From 9633508fe3a0cd76fc2337761b104a98cc169ca8 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 17 2020 00:17:31 +0000 Subject: mingw-gstreamer1-1.14.1 base --- diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..83bc72e --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1068 @@ +1 Notes on the Free Translation Project +*************************************** + +Free software is going international! The Free Translation Project is +a way to get maintainers of free software, translators, and users all +together, so that free software will gradually become able to speak many +languages. A few packages already provide translations for their +messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work on translations can contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +1.1 Quick configuration advice +============================== + +If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the `gettext' implementation in the GNU C library version 2 provides as +many features (such as locale alias, message inheritance, automatic +charset conversion or plural form handling) as the implementation here. +It is also not possible to offer this additional functionality on top +of a `catgets' implementation. Future versions of GNU `gettext' will +very likely convey even more functionality. So it might be a good idea +to change to GNU `gettext' as soon as possible. + + So you need _not_ provide this option if you are using GNU libc 2 or +you have installed a recent copy of the GNU gettext package with the +included `libintl'. + +1.2 INSTALL Matters +=================== + +Some packages are "localizable" when properly installed; the programs +they contain can be made to speak your own native language. Most such +packages use GNU `gettext'. Other packages have their own ways to +internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. If not, the included GNU +`gettext' library will be used. This library is wholly contained +within this package, usually in the `intl/' subdirectory, so prior +installation of the GNU `gettext' package is _not_ required. +Installers may use special options at configuration time for changing +the default behaviour. The commands: + + ./configure --with-included-gettext + ./configure --disable-nls + +will, respectively, bypass any pre-existing `gettext' to use the +internationalizing routines provided within this package, or else, +_totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might not be desirable. You should use +the more recent version of the GNU `gettext' library. I.e. if the file +`intl/VERSION' shows that the library which comes with this package is +more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + The configuration process will not test for the `catgets' function +and therefore it will not be used. The reason is that even an +emulation of `gettext' on top of `catgets' could not provide all the +extensions of the GNU `gettext' library. + + Internationalized packages usually have many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +1.3 Using This Package +====================== + +As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. If you happen to have the `LC_ALL' or some other +`LC_xxx' environment variables set, you should unset them before +setting `LANG', otherwise the setting of `LANG' will not have the +desired effect. Here `LL' is an ISO 639 two-letter language code, and +`CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your language by running the +command `locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from `no' to `nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under `nb' and some older ones under `no', it's recommended +for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +older translations are used. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +1.4 Translating Teams +===================== + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://translationproject.org/', in the "Teams" area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `coordinator@translationproject.org' to +reach the coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. + +1.5 Available Packages +====================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of November +2007. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo + +----------------------------------------------------+ + Compendium | [] [] [] [] | + a2ps | [] [] [] [] [] | + aegis | () | + ant-phone | () | + anubis | [] | + ap-utils | | + aspell | [] [] [] [] [] | + bash | [] | + bfd | | + bibshelf | [] | + binutils | | + bison | [] [] | + bison-runtime | [] | + bluez-pin | [] [] [] [] [] | + cflow | [] | + clisp | [] [] [] | + console-tools | [] [] | + coreutils | [] [] [] [] | + cpio | | + cpplib | [] [] [] | + cryptonit | [] | + dialog | | + diffutils | [] [] [] [] [] [] | + doodle | [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + fetchmail | [] [] () [] [] | + findutils | [] | + findutils_stable | [] [] [] | + flex | [] [] [] | + fslint | | + gas | | + gawk | [] [] [] | + gcal | [] | + gcc | [] | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] | + gip | [] | + gliv | [] [] | + glunarclock | [] | + gmult | [] [] | + gnubiff | () | + gnucash | [] [] () () [] | + gnuedu | | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gpe-aerial | [] [] | + gpe-beam | [] [] | + gpe-calendar | | + gpe-clock | [] [] | + gpe-conf | [] [] | + gpe-contacts | | + gpe-edit | [] | + gpe-filemanager | | + gpe-go | [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] | + gpe-package | | + gpe-sketchbook | [] [] | + gpe-su | [] [] | + gpe-taskmanager | [] [] | + gpe-timesheet | [] | + gpe-today | [] [] | + gpe-todo | | + gphoto2 | [] [] [] [] | + gprof | [] [] | + gpsdrive | | + gramadoir | [] [] | + grep | [] [] | + gretl | () | + gsasl | | + gss | | + gst-plugins-bad | [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] [] | + gst-plugins-ugly | [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | () | + gtkam | [] [] [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] [] | + indent | [] [] [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] [] | + iso_639 | [] [] [] [] | + jpilot | [] | + jtag | | + jwhois | | + kbd | [] [] [] [] | + keytouch | [] [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + latrine | () | + ld | [] | + leafpad | [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] | + libextractor | [] | + libgpewidget | [] [] [] | + libgpg-error | [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] | + libgsasl | | + libiconv | [] [] | + libidn | [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lprng | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] | + make | [] [] | + man-db | [] [] [] | + minicom | [] [] [] | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | + pilot-qof | | + popt | [] [] [] | + psmisc | [] | + pwdutils | | + qof | | + radius | [] | + recode | [] [] [] [] [] [] | + rpm | [] | + screem | | + scrollkeeper | [] [] [] [] [] [] [] [] | + sed | [] [] [] | + shared-mime-info | [] [] [] [] () [] [] [] | + sharutils | [] [] [] [] [] [] | + shishi | | + skencil | [] () | + solfege | | + soundtracker | [] [] | + sp | [] | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] | + texinfo | [] [] [] | + tin | () () | + tuxpaint | [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] | + util-linux-ng | [] [] [] [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] | + xpad | [] [] [] | + +----------------------------------------------------+ + af am ar az be bg bs ca cs cy da de el en en_GB eo + 6 0 2 1 8 26 2 40 48 2 56 88 15 1 15 18 + + es et eu fa fi fr ga gl gu he hi hr hu id is it + +--------------------------------------------------+ + Compendium | [] [] [] [] [] | + a2ps | [] [] [] () | + aegis | | + ant-phone | [] | + anubis | [] | + ap-utils | [] [] | + aspell | [] [] [] | + bash | [] | + bfd | [] [] | + bibshelf | [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] [] [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] | + cflow | [] | + clisp | [] [] | + console-tools | | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] | + cpplib | [] [] | + cryptonit | [] | + dialog | [] [] [] | + diffutils | [] [] [] [] [] [] [] [] [] | + doodle | [] [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] | + fetchmail | [] | + findutils | [] [] [] | + findutils_stable | [] [] [] [] | + flex | [] [] [] | + fslint | | + gas | [] [] | + gawk | [] [] [] [] () | + gcal | [] [] | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] | + gip | [] [] [] [] | + gliv | () | + glunarclock | [] [] [] | + gmult | [] [] [] | + gnubiff | () () | + gnucash | () () () | + gnuedu | [] | + gnulib | [] [] [] | + gnunet | | + gnunet-gtk | | + gnutls | | + gpe-aerial | [] [] | + gpe-beam | [] [] | + gpe-calendar | | + gpe-clock | [] [] [] [] | + gpe-conf | [] | + gpe-contacts | [] [] | + gpe-edit | [] [] [] [] | + gpe-filemanager | [] | + gpe-go | [] [] [] | + gpe-login | [] [] [] | + gpe-ownerinfo | [] [] [] [] [] | + gpe-package | [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] | + gphoto2 | [] [] [] [] [] | + gprof | [] [] [] [] [] | + gpsdrive | [] | + gramadoir | [] [] | + grep | [] [] [] | + gretl | [] [] [] () | + gsasl | [] [] | + gss | [] [] | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] | + gstreamer | [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] [] [] [] | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | [] | + iso_4217 | [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] | + jpilot | [] [] | + jtag | [] | + jwhois | [] [] [] [] [] | + kbd | [] [] | + keytouch | [] [] [] | + keytouch-editor | [] | + keytouch-keyboa... | [] [] | + latrine | [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | [] | + libgpewidget | [] [] [] [] [] | + libgpg-error | [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] | + libgsasl | [] [] | + libiconv | [] [] [] | + libidn | [] [] | + lifelines | () | + lilypond | [] [] [] | + lingoteach | [] [] [] | + lprng | | + lynx | [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] [] | + make | [] [] [] [] [] [] [] [] | + man-db | [] | + minicom | [] [] [] [] | + nano | [] [] [] [] [] [] [] | + opcodes | [] [] [] [] | + parted | [] [] [] | + pilot-qof | | + popt | [] [] [] [] | + psmisc | [] [] | + pwdutils | | + qof | [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] [] [] | + sed | [] [] [] [] [] | + shared-mime-info | [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] [] [] | + shishi | [] | + skencil | [] [] | + solfege | [] | + soundtracker | [] [] [] | + sp | [] | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + tin | [] () | + tuxpaint | [] [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux | [] [] [] [] [] [] [] | + util-linux-ng | [] [] [] [] [] [] [] | + vorbis-tools | | + wastesedge | () | + wdiff | [] [] [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + es et eu fa fi fr ga gl gu he hi hr hu id is it + 85 22 14 2 48 101 61 12 2 8 2 6 53 29 1 52 + + ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn + +--------------------------------------------------+ + Compendium | [] | + a2ps | () [] [] | + aegis | () | + ant-phone | [] | + anubis | [] [] [] | + ap-utils | [] | + aspell | [] [] | + bash | [] | + bfd | | + bibshelf | [] | + binutils | | + bison | [] [] [] | + bison-runtime | [] [] [] | + bluez-pin | [] [] [] | + cflow | | + clisp | [] | + console-tools | | + coreutils | [] | + cpio | [] | + cpplib | [] | + cryptonit | [] | + dialog | [] [] | + diffutils | [] [] [] | + doodle | | + e2fsprogs | [] | + enscript | [] | + fetchmail | [] [] | + findutils | [] | + findutils_stable | [] | + flex | [] [] | + fslint | | + gas | | + gawk | [] [] | + gcal | | + gcc | | + gettext-examples | [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] [] | + gip | [] [] | + gliv | [] | + glunarclock | [] [] | + gmult | [] [] [] | + gnubiff | | + gnucash | () () () | + gnuedu | | + gnulib | [] [] | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gpe-aerial | [] | + gpe-beam | [] | + gpe-calendar | [] | + gpe-clock | [] [] [] | + gpe-conf | [] [] [] | + gpe-contacts | [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] | + gpe-go | [] [] [] | + gpe-login | [] [] [] | + gpe-ownerinfo | [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] | + gpe-today | [] [] | + gpe-todo | [] | + gphoto2 | [] [] | + gprof | [] | + gpsdrive | [] | + gramadoir | () | + grep | [] [] | + gretl | | + gsasl | [] | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] | + gst-plugins-good | [] | + gst-plugins-ugly | [] | + gstreamer | [] | + gtick | [] | + gtkam | [] [] | + gtkorphan | [] | + gtkspell | [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] | + indent | [] [] | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] | + iso_3166_2 | [] | + iso_4217 | [] [] [] | + iso_639 | [] [] [] [] | + jpilot | () () | + jtag | | + jwhois | [] | + kbd | [] | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | | + latrine | [] | + ld | | + leafpad | [] [] | + libc | [] [] [] | + libexif | | + libextractor | | + libgpewidget | [] | + libgpg-error | | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | [] | + libiconv | [] | + libidn | [] [] | + lifelines | [] | + lilypond | [] | + lingoteach | [] | + lprng | | + lynx | [] [] | + m4 | [] [] | + mailfromd | | + mailutils | | + make | [] [] [] | + man-db | | + minicom | [] | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | + pilot-qof | | + popt | [] [] [] | + psmisc | [] [] [] | + pwdutils | | + qof | | + radius | | + recode | [] | + rpm | [] [] | + screem | [] | + scrollkeeper | [] [] [] [] | + sed | [] [] | + shared-mime-info | [] [] [] [] [] [] [] | + sharutils | [] [] | + shishi | | + skencil | | + solfege | () () | + soundtracker | | + sp | () | + system-tools-ba... | [] [] [] [] | + tar | [] [] [] | + texinfo | [] [] | + tin | | + tuxpaint | () [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] | + util-linux-ng | [] [] | + vorbis-tools | | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] | + xchat | [] [] [] [] | + xkeyboard-config | [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn + 51 2 25 3 2 0 6 0 2 2 20 0 11 1 103 6 + + or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta + +--------------------------------------------------+ + Compendium | [] [] [] [] [] | + a2ps | () [] [] [] [] [] [] | + aegis | () () | + ant-phone | [] [] | + anubis | [] [] [] | + ap-utils | () | + aspell | [] [] [] | + bash | [] [] | + bfd | | + bibshelf | [] | + binutils | [] [] | + bison | [] [] [] [] [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] [] | + cflow | [] | + clisp | [] | + console-tools | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + cpplib | [] | + cryptonit | [] [] | + dialog | [] | + diffutils | [] [] [] [] [] [] | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] | + findutils_stable | [] [] [] [] [] [] | + flex | [] [] [] [] [] | + fslint | [] | + gas | | + gawk | [] [] [] [] | + gcal | [] | + gcc | [] [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] [] | + gip | [] [] [] [] | + gliv | [] [] [] [] [] [] | + glunarclock | [] [] [] [] [] [] | + gmult | [] [] [] [] | + gnubiff | () [] | + gnucash | () [] | + gnuedu | | + gnulib | [] [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gpe-aerial | [] [] [] [] [] [] [] | + gpe-beam | [] [] [] [] [] [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] [] [] [] [] | + gpe-conf | [] [] [] [] [] [] [] | + gpe-contacts | [] [] [] [] [] | + gpe-edit | [] [] [] [] [] [] [] [] [] | + gpe-filemanager | [] [] | + gpe-go | [] [] [] [] [] [] [] [] | + gpe-login | [] [] [] [] [] [] [] [] | + gpe-ownerinfo | [] [] [] [] [] [] [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] [] [] [] [] [] [] | + gpe-su | [] [] [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] [] | + gpe-todo | [] [] [] [] | + gphoto2 | [] [] [] [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] | + gramadoir | [] [] | + grep | [] [] [] [] | + gretl | [] [] [] | + gsasl | [] [] [] | + gss | [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] | + gst-plugins-ugly | [] [] [] | + gstreamer | [] [] [] [] | + gtick | [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] | + gtkspell | [] [] [] [] [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] [] | + herrie | [] [] [] | + hylafax | | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] | + jpilot | | + jtag | [] | + jwhois | [] [] [] [] | + kbd | [] [] [] | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + latrine | | + ld | [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] | + libextractor | [] [] | + libgpewidget | [] [] [] [] [] [] [] [] | + libgpg-error | [] [] [] | + libgphoto2 | [] | + libgphoto2_port | [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] | + libidn | [] [] () | + lifelines | [] [] | + lilypond | | + lingoteach | [] | + lprng | [] | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] [] [] | + make | [] [] [] [] | + man-db | [] [] [] [] | + minicom | [] [] [] [] [] | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] | + pilot-qof | | + popt | [] [] [] [] | + psmisc | [] [] | + pwdutils | [] [] | + qof | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] | + rpm | [] [] [] [] | + screem | | + scrollkeeper | [] [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] | + shared-mime-info | [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] | + skencil | [] [] [] | + solfege | [] | + soundtracker | [] [] | + sp | | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + tin | () | + tuxpaint | [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] | + util-linux-ng | [] [] [] [] | + vorbis-tools | [] | + wastesedge | | + wdiff | [] [] [] [] [] [] [] | + wget | [] [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta + 0 5 77 31 53 4 58 72 3 45 46 9 45 122 3 + + tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu + +---------------------------------------------------+ + Compendium | [] [] [] [] | 19 + a2ps | [] [] [] | 19 + aegis | [] | 1 + ant-phone | [] [] | 6 + anubis | [] [] [] | 11 + ap-utils | () [] | 4 + aspell | [] [] [] | 16 + bash | [] | 6 + bfd | | 2 + bibshelf | [] | 7 + binutils | [] [] [] [] | 9 + bison | [] [] [] [] | 20 + bison-runtime | [] [] [] [] | 18 + bluez-pin | [] [] [] [] [] [] | 28 + cflow | [] [] | 5 + clisp | | 9 + console-tools | [] [] | 5 + coreutils | [] [] [] | 18 + cpio | [] [] [] [] | 11 + cpplib | [] [] [] [] [] | 12 + cryptonit | [] | 6 + dialog | [] [] [] | 9 + diffutils | [] [] [] [] [] | 29 + doodle | [] | 6 + e2fsprogs | [] [] | 10 + enscript | [] [] [] | 16 + fetchmail | [] [] | 12 + findutils | [] [] [] | 11 + findutils_stable | [] [] [] [] | 18 + flex | [] [] | 15 + fslint | [] | 2 + gas | [] | 3 + gawk | [] [] [] | 16 + gcal | [] | 5 + gcc | [] [] [] | 7 + gettext-examples | [] [] [] [] [] [] | 29 + gettext-runtime | [] [] [] [] [] [] | 28 + gettext-tools | [] [] [] [] [] | 20 + gip | [] [] | 13 + gliv | [] [] | 11 + glunarclock | [] [] [] | 15 + gmult | [] [] [] [] | 16 + gnubiff | [] | 2 + gnucash | () [] | 5 + gnuedu | [] | 2 + gnulib | [] | 10 + gnunet | | 0 + gnunet-gtk | [] [] | 3 + gnutls | | 4 + gpe-aerial | [] [] | 14 + gpe-beam | [] [] | 14 + gpe-calendar | [] [] | 7 + gpe-clock | [] [] [] [] | 21 + gpe-conf | [] [] [] | 16 + gpe-contacts | [] [] | 10 + gpe-edit | [] [] [] [] [] | 22 + gpe-filemanager | [] [] | 7 + gpe-go | [] [] [] [] | 19 + gpe-login | [] [] [] [] [] | 21 + gpe-ownerinfo | [] [] [] [] | 21 + gpe-package | [] | 6 + gpe-sketchbook | [] [] | 16 + gpe-su | [] [] [] [] | 21 + gpe-taskmanager | [] [] [] [] | 21 + gpe-timesheet | [] [] [] [] | 18 + gpe-today | [] [] [] [] [] | 21 + gpe-todo | [] [] | 8 + gphoto2 | [] [] [] [] | 21 + gprof | [] [] | 13 + gpsdrive | [] | 5 + gramadoir | [] | 7 + grep | [] | 12 + gretl | | 6 + gsasl | [] [] [] | 9 + gss | [] | 7 + gst-plugins-bad | [] [] [] | 13 + gst-plugins-base | [] [] | 11 + gst-plugins-good | [] [] [] [] [] | 16 + gst-plugins-ugly | [] [] [] | 13 + gstreamer | [] [] [] | 18 + gtick | [] [] | 7 + gtkam | [] | 16 + gtkorphan | [] | 7 + gtkspell | [] [] [] [] [] [] | 27 + gutenprint | | 4 + hello | [] [] [] [] [] | 38 + herrie | [] [] | 8 + hylafax | | 0 + idutils | [] [] | 15 + indent | [] [] [] [] [] | 28 + iso_15924 | [] [] | 4 + iso_3166 | [] [] [] [] [] [] [] [] [] | 54 + iso_3166_2 | [] [] | 4 + iso_4217 | [] [] [] [] [] | 24 + iso_639 | [] [] [] [] [] | 26 + jpilot | [] [] [] [] | 7 + jtag | [] | 3 + jwhois | [] [] [] | 13 + kbd | [] [] [] | 13 + keytouch | [] | 8 + keytouch-editor | [] | 5 + keytouch-keyboa... | [] | 5 + latrine | [] [] | 5 + ld | [] [] [] [] | 10 + leafpad | [] [] [] [] [] | 24 + libc | [] [] [] | 19 + libexif | [] | 5 + libextractor | [] | 5 + libgpewidget | [] [] [] | 20 + libgpg-error | [] | 6 + libgphoto2 | [] [] | 9 + libgphoto2_port | [] [] [] | 11 + libgsasl | [] | 8 + libiconv | [] [] | 11 + libidn | [] [] | 11 + lifelines | | 4 + lilypond | [] | 6 + lingoteach | [] | 6 + lprng | [] | 2 + lynx | [] [] [] | 15 + m4 | [] [] [] | 18 + mailfromd | [] [] | 3 + mailutils | [] [] | 8 + make | [] [] [] | 20 + man-db | [] | 9 + minicom | [] | 14 + nano | [] [] [] | 20 + opcodes | [] [] | 10 + parted | [] [] [] | 11 + pilot-qof | [] | 1 + popt | [] [] [] [] | 18 + psmisc | [] [] | 10 + pwdutils | [] | 3 + qof | [] | 4 + radius | [] [] | 7 + recode | [] [] [] | 25 + rpm | [] [] [] [] | 13 + screem | [] | 2 + scrollkeeper | [] [] [] [] | 26 + sed | [] [] [] [] | 23 + shared-mime-info | [] [] [] | 29 + sharutils | [] [] [] | 23 + shishi | [] | 3 + skencil | [] | 7 + solfege | [] | 3 + soundtracker | [] [] | 9 + sp | [] | 3 + system-tools-ba... | [] [] [] [] [] [] [] | 38 + tar | [] [] [] | 17 + texinfo | [] [] [] | 15 + tin | | 1 + tuxpaint | [] [] [] | 19 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux | [] [] [] | 20 + util-linux-ng | [] [] [] | 20 + vorbis-tools | [] [] | 4 + wastesedge | | 1 + wdiff | [] [] | 23 + wget | [] [] [] | 20 + xchat | [] [] [] [] | 29 + xkeyboard-config | [] [] [] | 14 + xpad | [] [] [] | 15 + +---------------------------------------------------+ + 76 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu + 163 domains 0 3 1 74 51 0 143 21 1 57 7 45 0 2036 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If November 2007 seems to be old, you may fetch a more recent copy +of this `ABOUT-NLS' file on most GNU archive sites. The most +up-to-date matrix with full percentage details can be found at +`http://translationproject.org/extra/matrix.html'. + +1.6 Using `gettext' in new packages +=================================== + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`coordinator@translationproject.org' to make the `.pot' files available +to the translation teams. + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..ec49a92 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,32 @@ +Erik Walthinsen +Matt Howell +Brent Bradburn +Wim Taymans +Richard Boulton +Zaheer Abbas Merali + - thread synchronization rework +David I. Lehn + - debian packaging + - various fixes +Chris Emerson + - PPC port + - small libxml patches +Jens Thiele + - color conversion patches +Thomas Nyberg + - gstreamer.m4 macros + - ALSA plugins +Bastien Nocera + - gnomevfs sink and source +Christian Fredrik Kalager Schaller + - Red Hat packaging and website work +Thomas Vander Stichele + - build system cleaning + - some audio plugins + - release pushing +David Schleef +Benjamin Otte +Ronald Bultje +Andy Wingo +Julien Moutte +Jan Schmidt diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c87cfe8 --- /dev/null +++ b/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..14de900 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,121773 @@ +=== release 1.14.1 === + +2018-05-17 13:17:26 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * meson.build: + Release 1.14.1 + +2018-05-17 13:17:26 +0100 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + Update docs + +2018-05-17 12:37:20 +0100 Tim-Philipp Müller + + * po/hr.po: + Update translations + +2018-05-10 00:05:51 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix race condition causing the same probe to be called multiple times + Probes were remembering a cookie that was used to check if the probe was + already called this time before the probes list changed. However the + same probes could've been called by another thread in between and thus + gotten a new cookie, and would then be called a second time. + https://bugzilla.gnome.org/show_bug.cgi?id=795987 + +2018-05-04 09:29:22 +0200 Edward Hervey + + * gst/gstregistrybinary.c: + * libs/gst/helpers/gst-ptp-helper.c: + gst: Use memcpy() instead of strncpy() where appropriate + strncpy() is assumed to be for strings so the compiler assumes that + it will need an extra byte for the string-terminaning NULL. + For cases where we know it's actually "binary" data, just copy it + with memcpy. + Fixes compiler warnings with gcc 8. + https://bugzilla.gnome.org/show_bug.cgi?id=795756 + +2018-05-05 16:16:45 +0200 Tim-Philipp Müller + + * gst/gstbufferlist.c: + * tests/check/gst/gstbufferlist.c: + bufferlist: fix abort due to underflow when creating 0-sized list + gst_buffer_list_new_sized(0) will cause an underflow in a calculation + which then makes it try to allocate huge amounts of memory, which + may lead to aborts. + https://bugzilla.gnome.org/show_bug.cgi?id=795758 + +2018-05-05 11:32:12 +0200 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * win32/common/libgstbase.def: + aggregator: fix exports and since marker for new API + https://bugzilla.gnome.org/show_bug.cgi?id=795332 + +2018-04-23 11:34:19 -0400 Olivier Crête + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Add API to check if a pad has a new buffer + https://bugzilla.gnome.org/show_bug.cgi?id=795332 + +2018-04-20 12:30:24 +0100 Tim-Philipp Müller + + * meson.build: + meson: fix invalid keyword argument warnings + cc.compiles() doesn't have a 'prefix' argument (yet) and the + prefix has already been prepended to the source code snippets. + https://github.com/mesonbuild/meson/issues/2364 + +2018-04-17 11:24:31 +0100 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + multiqueue, inputselector: show pad properties in gst-inspect-1.0 + +2018-04-13 20:15:46 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + base: fix some GIR annotations + Mostly related to out parameters and their transfer + +2018-03-29 18:59:43 +0200 Mark Nauwelaerts + + * gst/gstbuffer.c: + * gst/gstutils.c: + gst: add some GIR array annotations + +2018-04-11 19:56:01 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + gstdebug: fix occasional deadlocks on windows when outputting debug logging + When outputting debug logs on Windows, some sections are protected + with a non-recursive lock. Turns out though that gst_debug_message_get() + might indirectly, via our printf format extensions, call code which + in turn would try to log something when it can't handle something. If + that happens we end up in gst_debug_log_default() again recursively and + try to again take the lock that's already taken, thus deadlocking. + Format the debug message string outside of the critical section + instead to avoid this. + https://bugzilla.gnome.org/show_bug.cgi?id=784382 + +2018-04-09 14:19:19 +0100 Tim-Philipp Müller + + * gst/gsturi.h: + gsturi: include gstconfig.h earlier for GST_API define + +2018-03-27 10:25:46 +0200 Jan Alexander Steffens (heftig) + + * gst/gstinfo.c: + * tests/check/gst/gstinfo.c: + gstinfo: fix debug levels being applied in the wrong order + Remove unneeded reapplication of patterns. Besides being + superfluous (gst_debug_reset_threshold already applies + patterns) it was also wrong and didn't stop checking patterns + after the first match (broken in 67e9d139). + Also fix up unit test which checked for the wrong order. + https://bugzilla.gnome.org/show_bug.cgi?id=794717 + +2018-03-29 12:36:11 +1100 Matthew Waters + + * gst/gstbin.c: + bin: fix deep-element-added signal debug log message + Adding the bin to the child element doesn't really make sense. + +2018-03-20 16:11:01 +0200 Sebastian Dröge + + * gst/gstchildproxy.c: + * gst/parse/grammar.y: + gst: Fix compilation with latest GLib + g_object_ref() forwards the type of its argument nowadays. + ./grammar.y:409:14: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types] + gstchildproxy.c:212:7: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types] + +2018-03-21 10:20:14 +0200 Sebastian Dröge + + * libs/gst/net/net.h: + net: Include gstnetcontrolmessagemeta.h in net.h + +2018-03-21 10:13:44 +0200 Sebastian Dröge + + * gst/gstparamspecs.h: + paramspecs: Set g-i annotation values for GST_PARAM_* constants + +2018-03-21 10:11:30 +0200 Sebastian Dröge + + * gst/gstelementfactory.h: + elementfactory: GST_ELEMENT_FACTORY_TYPE_DECODABLE had DECRYPTOR added, update g-i annotation value + +=== release 1.14.0 === + +2018-03-19 20:09:51 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * meson.build: + Release 1.14.0 + +2018-03-19 20:09:51 +0000 Tim-Philipp Müller + + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + Update docs + +=== release 1.13.91 === + +2018-03-13 19:08:54 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * meson.build: + Release 1.13.91 + +2018-03-13 19:08:54 +0000 Tim-Philipp Müller + + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + Update docs + +2018-03-13 11:54:42 +0000 Tim-Philipp Müller + + * docs/gst/meson.build: + * docs/libs/meson.build: + meson: docs: update api decorators to ignore + +2018-03-12 23:12:13 +0000 Tim-Philipp Müller + + * docs/libs/Makefile.am: + docs: fixup for new libs API export decorators + +2018-03-12 23:03:26 +0000 Tim-Philipp Müller + + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnet.h: + * libs/gst/net/gstnetaddressmeta.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnetcontrolmessagemeta.h: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.h: + * libs/gst/net/gstptpclock.h: + * libs/gst/net/meson.build: + * libs/gst/net/net-prelude.h: + * libs/gst/net/net.h: + net: GST_EXPORT -> GST_NET_API + We need different export decorators for the different libs. + For now no actual change though, just rename before the release, + and add prelude headers to define the new decorator to GST_EXPORT. + +2018-03-12 23:03:26 +0000 Tim-Philipp Müller + + * common: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/controller-prelude.h: + * libs/gst/controller/controller.h: + * libs/gst/controller/controller_mkenum.py: + * libs/gst/controller/gstargbcontrolbinding.h: + * libs/gst/controller/gstdirectcontrolbinding.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gstproxycontrolbinding.h: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.h: + * libs/gst/controller/meson.build: + controller: GST_EXPORT -> GST_CONTROLLER_API + We need different export decorators for the different libs. + For now no actual change though, just rename before the release, + and add prelude headers to define the new decorator to GST_EXPORT. + +2018-03-12 23:03:26 +0000 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + * libs/gst/check/check-prelude.h: + * libs/gst/check/check.h: + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstcheck.h: + * libs/gst/check/gstconsistencychecker.h: + * libs/gst/check/gstharness.h: + * libs/gst/check/gsttestclock.h: + * libs/gst/check/meson.build: + check: GST_EXPORT -> GST_CHECK_API + We need different export decorators for the different libs. + For now no actual change though, just rename before the release, + and add prelude headers to define the new decorator to GST_EXPORT. + +2018-03-12 23:03:26 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/base/base-prelude.h: + * libs/gst/base/base.h: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstaggregator.h: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstflowcombiner.h: + * libs/gst/base/gstindex.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/base/gstqueuearray.h: + * libs/gst/base/gsttypefindhelper.h: + * libs/gst/base/meson.build: + base: GST_EXPORT -> GST_BASE_API + We need different export decorators for the different libs. + For now no actual change though, just rename before the release, + and add prelude headers to define the new decorator to GST_EXPORT. + +2018-03-12 23:03:26 +0000 Tim-Philipp Müller + + * docs/gst/Makefile.am: + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstallocator.h: + * gst/gstatomicqueue.h: + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstbufferpool.h: + * gst/gstbus.h: + * gst/gstcaps.h: + * gst/gstcapsfeatures.h: + * gst/gstchildproxy.h: + * gst/gstclock.h: + * gst/gstconfig.h.in: + * gst/gstcontext.h: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.h: + * gst/gstdatetime.h: + * gst/gstdebugutils.h: + * gst/gstdevice.h: + * gst/gstdevicemonitor.h: + * gst/gstdeviceprovider.h: + * gst/gstdeviceproviderfactory.h: + * gst/gstdynamictypefactory.h: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gstenumtypes.h.template: + * gst/gsterror.h: + * gst/gstevent.h: + * gst/gstformat.h: + * gst/gstghostpad.h: + * gst/gstinfo.h: + * gst/gstiterator.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstparamspecs.h: + * gst/gstparse.h: + * gst/gstpipeline.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.h: + * gst/gstpoll.h: + * gst/gstpreset.h: + * gst/gstpromise.h: + * gst/gstprotection.h: + * gst/gstquery.h: + * gst/gstregistry.h: + * gst/gstsample.h: + * gst/gstsegment.h: + * gst/gststreamcollection.h: + * gst/gststreams.h: + * gst/gststructure.h: + * gst/gstsystemclock.h: + * gst/gsttaglist.h: + * gst/gsttagsetter.h: + * gst/gsttask.h: + * gst/gsttaskpool.h: + * gst/gsttoc.h: + * gst/gsttocsetter.h: + * gst/gsttracer.h: + * gst/gsttracerfactory.h: + * gst/gsttracerrecord.h: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.h: + * gst/gsturi.h: + * gst/gstutils.h: + * gst/gstvalue.h: + gst: GST_EXPORT -> GST_API + We need different export decorators for the different libs. + For now no actual change though, just rename before the release, + and add prelude headers to define the new decorator to GST_EXPORT. + +2018-03-08 13:30:30 +1100 Matthew Waters + + * gst/gstpromise.c: + promise: be more explicit in docs about who/when to use reply/interrupt/expire + https://bugzilla.gnome.org/show_bug.cgi?id=794153 + +2018-03-07 11:19:25 -0500 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Balance unlock/unlock_stop in _src_stop() + Otherwise it's possible that we won't be able to start again + depending the implementation. We do start/stop in normal use cases + whenever GST_QUERY_SCHEDULING happens before we are started. + https://bugzilla.gnome.org/show_bug.cgi?id=794149 + +2018-03-07 11:16:00 -0500 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: No need to stop flushing in start_complete + The flushing state is handled a bit differently, there is no need + to stop flushing in start_complete. This would other result in + unlock_stop being called without unlock_start. + Unlike what the old comment says, there is no need to take the live + lock here, we are still single threaded at this point (app thread + or the state change thread). Also, we will wait for playing state + in create/getrange, no need to do that twice. + https://bugzilla.gnome.org/show_bug.cgi?id=794149 + +2018-03-05 11:52:24 +0200 Sebastian Dröge + + * gst/gstdebugutils.c: + debugutils: Change dot-file functions documentation to proper gtk-doc + This way gobject-introspection also picks it up and handles our + annotations. + See https://gitlab.gnome.org/GNOME/gobject-introspection/issues/194 + +2018-03-04 10:53:10 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * win32/common/libgstbase.def: + queuearray: Implement pop_tail_struct() for completeness + All other variants of {peek,pop}_{head,tail}_{,struct} were already + implemented. + https://bugzilla.gnome.org/show_bug.cgi?id=794035 + +2018-03-04 10:24:49 +0200 Sebastian Dröge + + * gst/gstpreset.c: + * gst/gsturi.c: + gst: Add some more (type filename) annotations + +=== release 1.13.90 === + +2018-03-03 21:51:49 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * meson.build: + Release 1.13.90 + +2018-03-03 21:51:49 +0000 Tim-Philipp Müller + + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + Update docs + +2018-02-13 22:20:18 +1100 Matthew Waters + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstsparsefile.c: + plugins: Don't force 64-bit file/seek functions variants on android + Most functions are automatically chosen from the _FILE_OFFSET_BITS + define, the remaining one (fstat) is only available on API >= 21 so + check for that + +2018-03-01 22:21:17 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * win32/common/libgstbase.def: + Add new symbol to docs and .def file + Fixes make check + +2018-03-01 16:19:09 -0500 Olivier Crête + + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * plugins/elements/gstqueue.c: + * tests/check/elements/queue.c: + queue: Ignore thresholds if a query is queued + The queue gets filled by the tail, so a query will always be the tail + object, not the head object. Also add a _peek_tail_struct() method to the + GstQueueArray to enable looking at the tail. + With unit test to prevent future regression. + https://bugzilla.gnome.org/show_bug.cgi?id=762875 + +2018-03-01 18:38:01 +0100 Mathieu Duponchelle + + * meson.build: + meson: -Wformat-* require -Wformat + +2018-03-01 17:20:06 +0100 Mathieu Duponchelle + + * gst/printf/meson.build: + * libs/gst/check/libcheck/meson.build: + * meson.build: + meson: enable more warnings + Modeled on the autotools build, -W flags are only + added if the compiler supports them. + https://bugzilla.gnome.org/show_bug.cgi?id=793958 + +2018-03-01 00:31:11 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + gstaggregator: pads must inherit from #GstAggregatorPad + Document this, and take advantage of that fact to use + GstAggregator.srcpad.segment instead of GstAggregator.segment + https://bugzilla.gnome.org/show_bug.cgi?id=793942 + +2018-03-01 01:15:34 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + Revert "gstaggregator: pads must inherit from #GstAggregatorPad" + This reverts commit 9774b3775d8483e5697f9196a26c1e5831113bd6. + Pushed by mistake + +2018-03-01 01:12:07 +0100 Mathieu Duponchelle + + * gst/gstghostpad.c: + ghostpad: ensure we build a ghost pad .. + When we construct from a custom GType + +2018-03-01 01:09:48 +0100 Mathieu Duponchelle + + * gst/gstpad.c: + pad: fix mixed declarations + +2018-03-01 00:31:11 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + gstaggregator: pads must inherit from #GstAggregatorPad + Document this, and take advantage of that fact to use + GstAggregator.srcpad.segment instead of GstAggregator.segment + https://bugzilla.gnome.org/show_bug.cgi?id=793942 + +2018-02-28 19:53:42 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: allow src GstAggregatorPads + See https://bugzilla.gnome.org/show_bug.cgi?id=793917 + https://bugzilla.gnome.org/show_bug.cgi?id=793934 + +2018-02-28 19:51:44 +0100 Mathieu Duponchelle + + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + pad, ghostpad: use the template gtype if specified + Also make sure the GType passed to the with_gtype versions + of the template constructors is_a GstPad + https://bugzilla.gnome.org/show_bug.cgi?id=793933 + +2018-02-21 22:25:25 -0500 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix integer overflow in bitrate calculation + https://bugzilla.gnome.org/show_bug.cgi?id=793284 + +2018-02-21 22:01:36 -0500 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: Avoid overflow in update_interval calculation + https://bugzilla.gnome.org/show_bug.cgi?id=793284 + +2018-02-21 21:43:59 -0500 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix check for update_interval + update_interval may be -1 + https://bugzilla.gnome.org/show_bug.cgi?id=793284 + +2018-02-19 15:39:46 +0900 Justin Kim + + * meson.build: + meson: Use .dylib suffix if darwin + For Mac OS, GST_EXTRA_MODULE_SUFFIX should be set as '.dylib'. + Otherwise, GStreamer fails to load its plugins. + https://bugzilla.gnome.org/show_bug.cgi?id=793584 + +2018-02-01 18:29:27 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * tests/check/libs/queuearray.c: + * win32/common/libgstbase.def: + queuearray: add _peek_tail() and _pop_tail() + API: gst_queue_array_pop_tail() + API: gst_queue_array_peek_tail() + These will be needed later for appsrc. + +2018-02-13 12:38:33 +0100 Mark Nauwelaerts + + * gst/gstbuffer.c: + * gst/gstevent.c: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gstsegment.c: + * gst/gsttaglist.c: + * gst/gsturi.c: + gst: fix some GIR annotations + Mostly related to out parameters and their transfer + +2018-01-10 04:08:57 +0100 Alicia Boya García + + * libs/gst/base/gstbasesink.c: + * tests/check/libs/basesink.c: + gstbasesink: Include segment.offset in the computation of position + Position queries with GST_FORMAT_TIME are supposed to return stream + time. + gst_base_sink_get_position() estimates the current stream time on its + own instead of using gst_segment_to_stream_time(), but the algorithm + used was not taking segment.offset into account, resulting in invalid + values when this field was set to a non-zero value. + https://bugzilla.gnome.org/show_bug.cgi?id=792434 + +2018-02-15 12:58:43 +1100 Matthew Waters + + * plugins/tracers/gstlatency.c: + tracers: latency: allow for non parented pads to send latency probes + Such a setup is used in rtspsrc for its TCP connection + https://bugzilla.gnome.org/show_bug.cgi?id=793478 + +2018-02-15 19:44:14 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + * meson.build: + Back to development + +=== release 1.13.1 === + +2018-02-15 16:31:16 +0000 Tim-Philipp Müller + + * NEWS: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coretracers.xml: + * gstreamer.doap: + * meson.build: + Release 1.13.1 + +2018-02-15 13:36:26 +0000 Tim-Philipp Müller + + * tests/check/gst/gstpipeline.c: + tests: pipeline: try to make test_pipeline_reset_start_time more reliable + Occasionally this test would fail, especially if the system is under load, + because the position query would pick up the last position from the + last buffer timestamp which has a lower timestamp than what we're + looking for. The sleep is long enough, however. It's unclear to me why + exactly this happens but there seems to be some kind of scheduling + issue going on as the streaming thread floods the sink with buffers. + Let's throttle the fakesrc to 100 buffers per second and make the sink + sync to the clock to restore some sanity. It should be totally sufficient + to test what we want to test, and seems to make things reliable here. + +2018-02-15 12:03:20 +0000 Tim-Philipp Müller + + * tests/check/gst/gsturi.c: + tests: uri: fix build without -DGST_DISABLE_DEPRECATED + Must undefine it before including gst headers, since the test + tests deprecated API. + +2018-02-15 12:09:31 +0000 Tim-Philipp Müller + + * gst/gstconfig.h.in: + gstconfig.h: want deprecation warnings if GST_DISABLE_DEPRECATED is *set* + Fix inverted logic. If GST_DISABLE_DEPRECATED is undefined, + we don't want warnings about deprecated API, and if it's + defined we do want warnings. + +2018-02-15 11:28:23 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/fr.po: + * po/hr.po: + * po/hu.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2018-02-14 19:37:35 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + docs: add flow combiner ref/unref to docs + So new-in-1.12 index actually has some entries. + +2018-02-14 19:13:28 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + docs: add index for new symbols in 1.14 + +2018-02-14 19:12:06 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + docs: add index for new symbols in 1.12 + +2018-02-08 17:22:14 +0000 Tim-Philipp Müller + + * meson.build: + meson: make version numbers ints and fix int/string comparison + WARNING: Trying to compare values of different types (str, int). + The result of this is undefined and will become a hard error + in a future Meson release. + +2018-02-03 17:56:04 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/printf/Makefile.am: + autotools: use -fno-strict-aliasing where supported + https://bugzilla.gnome.org/show_bug.cgi?id=769183 + +2018-02-03 17:55:29 +0100 Tim-Philipp Müller + + * gst/gstbuffer.h: + buffer: fix gtk-doc warning regarding _get_n_meta() declaration + +2018-02-02 00:24:20 +1100 Matthew Waters + + * gst/gstpromise.c: + * gst/gstpromise.h: + gstpromise: add since 1.14 markers + +2017-10-18 21:24:19 +1100 Matthew Waters + + * scripts/gst-uninstalled: + gst-uninstalled: add webrtc to libraries + +2018-01-31 14:01:36 +0100 Mathieu Duponchelle + + * gst/gstbuffer.h: + gstbuffer.h: move FLAG_LAST documentation back to the bottom + +2018-01-31 13:36:15 +0100 Mathieu Duponchelle + + * libs/gst/base/gstbasetransform.h: + basetransform: annotate virtual methods + +2018-01-30 16:41:39 +0100 Mathieu Duponchelle + + * gst/gstbuffer.h: + gstbuffer: add GST_BUFFER_FLAG_NON_DROPPABLE + This can be used to identify buffers for which a higher percentage + of redundancy should be allocated when performing forward error + correction, or to prevent still video frames from being dropped by + elements due to QoS. + https://bugzilla.gnome.org/show_bug.cgi?id=793008 + +2018-01-30 20:30:47 +0000 Tim-Philipp Müller + + * meson.build: + meson: use -fno-strict-aliasing if supported + https://bugzilla.gnome.org/show_bug.cgi?id=769183 + +2017-12-23 16:45:18 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add gst_buffer_get_n_meta() convenience function + Counts how many metas there are for a certain api type. + https://bugzilla.gnome.org/show_bug.cgi?id=791918 + +2017-10-22 18:05:30 +0530 Arun Raghavan + + * gst/gst.c: + * gst/gstallocator.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstcapsfeatures.c: + * gst/gstdatetime.c: + * gst/gstdevice.c: + * gst/gstdevicemonitor.c: + * gst/gstdeviceprovider.c: + * gst/gstelement.c: + * gst/gstevent.c: + * gst/gstinfo.c: + * gst/gstmessage.c: + * gst/gstmeta.c: + * gst/gstminiobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstparamspecs.c: + * gst/gstparse.c: + * gst/gstplugin.c: + * gst/gstprotection.c: + * gst/gstquery.c: + * gst/gstsample.c: + * gst/gststreamcollection.c: + * gst/gststreams.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gsttoc.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstvalue.c: + gst: Fix up a bunch of GIR annotations + This is mostly on nullable return values, and some other minor ones that + I ran across. + https://bugzilla.gnome.org/show_bug.cgi?id=789319 + +2017-05-27 05:19:20 +0530 Arun Raghavan + + * gst/gstdevicemonitor.c: + devicemonitor: Return NULL instead of FALSE + Same effect, meaning is clearer. + https://bugzilla.gnome.org/show_bug.cgi?id=789319 + +2018-01-26 12:42:28 +0100 François Laignel + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * tests/check/gst/gstmessage.c: + * win32/common/libgstreamer.def: + message: Add gst_message_writable_structure() + Add gst_message_writable_structure() to be able to add extra fields to + messages (and be on par with GstEvent). + https://bugzilla.gnome.org/show_bug.cgi?id=792928 + +2018-01-23 22:49:52 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: delegate buffer skipping to the aggregate thread + As we do that for serialized events as well, and the subclass will + most likely need to access pad->segment to make its decisions, + doing that from the sinkpad's streaming threads was racy. + +2017-12-28 12:12:45 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + API: GstAggregatorPad.skip_buffer virtual method + Allows subclasses to prevent buffers from being queued. + https://bugzilla.gnome.org/show_bug.cgi?id=781928 + +2018-01-23 20:04:02 +0100 Mathieu Duponchelle + + * libs/gst/base/gstbasesrc.h: + basesrc: Annotate some of the virtual methods + +2018-01-23 08:56:34 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + * win32/common/libgstbase.def: + aggregator: rename _get_buffer() -> _peek_buffer() and _steal -> _pop + https://bugzilla.gnome.org/show_bug.cgi?id=791204 + +2018-01-20 15:30:53 +0000 Tim-Philipp Müller + + * gst/gstchildproxy.c: + childproxy: gracefully handle methods being NULL + Do this for all method invoke functions for consistency. + https://bugzilla.gnome.org/show_bug.cgi?id=750154 + +2018-01-18 18:11:59 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: fix .def file for new API + Fixes check + distcheck + +2017-08-01 10:43:32 +0200 Michele Dionisio + + * libs/gst/net/gstptpclock.c: + ptp: fix build failure with #undef USE_MEASUREMENT_FILTERING + "Label ‘out’ used but not defined", since it's also used by + the USE_MEDIAN_PRE_FILTERING branch. + https://bugzilla.gnome.org/show_bug.cgi?id=785631 + +2018-01-18 19:16:12 +0200 Sebastian Dröge + + * gst/gstpadtemplate.h: + padtemplate: And add missing GST_EXPORT to gst_pad_template_new_with_gtype() + +2018-01-18 19:15:09 +0200 Sebastian Dröge + + * gst/gstpadtemplate.c: + padtemplate: Add missing Since: 1.14 marker to gst_pad_template_new_with_gtype() + +2018-01-18 19:08:10 +0200 Sebastian Dröge + + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + padtemplate: Add gst_pad_template_new_with_gtype() + For being able to create a pad template with GType without having a + static pad template. + +2018-01-18 19:07:49 +0200 Sebastian Dröge + + * gst/gstpadtemplate.c: + padtemplate: Add Since: 1.14 marker to gst_pad_template_new_from_static_pad_template_with_gtype() + +2018-01-16 10:17:58 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Avoid stream-dead-lock on deactivation + The following case can happen when two thread try to activate and + deactivate a pad at the same time: + T1: starts to deactivate, calls pre_activate(), sets in_activation + to TRUE and carries on + T2: starts to activate, calls pre_activate(), in_activation is TRUE + so it waits on the GCond + T1: calls post_activate(), tries to acquire the streaming lock .. + but can't because T2 is currently holding it + With this patch, the deadlock will no longer happen but does not + solve the problem that: + T2: will resume activation of the pad, set the pad mode to the target + one (PUSH or PULL) and eventually the streaming lock gets released. + T1: is able to finish calling post_activate() ... but ... the pad + wasn't deactivated (T2 was the last one to "activate" the pad. + https://bugzilla.gnome.org/show_bug.cgi?id=792341 + +2018-01-15 18:13:45 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Release pending g_cond_wait() when stopping/pausing task + Otherwise we would deadlock waiting forever for the streaming lock + to be released + https://bugzilla.gnome.org/show_bug.cgi?id=792341 + +2018-01-13 11:08:00 +0800 Jun Xie + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: fix confusing debug log message + In case of a short buffer, the debug log is quite confusing. + Distinguish the two types of failure cases to make it clearer. + https://bugzilla.gnome.org/show_bug.cgi?id=792486 + +2018-01-12 18:47:17 +0000 Tim-Philipp Müller + + * gst/gstobject.c: + docs: explicit refer to GObject docs for floating refs + https://bugzilla.gnome.org/show_bug.cgi?id=788477 + +2018-01-11 19:52:41 +0000 Tim-Philipp Müller + + * tests/check/elements/fakesink.c: + tests: fakesink: make notify stress test work better on Windows + Set up all ten pipelines and preroll them first, and only set + them to playing to run wild after they're all set up. If we set + them to PLAYING directly and let those threads run wild, then + it might take ages (many seconds) for the other pipelines to + even get up and running, especially on machines with only one + or two cores, and operating systems that suck at scheduling. + Now the fakesink test takes 19 secs instead of 71 secs on a + single-cpu windows machine. + +2018-01-11 19:32:08 +0000 Tim-Philipp Müller + + * tests/check/elements/filesrc.c: + tests: filesrc: more Windows fixes + Fix typo in newly-added windows uri test. + +2018-01-11 18:44:50 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + utils: use g_get_monotonic_time() as fallback in gst_utils_get_timestamp() + This is a better fit given that the function docs say this + should (only) be used for interval measurements, but also + this seems to give much better granularity on Windows + systems, where before this change there would often be + 10-20 lines of debug log with the same timestamp up front. + +2018-01-11 18:39:50 +0000 Tim-Philipp Müller + + * tests/check/gst/gstsystemclock.c: + tests: systemclock: scale stress test threads according to number of cpus + Scale the number of threads used in the stress tests according to + the number of cores/cpus. We want some contention, but we also + don't want too much contention, as some operating systems are + better at handling 100 threads running wild on a single core + than others. + +2018-01-11 17:10:45 +0000 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: plugin_load() must return a ref even if it was loaded already + Fix refcounting issue when plugin was loaded already. + gst_plugin_load() is supposed to return a ref, so it + must always return a ref. + This also fixes the gstplugin unit test on windows where + fork is not available and where test_load_coreelements() + would unref a plugin ref it didn't get and then mess up + the internal registry plugin list state for the next test, + in case where the test registry does not exist yet. + +2018-01-11 14:56:42 +0000 Tim-Philipp Müller + + * tests/check/elements/filesrc.c: + tests: filesrc: fix for windows + Location paths have backslashes on windows when converted from URI. + +2018-01-11 12:27:18 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + libs: check: print stacktrace on unexpected criticals + +2018-01-11 12:02:47 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_x86_64w.h: + tests: abi: fix abi test on 64-bit Windows + Add header with structure sizes for 64-bit windows as well. + They're almost the same as on Linux, but it looks like things + like padding unions get aligned slightly differently so there + are a handful of differences: + sizeof(GstGhostPad) is 528, expected 536 + sizeof(GstPad) is 512, expected 520 + sizeof(GstPadProbeInfo) is 64, expected 72 + sizeof(GstProxyPad) is 520, expected 528 + +2018-01-11 11:38:53 +0000 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: info: fix post init cat reg test on windows and with CK_FORK=no + The test checks that categories not covered by the pattern in the + GST_DEBUG string have debug level GST_LEVEL_DEFAULT set, but previous + tests mess with the default threshold, which made this test fail on + Windows or when run with CK_FORK=no. Fix this by resetting everything + at the beginning, and then also do a sanity check afterwards. + +2018-01-11 11:36:53 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: reset default threshold to LEVEL_DEFAULT not 0 + in set_threshold_from_string(). + +2017-11-08 20:05:03 +0100 Håvard Graff + + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/libcompat/libcompat.h: + * libs/gst/check/libcheck/meson.build: + * libs/gst/check/meson.build: + * libs/gst/meson.build: + * pkgconfig/meson.build: + * tests/meson.build: + meson: make check and tests build on Windows with msvc + +2018-01-02 10:02:45 +0100 Edward Hervey + + * libs/gst/check/gstharness.c: + gstharness: Remove double free + +2017-12-26 18:08:31 +0100 Sebastian Dröge + + * gst/gststreams.h: + streams: GstStreamType/GstStream are available since 1.10 + Annotate them as such. + +2017-12-26 13:46:20 +0100 Tim-Philipp Müller + + * meson.build: + meson: skip translations if gettext is not available + +2017-12-26 12:51:22 +0100 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: remove DEBUG_FUNCPTR + The new gst_element_do_foreach_pad() does not print the functions anymore. + +2017-12-26 12:17:53 +0100 Stefan Sauer + + * tools/gst-inspect.c: + inspect: add comment for how to improve tracer support + +2017-12-26 11:29:39 +0100 Stefan Sauer + + * gst/gstsegment.c: + segment: add a FIXME-2.0 for the format parameters + Capture the somewhat not ordinary use of the extra format parameter in a + comment. + See https://bugzilla.gnome.org/show_bug.cgi?id=788979 + +2017-12-24 16:21:38 +0100 Tim-Philipp Müller + + * gst/gst.c: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstdeinit.c: + * tests/check/meson.build: + Skip gst_deinit() if gstreamer was not initialized properly + Can happen if an error occurs during option parsing, for example. + https://bugzilla.gnome.org/show_bug.cgi?id=781914 + +2017-12-23 23:43:33 +0100 Jan Alexander Steffens (heftig) + + * tests/check/elements/multiqueue.c: + tests: multiqueue: Replace large test macro with function + Just a bit of cleanup. + https://bugzilla.gnome.org/show_bug.cgi?id=756867 + +2017-12-15 09:43:40 +0100 Jan Alexander Steffens (heftig) + + * tests/check/elements/multiqueue.c: + tests: multiqueue: Check we get CREATE+ENTER stream-statuses when adding pads + https://bugzilla.gnome.org/show_bug.cgi?id=756867 + +2017-12-15 09:14:57 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't start new pads until parented + Start task on new source pads added at runtime after they + have been added to the element, not during activation. + This ensures the pads can post their CREATE stream-status + messages and the application can set thread priorities. + https://bugzilla.gnome.org/show_bug.cgi?id=756867 + +2017-12-15 09:14:07 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstmultiqueue.c: + multiqueue: Split task handling from gst_single_queue_flush + https://bugzilla.gnome.org/show_bug.cgi?id=756867 + +2017-12-23 23:25:58 +0100 Jan Alexander Steffens (heftig) + + * libs/gst/base/gstaggregator.c: + aggregator: Avoid a maybe-uninitialized warning + Arch Linux x86_64, gcc 7.2.1-2, -Og -g3 + +2017-12-21 13:47:52 +0200 Sebastian Dröge + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: Don't hold the mutex while posint the download-complete message + Something might handle it from a sync message handler and call back into + downloadbuffer, causing a deadlock. + +2017-12-20 18:56:23 +0200 Sebastian Dröge + + * gst/gstsystemclock.c: + systemclock: set_default() clock parameter can be NULL + +2017-12-20 18:11:48 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Annotate set_clock() clock parameter with allow-none + +2017-12-20 18:09:28 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Annotate set_bus() bus parameter as allow-none + It's possible to replace the bus with NULL/None + +2017-12-10 22:50:05 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: update for gl lib move from bad to base + +2017-12-11 20:58:16 -0500 Nicolas Dufresne + + * libs/gst/base/gstbasetransform.c: + basetransform: Allow going passthrough inside decide_allocation + Sub-class may want to decide to go passthrough/in-place by inspecting + the support meta APIs. This patch duplicates the check for this mode, + so we still don't do uneeded allocation query while we allow sub-classes + to switch the behaviour during it's own decide_allocation call. + Notice that such sub-class need to reset the class to non-passthrough in + set_caps() in order for decide_allocation to be called again. This is + needed otherwise we'd be doing an allocation query in element in which + it make no sense (notably capsfilter). + https://bugzilla.gnome.org/show_bug.cgi?id=791453 + +2017-12-17 14:18:38 +0200 Sebastian Dröge + + * gst/gstplugin.c: + plugin: Annotate add_dependency() arguments as NULL-terminated arrays + +2017-12-14 00:03:04 +0530 Umang Jain + + * gst/gstbus.c: + docs: GstBus: Provide more information for ref/unref during bus watch. + https://bugzilla.gnome.org/show_bug.cgi?id=791588 + +2017-12-14 16:05:00 +1100 Matthew Waters + + * win32/common/libgstreamer.def: + update win32 defs for tracer API addition + +2017-12-14 14:48:47 +1100 Matthew Waters + + * common: + Automatic update of common submodule + From e8c7a71 to 3fa2c9e + +2017-12-05 21:36:34 +1100 Matthew Waters + + * docs/gst/gstreamer-sections.txt: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/inspect/plugin-coretracers.xml: + * gst/gsttracerfactory.c: + * gst/gsttracerfactory.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + docs: include tracers in the documentation + Requires exposing the tracer GType from the GstTracerFactory in order + to link the plugin with the tracer in the documentation. + https://bugzilla.gnome.org/show_bug.cgi?id=791253 + +2017-12-05 20:56:09 +1100 Matthew Waters + + * libs/gst/check/gstharness.c: + check/harness: fix transfer annotations on buffer passing functions + +2017-08-30 13:03:28 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * tests/check/libs/basesrc.c: + * win32/common/libgstbase.def: + basesrc: add buffer list support + Add a gst_base_src_submit_buffer_list() function that allows subclasses + to produce a bufferlist containing multiple buffers in the ::create() + function. The buffers in the buffer list will then also be pushed out + in one go as a GstBufferList. This can reduce push overhead + significantly for sources with packetised inputs (such as udpsrc) + in high-throughput scenarios. + The _submit_buffer_list() approach was chosen because it is fairly + straight-forward, backwards-compatible, bindings-friendly (as opposed + to e.g. making the create function return a mini object instead), + and it allows the subclass maximum control: the subclass can decide + dynamically at runtime whether to return a list or a single buffer + (which would be messier if we added a create_list virtual method). + https://bugzilla.gnome.org/show_bug.cgi?id=750241 + +2017-08-31 01:18:28 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesrc.c: + basesrc: minor code readability improvement + +2017-12-07 12:05:23 +0000 Tim-Philipp Müller + + * gst/gstbus.c: + * gst/gstevent.c: + * gst/gsttracer.c: + * gst/gsttracerutils.h: + * gst/gstvalue.h: + docs: Fix a few gtk-doc warnings + Broken links mostly. + +2017-12-06 20:58:42 +0000 Tim-Philipp Müller + + * tests/check/libs/aggregator.c: + tests: aggregator: fix caps leak in unit test + +2017-12-06 17:07:29 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Handle GST_PAD_PROBE_HANDLED on sticky event push + When actually pushing an event, if we get GST_FLOW_CUSTOM_SUCCESS_1 + (which is the conversion of GST_PAD_PROBE_HANDLED return value), + don't consider the stick event push as ignored, but as handled + +2017-12-06 13:40:46 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + event/query/message: Annotate get_structure() return value as nullable + +2017-12-06 13:36:30 +0200 Sebastian Dröge + + * gst/gstquery.c: + query: Add an empty structure in writable_structure() if there is none yet + This is consistent with how it works for GstEvent already. + +2017-12-05 18:21:00 +0100 Edward Hervey + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstpromise.c: + * gst/gststreamcollection.h: + * gst/gststreams.h: + docs: Misc addition/fixes + And also add the "Since" API sections for 1.12 and 1.14 + +2017-12-05 18:20:34 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + docs: Add documentation for GST_SEQNUM_INVALID + And link to it + +2017-12-05 17:28:55 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + utils: Never return a group_id of 0, add GST_GROUP_ID_INVALID + Various plugins use special values (0 or G_MAXUINT32) as an + invalid/unset group_id, but nothing guarantees a groupid won't have + that value. + Instead define a value which group_id will never have and make + gst_group_id_next() always return a value different from that. + API: GST_GROUP_ID_INVALID + +2017-12-05 16:42:57 +0000 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: make bindings use the GBytes variant for _take_all_data() + +2016-11-23 13:12:36 +0100 Havard Graff + + * libs/gst/check/gstharness.c: + harness: use new take_all_data() function in _dump_to_file(). + +2017-12-05 15:28:43 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + * tests/check/libs/gstharness.c: + harness: add gst_harness_take_all_data() + _take_all_data_as_{bytes,buffer}() + Convenience function to just grab all pending data + from the harness, e.g. if we just want to check if + it matches what we expect and we don't care about + the chunking or buffer metadata. + Based on patch by: Havard Graff + +2017-12-05 15:16:36 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: document that _extract_dup() will return NULL for 0-sized buf + And make it explicit, and don't call _extract() on NULL data buffer. + +2017-12-05 12:27:18 +0530 Nirbheek Chauhan + + * tests/check/meson.build: + meson: Use array syntax instead of .get() in tests + +2017-11-24 02:39:43 +0530 Nirbheek Chauhan + + * gst/parse/meson.build: + meson: Use new find_program fallback syntax + We use this syntax in libs/gst/helpers/meson.build already. + +2017-12-04 18:08:39 +0200 Sebastian Dröge + + * gst/gstelement.c: + gst: gst_element_remove_pad() is transfer none for the pad + While the refcount of the pad is decreased, it's the refcount that is + owned by the parent (i.e. the element) and not the one passed in by the + caller. + Fixes a memory leak in bindings. + +2017-12-04 11:24:47 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: add finish_buffer() vfunc + So subclasses can override the finish behaviour + and/or decorate or modify buffers before they + get pushed out. + https://bugzilla.gnome.org/show_bug.cgi?id=760981 + +2017-12-04 12:29:05 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: disable tag merging and forwarding for now + Subclasses should handle this for now. + +2017-11-06 20:23:12 +0100 Jan Alexander Steffens (heftig) + + * gst/gstdevicemonitor.c: + devicemonitor: Avoid maybe-uninitialized compiler warning + On Arch Linux x86_64, gcc 7.2.0-3, -Og -g3: + gstdevicemonitor.c: In function ‘bus_sync_message’: + gstdevicemonitor.c:276:8: error: ‘matches’ may be used uninitialized in this function [-Werror=maybe-uninitialized] + This commit also simplifies the code a bit. + https://bugzilla.gnome.org/show_bug.cgi?id=789983 + +2017-12-03 14:48:22 +0200 Sebastian Dröge + + * gst/gstdebugutils.c: + * gst/gstplugin.c: + * gst/gstregistry.c: + gst: Annotate various strings as type filename if they represent a path/filename + +2017-12-02 15:44:48 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * libs/gst/base/gstaggregator.c: + aggregator: hook up to docs + +2017-12-02 15:24:22 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/base/base.h: + * libs/gst/base/gstaggregator.h: + * libs/gst/base/meson.build: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/meson.build: + * win32/common/libgstbase.def: + aggregator: hook up to build system + https://bugzilla.gnome.org/show_bug.cgi?id=739010 + +2017-12-02 15:12:25 +0000 Tim-Philipp Müller + + Move GstAggregator from -bad to core + Merge branch 'aggregator-move' + https://bugzilla.gnome.org/show_bug.cgi?id=739010 + +2017-11-06 21:07:51 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Remove klass->sinkpads_type + This posed problems for the python bindings (and possibly others). + Instead, subclasses now use add_pad_template_with_gtype. + https://bugzilla.gnome.org/show_bug.cgi?id=789986 + +2017-11-02 18:32:55 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: add doc blurb for gst_aggregator_pad_is_eos() + +2017-11-02 16:05:12 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: also remove now-unused PadForeachFunc declaration + https://bugzilla.gnome.org/show_bug.cgi?id=785679 + +2017-08-02 12:08:26 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Remove pad iterator function + Use new gst_element_foreach_sink_pad() from core instead. + https://bugzilla.gnome.org/show_bug.cgi?id=785679 + +2017-11-02 12:46:26 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: use new gst_element_foreach_sink_pad() + Instead of gst_aggregator_iterate_sinkpads() which will + soon be removed. + https://bugzilla.gnome.org/show_bug.cgi?id=785679 + +2017-11-01 15:18:08 +0100 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: add more comments + +2017-10-23 11:52:38 +0200 Stefan Sauer + + * tests/check/libs/aggregator.c: + tests: comment and logging cleanups for audiomixer and aggregator + Remove some references to 'collectpads'. Logs pads through the object variants. + Add some more comments. Remove a left over comment. + +2017-10-22 19:43:17 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: fix type for latency property (int64 -> GStClockTime) + The value is used as GstClockTiem in the code. Adapt the hack^H^H^H^Hcode + in live-adder. + +2017-07-13 19:03:19 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Don't take flush lock from output thread + Instead just take it in the chain function. + https://bugzilla.gnome.org/show_bug.cgi?id=784911 + +2017-07-13 18:38:34 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Don't block if adding to the tail of the queue + If we're adding to the tail of the queue, it's because we're converting + a gap event, so don't block there it means we're calling from the output + thread. + https://bugzilla.gnome.org/show_bug.cgi?id=784911 + +2017-10-17 08:03:02 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: review code related to time level + Add a comment for when the state matters. Use a local var for priv in + update_time_level() to improve readability. Move the our_latency local + var below the query results checks. + +2017-10-17 07:51:51 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: init latency values with 0 instead of FALSE + +2017-10-15 20:46:09 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: code cleanup for event and query func + Only look up klass for non serialized events/queries. For events remove + superfluous assignment for the return value in the flushing case. + +2017-10-15 17:46:45 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: simplify pad_event_func for FLUSH_STOP events + We want to skip serialization for FLUSH_STOP events (apparently). We can + simplify the code to add it to the top-level conditions. There was nothing + done in the first code path if the event was FLUSH_STOP. + +2017-10-15 16:57:13 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: drop special casing for eos + Just queue it like any other serialized event. This way we don't need to + check if there still are buffers in the queue. + Validated with the tests and gst-launch-1.0 pipelines. + +2017-10-15 16:51:21 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: add a doc-blob for the event_func + +2017-10-15 16:48:21 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: rename a local variable + The variable tracks wheter the queue is not empty, but num_buffers==0. That + means we have events or queries to process. Rename accordingly. + +2017-10-15 12:17:42 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: remove commented code + The SEGMENT_DONE event does not require any special treatment. This is + commented out in 6efc106a67. + +2017-10-15 12:14:28 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: move the comment for the locks to the lock macros + Looks like some code was inserted afterwards. + +2017-10-15 10:44:44 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: improve section docs + Mention how data ends up in the queues. Document the relation of the pad + functions and the class vmethods to get events and queries. + +2017-10-14 18:18:44 +0200 Stefan Sauer + + * tests/check/libs/aggregator.c: + aggregator: add two more tests for a sequence of data + This verifies that we handle events and queries at the head of the queue and + then buffers. + +2017-10-14 13:26:02 +0200 Stefan Sauer + + * tests/check/libs/aggregator.c: + aggregator: refactor the test helper + Make the test helpers use a queue. This lets us also test sequences of events, + queries and data. + +2017-10-14 12:08:19 +0200 Stefan Sauer + + * tests/check/libs/aggregator.c: + aggregator: test cleanup + Remove gst_init() from a few tests. Use _OBJECT variants in logging. Remove + arbitrary extra blank lines. Make push_event() more like push_buffer() - set + the event to NULL and add cleanup to _chain_data_clear(). + +2017-10-03 12:36:10 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: cleanup event forwarding + Don't copy the whole event struct. Set the input params when we call the + forwarding helper. Initialize the internal fields and return values in the + helper. + +2017-10-03 12:08:42 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: simplify src_event + Avoid extra ref/unref, we have a ref and do_seek unrefs. Just return the result + as we have. This lets us remove the local var plus the label. + +2017-09-17 12:37:03 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: register func for do_events_and_queries + This fixes logging the func ptr from _iterate_sinkpads(). + +2017-09-17 12:30:37 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: only set clipped_buffer to NULL if needed + +2017-09-17 12:25:37 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: rename check_events + This function also handles queries. Update the code to loop until all events and + queuries are handled. + +2017-09-17 12:24:54 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: add a few more comments to PadPrivate struct + +2017-09-17 11:39:12 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: rename buffers field to data + The queue stores buffers, events and queries. + +2017-09-17 10:18:56 -0700 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: documentaion fixes + Fix typos and remove params docs, where the param was moved. + +2017-09-05 14:26:52 +0200 Edward Hervey + + * tests/check/libs/aggregator.c: + check: Fix usage of dual probes + Using two (or more) probes on the same pad where one of the probe + returns HANDLED or DROP is tricky since the other probes might + not be called. + Instead use regular probes and a proper pad (the sinkpad already existed, + it only required to be activated and have a dummy chain function for + the events/buffers to be received/handled properly) + +2017-07-30 12:17:57 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: log all events + We already log a few events explicitly, just log them all with more detail. + +2017-07-29 16:54:38 +0100 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: fix header formatting + +2017-07-24 18:38:57 +0300 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Remove the GAP event from the queue before queueing up the GAP buffer + Otherwise check_events() will not remove the GAP event (as the queue + tail is not the event anymore but the GAP buffer), then the GAP buffer + is handled, then the GAP event is handled again, ... forever. + +2017-07-18 00:30:51 +0100 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: mark symbols explicitly for export with GST_EXPORT + +2017-07-13 22:00:58 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: remove duplicated code fragment + This code already runs above when (event || query). + +2017-07-13 21:55:55 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: code cleanups + Fix comment typos, some copy'n'paste in logging. Add more doc comments. + +2017-04-13 22:11:55 +0200 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: Invalidate pad's tail position ... + when dequeuing a segment event. + https://bugzilla.gnome.org/show_bug.cgi?id=784593 + +2017-07-01 20:23:25 +0200 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: fix "'aggclass' may be used uninitialized in this function" + +2017-05-23 00:53:57 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Process serialized queries through the queue + This ensures that they really get processed in order with + buffers. Just waiting for the queue to be empty is sometimes not + enough as the buffers are dropped from the pad before the result is + pushed to the next element, sometimes resulting in surprising + re-ordering. + +2017-05-23 00:53:23 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Set flow to FLUSHING on pad stop + Fixes a rare race where the pad is being stopped while doing a query. + +2016-11-18 14:44:16 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Request pad templates which are not request pad + https://bugzilla.gnome.org/show_bug.cgi?id=782920 + +2016-11-18 14:41:54 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Don't restrict sink pad names + Sink pads could have other names than sink_%u + https://bugzilla.gnome.org/show_bug.cgi?id=782920 + +2017-05-21 15:19:17 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Implement propose allocation + https://bugzilla.gnome.org/show_bug.cgi?id=782918 + +2017-05-21 14:34:13 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Check for the result of caps events + https://bugzilla.gnome.org/show_bug.cgi?id=782918 + +2017-05-21 14:28:00 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Caps event always goes to the aggregate thread + So no need to check it here. + https://bugzilla.gnome.org/show_bug.cgi?id=782918 + +2017-05-20 16:58:54 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Add downstream allocation query + https://bugzilla.gnome.org/show_bug.cgi?id=746529 + +2017-05-20 15:56:16 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.h: + aggregator: Remove unused GST_FLOW_NOT_HANDLED + +2017-05-20 14:24:57 +0200 Matthew Waters + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: add simple support for caps handling + Modelled off the videoaggregator caps handling as that seems the most + mature aggregtor-using implementation that has caps handling there is. + https://bugzilla.gnome.org/show_bug.cgi?id=776931 + +2017-05-20 13:10:53 +0200 Nicolas Dufresne + + * libs/gst/base/gstaggregator.c: + aggregator: Reset upstream latency on first buffer + In the case an aggregator is created and pads are requested but only + linked later, we end up never updating the upstream latency. + This was because latency queries on pads that are not linked succeed, + so we never did a new query once a live source has been linked, so the + thread was never started. + https://bugzilla.gnome.org/show_bug.cgi?id=757548 + +2016-05-14 15:52:37 +0200 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Always handle sync'ed events on output thread + Having all synchronized events always be handled on the output + thread should make synchronization easier. + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2016-07-06 16:39:17 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Delay clipping to output thread + This is required because the synchronized events like caps or segments + may only be processed on the output thread. + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2016-07-07 16:13:57 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Make pad eos as soon as all buffers are processed, dont way for events + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2016-07-07 11:47:40 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Only count buffers when declaring queue full + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2016-07-06 16:41:44 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Simplify clip function + The return value was ignored anyway + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2016-05-15 16:04:58 +0300 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Only declare first buffer on actual buffer + The function needs to be unlocked if any data is received, but only + end the first buffer processing on an actual buffer, synchronized events + don't matter on the first buffer processing. + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2017-05-09 20:20:07 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Set initial position on first buffer + Set the initial position on the first buffer, otherwise the queue + will grow without limits before the output thread is started. + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2017-05-09 20:06:29 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Reset the pad's first buffer flag with the rest + There is not reason to have separate code to reset this one. + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2017-05-09 20:05:55 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Reset pad on init + Factor out the pad reset code from the flushing and use it on init as well + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2017-05-09 20:13:58 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Fix indentation + https://bugzilla.gnome.org/show_bug.cgi?id=781673 + +2017-03-08 15:01:13 -0300 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + docs: Port all docstring to gtk-doc markdown + +2017-04-12 12:06:52 -0300 Thibault Saunier + + * libs/gst/base/gstaggregator.h: + aggregator: Make instance var name match between .c and .h + Making GI happy + +2017-04-07 10:19:43 +0100 Vincent Penquerc'h + + * libs/gst/base/gstaggregator.c: + gstaggregator: fix event use after free + https://bugzilla.gnome.org/show_bug.cgi?id=781017 + +2016-09-06 16:05:53 -0300 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Use the event_full function for GstAggregatorPads + Allowing us to tell GstPad why we are failing an event, which might + be because we are 'flushing' even if the sinkpad is not in flush state + at that point. + +2016-05-25 13:38:47 -0400 Nicolas Dufresne + + * libs/gst/base/gstaggregator.c: + Revert "aggregator: Start the task when linked" + This reverts commit 302580c3815136d29479c3a8cae611d6e2ff3709. + +2016-04-13 16:30:28 -0400 Nicolas Dufresne + + * libs/gst/base/gstaggregator.c: + aggregator: Start the task when linked + Until now we would start the task when the pad is activated. Part of the + activiation concist of testing if the pipeline is live or not. + Unfortunatly, this is often too soon, as it's likely that the pad get + activated before it is fully linked in dynamic pipeline. + Instead, start the task when the first serialized event arrive. This is + a safe moment as we know that the upstream chain is complete and just + like the pad activation, the pads are locked, hence cannot change. + https://bugzilla.gnome.org/show_bug.cgi?id=757548 + +2016-04-22 10:15:39 -0400 Nicolas Dufresne + + * libs/gst/base/gstaggregator.c: + aggregator: Check all pads for data when live + When live, we still need to inspect all pads queue in order to determin + if we have received the first buffer or not. + https://bugzilla.gnome.org/show_bug.cgi?id=765431 + +2016-04-15 16:51:17 -0400 Nicolas Dufresne + + * libs/gst/base/gstaggregator.c: + aggregator: Fix locking when using the clock + This fixes a race where we check if there is a clock, then it get + removed and we endup calling gst_clock_new_single_shot_id() with a NULL + pointer instead of a valid clock and also calling gst_object_unref() + with a NULL pointer later. + https://bugzilla.gnome.org/show_bug.cgi?id=757548 + +2016-04-03 17:56:06 +0200 Aurélien Zanelli + + * libs/gst/base/gstaggregator.c: + aggregator: remove duplicated test of flow_return in pad_chain_internal + https://bugzilla.gnome.org/show_bug.cgi?id=764549 + +2016-03-28 13:52:07 +0300 Sebastian Dröge + + * tests/check/libs/aggregator.c: + aggregator: Fix leak in unit test + GST_PAD_PROBE_HANDLED means that we should've unreffed the probe data, + it was handled by us in one way or another. + +2016-03-27 19:06:50 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Fix strcmp test for sink template + +2016-03-27 18:41:30 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Don't try to be too smart while allocating pad names + Previously, while allocating the pad number for a new pad, aggregator was + maintaining an interesting relationship between the pad count and the pad + number. + If you requested a sink pad called "sink_6", padcount (which is badly named and + actually means number-of-pads-minus-one) would be set to 6. Which means that if + you then requested a sink pad called "sink_0", it would be assigned the name + "sink_6" again, which fails the non-uniqueness test inside gstelement.c. + This can be fixed by instead setting padcount to be 7 in that case, but this + breaks manual management of pad names by the application since it then becomes + impossible to request a pad called "sink_2". Instead, we fix this by always + directly using the requested name as the sink pad name. Uniqueness of the pad + name is tested separately inside gstreamer core. If no name is requested, we use + the next available pad number. + Note that this is important since the sinkpad numbering in aggregator is not + meaningless. Videoaggregator uses it to decide the Z-order of video frames. + +2016-03-04 15:50:26 +0900 Vineeth TM + + * tests/check/libs/aggregator.c: + bad: use new gst_element_class_add_static_pad_template() + https://bugzilla.gnome.org/show_bug.cgi?id=763081 + +2015-11-09 16:08:30 +0900 Hyunjun Ko + + * tests/check/libs/aggregator.c: + tests:aggregator: fix tc failure and correct check value + Failure by this commit 2dfa548f3645844082c3db65d96d87255701b3ad, which is + to append hooks instead of prepend. + Because of this change, aggretated_cb is not called and leads to failure. + And correct to check flush stop value instead of flush start value + https://bugzilla.gnome.org/show_bug.cgi?id=757801 + +2015-11-05 12:36:48 +0000 Luis de Bethencourt + + * libs/gst/base/gstaggregator.c: + aggregator: use GST_STIME_FORMAT for GstClockTimeDiff + No need to manually handle negative value of deadline, GST_STIME_FORMAT does + exactly this. + +2015-11-03 19:09:33 -0800 Stefan Sauer + + * libs/gst/base/gstaggregator.c: + aggregator: don't compare templ instance pointers + One can pass the PadTemplate from the element_class or the one from the factory. + While they have the same content, the addresses are different. + +2015-11-03 14:41:57 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Set to running in a single place + Only set to running when the thread is actually started. + +2015-11-03 14:37:26 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Document more locking + +2015-11-02 20:10:35 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Hold object lock while manipulating the segment + Make sure the object lock is held when aggregator->segment is + modified. + +2015-11-02 19:05:01 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Remove dead code + This code will never be called as max>=min in all cases. If the upstream + latency query returned min>max, the function already returned and all + values that are added to those have max>= min. + +2015-10-23 15:42:24 +0300 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Add create_new_pad() vfunc to allow subclasses to override the default behaviour + Not all aggregator subclasses will have a single pad template called sink_%u + and might do something special depending on what the application requests. + https://bugzilla.gnome.org/show_bug.cgi?id=757018 + +2015-09-30 19:05:35 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Convert GST_ERROR_OBJECT() for seek events to GST_DEBUG_OBJECT() + +2015-09-30 19:03:05 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: For the start time selection, only set the segment position + segment.time and segment.start can stay the same, and were always the same + before anyway because of a mistake. + https://bugzilla.gnome.org/show_bug.cgi?id=755623 + +2015-08-31 16:12:40 +0300 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Don't forward QOS events to sinkpads that had no buffer yet + Otherwise they will receive a QOS event that has earliest_time=0 (because we + can't have negative timestamps), and consider their buffer as too late + https://bugzilla.gnome.org/show_bug.cgi?id=754356 + +2015-09-17 19:42:34 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Keep at least two buffers in the queue in live mode + When in live mode, the queue needs to hold the currently processed + buffer and one more at least. + https://bugzilla.gnome.org/show_bug.cgi?id=754851 + +2015-09-11 12:21:50 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.h: + aggregator: Document that get_next_time() should return running time + https://bugzilla.gnome.org/show_bug.cgi?id=753196 + +2015-08-28 23:05:20 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Also ignore start-time on seek from gst_element_send_event() + https://bugzilla.gnome.org/show_bug.cgi?id=753806 + +2015-07-02 19:34:43 -0400 Olivier Crête + + * tests/check/libs/aggregator.c: + tests: Add test for seeking live pipelines + https://bugzilla.gnome.org/show_bug.cgi?id=745768 + +2015-07-02 19:19:33 -0400 Olivier Crête + + * tests/check/libs/aggregator.c: + tests: Make source live to re-enable aggregator timeout tests + The live mode is only enabled if one of the sources if live. + https://bugzilla.gnome.org/show_bug.cgi?id=745768 + +2015-03-06 19:50:08 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Queue "latency" buffers at each sink pad. + In the case where you have a source giving the GstAggregator smaller + buffers than it uses, when it reaches a timeout, it will consume the + first buffer, then try to read another buffer for the pad. If the + previous element is not fast enough, it may get the next buffer even + though it may be queued just before. To prevent that race, the easiest + solution is to move the queue inside the GstAggregatorPad itself. It + also means that there is no need for strange code cause by increasing + the min latency without increasing the max latency proportionally. + This also means queuing the synchronized events and possibly acting + on them on the src task. + https://bugzilla.gnome.org/show_bug.cgi?id=745768 + +2015-07-29 20:07:09 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Default to "zero" start time selection mode as documented + +2015-07-29 20:06:11 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Ignore the "first" mode if the segment not a time segment + +2015-06-15 18:30:20 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Add property to select how to decide on a start time + Before aggregator based elements always started at running time 0, + now it's possible to select the first input buffer running time or + explicitly set a start-time value. + https://bugzilla.gnome.org/show_bug.cgi?id=749966 + +2015-07-28 21:15:43 +0300 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Query the peer latency again on the next opportunity after a pad was added or removed + Adding a pad will add a new upstream that might have a bigger minimum latency, + so we might have to wait longer. Or it might be the first live upstream, in + which case we will have to start deadline based aggregation. + Removing a pad will remove a new upstream that might have had the biggest + latency, so we can now stop waiting a bit earlier. Or it might be the last + live upstream, in which case we can stop deadline based aggregation. + +2015-05-06 13:07:52 -0300 Thiago Santos + + * libs/gst/base/gstaggregator.h: + aggregator: add a convenience macro to get the source pad + Easier than casting or acessing the parent everywhere + +2015-06-01 18:50:14 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Document that the latency is in ns + +2015-05-28 00:59:39 +1000 Jan Schmidt + + * libs/gst/base/gstaggregator.c: + aggregator: Push EOS on error return. + Before shutting down the srcpad task due to a + downstream error, push an EOS to give downstream + a chance to shut down somewhat cleanly. + +2015-03-29 17:53:23 -0300 Reynaldo H. Verdejo Pinochet + + * libs/gst/base/gstaggregator.c: + aggregator: document gap handling behavior + https://bugzilla.gnome.org/show_bug.cgi?id=746249 + +2015-03-27 19:36:42 -0300 Reynaldo H. Verdejo Pinochet + + * libs/gst/base/gstaggregator.c: + aggregator: drop stale white space at warning + +2015-03-27 19:28:05 -0300 Reynaldo H. Verdejo Pinochet + + * tests/check/libs/aggregator.c: + aggregator: fix typo in test suite + +2015-03-27 18:32:27 -0300 Reynaldo H. Verdejo Pinochet + + * tests/check/libs/aggregator.c: + aggregator: add gap event handling unit test + https://bugzilla.gnome.org/show_bug.cgi?id=746249 + +2015-03-17 22:13:06 -0300 Reynaldo H. Verdejo Pinochet + + * libs/gst/base/gstaggregator.c: + aggregator: implement gap handling + https://bugzilla.gnome.org/show_bug.cgi?id=746249 + +2015-04-01 22:10:11 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Unify downstream flow return and flushing + Also means that having a non-OK downstream flow return + wakes up the chain functions. + https://bugzilla.gnome.org/show_bug.cgi?id=747220 + +2015-04-01 21:45:01 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Flushing is always in pad lock, no need to atomics + The usage of atomics was always doubtful as it was used to release a + GCond + https://bugzilla.gnome.org/show_bug.cgi?id=747220 + +2015-04-01 21:38:11 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Reset pending_eos on pad flush + https://bugzilla.gnome.org/show_bug.cgi?id=747220 + +2015-04-01 21:37:25 -0400 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Unify code to set a pad flushing + https://bugzilla.gnome.org/show_bug.cgi?id=747220 + +2015-03-06 21:12:52 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Query latency on first incoming buffer. + And keep on querying upstream until we get a reply. + Also, the _get_latency_unlocked() method required being calld + with a private lock, so removed the _unlocked() variant from the API. + And it now returns GST_CLOCK_TIME_NONE when the element is not live as + we think that 0 upstream latency is possible. + https://bugzilla.gnome.org/show_bug.cgi?id=745768 + +2015-03-06 21:12:13 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Be more aggressive with invalid replies to our latency query + https://bugzilla.gnome.org/show_bug.cgi?id=745768 + +2015-03-08 02:04:11 +1100 Matthew Waters + + * libs/gst/base/gstaggregator.h: + aggregatory: don't redefine GST_FLOW_CUSTOM_SUCCESS + +2015-02-27 00:26:00 +0530 Arun Raghavan + + * libs/gst/base/gstaggregator.c: + aggregator: Use standard upstream latency querying logic + The same functionality is duplicated in the default latency querying + now. + +2015-02-19 21:21:56 -0500 Olivier Crete + + * libs/gst/base/gstaggregator.c: + aggregator: Use src_lock to protect latency related members + One has to use the src_lock anyway to protect the min/max/live so they + can be notified atomically to the src thread to wake it up on changes, + such as property changes. So no point in having a second lock. + Also, the object lock was being held across a call to + GST_ELEMENT_WARNING, guaranteeing a deadlock. + +2015-02-19 18:53:32 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Remove untrue comment + +2015-02-19 18:30:35 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Don't try to push tags while flush seeking + The downstream segment could have been flushed already, so + need to re-send the segment event before re-sending the tags. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-02-19 11:04:28 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Use the sinkpads iterator directly to query upstream latencies + While gst_aggregator_iterate_sinkpads() makes sure that every pad is only + visited once, even when the iterator has to resync, this is not all we have + to do for querying the latency. When the iterator resyncs we actually have + to query all pads for the latency again and forget our previous results. It + might have happened that a pad was removed, which influenced the result of + the latency query. + +2015-02-19 10:57:09 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Move gst_aggregator_get_latency_unlocked() a bit + It was between another function and its helper function before, which was + confusing when reading the code as it had nothing to do with the other + functions. + +2015-02-19 01:28:06 +0200 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Fail the latency query if one of the upstream queries fails + +2015-02-18 15:53:53 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Document locking order + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-02-18 15:11:14 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Rename confusinly named SRC_STREAM_LOCK macros to SRC_LOCK + This will match the name of the lock itself. It is also not a stream + lock as it not recursive and not held while pushing. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-02-18 15:06:01 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Rename confusingly named stream lock to flush lock + This lock is not what is commonly known as a "stream lock" in GStremer, + it's not recursive and it's taken from the non-serialized FLUSH_START event. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-02-18 15:04:04 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Fix macro indendation + Changes no code + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-02-13 23:45:20 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: drop GAP events until we handle them properly + +2015-02-13 15:53:19 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * tests/check/libs/aggregator.c: + aggregator: use new gst_aggregator_pad_drop_buffer() + +2015-02-13 15:49:50 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: add gst_aggregator_pad_drop_buffer() + steal_buffer() + unref seems to be a wide-spread idiom + (which perhaps indicates that something is not quite + right with the way aggregator pad works currently). + +2015-02-12 13:32:39 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: only post latency message if anything changed + Perhaps we should check for element state as well and + only post it if in PLAYING state. + +2015-02-11 14:16:21 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + Improve and fix LATENCY query handling + This now follows the design docs everywhere, especially the maximum latency + handling. + https://bugzilla.gnome.org/show_bug.cgi?id=744106 + +2015-02-10 10:49:16 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Pause srcpad task on flow errors + Otherwise we will call the task function over and over again until + upstream finally handled the flow return and shuts us down. + +2015-02-06 10:59:27 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Streamline latency calculations + Min latency can never be invalid, latency property can never be invalid + either. So no need to check for all these things in various places. + +2015-02-06 10:36:28 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: If upstream has no max latency but the subclass has, take the subclass max latency + +2015-02-06 10:33:59 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Fix min>max latency error check + We have to include the upstream latency, our own latency and the subclass + latency in the calculations. + FIXME: This is still not entirely correct + +2015-02-06 10:30:59 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Don't add the latency property to the max latency + It has no meaning for the max latency and is only used to increase the min + latency. + +2015-01-26 17:06:29 +0100 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Cleanup locking around AggregatorPad flush related fields + And document the locking + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-26 13:11:05 +0100 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: keep chain functions as dumb as possible. + + A pad chain function has no business checking other pads, + that's what the aggregate thread is for. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-26 11:32:47 +0100 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: More fixes around locking when accessing protected private fields + In some more places we were accessing GstAggregator->segment + and GstAggregator->seqnum without holding the GST_OBJECT_LOCK + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-26 11:29:08 +0100 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Make the PAD_LOCK private + Instead of using the GST_OBJECT_LOCK we should have + a dedicated mutex for the pad as it is also associated + with the mutex on the EVENT_MUTEX on which we wait + in the _chain function of the pad. + The GstAggregatorPad.segment is still protected with the + GST_OBJECT_LOCK. + Remove the gst_aggregator_pad_peak_unlocked method as it does not make + sense anymore with a private lock. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-26 11:25:54 +0100 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + aggregator: Hide GstAggregatorPad buffer and EOS fileds + And add a getter for the EOS. + The user should always use the various getters to access + those fields + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 18:41:43 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Document locking of GstAggregatorPrivate members + Most of them are protected by the object lock, specify + which ones use a different lock. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 18:47:09 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.h: + aggregator: Document how the segment is protected + Document that it can only be accessed with the object lock. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 19:44:57 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Protect all latency related members with the object lock + The locking was not consistent, now consistently use the object lock. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 19:43:12 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Document locking for gst_aggregator_get_latency_unlocked() + Renamed it to _unlocked() to make it clear. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 19:35:25 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Protect the srcpad caps negotiation with the stream lock + Instead of adding another lock, use the srcpad stream lock, which is already + taken anyway to push out the new caps if needed. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 19:33:18 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Protect the tags with the object lock + The tags related variables were sometimes protected, sometimes not and + sometimes atomic. Put them all under the object lock. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 18:53:20 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Consistenly lock the flow_return state + Use the object's lock to protect it. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-21 18:45:36 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Consistently lock some members + Some members sometimes used atomic access, sometimes where not locked at + all. Instead consistently use a mutex to protect them, also document + that. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-14 14:38:09 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Protect exported pad members with the pad's object lock + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-14 14:35:15 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Replace event lock with pad's object lock + Reduce the number of locks simplify code, what is protects + is exposed, but the lock was not. + Also means adding an _unlocked version of gst_aggregator_pad_steal_buffer(). + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-09 22:01:00 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Protect data with the same mutex as GCond + Whenever a GCond is used, the safest paradigm is to protect + the variable which change is signalled by the GCond with the same + mutex that the GCond depends on. + https://bugzilla.gnome.org/show_bug.cgi?id=742684 + +2015-01-14 23:47:19 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Nitpick spacing/punctuation in debug logging + +2015-01-09 21:51:40 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Remove pointless atomic + It is only modified from the streaming thread + +2015-01-09 21:30:36 -0500 Olivier Crête + + * libs/gst/base/gstaggregator.c: + aggregator: Fix query leak + +2015-01-09 16:43:39 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Print jitter from clock waiting in the debug logs + +2015-01-04 17:15:37 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: don't use iterator when setting flush pending on pads + +2015-01-04 16:57:05 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: check if pads are ready more efficiently + No need to use an iterator for this which creates a temporary + structure every time and also involves taking and releasing the + object lock many times in the course of iterating. Not to mention + all that GList handling in gst_aggregator_iterate_sinkpads(). + +2015-01-04 12:59:19 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: name vfunc arguments consistently + +2015-01-01 15:46:00 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: add g-i transfer and scope annotations + +2015-01-01 14:10:05 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: register names of iterate_sinkpads functions with debug system + +2015-01-01 14:03:02 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: reduce debug messages for taking/releasing logs to TRACE level + Don't spam debug log with this stuff. + +2014-12-31 18:16:21 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: move property member into private structure + Our locking (or lack thereof) while accessing this also + looks generally quite dodgy. + +2014-12-31 14:50:58 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: remove empty dispose function + +2014-12-30 23:58:34 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: give private functions namespace prefix + Especially the GST_DEBUG_FUNCPTR ones. + +2014-12-31 12:35:06 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: fix up some docs comments in header + +2014-12-30 23:44:46 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: remove now-unused system clock member + +2014-12-30 19:22:01 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: make GstAggregatorPadForeachFunc take an GstAggregatorPad + +2014-12-30 17:50:17 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: bring start/stop vfunc semantics in line with other baseclasses + Sub-class should not have to chain up to GstAggregator's start/stop + vfuncs, same as in GstBaseSrc, GstBaseSink, GstBaseTransform etc. + +2014-12-28 18:26:49 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: remove pointless GST_DEBUG_FUNCPTR + Not useful for GObject vfuncs. + +2014-12-28 18:24:21 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: remove duplicate pad parent_class variable + G_DEFINE_TYPE already provides one, just need to use it. + +2014-12-28 18:22:57 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: add _CAST() variants for cast macros + +2014-12-28 01:13:33 +0000 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.h: + aggregator: make padding larger + Esp. the class structures, can't have enough + spare space for virtual functions. + +2014-12-27 16:15:41 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Log to the pad instead of the element + More correct way of doing the same thing as before + +2014-12-27 09:49:43 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Make sure that the minimum latencies are never GST_CLOCK_TIME_NONE + +2014-12-27 09:42:57 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Wait for the minimum latency, not the maximum + The minimum latency is the latency we have to wait at least + to guarantee that all upstreams have produced data. The maximum + latency has no meaning like that and shouldn't be used for waiting. + +2014-12-27 04:21:36 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Clamp the min latency at the max if it's greater + +2014-12-27 04:21:26 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Print the sinkpad name while logging latency queries + Very useful while debugging. + +2014-12-27 04:19:52 +0530 Nirbheek Chauhan + + * libs/gst/base/gstaggregator.c: + aggregator: Take the stream lock when iterating sink pads + When iterating sink pads to collect some data, we should take the stream lock so + we don't get stale data and possibly deadlock because of that. This fixes + a definitive deadlock in _wait_and_check() that manifests with high max + latencies in a live pipeline, and fixes other possible race conditions. + +2014-12-23 11:45:05 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Don't leak flush-start events + +2014-12-23 10:24:27 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Also change the default latency to 0, not just the minimum + +2014-12-23 09:52:20 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Fix docs and default value of the latency property + +2014-12-22 22:19:52 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Also include the subclass latency in the result of the latency query + +2014-12-22 15:26:37 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Post a latency message if the value of the latency property changes + +2014-12-22 15:03:59 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Wake up the src thread after handling a latency query + Due to changed latencies or changed live-ness we might have to + adjust if we wait on a deadline at all and how long. + +2014-12-22 15:00:36 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Don't count the number of times we need to wake up but instead check all conditions for waiting again + This simplifies the code and also makes sure that we don't forget to check all + conditions for waiting. + Also fix a potential deadlock caused by not checking if we're actually still + running before starting to wait. + +2014-12-17 19:51:32 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: Add function to allow subclasses to set their own latency + For audiomixer this is one blocksize, for videoaggregator this should + be the duration of one output frame. + +2014-12-17 17:54:09 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + aggregator: Add a timeout parameter to ::aggregate() + When this is TRUE, we really have to produce output. This happens + in live mixing mode when we have to output something for the current + time, no matter if we have enough input or not. + +2014-12-16 19:49:35 +0000 Tim-Philipp Müller + + * tests/check/libs/aggregator.c: + tests: fix aggregator unit test after property renaming + +2014-12-16 17:33:01 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Some minor cleanup + +2014-12-05 18:19:54 +1100 Matthew Waters + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: make the src pad task drive the pipeline for live pipelines + This removes the uses of GAsyncQueue and replaces it with explicit + GMutex, GCond and wakeup count which is used for the non-live case. + For live pipelines, the aggregator waits on the clock until either + data arrives on all sink pads or the expected output buffer time + arrives plus the timeout/latency at which time, the subclass + produces a buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=741146 + +2014-12-14 01:29:26 +0100 Sebastian Rasmussen + + * tests/check/libs/aggregator.c: + tests/aggregator: Use correct type when setting property + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=741495 + +2014-11-19 17:17:06 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Unblock events/queries immediately if the pad is flushing + https://bugzilla.gnome.org/show_bug.cgi?id=740376 + +2014-11-19 17:15:02 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Drop serialized events/queries if the pad is flushing + https://bugzilla.gnome.org/show_bug.cgi?id=740376 + +2014-11-19 17:03:41 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Block serialized events/queries until the pad has consumed all buffers + Otherwise the caps of the pad might change while the subclass still works with + a buffer of the old caps, assuming the the current pad caps apply to that + buffer. Which then leads to crashes and other nice effects. + https://bugzilla.gnome.org/show_bug.cgi?id=740376 + +2014-11-19 17:03:33 +0100 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Fix typo in debug output + +2014-11-17 14:00:10 +1100 Matthew Waters + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: add _get_latency() for subclass usage + API: gst_aggregator_get_latency + https://bugzilla.gnome.org/show_bug.cgi?id=739996 + +2014-10-20 18:25:08 +0530 Vineeth T M + + * libs/gst/base/gstaggregator.c: + audiomixer: critical error for blocksize, timeout min/max values + Audiomixer blocksize, cant be 0, hence adjusting the minimum value to 1 + timeout value of aggregator is defined with MAX of MAXINT64, + but it cannot cross G_MAXLONG * GST_SECOND - 1 + Hence changed the max value of the same + https://bugzilla.gnome.org/show_bug.cgi?id=738845 + +2014-10-07 16:57:27 +1100 Matthew Waters + + * tests/check/libs/aggregator.c: + tests/aggregator: add timeout handling test for the timeout parameter + +2014-10-06 21:46:24 +1100 Matthew Waters + + * libs/gst/base/gstaggregator.c: + aggregator: add latency query handling + +2014-10-06 18:23:03 +1100 Matthew Waters + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + aggregator: add a timeout property determining buffer wait time + Determines the amount of time that a pad will wait for a buffer before + being marked unresponsive. + Network sources may fail to produce buffers for an extended period of time, + currently causing the pipeline to stall possibly indefinitely, waiting for + these buffers to appear. + Subclasses should render unresponsive pads with either silence (audio), the + last (video) frame or what makes the most sense in the given context. + +2014-09-17 16:48:02 +0200 Jan Alexander Steffens (heftig) + + * libs/gst/base/gstaggregator.c: + aggregator: Replace GMainContext with GAsyncQueue (v2) + The previous implementation kept accumulating GSources, + slowing down the iteration and leaking memory. + Instead of trying to fix the main context flushing, replace + it with a GAsyncQueue which is simple to flush and has + less overhead. + https://bugzilla.gnome.org/show_bug.cgi?id=736782 + +2014-08-05 15:36:30 +0200 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: Set seqnum only when segments are received. + +2014-08-02 18:25:01 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Add a streaming lock so to secure flush start action + Without a lock that is taken in FLUSH_START we had a rare race where we + end up aggregating a buffer that was before the whole FLUSH_START/STOP + dance. That could lead to very wrong behaviour in subclasses. + +2014-07-18 13:58:55 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Query seeking when a seek failed to see if it was expected + And do not worry if seeking failed on a stream that is not seekable + +2014-07-18 01:41:26 +0200 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: set future seqnum before propagating the seek event. + So the seqnum is properly set for the following events. + +2014-07-08 16:16:55 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Store segment when seeked in READY for later use + +2014-10-06 10:11:23 +0300 Sebastian Dröge + + * libs/gst/base/gstaggregator.c: + aggregator: Unref the taglist in GstAggregator::stop() + +2014-10-03 12:34:15 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Take lock to ensure set_caps is not called concurently + Avoiding to be in an inconsistent state where we do not have + actual negotiate caps set as srccaps and leading to point where we + try to unref ->srccaps when they have already been set to NULL. + https://bugzilla.gnome.org/show_bug.cgi?id=735042 + +2014-08-11 23:38:40 +1000 Matthew Waters + + * libs/gst/base/gstaggregator.c: + aggregator: fix up doc comment for set_src_caps + It does not occur 'later' anymore + https://bugzilla.gnome.org/show_bug.cgi?id=732662 + +2014-08-07 19:54:36 +1000 Matthew Waters + + * libs/gst/base/gstaggregator.c: + videoaggregator: push the caps event as soon as we receive it + Along with the required mandatory dependent events. + Some elements need to perform an allocation query inside + ::negotiated_caps(). Without the caps event being sent prior, + downstream elements will be unable to answer and will return + an error. + https://bugzilla.gnome.org/show_bug.cgi?id=732662 + +2014-07-16 16:57:35 +0200 Mathieu Duponchelle + + * libs/gst/base/gstaggregator.c: + aggregator: Reset flow_return *after* stopping the srcpad task. + Otherwise it might be set in an already running aggregate function. + +2014-07-10 13:18:21 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Flush sinkpads when stopping + All values are meaningless in that case, so we should make sure that + we clean everything + +2014-07-10 13:15:55 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Do not forget to reset the flow return when stoping + Setting it to FLUSHING when the element is not started, and to OK + when it starts. + +2014-07-08 16:48:08 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Handle event seqnum + +2014-07-06 16:17:06 +0100 Tim-Philipp Müller + + * libs/gst/base/gstaggregator.c: + aggregator: fix locking + We would unlock a mutex we never locked on SEGMENT + events. + +2014-06-30 12:22:07 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + * tests/check/libs/aggregator.c: + aggregator: Avoid destroying sources we do not own + + Unref the maincontext in a new dispose function + + Make sure to remove all sources on dispose + https://bugzilla.gnome.org/show_bug.cgi?id=732445 + +2014-06-28 11:20:43 -0300 Thiago Santos + + * tests/check/libs/aggregator.c: + tests: aggregator: fix various leaks in the tests + +2014-06-28 09:34:05 -0300 Thiago Santos + + * libs/gst/base/gstaggregator.c: + aggregator: always store or unref the buffer on the _chain function + Otherwise it leaks, and it is very common to go to flushing when the + pipeline is stopping, leaking a buffer. + +2014-06-28 09:32:32 -0300 Thiago Santos + + * libs/gst/base/gstaggregator.c: + aggregator: always unref the buffer on _finish function + Otherwise the user doesn't know if it was unref'd or not + +2014-06-28 09:31:55 -0300 Thiago Santos + + * libs/gst/base/gstaggregator.c: + aggregator: add dispose/finalize functions + Add functions to be able to cleanup the mutex/cond and pending buffers + on the aggregator and on its pad + +2014-06-26 10:53:16 +1000 Matthew Waters + + * libs/gst/base/gstaggregator.c: + aggregator: plug a memory leak of the srccaps + +2014-06-21 16:51:01 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.h: + libs:base: Properly declare APIs as UNSTABLE + +2014-06-21 13:45:13 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + aggregator: Fix requested pad name + +2014-05-22 19:44:37 +0200 Thibault Saunier + + * libs/gst/base/gstaggregator.c: + * libs/gst/base/gstaggregator.h: + * tests/check/libs/aggregator.c: + aggregator: Add new GstAggregator base class + This base class has been added to a newly created libgstbadbase library + Co-Authored by: Mathieu Duponchelle + https://bugzilla.gnome.org/show_bug.cgi?id=731917 + +2017-12-02 12:02:15 +0000 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: info: add test for post-gst_init() category registration perf + When registering categories after gst_init() we would re-check *all* + categories against the existing GST_DEBUG patterns again, whereas + it's enough to just check the new category. Moreover, we would parse + the GST_DEBUG pattern string again and re-add that to the existing + pattern list for every newly-registered debug category, and then + check that against all categories of course. This made registering + categories after gst_init() very very slow. + +2017-12-02 12:29:20 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: always check match patterns for new debug categories + Not only if a match pattern was set originally via GST_DEBUG. + Patterns might be set programmatically as well after all. + +2017-12-02 12:22:47 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: fix performance issue with registering categories after gst_init() + When registering a new debug category after gst_init(), simply check + the existing patterns against that new category. + No need to iterate over all categories and recheck them all against + the existing patterns. + Also, no need to re-parse the existing pattern string set via GST_DEBUG + and add the same set of match patterns all over again to the existing + list of match patterns every time we register a new debug category. + Combined with iterating all debug categories on a change this would + make adding debug categories after gst_init() very very very slow. + +2017-12-01 13:33:48 -0500 Nicolas Dufresne + + * gst/gstplugin.c: + plugin-scanner: Measure string length in bytes + g_strndup() wants a number of bytes to copy, so use strlen intead of + UTF-8 strlen function. + +2017-11-30 17:49:10 +0100 Michael Tretter + + * libs/gst/net/gstptpclock.c: + ptpclock: do not require a name to create a clock + The gst_ptp_clock_new() does not actually require a name. However, for + example the rtpjitterbuffer may create a clock without a name, fail, and + fall back to not using the PTP clock. + https://bugzilla.gnome.org/show_bug.cgi?id=791034 + +2017-11-28 23:37:47 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: fix readable flag printing for pad properties + +2017-11-27 20:09:42 +1100 Matthew Waters + + * common: + Automatic update of common submodule + From 3f4aa96 to e8c7a71 + +2017-11-26 13:31:28 -0300 Thibault Saunier + + * gst/gstpreset.c: + Revert "preset: Do not save deprecated properties" + This reverts commit 81e10f61231ad56ca4aa07278993b87c6ec0f058. + A mistake lead to committing it twice in a weird way. + +2017-11-03 12:20:47 -0300 Thibault Saunier + + * gst/gstpreset.c: + preset: Do not save deprecated properties + It will g_warn upon deserialization and we should not use + those anyway. + https://bugzilla.gnome.org/show_bug.cgi?id=789871 + +2017-11-08 12:46:44 -0300 Thibault Saunier + + * gst/gsttaglist.c: + taglist: Avoid assertions when getting tag nick from unregister tag + With serialized GstDiscovererInfos we might end up trying to use + tags that have not been registered. + +2017-11-03 12:23:50 -0300 Thibault Saunier + + * gst/gstpreset.c: + preset: Do not save deprecated properties + It will g_warn upon desarialization and we should not use + those anyway. + https://bugzilla.gnome.org/show_bug.cgi?id=789871 + +2017-10-13 00:21:03 +0100 Tim-Philipp Müller + + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlog.c: + tracers: log: no need to link to our internal printf implementation + The call to __gst_vasprintf() was removed in commit 1a3e218b8. + +2017-11-26 00:20:13 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: don't print element flags whch are always 'none' + We print the interesting flags like clocking capabilities separately + later, this function just always prints 'none', so remove it. + +2017-11-25 23:43:56 +0000 Tim-Philipp Müller + + * gst/gstpadtemplate.c: + * tools/gst-inspect.c: + tools: gst-inspect: print pad properties where we know the subclass type + +2017-11-25 22:27:08 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: refactor way indentation is done during printing + +2017-11-25 13:07:12 +0100 Edward Hervey + + * gst/gstinfo.c: + gstinfo: Use free instead of g_free + Because + +2017-11-25 12:44:11 +0100 Edward Hervey + + * gst/gstinfo.c: + gstinfo: Don't leak array of strings + The array provided by backtrace_symbols needs to be freed. + +2017-11-24 12:08:07 +0100 Edward Hervey + + * tests/check/gst/gstbuffer.c: + check/buffer: Remove usless memcmp with empty size + 1) checking nothing against nothing is pointless + 2) memcmp needs to be provided non-NULL arguments + +2017-11-24 12:05:26 +0100 Edward Hervey + + * gst/gstutils.c: + gstutils: Fix linear regression comparision + The check for dropping precision was wrong when sxx and syy were negative. + if they are negative then "G_MAXINT64 - val" would always overflow + The check was meant to use G_MININT64 (like in the loop contained just + after). + +2017-11-24 13:58:01 +1100 Matthew Waters + + * libs/gst/check/Makefile.am: + check: add missing harness function to symbol export list + Fixes in user code: + undefined reference to `gst_harness_add_element_sink_pad' + Also reorder harness function list to be strictly in alphabetical order and + double check the list with: + awk '{ if ($1 !~ /#define/) if ($2 ~ /gst_harness_/) { print $2 }; if ($3 ~ /gst_harness_/) { print $3} }' libs/gst/check/gstharness.h | sort + +2017-11-24 13:41:20 +0100 Tim-Philipp Müller + + * tests/check/elements/capsfilter.c: + * tests/check/elements/dataurisrc.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/elements/queue2.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/elements/valve.c: + * tests/check/generic/sinks.c: + * tests/check/generic/states.c: + * tests/check/gst/gst.c: + * tests/check/gst/gstabi.c: + * tests/check/gst/gstatomicqueue.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstbufferpool.c: + * tests/check/gst/gstbus.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstcapsfeatures.c: + * tests/check/gst/gstchildproxy.c: + * tests/check/gst/gstclock.c: + * tests/check/gst/gstcontext.c: + * tests/check/gst/gstcontroller.c: + * tests/check/gst/gstcpp.cc: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstindex.c: + * tests/check/gst/gstinfo.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstparamspecs.c: + * tests/check/gst/gstplugin.c: + * tests/check/gst/gstpoll.c: + * tests/check/gst/gstpreset.c: + * tests/check/gst/gstprintf.c: + * tests/check/gst/gstpromise.c: + * tests/check/gst/gstprotection.c: + * tests/check/gst/gstquery.c: + * tests/check/gst/gstsegment.c: + * tests/check/gst/gststream.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/gst/gsttask.c: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + * tests/check/gst/gsttracerrecord.c: + * tests/check/gst/gsturi.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/adapter.c: + * tests/check/libs/gstharness.c: + * tests/check/libs/gstnetclientclock.c: + * tests/check/libs/gstnettimeprovider.c: + * tests/check/libs/gsttestclock.c: + tests: include config.h and don't include unix headers + In many cases the unistd.h includes weren't actually needed. + Preparation for making tests work on Windows with MSVC. + +2017-11-24 13:21:47 +0100 Tim-Philipp Müller + + * tests/check/libs/test_transform.c: + tests: add missing license header to test_transform.c + +2017-11-10 16:26:50 +0100 Mikhail Fludkov + + * configure.ac: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/Makefile.am: + gsttraceutils: actually disable tracing system hooks if configured + `./configure --disable-gst-tracer-hooks` didn't do anything, hooks were + always enabled regardless of the option. It works correctly in the + Meson build though. + +2017-10-26 12:09:07 +0200 Havard Graff + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: add gst_utils_dump_buffer() + Useful for debugging. + +2017-10-10 15:44:51 +0200 Håvard Graff + + * pkgconfig/meson.build: + meson.build: use join_paths() on prefix + So that "/" are correct on Windows and the paths in + the .pc files are like C:/some/where and not + C:\some\where. + +2017-11-24 09:49:27 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasetransform.c: + * libs/gst/net/gstptpclock.c: + libs: fix indentation + +2017-08-18 14:30:32 +0200 Stian Selnes + + * gst/gstpad.c: + * tests/check/gst/gstghostpad.c: + pad: gst_pad_activate_mode() always succeed if same mode + Checking that the pad is in the correct mode before the parent is + checked makes the call always succeed if the mode is ok. + This fixes a race with ghostpad where gst_pad_activate_mode() could + trigger a g_critical() if the ghostpad is unparented while the + proxypad is deactivating, for instance if the ghostpad is released. + More specifically, gst_ghost_pad_internal_activate_push_default()'s + call to gst_pad_activate_mode() would fail if ghostpad doesn't have a + parent. With this patch it will return true of mode is already + correct. + +2017-03-31 16:36:05 +0200 Havard Graff + + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstfunnel.h: + gstbasetranform: replace GST_BASE_TRANSFORM with GST_BASE_TRANSFORM_CAST + To avoid a global type-lock on chain etc. + +2017-11-24 09:53:41 +0100 Tim-Philipp Müller + + * gst/gstghostpad.c: + ghostpad: return TRUE if target pad was already set + The state is as it should be, so no reason to return + FALSE really, everything's good. + +2017-11-24 09:40:07 +0100 Tim-Philipp Müller + + * gst/gstghostpad.c: + ghostpad: access internal pad with lock held + +2017-03-30 09:17:08 +0200 Havard Graff + + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + ghostpad: fix race-condition while tearing down + An upstream query will take a ref on the internal proxypad, and can + hence end up owning the last reference to that pad, causing a crash. + +2013-03-23 13:44:51 +0100 Haakon Sporsheim + + * libs/gst/check/gstcheck.c: + check: Add test suite time elapsed output + +2017-11-23 15:28:39 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Only calculate level if we have valid levels + Doing calculations with GST_CLOCK_STIME_NONE would result in + completely bogus levels + +2017-11-23 13:56:51 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: allocate slightly larger than needed tables at startup + If we pre-allocate only *exactly* as many nodes as we need for the + core types, we are practically guaranteed a re-alloc when external + code like GstVideoTimeCode or GstEncodingProfile register their + own GstValue things. So allocate a bit more than strictly needed. + +2017-11-06 21:10:54 +0100 Mathieu Duponchelle + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + * win32/common/libgstreamer.def: + pad templates: Allow specifying GType + See https://bugzilla.gnome.org/show_bug.cgi?id=731301 + https://bugzilla.gnome.org/show_bug.cgi?id=789986 + +2017-11-22 15:59:39 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update for latest promise api changes + +2017-04-03 22:20:51 +1000 Matthew Waters + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gstpromise.c: + * gst/gstpromise.h: + * gst/meson.build: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstpromise.c: + * tests/check/meson.build: + * win32/common/libgstreamer.def: + gst: add a promise object + An object that can be waited on and asked for asynchronous values. + In much the same way as promise/futures in js/java/etc + A callback can be installed for when the promise changes state. + Original idea by + Jan Schmidt + With contributions from + Nirbheek Chauhan + Mathieu Duponchelle + https://bugzilla.gnome.org/show_bug.cgi?id=789843 + +2017-11-20 17:01:04 +0100 Edward Hervey + + * gst/gstregistrychunks.c: + registrychunks: Make sure we use aligned memory + This is in the same vein as for all other features. Some systems + might not allow unaligned read. + +2017-11-17 00:15:17 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: stop printing element state_change function + This is really not interesting at all, not sure why we print this. + +2017-11-17 00:14:35 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: fix double empty line after pad templates + +2017-11-16 10:47:46 +0100 Edward Hervey + + gstpad: Make pad (de)activation atomic + The following could happen previously: + * T1: calls gst_pad_set_active() + * T2: currently (de)activating it + * T1: gst_pad_set_active() returns, caller assumes that the pad has + completed the requested (de)activation ... whereas it is not + the case since the actual (de)activation in T2 might still be + going on. + To ensure atomicity of pad (de)activation, we use a internal + variable (and cond) to ensure only one thread at a time goes through + the actual (de)activation block + https://bugzilla.gnome.org/show_bug.cgi?id=790431 + +2017-11-16 08:26:12 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Make calls to GstPadActivateFunction MT-safe + checking whether we already were in the target GstPadMode was being + done too early and there was the risk that we *would* end up + (de)activating a pad more than once. + Instead, re-do the check for pad mode when entering the final pad + (de)activation block. + https://bugzilla.gnome.org/show_bug.cgi?id=790431 + +2017-11-10 12:07:28 -0500 Nicolas Dufresne + + * gst/gstparamspecs.c: + paramspec: Move condition check inside the g_return + It's mostly a debug check and crash avoidance, it's better to + keep all the condition inside the macro. + +2017-11-10 12:03:00 -0500 Nicolas Dufresne + + * gst/gstparamspecs.c: + paramspec: Add missing since for _spec_array() + +2017-11-10 14:10:31 +0100 Edward Hervey + + * plugins/elements/gstconcat.c: + concat: Handle single-pad use-cases + When EOS reaches concat, it will switch to the next candidate as its + activate pad. + The problem arises when there is only one sinkpad, the "active" pad + becomes NULL. This results in concat becoming unusable after it receives + a *single* EOS on its single sinkpad. + If we detect there is a single sinkpad and there is no current active pad: + * If we are waiting (from selected sink event/buffer), become the current + active pad. + * If there is a seek request, send it upstream. We don't switch the + active_sinkpad property at that point in time, since the seek could + fail. If the seek succeeds, the following SEGMENT (or STREAM_START) + will cause the pad_wait() to elect that pad as the new active one. + * Flush events get forwarded + https://bugzilla.gnome.org/show_bug.cgi?id=790167 + +2017-11-09 17:38:19 +0100 Edward Hervey + + * plugins/elements/gstconcat.c: + concat: Make QoS forward MT-safe + In the same way it's done for other event forwarding. + +2017-04-13 16:28:54 +0200 Guillaume Desmottes + + * plugins/tracers/gstlatency.c: + latency tracer: add timestamp to tracer records + Include the timestamp of the recorded log as in the 'stats' tracer. + This can be useful, for example, to plot a graph showing the latency + over time. + https://bugzilla.gnome.org/show_bug.cgi?id=781315 + +2017-11-04 11:45:54 +0100 Edward Hervey + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Fix overflow some more + Nothing guaranteed that off+size wouldn't exceed a 2**64 value. + Instead we reverse the operation and use a subtraction. + +2017-11-04 10:34:10 +0100 Edward Hervey + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Fix signed integer overflow + Make sure the whole calculation is done with 64bit unsigned values + (To be ready for people want to typefind exabyte files). + +2017-08-01 11:06:32 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * tests/check/gst/gstelement.c: + * win32/common/libgstreamer.def: + element: add gst_element_foreach_*pad() + Add convenience API that iterates over all pads, sink pads or + source pads and makes sure that the foreach function is called + exactly once for each pad. + This is a KISS implementation. It doesn't use GstIterator and + doesn't try to do clever things like resync if pads are added + or removed while the function is executing. We can still do that + in future if we think it's needed, but in practice it will + likely make absolutely no difference whatsoever, since these + things will have to be handled properly elsewhere by the element + anyway if they're important. + After all, it's always possible that a pad is added or removed + just after the iterator finishes iterating, but before the + function returns. + This is also a replacement for gst_aggregator_iterate_sink_pads(). + https://bugzilla.gnome.org/show_bug.cgi?id=785679 + +2017-10-27 14:58:28 +0200 Mathieu Duponchelle + + * plugins/tracers/gstleaks.c: + gstleaks.c: always log leaks listing + https://bugzilla.gnome.org/show_bug.cgi?id=789556 + +2017-11-01 12:27:31 +0200 Sebastian Dröge + + * libs/gst/net/meson.build: + net: Add new file to the meson.build + +2017-11-01 11:31:52 +0200 Sebastian Dröge + + * tests/misc/netclock-replay.c: + examples/netclock-replay: Fix build + +2017-10-30 10:49:06 +0100 Robert Rosengren + + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnetutils.c: + * libs/gst/net/gstnetutils.h: + netutils: Add util for setting socket DSCP + Util function for setting QoS DSCP added, to remove duplicated code in + netclientclock and nettimeprovider. Fix build error if missing IP_TOS. + https://bugzilla.gnome.org/show_bug.cgi?id=784737 + +2017-10-31 11:39:23 +0100 Edward Hervey + + * gst/gstvalue.h: + gstvalue: Cast GST_MAKE_FOURCC arguments + To make it explicit that we are dealing with uint32 targets + Avoids erroneous runtime error: left shift of negative value -1 + https://bugzilla.gnome.org/show_bug.cgi?id=789700 + +2017-10-11 11:08:12 -0400 Nicolas Dufresne + + * plugins/tracers/gstlatency.c: + latency-tracer: Exclude synchronization time + The goal of this tracer is to measure the processing latency between a + src and a sink. In push mode, the time was read after the chain function + have returned. As the amount of time we wait to get synched is reverse + to the amount of latency the source introduced, the result was quite + surprising. + This patch moves the latency calculation in the pre-push hook. When + there is no processing in a a pipeline (e.g. fakesrc ! fakesink), the + latency will now be 0 as it's supposed to. For pull mode, the code was + already correct. When GstBaseSink operate in pull mode, the processing + time is done durring the pull, so pull-post is the right hook. The + synchronization will happen after the pull has ended. Note that + GstBaseSink rarely operate in pull mode. + https://bugzilla.gnome.org/show_bug.cgi?id=788431 + +2017-10-27 09:53:06 +0200 Edward Hervey + + * gst/gstevent.c: + event: Don't allow invalid SELECT_STREAMS event creation + Asking to select no streams makes no sense and can create various + issues. + If one doesn't one any stream it should deactivate (or not use) the + element in question. + +2017-10-25 17:10:15 +0200 Edward Hervey + + * gst/gst.c: + gst: Fix build with option parsing disabled + +2017-10-20 17:28:11 +0200 Stefan Sauer + + * tests/check/gst/gstsegment.c: + segment: update the tests + Boy scout rule. Make is a little less painful to debug the tests by using + fail_unless_equals_{uint64,int64,float} where appropriate. Ideally the large + tests would be splitted to avoid guessing data dependencies. + +2017-10-20 16:15:01 +0200 Stefan Sauer + + * gst/gstsegment.h: + segment: clarify the segment docs for the duration + +2017-10-20 16:11:44 +0200 Stefan Sauer + + * gst/gstsegment.c: + Revert "segment: also intialize the duration" + This reverts commit f1baaae17557fa75a9bcd940b994597714be2f74. + +2017-10-20 14:30:42 +0200 Stefan Sauer + + * gst/gstsegment.c: + segment: also intialize the duration + If start and stop are set, calculate the duration and set it too. + +2017-10-20 13:02:35 +0200 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: print more details for typefind and tracer features + Print full details for typefind features. Print some of the available features + for tracers and add some todos for the ones we'd like to see. + +2017-10-20 11:16:46 +0200 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: reduce casting back and forth + Refactor the print_element_info() to take a GstPluginFeature. Reduces the need + to cast to and from GstElementFactory. + +2017-10-20 11:08:14 +0200 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: simplify the code for printing feature info + Rename print_element_features() to print_feature_info() and move the code that + handles the ElementFactory there. This simplifies the calling code and improves + readability. + Also don't leak the features for other factories. + +2017-06-02 16:27:29 +0200 Robert Rosengren + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Add possibility to set QoS DSCP value + https://bugzilla.gnome.org/show_bug.cgi?id=784737 + +2017-06-01 15:48:16 +0200 Robert Rosengren + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: Add possibility to set QoS DSCP value + https://bugzilla.gnome.org/show_bug.cgi?id=784737 + +2017-10-18 02:31:12 +1100 Jan Schmidt + + * gst/gstutils.c: + * gst/gstutils.h: + seqnum: Never return a seqnum of 0, reset GST_SEQNUM_INVALID + Various plugins use the value of '0' as an invalid seqnum value + (qtdemux for matching duplicated seek events, for example). Make + that behaviour explicit, create a GST_SEQNUM_INVALID value, + and ensure gst_util_seqnum_next never returns it. + +2017-10-16 16:06:37 +0530 Ashish Kumar + + * libs/gst/base/gstqueuearray.c: + queuearray: Fix for possible crashes due to null pointer dereferencing + https://bugzilla.gnome.org/show_bug.cgi?id=788838 + +2017-10-15 15:59:11 +0200 Stefan Sauer + + * libs/gst/base/gstcollectpads.c: + collectpads: mention the query function in the docs as well + +2017-10-06 21:59:03 +0200 Mathieu Duponchelle + + * gst/gstbuffer.c: + * tests/check/gst/gstmeta.c: + gstbuffer: fix meta removal in gst_buffer_foreach_meta + When updating the linked list, prev->next = next is correct + if prev is actually updated after being set to the head + of the list at the start. + https://bugzilla.gnome.org/show_bug.cgi?id=788617 + +2017-10-10 15:53:38 +0200 fengalin + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: Fix version for ref and unref functions + The functions were introduced in version 1.12.1, GstFlowCombiner was + introduced in 1.4. + https://bugzilla.gnome.org/show_bug.cgi?id=788778 + +2017-10-05 13:35:14 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: use new gst_buffer_list_calculate_size() utility function + +2017-10-05 10:24:24 +0530 Ashish Kumar + + * gst/gstdeviceprovider.c: + device-provider: gst_device_provider_unhide_provider() always fails + https://bugzilla.gnome.org/show_bug.cgi?id=788520 + +2017-10-04 14:16:46 +0200 Havard Graff + + * gst/meson.build: + * libs/gst/base/meson.build: + * libs/gst/controller/meson.build: + * libs/gst/net/meson.build: + * meson.build: + meson: remove vs_module_defs + The GST_EXPORT should handle it. + +2017-10-03 13:54:25 -0700 Reynaldo H. Verdejo Pinochet + + * libs/gst/base/gstbasetransform.h: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstntppacket.c: + * plugins/elements/gstidentity.c: + Use proper GtkDoc notation for NULL/FALSE/TRUE + +2017-10-02 17:59:17 +0200 Edward Hervey + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: iterate_sorted: Ensure sources are always returned last + For linked elements, the resulting gst_bin_iterate_sorted() will + properly return elements from sink to sources. + If we have some elements that are not linked, we *still* want to + ensure that we return: + * In priority any sinks + * Last of all any sources + * And in between any element which is neither source nor sink + For this to work, when looking for the next candidate element, + not only check the degree order, but if there are two candidates + with the same degree order, prefer the non-source one. + Amongst other things, this fixes the case where we activating a + bin containing unlinked sources and other elements. Without this + we could end up activating sources (which might start adding pads + to be linked) before other (to which those new source element pads + might be linked) are not activated + https://bugzilla.gnome.org/show_bug.cgi?id=788434 + +2017-10-02 14:11:19 -0400 Nicolas Dufresne + + * tests/check/elements/tee.c: + tee-test: Test a real use case + The real use case is when downstream didn't set a pool or + allocation params, in which case we expect the tee to not + create a pool or param from thin air. Dowstream setting + an pool with size=0 was in fact testing a downstream element + bug. The fact we handle that is accidental. + +2017-10-02 16:26:33 +0200 Stefan Sauer + + * plugins/elements/gsttee.c: + * tests/check/elements/tee.c: + tee: don't create a pool if none is needed + If the aggregated size is 0 and we create a pool, the pool would provide + buffers with no memory assigned. Handle that case and skip the pool. + This was the behaviour before cf803ea9f4e3fde92c1da86ecc47444035f7c0a7. + Add a test for this scenario. + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-10-02 13:35:52 -0400 Nicolas Dufresne + + * tests/check/elements/tee.c: + tee: Re-enabled alloc query + allow-not-linked test + In the unit test refactoring, the unlinked pad required to test + the different behaviour induced by "allow-not-linked" property + was removed. + Commit e364d7944ecbab86dea73c0ee3e639e766938d36 + Move all the code for this test in the proper function, and re-add + the missing unlinked pad. This makes the test useful again. + +2017-10-02 16:25:00 +0200 Stefan Sauer + + * tests/check/elements/tee.c: + tee: split the allocation query test + Split the large allocation_query test into seperate tests. Add a setup helper + to reduce code duplication. Fix the original test that used fail_unless instead + of ck_assert_int_eq and had it accidentially working. + +2017-10-02 16:22:00 +0200 Stefan Sauer + + * gst/gststructure.c: + structure: add a todo comment + Printing NULL is confusing when the type is e.g. a GArray that is not empty. + +2017-10-02 13:14:21 +0200 Stefan Sauer + + * gst/gstquery.c: + query: doc consistency + Mention that it is the 'buffer size', like we do elsewhere. + +2017-09-28 10:17:53 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: update exports file + +2017-09-27 20:29:06 +0200 Mathieu Duponchelle + + * gst/gst.c: + * gst/gstplugin.c: + gst: Modify behaviour of gst_get_main_executable_path + To actually return the path of the executable, not its + directory. + https://bugzilla.gnome.org/show_bug.cgi?id=788256 + +2017-09-26 21:51:53 +0200 Mathieu Duponchelle + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gst.h: + * win32/common/libgstreamer.def: + gst: API: gst_get_main_executable_path() + This is useful for plugins that need to inspect the + folder of the main executable in order to determine the + set of features they will expose, for example: + https://github.com/centricular/gstreamer-vst3 + https://bugzilla.gnome.org/show_bug.cgi?id=788214 + +2017-09-27 13:07:25 +0200 Mathieu Duponchelle + + * gst/gst.c: + gst: Do not try to determine executable path on iOS. + The method used relies on "libproc.h", which is only available + on OSX. + https://bugzilla.gnome.org/show_bug.cgi?id=788234 + +2017-09-27 13:01:13 +0200 Mathieu Duponchelle + + * gst/gst.c: + gst: Fix typo in windows function name. + GetModuleFilename -> GetModuleFileName + https://bugzilla.gnome.org/show_bug.cgi?id=788234 + +2017-09-27 10:06:12 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update export file + +2017-09-26 15:15:27 +0200 Mathieu Duponchelle + + * gst/gst.c: + * libs/gst/helpers/gst-plugin-scanner.c: + plugin dependencies: fix 6cddce7663cb4b6ee061950d20365f42cb755851 + There were a few errors: + * The plugin scanner now accepts executable path as an argument. + In case it is NULL, argc == 2 + * We find the executable path in init_pre instead of gst_init, + allowing this to work when gst is initialized through the + option group (eg gst-inspect) + * There was a semi-colon missing in the __APPLE__ #ifdef + +2017-09-25 20:35:59 +0200 Mathieu Duponchelle + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginloader.c: + * libs/gst/helpers/gst-plugin-scanner.c: + * win32/common/libgstreamer.def: + plugin: API: GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE + When a plugin declares a dependency using this flag, all the + relative paths are considered to be relative to the path of + the main executable. + We try to determine the path of the executable portably, + with implementations provided for Linux, Windows and Mac. + If retrieval of the path fails, we will not detect changes. + In order for the main executable path to be the same when + scanning a plugin in a child process, a new variable is + exposed in gst_private.h, _gst_executable_path + https://bugzilla.gnome.org/show_bug.cgi?id=788152 + +2017-09-21 14:13:47 +0300 Vivia Nikolaidou + + * scripts/git-update.sh: + git-update: Also build $EXTRA_MODULES + Doing a git pull but not autogen.sh / make is not consistent behaviour. + https://bugzilla.gnome.org/show_bug.cgi?id=787981 + +2017-09-19 23:58:26 +0200 Mathieu Duponchelle + + * tools/gst-inspect.c: + gst-inspect: Print GstValueArray properties nicely + https://bugzilla.gnome.org/show_bug.cgi?id=787924 + +2017-04-01 07:15:22 +0200 Mathieu Duponchelle + + * plugins/elements/gstmultiqueue.c: + Multiqueue: don't allow dropping SEGMENT_DONE events + https://bugzilla.gnome.org/show_bug.cgi?id=780795 + +2017-09-17 18:55:19 +0300 Sebastian Dröge + + * gst/gstinfo.h: + info: GstStackTraceFlags were added in 1.12 + +2017-08-31 13:05:57 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + plugins: use new gst_buffer_list_calculate_size() + +2017-08-31 12:54:55 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: add gst_buffer_list_calculate_size() + Returns size in bytes. + +2017-08-30 13:50:33 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: add gst_buffer_list_get_writable() + Ensures buffer is writable. Useful if we want to change + metadata on it such as timestamps. + https://bugzilla.gnome.org/show_bug.cgi?id=750241 + +2017-09-12 18:30:00 +0300 Michael Shigorin + + * gst/gstconfig.h.in: + gstconfig.h.in: initial e2k arch support + This makes gstreamer buildable on Elbrus 2000. + https://bugzilla.gnome.org/show_bug.cgi?id=787587 + +2017-09-09 16:14:05 +0300 Sebastian Dröge + + * gst/gstinfo.h: + info: GstDebugColorFlags are flags, not an enum + Annotate as such. + +2017-09-06 10:01:58 -0400 Nicolas Dufresne + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: Add a drop-allocation property + When enabled, this property will make the allocation query fail. This is + the same as one could have done using a tee before the tee started + implementing the allocation query. + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-09-05 15:57:51 -0400 Nicolas Dufresne + + * plugins/elements/gsttee.c: + * tests/check/elements/tee.c: + tee: Allocate one more buffer when multi-plexing + This extra buffer ensure that the downstream threads are not starved + when multiplexing a stream. + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-09-05 15:45:33 -0400 Nicolas Dufresne + + * tests/check/elements/tee.c: + tee: Add test for the allocation query + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-08-08 17:39:43 -0400 Nicolas Dufresne + + * plugins/elements/gsttee.c: + tee: Implement allocation query aggregation + This will aggregate allocation params, pool and will keep all + meta that has no parameters. + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-08-08 17:35:19 -0400 Nicolas Dufresne + + * plugins/elements/gsttee.c: + tee: Deprecate alloc-pad property + It has no effect, not implemented, and would lead to bad rendering. + https://bugzilla.gnome.org/show_bug.cgi?id=730758 + +2017-09-04 12:20:43 +0200 Miguel París + + * tests/check/gst/gstpad.c: + pad: add test to check handled and drop probes + https://bugzilla.gnome.org/show_bug.cgi?id=787243 + +2017-09-04 14:33:29 +0200 Edward Hervey + + * gst/gstpad.c: + pad: Don't call remaining probes after they return DROPPED|HANDLED + If multiple probes are set on a pad and one probe returns either + GST_PAD_PROBE_HANDLED or GST_PAD_PROBE_DROPPED we need to stop + calling the remaining probes. + https://bugzilla.gnome.org/show_bug.cgi?id=787243 + +2017-08-26 13:44:38 -0300 Thibault Saunier + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Handle serializing NULL GValueArray + Concider them as an empty array and do not segfault... + https://bugzilla.gnome.org/show_bug.cgi?id=786670 + +2017-08-24 16:00:42 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix taglist update spam + We would constantly re-post the taglist because + posted_avg_rate only gets set to avg_bitrate if + parse->priv->post_avg_bitrate is true, so if it's + false the posted rate will always differ from the + current average rate and we'd queue an update, + which leads to us spamming downstream and the + application with taglist updates. + Fix this by only queuing an update if the average + rate will actually be posted. + These taglists updates could cause expensive + operations on the application side, e.g. in Totem. + https://bugzilla.gnome.org/show_bug.cgi?id=786561 + +2017-08-17 12:23:10 +0100 Tim-Philipp Müller + + * README: + * common: + Automatic update of common submodule + From 48a5d85 to 3f4aa96 + +2017-08-17 14:13:39 +0300 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstdeviceprovider.c: + * gst/gstdeviceprovider.h: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element/deviceprovider: Add instance getter functions for class properties + That is, the metadata and pad templates. Using instance getters is + easier to deal with for bindings, especially autogenerated ones. + +2017-08-16 22:47:31 +0300 Sebastian Dröge + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: Return FLUSHING instead of EOS and don't start waiting for anything if currently flushing + Otherwise we might try unscheduling a clock id (that does not exist + yet), then the streaming thread waits for id and the state change never + continues because the streaming thread is blocked. + Also shutting down and flushing and similar should return FLUSHING, not + EOS. The stream is not over, we're just not accepting any buffers + anymore. + +2017-08-14 11:01:19 +0100 Tim-Philipp Müller + + * gst/gstallocator.c: + * win32/common/libgstreamer.def: + allocator: Hide private sysmem GType func + Was never exposed in any header file, only exported + by accident. + +2017-08-11 21:17:06 +0200 Carlos Rafael Giani + + * configure.ac: + configure: Add switches for enabling/disabling libdw and libunwind + https://bugzilla.gnome.org/show_bug.cgi?id=778193 + +2017-08-13 10:50:05 +0100 Tim-Philipp Müller + + * libs/gst/check/libcheck/libcompat/libcompat.h: + libcheck: fix build failure + Need to define CK_DLL_EXP to extern as well in libcompat.h + which gets included before the internal-check.h where the + other fallback definition for CK_DLL_EXP is. + duplicate symbol _check_minor_version in: + libcheckinternal.a(libcheckinternal_la-check.o) + libcheckinternal.a(libcheckinternal_la-check_log.o) + +2017-08-11 11:12:09 +0300 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Allow re-usability after EOS + After EOS, it is possible for a pad to be resetted by sending + either a STREAM_START or SEGMENT event + Mimic the same behaviour when receiving STREAM_START/SEGMENT events + in queue if we are EOS'd + https://bugzilla.gnome.org/show_bug.cgi?id=786056 + +2017-08-10 13:32:43 +0100 Tim-Philipp Müller + + * libs/gst/check/libcheck/meson.build: + * meson.build: + meson: hide symbols by default unless explicitly exported + +2017-08-10 11:15:26 +0100 Tim-Philipp Müller + + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstcheck.h: + * libs/gst/check/gstconsistencychecker.h: + * libs/gst/check/gstharness.h: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * libs/gst/check/libcheck/check.h.in: + libs: check: sprinkle some GST_EXPORT + Have to modify libcheck header a bit to avoid warnings + about duplicate 'extern extern'. + Also needs some additions to the libcheck meson.build file + to define CK_EXP_DLL when building the static libcheck. + +2017-08-08 12:56:24 +0100 Tim-Philipp Müller + + * gst/gstutils.c: + utils: fix g-ir-scanner warning about bogus transfer annotations + for vararg parameters. Vararg functions are not introspectable anyway, + so might just as well mark them as '(skip)' while we're at it. + gstutils.c:2611: Warning: Gst: invalid "transfer" annotation for : only valid for object and GVariant types + +2017-08-09 16:15:23 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Allow re-usability after EOS + After EOS, it is possible for a pad to be resetted by sending + either a STREAM_START or SEGMENT event + Mimic the same behaviour when receiving STREAM_START/SEGMENT events + in queue2 if we are EOS'd + https://bugzilla.gnome.org/show_bug.cgi?id=786056 + +2017-08-09 10:51:39 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + plugins: *queue* elements: Handle STREAM_START in EOS situation + When queue-like elements are in "EOS" situation (received GST_FLOW_EOS + from downstream or EOS was pushed), they drain buffers/events that + wouldn't be processed anyway and let through events that might + modify the EOS situation. + Previously only GST_EVENT_EOS and GST_EVENT_SEGMENT events were let + through, but we also need to allow GST_EVENT_STREAM_START to go + through since it resets the EOS state of pads since 1.6 + https://bugzilla.gnome.org/show_bug.cgi?id=786034 + +2017-08-08 21:19:32 +0300 Sebastian Dröge + + * gst/gstutils.c: + utils: Skip gst_calculate_linear_regression() in bindings + +2017-08-07 12:24:37 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Handle buffering levels on NOT_LINKED + When downstream returns NOT_LINKED, we return the buffering level + as being 100%. + Since the queue is no longer being consumed/used downstream, we + want applications to essentially "ignore" this queue for buffering + purposes. + If other streams are still being used, those stream buffering levels + will be used. If none are used, upstream will post an error message + on the bus indicating no streams are used. + https://bugzilla.gnome.org/show_bug.cgi?id=785799 + +2017-08-07 11:23:36 +0100 Tim-Philipp Müller + + * docs/gst/meson.build: + * docs/libs/meson.build: + meson: fix gtk-doc invocation + Argument is called "scanobjs_args", and we were missing a quote. + +2017-08-07 11:06:58 +0100 Tim-Philipp Müller + + * gst/meson.build: + * meson.build: + meson: fix a few warnings + +2017-08-07 10:33:32 +0100 Tim-Philipp Müller + + * pkgconfig/meson.build: + meson: add -lm to gstreamer-check-1.0 pkgconfig file + Fixes warning with meson from git about LIBM not being + defined in the configuration_data. + +2017-08-02 21:02:32 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Recheck sticky events after non-blocking buffer probes and blocking event probes + Without the former, event changes (e.g. setting a pad offset) does not + take effect for the current buffer but only for the next one. Without + the latter, non-blocking event probes would not see any updated events + yet. + +2017-07-29 10:28:03 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: fix build with gst debugging disabled + +2017-07-17 21:03:11 +0300 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + * win32/common/libgstreamer.def: + debug: Add a memory ringbuffer based debug logger + This stores debug logs in memory per thread and uses up to a + configurable amount of bytes per thread for the logs. Inactive threads + are timed out after a configurable amount of time. + https://bugzilla.gnome.org/show_bug.cgi?id=785035 + +2017-07-28 17:27:18 +0100 Sebastian Dröge + + * gst/gstsegment.c: + segment: Add missing out annotations for various parameters + +2017-07-26 14:17:46 +0100 Tim-Philipp Müller + + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstdownloadbuffer.h: + downloadbuffer: remove unused struct member + This was used in queue2 when handling in coming serialized + queries, but downloadbuffer just refuses serialized queries. + +2015-03-10 16:42:44 +0000 Luis de Bethencourt + + * libs/gst/check/libcheck/check_run.c: + check: duplicate code branches + CID #1226446 + +2017-07-26 11:15:58 +0300 George Kiagiadakis + + * gst/gstelement.c: + element: document that gst_element_continue_state needs to be called with the STATE_LOCK + It internally calls gst_element_change_state(), which requires the STATE_LOCK + https://bugzilla.gnome.org/show_bug.cgi?id=785431 + +2017-07-20 17:31:41 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: fix compiler warnings for SIGHUP handlers on windows + Fix unused variable/function compiler warnings on windows. + The SIGHUP handling is only available under unix. + https://bugzilla.gnome.org/show_bug.cgi?id=783661 + +2017-07-20 14:17:48 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix access to NULL pointer + sq can be NULL. + Also fix commit message (it's the queue we are iterating over that we + are logging, not the one passed as argument). + CID #1415569 + +2017-07-03 15:17:33 +0900 Seungha Yang + + * plugins/elements/gstmultiqueue.c: + multiqueue: Calculate interleave only within each streaming thread + ... and use the biggest interleave value among streaming threads. + This is to optimize multiqueue size adaptation on adaptive streaming + use case with "use-interleave" property. + https://bugzilla.gnome.org/show_bug.cgi?id=784448 + +2017-07-15 12:40:28 +0100 Tim-Philipp Müller + + * po/meson.build: + meson: po: use glib preset and read language list from LINGUAS + Supported since meson 0.37, so we can use it now. + +2017-07-15 11:54:18 +0100 Tim-Philipp Müller + + * gst/gstminiobject.c: + miniobject: don't modify memory if it's clearly not a valid miniobject + Add back function guard that checks the refcount in a read-only + operation first, and bail out without modifying the passed-in + memory if it's clearly not a valid mini object. Otherwise we + probably cause more harm than good. We keep the second sanity + check based on the 'real refcount' at the time of the unref + around for now too. + https://bugzilla.gnome.org/show_bug.cgi?id=784383 + +2017-07-14 16:56:54 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: deprecate non-functional "typefind" property + https://bugzilla.gnome.org/show_bug.cgi?id=736565 + +2017-07-10 16:52:38 +0200 Francisco Velazquez + + * tests/benchmarks/complexity.c: + * tests/benchmarks/complexity.scm: + benchmark: fix complexity benchmark + Make complexity benchmark code work for complexity > 1 + https://bugzilla.gnome.org/show_bug.cgi?id=784754 + +2017-07-14 16:12:25 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/gstpluginloader.c: + * meson.build: + win32: find plugin scanner in libexecdir subdir as configured + https://bugzilla.gnome.org/show_bug.cgi?id=679115 + +2017-07-13 21:52:34 +0800 Jason Lin + + * libs/gst/base/gstbasesink.c: + basesink: fix buffer leaks if preroll failed + buffer is not unreferened if preroll failed + :Detailed Notes: + - Problem : video freeze when switching from pause to 1/2-FF repeatedly + - RootCause : buffer leaks in basesink + - Solution : unref the buffer if prerolled failed + :Testing Preformed: + How to Test : + pause -> 1/2 FF -> resume -> pause -> 1/2 FF ... + https://bugzilla.gnome.org/show_bug.cgi?id=784932 + +2017-06-11 15:15:13 +0000 Graham Leggett + + * docs/gst/running.xml: + * tools/gst-launch-1.0.1: + * tools/gst-launch.c: + Generate a gstreamer pipeline diagram on SIGHUP. + Useful for debugging a pipeline that refuses to enter a given state. + https://bugzilla.gnome.org/show_bug.cgi?id=783661 + +2017-06-26 11:46:39 +0300 George Kiagiadakis + + * libs/gst/base/gstbasesrc.c: + basesrc: forward SINK_MESSAGE events downstream + https://bugzilla.gnome.org/show_bug.cgi?id=784551 + +2017-07-11 14:56:03 -0400 Nicolas Dufresne + + * meson.build: + meson: Fix bashcomp installation + For some reason the double quotes ended up in the path, hence + the helper where installed at "."/share/... + +2017-07-11 14:55:42 -0400 Nicolas Dufresne + + * data/bash-completion/helpers/meson.build: + * meson.build: + * plugins/elements/meson.build: + meson: Use join_paths and .set_quoted where possible + +2017-07-11 16:15:16 +0100 Tim-Philipp Müller + + * pkgconfig/meson.build: + meson: pkgconfig: add libunwind/libdw to gstreamer-1.0 Requires.private + https://bugzilla.gnome.org/show_bug.cgi?id=784795 + +2017-07-11 15:29:44 +0200 Edward Hervey + + * configure.ac: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + pkgconfig: Add private requirements + Add libunwind and dw to the .pc Requires.private. Fixes static library + compilation if gstreamer was compiled with one of those dependencies + https://bugzilla.gnome.org/show_bug.cgi?id=784795 + +2017-07-09 21:20:03 +0200 Stefan Sauer + + * libs/gst/base/gstbasesink.c: + basesink: use GST_CLOCK_TIME macros for readability + Replace some -1 comparison with GST_CLOCK_TIME macros. + +2017-07-09 21:16:44 +0200 Stefan Sauer + + * libs/gst/base/gstcollectpads.c: + collectpads: correct some comments and add more logging + Add more logging to analyze event handling (especially failure cases). + +2017-05-01 13:35:09 -0700 Scott D Phillips + + * tools/gst-stats.c: + tools: gst-stats: Use standard character escapes + Having '\e' expand to '\x1b' is a gnu extension. I didn't see any + document describing the behavior, but gcc also seems to expand + '\[' to '['. + https://bugzilla.gnome.org/show_bug.cgi?id=782028 + +2017-07-07 12:06:44 +0100 Tim-Philipp Müller + + * gst/parse/meson.build: + * meson.build: + meson: find python3 via python3 module + And rename python3 variable in meson build files for clarity. + https://bugzilla.gnome.org/show_bug.cgi?id=783198 + +2017-07-05 13:20:19 +0100 Tim-Philipp Müller + + * gst/meson.build: + * meson_options.txt: + * plugins/meson.build: + * tests/check/meson.build: + meson: add option to disable tracer hooks + +2017-07-05 13:19:00 +0100 Tim-Philipp Müller + + * tests/check/gst/gstmemory.c: + tests: memory: skip test that depends on debug system if it's disabled + +2017-07-05 13:17:49 +0100 Tim-Philipp Müller + + * gst/gsttracerutils.h: + tracing: fix build with tracer hooks disabled + +2017-07-03 09:03:24 +0100 Tim-Philipp Müller + + * gst/gstminiobject.c: + miniobject: make refcount tracing and debug logging reliable + Tracing of the refcounts wasn't thread-safe, and log output of + the refcount values before/after wasn't reliable. + https://bugzilla.gnome.org/show_bug.cgi?id=784383 + +2017-07-03 21:06:24 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: clarify code that deduces plugin name from file name + Make the final else branch explicit for clarity. + https://bugzilla.gnome.org/show_bug.cgi?id=783333 + +2017-06-27 07:44:17 +0200 Stefan Sauer + + * libs/gst/base/gstbytereader-docs.h: + docs: add a missing const in bytereader docs + This syncs the prototype with gstbytereader.h + +2017-06-29 10:50:50 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Removed unused private member qos_enabled + +2017-06-26 14:09:20 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't reallocate buffers when flushing + Instead of using gst_buffer_pool_set_active() when flushing, use + gst_buffer_pool_set_flushing(), this avoids uneeded reallocation of the + buffers. + +2017-06-01 10:36:26 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't hold LIVE_LOCK in create/alloc/fill + Holding this lock on live source prevents the source from changing + the caps in ::create() without risking a deadlock. This has consequences + as the LIVE_LOCK was replacing the STREAM_LOCK in many situation. As a + side effect: + - We no longer need to unlock when doing play/pause as the LIVE_LOCK + isn't held. We then let the create() call finish, but will block if + the state have changed meanwhile. This has the benefit that + wait_preroll() calls in subclass is no longer needed. + - We no longer need to change the state to unlock, simplifying the + set_flushing() interface + - We need different handling for EOS depending if we are in push or pull + mode. + This patch also document the locking of each private class member and + the locking order. + https://bugzilla.gnome.org/show_bug.cgi?id=783301 + +2017-06-01 10:01:13 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Protect access to pool and allocator + This was only partly protected by the object lock. Always take the + object lock to access the currently configured pool and allocator. + https://bugzilla.gnome.org/show_bug.cgi?id=783301 + +2017-06-29 08:30:50 +0900 Jimmy Ohn + + * tools/gst-inspect.c: + gst-inspect: Fix memory leak in print_pad_templates_info + gst_static_caps_get function returned allocated memory. + So, It should be free using gst_caps_unref. + https://bugzilla.gnome.org/show_bug.cgi?id=784311 + +2017-06-29 09:10:04 +0100 Tim-Philipp Müller + + * meson.build: + meson: check for ppoll() as well + +2017-06-27 09:59:52 -0400 Thibault Saunier + + * tools/meson.build: + meson: Add configinc as include_directory in tools/ + Otherwise when the glib is used as a subproject config.h is the glib + one, not ours. + +2017-06-23 15:13:16 -0400 Thibault Saunier + + * meson.build: + meson: Allow using glib as a subproject + +2017-06-28 09:54:56 +0200 Xabier Rodriguez Calvar + + * docs/gst/gstreamer-sections.txt: + * gst/gstprotection.c: + * gst/gstprotection.h: + * win32/common/libgstreamer.def: + protection: add function to filter system ids + gst_protection_filter_systems_by_available_decryptors() takes an array + of strings and returns a new array of strings filtered by the available + decryptors for them so the ones you get are the ones that you should be + able to decrypt. + https://bugzilla.gnome.org/show_bug.cgi?id=770107 + +2017-06-23 11:11:44 +0100 Tim-Philipp Müller + + * meson.build: + meson: fix with-package-name option + https://bugzilla.gnome.org/show_bug.cgi?id=784082 + +2017-06-02 00:52:37 +0200 Matej Knopp + + * gst/gstplugin.c: + gstplugin: remove gst prefix when loading plugin on MSVC + When building with Meson and MSVC, our plugins don't have a 'libgst' + suffix and are just 'gstfoo.dll', so look for that too. + https://bugzilla.gnome.org/show_bug.cgi?id=783333 + +2017-06-21 10:48:52 -0400 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: sinkcaps can be NULL in default caps negotiation + This was causing harmless assertion about the unreffed caps not being of + type caps. + https://bugzilla.gnome.org/show_bug.cgi?id=784041 + +2017-06-20 11:05:41 -0400 Thibault Saunier + + * win32/common/libgstreamer.def: + win32: Update .def file + +2017-06-14 17:12:32 -0400 Thibault Saunier + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + utils: Add a function to get a string representation of GstStateChange + API: + gst_state_change_get_name + https://bugzilla.gnome.org/show_bug.cgi?id=783798 + +2017-06-15 10:38:29 -0400 Thibault Saunier + + * gst/gstelement.h: + * gst/gstpipeline.c: + element: Add missing values for "to same" state changes + And handle newly added GstStateChange values in GstPipeline + https://bugzilla.gnome.org/show_bug.cgi?id=783798 + +2017-06-20 15:57:47 +0900 Heekyoung Seo + + * gst/gstutils.c: + utils: Fix leak in failed case of regression overflow checking + https://bugzilla.gnome.org/show_bug.cgi?id=783978 + +2017-06-20 16:10:07 +0900 Heekyoung Seo + + * gst/gstregistrychunks.c: + registrychunk: Fix leak in failed case of reading plugin dependency string + https://bugzilla.gnome.org/show_bug.cgi?id=783978 + +2017-06-20 10:00:16 +0300 Sebastian Dröge + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * win32/common/libgstcontroller.def: + controller: Export boxed type copy/free functions for GstControlPoint + +2017-06-20 09:57:01 +0300 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + * win32/common/libgstbase.def: + base: Export boxed type copy/free functions for the remaining types + +2017-06-16 13:34:00 +0000 Andrejs Vasiljevs + + * libs/gst/net/gstptpclock.c: + ptp: Unref timeout GSource for delay requests + https://bugzilla.gnome.org/show_bug.cgi?id=783864 + +2017-06-15 10:51:50 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + * gst/gsturi.h: + * tests/check/gst/gsturi.c: + * tests/check/meson.build: + meson: fix tests build with --werror + Need to pass -DGST_DISABLE_DEPRECATED to avoid warnings when + testing deprecated API such as gst_uri_construct(). + Also remove #ifndef GST_DISABLE_DEPRECATED guard from header + file, we don't use those any more for functions, the + GST_DEPRECATED_FOR macro is enough. + +2017-06-14 17:36:57 +0200 Dimitrios Katsaros + + * gst/gsturi.c: + * gst/gsturi.h: + * tests/check/gst/gsturi.c: + gsturi: Fixed incorrect escaping of path as a generic string + The gst_uri_construct function was escaping the location string + as a generic uri string. This is incorrect since the slash('/') + characters are reserved for use in this exact case. The patch + changes the escape_string function mode to handle the path correctly. + I have deleted the escape_string function since it is no longer being + used and have created a unit test for the function. I have also + deprecated this function in favour of the GstUri API. + https://bugzilla.gnome.org/show_bug.cgi?id=783787 + +2017-06-07 11:42:28 -0400 Thibault Saunier + + * tests/check/meson.build: + meson: Do not use path separator in test names + Avoiding warnings like: + WARNING: Target "elements/audioamplify" has a path separator in its name. + +2017-05-31 20:40:00 +0300 Sebastian Dröge + + * gst/gstbin.c: + bin: Put correct annotations on gst_bin_add() too + +2017-05-23 00:51:12 +0200 Olivier Crête + + * libs/gst/base/gstbasesrc.c: + basesrc: Hold object lock while updating latency + Otherwise in gst_base_src_query_latency(), it ended up + sometimes thinking it wasn't -1 when it was actually. + +2017-05-22 12:01:41 +0300 Sebastian Dröge + + * gst/gstobject.c: + object: Add missing annotations to get_value_array() / get_value_g_array() + Same as already used in GstControlBinding. + +2017-05-21 18:11:36 +0100 Tim-Philipp Müller + + * config.h.meson: + meson: actually remove config.h.meson as well + +2017-05-21 19:16:57 +0300 Sebastian Dröge + + * gst/gstprotection.c: + protection: Fix annotations for gst_protection_select_system() + +2017-05-21 17:04:10 +0200 Olivier Crête + + * gst/gstplugin.c: + plugin: Stop plugin symbol name at first . + This is because the python plugin ends up named + libgstpython.cpython-35m-x86_64-linux-gnu.so so we need to stop + at the first dot. + https://bugzilla.gnome.org/show_bug.cgi?id=782924 + +2017-05-21 14:26:01 +0100 Tim-Philipp Müller + + * Makefile.am: + * gst/meson.build: + * meson.build: + meson: don't need config.h.meson any more + Meson does the largefile support automatically nowadays, and + can generate a config.h from configuration_data() without a + template as input. + +2017-05-21 09:02:54 +0100 Tim-Philipp Müller + + * common: + * meson.build: + * tests/check/meson.build: + meson: make C++ compiler optional + It's only used to build tests to see if our headers are C++ clean. + +2017-05-20 17:57:39 +0100 Tim-Philipp Müller + + * libs/gst/check/meson.build: + meson: check: generate .gir file + https://bugzilla.gnome.org/show_bug.cgi?id=782173 + +2017-05-20 19:42:51 +0300 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstparse.c: + * gst/gstparse.h: + * win32/common/libgstreamer.def: + parse: Make gst_parse_context_copy() public for bindings + +2017-05-20 16:44:14 +0100 Tim-Philipp Müller + + * tools/Makefile.am: + tools: dist new gst-stats man page + Fixes meson build from tarball. + +2017-05-20 16:43:39 +0100 Tim-Philipp Müller + + * libs/gst/helpers/Makefile.am: + Dist meson ptp helper install script + Fixes meson build from tarball. + +2017-05-20 13:24:18 +0200 Thibault Saunier + + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks: Handle subclasses in filters even for unhandled/lazy loaded types + Using typename in the set of unhandled types instead of the quark so + that we also handle subclasses as with other filters. + +2017-05-19 19:22:27 +0200 Matthew Waters + + * gst/gstdebugutils.c: + debugutils: add missing E character to the legend + The E character on pads indicates the presence of the EOS flag. + +2017-05-17 21:50:25 +0200 Matej Knopp + + * gst/gstplugin.c: + gst-plugin: allow '-' in plugin file name + '-' will be translated to underscore when determining symbol name + https://bugzilla.gnome.org/show_bug.cgi?id=782756 + +2016-06-20 15:58:59 +0200 Christoph Reiter + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstclock.c: + * tests/check/gst/gstsystemclock.c: + gst: ref_sink() some more floating references returned by g_object_new() + https://bugzilla.gnome.org/show_bug.cgi?id=743062 + +2017-05-15 18:58:38 +0300 Sebastian Dröge + + * gst/gstbufferpool.c: + * gst/gstdevicemonitor.c: + * gst/gststreamcollection.c: + * gst/gststreams.c: + * gst/gsttracerrecord.c: + * gst/gsttracerutils.c: + * libs/gst/net/gstnettimeprovider.c: + gst: Clear floating flag in constructor of all GstObject subclasses that are not owned by any parent + I.e. most of them unfortunately. + https://bugzilla.gnome.org/show_bug.cgi?id=743062 + +2017-05-15 14:34:57 +0300 Sebastian Dröge + + * gst/gstallocator.c: + allocator: ref_sink() the global sysmem allocator after creation + It's not owned by the first one to ask for it, but by this very code. + https://bugzilla.gnome.org/show_bug.cgi?id=743062 + +2017-05-15 14:32:48 +0300 Sebastian Dröge + + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstcontrolsource.c: + * gst/gstsystemclock.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/check/gsttestclock.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstptpclock.c: + * tests/check/gst/gstcontroller.c: + gst: Don't ref_sink() GstObject subclasses in instance_init/constructor + This is something bindings can't handle and it causes leaks. Instead + move the ref_sink() to the explicit, new() constructors. + This means that abstract classes, and anything that can have subclasses, + will have to do ref_sink() in their new() function now. Specifically + this affects GstClock and GstControlSource. + https://bugzilla.gnome.org/show_bug.cgi?id=743062 + +2017-05-15 14:32:00 +0300 Sebastian Dröge + + * gst/gstdevicemonitor.c: + * gst/gstdeviceprovider.c: + * gst/gstelement.c: + * gst/gstghostpad.c: + * gst/gstobject.c: + * gst/gstpadtemplate.c: + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gststreamcollection.c: + * gst/gststreams.c: + * gst/gsttracerrecord.c: + * gst/gstutils.c: + * libs/gst/controller/gstproxycontrolbinding.c: + * libs/gst/net/gstnettimeprovider.c: + gst: Correctly annotate functions taking floating reference parameters and returning floating references + https://bugzilla.gnome.org/show_bug.cgi?id=702960 + +2017-05-15 14:29:05 +0300 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstghostpad.c: + * gst/gstregistry.c: + * gst/gstutils.c: + gst: Handle floating references consistently + If a function takes a floating reference parameter, it should also be + sinked in error cases. Otherwise the function behaves differently + between error and normal cases, which is impossible for bindings to + handle. + https://bugzilla.gnome.org/show_bug.cgi?id=747990 + +2015-07-10 15:36:59 +0900 Vineeth TM + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstobject.c: + gst: Fix floating reference inconsistencies in error cases + If a function takes a floating reference and sinks it, it should also do + that in error cases. I.e. call ref_sink() followed by unref(). + Otherwise the reference counting behaviour of the function will be + different between the good and the error case, and simply inconsistent. + https://bugzilla.gnome.org/show_bug.cgi?id=747990 + +2017-05-16 13:31:06 -0400 Nicolas Dufresne + + * gst/gstconfig.h.in: + Also use default visibility for plugins symbol + +2017-05-16 13:29:38 -0400 Nicolas Dufresne + + * config.h.meson: + * configure.ac: + * plugins/elements/Makefile.am: + * plugins/elements/meson.build: + * plugins/tracers/Makefile.am: + Remove plugin specific static build option + Static and dynamic plugins now have the same interface. The standard + --enable-static/--enable-shared toggle are sufficient. + +2017-05-16 00:02:11 +0100 Tim-Philipp Müller + + * tests/check/meson.build: + meson: fix gstprintf test linking + Must link against gstprint helper lib to use private symbol. + +2017-05-10 13:03:31 +0100 Tim-Philipp Müller + + * gst/gstconfig.h.in: + gstconfig.h: use default visibility for GST_EXPORT for gcc/clang too + This will be needed later when we switch to using -fvisibility=hidden. + +2017-05-10 13:07:31 +0100 Tim-Philipp Müller + + * gst/gstconfig.h.in: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstsegment.c: + * gst/gstsegment.h: + gst: add GST_DEPRECATED_FOR() and also export deprecated symbols + Can't use a #ifndef GST_DISABLE_DEPRECATED guard around deprecated + functions any more, as they won't get exported then. Besides, we + get a nicer error message from the compiler telling us what function + to use instead this way. + +2017-05-10 10:56:16 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstallocator.h: + * gst/gstatomicqueue.h: + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstbufferpool.h: + * gst/gstbus.h: + * gst/gstcaps.h: + * gst/gstcapsfeatures.h: + * gst/gstchildproxy.h: + * gst/gstclock.h: + * gst/gstcontext.h: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.h: + * gst/gstdatetime.h: + * gst/gstdebugutils.h: + * gst/gstdevice.h: + * gst/gstdevicemonitor.h: + * gst/gstdeviceprovider.h: + * gst/gstdeviceproviderfactory.h: + * gst/gstdynamictypefactory.h: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gstenumtypes.h.template: + * gst/gsterror.h: + * gst/gstevent.h: + * gst/gstformat.h: + * gst/gstghostpad.h: + * gst/gstinfo.h: + * gst/gstiterator.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstparamspecs.h: + * gst/gstparse.h: + * gst/gstpipeline.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.h: + * gst/gstpoll.h: + * gst/gstpreset.h: + * gst/gstprotection.h: + * gst/gstquery.h: + * gst/gstregistry.h: + * gst/gstsample.h: + * gst/gstsegment.h: + * gst/gststreamcollection.h: + * gst/gststreams.h: + * gst/gststructure.h: + * gst/gstsystemclock.h: + * gst/gsttaglist.h: + * gst/gsttagsetter.h: + * gst/gsttask.h: + * gst/gsttaskpool.h: + * gst/gsttoc.h: + * gst/gsttocsetter.h: + * gst/gsttracer.h: + * gst/gsttracerfactory.h: + * gst/gsttracerrecord.h: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.h: + * gst/gsturi.h: + * gst/gstutils.h: + * gst/gstvalue.h: + gst: mark symbols explicitly for export with GST_EXPORT + One omission: gst_allocator_sysmem_get_type() was + exported but never in any public header file. + +2017-05-10 00:11:10 +0100 Tim-Philipp Müller + + * common: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/controller_mkenum.py: + * libs/gst/controller/gstargbcontrolbinding.h: + * libs/gst/controller/gstdirectcontrolbinding.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gstproxycontrolbinding.h: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.h: + libs: controller: mark symbols explicitly for export with GST_EXPORT + +2017-05-09 16:19:31 +0100 Tim-Philipp Müller + + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstflowcombiner.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/base/gstqueuearray.h: + * libs/gst/base/gsttypefindhelper.h: + libs: base: mark symbols explicitly for export with GST_EXPORT + +2017-05-09 16:01:46 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnetaddressmeta.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnetcontrolmessagemeta.h: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.h: + * libs/gst/net/gstptpclock.h: + libs: net: mark symbols explicitly for export with GST_EXPORT + +2017-05-13 18:30:27 +0100 Tim-Philipp Müller + + * meson.build: + * meson_options.txt: + meson: add options to set package name and origin + https://bugzilla.gnome.org/show_bug.cgi?id=782172 + +2017-05-13 18:19:05 +0200 Stefan Sauer + + * docs/libs/Makefile.am: + docs: use the full path to ignore dirs + +2017-05-12 17:49:25 +0200 Stefan Sauer + + * libs/gst/check/gstharness.c: + docs: remove stray ',\' from doc comment + +2017-02-25 12:18:14 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: Add GstReferenceTimestampMeta + This is a meta that generically allows to attach additional reference + timestamps to a buffer, that don't have to relate to the pipeline clock + in any way. + Examples of this could be an NTP timestamp when the media was captured, + a frame counter on the capture side or the (local) UNIX timestamp when + the media was captured. + https://bugzilla.gnome.org/show_bug.cgi?id=779213 + +2017-05-09 16:29:21 +0100 Tim-Philipp Müller + + * meson.build: + meson: bump meson version requirement to 0.40.1 + +2016-12-15 12:48:55 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstbus.c: + * gst/gstbus.h: + * win32/common/libgstreamer.def: + bus: Add function to get the file descriptor of the bus + This is useful for integration with other event loops that work by + polling file descriptors. G_IO_IN will always be set whenever a message + is available currently. + https://bugzilla.gnome.org/show_bug.cgi?id=776126 + +2017-02-27 21:38:11 -0500 Nicolas Dufresne + + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + plugin: Unify static and dynamic plugin interface + This patch changes the entry point of each plugin in order to unify the + interface for static and dynamic plugin. What we do is replace the + current static plugin interface and extend the dymamic one. The plugin + entry was a C structure, name "gst_plugin_desc". With this patch, the + interface is now: + GstPpluginDesc *gst_plugin__get_desc(void); + The reason we change the C structure into function, is that it is + potentially more common to have function pointers, avoiding possible + binding language limitation. Additionally to that. This change prevents + the symbols from clashing between plugins, allowing to build once the + plugin (assuming you have -fPIC). + On the plugin loader side, we symply derive the shared object basename + to extract the plugin name. If this symbol is not found, we fallback to + gst_plugin_desc for backward compatibility. + This has one side effect, which is that the shared objects now need to + be named after their plugin name. This is generally the case with few + exceptions. The benifit of this limitation is that you can control the + gst_plugin__desc clash at file level. + https://bugzilla.gnome.org/show_bug.cgi?id=779344 + +2017-05-09 09:24:43 +0100 Tim-Philipp Müller + + * libs/gst/helpers/meson.build: + meson: fix search path for setcap + +2017-05-07 11:17:22 +0100 Tim-Philipp Müller + + * gst/gstdebugutils.c: + debugutils: make local variable static + +2017-05-05 12:23:43 +0100 Tim-Philipp Müller + + * libs/gst/helpers/ptp_helper_post_install.sh: + meson: fail silently in ptp helper post install script + .. in case permissions/capabilities could not be set. + +2017-05-05 12:02:33 +0100 Tim-Philipp Müller + + * libs/gst/helpers/meson.build: + meson: use cc.find_library() + find_library() was deprecated and removed in later versions. + +2017-05-05 11:49:08 +0100 Tim-Philipp Müller + + * config.h.meson: + * gst/meson.build: + * libs/gst/helpers/meson.build: + * libs/gst/helpers/ptp_helper_post_install.sh: + * meson.build: + * meson_options.txt: + meson: add gst-ptp-helper + https://bugzilla.gnome.org/show_bug.cgi?id=774418 + +2017-05-05 09:10:56 +0100 Tim-Philipp Müller + + * meson.build: + meson: fix indentation + No tabs please. + +2017-05-05 00:45:06 +0100 Tim-Philipp Müller + + * libs/gst/helpers/Makefile.am: + helpers: remove old cruft from CLEANFILES + These files are no longer built, so no need to clean them. + +2017-04-29 11:30:54 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + * meson.build: + g-i: no need to load registry in g-i scanner + +2017-05-04 21:37:28 +0100 Tim-Philipp Müller + + * Makefile.am: + * gst-element-check-1.0.m4: + Don't generate gst-element-check-1.0.m4 on the fly and fix meson build + This will interfere with 'git pull'. You will have to remove the + old generated gst-element-check-1.0.m4 manually if you're pulling + on a dirty build directory, sorry. + https://bugzilla.gnome.org/show_bug.cgi?id=782174 + +2017-05-04 21:06:21 +0100 Tim-Philipp Müller + + * meson.build: + meson: install gst-element-check-1.0.m4 + https://bugzilla.gnome.org/show_bug.cgi?id=782174 + +2017-04-30 12:10:49 +0900 Yasushi SHOJI + + * libs/gst/check/gstharness.c: + harness: Abort when failed to construct the specified pipeline + gst_harness_new_parse() returns without any error even if it doesn't + find the specified element. Then a succeeding call to + gst_harness_set_sink_caps_str() causes an error like this: + Unexpected critical/warning: gst_pad_push_event: assertion 'GST_IS_PAD (pad)' failed + This is a bit cryptic and doesn't give users any clue what was going + on. + gst_harness_new_parse() calls gst_harness_add_parse() with a newly + created empty harness and the given pipeline description string, but + gst_harness_add_parse() does not have a way to propagate the error + back to the caller. Since the function, gst_harness_add_parse(), is a + public API, it's not a good idea to change its signature. This patch, + instead, makes the function to g_error() when it discovers any error. + With this change the same error prints: + ** (myelement-test:25345): ERROR **: Unable to create pipeline 'bin.( myelement )': no element "myelement" + The current implementation of gst_parse_launch_full() doesn't return + partially constructed pipeline when GST_PARSE_FLAG_FATAL_ERRORS is + specified, however, this patch also adds a check for it. + https://bugzilla.gnome.org/show_bug.cgi?id=781958 + +2017-05-04 18:59:14 +0300 Sebastian Dröge + + * configure.ac: + * meson.build: + Back to development + +=== release 1.12.0 === + +2017-05-04 15:36:55 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * meson.build: + Release 1.12.0 + +2017-05-04 15:00:16 +0300 Sebastian Dröge + + * po/af.po: + * po/ast.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/fur.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2017-05-02 14:35:50 +0300 Sebastian Dröge + + * gst/gstmessage.c: + message: Don't pass a NULL debug string to g_utf8_validate() + g_utf8_validate() crashes on NULL, but NULL is valid for the debug + string nonetheless. + +2017-05-02 14:27:14 +0300 Sebastian Dröge + + * libs/gst/base/gstadapter.c: + adapter: Check if meta transform_func is NULL before using it + https://bugzilla.gnome.org/show_bug.cgi?id=782050 + +2017-05-02 10:32:54 +0200 Frédéric Dalleau + + * libs/gst/base/gstbasetransform.c: + basetransform: Check if meta transform_func is NULL before using it + An untested pointer segfaulted in webkit while playing video + on imx6 sabrelite. It turned out that the imx plugin didn't + implement the meta transform function. + The following GST_DEBUG trace was visible: + gstbasetransform.c:1779:foreach_metadata: copy metadata + GstImxVpuBufferMetaAPI + Thread 26 vqueue:src received signal SIGSEGV, Segmentation fault. + (gdb) bt + 0x00000000 in ?? () + 0x73f8d7d8 in foreach_metadata (inbuf=0xc9b020, meta=0x474b2490, + user_data=) at gstbasetransform.c:1781 + 0x73eb3ea8 in gst_buffer_foreach_meta (buffer=buffer@entry=0xc9b020, + func=0x73f8d705 , + user_data=user_data@entry=0x474b24d4) + at gstbuffer.c:2234 + https://bugzilla.gnome.org/show_bug.cgi?id=782050 + +2017-04-28 19:43:49 +0200 Víctor Manuel Jáquez Leal + + * gst/gst.c: + gst: check non-null before dereference + It is possible to use gst_deinit() without registering the base + classes. For example, when using gst_init_get_option_group() and + call the program with an invalid parameter. In that case, + gst_deinit() will lead to a segmentation fault, since there is a + dereference to a pointer that is null. + This patch validates if the type is non-null before dereferencing + it. + https://bugzilla.gnome.org/show_bug.cgi?id=781914 + +2017-04-28 11:57:41 +0200 Nicola Murino + + * scripts/gst-uninstalled: + gst-uninstalled: add opencv to bad libs + https://bugzilla.gnome.org/show_bug.cgi?id=781889 + +=== release 1.11.91 === + +2017-04-27 17:24:05 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * meson.build: + Release 1.11.91 + +2017-04-27 15:48:33 +0300 Sebastian Dröge + + * po/af.po: + * po/ast.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/fur.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2017-04-27 15:21:26 +0300 Sebastian Dröge + + * po/LINGUAS: + * po/ast.po: + * po/fur.po: + po: Update translations + +2017-04-24 20:27:33 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 60aeef6 to 48a5d85 + +2017-04-21 15:04:32 +0200 Koop Mast + + * tools/meson.build: + Meson: also build and install gst-stats-1.0 and it's man page. + https://bugzilla.gnome.org/show_bug.cgi?id=781585 + +2017-04-21 15:03:18 +0200 Koop Mast + + * tools/gst-stats-1.0.1: + Add very simple man page for gst-stats. + https://bugzilla.gnome.org/show_bug.cgi?id=781585 + +2017-04-21 10:51:59 -0300 Thibault Saunier + + * gst/gstelement.h: + doc: Fix some doctsing making GI happy + +2017-04-06 17:51:29 -0300 Thibault Saunier + + * gst/gstelement.h: + doc: Fix GstChangeState docstring + +2017-04-19 17:31:38 +0100 Sebastian Dröge + + * gst/gstinfo.c: + info: Move debug output in for_each_threshold_by_entry() to TRACE level + It's otherwise appearing many, many times in logs and usually is nothing + you're interested in. + +2017-03-31 12:22:00 +0100 Vincent Penquerc'h + + * tests/check/pipelines/seek.c: + tests: fix message leak in seek test + https://bugzilla.gnome.org/show_bug.cgi?id=780757 + +2017-03-29 19:26:53 +0900 Yasushi SHOJI + + * libs/gst/base/gstbasetransform.c: + basetransform: fix typo in debug log output + This unbalanced closing parenthesis is leftover from the commit + 8b739d91e7. It used to wrap the caps but we don't seem to do that in + the current code. + So, just remove it. No functionality has been changed. + https://bugzilla.gnome.org/show_bug.cgi?id=781484 + +2017-04-10 16:28:57 +0200 Rico Tzschichholz + + * gst/meson.build: + * libs/gst/base/meson.build: + * libs/gst/controller/meson.build: + * libs/gst/net/meson.build: + meson: A couple for GIR-generation fixes + +2017-04-12 09:48:53 -0300 Thibault Saunier + + * libs/gst/controller/meson.build: + meson: Add controller enum file as generated sources + Avoiding build failure like + https://ci.appveyor.com/project/thiblahute/gst-build-ge9m5/build/1.0.2857 + +2017-04-11 20:19:03 +0100 Tim-Philipp Müller + + * Makefile.am: + meson: dist new meson build script + +2017-04-11 20:16:53 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/controller.h: + controller: include new proxycontrolbinding header + And fix includes in docs to just include the main header (the + include for the proxycontrolbinding was wrong in the docs). + +2017-04-11 20:16:41 +0100 Tim-Philipp Müller + + * .gitignore: + .gitignore: ignore more + +2017-04-11 11:52:20 -0400 Olivier Crete + + * gst/parse/meson.build: + meson: Only check the first parameter + https://bugzilla.gnome.org/show_bug.cgi?id=781155 + +2017-04-11 10:17:40 -0300 Thibault Saunier + + * gst/parse/meson.build: + meson: Check bison and flex are recent enough + https://bugzilla.gnome.org/show_bug.cgi?id=781155 + +2017-04-10 23:48:53 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 39ac2f5 to 60aeef6 + +2017-04-10 12:24:06 -0400 Olivier Crête + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Accept NULL as a structure + Some GstStructure properties default to NULL, so it should + be a supported value. + With unit test. + +2017-04-10 14:26:42 +0300 Sebastian Dröge + + * libs/gst/controller/Makefile.am: + controller: Fix build with srcdir!=builddir + +2017-04-10 13:52:17 +0300 Rico Tzschichholz + + * libs/gst/controller/Makefile.am: + controller: Add missing sources/headers to the GIR build + +2017-04-09 12:16:39 +0300 Sebastian Dröge + + * libs/gst/controller/meson.build: + meson: And actually make the controller mkenums rules work + +2017-04-09 12:09:33 +0300 Sebastian Dröge + + * meson.build: + meson: Add check for glib-mkenums + +2017-04-09 12:02:43 +0300 Sebastian Dröge + + * libs/gst/controller/Makefile.am: + * libs/gst/controller/controller_mkenum.py: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/meson.build: + controller: Generate GLib enums automatically + +2017-04-04 17:53:39 +0100 Tim-Philipp Müller + + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstdynamictypefactory.c: + * gst/gstelementfactory.c: + * gst/gstplugin.c: + * gst/gstpluginloader.c: + * gst/gstregistry.c: + * gst/gstregistrychunks.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttracer.c: + * gst/gsttracerrecord.c: + * gst/gsttypefind.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstindex.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + * tests/check/gst/gstcontroller.c: + * tests/check/gst/gstelementfactory.c: + Don't use deprecated g_object_newv() + Use g_object_new() instead which nowadays has a shortcut for the + no-properties check. It still does an extra GType check in the + function guard, but there's a pending patch to remove that + and it's hardly going to be a performance issue in practice, + even less so on a system that's compiled without run-time checks. + Alternative would be to move to the new g_object_new_properties() + with a fallback define for older glib versions, but it makes the + code look more unwieldy and doesn't seem worth it. + Fixes deprecation warnings when building against newer GLib versions. + https://bugzilla.gnome.org/show_bug.cgi?id=780903 + +2017-04-07 13:49:29 -0400 Olivier Crête + + * tests/check/gst/gststructure.c: + test: Add test for serializing/deserializing NULL strings + +=== release 1.11.90 === + +2017-04-07 16:30:35 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * meson.build: + Release 1.11.90 + +2017-04-07 15:04:11 +0300 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2017-03-08 12:09:45 -0500 Olivier Crête + + * gst/gststructure.c: + structure: Don't print warning on NULL strings or pointers + Putting NULL for those is a valid serialization for the NULL value. + +2017-04-05 16:32:38 +0300 Sebastian Dröge + + * gst/gstclock.h: + gst: Use GstClockTimeDiff instead of GstClockTime as type for GST_SECOND and friends + They were (signed!) gint64 before because of G_GINT64_CONSTANT() already + and they are actually used in signed calculations. + With this change we at least ensure that an integer type of the correct + size is used for GI (it was using gint before). + +2017-04-05 15:46:26 +0300 Sebastian Dröge + + * gst/gstclock.h: + * gst/gstelementfactory.h: + * gst/gstevent.h: + * gst/gstquery.h: + gst: Update some more types and values of combined-flags constants + +2017-04-05 14:45:00 +0300 Sebastian Dröge + + * gst/gstbuffer.h: + * gst/gstmemory.h: + * gst/gstminiobject.h: + gst: Cast combined-flags constants to their respective target types + This makes C++ compilers a bit more happy without having the user of the + constants cast. It also provides the correct type information to GI. + https://bugzilla.gnome.org/show_bug.cgi?id=780923 + +2017-04-05 14:42:16 +0300 Sebastian Dröge + + * gst/gstbuffer.h: + * gst/gstmemory.h: + * gst/gstminiobject.h: + gst: Set values and types for combined-flags constants in GI annotations + +2017-04-05 14:26:33 +0300 Sebastian Dröge + + * gst/gstvalue.h: + value: Properly set value and type for GST_FLAG_SET_MASK_EXACT in GI annotations + Storing a -1 inside an unsigned integer confuses GIR based bindings + generators. + +2017-04-04 16:28:45 -0400 Nicolas Dufresne + + * data/bash-completion/helpers/gst.in: + completion: Try to avoid parsing summary + In GES, the summary refers to options that are only available when built + against gst-valdiate. Those where picked by our regex. This patch add a + initial grep to try and filter-out as best as possible the content to + which we will extract the command list. + +2017-04-04 14:25:52 -0400 Nicolas Dufresne + + * data/bash-completion/helpers/meson.build: + * data/meson.build: + * libs/gst/helpers/meson.build: + * meson.build: + meson: Add bash completion support + +2017-04-04 13:42:50 -0400 Nicolas Dufresne + + * configure.ac: + * data/Makefile.am: + * data/bash-completion/completions/gst-inspect-1.0: + * data/bash-completion/completions/gst-launch-1.0: + * data/bash-completion/helpers/.gitignore: + * data/bash-completion/helpers/gst.in: + * libs/gst/helpers/.gitignore: + * libs/gst/helpers/Makefile.am: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + completion: Place the completion helper in libexec + This patch reorganize the bash completion scripts in order to install + the binary helper (gst-completion-helper) in libexec path rather then + share folder. Most Linux hierarchy compliance requires that no binary + executable are placed in share. We also cleanup the unused .pc entries + and remove copy pasted parts of the script. Note that other project + including the common helper, should now use $_GST_HELPER to read + the binary executable gst-completion-helper. This helper is not longer + version, as it is placed in a versionned subfolder + (libexec/gstreamer.10) just like the other helpers (scanner and ptp). + +2017-03-31 11:22:49 +0100 Vincent Penquerc'h + + * gst/gstvalue.c: + gstvalue: fix GstValue leak in structure_field_union_into + https://bugzilla.gnome.org/show_bug.cgi?id=780751 + +2017-03-31 10:38:15 +0100 Vincent Penquerc'h + + * gst/gststreamcollection.c: + streamcollection: fix racy user-after-free + The issue happens when the structure is printed by the logging + subsystem: the object is included in the log, and this will cause the + full object printout to be done there. However, after dispose, the queue + was already cleared, so the access to it (to print the object) would + assert, as the queue was already freed. The patch changes it so that the + queue is merely empty, and only freed in _finalize. + https://bugzilla.gnome.org/show_bug.cgi?id=776293 + +2017-03-27 18:30:35 +0100 Tim-Philipp Müller + + * gst/gstdebugutils.c: + debugutils: add pad EOS flag in pipeline dot file dumps + But only if set. Helps debug issues with EOS propagation. + +2017-03-27 18:27:59 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: print structure property notifies nicer + One less layer of escaping, but still lots of ugly \. + +2017-03-24 14:33:19 -0400 Nicolas Dufresne + + * win32/common/libgstreamer.def: + Fix win32 libgstreamer.def ordering + This should fix make distcheck + +2017-03-15 17:31:39 -0400 Nicolas Dufresne + + * gst/gstparamspecs.c: + paramspec: Fix array validation logic + A paramspec validation should modify the content to match what the spec + requires and return TURE if a modification happened. This previous + implementation would only fix the first element of the array and return. + It was also return TRUE for empty array, while no modification was + needed. + https://bugzilla.gnome.org/show_bug.cgi?id=780111 + +2017-03-22 13:35:32 -0400 Nicolas Dufresne + + * gst/gstparamspecs.c: + array/fraction: In param types, use get_type() function directly + The GST_TYPE macro points to global variables initialized by the + first call to get_type. This is not an issue if you call gst_init() + but unfortunatly pygi will need to acces the param type before + init can be called. This removes an assertion. + +2017-03-22 13:33:47 -0400 Nicolas Dufresne + + * gst/gstparamspecs.c: + fraction/array: Make get_type() thread safe + Those aren't suppose to be called from multiple thread, but all + fundamental get_type() function are thread safe. Fix it to + be consistent and it may help if we change the typing mechanism + in GStreamer come day. + +2017-03-20 16:46:33 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + gstutils: Add helpers to get/set array properties + This is to help bindings access properties of type GST_TYPE_ARRAY. + This function will get/set the property and convert form/to + GValueArray. + New API: + gst_util_set_object_array + gst_util_get_object_array + https://bugzilla.gnome.org/show_bug.cgi?id=753754 + +2017-03-20 15:50:49 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: Add get/set_array/list using GValueArray + This adds a binding friendly interface to get and set arrays + and list into GstStructure. + New API: + - gst_structure_set_array + - gst_structure_set_list + - gst_structure_get_array + - gst_structure_get_list + https://bugzilla.gnome.org/show_bug.cgi?id=753754 + +2017-03-20 15:40:25 -0400 Nicolas Dufresne + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstvalue: Add transformation to/from GValueArray + This allow transforming a GValue of type G_TYPE_VALUE_ARRAY to + and from GST_TYPE_ARRAY/LIST. + https://bugzilla.gnome.org/show_bug.cgi?id=753754 + +2017-03-24 14:21:30 +0200 Sebastian Dröge + + * libs/gst/base/gstqueuearray.h: + queuearray: Add G_BEGIN_DECLS and G_END_DECLS to make it usable from C++ code + +2017-03-24 17:53:31 +1100 Jan Schmidt + + * gst/gstparamspecs.c: + paramspecs: Use gst_value_array_get_type() for GstParamSpecArray type + When registering GstParamSpecArray, use the gst_value_array_get_type() + function to get the type, rather than the GST_TYPE_ARRAY macro, which + gets it from the _gst_value_array_type, which is in turn only + initialised during gst_init() + Fixes criticals with (python) bindings that look up all the + types from the gobject-introspection info as soon as they + are imported. + /usr/lib64/python3.5/site-packages/gi/module.py:178: Warning: g_param_type_register_static: assertion 'g_type_name (pspec_info->value_type) != NULL' failed + g_type = info.get_g_type() + /usr/lib64/python3.5/site-packages/gi/module.py:212: Warning: g_type_get_qdata: assertion 'node != NULL' failed + type_ = g_type.pytype + /usr/lib64/python3.5/site-packages/gi/module.py:226: Warning: g_type_get_qdata: assertion 'node != NULL' failed + g_type.pytype = wrapper + /usr/lib64/python3.5/site-packages/gi/module.py:226: Warning: g_type_set_qdata: assertion 'node != NULL' failed + g_type.pytype = wrapper + +2017-03-17 22:32:19 +1100 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Don't forget error returns when processing more + If parsing returns a non-OK flow return in the middle + of processing an input buffer, don't overwrite that + if a later return is OK again - the subclass might + return not-linked in the middle, and then discard + subsequent data without pushing while returning OK. + A later success doesn't invalidate the earlier failure, + but we should continue processing after not-linked, so + as to keep parse state consistent. + https://bugzilla.gnome.org/show_bug.cgi?id=779831 + +2017-03-20 16:54:22 +0000 Tim-Philipp Müller + + * tools/gst-launch-1.0.1: + tools: replace mentions of 'mad' on the gst-launch-1.0 man page + The 'mad' plugin has been removed. Mention mpg123audiodec instead. + https://bugzilla.gnome.org/show_bug.cgi?id=776140 + +2017-03-13 11:08:01 +0000 Vincent Penquerc'h + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: fix union of int range and int when extending on a side + The internal representation uses bounds scaled by the step + Add tests to catch those cases + +2017-03-14 22:18:36 -0700 Thiago Santos + + * plugins/elements/gstqueue.c: + queue: avoid return flushing if we have a not-linked + Return the correct flow return instead of returning always flushing. + This would cause queue to convert not-linked to flushing and making + upstream elements stop. + Based on the previous patch for queue2. + https://bugzilla.gnome.org/show_bug.cgi?id=776999 + +2017-01-22 11:26:56 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: avoid return flushing if we have a not-linked + Return the correct flow return instead of returning always flushing. + This would cause queue2 to convert not-linked to flushing and making + upstream elements stop. + https://bugzilla.gnome.org/show_bug.cgi?id=776999 + +2016-09-18 12:02:54 -0300 Thiago Santos + + * tests/check/gst/gstbin.c: + tests: bin: add more tests for suppressed flags + Add tests to confirm flags are persisted even after removing + elements that have those suppressed flags + +2017-03-10 10:13:05 +0100 Wim Taymans + + * libs/gst/check/gstharness.c: + * plugins/elements/gstdownloadbuffer.c: + buffer: handle gst_buffer_map failures + +2017-03-10 10:12:49 +0100 Wim Taymans + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: unlock mutex in error case + +2017-03-09 12:09:57 +1100 Jan Schmidt + + * gst/gstvalue.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gststructure.c: + gstvalue: Do more checks when guessing at flagset strings + If guessing that a string matches a flagset, be more thorough + at checking that the string following a string of hex:hex: + actually looks like a flag set string. Add some unit tests + to catch more cases. + https://bugzilla.gnome.org/show_bug.cgi?id=779755 + +2017-03-09 12:09:57 +1100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Make min-interleave-time a configurable property + Remove a FIXME about making the minimum interleave + buffering a configurable property + +2017-03-08 14:51:42 +0000 Tim-Philipp Müller + + * gst/gstelementfactory.c: + elementfactory: promote factory not found log message to WARNING + In most cases people really want to know when an element + could not be created. + +2017-03-07 08:21:48 +0900 Seungha Yang + + * plugins/elements/gstinputselector.c: + inputselector: Always proxy position/duration query + active-pad switch causes reconfigure event with lock taken, + and upstream element might query the current position or duration + before returning the reconfigure event. + Meanwhile, gst_input_selector_get_linked_pad() is used to get srcpad + inside of default query handle, and it takes also lock. + Since inputselector is still locked by active-pad switch, and so the query + cannot be handled further. + https://bugzilla.gnome.org/show_bug.cgi?id=775445 + +2017-03-03 12:53:26 +0000 Tim-Philipp Müller + + * gst/gstinfo.h: + info: document that logging macros don't need newlines at the end + https://bugzilla.gnome.org/show_bug.cgi?id=779459 + +2017-02-24 21:35:27 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: add since marker to docs for new API + +2017-02-24 21:33:49 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for new API + +2017-02-24 10:23:01 -0300 Thibault Saunier + + * gst/gstregistry.c: + registry: Only scan plugin files that end with an extension + Not file that would for some reason end with 'so' or 'dll', etc... + https://bugzilla.gnome.org/show_bug.cgi?id=779175 + +2017-02-17 15:48:17 -0300 Thibault Saunier + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + pad: Add API to get the current state of a task + Avoiding the user to need to deal with the locking himself etc. + API: + gst_pad_task_get_state + https://bugzilla.gnome.org/show_bug.cgi?id=778830 + +2017-02-13 15:18:59 -0300 Thibault Saunier + + * gst/meson.build: + * meson.build: + * meson_options.txt: + meson: Add an option to disable usage of libunwind + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=778193 + +2017-02-24 15:59:35 +0200 Sebastian Dröge + + * meson.build: + meson: Update version + +2017-02-24 15:37:30 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.11.2 === + +2017-02-24 15:06:46 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + Release 1.11.2 + +2017-02-24 12:44:17 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2017-02-23 20:52:39 +0200 Vivia Nikolaidou + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Add deserialization for arrays/lists outside GstStructures + This is mostly useful for properties of those types when used in + gst-launch or similar. + https://bugzilla.gnome.org/show_bug.cgi?id=777375 + +2017-02-23 20:50:38 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Add a type abbreviation for GstFlagSet in serialization + +2017-02-23 20:47:30 +0200 Vivia Nikolaidou + + * gst/gst_private.h: + * gst/gststructure.c: + * gst/gstvalue.c: + value: Always add the type name to elements when serializing arrays/lists + But only when serializing outside of GstStructures, because in case of + GstStructure the type is already preprended to the array/list and the + GstStructure API makes sure that they have the same "generic" type so + deserialization works properly. + This keeps serialization of GstStructures the same as before, and the + GstCaps unit tests already test for that. However when serializing + standalone arrays/lists get the types added now. + +2017-02-23 20:22:03 +0200 Vivia Nikolaidou + + * gst/gst_private.h: + * gst/gststructure.c: + * gst/gstvalue.c: + value: Move list/array serialization/deserialization functions from GstStructure to GstValue + https://bugzilla.gnome.org/show_bug.cgi?id=777375 + +2017-02-23 20:16:17 +0200 Vivia Nikolaidou + + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + * win32/common/libgstreamer.def: + paramspecs: Add GstParamSpecArray for GST_TYPE_ARRAY typed properties + These are mostly useful to get our automatic + serialization/deserialization from strings and simple usage from + gst-launch or similar. + https://bugzilla.gnome.org/show_bug.cgi?id=777375 + +2017-02-21 20:23:51 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.c: + * tests/check/libs/bytereader.c: + bytereader: fix peek value when scanning for 00 00 01 with non-0 offset + We would add the offset a second time in _scan_for_start_code() + when we found a result, but it's already been added to the data + pointer at the beginning of _masked_scan_uint32_peek(), so the + peeked value would be wrong if the initial offset was >0, and + we would potentially read memory out-of-bounds. + Add unit test for all of this. + https://bugzilla.gnome.org/show_bug.cgi?id=778365 + +2017-02-20 12:16:32 +0100 Wim Taymans + + * gst/gstinfo.h: + info: put () around macro arguments + Put braces around macro arguments or else we might run into problems + with operater precedence. + +2017-02-20 10:45:57 +0100 Wim Taymans + + * gst/gstdeviceproviderfactory.c: + deviceproviderfactory: ignore empty classes + +2017-02-20 10:25:50 +0100 Wim Taymans + + * gst/gstdeviceproviderfactory.c: + deviceproviderfactory: compare class against NULL + gstdeviceproviderfactory.c:501:20: error: comparison between pointer and zero character constant [-Werror=pointer-compare] + if (classes[0] == '\0') + +2017-02-18 16:49:40 +0530 Nirbheek Chauhan + + * gst/meson.build: + meson: Fix build with latest upstream git + Trivial incorrect include_directories() call + +2017-02-18 10:03:24 +0100 Peter Korsgaard + + * gst/gstconfig.h.in: + gstconfig: Fix unaligned access support for the openrisc architecture + Teach gstconfig.h.in about the openrisc (or1k) architecture. Fixes + buildroot autobuild failure: + http://autobuild.buildroot.net/results/717/717d78ce0935749f477bdf3133b6f20057a28c01/build-end.log + https://bugzilla.gnome.org/show_bug.cgi?id=778866 + +2017-02-15 21:37:31 +0100 Stefan Sauer + + * libs/gst/base/gstbasesink.c: + gstbasesink: xref symbol in docs + +2017-02-15 20:58:49 +0100 Stefan Sauer + + * gst/gstpad.h: + pad: revert the content changes from previous commit + The default behaviour when returning GST_PAD_PROBE_OK is unrelated to + the other return code. + +2017-02-15 20:37:40 +0100 Stefan Sauer + + * gst/gstpad.h: + pad: fix docs for GstPadProbeReturn + There is no 'block' value, but we have 'drop'. Also fix the markup; it + is '%' to link to constants (and enum values). + +2016-10-24 22:47:29 +0100 Tim-Philipp Müller + + * Makefile.am: + meson: dist meson build files + Ship meson build files in tarballs, so people who use tarballs + in their builds can start playing with meson already. + +2017-01-31 09:55:59 +0000 Julien Isorce + + * tests/check/pipelines/seek.c: + tests: add 2 unit tests for non-flush seek with gstbaseparse + The unit test defines a test parse element that inherit from GstBaseParse. + The test pipeline is: fakesrc ! testparse ! fakesink sync=1 + Before the fix b2c05cac8 the first new test would have fail because the + pipeline would have wait doing nothing just after proceeded the seek event. + The second new test would have fail because the pipeline would have + played the media instantly just after proceeded the seek event + (like if sync was FALSE on the sink). + https://bugzilla.gnome.org/show_bug.cgi?id=777780 + +2017-01-31 21:19:18 +0200 Sebastian Dröge + + * gst/parse/grammar.y: + parse: Don't translate the "bin" element name + Otherwise we won't be able to create bins, there is no element called + "Behälter" if you're using a German locale. + https://bugzilla.gnome.org/show_bug.cgi?id=777998 + +2016-04-15 20:54:42 +0900 Seungha Yang + + * gst/gstsegment.c: + * tests/check/gst/gstsegment.c: + segment: Modifiy inside segment condition + There is a special case that segment_start == segment_stop == start. + It's inside of segment + https://bugzilla.gnome.org/show_bug.cgi?id=764707 + +2017-01-26 16:35:27 +0000 Thibault Saunier + + * gst/gstinfo.c: + info: Check libunwind return codes + +2017-01-18 18:16:26 -0300 Thibault Saunier + + * libs/gst/controller/meson.build: + * libs/gst/net/meson.build: + meson: libs: Add gir to the source list of the dependency + +2017-01-16 11:26:16 -0300 Thibault Saunier + + * gst/gst.c: + * gst/gstallocator.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstcapsfeatures.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstcompat.h: + * gst/gstcontext.c: + * gst/gstcontrolbinding.c: + * gst/gstcontrolsource.c: + * gst/gstdebugutils.h: + * gst/gstdevice.c: + * gst/gstdevicemonitor.c: + * gst/gstdeviceprovider.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstdynamictypefactory.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstmeta.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstparamspecs.c: + * gst/gstparse.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpoll.c: + * gst/gstpreset.c: + * gst/gstprotection.c: + * gst/gstquery.c: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gstsegment.c: + * gst/gststreamcollection.c: + * gst/gststreams.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttoc.c: + * gst/gsttocsetter.c: + * gst/gsttracer.c: + * gst/gsttracerfactory.c: + * gst/gsttracerrecord.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstindex.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstharness.c: + * libs/gst/check/gsttestclock.c: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstproxycontrolbinding.c: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetcontrolmessagemeta.c: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstptpclock.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstconcat.c: + * plugins/elements/gstdataurisrc.c: + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gststreamiddemux.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + Port gtk-doc comments to their equivalent markdown syntax + Modernizing our documentation and preparing a possible move to hotdoc. + This commits also adds missing @title metadatas to all SECTIONs + +2017-01-11 17:25:08 -0300 Thibault Saunier + + * gst/gstbuffer.h: + * gst/gstcontrolbinding.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstquery.h: + * gst/gststreamcollection.h: + * gst/gststreams.h: + * gst/gsttracer.h: + * gst/gsturi.h: + gst: Fix includes so that files can be built separately + It used to work but it has broke in the 1.10 cycle. + +2017-01-18 10:56:38 -0300 Thibault Saunier + + * gst/gstpoll.c: + gstpoll: Encode in utf-8 + +2017-01-26 15:32:31 -0800 Brendan Shanks + + * gst/gststreamcollection.h: + * gst/gststreams.h: + GstStream/GstStreamCollection: add g_autoptr() support + https://bugzilla.gnome.org/show_bug.cgi?id=777810 + +2017-01-26 16:51:21 +0000 Julien Isorce + + * libs/gst/base/gstbaseparse.c: + baseparse: correctly handle non-flush seek + Otherwise when seeking/looping to the start when reaching the end, + the sink waits for the duration of the stream. So the user hears + nothing for the duration of the stream before it actually loop again. + See example attached to the bug for that. + Existing test: + gst-plugins-good/tests/icles/test-segment-seeks foo.flac + Without the patch the user hears a crack/cut at each seek. + https://bugzilla.gnome.org/show_bug.cgi?id=777780 + +2016-05-24 14:57:54 +0200 Stian Selnes + + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Add API to filter g_warning/g_critical etc + New API functions to filter log messages before they are processed by + GstCheck. This can be used to discard specific messages that are + accepted by the test or to add callbacks that test specific messages. + Default bevavior when no callback is given to a filter is to discard the + message, because it does not makes sense to have a filter with no + callback which does not discard; that would be a noop. + Discarded messages will in addition to bypass the GstCheck handling also + return to GLib that the message is not fatal if it occurs. + https://bugzilla.gnome.org/show_bug.cgi?id=773091 + +2017-01-18 22:39:33 +0100 Stefan Sauer + + * gst/gstbin.c: + bin: update the docs for the event forwarding + First this sends the events not only to the sources and 2nd this is not only + for seek events. + +2017-01-18 15:07:58 +0200 Sebastian Dröge + + * gst/parse/grammar.y: + parse: Don't hold element's object lock while querying element pads' caps + This can easily deadlock if the element uses the object lock for + something internally, like posting an error message. Use an GstIterator + for iterating over the pads instead. + https://bugzilla.gnome.org/show_bug.cgi?id=777449 + +2017-01-16 09:41:19 +1100 Jan Schmidt + + * gst/gstbin.c: + gstbin: Quieten a noisy FIXME about duration caching + Only print this FIXME once per run, at it's pretty annoying in + lots of logs otherwise. + +2015-07-14 13:11:11 +0000 Jan Schmidt + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: Add ts-offset property. + Add a property to delay or advance sync time + when sync=true, with the same behaviour as + the ts-offset property in basesink + +2017-01-15 11:52:44 +0000 Tim-Philipp Müller + + * gst/gstdatetime.c: + * tests/check/gst/gstdatetime.c: + datetime: fix potential out-of-bound read on malformed datetime string + https://bugzilla.gnome.org/show_bug.cgi?id=777263 + +2017-01-13 12:34:43 +0000 Tim-Philipp Müller + + * meson.build: + meson: bump version + +2017-01-12 16:32:38 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.11.1 === + +2017-01-12 15:29:15 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + Release 1.11.1 + +2017-01-12 14:35:22 +0200 Sebastian Dröge + + * po/hr.po: + * po/id.po: + * po/pl.po: + * po/zh_CN.po: + Update .po files + +2017-01-12 14:34:18 +0200 Sebastian Dröge + + * po/hr.po: + * po/id.po: + * po/pl.po: + * po/zh_CN.po: + po: Update translations + +2017-01-12 14:26:55 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2017-01-05 13:45:37 +0100 Mark Nauwelaerts + + * tools/gst-inspect-1.0.1: + tools: update gst-inspect man page + +2017-01-05 10:32:03 -0300 Thibault Saunier + + * pkgconfig/meson.build: + meson: Do not generate .pc files for libgstcheck on windows + The lib is not built + +2017-01-04 12:10:45 +0100 Guillaume Desmottes + + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/meson.build: + meson: generate pkg-config -uninstalled pc files + Generating those files is useful for users building the GStreamer stack + using meson and having to link it to another project which is still + using the autotools. + https://bugzilla.gnome.org/show_bug.cgi?id=776810 + +2017-01-03 12:30:02 +0000 Tim-Philipp Müller + + * gst/gstpad.h: + pad: clarify docs for GST_PAD_PROBE_DROP + +2017-01-03 02:13:30 +1100 Jan Schmidt + + * plugins/elements/gstqueue.c: + queue: Don't generate GST_FLOW_ERROR without logging + At least log a message to the debug log when generating + a GST_FLOW_ERROR, to make it possible to find where it came from. + +2017-01-03 02:12:27 +1100 Jan Schmidt + + * gst/gstpadtemplate.c: + padtemplate: Fix null pointer dereference on invalid static caps + A typo in a static caps string may result in failure to + deserialise it, so don't dereference the result without + checking. + +2017-01-03 02:11:27 +1100 Jan Schmidt + + * gst/gstcaps.c: + caps: Fix null pointer dereference on invalid static caps + A typo in a static caps string may result in failure to + deserialise it, so don't dereference the result without + checking. + +2016-12-30 19:42:57 +0100 Stefan Sauer + + * gst/gststructure.c: + structure: reword comment for gst_structure_parse_string() + The comment was a bit confusing. Turn it into gtkdoc style and reword it. + +2016-12-28 21:47:03 +0100 Stefan Sauer + + * gst/gstinfo.c: + info: re-eval GST_DEBUG env var for late categories + When registering a new debug category after _debug_init(), we need to + re check the GST_DEBUG filter settings again. + In addition when parsing the filter setting, we need to already bump up + the min-debug level to not suppress debug log statments that dynamically + register a category. This happens in libraries that use a function to + register a category on first use. + +2016-12-29 17:04:04 +0100 Edward Hervey + + * scripts/gst-uninstalled: + gst-uninstalled: Default to python3 + It's 2016, unless you've specified a different version of python, + we'll default to python3 + +2016-12-28 13:45:54 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: also unset DISCONT on buffers in reverse playback fragments + +2016-12-21 21:58:53 -0300 Thibault Saunier + + * tools/gst-inspect-1.0.1: + * tools/gst-inspect.c: + gst-launch: Add a '--types' option to filter elements by types to print + This way the user can easily figure out what are the available audio + encoder for example doing: + gst-inspect-1.0 --types Encoder/Audio + https://bugzilla.gnome.org/show_bug.cgi?id=776392 + +2016-12-22 18:45:10 +0100 Nicolas Dechesne + + * tools/gst-launch.c: + tools: gst-launch: set GST_GL_XINITTHREADS + This ensure that XInitThreads is called and so gl contexts are properly + initialized. + https://bugzilla.gnome.org/show_bug.cgi?id=776401 + +2016-12-22 16:13:22 -0300 Thibault Saunier + + * gst/gstpreset.c: + gstpreset: Lower some debug logs level + A property not defined in a preset file can simply mean that the + user wants it to be set as it default value, and we should not warn + about that. + A missing preset file in a directory can happen has there are several + directory where a preset can be found in. + +2016-12-22 23:39:39 +0530 Nirbheek Chauhan + + * gst/meson.build: + meson: Fix order of C source and header in mkenums + Otherwise gstenum_h dependencies don't get added properly to gst_dep and + we see racy build failures everywhere. + +2016-12-17 14:35:19 +0000 Tim-Philipp Müller + + * gst/build_mkenum.py: + * gst/gstenumtypes.c.template: + * gst/gstenumtypes.h.template: + * gst/meson.build: + meson: use gnome.mkenums() with template files for enum file gen + Saves us a custom script. Template files are nicer than passing + multiline templating stuff through to glib-mkenums. And we can + get rid of our custom python script. + +2016-12-22 12:05:56 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Add guard to gst_element_release_pad() to ensure the pad belongs to this element + It's a programming error to pass other pads here, and it easily causes + crashes or other problematic behaviour down the road as subclasses + usually assume to only get their pads. + +2016-12-21 22:18:17 +0100 Stefan Sauer + + * plugins/tracers/gstrusage.c: + gstrusage: explicitly register to hooks + We were attaching to any probe point to take rusage samples. The new refcount + hooks are called way too frequently though to make this still feasible. + +2016-12-21 23:49:11 +0530 Nirbheek Chauhan + + * gst/meson.build: + * meson.build: + * tests/check/meson.build: + meson: Add several missing features from configure.ac + * -Wl,-Bsymbolic-functions + * HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID + * HAVE_POSIX_TIMERS + * HAVE_MONOTONIC_CLOCK + * HAVE_UINT128_T + * HAVE_LONG_LONG + * HAVE_PROCESS_H + * HAVE_GMP + * HAVE_GSL + * HAVE_DLADDR + Also, don't use prefix for checking functions, and only check msvc + functions on Windows. + +2016-12-21 09:33:39 +0530 Nirbheek Chauhan + + * config.h.meson: + * configure.ac: + * meson.build: + build: Remove unused functions + fgetpos, fsetpos, mmap, posix_memalign. None of these are used anywhere + in the codebase. + +2016-12-21 09:00:22 +0530 Nirbheek Chauhan + + * meson.build: + * plugins/tracers/meson.build: + meson: Derive defines from header/function names + This is what Autoconf already does for us, so just do this. Avoids + people making typos while adding header or function checks. Because we + use a config.h.meson, such typos won't even be noticed. + Also, starting from Meson 0.36.0, the XCode 8 workaround that we use for + clock_gettime is no longer needed. + +2016-12-21 10:02:45 +0100 Stefan Sauer + + * tests/check/gst/gststructure.c: + gststructure: simplify test + We can compare structures, that is what the caps fucntion that was used before + would call anyway. + +2016-12-20 21:08:09 +0100 Stefan Sauer + + * gst/gsttracerrecord.h: + tracerrecord: improve the values flags docs + +2016-12-20 21:07:14 +0100 Stefan Sauer + + * plugins/tracers/gstlatency.c: + latency: the latency is not an aggregated value + The logged latencies are individual meassurements. + +2016-12-02 08:29:11 -0300 Thibault Saunier + + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks: Allow user to set the flags to use to retrieve stack traces + https://bugzilla.gnome.org/show_bug.cgi?id=775541 + +2016-12-01 17:35:45 -0300 Thibault Saunier + + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks: Allow tracing Gst(Mini)Object reffing operations + It makes it much simpler to later debug refcount issues. + https://bugzilla.gnome.org/show_bug.cgi?id=775541 + +2016-11-30 17:05:56 -0300 Thibault Saunier + + * plugins/tracers/gstleaks.c: + leaks: Allow passing a GstStructure to configure the tracer + But keep understanding the simple synthax with a comma separated + list of filters + https://bugzilla.gnome.org/show_bug.cgi?id=775541 + +2016-12-21 00:40:10 +1100 Jan Schmidt + + * plugins/elements/gsttypefindelement.c: + typefind: Switch to normal mode before have-type + Before emitting have-type, switch to NORMAL + mode, as part of the have-type processing sends + the caps event downstream, which might trigger + actions like downstream autoplugging or + flushing seeks - and the latter are only + passed upstream if we've set typefind to NORMAL + mode. + +2016-12-13 21:12:23 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Protect against spurious wakeups of the condition variable + +2016-11-30 21:17:55 +0100 Fabrice Bellet + + * libs/gst/base/gstbasesink.c: + basesink: fix a use after free case + The event may be disposed while being pushed, so we make sure the + debug infrastructure won't use it after the gst_pad_push(). + +2016-12-16 18:30:20 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: fix typo in docs + +2016-12-16 23:45:08 +0530 Nirbheek Chauhan + + * gst/parse/meson.build: + * meson.build: + meson: Don't search for python3 twice + +2016-12-16 18:14:29 +0000 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + check: export new global variable + +2016-12-16 13:59:51 -0300 Thibault Saunier + + * libs/gst/check/gstcheck.c: + check: Avoid possible double free + +2016-12-02 11:59:43 -0300 Thibault Saunier + + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Allow listing unit tests names + Adding options while running gst_check_init + https://bugzilla.gnome.org/show_bug.cgi?id=775540 + +2016-12-15 15:37:45 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + * tools/gst-stats.c: + tracers/stats: log optional fields instead of GST_CLOCK_TIME_NONE + Simplify the traces and avoid trace analyzer to know that ((1<<64) - 1) means + we had no value. + +2016-12-16 15:05:46 +0100 Josep Torra + + * autogen.sh: + autogen.sh: drop a leftover docbook related bit + +2016-12-08 21:01:52 +1100 Matthew Waters + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: add structure intersect/union/is_subset/fixate implementations + Allows proper usage of structures in structures in caps. Subtraction + is not implemented due to complications with empty fields representing + all possible values. + The only implementation that doesn't delegate to the already existing + GstStructure functions is the union function. + https://bugzilla.gnome.org/show_bug.cgi?id=775796 + +2016-12-08 15:41:40 +1100 Matthew Waters + + * tests/check/gst/gststructure.c: + tests/structure: add some more is_subset checks + Explicitly testing extra/missing fields and name differences + +2016-12-14 18:19:00 +0000 Tim-Philipp Müller + + * tests/check/gst/gstmeta.c: + tests: meta: add test for gst_buffer_iterate_meta*() + https://bugzilla.gnome.org/show_bug.cgi?id=775727 + +2016-12-03 13:05:03 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add gst_buffer_iterate_meta_filtered() + For convenience. Pretty much every user of + gst_buffer_iterate_meta() filters for a specific + api type. + https://bugzilla.gnome.org/show_bug.cgi?id=775727 + +2016-12-14 15:22:30 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: mark gst_buffer_iterate_meta() as 'skip' for bindings + The pointer state arg won't work well, bindings can use + the foreach function instead. + https://bugzilla.gnome.org/show_bug.cgi?id=775727 + +2016-12-14 06:56:55 +0100 Iñaki García Etxebarria + + * gst/gstevent.c: + g-i: Fix annotations for gst_event_new_select_streams() and gst_event_parse_select_streams() + A gchar is not a string. + https://bugzilla.gnome.org/show_bug.cgi?id=775944 + +2016-12-13 23:25:39 -0800 Reynaldo H. Verdejo Pinochet + + * gst/gstpad.c: + gstpad: only warn on performance penalty if not using the template caps + After b76ecfd992b0d3a423cc9ace5539ecd2ba509d41 introduced + GST_PAD_FLAG_ACCEPT_TEMPLATE, the performance penalty this + message is refering to (the cascading ACCEPT_CAPS query) + only applies to the cases where !GST_PAD_IS_ACCEPT_TEMPLATE + +2016-12-13 20:51:17 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue/queue2: Protect against spurious condition variable wakeups + Make sure that we only wake up when we have to flush, or when this + specific query was handled. + https://bugzilla.gnome.org/show_bug.cgi?id=776039 + +2016-12-13 20:00:55 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue/queue2: Ensure that the streaming thread is unlocked after deactivating the srcpad + It might happen that the srcpad task function is never called at all, in + which case unlocking everything from there will never happen. + Make sure to unlock everything another time after the task function is + definitely stopped. + https://bugzilla.gnome.org/show_bug.cgi?id=776039 + +2016-12-12 22:14:24 +0100 Stefan Sauer + + * gst/gststructure.c: + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstvalue: add serialisation for GTypes + We need this in the GstTracerRecord. This will serialize GTypes to the typename + and vice versa. + +2016-12-13 13:20:09 +0100 Thibault Saunier + + * gst/gstinfo.c: + gst: Fix building with msvc + +2016-12-12 20:55:31 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: init new flags type in gst_init() + Fix 'make check' some more. + +2016-12-12 19:25:17 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for new API + +2016-11-30 15:10:48 -0300 Thibault Saunier + + info: Add a 'flags' parametter to gst_debug_get_stack_trace + This is an API break but that API has not been released yet. + We are passing a flag rather than a simple boolean as we can imagine + to implement more features in the future for example to retrieve a + stack trace for all the threads, etc.. + Retrieving source file and line numbers is pretty + expensive while getting a stack trace, this new argument + allows the user to decide to retrieve a backtrace + without those infos instead which is much faster. + For example running $ GST_LEAKS_TRACER_STACK_TRACE=1 GST_DEBUG=GST_TRACER:7 \ + GST_TRACERS=leaks time gst-launch-1.0 videotestsrc num-buffers=1 ! fakesink: + * With simple stack traces: + 0.04s user 0.02s system 99% cpu 0.060 total + * With full stack traces: + 0.66s user 0.23s system 96% cpu 0.926 total + https://bugzilla.gnome.org/show_bug.cgi?id=775423 + +2016-12-12 16:19:13 +0100 Edward Hervey + + * plugins/elements/gstfilesrc.c: + filesrc: Set GError in another error case + When changing the location while open, properly set the GError regarding + the failure. + +2016-12-10 18:38:32 +0900 Seungha Yang + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix overflow on get_buffering_level() + guint64 denominator factor for gst_util_uint64_scale_int() can cause overflow + https://bugzilla.gnome.org/show_bug.cgi?id=775921 + +2016-12-09 19:28:22 -0300 Thibault Saunier + + * meson_options.txt: + * plugins/tracers/meson.build: + meson: Fix build + +2016-12-09 17:55:39 -0300 Thibault Saunier + + * meson.build: + * plugins/tracers/meson.build: + * tests/check/meson.build: + meson: Support building with Gst debug disabled + +2016-12-09 22:39:36 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/libcompat/clock_gettime.c: + check: Fix macro check for OS X + TARGET_OS_MAC is defined on all Apple platforms. You need to check for + !TARGET_OS_IPHONE to detect OS X (now called macOS). + +2016-12-09 18:02:15 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Use gst_query_has_scheduling_mode_with_flags() convenience function + +2016-12-09 18:01:35 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/libcompat/clock_gettime.c: + check: Don't try to include CoreServices.h on iOS + On iOS, we have MobileCoreServices.h but it's not really needed. + +2016-12-09 17:59:53 +0530 Nirbheek Chauhan + + * config.h.meson: + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/README.txt: + * libs/gst/check/libcheck/libcompat/malloc.c: + * libs/gst/check/libcheck/libcompat/realloc.c: + * libs/gst/check/libcheck/meson.build: + * m4/check-checks.m4: + check: Don't check for malloc/realloc and try to fallback + When malloc is not available, this will set #define malloc rpl_malloc + which is implemented only inside libcheck, and not everything will link + to libcheck. + We don't really need to care too much about how malloc is implemented + and we don't care about platforms that don't implement malloc. + +2016-12-09 16:03:41 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/README.txt: + Add a README.txt with context for libcheck + https://bugzilla.gnome.org/show_bug.cgi?id=775870 + +2016-12-09 15:18:11 +0530 Nirbheek Chauhan + + * config.h.meson: + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/libcompat/alarm.c: + * libs/gst/check/libcheck/libcompat/clock_gettime.c: + * libs/gst/check/libcheck/libcompat/getline.c: + * libs/gst/check/libcheck/libcompat/gettimeofday.c: + * libs/gst/check/libcheck/libcompat/libcompat.c: + * libs/gst/check/libcheck/libcompat/libcompat.h: + * libs/gst/check/libcheck/libcompat/localtime_r.c: + * libs/gst/check/libcheck/libcompat/malloc.c: + * libs/gst/check/libcheck/libcompat/realloc.c: + * libs/gst/check/libcheck/libcompat/strdup.c: + * libs/gst/check/libcheck/libcompat/strsignal.c: + * libs/gst/check/libcheck/libcompat/timer_create.c: + * libs/gst/check/libcheck/libcompat/timer_delete.c: + * libs/gst/check/libcheck/libcompat/timer_settime.c: + * libs/gst/check/libcheck/meson.build: + * libs/gst/check/meson.build: + * m4/check-checks.m4: + * meson.build: + libcheck: Update the compatibility code and checks + This brings us up-to-speed with the latest compatibility code from upstream + check git. For completeness, we do all the checks that upstream check does, but + we skip the snprintf/vsnprintf code because it's not straightforward (involves + running code and that is bad for cross-compilation) and not necessary for the + platforms we support anyway. + If someone really wants this, they can uncomment this and copy the relevant + checks from the check git repository. + https://bugzilla.gnome.org/show_bug.cgi?id=775870 + +2016-12-09 15:18:11 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/libcompat/alarm.c: + * libs/gst/check/libcheck/libcompat/clock_gettime.c: + * libs/gst/check/libcheck/libcompat/libcompat.c: + * libs/gst/check/libcheck/libcompat/libcompat.h: + * libs/gst/check/libcheck/libcompat/localtime_r.c: + * libs/gst/check/libcheck/libcompat/strsignal.c: + * libs/gst/check/libcheck/libcompat/timer_create.c: + * libs/gst/check/libcheck/libcompat/timer_delete.c: + * libs/gst/check/libcheck/libcompat/timer_settime.c: + * libs/gst/check/libcheck/meson.build: + libcheck: Just move libcompat files to a subdir + Makes it clearer which files are actually used in libcheck and which are used + for cross-platform compatibility. This is going to be especially useful when we + add all the libcompat fallback code that upstream libcheck has which will add + about 6 new files. + https://bugzilla.gnome.org/show_bug.cgi?id=775870 + +2016-12-09 15:18:11 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_error.h: + * libs/gst/check/libcheck/check_impl.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_list.h: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_log.h: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_msg.h: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_pack.h: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_print.h: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/check_str.h: + libcheck: port to latest check git + Upstream seems to have stopped doing releases, but we need to update for better + Windows and Visual Studio support. + This patch only updates the libcheck sources and ignores the compatibility + sources for now. + https://bugzilla.gnome.org/show_bug.cgi?id=775870 + +2016-12-08 22:03:19 +0100 Stefan Sauer + + * plugins/tracers/gstlog.c: + tracers/log: log more detail + Log the objects like we would in GST_TRACE_OBJECT. Add the hook function into + the fucntion field. + +2016-12-08 22:02:17 +0100 Stefan Sauer + + * plugins/tracers/gstlog.c: + tracer/log: fix hook prototype + s/GstElement/GstPad/ + +2016-12-08 20:20:17 +0100 Stefan Sauer + + * gst/gstpad.c: + tracer: move the PAD_LINK tracer hook to _pad_link_full() + This is ultimately executing the pad_link. In the previous position we missed + some links, notably ghostpads. + +2016-12-07 21:53:49 +0100 Stefan Sauer + + * plugins/tracers/gstlatency.c: + tracer/latency: clear qdata + When reading the qdata, clear it to avoid it being read and unreffed again. + Fixes #774332 + +2016-12-06 22:32:31 +0100 Peter Seiderer + + * gst/gstconfig.h.in: + gstconfig: Fix unaligned access support for arc and nios2 architectures + Fixes buildroot autobuild failures ([1], [2]). + [1] http://autobuild.buildroot.net/results/fbd/fbdcd90635d5ec3a62ad98a7ff93b71b8e5ecde4 + [2] http://autobuild.buildroot.net/results/f3c/f3c9b0ed4ffb114221057237ce22c995b673a98b + https://bugzilla.gnome.org/show_bug.cgi?id=775728 + +2016-11-22 16:52:46 +0900 Seungha Yang + + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: + * gst/gsturi.h: + * tests/check/gst/gsturi.c: + * win32/common/libgstreamer.def: + uri: Add new uri API to get media fragments URI as table + As an usecase of URI fragment, it can indicate temporal or spatial + dimension of a media stream. To easily parse key-value pair, + newly added gst_uri_get_media_fragment_table () API will provide + the table of key-value pair likewise URI query. + See also https://www.w3.org/TR/media-frags/ + https://bugzilla.gnome.org/show_bug.cgi?id=774830 + +2016-12-06 16:27:23 +0100 Ricardo Ribalda Delgado + + * libs/gst/helpers/gst: + helpers/gst: Get bash completion options from gst-launch + It is more likely that gst-launch is installed than ges-launch + Reported-by: Marianna Smidth Buschle + https://bugzilla.gnome.org/show_bug.cgi?id=775714 + +2016-12-06 18:06:56 +0000 Tim-Philipp Müller + + * configure.ac: + configure: update for removed docs/design directory + +2016-12-05 18:16:34 -0300 Thibault Saunier + + * docs/Makefile.am: + * docs/design/Makefile.am: + * docs/design/draft-klass.txt: + * docs/design/draft-metadata.txt: + * docs/design/draft-push-pull.txt: + * docs/design/draft-tagreading.txt: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-TODO.txt: + * docs/design/part-activation.txt: + * docs/design/part-buffer.txt: + * docs/design/part-buffering.txt: + * docs/design/part-bufferpool.txt: + * docs/design/part-caps.txt: + * docs/design/part-clocks.txt: + * docs/design/part-context.txt: + * docs/design/part-controller.txt: + * docs/design/part-conventions.txt: + * docs/design/part-dynamic.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-element-source.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-framestep.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstghostpad.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-latency.txt: + * docs/design/part-live-source.txt: + * docs/design/part-memory.txt: + * docs/design/part-messages.txt: + * docs/design/part-meta.txt: + * docs/design/part-miniobject.txt: + * docs/design/part-missing-plugins.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-overview.txt: + * docs/design/part-preroll.txt: + * docs/design/part-probes.txt: + * docs/design/part-progress.txt: + * docs/design/part-push-pull.txt: + * docs/design/part-qos.txt: + * docs/design/part-query.txt: + * docs/design/part-relations.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + * docs/design/part-seqnums.txt: + * docs/design/part-sparsestreams.txt: + * docs/design/part-standards.txt: + * docs/design/part-states.txt: + * docs/design/part-stream-selection.txt: + * docs/design/part-stream-status.txt: + * docs/design/part-streams.txt: + * docs/design/part-synchronisation.txt: + * docs/design/part-toc.txt: + * docs/design/part-tracing.txt: + * docs/design/part-trickmodes.txt: + docs: Remove design doc as they have been moved to gst-docs + https://bugzilla.gnome.org/show_bug.cgi?id=775667 + +2016-11-29 17:34:40 -0300 Thibault Saunier + + * gst/gstinfo.c: + info: Properly start and end dwfl sessions when getting stack traces + We were creating a new session to retrive each line of a stack trace + and we are supposed to start it once for a whole stack trace. + And pass the whole file to gst-indent. + https://bugzilla.gnome.org/show_bug.cgi?id=775365 + +2016-12-02 22:47:32 +0100 Marcin Kolny + + * libs/gst/net/gstnetclientclock.c: + net: set clock name in the constructor + gst_net_client_clock_new() and gst_ntp_clock_new() didn't set the + "name" property. + https://bugzilla.gnome.org/show_bug.cgi?id=775538 + +2016-12-05 21:09:52 +0100 Peter Seiderer + + * gst/gstconfig.h.in: + gstconfig: Fix unaligned access support for microblaze and xtensa architectures + Fixes buildroot autobuild failures, for details see: + http://lists.busybox.net/pipermail/buildroot/2016-December/178895.html + https://bugzilla.gnome.org/show_bug.cgi?id=775661 + +2016-12-02 15:30:59 +0000 Tim-Philipp Müller + + * gst/gstmeta.h: + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_i386w.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + meta: remove unnecessary padding for GstMetaInfo struct + This structure is always allocated by GStreamer, can't be + subclassed or extended, and is never allocated or used on + the stack, so we don't need any padding and can extend it + as we please. + +2016-06-29 19:36:09 +0100 Tim-Philipp Müller + + * plugins/elements/gstelements_private.c: + * plugins/elements/gstelements_private.h: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstidentity.c: + fakesink, identity: print metas attached to buffer in silent=false mode + +2016-12-05 11:01:45 +0200 Sebastian Dröge + + * plugins/elements/gstconcat.c: + * plugins/elements/gsttee.c: + elements: Handle GstIterator RESYNC return value correctly in gst_iterator_foreach() + +2016-12-04 12:15:09 +0100 Stefan Sauer + + * plugins/tracers/gstlog.c: + tracers/log: log messages in message category + +2016-12-03 08:19:08 +0100 Edward Hervey + + * README: + * autogen.sh: + * common: + Automatic update of common submodule + From f980fd9 to 39ac2f5 + +2016-12-01 18:20:11 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Make sure to resync iterators and handle RESYNC at all in gst_iterator_foreach() calls + +2016-11-29 18:14:24 +0200 Sebastian Dröge + + * gst/gstclock.c: + clock: Fix offsetting of times_temp relative to the times array + +2016-11-29 10:34:14 -0300 Thibault Saunier + + * meson.build: + meson: Set default debug level to ERROR when running from git + +2016-11-28 19:28:27 +0530 Nirbheek Chauhan + + * gst/meson.build: + * plugins/elements/meson.build: + * tests/check/meson.build: + meson: Add Autotools changes that weren't mirrored + commits: + a7d282d27256ad1d1a55afc37d1db7f60b040089 + 6fdb4df0f8c8a9e39f7f7cb73ab65306fb0517f5 + 1aceebd67f0161806dc3b4b68488d599290f283e + +2016-11-28 14:11:27 +0100 Edward Hervey + + * tests/check/gst/gstpipeline.c: + check/pipeline: Make failure message more informative + This will provide maybe a bit more insight the next time it fails + +2016-11-28 14:00:18 +0100 Edward Hervey + + * tests/check/gst/gstmemory.c: + check/memory: Don't leak the custom allocator + +2016-11-28 13:48:16 +0100 Edward Hervey + + * gst/gstutils.c: + gstutils: Fix a pad leak + When requesting a pad from a template and it's already linked, this + means it was a static pad. Since we only want to return an *available* + pad, we must return NULL ... but we must also remove the reference + we got from getting that static pad. + The "No need to unref" message (which wasn't true for quite some time) + dates back from the very very very first commit introducing the 0.10 + features. + +2016-11-28 09:50:40 +0100 Edward Hervey + + * tests/check/elements/queue2.c: + check: Fix leak in queue2 test + +2016-11-23 15:41:28 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gstclock-linreg.c: + * gst/gstclock.c: + * gst/gstutils.c: + * gst/gstutils.h: + * tests/check/gst/gstclock.c: + * tests/check/gst/gstutils.c: + * win32/common/libgstreamer.def: + utils: Export linear regression calculation as public function + It is useful outside the GstClock code too. + https://bugzilla.gnome.org/show_bug.cgi?id=774916 + +2016-11-28 11:56:23 +0000 Tim-Philipp Müller + + * .gitignore: + * Makefile.am: + * configure.ac: + * gstreamer.spec.in: + Remove generated gstreamer.spec file + Likely extremely bitrotten, and we should not ship this anyway. + +2016-11-28 11:09:08 +0000 Tim-Philipp Müller + + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.interfaces: + * docs/plugins/inspect/plugin-coreelements.xml: + docs: add dataurisrc to docs and update + https://bugzilla.gnome.org/show_bug.cgi?id=774527 + +2016-11-28 11:10:05 +0000 Tim-Philipp Müller + + * tests/check/elements/filesrc.c: + tests: filesrc: init and clear GCond and mutex + Might otherwise leak on non-Linux systems. + +2016-11-28 11:08:24 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/dataurisrc.c: + tests: rewrite and enable dataurisrc test + Can't use playbin for core unit tests. + https://bugzilla.gnome.org/show_bug.cgi?id=774527 + +2016-11-28 11:07:20 +0000 Tim-Philipp Müller + + * plugins/elements/Makefile.am: + * plugins/elements/gstdataurisrc.c: + * plugins/elements/gstelements.c: + elements: add dataurisrc to build + Moved from -bad. + +2016-11-28 10:42:46 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + dataurisrc: fix string leak in property getter + +2016-11-28 11:18:39 +0000 Tim-Philipp Müller + + Move dataurisrc element from -bad + https://bugzilla.gnome.org/show_bug.cgi?id=774527 + +2016-11-28 12:28:28 +0200 Sebastian Dröge + + * gst/gstmessage.c: + message: Ensure that the "debug" field of error/warning/info messages is valid UTF-8 + The caller might pass arbitrary data here that caused the error, and + trying to set invalid UTF-8 in a GstStructure causes it to be not set at + all. Later when trying to parse it, the field will not exist and the + return value will point to invalid memory. Prevent this by storing NULL + instead. + Also print a g_warning(), the caller should never ever do this to begin + with. + +2016-11-26 11:20:51 +0000 Tim-Philipp Müller + + * .gitmodules: + common: use https protocol for common submodule + https://bugzilla.gnome.org/show_bug.cgi?id=775110 + +2016-11-26 11:06:20 +0000 Hanno Boeck + + * scripts/create-uninstalled-setup.sh: + scripts: create-uninstalled-setup: use https protocol to clone repos + The git:// protocol is problematic from a security perspective, as + it provides no authenticity of data. https:// also works better in + environments with restricted network connectivity. + Also add CLONE_OPTS to do shallow checkouts more easily. + https://bugzilla.gnome.org/show_bug.cgi?id=775110 + +2016-11-15 03:03:22 +0800 Ting-Wei Lan + + * meson.build: + meson: Support execinfo.h on FreeBSD by using -lexecinfo + FreeBSD supports execinfo.h and backtrace* functions, but + using them requires linking with -lexecinfo. + Requires sufficiently-new meson with #1053 fixed (post-0.36). + https://bugzilla.gnome.org/show_bug.cgi?id=774424 + +2016-11-23 18:56:20 +0100 Edward Hervey + + * tools/Makefile.am: + tools: Remove files to be cleaned + manpages are no longer auto-generated + cov-related files should not be there (if needed we could use gitignore) + +2016-11-04 18:54:10 -0400 Olivier Crête + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: Document the interaction between unlock() and wait_preroll() + This was totally non-obvious, the kind of big problem is that subclasses must + be able to unblock their streaming thread and continue exactly where they left off + on unpause! + https://bugzilla.gnome.org/show_bug.cgi?id=773912 + +2016-11-04 18:46:45 -0400 Olivier Crête + + * plugins/elements/gstelements_private.c: + * plugins/elements/gstelements_private.h: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfilesink.c: + fdsink: Block in preroll_wait on unlock + The correct behaviour of anything stuck in the ->render() function + between ->unlock() and ->unlock_stop() is to call + gst_base_sink_wait_preroll() and only return an error if this returns an + error, otherwise, it must continue where it left off! + https://bugzilla.gnome.org/show_bug.cgi?id=773912 + +2016-11-23 18:57:17 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Don't increment NULL pointers + Trivial workaround for coverity false warning. + CID 1394488, 1394487. + +2016-11-23 09:58:44 +0000 Tim-Philipp Müller + + * tools/.gitignore: + * tools/Makefile.am: + tools: fix distcheck and .gitignore + +2016-11-03 10:30:53 +0100 Antonio Ospite + + * tools/meson.build: + meson: tools: install the man pages + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-03 10:30:53 +0100 Antonio Ospite + + * tools/.gitignore: + * tools/Makefile.am: + * tools/gst-inspect-1.0.1: + * tools/gst-launch-1.0.1: + * tools/gst-typefind-1.0.1: + tools: ship the final man pages directly, no more man pages templates + Don't use templates for the man pages, the API version change is a rare + event, so it's not really worth keeping in place the "sed" boilerplate + to have it set at build time. + Shipping the final man pages directly also makes it easer to install the + man pages with meson (in a future commit). + Note that now all the occurrences of the programs names have the API + version as a suffix. + Traditionally the example command lines looked like: + gst-launch ... + Now they look like: + gst-launch-1.0 ... + This reflects the actual programs names and makes it easier to copy and + paste the example commands. + Also, the .gitignore file is adjusted not to ignore the final man pages + anymore. + You may need to clean your src/build directory before pulling in this + patch. + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-18 13:09:21 +1100 Matthew Waters + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstproxycontrolbinding.c: + * libs/gst/controller/gstproxycontrolbinding.h: + * libs/gst/controller/meson.build: + * tests/check/libs/controller.c: + * win32/common/libgstcontroller.def: + controllers: add new proxy control binding + Allows proxying the control interface from one property on one GstObject + to another property (of the same type) in another GstObject. + E.g. in a parent-child relationship, one may need to + gst_object_sync_values() on the child and have a binding (set elsewhere) + on the parent update the value. + Note: that this doesn't solve GObject property forwarding and must be + taken care of by the implementation manually or using GBinding. + https://bugzilla.gnome.org/show_bug.cgi?id=774657 + +2016-10-07 11:39:26 +0100 Julien Isorce + + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: log with GST_INFO instead GST_ERROR when subclass map failed. + Add unit test to ensure that. + It can be a normal execution path to do some map trials and there is + no need to worry the user in that case. + The application has to check the return value of gst_memory_map. + https://bugzilla.gnome.org/show_bug.cgi?id=765600 + +2016-11-17 17:37:16 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Ensure to set the RECONFIGURE flag again if reconfiguration failed + It might've failed just because of flushing or other things, and we + should retry again on the next possibility if something ever calls in + here again. + https://bugzilla.gnome.org/show_bug.cgi?id=774623 + +2016-11-17 16:39:52 -0800 Scott D Phillips + + * meson.build: + meson: add_global_arguments -> add_project_arguments + https://bugzilla.gnome.org/show_bug.cgi?id=774656 + +2016-11-16 23:19:28 +1100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Make sure not-linked streams get woken up + When running in sync-by-running-time mode, pad groups + that have exactly 1 pad and it's not-linked might never + wake up after computing a high time, as the per-pad-group + high time was only recomputed when a pad in the group + advances. + Wake those up using the global multiqueue high-time across + all other groups instead. + https://bugzilla.gnome.org/show_bug.cgi?id=774322 + +2016-11-16 10:55:29 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.h: + * gst/gstelement.h: + * gst/gstutils.h: + docs: misc fixes + +2016-11-16 10:51:48 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + utils: use temp var in fallback GST_WRITE_*() macros + To make sure the value is only expanded/used once, in case + there are side effects to it, and to avoid calculating it + or looking it up multiple times if there is a calculation + or lookup involved. + +2016-11-16 00:30:26 +1100 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix previous commit + Check the correct segment format value. + parse->segment.format is the format we're outputting in, + not the upstream format. Use parse->priv->upstream_format instead, + and make sure it's set in pull mode. + +2016-11-15 23:51:06 +1100 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Restrict query/convert responses when demuxing + If the parser is not parsing a raw elementary stream, restrict + the position, duration and conversion query replies to + things we can sensibly answer about - especially don't do + random conversions to/from bytes. + +2016-11-15 22:39:43 +1100 Jan Schmidt + + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + queues: Don't return negative position queries. + When subtracting queued data sizes from upstream queries + in queue, queue2, downloadbuffer and typefind, clamp the + result to not go negative, in case upstream returned + a nonsense value that's too small (as could happen if + upstream is estimating, or just broken) + +2016-11-14 11:27:05 -0800 Scott D Phillips + + * gst/gstbuffer.c: + * gst/gstprotection.c: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetcontrolmessagemeta.c: + Cast away const from GstMetaInfo in *_get_meta_info() functions + MSVC warns about the const in the implicit argument conversion in the + calls to g_once_init_{enter,leave}. It's OK so explicitly cast it. + https://bugzilla.gnome.org/show_bug.cgi?id=774293 + +2016-11-14 11:32:51 -0800 Scott D Phillips + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Update prototype of helper_find_suggest() + forward declaration prototype is updated to match the change in: + 5a72c23 Change some types to match their prototypes + https://bugzilla.gnome.org/show_bug.cgi?id=774293 + +2016-11-14 21:28:22 +0000 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * win32/MANIFEST: + * win32/README.txt: + * win32/common/config.h: + * win32/common/gstconfig.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + win32: remove copies of generated headers + +2016-11-14 21:18:13 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/Makefile.am: + * docs/htmlinstall.mak: + * docs/image-eps: + * docs/image-pdf: + * docs/image-png: + * docs/manuals.mak: + * docs/slides/Makefile.am: + * docs/slides/README: + * docs/slides/abstract: + * docs/slides/abstract.save: + * docs/slides/outline: + * docs/slides/slides: + * docs/url.entities: + * docs/xsl/Makefile.am: + * docs/xsl/admon.xsl: + * docs/xsl/css.xsl: + * docs/xsl/fileext.xsl: + * docs/xsl/fo.xsl: + * docs/xsl/html.xsl: + * docs/xsl/keycombo.xsl: + * docs/xsl/ulink.xsl: + docs: remove more docbook build cruft that's no longer needed + +2016-11-14 21:29:43 +0100 Stefan Sauer + + * docs/README: + docs/README: remove more outdated pieces of info/advice + +2016-10-20 22:32:50 +0200 Stefan Sauer + + * docs/design/part-tracing.txt: + * scripts/gst-plot-traces.sh: + scripts/gst-plot-traces.sh: make log parsing a bit more solid + Use grep -o to grab the log message only. This makes it work with colored log + files too. Prefilter the log to not catch tracer classes. + Update the commandline for the script in the docs. + +2016-10-20 15:38:46 -0300 Thibault Saunier + + * gst/printf/meson.build: + * libs/gst/check/libcheck/meson.build: + * meson.build: + meson: require meson 0.36 and use new `pic` arg on static libs + Removes a meson warning and some special casing we had. + +2016-11-11 10:30:44 -0800 Scott D Phillips + + * gst/gstevent.h: + * gst/gsttask.c: + * libs/gst/base/gsttypefindhelper.c: + Change some types to match their prototypes + Particularly note that the underlying integer type of the enum + GstTypeFindProbability is implementation dependent and may not match + guint. + https://bugzilla.gnome.org/show_bug.cgi?id=774293 + +2016-11-14 18:04:28 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translatable strings + +2016-11-14 17:46:07 +0000 Tim-Philipp Müller + + * Makefile.am: + * autogen.sh: + * configure.ac: + * docs/Makefile.am: + * docs/README: + * docs/faq/.gitignore: + * docs/faq/Makefile.am: + * docs/faq/base.css: + * docs/faq/dependencies.xml: + * docs/faq/developing.xml: + * docs/faq/faq.xml: + * docs/faq/general.xml: + * docs/faq/getting.xml: + * docs/faq/git.xml: + * docs/faq/legal.xml: + * docs/faq/start.xml: + * docs/faq/troubleshooting.xml: + * docs/faq/using.xml: + * gstreamer.spec.in: + docs: remove FAQ which was moved into gst-docs module + +2015-04-29 12:34:49 +0200 Nicola Murino + + * scripts/gst-uninstalled: + gst-uninstalled: add GIO_EXTRA_MODULES + In case glib is installed into local prefix dir. + https://bugzilla.gnome.org/show_bug.cgi?id=748626 + +2016-11-12 12:36:05 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + utils: faster GST_WRITE_* macros if unaligned access is possible + https://bugzilla.gnome.org/show_bug.cgi?id=599546 + +2016-11-11 20:31:03 +0000 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: better error message when linking two elements with capsfilter fails + https://bugzilla.gnome.org/show_bug.cgi?id=760550 + +2016-11-11 16:11:15 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + * win32/common/libgstreamer.def: + Add gst_print(), gst_println(), gst_printerr(), gst_printerrln() + Useful for debugging. + https://bugzilla.gnome.org/show_bug.cgi?id=766470 + +2016-11-11 10:23:17 -0800 Scott D Phillips + + * gst/gsttaglist.c: + taglist: remove `return void` in gst_tag_register + MSVC warns on this and the documentation about the warning says: + > The compiler assumes the function returns a value of type int + which is a little scary, so lets just remove the unnecessary 'return' + https://bugzilla.gnome.org/show_bug.cgi?id=774293 + +2016-05-09 15:32:43 +0200 Nicolas Huet + + * tests/check/libs/adapter.c: + tests: add unit test for gst_adapter_prev_pts_at_offset() + https://bugzilla.gnome.org/show_bug.cgi?id=765662 + +2016-04-27 10:57:29 +0200 Nicolas Huet + + * libs/gst/base/gstadapter.c: + adapter: fix distance when getting prev pts/dts at offset + https://bugzilla.gnome.org/show_bug.cgi?id=765662 + +2016-10-26 22:38:07 -0700 Scott D Phillips + + * meson.build: + meson: don't add_global_arguments when being built as a subproject + https://bugzilla.gnome.org/show_bug.cgi?id=773568 + +2016-07-21 10:52:30 +0200 Guillaume Desmottes + + * libs/gst/base/gstbasetransform.c: + basetransform: fix pool leak when early returning in decide_allocation + https://bugzilla.gnome.org/show_bug.cgi?id=769023 + +2016-07-27 13:39:50 +0200 Guillaume Desmottes + + * gst/gstinfo.c: + info: add GstStream and GstStreamCollection support to gst_debug_print_object() + https://bugzilla.gnome.org/show_bug.cgi?id=769220 + +2016-08-12 08:03:41 +0900 Seungha Yang + + * libs/gst/base/gstbasesrc.c: + basesrc: Support PROTECTION event from application + Application may want to send PROTECTION event to the src element. + https://bugzilla.gnome.org/show_bug.cgi?id=769775 + +2016-11-03 13:34:18 +0100 Antonio Ospite + + * tools/meson.build: + meson: tools: generate the targets dynamically + The three targets are the same except for input and output + files, use a loop and generate them dynamically. + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-03 15:21:05 +0100 Antonio Ospite + + * tools/gst-inspect.1.in: + * tools/gst-typefind.1.in: + tools: don't mention gst-feedback in man pages + gst-feedback no longer exists. + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-03 00:18:21 +0100 Antonio Ospite + + * tools/gst-launch.1.in: + tools: put the examples descriptions before the commands in man page + Put the description of the example command lines before the command + instead of after them. The new way is more intuitive. + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-02 22:56:01 +0100 Antonio Ospite + + * tools/gst-launch.1.in: + tools: don't start lines with single quotes in man page + When a line starts with a single quote it's treated in a special way by + man, which may result in paragraphs of the man page not rendered by the + man pager, so just avoid that. + A possible solution could have been to escape the singe quote with + a \(cq sequence but this is rather unreadable, instead the text has been + reformatted to have the problematic quoted 'ppc' string on the previous + line. + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-02 22:36:27 +0100 Antonio Ospite + + * tools/gst-inspect.1.in: + * tools/gst-launch.1.in: + * tools/gst-typefind.1.in: + tools: escape dashes in the man pages + The portable way to have the dashes to be rendered as ASCII minuses is + to use the sequence backslash-dash, use this style at least for text + that can be copied and pasted (e.g. command names, file names, element + options). + Also use backslash-dash in the NAME section as suggested by lexgrog(1). + https://bugzilla.gnome.org/show_bug.cgi?id=773917 + +2016-11-11 04:42:30 +0530 Nirbheek Chauhan + + * libs/gst/net/meson.build: + meson: Fir dependencies of gstnet-1.0 + It depends on gst_base_dep which will pull in gst_dep + +2016-11-11 04:41:39 +0530 Nirbheek Chauhan + + * libs/gst/base/meson.build: + meson: Add GstBase-1.0.gir to gst_base_dep + Without this, GIR generators can't find and use it + +2016-11-10 13:42:46 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * win32/common/libgstbase.def: + baseparse: add since marker for new API to docs and fix win32 .def file + +2016-11-10 12:47:37 +0000 Vincent Penquerc'h + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * win32/common/libgstbase.def: + baseparse: expose gst_base_parse_drain + +2016-11-09 14:07:28 -0300 Thibault Saunier + + * libs/gst/base/meson.build: + * libs/gst/controller/meson.build: + * libs/gst/net/meson.build: + meson: Advertise dependency on gst_dep generating girs + And do not simply link to libgst as the gir information + location only exist in declare_dependecy + https://bugzilla.gnome.org/show_bug.cgi?id=774044 + +2016-11-08 17:09:53 +0100 Victor Toso + + * tests/misc/netclock-replay.c: + tests: Fix compile warning on mingw64 + In file included from ../../libs/gst/net/gstntppacket.c:35:0, + from netclock-replay.c:25: + ../../config.h:546:0: error: "__MSVCRT_VERSION__" redefined [-Werror] + #define __MSVCRT_VERSION__ 0x0601 + In file included from /usr/x86_64-w64-mingw32/sys-root/mingw/include/crtdefs.h:10:0, + from /usr/x86_64-w64-mingw32/sys-root/mingw/include/stdio.h:9, + from netclock-replay.c:21: + /usr/x86_64-w64-mingw32/sys-root/mingw/include/_mingw.h:220:0: note: + this is the location of the previous definition + # define __MSVCRT_VERSION__ 0x0700 + https://bugzilla.gnome.org/show_bug.cgi?id=774108 + +2016-11-09 11:37:09 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Make sure to only lock the stream lock once + We also only unlock it once, and otherwise have it locked forever from + this thread, causing deadlocks on shutdown later. + +2016-11-08 16:58:53 +0100 Victor Toso + + * gst/gstpoll.c: + pool: Fix compiler warning on mingw64 + gstpoll.c: In function 'release_event': + gstpoll.c:239:3: error: suggest parentheses around assignment used as + truth value [-Werror=parentheses] + if (status = WaitForSingleObject (set->wakeup_event, INFINITE)) { + ^~ + https://bugzilla.gnome.org/show_bug.cgi?id=774108 + +2016-11-04 21:15:58 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def for new API + +2016-11-04 10:19:17 -0300 Thibault Saunier + + * meson.build: + meson: Unset the plugin paths to generate the .gir files + Avoiding problems when using subproject: + Failed to load plugin 'something.so: file too short + +2016-10-10 16:40:21 +0200 Thibault Saunier + + * gst/gstinfo.c: + debug: Remove the Gst only based stack trace printing implementation + We now have 2 other implementations that should work better. + https://bugzilla.gnome.org/show_bug.cgi?id=772555 + +2016-10-07 12:02:44 +0200 Thibault Saunier + + * plugins/tracers/Makefile.am: + * plugins/tracers/gstleaks.c: + * plugins/tracers/meson.build: + tracers: leaks: Use the new gst_debug_get_stack_trace + And remove the local implementation of it. + https://bugzilla.gnome.org/show_bug.cgi?id=772555 + +2016-10-07 11:38:27 +0200 Thibault Saunier + + * config.h.meson: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/meson.build: + * meson.build: + * plugins/tracers/meson.build: + gst: Use libunwind/libdw to generate backtraces if avalaible + Making the gst_debug_print_trace function more generally useful. + API: + + gst_debug_get_trace + https://bugzilla.gnome.org/show_bug.cgi?id=772555 + +2016-11-02 13:57:51 +0100 Antonio Ospite + + * tools/gst-launch.c: + tools: gst-launch: fix minor memory leak when failing to parse options + Commit 215cfcf99338 (gstreamer: Fix memory leaks when context parse + fails) fixes some memory leak, but in one of the newly added calls to + g_clear_error() the wrong variable was passed. + When failing to parse command line options, free the "err" variable, not + the "error" one. + https://bugzilla.gnome.org/show_bug.cgi?id=773907 + +2016-11-03 15:22:34 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesink.c: + basesink: Make sure we never drop the preroll buffer + This is cosmetic as 'late' should never be set during preroll (in pause). + Though code may evolve in the future, so this is good for preventing + potential bugs. + https://bugzilla.gnome.org/show_bug.cgi?id=772468 + +2016-10-05 14:26:11 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesink.c: + basesink: Don't nest prepare/render calls + When the first buffer arrives, we endup calling: + ->prepare() + ->prepare() + ->preroll() + ->render() + This will likely confuse any element using this method. With this patch, + we ensure the preroll take place before the first render prepare() is + called. This will result in: + ->prepare() + ->preroll() + ->prepare() + ->render() + https://bugzilla.gnome.org/show_bug.cgi?id=772468 + +2016-11-02 16:27:58 +0000 Luis de Bethencourt + + * libs/gst/base/gstbasesink.c: + basesink: fix typo in documentation + Small typo in the documentatin of gst_base_sink_set_drop_out_of_segment(). + Fixing it. + +2016-11-02 16:35:59 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: Fix gst_base_sink_set_drop_out_of_segment() documentation + Also silences a GI warning. + +2016-11-02 14:11:43 +0530 Nirbheek Chauhan + + * libs/gst/check/libcheck/clock_gettime.c: + clock_gettime.c: Use __APPLE__ instead of __MACH__ + Hurd also defines __MACH__, but it does not have mach_absolute_time. Use + the more strict __APPLE__ instead. + Has also been sent upstream: https://github.com/libcheck/check/pull/65 + +2016-11-02 14:01:38 +0530 Nirbheek Chauhan + + * m4/check-checks.m4: + build: Fix AM_CONDITIONAL check for clock_gettime + It was always evaluating to false, so clock_gettime.c was always being + included into libcheck. This breaks building on Hurd and causes us to + always override clock_gettime() even when it is available. + https://bugzilla.gnome.org/show_bug.cgi?id=773813 + +2016-11-02 10:12:58 +0200 Sebastian Dröge + + * gst/meson.build: + gst: Also include the gstdynamictypefactory.c source file in the build + +2016-11-02 10:04:01 +0200 Sebastian Dröge + + * gst/Makefile.am: + * gst/meson.build: + gst: Install gstdynamictypefactory.h header file + +2016-11-02 09:35:05 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + Revert "baseparse: fix draining with less data than min frame size available" + This reverts commit 2e278aeb7128e8732f5324ab8c8b22a47950c80a. + Some parsers, specifically audio parsers, assume to get all remaining + data on EOS and just pass them onwards. While the idea here is correct, + we will probably need a property for this on baseparse for parsers to + opt-in. + https://bugzilla.gnome.org/show_bug.cgi?id=773666 + +2015-06-26 03:29:27 +1000 Jan Schmidt + + * gst/parse/grammar.y: + * gst/parse/parse.l: + * gst/parse/types.h: + * tests/check/pipelines/parse-launch.c: + * tools/gst-launch.1.in: + parse-launch: Support linking all pads with new operator + Introduce a new operator ':' - e.g. element1 ':' element2 + For example, 'uridecodebin : encodebin' - + if the encodebin has multiple profiles compatible with the + decodebin, multiple links will be created. + With '!' , after one delayed link is successfully done, the + pad-added callback is disconnected. + https://bugzilla.gnome.org/show_bug.cgi?id=751450 + +2016-11-02 11:32:42 +1100 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + * win32/common/libgstbase.def: + Add new basesink API to exports and Since markers + Add Since markers to the new basesink API to drop + out-of-segment buffers, and add them to the + win32 exports + +2015-05-14 00:25:21 +1000 Jan Schmidt + + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstdynamictypefactory.c: + * gst/gstdynamictypefactory.h: + * gst/gstelementfactory.h: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * gst/gststructure.c: + * gst/gstvalue.c: + * win32/common/libgstreamer.def: + dynamic types: Implement dynamic types in the registry + Implement GstDynamicTypeFactory as a new registry feature. + GstDynamicTypeFactory provides a way of registering a GType + into the registry, such that it will be registered as a dynamic + type when the registry is loaded, and then automatically loaded + if the type is needed during caps parsing. + This allows using non-core types in pad templates, by loading a + registry feature to create the GType on the fly. + https://bugzilla.gnome.org/show_bug.cgi?id=750079 + +2016-04-29 02:38:49 +1000 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * plugins/elements/gstfakesink.c: + fakesink: Add property to not drop out-of-segment buffers + Implement handling in basesink to not unconditionally discard + out-of-segment buffers and expose it as a new property on fakesink + (not unconditionally in all basesink based sinks). + The property defaults to FALSE. + https://bugzilla.gnome.org/show_bug.cgi?id=765734 + +2016-11-01 23:54:05 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Update GstValue table size for GValueArray + +2016-07-07 19:41:49 +0300 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Always push all sticky events whenever we forward a serialized event + Otherwise downstream will have an inconsistent set of sticky events at this + point, e.g. when a TAG event is pushed and downstream wants to relate it to + the stream by looking at the current STREAM_START event. + https://bugzilla.gnome.org/show_bug.cgi?id=768526 + +2016-03-29 10:38:05 +0300 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Set GST_PAD_FLAG_PROXY_CAPS before forwarding sticky events + https://bugzilla.gnome.org/show_bug.cgi?id=752213 + +2016-10-29 11:17:38 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix draining with less data than min frame size available + baseparse would pass whatever is left in the adapter to the + subclass when draining, even if it's less than the minimum + frame size required. This is bogus, baseparse should just + discard that data then. The original intention of that code + seems to have been that if we have more data available than + the minimum required we should pass all of the data available + and not just the minimum required, which does make sense, so + we'll continue to do that in the case that more data is available. + Fixes assertions in rawvideoparse on EOS after not-negotiated with + fakesrc sizetype=random ! queue ! rawvideoparse format=rgb ! appsink caps=video/x-raw,format=I420 + https://bugzilla.gnome.org/show_bug.cgi?id=773666 + +2015-10-29 22:51:18 +0100 Stian Selnes + + * gst/gstinfo.c: + info: Replace %p and %r in GST_DEBUG_FILE + It's useful to be able to set a name pattern for GST_DEBUG_FILE so that + the same environment variable can be used for multiple processes and + still write to different files. Especially useful if these processes + run simultaneously. + %p: Replaced with PID + %r: Replaced with random number + %p is obviously useful. %r is useful when for instance running two + processes with same PID but in different containers. + https://bugzilla.gnome.org/show_bug.cgi?id=773092 + +2013-05-02 10:09:29 +0200 Stian Selnes + + * gst/gst.c: + * gst/gstregistry.c: + registry: set env GST_REGISTRY_DISABLE=yes to disable registry + If GST_REGISTRY_DISABLE=yes the registry is disabled similar to + compile time switch GST_DISABLE_REGISTRY. + https://bugzilla.gnome.org/show_bug.cgi?id=773089 + +2015-11-11 16:43:40 +0100 Stian Selnes + + * gst/gstvalue.c: + gstvalue: Make GValueArray serializable + For instance very useful for logging GValueArray with GST_PTR_FORMAT + https://bugzilla.gnome.org/show_bug.cgi?id=761918 + +2016-04-29 16:26:49 +0900 Wonchul Lee + + * gst/gstelement.c: + * gst/gstpadtemplate.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstpad.c: + element: Allow multiple conversion specifiers for request pads + This allows pad template names like "src_%u_%u", but it does not allow + multiple specifiers of string type %s as that would lead to ambiguities. + https://bugzilla.gnome.org/show_bug.cgi?id=761225 + +2015-11-05 17:13:25 -0300 Thiago Santos + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add no-reconfigure link check + Enable it to prevent sending reconfigure when linking elements. + Useful for autoplugging when we know caps or bufferpools shouldn't change + to save doing caps renegotiation to end up with the same final scenario. + The no-reconfigure is not a proper check, it is a flag. It is implemented + as a GstPadLinkCheck to avoid creating another gst_pad_link variant. + https://bugzilla.gnome.org/show_bug.cgi?id=757653 + +2016-11-01 18:08:18 +0000 Tim-Philipp Müller + + * meson.build: + meson: update version + +2016-11-01 17:35:18 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/Makefile.am: + * docs/manual/.gitignore: + * docs/manual/Makefile.am: + * docs/manual/README: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-buffering.xml: + * docs/manual/advanced-clocks.xml: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/advanced-dparams.xml: + * docs/manual/advanced-interfaces.xml: + * docs/manual/advanced-metadata.xml: + * docs/manual/advanced-position.xml: + * docs/manual/advanced-threads.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/appendix-compiling.xml: + * docs/manual/appendix-integration.xml: + * docs/manual/appendix-licensing.xml: + * docs/manual/appendix-porting.xml: + * docs/manual/appendix-programs.xml: + * docs/manual/appendix-quotes.xml: + * docs/manual/base.css: + * docs/manual/basics-bins.xml: + * docs/manual/basics-bus.xml: + * docs/manual/basics-data.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-init.xml: + * docs/manual/basics-pads.xml: + * docs/manual/basics-plugins.xml: + * docs/manual/bin-element-ghost.png: + * docs/manual/bin-element-noghost.png: + * docs/manual/bin-element.png: + * docs/manual/clocks.png: + * docs/manual/communication.png: + * docs/manual/diagrams-clocks.svg: + * docs/manual/diagrams-general.svg: + * docs/manual/diagrams-pipelines.svg: + * docs/manual/filter-element-multi.png: + * docs/manual/filter-element.png: + * docs/manual/gstreamer-overview.png: + * docs/manual/hello-world.png: + * docs/manual/highlevel-playback.xml: + * docs/manual/highlevel-xml.xml: + * docs/manual/images/.gitignore: + * docs/manual/intro-basics.xml: + * docs/manual/intro-gstreamer.xml: + * docs/manual/intro-motivation.xml: + * docs/manual/intro-preface.xml: + * docs/manual/linked-elements.png: + * docs/manual/manual.xml: + * docs/manual/mime-world.png: + * docs/manual/outline.txt: + * docs/manual/simple-player.png: + * docs/manual/sink-element.png: + * docs/manual/src-element.png: + * docs/manual/state-diagram.svg: + * docs/manual/thread-buffering.png: + * docs/manual/thread-synchronizing.png: + * docs/manual/titlepage.xml: + * docs/pwg/.gitignore: + * docs/pwg/Makefile.am: + * docs/pwg/advanced-allocation.xml: + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-dparams.xml: + * docs/pwg/advanced-events.xml: + * docs/pwg/advanced-interfaces.xml: + * docs/pwg/advanced-negotiation.xml: + * docs/pwg/advanced-qos.xml: + * docs/pwg/advanced-request.xml: + * docs/pwg/advanced-scheduling.xml: + * docs/pwg/advanced-tagging.xml: + * docs/pwg/advanced-types.xml: + * docs/pwg/appendix-checklist.xml: + * docs/pwg/appendix-licensing.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/appendix-python.xml: + * docs/pwg/base.css: + * docs/pwg/building-boiler.xml: + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-eventfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/building-props.xml: + * docs/pwg/building-queryfn.xml: + * docs/pwg/building-signals.xml: + * docs/pwg/building-state.xml: + * docs/pwg/building-testapp.xml: + * docs/pwg/intro-basics.xml: + * docs/pwg/intro-preface.xml: + * docs/pwg/other-base.xml: + * docs/pwg/other-manager.xml: + * docs/pwg/other-ntoone.xml: + * docs/pwg/other-oneton.xml: + * docs/pwg/other-sink.xml: + * docs/pwg/other-source.xml: + * docs/pwg/pwg.xml: + * docs/pwg/titlepage.xml: + * tests/examples/Makefile.am: + * tests/examples/manual/.gitignore: + * tests/examples/manual/Makefile.am: + * tests/examples/manual/extract.pl: + docs: remove app dev manual and plugin writer's guide + They have moved to gst-docs and will be maintained there in future. + +=== release 1.11.0 === + +2016-11-01 18:53:15 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.10.0 === + +2016-11-01 17:50:24 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.10.0 + +2016-11-01 17:40:11 +0200 Sebastian Dröge + + * po/nb.po: + Update .po files + +2016-11-01 17:38:43 +0200 Sebastian Dröge + + * po/nb.po: + po: Update translations + +2016-11-01 17:36:02 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2016-10-25 12:21:07 +0530 Nirbheek Chauhan + + * meson.build: + * meson_options.txt: + meson: Add an option to explicitly disable gtk-doc + Similar to how Autotools provides an option, default is 'enabled'. + +2016-10-24 11:45:38 -0400 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.c: + Revert "collectpads: Assume PTS is equal DTS if PTS is missing" + This reverts commit 9b0d42ceecb3198399d7e05e3d5f080a7ca27ca9. + https://bugzilla.gnome.org/show_bug.cgi?id=762207 + +2016-10-18 11:59:25 -0400 Nicolas Dufresne + + * gst/gstallocator.c: + allocator: Mark registered allocator for leak + +2016-06-21 08:00:30 -0500 Andrew Eikum + + * gst/gstmessage.h: + gstmessage.h: Avoid gcc bit shift overflow compiler warning + Avoids bit shift overflow warning with gcc6. + https://bugzilla.gnome.org/show_bug.cgi?id=767882 (glib) + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71803 (gcc) + https://bugzilla.gnome.org/show_bug.cgi?id=767883 + +2016-10-23 22:11:08 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: fix erroneous use of _("") + Fixes xgettext warnings when doing 'make update-po': + gst/parse/grammar.y:217: warning: Empty msgid. It is reserved by GNU gettext: + gettext("") returns the header entry with + meta information, not the empty string. + +2016-10-22 17:05:44 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + docs: add index for API new in 1.10 + +2016-10-22 17:05:25 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + docs: add index for API new in 1.8 + +2016-10-21 15:40:47 +0200 Jesper Larsen + + * libs/gst/base/gstadapter.c: + adapter: Fix mix-up between DTS and PTS + https://bugzilla.gnome.org/show_bug.cgi?id=773319 + +2016-10-21 15:22:28 +0300 Sebastian Dröge + + * plugins/elements/gstqueue.c: + Revert "queue: Fix race when calculating cur_level.time" + This reverts commit d03bd547809f849405a3f706920091d9b03147b0. + It breaks the unit test, although it ensures that only correct values + are used for calculations. Needs to be fixed up. + https://bugzilla.gnome.org/show_bug.cgi?id=773096 + +2016-10-20 17:19:25 -0300 Thibault Saunier + + * gst/printf/meson.build: + * libs/gst/check/libcheck/meson.build: + * meson.build: + Revert "meson: Use the new `pic` argument on static libs" + This reverts commit a5752240a178c2c651ed10167025fad8b9c4e7bd. + pic was added after 0.35 and will be present in 0.36 (meson + documentation was wrong). + +2016-10-20 15:38:46 -0300 Thibault Saunier + + * gst/printf/meson.build: + * libs/gst/check/libcheck/meson.build: + * meson.build: + meson: Use the new `pic` argument on static libs + We depend on meson 0.35 which makes it simpler to handle + Removes a meson warning + +2016-09-14 14:23:56 +0200 Stian Selnes + + * plugins/elements/gstqueue.c: + queue: Fix race when calculating cur_level.time + On the first buffer, it's possible that sink_segment is set but + src_segment has not been set yet. If this is the case, we should not + calculate cur_level.time since sink_segment.position may be large and + src_segment.position default is 0, with the resulting diff being larger + than max-size-time, causing the queue to start leaking (if + leaky=downstream). + One potential consequence of this is that the segment event may be + stored on the srcpad before the caps event is pushed downstream, causing + a g_warning ("Sticky event misordering, got 'segment' before 'caps'"). + https://bugzilla.gnome.org/show_bug.cgi?id=773096 + +2016-09-27 00:00:30 +1000 Matthew Waters + + * gst/gstelement.c: + element: use g_strcmp0 in set_context + It's NULL-safe while the libc implementation may not be. + https://bugzilla.gnome.org/show_bug.cgi?id=771773 + +2016-09-26 23:59:29 +1000 Matthew Waters + + * gst/gstelement.c: + element: check for invalid gstcontext's being provided to set_context + https://bugzilla.gnome.org/show_bug.cgi?id=771773 + +2016-10-18 09:38:04 +0530 Nirbheek Chauhan + + * configure.ac: + * meson.build: + build: Apply XCode 8 workaround for iOS too + clock_gettime was also added for iOS 10.0, so don't use it if we're + targetting an older version. That would've caused the symbol to not be + found at runtime on older devices. + +2016-10-15 21:49:21 +0530 Nirbheek Chauhan + + * meson.build: + meson: Don't use c_std=c99 + Just use the default c_std used by the compiler. With GCC on Linux this + is gnu89. + Tons of errors related to time.h, signal.h, etc when using c99: + FAILED: libs/gst/check/libcheck/check@sta/check_run.c.o + cc '-Ilibs/gst/check/libcheck/check@sta' '-fdiagnostics-color=always' '-I../libs/gst/check/libcheck' '-Ilibs/gst/check/libcheck' '-I.' '-I../.' '-Ilibs/gst/check/libcheck/..' '-I../libs/gst/check/libcheck/..' '-pipe' '-Wall' '-Winvalid-pch' '-std=c99' '-DHAVE_CONFIG_H' '-fPIC' '-O2' '-g' '-fPIC' '-MMD' '-MQ' 'libs/gst/check/libcheck/check@sta/check_run.c.o' '-MF' 'libs/gst/check/libcheck/check@sta/check_run.c.o.d' -o 'libs/gst/check/libcheck/check@sta/check_run.c.o' -c ../libs/gst/check/libcheck/check_run.c + In file included from ../libs/gst/check/libcheck/check_run.c:21:0: + ../libs/gst/check/libcheck/libcompat.h:167:18: warning: ‘struct itimerspec’ declared inside parameter list will not be visible outside of this definition or declaration + const struct itimerspec *new_value, struct itimerspec *old_value); + ^~~~~~~~~~ + ../libs/gst/check/libcheck/check_run.c:98:25: error: array type has incomplete element type ‘struct sigaction’ + static struct sigaction old_action[3]; + ^~~~~~~~~~ + ../libs/gst/check/libcheck/check_run.c:99:25: error: array type has incomplete element type ‘struct sigaction’ + static struct sigaction new_action[3]; + ^~~~~~~~~~ + [...] + ninja: build stopped: subcommand failed. + The change was originally made because gnu99 was causing issues on OS X. + +2016-10-14 11:59:24 +0200 Thibault Saunier + + * plugins/tracers/gststats.c: + stats: Fix warning + +2016-10-04 09:20:37 -0300 Thibault Saunier + + * libs/gst/helpers/meson.build: + * meson.build: + * tests/check/meson.build: + meson: Make use of new environment object and set plugin path to builddir + - Properly set where to find gst-plugin-scanner + - Use GST_LOADING_WHITELIST so that only core plugins are used + Bump meson requirement to 0.35 + +2016-10-13 18:20:58 +0200 Sebastian Dröge + + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + controlbinding: Store object in a thread-safe GWeakRef + g_object_weak_ref() is not thread-safe. + +2016-10-13 18:02:38 +0200 Sebastian Dröge + + * libs/gst/controller/gstargbcontrolbinding.c: + argbcontrolbinding: gst_object_replace() is transfer none + +2016-10-13 18:01:14 +0200 Sebastian Dröge + + * libs/gst/controller/gstdirectcontrolbinding.c: + directcontrolbinding: Clarify in the documentation what the difference between absolute and not is + +2016-10-13 17:55:45 +0200 Sebastian Dröge + + * gst/gstcontrolsource.c: + controlsource: Remove misleading sentence from the documentation + control sources are not required to return values between 0.0 and 1.0. + This is completely up to the control binding that is used. + +2016-10-13 17:21:30 +0200 Sebastian Dröge + + * gst/gstobject.c: + object: Fix broken sentence structure in docs + +2016-10-13 12:18:12 +0100 Vincent Penquerc'h + + * plugins/tracers/gststats.c: + tracers: fix structure leak + https://bugzilla.gnome.org/show_bug.cgi?id=772851 + +2016-10-13 12:03:20 +0200 Edward Hervey + + * gst/gststreams.h: + streams: Extend GstStreamType documentation + Users shouldn't assume it will be a single value since it's a flag. + +2016-10-03 20:22:53 +0530 Nirbheek Chauhan + + * configure.ac: + * m4/check-checks.m4: + * meson.build: + build: Fix clock_gettime check with XCode 8 + With XCode 8, clock_gettime will be incorrectly detected as being + available regardless of what OS X version we're targetting because the + symbol is available in the .tbd library as a weak symbol. + See: https://github.com/Homebrew/homebrew-core/issues/3727#issue-170086273 + It's only starting from macOS 10.12 that clock_gettime is actually + available, so we can unconditionally disable it when targetting older + versions. We cannot simply do AC_CHECK_FUNCS with -Wl,-no_weak_imports + because the autoconf check does its own prototype declaration that + doesn't trigger that compiler flag. + https://bugzilla.gnome.org/show_bug.cgi?id=772451 + +2016-10-11 12:12:57 +0200 Edward Hervey + + * gst/gstbin.h: + bin: Add a new GST_BIN_FLAG_STREAMS_AWARE flag + This flag is to indicate to child elements that they can add and + remove pads at any point in time without re-adding existing ones. + Elements should post before-hand a GST_MESSAGE_STREAM_COLLECTION + https://bugzilla.gnome.org/show_bug.cgi?id=772741 + +2016-10-10 10:59:26 +0100 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: paths in env vars are separated by semicolons on windows + https://bugzilla.gnome.org/show_bug.cgi?id=772431 + +2016-10-07 17:02:47 +0200 Guillaume Desmottes + + * docs/design/part-tracing.txt: + docs: fix GST_LEAKS_TRACER_SIG doc + The documentation wasn't mentioning the SIGUSR2 signal. + https://bugzilla.gnome.org/show_bug.cgi?id=772571 + +2016-10-08 17:23:08 +0200 Edward Hervey + + * gst/gstbin.c: + bin: Fix iterator resync'ing + When we get GST_ITERATOR_RESYNC, we need to call gst_iterator_resync() + otherwise we will always get GST_ITERATOR_RESYNC (and that loop would + run forever). + +2016-10-08 13:54:42 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Implement gst_event_full_func handling + Same as we do for queue + +2016-10-08 13:20:58 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + tracer/rusage: fix format string args + The format string contains a process id, but we did not provice one. This + caused us to log garbage since all args got shifted. + +2016-10-01 16:47:05 +0300 Sebastian Dröge + + * gst/gstmessage.c: + message: Fix typo in gst_message_new_progress() docs + test -> text + +2016-09-30 09:57:57 -0300 Thibault Saunier + + * hooks/pre-commit.hook: + * meson.build: + meson: Setup pre-commit hooks when configuring + +2016-09-30 11:38:37 +0100 Tim-Philipp Müller + + * meson.build: + meson: update version + +=== release 1.9.90 === + +2016-09-30 13:01:17 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.9.90 + +2016-09-30 12:08:52 +0300 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2016-09-30 11:41:14 +0300 Sebastian Dröge + + * po/de.po: + po: Update translations + +2016-09-27 18:00:47 +0100 Tim-Philipp Müller + + * meson.build: + * plugins/tracers/meson.build: + meson: tracers: signal availability of libunwind and backtrace() to code + Not setting cdata here on purpose because of .. complications. + +2016-09-26 18:21:19 -0300 Thibault Saunier + + * config.h.meson: + * meson.build: + * plugins/meson.build: + * plugins/tracers/meson.build: + meson: Build tracers + +2016-09-23 20:40:39 -0300 Thibault Saunier + + * docs/gst/meson.build: + * docs/libs/meson.build: + * docs/meson.build: + meson: Fix gtkdoc using new meson features + +2016-09-26 12:14:14 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + * tests/check/gst/gstmeta.c: + tests: remove unused valgrind stuff + Code was also checking the wrong define anyway. + +2016-09-26 12:12:12 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/pipelines/parse-launch.c: + tests: parse-launch: looks clean nowadays, so re-enable for valgrind + Also, the valgrind bits weren't hooked up properly anyway, + checking the wrong define. + +2016-09-24 18:22:26 +0100 Tim-Philipp Müller + + * config.h.meson: + * meson.build: + meson: remove incorrect and unneeded check for ptrdiff_t + Need to include stddef.h for it, so this would've worked: + if cc.has_type('ptrdiff_t', prefix: '#include ') + +2016-09-24 18:06:31 +0100 Tim-Philipp Müller + + * gst/printf/meson.build: + meson: fix internal printf for %ll format modifier on 32-bit systems + gst/gstprintf unit test would fail on 32-bit x86 with: + gstprintf.c:83:printf_I32_I64:0: 'str' (64-bit x value = b5a6978f) is not equal to '"64-bit x value = f1e2d3c4b5a6978f"' + +2016-09-23 04:19:47 +0530 Nirbheek Chauhan + + * gst/meson.build: + Revert "meson: Force gstenum_h to be built when using gst_dep" + This reverts commit cfc565e2d88a8e7d656b68c5c2a1b7acb08cdb7f. + The commit was redundant since gst_gen_sources already contains + gstenum_h. We're still investigating why some people are still seeing + a racy build failure. + +2016-09-23 00:28:53 +0530 Nirbheek Chauhan + + * gst/meson.build: + meson: Force gstenum_h to be built when using gst_dep + This forces gstenumtypes.h to be built whenever something uses gst_dep + as a subproject dependency. This is needed since gst/gst.h includes + gstenumtypes.h + Closes https://github.com/mesonbuild/meson/issues/714 which is not + actually a Meson bug. + +2016-09-19 10:07:51 -0400 Sebastian Dröge + + * gst/gstbin.c: + bin: Add forgotten "git commit --amend" for last commit + Need to cast away the const as g_queue_foreach() takes a non-const GQueue* + +2016-09-19 10:04:55 -0400 Kouhei Sutou + + * gst/gstbin.c: + bin: When copying the sort iterator, also copy its internal queue + Otherwise both iterators share the same references, the second one + usually resulting in a crash when being freed. + https://bugzilla.gnome.org/show_bug.cgi?id=771649 + +2016-09-11 15:28:43 +0200 Carlos Rafael Giani + + * tests/check/elements/queue2.c: + queue2: Fix watermark test + This carries over code for a similar test from multiqueue to ensure full + control over the dataflow while testing. (The previous attempt was racy + since the fill level changed without any thread sync with the test code.) + https://bugzilla.gnome.org/show_bug.cgi?id=771210 + +2016-09-11 15:26:26 +0200 Carlos Rafael Giani + + * plugins/elements/gstqueue2.c: + queue2: Update buffering if its enabled and low/high watermarks are changed + https://bugzilla.gnome.org/show_bug.cgi?id=771210 + +2016-09-15 17:38:49 +0530 Arun Raghavan + + * gst/gstmessage.c: + message: Fix documentation for gst_message_new_duration() + Seems like there was some documentation left over from when this was + gst_message_new_duration(). + +2016-09-12 17:41:16 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Remove unused fields and always use the buffer timestamp difference for calculating the QoS proportion + The buffer timestamps are only hints and more often than not have + nothing to do with reality. + https://bugzilla.gnome.org/show_bug.cgi?id=771306 + +2016-09-08 12:58:54 +0530 Nirbheek Chauhan + + * configure.ac: + * gst/gstconfig.h.in: + * meson.build: + gstconfig: Use __declspec when built with MinGW and linking with MSVC + Earlier we were only using __declspec(dllexport/import) when we were + built with MSVC because when built with MinGW and linking with MinGW we + don't need it (and we get linker errors because of it). + However, when we're built with MinGW and someone wants to link to us + with MSVC, we still need the prototypes to have __declspec(dllimport) + since MSVC cannot do auto-import like GCC can. + https://bugzilla.gnome.org/show_bug.cgi?id=771029 + +2016-09-12 17:07:09 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Also don't *unset* element flags if they're in the suppressed flags + Otherwise our bin might lose various flags that were explicitly set on + it at arbitrary times. + +2016-09-10 11:59:11 -0300 Thiago Santos + + * tests/check/gst/gstbin.c: + tests: gstbin: add tests for suppressed flags + Some simple tests to make sure it keeps working + +2016-09-02 17:39:17 +0900 Wonchul Lee + + * gst/gstbin.c: + * gst/gstbin.h: + * win32/common/libgstreamer.def: + bin: Add setter and getter to suppress element flags + Suppress-flags is for preventing propagation of child element's specific + flag when it is added to the bin. + https://bugzilla.gnome.org/show_bug.cgi?id=770627 + +2016-09-10 20:50:48 +1000 Jan Schmidt + + * autogen.sh: + * common: + Automatic update of common submodule + From b18d820 to f980fd9 + +2015-11-13 16:00:02 +0000 Graham Leggett + + * gst/gst.c: + gst: Ensure gst_value is initialised before gst_tag + Otherwise GST_TYPE_FRACTION will work correctly in tags. + https://bugzilla.gnome.org/show_bug.cgi?id=753922 + +2016-09-09 11:46:11 +0300 Sebastian Dröge + + * gst/gstutils.c: + element: Reset the stop position to NONE in seek_simple() + When using seek_simple() in combination with other kinds of seeks, this + becomes problematic. seek_simple() does not reset the stop position to + GST_CLOCK_TIME_NONE but keeps whatever a previous seek did. So for example + when doing a seek_simple() after a rate=-1 seek, we would usually get + assertions that start>stop (and stop being the old stop from the rate=1 seek). + https://bugzilla.gnome.org/show_bug.cgi?id=771104 + +2016-09-10 09:53:42 +1000 Jan Schmidt + + * autogen.sh: + * common: + Automatic update of common submodule + From f49c55e to b18d820 + +2016-09-09 09:36:40 -0300 Thibault Saunier + + * tests/check/meson.build: + meson:tests: Bump timeout to 3 minutes + Basically we already have each test with a 20sec timeout, + and testsuite can last more than the default 30secs from + meson. 3 minutes is another arbitrary timeout but should + be good enough. + +2016-09-08 15:19:38 +0300 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Use the average durations based on timestamps for the QoS proportion when doing trickmodes + The durations of the buffers are (usually) assuming that no frames are being + dropped and are just the durations coming from the stream. However if we do + trickmodes, frames are being dropped regularly especially if only key units + are supposed to be played. + Fixes completely bogus QoS proportion values in the above case. + +2016-09-05 18:07:49 -0300 Thibault Saunier + + * meson.build: + meson: Fix building with meson 0.34 + +2016-08-26 20:06:59 -0300 Thibault Saunier + + * gst/meson.build: + * meson.build: + * meson_options.txt: + meson: Allow others to build GIR files when using GStreamer as subproject + And add a way to disable the introspection and bump version to 1.9.2 + +2016-09-05 11:11:29 +0300 Sebastian Dröge + + * gst/gstconfig.h.in: + gstconfig.h.in: Add another version of the SH4 #define and S390x + https://bugzilla.gnome.org/show_bug.cgi?id=770731 + +2016-09-05 09:50:17 +0200 Wim Taymans + + * gst/gstconfig.h.in: + config: newer gcc doesn't know __ppc__ and __ppc64__ anymore + __ppc__ and __ppc64__ are non-standard defines, we should use + __powerpc__ and __powerpc64__ instead because newer gcc doesn't know + them anymore. + +2016-09-04 20:39:31 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: add * for pointer signal arguments where needed + Print GObject argument properly with pointer marker: + "client-added" : void user_function (GstElement* object, + GObject* arg0, + gpointer user_data); + instead of + "client-added" : void user_function (GstElement* object, + GObject arg0, + gpointer user_data); + for gst-inspect-1.0 tcpserversink. + +2016-09-02 23:22:17 +0100 Tim-Philipp Müller + + * tests/Makefile.am: + tests: don't build misc subdir if both examples and benchmarks have been disabled + https://bugzilla.gnome.org/show_bug.cgi?id=770740 + +2016-09-01 14:13:40 +0200 Wim Taymans + + * gst/gstconfig.h.in: + config: support System z + +2016-09-01 12:25:23 +0300 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.9.2 === + +2016-09-01 12:24:45 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.9.2 + +2016-09-01 11:22:45 +0300 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations + +2016-08-31 09:49:03 +0200 Carlos Rafael Giani + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + multiqueue: Add higher-resolution low/high-watermark properties + low/high-watermark are of type double, and given in range 0.0-1.0. This + makes it possible to set low/high watermarks with greater resolution, + which is useful with large multiqueue max sizes and watermarks like 0.5%. + Also adding a test to check the fill and watermark level behavior. + https://bugzilla.gnome.org/show_bug.cgi?id=770628 + +2016-08-31 09:48:53 +0200 Carlos Rafael Giani + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Distinguish between buffering percentage and buffering level + To make the code clearer, and to facilitate future improvements, introduce + a distinction between the buffering level and the buffering percentage. + Buffering level: the queue's current fill level. The low/high watermarks + are in this range. + Buffering percentage: percentage relative to the low/high watermarks + (0% = low watermark, 100% = high watermark). + To that end, get_percentage() is renamed to get_buffering_level(). Also, + low/high_percent are renamed to low/high_watermark to avoid confusion. + mq->buffering_percent values are now normalized in the 0..100 range for + buffering messages inside update_buffering(), and not just before sending + the buffering message. Finally the buffering level range is parameterized + by adding a new constant called MAX_BUFFERING_LEVEL. + https://bugzilla.gnome.org/show_bug.cgi?id=770628 + +2016-08-31 09:48:38 +0200 Carlos Rafael Giani + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Rename percent/percent_changed to buffering_percent(_changed) + This is a prerequisite for subsequent commits, and makes queue2 and + multiqueue code a little more consistent. + https://bugzilla.gnome.org/show_bug.cgi?id=770628 + +2016-08-23 14:57:33 +0900 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix high_time wakeup logic + When calculating the high_time, cache the group value in each singlequeue. + This fixes the issue by which wake_up_next_non_linked() would use the global + high-time to decide whether to wake-up a waiting thread, instead of the group + one, resulting in those threads constantly spinning. + Tidy up a bit the waiting logic while we're at it. + With this patch, we go from 212% playing a 8 audio / 8 video file down to less + than 10% (most of it being the video decoding). + https://bugzilla.gnome.org/show_bug.cgi?id=770225 + +2016-08-28 16:02:14 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: don't print internal pad request function name + This just confuses people, they look at it and try to call it + directly by name, instead of using the public GstElement API. + It stands to reason that it goes without saying that when an + element provides request pads that they can actually be + requested using the standard API, and there's no point in + printing internal implementation details of the element. + +2016-08-23 13:27:58 -0300 Thibault Saunier + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + Make use of the new GST_ELEMENT_FLOW_ERROR API all around. + https://bugzilla.gnome.org/show_bug.cgi?id=770158 + +2016-08-23 13:27:20 -0300 Thibault Saunier + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.h: + element: Add API to more easily post messages about flowing issues + In many parts of the code we raise streaming error when the flow + goes wrong, and each time we create more or less similare error + message. Also that message does not let the application know what + has actually gone wrong. In the new API we add a "flow-return" detail + field inside the GstMessage so that the application has all the information + if it needs it. + API: + GST_ELEMENT_FLOW_ERROR + https://bugzilla.gnome.org/show_bug.cgi?id=770158 + +2016-08-26 19:27:22 +0530 Nirbheek Chauhan + + * configure.ac: + * gst/gstconfig.h.in: + * meson.build: + gstconfig: Decide GST_EXPORT declaration style at build time + We only use GST_EXPORT consistently when building with MSVC by using the + visual studio definitions files (win32/common/*.def), so always disable + it when building with Autotools and only enable it with Meson when + building with MSVC. + This allows you to use MinGW to link to a GStreamer built with MSVC and + get the correct function prototypes to find functions and variables in + DLLs. + +2016-08-26 16:21:30 +0900 Wonchul Lee + + * docs/design/part-stream-selection.txt: + docs: fix typo in stream selection docs + https://bugzilla.gnome.org//show_bug.cgi?id=770428 + +2016-08-26 12:55:04 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: rename gst_element_message_new_details() to gst_make_element_message_details() + Fixes g-i warning "Gst: Constructor return type mismatch + symbol='gst_element_message_new_details' constructed='Gst.Element' + return='Gst.Structure'". + This is a newly-added function in git that has not been in a stable + release yet, so it's fine to rename it. It's also only used indirectly + via macros. + +2016-08-26 12:35:23 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + * gst/gstmessage.c: + * gst/gsttracerutils.c: + docs: fix various gtk-doc warnings + e.g. "warning: multi-line since docs found" + +2016-08-26 12:04:33 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + g-i: info: allow passing NULL to gst_debug_remove_log_function() + Useful for removing the default handler from bindings. + +2016-08-25 15:04:06 -0300 Thibault Saunier + + * docs/gst/meson.build: + * docs/libs/meson.build: + * meson.build: + meson: doc: Fix building documentation when using subprojects + and check the presence of gtk-doc before building the documentation + +2016-08-26 03:17:41 +1000 Jan Schmidt + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Implement can_intersect for GstFlagSet types + Make sure that gst_value_can_intersect returns TRUE + for GstFlagSet combinations that can successfully + intersect + +2016-08-03 15:20:20 +0200 Carlos Rafael Giani + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + * tests/check/elements/queue2.c: + queue2: Add higher-resolution low/high-watermark properties + low/high-watermark are of type double, and given in range 0.0-1.0. This + makes it possible to set low/high watermarks with greater resolution, + which is useful with large queue2 max sizes and watermarks like 0.5%. + Also adding a test to check the fill and watermark level behavior. + https://bugzilla.gnome.org/show_bug.cgi?id=769449 + +2016-08-03 15:27:40 +0200 Carlos Rafael Giani + + * plugins/elements/gstqueue2.c: + queue2: Distinguish between buffering percentage and buffering level + To make the code clearer, and to facilitate future improvements, introduce + a distinction between the buffering level and the buffering percentage. + Buffering level: the queue's current fill level. The low/high watermarks + are in this range. + Buffering percentage: percentage relative to the low/high watermarks + (0% = low watermark, 100% = high watermark). + To that end, get_buffering_percent() is renamed to get_buffering_level(), + and the code at the end that transforms to the buffering percentage is + factored out into a new convert_to_buffering_percent() function. Also, + the buffering level range is parameterized by adding a new constant called + MAX_BUFFERING_LEVEL. + https://bugzilla.gnome.org/show_bug.cgi?id=769449 + +2016-08-23 10:52:32 +0100 Tim-Philipp Müller + + * docs/random/release: + docs: release: add tag signing command + +2016-07-07 08:01:24 +0200 Arjen Veenhuizen + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add explicit getters and setters for buffer flags + These can be used from bindings. + https://bugzilla.gnome.org/show_bug.cgi?id=768301 + +2016-08-22 00:01:46 +0100 Tim-Philipp Müller + + * libs/gst/check/meson.build: + meson: install libgstcheck-1.0 and add api version to name + +2016-08-20 08:54:27 +0900 Hoonhee Lee + + * gst/gststreams.c: + streams: update and emit notify signal only if taglist actually changed + https://bugzilla.gnome.org/show_bug.cgi?id=770161 + +2016-08-12 20:25:17 +0530 Nirbheek Chauhan + + * .gitignore: + * config.h.meson: + * docs/gst/meson.build: + * docs/libs/meson.build: + * docs/meson.build: + * gst/build_mkenum.py: + * gst/meson.build: + * gst/parse/gen_grammar.py.in: + * gst/parse/gen_lex.py.in: + * gst/parse/meson.build: + * gst/printf/meson.build: + * libs/gst/base/meson.build: + * libs/gst/check/libcheck/meson.build: + * libs/gst/check/meson.build: + * libs/gst/controller/meson.build: + * libs/gst/helpers/meson.build: + * libs/gst/meson.build: + * libs/gst/net/meson.build: + * libs/meson.build: + * meson.build: + * meson_options.txt: + * pkgconfig/meson.build: + * plugins/elements/meson.build: + * plugins/meson.build: + * po/meson.build: + * tests/benchmarks/meson.build: + * tests/check/meson.build: + * tests/examples/adapter/meson.build: + * tests/examples/controller/meson.build: + * tests/examples/helloworld/meson.build: + * tests/examples/memory/meson.build: + * tests/examples/meson.build: + * tests/examples/netclock/meson.build: + * tests/examples/ptp/meson.build: + * tests/examples/stepping/meson.build: + * tests/examples/streamiddemux/meson.build: + * tests/examples/streams/meson.build: + * tests/meson.build: + * tests/misc/meson.build: + * tools/meson.build: + Add support for Meson as alternative/parallel build system + https://github.com/mesonbuild/meson + With contributions from: + Tim-Philipp Müller + Mathieu Duponchelle + Jussi Pakkanen (original port) + Highlights of the features provided are: + * Faster builds on Linux (~40-50% faster) + * The ability to build with MSVC on Windows + * Generate Visual Studio project files + * Generate XCode project files + * Much faster builds on Windows (on-par with Linux) + * Seriously fast configure and building on embedded + ... and many more. For more details see: + http://blog.nirbheek.in/2016/05/gstreamer-and-meson-new-hope.html + http://blog.nirbheek.in/2016/07/building-and-developing-gstreamer-using.html + Building with Meson should work on both Linux and Windows, but may + need a few more tweaks on other operating systems. + +2016-08-13 13:55:15 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * pkgconfig/gstreamer.pc.in: + Move gstconfig.h back to normal include dir + Now that it's arch-independent again. Will need fixes in cerbero too. + +2016-06-21 18:59:49 +0530 Nirbheek Chauhan + + * configure.ac: + * gst/gstconfig.h.in: + gstconfig.h: Detect unaligned access support at compile-time + This makes gstconfig.h completely arch-independent. Should cover all + compilers that gstreamer is known to build on, and all architectures + that I could find information on. People are encouraged to file bugs if + their platform/arch is missing. + +2016-08-13 09:55:46 +0100 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstclock.c: + * gst/gstconfig.h.in: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gsttrace.c: + * gst/gsttrace.h: + * po/POTFILES.in: + * tests/check/Makefile.am: + * win32/common/gstconfig.h: + * win32/common/libgstreamer.def: + Remove old alloc tracing code now that we have a GstTracer-based replacement + It's been internal API only in 1.x. + +2016-08-12 16:15:25 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Post buffering messages earlier in ringbuffer mode + In ringbuffer mode we need to make sure we post buffering messages *before* + blocking to wait for data to be drained. + Without this, we would end up in situations like this: + * pipeline is pre-rolling + * Downstream demuxer/decoder has pushed data to all sinks, and demuxer thread + is blocking downstream (i.e. not pulling from upstream/queue2). + * Therefore pipeline has pre-rolled ... + * ... but queue2 hasn't filled up yet, therefore the application waits for + the buffering 100% messages before setting the pipeline to PLAYING + * But queue2 can't post that message, since the 100% message will be posted + *after* there is room available for that last buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=769802 + +2016-08-08 16:42:06 +0200 Josep Torra + + * plugins/elements/gstmultiqueue.c: + multiqueue: removed redundant call to g_thread_self + Remove an unneeded call to g_thread_self and minor coding style fix. + +2016-03-16 18:00:15 +1100 Jan Schmidt + + * plugins/elements/gstinputselector.c: + inputselector: Handle stream-group-done + Handle the new stream-group-done message to unblock pads which + are waiting for the running time to advance on that group. + https://bugzilla.gnome.org/show_bug.cgi?id=768995 + +2016-03-14 14:20:42 +1100 Jan Schmidt + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstpad.c: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstevent.c: + * win32/common/libgstreamer.def: + events: Implement the stream-group-done event + A new event which precedes EOS in situations where we + need downstream to unblock any pads waiting on a stream + before we can send EOS. E.g, decodebin draining a chain + so it can switch pads. + https://bugzilla.gnome.org/show_bug.cgi?id=768995 + +2016-07-25 11:22:36 +0200 Carlos Rafael Giani + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstmessage.c: + * win32/common/libgstreamer.def: + message: Add redirect message + Redirection messages are already used in fragmented sources and in + uridecodebin, so it makes sense to introduce these as an official message + type. + https://bugzilla.gnome.org/show_bug.cgi?id=631673 + +2016-07-25 19:15:15 +1000 Jan Schmidt + + * plugins/elements/gstinputselector.c: + inputselector: Wake other pads when selected goes EOS + Other pads that are waiting for the stream on the selected + pad to advance before they finish waiting themselves + should be given the chance to do so when the selected pad + goes EOS. Fixes problems where input streams can end up + waiting forever if the active stream goes EOS earlier than + their own end time. + +2016-07-24 01:35:41 +0100 Tim-Philipp Müller + + * gst/gstelement.h: + element: fix GST_ELEMENT_ERROR() error code expansion + In some corner cases, the error 'code' part passed to + GST_ELEMENT_ERROR() is a valid define as well, in which + case it won't survive two levels of macro expansion, but + only one. Fixes: + oss4-sink.c: In function ‘gst_oss4_sink_open’: + error: ‘GST_RESOURCE_ERROR_0x00000002’ undeclared (first use in this function) + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, + which is from GST_ELEMENT_ERROR(el,RESOURCE,OPEN_WRITE,..) + and OPEN_WRITE happens to be defined to 2 here. + https://bugzilla.gnome.org/show_bug.cgi?id=756806 + https://bugzilla.gnome.org/show_bug.cgi?id=769117 + +2016-07-22 17:32:33 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + message: fix some nonsensical annotations + +2016-07-22 15:25:09 +0100 Vincent Penquerc'h + + * docs/gst/gstreamer-sections.txt: + docs: add GST_ELEMENT_*_WITH_DETAILS to doc list + +2016-07-22 15:04:58 +0100 Vincent Penquerc'h + + * docs/gst/gstreamer-sections.txt: + docs: list new message details apis where they seem to belong + +2016-07-22 14:59:56 +0100 Vincent Penquerc'h + + * win32/common/libgstreamer.def: + libgstreamer.def: fix mentions of new message details api + I had not updated it after the review changes + +2016-03-02 11:22:23 +0000 Vincent Penquerc'h + + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * tests/check/gst/gstmessage.c: + * win32/common/libgstreamer.def: + message: new API for additional custom data to error messages + https://bugzilla.gnome.org/show_bug.cgi?id=756806 + +2016-07-20 12:22:10 +0200 Guillaume Desmottes + + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + tracers: leaks: update type filter later for unknown types + This allow us to filter using an object type which is implemented + by a plugin like, say, GstGtkGLSink. + https://bugzilla.gnome.org/show_bug.cgi?id=768989 + +2016-07-19 14:45:53 +0200 Aurélien Zanelli + + * libs/gst/base/gstcollectpads.c: + collectpads: add g-i transfer annotations to peek/pop/read_buffer/take_buffer functions + https://bugzilla.gnome.org/show_bug.cgi?id=768948 + +2016-07-19 23:18:24 +1000 Jan Schmidt + + * tests/check/libs/gstnetclientclock.c: + tests: Use gst_clock_wait_for_sync () for net client clock + Instead of looping, use the gst_clock_wait_for_sync() function + to give clocks up to 1 second to synchronise + +2016-07-13 15:43:21 +0200 Guillaume Desmottes + + * gst/gstmessage.c: + message: fix annotation of parse_stream_{collection,streams_selected} + gst_structure_id_get() returns a new reference so the returned object is + actually (transfer full). + The unit tests was already unreffing the objects. + https://bugzilla.gnome.org/show_bug.cgi?id=768776 + +2016-07-13 15:43:21 +0200 Guillaume Desmottes + + * gst/gstdevicemonitor.c: + * gst/gstmessage.c: + message: fix annotation of parse_device_{added,removed} + gst_structure_id_get() returns a new reference so the returned device is + actually (transfer full). + The code using this API was already correct but the code example in + comments was not. + https://bugzilla.gnome.org/show_bug.cgi?id=768776 + +2016-07-14 16:40:22 +0200 Guillaume Desmottes + + * gst/gstpad.c: + pad: add g-i transfer annotatation to _store_sticky_event() + For clarity. + https://bugzilla.gnome.org/show_bug.cgi?id=768810 + +2016-07-12 12:32:56 +0300 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Fix automatic-eos=false mode if a segment.stop is given + If segment.stop was given, and the subclass provides a size that might be + smaller than segment.stop and also smaller than the actual size, we would + already stop there. + Instead try reading up to segment.stop, the goal is to ignore the (possibly + inaccurate) size the subclass gives and finish until segment.stop or when the + subclass tells us to stop. + +2016-07-11 21:13:28 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From f363b32 to f49c55e + +2016-07-11 18:45:49 +0530 Nirbheek Chauhan + + * tests/benchmarks/capsnego.c: + benchmarks: Fix potential stack corruption in capsnego test + flavour_str is a non-const pointer that will be written to if the -f + option is passed + +2016-07-11 11:34:02 +0200 Guillaume Desmottes + + * plugins/tracers/gstleaks.c: + leaks: check return values of libunwind calls + +2016-07-11 09:58:47 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Fix average input rate calculation on small input range + When dealing with small-ish input data coming into queue2, such as + adaptivedemux fragments, we would never take into account the last + <200ms of data coming in. + The problem is that usually on TCP connection the download rate + gradually increases (i.e. the rate is lower at the beginning of a + download than it is later on). Combined with small download time (less + than a second) we would end up with a computed average input rate + which was sometimes up to 30-50% off from the *actual* average input + rate for that fragment. + In order to fix this, force the average input rate calculation when + we receive an EOS so that we take into account that final window + of data. + https://bugzilla.gnome.org/show_bug.cgi?id=768649 + +2016-07-08 16:31:56 +0200 Guillaume Desmottes + + * gst/gstminiobject.c: + miniobject: weak_unref: display the pointer of the object if failing + That's generally the most useful information to help debugging the + problem. + https://bugzilla.gnome.org/show_bug.cgi?id=768579 + +2016-07-08 16:29:38 +0200 Guillaume Desmottes + + * gst/gstbin.c: + bin: properly display the type of the removed message + Makes debugging easier. + https://bugzilla.gnome.org/show_bug.cgi?id=768579 + +2016-07-08 17:46:06 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + element: re-create threadpool after cleaning up tasks + We don't free this from gst_deinit() but from gst_task_cleanup_all(), + so more GStreamer API may be called. In particular makes unit tests + work again with CK_FORK=no. + https://bugzilla.gnome.org/show_bug.cgi?id=768577 + +2016-07-08 16:53:51 +0200 Guillaume Desmottes + + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks: warn if object is destroyed while the tracer is disposing + This should not happen and generally means some thread is still running. + https://bugzilla.gnome.org/show_bug.cgi?id=768578 + +2016-07-08 16:36:01 +0200 Guillaume Desmottes + + * gst/gst_private.h: + * gst/gstelement.c: + * gst/gsttask.c: + element: clean up thread pool from gst_task_cleanup_all() + This ensures that all async operations (started from gst_element_call_async()) + have been completed and so there is no extra thread running. + Fix races when checking for leaks on unit tests as some of those + operations were still running when the leaks tracer was checking for + leaked objects. + https://bugzilla.gnome.org/show_bug.cgi?id=768577 + +2016-07-08 11:15:06 +0200 Guillaume Desmottes + + * configure.ac: + * plugins/tracers/gstleaks.c: + leaks tracer: use G_OS_UNIX to check for signal support + Checking for signal.h is not good enough as it's present in Windows. + Those signals are UNIX specific anyway. + https://bugzilla.gnome.org/show_bug.cgi?id=767857 + +2016-06-22 16:25:16 +0200 Guillaume Desmottes + + * configure.ac: + * docs/design/part-tracing.txt: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks tracer: add creation stack trace support + This allow us to provide the trace of leaked objects making it easier + to debug. + https://bugzilla.gnome.org/show_bug.cgi?id=767862 + +2016-06-01 11:08:39 +0200 Guillaume Desmottes + + * docs/design/part-tracing.txt: + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + leaks tracer: add checkpoint support using SIGUSR2 + https://bugzilla.gnome.org/show_bug.cgi?id=767857 + +2016-05-31 16:56:26 +0200 Guillaume Desmottes + + * configure.ac: + * docs/design/part-tracing.txt: + * plugins/tracers/gstleaks.c: + leaks tracer: log alive objects when receiving SIGUSR1 + We don't want to automatically catch signals so use an env variable to + enable this feature. + https://bugzilla.gnome.org/show_bug.cgi?id=767857 + +2016-07-07 13:15:51 +0300 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Only forward sticky events on GAP events if needed + That is, if the active pad changed and if forwarding of sticky events is + requested at all. We otherwise forward events too often. + +2016-07-05 16:50:16 +0200 Miguel París Díaz + + * gst/gstpad.c: + pad: check query caps answered and caps not NULL + https://bugzilla.gnome.org/show_bug.cgi?id=768450 + +2016-07-06 13:50:56 +0300 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.9.1 === + +2016-07-06 13:05:02 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 1.9.1 + +2016-07-06 11:37:56 +0300 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2016-07-06 10:17:37 +0300 Sebastian Dröge + + * po/da.po: + * po/hr.po: + * po/pt_BR.po: + * po/sk.po: + po: Update translations + +2016-07-05 12:17:18 +0200 Jan Alexander Steffens (heftig) + + * libs/gst/base/gstbaseparse.c: + baseparse: Don't add calculated bitrates until threshold + Waiting before posting calculated bitrates seems to be the + intent of the code, so avoid adding them to the tag list + pushed with the first frame. + When the threshold is reached, gst_base_parse_update_bitrates + sets tags_changed, so this posts the calculated ones right + that moment. + This prevents an insane average calculated from just the + first (key) frame from getting posted. + https://bugzilla.gnome.org/show_bug.cgi?id=768439 + +2016-07-04 10:00:38 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Make sure to not create an invalid event order when generating the default CAPS event because of a GAP event + There must be a SEGMENT event before the GAP event, and SEGMENT events must + come after any CAPS event. We however did not produce any CAPS yet, so we need + to ensure to insert the CAPS event before the SEGMENT event into the pending + events list. + https://bugzilla.gnome.org/show_bug.cgi?id=766970 + +2016-07-01 22:34:59 +1000 Jan Schmidt + + * gst/gstinfo.h: + gstinfo: Avoid gcc 6 warning that breaks the tests build + gcc 6 has problems detecting and avoiding throwing + a warning for tautological compares in macros (they + should only trigger for compares outside macros). + Avoid them with a nasty cast of one parameter to void * + https://bugzilla.gnome.org/show_bug.cgi?id=764526 + +2016-07-01 09:44:12 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix behaviour with not-linked and eos pads + This is an update on c9b6848885f4675d447e823c8fb117e247658252 + multiqueue: Fix not-linked pad handling at EOS + While that commit did fix the behaviour if upstream sent a GST_EVENT_EOS, + it would break the same issue when *downstream* returns GST_FLOW_EOS + (which can happen for example when downstream decoders receive data + from after the segment stop). + GST_PAD_IS_EOS() is only TRUE when a GST_EVENT_EOS has flown through it + and not when a GST_EVENT_EOS has gone through it. + In order to handle both cases, also take into account the last flow + return. + https://bugzilla.gnome.org/show_bug.cgi?id=763770 + +2016-06-30 15:07:28 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gststreamcollection.c: + * gst/gststreamcollection.h: + * gst/gststreams.c: + * gst/gstutils.c: + streams: sprinkle some Since: markers for docs + +2016-06-30 14:37:17 +0100 Tim-Philipp Müller + + * plugins/elements/gstmultiqueue.c: + multiqueue: add gtk-doc blurb for new pad property + +2016-02-10 11:42:04 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Add a pad property to "group" streams + When syncing by running time, multiqueue will throttle unlinked streams + based on a global "high-time" and the pending "next_time" of a stream. + The idea is that we don't want unlinked streams to be "behind" the global + running time of linked streams, so that if/when they get linked (like when + switching tracks) decoding/playback can resume from the same position as + the other streams. + The problem is that it assumes elements downstream will have a more or less + equal buffering/latency ... which isn't the case for streams of different + type. Video decoders tend to have higher latency (and therefore consume more + from upstream to output a given decoded frame) compared to audio ones, resulting + in the computed "high_time" being at the position of the video stream, + much further than the audio streams. + This means the unlinked audio streams end up being quite a bit after the linked + audio streams, resulting in gaps when switching streams. + In order to mitigate this issue, this patch adds a new "group-id" pad property + which allows users to "group" streams together. Calculating the high-time will + now be done not only globally, but also per group. This ensures that within + a given group unlinked streams will be throttled by that group's high-time + instead. + This fixes gaps when switching downstream elements (like switching audio tracks). + +2015-06-12 10:53:23 +0200 Edward Hervey + + * docs/design/part-stream-selection.txt: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gststreamcollection.c: + * gst/gststreamcollection.h: + * gst/gststreams.c: + * gst/gststreams.h: + * gst/gstutils.c: + * gst/gstutils.h: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gststream.c: + * tests/check/gst/gststream.h: + * win32/common/libgstreamer.def: + gst: New Stream listing/selection system + * GstStream + * GstStreamCollection + * GST_EVENT_SELECT_STREAMS + * GST_MESSAGE_STREAM_COLLECTION + +2016-06-29 23:24:02 +0200 Sebastian Dröge + + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstpoll.c: + poll: #define EWOULDBLOCK to EAGAIN if it's not defined on Windows + +2016-06-29 14:05:18 +0200 Sebastian Dröge + + * gst/gstbufferpool.c: + bufferpool: Fix handling of the GstPoll + Especially if multiple threads are waiting for buffers to be available again, + the current code was wrong. Fix this and document clearly how the GstPoll is + supposed to be used. + Also fix some potential races with reading from the GstPoll before writing + actually happened. + https://bugzilla.gnome.org/show_bug.cgi?id=767979 + +2016-06-29 14:02:55 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Make sure to always read the control after popping a message + It might happen that we popped the message before writing of the control + happened. In this case we just have to retry again a bit later, and failure to + do so will cause an additional byte in the control and the GSource / + gst_poll_wait() to always wake up again immediately. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-29 13:37:28 +0200 Sebastian Dröge + + * gst/gstsystemclock.c: + systemclock: Improve GstPoll handling and don't check for impossible errno values + Also just read/write control every time, GstPoll is optimized by itself + already to only do I/O if switching between empty and one byte. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-29 13:35:35 +0200 Sebastian Dröge + + * gst/gstpoll.c: + poll: Clarify when FALSE is returned from read/write_control() + And also mention what the expected values of errno are going to be. + write_control() will only ever return FALSE if there was a critical error. It + will never return because of EINTR, EAGAIN or EWOULDBLOCK. + read_control() will return FALSE if there was no byte to read, in which case + errno would be EWOULDBLOCK. + In all other cases there was a critical error. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-29 13:26:57 +0200 Sebastian Dröge + + * gst/gstpoll.c: + poll: set_controllable(), restart() and set_flushing() are only valid for non-timer GstPolls + On timer GstPolls it will cause the control socket state to become + inconsistent as now one less read_control() than write_control() be would + needed. + Similarly, read_control() and write_control() are only valid on timer + GstPolls. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-29 13:11:01 +0200 Sebastian Dröge + + * gst/gstpoll.h: + poll: Warn if the return value of gst_poll_read_control() is unused + This might fail even under correct usage, e.g. if read_control() is called + from another thread before write_control() finished in another. It has to be + retried then, or other measures have to be taken, depending on how it is used + by the surrounding code. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-29 18:57:42 +0200 Matthew Gruenke + + * gst/gstpoll.c: + poll: Fix various race conditions with read_control() and write_control() + This addresses slightly different race conditions on Linux and Windows, and + fixes gst_poll_read_control() when control_pending == 0. + On Linux, the socketpair() used for control should not be made O_NONBLOCK. + If there's any propagation delay between set->control_write_fd.fd and + set->control_read_fd.fd, even the mutex now held will not be sufficient to + prevent a race condition. There's no benefit to using O_NONBLOCK, here. + Only liabilities. + For Windows, it's necessary to fix the race condition between testing + set->control_pending and performing WAKE_EVENT()/RELEASE_EVENT(). This is + accomplished by acquiring and holding set->lock, for both of these operations. + We could optimize the Linux version by making this Windows-specific. + For consistency with the Linux implementation, Windows' RELEASE_EVENT() + has also been made to block, although it should never happen. + Also, changed release_wakeup() to return TRUE and decrement control_pending + only when > 0. Furthermore, RELEASE_EVENT() is called only when + control_pending == 1. + Finally, changed control_pending to use normal, non-atomic arithmetic + operations, since it's now protected by set->lock. + Note: even though the underlying signaling mechanisms are blocking, + release_wakeup() is effectively non-blocking, as it will only attempt to read + from control_read_fd.fd after a byte has been written to control_write_fd.fd + or WaitForSingleObject() after it's been signaled. + https://bugzilla.gnome.org/show_bug.cgi?id=750397 + +2016-06-28 15:01:17 +0200 Guillaume Desmottes + + * gst/gstbus.c: + bus: chain up GObject::constructed() to the parent class' implementation + Needed so GstBus can be tracked by the leaks tracer. + https://bugzilla.gnome.org/show_bug.cgi?id=768141 + +2016-06-24 05:26:09 +0530 Nirbheek Chauhan + + * gst/gstconfig.h.in: + gstconfig.h: Don't use extern with dllexport + GCC emits an error for this with -Werror: + plugin.c:22:1: error: 'gst_plugin_desc' initialized and declared 'extern' [-Werror] + This matches how glib does symbol exporting. + https://bugzilla.gnome.org/show_bug.cgi?id=767463 + +2016-06-21 19:49:15 +0530 Nirbheek Chauhan + + * configure.ac: + * gst/gstconfig.h.in: + win32: Don't use dllexport/import when only building statically + If the prototypes in the public API have dllimport in them when building + statically on Windows, the compiler will look for symbols with symbol + mangling and indirection corresponding to a DLL. This will cause a build + failure when trying to link tests/examples/etc. + External users of GStreamer also need to define -DGST_STATIC_COMPILATION + if they want to link to static gstreamer libraries on Windows. + A similar version of this patch has been committed to all gstreamer + repositories. + https://bugzilla.gnome.org/show_bug.cgi?id=767463 + +2016-06-21 11:45:26 -0400 Nicolas Dufresne + + * common: + Automatic update of common submodule + From ac2f647 to f363b32 + +2016-06-15 16:24:27 +0100 Vincent Penquerc'h + + * tests/check/elements/queue2.c: + tests: add a test for small ring buffer sizes + https://bugzilla.gnome.org/show_bug.cgi?id=767688 + +2016-06-15 13:43:59 +0100 Vincent Penquerc'h + + * plugins/elements/gstqueue2.c: + queue2: fix crash deleting current region for small ring buffers + Ensure we do not attempt to destroy the current range. Doing so + causes the current one to be left dangling, and it may be dereferenced + later, leading to a crash. + This can happen with a very small queue2 ring buffer (10000 bytes) + and 4 kB buffers. + repro case: + gst-launch-1.0 fakesrc sizetype=2 sizemax=4096 ! \ + queue2 ring-buffer-max-size=1000 ! fakesink sync=true + https://bugzilla.gnome.org/show_bug.cgi?id=767688 + +2016-06-20 11:34:49 +0100 Tim-Philipp Müller + + * tests/check/gst/gstobject.c: + tests: gstobject: fix typo in test name + +2016-06-16 14:08:01 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-tracing.txt: + docs/design/part-tracing: fix reference to renamed func + +2016-06-08 12:34:53 -0400 Nicolas Dufresne + + * plugins/elements/gsttee.c: + tee: Properly handle return value when only 1 pad + This patch handle the case when you have 1 pad (so the fast path is + being used) but this pad is removed. If we are in allow-not-linked, we + should return GST_FLOW_OK, otherwise, we should return GST_FLOW_UNLINKED + and ignore the meaningless return value obtained from pushing. + https://bugzilla.gnome.org/show_bug.cgi?id=767413 + +2016-06-16 15:52:16 +0200 Stefan Sauer + + * scripts/gst-plot-traces.sh: + gst-plot-traces.sh: add a script to plot gst-tracer graphs + The script extracts cpu-usage data from a tracelog and plots it via gnuplot. + +2016-06-15 16:12:23 +0200 Sebastian Dröge + + * gst/gstdevice.c: + device: Fix typo + paramater -> parameter + +2016-06-14 19:16:33 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + info: flesh out GST_PTR_FORMAT docs a bit + +2016-06-13 18:33:27 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Update start time when losing state only if we were in PLAYING + If we were in PAUSED, the current clock time and base time don't have much to + do with the running time anymore as the clock might have advanced while we + were PAUSED. The system clock does that for example, audio clocks often don't. + Updating the start time in PAUSED will cause a) the wrong position to be + reported, b) step events to step not just the requested amount but the amount + of time we spent in PAUSED. The start time should only ever be updated when + going from PLAYING to PAUSED to remember the current running time (to be able + to compensate later when going to PLAYING for the clock time advancing while + PAUSED), not when we are already in PAUSED. + Based on a patch by Kishore Arepalli + The updating of the start time when the state is lost was added in commit + ba943a82c0bbfd17c9ee9f5068d44c9d9274fd13 to fix the position reporting when + the state is lost. This still works correctly after this change. + https://bugzilla.gnome.org/show_bug.cgi?id=739289 + +2016-06-11 22:18:06 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Log pad offsets as signed times + +2016-06-11 21:56:19 +0300 Sebastian Dröge + + * tests/check/gst/gstpad.c: + pad: Also check the number of segment events and if other serialized events and queries trigger segment updating too + https://bugzilla.gnome.org/show_bug.cgi?id=765049 + +2016-06-11 21:37:47 +0300 Sebastian Dröge + + * tests/check/gst/gstpad.c: + pad: Add unit test for pad offset handling on src pads + https://bugzilla.gnome.org/show_bug.cgi?id=765049 + +2016-06-07 11:32:47 +0300 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: + * win32/common/libgstbase.def: + adapter: Rename functions and implement new functions, update test + We don't do calculations with different units (buffer offsets and bytes) + anymore but have functions for: + 1) getting the number of bytes since the last discont + 2) getting the offset (and pts/dts) at the last discont + and the previously added function to get the last offset and its distance from + the current adapter position. + https://bugzilla.gnome.org/show_bug.cgi?id=766647 + +2016-05-19 10:31:02 +0200 Edward Hervey + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: + * win32/common/libgstbase.def: + adapter: Add methods to query current offset + API: gst_buffer_prev_offset + API: gst_buffer_get_offset_from_discont + The gst_buffer_get_offset_from_discont() method allows retrieving the current + offset based on the GST_BUFFER_OFFSET of the buffers that were pushed in. + The offset will be set initially by the GST_BUFFER_OFFSET of + DISCONT buffers, and then incremented by the sizes of the following + buffers. + The gst_buffer_prev_offset() method allows retrievent the previous + GST_BUFFER_OFFSET regardless of flags. It works in the same way as + the other gst_buffer_prev_*() methods. + https://bugzilla.gnome.org/show_bug.cgi?id=766647 + +2016-06-09 17:42:13 +0100 Tim-Philipp Müller + + * gst/gstconfig.h.in: + gstconfig.h.in: indent #if #else jungle for better readability + +2016-06-08 12:11:19 +0300 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: Add gst_pad_link_maybe_ghosting() for consistency + We already had a _full() version, but having that alone seems inconsistent. + Add a non-full version that mirrors the behaviour of gst_pad_link() vs + gst_pad_link_full(). + +2016-05-22 13:10:06 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Make sure DISCONT flags are properly propagated + If we drop a frame that contained a discontinuity, we must remember + that for the next frame that *will* be pushed downstream. + https://bugzilla.gnome.org/show_bug.cgi?id=766795 + +2016-06-04 13:31:58 +0100 Tim-Philipp Müller + + * gst/gstdeviceprovider.c: + deviceprovider: remove base_class_finalize function + It's not going to get called anyway. + https://bugzilla.gnome.org/show_bug.cgi?id=765540 + +2016-06-04 13:11:55 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + element: remove base_class_finalize_func which is never called + Won't be called for static types, so no point keeping it around. + https://bugzilla.gnome.org/show_bug.cgi?id=765540 + +2016-06-03 13:55:44 +0100 Tim-Philipp Müller + + * plugins/tracers/gstleaks.c: + tracers: leaks: some micro-optimisations + - we know number of filter items is not going to change, + but compiler doesn't + - only do GST_IS_TRACER check for GObjects, not mini objects + - use non-type check cast macros in performance critical paths + +2016-05-10 09:29:12 +0200 Guillaume Desmottes + + * docs/design/part-tracing.txt: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstleaks.c: + * plugins/tracers/gstleaks.h: + * plugins/tracers/gsttracers.c: + tracers: add leaks tracer + https://bugzilla.gnome.org/show_bug.cgi?id=765052 + +2016-05-30 12:11:13 +0200 Guillaume Desmottes + + * gst/gstcaps.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstelementfactory.c: + * gst/gstpadtemplate.c: + * gst/gsttask.c: + * libs/gst/net/gstnetclientclock.c: + Use MAY_BE_LEAKED_FLAG + This helps having "make check" passing with the leaks tracer enabled. + https://bugzilla.gnome.org/show_bug.cgi?id=766008 + +2016-05-09 16:31:36 +0200 Guillaume Desmottes + + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + tracing: add hooks when objects or miniobjects are created and destroyed + https://bugzilla.gnome.org/show_bug.cgi?id=765052 + +2016-05-09 16:56:56 +0200 Guillaume Desmottes + + * gst/gst.c: + gst_deinit: move down tracers cleaning + We want the tracer detecting leaks to be finalized as late as possible + to give the chance to other gst components to be properly cleaned first. + https://bugzilla.gnome.org/show_bug.cgi?id=765052 + +2016-05-10 11:06:42 +0200 Guillaume Desmottes + + * tests/check/gst/gstplugin.c: + tests: plugin: remove feature refcount assert + This check fails if one, or more, tracers are loaded while running the + test. The new "leaks" tracer will be able to check for leaks anyway. + https://bugzilla.gnome.org/show_bug.cgi?id=765052 + +2016-04-14 12:25:43 +0300 Guillaume Desmottes + + * gst/gststructure.c: + tracerrecord: allow G_TYPE_POINTER for field types + Tracers may want to display the address of an object. + https://bugzilla.gnome.org/show_bug.cgi?id=765052 + +2016-05-30 13:42:36 +0200 Stefan Sauer + + * tests/check/gst/gstobject.c: + gstobject: split up name tests + It is better to have separate tests: + 1) the test name will tell what is broekn when the test fails + 2) we still run the other tests when one assert fails + 3) the tests are easier to understand + 4) we don't rely on sie effect of previous actions + 5) ... + Also ix the assertion message for the name checks (Gst -> fakeobject). + +2016-05-30 02:06:01 -0700 Stefan Sauer + + * docs/design/part-tracing.txt: + design: update design doc + Some of the api was renamed before the merge. + +2016-05-30 02:04:18 -0700 Stefan Sauer + + * gst/gstquery.c: + docs: xref the free function and expand allocation query docs + Add xrefs for how to parse pool details from an allocation query. + +2016-05-26 14:43:10 -0400 Nicolas Dufresne + + * tests/check/gst/gstobject.c: + object: Add _set_name() test on parented object + This is not allowed, and set_name() should fail. + https://bugzilla.gnome.org/show_bug.cgi?id=766923 + +2016-05-26 14:41:38 -0400 Nicolas Dufresne + + * tests/check/gst/gstobject.c: + object: Check that name change are notified once + GObject allow calling g_object_notify() within set_property() and + won't notify it twice. As it was raised during review, add a unit test to + make sure. + https://bugzilla.gnome.org/show_bug.cgi?id=766923 + +2016-05-26 13:17:37 -0400 Nicolas Dufresne + + * gst/gstobject.c: + object: Notify name change when using _set_name() + There was a 0.11 FIXME about notifying the name change or removing that + function. Clearly we can't remove this function, so let's notify it. + https://bugzilla.gnome.org/show_bug.cgi?id=766923 + +2016-05-25 15:30:21 +0200 Edward Hervey + + * gst/gst_private.h: + gst_private: Fix gstconfig include + Since it's a generated header, we need to specify the gst subdir so + that it gets properly included in out-of-dir compilation + +2016-05-25 10:48:05 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + gst: make sure to include gstconfig.h also in gst_private.h + For GST_EXPORT define and also things like GST_DISABLE_REGISTRY. + Hopefully fixes the following build failure on cerbero-cross-mingw32: + helpers/gst-plugin-scanner.c:50: undefined reference to `_imp___gst_disable_registry_cache' + +2016-05-24 00:40:27 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + g-i: pass compiler env to g-ir-scanner + It's what introspection.mak does as well. Should + fix spurious build failures on gnome-continuous. + +2016-05-23 21:15:48 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + gst: g-i: pass compiler with quotes + So CC="ccache gcc" works properly. + +2016-05-23 21:06:53 +0100 Ray Strode + + * gst/Makefile.am: + gst: attempt to fix/track-down mysterious gnome-continuous build failures + +2016-05-23 18:00:30 +0100 Tim-Philipp Müller + + * gst/gstiterator.c: + iterator: only unset GValue if it was inited + And add some function guards. From GLib 2.48 on it is + allowed to pass an uninitialised GValue to g_value_unset(). + https://bugzilla.gnome.org/show_bug.cgi?id=763762 + +2016-05-23 18:44:01 +0530 Nirbheek Chauhan + + * gst/parse/Makefile.am: + gst/parse: Also pass -DGST_EXPORTS here + This static library gets included directly into libgstreamer-1.0.so, so it needs + the same GST_EXPORTS definition as the rest of the code that's compiled into + that otherwise it will try to find the constants it uses from gstinfo via DLL + importing (__declspec(dllimport)). + Fixes https://ci.gstreamer.net/job/cerbero-cross-mingw32/4393/ + +2016-05-20 00:24:54 +0530 Nirbheek Chauhan + + * gst/gstconfig.h.in: + gstconfig.h: Always use dllexport/import on Windows + __declspec(dllexport/import) are supported by GCC and are needed for + properly generating code that fetches the values of constants from DLLs + built with __declspec(dllexport) which happens when anything using + GST_EXPORT is built with MSVC. + See: https://msdn.microsoft.com/en-us/library/619w14ds.aspx + Essentially, if you built gstreamer with MSVC and then tried to use + constants from it (such as GST_TYPE_CAPS) in a plugin, GCC would + retrieve the address of the value instead of the value itself. + +2016-05-19 11:27:36 -0300 Danilo Cesar Lemes de Paula + + * scripts/git-update.sh: + scripts: make git-update.sh build with all cores available + The git-update.sh now builds with all cores available. In case of + failure it defaults to 1 + The developer can still override this by setting -j to something else + in MAKEFLAGS, as stated by 299605dfe2f97fca330161ff01a392e1a85fe422. + https://bugzilla.gnome.org/show_bug.cgi?id=766666 + +2016-05-04 13:53:56 +0200 Guillaume Desmottes + + * gst/gstminiobject.h: + * gst/gstobject.h: + (mini)object: add MAY_BE_LEAKED flag + https://bugzilla.gnome.org/show_bug.cgi?id=766008 + +2016-05-15 14:15:51 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: emit deep-element-{added,removed} for children of newly-added/removed bin + https://bugzilla.gnome.org/show_bug.cgi?id=578933 + +2016-05-14 10:55:53 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstbin.h: + * tests/check/gst/gstbin.c: + bin: add "deep-element-added" and "deep-element-removed" signals + This means applications and bin sub-classes can easily track when + a new child element is added to the pipeline sub-hierarchy or + removed. + Currently doesn't signal deep added/removed for elements inside + a bin if a bin is added/removed. + https://bugzilla.gnome.org/show_bug.cgi?id=578933 + +2016-05-15 15:02:49 +0300 Sebastian Dröge + + * gst/gstpad.h: + pad: Improve IDLE probe docs + Make it explicit that the pad is only blocked while the callback is running, + and the pad will be unblocked again once the callback returned. + If BLOCK and IDLE behaviour is needed, both need to be used. + https://bugzilla.gnome.org/show_bug.cgi?id=766002 + +2016-05-15 13:29:55 +0300 Sebastian Dröge + + * docs/plugins/inspect/plugin-coreelements.xml: + docs: Update for git master + +2016-03-11 16:04:52 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue: Only unblock upstream waiting for the query once downstream is finished + ... when flushing and deactivating pads. Otherwise downstream might have a + query that was already unreffed by upstream, causing crashes or other + interesting effects. + https://bugzilla.gnome.org/show_bug.cgi?id=763496 + +2016-05-14 17:31:51 +0300 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + basesink/src: Post an error message if ::start() fails + The subclass should do that already, but just in case do it ourselves too as a + fallback. Without this, e.g. playbin will just wait forever if this fails + because it is triggered as part of an ASYNC state change. + +2016-05-14 23:36:43 +1000 Jan Schmidt + + * gst/gstbin.c: + bin: Fix EOS forwarding on PLAYING->PLAYING + When doing a transition from PLAYING to PLAYING, we will fail + to forward an EOS message on the bus, and noone else will ever + send it because there'll be no actual state changed message. + Allow EOS through directly in that case. + +2016-05-13 09:43:14 +0200 Edward Hervey + + * gst/gstpad.c: + pad: Don't drop LATENCY queries with default implementation + If there is only one pad in the internal pads, when folding for + LATENCY queries it will just drop the response if it's not live. + This is maybe not the proper fix, but it will just accept the first + peer responses, and if there are any other pads, it will only take + them into account if the response is live. + This *should* properly handle the aggregation/folding behaviour of + multiple live peer responses, while at the same time handling the + simple one-pad-only-and-forward use-case + https://bugzilla.gnome.org/show_bug.cgi?id=766360 + +2016-04-07 00:46:20 +1000 Jan Schmidt + + * tools/gst-launch.1.in: + Update the examples in the gst-launch-1.0 manpage + Replace elements that don't exist any more with ones + that do, and insert elements like mpegaudioparse where + they are needed. + https://bugzilla.gnome.org/show_bug.cgi?id=727105 + +2016-04-02 01:05:39 +1100 Jan Schmidt + + * gst/gst.c: + debug: Instantiate GType when dumping debug categories. + A lot of debug categories are declared in element class_init + functions, which don't get run until the element is first created + (not just registered in the plugin load function). This means + that --gst-debug-help doesn't print out a lot of categories. + Creating an instance of each element from the element factory + makes them visible, at some extra cost - 2-3 times longer, which can + be a full second or two of extra waiting. Yikes! + https://bugzilla.gnome.org/show_bug.cgi?id=741001 + +2016-05-11 15:06:39 +0300 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Only push a CAPS event downstream if the sinkpad is not in PULL mode + The other signal handlers of the type-found signal might have reactivated + typefind in PULL mode already, pushing a CAPS event at that point would cause + deadlocks and is in general unexpected by elements that are in PULL mode. + https://bugzilla.gnome.org/show_bug.cgi?id=765906 + +2016-05-11 12:16:09 +0900 Wonchul Lee + + * gst/gstdebugutils.c: + debugutils: fix warning on enum properties printing + https://bugzilla.gnome.org/show_bug.cgi?id=766251 + +2016-05-10 15:01:42 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix pad state when deactivating from one mode and then trying to activate another and failing + When activating a pad in PULL mode, it might already be in PUSH mode. We now + first try to deactivate it from PUSH mode and then try to activate it in PULL + mode. If the activation fails, we would set the pad to flushing and set it + back to its old mode. However the old mode is wrong, the pad is not in PUSH + mode anymore but in NONE mode. + This fixes e.g. typefind in decodebin reactivating PUSH/PULL mode if upstream + actually fails to go into PULL mode after first PUSHING data to typefind. + +2016-03-13 11:05:29 -0400 Anthony G. Basile + + * libs/gst/check/libcheck/strsignal.c: + libcompat.h: strsignal() should be not be decleared const + POSIX standards requires strsignal() to return a pointer to a char, + not a const pointer to a char. [1] On uClibc, and possibly other + libc's, that do not HAVE_DECL_STRSIGNAL, libcompat.h declares + const char *strsignal (int sig) which causes a type error. + [1] man 3 strsignal + https://bugzilla.gnome.org/show_bug.cgi?id=763567 + +2016-05-05 18:50:05 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: add debug category + Not that it logs much. + +2016-05-05 18:02:21 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: fix docs for gst_flow_combiner_reset() + +2016-05-04 10:04:30 +0200 Guillaume Desmottes + + * tests/check/pipelines/parse-launch.c: + parse-launch: fix factory leak in test + We get 2 references one from gst_element_factory_find() and the other + from gst_plugin_feature_load(). + https://bugzilla.gnome.org/show_bug.cgi?id=765976 + +2016-05-04 13:46:46 +0200 Guillaume Desmottes + + * tests/check/gst/gstminiobject.c: + miniobject: fix ref count leaks in tests + https://bugzilla.gnome.org/show_bug.cgi?id=765978 + +2016-05-04 09:53:32 +0200 Guillaume Desmottes + + * gst/gstutils.c: + * tests/check/pipelines/parse-launch.c: + utils: fix element leak in find_common_root() + The root element was not unreffed when iterating over ancestors. + https://bugzilla.gnome.org/show_bug.cgi?id=765961 + +2016-05-02 17:35:29 +0200 Guillaume Desmottes + + * tools/gst-inspect.c: + inspect: fix feature leak + https://bugzilla.gnome.org/show_bug.cgi?id=765957 + +2016-05-03 11:49:03 +0200 Guillaume Desmottes + + * gst/gsturi.c: + uri: unref instead of using _gst_uri_free() directly + This confuses gst_tracing as we shortcut the mini object reference + system. + https://bugzilla.gnome.org/show_bug.cgi?id=765958 + +2016-05-02 09:32:47 +0200 Guillaume Desmottes + + * tests/check/pipelines/seek.c: + pipeline: fix bus leak in seek test + gst_bus_add_signal_watch_full() keeps a ref on the bus which should + be released using gst_bus_remove_signal_watch(). + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 09:29:31 +0200 Guillaume Desmottes + + * tests/check/elements/streamiddemux.c: + streamiddemux: fix list and event leaks in test + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 08:43:04 +0200 Guillaume Desmottes + + * tests/check/elements/selector.c: + selector: fix pad leaks in tests + setup_input_pad() creates a new pad so we should unref it once we're + done. + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 08:33:42 +0200 Guillaume Desmottes + + * tests/check/elements/filesrc.c: + filesrc: fix buffer leaks in tests + gst_check_setup_sink_pad() internally uses gst_check_chain_func() so we + should call gst_check_drop_buffers() when tearing down tests to free the + buffers which have been exchanged through the pipeline. + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 08:29:00 +0200 Guillaume Desmottes + + * tests/check/elements/fakesink.c: + fakesink: fix pipeline leak in test + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 07:35:45 +0200 Guillaume Desmottes + + * tests/check/gst/gstelementfactory.c: + elementfactory: fix factory leak in test + https://bugzilla.gnome.org/show_bug.cgi?id=765903 + +2016-05-02 16:00:42 +0200 Guillaume Desmottes + + * gst/gstdeviceproviderfactory.c: + deviceproviderfactory: fix factory leak + The code path when early returning was leaking the extra reference on + the factory. + https://bugzilla.gnome.org/show_bug.cgi?id=765904 + +2016-04-10 11:42:18 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + query: fix compiler warning + C4146: unary minus operator applied to unsigned type, result still unsigned + +2016-04-28 14:59:51 +0300 Guillaume Desmottes + + * tests/check/gst/gstbin.c: + bin: fix leaks in unit tests + The test rely on bus being flushed when setting the bin to the NULL state which + is not the case. This apply only when setting the pipeline state to + NULL. + https://bugzilla.gnome.org/show_bug.cgi?id=765720 + +2016-04-28 14:56:18 +0300 Guillaume Desmottes + + * tests/check/gst/gstpad.c: + pad: fix buffer leaks in tests + The buffer received through the pad have to be unreffed using + gst_check_drop_buffers(). + https://bugzilla.gnome.org/show_bug.cgi?id=765719 + +2016-04-30 14:15:08 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstghostpad.c: + * libs/gst/check/gstharness.c: + Fix some nonsensical g-i annotations + +2016-04-29 14:55:02 +0200 Matej Knopp + + * plugins/elements/gstmultiqueue.c: + multiqueue: Ignore time when determining whether sparse stream limits have been reached + Basically, sq->max_size.visible is never increased for sparse streams in + overruncb when empty queue has been found; + If the queue is sparse it just skip the entire logic determining whether + max_size.visible should be increased, deadlocking the demuxer. + What should be done instead is that when determining if limits have been + reached, to ignore time for sparse streams, as the buffer may be far in the + future. + https://bugzilla.gnome.org/show_bug.cgi?id=765736 + +2016-02-28 12:06:40 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: Add gst_element_call_async() + This calls a function from another thread, asynchronously. This is to be + used for cases when a state change has to be performed from a streaming + thread, directly via gst_element_set_state() or indirectly e.g. via SEEK + events. + Calling those functions directly from the streaming thread will cause + deadlocks in many situations, as they might involve waiting for the + streaming thread to shut down from this very streaming thread. + This is mostly a convenience function around a GThreadPool and is for example + used by GstBin to continue asynchronous state changes. + https://bugzilla.gnome.org/show_bug.cgi?id=760532 + +2016-04-27 09:21:31 +0300 Sebastian Dröge + + * docs/manual/advanced-dataaccess.xml: + manual: Fix buffer memory leak in appsrc example + g_signal_emit_by_name() is not like gst_app_src_push_buffer() due to reference + counting limitations of signals, it does *not* take ownership of the buffer. + +2016-04-26 16:02:14 +0300 Guillaume Desmottes + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstcaps.c: + caps: add cleanup priv function + Those are allocated in _priv_gst_caps_initialize() so it makes + sense to have a symetric cleanup functions called by gst_deinit(). + https://bugzilla.gnome.org/show_bug.cgi?id=765606 + +2016-04-26 16:02:14 +0300 Guillaume Desmottes + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstcapsfeatures.c: + capsfeature: add cleanup priv function + Those are allocated in _priv_gst_caps_features_initialize() so it makes + sense to have a symetric cleanup functions called by gst_deinit(). + https://bugzilla.gnome.org/show_bug.cgi?id=765606 + +2016-04-21 14:45:39 +0100 Alex Ashley + + * libs/gst/check/gsttestclock.c: + testclock: add clock-type property + To allow the GstTestClock to be used as a GstSystemClock, it is + useful to implement the clock-type property that GstSystemClock + provides. This allows GstTestClock to be used as the system clock + with code that expects a GstSystemClock. + https://bugzilla.gnome.org/show_bug.cgi?id=762147 + +2016-04-21 13:49:32 +0300 Sebastian Dröge + + * gst/gstdatetime.c: + datetime: Sanity check year, month and day when parsing ISO-8601 strings + Passing years > 9999, months > 12 or days > 31 to gst_date_time_new() will + cause an assertion and generally does not make much sense. Instead consider it + as a parsing error like hours > 24 and return NULL. + +2016-04-20 11:46:19 +0300 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Remember if we interpolated DTS from PTS and refresh it whenever we update the PTS + Otherwise PTS and DTS will come out of sync if upstream continues to provide + PTS and not DTS, and we have to skip some data from the stream or PTS are not + exactly increasing with the duration of each packet. + https://bugzilla.gnome.org/show_bug.cgi?id=765260 + +2016-04-20 11:45:28 +0300 Sebastian Dröge + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Fix gobject-introspection warning about invalid transfer annotation + gsttypefindhelper.c:485: Warning: GstBase: invalid "transfer" annotation for gsize: only valid for array, struct, union, boxed, object and interface types + +2016-04-18 13:05:40 +0300 Guillaume Desmottes + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstallocator.c: + allocator: add cleanup method + Make tracking memory leaks easier. + https://bugzilla.gnome.org/show_bug.cgi?id=765212 + +2016-03-25 15:55:18 +0100 Francisco Velazquez + + * tests/check/gst/gstplugin.c: + tests: plugin: improve debug message + https://bugzilla.gnome.org/show_bug.cgi?id=764199 + +2016-04-14 11:54:32 +0200 Carlos Rafael Giani + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + multiqueue: Recheck buffering status after changing low threshold + https://bugzilla.gnome.org/show_bug.cgi?id=763757 + +2016-04-14 00:09:44 +0200 Carlos Rafael Giani + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + multiqueue: Recalculate fill level after changing high-threshold + This ensures the following special case is handled properly: + 1. Queue is empty + 2. Data is pushed, fill level is below the current high-threshold + 3. high-threshold is set to a level that is below the current fill level + Since mq->percent wasn't being recalculated in step #3 properly, this + caused the multiqueue to switch off its buffering state when new data is + pushed in, and never post a 100% buffering message. The application will + have received a <100% buffering message from step #2, but will never see + 100%. + Fix this by recalculating the current fill level percentage during + high-threshold property changes in the same manner as it is done when + use-buffering is modified. + https://bugzilla.gnome.org/show_bug.cgi?id=763757 + +2016-04-15 13:50:30 +0300 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: When initializing DTS from PTS, remember that we did so + If we don't store the value in prev_dts, we would over and over again + initialize the DTS from the last known upstream PTS. If upstream only provides + PTS every now and then, then this causes DTS to be rather static. + For example in adaptive streaming scenarios this means that all buffers in a + fragment will have exactly the same DTS while the PTS is properly updated. As + our queues are now preferring to do buffer fill level calculations on DTS, + this is causing huge problems there. + See https://bugzilla.gnome.org/show_bug.cgi?id=691481#c27 where this part of + the code was introduced. + https://bugzilla.gnome.org/show_bug.cgi?id=765096 + +2016-04-14 09:58:04 +0100 Julien Isorce + + * README: + * common: + Automatic update of common submodule + From 6f2d209 to ac2f647 + +2016-04-13 16:08:30 +0100 Vincent Penquerc'h + + * plugins/elements/gstmultiqueue.c: + multiqueue: catch errors and flushing case after lock + This ensures we can not get into an indefinite wait on the + following cond var wait. + https://bugzilla.gnome.org/show_bug.cgi?id=764999 + +2016-04-13 16:40:43 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: fix up caps printing in verbose mode + Add missing 'else' and print caps and taglists without the + annoying duplicate string escaping, making both nicer to read. + Fixes string leak and coverity CID 1358492. + +2016-04-13 12:38:05 +0300 Guillaume Desmottes + + * plugins/tracers/gstrusage.c: + rusage: properly free the queue memory + The queue is allocated as part of the tracer struct so we should not + use g_queue_free() to free it. + https://bugzilla.gnome.org/show_bug.cgi?id=764985 + +2016-04-13 10:21:15 +0300 Sebastian Dröge + + * gst/gstbuffer.c: + * gst/gstmeta.c: + meta: Warn if a meta implementation is registered without init function + This previously caused uninitialized memory unless something else was + initializing all the fields explicitly to something. + To be on the safe side, we also allocate metas without init function to all + zeroes now as it was relatively common. + https://bugzilla.gnome.org/show_bug.cgi?id=764902 + +2016-04-12 15:17:36 +0300 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + Revert "basesink: Take PREROLL_LOCK in wait_event()" + This reverts commit 828a4627db0cb6a6706b96d9be97e5e5c7d22215. + The lock was already taken elsewhere, in gst_base_sink_event(). + +2016-04-12 15:11:30 +0300 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Take PREROLL_LOCK in wait_event() + It is calling do_sync(), which requires the STREAM_LOCK and PREROLL_LOCK to be + taken. The STREAM_LOCK is already taken in all callers, the PREROLL_LOCK not. + https://bugzilla.gnome.org/show_bug.cgi?id=764939 + +2016-02-11 09:33:28 +0100 Julien Isorce + + * tests/check/Makefile.am: + tests: add PTHREAD_CFLAGS for make check to pass on OS X + Currently "make check" fails with: + "error: argument unused during compilation: '-pthread'" + PTHREAD_CFLAGS now contains -Qunused-arguments to fix that. + Explanation here: http://savannah.gnu.org/patch/?8186#comment21 + https://bugzilla.gnome.org/show_bug.cgi?id=747954 + +2016-04-11 10:44:22 +0100 Tim-Philipp Müller + + * tests/check/libs/baseparse.c: + tests: baseparse: make work with CK_FORK=no + https://bugzilla.gnome.org/show_bug.cgi?id=623469 + +2016-04-11 10:27:56 +0100 Tim-Philipp Müller + + * tests/check/libs/test_transform.c: + * tests/check/libs/transform1.c: + * tests/check/libs/transform2.c: + tests: transform1: make test work with CK_FORK=no + We need to clear some global state and register a new test + basetransform subclass for each test because we do things + in class_init base on global state. + https://bugzilla.gnome.org/show_bug.cgi?id=623469 + +2016-04-10 20:45:24 +0100 Tim-Philipp Müller + + * tests/check/libs/collectpads.c: + tests: collectpads: fix for CK_FORK=no + Reset global state when done, and unref sink pads too + in teardown function to make it valgrind clean. + https://bugzilla.gnome.org/show_bug.cgi?id=623469 + +2016-04-10 20:25:44 +0100 Tim-Philipp Müller + + * tests/check/elements/streamiddemux.c: + tests: streamiddemux: fix with CK_FORK=no + Clear global state when done. + https://bugzilla.gnome.org/show_bug.cgi?id=623469 + +2016-04-10 20:04:07 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferpool.c: + tests: bufferpool: fix wrong assumptions about pointers and object lifecycles + The test assumed that if a buffer has the same pointer address as + before it is in fact the same mini object and has been re-used by + the pool. This seems to be mostly true, but not always. The buffer + might be destroyed and when a new buffer is created the allocator + might return the same memory that we just freed. + Instead attach a qdata with destroy notify function to buffer + instances we want to track to make sure the buffer actually + gets finalized rather than resurrected and put back into the pool. + +2016-04-10 18:37:31 +0100 Tim-Philipp Müller + + * docs/pwg/building-boiler.xml: + * docs/pwg/pwg.xml: + docs: pwg: remove broken references to example code + We point to gst-template at the beginning that shoul be + enough. + https://bugzilla.gnome.org/show_bug.cgi?id=623575 + +2016-04-08 13:26:48 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: don't run tracerrecord in valgrind for now + Because of the way we implement logging and adding/removing + log functions currently (we leak a GList on purpose) this + test leaks. + +2016-03-05 17:51:01 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: use new async property change notification API + https://bugzilla.gnome.org/show_bug.cgi?id=763142 + +2016-03-05 14:12:36 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstelement.c: + * win32/common/libgstreamer.def: + element: add API to get property change notifications via messages + Be notified in the application thread via bus messages about + notify::* and deep-notify::* property changes, instead of + having to deal with it in a non-application thread. + API: gst_element_add_property_notify_watch() + API: gst_element_add_property_deep_notify_watch() + API: gst_element_remove_property_notify_watch() + API: gst_message_new_property_notify() + API: gst_message_parse_property_notify() + API: GST_MESSAGE_PROPERTY_NOTIFY + https://bugzilla.gnome.org/show_bug.cgi?id=763142 + +2016-04-07 20:29:10 +0300 Sebastian Dröge + + * tests/check/gst/gstcpp.cc: + * tests/check/libs/gstlibscpp.cc: + tests: Add C++ tests for the other INIT macros we have + +2016-04-06 17:19:28 +0100 Tim-Philipp Müller + + * tests/check/gst/gstcpp.cc: + tests: gstcpp: flesh out C++ test so we can add more bits + Like a check for GST_MAP_INFO_INIT. + +2016-04-06 16:48:38 +0100 Tim-Philipp Müller + + * tests/check/libs/gstlibscpp.cc: + tests: use catch-all includes for c++ gst libs include test + So we get any new header files as well as they're added. + +2016-04-06 17:23:20 +0100 Tim-Philipp Müller + + * gst/gstmemory.h: + memory: fix C++ compiler warnings with GST_MAP_INFO_INIT + +2016-04-04 10:28:18 +0000 Matthew Waters + + * gst/gstutils.c: + * tests/check/gst/gstutils.c: + utils: check the correct element's state on ghosting pads + Checking the current element's state when we're adding pads to + the parent element is checking the wrong thing. + Silences a 'attempting to add an inactive pad to a running element' + warning when adding a ghost pad to a running parent bin of the parent + bin of the element. + https://bugzilla.gnome.org/show_bug.cgi?id=764176 + +2016-03-25 01:28:18 +0000 Matthew Waters + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: expose pad_link_maybe_ghosting + This is a useful function to automatically add ghost pads when linking + two elements across bin boundaries without know their exact parentage. + e.g. when using gst_parse_bin_from_description (with or without it ghosting pads), + one can simply retreive the src/sink pads from the bin to link to another pad. + Similar functionality is provided by gst_element_link_pads{_full}() however only + by pad name rather than by actual pads. + API: gst_pad_link_maybe_ghosting_full + https://bugzilla.gnome.org/show_bug.cgi?id=764176 + +2016-04-03 23:35:46 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-states.txt: + docs/design/part-states.txt: spelling fix + +2015-05-15 13:36:04 +0100 Mark Combellack + + * gst/gstbin.c: + * gst/gstbufferpool.c: + * gst/gstelement.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpipeline.c: + GST_REFCOUNTING: Add logging of pointer address for dispose, finalize, etc messages + Updated the GST_REFCOUNTING logging so that it includes the pointer + address of the object that is being disposed or finalized. + With this change is is then possible to match up GST_REFCOUNTING log messages + for object allocation/disposal/finalization. This can help with diagnosing + "memory leaks" in applications that have not correctly disposed of all the + GStreamer objects it creates. + https://bugzilla.gnome.org/show_bug.cgi?id=749427 + +2016-03-31 11:46:03 +0100 Luis de Bethencourt + + * gst/gstinfo.c: + info: only open log file when adding it to the log function + This avoids the leak of opening it and then not passing it or closing it + before it goes out of scope. + +2016-04-01 22:41:51 +0300 Sebastian Dröge + + * gst/gstclock.c: + clock: Return FALSE in all paths that don't set out parameters in gst_clock_add_observation_unapplied() + It returned TRUE when regression failed, while not setting any of the out + parameters. This caused uninitialized data from the stack to be used for + setting the clock calibration. + +2016-03-24 17:34:20 -0300 Thiago Santos + + * gst/gstpad.c: + pad: rework probe's hook_marshall function + PUSH and PULL mode have opposite scenarios for IDLE and BLOCK + probes. + For PUSH it will BLOCK with some data type and IDLE won't have a type. + For PULL it will BLOCK before getting some data and will be IDLE when + some data is obtained. + The check in hook_marshall was specific for PUSH mode and would cause + PULL probes to fail to be called. Adding different checks for the mode + to fix this issue. + https://bugzilla.gnome.org/show_bug.cgi?id=761211 + +2016-03-24 17:34:40 -0300 Thiago Santos + + * tests/check/gst/gstpad.c: + tests: pad: extra tests for pad pull probes + For BUFFER and IDLE probes + https://bugzilla.gnome.org/show_bug.cgi?id=761211 + +2016-01-28 16:22:17 +0100 Matej Knopp + + * tests/check/gst/gstpad.c: + pad: Add test for blocking pull probe + https://bugzilla.gnome.org/show_bug.cgi?id=761211 + +2016-03-24 12:13:39 -0300 Thiago Santos + + * gst/gstpad.c: + pad: consider PROBE_TYPE_EVENT_FLUSH when using PROBE_TYPE_ALL_BOTH + When GST_PAD_PROBE_EVENT_FLUSH is used, the probes already have + a data type and it is not needed to automatically add the default + types. + https://bugzilla.gnome.org/show_bug.cgi?id=762330 + +2016-02-19 16:18:12 +0100 Linus Svensson + + * tests/check/gst/gstpad.c: + gstpad tests: Add a test for flush event only probes + https://bugzilla.gnome.org/show_bug.cgi?id=762330 + +2016-03-26 17:21:51 +0000 Tim-Philipp Müller + + * gst/gstdebugutils.c: + debugutils: fix enum/flag properties printing for elements + We want to use the flag/enum nicks here, not only because they + are shorter but also because in case of element-specific enums + and flags we abuse the enum/flag name field for the description, + and we don't want that printed in the dot file. + https://bugzilla.gnome.org/show_bug.cgi?id=763814 + +2016-03-23 10:31:46 +0000 Tim-Philipp Müller + + * gst/gsttrace.c: + alloctrace: print size and allocator details for buffers and memories + +2016-02-29 19:04:16 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: make it possible to remove default log handler before gst_init() + Make sure it's not even added then, so that we never output + anything via the default log handler then. + https://bugzilla.gnome.org/show_bug.cgi?id=751538 + +2016-03-05 14:27:35 +0000 Tim-Philipp Müller + + * gst/gstmemory.h: + * gst/gstminiobject.h: + * gst/gsturi.h: + miniobject, memory, uri: warn on unused return value of some funcs + Make compiler issue a warning for common beginner mistakes such as: + ... + gst_buffer_make_writable (buf); + gst_buffer_map (buf, &map, GST_MAP_WRITE); + ... + and similar. Only do this for some functions for now. + +2016-03-26 11:17:02 +0000 Tim-Philipp Müller + + * .gitignore: + .gitignore new netclock-replay testing tool binary + +2015-10-17 18:01:47 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: allow plugin and feature filter funcs to call registry API + Don't keep the registry locked whilst iterating over the plugins + or features with a filter function. This would deadlock if the + callback tried to access the registry from the function. Instead, + make a copy of the feature/plugin list and then filter it without + holding the registry lock. This is still considerably faster than + the alternative which would be to use a GstIterator. + https://bugzilla.gnome.org/show_bug.cgi?id=756738 + +2016-03-25 12:59:57 +0200 Sebastian Dröge + + * configure.ac: + configure: Remove unneeded parenthesis from AG_GST_CHECK_CHECKS + +2016-03-25 12:05:41 +0200 Sebastian Dröge + + * tests/check/elements/valve.c: + valve: Fix unit test by sending caps before buffers + Unexpected critical/warning: gstpad.c:4400:gst_pad_push_data:<'':src> Got data flow before segment event + https://bugzilla.gnome.org/show_bug.cgi?id=763753 + +2016-03-25 10:23:46 +0200 Sebastian Dröge + + * tests/misc/Makefile.am: + netclock: Link the replay example to GIO + +2016-03-03 21:45:54 +0530 Arun Raghavan + + * tests/misc/Makefile.am: + * tests/misc/netclock-replay.c: + tests: Add some code to replay and analyse netclientclock + This takes readings in the form of ... + + ... with one observation per line, and then replays it using the + netclientclock code. + The output is the statistics structure emitted by the netclientclock, + which can then be analysed and tuned once we get those readings for + potential edge-cases. + It should be possible to find some inputs with "bad" data and convert + this into a unit test for future tweaks to run against. + +2016-03-03 21:44:35 +0530 Arun Raghavan + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Always dump clock observations in logs + This makes it possible to examine what values we get in logs, and + potentially tune our filtering/extrapolation in various scenarios. + +2016-03-04 15:50:26 +0900 Vineeth TM + + * plugins/elements/gstdataurisrc.c: + bad: use new gst_element_class_add_static_pad_template() + https://bugzilla.gnome.org/show_bug.cgi?id=763081 + +2016-03-16 15:13:39 +0100 Havard Graff + + * plugins/elements/gstvalve.c: + * tests/check/elements/valve.c: + valve: don't send sticky events as a direct response to upstream events + Also refactor the existing valve test to actually test the valve, + and not just test the EOS mechanism of a pad. + https://bugzilla.gnome.org/show_bug.cgi?id=763753 + +2016-03-11 09:23:04 +0100 Carlos Rafael Giani + + * gst/gstparse.c: + * gst/gstparse.h: + * gst/parse/grammar.y: + parse-launch: Add flag for placing elements in a bin instead of a pipeline + By default, gst_parse_launch_full() creates a GstPipeline if there's more + than one toplevel element. Add a flag to let it use a GstBin instead. + Also fix the parser to let it use this flag for GST_TYPE_ELEMENT property + values, to avoid having GstPipelines inside other GstPipelines. + https://bugzilla.gnome.org/show_bug.cgi?id=763457 + +2016-03-08 19:08:16 +0000 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + capsfilter: optimisation: avoid unnecessary gst_pad_has_current_caps() checks + No need to do this for every input buffer, since it involves + locking and iterating of the sticky events array and such. + https://bugzilla.gnome.org/show_bug.cgi?id=763337 + +2016-03-03 14:15:00 +0900 Vineeth TM + + * gst/gstpadtemplate.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * tests/check/elements/fakesink.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstprotection.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/baseparse.c: + * tests/check/libs/collectpads.c: + * tests/check/libs/test_transform.c: + * tests/check/pipelines/parse-launch.c: + * tests/check/pipelines/seek.c: + gstreamer: use new gst_element_class_add_static_pad_template() + https://bugzilla.gnome.org/show_bug.cgi?id=763020 + +2016-03-02 17:47:33 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: Use full running time for level calculation + Ensures we have proper time level estimation for the cases where + the incoming buffers have PTS/DTS outside of the segment start/stop + values. + https://bugzilla.gnome.org/show_bug.cgi?id=762995 + +2016-01-27 11:46:06 +0100 Stian Selnes + + * gst/gstpad.c: + pad: Fix race between gst_element_remove_pad and state change + When going from READY to NULL all element pads are deactivated. If + simultaneously the pad is being removed from the element with + gst_element_remove_pad() and the pad is unparented, there is a race + where the deactivation will assert (g_critical) if the parent is lost at + the wrong time. + The proposed fix will check parent only once and retain it to avoid the + race. + https://bugzilla.gnome.org/show_bug.cgi?id=761912 + +2016-03-02 21:11:51 -0500 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.c: + collectpads: Assume PTS is equal DTS if PTS is missing + This is the best guess we can make if such a buffer reached the collect + pad. This is uncommon, we do expect parsers to have tried and fixed that + if possible (or needed). + https://bugzilla.gnome.org/show_bug.cgi?id=762207 + +2016-03-24 13:32:41 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +2016-03-24 11:49:44 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Remove redundant assignment + CID 1357158 + +=== release 1.8.0 === + +2016-03-24 11:49:08 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.8.0 + +2016-03-24 11:35:26 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2016-03-13 11:05:29 -0400 Anthony G. Basile + + * libs/gst/check/libcheck/libcompat.h: + libcompat.h: strsignal() should be not be decleared const + POSIX standards requires strsignal() to return a pointer to a char, + not a const pointer to a char. [1] On uClibc, and possibly other + libc's, that do not HAVE_DECL_STRSIGNAL, libcompat.h declares + const char *strsignal (int sig) which causes a type error. + [1] man 3 strsignal + https://bugzilla.gnome.org/show_bug.cgi?id=763567 + +2016-03-22 19:04:59 +0200 Sebastian Dröge + + * gst/gstpreset.c: + preset: Use GST_PRESET_PATH as an extension of the system path, not a replacement of the user path + First load all system presets, then all from the environment variable, then + from the app directory, then from the user directory. Any one in the chain + with the highest version completely replaces all previous ones, later ones + with lower versions are merged in without replacing existing presets. + This is basically the same behaviour as before, just that GST_PRESET_PATH is + inserted as another source of directories between the system and app presets. + It was added in ca08af1f17d2ce36b83998a0ba3a7b8bcafd7872, but was + accidentially overriding the user preset path there. Which caused inconsistent + behaviour as new presets were still stored in the system path, just not loaded + from there. Meaning you could store a new preset (in the user path), just for + GstPreset to not find it anymore later (because it only looked in the + GST_PRESET_PATH instead of the user path). + https://bugzilla.gnome.org/show_bug.cgi?id=764034 + +2016-03-19 12:55:09 +0100 Aurélien Zanelli + + * gst/gstutils.c: + utils: add 'transfer full' annotation to gst_pad_peer_query_caps + https://bugzilla.gnome.org/show_bug.cgi?id=763912 + +2016-03-19 12:39:18 +0100 Aurélien Zanelli + + * gst/gstpad.c: + pad: add 'transfer full' and 'nullable' annotations to gst_pad_get_current_caps + and also change the description accordingly since function returns an + incremented caps object or NULL if there is no caps set. + https://bugzilla.gnome.org/show_bug.cgi?id=763912 + +2016-03-18 16:02:43 -0400 Ben Iofel + + * gst/gstutils.c: + utils: fix gir annotation for gst_element_query_convert() + https://bugzilla.gnome.org/show_bug.cgi?id=763895 + +2016-03-17 01:42:55 +1100 Jan Schmidt + + * tests/check/elements/multiqueue.c: + tests: Check multiqueue not-linked EOS handling + Add a test which checks that not-linked pads continue + to output data after linked pads have gone EOS + https://bugzilla.gnome.org/show_bug.cgi?id=763770 + +2016-03-18 03:08:39 +1100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix not-linked pad handling at EOS + Ensure that not-linked pads will drain out at EOS by + correctly detecting the EOS condition based on the EOS + pad flag (which indicates we actually pushed an EOS), + and make sure that not-linked pads are woken when doing + EOS processing on linked pads. + https://bugzilla.gnome.org/show_bug.cgi?id=763770 + +2016-03-15 16:37:33 +0100 Romain Picard + + * plugins/elements/gsttypefindelement.c: + typefind: Allow caps query in "have-type" signal handlers + If an application calls gst_pad_query_caps from its "have-type" signal handler, + then the query fails because typefind->caps has not been set yet. + This patch sets typefind->caps in the object method handler, before the signal + handlers are called. + https://bugzilla.gnome.org/show_bug.cgi?id=763491 + +=== release 1.7.91 === + +2016-03-15 11:56:10 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.7.91 + +2016-03-15 11:44:03 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/rw.po: + * po/sk.po: + * po/sl.po: + * po/sq.po: + * po/tr.po: + * po/zh_TW.po: + Update .po files + +2016-03-15 11:39:42 +0200 Sebastian Dröge + + * po/cs.po: + * po/fr.po: + * po/hu.po: + * po/ru.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: Update translations + +2016-03-11 14:17:13 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Store caps on the pad before emitting have-type but send it downstream only in the default signal handler + https://bugzilla.gnome.org/show_bug.cgi?id=763491 + +2016-03-13 10:33:53 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Recheck after pre_push_frame() if there are tags pending + Many parsers are storing tags only in pre_push_frame(), if we wouldn't check + afterwards we would push buffers before those tags and a lot of code assumes that + tags are available before preroll. + https://bugzilla.gnome.org/show_bug.cgi?id=763553 + +2016-03-14 11:15:07 +0100 Carlos Rafael Giani + + * plugins/elements/gstconcat.c: + concat: Fix comment typo + +2016-03-12 12:56:28 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + Revert "typefind: Store caps on the pad before emitting have-type but send it downstream only in the default signal handler" + This reverts commit 0835c3d6569dde0ec9e5524436367c7678cc4a4a. + It causes deadlocks in decodebin, which currently would deadlock if the caps + are already on the pad in have-type and are forwarded while copying the sticky + events (while holding the decodebin lock)... as that might cause the next + element to expose pads, which then calls back into decodebin and takes the + decodebin lock. + This needs some more thoughts. + +2016-03-11 14:17:13 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Store caps on the pad before emitting have-type but send it downstream only in the default signal handler + https://bugzilla.gnome.org/show_bug.cgi?id=763491 + +2016-03-10 10:35:40 +0100 Carlos Rafael Giani + + * gst/gstelement.h: + * gst/gstobject.h: + docs: Flesh out element and object macro accessor docs a bit + https://bugzilla.gnome.org/show_bug.cgi?id=763213 + +2016-03-09 16:06:58 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Remove some obsolete code that can cause warnings + +2016-03-09 13:44:24 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Don't reset calibration of internal clock whenever a new netclient clock is created + https://bugzilla.gnome.org/show_bug.cgi?id=763325 + +2016-03-04 18:23:18 +0100 Víctor Manuel Jáquez Leal + + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: + gstbuffer: fix GstParentBufferMeta GType name + The alias define GST_TYPE_PARENT_BUFFER_META_API_TYPE is wrong and + breaks the usage of gst_buffer_get_parent_buffer_meta(). + This patch fixes the GType alias and make another alias to keep the API + compatibility guarded by GST_DISABLE_DEPRECATED. + Also added a unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=763112 + +2016-03-02 10:37:09 +0200 Sebastian Dröge + + * gst/gsttracerrecord.c: + tracerrecord: Remove useless NULL check and add assertion for making assumptions explicit + gst_structure_new_empty() is not returning NULL in any valid scenarios, + checking for NULL here is useless. Especially because we would dereference any + NULL right after the NULL check again. + CID 1352037. + We previously check if the string ends on .class, as such strrchr() should + return something non-NULL. Add an assertion for that. + CID 1349642. + +2016-03-01 19:50:26 +0000 Tim-Philipp Müller + + * gst/gstelement.c: + element: minor docs fix + Make gtk-doc happy. + +=== release 1.7.90 === + +2016-03-01 18:14:03 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.7.90 + +2016-03-01 16:52:41 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations + +2016-02-29 23:33:03 +0200 Sebastian Dröge + + * gst/gstbus.c: + * tests/check/gst/gstpipeline.c: + Revert "bus: change GstBusSource to hold a weak ref to GstBus" + This reverts commit 894c67e642c0f858b5b18097fa7c995bf3cc50c1. + +2016-02-29 23:32:58 +0200 Sebastian Dröge + + * gst/gstbus.c: + Revert "bus: Make sure to remove the GPollFD from the GSources when destroying the bus" + This reverts commit 05700a7082c145057ccc0be763067bcc263239eb. + +2016-02-29 17:06:36 +0200 Sebastian Dröge + + * gst/gstelement.h: + element: Remove GST_STATE_LOCK_FULL() / UNLOCK_FULL() + There is no corresponding API for that in GLib and nobody could've ever used + these macros without compiler errors anyway. + +2016-02-29 10:01:50 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Make sure to remove the GPollFD from the GSources when destroying the bus + Otherwise the GSource can look into our already destroyed bus where the + GPollFD is stored. + https://bugzilla.gnome.org/show_bug.cgi?id=762849 + +2016-02-29 11:06:50 +0900 Vineeth TM + + * tests/check/gst/gstghostpad.c: + tests: ghostpad: Fix memory leaks + https://bugzilla.gnome.org/show_bug.cgi?id=762845 + +2016-02-28 13:59:48 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: add guard to check writability when removing tags from a taglist + https://bugzilla.gnome.org/show_bug.cgi?id=762793 + +2016-02-27 15:36:28 +0000 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstconcat.c: + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gststreamiddemux.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + elements: use new gst_element_class_add_static_pad_template() + https://bugzilla.gnome.org/show_bug.cgi?id=762778 + +2016-02-27 15:28:49 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: add gst_element_class_add_static_pad_template() + Pretty much every single element does + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&some_templ)); + which is both confusing and unnecessary. We might just + as well add a function to do that in one step. + https://bugzilla.gnome.org/show_bug.cgi?id=762778 + +2016-02-27 15:32:19 +0000 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefind: fix indentation + +2016-02-26 12:40:55 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From b64f03f to 6f2d209 + +2016-02-25 22:36:14 +0000 James Stevenson + + * gst/gstbus.c: + bus: Prevent gst_bus_add_watch_full_unlocked from a segfault if priv->poll == NULL + This happens if the process runs out of file descriptors. Better print + a critical warning instead of just crashing. + https://bugzilla.gnome.org/show_bug.cgi?id=762702 + +2016-02-24 10:56:24 -0300 Thiago Santos + + * gst/gstbus.c: + * tests/check/gst/gstpipeline.c: + bus: change GstBusSource to hold a weak ref to GstBus + When holding a regular ref it will cause the GstBus to never + reach 0 references and it won't be destroyed unless the application + explicitly calls gst_bus_remove_signal_watch(). + Switching to weakref will allow the GstBus to be destroyed. + The application is still responsible for destroying the + GSource. + https://bugzilla.gnome.org/show_bug.cgi?id=762552 + +2016-02-25 14:11:34 +0200 Sebastian Dröge + + * plugins/elements/gstidentity.c: + identity: Add a " " after pts: in the silent=false output + +2014-04-16 11:42:18 +0200 Edward Hervey + + * docs/manual/advanced-dataaccess.xml: + manual: Fix examples to check for gst_buffer_map return values + Otherwise people reading the manual will expect it to always + succeed :) + https://bugzilla.gnome.org/show_bug.cgi?id=728326 + +2014-04-16 11:40:46 +0200 Edward Hervey + + * libs/gst/check/gstcheck.c: + gstcheck: Check return value of gst_buffer_map + We can't check contents if we don't have access to it + https://bugzilla.gnome.org/show_bug.cgi?id=728326 + +2014-04-16 11:39:15 +0200 Edward Hervey + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue2.c: + plugins: Check return values of gst_buffer_map() + They can fail for various reasons. + For non-fatal cases (such as the dump feature of identiy and fakesink), + we just silently skip it. + For other cases post an error message. + https://bugzilla.gnome.org/show_bug.cgi?id=728326 + +2016-02-23 17:23:43 +0100 Edward Hervey + + * gst/gstbuffer.c: + buffer: Check return value of gst_memory_map() + Only do memory operations if the memory was succesfully map'ed + https://bugzilla.gnome.org/show_bug.cgi?id=728326 + +2016-02-23 18:17:42 +0200 Sebastian Dröge + + * plugins/elements/gstdataurisrc.c: + dataurisrc: Don't assume that get_current_caps() returns non-NULL caps after has_current_caps() + Remove calls to gst_pad_has_current_caps() which then go on to call + gst_pad_get_current_caps() as the caps can go to NULL in between. Instead just + use gst_pad_get_current_caps() and check for NULL. + https://bugzilla.gnome.org/show_bug.cgi?id=759539 + +2015-12-10 15:32:27 +0100 Adam Miartus + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: add GST_TAG_CONDUCTOR + This is useful for metadata which explicitely distinguishes + between artist/composer and conductor. + https://bugzilla.gnome.org/show_bug.cgi?id=762450 + +2016-02-22 14:09:56 +0100 Mark Nauwelaerts + + * gst/gstevent.c: + event: add some more documentation on stream-id + ... where it might end up being used for. + +2016-01-22 11:25:30 +0100 Thibault Saunier + + * gst/gsttracerutils.c: + tracer: Initialize GstTracer _priv_tracers and quarks unconditionnally + Some people might use tracer hooks even if GST_TRACER_PLUGINS is not + set. + https://bugzilla.gnome.org/show_bug.cgi?id=760979 + +2016-02-20 10:18:06 +0000 Tim-Philipp Müller + + * docs/manual/appendix-integration.xml: + docs: manual: remove dead link from integration page + +2016-02-20 10:13:38 +0000 Tim-Philipp Müller + + * docs/manual/advanced-dataaccess.xml: + docs: manual: fix formatting + advanced-dataaccess.xml:1210: element listitem: validity error : Element + listitem content does not follow the DTD, expecting (...), + got (para CDATA para ) + + +2016-02-20 00:55:30 +0000 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: check for git in create-uninstalled-setup.sh as well + +2016-02-19 20:26:26 +0530 Nirbheek Chauhan + + * gst/glib-compat.c: + * gst/gsttask.c: + * libs/gst/net/gstptpclock.c: + Whenever we include windows.h, also define WIN32_LEAN_AND_MEAN + This reduces the number of symbols and code pulled in drastically + +2016-02-13 06:53:24 +0530 Nirbheek Chauhan + + * gst/printf/gst-printf.h: + printf: On MSVC, also define HAVE_STDINT_H_WITH_UINTMAX + MSVC provides stdint.h but not inttypes.h, and we need to include stdint.h to + get intmax_t + +2016-02-13 06:42:06 +0530 Nirbheek Chauhan + + * libs/gst/net/gstptpclock.c: + ptpclock: Only include unistd.h if found + unistd.h is not provided by the Microsoft Visual C++ compiler. It instead + provides the necessary defines through io.h + +2016-02-13 06:19:52 +0530 Nirbheek Chauhan + + * gst/gstplugin.c: + plugin: Only check for S_IFBLK if it is defined + Windows does not define S_IFBLK since it doesn't have block devices + +2016-02-19 20:17:02 +0000 Tim-Philipp Müller + + * win32/MANIFEST: + * win32/README.txt: + * win32/common/dirent.c: + * win32/common/dirent.h: + * win32/common/gtchar.h: + * win32/common/libgstdataprotocol.def: + * win32/vs10/Common.props: + * win32/vs10/Library.props: + * win32/vs10/Plugin.props: + * win32/vs10/ReadMe.txt: + * win32/vs10/Tool.props: + * win32/vs10/base/base.vcxproj: + * win32/vs10/base/base.vcxproj.filters: + * win32/vs10/controller/controller.vcxproj: + * win32/vs10/controller/controller.vcxproj.filters: + * win32/vs10/generated/generated.vcxproj: + * win32/vs10/generated/generated.vcxproj.filters: + * win32/vs10/gst-inspect/gst-inspect.vcxproj: + * win32/vs10/gst-inspect/gst-inspect.vcxproj.filters: + * win32/vs10/gst-launch/gst-launch.vcxproj: + * win32/vs10/gst-launch/gst-launch.vcxproj.filters: + * win32/vs10/gst-typefind/gst-typefind.vcxproj: + * win32/vs10/gst-typefind/gst-typefind.vcxproj.filters: + * win32/vs10/gstcoreelements/gstcoreelements.vcxproj: + * win32/vs10/gstcoreelements/gstcoreelements.vcxproj.filters: + * win32/vs10/gstreamer.sln: + * win32/vs10/gstreamer/gstreamer.vcxproj: + * win32/vs10/gstreamer/gstreamer.vcxproj.filters: + * win32/vs10/net/net.vcxproj: + * win32/vs10/net/net.vcxproj.filters: + * win32/vs6/grammar.dsp: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstcontroller.dsp: + * win32/vs6/libgstcoreelements.dsp: + * win32/vs6/libgstnet.dsp: + * win32/vs6/libgstreamer.dsp: + * win32/vs7/grammar.vcproj: + * win32/vs7/gst-inspect.vcproj: + * win32/vs7/gst-launch.vcproj: + * win32/vs7/gstreamer.sln: + * win32/vs7/libgstbase.vcproj: + * win32/vs7/libgstcontroller.vcproj: + * win32/vs7/libgstcoreelements.vcproj: + * win32/vs7/libgstreamer.vcproj: + * win32/vs8/grammar.vcproj: + * win32/vs8/gst-inspect.vcproj: + * win32/vs8/gst-launch.vcproj: + * win32/vs8/gstreamer.sln: + * win32/vs8/libgstbase.vcproj: + * win32/vs8/libgstcontroller.vcproj: + * win32/vs8/libgstcoreelements.vcproj: + * win32/vs8/libgstreamer.vcproj: + win32: update README and remove outdated build cruft + This hasn't been touched for generations, doesn't work, + and is just causing confusion. We also don't want to + maintain these files manually. + +2016-02-19 08:43:00 +0000 George Yunaev + + * docs/manual/advanced-dataaccess.xml: + manual: Explain what happens if upstream elements are removed from the pipeline without draining them first + https://bugzilla.gnome.org/show_bug.cgi?id=762302 + +2016-02-19 14:41:55 +0000 Tim-Philipp Müller + + * tests/check/elements/identity.c: + * tests/check/libs/gstharness.c: + tests: fix indentation + +2016-02-19 12:38:21 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.7.2 === + +2016-02-19 11:47:52 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 1.7.2 + +2016-02-19 10:29:40 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations + +2016-02-18 14:20:17 +0000 Julien Isorce + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + uninstalled.pc: add support for non libtool build systems + Currently the .la path is provided which requires to use libtool as + mentioned in the GStreamer manual section-helloworld-compilerun.html. + It is fine as long as the application is built using libtool. + So currently it is not possible to compile a GStreamer application + within gst-uninstalled with CMake or other build system different + than autotools. + This patch allows to do the following in gst-uninstalled env: + gcc test.c -o test $(pkg-config --cflags --libs gstreamer-1.0) + Previously it required to prepend libtool --mode=link + https://bugzilla.gnome.org/show_bug.cgi?id=720778 + +2016-02-18 11:43:22 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "pad: PULL probes are called without a buffer so don't require any of the data flags to be set" + This reverts commit b89fa4786b3df6cb79f662c037dee74b3f7428d6. + The changes break various tests. + +2016-02-18 11:43:04 +0200 Sebastian Dröge + + * tests/check/gst/gstpad.c: + Revert "pad: Add test for blocking pull probe" + This reverts commit 17d30e944be0425ebb4fb6046f82d1f61701fe8f. + The PULL probe changes break various tests. + +2016-02-18 11:09:36 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Protect against failing to map input memory when merging memories + https://bugzilla.gnome.org/show_bug.cgi?id=762239 + +2016-01-28 16:22:17 +0100 Matej Knopp + + * tests/check/gst/gstpad.c: + pad: Add test for blocking pull probe + https://bugzilla.gnome.org/show_bug.cgi?id=761211 + +2016-02-17 16:57:27 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: PULL probes are called without a buffer so don't require any of the data flags to be set + https://bugzilla.gnome.org/show_bug.cgi?id=761211 + +2016-02-17 16:41:02 +0200 Sebastian Dröge + + * gst/gstelement.c: + Revert "element: Don't hold state lock all the time while sending an event" + This reverts commit b427997119a2b6aacbeb550f729936f8b963e24b. + It breaks things that used to work before, even if the change by itself is + correct and the previous code is just working around deeper bugs in the async + state change code. Let's go back to what previously worked and then fix async + state changes in general. + https://bugzilla.gnome.org/show_bug.cgi?id=760532 + +2016-02-17 15:26:49 +0100 Edward Hervey + + * gst/gstghostpad.c: + Revert "ghostpad: Do nothing in _internal_activate_push_default" + That commit would break scheduling reconfiguration with ghostpads + This reverts commit ab55ad7eaad4fa2c0b16c789350e882cf70a27ed. + +2016-02-17 15:25:08 +0100 Edward Hervey + + * tests/check/gst/gstghostpad.c: + check: Add test for checking scheduling reconfiguration with ghostpads + Showcases the regression introduced by this commit: + Commit: ab55ad7eaad4fa2c0b16c789350e882cf70a27ed + Author: Stian Selnes + Date: Wed Jan 27 13:20:23 2016 +0100 + ghostpad: Do nothing in _internal_activate_push_default + +2016-02-17 11:02:34 +0100 Havard Graff + + * tests/check/gst/gstghostpad.c: + ghostpad: add some tests for activation + https://bugzilla.gnome.org/show_bug.cgi?id=761913 + +2016-01-27 13:20:23 +0100 Stian Selnes + + * gst/gstghostpad.c: + ghostpad: Do nothing in _internal_activate_push_default + When calling gst_pad_activate_mode() on a ghostpad + gst_ghost_pad_activate_push_default() will be called. This will call + gst_pad_activate_mode() on the proxypad (which is internal of the + ghostpad), calling gst_ghost_pad_internal_activate_push_default(), which + again will call gst_pad_activate_mode() on the original ghostpad. + By simply returning TRUE in + gst_ghost_pad_internal_activate_push_default() the redundant call to + gst_pad_activate_mode() (for the same pad) is avoided. + https://bugzilla.gnome.org/show_bug.cgi?id=761913 + +2016-02-16 17:53:10 -0300 Thiago Santos + + * gst/gstregistrychunks.c: + registrychunks: remove unused macro + macro was added in 2011 and isn't used anymore + +2016-02-16 19:11:59 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + * tests/check/elements/queue2.c: + Revert "queue2: add overrun signal" + This reverts commit 8ae8b2723d0cf179a4f09b2f6c5f797e2d97034d. + It's not used anymore by anything and was considered a bad idea in general. + +2014-06-05 13:27:28 -0700 Evan Nemerson + + * gst/gstbuffer.c: + * gst/gstcaps.c: + * gst/gstcapsfeatures.c: + * gst/gstclock.h: + * gst/gstevent.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstmessage.c: + * gst/gstpadtemplate.c: + * gst/gstpluginfeature.c: + * gst/gstquery.c: + * gst/gststructure.c: + * gst/gsttagsetter.c: + * gst/gsttypefindfactory.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + docs: annotate C examples as such + https://bugzilla.gnome.org/show_bug.cgi?id=731292 + +2016-02-15 11:13:40 -0300 Thiago Santos + + * tests/benchmarks/tracerserialize.c: + benchmark: tracerserialize: add missing return statement + tracerserialize.c:117:1: error: control reaches end of + non-void function [-Werror=return-type] + +2016-02-15 10:06:09 -0300 Thiago Santos + + * gst/gstprotection.c: + * libs/gst/check/gstharness.c: + * tests/check/gst/gstsystemclock.c: + protection/harness/systemclock: move declaration out of for loop initialization + C90 compilers complain about it + error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode + Also run gst-indent on systemclock tests. + +2016-01-27 15:16:03 +0100 Havard Graff + + * libs/gst/check/gstharness.c: + harness: always set our test-clock on the harnessed element + The integration is already so tight, there is no reason to + not further formalize it! + https://bugzilla.gnome.org/show_bug.cgi?id=761914 + +2016-02-13 16:10:27 +0000 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: fix compilation + Was supposed to be squashed with 336c7bb6 + https://bugzilla.gnome.org/show_bug.cgi?id=761910 + +2016-02-13 16:10:11 +0000 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: fix indentation + +2016-01-21 13:33:15 +0100 Stian Selnes + + * libs/gst/check/gstharness.c: + * tests/check/libs/gstharness.c: + harness: Fix MT issues when forwarding event/query to sink harness + https://bugzilla.gnome.org/show_bug.cgi?id=761910 + +2016-02-13 10:04:42 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add new -bad libraries audio, player and wayland to paths + And remove egl which no longer exists. + +2016-02-12 11:57:55 -0800 Martin Kelly + + * libs/gst/base/gstpushsrc.h: + pushsrc: fix minor typos in header + https://bugzilla.gnome.org/show_bug.cgi?id=761970 + +2016-01-21 13:28:23 +0100 Stian Selnes + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + harness: Add event stress test functions with callback + Similar to the stress test functions for buffers that has a callback to + create the buffer to be pushed, it's useful to have functions that use a + callback to create the event to be pushed. + API: gst_harness_stress_push_event_with_cb_start() + API: gst_harness_stress_push_event_with_cb_start_full() + API: gst_harness_stress_send_upstream_event_with_cb_start() + API: gst_harness_stress_push_upstream_event_with_cb_start_full() + https://bugzilla.gnome.org/show_bug.cgi?id=761932 + +2016-01-14 21:54:42 +0100 Havard Graff + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/libs/gsttestclock.c: + testclock: add crank method + And use it inside GstHarness + API: gst_test_clock_crank() + https://bugzilla.gnome.org/show_bug.cgi?id=761906 + +2015-12-09 13:43:38 +1100 Havard Graff + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + harness: enable empty harness creation and refactor around this + Also make the testclock a member of the harness, allowing some + more interactions with the clock prior to adding elements. + https://bugzilla.gnome.org/show_bug.cgi?id=761905 + +2016-02-12 15:12:43 +0100 Stian Selnes + + * libs/gst/check/gstcheck.h: + check: fix unused parameter compiler warning + https://bugzilla.gnome.org/show_bug.cgi?id=761919 + +2015-08-04 17:09:35 +0200 Mikhail Fludkov + + * libs/gst/check/gstharness.c: + harness: fix the race in blocking push mode + Depending on when gst_harness_pull was called - before the buffer reached + gst_harness_chain or after we can get different behaviors of the test + with enabled blocking push mode. The fix makes the behavior always the + same. In pull function we get the buffer first, thus making sure + gst_harness_chain waits for the signal, and emitting the signal after. + https://bugzilla.gnome.org/show_bug.cgi?id=761931 + +2016-02-04 15:16:41 +0100 Stian Selnes + + * libs/gst/check/gstcheck.h: + check: Add tcase_skip_broken_loop_test + https://bugzilla.gnome.org/show_bug.cgi?id=761917 + +2016-01-21 13:25:40 +0100 Stian Selnes + + * libs/gst/check/gstharness.c: + harness: Fix docs for stress test functions + notify is not called per buffer, but when the thread is freed. + Comment about serialized events and OOB does not make sense for upstream + events. + https://bugzilla.gnome.org/show_bug.cgi?id=761909 + +2015-12-08 14:18:21 +0100 Stian Selnes + + * libs/gst/check/gstharness.c: + harness: Unset sink_forward_pad before tearing down sink_harness + Set the sink_forward_pad to NULL before tearing down sink_harness to + avoid that the harness tries to forward events/queries to it while it's + tearing down. + https://bugzilla.gnome.org/show_bug.cgi?id=761904 + +2015-09-29 12:12:24 +0200 Havard Graff + + * libs/gst/check/gstharness.c: + harness: fix up docs to reference functions properly + https://bugzilla.gnome.org/show_bug.cgi?id=761901 + +2016-02-10 14:01:54 +0100 Víctor Manuel Jáquez Leal + + * gst/gstbufferpool.c: + bufferpool: pass acquire params to alloc_buffer + When allocating a new buffer in the pool, both the do_alloc_buffer() and the + vmethod, alloc_buffer(), receive the parameter GstBufferPoolAcquireParams. + Nonetheless, when default_acquire_buffer() calls the do_alloc_buffer() it does + not pass the received GstBufferPoolAcquireParams, so when the user pass those + parameters they are ignored by alloc_buffer() vmethod. + This one-liner patch pass the received acquire params to do_alloc_buffer(). + https://bugzilla.gnome.org/show_bug.cgi?id=761824 + +2016-02-10 09:09:29 +0100 Stian Selnes + + * gst/gstsystemclock.c: + * tests/check/gst/gstsystemclock.c: + systemclock: Fix wait/unschedule race + Fixes a race where an entry is set to BUSY in + gst_system_clock_id_wait_jitter() and is UNSCHEDULED before + gst_system_clock_id_wait_jitter_unlocked() starts processing it. The + wakeup added by gst_system_clock_id_unschedule() must be cleaned up. + Two stress tests are added. One test that triggers the specific issue + described above. The second stresses the code path where a wait is + rescheduled because the poll returned early. + https://bugzilla.gnome.org/show_bug.cgi?id=761586 + +2016-02-05 15:34:47 -0300 Thiago Santos + + * gst/gstsystemclock.c: + systemclock: handle unschedule of late entries + If the clockentry is too late and is unscheduled before it gets + a change to detect its lateness the wakeup count and the poll are + used but never properly cleaned up. This leaves it in a dirty state + that is going to mess with the next clock entry waiting requests. + https://bugzilla.gnome.org/show_bug.cgi?id=761586 + +2016-02-05 19:08:18 -0300 Thiago Santos + + * tests/check/Makefile.am: + tests: extend the AM_TESTS_ENVIRONMENT from check.mak + To get the CK_DEFAULT_TIMEOUT defined for all tests + https://bugzilla.gnome.org/show_bug.cgi?id=761472 + +2016-02-05 18:01:52 -0300 Thiago Santos + + * autogen.sh: + * common: + Automatic update of common submodule + From 86e4663 to b64f03f + +2016-02-04 10:07:22 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix stray discont flag set on outgoing buffers in push mode + We have no guarantees about what flags are set on buffers we take + out of the GstAdapter. If we push out multiple buffers from the + first input buffer (which will have discont set), only the first + buffer we push out should be flagged as discont, not all of the + buffers produced from that first initial input buffer. + Fixes issue where the first few mp3 frames/seconds of data in push + mode were skipped or garbled in some cases, and the discont flags + would also trip up decoders which were getting drained/flushed for + every buffer. This was a regression introduced in 1.6 apparently. + +2016-02-02 16:35:34 +0100 Thibault Saunier + + * libs/gst/controller/gstdirectcontrolbinding.c: + controller: Do not unset uninitiallized GValue + In case the property was not interpollable we might never initialize + the GValue, we should thus never unset it. + +2016-02-02 16:34:51 +0000 Tim-Philipp Müller + + * docs/pwg/advanced-allocation.xml: + docs: pwg: fix missing end of line semicolon in custom meta example + +2016-02-02 10:56:35 +0000 Tim-Philipp Müller + + * gst/gsturi.c: + uri: add guard to make sure gstreamer is initialized + https://bugzilla.gnome.org/show_bug.cgi?id=761448 + +2016-02-01 18:41:55 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add new rtsp server plugin location to plugins path + +2016-01-25 16:30:04 +0900 HoonHee Lee + + * libs/gst/base/gstbaseparse.c: + baseparse: Try to generate caps on the srcpad before forwarding GAP event + To configure downstream elements and complete initial pre-rolling, + ensure we have default output caps before forwarding GAP event. + https://bugzilla.gnome.org/show_bug.cgi?id=753899 + +2016-01-28 20:18:55 -0700 Alex Henrie + + * plugins/elements/gsttypefindelement.c: + typefindelement: Improve English grammar + https://bugzilla.gnome.org/show_bug.cgi?id=761273 + +2016-01-27 12:45:20 +0000 Luis de Bethencourt + + * docs/manual/advanced-clocks.xml: + docs: fix an other typo in clock chapter + Shockingly I missed this bigger typo in the previos fix + +2016-01-27 12:24:57 +0000 Luis de Bethencourt + + * docs/manual/advanced-clocks.xml: + docs: fix typo in clock chapter + +2016-01-25 12:09:54 +0900 Vineeth TM + + * tests/check/gst/gstinfo.c: + tests:gstinfo: Fix string memory leak + info_fourcc test leaks string. + https://bugzilla.gnome.org/show_bug.cgi?id=761071 + +2016-01-23 16:00:48 +0000 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: info: make work without registry + +2016-01-22 12:50:08 +0000 Tim-Philipp Müller + + * docs/design/part-tracing.txt: + * gst/gsttracerutils.c: + * tests/benchmarks/tracing.sh: + tracer: rename GST_TRACER_PLUGINS env var to GST_TRACERS + +2016-01-21 08:12:01 +0100 Stefan Sauer + + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + * tests/check/gst/gsttracerrecord.c: + tracerrecord: don't leak the spec structures + Change the gst_tracer_record_new() api to take the parameters the make the + spec structure directly. This allows us to own the top-level structure and + also collect the args so that we can take ownership of the sub-structures. + https://bugzilla.gnome.org/show_bug.cgi?id=760821 + +2016-01-21 15:45:30 +0000 Tim-Philipp Müller + + * gst/gstdevice.c: + device: fix comparison in _has_classesv() + We're comparing a pointer type with '\0' here, which + probably isn't right, and the loop condition made sure + that classes[0] is != NULL already, so it's pointless. + Was probaby meant to check if the string pointed to is + not empty, so make it do that instead. + +2016-01-20 20:32:24 +0100 Stefan Sauer + + * tests/check/gst/gsttracerrecord.c: + test/tracerrecord: unref objects and free string + +2016-01-18 22:45:58 +0000 Florin Apostol + + * tests/check/gst/gstsystemclock.c: + systemclock: tests: added stress test for async order + Keep inserting alarms at the beginning of the list. Due to + https://bugzilla.gnome.org/show_bug.cgi?id=760757 + alarm thread will get confused and not serve them in order. + +2016-01-18 16:25:20 +0000 Florin Apostol + + * gst/gstsystemclock.c: + systemclock: fixed race condition in handling alarms + When choosing the first entry from the list, gst_system_clock_async_thread + must set the entry state to busy before releasing the clock lock. Otherwise + a new entry could be added to the beginning of the list and + gst_system_clock_async_thread will be unaware and keep waiting on the entry + it has already chosen. + Also improved messages about expected state and bumped them to ERROR level + to detect unexpected state changes. + https://bugzilla.gnome.org/show_bug.cgi?id=760757 + +2016-01-20 11:07:17 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + utils: remove duplicate check + +2016-01-20 09:57:00 +0000 Tim-Philipp Müller + + * plugins/elements/gstmultiqueue.c: + multiqueue: two small fixes for when an existing pad is requested + Unlock when returning NULL from gst_single_queue_new(), and don't + crash with debug logging enabled if NULL is returned. + Spotted by Steven Hoving. + +2016-01-20 10:02:37 +0100 Stefan Sauer + + * gst/gstvalue.c: + gstvalue: remove a half finishesh sentence in the docs + No idea what was the idea here. SO lets just drop it. + +2016-01-19 14:39:06 +0900 Vineeth TM + + * gst/gsttracerrecord.c: + tracerrecord: Fix self->spec structure invalid free + self->spec is got using g_value_get_boxed(), which is a transfer none function. + So the same should not be freed, which is resulting in wrong behavior. + https://bugzilla.gnome.org/show_bug.cgi?id=760821 + +2016-01-20 09:25:44 +0100 Vineeth TM + + * gst/gsttracerrecord.c: + tracerrecord: Initialise flags to avoid wrong comparision + GstTracerValueFlags is not being initialized and the same could result in wrong + comparision and behavior. Hence initializing it to GST_TRACER_VALUE_FLAGS_NONE. + https://bugzilla.gnome.org/show_bug.cgi?id=760821 + +2016-01-20 09:18:01 +0100 Stefan Sauer + + * tests/check/gst/gstinfo.c: + tests/gst/info: Fix messages glist memory leak + +2016-01-19 15:03:55 +0900 Vineeth TM + + * tests/check/gst/gsttracerrecord.c: + tests: tracerrecord: Fix messages glist memory leak + https://bugzilla.gnome.org/show_bug.cgi?id=760821 + +2016-01-18 21:12:53 +0100 Stefan Sauer + + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gststructure.c: + * gst/gstvalue.c: + tracer: add an internal ptr format for tracer serialisation + We need to apply the string wrapping that value serialisation does also in the + tracer logging, otherwise we can't parse nested structures. + +2016-01-18 21:09:49 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + * tools/gst-stats.c: + tracer/gststats: fix mismatch between '.class' and tracer args + Clean up from the recent changes. The logging descriptiors did not match what we logged. + +2015-11-12 01:14:34 +1100 Jan Schmidt + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Add use-tags-bitrate property + The use-tags-bitrate property makes queue2 look at + tag events in the stream and extract a bitrate for the + stream to use when calculating a duration for buffers + that don't have one explicitly set. + This lets queue2 sensibly buffer to a time threshold + for any bytestream for which the general bitrate is known. + +2016-01-19 12:04:16 +0000 Luis de Bethencourt + + * gst/gsttracerrecord.c: + tracerrecord: avoid overwriting value + res value is overwritten, remove the assignment. + priv__gst_structure_append_template_to_gstring () always returns TRUE + anyway. + CID 1349645 + +2016-01-19 11:11:25 +0100 Edward Hervey + + * tests/benchmarks/Makefile.am: + benchmarks: Disable tracerserialize benchmark on GST_DISABLE_GST_DEBUG + no gst-debugging => no tracer logging (and no pony either) + +2016-01-19 11:10:30 +0100 Edward Hervey + + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + tracerrecord: Disable logging if GST_DISABLE_GST_DEBUG + Make the gst_tracer_record_log() a no-op if the gst-debug subsystem + is disabled. + +2016-01-18 19:17:16 +0000 Tim-Philipp Müller + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: fail flag deserialization on invalid flag names + +2016-01-18 19:10:48 +0000 Tim-Philipp Müller + + * tests/check/gst/gststructure.c: + tests: structure: fix wrong flag name in deserialization test + There is no GST_SEEK_FLAGS_NONE only GST_SEEK_FLAG_NONE (but + the deserializer silently skips bad flag names currently). + +2016-01-17 23:49:27 +0000 Tim-Philipp Müller + + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + * tools/gst-stats.c: + tracers: fix thread-id casts to 64-bit ints on 32-bit systems + https://bugzilla.gnome.org/show_bug.cgi?id=760762 + +2016-01-18 10:13:02 +0900 Vineeth TM + + * gst/gst.c: + gst: ref/unref new enum types in gst_init/deinit + https://bugzilla.gnome.org/show_bug.cgi?id=760767 + +2016-01-17 00:08:33 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update exports for new flags get_type() + +2016-01-16 22:43:23 +0100 Philip Van Hoof + + * gst/gsttracer.c: + * gst/gsttracer.h: + tracer.h: don't include private noinst header gsttracerutils.h in a public header + https://bugzilla.gnome.org/show_bug.cgi?id=760732 + +2016-01-16 21:24:19 +0100 Stefan Sauer + + * tests/benchmarks/tracing.sh: + benchmark: improve script + Use a temp file for the log and fix one env-var. + +2016-01-16 21:23:10 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + tracer/stats: use the right log template + When porting we used the wrong record (copy and paste). + +2016-01-16 21:04:46 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gsttracerrecord.h: + tracer: update the docs + Add the new enum and flags. Remove the GstTracerRecordPrivate. + +2016-01-16 21:02:39 +0100 Stefan Sauer + + * tools/gst-stats.c: + gst-stats: update to latest tarcer api + The thread-ids are serialized as uint64. The 'elem-ix' got changed to + 'element-ix'. Make the code a bit more robust. + +2016-01-16 18:55:07 +0100 Stefan Sauer + + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + * plugins/tracers/gststats.c: + tracer: use the new flags to create the optional field in the format string + This spares us explicitly listing the field in the spec. and thus hide this + implementation detail. + +2016-01-16 18:52:32 +0100 Stefan Sauer + + * docs/design/part-tracing.txt: + * gst/gsttracerrecord.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracer: add a GstTracerValueFlags and replace strings + This allows us to document the flags and makes the logs a bit smaller. + +2016-01-16 16:01:38 +0000 Tim-Philipp Müller + + * gst/gstmessage.c: + message: add function guard to gst_message_set_buffering_stats() + https://bugzilla.gnome.org/show_bug.cgi?id=760704 + +2016-01-16 14:51:37 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/gst/Makefile.am: + * gst/gst.h: + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + * gst/gsttracerutils.c: + * plugins/tracers/Makefile.am: + * tests/check/Makefile.am: + gst.h: Don't spew warnings if GST_USE_UNSTABLE_API is not defined + Only hide GstTracer and GstTracerRecord API behind GST_USE_UNSTABLE_API, + but don't spew any warnings, otherwise everyone has to define this + to avoid compiler warnings. + This reverts parts of commit 89ee5d948dff560204e6edd210c44ed2b8654b8e. + +2016-01-16 13:30:34 +0100 Stefan Sauer + + * tests/benchmarks/tracerserialize.c: + * tests/benchmarks/tracing.sh: + benchmarks: update the tracer benchmark and add a shell benchmark + +2016-01-16 13:28:32 +0100 Stefan Sauer + + * docs/design/part-tracing.txt: + docs/design: update tracerspec examples + +2016-01-16 13:27:59 +0100 Stefan Sauer + + * docs/design/draft-tagreading.txt: + docs/design: spell checking + +2016-01-16 13:24:16 +0100 Stefan Sauer + + * configure.ac: + * docs/gst/Makefile.am: + * gst/gst.h: + * gst/gsttracer.c: + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + * gst/gsttracerutils.c: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + * tests/check/Makefile.am: + * win32/common/libgstreamer.def: + tracer: add a GFlag for the tracer scope + Port all tracers. Add the GST_USE_UNSTABLE_API flag to the internal CFLAGS so + that we don't have to specify this for gir, docs, mkenum, ... + +2016-01-16 10:48:02 +0100 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + output-selector: Make access to the active pad and last buffer thread-safe + Both can be modified from different threads at the same time. + +2016-01-16 10:47:36 +0100 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + output-selector: Notify when the active-pad property is changing + +2016-01-12 14:59:04 +0100 Stefan Sauer + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gststructure.c: + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerrecord.c: + * gst/gsttracerrecord.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gsttracerrecord.c: + * win32/common/libgstreamer.def: + tracerrecord: add a log record class + We use this class to register tracer log entry metadata and build a log + template. With the log template we can serialize log data very efficiently. + This also simplifies the logging code, since that is now a simple varargs + function that is not exposing the implementation details. + Add docs for the new class and basic tests. + Remove the previous log handler. + Fixes #760267 + +2016-01-15 09:48:32 +0100 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Check return value of g_socket_close() + CID 1348452 + +2016-01-15 09:02:42 +0100 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Free data after removing it from the list + Does not matter here but makes Coverity more happy. It can't + know that g_list_remove() only looks at the pointer value but + does not dereference it. + CID 1348454 + +2016-01-15 00:30:59 +0530 Nirbheek Chauhan + + * gst/gstdevicemonitor.c: + GstDeviceMonitor: Clarify the behaviour of gst_device_monitor_add_filter + +2016-01-15 00:25:05 +0530 Nirbheek Chauhan + + * gst/gstdevicemonitor.c: + GstDeviceMonitor: Don't remove unmatched class filters + If no providers for a particular class could be found, then removing unmatched + filters would cause all devices to be returned instead which is not at all what + the user intended. We still return 0 for unmatched filters. + +2016-01-13 21:32:20 +0000 Florin Apostol + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Fix GError memory leak in handling NTP response + Error was not released if gst_ntp_packet_receive failed. + https://bugzilla.gnome.org/show_bug.cgi?id=760598 + +2016-01-13 13:10:10 +1100 Matthew Waters + + * win32/common/libgstreamer.def: + win32: update exports for API additions + +2016-01-11 16:31:39 +1100 Matthew Waters + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + info: expose debugging printf functions + Other gst libraries and/or elements may want to add some debug logging to an + external debug system or implement delayed debugging for performance reasons. + Exposes the internal __gst_vasprintf as gst_info_vasprintf which has a fallback + to g_vasprintf if the debug system is disabled. + API: gst_info_vasprintf + API: gst_info_strdup_vprintf + API: gst_info_strdup_printf + https://bugzilla.gnome.org/show_bug.cgi?id=760421 + +2016-01-11 21:17:25 +0100 Carlos Rafael Giani + + * libs/gst/base/gstbasesrc.c: + basesrc: Only set duration/position query values in case of query success + Currently, the query values are being set even if the query itself was + determined to have failed. Fix this to ensure the values are only set in + case of a query success. + https://bugzilla.gnome.org/show_bug.cgi?id=760479 + +2016-01-10 14:30:05 +0100 Stefan Sauer + + * plugins/tracers/gstlatency.c: + * plugins/tracers/gststats.c: + tracers: code clean ups + Drop some trailing whilespace. Make field order consistent. + +2016-01-08 23:35:53 +0100 Stefan Sauer + + * tests/benchmarks/tracerserialize.c: + benchmark: fix copy'n'past of the file-description comment + +2016-01-08 23:06:55 +0100 Stefan Sauer + + * tests/benchmarks/.gitignore: + * tests/benchmarks/Makefile.am: + * tests/benchmarks/tracerserialize.c: + benchmark: add a benchmark for bgo/760267 + Big suprise - GstStructure is faster than GVariant. + +2015-03-10 13:07:18 +0900 HoonHee Lee + + * plugins/elements/gstfunnel.c: + funnel: improve debug message + https://bugzilla.gnome.org/show_bug.cgi?id=745939 + +2016-01-08 19:25:24 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + * tests/check/gst/gstinfo.c: + info: add buffer list support to GST_PTR_FORMAT + +2015-11-25 17:36:25 +0100 Aurélien Zanelli + + * gst/gstcontrolsource.h: + controlsource: fix GetValue and GetValueArray documentation + GstControlSourceGetValue() value paramater is a gdouble, not a GValue + and GstControlSourceGetValueArray doesn't return a GstValueArray but + an array of double. + https://bugzilla.gnome.org/show_bug.cgi?id=758668 + +2016-01-07 23:03:48 +0100 Stefan Sauer + + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstlog.c: + * plugins/tracers/gststats.c: + tracer: harmonize the query hooks + In post hooks always pass the return value as the last param. Pass the query + also to post hooks since it is still alive. + +2016-01-07 22:47:37 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + tracers/stats: add missing parameters to callback functions + +2016-01-07 22:43:58 +0100 Stefan Sauer + + * gst/gsttracerutils.c: + tracerutils: update #endif comment + We changed the define, but left the comment inconsistent. + +2016-01-07 19:13:03 +0100 Stefan Sauer + + * docs/gst/Makefile.am: + * docs/gst/gstreamer-sections.txt: + * gst/gsttracerutils.h: + tracerutils: document the tracer hook functions + Document all tracer hook function pointer together with the detail string that + one needs to use with gst_tracing_register_hook(). + +2016-01-07 18:46:21 +0200 Sebastian Dröge + + * gst/gsttracerutils.c: + tracer: Use GST_DISABLE_GST_TRACER_HOOKS instead of GST_DISABLE_GST_DEBUG everywhere + Previously we used the latter one still for the tracer utility code, causing + undefined references in the resulting binary if the debugging system was + disabled but the tracer system not. + +2016-01-07 18:41:25 +0200 Sebastian Dröge + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + * gst/gsttracerutils.h: + gst: Rename _priv_gst_info_start_time to _priv_gst_start_time and initialize it centrally + It's used by the debugging and tracer subsystem and in various files, make it + a central thing that is initialized independ of the existence of those + subsystems. + +2016-01-06 21:42:30 +0100 Stefan Sauer + + * win32/common/libgstreamer.def: + win32: update win32 exports + Remove the _hook_id() methods we made internal in the prev commit. + +2016-01-06 21:17:16 +0100 Stefan Sauer + + * gst/gststructure.c: + structure: log a warning if we can't serialize a field + The function always returns TRUE right now, so atleast log something. + +2015-10-06 12:49:00 +0000 Aleksander Wabik + + * tests/check/elements/queue2.c: + tests: queue2: add test for fill level arithmetic overflow + https://bugzilla.gnome.org/show_bug.cgi?id=755971 + +2016-01-06 19:51:44 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: avoid calculating fill levels multiple times + Macro expansion means we might calculate the fill level once + for the check and then possibly again for the return value. + +2016-01-06 19:50:21 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix fill level arithmetic overflow with large values + Based on patch by: Aleksander Wabik + https://bugzilla.gnome.org/show_bug.cgi?id=755971 + +2016-01-06 20:41:26 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * plugins/tracers/gstrusage.c: + tracer: make gst_tracing_register_hook_id static + We don't need to expose this as public API. Change the only plugin that was + using it. + +2016-01-06 18:56:38 +0000 Tim-Philipp Müller + + * docs/design/Makefile.am: + docs: design: update list of disted files after file rename + +2016-01-06 19:42:49 +0200 Sebastian Dröge + + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-sections.txt: + docs: Hide NTP packet API and add GST_PTP_STATISTICS_* defines to the docs + +2016-01-06 18:17:27 +0100 Stefan Sauer + + * libs/gst/net/gstptpclock.h: + docs: remove parent docs for GstPtpClock + Instance docs don't need to docuemnt the parent (first member). + +2016-01-06 18:14:06 +0100 Stefan Sauer + + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-sections.txt: + docs: cleanup -unused.txt report for libs + The IGNORE_H_FILES can only contain files or dirs. + +2016-01-06 17:58:11 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + docs: add more core api to the right sections + Add new and documented api reported in -unused.txt to -section.txt. + +2016-01-06 17:54:44 +0100 Stefan Sauer + + * docs/gst/Makefile.am: + docs: exclude more header from doc-scan + Exclude gst/printf/*.h and a few generated .h files from the api-scan. This + makes -unused.txt report file from gtkdoc useful again. + +2016-01-06 16:21:40 +0200 Sebastian Dröge + + * gst/gstclock.c: + clock: adjust/unadjust_with_calibration() have a clock parameter but it's useless + Document this, for 2.0 we should just remove that parameter. + +2016-01-06 16:19:22 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + clock: Add gst_clock_unadjust_with_calibration() + We already have gst_clock_adjust_with_calibration() and + gst_clock_unadjust_unlocked(), having the other variant is useful. + +2016-01-06 13:33:39 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + docs: add new pad-event function to the docs + +2016-01-06 13:26:27 +0100 Stefan Sauer + + * docs/gst/Makefile.am: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + docs: hide internal tracer api from docs + Also address warnigns regarding the unstable tracer api. + +2016-01-06 12:47:26 +0100 Stefan Sauer + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/gsttracer.c: + docs: add the tracer to the docs + Add GstTracer and GstTracerFactory to the core docs. + +2016-01-06 11:52:53 +0100 Stefan Sauer + + * docs/design/part-tracing.txt: + docs: rename the tracer doc to part since it is now merged + +2016-01-06 11:35:46 +0100 Stefan Sauer + + * gst/Makefile.am: + tracerutils: move header to noinst section + This is internal code, that is only to be used in core. + +2016-01-06 11:31:16 +0100 Stefan Sauer + + * configure.ac: + * gst/gsttracerutils.h: + configure: add a new option to disable the tracer hooks + This was previously done via {enable,disable}-gst-debug. Since both subsystems + are independent having separate options is better. + +2016-01-05 16:44:53 +0200 Sebastian Dröge + + * gst/gstclock.c: + * libs/gst/net/gstnetclientclock.c: + clock: Fix typo + clocked -> clock + +2016-01-05 14:59:34 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Disconnect the "synced" signal handler from the internal clock + Not from the external one. + +2016-01-05 13:57:12 +0100 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + controller: rename new cubic interpolation mode + Don't abbreviate to 'mono' and use 'monotonic' instead. + +2016-01-05 14:23:26 +0200 Sebastian Dröge + + * gst/gstclock.c: + clock: Don't allow setting an unsynced clock as master + +2016-01-05 14:21:58 +0200 Sebastian Dröge + + * gst/gstclock.c: + clock: Don't try to slave unsynced clocks + They will return useless values from get_time(). + +2016-01-05 13:41:08 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + ntp: The clock inherits from GstNetClientClock, not just GstSystemClock + +2016-01-04 17:18:07 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Destroy a cached clock 60 seconds after its last use + There's not much lost by having the clock idle around a bit longer but it will + potentially allow anybody wanting to use the same clock server again to sync + much faster. + +2016-01-04 16:31:23 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Only ever run one clock against a specific server + If multiple net/NTP clocks are created for the same server, reuse the same + internal clock for all of them. This makes sure that we don't flood the server + with too many requests and also possibly allows faster synchronization if + there already was an earlier synchronized clock when creating a new one. + +2016-01-04 10:39:27 +0200 Sebastian Dröge + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: Use GInitable instead of having a new() function that can return NULL + Bindings don't like that much and as we're using GIO here anyway we can as + well use GInitable for possibly failing initialization. + +2016-01-03 14:06:16 +0200 Sebastian Dröge + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: Mark address, port and clock properties CONSTRUCT_ONLY + They can't sensibly be changed after construction. + +2016-01-03 22:55:48 +0100 Stefan Sauer + + * gst/parse/grammar.y: + parse_launch: make nicer log messages + Add two macros to build nicer element/pad name strings. The macros avoid + printing "(NULL)" and print the element type in addition to the name. + +2016-01-02 19:42:17 +0100 Stefan Sauer + + * gst/gstparse.h: + * gst/parse/grammar.y: + parse-launch: warn when still waiting to plug sub-pipelines after no-more-pads + The parse-launch API automagically handles dynamic pads and performs delayed + linking as needed, without any feedback about whether the linking succeeded or + not however. If a delayed dynamic link can't be completed for whatever reason, + parse-launch will simply wait in case a suitable pad appears later. This may + never happen though, in which case the pipeline may just hang forever. + Try to improve this by connecting to the "no-more-pads" signal of any element + with dynamic pads and posting a warning message for the related outstanding + dynamic links when "no-more-pads" is emitted. + Fixes #760003 + +2015-12-31 19:27:12 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gsttracer.c: + * gst/gsttracerfactory.c: + * gst/gsttracerfactory.h: + docs: fix some warnings and add some since markers + +2016-01-03 11:39:24 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + tracing: add some pointers about memory tracing + +2016-01-03 11:37:57 +0100 Stefan Sauer + + * gst/parse/grammar.y: + grammar.y: remove trailing whitespace + +2015-12-31 00:04:09 +0000 Tim-Philipp Müller + + * tests/check/gst/gstvalue.c: + tests: value: test buffer serialisation/deserialisation more thoroughly + Tests data/strings as well, not just that we received + something non-NULL back. + +2015-12-31 10:57:37 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: fix typo in comment + +2015-12-30 16:57:29 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Implement resolval of hostnames + Just allowing IPs here is not ideal and implementing DNS resolval is easy. + +2015-12-29 16:28:02 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptpclock: Add read-only properties to get the master and grandmaster clock ids + +2015-12-29 14:32:47 +0200 Sebastian Dröge + + * gst/gstcaps.c: + caps: Add (transfer full) annotation to simplify() and subtract() return value + https://bugzilla.gnome.org/show_bug.cgi?id=759948 + +2015-12-29 11:06:39 +0100 Aurélien Zanelli + + * gst/gstcaps.c: + caps: add 'transfer full' annotation to caps returned by interserction functions + To make clear caller is responsible to unref them. + https://bugzilla.gnome.org/show_bug.cgi?id=759948 + +2015-12-28 19:41:38 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs.types: + net: Add NTP and PTP clock types to the docs + This gives us the property documentation for example. + +2015-12-27 19:42:37 +0100 Stefan Sauer + + * libs/gst/check/gstcheck.c: + check: don't memcmp twice + Simply call fail() in the condition after the first memcmp. + +2015-12-24 15:27:12 +0100 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.7.1 === + +2015-12-24 13:58:52 +0100 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.7.1 + +2015-12-24 12:50:33 +0100 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-12-24 12:21:21 +0100 Sebastian Dröge + + * po/cs.po: + * po/de.po: + * po/fr.po: + * po/hu.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: Update translations + +2015-12-21 00:43:49 +0100 Koop Mast + + * configure.ac: + configure: Make -Bsymbolic check work with clang. + Update the -Bsymbolic check with the version glib has. This version + works with clang. + https://bugzilla.gnome.org/show_bug.cgi?id=759713 + +2015-12-16 09:35:18 +0100 Sebastian Dröge + + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + docs: update to git + +2015-12-14 11:09:46 +0900 Vineeth TM + + * plugins/elements/gstdataurisrc.c: + plugins-bad: Fix example pipelines + rename gst-launch --> gst-launch-1.0 + replace old elements with new elements(ffmpegcolorspace -> videoconvert, ffenc_** -> avenc_**) + fix caps in examples + https://bugzilla.gnome.org/show_bug.cgi?id=759432 + +2015-11-10 12:38:59 -0500 Xavier Claessens + + * gst/gstallocator.h: + * gst/gstatomicqueue.h: + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstbus.h: + * gst/gstcaps.h: + * gst/gstcapsfeatures.h: + * gst/gstclock.h: + * gst/gstcontext.h: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.h: + * gst/gstdatetime.h: + * gst/gstdevice.h: + * gst/gstdevicemonitor.h: + * gst/gstdeviceprovider.h: + * gst/gstdeviceproviderfactory.h: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gstevent.h: + * gst/gstghostpad.h: + * gst/gstiterator.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstparse.h: + * gst/gstpipeline.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.h: + * gst/gstquery.h: + * gst/gstregistry.h: + * gst/gstsample.h: + * gst/gstsegment.h: + * gst/gststructure.h: + * gst/gstsystemclock.h: + * gst/gsttaglist.h: + * gst/gsttask.h: + * gst/gsttaskpool.h: + * gst/gsttoc.h: + * gst/gsttracer.h: + * gst/gsttracerfactory.h: + * gst/gsttypefindfactory.h: + * gst/gsturi.h: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstflowcombiner.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/check/gsttestclock.h: + * libs/gst/controller/gstargbcontrolbinding.h: + * libs/gst/controller/gstdirectcontrolbinding.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.h: + * libs/gst/net/gstptpclock.h: + core: Add g_autoptr() support to all types + https://bugzilla.gnome.org/show_bug.cgi?id=754464 + +2015-12-14 13:06:57 +0100 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Check if parsing the name template with sscanf() was successful + If not, go back to the automatic pad numbering. + CID 1195129 + +2015-12-14 11:20:43 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + queue/multiqueue: Don't special-case CAPS events in the event handlers + For CAPS events we will never ever have a FALSE return value here, so just + remove the dead code instead of causing future confusion. + +2015-12-14 11:16:50 +0100 Sebastian Dröge + + * plugins/elements/gstqueue.c: + Revert "queue: Illegal memory access of sink event" + This reverts commit 78614c505a2a761cb4dcb7f4e5f3e9f97c9a8e88. + The code it was fixing does not have any effect anyway and will be removed in + the next commit. + +2015-12-14 10:32:14 +0900 Vineeth TM + + * plugins/elements/gstqueue.c: + queue: Illegal memory access of sink event + Once event is pushed to pad, then queue should not access the event. + This is leading to invalid read valgrind errors + https://bugzilla.gnome.org/show_bug.cgi?id=759430 + +2015-12-14 10:10:04 +0100 Sebastian Dröge + + * gst/gstelement.c: + element: Unref event if GstElement::send_event() is not implemented + Otherwise we'll take ownership of the event only if it's implemented, and + leak the event in all other situations. + +2015-12-14 10:04:19 +0100 Sebastian Dröge + + * docs/manual/advanced-dataaccess.xml: + manual: Fix dynamic pipeline example + Use GST_PAD_PROBE_PASS to pass through all events other than EOS instead of + blocking on the first non-EOS event forever. Also fix a typo in a comment in + that function. + Thanks to David Jaggard for reporting this on the mailing list. + +2015-12-13 00:37:39 +0000 Luis de Bethencourt + + * docs/pwg/building-boiler.xml: + docs: typo in the location of make_element tool + https://bugzilla.gnome.org/show_bug.cgi?id=759352 + +2015-12-12 01:13:59 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: drop unneeded macros for G_OS_WIN32 + +2015-12-12 01:09:20 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfdsrc.c: + fdsrc: drop unneeded macros for G_OS_WIN32 + +2015-12-12 01:06:43 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfdsrc.c: + fdsrc: enable large file support in Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-11 22:14:32 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfdsink.c: + fdsink: enable large file support in Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-11 20:52:57 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstqueue2.c: + queue2: fix some typos + +2015-12-11 20:42:05 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstqueue2.c: + queue2: enable large file support on Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-11 19:11:01 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: fix some typos + +2015-12-11 18:59:32 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: enable large file support on Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-11 14:36:29 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstsparsefile.c: + sparsefile: drop bogus reference to file descriptor + +fix typo on return value comment + +2015-12-11 14:07:27 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstsparsefile.c: + sparsefile: enable large file support on Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-10 14:32:27 +0100 Aurélien Zanelli + + * gst/gstelement.c: + element: unref message in _post_message when there is no implementation + 'gst_element_post_message' takes the ownership of the message, so it + shall unref it when there is no post_message implementation. Otherwise + message is leaked. + https://bugzilla.gnome.org/show_bug.cgi?id=759300 + +2015-12-10 11:35:05 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Don't hold state lock all the time while sending an event + This lock seems to exist only to prevent elements from changing states while + events are being processed. However events are going to be processed + nonetheless in those elements if sent directly via pads, so protection must + already be implemented inside the elements for event handling if it is needed. + As such having the lock here is not very useful and is actually causing + various deadlocks in different situations as described in + https://bugzilla.gnome.org/show_bug.cgi?id=744040 + +2015-12-07 20:27:45 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfilesrc.c: + filesrc: enable large file support in Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-03 15:04:32 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfilesink.c: + filesink: enable large file support on Android + https://bugzilla.gnome.org/show_bug.cgi?id=758980 + +2015-12-03 15:01:27 -0800 Reynaldo H. Verdejo Pinochet + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + filesink: indentation fixes + +2015-12-09 17:40:02 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't use random segment.position from upstream + segment.position is meant for internal usage only, but the various + GST_EVENT_SEGMENT creationg/parsing functions won't clear that field. + Use the appropriate segment boundary as an initial value instead + +2015-12-07 17:25:02 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Post a LATENCY message with async-handling=TRUE if the PLAYING state is reached + Otherwise each bin might have a different latency in the end, causing + synchronization problems. + The bin will still first handle latency internally as before, but gives the + overall pipeline the opportunity to update the latency of the whole pipeline + afterwards. + https://bugzilla.gnome.org/show_bug.cgi?id=759125 + +2015-12-07 18:20:35 +0200 Athanasios Oikonomou + + * libs/gst/base/gstbaseparse.c: + baseparse: post tag list when avg bitrate changes at least 2% + Watching videos with variant bitrate is common to have delta + more than 10 kbps, resulting in tag list spam. + Instead of relying on fixed 10 kpbs delta, it is better to + calculale the difference in percentage and update tag list + only when bitrate changes more than 2%. + https://bugzilla.gnome.org/show_bug.cgi?id=759055 + +2015-12-07 09:08:01 -0500 Nicolas Dufresne + + * autogen.sh: + * common: + Automatic update of common submodule + From b319909 to 86e4663 + +2015-12-07 12:59:39 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Check for an activated pad before adding, not a non-flushing one + The pad could be activated but flushing because of a FLUSH_START event. That's + not what we're looking for here, we want to check for activated pads. + https://bugzilla.gnome.org/show_bug.cgi?id=758928 + +2015-11-19 15:33:06 -0300 Thiago Santos + + * tests/check/elements/funnel.c: + tests: funnel: remove state change from stress tests + Changing states up and down while buffers are being pushed is not + a valid use case. If a pad is deactivated and reactivated during + a buffer push it is racy with the check of pushed sticky events + and the actual chainfunction call. As it might call the chain + without noticing the peer pad lost its previous sticky events. + https://bugzilla.gnome.org/show_bug.cgi?id=758340 + +2015-12-04 10:22:56 -0500 Nicolas Dufresne + + * tools/gst-launch.c: + gst-launch: Fix process return value on error + In case of a run-time error message, the process return value was left + unset. This would lead to error not being caught at shell level. + https://bugzilla.gnome.org/show_bug.cgi?id=759019 + +2015-12-04 10:45:25 -0500 Nicolas Dufresne + + * tools/gst-launch.c: + Revert "tools: gst-launch: return non-0 exit code on async error" + This reverts commit 2ee4cba2485d7f1646d48e4559426aed4ba99c85. + +2015-12-04 15:09:39 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: return non-0 exit code on async error + When an error happens in playing state, still return a + non-0 exit code. + https://bugzilla.gnome.org/show_bug.cgi?id=759019 + +2015-12-04 14:39:29 +0000 Ross Burton + + * libs/gst/helpers/Makefile.am: + helpers: really fix install race + My previous fix for #758029 wasn't quite right and simply made the race rarer. + Some of the files are installed by install-exec and others by install-exec, so + the hooks need to be split too. + https://bugzilla.gnome.org/show_bug.cgi?id=758029 + +2015-12-04 11:56:45 +0100 Wim Taymans + + * gst/gstquery.c: + query: fix docs + The allocation query has parameters with the meta API, not flags. + +2015-12-02 15:02:25 -0800 Reynaldo H. Verdejo Pinochet + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + Drop usage of deprecated g-ir-scanner --strip-prefix flag + +2015-12-02 16:28:23 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix set/get property + Blame it on the rebasing :) + +2015-11-12 17:15:37 +0100 Edward Hervey + + * gst/gstpad.c: + * gst/gstpad.h: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * win32/common/libgstreamer.def: + pad: Implement GstPadEventFullFunction + API: GstPadEventFullFunction + Returns a GstFlowReturn, allows asynchronous elements to properly + propagate flow returns + https://bugzilla.gnome.org/show_bug.cgi?id=757821 + +2015-11-30 17:09:43 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Use signed clock values for running time calculation + This improves the accuracy of queue levels and when to push buffers + for buffers falling outside of the segment + https://bugzilla.gnome.org/show_bug.cgi?id=757193 + +2015-11-27 09:45:29 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Add an extra cache time for unlinked streams + When synchronizing the output by time, there are some use-cases (like + allowing gapless playback downstream) where we want the unlinked streams + to stay slightly behind the linked streams. + The "unlinked-cache-time" property allows the user to specify by how + much time the unlinked streams should wait before pushing again. + +2015-10-26 08:06:01 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Optimize multiqueue sizes based on interleave + Multiqueue should only be used to cope with: + * decoupling upstream and dowstream threading (i.e. having separate threads + for elementary streams). + * Ensuring individual queues have enough space to cope with upstream interleave + (distance in stream time between co-located samples). This is to guarantee + that we have enough room in each individual queues to provide new data in + each, without being blocked. + * Limit the queue sizes to that interleave distance (and an extra minimal + buffering size). This is to ensure we don't consume too much memory. + Based on that, multiqueue now continuously calculates the input interleave + (per incoming streaming thread). Based on that, it calculates a target + interleave (currently 1.5 x real_interleave + 250ms padding). + If the target interleave is greater than the current max_size.time, it will + update it accordingly (to allow enough margin to not block). + If the target interleave goes down by more than 50%, we re-adjust it once + we know we have gone past a safe distance (2 x current max_size.time). + This mode can only be used for incoming streams that are guaranteed to be + properly timestamped. + Furthermore, we ignore sparse streams when calculating interleave and maximum + size of queues. + For the simplest of use-cases (single stream), multiqueue acts as a single + queue with a time limit of 250ms. + If there are multiple inputs, but each come from a different streaming thread, + the maximum time limit will also end up being 250ms. + On regular files (more than one input stream from the same upstream streaming + thread), it can reduce the total memory used as much as 10x, ending up with + max_size.time around 500ms. + Due to the adaptive nature, it can also cope with changing interleave (which + can happen commonly on some files at startup/pre-roll time) + +2013-01-08 21:16:42 +0000 Vincent Penquerc'h + + * plugins/elements/gstmultiqueue.c: + multiqueue: use new stream-start event sparse flag to avoid overreading subtitles + This will mean a much lower delay before a subtitles track changes take + effect. Also avoids excessive memory usage in many cases. + This will also consider sparse streams as (individually) never full, so + as to avoid blocking all playback due to one sparse stream. + https://bugzilla.gnome.org/show_bug.cgi?id=600648 + +2015-10-30 10:22:20 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix high_time computation + * Avoid the computation completely if we know we don't need it (not in + sync time mode) + * Make sure we don't override highest time with GST_CLOCK_TIME_NONE on + unlinked pads + * Ensure the high_time gets properly updated if all pads are not linked + * Fix the comparision in the loop whether the target high time is the same + as the current time + * Split wake_up_next_non_linked method to avoid useless calculation + https://bugzilla.gnome.org/show_bug.cgi?id=757353 + +2015-11-06 03:02:42 +1100 Jan Schmidt + + * plugins/elements/gstqueue2.c: + queue2: Don't report 0% unless empty + When preparing a buffering message, don't report 0% if there + is any bytes left in the queue at all. We still have something + to push, so don't tell the app to start buffering - maybe + we'll get more data before actually running dry. + +2015-11-30 17:11:33 +0100 Edward Hervey + + * gst/gstclock.h: + gstclock: Fix GST_STIME_ARGS + It wasn't properly handling GST_CLOCK_STIME_NONE and always use the + sign marker (+/-) to make it easier to identify signed values in + logs + https://bugzilla.gnome.org/show_bug.cgi?id=758870 + +2015-11-30 23:08:50 +0100 Thibault Saunier + + * gst/gstcontrolsource.c: + controlsource: Annotate get_value[_array] as (method) + As the names clash with gst_object_get_value[_array] + https://bugzilla.gnome.org/show_bug.cgi?id=756950 + +2015-11-13 17:32:57 -0500 Nicolas Dufresne + + * gst/gstplugin.c: + * gst/gstplugin.h: + plugin: Add prefix support to dependencies + This adds a new flags, GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX, + which allow using the names as prefix for plugin depencies. + https://bugzilla.gnome.org/show_bug.cgi?id=758083 + +2015-11-13 16:32:31 -0500 Nicolas Dufresne + + * gst/gstplugin.c: + plugin: Allow device nodes as dependency + This is useful for feature that are produced after probing a specific + node. You want to reload this plugin if the specific node(s) have been + removed, added, or reloaded. + https://bugzilla.gnome.org/show_bug.cgi?id=758080 + +2015-11-13 16:20:42 -0500 Nicolas Dufresne + + * gst/gstplugin.c: + plugin: Don't do lossy shift on hash + In plugin is responsible for calculating a hash of the dependencies + in order to determine if the cache should be invalidated or not. + Currently, the hash combining method removes a bit of the original + have before combining with an addition. As we use 32bits for our hash + and shift 1 bit for each file and directory, that resulting hash only + account for the last 32 files. And is more affected by the last file. + Rotating technique (shifting, and adding back the ending bit), can be + use to make the addition non-commutative. In a way that different order + gives different hashes. In this case, I don't preserve this behaviour + because the order in which the files are provided by the OS is + irrelevant. + In most cases, the XOR operation is used to combine hashes. In this + code we use the addition. I decided to preserve the addition because + we make use of non-random hash ((guint) -1) in the algorithm for + matching files that are not really part of the hash (symlinks, special + files). Doing successive XOR on this value, will simply switch from + full ones, to full zero. The XOR used with whitelist has been preserved + as it's based on a fairly randomized hash (g_str_hash). + https://bugzilla.gnome.org/show_bug.cgi?id=758078 + +2015-11-23 21:40:34 +0000 Lukasz Forynski + + * gst/gstinfo.h: + info: fix compiler warning with -Wpedantic and gcc 5 + Gstreamer compiled with gcc 5.2 and -Wpedantic produces the + following warning: + 'ISO C does not support '__FUNCTION__' predefined identifier [-Wpedantic] + const char *s = __FUNCTION__;' + Since gcc 5 enables C99 by default, use __func__ if it's available + instead of the non-standard __FUNCTION__ (as suggested in [2]). + [1]: https://gcc.gnu.org/gcc-5/changes.html + [2]: https://gcc.gnu.org/gcc-5/porting_to.html + https://bugzilla.gnome.org/show_bug.cgi?id=758541 + +2015-11-20 19:45:39 +0000 Tim-Philipp Müller + + controller: fix annotation to make g-ir-scanner happy + gstinterpolationcontrolsource.h:59: Warning: GstController: missing ":" at column 51: + * @GST_INTERPOLATION_MODE_CUBIC_MONO: (Since 1.8) monotonic cubic interpolation, will not + gstinterpolationcontrolsource.h:59: Warning: GstController: unknown annotation: since + +2014-09-29 14:03:13 +0530 Ravi Kiran K N + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: add GST_TAG_PRIVATE_DATA + Can be used to represent private data that may be + contained in tags, such as ID3v2 PRIV frames. + https://bugzilla.gnome.org/show_bug.cgi?id=730926 + +2015-11-19 17:24:53 +0000 Luis de Bethencourt + + * plugins/elements/gstdataurisrc.c: + * tests/check/elements/dataurisrc.c: + docs: update gst-launch-0.10 lines + Update references to gst-launch-0.10 to gst-launch-1.0 + +2015-11-19 00:51:44 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + Revert "baseparse: do not overwrite header buffer timestamps" + This reverts commit 2c475a035543efc0202ecdc52070295a421ed4b4. + This causes issues with h264parse. It breaks timestamps as + there are headers in the middle of the stream and this patch + makes the timestamps for those differ from the ones that + are adjusted, creating a discontinuity and leading to sync + issues. + +2015-11-17 18:47:48 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + Revert "baseparse: simplify code a bit" + This reverts commit 3984f7159a72c2eebe01905ee53716e3b2abcb30. + +2015-11-18 11:46:45 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: don't print criticals when receiving custom events in ring buffer mode + Downgrade from g_warning to GST_WARNING log message. + https://bugzilla.gnome.org/show_bug.cgi?id=758276 + +2015-11-18 09:21:23 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp-helper: Disable multicast loopback + We're not really interested in our own packets and ignore them anyway. + +2015-11-17 09:17:58 +0900 Vineeth TM + + * gst/gstdebugutils.c: + debugutils: Fix string memory leak + https://bugzilla.gnome.org/show_bug.cgi?id=758207 + +2015-11-16 08:22:14 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: simplify code a bit + Avoid repeated checks for testing if a buffer is a header + +2015-11-13 20:44:57 -0300 Thiago Santos + + * libs/gst/base/gstcollectpads.c: + collectpads: handle buffer with dts-only when mapping to running time + Otherwise the buffer was left with the original values and later would + be compared with other buffers that were converted to runninn time, + leading to bad interleaving of multiple streams. + https://bugzilla.gnome.org/show_bug.cgi?id=757961 + +2015-11-13 16:31:06 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: do not overwrite header buffer timestamps + baseparse tries to preserve timestamps from upstream if + it is running on a time segment and write that to + output buffers. It assumes the first DTS is going to be + segment.start and sets that to the first buffers. In case + the buffer is a header buffer, it had no timestamps and + will have only the DTS set due to this mechanism. + This patch prevents this by skipping this behavior for + header buffers. + https://bugzilla.gnome.org/show_bug.cgi?id=757961 + +2015-06-18 13:56:53 -0700 Aleix Conchillo Flaqué + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: add drop-buffer-flags property + New property drop-buffer-flags that will discard buffers that have the + given flags set. + https://bugzilla.gnome.org/show_bug.cgi?id=751182 + +2015-11-12 19:46:44 +0000 Ross Burton + + * libs/gst/helpers/Makefile.am: + helpers: fix install race + The install hook needs to be a install-data-hook not an install-exec-hook as the + helpers are installed into helperdir which is considered data (only path + variables with "exec" in are considered executables). + The explicit dependency on install-helpersPROGRAMS was an attempt at solving + this, but this causes occasional races where install-helpersPROGRAMS can run + twice in parallel (once via install-all, once via the hook's dependency). + https://bugzilla.gnome.org/show_bug.cgi?id=758029 + +2015-11-12 16:14:18 +0100 Heinrich Fink + + * tests/check/gst/gstsystemclock.c: + systemclock: Add test for gst_clock_get_resolution + In a series of time measurements, the diff between now and previous + timestamps is either 0 or at least as long as get_resolution returned. + https://bugzilla.gnome.org/show_bug.cgi?id=758012 + +2015-11-12 11:26:56 +0100 Heinrich Fink + + * gst/gstsystemclock.c: + systemclock: Use mach_time on Apple platforms + On iOS/OSX g_get_current_time was used by default. However, mach_time is + the preferred high-resolution monotonic clock to be used on Apple + platforms. + https://bugzilla.gnome.org/show_bug.cgi?id=758012 + +2015-11-11 11:11:23 -0300 Thiago Santos + + * plugins/tracers/gstlog.c: + tracers: log: add missing hooks + Log all possible hooks + +2015-10-29 08:40:32 -0300 Thiago Santos + + * gst/gstelement.c: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + tracer: add element-change-state-pre/post hook + Helps catching when a state change is starting and ending. + It is also possible to track the end of state changes by checking the + async-done or state-change messages. + This is particularly important for elements that do async state changes. + +2015-11-11 14:32:44 +0100 Miguel París Díaz + + * tests/check/gst/gstpad.c: + pad: test for checking the order of the probe calls + https://bugzilla.gnome.org/show_bug.cgi?id=757197 + +2015-11-10 14:41:35 -0300 Thiago Santos + + * gst/gstcontext.c: + context: fix some copy and paste leftover in docs + +2015-11-10 14:37:27 -0300 Thiago Santos + + * gst/gstcontext.c: + context: add some more documentation + Add a short paragraph on what means for a context to be persistent + +2015-11-09 18:02:09 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + utils: use 'static inline' instead of 'inline static' for gtk-doc + gtk-doc doesn't seem to recognise the former variant. + +2015-11-09 17:59:16 +0000 Tim-Philipp Müller + + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.h: + * gst/gstcontext.h: + * gst/gstevent.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstquery.h: + * gst/gstsample.h: + * gst/gsttaglist.h: + * gst/gsturi.h: + * gst/gstutils.h: + * libs/gst/base/gstbytewriter.h: + docs: remove dummy function declarations with G_INLINE_FUNCTION for gtk-doc + gtk-doc can handle static inline functions just fine these days, + there's no need for this stuff any more. + +2015-02-23 13:16:19 +1000 Duncan Palmer + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Add the avg-in-rate property. + https://bugzilla.gnome.org/show_bug.cgi?id=733959 + +2015-11-04 12:02:51 +0100 Philippe Normand + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + * tests/check/elements/queue2.c: + queue2: add overrun signal + Notifies that the queue2 is full, same as queue does + https://bugzilla.gnome.org/show_bug.cgi?id=733959 + +2015-09-29 21:14:19 -0300 Thiago Santos + + * tests/check/gst/gstpad.c: + pad: tests for accept-caps handling with proxy pads + Adds 3 new tests for testing accept-caps behavior with + proxy-caps pads. + 1) A scenario where there is no proxy. The caps should be compared to the + template caps of the pad + 2) A scenario where there is a compatible pad. The caps should be compared + to the proxied pad caps (and also with the template) + 3) A scenario where there is an incompatible proxy pad. No caps should be + possible at all. + https://bugzilla.gnome.org/show_bug.cgi?id=754112 + +2015-11-05 16:15:22 -0300 Thiago Santos + + * gst/gstpad.c: + pad: check template caps for proxy pads in accept-caps + Validate that the proxy pad indeed accepts the caps by also + comparing with the pad template caps, otherwise when the pad + had no internally linked pads it would always return true. + https://bugzilla.gnome.org/show_bug.cgi?id=754112 + +2015-11-06 12:58:42 +0100 Thibault Saunier + + * gst/gstpreset.c: + Fix build with -Werror=maybe-uninitialized + +2015-11-06 12:05:18 +0100 Thibault Saunier + + * gst/gstpreset.c: + * scripts/gst-uninstalled: + preset: Add a GST_PRESET_PATH env variable for presets to be usable uninstalled + And start setting the various uninstalled presets paths. + +2015-11-05 08:56:43 +0100 Anton Bondarenko + + * plugins/elements/gstfilesink.c: + filesink: continue element cleanup even if fclose fails + Sometimes filesink cleanup during stop may fail due to fclose error. + In this case object left partial cleanup with no file opened + but still holding old file descriptor. + It's not possible to change location property in a such state, + so next start will cause old file overwrite if 'append' does not set. + According to man page and POSIX standard about fclose behavior(extract): + ------------------------------------------------------------------------ + The fclose() function shall cause the stream pointed to by stream + to be flushed and the associated file to be closed. + ... + Whether or not the call succeeds, the stream shall be disassociated + from the file and any buffer set by the setbuf() or setvbuf() + function shall be disassociated from the stream. + ... + The fclose() function shall perform the equivalent of a close() + on the file descriptor that is associated with the stream + pointed to by stream. + After the call to fclose(), any use of stream results + in undefined behavior. + ------------------------------------------------------------------------ + So file is in 'closed' state no matter if fclose succeed or not. + And cleanup could be continued. + https://bugzilla.gnome.org/show_bug.cgi?id=757596 + +2015-11-01 00:04:27 +1100 Jan Schmidt + + * gst/gstpad.c: + pad: Mark sticky events as sent on not-linked + Instead of re-sending sticky events over and over to a not-linked + pad, mark them as sent the first time. If the not-linked came from + downstream, it already received the events. If the pad is actually + not-linked, the sticky events will be rescheduled when the + pad is linked anyway. + +2015-10-29 18:53:29 +1100 Jan Schmidt + + * gst/gstghostpad.c: + ghostpad: Allow deactivation with no peer. + Allow deactivation in pull-mode, since that implies we + had a peer, activated in pull mode, then the peer disa-peer-ed ;) + +2015-10-28 17:31:07 -0300 Thiago Santos + + * gst/gstelement.c: + * gst/gstelementfactory.c: + element: emit tracer's element-new hook from 'constructed' + It allows to properly emitting it for all newly created elements + https://bugzilla.gnome.org/show_bug.cgi?id=757045 + +2015-10-28 06:03:39 -0300 Thiago Santos + + * plugins/tracers/gststats.c: + stats: log the element-new hook properly + To be able to get the time the elements were created instead of + just logging them without a time + +2015-10-28 18:04:46 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Unblock blocking pad probes when receiving FLUSH_START in send_event() too + Without this, flushing might not unblock the streaming thread and cause deadlocks. + https://bugzilla.gnome.org/show_bug.cgi?id=757257 + +2015-10-28 13:04:25 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Document the order in which pad probes are called + https://bugzilla.gnome.org/show_bug.cgi?id=757197 + +2015-10-27 18:05:05 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Append hooks instead of prepending to call them in the order they were added + https://bugzilla.gnome.org/show_bug.cgi?id=757197 + +2015-10-26 12:50:12 +0100 Stian Selnes + + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + * win32/common/libgstnet.def: + netaddressmeta: gst_buffer_get_net_address_meta() as function + Implement gst_buffer_get_net_address_meta() as a function instead + of a macro in order to get gobject-introspection to work. + https://bugzilla.gnome.org/show_bug.cgi?id=702921 + +2015-10-26 18:07:11 +0530 Nirbheek Chauhan + + * gst/gstbuffer.h: + buffer: flesh out docs for gst_buffer_make_writable() a little + There is a similar explanation in gst_caps_make_writable, but the existing + documentation can be misleading since it does not define what 'is already + writable' means. + Also note when this function is meant to be used. + +2015-10-26 17:35:34 +0530 Nirbheek Chauhan + + * gst/gstcaps.c: + caps: clarify docs for a few functions that they don't update things in-place + It is not necessarily clear from the existing introspection tags and + documentation alone. + +2015-10-27 08:48:07 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue/queue2: Use GST_BUFFER_DTS_OR_PTS + The input of queue/queue2 might have DTS set, in which cas we want + to take that into account (instead of the PTS) to calculate position + and queue levels. + https://bugzilla.gnome.org/show_bug.cgi?id=756507 + +2015-10-13 17:20:26 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Use buffer DTS if present, else PTS + In order to accurately determine the amount (in time) of data + travelling in queues, we should use an increasing value. + If buffers are encoded and potentially reordered, we should be + using their DTS (increasing) and not PTS (reordered) + https://bugzilla.gnome.org/show_bug.cgi?id=756507 + +2015-10-27 08:33:41 +0100 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Use GST_BUFFER_DTS_OR_PTS + Simplifies code a bit + +2015-10-26 07:59:54 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + buffer: Add a GST_BUFFER_DTS_OR_PTS macro + API: GST_BUFFER_DTS_OR_PTS + Many scenarios/elements require dealing with streams of buffers that + might have DTS set (i.e. encoded data, potentially reordered) + To simplify getting the increasing "timestamp" of those buffers, create + a macro that will return the DTS if valid, and if not the PTS + +2015-10-06 12:21:04 +0200 Guillaume Desmottes + + * docs/gst/gstreamer-sections.txt: + doc: add GST_{PTR,SEGMENT}_FORMAT + Very useful formats in debug output so best to have them in the + generated doc. + https://bugzilla.gnome.org/show_bug.cgi?id=756115 + +2015-10-26 10:53:35 +0200 Sebastian Dröge + + * gst/gstsegment.c: + segment: Return -1 if gst_segment_to_stream_time_full() considers the position not inside the segment + Fixes GstPipeline unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=756564 + +2015-10-24 16:52:44 +0100 Florin Apostol + + * gst/gsturi.c: + uri: fix behaviour for merging uris ending in .. without following / + https://bugzilla.gnome.org/show_bug.cgi?id=757065 + +2015-10-24 16:43:59 +0100 Florin Apostol + + * tests/check/gst/gsturi.c: + uri: tests: added unit test for streams ending in .. without following / + https://bugzilla.gnome.org/show_bug.cgi?id=757065 + +2015-08-27 12:43:28 +0200 Thibault Saunier + + * gst/gstdebugutils.c: + debug: Dump pad properties values + Currently we only show element properties values, we should also show + pad properties values + https://bugzilla.gnome.org/show_bug.cgi?id=754166 + +2015-10-23 20:04:42 +0300 Sebastian Dröge + + * gst/gstsegment.c: + segment: Remove leftover debug g_print() + +2015-10-15 14:49:37 +0300 Vivia Nikolaidou + + * docs/design/part-synchronisation.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: Add _full variants of all stream/running_time from/to segment position functions + See formula clarifications in design docs for calculation details. + https://bugzilla.gnome.org/show_bug.cgi?id=756564 + +2015-09-26 01:29:07 +0300 Vivia Nikolaidou + + * scripts/gst-uninstalled: + gst-uninstalled: Added env var for uninstalled PTP helper + https://bugzilla.gnome.org/show_bug.cgi?id=755651 + +2015-10-22 12:00:42 +0200 Guillaume Desmottes + + * libs/gst/base/gstbasesink.h: + basesink: rename argument of PREROLL_{COND,LOCK} macros + They take a GstBaseSink instance as argument at not a GstPad. Rename the + argument to 'obj' which is not miss leading and in line with + GST_BASE_SINK_PAD(obj). + https://bugzilla.gnome.org/show_bug.cgi?id=756954 + +2015-10-22 10:05:14 +0200 Mathieu Duponchelle + + * gst/gstcontrolsource.c: + gstcontrolsource: Add missing (out) annotation + +2015-10-21 14:34:47 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From b99800a to b319909 + +2015-10-21 14:49:49 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix docs/annotation of gst_pad_probe_info_get_buffer_list() + It's not get_bufferlist(). Because of that it was ignored by the docs and + G-I, leading to crashes because of broken ownership transfer. + https://bugzilla.gnome.org/show_bug.cgi?id=756898 + +2015-10-20 17:29:42 +0300 Sebastian Dröge + + * configure.ac: + * gst/gstpad.c: + * libs/gst/base/gstbasetransform.c: + Use new GST_ENABLE_EXTRA_CHECKS #define + https://bugzilla.gnome.org/show_bug.cgi?id=756870 + +2015-10-21 14:25:40 +0300 Sebastian Dröge + + * README: + * common: + Automatic update of common submodule + From 9aed1d7 to b99800a + +2015-10-20 13:46:24 +0100 Luis de Bethencourt + + * tools/gst-stats.c: + stats: always free log + We always want to free the open file log if fopen() succeeded. Independently + of if fgets() succeeds or fails. + CID 1326055 + https://bugzilla.gnome.org/show_bug.cgi?id=756864 + +2015-10-19 16:50:51 +0300 Vivia Nikolaidou + + * gst/gstsegment.c: + * tests/check/gst/gstsegment.c: + segment: Correct stream_time calc for negative applied rate + Updated gst_segment_position_from_stream_time and gst_segment_to_stream_time to reflect correct calculations for the case when the applied rate is negative. + Pasting from design docs: + =============================== + Stream time is calculated using the buffer times and the preceding SEGMENT + event as follows: + stream_time = (B.timestamp - S.start) * ABS (S.applied_rate) + S.time + For negative rates, B.timestamp will go backwards from S.stop to S.start, + making the stream time go backwards. + =============================== + Therefore, the calculation for applied_rate < 0 should be: + stream_time = (S.stop - B.timestamp) * ABS (S.applied_rate) + S.time + and the reverse: + B.timestamp = S.stop - (stream_time - S.time) / ABS (S.applied_rate) + https://bugzilla.gnome.org/show_bug.cgi?id=756810 + +2015-10-19 21:39:19 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + * docs/plugins/gstreamer-plugins-docs.sgml: + * gst/gsttracerutils.c: + tracer: rename the envvar to GST_TRACER_PLUGINS + The subsystem reused the GST_TRACE var that is allready in use by the alloc tracer. + Fixes #756760 + +2015-10-15 16:32:42 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Improve incoming SEGMENT handling + Previously this code was just blindly setting the cached flow return + of downstream to GST_FLOW_OK when we get a SEGMENT. + The problem is that this can not be done blindly. If downstream was + not linked, the corresponding sinqlequeue source pad thread might be + waiting for the next ID to be woken up upon. + By blindly setting the cached return value to GST_FLOW_OK, and if that + stream was the only one that was NOT_LINKED, then the next time we + check (from any other thread) to see if we need to wake up a source pad + thread ... we won't even try, because none of the cached flow return + are equal to GST_FLOW_NOT_LINKED. + This would result in that thread never being woken up + https://bugzilla.gnome.org/show_bug.cgi?id=756645 + +2015-09-26 18:16:07 +0800 Ting-Wei Lan + + * gst/gstutils.h: + gstutils: Fix build with clang -Werror=cast-align + https://bugzilla.gnome.org/show_bug.cgi?id=755657 + +2015-10-17 22:13:08 +0300 Sebastian Dröge + + * gst/gstbin.c: + bin: Make sure to free all cached messages when going to NULL + An ASYNC READY->PAUSED might have failed without the bin code noticing during + the state change, in which case we will never get PAUSED->READY and would leak + messages. + https://bugzilla.gnome.org/show_bug.cgi?id=756611 + +2015-10-16 15:59:49 +0100 Tim-Philipp Müller + + * docs/gst/running.xml: + * gst/gstdebugutils.h: + * tools/gst-launch.1.in: + docs: mention xdot utility to view .dot files directly + +2015-10-16 12:00:50 +0100 Tim-Philipp Müller + + * gst/gsttrace.c: + alloctrace: show details of events and messages leaked + So it's clearer what leaked. + +2015-10-16 11:54:18 +0100 Tim-Philipp Müller + + * docs/manual/advanced-metadata.xml: + docs: manual: improve advanced metadata example a bit + Accept both filename and a URI as argument, and print + the error from the error message if there's an error. + https://bugzilla.gnome.org/show_bug.cgi?id=756630 + +2015-10-15 19:05:21 -0300 Thiago Santos + + * gst/gstmemory.h: + memory: fix typo in documentation + It should be 1.2 unless this is a flag from the future + +2015-09-15 18:08:18 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Accept STREAM_START after EOS + In the same way core now allows STREAM_START to remove the flushing + state from pads, we need to do the same thing in multiqueue + +2015-10-14 11:03:22 +0300 Sebastian Dröge + + * tests/check/gst/gstsegment.c: + segment: Convert function to macro in unit test to get proper line numbers on failures + https://bugzilla.gnome.org/show_bug.cgi?id=748316 + +2015-10-12 17:29:26 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Update internal position even if not linked + Our current position has nothing to do with being linked or not. + Avoids having stray segment updates fired every 2s + +2015-10-07 22:55:44 +0100 Florin Apostol + + * gst/gstpad.c: + pad: fix memory leak when sending events to an EOS pad + https://bugzilla.gnome.org/show_bug.cgi?id=756208 + +2015-10-07 12:01:16 +0100 Sebastian Dröge + + * plugins/tracers/Makefile.am: + tracers: Only link against libgstprintf.la if the debugging system is enabled + It does not exist otherwise and linking will fail. + +2015-10-07 11:25:52 +0100 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + gst-ptp-helper: #include to fix net/if.h include on OSX 10.6 + In file included from gst-ptp-helper.c:40:0: + /usr/include/net/if.h:265:19: error: field 'ifru_addr' has incomplete type + struct sockaddr ifru_addr; + https://bugzilla.gnome.org/show_bug.cgi?id=756136 + +2015-10-07 12:22:34 +0200 Stefan Sauer + + * configure.ac: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gsttracers.c: + Revert "tracers: Only build getrusage() tracer if RUSAGE_THREAD is available" + This reverts commit 8ddbf76626a48420306869db1d171f854cc25310. + +2015-10-07 12:21:56 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + tracers/rusage: ifdef the RUSAGE_THREAD usage + Some versions of andoid don't seem to have it. + +2015-10-07 11:11:30 +0100 Sebastian Dröge + + * configure.ac: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gsttracers.c: + tracers: Only build getrusage() tracer if RUSAGE_THREAD is available + +2015-10-06 21:46:55 +0200 Stefan Sauer + + * win32/common/libgstreamer.def: + win32: remove gst_tracer_quark_id_get_type + Revert addition from 777bbeea605051ae3d2fa7e02ad8589001e78ce0. + +2015-10-06 18:52:38 +0200 Stefan Sauer + + * gst/gsttracer.h: + * gst/gsttracerutils.h: + tracer: move prototype to the right header + Fixes the build when the tracing subsystem is disabled. + +2015-10-06 18:49:46 +0200 Stefan Sauer + + * gst/gst.c: + * gst/gsttracerutils.h: + tracer: mark GstTracerQuarkId as non GEnum + This reverts 72ca02b1de4066eeae35c891e275386770117778 and marks the enum + accordingly. + +2015-10-06 18:46:24 +0200 Stefan Sauer + + * plugins/tracers/Makefile.am: + * plugins/tracers/gsttracers.c: + tracers: disable the log tracer if debug logging is disabled + +2015-10-06 18:45:41 +0200 Stefan Sauer + + * plugins/tracers/Makefile.am: + makefile.am: Remove obsolete Android build cruft + This is not needed any longer. + +2015-10-06 14:01:03 +0200 Stefan Sauer + + * gst/gsttracerutils.h: + tracer: fix the build with debug (tracer) disabled + Sync the macro definitions. The dummy defines has argument mismatches. + +2015-10-06 11:39:33 +0200 Stefan Sauer + + * gst/gsttracerutils.h: + tracer: fix the build with debug (tracer) disabled + Remove commas at the end of the macros. + +2015-09-01 16:39:30 -0300 Thiago Santos + + * plugins/tracers/gststats.c: + tracers: stats: add message structure to output + The name of the message is not enough. For example, state-change + is not enough to know the transition. + https://bugzilla.gnome.org/show_bug.cgi?id=754496 + +2015-10-05 19:05:58 -0300 Thiago Santos + + * gst/gst.c: + gst: adding tracer quark id to gst init and deinit + Fixes issues at make check + +2015-10-05 18:50:48 -0300 Thiago Santos + + * win32/common/libgstreamer.def: + win32: libgstreamer: add tracer functions + +2015-10-05 21:29:49 +0200 Stefan Sauer + + * tests/check/gst/gsttag.c: + tests: fix the tag test + The previous change (see bgo #756069) was causing us to free the same pointer + multiple times. If we actually get a sample back, the test fails, no need to + free anything in that case. + +2015-06-04 01:50:34 +0200 Marcin Kolny + + * docs/design/draft-tracing.txt: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstpad.c: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + tracer: add missing hooks + Add following hooks: element-new, element-add-pad, element-remove-pad, + bin-add-pre, bin-add-post, bin-remove-pre, bin-remove-post, pad-link-pre, + pad-link-post, pad-unlink-pre, pad-unlink-post. + https://bugzilla.gnome.org/show_bug.cgi?id=733187 + +2015-03-13 18:31:40 +0000 Thiago Santos + + * plugins/tracers/gststats.c: + tracer: gststats: add thread-id to log line + +2015-03-13 13:10:42 +0000 Thiago Santos + + * gst/gstpad.c: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gststats.c: + tracer: add pad query hooks + +2015-01-15 06:32:48 +0100 Mathieu Duponchelle + + * gst/gsttracer.c: + tracer: strdup the passed parameters. + +2015-01-13 22:11:34 +0100 Mathieu Duponchelle + + * plugins/tracers/gstlog.c: + tracer: Use GST_TIME_ARGS when printing with GST_TIME_FORMAT. + +2014-10-16 10:42:05 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + tracing: update docs + +2014-10-02 19:52:03 +0200 Stefan Sauer + + * plugins/tracers/gststats.c: + * tools/gst-stats.c: + stats: TIMESTAMP -> PTS + +2014-09-22 09:55:56 +0200 Stefan Sauer + + * gst/gst.c: + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracing: rename the global api to gst_tracing + This makes it more obvious what is the api for tracer elements and what is api + for the global state. + +2014-09-18 08:28:48 +0200 Stefan Sauer + + * tools/gst-stats.c: + stats: fix cpu stats printing + Only print them if we have them. Also scale them by 10.0 as the are in + per-mille now. + +2014-09-18 08:26:19 +0200 Stefan Sauer + + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracers: eliminate var_args + Register tracer hooks as GCallback. Use macros for hook dispatch and cast the + hook functions back to the appropriate type. + +2014-09-17 09:41:46 +0200 Stefan Sauer + + * tools/gst-stats.c: + stats: don't warn on ".class" log lines + +2014-09-17 08:38:02 +0200 Stefan Sauer + + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gstrusage.h: + * plugins/tracers/gststats.c: + * plugins/tracers/gststats.h: + tracers: code cleanups + Move static variables to instance variables. Add finalize methods. Remove code + that is commented out. Cleanup locking code. + +2014-09-15 22:27:11 +0200 Stefan Sauer + + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracer: use GQuark or strings for the hook id + This way one can define new tracing probes without changing the core. We are + using our own quark table, as 1) we only want to initialize them if we're + tracing, 2) we want to share them with the tracers. + +2014-09-15 13:15:17 +0200 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracer: simplify hook api + Instead of a single invoke() function and a 'mask', register to individual + hooks. This avoids one level of indirection and allows us to remove the + hook enums. The message enms are now renamed to hook enums. + +2014-09-12 18:43:52 +0200 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerutils.c: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracer: drop the HookId hid from the invoke method + The MessageId is more detailed and anyway needed to interpret the varargs. + +2014-09-12 11:17:41 +0200 Stefan Sauer + + * plugins/tracers/gststats.c: + stats: fixup doc name and remove commented code + +2014-09-12 08:40:01 +0200 Stefan Sauer + + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracers: add metadata for the logged values + +2014-09-11 13:02:51 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + rusage: improve cpu load meassurements + Get the number of cpus and scale process cpu-load accordingly. Switch the + cpuload to be per-mille to get smoother graphs. Add a bit more logging and use + the _OBJECT variant. + +2014-09-11 13:00:59 +0200 Stefan Sauer + + * gst/gsttracer.c: + tracer: remove commented code + +2014-09-10 08:33:38 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: update tracer design + Update the tracer event classes section. Add a performance section. + +2014-09-10 08:32:18 +0200 Stefan Sauer + + * gst/gsttracer.c: + tracer: use GST_PTR_FORMAT to log the structure + This way we only expand the structure when we're logging. This allows us to + meassure the pure tracing seperately from the logging. + Also add some comments on further improvements. + +2014-09-10 07:55:33 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + * tools/gst-stats.c: + rusage: implement windowing of cpuload + Add a local help to the rusage plugin that supports windowing of values. We want + to generalize this for use in other plugins. + +2014-09-04 10:11:52 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + * tools/gst-stats.c: + rusage: announce the data format + Rusage will now announce what is meassures and how it is logged. Use the new format in stats. + Cleanup the the code and naming. + +2014-07-28 22:08:49 +0200 Stefan Sauer + + * plugins/tracers/gstrusage.c: + * tools/gst-stats.c: + stats: improve cpu load meassurements + Rename variables for clarity. Handle the initial disparity between debug time + and the time already spent in the proc and main thread. + +2014-07-18 08:09:32 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: update tracer design + +2014-07-28 08:49:38 +0200 Stefan Sauer + + * gst/gstquark.c: + * gst/gstquark.h: + quarks: revert the quark changes, we not using them anymore + +2014-07-18 07:49:38 +0200 Stefan Sauer + + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstregistrychunks.c: + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerfactory.c: + * gst/gsttracerfactory.h: + * gst/gsttracerutils.c: + * gst/gsttracerutils.h: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlatency.h: + * plugins/tracers/gstlog.h: + * plugins/tracers/gstrusage.h: + * plugins/tracers/gststats.h: + tracer: split into tracer and tracerutils + Keep tracer base class in tracer and move core support into the utils module. + Add a unstable-api guard to the tracer.h so that external modules would need to + acknowledge the status by setting GST_USE_UNSTABLE_API. + +2014-07-16 18:48:52 +0200 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracerfactory.c: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + docs: add gtk-doc blobs + +2014-02-20 11:15:20 +0100 Stefan Sauer + + * plugins/tracers/gstlatency.c: + latency: take stop time when buffer is handled + Now we meassure time from 'before buffer transfer on src' to when the 'buffer is processed on sink'. + +2014-07-15 09:49:23 +0200 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracer.h: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gststats.c: + tracers: add a logging helper to remove identical copies from the tracers + +2014-02-18 16:15:44 +0100 Stefan Sauer + + * plugins/tracers/gstlatency.c: + * plugins/tracers/gststats.c: + tracers: tweak the get_real_pad_parent() + By using the we ended up on the actual element, not the parent. + +2014-02-18 11:06:10 +0100 Stefan Sauer + + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlatency.c: + * plugins/tracers/gstlatency.h: + * plugins/tracers/gsttracers.c: + tracers: add a new latency tracer + Add a new tracer with pushes extra events to meassure src-to-sink processing latency. + +2014-02-17 18:30:24 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: update design docs + Add new tracer idea. + +2013-11-22 19:10:04 +0100 Stefan Sauer + + * tools/gst-stats.c: + gst-stats: use the rusage stats + Add cpuload info from rusage traces. + +2013-11-20 08:22:58 +0100 Stefan Sauer + + * configure.ac: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstrusage.c: + * plugins/tracers/gstrusage.h: + * plugins/tracers/gsttracers.c: + rusage: add a new rusage tracer + The tracer hooks up to all probes and logs resource usage figures. + +2014-07-15 10:20:22 +0200 Stefan Sauer + + * tools/gst-stats.c: + gst-stats: filter complete thread section if we have no pads + +2013-11-19 08:04:38 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + * tools/gst-stats.c: + stats: improve the handling of parentage + Log new object after we did the check for parents. + +2013-11-17 11:37:14 +0100 Stefan Sauer + + * tools/gst-stats.c: + stats: print thread key for stats and filter empty pad-sections + +2013-11-17 11:15:36 +0100 Stefan Sauer + + * tools/gst-stats.c: + stats: update buffer flags + Remove some buffer flags that were leftovers from 0.10 and handle new 1.0 buffer + flags. + +2013-11-04 20:11:09 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + * plugins/tracers/gststats.h: + * tools/.gitignore: + * tools/Makefile.am: + * tools/gst-stats.c: + stats: add a stats frontend + Parse the log and collect data from tracer messages. + +2013-11-15 09:36:21 +0100 Stefan Sauer + + * gst/gsttracer.h: + tracer: use the same timebase as the logging + +2014-07-16 09:22:37 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: update design + +2014-07-16 09:41:48 +0200 Stefan Sauer + + * plugins/tracers/gstlog.c: + log: add query log category + +2013-11-02 18:24:56 +0100 Stefan Sauer + + * gst/gsttracer.c: + tracer: parse parameters + +2014-07-16 09:22:14 +0200 Stefan Sauer + + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gsttracer.h: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlog.c: + * plugins/tracers/gststats.c: + tracer: add more hooks and handle it in the plugins + +2013-10-30 08:19:41 +0100 Stefan Sauer + + * plugins/tracers/gststats.c: + stats: handle buffer lists + +2013-10-30 08:04:27 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + * plugins/tracers/gstlog.c: + log: make the log tracer more verbose again + Define log formats per message type and print details. + +2013-10-28 21:59:19 +0100 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracer.h: + * plugins/tracers/gstlog.c: + * plugins/tracers/gststats.c: + tracer: use a macros for the enabled check + Avoid a function call and check the variables from the macro. + +2013-10-28 21:39:52 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + * gst/gstpad.c: + * gst/gsttracer.c: + * gst/gsttracer.h: + tracer: use macros for hooks + Wrap the hook with a pre and post macro. This looks less intrusive than the + previous version, although it is a little less optimized. + +2013-10-28 21:28:18 +0100 Stefan Sauer + + * gst/gstpad.c: + * gst/gstquark.c: + * gst/gsttracer.c: + * gst/gsttracer.h: + * plugins/tracers/gstlog.c: + * plugins/tracers/gststats.c: + tracer: pass the timestamp directly + Avoid the structure mashalling (and weird field naming). + +2013-10-28 08:08:20 +0100 Stefan Sauer + + * plugins/tracers/Makefile.am: + * plugins/tracers/gststats.c: + * plugins/tracers/gststats.h: + * plugins/tracers/gsttracers.c: + stats: add a tracer that collects pipeline statistics + This is more or less equiv to the the statistics in gst-tracelib. + +2013-10-28 08:07:52 +0100 Stefan Sauer + + * plugins/tracers/gstlog.h: + log: add cast macro + +2013-10-27 20:43:25 +0100 Stefan Sauer + + * gst/gsttracer.c: + * gst/gsttracer.h: + * plugins/tracers/gstlog.c: + tracer: pass the instance to the vmethod + +2013-10-27 17:05:52 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + * plugins/tracers/gstlog.c: + design: more planning + +2013-10-27 17:04:32 +0100 Stefan Sauer + + * gst/gstpad.c: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gsttracer.c: + * gst/gsttracer.h: + tracer: switch to quarks and add another hook for buffer flow + Use pre-defines quarks as this will be called quite often. + +2013-10-27 12:45:54 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + * gst/gsttracer.c: + * gst/gsttracer.h: + * plugins/tracers/gstlog.c: + tracer: add the hook-id to the invoke signature + Tracers that subscribe to multiple hooks can know what hook was used. + +2013-10-26 22:05:13 +0200 Stefan Sauer + + * tools/gst-inspect.c: + inspect: add support for the new factory + Handle tracer modules. + +2013-10-24 14:47:48 +0200 Stefan Sauer + + * configure.ac: + * docs/design/draft-tracing.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstpad.c: + * gst/gstregistrybinary.h: + * gst/gstregistrychunks.c: + * gst/gsttracer.c: + * gst/gsttracer.h: + * gst/gsttracerfactory.c: + * gst/gsttracerfactory.h: + * plugins/Makefile.am: + * plugins/tracers/.gitignore: + * plugins/tracers/Makefile.am: + * plugins/tracers/gstlog.c: + * plugins/tracers/gstlog.h: + * plugins/tracers/gsttracers.c: + tracer: initial prototype for the tracing subsystem + +2015-10-05 11:12:47 +0900 Vineeth TM + + * tests/check/gst/gsttag.c: + * tools/gst-launch.c: + tests/gst-launch: Fix sample memory leak + When sample is got using gst_tag_list_get_sample_index, it should + be free'd. + https://bugzilla.gnome.org/show_bug.cgi?id=756069 + +2015-10-02 22:17:04 +0300 Sebastian Dröge + + * configure.ac: + * gst/gst.c: + * gst/gsturi.c: + * gst/gstvalue.c: + Update GLib dependency to 2.40.0 + +2015-08-20 16:21:59 +0900 Vineeth TM + + * docs/manual/advanced-dataaccess.xml: + * docs/manual/appendix-integration.xml: + * docs/manual/basics-init.xml: + * libs/gst/helpers/gst-completion-helper.c: + * libs/gst/helpers/gst-ptp-helper.c: + * tests/benchmarks/capsnego.c: + * tests/examples/ptp/ptp-print-times.c: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + gstreamer: Fix memory leaks when context parse fails + When g_option_context_parse fails, context and error variables are not getting free'd + which results in memory leaks. Free'ing the same. + And replacing g_error_free with g_clear_error, which checks if the error being passed + is not NULL and sets the variable to NULL on free'ing. + https://bugzilla.gnome.org/show_bug.cgi?id=753851 + +2015-09-23 23:03:29 +0200 Jan Alexander Steffens (heftig) + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + timedvaluecontrolsource: Use g_sequence_lookup where possible + When looking for exact matches in the sequence, this results + in much simpler code than when using g_sequence_search. + https://bugzilla.gnome.org/show_bug.cgi?id=755498 + +2015-10-01 22:09:58 +0200 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + interpolationcontrolsource: fix write over the array size + The '++' got incidentially added during the refactoring in + 2fe3939ce7ea84c45dd922e7f1097dd07f11fc5d. + +2015-09-30 17:29:16 +0200 Stefan Sauer + + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * tests/check/libs/struct_arm.h: + * tests/check/libs/struct_hppa.h: + * tests/check/libs/struct_i386.h: + * tests/check/libs/struct_ppc32.h: + * tests/check/libs/struct_ppc64.h: + * tests/check/libs/struct_sparc.h: + * tests/check/libs/struct_x86_64.h: + controlpoint: change the padding to be of arch-independent size + The default padding I introduced in d4f81fb4e62d34a4c1dabc65b23ede7ce7694c63 is + actually only 4 pointers and on 32bit platforms already smaller than the union. + Replace it with a fixed 64byte padding. Don't add the normal padding for now. + Fixes #755822 + +2015-08-21 17:42:52 +0100 Luis de Bethencourt + + * scripts/gst-uninstalled: + gstreamer-uninstalled: add path for OpenCV haar cascade files + Some OpenCV plugins use haar cascade files that are included in the + GStreamer sources. To be able to use these from uninstalled, they need + to be found through an environment variable. + Adding this environment variable pointing to haar cascade files to + gst-uninstalled. + +2015-09-28 16:01:55 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: fix 'format string is not a string literal' warning with clang + Broke this when I removed the G_GNUC_PRINTF in a previous + commit to fix indentation, since it was not really needed. + Turns out unlike gcc clang warns though if a non-literal + format string is passed then. Fix indentation differently. + http://clang.llvm.org/docs/AttributeReference.html#format-gnu-format + +2015-09-28 16:45:47 +0200 Stefan Sauer + + * tests/examples/manual/Makefile.am: + tests: fix the manual tests by setting the right env-vars + +2015-09-28 16:22:36 +0200 Stefan Sauer + + * libs/gst/controller/gstdirectcontrolbinding.h: + directcontrolbinding: fix formatting + +2015-09-28 16:21:55 +0200 Stefan Sauer + + * libs/gst/base/gstindex.h: + index: mark two structs that don't have abi padding + +2015-09-28 16:19:40 +0200 Stefan Sauer + + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * tests/check/libs/struct_arm.h: + * tests/check/libs/struct_hppa.h: + * tests/check/libs/struct_i386.h: + * tests/check/libs/struct_ppc32.h: + * tests/check/libs/struct_ppc64.h: + * tests/check/libs/struct_sparc.h: + * tests/check/libs/struct_x86_64.h: + controller: add the missing abi padding + While this technically is an abi break, we decided to do this: + 1) the struct is documented to be internal + 2) the struct is alloced and freed inside the library + 3) there are no public methods that receive or return instances + 4) the only code known to use this struct are classes containd here + +2015-09-24 00:04:48 +1000 Matthew Waters + + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * tests/check/gst/gstcontext.c: + * win32/common/libgstreamer.def: + bin: implement context propagation when adding elements + When adding an element to a bin we need to propagate the GstContext's + to/from the element. + This moves the GstContext list from GstBin to GstElement and adds + convenience functions to get the currently set list of GstContext's. + This does not deal with the collection of GstContext's propagated + using GST_CONTEXT_QUERY. Element subclasses are advised to call + gst_element_set_context if they need to propagate GstContext's + received from the context query. + https://bugzilla.gnome.org/show_bug.cgi?id=705579 + +2015-09-07 09:39:32 +0200 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + interpolationcontrolsource: add cubic_mono interpolation + This new mode won't overshoot the min/max y values set by the control-points. + Fixes #754678 + API: GST_INTERPOLATION_MODE_CUBIC_MONO + +2015-09-07 09:37:05 +0200 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + interpolationcontrolsource: refactor code + Extract common code that looks up the control-points around the timestamp. Add + some comments for future investigation. + +2015-09-04 16:38:37 +0200 Stefan Sauer + + * configure.ac: + * tests/examples/controller/.gitignore: + * tests/examples/controller/Makefile.am: + * tests/examples/controller/controller-graph.c: + tests/examples: add a demo for the interpolation control source modes + This is in preparation for new modes to be added. In particullar it demonstrates + how the cubic splines overshoot the range. + +2015-09-09 11:55:28 -0300 Thiago Santos + + * plugins/elements/gstcapsfilter.c: + capsfilter: remove proxying of accept-caps downstream + The design is to only do a local check + +2015-08-25 19:37:30 -0300 Thiago Santos + + * gst/gstpad.c: + pad: don't fallback to caps queries with proxy pads + A proxy-pad should always proxy the caps related queries + and events to its down or upstream peers on the other side + of the element. Falling back to a caps query seems wrong. + https://bugzilla.gnome.org/show_bug.cgi?id=754112 + +2015-09-26 11:03:24 +0100 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: minor doc fixes + +2015-09-02 17:58:38 +0300 Vivia Nikolaidou + + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * libs/gst/base/gstbasesink.c: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: Replaced gst_segment_to_position with gst_segment_position_from_running_time + gst_segment_to_position might cause confusion, especially with the addition of + gst_segment_position_from_stream_time . Deprecated gst_segment_to_position + now, and replaced it with gst_segment_position_from_running_time. + Also added unit tests. + +2015-09-02 17:38:25 +0300 Vivia Nikolaidou + + * tests/check/gst/gstsegment.c: + segment: Added unit tests for gst_segment_position_from_stream_time + +2015-09-25 15:57:16 +0300 Vivia Nikolaidou + + * gst/gstsegment.c: + segment: gst_segment_to_stream_time: Renamed 'result' to 'stream_time' + Renamed the "result" variable to "stream_time" for better readability. + +2015-09-25 15:56:45 +0300 Vivia Nikolaidou + + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * win32/common/libgstreamer.def: + segment: Added gst_segment_position_from_stream_time() + gst_segment_position_from_stream_time() will convert stream time into a + position in the segment so that gst_segment_to_stream_time() with that + position returns the same stream time. It will return -1 if the stream time + given is not inside the segment. + +2015-09-02 16:36:35 +0300 Vivia Nikolaidou + + * docs/design/part-synchronisation.txt: + * gst/gstsegment.h: + segment: Rewording of struct field descriptions + The new wording makes it easier to understand exactly what each field of the + GstSegment struct represents. + +2015-08-31 15:35:11 +0300 Sebastian Dröge + + * gst/gstevent.c: + event: Make sure that timestamp + diff in QoS events is never smaller than 0 + When a running-time-offset is stored in the event, it could become smaller + than 0 although the event is otherwise correct. This can happen when pad + offsets are used. + To prevent this, we set the timestamp to -diff, so that in the end the sum of + both is exactly 0. + https://bugzilla.gnome.org/show_bug.cgi?id=754356 + +2015-09-16 23:40:44 +0200 Sebastian Dröge + + * tests/check/gst/gsturi.c: + uri: Add test for correct absolute URI handling in gst_uri_from_string_with_base() + If the second parameter is an absolute URI, the base should have no effect and + the second parameter should be returned again. + https://bugzilla.gnome.org/show_bug.cgi?id=755134 + +2015-09-25 23:51:03 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.6.0 === + +2015-09-25 23:14:33 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.6.0 + +2015-09-25 22:41:16 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-09-25 10:18:07 +0900 Vineeth TM + + * libs/gst/net/gstptpclock.c: + ptpclock: Fix error leak during failures + https://bugzilla.gnome.org/show_bug.cgi?id=755607 + +2015-09-21 13:58:51 +0200 Stian Selnes + + * plugins/elements/gstfunnel.c: + * tests/check/elements/funnel.c: + funnel: Fix racy state change + Iterator may need to be resynced, for instance if pads are released + during state change. + got_eos should be protected by the object lock of the element, not of + the pad, as is the case throughout the rest of the funnel code. + https://bugzilla.gnome.org/show_bug.cgi?id=755343 + +2015-09-21 15:22:19 +0200 Stian Selnes + + * gst/gstbin.c: + * gst/gstelement.c: + bin: element: Ignore activate result for removed pads on state change + This fixes a race where a state change may return failure if it has + request pads that are deactivated and removed (and thus have no + parent) at the same time as the element changes state and (de)activates + its pads. + https://bugzilla.gnome.org/show_bug.cgi?id=755342 + +2015-09-24 10:23:14 +0200 Havard Graff + + * libs/gst/check/gstharness.c: + * tests/check/libs/gstharness.c: + harness: don't crash when adding a sink-harness without h->sinkpad + https://bugzilla.gnome.org/show_bug.cgi?id=755511 + +2015-09-23 20:31:48 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Print buffer PTS when submitting an input buffer + +2015-09-21 14:58:46 +0900 Eunhae Choi + + * plugins/elements/gstinputselector.c: + inputselector: Fix buffer leak in sync_streams & cache_buffers mode + After doing gst_pad_push() in case of sync_streams and cache_buffers, + if the buffer can not be kept in cache, it should be unreffed to avoid + memory leackage. + https://bugzilla.gnome.org/show_bug.cgi?id=755141 + +2015-09-19 16:57:26 +0530 Vikram Fugro + + * gst/gstcaps.c: + * gst/gstpad.h: + gst: Documentation typo fix in caps & pad APIs + gst_caps_can_intersect() & GST_PAD_IS_ACCEPT_INTERSECT() + documentation typo fix. + https://bugzilla.gnome.org/show_bug.cgi?id=755257 + +=== release 1.5.91 === + +2015-09-18 19:07:18 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.5.91 + +2015-09-18 19:07:10 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-09-18 11:49:03 +0200 Sebastian Dröge + + * po/zh_CN.po: + po: Update translations + +2015-09-15 10:56:40 +0900 Vineeth TM + + * libs/gst/check/gstcheck.c: + * plugins/elements/gstdownloadbuffer.c: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + downloadbuffer, benchmarks: fix error leaks in failure code paths + https://bugzilla.gnome.org/show_bug.cgi?id=755019 + +2015-09-15 10:52:55 +0900 Vineeth TM + + * libs/gst/check/gstcheck.c: + check: Fix indentation + https://bugzilla.gnome.org/show_bug.cgi?id=755019 + +2015-09-15 18:05:11 +0100 Tim-Philipp Müller + + * gst/gstbufferpool.c: + bufferpool: sprinkle some allow-none and out annotations for g-i + +2015-09-14 11:01:11 +0900 Vineeth TM + + * gst/gstbin.c: + bin: fix typo in log message when threadpool alloc fails + https://bugzilla.gnome.org/show_bug.cgi?id=754975 + +2015-09-11 17:58:48 +0300 Igor Rondarev + + * configure.ac: + * gst/Makefile.am: + configure: Check for socketpair() in -lsocket too + On e.g. QNX it is in an external library, not libc. + https://bugzilla.gnome.org/show_bug.cgi?id=754875 + +2015-09-09 13:10:04 +0530 Arun Raghavan + + * docs/gst/gstreamer-sections.txt: + Revert "docs: Make sure gst_debug_bin_to_dot_data() is documented" + This reverts commit 0dffeb03018d12be522c2d97aaaf8102153bd7c0. + The commit is erroneous and documents the function twice. + +2015-07-23 12:18:51 +0530 Arun Raghavan + + * docs/gst/gstreamer-sections.txt: + docs: Make sure gst_debug_bin_to_dot_data() is documented + Thanks to Nirbheek Chauhan for pointing this + out. + +2015-08-05 10:07:50 +0200 Stian Selnes + + * libs/gst/check/gstharness.c: + * tests/check/libs/gstharness.c: + harness: Fix race for gst_harness_element_ref + In order for gst_harness_new_full to be MT-safe the increase and + decrease of HARNESS_REF must be MT-safe. This allows for creating + multiple harnesses from different threads wrapping the same element. + https://bugzilla.gnome.org/show_bug.cgi?id=754661 + +2015-08-05 09:59:39 +0200 Stian Selnes + + * libs/gst/check/gstharness.c: + harness: Allow-none for custom stress init func + It should be allowed to not have a function to initialize the user data + since it's often not necessary; it may already be initialized. + https://bugzilla.gnome.org/show_bug.cgi?id=754661 + +2015-09-06 09:58:09 +0100 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.signals: + docs: remove signal that no longer exists from docs + +2015-09-05 11:20:49 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for translated string changes + +2015-09-05 11:18:27 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: fix --exclude command line option + This has not worked (as in: crashed) since 2005, so + perhaps it should just be removed instead. + +2015-08-31 12:07:10 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + Revert "queue2: Process SEEKING query" + This caused problems with oggdemux when queue2 was + operating in queue mode and the souphttpsrc upstream + is not seekable because the server doesn't support + range requests. It would then still claim seekability + and then things go wrong from there. + This reverts commit 7b0b93dafe4ac547552cdb66ade5d8aa0405e7b4. + https://bugzilla.gnome.org/show_bug.cgi?id=753887 + +2015-08-29 20:14:44 +0200 Havard Graff + + * libs/gst/check/gstharness.c: + harness: misc bugfixes + 1. Get a list of pad templates from the element class, not the + factory. This allows us to interact with test-elements that does + not have a factory. + 2. Use the pad_template_caps in caps-queries when caps is not set + explicitly on the pad. Not doing so is simply wrong, and prohibits + interactions with special templates used for testing. + https://bugzilla.gnome.org/show_bug.cgi?id=754193 + +2015-08-26 09:29:05 -0300 Thiago Santos + + * tests/check/gst/gstevent.c: + tests: event: fix build failure + gst/gstevent.c:250:5: error: ‘for’ loop initial declarations are only + allowed in C99 or C11 mode + +2015-08-24 21:04:37 +0300 Vivia Nikolaidou + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: Make sure we don't add/remove a bin to/from itself + Doing so would deadlock from trying to acquire the object lock twice + https://bugzilla.gnome.org/show_bug.cgi?id=754036 + +2015-08-21 14:28:48 -0700 Nicolas Dufresne + + * libs/gst/base/gstbasetransform.c: + basetransform: Reconfigure before propose_allocation + There exist cases where a reconfigure event was propagated from + downstream, but caps didn't change. In this case, we would + reconfigure only when the next buffer arrives. The problem is that + due to the allocation query being cached, the return query parameters + endup outdated. + In this patch we refactor the reconfigurating code into a function, and + along with reconfiguring when a new buffer comes in, we also reconfigure + when a query allocation arrives. + https://bugzilla.gnome.org/show_bug.cgi?id=753850 + +2015-08-07 15:39:59 -0400 Nicolas Dufresne + + * tests/check/libs/basesrc.c: + basesrc-test: Fix race testing segment update + As this test is using a short sleep (GST_USECOND, which is 10ms + in microsecond), sometimes that EOS event is received before the + loop in basesrc have run _do_seek() and pushed the update segment. + To solve this issue, we wait for the initial segment (and flush it) + then we wait for the second segment before sending EOS. + https://bugzilla.gnome.org/show_bug.cgi?id=753365 + +2015-08-19 11:46:07 +0200 Thibault Saunier + + * scripts/gst-uninstalled: + bin: Add NLE to GST_PLUGIN_PATH + +=== release 1.5.90 === + +2015-08-19 12:50:56 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.5.90 + +2015-08-19 12:33:41 +0300 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-08-19 11:17:29 +0300 Sebastian Dröge + + * po/zh_CN.po: + po: Update translations + +2015-08-18 15:44:02 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: avoid tag list spam if upstream provides bitrate tags already + Explicitly keep track again whether upstream tags or parser tags + already contain bitrate information, and only force a tag update + for a bitrate if we are actually going to add the bitrate to the + taglist later. This fixes constant re-sending of the same taglist, + because upstream provided a bitrate already and we didn't add it, + so we didn't save the 'posted' bitrate, which would then in turn + again trigger the 'bitrate has changed too much, update tags' + code path. Fixes tag spam with m4a files for example. + https://bugzilla.gnome.org/show_bug.cgi?id=679768 + +2015-08-17 22:06:11 +0200 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: bring the dot style a bit closer to what we use in the docs + Use round corners for bins and elements. Put sink pads on the left and src pads + on the right of elements. + +2015-08-15 18:30:15 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix tag handling + In 0.10 there were no sticky events, and all tag events + sent would just be merged with the previously-received + tags. In 1.x we have sticky events, and the tags in the + tag event(s) should at all times carry the complete tags, + so we can't just push some tags and then just push tags + with just bitrates to update the bitrates, etc. + Instead we need to keep track of the upstream stream tags + received, of the tags set by the video decoder subclass, + and send an updated tag event with the combined tags + including our own bitrate tags (if applicable) whenever + the upstream tags, the subclass tags or any of our bitrates + change. + https://bugzilla.gnome.org/show_bug.cgi?id=679768 + +2015-08-16 10:15:56 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * win32/common/libgstbase.def: + baseparse: add API for subclass to set tags + This is needed so that we can do proper tag handling + all around, and combine the upstream tags with the + tags set by the subclass and any extra tags the + base class may want to add. + API: gst_base_parse_merge_tags() + https://bugzilla.gnome.org/show_bug.cgi?id=679768 + +2015-08-15 16:01:28 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: save upstream stream tags + We'll need those later. + https://bugzilla.gnome.org/show_bug.cgi?id=679768 + +2015-08-15 16:39:40 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: minor code simplification + Use gst_pad_peer_query_duration() and remove a few + unnecessary levels of indentation. Rest of code might + looks a bit questionable, but leave it as is for now. + +2015-08-15 17:59:21 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Break sticky event array iterations if the type is bigger than the one we look for + Microoptimization we can do because the array is sorted by type. + +2015-04-29 15:49:17 +0200 Edward Hervey + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + gstpad: Add a new GST_PROBE_HANDLED return value for probes + In some cases, probes might want to handle the buffer/event/query + themselves and stop the data from travelling further downstream. + While this was somewhat possible with buffer/events and using + GST_PROBE_DROP, it was not applicable to queries, and would result + in the query failing. + With this new GST_PROBE_HANDLED value, the buffer/event/query will + be considered as successfully handled, will not be pushed further + and the appropriate return value (TRUE or GST_FLOW_OK) will be returned + This also allows probes to return a non-default GstFlowReturn when dealing + with buffer push. This can be done by setting the + GST_PAD_PROBE_INFO_FLOW_RETURN() field accordingly + https://bugzilla.gnome.org/show_bug.cgi?id=748643 + +2015-08-15 13:25:35 +0200 Mathieu Duponchelle + + * gst/gstversion.h.in: + gstversion: Add missing include in .in file. + +2015-08-11 00:35:21 +0200 Mathieu Duponchelle + + * gst/glib-compat.h: + * gst/gstallocator.h: + * gst/gstatomicqueue.h: + * gst/gstcapsfeatures.h: + * gst/gstclock.h: + * gst/gstcompat.h: + * gst/gstcontext.h: + * gst/gstdeviceprovider.h: + * gst/gstelementmetadata.h: + * gst/gstmacros.h: + * gst/gstmemory.h: + * gst/gstmeta.h: + * gst/gstpad.h: + * gst/gstpluginloader.h: + * gst/gstquark.h: + * gst/gsttrace.h: + Headers: add missing includes. + +2015-08-15 06:41:14 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + docs: add the new pad accept-template flag to the docs + +2015-08-14 22:44:50 +0530 Nirbheek Chauhan + + * docs/libs/gstreamer-libs-sections.txt: + docs: section entry missing for gst_direct_control_binding_new_absolute + +2015-08-14 08:14:52 -0300 Thiago Santos + + * tests/check/gst/gstpad.c: + tests: pad: tests for accept-caps default handling + Check if all the default 4 accept-caps possibilities are working: + subset or intersect check and query-caps or template caps comparisons. + https://bugzilla.gnome.org/show_bug.cgi?id=753623 + +2015-08-14 07:51:07 -0300 Thiago Santos + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add GST_PAD_FLAG_ACCEPT_TEMPLATE + It will make the default accept-caps handler use the pad template + caps instead of the query-caps result to check if the caps is + acceptable. This is aligned with what the design docs says the + accept-caps should do (be non-recursive) and should be faster. It + is *not* enabled by default, though. + API: GST_PAD_FLAG_ACCEPT_TEMPLATE + API: GST_PAD_IS_ACCEPT_TEMPLATE + API: GST_PAD_SET_ACCEPT_TEMPLATE + API: GST_PAD_UNSET_ACCEPT_TEMPLATE + https://bugzilla.gnome.org/show_bug.cgi?id=753623 + +2015-08-14 11:10:03 +0200 Edward Hervey + + * tests/check/generic/states.c: + check: Rename states unit test + Makes it easier to differentiate from other modules states unit test + +2015-08-13 13:08:03 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: rework accept-caps + According to the design docs: + The ACCEPT_CAPS query is not required to work recursively, it can simply + return TRUE if a subsequent CAPS event with those caps would return + success. + So make it a shallow check instead of recursivelly check downstream. + https://bugzilla.gnome.org/show_bug.cgi?id=748635 + +2015-08-13 12:44:29 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: remove some dead code + Doesn't seem like it is going to get back to life anytime soon + Also removes a {} block that was likely used to keep the dead + code around. + +2015-08-11 08:07:53 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: respect accept-caps intersect flag + GstPad has a flag for suggesting if the accept-caps + query should use intersect instead of the default + subset caps operation to verify if the caps would be + acceptable. + basetransform currently always uses the subset check and + this patch makes it honor the flag for using intersect + if it is set. + https://bugzilla.gnome.org/show_bug.cgi?id=748635 + +2015-08-12 13:12:38 +0900 Vineeth TM + + * libs/gst/base/gstbasetransform.c: + basetransform: remove unreachable return statement + https://bugzilla.gnome.org/show_bug.cgi?id=753538 + +2015-08-11 11:09:24 +0100 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + tests: ignore new harness test binary + +2015-08-10 15:31:37 +0300 Vivia Nikolaidou + + * gst/gstdatetime.c: + * tests/check/gst/gstdatetime.c: + datetime: accept just a time as ISO 8601 string and use today's date then + If no date and only a time is given in gst_date_time_new_from_iso8601_string(), + assume that it is "today" and try to parse the time-only string. "Today" is + assumed to be in the timezone provided by the user (if any), otherwise Z - + just like the behavior of the existing code. + https://bugzilla.gnome.org/show_bug.cgi?id=753455 + +2015-07-24 00:41:57 +0200 Havard Graff + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + * tests/check/Makefile.am: + * tests/check/libs/gstharness.c: + harness: add _set_forwarding function + To be able to disable the slightly "magic" forwarding of the + necessary events between the harnesses. + Also introduce a new test-suite for GstHarness, that documents the + feature, and should hopefully expand into documenting most of the + features the harness possesses. + https://bugzilla.gnome.org/show_bug.cgi?id=752746 + +2015-08-08 17:59:51 +0200 Wim Taymans + + * gst/gstdevicemonitor.c: + devicemonitor: fix provider leak + +2015-08-08 15:28:19 +0200 Edward Hervey + + * gst/gstpad.c: + pad: Fix previous commit + We want to get the caps query *result* + +2015-07-16 18:56:00 +0200 Wim Taymans + + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * gst/gstdeviceprovider.c: + * gst/gstdeviceprovider.h: + * win32/common/libgstreamer.def: + deviceprovider: Add method to hide devices from a provider + Add methods to add/remove the providers that should be hidden by this + provider. Also make a method to get a list of hidden providers. + This makes it possible to have multiple systems monitor the same devices + and remove duplicates. + Add a property to see all devices, even duplicate ones from hidden + providers. + +2015-08-08 14:42:52 +0200 Edward Hervey + + * gst/gstpad.c: + pad: get_allowed_caps() should go through both pads + The previous implementation was doing a direct call to the peer pad, + which resulted in query probes never being called on the original pad. + Instead of that, get the peer pad caps by using gst_pad_peer_query() + which will call probes in the expected fashion. + +2015-08-07 10:08:21 +0900 Vineeth TM + + * gst/gstvalue.c: + value: free caps during failure + While calling gst_value_deserialize_sample, if there is a failure + after caps is ref'ed, then caps is getting leaked. Hence checking for + caps in fail: goto condition and unref'ing it + https://bugzilla.gnome.org/show_bug.cgi?id=753338 + +2015-07-21 13:35:33 +0200 Thibault Saunier + + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstregistry.c: + registry: Add plugins to the registry we are loading and not default one + When running gst_registry_scan_plugin_file we were losing the + information about the registry being loaded and ended up adding the + plugin to the default registry which was not correct. + https://bugzilla.gnome.org/show_bug.cgi?id=752662 + +2015-08-05 15:51:27 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesink.c: + basesink: Only drop buffer if their PTS is out of segment + As of now, even for stream completly inside segment, there is no + guarantied that the DTS will be inside the segment. Specifically + for H.264 with B-Frames, the first few frames often have DTS that + are before the segment. + Instead of using the sync timestamp to clip out of segment buffer, + take the duration from the start/stop provided by the sub-class, and + check if the pts and pts_end is out of segment. + https://bugzilla.gnome.org/show_bug.cgi?id=752791 + +2015-08-05 14:05:25 +0100 Luis de Bethencourt + + * libs/gst/check/gstharness.c: + harness: don't run code inside g_assert + Even though asserts can't be disabled in GstHarness, Coverity still + complains about running code inside them. Moving the code to outside the + g_asserts(). + CID #1311326, #1311327, #1311328 + +2015-07-17 10:18:02 +0200 Wim Taymans + + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * win32/common/libgstreamer.def: + devicemonitor: get a list of currently monitored providers + Get a list of the currently monitored providers. + +2015-08-02 17:38:14 +0200 George Kiagiadakis + + * gst/gstpad.c: + pad: fix invalid unref after IDLE probe on non-OK flow return + In case there is an IDLE probe fired from gst_pad_push_data and it + doesn't return GST_FLOW_OK, the code jumps to the probe_stopped + label which tries to unref the data object. However, at this point + the data object belongs downstream and must not be touched. + By setting data = NULL, the code skips this unref. + https://bugzilla.gnome.org//show_bug.cgi?id=753151 + +2015-08-04 20:08:04 +1000 Jan Schmidt + + * gst/gstbuffer.c: + buffer: Fix the name of the parentbuffermeta debug category. + Don't use 'glbufferrefmeta' as the debug category for the + parent buffer meta. + +2015-08-04 13:45:09 +0900 Eunhae Choi + + * plugins/elements/gstqueue2.c: + queue2: not update upstream size with negative value + upstream_size can be negative but queue->upstream_size is unsigned type. + to get a chance to update queue->upstream_size in gst_queue2_get_range() + it should keep the default value. + https://bugzilla.gnome.org/show_bug.cgi?id=753011 + +2015-08-04 19:59:28 +1000 Jan Schmidt + + * gst/gstbuffer.c: + * win32/common/libgstreamer.def: + buffer: Remove extra debug symbol from exports + Don't export the debug variable for the parent_buffer_meta. + This was accidentally exported and shouldn't be public + +2015-08-04 00:11:24 +0200 Stefan Sauer + + * plugins/elements/gstfilesink.c: + filesink: use GST_INFO_OBJECT for more detail + Helps to distiguish multiple filesinks. + +2015-07-30 17:29:25 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + docs: info: remove 0.8 terminology from log level description + We don't "iterate" bins or pipelines any more. + +2015-07-30 12:17:16 +0100 Tim-Philipp Müller + + * tests/check/libs/baseparse.c: + tests: baseparse: fix buffer leak in unit test + Fixes make check-valgrind + +2015-07-28 21:14:22 -0400 Nicolas Dufresne + + * gst/gstsegment.h: + doc/seekflags: Fix cross references + This fixes miss-use of @ instead of % to refer to enumeration + values. + +2015-07-28 22:30:54 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: add a few more new symbols and defines + +2015-07-28 16:57:43 -0400 Nicolas Dufresne + + * plugins/elements/gstcapsfilter.h: + doc/capsfilter: Document filtering modes + This is documentation for the HTML documentation. + +2015-07-28 16:50:55 -0400 Nicolas Dufresne + + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + doc/filesink: Add BufferMode enumeration + This is purely for documentation purpose. This way the values will + show up in the HTML documentation. + +2015-07-28 15:50:40 -0400 Nicolas Dufresne + + * libs/gst/check/gstharness.c: + doc/gsthardness: Fix typo in GstAllocationParams + It's not GstAllocatorParams but GstAllocationParams. + +2015-07-28 15:46:09 -0400 Nicolas Dufresne + + * libs/gst/check/gstharness.c: + doc/gstharness: Remove unknown parameter + sink_elenment_name is not a parameter of gst_harness_add_sink_harness() + function, but still it show up in documentation. + +2015-07-28 12:19:04 +0300 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + capsfilter: Only remember previous filter caps if they were actually used for something + If nobody ever saw the previous filter caps, nothing could've negotiated with + them and we can just pretend they never existed at all. + +2015-07-28 12:16:12 +0300 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: When switching caps change modes, forget all previous caps + +2015-07-23 18:15:05 -0400 Olivier Crête + + * libs/gst/base/gstbasetransform.c: + basetransform: Return FLOW_FLUSHING if negotiation fails during shutdown + https://bugzilla.gnome.org/show_bug.cgi?id=752800 + +2015-07-22 18:55:29 -0400 Olivier Crête + + * libs/gst/check/gstharness.c: + harness: Fix indendation + +2015-07-21 13:14:59 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasetransform.c: + basetransform: Avoid increasing query reference + gst_query_find_allocation_meta() requires the query to be + writable to work. This patch ensure avoids taking a reference + on the query, so we can now check if a certain allocation meta + is present. + https://bugzilla.gnome.org/show_bug.cgi?id=752661 + +2015-07-22 15:38:06 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + docs: fix description of gst_buffer_extract_dup() + No GBytes involved. + +2015-07-21 00:17:28 -0300 Thiago Santos + + * plugins/elements/gstconcat.c: + concat: dot not reset pad states too early + Resetting the flushing state of the pads at the end of the + PAUSED_TO_READY transition will make pads handle serialized + queries again which will wait for non-active pads and might + cause deadlocks when stopping the pipeline. + Move the reset to the READY_TO_PAUSED instead. + https://bugzilla.gnome.org/show_bug.cgi?id=752623 + +2015-07-20 16:18:06 +0200 Havard Graff + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + harness: add functions for adding sub-harnesses directly + By introducing gst_harness_add_src_harness and gst_harness_add_sink_harness + we collect all sub-harness setup in one function, making the previous + sub-harness creation functions now calls these directly, and making it + much easier (and less error-prone) to add your own src or sink-harness + using the more generic harness-creation functions. + +2015-07-17 17:44:52 -0400 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: Don't override gst_segment_do_seek() + This line has no purpose, clearly gst_segment_do_seek() is doing + the right job, also, having the start time (a timestamp) be that + same as time (the stream time) is quite odd. + https://bugzilla.gnome.org/show_bug.cgi?id=750783 + +2015-07-17 17:43:26 -0400 Nicolas Dufresne + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix extrapolation of seeksegment.stop + The stop shall be relative to start if extrapolated from the + duration. + https://bugzilla.gnome.org/show_bug.cgi?id=750783 + +2015-07-16 18:47:20 +0200 Wim Taymans + + * gst/gstdevicemonitor.c: + devicemonitor: do start and stop outside of the lock + Release the monitor lock when calling the provider start/stop methods. + Because we release the lock now, We need to make sure we check the + cookie again and keep track of started and removed providers. + +2015-07-16 18:43:06 +0200 Wim Taymans + + * gst/gstdeviceprovider.c: + * gst/gstdeviceprovider.h: + deviceprovider: small cleanups + Protect against wrong arguments. + Clean up the header file indentation. + +2015-07-16 17:25:24 +0200 Wim Taymans + + * gst/gstdevicemonitor.c: + devicemonitor: keep order of providers and devices + The deviceproviders are added to the array sorted by their rank. Make + sure we keep this ordering when removing a provider. + We use _prepend to collect the devices, use g_list_reverse to get the + devices in the right order; sorted by rank and in the same order as + returned by the provider. + +2015-07-16 17:50:49 +0100 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: fix indentation + +2015-07-16 17:50:06 +0100 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: fix pad template leak + +2015-07-16 17:13:35 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + docs: drop reference to sourceforge mailing list adress + +2015-07-16 17:53:40 +0200 Havard Graff + + * libs/gst/check/gstharness.c: + harness: don't re-establish the harness sink and src pads + Given that the element has the possibility to have one, they should + already be there. + https://bugzilla.gnome.org/show_bug.cgi?id=752498 + +2015-07-13 11:03:13 +0200 Stian Selnes + + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + harness: Improve detection of element type + The element flag does not indicate wether a bin should be tested as a + source or as a sink, eg. a bin with the sink flag may still have a + source pad and a bin with the source flag may have a sink pad. In this + case it is better to determine the element type by looking at the + available pads and pad templates. + Also rename srcpad and sinkpad where it actually represents + element_srcpad_name and element_sinkpad_name. + https://bugzilla.gnome.org/show_bug.cgi?id=752493 + +2015-07-13 11:10:49 +0200 Stian Selnes + + * libs/gst/check/gstharness.c: + harness: Forward sticky events to sink harness + Fixes issue where if a sink harness was added late the sticky events + would not be forwared. + https://bugzilla.gnome.org/show_bug.cgi?id=752494 + +2015-07-16 12:36:14 +0100 Tim-Philipp Müller + + * libs/gst/check/gstharness.h: + harness: make header nicer to read + +2015-07-16 10:36:36 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: add new function to API docs + +2015-07-15 18:21:13 +0200 Wim Taymans + + * gst/gstdevice.c: + * gst/gstdevice.h: + * win32/common/libgstreamer.def: + device: add generic struct with properties + Add a generic structure to hold any additional properties about the + device. + +2015-07-14 12:44:12 +0100 Tim-Philipp Müller + + * plugins/elements/gsttee.c: + tee: fix typo in allow-not-linked property description + +2015-07-13 14:24:34 +0100 Tim-Philipp Müller + + * gst/gstbus.c: + docs: bus: mention main loop requirement in gst_bus_add_watch() docs + +2015-03-18 16:05:34 +0530 Prashant Gotarne + + * gst/gsttask.c: + task: add function guard for _set_lock() and fix guard for _join() + Should only access the object structure after checking + it's valid in gst_task_join(). + https://bugzilla.gnome.org/show_bug.cgi?id=746385 + https://bugzilla.gnome.org/show_bug.cgi?id=746431 + +2015-05-19 18:58:11 +0200 Philippe Normand + + * gst/gstprotection.c: + protection: implement meta transform function + Copy the GstMeta contents over to the new buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=749590 + +2015-07-10 09:12:15 +0900 Vineeth TM + + * libs/gst/base/gstbaseparse.c: + baseparse: estimate duration on EOS + For files which are smaller than 1.5 seconds, the duration + estimation does not happen. So the duration will always be + displayed as 0. Updating the duration on EOS when the estimation + has not happened already + https://bugzilla.gnome.org/show_bug.cgi?id=750131 + +2015-07-10 11:01:21 +0900 Hyunjun Ko + + * libs/gst/base/gstadapter.c: + adapter: change log message properly + https://bugzilla.gnome.org/show_bug.cgi?id=752116 + +2015-07-09 00:12:51 +0900 Justin Joy + + * plugins/elements/gststreamiddemux.c: + * plugins/elements/gststreamiddemux.h: + docs: add StreamidDemux to documentation + https://bugzilla.gnome.org/show_bug.cgi?id=749873 + +2015-07-09 00:21:42 +0900 Hyunjun Ko + + * libs/gst/base/gstadapter.c: + adapter: fix to get valid (buffer_)list + get_list/get_buffer_list should be done with buffers in adapter remaining + while take_list/take_buffer_list flushes each buffer one by one. + https://bugzilla.gnome.org/show_bug.cgi?id=752116 + +2015-07-08 20:06:27 +0900 Hyunjun Ko + + * tests/check/libs/adapter.c: + adapter: unit test for new get_(buffer_)list + +2015-07-08 12:00:56 +0200 Arnaud Vrac + + * libs/gst/base/gstbaseparse.c: + baseparse: put buffer in a correct state after gst_adapter_get_buffer call + We must make the buffer writable to write its PTS and DTS, and also + reset its duration. + The behaviour is now the same as before commit c3bcbadd, except metas + might still be attached to the buffer extracted from the adapter. + https://bugzilla.gnome.org/show_bug.cgi?id=752092 + +2015-07-07 15:02:45 +0100 Tim-Philipp Müller + + * libs/gst/check/gstharness.c: + harness: fix indentation and replace stress test function macros + These screw with indentation and seem a bit trivial. Just copy'n'paste. + +2015-07-07 10:46:48 +0900 Hyunjun Ko + + * gst/gstbuffer.c: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetcontrolmessagemeta.c: + * tests/check/gst/gstmeta.c: + meta: transform_func: return FALSE if not supported or failed + https://bugzilla.gnome.org/show_bug.cgi?id=751778 + +2015-07-07 11:53:07 +0200 Havard Graff + + * plugins/elements/gstidentity.c: + * tests/check/elements/identity.c: + identity: refactor and add tests using GstHarness + Writing a test for unscheduling the gst_clock_id_wait inside the + identity element, found an invalid read, caused by removing the clock-id + when calling _unschedule instead of letting the code calling _wait remove + the clock-id after being unscheduled. + https://bugzilla.gnome.org/show_bug.cgi?id=752055 + +2014-04-12 19:48:15 +0100 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + harness: make sure g_assert() statements are always active + We have code with side effects inside g_assert()s, so make + sure those are always enabled here (they might otherwise + get disabled for release builds). + +2015-07-07 00:56:41 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + harness: rename GstHarnessPrepareBuffer -> GstHarnessPrepareBufferFunc + https://bugzilla.gnome.org/show_bug.cgi?id=751916 + +2015-07-07 00:53:48 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/check.h: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + docs: add GstHarness to documentation + https://bugzilla.gnome.org/show_bug.cgi?id=751916 + +2013-12-16 10:47:47 +0100 Havard Graff + + * libs/gst/check/Makefile.am: + * libs/gst/check/gstharness.c: + * libs/gst/check/gstharness.h: + check: Add GstHarness convenience API for unit tests + http://gstconf.ubicast.tv/videos/gstharness-again-a-follow-up/ + https://bugzilla.gnome.org/show_bug.cgi?id=751916 + +2015-07-06 09:26:58 +0900 Vineeth TM + + * libs/gst/base/gstbaseparse.c: + baseparse: reverse playback in pull mode + right now reverse playback is disabled in pull mode. + enabling the code for the same and changing a bit of logic + to make reverse playback work. + https://bugzilla.gnome.org/show_bug.cgi?id=750783 + +2015-06-20 08:33:26 +0900 Vineeth T M + + * tests/check/libs/baseparse.c: + baseparse: add reverse playback test in pull mode + add test for reverse playback in pull mode and compare + the buffers being received in sink chain to make sure + the playback is allright + https://bugzilla.gnome.org/show_bug.cgi?id=750783 + +2015-07-06 14:31:24 +0530 Arun Raghavan + + * scripts/git-update.sh: + Revert "scripts: Allow passing make flags to git-update.sh" + This reverts commit ab5fdd72129ea61e8dff51cdc0afcccac03ebc2b. + We can use the MAKEFLAGS environment variable to pass options to make, + so avoid adding another mechanism that could be confusing. + +2015-07-06 11:16:27 +0530 Arun Raghavan + + * gst/gstpad.h: + pad: Clarify pad probe return type documentation + +2015-07-02 14:32:21 +0800 Song Bing + + * libs/gst/base/gstbasesink.c: + basesink: Shouldn't drop buffer when sync=false + Shouldn't drop buffer when sync=false + https://bugzilla.gnome.org/show_bug.cgi?id=751819 + +2015-07-06 11:25:50 +0530 Arun Raghavan + + * scripts/git-update.sh: + scripts: Allow passing make flags to git-update.sh + Mostly adding this for add a -jN as appropriate while building. + +2015-05-30 14:27:05 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + queue: avoid slice allocs/frees for each item + Microoptimisation: Let GstQueueArray store our + item struct. That way we don't have to alloc/free + temporary QueueItem slices for every item we want + to put into the queue. + https://bugzilla.gnome.org/show_bug.cgi?id=750149 + +2015-05-30 13:07:50 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * win32/common/libgstbase.def: + queuearray: allow storing of structs in addition to pointers + This way we don't have to allocate/free temporary structs + for storing things in the queue array. + API: gst_queue_array_new_for_struct() + API: gst_queue_array_push_tail_struct() + API: gst_queue_array_peek_head_struct() + API: gst_queue_array_pop_head_struct() + API: gst_queue_array_drop_struct() + https://bugzilla.gnome.org/show_bug.cgi?id=750149 + +2015-07-03 21:57:55 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From f74b2df to 9aed1d7 + +2015-06-19 00:05:44 -0400 Olivier Crête + + * gst/gstpad.c: + * tests/check/gst/gstbin.c: + pad: Enforce NEED_PARENT flag also for chain + The check for the presence of the parent in the presence of + the NEED_PARENT flag was missing for the chain function. Also keep + a ref on the parent in case the pad is removed mid-chain. + +2015-07-03 15:55:08 +0200 Stefan Sauer + + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + docs: update for two missing elements + Concat was not linked and streamiddemux was missing. + +2015-07-03 12:37:54 +0200 Stefan Sauer + + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + * plugins/elements/gstfakesrc.c: + docs: another sweep canonicalizing the plugin docs sections file + Use underscores for capsfilter macros. Correct the type-name for fakesrc + if we ever implement the enum. + +2015-07-03 11:45:19 +0200 Stefan Sauer + + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gsttypefindelement.h: + docs: order and canonicalize the -sections.txt file + Have all sections in alphabetical order. Also make the macro order consistent. + This is a preparation for generating the file. Remove GET_CLASS macro for + typefine element, since it is not used and the header is not installed. + +2013-12-16 11:24:17 +0100 Stian Selnes + + * gst/gstmemory.h: + memory: Add missing field initializers to GstMapInfo + https://bugzilla.gnome.org/show_bug.cgi?id=751881 + +2015-07-02 15:10:43 +0100 Luis de Bethencourt + + * plugins/elements/gstinputselector.c: + inputselector: remove always-true check + event can't be NULL, it has been dereferenced by GST_EVENT_TYPE (), and no + case frees the pointer. Remove unnecessary check which will always be True. + CID #1308955 + +2015-07-01 10:50:19 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + transform: Also copy POOL metas and make sure to copy over metas when creating subbuffers + POOL meta just means that this specific instance of the meta is related to a + pool, a copy should be made when reasonable and the flag should just not be + set in the copy. + +2015-07-01 10:45:01 +0200 Sebastian Dröge + + * libs/gst/base/gstadapter.c: + adapter: Also copy POOL metas and make sure to copy over metas when creating subbuffers + POOL meta just means that this specific instance of the meta is related to a + pool, a copy should be made when reasonable and the flag should just not be + set in the copy. + +2015-07-01 10:36:36 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Don't copy "memory" metas unconditionally + Don't copy memory metas if we only copied part of the buffer, didn't + copy memories or merged memories. In all these cases the memory + structure has changed and the memory meta becomes meaningless. + https://bugzilla.gnome.org/show_bug.cgi?id=751712 + +2015-07-01 10:25:15 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + Revert "buffer: Don't copy POOLED and memory metadata unconditionally" + This reverts commit 7a08fa5ec4804f104e9aa9f458322f6eb49a7e49. + +2015-06-30 13:38:10 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Don't copy POOLED and memory metadata unconditionally + https://bugzilla.gnome.org/show_bug.cgi?id=751712 + +2015-06-30 11:18:24 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Use new gst_adapter_get_buffer() API instead of gst_adapter_map() + This preserves GstMeta properly unless the subclass does special things. It's + enough to make h264parse's stream-format/alignment conversion pass through + metas as needed. + https://bugzilla.gnome.org/show_bug.cgi?id=742385 + +2015-06-30 11:11:25 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * win32/common/libgstbase.def: + adapter: Add get variants of the buffer based take functions + Main difference to gst_adapter_map() for all practical purposes is that + GstMeta of the buffers will be preserved. + https://bugzilla.gnome.org/show_bug.cgi?id=742385 + +2015-06-29 17:03:10 +0200 Sebastian Dröge + + * libs/gst/base/gstadapter.c: + adapter: Copy over GstMeta from the input buffers to the output + All functions that return a GstBuffer or a list of them will now copy + all GstMeta from the input buffers except for meta with GST_META_FLAG_POOLED + flag or "memory" tag. + This is similar to the existing behaviour that the caller can't assume + anything about the buffer flags, timestamps or other metadata. And it's + also the same that gst_adapter_take_buffer_fast() did before, and what + gst_adapter_take_buffer() did if part of the first buffer or the complete + first buffer was requested. + https://bugzilla.gnome.org/show_bug.cgi?id=742385 + +2015-06-29 20:27:12 -0400 Olivier Crête + + * libs/gst/net/gstptpclock.c: + ptp: Init function can take a NULL interfaces array + +2015-06-29 13:57:11 +0900 Vineeth TM + + * tests/check/gst/gstcaps.c: + tests: caps: fix test_intersect_flagset failure + test_intersect_flagset fails because when caps is being + created, flags and mask are being cast to uint64 while + they should be uint. This results in invalid memory access + or a segfault. + https://bugzilla.gnome.org/show_bug.cgi?id=751628 + +2015-06-29 14:22:46 +0200 Thibault Saunier + + * scripts/gst-uninstalled: + scripts: Fix GST_VALIDATE_PLUGIN_PATH + It moved recently + +2015-06-29 13:58:04 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.h: + basetransform: Fix up documentation of transform_meta vfunc + By default we copy all metas that have no tags. + +2015-06-29 10:41:27 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.h: + directcontrolbinding: fix ABI break + Structure size was increased without adjustment of the padding. + https://bugzilla.gnome.org/show_bug.cgi?id=751622 + https://bugzilla.gnome.org/show_bug.cgi?id=740502 + +2015-03-19 15:55:14 +0530 Prashant Gotarne + + * gst/gsttask.c: + task: guard against NULL task function + https://bugzilla.gnome.org/show_bug.cgi?id=746439 + +2015-05-14 11:48:45 +0200 Miguel París Díaz + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstfunnel.h: + funnel: add "forward-sticky-events" property + It is useful to avoid sending sticky event on stream changes. + https://bugzilla.gnome.org/show_bug.cgi?id=749315 + +2015-06-25 00:04:07 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.5.2 === + +2015-06-24 22:49:17 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.5.2 + +2015-06-24 22:45:00 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-06-22 23:37:27 -0300 Thiago Santos + + * tests/check/gst/gstutils.c: + tests: gstutils: fix wrong description of test element + It is a fakesink with request pads, not a source + +2015-06-24 15:35:16 +0200 Jonas Holmberg + + * gst/gstbufferpool.c: + bufferpool: Fixed compiler warning + The pool variable was unused when buidling with debug disabled. + +2015-06-24 11:13:40 +0200 Sebastian Dröge + + * po/cs.po: + * po/de.po: + * po/hu.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/uk.po: + * po/vi.po: + po: Update translations + +2015-06-24 11:12:03 +0200 Sebastian Dröge + + * win32/common/libgstreamer.def: + win32: Update .def file for new API + +2015-06-24 14:19:04 +0900 Hyunjun Ko + + * libs/gst/base/gstbasesink.c: + basesink: need to deep-copy last buffer list in drain + https://bugzilla.gnome.org/show_bug.cgi?id=751420 + +2015-06-24 10:52:02 +0200 Sebastian Dröge + + * gst/gstbufferlist.c: + bufferlist: Warn if copying a buffer fails in gst_buffer_list_copy_deep() + +2015-06-24 14:18:47 +0900 Hyunjun Ko + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: add new api gst_buffer_list_copy_deep + https://bugzilla.gnome.org/show_bug.cgi?id=751420 + +2015-06-23 16:58:56 +0200 Jonas Holmberg + + * libs/gst/check/gstcheck.c: + * tests/check/gst/gstobject.c: + gstcheck: Print newline in message handler + The message handler is supposed to print a newline after the message + just like the default message handler. + +2015-06-12 16:54:32 +0800 Song Bing + + * plugins/elements/gstinputselector.c: + inputselector: Handle different duration track selection + Support track switch from EOS track to non-EOS one. + https://bugzilla.gnome.org/show_bug.cgi?id=750761 + +2015-06-12 16:52:46 +0800 Song Bing + + * gst/gstpad.c: + pad: Clear EOS flag after received STREAM_START event + Clear EOS flag after received STREAM_START event + https://bugzilla.gnome.org/show_bug.cgi?id=750761 + +2015-06-22 14:30:49 -0300 Thiago Santos + + * tests/check/gst/gstutils.c: + tests: gstutils: add tests for gst_element_get_compatible_pad + Adds tests for gst_element_get_compatible_pad for when it has to + request pads. + Note that these tests don't cover the case when it has to request + a pad that already exists. + https://bugzilla.gnome.org/show_bug.cgi?id=751235 + +2015-06-19 15:46:56 -0300 Thiago Santos + + * gst/gstutils.c: + utils: use caps when getting a compatible pad by template + Do not ignore the caps argument when requesting a pad by template. + This is particularly harmful when the pad caps query by default + returns ANY so it will match the first template instead of the + one that actually intersects with the caps. + https://bugzilla.gnome.org/show_bug.cgi?id=751235 + +2015-06-23 00:14:30 +1000 Jan Schmidt + + * gst/gstsample.h: + gstsample.h: Include gstbufferlist.h now that it uses GstBufferList + +2015-06-17 16:12:13 +0200 Mathieu Duponchelle + + * plugins/elements/gstconcat.c: + concat: when releasing pad, send EOS appropriately. + Previously, concat sent an EOS if there was a next pad. + https://bugzilla.gnome.org/show_bug.cgi?id=751107 + +2015-06-16 16:14:18 +0200 Carlos Rafael Giani + + * plugins/elements/gstconcat.c: + * plugins/elements/gstconcat.h: + concat: Add adjust-base property + This disables the segment.base adjustments, which is useful if downstream + takes care of base adjustments already (example: a combination of concat + and streamsynchronizer) + https://bugzilla.gnome.org/show_bug.cgi?id=751047 + +2015-06-22 14:04:45 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Unset the last buffer list if we only got a buffer + Also remember any preroll buffer list. + +2015-06-22 13:33:29 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + sample: Add new API to the docs + +2015-06-22 20:02:55 +0900 Hyunjun + + * libs/gst/base/gstbasesink.c: + basesink: enable to get last sample including buffer list if needed + In case of a buffer list rendering, last-sample is not updated. + It needs to be updated and enable to get buffer list from last-sample. + https://bugzilla.gnome.org/show_bug.cgi?id=751026 + +2015-06-22 19:35:40 +0900 Hyunjun + + * gst/gstsample.c: + * gst/gstsample.h: + sample: add gst_sample_set/get_buffer_list apis + Allowed to set/get buffer list to sample if needed + https://bugzilla.gnome.org/show_bug.cgi?id=751026 + +2015-06-19 10:52:10 +0100 Tim-Philipp Müller + + * test.py: + test.py: remove accidentally committed file + +2015-06-18 11:51:48 -0400 Nicolas Dufresne + + * gst/gstbuffer.c: + * gst/gstelementfactory.h: + * gst/gstsegment.h: + * gst/gstsystemclock.h: + * libs/gst/base/gstbasetransform.h: + doc: Unify Since mark for attribute and enum + As this show up as prose in the doc, simply make it consistent + and "arguable" nicer to read. + +2015-06-18 11:48:50 -0400 Nicolas Dufresne + + * gst/gstbuffer.h: + doc: Remove parenthesis around Since: + This confuse the parser, hence it does not endup in the doc and the + index properly. + +2015-05-06 16:44:48 +1000 Jan Schmidt + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + Add GstParentBufferMeta + A core meta which helps implement the old concept + of sub-buffering in some situations, by making it + possible for a buffer to keep a ref on a different + parent buffer. The parent buffer is unreffed when + the Meta is freed. + This meta is used to ensure that a buffer whose + memory is being shared to a child buffer isn't freed + and returned to a buffer pool until the memory + is. + https://bugzilla.gnome.org/show_bug.cgi?id=750039 + +2015-06-16 18:08:24 -0400 Nicolas Dufresne + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + * test.py: + gi: Use INTROSPECTION_INIT for --add-init-section + This new define was added to common. The new init section fixed + compilation warning found in the init line that was spread across + all files. + +2015-06-16 17:46:44 -0400 Nicolas Dufresne + + * common: + Automatic update of common submodule + From 6015d26 to f74b2df + +2015-06-15 10:06:00 -0400 Nicolas Dufresne + + * gst/gstclock.h: + clock: Fix _STIME_FORMAT macros + This macro didn't work well as it relied on the sign on the last + divided number (number of days). This value is most of the time + zero, and zero is considered positive in printf. Instead, deal with + the sign manually, and resuse the original macros for the rest. This + actually simplify the macro a lot. + +2015-06-14 20:48:29 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefindelement: reset segment only once streaming has stopped + Fixes the occasional criticals in the discoverer unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=745073 + https://bugzilla.gnome.org/show_bug.cgi?id=750823 + +2015-06-14 11:23:22 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-sections.txt: + doc: Add more missing symbols in lib-sections.txt + These where causing broken links. + +2015-06-14 11:22:54 -0400 Nicolas Dufresne + + * libs/gst/net/gstnetaddressmeta.c: + doc: Fix reference to unknown type GstNetAddress + +2015-06-14 11:22:36 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + doc: Include and fix GstControlPoint + +2015-06-14 11:21:26 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-docs.sgml: + doc: Add GstNetControlMessageMeta to the doc + This is being referenced elsewhere, but results in broken links. + It seems to be public API, so I think it should be in the doc. + +2015-06-14 10:59:51 -0400 Nicolas Dufresne + + * libs/gst/base/gstpushsrc.h: + doc: Document GstPushSrcClass + +2015-06-14 10:58:18 -0400 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.h: + doc: Better document new GstCollectData.ABI.abi.dts + The doc generator get confused with the inline structure. So + workaround by wrapping the inner of the structure with + public/private mark, and document that GST_COLLECT_PADS_DTS macro + shall be used to access this. + +2015-06-14 10:56:28 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.h: + * libs/gst/net/gstnetcontrolmessagemeta.h: + * libs/gst/net/gstptpclock.h: + doc: Various doc fixes for libgstreamer-base + * Fix function name in sections.txt + * Add few missing or fix miss-named + * Workaround gtk-doc being confused with non typedef + types (loose track of public/private + +2015-06-14 10:25:52 -0400 Nicolas Dufresne + + * gst/gstdevicemonitor.c: + * gst/gsturi.c: + * gst/gsturi.h: + * gst/gstvalue.c: + doc: More doc warning fixes + So from this point, the remaining warning for libgstreamer are about + protected member not showing in the doc. This may need some discussion + with upstream gtk-doc people. + * Remove % in from of none macro + * Fixed GST_TYPE_FAGS -> GST_TYPE_FAG_SET + * Minor wording fix + * Can't link to GstUri.port, so split the .port part + +2015-06-14 09:17:21 -0400 Nicolas Dufresne + + * gst/gsturi.c: + doc: In GstUri we meant nul-terminated, not %NULL + %NULL refers to the pointer. I've written it this way in one + word as this is what GLib uses. + +2015-06-13 21:02:20 -0400 Nicolas Dufresne + + * gst/gstplugin.h: + doc: Cannot reference GST_PACKAGE_RELEASE_DATETIME + So simply remove the % sign. + +2015-06-13 20:52:01 -0400 Nicolas Dufresne + + * gst/gstclock.c: + doc: Fix typo in ref _clock_wait_for_sync() + +2015-06-13 20:37:34 -0400 Nicolas Dufresne + + * gst/gsturi.c: + doc: Fix GstUri doc typos + * Use &perctn; instead of reserved character % + * NULL take two L + +2015-06-13 20:19:59 -0400 Nicolas Dufresne + + * gst/gstallocator.h: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.h: + * gst/gstclock.h: + * gst/gsterror.h: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstprotection.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + doc: Fix Since: marks + There was few Since: mark missing their column. Also unify the way + we set the Since mark on enum value and structure members. These + sadly don't show up in the index. + +2015-06-13 20:01:27 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + doc: Add gst_buffer_copy_deep() + +2015-06-13 19:47:45 -0400 Nicolas Dufresne + + * libs/gst/check/gstconsistencychecker.c: + gi: Skip gst_consitency_checker_new + This non boxed type cannot be allocated safely. + +2015-06-13 19:46:21 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + doc: Add indexes of added APIs + One of the nice feature in GTK doc is that it generate indexes + of added APIs base on the since marker. Include that in our doc + while fixing the issue of duplicate ID (produce xml contains that + id it seems) + +2015-06-13 15:10:53 -0400 Nicolas Dufresne + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + doc: Make ..._source_find_control_point_iter transfer none + +2015-06-13 14:40:43 -0400 Nicolas Dufresne + + * libs/gst/net/gstntppacket.c: + doc: Silence warning about unused gstntppacket section + This API is internal. + +2015-06-13 14:37:42 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/net/gstntppacket.c: + Revert "doc: Add GstNtpPacket to the doc" + This reverts commit c4eb876961aba1092c4831a8feaf48d7be1e38ae. + Oops, this is not a public API + +2015-06-13 14:21:41 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/net/gstntppacket.c: + doc: Add GstNtpPacket to the doc + +2015-06-13 13:55:27 -0400 Nicolas Dufresne + + * libs/gst/base/gstindex.c: + doc: Remove gstindex from doc comment + Moving that to normal comment to silence the generator. GstIndex + is not in GStreamer library at the moment (removed from 0.10). + +2015-06-13 13:48:03 -0400 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.c: + gi: Set collectpads function param scope + +2015-06-13 13:42:58 -0400 Nicolas Dufresne + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytewriter.c: + gi: Skip allocator of non-boxed structure + These are not usable as they are, and can easily lead to crash + or leaks. This also silence warning from the scanner. If we manage to + make this usable, we can then remove that mark, it will require + to make this type boxed. + +2015-06-13 13:24:13 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Give gstconfig a nice name + As all other section do have a nice came case name, it seems + more consistent. + +2015-06-13 13:19:21 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Add missing gst_event_new/parse_protection + +2015-06-13 13:19:05 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Give gstprotection section a nice title + +2015-06-13 13:14:30 -0400 Nicolas Dufresne + + * gst/gstevent.c: + doc: Remove uneeded protectionevent section + These functions are part of gstevent section already. Keep the doc, + since it's good. + +2015-06-13 12:32:49 -0400 Nicolas Dufresne + + * gst/gsttaglist.c: + taglist: Add missing scope to func param + This tell GI if this function is for actions (call) or is the + answer of this method being asynchronous (async). In this case + it's a call. This also silence warning from the GI scanner. + +2015-06-13 12:27:31 -0400 Nicolas Dufresne + + * gst/gstprotection.h: + gstprotection: Add missing Since 1.6 mark + +2015-06-13 12:26:13 -0400 Nicolas Dufresne + + * gst/gstprotection.c: + gstprection: _add_protection_meta() is transfer none + Just like gst_buffer_add_meta() this function should also be + transfer none. This also silence a gi warning about returning + a copy of a non boxed bare structure. + +2015-06-13 12:25:19 -0400 Nicolas Dufresne + + * gst/gstprotection.c: + * gst/gstprotection.h: + * tests/check/gst/gstprotection.c: + gstprotection: Add missing namespace to macro + GST_PROTECTION_SYSTEM_ID_CAPS_FIELD was missing the GST_ namespace. + Add it before its too late. + +2015-06-13 11:55:10 -0400 Nicolas Dufresne + + * gst/gstversion.h.in: + doc: Keep SECTION: after the ifdef + Otherwise GTK doc will see it as often as we include that files + and warn about duplicated SECTION: + +2015-06-13 10:23:52 -0400 Nicolas Dufresne + + * gst/gstminiobject.c: + gi: Skip mini object method that play with refcounting + It make no sense to allow using that. Any use would lead to leak + of crash. Note that GMiniObject is entirely unusable as you cannot + cast from let's say GstBuffer to GstMiniObject. + +2015-06-13 15:05:05 +0100 Tim-Philipp Müller + + libs: more doc scanner fixes + gstbasetransform.h:196: Warning: GstBase: "@submit_input_buffer" parameter unexpected at this location: + * @submit_input_buffer: Function which accepts a new input buffer and pre-processes it. + gstnetcontrolmessagemeta.c:103: Warning: GstNet: gst_buffer_add_net_control_message_meta: unknown parameter 'message' in documentation comment, should be 'addr' + +2015-06-13 09:37:46 -0400 Nicolas Dufresne + + * gst/gstminiobject.h: + doc: Fix annoation for GstMiniObject + Replacing reprecated "Ref Func:", "Unref Fun:" etc. comment block + with appropriate (ref-func name) etc. annotation. + +2015-06-13 09:34:06 -0400 Nicolas Dufresne + + * gst/gstelementfactory.h: + doc: Fix unbalanced parenthesis + +2015-06-13 09:30:24 -0400 Nicolas Dufresne + + * gst/gstclock.h: + doc: Fix more typo + +2015-06-13 09:22:41 -0400 Nicolas Dufresne + + * gst/gstclock.h: + doc: Fix type in previous commit + Marker is (value .. not (alue. + +2015-06-13 09:19:27 -0400 Nicolas Dufresne + + * gst/gstclock.h: + * gst/gstelementfactory.h: + doc: Don't use deprecated Value: and Type: comment + Instead use appropriate annotation. Annotations can be added + to the right of the constant name in a comment block. + +2015-06-12 17:07:38 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-sections.txt: + collectpads: Add new macro to the doc + https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-06-12 17:07:26 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + clock: Add new signed time macro to the doc + https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-06-10 14:17:01 -0400 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.c: + collectpads: Don't initially send an invalid DTS + Sending a possibly invalid DTS may confuse the muxers, which will + then think the DTS is going backward. + https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-04-03 17:54:50 -0400 Nicolas Dufresne + + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * tests/check/libs/collectpads.c: + collectpads: Add negative DTS support + Make gst_collect_pads_clip_running_time() function also store the + signed DTS in the CollectData. This signed DTS value can be used by + muxers to properly handle streams where DTS can be negative initially. + https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-06-12 12:06:05 -0400 Nicolas Dufresne + + * gst/gstclock.h: + clock: Add signed time utilities + Add utility to print signed value of time. This is useful to + trace running time values in gint64 or GstClockTimeDiff values. + Additionally, define GST_CLOCK_STIME_NONE to indicate an invalid + signed time value and validation macro. New macros are: + GST_CLOCK_STIME_NONE + GST_CLOCK_STIME_IS_VALID + GST_STIME_FORMAT + GST_STIME_ARGS + https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-06-10 20:44:26 -0300 Thiago Santos + + * gst/gstmessage.c: + message: add allow-none to gst_message_new_ function + No restriction for creating messages without a source + +2015-06-12 13:45:33 +0100 Tim-Philipp Müller + + * win32/common/libgstcontroller.def: + win32: update .def file for new API + +2015-05-27 12:29:41 +0300 Lazar Claudiu + + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.h: + * tests/check/libs/controller.c: + * tests/examples/controller/.gitignore: + * tests/examples/controller/Makefile.am: + * tests/examples/controller/absolute-example.c: + controller: Added absolute direct control binding, example and test + Fixes: 740502 + API: gst_direct_control_binding_new_absolute + +2015-06-04 00:03:16 +1000 Matthew Waters + + * docs/gst/gstreamer-sections.txt: + * gst/gstallocator.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: provide a mem_map_full that takes the GstMapInfo + Follow up of 7130230ddb349d0ca7942abdba26b7558df055d1 + Provide the memory implementation the GstMapInfo that will be used to + map/unmap the memory. This allows the memory implementation to use + some scratch space in GstMapInfo to e.g. track different map/unmap + behaviour or store extra implementation defined data about the map + in use. + https://bugzilla.gnome.org/show_bug.cgi?id=750319 + +2015-04-08 14:21:43 -0700 Alison Chaiken + + * docs/manual/basics-pads.xml: + docs: manual: fix name reversal in basics-pads + https://bugzilla.gnome.org/show_bug.cgi?id=747532 + +2015-06-11 23:06:26 +0100 Tim-Philipp Müller + + * plugins/elements/gstelements_private.c: + gst_writev: define UIO_MAXIOV on iOS/OSX + Apparently it's only seton iOS/OSX if defined(KERNEL). + +2015-06-12 01:15:19 +1000 Jan Schmidt + + * plugins/elements/gstelements_private.c: + gst_writev: Respect UIO_MAXIOV limit for the iov array + If we receive more than UIO_MAXIOV (1024 typically) buffers + in a single writev call, fall back to consolidating them + into one output buffer or multiple write calls. + This could be made more optimal, but let's wait until it's + ever a bottleneck for someone + +2015-06-11 12:34:04 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * win32/common/libgstreamer.def: + pipeline: Add gst_pipeline_set_latency(), getter and GObject property + This overrides the default latency handling and configures the specified + latency instead of the minimum latency that was returned from the LATENCY + query. + https://bugzilla.gnome.org/show_bug.cgi?id=750782 + +2015-06-11 11:37:30 +0200 Carlos Rafael Giani + + * plugins/elements/gstconcat.c: + concat: Add active-pad property + https://bugzilla.gnome.org/show_bug.cgi?id=746949 + +2015-06-11 11:05:53 +0200 Sebastian Dröge + + * plugins/elements/gstconcat.c: + concat: Also reset the current start offset when receiving a FLUSH_STOP on the srcpad + +2015-06-11 11:05:38 +0200 Sebastian Dröge + + * plugins/elements/gstconcat.c: + concat: Add some newlines to event handling code to make the code look a bit less dense + +2015-06-11 10:53:30 +0200 Carlos Rafael Giani + + * plugins/elements/gstconcat.c: + concat: Reset segment base offset after FLUSH_STOP with reset_time = TRUE + If the reset_time value of a FLUSH_STOP event is set to TRUE, the pipeline + will have the base_time of its elements reset. This means that the concat + element's current_start_offset has to be reset to 0, since it was + calculated with the old base-time in mind. + Only FLUSH_STOP events coming from the active pad are looked at. + Signed-off-by: Carlos Rafael Giani + +2015-03-28 16:46:32 +0100 Carlos Rafael Giani + + * plugins/elements/gstconcat.c: + concat: Forward FLUSH_START and FLUSH_STOP events + Without this, seeking deadlocks if performed while the pipeline is paused. + Only flush events coming from the active pad are forwarded. + https://bugzilla.gnome.org/show_bug.cgi?id=745366 + +2015-06-09 14:28:30 +0200 Stefan Sauer + + * Makefile.am: + cruft: add the obsolete tmpl dir to cruft-dirs + +2015-06-09 11:30:10 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From d9a3353 to 6015d26 + +2015-06-09 11:01:53 +0200 Edward Hervey + + * plugins/elements/gstfilesink.c: + filesink: Fix fsync/_commit usage + _MSC_VER will only be defined when building *on* windows and not just + *for* windows. Instead, use the G_OS_WIN32 define + +2015-06-09 10:59:42 +0200 Sebastian Dröge + + * configure.ac: + * libs/gst/helpers/gst-ptp-helper.c: + ptp: Check for the actual API we use instead of just looking for __APPLE__ + Should fix the build on FreeBSD, DragonFly and other BSDs. + https://bugzilla.gnome.org/show_bug.cgi?id=750530 + +2015-06-08 17:10:56 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Use the new GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC flag + https://bugzilla.gnome.org/show_bug.cgi?id=750574 + +2015-06-08 17:04:55 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Make the clock a wrapper clock around an internal clock + The internal clock is only used for slaving against the remote clock, while + the user-facing GstClock can be additionally slaved to another clock if + desired. By default, if no master clock is set, this has exactly the same + behaviour as before. If a master clock is set (which was not allowed before), + the user-facing clock is reporting the remote clock as internal time and + slaves this to the master clock. + This also removes the weirdness that the internal time of the netclientclock + was always the system clock time, and not the remote clock time. + https://bugzilla.gnome.org/show_bug.cgi?id=750574 + +2015-06-08 23:07:40 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From d37af32 to d9a3353 + +2015-06-08 20:00:47 +0100 Tim-Philipp Müller + + * tests/check/elements/fakesink.c: + tests: fakesink: fix string leak in unit test + +2015-06-09 00:52:34 +1000 Jan Schmidt + + * plugins/elements/gstfilesink.c: + filesink: Fix Windows build by using _commit instead of fsync. + +2015-06-08 12:22:56 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptp: Make sure to always initialize the variables we put into the statistics structure later + CID 1304676, 1304677, 1304678, 1304679. + +2015-06-08 12:02:39 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp: Ensure that not too much is read from or written to struct ifreq.ifr_name + +2015-06-08 19:33:03 +1000 Jan Schmidt + + * libs/gst/base/gstbasetransform.h: + basetransform: Add Since markers for new vfuncs + Add Since: 1.6 markers for the new submit_input_buffer() and + generate_output() vfuncs + +2015-05-23 01:08:29 +1000 Jan Schmidt + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/test_transform.c: + * tests/check/libs/transform2.c: + basetransform: Split input buffer processing from output generation + Allow for sub-classes which want to collate incoming buffers or + split them into multiple output buffers by separating the input + buffer submission from output buffer generation and allowing + for looping of one of the phases depending on pull or push mode + operation. + https://bugzilla.gnome.org/show_bug.cgi?id=750033 + +2015-04-16 10:32:02 +1000 Jan Schmidt + + * gst/gstbuffer.h: + * plugins/elements/gstfilesink.c: + Add GST_BUFFER_FLAG_SYNC_AFTER flag, and implement in filesink. + Makes it possible to get filesink to fsync() after rendering + a buffer. + +2015-06-08 10:46:24 +0200 Руслан Ижбулатов + + * libs/gst/net/gstptpclock.c: + ptp: Fix build on Windows, and in general the GI build when PTP support was not available + It's not going to work on Windows still, the helper process needs to be + ported. + +2015-06-07 23:05:53 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 21ba2e5 to d37af32 + +2015-06-07 17:31:50 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From c408583 to 21ba2e5 + +2015-06-07 16:58:40 +0200 Stefan Sauer + + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + docs: remove variables that we define in the snippet from common + This is syncing our Makefile.am with upstream gtkdoc. + +2015-06-07 17:16:06 +0200 Stefan Sauer + + * autogen.sh: + * common: + Automatic update of common submodule + From d676993 to c408583 + +2015-06-07 16:44:26 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +2015-06-07 10:52:33 +0200 Sebastian Dröge + + * libs/gst/net/gstntppacket.c: + netclientclock: The NTP poll interval is a signed int8, not unsigned + +=== release 1.5.1 === + +2015-06-07 09:41:28 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.5.1 + +2015-06-07 09:33:52 +0200 Sebastian Dröge + + * po/cs.po: + * po/de.po: + * po/fr.po: + * po/tr.po: + po: Update translations + +2015-06-07 09:32:39 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Add Since marker to the docs for gst_ntp_clock_new() + +2015-06-07 09:32:12 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2015-06-07 09:08:35 +0200 Sebastian Dröge + + * tests/check/gst/gstmemory.c: + memory: Fix compiler warnings in unit test + gst/gstmemory.c:570:38: error: implicit conversion from enumeration type 'GstMapFlags' to different enumeration + type 'GstLockFlags' [-Werror,-Wenum-conversion] + fail_unless (gst_memory_lock (mem, GST_MAP_WRITE)); + ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~ + +2015-06-07 08:59:23 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptpclock: Use the current path delay for calculation the local/remote clock times + The mean might currently be changing, and the current path delay is the + closest we can get to the actual delay around the current SYNC message. + +2015-06-06 23:05:32 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Add some copyright stuff + +2015-06-06 21:43:05 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstntppacket.c: + * libs/gst/net/gstntppacket.h: + * win32/common/libgstnet.def: + netclientclock: Add NTPv4 support + This uses all of the netclientclock code, except for the generation and + parsing of packets. Unfortunately some code duplication was necessary + because GstNetTimePacket is public API and couldn't be extended easily + to support NTPv4 packets without breaking API/ABI. + +2015-06-06 20:39:47 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Preparation for NTPv4 support + We extend our calculations to work with local send time, remote receive time, + remote send time and local receive time. For the netclientclock protocol, + remote receive and send time are assumed to be the same value. + For the results, this modified calculation makes absolutely no difference + unless the two remote times are different. + +2015-06-06 19:01:06 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock. Fix last commit + Apparently I failed at git add -i. + +2015-06-06 18:42:18 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Make gst_net_client_clock_new() a thing wrapper around g_object_new() + Bindings will like this, and also it fixes a FIXME comment. + +2015-06-06 14:34:39 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptpclock: Use #define everywhere instead of G_N_ELEMENTS() + +2015-06-06 14:31:16 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + netclientclock: Filter RTTs based on the median of the last RTTs before considering them at all + This improves accuracy on wifi or similar networks, where the RTT can go very + high up for a single observation every now and then. Without filtering them + away completely, they would still still modify the average RTT, and thus all + clock estimations. + +2015-06-06 14:19:21 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptpclock: Use a system clock for the time observations instead of gst_util_get_timestamp() + They don't necessarily use the same underlying clocks (e.g. on Windows), or + might be configured to a different clock type (monotonic vs. real time clock). + We need the values a clean system clock returns, as those are the values used + by the internal clocks. + +2015-06-06 12:35:58 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptpclock: Fix documentation a bit + +2015-06-05 19:35:29 +0100 Tim-Philipp Müller + + * tests/check/elements/fakesink.c: + tests: fakesink: test notify::last-message and deep-notify::last-message + deep-notify::last-message seems to cause some problems, so disable for now. + https://bugzilla.gnome.org/show_bug.cgi?id=681642 + +2015-06-05 10:02:04 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Post an error if we can't typefind the data until EOS + https://bugzilla.gnome.org/show_bug.cgi?id=750439 + +2015-06-04 19:05:44 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp-helper: Make sure to use g_poll() for the main context + The modified main context from https://bugzilla.gnome.org/show_bug.cgi?id=741054 + somehow calls setugid(), which abort()s setuid root applications on OSX. + +2015-06-04 18:32:14 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp-helper: Make sure that we are running setuid root if configured that way + +2015-06-04 18:00:50 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp-helper: Fix interface listing and MAC retrieval on OSX + +2015-06-03 19:04:15 +0300 Vivia Nikolaidou + + * tools/gst-indent: + gst-indent: Add support for gindent as executable name + gst-indent used to support gnuindent and indent as executable names. + However, on OSX one can "brew install gnu-indent" and then the + executable name will be gindent. Added support for that. + https://bugzilla.gnome.org/show_bug.cgi?id=750351 + +2015-06-03 16:42:57 +0100 Luis de Bethencourt + + * libs/gst/helpers/.gitignore: + gitignore: add libs/gst/helpers/gst-ptp-helper + +2015-06-03 16:34:58 +0100 Luis de Bethencourt + + * libs/gst/helpers/Makefile.am: + ptp: ignore permission errors in Makefile + To satisfy the buildslaves ignore permission errors in chown, chmod and setcap + +2015-06-03 17:06:09 +0200 Sebastian Dröge + + * libs/gst/helpers/gst-ptp-helper.c: + ptp: Don't use SIOCGIFHWADDR on Apple + Just #ifdef the code for now, this should be implemented around + IOKit later instead of using ioctls. + +2015-06-03 16:28:44 +0200 Philippe Normand + + * libs/gst/helpers/Makefile.am: + build: make install-exec-hooks depend on install-helpersPROGRAMS + To avoid race conditions where make would try to change ownership and + permissions of the not-yet-installed ptp helper. + +2015-06-03 16:08:43 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptp: Fix debug output to print the difference instead of absolute values + +2015-06-03 15:22:31 +0200 Wim Taymans + + * libs/gst/net/gstptpclock.c: + ptpclock: fix compilation + Don't put code between declarations. + Fix use of uninitialized variables + +2015-06-03 11:04:48 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptp: Add median based pre-filtering of delays + If the delay measurement is too far away from the median of the window of last + delay measurements, we discard it. This increases accuracy on wifi a lot. + https://bugzilla.gnome.org/show_bug.cgi?id=749391 + +2015-06-02 15:24:06 +0200 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptp: Add #define to only use SYNC messages for which we can send DELAY_REQ + https://bugzilla.gnome.org/show_bug.cgi?id=749391 + +2015-05-15 16:58:51 +0300 Sebastian Dröge + + * libs/gst/net/gstptpclock.c: + ptp: Add #defines to enable/disable improvements for unreliable networks + We should do some more measurements with all these and check how much sense + they make for PTP. Also enabling them means not following IEEE1588-2008 by the + letter anymore. + https://bugzilla.gnome.org/show_bug.cgi?id=749391 + +2015-05-14 12:18:25 +0200 Sebastian Dröge + + * configure.ac: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/helpers/Makefile.am: + * libs/gst/helpers/gst-ptp-helper.c: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstptp_private.h: + * libs/gst/net/gstptpclock.c: + * libs/gst/net/gstptpclock.h: + * libs/gst/net/net.h: + * tests/examples/Makefile.am: + * tests/examples/ptp/.gitignore: + * tests/examples/ptp/Makefile.am: + * tests/examples/ptp/ptp-print-times.c: + * win32/common/libgstnet.def: + ptp: Initial implementation of a PTP clock + GstPtpClock implements a PTP (IEEE1588:2008) ordinary clock in + slave-only mode, that allows a GStreamer pipeline to synchronize + to a PTP network clock in some specific domain. + The PTP subsystem can be initialized with gst_ptp_init(), which then + starts a helper process to do the actual communication via the PTP + ports. This is required as PTP listens on ports < 1024 and thus + requires special privileges. Once this helper process is started, the + main process will synchronize to all PTP domains that are detected on + the selected interfaces. + gst_ptp_clock_new() then allows to create a GstClock that provides the + PTP time from a master clock inside a specific PTP domain. This clock + will only return valid timestamps once the timestamps in the PTP domain + are known. To check this, the GstPtpClock::internal-clock property and + the related notify::clock signal can be used. Once the internal clock + is not NULL, the PTP domain's time is known. Alternatively you can wait + for this with gst_ptp_clock_wait_ready(). + To gather statistics about the PTP clock synchronization, + gst_ptp_statistics_callback_add() can be used. This gives the + application the possibility to collect all kinds of statistics + from the clock synchronization. + https://bugzilla.gnome.org/show_bug.cgi?id=749391 + +2015-06-03 13:16:15 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + clock: Add GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC and related API + gst_clock_wait_for_sync(), gst_clock_is_synced() and gst_clock_set_synced() + plus a signal to asynchronously wait for the clock to be synced. + This can be used by clocks to signal that they need initial synchronization + before they can report any time, and that this synchronization can also get + completely lost at some point. Network clocks, like the GStreamer + netclientclock, NTP or PTP clocks are examples for clocks where this is useful + to have as they can't report any time at all before they're synced. + https://bugzilla.gnome.org/show_bug.cgi?id=749391 + +2015-06-03 18:03:36 +1000 Matthew Waters + + * gst/gstallocator.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: provide a mem_unmap function that takes the flags to unmap + There are gstmemory's available that operate in two memory domains + and need to ensure consistent access between these domains. + Imagine a scenario where e.g. the GLMemory is mapped twice in both + the GPU and the CPU domain. On unmap or a subsequent map, it would + like to ensure that the most recent data is available in the memory + domain requested. Either by flushing the writes and/or initiating a + DMA transfer. Without knowing which domain is being unmapped, the + memory does not know where the most recent data is to transfer to + the other memory domain. + Note: this still does not allow downgrading a memory map. + https://bugzilla.gnome.org/show_bug.cgi?id=750319 + +2015-06-02 16:14:50 +1000 Matthew Waters + + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: gst_memory_share may fail to exclusively lock the parent memory + Now that locking exclusively dows not always succeed, we need to signal + the failure case from gst_memory_init. + Rather than introducing an API or funcionality change to gst_memory_init, + workaround by checking exclusivity in the calling code. + https://bugzilla.gnome.org/show_bug.cgi?id=750172 + +2015-06-02 00:23:37 +1000 Matthew Waters + + * gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + buffer: locking memory exclusively may fail + Attempt to return a copy of the memory instead. + https://bugzilla.gnome.org/show_bug.cgi?id=750172 + +2015-05-31 21:25:23 +1000 Matthew Waters + + * gst/gstminiobject.c: + * tests/check/gst/gstmemory.c: + miniobject: disallow a double write/exclusive lock + gst_memory_lock (mem, WRITE | EXCLUSIVE); + gst_memory_lock (mem, WRITE | EXCLUSIVE); + Succeeds when the part-miniobject.txt design doc suggests that this should fail: + "A gst_mini_object_lock() can fail when a WRITE lock is requested and + the exclusive counter is > 1. Indeed a GstMiniObject object with an + exclusive counter 1 is locked EXCLUSIVELY by at least 2 objects and is + therefore not writable." + https://bugzilla.gnome.org/show_bug.cgi?id=750172 + +2015-06-02 20:32:35 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + uri: match return type of get_uri_type() implementation to declaration + https://bugzilla.gnome.org/show_bug.cgi?id=750292 + +2015-06-03 00:12:36 +1000 Jan Schmidt + + * gst/gstbuffer.c: + gstbuffer: Add a note about metas needing to be copied last + +2015-05-27 22:23:00 +1000 Jan Schmidt + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstvalue: Implement gst_value_is_subset() for flagsets + +2015-06-02 16:33:48 +0200 Edward Hervey + + * tests/check/gst/gstprotection.c: + check: Use GST_CHECK_MAIN macro + +2015-05-20 21:18:08 +0900 eunhae choi + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: release lock before posting msg + to avoid the deadlock in playbin2, + send msg after release the download buffer lock. + https://bugzilla.gnome.org/show_bug.cgi?id=749535 + +2015-05-31 20:21:42 -0300 Reynaldo H. Verdejo Pinochet + + * gst/gststructure.c: + structure: add note about missing field creation on _set() + +2015-05-30 13:01:09 +0100 Tim-Philipp Müller + + * tests/check/gst/gstcaps.c: + * tests/check/gst/gststructure.c: + tests: fix some leaks in new flagset checks + +2015-05-30 12:39:19 +0100 Tim-Philipp Müller + + * libs/gst/base/gstqueuearray.c: + queuearray: remove duplicate assignment + We've already done this earlier in the function, + and nothing has changed since we first read it. + +2015-05-27 17:22:28 +0530 Nirbheek Chauhan + + * gst/gst.c: + gst/gst.c: Add a warning about DllMain to prevent misuse + DllMain should not be relied on for anything except storing the DLL handle. + It should also not be defined for static builds, but doing so is not + straightforward and is mostly harmless, so let's just add a comment about that + for now. + +2015-05-27 13:54:25 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Improve debug output a bit + +2015-05-26 14:46:16 +0100 Luis de Bethencourt + + * docs/design/draft-klass.txt: + docs: fix typo in draft-klass.txt + +2015-05-26 14:03:25 +0100 Luis de Bethencourt + + * docs/code-reviews/README: + * docs/code-reviews/gstbin.c-1.41: + code-reviews: remove obsolete code reviews + This obsolete folder hasn't been touched since 2001 and has no purpose. It + confuses new developers. + +2015-05-25 21:02:28 +1000 Matthew Waters + + * libs/gst/base/gstbasesink.c: + basesink: use the slightly more correct take_sample for last-sample + gst_value_take_buffer() and gst_value_take_sample() both resolve to + g_value_take_boxed(). Use the method with the correct name if we + ever change that. + +2015-05-25 16:23:33 +1000 Jan Schmidt + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + * tests/check/gst/capslist.h: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstvalue.c: + * win32/common/libgstreamer.def: + gstvalue: Add GstFlagSet type + GstFlagSet is a new type designed for negotiating sets + of boolean capabilities flags, consisting of a 32-bit + flags bitfield and 32-bit mask field. The mask field + indicates which of the flags bits an element needs to have + as specific values, and which it doesn't care about. + This allows efficient negotiation of arrays of boolean + capabilities. + The standard serialisation format is FLAGS:MASK, with + flags and mask fields expressed in hexadecimal, however + GstFlagSet has a gst_register_flagset() function, which + associates a new GstFlagSet derived type with an existing + GFlags gtype. When serializing a GstFlagSet with an + associated set of GFlags, it also serializes a human-readable + form of the flags for easier debugging. + It is possible to parse a GFlags style serialisation of a + flagset, without the hex portion on the front. ie, + +flag1/flag2/flag3+flag4, to indicate that + flag1 & flag4 must be set, and flag2/flag3 must be unset, + and any other flags are don't-care. + https://bugzilla.gnome.org/show_bug.cgi?id=746373 + +2015-05-20 20:19:29 +0200 Thibault Saunier + + * gst/gstvalue.c: + gstvalue: Add a comparision function for GstStructures + +2015-05-19 14:34:04 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + net: keep GCancellable fd around instead of re-creating it constantly + Just create the cancellable fd once and keep it around instead + of creating/closing it for every single packet. Since we spend + most time waiting for packets, an fd is alloced and in use pretty + much all the time anyway. + +2015-05-18 12:52:00 +0100 Tim-Philipp Müller + + * plugins/elements/gstfdsrc.c: + Revert "doc: Workaround gtkdoc issue" + This reverts commit 460a7bf68292d057c77e84d1ea86b8e73fc081f3. + This should be fixed by the gtk-doc 1.23 release. + cannot contain : + http://www.docbook.org/tdg/en/html/para.html + http://www.docbook.org/tdg/en/html/refsect2.html + +2015-05-11 10:52:23 +0200 Wim Taymans + + * plugins/elements/gstsparsefile.c: + sparsefile: small cleanup + The error path unrefs file->file so make sure we only go there when + there is a non-NULL file->file. + +2015-05-16 23:29:03 -0400 Nicolas Dufresne + + * plugins/elements/gstfdsrc.c: + doc: Workaround gtkdoc issue + With gtkdoc 1.22, the XML generator fails when a itemizedlist is + followed by a refsect2. Workaround the issue by wrapping the refsect2 + into para. + +2015-05-13 13:28:05 -0300 Reynaldo H. Verdejo Pinochet + + * docs/design/part-negotiation.txt: + docs/design/part-negotiation.txt: minor corrections + +2015-05-16 12:57:12 +0200 Thibault Saunier + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + timedvaluecontrolsource: Check that the only iter is the end iter in the GSequence + Previous patch was assuming that if the returned iter was the last iter + the GSequence was empty, which is obviously wrong. + +2015-05-16 11:17:40 +0200 Thibault Saunier + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + timedvaluecontrolsource: Fix removing all keyframes, and adding one back + We were segfaulting because g_sequence_search was returning the iter_end, + and that iterator does not contain anything and thus should not be used + directly + +2015-05-15 20:44:08 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesrc.c: + fakesrc: fix property description + We're enterprise now folks. + +2015-05-15 14:57:14 +0100 Vincent Penquerc'h + + * gst/gstpad.c: + pad: bump chain function call logs from LOG to DEBUG + They're really useful compared to other LOG stuff in there, so + there is value is including them and not the rest. + +2015-05-15 13:43:12 +0200 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/check/gst/gstobject.c: + * win32/common/libgstreamer.def: + gstobject: add gst_object_has_as_ancestor and deprecate previous function + The old gst_object_has_ancestor will call the new code. This establishes the + symetry with the new gst_object_has_as_parent. + API: gst_object_has_as_ancestor() + +2015-05-15 08:05:50 +0200 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/check/gst/gstobject.c: + * win32/common/libgstreamer.def: + gstobject: rename gst_object_has_parent to gst_object_has_as_parent + This avoid confusion with a potential punction that check if a gstobject has-a + parent. + API: gst_object_has_as_parent() + +2015-05-14 15:49:43 +0800 Jian + + * libs/gst/base/gstbasesink.c: + basesink: Fix QoS/lateness checking if subclass implements prepare/prepare_list vfuncs + In basesink functions gst_base_sink_chain_unlocked(), below code is used to + checking if buffer is late before doing prepare call to save some effort: + if (syncable && do_sync) + late = + gst_base_sink_is_too_late (basesink, obj, rstart, rstop, + GST_CLOCK_EARLY, 0, FALSE); + if (G_UNLIKELY (late)) + goto dropped; + But this code has problem, it should calculate jitter based on current media + clock, rather than just passing 0. I found it will drop all the frames when + rewind in slow speed, such as -2X. + https://bugzilla.gnome.org/show_bug.cgi?id=749258 + +2015-05-11 17:14:50 +0200 Víctor Manuel Jáquez Leal + + * plugins/elements/gstfdsrc.c: + fdsrc: docs: fix and update documentation + Update example to use gst-launch-1.0 and fix a paragraph. + https://bugzilla.gnome.org/show_bug.cgi?id=749233 + +2015-05-09 11:53:49 +0100 Tim-Philipp Müller + + * Makefile.am: + Add removed example directories to CRUFT_DIRS + +2015-05-08 14:08:42 +0100 Tim-Philipp Müller + + * gst/gstparse.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gsttee.c: + docs: gst-launch -> gst-launch-1.0 in example pipelines + And some small example pipeline fix-ups. + +2015-05-09 22:10:30 -0300 Reynaldo H. Verdejo Pinochet + + * docs/design/part-conventions.txt: + docs/design/part-conventions.txt: minor corrections + +2015-05-09 22:04:52 -0300 Reynaldo H. Verdejo Pinochet + + * docs/design/part-context.txt: + docs/design/part-context.txt: minor corrections + +2015-05-09 22:01:04 -0300 Reynaldo H. Verdejo Pinochet + + * docs/design/part-clocks.txt: + docs/design/part-clocks.txt: minor corrections + +2015-05-02 17:16:38 +0100 Tim-Philipp Müller + + * docs/manual/appendix-porting.xml: + * docs/random/porting-to-1.0.txt: + docs: update porting guides to mention new device probing API + +2015-05-01 20:37:18 -0300 Reynaldo H. Verdejo Pinochet + + * docs/design/part-states.txt: + docs/design/part-states.txt: minor corrections + +2015-05-01 18:32:26 +0900 Jimmy Ohn + + * gst/gstevent.h: + event: remove duplicated include + https://bugzilla.gnome.org/show_bug.cgi?id=748739 + +2015-04-28 19:59:31 +0100 Tim-Philipp Müller + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/launch/.gitignore: + * tests/examples/launch/Makefile.am: + * tests/examples/launch/mp3parselaunch.c: + * tests/examples/metadata/.gitignore: + * tests/examples/metadata/Makefile.am: + * tests/examples/metadata/read-metadata.c: + * tests/examples/queue/.gitignore: + * tests/examples/queue/Makefile.am: + * tests/examples/queue/queue.c: + * tests/examples/typefind/.gitignore: + * tests/examples/typefind/Makefile.am: + * tests/examples/typefind/typefind.c: + tests: remove some pointless ancient code examples + +2015-04-28 17:54:51 +0300 Ilya Konstantinov + + * libs/gst/base/gstbaseparse.c: + baseparse: fix GST_BASE_PARSE_FLAG_LOST_SYNC + Since frame->priv->discont was cleared earlier, + GST_BASE_PARSE_FLAG_LOST_SYNC was never being set. + Take the chance to refactor the frame creation a bit to + organize the flags setting and reset. + https://bugzilla.gnome.org/show_bug.cgi?id=738237 + +2015-03-09 19:31:36 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: respect DISCONT flag on buffers + Drain the parser when a DISCONT buffer is received and then mark + the next buffer to be pushed as a DISCONT one + https://bugzilla.gnome.org/show_bug.cgi?id=745927 + +2015-04-28 15:50:46 +0200 Sebastian Dröge + + * gst/gsttaglist.c: + taglist: Copy the tag scope too when copying tag lists + +2015-04-20 20:02:51 -0400 Olivier Crête + + * plugins/elements/gstidentity.c: + identity: Also synchronize GAP events in sync=1 + https://bugzilla.gnome.org/show_bug.cgi?id=601853 + +2015-04-20 19:31:37 -0400 Olivier Crête + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: With sync=true, don't pre-roll + To act like a real live element, block the streaming when paused, and + return NO_PREROLL. + https://bugzilla.gnome.org/show_bug.cgi?id=601853 + +2015-04-20 19:24:45 -0400 Olivier Crête + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: Take upstream latency into account for sync=1 + https://bugzilla.gnome.org/show_bug.cgi?id=601853 + +2015-04-20 19:07:27 -0400 Olivier Crête + + * plugins/elements/gstidentity.c: + identity: Handle PTS and DTS separately + https://bugzilla.gnome.org/show_bug.cgi?id=601853 + +2015-04-26 17:05:48 +0100 Tim-Philipp Müller + + * .gitignore: + * Android.mk: + * gst/Makefile.am: + * gst/parse/Makefile.am: + * libs/Makefile.am: + * libs/gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/helpers/Makefile.am: + * libs/gst/net/Makefile.am: + * plugins/Makefile.am: + * plugins/elements/Makefile.am: + * tests/examples/controller/Makefile.am: + * tools/Makefile.am: + Remove obsolete Android build cruft + This is not needed any longer. + +2015-04-24 16:51:24 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Only try to push the first EOS received + Subsequent EOS will push on the source pad that already received + EOS and that will make the event function return FALSE. It needs + only to push the first one and only return TRUE for the subsequent + ones. + +2015-04-24 15:19:26 +0100 Tim-Philipp Müller + + * tests/check/gst/gstprintf.c: + tests: printf: add unit test for %% + https://bugzilla.gnome.org/show_bug.cgi?id=748414 + +2015-04-24 15:16:24 +0100 Tim-Philipp Müller + + * gst/printf/vasnprintf.c: + printf: fix invalid memory access in case of %% + https://bugzilla.gnome.org/show_bug.cgi?id=748414 + +2015-04-23 15:55:44 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: define GST_CHECK_TEST_ENVIRONMENT_BEACON + +2015-04-23 15:54:08 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: optionally check env var for us to make sure test env is set up + If GST_CHECK_TEST_ENVIRONMENT_BEACON is defined, check if the + environment variable it is defined to is set up at the start + of each test. + https://bugzilla.gnome.org//show_bug.cgi?id=747624 + +2015-04-23 09:06:42 +0900 Changbok Chea + + * libs/gst/base/gstbasesrc.c: + basesrc: Remove unused assignment in perform_seek() + https://bugzilla.gnome.org/show_bug.cgi?id=748345 + +2015-04-22 11:44:00 +0530 Prashant Gotarne + + * tests/check/gst/gstmemory.c: + test: memory: Added test to verify the allocation params + New test added to verify the allocation params for the memory + https://bugzilla.gnome.org/show_bug.cgi?id=748277 + +2015-04-22 11:04:06 -0600 Jason Litzinger + + * tests/check/gst/gstinfo.c: + tests: info: add test case to reproduce infinite loop + gst_debug_unset_threshold_for_name() used to go into an + infinite loop when there was more than one category in + the list. This test captures the problem by failing + via timeout. + https://bugzilla.gnome.org/show_bug.cgi?id=748321 + +2015-04-22 12:03:33 -0600 Jason Litzinger + + * gst/gstinfo.c: + gstinfo: fix infinite loop in gst_debug_unset_threshold_for_name() + Ensure iterator is advanced. The current list iteration code only + advances the iterator (walk) if a match is found, which results + in an infinite loop when more than one entry exists in the list. + https://bugzilla.gnome.org/show_bug.cgi?id=748321 + +2015-04-22 10:14:53 +0100 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: create-uninstalled-setup: miscellaneous fixes + Error out if required build tools (flex, bison, pkg-config) + are not present, instead of printing a message and then + continuing. + Check out submodules when fetching the repositories, so + they're already there and ready later. + Remove some 0.10 cruft. + +2015-04-22 09:59:24 +0100 Tim-Philipp Müller + + * .gitignore: + Add INSTALL to .gitignore + +2015-04-22 09:56:55 +0100 Tim-Philipp Müller + + * tests/check/generic/states.c: + tests: error out if test environment is not actually set up properly + https://bugzilla.gnome.org//show_bug.cgi?id=747624 + +2015-04-22 09:52:58 +0100 Tim-Philipp Müller + + * configure.ac: + configure: can use AM_SILENT_RULES unconditionally now + https://autotools.io/automake/silent.html + +2015-04-22 09:47:39 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump automake requirement to 1.14 and autoconf to 2.69 + This is only required for builds from git, people can still + build tarballs if they only have older autotools. + https://bugzilla.gnome.org//show_bug.cgi?id=747624 + +2015-04-22 10:32:57 +0200 Sebastian Dröge + + * INSTALL: + Remove INSTALL file + autotools automatically generate this, and when using different versions + for autogen.sh there will always be changes to a file tracked by git. + +2015-04-20 22:07:34 +0200 Thibault Saunier + + * scripts/gst-uninstalled: + gstreamer-uninstalled: Update path to the GstValidate scenarios + +2015-04-20 09:23:43 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Check return value of meta transform function in gst_buffer_copy_into() + ... by printing some debug output whenever copying a GstMeta fails. + https://bugzilla.gnome.org/show_bug.cgi?id=748119 + +2015-04-18 12:31:02 +0100 Tim-Philipp Müller + + * gst/gstevent.h: + event: fix header formatting + +2015-04-18 12:28:15 +0100 Tim-Philipp Müller + + * tests/check/gst/gstprotection.c: + tests: protection: fix leak in unit test + +2015-04-18 12:27:46 +0100 Tim-Philipp Müller + + * gst/gst.h: + gst.h: include the new gstprotection.h header + https://bugzilla.gnome.org/show_bug.cgi?id=705991 + +2015-04-15 15:33:31 +0100 Alex Ashley + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gstprotection.c: + * gst/gstprotection.h: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstprotection.c: + * win32/common/libgstreamer.def: + protection: add GstProtectionMeta to support protected content + In order to support some types of protected streams (such as those + protected using DASH Common Encryption) some per-buffer information + needs to be passed between elements. + This commit adds a GstMeta type called GstProtectionMeta that allows + protection specific information to be added to a GstBuffer. An example + of its usage is qtdemux providing information to each output sample + that enables a downstream element to decrypt it. + This commit adds a utility function to select a supported protection + system from the installed Decryption elements found in the registry. + The gst_protection_select_system function that takes an array of + identifiers and searches the registry for a element of klass Decryptor that + supports one or more of the supplied identifiers. If multiple elements + are found, the one with the highest rank is selected. + This commit adds a unit test for the gst_protection_select_system + function that adds a fake Decryptor element to the registry and then + checks that it can correctly be selected by the utility function. + This commit adds a unit test for GstProtectionMeta that creates + GstProtectionMeta and adds & removes it from a buffer and performs some + simple reference count checks. + API: gst_buffer_add_protection_meta() + API: gst_buffer_get_protection_meta() + API: gst_protection_select_system() + API: gst_protection_meta_api_get_type() + API: gst_protection_meta_get_info() + https://bugzilla.gnome.org/show_bug.cgi?id=705991 + +2015-03-16 12:35:27 +0000 Alex Ashley + + * gst/gstevent.c: + * gst/gstevent.h: + * tests/check/gst/gstevent.c: + * win32/common/libgstreamer.def: + event: add new GST_EVENT_PROTECTION + In order for a decrypter element to decrypt media protected using a + specific protection system, it first needs all the protection system + specific information necessary (E.g. information on how to acquire + the decryption keys) for that stream. + The GST_EVENT_PROTECTION defined in this commit enables this information + to be passed from elements that extract it (e.g. qtdemux, dashdemux) to + elements that use it (E.g. a decrypter element). + API: GST_EVENT_PROTECTION + API: gst_event_new_protection() + API: gst_event_parse_protection() + https://bugzilla.gnome.org/show_bug.cgi?id=705991 + +2015-04-18 11:42:21 +0100 Tim-Philipp Müller + + * plugins/elements/gsttee.c: + tee: fix use of possibly-freed pad in debug statement + The gst_object_unref() in the block above may be dropping + the last ref to the pad and free the pad. Set pad pointer + to NULL here, so that we don't accidentally use a + possibly-freed pad pointer in the debug log statements + further below, and also use the tee element as log object + since that's more appropriate anyway. + Fixes valgrind warnings and crashes in tee test_stress + unit test when debug logging is enabled. + +2015-04-18 12:00:13 +0100 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: info: fix unit test when run with GST_DEBUG=*:9 + Only save the messages we're interested in and expecting. + When run with *:9 we might get additional TRACE level + messages from other categories and then we don't end up + with the number of messages we expect. + +2015-04-18 11:25:16 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpad.c: + tests: pad: fix buffer leak in new blocking_with_probe_type_idle test + +2015-04-18 11:11:26 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpad.c: + tests: pad: fix invalid memory access in debug log message + The string we put in the buffer is not NUL-terminated, so + don't try to print that via %s in a debug log message. + +2015-04-17 15:19:07 +0200 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: on OSX, MKDIR_P is install-sh -c -d + So we need to call it before cding to the bin directory. + +2015-04-17 13:02:12 +0200 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: install -D isn't portable, use $(MKDIR_P) instead. + +2015-04-14 10:47:20 -0300 Thiago Santos + + * tests/check/gst/gstpad.c: + tests: pad: test that idle probe will block + This tests add an idle probe on an idle pad from a separate thread + so that the callback is called immediatelly. This callback will sit + still and then we try to push a buffer on this same pad. It verifies + that the idle probe blocks data passing + https://bugzilla.gnome.org/show_bug.cgi?id=747852 + +2015-04-14 17:06:36 -0300 Thiago Santos + + * gst/gstpad.c: + pad: block data flow when idle probe is running + When idle probe runs directly from the gst_pad_add_probe() function + we need to make sure that no data flow happens as idle probe + is a blocking probe. The idle probe will prevent that any + buffer, bufferlist or serialized events and queries are not + flowing while it is running. + https://bugzilla.gnome.org/show_bug.cgi?id=747852 + +2015-04-16 13:41:20 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + docs: clarify that return value of gst_filename_to_uri() must be freed + https://bugzilla.gnome.org/show_bug.cgi?id=747104 + +2015-04-15 11:02:54 +0100 Vincent Penquerc'h + + * gst/gstbin.c: + * tests/check/generic/states.c: + bin: undo upward state changes on children when a child fails + When a bin changes states upwards, and a child fails to change, + any child that was already switched will not be reset to its + original state, leaving its state inconsistent with the bin, + which does not change state due to the failure. + If the state change was from NULL to READY, it means that deleting + this bin will cause those children to be deleted while not in + NULL state, which is a Bad Thing. For other upward changes, it + is less of a problem, as a subsequent switch back to NULL will + cause an actual downwards change on those inconsistent elements, + albeit from the "wrong" state. + We now reset state to the original one when a child fails. + Includes unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=747610 + +2015-04-15 14:45:21 +0200 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: use $(INSTALL) to ... install the helper. + As it will create the folders and set permissions appropriately, + better than doing it manually. + +2015-04-15 13:02:36 +0200 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: Fix Makefile.am to install the completion-helper correctly. + + The program is installed at install-exec time, we thus need + to move it in install-exec-hook, not install-data-hook. + +2015-04-15 11:38:35 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasesrc.c: + Revert "basesrc: fix pool leak on allocation query error path" + This reverts commit 84fdf50b2f98951a32fa14802b62621f1105cd35. + It seems the bug was fixed independently, and the merge was + automagic, yielding two extra free calls. + +2015-04-14 13:42:55 +0900 Suhwang Kim + + * tests/check/gst/gstclock.c: + tests: clock: fix test clock name + Don't call the slave test clock "Master". + https://bugzilla.gnome.org/show_bug.cgi?id=746430 + +2015-04-14 17:47:08 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + elementfactory: add ENCRYPTOR class defines + to go with DECRYPTOR. + +2015-03-16 13:11:59 +0000 Alex Ashley + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + elementfactory: add DECRYPTOR class defines + An element that performs decryption does not naturally fit within any + of the existing element factory class types. It is useful to be able + to easily get a list of all elements that support decryption so that + a union can be computed between the protection systems that have a + supported decryptor and the allowed protection systems for a particular + stream. + This commit adds a new GST_ELEMENT_FACTORY_TYPE_DECRYPTOR and its + associated string identifier "Decryptor". It also adds + GST_ELEMENT_FACTORY_TYPE_DECRYPTOR to GST_ELEMENT_FACTORY_TYPE_DECODABLE + so that uridecodebin can auto-plug a decryption element. + https://bugzilla.gnome.org/show_bug.cgi?id=705991 + +2015-04-13 17:01:41 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefindelement: Use gst_event_unref() instead of gst_mini_object_unref() + casting + +2015-04-13 14:40:22 +0200 Guillaume Desmottes + + * plugins/elements/gsttypefindelement.c: + typefind: fix leak in gst_type_find_element_src_event() + gst_type_find_element_src_event() is supposed to consume @event but wasn't + doing so when it was handling the event itself. + https://bugzilla.gnome.org/show_bug.cgi?id=747775 + Signed-off-by: Guillaume Desmottes + +2015-04-11 20:44:02 +0900 Hyunjun Ko + + * gst/gstvalue.c: + gstvalue: reset errno before g_ascii_strtoull call + "errno" already has meaningless value before g_ascii_strtoull call. + This causes invalid error check without reset. + https://bugzilla.gnome.org/show_bug.cgi?id=747690 + +2015-04-12 13:13:32 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Only set DTS to segment.start on the first buffer if subclass did not provide PTS + Otherwise we're going to set a rather arbitrary DTS of segment.start (usually + 0) for live sources, which confuses synchronization if the source started + capturing at a later time. And it's especially wrong for raw media, for which + we should not set any DTS at all. + https://bugzilla.gnome.org/show_bug.cgi?id=747731 + +2014-09-02 17:40:28 +0300 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Run the default have-type handler after all application handlers + Otherwise the CAPS event will already be forwarded downstream and + the application has no way to intervene anymore. + https://bugzilla.gnome.org/show_bug.cgi?id=735896 + +2015-03-10 12:57:44 +1000 Duncan Palmer + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't automatically enter the buffering state when use-buffering is set. + There is no reason I can see to set mq->buffering = TRUE when + use_buffering is set; the code here also calls update_buffering(), which + will set mq->buffering = TRUE if this is warranted because of low buffer + levels. + https://bugzilla.gnome.org/show_bug.cgi?id=745937 + +2015-04-10 12:32:27 +0200 Guillaume Desmottes + + * plugins/elements/gstinputselector.c: + inputselector: fix cached buffer leak in chain function + gst_selector_pad_chain() was popping cached buffers out of the queue without + freeing those. Make sure we don't steal the GstBuffer as the cached buffer ref + has been passed to the pad chain function. + This can be reproduced by running the + validate.file.playback.switch_subtitle_track_while_paused.test5_mkv scenario + with Valgrind. + https://bugzilla.gnome.org/show_bug.cgi?id=747611 + Signed-off-by: Guillaume Desmottes + +2015-04-08 16:04:11 +0200 Edward Hervey + + * common: + * tests/check/Makefile.am: + * tests/examples/manual/Makefile.am: + tests: Use AM_TESTS_ENVIRONMENT + Needed by the new automake test runner + +2015-04-07 15:00:46 +0530 Prashant Gotarne + + * gst/gstbufferlist.c: + bufferlist: make sure list is writable before adding or removing buffers + https://bugzilla.gnome.org/show_bug.cgi?id=747439 + +2015-04-07 14:34:58 +0530 Prashant Gotarne + + * gst/gstbufferlist.c: + bufferlist: minor docs addition for gst_buffer_list_get() + Return buffer remains valid as long as list is valid + and buffer is not removed from list. + https://bugzilla.gnome.org/show_bug.cgi?id=747438 + +2015-04-07 11:38:31 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasesrc.c: + basesrc: fix pool leak on allocation query error path + It could be triggered by: + gst-launch-1.0 videotestsrc num-buffers=20 ! videcrop bottom=214748364 ! videoconvert ! autovideosink + Spotted while testing: + https://bugzilla.gnome.org/show_bug.cgi?id=743910 + +2015-04-06 18:45:37 -0700 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Forward SEGMENT_DONE events immediately + There might be no more data coming afterwards, and we just drained everything + that was left to be pushed anyway. + +2015-04-06 18:56:25 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + docs: fix cross-reference to environment variables in GstInfo + https://bugzilla.gnome.org/show_bug.cgi?id=747416 + +2015-04-06 10:18:15 +0530 Prashant Gotarne + + * gst/gstmemory.c: + memory: add check for writablity in resize + Add guard to gst_memory_resize() to make sure the + memory to be resized is actually writable. + https://bugzilla.gnome.org/show_bug.cgi?id=747392 + +2015-04-05 16:47:26 +0100 Tim-Philipp Müller + + * tests/check/elements/multiqueue.c: + tests: multiqueue: add test to make sure initial events go through without buffers + +2015-04-05 16:06:44 +0100 Tim-Philipp Müller + + * tests/check/elements/queue.c: + tests: queue: check that the initial events are sent on immediately + Add a check that makes sure stream-start, caps, and segment events + are passed on by queue without delay, i.e. even if no buffer is + sent. + +2015-04-04 18:33:18 -0700 Sebastian Dröge + + * gst/gstpad.c: + pad: Print debug output from gst_pad_link_full() if preparing linking failed + Makes it easier to find linking failures in debug logs. + +2015-04-04 19:29:51 +0100 Tim-Philipp Müller + + * gst/gstsegment.h: + segment: small docs addition + https://bugzilla.gnome.org/show_bug.cgi?id=690564 + +2015-04-04 18:18:03 +0100 Tim-Philipp Müller + + * docs/design/part-streams.txt: + * docs/design/part-synchronisation.txt: + docs: design: fix some 0.10-isms in GstSegment docs + 1) segment.accum -> segment.base + 2) Refer to GstSegment members as S.foo instead of + NS.foo, the event is now called a segment event + rather than newsegment event. + 3) There's no more abs_rate field in GstSegment, + and there never was an abs_applied_rate field. + https://bugzilla.gnome.org/show_bug.cgi?id=690564 + +2015-04-04 04:14:50 +0300 Ilya Konstantinov + + * libs/gst/base/gstbasesrc.c: + basesrc: do not leak buffer pool in error case + https://bugzilla.gnome.org/show_bug.cgi?id=747321 + +2015-04-03 19:12:48 -0400 Nicolas Dufresne + + * gst/gsturi.c: + uri: Silence a compiler warning + This is a false positive for use initialized. The variable is set and + used enclosed in the safe if condition. + +2015-04-03 16:32:16 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Add gst_segment_to_running_time_full + +2015-04-03 13:19:13 -0700 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Fix documentation, buffer pools are unreffed and not freed + +2015-04-03 20:43:15 +0100 Tim-Philipp Müller + + * INSTALL: + Update INSTALL to the automake 1.14 version + +2015-04-03 18:57:36 +0100 Tim-Philipp Müller + + * autogen.sh: + * common: + Automatic update of common submodule + From bc76a8b to c8fb372 + +2015-04-03 16:27:10 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: fix exports + +2015-03-19 10:45:56 +0000 Vincent Penquerc'h + + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * win32/common/libgstreamer.def: + segment: add gst_segment_is_equal + It beats memcmp due to the 'reserved' fields. + API: gst_segment_is_equal() + Found via, but probably not directly linked to, + https://bugzilla.gnome.org/show_bug.cgi?id=738216 + +2015-04-03 00:36:42 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + win32: add new API to exports + +2014-08-06 10:32:39 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: allow probes to remove the data item whilst returning PROBE_OK + Use case: we want to block the source pad of a leaky queue and + drop the buffer that causes the block. If we return PROBE_DROP + then the buffer gets dropped, but we get called again. If we + return PROBE_OK we can't easily drop the buffer. If we just + replace the item into the GstPadProbeInfo structure with NULL, + GStreamer will push a NULL buffer to the next element when we + unblock the pad probe. This patch ensures it doesn't do that. + https://bugzilla.gnome.org/show_bug.cgi?id=734342 + +2015-02-12 19:39:44 -0500 Olivier Crête + + * gst/gstelement.c: + element: Document when a clock is available from gst_element_get_clock() + https://bugzilla.gnome.org/show_bug.cgi?id=744442 + +2015-02-12 19:40:06 -0500 Olivier Crête + + * docs/gst/gstreamer-sections.txt: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + pipeline: Add binding friendly gst_pipeline_get_pipeline_clock() + Also skip gst_pipeline_get_clock() and gst_pipeline_set_clock() from the + bindings as they are confused with gst_element_*_clock(). + API: gst_pipeline_get_pipeline_clock() + https://bugzilla.gnome.org/show_bug.cgi?id=744442 + +2015-04-02 17:32:42 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasetransform.c: + basetransform: Add Since mark for new method + https://bugzilla.gnome.org/show_bug.cgi?id=734424 + +2015-02-20 17:50:48 +0100 Thibault Saunier + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: Add a method to let subclasses cleanly update srcpad caps + API: + gst_base_transform_update_src + https://bugzilla.gnome.org/show_bug.cgi?id=734424 + +2015-04-02 21:18:39 +0100 Tim-Philipp Müller + + * docs/pwg/advanced-scheduling.xml: + * docs/pwg/advanced-types.xml: + docs: pwg: fix missing comma and 0.10-ism in code sample + https://bugzilla.gnome.org/show_bug.cgi?id=747267 + https://bugzilla.gnome.org/show_bug.cgi?id=747266 + +2015-04-02 19:29:46 +0300 Ilya Konstantinov + + * gst/gstmemory.c: + memory: improve docs for _copy() and _share() + +2015-04-02 11:42:20 +0530 Prashant Gotarne + + * tests/check/elements/filesink.c: + test: filesink: add tests for buffers with multiple memory blocks + Update test_seeking testcase to verify the render and render_list + virtual method handle buffers and buffer list containing multiple + memory blocks correctly. + https://bugzilla.gnome.org/show_bug.cgi?id=747223 + +2015-04-02 09:44:33 +0200 Thibault Saunier + + * gst/gstelement.h: + element: Add a FIXME for 2.0 about request_new_pad VS request_pad naming + +2015-04-02 09:34:00 +0200 Thibault Saunier + + * gst/gstelement.c: + element: Fix request_new_pad introspection + Marking gst_element_request_pad as the caller of the ->request_new_pad + virtual method. + +2015-04-01 09:20:24 +0530 Prashant Gotarne + + * tests/check/elements/filesink.c: + tests: filesink: add check for render_list virtual method + GstFileSink implements the render_list virtual method to render + a list of buffers. Update the test_seeking test case to also + check the render_list method implementation. + https://bugzilla.gnome.org/show_bug.cgi?id=747100 + +2015-04-01 12:13:17 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstcaps.c: + * gst/gstdebugutils.c: + debugutils: nicer printing of caps features + Only print interesting caps features, don't + append (memory:SystemMemory) to all caps, + which makes them much more unwieldy and + harder to read. Also use internal function + to get caps features so that our printing + has no side effects on the caps. + https://bugzilla.gnome.org/show_bug.cgi?id=746809 + +2015-03-26 13:05:57 +0100 Lubosz Sarnecki + + * gst/gstdebugutils.c: + debugutils: plot caps features + https://bugzilla.gnome.org/show_bug.cgi?id=746809 + +2015-03-31 23:48:22 +0900 Wonchul Lee + + * gst/gstpad.c: + pad: Fix a typo in a docstring + https://bugzilla.gnome.org/show_bug.cgi?id=747119 + +2015-03-31 11:15:10 +0200 Edward Hervey + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Don't use g-ir-scanner cache at compile time + It pollutes user directories and we don't need to cache it + https://bugzilla.gnome.org/show_bug.cgi?id=747095 + +2015-03-28 14:45:35 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: fix outdated debug message + Buffer lists don't have groups any more in 1.0 + +2015-03-27 18:20:37 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Flush-stop starts live task in paused + The flush-stop event should not restart the task for live sources unless + the element is playing. This was breaking seeks in pause with the rtpsrc. + https://bugzilla.gnome.org/show_bug.cgi?id=635701 + +2015-03-27 16:23:40 +0000 Luis de Bethencourt + + * tests/check/elements/filesink.c: + tests: check location isn't truncated + Test covering the recent commit where location='".abc' won't get truncated + to '.ab' anymore + https://bugzilla.gnome.org/show_bug.cgi?id=688625 + +2015-03-26 17:01:06 +0000 Luis de Bethencourt + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstvalue: only unwrap string delimited with " + Don't unwrap strings that start but don't finish with a double quote. If a + string is delimited by two quotes we unescape them and any special characters + in the middle (like \" or \\). If the first character or the last character + aren't a quote we assume it's part of an unescaped string. + Moved some deserialize_string unit tests because we don't try to unwrap strings + missing that second quote anymore. + https://bugzilla.gnome.org/show_bug.cgi?id=688625 + +2015-03-27 17:16:03 +0000 Luis de Bethencourt + + * gst/parse/grammar.y: + parse: check before truncating strings + Don't truncate the last character of a string if it isn't necessary. + https://bugzilla.gnome.org/show_bug.cgi?id=688625 + +2015-03-27 10:15:16 +0100 Sebastian Dröge + + * gst/gstbus.c: + bus: Add guards against invalid arguments to set_flushing() and poll() + https://bugzilla.gnome.org/show_bug.cgi?id=746871 + +2015-03-25 10:49:08 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + * tests/check/libs/baseparse.c: + baseparse: only post 'no valid frames' error if buffers were received + Otherwise baseparse will consider empty streams to be an error while + an empty stream is a valid scenario. With this patch, errors would + only be emitted if the parser received data but wasn't able to + produce any output from it. + This change is only for push-mode operation as in pull mode an + empty file can be considered an error for the one driving the + pipeline + Includes a unit test for it + https://bugzilla.gnome.org/show_bug.cgi?id=733171 + +2015-03-19 10:36:11 +0100 Jose Antonio Santos Cadenas + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * tests/check/elements/tee.c: + tee: Add allow-not-linked property + This property avoids not linked error when all the pads are unlinked + or when there are no source pads. This is useful in dynamic pipelines + where it can happen that for a short time there are no pads at all or + all downstream pads are not linked yet. + https://bugzilla.gnome.org/show_bug.cgi?id=746436 + +2015-03-21 17:13:18 -0500 Michael Catanzaro + + * docs/gst/running.xml: + docs: Fix typos + https://bugzilla.gnome.org/show_bug.cgi?id=746585 + +2015-03-21 15:46:50 -0500 Michael Catanzaro + + * gst/gstpluginloader.c: + pluginloader: Fix typos + https://bugzilla.gnome.org/show_bug.cgi?id=746585 + +2015-03-24 16:04:16 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + output-selector: add drain handling + Release the latest buffer, if any, and then just let + the drain be pushed downstream + +2015-03-24 19:32:49 +0100 Mathieu Duponchelle + + * Makefile.am: + Revert "Fix distcheck" + This reverts commit 56dd2d89c4eac460cbc37e2a51c1dd9e792999e8. + Installing completions to a custom prefix is now fixed. + +2015-03-24 19:30:52 +0100 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: remove completion-helper on uninstall + + And add it to CLEANFILES + +2015-03-18 19:38:15 +0100 Mathieu Duponchelle + + * data/completions/gst-inspect-1.0: + * data/completions/gst-launch-1.0: + * libs/gst/helpers/gst: + completions: remove last unnamespaced symbols. + https://bugzilla.gnome.org/show_bug.cgi?id=744877 + +2015-03-18 14:44:21 +0100 Mathieu Duponchelle + + * data/completions/gst-inspect-1.0: + * data/completions/gst-launch-1.0: + completions: remove deprecated shell syntax. + https://bugzilla.gnome.org/show_bug.cgi?id=744877#c21 + +2015-03-18 14:37:11 +0100 Mathieu Duponchelle + + * data/completions/gst-inspect-1.0: + * data/completions/gst-launch-1.0: + completions: prefix shell functions with _gst + + To make it more difficult for them to conflict in the + global namespace. + https://bugzilla.gnome.org/show_bug.cgi?id=744877#c21 + +2015-03-24 13:13:29 -0400 Nicolas Dufresne + + * configure.ac: + bash-completion: Respect the prefix + Don't try and install the bash helpers outside the defined prefix. + https://bugzilla.gnome.org/show_bug.cgi?id=744877 + +2014-11-19 13:08:45 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + input-selector: Rename _activate_sinkpad to _get_active_sinkpad + Removes the now unused 'pad' parameter and renames the function + to something more appropriate. + https://bugzilla.gnome.org/show_bug.cgi?id=739620 + +2014-11-19 13:03:21 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + input-selector: Remove pad's 'active' field + This is now never read. + https://bugzilla.gnome.org/show_bug.cgi?id=739620 + +2014-11-19 12:59:12 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + input-selector: Use segment-presence for running_time check + When determining whether the running_time of a pad can be + calculated, check if the segment is in TIME format instead + of using the 'active' field. + Since the latter is set through *any* activity, it's not a + reliable indicator of segment presence. + https://bugzilla.gnome.org/show_bug.cgi?id=739620 + +2015-03-23 13:20:34 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + input-selector: Remove 'blocked' flag + With the disappearance of the 'block' signal, this + flag cannot be set to TRUE. + gst_input_selector_wait disappears as it never waits + and just returns self->flushing. + https://bugzilla.gnome.org/show_bug.cgi?id=736891 + +2015-03-23 12:12:51 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + input-selector: Remove obsolete 'block' signal + This signal blocks the input-selector with no means of unblocking + other than a state change back to READY. It seems this signal was + part of an old way of synchronously switching the selector, + together with the already-removed 'switch' signal. + Removing the signal is safe, as attempting to use it could only + end in deadlocks. Attempting to emit an unknown signal just causes + g_criticals. + https://bugzilla.gnome.org/show_bug.cgi?id=736891 + +2015-03-23 13:05:30 +0100 Jan Alexander Steffens (heftig) + + * plugins/elements/gstinputselector.c: + input-selector: Fix waiting on EOS + This apparently got broken by bc1ec4e. Since self->blocked is always + FALSE, gst_input_selector_wait never actually waits. + Using (!self->eos || self->blocked) && ... as the loop condition would + be incorrect as well, because then the other call to the function in + _chain would block until EOS, so the functions cannot be merged trivially. + Since blocking is obsolete, gst_input_selector_wait will get removed anyway. + As such, just inline the loop. + https://bugzilla.gnome.org/show_bug.cgi?id=746518 + +2015-03-20 07:23:53 -0300 Thiago Santos + + * tests/check/elements/selector.c: + tests: input-selector: new tests for EOS handling + 3 new tests: + 1) Tests that a stream that is empty (just an EOS event) + on inactive pad doesn't get through and tamper + with the active pad that still has data + 2) Tests that a stream that is shorter than the active one + (pushes EOS earlier) doesn't has its EOS pushed + 3) Tests that switching to an inactive stream that has received + EOS will make input-selector push EOS + https://bugzilla.gnome.org/show_bug.cgi?id=746518 + +2015-03-19 12:11:19 +0000 Thiago Santos + + * tests/check/elements/selector.c: + tests: selector: remove weird semicolons at the end of test functions + Even though it works, it is not needed and seems more natural + to not have semicolons at the end of function declarations + https://bugzilla.gnome.org/show_bug.cgi?id=746518 + +2014-07-17 16:33:29 +0200 Jan Alexander Steffens (heftig) + + * plugins/elements/gstqueue2.c: + queue2: Process SEEKING query + Add QUERY_SEEKING handling to queue2, so RTMP live streams become + seekable when a queue2 in download or ringbuffer mode is inserted: + rtmpsrc ! queue2 ! flvdemux + https://bugzilla.gnome.org/show_bug.cgi?id=733351 + +2015-03-21 19:37:30 +0100 Sebastian Dröge + + * libs/gst/check/libcheck/check_run.c: + check: Fix uninitialized variable compiler warning with gcc + check_run.c: In function 'sig_handler': + check_run.c:127:13: warning: 'child_sig' may be used uninitialized in this function [-Wmaybe-uninitialized] + killpg(group_pid, child_sig); + ^ + check_run.c:130:31: warning: 'idx' may be used uninitialized in this function [-Wmaybe-uninitialized] + sigaction(sig_nr, &old_action[idx], NULL); + ^ + +2015-03-21 15:19:43 +0100 Sebastian Dröge + + * libs/gst/check/libcheck/check_run.c: + check: Catch SIGTERM and SIGINT in the test runner and kill all currently running tests + Otherwise e.g. ctrl+c in the test runner exits the test runner, while the test + itself is still running in the background, uses CPU and memory and potentially + never exits (e.g. if the test ran into a deadlock or infinite loop). + The reason why we have to manually kill the actual tests is that after + forking they will be moved to their own process group, and as such are + not receiving any signals sent to the test runner anymore. This is supposed + to be done to make it easier to kill a test, which it only really does if + the test itself is forking off new processes. + This fix is not complete though. SIGKILL can't be caught at all, and error + signals like SIGSEGV, SIGFPE are currently not caught. The latter will only + happen if there is a bug in the test runner itself, and as such seem less + important. + +2015-03-19 13:51:38 +0100 Sebastian Dröge + + * plugins/elements/gstvalve.c: + valve: Don't drop non-serialized queries when the valve is dropping + Otherwise we end up dropping e.g. CAPS queries, and then upstream just + negotiates to whatever format it wants to. Once the valve is not-dropping + anymore this can easily result in negotiation failing completely. + https://bugzilla.gnome.org/show_bug.cgi?id=746448 + +2015-03-20 09:00:47 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: remove the bounds check from _to_running_time_full() + Do not do any checks for the start/stop in the new + gst_segment_to_running_time_full() method, we can let this be done by + the more capable gst_segment_clip() method. This allows us to remove the + enum of results and only return the sign of the calculated running-time. + We need to put the old clipping checks in the old + gst_segment_to_running_time() still because they work slightly + differently than the _clip methods. + See https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-03-19 17:36:36 +0100 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + segment: add option to disable clipping + Add a clip argument to gst_segment_to_running_time_full() to disable + the checks against the segment boundaries. This makes it possible to + generate an extrapolated running-time for timestamps outside of the + segment. + See https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-03-18 16:27:36 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: ref/unref new enum type in gst_init/deinit() + +2015-03-18 14:16:48 +0100 Mathieu Duponchelle + + * tests/misc/test-gstreamer-completion.sh: + * tools/gstreamer-completion: + tools: remove outdated completion script + + Remove the associated test + https://bugzilla.gnome.org/show_bug.cgi?id=744877#c21 + +2015-03-18 11:31:51 +0100 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: add helper to get negative running-time + Add a helper method to get a running-time with a little more features + such as detecting if the value was before or after the segment and + negative running-time. + API: gst_segment_to_running_time_full() + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=740575 + +2015-03-18 10:53:30 +0100 Wim Taymans + + * gst/gstsegment.c: + * tests/check/gst/gstsegment.c: + segment: fix offset handling with non 0 start + The position in the segment is relative to the start but the offset + isn't, so subtract the start from the position when setting the offset. + Add unit test for this as well. + +2015-03-18 09:36:35 +0100 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Add support for buffer lists + +2013-11-29 16:28:41 -0500 Olivier Crête + + * libs/gst/base/gstbaseparse.c: + baseparse: remove duplicate code + These are already freed by gst_base_parse_clear_queues() + https://bugzilla.gnome.org/show_bug.cgi?id=679768 + +2015-03-17 15:41:38 +0100 Sebastian Dröge + + * gst/gstpluginloader.c: + pluginloader: Fix indention + +2015-03-13 11:08:25 +0000 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: reset skip on segments and discontinuities + Large scale skip is an optimization, and thus it is safer to + stop skipping than to continue. Clear skip on segments and + discontinuities, as these are points where it is possible that + the original idea of "bytes to skip" changes. + +2015-03-15 14:19:17 +0000 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't grow queue infinitely if only one pad is linked + This was introduced by + https://bugzilla.gnome.org/show_bug.cgi?id=719893 + https://bugzilla.gnome.org/show_bug.cgi?id=722891 + but it doesn't make any sense at all and causes huge memory leaks. + https://bugzilla.gnome.org/show_bug.cgi?id=744253 + +2015-03-14 21:07:01 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: handle empty buffer list more gracefully + Don't abort, just ignore it. It's like a buffer + without memories. + +2015-03-14 17:39:39 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + adapter: minor optimisation for gst_adapter_take_buffer_list() + Try to allocate buffer list with a suitable size from the + beginning to avoid having to re-alloc the buffer list array. + +2015-03-14 17:23:03 +0000 Tim-Philipp Müller + + * tests/check/libs/adapter.c: + tests: add unit test for gst_adapter_take_buffer_list() + +2015-03-14 17:20:33 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * win32/common/libgstbase.def: + adapter: add gst_adapter_take_buffer_list() + API: gst_adapter_take_buffer_list() + +2015-03-14 16:05:57 +0000 Tim-Philipp Müller + + * tests/.gitignore: + * tests/check/elements/.gitignore: + Add new streamiddemux binaries to .gitignore + +2015-03-14 16:00:47 +0000 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.c: + collectpads: avoid multiple calls to gst_buffer_get_size() in macro + +2015-03-14 15:58:00 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + adapter: avoid multiple calls to gst_buffer_get_size() in macro + +2015-03-13 18:22:01 +0000 Ramiro Polla + + * gst/gstelement.c: + element: properly escape percent sign in documentation + +2015-03-14 13:37:09 +0000 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Use the correct enum type to fix a compiler warning + gstbuffer.c:522:58: error: implicit conversion from enumeration type 'GstBufferFlags' to + different enumeration type 'GstBufferCopyFlags' [-Werror,-Wenum-conversion] + if (!gst_buffer_copy_into (copy, (GstBuffer *) buffer, flags, 0, -1)) + ~~~~~~~~~~~~~~~~~~~~ ^~~~~ + gstbuffer.c:534:46: error: implicit conversion from enumeration type 'GstBufferCopyFlags' to + different enumeration type 'GstBufferFlags' [-Werror,-Wenum-conversion] + return gst_buffer_copy_with_flags (buffer, GST_BUFFER_COPY_ALL); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~ + ./gstbuffer.h:433:31: note: expanded from macro 'GST_BUFFER_COPY_ALL' + ...((GstBufferCopyFlags)(GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY)) + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +2015-03-14 14:06:09 +0100 Wim Taymans + + * win32/common/libgstnet.def: + defs: update defs + +2014-10-30 15:39:21 +0000 William Manley + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetcontrolmessagemeta.c: + * libs/gst/net/gstnetcontrolmessagemeta.h: + meta: Add `GstNetControlMessageMeta` + GstNetAddress can be used to store ancillary data which was received with + or is to be sent alongside the buffer data. When used with socket sinks + and sources which understand this meta it allows sending and receiving + ancillary data such as unix credentials (See `GUnixCredentialsMessage`) + and Unix file descriptions (See `GUnixFDMessage`). + This will be useful for implementing protocols which use file-descriptor + passing in payloaders/depayloaders without having to re-implement all the + socket handling code already present in elements such as multisocketsink, + etc. This, in turn, will be useful for implementing zero-copy video IPC. + This meta uses the platform independent `GSocketControlMessage` API + provided by GLib as a part of GIO. As a result this new meta does not + require any new dependencies or any conditional compliation for + portablility, although it is unlikely to do anything useful on non-UNIX + platforms. + +2015-03-14 11:57:33 +0000 Nicolas Dufresne + + * gst/gstquery.c: + allocation: Allow allocation pool without size + This allow proposing a number of buffers required even if the size + of buffer is unfixed. This is often the case for encoded formats. + +2015-03-01 13:15:40 -0500 Nicolas Dufresne + + * gst/gstbufferpool.c: + * tests/check/gst/gstbufferpool.c: + bufferpool: Don't stop the pool in set_config() + Don't stop the pool in set_config(). Instead, let the controlling + element manage it. Most of the time, when an active pool is being + configured is because the caps didn't change. + https://bugzilla.gnome.org/show_bug.cgi?id=745377 + +2015-03-13 18:53:11 +0000 Thiago Santos + + * libs/gst/base/gstbasesink.c: + basesink: drain on allocation query + Allows buffers to be reclaimed when caps is to be renegotiated so + that bufferpools can be stopped. As the allocation query is + serialized all buffers have been already drained from the pipeline, + except this last_sample one. + https://bugzilla.gnome.org/show_bug.cgi?id=682770 + +2015-03-13 18:35:14 +0000 Thiago Santos + + * libs/gst/base/gstbasesink.c: + basesink: when draining, deep copy the last buffer to unref old memory + Use gst_buffer_copy_deep() to force the copy of the underlying + memory instead of possibly doing a shallow copy of the buffer + and just referencing the memory + https://bugzilla.gnome.org/show_bug.cgi?id=745287 + +2015-03-13 18:35:01 +0000 Thiago Santos + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: + * win32/common/libgstreamer.def: + gstbuffer: add gst_buffer_copy_deep + A variant of gst_buffer_copy that forces the underlying memory + to be copied. + This is added to avoid adding an extra reference to a GstMemory + that might belong to a bufferpool that is trying to be drained. + The use case is when the buffer copying is done to release the + old buffer and all its resources. + https://bugzilla.gnome.org/show_bug.cgi?id=745287 + +2015-03-13 15:31:30 +0000 Sebastian Dröge + + * gst/gstbus.c: + bus: Use g_list_free_full() instead of manually unreffing and freeing + Also unref the messages, not the GList nodes. + +2015-03-13 13:42:46 +0000 Sebastian Dröge + + * gst/gstbus.c: + bus: Fix another case where we hold the object lock while unreffing a message + +2015-03-13 15:28:42 +0200 Vivia Nikolaidou + + * gst/gstbus.c: + bus: Unreferencing messages outside the lock + Shouldn't take the lock while unreferencing messages, because that may cause + more messages to be sent, which will try to take the lock and cause the app to + hang. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=728777 + +2015-02-23 20:27:32 +0200 Vivia Nikolaidou + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: Add gst_bin_sync_children_states() + gst_bin_sync_children_states() will iterate over all the elements of a bin and + sync their states with the state of the bin. This is useful when adding many + elements to a bin and would otherwise have to call + gst_element_sync_state_with_parent() on each and every one of them. + https://bugzilla.gnome.org/show_bug.cgi?id=745042 + +2015-02-03 16:12:32 +0100 Aurélien Zanelli + + * gst/printf/vasnprintf.c: + printf: handle unsigned modifier for long long + Otherwise, an unsigned integer will be displayed as a signed one if we + use internal print, ie HAVE_LONG_LONG_FORMAT is not defined. + https://bugzilla.gnome.org/show_bug.cgi?id=746096 + +2015-03-12 14:39:37 +0000 Sebastian Dröge + + * plugins/elements/gststreamiddemux.c: + streamiddemux: Reset pad counter after removing all pads + +2014-03-04 19:40:05 +0900 HoonHee Lee + + * configure.ac: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gststreamiddemux.c: + * plugins/elements/gststreamiddemux.h: + * tests/check/Makefile.am: + * tests/check/elements/streamiddemux.c: + * tests/examples/Makefile.am: + * tests/examples/streamiddemux/Makefile.am: + * tests/examples/streamiddemux/streamiddemux-stream.c: + streamiddemux: Add streamiddemux element + Demultiplex a stream to multiple source pads based on the stream ids from the + stream-start events. This basically reverses the behaviour of funnel. + https://bugzilla.gnome.org/show_bug.cgi?id=707605 + +2015-03-12 13:29:35 +0000 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + win32: update + +2015-03-12 13:26:59 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstprintf.c: + tests: add some basic unit tests for our printf stuff + To test new %I32 support. + https://bugzilla.gnome.org/show_bug.cgi?id=744281 + +2015-02-10 17:40:48 +0100 Matej Knopp + + * gst/printf/printf-parse.c: + printf: add support for %I32 + https://bugzilla.gnome.org/show_bug.cgi?id=744281 + +2015-03-12 13:14:52 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: move category level threshold check into log function dispatcher + Minor optimisation: check category log level earlier in the + log function dispatcher and not only in the default log + function. + https://bugzilla.gnome.org/show_bug.cgi?id=745213 + +2015-03-12 12:59:57 +0000 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Reset segment when deactivating pull mode or not running in pull mode + We use the segment format to detect if we run the streaming thread or not. + Without resetting we might believe we do so, although we only did in the past + and are now running in e.g. push mode. + https://bugzilla.gnome.org/show_bug.cgi?id=745073 + +2015-03-08 20:42:38 +0100 Michał Dębski + + * libs/gst/check/libcheck/check_msg.c: + * m4/check-checks.m4: + check: Use mkstemp instead of tempnam if possible + Using tempnam() is deprecated, this gives warning and fails the build + with -Werror. + https://bugzilla.gnome.org/show_bug.cgi?id=745858 + +2015-03-11 16:36:29 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: clean up the need_preroll variable + Based on patch from Song Bing + Don't just set the need_preroll flag to TRUE in all cases. When we + are already prerolled it needs to be set to FALSE and when we go to + READY we should not touch it. We should only set it to TRUE in other + cases, like what the code above does. + See https://bugzilla.gnome.org/show_bug.cgi?id=736655 + +2014-12-05 14:16:52 +0900 hoonhee.lee + + * plugins/elements/gstfunnel.c: + * tests/check/elements/funnel.c: + funnel: handle GAP event to forwards sticky events into downstream + If no data is coming and funnel receive GAP event, need to forwards sticky events + into downstream if it needs. + https://bugzilla.gnome.org/show_bug.cgi?id=738202 + +2015-03-10 16:42:44 +0000 Luis de Bethencourt + + * libs/gst/check/libcheck/check_run.c: + check: duplicate code branches + CID #1226446 + +2015-03-10 09:21:22 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + * tests/check/pipelines/queue-error.c: + Fix double semicolons + +2015-02-22 10:12:01 +0100 Mark Nauwelaerts + + * win32/common/libgstbase.def: + win32: update exports + +2015-02-21 20:13:04 +0100 Mark Nauwelaerts + + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + flowcombiner: add a gst_flow_combiner_update_pad_flow() method + https://bugzilla.gnome.org/show_bug.cgi?id=744572 + API: gst_flow_combiner_update_pad_flow() + +2015-02-15 20:52:10 +0100 Mark Nauwelaerts + + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + flowcombiner: add a gst_flow_combiner_reset() method + https://bugzilla.gnome.org/show_bug.cgi?id=744572 + API: gst_flow_combiner_reset() + +2015-03-06 10:59:58 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Fix typo in debug message + +2015-03-05 18:30:45 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: avoid malloc/free if log object is NULL + +2015-03-05 17:54:04 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: move __FILE__ path shortening into default log handler + Instead of always shortening the __FILE__ path, even if the + log message is not actually printed, which might happen if + the log level is activated but the category is not, only + shorten the path if we're actually going to output it and + if it looks like it needs shortening. Log handlers had no + guarantee that they would get a name instead of a path + anyway on any architecture, so it shouldn't be a problem. + https://bugzilla.gnome.org/show_bug.cgi?id=745213 + +2015-02-27 01:16:58 +1100 Peter Urbanec + + * gst/gstinfo.c: + info: shorten __FILE__ on all platforms + This is useful not only for MSVC, but also with gcc/Linux + when doing cross-compilation builds and out-of-tree builds. + https://bugzilla.gnome.org/show_bug.cgi?id=745213 + +2015-03-04 11:02:41 +0000 Vincent Penquerc'h + + * docs/design/part-latency.txt: + docs: clarify min-latency wording in part-latency.txt + https://bugzilla.gnome.org/show_bug.cgi?id=744338 + +2015-02-26 14:43:25 +0100 Marcin Kolny + + * win32/common/gstconfig.h: + win32/common/gstconfig.h: removed libxml include directive + This is a leftover from 0.10 and not needed anymore. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=745210 + +2015-03-03 12:53:13 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Signal the sinkpad thread if a flow error happened + It might still be waiting for a query to be handled, or the queue to become + empty again for the next item. Also if downstream returns FLUSHING, flush the + queue like we do in queue and multiqueue. + +2015-03-03 12:48:34 +0100 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Wake up the query function on errors from the loop function + Otherwise we might wait forever for serialized queries to be handled as the + loop function is stopped and as such we will never ever dequeue the query and + handle it. + https://bugzilla.gnome.org/show_bug.cgi?id=745319 + +2015-03-02 20:31:58 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + utils: improve warning when linking elements without common ancestor + This comes up quite a lot and it's a common mistake, so let's + try to improve the warning message a little. + +2015-02-27 00:33:27 +0530 Arun Raghavan + + * plugins/elements/gstinputselector.c: + input-selector: Drop custom latency query handling + The default latency query handler now implements this logic + +2015-02-26 15:57:20 +0100 Mathieu Duponchelle + + * scripts/gst-uninstalled: + gst-unsinstalled: Add ges-launch manuals path to MANPATH. + +2015-02-26 13:08:48 +0530 Arun Raghavan + + * gst/gstpad.c: + pad: Don't fail latency query on unlinked pads + A single unlinked pad can make the latency query fail across the + pipeline, which is probably not desirable. Instead, we return a default + anything goes value. + Perhaps we should also be emitting a gst_message_new_latency() when a + PLAYING element has one of its pads linked. + https://bugzilla.gnome.org/show_bug.cgi?id=745197 + +2014-10-22 16:43:43 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Don't emit errors on EOS if we saw GAP events + If we saw GAP events (meaning the streams is advancing) before we get + EOS, we should not post an ERROR, since it is not fatal. + https://bugzilla.gnome.org/show_bug.cgi?id=745143 + +2015-02-25 08:26:19 +0100 Edward Hervey + + * gst/gstvalue.h: + * tests/check/gst/gstinfo.c: + gstvalue: Make sure GST_FOURCC_ARGS produces printable characters + Some systems will crash if we use non-printable characters in print/debug + statements. + Make sure that GST_FOURCC_ARGS never does that + https://bugzilla.gnome.org/show_bug.cgi?id=745144 + +2015-02-25 16:11:06 +0000 Luis de Bethencourt + + * gst/gstutils.c: + gstutils: remove incorrect Fixme comment + If the checks were changed to using g_return_if_fail() the GST_DEBUG lines + about the specific failure would be lost. + +2015-02-25 16:02:39 +0000 Luis de Bethencourt + + * gst/gstutils.c: + gstutils: remove obsolete Fixme comment + gst_pad_link_filtered() is very long gone and current + gst_element_link_pads_filtered() doesn't apply to this Fixme comment. + +2015-02-24 21:58:00 +0100 Matthieu Bouron + + * scripts/gst-uninstalled: + gst-uninstalled: add adaptivedemux paths from -bad + https://bugzilla.gnome.org/show_bug.cgi?id=745122 + +2015-02-24 18:14:47 +0000 Luis de Bethencourt + + * docs/faq/developing.xml: + docs: remove dead link + Remove dead link to wiki page for SubmittingPatches + https://bugzilla.gnome.org/show_bug.cgi?id=730311 + +2015-02-24 14:07:54 +0100 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + helpers: Fix install of completion-helper. + By applying the supplied transformation to the program name, + for example --program-prefix. + +2015-02-23 16:39:43 -0500 Nicolas Dufresne + + * libs/gst/helpers/Makefile.am: + completion-helper: Add missing DESTDIR + Otherwise doing "make install DESTDIR" will try to write to + /usr/share/... + +2015-02-23 21:17:16 +0100 Mathieu Duponchelle + + * libs/gst/helpers/gst-completion-helper.c: + completion-helper: Add filtering by klass and sink caps. + +2015-02-21 17:13:26 +0100 Mark Nauwelaerts + + * plugins/elements/gstmultiqueue.c: + multiqueue: avoid returning downstream GST_FLOW_EOS from previous segment to current upstream segment + +2015-02-22 10:02:25 +0100 Mark Nauwelaerts + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: fix documentation comment typo + +2015-02-22 10:01:33 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: drain segment upon SEGMENT_DONE to ensure proper event order + +2015-02-22 10:01:50 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: clean up some bogus commented code + +2015-02-23 19:10:08 +0100 Mathieu Duponchelle + + * libs/gst/helpers/Makefile.am: + completion-helper: Append $(EXEEXT) to the name of the moved file. + Fixes the build on Windows + (https://ci.gstreamer.net/job/cerbero-cross-mingw32/1742/console) + +2015-02-23 17:23:33 +0000 Tim-Philipp Müller + + * Makefile.am: + Fix distcheck + Disable bash completion during distchecking otherwise + it may try to install into a system path and fail. + +2015-02-23 17:16:45 +0000 Tim-Philipp Müller + + * Makefile.am: + Dist new data directory + Fixes 'make dist' + +2015-02-20 22:04:22 +0100 Mathieu Duponchelle + + * Makefile.am: + * configure.ac: + * data/Makefile.am: + * data/completions/gst-inspect-1.0: + * data/completions/gst-launch-1.0: + * libs/gst/helpers/.gitignore: + * libs/gst/helpers/Makefile.am: + * libs/gst/helpers/gst: + * libs/gst/helpers/gst-completion-helper.c: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + bash-completion: Implement in a different way. + + Gets installed + + Uses a helper tool, gst-completion-helper, installed in + bash-completions/helpers. + + Adds a common script that other tools can source. + https://bugzilla.gnome.org/show_bug.cgi?id=744877 + +2015-02-23 12:08:49 +0000 Luis de Bethencourt + + * gst/Makefile.am: + * gst/gst.h: + GstDeviceMonitor: keep alphabetical order + +2015-02-20 16:22:23 -0500 Olivier Crête + + * gst/gstelement.c: + * tests/check/gst/gstelement.c: + Revert "element: set pads need-parent flag to false when removing" + This reverts commit 1911554cff2c4a11772b541a8215a80c728b1097. + This breaks the functionality of GST_PAD_FLAG_NEED_PARENT, the reason for this + flag is that if a pad is removed from a running element, you don't want + functions (such as chain or event) to be called on the pad without a parent set. + This can happen if you remove a request or sometimes pad from a running element. + I don't see the code that caused this in tsdemux, but if it needs to unset + the flag on remove, it should do it itself and then make sure that the parent + exists in any pad function. + +2015-02-19 12:17:15 +0100 Mathieu Duponchelle + + * libs/gst/check/gstcheck.h: + check: cast element in ASSERT_SET_STATE. + https://bugzilla.gnome.org/show_bug.cgi?id=744777 + +2015-02-19 01:16:52 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Use a separate query for upstream pads and let it fail if one upstream query fails + +2015-02-19 01:12:49 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: If the latency query fails for one of the pads, it fails overall + +2015-02-18 11:05:19 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Remove unused boolean parameter from internal functions + +2015-02-17 12:11:43 +0200 Sebastian Dröge + + * tests/check/elements/queue.c: + queue: Add unit test for buffer list and time level handling + +2015-02-17 11:44:40 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Add support for buffer lists + +2015-02-17 11:41:50 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Count the number of buffers in a buffer list for updating the current levels + instead of just assuming one buffer. + +2015-02-17 20:47:23 +0000 Tim-Philipp Müller + + * gst/gstmessage.c: + message: revive async delivery message before bus thread can run unref + Revive message in dispose handler before we signal the bus thread, + otherwise the bus thread might be woken up and unref the message + before we had a chance to revive it yet. + +2015-02-16 23:02:40 +0000 Tim-Philipp Müller + + * tests/check/gst/gstbus.c: + tests: bus: add unit test for async message delivery + +2015-02-16 22:39:42 +0000 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstbus.c: + * gst/gstmessage.c: + message, bus: fix async message delivery + Async message delivery (where the posting thread gets blocked + until the message has been processed and/or freed) was pretty + much completely broken. + For one, don't use GMutex implementation details to check + whether a mutex has been initialized or not, esp. not + implementation details that don't hold true any more with + newer GLib versions where atomic ops and futexes are used + (spotted by Josep Torras). This led to async message + delivery no longer blocking with newer GLib versions on + Linux. + Secondly, after async delivery don't free mutex/GCond + embedded inside the just-freed message structure. + Use a new (private) mini object flag to signal GstMessage + that the message being freed is part of an async delivery + on the bus so that the dispose handler can keep the message + alive and the bus can free it once it's done cleaning up + stuff. + +2015-02-16 19:24:44 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + info: nicer buffer offset printing when offsets are not set + Print unset offsets as 'none' instead of humongous numbers, + for better readability. + +2015-02-16 11:35:41 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Only initialize GValue to a type once, not on every retry + Otherwise we'll get warnings like this: + cannot initialize GValue with type 'gboolean', the value has already been initialized as 'gboolean' + +2015-02-14 12:15:03 +0100 Matthieu Bouron + + * gst/gstutils.c: + gstutils: check uri before using it in gst_pad_create_stream_id_internal + If an element implements wrongly the URI query and set the uri to NULL and if + the element calls gst_pad_create_stream_id at some point, it will lead to crash + as the uri is not supposed to be NULL in the gst_pad_create_stream_id_internal + function. + https://bugzilla.gnome.org/show_bug.cgi?id=744520 + +2015-02-13 19:43:24 +0100 Thibault Saunier + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + timedvaluecontrolsource: Do not wrongly send value-removed + And avoid freeing something we do not own + +2015-02-04 15:06:17 +0100 Thibault Saunier + + * scripts/gst-uninstalled: + gst-uninstalled: Set GST_VALIDATE_PLUGIN_PATH + +2015-02-12 13:34:49 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: fix documentation and debug message after latency updates + Changes docs and message according to latency handling fix + +2015-02-12 14:50:15 +0000 Frédéric Wang + + * plugins/elements/gstfdsrc.c: + fdsrc: use g_ascii_strtoull() to convert size string in uri + sscanf() doesn't handle G_GUINT64_FORMAT well on mingw64 it + appears, leading to compiler warnings. + https://bugzilla.gnome.org/show_bug.cgi?id=744034 + +2015-02-12 14:03:15 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: gst_pad_iterate_internal_links() can return NULL if there are none + +2015-02-12 14:03:03 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Return NULL instead of FALSE for pointers + +2015-02-12 13:55:36 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Implement more useful default handling for the LATENCY query + Before we just took the values from the first pad that succeded the query, + now we accumulate the results of every sinkpad properly and return that + result. + +2015-02-12 11:26:26 +0200 Sebastian Dröge + + * docs/design/part-latency.txt: + design/part-latency: Minor logic fix + The maximum latency will be the element's minimum latency or bigger, + not bigger than the element's minimum latency or bigger. + +2015-02-11 13:41:56 +0100 Sebastian Dröge + + * gst/gstquery.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue.c: + Improve and fix LATENCY query handling + This now follows the design docs everywhere. + https://bugzilla.gnome.org/show_bug.cgi?id=744106 + +2015-02-11 12:20:39 +0100 Sebastian Dröge + + * docs/design/part-latency.txt: + design/part-latency: Add more details about min/max latency handling + These docs missed many details that were not obvious and because of that + handled in a few different, incompatible ways in different elements and base + classes. + https://bugzilla.gnome.org/show_bug.cgi?id=744106 + +2015-02-07 05:16:23 +1100 Jan Schmidt + + * tests/check/gst/gstclock.c: + tests: Fix clock regression test + Fix up the values the test is checking for now that + the clock regression returns parameters starting from + the end of the regression range. + +2015-02-07 04:22:22 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Don't update the clock when it desynch + Add a hold off when the clock calibration suddenly loses synch, + as it may be a glitch, but also make sure we update if it stays + desynched for more than a few seconds + +2015-02-06 06:07:43 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Make the RTT average ignore large values more forcefully. + Smooth larger RTTs a little harder, so excessively large values + perturb the average a bit less, and therefore get filtered out + more strongly + +2015-02-05 22:55:39 +1100 Jan Schmidt + + * gst/gstclock-linreg.c: + clock: Make linear regression x/y base start from maximum observation. + Project the results of the linear regression to the end of the + regression range, so they're more directly comparable to results + going forward + +2015-02-05 13:49:47 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: add "offset" property to go with gst_pad_set_offset() + So we can set the offset via gst-launch. + +2015-02-02 08:22:47 +0100 Stefan Sauer + + * gst/gstplugin.c: + plugin: add more detail to logging when not loading a plugin + Improve the log messages and add e.g the version number we checked. + +2015-02-02 17:37:44 +1100 Jan Schmidt + + * gst/gstpad.c: + gstpad: Fix a typo in a docstring. + +2015-02-01 14:23:26 -0500 Nicolas Dufresne + + * gst/gsttask.c: + build: Check that _MSC_VER macro is defined + +2015-02-01 03:39:03 +0200 Ilya Konstantinov + + * configure.ac: + * gst/gsttask.c: + task: Add thread name support on OS X and iOS + +2015-01-29 16:37:07 +0100 Sebastian Dröge + + * gst/gstclock-linreg.c: + clock: Don't use invalid objects for GST_DEBUG_OBJECT() + Not sure what "clock" actually is here, it must be something defined by one of + the headers that are included. + +2015-01-29 12:10:18 +0100 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Document that gst_buffer_copy_region() accepts -1 as size to copy until the end + It's just a wrapper around gst_buffer_copy_into() after all. + +2014-12-09 16:28:56 +1100 Jan Schmidt + + * gst/gstsegment.c: + * gst/gstsegment.h: + segment: Add new skip flags for clarifying trick mode playback. + Add GST_SEEK_FLAG_TRICKMODE_KEY_UNITS and + GST_SEEK_FLAG_TRICKMODE_NO_AUDIO, and rename GST_SEEK_FLAG_SKIP + to GST_SEEK_FLAG_TRICKMODE (with backwards compat define). + Do the same for the corresponding SEGMENT flags. + https://bugzilla.gnome.org/show_bug.cgi?id=735666 + +2015-01-23 08:59:27 +0100 Stefan Sauer + + * libs/gst/check/gstcheck.c: + check: fix another typo in the docs + +2015-01-22 23:10:06 +0200 Sebastian Dröge + + * gst/gsturi.c: + * tests/check/gst/gsturi.c: + uri: Fix indention + +2015-01-21 14:10:02 +0000 David Waring + + * tests/check/gst/gsturi.c: + uri: Fix new URI parsing tests based on GNet's + https://bugzilla.gnome.org/show_bug.cgi?id=743195 + +2015-01-21 14:09:45 +0000 David Waring + + * gst/gsturi.c: + uri: Fix parsing issues + Make host IPs in square brackets store only the IP, i.e. strip the brackets. + Strip leading whitespace characters in URIs. + Fail parsing when host part does not match any valid formats from RFC3986. + https://bugzilla.gnome.org/show_bug.cgi?id=743195 + +2015-01-19 19:15:32 +0100 Sebastian Dröge + + * tests/check/gst/gsturi.c: + uri: Add parsing unit test based on GNet's + Plus some new URIs to parse. + https://git.gnome.org/browse/archive/gnet/plain/tests/check/gnet/gneturi.c + https://bugzilla.gnome.org/show_bug.cgi?id=743195 + +2015-01-22 11:29:18 +0100 Heinrich Fink + + * libs/gst/check/gstcheck.c: + check: Fix doc of GST_CHECKS and GST_CHECKS_IGNORE + https://bugzilla.gnome.org/show_bug.cgi?id=743335 + +2015-01-21 18:07:09 +0100 Sebastian Dröge + + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + check: Add _fail_unless() compatibility function around _ck_assert_failed() + We exported this in < 1.5 and it was automatically used by many macros + from the header. Keep it exported for now. + +2015-01-21 14:12:22 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Inline apply_pad_offset() + Avoid doing a function call for something which will mostly be unused + +2015-01-21 14:10:06 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Fix debug message + +2015-01-21 11:45:41 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Fix PROBE_NO_DATA macro + The problem was that the macro was always used with 'ret' as the defaultval + argument. + This would result in the macro eventually expanding to + if (G_UNLIKELY (ret != ret && ret != GST_FLOW_OK)) + ... ret != ret will always fail, and therefore we'd never call the + following line. + Instead of that, store the previous value locally for comparision + +2015-01-21 22:44:59 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Fix docs typo. Clock bus messages are GST_MESSAGE_ELEMENT + +2015-01-15 22:32:28 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Implement rate limits for polling and fix up skew limits + Add the minimum-update-interval property to the clock, with a default + of 50ms and don't send polling requests faster than that. That helps to + ensure we spread the initial observations out a little - startup takes + a little longer, but tracking is more stable. + Move the discont skew limiting code inside an if statement, so that + it's only done when the linear regression succeeds and the clock + parameters might actually change. + +2015-01-15 10:05:32 +1100 Jan Schmidt + + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gstclock-linreg.c: + * gst/gstclock.c: + * tests/check/gst/gstclock.c: + clock: Improve slaving regression. + Add domain checks for the input values, and a variable precision + calculation that loops if necessary to ensure we never overflow + accumulators and then silently produce garbage results. + Make the (non-public) linear regression function available for + unit testing by putting it in a separate source file the test + can include. Add a unit test that the new regression function + produces sensible results for several inputs taken from real-world + captures. + +2015-01-10 21:42:00 +1100 Jan Schmidt + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/netclock/.gitignore: + * tests/examples/netclock/Makefile.am: + * tests/examples/netclock/netclock-client.c: + * tests/examples/netclock/netclock-server.c: + netclock: Add simple network clock server and client examples + +2015-01-10 21:42:00 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Implement sending statistic bus messages and discont limits + Allow setting a GstBus on the network clock client + via a new 'bus' object property. If a bus is set, the + clock will output an element message containing statistics + about new clock observations and the clock correlation. + When the local clock is synchronised with the remote, limit the + maximum jump in the clock at any point to be one average RTT to + the server. Also, publish in the bus message whether we are + synched with the remote or not. + +2015-01-10 21:42:00 +1100 Jan Schmidt + + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + clock: Add gst_clock_add_observation_unapplied() + gst_clock_add_observation_unapplied() adds a new master/slave clock + observation and runs the regression without activating the new + calibration results. + +2014-12-16 22:51:22 +1100 Jan Schmidt + + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + clock: Add gst_clock_adjust_with_calibration() + gst_clock_adjust_with_calibration() uses directly passed calibration + parameters, instead of using the clock's current calibration, + allowing for calculations using pending or old calibration params + +2015-01-21 09:45:16 +0100 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + output-selector: Constify negotiation mode GEnumValue table + +2015-01-20 10:35:47 -0300 Thiago Santos + + * gst/gstevent.c: + docs: fix typo in GstEvent docs + send -> sent + +2015-01-20 09:19:10 +0100 Thibault Saunier + + * scripts/git-update.sh: + * scripts/gst-uninstalled: + scripts: Remove gnonlin from the scripts + It is not maintain anymore and its feature are now inside the GStreamer + Editing Services (for the time being). + +2015-01-16 19:17:31 +0100 Sebastian Dröge + + * gst/gstbin.c: + bin: Pass structs we plan to modify around by pointer, not value + Otherwise the struct is going to be copied, which is not very efficient. And + also has the nice side effect that modifications of the struct might be + done in a copy, and we later use the original struct without the changes. + Caused LATENCY queries to always return the initialization values in one of my + tests, instead of the actual values reported by child elements. + +2015-01-14 10:52:11 +0000 Vincent Penquerc'h + + * plugins/elements/gstidentity.c: + identity: send gap events when dropping buffers + +2015-01-13 18:11:39 +0000 Phillip Wood + + * gst/gstpreset.c: + preset: fix incorrect preset version comparison + Use app_version if there are no system presets, so that if the + application presets are newer than the user presets they are merged. + https://bugzilla.gnome.org/show_bug.cgi?id=742877 + +2015-01-12 16:03:02 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Don't dereference NULL pointer + CID 1262286 + +2015-01-12 15:55:47 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From f2c6b95 to bc76a8b + +2015-01-11 23:00:29 +0100 Stefan Sauer + + * gst/gstpreset.c: + preset: fix sorting presets + The glib docs are not clear on this, but the qsort man-page is - the + GCompareDataFunc does not get the strings, but pointers to them. + +2014-12-31 18:52:34 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + inputselector: fix silly GQueue iteration code + Not active by default though. + +2015-01-04 23:24:53 +0100 Stefan Sauer + + * gst/gstpreset.c: + preset: don't return empty preset lists + Add a shortcut for the cases where an element implements the preset iface but + has no presets and return NULL instead of an empty list in that case. + +2015-01-04 23:08:47 +0100 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: only print presets line if num-presets > 0 + Also check for an empty strv. + +2015-01-04 22:51:09 +0100 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: fix output for -a + Use n_print to ensure all lines are prefixed with the element name. + +2014-12-29 11:54:00 +0100 Stefan Sauer + + * docs/libs/Makefile.am: + docs: ignore libcheck headers that use doxygen comments + +2014-12-29 11:52:22 +0100 Stefan Sauer + + * gst/gstinfo.h: + docs: fix two gtk-doc warnings + One by correcting the end-of-comment marker and one by making sure the function + prototype in the header is in sync with the c file and doc-blob. + +2014-12-26 23:22:30 +0100 Sebastian Rasmussen + + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + * docs/plugins/gstreamer-plugins-sections.txt: + docs: Add missing interfaces to documentation + https://bugzilla.gnome.org/show_bug.cgi?id=742057 + +2014-12-27 15:15:30 +0530 Nirbheek Chauhan + + * gst/gstiterator.c: + iterator: Fix outdated example code and accompanying documentation + GstIterator no longer returns a refcounted gpointer + +2014-12-24 13:46:28 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Use the same waiting function for EOS and non-EOS waiting + +2014-12-24 13:44:09 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Wake up all waitings pads directly if we forward the EOS event + Otherwise they might wait a bit longer unnecessarily. + Also do some minor cleanup. + +2014-12-24 10:13:51 +0800 Song Bing + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Block when receiving an EOS event on a deactivated pad + ... and only unblock when either a) the pad becomes active and the event + should be forwarded or b) the active pad went EOS itself. + Otherwise it can happen that we switch from a longer track that is not EOS yet + to a shorter track that already is EOS, but the shorter track won't have any + possibility to send its EOS event downstream anymore. + https://bugzilla.gnome.org/show_bug.cgi?id=740949 + +2014-12-23 12:54:50 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Keep a ref of the currently active sinkpad around + Otherwise we can't be sure that the pointer points to a still existing + pad instance after releasing the lock. + +2014-12-23 12:53:58 +0100 Song Bing + + * plugins/elements/gstinputselector.c: + inputselector: Get the active sinkpad again after taking the lock when handling events + It might have changed in the meantime. + https://bugzilla.gnome.org/show_bug.cgi?id=741893 + +2014-12-22 13:08:37 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Short-circuit CAPS query handling if transform_caps returns EMPTY caps + Both for the peer filter caps and the converted caps based on the peer caps. + If the peer filter caps are EMPTY, the peer caps query will also return + EMPTY. There's no ned to both downstream/upstream with this query. + +2014-12-22 11:45:13 +0100 Sebastian Dröge + + * MAINTAINERS: + MAINTAINERS: Update my mail address + +2014-12-21 14:12:29 +0100 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: use a constant for the max param length + Improve readability by using a define for the max-chars. Also use the unicode + ellipsis as dot files are utf-8. + +2014-12-15 14:03:54 +0100 Stefan Sauer + + * tools/gst-inspect.c: + gst-inspect: print preset names + If the element supports presets and ships some, print them. + Fixes #741427 + +2014-12-19 11:35:24 +0100 Edward Hervey + + * gst/gstinfo.h: + gstinfo: Add new maximum level debugging + API: GST_LEVEL_MAX + By compiling gstreamer (or plugins) with GST_LEVEL_MAX defined, only + the debugging statements at or below that level will be compiled in. + This allows compiling in some debugging (like errors and warnings) which + helps in debugging, but without the full cpu/memory overhead of all debugging + enabled. + +2014-12-18 12:04:22 -0300 Thiago Santos + + * libs/gst/check/gstcheck.c: + gstcheck: fix GI annotation + Add missing : to annotation + +2014-11-13 14:53:59 +0000 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: jump over large skips in pull mode + This bypasses the dumping of buffers we still have to do in push mode. + https://bugzilla.gnome.org/show_bug.cgi?id=730053 + +2014-10-25 17:16:25 +0530 Arun Raghavan + + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + debugutils: Truncate parameter values that are too long + This removes some information from the dumps, but improves readability. + https://bugzilla.gnome.org/show_bug.cgi?id=739165 + +2014-12-18 10:53:02 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From ef1ffdc to f2c6b95 + +2014-12-16 16:31:21 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gststructure.c: + * gst/gststructure.h: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gststructure.c: + * win32/common/libgstreamer.def: + structure/caps: Add gst_{structure,caps}_filter_and_map_in_place() + https://bugzilla.gnome.org/show_bug.cgi?id=739765 + +2014-12-16 18:14:22 +0100 Sebastian Dröge + + * tests/check/gst/gststructure.c: + structure: Add simple unit test for foreach() and map_in_place() + +2014-11-07 11:15:09 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * tests/check/gst/gstcaps.c: + caps: Add gst_caps_foreach() and gst_caps_map_in_place() + https://bugzilla.gnome.org/show_bug.cgi?id=739765 + +2014-12-16 15:53:06 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translatable strings + +2014-12-14 12:54:32 +0100 Sebastian Rasmussen + + * configure.ac: + * libs/gst/check/Makefile.am: + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + check: Have autotools generate internal-check.h + Previously GStreamer got access to the libcheck interface by including + libs/gst/check/check.h which in turn included internal-check.h in the + same directory. internal-check.h was generated by copying + libs/gst/check/libcheck/check.h which in turn was generated from + check.h.in in the same directory. In this case generating + libs/gst/check/libcheck/check.h is unnecessary, in addition this file + was accidentally distributed in generated project tarballs. + Now libs/gst/check/internal-check.h is generated directly from + libs/gst/check/libcheck/check.h.in by configure. This means that the + libcheck source must include internal-check.h instead of the previously + generated libs/gst/check/libcheck/check.h. However the unnecessary + intermediate step is now skipped. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=741359 + +2014-12-16 10:13:03 -0500 Nicolas Dufresne + + * gst/gstbufferpool.c: + * tests/check/gst/gstbufferpool.c: + bufferpool: Don't check size in config validation + Pools are allowed to change the size in order to adapt padding. So + don't check the size. Normally pool will change the size without + failing set_config(), but it they endup changing the size before + the validate method may fail on a false positive. + https://bugzilla.gnome.org/show_bug.cgi?id=741420 + +2014-12-16 12:21:59 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: log reason for discarded buffers + PERFORMANCE log the reason why a buffer could not be recycled in the + bufferpool. + +2014-12-15 14:53:28 +0100 Sebastian Rasmussen + + * m4/check-checks.m4: + check: Update version number of included libcheck + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=741550 + +2014-12-12 21:02:22 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update exports + +2014-12-12 21:54:01 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + docs: add new preset api + +2014-12-12 21:38:26 +0100 Stefan Sauer + + * gst/gstpreset.c: + * gst/gstpreset.h: + preset: add gst_preset_is_editable() + Add a function to check if the preset iface implementation is editable and + document this from the implementers perspective. + API: gst_preset_is_editable() + +2014-12-12 14:23:19 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update def file + +2014-12-12 13:57:39 +0100 Sebastian Dröge + + * gst/gstdebugutils.c: + debugutils: Fix compiler warning + gstdebugutils.c: In function 'gst_debug_bin_to_dot_data': + gstdebugutils.c:683:530: error: 'return' with no value, in function returning non-void [-Werror] + g_return_if_fail (GST_IS_BIN (bin)); + +2014-12-12 13:15:02 +0530 Arun Raghavan + + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + debugutils: Add a gst_debug_bin_to_dot_data() method + This provides the dot file as a string, rather than dumping to a file. + https://bugzilla.gnome.org/show_bug.cgi?id=741425 + +2014-12-10 11:17:11 +0000 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefind: minor cosmetic change + No nee to abbrev variab nam here, nicer to read if full. + +2014-12-10 11:16:09 +0000 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefind: use GST_BUFFER_OFFSET_NONE for buffer offset + +2014-12-07 12:55:26 +0100 Sebastian Rasmussen + + * libs/gst/check/libcheck/check.h.in: + check: Avoid requring (u)intmax_t in macros + Previously embedded libcheck versions did not depend on (u)intmax_t and + doing so would require projects using GStreamer's check framework to add + AX_CREATE_STDINT_H to their configure.ac. A workaround is to fallback to + glib types. This patch assumes that glib.h is always included before + internal-check.h which is ok since everything Gstreamer would include + gst/gstcheck.h instead of directly including internal-check.h. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727826 + +2014-12-06 19:03:04 +0100 Sebastian Rasmussen + + * libs/gst/check/libcheck/clock_gettime.c: + check: Fix compilation error for iOS + libcheck includes CoreServices for its compat for clock_gettime(), + even though it never uses anything it declares. Let's remove it. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727826 + +2014-11-15 13:26:47 +0100 Sebastian Rasmussen + + * configure.ac: + * libs/gst/check/gstcheck.h: + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_error.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/libcompat.h: + * m4/check-checks.m4: + check: Apply GStreamer-specific patches + Reintroduced patches: + * Make sure that fail_if(1) actually fails + from commit 9f99d056a263e71a5e6181224829def906cf0226 + New patches due to updated libcheck (based on 0.9.14): + * Checks in m4/check-checks.m4 to cater for new dependencies + * Conditional compile-time compat POSIX fallbacks for libcheck + * Avoid relative paths for libcheck header files + * Make timer_create() usage depend on posix timers, not librt + * Rely on default AX_PTHREAD behavior to allow HAVE_PTHREAD to be used + when checking for types and functions (like clock_gettime()) + * Avoid double declaration of clock_gettime() when availabe outside of + librt by making compat clock_gettime() declaration conditional + * check 0.9.9 renamed _fail_unless() and 0.9.12 later renamed it again + to _ck_assert_failed(), so ASSERT_{CRITICAL,WARNING}() now calls this + function + * Remove libcheck fallback infrastructure for malloc(), realloc(), + gettimeofday() and snprintf() since either they appear to be + available or they introduce even more dependencies. + The result is an embedded check in gstreamer that has been tested by + running check tests in core, -base, -good, -bad, -ugly and rtsp-server + on Linux, OSX and Windows. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727826 + +2014-11-15 12:53:32 +0100 Sebastian Rasmussen + + * libs/gst/check/libcheck/alarm.c: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_error.h: + * libs/gst/check/libcheck/check_impl.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_list.h: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_log.h: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_msg.h: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_pack.h: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_print.h: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/check_str.h: + * libs/gst/check/libcheck/clock_gettime.c: + * libs/gst/check/libcheck/libcompat.c: + * libs/gst/check/libcheck/libcompat.h: + * libs/gst/check/libcheck/localtime_r.c: + * libs/gst/check/libcheck/strsignal.c: + * libs/gst/check/libcheck/timer_create.c: + * libs/gst/check/libcheck/timer_delete.c: + * libs/gst/check/libcheck/timer_settime.c: + check: Import version 0.9.14 + This lifts the files almost verbatim (the changes being running though + gst-indent and fixing the FSF address) from the upstream respository. + Therefore this commit reverts some GStreamer-specific patches to check + that will be reintroduced next. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727826 + +2014-11-04 19:11:50 +0100 Edward Hervey + + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefind: Propagate input buffer offset + The initial buffers might have non-default offsets, make sure they get + propagated if present. + +2014-10-07 16:44:45 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: clamp reported position based on direction + When using a negative rate (rate being segment.rate * segment.applied_rate), + we will end up reporting decreasing positions, therefore adjust the clamping + against last reported value accordingly. + Fixes positions getting properly reported with applied_rate < 0.0 + https://bugzilla.gnome.org/show_bug.cgi?id=738092 + +2014-11-28 14:17:54 +0100 Sebastian Dröge + + * docs/manual/advanced-buffering.xml: + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstcontrolbinding.c: + * gst/gstdevicemonitor.c: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstplugin.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * libs/gst/check/gsttestclock.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * tools/gst-launch.c: + Don't compare booleans for equality to TRUE and FALSE + TRUE is 1, but every other non-zero value is also considered true. Comparing + for equality with TRUE would only consider 1 but not the others. + Also normalize booleans in a few places. + +2014-11-30 23:50:53 +0000 Tim-Philipp Müller + + * plugins/elements/gstelements_private.c: + plugins: fix build on windows + gstelements_private.c: In function 'gst_writev_buffers': + gstelements_private.c:236:51: error: 'EWOULDBLOCK' undeclared + +2014-11-28 15:09:16 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesink.c: + filesink: use writev() in ::render() to write out memories without merging them + +2014-11-28 15:04:27 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + filesink: implement ::render_list() function that uses writev() + +2014-11-28 14:47:20 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + fdsink: use writev() in ::render() to write out memories without merging them + +2014-11-28 14:39:33 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + fdsink: implement ::render_list() using writev() + Write out multiple buffers possibly containing multiple + memories with one writev() call, without merging the + buffer memories first, like ::render() does currently. + +2014-11-28 14:38:30 +0000 Tim-Philipp Müller + + * configure.ac: + * plugins/elements/gstelements_private.c: + * plugins/elements/gstelements_private.h: + plugins: add helper function for writing buffers out with writev() + +2014-11-28 14:15:30 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: update the duration variable before emitting the bus + Otherwise the application might still get the old value if it asks + between the message and the real update. + +2014-11-28 16:25:02 +0100 Edward Hervey + + * gst/gstelement.c: + element: Fix doc and default implementation of send_event + The documentation states that gst_element_send_event is to "send an event + to an element". + Therefore we *send* upstream events to a source pad and downstream events + to a sink pad + +2014-11-28 11:16:00 +0100 Edward Hervey + + * gst/gstelement.c: + element: Figure default send_event direction handling + If we get a downstream event we want to send it to a random SINK pad + (and vice-versa). + +2014-11-27 18:00:57 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Compare correct caps variable against NULL before comparing caps + +2014-11-27 17:10:19 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From f32cfcd to ef1ffdc + +2014-11-10 09:58:47 +0100 Thibault Saunier + + * scripts/gst-uninstalled: + scripts:uninstalled: Make sur the GES TestManager is registered + So that whenever user work with GstValidate they can run GES tests + within the gst-uninstalled environment + +2014-11-26 21:48:05 +0530 Arun Raghavan + + * common: + * m4/ax_pthread.m4: + build: Update ax_pthread.m4 and move it to common + Has some updates for Clang support (might not work with newer Clang + properly, yet), AIX support, and some misc fixes. + +2014-11-25 17:46:12 +0100 Sebastian Dröge + + * libs/gst/controller/gsttriggercontrolsource.c: + triggercontrolsource: Fix short description for the docs + +2014-11-25 09:39:40 +0000 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: add GST_GL_* environment variables to 'Running GStreamer' section + +2014-11-23 05:45:24 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: percentage is relative to high-percent + When comparing percentage values, compare with 0-100 scale as it + has already been made relative to 0-high_percent, otherwise we mark + the queue as not buffering and report a 50% to the user. This leads to + a buffering stall as the user assumes the queue is still buffering but + it thinks it isn't. + https://bugzilla.gnome.org/show_bug.cgi?id=736969 + +2014-11-23 05:42:51 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: percentage is an absolute value + multiqueue's queues stored percent value is the percentage from 0 + to 100 (max-size-*) and should be compared with the requested limit + (high_percentage) set by the user and not with 100% to check if + buffering should stop. Otherwise we are only stopping buffering when the + queue gets completely full. + +2014-11-20 21:33:59 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Fix caps equality check + Instead of checking if our outcaps are equivalent to the previous incaps, and + if that is the case not setting any caps on the pad... compare against our + previous outcaps because that's what we care about. + Fixes some cases where the outcaps became equivalent to the previous incaps, + but the previous outcaps were different and we were then sending buffers + downstream that were corresponding to the caps we forgot to set on the pad. + Resulting in crashes or image corruption. + +2014-11-20 13:33:12 +0000 Tim-Philipp Müller + + * common: + common: update for bison version check patch + Fix configure check with bison development version. + https://bugzilla.gnome.org/show_bug.cgi?id=728946 + +2014-11-20 13:34:32 +0100 Wim Taymans + + * gst/gststructure.c: + * tests/check/gst/gststructure.c: + structure: don't overread input when searching for " + When searching for the string terminator don't read past the ending + 0-byte when escaping characters. + Add unit test for various escaping cases. + +2014-11-03 17:46:57 +0000 Vincent Penquerc'h + + * gst/gstpad.c: + pad: fail dropped queries + Previously, dropping a query from a pad probe would deem the + query succeeded, and the caller might then assume the query's + results are valid, and thus dereference an invalid object + such as a GstCaps. + We now assume dropped queries did not succeed. Dropped events + and buffers are still deemed a success. + Added back after previous revert, as it's been double checked. + https://bugzilla.gnome.org/show_bug.cgi?id=740003 + +2014-11-12 13:55:23 +0000 Vincent Penquerc'h + + * gst/gstpad.c: + Revert "pad: fail dropped queries" + This was pushed by mistake along with an unrelated patch. + This reverts commit c7103ce4b8c1da7dcfbcf2ec83a42a376fb896e1. + +2014-05-13 11:18:08 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: allow skipping more data than we currently have + This can be useful for skipping large unwanted data, such as + large album art, when we know the size of it from a metadata + header. + +2014-11-03 17:46:57 +0000 Vincent Penquerc'h + + * gst/gstpad.c: + pad: fail dropped queries + Previously, dropping a query from a pad probe would deem the + query succeeded, and the caller might then assume the query's + results are valid, and thus dereference an invalid object + such as a GstCaps. + We now assume dropped queries did not succeed. Dropped events + and buffers are still deemed a success. + +2014-11-12 11:30:51 +0100 Haakon Sporsheim + + * gst/gsttask.c: + * tests/check/gst/gsttask.c: + task: Fix pause/stop race condition + If a task thread is calling pause on it self and the + controlling/"main" thread stops the task, it could end in a race + where gst_task_func loops and then checks for paused after the + controlling thread just changed the task state to stopped. + Hence the task would actually call func again even though it was + both paused and stopped. + https://bugzilla.gnome.org/show_bug.cgi?id=740001 + +2014-11-10 10:01:02 +0100 Sebastian Dröge + + * tests/check/gst/gstobject.c: + gstobject: Don't check booleans for equality in the unit test + Every value other than 0/FALSE is TRUE, == TRUE will only check for 1. + +2014-11-05 11:50:47 +0100 Jan Alexander Steffens (heftig) + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/check/gst/gstobject.c: + * win32/common/libgstreamer.def: + gstobject: Add gst_object_has_parent() + Adds gst_object_has_parent, which works like gst_object_has_ancestor + but does not ascend further. + API: gst_object_has_parent() + +2014-11-09 10:37:42 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Don't bother the subclass with setting the same caps multiple times + +2014-11-09 10:32:18 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Don't bother the subclass with setting the same caps multiple times + +2014-11-09 10:29:57 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't bother the subclass with setting the same caps multiple times + +2014-11-07 08:22:02 +0100 Stefan Sauer + + * gst/gststructure.c: + structure: remove conditional for G_VALUE_COLLECT_INIT + This API is in glib since 2.24 and we currently require 2.32 and already use + this unconditionally elsewhere. + +2014-11-05 19:09:39 +0100 Stefan Sauer + + * gst/gstpreset.c: + preset: remove commented code + The GQuark was never used. + +2014-11-07 11:34:08 +0100 Sebastian Dröge + + * gst/Makefile.am: + * pkgconfig/gstreamer.pc.in: + gstconfig: Put gstconfig.h into $(libdir)/gstreamer-1.0/include + It's architecture dependent and should not be placed into the include + directory as the assumption is that all those headers are architecture + independent. + https://bugzilla.gnome.org/show_bug.cgi?id=739767 + +2014-11-07 10:56:42 +0100 Sebastian Dröge + + * gst/gsturi.c: + uri: Fix gobject-introspection warnings + gsturi.c:997: Error: Gst: Skipping invalid GTK-Doc comment block: + /** private GstUri functions **/ + ^ + gsturi.c:1179: Error: Gst: Skipping invalid GTK-Doc comment block: + /** RFC 3986 functions **/ + ^ + +2014-10-24 21:25:54 +1100 Jan Schmidt + + * libs/gst/base/gstdataqueue.c: + dataqueue: Fix gst_data_queue_new() description. + Reword the function docs, which haven't made any sense since + gst_data_queue_new_full() was removed a few years ago. + +2014-11-03 18:27:21 +0100 Thibault Saunier + + * libs/gst/base/gstbasesink.c: + basesink: Answer the query position when receiving it from upstream + Currently we are just returning FALSE, but we do have the information + we should just answer the query the same way as when answering through + the GstElement.query vmethod default implementation. + https://bugzilla.gnome.org/show_bug.cgi?id=739580 + +2014-10-22 14:07:09 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + * tests/check/elements/capsfilter.c: + capsfilter: Add an optional delayed caps change mode + In this mode we accept previously set filter caps until + upstream renegotiates to something that is compatible + to the current filter caps. + This allows dynamic caps changes in the pipeline even + if there is a queue between any conversion element + and the capsfilter. Without this we would get not-negotiated + errors if timing is bad. + https://bugzilla.gnome.org/show_bug.cgi?id=739002 + +2014-11-02 20:16:53 +0000 Tim-Philipp Müller + + * gst/gsttoc.c: + toc: minor code clean-up + And get rid of g_list_prepend/g_list_reverse + anti-pattern while we're at it. + +2014-11-02 18:51:08 +0000 Luis de Bethencourt + + * gst/gst.c: + gst: ensure GStreamer initialization debug message is displayed + The GST_INFO ("initialized GStreamer succesfully") is currently at the end of + gst_init_check which isn't guaranteed to be run since GStreamer can be + initialized by using init_pre and init_post directly from GOptionContext like + gst-launch does. Ensure this message is displayed by moving it to init_post. + +2014-11-01 19:56:41 +0000 Luis de Bethencourt + + * gst/gstbus.c: + * libs/gst/base/gstadapter.c: + doc: Do not use deprecated gtk-doc 'Rename to' tag + GObject introspection GTK-Doc tag "Rename to" has been deprecated, changing to + rename-to annotation. + https://bugzilla.gnome.org/show_bug.cgi?id=739514 + +2014-11-01 22:30:30 +0100 Aurélien Zanelli + + * tools/gst-inspect.c: + gst-inspect: add G_PARAM_DEPRECATED to known flags + Display 'deprecated' instead of flag value when using G_PARAM_DEPRECATED + in element properties. + https://bugzilla.gnome.org/show_bug.cgi?id=739518 + +2014-10-31 16:10:01 +0000 Tim-Philipp Müller + + * tests/check/tools/gstinspect.c: + tests: refactor tools check a little + Use an array of constant strings so if arguments get + removed from it they are not considered leaked, and + valgrind is happy. Still some stuff leaking in GLib + though. + +2014-10-30 23:14:59 +0000 Tim-Philipp Müller + + * tests/check/libs/bytereader.c: + tests: fix out-of-bounds memory access in bytereader unit test + Caught by -fsanitize=address / libasan. + https://bugzilla.gnome.org/show_bug.cgi?id=739431 + +2014-10-28 19:16:52 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: make gst_init() thread-safe + Because we can, and there isn't really any + reason not to do so. + +2014-10-28 09:28:28 +0000 Tim-Philipp Müller + + * tests/check/elements/fdsrc.c: + tests: fdsrc: don't ignore return value of write() + Causes compiler warnings on some systems. + +2014-10-28 00:04:05 +0000 Tim-Philipp Müller + + * tests/check/elements/fdsrc.c: + tests: fix fdsrc test corner case + Make pipe socket non-blocking, so we don't + end up being blocked in a write on the pipe + while the src is eos and not reading data + any more, and thus we never unblock and never + notice that we're done. This would happen + quite reliably on the rpi. + +2014-10-27 17:56:15 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 84d06cd to 7bb2bce + +2014-10-25 17:15:42 +0530 Arun Raghavan + + * gst/gstdebugutils.c: + debugutils: Trivial typo fix + +2014-10-24 12:51:07 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: don't unlock mutex that is not locked + Fixes 'Attempt to unlock mutex that was not locked' + warning with newer GLibs when sink is shut down in + certain situations. Triggered by the decodebin + test_reuse_without_decoders unit test in -base + sometimes, esp. on slower machines. + +2014-10-22 18:25:26 +0100 Tim-Philipp Müller + + * win32/common/libgstcontroller.def: + win32: update .def for new _get_type() function for GstControlPoint + https://bugzilla.gnome.org/show_bug.cgi?id=737616 + +2014-09-29 21:10:14 +0200 Thibault Saunier + + timedvaluecontrolsource: Add some signals about values changes + In order for user to be able to track changes in the value set in + GstTimedValueControlSource the following signals have been added: + * value-added + * value-removed + * value-changed + To be able to use a GstControlPoint to be marshalled into the signals, + the GstControlPoint structure is now registerd as a GBoxed type. + New API: + ~~~~~~~ + * GstTimedValueControlSource::value-added + * GstTimedValueControlSource::value-removed + * GstTimedValueControlSource::value-added + https://bugzilla.gnome.org/show_bug.cgi?id=737616 + +2014-10-21 13:01:00 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From a8c8939 to 84d06cd + +2014-10-21 12:18:33 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + message: remove duplicate gst_message_get_type() in init + Spotted by: Jan Steffens + +2014-10-21 12:57:45 +0200 Stefan Sauer + + * README: + * common: + Automatic update of common submodule + From 6e75498 to a8c8939 + +2014-10-20 16:39:38 +0200 Stefan Sauer + + * plugins/elements/gstidentity.c: + identity: include the actual delta in the message + Including the actual delta in the message makes it easy to see, if the new + buffer is behind or ahead and how much. + +2014-10-18 18:43:43 +1100 Jan Schmidt + + * gst/gstvalue.c: + gstvalue: Tidy initialisation + Use some macros to make our value functions setup a bit + tidier, and micro-optimise a few reallocs by setting an + initial size for the global type arrays. + +2014-10-18 17:27:04 +1100 Jan Schmidt + + * tools/gst-indent: + gst-indent: Run indent twice. Once is not idempotent, twice seems to be. + +2014-10-16 10:13:14 +0400 Andrei Sarakeev + + * plugins/elements/gstmultiqueue.c: + multiqueue: Wake up any waiting streams if the current one goes EOS + Otherwise we might have unlinked streams waiting. + https://bugzilla.gnome.org/show_bug.cgi?id=738198 + +2014-10-17 12:41:04 +0200 Stefan Sauer + + * gst/gsttypefind.c: + typefind: simplify registration code + Remove a useless assert (we just instantiated this type). Drop the free'ing of + the extension array. As we just created the instance this is always NULL. + +2014-10-16 10:55:36 +0200 Felix Schwarz + + * docs/pwg/advanced-allocation.xml: + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-events.xml: + * docs/pwg/advanced-qos.xml: + * docs/pwg/advanced-tagging.xml: + docs: pwd: fix typos + https://bugzilla.gnome.org/show_bug.cgi?id=738612 + +2014-10-11 19:28:21 +0200 Linus Svensson + + * tests/check/gst/gstbus.c: + tests: Add a test for removing a bus watch + https://bugzilla.gnome.org/show_bug.cgi?id=735195 + +2014-08-19 23:28:52 +0200 Linus Svensson + + * gst/gstbus.c: + * gst/gstbus.h: + * tests/check/gst/gstbus.c: + * win32/common/libgstreamer.def: + bus: Add a function to remove a bus watch + If a bus watch is added to the non default main context it's not + possible to remove it using g_source_remove(). + Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=735195 + +2014-10-08 22:51:56 +0530 Arun Raghavan + + * gst/gstevent.h: + docs: Update GstQOSType documentation a bit + Correction for who is producing data too fast, and some other minor + clarifications. + https://bugzilla.gnome.org/show_bug.cgi?id=738166 + +2014-10-08 16:03:20 +0200 Guillaume Desmottes + + * docs/pwg/advanced-allocation.xml: + * docs/pwg/advanced-qos.xml: + docs: pwg: fix two typos + https://bugzilla.gnome.org/show_bug.cgi?id=738153 + +2014-10-08 15:37:37 +0200 Guillaume Desmottes + + * docs/pwg/advanced-negotiation.xml: + docs: pwg: fix typo in 'Dynamic negotiation' section + The point of this example is to show how to set caps + on the source pad once it has been set on the sink pad. + So, in passthrough mode, the caps is just copied to the + source pad. + https://bugzilla.gnome.org/show_bug.cgi?id=738153 + +2014-10-08 09:37:41 -0700 Aleix Conchillo Flaqué + + * plugins/elements/gstmultiqueue.c: + multiqueue: don't lock multiqueue when pushing serialized queries + If we are pushing a serialized query into a queue and the queue is + filled, we will end in a deadlock. We need to release the lock before + pushing and acquire it again afterward. + https://bugzilla.gnome.org/show_bug.cgi?id=737794 + +2014-10-08 01:33:51 +1100 Jan Schmidt + + * libs/gst/base/gstcollectpads.c: + collectpads: Use GST_PTR_FORMAT in debug to output buffer details + Use %GST_PTR_FORMAT instead of %p in debug output so all the buffer + details are output + +2014-10-06 13:38:21 +0200 Nicolas Huet + + * gst/gstsystemclock.c: + systemclock: fix multi-thread entry status issue + Running two threads, one executing the timer and one unscheduling it, the + unscheduled status set by the second thread is sometimes overwritten by the + first one. + https://bugzilla.gnome.org/show_bug.cgi?id=737999 + +2014-10-03 14:04:58 +0100 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + inputselector: fix compilation + +2014-10-03 14:44:48 +0200 Stefan Sauer + + * plugins/elements/gstinputselector.c: + input-selector: extract some common code into helpers + +2014-10-03 14:01:59 +0200 Stefan Sauer + + * plugins/elements/gstinputselector.c: + input-selector: small code cleanups + Rename TIMESTAMP -> PTS. Move a var down to the scope where it is used. Use + g_queue_free_full(). + +2014-10-03 13:47:42 +0200 Stefan Sauer + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: fix printf format + The padcount is uint. Also add comments to the instance vars. + +2014-10-02 03:30:24 +0200 Matej Knopp + + * libs/gst/base/gstbaseparse.c: + baseparse: don't leak caps in gst_base_parse_process_streamheader + https://bugzilla.gnome.org/show_bug.cgi?id=737762 + +2014-10-03 13:14:25 +0200 Matej Knopp + + * tests/check/libs/baseparse.c: + tests: baseparse: set_sink_caps vfunc should't take ownership of the caps + https://bugzilla.gnome.org/show_bug.cgi?id=737762 + +2014-10-03 09:57:37 +0100 Luis de Bethencourt + + * plugins/elements/gstfakesrc.c: + fakesrc: mark the pattern property as unused + Revert the previous commit which removes the pattern property of fakesrc because + doing so will break ABI. Bringing the property back but marking it as unused + in the property string. + https://bugzilla.gnome.org/show_bug.cgi?id=737683 + +2014-10-03 09:01:15 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + Revert "baseparse: don't leak caps in gst_base_parse_process_streamheader" + This reverts commit 5e8b4bf085180f7a4c7ae6ec0f525baeaedd4df8. + This causes refcounting criticals in the baseparse unit test. + +2014-10-02 13:45:34 +0100 Luis de Bethencourt + + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + fakesrc: removing unused pattern option + Eventhough the "pattern" property of fakesrc can be set, it is never used. The + only pattern supported is the default 0x00 -> 0xff, and if a pattern is set by + the user it is ignored. Removing the unused property and variable. + https://bugzilla.gnome.org/show_bug.cgi?id=737683 + +2014-10-02 14:55:22 +0300 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Add missing break in switch + +2014-10-02 11:00:32 +0300 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: update segment position on GAP events to calculate levels properly + https://bugzilla.gnome.org/show_bug.cgi?id=737498 + +2014-10-02 10:57:43 +0300 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: update segment position on GAP events to calculate levels properly + https://bugzilla.gnome.org/show_bug.cgi?id=737498 + +2014-09-27 20:10:34 +0200 Matej Knopp + + * plugins/elements/gstmultiqueue.c: + multiqueue: update segment position on GAP events to calculate levels properly + https://bugzilla.gnome.org/show_bug.cgi?id=737498 + +2014-10-02 03:30:24 +0200 Matej Knopp + + * libs/gst/base/gstbaseparse.c: + baseparse: don't leak caps in gst_base_parse_process_streamheader + https://bugzilla.gnome.org/show_bug.cgi?id=737762 + +2014-10-02 10:13:28 +0300 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: Push pending events before a buffer also if upstream never configured caps but we have srcpad caps already + Otherwise we never send pending events downstream that arrive after we + configured caps on the srcpad. + https://bugzilla.gnome.org/show_bug.cgi?id=737735 + +2014-09-29 17:48:29 +0300 Sebastian Dröge + + * gst/gsturi.c: + uri: Don't unconditionally use g_list_copy_deep() + We don't depend on GLib 2.34 yet and just for this seems a bit useless. + https://bugzilla.gnome.org/show_bug.cgi?id=737584 + +2014-09-29 16:22:47 +0300 Sebastian Dröge + + * configure.ac: + * gst/gsturi.c: + uri: Include our own BSD licensed copy of strcasestr() for Windows and others + +2014-09-29 15:54:37 +0300 Sebastian Dröge + + * gst/gsturi.c: + uri: Fix compiler warnings with gcc + These are actually not true. + gsturi.c: In function '_gst_uri_string_to_table.constprop': + gsturi.c:1316:27: error: 'pct_kv_sep' may be used uninitialized in this function [-Werror=maybe-uninitialized] + for (next_sep = strcasestr (value, pct_kv_sep); next_sep; + ^ + gsturi.c:1283:24: error: 'pct_part_sep' may be used uninitialized in this function [-Werror=maybe-uninitialized] + next_sep = strcasestr (next_sep + 1, pct_part_sep)) { + ^ + +2014-09-29 12:19:35 +0300 Sebastian Dröge + + * gst/gsturi.c: + uri: Fix memory leak in gst_uri_join() + The merged path segments are a deep-copied list and we need to free the + contained strings too instead of just the list nodes themselves. + +2014-07-31 22:18:53 +0100 David Waring + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: + * gst/gsturi.h: + * tests/check/gst/gsturi.c: + * win32/common/libgstreamer.def: + GstUri: Add GstUri miniobject to handle URIs in an RFC 3986 compliant fashion + https://bugzilla.gnome.org/show_bug.cgi?id=725221 + +2014-09-27 13:57:42 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + scripts: add gst-rpicamsrc to gst-uninstalled + +2014-09-25 21:21:09 +0200 Stefan Sauer + + * gst/gstelement.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gstvalue.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstfilesrc.c: + * tests/check/tools/gstinspect.c: + * tools/gst-inspect.c: + fixme: bump leftover 0.11 fixme comments + +2014-09-25 21:04:23 +0200 Stefan Sauer + + * gst/gstevent.c: + event: 'newsegment' to 'segment' in the docs + Brings the api-docs in sync with the 1.0 api rename. + +2014-09-25 20:23:31 +0200 Stefan Sauer + + * libs/gst/base/gstbasesrc.c: + basesrc: move the quick return up + Don't assign local vars if we skip anyway. Add logging for failure conditio + +2014-09-25 19:01:52 +0100 Tim-Philipp Müller + + * Makefile.am: + * common: + tests: parallelise 'make valgrind' + Use $(MAKE) instead of 'make' inside the Makefile, + otherwise the make will run as if -j1 had been + specified and complain about the job server not + being available, and with $(MAKE) in inherits the + parent make's settings it seems. + Upgrade common submodule for parallel check-valgrind. + Let this settle a bit before upgrading the other modules. + +2014-09-25 18:57:32 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: update .def file + It's sorted. If it's unsorted, make check-exports fails. + +2014-09-25 18:55:03 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: remove confusing warning about running under valgrind + We're not actually doing anything differently anywhere when + we detect that we're running under valgrind, so let's not + print that confusing message that makes people wonder how + they can switch it off so they can valgrind the normal + code paths. Seeing that we're not doing that nor have done + so in the last 10 years we might just as well remove the + entire check actually. + +2014-09-25 16:21:51 +0100 Tim-Philipp Müller + + * tests/check/libs/baseparse.c: + tests: fix caps leak in baseparse unit test + +2014-09-25 14:54:23 +0200 Jonas Holmberg + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + * tests/check/libs/flowcombiner.c: + * win32/common/libgstbase.def: + flowcombiner: add a gst_flow_combiner_clear() method + https://bugzilla.gnome.org/show_bug.cgi?id=737359 + API: gst_flow_combiner_clear() + +2014-09-24 10:11:54 +0200 Thibault Saunier + + * scripts/gst-uninstalled: + scripts: Handle gst-python in gst-uninstalled + https://bugzilla.gnome.org/show_bug.cgi?id=709082 + +2014-06-03 14:23:30 +0200 Thibault Saunier + + * plugins/elements/gstcapsfilter.c: + capsfilter: Remove EOS event from pending_event list on FLUSH_STOP + https://bugzilla.gnome.org/show_bug.cgi?id=709868 + +2014-09-22 14:27:05 +0100 William Manley + + * gst/gstbuffer.c: + docs: Fix GstBuffer typo "memory bock" -> "memory block" + https://bugzilla.gnome.org/show_bug.cgi?id=737117 + +2014-09-22 17:27:31 +0100 William Manley + + * gst/gstbuffer.c: + docs: Improve gst_buffer_get_meta() to clear up confusion + I was confused by the existence of `gst_buffer_get_meta` as it suggested + to me that you should only attach one of any type of GstMeta to a buffer. + It's perfectly fine to attach multiple from a single API so I'm + documenting that here. + https://bugzilla.gnome.org/show_bug.cgi?id=737129 + +2014-09-22 19:05:32 +0200 Marcin Kolny + + * gst/gstdatetime.h: + datetime: added missing include directives + https://bugzilla.gnome.org/show_bug.cgi?id=737133 + +2014-09-23 14:31:29 +0200 Thibault Saunier + + * plugins/elements/gstqueue.c: + queue: Do not forget to release the QUEUE_LOCK in the out_flow_error path + Avoiding deadlocks! + +2014-09-23 12:53:18 +0200 Stefan Sauer + + * libs/gst/base/gstbasesrc.h: + docs: fix a small contradition in the docs + The vmethod get_size() shall return the size in 'format' as configured by + _set_format(). + +2014-09-22 09:33:04 +0200 Thibault Saunier + + * plugins/elements/gstqueue.c: + queue: Do not hold GST_QUEUE_LOCK while posting ERROR messages + This might create deadlocks and we need to avoid holding element + specific lock while posting messages + For example a deadlock will happen if while posting the message, + someone connected on the bus (sync) tries to DOT the pipeline. + https://bugzilla.gnome.org/show_bug.cgi?id=737102 + +2014-09-19 12:02:46 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: do not post buffering messages holding the lock + It might cause deadlocks to post messages while holding the queue2 + lock. To avoid this a new boolean flag is set whenever a new + buffering percent is found. The message is posted after the lock + is released. + To make sure the buffering messages are posted in the right order, messages + are posted holding another lock. This prevents 2 threads trying to post + messages at the same time. + https://bugzilla.gnome.org/show_bug.cgi?id=736969 + +2014-09-19 09:42:10 +0530 Ravi Kiran K N + + * gst/gsturi.c: + gsturi: Remove unnecessary code + gst_uri_handler_set_uri() function has new_uri, location and colon + are not necessary, they can be removed. + https://bugzilla.gnome.org/show_bug.cgi?id=736877 + +2014-09-19 00:33:58 +0100 Tim-Philipp Müller + + * docs/pwg/advanced-tagging.xml: + * docs/pwg/intro-basics.xml: + docs: pwg: fix some links to the API docs + https://bugzilla.gnome.org/show_bug.cgi?id=736762 + +2014-09-18 18:55:47 +0100 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: remove FIXME + https://bugzilla.gnome.org/show_bug.cgi?id=735878 + +2014-09-17 21:49:18 -0400 Olivier Crête + + * gst/gst.c: + gst: Fix spelling error + Thank to Adrian Owen for reporting this error. + https://bugzilla.gnome.org/show_bug.cgi?id=736839 + +2014-09-17 17:17:10 +0200 Ognyan Tonchev + + * plugins/elements/gsttypefindelement.c: + typefindelement: do not leak sticky events in flush_stop + https://bugzilla.gnome.org/show_bug.cgi?id=736813 + +2014-09-12 14:42:23 +0200 Stefan Sauer + + * gst/gstinfo.c: + info: avoid global variable for log_file + Use user_data to pass the log_file handle to the logger-function. + If one wants to change the log target (e.g. GST_DEBUG_FILE), simply call + gst_debug_remove_log_function() and re-add the handler with the new log-target + using gst_debug_add_log_function (). + +2014-09-16 13:48:18 +0200 Ognyan Tonchev + + * gst/gstevent.c: + event: add annotations to gst_event_parse_toc_select() + https://bugzilla.gnome.org/show_bug.cgi?id=736739 + +2014-09-11 18:01:58 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: do not post messages holding the lock + It might cause deadlocks to post messages while holding the multiqueue + lock. To avoid this a new boolean flag is set whenever a new buffering percent + is found. The message is posted after the lock can be released. + To make sure the buffering messages are posted in the right order, messages + are posted holding another lock. This prevents 2 threads trying to post + messages at the same time. + https://bugzilla.gnome.org/show_bug.cgi?id=736295 + +2014-09-16 16:07:40 +0200 Wim Taymans + + * docs/pwg/other-base.xml: + docs: fix typo + +2014-09-16 12:17:48 +0200 Ognyan Tonchev + + * gst/gstquery.c: + query: Add annotations to gst_query_add_allocation_pool() + https://bugzilla.gnome.org/show_bug.cgi?id=736736 + +2014-09-15 16:38:17 +0200 Aurélien Zanelli + + * libs/gst/base/gstbasesrc.c: + basesrc: handle reference in set_allocation rather than in prepare_allocation + Otherwise we can forget to unref objects in error cases. + https://bugzilla.gnome.org/show_bug.cgi?id=736680 + +2014-09-15 13:06:40 +0300 Sebastian Dröge + + * libs/gst/check/gstcheck.c: + check: Use the name parameter of gst_check_setup_src_pad_by_name() and the sink variant + This was hardcoded to "sink" / "src" by accident in previous refactoring. + +2014-09-13 20:12:52 +0100 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstvalve.c: + coreelements: mark properties with MUTABLE_PLAYING + +2014-09-11 15:52:32 +0200 Thibault Saunier + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Add a function to check destruction of objects + Add a method letting people to ensure that unreffing one object + leads to its destruction, and possibly the destruction of more object + (think destruction of a GstBin etc...). + https://bugzilla.gnome.org/show_bug.cgi?id=736477 + +2014-09-12 14:10:40 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: don't list pad functions + Don't print all the different pad functions, it's just + confusing and no one has ever needed to know this for + anything ever anyway, it's just useless information. + Besides, we also label the default implementations as + 'custom' implementations (the code that tries to + prevent that doesn't actually work it seems). + https://bugzilla.gnome.org/show_bug.cgi?id=736377 + +2014-09-12 15:22:19 +0300 Sebastian Dröge + + * gst/gstpad.c: + pad: Make sure the buffer to get/pull_range() has at least the requested size + https://bugzilla.gnome.org/show_bug.cgi?id=735861 + +2014-09-05 18:36:02 +0000 Tiago + + * libs/gst/check/gstcheck.c: + check: Adding documentation to the gst_check_setup_sink_pad_by_name function + https://bugzilla.gnome.org/show_bug.cgi?id=734190 + +2014-09-10 14:53:00 +0200 Ognyan Tonchev + + * gst/gstquery.c: + query: add annotations to gst_query_set_nth_allocation_pool() + https://bugzilla.gnome.org//show_bug.cgi?id=736424 + +2014-09-11 09:35:17 +0200 Rémi Lefèvre + + * plugins/elements/gstvalve.c: + valve: fix typo in description + https://bugzilla.gnome.org/show_bug.cgi?id=736455 + +2014-09-09 20:43:02 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.h: + baseparse: minor docs fix + +2014-09-07 01:30:16 -0300 Thiago Santos + + * plugins/elements/gstdataurisrc.c: + Revert "dataurisrc: Remove unnecessary else if condition" + This reverts commit 3024ae9c38490817a76c83feab3c8472989cafad. + The *buf can be NULL or not depending if the caller of gst_pad_get_range + function provided or not a buffer. + +2014-09-04 13:38:21 +0530 Vineeth T M + + * plugins/elements/gstdataurisrc.c: + dataurisrc: Remove unnecessary else if condition + In gst_data_uri_src_create(), buf cannot be NULL, hence + else if (*buf != NULL) will be invalid so removing the + else if condition and adding a check to unreference buf + in else condition, just in case + https://bugzilla.gnome.org/show_bug.cgi?id=735861 + +2014-09-03 17:38:16 +0100 Tim-Philipp Müller + + * gst/gstdevicemonitor.c: + devicemonitor: fix typo in sample code in docs + https://bugzilla.gnome.org/show_bug.cgi?id=735975 + +2014-08-25 11:34:48 +0200 Wim Taymans + + * tests/check/gst/gstpad.c: + tests: add flush-stop on inactive pad test + Check that pushing flush-stop on an inactive pad does not clear the + flushing flag. + +2014-08-21 15:49:17 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't accept flush-stop on inactive pads + Inactive pads should at all times have the flushing flag set. This means + that when we get a flush-stop on an inactive pad we must ignore it. + On sinkpads, make this more explicit. We used to not clear the flush + flag but remove the events and then return an error because the flushing + flag was set. Now just simply refuse the event without doing anything. + On srcpads, check that we are trying to push a flush-stop event and + refuse it. We would allow this and mark the srcpad as non-flushing + anymore. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=735357 + +2014-08-27 17:06:57 +0530 Ravi Kiran K N + + * plugins/elements/gstoutputselector.c: + output-selector: Send all events to active src pad and EOS to all src pads + Fixes tests/icles/output-selector-test + https://bugzilla.gnome.org/show_bug.cgi?id=729811 + +2014-09-02 12:11:44 +0530 Vineeth T M + + * plugins/elements/gstdataurisrc.c: + dataurisrc: Make get_uri() threadsafe + https://bugzilla.gnome.org/show_bug.cgi?id=735861 + +2014-08-28 17:24:56 +0200 Guillaume Desmottes + + * docs/manual/advanced-dataaccess.xml: + manual: fix typo in advanced-dataaccess.xml + https://bugzilla.gnome.org/show_bug.cgi?id=735609 + +2014-08-26 20:14:40 +0200 Arnaud Vrac + + * gst/gstbuffer.c: + buffer: do not touch memory tag flag when copying buffer flags + The tag memory flag will be set later if the memory is also copied. This + patch avoids buffers being freed needlessly in bufferpools. + https://bugzilla.gnome.org/show_bug.cgi?id=735574 + +2014-07-15 16:06:49 +0200 Linus Svensson + + * gst/gstbus.c: + bus: gst_bus_add_watch() can return 0 on error + Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=735195 + +2014-08-25 13:44:30 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: handle streamheaders by prepending them to the stream + Add a first_buffer boolean state flag to have baseparse do actions + before pushing data. This is used to check the caps for streamheader + buffers that are prepended to the stream, but only if the first buffer + isn't already marked with the _HEADER flag. In this case, it is assumed + that the _HEADER marked buffer is the same as the streamheader. + https://bugzilla.gnome.org/show_bug.cgi?id=735070 + +2014-08-27 11:01:01 +0300 Sebastian Dröge + + * plugins/elements/gstconcat.c: + concat: Allow seeking on the currently playing stream + This is consistent with the stream time reporting. + +2014-08-23 12:24:27 +0100 Tim-Philipp Müller + + * gst/gstpad.h: + pad: add g-i 'transfer full' annotations to chain and chain_list functions + https://bugzilla.gnome.org/show_bug.cgi?id=735210 + +2014-08-22 10:32:38 +0200 Guillaume Desmottes + + * gst/gstpad.h: + pad: annotate GstPadEventFunction event with 'transfer full' + The callback is supposed to take ownership of the event so + best to be explicit about it. + https://bugzilla.gnome.org/show_bug.cgi?id=735210 + +2014-08-20 12:55:51 +0200 Linus Svensson + + * tests/check/elements/queue.c: + tests: add test that triggers deadlock in state change of queue + When receiving FLASH_STOP in a state transition to READY, a queue + element can end up with an active task that will never end. + https://bugzilla.gnome.org/show_bug.cgi?id=734688 + +2014-08-21 14:02:16 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + queue: fix race when flush-stop event comes in whilst shutting down + Don't re-start the queue push task on the source pad when a + flush-stop event comes in and we're in the process of shutting + down, otherwise that task will never be stopped again. + When the element is set to READY state, the pads get de-activated. + The source pad gets deactivated before the queue's own activate_mode + function on the source pads gets called (which will stop the thread), + so checking whether the pad is active before re-starting the task on + receiving flush-stop should be fine. The problem would happen when the + flush-stop handler was called just after the queue's activate mode + function had stopped the task. + Spotted and debugged by Linus Svensson + https://bugzilla.gnome.org/show_bug.cgi?id=734688 + +2014-08-06 14:01:09 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * tests/check/libs/bytereader.c: + * win32/common/libgstbase.def: + bytereader: add gst_byte_reader_peek_sub_reader() and _get_sub_reader() + Adds API to get or peek a sub-reader of a certain size from + a given byte reader. This is useful when parsing nested chunks, + one can easily get a byte reader for a sub-chunk and make + sure one never reads beyond the sub-chunk boundary. + API: gst_byte_reader_peek_sub_reader() + API: gst_byte_reader_get_sub_reader() + +2014-07-25 16:39:40 +0200 Aurélien Zanelli + + * libs/gst/base/gstbasesrc.c: + docs: make explicit that the caps passed to gst_base_src_set_caps() are 'tranfer none' + https://bugzilla.gnome.org/show_bug.cgi?id=733741 + +2014-08-14 18:53:40 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + inputselector: always proxy caps query + Otherwise it would only be proxied for the active pad which can lead + upstream to use an incompatible caps for the downstream element. + Even if a reconfigure event is sent upstream when the pad is activated, this + will save the caps reconfiguration if it is already using an acceptable caps. + +2014-08-14 14:37:56 +0100 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.h: + base: and fix build with new g-i again + +2014-08-14 14:25:06 +0100 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.h: + base: remove g-i annotation that makes older g-ir-scanner crash + Just remove one skip annotation that causes this: + ** (g-ir-compiler:12458): ERROR **: Caught NULL node, parent=empty + with older g-i versions such as 1.32.1. + +2014-08-13 14:12:00 +0200 Philippe Normand + + * gst/gstbus.c: + bus: destroy signal watch from the context it was mapped to + Don't rely on g_source_remove() because it operates on the main + context. If a signal watch was added to a new thread-default context + g_source_remove() would have no effect. So simply use + g_source_destroy() to avoid this problem. + Additionally the source_id was removed from GstBusPrivate because it + was redundant with the signal watch GSource also stored in that + structure. + https://bugzilla.gnome.org/show_bug.cgi?id=734716 + +2014-08-07 12:18:04 +0200 Thibault Saunier + + * plugins/elements/gstmultiqueue.c: + multiqueue: Not post BUFFERING message if one of the singlequeue doesn't need it + Imagine the following 'pipeline' + -------------- + p1/| 'fullqueue' |--- 'laggy' downstream + --------- / | | + -| demuxer | | multiqueue | + --------- \ | | + p2\| 'emptyqueue' |--- 'fast' downstream + -------------- + In the case downstream of one single queue (fullqueue) has (a lot of) latency + (for example for reverse playback with video), we can end up having the other + SingleQueue (emptyqueue) emptied, before that fullqueue gets + unblocked. In the meantime, the demuxer tries to push on fullqueue, and + is blocking there. + In that case the current code will post a BUFFERING message on the bus when + emptyqueue gets emptied, that leads to the application setting the pipeline state to + PAUSED. So now we end up in a situation where 'laggy downstream' is + prerolled and will not unblock anymore because the pipeline is set to + PAUSED, the fullequeue does not have a chance to be emptied and + the emptyqueue can not get filled anymore so no more BUFERRING message + will be posted and the pipeline is stucked in PAUSED for the eternity. + Making sure that we do not try to "buffer" if one of the single queue + does not need buffering, prevents this situtation from happening though it lets the + oportunity for buffering in all other cases. + That implements a new logic where we need all singlequeue to need + buffering for the multiqueue to actually state buffering is needed, + taking the maximum buffering of the single queue as the reference point. + https://bugzilla.gnome.org/show_bug.cgi?id=734412 + +2014-08-13 13:01:23 +0300 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Only handle flow returns < EOS as errors, not e.g. flushing + +2014-08-13 12:40:37 +0300 Sebastian Dröge + + * gst/gstbin.c: + bin: Use allow-none instead of nullable until we depend on a new enough GI version + +2014-08-13 12:39:47 +0300 Sebastian Dröge + + * gst/gstbin.c: + bin: gst_bin_new() can accept NULL as name + +2014-08-13 12:37:08 +0300 Sebastian Dröge + + * gst/gstelement.c: + element: Clarify docs about gst_element_get_request_pad() and remove deprecation part + This function is not really pad or slow for the common case of requesting a + pad with the name of the template. It is only slower if you to name your pads + directly instead of letting the element handle it. + Also there's no reason to deprecate it in favor of a more complicated function + for the common case. + +2014-08-13 12:20:51 +0300 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Post errors if we receive EOS after downstream reported an error + There will be no further data flow that would allow us to propagate the + error upstream, causing nobody at all to post an error message. + +2014-08-13 12:15:03 +0300 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Post errors when receiving EOS after downstream returned an error + There might be no further data flow that would allow us to propagate the + error upstream, causing nobody to post an error at all. + +2014-08-13 12:10:39 +0300 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Post errors ourselves if they are received after EOS + After EOS there will be no further buffer which could propagate the + error upstream, so nothing is going to post an error message and + the pipeline just idles around. + +2014-08-12 20:03:06 +0530 Arun Raghavan + + * gst/gstpad.c: + docs: Trivial pad documentation fix + Presumably a copy-pasto. + +2014-08-08 09:54:02 +0200 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/concat.c: + concat: Add unit tests for concat element + +2014-08-08 09:13:50 +0200 Sebastian Dröge + + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * plugins/elements/gstconcat.c: + concat: Add documentation and integrate into documentation build + +2014-08-07 14:42:44 +0200 Sebastian Dröge + + * plugins/elements/Makefile.am: + * plugins/elements/gstconcat.c: + * plugins/elements/gstconcat.h: + * plugins/elements/gstelements.c: + concat: Add new element that concatenates multiple streams + https://bugzilla.gnome.org/show_bug.cgi?id=734470 + +2014-08-09 10:57:56 -0300 Thiago Santos + + * tests/check/gst/gstcaps.c: + tests: caps: add check for caps with features intersection + Checks that a caps without features doesn't intersect with + one that has features + +2014-08-07 14:54:37 +0100 Tim-Philipp Müller + + * tests/examples/controller/audio-example.c: + * tests/examples/controller/text-color-example.c: + examples: controller: fix typo in comments + +2014-08-06 13:58:22 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.h: + bytereader: use unchecked inline variant for get_remaining in more places + We've already done the g_return_*_if_fail (reader != NULL) + dance in those places, so no need to do it again. + +2014-08-06 14:43:08 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Ghostpads can be request pads too but check if the pad has a template + Otherwise we dereference NULL in some cases and crash. + +2014-08-06 12:34:42 +0200 Sebastian Rasmussen + + * docs/manual/appendix-programs.xml: + * tests/check/gst/gstbin.c: + * tests/check/pipelines/parse-launch.c: + * tests/examples/launch/mp3parselaunch.c: + tests: Add missing unrefs of objects after use + Unreffing the objects returned by gst_bin_get_by_name() and + gst_pipeline_get_use() were missing in several tests, so add these. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=734345 + +2014-08-06 12:55:57 +0200 Sebastian Dröge + + * tests/check/gst/gstutils.c: + utils: Fix unititialized variable compiler warning + +2014-07-13 15:31:08 +0200 Sebastian Rasmussen + + * tests/check/gst/gstutils.c: + tests: Add test verifying gst_element_link_pads_full() + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=733119 + +2014-07-13 15:28:32 +0200 Sebastian Rasmussen + + * gst/gstutils.c: + utils: Unref/release pads in error cases when linking pads + Previously gst_element_link_pads_full() forgot to unreference or release + request pads in several error cases. Also comments were added mentioning + why releasing is not necessary in some places. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=733119 + +2014-08-01 17:27:39 -0300 Tiago Cesar Katcipis + + * libs/gst/check/gstcheck.c: + gstcheck: add docs for gst_check_setup_src_pad_by_name() + https://bugzilla.gnome.org/show_bug.cgi?id=734142 + +2014-07-31 18:32:03 +0200 Edward Hervey + + * Makefile.am: + * common: + Makefile: Add usage of build-checks step + Allows building checks without running them + +2014-07-30 15:46:22 +0300 Mohammed Sameer + + * gst/gstbufferpool.c: + bufferpool: Add missing error checking to default_alloc_buffer() + default_alloc_buffer() calls gst_buffer_new_allocate() but does not check for + failed allocation. + This patch makes default_alloc_buffer() return an error (GST_FLOW_ERROR) if + buffer allocation fails. + https://bugzilla.gnome.org/show_bug.cgi?id=733974 + +2014-07-29 14:21:33 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: avoid using infinite buffers limit if finite is requested + If the current max-buffers limit it infinite and a finite value is + requested, switch to the MAX (requested, current-value) to set some + limit but not below what we know that we've needed so far. + https://bugzilla.gnome.org/show_bug.cgi?id=733637 + https://bugzilla.gnome.org/show_bug.cgi?id=733837 + +2014-07-24 22:02:58 +0200 Sebastian Rasmussen + + * gst/parse/grammar.y: + parse: Unref reference to enclosing bins + Previously all reference to enclosing bins of an element were leaked + when doing delaying setting a property. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=733697 + +2014-07-27 02:37:08 +0000 Руслан Ижбулатов + + * tools/gst-launch.c: + gst-launch: Support SIGINT (Ctrl+C) on W32 + W32 has no SIGINT, but it does have SetConsoleCtrlHandler(), which sets up + a handler for Ctrl+C. + https://bugzilla.gnome.org/show_bug.cgi?id=733814 + +2014-07-27 03:06:16 +0000 Руслан Ижбулатов + + * gst/gstpoll.c: + poll: Prevent false-negative from WAKE_EVENT() on W32 + SetEvent() seems to not call SetLastError(0) internally, so checking last + error after calling SetEvent() may return the error from an earlier W32 API + call. Fix this by calling SetlastError(0) explicitly. + Currently WAKE_EVENT() code is cramped into a macro and doesn't look to be + entirely correct. Particularly, it does not check the return value of + SetEvent(), only the thread-local W32 error value. It is likely that SetEvent() + actually just returns non-zero value, but the code mistakenly thinks that the + call has failed, because GetLastError() seems to indicate so. + https://bugzilla.gnome.org/show_bug.cgi?id=733805 + +2014-07-26 14:42:54 +0100 Tim-Philipp Müller + + * gst/gst.h: + gst: include atomicqueue.h again in gst.h + It's a public header of gstreamer core, so #include + should make the API available. + +2014-07-25 11:45:56 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefindelement: remove prototype for function that no longer exists + +2014-07-24 14:39:11 -0300 Thiago Santos + + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * tests/check/libs/bytereader.c: + * win32/common/libgstbase.def: + bytereader: add gst_byte_reader_masked_scan_uint32_peek + Adds gst_byte_reader_masked_scan_uint32_peek just like + GstAdapter has a _peek and non _peek version + Upgraded tests to check that the returned value is correct in the + _peek version + API: gst_byte_reader_masked_scan_uint32_peek + https://bugzilla.gnome.org/show_bug.cgi?id=728356 + +2014-06-26 14:09:25 +0100 Tim-Philipp Müller + + * gst/gstbufferlist.c: + bufferlist: pre-allocate buffer array in one go with the buffer list + We can now create and free a buffer list with one slice alloc/free + call in most cases, instead of one slice alloc/free for the list, + one slice alloc/free for the GArray, and one malloc/free for the + GArray array. In practice we know the max size of our buffer list + from the start, so can avoid reallocs. + https://bugzilla.gnome.org/show_bug.cgi?id=732284 + +2014-07-23 21:27:48 +0200 Stefan Sauer + + * gst/gst_private.h: + * gst/gstdebugutils.c: + private: allow internal access to the debug base-time + Moving the extern to the head lets us access this from other parts as well. This + is neeed in the tracer branch. + +2014-07-23 00:15:17 +0530 Arun Raghavan + + * scripts/git-update.sh: + scripts: Use git pull --rebase + No point introducing redundant merge commits. + +2014-07-21 12:41:08 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/gst/gsttaglist.c: + Revert "tests: taglist: add basic test for taglists serialization" + This reverts commit 85d23d19b7de40541d63b0bc76d8b646c321af26. + There was already a gsttag.c tests file, this test has been merged + in it in the previous commit + +2014-07-21 12:40:47 -0300 Thiago Santos + + * tests/check/gst/gsttag.c: + tests: tag: add the empty taglist serialization test + Adds the test to the appropriate and already existing file. + +2014-07-14 18:46:54 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/gst/gsttaglist.c: + tests: taglist: add basic test for taglists serialization + Make sure it works with empty taglists + +2014-07-14 18:25:50 -0300 Thiago Santos + + * tests/check/gst/gststructure.c: + tests: gststructure: serialization of tag event structure + Adds a test that checks that the serialization of a tag event structure + works without problems + https://bugzilla.gnome.org/show_bug.cgi?id=733131 + +2014-07-14 18:23:43 -0300 Thiago Santos + + * gst/gstvalue.c: + gstvalue: add GstTagList compare function + When serializing GstStructures from events in GDP it will add a taglist + as a GstStructure field, having the compare function allows comparison of + GstStructures to check if the serialized/deserialized version matches the + original one, among other cases. + https://bugzilla.gnome.org/show_bug.cgi?id=733131 + +2014-07-09 15:48:10 +0200 Srimanta Panda + + * plugins/elements/gstfunnel.c: + funnel: Fix for racy EOS event handling + When eos events are forwarded simultaneouly from two sinkpads on + funnel, it doesnot forward the eos to sourcepad. The reason is + sticky events are stored after the event callbacks are returned. + Therefore while one is about to store the sticky events on the its + sinkpad, other sinkpad starts checking for the eos events on all other + sinkpads and assumes eos is not present yet. + https://bugzilla.gnome.org/show_bug.cgi?id=732851 + +2014-07-17 16:05:00 +0200 Sebastian Dröge + + * tests/check/gst/gstpipeline.c: + pipeline: Add unit test for resetting of the start time + Also check if this properly affects basesink elements to not + report the old start time but the real current position when + setting to PAUSED again. + +2014-07-15 18:19:24 +0200 Sebastian Dröge + + * gst/gstpipeline.c: + pipeline: Reset the start time when going from PAUSED to READY too + +2014-07-15 17:19:10 +0200 Sebastian Dröge + + * gst/gstpipeline.c: + pipeline: Reset start time in READY->PAUSED before chaining up + Otherwise bin will change the state of the child elements without + distributing the new start time. + +2014-06-28 17:58:26 +0100 Tim-Philipp Müller + + * plugins/elements/gstelements_private.c: + elements: improve buffer flags to string utility function + Avoid relocations and refactor so that we don't calculate + the fixed and known at compile time maximum string size + every time. Also skip the mini object flags which we are + not going to print anyway. + +2014-07-19 18:04:31 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.4.0 === + +2014-07-19 16:46:41 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.4.0 + +2014-07-19 16:21:20 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-07-19 12:16:58 +0200 Sebastian Dröge + + * po/da.po: + * po/sv.po: + po: Update translations + +2014-07-17 15:53:53 +0200 Thibault Saunier + + * libs/gst/base/gstbaseparse.c: + baseparse: Return FLOW_FLUSHING when pushing a frame on a pad that has been flushed + When going to READY, it is possible that we are still pusing a frame but that + our srcpad has already been set to flushing. In that case we should not + post any error on the bus but instead cleanly return FLOW_FLUSHING. + https://bugzilla.gnome.org/show_bug.cgi?id=733320 + +2014-07-17 07:07:36 +0200 Edward Hervey + + * plugins/elements/gsttypefindelement.c: + typefindelement: Propagate input buffer PTS and DTS + The initial buffers (that were used for timestamping) might have PTS + and DTS set. In order to forward those properly, get the initial + PTS/DTS from the adapter and set them on the reconstructed output + buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=733291 + +2014-07-12 17:01:23 +0200 Sebastian Rasmussen + + * gst/gstdebugutils.c: + debugutils: Unref pad template after use + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=733121 + +2014-07-14 18:10:45 -0300 Thiago Santos + + * gst/gst.c: + gst: init taglist gtype to use it in gstvalue + Otherwise it will have a 0 value and GstTagList won't be found + for GstValue functions (serialization/deserialization) + https://bugzilla.gnome.org/show_bug.cgi?id=733131 + +=== release 1.3.91 === + +2014-07-11 10:46:01 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.3.91 + +2014-07-11 10:41:20 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-07-11 08:51:08 +0200 Sebastian Dröge + + * po/da.po: + * po/vi.po: + po: Update translations + +2014-07-05 18:29:29 +0200 Sebastian Rasmussen + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * gst/gstcaps.h: + * gst/gstdevice.c: + * gst/gstdeviceprovider.c: + * gst/gstdeviceproviderfactory.c: + * gst/gsttoc.h: + * gst/gstvalue.c: + * libs/gst/check/gstcheck.c: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + docs: Fix documentation typos and inconsistencies + * GstGlobalDeviceMonitor was renamed to GstDeviceMonitor + * Expand GST_MESSAGE_DEVICE to the full enum value names + * Correct the incorrect references to the GstDeviceProvider interfaces + * Describe caps arguments for gstcheck interface + * Add missing docs for GstNetAddressMeta and its add function + * Add docs for toc helper macros + * Avoid refering to GstValueList type as done elsewhere + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732786 + +2014-07-05 17:13:21 +0200 Sebastian Rasmussen + + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + docs: Cleanup interface references in docs + * Delete references to removed interfaces + * Add missing documentation sections + * Fix duplicate interface references for GstDevice + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732786 + +2014-07-08 11:17:41 +0200 Sebastian Dröge + + * plugins/elements/gstfilesrc.c: + * plugins/elements/gsttee.c: + * tools/gst-launch.1.in: + docs: There is no decodebin2 anymore, don't pretend otherwise + +2014-07-07 16:14:32 -0300 Thiago Santos + + * plugins/elements/gstfdsrc.c: + fdsrc: fix error setting when uri is invalid + Elements should always set the GError + +2014-07-06 12:13:04 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + libs: gstcheck: check that mutex is locked before g_cond_wait*() is called + Sanity check to catch problems in unit test. + +2014-07-06 12:12:20 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + libs: gstcheck: init and clear global mutex and cond variables + +2014-07-06 12:09:31 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpoll.c: + tests: fix locking in gstpoll unit test + The mutex needs to be locked when g_cond_wait*() is + called. + +2014-07-05 16:24:18 +0100 Matthieu Bouron + + * scripts/gst-uninstalled: + gst-uninstalled: add video and base library paths from -bad + https://bugzilla.gnome.org/show_bug.cgi?id=732770 + +2014-07-04 19:40:28 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: suppress GLib warnings when gst-inspecting deprecated properties + GLib in git will spew a g_warning() when a property marked as + deprecated via param spec flags is accessed. Suppress this by + setting the appropriate environment variable. + +2014-07-03 10:11:02 +0200 Sebastian Dröge + + * gst/gstmessage.h: + message: Work around g-i/pygobject/gjs bug with ~0 in enums + GST_MESSAGE_ANY was considered a long by pygobject and gjs, and thus + couldn't be used in gst_bus_poll() and similar APIs as they expect an + int-typed enum. + Just use 0xffffffff instead for now. + https://bugzilla.gnome.org/show_bug.cgi?id=732633 + +2014-07-02 08:41:18 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: don't use post-GLib 2.32 API in bufferlist test + g_ptr_array_insert() is GLib >= 2.40 + +2014-07-01 12:22:56 +0200 Göran Jönsson + + * gst/gstpad.c: + pad: Don't unlock while iterating over all sticky events for removal + Otherwise we might end up getting the event removed from elsewhere + at the same time while we're unlocked for g_object_notify(). + https://bugzilla.gnome.org/show_bug.cgi?id=732556 + +2014-07-01 19:17:11 +0200 Sebastian Dröge + + * plugins/elements/gstidentity.c: + identity: Proxy the accept-caps query + We always work in passthrough mode so there's no point in doing + something more clever in basetransform. Also the basetransform + code leads to problems with incomplete caps and downstream + elements that use GST_PAD_FLAG_ACCEPT_INTERSECT. + https://bugzilla.gnome.org/show_bug.cgi?id=732559 + +2014-07-01 11:21:53 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasesink.c: + basesink: reset QoS on segment event + This avoids spurious warnings about slow machine when upstream + sends new segments without flushing. + +2014-06-30 23:39:18 -0700 Evan Nemerson + + * gst/gstbufferpool.c: + * gst/gstdevice.c: + * gst/gstdevicemonitor.c: + * gst/gstdeviceprovider.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gsttestclock.c: + introspection: Assorted minor introspection and documentation fixes + https://bugzilla.gnome.org/show_bug.cgi?id=732534 + +2014-06-30 08:59:18 +0000 Guillaume Desmottes + + * gst/gstdevicemonitor.c: + devicemonitor: Stop using g_clear_pointer() + We dont't want to depend on GLib 2.34 for now. + +2014-06-29 19:16:05 +0200 Sebastian Dröge + + * tests/check/libs/sparsefile.c: + sparsefile: Initialize memory in unit test to make valgrind happy + We were writing unitialized stack memory to the file. + +2014-06-28 09:35:21 -0300 Thiago Santos + + * plugins/elements/gstdataurisrc.c: + dataurisrc: fix leak as gst_buffer_replace adds its own ref + So unref the buffer after that otherwise it leaks + +=== release 1.3.90 === + +2014-06-28 10:45:18 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.3.90 + +2014-06-28 10:41:48 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-06-27 10:44:32 +0100 Tim-Philipp Müller + + * gst/gstdevicemonitor.c: + * tests/check/gst/gstdevice.c: + devicemonitor: don't fail when started without any filters + Just show all devices then. + +2014-06-27 10:44:01 +0100 Tim-Philipp Müller + + * gst/gstdeviceproviderfactory.c: + deviceproviderfactory: handle NULL classes argument and match any + +2014-06-26 21:00:40 -0400 Olivier Crête + + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstdevice.c: + device: Add unit tests + +2014-06-26 17:22:25 -0400 Olivier Crête + + * gst/gstdevicemonitor.c: + * gst/gstdeviceprovider.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstmessage.c: + devicemonitor: Improve documentation + +2014-06-26 17:13:12 -0400 Olivier Crête + + * docs/gst/gstreamer-sections.txt: + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * gst/gstdeviceprovider.c: + * gst/gstdeviceproviderfactory.c: + * gst/gstdeviceproviderfactory.h: + * win32/common/libgstreamer.def: + devicemonitor: Make it possible to add multiple filters + Each filter will include a GstCaps and a set of classes to match + +2014-06-26 16:31:51 -0400 Olivier Crête + + * gst/gstdevice.c: + device: Add pre-conditions + +2014-06-26 15:08:46 -0400 Olivier Crête + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * gst/gstglobaldevicemonitor.h: + * win32/common/libgstreamer.def: + GstDeviceMonitor: Rename from GstGlobalDeviceMonitor + +2014-06-26 14:28:09 -0400 Olivier Crête + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/plugins/gstreamer-plugins.hierarchy: + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstdevice.c: + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitorfactory.h: + * gst/gstdeviceprovider.c: + * gst/gstdeviceprovider.h: + * gst/gstdeviceproviderfactory.c: + * gst/gstdeviceproviderfactory.h: + * gst/gstglobaldevicemonitor.c: + * gst/gstglobaldevicemonitor.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * tools/gst-inspect.c: + * win32/common/libgstreamer.def: + DeviceProvider: Rename from DeviceMonitor + +2014-06-26 19:31:33 +0200 Sebastian Dröge + + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + dataqueue: Hide from bindings + Other languages have their own data structures that are more convenient to + use. + https://bugzilla.gnome.org/show_bug.cgi?id=731303 + +2014-06-26 19:30:52 +0200 Sebastian Dröge + + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + queuearray: Hide from bindings + Other languages have their own data structures that are more convenient to use. + https://bugzilla.gnome.org/show_bug.cgi?id=731350 + +2014-05-28 10:14:45 +0100 Philip Withnall + + * gst/gstminiobject.c: + miniobject: Add missing (nullable) annotations + gst_mini_object_replace() can take NULL mini-objects. + https://bugzilla.gnome.org/show_bug.cgi?id=730873 + +2014-06-26 19:02:06 +0200 Sebastian Dröge + + * gst/gstmessage.c: + message: Application and element messages should not have NULL structures + It does not make sense for them. + +2014-06-11 16:19:01 -0700 Evan Nemerson + + * gst/gstbufferpool.c: + * gst/gstelement.c: + * gst/gstinfo.h: + * gst/gstmessage.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstplugin.h: + * gst/gstpreset.c: + * gst/gsttaglist.c: + introspection: add some missing allow-none annotations to in params + https://bugzilla.gnome.org/show_bug.cgi?id=730957 + +2014-06-11 16:06:19 -0700 Evan Nemerson + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstobject.c: + * gst/gstpreset.c: + * gst/gstquery.h: + * gst/gsttoc.c: + * gst/gstvalue.c: + introspection: add nullability annotations to out and inout params + https://bugzilla.gnome.org/show_bug.cgi?id=730957 + +2014-06-11 15:21:34 -0700 Evan Nemerson + + * gst/gstallocator.c: + * gst/gstatomicqueue.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstbus.c: + * gst/gstcapsfeatures.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstcontrolbinding.c: + * gst/gstdatetime.c: + * gst/gstdevicemonitorfactory.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstmemory.c: + * gst/gstmeta.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstpoll.c: + * gst/gstpreset.c: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttaskpool.c: + * gst/gsttoc.c: + * gst/gsttocsetter.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstvalue.c: + introspection: add missing (nullable) annotations to return values + Support for (nullable) was added to G-I at the same time as nullable + return values. Previous versions of G-I will not mark return values as + nullable, even when an (allow-none) annotation is present, so it is + not necessary to add (allow-none) annotations for compatibility with + older versions of G-I. + https://bugzilla.gnome.org/show_bug.cgi?id=730957 + +2014-06-11 17:15:39 -0700 Evan Nemerson + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + base: assorted introspection fixes and additions + https://bugzilla.gnome.org/show_bug.cgi?id=731542 + +2014-06-11 17:12:20 -0700 Evan Nemerson + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstindex.c: + * libs/gst/base/gsttypefindhelper.c: + base: add (nullable) annotations to return values + https://bugzilla.gnome.org/show_bug.cgi?id=731542 + +2014-06-26 14:08:03 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: add another buffer list test case + +2014-06-26 13:24:08 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: port and re-enable buffer list tests + And remove some which don't apply any more. + +2014-06-26 11:58:04 +0300 George Kiagiadakis + + * tests/check/gst/gstcaps.c: + tests: enhance the gstcaps test_features to also test gst_caps_set_features() + Compliments my previous patch for gst_caps_set_features, which would + previously assert and leak the old GstCapsFeatures if the caps already + had a GstCapsFeatures and you were trying to replace it with a new one. + +2014-06-26 11:16:34 +0300 George Kiagiadakis + + * gst/gstcaps.c: + caps: unset the parent refcount of the old features before freeing them in gst_caps_set_features() + Otherwise gst_caps_features_free() asserts and the features structure is leaked + +2014-06-16 19:30:06 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: avoid returning _OK for _NOT_LINKED + When the parser receives non-aligned packets it can push a buffer + and get a not-linked return while still leaving some data still to + be parsed. This remaining data will not form a complete frame and + the subclass likely returns _OK and baseparse would take that + as the return, while it the element is actually not-linked. + This patch fixes this by storing the last flow-return from a push + and using that if a parsing operation doesn't result in data being + flushed or skipped. + https://bugzilla.gnome.org/show_bug.cgi?id=731474 + +2014-06-25 11:40:57 +0100 Tim-Philipp Müller + + * plugins/elements/gstelements_private.c: + elements: fix copyright and remove gtk-doc chunk + Trivial as it may be, this code was mostly copied from + somewhere else. The gtk-doc chunk is not needed, since + it's not public API. + +2014-06-02 22:07:52 -0400 Olivier Crête + + * plugins/elements/gstfilesrc.c: + filesrc: Ignore seek error on non-seekable files + This make it works with FIFOs. + https://bugzilla.gnome.org/show_bug.cgi?id=731176 + +2014-06-22 19:36:14 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.3 === + +2014-06-22 18:07:42 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.3.3 + +2014-06-22 17:15:40 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-06-22 14:23:03 +0200 Sebastian Dröge + + * po/hu.po: + * po/id.po: + * po/sr.po: + * po/zh_TW.po: + po: Update translations + +2014-06-22 12:52:01 +0100 Tim-Philipp Müller + + * tests/check/gst/gstcaps.c: + tests: add unit test for gst_caps_is_any() and _is_empty() + https://bugzilla.gnome.org//show_bug.cgi?id=731704 + +2014-06-22 12:50:42 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: gst_caps_is_any() should return TRUE or FALSE + Not some flag value instead of TRUE. Fixes code like + gst_caps_is_any() == TRUE. + https://bugzilla.gnome.org//show_bug.cgi?id=731704 + +2014-06-01 16:56:41 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstdevice.c: + * gst/gstdevice.h: + * win32/common/libgstreamer.def: + device: rename "klass" and get_klass() to "device-class" and _get_device_class() + There's some precedent in GstElementFactory, but a + "klass" property just seems weird. + +2014-06-20 18:34:44 +0100 Tim-Philipp Müller + + * tests/benchmarks/capsnego.c: + benchmarks: capsnego: add --loops command line option + And default to 50 loops. + +2014-06-20 17:14:52 +0100 Tim-Philipp Müller + + * tests/benchmarks/capsnego.c: + benchmark: capsnego: use GOptionContext for option parsing + +2014-06-19 12:10:23 +0100 Tim-Philipp Müller + + * tests/check/gst/gstvalue.c: + tests: fix compiler warnings in gstvalue tests + Calling GST_VALUE_HOLDS_*(&v) now results in a compiler + warning about value!=NULL always being false, so check + type directly in those cases. + +2014-06-17 22:45:57 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + * gst/gstutils.c: + * gst/gstvalue.h: + value: simplify GST_VALUE_HOLDS for our boxed and fundamental types + Boxed types can't be derived from, and we don't support + deriving from our special fundamental types (the code + checks for GType equality in most places. + +2014-06-20 16:55:06 -0400 Olivier Crête + + * docs/gst/gstreamer-sections.txt: + * gst/gstdevice.c: + * gst/gstdevice.h: + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * gst/gstdevicemonitorfactory.h: + * gst/gstglobaldevicemonitor.c: + * gst/gstglobaldevicemonitor.h: + * gst/gstmessage.c: + GstDevice: Document GstDevice and related classes + +2014-06-16 13:47:55 +0200 Srimanta Panda + + * plugins/elements/gstfunnel.c: + * tests/check/elements/funnel.c: + Fix funnel EOS handling and wrong unittest + When no data is coming from sinkpads and eos events + arrived at one of the sinkpad, funnel forwards the EOS + event to downstream. It forwards the EOS because lastsink pad + is NULL. Also the unit testcase of the funnel is not checking + the correct behavior as it should. The unit test case should + fail if one of the sink pad has already EOS present on it and + we are trying to push one more EOS. + https://bugzilla.gnome.org/show_bug.cgi?id=731716 + +2014-06-19 08:09:55 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: optimise checks for lists + Our fundamental types are non-derivable, so we can + just check for equality. Also avoid doing the same + check multiple times in a couple of places. + +2014-06-19 08:06:31 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: use g_assert() in internal function for already-checked things + So these get compiled out for releases. + +2014-06-19 08:05:40 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: add internal _can_compare_unchecked() + +2014-06-19 08:03:37 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: add internal _list_concat() that takes ownership of input values + Avoids unnecessary copies. + +2014-06-18 19:06:58 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + structure: simplify value type checks in getters + Just check for GType equality in common cases. + +2014-06-19 09:29:18 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Add a FIXME 2.0 for a fraction ranges optimization + Currently we leak the internal representation of them as two GValues that + contain a fraction. Without this we could store fraction ranges as + data[0] = (min_n << 32) | (min_d) + data[1] = (max_n << 32) | (max_d) + and wouldn't require an additional allocation per range. + +2014-06-19 09:23:56 +0200 Sebastian Dröge + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Make sure to cast int range values to guints before storing them + Otherwise negative values will sets all of the 64 bits due to two's + complement's definition of negative values. + Also add a test for negative int ranges. + +2014-06-19 07:57:11 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update exports + +2014-06-19 09:05:18 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Store integer ranges directly in a GValue without additional allocation + Micro optimization to save some allocations. Next step to do this + with fraction ranges too. + +2014-06-19 08:43:02 +0200 Edward Hervey + + * gst/gst_private.h: + gst_private: Fix duplicate definition + +2014-06-19 08:05:03 +0200 Sebastian Dröge + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstallocator.c: + * gst/gstcapsfeatures.h: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttoc.c: + * gst/gsttoc.h: + gst: Store more basic type GTypes in variables + Micro optimization to change a function call to a variable access + for all our basic types. + +2014-06-19 08:04:01 +0200 Sebastian Dröge + + * gst/gstvalue.c: + * gst/gstvalue.h: + value: Store our fundamental type GTypes in variables + Micro optimization to change a function call to a variable access + for all our basic types. + +2014-06-17 07:31:48 +0200 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Speed up gst_value_intersect/_subtract + Both gst_value_intersect and gst_value_subtract will call + gst_value_compare if one of their arguments isn't a list. + gst_value_compare will then re-do a check to see if one of + the arguments is a list (for the special case of comparing a unitary + value with a list of length 1). + The problem is that the various G_VALUE_HOLDS represent an expensive + amount of calling gst_value_compare (almost half of it) to see if + the provided arguments are list. These checks can be done without + when we know that the arguments aren't lists. + * Create a new "nolist" gst_value_compare which avoids that special + case comparision + Benchmarks: + valgrind/callgrind: average speedup in instruction calls for + gst_value_intersect and gst_value_subtract is around 56% (Makes 63% + of the calls it used to take previously) + tests/benchmarks/capsnego: With default settings (depth 4, children 3 + 607 elements), time taken for transition from READY to PAUSED: + Before : 00.391519153 + After : 00.220397492 + 56% of the time previously used, +77% speedup + https://bugzilla.gnome.org/show_bug.cgi?id=731756 + +2014-06-17 14:39:00 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: remove some cruft from the bufferlist test + Buffers no longer carry caps, and bufferlists don't have + groups where buffers may need to be merged into one any more. + +2014-06-16 20:30:13 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: add test for gst_buffer_list_remove() + +2014-06-16 20:29:56 +0100 Tim-Philipp Müller + + * gst/gstbufferlist.c: + bufferlist: fix buffer leak in _remove() + +2014-06-16 09:18:45 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: fix g-i transfer annotations + +2014-06-16 08:41:48 +0200 Edward Hervey + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: Fixed GBoxedCopyFunc + I'll just quote the most interesting man in the world: + "I don't usually push commits, but when I do I don't compile it + first" + +2014-06-14 16:30:49 +0100 Tim-Philipp Müller + + * gst/gstdevicemonitor.h: + * gst/gstglobaldevicemonitor.c: + devicemonitor: some docs additions and fixes + +2014-06-14 16:28:48 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: add exports for new get_type() function + +2014-06-14 11:31:44 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.c: + flowcombiner: keep a ref to the pads we're using + Needed for use via the boxed type. + https://bugzilla.gnome.org/show_bug.cgi?id=731355 + +2014-06-14 10:54:41 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + flowcombiner: add boxed type for bindings + https://bugzilla.gnome.org/show_bug.cgi?id=731355 + +2014-06-11 16:28:51 -0700 Evan Nemerson + + * gst/gstdevice.c: + * gst/gstdevicemonitorfactory.c: + * gst/gstevent.c: + introspection: minor annotation additions + https://bugzilla.gnome.org/show_bug.cgi?id=731541 + +2014-06-11 19:08:04 -0700 Evan Nemerson + + * gst/Makefile.am: + introspection: include gstversion.h in GIR generation + https://bugzilla.gnome.org/show_bug.cgi?id=703021 + +2014-06-10 10:23:13 -0400 Nicolas Dufresne + + * libs/gst/base/gstbytereader.c: + bytereader: Use concistant derefence method + This is minor style fix to not mix *var and var[N]. + +2014-06-10 09:35:38 -0400 Sungho Bae + + * libs/gst/base/gstbytereader.c: + bytereader: Use pointer instead of index access + Currently the scan uses Boyer-moore method and its performance is good. + but, it can be optimized from an implementation of view. + The original scan code is implemented by byte array and index-based access. + In _scan_for_start_code(), the index is increasing from start to end and the + base address of the byte array is referred to as return value. + In the case, index-based access can be replaced by pointer access, which + improve the performance by removing index-related operations. + Its performace is enhanced by approximately 8% on arm-based embedded devices. + Although it seems trivial, it can affect the overall performance because the + _scan_for_start_code() function is very often called when H.264/H.265 video is + played. + In addition, the technique can apply for all architectures and it is good in + view of readability and maintainability. + https://bugzilla.gnome.org/show_bug.cgi?id=731442 + +2014-06-07 10:13:56 +0100 Tim-Philipp Müller + + * gst/gstglobaldevicemonitor.h: + globaldevicemonitor: prettify header + +2014-06-07 09:46:42 +0100 Tim-Philipp Müller + + * tests/check/libs/queuearray.c: + tests: add unit test for queuearray expansion from 1 + https://bugzilla.gnome.org/show_bug.cgi?id=731349 + +2014-06-06 16:36:00 -0700 Evan Nemerson + + * libs/gst/base/gstqueuearray.c: + queuearray: fix expanding size of queue from 1 + Without we would not actually expand and access + memory beyond the allocated region for the array. + https://bugzilla.gnome.org/show_bug.cgi?id=731349 + +2014-06-05 16:55:15 -0700 Evan Nemerson + + * libs/gst/base/gstdataqueue.c: + dataqueue: clear up documentation of gst_data_queue_new + The gpointer argument is passed to all three callbacks, not just one. + https://bugzilla.gnome.org/show_bug.cgi?id=731302 + +2014-05-30 00:17:06 -0700 Evan Nemerson + + * gst/gstcontrolbinding.c: + * gst/gstcontrolsource.c: + * gst/gstdevicemonitorfactory.h: + * gst/gstutils.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstindex.c: + introspection: fix some minor annotation bugs + https://bugzilla.gnome.org/show_bug.cgi?id=730982 + +2014-06-05 12:38:20 -0700 Evan Nemerson + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstindex.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + base: use correct syntax in documentation more consistently + Previously, many constants were prefixed with # or unprefixed, + some functions and macros were prefixed with # instead of suffixed + with (), etc. + https://bugzilla.gnome.org/show_bug.cgi?id=731293 + +2014-05-07 18:26:38 +0800 zhouming + + * libs/gst/base/gstbaseparse.c: + baseparse: Pass rate of input segment to output segment + https://bugzilla.gnome.org/show_bug.cgi?id=729701 + +2014-04-07 14:49:59 +0100 Vincent Penquerc'h + + * plugins/elements/Makefile.am: + * plugins/elements/gstelements_private.c: + * plugins/elements/gstelements_private.h: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + gstbuffer: factor three flags-to-string loops + +2014-06-03 23:42:45 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: make printing datetimes work with GST_PTR_FORMAT + +2014-06-03 23:38:28 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + datetime: change internal implementation to mini object + And move type stuff from GstValue to GstDateTime. + +2014-06-03 22:19:33 +0200 Wim Taymans + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: fix uninitialized variable + +2014-06-03 22:12:13 +0200 Wim Taymans + + * docs/design/part-buffering.txt: + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: improve start/stop in buffering query + The start and stop should represent the currently downloading region. + The estimated-total should represent the remaining time to download + the currently downloading region. This makes it a lot more useful + for applications because they can then use those values to update + the fill region and use the estimated time to delay playback. + Update the docs with this clarification. + +2014-04-07 14:35:04 +0100 Vincent Penquerc'h + + * plugins/elements/gstidentity.c: + identity: add static and const where appropriate + +2014-04-07 14:31:17 +0100 Vincent Penquerc'h + + * plugins/elements/gstidentity.c: + identity: fix potential buffer overflow + Coverity 1037155 + +2014-06-03 14:49:44 +0200 Wim Taymans + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: reset read and write positions + Reset the read and write positions right after we open the file or flush + it. We are also in the buffering state with 0 percent buffered when we + start. + +2014-06-03 14:47:17 +0200 Wim Taymans + + * gst/gstinfo.c: + info: first handle all miniobjects, then GObjects + First handle all miniobjects before we attempt to dereference the first + field pointer and look at the GType. With the recent glib change to + speed up G_IS_OBJECT, this causes crashes on miniobjects otherwise. + +2014-06-03 14:46:11 +0200 Wim Taymans + + * gst/gstinfo.c: + info: GstDateTime does not have a GType as first field + GstDateTime does not have the GType as the first field so we can't use + it to detect its type. + +2014-06-03 14:45:22 +0200 Wim Taymans + + * gst/gstinfo.c: + info: use macros to check types + Use the macros to check the type of objects instead of directly poking + at the first field. + +2014-06-01 23:51:20 +0100 Tim-Philipp Müller + + * gst/gstglobaldevicemonitor.c: + globaldevicemonitor: connect sync-message signal on the right object + Fixes criticals at runtime and makes stuff actually work. + +2014-05-31 17:35:52 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Keep still meaningfull pending events on FLUSH_STOP + Only EOS and segment should be deleted in that case. + https://bugzilla.gnome.org/show_bug.cgi?id=709868 + +2014-05-30 09:13:12 +0200 Sebastian Dröge + + * gst/gstminiobject.c: + Revert "miniobject: Add missing (nullable) annotations" + This reverts commit 96361e9b5c5d00dc7712ff3a9acfbe10df7cd9fe. + This was not supposed to be pushed yet! + +2014-05-30 09:12:14 +0200 Sebastian Dröge + + * gst/gstbufferpool.h: + bufferpool: It's pool, not poo... even when talking about flushing + +2014-05-28 10:14:45 +0100 Philip Withnall + + * gst/gstminiobject.c: + miniobject: Add missing (nullable) annotations + gst_mini_object_replace() can take NULL mini-objects. + https://bugzilla.gnome.org/show_bug.cgi?id=730873 + +2014-05-30 01:42:17 -0300 Thiago Santos + + * tests/check/elements/multiqueue.c: + tests: multiqueue: fix leaks + +2014-05-29 14:54:34 -0700 Evan Nemerson + + * gst/gst.c: + * gst/gstallocator.c: + * gst/gstatomicqueue.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstbus.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstcapsfeatures.c: + * gst/gstchildproxy.c: + * gst/gstcontext.h: + * gst/gstcontrolsource.c: + * gst/gstdatetime.c: + * gst/gstdevice.c: + * gst/gstdevicemonitorfactory.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstiterator.h: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstmeta.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstparse.c: + * gst/gstparse.h: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstpreset.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gstsegment.c: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttoc.c: + * gst/gsttocsetter.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstvalue.c: + docs: convert NULL, TRUE, and FALSE to %NULL, %TRUE, and %FALSE + This should help improve documentation generated for + languages other than C. + https://bugzilla.gnome.org/show_bug.cgi?id=730961 + +2014-05-30 00:13:30 +0100 Tim-Philipp Müller + + * gst/gstobject.c: + docs: fix type in GstObject docs + +2014-05-29 15:04:45 -0700 Evan Nemerson + + * gst/gstbufferpool.c: + bufferpool: fix gst_buffer_pool_has_option() documentation + https://bugzilla.gnome.org/show_bug.cgi?id=730962 + +2014-05-29 14:07:15 -0300 Thiago Santos + + * gst/gstelement.c: + * tests/check/gst/gstelement.c: + element: set pads need-parent flag to false when removing + When a pad is added the need-parent flag is set to true, so when + they are removed the flag should be set back to false + This was preventing GstPads to be reused in elements (removed and + later re-added). A unit tests was added to verify that this is + working now. + The use case is tsdemux that has a program-number property and + allows the user to switch programs. In order to do that tsdemux + will remove the pads of the current program and add from the new + ones. The removed pads are kept in the demuxer for later if the + user selects the old program again. + +2014-05-27 08:09:36 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: post buffering message when queues flush + The buffering status goes back to 0, so inform the application about it + https://bugzilla.gnome.org/show_bug.cgi?id=726423 + +2014-05-29 14:39:36 -0400 Nicolas Dufresne + + * .gitignore: + gitignore: Ignore VIM swap files + +2014-05-27 13:36:29 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + * gst/gstpad.h: + pad: two minor docs fixes + +2014-05-27 10:09:02 +0100 Tim-Philipp Müller + + * libs/gst/base/gstflowcombiner.h: + flowcombiner: beautify headers a little + +2014-05-27 10:05:51 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstflowcombiner.h: + docs: add GstFlowCombiner + +2014-05-27 09:55:27 +0100 Tim-Philipp Müller + + * libs/gst/base/base.h: + base: include flowcombiner header from base.h + +2014-05-26 12:31:33 -0300 Thiago Santos + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstflowcombiner.c: + * libs/gst/base/gstflowcombiner.h: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/flowcombiner.c: + * win32/common/libgstbase.def: + flowcombiner: add GstFlowCombiner + Adds a utility struct that is capable of storing and aggregating flow returns + associated with pads. + This way all demuxers will have a standard function to use and have the + same expected results. + Includes tests. + https://bugzilla.gnome.org/show_bug.cgi?id=709224 + +2014-05-23 13:25:35 -0300 Thiago Santos + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + * win32/common/libgstreamer.def: + pad: store last flow return and provide acessor function + Stores the last result of a gst_pad_push or a pull on the GstPad and provides + a getter and a macro to access this field. + Whenever the pad is inactive it is set to FLUSHING + API: gst_pad_get_last_flow_return + https://bugzilla.gnome.org/show_bug.cgi?id=709224 + +2014-05-23 15:26:59 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * tests/check/gst/gstbufferpool.c: + * win32/common/libgstreamer.def: + bufferpool: Add method and virtuals to set flushing state + Currently there is no other way to unlock a buffer pool other then + stopping it. This may have the effect of freeing all the buffers, + which is too heavy for a seek. This patch add a method to enter and + leave flushing state. As a convenience, flush_start/flush_stop + virtual are added so pool implementation can also unblock their own + internal poll atomically with the rest of the pool. This is fully + backward compatible with doing stop/start to actually flush the pool + (as being done in GstBaseSrc). + https://bugzilla.gnome.org/show_bug.cgi?id=727611 + +2014-05-26 14:23:13 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Passthrough ALLOCATION queries in passthrough mode even if we had no caps yet + Or if the element does not care about caps at all. + Also remove an assigned but unused local variable. + https://bugzilla.gnome.org/show_bug.cgi?id=710268 + +2014-05-25 16:10:30 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update + +2014-05-25 16:57:59 +0200 Piotr Drąg + + * po/POTFILES.in: + po: update POTFILES + https://bugzilla.gnome.org/show_bug.cgi?id=730718 + +2014-05-21 13:23:21 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.2 === + +2014-05-21 13:06:34 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.3.2 + +2014-05-21 11:39:53 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-05-21 10:50:43 +0200 Sebastian Dröge + + * README: + * common: + Automatic update of common submodule + From 211fa5f to 1f5d3c3 + +2014-05-19 11:05:12 +0200 Sebastian Dröge + + * tests/check/gst/gstvalue.c: + value: Add some positive testcase for string deserialization + +2014-05-18 10:49:50 +0100 Tim-Philipp Müller + + * README: + * docs/faq/getting.xml: + docs: remove reference to Mandrake and packages we no longer provide + https://bugzilla.gnome.org/show_bug.cgi?id=730312 + +2014-05-15 16:41:58 +0200 Wim Taymans + + * docs/design/part-caps.txt: + docs: fix typo + +2014-05-14 13:40:03 +0100 Tim-Philipp Müller + + * gst/gstpluginloader.c: + pluginloader: fix compiler warning on windows + gstpluginloader.c:584:1: error: label 'beach' defined but not used + https://bugzilla.gnome.org/show_bug.cgi?id=730125 + +2014-05-13 19:51:34 +0100 Tim-Philipp Müller + + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstsparsefile.c: + * plugins/elements/gstsparsefile.h: + elements: don't depend on libgio just for g_io_error_from_errno() + https://bugzilla.gnome.org/show_bug.cgi?id=729949 + +2014-05-13 19:30:38 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * plugins/elements/Makefile.am: + * plugins/elements/gstdownloadbuffer.h: + * plugins/elements/gstsparsefile.c: + * plugins/elements/gstsparsefile.h: + * tests/check/libs/sparsefile.c: + * win32/common/libgstbase.def: + sparsefile: keep it private as helper API for downloadbuffer + There's no expectation that any other element or applications + might want to use this helper API any time soon, so keep it + private for the time being. There were open questions regarding + portability and binding-friendliness too. + This also removes the gio dependency of -base again. + https://bugzilla.gnome.org/show_bug.cgi?id=729951 + https://bugzilla.gnome.org/show_bug.cgi?id=729949 + +2014-05-13 19:14:08 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs.types: + docs: pick up GstBaseParse hierarchy and properties + +2014-05-13 19:10:43 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + docs: expose GstPushSrcClass in documentation + Might come in handy in case someone wants to derive from it. + +2014-05-12 17:03:46 +0200 Edward Hervey + + * gst/gstpluginloader.c: + pluginloader: Don't leak pluginloader in error cases + CID #1212154 + +2014-05-12 16:59:29 +0200 Edward Hervey + + * gst/gstcaps.c: + caps: Don't leak features on error cases + If we fail to parse fields, we would end up leaking the features we + parsed just before + CID #1212152 + +2014-05-09 14:28:59 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasetransform.c: + basetransform: Correctly reset configuration + When pool can't we use, and we fall back to default pool, we need to + correctly reset that pool configuration. + +2014-05-09 14:46:59 +0200 Edward Hervey + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: Use non-freed variable + address is only used temporarily. Use the proper variable instead. + CID #1212189 + +2014-05-08 17:33:37 -0300 Thiago Santos + + * tests/check/elements/multiqueue.c: + tests: multiqueue: test to check queue overrun with pts=none + Checks if buffers with pts=none can break the queue time size limit + and allow more buffers than expected + +2014-05-08 14:48:00 -0400 Nicolas Dufresne + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: Fix 32bit build + format '%lli' expects argument of type 'long long int', but argument 8 has type 'gsize' + +2014-05-08 14:12:16 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + pool-nego: Correctly reset the configuration + When pool cannot be used, correctly reset the configuration before + configuration a default pool. + +2014-04-15 14:17:00 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + pool-nego: Retry setting configuration with modified config + Buffer pool set_config() may return FALSE if requested configuration needed + small changes. Reget the config and try setting it again (validating the + changes first). This ensure we have a configured pool if possible. + https://bugzilla.gnome.org/show_bug.cgi?id=727916 + +2014-05-08 12:47:43 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * tests/check/gst/gstbufferpool.c: + * win32/common/libgstreamer.def: + bufferpool: Add an helper to validate config + When we call gst_buffer_pool_set_config() the pool may return FALSE and + slightly change the parameters. This helper is useful to do the minial required + validation before accepting the modified configuration. + https://bugzilla.gnome.org/show_bug.cgi?id=727916 + +2014-04-08 19:27:55 -0400 Nicolas Dufresne + + * gst/gstbufferpool.c: + bufferpool: Update the configure even if set_config() returned false + According to the documentation, when set_config() return false, it should be + possible to read the modified version of the config. This patch fixes the + implementation so it is now according to the documentation. + https://bugzilla.gnome.org/show_bug.cgi?id=727916 + +2014-05-06 15:35:14 -0400 Nicolas Dufresne + + * gst/gstbufferpool.c: + * tests/check/gst/gstbufferpool.c: + bufferpool: Add support for reconfiguring a pool + If a pool config is being configured again, check if the configuration have changed. + If not, skip that step. Finally, if the pool is active, try deactivating it. + https://bugzilla.gnome.org/show_bug.cgi?id=728268 + +2014-05-06 16:59:34 -0400 Nicolas Dufresne + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Add support for GstAllocationParams comparision + This is useful to compare buffer pool configuaration. + https://bugzilla.gnome.org/show_bug.cgi?id=728268 + +2014-05-06 16:46:55 -0400 Nicolas Dufresne + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Add support for GObject comparising in structures + This is useful to allow comparing pool configuration where a GstAllocator + is set. + https://bugzilla.gnome.org/show_bug.cgi?id=728268 + +2014-05-08 17:50:50 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: fix case where gst_plugin_load_file() didn't set the error on failure + +2014-05-08 16:30:55 +0100 Tim-Philipp Müller + + * libs/gst/base/gstsparsefile.c: + sparsefile: add some Since markers to docs + +2014-05-08 16:25:55 +0100 Tim-Philipp Müller + + * libs/gst/base/gstsparsefile.c: + * libs/gst/base/gstsparsefile.h: + * tests/check/libs/.gitignore: + sparsefile: sprinkle G_BEGIN_DECLS / G_END_DECLS + for c++, and remove outdated comment, and add + new unit test to .gitignore. + +2014-05-08 16:49:53 +0200 Wim Taymans + + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: small cleanups + +2014-05-08 14:51:12 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * plugins/elements/gstdownloadbuffer.c: + downloadbuffer: update docs + +2014-05-08 14:50:42 +0200 Wim Taymans + + * win32/common/libgstbase.def: + win32: update def + +2014-02-21 16:32:52 +0100 Wim Taymans + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstsparsefile.c: + * libs/gst/base/gstsparsefile.h: + * plugins/elements/Makefile.am: + * plugins/elements/gstdownloadbuffer.c: + * plugins/elements/gstdownloadbuffer.h: + * plugins/elements/gstelements.c: + * tests/check/Makefile.am: + * tests/check/libs/sparsefile.c: + Add new downloadbuffer element + See https://bugzilla.gnome.org/show_bug.cgi?id=680183 + +2014-05-02 17:42:58 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstpadtemplate.h: + * plugins/elements/gstmultiqueue.c: + pads: update docs for request pads + We would like to encourage the use of gst_element_request_pad() + +2014-05-02 17:02:37 +0100 Tim-Philipp Müller + + * libs/gst/check/libcheck/check.c: + check: use _exit() instead of exit() in fail_unless() so we exit immediately + exit() will call atexit handlers, which may try to + clean up things or wait for things to get cleaned up, + which we don't want or need. We just want to stop + and let the parent know about the failure as quickly + as possible in case fork() is used. + Fixes timeouts on assert failures in checks where + an exit handler waits for things to stop, but they + don't stop because they haven't been shut down, + and they haven't been shut down because there's no + simple way to do so on failures. + http://sourceforge.net/p/check/patches/50/ + +2014-05-04 14:52:01 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + value: init flag mask more correctly + +2014-05-04 13:32:46 +0000 Руслан Ижбулатов + + * plugins/elements/gstfilesrc.c: + filesrc: g_memmove() is deprecated + https://bugzilla.gnome.org/show_bug.cgi?id=712811 + +2014-05-03 20:48:22 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.3.1 === + +2014-05-03 17:41:41 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 1.3.1 + +2014-05-03 17:34:08 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2014-05-03 17:20:46 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations + +2014-05-03 12:14:43 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + docs: add new device probing API to docs table of contents + https://bugzilla.gnome.org/show_bug.cgi?id=729440 + +2014-05-02 22:22:03 -0400 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Add GstDevice* to gstreamer-sections.txt + https://bugzilla.gnome.org/show_bug.cgi?id=729440 + +2014-05-03 10:14:40 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From bcb1518 to 211fa5f + +2014-05-01 10:37:18 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesink.c: + basesink: Always render prepared buffer + Currently, if prepare() takes too much time, we skip the call to render(). + The side effect of this, is that we endup starving the render(). The solution + in this patch is to always render frames that are on time before prepare() is + executed. This will maximize the number of frames we display and smoothly + degrade the rendering performance. + https://bugzilla.gnome.org/show_bug.cgi?id=729335 + +2014-05-01 14:52:24 -0400 Luis de Bethencourt + + * scripts/git-version.sh: + scripts/git-version.sh: add more modules + Add more git repositories to check (so git-version.sh is consistent with + gst-uninstalled) and display the date of the last commit, which is more valuable + information than the last commit's hash. + +2014-05-01 18:42:47 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Always first post the state-changed message for PAUSED->READY before posting any pending EOS message + https://bugzilla.gnome.org/show_bug.cgi?id=727949 + +2014-04-17 21:10:55 +0200 Sebastian Dröge + + * tests/check/libs/basesink.c: + basesink: Add test for checking that EOS always comes after the state change to PLAYING + https://bugzilla.gnome.org/show_bug.cgi?id=727949 + +2014-04-15 15:55:25 +0200 Stian Selnes + + * gst/gstbufferpool.c: + bufferpool: fix log message of buffer pointer + +2014-04-30 18:20:28 -0400 Luis de Bethencourt + + * scripts/git-version.sh: + scripts/git-version.sh: remove unused variable + +2014-04-30 10:47:19 -0400 Luis de Bethencourt + + * scripts/git-version.sh: + scripts/git-version.sh: fix mistaken comments + +2014-04-28 13:02:11 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: avoid signaling overrun on the first segment + When the first segment has position != 0 and position > max-size-time + it will immediatelly cause the multiqueue to signal overrun. + This can happen easily with adaptive streams when switching bitrates + and starting a new group. The segment for this new group will have + a position that is much greater than 0 and will lead to this issue. + This is particularly harmful when the adaptive stream uses mpegts + that doesn't emit no-more-pads and it might happen that only one + of the stream pads was added when the multiqueue overruns and gets + the group ready for exposing. So the user will only get audio or + video. + The solution is to fallback to the sink segment while the source pad + has no segment. + https://bugzilla.gnome.org/show_bug.cgi?id=729124 + +2014-04-28 10:14:50 +0200 Xavi Artigas + + * docs/random/porting-to-1.0.txt: + docs: enhancements to porting guide documentation + https://bugzilla.gnome.org/show_bug.cgi?id=727754 + +2014-04-28 09:43:32 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: Add boolean to URI query to specify if a redirect is permanent or not + +2014-04-25 07:38:00 +0000 Srimanta Panda + + * plugins/elements/gstfunnel.c: + funnel: Check if the last pad was set + If no data is coming but only EOS is sent from all of the sinkpad, it is not + forwarding the EOS. + https://bugzilla.gnome.org/show_bug.cgi?id=727945 + +2014-04-26 17:02:18 +0100 Felipe Ortiz + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.h: + docs: add docs for various GstPad macros + https://bugzilla.gnome.org/show_bug.cgi?id=723652 + +2014-04-26 23:12:13 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.h: + Revert "docs: add docs for various GstPad macros" + This reverts commit d17438d5fd321daec4adbeb28a8fb5d5e07298dc. + This commit featured the wrong author, sorry. + +2014-04-26 21:21:51 +0100 Tim-Philipp Müller + + * docs/README: + * gst/gst.c: + * gst/gstallocator.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstghostpad.c: + * gst/gstiterator.c: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstmeta.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstparamspecs.c: + * gst/gstpipeline.c: + * gst/gstquery.c: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gstsegment.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstvalue.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimeprovider.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstvalve.c: + docs: remove outdated and pointless 'Last reviewed' lines from docs + They are very confusing for people, and more often than not + also just not very accurate. Seeing 'last reviewed: 2005' in + your docs is not very confidence-inspiring. Let's just remove + those comments. + +2014-03-26 15:56:08 -0400 Nicolas Dufresne + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + buffer: Only set TAG_MEMORY if the memory has been replaced + Currently we set TAG_MEMORY as soon a resize changes the size of one + of the memory. This has the side effect that buffer pool cannot know if + the memory have simply been resized, or if the memorys has been replaced. + This make it hard to actually implement _reset(). Instead, only set the + TAG_MEMORY if one or more memory has been replaced, and do a light + sanity check of the size. + https://bugzilla.gnome.org/show_bug.cgi?id=727109 + +2014-04-26 17:02:18 +0100 Showayb Zahda + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.h: + docs: add docs for various GstPad macros + https://bugzilla.gnome.org/show_bug.cgi?id=723652 + +2014-04-25 15:38:39 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: When going to READY make sure to always deactivate pads + We might not have reached PAUSED yet because of an async error, + but nonetheless we want to make sure that the pads are always + deactivated in READY state. + +2014-04-22 18:23:15 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Don't left-shift into the sign bit, the result is undefined + +2014-04-22 18:16:10 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Use an unsigned 64 bit integer as a mask + We shift the mask to the right later and shifting the result + of shifting over the sign bit is undefined. + +2014-04-20 11:59:02 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Make sure to always hold the LIVE_LOCK when going to the flushing label + https://bugzilla.gnome.org/show_bug.cgi?id=728596 + +2014-04-11 19:52:02 +0200 Srimanta Panda + + * plugins/elements/gstfunnel.c: + * tests/check/elements/funnel.c: + funnel: Handle end of stream event on sink pad + Handle end of stream events on sink pad. Check all the sink pad + has received eos before forwarding to source pad. + Fixes : https://bugzilla.gnome.org/show_bug.cgi?id=727945 + +2014-04-05 11:37:53 +0200 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Prevent division or modulo by zero + The step can end up being zero if the underlying value isn't a valid + range GValue. + In those cases, return FALSE. + We don't use g_return*_if_fail since it will already have been triggered + by the above-mentionned _get_step() functions. + CID #1037132 + +2014-04-09 16:44:07 +0200 Antoine Jacoutot + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + libs: g-ir-scanner: do not hardcode libtool path + https://bugzilla.gnome.org/show_bug.cgi?id=726571 + +2014-04-16 19:49:56 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + * gst/gstmemory.c: + memory/buffer: Initialise GstMapInfo to zeroes if mapping fails + This should allow for more meaningful errors. Dereferencing NULL + is more useful information than dereferencing a random address + happened to be on the stack. + +2014-04-16 17:49:06 +0200 Sebastian Dröge + + * gst/gstpreset.c: + preset: Unref return value of gst_child_proxy_get_child_by_index() instead of leaking it + +2014-04-16 17:48:57 +0200 Sebastian Dröge + + * gst/gstpreset.c: + preset: Automatic code style fixes + +2014-04-16 15:17:04 +0100 Vincent Penquerc'h + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: fix event/preroll deadlock differently + The qlock is released between popping a buffer from the queue + and pushing it. When this buffer causes the sink to wait in + preroll, this lets a query see that the queue is empty, and + push the query then wait for it to be serviced. However, this + will not be done till after peroll, and this will thus block. + If upstream was waiting on buffering to reach 100% before + switching to PLAYING, a deadlock would ensue. + This had been fixed recently by failing queries when the + queue2 was buffering, but this happens to break some other + case (playbin on a local http server and matroska), while + this patch works for both. + See https://bugzilla.gnome.org/show_bug.cgi?id=728345 + +2014-04-16 07:59:27 +0200 Edward Hervey + + * libs/gst/check/Makefile.am: + check: Fix exported symbol name + it's _template and not _templ + +2014-04-15 21:16:06 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Add missing space in debug output + +2014-04-15 12:58:59 +0200 Sebastian Dröge + + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Add new API to set up pads from non-static pad templates + +2014-04-14 21:35:52 +0200 Sebastian Dröge + + * tests/check/libs/collectpads.c: + collectpads: Fix memory leak in unit test + +2014-04-12 15:22:35 +0100 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/libs/gsttestclock.c: + testclock: replace newly-added GstTestClockIDList structure with a simple GList + Keep it simple. Likely also makes things easier for bindings, + and efficiency clearly has not been a consideration given how + the existing code handled these lists. + +2014-04-12 14:30:43 +0100 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + docs: testclock: fix up Since markers + +2014-04-12 00:28:51 +0100 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + testclock: add back gst_test_clock_wait_for_pending_id_count() + .. but deprecate it. ABI stability and all that. + It's a dangerous and racy function to use. + +2014-03-23 15:08:26 +0000 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + testclock: remove unused variable + Fixes compiler warning. + +2013-12-16 10:01:37 +0100 Havard Graff + + * libs/gst/check/Makefile.am: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/libs/gsttestclock.c: + testclock: add support for waiting and releasing multiple GstClockIDs + In order to be deterministic, multiple waiting GstClockIDs needs to be + released at the same time, or else one can get into the situation that + the one being released first can add itself back again before the next + one waiting is released. + Test added for new API and old tests rewritten to comply. + +2014-04-01 15:38:54 +0200 Linus Svensson + + * gst/gstpad.c: + pad: don't access unowned and possibly already freed event + Don't print the name of the event when ownership is given away. + https://bugzilla.gnome.org/show_bug.cgi?id=727484 + +2014-04-12 07:13:02 +0200 Wim Taymans + + * tools/gst-inspect.c: + inspect: print structure values of properties + +2014-04-11 22:38:25 +1000 Jan Schmidt + + * plugins/elements/gstinputselector.c: + input-selector: Hold pad object lock when changing tags + Avoid spurious crashes when tags are retrieved just as + new ones arrive. + +2014-04-11 13:45:21 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: Fix range iteration + We want to iterate over items idx to idx + length + We use the len variable as the corrected number of memory to iterate + and then properly go over all items. + Fixes the issue where specifying any idx different from 0 had no effect + Spotted by clang static analyzer + +2014-04-09 17:01:01 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + structure: error out when trying to fixate a fraction near an invalid target + +2014-04-04 17:28:23 +0200 Sebastian Dröge + + * gst/gstevent.c: + event: Update running time in QoS based on the pad offsets + https://bugzilla.gnome.org/show_bug.cgi?id=722697 + +2014-04-04 17:15:25 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Apply pad offsets on all events, not just segment events + +2014-04-04 17:06:18 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * win32/common/libgstreamer.def: + event: Add running-time-offset field to all events + Events passing through #GstPads that have a running time + offset set via gst_pad_set_offset() will get their offset + adjusted according to the pad's offset. + If the event contains any information that related to the + running time, this information will need to be updated + before usage with this offset. + +2014-04-09 16:40:27 +0100 Vincent Penquerc'h + + * gst/gstutils.c: + utils: avoid dividing by zero when multiplying y/z by 0/x + The gcd of 0/x is 0, and this is then used as a denominator. + +2014-04-09 16:01:09 +0200 Sebastian Dröge + + * tests/check/elements/multiqueue.c: + multiqueue: And actually run the other tests again + +2014-04-09 15:57:35 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Wake up the queues if limits are changing in a way that would unblock the queue + +2014-04-09 15:42:48 +0200 Sebastian Dröge + + * tests/check/elements/multiqueue.c: + multiqueue: Add test for checking if pads are waked up when limits are changed + +2014-04-09 10:15:33 +0200 Jose Antonio Santos Cadenas + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix memory leak + Queued frames were not released after being pushed, this + caused a leak of the GstBaseParseFrame structure. + https://bugzilla.gnome.org/show_bug.cgi?id=727883 + +2014-04-07 17:49:14 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: use g_strerror() instead of strerror() + Need UTF-8 encoding. + +2014-04-07 17:47:30 +0100 Tim-Philipp Müller + + * libs/gst/check/libcheck/check_run.c: + Revert "check: only call setpgid on valid child PIDs" + This reverts commit b9313afc75b68d986e473b76b55543456857912b. + This should be fixed in upstream libcheck instead. We want + to keep diff of our local copy to upstream libcheck + to a minimum. + +2014-04-07 17:33:34 +0100 Vincent Penquerc'h + + * plugins/elements/gstqueue2.c: + queue2: warn if we can't remove our temporary file + It's not fatal though, so do not error out. + Coverity 1037121 + +2014-04-07 15:38:09 +0100 Vincent Penquerc'h + + * libs/gst/check/libcheck/check_run.c: + check: only call setpgid on valid child PIDs + Coverity 206186 + +2014-04-07 15:38:17 +0100 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: no need for a translated message for impossible error cases + The message is too technical anyway, the default message works + just fine here as well. + +2014-04-07 15:18:32 +0100 Vincent Penquerc'h + + * plugins/elements/gstfilesrc.c: + filesrc: catch failure to seek back to zero after seek test + This should never happen theoretically, but since a transient + failure would get us to silently read wrong data, it's worth + erroring out. And it silence this: + Coverity 206034 + +2014-04-07 11:36:58 +0200 Sebastian Dröge + + * gst/parse/Makefile.am: + parse: Don't dist the bison and flex generated headers + https://bugzilla.gnome.org/show_bug.cgi?id=727253 + +2014-04-06 11:23:34 +0200 Sebastian Rasmussen + + * gst/gstdebugutils.c: + debugutils: Handle caps field values being NULL + GST_DEBUG_BIN_TO_DOT_FILE() would cause a segfault whenever it encountered an + element's caps that had a field value being NULL. Such fields are successfully + handled e.g. by GST_*_OBJECT(), and with this patch so does + GST_DEBUG_BIN_TO_DOT_FILE(). Even if string fields with a NULL value are + not supposed to be valid in caps, such caps can be created. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=727701 + +2014-04-05 11:44:01 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Remove always-true-checks + a gsize is guaranteed to be positive on all systems since it's an + unsigned value. + CID #1037147 + +2014-04-05 11:44:01 +0200 Edward Hervey + + * libs/gst/base/gstadapter.c: + adapter: Remove always-true-checks + a gsize is guaranteed to be positive on all systems since it's an + unsigned value. + CID #1037145 + CID #1037146 + +2014-04-05 11:37:53 +0200 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Prevent division or modulo by zero + The step can end up being zero if the underlying value isn't a valid + range GValue. + In those cases, return FALSE. + We don't use g_return*_if_fail since it will already have been triggered + by the above-mentionned _get_step() functions. + Spotted by Coverity. + +2014-03-25 12:23:32 +0100 Haakon Sporsheim + + * gst/gstvalue.c: + gstvalue: Fix comparison of int/int64 range + Checking step three times seems unnecessary. + A similar bug was fixed for double range in + commit 3ea6b04c10b10fde9d62190068f274b940edef07 + +2014-04-03 18:17:03 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + inputselector: fix build with debug cached buffers enabled + gstinputselector.c:818:5: error: format not a string literal + and no format arguments [-Werror=format-security] + +2014-04-03 20:31:16 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Make sure to set the DISCONT flag on the first buffer of each GOP in reverse playback mode + +2014-04-03 13:20:11 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: removing duplicated inner if + The inner if replicates the same code of the outer and is useless + as flag_segment will always be true. + Found by coverity. + +2014-04-03 07:36:03 +0200 Edward Hervey + + * tools/gst-launch.1.in: + gst-launch.1: Playbin2 is dead, long live playbin + Looks like that was the last remaining mention in core ... + +2014-04-02 23:52:10 +0200 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Add missing \n in output + +2014-04-01 15:35:24 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + scripts: gst-uninstalled: gst-plugins-gl libs got merged into -bad + +2014-03-29 10:18:34 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Include event type in debug output when delaying a sticky event because of not-linked + +2014-03-29 10:16:12 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix splitting and reversing of GOPs in reverse playback mode + We iterate the current discont group backwards and push each GOP forwards, + starting from the last one. However if the first buffer in the current + discont group is a keyframe, we will keep it around until next time, + which is far from ideal. Just push it. + +2014-03-25 12:38:07 +0100 Wim Taymans + + * tools/gst-launch.c: + launch: place the deep-notify on the right pipeline + If the toplevel bin is not not a pipeline, we place the bin in a + pipeline. Also make sure that we connect to the deep-notify of this new + pipeline because we will g_signal_handler_disconnect() from it later. + +2014-03-24 16:34:27 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: copy last_sample on DRAIN + Make sure we don't hold a ref to a buffer from before the DRAIN query by + making a copy of the last_buffer. + +2014-03-24 16:11:30 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: don't clear TAG on NULL buffer + When the buffer fails to copy, don't clear the TAG on the NULL pointer. + +2014-03-20 06:14:33 -0400 Vincent Penquerc'h + + * plugins/elements/gstqueue2.c: + queue2: fix event/preroll deadlock + The qlock is released between popping a buffer from the queue + and pushing it. When this buffer causes the sink to wait in + preroll, this lets a query see that the queue is empty, and + push the query then wait for it to be serviced. However, this + will not be done till after peroll, and this will thus block. + If upstream was waiting on buffering to reach 100% before + switching to PLAYING, a deadlock would ensue. + We fix it by refusing the query when buffering, as per Wim's + recommendation on IRC. + +2014-03-23 12:53:55 +0000 Tim-Philipp Müller + + * tests/check/libs/gstnetclientclock.c: + tests: make netclientclock test faster and less flaky + +2014-03-21 12:16:54 +0100 Wim Taymans + + * gst/gst.c: + gst: init new flag types to pass make check + +2014-03-19 09:33:53 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Update buffering status and maybe post buffering message right when enabling buffering + +2014-03-19 09:32:45 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Update buffering status and maybe post buffering message right when enabling buffering + +2014-03-18 18:12:16 +0100 Sebastian Dröge + + * tests/check/elements/fakesink.c: + fakesink: Update positions we're checking for after a state is lost + +2014-03-18 18:11:15 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Update start time when we lose our state + Otherwise we report not the correct position while the state is lost. + +2014-03-18 16:47:42 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Don't clip the reported position in PAUSED to after the last buffer end timestamp + Otherwise we jump forward when pausing, and go backwards a bit again + when resuming playback. + +2014-03-17 10:05:31 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update exports for GstToc loop + +2014-03-17 10:05:18 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update export for gst*device symbols + +2014-03-17 09:51:45 +0100 Edward Hervey + + * gst/gstdevice.c: + * gst/gstdevicemonitor.c: + * gst/gstglobaldevicemonitor.c: + devicemonitor: Use local includes and use gst_private before anything + Should fix build issues on BSD + +2014-03-16 20:50:53 -0400 Olivier Crête + + * tools/gst-inspect.c: + gst-inpect: Print device monitor + +2014-03-16 15:56:59 -0400 Olivier Crête + + * gst/gstdevice.c: + * gst/gstdevice.h: + * gst/gstglobaldevicemonitor.c: + device: Add "klass" to GstDevices + +2014-03-16 18:02:56 -0400 Olivier Crête + + * gst/gstdevicemonitorfactory.c: + * gst/gstdevicemonitorfactory.h: + * gst/gstglobaldevicemonitor.c: + * gst/gstglobaldevicemonitor.h: + devicemonitor: Make classes into pure strings + Instead of having strings & flags, make them just strings + +2014-03-17 06:29:27 +1100 Jan Schmidt + + * gst/gstbus.c: + * gst/gstmessage.h: + * tests/check/gst/gstbus.c: + Fix extended message handling with gst_bus_pop_timed_filtered() + Make sure extended message types don't get accidentally matched + when not asked for in the mask + +2014-03-17 05:24:12 +1100 Jan Schmidt + + * gst/gstbin.c: + gstbin: Avoid pointless object lock forwarding messages. + Every instance of calling bin_do_message_forward() first took the + object lock, so that bin_do_message_forward() could drop it and + then reclaim. Instead, only take the object lock afterward where + needed. + +2014-02-19 02:27:36 +0100 Mathieu Duponchelle + + * libs/gst/base/gstcollectpads.c: + collectpads: When seek flushed, immediately set eospads to 0 + This prevents situations where a first branch would get seeked and + receive a buffer before all branches got seeked, and thus collected + would get called based on EOS from the previous segment. + As a consequence, during the process of seeking, don't decrease + the eospads number when a FLUSH_STOP is received. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=724571 + +2014-03-16 17:47:06 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads.c: + collectpads: Unref peer pad + +2014-02-16 20:35:09 +0100 Mathieu Duponchelle + + * libs/gst/base/gstcollectpads.c: + collectpads: Forward seek events to the peer directly + Taken from the adder seek handling code. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=726461 + +2014-01-02 22:30:11 +0100 Stefan Sauer + + * docs/design/part-toc.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + toc: expand GstTocEntry with loop fields + Add loop_type and repeat_count fields to GstTocEntry plus setters and getters. + This allows to represent edit-lists in a toc as well as loops in instruemnts (wav, xi). + API: gst_toc_entry_set_loop + API: gst_toc_entry_get_loop + +2014-03-16 15:19:49 +0000 Tim-Philipp Müller + + * gst/gstglobaldevicemonitor.c: + globaldevicemonitor: update for new message API + https://bugzilla.gnome.org/show_bug.cgi?id=678402 + +2013-01-08 21:30:44 -0500 Olivier Crête + + * gst/Makefile.am: + * gst/gst.h: + * gst/gstglobaldevicemonitor.c: + * gst/gstglobaldevicemonitor.h: + * win32/common/libgstreamer.def: + globaldevicemonitor: Add device monitor aggregator + https://bugzilla.gnome.org/show_bug.cgi?id=678402 + +2014-03-16 14:08:45 +0000 Tim-Philipp Müller + + * tests/check/gst/gstbus.c: + tests: add test for extended message types and gst_bus_timed_pop_filtered + +2014-03-16 14:08:00 +0000 Tim-Philipp Müller + + * gst/gst.c: + * gst/gstbus.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + message, bus: do extended message types slightly differently + https://bugzilla.gnome.org/show_bug.cgi?id=678402 + +2014-03-16 14:07:35 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: fix indentation + +2012-10-16 12:27:04 -0400 Olivier Crête + + * gst/Makefile.am: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstdevice.c: + * gst/gstdevice.h: + * gst/gstdevicemonitor.c: + * gst/gstdevicemonitor.h: + * gst/gstdevicemonitorfactory.c: + * gst/gstdevicemonitorfactory.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * win32/common/libgstreamer.def: + devicemonitor: Add GstDeviceMonitor and related + Also add GstDevice and GstDeviceMonitorFactory + And add code to the registry to save them + https://bugzilla.gnome.org/show_bug.cgi?id=678402 + +2013-08-14 15:56:11 -0400 Olivier Crête + + * gst/gst.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + message: Add GST_MESSAGE_EXTENDED + https://bugzilla.gnome.org/show_bug.cgi?id=678402 + +2014-03-16 11:05:56 +0100 Stefan Sauer + + * gst/gstutils.c: + pad: actually return data.ret + The return value from gst_pad_forward() is the aggregated return value from the callback and the callback returns FALSE to continue iterating. + +2014-03-15 15:54:33 +0100 Stefan Sauer + + * gst/gstutils.c: + pad: forward return value from gst_pad_forward + Instead of ignoring the return value and always return TRUE pass the already agregated result back. + +2014-03-15 13:57:19 -0300 Thiago Santos + + * win32/common/libgstreamer.def: + win32: fix make-check by running 'make update-exports' + +2014-03-14 13:32:17 -0300 Thiago Santos + + * tests/check/elements/multiqueue.c: + tests: multiqueue: fix eos count on test for not-linked case + From the test case: + /* This test creates a multiqueue with 2 streams. One receives + * a constant flow of buffers, the other only gets one buffer, and then + * new-segment events, and returns not-linked. The multiqueue should not fill. + */ + If one of the queues goes EOS and the other returns NOT_LINKED the stream + can be considerered EOS as a NOT_LINKED means that one of the branches has no + sink downstream that will block the EOS message posting. + https://bugzilla.gnome.org/show_bug.cgi?id=725917 + +2014-03-01 23:18:44 +0100 Sebastian Rasmussen + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * win32/common/libgstbase.def: + adapter: Adapt gst_adapter_copy() for bindings + This is done by introducing a new gst_adapter_copy_bytes() call that + returns a GBytes structure. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725476 + +2014-03-14 18:40:31 +0000 Tim-Philipp Müller + + * plugins/elements/gstmultiqueue.c: + docs: fix multiqueue docs for new template names foo_%d -> foo_%u + https://bugzilla.gnome.org/show_bug.cgi?id=726358 + +2014-03-11 21:55:46 +0000 Tim-Philipp Müller + + * docs/plugins/inspect/plugin-coreelements.xml: + docs: update plugin docs + +2014-03-11 21:44:39 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: simplify gst_pad_link_get_name() and fix Since marker + Has added benefit that compiler might warn if more values + are added to the enum. + +2014-03-11 21:46:14 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: add debug helper for GstPadLinkReturn names + Add a helper like gst_flow_get_name() for GstPadLinkReturn. Use this in core. + API: gst_pad_link_get_name() + +2014-03-11 21:12:15 +0100 Stefan Sauer + + * plugins/elements/gsttee.c: + tee: use store_sticky events add add more logging + Use the pad as object for logging to get more context. Use + gst_pad_store_sticky_event() instead of sending the event. This avoids a warning + as here the pad is not yet linked and we actually don't want to send anyway. + +2014-03-10 10:00:28 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: if buffering is disabled while buffering, post 100% message + Avoids stall waiting for buffering to reach 100% + +2014-03-10 09:49:09 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: remove unused variable + buffering_iteration was never used + +2014-03-10 09:49:07 -0300 Thiago Santos + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue: queue2: preserve last flow result when pushing events + Avoids mistakenly returning _OK when downstream is still + _NOT_LINKED on subsequent received pad pushes + https://bugzilla.gnome.org/show_bug.cgi?id=725917 + +2014-03-10 09:49:05 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: if buffering is disabled while buffering, post 100% message + Avoids stall waiting for buffering to reach 100% + +2014-03-10 09:48:58 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: do not reset last push result when pushing events + Use the last result as a default when pushing a item from a single queue, + otherwise the status gets reset to _OK when pushing events. + This causes problems when mistakenly activating a not-linked stream + that is being ignored upstream as it is not being used (adaptive + scenarios), it will make the multiqueue post a buffering message + on a pad that won't receive buffers + https://bugzilla.gnome.org/show_bug.cgi?id=725917 + +2014-03-07 20:43:44 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + buffer: invert meaning of GST_BUFFER_FLAG_TAG_MEMORY + It's nicer to only have it set when something noteworthy + happened and otherwise unset. + https://bugzilla.gnome.org/show_bug.cgi?id=725862 + +2014-03-06 22:51:57 +0100 Stefan Sauer + + * gst/gstpad.c: + pad: fix gst_pad_add_probe() return value docs + Also fix comment typos and add more detail in the logs. + +2014-03-06 20:40:46 +0000 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + fakesink, identity, fakesrc: fix debug printing if TAG_MEMORY buffer flag + The IN_CAPS flag does not exist any more. + +2014-03-06 13:01:40 +0200 George Kiagiadakis + + * gst/gstghostpad.c: + ghostpad: use gst_pad_get_peer to acquire a reference to the target pad + This ensures that the lock of the internal pad is held while referencing + it's peer (= the target pad), which ensures that the peer is not + going to be unlinked/destroyed in the meantime. + https://bugzilla.gnome.org/show_bug.cgi?id=725809 + +2014-03-06 12:40:23 +0200 George Kiagiadakis + + * gst/gstghostpad.c: + ghostpad: hold a reference to the target pad while unlinking it + https://bugzilla.gnome.org/show_bug.cgi?id=725809 + +2014-03-02 05:08:24 +0100 Sebastian Rasmussen + + * .gitignore: + .gitignore: Ignore gcov intermediate files + https://bugzilla.gnome.org/show_bug.cgi?id=725478 + +2014-03-02 17:55:45 +0100 Sebastian Rasmussen + + * gst/gstbufferpool.c: + * gst/gstmeta.c: + * libs/gst/base/gstbaseparse.h: + docs: Fix typos and remove unknown annotations + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=725517 + +2014-02-28 20:53:38 +0100 Stefan Sauer + + * gst/gstcontext.c: + docs: use the new markdown for ordered list. + This was plain text that had all list items one after the other (including a + repeated number). Now it will atleast look good when processed with gtk-doc + 1.20. + +2014-02-28 09:34:19 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From fe1672e to bcb1518 + +2014-02-27 22:26:30 -0300 Reynaldo H. Verdejo Pinochet + + * gst/gstevent.c: + * gst/gstpadtemplate.c: + docs: fix problems introduced by c068b225fef5a9bf0 + - Fix failing build + - Drop added trailing whitespace + +2014-02-27 18:27:37 +0100 Stefan Sauer + + * gst/gstbuffer.c: + buffer: add return values to g_return_if_fail + FIxes previous commit. + +2014-02-27 18:06:56 +0100 Stefan Sauer + + * gst/gstbuffer.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstinfo.c: + * gst/gstiterator.c: + * gst/gstmessage.c: + * gst/gstpadtemplate.c: + * gst/gstquery.c: + * gst/gsttypefindfactory.c: + docs: convert the examples to use gtk-doc markup, instead of docbook + The gtk-doc markup is less intrusive and better handled when creating docs for + language bindings. The titles (where used) where not adding much. + +2014-02-27 16:46:11 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + docs: add some more new API do docs + +2014-02-27 16:40:34 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * tests/check/gst/gstbufferpool.c: + bufferpool: only release buffers with writable memory + Check if the memory is writable before releasing the buffer into the + pool again. + Add unit test for this scenario. + +2014-02-27 16:39:50 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add function to check writability of memory + Check if memory is writable in a buffer and thus is exclusively owned by + this buffer. + +2014-02-27 15:14:59 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * tests/check/gst/gstbufferpool.c: + bufferpool: Use TAG_MEMORY to check memory before releasing + Tag allocated buffers with TAG_MEMORY. When they are released later, + only add them back to the pool if the tag is still there and the memory + has not been changed, otherwise throw the buffer away. + Add unit test to check various scenarios. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=724481 + +2014-02-27 14:35:09 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add a new flag to track memory changes + Add a flag to check if the memory changed in a buffer. + +2014-02-26 15:36:42 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: remove wrong comment + Refcount and writability are not related for memory objects. + +2014-02-25 17:46:49 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: refactor free_buffer + Make a do_free_buffer method to also decrements the number of allocated + buffers. Stop will now be successful when all buffers are freed. + +2014-02-26 22:10:28 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From 1a07da9 to fe1672e + +2014-02-26 20:24:41 +0100 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: add a legend to pipeline dumps + We use a couple of symbols to represent states/flags. Add a short explanation for them. + +2013-07-31 09:26:26 +0200 Olivier Crête + + * gst/gstdebugutils.c: + debugutils: Print if there is a task started from a pad + https://bugzilla.gnome.org/show_bug.cgi?id=705189 + +2014-02-25 16:11:20 +0100 Sebastian Dröge + + * gst/gststructure.c: + structure: Use get_uint64() in gst_structure_get_clock_time() + Its code is identical. + +2014-02-25 15:41:45 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * tests/check/gst/gststructure.c: + * win32/common/libgstreamer.def: + structure: Add getters for int64 and uint64 values + +2014-02-19 21:17:27 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + * tests/check/libs/basesrc.c: + basesrc: Do not send eos when seeking after last buffer + If pushing the last buffer triggers a seek from downstream, do not + go into EOS if a new segment was requested. + Contains unit test + https://bugzilla.gnome.org/show_bug.cgi?id=724757 + +2014-02-21 09:03:50 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: remove insanity and the old gst-openmax + +2014-02-20 18:47:42 +0100 Thibault Saunier + + * scripts/gst-uninstalled: + gst-uninstalled: Add paths to gst-devtools/validate + +2014-02-20 15:34:36 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: If we only have a single pad, don't consider all pads not linked and grow the queue indefinitely + +2014-02-19 10:57:33 +0100 Stefan Sauer + + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: also use the glob on GST_CHECKS when forcing to run broken tests + GST_CHECKS can be simply "test*" to run run all tests (including those that are + marked broken). Update the sparse comments a bit to tell how this works. + +2014-02-18 15:46:32 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: don't truncate the temp file on shutdown + We want to keep the downloaded file untruncated so that we can use it + again later. + Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=724373 + +2014-02-18 14:21:20 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: Fix merging of ranges + Make a method to get the seeking threshold. If data is further away from + this threshold we want to perform a seek upstream. + When the current downloaded range can merge with the next range, + actually include the data of the next range into the current range + instead of discarding it. Also decide if we seek to the write position + of the merged range or continue reading. + +2014-02-18 11:49:37 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: in automatic_eos mode, don't modify the size + Don't set the size to -1 in automatic_eos mode (which also updates the + duration to -1). We only want automatic_eos mode influence the maxsize + calculations without any side effects. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=724564 + +2014-02-17 11:37:30 +0100 Jan Alexander Steffens (heftig) + + * docs/pwg/advanced-types.xml: + pwg: Update raw properties + Using info from gst-plugins-base/docs/design . + Encoded streams might make use of the raw properties, so list them all under foo/* . + For foo/raw, only note which of these properties are mandatory. + I didn't take a closer look at the raw formats yet. Those might still be out-of-date. + https://bugzilla.gnome.org/show_bug.cgi?id=724187 + +2014-02-17 17:28:38 +0000 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: create-uninstalled-setup: remove dead http links + https://bugzilla.gnome.org/show_bug.cgi?id=724561 + +2014-02-15 22:34:33 +0100 Stefan Sauer + + * docs/gst/gstreamer.types.in: + docs: add the boxed types to the .types.in + This makes them show up in the object hierarchy. + +2014-02-15 21:22:45 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.h: + docs: gtkdoc is not good at parsing inline functions in headers + Mark the inline function, so that gtkdoc skips them. Avoids some warnings about + unparsable declarations. + +2014-02-13 12:07:50 +0100 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * win32/common/libgstbase.def: + basesrc: Add gst_base_src_set_automatic_eos() API + This defaults to TRUE and if it is set to FALSE it is the subclasses + responsibility to return GST_FLOW_EOS from the create() vmethod once + the stream is done. + +2014-02-11 16:30:31 +0000 William Manley + + * docs/gst/running.xml: + * gst/gstregistry.c: + docs: Fix location of plugins and registry in home directories + Fixes out of date documentation left over since 0.10. In 1.0 plugins are + stored in $XDG_DATA_HOME and the registry in $XDG_CACHE_HOME conformant + with the XDG Base Directory Specification[1]. + [1]: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + https://bugzilla.gnome.org/show_bug.cgi?id=724132 + +2014-02-11 13:27:25 +0100 Sebastian Dröge + + * gst/gsterror.h: + error: GST_RESOURCE_ERROR_NOT_AUTHORIZED will be available since 1.2.4 + +2014-02-11 13:09:11 +0100 Sebastian Dröge + + * gst/gsterror.c: + * gst/gsterror.h: + error: Add RESOURCE_NOT_AUTHORIZED error + This allows to distinguish normal read failures from read failures + where we miss authorization. + +2014-02-10 17:09:59 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Fix yet another compiler warning + https://bugzilla.gnome.org/show_bug.cgi?id=724045 + +2014-02-10 08:00:36 +0100 Sebastian Rasmussen + + * docs/design/Makefile.am: + docs: add missing seqnum file for distribution + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=723997 + +2014-02-09 16:53:55 +0000 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: document GST_TAG_*ENCODING environment variables + https://bugzilla.gnome.org/show_bug.cgi?id=721850 + +2014-02-09 16:47:53 +0000 Tim-Philipp Müller + + * docs/Makefile.am: + docs: enable parallel build of subdirectories + We can build gtk docs, ADM, PWG and FAQ in parallel. + +2014-02-09 16:38:10 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: add support for blacklisting checks via GST_CHECKS_IGNORE + +2014-02-09 00:25:14 +0000 Tim-Philipp Müller + + * tests/check/libs/baseparse.c: + tests: fix leak in baseparse test + Or rather make it not show up any more by moving + it from 'definitely lost' into 'possibly lost'. + +2014-02-08 23:39:03 +0000 Tim-Philipp Müller + + * tests/check/gst/gstsystemclock.c: + tests: fix leak in systemclock test + +2014-02-08 16:42:55 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Make clang happy with our g_vprintf() wrapper + +2014-02-06 14:18:31 +0800 Chun-wei Fan + + * gst/gst.c: + * gst/gstpluginloader.c: + * gst/gstpreset.c: + * gst/gstregistry.c: + windows: Make GStreamer installation relocatable + Use the technique that is now done in GTK+ so that the plugins do not have + to be installed in c:\gstreamer\lib\\gstreamer-$(GSTApiVersion), + but can be installed in + \lib\\gstreamer-$(GSTApiVersion), + or as per g_win32_get_package_installation_directory_of_module() allows. + https://bugzilla.gnome.org/show_bug.cgi?id=679115 + +2013-10-30 17:02:35 -0500 Brendan Long + + * gst/gsttask.c: + * gst/gsttaskpool.c: + * libs/gst/base/gstcollectpads.c: + gst: clear floating references for GstTask, GstTaskPool and GstCollectPads + https://bugzilla.gnome.org/show_bug.cgi?id=710342 + +2013-10-30 17:02:02 -0500 Brendan Long + + * gst/gstbufferpool.c: + * gst/gstpad.c: + docs: gst_pad_new_from_*_template and gst_buffer_pool_new constructors return floating references + https://bugzilla.gnome.org/show_bug.cgi?id=710342 + +2014-02-05 10:11:43 +0100 Edward Hervey + + * tests/check/elements/capsfilter.c: + check: Remove a minor leak in unit test + Makes valgrind happy + +2014-02-04 22:23:06 +0100 Sebastian Dröge + + * docs/manual/advanced-dataaccess.xml: + manual: Fix build by using the correct C file name + +2014-02-04 21:36:18 +0100 Sebastian Dröge + + * docs/manual/advanced-dataaccess.xml: + manual: Clean up code a bit to be suitable for the docs + +2014-01-03 07:25:37 -0800 Todd Agulnick + + * docs/manual/advanced-dataaccess.xml: + manual: Replace manual's effectswitch.c with newer test-effect-switch.c + https://bugzilla.gnome.org/show_bug.cgi?id=721100 + +2014-01-29 14:39:19 +0000 Matthieu Bouron + + * tests/check/gst/gstcaps.c: + tests: add caps features unit tests + https://bugzilla.gnome.org/show_bug.cgi?id=723236 + +2014-02-04 18:42:02 +0100 Sebastian Dröge + + * gst/gstcaps.c: + caps: When getting capsfeatures and none are there, store sysmem capsfeatures + ... instead of returning a reference to a global instance. The caller might + want to change the global instance otherwise, which causes funny effects like + all global instances being changed and at the same time nothing in the caps + being changed. + As the caps might be immutable while we do this we have to do some magic + with atomic operations. + https://bugzilla.gnome.org/show_bug.cgi?id=723236 + +2014-02-04 18:03:47 +0100 Sebastian Dröge + + * gst/gstcaps.c: + caps: Don't get us sysmem capsfeatures if we just check for fixed caps + +2014-02-04 17:48:54 +0100 Sebastian Dröge + + * gst/gstcapsfeatures.c: + capsfeatures: Make sure that the static ANY/EMPTY capsfeatures are never mutable + See https://bugzilla.gnome.org/show_bug.cgi?id=723236 + +2014-01-31 09:14:41 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontrolbinding.h: + * gst/gstmeta.h: + * libs/gst/base/gstbasetransform.c: + docs: fix more gtk-doc warnings + +2014-01-31 08:35:41 +0100 Stefan Sauer + + * docs/gst/Makefile.am: + * docs/gst/gstreamer-sections.txt: + * gst/gstallocator.h: + docs: unhide docs for allocator + Unhinde the class docs. Tech gtk-doc about GST_EXPORTS. + +2014-01-31 08:08:37 +0100 Stefan Sauer + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * tests/check/gst/gstbufferpool.c: + bufferpool: more tests and small doc fixes + +2014-01-30 21:24:21 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + tools: Support non-ASCII tags + By calling setlocale() to get us multi-byte/UTF-8 support. + https://bugzilla.gnome.org/show_bug.cgi?id=723164 + +2014-01-30 03:22:56 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + outputselector: respect the 'negotiation-mode' property + If the segment event is allowed to be pushed to all pads it + will lead to an assertion of 'sticky event misordering: + segment received before caps' in case the pad-negotiation-mode + is set to 'active' or 'none'. + This patch fixes this by making all sticky events follow the + property like the caps event to prevent misordering warnings. + When a new pad is activated the current sticky events on the + sinkpad are forwarded to it in the proper order. + https://bugzilla.gnome.org/show_bug.cgi?id=723266 + +2014-01-30 12:54:20 +0100 Stefan Sauer + + * tests/benchmarks/gstpoolstress.c: + poolstress: print speedup + +2014-01-30 12:42:02 +0100 Stefan Sauer + + * gst/gstbufferpool.c: + bufferpool: misc cleanups + Review the documentation, comments and logging. Set the initial size to 16 as + the size is rounded up to the next power of two anyway. + +2014-01-30 08:11:12 +0100 Stefan Sauer + + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstbufferpool.c: + bufferpool: add a new testsuite or the pool + Start with some basic tests. + +2014-01-30 12:26:05 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: avoid excessive GstPoll activity + Keep an extra write ref on the control socket. This ensures that we + avoid a read/write on the socket when going from non-empty->empty->not-empty. + We remove the write ref only when we actually are empty and we need to + wait for flushing or a new buffer. + This makes the bufferpool benchmark about 30% faster than the pure + malloc implementation. + +2014-01-30 12:25:33 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: improve debug + Add object pointer in debug lines. + +2014-01-30 10:43:36 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From d48bed3 to 1a07da9 + +2014-01-29 22:46:48 +0100 Stefan Sauer + + * docs/design/part-toc.txt: + part-toc: emphasize that the later chapters are design draft ideas + +2014-01-29 20:20:56 +0100 Stefan Sauer + + * docs/design/part-toc.txt: + part-toc: add format specific information + +2014-01-29 18:21:34 +0100 Stefan Sauer + + * tests/benchmarks/gstpoolstress.c: + poolstress: code cleanups + Add a few comments. Tell in the results, which number are from which test. + +2014-01-29 13:20:19 +0100 Nicola Murino + + * scripts/gst-uninstalled: + gst-uninstalled: use print as function + https://bugzilla.gnome.org/show_bug.cgi?id=723229 + +2014-01-28 11:58:53 -0300 Thiago Santos + + * tests/check/elements/capsfilter.c: + tests: capsfilter: add test for pending_events pushing + make sure that pending events are pushed when caps are already + set when a buffer is received + +2014-01-28 11:12:56 -0300 Thiago Santos + + * plugins/elements/gstcapsfilter.c: + capsfilter: do not forget to push pending events + Push pending events before buffers if caps is already + set + +2014-01-24 19:19:08 +0100 Arnaud Vrac + + * plugins/elements/gstmultiqueue.c: + multiqueue: do not reduce single queue below current level + When the single queue size was just bumped by 1 to allow more buffers to + be added, the buffers limit could be reduced to the current level when + setting the max-size-buffers property. This would result in a stall + since the queue would not grow anymore at this point. + Prevent this by not reducing a single queue size below the current + number of buffers + 1. + https://bugzilla.gnome.org/show_bug.cgi?id=712597 + +2014-01-24 13:20:49 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: do not forget to clear the forced_eos flag + otherwise it will always use the seqnum of the event + sent by the application + +2014-01-23 15:52:51 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + * tests/check/libs/basesrc.c: + basesrc: preserve seqnum of eos events sent by the user + Store the eos event seqnum and use it when creating the + new eos event to be pushed downstream. To know if the eos + was caused by the eos events received on send_event, a + 'forced_eos' flag is used to use the correct seqnum on + the event pushed downstream. + Useful if the application wants to check if the EOS message + was generated from its own pushed EOS or from another source + (stream really finished). + Also adds a test for this + https://bugzilla.gnome.org/show_bug.cgi?id=722791 + +2014-01-23 15:34:27 -0300 Thiago Santos + + * docs/design/part-seqnums.txt: + docs: design: add part-seqnums + Hopefully clarifies how seqnums should be used and copied from + events to events/messages when those are handled. + https://bugzilla.gnome.org/show_bug.cgi?id=722791 + +2014-01-24 09:28:05 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Break the loop immediately if we found an empty queue + No need to continue looking at all the others + +2014-01-23 15:47:23 +0100 Per x Johansson + + * plugins/elements/gstmultiqueue.c: + multiqueue: Allow growing a queue if all other queues are not linked + In the case where one singlequeue is full and all other are not linked, the + growing of the full queue does not work correctly. The result depends on if + the full queue is last in the queue list or not. + https://bugzilla.gnome.org/show_bug.cgi?id=722891 + +2014-01-22 11:10:01 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Minor code cleanup + !check_sticky()==GST_FLOW_OK is a bit confusing, compared to + check_sticky()!=GST_FLOW_OK. + +2014-01-20 15:26:54 +0100 Fabian Kirsch + + * tests/check/pipelines/parse-launch.c: + parse: Additional tests for parser + https://bugzilla.gnome.org/show_bug.cgi?id=710034 + +2014-01-18 14:48:35 +0100 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Properly copy mutexes around when creating a copy of a filter iterator + +2014-01-18 14:34:45 +0100 Sebastian Dröge + + * tests/check/gst/gstiterator.c: + iterator: Add unit tests for filtering, recursive filtering and locking + https://bugzilla.gnome.org/show_bug.cgi?id=711138 + +2014-01-18 14:43:20 +0100 Stewart Brodie + + * gst/gstiterator.c: + iterator: Preserve the master lock when creating recursive iterator filters with the same lock + This way we make sure that a) the lock is always taken when checking + the cookie and calling the iterator's next functions and b) it is + not taken while calling any of the iterator filter functions. + https://bugzilla.gnome.org/show_bug.cgi?id=711138 + +2014-01-17 22:53:01 -0300 Thiago Santos + + * gst/gstpad.c: + pad: fix sticky event leak after sticky_events_foreach + events_foreach adds an extra ref when giving the event to the + user function. In case it was unrefed by the user, this extra ref + disappeared, but events_foreach still should unref again to + lose its own ref before removing the event from the array. + https://bugzilla.gnome.org/show_bug.cgi?id=722467 + +2014-01-16 20:11:03 +0100 Stefan Sauer + + * gst/gst.c: + * gst/gstinfo.c: + info: move some env-var checks from gst to gstinfo as well + We were doing some log related initialisation in gst.c after calling + _priv_gst_debug_init(). Just move it there for consistency. + +2014-01-16 18:16:35 +0100 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: Only set caps on the srcpad if it's activated in push mode + https://bugzilla.gnome.org/show_bug.cgi?id=722289 + +2014-01-16 12:28:47 +0100 Fabian Kirsch + + * gst/parse/grammar.y: + parse: Some minor fixes + Fix destructor segfaulting + Expect 0 grammar-ambiguities + Fix order of bin-properties assignment + https://bugzilla.gnome.org/show_bug.cgi?id=710034 + +2014-01-15 19:28:01 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + inputselector: removing duplicate field position + It is already stored inside the GstSegment struct and + was only duplicating information. Also removed some + weird positon if/else that would possibly change the + segment that was going to be pushed downstream + +2014-01-15 00:12:26 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: prevent buffering forever with playbin + When prerolling/buffering, multiqueue has its buffers limit set + to 0, this means it can take an infinite amount of buffers. + When prerolling/buffering finishes, its limit is set back to 5, but + only if the current level is lower than 5. It should (almost) never be + and this will cause prerolling/buffering to need to wait to reach the + hard bytes and time limits, which are much higher. + This can lead to a very long startup time. This patch fixes this + by setting the single queues to the max(current, new_value) instead + of simply ignoring the new value and letting it as infinite(0) + https://bugzilla.gnome.org/show_bug.cgi?id=712597 + +2014-01-15 11:12:08 +0100 Sebastian Dröge + + * gst/gstsegment.c: + segment: gst_segment_offset_running_time() will be available in 1.2.3 + +2014-01-14 16:15:21 -0500 Nicolas Dufresne + + * docs/gst/gstreamer-sections.txt: + doc: Update sections with the new rounding macros + +2014-01-14 16:15:02 -0500 Nicolas Dufresne + + * gst/gstutils.h: + util: Add GST_ROUND_UP_N and GST_ROUND_DOWN_N + These are generic rounding macro that works for any power of two. + +2014-01-14 16:47:38 +0100 Sebastian Dröge + + * tests/check/elements/tee.c: + tee: Add unit test for requesting pad names + +2014-01-14 16:45:53 +0100 Sebastian Dröge + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + tee: Make sure to give pads the name that was requested + Also check for uniqueness and make sure we create a new + pad index properly if some were requested with names but + the new one is not. + +2014-01-14 15:52:26 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parse: Make sure to create and link chains in the order as written + Make this work again: + audiotestsrc ! tee name=t t.src_0 ! queue ! fakesink t.src_1 ! queue ! fakesink + and this fail again: + audiotestsrc ! tee name=t t.src_1 ! queue ! fakesink t.src_0 ! queue ! fakesink + as tee just counts itself and does not care about the pad names we request + from it. + +2014-01-14 13:45:34 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parse: Remove some C99-style comments + +2014-01-14 13:44:11 +0100 Sebastian Dröge + + * gst/parse/types.h: + parse: Use GSlice for allocating and freeing links and chains + +2014-01-14 13:42:20 +0100 Sebastian Dröge + + * gst/parse/types.h: + parse: Add comment about why we disable the "tracing" + It did not print anything useful before anyway, everything + was commented out. + Also remove some unneeded struct members. + +2014-01-14 13:36:24 +0100 Sebastian Dröge + + * tests/check/pipelines/parse-launch.c: + parse-launch: Add some more failing pipelines + Also convert some comments about valgrind warnings to + FIXME comments. These were leaking since some time already. + +2014-01-10 21:10:17 +0100 Fabian Kirsch + + * gst/parse/grammar.y: + * gst/parse/parse.l: + * gst/parse/types.h: + * tests/check/pipelines/parse-launch.c: + parse: Refactor grammar, make it more consistent and fix conflicts + https://bugzilla.gnome.org/show_bug.cgi?id=710034 + +2014-01-13 20:48:32 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + docs: ensure GstBufferPools shows up as with GObject features + GstBufferPool is a GstObject, add the _get_type function to the types file. + +2014-01-13 08:37:37 -0300 Thiago Santos + + * tests/check/libs/baseparse.c: + tests: baseparse: add test for reverse playback on passthrough + Baseparse stores buffers for reverse playback to push on the next + DISCONT, the issue was that it wouldn't ever check for a discont + on passthrough mode as it skips all real parsing. This test + was create to verify this issue and prevent it from happening again + https://bugzilla.gnome.org/show_bug.cgi?id=721941 + +2014-01-11 10:49:17 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/baseparse.c: + tests: baseparse: add basic test for baseparse + Just a small test to check that basic playback works + +2014-01-10 09:10:06 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: do not accumulate buffers on passthrough mode + If on passthrough during reverse playback, do not accumulate buffers as + baseparse will never check for DISCONT flag to push those buffers. + So just push buffers downstream as if it was forward playback. + https://bugzilla.gnome.org/show_bug.cgi?id=721941 + +2014-01-06 21:47:22 +0100 Stefan Sauer + + * libs/gst/base/gstbasesrc.c: + basesrc: don't confuse GST_PAD_MODE_NONE and PULL + Use a switch-case to explicitly handle all pad-modes. This way we don't log an error when the pad is not yet activated. + +2014-01-09 07:56:55 +0100 Stefan Sauer + + * gst/gstobject.c: + gstobject: add FIXME and docs for the disabled notify on parent + We haven't found a way to re-enable emitting notify and deep-notify for parent + changes. Add a FIXME-2.0 and a doc blob on the property. See #693281. + +2014-01-08 16:28:54 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: do not ignore TIME segments + TIME segments are being ignored and a standard initialized + segment is used instead. This causes issues as not properly detecting + reverse playback or not cliping output based on the segment. + This seems to be a regression from one of the GstSegment/GstEvent + redesigns on the 0.10 -> 1.0 transition + +2014-01-08 15:47:10 +0100 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: improve check, also check stream-time + +2014-01-08 15:31:28 +0100 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: add unit test for segment _offset_running_time() + Add a unit test to check that positive and negative offsets are applied + correctly in various cases. + +2014-01-08 15:23:00 +0100 Wim Taymans + + * gst/gstsegment.c: + segment: take offset into account in _to_position() + Take the offset into account when converting between running-time and + segment positions. + +2014-01-08 14:57:04 +0100 Wim Taymans + + * gst/gstpad.c: + pad: use new segment offset method to apply the offset + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=721422 + +2014-01-08 14:54:47 +0100 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + * win32/common/libgstreamer.def: + segment: add method to offset the segment running-time + Add a method that can apply an offset to the calculated running-time of + a segment. + +2014-01-08 14:52:04 +0100 Wim Taymans + + * libs/gst/base/gstcollectpads.c: + collectpads: take offset into account for expected segment position + The firt valid segment position is start + offset. + Also add some more debug and a FIXME + +2014-01-08 14:50:29 +0100 Wim Taymans + + * gst/gstinfo.c: + info: debug segment offset field as well + +2014-01-08 09:53:09 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Allow growing a queue if all other queues are not linked + See https://bugzilla.gnome.org/show_bug.cgi?id=719893 + +2014-01-07 16:18:37 +0100 Wim Taymans + + * plugins/elements/gstfilesrc.c: + filesrc: don't try to seek to -1 offset + The offset can be -1 when we are configured in TIME format. Instead of + failing the seek and erroring, do what and offset of -1 is supposed to + do and simply read from the current offset. + +2014-01-06 21:04:32 +0100 Stefan Sauer + + * libs/gst/base/gstbasesrc.c: + basesrc: demote error to warning + This is not an error. A subclass returning FALSE for is_seekable() is one way of + saying that we can't operate in pull mode. + +2014-01-03 11:47:23 +0800 YanpingZhang + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix hanging if shut down while handling a serialized query + https://bugzilla.gnome.org/show_bug.cgi?id=721253 + +2014-01-02 16:22:37 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: remove pending_segment as it was being misused + It wasn't required, instead baseparse was using it to check the media + caps to identify if it was handling audio or video. + The pending_segment was removed and a checked_media boolean + replaced it for a more accurate naming. + https://bugzilla.gnome.org/show_bug.cgi?id=721350 + +2014-01-02 13:43:54 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: push pending events before GAP event + A GAP event is handled as an empty buffer by sinks and they expect + to receive start up events before GAP events (like a segment). + This is important specially if there is a GAP at the beginning of + a stream (before any buffers) so that the segment event can be + pushed downstream before the GAP + https://bugzilla.gnome.org/show_bug.cgi?id=721350 + +2014-01-02 13:41:25 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: refactor pending events pushing + Refactor code repeated 3 times to a common function + https://bugzilla.gnome.org/show_bug.cgi?id=721350 + +2014-01-02 20:17:58 +0100 Stefan Sauer + + * docs/design/part-toc.txt: + design/part-toc.txt: update design docs + +2014-01-02 13:34:52 +0100 Sebastian Dröge + + * tests/check/gst/gstpad.c: + pad: Add unit test for adding/removing blocking probes while a pad is blocked + And make sure that these new probes are actually called if they should + instead of silently blocking the pad forever. + https://bugzilla.gnome.org/show_bug.cgi?id=721289 + +2014-01-02 13:33:20 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Check if new probes need to be called when adding/removing some + This allows blocking a pad, add a new blocking probe, removing + the first probe and then having the second probe called. Which + could then decide that data-flow should actually continue + instead of blocking now. + https://bugzilla.gnome.org/show_bug.cgi?id=721289 + +2014-01-02 11:13:27 +0100 Sebastian Dröge + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + tee: Remove dyn lock + It was used for pad-alloc in 0.10 but currently is completely unused + and not necessary. All pad access is protected by the tee object lock + and keeping another reference to the current pad. + +2014-01-02 11:09:59 +0100 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Keep another ref to our one and only srcpad around while pushing + A pad probe on that pad might otherwise just release the pad, drop + the last reference and cause great misery. + https://bugzilla.gnome.org/show_bug.cgi?id=721300 + +2013-12-30 19:03:22 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Keep an extra ref of the pad when calling an IDLE probe immediately + The callback might destroy the pad. + +2013-12-30 18:44:24 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Only call IDLE probes if we are actually idle + Also only check the data types for non-IDLE probes. When we + are idle, we have no data type obviously. + Previously we were calling IDLE probes during data flow whenever + a non-blocking probe would be called. The pad was usually not idle + at that time. + +2013-12-30 16:10:08 +0000 Tim-Philipp Müller + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: remove unnecessary NULL check + Error is never NULL when we break out of the loop. + COVERITY CID 1037151 + +2013-12-30 16:05:47 +0000 Tim-Philipp Müller + + * libs/gst/net/gstnettimeprovider.c: + Revert "nettimeprovider: Remove dead code" + This reverts commit 9649cd4ca19a75d0319117a77a7609e4b8c96533. + This is not right, and it's also not what coverity + is complaining about. + +2013-12-30 16:47:32 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Remove unneeded checks + item is guaranteed to be non-null. + COVERITY CID 1037152 + COVERITY CID 1037153 + +2013-12-30 16:34:08 +0100 Edward Hervey + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: Remove dead code + err is always NULL by the point we reach this line + COVERITY CID 1037151 + +2013-12-30 14:47:19 +0100 Stefan Sauer + + * gst/gsttaglist.h: + taglist: fix since marker again (1.3 -> 1.4) + Since markers should point to the appropriate stable version. + +2013-12-30 14:40:40 +0100 Stefan Sauer + + * gst/gsttaglist.h: + taglist: fix since-marker in docs (we're in 1.3.X) + +2013-12-30 14:22:37 +0100 Stefan Sauer + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: add a tag for midi base note numbers + Audio files containing sampled instruments can have metadata describing the note + that was played on the instrument. + +2013-12-30 10:01:39 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Don't ignore probe callback return value when immediately calling IDLE probe + https://bugzilla.gnome.org/show_bug.cgi?id=721096 + +2013-12-29 14:06:55 +0000 Pedro Côrte-Real + + * scripts/git-update.sh: + scripts: git-update.sh: fix for non-master branches + Pull from tracking branch instead of origin/master, so + that this works with e.g. 1.2 as well. + +2013-12-27 12:55:02 +0100 Sebastian Dröge + + * gst/parse/Makefile.am: + * gst/parse/parse.l: + parse: Use GLib malloc/free/realloc functions + https://bugzilla.gnome.org/show_bug.cgi?id=720100 + +2013-12-26 12:16:26 +0000 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: create-uninstalled-setup: re-use existing master branch if it exists + When creating separate checkout for non-master branches. + +2013-12-26 11:39:27 +0100 Erik Andresen + + * docs/manual/advanced-dataaccess.xml: + docs: fix memory leak of appsink example in manual + https://bugzilla.gnome.org/show_bug.cgi?id=721076 + +2013-12-22 22:33:12 +0000 Tim-Philipp Müller + + * autogen.sh: + * common: + Automatic update of common submodule + From dbedaa0 to d48bed3 + +2013-12-22 22:04:37 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for string changes + +2013-12-22 21:56:03 +0000 Tim-Philipp Müller + + * po/Makevars: + po: set gettext domain in Makevars so we don't have to patch the generated Makefile.in.in + https://bugzilla.gnome.org/show_bug.cgi?id=705455 + +2013-12-20 14:41:06 +0100 Wim Taymans + + * gst/gstutils.h: + utils: Add round down 128 macro for completeness + +2013-11-13 17:06:23 -0500 Nicolas Dufresne + + * gst/gstutils.h: + utils: Add round up 128 macro + +2013-12-20 14:30:22 +0100 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Setting the PROXY_CAPS flag on the srcpad does not make much sense + funnel outputs whatever one of the upstreams currently outputs, a caps + query to a random upstream does not give the right answer here. + +2013-12-20 11:37:53 +0100 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Proxy CAPS and ALLOCATION queries + +2013-11-18 10:46:00 -0300 Thiago Santos + + * plugins/elements/gstmultiqueue.c: + multiqueue: post 100% buffering if single queue is not linked + This makes buffering stop in case a stream switch happens. This is + important for adaptive streams that can disable not-linked streams + to avoid consuming the network bandwidth. + https://bugzilla.gnome.org/show_bug.cgi?id=719575 + +2013-12-18 05:19:46 -0500 William Jon McCann + + * docs/manual/appendix-integration.xml: + docs: fix project links + https://bugzilla.gnome.org/show_bug.cgi?id=720665 + +2013-12-10 15:53:54 +0100 David Svensson Fors + + * libs/gst/base/gstbasesrc.c: + basesrc: use segment start if DTS for first buffer is unset + https://bugzilla.gnome.org/show_bug.cgi?id=720199 + +2013-12-12 17:17:40 +0000 Matthieu Bouron + + * scripts/gst-uninstalled: + gst-uninstalled: add gstreamer-vaapi paths + https://bugzilla.gnome.org/show_bug.cgi?id=720337 + +2013-12-14 21:20:45 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/bitreader-noinline.c: + * tests/check/libs/bytereader-noinline.c: + * tests/check/libs/bytewriter-noinline.c: + tests: add unit test for bitreader, bytereader and bytewriter with no inlining used + +2013-12-14 18:38:41 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.h: + bytereader: add inline variant of gst_byte_reader_init() + +2013-12-14 18:31:38 +0000 Tim-Philipp Müller + + * libs/gst/base/gstqueuearray.c: + docs: fix docs for gst_queue_array_peek_head() + +2013-12-14 19:08:35 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parse: Don't define yyscan_t twice + https://bugzilla.gnome.org/show_bug.cgi?id=720316 + +2013-12-13 22:51:32 +0000 Tim-Philipp Müller + + * docs/random/moving-plugins: + docs: moving plugins: minor 0.10 -> 1.0 fix + Spotted by Jay Fenlason + +2013-12-11 14:42:34 +0100 Wim Taymans + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue: don't ignore event return value + Pass the event return value upstream. + Remove strange goto construct. + +2013-12-10 18:30:03 -0500 Edward Hervey + + * tools/gst-launch.c: + gst-launch: Handle taglist copy failure + If we couldn't copy the tags, just return instead of trying to use bogus + values. + +2013-12-10 18:25:22 -0500 Edward Hervey + + * tools/gst-inspect.c: + gst-inspect: Index features are no more + So remove code that will never be used + +2013-12-10 17:53:24 -0500 Edward Hervey + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstvalue: Fix comparision of double range + Checking twice the lower bound is great (you never know, it might change + between the two calls by someone using emacs butterfly-mode), but it's a bit + more useful to check the higher bound are also identical. + Detected by Coverity + +2013-12-10 17:09:07 -0500 Edward Hervey + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: Fix out-of-bounds detection + We want to abort if we higher than the maximum *OR* lower than the minimum + accepted value. + Detected by Coverity. + +2013-12-07 19:04:16 +0000 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: add unit test for registering the same category twice + +2013-12-07 19:32:58 +0100 Víctor Manuel Jáquez Leal + + * gst/gstinfo.c: + info: return existing category if a debug category is registered twice + If a category with the same name is found when creating a new + one, the found category is returned instead of an invalid pointer. + Fixes issue with gst-vaapi (which uses an internal copy of the + codec parsers) caused by commit ccba9130. + https://bugzilla.gnome.org/show_bug.cgi?id=720036 + +2013-12-07 15:38:19 +0100 Sebastian Rasmussen + + * docs/design/part-negotiation.txt: + * docs/design/part-overview.txt: + * docs/design/part-progress.txt: + * docs/design/part-synchronisation.txt: + * docs/design/part-trickmodes.txt: + * docs/manual/advanced-buffering.xml: + * docs/manual/advanced-clocks.xml: + * docs/manual/outline.txt: + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-negotiation.xml: + * gst/gstatomicqueue.h: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.c: + * gst/gstcapsfeatures.c: + * gst/gstchildproxy.c: + * gst/gstconfig.h.in: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstparse.c: + * gst/gstparse.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpoll.c: + * gst/gstpreset.c: + * gst/gstquery.c: + * gst/gstregistry.c: + * gst/gstsegment.c: + * gst/gstsegment.h: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gsttocsetter.c: + * gst/gsttypefind.h: + * gst/gstutils.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytewriter-docs.h: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstqueuearray.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gsttestclock.c: + * libs/gst/net/gstnettimepacket.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + * win32/common/gstconfig.h: + docs: Fix typos in function/object descriptions + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720029 + +2013-12-07 15:40:32 +0100 Sebastian Rasmussen + + * gst/gstobject.c: + * gst/gstpad.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstsegment.c: + * tests/check/gst/gststructure.c: + Fix some typos in code comments and debug messages + https://bugzilla.gnome.org/show_bug.cgi?id=720029 + +2013-12-06 20:50:19 +0000 Stewart Brodie + + * gst/gststructure.c: + * gst/gsttaglist.c: + docs: clarify encoding of strings in GstStructures and taglists + https://bugzilla.gnome.org/show_bug.cgi?id=709262 + +2013-07-02 20:27:59 -0400 Olivier Crête + + * libs/gst/base/gstbasesrc.c: + basesrc: Set format to TIME if do-timestamp is TRUE + https://bugzilla.gnome.org/show_bug.cgi?id=702842 + +2013-12-05 00:26:13 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: don't try to remove already-removed GSource from main loop + It's considered a programming error in recent GLib versions now. + We may already have removed the source by returning FALSE from + the callback if it was fired. Fixes warning with newer GLibs + when interrupting a pipeline with Control-C. + +2013-12-04 17:35:18 -0500 Olivier Crête + + * gst/gstinfo.c: + info: Make sure the same category is not added twice + +2013-12-04 17:35:02 -0500 Olivier Crête + + * gst/gstinfo.c: + info: Protect __categories list in get_category with lock too + +2013-12-04 00:10:36 +0100 Sebastian Rasmussen + + * docs/Makefile.am: + * docs/design/Makefile.am: + docs: add missing files for distribution + * add some documentation files in docs/design + * add docs/list-ulink.xsl so check in docs/manual works + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=719814 + +2013-12-03 21:46:19 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add ACCEPT_INTERCEPT flag + Make a new flag on the pad that tweaks the default behaviour of the + accept-caps function. By default it will check for a subset of the + query-caps result but this is not always desirable. The query-caps + result contains all the constraints to make a good caps decision + upstream but sometimes, like for parsers, not all the constrained caps + fields are known upstream and then a subset check would fail. Switching + to an intersection makes this work again. + See https://bugzilla.gnome.org/show_bug.cgi?id=705024 + https://bugzilla.gnome.org/show_bug.cgi?id=677401 + +2013-12-02 22:22:36 -0500 Olivier Crête + + * plugins/elements/gstmultiqueue.c: + multiqueue: Wake up on reconfigure event + After patch bda406c4, the state of the singlequeue was set to OK, but nothing + would then wake up the thread, as the other wakeup functions only look at + singlequeues that are marked as having received as not-linked. + https://bugzilla.gnome.org/show_bug.cgi?id=708200 + +2013-11-30 12:15:37 +0100 Sebastian Rasmussen + + * docs/gst/gstreamer-sections.txt: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-sections.txt: + * docs/plugins/gstreamer-plugins-sections.txt: + * gst/gstcontext.c: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstobject.c: + * gst/gstpad.h: + * gst/gstvalue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstoutputselector.h: + docs: add missing docs, fixing doc errors + * add many missing declarations to sections + * GstController has been removed, update docs + * skip GstIndex when generating documentation + * rephrase so gtkdoc doesn't imagine return value + * add missing argument description for gst_context_new() + * document GstOutputSelectorPadNegotiationMode and move to header-file + https://bugzilla.gnome.org/show_bug.cgi?id=719614 + +2013-11-30 14:52:40 +0100 Sebastian Rasmussen + + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcaps.c: + * gst/gstcontext.c: + * gst/gstmeta.h: + * gst/gstpad.c: + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstqueuearray.c: + * libs/gst/check/gsttestclock.c: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + docs: cosmetic changes in references/decriptions + * fix typo GstBufferFlag -> GstBufferFlags + * fix typo GstFeatures -> GstCapsFeatures + * fix typo GstAllocatorParams -> GstAllocationParams + * fix typo GstContrlSources -> GstControlSource + * do not refer to gstcheck as an object + * make references gtk_init() and tcase_set_timeout() not be references + * gst_element_get_pad() renamed gst_element_get_static_pad() + * gst_clock_id_wait_async_full() renamed gst_clock_id_wait_async() + * _drop_element() is really gst_queue_array_drop_element() + * gst_pad_accept_caps() was removed, do not refer to it + * separate GST_META_TAG_MEMORY_STR declaration from description + * do not describe removed gst_collect_pads_collect() + * correctly link to GstElementClass' virtual set_context() + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=719614 + +2013-11-29 14:00:35 -0500 Olivier Crête + + * gst/parse/Makefile.am: + parse: Manually insert priv_gst_parse_yyget/set_column prototypes for older flex + Older versions of flex (before 2.5.36) don't add the prototype, so it must + be added manually. We can't check by the version number, because Debian/Ubuntu + patched it into their 2.5.35 at some point. + +2013-11-19 11:41:54 -0300 Thiago Santos + + * gst/gstutils.c: + gstpad: drop assertion on gst_pad_peer_query_position + It is a 'both' query, so it can be sent both ways + +2013-11-18 18:11:56 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + inputselector: handle gap events + Use gap events to advance the selector's pad position. + This is relevant to keep sync_streams mode working when one of the + streams doesn't have data all the time. + +2013-11-29 17:02:41 +0100 Wim Taymans + + * gst/gstghostpad.c: + Revert "ghostpad: copy sticky events to SRC ghostpads" + This reverts commit 8162a583a4dd68582bf186e2e47a8f0d68fa1980. + Automatically copying the sticky events makes it impossible for apps + and elements to filter the events with event probes. This causes + regressions (See #719437). The best option is to let the app/element + copy and filter the events themselves after the ghostpad target is + set. + +2013-11-19 15:03:35 +0100 Fabian Kirsch + + * gst/parse/.gitignore: + * gst/parse/Makefile.am: + * gst/parse/grammar.y: + parse: fix segfaulting prototype-mismatch + Now YYDEBUG is always set, so check it's value + https://bugzilla.gnome.org/show_bug.cgi?id=712679 + +2013-11-27 18:32:22 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Fix docstring for round-trip-limit and uninit access warning. + Fix a typo in a doc string - the property is round-trip-limit, not + roundtrip-limit. + Remove a bogus GST_WARNING that can print an uninitialised variable + and is redundant anyway. + +2013-11-26 11:56:46 +0100 Carlos Rafael Giani + + * libs/gst/net/gstnetclientclock.c: + netclock: Add round-trip-limit parameter + Sometimes, packets might take a very long time to return. Such packets + usually are way too late and destabilize the regression with their + obsolete data. On Wi-Fi, round-trips of over 7 seconds have been observed. + If the limit is set to a nonzero value, packets with a round-trip period + larger than the limit are ignored. + Signed-off-by: Carlos Rafael Giani + https://bugzilla.gnome.org/show_bug.cgi?id=712385 + +2013-11-25 19:04:38 -0500 Olivier Crête + + * gst/gstquery.c: + query: Fix gi annotations of gst_structure_new_custom() + +2013-11-26 02:43:54 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Fix C99 comment + +2013-11-26 02:17:36 +1100 Jan Schmidt + + * libs/gst/net/gstnetclientclock.c: + netclock: Implement rolling-average filter on observations. + Keep a rolling average of the round trip time for network clock + observations, favouring shorter round trips as being more accurate. + Don't pass any clock observation to the clock slaving if it has a + round-trip time greater than 2 times the average. + Actual shifts in the network topology will be noticed after some + time, as the rolling average incorporates the new round trip times. + +2013-11-25 20:33:42 +1100 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + basesink: Add debug into gst_base_sink_default_query() for accept_caps + +2013-11-14 15:32:59 +0100 Philippe Normand + + * tools/gst-launch.c: + gst-launch: exit with an error code when an error occured + If the pipeline failed to pre-roll or the user interrupted the + execution then set the exit code to a positive value. + https://bugzilla.gnome.org/show_bug.cgi?id=712300 + +2013-11-22 01:35:18 +0100 Sebastian Rasmussen + + * gst/gstutils.c: + gstutils: Escape stream id format in comments + These must be escaped for gtk-doc to parse the comments without warnings. + https://bugzilla.gnome.org/show_bug.cgi?id=714989 + +2013-11-21 15:04:04 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstinfo.c: + * gst/gsturi.c: + gst: g_memmove() is deprecated + Just use plain memmove(), g_memmove() is deprecated in + recent GLib versions. + https://bugzilla.gnome.org/show_bug.cgi?id=712811 + +2013-11-21 14:13:16 +0100 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: copy sticky events to SRC ghostpads + Update the sticky events on SRC ghostpads when retargeting. This ensures + that the ghostpad has the exect same sticky events as the target pad. We + don't want to do this for SINK ghostpads, they got the events from + downstream and we don't want to overwrite them with the target pad + events. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=707621 + +2013-11-21 12:28:00 +0100 Wim Taymans + + * gst/gstpad.h: + pad: move debug function closer to the enum it debugs + +2013-11-18 21:39:54 +0100 Wim Taymans + + * gst/gstpluginloader.c: + pluginloader: check read/write before closed + first try to read or write on the socket before checking the closed state. This + makes sure we handle all data on the socket before erroring out. + +2013-11-18 21:37:06 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: improve debug + So that we can see the return values of functions in the log. + +2013-11-18 15:28:32 +0000 Tim-Philipp Müller + + * tests/check/gst/gstbus.c: + tests: fix GstBus unit test with latest GLib + g_source_remove() works on the default main context, and + we're doing things with a custom context. Fixes warning + with newer GLib versions. + +2013-11-16 12:24:56 +0000 Tim-Philipp Müller + + * gst/gstbin.h: + * gst/gstbuffer.c: + * gst/gstinfo.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstqueuearray.c: + docs: cosmetic since marker fixes + +2013-11-16 15:17:57 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: ensure to preserve upstream timestamps + ... rather than have subclass coming up with an internally parsed one. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=707230 + +2013-11-15 07:32:48 +0100 Sebastian Dröge + + * gst/gstbin.c: + bin: Resync iterator if necessary + +2013-11-13 19:55:41 +0100 Sebastian Dröge + + * gst/gstvalue.c: + * tests/check/gst/gstcaps.c: + value: Lists with all equal elements are equal to a single value + Otherwise caps containing f={X, X} are not compatible with f=X + https://bugzilla.gnome.org/show_bug.cgi?id=709253 + +2013-11-11 16:47:06 +0000 Tim-Philipp Müller + + * gst/gstsystemclock.c: + systemclock: add Since markers for new API + +2013-11-11 17:29:48 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Really update the def files + +2013-11-11 17:02:35 +0100 Sebastian Dröge + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + win32: Update def files + +2013-11-11 16:50:13 +0100 Sebastian Dröge + + * scripts/gst-uninstalled: + gst-uninstalled: Also export LD_LIBRARY_PATH for gst-plugins-gl + +2013-11-05 12:22:51 +0000 Matthieu Bouron + + * scripts/gst-uninstalled: + gst-uninstalled: export gst-plugins-gl DYLD_LIBRARY_PATH + https://bugzilla.gnome.org/show_bug.cgi?id=711488 + +2013-11-06 18:46:19 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads.c: + collectpads: Always send SEEK events to all pads, even if one fails + +2013-11-06 18:41:10 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + collectpads: Update documentation for flushing seek handling + +2013-11-06 18:05:22 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads.c: + collectpads: Don't leak seek events + +2013-09-16 09:55:58 +0200 Alessandro Decina + + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + collectpads: implement flushing seek support + Implement common flushing seek logic in GstCollectPads. Add new + API so that elements can opt-in to using the new logic + (gst_collect_pads_src_event_default) and can extend it + (gst_collect_pads_set_flush_function) to flush any internal + state. + See https://bugzilla.gnome.org/show_bug.cgi?id=706779 and + https://bugzilla.gnome.org/show_bug.cgi?id=706441 for the + background discussion. + API: gst_collect_pads_set_flush_function() + API: gst_collect_pads_src_event_default() + https://bugzilla.gnome.org/show_bug.cgi?id=708416 + +2013-09-16 08:35:37 +0200 Alessandro Decina + + * tests/check/libs/collectpads.c: + tests: collectpads: add flushing seek tests + https://bugzilla.gnome.org/show_bug.cgi?id=708416 + +2013-09-16 08:31:47 +0200 Alessandro Decina + + * tests/check/libs/collectpads.c: + tests: collectpads: tweak stub _collect to push all buffers + https://bugzilla.gnome.org/show_bug.cgi?id=708416 + +2013-09-16 08:26:25 +0200 Alessandro Decina + + * tests/check/libs/collectpads.c: + tests: collectpads: update my email address + https://bugzilla.gnome.org/show_bug.cgi?id=708416 + +2013-11-11 13:27:27 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Don't use gst_buffer_get_size() when possible + Makes qst_queue_locked_dequeue 20% faster + +2013-11-11 12:25:14 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + * tests/check/gst/gstsystemclock.c: + * win32/common/libgstreamer.def: + systemclock: Add gst_system_clock_set_default + Used for setting the default system clock that is obtained through + gst_system_clock_obtain(), which is sometimes needed for unit + testing. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711269 + +2013-11-04 18:57:18 +0100 Stefan Sauer + + * tools/gst-typefind.c: + typefind: use g_get_prgname() for error message + +2013-11-06 10:15:59 +0100 Wim Taymans + + * plugins/elements/gstvalve.c: + valve: proxy caps and allocation + Proxy the caps queries on the srcpad as well. + Proxy the allocation query on the sinkpad. + +2013-11-05 11:17:25 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 865aa20 to dbedaa0 + +2013-11-04 13:56:37 -0800 Reynaldo H. Verdejo Pinochet + + * tools/gst-inspect.c: + gst-inspect: Remove some dead code + +2013-11-04 11:48:47 +0100 Alessandro Decina + + * gst/gstmemory.c: + memory: explicitly cast to GstLockFlags to avoid compiler warnings + +2013-11-02 15:36:19 +0100 Mark Nauwelaerts + + * gst/gstsegment.c: + segment: resurrect sanitizing start and stop for seeking + +2013-11-02 15:42:07 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + basesrc: mind boggling wrap when comparing offsets + +2013-11-02 15:38:13 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: try first frame pts and dts for a valid start timestamp + +2013-11-02 15:37:30 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: print proper variable in debug statement + +2013-11-01 16:35:59 +0000 Olivier Crête + + * gst/gstparse.c: + * tests/check/pipelines/parse-launch.c: + parse: Make the FATAL_ERRORS flag also work without a GError + Also add a unit tests + +2013-10-23 15:56:20 +0100 Matthieu Bouron + + * tools/gst-launch.c: + gst-launch: fix potential uninitialized variable warning + https://bugzilla.gnome.org/show_bug.cgi?id=710758 + +2013-10-31 16:16:48 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-MT-refcounting.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-framestep.txt: + * docs/design/part-messages.txt: + * docs/design/part-probes.txt: + * docs/design/part-relations.txt: + docs: fix common typos emited/eachother/... + +2013-10-30 21:53:36 +0100 Sebastian Dröge + + * gst/gstutils.c: + * gst/gstutils.h: + utils: Add some attributes and reorganize code to fix compiler warnings + gstutils.c:3659:41: error: format string is not a string literal + [-Werror,-Wformat-nonliteral] + gchar *expanded = g_strdup_vprintf (stream_id, var_args); + https://bugzilla.gnome.org/show_bug.cgi?id=710621 + +2013-10-25 14:56:16 +0200 Antonio Ospite + + * docs/pwg/advanced-negotiation.xml: + pwg: rename the "samplerate" variable to make example code compilable + In one of the examples about gst_my_filter_setcaps() there is a variable + declared as "rate", but then the name "samplerate" is used when setting + the caps. + Use the name "rate" everywhere in gst_my_filter_setcaps(). + https://bugzilla.gnome.org/show_bug.cgi?id=710876 + +2013-10-29 18:09:32 +0100 Fabian Kirsch + + * docs/manual/basics-elements.xml: + doc: fix forward reference about ghost pads + https://bugzilla.gnome.org/show_bug.cgi?id=711089 + +2013-10-28 12:55:19 +0000 Tim-Philipp Müller + + * docs/design/part-buffer.txt: + * docs/design/part-caps.txt: + * docs/design/part-context.txt: + * docs/design/part-messages.txt: + docs: design: fix some fixes + +2013-10-26 09:48:06 +0100 Tim-Philipp Müller + + * docs/faq/developing.xml: + docs: flesh out gst-uninstalled entry in faq some more + https://bugzilla.gnome.org/show_bug.cgi?id=709916 + +2013-10-16 15:00:41 +0200 Fabian Kirsch + + * docs/faq/developing.xml: + docs: FAQ update to mention create-uninstalled-setup.sh + https://bugzilla.gnome.org/show_bug.cgi?id=709916 + +2013-10-25 21:29:01 +0200 Stefan Sauer + + * gst/gstregistrychunks.c: + registry: small cleanups and use object log variants more + +2013-10-25 21:28:30 +0200 Stefan Sauer + + * gst/gst_private.h: + private: remove left-over comment + The caps are saved in the registry. + +2013-10-25 18:51:53 +0200 Stefan Sauer + + * gst/gstregistrychunks.c: + registry: use g_slice_free for slice memory + Avoid memory list corruption, but g_free'ing slice memory. + +2013-10-23 18:16:54 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: flesh out the tracing design a little more + +2013-10-25 11:02:19 -0400 Luis de Bethencourt + + * gst/gstobject.c: + docs: fix typos in gstobject + +2013-10-21 18:01:21 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-meta.txt: + docs: Gram and nit fixes for part-meta.txt + +2013-10-14 22:03:50 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-element-source.txt: + docs: Gram and nit fixes for part-element-source.txt + +2013-10-14 21:54:31 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-element-sink.txt: + docs: Gram and nit fixes for part-sink.txt + +2013-10-14 18:43:40 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-conventions.txt: + docs: Gram and nit fixes for part-conventions.txt + +2013-10-14 18:34:06 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-controller.txt: + docs: Gram and nit fixes for part-controller.txt + +2013-10-14 18:24:18 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-context.txt: + docs: Gram and nit fixes for part-context.txt + +2013-10-14 18:13:35 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-clocks.txt: + docs: Gram and nit fixes for part-clocks.txt + +2013-10-14 18:05:43 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-caps.txt: + docs: Gram and nit fixes for part-caps.txt + +2013-10-14 17:44:27 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-buffer.txt: + docs: Gram and nit fixes for part-buffer.txt + +2013-10-14 17:29:19 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-bufferpool.txt: + docs: Gram and nit fixes for part-bufferpool.txt + +2013-10-14 05:39:19 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-buffering.txt: + docs: Gram and nit fixes for part-buffering.txt + +2013-10-13 21:16:47 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-messages.txt: + docs: Gram and nit fixes for part-messages.txt + +2013-10-13 20:42:40 -0700 Reynaldo H. Verdejo Pinochet + + * docs/design/part-memory.txt: + docs: Gram and nit fixes for part-memory.txt + +2013-10-18 08:58:05 +0100 Philip Withnall + + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetclientclock.h: + net: Constify a parameter to gst_net_client_clock_new() + Even though this parameter is not used, it should be const to fit in with the + coding standards for other similar parameters. Client code already passes in + const strings under the expectation that they won’t be modified. + https://bugzilla.gnome.org/show_bug.cgi?id=710442 + +2013-10-15 11:44:05 +0200 Sebastian Dröge + + * gst/gstdatetime.c: + datetime: Make sure to include gst_private.h before glib-compat-private.h + We need to define the GLib log domain before including glib.h, which is + included by glib-compat-private.h. + +2013-10-14 18:07:17 -0300 Thibault Saunier + + * docs/gst/gstreamer-sections.txt: + docs: Add gst_pad_store_sticky_event to sections.txt + So it appears in the generated documentation + +2013-09-29 17:35:11 +0200 Sebastian Rasmussen + + * plugins/elements/gstfilesrc.c: + * tests/check/elements/filesrc.c: + tests/filesrc: Set location in wrong state + Also remove incorrect comment about code possibly not being reachable + that is now exercised by the filesrc unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=709831 + +2013-10-12 16:16:09 +1100 Jan Schmidt + + * gst/gstparse.c: + * tests/check/pipelines/parse-launch.c: + parse: Fix transfer annotations for parse_launch functions. + gst_parse_launchv, gst_parse_launchv_full and gst_parse_launch_full + all return floating refs, the same as gst_parse_launch, which just + calls gst_parse_launch_full internally anyway. + Add a unit test assertion to check it's true. + Spotted by nemequ on IRC. + +2013-10-10 08:30:27 -0700 Reynaldo H. Verdejo Pinochet + + * docs/manual/appendix-checklist.xml: + * gst/gst.c: + * tests/misc/test-gstreamer-completion.sh: + core: Fix max DEBUG_LEVEL incongruence on 5 vs 9 + In the docs and the autocompletion logic the maximum + value jumped incongruently between 5 and 9. + +2013-10-10 13:19:09 +0200 Sebastian Dröge + + * tests/check/gst/gstcaps.c: + caps: Skip test_subset_duplication until the bug is fixed + https://bugzilla.gnome.org/show_bug.cgi?id=709253 + +2013-10-10 12:56:54 +0200 Fabian Kirsch + + * docs/manual/basics-elements.xml: + * docs/manual/basics-pads.xml: + * docs/manual/intro-motivation.xml: + * docs/manual/manual.xml: + docs: Fix some reference URIs + https://bugzilla.gnome.org/show_bug.cgi?id=709804 + +2013-10-02 13:03:54 +0200 Sebastian Dröge + + * tests/check/gst/gstcaps.c: + caps: Add a testcase for subset checks on lists with duplicated items + https://bugzilla.gnome.org/show_bug.cgi?id=709253 + +2013-10-09 15:36:48 -0300 Thibault Saunier + + * libs/gst/base/gstcollectpads.c: + collectpads: Call the collected function while it returns FLOW_OK + This allows us to make sure the elements is EOS and does not have + remaining buffers to be drained. + https://bugzilla.gnome.org/show_bug.cgi?id=709637 + +2013-10-05 10:08:30 +0100 Tim-Philipp Müller + + * docs/design/part-qos.txt: + docs: fix function name in qos design docs + +2013-10-02 12:30:54 +0100 Tim-Philipp Müller + + * tests/check/elements/multiqueue.c: + tests: use tcase_skip_broken_test() to skip broken multiqueue test + So that we get a warning in the output that reminds us that + something needs to be fixed. + +2013-10-02 11:24:02 +0200 Edward Hervey + + * tests/check/elements/multiqueue.c: + check: Disable multiqueue test_output_order check + The check itself is racy. + (CK_FORK=no GST_CHECK=test_output_order make elements/multiqueue.forever). + The problem is indeed the test and not the actual element behaviour. + The objects to push are being pulled out of the single internal queues in the + right order and at the right time... + But between: + * the moment the global multiqueue lock is released (which was used to detect + if we should pop and push downstream the next buffer) + * and the moment it is received by the source pad (which does the check) + => another single queue (like the unlinked pad) might pop and push a buffer + downstream + What should we do ? Putting a bigger margin of error (say 5 buffers) doesn't + help, it'll eventually fail. + I can't see how we can detect this reliably. + https://bugzilla.gnome.org/show_bug.cgi?id=708661 + +2013-09-25 19:06:55 -0300 Thiago Santos + + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: fix caps serialization when there are caps inside caps + Wrap caps strings so that it can handle serialization and deserialization + of caps inside caps. Otherwise the values from the internal caps are parsed + as if they were from the upper one + https://bugzilla.gnome.org/show_bug.cgi?id=708772 + +2013-09-28 08:40:42 +0200 Edward Hervey + + * gst/gstpluginloader.c: + pluginloader: Check errors on the proper fd + Most likely a copy-paste error from the block before. + If we're going to check for error/closed on the write fd... do it + on the write fd + +2013-09-26 14:09:02 -0600 Brendan Long + + * libs/gst/base/gstbasesrc.c: + docs: fix spelling of "generic" in GstBaseSrc's documentation. + https://bugzilla.gnome.org/show_bug.cgi?id=708870 + +2013-09-26 11:32:50 +0200 Wim Taymans + + * gst/gstpad.c: + pad: only check event order when something changed + Check the event order in dataflow only when something changed instead + of for each buffer. + +2013-09-24 18:28:05 +0100 Tim-Philipp Müller + + * README: + * common: + Automatic update of common submodule + From 6b03ba7 to 865aa20 + +2013-09-24 15:05:16 +0200 Sebastian Dröge + + * configure.ac: + configure: Actually use 1.3.0.1 as version to make configure happy + +2013-09-24 15:00:17 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.2.0 === + +2013-09-24 14:07:02 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.2.0 + +2013-09-24 14:06:28 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-09-24 13:10:36 +0200 Sebastian Dröge + + * tests/check/gst/gstcontext.c: + context: Add test for the context caching in GstBin + https://bugzilla.gnome.org/show_bug.cgi?id=708668 + +2013-09-24 12:47:52 +0200 Sebastian Dröge + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + Revert "Potential GstContext regression" + This reverts commit e658379534eb4a90b654d90f1d0bdf86f37c6e31. + This test commit should've never been pushed. Oops. + +2013-09-24 12:46:52 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Make sure to cache context types that we did not store yet + https://bugzilla.gnome.org/show_bug.cgi?id=708668 + +2013-09-24 10:29:06 +0100 Alex Ashley + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + Potential GstContext regression + Since the refactoring of GstContext (commits + qc9fa2771b508e9aaeecc700e66e958190476f, + a7f5dc8b8af837f01782d1572379948ff62daab7, + 690326f906dc82e41ea58b81cdb2e3e88b754, + d367dc1b0d4ecb37f4d27267e03d7bf0c6c06a6, and + 82d158aed3f2e8545e1e7d35085085ff58f18) I am no longer able to get + a shared context for an element that is used twice in a pipeline. + I used the documentation and eglglessink as my reference for + implementing the GstContext logic. + As the code was tied to a hardware decoder, I have ported the + GstContext code to fakesink to show the problem. Using the old + API a single ExampleMgr instance is created, but using the new + API each element is creating its own instance. + +2013-09-24 10:42:06 +0200 Sebastian Dröge + + * libs/gst/base/gstcollectpads.c: + collectpads: Make sure that the object lock is always taken when accessing the private pad list + https://bugzilla.gnome.org/show_bug.cgi?id=708636 + +2013-09-17 23:23:34 +0200 Mathieu Duponchelle + + * libs/gst/base/gstcollectpads.c: + collectpads: Use private pad list in set_flushing_unlocked + pads->data is the public list. It is dynamically rebuilt at each call to + check_collected, in check_pads to be specific. When you add a pad and + collectpads have been started, it is not added to the public list. + Thus there exists a possible race where : + 1) You would add a pad to collectpads while running. + 2) You set collectpads to flushing before check_collected has been called again + -> the pad is not set to flushing + 3) the pad starts pushing data as downstream might not be prepared, in the case + of adder it then returns FLOW_FLUSHING. + 4) elements like demuxers, when they get a FLOW_FLUSHING, stop their tasks, + never to be seen again. + https://bugzilla.gnome.org/show_bug.cgi?id=708636 + +2013-09-23 11:47:14 +0200 Wim Taymans + + * libs/gst/check/gsttestclock.c: + * tests/check/libs/gsttestclock.c: + tests: handle unscheduled entries correctly + Make the testclock return GST_CLOCK_UNSCHEDULED when an unscheduled entry is + used for gst_clock_wait() or gst_clock_wait_async(). + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708605 + +2013-09-22 11:09:36 +0200 Edward Hervey + + * scripts/gst-uninstalled: + gst-uninstalled: Allow specifying the checkout directory by env variable + For some rare cases, one might not be able to use the hardcoded $HOME/gst + location yet would still want to use the gst-uninstalled script as-is (which + has the benefit of being constantly updated). + For these cases, the checkout directory can be specified with the + GST_UNINSTALLED_ROOT environment variable. + Ex: + export GST_UNINSTALLED_ROOT=$HOME/somewhere/with/checkouts + And then just call gst-uninstalled directly: + $GST_UNINSTALLED_ROOT/gstreamer/gst-uninstalled + +2013-09-20 16:16:26 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From b613661 to 6b03ba7 + +2013-09-19 18:42:31 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 74a6857 to b613661 + +2013-09-19 17:34:27 +0100 Tim-Philipp Müller + + * autogen.sh: + * common: + Automatic update of common submodule + From 12af105 to 74a6857 + +2013-09-19 17:12:14 +0100 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + check: testclock: fix function guards + Should be g_return_*() not g_assert(), even if it's for tests only. + +2013-09-19 16:43:18 +0100 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + check: testclock: don't put code with side-effects in g_assert() + Fixes unit test failures when -DG_DISABLE_ASSERT is used. + https://bugzilla.gnome.org/show_bug.cgi?id=706551 + +2013-09-19 12:07:56 +0200 Edward Hervey + + * gst/gstcontext.c: + gstcontext: Fix return values some more + Return value is a boolean not a pointer + +2013-09-19 11:49:26 +0200 Sebastian Dröge + + * gst/gstcontext.c: + context: Fix return values for gst_context_has_context_type() in assertions + +2013-09-19 11:34:51 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.1.90 === + +2013-09-19 10:48:24 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.1.90 + +2013-09-19 10:05:51 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-09-19 09:49:40 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontext.c: + * gst/gstcontext.h: + * win32/common/libgstreamer.def: + context: Add convenience function gst_context_has_context_type() + +2013-09-19 09:42:15 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations + +2013-09-18 23:07:31 +0200 Sebastian Dröge + + * gst/gstmessage.c: + message: Implement getting the name of the context message types + +2013-09-17 21:36:22 +0200 Sebastian Dröge + + * gst/gstcontext.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * tests/check/gst/gstcontext.c: + context: Fix unit test for GstContext changes + +2013-09-17 14:34:47 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Update for GstContext changes + +2013-09-17 14:29:06 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + context: Update docs + +2013-09-17 14:25:10 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Implement context caching and propagation again + +2013-09-17 13:50:08 +0200 Sebastian Dröge + + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + message/query: Simplify CONTEXT messages/queries to only contain a single type + +2013-09-17 13:33:33 +0200 Sebastian Dröge + + * docs/design/part-context.txt: + * gst/gstcontext.c: + context: Update documentation + +2013-09-17 13:28:42 +0200 Sebastian Dröge + + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstinfo.c: + context: Change GstContext to contain only a single context + It was unintuitive that GstContext was actually a list of different + contexts. GstContext now is only a type string and a structure to + contain the actual context. + +2013-09-17 13:12:28 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + element: Remove GstContext caching + +2013-09-17 13:10:53 +0200 Sebastian Dröge + + * gst/gstcontext.c: + * gst/gstcontext.h: + context: Add persistent qualifier for a context + Non-persistent contexts are removed when elements go back + to NULL state, persistent contexts are not. Applications + most likely want to set persistent contexts. + +2013-09-17 13:10:16 +0200 Sebastian Dröge + + * gst/gstquery.h: + query: Make CONTEXT query upstream and downstream + +2013-09-17 13:09:34 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + event: Remove CONTEXT downstream event + This is going to be implemented with an upstream query instead + for consistency and simplicity. + +2013-09-13 14:41:45 +0200 Jonas Holmberg + + * gst/gst.c: + gst: Stop all unused threads in GThreadPool in gst_deinit() + Since the default number of max unused threads in GThreadPool has been + changed from 0 to 2 it needs to be set to 0 to stop all threads or + valgrind will report them as memory leaks. + +2013-09-10 16:39:30 +0100 Rico Tzschichholz + + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + controlbindings: fix pspec relaxation for control source properties + The change should have been from PARAM_CONSTRUCT_ONLY to + PARAM_CONSTRUCT, otherwise bindings are affected, since + they look for the CONSTRUCT flag. + See ec55363d + +2013-09-10 10:15:03 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Only update current level if we already downloaded a range + Otherwise queue->level is NULL and dereferencing that is not a good + idea in general. + https://bugzilla.gnome.org/show_bug.cgi?id=707648 + +2013-09-09 15:40:25 +0200 Sebastian Dröge + + * gst/gstmeta.h: + meta: Deprecate GST_META_TAG_MEMORY + The GQuarks are not exported by any public API + +2013-08-22 00:02:28 +0200 Mathieu Duponchelle + + * docs/gst/gstreamer-sections.txt: + * gst/gstmeta.h: + * win32/common/libgstreamer.def: + meta: Add a #define for memory metadata + +2013-08-22 00:01:44 +0200 Mathieu Duponchelle + + * gst/gstmeta.c: + * libs/gst/base/gstbasetransform.c: + basetransform: implement a default transform_meta. If a metadata has no dependency as shown by the tags, copy it. + +2013-08-22 21:32:36 +0200 Mathieu Duponchelle + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: API: Add gst_meta_api_type_get_tags() to get all meta tags. + +2013-09-09 14:21:56 +0200 Sebastian Dröge + + * tests/check/elements/capsfilter.c: + tests/capsfilter: Fix memory leak and compare caps directly instead of strcmp() + +2013-09-06 23:03:54 +0200 Sebastian Rasmussen + + * tests/check/elements/capsfilter.c: + tests/capsfilter: Test caps-related queries and property + +2013-09-06 15:09:46 -0300 Gustavo Noronha Silva + + * plugins/elements/gstqueue2.c: + Update the buffering state before stalling for more data + In some cases the wait for more data was happening without updating + the buffering state, meaning the API user would not be able to notice + it should pause the pipeline and update UI to indicate that is the + case, the video would likely stutter instead. + https://bugzilla.gnome.org/show_bug.cgi?id=707648 + +2013-09-04 15:28:10 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: preserve seqnum on segments after seeks + The seqnum of the segment after a seek should be the same of + the seek event. Downstream elements might rely on seqnums to + identify events related to a seek. + This is particularly important when a demuxer maps a TIME seek + into a BYTES seek for upstream and it needs to identify the + corresponding segment event and map it back into TIME to push + downstream, possibly using the values from the original seek + event. + https://bugzilla.gnome.org/show_bug.cgi?id=707530 + +2013-09-05 14:14:42 +0200 Zaheer Abbas Merali + + * libs/gst/base/gstcollectpads.c: + collectpads: Don't unref NULL GstCollectData + If a pad is removed while a collectpads element (say adder) is in a chain + function waiting to be collected, there is a possibility that an unref happens + on a NULL pointer. + https://bugzilla.gnome.org/show_bug.cgi?id=707536 + +2013-09-04 17:11:20 +0200 Christian Fredrik Kalager Schaller + + * gstreamer.spec.in: + Remove PyXML from spec file, it is not longer needed + +2013-09-04 14:40:57 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Add missing break after handling the GAP event + Thanks to Edward Hervey for noticing. + +2013-09-04 09:18:55 +0100 Tim-Philipp Müller + + * scripts/gst-plot-timeline.py: + * tools/Makefile.am: + tools: move gst-plot-timeline.py into scripts directory + So it's not in PATH in an uninstalled setup (thwarting + gst-play autocompletion). + +2013-09-03 23:59:05 +0200 Matej Knopp + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't reduce single queue visible size below its current level + If the multiqueue has automatically grown chances are good that + we will cause the pipeline to starve if the maximum level is reduced + below that automatically grown size. + https://bugzilla.gnome.org/show_bug.cgi?id=707156 + +2013-09-02 13:53:51 +0200 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + outputselector: Don't adjust segment->start to the current time when switching pads + This does not make any sense at all and breaks timestamp->running_time + calculations in unpredictable ways. + https://bugzilla.gnome.org/show_bug.cgi?id=707130 + +2013-08-29 23:18:31 +0200 Mathieu Duponchelle + + * plugins/elements/gstcapsfilter.c: + capsfilter: Delete link directly in pending_events. + When removing a segment event. + https://bugzilla.gnome.org/show_bug.cgi?id=707088 + +2013-08-29 11:07:38 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: demote log message, don't spam INFO level when handling buffer lists + +2013-08-28 13:26:28 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.1.4 === + +2013-08-28 12:36:16 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.1.4 + +2013-08-28 12:36:01 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-08-28 12:30:00 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hr.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/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2013-08-27 09:31:22 +0200 Alessandro Decina + + * plugins/elements/gstfilesink.c: + filesink: please gcc (avoid a warn_unused_result warning) + +2013-08-27 07:51:35 +0200 Alessandro Decina + + * plugins/elements/gstfilesink.c: + * tests/check/elements/filesink.c: + filesink: flush (discard data) on FLUSH_STOP + Reset the write position to 0 and truncate the file on FLUSH_STOP. + +2013-08-27 07:05:11 +0200 Alessandro Decina + + * tests/check/elements/filesink.c: + tests: filesink: small refactoring + +2013-08-26 13:19:10 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: gst-launch: don't print properties being reset when shutting down + It's just noise. + +2013-08-22 19:01:32 +0200 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: Don't push out identical caps + This avoids triggering plenty of extra code/methods/overhead downstream when + we can just quickly check whenever we want to set caps whether they are + identical or not + https://bugzilla.gnome.org/show_bug.cgi?id=706600 + +2013-08-21 12:21:43 +0100 Tim-Philipp Müller + + * gst/gstsample.c: + docs: flesh out gst_sample_get_buffer() a little + https://bugzilla.gnome.org/show_bug.cgi?id=706478 + +2013-08-20 23:59:29 -0700 Kerrick Staley + + * gst/parse/grammar.y: + parse: make grammar.y work with Bison 3 + YYLEX_PARAM is no longer supported in Bison 3. + https://bugzilla.gnome.org/show_bug.cgi?id=706462 + +2013-08-20 17:15:41 +0900 Wonchul Lee + + * gst/gstsample.h: + sample: Add gst_sample_copy() + https://bugzilla.gnome.org/show_bug.cgi?id=706454 + +2013-08-19 14:55:22 -0400 Olivier Crête + + * gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + buffer: Fix gst_buffer_memcmp() where the buffer is smaller than size + Also add unit tests for gst_buffer_memcmp + https://bugzilla.gnome.org/show_bug.cgi?id=706162 + +2013-08-20 17:06:49 +0100 Tim-Philipp Müller + + * gst/gstutils.c: + docs: flesh out gst_element_query_{duration,position} docs a bit + +2013-08-14 16:18:59 +0100 Matthieu Bouron + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: handle publisher and interpreted-by tags + https://bugzilla.gnome.org/show_bug.cgi?id=705999 + +2013-08-20 13:58:24 +0200 Sebastian Dröge + + * gst/gstpluginloader.c: + pluginloader: Don't call memcpy() with NULL src and 0 length + +2013-08-20 10:16:41 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Properly unlock the sinkpad streaming thread when deactivating the pad + https://bugzilla.gnome.org/show_bug.cgi?id=705835 + +2013-08-20 10:16:05 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Properly unlock the sinkpad streaming thread when deactivating the pad + https://bugzilla.gnome.org/show_bug.cgi?id=706360 + +2013-08-19 16:38:50 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Clean up after the streaming thread has stopped + https://bugzilla.gnome.org/show_bug.cgi?id=705835 + +2013-08-19 16:38:40 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Clean up after the streaming thread has stopped + https://bugzilla.gnome.org/show_bug.cgi?id=705835 + +2013-08-19 16:38:16 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Clean up after the streaming thread has stopped + https://bugzilla.gnome.org/show_bug.cgi?id=705835 + +2013-07-01 14:04:46 -0600 Brendan Long + + * gst/gstparse.h: + * gst/gstutils.c: + * gst/parse/grammar.y: + parse: Add GST_FLAG_NO_SINGLE_ELEMENT_BINS + This makes gst_parse_bin_from_description() return an element instead of + a bin if there's only one element. Also changed gstparse.c to use this, + so gst-launch won't create superfluous bins. + https://bugzilla.gnome.org/show_bug.cgi?id=703405 + +2013-08-16 20:36:53 +0200 Arnaud Vrac + + * gst/gstquery.c: + query: return NULL when parsing uri redirection that was not set + https://bugzilla.gnome.org/show_bug.cgi?id=706160 + +2013-08-18 11:48:40 +0200 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Update since marker for gst_buffer_extract_dup() to 1.0.10 + +2013-08-16 16:45:41 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: don't crash on EOS if queue is empty + Fixes spurious crash in test_simple_shutdown_while_running + unit test. + +2013-08-16 16:28:12 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: don't change global buffering state from within query handler + When a buffering query is handled it uses the get_buffering_percent() + function to get some statitics. Unfortunately this function also + calculates whether the queue should be buffering and adapts the + global queue2 state in case of state transitions from/to buffering + (including whether a buffering message was posted on the bus!). + This means that there is a race which can cause buffering messages + to never posted if the global state changes happen as a result of aa + query instead of resulting from bytes flowing in/out. + Spotted by Sjoerd Simons. + Change to only query state in get_buffering_percent() and update + state only in update_buffering(). + https://bugzilla.gnome.org/show_bug.cgi?id=705332 + +2013-08-16 12:54:38 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: update buffering when changing capacity + When the capacity of the queue changes, make sure we post an updated buffering + message because we might suddenly have completed the buffering stage. + +2013-08-15 15:35:08 +0200 Jonas Holmberg + + * gst/gst.c: + Free thread pools in gst_deinit() + +2013-08-16 11:03:30 +0200 Jonas Holmberg + + * libs/gst/check/gstcheck.c: + check: Call gst_deinit() at exit of all processes + +2013-08-14 21:41:23 +0100 Tim-Philipp Müller + + * gst/gstclock.c: + clock: simplify internal gst_clock_return_get_name() helper + +2013-08-14 17:44:48 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: improve flush-start handling + Use custom code to implement flush-stop, we can't reuse the set_flushing code + because we can't touch the live_playing flag and we need to signal the + streaming thread. + +2013-08-14 17:14:15 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: stop flushing in flush-stop + +2013-08-14 16:58:41 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle flush better + Unlock the streaming thread when flushing so that we can + insert the flush-stop correctly. + +2013-08-14 15:46:57 +0200 Edward Hervey + + * .gitignore: + .gitignore: ignore .dirstamp + +2013-08-14 07:21:06 +0200 Edward Hervey + + * libs/gst/check/Makefile.am: + check: Don't use nodist headers on gir scanner + Just creates noise and bogus symbols + +2013-08-07 18:20:03 +0200 Edward Hervey + + * gst/gstcompat.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + gst: minor docstring fixups to make g-i happy + note: the #ifndef move is actually a move of the "SECTION" docstring + +2013-08-13 17:14:53 +0200 Edward Hervey + + * .gitignore: + .gitignore: Ignore files from automake test-driver + +2013-08-07 18:24:40 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Add a property to disable passthrough + In some specific cases (like transmuxing) we want to force the element + to actually parse all incoming data even if the element deems it is not + necessary. + This property simply ignores requests from the element to enable passthrough + mode which results in processing always being enabled. + https://bugzilla.gnome.org/show_bug.cgi?id=705621 + +2013-08-07 21:26:01 -0300 Thiago Santos + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * win32/common/libgstbase.def: + dataqueue: add gst_data_queue_push_force + Adds a variant of the _push function that doesn't check the queue limits + before adding the new item. It is useful when pushing an element to the + queue shouldn't lock the thread. + One particular scenario is when the queue is used to serialize buffers + and events that are going to be pushed from another thread. The + dataqueue should have a limit on the amount of buffers to be stored to + avoid large memory consumption, but events can be considered to have + negligible impact on memory compared to buffers. So it is useful to be + used to push items into the queue that contain events, even though the + queue is already full, it shouldn't matter inserting an item that has + no significative size. + This scenario happens on adaptive elements (dashdemux / mssdemux) as + there is a single download thread fetching buffers and putting into the + dataqueues for the streams. This same download thread can als generate + events in some situations as caps changes, eos or a internal control + events. There can be a deadlock at preroll if the first buffer fetched + is large enough to fill the dataqueue and the download thread and the + next iteration of the download thread decides to push an event to this + same dataqueue before fetching buffers to other streams, if this push + locks, the pipeline will be stuck in preroll as no more buffers will be + downloaded. + There is a somewhat common practice in dash streams to have a single + very large buffer for audio and one for video, so this will always + happen as the download thread will have to push an EOS right after + fetching the first buffer for any stream. + API: gst_data_queue_push_force + https://bugzilla.gnome.org/show_bug.cgi?id=705694 + +2013-08-13 13:06:50 +0200 Sebastian Dröge + + * gst/gstallocator.c: + sysmem: Only copy the requested part of memory instead of the complete source memory + https://bugzilla.gnome.org/show_bug.cgi?id=705678 + +2013-08-13 12:11:19 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + * win32/common/libgstreamer.def: + query: add Since markers for new API and add to exports file + +2013-07-23 16:25:27 +0200 Andoni Morales Alastruey + + * gst/gstquery.c: + query: fix annotation for gst_query_parse_uri + +2013-04-19 12:14:54 +0200 Andoni Morales Alastruey + + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + query: add new redirection uri the URI query + +2013-08-12 09:25:34 -0300 Thiago Santos + + * gst/gstquery.c: + query: add some missing 'transfer none' gi annotations + The current documentation is controverse, while it states that the + returned value is valid only while the query is is valid, which presumes + a 'transfer none' policy. But the tooltip for the 'out' annotation + states the default is 'transfer-full'. + Add the missing 'transfer none' annotations to fix this. + +2013-08-08 12:08:31 +0200 Nicolas Dufresne + + * libs/gst/base/gstbytereader.c: + bytereader: Accelerate MPEG/H264 start code scanning + Accelerate MPEG/H264 start code scanning using Boyer-Moor bad character + heuristic. + https://bugzilla.gnome.org/show_bug.cgi?id=702357 + +2013-08-10 11:31:23 +0100 Tim-Philipp Müller + + * gst/gstpipeline.c: + pipeline: g-i: allow clock to be NULL in gst_pipeline_use_clock() + https://bugzilla.gnome.org/show_bug.cgi?id=705751 + +2013-08-07 14:17:28 -0300 Adrian Pardini + + * libs/gst/controller/gstdirectcontrolbinding.c: + controller: fixes int overflow with properties that span +-INT_MAX + When the range for a property is defined as -INT_MAX-1 .. INT_MAX, like + the xpos in a videomixer the following expression in the macro + definitions of convert_g_value_to_##type (and the equivalent in + convert_value_to_##type) + v = pspec->minimum + (g##type) ROUNDING_OP ((pspec->maximum - pspec->minimum) * s); + are converted to: + v = -2147483648 + (g##type) ROUNDING_OP ((2147483647 - -2147483648) * s); + (2147483647 - -2147483648) overflows to -1 and the net result is: + v = -2147483648 + (g##type) ROUNDING_OP (-1 * s); + so v only takes the values -2147483648 for s == 0 and 2147483647 + for s == 1. + Rewriting the expression as minimum*(1-s) + maximum*s gives the correct + result in this case. + https://bugzilla.gnome.org//show_bug.cgi?id=705630 + +2013-08-02 13:31:59 +0200 Lubosz Sarnecki + + * configure.ac: + build: add subdir-objects to AM_INIT_AUTOMAKE + Fixes warnings with automake 1.14 + https://bugzilla.gnome.org/show_bug.cgi?id=705350 + +2013-08-02 16:21:45 +0200 Wim Taymans + + * docs/design/part-gstpipeline.txt: + design: fix typo + +2013-07-29 15:48:32 +0200 Sjoerd Simons + + * plugins/elements/gstqueue2.c: + queue2: Fix backwards seeks into undowloaded ranges + When in download buffering mode queue2 didn't check if a range offset is + in a undownloaded range before the currently in-progress range. Causing + seeks to an earlier offset to, well, take a while. + +2013-07-30 19:27:23 +0200 Kjartan Maraas + + * gst/gstutils.c: + * libs/gst/check/gsttestclock.c: + docs: some small gtk-doc markup fixes + https://bugzilla.gnome.org/show_bug.cgi?id=705156 + +2013-07-30 19:27:23 +0200 Kjartan Maraas + + * gst/gst.c: + gst: register new color mode enum, fixing 'make check' + https://bugzilla.gnome.org/show_bug.cgi?id=705156 + +2013-04-16 19:04:48 +0200 Edward Hervey + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Avoid using buffer_get_size in tight loops + Calling gst_buffer_get_size represented 2/3 of the cost of helper_find_peek + which was called whenever a typefindfunction wanted to peek at data. + We already know the size (from the GstMapInfo), so just use that. + +2013-07-29 19:38:51 +0100 Tim-Philipp Müller + + * po/LINGUAS: + * po/bg.po: + * po/cs.po: + * po/de.po: + * po/el.po: + * po/fr.po: + * po/gl.po: + * po/hr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/lt.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sl.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2013-07-29 19:13:03 +0100 Tim-Philipp Müller + + * common: + common: revert accidental re-winding of common submodule + +2013-07-26 16:15:24 +0200 Sjoerd Simons + + * gst/gstquery.c: + query: Clarify the estimated-total documentation + Tweak the documentation slightly to clarify that the estimated-total in + a a Buffering query the total remaining time of a download, not the + total time for the complete download. Also indicate the unit used. + https://bugzilla.gnome.org/show_bug.cgi?id=704934 + +2013-07-26 15:08:13 +0200 Sjoerd Simons + + * plugins/elements/gstqueue2.c: + queue2: Forward the schedule query upstream + When asked about the scheduling flags first check with upstream and + simply add the _SEEKABLE flag when using a temporary file as storage. + This enables the forwarding of _SEQUENTIAL and _BANDWIDTH_LIMITED from + sources if needed. + https://bugzilla.gnome.org/show_bug.cgi?id=704927 + +2013-07-29 14:47:15 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.1.3 === + +2013-07-29 13:34:53 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 1.1.3 + +2013-07-29 13:30:25 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-07-29 12:10:45 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base: Fix handling of SEGMENT query + The values should be in stream-time, and start/stop should not + be swapped for negative rates. + +2013-07-29 11:05:09 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Only advance offset by the number of bytes we actually read + There might be a short read at EOS. + +2013-07-29 10:48:30 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Implement SEGMENT query + +2013-07-26 18:36:04 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: fix Since: marker for new gst_buffer_extract_dup() + +2013-07-26 12:19:32 +0200 Wim Taymans + + * gst/gstclock.c: + clock: debug the clock return values + +2013-07-25 12:20:14 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + baseparse: fix seqnum handling for seeks + Use the same seqnum as the seek for flushes/segments that are + caused by the seek. Also do the same for segment events + Fixes #676242 + +2013-07-24 10:29:30 -0700 David Schleef + + * gst/gstinfo.c: + info: parse debug levels > 9 + +2013-07-24 16:57:46 +0200 Sebastian Dröge + + * gst/gstvalue.c: + value: Fix copy&paste mistakes in the bitmask function docs + +2013-07-24 11:21:27 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Don't shadow variables that are set inside our scope and then used outside our scope + Fixes uninitialized use of these variables. + +2013-07-24 10:30:25 +0200 Sebastian Dröge + + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_i386w.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + tests: Remove other interface structs from the ABI tests too + +2010-10-15 13:16:59 -0300 Thiago Santos + + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_i386w.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + tests: Remove GstTagSetter from ABI checks + Interfaces can have new members added without breaking ABI, so + remove it from the check. + https://bugzilla.gnome.org/show_bug.cgi?id=623799 + +2013-07-23 15:39:53 -0400 Thibault Saunier + + * libs/gst/check/libcheck/check_print.c: + libcheck: Escape strings in the generated xml files + This is copy pasted from upstream libcheck + +2013-07-23 18:53:44 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Print some debug output if a stream-start event without group-id arrives + Ideally all elements would implement handling of that to get proper + stream-start message handling and other things. + +2013-07-22 18:03:01 +0200 Arnaud Vrac + + * plugins/elements/gstinputselector.c: + input-selector: Fix missing pad activation notification + A new active pad might not be notified in some cases, which results + in the current track number not being set in playbin. + The active-pad notification is only sent in the chain and sink_event + functions, and only when the buffer or event that triggered the active + pad selection is from the newly activated pad. So in the other case + the notification will never be sent. + https://bugzilla.gnome.org/show_bug.cgi?id=704691 + +2013-07-22 17:25:47 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + value: handle deserialisation of nonexistant enum value more gracefully + +2013-07-22 14:12:18 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Don't push new stream-start events on stream change unless they all have group ids + https://bugzilla.gnome.org/show_bug.cgi?id=704408 + +2013-07-22 12:06:29 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Use new group-id in stream-start event + +2013-07-22 12:06:08 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base: Use new group-id field in stream-start event and message + +2013-07-22 11:42:18 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Use the new group-id field of the stream-start message for stream-start message aggregation + If all stream-start messages had a group id (for backwards compatibility), + we only consider a stream started if all had the same group id. + In 2.0 we should make the group id mandatory. + +2013-07-22 11:41:35 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + gst: Add new group-id field to the stream-start event + All streams that have the same group id are supposed to be played + together, i.e. all streams inside a container file should have the + same group id but different stream ids. The group id should change + each time the stream is started, resulting in different group ids + each time a file is played for example. + +2013-07-18 23:29:49 +0100 Tim-Philipp Müller + + * common: + common: revert accidental change of common submodule + +2013-07-18 14:39:42 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + gst: Add some more Since: 1.2 + +2013-07-18 14:34:31 +0200 Sebastian Dröge + + * gst/gstinfo.c: + info: Add some Since: 1.2 + +2013-07-18 15:10:10 +0400 Руслан Ижбулатов + + * common: + * docs/gst/gstreamer-sections.txt: + * docs/gst/running.xml: + * docs/manual/appendix-checklist.xml: + * gst/gst.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * tools/gst-launch.1.in: + * tools/gst-plot-timeline.py: + * win32/common/libgstreamer.def: + info: Add debug color mode option + This allows to explicitely set the debug output color + mode to UNIX on every platform, enable it (use platform + default color mode) or enable it. + https://bugzilla.gnome.org/show_bug.cgi?id=674320 + +2012-04-18 14:35:32 +0400 Руслан Ижбулатов + + * gst/gstinfo.c: + info: Fix black and underline coloring on W32 + Fixes #674320 + +2012-04-18 14:12:16 +0400 Руслан Ижбулатов + + * gst/gstinfo.c: + info: Cut down src file names for MinGW too + Fixes #674320 + +2013-07-16 17:47:45 +0200 Nicola Murino + + * scripts/gst-uninstalled: + gst-uninstalled: Fix gst-plugins-gl in uninstalled setup + https://bugzilla.gnome.org/show_bug.cgi?id=703499 + +2013-07-16 15:35:08 -0400 Olivier Crête + + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + adapter: Take account of the skip in gst_adapter_take_buffer_fast() + Include regression test + +2013-07-15 15:41:44 -0400 Olivier Crête + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: + * win32/common/libgstbase.def: + adapter: Add function to return buffer composed of multiple memories + API: gst_adapter_take_fast() + +2013-07-16 16:24:38 +0200 Sebastian Dröge + + * gst/gstquery.c: + query: Don't assert if no context is set in the query + +2013-07-16 14:47:05 +0100 Tim-Philipp Müller + + * tests/benchmarks/.gitignore: + benchmarks: ignore new benchmark binary + +2013-07-16 14:46:15 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + * gst/gstquery.h: + query: sprinkle some Since 1.2 markers in docs + +2013-07-16 14:44:03 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnettimeprovider.c: + timeprovider: g-i: allow None as address for gst_net_time_provider_new() + +2013-07-16 15:34:57 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Return an empty GstContext if none was set yet + +2013-07-16 15:16:16 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: Add gst_query_has_context_type() + +2013-07-16 11:36:50 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: only block serialized query when it's safe + We must be certain that we don't cause a deadlock when blocking the serialized + queries. One such deadlock can happen when we are buffering and downstream is + blocked in preroll and a serialized query arrives. Downstream will not unblock + (and allow our query to execute) until we complete buffering and buffering will + not complete until we can answer the query.. + https://bugzilla.gnome.org/show_bug.cgi?id=702840 + +2013-07-15 11:36:18 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: A newly activated pad should be marked as needing reconfiguration + +2013-07-15 11:32:54 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "pad: Don't consider flushing pads as needing reconfiguration" + This reverts commit 948a9d2f2b728f5fb60be45d47a818cebeb60c7d. + This is racy and trying to reconfigure and fail is still better + than not trying to reconfigure at all. + https://bugzilla.gnome.org/show_bug.cgi?id=704100 + +2013-07-15 11:32:10 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Leave the loop function faster if we're flushing + Especially don't even try to send stream-start event or try + to negotiate. + https://bugzilla.gnome.org/show_bug.cgi?id=704100 + +2013-07-12 10:08:26 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Deactivate and remove pad without the inputselector lock + Otherwise we might get deadlocks caused by lock order inversion: + During the chain function the stream lock is first locked and then the + inputselector lock. During pad release we first locked the inputselector + lock and then deactivating the pad would lock the stream lock. + There's no reason why the inputselector lock should be required while + deactivating and removing the pad, it's only needed before. + https://bugzilla.gnome.org/show_bug.cgi?id=704002 + +2013-07-11 16:57:06 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.1.2 === + +2013-07-11 15:12:39 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.1.2 + +2013-07-11 15:11:27 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-07-10 15:52:10 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Always forward clock-lost message if we're not a top-level bin + This makes sure that no bin misses the clock-lost messages, independent + of the state, and could return an old, non-working clock from + gst_bin_provide_clock_func(). + https://bugzilla.gnome.org/show_bug.cgi?id=701997 + +2013-07-10 14:30:31 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Keep previous active sinkpad around until we're done with it + Otherwise we'll send a new segment event downstream for each buffer. + +2013-07-08 15:26:38 +0100 Tim-Philipp Müller + + * gst/gstallocator.c: + allocator: fix type of gst_memory_alignment to match declaration + Fixes compiler warnings such as + gstallocator.c:61:8: error: conflicting types for 'gst_memory_alignment' + ../gst/gstallocator.h:52:18: note: previous declaration of 'gst_memory_alignment' was here + +2013-07-05 21:36:27 +0200 Piotr Drąg + + * po/POTFILES.in: + po: update POTFILES.in + https://bugzilla.gnome.org/show_bug.cgi?id=703682 + +2013-07-04 20:39:26 -0400 Thibault Saunier + + * libs/gst/base/gstbasesrc.c: + basesrc: Do not lock a mutex that does not exist + The GST_LIVE_LOCK is on GstBaseSrc, not on its source pad. + +2013-07-03 21:23:44 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: reset PTS after seek + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702778 + +2013-07-03 13:03:49 -0400 Nicolas Dufresne + + * gst/gstallocator.c: + * gst/gstevent.c: + * gst/gstghostpad.c: + * gst/gstinfo.h: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstpad.c: + * gst/gstplugin.c: + * gst/gsttaglist.c: + * gst/gsttypefind.c: + * gst/gstutils.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + Add few missing allow-none annotation + +2013-07-03 09:27:13 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add new -bad mpegts lib + And remove signalprocessor/video libs from -bad which have gone + away or were merged into -base. + +2013-07-01 20:35:21 -0400 Olivier Crête + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstfunnel.h: + * tests/check/elements/funnel.c: + funnel: Re-push all sticky events when buffers come from a different pad + Don't special case segment/caps, just push all sticky events when they are + received on the currently active pad or when the active pad changes. + +2013-07-01 20:21:10 -0400 Olivier Crête + + * plugins/elements/gstfunnel.c: + funnel: Use default pad function for upstream event/queries + The default functions in 1.x already do the right thing + +2013-07-01 20:18:58 -0400 Olivier Crête + + * tests/check/elements/funnel.c: + tests: Remove funnel pad_alloc test + +2013-07-01 20:07:03 -0400 Olivier Crête + + * libs/gst/check/gstcheck.h: + check: Change stream_id parameter name to match GtkDoc + +2013-07-01 11:10:00 +0200 Jonas Holmberg + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * tests/check/elements/funnel.c: + check: Added gst_check_setup_events_with_stream_id() + Added a new function gst_check_setup_events_with_stream_id(), since + gst_check_setup_events() does not work with multiple pads. + https://bugzilla.gnome.org/show_bug.cgi?id=703377 + +2013-06-30 18:39:03 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Don't consider flushing pads as needing reconfiguration + Renegotiation and reconfiguration will fail because all queries + and events won't be accepted by the pad if it's flushing. In the + best case this just causes unneeded work and spurious warnings in + the debug logs, in the worst case it causes elements to fail completely. + +2013-06-24 23:25:51 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: only block serialized query when it's safe + We must be certain that we don't cause a deadlock when blocking the serialized + queries. One such deadlock can happen when we are buffering and downstream is + blocked in preroll and a serialized query arrives. Downstream will not unblock + (and allow our query to execute) until we complete buffering and buffering will + not complete until we can answer the query.. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702840 + +2013-06-19 12:30:47 +0200 Sjoerd Simons + + * gst/gstpad.c: + pad: Add a filter to the caps_query done by acceptcaps + Use the caps that the pad is asked to accept as filter for the query + https://bugzilla.gnome.org/show_bug.cgi?id=702632 + +2013-06-19 12:19:02 +0200 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + basetransform: optimize default acceptcaps implementation + Pass the fixed caps we're asked to accept as a filter for the caps + query, so we don't get a fully-expanded set of caps back (which we don't + need and can take a lot of time for intersection). + This reduces the time for camerabin to produce a second frame on a + logitech C910 camera from around 52 seconds to a bit less then 16 + seconds on my system. + https://bugzilla.gnome.org/show_bug.cgi?id=702632 + +2013-06-19 09:19:53 +0200 Edward Hervey + + * gst/gsttaglist.c: + taglist: Avoid combinatorial explosion when merging tags + When appending/prepending tags, avoid re-creating (and copying) lists if we already + have one and instead just append/prepend the GValue to the list. + https://bugzilla.gnome.org/show_bug.cgi?id=702545 + +2013-06-19 10:53:21 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Don't hold the queue mutex while doing serialized queries downstream + https://bugzilla.gnome.org/show_bug.cgi?id=702520 + +2013-06-19 10:45:45 +0200 Sebastian Dröge + + * tests/check/gst/gstbuffer.c: + buffer: Add unit test for map_range() + https://bugzilla.gnome.org/show_bug.cgi?id=702617 + +2013-06-19 08:36:22 +0200 Paul HENRYS + + * gst/gstbuffer.c: + buffer: Fix wrong size/index handling when merging memory + https://bugzilla.gnome.org/show_bug.cgi?id=702617 + +2013-06-18 11:39:55 +0200 Stefan Sauer + + * docs/list-ulink.xsl: + docs: add missing file for doc-link check + +2013-06-17 11:12:51 +0200 Wim Taymans + + * tests/benchmarks/Makefile.am: + * tests/benchmarks/gstpoolstress.c: + tests: add stress test for buffers and pools + +2013-06-17 10:25:20 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: call state change in all cases + When we asynchronously go from READY to PLAYING, also call the + state change function so that subclasses can update their state for PLAYING. + Because the PREROLL lock is not recursive, we can't make this without + races and we must assume for now that the subclass can handle concurrent calls + to PAUSED->PLAYING and PLAYING->PAUSED. We can make this assumption because not + many elements actually do something in those state changes and the ones that + did would be broken even more without this change. + https://bugzilla.gnome.org/show_bug.cgi?id=702282 + +2013-06-16 15:07:35 +0200 Stefan Sauer + + * docs/faq/dependencies.xml: + * docs/manual/appendix-integration.xml: + * docs/manual/basics-pads.xml: + * docs/manual/intro-motivation.xml: + docs: fix some external links + +2013-06-16 14:45:08 +0200 Stefan Sauer + + * docs/manuals.mak: + docs: check for broken links in docs + The check is done using curl (if available). It lists the curl exit code + http + status code (for those > 399) together with the use of the url in the code. The + check is not fatal. + +2013-06-16 13:05:21 +0200 Stefan Sauer + + * docs/manual/basics-elements.xml: + * docs/pwg/intro-preface.xml: + docs: change https to http urls + Thank you browser for needlessly changing to https for static doc pages. + +2013-06-16 11:41:52 +0200 Stefan Sauer + + * docs/faq/developing.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-init.xml: + * docs/pwg/intro-preface.xml: + docs: update links to developer.gnome.org + The URL layout has changed. Fix the links and comment out one paragraph where + the doc is gone. + Fixes #702135 + +2013-06-14 13:05:38 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: Add gst_structure_new_from_string() + Convenience API for bindings, gst_structure_from_string() returns + a tuple (structure, end_ptr) in bindings and is unintuitive to use + because of that. + +2013-06-13 08:36:23 +0200 Hans de Goede + + * gst/gst.c: + gst: Don't intercept --help in gst_init() + Before this patch gst_init would intercept --help, causing for example + cheese's --help to look like this: + [hans@shalem cheese]$ cheese --help + Usage: + cheese [OPTION...] - GStreamer initialization + Help Options: + -h, --help Show help options + --help-all Show all help options + --help-gst Show GStreamer Options + gst_init is the only gfoo_init function which does this. + https://bugzilla.gnome.org/show_bug.cgi?id=702089 + +2013-06-12 09:45:56 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add uridownloader lib in -bad to search paths + Even if it might not be around for long. + +2013-06-11 10:25:02 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Remove unref that should not be there + We keep a reference to the context around all the time. + https://bugzilla.gnome.org/show_bug.cgi?id=701985 + +2013-06-09 17:20:22 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Improve GstContext handling + https://bugzilla.gnome.org/show_bug.cgi?id=700967 + +2013-06-07 13:07:37 +0200 Kim Lam + + * win32/vs10/base/base.vcxproj: + win32: Don't include gstcollectpads.c twice + https://bugzilla.gnome.org/show_bug.cgi?id=701603 + +2013-05-31 09:39:55 -0600 Brendan Long + + * plugins/elements/gstinputselector.c: + input-selector: send notify::active signal for input-selector pads. + https://bugzilla.gnome.org/show_bug.cgi?id=701319 + +2013-06-06 16:46:12 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Only force-update the duration for dynamic sources when doing the DURATION query + Doing it after every single create() is not very efficient and not necessary. + Especially on network file systems fstat() is not cached and causes network + traffic, making the source possibly unusable slow. + https://bugzilla.gnome.org/show_bug.cgi?id=652037 + +2013-06-05 18:36:40 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.1.1 === + +2013-06-05 17:58:51 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 1.1.1 + +2013-06-05 16:06:35 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2013-06-05 15:14:14 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 098c0d7 to 01a7a46 + +2013-06-05 11:02:50 +0200 Edward Hervey + + * gst/gstbufferpool.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstreamer.def: + gstvalue: Add _append_and_take_value() public variants + API: gst_value_array_append_and_take_value + API: gst_value_list_append_and_take_value + We were already using this internally, this makes it public for code + which frequently appends values which are expensive to copy (like + structures, arrays, caps, ...). + Avoids copies of the values for users. The passed GValue will also + be 0-memset'ed for re-use. + New users can replace this kind of code: + gst_value_*_append_value(mycontainer, &myvalue); + g_value_unset(&myvalue); + by: + gst_value_*_append_and_take_value(mycontainer, &myvalue); + https://bugzilla.gnome.org/show_bug.cgi?id=701632 + +2013-05-29 17:20:34 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: Use internal function for buffer_new_wrapped + Shaves ~10% instruction calls from the total cost + https://bugzilla.gnome.org/show_bug.cgi?id=701633 + +2013-05-30 22:57:49 -0600 Brendan Long + + * plugins/elements/gstinputselector.c: + input-selector: return FALSE for "active" property if selector is NULL + https://bugzilla.gnome.org/show_bug.cgi?id=701323 + +2013-06-01 14:00:22 +0100 Andrzej Bieniek + + * docs/manual/advanced-threads.xml: + manual: update elements to match the rest of "Boost priority of a thread" section + +2013-06-01 13:55:50 +0100 Andrzej Bieniek + + * docs/manual/advanced-dataaccess.xml: + manual: fix comment in effectswitch example + +2013-06-01 13:49:18 +0100 Andrzej Bieniek + + * docs/manual/advanced-dataaccess.xml: + manual: fix a typo in "Inserting data with appsrc" section + +2013-06-01 13:22:22 +0100 Andrzej Bieniek + + * docs/pwg/advanced-dparams.xml: + * docs/pwg/advanced-qos.xml: + * docs/pwg/appendix-checklist.xml: + pwg: fix a few typos + +2013-05-31 23:37:07 +0100 Andrzej Bieniek + + * docs/pwg/advanced-allocation.xml: + * docs/pwg/building-boiler.xml: + * docs/random/porting-to-1.0.txt: + docs: remove double "the" + +2013-05-28 23:34:54 +0100 Krzysztof Konopko + + * scripts/git-update.sh: + scripts: improve git-update.sh status message + By default when the script is about to exit (normally or due to an error), + it checks whether $ERROR_LOG file exists. If the log file exists, the + script prints a "Failures: " message prefix and dumps the log file to the + output. + Apparently the log file is always created and if the update/build is + successful, the script finishes with a bit misleading "Failures: " message. + An improvement provided with this change lets the log file to be created as + needed, i.e. if there's an error message to be printed. If the file + doesn't exists, the script prints a "Update done" message which clearly + indicates success. + https://bugzilla.gnome.org/show_bug.cgi?id=701177 + +2013-05-30 07:03:40 +0200 Wim Taymans + + * tests/check/generic/sinks.c: + check: fix position unit test + +2013-05-30 06:51:24 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve position reporting without clock + When no base time or when sync is disabled, use the same logic as + in paused to report position. The logic in PLAYING assumes we use the + clock. + +2013-05-29 11:36:38 +0200 Sebastian Dröge + + * tests/check/gst/gstpad.c: + pad: Fix memory leak in the unit test + +2013-05-28 12:44:19 +0200 Sebastian Dröge + + * gst/gstelementfactory.c: + elementfactory: Add support for checking subtitle/metadata factory types + +2013-05-28 12:41:27 +0200 Sebastian Dröge + + * gst/gstelementfactory.c: + elementfactory: Add support for checking only the media type of a factory + And while at it also add Metadata and Subtitle media types. + +2013-05-27 16:38:18 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + (multi)queue: Don't access query items during flushing + +2013-05-27 16:22:00 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't do serialized queries when we're flushing + Just immediately fail the query, otherwise we would wait forever + for the query to be answered. + +2013-05-27 16:08:39 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: First set query result, then signal GCond + +2013-05-27 15:59:07 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: Fix handling of serialized queries + During FLUSH_START the query needs to be unblocked already, otherwise + it can lead to deadlocks if the FLUSH_START is the result of something + done from the streaming thread of the srcpad (the queue will never be + emptied!). + +2013-05-27 15:41:14 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Unblock any waiting serialize queries on FLUSH_START + Fixes some deadlocks during flushing. + And store queue items differently to not accidentially read + already unreffed queries when flushing. Queries are owned by + upstream and not us. + +2013-05-27 13:01:43 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue/queue2/multiqueue: When flushing, make sure to not lose any sticky events + https://bugzilla.gnome.org/show_bug.cgi?id=688824 + +2013-05-27 12:40:50 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Store sticky events even if the pad is flushing + But do this only for events that are not dropped by flushing, + i.e. do it only for everything except SEGMENT and EOS. + Without this we might drop a CAPS event if flushing happens + at an unfortunate time and nobody is resending the CAPS event. + https://bugzilla.gnome.org/show_bug.cgi?id=700806 + +2013-05-25 22:03:53 -0400 Nicolas Dufresne + + * plugins/elements/gstvalve.c: + valve: Don't read sticky flag from unrefed event + +2013-05-24 23:28:04 +0100 Tim-Philipp Müller + + * plugins/elements/gsttee.c: + tee: fix property description for now-unused "alloc-pad" property + Should probably proxy ALLOCATION queries on that though, if set. + But what else? CAPS and ACCEPT_CAPS too? + +2013-05-24 23:01:09 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasetransform.c: + basetransform: remove 0.10-ism from docs + gst_buffer_pad_alloc() never existed, and gst_pad_alloc_buffer() + doesn't exist any more either, so don't mention it in the docs. + https://bugzilla.gnome.org/show_bug.cgi?id=694714 + +2013-05-24 19:22:22 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Add support for serialized queries if using a memory queue + +2013-05-24 18:47:24 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Set the last serialized query result to FALSE when flushing + +2013-05-24 18:42:55 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Initialize all GstMultiQueueItem fields in both code paths + +2013-05-24 18:38:40 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't access the query after signalling the waiting thread + It might've free'd the query already. + +2013-05-24 18:30:44 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Make sure to always signal any possible pending serialized queries + And don't unref them when flushing the queue, they're owned by the caller! + https://bugzilla.gnome.org/show_bug.cgi?id=700342 + +2013-05-24 14:37:19 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Return GST_FLOW_ERROR if the allocator did not allow to allocate a buffer + +2013-05-24 16:24:10 +0900 Olivier Crête + + * docs/manual/appendix-integration.xml: + docs: Remove mention of gconf* elements + Instead recommend pulsesrc/sink for audio, there is nothing GNOME + specific for video. + +2013-05-15 13:22:04 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Handle the force-caps property more similar to all typefinding code flow + This makes sure that events happen in order and simplifies the code a bit. + +2013-05-15 11:21:46 +0200 Sebastian Dröge + + * libs/gst/check/gstcheck.c: + check: Fix event handling in gst_check_element_push_buffer_list() + +2013-05-15 10:51:01 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 5edcd85 to 098c0d7 + +2013-05-10 16:03:34 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Only check if we get buffers before stream-start/segment if compiling without G_DISABLE_ASSERT + In releases this is set usually. + +2013-05-09 17:17:14 -0400 Nicolas Dufresne + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Add helper that sends initial events + https://bugzilla.gnome.org/show_bug.cgi?id=700033 + +2013-05-09 17:22:16 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix uninitialized variable compiler warning + +2013-05-09 17:21:13 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Make sure pending, older sticky events are sent downstream in dynamic linking scenarios + If a pad block was triggered from sending a sticky event downstream, it + could happen that the pad block is relinking pads, which then requires + to resend previous sticky events. + +2013-05-09 13:32:07 +0200 Sebastian Dröge + + * tests/check/elements/fakesink.c: + * tests/check/elements/filesink.c: + * tests/check/elements/funnel.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/elements/queue2.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/libs/collectpads.c: + tests: Fix event order warnings and dataflow before stream-start/segment event + +2013-05-09 13:31:38 +0200 Sebastian Dröge + + * tests/check/libs/test_transform.c: + * tests/check/libs/transform1.c: + basetransform: Properly port unit test to actually use caps and check results + +2013-05-09 12:50:20 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Store sticky events on the srcpad if we're dropping them because of leaking + +2013-05-09 12:27:12 +0200 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + outputselector: Always forward sticky events to all pads + +2013-05-09 12:15:48 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Forward all sticky events, including stream-start + +2013-05-09 11:05:50 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Warn if data flow happens before stream-start or segment event + +2013-05-09 10:59:41 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Only let gst_pad_sticky_events_foreach() iterate over existing events + +2013-05-09 10:29:11 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: If we push sticky events because of another sticky event, only push those that come before the new event + https://bugzilla.gnome.org/show_bug.cgi?id=699937 + +2013-05-09 09:50:41 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: Add more debug output and forward caps events immediately too + +2013-05-09 09:42:33 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: No sticky events must arrive after EOS + +2013-05-09 09:38:35 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: Fix typo in last commit + +2013-05-08 19:44:09 -0400 Nicolas Dufresne + + * gst/gstpad.c: + pad: Improve warning message naming events type name + With this patch, message should look like ¨Sticky event misordering, got + 'caps' before 'stream-start'¨ making it faster to debug. + https://bugzilla.gnome.org/show_bug.cgi?id=688188 + +2013-05-08 18:19:48 -0400 Nicolas Dufresne + + * gst/gstpad.c: + pad: Only inforce STREAM_START, CAPS and SEGMENT ordering + Previous patch was inforcing a complete ordering of the sticky events, while + in fact, only STREAM_START, CAPS and SEGMENT events need proper ordering. + See: https://bugzilla.gnome.org/show_bug.cgi?id=688188 + +2013-05-09 09:32:49 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + capsfilter: Send all events that should happen after CAPS after the CAPS event + +2013-05-08 21:45:08 -0400 Nicolas Dufresne + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + capsfilter: Send caps before segment + In the case the source has no caps, caps must be sent before segment. This + fixes few unit tests that where failing due to the new misordering warning. + https://bugzilla.gnome.org/show_bug.cgi?id=699968 + +2013-05-07 21:53:37 -0400 Nicolas Dufresne + + * gst/gstpad.c: + pad: Detect, fix and warn when sticky events are in wrong order + We can prevent buggy element from causing other elements to fail or crash + by sorting sticky event at insertion. In this case, we also warn as this + is not supposed to happen. + See: https://bugzilla.gnome.org/show_bug.cgi?id=688188 + +2013-05-08 10:26:15 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbuffer.c: + tests: add some basic checks for gst_buffer_fill() + +2013-05-08 10:25:36 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: allow calling _fill() with a NULL data pointer if size is 0 bytes + +2013-05-07 16:46:32 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Add FIXME comment for unused assignment results + +2013-05-07 15:18:06 +0100 Tim-Philipp Müller + + * docs/manual/advanced-metadata.xml: + docs: fix typo in metadata section in app dev manual + There's no g_tag_list_get_xyz(). + +2013-05-07 14:47:09 +0300 Sreerenj Balachandran + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + controller: Fix the function signature and a minor typo fix + https://bugzilla.gnome.org/show_bug.cgi?id=699827 + +2013-05-06 18:47:44 -0400 Nicolas Dufresne + + * plugins/elements/gsttypefindelement.c: + typefind: Send stream-start before anything else + To do so, send stream-start when the streaming thread goes up for the first + time. + https://bugzilla.gnome.org/show_bug.cgi?id=699767 + +2012-12-26 11:54:51 +0000 David Rothlisberger + + * tools/gstreamer-completion: + tools/gstreamer-completion: Allow 1.0 and 0.10 scripts installed simultaneously + As long as the scripts' filenames are different, and the _gst_inspect + and _gst_launch functions are named differently, the completion scripts + for GStreamer 1.0 and 0.10 can be installed side-by-side in + /etc/bash_completion.d. + On my 0.10 branch† the completion script is renamed to + "gstreamer-completion-0.10" and the functions are renamed to + "_gst_inspect_0_10" and "_gst_launch_0_10". The remaining helper + functions should remain identical (the command-line interface to + gst-inspect hasn't changed, nor has the format of the gst-launch + pipeline), so it doesn't matter if the 1.0 script overrides the 0.10 + script's definitions. + Note that I don't expect there to be another GStreamer 0.10 release, so + the 0.10 completion script will probably never be officially released; + but it is still worthwhile allowing both scripts to be installed + alongside each other, for those who install the 0.10 completion script + manually. + Fixes: #690515 + † https://github.com/drothlis/gstreamer/blob/bash-completion-0.10/tools/gstreamer-completion-0.10 + +2012-12-21 18:13:53 +0000 David Rothlisberger + + * tests/misc/test-gstreamer-completion.sh: + * tools/gstreamer-completion: + tools/gstreamer-completion: Complete option & property values on bash 3.2 + Bash 3's completion doesn't split words by characters in + COMP_WORDBREAKS. In particular it doesn't split at "=" signs. Now + _gst_launch_parse handles both bash 3 and 4 format of COMP_WORDS. + Note that "${cur%%=*}" means cur's value with the longest possible match + of "=*" deleted from the end; "${cur#*=}" means cur's value with the + shortest possible match of "*=" deleted from the beginning. See + http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html + Regardless of the version of bash running the unit tests, I can test for + both behaviours because the unit test populates COMP_WORDS manually. So + this tests the bash 3 behaviour: + test_gst_inspect_completion --gst-debug-level=4 + and this tests the bash 4 behaviour: + test_gst_inspect_completion --gst-debug-level = 4 + +2012-12-21 08:56:26 +0000 David Rothlisberger + + * tests/misc/test-gstreamer-completion.sh: + * tools/gstreamer-completion: + tools/gstreamer-completion: Bash 3.2 compatibility fixes + Compatible with bash 3.2; doesn't require the bash-completion package at + all (though the easiest way to install this script is still to install + bash-completion, and then drop this script into /etc/bash_completion.d). + Note that bash 3 doesn't break COMP_WORDS according to characters in + COMP_WORDBREAKS, so "property=val" looks like a single word, so this + won't complete property values (on bash 3). Similarly, + "--gst-debug-level=" won't complete properly (on bash 3), but + "--gst-debug-level " will. + For that reason, I now offer "--gst-debug-level" etc as completions + instead of "--gst-debug-level=". + Functions "_init_completion" and "_parse_help" were provided by the + bash-completion package >= 2.0; now I roll my own equivalent of + "_parse_help", and instead of "_init_completion" I use + "_get_comp_words_by_ref" which is available from bash-completion 1.2 + onwards. If the bash-completion package isn't available at all I use + bash's raw facilities, at the expense of not completing properly when + the cursor is in the middle of a word. + The builtin "compopt" doesn't exist in bash 3; those users will just + have to live with the inconvenience of "property=" completing to + "property= " with a trailing space. Property values aren't completed + properly anyway on bash 3 (see above). + "[[ -v var ]]" to test whether a variable is set, also doesn't exist in + bash 3. Neither does ";;&" to fall through in a "case" statement. + In the unit tests: + * On my system (OS X), "#!/bin/bash" is bash 3.2, whereas + "#!/usr/bin/env bash" is the 4.2 version I built myself. + * I have to initialise array variables like "expected=()", or bash 3 + treats "+=" as appending to an array already populated with one empty + string. + +2012-12-19 10:46:50 +0000 David Rothlisberger + + tools/gstreamer-completion: Support gst-inspect, and gst-launch element properties + Completes options like "--gst-debug-level" and the values of some of + those options; completes gst-launch pipeline element names, property + names, and even property values (for enum or boolean properties only). + Doesn't complete all caps specifications, nor element names specified + earlier in the pipeline with "name=...". + The GStreamer version number is hard-coded into the completion script: + This patch is off the master branch and has the version hard-coded as + "1.0"; it needs to be updated if backported to the 0.10 branch. You + could always create a "gstreamer-completion.in" that has the appropriate + version inserted by "configure", but I'd rather not do that. The + hard-coded version is consistent with the previous implementation of + gstreamer-completion, which had the registry path hard-coded as + ~/.gstreamer-1.0/registry.xml. + Note that GStreamer 0.10 installs "gst-inspect" and "gst-inspect-0.10". + "gst-inspect --help" only prints 4 flags (--help, --print, --gst-mm, + gst-list-mm) whereas "gst-inspect-0.10 --help-all" prints the full list + of flags. The same applies to "gst-launch" and "gst-launch-0.10". + GStreamer 1.0 only installs "gst-inspect-1.0", not "gst-inspect". + Requires bash 4; only tested with bash 4.2. Requires "bash-completion" + (which you install with your system's package manager). + Put this in /etc/bash_completion.d/ or in `pkg-config + --variable=compatdir bash-completion`, where it will be loaded at the + beginning of every new terminal session; + or in `pgk-config --variable=completionsdir bash-completion`, renamed to + match the name of the command it completes (e.g. "gst-launch-1.0", with + an additional symlink named "gst-inspect-1.0"), where it will be + autoloaded when needed. + test-gstreamer-completion.sh is (for now) in tests/misc -- it might be + worth creating "tests/check/tools", with all the necessary automake + boilerplate, and moving test-gstreamer-completion.sh there, and have it + run automatically with "make check". + IF YOU'RE NEW TO BASH COMPLETION SCRIPTS + ---------------------------------------- + "complete -F _gst_launch gst-launch-1.0" means that bash will run the + function "_gst_launch" to generate possible completions for the command + "gst-launch-1.0". + "_gst_launch" must return the possible completions in the array variable + COMPREPLY. (Note on bash syntax: "V=(a b c)" assigns three elements to + the array "V"). + "compgen" prints a list of possible completions to standard output. Try + it: + compgen -W "abc1 abc2 def" -- "a" + compgen -f -- "/" + The last argument is the word currently being completed; compgen uses it + to filter out the non-matching completions. We put "--" first, in case + the word currently being completed starts with "-" or "--", so that it + isn't treated as a flag to compgen. + For the documentation of COMP_WORDS, COMP_CWORD, etc see + http://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#index-COMP_005fCWORD-180 + See also: + * http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html + * http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html + The bash-completion package provides the helper function + "_init_completion" which populates variables "cur", "prev", and "words". + See + http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=blob;f=bash_completion;h=870811b4;hb=HEAD#l634 + Note that by default, bash appends a space to the completed word. When + the completion is "property=" we don't want a trailing space; calling + "compopt -o nospace" modifies the currently-executing completion + accordingly. See + http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#index-compopt + +2012-11-13 16:36:46 +0000 David Rothlisberger + + * tools/gstreamer-completion: + tools/gstreamer-completion: Updated to work with the binary registry + The original registry was in xml format (~/.gstreamer-*/registry.xml). A + binary registry format was added in 2007 (commit ebf0c9d3) and made the + default in 2008 (commit 3f39fd7e). In 0.10 you could still choose at + "configure" time to use the xml registry instead; in 1.0 the binary + registry is your only choice. + This change to gstreamer-completion should work with either format + because it parses the output of "gst-inspect" instead of reading the + registry file directly. + Note that _gst_launch no longer needs an explicit "return 0" because, + unlike the previous grep command, compgen always returns 0 (unless a + genuine error occurs). + Just like the previous implementation by David Schleef, this "only + completes names of features, but that's 90% of what I want it for." + +2013-04-29 21:11:36 +0200 Stefan Sauer + + * docs/random/porting-to-1.0.txt: + porting-to-1.0.txt: nit clarification + It is the process context that matters. + +2013-04-29 13:20:11 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Always leave TYPEFIND mode when we're stopping typefinding + +2013-04-29 13:03:24 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Simplify code + This is only called when in TYPEFIND mode. + +2013-04-29 12:58:07 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Push pending events independent of the existence of a downstream chain function and peer + Downstream might create a peer only as result of the events in theory. + +2013-04-29 12:56:54 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Only push CAPS event once if we get one from upstream + https://bugzilla.gnome.org/show_bug.cgi?id=692784 + +2013-04-29 12:54:27 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Stop typefinding if we get a CAPS event from upstream + +2013-04-29 12:52:46 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Improve handling of GAP events + There's still room for improvement though. + +2013-04-29 12:48:29 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Forward events that should happen before the caps event directly + There's no point in storing them and sending them later, and doing so would + later require to distinguish between events that should come before caps and + after. + https://bugzilla.gnome.org/show_bug.cgi?id=692784 + +2013-04-29 12:48:13 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Only push pending buffers and events if we have caps + +2013-04-29 12:39:20 +0200 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefind: Remove code that would cause caps to be sent twice + Whenever we set typefind->caps we will also send a caps event downstream. + +2013-04-27 20:33:06 +0200 Wim Taymans + + * docs/pwg/advanced-allocation.xml: + pwg: improve allocation docs + +2013-04-27 11:46:13 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: set CK_TIMEOUT_MULTIPLIER on ARM + https://bugzilla.gnome.org/show_bug.cgi?id=695599 + +2013-04-27 00:05:45 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + * tests/check/pipelines/simple-launch-lines.c: + typefind: fix caps leak when used in connection with uridecodebin and playbin + Don't leak forced sink caps. + +2013-04-22 18:08:43 -0300 Thibault Saunier + + * libs/gst/controller/gsttimedvaluecontrolsource.c: + controller: Fix element-type annotations + +2013-04-25 16:38:49 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Try to not push read-only buffers + We should only increase the refcount before pushing if we're + really going to use the buffer afterwards. + +2013-04-25 07:15:39 +0200 Alessandro Decina + + * tests/check/gst/gstpad.c: + tests: add check for FLUSH pad probes + +2013-04-24 08:40:32 +0200 Alessandro Decina + + * gst/gstpad.c: + gstpad: run probes for FLUSH events sent with gst_pad_send_event + Move probe handling in gst_pad_send_event_unchecked so that probes are run for + FLUSH events too. + +2013-04-24 15:58:49 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + netclock: Add support for IPv6 + +2013-04-24 12:30:07 +0100 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + porting-to-1.0.txt: add troubleshooting section + Add note about "cannot register existing type `GstObject'" warning. + +2013-04-23 11:47:54 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Only infer TS if PTS interpolation is enabled + Otherwise this is breaking timestamps of formats that + need reordering. + https://bugzilla.gnome.org/show_bug.cgi?id=597662 + +2013-04-23 11:17:05 +0200 Wim Taymans + + * gst/gstpad.c: + pad: notify caps property on NULL as well + Also notify the caps property when it changes to NULL + +2013-04-23 11:16:16 +0200 Wim Taymans + + * gst/gstpad.c: + pad: clarify locking + +2013-04-22 23:50:17 +0100 Tim-Philipp Müller + + * MAINTAINERS: + * README: + * README.static-linking: + * common: + Automatic update of common submodule + From 3cb3d3c to 5edcd85 + +2013-04-19 15:01:20 +0200 Sebastian Dröge + + * docs/design/Makefile.am: + * docs/design/part-context.txt: + * gst/gstcontext.c: + part-context: Write some design documentation about GstContext + +2013-04-19 13:21:34 +0200 Sebastian Dröge + + * docs/design/part-caps.txt: + part-caps: Add more information about caps features, caps semantics and how to use them + +2013-04-19 11:23:31 +0200 Sebastian Dröge + + * docs/design/part-caps.txt: + * gst/gstcapsfeatures.c: + capsfeatures: Add documentation about ANY GstCapsFeatures + +2013-04-19 10:24:06 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Don't set last_render_time if we're checking for a late buffer before ::prepare() + This makes sure that at least one buffer per second is rendered if buffers + are dropped before ::prepare. Without this change, at least one buffer per + second wouldn't be too late before ::prepare anymore but would be dropped + before ::render because of last_render_time being set before ::prepare + already. + +2013-02-08 03:57:44 -0200 Andre Moreira Magalhaes (andrunko) + + * gst/gstvalue.c: + gstvalue: Add compare function for caps + +2013-01-15 16:57:20 -0300 Thiago Santos + + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * win32/common/libgstbase.def: + dataqueue: add gst_data_queue_peek + This function works just like gst_data_queue_pop, but it doesn't + remove the object from the queue. + Useful when inspecting multiple GstDataQueues to decide from which + to pop the element from. + Add: gst_data_queue_peek + +2013-04-18 10:14:09 +0100 Tim-Philipp Müller + + * tests/check/gst/.gitignore: + tests: ignore new test binary + +2013-04-18 10:13:30 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: update for latest context API changes + +2013-04-18 10:17:44 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontext.c: + * gst/gstcontext.h: + * tests/check/gst/gstcontext.c: + * win32/common/libgstreamer.def: + context: Add gst_context_writable_structure() and let get_structure() return const again + +2013-04-18 00:44:32 +0100 Tim-Philipp Müller + + * gst/printf/printf-parse.c: + * tests/check/gst/gstinfo.c: + printf: fix handling of old printf extension specifiers for ABI compatibility + Fixes abort when the old specifiers are used. Fix up the conversion + specifier, it would get overwritten with 'c' below to the extension + format char, which then later is unhandled, leading to the abort. + Also fix up and enable unit test for this. + https://bugzilla.gnome.org/process_bug.cgi + +2013-04-18 00:28:00 +0100 Tim-Philipp Müller + + * tests/check/gst/gstinfo.c: + tests: add unit test for old printf extension specifiers + To make sure we maintain binary compatibility with the old + specifiers. + https://bugzilla.gnome.org/show_bug.cgi?id=698242 + +2013-04-18 00:19:23 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: run skipped tests if explicitly requested via GST_CHECKS + If a test that's disabled with tcase_skip_broken_test() is listed + in the GST_CHECKS environment variable, run it anyway. + +2013-04-17 13:47:35 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Add GstContext support + gst-launch will collect all the contexts from the pipeline elements + and update the overall pipeline context with it. + +2013-04-17 12:44:29 +0200 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/gst/gstcontext.c: + context: Add unit test for GstContext + +2013-04-17 12:17:49 +0200 Sebastian Dröge + + * gst/gstcontext.c: + * gst/gstcontext.h: + context: Return a non-const GstStructure to make code simpler and update docs + +2013-03-29 14:56:57 +0100 Philippe Normand + + * docs/design/part-scheduling.txt: + * gst/gstquery.h: + * win32/common/gstenumtypes.c: + query: new _BANDWIDTH_LIMITED flag + Source elements with limited bandwidth capabilities and supporting + buffering for downstream elements should set this flag when answering + a scheduling query. This is useful for the on-disk buffering scenario + of uridecodebin to avoid checking the URI protocol against a list of + hardcoded protocols. + Bug 693484 + +2013-04-16 09:55:00 +0100 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: fix missing flacdec in porting-to-1.0 pipeline example + +2013-04-16 09:03:52 +0100 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: add note about decoders and parsers to porting-to-1.0 doc + +2012-10-24 11:58:35 +0200 Sebastian Dröge + + * configure.ac: + * gst/gstplugin.h: + * plugins/elements/Makefile.am: + gst: Add better support for static plugins + API: GST_PLUGIN_STATIC_DECLARE() + API: GST_PLUGIN_STATIC_REGISTER() + Based on a patch by Håvard Graff . + This now allows GST_PLUGIN_DEFINE() to create a static plugin if + GST_PLUGIN_BUILD_STATIC is defined. The resulting plugin can be + statically linked or dynamically linked during compilation but + can't be dynamically loaded during runtime. + Also adds GST_PLUGIN_STATIC_DECLARE() and GST_PLUGIN_STATIC_REGISTER(), + which allows to register a static linked plugin easily. + It is still required to manually register every single statically linked + plugin from inside the application as this can't be automated in a portable + way. + A new configure parameter --enable-static-plugins was added that allows + to build all plugins we build here as static plugins. + Fixes bug #667305. + +2013-04-12 13:50:39 +1200 Douglas Bagnall + + * docs/manual/appendix-porting.xml: + manual: Patch manual to refer to porting guide + https://bugzilla.gnome.org/show_bug.cgi?id=697845 + +2013-04-13 19:43:10 +0300 Sreerenj Balachandran + + * gst/gstpluginfeature.c: + pluginfeature: Fix the GstPluginFeature name comparison. + The gst_plugin_feature_rank_compare_func() should return + negative value, if the rank of both PluginFeatures are equal and + the name of first PluginFeature comes before the second one. + https://bugzilla.gnome.org/show_bug.cgi?id=697990 + +2013-04-14 17:54:22 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 2736592 to 3cb3d3c + +2013-04-14 17:25:35 +0100 Tim-Philipp Müller + + * autogen.sh: + * common: + Automatic update of common submodule + From aed87ae to 2736592 + +2013-04-14 11:33:41 +0100 Tim-Philipp Müller + + * gst/printf/printf.c: + * gst/printf/printf.h: + printf: disable some unused printf variants + +2013-04-14 11:23:10 +0100 Tim-Philipp Müller + + * gst/printf/gst-printf.h: + printf: use sprintf() to work around glibc complaining about %n in a writable format string + Don't use snprintf(), but use sprintf instead and do our own + length calculations, because glibc may complain about us passing + %n in a format string if the string is in writable memory, and + here the format string is always in writable memory since we + construct it on the fly. This happens if glibc has been compiled + with _FORTIFY_SOURCE=2, which seems to be the case on some + distros/systems). On the upside, we now use the sprintf code path + on all systems which should be better from a maintenance point + of view. + https://bugzilla.gnome.org/show_bug.cgi?id=697970 + +2013-04-13 12:18:28 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpoll.c: + tests: skip all GstPoll tests on Windows + As they don't work there, and it's non-trivial to fix. + https://bugzilla.gnome.org/show_bug.cgi?id=697609 + +2013-04-13 12:00:12 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: only add a '*' for non-'gpointer' pointers + Spotted by Jose Antonio Santos Cadena. + https://bugzilla.gnome.org/show_bug.cgi?id=697791 + +2013-04-12 14:48:29 +0200 Gwenole Beauchesne + + * gst/gstplugin.h: + plugin: fix name expansion for GST_PLUGIN_DEFINE macro + Make GST_PLUGIN_DEFINE use G_STRINGIFY() to convert the name argument + into a meaningful string. The advantage of this is that `name' can be + expanded from other macros defined in the plug-in element. + Signed-off-by: Gwenole Beauchesne + https://bugzilla.gnome.org/show_bug.cgi?id=697872 + +2013-04-13 11:35:49 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: add new translatable strings + +2013-04-12 23:58:52 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gstelement.c: + * gst/gstinfo.c: + printf: don't build if debugging subsystem was disabled + +2013-04-10 11:51:37 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/printf/Makefile.am: + * gst/printf/gst-printf.h: + printf: deal with some of the HAVE_FOO used in the printf code + Probably needs some more work for MSVC. + +2013-04-08 19:42:27 +0100 Tim-Philipp Müller + + * gst/printf/README: + * gst/printf/vasnprintf.c: + printf: fix alloca use for windows with mingw32 + Don't use just GLIB_HAVE_ALLOCA_H to check if alloca is available, + that's just for the header. GLib may define alloca for us otherwise + too irrespective of GLIB_HAVE_ALLOCA_H. + Fixes compiler warning with mingw32: + gst/printf/vasnprintf.c:73:0: warning: "alloca" redefined + +2013-04-07 20:11:21 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/printf/Makefile.am: + * gst/printf/vasnprintf.c: + printf: enable and fix compiler warnings + But suppress -Wformat-nonliteral warnings since sprintf + is used with a runtime-generated format string in our + vasnprintf implementation. + +2013-04-07 18:21:00 +0100 Tim-Philipp Müller + + * gst/printf/printf-parse.c: + * gst/printf/vasnprintf.c: + * gst/printf/vasnprintf.h: + printf: fix up dodgy use of #if HAVE_FOO and #if !HAVE_FOO + Should use #ifdef and #ifndef. + +2013-04-07 17:36:29 +0100 Tim-Philipp Müller + + * gst/printf/Makefile.am: + printf: mark internal functions as internal + +2013-04-07 17:29:02 +0100 Tim-Philipp Müller + + * gst/printf/printf-parse.c: + printf: skip pointer extension signifier chars after %p + So they don't get printed after the serialised pointer string. + +2013-04-07 17:21:10 +0100 Tim-Philipp Müller + + * gst/printf/vasnprintf.c: + printf: don't leak serialised pointer extension strings + +2013-04-07 17:02:55 +0100 Tim-Philipp Müller + + * gst/printf/printf-parse.c: + printf: handle old GST_PTR_FORMAT %P and GST_SEGMENT_FORMAT %Q defines too + For binary backwards compatibility. + +2013-04-07 16:41:40 +0100 Tim-Philipp Müller + + * gst/printf/printf-args.c: + * gst/printf/printf-args.h: + * gst/printf/printf-parse.c: + * gst/printf/printf-parse.h: + * gst/printf/vasnprintf.c: + printf: make printf parser recognise our pointer extension format + and call the hook to get a string for the pointer instead. + https://bugzilla.gnome.org/show_bug.cgi?id=613081 + +2013-03-30 18:28:38 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/printf/Makefile.am: + * gst/printf/README: + * gst/printf/printf-extension.c: + * gst/printf/printf-extension.h: + printf: add infrastructure for pointer extensions hook + Does not do anything yet. On a sidenote, we can't just use + %p\001 or so to signal the extension because g-i complains + about an invalid ascii character then, so have to resort to + something more elaborate, such as %p\aA etc. + https://bugzilla.gnome.org/show_bug.cgi?id=613081 + +2013-03-30 17:20:13 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/gstconfig.h.in: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + info: use new internal printf for debug message printing + and remove all the printf extension/specifier stuff for + the system printf. Next we need to add back the custom + specifiers to our own printf implementation. + https://bugzilla.gnome.org/show_bug.cgi?id=613081 + +2013-03-30 15:13:32 +0000 Tim-Philipp Müller + + * configure.ac: + * gst/Makefile.am: + * gst/printf/Makefile.am: + * gst/printf/README: + * gst/printf/asnprintf.c: + * gst/printf/gst-printf.h: + * gst/printf/printf-args.c: + * gst/printf/printf-args.h: + * gst/printf/printf-parse.c: + * gst/printf/printf-parse.h: + * gst/printf/printf.c: + * gst/printf/printf.h: + * gst/printf/vasnprintf.c: + * gst/printf/vasnprintf.h: + printf: add our own printf implementation for debug logging + We will add support for our own printf modifiers, so we can + get nice debug log output on all operating systems irrespective + of the specific libc version used. + https://bugzilla.gnome.org/show_bug.cgi?id=613081 + +2013-04-12 16:13:15 +0100 Wim Taymans + + * gst/gsttaglist.c: + taglist: avoid triggering an assertion + When deserialization of the structure fails, return a NULL taglist instead of + asserting. + +2013-04-11 14:54:32 +0200 Jose Antonio Santos Cadenas + + * tools/gst-inspect.c: + gst-inspect: add pointer mark to signal and action return types that are pointers + When the return type of a signal or action is a pointer, it + should have an asterisk to mark it as such. + https://bugzilla.gnome.org/show_bug.cgi?id=697791 + +2013-04-11 22:32:39 +0100 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: document type change of playbin's connection-speed property in porting docs + +2013-04-11 14:31:01 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add _gst_max_memory() function + Add the a function to query the maximum amount of memory blocks that can be + added to a buffer. Also improve the docs for _insert_memory(). + +2013-04-11 14:04:45 +0100 Wim Taymans + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: notify of changed bound address + Notify when the bound address is known, just like the port. + +2013-04-11 13:55:47 +0100 Wim Taymans + + * tools/gst-launch.c: + launch: handle PROGRESS messages + Wait for all PROGRESS messages (if any) to complete before going to the PLAYING + state. This is the only way we can wait for live elements to complete their + operations. + This is interesting for elements like rtspsrc that do some asynchronous network + requests as part of going to the PAUSED state. It could be possible that it, for + example, provides a clock and then we would like to wait until it completes + so that we can use the provided clock when going to PLAYING. + +2013-04-11 15:05:08 +1200 Douglas Bagnall + + * docs/pwg/advanced-negotiation.xml: + Toggle upstream and downstream in RECONFIGURE paragraph. + +2013-04-11 10:11:25 +1200 Douglas Bagnall + + * libs/gst/base/gstcollectpads.c: + GstCollectPads documentation: gst_collect_pads_read is gone. + +2013-04-10 21:24:38 +0200 Stefan Sauer + + * gst/gstbus.c: + bus: fix the precondition for gst_bus_disable_sync_message_emission() + Use the right variable and invert the test. The precondition should catch + someone calling to once too often. + +2013-04-09 19:37:06 -0400 Olivier Crête + + * gst/gstcapsfeatures.c: + capsfeatures: Init debug category before ever using it + +2013-04-09 20:59:36 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 04c7a1e to aed87ae + +2013-04-03 21:32:54 +0400 Руслан Ижбулатов + + * docs/manuals.mak: + Use xlstproc instead of docbook2html + +2013-04-09 10:17:45 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnetclientclock.c: + netclientclock: bind socket before querying local address + Fails on windows otherwise. + https://bugzilla.gnome.org/show_bug.cgi?id=697608 + +2013-04-08 13:14:35 +0400 Руслан Ижбулатов + + * configure.ac: + configure: Also check for clock_gettime in libpthread + libwinpthreads provides POSIX time API. + It also provides libpthread alias for itself, for compatibility, so that + is what we will link with. + Fixes #697550 + +2013-04-08 15:30:07 +0400 Руслан Ижбулатов + + * gst/gstsystemclock.c: + * gst/gstutils.c: + clock: Do use HAVE_CLOCK_GETTIME + Fixes #697549 + +2013-04-08 14:42:15 +0400 Руслан Ижбулатов + + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_i386w.h: + libsabi: Special struct size values for W32 + These account for both possible type size mismatch AND -mms-bitfields + packing. Sizes are taken from an i686-w64-mingw32-built GStreamer, + gcc 4.8.0, mingw-w64 svn-r5685. + Fixes #697551 + +2013-04-09 09:22:39 +0400 Руслан Ижбулатов + + * tests/check/gst/gstpad.c: + tests: fix GstPad test on windows and in CK_FORK=no mode + Need to clear buffer lists at the end of each test. + https://bugzilla.gnome.org/show_bug.cgi?id=697610 + +2013-04-06 16:09:54 -0700 David Schleef + + * tools/gst-launch.c: + gst-launch: Fix space in fault message + +2013-04-06 22:10:58 +0200 Sebastian Dröge + + * gst/gstcapsfeatures.c: + capsfeatures: Copy ANY flag when copying caps features too + +2013-04-06 21:49:25 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * tools/gst-inspect.c: + caps: Handle ANY caps features properly in more places + +2013-04-06 21:21:39 +0200 Sebastian Dröge + + * tests/check/gst/gstcaps.c: + caps: Add test for operations on caps with ANY features + +2013-04-06 21:09:49 +0200 Sebastian Dröge + + * gst/gstcaps.c: + caps: Properly handle ANY caps features in caps operations + +2013-04-05 21:10:48 +0200 Stefan Sauer + + * gst/gstbus.c: + bus: update signal docs for gst_bus_enable_sync_message_emission() + +2013-04-05 10:15:37 +0200 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: ignore empty not-linked queues + We need to ignore the not-linked queues in the underrun and overrun callbacks + because they are expected to be empty. + +2013-04-04 23:12:52 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: fix caps feature leak + Fixes leaks in 14 core unit tests including + gst/gstcaps. + +2013-04-04 19:16:23 +0200 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: start pushing again on RECONFIGURE + When we got NOT_LINKED before and we receive a RECONFIGURE event, start pushing + again on the source pad. + See https://bugzilla.gnome.org/show_bug.cgi?id=676304 + +2013-04-04 19:07:29 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: start pushing again on RECONFIGURE + When we got NOT_LINKED before and we receive a RECONFIGURE event, start pushing + again on the source pad. + See https://bugzilla.gnome.org/show_bug.cgi?id=676304 + +2013-04-04 19:06:35 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + queue: start pushing again on RECONFIGURE + When we got NOT_LINKED before and we receive a RECONFIGURE event, start pushing + again on the source pad. + See https://bugzilla.gnome.org/show_bug.cgi?id=676304 + +2013-04-04 17:59:10 +0200 Wim Taymans + + * gst/gststructure.c: + structure: simplify is_subset check + Iterate over the fields of the superset instead of those of the subset. + This way we can check the presence of the subset field and do the subset check + in one iteration. + +2013-04-04 17:46:09 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: update docs, is_subset() works now + +2013-04-04 16:39:23 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: fix docs + +2013-04-04 16:20:24 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: add gst_pad_store_sticky_event() + Rewire some internal functions and expose a new + gst_pad_store_sticky_event() function. + API: gst_pad_store_sticky_event() + +2013-04-04 15:45:23 +0200 Wim Taymans + + * gst/gstpad.h: + pad: clarify docs + +2013-04-04 15:45:15 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve debug + +2013-04-04 10:17:30 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: don't WARN, just DEBUG + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=696911 + +2013-03-30 11:06:59 +0000 Nicolas Dufresne + + * gst/gstsegment.c: + segment: Fix seeking when position is slightly outside the segment + Very often, when the end of a segment is detected by demuxer, the position + is slightly outside the segment boundaries. Currently, if that is the case + the base will be set to NONE instead of normal accumulation. This would + break non-flushing seeks in oggdemux and most likely other demuxers. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=696899 + +2013-04-03 17:29:51 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2013-04-03 16:02:34 +0200 Wim Taymans + + * gst/gst.c: + gst: add stream flags + +2013-04-02 18:17:00 -0600 Brendan Long + + * docs/random/porting-to-1.0.txt: + porting-to-1.0.txt: subtitle text media types changed as well + https://bugzilla.gnome.org/show_bug.cgi?id=697153 + +2013-04-02 23:51:06 +0100 Tim-Philipp Müller + + * gst/gstcontext.c: + * gst/gstevent.c: + * gst/gstevent.h: + * tests/check/gst/.gitignore: + docs: more since markers and other docs fixes + +2013-04-02 23:21:39 +0100 Tim-Philipp Müller + + * gst/gstcapsfeatures.c: + docs: add since markers to capsfeatures docs + +2013-04-02 23:18:42 +0100 Tim-Philipp Müller + + * scripts/git-update.sh: + scripts: add some more modules to git-update.sh + https://bugzilla.gnome.org/show_bug.cgi?id=697058 + +2013-04-02 23:04:51 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add uninstalled orc/orc-test/.libs to library paths + This is needed by the unit tests in gst-plugins-base, -good etc. + Spotted by Alex Kaye. + https://bugzilla.gnome.org/show_bug.cgi?id=697093 + +2013-04-02 22:13:22 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcapsfeatures.c: + * gst/gstcapsfeatures.h: + * tests/check/gst/gstcapsfeatures.c: + capsfeatures: Add GST_CAPS_FEATURES_ANY + This is equal to any other caps features but results in unfixed caps. It + would be used by elements that only look at the buffer metadata or are + currently working in passthrough mode, and as such don't care about any + specific features. + +2013-04-01 22:13:10 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: minor cosmetic changes + Let's not use ugly leading underscores for + static functions. + +2013-04-01 21:23:21 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: fix object printing of caps features in debug log + +2013-04-01 16:38:43 +0200 Stefan Sauer + + * docs/design/draft-tracing.txt: + draft-tracing: update draft design with timer ideas + +2013-03-30 17:03:44 +0100 Stefan Sauer + + * gst/gstinfo.c: + info: refactor pretty printing objects + Extract formatters into local functions. Change the structure filtering so that + it works for taglists too. + +2013-03-30 16:39:38 +0100 Stefan Sauer + + * gst/gstelement.c: + element: make post_message and query more alike + +2013-04-01 10:20:01 +0200 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Print caps features too + +2013-04-01 10:19:25 +0200 Sebastian Dröge + + * gst/gstcapsfeatures.c: + capsfeatures: For copying features it's not required to have no parent refcount + +2013-04-01 10:19:01 +0200 Sebastian Dröge + + * gst/gstcaps.c: + caps: Set features' parent refcount in gst_caps_set_features() too + +2013-04-01 10:18:39 +0200 Sebastian Dröge + + * gst/gstcaps.c: + caps: Set sysmem features if explicitely requested + +2013-03-31 19:09:46 +0200 Sebastian Dröge + + * docs/design/part-caps.txt: + design: Add the caps features and describe how the caps operations actually work + +2013-03-30 15:35:19 +0100 Sebastian Dröge + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstcapsfeatures.c: + * gst/gstcapsfeatures.h: + * gst/gstinfo.c: + * gst/gststructure.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * tests/check/Makefile.am: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstcapsfeatures.c: + * win32/common/libgstreamer.def: + caps: Add new data type for handling caps features to the caps + These are meant to specify features in caps that are required + for a specific structure, for example a specific memory type + or meta. + Semantically they could be though of as an extension of the media + type name of the structures and are handled exactly like that. + +2013-03-31 15:30:19 +0100 Tim-Philipp Müller + + * gst/gstevent.h: + event: add SELECT and UNSELECT stream flags for stream-start event + So demuxers can signal which audio/video/subtitle streams should + be selected by default and which should not be selected + automatically. + API: GST_STREAM_FLAG_SELECT + API: GST_STREAM_FLAG_UNSELECT + https://bugzilla.gnome.org/show_bug.cgi?id=695968 + https://bugzilla.gnome.org/show_bug.cgi?id=690911 + +2013-01-06 20:27:54 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * tests/check/gst/gstevent.c: + * win32/common/libgstreamer.def: + event: add stream flags to stream-start event + API: gst_event_set_stream_flags() + API: gst_event_parse_stream_flags() + API: GST_STREAM_FLAG_NONE + API: GST_STREAM_FLAG_SPARSE + https://bugzilla.gnome.org/show_bug.cgi?id=600648 + +2013-03-31 11:26:32 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: Add API to get the last set context from an element + Elements should override GstElement::set_context() and also call + gst_element_set_context() to keep this context up-to-date with + the very latest context they internally use. + +2013-03-30 14:04:28 +0100 Stefan Sauer + + * docs/design/draft-tracing.txt: + design: add initial tracing design doc + +2013-03-30 11:47:29 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Let gst_pad_get_allowed_caps() pass the caps own caps as filter + This will reduce the number of caps created downstream and we don't + need to intersect in the very end with the pad's own caps. + +2013-03-30 10:24:27 +0100 Josep Torra + + * libs/gst/base/gstbasesink.c: + basesink: fixes compiler warning + gstbasesink.c: In function 'gst_base_sink_chain_unlocked': + gstbasesink.c:3204: warning: 'ret' may be used uninitialized in this function + +2013-03-29 19:01:59 +0100 Stefan Sauer + + * gst/gstchildproxy.c: + childproxy: fix gir warning + +2013-03-29 18:49:14 +0100 Edward Hervey + + * docs/pwg/building-boiler.xml: + Revert "pwg: Fix example" + This reverts commit 5d64f27d881274a40f0441bb8c5b3816fdfc5b9e. + *sigh* + +2012-11-06 09:41:58 +0100 Edward Hervey + + * docs/pwg/building-boiler.xml: + pwg: Fix example + +2012-11-11 13:52:25 +0100 Edward Hervey + + * gst/gstpad.c: + pad: Remove SEGMENT sticky events when flushing + When flushing, it is expected that upstream will send a SEGMENT + event afterwards. + This also avoids stray SEGMENT events from coming through after a + flush. + +2013-03-28 15:35:13 +0100 Sebastian Dröge + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstinfo.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + gst: Add new GstContext miniobject for sharing contexts in a pipeline + +2013-03-28 16:42:50 +0100 Stefan Sauer + + * libs/gst/controller/gstargbcontrolbinding.c: + argb-controlbinding: fix messed up property setter + This was misassigning the control sources. It was also leaking the old values if + a control source would be replaced. + +2013-03-27 18:25:08 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: reset next_pts upon SEGMENT event + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=691481 + +2013-02-26 19:58:49 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: more inter-timestamp tracking + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=691481 + +2013-03-26 19:22:18 -0400 Olivier Crête + + * docs/gst/gstreamer-sections.txt: + * gst/gstallocator.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: Add annotations and pygi friendly extraction function + API: gst_buffer_extract_dup + +2013-03-27 17:08:51 +0100 Wim Taymans + + * docs/random/porting-to-1.0.txt: + porting: hopefully clarify a little + +2013-03-25 18:11:54 -0700 David Schleef + + * gst/gstutils.c: + Update docs for gst_pad_create_stream_id_printf() + To indicate that format strings should be alpha sortable. + +2013-03-25 09:16:05 +0100 Sebastian Dröge + + * tests/check/gst/gstcaps.c: + caps: Add unit test for GST_CAPS_{ANY,NONE} and GST_STATIC_CAPS_{ANY,NONE} + https://bugzilla.gnome.org/show_bug.cgi?id=696435 + +2013-03-25 09:19:24 +0100 Sebastian Dröge + + * gst/gstcaps.c: + caps: Fix gst_static_caps_get(GST_STATIC_CAPS_NONE) + https://bugzilla.gnome.org/show_bug.cgi?id=696435 + +2013-03-21 21:00:54 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't send error if negotiate fails because we are flushing + Negotiation may be aborted by a flush from another thread that need to + stop the task (i.e. seek). Check that case and silently pause the task. + https://bugzilla.gnome.org/show_bug.cgi?id=696357 + +2013-03-24 17:53:35 +0000 Tim-Philipp Müller + + * docs/design/part-toc.txt: + * gst/gsttoc.c: + toc: some documentation updates + +2013-03-22 20:02:57 +0000 Tim-Philipp Müller + + * docs/pwg/building-queryfn.xml: + docs: fix typo in query function example in Plugin Writer's Guide + https://bugzilla.gnome.org/show_bug.cgi?id=696142 + +2013-03-07 12:11:30 +0100 Jonas Holmberg + + * tests/check/libs/collectpads.c: + tests: fix spurious failure in test_collect collectpads test + pop() in collected callback. + There were three threads in the test cases that hanged: the test thread and two + threads that push buffers. Each thread push one buffer on one pad. There are + two pads in the collectpads so the second buffer will trigger the + collect-callback. + This is what happens when the hang occurs: + The first thread pushes a buffer and initializes a cookie to the value of a + counter in the collectpads object and waits on a cond for the counter to change + and for someone to consume the buffer (i.e. _pop() it). + The second thread pushes a buffer and calls the collected callback, which + signals the cond that the test thread is waiting for. + The test thread pops both buffers (without holding any lock). Each call to + _pop() increases the counter broadcasts the condition that the first thread is + now waiting for. It then joins both threads (hangs). + The first thread wakes up and returns, since its buffer has been consumed. + The second thread starts executing again. When the callback, called by the + second thread, has returned it initializes a cookie to the value of a counter, + which has already prematurely been increased by the test thread when it popped + the buffers, and wait's on a cond for the counter to change and for someone to + consume the buffer (i.e. _pop() it). Since the buffer has already been poped + and the counter has already been increased it will be stuck forever. + https://bugzilla.gnome.org/show_bug.cgi?id=685555 + +2013-03-16 12:05:39 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: remove ffmpeg libs from dynamic linker paths + We link those libs into the plugin statically, or use external + system libs, but never the internal snapshot dynamically. + +2013-03-16 12:00:55 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add gst-editing-serves to GI_TYPELIB_PATH + So pygi can find it. + https://bugzilla.gnome.org/show_bug.cgi?id=695937 + +2013-03-12 13:53:57 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + utils: make sure slow GST_READ_UINT* variants don't have unexpected side effects + Fixes unit test on systems where unaligned memory access is not possible. + https://bugzilla.gnome.org/show_bug.cgi?id=695599 + +2013-03-05 11:14:41 +0100 Wim Taymans + + * tools/gst-launch.c: + launch: don't exit the loop on buffering in paused + When we receive a buffering message of 100% in the paused state, we exit + the event_loop and move to the PLAYING state. What should happen is that + we wait for both ASYNC-DONE and 100% buffering before continueing. + +2013-03-08 13:15:32 +0100 Stefan Sauer + + * docs/design/part-controller.txt: + design: update controller design and add some thoughs for future stuff + +2013-03-08 08:13:06 +0100 Stefan Sauer + + * libs/gst/controller/gstdirectcontrolbinding.c: + docs: mention clipping of values in control-binding docs + +2013-03-08 08:10:20 +0100 Stefan Sauer + + * tests/check/gst/gstcontroller.c: + controller: code cleanups + Use a property for accessing the control-source on the binding. Drop base_init + on the test object. + +2013-03-07 11:46:33 +0100 Sebastian Dröge + + * gst/gstquery.c: + query: gst_query_get_n_allocation_params() returns a new ref to the allocator + +2013-03-07 11:35:03 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + controller: remove a bogus test + We previously forgot to initilize the amplitde property to the default and thus it was 0.0. Therefore a default lfo controlsource returned a series of 0.0 and the test was asserting on that. + +2013-03-07 09:15:14 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + controlbinding: relax the pspec for the control-source + We can change control sources on controlbindings. + +2013-03-07 09:12:59 +0100 Stefan Sauer + + * libs/gst/controller/gstlfocontrolsource.c: + lfo: set a sensible lower boundary for the frequency + Use DBL_MIN, which is a the smalles double greater than zero that is not in + denormal format. This exposes the limit better than the runtime check. + +2013-03-06 23:59:28 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 2de221c to 04c7a1e + +2013-03-06 16:40:27 +0100 Stefan Sauer + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: init the amplitude to the default and update the docs + +2013-03-05 11:30:22 +0100 Sebastian Dröge + + * scripts/gst-uninstalled: + gst-uninstalled: Add all the base/bad libraries and remove obsolete ones + +2013-03-03 16:00:11 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: fix use of uninitialized variable + Running suite(s): GstBaseSink + ==22023== Conditional jump or move depends on uninitialised value(s) + ==22023== at 0x505FFCE: gst_base_sink_get_sync_times (gstbasesink.c:1936) + ==22023== by 0x5068C80: gst_base_sink_do_sync (gstbasesink.c:2379) + ==22023== by 0x506BCD2: gst_base_sink_default_wait_event (gstbasesink.c:2903) + ==22023== by 0x50633A4: gst_base_sink_default_event (gstbasesink.c:2918) + ==22023== by 0x6F5C216: gst_fake_sink_event (gstfakesink.c:383) + ==22023== by 0x505F164: gst_base_sink_event (gstbasesink.c:3108) + ==22023== by 0x52FA090: gst_pad_send_event_unchecked (gstpad.c:4822) + ==22023== by 0x5303756: gst_pad_send_event (gstpad.c:4984) + ==22023== by 0x40165B: basesink_test_gap (basesink.c:148) + +2013-03-03 12:06:36 +0100 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Fix memory copying logic in copy_into() + https://bugzilla.gnome.org/show_bug.cgi?id=695035 + +2013-03-03 11:28:32 +0100 Sebastian Dröge + + * gst/gstregistrychunks.c: + registrychunks: Use correct print format specifiers to fix compiler warnings + +2013-02-22 14:22:01 -0800 David Schleef + + * gst/gstobject.c: + Fix misspellings of 'continuous' + +2013-02-22 14:56:49 -0800 David Schleef + + * libs/gst/base/gstcollectpads.c: + collectpads: take DTS into account + Importantly, this patch converts DTS to running time. Less importantly, + and possibly a problem for some muxers, is that it orders buffers by + DTS (if it is valid, otherwise PTS). This is generally correct, but + might be somewhat surprising to muxers. + Also note that once converted to running time, DTS can end up negative. + +2013-02-28 22:59:43 +0100 Stefan Sauer + + * docs/manual/advanced-dparams.xml: + manual: improve the controller docs a little more + Reword some sections. Explain value mappings better. + +2013-02-28 19:40:32 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add gst-libav to pkg-config path + +2013-02-27 22:15:48 +0100 Stefan Sauer + + * gst/gstsegment.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + seeking: add more logging for seeking + Especially add logging to error code paths. + +2013-02-27 10:09:56 +0100 Sebastian Dröge + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: Gracefully handle gst_memory_copy() returning NULL without crashing + gst_buffer_copy_into() and gst_buffer_resize_range() can now fail. + +2013-02-26 17:33:30 +0100 Wim Taymans + + * gst/gstallocator.c: + * win32/common/libgstreamer.def: + allocator: small internal cleanups + Rename System memory allocator to GstAllocatorSysmem and the memory to + GstMemorySystem. + +2013-02-26 15:37:24 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add method to check memory type + Add a method to check if a memory was allocated from an allocator of + a given type. + API: gst_memory_is_type() + +2013-02-26 15:36:10 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: improve docs a little + +2013-02-26 15:32:25 +0100 Wim Taymans + + * docs/design/part-gstbin.txt: + * docs/design/part-messages.txt: + * gst/gstbin.c: + use GST_MESSAGE_DURATION_CHANGED in docs and code + +2013-02-26 14:40:38 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: don't unref allocator too soon + Unref the allocator *after* we have freed the memory. We also need to keep + a ref to the allocator around because following the now freed memory would + lead to crashes. + +2013-02-26 09:08:49 +0100 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: Fix inverted logic for deciding if memory should be shared or copied + https://bugzilla.gnome.org/show_bug.cgi?id=694717 + +2013-02-26 07:50:13 +0100 Stefan Sauer + + * docs/random/porting-to-1.0.txt: + porting: mention segment accumulation in the porting guide + This needs more detail, but at least gives people a hint on the issue. + +2013-02-26 07:48:35 +0100 Stefan Sauer + + * gst/gstmessage.c: + docs: s/start/done/ copy'n'paste mistake + +2013-02-25 13:57:43 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: Add new API to remove allocation params and pools from the allocation query + +2013-02-25 13:24:33 +0100 Sebastian Dröge + + * gst/gstquery.c: + query: Document that the first allocator in the allocation query should allow mapping to system memory + +2013-02-24 09:24:26 +0100 Sebastian Dröge + + * gst/gstmemory.c: + memory: Keep a reference to the allocator + Otherwise the allocator might get freed while it's still used + by the memory + +2013-02-24 09:33:03 +0100 Sebastian Dröge + + * gst/gstbuffer.c: + buffer: If sharing a GstMemory fails, fall back to copying it + +2013-02-23 18:36:15 +0000 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: porting-to-1.0.txt: some element names have changed + +2013-02-23 08:19:48 +0100 Sebastian Dröge + + * gst/gstmemory.h: + memory: It's contiguous, not continous + +2013-02-22 12:41:09 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstmemory.h: + memory: Add new memory flag to specify that memory can't be mapped + +2013-02-22 09:02:22 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstmemory.h: + memory: Add memory flag to mark physically continous memory + +2013-02-16 23:02:21 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasetransform.c: + basetransform: don't pass NULL outcaps to transform_size on shutdown + gst_pad_get_current_caps() on the source pad might yield NULL caps + if we're being shut down and the source pad has already been + deactivated by the other thread that's changing state. Just bail + out in that case, instead of passing NULL caps to the transform_size + function, which it might not expect. + Fixes spurious warnings in audioresample shutdown unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=693996 + +2013-02-21 10:18:14 +0100 Sebastian Dröge + + * scripts/gst-uninstalled: + gst-uninstalled: Add ORC + +2013-02-19 18:00:48 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + * tests/check/gst/gstutils.c: + utils: avoid unexpected side-effects of GST_WRITE_* macros + Make sure the data argument is only evaluated once. + +2013-02-19 17:36:50 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstcheck.h: + * tests/check/gst/gstutils.c: + check: add some more fail_unless_*() macros for convenience + API: fail_unless_equals_int_hex + API: assert_equals_int_hex + API: fail_unless_equals_int64_hex + API: assert_equals_int64_hex + API: fail_unless_equals_uint64_hex + API: assert_equals_uint64_hex + API: fail_unless_equals_pointer + API: assert_equals_pointer + +2013-02-19 12:42:32 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + scripts: add new -base allocators library to gst-uninstalled search paths + +2013-02-18 20:47:04 +0100 Stefan Sauer + + * tests/check/libs/collectpads.c: + collectpads: add two more tests using collectpads within an element + Add a static plugin with a rudimentary element using collectpads and do some + pipeline based tests. + +2013-02-17 12:50:03 -0800 David Schleef + + * docs/manual/appendix-porting.xml: + docs: Fix some ambiguous wording + +2013-02-17 19:53:55 +0100 Stefan Sauer + + * libs/gst/controller/gsttriggercontrolsource.c: + triggercontrolsource: add missing end_iter check for sequence + Avoid accessing the end-iter, this is a marker without a data field. + +2013-02-17 13:20:20 +0100 Stefan Sauer + + * gst/gstelement.c: + docs: link to the appropriate messages from gst_elements_set_state() docs + For an async state change return one would wait for ASYNC_DONE or STATE_CHANGED. + +2013-02-16 14:20:06 +0000 Tim-Philipp Müller + + * gst/gstbuffer.h: + buffer: add since marker for new COPY_DEEP buffer flag + +2013-02-16 14:59:02 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add option to deep copy a buffer + Add a buffer copy flag to force a memory copy in all cases. + +2013-02-14 14:09:13 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + Revert "utils: Use gst_pad_get_pad_template() in gst_element_get_compatible_pad_template()" + This reverts commit 1a1a9e143fb0e155d7627aa8e489cd5d04bc093c. + This breaks the pipelines/tagschecking unit test for some reason + (fakesrc ! capsfilter ! qtmux linking fails now). It might be + a bug in the unit test of course, but someone will need to + investigate this. Reverting for now. + https://bugzilla.gnome.org/show_bug.cgi?id=692508 + +2013-02-15 13:08:18 +0100 Wim Taymans + + * gst/gstallocator.c: + allocator: improve fallback copy function + Only use the allocator of the copied memory when we can use the default + _alloc function on it. Otherwise we will have to use the default + allocator for the copy. + +2013-02-14 13:55:10 +0000 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: fix location in user's home directory where GStreamer looks for plugins + It's based on the xdg user data dir now in 1.0. + +2013-01-25 06:50:27 -0300 Niv Sardi + + * gst/gstutils.c: + utils: Use gst_pad_get_pad_template() in gst_element_get_compatible_pad_template() + motivation comes from: /* FIXME: why not gst_pad_get_pad_template (pad); */ + this code path is quite nicer, we now only revert to creating the template + if gst_pad_get_pad_template fails. + with this fork, we gain a non-allocation of GstCaps *templcaps + https://bugzilla.gnome.org/show_bug.cgi?id=692508 + +2013-02-13 00:27:28 +0000 Krzysztof Konopko + + * tools/gst-launch.c: + gst-launch: Use g_unix_signal_add() to handle keyboard interruption + Current implementation uses a traditional signal handler and a 250ms + timeout callback in the event loop. Adding a GSource with + g_unix_signal_add() to the GMainLoop is a much more elegant solution. + The signal handler with this approach can send a message to the bus + directly rather than set a flag as all dispatching intricacies are handled + by GLib. + https://bugzilla.gnome.org/show_bug.cgi?id=693481 + +2013-02-14 00:07:22 +0000 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: flesh our 'Running GStreamer' bits a bit + https://bugzilla.gnome.org/show_bug.cgi?id=693607 + +2013-02-13 23:27:16 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + docs: flesh out gst-launch-1.0 man page a little + Fix up default location of the registry. + Mention more options for GST_DEBUG (wildcards and + named debug levels). + Explain what to do with the dot files that can be + produced by setting GST_DEBUG_DUMP_DOT_DIR. + https://bugzilla.gnome.org/show_bug.cgi?id=693607 + +2012-12-27 00:03:06 +0100 Gert Michael Kulyk + + * docs/manual/advanced-metadata.xml: + docs: fix advanced-metadata code example in manual + https://bugzilla.gnome.org/show_bug.cgi?id=690751 + +2013-02-13 16:52:13 +0000 Tim-Philipp Müller + + * gst/gstmessage.c: + * tests/check/gst/gstmessage.c: + message: accept NULL error argument in gst_message_parse_{error,warning,info} + And simplify code a bit while at it. + https://bugzilla.gnome.org/show_bug.cgi?id=693704 + +2013-02-13 17:00:23 +0100 Sebastian Dröge + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Remove set-style bitmask intersection/union/subtraction functions + Set operations on the bitmasks don't make much sense and result + in invalid caps when used as a channel-mask. They are now handled + exactly like integers. + This functionality was not used anywhere except for tests. + https://bugzilla.gnome.org/show_bug.cgi?id=691370 + +2013-02-13 11:19:06 +0100 Sebastian Dröge + + * gst/gstbin.c: + bin: The latency query should return TRUE by default, different to other queries + Fixes unit test failures caused by f3d268de7f7fb1161778a9a95e0d54d8c89ef626 + +2013-02-13 10:46:37 +0100 Sebastian Dröge + + * gst/gststructure.c: + * tests/check/gst/gstcaps.c: + structure: Make sure that subsets have all fields of the superset + "video/x-h264,parsed=(boolean)true" is not a superset of + "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal" + for example. + https://bugzilla.gnome.org/show_bug.cgi?id=693365 + +2013-02-12 12:32:23 -0800 David Schleef + + * win32/common/libgstbase.def: + update exports for baseparse API changes + +2013-02-12 12:31:42 -0800 David Schleef + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix doc typo + +2013-02-11 16:51:48 -0800 David Schleef + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: add gst_base_parse_set_ts_at_offset() + Sets the buffer timestamps based on last seen timestamps at a + particular offset into the frame. + API: gst_base_parse_set_ts_at_offset() + +2013-02-11 16:42:41 -0800 David Schleef + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: Add gst_adapter_prev_[pd]ts_at_offset() + Original patch written by Michael Smith . + API: gst_adapter_prev_pts_at_offset() + API: gst_adapter_prev_dts_at_offset() + +2013-02-09 18:14:09 +0100 Philippe Normand + + * gst/gstbin.c: + bin: query sink elements and source pads of the bin + gst_bin_query() now forwards the query to the source pads as well if + none of the sinks of the bin satisfied the query. This helps in the + case of DURATION queries done a bin containing a source element. + Fixes bug 638749 + +2013-02-07 12:47:02 +0100 Alexander Schrab + + * gst/gstbin.c: + bin: Let gst_bin_send_event() send events to ghost pads as well + +2013-02-11 22:52:25 +0100 Stefan Sauer + + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + compat: kill more uses of gst_pad_set_caps() + +2013-02-12 00:08:51 +1100 Tim 'mithro' Ansell + + * gst/gstvalue.c: + gstvalue: Adding offset to GstSegment serialize/deserialize. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=693587 + +2013-02-09 12:32:02 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: improve PTS interpolating + ... and tracking of DTS. Fixes cases where PTS is locked on to the + DTS of an incoming buffer with no PTS with invalid data, leading to + no outgoing PTS (since it is not allowed smaller than DTS). + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=691481 + +2013-02-08 21:28:18 +0100 Stefan Sauer + + * docs/random/porting-to-1.0.txt: + docs: add more porting details + +2013-02-08 21:21:48 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + * gst/gstobject.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + controlbinding: error handling for binding controlsources to wrong properties + Add warning if property is not suitable for controlling. When adding a control- + binding check that pspec!=NULL. + +2013-02-07 13:08:49 +0100 Wim Taymans + + * gst/gstelement.c: + element: remove old docs about iterators + +2013-02-07 12:52:26 +0100 Wim Taymans + + * gst/gstbin.c: + bin: remove old comment + The iterators now return a GValue and not the object directly anymore. + +2013-02-07 12:50:08 +0100 Wim Taymans + + * gst/gstbin.c: + bin: reset GValue from iterator after usage + +2013-02-05 17:15:37 +0100 Wim Taymans + + * tests/check/libs/basesink.c: + tests: add basesink test + +2013-02-05 17:19:50 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: handle sync of EOS after item without duration + After a buffer or GAP without duration, an EOS event should be rendered + immediately instead of waiting for the end of the segment. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=692868 + +2013-02-02 11:55:52 -0800 Nate Bogdanowicz + + * gst/gstpipeline.c: + gstpipeline: fix failed assertion caused by seeking pipeline with NULL clock + Under certain GST_STATE_CHANGED_PAUSED_TO_PLAYING transitions, a pipeline with + a NULL clock will fail an assertion due to an unchecked call to gst_object_ref(). + This is fixed by simply adding a check and only ref-ing if the clock is not NULL. + https://bugzilla.gnome.org/show_bug.cgi?id=693065 + +2013-02-05 13:44:06 +0100 Wim Taymans + + * gst/gststructure.h: + structure: change argument name for docs + +2013-02-04 10:30:32 +0100 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: fix order of caps on an unnegotiated link + headlabel is the sink_pad (where the link points to) and not the other way around. + +2013-02-01 21:59:41 +0100 Stefan Sauer + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * gst/gstcontrolbinding.c: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + docs: update the controller docs + Add the control bindings to the docs. Add a little more detail. + +2013-02-01 21:57:45 +0100 Stefan Sauer + + * docs/random/porting-to-1.0.txt: + porting: a few updates for the porting guide + +2013-01-30 13:06:44 +0000 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.c: + dataqueue: can't pass a GType through GINT_TO_POINTER + Use GSIZE_TO_POINTER instead. sizeof(GType) may be larger + than sizeof(gulong) and sizeof(int), so the casts may + chop off some bits from the GType value on some architectures. + +2013-01-29 12:40:52 +0100 Alexander Schrab + + * tests/check/elements/queue.c: + tests: unit test to trigger the queue/flushing race condition bug for allocation queries + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + +2013-01-28 11:05:28 +0100 Alexander Schrab + + * plugins/elements/gstqueue.c: + queue: remove query from queue if queue is flushing + When querying a queue that is flushing we end up adding + a query to the queuearray without taking a reference to + that query (because the normal functionality is to block + until that query is done and discarded from the queue). + This later causes problem if the query is unreffed outside + of the queue before we discard the queue. There is a check + to avoid unreffing any lingering query-objects, but since + the query has been deleted that check fails. + This commit depends on other fixes done to gst_queue_array_find() + and gst_queue_array_drop_element(). + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + +2013-01-30 11:55:18 +0000 Tim-Philipp Müller + + * libs/gst/base/gstqueuearray.c: + queuearray: make _find() find the value if no compare function is provided + Allow NULL as compare function for direct value lookup. + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + +2013-01-30 11:34:15 +0000 Tim-Philipp Müller + + * tests/check/libs/queuearray.c: + tests: check return value of gst_queue_array_drop_element() too + Was added when the API was made public in git master. + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + +2013-01-29 22:54:21 +0000 Tim-Philipp Müller + + * tests/check/libs/queuearray.c: + tests: one more test for gst_queue_array_drop_element() + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + Conflicts: + tests/check/libs/queuearray.c + +2013-01-28 11:05:28 +0100 Alexander Schrab + + * libs/gst/base/gstqueuearray.c: + queuearray: fix gst_queue_array_find() + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + +2013-01-28 11:05:28 +0100 Alexander Schrab + + * libs/gst/base/gstqueuearray.c: + queuearray: fix gst_queue_array_drop_element() + https://bugzilla.gnome.org/show_bug.cgi?id=692691 + Conflicts: + libs/gst/base/gstqueuearray.c + +2013-01-29 16:55:23 +0200 Sreerenj Balachandran + + * libs/gst/base/gstbitreader-docs.h: + docs: align the comments correctly with the declaration in bitreader docs + https://bugzilla.gnome.org/show_bug.cgi?id=692809 + +2013-01-29 09:45:23 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle renegotiation correctly + Don't retry to negotiate when we fail to negotiate but instead produce a + NOT_NEGOTIATED error. We only want to retry negotiation if the result from + gst_pad_push() returned NOT_NEGOTIATED. + +2013-01-28 20:41:20 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From a942293 to 2de221c + +2013-01-28 13:05:44 +0100 Wim Taymans + + * tests/examples/streams/stream-status.c: + example: fix FIXME in example + Use setpriority to raise priority + +2013-01-27 06:20:51 -0800 Simon Feltman + + * gst/Makefile.am: + g-i: add built enumtypes headers and sources to gir creation + Add gstenumtypes.h/c for inclusion with g-ir-scanner. This fixes + problems where introspection based bindings think GstState is + typeless due to the GType not being included as an annotation. + https://bugzilla.gnome.org/show_bug.cgi?id=691185 + +2013-01-27 09:18:00 +0530 B.Prathibha + + * tests/check/pipelines/stress.c: + tests: use g_timeout_add_seconds in pipeline stress test + https://bugzilla.gnome.org/show_bug.cgi?id=692612 + +2013-01-24 17:50:31 -0500 Olivier Crête + + * docs/libs/gstreamer-libs-sections.txt: + docs: Put the right path for the gstttestclock include file + +2013-01-24 15:50:17 +0100 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: rename variable + The filter variable was used twice for different things. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=692432 + +2013-01-17 21:35:48 -0300 Niv Sardi + + * gst/gstpad.c: + gst_pad_check_reconfigure: only remove flag if set. + the code ifed a debug statement, that can't be right. anyway, the way it is, + we don't really need that branch, as we set the flag to unset only if set + (and that can't fail) hence the end result is always to unset the flag. + Signed-off-by: Niv Sardi + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=691985 + +2013-01-17 21:43:25 -0300 Niv Sardi + + * libs/gst/base/gstbasesrc.c: + basesrc: set NEED_RECONFIGURE flag if negotiate fails + When negotiation fails, mark the pad as needing a reconfigure again so + that it gets picked up again next time. + Signed-off-by: Niv Sardi + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=691986 + +2013-01-19 12:51:56 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * tests/check/gst/gstpad.c: + * win32/common/libgstreamer.def: + pad: add gst_pad_get_stream_id() utility function + API: gst_pad_get_stream_id() + +2013-01-18 16:05:09 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + tools: minor addition to gst-launch-1.0 man page + https://bugzilla.gnome.org/show_bug.cgi?id=692015 + +2013-01-18 16:01:11 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + tools: update gst-launch-1.0 man page for new debug levels + There are more debug levels these days, not only 0-5. + https://bugzilla.gnome.org/show_bug.cgi?id=692015 + +2013-01-17 00:38:14 -0600 Daniel Díaz + + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_arm.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_arm.h: + tests: fix ABI check struct sizes for ARM + and re-enable ABI check for ARM. + https://bugzilla.gnome.org/show_bug.cgi?id=691828 + +2013-01-16 17:24:42 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + docs: add a note to the gst_adapter_take_buffer() docs about buffer flags + https://bugzilla.gnome.org/show_bug.cgi?id=682110 + +2013-01-16 11:29:47 +0000 Tim-Philipp Müller + + * tests/check/gst/gstabi.c: + * tests/check/libs/libsabi.c: + tests: disable ABI checks for architectures where the struct sizes are not up-to-date + https://bugzilla.gnome.org/show_bug.cgi?id=691828 + +2013-01-15 15:03:43 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 2a068ce to a942293 + +2013-01-15 13:47:32 +0000 Tim-Philipp Müller + + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + * tests/check/Makefile.am: + Use GST_*_1_0 environment variables everywhere + The _1_0 suffixed environment variables override the + non-suffixed ones, so if we're in an environment that + sets the _1_0 suffixed ones, such as jhbuild, we need + to set those to make sure ours actually always get + used. + +2013-01-15 13:47:13 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translated string + +2013-01-15 09:42:20 +0000 Tim-Philipp Müller + + * gst/gstpipeline.c: + pipeline: add allow-none annotation for gst_pipeline_new()'s name property + +2013-01-14 20:02:42 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + docs: minor GstBaseParse docs fixes + Expose docs for gst_base_parse_finish_frame(). + +2013-01-14 17:01:22 +0100 Wim Taymans + + * libs/gst/base/gsttypefindhelper.c: + typefind: handle map failure + +2013-01-14 17:00:46 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle map failure + +2013-01-14 17:00:23 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: handle map failure + +2013-01-13 14:45:31 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: add vfuncs to intercept queries + Useful for video parses that want to attach matter or + find out if downstream supports certain metas. + API: GstBaseParseClass::src_query() + API: GstBaseParseClass::sink_query() + https://bugzilla.gnome.org/show_bug.cgi?id=691475 + +2013-01-12 20:54:26 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix up name of default event vfuncs + +2013-01-10 11:34:14 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontrolbinding.h: + controlbinding: hide one unused typedef + This is not used internally. + +2013-01-10 11:33:42 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + * gst/gstcontrolsource.c: + docs: improve api docs for controlsource and -binding + +2013-01-05 16:30:04 +0000 Tim-Philipp Müller + + * tests/check/gst/gstghostpad.c: + tests: fix leak in ghostpad unit test + The created pad is never used and overwritten with + another newly-created pad a few lines below. + +2013-01-04 12:27:38 +0000 Tim-Philipp Müller + + * gst/gstsystemclock.h: + docs: minor systemsclock doc fix + +2013-01-03 10:16:18 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Initialize uninitialized variable + +2012-12-30 23:35:48 +0100 Thijs Vermeir + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: return gssize from gst_adapter_masked_scan_* functions + As the return value of this function is -1 when the match is not found + +2013-01-01 10:23:59 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Check if buffers are too late before calling prepare/prepare_list + https://bugzilla.gnome.org/show_bug.cgi?id=690936 + +2012-12-30 23:48:47 +0000 Tim-Philipp Müller + + * configure.ac: + configure: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS + AM_CONFIG_HEADER has been removed in the just-released automake 1.13: + https://lists.gnu.org/archive/html/automake/2012-12/msg00038.html + https://bugzilla.gnome.org/show_bug.cgi?id=690881 + +2012-12-22 16:50:49 +0000 Tim-Philipp Müller + + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + caps, structure, taglist: micro-optimisations + Avoid some unnecessary GValue copying by making use of + gst_structure_id_take_value() where possible. + +2012-12-22 16:29:03 +0000 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: some micro-optimisations + Avoid unnecessary value copying, and unnecessary init/unset + cycles which all go through the value table. There's a bunch + of places where we copy a value and then unset it in the next + line, instead of just taking over the source value. + +2012-12-22 16:53:47 +0100 Thijs Vermeir + + * scripts/create-uninstalled-setup.sh: + scripts: fix location of repository with ssh + +2012-12-21 16:36:37 +0100 Wim Taymans + + * gst/gstbin.c: + * gst/gstbin.h: + bin: add flag to disable resync state change + Add a GST_BIN_FLAG_NO_RESYNC that disables a resync when an element is added, + removed or linked in the bin. This is interesting for complex bins that + dynamically add elements to themselves and want to manage the state of those + elements without interference from resyncs. + See https://bugzilla.gnome.org/show_bug.cgi?id=690420 + +2012-12-21 10:09:30 +0100 Wim Taymans + + * docs/design/part-synchronisation.txt: + docs: update synchronization document a little + +2012-12-20 16:40:04 +0100 Wim Taymans + + * gst/gstsystemclock.h: + systemclock: add OTHER clock type + Add an OTHER clock type so that subclasses are able to mark themselves as + using some other clock source than the realtime or monotonic clock. + +2012-12-20 13:31:02 +0100 Branko Subasic + + * plugins/elements/gstmultiqueue.c: + multiqueue: correct overrun handling + The control of wheteher a SingleQueue is full is not correct. + Rewrote single_queue_overrun_cb() so it checks the correct variables + when checking if the queue has reached the hard limits, and to + increase the max buffer limit once for each call. + https://bugzilla.gnome.org/show_bug.cgi?id=690557 + +2012-12-20 11:59:54 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: implement buffering query for all modes + Also implement the buffering query for STREAM mode. + +2012-12-20 11:30:25 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: refactor buffering percent and stats + Make methods to get the current buffering percent and the stats. We will use + this in the query later. + +2012-12-13 13:47:29 +0100 Arnaud Vrac + + * libs/gst/base/gstbaseparse.c: + baseparse: fix invalid output timestamps in some cases + +2012-12-14 15:22:27 +0100 Wim Taymans + + * docs/design/part-element-sink.txt: + * docs/design/part-events.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstoutputselector.c: + NEWSEGMENT -> SEGMENT + +2012-12-14 14:03:43 +0000 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.prerequisites: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/random/porting-to-1.0.txt: + docs: update plugin docs + Update args/signals etc. + +2012-12-14 11:09:30 +0100 Wim Taymans + + * gst/gstsample.c: + * gst/gststructure.c: + add debug category + Adding a debug category is nicer than logging to the default category + +2012-12-14 11:08:57 +0100 Wim Taymans + + * gst/gstelement.c: + element: improve debug + +2012-12-13 14:48:35 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: call _stop when start failed + When we failed to complete the start, call stop again. This makes sure that all + successfull calls to _start are paired with a _stop. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=687845 + +2012-12-12 16:44:14 +0000 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/base/base.h: + * libs/gst/check/Makefile.am: + * libs/gst/check/check.h: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/controller.h: + * libs/gst/net/Makefile.am: + * libs/gst/net/net.h: + libs: Use foo/foo.h as single-include header consistently everywhere + https://bugzilla.gnome.org/show_bug.cgi?id=688785 + +2012-12-11 16:46:18 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: pass DTS and PTS to handle_buffer + This makes it handle the timestamps correctly and avoids using a wrong timestamp + for the output. + +2012-12-11 16:46:01 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: improve debug + Add pts and dts in debug log + +2012-11-03 16:59:39 +0000 Andrzej Bieniek + + * tools/gst-launch.c: + gst-launch: report execution time in GST_TIME_FORMAT + https://bugzilla.gnome.org/show_bug.cgi?id=687523 + +2012-12-10 11:55:42 +0100 Wim Taymans + + * gst/gstplugin.c: + plugin: protect against NULL filename in debug + See https://bugzilla.gnome.org/show_bug.cgi?id=689948 + +2012-12-06 09:48:08 +0100 Wim Taymans + + * gst/gstbufferpool.h: + bufferpool: clarify docs + +2012-12-05 14:56:48 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: fix docs + +2012-12-05 14:24:14 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: fix 0.10 docs to make more sense in 1.0 + +2012-12-05 14:03:27 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: fix docs for 1.0 + Add parent to chain function signature and use it. + +2012-11-30 10:41:51 +0100 Wim Taymans + + * gst/gstmessage.c: + message: add reset-time type string + +2012-11-30 10:41:36 +0100 Wim Taymans + + * gst/gstbin.c: + bin: remove some casts + +2012-11-28 18:08:52 +0000 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: add link to python porting doc and app dev manual to porting-to-1.0.txt + +2012-11-28 17:36:55 +0100 Edward Hervey + + * configure.ac: + configure.ac: Update libtool versioning + In order for 1.x and 1.(x+1) versions to not invade on each other + we need to have different lib versions. + So we need a consistent and predictable scheme: + library version number = MINOR * 100 + MICRO + Ex: + 1.0.0 => 0 (duh) + 1.0.3 => 3 + 1.1.0 => 100 + 1.1.1 => 101 + 1.2.0 => 120 + 1.10.5 => 1005 + .... + +2012-11-26 18:16:52 -0500 Luis de Bethencourt + + * scripts/gst-uninstalled: + add gst-editing-services to PKG_CONFIG_PATH + +2012-11-26 00:51:38 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: clean up sections file for pad probe defines that moved into enum + +2012-11-26 00:20:26 +0000 Tim-Philipp Müller + + * common: + * gst/Makefile.am: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + gst: don't require gthread-2.0 + We don't need to link to gthread-2.0 any longer, since all + the normal thread-related stuff is in GLib proper, and we + don't use g_thread_init() any more. + https://bugzilla.gnome.org/show_bug.cgi?id=689043 + +2012-11-25 23:42:57 +0000 Tim-Philipp Müller + + * configure.ac: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + gstreamer-1.0.pc: move gmodule-no-export-2.0 dependency to Requires.private + Users of GStreamer are not generally expected to use the GModule API + directly. so don't force them all to link against it. + While we're at it, no need to define this via configure.ac really, just + put the dependencies directly into the .pc.in file. + +2012-11-25 23:26:47 +0000 Tim-Philipp Müller + + * docs/manual/appendix-integration.xml: + * docs/manual/basics-init.xml: + * gst/gst.c: + docs: remove all mention of g_thread_init() + It's been deprecated since GLib 2.32 and isn't needed any + longer. + +2012-11-25 18:11:38 +0000 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.c: + dataqueue: reduce debug log spam a bit + Log locking/unlocking with TRACE debug level. + +2012-11-23 21:09:45 +0100 Alessandro Decina + + * gst/gstevent.c: + event: fix annotation for gst_event_parse_stream_start + +2012-11-23 13:36:09 +0000 Tim-Philipp Müller + + * gst/gstpad.h: + pad: document more pad probe values + +2012-11-23 13:34:24 +0000 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.h: + testclock: remove unnecessary include + +2012-11-23 13:32:07 +0000 Tim-Philipp Müller + + * tests/check/gst/gstclock.c: + tests: fix clock unit test build failure after header changes + https://bugzilla.gnome.org/show_bug.cgi?id=688785 + +2012-11-23 12:47:25 +0000 Tim-Philipp Müller + + * gst/gstpad.h: + pad: don't use parenthesis for ORed pad probe flag enums + glib-mkenum doesn't like them for some reason. + https://bugzilla.gnome.org/show_bug.cgi?id=688804 + +2012-11-23 10:58:25 +0100 Olivier Crête + + * gst/gstpad.h: + pad: Put all of the probe types in the enum so they work with bindings + https://bugzilla.gnome.org/show_bug.cgi?id=688804 + +2012-11-20 23:13:33 -0800 Evan Nemerson + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbase.h: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstcontroller.h: + * libs/gst/net/gstnet.h: + libs: Add missing single include headers and use them in GIRs + +2012-11-20 16:34:28 +0100 Wim Taymans + + * tests/check/libs/gsttestclock.c: + tests: don't use deprecated thread API + +2012-11-20 16:19:52 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add some debug + +2012-11-20 16:19:16 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: reset START_TIME when needed + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=685870 + +2012-11-20 15:37:11 +0100 Sebastian Dröge + + * gst/gstvalue.h: + value: Make G-I happy by hiding gst_g_thread_get_type() + +2012-11-20 15:07:37 +0100 Christian Fredrik Kalager Schaller + + * gstreamer.spec.in: + Remove xfig from spec file + +2012-11-20 15:06:14 +0100 Sebastian Dröge + + * gst/gstvalue.c: + value: Use the GLib GType for GThread if compiling against GLib 2.35.3 or newer + +2012-11-20 12:56:12 +0100 Sebastian Dröge + + * gst/gst.c: + gst: Don't set the locale in gst_init() + The function init_pre() in gstreamer/gst/gst.c calls setlocale(LC_ALL, ""), + which sets the locale to the values specified in the environment. This is + wrong for two reasons: + 1. It is absolutely not the task of a library to decide on the correct locale + for a program. Some programs change the locale for various (good or bad) + reasons, and libraries should respect that. Programs where GStreamer's + overwriting of the locale causes bugs include Emacs [1, 2], Sublime Text [3], + and Lua [4]. + [1] http://debbugs.gnu.org/cgi/bugreport.cgi?bug=12392 + [2] http://bugzilla.novell.com/show_bug.cgi?id=779426 + [3] http://www.sublimetext.com/forum/viewtopic.php?f=3&t=8543 + [4] https://github.com/pavouk/lgi/issues/19 + Note that setting the locale can cause problems for programs that are not even + linked against GStreamer. In the case of Emacs, for example, GStreamer seems + to be initialized through GTK via libcanberra. + 2. Setting the locale is not thread-safe, and therefore should not be done in a + library. + https://bugzilla.gnome.org/show_bug.cgi?id=685650 + +2012-11-16 19:41:48 +0100 Arnaud Vrac + + * libs/gst/base/gstbaseparse.c: + baseparse: forward stream-start event in push mode + +2012-11-19 13:38:30 +0100 Christian Fredrik Kalager Schaller + + * docs/README: + * docs/manual/state-diagram.fig: + * docs/random/wtay/player.fig: + Remove two last .fig files from build, they are now replaced with .svg files. That said I don't think either .fig file was still being used anywhere. With this change and the one in common GStreamer no longer depends on xfig. + +2012-11-19 13:16:48 +0100 Christian Fredrik Kalager Schaller + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gstreamer + +2012-11-19 11:23:32 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From b497c4f to a72faea + +2012-11-19 11:45:07 +0100 Christian Fredrik Kalager Schaller + + * docs/manual/state-diagram.svg: + * docs/random/wtay/player.svg: + Add SVG versions of .fig file + +2012-11-17 10:27:11 +0000 Tim-Philipp Müller + + * tests/examples/manual/Makefile.am: + examples: don't compile testrtpool example if pthreads are not available like on win32 + Based on patch by: italarab@gmail.com + https://bugzilla.gnome.org/show_bug.cgi?id=688511 + +2012-11-13 21:13:00 +0100 Arnaud Vrac + + * plugins/elements/gstinputselector.c: + inputselector: fix clock leak in wait_running_time + https://bugzilla.gnome.org/show_bug.cgi?id=688477 + +2012-11-17 00:13:14 +0000 Tim-Philipp Müller + + * gst/gstcompat.h: + gstcompat.h: move more deprecated API into the deprecated section + https://bugzilla.gnome.org/show_bug.cgi?id=675598 + +2012-11-14 12:20:54 +0100 Philippe Normand + + * gst/gsttask.c: + task: documentation update + GStaticRecMutex usage has been replaced by GRecMutex, reflect this + change in the documentation. + +2012-11-14 10:55:15 +0000 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + testclock: port to new GLib threading API + +2012-11-13 23:11:34 +0000 Tim-Philipp Müller + + * gst/gstcompat.h: + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + tests: gst_adapter_prev_timestamp -> gst_adapter_prev_pts + https://bugzilla.gnome.org/show_bug.cgi?id=675598 + +2012-11-13 22:42:05 +0000 Tim-Philipp Müller + + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/libs/.gitignore: + testclock: minor cleanups, add since markers for gtk-doc + https://bugzilla.gnome.org/show_bug.cgi?id=683012 + +2012-08-30 01:58:41 +0200 Sebastian Rasmussen + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/libs/gsttestclock.c: + check: allow GstTestClock to handle clock notifications + API: gst_test_clock_peek_id_count() + API: gst_test_clock_has_id() + API: gst_test_clock_peek_next_pending_id() + API: gst_test_clock_wait_for_next_pending_id() + API: gst_test_clock_wait_for_pending_id_count() + API: gst_test_clock_process_next_clock_id() + API: gst_test_clock_get_next_entry_time() + https://bugzilla.gnome.org/show_bug.cgi?id=683012 + +2012-11-13 21:29:01 +0000 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + check: add dependency on gstcheck header files for exports.sym + So exports.sym gets updated correctly, and our new symbols get + exported correctly, which makes g-ir-scanner much happier in + terms of linking. + https://bugzilla.gnome.org/show_bug.cgi?id=683012 + +2012-08-29 16:11:10 +0200 Sebastian Rasmussen + + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * libs/gst/check/Makefile.am: + * libs/gst/check/gsttestclock.c: + * libs/gst/check/gsttestclock.h: + * tests/check/Makefile.am: + * tests/check/libs/gsttestclock.c: + check: add GstTestClock as a deterministic clock for testing + API: GstTestClock + API: gst_test_clock_new() + API: gst_test_clock_new_with_start_time() + API: gst_test_clock_set_time() + API: gst_test_clock_advance_time() + https://bugzilla.gnome.org/show_bug.cgi?id=683012 + +2012-11-09 21:10:42 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasesrc.c: + basesrc: fix debug message + +2012-11-08 20:22:19 +0000 Tim-Philipp Müller + + * gst/gststructure.h: + structure: re-indent header file + Tabs to spaces. + +2012-11-12 11:40:59 +0100 Sebastian Dröge + + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + value: API: Add boxed type for GThread + +2012-11-12 10:30:08 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Fix indention for printing typefinder features + +2012-11-12 01:40:42 +0100 Sebastian Rasmussen + + * gst/gstinfo.c: + info: fix compiler warning when debugging disabled + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=688130 + +2012-11-10 09:50:49 +0100 Alessandro Decina + + * plugins/elements/gstqueue.c: + queue: remove unused label. Fixes compiler warning. + +2012-10-29 12:08:31 +0000 Alessandro Decina + + * plugins/elements/gstqueue.c: + * tests/check/elements/queue.c: + queue: don't fail in _sink_event for sticky events + Implement the same behaviour as gst_pad_push_event when pushing sticky events + fails, that is don't fail immediately but fail when data flow resumes and upstream + can aggregate properly. + This fixes segment seeks with decodebin and unlinked audio or video branches. + Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=687899 + +2012-11-09 16:50:50 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: add simple rate control + Add a max-bitrate property that will slightly delay rendering of buffers if it + would exceed the maximum defined bitrate. This can be used to do + rate control on network sinks, for example. + API: GstBaseSink::max-bitrate + API: gst_base_sink_set_max_bitrate() + API: gst_base_sink_get_max_bitrate() + +2012-11-08 15:33:01 +1100 Matthew Waters + + * gst/gstbufferpool.c: + bufferpool: lock before unlock in _get_config + Fixes deadlock on Windows + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=687896 + +2012-11-07 18:15:11 +0000 Tim-Philipp Müller + + * configure.ac: + configure: update courtesy of autoupdate + +2012-11-07 17:59:49 +0000 Tim-Philipp Müller + + * common: + common: update for AG_GST_PLUGIN_DOCS python checks + +2012-11-06 18:29:28 +0100 Olivier Crête + + * docs/gst/running.xml: + * tools/gst-launch.1.in: + Document GST_DEBUG_FILE + +2012-11-06 17:03:47 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: fix alignment of rank, etc. + +2012-11-06 16:58:04 +0000 Tim-Philipp Müller + + * plugins/elements/gstelements.c: + elements: fix leading space in plugin description string + +2012-11-03 20:38:00 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + * plugins/elements/gstdataurisrc.h: + * tests/check/elements/dataurisrc.c: + Fix FSF address + https://bugzilla.gnome.org/show_bug.cgi?id=687520 + +2012-11-03 20:44:48 +0000 Tim-Philipp Müller + + * COPYING: + * docs/random/LICENSE: + * gst/gettext.h: + * gst/glib-compat-private.h: + * gst/glib-compat.c: + * gst/glib-compat.h: + * gst/gst-i18n-app.h: + * gst/gst-i18n-lib.h: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstallocator.c: + * gst/gstallocator.h: + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstbus.c: + * gst/gstbus.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstcompat.h: + * gst/gstconfig.h.in: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstelementmetadata.h: + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstiterator.h: + * gst/gstmacros.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstmeta.c: + * gst/gstmeta.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + * gst/gstparse.c: + * gst/gstparse.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstpluginloader.c: + * gst/gstpluginloader.h: + * gst/gstpoll.c: + * gst/gstpoll.h: + * gst/gstpreset.c: + * gst/gstpreset.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + * gst/gstregistrybinary.h: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * gst/gstsample.c: + * gst/gstsample.h: + * gst/gstsegment.c: + * gst/gstsegment.h: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * gst/gsttask.c: + * gst/gsttask.h: + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + * gst/gsttoc.c: + * gst/gsttoc.h: + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + * gst/gsttrace.c: + * gst/gsttrace.h: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.c: + * gst/gsttypefindfactory.h: + * gst/gsturi.c: + * gst/gsturi.h: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + * gst/gstversion.h.in: + * gst/math-compat.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader-docs.h: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter-docs.h: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstindex.c: + * libs/gst/base/gstindex.h: + * libs/gst/base/gstmemindex.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstconsistencychecker.h: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_error.h: + * libs/gst/check/libcheck/check_impl.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_list.h: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_log.h: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_msg.h: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_pack.h: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_print.h: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/check_str.h: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstargbcontrolbinding.h: + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.h: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.h: + * libs/gst/helpers/gst-plugin-scanner.c: + * libs/gst/net/gstnet.h: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnettimeprovider.h: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.h: + * plugins/elements/gstelements.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfilesrc.h: + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstoutputselector.h: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + * scripts/create-uninstalled-setup.sh: + * scripts/five-bugs-a-day.pl: + * tests/benchmarks/caps.c: + * tests/benchmarks/capsnego.c: + * tests/benchmarks/complexity.c: + * tests/benchmarks/controller.c: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + * tests/benchmarks/init.c: + * tests/benchmarks/mass-elements.c: + * tests/check/elements/capsfilter.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/elements/queue2.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/elements/valve.c: + * tests/check/generic/sinks.c: + * tests/check/generic/states.c: + * tests/check/gst/gst.c: + * tests/check/gst/gstabi.c: + * tests/check/gst/gstatomicqueue.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstbus.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstchildproxy.c: + * tests/check/gst/gstclock.c: + * tests/check/gst/gstcontroller.c: + * tests/check/gst/gstdatetime.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstelementfactory.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstindex.c: + * tests/check/gst/gstinfo.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstmemory.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gstmeta.c: + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstparamspecs.c: + * tests/check/gst/gstpipeline.c: + * tests/check/gst/gstplugin.c: + * tests/check/gst/gstpoll.c: + * tests/check/gst/gstpreset.c: + * tests/check/gst/gstquery.c: + * tests/check/gst/gstregistry.c: + * tests/check/gst/gstsegment.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/gst/gsttask.c: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + * tests/check/gst/gsturi.c: + * tests/check/gst/gstutils.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/adapter.c: + * tests/check/libs/basesink.c: + * tests/check/libs/basesrc.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/bytewriter.c: + * tests/check/libs/collectpads.c: + * tests/check/libs/controller.c: + * tests/check/libs/gstlibscpp.cc: + * tests/check/libs/gstnetclientclock.c: + * tests/check/libs/gstnettimeprovider.c: + * tests/check/libs/libsabi.c: + * tests/check/libs/queuearray.c: + * tests/check/libs/transform1.c: + * tests/check/libs/typefindhelper.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/parse-disabled.c: + * tests/check/pipelines/parse-launch.c: + * tests/check/pipelines/queue-error.c: + * tests/check/pipelines/seek.c: + * tests/check/pipelines/simple-launch-lines.c: + * tests/check/pipelines/stress.c: + * tests/check/tools/gstinspect.c: + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-memory.h: + * tests/examples/memory/my-vidmem.c: + * tests/examples/memory/my-vidmem.h: + * tests/examples/metadata/read-metadata.c: + * tests/examples/streams/testrtpool.c: + * tests/examples/streams/testrtpool.h: + * tests/examples/typefind/typefind.c: + * tests/misc/network-clock-utils.scm: + * tests/misc/network-clock.scm: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/tools.h: + * win32/common/gstconfig.h: + * win32/common/gstversion.h: + Fix FSF address + https://bugzilla.gnome.org/show_bug.cgi?id=687520 + +2012-10-31 19:33:30 +0000 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.args: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: add "flush-on-eos" property + In flush-on-eos=true mode any data remaining in the queue is + discarded when an EOS event is received, and the EOS passed + downstream as soon as possible (instead of waiting for all + buffers in the queue to get processed by downstream first). + May or may not be useful in capture/encoding scenarios. + +2012-10-31 18:32:38 +0000 Tim-Philipp Müller + + * common: + common: update for python detection + Fixes docs build. + +2012-10-31 17:37:37 +0000 Tim-Philipp Müller + + * common: + * configure.ac: + configure: let AG_GST_PLUGIN_DOCS check for python + And update common for move from AS_PATH_PYTHON to AM_PATH_PYTHON, + which as a side-effect should pick up newer python versions as well. + https://bugzilla.gnome.org/show_bug.cgi?id=563903 + +2012-10-30 10:04:44 +1100 Jan Schmidt + + * libs/gst/base/gstcollectpads.c: + collectpads: Clarify docs about the buffer handler callback. + Clarify that the callback owns a ref on a passed buffer. + +2012-10-30 10:04:14 +1100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Add EOS status to debug output about filled/unfilled + +2012-10-22 00:31:09 +1100 Jan Schmidt + + * tests/check/libs/collectpads.c: + check: Add a simple test for the CollectPads buffer collect callback + +2012-10-29 13:26:10 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + g-i: fix "can't resolve libraries to shared libraries: gstcheck-1.0" build error + Revert --library=libfoo-1.0.la -> --library=foo-1.0 change made + in previous commit. Turns out that was wrong, despite what the + man page says. + https://bugzilla.gnome.org/show_bug.cgi?id=603710 + +2012-10-29 11:30:30 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + pad: downgrade 'creating random stream-id' debug log message + No need for it to be a warning. + +2012-06-13 13:02:48 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: prevent excessively high memory usage with long streams + Large streams would index one frame every second, which can get quite + large with multi-hour streams, so add an additional byte-based + minimum distance as well, which will kick in for long streams + and make sure we never have more than a couple of thousand index + entries. + https://bugzilla.gnome.org/show_bug.cgi?id=666053 + +2012-10-28 17:17:49 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + libs: g-i: avoid multiple libraries in the shared-library tag + Using multiple libraries causes problems for the C# bindings and + will for similiar languages such as Java when there are bindings + for them. + Also change --library=libgstfoo-X.la to --library=gstfoo-X as + the man page suggests it should be done. + https://bugzilla.gnome.org/show_bug.cgi?id=679315 + +2012-10-28 15:53:19 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * win32/common/libgstreamer.def: + pluginfeature: add gst_plugin_feature_get_plugin_name() + API: gst_plugin_feature_get_plugin_name() + https://bugzilla.gnome.org/show_bug.cgi?id=571832 + +2012-10-27 14:40:14 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: allow setting of GST_DEBUG levels by name + e.g. GST_DEBUG=*:INFO,*src:LOG + +2012-06-29 12:38:52 -0400 Thibault Saunier + + * gst/gst.c: + gst: make us of the new gst_debug_set_threshold_from_string function + https://bugzilla.gnome.org/show_bug.cgi?id=679152 + +2012-06-29 12:05:36 -0400 Thibault Saunier + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + * win32/common/libgstreamer.def: + info: add a function to set debug threshold from a GST_DEBUG-style string + Use the same format as with the GST_DEBUG environment variable. + API: gst_debug_set_threshold_from_string() + https://bugzilla.gnome.org/show_bug.cgi?id=679152 + +2012-10-25 15:27:23 +0200 Sebastian Dröge + + * tests/check/libs/queuearray.c: + queuearray: Fix unit test + +2012-10-22 10:13:20 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * plugins/elements/Makefile.am: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueuearray.h: + * win32/common/libgstbase.def: + dataqueue/queuearray: Make public API again + These are actually used outside of coreelements nowadays. + Also hide lots of internals and add padding and documentation. + +2012-10-25 12:10:27 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to feature development + +=== release 1.0.2 === + +2012-10-25 00:04:49 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 1.0.2 + +2012-10-24 16:13:34 +0400 Руслан Ижбулатов + + * tests/examples/manual/Makefile.am: + examples: link testrtpool to pthreads + Fixes #686787 + +2012-10-24 11:46:01 +0200 Sebastian Dröge + + * gst/gstevent.c: + event: Allow GST_CLOCK_TIME_NONE as duration for GAP events + +2012-10-24 11:16:12 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: use new GCond for async state change + Use a new GCond, protected with the object lock, to signal completion + of the async state change. We can't reuse the live lock because that + one can be locked when the create function blocks. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=686723 + +2012-10-22 20:25:43 +0200 Miguel Angel Cabrera Moya + + * gst/gstallocator.c: + allocator: fix memory leak in _fallback_mem_copy + https://bugzilla.gnome.org/show_bug.cgi?id=686658 + +2012-10-22 20:33:06 +0200 Miguel Angel Cabrera Moya + + * gst/gstpreset.c: + preset: remove variable not read + https://bugzilla.gnome.org/show_bug.cgi?id=686659 + +2012-10-22 15:04:26 +0200 Sebastian Dröge + + * configure.ac: + * libs/gst/check/libcheck/Makefile.am: + * m4/ax_pthread.m4: + * tests/examples/streams/Makefile.am: + configure: Properly check for pthread + The old check failed on Android for example. + +2012-10-22 10:25:40 +0200 Sebastian Dröge + + * gst/gstinfo.c: + info: Don't use GST_DEBUG() in gst_debug_add_log_function() and related functions unconditionally + If GStreamer was not initialized yet this will cause g_warnings(). + +2012-10-20 19:44:43 +0100 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.h: + collectpads: fix g-i annotation for GstCollectPadsBufferFunction + We pass ownership of the buffer to the function. + +2012-10-20 12:54:06 +0100 Tim-Philipp Müller + + * docs/libs/Makefile.am: + * gst/gst.c: + g_type_init() is no longer required and deprecated in glib >= 2.35.0 + https://bugzilla.gnome.org/show_bug.cgi?id=686456 + +2012-10-19 13:36:33 -0700 Michael Smith + + * gst/gstsample.c: + GstSample: fix typo in G-I annotations, allows creating GstSamples from bindings. + +2012-10-18 15:31:17 +0200 Sebastian Dröge + + * gst/gstpoll.c: + poll: Fix compiler warning about constness + passing argument 1 of 'g_mutex_lock' discards 'const' qualifier from pointer target type + passing argument 1 of 'g_mutex_unlock' discards 'const' qualifier from pointer target type + +2012-10-17 17:34:26 +0100 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + Use gst_element_class_set_static_metadata() + where possible. Avoids some string copies. Also re-indent + some stuff. Also some indent fixes here and there. + +2012-10-17 16:49:19 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstpipeline.c: + bin, pipeline: use gst_element_class_set_static_metadata() + So the strings aren't copied. + +2012-10-16 12:31:50 +0200 Sebastian Dröge + + * gst/gstelement.c: + * gst/gstelement.h: + element: API: Add GstElement::post_message() vfunc + Conflicts: + gst/gstelement.h + +2012-10-16 11:54:54 +0200 Wim Taymans + + * docs/pwg/advanced-events.xml: + pwg: link to caps and qos chapters + +2012-10-16 11:20:59 +0200 Wim Taymans + + * docs/pwg/building-boiler.xml: + * docs/pwg/building-queryfn.xml: + * docs/pwg/pwg.xml: + pwg: add section about query function + +2012-10-16 11:12:38 +0200 Wim Taymans + + * docs/pwg/building-eventfn.xml: + pwg: fix event function + +2012-10-15 19:56:36 +0100 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + collectpads: minor docs fixes + +2012-10-15 19:55:42 +0100 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.c: + collectpads: fix buffer leak in clip_time + +2012-10-15 18:44:52 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads.c: + collectpads: call clip function with user data + +2012-10-15 14:06:45 +0200 Wim Taymans + + * docs/pwg/pwg.xml: + pwg: reorder some chapters + Reorder some chapter so that they match the steps done in the + element. + +2012-10-15 13:59:50 +0200 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: small tweaks to negotiation + +2012-10-15 13:44:51 +0200 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: improve negotiation documentation some more + +2012-10-15 12:10:46 +0200 Wim Taymans + + * docs/design/part-negotiation.txt: + * docs/pwg/advanced-negotiation.xml: + pwg: update negotiation part + +2012-10-15 12:10:11 +0200 Wim Taymans + + * docs/design/part-synchronisation.txt: + docs: update synchronization docs + +2012-10-12 16:58:03 +0200 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: work on rewriting caps negotiation docs + +2012-10-12 16:09:26 +0200 Wim Taymans + + * docs/design/part-negotiation.txt: + design: rename passthrough negotiation + Rename passthrough negotiation to transform negotiation to avoid + confusion with passthrough operation. + +2012-10-12 13:15:48 +0200 Wim Taymans + + * docs/manual/basics-elements.xml: + * docs/manual/basics-pads.xml: + manual: no more new-decoded-pad + +2012-10-12 13:13:32 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * docs/manual/appendix-compiling.xml: + * docs/manual/manual.xml: + manual: move embedding elements to separate chapter + +2012-10-12 13:01:28 +0200 Wim Taymans + + * docs/pwg/advanced-qos.xml: + pwg: small example for throttle + +2012-10-12 12:55:57 +0200 Wim Taymans + + * docs/pwg/advanced-qos.xml: + * docs/pwg/pwg.xml: + pwg: add info about QoS + +2012-10-12 12:55:25 +0200 Wim Taymans + + * docs/pwg/intro-basics.xml: + pwg: adds some more links + +2012-10-12 12:55:03 +0200 Wim Taymans + + * docs/design/part-qos.txt: + qos: messages are posted, not dropped + +2012-10-12 10:35:43 +0200 Wim Taymans + + * docs/manual/communication.png: + * docs/manual/diagrams-general.svg: + * docs/manual/diagrams-pipelines.svg: + * docs/manual/gstreamer-overview.png: + * docs/manual/mime-world.png: + * docs/manual/thread-buffering.png: + manual: update graphics + +2012-10-11 17:10:17 +0200 Wim Taymans + + * docs/manual/advanced-buffering.xml: + * tests/examples/manual/.gitignore: + * tests/examples/manual/Makefile.am: + manual: add example of no-rebuffer buffering strategy + +2012-10-11 17:10:04 +0200 Wim Taymans + + * docs/manual/basics-bus.xml: + * docs/manual/intro-gstreamer.xml: + manual: small tweaks + +2012-10-11 17:09:29 +0200 Wim Taymans + + * gst/gstquery.c: + query: buffering time left is in milliseconds + +2012-10-11 17:07:39 +0200 Wim Taymans + + * docs/manual/basics-bins.xml: + manual: add some text about bin state change order + +2012-10-10 16:43:58 +0200 Wim Taymans + + * docs/manual/highlevel-playback.xml: + * tests/examples/manual/Makefile.am: + manual: talk about playsink + Talk about playsink and give an example of its usage. + +2012-10-10 14:11:43 +0200 Wim Taymans + + * tests/check/elements/dataurisrc.c: + replace some playbin2 -> playbin + +2012-10-10 13:08:31 +0200 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/highlevel-playback.xml: + * docs/manual/manual.xml: + * tests/examples/manual/Makefile.am: + manual: add something about uridecodebin + +2012-10-10 11:35:01 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads.c: + collectpads: ensure all timestamps are in same time domain + ... by not only processing incoming buffers through a clip function, + but also other timestamps such as those coming from GAP event. + +2012-10-10 10:36:32 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.h: + docs: adjust some parameter mismatches + +2012-10-10 11:34:27 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Downgrade GST_WARNING to GST_INFO + It's usually not a problem if a query fails if there's no peer, + especially as it will happen during pad linking (caps query) + quite often and spams the logs. + +2012-10-09 17:06:04 +0200 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * tests/examples/manual/.gitignore: + * tests/examples/manual/Makefile.am: + manual: remove outdated autoplugging section + Remove autoplugging chapter and point to decodebin/playbin examples. + +2012-10-09 16:12:01 +0200 Wim Taymans + + * docs/manual/advanced-threads.xml: + * tests/examples/manual/.gitignore: + * tests/examples/manual/Makefile.am: + manual: Talk about threading + Rework the threading chapter. + Talk about stream-status and give some examples on how to change + the thread priorities. + +2012-10-09 15:57:29 +0200 Wim Taymans + + * docs/design/part-stream-status.txt: + design: improve stream-status document + +2012-10-09 15:31:19 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: retrieve the result from start_complete + gst_base_src_start_complete() can fail when the thread could not be + started, for example. Make sure it causes the state change to fail by + retrieving the result from _start_complete(). + +2012-10-09 15:31:04 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: improve debug + +2012-10-09 10:24:34 +0200 Wim Taymans + + * gst/gstpad.h: + pad: small docs fixes and remove a 0.11 fixme + +2012-10-08 16:42:11 +0200 Wim Taymans + + * docs/design/part-buffering.txt: + * docs/manual/advanced-buffering.xml: + * docs/manual/manual.xml: + manual: talk a bit about buffering + +2012-10-08 13:22:30 +0200 Wim Taymans + + * docs/manual/advanced-clocks.xml: + * docs/pwg/advanced-clock.xml: + docs: improve clock chapter + +2012-10-08 10:39:30 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * tests/examples/manual/Makefile.am: + manual: add example for effect switching + +2012-10-08 09:11:53 +0200 Wim Taymans + + * docs/design/part-preroll.txt: + * docs/design/part-sparsestreams.txt: + docs: small updates + +2012-10-07 16:48:25 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development (bug-fixing) + +=== release 1.0.1 === + +2012-10-07 13:10:33 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Release 1.0.1 + +2012-10-07 00:15:49 +0100 Tim-Philipp Müller + + * tests/check/gst/struct_i386.h: + * tests/check/libs/struct_i386.h: + tests: update struct_i386.h for ABI checks + Fixes make check on 32-bit x86. + +2012-10-06 17:26:21 +0100 Tim-Philipp Müller + + * tests/check/gst/struct_ppc32.h: + * tests/check/libs/struct_ppc32.h: + tests: update struct_ppc32.h for ABI checks + Fixes make check on 32-bit PowerPC. + +2012-10-06 14:55:35 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 6c0b52c to 6bb6951 + +2012-10-06 12:08:34 +0100 Tim-Philipp Müller + + * tests/examples/manual/.gitignore: + examples: .gitignore more binaries from the manual + +2012-10-05 16:04:52 +0200 Wim Taymans + + * docs/design/Makefile.am: + * docs/design/part-block.txt: + * docs/design/part-probes.txt: + docs: remove obsolete part-block document + Merge the part-block document into part-probes + +2012-10-05 09:42:59 +0200 Wim Taymans + + * gst/gstpad.c: + pad: resend dropped events + If we try to push sticky events but a probe dropped them, we don't mark + the event as received and mark the pad as PENDING_EVENTS. This ensures + that we resend the event the next time. For this we need to let the + custom flow return from the probe trickle up to + gst_pad_push_event_unchecked() so that we can differentiate between + OK and DROPPED probe returns. + +2012-10-05 07:14:17 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't store sticky events on flushing/EOS pads + Don't store sticky events on flushing or EOS pads. This was done + correctly for source pads but not for sink pads. + +2012-10-04 11:24:09 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstbase.def: + docs: add Since markers for new API and add it to docs and .def file + +2012-10-04 11:50:58 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * tests/examples/manual/Makefile.am: + manual: add dynamic capsfilter example + +2012-10-04 11:18:19 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: don't prefer passthrough + Basetransform should not try to negotiate in passthrough mode but + respect the order of what we return in the transform_caps method. + A typical case is that you specify some specific new caps in the + caps property but also allow the current caps to pass. + +2012-10-04 11:15:36 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetrans: add an option to prefer passthrough + Basetransform attempts to do passthrough mode regardless of the order of + the transform_caps method. Add a method to disable this. + This is needed for elements like capsfilter that want to transform caps + based on the order of the caps property. + +2012-10-04 10:01:19 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: improve some comments + +2012-10-03 17:17:02 +0200 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-dataaccess.xml: + manual: talk some more about dynamic pipelines + +2012-10-03 13:49:34 +0200 Wim Taymans + + * gst/gstmeta.c: + meta: don't put essential logic in g_return_val_* + +2012-10-03 13:45:22 +0200 Wim Taymans + + * docs/pwg/advanced-allocation.xml: + * libs/gst/net/gstnetaddressmeta.c: + * tests/check/gst/gstmeta.c: + meta: do metadata registration threadsafe + We need to use g_once to register the metadata implementations + only once. + See https://bugzilla.gnome.org/show_bug.cgi?id=685332 + +2012-10-03 13:35:20 +0200 Wim Taymans + + * gst/gstmeta.c: + meta: handle multiple implementation registration + First check that we can actually register the implementation before + making a GstMetaInfo. If we can't register we would otherwise end + up with an undefined type and an invalid GstMetaInfo. + It's possible that type registration fails because another metadata + with the same implementation name was already registered. + +2012-10-03 13:12:44 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + manual: use CDATA for code blocks + then we don't have to escape special token anymore. + +2012-10-03 13:09:00 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * tests/examples/manual/Makefile.am: + manual: add partial preroll example with probes + +2012-10-03 10:53:20 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + manual: add more stuff about probes + +2012-10-02 17:23:28 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + manual: start talking about dynamic pipeline changes + +2012-10-02 16:47:05 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + manual: move section around + +2012-10-02 16:44:28 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * tests/examples/manual/Makefile.am: + pwg: add appsink docs + +2012-10-02 16:15:19 +0200 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * tests/examples/manual/Makefile.am: + pwg: rewite data-access chapter + Rewrite the data-access chapter so that we talk about appsrc instead + of the fakesrc hacks. + +2012-10-02 13:22:35 +0200 Wim Taymans + + * docs/design/draft-klass.txt: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/advanced-metadata.xml: + * docs/manual/appendix-integration.xml: + * gst/gstpreset.c: + * po/README: + * tools/gst-plot-timeline.py: + docs: some 0.10 -> 1.0 changes + +2012-10-02 13:12:39 +0200 Wim Taymans + + * docs/pwg/advanced-allocation.xml: + pwg: add allocation query example + +2012-10-02 12:49:17 +0200 Wim Taymans + + * docs/pwg/advanced-allocation.xml: + pwg: add bufferpool docs + +2012-10-02 11:34:47 +0200 Wim Taymans + + * docs/manual/appendix-programs.xml: + * docs/manual/manual.xml: + * docs/pwg/advanced-allocation.xml: + pwg: flesh out allocation docs + Add more examples. + Add example for implementing new metadata. + Add programs to the docs (again?), it seems to contain useful info. + +2012-10-01 16:59:41 +0200 Wim Taymans + + * docs/pwg/titlepage.xml: + pwg: add new author + +2012-10-01 16:55:55 +0200 Wim Taymans + + * docs/pwg/advanced-allocation.xml: + pwg: add allocation docs + +2012-10-01 16:46:03 +0200 Wim Taymans + + * docs/design/part-buffer.txt: + * docs/design/part-bufferpool.txt: + * docs/design/part-meta.txt: + docs: update design docs + +2012-10-01 13:28:54 +0200 Wim Taymans + + * docs/design/part-bufferpool.txt: + * docs/design/part-memory.txt: + * docs/pwg/advanced-allocation.xml: + * docs/pwg/pwg.xml: + docs: more docs fixes + Fix allocator design doc + Add beginning of allocation chapter in the pwg + +2012-10-01 11:47:46 +0200 Wim Taymans + + * docs/pwg/appendix-checklist.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/other-manager.xml: + * docs/pwg/other-ntoone.xml: + pwg: final cleanups for 1.0 + +2012-10-01 11:24:52 +0200 Wim Taymans + + * docs/pwg/advanced-events.xml: + * docs/pwg/other-base.xml: + pwg: fix events and base classes + +2012-10-01 10:40:54 +0200 Wim Taymans + + * docs/pwg/advanced-tagging.xml: + pwg: fixup tag docs + +2012-10-01 09:48:48 +0200 Wim Taymans + + * docs/pwg/advanced-interfaces.xml: + pwg: patch up the section about interfaces + +2012-09-30 04:05:36 +1000 Jan Schmidt + + * libs/gst/base/gstbasesrc.c: + basesrc: Fix seamless segment function + The 3rd parameter of gst_base_src_new_seamless_segment in + 0.10 is the time associated with the start of the new segment, + not the position in the new segment. Fix the name of the parameter, + the docs, and the implementation to match the needs of the only + extant consumer: DVD playback. + +2012-09-29 14:35:58 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + * tests/check/gst/gstcaps.c: + value: avoid duplicates when intersecting lists + Fixes negotiation taking a ridiculous amount of + time (multiple 10s of seconds on a core2) when + there are duplicate entries in lists. + Could have a negative performance impact on other + scenarios because we now have to iterate the + dest list to avoid duplicates, but we don't + have a lot of lists any more these days, and + they tend to be small anyway. The negatives + are hopefully countered by the positive effects + of reducing the list length early on in the + process. And in any case, it's the right thing + to do. + Based on patch by Andre Moreira Magalhaes. + https://bugzilla.gnome.org/show_bug.cgi?id=684981 + +2012-09-29 00:27:03 +0100 Tim-Philipp Müller + + * docs/pwg/building-boiler.xml: + pwg: minor update + https://bugzilla.gnome.org/show_bug.cgi?id=621121 + +2012-09-28 23:53:53 +0200 Wim Taymans + + * docs/faq/dependencies.xml: + faq: add missing tag + +2012-09-28 15:17:27 -0400 Olivier Crête + + * gst/gstminiobject.c: + * tests/check/gst/gstmemory.c: + miniobject: Always reject WRITE locks on READONLY miniobjects + Verify that mapping a read-only memory as read doesnt make it writable + +2012-09-28 20:38:20 +0100 Tim-Philipp Müller + + * docs/faq/dependencies.xml: + * docs/random/autotools: + * docs/random/moving-plugins: + docs: purge all mention of liboil, update FAQ + https://bugzilla.gnome.org/show_bug.cgi?id=673285 + +2012-09-28 16:03:15 +0200 Wim Taymans + + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-dparams.xml: + * docs/pwg/advanced-interfaces.xml: + pwg: update for 1.0 + Rewrite clock part. + start on interfaces + +2012-09-28 13:25:49 +0200 Wim Taymans + + * docs/pwg/advanced-request.xml: + pwg: rework dynamic pads docs + +2012-09-28 13:25:30 +0200 Wim Taymans + + * docs/pwg/advanced-scheduling.xml: + pwg: rework scheduling docs + +2012-09-28 13:24:52 +0200 Wim Taymans + + * docs/pwg/building-props.xml: + * docs/pwg/other-base.xml: + pwg: remove some GST_BOILERPLATE + +2012-09-28 11:18:11 +0200 Wim Taymans + + * docs/design/part-activation.txt: + docs: update activation design docs + +2012-09-28 10:41:54 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: fix activate docs + +2012-09-28 10:04:51 +0200 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: fix more negotiation for 1.0 + +2012-09-27 16:59:04 +0200 Olivier Blin + + * gst/gstinfo.c: + info: do not register printf extension for %p + This happened when glib was not using system printf, and caused the + internal gstreamer printf extensions to be used for all %p printfs, + causing crashes. + https://bugzilla.gnome.org/show_bug.cgi?id=684970 + +2012-09-27 17:21:53 +0200 Wim Taymans + + * docs/pwg/advanced-negotiation.xml: + pwg: fix some negotiation to 1.0 + +2012-09-27 14:42:07 +0200 Wim Taymans + + * docs/pwg/building-props.xml: + * docs/pwg/building-state.xml: + * docs/pwg/building-testapp.xml: + pwg: more updates for 1.0 + +2012-09-27 13:57:46 +0200 Wim Taymans + + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-eventfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/pwg.xml: + pwg: more updates for 1.0 + +2012-09-27 11:53:36 +0200 Wim Taymans + + * docs/pwg/building-boiler.xml: + pwg: update boiler to 1.0 + +2012-09-27 11:06:06 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: also ref the internal pad for activate functions + Also take a ref to the internal pad in the activate functions + +2012-09-24 18:26:16 -0400 Olivier Crête + + * gst/gstghostpad.c: + proxypad: Hold a reference to the internal pad while pushing through it + https://bugzilla.gnome.org/show_bug.cgi?id=684809 + +2012-09-25 14:44:54 -0400 Olivier Crête + + * tests/check/gst/gstghostpad.c: + tests: Test the case where ghost pads are removed while streaming + https://bugzilla.gnome.org/show_bug.cgi?id=684809 + +2012-09-27 09:44:07 +0200 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_arm.h: + * tests/check/libs/struct_hppa.h: + * tests/check/libs/struct_i386.h: + * tests/check/libs/struct_ppc32.h: + * tests/check/libs/struct_ppc64.h: + * tests/check/libs/struct_sparc.h: + * tests/check/libs/struct_x86_64.h: + tests: enable library abi checks + +2012-09-26 23:32:35 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + docs: fix up basesrc/basesink docs formatting + +2012-09-26 17:08:30 +0200 Wim Taymans + + * tests/check/Makefile.am: + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + tests: add abi checks + Enable abi checks again. + Fix abi sizes for x86_64, copy the file to other archs. + +2012-09-26 16:26:48 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + update docs for 1.0 API + +2012-09-26 14:15:01 +0200 Mark Nauwelaerts + + * gst/gsturi.c: + uri: use proper 'transfer floating' annotation + https://bugzilla.gnome.org/show_bug.cgi?id=664099 + +2012-09-26 13:19:13 +0200 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefind: send STREAM-START event + Send a STREAM_START event when we are operating in pull mode. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=684424 + +2012-09-26 10:55:28 +0200 Mark Nauwelaerts + + * gst/gstsegment.h: + segment: mark GstSegmentFlags as flags rather than enum + ... which really makes a difference when trying to serialize + a flags value which is a combination of flags, which is hard + to do as an enum type. + +2012-09-26 10:54:06 +0200 Mark Nauwelaerts + + * plugins/elements/gstidentity.c: + identity: retimestamp both pts and dts when doing so + +2012-09-26 15:01:42 +1000 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Move some run of the mill debug statements to LOG level + +2012-09-26 14:23:52 +1000 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Output timestamps after a seek. + Reinitialise the DTS after a seek so as to continue + generating timestamps when baseparse is not downstream + of a demuxer. + Fixes: #684538 + +2012-09-25 17:06:45 +0200 Wim Taymans + + * docs/manual/appendix-programs.xml: + * docs/manual/basics-pads.xml: + * docs/pwg/advanced-types.xml: + * docs/pwg/building-boiler.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/other-ntoone.xml: + * tools/gst-launch.1.in: + * tools/gst-typefind.1.in: + docs: updates + MIME-type -> Media type + Fix some old gst-inspect output + +2012-09-25 16:53:08 +0200 Wim Taymans + + * docs/pwg/intro-basics.xml: + * docs/pwg/intro-preface.xml: + pwg: update for 1.0 API + +2012-09-25 15:11:33 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: add section for metadata + +2012-09-25 13:09:38 +0200 Sebastian Dröge + + * gst/gstelement.c: + * gst/gstelementfactory.c: + elementfactory: Fail if no valid element factory metadata is set + +2012-09-25 13:09:28 +0200 Sebastian Dröge + + * gst/gstplugin.c: + plugin: Fail if no valid plugin metadata is set + +2012-09-25 15:06:43 +0200 Mark Nauwelaerts + + * plugins/elements/gstidentity.c: + identity: also track and store segment info in single segment mode + +2012-09-25 14:40:20 +0200 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/advanced-interfaces.xml: + * docs/manual/advanced-threads.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/appendix-integration.xml: + * docs/manual/appendix-porting.xml: + * docs/manual/basics-bins.xml: + * docs/manual/basics-bus.xml: + * docs/manual/basics-data.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/highlevel-components.xml: + * docs/manual/intro-basics.xml: + * docs/manual/manual.xml: + * docs/random/porting-to-1.0.txt: + * tests/examples/manual/Makefile.am: + manual: fix up the manual + MIME-type -> media types + Fix up the manual in various places with the 1.0 way of doing things + such as probes, static elements, scheduling, ... + Add porting from 0.10 to 1.0 chapter. + Add probe example to build. + Remove some docs for remove components such as GstMixer and + GstPropertyProbe, XML... + +2012-09-24 16:50:50 +0200 Wim Taymans + + * docs/manual/intro-gstreamer.xml: + docs: gst-python is no more + gst-python is no more and gst-libav is one of the main modules that + we release. + +2012-09-24 16:31:34 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + docs: fix basesink docs + +2012-09-24 16:25:36 +0200 Wim Taymans + + * docs/faq/getting.xml: + * docs/faq/troubleshooting.xml: + * docs/faq/using.xml: + docs: update FAQ + Change versions. + Use tools with version prefix. + +2012-09-25 13:15:14 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations for typo fix + +2012-09-25 13:14:53 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: fix typo in translated string + Spotted by Chris Leonard. + https://bugzilla.gnome.org/show_bug.cgi?id=684755 + +2012-09-25 09:27:59 +0200 Sebastian Dröge + + * gst/gstpluginfeature.c: + pluginfeature: Remove 0.11.9X->1.0.0 version mangling + +2012-09-25 01:02:03 +0100 Josep Torra Valles + + * tests/benchmarks/complexity.c: + * tests/benchmarks/gstpollstress.c: + benchmarks: printf format fixes to make intel compiler happy + https://bugzilla.gnome.org/show_bug.cgi?id=552657 + +2012-09-25 00:55:59 +0100 Josep Torra Valles + + * libs/gst/base/gsttypefindhelper.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gsttee.c: + * tools/gst-launch.c: + * tools/tools.h: + Make intel compiler happier + https://bugzilla.gnome.org/show_bug.cgi?id=552657 + +2012-09-24 16:31:54 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development (bug fixing) + +=== release 1.0.0 === + +2012-09-24 12:19:16 +0100 Tim-Philipp Müller + + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 1.0.0 + +2012-09-24 00:39:26 +0100 Tim-Philipp Müller + + * docs/random/porting-to-1.0.txt: + docs: update 0.11 references in porting guide + +2012-09-24 00:37:27 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + * docs/random/porting-to-1.0.txt: + docs: rename porting-to-0.11.txt to porting-to-1.0.txt + +2012-09-23 19:56:43 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: fix FIXME printing for tcase_skip_broken_test() + +2012-09-23 17:30:50 +0100 Tim-Philipp Müller + + * docs/random/release: + docs: update release doc + Create tags for releases without the ugly RELEASE- prefix. + +2012-09-23 12:42:01 +0100 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.c: + collectpads: don't forward random stream-start event + It's not right, and we don't know what extra properties + that event might have set in future (e.g. sparseness). + This change means collectpad users need to create their + own stream-start event now. We could add a utility + function that creates a stream-start event based on + the input stream-start events. + +2012-09-22 16:07:15 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 4f962f7 to 6c0b52c + +2012-09-21 21:13:27 +0200 Mark Nauwelaerts + + * docs/manual/advanced-dparams.xml: + manual: update controller documentation + +2012-09-21 21:13:13 +0200 Mark Nauwelaerts + + * gst/gstobject.c: + object: update controller documentation + +2012-09-18 15:22:03 +0200 Bastian Winkler + + * tools/gst-launch.1.in: + man: Fix syntax for value lists in caps strings + Value lists use curly brackets instead of parentheses + https://bugzilla.gnome.org/show_bug.cgi?id=684293 + +2012-09-20 14:48:17 -0400 Olivier Crête + + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: Remove pad probes only once + Also add test to make sure that if a pad probe is removed while it's + callback is running, the cleanup_hook isn't called again if it + returns GST_PAD_PROBE_REMOVE + +2012-09-19 15:01:46 -0400 Olivier Crête + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: Add functions to safely access GstProbeInfo data pointer + This is so that introspection based bindings can access it. + https://bugzilla.gnome.org/show_bug.cgi?id=684402 + +2012-09-19 23:25:54 +0100 Tim-Philipp Müller + + * docs/manual/basics-bins.xml: + docs: remove reference to 0.8 GstBin API from manual + https://bugzilla.gnome.org/show_bug.cgi?id=684048 + +2012-09-19 15:14:35 +0200 Mark Nauwelaerts + + * plugins/elements/gstidentity.c: + identity: transform GAP event in single segment mode + +2012-09-19 09:44:08 +0100 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads.c: + docs: collectpads doc fixes + +2012-09-18 21:49:41 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: check acquire result value + Check the result value from _buffer_pool_acquire() and return the + value when allocation failed. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=684285 + +2012-09-18 12:14:34 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix refcount bug by unreffing the correct variable + +=== release 0.11.99 === + +2012-09-17 17:56:44 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.11.99 + +2012-09-17 13:35:26 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/Makefile.am: + * gst/gst.h: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + * win32/vs10/Common.props: + Remove GST_USE_UNSTABLE_API guard and defines + +2012-09-17 13:09:58 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstghostpad.c: + pad: Add parent parameter to the link and unlink functions + Fixes part of bug #683995. + +2012-09-16 23:20:46 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + * gst/gstvalue.c: + * tests/check/gst/gsttag.c: + sample: add serialisation/deserialisation functions for GstSample + Since these things are inside taglists now, it would be good to be + able to print them and deserialise them. + https://bugzilla.gnome.org/show_bug.cgi?id=681322 + +2012-09-15 21:56:07 +0200 Christian Fredrik Kalager Schaller + + * gstreamer.spec.in: + Switch to F18 naming of the package + +2012-09-15 18:43:39 +0200 Mark Nauwelaerts + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/basics-elements.xml: + * tools/gst-inspect.c: + use gst_element_factory_get_metadata to replace obsolete API + +2012-09-14 17:52:14 +0200 Mark Nauwelaerts + + * docs/manual/advanced-metadata.xml: + * docs/manual/basics-bus.xml: + replace gst_tag_list_free with gst_tag_list_unref + +2012-09-14 17:08:49 +0200 Mark Nauwelaerts + + * plugins/elements/gstdataurisrc.c: + replace gst_element_class_set_details_simple with gst_element_class_set_metadata + +2012-09-14 17:00:23 +0200 Mark Nauwelaerts + + * tests/check/gst/gstcontroller.c: + * tests/check/gst/gstpreset.c: + * tests/check/libs/controller.c: + * tests/check/libs/test_transform.c: + * tests/check/pipelines/parse-launch.c: + * tests/examples/controller/control-sources.c: + replace gst_element_class_set_details_simple with gst_element_class_set_metadata + +2012-09-06 16:32:35 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: whitespace fix + +2012-09-14 14:08:18 +0100 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins-docs.sgml: + docs: indexers are no more + https://bugzilla.gnome.org/show_bug.cgi?id=684018 + +2012-09-14 13:34:24 +0200 Wim Taymans + + * tests/examples/stepping/framestep1.c: + tests: fix for appsink return value addition + +2012-09-14 02:54:52 +0100 Tim-Philipp Müller + + * configure.ac: + Back to development + +=== release 0.11.94 === + +2012-09-14 02:46:34 +0100 Tim-Philipp Müller + + * ChangeLog: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.11.94 + +2012-09-14 01:28:46 +0100 Olivier Crête + + * gst/gstpad.c: + pad: don't try to pretty-print event after we've given away ownership + Might cause crashes with debug logging enabled. + https://bugzilla.gnome.org/show_bug.cgi?id=683996 + +2012-09-14 01:17:54 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2012-09-14 00:30:37 +0100 Tim-Philipp Müller + + * gst/gstcompat.h: + gstcompat: fix backwards compat macro for gst_message_new_duration + Name it properly, so it, like, works. Clearly no one actually + used that.. + +2012-09-13 12:00:08 +0200 Wim Taymans + + * docs/pwg/advanced-types.xml: + * docs/pwg/intro-basics.xml: + docs: fix formats a little + +2012-09-13 11:38:52 +0200 Wim Taymans + + * win32/common/libgstbase.def: + defs: add new baseparse function + +2012-09-13 11:38:33 +0200 Wim Taymans + + * tools/gst-launch.1.in: + docs: fourcc is no more + +2012-09-13 11:35:41 +0200 Wim Taymans + + * docs/design/draft-klass.txt: + * docs/design/part-missing-plugins.txt: + * docs/faq/using.xml: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/appendix-programs.xml: + * docs/manual/basics-pads.xml: + * docs/pwg/advanced-negotiation.xml: + * docs/pwg/building-boiler.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/other-ntoone.xml: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gsttee.c: + * tests/benchmarks/caps.c: + * tests/benchmarks/capsnego.c: + * tests/check/gst/gststructure.c: + * tools/gst-launch.1.in: + docs: fix some docs + from git grep for ffmpegcolorspace and x-raw- + +2012-09-13 10:48:08 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.h: + parse: add missing declaration + +2012-09-13 10:24:16 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: indent fix + +2012-09-12 22:44:37 -0700 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Add a mode/flag for disabling PTS interpolation + To be used by sub-classes implementing video formats with reordering + such as MPEG. + +2012-09-10 18:38:57 -0700 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Handle GAP and still-frame events. + Hacky, because the still-frame code all lives in -base, where we + can't use it - so this is a hacky duplication of -base code. Not + sure which way to fix this: Move baseparse to -base, or move still-frame + events to core? + +2012-09-04 19:38:26 -0700 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Restructure event handling + Make the event handling more like what videodecoder does, + to ensure that all events are passed to child classes before being + placed on the pending queue or pushed onward. + +2012-09-03 10:30:08 -0700 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: Store incoming cached events in reverse order + Reverse the list just before sending. Prepending is more efficient + than appending, so this saves some cycles. + +2012-09-02 23:32:50 -0700 Jan Schmidt + + * libs/gst/base/gstbaseparse.c: + baseparse: First attempt at handling both DTS and PTS + +2012-09-13 00:38:21 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: add warning when we get something else than a sample for a sample tag + Facilitate GstBuffer -> GstSample transition for some tags, + could be hard to catch otherwise when creating tags, since + it'll only be apparent later when someone tries to read the + tags. + +2012-09-12 14:14:31 +0200 Andreas Frisch + + * gst/gstelementfactory.c: + elementfactory: don't crash if no element klass has been set + https://bugzilla.gnome.org/show_bug.cgi?id=683865 + +2012-09-12 23:12:14 +0200 Stefan Sauer + + * tests/check/libs/collectpads.c: + collectpads: fix a misplaced ')' + +2012-09-12 21:20:46 +0100 Tim-Philipp Müller + + * gst/gsterror.c: + error: don't tell people to file a bug for negotiation errors + +2012-09-12 20:54:50 +0200 Stefan Sauer + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * tests/check/libs/collectpads.c: + * win32/common/libgstbase.def: + collectpads: remove gst_collect_pads_add_pad_full + Rename gst_collect_pads_add_pad_full() to gst_collect_pads_add_pad() and fix all + invocations. + +2012-09-12 17:16:41 +0200 Mark Nauwelaerts + + * plugins/elements/gstfilesink.c: + filesink: fix build on Cygwin + ... where __fbufsize is not available + +2012-09-12 13:00:15 +0100 Tim-Philipp Müller + + * tests/check/elements/queue2.c: + Revert "tests: fix buffer leak in queue2 unit test" + This reverts commit 232fd2953eb00f694b667e7796704f5974cea452. + This was already fixed. + +2012-05-24 13:08:16 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix possible data corruption in ring buffer mode when seeking + Fix race that could cause data corruption when seeking in ring buffer + mode. + In perform_seek_to_offset(), called from the demuxer's pull_range + request, we drop the lock, tell upstream (usually a http source) + to seek to a different offset, then re-acquire the lock before we + do things to the ranges. However, between us sending the seek event + and re-acquiring the lock, the source thread might already have pushed + some data and moved along the range's writing_pos beyond the seek + offset. In that case we don't want to set the writing position back + to the requested seek position, as it would cause data to be written + to the wrong offset in the file or ring buffer. + Reproducible doing seek-emulated fast-forward/backward on 006653. + Conflicts: + plugins/elements/gstqueue2.c + +2012-05-24 13:06:47 +0100 Tim-Philipp Müller + + * tests/check/elements/queue2.c: + tests: fix buffer leak in queue2 unit test + +2012-09-12 12:23:22 +0200 Mark Nauwelaerts + + * libs/gst/check/gstcheck.h: + check: remove glib deprecation compatibility trickery + +2012-09-12 12:22:53 +0200 Mark Nauwelaerts + + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * tests/check/elements/queue.c: + * tests/check/elements/tee.c: + check: port to the new GLib thread API + +2012-09-12 11:52:25 +0200 Mark Nauwelaerts + + * tests/check/elements/fakesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/elements/queue2.c: + * tests/check/elements/tee.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstbus.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpipeline.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/gst/gsttocsetter.c: + * tests/check/libs/collectpads.c: + tests: port to new GLib thread API + +2012-09-12 11:49:55 +0200 Mark Nauwelaerts + + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + tests: benchmarks: align error message with code + +2012-09-11 19:49:58 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * win32/common/libgstreamer.def: + pad: expose gst_pad_mode_get_name() and use it in baseparse + +2012-09-11 13:22:57 +0100 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + * scripts/gst-uninstalled: + scripts: update for gst-ffmpeg -> gst-libav + Now that we have a gst-libav git repository (symlinked to gst-ffmpeg). + +2012-09-11 17:27:03 +0200 Mark Nauwelaerts + + * gst/gstquery.c: + query: adjust test logic for scheduling mode with flagS + +2012-09-11 16:39:34 +0200 Mark Nauwelaerts + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: add convenience API to query for scheduling mode and flags + +2012-09-11 16:29:12 +0200 Wim Taymans + + * docs/design/part-events.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstbuffer.h: + * gst/gstevent.c: + * gst/gstevent.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/gst/gstevent.c: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/libgstreamer.def: + events: remove STREAM_CONFIG + We won't be able to implement this so it's better to move it out of the way. + +2012-09-11 16:09:37 +0200 Wim Taymans + + * libs/gst/base/gstcollectpads.h: + collectpads: clean up header indentation + +2012-09-11 11:34:11 +0200 Wim Taymans + + * gst/gstutils.c: + utils: allow NULL stream_id also when 0 srcpads + We usually first create the stream_id for the stream_start event and then add + the pad to the element. This means that this functions should work when there + are no pads on the element yet. + +2012-09-10 21:39:32 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + * libs/gst/base/gstbaseparse.c: + * plugins/elements/gsttypefindelement.c: + baseparse, typefind: only activate in pull mode if upstream is seekable + Upstream might support pull mode, but only sequential pulls, + which isn't gonna do much for us. + https://bugzilla.gnome.org/show_bug.cgi?id=634927 + +2012-09-10 20:30:32 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + porting-to-0.11.txt: some minor fixes + +2012-09-10 16:52:46 +0100 Tim-Philipp Müller + + * gst/gstsample.c: + sample: free info structure with sample if there is one and fix copy with NULL info structure + +2012-09-10 12:20:15 +0200 Mark Nauwelaerts + + * gst/gstmemory.h: + memory: add padding to GstMapInfo + +2012-09-10 12:12:02 +0200 Mark Nauwelaerts + + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + libs: adjust comment style + +2012-09-10 12:11:23 +0200 Mark Nauwelaerts + + * gst/gstcompat.h: + * gst/gstobject.c: + gst: remove some defunct commented code + +2012-09-10 12:00:22 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: improve porting doc + +2012-09-10 10:08:09 +0200 Wim Taymans + + * tests/check/tools/gstinspect.c: + tests: disable deprecation warnings + define GLIB_DISABLE_DEPRECATION_WARNINGS earlier so that it is defined before + the glib headers are loaded or else we trip over the GValueArray deprecations in + gst-inspect.c. + +2012-09-07 01:02:10 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstdirectcontrolbinding.c: + controller: fix direct control binding double -> int conversion + Round properly to nearest integer. Fixes controller + unit test on PowerPC G4. + +2012-09-06 15:06:08 +0100 Tim-Philipp Müller + + * tests/examples/helloworld/helloworld.c: + examples: fix bus/fd leak in hello world example + https://bugzilla.gnome.org/show_bug.cgi?id=683470 + +2012-09-05 19:55:10 +0100 Tim-Philipp Müller + + * gst-element-check.m4: + gst-element-check.m4: fix action-if-found and not-found invocation + Arguments got shifted back by one. + +2012-09-05 15:37:13 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads.c: + collectpads: handle GAP event + +2012-09-04 12:13:11 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: wait_eos -> wait_event + Fix a FIXME. Now we can also pass the GAP event to the subclass. + +2012-09-03 18:45:03 +0100 Tim-Philipp Müller + + * tests/examples/controller/Makefile.am: + examples: update Makefile.am android bits in controller example + Should fix build failure reported on IRC. + +2012-08-30 19:15:42 +0200 Wim Taymans + + * gst/gstpad.c: + pad: check sticky events also after pad block + Recheck for sticky events after doing a pad block because the pad block could + have caused a relink and then we need to resend the events to the newly linked + pad. + Fixes things like switching of visualisations. + +2012-09-02 02:04:14 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: update for gst_message_new_duration -> _duration_changed() + +2012-09-02 01:17:44 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbin.c: + * gst/gstcompat.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + message: rename GST_MESSAGE_DURATION -> GST_MESSAGE_DURATION_CHANGED + The duration should be re-queried via a query using the + normal path, we don't want applications to use the value + from the message itself, since it might no match what a + duration query done from the sink upstream might yield. + Also disables duration caching in GstBin. It should be + added back again at some point. + +2012-09-01 23:54:23 +0100 Tim-Philipp Müller + + * configure.ac: + configure: add reminder to remove GST_UNSTABLE_API stuff before 1.0.0 + +2012-09-01 18:06:58 +0100 Tim-Philipp Müller + + * .gitignore: + * Makefile.am: + * configure.ac: + * gst-element-check.m4: + * gst-element-check.m4.in: + gst-element-check.m4: rename AM_GST_ELEMENT_CHECK to GST_ELEMENT_CHECK + And allow passing of a minimum version (if not needed, pass 1.0). + https://bugzilla.gnome.org/show_bug.cgi?id=682968 + +2012-09-01 17:50:14 +0100 Tim-Philipp Müller + + * tests/check/.gitignore: + * tests/check/Makefile.am: + * tests/check/tools/gstinspect.c: + tests: add check for gst-inspect --exists functionality + +2012-09-01 17:47:58 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: add --exists and --atleast-version option to gst-inspect + For checking if an element exists with a given minimum version. + Will use that in our new GST_ELEMENT_CHECK m4 macro. + https://bugzilla.gnome.org/show_bug.cgi?id=682968 + +2012-09-01 17:32:04 +0100 Tim-Philipp Müller + + * gst/gstpluginfeature.c: + pluginfeature: disable version mangling for post-1.0.0 release + Just in case we don't grep for FIXME 1.0 before the release. + +2012-08-31 11:31:45 -0700 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + basesink: Make GAP events actually trigger preroll + Slightly hacky approach needing refinement + +2012-08-31 06:25:22 -0700 Jan Schmidt + + * gst/gstpad.c: + gstpad: make some debug statements more verbose + +2012-08-31 06:23:53 -0700 Jan Schmidt + + * gst/gstghostpad.c: + * plugins/elements/gstinputselector.c: + ghostpad: Make some debugging more verbose + Also, remove an unnecessary #include in input-selector + +2012-08-28 15:44:48 -0700 Jan Schmidt + + * gst/gstsegment.c: + GstSegment: Fix doc description string last_stop->position + +2012-08-30 19:47:57 +0100 Arnaud Vrac + + * plugins/elements/gstinputselector.c: + inputselector: fix clock leak + https://bugzilla.gnome.org/show_bug.cgi?id=682997 + +2012-08-29 22:57:02 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: output gst-inspect errors to stderr + +2012-08-28 07:39:50 +0200 Alban Browaeys + + * gst/gstvalue.c: + value: fix crash serialising a 0 flags value when there's no name for it + Fixes segfault when doing gst-launch-1.0 -v -m camerabin + (encodebin notifies a 0 value for its "flag" property). + https://bugzilla.gnome.org/show_bug.cgi?id=682958 + +2012-08-24 23:14:57 +0100 Tim-Philipp Müller + + * gst/gst.c: + gst: log performance warning debug message if glib emulates atomic ops + +2012-08-23 13:51:27 +0100 Lionel Landwerlin + + * gst/Makefile.am: + gst: use configure-detected or externally provided glib-mkenums + To ease cross-compilation. + https://bugzilla.gnome.org/show_bug.cgi?id=677620 + +2012-08-22 13:29:34 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 668acee to 4f962f7 + +2012-08-22 13:14:56 +0200 Stefan Sauer + + * configure.ac: + configure: bump gtk-doc req to 1.12 (mar-2009) + This allows us to e.g. unconditionally use gtkdoc-rebase. + +2012-08-21 13:30:52 +0200 Wim Taymans + + * gst/gstmemory.h: + memory: add _make_writable + +2012-08-21 00:03:37 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: mention some media type changes in porting-to-0.11.txt doc + +2012-08-20 13:51:05 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: minor update to porting doc for child proxy lookup method + And a typo fix. + +2012-08-20 11:31:51 +0200 Wim Taymans + + * gst/gstallocator.c: + allocator: make a copy with the same alignment + When making a copy of the memory allocated from the default memory allocator, + make sure the new copy has the same alignment as the original memory. + See https://bugzilla.gnome.org/show_bug.cgi?id=680796 + +2012-08-19 17:51:00 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: make seeking in DEFAULT format work if the subclass can convert for us + We only deal in TIME format ourselves, but if the subclass can handle + converting other formats into TIME format, we can support that too. + Fixes seeking in DEFAULT (sample) format with flacparse, + and the flacdec unit test. + +2012-08-18 21:42:23 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + tools: minor fixes to gst-launch man page + +2012-08-17 12:23:50 +0200 Stefan Sauer + + * gst/gstpreset.c: + preset: implement child_proxy support + Elements such as the GstIirEqualizerNBands would so far not store the properties + of their children. Now we also grab the properties of child elements and try to + restore them. + +2012-08-14 18:44:38 +0200 Edward Hervey + + * plugins/elements/gstinputselector.c: + inputselector: Wait for other streams to advance on unselected pads + Otherwise we end up dropping a lot of data in the case where data starts + arriving on the non-selected pad, resulting in big gaps in stream switching + +2012-08-14 18:43:54 +0200 Edward Hervey + + * plugins/elements/gstinputselector.c: + inputselector: More debug statements + +2012-08-14 18:42:31 +0200 Edward Hervey + + * plugins/elements/gstinputselector.c: + inputselector: Don't forward stream-start sticky events + Only one STREAM_START event should be let through, else it will + confuse downstream elements that think a new stream is starting + whereas in fact we are just switching to a different input. + In the future we might want to let them through but with the same + sequence number. + +2012-08-14 15:46:35 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * win32/common/libgstbase.def: + docs: Add new basesrc/basetransform API to the docs + +2012-08-07 17:38:53 +0200 Víctor Manuel Jáquez Leal + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: getters for pool and allocator + Sometimes a transform filter would need the buffer pool or the memory + allocator negotiated by the base class, for example, for querying different + parameters, such as a bigger number of buffers to allocate by the buffer pool. + This patch expose a two getters accessors: one for the buffer pool and the + other for the memory allocator. + +2012-08-07 17:35:48 +0200 Víctor Manuel Jáquez Leal + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: getters for pool and allocator + Sometimes the sources would use the buffer pool or the memory allocator for + something else than just allocating output buffers; for example, querying for + different parameters, such as a bigger number of buffers to allocate by the + pool. + This patch expose a two getters accessors: one for the buffer pool and the + other for the memory allocator. + +2012-08-14 00:39:18 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstregistry.c: + * gst/gstregistry.h: + * win32/common/libgstreamer.def: + registry: remove some unused and in their current form pointless API + Not so useful: just adds/reads stuff from an internal GList without + actually doing anything with those paths, so remove for now: + gst_registry_add_path + gst_registry_get_path_list + https://bugzilla.gnome.org/show_bug.cgi?id=608841 + +2012-08-12 13:27:06 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: fix up for gst_child_proxy_lookup() only working on child proxy interfaces + https://bugzilla.gnome.org/show_bug.cgi?id=681681 + +2012-08-12 13:24:18 +0100 Tim-Philipp Müller + + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + childproxy: make gst_child_proxy_lookup() a proper GstChildProxy method + No longer accept any old GObjects. This makes things nicer for + bindings. If a utility function that handles both nicely + is deemed worthwhile, we can still add one to gstutils. + https://bugzilla.gnome.org/show_bug.cgi?id=681681 + +2012-08-13 00:01:16 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + value: when serialising arrays or lists, handle types we can't serialise more gracefully + https://bugzilla.gnome.org/show_bug.cgi?id=681322 + +2012-08-12 19:39:46 +0100 Tim-Philipp Müller + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: add some more details to failure messages + Mention pad where the problem occured, and the event name. + +2012-08-12 18:36:09 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/libs/collectpads.c: + tests: fix collectpads test + After an EOS we must send a FLUSH_STOP event if + we want to send data again. + +2012-08-12 18:31:13 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + event: fix leak in gst_event_parse_stream_start() + gst_structure_id_get() will make a copy of the string + extracted, but we're assigning it to a const gchar *. + +2012-08-12 16:40:03 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpipeline.c: + tests: make pipeline test valgrind clean + +2012-08-12 16:37:02 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/gst/gstpipeline.c: + tests: fix pipeline unit test + Which was disabled because it failed. + +2012-08-12 15:48:20 +0100 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: fix unterminated quoted string in create-uninstalled-setup.sh + +2012-08-12 00:12:56 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: mention gst_video_format_parse_caps() in porting guide + +2012-08-11 22:19:32 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + * gst/gstcontrolbinding.h: + * gst/gstevent.c: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttoc.c: + * gst/gstutils.c: + docs: fix up docs a bit + +2012-08-11 22:18:13 +0100 Tim-Philipp Müller + + * gst/gstchildproxy.c: + childproxy: fix up g-i annotation for _lookup() paramspec return value + No ref is returned here. + +2012-08-11 22:17:35 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for new buffer functions + +2012-08-10 22:58:56 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix reverse playback with upstream demuxers that support it + Don't just return FALSE for seek events with negative rates when + operating in push mode. An upstream demuxer may support this just + fine, so if we're not operating in pull mode always check upstream + first if it can handle the seek event. This fixes reverse playback + where the upstream demuxer supports it (e.g. with qtdemux). The + same code would work fine in 0.10, because baseparse will just + call the default pad event handler if FALSE was returned from the + baseparse event handler, and the pad event handler will just + forward it upstream. In 0.11 the baseclass or subclass is + responsible for chaining up to the parent class or forwarding the + event upstream in any case. + Disable reverse playback in pull mode for now, there seems to + be something going wrong with the segment configuration in that + case. + +2012-08-04 11:48:52 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: do not error on not-negotiated + Don't error out too early and let upstream decide if it can + workaround a not-negotiated problem + https://bugzilla.gnome.org/show_bug.cgi?id=681198 + +2012-08-04 11:48:13 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: retry on not-negotiate if a reconfigure is pending + Before erroring out on not-negotiated returns, check if the pad + has the reconfigure flag set and retry. + https://bugzilla.gnome.org/show_bug.cgi?id=681198 + +2012-08-04 11:42:05 -0300 Thiago Santos + + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: add gst_pad_needs_reconfigure + Add an alternative version of gst_pad_check_reconfigure that doesn't + clear the reconfigure flag. + Useful for increasing error resilience without duplicating the + reconfigure code in pad task functions. + API: gst_pad_needs_reconfigure + https://bugzilla.gnome.org/show_bug.cgi?id=681198 + +2012-07-29 15:44:45 -0700 Evan Nemerson + + * gst/gstpad.h: + pad: add GST_PAD_LINK_CHECK_DEFAULT to GstPadLinkCheck + This allows introspection-based bindings to access + Gst.PadLinkCheck.DEFAULT instead of + Gst.PAD_LINK_CHECK_DEFAULT. + https://bugzilla.gnome.org/show_bug.cgi?id=678301 + +2012-07-29 14:57:41 -0700 Evan Nemerson + + * gst/gstbuffer.c: + buffer: mark gst_buffer_wrapped* data as array + https://bugzilla.gnome.org/show_bug.cgi?id=678301 + +2012-07-24 13:26:00 -0700 Evan Nemerson + + * gst/gstobject.c: + * gst/gsttoc.c: + introspection: fix some warnings generated by g-ir-scanner. + https://bugzilla.gnome.org/show_bug.cgi?id=678301 + +2012-07-30 21:46:18 -0700 Evan Nemerson + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: convert gst_buffer_* macros to functions + GObject Introspection does not support macros. + This is needed for bindings. We can still add back + macros or inline functions again later if we think + it's worth it. + https://bugzilla.gnome.org/show_bug.cgi?id=678301 + +2012-08-10 13:50:41 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnetclientclock.c: + netclientclock: fix printf format in debug message + +2012-08-10 12:23:03 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: fix max_buffers handling + When max_buffers > 0 and the pool is empty, actually try to allocate more + buffers up to the max_buffers limit. + We need to add a counter for this to count how many buffers we allocated and + check this against the max_buffers limit. + Reorganise and clean up some code. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=681153 + +2012-08-10 09:19:25 +0100 Tim-Philipp Müller + + * libs/gst/net/gstnetclientclock.c: + netclientclock: simplify by using g_socket_condition_timed_wait() + No need to use a custom main context and custom timeout sources, + just use g_socket_condition_timed_wait() instead, which was added + for exactly this case. + Also seems to help with the unit test deadlocking with glib 2.33.x + https://bugzilla.gnome.org/show_bug.cgi?id=681575 + +2012-08-09 19:15:29 +0100 Tim-Philipp Müller + + * gst/gstobject.c: + gstobject: fix double string escaping in gst_object_default_deep_notify() + Make output of gst-launch -v readable again. + last-message = "event\ \ \ \*\*\*\*\*\*\*\ \(fakesink0:sink\)\ E\ \(type:\ tag\ \(20510\)\,\ GstTagList-stream\,\ taglist\=\(taglist\)\"taglist\\\,\\\ video-codec\\\=\\\(string\\\)H264\\\,\\\ + minimum-bitrate\\\=\\\(uint\\\)636611\\\,\\\ bitrate\\\=\\\(uint\\\)980729\\\,\\\ maximum-bitrate\\\=\\\(uint\\\)1116707\\\;\"\;\)\ 0x15bc760" + vs. + last-message = event ******* (fakesink0:sink) E (type: tag (20510), GstTagList-stream, taglist=(taglist)"taglist\,\ video-codec\=\(string\)H264\,\ minimum-bitrate\=\(uint\)856039\,\ bitrate + \=\(uint\)1019748\,\ maximum-bitrate\=\(uint\)1116707\;";) 0x11149e0 + +2012-08-09 16:18:59 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: check writability + fix the writability check for miniobjects. We should check the shared counter. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=681450 + +2012-08-08 16:08:44 +0200 Sebastian Dröge + + * gst/gstallocator.c: + allocator: Set the alignment at the correct place in GstAllocationParams + +2012-08-08 16:18:15 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + Back to development + +=== release 0.11.93 === + +2012-08-08 15:05:08 +0100 Tim-Philipp Müller + + * configure.ac: + * gstreamer.doap: + * win32/common/config.h: + Release 0.11.93 + +2012-08-08 14:49:23 +0100 Tim-Philipp Müller + + * tests/check/gst/gstobject.c: + tests: remove silly test_fail_abstract_new check + Our check would make sure that GLib segfaults when + someone tries to instantiate an abstract type, which + is an extremely useful thing to check for. + In newer GLibs this is fixed and we get an abort with + a g_error() now it seems, so let's just remove this + check entirely. + +2012-08-08 09:53:26 +0100 Tim-Philipp Müller + + * tests/examples/stepping/framestep1.c: + examples: don't put things with side effects inside g_assert() + They will be defined away to NOOPs otherwise in release builds. + +2012-08-08 09:13:38 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update for stream-id API additions + +2012-08-08 00:54:49 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: fix for new GstChildProxy::child-added signal callback signature + Fixes crash with gst-launch-1.0 uridecodebin uri=... suburi=... ! .. + +2012-08-07 10:46:17 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Add allow-none to the function argument of gst_bus_set_sync_handler() + https://bugzilla.gnome.org/show_bug.cgi?id=681139 + +2012-08-06 16:33:57 +0400 Руслан Ижбулатов + + * docs/gst/Makefile.am: + docs: Make sure scanner gets required libraries + +2012-08-06 20:08:07 +0100 Tim-Philipp Müller + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: print which event we received before stream-start + +2012-08-06 20:04:09 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesrc.c: + basesrc: don't try to answer URI queries with NULL URIs + Should make unit tests in -base that use appsrc a bit happier. + +2012-07-29 14:25:34 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * tests/check/elements/queue.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstpad.c: + event: Update for stream-start event API changes + +2012-07-28 08:37:00 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstutils.c: + * gst/gstutils.h: + event: Add new stream-id field to the stream-start event + This is supposed to allow uniquely identifying a single stream. + +2012-07-27 17:41:43 +0200 Edward Hervey + + * plugins/elements/gstinputselector.c: + inputselector: Use the first created pad by default + This guarantees a bit more consistency in which input stream will + be selected by default. It would previously be the first pad on which + an event/buffer/query was received ... which was racy and non-predictable. + +2012-07-27 17:38:34 +0200 Edward Hervey + + * gst/gstelement.c: + element: Specify the order of pad iterators + The order of returned pads wasn't specified before, so let's specify + it and use an order which might prove the most useful : the order in + which pads were added to the element. + If someone changes the order, make sure users of those iterators from + now on don't rely on that order ! + +2012-08-05 17:16:27 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: add tcase_skip_broken_test() define + Skips broken tests but logs an ERROR-level message to + draw attention to that fact. + +2012-08-05 17:12:35 +0100 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + tests: update .gitignore for queuearray test binary + +2012-08-05 17:11:46 +0100 Tim-Philipp Müller + + * tests/check/libs/gstnetclientclock.c: + tests: fix spurious netclientclock test failures + Give clocks a bit more time to synchronise. + +2012-08-05 16:59:35 +0100 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + win32: update generated files + +2012-08-05 16:41:21 +0100 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + input-selector: use generic marshaller for "block" action signal + +2012-08-05 16:37:24 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 94ccf4c to 668acee + +2012-08-04 13:37:32 +0100 Tim-Philipp Müller + + * gst/gstallocator.c: + * gst/gstbuffer.c: + buffer, defaultmem: add option to poison memory before freeing it + Might be useful to track down certain bugs. + +2012-08-03 23:54:33 +0100 Tim-Philipp Müller + + * gst/gst.c: + gst: ref/unref taglist scope enum in gst_init() + Fixes make check and distcheck + +2012-08-03 00:05:53 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: warn if plugin name starts with a " + This can easily happen as side-effect of the plugin name + in GST_PLUGIN_DEFINE no longer being a string in 0.11, but + a name to G_STRINGIFY. + +2012-08-02 13:19:27 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: update porting-to-0.11 document with a "soft" API changes checklist + Point out some API changes that the compiler won't + be able to warn about. + +2012-08-02 11:33:41 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: fix printing of partial dates in gst-launch + +2012-08-02 11:15:16 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + Revert "tools: print TOC scope" + This reverts commit ee6ab7c93638a6519acb976699a6ad149d520a95. + The application will probably only ever receive global TOCs, + so don't really need this. + +2012-08-01 17:49:27 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new tag list scope symbols + +2012-08-01 11:58:55 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefind: send segment_done event in addition to segment_done message + +2012-07-31 17:25:50 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstfilesrc.c: + basesrc: Add default handler for URI query in GstURIHandler subclasses + +2012-07-28 17:33:52 +0200 Sjoerd Simons + + * libs/gst/check/libcheck/check.h.in: + check: unbreak fail #define + The fail() definition was changed to not fail with non-GCC compilers, + unfortunately the change was incorrect and appended the first argument + of fail to the expression string instead of making it the message. + This change does mean that fail() now requires a message to be passed + along. + https://bugzilla.gnome.org/show_bug.cgi?id=680755 + +2012-07-29 23:37:19 +0200 Jens Georg + + * gst/gstbuffer.c: + buffer: Update annotations + https://bugzilla.gnome.org/show_bug.cgi?id=680805 + +2012-07-29 23:20:07 +0200 Jens Georg + + * gst/gstutils.c: + utils: Update annotation for get_compatible_pad + https://bugzilla.gnome.org/show_bug.cgi?id=680804 + +2012-07-28 21:23:24 -0400 Thibault Saunier + + * gst/gsturi.c: + uri: Fix wrong 'array zero-terminated=1' annotation for strings + +2012-07-28 11:02:30 +0100 Tim-Philipp Müller + + * docs/design/part-toc.txt: + docs: update TOC design docs a little + +2012-07-28 09:41:30 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + event: make TOC event multi-sticky + We need to send two kinds of TOCs downstream as events, + and need both to stick to the pads. + https://bugzilla.gnome.org/show_bug.cgi?id=678742 + +2012-07-28 08:30:36 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: print TOC scope + +2012-07-27 23:56:54 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gsttoc.c: + * gst/gsttoc.h: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + * win32/common/libgstreamer.def: + toc: add GstTocScope and require it in the constructor + This is because we need to be able to signal different TOCs + to downstream elements such as muxers and the application, + and because we need to send both types as events (because + the sink should post the TOC messages for the app in the + end, just like tag messages are now posted by the sinks), + and hence need to make TOC events multi-sticky. + https://bugzilla.gnome.org/show_bug.cgi?id=678742 + +2012-07-27 23:54:00 +0100 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: create-uninstalled-setup.sh: check for basic build tools and deps + .. before checking out stuff. + +2012-07-27 23:52:12 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * libs/gst/base/gstbaseparse.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstutils.c: + tag: Add a scope to taglists + This specifies if a given taglist applies to the complete + medium or only this specific stream. By default a taglist + has a stream scope. + Fixes bug #677619. + +2012-07-27 17:09:45 +0200 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + segment: add offset field + Add an offset field that is used to track at what position the segment was + updated. This is used to set the running time to 0 when we do a flushing + seek that doesn't update the position. + See https://bugzilla.gnome.org/show_bug.cgi?id=680306 + +2012-07-27 15:19:57 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstsegment.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gststructure.c: + Update for new seeking variable name + When seeking, the start value and type are now called start and start_type. + +2012-07-27 14:53:03 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: small cleanup + Move the code to update the segment at the end of the function. + +2012-07-27 12:05:25 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + Update docs and .def file for taglist API change + +2012-07-27 13:02:52 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: remove redundant checks + We don't need to check the segment format anymore because we asserted on them + being equal before. + +2012-07-27 12:24:03 +0200 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: improve segment tests + +2012-07-27 12:12:37 +0200 Wim Taymans + + * gst/gstallocator.c: + * gst/gstallocator.h: + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-vidmem.c: + allocator: remove user_data from alloc vmethod + Remove the user_data from the alloc vmethod. Subclasses that implement a new + alloc function can also implement their own vmethod to pass extra arguments. We + can then also require that custom allocators implement an alloc function so that + gst_allocator_alloc() always works. + +2012-07-27 10:41:54 +0200 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: remove segment accumulation checks + Remove the checks because there is no more segment accumulation. + +2012-07-26 16:44:15 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: make GST_TAG_APPLICATION_DATA also a GstSample + That way additional meta-data can be passed along with it. + +2012-07-26 15:51:10 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + taglist: gst_tag_list_get_buffer*() => gst_tag_list_get_sample*() + Image tags and other tags are now of GstSample type. + +2012-07-26 15:26:09 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: print image tags and other GstSample tags properly + These tags are now of type GstSample not GstBuffer. + +2012-07-24 21:38:35 +0200 Stefan Sauer + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * win32/common/libgstbase.def: + collectpads: remove unimplemented api + We can always add this back if we need it. Fixes parts of #670852. + +2012-07-24 13:49:36 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: also account for frame size when merely scanning for frame + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=680495 + +2012-07-24 13:48:39 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: remove obsolete function parameter + +2012-07-24 12:38:15 +0200 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: require bytes before typefinding + Require that we have some bytes in the adapter before we attempt to typefind. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=680479 + +2012-07-23 18:49:13 +0200 Christian Fredrik Kalager Schaller + + * gstreamer.spec.in: + update spec file with latest changes + +2012-07-23 16:27:34 +0200 Wim Taymans + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + bufferlist: pass index as gint to _insert + Make the idx argument of _insert() a gint because we allow -1 as a value. + Improve annotation. + +2012-07-23 13:40:38 +0200 Wim Taymans + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + plugins: print flags better + print the buffer flags as a hex number so that it becomes easier to see what + flags are set. + +2012-07-18 17:03:45 +0200 Sebastian Rasmussen + + * gst/gstpoll.c: + gstpoll: Improve warning message when re-adding fd to fdset + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=680181 + +2012-07-23 08:44:04 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 98e386f to 94ccf4c + +2012-07-20 00:49:28 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + * gst/gstvalue.c: + value: add GstTagList serialisation/deserialisation + So we can serialise/deserialise taglists inside structures, + which used to work automagically before because GstTagList + was just a typedef to GstStructure (same for the GType), + but now that it's a separate GType we need to register + explicit functions for this. + Helps with GDP stuff in pipelines/streamheader tests. + +2012-07-20 09:38:47 +0200 Philippe Normand + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update .po files + +2012-07-19 13:51:23 +0200 Mark Nauwelaerts + + * tests/check/gst/gstbuffer.c: + tests: gstbuffer: add tests for some mulitple map combinations + +2012-07-19 13:35:34 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: fix sharedness check + +2012-07-19 13:20:27 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: refuse write when object is shared + In all cases, refuse to write an object when it is shared by more than one + object (also when the object was locked before). + See https://bugzilla.gnome.org/show_bug.cgi?id=679145 + +2012-07-18 15:21:33 +0200 Mark Nauwelaerts + + * tests/check/gst/gstbuffer.c: + tests: gstbuffer: extend buffer copy test + +2012-07-19 12:42:05 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: set buffering-left to 0 on 100% buffering + Set the buffering-left field in the query to 0 when we are completely buffered. + Improve the debug. + +2012-07-19 12:14:29 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix buffering query + Fix the buffering query, fill in the right buffering-left and estimated-total + values. + +2012-07-19 10:54:16 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix the buffering-left in the buffering message + The buffering-left field in the buffering message should contain a time estimate + in milliseconds about for long the buffering is going to take. We can calculate + this value when we do rate_estimates. + +2012-07-19 10:14:18 +0200 Wim Taymans + + * gst/gstmessage.c: + message: improve buffering message defaults + Remove the estimated-total field, this should not be part of the buffering + message. + Set the default value of buffering-left to 0 when the percent is 100. + +2012-07-18 17:44:54 +0200 Wim Taymans + + * gst/gstpad.c: + pad: fix debug line + Use QUERY_TYPE on query types. + +2012-07-18 17:35:58 +0200 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * win32/common/libgstreamer.def: + ghostpad: remove custom function + Remove custom pad functions, the default ones are better. + +2012-07-18 17:30:30 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add PROXY_SCHEDULING flag + Add a flag that makes the default query handler forward the scheduling query. + +2012-07-18 17:30:04 +0200 Wim Taymans + + * gst/gstutils.c: + utils: fix docs + +2012-07-18 16:20:41 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstutils.c: + pad: improve query caps function + In the proxy_query_caps function, also filter against the filter in the query. + We don't need to filter against the filter in the query anymore in the default + caps query function because we already did this in the proxy_query_caps. + +2012-07-18 11:17:23 +0200 Wim Taymans + + * docs/design/part-framestep.txt: + * gst/gstsegment.c: + * libs/gst/base/gstbasesink.c: + basesink: handle -1 step amounts + Define a 0 and -1 step amount. They used to almost do the same thing but now, 0 + cancels/stops the current step and -1 keeps on stepping until the end of the + segment. + See https://bugzilla.gnome.org/show_bug.cgi?id=679378 + +2012-07-18 12:30:59 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + query: fix gst_query_parse_nth_allocation_pool() annotation + It returns a ref to the pool. + +2012-07-17 15:52:53 +0200 Edward Hervey + + * tests/check/gst/gstghostpad.c: + check: Avoid deadlock + Queries will be sent when pipeline goes down to NULL, which would + result in the probe being called ... but can't take the lock. + +2012-07-17 15:50:09 +0200 Edward Hervey + + * gst/gstghostpad.c: + gstghostpad: Forward queries in both direction + Use the peer of the internal pad to forward them, instead of the + target which only exists for the ghostpad (and not the internal + proxy pad). + +2012-07-17 11:20:43 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + docs: More entries + +2012-07-18 09:15:51 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + queue: answer SCHEDULING query + Instead of letting the default query handler fail. + +2012-07-17 19:20:23 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: handle CAPS event and drop it if operating in ring buffer mode + Fixes "Unexpected event of kind caps can't be added in temp file" + warning when doing download buffering. + +2012-07-17 12:57:59 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: make _foreach_meta more powerful + Make _foreach_meta return FALSE when the foreach function returned FALSE. + +2012-07-17 12:52:59 +0200 Wim Taymans + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + bufferlist: improve foreach function + Make the foreach function return FALSE when one of the function calls returned + FALSE. + +2012-07-17 12:50:24 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add more debug + +2012-07-17 12:40:54 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix debug string + +2012-07-17 09:57:47 +0200 Wim Taymans + + * gst/gstparse.c: + * gst/parse/grammar.y: + * gst/parse/types.h: + parse: fix some debug + +2012-07-17 09:48:00 +0200 Wim Taymans + + * gst/gstparse.c: + parse: only escape spaces outside of quotes + When we escape spaces to keep arguments together, only escape when the space is + outside a "" string. + See https://bugzilla.gnome.org/show_bug.cgi?id=673319 + +2012-07-17 09:44:10 +0200 Wim Taymans + + * gst/gstparse.c: + Revert "parse: escape \ with a \ as well, so that we don't lose the \ when unescaping" + This reverts commit dd9fedb41f1ada8e1f8bd5346fccd3d068d543cb. + This is not the right place to escape the \, we should only escape the spaces to + keep the arguments together that were provided as one group (with quotes on the + shell). + +2012-07-10 12:27:11 -0700 Evan Nemerson + + * gst/gstutils.c: + utils: set return type of gst_parse_bin_* to GstBin for introspection + +2012-06-30 12:33:43 -0700 Evan Nemerson + + * libs/gst/net/gstnettimepacket.c: + nettimepacket: add missing array annotation to gst_net_time_packet_new + +2012-06-29 17:33:49 -0700 Evan Nemerson + + * gst/gstformat.c: + introspection: add missing array annotation to gst_formats_contains + +2012-07-16 20:54:17 +0200 Stefan Sauer + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: aggregate durations like in adder + Stop querying the duration once an element return unknown and return unknown + as a final result. This avoid eventually cutting off a stream too early. + Add a tests to docuement the behavior. + +2012-07-16 00:24:46 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: just return NULL on short input strings instead of a warning + We want to be able to use this function on random non-NULL input, + this should not result in a runtime-critical. + +2012-07-15 12:59:44 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix seekability querying with formats with headers like FLAC + Move code that checks for upstream seekability and all that to + the right place, otherwise it will never be done for formats + that have headers such as FLAC, as handle_and_push frame will + be called the first time only after headers have been processed + (and framecount is > 0). This then makes us report that we + can't seek, which disables the seek bar in totem. + +2012-07-14 20:33:30 +0100 Tim-Philipp Müller + + * plugins/elements/gstdataqueue.c: + * plugins/elements/gstdataqueue.h: + plugins: embed GstAueueArray in dataqueue struct as well + +2012-07-14 20:28:54 +0100 Tim-Philipp Müller + + * plugins/elements/gstelements.c: + plugins: don't use one-time array in plugin_init + +2012-07-14 20:26:04 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: embed GstQueueArray structure + +2012-07-14 20:00:30 +0100 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.h: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstfilesink.h: + * plugins/elements/gstfilesrc.h: + * plugins/elements/gstfunnel.h: + * plugins/elements/gstidentity.h: + * plugins/elements/gstinputselector.h: + * plugins/elements/gstmultiqueue.h: + * plugins/elements/gstoutputselector.h: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueue2.h: + * plugins/elements/gstqueuearray.h: + * plugins/elements/gsttee.h: + * plugins/elements/gsttypefindelement.h: + * plugins/elements/gstvalve.h: + plugins: sprinkle some more G_GNUC_INTERNAL + +2012-07-14 19:38:39 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueuearray.c: + * plugins/elements/gstqueuearray.h: + plugins: add init/clear functions to GstQueueArray + +2012-07-14 19:24:57 +0100 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * plugins/elements/Makefile.am: + * plugins/elements/gstdataqueue.h: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueuearray.c: + * plugins/elements/gstqueuearray.h: + * tests/check/libs/queuearray.c: + * win32/common/libgstbase.def: + base: make GstQueueArray private to coreelements for now + Keep it private until we have a reason to make it public. + +2012-07-14 19:08:24 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: check value type matches tag type when adding values to a taglist + +2012-07-14 18:52:50 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: make taglists and datetime loggable via GST_PTR_FORMAT + +2012-07-13 12:05:15 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: send seek event upstream first + First try to let upstream handle the seek event, then fail if the event is + something we don't understand. + +2012-07-13 09:43:59 +0200 Wim Taymans + + * tests/check/gst/gstpad.c: + pad: fix test raciness + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=679506 + +2012-07-12 13:17:51 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: fix gst-ffmpeg plugin path again + +2012-07-12 12:09:13 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add clutter-gst and refine plugin search paths + +2012-07-12 00:34:22 +1000 Jan Schmidt + + * gst/gstpad.c: + gstpad: Move sticky flag clearing code to gst_pad_activate_mode + The ghostpad code directly activates/deactivates the child code by + calling gst_pad_activate_mode, rather than gst_pad_set_active, so + make sure to clear the flags in gst_pad_activate_mode(), which should + catch all cases. + +2012-07-11 12:40:10 +0200 Wim Taymans + + * gst/gstevent.c: + event: improve annotation + +2012-07-11 12:37:05 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: handle step end correctly + when we have a new step event with a -1 amount, make sure that we follow the + regular code path so that the stop_end handler is called as usual. This takes + care of flushing the buffer in case of a flushing step and also posts a step end + message. + See https://bugzilla.gnome.org/show_bug.cgi?id=679378 + +2012-07-11 13:14:57 +0200 Sebastian Dröge + + * win32/common/libgstbase.def: + * win32/common/libgstnet.def: + win32: Fix exported symbols list for real now + +2012-07-11 11:21:18 +0200 Stefan Sauer + + * gst/gstsegment.c: + segment: remove removed api from the docs. + +2012-07-11 12:46:31 +0200 Sebastian Dröge + + * win32/common/libgstbase.def: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + win32: Updated exported symbols list + +2012-07-11 12:45:51 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + toc: Add functions to retrieve the parent GstToc/GstTocEntry of a GstTocEntry + +2012-07-10 18:15:20 +0300 Anton Belka + + * gst/gsttoc.c: + toc: Fix gst_toc_find_entry() + Recursive search for the required entry, instead of returning the + top-level entry that contains an entry with the search UID. + +2012-07-11 10:26:13 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: Push STREAM_START in pull-mode + +2012-07-11 10:24:51 +0200 Edward Hervey + + * gst/gststructure.c: + structure: Demote WARNING to DEBUG + It is not an issue to get fields that don't exist, calling code should + handle that. + +2012-07-10 11:46:41 +0200 Edward Hervey + + * gst/gst.c: + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstconfig.h.in: + * gst/gstdatetime.c: + * gst/gstdebugutils.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gsterror.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstiterator.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + * gst/gstparse.c: + * gst/gstparse.h: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstpoll.c: + * gst/gstpoll.h: + * gst/gstpreset.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gstsegment.c: + * gst/gstsegment.h: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + * gst/gsttoc.c: + * gst/gsttocsetter.c: + * gst/gsttrace.h: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + * gst/gstversion.h.in: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader-docs.h: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter-docs.h: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstindex.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstconsistencychecker.h: + * plugins/elements/gstdataqueue.c: + * plugins/elements/gstdataqueue.h: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + Remove 0.10-related documentation and "Since" markers + +2012-07-10 00:39:37 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesrc.c: + basesrc: provide fallback in case a create function doesn't know about provided buffers + In 0.11 the caller may provide a buffer to be filled by the source to + pull_range/get_range/create, but it's easy to miss this new case when + porting code from 0.10. Provide fallback that copies the created data + into the provided buffer for now. + This makes oggdemux in pull-mode work with dataurisrc. + +2012-07-10 10:31:00 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasetransform.c: + query: copy structure in _add_allocation_meta() + Make gst_query_add_allocation_meta() take a copy of the passed caps instead of + taking ownership. This makes it easier for the caller in most cases because it + doesn't have to make a copy and deal with NULL values. + +2012-07-10 10:11:57 +0200 Wim Taymans + + * gst/gst.c: + gst: add new flags + +2012-07-09 23:47:53 +0200 Matej Knopp + + * gst/gstminiobject.c: + miniobject: fix exclusive lock/unlock race + +2012-07-10 00:59:40 +0100 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + dataurisrc: copy into provided buffer if a buffer is provided + +2012-07-09 21:51:07 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gsttypefindelement.c: + basesrc, basesink, baseparse, typefind: use GST_SEGMENT_FLAG with segment flags + +2012-07-09 22:11:31 +0200 Stefan Sauer + + * gst/gstsegment.c: + * gst/gstsegment.h: + segment: also copy the segment flag + Fixes segmented seeks (as tested e.g. in the adder tests in base). + +2012-07-09 20:55:00 +0100 Tim-Philipp Müller + + * plugins/elements/gstdataqueue.h: + plugins: sprinkle G_GNUC_INTERNAL for dataqueue functions + And remove padding, since this is not public API any more. + +2012-07-09 20:48:56 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/parse/types.h: + gst: sprinkle some G_GNUC_INTERNAL for internal functions + +2012-07-09 20:09:55 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + tests: fix toc unit tests + Meant to check subsubentry, not subentry. + +2012-07-09 18:58:24 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttoc.c: + tests: minor toc test clean-up + +2012-07-09 18:51:37 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + tests: turn toc check macros into proper functions + So we can see the line number of the check that fails. + +2012-07-09 20:31:00 +0200 Edward Hervey + + * win32/common/libgstbase.def: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + win32: Update defs file for API changes/addition + +2012-07-09 20:29:29 +0200 Edward Hervey + + * tests/check/gst/gstbin.c: + * tests/check/gst/gstparamspecs.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/simple-launch-lines.c: + check: Update tests for new STREAM_START message + +2012-07-09 20:28:54 +0200 Edward Hervey + + * tests/check/gst/gstbin.c: + check: Ensure STREAM_START message is posted + A STREAM_START message is posted if and only if all sinks in the + bin/pipeline received the STREAM_START event + +2012-07-09 20:28:20 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Post a STREAM_START message when we see the event + +2012-07-09 20:27:44 +0200 Edward Hervey + + * gst/gstbin.c: + gstbin: collect and aggregate STREAM_START messages + when all sinks have posted a STREAM_START, the bin will forward a + new STREAM_START message to the parent bin or application + +2012-07-09 20:08:15 +0200 Edward Hervey + + * gst/gstmessage.c: + * gst/gstmessage.h: + * win32/common/libgstreamer.def: + gstmessage: New GST_MESSAGE_STREAM_START + message counterpart to the GST_EVENT_STREAM_START event + +2012-07-09 19:59:33 +0200 Edward Hervey + + * tests/check/gst/gstbin.c: + check: Unit test for EOS message + Make sure we get the aggregated message if and only if all sinks + received an EOS event + +2012-07-09 19:56:15 +0200 Stefan Sauer + + * libs/gst/base/gstcollectpads.c: + collectpads: add STREAM_START handling + Use a flag to forward the first STREAM_START + +2012-07-09 16:20:49 +0100 Tim-Philipp Müller + + * docs/design/part-caps.txt: + * docs/design/part-streams.txt: + docs: update stream docs for SEGMENT_START event + +2012-07-09 16:48:56 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: fix more docs + +2012-07-09 16:22:04 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstallocator.h: + docs: fix docs a little more + +2012-07-09 16:02:50 +0200 Wim Taymans + + * gst/Makefile.am: + * gst/gstallocator.c: + * gst/gstallocator.h: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/examples/memory/memory_test.c: + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-memory.h: + * tests/examples/memory/my-vidmem.c: + memory: Make GstAllocator a GstObject + Make GstAllocator a GstObject instead of a GstMiniObject, like bufferpool. + Make a new gstallocator.c file. Make a GstAllocator subclass for the default + allocator. + +2012-07-09 13:20:30 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: remove unused macros + +2012-07-09 13:20:05 +0200 Wim Taymans + + * gst/gstclock.c: + * tests/check/gst/gstclock.c: + clock: make abstract + Make the GstClock type abstract. + Fix a horrible hack in the clock unit test. + +2012-07-09 15:37:28 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + queue: Fix handling of min-threshold and serialized queries + Only consider the queue empty if the minimum thresholds + are not reached and data is at the queue head. Otherwise + we would block forever on serialized queries. + This also makes sending of serialized events, like caps, happen + faster and potentially improves negotiation performance. + Fixes bug #679458. + +2012-07-09 13:15:46 +0100 Tim-Philipp Müller + + * gst/gsttoc.c: + toc: remove padding now that the structs are private + +2012-07-09 13:12:27 +0100 Tim-Philipp Müller + + * gst/gsttoc.c: + * gst/gsttoc.h: + * tests/check/gst/gsttoc.c: + toc: add gst_toc_dump() function for debugging + API: gst_toc_dump() + +2012-07-03 00:07:11 +0100 Tim-Philipp Müller + + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstsystemclock.c: + * tests/check/gst/gstpipeline.c: + bus, clock: make sure these never have a floating ref + Clear the initial floating ref in the init function for + busses and clocks. These objects can be set on multiple + elements, so there's no clear parent-child relationship + here. Ideally we'd just not make them derive from + GInitiallyUnowned at all, but since we want to keep + using GstObject features for debugging, we'll just do + it like this. + This should also fix some problems with bindings, which + seem to get confused when they get floating refs from + non-constructor functions (or functions annotated to + have a 'transfer full' return type). This works now: + from gi.repository import GObject, Gst + GObject.threads_init() + Gst.init(None) + pipeline=Gst.Pipeline() + bus = pipeline.get_bus() + pipeline.set_state(Gst.State.NULL) + del pipeline; + https://bugzilla.gnome.org/show_bug.cgi?id=679286 + https://bugzilla.gnome.org/show_bug.cgi?id=657202 + +2012-07-08 20:15:33 +0200 Stefan Sauer + + * tools/gst-inspect.c: + inspect: suppress glib deprecations warnings for G_VALUE_ARRAY + +2012-07-07 23:13:20 +0100 Tim-Philipp Müller + + * tests/check/gst/gstvalue.c: + tests: add more tests for datetime value serialisation/deserialisation + Esp. of partial datetimes. + +2012-07-07 22:46:00 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: use datetime serialise/deserialise functions for datetimes + This re-uses existing code and makes sure we properly serialise + and deserialise datetimes where not all fields are set (thus + fixing some warnings when serialising such datetimes). + +2012-07-07 22:40:12 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: do our own serialisation so we can serialise microseconds as well + We still don't do that in _to_iso8601_string() though, since + this will probably mostly be used in tags, where it doesn't + matter so much and the microsecond argument might not be + well-received by some tag readers. + +2012-07-07 19:43:50 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: when deserialising parse microseconds if available + +2012-07-07 16:01:41 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: fix second parsing failure case when deserialising datetime + When we fail to parse the number of seconds, reset the value to -1 + instead of passing some error value as seconds. Also, we can still + try to parse timezone information. + +2012-07-07 15:44:57 +0100 Tim-Philipp Müller + + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-vidmem.c: + examples: fix debug log print formats in memory examples + +2012-07-07 01:37:50 +0200 Sebastian Rasmussen + + * gst/gstinfo.c: + gstinfo: Add destroy notify arguments to debug stubs + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=679535 + +2012-07-06 20:37:06 +0200 Sebastian Rasmussen + + * gst/gststructure.c: + gststructure: Set lcopy string const exactly as glib's macro + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=679534 + +2012-07-06 17:19:21 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-vidmem.c: + memory: expose the GstAllocation structure + Expose the GstAllocation structure and provide an _init function. This makes it + easier to make 'subclasses' of the allocator that contain more info. + It also allows us to expose the flags on the allocator miniobject. + Make a flag to note that the allocator uses a custom alloc function. + +2012-07-06 12:45:29 +0200 Edward Hervey + + * gst/gststructure.c: + structure: Demote WARNING to INFO + It is common to use gst_structure_get() to know if a field is present + or not. + +2012-07-06 11:41:52 +0200 Edward Hervey + + * tools/gst-inspect.c: + gst-inspect: Remove unused define + +2012-07-06 11:41:33 +0200 Edward Hervey + + * tests/check/libs/libsabi.c: + check: gstcontroller.h doesn't exist anymore + +2012-07-06 11:40:47 +0200 Edward Hervey + + * tests/check/libs/basesrc.c: + check: Use consistencycheck on basesrc + +2012-07-06 11:38:58 +0200 Edward Hervey + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: Check for STREAM_START event + Check that it is always before any serialized event. + +2012-07-06 10:13:28 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefindelement: remove unimplemented maximum property + +2012-07-06 10:09:55 +0100 Tim-Philipp Müller + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + tee: remove unimplemented has-sink-loop property + +2012-07-06 10:07:56 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: remove deprecated temp-location use, make it read-only + +2012-07-06 09:57:52 +0100 Tim-Philipp Müller + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: remove deprecated check-perfect property + Replaced by the more specific check-imperfect-{timestamp,offset} + +2012-07-06 11:49:47 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + query: use more generic structure for meta params + +2012-07-06 11:22:43 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: + * gst/gstquery.h: + query: make find_allocation_meta method + Make gst_query_find_allocation_meta() that also return the index of the metadata + and replaces gst_query_has_allocation_meta(). + +2012-07-06 11:00:38 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + query: add flags to allocation query + Make it possible to add API specific flags to the ALLOCATION query. This makes + it possible to also check what kinds of subfeatures of the metadata API are + supported. + +2012-07-06 09:11:48 +0200 Wim Taymans + + * tests/examples/memory/memory_test.c: + tests: remove unused includes + +2012-07-05 18:07:52 +0200 Wim Taymans + + * tests/examples/memory/Makefile.am: + * tests/examples/memory/memory_test.c: + * tests/examples/memory/my-memory.h: + * tests/examples/memory/my-vidmem.c: + * tests/examples/memory/my-vidmem.h: + memory: add more examples + Add an example of a custom allocator with a custom API. + +2012-07-05 17:11:01 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/examples/memory/Makefile.am: + * tests/examples/memory/memory_test.c: + * tests/examples/memory/my-memory.c: + * tests/examples/memory/my-memory.h: + memory: add gst_memory_init() + Add a method that memory implementations can call to initialize the standard + GstMemory structure. + Move the parent handling in the _free handler. + Rearrange some internal function parameters so that the order is consistent. + Add more memory examples + +2012-07-05 16:17:53 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: fix some miniobject docs + +2012-07-05 14:25:13 +0200 Wim Taymans + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/memory/.gitignore: + * tests/examples/memory/Makefile.am: + * tests/examples/memory/memory_test.c: + tests: add memory example + +2012-07-05 12:25:45 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttoc.c: + tests: fix toc unit test build by removing toc query stuff there too + +2012-07-05 13:03:10 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * win32/common/libgstreamer.def: + event: Add format and position to the segment-done event + +2012-07-05 12:53:57 +0200 Wim Taymans + + * docs/design/part-buffer.txt: + * docs/design/part-memory.txt: + * docs/design/part-miniobject.txt: + docs: update docs + +2012-07-05 12:17:55 +0200 Wim Taymans + + * gst/gstminiobject.h: + miniobject: increase amount of possible flags + +2012-07-05 12:52:51 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + event: Implement segment-done event + +2012-07-05 12:37:01 +0200 Sebastian Dröge + + * docs/design/part-toc.txt: + part-toc: Remove section about TOC query + +2012-07-05 12:34:43 +0200 Sebastian Dröge + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + win32: Update exported symbols list + +2012-07-05 12:31:58 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: + * gst/gstquery.h: + query: Remove the TOC query, it's not very useful now that we have sticky events + +2012-07-03 18:49:18 +0200 Sebastian Dröge + + * gst/gstquark.c: + * gst/gstquark.h: + quark: Remove unneeded quarks + +2012-07-03 18:45:05 +0200 Sebastian Dröge + + * docs/design/part-toc.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + * tools/gst-launch.c: + * win32/common/libgstbase.def: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + toc: Make structures opaque and clean up function names and fields a bit + +2012-07-04 17:02:09 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer:fix debug category + +2012-07-04 16:38:15 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstevent.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + * gst/gstsample.c: + * gst/gsttaglist.c: + * gst/gsttoc.c: + * tests/check/gst/gstmemory.c: + * win32/common/libgstreamer.def: + miniobject: add lock functionality to GstMiniObject + Move the locking methods from GstMemory to GstMiniObject. + Add a miniobject flag to enable LOCKABLE objects. LOCKABLE objects can + use the lock/unlock API to control the access to the object. + Add a minobject flag that allows you to lock an object in readonly mode. + Modify the _is_writable() method to check the shared counter for LOCKABLE + objects. This allows us to control writability separately from the refcount for + LOCKABLE objects. + +2012-07-04 16:04:28 +0200 Wim Taymans + + * gst/gst_private.h: + * gst/gstinfo.c: + info: add new locking debug category + +2012-07-04 12:28:56 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: fix is_exclusive + +2012-07-04 12:03:32 +0200 Wim Taymans + + * gst/gstmemory.h: + memory: add LOCK_FLAG_READWRITE define + +2012-07-04 11:48:37 +0200 Wim Taymans + + * docs/design/part-memory.txt: + memory: update docs + +2012-07-04 10:12:43 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: small cleanup + +2012-07-03 13:50:06 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * win32/common/libgstreamer.def: + update for new symbols + +2012-07-03 13:47:49 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: Fix the NO_SHARE flag in the constructor + The NO_SHARE flag does not influence the exclusiveness of the buffer initially + but only if a _share operation can be done. Otherwise, we would not be able to + WRITE map a buffer memory because it would have a share count of at least 2. + +2012-07-03 13:47:30 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: only check the locking refcount + +2012-07-03 13:46:40 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: fix resize + Correctly update the exclusive locks + +2012-07-03 13:45:03 +0200 Wim Taymans + + * gst/gstmemory.h: + memory: Use lock flags for map flags + We implement the locking in gst_memory_map with the lock flags, make matching + flags the same number so that we can use the map flags directly as lock flags. + +2012-07-03 12:18:02 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: lock memory EXCLUSIVE + lock the memory that the buffer references as EXCLUSIVE. This makes sure that + when we share the memory with other buffers that it becomes unwritable. + +2012-07-03 12:16:19 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: cleanup the locking code + cleanup and fix the locking code + +2012-07-03 09:48:32 +0200 Wim Taymans + + * docs/design/part-memory.txt: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: expose the internal locking api + Expose the internally used methods for locking and unlocking the object. Pass + the access mode to the unlock function for extra checks and because we need it + for the EXCLUSIVE locks. + Make some new defines to specify the desired locking. + Add a new EXCLUSIVE lock mode which will increment the shared counter. Objects + with a shared counter > 1 will not be lockable in WRITE mode. + +2012-06-29 16:37:05 +0200 Mark Nauwelaerts + + * tests/check/gst/gstbuffer.c: + tests: gstbuffer: extend buffer copy test + ... to check for independence of copied buffer. + +2012-07-04 18:32:47 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: remove outdated bits of warning message + I think we can be reasonable sure people are using an up-to-date + gst-uninstalled script now. + +2012-07-04 18:16:23 +0100 Tim-Philipp Müller + + * gst/gstpluginloader.c: + * gst/gstregistry.c: + Add versioned variants of some environment variables + Improve parallel installability in setups like jhbuild by + providing versioned variants of some environment variables: + GST_REGISTRY_1_0 + GST_PLUGIN_PATH_1_0 + GST_PLUGIN_SYSTEM_PATH_1_0 + GST_PLUGIN_SCANNER_1_0 + will now be checked before checking the unversioned ones. + https://bugzilla.gnome.org/show_bug.cgi?id=679407 + +2012-07-04 17:55:58 +0100 Tim-Philipp Müller + + * gst/gstsample.h: + docs: fix typo in GstSample docs + +2012-07-04 17:36:55 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + * tests/check/gst/gsturi.c: + uri: there are valid URI protocols with only two letters, like fd:// + We added a minimum length of three letters originally so we would + fail to recognise DOS/Windows-style filenames as valid URIs (as we + should). Two should be just fine as well. + +2010-10-13 13:36:08 +0200 Edward Hervey + + * win32/common/libgstbase.def: + win32: API additions + +2009-09-29 09:54:24 +0200 Edward Hervey + + * plugins/elements/gstdataqueue.c: + * plugins/elements/gstdataqueue.h: + dataqueue: Use GstQueueArray + +2009-09-28 17:31:49 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: Use new GstQueueArray for local storage. + Makes _chain() and _loop() 25% faster + +2009-09-29 09:06:13 +0200 Edward Hervey + + * tests/check/Makefile.am: + * tests/check/libs/queuearray.c: + check: New unit test for GstQueueArray + +2009-09-28 17:30:04 +0200 Edward Hervey + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstqueuearray.c: + * libs/gst/base/gstqueuearray.h: + * win32/common/libgstbase.def: + libs: New growing-only queue. + This is a queue which has the same API as GQueue, except that: + * It uses an array, instead of a doubled-linked-list + * The array can only grow. + This code is not-threadsafe. It is up to the owner to make sure the + proper locking is taken before calling this API. + +2012-07-04 16:16:04 +0100 Tim-Philipp Müller + + * docs/design/part-segments.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + segment: make sure we don't have unmapped seek flags littering out segment flags + Make GstSeekFlag to GstSegmentFlag conversion explicit, and + set only those seek flags in the segment flags which are + mapped. This makes sure we don't have extraneous flags + littering our segment flag field, which also fixes the + debug printing/serialisation of segment events in the + debug log. + +2012-07-04 10:24:11 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: minor porting-to-0.11.txt update + +2012-07-04 10:23:06 +0100 Tim-Philipp Müller + + * tests/check/gst/gstdatetime.c: + tests: make checks for from/to_g_date_time() actually work properly + +2012-06-29 21:52:47 -0400 Joshua M. Doe + + * docs/gst/gstreamer-sections.txt: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * tests/check/gst/gstdatetime.c: + * win32/common/libgstreamer.def: + datetime: add conversion to/from GDateTime + Exposes existing constructor. + API: gst_date_time_to_g_date_time() + API: gst_date_time_new_from_g_date_time() + https://bugzilla.gnome.org/show_bug.cgi?id=679080 + +2012-07-04 08:52:08 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: remove unused gst_print_* functions + +2012-07-03 22:24:22 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pads: no need to deactivate pads that are already in PAD_MODE_NONE + +2012-07-03 22:20:40 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstpad.c: + pads: make pad activation debug logs a bit more readable + +2012-07-03 19:15:25 +0100 Tim-Philipp Müller + + * tests/check/elements/fakesrc.c: + tests: add unit test for element re-use using fakesrc + +2012-07-03 19:04:54 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pad: clear EOS flag when deactivating pads fixing element re-use + +2012-07-03 17:25:21 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Post TOC messages on the bus in the sinks, similar to tags + +2012-07-03 12:38:55 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: fix the _get_mapped function + Fix the internal _get_mapped function. gst_memory_make_mapped() takes ownership + of the memory so we need to keep an additional ref until we are done. + +2012-07-03 12:23:36 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add more debug log + +2012-07-03 10:02:55 +0200 Sebastian Dröge + + * gst/gstevent.h: + event: The GAP event is (partially) implemented now, STREAM_CONFIG isn't + +2012-06-28 16:42:08 +0800 Chun-wei Fan + + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + controlbindings: include gst/math-compat.h for isnan() + Due to the usage of isnan(), where an implementation is added into + gst/math-compat.h. Fixes build on Visual C++. + https://bugzilla.gnome.org/show_bug.cgi?id=679112 + +2012-06-29 16:52:31 +0800 Chun-wei Fan + + * gst/math-compat.h: + math-compat.h: add implementation for isnan() for Visual C++ + Visual C++ does not have isnan(), so add fallback to + math-compat.h (could use _isnan() in this case, but + this makes it work for all cases where isnan is missing). + https://bugzilla.gnome.org/show_bug.cgi?id=679112 + +2012-06-29 10:56:34 +0800 Chun-wei Fan + + * plugins/elements/gstfdsink.c: + fdsink.c: fix G_OS_WIN32 #ifdef + Postpone the #ifdef to a point after glib.h (via gstfdsink.h) is included + so that the needed defines and header includes can be done correctly, + especially on Visual C++ builds. + https://bugzilla.gnome.org/show_bug.cgi?id=679112 + +2012-05-27 23:09:43 +0300 Raimo Järvi + + * tests/check/gst/gstdatetime.c: + tests: fix build of datetime unit test in Windows + Also include config.h for all the #ifdef HAVE_XYZ. + https://bugzilla.gnome.org/show_bug.cgi?id=676935 + +2012-06-29 11:19:07 +0200 Wim Taymans + + * gst/gstobject.c: + gstobject: don't use g_strdup_value_contents() + g_strdup_value_contents() does some extra escaping, preventing us from using the + output on the console to be used directly. + +2012-06-28 14:41:43 +0100 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: expand a bit more on GST_DEBUG docs + +2012-06-28 11:02:19 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add _append_region function + Make a gst_buffer_append_region() function that allows you to append a memory + region from one buffer to another. This is a more general version of + gst_buffer_append(). + +2012-06-28 09:36:34 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle DTS and PTS + Use DTS and PTS of the subclass. + Calculate PTS from DTS on keyframes. + +2012-06-27 23:01:13 +0100 Tim-Philipp Müller + + * tests/check/gst/gstdatetime.c: + tests: test datetime deserialisation a bit more + +2012-06-27 23:00:08 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: ignore 0 days or months in dates + Handle 0 months or days correctly in date strings, so that + 2012-06-00 is parsed the same as 2012-06, for example. + +2012-01-01 16:38:08 +0100 Idar Tollefsen + + * configure.ac: + * m4/check-checks.m4: + build: Make sure AC_INCLUDES_DEFAULT is used + Without using AC_INCLUDES_DEFAULT explicitly, + certain platforms will complain that the header + was found, but not usable by the compiler. + This happens for instance on Solaris where certain + headers are needed to pull in proper defines. + Also upgrade to newer autoconf syntax and use proper quoting. + https://bugzilla.gnome.org/show_bug.cgi?id=667293 + +2012-06-27 20:52:52 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + tests: fix bus leak in GstBin test_state_change_skip test + Still not valgrind clean though. + +2012-06-27 19:59:29 +0100 Christophe Fergeau + + * gst/gstparse.c: + parse: escape \ with a \ as well, so that we don't lose the \ when unescaping + If we have a file called Foo\Bar.ogg, there is no way to pass + that filename properly to filesrc in gst_parse_launch(), since + gst_parse_unescape() will just unescape \x to x. + Not cherry-picking this into 0.10 since there are apparently + apps that work around this problem and which would break if + we fixed it there too. + https://bugzilla.gnome.org/show_bug.cgi?id=673319 + +2012-06-27 16:37:54 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.h: + elementfactory: annotate some of the type defines for g-i + Type is not picked up yet though, and we still need + to annotate values for the 'simple' defines. + https://bugzilla.gnome.org/show_bug.cgi?id=677925 + +2012-06-27 14:48:55 +0100 Tim-Philipp Müller + + * gst/gstclock.h: + clock: annotate GST_CLOCK_TIME_NONE with its value for g-i + The value now gets picked up, but it still thinks the type + is a 'gint'. + https://bugzilla.gnome.org/show_bug.cgi?id=678928 + +2012-06-27 13:19:23 +0100 Tim-Philipp Müller + + * tests/check/gst/gstdatetime.c: + tests: add some datetime serialisation/deserialisation tests + https://bugzilla.gnome.org/show_bug.cgi?id=678031 + +2012-06-27 13:16:07 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstdatetime.c: + * gst/gstvalue.c: + datetime: fix compare function + Take into account that not all fields might be valid (though they + are valid in the GDateTime structure). But we should just return + unordered if the set fields don't match. Also, don't check + microseconds when comparing datetimes, since we don't serialise + those by default if they're available. This ensures date times are + still regarded as equal after serialising+deserialising. + +2012-06-18 08:06:49 +0200 Oleksij Rempel + + * docs/gst/gstreamer-sections.txt: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * win32/common/libgstreamer.def: + datetime: add serialisation to and deserialisation from ISO 8601 strings + Some tag parsers and writers use same datetime format based on ISO 8601. + We can reduce some code by creating some general functions for it. + API: gst_date_time_to_iso8601_string() + API: gst_date_time_new_from_iso8601_string() + https://bugzilla.gnome.org/show_bug.cgi?id=678031 + +2012-06-07 11:30:48 +0100 Lionel Landwerlin + + * Makefile.am: + * configure.ac: + * tests/Makefile.am: + configure: add --disable-tools and --disable-benchmarks options + Add option to avoid build binaries. When building for platforms like + android, you might want to not link any "final" binary, mostly because + it requires special link flags or other parts of code that aren't + in the C library. + https://bugzilla.gnome.org/show_bug.cgi?id=677621 + +2012-06-26 20:41:18 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gsttoc.c: + * tests/check/gst/gsttoc.c: + toc: put toc directly into event/message/query structure + Now that TOCs are refcounted and have a GType, we can just + stuff a ref of the TOC directly into the various toc + event/message/query structures and get rid of lots of + cracktastic GstStructure <-> GstToc serialisation and + deserialisation code. We lose some TOC sanity checking + in the process, but that should really be done when + it's being created anyway. + +2012-06-26 18:22:33 +0100 Tim-Philipp Müller + + * gst/gstbus.c: + Revert "bus: skip gst_bus_create_watch as GSource is not introspectable" + This reverts commit 930e36a89bc5c2a0f2e4ab7a73bfa630c1e0336a. + This shouldn't have been pushed, since GSource is now handled + (https://bugzilla.gnome.org/show_bug.cgi?id=657725) + +2011-08-29 13:57:03 -0300 Johan Dahlin + + * gst/gstbus.c: + bus: skip gst_bus_create_watch as GSource is not introspectable + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2012-06-26 17:35:22 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: some more additions to the porting-to-0.11 guide + +2012-06-26 17:27:31 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/tools.h: + tools: minor clean-up + Get rid of superfluous argument. + +2012-06-26 17:04:01 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/tools.h: + tools: remove useless g_set_prgname() wrapper + +2012-06-26 16:55:30 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: point people to right binary when a crash happens + "gst-launch" is the 0.10 wrapper script, using that with + gdb is not going to yield great results. + +2012-06-26 16:42:36 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump GLib requirement to now-released stable version + +2012-06-26 16:42:10 +0100 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + inputselector: remove some dead code for old GLib versions + +2012-06-25 23:17:32 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + * win32/common/libgstreamer.def: + toc: add more entry types + Make entry types less abstract. + https://bugzilla.gnome.org/show_bug.cgi?id=678742 + +2012-06-17 12:48:04 +1000 Jan Schmidt + + * docs/random/porting-to-0.11.txt: + a couple of notes for the 0.11 porting guide + +2012-06-26 09:51:10 +0200 Wim Taymans + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * win32/common/libgstreamer.def: + miniobject: add steal_qdata + Rework the qdata code a little + +2012-06-25 19:52:44 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + * tests/check/gst/gsttocsetter.c: + * win32/common/libgstreamer.def: + tocsetter: clean up and update API for refcounted TOCs + Let's keep it simple for now: + gst_toc_setter_reset_toc() -> gst_toc_setter_reset() + gst_toc_setter_get_toc_copy() -> removed + gst_toc_setter_get_toc() -> returns a ref now + gst_toc_setter_get_toc_entry_copy() -> removed, + use TOC functions instead + gst_toc_setter_get_toc_entry() -> removed, + use TOC functions instead + gst_toc_setter_add_toc_entry() -> removed, + to avoid problems with (refcount-dependent) + writability of TOC; use TOC functions instead + +2012-06-25 09:32:41 +0200 Wim Taymans + + * gst/gstmemory.h: + memory: improve docs + Mention that custom allocator functions can pass whatever they want to the + user_data. + +2012-04-06 18:00:33 +0400 Alexander Saprykin + + * gst/gsttagsetter.c: + tagsetter: use G_DEFINE_INTERFACE_* macro + https://bugzilla.gnome.org/show_bug.cgi?id=673641 + +2012-04-06 17:59:35 +0400 Alexander Saprykin + + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + tocsetter: use G_DEFINE_INTERFACE_* macro + https://bugzilla.gnome.org/show_bug.cgi?id=673641 + +2012-06-25 00:10:53 +0100 Tim-Philipp Müller + + * docs/design/part-toc.txt: + docs: update design docs for TOC API changes too + +2012-06-24 20:10:34 +0100 Tim-Philipp Müller + + * gst/gsttocsetter.c: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + * tools/gst-launch.c: + tocsetter, gst-launch, tests: update for GstToc API changes + +2012-06-24 20:08:33 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + * win32/common/libgstreamer.def: + toc: make GstToc and GstTocEntry mini objects + Because we can, and in order to make them refcounted. + +2012-06-23 21:42:58 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: fix confusing log message + +2012-06-23 21:35:33 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + value: fix int64 - int64 range intersection on big endian systems + Works better if we use the v_int64 field of the GValue instead of v_int. + +2012-06-23 19:56:12 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + * gst/gstsample.c: + * gst/gsttaglist.c: + miniobjects: pass copy, dispose and free function to gst_mini_object_init() + So mini objects don't have to poke into the GstMiniObject part + of the structure. Saves lines of code, and seems slightly cleaner. + We don't have proper OO hierarchies or methods here after all. + +2012-06-23 17:05:05 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: remove some outdated FIXMEs and comments + +2012-06-23 17:04:53 +0100 Tim-Philipp Müller + + * gst/gstsample.c: + sample: some more g-i annotations + +2012-06-23 16:59:10 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + * tests/check/gst/gsttag.c: + sample: add compare function for GstSample + Should make gst_tag_list_is_equal() work properly with image tags. + https://bugzilla.gnome.org/show_bug.cgi?id=672637 + +2012-06-23 16:30:03 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + value: fix buffer compare function + +2012-06-23 14:41:50 +0100 Tim-Philipp Müller + + * tests/check/gst/gsturi.c: + tests: add unit test for gst_element_make_from_uri() + https://bugzilla.gnome.org/show_bug.cgi?id=645467 + +2012-06-23 14:41:17 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: update for gst_element_make_from_uri() change + +2012-06-23 14:40:17 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + * gst/gsturi.h: + uri: add error argument to gst_element_make_from_uri() + So callers can differentiate between there not being a + handler for the protocol, and them not accepting the URI + for some reason. + https://bugzilla.gnome.org/show_bug.cgi?id=645467 + +2012-06-23 12:37:16 +0100 Tim-Philipp Müller + + * gst/gstmemory.h: + memory: annotate GstMapInfo data as array for g-i + +2012-06-20 12:53:04 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: remove pointless get_state() in gst-launch + State changes to NULL state are always sync. + +2012-06-21 01:28:43 -0300 Thiago Santos + + * plugins/elements/gstinputselector.c: + inputselector: avoid notify-tags holding lock + unlock before issuing this notification to prevent + deadlocks when other elements reacts to new tags. + Fixes #678220 + +2012-06-18 16:54:29 -0300 Thiago Santos + + * scripts/gst-uninstalled: + gst-uninstalled: add gst-p-bad gst-libs to the path + Makes videoparsers and camerabins from bad usable from an uninstalled + environment at osx + +2012-06-20 13:28:08 +0200 Wim Taymans + + * gst/gstinfo.c: + * gst/gstinfo.h: + * tests/check/gst/gstinfo.c: + info: add destroy notify to gst_debug_add_log_function() + +2012-06-20 13:27:33 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve introspection annotation + +2012-06-20 12:29:35 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstbus.h: + * tests/check/generic/sinks.c: + * tests/check/gst/gstbin.c: + * tests/examples/streams/rtpool-test.c: + * tests/examples/streams/stream-status.c: + * tools/gst-launch.c: + bus: add GDestroyNotify to set_sync_handler() + +2012-06-20 12:06:11 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-06-20 11:59:09 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gsttask.c: + * gst/gsttask.h: + task: add separate methods to add enter/leave callback + Remove the structure of callbacks and replace with separate methods to register + each callback. This is much more binding friendly. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677898 + +2012-06-20 10:31:49 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gsttask.c: + * gst/gsttask.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gsttask.c: + task: add GDestroyNotify to _new + Add a GDestroyNotify to the user_data we pass to gst_task_new() + Change gst_pad_start_task() to also take the notify + +2012-06-20 09:58:14 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstmeta.c: + * tests/check/gst/gstsystemclock.c: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + clock: remove _full version + Rename gst_clock_id_wait_async_full() to gst_clock_id_wait_async() + and remove the old gst_clock_id_wait_async() version. + +2012-06-20 09:22:40 +0200 Wim Taymans + + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimepacket.h: + nettimepacket: make boxed + +2012-06-19 19:55:30 -0700 Evan Nemerson + + * libs/gst/net/gstnettimepacket.c: + net: fix some argument names in documentation + +2012-06-19 19:55:02 -0700 Evan Nemerson + + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + controller: assorted minor introspection fixes + +2012-06-19 19:53:54 -0700 Evan Nemerson + + * libs/gst/check/gstcheck.c: + check: add some missing documentation, including annotations + +2012-06-19 18:41:04 -0700 Evan Nemerson + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.c: + base: add some missing introspection annotations + +2012-06-19 17:37:59 -0700 Evan Nemerson + + * gst/gsttaskpool.c: + task pool: set scope of gst_task_pool_push callback to async + +2012-06-19 17:33:45 -0700 Evan Nemerson + + * gst/gstatomicqueue.c: + * gst/gstbuffer.c: + * gst/gstelementfactory.c: + * gst/gsttaskpool.c: + introspection: add missing return value annotations + +2012-06-19 16:09:10 -0700 Evan Nemerson + + * gst/gstbus.h: + * gst/gstinfo.h: + * gst/gstminiobject.h: + * gst/gsttask.h: + * gst/gsttaskpool.h: + * gst/gsttypefind.h: + introspection: rename some "data" arguments to "user_data" + GObject Introspection will automatically treat "user_data" arguments + as closure data. + +2012-06-19 16:08:46 -0700 Evan Nemerson + + * gst/gsttoc.h: + toc: add some missing element-type annotations + +2012-06-19 16:06:49 -0700 Evan Nemerson + + * gst/gstbufferpool.h: + buffer pool: put GstBufferPoolAcquireParams typedef before struct + Works around https://bugzilla.gnome.org/show_bug.cgi?id=581525 + +2012-06-19 16:14:46 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: preroll and sync on gap events + +2012-06-19 16:08:00 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: reorganize the code a little + Move the code to get the sync times together. + +2012-06-19 14:30:37 +0100 Sebastian Dröge + + * gst/gstmemory.h: + memory: Fix docs typo + +2012-06-19 14:05:21 +0200 Wim Taymans + + * gst/gstclock.h: + clock: assert about timestamp overflows + Assert when converting to timeval and timespec about overflows. This can happen + on platforms with 32bits long. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=678181 + +2012-06-19 10:13:15 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: remove gst_pad_set_caps + +2012-06-19 10:32:10 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Only proxy the allocation query for the active pad and send reconfigure events to the old/new pad when switching pads + +2012-06-18 16:14:19 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstcompat.h: + * gst/gstpad.c: + * gst/gstpad.h: + pad: move gst_pad_set_caps() to compat + We want code to explicitly send a caps event instead. + +2012-06-18 16:13:22 +0200 Wim Taymans + + * gst/gstutils.c: + utils: fix some docs + +2012-06-18 15:52:05 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: small doc fix + +2012-06-18 15:28:20 +0200 Sebastian Rasmussen + + * gst/gstclock.h: + clock: fix compiler warning + Cast to the right value, it might indeed overflow but we want the compiler to + ignore that. + +2012-06-18 15:22:26 +0200 Wim Taymans + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + miniobject: hide qdata array layout + +2012-06-18 15:21:31 +0200 Wim Taymans + + * docs/design/part-meta.txt: + docs: clarify qdata wrt to metadata + +2012-06-18 15:21:12 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update for new api + +2012-06-15 16:56:46 -0700 Evan Nemerson + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbytewriter.c: + introspection: assorted introspection and documentation fixes in base + +2012-06-15 18:35:05 -0700 Evan Nemerson + + * libs/gst/base/gstadapter.c: + adapter: add missing element-type annotations + +2012-06-15 16:14:49 -0700 Evan Nemerson + + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + atomic queue: register as boxed type + +2012-06-15 16:43:30 -0700 Evan Nemerson + + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + * gst/gstclock.c: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstevent.c: + * gst/gstobject.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstpipeline.c: + * gst/gsttaglist.c: + * gst/gstutils.c: + introspection: assorted introspection and documentation fixes + These changes are to clean up syntax issues such as missing colons, + missing spaces, etc., and minor issues such as argument names in + headers not matching the implementation and/or documentation. + +2012-06-15 14:50:48 -0700 Evan Nemerson + + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + toc setter: change GstTocSetterIFace to GstTocSetterInterface + Without this GObject Introspection does not recognize the connection + to GstTocSetter. + +2012-06-18 12:15:57 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: update docs a little + +2012-06-18 11:36:25 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * win32/common/libgstbase.def: + basesink: wait_eos() -> wait() + Rename gst_base_sink_wait_eos() to gst_base_sink_wait() to avoid confusion and + introspection problems with the ::wait_eos vmethod. Also this method can be used + to wait for other things than EOS. Update the docs a little. + +2012-06-18 10:13:38 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool:check caps argument + Caps should be NULL or fixed when configured in a bufferpool + +2012-06-15 17:01:37 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: NULL is not a valid caps anymore + +2012-06-15 15:48:42 +0200 Wim Taymans + + * docs/design/part-buffering.txt: + docs: review the buffering docs + +2012-06-15 15:36:41 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix percent scaling + Use _scale functions to scale the percent values. + Correctly scale the percent values in the buffering ranges. + +2012-06-15 14:54:48 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: avoid flush when starting + When we are doing the initial seek in startup, avoid doing a flush + (and unlock) because we know that the task is not started yet. + +2012-06-15 12:58:10 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-06-15 12:55:20 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstelementfactory.c: + * gst/gstevent.c: + * gst/gstghostpad.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstpad.c: + * gst/gstquery.c: + * gst/gstquery.h: + docs: improve API docs + +2012-06-15 00:00:12 +0100 Tim-Philipp Müller + + * gst/gstmemory.c: + alllocator: no need to store structure size inside the structure + +2012-06-14 23:54:22 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + query: no need to store the size of the structure inside the structure + +2012-06-14 23:52:41 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + event: no need to store the size of the structure inside the structure + +2012-06-14 23:49:10 +0100 Tim-Philipp Müller + + * gst/gstbufferlist.c: + bufferlist: no need to store the size of the structure inside the structure + +2012-06-14 23:45:14 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: no need to store the size of the caps structure inside the structure + +2012-06-14 23:41:57 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + message: no need to store size of the message structure inside the structure + +2012-06-14 23:38:54 +0100 Tim-Philipp Müller + + * gst/gstsample.c: + sample: no need to store the size of the sample structure inside the structure + +2012-06-14 23:36:29 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: no need to store the size of the tag list structure inside the structure + +2012-06-15 11:24:46 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: expand docs a little + Add blurb about qdata and weak refs. + +2012-06-15 10:44:24 +0200 Wim Taymans + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * win32/common/libgstreamer.def: + miniobject: add qdata + Keep track of qdata for miniobjects. Reuse the weak ref array for this because + we can. + +2012-06-15 10:56:13 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: fix error in the weak ref handling + When 2 weak refs are added, the array is not resized big enough. + Simplify the weak ref handling code. + Free memory when we remove all weak refs. + Allow installing the same weak ref multiple times, like in gobject. + +2012-06-14 17:11:11 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + * gst/gstsample.c: + * gst/gsttaglist.c: + miniobject: remove the size field + The size field is used by subclasses to store the total allocated size of the + memory for this miniobject. Because miniobject doesn't really do anything with + this field we can move it to the subclasses. + +2012-06-14 16:30:12 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/check/gstcheck.h: + * tests/check/gst/gstmemory.c: + * win32/common/libgstreamer.def: + memory: make GstMemory a miniobject + +2012-06-14 16:27:26 +0200 Wim Taymans + + * gst/gsttrace.c: + trace: always print miniobject refcount + +2012-06-14 15:40:43 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: fix copy function + Make the copy function map to ref because we can't safely copy the user_data. + +2012-06-14 15:33:50 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + memory: make GstAllocator a miniobject + +2012-06-12 13:26:35 +0200 David Svensson Fors + + * plugins/elements/gstfunnel.c: + gstfunnel: avoid access of freed pad + Save the value of the pad's got_eos in gst_funnel_release_pad, + before calling gst_element_remove_pad. This is because + gst_element_remove_pad may free the pad. + https://bugzilla.gnome.org/show_bug.cgi?id=678017 + +2012-06-14 14:05:15 +0100 Vincent Penquerc'h + + * gst/gstelement.c: + element: fix pad transfer annotation from none to full + since the pad will be unreffed. + +2012-06-13 10:52:48 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * libs/gst/base/gstbasesink.c: + message: add the running-time to the async-done message + Add the running-time of the buffer that caused the async operation to complete + to the async-done message. + Update bin to handle the new async-done message. + +2012-06-13 10:51:04 +0200 Wim Taymans + + * gst/gstpipeline.c: + * libs/gst/base/gstbasesink.c: + pipeline: use reset_time message to reset the start time + Use the new RESET_TIME message to reset the start-time of the pipeline to the + requested time. + Make basesink request a new running-time when the flush-stop message tells it to + insteasd of waiting for preroll. + +2012-06-13 10:16:27 +0200 Wim Taymans + + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + message: add a new message to reset time + Add a new message to reset the pipeline running_time. Currently reseting the + pipeline can only be requested in the async_done message which means that the + pipeline needs to be prerolled. It is better to move this to a separate message. + +2012-06-12 17:11:51 +0200 Wim Taymans + + * gst/gstbin.c: + bin: always recurse into bins when doing state changes + Never skip the state change of a bin because it needs to update the base time of + its children when needed. + +2012-06-13 00:30:48 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: update for new datetime api + +2012-06-13 00:28:00 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for latest API + +2012-06-13 00:25:24 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: add new datetime API + +2012-06-13 00:21:32 +0100 Tim-Philipp Müller + + * tests/check/gst/gstdatetime.c: + tests: add some basic unit tests for partial date time fields + +2012-06-12 23:52:02 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + * gst/gstdatetime.h: + datetime: clean-ups and new API adjustments + Remove constructors we don't want: + gst_date_time_new_ymd_h() because we don't want to + support hour-only for now; + gst_date_time_new_ymd_hm() because we don't want to + add constructors with time info where the caller doesn't + have to think about what timezone the time is in. + Lots of compulsive clean-up. Docs fixes. Replace + has_minute() and has_hour() with has_time(). + +2012-06-12 22:35:42 +0200 Oleksij Rempel + + * gst/gstdatetime.c: + * gst/gstdatetime.h: + datetime: allow GstDateTime where not all fields are set + In order to deserialise and re-serialise dates and date times + from tags properly, we need to be able to express partial + dates (e.g. YYYY or YYYY-MM) and date times. + We only support partial date times where all the more + significant fields above the first unset field are set + (e.g. YYYY-00-DD is not supported). + Calling _get_foo() when foo is not set is not allowed + any more, callers need to check which fields are set + first. + https://bugzilla.gnome.org/show_bug.cgi?id=677757 + +2012-06-12 22:45:09 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + * gst/gstquark.c: + * gst/gstquark.h: + message: fix up minor inconsistency in structure name of state-changed message + +2012-06-12 11:42:30 -0700 Evan Nemerson + + * gst/gstbin.h: + * gst/gstclock.h: + * gst/gstelement.h: + * gst/gstobject.c: + * gst/gstpadtemplate.h: + introspection: add some missing annotations + +2012-06-12 14:24:27 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle flush events on the element as well + Handle flush-start and flush-stop sent on the element as well and send them + downstream. Make sure to send a segment event after the flush stop. + +2012-06-12 11:05:05 +0200 Stefan Sauer + + * gst/gstchildproxy.c: + childproxy: add a few more comments + +2012-06-11 20:34:00 +0200 Stefan Sauer + + * gst/gstchildproxy.h: + childproxy: fix signal handler signatures in class + When adding the name parameter, we forgot to add it here too. + +2012-06-11 10:59:49 +0200 Stefan Sauer + + * gst/gstbin.c: + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + * tests/check/gst/gstchildproxy.c: + childproxy: use GstChildProxy instead of GObject on the public api + Fix usage and also cleanup gst_object api use on gobjects. + +2012-06-11 15:49:10 +0200 Wim Taymans + + * gst/gstelement.h: + element: remove unused UNPARENTING flag + +2012-06-11 15:41:58 +0200 Wim Taymans + + * gst/gstbin.c: + bin: reorganize _remove_func to avoid races + Make the gst_bin_remove_func more like the add_func. Check if the element we try + to remove from the bin has the bin as the parent and set the parent flag to NULL + immediately, this allows us to avoid concurrent remove operations without using + the UNPARENTING element flag. After we unparented the element from the bin, we + update the bin state and remove the element from the list. Finally we unlink + all the pads. + This avoids a race condition where the element could still claim to have the + bin as the parent while the bin didn't have a pointer to the element anymore. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=647759 + +2012-06-10 12:48:00 -0400 Matej Knopp + + * plugins/elements/gsttypefindelement.c: + typefindelement: Only send caps when pad is being activated + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677819 + +2012-06-10 12:41:12 -0400 Matej Knopp + + * gst/gstelement.c: + gstelement: Start over if subclass removed the next pad too + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677818 + +2012-06-09 18:05:14 +0100 Tim-Philipp Müller + + * gst/gstdatetime.c: + datetime: remove fallback code for old GLibs + +2012-06-09 17:13:04 +0100 Tim-Philipp Müller + + * scripts/create-uninstalled-setup.sh: + scripts: add create-uninstalled-setup script + Little script that sets up things in ~/gst and clones + the main modules and prints some instructions. + From http://gstreamer.freedesktop.org/wiki/UninstalledSetup + +2012-06-08 15:45:38 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gsttypefindelement.c: + elements: Use gst_pad_set_caps() and don't ignore its return value + +2012-06-08 15:41:17 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't ignore the return value of gst_pad_set_caps() and call it after the vfunc + +2012-06-08 15:36:40 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Use gst_pad_set_caps() instead of the manual event fiddling + +2012-06-08 15:32:37 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Don't return the return value of gst_pad_set_caps() + e.g. it returns FALSE if incompatible caps are set on the pad. + +2012-06-06 19:02:00 +0200 Edward Hervey + + * gst/gstutils.h: + gstutils: Faster read macros + On platforms that can do unaligned read/write, we can read/write much faster + by just casting. + https://bugzilla.gnome.org/show_bug.cgi?id=599546 + +2012-06-07 12:49:10 +0200 Edward Hervey + + * tests/check/gst/gstutils.c: + check: Add a test for GST_READ_* macros + +2012-06-08 14:49:51 +0200 Edward Hervey + + * common: + Update common submodule + +2012-06-07 17:58:02 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix reconfigure + Use the pad methods to set and check the reconfigure flags + Clear the reconfigure flag before we negotiate so that we don't miss any + reconfigure events while negotiating + +2012-06-07 15:56:44 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 0.11.92 === + +2012-06-07 15:56:17 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + Release 0.11.92 + +2012-06-07 15:53:49 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2012-06-07 15:28:39 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: release the object lock sooner + Release the object lock before we get the time of the clock because that code + might take other locks. + Fix potential clock refcount error because we released the object lock but + didn't ref the clock. + +2012-06-07 10:34:46 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: remove 0.11 fixme + We always require elements to have an unlock_stop vmethod. + +2012-06-06 18:11:13 +0200 Edward Hervey + + * gst/gstregistry.c: + registry: We name the registry after the target cpu + And not the host cpu + Conflicts: + gst/gstregistry.c + +2012-06-06 18:18:18 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 1fab359 to 03a0e57 + +2012-06-06 15:45:11 +0200 Wim Taymans + + * tests/check/gst/gsttoc.c: + tests: fix unit test after event change + Someone forgot to run make check before pushing... + +2012-06-06 11:06:32 +0300 Sreerenj Balachandran + + * libs/gst/base/gstadapter.c: + gstadapter: Align the comment description with public api instead of internal one. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677536 + +2012-06-06 15:29:49 +0200 Wim Taymans + + * gst/gstelement.c: + element: fix pad cleanup in dispose + In the dispose handler we first need to release all the request pads and then + remove the remaining pads. This is because it is possible that releasing the + request pad might also cleanly remove some of the other dynamic pads, like + what rtpsession does. + https://bugzilla.gnome.org/show_bug.cgi?id=677436 + +2012-06-06 14:14:31 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + event: Don't make the TOC event a multi-sticky event + Elements are supposed to merge upstream events. + +2009-10-13 17:24:34 +0200 Havard Graff + + * gst/gstpad.c: + Make sure that unlinked pads do not cause a return false on latency events. + Context: Latency configuration should not be + messed up because of not-linked pads. In general, + one return FALSE on latency distribution causes + the "overall" pipeline latency configuration to + fail. This shows up as noise in logs (warning). + Conflicts: + gst/gstpad.c + +2012-06-06 12:52:09 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * libs/gst/base/gstbaseparse.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gstutils.c: + event: add name to sticky_multi events + The name of the event is used to store multiple sticky events of a certain type + on a pad. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676859 + +2012-06-06 09:59:55 +0200 Sebastian Dröge + + * docs/design/part-negotiation.txt: + design: Also mention that the order of the filter caps is important + +2012-06-06 09:15:04 +0200 Wim Taymans + + * gst/gstquery.c: + query: improve docs + +2012-06-06 09:13:11 +0200 Wim Taymans + + * gst/gstpad.c: + pad: only serialized events can't pass after EOS + Only serialized events can't be sent on pads that are EOS. Otherwise a seek + event would be refused as well. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677520 + +2012-06-05 14:38:25 +0200 Wim Taymans + + * docs/design/part-negotiation.txt: + docs: talk about the filter caps + +2012-06-02 16:44:59 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttag.c: + tests: add unit test for tag list writability + +2012-06-02 16:38:35 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gsttagsetter.c: + * tests/examples/metadata/read-metadata.c: + gst_tag_list_free -> gst_tag_list_unref + +2012-06-02 16:29:45 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: expand taglist section in porting-to-0.11 docs a bit + +2012-06-05 11:28:38 +0200 Wim Taymans + + * docs/design/part-negotiation.txt: + docs: update negotiation docs + Mention that the acceptcaps query does not have to be recursive + +2012-06-05 09:40:14 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: remove obsolete caps code + +2012-06-05 09:39:41 +0200 Wim Taymans + + * gst/gstutils.c: + utils: improve debug + +2012-06-05 09:21:10 +0200 Wim Taymans + + * tests/check/gst/gstutils.c: + tests: fix unit test + Before we can change the caps on a sinkpad with fixed caps we need to unfix the + pad caps. + +2012-06-05 09:10:05 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't pause task on EOS + Elements should not rely on core to pause tasks on EOS. + +2012-06-05 09:00:01 +0200 Wim Taymans + + * gst/gstpad.c: + pad: fix event type check + +2012-06-04 16:19:26 +0200 Wim Taymans + + * gst/gstpad.c: + pad: fix 'res' may be used uninitialized in this function + +2012-06-04 13:00:53 +0200 Sebastian Dröge + + * tests/check/elements/funnel.c: + funnel: Fix unit test + +2012-06-04 12:57:59 +0200 Sebastian Dröge + + * tests/check/elements/valve.c: + valve: Fix unit test + +2012-06-04 11:46:42 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Don't accept any buffers or events after EOS + +2012-06-04 11:13:02 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: also perform state processing upon non-OK return + ... since processing might still continue (if e.g. NOT_LINKED) + and then proper state (e.g. offset) needs to be maintained + (e.g. to arrange for a new frame setup). + +2012-06-04 11:25:47 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Always return errors for EOS events immediately + For non-EOS events things will error out later during data + flow but after EOS events no data flow is happening. + See bug #677340. + +2012-06-04 09:27:35 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Only forward caps events to a pad if it accepts the caps + Fixes bug #677335. + +2012-06-02 20:01:01 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "pad: Return FALSE if pushing of sticky events failed" + This reverts commit 0f924b922c712059d7752fc15b832551745ff27e. + Sticky events should always return TRUE when pushing and will + only cause failures during data flow later. + +2012-06-02 16:18:46 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pad: fix variable-set-but-not-used compiler warning + +2012-06-02 16:55:07 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: If pushing a sticky event failed, make sure to at least push any pending EOS events + Otherwise a pipeline where one sticky event fails to be sent will + never forward EOS events downstream. This can cause pipelines to + wait forever for EOS on errors. + +2012-06-02 16:02:07 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Return FALSE if pushing of sticky events failed + Instead of just ignoring failure of pushing sticky events and + returning TRUE as if everything is fine. + +2012-06-01 16:34:16 +0200 Andre Moreira Magalhaes (andrunko) + + * plugins/elements/gstinputselector.c: + inputselector: Correctly get current running time when syncing to the segment information + Fixes bug #677263. + +2012-06-01 10:28:30 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From f1b5a96 to 1fab359 + +2012-05-25 22:58:57 -0500 Mike Ruprecht + + * tests/check/elements/funnel.c: + tests: Add funnel test to cover EOS event handling + Ported from f3b2dd6f in the 0.10 branch + +2012-05-25 22:52:33 -0500 Mike Ruprecht + + * plugins/elements/gstfunnel.c: + funnel: Only emit EOS event if all sinkpads have received one + If multiple sources are plugged into the funnel and one of the + sources emits an EOS, that event is propogated through the funnel + even though other sources connected to the funnel may still be + pushing data. This patch waits to send an EOS event until the + funnel has received an EOS event on each sinkpad. + Ported from d397ea97 in 0.10 branch. + +2012-05-29 19:24:25 -0500 Mike Ruprecht + + * tests/check/elements/funnel.c: + tests: Fix invalid read when releasing request pads in funnel tests + +2012-05-29 19:23:07 -0500 Mike Ruprecht + + * plugins/elements/gstfunnel.c: + funnel: Fix buffer leak + +2012-05-31 17:45:29 +0200 Andre Moreira Magalhaes (andrunko) + + * plugins/elements/gstinputselector.c: + inputselector: Don't try to sync on the segment if it has no TIME format + ...and wait until it is actually configured and has a format before + trying to sync. + +2012-05-31 17:03:54 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: No need to broadcast the signal in flush-stop + Everything stopped at this point already. + Conflicts: + plugins/elements/gstinputselector.c + +2012-05-31 13:07:49 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 92b7266 to f1b5a96 + +2012-05-31 10:10:41 +0100 Bastien Nocera + + * plugins/elements/gstqueue2.c: + queue2: Fix property name in the docs + temp-template, not temp-tmpl + https://bugzilla.gnome.org/show_bug.cgi?id=677170 + +2012-05-28 14:29:00 -0300 Andre Moreira Magalhaes (andrunko) + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Properly sync when changing streams + This adds properties to use the clock time for deciding when + to drop buffers for inactive pads and a property to buffer all + not rendered buffers for the active pad to allow pad switching + without losing any buffers at all. + Conflicts: + plugins/elements/gstinputselector.c + +2012-05-30 12:44:56 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ec1c4a8 to 92b7266 + +2012-05-30 11:18:39 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 3429ba6 to ec1c4a8 + +2012-05-29 08:48:36 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: add guards to make sure taglist is writable when modifying it + Now that taglists are refcounted we need to check if they're + writable before modifying them. + +2012-05-28 23:54:10 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * win32/common/libgstreamer.def: + taglist: avoid unnecessary string copying when registering tags + Add gst_tag_register_static() - no need to copy all those + string constants, whether translated or not. + API: gst_tag_register_static() + +2012-05-28 00:08:56 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: check for GLib-GIO criticals as well + +2012-05-28 00:08:18 +0100 Tim-Philipp Müller + + * gst/gsttagsetter.c: + * gst/gsttoc.c: + * plugins/elements/gstinputselector.c: + * tools/gst-launch.c: + gst_tag_list_free() -> gst_tag_list_unref() + +2012-05-27 23:58:27 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstcompat.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + * win32/common/libgstreamer.def: + taglist: make GstTagList a GstMiniObject + Which adds refcounting support, and other things. + +2012-05-27 20:31:30 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: log freeing of caps at same log level as creation, i.e. TRACE + +2012-05-26 11:37:49 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquark.c: + * gst/gstquark.h: + message, event: update for tag lists not being structures any more + +2012-05-21 00:31:29 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: make proper struct not just a GstStructure + +2012-05-25 10:28:40 +0200 Josep Torra + + * gst/gst.c: + * gst/gstdebugutils.c: + debugutils: Fix static linking on OS X + The linking behaviour of external variables that are not initialized + in the compilation unit where they are defined is undefined. On OS X + this causes a linking failure when statically linking GStreamer. + +2012-05-25 09:17:17 +0100 Luis de Bethencourt + + * scripts/five-bugs-a-day.pl: + five-bugs-a-day: use splice to trim the bug list + +2012-05-24 23:30:29 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + fakesrc: put byte position rather than buffer count into GST_BUFFER_OFFSET + If we're sending a segment in BYTE format, the offset + should be in bytes as well. + +2012-05-24 11:48:19 +0100 Luis de Bethencourt + + * docs/design/part-segments.txt: + docs: fix a typo in part-segments.txt + +2012-05-24 11:02:53 +0200 Brian Cameron + + * libs/gst/base/gsttypefindhelper.c: + typefind: fix prototype of helper_find_suggest + The proto for helper_find_suggest has a different argument than the actual + function in the same file has. This causes the Sun Studio compiler to fail. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676624 + Conflicts: + libs/gst/base/gsttypefindhelper.c + +2012-05-24 08:07:14 +0100 Tim-Philipp Müller + + * scripts/five-bugs-a-day.pl: + scripts: remove a stray print from debugging and fix up cron entry docs + +2012-05-24 09:03:12 +0200 Sebastian Dröge + + * scripts/five-bugs-a-day.pl: + five-bugs-a-day: Make #! to perl more portable + +2012-05-24 07:56:48 +0100 Tim-Philipp Müller + + * scripts/five-bugs-a-day.pl: + scripts: remove fixed 'known issue' from five-bugs-a-day script + This was with commas actually, and should be fixed now. + +2012-05-24 07:54:50 +0100 Tim-Philipp Müller + + * scripts/five-bugs-a-day.pl: + scripts: add five-bugs-a-day script + Cron fodder. + +2012-05-22 14:27:48 +0300 Sreerenj Balachandran + + * tests/examples/helloworld/helloworld.c: + tests: rename playbin2 to playbin and adding some debug info + +2012-05-22 18:27:36 +0200 Edward Hervey + + * gst/gsturi.c: + uri: Add some debug statements + +2012-05-22 13:51:47 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update defs file + +2012-05-21 09:14:39 +0200 Wim Taymans + + * tests/check/gst/gstbin.c: + bin: port unit test to 0.11 + +2012-05-21 15:14:51 +0200 Stefan Sauer + + * gst/gstelement.c: + * gst/gstutils.c: + docs: improve the seeking docs more. + Also mention it on _element_seek{,_simple} and be more precise why it happens. + +2012-05-21 13:17:21 +0200 Stefan Sauer + + * gst/gstelement.c: + * gst/gstevent.c: + docs: fix a typo and clarify event handling a bit more + Tell about async_done messages for some events and review the _event_new_seek + docs. + +2012-05-18 15:04:35 +0200 Wim Taymans + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: try harder to avoid state changes in wrong direction + When the bin does an upward state change, try to avoid doing a downward state + change on the child and vice versa. + Add some more unit tests for this fix. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=621833 + +2012-05-18 20:11:55 +0300 Anton Belka + + * tools/gst-launch.c: + gst-launch: fix -c, --toc message + +2012-05-21 01:48:29 +0300 Anton Belka + + * gst/gsttoc.c: + * gst/gsttoc.h: + toc: Add boxed types for GstToc and GstTocEntry + +2012-05-20 18:23:57 +0100 Tim-Philipp Müller + + * gst/gsttoc.c: + * gst/gsttoc.h: + toc: fix type of pad parameter to gst_toc_entry_new_with_pad() + +2012-05-20 18:16:45 +0100 Tim-Philipp Müller + + * gst/gsttoc.c: + toc: use correct GType for tag lists + +2012-05-20 18:06:22 +0100 Tim-Philipp Müller + + * gst/gsttoc.c: + toc: avoid unnecessary GValue acrobatics + +2012-05-20 17:48:55 +0100 Tim-Philipp Müller + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gsttoc.c: + toc: use global quark table + +2012-05-20 17:10:24 +0100 Tim-Philipp Müller + + * gst/gstquark.c: + toc: fix internal TOC query and event structure names + Make them consistent with all the other query and event names. + +2012-05-19 17:24:52 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstpluginfeature.h: + pluginfeature: make GstPluginFeature structure private + Make GstPluginFeature opaque until we have time to + clean it up a little. Only GstElementFactory and + GstTypefindFactory derive from it, and they are + opaque already, and we currently don't support + custom plugin features in the registry anyway. + +2012-05-19 17:23:43 +0100 Tim-Philipp Müller + + * tests/check/gst/gstplugin.c: + * tools/gst-inspect.c: + tools, tests: don't access the GstPluginFeature structure directly + +2012-05-19 17:16:35 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * win32/common/libgstreamer.def: + pluginfeature: add gst_plugin_feature_get_plugin() + Add function to retrieve plugin that provides this feature. + API: gst_plugin_feature_get_plugin() + +2012-05-19 16:21:39 +0100 Tim-Philipp Müller + + * common: + common: update for gstscanobj changes + +2012-05-19 15:51:53 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstelementfactory.h: + * tests/check/gst/gstelementfactory.c: + elementfactory: make object struct opaque for now + Make GstElementFactory opaque until we have time to + clean it up a little. It's not something anyone + would need to derive from. + +2012-05-19 14:59:14 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: don't use private GstElementFactory API in gst-inspect + +2012-05-19 14:52:29 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * win32/common/libgstreamer.def: + elementfactory: add gst_element_factory_get_metadata_keys() + API: gst_element_factory_get_metadata_keys() + +2012-05-18 09:52:09 +0200 Wim Taymans + + * tools/gst-launch.c: + launch: improve EOS on shutdown handling + When the -e option is selected, also wait for EOS when the pipeline produced an + error. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=630997 + +2012-05-16 18:53:15 +0300 Anton Belka + + * gst/gststructure.c: + docs: fix gst_structure_to_string() docs + +2012-05-16 13:24:23 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: throttle-time is used + +2012-05-16 12:08:44 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: add prepare method + Add a prepare method that is called before sync happens. The purpose of this + method is to prepare the rendering of the giving buffer so that the following + render() call after sync is a quick as possible. + +2012-05-16 09:16:26 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: avoid potential deadlock + In gst_base_src_start_complete() we do a perform_seek() that will eventually + start the streaming thread which acquires the live lock and then goes to sleep + in the case of appsrc. Right after we perform seek we also try to acquire the + live lock which might then deadlock. + fix this by taking the stream lock before performing the seek. This makes sure + that the streaming thread cannot start and grab the live lock until we are done + and release the stream lock again. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676048 + +2012-05-15 19:11:15 +0100 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: remove references to mmap in comments and debug messages + +2012-05-15 16:38:30 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + * tools/gst-launch.c: + * win32/common/libgstreamer.def: + gst: Rename gst_toc_entry_type_to_string() to gst_toc_entry_type_get_nick() + It's more consistent. + +2012-05-15 14:59:07 +0300 Anton Belka + + * tools/gst-launch.c: + gst-launch: fix print_toc_entry() + +2012-05-15 14:48:35 +0300 Anton Belka + + * docs/gst/gstreamer-sections.txt: + * gst/gsttoc.c: + * gst/gsttoc.h: + * win32/common/libgstreamer.def: + toc: API: Add gst_toc_entry_type_to_string() + +2012-05-14 03:57:50 +0200 Alban Browaeys + + * plugins/elements/gsttypefindelement.c: + typefindelement: if sink pad is activated do not change mode + In commit bf0964b6 a check for pad is activated was not carried. + This leads to attempt to pull while in push mode when force_caps + is set. In this case without the attached check even when activated + in pull mode we activate back to push mode. + This is from comment in previous code , case number eight: + 8. if the sink pad is activated, we are in pull mode. succeed. + - otherwise activate both pads in push mode and succeed. + Putting it back fixes playback of webm in webkit+gstreamer 1.0 . + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676003 + +2012-05-13 16:59:24 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 0.11.91 === + +2012-05-13 16:02:36 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + Release 0.11.91 + +2012-05-13 16:02:18 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2012-05-13 15:55:43 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From dc70203 to 3429ba6 + +2012-05-09 14:22:20 +0200 Sebastian Rasmussen + + * gst/gst.c: + gst: Only include init/deinit of alloc tracing when enabled + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=675806 + +2012-05-11 09:07:16 +0200 Wim Taymans + + * docs/design/part-block.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-overview.txt: + * docs/design/part-preroll.txt: + * docs/design/part-probes.txt: + * docs/design/part-segments.txt: + * docs/design/part-states.txt: + * docs/pwg/advanced-events.xml: + * libs/gst/base/gstbasesrc.c: + docs: fix docs + GST_FLOW_WRONG_STATE -> GST_FLOW_FLUSHING + +2012-05-10 12:15:49 +0200 Wim Taymans + + * docs/design/part-bufferpool.txt: + docs: improve bufferpool docs + +2012-05-08 20:12:42 +0300 Anton Belka + + * tools/gst-launch.c: + gst-launch: print tags in toc + +2012-05-05 22:17:43 +0300 Raimo Järvi + + * gst/gstpoll.c: + * gst/gstsystemclock.c: + * plugins/elements/gstfilesrc.c: + * tests/check/elements/filesrc.c: + * tests/check/gst/gstpoll.c: + gst: Fix compiler warnings on mingw-w64 + https://bugzilla.gnome.org/show_bug.cgi?id=675525 + +2012-05-02 14:00:43 +0300 Sreerenj Balachandran + + * gst/gstmemory.c: + memory: add missing parameter to default_mem_map() + Fixes function signature for correctness. + https://bugzilla.gnome.org/show_bug.cgi?id=675289 + +2012-05-02 08:08:15 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for new API + +2012-05-01 22:35:38 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gsttypefindfactory.h: + typefindfactory: make object struct opaque for now + Make opaque until we have time to clean it up a little. + +2012-05-01 22:30:32 +0100 Tim-Philipp Müller + + * gst/gsttypefindfactory.c: + * gst/gsttypefindfactory.h: + typefindfactory: fix return type of gst_type_find_factory_get_extensions() + +2012-05-01 22:28:11 +0100 Tim-Philipp Müller + + * libs/gst/base/gsttypefindhelper.c: + * tools/gst-inspect.c: + tools, base: don't poke into GstTypeFindFactory struct, use public API + +2012-05-01 22:33:30 +0100 Tim-Philipp Müller + + * gst/gsttypefindfactory.c: + * gst/gsttypefindfactory.h: + * libs/gst/base/gsttypefindhelper.c: + typefindfactory: add gst_type_find_factory_has_function() + Add API so people don't have to poke the struct for this. + +2012-05-01 15:52:14 -0300 Thiago Santos + + * gst/gstcaps.c: + gstcaps: Update docs for gst_caps_is_equal + NULL caps aren't valid caps in 1.0 and aren't accepted in + gst_caps_is_equal + +2012-05-01 19:47:05 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + * tests/check/gst/gsturi.c: + uri: require URI protocol bit to be at least 3 characters to be valid + We want to return FALSE when run on a windows-style file path. + https://bugzilla.gnome.org/show_bug.cgi?id=674296 + +2012-04-26 17:26:50 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + basetransform/basesrc: Do bufferpool configuration inside the default decide_allocation() implementation + This allows subclasses to override it, as is necessary for e.g. the + video-crop meta. It is now necessary that after decide_allocation() + there is always a allocator and a configured buffer pool inside the + query. + +2012-04-28 21:37:56 +0200 Matej Knopp + + * gst/gstghostpad.c: + ghostpad: set result on accept caps query when there is no peer + +2012-05-01 10:50:32 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + adapter: remove _try_to_merge_up() + It causes the timestamp to go wrong, should not cause much of a performance + increase and in the cases where it is faster, it is broken in 0.10 as well. + We should try to review this when rewriting the adapter for 0.11 memory + features. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674791 + +2012-05-01 09:25:25 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: make internals private + Make the adapter fields private. + +2012-04-30 20:29:21 +0400 Руслан Ижбулатов + + * plugins/elements/gstfilesrc.c: + filesrc: rearrange sys/stat.h inclusion point for MinGW + gstplugin.h used to include this for us, but doesn't any longer. + https://bugzilla.gnome.org/show_bug.cgi?id=675171 + +2012-04-30 09:58:09 +0100 Vincent Penquerc'h + + * docs/design/part-seeking.txt: + * gst/gstsegment.h: + * win32/common/gstenumtypes.c: + event: add new seek snap flags + They can be used to select snapping behavior (to previous, next, or + nearest location, where relevant) when seeking. + The seeking implementation (eg, demuxer) may currently ignore some + or all of these flags. + +2012-04-29 20:06:58 +0100 Tim-Philipp Müller + + * gst/gstplugin.h: + docs: remove reference to removed API in plugin docs + +2012-04-29 20:06:38 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: avoid some relocations + +2012-04-29 18:35:11 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstregistry.c: + * win32/common/libgstreamer.def: + plugin: remove gst_plugin_name_filter + It's only used internally, most other users will likely + want to use gst_registry_find_plugin() directly instead + (and if not, they can easily walk the list and doing the + strcmp themselves). + +2012-04-29 17:46:32 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.h: + * gst/gstpluginloader.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * tools/gst-inspect.c: + plugin: use GstObject flags for plugin flags + +2012-04-29 17:03:32 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.h: + plugin: make GstPlugin object structure opaque for now + There's no reason anyone would want to derive from this, so + just make opaque until we manage to make all the private bits + private properly (which I'm not doing right now because it's + more invasive and I have registry modifications locally which + touch all that code as well). + +2012-04-29 16:49:57 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: use public accessors for plugin description details + Mostly anyway (flags still need sorting out). + +2012-04-29 16:46:55 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstplugin.c: + * gst/gstplugin.h: + * win32/common/libgstreamer.def: + plugin: remove gst_plugin_get_module() + This is an implementation detail really, and it's not + clear what anyone would do with this. It's unused as + far as I'm aware, so just remove it for now. + +2012-04-29 16:20:50 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstplugin.c: + * gst/gstplugin.h: + * win32/common/libgstreamer.def: + plugin: add accessor for release date time string in plugin description + API: gst_plugin_get_release_date_string() + +2012-04-29 15:53:05 +0100 Tim-Philipp Müller + + * tests/check/gst/gstplugin.c: + tests: use public accessors to get plugin description details + +2012-04-29 13:28:09 +0100 Tim-Philipp Müller + + * gst/gstobject.c: + gstobject: give the 20th queue element a different name than the first queue2 one + Fixes issue with the default naming scheme. + +2012-04-18 17:37:25 +0400 Руслан Ижбулатов + + * gst/parse/grammar.y: + Fix format string in grammar.y + Fixes #674849 + +2012-04-25 20:14:13 +0200 Stefan Sauer + + * libs/gst/controller/gstdirectcontrolbinding.c: + controlbindings: add comments for sparse control source + +2012-04-25 20:10:11 +0200 Stefan Sauer + + * gst/gstcontrolbinding.c: + controller: emulate _get_g_value_array() + Add a default implementation on the baseclass. + +2012-04-25 09:47:10 +0200 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.c: + * gst/gstobject.c: + * gst/gstobject.h: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.h: + * tests/check/libs/controller.c: + * tests/examples/controller/control-sources.c: + * win32/common/libgstreamer.def: + controller: expand the api to offer functions for plain and GValue arrays + Rename the _get_value_array() functions to _get_g_value_array() and reintroduce + the former to operate on plain unboxed c datatypes (like in 0.10). The _g_value + variants are for bindings while the _value ones are more suited to processing + in elements. + +2012-04-25 18:11:03 +0200 Sebastian Dröge + + * scripts/gst-uninstalled: + gst-uninstalled: Add insanity, insanity-gst and gst-editing-services + +2012-04-25 09:06:05 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: Reset the buffer before releasing into pool + Reset the buffer not after we acquire but before we release into the pool. This + makes sure that the pool only has buffers in a clean state and that we can set + extra metadata on buffers in the acquire method. this means that we need to + remove an argument from the method. + +2012-04-23 15:32:04 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: MARKER is for the start of a talkspurt + +2012-04-24 16:01:52 +0200 Mark Nauwelaerts + + * tests/check/elements/queue2.c: + * tests/check/gst/gstpad.c: + tests: plug some leaks + +2012-04-23 17:04:57 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads.c: + collectpads: do not unref flush_start twice + Based on patch by Matej Knopp + +2012-04-23 16:57:16 +0200 Mark Nauwelaerts + + * libs/gst/base/gstadapter.c: + adapter: refresh skip following merge_up attempt + ... as the latter might now adjust skip as well. + +2012-04-23 09:18:48 +0200 Sebastian Dröge + + * gst/gstmessage.h: + message: Remove comma at end of enum list + This comma confuses some compilers. + +2012-04-18 15:31:23 +0400 Руслан Ижбулатов + + * plugins/elements/gsttee.c: + tee: Remove unneeded unlock + +2012-04-18 05:12:55 +0400 Руслан Ижбулатов + + * gst/gstregistry.c: + registry: fix hardcoded 0.10 version in win32 pluginscanner + https://bugzilla.gnome.org/show_bug.cgi?id=674294 + +2012-04-17 15:37:27 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstmeta.h: + * tests/check/gst/gstmeta.c: + meta: add LOCKED flag + Add a new LOCKED flag to the metadata. Refuse removing LOCKED metadata from + a buffer. + Mark the metadata from the bufferpool LOCKED. + Add unit test for LOCKED flag + +2012-04-17 14:38:01 +0200 Mark Nauwelaerts + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstcollectpads2.h: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/collectpads.c: + * tests/check/libs/gstlibscpp.cc: + * tests/check/libs/libsabi.c: + * win32/common/libgstbase.def: + * win32/vs10/base/base.vcxproj: + * win32/vs10/base/base.vcxproj.filters: + collectpads2: rename to collectpads + +2012-04-17 12:54:45 +0200 Mark Nauwelaerts + + * libs/gst/base/gstadapter.c: + adapter: ensure writable head buffer before skipping part of it + +2012-04-17 12:29:50 +0200 Mark Nauwelaerts + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + libs/gst/base/gstcollectpads2.c + +2012-04-17 12:23:05 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + collectpads2: always recording incoming segment info if no buffer_func set + +2012-04-17 10:38:05 +0200 Wim Taymans + + * docs/gst/running.xml: + docs: update the debug and trace env var docs + +2012-04-17 10:33:59 +0200 Wim Taymans + + * gst/gsttrace.c: + trace: use g_parse_debug_string instead of atoi + Make the GST_TRACE env variable take a comma separated list of strings + describing the options to enable instead of a number. + +2012-04-16 21:14:17 +0000 Youness Alaoui + + * tools/gst-inspect.c: + gst-inspect: If running with --print-all, fix printing of the Children: line + +2012-04-16 21:14:02 +0000 Youness Alaoui + + * tools/gst-inspect.c: + gst-inspect: If running with --print-all, fix printing of signal names + +2012-04-16 16:36:52 +0200 Mark Nauwelaerts + + * win32/common/libgstbase.def: + win32: add new collectpads2 API to .def file + +2012-04-16 16:29:34 +0200 Mark Nauwelaerts + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + libs/gst/base/gstcollectpads2.c + +2012-04-16 16:24:18 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: provide query default and callback handling + ... which presently mainly serves to answer SEEKING query negatively + to dissuade upstream encoders from doing any seeking and + "header finalization" (since the returned result of pushing a + sticky event is fairly useless nowadays). + +2012-04-16 16:24:10 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: modify event handling using a default event handler + ... that elements should "chain up" to. + +2012-04-16 15:35:23 +0200 Wim Taymans + + * gst/gstvalue.c: + segment: add rude serialization + Ass serialize and deserialize functions for GstSegment so that gdp and + gst_structure_to_string show the segment values. We convert to a GstSegment + first to make things easier.. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674100 + +2012-02-03 17:08:35 +0000 Vincent Penquerc'h + + * libs/gst/base/gstcollectpads2.c: + collectpads2: assume 0 based segment if no time segment was provided + https://bugzilla.gnome.org/show_bug.cgi?id=669305 + +2012-04-16 10:28:15 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: add size to debug log + +2012-04-16 10:27:29 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Set sequence number on segment events + +2012-04-16 10:22:53 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Forward all sticky events when switching pads + +2012-04-16 10:05:02 +0200 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Store pad state directly inside the pads instead of GObject qdata + +2012-04-16 09:45:27 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Send reconfigure event on the new active pad when pads are switched + +2012-04-16 09:08:46 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6db25be to dc70203 + +2012-04-14 03:27:29 +0200 Matej Knopp + + * libs/gst/base/gstadapter.c: + Remove skipped part of buffer when mapping the adapter + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674085 + +2012-04-14 10:24:38 +0200 Wim Taymans + + * tests/check/libs/adapter.c: + tests: add another adapter test + Test performance of merging + +2012-04-14 10:23:49 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: improve debug + +2012-04-13 14:22:34 +0200 Matej Knopp + + * plugins/elements/gstmultiqueue.c: + multiqueue: gst_single_queue_flush unlocks the queue twice + https://bugzilla.gnome.org/show_bug.cgi?id=674044 + +2012-04-13 13:36:37 +0200 Sebastian Dröge + + * autogen.sh: + * configure.ac: + configure: Modernize autotools setup a bit + Also we now only create tar.bz2 and tar.xz tarballs. + +2012-04-13 13:36:47 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 464fe15 to 6db25be + +2012-04-13 11:58:49 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: plug caps leak + +2012-04-13 08:10:19 +0200 Stefan Sauer + + * gst/gstcontrolbinding.c: + controlbinding: only take a weak ref on the object + Fixes the leaks in the tests. Added a TODO comment to eventually rework this + some more (while we can). + +2012-04-12 18:15:27 -0400 Reynaldo H. Verdejo Pinochet + + * Android.mk: + Sync Android.mk entries to the new major version + Change naming on the pkgconfig files to reflect + the 0.10 -> 1.0 bump. + +2012-04-12 14:59:52 +0200 Edward Hervey + + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + controller: Chain up to parent class dispose/finalize + Avoids leaks + +2012-04-12 14:59:31 +0200 Edward Hervey + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: Use gst_object_{ref|unref} where applicable + Allows us to debug object life + +2012-04-12 14:58:47 +0200 Edward Hervey + + * gst/gstobject.c: + * gst/gstpluginfeature.c: + gst: Use gst_object_{ref|unref} where applicable + Allows us to debug object life + +2012-04-12 11:53:00 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: improve arg checking + Allow idx == 0 and length == -1 on empty buffers for the _range methods. + +2012-04-12 11:18:22 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 0.11.90 === + +2012-04-12 09:57:01 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.prerequisites: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.11.90 + +2012-04-12 09:56:43 +0200 Sebastian Dröge + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2012-04-11 13:20:18 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix merge error + +2012-04-11 12:58:19 +0200 Wim Taymans + + * tests/check/elements/queue2.c: + queue2: set buffer to NULL before pull + +2012-04-11 12:54:36 +0200 Wim Taymans + + * tests/check/elements/queue2.c: + tests: port queue2 tests to 0.11 + +2012-04-11 12:50:50 +0200 Wim Taymans + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + gst/gsttoc.c + plugins/elements/gstqueue2.c + +2012-04-11 12:34:55 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: signal delete before waiting + When we don't have the requested data in the ringbuffer and we move our read + pointer to the requested position, signal the delete cond to inform the writer + that we changed the current fill level. If we don't, the writer might stay + blocked and we might wait forever. + +2012-04-11 12:15:37 +0200 Wim Taymans + + * tests/check/elements/queue2.c: + queue2: add test for ringbuffer deadlock + +2012-04-11 12:02:50 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: update current read position before waiting + When we don't have enough bytes in the ringbuffer to satisfy the current + request, first update the current read position before waiting. If we don't do + that, the ringbuffer might appear full and the writer will never write more + bytes to wake us up. + +2012-04-11 12:00:10 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add range only on sinkpad + Only add the range when we receive a segment event on the sinkpad. The add_range + method will modify the write position, which only makes sense to do on the + sinkpad. + +2012-04-11 11:55:56 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix debug message + We're not writing to the offset of the buffer + +2012-04-11 11:55:28 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add_range already updates the level + +2012-04-10 14:11:26 +0400 Alexander Saprykin + + * gst/gsttoc.c: + toc: fix memory leaks while copying content + +2012-04-10 14:18:48 +0400 Alexander Saprykin + + * tests/check/gst/gsttocsetter.c: + tocsetter: fix memory leaks in unit test + +2012-04-10 14:16:50 +0400 Alexander Saprykin + + * tests/check/gst/gsttoc.c: + toc: fix memory leaks in unit test + +2012-04-10 14:18:48 +0400 Alexander Saprykin + + * tests/check/gst/gsttocsetter.c: + tocsetter: fix memory leaks in unit test + +2012-04-10 14:16:50 +0400 Alexander Saprykin + + * tests/check/gst/gsttoc.c: + toc: fix memory leaks in unit test + +2012-04-10 14:11:26 +0400 Alexander Saprykin + + * gst/gsttoc.c: + toc: fix memory leaks while copying content + +2012-04-10 19:39:58 +0300 Sreerenj Balachandran + + * gst/gstbuffer.c: + buffer: Clean up header files + +2012-04-10 16:07:52 +0200 Wim Taymans + + Merge remote-tracking branch 'origin/0.10' + +2012-04-10 16:04:54 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: clear seeking flag in all cases + Also clear the seeking flag when downstream is in pull mode. + +2012-04-10 12:55:31 +0200 Wim Taymans + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + gst/gst.c + plugins/elements/gstqueue2.c + +2012-04-10 12:49:04 +0200 Wim Taymans + + * gst/gst.c: + gst: add toc entry ref/unref + +2012-04-10 12:09:53 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: set seeking flag with the queue lock + +2012-04-10 11:20:09 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Keep track of the seeking state + Set the seeking flag right before we send a seek event upstream and discard all + data untill we see a flush-stop again. We need to do this because we activate + the range that we seek to immediately after sending the seek event and it is + possible that we receive data in our chain function from before the seek + which would then be added to the wrong range resulting in data corruption. + +2012-04-10 11:16:14 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: make range on newsegment for ringbuffer + When using the ringbuffer, handle the newsegment event like we handle it when + using the temp-file mode: create a new range for the new byte segment. The new + segment should normally already be created when we do a seek. + +2012-04-09 16:42:30 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + +2012-04-09 16:40:47 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't use buffer after pushing it downstream + +2012-04-09 16:04:22 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + +2012-04-09 15:58:21 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Fail if a pad for a non-request template is requested + +2012-04-09 13:40:35 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + * gst/gstquark.c: + * gst/gstquark.h: + element: use quarks when storing standard metadata in structures + +2012-04-09 13:05:07 +0100 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + plugins: use new gst_element_class_set_static_metadata() + +2012-04-09 12:47:58 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: add gst_element_class_{set,add}_static_metadata() + Add gst_element_class_{add,set}_metadata() variants for static strings, + so we can avoid unnecessary g_strdup()s. + API: gst_element_class_add_static_metadata() + API: gst_element_class_set_static_metadata() + +2012-04-08 21:17:14 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttask.h: + * tests/examples/streams/stream-status.c: + task: remove gst_task_set_priority() + It doesn't actually do anything. + +2012-01-14 00:31:32 -0500 Matej Knopp + + * win32/vs10/Common.props: + * win32/vs10/Library.props: + * win32/vs10/Plugin.props: + * win32/vs10/ReadMe.txt: + * win32/vs10/Tool.props: + * win32/vs10/base/base.vcxproj: + * win32/vs10/base/base.vcxproj.filters: + * win32/vs10/controller/controller.vcxproj: + * win32/vs10/controller/controller.vcxproj.filters: + * win32/vs10/generated/generated.vcxproj: + * win32/vs10/generated/generated.vcxproj.filters: + * win32/vs10/gst-inspect/gst-inspect.vcxproj: + * win32/vs10/gst-inspect/gst-inspect.vcxproj.filters: + * win32/vs10/gst-launch/gst-launch.vcxproj: + * win32/vs10/gst-launch/gst-launch.vcxproj.filters: + * win32/vs10/gst-typefind/gst-typefind.vcxproj: + * win32/vs10/gst-typefind/gst-typefind.vcxproj.filters: + * win32/vs10/gstcoreelements/gstcoreelements.vcxproj: + * win32/vs10/gstcoreelements/gstcoreelements.vcxproj.filters: + * win32/vs10/gstreamer.sln: + * win32/vs10/gstreamer/gstreamer.vcxproj: + * win32/vs10/gstreamer/gstreamer.vcxproj.filters: + * win32/vs10/net/net.vcxproj: + * win32/vs10/net/net.vcxproj.filters: + win32: add VS 10 Project files + https://bugzilla.gnome.org/show_bug.cgi?id=666219 + +2012-04-08 18:25:39 +0100 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + win32: update for version changes + +2012-04-07 16:35:27 +0100 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/0.10' + +2012-04-07 16:06:22 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new TOC API to libgstreamer.def + Fixes 'make check'. + +2012-04-07 16:05:33 +0100 Tim-Philipp Müller + + * tests/check/gst/.gitignore: + tests: add new toc test binaries to .gitignore + +2012-04-07 16:04:14 +0100 Tim-Philipp Müller + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gsttoc.c: + gst: don't export private TOC functions + +2012-04-07 15:42:08 +0100 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + gst/gstatomicqueue.c + +2012-02-24 15:24:42 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix race + After a writer has written to its reserved write location, it can only make the + location available for reading if all of the writers with lower locations have + finished. + +2012-02-24 12:51:24 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix subtle race + Fix a race where the reader would see the updated the tail pointer before the + write could write the data into the queue. Fix this by having a separate reader + tail pointer that is only incremented after the writer wrote the data. + +2012-04-07 15:20:05 +0100 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: set default block size from local define + Doesn't actually change the default value, just makes use of the + define there is. Superficial testing with fakesink and jpegdec did + not reveal improved performance for bigger block sizes, so leave + default as it is. + +2012-04-06 16:46:58 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: don't update the current reading_pos in flush + A flush from the upstream element should not make buffering go to 0, the next + pull request might be inside a range that we have and then we don't need to + buffer at all. If the next pull is outside anything we have, buffering will + happen as usual anyway. + +2012-04-06 12:42:39 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix for merged changes + +2012-04-06 12:37:41 +0200 Wim Taymans + + Merge branch '0.10' + +2012-04-06 12:32:49 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: check the pad mode on the right pad + +2012-04-06 12:24:22 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: forward flush events correctly + We want to forward the flush events received on the sinkpad whenever the srcpad + is activated in pushmode, which can also happen when using the RINGBUFFER or + DOWNLOAD mode and downstream failed to activate us in pull mode. + +2012-04-05 21:56:05 +0200 Stefan Sauer + + * gst/gstcontrolbinding.c: + controlbinding: chain up on dispose and finalize + +2012-04-05 21:55:07 +0200 Stefan Sauer + + * gst/gstobject.c: + gstobject: unparent the controlbinding on dispose + +2012-04-05 21:07:55 +0200 Stefan Sauer + + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.c: + controller: dup the objects to avoid premature frees + +2012-04-05 21:06:14 +0200 Stefan Sauer + + * tests/check/gst/gstcontroller.c: + controller: add a finalizer for the test controlbindings + No idea why valgrind still inists that there are leaks. + +2012-04-05 18:42:30 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 7fda524 to 464fe15 + +2012-04-05 18:02:56 +0200 Sebastian Dröge + + * plugins/elements/gstdataurisrc.c: + gst: Update for GST_PLUGIN_DEFINE() API changes + +2012-04-05 14:17:16 +0200 Sebastian Dröge + + * docs/pwg/building-boiler.xml: + * gst/gstplugin.h: + * plugins/elements/gstelements.c: + gst: Change name parameter of GST_PLUGIN_DEFINE() to not take a string anymore + This will be needed when we later add support for static linking + of plugins without introducing new API or changing existing API. + +2012-04-05 13:23:00 +0200 Sebastian Dröge + + * configure.ac: + * gst/gstpluginfeature.c: + gstplugin: Add hack for handling 0.11.9X and 0.11.89.X with X>0 the same as 1.0.0 + Also update the version number to 0.11.89.1 + +2012-04-05 12:22:11 +0200 Mark Nauwelaerts + + * gst/gsttocsetter.c: + tocsetter: clear mutex upon free + +2012-04-05 10:56:22 +0200 Sebastian Dröge + + * gst/gstregistrybinary.h: + registry: Set registry version to 1.0.0 too + +2012-04-05 10:36:08 +0200 Wim Taymans + + Merge branch '0.10' + Conflicts: + plugins/elements/gstqueue2.c + +2012-04-05 10:03:02 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: stop waiting for more data after EOS + When we have EOS, read the remaining bytes in the buffer and make sure we don't + wait for more data. Also clip the output buffer to the amount of remaining + bytes. + +2012-04-05 09:56:52 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: check for filled buffer correctly + When using the ringbuffer mode, the buffer is filled when we reached the + max_level.bytes mark or the total size of the ringbuffer, whichever is smaller. + +2012-04-04 13:07:27 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: avoid waiting for a filled buffer + Use a threshold variable to hold the maximum distance from the current position + for with we will wait instead of doing a seek. + When using the ringbuffer and the requested offset is not available, avoid + waiting until the complete ringbuffer is filled but instead do a seek when the + requested data is further than the threshold. + Avoid doing the seek twice in the ringbuffer case. + Use the same threshold for ringbuffer and download buffering. + +2012-04-05 09:07:18 +0200 Alessandro Decina + + * gst/gstbuffer.c: + gstbuffer: fix compile warning + +2012-04-04 13:13:52 +0200 Sebastian Dröge + + * Makefile.am: + * configure.ac: + * docs/faq/developing.xml: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/running.xml: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/manual/basics-helloworld.xml: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/random/autotools: + * docs/version.entities.in: + * gst-element-check.m4.in: + * gst/Makefile.am: + * gst/gstplugin.c: + * gst/gstpreset.c: + * gst/gstregistry.c: + * gst/gstversion.h.in: + * gstreamer.spec.in: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/helpers/Makefile.am: + * libs/gst/net/Makefile.am: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-base.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-controller.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-net.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + * plugins/elements/Makefile.am: + * tests/benchmarks/Makefile.am: + * tests/check/Makefile.am: + * tests/check/gst/gstpreset.c: + * tests/examples/adapter/Makefile.am: + * tests/examples/controller/Makefile.am: + * tests/examples/manual/Makefile.am: + * tools/Makefile.am: + * tools/gst-launch.1.in: + * tools/gstreamer-completion: + * win32/common/config.h: + gst: Change versioning + Remove GST_MAJORMINOR and replace it by GST_API_VERSION + Also set GST_VERSION_{MAJOR,MINOR,MICRO,NANO} explicitely + now. + All versions are at 1.0.0 now for the release soon but + API/ABI can still change until the 1.0.0 release. + Next release versions until 1.0.0 will be 0.10.9X and + these will be release candidates. GST_VERSION_* will + nonetheless stay at 1.0.0.0. + +2012-04-04 12:25:40 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + docs/gst/gstreamer-sections.txt + gst/Makefile.am + gst/gst.c + gst/gst.h + gst/gstevent.c + gst/gstevent.h + gst/gstmessage.c + gst/gstmessage.h + gst/gstquark.c + gst/gstquark.h + gst/gstquery.c + gst/gstquery.h + gst/gsttoc.c + gst/gsttoc.h + gst/gsttocsetter.c + tests/check/Makefile.am + tests/check/gst/gsttoc.c + tests/check/gst/gsttocsetter.c + +2012-04-03 16:51:54 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: improve _set_size() + +2012-04-03 16:44:58 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: make get_sizes and _resize with ranges + Make the _get_sizes and _resize methods work on a range of memory to make them + more powerfull. + +2012-04-03 18:25:40 +0200 Mark Nauwelaerts + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: allow some more events before a segment event + +2012-04-03 15:46:29 +0200 Stefan Sauer + + * gst/gsttocsetter.c: + tocsetter: use new glib mutex api + +2012-04-02 23:17:21 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: fix compiler warning + gst-launch.c: In function ‘print_toc_entry’: + gst-launch.c:446:3: error: the size of array ‘spc’ can’t be evaluated [-Werror=vla] + gst-launch.c:446:3: error: variable-sized object may not be initialized + +2012-04-02 23:29:24 +0100 Tim-Philipp Müller + + * tests/check/gst/.gitignore: + tests: add new unit test binaries to .gitignore + +2012-04-02 23:28:15 +0100 Tim-Philipp Müller + + * gst/gst.c: + gst: ref new entry enum types + Fixes 'make check', again. + +2012-04-02 23:24:22 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new API to .def file + Fixes 'make check'. + +2012-04-02 23:23:46 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gsttoc.c: + toc: don't export private functions + +2012-04-02 23:17:21 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: fix compiler warning + gst-launch.c: In function ‘print_toc_entry’: + gst-launch.c:446:3: error: the size of array ‘spc’ can’t be evaluated [-Werror=vla] + gst-launch.c:446:3: error: variable-sized object may not be initialized + +2012-04-02 23:16:39 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translatable strings + +2012-04-02 23:01:17 +0200 Stefan Sauer + + Merge remote-tracking branch 'origin/master' + +2012-04-02 22:09:07 +0200 Stefan Sauer + + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gsttoc.c: + * gst/gsttoc.h: + * tests/check/gst/gsttoc.c: + * tests/check/gst/gsttocsetter.c: + toc: port to 0.11 + +2012-03-22 08:36:02 +0100 Stefan Sauer + + * tools/gst-launch.c: + gst-launch: add -c, --toc to print the toc + Print the nested chapter and edition structure of the chapters message. + +2012-03-28 23:15:41 +0400 Alexander Saprykin + + * docs/design/Makefile.am: + * docs/design/part-toc.txt: + docs: add overview of GstToc usage + +2012-03-14 21:14:23 +0400 Alexander Saprykin + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + docs: Add GstToc and GstTocSetter sections with related functions + +2012-03-14 21:13:22 +0400 Alexander Saprykin + + * tests/check/Makefile.am: + * tests/check/gst/gsttocsetter.c: + gstchecks: Add unit test for the GstTocSetter + +2012-03-14 21:12:22 +0400 Alexander Saprykin + + * tests/check/Makefile.am: + * tests/check/gst/gsttoc.c: + gstchecks: Add unit test for the GstToc + +2012-03-14 20:45:35 +0400 Alexander Saprykin + + * gst/Makefile.am: + * gst/gst.h: + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + Add new GstTocSetter interface + +2012-03-14 20:42:56 +0400 Alexander Saprykin + + * gst/gstquery.c: + * gst/gstquery.h: + Add new TOC query + +2012-03-14 20:41:48 +0400 Alexander Saprykin + + * gst/gstmessage.c: + * gst/gstmessage.h: + Add new TOC message + +2012-03-14 20:40:32 +0400 Alexander Saprykin + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + Add new TOC and TOC select events + +2012-03-14 20:01:51 +0400 Alexander Saprykin + + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gsttoc.c: + * gst/gsttoc.h: + Add generic table of contents (TOC) support + +2012-04-02 21:15:09 +0200 Stefan Sauer + + Merge branch '0.10' + Conflicts: + docs/gst/gstreamer-sections.txt + gst/Makefile.am + gst/gst.c + gst/gst.h + gst/gstevent.c + gst/gstevent.h + gst/gstmessage.h + gst/gstquark.c + gst/gstquark.h + gst/gstquery.c + gst/gstquery.h + tests/check/Makefile.am + +2012-04-02 15:30:04 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + libs/gst/base/gstbaseparse.c + +2012-04-02 15:13:24 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: always attempt to push if not-linked + This avoids ending up with plenty of pending data (since we'll only + try to parse/push one frame from the incoming buffer). + Fixes increasing memory consumption when parsers aren't linked + Conflicts: + libs/gst/base/gstbaseparse.c + +2012-04-02 15:13:24 +0200 Edward Hervey + + * libs/gst/base/gstbaseparse.c: + baseparse: always attempt to push if not-linked + This avoids ending up with plenty of pending data (since we'll only + try to parse/push one frame from the incoming buffer). + Fixes increasing memory consumption when parsers aren't linked + +2012-04-01 03:30:51 +0400 Руслан Ижбулатов + + * plugins/elements/gstfdsrc.c: + Timeout is not used on W32 + Fixes #673267 + +2012-04-02 11:09:50 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + trans: add transform_ip_on_passthrough + Add an option to control if transform_ip is called in passthrough mode or not. + for elements that don't want to look at the data in passthrough mode, this can + avoid some extra processing, mostly in subclasses. + +2012-03-22 08:36:02 +0100 Stefan Sauer + + * tools/gst-launch.c: + gst-launch: add -c, --toc to print the toc + Print the nested chapter and edition structure of the chapters message. + +2012-03-28 23:15:41 +0400 Alexander Saprykin + + * docs/design/Makefile.am: + * docs/design/part-toc.txt: + docs: add overview of GstToc usage + +2012-03-14 21:14:23 +0400 Alexander Saprykin + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + docs: Add GstToc and GstTocSetter sections with related functions + +2012-03-14 21:13:22 +0400 Alexander Saprykin + + * tests/check/Makefile.am: + * tests/check/gst/gsttocsetter.c: + gstchecks: Add unit test for the GstTocSetter + +2012-03-14 21:12:22 +0400 Alexander Saprykin + + * tests/check/Makefile.am: + * tests/check/gst/gsttoc.c: + gstchecks: Add unit test for the GstToc + +2012-03-14 20:45:35 +0400 Alexander Saprykin + + * gst/Makefile.am: + * gst/gst.h: + * gst/gsttocsetter.c: + * gst/gsttocsetter.h: + Add new GstTocSetter interface + +2012-03-14 20:42:56 +0400 Alexander Saprykin + + * gst/gstquery.c: + * gst/gstquery.h: + Add new TOC query + +2012-03-14 20:41:48 +0400 Alexander Saprykin + + * gst/gstmessage.c: + * gst/gstmessage.h: + Add new TOC message + +2012-03-14 20:40:32 +0400 Alexander Saprykin + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + Add new TOC and TOC select events + +2012-03-14 20:01:51 +0400 Alexander Saprykin + + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gsttoc.c: + * gst/gsttoc.h: + Add generic table of contents (TOC) support + +2012-04-01 12:01:34 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: reuse more code + +2012-04-01 11:42:52 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: + * win32/common/libgstreamer.def: + buffer: make function to find memory in a buffer + Make a function to find the memory blocks for a region in a buffer. + +2012-03-31 21:26:22 +0200 Stefan Sauer + + * gst/gstchildproxy.c: + childproxy: fix more missing GST_OBJECT -> G_OBJECT use + +2012-03-31 18:34:23 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: use buffer_wrap + +2012-03-31 17:10:35 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * win32/common/libgstreamer.def: + buffer: add peek_memory method + Add a peerk_memory method that simply fetches the memory at an offset without + refcounting or merging. + +2012-03-31 12:00:56 +0200 Wim Taymans + + * gst/parse/grammar.y: + grammar.y: fix childproxy code + It takes GObject and not GstObject now + +2012-03-30 22:46:02 +0200 Stefan Sauer + + * gst/gstbin.c: + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + childproxy: include the child name in the signal + +2012-03-30 22:44:31 +0200 Stefan Sauer + + * gst/parse/grammar.y: + parser: update for childproxy api changes + +2012-03-30 22:36:35 +0200 Stefan Sauer + + * gst/gstchildproxy.c: + childproxy: fix signal parameter types + +2012-03-30 22:17:09 +0200 Stefan Sauer + + * gst/gstbin.c: + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + * tests/check/gst/gstchildproxy.c: + childproxy: use GObject instead of GstObject + This makes it prossible to be used more widely. Fix implementations for the API + change. + +2012-03-30 22:01:55 +0200 Stefan Sauer + + * gst/gstchildproxy.c: + * gst/gstchildproxy.h: + childproxy: make get_child_by_name virtual + Allows implementations to use custom name->object mappings. + +2012-03-30 22:01:26 +0200 Stefan Sauer + + * gst/gstchildproxy.c: + childproxy: fix indentation + +2012-03-30 18:04:51 +0200 Wim Taymans + + * docs/design/part-buffer.txt: + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbytewriter.c: + * plugins/elements/gstfakesrc.c: + * tests/check/gst/gstbuffer.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/typefindhelper.c: + * win32/common/libgstreamer.def: + buffer: improve the buffer memory methods + gst_buffer_take_memory -> gst_buffer_insert_memory because insert is what the + method does. + Make all methods deal with ranges so that we can replace, merge, remove and map + a certain subset of the memory in a buffer. With the new methods we can make + some code nicer and reuse more code. Being able to deal with a subset of the + buffer memory allows us to optimize more cases later (most notably RTP headers + and payload that could be in different memory objects). + Make some more convenient macros that call the more generic range methods. + +2012-03-30 16:53:09 +0200 Mark Nauwelaerts + + * plugins/elements/gsttypefindelement.c: + typefindelement: plug caps leaks + +2012-03-30 16:53:05 +0200 Mark Nauwelaerts + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: also unmap collected mapped buffers + +2012-03-30 16:53:00 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasetransform.c: + basetransform: plug caps leak + +2012-03-30 11:58:20 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: Rename ::event() to ::sink_event() for consistency + +2012-03-30 11:49:16 +0200 Edward Hervey + + * libs/gst/base/gstbasesrc.h: + basesink: lower GST_BASE_SRC_FLAG_LAST + It wouldn't leave that much room for subclass users + +2012-03-30 08:55:33 +0200 Edward Hervey + + * win32/common/libgstbase.def: + win32: Update defs file + +2012-03-29 18:03:35 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter.c: + bytewriter: Actually commit the .c file changes too + +2012-03-29 17:59:28 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter.h: + bytewriter: Add unchecked/inline variant of gst_byte_writer_put_buffer() + +2012-03-29 17:53:47 +0200 Edward Hervey + + * gst/gstquery.c: + gstquery: Fix annotation + +2012-03-29 17:44:02 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Flush the internal queue when we see GST_FLOW_FLUSHING + Ensures that we don't end up with stale contents (like GstQuery) in + the internal GQueue after any blocking upstream thread returns. + +2012-03-29 17:43:17 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Don't unref GstQuery travelling through the queue + Unlike events and buffers, the reference is not given to us + +2012-03-29 17:08:49 +0200 Mark Nauwelaerts + + * gst/gstquery.c: + query: parsing allocation query need not provide reffed caps + ... in line with other query parsing function. + +2012-03-29 15:45:00 +0200 Fabrizio (Misto) Milo + + * gst/gstcaps.c: + caps: spelling fixes + +2012-03-29 15:28:44 +0200 Edward Hervey + + * gst/gstelement.h: + gstelement: lower GST_ELEMENT_FLAG_LAST + It wouldn't leave that much room for subclass users + +2012-03-29 15:18:33 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: Fix unitialized variable + gcc 4.5 complains otherwise :( + +2012-03-29 14:54:53 +0200 Sebastian Dröge + + Merge remote-tracking branch 'origin/0.10' + Conflicts: + plugins/elements/gstmultiqueue.c + +2012-03-29 14:45:41 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Wake up all not-linked streams when a stream switches from linked to not-linked + We reset all the waiting streams, let them push another buffer to + see if they're now active again. This allows faster switching + between streams and prevents deadlocks if downstream does any + waiting too. + Also improve locking a bit, srcresult must be protected by the + multiqueue lock too because it's used/set from random threads. + +2012-03-29 14:32:24 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Recompute high-time too when flushing, not only high-id + +2012-03-29 13:39:40 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Only wait until the active pad's running time is reached if the active pad already saw data + Otherwise we might block forever because upstream (e.g. multiqueue) is waiting + for the previously active stream to return forever (which is waiting here + in inputselector) before pushing something on the newly selected stream. + +2012-03-29 13:34:50 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstclock.c: + * gst/gstelementfactory.c: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstiterator.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmessage.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstpipeline.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gstsample.c: + * gst/gstsegment.c: + * gst/gststructure.c: + * gst/gsttask.c: + * gst/gsttrace.c: + * gst/gsturi.c: + * gst/gstvalue.c: + docs: update more documentation + +2012-03-28 18:12:23 +0200 Wim Taymans + + * docs/pwg/advanced-events.xml: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstevent.c: + * gst/gstminiobject.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesrc.h: + review some docs + +2012-03-28 16:44:34 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: simplify and refactor _span and _merge + Unify the _span and _merge code paths and simplify now that we only use this + internally. + +2012-03-28 15:16:01 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: we always call _span with the buffer size + +2012-03-28 15:12:05 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: move some code around + +2012-03-28 15:08:44 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: we call _span always with 0 offset + +2012-03-28 13:08:59 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: remove always FALSE function argument + +2012-03-28 16:39:54 +0200 Mark Nauwelaerts + + * gst/gstbuffer.c: + buffer: delay buffer unref until buffer no longer needed + +2012-03-28 12:44:44 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstadapter.c: + * tests/check/gst/gstbuffer.c: + * win32/common/libgstreamer.def: + buffer: unify buffer merge methods + Add gst_buffer_append() which appends the memory blocks from one buffer to + another. Remove the old inefficient _merge() and _join() methods which forced a + premature memcpy in most cases. + Remove the _is_span() and _span() methods they are not needed anymore now that + we can _append(). Merging and spanning will be delayed until mapping or maybe + not at all when the element can deal with the different memory blocks. + +2012-03-27 15:24:49 -0400 Olivier Crête + + * gst/gstghostpad.c: + gstpad: Fix typo in docstring + +2012-03-27 15:24:49 -0400 Olivier Crête + + * gst/gstghostpad.c: + gstpad: Fix typo in docstring + +2012-03-27 15:16:55 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: re-enable _span offset calculations + when we _span two complete buffers, we can copy offsets and timestamps. + +2012-03-27 15:00:38 +0200 Wim Taymans + + * gst/gsttrace.c: + trace: add refcount to trace debug + +2012-03-27 14:59:06 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add more _is_writable checks + Add some checks to assert on writability for functions that modify metadata. + +2012-03-27 12:40:36 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: remove const from get/set_param + Remove the const from the GstCaps in get/set_param. set_param modifies + the refcount of the caps. + Don't increment the refcount of the caps result of get_param like we + do with other objects. + Update some annotiations. + +2012-03-27 12:39:53 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: fix annotation for _release + _release takes ownership of the buffer + +2012-03-27 12:31:18 +0200 Sebastian Dröge + + * gst/gstbus.c: + * gst/gstbus.h: + bus: Change the timeout argument type of gst_bus_poll() from GstClockTimeDiff to GstClockTime + This is more consistent with the other GstBus methods that have a timeout. + +2012-03-26 19:13:21 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: remove old code + Remove attempt to delay _make_writable + +2012-03-26 18:07:35 +0200 Mark Nauwelaerts + + * gst/gstcaps.c: + caps: ensure writable caps prior to modification + +2012-03-26 17:38:50 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: check min/max_buffers + +2012-03-26 17:35:18 +0200 Wim Taymans + + * gst/gstquery.c: + query:fix copy-and-paste problem + +2012-03-26 11:54:59 +0200 Wim Taymans + + Replace master with 0.11 + +2012-03-23 18:51:52 +0100 Mark Nauwelaerts + + * gst/gstutils.c: + utils: add and improve debug messages + ... so they end up in a more expected debug category rather than oblivion. + +2012-03-22 15:54:55 +0100 Wim Taymans + + * configure.ac: + back to devel + +2012-03-22 15:49:36 +0100 Wim Taymans + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect-build.stamp: + * docs/plugins/inspect.stamp: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Release 0.11.3 + +2012-03-22 15:22:57 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasetransform.c: + basetransform: remove automatic and undocumented setting of always_in_place + ... which controls how to (forcibly) deal with (non-)writable data and + is not necessarily related to identical caps. + In particular, it is also not so helpful anymore with a more advanced + GstVideoFilter subclass which always has a transform_ip method currently, + even though its subclass may not have a corresponding _ip method. + +2012-03-22 10:45:06 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + +2012-03-22 08:35:25 +0100 Stefan Sauer + + * tools/gst-launch.c: + gst-launch: don't shadow global variable + +2012-03-21 12:10:21 +0100 Wim Taymans + + * libs/gst/Makefile.am: + dist net directory only once + +2012-03-21 09:00:45 +0100 Sebastian Dröge + + * gst/gstquery.c: + query: Only allow fixed caps in the accept-caps query + +2012-03-20 17:08:28 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: do queries more directly + Just call our internal query function instead of going through the pad and the + query handler etc. + +2012-03-20 17:08:00 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: add some performance debug + +2012-03-20 13:14:55 +0100 Wim Taymans + + * gst/gstpad.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue2.c: + pad: improve docs of get/pull_range + Improve the docs of the get/pull_range functions, define the lifetime of the + buffer in case of errors and short reads. + Make sure the code does what the docs say. + +2012-03-20 10:20:29 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * tests/check/gst/gstevent.c: + buffer: improve gst_buffer_new_wrapped_full() + Make it possible to wrap all kinds of memory by exposing all properties to + gst_buffer_new_wrapped_full(). This makes it possible to also create writable + memory without a free function or memory with extra padding. + +2012-03-19 11:45:27 +0100 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: handle serialized queries + +2012-03-16 22:51:14 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: make more stuff private + +2012-03-16 22:25:38 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: small cleanups + +2012-03-16 21:37:10 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/filesrc.c: + pad: change the semantics of get/pull_range a little + Make it so that one can specify a buffer for get/pull_range where the downstream + element should write into. When passing NULL, upstream should allocate a buffer, + like in 0.10. + We also need to change the probes a little because before the pull probe, there + could already be a buffer passed. This then allows us to use the same PROBE + macro for before and after pulling. + While we're at the probes, make the query probe more powerful by handling the + GST_PAD_PROBE_DROP return value. Returning _DROP from a query probe will now + return TRUE upstream and will not forward the probe to the peer or handler. + Also handle _DROP for get/pull_range properly by not dispatching to the + peer/handler or by generating EOS when the probe returns DROP and no buffer. + Make filesrc handle the non-NULL buffer passed in the get_range function and + skip the allocation in that case, writing directly into the downstream provided + buffer. + Update tests because now we need to make sure to not pass a random value in the + buffer pointer to get/pull_range + +2012-03-16 21:36:33 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: proxy allocation query + +2012-03-16 18:39:08 +0100 Wim Taymans + + * gst/gstevent.c: + event: fix docs a little, alloc_buffer is gone + +2012-03-15 22:09:02 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstmemory.h: + * gst/gstquark.c: + * gst/gstquark.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstreamer.def: + bufferpool: split bufferpool configuration + Make separate methods to control the bufferpool and the allocator used by the + bufferpool. + Make it possible to change the allocator of a pool. + +2012-03-15 20:23:59 +0100 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstreamer.def: + query: rework the ALLOCATION query + Separate the bufferpool and allocator hints in the allocation query, some + of the values don't always make sense together. + Keep the bufferpool and its configuration together. + Keep the allocator and its parameters together. + Allow for multiple bufferpool configurations in the query. + +2012-03-15 16:50:31 +0100 Wim Taymans + + * gst/gstpad.c: + pad: comment and debug improvement + +2012-03-15 16:49:33 +0100 Wim Taymans + + * gst/gstutils.c: + utils: improve debug + also fix a potential memory leak + +2012-03-15 14:28:22 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-03-15 14:01:44 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + GstBufferPoolParams -> GstBufferPoolAcquireParams + Because those flags are not from the bufferpool but for the acquire function. + +2012-03-15 13:28:28 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstcompat.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstvalue.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstqueue2.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + * win32/common/libgstreamer.def: + memory: group allocation parameters in a struct + Group the extra allocation parameters in a GstAllocationParams structure to make + it easier to deal with them and so that we can extend them later if needed. + Make gst_buffer_new_allocate() take the GstAllocationParams for added + functionality. + Add boxed type for GstAllocationParams. + +2012-03-15 00:25:50 +0100 Wim Taymans + + * plugins/elements/gstfilesrc.c: + filesrc: only update buffer size on short read + +2012-03-15 00:24:40 +0100 Wim Taymans + + * gst/gstquery.c: + query: fix copy function + Copy the structure too. + +2012-03-15 00:23:57 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: fix maxsize after align + when we align the data pointer, make sure to update the maxsize. + Add some more debug + +2012-03-14 22:58:34 +0100 Wim Taymans + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue: remove useless PROXY_ALLOCATION flag + +2012-03-14 21:32:22 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + memory: Add 0 padding + Change gst_allocator_alloc() so that we can also spicify flags and padding. + Add 2 new flags to mark the memory 0 prefixed/padded. This allows us to + remove some resizes in the base classes. + When allocating memory, memset prefix and padding with 0 when the flags tell + us to. + On resize, clear the zero padding flags if we can't guarantee the memory is + still 0 filled. + Update tests. + +2012-03-14 19:37:22 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + query: also include padding in ALLOCATION query + Negotiating padding is needed on second thought so include it in the + ALLOCATION query. + Make the bufferpool take padding into account when allocating. + Make basesrc take padding into account. + Use padding and prefix when allocating in basetransform. + +2012-03-14 18:45:55 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: take prefix into account when allocating + Take into account the prefix that we received from the allocation query and use + it to allocate and resize a larger buffer. + +2012-03-14 17:16:36 +0100 Mark Nauwelaerts + + * gst/gstbufferpool.c: + bufferpool: free owned discarded pool config + +2012-03-14 16:27:31 +0100 Wim Taymans + + * gst/gstpad.c: + * libs/gst/base/gstbasesink.c: + pad: implement DRAIN handling + When we forward the DRAIN query and there is nothing to forward it to, assume we + are drained. + When a basesink receives a drain query, reply with TRUE. + +2012-03-14 16:14:12 +0100 Wim Taymans + + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: add new drain query + With the new serialized downstream queries we can implement a drain query that + makes an element waits until a downstream element replies to the query. + +2012-03-14 16:01:15 +0100 Wim Taymans + + * gst/gstpad.c: + pad: make serialized queries push sticky events first + Before we can proceed with a serialized query, we need to be sure that all + sticky events were pushed. + +2012-03-14 15:42:47 +0100 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue2.c: + queues: warn when receiving a serialized event + .. until we implement it. + +2012-03-14 15:42:33 +0100 Wim Taymans + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: add support for serialized queries + +2012-03-14 15:29:12 +0100 Wim Taymans + + * gst/gstpad.c: + pad: take stream lock on serialized queries + +2012-03-14 15:16:56 +0100 Wim Taymans + + * gst/gstpad.c: + pad: enforce correct query direction + +2012-03-14 14:51:16 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: register queries like events + Also register queries with a QueryType that allows us to check if the event is + sent in the right direction. Add a serialized query type because we will need + this for the allocation query. + Remove the QueryTypeDefinition stuff, it is not used anymore and we now use + custom queries and separate API for them. + Update defs. + +2012-03-14 12:42:00 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: add more debug + +2012-03-13 15:40:37 +0100 Wim Taymans + + * gst/gstbin.c: + bin: remove old compat mode + +2012-03-13 15:40:23 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: small docs update + +2012-03-13 10:04:36 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: remove gst_caps_union() + Remove gst_caps_union(), use gst_caps_merge(). This function was not used + anymore and it is unclear what the difference is with _merge(). + +2012-03-12 23:05:01 +0000 Tim-Philipp Müller + + * configure.ac: + configure: bump AS_LIBTOOL version + API was added to collectpads2 + +2012-03-12 23:02:48 +0000 Tim-Philipp Müller + + * configure.ac: + configure: backport AS_LIBTOOL version from 0.10.36 release + Might fix issues with missing symbols for people who install GStreamer + from source and at some point jumped back and forth between git master + and the 0.10.36 release (or 0.10. branch). + +2012-03-12 23:08:00 +0100 Stefan Sauer + + * libs/gst/base/gstcollectpads2.c: + docs: fix function name and typo + +2012-03-12 19:52:03 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: get template caps only once + Get the template caps of the pads only once, avoids unecessary ref + and unrefs. + +2012-03-12 18:34:30 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: delay _make_writable() until needed in _normalize() + Delay _make_writable() until we actually found a list and need to update the + caps. + +2012-03-12 18:25:38 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: shortcut simplify earlier + A simple caps is already simplified, no need to check for fixedness. + +2012-03-12 18:22:05 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: small cleanup, remove const + +2012-03-12 18:02:27 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: small cleanups + +2012-03-12 16:40:38 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: small doc improvement + +2012-03-12 16:18:45 +0200 Sreerenj Balachandran + + * configure.ac: + configure.ac: bump required GLib to 2.31.14 + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=671911 + +2012-03-12 13:50:45 +0000 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: update porting-to-0.11.txt a little + +2012-03-12 12:35:07 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: fix some 0.11 FIXMEs + +2012-03-12 12:21:34 +0100 Wim Taymans + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + caps: make _normalize take ownership of input + Make gst_caps_normalize() take ownership of the input so that it can more + intelligently decide when to copy or not. + +2012-03-12 11:38:37 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstmeta.c: + * gst/gstmeta.h: + * gst/gstquery.c: + * gst/gstregistrychunks.c: + * plugins/elements/gstcapsfilter.c: + * tests/check/gst/gstcaps.c: + * win32/common/libgstreamer.def: + caps: _do_simplify() -> _simplify() + Rename _do_simplify() to _simplify(). The name was introduced as a replacement + method for a deprecated method but we can now rename it again. + Fix some docs. + +2012-03-12 10:42:23 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstregistrychunks.c: + * plugins/elements/gstcapsfilter.c: + * tests/check/gst/gstcaps.c: + caps: improve _do_simplify + Make gst_caps_do_simplify() take ownership of the input caps and produce a + simplified output caps. This removes the requirement of having writable input + caps and the method can make the caps writable only when needed. + +2012-03-12 10:41:28 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + tests: fix unit test + with the new caps API, there is more sharing and less copying going on so the + unit test refcounts are different. + +2012-03-12 09:03:42 +0000 Christian Fredrik Kalager Schaller + + * docs/faq/general.xml: + update license link to point to 2.1 license, instead of just generic lgpl file, which is always the latest and thus not correct for gstreamer + +2012-03-11 18:57:44 +0100 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstpadtemplate.c: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstcaps.c: + caps: avoid using in-place oprations + Rework some caps operations so they don't rely on writable caps but instead take + ownership of the input caps and do _make_writable() only when needed. + Remove some const from caps functions, it does not make much sense for + refcounted objects and does not allow us to return a refcount to the const input + caps. + Rework the base classes fixate vmethods to not operate on the caps in-place. + All this saves us around 30% of caps and structure copy and new operations. + +2012-03-11 17:22:01 +0100 Wim Taymans + + * gst/gststructure.c: + structure: add allocation debug + +2012-03-10 09:25:43 +0100 Wim Taymans + + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * libs/gst/base/gsttypefindhelper.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefind: remove const from refcounted GstCaps + Having const on refcounted objects require us to make copies instead of simply + taking a ref, don't do that. + +2012-03-10 09:15:43 +0100 Wim Taymans + + * gst/gstregistrychunks.c: + registry: avoid copy when caps are fixed + Avoid doing a useless copy when the caps are fixed and simplify will not do + anything. + +2012-03-09 16:14:02 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: small optimizations + shortcut heavy work when buffer_resize does nothing. + Avoid an extra _ref when mapping a buffer. + Add some G_LIKELY. + +2012-03-09 15:03:11 +0100 Wim Taymans + + * docs/design/part-bufferpool.txt: + bufferpool: fix array types + +2012-03-09 14:30:01 +0100 Wim Taymans + + * docs/design/part-buffer.txt: + * docs/design/part-bufferpool.txt: + * docs/design/part-memory.txt: + * docs/design/part-meta.txt: + * docs/design/part-overview.txt: + * docs/design/part-scheduling.txt: + docs: update docs + +2012-03-09 11:53:54 +0100 Wim Taymans + + * gst/gstpad.c: + pad: also push sticky events on new event + Make a helper function check_sticky to check and push pending sticky events. + Move the handling of the result of pushing the sticky event inside the + push_event function, we need to mark the event as received when it was pushed + correctly. + Move the sticky events code outside of gst_pad_push_event_unchecked and + make it purely handle sending the event to the peer. + when pushing a sticky event, first store it on the pad. Then check and push any + pending sticky events when we get a serialized or sticky event on a srcpad. This + fixes the issue where sticky events are not pushed when an event is pushed. + +2012-03-09 11:52:29 +0100 Wim Taymans + + * gst/gstpad.c: + pad: store the received result from _foreach + If the foreach function changes the received state of the sticky event, make + sure we remember that. + +2012-03-09 11:52:11 +0100 Wim Taymans + + * gst/gstpad.c: + pad: add comment + +2012-03-09 11:49:08 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + test: add test to check sticky events order + Sticky events pushed on an unlinked pad should be stored on the pad. When the + pad is then linked and an event is pushed, the event should be merged with the + already existing sticky events and then the sticky events should be pushed in + the order that they were originally pushed. + +2012-03-09 11:48:40 +0100 Wim Taymans + + * tests/check/gst/gstutils.c: + test: fix typo in comment + +2012-03-08 20:08:20 +0000 Tim-Philipp Müller + + * tests/check/pipelines/seek.c: + tests: port pipeline/seek test to 0.11 + Doesn't fail in 0.11 of course, at least not on my machine. + +2012-03-08 19:55:30 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + common + gst/gstpad.h + gst/gsttask.c + libs/gst/base/gstcollectpads2.h + +2012-03-08 16:30:49 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + * gst/gsttask.c: + pad, task: improve debug logging + +2012-03-08 16:26:44 +0000 Tim-Philipp Müller + + * gst/gstpad.h: + * libs/gst/base/gstcollectpads2.h: + pads, collectpads2: get rid of superfluous brackets around static rec mutex calls + Makes it possible to define those calls to something for tracing. + +2012-03-08 16:25:20 +0000 Tim-Philipp Müller + + * common: + common: update common module + For make foo/bar.check-norepeat target. + +2012-03-08 15:23:56 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/pipelines/.gitignore: + * tests/check/pipelines/seek.c: + tests: add minimal basesrc ! sink seeking unit test + Should reproduce 'GStreamer-WARNING **: wrong STREAM_LOCK count 0' + warnings (with make pipelines/seek.torture or pipelines/seek.forever + anyway, since it appears to be racy). + https://bugzilla.gnome.org/show_bug.cgi?id=670846 + +2011-12-26 00:18:29 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstreamer.def: + value: remove gst_value_register_{subtract,union,intersect}_func() API + There isn't really any need to provide public API for that. It's not + used anywhere in practice, and we aim to provide an API that works + for GstCaps, not some kind of generic set manipulation API based on + GValue. Making this private also makes it easier to optimise this + later. We can always put it back if someone actually needs it. + +2012-03-08 10:47:39 +0100 Wim Taymans + + * plugins/elements/gsttee.c: + tee: fix refcount error + +2012-03-08 09:45:06 +0100 Wim Taymans + + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: return ANY for a pad without template + Because gst_pad_get_pad_template_caps() returns ANY when there is no template, + the query caps function should also return ANY when there is no template (and no + pad current caps) instead of EMPTY. + +2012-03-08 09:44:21 +0100 Wim Taymans + + * gst/gstpad.c: + pad: small cleanup + +2012-03-07 15:34:36 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: add comment + +2012-03-08 10:32:02 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix merge mistake + +2012-03-08 10:19:52 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbaseparse.c + libs/gst/base/gstbasetransform.c + plugins/elements/gsttee.c + +2012-03-07 11:23:56 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.h: + baseparse: arrange for properly disjoint frame flags + +2012-03-06 15:17:05 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: delay pool activation + Delay the activation of the bufferpool until we actually need a buffer from the + pool. + +2012-03-06 12:28:02 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix 'self-comparison always evaluates to true' + This was really a bug. + +2012-03-06 12:24:53 +0100 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Fix 'use of logical '&&' with constant operand' compiler warning + This is actually a real bug. + +2012-03-06 12:23:15 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Fix 'equality comparison with extraneous parentheses' compiler warning + +2012-03-06 12:16:19 +0100 Sebastian Dröge + + * gst/gst.c: + gst: Fix 'comparison of unsigned enum expression >= 0 is always true' compiler warning + +2012-03-05 15:23:46 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: don't propose_allocation before negotiation + Answer the allocation query with FALSE when we are not negotiated yet because at + that point we have no idea if we need to proxy the allocation query or not. + +2012-03-05 14:41:12 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix handling of multiple newsegment events + Previously only the last would be pushed, which would cause + invalid running times downstream. This also fixes the handling + of update newsegment events. + +2012-03-05 14:25:57 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Also flush the close_segment + Pushing this after flushing will confuse downstream. + +2012-03-05 14:23:17 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Remove obsolete code and move gap handling to the correct place + The segment start adjustment code in pull mode should never trigger + anymore because the bisection code earlier would have already made + sure that we're at the desired position. + Also move the gap handling some lines below after sending the currently + configured segments. Otherwise we might fill gaps in a segment that is + not configured downstream yet. + +2012-03-05 13:12:18 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Clear some more state when receiving FLUSH_STOP + Like pending serialized events and the currently cached buffer. + +2012-03-05 13:00:38 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Only queue serialized events for sending them later + +2012-03-05 00:34:36 +0000 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + libgstcheck: export gst_consistency_checker_add_pad() + Fix build of the adder unit test in -base again. + +2012-03-02 17:32:28 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: refine metadata filter and transform + Add a vmethod to filter metadata that should be passed upstream. By default, + don't pass anything. + Add a vmethod to transform metadata from the input buffer to the output buffer. + By default, nothing is transformed or copied. + +2012-03-02 17:04:05 +0100 Wim Taymans + + * gst/gst.h: + gst: include gstmeta.h + +2012-03-02 17:03:49 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: add more debug info + +2012-03-02 13:02:46 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-03-02 13:02:37 +0100 Wim Taymans + + * tests/check/gst/gstmeta.c: + tests: improve metadata test + +2012-03-02 12:45:23 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmeta.h: + meta: add boolean to signal a region copy + Add a boolean to the metadata copy transform that signals if a only a + region is copied. + +2012-03-02 12:16:03 +0100 Stefan Sauer + + * libs/gst/check/gstconsistencychecker.c: + consitencychecker: don't fail on multiple flush_start events + This seems to be okay after a irc discussion. + +2012-03-02 11:57:52 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: transform docs + Use gst- prefix for metadata transform types. + +2012-03-02 11:04:21 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: fix comment + +2012-03-02 11:05:48 +0100 Sebastian Dröge + + * Android.mk: + * Makefile.am: + * docs/gst/Makefile.am: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstchildproxy.c: + * gst/gstelement.c: + * gst/gstmarshal.list: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstregistry.c: + * gst/gsturi.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstindex.c: + * libs/gst/base/gstpushsrc.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gsttypefindelement.c: + * win32/common/gstmarshal.c: + * win32/common/gstmarshal.h: + gst: Remove gstmarshal.[ch] completely and use the generic marshaller + Fixes bug #671130. + +2012-03-02 10:51:42 +0100 Sebastian Dröge + + * gst/Makefile.am: + gst: Don't install gstmarshal.h + The generic, FFI based marshaller should be used instead of these + and we definitely shouldn't export the marshallers in our public API. + +2012-03-01 17:39:17 +0100 Wim Taymans + + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gstmeta.c: + meta: improve debugging + Add category for metadata debug + +2012-03-01 17:38:54 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: improve debugging + +2012-03-01 17:38:27 +0100 Wim Taymans + + * gst/gstpad.c: + pad: improve debugging + +2012-03-01 15:18:04 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: remove metadata tagged with the memory tag + Remove metadata that describes the particular memory of the buffer it is + attached to. We need to do this because in non-passthrough mode we will allocate + new memory for our output buffer. + +2012-03-01 15:17:37 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: add tag for memory metadata + +2012-03-01 14:49:38 +0100 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + query: add method to remove allocation_meta + Also g_return_if_fail for out-of-bounds access instead of silently failing. + +2012-03-01 14:30:58 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: improve propose_allocation + Improve the propose allocation vmethod by passing the downstream allocation + query to it. This way the vmethod implementation can use properties of the + downstream allocation to generate the upstream query result. If there is no + downstream quety, it means that the element is working in passthrough mode. + Implement a default decide_allocation. + +2012-03-01 11:11:43 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: clear allocation parameters in passthrough + Clear the allocation parameters when we operate in passthrough. + +2012-03-01 11:06:49 +0100 Wim Taymans + + * tests/check/elements/capsfilter.c: + * tests/check/elements/tee.c: + * tests/check/elements/valve.c: + * tests/check/gst/capslist.h: + * tests/check/gst/gstelementfactory.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gststructure.c: + * tests/check/pipelines/parse-launch.c: + * tests/check/pipelines/queue-error.c: + tests: fix old caps in tests now that core warns + +2012-03-01 14:51:26 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/check/gstconsistencychecker.c: + libs: Fix some merge mistakes + +2012-03-01 14:43:01 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstcollectpads2.c + libs/gst/check/gstconsistencychecker.c + +2012-02-28 12:03:46 +0100 Mark Nauwelaerts + + * gst/gstpad.c: + pad: fix some debug message typos + +2012-02-29 21:57:00 +0100 Stefan Sauer + + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstconsistencychecker.h: + consitencychecker: add handling for sink-pads + Add a pad-probe for sink-pads. One can now add extra pads (belonging to the same + element) to a checker. This allows us to extend the checks. + +2012-02-29 17:20:23 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmeta.c: + * gst/gstmeta.h: + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + * tests/check/gst/gstmeta.c: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + meta: split registration of API and implementation + Split out the registration of the metadata API and its implementation. Make a + GType for each metadata API. This allows us to store extra information with the + API type such as the tags. + Change the buffer API so that we can get the metadata using the API GType. + Change the query API so that we use the metadata API GType in the allocation + query instead of a string. + Update netaddress and unit tests + +2012-02-29 16:00:22 +0100 Wim Taymans + + * gst/gstminiobject.h: + minobject: small .h indent fix + +2012-02-29 12:41:44 +0000 Tim-Philipp Müller + + * gst/gststructure.c: + structure: print a g_warning() if someone tries to construct 0.10-style raw audio/video caps + +2012-02-29 08:44:04 +0100 Stefan Sauer + + * libs/gst/check/gstconsistencychecker.c: + consistencychecker: also check for duplicated flush_starts + +2012-02-28 20:36:59 +0100 Stefan Sauer + + * libs/gst/base/gstcollectpads2.c: + collectpads2: add more logging + +2012-02-28 16:17:47 +0100 Wim Taymans + + * gst/gstmeta.h: + * libs/gst/net/gstnetaddressmeta.c: + * tests/check/gst/gstmeta.c: + meta: add return vale to transform + Add a boolean return value so that we can see when a transform fails. + +2012-02-28 12:52:00 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + * win32/common/libgstreamer.def: + meta: add method to check for a tag + +2012-02-28 12:51:27 +0100 Wim Taymans + + * tests/check/gst/gstmeta.c: + tests: fix unit test + +2012-02-28 11:34:48 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + * libs/gst/net/gstnetaddressmeta.c: + meta: add support to tagging the metadata + Add support for adding tags to the metadata. with some standard keys, this + should make it possible to describe what the metadata refers to. We should be + able to use this information to decide if a transformation destroys the metadata + or not. + +2012-02-27 13:35:10 +0100 Edward Hervey + + * gst/gstquery.c: + * tools/gst-inspect.c: + Suppress deprecation warnings in selected files, for g_value_array_* mostly + +2012-02-27 11:46:08 +0100 Wim Taymans + + * tests/check/gst/gstbus.c: + tests: increase bus test timeout + +2012-02-21 20:43:48 +0000 Tim-Philipp Müller + + * tests/check/gst/gstdatetime.c: + tests: make datetime test more reliably when comparing two almost identical nows + Account for rounding errors in some places, and that two nows are + not always entirely identical, so allow some leeway when comparing + microseconds and seconds. Ran into this too often, esp. when the + system is under load. + +2012-02-27 09:48:06 +0100 Wim Taymans + + * gst/gst.h: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstbus.c: + * gst/gstbus.h: + remove some useless includes in .h + +2012-02-27 09:02:07 +0100 Wim Taymans + + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstsystemclock.c: + * libs/gst/net/gstnetclientclock.c: + * tests/check/gst/gstsystemclock.c: + * win32/common/libgstreamer.def: + clock: make more stuff private + Expose methods to get and set the timeout because subclasses uses this. + +2012-02-26 20:45:14 +0100 Wim Taymans + + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + systemclock: make more stuff private + +2012-02-26 20:44:50 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: make more stuff private + +2012-02-26 16:32:32 +0100 Wim Taymans + + * gst/gstbus.c: + * gst/gstbus.h: + bus: make more fields private + +2012-02-27 00:09:57 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + fdsink: fix compilation after merge + +2012-02-27 00:08:39 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + NEWS + RELEASE + configure.ac + docs/plugins/gstreamer-plugins.hierarchy + docs/plugins/inspect/plugin-coreelements.xml + libs/gst/base/gstcollectpads.c + libs/gst/base/gstcollectpads2.c + plugins/elements/gstfdsink.c + win32/common/config.h + win32/common/gstenumtypes.c + win32/common/gstversion.h + +2012-02-26 23:11:23 +0100 Stefan Sauer + + * libs/gst/base/gstcollectpads2.c: + collectpads2: rescue the annotation from collectpads + +2012-02-26 23:10:58 +0100 Stefan Sauer + + * libs/gst/base/gstcollectpads.c: + docs: fix a typo in comment + +2012-02-26 22:57:02 +0100 Stefan Sauer + + * libs/gst/base/gstcollectpads2.c: + collectpads2: move "MT save" tags to doc body + It is not useful to have "MT safe" tags randomly in body, returns or since paragraphs. + +2012-02-25 15:18:00 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + fdsink: implement GstBaseSink::query instead of messing with the pad + +2012-02-25 15:08:55 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + fdsink: implement SEEKING query + We may or may not support seeking. stdout to a + terminal doesn't support seeking, for example, but + ... ! fdsink > file.foo just might. + +2012-02-25 15:07:43 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesink.c: + filesink: implement SEEKING query + We may or may not do seeking, depends on the + output file/device really, it doesn't have to + be a file after all. + +2012-02-25 15:07:05 +0000 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + fakesink: answer SEEKING query + We don't do seeking, in case anyone wants to know. + +2012-02-24 23:39:30 +0000 Tim-Philipp Müller + + * gst/gstregistrybinary.c: + registry: fix lseek() return code handling + lseek() returns the offset if successful, and this is != 0 and + does not indicate an error. And if it does actually fail, don't + return FALSE (0) as an int, but -1. None of these things are + likely to have made a difference, ever. I don't think the offset + seek can ever actually happen, the current file position and the + current offset should always be increased in lock step, unless + there was an error in which case we'd just error out. + +2012-02-24 23:19:51 +0000 Tim-Philipp Müller + + * gst/gstregistrybinary.c: + registry: don't forget to clean up registry temp file in another error case + Also clean up temp file if we get an error during write() rather + than just when doing fsync() or close(). + +2012-02-24 15:24:42 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix race + After a writer has written to its reserved write location, it can only make the + location available for reading if all of the writers with lower locations have + finished. + +2012-02-24 12:53:52 +0100 Wim Taymans + + * plugins/elements/gstdataurisrc.c: + * tests/check/elements/dataurisrc.c: + dataurisrc: fix docs and unit test + +2012-02-24 12:51:24 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix subtle race + Fix a race where the reader would see the updated the tail pointer before the + write could write the data into the queue. Fix this by having a separate reader + tail pointer that is only incremented after the writer wrote the data. + +2012-02-24 11:00:21 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * plugins/elements/gstcapsfilter.c: + * win32/common/libgstbase.def: + basetransform: fix reconfigure methods + Rename gst_base_transform_suggest to gst_base_transform_reconfigure_sink because + that is what it does. Also remove the caps and size because that is not needed. + Rename gst_base_transform_reconfigure to gst_base_transform_reconfigure_src. + Remove some old unused code in capsfilter. + +2012-02-24 10:23:27 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * libs/gst/net/gstnetaddressmeta.c: + * tests/check/gst/gstmeta.c: + * win32/common/libgstreamer.def: + meta: flesh out the metadata transform + Flesh out the transform method. Add a type and extra info to the transform + function so that implementation can transform the metadata. + Remove the copy function and replace with the more generic transform. + +2012-02-24 10:23:17 +0100 Wim Taymans + + * docs/design/part-meta.txt: + docs: update docs + +2012-02-23 08:48:22 -0800 David Schleef + + * tests/check/Makefile.am: + Fix gap in Makefile + +2012-02-23 08:48:10 -0800 David Schleef + + * gst/gstmemory.c: + spelling fix + +2011-12-26 16:45:20 -0800 David Schleef + + * gst/gstpoll.c: + poll: fix spelling of writable + +2012-02-23 15:32:33 +0100 Wim Taymans + + * gst/gstmemory.h: + memory: add user_data to GstMapInfo + Add extra pointers to GstMapInfo so that implementations can use these to store + extra info. + +2012-02-23 15:32:19 +0100 Wim Taymans + + * gst/gstbufferpool.h: + bufferpool: improve docs + +2012-02-23 12:09:31 +0000 Tim-Philipp Müller + + * NEWS: + * RELEASE: + Update NEWS and RELEASE as well + +2012-02-23 11:59:22 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + docs: remove transform lock + +2012-02-23 10:36:57 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + Bump version after releases + +2012-02-23 11:08:26 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: remove transform lock + This is not needed anymore by the baseclass. subclasses should do their own + locking when needed. + +2012-02-23 10:12:44 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: cleanups + Clean up the setcaps function. + The passthrough variable is protected with the object lock. + +2012-02-22 15:26:05 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: improve propose_allocation + Always call the propose_allocation method and provide a default implementation + that passes the query on in passthrough mode so that subclasses can also call + this. Also pass if the transform is in passthrough mode so that the + implementation can adjust its algorithm. + +2012-02-22 12:24:34 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetrans: improve fixate_caps function + Make it possible to also implement non-inplace fixate functions. Let the fixate + function make the caps writable when needed because some fixate functions might + not need to modify the caps. + +2012-02-22 02:02:50 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbytewriter.c: + * plugins/elements/gstfakesrc.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/typefindhelper.c: + memory: make _new_wrapped take user_data and notify + Make it possible to configure a GDestroyNotify and user_data for + gst_memory_new_wrapped() this allows for more flexible wrapping of foreign + memory blocks. + +2012-02-02 13:45:25 -0500 Ryan Lortie + + * autogen.sh: + build: avoid touching .po files during 'make' + A simple workaround to deal with GNU gettext automake integration + failing to deal with git. + https://bugzilla.gnome.org/show_bug.cgi?id=669207 + +2012-02-21 21:06:17 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + input-selector: default to sync-streams=true + I think this is the expected behaviour, and we couldn't do this + in 0.10 for backwards-compatibility reasons, so change it now. + +2012-02-21 16:39:05 +0100 Wim Taymans + + * tests/check/elements/queue.c: + tests: fix queue unit test after queue changes + +2012-02-21 16:38:37 +0100 Wim Taymans + + * plugins/elements/gstqueue.c: + queue: remove some old code + +2012-02-21 16:37:11 +0100 Wim Taymans + + * gst/gstpad.c: + pad: handle NULL callbacks + When we have a matching NULL callback, also consider the 'callback' marshalled, + this way blocking probes with a NULL callback actually work. + +2012-02-21 12:52:44 +0100 Wim Taymans + + * plugins/elements/gstqueue.c: + queue: remove weird link behaviour + Remove the link functions and always start the pad task on the srcpad. If + applications need to autoplug they can put a blocking probe on the srcpad like + they would with any other element. + +2012-02-21 12:52:18 +0100 Wim Taymans + + * plugins/elements/gstfakesrc.c: + fakesrc: handle pts/dts + +2012-02-21 12:46:44 +0100 Wim Taymans + + * plugins/elements/gstfakesink.c: + fakesink: remove custom marshaller + +2012-02-21 12:43:18 +0100 Wim Taymans + + * plugins/elements/gstidentity.c: + identity: also debug dts/pts + +2012-02-21 12:13:28 +0100 Wim Taymans + + * plugins/elements/gstfakesink.c: + fakesink: debug pts and dts + +2012-02-21 12:12:21 +0100 Wim Taymans + + * plugins/elements/gstidentity.c: + identity: remove custom marshaller + +2011-11-24 18:40:40 +0100 Matej Knopp + + * tests/check/gst/gstpad.c: + Unit test for queue src caps notification + +2012-02-20 14:37:11 +0100 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: fix useless segment test + +2012-02-20 14:29:30 +0100 Wim Taymans + + * gst/gstsegment.c: + segment: don't use duration in clipping + Don't use the duration in the segment for calculating clipping values. + The duration is expressed in stream time and clipping is done on unrelated + timestamp values. + This used to be interesting for elements that used the segment structure to + implement seeking because then they would use stream-time for the segment + start/stop values and the duration could be used as a fallback when the stop + position was not set. Now that the complete segment event is passed between + elements we cannot do this anymore because some elements might store the + duration and start/stop values with different time bases in the segment. + +2012-02-20 14:22:00 +0100 Wim Taymans + + * gst/gstinfo.c: + info: debug segment duration as well + +2012-02-20 11:46:36 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: copy metadata when using a pool + also copy the metadata when we allocated a new buffer from a pool + +2012-01-26 03:02:48 -0500 Matej Knopp + + * libs/gst/net/gstnettimepacket.c: + nettimepacket: fix printf format warning in debug message + https://bugzilla.gnome.org/show_bug.cgi?id=664491 + +2012-02-18 01:04:18 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: fix more docs + +2012-02-17 15:53:58 -0800 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.h: + * gst/gstmemory.h: + doc fixups + +2012-02-17 15:09:56 -0800 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: Move variable and assignment to where it's needed + +2012-02-17 15:09:06 -0800 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: Handle return value of decide_allocation vmethod + If it fails, properly propagate the error + +2012-02-17 15:08:32 -0800 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Remove useless assignment + +2012-02-17 15:07:56 -0800 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Gracefully handle NULL Gvalue + Avoids unreferencing NULL pointer + +2012-02-18 00:03:41 +0100 Wim Taymans + + * gst/gstpad.c: + pad: make some errors critical + When we have no chain function or when we are operating the pad in the wrong + mode, emit a critical instead of posting an error message. This is certainly a + programming error and we cannot always post a message (like when the pad has no + parent) + +2012-02-18 00:03:13 +0100 Wim Taymans + + * gst/gstinfo.c: + info: also debug position of segment + +2012-02-17 23:59:28 +0100 Wim Taymans + + * win32/common/config.h: + * win32/common/gstversion.h: + win32: back to development + +2012-02-17 11:02:40 +0100 Wim Taymans + + * configure.ac: + configure: back to development + +=== release 0.11.2 === + +2012-02-17 11:01:16 +0100 Wim Taymans + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * gstreamer.doap: + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + RELEASE 0.11.2 + +2012-02-15 17:12:09 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: tweak some documentation + +2012-02-15 17:11:54 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: simplify and improve frame state handling + Use a frame flag to signal to subclass it should reset any retained + state w.r.t. frame parsing since the frame being passed is 'new', + i.e. not related to previously passed and processed data. + +2012-02-15 13:15:55 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: don't leak event + In the unlikely case where the subclass set the event function to NULL, don't + leak the event. + +2012-02-15 12:19:13 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: make activation code more like other + Make the pad activation code look more like other activation code. + Only start the sinkpad task when we decide to activate in pull mode, when we + later add srcpad pullmode this will be needed. + +2012-02-15 12:18:38 +0100 Wim Taymans + + * gst/gsttask.c: + task: add more debug + +2012-02-15 11:11:11 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: add some more debug + +2012-02-15 10:58:08 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: track consumed input size + ... as used by subsequent input data rate estimation (and seeking). + +2012-02-15 10:11:35 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: chain up to parent for defaults + Chain up to the parent instead of using the FALSE return value from the event + function (because it's otherwise impossible to return an error). + +2012-02-15 10:10:53 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: don't ignore return value when starting a task + +2012-02-14 20:17:37 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: Revert "baseparse: really provide upstream ts to subclass" + This reverts commit 2363490ef5a9fe8d414369d24fcaa65a9dfa83ac. + +2012-02-14 19:33:50 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: remove dead code and superfluous loop level + +2012-02-14 19:33:46 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: modify reverse playback handling + ... so as to allow the push-mode case to provide data to subclass + on a buffer by buffer basis (as in regular forward case), rather + than all buffers of a fragment chucked together. + Also refactor buffer handling some more, and add some debug. + +2012-02-14 19:33:33 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: really provide upstream ts to subclass + +2012-02-14 13:24:49 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: clean up src query handler + +2012-02-14 12:57:14 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: pass results from activation + +2012-02-14 10:35:06 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2012-02-14 10:30:40 +0100 Wim Taymans + + * win32/common/libgstbase.def: + defs: update + +2012-02-13 18:22:37 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: modify API to a _finish_frame based approach + ... which aligns it with other baseclass in the wild, and should give + converter parsers a bit cleaner freedom. + +2012-02-13 18:09:51 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: fix reverse playback + ... especially for all-keyframe (audio) cases. + +2012-02-13 16:33:00 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + * win32/common/libgstreamer.def: + memory: more work on refcount and writability + Rename _is_writable() with _is_exclusive because the writability does not depend + on the amount of references to the memory object anymore. + Add accessor macros for the memory flags. + Rename the GstBuffer _peek_memory() method to _get_memory() and return a + reference to the memory now that we can do this without affecting writability + of the memory object. Make it possible to also make this function merge the + buffer memory. + Add methods to replace memory in a buffer. Make some convience macros for the + buffer memory functions. + Fix unit tests. + +2012-02-13 17:22:51 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + def: update + +2012-02-13 15:18:28 +0100 Wim Taymans + + * gst/gstmeta.h: + meta: fix typos + +2012-02-12 21:17:41 +0000 Tim-Philipp Müller + + * docs/design/part-events.txt: + docs: add a paragraph about the STREAM CONFIG event to the design docs + +2012-02-12 21:04:18 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstevent.h: + event: make _parse_nth_stream_config_header() and _parse_setup_data() return a boolean + As they can fail (only one of stream headers or setup data + is usually present). + +2012-02-12 20:51:39 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstevent.c: + event: rename gst_event_{set,parse}_stream_config_codec_data() to _setup_data() + More generic. + +2012-02-10 15:03:03 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2012-02-10 14:58:13 +0100 Wim Taymans + + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + clean up object init + Make an _init method where the parent mini-object and other fields are + initialized. + Check that the passed structure doesn't already have a parent. + Use the _new_custom () constructors + +2012-02-07 11:28:41 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: bitrate mechanics should not deal with duration update + ... since that is already handled by _update_duration, or should not be done + altogether if the duration is determined by non-estimated means. + Fixes #669502. + +2012-02-10 12:45:50 +0000 Tim-Philipp Müller + + * docs/design/part-events.txt: + docs: push_event doesn't return a flow value after all + +2012-02-10 12:05:18 +0100 Wim Taymans + + * gst/gstpad.c: + pad: silence probe debug a litte + +2012-02-10 11:24:28 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: implement faster ACCEPT_CAPS query + +2012-02-10 11:09:01 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstpad.c: + gst: add some performance logging + Add some performance logging for caps copy and the slow default acceptcaps + implementation + +2012-01-14 19:16:01 +0100 Wim Taymans + + * docs/design/draft-metadata.txt: + * docs/design/part-TODO.txt: + * docs/design/part-bufferpool.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-latency.txt: + * docs/design/part-meta.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-probes.txt: + * docs/design/part-query.txt: + * docs/design/part-segments.txt: + * docs/design/part-streams.txt: + * gst/gstquery.c: + docs: update and improve docs + +2012-02-09 00:14:58 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: remove gst_element_class_install_std_props() + It's only used in one place (rtmp), and there not very well. + +2012-02-08 23:47:40 +0000 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + fakesrc, identity, fakesink: do not generate last-message updates by default + Default to not creating lots of overhead by doing a couple of + g_strdup_printf()/g_free() per buffer or event just to generate + a last-message update that rarely anyone listens to. This means + that you need to enable silent=true explicitly in order to get + last-message dumps in gst-launch -v now. On the upside, people + won't inadvertently end up benchmarking g_strdup_printf() + performance instead of gstreamer data handling performance any + more. + Maybe the silent property should be renamed to enable-last-message + or something like that? + +2012-02-08 15:16:46 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstcollectpads2.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstpad.c: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstmarshal.c: + * win32/common/gstmarshal.h: + GST_FLOW_WRONG_STATE -> GST_FLOW_FLUSHING + +2012-02-08 15:34:28 +0100 Mark Nauwelaerts + + * plugins/elements/gstqueue.c: + queue: use default query function to optionally forward query + ... rather than querying peer unconditionally with possibly undesirable + outcome in case of e.g. SCHEDULING query. + +2012-02-08 15:03:56 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: clean up a few minor extraneous tokens + +2012-02-07 12:48:50 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: remove closing segment handling + +2012-02-08 14:45:25 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2012-02-08 14:32:01 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: fix race in pad mode change + Fixes #668909 and presumably also #669483 + +2012-02-08 12:57:11 +0100 Wim Taymans + + * gst/gstpad.c: + pad: error when activation mode is wrong + Post an error when we try to push on a pad activated in pull mode and pull on a + pad in push mode. + +2012-02-08 09:30:02 +0100 Wim Taymans + + * gst/gstclock.c: + clock: remove method declaration too + +2012-02-07 13:41:20 +0100 Stefan Sauer + + * gst/gstclock.c: + * gst/gstclock.h: + clock: remove unimplemented stats property while we can + +2012-02-07 10:44:07 +0100 Wim Taymans + + * plugins/elements/gstfakesrc.c: + fakesrc: remove custom marshaller + Remove our custom marshaller. + Make the buffer in the handoff signal static_scope so that it is actually + writable. + +2012-02-06 09:46:47 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstminiobject.c: + * gst/gstpad.c: + gst: improve debugging + +2012-01-04 17:10:15 +0100 Havard Graff + + * gst/gstregistry.c: + registry: fix compilation with --disable-registry + __registry_reuse_plugin_scanner is only defined when + GST_DISABLE_REGISTRY is not defined. + gstregistry.c: In function 'gst_registry_scan_plugin_file': + gstregistry.c:1131:8: error: '__registry_reuse_plugin_scanner' undeclared (first use in this function) + https://bugzilla.gnome.org/show_bug.cgi?id=667284 + +2012-02-02 17:18:22 +0000 Vincent Penquerc'h + + * gst/gstbin.c: + bin: reset the EOS detection machinery after sending an EOS message + This will allow detecting further EOS, for instance after looping + a stream without changing states. + https://bugzilla.gnome.org/show_bug.cgi?id=668289 + +2012-01-07 23:00:12 -0500 Ryan Lortie + + * autogen.sh: + autogen.sh: allow calling from out-of-tree + https://bugzilla.gnome.org/show_bug.cgi?id=667664 + +2012-02-02 16:59:12 +0100 Wim Taymans + + * gst/gsttrace.c: + trace: print caps in dump + +2012-02-02 16:04:10 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-02-02 15:57:48 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: add debug and trace for GstMemory + +2012-02-02 15:55:44 +0100 Wim Taymans + + * gst/gstobject.c: + * gst/gsttrace.c: + trace: don't check random pointers for objects + Only see if the traced pointer is a GObject when it was registered with the + special offset of -2. + +2012-02-02 15:54:28 +0100 Wim Taymans + + * gst/gst_private.h: + * gst/gstinfo.c: + Update debug categories + Remove some categories marked for deletion. + Add a category for GstMemory. + +2012-02-02 15:52:19 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstbufferpool.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstsample.h: + remove TRACE_NAME from headers + +2012-02-02 13:17:38 +0100 Wim Taymans + + * tests/check/gst/gstbuffer.c: + buffer: add new test + +2012-02-02 13:15:24 +0100 Wim Taymans + + * plugins/elements/gstidentity.c: + dentity: remove prepare_output_buffer + Correctly mark passthrough on the baseclass so that it can correctly do the + allocation of the output buffers. + Remove our custom prepare_output_buffer function now that the baseclass is + smarter. + +2012-02-02 13:10:27 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: improve prepare_output_buffer + Clean up the prepare_output_buffer function. + Reuse the input buffer when it is writable and when doing an + in-place but non-passthrough transform. + Move the copy-metadata function call to the prepare_output_buffer default + function. If subclasses implement a custom prepare_output_buffer, they must also + copy the metadata themselves. + Remove a useless memory copy because prepare_output_buffer already did that. + +2012-02-02 12:32:49 +0100 Wim Taymans + + * plugins/elements/gstidentity.c: + identity: only map when using the memory + +2012-02-02 12:32:07 +0100 Wim Taymans + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + plugins: proxy allocation query + +2012-02-02 12:30:14 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: simplify code + We already checked passthrough a few lines above. + +2012-02-02 12:07:28 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + memory: add some performce debug info + Add some PERFORMANCE debug lines where we copy and do other suboptimal things. + +2012-02-02 12:05:37 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add flag to proxy allocation query + Add a flag to force the default query handler to forward the allocation query + instead of discarding it. + Reorder the pad flags a bit. + +2012-02-02 01:30:12 +0000 Tim-Philipp Müller + + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * tests/check/libs/typefindhelper.c: + typefind: pass extensions as comma-separated list in a simple string + Fix annoying gst_type_find_register() function signature. A simple + string with comma-separated extensions works just as well and saves + lines of code, casts, relocations and ultimately kittens. + +2012-01-31 17:41:13 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: fix race in startup + Mark renegotiate before starting the pushing thread. + Do also check if we are starting in the get_range function. + +2012-01-31 16:27:55 +0100 Wim Taymans + + * gst/gstelement.c: + element: don't crash on missing template + Some request pads don't have a padtemplate (mostly those from encodebin). Avoid + crashing in this case. + +2012-01-31 12:20:41 +0100 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + * tests/examples/controller/text-color-example.c: + controller: constructures for control sources return GstControlSource + Don't return the specific types. In most cases there is no specific api there + anyway. + +2012-01-31 12:10:21 +0100 Wim Taymans + + * gst/gstvalue.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + don't do logic in g_assert... + +2012-01-30 19:17:00 +0100 Stefan Sauer + + * gst/gstobject.c: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstargbcontrolbinding.c: + * libs/gst/controller/gstargbcontrolbinding.h: + * libs/gst/controller/gstdirectcontrolbinding.c: + * libs/gst/controller/gstdirectcontrolbinding.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + * tests/examples/controller/text-color-example.c: + * win32/common/libgstcontroller.def: + controller: rename control-bindings + gst_control_binding_xxx -> gst_xxx_control_binding for consistency. + +2012-01-30 14:48:44 -0200 João Paulo Pizani Flor + + * gst/gstpreset.h: + Fixes the lack of an include directive in gst/gstpreset.h + It blocked the build of external libraries depending on gstreamer-core (namely, gstreamermm). + Complete bug report at https://bugzilla.gnome.org/show_bug.cgi?id=669036 + +2012-01-30 18:17:34 +0100 Stefan Sauer + + * gst/gstcontrolsource.c: + controlsource: sink the floating ref + control sources can be used on several control bindings. + +2012-01-30 17:15:21 +0100 Wim Taymans + + * gst/gstbuffer.h: + buffer; remove IN_CAPS buffer flag + The IN_CAPS buffer flag is deprecated and should be replaced with the HEADER + flag. + +2012-01-30 16:09:03 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs; update for new api + +2012-01-30 15:59:02 +0100 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + query: pass allocator in query + Place the allocator object in the ALLOCATION query instead of the name. This + allows us to exchange allocators that are not in the global pool of allocators. + Update elements for the new api + +2012-01-30 15:57:39 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add memory type + Add memory type when registering memory allocators. Add getter for the memory + type. + +2012-01-29 22:58:51 +0000 Olivier Crête + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + valve: Repush sticky events after disabling dropping + +2012-01-30 13:28:34 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add boxed GType for the allocator + +2012-01-30 13:02:13 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstreamer.def: + memory: make the allocator refcounted + Add refcounting to the GstAllocator object. + Remove const from functions because the allocator is refcounted now. + Rename the vmethods for consistency + Expose the constructor for GstAllocator and add a destroy notify for the + user_data. This should make it possible to create allocators that are not + registered and shared globally along with the possibility to destroy them + properly. + Update defs with new symbols. + +2012-01-30 10:30:58 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update for gap event + +2012-01-30 10:07:51 +0100 Philippe Normand + + * gst/gst.c: + * gst/gst.h: + core: don't ship gsttrace.h private header + Include it explicitely in gst.c and no longer include it in gst.h. + That header was made private in 1969b94267b4f377ea2663876ae8720717889693. + +2012-01-28 18:50:23 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + event: require a valid duration for the GAP event + +2012-01-28 18:49:44 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: ref new enum type in gst_init() + +2012-01-27 18:57:21 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + docs: add some (out) annotations for stream config parser functions + +2012-01-27 18:56:01 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstevent.c: + event: add constructor and parse function for new GAP event + (Whatever you do, don't mention the filler event.) + +2012-01-27 18:37:13 +0000 Tim-Philipp Müller + + * gst/gstevent.h: + docs: GST_EVENT_STREAM_CONFIG is implemented now + +2012-01-27 17:57:58 +0000 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: mention codec data / stream header change in porting docs + +2012-01-28 14:35:51 +0000 Olivier Crête + + * gst/gstcaps.c: + * gst/gstiterator.c: + * gst/gstpadtemplate.c: + * gst/gstparse.c: + * gst/gstsegment.c: + * gst/gsttaglist.c: + * gst/gsttypefind.c: + * gst/gstvalue.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstindex.c: + Use macros to register boxed types thread safely + +2012-01-28 08:38:03 +0100 Olivier Crête + + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: Update gst_check_element_push_buffer to 0.11 style caps + Pass the desired caps explicitely + +2012-01-27 19:00:03 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Fix memory leak + +2012-01-27 18:53:45 +0100 Sebastian Dröge + + * tools/gst-inspect.c: + gst-inspect: Don't unref plugin features multiple times + gst_plugin_feature_list_free() unrefs them too. + +2012-01-27 17:50:38 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: add new stream config functions to docs + +2012-01-27 17:49:48 +0000 Tim-Philipp Müller + + * tests/check/pipelines/simple-launch-lines.c: + tests: fix simple-launch-lines compilation + Don't use removed API. + +2012-01-27 18:46:49 +0100 Sebastian Dröge + + * gst/gstsegment.h: + segment: Add padding to the public struct + +2012-01-27 17:45:39 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: don't ref GType for private enum for which there's no GType any more + +2012-01-27 17:45:15 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def for new and removed API + +2012-01-27 17:39:12 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstevent.c: + event: add construct and parse API for the new STREAM CONFIG event + codec data and stream headers don't belong into caps, since they + are not negotiated. We signal them using the STREAM CONFIG event + instead. + +2012-01-27 18:24:43 +0100 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + trace: remove from public headers + +2012-01-27 12:16:05 +0100 Andoni Morales Alastruey + + * gst/gstcaps.c: + caps: fix documenation typo + +2012-01-27 17:50:42 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstcaps.c: + * gst/gstclock.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gsttrace.c: + * gst/gsttrace.h: + * tools/gst-launch.c: + trace: rework alloc tracing + Remove trace, we use debug log for that + Make alloc trace simpler, removing some methods. + Activate alloc trace with a GST_TRACE=3 environment variable. + Dump leaked objects atexit. + Provide an offset in the object where the GType can be found so that more + verbose info can be given for objects. + Remove -T option from gst-launch because tracing is now triggered with the + environment variable. + +2012-01-25 12:35:43 +0000 Vincent Penquerc'h + + * plugins/elements/gsttypefindelement.c: + typefind: answer caps queries with our typefound caps + This avoids merely forwarding the event to the sink, and getting + something useless such as ANY. + https://bugzilla.gnome.org/show_bug.cgi?id=667571 + +2012-01-27 16:18:00 +0100 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + typefind: Do typefinding from a separate thread and not from the state change function + +2012-01-27 15:32:37 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix memory leak + unmap the buffer memory on errors. + +2012-01-27 15:32:18 +0100 Wim Taymans + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstminiobject.c: + trace: make alloc trace work for miniobject again + +2012-01-27 15:09:35 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstcollectpads2.c + libs/gst/base/gstcollectpads2.h + +2012-01-27 15:02:52 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: Move private fields from the public structs to private structs + Fixes bug #668764. + +2012-01-27 13:05:48 +0100 Stefan Sauer + + * libs/gst/controller/gstcontrolbindingargb.c: + * libs/gst/controller/gstcontrolbindingdirect.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + controller: no fancy utf8 chars in the gi annotations + +2012-01-27 12:50:24 +0100 Wim Taymans + + * gst/gstdebugutils.c: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * tests/check/libs/adapter.c: + tests: fix some more leaks + +2012-01-27 12:33:32 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Fix handling of the new stream-start event + +2012-01-27 11:32:12 +0000 Vincent Penquerc'h + + * gst/gstplugin.c: + gstplugin: add a few consts to read only data + +2012-01-27 12:22:48 +0100 Stefan Sauer + + * libs/gst/controller/gstcontrolbindingargb.c: + * libs/gst/controller/gstcontrolbindingdirect.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + controller: add gi annotations + +2012-01-27 12:14:28 +0100 Sebastian Dröge + + * tests/check/gst/gstutils.c: + utils: Fix unit test + +2012-01-27 12:10:09 +0100 Wim Taymans + + * tests/check/gst/gstvalue.c: + tests: fix leaks + +2012-01-27 11:40:37 +0100 Wim Taymans + + * gst/gstmemory.c: + memory: avoid memory leak + Unref the old memory in make_mapped. + Add some debug info + +2012-01-27 11:40:05 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: avoid caps leak + +2012-01-27 11:01:27 +0100 Sebastian Dröge + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + identity/fake{src,sink}: Include event type name in the debug output + +2012-01-27 10:54:56 +0100 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + event: Mark the new GAP event as non-sticky + +2012-01-27 10:46:02 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: Drop the stream-start and stream-config events by default + +2012-01-27 10:42:09 +0100 Sebastian Dröge + + * gst/gstevent.c: + event rebase + +2012-01-27 10:41:07 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Send the stream-start event as first event ever + +2012-01-27 10:30:43 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * win32/common/libgstreamer.def: + event: Add constructor and docs for the new STREAM_START event + +2012-01-26 19:28:01 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add user data to chain functions + +2012-01-26 18:56:14 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix typo + +2012-01-26 18:22:29 +0000 Vincent Penquerc'h + + * gst/gsttaglist.c: + taglist: restore date/time type to GstDateTime + The change to GDateTime was apparently accidental, and + breaks plugins trying to feed a GstDateTime to the taglist APi. + +2012-01-26 19:12:16 +0200 Peteris Krisjanis + + * gst/gstparse.c: + gst: gst_parse_launch now returns a floating reference + +2012-01-26 18:53:51 +0100 Edward Hervey + + * gst/gststructure.c: + gststructure: Set "transfer none" to return values that shouldn't be freed + +2010-12-04 18:53:55 -0800 David Schleef + + * gst/gstelement.c: + element: call ->release_pad() to clean up pad + https://bugzilla.gnome.org/show_bug.cgi?id=636011 + https://bugzilla.gnome.org/show_bug.cgi?id=402562 + +2012-01-26 16:31:50 +0100 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + event: add some more events + Add some more new events that we want to implement later. + +2012-01-26 15:15:21 +0100 Andoni Morales Alastruey + + * gst/gstmemory.c: + gstmemory: add missing parameter + +2012-01-26 14:57:14 +0100 Sebastian Dröge + + * gst/gstcaps.c: + caps: Fix compiler warning + +2012-01-26 14:55:30 +0100 Sebastian Dröge + + * gst/gstcaps.c: + caps: Use correct size for caps allocation + +2012-01-26 14:45:30 +0100 Sebastian Dröge + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: Make GstCaps public struct more opaque by moving the private pointer into the implementation + +2012-01-26 14:33:12 +0100 Sebastian Dröge + + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstelementfactory.c: + * gst/gstregistrychunks.c: + caps: Store a pointer to GstCaps in GstStaticCaps + ...instead of using hackish subclass of GstCaps, which also + had some thread-safety problems. + +2012-01-26 13:24:44 +0100 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstpad.c: + event: remove the sticky event index + We don't use the sticky event index anymore, ordering of the events are how they + were sent initially. + Add some more padding between the event numbers so that we can insert new events + later. + +2012-01-26 10:48:02 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * tests/check/libs/.gitignore: + docs: remove collectpads from docs, fix build + +2012-01-26 10:22:29 +0000 Tim-Philipp Müller + + * gst/gstbufferpool.c: + bufferpool: use GstValueArray instead of GValueArray for storing options in the config + Since GValueArray is deprecated. It's all only internal anywhere here, + but if we use GstValueArray the option strings get serialized nicely + in the debug logs at least. + +2012-01-26 09:26:48 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: gst-inspect: suppress deprecation warnings for G_TYPE_VALUE_ARRAY + For now anyway. + +2012-01-26 11:42:29 +0100 Sebastian Dröge + + * tests/check/Makefile.am: + collectpads2: Unit test is valgrind clean now + +2012-01-26 11:40:53 +0100 Sebastian Dröge + + * tests/check/libs/collectpads2.c: + collectpads2: Fix unit test to actually work again + +2012-01-26 11:38:29 +0100 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/libs/collectpads2.c: + * tests/check/libs/gstlibscpp.cc: + * tests/check/libs/libsabi.c: + collectpads2: Port collectpads unit test to collectpads2 + Currently fails but really shouldn't. + +2012-01-26 11:01:21 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add probe id to the info + +2012-01-26 10:48:56 +0100 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * win32/common/libgstbase.def: + collectpads: Remove old collectpads + Still have to rename collectpads2 to collectpads before the 1.0 release. + +2012-01-26 10:30:25 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: Don't forward CAPS event automatically + +2012-01-25 18:49:15 +0100 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: Fix handling of the event function and document it + The event function is supposed to forward/drop the event in any case + now and takes ownership of the event. + +2012-01-25 18:36:42 +0100 Jason DeRose + + * gst/gstpadtemplate.c: + gst_pad_template_new() now returns a floating reference + +2012-01-25 19:41:03 +0200 Peteris Krisjanis + + * gst/gstpipeline.c: + gst_pipeline_new now returns a floating reference. + +2012-01-25 17:27:40 +0200 Peteris Krisjanis + + * gst/gstutils.c: + gst: gst_parse_bin_from_description returns a new reference + +2012-01-25 15:14:17 +0000 Tim-Philipp Müller + + * gst/gstquery.c: + query: use GArray for internal arrays instead of the now-deprecated GValueArray + +2012-01-25 16:01:02 +0200 Peteris Krisjanis + + * gst/gstbin.c: + * gst/gstghostpad.c: + * gst/gstpad.c: + gst: Changed introspection transfer flag to (transfer floating) + for gst_pad_new, gst_ghost_pad_new and gst_bin_new constuctors. Fixes + segfaults due of transfer full and floating ref problem. + +2012-01-25 13:46:13 +0100 Thomas Vander Stichele + + * common: + Automatic update of common submodule + From c463bc0 to 7fda524 + +2012-01-24 14:37:25 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add flags to the mapinfo + +2012-01-20 16:10:26 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + memory: make guint8 * for easy usage + +2012-01-20 14:56:49 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + memory: add method to create mapped memory + Add a method to create a GstMemory with the desired mapping. Makes a copy of the + memory if it is currently in use. + +2012-01-20 14:23:57 +0100 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstvalue.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue2.c: + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmemory.c: + * tests/check/gst/gstmeta.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/adapter.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/examples/adapter/adapter_test.c: + Add new GstMapInfo + Use a structure to hold info about the mapping. The application then keeps track + of this state and we can use it to unmap the memory again later. + +2012-01-25 11:49:50 +0100 Edward Hervey + + * gst/gstcontrolbinding.h: + controlbindings: name is not a const + It gets modified during the life of the object. Fixes build. + +2012-01-25 11:43:13 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2012-01-25 11:37:40 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 2a59016 to c463bc0 + +2012-01-24 21:53:14 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * libs/gst/controller/gstcontrolbindingargb.c: + * libs/gst/controller/gstcontrolbindingdirect.c: + * libs/gst/controller/gstcontrolbindingdirect.h: + * tests/check/gst/gstcontroller.c: + * win32/common/libgstcontroller.def: + controller: cleanup the control-binding construction + This is now bindings firendly as _new is just a classic c convenience and all + the work is done in a constructor. As a side effect _new never fails. + Fix the tests. + +2012-01-24 14:40:33 +0000 Vincent Penquerc'h + + * gst/gstvalue.c: + gstvalue: handle NULL dest in bitmask/bitmask intersection + +2011-12-01 12:43:03 +0000 Vincent Penquerc'h + + * tests/check/gst/gstvalue.c: + tests: add basic tests for new stepped ranges + https://bugzilla.gnome.org/show_bug.cgi?id=665294 + +2011-11-30 14:45:12 +0000 Vincent Penquerc'h + + * gst/gststructure.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstreamer.def: + gstvalue: add stepped ranges + int and int64 ranges can now have an optional step (defaulting to 1). + Members of the range are those values within the min and max bounds + which are a multiple of this step. + https://bugzilla.gnome.org/show_bug.cgi?id=665294 + +2011-11-30 17:58:07 +0000 Vincent Penquerc'h + + * gst/gstutils.c: + * gst/gstutils.h: + gstutils: add a 64 bit version of GCD calculation + https://bugzilla.gnome.org/show_bug.cgi?id=665294 + +2011-11-04 18:26:15 +0000 Vincent Penquerc'h + + * gst/gstvalue.c: + gstvalue: enforce identical basic types in lists, arrays + https://bugzilla.gnome.org/show_bug.cgi?id=322587 + +2012-01-23 10:32:01 +0000 Tim-Philipp Müller + + * tests/benchmarks/controller.c: + benchmarks: add missing include + +2012-01-23 11:03:09 +0100 Stefan Sauer + + * gst/gstobject.c: + object: register all properties in one go + +2012-01-23 11:02:45 +0100 Stefan Sauer + + * docs/design/part-controller.txt: + docs: update controller api design + +2012-01-21 20:03:52 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstobject.c: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstcontrolbindingargb.c: + * libs/gst/controller/gstcontrolbindingargb.h: + * libs/gst/controller/gstcontrolbindingdirect.c: + * libs/gst/controller/gstcontrolbindingdirect.h: + * tests/benchmarks/controller.c: + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/.gitignore: + * tests/examples/controller/Makefile.am: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + * tests/examples/controller/text-color-example.c: + * win32/common/libgstreamer.def: + controller: allow different controlbindings + Make controlbinding an abstract baseclass. Move implementation to control- + binding-direct and add a control-binding-argb. Add an example. + +2012-01-22 22:44:59 +0000 Tim-Philipp Müller + + * gst/gstformat.c: + * gst/gstinfo.c: + * gst/gstplugin.c: + * gst/gstquery.c: + * gst/gstregistry.c: + * gst/gstsystemclock.c: + * gst/gsttask.c: + * tests/check/elements/multiqueue.c: + Replace deprecated GStaticMutex with GMutex + https://bugzilla.gnome.org/show_bug.cgi?id=662207 + +2012-01-22 15:23:13 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: fix typo in gst-inspect debug message + +2012-01-22 01:39:49 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gst.c: + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstmessage.c: + * tests/check/gst/gststructure.c: + * win32/common/libgstreamer.def: + Use GLib's type for GError instead of our own + We introduced our own when GLib didn't want to add a GType + for GError. But now that there is one, we can use GLib's + unconditionally and remove our version. + +2012-01-22 01:27:42 +0000 Tim-Philipp Müller + + * plugins/elements/gstmultiqueue.h: + multiqueue: fix size of atomic counter + +2012-01-22 01:25:22 +0000 Tim-Philipp Müller + + * gst/glib-compat-private.h: + * gst/gst.c: + * gst/gstatomicqueue.c: + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstdatetime.c: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstpoll.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/helpers/gst-plugin-scanner.c: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gsttee.c: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + Use recent GLib API unconditionally now that we depend on the latest GLib + +2012-01-22 00:42:34 +0000 Tim-Philipp Müller + + * gst/gst.c: + * gst/gsttrace.c: + * gst/gsttrace.h: + trace: don't use deprecated GStaticMutex API in (still) public header + +2012-01-21 12:56:50 +0000 Tim-Philipp Müller + + * scripts/gst-uninstalled: + scripts: set GI_TYPELIB_PATH in gst-uninstalled + So pygi finds/uses the local g-i files. + +2012-01-20 18:06:04 +0000 Vincent Penquerc'h + + * libs/gst/check/libcheck/check.h.in: + libcheck: make the definition of fail not fail with non GCC compilers + +2012-01-20 14:42:31 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/benchmarks/controller.c: + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + * win32/common/libgstreamer.def: + controller: improve control binding handling + Change _set_control_binding to _add_control_binding and take ownership. Add a + _remove_control_binding function. + +2012-01-20 08:27:57 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/benchmarks/controller.c: + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + * win32/common/libgstreamer.def: + controller: remove convenience api for control sources + This is needed to support multiple kinds of control-bindings. + +2012-01-19 15:17:58 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle NULL from getcaps + If the getcaps functions returns NULL, return FALSE from the CAPS query. + +2012-01-19 15:17:33 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: handle lists correctly + +2012-01-17 16:23:33 -0500 Colin Walters + + * common: + * configure.ac: + build: add --disable-fatal-warnings configure option + It's reasonable to build from git, but not want to turn all compiler + warnings into fatal errors. For example, GNOME's jhbuild helps people + get newer versions of software than came from their distribution, but + they may not necessarily want to hack on it. + +2012-01-19 12:57:48 +0100 Mark Nauwelaerts + + * tests/benchmarks/gstclockstress.c: + tests: clockstress: perform sanity check on thread number argument + +2012-01-19 09:12:05 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstmemory.c: + memory improvements + Make the memory object simply manage the data pointer and the maxsize and move + the offset and size handling to common functionality. + Use the READONLY flag to set a readonly lock. + Remove the data and size fields from the unmap method. We need an explicit + resize operation instead of using the unmap function. + Make internal helper lock and unlock functions. + Update unit test and users of the old API. + +2012-01-19 11:43:53 +0000 Tim-Philipp Müller + + * gst/gstbus.c: + docs: fix typo in bus docs + +2012-01-13 17:45:17 -0500 Matej Knopp + + * .gitignore: + .gitignore: add visual studio IDE files and OS X .DS_Store files + https://bugzilla.gnome.org/show_bug.cgi?id=667899 + +2012-01-19 09:27:04 +0100 Wim Taymans + + * gst/glib-compat-private.h: + * gst/gstbin.c: + * gst/gstbufferpool.c: + * gst/gstbus.c: + * gst/gstbus.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstmemory.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstmeta.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpoll.c: + * gst/gsttask.c: + * gst/gsttask.h: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.c: + * plugins/elements/gstdataqueue.c: + * plugins/elements/gstdataqueue.h: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstpollstress.c: + * tests/check/gst/gsttask.c: + Update for new gthread API + +2012-01-18 16:52:55 +0100 Sebastian Dröge + + * configure.ac: + configure.ac: GIO check is now in gst-glib2.m4 + +2012-01-18 16:45:51 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 0807187 to 2a59016 + +2012-01-18 16:14:51 +0100 Sebastian Dröge + + * configure.ac: + configure.ac: Require GLib 2.31.10 and improve GIO check + +2012-01-18 12:07:46 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: Always call ::propose_allocation vfunc + And only forward the allocation query if we're working in + passthrough mode if no ::propose_allocation is implemented. + In place buffer transformations will change the buffer + content and require explicit handling of all metas. + +2012-01-18 11:37:57 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Don't forward the allocation query by default + This has to be handled explicitely by elements to + make sure that they support all the metas passed + in the allocation query. + Metas have to supported explicitely, otherwise the + query will fail. All elements in a chain need to + support a specific meta to allow its usage. + +2012-01-18 01:31:56 +0000 Tim-Philipp Müller + + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmeta.c: + gst: suppress some more deprecated thread api until we fix it up + Which should be soon, since we already depend on an unstable glib for -base. + +2012-01-18 01:18:33 +0000 Tim-Philipp Müller + + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + win32: update .def files for api changes + +2012-01-17 23:57:44 +0000 Tim-Philipp Müller + + * configure.ac: + * libs/gst/Makefile.am: + configure: remove --disable-net option and always build libgstnet + It should work everywhere now, and -base and -good depend on + the GstNetMeta API. + +2012-01-17 23:52:07 +0000 Tim-Philipp Müller + + * configure.ac: + * libs/gst/net/Makefile.am: + configure: remove some socket cruft + +2010-05-05 16:33:51 +0100 Tim-Philipp Müller + + * configure.ac: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnettimeprovider.h: + * tests/check/Makefile.am: + * tests/check/libs/gstnettimeprovider.c: + net: port to use gio's networking API + Some warts still, but it's a start. + +2012-01-17 16:50:13 +0100 Sebastian Dröge + + * libs/gst/net/Makefile.am: + net: Add GIO to the gi-scanner packages + +2012-01-16 13:34:28 +0100 Sebastian Dröge + + * configure.ac: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-net.pc.in: + netaddressmeta: Use GSocketAddress instead of our own wrapper type + +2012-01-16 15:57:35 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstmemory.c: + memory: make writability check into a method + Use a method to check for writability instead of a macro so that we can change + the implementation more easily. + +2012-01-16 12:24:48 +0100 Wim Taymans + + * tests/check/gst/gstmemory.c: + tests: improve memory test + +2012-01-16 12:24:20 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: improve docs + +2012-01-11 10:59:53 +0100 Mark Nauwelaerts + + * libs/gst/base/gstadapter.c: + adapter: ensure automagic _unmap in some more cases + +2011-11-15 17:42:56 +0000 Vincent Penquerc'h + + * libs/gst/base/gstadapter.c: + adapter: automatically unmap on clearing + When _clear gets called between _map and _unmap, buffers + will be unreffed. If the adapter was mapped, memory leaks + may occur. + While calling _clear between _map and _unmap does not seem + like such a great idea, this is possible in the audio + encoder base class, as _clear may be called in _finish_frame. + Since the audio encoder relies on flushing to keep track of + timestamps, delaying flushing till after handle_frame seems + dangerous. + So, we unmap on clear, as the next unmap will do nothing. + This makes _clear safe to call between _map and _unmap, + while avoiding leaking the mapped buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=664133 + +2012-01-13 14:20:33 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + basesrc: prevent unlikely caps leak + +2012-01-13 10:43:12 +0000 Vincent Penquerc'h + + * tools/gst-inspect.c: + gst-inspect: plug factory leak on error + +2012-01-13 00:22:03 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + tools/gst-inspect.c + +2012-01-12 20:46:27 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * tests/check/gst/gstvalue.c: + * win32/common/libgstreamer.def: + Remove GST_TYPE_DATE, our own GDate type + Which we had to add because GLib didn't have it + back in the day. Port everything to plain old + G_TYPE_DATE, which is also a boxed type. Ideally + we'd just use GDateTime for everything, but it + doesn't support not setting some of the fields + unfortuntely (which would be very useful for + tag handling in general, if we could express + 2012-01 for example). + https://bugzilla.gnome.org/show_bug.cgi?id=666351 + +2012-01-12 19:53:11 +0000 Antoine Tremblay + + * libs/gst/base/gstbaseparse.c: + baseparse: clear adapter in reset so baseparse is reusable + GstBaseParse was not clearing its adapter on reset causing + problems when a pipeline went for example from PLAYING to NULL + state and then back to PLAYING again. The data from the last + stream would be used in the parser. + https://bugzilla.gnome.org/show_bug.cgi?id=667444 + +2012-01-12 15:50:53 +0000 Vincent Penquerc'h + + * tools/gst-inspect.c: + gstinspect: fix features and list leaks + +2012-01-12 11:03:10 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: add new API to .def file + +2012-01-11 12:19:20 +0000 Vincent Penquerc'h + + * gst/gststructure.c: + gststructure: clarify _get docs about the returned reference + https://bugzilla.gnome.org/show_bug.cgi?id=667689 + +2012-01-10 13:00:07 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2012-01-06 16:39:04 +0100 Edward Hervey + + * plugins/elements/gsttypefindelement.c: + typefind: Send caps again after activation + Avoids ending up in cases where typefind gets activated in pull-mode + and caps never get sent. + https://bugzilla.gnome.org/show_bug.cgi?id=667337 + +2012-01-09 15:59:09 +0000 Christian Fredrik Kalager Schaller + + * gstreamer.spec.in: + Add latest specfile changes + +2012-01-09 15:58:45 +0000 Christian Fredrik Kalager Schaller + + * gst/gstdebugutils.h: + Also add headerfile + +2012-01-09 15:57:51 +0000 Christian Fredrik Kalager Schaller + + * gst/gstdebugutils.c: + Fix dotfile API to be exported since macros can't be GI bound + +2012-01-09 13:19:04 +0000 Tim-Philipp Müller + + * tests/check/gst/.gitignore: + tests: ignore new memory test binary + +2012-01-09 03:14:41 -0500 Matej Knopp + + * gst/gstmemory.c: + * libs/gst/controller/gsttriggercontrolsource.c: + Fix printf format build warnings + +2012-01-09 13:10:10 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/eo.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations for new strings + +2012-01-06 15:01:24 +0100 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Allow NULL dest when subtracting bitmask + Happens when checking for subsets of caps + +2012-01-06 13:32:55 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: ensure writable memory in memset + +2012-01-06 13:10:18 +0100 Wim Taymans + + * docs/design/part-memory.txt: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstmemory.c: + memory: check semantics of nested mappings + Count how many mappings are currently active and also with what access pattern. + Update the design doc with restrictions on the access patterns for nested + mappings. + Check if nested mappings obey the access mode restrictions of the design doc. + Add various unit tests to check the desired behaviour. + +2012-01-06 13:06:32 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: unmap with the right data pointer + Use the original data pointer to unmap the buffer memory. + +2012-01-06 10:39:46 +0100 Wim Taymans + + * gst/gstmemory.c: + docs: improve memory docs + +2012-01-06 07:02:36 +0100 Wim Taymans + + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: handle -1 size in unmap + handle -1 in unmap correctly when the offset is modified. + +2012-01-06 06:43:08 +0100 Wim Taymans + + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: improve semantics of unmap + Make an unmap call with a different data pointer than the map call update the + offset field. This allows for both offset and size adjustements in the unmap + call. + +2011-11-29 14:22:44 +0100 Havard Graff + + * libs/gst/base/gstbasesink.c: + basesink: don't compensate for render-delay twice + https://bugzilla.gnome.org/show_bug.cgi?id=667298 + +2012-01-05 18:15:20 +0100 Wim Taymans + + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: add more checks + Add check for mapping and resizing + +2012-01-05 17:28:28 +0100 Wim Taymans + + * docs/design/part-memory.txt: + * gst/gstmemory.c: + * tests/check/gst/gstmemory.c: + memory: take offset into account + Take the offset into account whem mapping and unmapping the buffer. + +2012-01-05 17:02:48 +0100 Wim Taymans + + * docs/design/part-memory.txt: + docs: clarify resize and current mappings + +2012-01-05 16:41:58 +0100 Wim Taymans + + * docs/design/part-memory.txt: + * tests/check/gst/gstmemory.c: + memory: clarify nested mappings, add unit test + +2012-01-05 12:30:00 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new API to .def file + +2012-01-05 13:22:42 +0100 Wim Taymans + + * tests/check/gst/gstmemory.c: + tests: add more memory unit tests + Check for unmap with invalid size + +2012-01-05 13:11:05 +0100 Wim Taymans + + * gst/gstmemory.c: + * tests/check/Makefile.am: + * tests/check/gst/gstmemory.c: + tests: add unit test for GstMemory + Add a GstMemory unit test + Add some more asserts in GstMemory to catch invalid cases. + +2012-01-05 13:09:29 +0100 Wim Taymans + + * libs/gst/check/gstcheck.h: + check: add macro to check for memory refcount + +2012-01-05 12:39:17 +0100 Wim Taymans + + * docs/design/part-memory.txt: + improve docs a little + +2011-12-16 13:11:36 +0100 Sebastian Dröge + + * tests/check/gst/gstvalue.c: + value: Add tests for the bitmask type + +2011-12-16 12:39:15 +0100 Sebastian Dröge + + * gst/gststructure.c: + structure: Add "bitmask" as alias for (GstBitmask) when (de-)serializing values + +2011-12-16 12:32:26 +0100 Sebastian Dröge + + * gst/gstvalue.c: + * gst/gstvalue.h: + value: Add 64-bit bitmask type + +2012-01-01 16:32:27 +0100 Idar Tollefsen + + * autogen.sh: + build: don't output configure options via autogen if $NOCONFIGURE is set + https://bugzilla.gnome.org/show_bug.cgi?id=667296 + +2012-01-05 00:30:30 +0000 Tim-Philipp Müller + + * gst/gst-i18n-app.h: + * gst/gst-i18n-lib.h: + gst: include locale.h before any other i18n headers + This is also how we do it in -base. + https://bugzilla.gnome.org/show_bug.cgi?id=667290 + +2012-01-01 16:46:04 +0100 Idar Tollefsen + + * gst/gst_private.h: + * gst/gstconfig.h.in: + gstconfig.h: adds and uses SunPro visibility attribute for proper function exports + Define GST_EXPORT for SunPro. + https://bugzilla.gnome.org/show_bug.cgi?id=667289 + +2012-01-01 16:47:14 +0100 Idar Tollefsen + + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstinputselector.c: + plugins: explicitly cast initialization values to the correct type + https://bugzilla.gnome.org/show_bug.cgi?id=667288 + +2012-01-01 20:17:41 +0100 Idar Tollefsen + + * gst/gstpoll.c: + poll: include correct poll.h based on autoconf test + https://bugzilla.gnome.org/show_bug.cgi?id=667286 + +2012-01-04 23:46:19 +0000 Tim-Philipp Müller + + * configure.ac: + configure: check for sys/poll.h + https://bugzilla.gnome.org/show_bug.cgi?id=667286 + +2012-01-04 19:50:01 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From a62f3d4 to 0807187 + +2012-01-04 10:04:11 +0100 Wim Taymans + + * gst/gstbuffer.h: + buffer: only reserve 6 extra flags + Only reserve 6 extra flags instead of 10 so that more media specific flags + are available. + +2012-01-03 15:26:54 +0100 Wim Taymans + + * plugins/elements/gstdataurisrc.c: + GST_FLOW_UNEXPECTED -> GST_FLOW_EOS + +2012-01-03 15:25:31 +0100 Wim Taymans + + * gst/gstcompat.h: + * libs/gst/base/gstcollectpads2.c: + GST_FLOW_UNEXPECTED -> GST_FLOW_EOS + +2012-01-03 15:05:47 +0100 Wim Taymans + + * gst/gstcompat.h: + compat: restore UNEXPECTED + +2012-01-03 15:03:38 +0100 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstcompat.h: + * gst/gstelement.h: + * gst/gstmemory.c: + * gst/gstregistry.c: + * gst/gstsample.c: + docs: fix some docs + +2012-01-03 14:45:08 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2012-01-03 14:43:05 +0100 Wim Taymans + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: avoid exposing the lists in tags + +2012-01-03 13:42:12 +0100 Wim Taymans + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: add missing functions + Add missing and essential functions now that we can't directly use GstStructure + methods on the taglist anymore. + +2012-01-03 10:42:31 +0100 Wim Taymans + + * gst/gstvalue.h: + value: add macro to check if a gvalue holds a sample + +2012-01-02 15:47:46 +0100 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + docs: fix build of docs examples + Update for registry method rename + +2012-01-02 15:39:02 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: turn assert into a real error + Post a real error instead of just asserting. + +2012-01-02 15:38:25 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: handle latency event + +2012-01-02 02:32:49 +0000 Tim-Philipp Müller + + * gst/gstregistry.c: + * gst/gstregistry.h: + * tests/check/gst/gstplugin.c: + * win32/common/libgstreamer.def: + registry: get rid of gst_default_registry_*() convenience macros + They're not really worth it: hardly save any typing, and aren't + great for bindings or gobject-introspection. + +2012-01-02 02:22:51 +0000 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + * gst/gst.c: + * gst/gstelementfactory.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpluginloader.c: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * libs/gst/check/gstcheck.c: + * tests/check/generic/states.c: + * tests/check/gst/gstplugin.c: + * tests/check/gst/gstregistry.c: + * tools/gst-inspect.c: + * win32/common/libgstreamer.def: + registry: rename gst_registry_get_default() to gst_registry_get() + It's not really a default if there is only one that can't be changed. + Should we return a ref like e.g. g_volume_monitor_get() does? + +2012-01-02 02:21:40 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gsttaglist.c + plugins/elements/gstoutputselector.c + +2012-01-02 00:17:17 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: add GST_TAG_LANGUAGE_NAME + API: GST_TAG_LANGUAGE_NAME + +2012-01-01 20:59:22 +0100 Stefan Sauer + + * docs/design/part-controller.txt: + docs: update controller design doc + +2012-01-01 20:57:34 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + controller: rename some tests + +2012-01-01 20:55:20 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + * tests/check/libs/controller.c: + controller: support control mapping for enums + Add a mapping for enum types (supporting sparse enums). Add a test. + +2012-01-01 20:43:51 +0100 Stefan Sauer + + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/control-sources.c: + controller: remove nonsense parts from test object property descriptions + +2012-01-01 18:54:23 +0100 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + interpolationcontrolsource: fix cubic interpolation for arrays + +2012-01-01 18:50:55 +0100 Stefan Sauer + + * tests/examples/controller/control-sources.c: + audio-example: also plot reverse-saw + +2012-01-01 18:43:23 +0100 Stefan Sauer + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: cleanups and fix triangle calculations + +2012-01-01 18:34:12 +0100 Stefan Sauer + + * tests/examples/controller/audio-example.c: + audio-example: fix the example + We need to scale the frequency values. + +2012-01-01 15:16:06 +0100 Stefan Sauer + + * libs/gst/controller/gstlfocontrolsource.c: + * tests/examples/controller/control-sources.c: + lfocontrolsource: make chainable + Now the properties of this controlsource are in turn controlable. Add an example + to show the usage. + +2012-01-01 15:01:22 +0100 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: add logging and fix array functions + +2012-01-01 14:55:35 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + controller: cleanup the tests + +2012-01-01 14:28:54 +0100 Stefan Sauer + + * gst/gstcontrolbinding.c: + controller: add more debug logging + +2011-12-31 17:37:20 -0800 David Schleef + + * tests/check/Makefile.am: + convert Makefile spaces to tabs + +2011-12-31 15:52:18 +0100 Stefan Sauer + + * tests/examples/controller/control-sources.c: + controller: also test array functions + Improve the example to also collect value arrays and plot them. + +2011-12-31 15:26:26 +0100 Stefan Sauer + + * gst/gstobject.c: + controller: remove obsolete FIXME comment + +2011-12-31 09:56:53 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + controller: fix tests + Set a defined value to check for no-change. + +2011-12-30 18:35:40 +0100 Stefan Sauer + + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * tests/benchmarks/controller.c: + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + control-sources: turn into GstObjects + This is a preparation for chaining them. + +2011-12-30 19:37:31 +0000 Tim-Philipp Müller + + * gst/gstmarshal.list: + * gst/gstregistry.c: + * gst/gstregistry.h: + registry: remove padding and signal vfuncs + And fix signal GTypes and marshaller. No one will ever + need to subclass our registry, so just remove the padding + and the signal vfuncs. + +2011-12-30 15:39:55 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: disable GstIndex unit test + +2011-12-30 15:31:17 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstindex.c: + * libs/gst/base/gstindex.h: + * libs/gst/base/gstmemindex.c: + index: rename GstAssocFlags to GstIndexAssociationFlags + Just in case we resurrect this later. + +2011-12-30 15:24:52 +0000 Tim-Philipp Müller + + * libs/gst/base/gstindex.c: + * libs/gst/base/gstindex.h: + * libs/gst/base/gstmemindex.c: + base: disable unused index API and make functions static + It's simply private helper API for now, until someone + fixes up GstBaseParse not to need it any more. + +2011-12-30 15:24:32 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: remove index API from .def file + +2011-12-30 15:06:34 +0000 Tim-Philipp Müller + + * gst/gstelement.h: + element: add LARGE padding to class structure + Four slots for expansion is not a lot. + +2011-12-30 15:03:02 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstindexfactory.c: + * gst/gstindexfactory.h: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstindex.c: + * libs/gst/base/gstindex.h: + * libs/gst/base/gstmemindex.c: + * plugins/Makefile.am: + * plugins/indexers/.gitignore: + * plugins/indexers/Makefile.am: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstindexers.c: + * plugins/indexers/gstindexers.h: + * tools/gst-inspect.c: + * tools/gst-launch.c: + index: remove GstIndex and GstIndexFactory for now + There are many good use cases for GstIndex and we want + to add it back again in some form, but possibly not with + the current API, which is very powerful (maybe too powerful), + but also a bit confusing. At the very least we'd need to + make the API bindings-friendly. + +2011-12-30 17:57:41 +0100 Stefan Sauer + + * gst/gst.c: + gst: unref the two cotnroller types in _deinit() + +2011-12-30 17:51:01 +0100 Stefan Sauer + + * tests/check/gst/gstcontroller.c: + controller: add more tests to core controller suite + Extend the dummy control-source to allow testing the sync code path. Add test + for 1:1 and 2:1 value <-> control-source sync. + +2011-12-30 13:52:08 +0100 Stefan Sauer + + * tests/check/gst/gstcontroller.c: + controller: add a test for bindings control sources multiple times + +2011-12-30 12:59:46 +0000 Tim-Philipp Müller + + * gst/math-compat.h: + math-compat: move static variable for NAN into #ifndef NAN block + And use G_GNUC_UNUSED instead of __attribute_used__ + +2011-12-30 13:32:18 +0100 Stefan Sauer + + * gst/math-compat.h: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.c: + controller: use NAN instead of FP_NAN (which is the class) + Also add a fallback define to math-compat.h. + Fixes #666887 + +2011-12-29 16:56:46 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + output-selector: Do not false warn about unlinked pad + When output-selector didn't receive a newsegment event it would + warn about pad being unlinked when switching pads. Making the logs + wrong and misleading. + +2011-12-29 16:49:39 +0100 Edward Hervey + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-12-28 15:13:09 +0100 Edward Hervey + + * tests/check/gst/gstpad.c: + tests: Fix leak in pad check + +2011-12-28 14:51:50 +0100 Wim Taymans + + * gst/gst.c: + gst: deinit meta flags too + +2011-12-28 12:25:59 +0100 Edward Hervey + + * gst/gst.c: + gst: Initialize new GstMetaFlags in init_post() + +2011-12-01 19:05:59 +0100 Edward Hervey + + * gst/gstquery.c: + gstquery: Small doc fixups + +2011-12-16 02:20:27 +0100 Matej Knopp + + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.h: + * gst/gstevent.h: + * gst/gstinfo.h: + * gst/gstmemory.h: + * gst/gstsample.h: + * gst/gststructure.h: + * gst/gsttrace.h: + win32: fix exported variables for VS 2010 + https://bugzilla.gnome.org/show_bug.cgi?id=666219 + +2011-12-27 13:48:36 +0100 Stefan Sauer + + * libs/gst/controller/gsttriggercontrolsource.c: + triggercontrolsource: fix control reaches end of non-void function + Return NAN and check the value further up. + Fixes #666890 + +2011-12-27 11:40:40 +0000 Tim-Philipp Müller + + * libs/gst/controller/gsttriggercontrolsource.c: + controller: quick-fix compiler warning breaking the build + This is likely not the proper fix. + https://bugzilla.gnome.org/show_bug.cgi?id=666890 + +2011-12-27 11:35:28 +0000 Tim-Philipp Müller + + * tests/check/gst/gstplugin.c: + tests: can't access private registry structure members directly any longer + +2011-12-27 11:24:48 +0000 Tim-Philipp Müller + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: fix compiler warning in interpolation control source + gstinterpolationcontrolsource.c:54: warning: type qualifiers ignored + on function return type + https://bugzilla.gnome.org/show_bug.cgi?id=666890 + +2011-12-26 18:44:39 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: remove "fd" property + It's no longer useful, since we don't use mmap any more anyway, + and we might use a different API for I/O in future (such as GIO). + +2011-12-26 18:41:13 +0000 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + registry: move private bits into private struct + +2011-12-26 11:26:05 +0000 Tim-Philipp Müller + + * gst/gstvalue.c: + value: micro-optimisation: avoid some unnecessary g_value_unset() + We know there's nothing to do here and can save us the function + calls and GValueTable lookups. + +2011-12-25 23:41:03 +0000 Tim-Philipp Müller + + * Android.mk: + * configure.ac: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * gstreamer.spec.in: + * libs/gst/Makefile.am: + * libs/gst/dataprotocol/.gitignore: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/dataprotocol/dataprotocol.c: + * libs/gst/dataprotocol/dataprotocol.h: + * libs/gst/dataprotocol/dp-private.h: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol.pc.in: + * scripts/gst-uninstalled: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/libs/gdp.c: + * tests/check/libs/gstlibscpp.cc: + * tests/check/libs/libsabi.c: + * win32/MANIFEST: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstdataprotocol.dsp: + libs: remove gdp dataprotocol library + Made private and moved to gdp plugin in -base for + the time being, until we figure out what we do with + gdp and 0.11. + +2011-12-25 21:02:41 +0000 Tim-Philipp Müller + + * tests/benchmarks/controller.c: + tests: fix unused-variable compiler warning + +2011-12-25 21:01:43 +0000 Tim-Philipp Müller + + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + win32: update exports for new API + +2011-12-25 20:49:41 +0100 Stefan Sauer + + * docs/design/part-controller.txt: + docs: add the start of a design document for controller + +2011-12-25 18:49:01 +0100 Stefan Sauer + + * tests/check/Makefile.am: + * tests/check/gst/gstcontroller.c: + * tests/check/libs/controller.c: + controller: split and cleanup the tests + The controller object was once copied from buzztards unit tests. Change + TestMonoSource to TestObj as it is not a full fledged element. Split the tests + into a core and library test suite. + +2011-12-22 23:48:30 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstobject.c: + * gst/gstobject.h: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsourceprivate.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.c: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/check/libs/gstlibscpp.cc: + * tests/examples/controller/.gitignore: + * tests/examples/controller/Makefile.am: + * tests/examples/controller/audio-example.c: + * tests/examples/controller/control-sources.c: + controller: move GValue handling from control-sources to -binding + ControlSources are now gdouble based. A control source is mapped to a + particullar GObject property using a ControlBinding. + +2011-12-20 22:36:18 +0100 Stefan Sauer + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstcontrolbinding.c: + * gst/gstcontrolbinding.h: + * gst/gstcontrolsource.c: + * gst/gstobject.c: + * gst/gstobject.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * tests/check/libs/controller.c: + controller: move GstControlledProperty into a separate class + Add a GstControlBinding class. This is a preparation for making the + controlsources generate double valued control curves and do the gparamspec + mapping in the control binding. Now the API in GstObject is again mostly + for convenience. + +2011-12-25 12:47:55 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + plugins/elements/gstfilesrc.c + +2011-12-25 12:39:49 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: return any remaining data on EOS before returning FLOW_UNEXPECTED + +2011-12-25 12:29:46 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: minor cosmetic changes + Rename woffset variable, maintain separate bytes_read in addition + to length variable. + +2011-12-25 12:13:57 +0000 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads2.c: + collectpads2: fix up compilation after merge + +2011-12-25 11:58:12 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + libs/gst/base/gstbasetransform.c + libs/gst/controller/gstinterpolationcontrolsource.c + libs/gst/controller/gstlfocontrolsource.c + plugins/elements/gstfilesrc.c + Dit not merge controller or basetransform changes. + +2011-12-24 14:59:16 -0300 Thiago Santos + + * docs/random/porting-to-0.11.txt: + porting: update porting-to-0.11 + Update gst_pad_get_caps -> gst_pad_query_caps change + +2011-12-23 15:37:45 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: cleanup metadata in reset_buffer + Use the reset_buffer vmethod to remove the unpooled metadata from the buffer. + +2011-12-22 16:00:28 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + def: update for new symbols + +2011-12-22 15:55:29 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: handle metadata in the pool + Mark all metadata on the allocated buffers with a POOLED flag. When a buffer + returns to the pool, remove all metadata that did not have the POOLED flag. This + makes sure that we never leave unknown metadata to the buffers in the pool. + +2011-12-22 15:54:03 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add foreach function for the metadata + +2011-12-22 15:53:19 +0100 Wim Taymans + + * gst/gstbufferlist.c: + bufferlist: small doc fix + +2011-12-22 15:52:08 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmeta.h: + meta: add metadata flags + Add metadata flags so that we can set extra properties of the metadata + +2011-12-02 14:10:32 +0100 Mark Nauwelaerts + + * gst/gstpipeline.c: + pipeline: only have a top-level pipeline do pipeline management + Fixes #665390. + +2011-12-22 11:08:42 +0000 Tim-Philipp Müller + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: fix GType name of interpolation mode enum + +2011-12-21 11:13:47 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + def: update + +2011-12-21 11:08:34 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: rename variable for consistency + Rename the variable for GST_CAPS_NONE to _gst_caps_none for consistency and to + hie the fact that NONE caps are also accidentally empty caps. + +2011-12-19 14:27:47 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: If the filtered peer caps are already empty error out early + +2011-12-20 13:21:36 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + def: update defs + +2011-12-20 13:14:07 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: add ANY and EMPTY singletons + Add a singleton for ANY and EMPTY caps and make the GST_CAPS_ANY and + GST_CAPS_NONE point to them. This makes the API more consistent now + that the macro does not magically create a ref. It also solves some leaks in + places where the macro was used to register a padtemplate. + +2011-12-20 13:13:04 +0100 Wim Taymans + + * gst/gsttypefind.c: + * gst/gsttypefind.h: + remove const in gst_type_find_register() + Remove the const from the GstCaps in gst_type_find_register() because the + function takes a ref to the caps. + +2011-12-20 12:59:37 +0100 Wim Taymans + + * win32/common/libgstcontroller.def: + defs: update + +2011-12-20 11:38:19 +0100 Stefan Sauer + + * gst/gstcontrolsource.c: + controller: remove unused parent_class varriable from controlsource + +2011-12-19 23:32:57 +0100 Stefan Sauer + + * docs/libs/gstreamer-libs-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstobject.c: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + controller: cleanup interpolation modes + Remove deprecated/unimplemented modes. Turn interpolation mode into a gobject + property. Update docs and examples. + +2011-12-19 11:13:45 +0100 Stefan Sauer + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * docs/random/porting-to-0.11.txt: + * gst/gstobject.c: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + * libs/gst/controller/gsttimedvaluecontrolsource.c: + * libs/gst/controller/gsttimedvaluecontrolsource.h: + * libs/gst/controller/gsttriggercontrolsource.c: + * libs/gst/controller/gsttriggercontrolsource.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + controlsources: refactor interpolation control source + Move most of the code to a GstTimedValueControlSource. Split out the trigger + 'interpolation mode' to a new control source class. Move tests and examples to + new api. Update docs. + Fixes #610338 + +2011-12-19 22:01:02 +0100 Stefan Sauer + + * libs/gst/controller/gstlfocontrolsource.c: + controlsource: clean up lfo control source + Remove parent_class and use var from G_DEFINE_TYPE macro. Remove unused dispose + implementation. + +2011-12-19 20:57:44 +0000 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: add new collectpads2 function to .def file + +2011-12-16 17:59:22 +0100 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: add convenience clipping function + ... which also converts to running time; useful for typical muxer. + +2011-12-19 17:38:18 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasetransform.c: + basetransform: do not delay sparse stream newsegment updates + +2011-12-19 17:00:18 +0100 Wim Taymans + + * gst/gstmemory.h: + memory: make subclasses add other flags + Add GST_MAP_FLAG_LAST so that implementations can add additional flags when + mapping memory. + +2011-12-19 12:33:18 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasetransform.c: + basetransform: suggestion compatible with upstream is not much of a suggestion + ... in that upstream is already complying with that suggestion. + Fixes #666174. + +2011-12-15 14:31:05 +0100 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + collectpads2: delay collecting buffer if a pad newly set waiting + ... as commented; make code correspond to it (again). + +2011-12-15 16:06:30 +0100 Stefan Sauer + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + controller: user the parent_class vars from G_DEFINE_TYPE + +2011-12-14 12:13:36 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + pad: allow NULL as filter caps argument with query_caps() + https://bugzilla.gnome.org/show_bug.cgi?id=666154 + +2011-12-12 13:05:36 +0000 Vincent Penquerc'h + + * plugins/elements/gstfilesrc.c: + filesrc: do not mistake short reads for EOS + While local filesystems will usually not cause short reads, + this may happen on seekable files on some remote filesystems. + Instead, loop till we get the requested amount of data, or + an actual EOS (ie, 0 bytes). + https://bugzilla.gnome.org/show_bug.cgi?id=665921 + +2011-11-14 02:26:31 +0100 Matej Knopp + + * libs/gst/base/gstbaseparse.c: + baseparse: Clear queued frames with other queues + +2011-12-12 12:11:40 +0000 Tim-Philipp Müller + + * configure.ac: + * gst/gstelementfactory.c: + elementfactory: use new 'transfer floating' annotation for gst_element_factory_make() + Requires gobject-introspection 1.31.1 (older versions will + error out with that). + https://bugzilla.gnome.org/show_bug.cgi?id=664099 + +2011-12-12 12:09:02 +0000 Tim-Philipp Müller + + * po/cs.po: + * po/eo.po: + * po/es.po: + * po/sr.po: + po: update languages + +2011-12-12 12:00:16 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-12-12 11:54:56 +0100 Sebastian Dröge + + * gst/glib-compat-private.h: + * gst/glib-compat.c: + glib-compat: Add license boilerplate for LGPL + +2011-12-10 01:16:05 +0000 Tim-Philipp Müller + + * po/LINGUAS: + * po/cs.po: + * po/eo.po: + * po/es.po: + * po/gl.po: + * po/sl.po: + * po/sr.po: + * po/uk.po: + po: update translations + +2011-12-10 11:08:22 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: say we handle RECONFIGURE event + We handle the RECONFIGURE event so return TRUE from the event handler. + +2011-12-10 11:07:02 +0100 Wim Taymans + + * gst/gstpad.c: + pad: don't forward on NULL pads + The iterator can return NULL in some cases, avoid pushing on those + NULL pads. + +2011-12-07 16:01:07 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstpreset.c: + * gst/gstpreset.h: + * win32/common/libgstreamer.def: + preset: allow applications to specify an extra preset dir + An extra application preset dir help to organize presets created for special + purposes. Fixes #660760 + API: gst_preset_set_app_dir(), gst_preset_get_app_dir() + +2011-12-09 10:01:16 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: stop when negotiation fails + +2011-12-08 17:32:19 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-12-08 18:00:00 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Fix code path to come up with possible caps if incompatible caps are provided to buffer_alloc() + Previous code could almost never work and this should be slightly + better. + +2011-12-08 17:21:30 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Fall back to upstream provided caps if suggested caps are not supported by the sinkpad + +2011-12-08 17:07:05 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Fall back to upstream provided caps if fixation of suggested caps failed + +2011-12-08 17:02:28 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Refactor gst_base_transform_buffer_alloc() code + Don't check if upstream provided caps are compatible with upstream + and don't try to fixate these caps. They must be fixated in any case. + +2011-12-08 00:49:17 +0000 Tim-Philipp Müller + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + win32: update .def files for latest API additions + +2011-12-08 00:47:46 +0000 Tim-Philipp Müller + + * tests/check/elements/selector.c: + tests: fix up selector test after merge + +2011-12-08 00:39:10 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstindexfactory.c + libs/gst/base/gstbasetransform.c + plugins/elements/gstfakesink.c + plugins/elements/gstfakesrc.c + plugins/elements/gstidentity.c + plugins/elements/gstinputselector.c + plugins/elements/gstoutputselector.c + Note: did not merge any of the basetransform changes from 0.10. + +2011-12-07 17:57:49 +0000 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: do not use a byte value instead of a time value when bisecting + This fixes FLAC seeking on some FLAC files. + +2011-12-07 11:04:42 +0100 Sebastian Dröge + + * tests/check/elements/selector.c: + selector: Push newsegment events before any buffers are pushed in the unit test + +2011-12-07 11:01:49 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Don't send a NEWSEGMENT event if a buffer arrived before the segment was configured + +2011-12-07 11:01:31 +0100 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + outputselector: Don't send last segment/buffer when no segment was configured yet + +2011-12-07 09:50:40 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: If suggested caps are not compatible with upstream try to come up with compatible caps + Fixes bug #662199. + +2011-12-06 23:52:53 +0000 Tim-Philipp Müller + + * gst/gstindexfactory.c: + indexfactory: fix memory leak + Introduced by commit bd302bb6 pluginfeature: avoid duplicating feature->name + https://bugzilla.gnome.org/show_bug.cgi?id=459466 + https://bugzilla.gnome.org/show_bug.cgi?id=665703 + +2011-12-06 18:09:13 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: put new event probe type next to other event types + +2011-12-05 21:20:52 +0100 Matej Knopp + + * gst/gstpad.c: + * gst/gstpad.h: + Add GST_PAD_PROBE_TYPE_HANDLE_FLUSH + +2011-12-06 14:55:15 +0100 Sebastian Dröge + + * plugins/elements/gstfakesink.c: + fakesink: Make event/buffer verbose output consistent with identity + +2011-12-06 14:55:11 +0100 Sebastian Dröge + + * plugins/elements/gstidentity.c: + identity: Print buffer flags in the verbose output + +2011-12-06 14:53:47 +0100 Sebastian Dröge + + * plugins/elements/gstfakesrc.c: + fakesrc: Make event/buffer verbose output consistent with identity and print buffer flags + +2011-12-06 14:46:46 +0100 Stefan Sauer + + * tests/check/gst/gstpad.c: + tests: don't include glib/gthread.h directly + The g_thread functions are available after including glib.h as per docs. + +2011-12-06 14:23:39 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + controller: port the test to new api as well + +2011-12-06 14:23:12 +0100 Stefan Sauer + + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstobject.c: + * gst/gstobject.h: + controller: fix gpointer vs. gpointer* mess up + +2011-12-06 14:24:15 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + pad: remove GST_FLOW_RESEND + It is unused and undefined. + +2011-12-06 14:01:50 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfakesrc.c: + basesrc: add async start option + Add a method to enable async start behaviour. The subclass can then complete the + start operation from any other thread by caling gst_base_src_start_complete(). + The base class can wait for the start to complete with + gst_base_src_start_wait(). + +2011-12-06 13:58:00 +0100 Wim Taymans + + * tests/check/libs/controller.c: + fix compilation + +2011-12-06 13:47:29 +0100 Wim Taymans + + * plugins/elements/gstfilesrc.c: + filesrc: cleanup error path + +2011-12-06 13:39:05 +0100 Wim Taymans + + * libs/gst/controller/gstinterpolation.c: + fix compilation + +2011-12-06 08:48:57 +0100 Stefan Sauer + + * gst/gstobject.c: + controller: use _OBJECT logging variants more + +2011-12-06 08:35:57 +0100 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstobject.c: + * gst/gstobject.h: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstlfocontrolsource.c: + * tests/benchmarks/controller.c: + controller: remove GstValueArray + Instead pass the values as arguments. This simplifies that code and helps + bindings. + +2011-12-06 08:35:10 +0100 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + * gst/gstobject.c: + * gst/gstobject.h: + controller: remove gst_object_get_value_arrays + One can easilly loop over the controlled properties manually. This is step 1 in + removing GstValueArray. + +2011-12-04 07:33:32 +0100 Matej Knopp + + * gst/gstpad.c: + correct return value in gst_push_sticky + +2011-12-05 11:07:24 +0100 Wim Taymans + + * gst/gstmessage.h: + * gst/gstquery.h: + make some macros into inline functions + +2011-12-05 10:24:34 +0100 Wim Taymans + + * gst/gstcaps.h: + * gst/gstevent.h: + * libs/gst/base/gsttypefindhelper.c: + make some more macros as inline functions + Make some macros as inline functions for added type checking. + USe new gst_caps_take() in typefind + +2011-12-05 10:23:04 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: remove some old methods + +2011-12-04 21:19:04 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: allow non-joinable threads in private g_thread_create() copy + Looks like some tests use non-joinable threads after all. + +2011-12-04 15:42:07 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: remove removed tag list functions from docs as well + +2011-12-04 15:38:09 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstobject.h + libs/gst/check/gstcheck.h + libs/gst/controller/gstcontroller.c + plugins/elements/gstidentity.c + tools/gst-xmlinspect.c + +2011-12-04 14:38:26 +0000 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gsttask.c: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads2.c: + * plugins/elements/gstmultiqueue.c: + Suppress deprecation warnings in selected files, for g_static_rec_mutex_* mostly + GStaticRecMutex is part of our API/ABI, not much we can do here in 0.10. + +2011-12-04 13:35:38 +0000 Tim-Philipp Müller + + * gst/glib-compat-private.h: + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstobject.h: + * gst/gsttask.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + Work around deprecated thread API in glib master + Add private replacements for deprecated functions such as + g_mutex_new(), g_mutex_free(), g_cond_new() etc., mostly + to avoid the deprecation warnings. We can't change most of + these in 0.10 because they're part of our API and ABI. + +2011-12-04 13:09:53 +0000 Tim-Philipp Müller + + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + benchmarks: g_thread_create() is deprecated in GLib master, use g_thread_try_new() instead + +2011-12-04 13:04:35 +0000 Tim-Philipp Müller + + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + net: initialise GError variables to NULL + +2011-12-04 11:43:10 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update defs files + +2011-12-04 11:42:39 +0100 Edward Hervey + + * gst/gstquery.c: + gstquery: Fix unitialized variable + +2011-12-04 11:32:57 +0100 Edward Hervey + + * gst/gstsegment.c: + gstsegment: Initialize with proper type + +2011-12-03 17:40:53 +0000 Tim-Philipp Müller + + * gst/gst.c: + * libs/gst/helpers/gst-plugin-scanner.c: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + g_thread_init() is deprecated in glib master + It's not needed any longer. + +2011-12-03 16:02:36 +0000 Tim-Philipp Müller + + * gst/gsttagsetter.c: + tagsetter: update for thread API deprecations in glib master + +2011-12-03 15:36:58 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: update for thread API deprecations in glib master + +2011-12-03 15:18:21 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: remove gst_tag_list_get_{char,uchar} + Those are unused and should never be used anywhere anyway + really. + +2011-12-03 14:06:58 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: remove some macros that no longer exist + +2011-12-03 13:58:51 +0000 Tim-Philipp Müller + + * gst/gstsystemclock.c: + * libs/gst/check/gstcheck.h: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + g_thread_create() is deprecated in GLib master, use g_thread_try_new() instead + +2011-12-03 07:06:11 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: use dts and pts for sync + First use DTS, then fall back to PTS for synchronization. + +2011-12-03 07:01:45 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: small cleanups + +2011-12-03 06:45:26 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: merge preroll functions + Inline a function that is only called from one place to make things a little + easier to follow. + +2011-12-03 06:29:42 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: more cleanups + Don't pass around the object type, we can find that very efficiently from the + object itself now. + +2011-12-02 23:13:23 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: clean up method names + +2011-12-02 22:50:55 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: merge render_object into chain + Merge the render_object code with the chain method. It is only called from there + and there are quite a few variables that can be reused to makes things less + confusing. + +2011-12-02 22:36:38 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: remove obsolete code + Remove some more code now that the render_object ethod is only + called with buffers or bufferlsts. + +2011-12-02 22:20:08 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfilesink.c: + basesink: clean up event handling + Add new wait_eos vmethod to wait for the eos timeout before posting the EOS + message on the bus. + Add default event handler. Move the default event actions in there. Call the + event vmethod from the pad event handler. Subclasses are now supposed to chain + up to the parent event handler or unref the event and do their own thing. + Avoid passing unused parameters to functions. + +2011-12-02 13:19:38 +0100 Mark Nauwelaerts + + * plugins/elements/gstidentity.c: + identity: unlock clock wait when appropriate + ... notably FLUSH and state change to READY. + +2011-12-02 13:35:58 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: small cleanup + Avoid passing around the segment. + +2011-12-02 13:28:18 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: remove clip_segment + We only need one segment now that the preroll queue is gone. + +2011-12-02 12:42:50 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: more cleanups + Remove some unneeded functions, inline the code. + Remove the queue_object functions, we can proceed with the rendering + immediately. + +2011-12-02 12:20:02 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: remove obsolete code + Remove the preroll queue and proceed directly to the rendering of objects. + +2011-12-01 23:35:26 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstbus.c + gst/gstevent.c + libs/gst/base/gstbasetransform.c + +2011-12-01 18:50:32 +0100 Wim Taymans + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: make some tags of type GstSample + Make the image and attachment tags of type GstSample so that we can include + extra caps and info along with the buffer data. + +2011-12-01 18:49:34 +0100 Wim Taymans + + * gst/gstsample.c: + * gst/gstsample.h: + sample: remove const + The writability of the structure is ensured by the refcount of the parent + miniobject and we're fine if the parent is writable. + +2011-12-01 16:46:06 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * tests/check/libs/basesink.c: + * win32/common/libgstbase.def: + basesink: last-buffer -> last-sample + Rename the last-buffer property to last-sample and make it return the new + GstSample type so that we can include caps and timing info in one nice bundle. + +2011-12-01 16:37:46 +0100 Wim Taymans + + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstsample.c: + * gst/gstsample.h: + * win32/common/libgstreamer.def: + sample: add new sample miniobject + Add a new simple miniobject that is a combination of a GstBuffer, GstCaps, + GstSegment and other arbitrary info organized in a GstStructure. This object can + be used to exchange samples between an element and the application or for + storing album art in tags etc. + +2011-12-01 16:25:07 +0100 Stefan Sauer + + * gst/gstbus.c: + bus: use GST_MESSAGE_SOURCE_NAME() which also takes care of src=NULL. + +2011-12-01 15:35:26 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: add some more debug + +2011-12-01 15:35:02 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: add some more debug + +2011-12-01 15:34:06 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add copy flag for meta + Add a flag to control if the meta should be copied or not instead of always + copying. + +2011-11-29 19:08:41 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: remove old property + +2011-11-30 13:59:46 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Always intersect the suggested sink caps with the peer caps + This makes sure that we get correct and complete caps. The suggested caps + could be incomplete, e.g. video/x-raw-rgb without any fields, and by + intersecting with the peer caps we get something usable. + Fixes bug #662199. + +2011-11-30 12:39:34 +0000 Tim-Philipp Müller + + * gst/gstinfo.h: + info: move FIXME log level after WARNING + So it's now ERROR < WARNING < FIXME < INFO and *:5 becomes *:6. + +2011-11-30 00:24:32 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + event: warn and fail instead of creating newsegment events in GST_FORMAT_UNDEFINED + +2011-11-29 15:53:01 +0100 Wim Taymans + + * gst/gstbin.c: + bin: keep the element flags up-to-date + Keep the require/provide_clock flags up to date. + +2011-11-29 11:47:34 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: source and sink pads proxy caps + +2011-11-28 23:20:32 +0000 Tim-Philipp Müller + + Merge commit '7521b597f4dc49d8d168f368f0e7ebaf98a72156' into 0.11 + +2011-11-28 21:15:31 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-11-28 18:23:41 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + update for indexable change + +2011-11-28 18:12:34 +0100 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + * tools/gst-inspect.c: + * win32/common/libgstreamer.def: + element: add indexable flag + Remove the is_indexable method check and use an element flag to check if the + element can use an index. + +2011-11-28 17:50:17 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2011-11-28 17:22:44 +0100 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * tools/gst-inspect.c: + element: use flags for require/provide clock + Remove the _require/_provide_clock() methods and use element flags to mark + elements instead of looking at the implementation of the vmethod. + +2011-11-28 16:54:55 +0100 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * tests/check/gst/gstbin.c: + element: clean up element flags + Clean up the element flags + +2011-11-28 15:35:21 +0100 Wim Taymans + + * gst/gstevent.c: + event: add sticky custom quark + +2011-11-28 14:24:16 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: _CAPS_FLAGS_ -> CAPS_FLAG_ + +2011-11-28 12:30:15 +0000 Vincent Penquerc'h + + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + gstelement: add gst_element_class_add_pad_template_from_static + This function helps ensure the pad template is unreffed + without having to complicate the calling code. + https://bugzilla.gnome.org/show_bug.cgi?id=662664 + +2011-11-28 13:08:27 +0000 Vincent Penquerc'h + + * plugins/elements/gstdataurisrc.c: + various: fix pad template ref leaks + https://bugzilla.gnome.org/show_bug.cgi?id=662664 + +2011-11-28 13:54:43 +0100 Wim Taymans + + * gst/gstpad.c: + pad: Handle sticky event errors + Use GstFlowReturn to internally pass events between pads. + When we sticky events cause an error, translate this error into a GstFlowReturn. + Caps events will, for example, generate a NOT_NEGOTIATED return when the event + function returns an error. + This allows us then to refuse sending buffers if one of the sticky events is + refused and generate a correct error return value. + +2011-11-28 13:52:00 +0100 Wim Taymans + + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + tests: don't return FALSE from events + Returning FALSE from the event handler shuts down the sender. + +2011-11-28 13:51:11 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + test: fix refcount error + +2011-11-28 11:15:27 +0100 Edward Hervey + + * gst/gstmeta.c: + gstmeta: Some more docs + +2011-11-28 10:55:28 +0100 Wim Taymans + + * gst/gstevent.h: + event: add custom downstream sticky event + +2011-11-28 01:12:48 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix up comment after merge from 0.10 + +2011-11-28 01:11:47 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-11-28 01:10:20 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix refactoring of draining-on-eos, munge flow return to FLOW_OK + +2011-11-28 01:00:28 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix up new bufferlist code for 0.11 + +2011-11-28 00:40:55 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + plugins/elements/gstqueue2.c + +2011-11-03 10:34:49 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: add bufferlist support + We want to maintain buffer lists if possible. + +2011-11-03 13:02:36 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: split out draining of queue on FLOW_UNEXPECTED into separate function + +2011-11-03 08:55:20 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: pass item type enum to _enqueue instead of simple isbuffer boolean + Avoids some unnecessary GST_IS_EVENT() + +2011-11-27 20:32:14 +0100 Matej Knopp + + * gst/gstcaps.h: + caps: fix compilation warning + GST_STATIC_CAPS is missing initializer for GstMiniObject's n_weak_refs and + weak_refs resulting in compilation warning (llvm-gcc -Wall) + https://bugzilla.gnome.org/show_bug.cgi?id=664927 + +2011-11-27 22:26:12 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-11-27 20:36:31 +0100 Stefan Sauer + + * gst/gstbin.c: + * gst/gstelement.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + warnings: avoid set-but-unused warnings with load-save disabled + +2011-11-26 17:34:12 +0100 Matej Knopp + + * libs/gst/base/gstbaseparse.c: + baseparse: fix broken default caps query + https://bugzilla.gnome.org/show_bug.cgi?id=664880 + +2011-11-26 19:51:37 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-11-26 19:45:48 +0000 Tim-Philipp Müller + + * gst/gsturi.h: + uri: fix wrong G_GNUC_MALLOC + _get_protocols() points to const memory in 0.10 + despite the non-const return value. + +2011-11-26 19:44:23 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstbuffer.h + gst/gstbufferlist.h + gst/gstcaps.h + gst/gstdatetime.h + gst/gstelementfactory.h + gst/gstevent.h + gst/gstghostpad.h + gst/gstindexfactory.h + gst/gstiterator.h + gst/gstmessage.h + gst/gstminiobject.h + gst/gstpipeline.h + gst/gstquery.h + gst/gstsegment.h + gst/gststructure.h + gst/gsttaglist.h + gst/gsturi.h + gst/gstvalue.h + libs/gst/base/gstbitreader.h + libs/gst/base/gstbytereader.h + libs/gst/base/gstbytewriter.h + Note: can't use G_GNUC_MALLOC with GstCaps return + values in 0.11 because of the EMPTY+ANY singletons. + +2011-11-26 18:58:38 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstdataqueue.h: + libs: sprinkle some G_GNUC_MALLOC + Maybe gcc can do something clever with that, or at least + warn us if we don't save the return value somewhere. + +2011-11-26 18:57:44 +0000 Tim-Philipp Müller + + * gst/gstatomicqueue.h: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.h: + * gst/gstdatetime.h: + * gst/gstelementfactory.h: + * gst/gstevent.h: + * gst/gstghostpad.h: + * gst/gstindexfactory.h: + * gst/gstiterator.h: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstpadtemplate.h: + * gst/gstparamspecs.h: + * gst/gstparse.h: + * gst/gstpipeline.h: + * gst/gstpluginfeature.h: + * gst/gstpoll.h: + * gst/gstpreset.h: + * gst/gstquery.h: + * gst/gstsegment.h: + * gst/gststructure.h: + * gst/gsttaglist.h: + * gst/gsturi.h: + * gst/gstvalue.h: + gst: sprinkle some G_GNUC_MALLOC + Maybe gcc can do something clever with that, or at least + warn us if we don't save the return value somewhere. + +2011-11-25 23:54:57 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-11-25 23:15:23 +0100 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + docs: update porting docs. + +2011-11-16 01:04:45 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: + * win32/common/libgstreamer.def: + buffer: add gst_buffer_{set,get}_qdata() + Allows people/us to attach arbitrary metadata to buffers. + https://bugzilla.gnome.org/show_bug.cgi?id=664720 + API: gst_buffer_set_qdata() + API: get_buffer_get_qdata() + +2011-11-25 07:11:24 +0100 Wim Taymans + + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: fix blocking probe emission + If we are dealing with a blocking probe, only then check if one the + blocking flags of the hook matches. + Add some more debug. + Make the pad unit test less racy. + +2011-11-24 17:47:09 +0100 Matej Knopp + + * tests/check/gst/gstpad.c: + Add test for PAD_PROBE_TYPE_BLOCK and PAD_PROBE_TYPE_BLOCKING + +2011-11-25 05:54:09 +0100 Wim Taymans + + * gst/gstutils.c: + utils: fix debug of query result + +2011-11-24 22:52:19 +0100 René Stadler + + * gst/gstquery.c: + query: fix typo in doc + Causes a warning from the introspection scanner. + +2011-11-24 21:36:12 +0100 René Stadler + + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * tests/check/elements/capsfilter.c: + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/identity.c: + * tests/check/elements/queue.c: + * tests/check/elements/selector.c: + check: drop caps argument from gst_check_setup_{src,sink}_pad + Calling set_caps at that point is not useful in 0.10 (FIXME comment!), and in + 0.11 it is totally pointless: the caps event doesn't stick to a flushing pad. + +2011-11-24 14:07:14 +0100 René Stadler + + * win32/common/libgstbase.def: + defs: update for byte_writer_put_buffer + +2011-11-24 11:23:07 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstpad.c + libs/gst/base/gstbaseparse.c + +2011-11-24 11:15:29 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Remove g_warning() if pad accepted caps that are not a subset of the pad caps + This check is correct but unfortunately it's impossible to implement + in a threadsafe way because the caps could have changed in the meantime. + Fixes bug #659606. + +2011-10-03 12:34:20 +0100 Vincent Penquerc'h + + * plugins/elements/gstmultiqueue.c: + multiqueue: check filled state of queues even if another one is empty + This will avoid a case where overrun is never signalled if some + stream never produces any data, causing playbin2 to not end preroll. + https://bugzilla.gnome.org/show_bug.cgi?id=660778 + +2011-11-24 09:31:14 +0100 Edward Hervey + + * tests/check/gst/gstpad.c: + tests: Check for dataflow with incompatible caps + This test currently fails, but is there to ensure we fix this issue + and keep it fixed, since it completely breaks delayed negotiation + use-cases. + This behaviour started breaking since + dd65aae9a177f7b11dcef0f690a78d698f667cd4 + +2011-11-24 09:31:02 +0100 Edward Hervey + + * tests/check/gst/gstpad.c: + tests: Add comments to gstpad tests + +2011-11-24 09:30:14 +0100 Edward Hervey + + * tests/check/gst/gstpad.c: + tests: Remove "#if 0" block for behaviour that now works + +2011-11-24 09:28:32 +0100 Edward Hervey + + * tests/check/gst/gstpad.c: + tests: Remove commented block + This behaviour is actually tested in test_push_unlinked + +2011-11-24 01:06:52 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: make gst-inspect print a nasty debug message for non-grata property type + Try to eradicate properties of long/ulong/char/uchar type. + +2011-11-23 17:50:17 +0100 Wim Taymans + + * gst/gstevent.h: + * gst/gstpad.c: + * gst/gstpad.h: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gsttee.c: + event: add STICKY_MULTY events + Add a new event flag for sticky events so that multiple events of that type can + be stored on a pad at the same time. Change the _get_sticky_event() function to + loop over the multiple events of a type. + Change the foreach function to make it possible to removed and modify the sticky + events on a pad. + Use an variable size array now to store the events. This could later be + optimized some more. + +2011-11-23 17:39:43 +0100 Wim Taymans + + * gst/gstbus.c: + bus: handle NULL message src in debug + +2011-11-23 17:38:24 +0100 Wim Taymans + + * gst/gstbufferlist.c: + bufferlist: avoid reading past the array + When the foreach function told us to remove the buffer from the list, decrease + the length of the array or else we might read past the last item in the array. + +2011-11-23 13:42:56 +0100 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Return template caps instead of other side's peer caps if get_sink_caps vfunc is not implemented + Using gst_pad_proxy_get_caps() breaks backwards compatibility with old + parsers because it will propagate the other side's fields like "parsed" + and "framed" and also breaks parser/converters. + Fixes bug #664221. + +2011-11-23 11:03:19 +0100 René Stadler + + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + bytewriter: add method to write out a buffer + In 0.10, this can be done with a one-liner by using GST_BUFFER_DATA/SIZE with + put_data. A 0.11 user has to resort to gst_buffer_map, which is less convenient + and might require a memcpy internally. + API: gst_byte_writer_put_buffer() + +2011-11-23 08:17:36 +0100 Wim Taymans + + * gst/gstpad.c: + pad: take peerpad correctly + Don't take the peerpad too early, it might change because of the + probes. + +2011-11-22 18:32:51 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: rework sticky events + Rewrite sticky events, trying to make it a bit more simple. + When sticky events are pushed on a srcpad, store them in the sticky event + array and mark the event with received = FALSE. + When the sticky event is successfully sent to the peer pad, make + received = TRUE. + Keep a PENDING_EVENTS pad flag that is set when one of the events is in + the received = FALSE state for some reason. + when activating a sinkpad, mark all events received = FALSE on the peer + srcpad. + When pushing a buffer, check the PENDING_EVENTS flag and if it is set, push all + events to the peer pad first. + +2011-11-22 18:32:23 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: also let caps events go through + +2011-11-22 16:43:34 +0100 Wim Taymans + + * gst/gst.c: + gst: add new flags + +2011-11-21 18:56:19 +0100 Matej Knopp + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: fix return type of _map() to gconstpointer + Fixes compiler warnings on OSX: + gstadapter.h:82: warning: type qualifiers ignored on function return type + gstadapter.c:412: warning: type qualifiers ignored on function return type + const gpointer is not the same as gconstpointer or const void *. + https://bugzilla.gnome.org/show_bug.cgi?id=664491 + +2011-11-22 12:46:39 +0100 Wim Taymans + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + defs: update defs files + +2011-11-22 12:45:41 +0100 Wim Taymans + + * gst/gstbuffer.h: + * gst/gstevent.h: + padd return value from _mini_object_replace() + +2011-11-21 18:56:19 +0100 Matej Knopp + + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue2.c: + Fix printf format compiler warnings on OSX/64bit + https://bugzilla.gnome.org/show_bug.cgi?id=664491 + +2011-11-21 17:46:45 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + tests: improve pad tests + +2011-11-21 17:43:51 +0100 Wim Taymans + + * gst/gstpad.c: + pad: fix locking order error + +2011-11-21 17:43:04 +0100 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: fix print format + +2011-11-21 15:47:01 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + pad: Add destroy notify to pad functions + Add _full variants of the pad function setters that take a destroy notify. + Make some macros that make the old method name pass NULL to this new + function. + +2011-11-21 13:29:05 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/filesrc.c: + pad: Merge pad mode activation functions + Add the pad mode to the activate function so that we can reuse the same function + for all activation modes. This makes the core logic smaller and allows for some + elements to make their activation code easier. It would allow us to add more + scheduling modes later without having to add more activate functions. + +2011-11-18 18:08:21 +0100 Wim Taymans + + * docs/design/part-scheduling.txt: + * gst/gstquery.c: + docs: update design doc + also fix default alignment value (0 == no-alignment) + +2011-11-18 17:27:16 +0100 Wim Taymans + + * gst/gstpad.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstpushsrc.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + query: improve scheduling query + Turns some boolean arguments in the scheduling query to flags, which are easier + to extend and makes the code easier to read. + Make extra methods for configuring and querying the supported scheduling modes. + This should make it easier to add new modes later. + +2011-11-18 14:08:45 +0100 Wim Taymans + + * gst/gstquery.h: + query: move flags closer to buffering query + +2011-11-18 13:46:46 +0100 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + pad: add parent to activate functions + +2011-11-18 12:35:46 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gst.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + pad: fix scheduling mode enums + GstPadActivateMode -> GstPadMode + GST_PAD_ACTIVATE_* -> GST_PAD_MODE_* + +2011-11-17 16:14:34 +0100 Wim Taymans + + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * plugins/elements/gsttypefindelement.c: + typefind: fix for new getrange method signature + gst_type_find_helper_get_range_ext -> gst_type_find_helper_get_range + +2011-11-17 12:40:45 +0100 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads2.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/funnel.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/elements/tee.c: + * tests/check/elements/valve.c: + * tests/check/gst/gstpad.c: + * tests/check/libs/test_transform.c: + pad: add parent to other functions + Add parent to chain, chain_list, getrange and event functions. + +2011-11-17 08:21:05 +0100 Stefan Sauer + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * tests/check/libs/collectpads.c: + collectpads: move fields out of reserved and restore padding + Do the 0.11 ABI changes. Add extra fields for destroy_notify and drop the qdata + hack. Rename _add_pad_full to _add_pad and remove the old _add_pad. + +2011-11-16 17:49:46 +0100 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + add parent to internal links + +2011-11-16 17:22:56 +0100 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + * tests/check/elements/multiqueue.c: + pad: add parent to the query function + +2011-11-16 12:36:51 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + * gst/gstdebugutils.c: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + GstPadFlags: rename flags GST_PAD_* -> GST_PAD_FLAG_* + +2011-11-16 12:10:55 +0100 Wim Taymans + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gstvalve.c: + plugins: remove obsolete parent checks + +2011-11-16 12:08:22 +0100 Wim Taymans + + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpad.h: + pad: keep the parent alive when requested + Add a new pad flag NEED_PARENT that ensures that the parent of a pad is + reffed and not NULL when the event, query and internal links functions + are called. + When a pad is added to an element automatically make sure the NEED_PARENT flag + is enabled. + +2011-11-16 10:29:47 +0100 Wim Taymans + + * gst/gstutils.c: + don't require parent element to proxy + +2011-11-16 10:16:55 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + update porting doc + +2011-11-15 18:16:24 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + pad: move query convenience functions together + Move the caps convenience functions to the other query functions. + +2011-11-15 17:50:34 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * plugins/elements/gstqueue2.c: + _query_peer_*() -> _peer_query_*() + +2011-11-15 17:40:19 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstcapsfilter.c: + _accept_caps() -> _query_accept_caps() + +2011-11-15 17:11:46 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/elements/selector.c: + _peer_get_caps() -> peer_query_caps() + +2011-11-15 16:46:37 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/highlevel-components.xml: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/elements/selector.c: + * tests/check/elements/valve.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstutils.c: + pad: _get_caps() -> _query_caps() + +2011-11-15 16:16:53 +0100 Wim Taymans + + * gst/gstutils.c: + utils: fix docs + +2011-11-15 16:13:59 +0100 Wim Taymans + + * gst/gstutils.c: + utils: fix the proxy functions + fix the proxy functions for query_accept_caps and query_caps to use the pad + forward helper functions which correctly forwards on the internally linked pads. + +2011-11-15 16:13:28 +0100 Wim Taymans + + * gst/gstpad.h: + pad: improve some flag macros + +2011-11-15 16:13:15 +0100 Wim Taymans + + * gst/gstpad.c: + pad: fix debug line + +2011-11-15 11:20:48 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstdebugutils.c: + * gst/gstelement.c: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gstvalve.c: + * tests/check/elements/multiqueue.c: + * tests/check/gst/gstutils.c: + * tools/gst-inspect.c: + pad: remove getcaps and use caps query + Remove the getcaps function on the pad and use the CAPS query for + the same effect. + Add PROXY_CAPS to the pad flags. This instructs the default caps event and query + handlers to pass on the CAPS related queries and events. This simplifies a lot + of elements that passtrough caps negotiation. + Make two utility functions to proxy caps queries and aggregate the result. Needs + to use the pad forward function instead later. + Make the _query_peer_ utility functions use the gst_pad_peer_query() function to + make sure the probes are emited properly. + +2011-11-14 11:26:17 +0100 Wim Taymans + + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + query: add caps query + +2011-11-14 09:57:32 +0000 Tim-Philipp Müller + + * gst/gstquery.h: + query: remove GST_QUERY_LAST + +2011-11-14 10:27:01 +0100 Wim Taymans + + * gst/gstbufferpool.h: + * gst/gstmemory.h: + * gst/gstmeta.h: + * gst/gstpad.h: + * gst/gstquery.h: + fix docs + +2011-11-12 10:29:30 +0200 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + controller: remove functions to add/remove controlled properties + Make that implizit with attaching/detaching controlsources. This is a lot easier + and has less invalid state (controlled property without control source). + +2011-11-13 23:55:56 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + Update for GstURIHandler get_protocols() changes + +2011-11-13 23:25:23 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * tools/gst-inspect.c: + plugins, tools: update for get_protocols() return value change + +2011-11-13 23:14:15 +0000 Tim-Philipp Müller + + * gst/gsturi.h: + uri: clean up header files + Tabs to spaces. + +2011-11-13 23:07:58 +0000 Tim-Philipp Müller + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gsturi.c: + * gst/gsturi.h: + urihandler: fix return type of get_protocols() + +2011-11-13 20:56:02 +0000 Tim-Philipp Müller + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gsturi.h: + urihandler: fix return type of _get_uri_type() + Return a GstURIType and not a plain guint. + +2011-11-13 17:45:19 +0000 Tim-Philipp Müller + + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + tests: update unit tests for URI handler API changes + +2011-11-13 17:44:57 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + elements: update fd + file sources and sinks for GstUriHandler changes + +2011-11-13 17:44:06 +0000 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + * gst/gst.c: + * gst/gsturi.c: + * gst/gsturi.h: + * win32/common/libgstreamer.def: + urihandler: pass GError argument to gst_uri_handler_set_uri() + Also let gst_uri_handler_set_uri check already if the protocol + is supported, so that not every uri handler has to do that + itself. + +2011-11-13 15:51:44 +0000 Tim-Philipp Müller + + * gst/gsturi.c: + * gst/gsturi.h: + urihandler: make _get_uri() return a copy + For thread-safety. + +2011-11-13 15:37:40 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: + * gst/gsturi.h: + * plugins/elements/gstfilesrc.c: + urihandler: remove "new-uri" signal + No one but filesrc used that API. Should probably be replaced by + requiring an "uri" property instead, and then objects can do a + notify on that. Also removed interface structure padding, it's + not needed. + +2011-11-13 13:23:09 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + tools/gst-inspect.c + +2011-11-12 16:42:14 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: print current value as default value + Instead of printing separate 'Current' and 'Default' values + (the former obtained via g_object_get() and the latter from + the property GParamSpec), simply print the Current value as + the Default value. This is the right thing to do for almost + all elements and avoids confusion if a subclass of a base + class chooses a different default than the base class. + +2011-11-12 14:55:07 +0000 Tim-Philipp Müller + + * gst/gstelementfactory.c: + * gst/gstparse.c: + * gst/gstplugin.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + gst, controller: replace g_list_prepend + reverse with GQueue + +2011-11-12 14:04:10 +0000 Tim-Philipp Müller + + * gst/gstbuffer.h: + docs: fix typo in buffer docs + +2011-11-12 01:54:44 +0100 René Stadler + + * libs/gst/base/gstbasetransform.c: + basetransform: fix caps unref in transform_caps filter subset check + I did not test this, but the code looked very wrong. + +2011-11-12 01:51:11 +0100 René Stadler + + * gst/gstquery.c: + query: do not return a ref from parse_accept_caps + Makes this exactly like gst_event_parse_caps. This is what current code + expects, so it fixes some leaks. + +2011-11-11 17:17:43 +0100 Wim Taymans + + * libs/gst/base/gstbaseparse.h: + * libs/gst/base/gstbitreader-docs.h: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstcollectpads2.h: + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gstlfocontrolsourceprivate.h: + * libs/gst/dataprotocol/dataprotocol.h: + * libs/gst/net/gstnetaddressmeta.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.h: + .h: fix header files + Ensure correct indentation and retab + Make sure all structure have padding + +2011-11-11 16:52:41 +0100 Wim Taymans + + * gst/gst.h: + * gst/gstbufferpool.h: + * gst/gstbus.h: + * gst/gstchildproxy.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstcontrolsource.h: + * gst/gstdatetime.h: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gstformat.h: + * gst/gstghostpad.h: + * gst/gstindex.h: + * gst/gstindexfactory.h: + * gst/gstiterator.h: + * gst/gstmemory.h: + * gst/gstmeta.h: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstparamspecs.h: + * gst/gstpipeline.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.h: + * gst/gstpluginloader.h: + * gst/gstpreset.h: + * gst/gstregistry.h: + * gst/gsttagsetter.h: + * gst/gsttask.h: + * gst/gsttaskpool.h: + * gst/gsttrace.h: + * gst/gsttypefindfactory.h: + * gst/gstutils.h: + * gst/gstvalue.h: + .h: fix header files + Ensure correct indentation and :retab. + Make sure all structures have padding + Fix up some old ABI additions. + +2011-11-11 17:04:52 +0200 Stefan Sauer + + * gst/gstobject.c: + docs: fix invalid xml + +2011-11-11 10:00:35 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: avoid < -1 sizes + +2011-11-11 01:47:30 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + buffer, memory: make size arguments where -1 is allowed signed + +2011-11-11 01:44:16 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for latest API changes + +2011-11-10 19:37:28 +0200 Stefan Sauer + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * docs/random/porting-to-0.11.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstcontroller.c: + * gst/gstcontroller.h: + * gst/gstcontrolsource.c: + * gst/gstobject.c: + * gst/gstobject.h: + * tests/benchmarks/controller.c: + * tests/check/libs/controller.c: + * tests/examples/controller/audio-example.c: + controller: merge controller into gstobject + This make the controller even more lightweight (no extra object, no extra lock, + less indirections). For object that don't use the controller the only 'overhead' + is a 3 unused fields in the gst_object structure. + +2011-11-10 18:58:35 +0100 Wim Taymans + + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + netmeta: avoid using g[u]long in headers + +2011-11-10 18:18:24 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbaseparse.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/libs/adapter.c: + adapter: remove flush from _unmap + +2011-11-10 16:02:59 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: implement a default get_caps function + Don't rely on the return value of a vmethod to trigger the default + implementation but make a real defaul implementation of the method that the + subclass can chain up to. + +2011-11-10 14:13:54 +0000 Vincent Penquerc'h + + * gst/gstbuffer.c: + gstbuffer: remove incorrect assertion + Offset and sizes have no bearing on each other here. + +2011-11-10 13:59:28 +0100 Edward Hervey + + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + win32: Update def files + +2011-11-10 13:53:33 +0100 Edward Hervey + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + gst: More introspection annotations + +2011-11-10 13:51:28 +0100 Edward Hervey + + * gst/gstmemory.c: + * gst/gstmemory.h: + gstmemory: Register a GBoxed GType + Allows using it from g-i + +2011-11-10 13:50:23 +0100 Edward Hervey + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Add --warn-all to introspection scanner + ... and let's get fixing all those docs ! + +2011-11-10 13:38:58 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix vmethods + Make a default implementation of the transform_caps vmethod so that subclasses + can call into it. + Make a default implementation of transform_size. + Avoid doing something in the vmethod trampoline. + +2011-11-10 13:37:12 +0100 Wim Taymans + + * tests/check/libs/test_transform.c: + tests: only override when != NULL + Only override the methods in the unit tests when != NULL otherwise we might + override the default implementation. + +2011-11-10 13:36:10 +0100 Wim Taymans + + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + pushsrc: make alloc method a vmethod + +2011-11-10 12:33:49 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: reorder vmethod according to .h file + +2011-11-10 12:33:33 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.h: + basesink: improve comments + +2011-11-10 12:33:10 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: don't do things in the vmethod trampoline + +2011-11-10 12:09:57 +0100 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + element: add a default set_clock implementation + Add a default set_clock implementation and avoid doing work in the vmethod + trampoline. This requires subclasses to chain up. + +2011-11-10 12:08:51 +0100 Wim Taymans + + * gst/gstelement.c: + element: don't do anything in the vmethod trampoline + Avoid doing stuff in the vmethod trampoline, just let the default + implementation of the method take care of things. + +2011-11-10 12:08:15 +0100 Wim Taymans + + * gst/gstelement.c: + element: fix some docs + +2011-11-10 11:42:26 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: use gpointer for return types + +2011-11-10 11:12:36 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update doc + +2011-11-10 10:58:42 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstpad.c: + * tools/gst-inspect.c: + pad: remove GstPadFixateCapsFunction + The fixate caps function was not used externally and we have vmethods in the + base classes where it is needed. + Update some docs. + simplify some fixate functions in the base classes. Also pass the untruncated + caps to the vmethod. + +2011-11-09 17:43:49 +0100 Wim Taymans + + * gst/gstpad.c: + pad: don't store events on flushing pads + check the flushing state of the pad before storing the event. + +2011-11-09 17:36:00 +0100 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * tools/gst-inspect.c: + pad: make an ACCEPT_CAPS query + Replace the acceptcaps function with a query. + +2011-11-09 17:25:30 +0100 Wim Taymans + + * gst/gstpad.c: + * plugins/elements/gsttypefindelement.c: + pad: refuse events in flushing + when we are flushing, don't store the event on the pad but simply return FALSE. + Don't deactivate the srcpad, we need it to be active in order to push the + caps. Downstream can change the scheduling mode of an active pad. + +2011-11-09 17:19:12 +0100 Wim Taymans + + * gst/gstelement.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + element: remove more query_types + +2011-11-09 11:05:59 +0100 Stefan Sauer + + * Android.mk: + * tests/examples/controller/Makefile.am: + Android: build audio controller example + Add buildsystem hooks for building the audiocontroller example + with the NDK. + Signed-off-by: Reynaldo H. Verdejo Pinochet + +2011-11-09 12:21:17 +0100 René Stadler + + * tests/check/gst/gstpad.c: + tests: pad: add tests for sticky caps handling + test_sticky_caps_flushing is currently failing. + +2011-11-09 12:12:26 +0100 Wim Taymans + + * common: + update common + +2011-11-09 12:03:28 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-11-09 12:02:12 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting doc + +2011-11-09 11:47:10 +0100 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasetransform.c: + * tools/gst-inspect.c: + remove query types + It was not really useful + +2011-11-08 18:09:28 +0000 Vincent Penquerc'h + + * gst/gstvalue.c: + gstvalue: consider lists and ranges equal if they hold the same set + This fixes caps operations when different elements advertise some + of their caps' properties differently (eg, for audio channels, either + a range from 1 to 2, or a list of 1 and 2). + https://bugzilla.gnome.org/show_bug.cgi?id=663643 + +2011-11-09 11:24:26 +0100 Stefan Sauer + + * tests/check/gst/gststructure.c: + tests: add a subset test for structure + +2011-11-09 11:22:36 +0100 Wim Taymans + + * gst/gstghostpad.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + pad: add more queries + Add more query functions to prepare for doing more with queries + +2011-10-28 13:39:58 +0200 Stefan Sauer + + * docs/manual/advanced-dparams.xml: + docs: also fix wrong call order for controller in manual + +2011-11-08 17:32:11 +0100 Wim Taymans + + * docs/design/part-probes.txt: + * gst/gstpad.c: + * gst/gstpad.h: + pad: install query probes + Fire query probes according to updated design doc. + +2011-11-08 15:51:48 +0100 Wim Taymans + + * gst/gstpad.h: + pad: remove lock/unlock_full versions of stream-lock + +2011-11-08 15:48:34 +0100 Wim Taymans + + * gst/gstpad.h: + pad: add defines for query probes + +2011-11-08 13:30:18 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + pad: fix unit test + +2011-11-08 13:13:55 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: update docs + +2011-11-08 13:02:04 +0100 Wim Taymans + + * tests/check/gst/gstpad.c: + test: port to 0.11 + +2011-11-08 12:54:15 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstelement.h + gst/gstghostpad.c + gst/gstminiobject.c + +2011-11-08 12:47:33 +0100 Wim Taymans + + * docs/design/part-probes.txt: + * gst/gstpad.c: + * gst/gstpad.h: + pad: add pull mode probes + Allow probes to inspect the offset and size from a probe in pull mode and allow + the probe to modify the buffer. + Update design doc a little. + +2011-11-08 12:22:21 +0100 René Stadler + + * tests/check/gst/gstpad.c: + tests: pad: add test to verify flushing behaviour + Seems like a trivial case, but this was actually broken in 0.11 recently. + +2011-11-08 11:04:19 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/elements/selector.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/basesrc.c: + * tests/check/pipelines/queue-error.c: + pad: Add GstPadProbeInfo + Make a new GstPadProbeInfo structure and pass this in the probe callback. This + allows us to add more things later and also allow the callback to replace or + modify the passed object. + +2011-11-08 08:26:29 +0100 Stefan Sauer + + * gst/gstevent.c: + event: log creation of qos events at LOG level instead at INFO + +2011-11-07 16:57:37 +0100 Stefan Sauer + + * gst/gstbuffer.c: + buffer: improve parameter docs + +2011-11-08 00:32:36 +0000 Tim-Philipp Müller + + * gst/gstcaps.c: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstminiobject.c: + * gst/gststructure.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + docs: fix Since: markers for API added after 0.10.35 + +2011-11-08 00:15:49 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def file for new API + API: gst_caps_is_strictly_equal() + +2011-11-07 17:17:39 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstvalue.c + +2011-11-07 17:04:13 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/elements/selector.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/basesrc.c: + * tests/check/pipelines/queue-error.c: + pad: rework pad probes + Make a separate cookie to detect chancges in the list of probes and keeping + track of what hooks have been invoked yet. + Remove the requirement to have probes on srcpads in push mode and sinkpads in + pull mode. + Add some more debug. + Keep track of what callbacks got executed. If no callback is called and we are a + blocking pad, let the item pass. This allows you to block pads on selected + items only. + Explicitly have an UPSTREAM and DOWNSTREAM PadProbeType. This allows you to only + block the pad on upstream or downstream items. + Add convenience macros to only block on downstream/upstream items. + +2011-10-27 12:59:57 +0100 Vincent Penquerc'h + + * gst/gstcaps.c: + gstcaps: remove unneeded use of gint64 + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-10-27 12:24:13 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + * gst/gstvalue.c: + gstvalue: quicker version of intersection when we do not need the result + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-10-27 12:02:43 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + gststructure: simplify return statement in gst_structure_can_intersect + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-10-27 11:41:30 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + gststructure: early out when we know a value cannot be a subset + If two values can be ordered, but are unequal, they are + necessarily distinct, thus one cannot be a subset of the other. + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-10-27 10:35:53 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + * gst/gstvalue.c: + gstvalue: quicker test for substraction emptiness + When we do not care about the actual resulting set, + but only whether it is empty of not, we can skip a fair bit + of GValue juggling. + Add a function that does so, since we cannot just pass NULL + to the existing API as it may be part of the API contract. + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-10-27 09:45:41 +0100 Vincent Penquerc'h + + * gst/gststructure.c: + gststructure: rejig test ordering for speed + https://bugzilla.gnome.org/show_bug.cgi?id=662777 + +2011-11-07 12:28:22 +0100 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + docs: mention more api changes in the porting guide + +2011-11-07 10:40:23 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: fix compilation + +2011-11-07 10:01:27 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasetransform.c + +2011-11-06 00:07:10 +0000 Tim-Philipp Müller + + * gst/gstcontroller.c: + Revert "controller: fix g_return statement" + This reverts commit 593d2b297bd7b5ce9dbcdf2f1ae2b7624d94d6ae. + gst_controller_set_disabled () returns a void. + +2011-11-05 12:10:29 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + docs: remove refs to removed API + +2011-11-04 21:37:45 +0100 Stefan Sauer + + * gst/gstcontroller.c: + * gst/gstobject.c: + controller: the object needs a ref to the controller for the convenience api + Add a hack to ensure the object will have a ref to the controller once we + create it. Fixes the audio example (that uses the controller api directly). + +2011-11-04 21:37:21 +0100 Stefan Sauer + + * gst/gstcontroller.c: + controller: fix g_return statement + +2011-11-04 21:35:55 +0100 Stefan Sauer + + * gst/gstcontroller.c: + controller: logging tweaks + Don't log in _new before we have the log category. Use _OBJECT variants. + +2011-11-05 01:27:54 +0000 Tim-Philipp Müller + + * gst/gstcontroller.c: + * gst/gstobject.c: + gst: fix some compiler warnings + gstobject.c: In function 'gst_object_has_active_automation': + gstobject.c:1076:3: error: 'return' with no value, in function returning non-void + gstcontroller.c: In function 'gst_controller_is_active': + gstcontroller.c:509:3: error: 'return' with no value, in function returning non-void + +2011-11-04 20:50:58 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + * gst/gstcontroller.c: + * gst/gstcontroller.h: + * gst/gstobject.c: + * gst/gstobject.h: + controller: add api to check for active controllers (needed for e.g. volume) + +2011-11-04 20:32:32 +0100 Stefan Sauer + + * gst/gstobject.h: + controller: remove obsolete comments from api transition + +2011-11-04 14:00:24 +0100 Stefan Sauer + + * tests/check/libs/controller.c: + * tests/check/libs/gstlibscpp.cc: + controller: fix tests after move and API changes + +2011-11-04 11:42:34 +0100 Stefan Sauer + + * tests/benchmarks/controller.c: + * tests/examples/controller/audio-example.c: + * tools/gst-inspect.c: + controller: port to new controller api + +2011-11-04 11:39:25 +0100 Stefan Sauer + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + controller: update docs for controller move + +2011-11-04 11:34:11 +0100 Stefan Sauer + + * gst/Makefile.am: + * gst/gst.h: + * gst/gstclock.h: + * gst/gstcontroller.c: + * gst/gstcontroller.h: + * gst/gstcontrolsource.c: + * gst/gstcontrolsource.h: + * gst/gstobject.c: + * gst/gstobject.h: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/lib.c: + controller: move to core/gstobject + Move the controller to gstobject as a simple delegate. The controller and + controlsource are not classes in core. The controlsources stay separate as a lib + for now. This way we can avoid the qdata lookups. + Also remove controller_init(). There is no more need to link to controller for + elements. + Also sanitize the API. We now have functions to add properties like we had + methods to remove that. That avoids then ref count hacks we had in _new. + +2011-11-03 18:23:13 +0100 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + docs: small clarification + +2011-11-03 18:22:16 +0100 Stefan Sauer + + * docs/gst/gstreamer-sections.txt: + docs: missing rename iface->interface in the docs + +2011-11-04 19:17:06 +0100 Wim Taymans + + * gst/gstbin.c: + bin: fix the iterator copy + +2011-11-04 19:11:19 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstbin.c + +2011-11-03 15:36:59 +0000 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + basetransform: Only use the cached transform on strictly equal caps + https://bugzilla.gnome.org/show_bug.cgi?id=663333 + +2011-11-03 15:35:32 +0000 Sjoerd Simons + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: Add gst_caps_is_strictly_equal + +2011-11-04 18:47:10 +0100 Wim Taymans + + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + tests: fix tests + Since blocks are not on both directions, we need to check in the block callback + if we are not blocking on an upstream event and let it pass. + +2011-11-04 18:19:14 +0100 Wim Taymans + + * docs/design/part-probes.txt: + * gst/gstpad.c: + pad: make probes work on all pads + fixes #644907 + +2011-10-15 22:52:25 +0300 Peteris Krisjanis + + * gst/gstclock.h: + introspection: add Value annotations for GST_SECOND, GST_MSECOND, GST_USECOND, GST_NSECOND constants + gobject-introspection won't parse them properly otherwise. + Still need to force the right type though (either GstClockTime or + guint64), but Type: xyz has no effect for me here, so someone with + a newer g-i needs to test this. + Some other defines are also missing, e.g. GST_CLOCK_TIME_NONE. + +2011-11-04 00:03:05 +0000 Tim-Philipp Müller + + * configure.ac: + configure: suppress unused variable warnings if gst debugging is disabled + https://bugzilla.gnome.org/show_bug.cgi?id=662952 + +2011-11-04 00:02:07 +0000 Tim-Philipp Müller + + * configure.ac: + configure: fix typo around GLIB_EXTRA_CFLAGS in GST_ALL_CXXFLAGS + +2011-11-03 23:08:52 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: use statically allocated GQueue + +2011-11-03 22:58:50 +0000 Tim-Philipp Müller + + * gst/gstbin.c: + bin: use statically allocated GQueue + Because we can. + +2011-11-03 22:51:57 +0000 Tim-Philipp Müller + + * libs/gst/base/gstcollectpads2.h: + collectpads2: use flags enum instead of guint in structure + +2011-11-03 08:47:20 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: use statically allocated GQueue + +2011-11-03 17:49:45 +0100 Wim Taymans + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * tests/check/elements/funnel.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstutils.c: + * tests/check/pipelines/parse-launch.c: + fix request pad + Make all request pads take _%u in the template. + Fix up unit tests. + +2011-11-03 16:49:48 +0100 Wim Taymans + + * win32/common/libgstnet.def: + def: update defs + +2011-11-03 16:46:35 +0100 Wim Taymans + + * common: + * libs/gst/net/Makefile.am: + * libs/gst/net/gstnetaddressmeta.c: + * libs/gst/net/gstnetaddressmeta.h: + net: add net address metadata + +2011-11-03 14:26:12 +0100 Wim Taymans + + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnettimeprovider.h: + nettime: clean up header + +2011-11-03 14:14:54 +0100 Wim Taymans + + * gst/gsttask.c: + task: don't use lock/unlock_full + +2011-11-03 11:30:52 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstghostpad.c + +2011-11-02 12:37:15 +0100 Wim Taymans + + * gst/gstpad.c: + pad: small cleanup + +2011-10-25 17:26:50 -0400 Nicolas Dufresne + + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + ghostpad: Don't cache internal proxy pad target + The internal proxy pad target is simply a cache of the internal proxy pad + peer. This patch uses the well implement GstPad peer handling to obtain the + target. This fixes issues with target not being set in both direction when + two ghostpads are linked together (empty bin). + https://bugzilla.gnome.org/show_bug.cgi?id=658517 + +2011-11-02 12:06:47 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbaseparse.c: + * tests/check/gst/gstutils.c: + * win32/common/libgstreamer.def: + utils: remove _found_tags_ API + remove gst_element_found_tags() and gst_element_found_tags_for_pad(), they are + nothing more than a wrapper around gst_pad_push_event() + +2011-11-02 10:29:04 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + common + configure.ac + +2011-10-30 21:33:11 +0100 Wim Taymans + + * gst/gstbuffer.h: + buffer: improve docs + +2011-10-29 09:43:04 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + event: make GstSegment argument const + +2011-10-29 09:41:08 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: remove metatiming from docs + +2011-10-29 09:26:49 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstpad.c: + * gst/gsttask.c: + * gst/gsttask.h: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gsttask.c: + * win32/common/libgstreamer.def: + task: api cleanup + gst_task_create() -> gst_task_new() + +2011-10-29 09:02:00 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbufferpool.c: + * gst/gstcaps.c: + * gst/gstelement.c: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gsttaglist.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gststructure.c: + * tests/check/pipelines/simple-launch-lines.c: + * win32/common/libgstreamer.def: + structure: cleanup API + gst_structure_empty_new() -> gst_structure_new_empty() + gst_structure_id_empty_new() -> gst_structure_new_id_empty() + gst_structure_id_new() -> gst_structure_new_id() + +2011-10-29 08:38:51 +0200 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: remove timing metadata + This is now on buffers by default + +2011-10-29 08:24:12 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstpad.c: + * libs/gst/base/gstbasesink.c: + * plugins/elements/gstmultiqueue.c: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: clean up API + gst_buffer_list_len() -> gst_buffer_list_length() + gst_buffer_list_sized_new() -> gst_buffer_list_new_sized() + +2011-11-01 14:17:21 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + adapter: simplify gst_adapter_take_list() + Use a stack-allocated GQueue to assemble our GList. + +2011-11-01 10:56:39 +0000 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + docs: mention GstActivateMode rename in porting doc + +2011-11-01 00:25:02 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * win32/common/gstenumtypes.c: + * win32/common/libgstreamer.def: + pad: rename GstActivateMode to GstPadActivateMode + These might be useful: + sed -i -e 's/GstActivateMode/GstPadActivateMode/g' `git grep GstActivateMode | sed -e 's/:.*//' | sort -u` + sed -i -e 's/GST_ACTIVATE_/GST_PAD_ACTIVATE_/g' `git grep GST_ACTIVATE_ | sed -e 's/:.*//' | sort -u` + +2011-11-01 00:13:35 +0000 Tim-Philipp Müller + + * docs/design/part-probes.txt: + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gst.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/elements/selector.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpipeline.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/basesrc.c: + * tests/check/pipelines/queue-error.c: + * win32/common/gstenumtypes.c: + * win32/common/libgstreamer.def: + pad: rename GstProbeType and GstProbeReturn to GstPadProbe{Type,Return} + Better now than later in the cycle. These might come in handy: + sed -i -e 's/GstProbeReturn/GstPadProbeReturn/g' `git grep GstProbeReturn | sed -e 's/:.*//' | sort -u` + sed -i -e 's/GST_PROBE_/GST_PAD_PROBE_/g' `git grep GST_PROBE_ | sed -e 's/:.*//' | sort -u` + sed -i -e 's/GstProbeType/GstPadProbeType/g' `git grep GstProbeType | sed -e 's/:.*//' | sort -u` + +2011-10-31 23:32:17 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * win32/common/libgstreamer.def: + taglist: remove gst_tag_list_get_*long*() + No one uses this or should ever need to use it, since + the size is architecture-specific anyway. If normal + integers don't do, one should use 64-bit integers. + +2011-10-31 19:04:20 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + Update .def file for removed/changed API + +2011-10-31 19:23:41 +0100 René Stadler + + * libs/gst/base/gstbasetransform.c: + basetransform: fix crash/warning in find_transform when pad is unlinked + Looks like the revert conflict in commit a44271 was resolved incorrectly. + +2011-10-31 17:45:44 +0000 Tim-Philipp Müller + + * common: + * configure.ac: + configure: make GLIB_EXTRA_CFLAGS overwritable + Make 'make GLIB_EXTRA_CFLAGS=...' work. + +2011-10-31 14:16:05 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstfilter.c: + * gst/gstfilter.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + filter: remove gst_filter_run() and deprecated filter func + If someone wants to resurrect this, please use a less + generic name space for it. + +2011-10-31 14:03:15 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstpluginfeature.c + +2011-10-30 10:26:11 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * libs/gst/base/gstbaseparse.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/gst/gstutils.c: + taglist: rename _new() to _new_empty() and new_full*() to new*() + +2011-10-30 21:54:36 +0000 Tim-Philipp Müller + + * gst/gstfilter.c: + * gst/gstfilter.h: + filter: deprecate gst_filter_run() + It's not really used outside of core at all, and has + serious namespace issues. If anyone feels the need to + revive this one, please use a less generic name space. + API: deprecate gst_filter_run() + API: deprecate GstFilterFunc + +2011-10-30 21:39:36 +0000 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: don't use soon-to-be-deprecated gst_filter_run() + Lines-of-code savings are negligible anyway. + +2011-10-30 21:21:59 +0000 Tim-Philipp Müller + + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * tests/check/gst/struct_x86_64.h: + pluginfeature: deprecate gst_plugin_feature_type_name_filter() + It's only used internally anyway and the helper struct + has namespace issues. + API: deprecated gst_plugin_feature_type_name_filter() + API: deprecated GstTypeNameData + +2011-10-30 10:05:23 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: make opaque + Hide the fact that it's just a GstStructure from the API. We + may want to change this in future (e.g. to add refcounting). + Also, it caused problems for bindings (though that's mostly + the way we typedefed it to GstStructure). + +2011-10-30 10:00:28 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-10-30 09:58:16 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + * win32/common/libgstreamer.def: + taglist: add to_string and new_from_string functions + We want to make GstTagList opaque and not have people use + GstStructure API on it. + API: gst_tag_list_to_string() + API: gst_tag_list_new_from_string() + +2011-10-30 09:31:39 +0000 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into 0.11 + +2011-10-30 01:46:22 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: avoid pointless tag name -> quark lookups + We never get a tag name quark from a caller, it's always a + string, from which we'll try to look up our tag info in the + hash table, so change the hash table key from quark to string. + Avoids a bunch of pointless string => quark lookup in the + global quark table. We need to do an extra string => quark + conversion now when we copy a taglist, but in that case we're + in a slow path anyway. + +2011-10-30 00:44:44 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + * win32/common/libgstreamer.def: + taglist: add gst_tag_list_is_equal() + API: gst_tag_list_is_equal() + +2011-10-29 23:52:22 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + structure: identical structures are definitely equal + +2011-10-29 20:06:54 +0100 Tim-Philipp Müller + + * gst/gsttaglist.h: + taglist: fix string for GST_TAG_ARTIST_SORTNAME + For historical reasons it was mapped to a musicbrainz prefix, + but it's not really musicbrainz-specific at all. + +2011-10-29 19:59:05 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstelementfactory.h: + elementfactory: move private functions for registry to private header + +2011-10-28 21:40:47 +0200 René Stadler + + * libs/gst/base/gstbasetransform.c: + basetransform: fix invalid access to unreffed allocation query + +2011-10-28 16:45:23 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: fix docs some more + +2011-10-28 16:27:43 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasetransform.c + +2011-10-28 16:08:37 +0200 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: fix segment check + +2011-10-28 15:52:58 +0200 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + segment: remove GST_SEEK_TYPE_CUR + +2011-10-28 15:52:41 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: improve docs + +2011-10-28 15:16:43 +0200 Wim Taymans + + * plugins/elements/gstdataurisrc.c: + make elements compile again + +2011-10-28 13:02:26 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter.h: + bytewriter: Add padding + +2011-10-28 13:02:19 +0200 Sebastian Dröge + + * libs/gst/base/gstbitreader.h: + bitreader: Add padding + +2011-10-28 13:02:10 +0200 Sebastian Dröge + + * libs/gst/base/gstbytereader.h: + bytereader: Add padding + +2011-10-28 12:31:03 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update + +2011-10-28 12:28:46 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + docs: update + +2011-10-28 12:27:43 +0200 Wim Taymans + + * win32/common/libgstbase.def: + defs: update for new api + +2011-10-28 12:17:58 +0200 Wim Taymans + + * libs/gst/check/gstconsistencychecker.c: + check: also debug the DTS + +2011-10-28 12:16:21 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: use pts/dts on buffers + +2011-10-28 12:24:02 +0200 Wim Taymans + + * gst/gstcompat.h: + compat: add timestamp compat defines + +2011-10-28 12:15:44 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstinfo.c: + buffer: add pts/dts to buffers + +2011-10-28 11:53:32 +0200 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + basetransform: Also fush the cache when changing the upstream caps suggestion + +2011-10-28 11:50:23 +0200 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + basetransform: Add debug output when returning a cached transform + +2011-10-28 11:33:44 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-10-28 11:30:57 +0200 Wim Taymans + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + coolectpads2: port to 0.11 + +2011-10-28 11:13:55 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-10-28 10:54:19 +0200 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + collectpads2: Fix refcount handling if a buffer was dropped due to clipping + +2011-10-28 10:37:21 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + * win32/common/libgstbase.def: + collectpads2: Merge the clip and prepare_buffer function into one + +2011-10-28 10:17:06 +0200 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + collectpads2: Merge clipping API from old collectpads + +2011-10-28 09:19:29 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: make default query function name show up in gst-inspect + +2011-09-27 15:48:52 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads2.c: + collectpads2: avoid hanging in case of sparse newsegment events + ... in the extent that a non-waiting pad (so indicated by newsegment) + turns out to provide the best buffer, which is then forced to waiting + for book-keeping purposes, but that should only be temporary. + See bug #415754. + +2011-10-28 09:38:35 +0200 Sebastian Dröge + + * libs/gst/base/gstcollectpads2.c: + collectpads2: Use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-10-28 09:35:50 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + collectpads2: Add to the documentation + +2011-10-28 09:26:11 +0200 Sebastian Dröge + + * win32/common/libgstbase.def: + win32: Add new collectpads2 API + +2011-10-28 09:18:55 +0200 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstcollectpads2.c: + * libs/gst/base/gstcollectpads2.h: + base: Add collectpads2 + This handles muxing of sparse/subtitle streams and has + lots of cleanup. Still missing is special support for + live streams but this can be added later without breaking + API/ABI. + Based on the version from the videomixer plugin. + https://bugzilla.gnome.org/show_bug.cgi?id=415754 + +2011-10-27 17:09:51 +0200 Wim Taymans + + * tests/check/elements/funnel.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstelementfactory.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/transform1.c: + * tests/check/pipelines/queue-error.c: + tests: fix compilation + +2011-10-27 17:09:34 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update + +2011-10-27 17:09:04 +0200 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: add empty_simple variants + +2011-10-27 16:51:16 +0200 Wim Taymans + + * tests/check/gst/gstiterator.c: + * tests/check/gst/gststructure.c: + * tests/check/pipelines/simple-launch-lines.c: + tests: fix compilation + +2011-10-27 14:56:24 +0100 Johan Boulé + + * gst/gstcaps.h: + caps: use G_GNUC_NULL_TERMINATED for gst_caps_new_simple() and gst_caps_new_full() + If you get warnings, use gst_caps_new_empty(). + https://bugzilla.gnome.org/show_bug.cgi?id=343346 + +2011-10-27 15:27:19 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasetransform.c + +2011-10-27 13:25:08 +0100 Tim-Philipp Müller + + * gst/gststructure.h: + structure: use G_GNUC_NULL_TERMINATED for gst_structure_new() + If you get a warning, use gst_structure_empty_new(). + https://bugzilla.gnome.org/show_bug.cgi?id=343346 + +2011-10-27 23:08:14 +1100 Jan Schmidt + + * libs/gst/base/gstbasetransform.c: + basetransform: Fix refcount leak + Don't leak peercaps and a ref to the basetransform when returning + the cached caps. + +2011-10-27 10:38:10 +0200 Stefan Sauer + + * libs/gst/controller/gstcontroller.c: + controller: fix wrong order of calls in the docs. + +2011-10-26 12:23:07 +0200 Stefan Sauer + + * gst/gstevent.c: + event: clarify docs for step event + +2011-10-18 23:19:47 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: add support for GST_REGISTRY_REUSE_PLUGIN_SCANNER=no + This will make sure we spawn a new plugin scanner helper for each plugin + to be introspected, which helps with making sure we don't load too many + shared objects (libs, plugins) at the same time on systems where there + is a hard limit like on Android. + A better version might re-use the scanner for up to N times, though + it's not clear whether that would actually improve things dramatically. + https://bugzilla.gnome.org/show_bug.cgi?id=662091 + +2011-10-21 10:23:04 -0300 Thiago Santos + + * gst/gstcaps.c: + caps: No need to require writable caps for _append/_merge second caps + The second caps ownership is transfered, no need to require it to + be writable from the caller function. Instead, _append and _merge + make it writable on their own. + Discovered because of an assertion on encoding-profile.c in + _get_input_caps using _merge but not passing writable caps. + +2011-10-21 14:20:40 +0200 Stefan Sauer + + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + interfaces: clean up the use of iface and class/klass + +2011-10-21 11:15:11 +0200 Stefan Sauer + + * docs/random/porting-to-0.11.txt: + * docs/random/status-0.11-14-jun-2011.txt: + * gst/gstquery.c: + docs: spelling and formatting fixes + +2011-10-21 10:52:46 +0200 Edward Hervey + + Merging origin/master + Conflicts: + gst/gstbin.c + gst/gstbus.c + gst/gstdebugutils.c + gst/gstpad.c + libs/gst/base/gstbaseparse.c + libs/gst/base/gstbasesrc.c + +2011-10-20 16:59:01 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: Fix documentation, it's pre_push_frame and not pre_push_buffer + +2011-10-20 14:02:44 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasetransform.c: + basetransform: cache transformed caps where appropriate + Speeds up negotiation a fair bit on a contrived pipeline + with a dozen colorspace conversions. + Hopefully clears out the cache every time it ought to. + https://bugzilla.gnome.org/show_bug.cgi?id=662291 + +2011-10-20 10:45:30 -0300 Reynaldo H. Verdejo Pinochet + + * Android.mk: + Fix broken android building due to name change in 01d87250a845e55d6 + +2011-10-20 08:31:18 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + basebarse: Add detect vfunc to allow subclasses to do format detection before anything else + API: GstBaseParseClass::detect() + This is called with the first buffers until the subclass has finished detection + and only afterwards the original buffers are handled as before. The vfunc allows + detection of the stream format without breaking the upstream framing. + +2011-10-20 08:57:57 +0200 Stefan Sauer + + * gst/gstpad.c: + pad: not only describe conditions in the docs, also check them in the code + When blocking pads, check if the pad is in the rigt direction. Log some info + for the developer and return FALSE, instead of just locking up. + +2011-10-19 23:07:46 +0200 René Stadler + + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * tests/check/generic/states.c: + * tests/check/gst/gstregistry.c: + Revert gst_plugin_feature_get_name to const string return + Returning a newly allocated string makes no sense. It's unexpected for a + getter, and also this behaves differently in 0.10, so it would make future + merges harder. + Except for these two places here in core which were updated for the new + semantic, the return value is getting leaked all over the place. + +2011-10-19 12:12:36 +0200 Edward Hervey + + * gst/gstobject.c: + gstobject: Add (skip) annotation to gst_object_ref_sink + +2011-10-19 11:59:29 +0200 Edward Hervey + + * gst/gstiterator.c: + gstiterator: Add skip annotation for creating GstIterator + Not really useful for bindings + +2011-08-29 13:56:19 -0300 Johan Dahlin + + * gst/gstpoll.c: + introspection: Skip gst_poll apis + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:55:13 -0300 Johan Dahlin + + * gst/gstvalue.c: + introspection: Skip GType and GValue transform apis + These do not make sense to expose to language bindings + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:54:21 -0300 Johan Dahlin + + * gst/gst.c: + introspection: Skip gst_init_get_option_group + It uses GOptionGroup which is not wrappable + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:53:39 -0300 Johan Dahlin + + * gst/gstbufferpool.c: + * gst/gstparamspecs.c: + introspection: Add missing annotations + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:52:26 -0300 Johan Dahlin + + * gst/gstbus.c: + introspection: Rename gst_bus_add_watch_full to gst_bus_add_watch + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:50:40 -0300 Johan Dahlin + + * gst/gstindex.h: + Sync documentation arguments + The introspection scanner warns if the header and the source + uses mismatching parameter names. + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-08-29 13:50:02 -0300 Johan Dahlin + + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + Add gst_structure_get_type + https://bugzilla.gnome.org/show_bug.cgi?id=657640 + +2011-10-18 19:21:58 -0300 Thiago Santos + + * gst/gstmessage.c: + message: protect against null message sources + Message sources can be null, check if it is before trying to + access its name. + +2011-10-18 08:48:37 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.h: + baseparse: add since doc to new getcaps function + +2011-10-18 14:08:19 +0200 Stefan Sauer + + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstmessage.c: + * libs/gst/base/gstbasesink.c: + logging: more logging and prefer human readable details over memory locations + +2011-10-18 14:05:37 +0200 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: improve display of ghost- and proxypads + Handle virtual links between ghost and proxypads when iterating pads instead of + when linking. Besides using less code this provides a more accurate picture. + +2011-10-18 13:54:52 +0200 Edward Hervey + + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: Add g-i annotations and remove "Since:" markers + +2011-10-17 14:42:08 -0300 Thiago Santos + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: add getcaps function + Adds a getcaps function to the sink pad to make parsers propagate + downstream caps restrictions to upstream. + The pipeline "audiotestsrc num-buffers=100 ! faac ! aacparse ! + "audio/mpeg, version=(int)4, stream-format=(string)adts" ! filesink" + wouldn't work because aacparse wouldn't propagate the adts restriction + upstream to faac. + This patch adds a default getcaps to the sink pad to simply proxy + downstream caps and also adds a 'get_sink_caps' function pointer + to GstBaseParseClass for subclasses that need more refined getcaps. + https://bugzilla.gnome.org/show_bug.cgi?id=661874 + +2011-10-18 12:39:03 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: also update the stream time + +2011-10-18 10:58:14 +0200 Sebastian Dröge + + * libs/gst/base/gstbaseparse.c: + baseparse: Fix handling of queued frames + gst_base_parse_push_frame() already frees the frame, no need to + do it another time again. + +2011-10-17 21:38:56 +0200 René Stadler + + * tests/check/elements/selector.c: + tests: fix padtemplate leak in selector test + In 0.11, gst_pad_get_pad_template returns a reference. + +2011-10-17 21:37:17 +0200 René Stadler + + * gst/gstpad.c: + pad: fix buffer/event leak when pad is flushing + Apparently this got lost while refactoring probes. + +2011-10-17 17:00:04 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: remove the memory from the tmpbuf + We use a tmpbuf to hold a temporary pointer to the adapter memory. We need to + remove that memory when we no longer need it. + +2011-10-17 13:55:35 +0200 René Stadler + + * gst/gstcaps.c: + caps: fix race condition and memory leak in gst_static_caps_get + This was leaking the PtrArray from caps->priv, as set up by the other call to + gst_caps_init. Also, the thread safety issue presented in the comment above was + not taken care of anymore. We now zero the refcount again when publishing the + structure. + Fixes #661629. + +2011-10-17 09:28:43 +0200 Edward Hervey + + * libs/gst/check/gstcheck.h: + gstcheck: Make ASSERT_MINI_OBJECT_REFCOUNT more useful + knowing which miniobject failed helps us locate it in debug logs + +2011-10-17 09:28:24 +0200 Edward Hervey + + * libs/gst/check/gstcheck.c: + gstcheck: Make _check_buffer_data a bit more verbose + +2011-10-17 09:27:49 +0200 Edward Hervey + + * tests/check/gst/gstregistry.c: + check: Don't leak the feature name + +2011-10-17 09:27:26 +0200 Edward Hervey + + * gst/gstregistry.c: + gstregistry: Don't leak feature name + +2011-10-16 21:12:07 +0100 Tim-Philipp Müller + + * gst/gstbus.c: + bus: give watch source a name + Give our GSource a meaningful name. Source names can be + used for debugging and profiling, for example with + systemtap or gdb. + +2011-10-14 09:35:09 +0200 Edward Hervey + + * gst/gstutils.c: + gstbuffer: Add transfer annotations for gst_buffer_join() + +2011-10-16 17:42:22 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-16 17:03:27 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-16 17:00:09 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update porting list + +2011-10-16 14:45:03 +0200 Wim Taymans + + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstregistry.c: + * gst/gstsystemclock.c: + * gst/gsttypefindfactory.c: + fix more parent_class + +2011-10-16 14:20:33 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstevent.h + +2011-10-16 14:17:25 +0200 Wim Taymans + + * gst/gstpadtemplate.c: + padtemplate: clean up parent_class + +2011-10-14 12:57:38 +0200 Wim Taymans + + * gst/gstpad.c: + pad: clean up parent_class handling + +2011-10-14 09:35:09 +0200 Edward Hervey + + * gst/gstutils.c: + gstbuffer: Add transfer annotations for gst_buffer_join() + +2011-10-14 09:27:38 +0200 Edward Hervey + + * tools/gst-inspect.c: + gst-inspect: Don't leak plugin feature list + +2011-10-13 17:33:06 +0200 Stefan Sauer + + * gst/gstbus.c: + bus: fix typo in the docs + +2011-10-13 16:48:02 +0200 Stefan Sauer + + * gst/gstdebugutils.c: + debugutils: show if an element is state-locked + +2011-10-13 16:42:10 +0200 Stefan Sauer + + * gst/gstbin.c: + logging: use _OBJECT variants more + +2011-10-13 12:23:59 +0200 René Stadler + + * libs/gst/base/gstbasesrc.c: + basesrc: fix caps leak + +2011-10-13 10:19:34 +0200 Sebastian Dröge + + * gst/gstbuffer.h: + buffer: Use an inline function instead of a macro for gst_buffer_replace() + This gives us type checks by the compiler and more useful compiler errors. + +2011-10-13 10:18:51 +0200 Sebastian Dröge + + * gst/gstevent.h: + event: Use an inline function instead of a macro for gst_event_replace() + This gives us type checks by the compiler and more useful compiler errors. + +2011-10-13 08:51:42 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstutils.c + libs/gst/base/gstbasesrc.c + +2011-10-12 18:14:00 -0300 Thiago Santos + + * gst/gstghostpad.c: + ghostpad: Do not unref the internal pad twice + g_value_unset should already unref the internal proxypad, no + need to do it again + +2011-10-12 17:17:09 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: properly adjust start time + When we do a non-flushing seek and closed the current segment, + make sure that we open the next segment from where we closed. + +2011-10-12 14:37:31 +0200 René Stadler + + * gst/gstevent.c: + event: add transfer type for gst_event_new_caps argument + These annotations are useful to humans as well... + +2011-10-12 14:34:24 +0200 René Stadler + + * plugins/elements/gstcapsfilter.c: + capsfilter: fix caps leak + gst_event_new_caps does not steal a reference to the caps. + +2011-10-12 13:31:48 +0200 René Stadler + + * gst/gstevent.c: + event: fix gst_event_new_segment transfer type + +2011-10-11 13:54:45 +0200 Edward Hervey + + * tests/check/generic/states.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstutils.c: + * tests/check/gst/gstvalue.c: + tests: Fix more leaks + +2011-10-11 13:53:39 +0200 Edward Hervey + + * plugins/elements/gstcapsfilter.c: + capsfilter: Don't leak caps + +2011-10-11 13:51:54 +0200 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: Fix a caps leak and move a codeblock + The result from the block of code that was moved would only have + been used if 'peercaps' was present. + +2011-10-11 13:51:37 +0200 Edward Hervey + + * gst/gstpadtemplate.c: + * gst/gstvalue.c: + gst: More 'transfer' annotations + +2011-10-10 19:41:33 +0100 Tim-Philipp Müller + + * gst/gstutils.c: + utils: catch invalid instance sizes in gst_type_register_static_full() + Add guards to catch overly large instance sizes. + https://bugzilla.gnome.org/show_bug.cgi?id=660955 + +2011-10-10 19:30:34 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: remove gst_type_register_static_full() + It was only really used by GST_BOILERPLATE, and that is no more. + https://bugzilla.gnome.org/show_bug.cgi?id=660955 + +2011-10-10 11:47:42 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: avoid trying to alloc enormous buffer + If a class extending basesrc doesn't set blocksize, basesrc + would try to allocate a (guint)-1 sized buffer, which is enormous + and likely would fail. + Avoid it and error out. + +2011-10-10 17:17:37 +0200 Edward Hervey + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 17:04:39 +0200 Edward Hervey + + * gst/gstghostpad.c: + ghostpad: If we don't control a pad/template, return proper caps + If there's a filter, we can return that in _get_caps() + +2011-10-10 16:52:43 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Specify transfer full for gst_pad_get_caps() + It increments the reference count of the returned caps. + +2011-10-10 11:02:08 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Add debug to know what events are transferred between pads + +2011-10-10 10:38:12 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Unset EOS event on FLUSH_STOP + +2011-10-07 11:49:19 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Don't ignore downstream FlowReturn with IDLE probes + If pushgin downstream returned a non-ok value (like GST_FLOW_WRONG_STATE), + we don't want to end up returning a different value (GST_FLOW_OK in this + case) if IDLE probes are present. + +2011-10-10 13:23:09 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 12:54:54 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 12:38:35 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 12:27:52 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 11:49:46 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-10 11:36:23 +0200 Wim Taymans + + * gst/gstcompat.h: + compat: add compat define for UNEXPECTED + +2011-10-10 11:33:51 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + * gst/gstbufferpool.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstcollectpads.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/filesrc.c: + * tests/check/gst/gstpad.c: + pad: GST_FLOW_UNEXPECTED -> GST_FLOW_EOS + +2011-10-10 11:30:21 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-09 11:49:45 -0300 Thiago Santos + + * tests/check/elements/tee.c: + tests: tee: Remember to initialize variables to NULL + app_thread needs to be initialized to NULL, otherwise tests + will try to use it and crash + +2011-10-08 20:56:59 +0100 Tim-Philipp Müller + + * common: + Update common for check-exports script changes + +2011-10-08 20:46:22 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + * gst/gstelementfactory.c: + * win32/common/libgstreamer.def: + elementfactory: don't export private _gst_elementclass_factory quark + +2011-10-08 20:15:46 +0100 Tim-Philipp Müller + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + info: make _gst_debug_init() private for now + This was a FIXME for 0.11. I guess a case could be made to keep it around + separately for apps or libraries that only want to use GStreamer's debugging + system, but it seems more likely they'd just copy the two source files into + their own tree if the case. Also, things like types wouldn't be initialised + without gst_init(). We can still make it public again if anyone needs it, + but then we should make it a proper function and not hide it behind + underscores. + +2011-10-08 19:54:06 +0100 Tim-Philipp Müller + + Merge remote-tracking branch 'origin/master' into symbol-exports + +2011-10-08 14:17:25 +0100 Tim-Philipp Müller + + * gst/gstparse.c: + * gst/parse/.gitignore: + * gst/parse/Makefile.am: + * gst/parse/grammar.y: + * gst/parse/types.h: + gstparse: prefix generated parser functions so they don't get exported + Don't export those 35-something random _gst_parse_yy* symbols. These were + never in any header files and also blacklisted from our .def files, in + case anyone wonders. + +2011-10-08 13:37:09 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstobject.c: + * win32/common/libgstreamer.def: + info: rename __gst_debug_* to _gst_debug_* and fix symbol export regexp + Only export GStreamer symbols with one leading underscore, not two + or more leading underscores. + Requires a rebuild of the entire stack, sorry. + +2011-10-08 15:16:59 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update doc + +2011-10-08 14:25:02 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-10-08 14:23:30 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update + +2011-10-08 12:08:49 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: upate porting list + +2011-10-08 09:41:54 +0200 Wim Taymans + + * gst/gstinfo.c: + info: port to 0.11 + +2011-10-08 09:28:02 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstpad.c + +2011-10-07 09:45:20 -0300 Thiago Santos + + * gst/gstpipeline.c: + pipeline: Use pipeline category for one more log message + Makes debugging easier. + +2011-10-07 16:36:10 +0200 Robert Swain + + * gst/gstinfo.c: + * gst/gstpad.c: + GST_PTR_FORMAT: Add GstBuffer ptr format and use in GST_SCHEDULING + GstBuffer pointers can now be printed using GST_PTR_FORMAT. This is used + in the very useful GST_SCHEDULING debug logs in gstpad.c and allows for + easier and more information tracking of buffer progress through a + pipeline with just debug logging. + +2011-10-07 13:55:18 +0100 Tim-Philipp Müller + + * tests/check/generic/sinks.c: + tests: fix compiler warnings in sinks test + +2011-10-07 13:54:51 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * plugins/elements/Makefile.am: + * plugins/elements/gstdataqueue.c: + * plugins/elements/gstdataqueue.h: + * plugins/elements/gstmultiqueue.h: + * tests/check/libs/gstlibscpp.cc: + * tests/check/libs/libsabi.c: + * win32/common/libgstbase.def: + base: make GstDataQueue private API for multiqueue + There's no code that uses it other than multiqueue, so make it private + to multiqueue for now. That way we can also do optimisations that + require API/ABI breaks. If anyone ever wants to use it, we can still + make it public again. + +2011-10-06 17:27:47 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-10-06 17:26:02 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update list + +2011-10-06 14:34:09 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: send duration message when updating internal duration + +2011-10-06 14:04:05 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update list + +2011-10-06 10:59:09 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + update porting list + +2011-10-05 20:06:51 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update list + +2011-10-05 13:43:46 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + porting: update porting status + +2011-10-05 11:20:37 +0200 Edward Hervey + + * gst/gstbufferpool.c: + gstbufferpool: Use glib compat macros for atomic pointers + +2011-10-04 18:55:20 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + update porting list + +2011-10-04 18:55:09 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: improve docs + +2011-10-04 18:38:50 +0200 Wim Taymans + + * plugins/elements/gstdataurisrc.c: + dataurisrc: port to 0.11 + +2011-10-04 17:39:17 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-10-04 17:36:26 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + update porting list + +2011-10-04 15:55:05 +0200 Edward Hervey + + * gst/gstevent.c: + gstevent: specify (transfer) for gst_event_new_segment + +2011-10-04 13:16:14 +0200 Wim Taymans + + * docs/random/wtay/porting-list-0.11.txt: + add porting list + +2011-09-26 14:36:46 +0400 Stas Sergeev + + * libs/gst/base/gstbaseparse.c: + baseparse: Return success if optional start/stop method is not provided + This allows to not implement the optional start/stop methods. + +2011-10-03 10:06:17 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbaseparse.c + +2011-10-03 09:29:10 +0200 Edward Hervey + + * gst/gstquery.c: + gstquery: Make debugging message more informative + For all the newcomers out there who still don't know the values of + GstQueryType enum by heart... + ... and old-timers who've got better things to do :) + +2011-09-30 15:25:20 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: make estimating the position in query handler actually work + No point estimating if we don't set the result afterwards. + +2011-09-26 13:14:42 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbaseparse.c: + baseparse: answer position query in stream time and try upstream first + Let the demuxer have first say as well. + https://bugzilla.gnome.org/show_bug.cgi?id=659485 + +2011-09-30 14:52:01 +0100 Tim-Philipp Müller + + * gst/gst.h: + gst.h: include header for atomic queue + +2011-09-30 14:50:51 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstatomicqueue.c: + tests: add minimal test for GstAtomicQueue + Just new + free. + +2011-09-29 18:06:25 +0200 Wim Taymans + + * docs/random/release: + update release notes + Change the mail addresses to the freedesktop ones + +2011-09-29 17:04:57 +0200 Wim Taymans + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + back to development + +=== release 0.11.1 === + +2011-09-29 16:50:21 +0200 Wim Taymans + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + RELEASE 0.11.1 + +2011-09-28 18:46:09 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: fix memory alignment + Fix compilation when POSIX_MEMALIGN is not set. + Debug the configured alignment. + Fixes https://bugzilla.gnome.org/show_bug.cgi?id=660300 + +2011-09-28 18:44:12 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve debug + +2011-09-28 11:28:25 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + transform: fix after merge + +2011-09-28 11:24:42 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-09-28 11:16:33 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + docs: fix some more docs + +2011-09-26 19:52:13 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasetransform.c: + basetransform: send delayed events earlier + Some elements (such as videorate) might push buffers early, + for instance in in transform_ip. We want events (and in particular + any NEWSEGMENT event) to be pushed before that. + This fixes transmageddon wedging on converting a file starting + with a non zero offset to Ogg. + https://bugzilla.gnome.org/show_bug.cgi?id=660165 + +2011-09-26 20:47:35 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferpool.h: + * gst/gstcaps.h: + * gst/gstevent.h: + * gst/gstiterator.h: + * gst/gstmemory.c: + * gst/gstmessage.h: + * gst/gstmeta.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstpad.h: + * gst/gstquery.c: + docs: fix docs + +2011-09-26 19:25:22 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-09-26 19:24:19 +0200 Wim Taymans + + * gst/gstsegment.h: + segment: improve API docs a little + +2011-09-26 00:30:47 +0300 Raimo Järvi + + * gst/gstregistry.c: + * gst/gststructure.c: + gst: Fix compiler warnings on 64 bit mingw-w64 + Fixes bug #660083. + +2011-09-25 16:10:53 +0100 Tim-Philipp Müller + + * tests/examples/helloworld/helloworld.c: + examples: fix bogus g_object_unref in helloworld example + GMainLoop is not a GObject. + https://bugzilla.gnome.org/show_bug.cgi?id=424143 + +2011-09-23 13:09:25 +0200 Edward Hervey + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstcaps.c + gst/gstpad.c + libs/gst/base/gstbasesink.c + libs/gst/base/gstbasesink.h + libs/gst/base/gstbasetransform.c + +2011-09-21 13:43:48 +0200 Edward Hervey + + * common: + Update common to 0.11 branch + +2011-09-20 13:04:06 +0100 Vincent Penquerc'h + + * libs/gst/base/gstbasetransform.c: + basetransform: delay serialized events when src caps are not set yet + https://bugzilla.gnome.org/show_bug.cgi?id=659571 + +2011-09-13 17:04:31 +0400 Stas Sergeev + + * gst/gstpad.c: + pad: Set caps on pad before checking if the pad is linked + This allows the setcaps handler and notify::caps to link + the pad downstream and doesn't require hacks to always + provide a peer to the pad, like in decodebin2. + +2011-09-15 11:49:43 -0700 Fabrizio (Misto) Milo + + * gst/gstcaps.c: + caps: use g_value_take_string() and gst_value_get_caps() instead of accessing internal fields + +2011-09-16 13:38:41 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pad: add more debug logging for other chain function code path as well + +2011-09-16 13:13:30 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pad: fix up printf format in debug message + Which I messed up. + +2011-09-15 13:20:15 +0100 Vincent Penquerc'h + + * gst/gstpad.c: + pad: make some debug traces more useful + https://bugzilla.gnome.org/show_bug.cgi?id=659139 + +2011-09-14 22:54:18 +0100 Tim-Philipp Müller + + * scripts/gstcvstest.sh: + scripts: remove gstcvstest.sh + +2011-09-13 23:04:09 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: fix clang compiler warning + Cast enum to int before checking for negative values, which are + impossible according to the enum list. + gstlfocontrolsource.c:652:45: error: comparison of unsigned enum expression < 0 + is always false [-Werror,-Wtautological-compare] + if (waveform >= num_waveforms || waveform < 0) { + ~~~~~~~~ ^ ~ + https://bugzilla.gnome.org/show_bug.cgi?id=653137 + +2011-09-13 21:58:21 +0100 Tim-Philipp Müller + + * tests/check/elements/filesrc.c: + tests: make sure filesrc returns escaped URIs even if the input was unescaped + https://bugzilla.gnome.org/show_bug.cgi?id=654673 + +2011-09-10 18:15:49 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: move log messages for caps creation/freeing into TRACE category + Reduce SPAM for GST_CAPS:5. + +2011-09-09 12:56:20 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Only do the subset check in gst_pad_accept_caps() if the pad claims to accept the caps + +2011-09-07 17:21:55 -0400 Nicolas Dufresne + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * plugins/elements/gstfilesink.c: + basesink: make it easy to override the pad query + Add a vmethod to handle the pad query. + Install a default handler for the pad query. + Use the new query function in filesink + +2011-09-08 14:39:30 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + Revert "Revert "basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible"" + This reverts commit 0bc6d49c950210bf422615fb8dc98c5adcd5e456. + Conflicts: + libs/gst/base/gstbasetransform.c + +2011-09-08 14:31:52 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "Revert "pad: Check for subsets, not non-empty intersections to check if caps are compatible"" + This reverts commit 2bfada5581e35a2d37188f48a2c7442644f10bb3. + Conflicts: + gst/gstpad.c + For 0.11 we want to enforce that only subsets of the pad + caps are allowed. This breaks backward compatibility for + some elements, which is why we only print a warning in + 0.10. + +2011-09-08 14:30:07 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstpad.c + +2011-09-08 14:29:00 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "pad: Use gst_pad_accept_caps() instead of manually checking when configuring a sinkpad" + This reverts commit d3cad28da936b037d877dc70c02286b81b680284. + It causes performance problems because acceptcaps() propagates downstream. + +2011-09-08 14:23:50 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + docs/design/draft-buffer2.txt + docs/design/part-TODO.txt + docs/design/part-block.txt + docs/design/part-bufferlist.txt + docs/design/part-caps.txt + docs/design/part-element-transform.txt + docs/design/part-events.txt + docs/design/part-negotiation.txt + gst/gstcaps.c + gst/gstevent.h + gst/gstghostpad.c + gst/gstinterface.c + gst/gstpad.c + gst/gstpad.h + gst/gstutils.c + libs/gst/base/gstbasesink.c + libs/gst/base/gstbasesrc.c + libs/gst/base/gstbasetransform.c + libs/gst/base/gsttypefindhelper.c + plugins/elements/gstcapsfilter.c + plugins/elements/gsttee.c + tests/check/generic/sinks.c + tools/gst-launch.1.in + +2011-09-08 13:41:19 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Use gst_pad_accept_caps() instead of manually checking when configuring a sinkpad + +2011-09-08 13:40:06 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Print a g_warning() if pad accept caps that are not a subset of its caps + In 0.11 only subsets are supported again as documented instead of also + allowing non-empty intersections. + +2011-09-08 13:26:24 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + Revert "basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible" + This reverts commit 5e5cc5e89e7e2858a6352fa4c81a374f6e5a6297. + See bug #658541. + +2011-09-08 13:26:01 +0200 Sebastian Dröge + + * gst/gstpad.c: + Revert "pad: Check for subsets, not non-empty intersections to check if caps are compatible" + This reverts commit 0c5d50207326d74a4805bcd898bfac887540f12b. + See bug #658541. + +2011-09-07 13:14:38 +0200 Piotr Fusik + + * README: + * docs/README: + * docs/design/draft-buffer2.txt: + * docs/design/draft-klass.txt: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-TODO.txt: + * docs/design/part-activation.txt: + * docs/design/part-block.txt: + * docs/design/part-buffering.txt: + * docs/design/part-bufferlist.txt: + * docs/design/part-caps.txt: + * docs/design/part-clocks.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-framestep.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstghostpad.txt: + * docs/design/part-latency.txt: + * docs/design/part-messages.txt: + * docs/design/part-missing-plugins.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-qos.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-seeking.txt: + * docs/design/part-states.txt: + * docs/design/part-stream-status.txt: + * docs/faq/Makefile.am: + * docs/faq/dependencies.xml: + * docs/faq/general.xml: + * docs/manual/Makefile.am: + * docs/manual/advanced-clocks.xml: + * docs/manual/advanced-dparams.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-init.xml: + * docs/manual/basics-pads.xml: + * docs/manual/diagrams-general.svg: + * docs/manual/highlevel-components.xml: + * docs/manual/intro-gstreamer.xml: + * docs/pwg/Makefile.am: + * docs/pwg/advanced-tagging.xml: + * docs/pwg/intro-basics.xml: + * docs/pwg/intro-preface.xml: + * docs/pwg/other-base.xml: + * docs/pwg/other-source.xml: + * docs/random/autoplug2: + * docs/random/bbb/optional-properties: + * docs/random/bbb/streamselection: + * docs/random/caps: + * docs/random/company/gvadec.txt: + * docs/random/ensonic/draft-bufferpools.txt: + * docs/random/ensonic/embedded.txt: + * docs/random/ensonic/media-device-daemon.txt: + * docs/random/ensonic/plugindocs.txt: + * docs/random/ensonic/profiling.txt: + * docs/random/eos: + * docs/random/hierarchy: + * docs/random/i18n: + * docs/random/interfaces: + * docs/random/negotiation: + * docs/random/omega/sched/chains: + * docs/random/omega/testing/framework: + * docs/random/plugins: + * docs/random/rtp: + * docs/random/slomo/controller.txt: + * docs/random/sources: + * docs/random/streamheader: + * docs/random/testing/syntax: + * docs/random/types2: + * docs/random/uraeus/gstreamer_and_midi.txt: + * docs/random/vis-transform: + * docs/random/wtay/caps-negociation: + * docs/random/wtay/threading: + * docs/random/wtay/threads_hilevel: + * gst/gstbin.c: + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gstelement.c: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstghostpad.c: + * gst/gstinterface.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstparamspecs.h: + * gst/gstparse.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstpoll.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gsthelper.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * tests/benchmarks/capsnego.c: + * tests/check/elements/filesink.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstelementfactory.c: + * tests/check/gst/gstevent.c: + * tools/gst-launch.1.in: + * win32/README.txt: + docs, gst: typo fixes + https://bugzilla.gnome.org/show_bug.cgi?id=658449 + +2011-09-07 15:07:20 +0100 Tim-Philipp Müller + + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + docs: fix make distcheck + No point removin those empty override files from git, they'll + just be re-created later, so let's tell gtk-doc about them, so + it can clean them up properly. + +2011-09-07 16:02:31 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: If there's no peer we still have to transform ANY caps in getcaps() + Otherwise elements like capsfilter will return ANY caps if no + peer is present instead of the filter caps. The transform_caps() + vfunc could do transformations to the template caps that do not + result in the unmodified template caps. + +2011-09-07 14:05:03 +0200 Stefan Sauer + + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + docs: cleanup makefiles + Remove commented out parts that we don't need. Remove "the wingo addition" - no + so useful after all. Narrow down file-globs for plugin docs. + +2011-09-07 13:50:08 +0200 Stefan Sauer + + * gst/gstelement.c: + docs: escape % in docblob + +2011-09-02 19:46:06 +0400 Stas Sergeev + + * gst/gstghostpad.c: + ghostpad: Use gst_pad_set_caps() instead of manually changing caps + gst_pad_set_caps() does essentially the same but additionally calls + the pad's setcaps function. + Fixes bug #658076. + +2011-09-06 21:24:10 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From a39eb83 to 11f0cd5 + +2011-09-06 15:39:52 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 605cd9a to a39eb83 + +2011-09-06 12:17:05 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible + +2011-09-06 12:19:58 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Check for subsets, not non-empty intersections to check if caps are compatible + Pads should only accept caps that are a subset of the pad caps, e.g. + they should accept only caps that have a non-empty intersection and + at least all fields of the pad caps. + Without this a pad that wants for example + "video/x-h264,stream-format=byte-stream" + will be happy to accept + "video/x-h264". + +2011-08-29 17:06:18 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + * win32/common/libgstreamer.def: + miniobject: change to GST_DEFINE_MINI_OBJECT_TYPE + Append _TYPE to the macro for consistency with other similar macros. + +2011-08-29 15:34:30 +0200 Wim Taymans + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmessage.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + * win32/common/libgstreamer.def: + init: add _get_type() functions + Remove gst_mini_object_register() and add a GST_DEFINE_MINI_OBJECT macro to + define a _get_type() function for the boxed miniobject. + Remove a bunch of custom _get_type() functions and replace them with the + miniobject macro. + Rename some _init method to _priv_*_initialize() like the rest of them. + Inspired by patch from Johan Dahlin and see bug #657603 + +2011-08-29 13:27:26 +0200 Wim Taymans + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstformat.c: + * gst/gstmessage.c: + * gst/gstplugin.c: + * gst/gstquery.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gstvalue.c: + * win32/common/libgstreamer.def: + gst: add some _priv prefixes to private methods + +2011-08-29 12:38:54 +0200 Wim Taymans + + * gst/gstminiobject.c: + mini-object: use ref/unref directly in boxed copy/free + GLib will not call our copy/free with a NULL object + +2011-08-26 14:37:54 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstmessage.c + gst/gstquery.c + gst/gstregistrychunks.c + gst/gstsegment.c + libs/gst/base/gstbasetransform.c + libs/gst/base/gstbasetransform.h + libs/gst/base/gsttypefindhelper.c + plugins/elements/gsttypefindelement.c + +2011-08-26 14:18:33 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + base: rename allocation vmethods + Name the allocation vmethod on srcpad decide_allocation because source pads will + have to decide what allocation parameters will be used. + Name the allocation vmethod on sinkpads propose_allocation because they will + need to configure the allocation query with a proposed values for upstream. + +2011-08-26 14:17:23 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: improve flags + Rename DROP to DECODE_ONLY. + Add DROPPABLE flag to mark buffers that can be dropped to save bandwidth without + destroying the stream. + +2011-08-26 14:09:47 +0200 Josep Torra + + * gst/gsttrace.h: + * gst/gsttypefind.h: + docs: add since 0.10.36 on the new _NONE enum values + +2011-08-26 00:13:16 +0200 Josep Torra + + * tests/examples/stepping/framestep1.c: + stepping: use the proper argument order + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-26 00:06:12 +0200 Josep Torra + + * plugins/indexers/gstfileindex.c: + fileindex: explicitly cast to the enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-26 00:00:25 +0200 Josep Torra + + * plugins/elements/gsttypefindelement.c: + typefinder: use GST_TYPE_FIND_NONE instead of 0 + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 23:53:58 +0200 Josep Torra + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 23:49:38 +0200 Josep Torra + + * gst/gsttypefind.h: + * libs/gst/base/gsttypefindhelper.c: + typefind: add GST_TYPE_FIND_NONE and use it + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 23:26:08 +0200 Josep Torra + + * libs/gst/base/gstbaseparse.c: + baseparse: use the enum values for 0 and don't abuse on gboolean coincidence + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 23:06:56 +0200 Josep Torra + + * libs/gst/base/gstbaseparse.c: + baseparse: put the arguments of g_return_val_if_fail in the proper order + +2011-08-25 22:48:54 +0200 Josep Torra + + * gst/gstparse.c: + parse: use GST_PARSE_FLAG_NONE instead of 0 + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 22:42:08 +0200 Josep Torra + + * gst/gstvalue.c: + value: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 22:29:45 +0200 Josep Torra + + * gst/gstutils.c: + utils: minor changes related to enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 22:05:26 +0200 Josep Torra + + * gst/gsttrace.c: + * gst/gsttrace.h: + trace: add GST_ALLOC_TRACE_NONE for consistency and use it + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:52:05 +0200 Josep Torra + + * gst/gsttask.c: + task: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:49:29 +0200 Josep Torra + + * gst/gstsystemclock.c: + * gst/gsttagsetter.c: + tagsetter: use GST_TAG_MERGE_UNDEFINED instead of FALSE + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:30:57 +0200 Josep Torra + + * gst/gstsegment.c: + segment: use GST_SEEK_FLAG_NONE instead of 0 + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:25:46 +0200 Josep Torra + + * gst/gstregistrychunks.c: + registrychunks: explicitly cast to the enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:18:15 +0200 Josep Torra + + * gst/gstquery.c: + query: minor changes related to enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-25 21:03:53 +0200 Josep Torra + + * gst/gstpadtemplate.c: + padtemplate: explicitly cast to the enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-16 23:00:47 +0200 Josep Torra + + * gst/gstpad.c: + * gst/gstpad.h: + pad: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-16 22:51:29 +0200 Josep Torra + + * gst/gstmessage.c: + message: explicitly cast to the right enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-16 22:41:32 +0200 Josep Torra + + * gst/gstinfo.c: + info: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-16 22:37:08 +0200 Josep Torra + + * gst/gstindex.c: + index: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-16 22:29:59 +0200 Josep Torra + + * gst/gstformat.c: + format: use GST_FORMAT_UNDEFINED and few casts to GstFormat + Fixes warning #188: enumerated type mixed with another type reported by ICC. + +2011-08-26 13:02:34 +0100 Sjoerd Simons + + * libs/gst/base/gstbasetransform.h: + basetransform: Fix bodged previous commit + +2011-08-26 12:37:43 +0100 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: Use GstPadDirection in the query vfunc + Wim suggested that using GstPadDirection instead of a GstPad in the + arguments to the new query vfunc would be more consistent with the other + functions. + +2011-08-26 13:40:44 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: rename _CLIP to _DROP flag + We can also use a flag to indicate that a frame should be decoded but not + displayed regardless of the the segment boundaries so we use the more generic + _DROP. + +2011-08-26 12:28:28 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: remove some unused variables + +2011-08-26 11:44:12 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: add vmethod to configure upstream bufferpool + Add a vmethod that can be implemented to influence the bufferpool that upstream + elements will use. + +2011-08-26 11:24:42 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: use pad direction like other vmethods + +2011-08-26 11:09:07 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasetransform.c + libs/gst/base/gstbasetransform.h + +2011-08-26 10:57:37 +0200 Wim Taymans + + * gst/gsturi.h: + uri: some doc fixes + +2011-08-25 11:02:16 +0100 Sjoerd Simons + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + BaseTransform: Add a query vfunc + +2011-07-20 14:05:27 +0200 Sjoerd Simons + + * plugins/elements/gstcapsfilter.c: + capsfilter: don't assume _get_caps still has to be + _set_caps only gets called when the buffer is actually pushed, so there + is a reasonably big window between when the initial caps are retrieved + and when the caps are set on our src pad. So we can't assume the not + having negotiated caps on our src pad means _get_caps still has to be + called. + Instead simply always suggest the new caps on buffer_alloc. + +2011-08-25 18:04:28 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: add clip flag + +2011-08-25 16:21:18 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: rework flags a little + Reorder buffer flags and add some new ones. + Remove the media specific flags, we can now easily do this with the FLAG_LAST + flag because we don't extend from GstBuffer anymore. + +2011-08-25 16:20:21 +0200 Wim Taymans + + * gst/gstbuffer.c: + * libs/gst/base/gstbasetransform.c: + buffer: always copy all buffer flags when asked + Don't try to be smart and copy only a subset of buffer flag + +2011-08-25 16:19:52 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + update defs + +2011-08-25 14:09:37 +0200 Wim Taymans + + * gst/gst.c: + * gst/gstbuffer.h: + buffer: pluralize the buffer flags + +2011-08-25 12:38:58 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * tests/check/generic/sinks.c: + * tests/check/pipelines/stress.c: + basesink: remove preroll-queue-len property + Remove the preroll-queue-len property and move its variables to a private + section so that we can remove them later. + +2011-08-24 10:43:09 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstobject.c + +2011-08-23 18:19:53 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: ensure start_time reset upon flush + +2011-08-23 11:55:17 +0200 Stefan Kost + + * gst/gstobject.c: + gstobject: also remove the cast as this is causing the trouble + +2011-08-23 11:41:02 +0200 Stefan Kost + + * gst/gstobject.c: + gstobject: use the atomic macros to deal with the glib change in the impl. + +2011-08-22 12:49:04 +0200 Wim Taymans + + * gst/gstobject.c: + * gst/gstobject.h: + object: make _replace like the miniobject version + +2011-08-22 12:33:35 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstbuffer.h + gst/gstcaps.c + gst/gstcaps.h + gst/gstevent.c + +2011-08-22 12:19:19 +0200 Wim Taymans + + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + * tests/check/gst/capslist.h: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstvalue.c: + * tests/check/pipelines/parse-launch.c: + * win32/common/libgstreamer.def: + value: remove our FOURCC GType + Remove our custom fourcc GValue. + +2011-08-21 14:07:08 -0700 David Schleef + + * gst/gstobject.c: + object: make gst_object_replace() atomic + +2011-08-20 14:07:55 +0200 Stefan Kost + + * gst/gstelement.c: + docs: more clarification for element docs + Don't suggest deprecated method in the desction docs and try to be more helpful + in other places by suggesting related functions. + +2011-08-20 09:56:01 +0200 Stefan Kost + + * gst/gstelement.c: + docs: small clarification in the gst_element_get_request_pad docs + Make it more obvious that one should pass the template name. + +2011-08-18 20:46:01 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: don't use == in debug string + It messes up GST_DEBUG=*:5 make foo/bar.valgrind, because + our Makefile looks for '==' as marker of valgrind output. + +2011-08-18 20:44:01 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix crash on seek from streaming thread on newsegment event + Event if it's not allowed, we can easily prevent it, so let's do + that. + https://bugzilla.gnome.org/show_bug.cgi?id=656771 + +2011-08-17 17:56:40 +0200 Wim Taymans + + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: add method to fixate one field + +2011-08-17 17:16:21 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: add default fixate function + Add a default fixate function which does gst_caps_fixate() because + gst_pad_fixate() does not do that anymore. + +2011-08-17 09:25:04 +0200 Wim Taymans + + * gst/gstpad.c: + * libs/gst/base/gstbasetransform.h: + docs: improve some docs + +2011-08-16 18:29:29 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: return processed number of bytes + Make _fill, _extract and _memset return the actual number of bytes that were + handled in case the buffer size is less than the specified size. + +2011-08-16 17:19:29 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.c: + docs: fix typo in element factory documentation + +2011-08-16 17:32:20 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/dataprotocol/dataprotocol.c: + buffer: rename PREROLL -> LIVE flag + Rename the GST_BUFFER_FLAG_PREROLL to GST_BUFFER_FLAG_LIVE and give the new flag + a meaning. The old PREROLL flag never had a clear meaning. + +2011-08-15 21:05:34 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: fix compiler warning reported by ICC + The MAX macro expands to code that checks if an unsigned integer is < 0. + Fixes warning #186: pointless comparison of unsigned integer reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-10 11:39:23 +0200 Josep Torra + + * gst/gstbuffer.h: + buffer: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-10 11:07:49 +0200 Josep Torra + + * gst/gstelement.h: + gststate: explicitly cast to the enum type + Fixes warning #188: enumerated type mixed with another type reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-09 23:42:26 +0200 Josep Torra + + * gst/gstevent.c: + event: explicitly cast to the right enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-09 23:33:43 +0200 Josep Torra + + * gst/gsterror.c: + gsterror: explicitly cast to the right GstGError code enum types + Fixes warning #188: enumerated type mixed with another type reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-09 23:26:13 +0200 Josep Torra + + * gst/gstdebugutils.c: + debugutils: use GST_STATE_VOID_PENDING for GstState instead of 0 + Fixes a warning reported by ICC. + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-09 22:48:53 +0200 Josep Torra + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: define GST_CAPS_FLAGS_NONE for consistency with other enumerations + Use them to fix warnings when building with ICC. + API: GST_CAPS_FLAGS_NONE + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-09 22:29:44 +0200 Josep Torra + + * gst/gst.c: + gst: use GstDebugLevel enum type to fix a warning building with ICC + https://bugzilla.gnome.org/show_bug.cgi?id=656265 + +2011-08-15 16:45:33 +0200 Wim Taymans + + * gst/gstpad.c: + pad: make fixate caps behave like other functions + Install a default fixate caps function on pads like all the other pad functions. + +2011-08-15 16:45:05 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update for new symbols + +2011-08-15 14:43:14 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-08-15 14:40:38 +0200 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstpad.c: + * gst/gststructure.c: + caps: add fixate function + Add a fixate function and use it in gstpad.c + +2011-08-15 14:32:17 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gststructure.c: + * gst/gststructure.h: + structure: add function to fixate + Add a function to fixate a structure and use it for the default fixate function + in gstpad.c. + +2011-08-15 13:17:44 +0200 Guillaume Desmottes + + * scripts/gst-uninstalled: + gst-uninstalled: add Farsight and Nice support + https://bugzilla.gnome.org/show_bug.cgi?id=656557 + +2011-08-15 14:17:39 +0200 Wim Taymans + + * gst/gstpad.c: + pad: fix default acceptcaps + Make the acceptcaps function behave like all the other functions with a default + implementation. Don't try to chain up to the default implementation when it was + set to NULL explicitly but return FALSE instead. + Fix some docs + +2011-08-15 13:24:11 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: fix some macros + Remove a rather usless macro to check if a pad mode is active and + add GST_PAD_IS_ACTIVE(). + +2011-08-15 12:18:59 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting doc + +2011-08-15 12:16:30 +0200 Wim Taymans + + * gst/gstdebugutils.c: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: remove gst_pad_get_negotiated_caps() + Remove gst_pad_get_negotiated_caps(), it does not realy do what it says, + gst_pad_get_current_caps() returns the currently negotiated caps on the pad + correctly. + +2011-08-12 19:27:21 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix deadlock in error path + Don't lock the same lock twice. Spotted by Josep Torre Valles. + +2011-08-12 12:45:01 +0300 Peteris Krisjanis + + * gst/gstiterator.c: + iterator: Fix gst_iterator_next() element annotation + +2011-08-11 09:31:25 +0100 Tim-Philipp Müller + + * docs/pwg/advanced-types.xml: + docs: fix typo in PWG + RBG -> RGB. Spotted by Will Thompson. + https://bugzilla.gnome.org/show_bug.cgi?id=656326 + +2011-08-11 10:09:41 +0200 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: removed non-sense comment + +2011-08-10 17:07:54 +0200 Edward Hervey + + Merge remote-tracking branch 'origin/master' into 0.11 + Conflicts: + gst/gstdebugutils.c + gst/gstelementdetails.h + gst/gstregistrychunks.c + tools/gst-run.c + +2011-08-08 19:36:04 +0200 Stefan Kost + + * gst/gstelementdetails.h: + * gst/gstregistrychunks.c: + registry: move utf-8 validation to registry saving time + Instead of checking for valid utf-8 element-details every time we create + elements (from plugin-init or registry), do it before we save the registry. + Fixes #656193. + +2011-08-10 11:01:58 +0200 Josep Torra + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmeta.c: + * gst/gstpad.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + Fix and clarify debug statements + Fixes build on MacOSX + Signed-off-by: Edward Hervey + +2011-08-05 10:59:42 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: Clarify doc + +2011-08-07 09:14:50 +0100 Tim-Philipp Müller + + * docs/manual/basics-helloworld.xml: + docs: fix helloworld compile command line for newer gcc + https://bugzilla.gnome.org/show_bug.cgi?id=656092 + +2011-08-06 18:20:51 +0200 Shaun Hoopes + + * gst/gstdebugutils.c: + debugutils: improve dot file flow layout + Iterate source- and sink-pads separately to ensure that the graph reflects the + upstream/downstream order. Fixes #643269 + +2011-08-06 14:17:50 +0200 Thomas Vander Stichele + + * gstreamer.spec.in: + gstreamer.spec: make buildable and parallel + +2011-08-05 12:12:33 +0100 Tim-Philipp Müller + + * tools/gst-run.c: + tools: make unversioned wrapper look for -0.10 tools only + Don't want (incompatible) 0.11 tools to be picked up by accident. + +2011-08-04 18:00:02 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: add alloc vmethod + Make an alloc vmethod so that subclasses can override or call the default + implementation when they want. + +2011-08-04 17:26:34 +0200 Wim Taymans + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + defs: update defs + +2011-08-04 17:12:47 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: cleanups and mark reconfigure + Don't abuse the result variable. + Mark the srcpad with a reconfigure so that negotiation happens. + +2011-08-04 17:12:21 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add method to mark reconfigure + +2011-08-04 16:56:42 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: remove negotiation from the state change + Remove the negotiation from the state change function, it causes data transfer + and bufferpool negotiation, which is not supposed to be done. Since we have the + reconfigure state on the pad, the create function will do the negotiation as + soon as it gets in the streaming thread. + +2011-08-04 16:34:49 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: expose set_caps method + Expose a previously static method so that custom negotiate implementation can + call it and do the right thing. + +2011-08-04 13:48:11 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: PAUSED<->PLAY doesn't change pool state + Don't change the state of the bufferpool when going between PAUSED and PLAYING, + it will dealloc and realloc all buffers, which is clearly too invasive. We will + need to add some other way of unblocking the bufferpool. + +2011-08-04 11:00:57 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstmemory.c: + fix default alignment + A 0 alignment is the default. + +2011-08-04 10:54:29 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * win32/common/libgstreamer.def: + bufferpool: add gst_buffer_pool_is_active() + +2011-08-03 11:57:50 +0200 Wim Taymans + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + back to development + +=== release 0.11.0 === + +2011-08-02 20:55:28 +0200 Wim Taymans + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gstreamer.doap: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + RELEASE 0.11 + +2011-08-03 11:04:12 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + porting-to-0.11: Add section about GstIterator + +2011-08-01 18:12:12 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: don't add the same option twice + Make sure that we only add an option to the array once. + +2011-07-30 14:04:43 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * win32/common/libgstreamer.def: + bufferpool: add method to check for an option + Add a method to check if an option is supported on the bufferpool. + +2011-07-29 17:10:09 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + bufferpool: add options API to bufferpool + Make it possible to query the supported options of a bufferpool and enable + options. This is a bit more generic than the API to enable metadata. The purpose + is to make it possible to add new custom config options to the configuration of + the bufferpool when supported. + +2011-07-28 12:11:36 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + * gst/gstelement.h: + element: don't use G_CONST_RETURN + It's been deprecated in newer GLib versions + +2011-07-28 12:01:58 +0100 Tim-Philipp Müller + + * docs/manual/advanced-position.xml: + manual: update for position/duration query API change + +2011-07-27 00:28:50 +0100 Tim-Philipp Müller + + * tests/check/elements/fakesink.c: + * tests/check/elements/filesink.c: + * tests/check/generic/sinks.c: + * tests/examples/stepping/framestep1.c: + tests: update for query API changes + +2011-07-27 00:28:19 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + plugins: update for query API changes + +2011-07-27 00:26:43 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base: update for query API changes + +2011-07-27 00:17:02 +0100 Tim-Philipp Müller + + * docs/random/porting-to-0.11.txt: + * gst/gstquery.c: + * gst/gstutils.c: + * gst/gstutils.h: + gst: fix awkward dest_format inout parameter in query utility functions + The idea was originally that if one passed &dest_fmt with + dest_fmt=GST_FORMAT_DEFAULT, then the code answering the query + could change dest_fmt to the actual default format used. However, + in more than half a decade of GStreamer 0.10 no piece of code in + GStreamer has ever used that feature, nor are there that many + users of this API that actually check whether the format returned + is the original format passed before using the values returned. + Also, it's just annoying-to-use API in its own right. + For all these reasons, make it so that the destination format is + passed directly and can't be changed by the element queried. + +2011-07-27 12:50:39 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-07-27 12:49:40 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: add more comments + +2011-07-27 12:45:17 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: also pass allocation query in in_place + When we are doing an in_place transform, don't do the allocation query but let + the upstream element decide. + +2011-07-26 22:41:59 -0700 Evan Nemerson + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + base: add missing (out) annotation for byte reader/writer functions + https://bugzilla.gnome.org/show_bug.cgi?id=655381 + +2011-07-27 10:09:11 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.c: + elementfactory: fix g-i annotation for _create() and _make() to allow NULL object names + +2011-07-26 18:48:20 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve the getcaps function + Refactor calling the GETCAPS function and checks. + Move the filter code in one place. + When using fixed pad caps, get the currently configured caps and then fallback + to the GETCAPS function. We used to simply ignore the GETCAPS function, which + resulted in transform elements returning the template caps instead of doing the + caps transform. + +2011-07-26 15:43:55 +0200 Wim Taymans + + * gst/gstpad.c: + pad: only update caps when changed + Only call the event function with the caps event when the caps changed. + +2011-07-26 14:37:51 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: add some more debug info + +2011-07-26 12:21:38 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * plugins/elements/gstfilesink.c: + basesink: make it easy to override the pad query + Add a vmethod to handle the pad query. + Install a default handler for the pad query. + Add a vmethod to setup the allocation properties. + Use the new query function in filesink + +2011-07-26 12:20:55 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.h: + basesrc: improve docs + +2011-07-26 12:20:04 +0200 Wim Taymans + + * gst/gstpad.c: + pad: add allocation query just because + +2011-07-25 15:21:21 +0200 Wim Taymans + + * gst/gstpoll.c: + poll: improve debugging + +2011-07-25 12:53:10 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + miniobject: avoid race in bufferpool release + Avoid playing with the refcount to decide when a buffer has been recycled by the + dispose function. The problem is that we then temporarily can have a buffer with + a refcount > 1 being acquired from the pool, which is not writable. Instead use + a simple boolean return value from the dispose function to inform the called + that the object was recycled or not. + +2011-07-25 12:49:24 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: use DEBUG instead of ERROR for logging + Don't use the ERROR log category because the allocation failure migh only be + bacause of a state change. + +2011-07-25 12:14:16 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: start with raised control socket + In the inactive state, the control socket should be in the raised state, we will + release it when we start. + +2011-07-24 11:24:44 +0200 Stefan Kost + + * docs/pwg/advanced-clock.xml: + * docs/pwg/building-chainfn.xml: + pwd: discontinous event -> newsegment event + Fix a 0.8 leftover as mentioned on bug #621121. + +2011-07-24 09:05:22 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + talk about the basetransform sink_event vmethod + +2011-07-23 08:00:09 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstcontrollerprivate.h: + controller: fix build failure due to compiler warning + Presumably with newer GLib version. + https://bugzilla.gnome.org/show_bug.cgi?id=655155 + +2011-07-22 21:17:42 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * plugins/elements/gstidentity.c: + basetransform: fix sink event handling + Implement the sink event handling like the src event handler. Make the default + implementation parse and forward the event. This makes it possible to actually + return an error value from the event handler. + +2011-07-22 19:19:59 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: handle failures + Handle failure to activate the bufferpool. + +2011-07-22 19:11:56 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: improve debugging. + +2011-07-21 18:50:25 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: add reset_buffer vmethod + Add a vmethod to reset a buffer to its original state. Add a default + implementation that resets the flags, timestamps and offsets. + Add some more docs. + +2011-07-21 17:42:08 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstidentity.c: + basetrans: Remove ref in passthrough + Remove the requirement to have to return a ref to the input buffer when in + passthrough mode. This saves a few ref/unref cycles and fixes another 0.11 + FIXME. + +2011-07-21 17:29:13 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: make new copy_metadata vmethod + Make a new copy_metadata vmethod and move the code to copy the timestamps, flags + and offsets into a default implementation. This will allow us to give the + subclasses a chance to override the copy method. + +2011-07-21 16:49:13 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbaseparse.c + libs/gst/base/gstbasesink.c + +2011-07-21 16:39:04 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: avoid intermediate method + Simply call the prepare_output_buffer method instead of calling an intermediate + function. + +2011-07-21 16:30:07 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: move the metadata copy code + Move the metadata copy code to the default prepare_output_buffer implementation. + +2011-07-21 15:49:00 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: move prepare_output_buffer code + Move the code for prepare_output_buffer to a default implementation. this allows + us to simplify some things and have subclasses call into the default + implementation when needed. + +2011-07-21 15:48:25 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: only get size for debug + +2011-07-21 14:18:30 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetrans: fix comment and warn + Emit a warning in the debug log when something seems weird. + +2011-07-21 14:14:58 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: only get caps for size transform + Delay getting the caps until we need to call the transform_size function. + +2011-07-21 13:56:11 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstidentity.c: + basetrans: remove useless variables from prepare_output_buffer + Remove the caps and size from the prepare_output_buffer function. with + bufferpools and capsnego done differently, we don't need this in most cases and + if we do, we can simply use the transform_size function and get the caps from + the srcpad. + +2011-07-18 17:22:41 +0200 Stefan Kost + + * docs/manual/advanced-clocks.xml: + docs: clarify clocks docs in manual + After a question on the mailing list, mention that *flushing* seeks reset the + running time. + +2011-07-16 22:00:15 +0300 Raluca Elena Podiuc + + * gst/gstevent.c: + * gst/gstmessage.c: + docs: removed double negation in event/message seq num description + https://bugzilla.gnome.org/show_bug.cgi?id=654751 + +2011-07-16 12:21:12 +0100 Tim-Philipp Müller + + * tests/check/elements/filesrc.c: + tests: make sure non-ASCII chars in filenames are escaped when creating URIs from them + https://bugzilla.gnome.org/show_bug.cgi?id=654673 + +2011-07-15 16:04:11 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: don't accidentally disable the pool + When we set a pool and it is the same as the old pool, don't disable the pool. + +2011-07-15 13:27:13 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: call release_buffer after alloc + After we allocated a new buffer, call the release_buffer vmethod to put the new + buffer in the pool instead of assuming that the pool uses the default + release_method implementation. + +2011-07-15 11:52:22 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: add macro to check for flushing + +2011-07-15 11:51:54 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: improve debug message + +2011-07-14 12:45:33 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix printf format in debug message + +2011-07-13 11:39:15 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: unset PLAYING transition flag when transition completed + +2011-07-12 14:07:57 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: fix resize function some more + Don't remove memory blocks from the buffer when we clip and resize, instead set + the memory offset and size to 0. This allows us to make the buffer larger again + later. + +2011-07-12 13:40:35 +0200 Wim Taymans + + * gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + buffer: improve size handling + Also handle the case where multiple empty memory blocks are in the buffer. + Add unit test for this. + +2011-07-12 12:00:58 +0200 Wim Taymans + + * gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + buffer: fix _resize some more + Add more debug. + Alow resize to 0 bytes. + Do clipping correctly. + Add more unit tests. Also add a failing test: when we resize to 0 and then + try to resize back to the original size it fails because the memory was + removed. + +2011-07-11 18:00:52 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstbuffer.c: + buffer: fix negative offsets some more + Allow for negative offsets when doing memory copy and share. + Add fast path in the _get_sizes() function. + Fix resize for negative offset and expanding the buffer. + Add some unit tests. + +2011-07-11 16:43:33 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: add defs for new methods + +2011-07-11 16:42:56 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: fix _resize better + +2011-07-11 16:17:57 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + buffer: add api to get the current memory offset + Also return the offset in a GstMemory block with the get_sizes() method. This + allows us to figure out how much prefix there is unused. + Change the resize function so that a negative offset can be given. This would + make it possible to resize the buffer so that the prefix becomes available. + Add gst_buffer_get_sizes() to return the offset and maxsize as well as the size. + Also change the buffer resize method so that we can specify a negative offset + to remove prefix bytes. + +2011-07-11 14:40:07 +0200 Mark Nauwelaerts + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add some memory wrapped buffer allocation helpers + +2011-07-11 12:11:13 +0200 Wim Taymans + + * gst/gstminiobject.h: + miniobject: cleanup headers + +2011-07-11 11:40:08 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: eat incoming caps event + ... as it is typically up to baseclass to set proper src caps. + +2011-07-11 11:37:28 +0200 Mark Nauwelaerts + + * gst/gstpad.c: + pad: avoid inadvertently dropping an event + ... particularly a non-sticky serialized event that happens to pass + when an event update is pending. + +2011-07-04 12:58:54 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: try harder to arrange increasing position reporting + ... rather than having a momentary decreasing one while transitioning + to PLAYING. + Fixes #628021. + +2011-07-08 16:07:12 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new API to .def file + +2011-07-06 15:13:30 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: make idx argument to gst_buffer_take_memory() signed + Since -1 is acceptable, it should be signed. + +2011-07-07 14:57:18 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix invalid memory access in debug messages + Don't use buffers that we've given away or unrefed in debug messages. + +2011-07-07 11:14:34 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: fix after merge + +2011-07-07 11:13:19 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasesrc.c + +2011-07-06 16:08:56 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add memset function + +2011-07-06 12:09:28 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: fix guards for gst_buffer_take_memory() + Since idx = -1 makes it default to idx=len, len is also + a valid input idx. + +2011-07-05 16:38:06 +0200 Wim Taymans + + * gst/gst.c: + gst: add class ref/unref + +2011-07-05 16:32:45 +0200 Wim Taymans + + * tests/check/libs/transform1.c: + test: disable failing unit tests + Disable unit tests that are failing until someone ports this to 0.11 + +2011-07-05 16:20:03 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + * tests/check/elements/queue.c: + queue: fix unit test + Set the right position member in the segment event. + Add some debug to queue. + +2011-07-05 00:10:26 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/Makefile.am: + * gst/gst.h: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + gst: make compiler warn about unstable API if GST_USE_UNSTABLE_API is not defined + And define it in our own build. + +2011-07-05 00:12:13 +0100 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: update .def files for latest API changes/additions + +2011-06-30 17:39:37 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + basesrc: do not sneakily mess with current offset when updating length + +2011-06-28 22:18:46 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + basesrc: unref allocation query when no longer needed + +2011-06-28 19:01:57 +0200 Mark Nauwelaerts + + * plugins/elements/gstinputselector.c: + inputselector: avoid iterating over a single NULL pad + +2011-06-20 23:28:07 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * docs/random/porting-to-0.11.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstinterface.c: + * gst/gstinterface.h: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstinterface.c: + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + Remove GstImplementsInterface + It was a bit too clever, and didn't really work as an API, + confusing people to no end. Better implement specific methods + whether an interface is usable/available/ready on the interface + itself, or even add GError arguments, rather than try to have + per-instance interfaces. + +2011-06-25 13:51:52 -0700 Emmanuel Pacaud + + * gst/gsttask.c: + task: Check for PR_SET_NAME before using + Fixes: #653172. + Signed-off-by: David Schleef + +2011-06-23 11:27:52 -0700 David Schleef + + * common: + Automatic update of common submodule + From 69b981f to 605cd9a + +2011-06-23 18:03:22 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + query: add method to check for metadata + Add a method to check if a certain metadata is supported in the ALLOCATION + query. + +2011-06-22 18:07:18 +0200 Wim Taymans + + * docs/design/part-meta.txt: + docs: update design docs a little + Update the design doc with the current state of the videometadata. + +2011-06-22 17:12:34 +0200 Koop Mast + + * plugins/elements/gsttee.c: + tee: use & instead of && for masking bits + See #653137 + +2011-06-22 17:09:52 +0200 Koop Mast + + * libs/gst/base/gstbasetransform.c: + basetransform: remove redundant () + See #653137 + +2011-06-22 17:05:27 +0200 Koop Mast + + * libs/gst/base/gstbaseparse.c: + baseparse: fix seekstop + See #653137 + +2011-06-22 16:58:53 +0200 Koop Mast + + * gst/gstsegment.c: + segment: cast to right type + See #653137 + +2011-06-22 16:38:04 +0200 Wim Taymans + + * gst/gstelementfactory.c: + * gst/gsturi.c: + * gst/gsturi.h: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + uri: remove some _full variants + +2011-06-22 16:16:56 +0200 Wim Taymans + + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstutils.c: + * libs/gst/base/gstbasesink.c: + tags: Remove crazy tag messages + Don't mix messages and pads and tags. + Make the sink post tag messages when a tag event is received. + Since tags are sticky on pads now, they can be retrieved from there + when needed. + +2011-06-22 12:28:14 +0200 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstelementfactory.c: + caps: Hide implementation details + Make the Array of structures private. This should allow us to implement + the array more efficiently or with some preallocated structures when + we want to later. + Add a new method to clean up a static structure so that we can remove some code + that pokes into the private bits of the caps. + +2011-06-22 12:26:19 +0200 Wim Taymans + + * docs/design/part-negotiation.txt: + docs: update negotiation design doc + +2011-06-22 11:42:46 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + memory: rename GstMemoryAllocator -> GstAllocator + simplify the name of the allocator object. + +2011-06-21 17:54:38 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + win32/common/config.h + win32/common/gstversion.h + +2011-06-21 17:47:36 +0200 Wim Taymans + + * docs/design/part-bufferpool.txt: + docs: update bufferpool design doc + +2011-06-21 17:47:23 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: improve debugging + +2011-06-21 15:15:44 +0200 Stefan Kost + + * docs/manual/communication.png: + images: strip images of extra text tags + +2011-06-21 12:32:46 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: return empty metadata array + Return a string array with NULL instead of NULL from the default get_metas + function. + +2011-06-21 12:31:57 +0200 Wim Taymans + + * gst/gstpad.c: + pad: use event function directly + We will never go in this code path for CAPS events so directly call the event + function. + +2011-06-21 10:29:51 +0200 Wim Taymans + + * gst/gstpad.c: + pad: notify caps after we store the new caps + notify caps after we store the new caps so that the new caps are actually + visible for the app. + +2011-06-20 17:32:47 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: activate the bufferpool + always activate the bufferpool, even if we get it from the allocation + query. + +2011-06-20 17:32:11 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: always activate the pool we get + Activate the pool when we get it from the allocation query. + +2011-06-20 16:47:40 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: inprove allocation handling + Add vmethod for subclasses to influence the pool and allocator. + Log when query fails. + Respect negotiated allocator and alignment. + +2011-06-20 16:46:05 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: Improve logging + Log when things fail. + Fix a query leak. + +2011-06-20 16:44:35 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: improve debug + Log a debug line when there is no target pad and when this makes the default + implementation fail. + Take the internal pads directly when we can. + +2011-06-20 15:40:51 +0200 Mark Nauwelaerts + + * configure.ac: + configure.ac: bump required GLib to 2.26 + +2011-06-20 13:26:06 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: add function to set metadata api + Add a function to retrieve an array of supported metadata apis from the the + bufferpool. + Add functions to configure and query the configured metadata apis in a + bufferpool configuration. + +2011-06-19 13:15:19 -0300 Thiago Santos + + * gst/gstbuffer.c: + gstbuffer: Minor fix to docs + Adds missing parameter to docs of gst_buffer_copy_region + +2011-06-18 17:35:41 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Remove unused variable do_event_actions + do_event_actions was always used as TRUE + +2011-06-18 14:38:53 +0100 Tim-Philipp Müller + + * configure.ac: + Bump gobject-introspection requirement to >= 0.6.8 + For --add-init-section + +2011-06-16 17:27:21 +0100 Tim-Philipp Müller + + Bump git version after unplanned 0.10.35 release + Merge remote-tracking branch 'origin/0.10.35' + +2011-06-14 17:57:21 +0200 Philip Jägenstedt + + * libs/gst/base/gstbasesink.c: + basesink: Fix typo in documentation + Fixes #652577. + +2011-06-16 10:55:15 +0100 Tim-Philipp Müller + + * gst/gstutils.h: + Revert "utils: remove some macros now in glib" + This reverts commit de29ae7b929cedbf6b9838ea53b05efabdce4ce7. + Re-adds GFLOAT_TO_LE, GFLOAT_TO_BE, GDOUBLE_TO_LE, and GDOUBLE_TO_BE. + Turns out these aren't in GLib yet afer all (since we didn't + actually open a bug to get them added..) + +=== release 0.10.35 === + +2011-06-15 19:15:24 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.35 + This is an ad-hoc release that is almost identical to 0.10.34: + * work around GLib atomic ops API change + * some minor win32/mingw fixes + * don't use G_CONST_RETURN in public headers + +2011-06-15 16:56:30 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: fix refcounting problem + +2011-06-09 17:13:35 +0100 Javier Jardón + + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstformat.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstquery.h: + * gst/gststructure.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * gst/gsttrace.h: + * gst/gsturi.c: + * gst/gsturi.h: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.h: + Use "const" instead G_CONST_RETURN + G_CONST_RETURN will be deprecated soon. + https://bugzilla.gnome.org/show_bug.cgi?id=652211 + +2011-06-04 00:30:15 -0700 David Schleef + + * gst/glib-compat-private.h: + * gst/gstatomicqueue.c: + * gst/gstelementfactory.c: + * gst/gstpoll.c: + * gst/gstsystemclock.c: + * gst/gstutils.c: + * plugins/elements/gstmultiqueue.c: + * tests/benchmarks/gstclockstress.c: + Work around changes in g_atomic API + See #651514 for details. It's apparently impossible to write code + that avoids both type punning warnings with old g_atomic headers and + assertions in the new. Thus, macros and a version check. + +2011-05-25 13:40:30 +0400 Руслан Ижбулатов + + * gst/gstsystemclock.c: + systemclock: Placate gcc by defining EWOULDBLOCK to something + +2011-05-25 12:47:51 +0400 Руслан Ижбулатов + + * gst/gstpoll.c: + poll: Fix WAKE_EVENT() to behave posixly on Windows + +2011-06-14 15:18:26 +0200 Wim Taymans + + * docs/design/part-TODO.txt: + * docs/random/status-0.11-14-jun-2011.txt: + docs: update docs + +2011-06-13 19:10:00 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-06-13 16:31:53 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbytewriter.c: + * plugins/elements/gstfakesrc.c: + * tests/check/gst/gstbuffer.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/typefindhelper.c: + buffer: add index to _take_memory() + Add an index to gst_buffer_take_memory() so that we can also insert memory at a + certain offset. This is mostly interesting to prepend a header memory block to + the buffer. + +2011-06-13 16:30:22 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't forward scheduling query + The scheduling query should not be forwarded, because elements need to implement + special code to handle different scheduling methods. + +2011-06-13 12:07:03 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + basesrc: Allocator buffers from negotiated allocator + Allocate buffers from the negotiated allocator or bufferpool. + Handle the state of the bufferpool when flushing. + Add fill method to pushsrc. + +2011-06-13 12:04:28 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add more debug + +2011-06-13 11:51:08 +0200 Wim Taymans + + * gst/gstbufferpool.h: + bufferpool: small indentation fix + +2011-06-13 11:50:42 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: pass the allocator as const + +2011-06-13 10:19:30 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: negotiate allocation + Add vmethod to configure allocation methods. + Remove some unused variables + +2011-06-11 20:45:42 +0200 Wim Taymans + + * gst/gstquery.c: + query: add some more checks + Make sure that the alignment is valid. + When we have a 0 size (variable buffer size), we can't have a bufferpool. + +2011-06-11 19:54:47 +0200 Wim Taymans + + * gst/gstquery.c: + query: set all default values + Fill all query values with good defaults. + +2011-06-11 18:52:42 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * libs/gst/base/gstbasetransform.c: + bufferpool: remove postfix parameter + Remove the postfix parameter, it's not used and can be done differently. + +2011-06-10 17:50:27 +0200 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: use same alignment values as GstMemory + Use the same alignment values for the bufferpool as we use for the GstMemory + API. + +2011-06-10 17:32:48 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: use new _check_reconfigure() method + +2011-06-10 17:32:20 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add _check_reconfigure() method + Add a method to check and clear the RECONFIGURE flag on a pad. + +2011-06-10 16:47:29 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add support for buffer in memory + Fix the code to support allocating the buffer and memory in one memory block. + Add an extra variable to store the memory of the buffer. + This code is disabled still because of complications. + +2011-06-10 16:46:12 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: expose default alignment + Export the gst_memory_alignment variable so that others can know the default + configured alignment of the system. + +2011-06-10 16:19:46 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: fix is_span + Subtract the offset of the parent from is_span. + +2011-06-10 13:59:31 +0200 Wim Taymans + + * configure.ac: + * gst/gstbuffer.c: + * gst/gstmemory.c: + memory: respect configured alignment + Move the alignment from GstBuffer to GstMemory. + make sure memory is at least aligned to the configured values. + +2011-06-10 13:40:57 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcompat.h: + * gst/gstvalue.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstqueue2.c: + buffer: make new _buffer_allocate method + Make a new method to allocate a buffer + memory that takes the allocator and the + alignment as parameters. Provide a macro for the old method but prefer to use + the new method to encourage plugins to negotiate the allocator properly. + +2011-06-10 12:44:40 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: + * win32/common/libgstbase.def: + docs: update for gst_base_src_set_dynamic_size + Add to sections file and add Since: marker. Also update + win32 .def file. + API: gst_base_src_set_dynamic_size() + +2011-06-10 13:44:19 +0200 Edward Hervey + + * docs/design/Makefile.am: + design: part-bufferlist.txt was merged into another doc + +2011-06-10 13:34:59 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + docs: Update sections files for added/removed symbols + +2011-06-10 13:10:42 +0200 Edward Hervey + + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + win32: Update for added/removed symbols + +2011-06-10 13:04:23 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfilesrc.c: + basesrc: add fill vmethod to basesrc + Add a new fill virtual method to basesrc. The purpose of this method is to fill + a provided buffer with data. + Add a default implementation of the create method that allocates a buffer and + calls the fill method on it. This would allow the base class to implement + bufferpool and allocator negotiation on behalf of the subclasses. + Fix the blocksize property. + Make filesrc use the new fill method. + +2011-06-10 12:09:49 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstelementfactory.c + gst/gstelementfactory.h + gst/gstpad.h + gst/gstpluginfeature.c + gst/gstpluginfeature.h + +2011-06-10 11:55:08 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * tests/check/elements/fakesink.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstpad.c: + event: add reset_time boolean to flush_stop event + Add a boolean to the flush_stop event to make it possible to implement flushes + that don't reset_time. + Make basesink post async_done with the reset_time property from the flush stop + event. + Fix some unit tests + +2011-06-09 17:13:35 +0100 Javier Jardón + + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstformat.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstquery.h: + * gst/gststructure.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * gst/gsttrace.h: + * gst/gsturi.c: + * gst/gsturi.h: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.h: + Use "const" instead G_CONST_RETURN + G_CONST_RETURN will be deprecated soon. + https://bugzilla.gnome.org/show_bug.cgi?id=652211 + +2011-06-09 13:37:28 +0200 Wim Taymans + + * gst/gstpad.c: + pad: use new event methods to replace events + Using the new event methods, we can atomically transfer the event from the + pending list to the active list. + +2011-06-09 13:36:52 +0200 Wim Taymans + + * gst/gstevent.h: + event: make macros for new miniobject methods + +2011-06-09 13:35:08 +0200 Wim Taymans + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + miniobject: add new methods to manage miniobject pointers + Add a new method to steal the miniobject stored at a location. + Add a new method to store a miniobject in a location and taking ownership + of the miniobject. + +2011-06-09 13:34:19 +0200 Wim Taymans + + * gst/gstpad.h: + pad: fix header + +2011-06-09 12:31:47 +0200 Wim Taymans + + * gst/gstpad.h: + pad: fix spurious include + +2011-06-09 12:01:02 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + libs/gst/base/gstbasesrc.c + +2011-06-09 11:39:08 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gsttee.c: + pad: forward events by default + Always forward all events in the default handler. Previously it used to not + forward caps events by default. It makes more sense to forward the caps events, + if the element is interested in the caps, it will implement an event handler to + retrieve the caps and then it can decide to forward or not. If the element has + no event handler, it probably just doesn't care about caps and it probably is + also not going to modify the data in a way that needs a caps change. + +2011-06-09 11:13:55 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: fix typo in docs + +2011-06-08 18:22:36 +0200 Mark Nauwelaerts + + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + filesrc/fdsrc: indicate dynamic size handling to basesrc + +2011-06-08 18:22:03 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: add dynamic size handling + This allows subclass to indicate that size reported by src may not be static + and should as such be updated regularly, rather than only when really + needed. + Particular examples are filesrc or fdsrc reading from a file that is still + growing (e.g. being downloaded). + Fixes #652037. + +2011-06-08 20:14:16 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + Revert "basesrc: Send an update NEWSEGMENT event downstream if the duration changes" + This reverts commit 934faf163caf10ed3d54d81fd7b793069913dffd. + Original commit leads to possibly sending newsegment event downstream + in pull mode. In push mode, quite some downstream elements + are likely to only expect newsegment event following a seek they performed + and as such may have their state messed up. + +2011-06-08 18:35:16 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: inline the clip segment + +2011-06-08 17:25:43 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstpipeline.c: + * gst/gstquark.c: + * gst/gstquark.h: + message: rename variable + Rename the new_base_time variable to reset_time, which looks better. + +2011-06-08 16:41:05 +0200 Wim Taymans + + * gst/gstsegment.h: + segment: separate the seek and segment flags + Separate the seek flags and segment flags as separate enums because we might + want to have different flags for both. + +2011-06-08 13:40:32 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstpipeline.c: + * gst/gstquark.c: + * gst/gstquark.h: + * libs/gst/base/gstbasesink.c: + message: move the new_base_time flag to async_done + Move the flag to indicate that a new_base_time should be distributed to the + pipeline, from the async_start to the async_done message. This would allow us to + decide when to reset the pipeline time based on other reasons than the + FLUSH_START event. + The main goal eventually is to make the FLUSH events not reset time at all but + reset the time based on the first buffer or segment that prerolls the pipeline + again. + +2011-06-08 13:39:19 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + docs: Update gstreamer-sections for new/removed API + +2011-06-08 13:30:49 +0200 Edward Hervey + + * gst/gstbuffer.h: + gstbuffer: Remove deprecated GST_BUFFER_* macros + data, size, mallocdata and free_func no longer exist. + +2011-06-08 13:06:17 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update for added/removed symbols + +2011-06-08 12:58:29 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: remove setcaps function + Remove the setcaps function, elements should use the caps event to be informed + of the format. + +2011-06-08 12:04:49 +0200 Wim Taymans + + * docs/design/part-memory.txt: + * gst/gstmemory.c: + * tests/check/gst/gstmeta.c: + memory: Require implementation to implement _share + Require the memory implementations to implement a share operation. This allows + us to remove the fallback share implementation which uses a different allocator + implementation and complicates things too much. + Update design doc a bit. + +2011-06-08 11:03:50 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstquery.c: + memory: cleanups and improve docs + Make the fallback copy use the same memory allocator as the original object. + Improve some docs. + Require an alloc function when registering an allocator. + Remove gst_memory_allocator_get_default() and merge the feature in + gst_memory_allocator_find() + Fix locks on the hashtable. + Remove defined but not-implemented gst_memory_span() method. + +2011-06-07 18:18:27 +0200 Wim Taymans + + * docs/design/part-memory.txt: + docs: add beginnings of memory design doc + +2011-06-07 17:54:33 +0200 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: pass user_data to the alloc function + Pass the user data that was passed to _register to the alloc function of an + allocator. + +2011-06-07 17:34:17 +0200 Wim Taymans + + * gst/gstmemory.h: + memory: fix some typos + +2011-06-07 17:03:09 +0200 Wim Taymans + + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfilesrc.h: + filesrc: remove MMAP code + Remove the mmap code, it was disabled and probably needs a complete rewrite + anyway if this is to be ported to 0.11. + +2011-06-07 16:35:07 +0200 Wim Taymans + + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + query: add methods to query allocators + Add API to add and query allocator implementations to/from the ALLOCATION query. + +2011-06-07 16:14:50 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: use allocators to allocate memory + Rename the GstMemoryImpl to GstMemoryAllocator because that's really what it is. + Add an alloc vmethod to the allocator members. + Improve registration of allocators. + Add methods to get and set the default allocator + Always use an allocator to allocate memory, use the default allocator when NULL + is passed. + Add user_data to the allocator Info so that we can pass extra info to the + allocator new method. + +2011-06-07 13:03:29 +0100 Tim-Philipp Müller + + * docs/design/part-meta.txt: + * docs/design/part-negotiation.txt: + docs: minor fix and clarification + +2011-06-07 13:38:35 +0200 Wim Taymans + + * gst/gstevent.h: + event: move some more defines on top + +2011-06-07 13:25:26 +0200 Wim Taymans + + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstutils.c: + * gst/gstutils.h: + fix some circular includes + typedef some structs before including other files to avoid circular dependencies + in the header files. + +2011-06-07 11:01:36 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update for added/removed symbols + +2011-06-06 12:23:04 +0200 Edward Hervey + + * tests/check/elements/tee.c: + check/tee: Pads need to be activated before caps are set + Also add debugging to figure out what's going on + +2011-06-07 10:52:02 +0200 Wim Taymans + + * gst/gstutils.c: + * gst/gstutils.h: + utils: remove proxy_setcaps + Remove proxy_setcaps, elements should use the caps event and forward caps + themselves. + +2011-06-07 10:51:23 +0200 Wim Taymans + + * plugins/elements/gstoutputselector.c: + outputselector: fix refcounting of events + _pad_event_forward() takes ownership of the caps. + +2011-06-07 10:49:34 +0200 Wim Taymans + + * gst/gstpad.c: + pad: Improve pad event forward code + Return TRUE when the pad has no parent or when there are no internally linked + pads. + +2011-06-07 10:04:52 +0200 Wim Taymans + + * plugins/elements/gstoutputselector.c: + * plugins/elements/gsttee.c: + plugins: use the caps event + Use the caps event and avoid using the setcaps function. Use some of the new pad + forward functions to implement desired behaviour. + +2011-06-07 10:02:06 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Rename and rework the dispatcher function + Rename gst_pad_dispatcher() to gst_pad_forward() and make it more useful by + iterating the internal links of a pad and handling resync properly. + Add a method gst_pad_event_forward() that unconditionally forwards an event to + all internally linked pads. + Update some pad code to use the new forward function. + +2011-06-07 09:43:20 +0200 Wim Taymans + + * gst/gstdebugutils.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gsttypefindelement.c: + * tools/gst-inspect.c: + caps: use the caps event + Use the caps event instead of gst_pad_set_caps() and the setcaps function + +2011-06-06 16:11:31 +0200 Wim Taymans + + * docs/design/part-TODO.txt: + * docs/design/part-block.txt: + * docs/design/part-buffer.txt: + * docs/design/part-bufferlist.txt: + * docs/design/part-caps.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-latency.txt: + * docs/design/part-messages.txt: + * docs/design/part-meta.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-overview.txt: + * docs/design/part-probes.txt: + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + * docs/design/part-sparsestreams.txt: + * docs/design/part-streams.txt: + * docs/design/part-synchronisation.txt: + * docs/design/part-trickmodes.txt: + docs: go over design docs and fix things + Remove bufferlist part, it's merged with part-buffer.txt + +2011-06-06 11:21:23 +0200 Edward Hervey + + * gst/gst.c: + gst: Add enum/flags (de)registration in gst_(de)init + +2011-06-06 11:20:29 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Don't accept segments after EOS + And refactor the code slightly to avoid code duplication. + This solves a regression introduced by bdbc0693 + +2011-06-06 10:27:57 +0200 Edward Hervey + + * tests/check/gst/gstghostpad.c: + check/ghostpad: Activate pads before checking for caps forwarding/setting + This is now done via in-band events, so the pads need to be active + +2011-06-05 18:11:22 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstbuffer.h: + * gst/gstbufferpool.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstiterator.c: + * gst/gstmemory.h: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstquery.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstpushsrc.c: + docs: update for API changes + Also remove GST_PAD_CHECKGETRANGEFUNC macro + +2011-06-05 15:46:54 +0100 Tim-Philipp Müller + + Merge branch 'master' into 0.11 + +2011-06-04 15:42:13 +0100 Tim-Philipp Müller + + * gst/parse/Makefile.am: + parse: add prototypes for unused functions to avoid compiler warning + The warning is never fatal, because we don't use -Werror for the + parser helper library build, but the warnings are annoying anyway. + +2011-06-05 14:10:50 +0100 Tim-Philipp Müller + + * tools/Makefile.am: + * tools/gst-run.c: + tools: remove unversioned gst-launch, gst-inspect and gst-typefind + The unversioned tool wrappers are confusing and annoying for packagers, + users and developers alike. A gst-launch pipeline that works in 0.10 + will likely not work in 0.11 (e.g. because elements or properties get + renamed, or syntax changes). The unversioned tools also yield useless + results when used with gdb or valgrind. Packagers need to co-ordinate + the packaging of all major versions to make sure there are no conflicts + when both try to install the same files. When two major versions are + in use (e.g. 0.10 and 0.11/1.0), it may be unclear (when looking at + things on IRC/pastebin/mailing list etc.) which version is actually + being used when there are unversioned wrappers. For all these reasons, + it seems best to just remove them for now. + +2011-06-04 16:04:35 +0100 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstmarshal.c: + * win32/common/gstmarshal.h: + * win32/common/gstversion.h: + * win32/common/libgstreamer.def: + win32: update exports and other things + +2011-06-04 15:44:39 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translatable string and removed strings + +2011-06-04 15:23:56 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstinfo.c: + info: remove GST_XML debug category as well + +2011-06-04 15:22:06 +0100 Tim-Philipp Müller + + * Android.mk: + * Makefile.am: + * configure.ac: + * docs/design/part-TODO.txt: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstconfig.h.in: + * gst/parse/Makefile.am: + * gstreamer.spec.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + * plugins/indexers/Makefile.am: + * plugins/indexers/gstindexers.c: + * plugins/indexers/gstindexers.h: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstxml.c: + * tests/check/gst/struct_arm.h: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + * tests/examples/manual/Makefile.am: + * tools/.gitignore: + * tools/Makefile.am: + * tools/gst-launch.1.in: + * tools/gst-xmllaunch.1.in: + Remove everything libxml2- and loadsave-related + +2011-06-04 14:41:16 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + tools: remove SIGUSR* handling from gst-launch + Remove SIGUSR* handling from gst-launch, since it might interfere + with other things (e.g. libleaks), and should be done differently + anyway (either via support for simple timed-commands scripting or + remote control via DBus or so). + +2011-06-04 14:28:08 +0100 Tim-Philipp Müller + + * gstreamer.spec.in: + * tools/.gitignore: + * tools/BUGS: + * tools/Makefile.am: + * tools/README: + * tools/gst-xmlinspect.1.in: + * tools/gst-xmlinspect.c: + * tools/xml2text.xsl: + tools: remove gst-xmlinspect + People should just query the registry themselves or write a small + python script if they need this functionality (which is likely + less work than parsing the XML that this script outputs, and I'm + not aware of anything using the xml2text xsl either). + +2011-06-04 14:22:05 +0100 Tim-Philipp Müller + + * docs/faq/using.xml: + * gstreamer.spec.in: + * tools/.gitignore: + * tools/Makefile.am: + * tools/gst-feedback-m.m: + * tools/gst-feedback.1.in: + tools: remove gst-feedback + It's not really that useful, and no one's been using it for years. + +2011-06-04 14:13:07 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpad.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + tools, tests: fix some unused-but-set-variable compiler warnings + +2011-06-04 14:02:23 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translatable string + +2011-06-04 00:30:15 -0700 David Schleef + + * gst/glib-compat-private.h: + * gst/gstatomicqueue.c: + * gst/gstelementfactory.c: + * gst/gstpoll.c: + * gst/gstsystemclock.c: + * gst/gstutils.c: + * plugins/elements/gstmultiqueue.c: + * tests/benchmarks/gstclockstress.c: + Work around changes in g_atomic API + See #651514 for details. It's apparently impossible to write code + that avoids both type punning warnings with old g_atomic headers and + assertions in the new. Thus, macros and a version check. + +2011-06-03 18:10:24 +0200 Edward Hervey + + * gst/gstpad.h: + gstpad: Small doc fixup + +2011-06-03 15:53:21 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update .def for latest APi changes + +2011-06-03 17:24:45 +0200 Wim Taymans + + * gst/gstpad.h: + pad: clean up probe flags + +2011-06-03 17:24:21 +0200 Wim Taymans + + * docs/design/part-probes.txt: + docs: first version of probes document + +2011-06-03 16:46:26 +0200 Wim Taymans + + * gst/gstpad.c: + pad: check flushing in pullrange too + +2011-06-03 13:56:04 +0200 Wim Taymans + + * gst/gstpad.c: + pad: cleanups + Use defines instead of hardcoded values for masks. + +2011-06-03 13:25:54 +0200 Wim Taymans + + * gst/gststructure.c: + * tests/check/gst/gststructure.c: + structure: fix some more 0.11 fixmes + don't allow spaces in structure names and fix unit tests. + +2011-06-03 12:43:32 +0200 Wim Taymans + + * docs/design/draft-allocation.txt: + * docs/design/part-bufferpool.txt: + docs: update bufferpool design doc + Move the bufferpool design doc from draft to part and merge it with + the allocation draft. + +2011-06-03 12:40:56 +0200 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: make the default behaviour to wait + The most common case is to not specify any flags when doing the allocation. Make + the allocation from a pool with a maximum amount of buffers block by default for + this reason. + +2011-06-03 11:15:30 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting doc + +2011-06-02 19:24:26 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: use caps event instead of setcaps + +2011-06-02 19:23:47 +0200 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + ghostpad: remove setcaps functions + Remove the setcaps functions, it is now handled with the caps event. + +2011-06-02 18:28:54 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: pass the right alignment + +2011-06-02 18:28:17 +0200 Wim Taymans + + * gst/gstmemory.c: + memmory: small cleanup + +2011-06-02 18:13:33 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: fix alignment calculations + Fix the alignment calculation. + Improve documentation. + +2011-06-02 18:13:10 +0200 Wim Taymans + + * gst/gstbufferpool.c: + pool: debug the config + +2011-06-02 15:38:43 +0200 Wim Taymans + + * gst/gstutils.h: + utils: remove some macros now in glib + We depend on the right glib now + +2011-06-02 15:38:29 +0200 Wim Taymans + + * gst/gststructure.c: + structure: fix a FIXME + +2011-06-02 15:38:04 +0200 Wim Taymans + + * gst/gstutils.c: + utils: use g_printerr() as stated in the FIXME + +2011-06-02 15:37:41 +0200 Wim Taymans + + * gst/gstelement.c: + element: small cleanups + +2011-06-02 14:09:46 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + element: inline the recursice state lock + +2011-06-02 13:46:26 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: inline the recursive stream lock + +2011-06-02 13:35:52 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: remove unused fields and methods and signals + +2011-06-02 13:23:53 +0200 Wim Taymans + + * gst/gstpad.c: + pad: use new gst_value_fixate instead + Use the new gst_value_fixate() function instead of our own version. + +2011-06-02 13:21:55 +0200 Wim Taymans + + * gst/gstvalue.c: + * gst/gstvalue.h: + value: add function to fixate a value + Add a function to fixate a GValue. This is the same function as is in GstPad. + +2011-06-02 13:18:39 +0200 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + caps: remove some custom refcounting methods + Remove some custom made refcounting methods and use the miniobject ones instead. + +2011-06-02 12:40:05 +0200 Wim Taymans + + * gst/gstpad.c: + pad: optimize linking + Optimize linking by only releasing the pad locks when there are link functions + installed on the pads. + Add some G_LIKELY here and there. + Move error paths out of the main code flow. + +2011-06-02 12:39:34 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: remove deprecated have-data signal + +2011-06-02 11:21:09 +0200 Wim Taymans + + * gst/gstpad.c: + pad: add idle probe for pull method too + +2011-06-02 11:01:31 +0200 Wim Taymans + + * gst/gstpad.c: + pad: more cleanups + Use miniobject unref when we can + Reuse existing data type identifier instead of an extra boolean. + +2011-06-01 19:47:10 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + plugins/elements/gstoutputselector.c + +2011-06-01 19:27:55 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/elements/selector.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/basesrc.c: + * tests/check/pipelines/queue-error.c: + pad: further improve probes and pad blocking + Keep track of installed number of probes to shortcut emission. + Allow NULL callbacks, this is useful for blocking probes. + Improve probe selection based on the mask, an empty mask for the data or the + scheduling flags equals that all probes match. + Add some more debug info. + Don't check the flushing flag in the probe callback handler, this needs to be + done before calling the handler. + Fix blocking probes. + Fix unit tests + +2011-05-31 19:16:09 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpipeline.c: + pad: implement pad block with probes + +2011-05-30 19:03:38 +0200 Wim Taymans + + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstconsistencychecker.c: + * tests/check/elements/selector.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpipeline.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/basesrc.c: + * tests/check/pipelines/queue-error.c: + utils: remove _full variants of probes + Remove the _full variants and add the destroy notify to the regular methods. + +2011-06-01 15:29:20 +0200 Edward Hervey + + * tests/check/gst/struct_arm.h: + check/abi: Ignore GstXML* on arm when not present + +2011-05-31 18:31:53 +0200 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: Use local priv variable instead of trans->priv + +2011-05-31 18:30:50 +0200 Edward Hervey + + * gst/gstsegment.c: + gstsegment: Remove dead assignment + base is unconditionally written a couple of lines below + +2011-05-31 18:30:30 +0200 Edward Hervey + + * gst/gstbin.c: + * gst/gstbufferpool.c: + * gst/gstelement.c: + * libs/gst/base/gstbasesink.c: + gst: Remove obvious dead assignments + +2011-05-31 13:43:47 +0200 Edward Hervey + + * plugins/elements/gstoutputselector.c: + outputselector: Remove dead assignment + +2011-05-30 18:29:06 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + pad: Rework pad blocking, another attempt + Make the PadBlock callback take a GstBlockType parameter to handle the different + kind of stages in the pad block. This provides for more backwards compatibility + in the pad block API. + Separate blocking and unblocking into different methods, only blocking can do a + callback, unblock is always immediately. Also removed synchronous blocking, it + can always be implemented with a callback. + +2011-05-30 13:40:04 +0200 Wim Taymans + + * gst/gstpad.c: + * tests/check/elements/fakesink.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + Revert "pad: rework pad blocking, first part" + This reverts commit 415da89f3c9fe46fc3361236df9a3b76e607e138. + Conflicts: + gst/gstpad.c + +2011-05-30 12:27:31 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve debugging + +2011-05-30 11:33:57 +0200 Sebastian Dröge + + * gst/gststructure.c: + * gst/gstvalue.c: + value: Consider "1" and "{1}" as equal in gst_value_compare() + Previously this was only done in the is_subset() check but + having it only there brings us into definition-hell where + "1" and "{1}" are subset of each other but not equal. + +2011-05-30 07:44:50 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Don't access the GstMessage structure directly + +2011-05-30 07:41:13 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-05-30 07:36:58 +0200 Sebastian Dröge + + * gst/gststructure.c: + * tests/check/gst/gstcaps.c: + caps: Fix subset check for equivalent lists and scalar values + For example "{ 1 }" and "1" are not strictly equal but + both are a subset of each other. Also add a unit test + for this. + +2011-05-29 19:28:34 +0100 Tim-Philipp Müller + + * docs/faq/general.xml: + docs: fix bugzilla URL + htpp -> http + https://bugzilla.gnome.org/show_bug.cgi?id=651362 + +2011-05-28 10:24:37 +0300 Stefan Kost + + * gst/gstelement.h: + docs: xrefs more api around GstStateChange and GstStateChangeReturn. + +2011-05-28 09:51:45 +0300 Stefan Kost + + * gst/gstmessage.h: + docs: xref the async messages to GstStateChange + +2011-05-27 17:20:56 +0200 Wim Taymans + + * gst/gstpad.c: + * tests/check/elements/fakesink.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + pad: rework pad blocking, first part + Make pad block call the callback as soon as the pad is not in use. This makes it + possible to make sure that when the callback is called, no activity is happening + on the pad and that no activity will ever happen until the pad is unblocked + again. This makes pad blocking work when there is no dataflow or after EOS and + greatly helps dynamic pipelines. + Move the probe handling right where we wait on the pad block. The two are + related but not the same and the probe can eventually influence the pad + blocking as we'll se later. + Fix up some broken unit tests or tests that fail with the new behaviour. + +2011-05-27 17:18:00 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * tests/check/libs/basesrc.c: + basesrc: remove deprecated clean shutdown method + +2011-05-27 14:00:56 +0200 Wim Taymans + + * plugins/elements/gsttee.c: + tee: deactivate the pad after removing it + When releasing the request pad, first remove it from the element and then + deactivate it. If we do it the other way around, a gst_pad_push on the element + might return wrong-state before we had a chance to detect the removed pad in the + chain function. + +2011-05-27 15:14:32 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: catch and print missing-plugin messages in gst-launch + So that users get some feedback if they're using a pipeline + like src ! decodebin2 ! sink and are missing an element. + +2011-05-27 14:02:03 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Fix for SEGMENT event API changes + +2011-05-27 13:58:26 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-05-27 13:55:31 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * win32/common/libgstreamer.def: + caps: Add gst_caps_is_subset_structure() + API: gst_caps_is_subset_structure() + This allows to check if a structure is a subset of given + caps without allocating a new caps instance for it. + +2011-05-27 13:47:11 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: Add gst_structure_is_subset() + API: gst_structure_is_subset() + +2011-05-27 13:38:51 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + caps: Optimize gst_caps_is_subset() + ..and as a result gst_caps_is_equal() and others. + This now only checks if for every subset structure there is + a superset structure in the superset caps. Previously we were + subtracting one from another, creating completely new caps + and then even simplified them. + The new implemention now is about 1.27 times faster and doesn't + break the -base unit tests are anything anymore. + +2011-05-27 13:37:06 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + caps: Fix subset check in gst_caps_merge() + Caps A are a subset of caps B even if caps B doesn't + have all fields of caps A. + Also add a unit test for this. + +2011-05-27 12:56:03 +0200 Sebastian Dröge + + * gst/gstcaps.c: + Revert "caps: Optimize gst_caps_is_subset()" + This reverts commit 32248a9b852bcb568a5b642299ecc8e5bf48ea13. + This breaks some tests in -base and the failures should + be fixed first. + +2011-05-27 12:45:59 +0200 Sebastian Dröge + + * gst/gstcaps.c: + caps: Optimize gst_caps_is_subset() + ..and as a result gst_caps_is_equal() and others. + This now only checks if for every subset structure there is + a superset structure in the superset caps. Previously we were + subtracting one from another, creating completely new caps + and then even simplified them. + The new implemention now is about 1.27 times faster. + +2011-05-27 11:45:16 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Drop sticky events pushed on flushing srcpads instead of activating them immediately + +2011-05-26 14:56:12 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * libs/gst/base/gstbasetransform.c: + basetransform: Pass the complete caps to transform_caps + Instead of passing it structure by structure. This allows + better optimized transform_caps functions and allows better + transformation decisions. + See bug #619844. + +2011-05-27 09:05:46 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Send an update NEWSEGMENT event downstream if the duration changes + This allows streaming the complete file for files that have grown since + streaming started. + Fixes bug #647940. + +2011-05-26 19:45:14 +0200 Wim Taymans + + * gst/gstpad.c: + pad: refactor _push_event + Rework _push_event() a little so that it drops events on blocking pads. + Make sure that events are forwarded when we unblock. + Add counter on the pad to keep track of busy pads. + +2011-05-26 18:21:09 +0200 Wim Taymans + + * gst/gstpad.c: + pad: refactor pre and post chain code + +2011-05-26 17:50:15 +0200 Wim Taymans + + * gst/gstpad.c: + pad: keep counter for active pads + Keep a counter to mark the amount of threads currently pushing data on the pad. + +2011-05-26 17:39:17 +0200 Wim Taymans + + * gst/gstpad.c: + pad: refactor pre push code + Refactor the code that is executed as the first step of a push operation where + we check the probes and blocking and resolve the peer. + +2011-05-26 17:08:03 +0200 Wim Taymans + + * gst/gst_private.h: + * gst/gstpad.c: + * gst/gstutils.c: + pad: remove pad cache + Remove the pad cache as this is going to be reworked for new pad blocking and + probes. + +2011-05-26 16:48:14 +0200 Wim Taymans + + * gst/gstpad.c: + pad: simplify handling of buffer lists + Implement a default buffer-list function in case the element doesn't implement + one. + Also pass buffer-lists to the have-data signal, this allows us to remove some + backward compatibility code. + +2011-05-26 16:15:52 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + pad: remove old gst_pad_set_blocked methods + +2011-05-26 14:14:13 +0200 Sebastian Dröge + + * libs/gst/base/gstpushsrc.c: + pushsrc: Fix infinite recursion in pushsrc query handler + +2011-05-26 13:36:48 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-05-25 16:02:10 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + gst: we can now use GLib 2.24 API unconditionally + +2011-05-25 15:54:01 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump GLib requirement to >= 2.24 + http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement + +2011-05-25 15:38:30 +0100 Tim-Philipp Müller + + * docs/random/release: + docs: update release instructions for gnome change + +2011-05-25 13:40:30 +0400 Руслан Ижбулатов + + * gst/gstsystemclock.c: + systemclock: Placate gcc by defining EWOULDBLOCK to something + +2011-05-25 12:47:51 +0400 Руслан Ижбулатов + + * gst/gstpoll.c: + poll: Fix WAKE_EVENT() to behave posixly on Windows + +2011-05-24 20:28:18 +0300 Stefan Kost + + * gst/gstregistrybinary.h: + registrybinary: small cleanups + Remove unneeded braces from string define. Small doc improvement. + +2011-05-24 20:27:02 +0300 Stefan Kost + + * gst/gstpreset.c: + preset: use guint for the version number parts + Use unsigned integers for extra safety (like we do in plugin version parsing). + +2011-05-24 18:39:41 +0200 Wim Taymans + + * gst/gst_private.h: + * gst/gstelement.c: + remove some more deprecated methods + +2011-05-24 18:29:48 +0200 Wim Taymans + + * gst/gstpadtemplate.h: + padtemplate: remove unused flag + +2011-05-24 18:17:24 +0200 Wim Taymans + + * gst/gstelementfactory.c: + * gst/gstindexfactory.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * gst/gstregistrychunks.c: + * libs/gst/base/gsttypefindhelper.c: + * tests/check/gst/gstplugin.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + feature: use object name + Remove the name property from the plugin feature and port code to use the object + name instead. + +2011-05-24 18:16:36 +0200 Wim Taymans + + * configure.ac: + * gst/gstconfig.h.in: + remove old glib check + +2011-05-24 17:43:36 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-05-24 17:36:24 +0200 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstquery.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstpushsrc.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + scheduling: port to new scheduling query + +2011-05-24 12:52:09 +0200 Wim Taymans + + * docs/design/part-scheduling.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + query: add SCHEDULING query + Add a new query to replace the checkgetrange function. + +2011-05-24 19:43:58 +0530 Debarshi Ray + + * libs/gst/check/gstcheck.h: + check: add fail_unless_equals_int64 + https://bugzilla.gnome.org/show_bug.cgi?id=650973 + +2011-05-24 16:14:57 +0200 Sebastian Dröge + + * plugins/elements/gstoutputselector.c: + outputselector: Forward sticky events to newly created srcpads + +2011-05-24 16:13:22 +0200 Sebastian Dröge + + * plugins/elements/gsttee.c: + tee: Forward sticky events to newly created srcpads + +2011-05-24 16:08:41 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Add gst_pad_sticky_events_iterate() function + +2011-05-24 13:27:09 +0200 Sebastian Dröge + + * gst/gstdebugutils.c: + debugutils: Fix for GstIterator API changes + +2011-05-24 13:28:00 +0200 Sebastian Dröge + + * gst/gstdebugutils.c: + Revert "debugutils: Fix for GstIterator API changes" + This reverts commit e1cc3176d6fb8023bbe0c733615b2a8c420a2077. + This is not the 0.11 branch... + +2011-05-24 13:27:09 +0200 Sebastian Dröge + + * gst/gstdebugutils.c: + debugutils: Fix for GstIterator API changes + +2011-05-24 09:48:44 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstpad.h + +2011-05-24 00:26:40 +0300 Kipp Cannon + + * gst/gstclock.h: + clock: improve the GST_TIME_FORMAT/ARGS docs + +2011-05-23 23:40:20 +0300 Stefan Kost + + * gst/gstpad.h: + docs: hide this from the docs + +2011-05-23 18:30:19 +0200 Wim Taymans + + * gst/gstevent.c: + event: use GST_SEGMENT_FORMAT for segments + +2011-05-23 18:15:00 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + transform: fixes for bufferpool handling + Don't error out when the allocation query returns success. + Do bufferpool query after we pushed the caps event downstream so that we can get + a good bufferpool suggestion. + Also proxy the bufferpool query downstream when we operate in in_place mode. + +2011-05-23 18:14:27 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve debugging + +2011-05-23 16:53:01 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + transform: reset reconfigure state + When we negotiate new caps, reset the reconfigure state. + +2011-05-20 18:56:37 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: WIP handle bufferpool + +2011-05-21 19:06:08 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: avoid calling _set_caps() on the srcpad + Avoid installing a setcaps function on the srcpad and calling the setcaps + function, we can do more efficiently with sending the event ourself and calling + our vmethod. + +2011-05-20 16:03:10 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstpad.h + gst/gstplugin.h + +2011-05-20 15:58:10 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: remove some more code + Remove some more unused code from basetransform. + Prepare for implementing bufferpools. + +2011-05-20 15:50:05 +0300 Stefan Kost + + * win32/common/libgstbase.def: + win32: add new api + +2011-05-20 15:48:09 +0300 Stefan Kost + + * gst/gstpad.h: + * gst/gstplugin.h: + deprecation-guards: fixup for commit 9ff4ec3104d2510b8f379ff38c671682ff795e33 + Remove the deprecation guards for GST_PLUGIN_DEFINE_STATIC again (even though it + is deprecated) as we use it in the tests. Remove "_" for intlinkfunc. + +2011-05-20 13:06:57 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-05-20 13:03:51 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Only reinit the cached GstClockID if it is for the same clock + The clock might have changed since the clock ID was created and in + that case we have to request a new one. + +2011-05-20 12:43:24 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + element: add method to get metadata + Add a method to get the metadata from a klass. + +2011-05-20 12:43:02 +0200 Wim Taymans + + * gst/gstelementfactory.h: + factory: fix typo + +2011-05-20 12:18:48 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Always send a SEGMENT event when the active pad changes + +2011-05-20 12:16:59 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Fix copy&paste mistake in the srcpad event function + +2011-05-20 12:07:45 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + docs/plugins/gstreamer-plugins.hierarchy + +2011-05-20 12:00:11 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Send upstream events to all sinkpads, not only the selected one + This makes sure that SEEK events are sent to all upstream elements, which is + required if different streams are completely distinct pipeline parts. Also this + allows QoS to be done on deselected streams, flushes to be handled correctly, + etc. + +2011-05-20 11:36:25 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + pad: add pending event for sticky events + Change the sticky event array so that it contains a pending and an active event. + Events on the sinkpad are copied to the pending array and after the eventfunc + returned TRUE, moved to the active event. This allows us to queue new events + like when we do per-pad offsets without removing the currently active event. + Remove the active argument from the gst_pad_get_sticky_event() method, the + pending events are not something we want to expose. + +2011-05-20 00:39:10 +0300 Stefan Kost + + * gst/gstpreset.c: + * gst/gstpreset.h: + preset: include cleanup + Only have include in the installed header we need to use it. Move the includes + needed by the implementation to the c file. + +2011-05-19 23:19:30 +0300 Stefan Kost + + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.interfaces: + docs: update plugin introspection data + Now more files are merged and produced in a canonical fashion, which hopefully + creates less or no delta in the future. + +2011-05-19 22:56:28 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 9e5bbd5 to 69b981f + +2011-05-19 19:07:29 +0200 Wim Taymans + + * tests/check/gst/gstpad.c: + tests: caps are not stored on flushing pads + Caps are now also stored on flushing pads in the inactive state. + +2011-05-19 19:01:09 +0200 Wim Taymans + + * gst/gstpad.c: + pad: apply pad offset on sinkpad events too + Apply the pad offset in the send_event() function as well. + +2011-05-19 18:27:55 +0200 Wim Taymans + + * gst/gstpad.c: + pad: add per-pad offsets + When linking pads and when copying a segment event from the sourc pad to the + sinkpad, apply the src and sinkpad offsets to the segment base. Make sure that + we only modify the event stored on the sinkpad and never the one on the source + pad. + When changing the pad offset, perform the segment copy with the updated offsets. + When pushing a segment event, apply the srcpad offset before sending the event + to the peer pad. + This part is missing the adjustment of the segment event on the sinkpad, which + is for a later patch. + +2011-05-19 16:26:06 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add methods to adjust the offset + Add methods to adjust the offset. This will be used to change the segment events + with an offset so that we can tweak the timing of the stream on a per-pad base. + +2011-05-19 12:11:43 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Port to the new segment API + The switch action signal with the stop and start running times + is not necessary anymore. Closing of segments is not necessary + and adjusting the start running time of a segment can later be + done with new GstPad API. + +2011-05-19 11:30:06 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstghostpad.h + +2011-05-18 19:43:44 +0200 Wim Taymans + + * gst/gstpad.c: + pad: store sticky events on flushing sinkpads too + First store the sticky event on the sinkpad in the inactive state, then check + for the flushing flag. We want to have the events on sinkpads at all times, + ready to be activated when the pad becomes active. + +2011-05-18 18:53:35 +0200 Wim Taymans + + * gst/gstpad.c: + pad: move caps check to central location + Make a function to call the eventfunc and perform a caps check when we are + dispatching a caps event. + This makes sure that all code paths correctly check that the caps are + acceptable before sending the caps to the eventfunction. + +2011-05-18 18:52:22 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: avoid calling setcaps too many times + Don't call setcaps, the caps event will take care of propagating the caps on all + pads. + +2011-05-18 18:48:03 +0200 Wim Taymans + + * gst/gstquery.c: + query: add allocation query name + Add ALLOCATION query name and guard some functions against invalid queries. + +2011-05-18 16:56:13 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * tests/check/gst/gstevent.c: + * tests/check/libs/basesrc.c: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + event: Make SEGMENT event parsing API more consistent with the others + +2011-05-18 16:47:44 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: relax caps check + Also run the caps transform function on ANY caps, like we used to do before. + This makes sure that capsfilter has a chance to filter ANY caps as well. + +2011-05-18 16:29:10 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Don't forget to take the object lock when getting a sticky event + +2011-05-18 16:26:31 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Add function to get sticky events from a pad + API: gst_pad_get_sticky_event() + +2011-05-18 15:43:20 +0200 Wim Taymans + + * gst/gstevent.c: + * tests/check/gst/gstevent.c: + event: fix event copy + Fix parent refcount on event copy. + Fix unit test. + +2011-05-18 15:29:25 +0200 Wim Taymans + + * gst/gstpad.c: + pad: notify caps property change in callsetcaps + Notify the caps property change in the backwards compatible function to call the + setcaps function. + +2011-05-18 16:09:19 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From fd35073 to 9e5bbd5 + +2011-05-18 15:04:48 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + docs: remove GstProxyPad from private section + +2011-05-18 15:02:02 +0300 Stefan Kost + + * gst/gstghostpad.h: + * gst/gstminiobject.c: + docs: use the same name for the argument in prototype and docs + +2011-05-18 14:59:45 +0300 Stefan Kost + + * tests/examples/manual/Makefile.am: + manual: put generated sources to BUILT_SOURCES and clean them on make clean + +2011-05-18 13:19:31 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-05-18 13:14:57 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstminiobject.c + gst/gstpad.c + gst/gstpad.h + gst/gstplugin.h + libs/gst/base/gstbaseparse.c + +2011-05-18 14:10:12 +0300 Stefan Kost + + * tests/examples/manual/Makefile.am: + manual: reinsert missing space to fix previous commit + +2011-05-18 13:54:42 +0300 Stefan Kost + + * tests/examples/manual/Makefile.am: + manual: simplify the snipet extraction rules + Use $< instead of repeating the name of the dependency. + +2011-05-18 10:59:38 +0300 Stefan Kost + + * tests/examples/manual/Makefile.am: + manual: don't extract the xml example anymore, its gone + As a followup for commit cda5a353d27326c0272a79c92c11c221a4092da4 don't try + extracting an example that has been removed. + +2011-05-18 12:23:39 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 46dfcea to fd35073 + +2011-05-18 11:21:52 +0200 Wim Taymans + + * docs/design/part-events.txt: + docs: update docs some more + +2011-05-18 11:08:52 +0200 Wim Taymans + + * docs/design/part-events.txt: + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: rework sticky events a little + Update the design docs with some clear rules for how sticky events are + handled. + Reimplement the sticky tags, use a small structure to hold the event and its + current state (active or inactive). + Events on sinkpads only become active when the event function returned success + for the event. + When linking, only update events that are different. + Avoid making a copy of the event array, use the object lock to protect the event + array and release it only to call the event function. This will need to check + if something changed, later. + Disable a test in the unit test, it can't work yet. + +2011-05-17 22:17:14 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: maintain frame state during frame parsing round + See #650093. + +2011-05-12 11:55:20 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: provide latency query support + +2011-05-17 22:15:38 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: make minimum frame size handling more efficient and convenient + While some formats allow subclass to determine a specific subsequent + needed frame size, others may to need to scan for markers and can only + request 'additional data' by whatever reasonable available step. + In push mode, trying to minimize additional latency leads to step size + being the next input buffer. In pull mode, any reasonable step size + (such as already used by buffer caching) can be applied. + +2011-05-17 22:38:14 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbaseparse.c: + baseparse: set correct buffer size + +2011-05-06 10:54:08 +0300 Stefan Kost + + * tools/gst-inspect.c: + inspect: show flags the same way they need to be entered + The (de)serialisation uses "+" and not " | ". + +2011-04-28 11:34:39 +0300 Stefan Kost + + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * gst/gstregistrychunks.c: + pluginfeature: avoid duplicating feature->name + The feature name is not supposed to change over time anyway. In order to enforce + this parentize features to the registry and make the feature->name pointing to + GstObject:name. In 0.11 we could consider of removing the feature->name variable + (FIXME comment added). + Fixes: #459466 + +2011-05-02 15:36:14 +0300 Stefan Kost + + * gst/gst_private.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstplugin.h: + docs: add deprecation guards + Move GstPadIntLinkFunction to private header to avoid a dozen #ifdefs. Use a + gpointer in public header instead. + +2011-05-17 19:03:30 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't push sticky events on flush + Only allow serialized and non-flush events forward the sticky events. + +2011-05-17 18:23:22 +0200 Wim Taymans + + * tests/check/gst/gstghostpad.c: + test: reset pad caps properly + +2011-05-17 18:23:06 +0200 Wim Taymans + + * gst/gstpad.c: + pad: add more debug + +2011-05-17 18:21:38 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: remove unused code + The code to make sure that caps are properly set on both pads, it now happens + automatically with the caps event. + +2011-05-17 17:53:00 +0200 Wim Taymans + + * tests/check/gst/gstsegment.c: + tests: fix tests + Remove the tests that handle incompatible formats, we don't want that anymore. + +2011-05-17 17:51:58 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: handle wraparound better + Now that we use unsigned values for the segment, handle wraparound when seeking + better. + +2011-05-17 16:50:53 +0200 Wim Taymans + + * tests/check/gst/gstpad.c: + pad: remove unref, the object is NULL + +2011-05-17 14:01:05 +0200 Sebastian Dröge + + * gst/gstevent.c: + * gst/gstevent.h: + event: The RECONFIGURE element only exists in 0.11 + Implementing it properly in 0.10 seems to be impossible. + +2011-05-17 13:13:11 +0200 Sebastian Dröge + + * tests/check/elements/selector.c: + * tests/check/elements/valve.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + tests: Update for caps/pad template related API changes + +2011-05-17 12:25:22 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + base: Update for caps/pad template related API changes + +2011-05-17 12:04:27 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstutils.c: + gst: Update for caps/pad template related API changes + +2011-05-17 12:12:23 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstelement.c: + element: Consider GstPadTemplate as immutable + Don't copy the templates when creating subclasses but only increase + their refcount. + +2011-05-17 12:10:27 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstelement.c: + * gst/gstpadtemplate.c: + padtemplate: Create pad templates with floating refs + And take ownership of the floating ref in gst_element_add_pad_template() + +2011-05-17 12:07:03 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstpadtemplate.c: + padtemplate: Improve reference handling of the template's caps + gst_pad_template_new() does not take ownership of the caps anymore. + +2011-05-16 13:39:25 +0100 Tim-Philipp Müller + + * gst/gstminiobject.c: + miniobject: delay private data initialisation until actually needed + We only use the private instance data for weak references for now, + so can delay initialisation until actually needed (microoptimisation) + +2011-05-17 11:59:00 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + pad: Let template related functions return new references + gst_pad_template_get_caps(), gst_pad_get_pad_template_caps() + and gst_pad_get_pad_template() return a new reference of the + caps or template now and the return value needs to be + unreffed after usage. + +2011-05-17 11:45:46 +0200 Sebastian Dröge + + * gst/gstevent.c: + * tests/check/gst/gstevent.c: + Revert "event: example of how to optimize events" + This reverts commit fa28e2c5e6e5e172be308c0c50f44ed6f39e1a71. + The optimization only has minimal impact on the performance and + makes everything more complex. + +2011-05-17 11:45:42 +0200 Sebastian Dröge + + * gst/gstevent.c: + Revert "event: update the structure when needed" + This reverts commit 905100cdbe580d4d182bfd9d5ec9b368a110f464. + +2011-05-17 11:22:58 +0200 Sebastian Dröge + + * gst/gststructure.c: + structure: Fix compilation + +2011-05-17 11:20:05 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesrc.c: + * tests/check/gst/gstquery.c: + Revert "query: allow _make_writable on query handlers" + This reverts commit cf4fbc005c5c530c2a509a943a05b91d6c9af3fb. + This change did not improve the situation for bindings because + queries are usually created, then directly passed to a function + and not stored elsewhere, and the writability problem with + miniobjects usually happens with buffers or caps instead. + +2011-05-17 11:19:16 +0200 Sebastian Dröge + + * gst/gstbin.c: + Revert "bin: Dereference GstQuery** before passing it to GST_QUERY_TYPE_NAME" + This reverts commit 437c92b403e0c7da9b9d4509ef4ffbd05710df2b. + +2011-05-17 11:19:14 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + Revert "ghostpad: fix g_return_* with new query" + This reverts commit 877c1c28ff957ca92911eadfc785f8661d9e0127. + +2011-05-17 09:40:38 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + win32/common/libgstreamer.def + +2011-05-17 09:35:54 +0200 Sebastian Dröge + + * gst/gststructure.c: + * gst/gststructure.h: + structure: Make both parameters to gst_structure_is_equal() const + +2011-05-17 09:33:47 +0200 Sebastian Dröge + + * gst/gststructure.c: + structure: Update Since markers to the correct version + +2011-05-17 09:33:04 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: Add gst_structure_intersect() + API: gst_structure_intersect() + +2010-09-10 18:33:34 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + gststructure: Add gst_structure_can_intersect API + Allows checking if two structures can intersect without having to + go through GstCaps + API: gst_structure_can_intersect + https://bugzilla.gnome.org/show_bug.cgi?id=629300 + +2010-09-10 18:14:05 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + gstructure: New API: gst_structure_is_equal + Allows checking equality of GstStructure without having to create + intermediary GstCaps. + API: gst_structure_is_equal + https://bugzilla.gnome.org/show_bug.cgi?id=629300 + +2011-05-16 19:09:54 +0200 Wim Taymans + + * tests/check/gst/gstutils.c: + tests: set elements in PAUSED + Set elements in PAUSED before trying to set caps on pads. + +2011-05-16 19:05:23 +0200 Wim Taymans + + * tests/check/gst/gstghostpad.c: + test: fix ghostpad test + We need to have activated pads before we can pass around caps. + Don't set NULL caps on pads. + +2011-05-16 19:04:35 +0200 Wim Taymans + + * gst/gstpad.c: + pad: avoid setting NULL caps on pads + +2011-05-16 18:48:20 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix buffer refcounting + When we fail to allocate an output buffer, set the buffer pointer to NULL or + else the calling function will try to unref it. + Remove some old comments + +2011-05-16 18:29:29 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: allow NULL filters and fix refcounting + +2011-05-16 18:12:33 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: only add the structure when we could set the parent + +2011-05-16 17:53:48 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: fix g_return_* with new query + +2011-05-16 17:24:11 +0200 Sebastian Dröge + + * win32/common/libgstreamer.def: + win32: Update list of exported symbols + +2011-05-16 16:59:20 +0200 Wim Taymans + + * plugins/elements/gstinputselector.c: + inputselector: handle more formats + Use the segment format instead of a hardcoded _TIME. + +2011-05-16 16:57:48 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: handle more formats + Don't hardcode GST_FORMAT_TIME in places, we can work with many formats. + +2011-05-16 16:54:02 +0200 Sebastian Dröge + + Merge branch '0.11' of ssh://git.freedesktop.org/git/gstreamer/gstreamer into 0.11 + +2011-05-16 16:53:04 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + docs/gst/gstreamer-sections.txt + gst/gstbin.c + gst/gstelement.c + gst/gstelement.h + gst/gstghostpad.c + gst/gstminiobject.c + gst/gstminiobject.h + libs/gst/base/gstbasesrc.c + libs/gst/base/gstbasetransform.c + plugins/elements/gstinputselector.c + tests/check/gst/gstminiobject.c + +2011-05-16 16:10:49 +0200 Wim Taymans + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/highlevel-components.xml: + update manual code examples for new _get_caps() + +2011-05-13 08:34:33 +0200 Sebastian Dröge + + * tests/check/elements/multiqueue.c: + * tests/check/elements/selector.c: + * tests/check/elements/valve.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstutils.c: + * tests/check/libs/test_transform.c: + * tests/check/libs/transform1.c: + tests: Update for negotiation related API changes + +2011-05-11 15:38:09 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstvalve.c: + elements: Update for negotiation related API changes + The filter caps are only forwarded and returned instead + of ANY caps in the core elements because they don't do + anything caps specific. + +2011-05-11 15:12:04 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + base: Improve negotiation with new getcaps() filter + +2011-05-10 17:56:33 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + gst: Add a filter caps parameter to all get_caps() functions + This is used to pass the possible caps and preferences to + the pad and to allow better negotiation decisions. + +2011-04-19 20:05:07 +0200 Mark Nauwelaerts + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: adjust input data rate estimation + ... being aware of possible initial higher burst rate. + +2011-05-13 18:07:24 +0200 Wim Taymans + + * docs/plugins/gstreamer-plugins.args: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstinfo.c: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstsegment.c: + * gst/gstsegment.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/filesink.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstinfo.c: + * tests/check/gst/gstsegment.c: + * tests/check/libs/basesrc.c: + Rework GstSegment handling + Improve GstSegment, rename some fields. The idea is to have the GstSegment + structure represent the timing structure of the buffers as they are generated by + the source or demuxer element. + gst_segment_set_seek() -> gst_segment_do_seek() + Rename the NEWSEGMENT event to SEGMENT. + Make parsing of the SEGMENT event into a GstSegment structure. + Pass a GstSegment structure when making a new SEGMENT event. This allows us to + pass the timing info directly to the next element. No accumulation is needed in + the receiving element, all the info is inside the element. + Remove gst_segment_set_newsegment(): This function as used to accumulate + segments received from upstream, which is now not needed anymore because the + segment event contains the complete timing information. + +2011-05-16 10:25:10 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Re-implement notify::caps + +2011-05-14 14:02:06 +0100 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.args: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + docs: fix up some Since markers and update for new multiqueue args + +2011-05-12 16:48:41 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Don't interprete pipelines without sink elements as always being in EOS state + Some tests (e.g. elements/capsfilter) have pipelines with dangling + sinkpads and without a sink element. These pipelines can never post + an EOS message (because this is only valid by a sink) and as such + should never get an EOS message posted by the bin. + +2011-05-12 15:51:22 +0200 Sebastian Dröge + + * gst/gstsystemclock.c: + systemclock: Only retry writing to the socket for EAGAIN, EWOULDBLOCK and EINTR + Fixes infinite loop in some cases, bug #650002. + +2011-05-12 09:59:20 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + miniobject: Add new miniobject weak ref/unref functions to the docs + +2011-05-12 09:55:45 +0200 Sebastian Dröge + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + miniobject: Minor cleanup of last commit + +2011-05-11 13:09:19 -0400 José Alburquerque + + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * tests/check/gst/gstminiobject.c: + miniobject: Add weak referencing functionality + API: gst_mini_object_weak_ref() + API: gst_mini_object_weak_unref() + Add weak referencing functionality to GstMiniObject, which + allows to get notifications when an mini object is destroyed + but doesn't increase the real refcount. This is mostly + useful for bindings. + Fixes bug #609473. + +2011-03-19 10:28:49 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: Add sync mode that syncs inactive pads to the running time of the active pad + Fixes bug #645017. + +2011-03-22 13:19:47 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Add mode to synchronize deactivated/not-linked streams by the running time + Fixes bug #645107, #600648. + +2011-04-18 14:26:33 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Only post EOS messages after reaching the PLAYING state + Fixes bug #647756. + +2011-05-10 16:37:44 +0200 Sebastian Dröge + + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + element: Add GstElement::state_changed vfunc + API: GstElement::state_changed + This is always called when the state of an element has changed and + before the corresponding state-changed message is posted on the bus. + +2011-05-06 16:44:29 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * win32/common/libgstreamer.def: + ghostpad: Add docs for all the new, public functions + +2011-05-06 16:15:51 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: Add guards against invalid parameters to the new, public functions + +2011-05-06 16:00:22 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * win32/common/libgstreamer.def: + ghostpad: Rename ghostpad/proxypad default functions + API: gst_ghost_pad_activate_pull_default + API: gst_ghost_pad_activate_push_default + API: gst_ghost_pad_internal_activate_pull_default + API: gst_ghost_pad_internal_activate_push_default + API: gst_ghost_pad_link_default + API: gst_ghost_pad_setcaps_default + API: gst_ghost_pad_unlink_default + API: gst_proxy_pad_acceptcaps_default + API: gst_proxy_pad_bufferalloc_default + API: gst_proxy_pad_chain_default + API: gst_proxy_pad_chain_list_default + API: gst_proxy_pad_checkgetrange_default + API: gst_proxy_pad_event_default + API: gst_proxy_pad_fixatecaps_default + API: gst_proxy_pad_getcaps_default + API: gst_proxy_pad_getrange_default + API: gst_proxy_pad_iterate_internal_links_default + API: gst_proxy_pad_query_default + API: gst_proxy_pad_query_type_default + API: gst_proxy_pad_setcaps_default + +2011-05-06 15:50:20 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + * gst/gstghostpad.h: + ghostpad: Make all the internal caps functions public + This is useful if ghostpad/proxypads should be used but + additional code should be executed, e.g. for tracking + segments in the event function. + +2011-05-06 15:25:04 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: Only implement the iterate_internal_links function on proxypads + ghostpads inherit it from their parent class. Also make it threadsafe. + +2011-05-06 15:16:09 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + * tests/check/gst/gstghostpad.c: + * win32/common/libgstreamer.def: + ghostpad: API: Expose gst_proxy_pad_get_internal() + This allows to get the internal pad of ghostpads and + proxypads without using gst_pad_iterate_internal_links() + and is much more convenient. + The internal pad of a ghostpad is the pad of the opposite direction + that is used to link to the ghostpad target. + +2011-05-05 17:54:56 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: When trying to fixate the sink suggestion prefer its structure order + +2011-05-05 11:28:38 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + caps: Merge structures when intersecting instead of appending them + This prevents adding duplicates over and over again to the resulting + caps if they already describe the new intersection result. + While this changes intersection from O(n*m) to O(n^2*m), it results in + smaller caps, which in the end will decrease further processing times. + For example in an audioconvert ! audioconvert ! audioconvert pipeline, + when forwarding the downstream caps preference in basetransform + (see e26da72de25a91c3eaad9f7c8b2f53ba888a0394) this results in + 16 instead of 191 caps structures. + +2011-05-04 11:29:15 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: In getcaps() prefer the caps order and caps of downstream if possible + +2011-05-03 17:26:53 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Prefer caps order given by the subclass of the template caps order + +2011-04-20 22:52:36 +0200 Miguel Angel Cabrera Moya + + * gst/parse/types.h: + * tests/check/pipelines/parse-launch.c: + parse: don't unescape inside quotes + Escaped characters inside quoted strings are supposed to be unescaped by + deserialization functions, not by parsing functions. + https://bugzilla.gnome.org/show_bug.cgi?id=648025 + +2011-04-18 10:04:24 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Remove unnecessary FIXME + Resetting the result is not necessary when resyncing because + pads that previously got the event will be skipped and we + need to consider the results of the previous pushes. + +2011-04-18 09:53:55 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: If activating one pad failed error out early instead of trying to activate the next pads + If one pad fails to activate the complete activation process will fail + anyway and trying to activate the other pads only wastes time. + +2011-04-18 09:49:04 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: If activating one pad failed error out early instead of trying to activate the next pads + If one pad fails to activate the complete activation process will fail + anyway and trying to activate the other pads only wastes time. + +2011-05-14 09:31:33 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development + +=== release 0.10.34 === + +2011-05-14 01:00:23 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.34 + +2011-05-13 08:38:06 +0200 Sebastian Dröge + + * tests/check/gst/gstmeta.c: + meta: Fix compilation of the unit test after removal of the serialize/deserialize functions + +2011-05-04 15:31:56 +0300 Vincent Penquerc'h + + * libs/gst/base/gstbasesrc.c: + basesrc: do not set first buffer timestamp to 0 for live sources + Doing so avoids a large timestamp gap between first and second buffer + for live sources which take time to start up. + The first buffer now has a "live" timestamp based on the running time, + as other buffers do. + https://bugzilla.gnome.org/show_bug.cgi?id=649369 + +2011-05-11 19:10:24 +0200 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: remove (de)serialize functions + Add a GType to the metadata to identify the GstMetaInfo. + We can remove the (de)serialize functions for the metadata because we can + register GTtype transform functions between various types to implement + serialization later. + +2011-05-11 18:17:45 +0200 Wim Taymans + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gststructure.c: + * gst/gststructure.h: + structure: more cleanups + gst_structure_get_type() -> _gst_structure_type to avoid method calls for + getting the GType that initialized at the start. + Hide some structure fields in private data so that we can change the + implementation. + Move structure equality check from caps.c to structure.c where it belongs. + +2011-05-11 18:07:23 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: remove obsolete code + Remove some obsolete code. + Don't try to reconfigure when we don't have sink caps. + +2011-05-11 16:46:49 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Dereference GstQuery** before passing it to GST_QUERY_TYPE_NAME + +2011-05-11 16:03:40 +0200 Wim Taymans + + * gst/gstevent.c: + event: update the structure when needed + When we get the structure of an event, make sure it also contains the fields + that we keep in fast variables, this way we can easily serialize and debug + the events. We would probably later simply prefer to register a transform + function to G_TYPE_STRING and G_TYPE_BYTEARRAY etc.. + +2011-05-11 16:01:41 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: cleanups + We don't need to check if the type is 0, the init function is only called once + in the beginning. + +2011-05-11 12:04:43 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + event: clean up some macros + Avoid executing a method for GST_TYPE_EVENT but instead use the type variable + directly. We can do this because we register it before anything else. + +2011-05-11 15:48:15 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Fix GST_DEBUG parameters to be consistent with the format string + +2011-05-11 15:26:02 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Implement support for pad reconfiguration again + +2011-05-11 15:18:56 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + capsfilter: Fix deadlock, gst_pad_get_current_caps() already takes the pad's object lock + +2011-05-11 11:06:36 +0200 Wim Taymans + + * gst/gstevent.c: + * tests/check/gst/gstevent.c: + event: example of how to optimize events + Use a structure for the QoS event by 'extending' the GstEventImpl structure. + This should avoid allocation of GstStructures and its contents. + +2011-05-10 11:11:15 +0200 Mark Nauwelaerts + + * plugins/elements/gstmultiqueue.c: + multiqueue: ensure thread safety when adding a pad + This seems to be a regression, and was causing crashes. + https://bugzilla.gnome.org/show_bug.cgi?id=649878 + +2011-05-10 18:36:33 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/filesrc.c: + * tests/check/gst/gstquery.c: + query: allow _make_writable on query handlers + Pass a GstQuery ** to the query handlers so that they can make the query + writable before using a setter on it. + Port code to new API. + +2011-05-10 16:46:15 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting doc + +2011-05-10 16:41:36 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gsttee.c: + element: use request_new_pad_full as the default + Add GstCaps to request_new_pad so that request_new_pad_full can be removed. + Fix elements. + +2011-05-10 16:23:08 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting doc + +2011-05-10 15:41:54 +0200 Wim Taymans + + * gst/gstquery.c: + query: make sure query is writable + Make sure the Query is writable before executing the setters. + +2011-05-10 15:33:53 +0200 Wim Taymans + + * gst/gstinfo.c: + * gst/gstquery.c: + * gst/gstquery.h: + * tests/check/gst/gstquery.c: + query: Hide GstStructure in queries + Hide the GstStructure from the query API. + Rename some methods to match the more common names in GObject libraries. + Add some more useful query API. + +2011-05-10 13:34:10 +0200 Wim Taymans + + * gst/gstbus.c: + * gst/gstinfo.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * plugins/elements/gstfakesink.c: + message: hide the message structure field + Make a private structure to hold the GstStructure bits of the message. + Add some more useful macros like we have for events. + +=== release 0.10.33 === + +2011-05-10 08:55:10 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.33 + Highlights: + - new parser base class: GstBaseParse + - new core element: funnel + - OSX multi-arch fixes + - new QoS type for QoS events + - new progress message API to notify applications of asynchronous operations + - countless other fixes and improvements + +2011-05-10 12:29:06 +0200 Wim Taymans + + * gst/gstcaps.h: + caps: fix the macros a little + +2011-05-10 11:50:16 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstinfo.c: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/dataprotocol/dataprotocol.c: + event: Hide the GstStructure + Hide the GstStructure of the event in the implementation specific part so that + we can change it. + Add methods to check and make the event writable. + Add a new method to get a writable GstStructure of the element. + Avoid directly accising the event structure. + +2011-05-09 18:48:55 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstevent.c: + event: _qos_full -> _qos + +2011-05-09 17:51:07 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstsegment.c: + * gst/gstsegment.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * tests/check/elements/fakesink.c: + * tests/check/elements/filesink.c: + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstinfo.c: + * tests/check/gst/gstsegment.c: + * tests/check/libs/basesrc.c: + segment: remove _full version + Rename the _full versions of the functions to the normal function names. + +2011-05-09 16:39:13 +0200 Wim Taymans + + * gst/gstsegment.c: + * gst/gstsegment.h: + * libs/gst/base/gstbasesink.c: + * plugins/elements/gstinputselector.c: + segment: remove abs_rate from segment structure + Remove the abs_rate field from the segment structure, we can trivially compute + it when needed. + +2011-05-09 16:21:28 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstghostpad.c: + * tests/check/libs/transform1.c: + caps: remove caps from buffers and pads + Remove the GstCaps from buffers and pads. We now use CAPS events to negotiate + formats between element. + +2011-05-09 15:06:20 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: Use CAPs event + Use the caps event to configure basetransform. + Remove force_alloc hack, we don't need this in 0.11 with new upstream + negotiation. + Avoid getting some pad caps. + +2011-05-09 15:06:07 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add some more debug + +2011-05-08 11:02:16 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Add new symbols + +2011-05-08 11:01:57 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: Fix unitialized variables + +2011-05-09 10:54:10 +0200 Wim Taymans + + * gst/gstutils.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + tools: avoid using pad caps + Avoid directly accessing the pad caps, use gst_pad_get_current_caps() instead. + +2011-05-08 13:14:55 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-05-08 13:07:13 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: use CAPS event instead of setcaps function + +2011-05-08 12:46:17 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstpad.c: + * tools/gst-launch.c: + base: avoid using buffer caps + Comment all code using buffer caps. + Rework capsfilter code a little. + Fix some unit tests + +2011-05-08 12:43:26 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve caps event handling + Fix replace of caps events when linking: we need to unref the old ones. + Make sure we pass error values around. + Move backward compat code into the default handler for now. + +2011-05-08 12:38:05 +0200 Wim Taymans + + * gst/gstevent.c: + event: don't ref the caps + Use a different way of getting the caps from the caps event so that no + refcounting happens. + +2011-05-08 12:37:44 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: avoid using buffer caps + +2011-05-06 23:40:58 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: don't post loads of empty taglists + Only post bitrate updates if there's something to post, don't + post empty taglists if nothing changed. + +2011-05-06 19:04:54 +0200 Wim Taymans + + * gst/gstghostpad.c: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + pad: avoid using the old GST_PAD_CAPS + Don't use GST_PAD_CAPS but instead use the new gst_pad_get_current_caps() + method. + Avoid setting caps on buffers. + +2011-05-06 19:03:33 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: add 2 new caps methods + Add method to get the currently configured caps on the pad. + Add a method to check if caps are configured on a pad. + +2011-05-06 17:59:33 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + pad: implement fixed caps with an object flag + Implement fixed caps with an object flag instead of a custom getcaps function. + +2011-05-06 17:30:24 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't use buffer caps for negotiation + Don't use the buffer caps for negotiation anymore but use the CAPS events. + Make the _set_caps method produce the CAPS event, add some backward + compatibility code to trigger the setcaps functions on src and sinkpads. + Remove all negotiation code from the chain functions. + Don't use the GST_PAD_CAPS variable anymore to store the caps but retrieve the + caps from the sticky event array. + +2011-05-06 16:14:41 +0200 Wim Taymans + + * tests/check/elements/selector.c: + selector: don't unset caps + +2011-05-06 16:14:23 +0200 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefind: don't unset caps + +2011-05-06 16:13:55 +0200 Wim Taymans + + * libs/gst/check/gstcheck.c: + check: let the normal code unset caps + +2011-05-06 16:11:44 +0200 Wim Taymans + + * plugins/elements/gstoutputselector.c: + outputselector: handle NULL pads in some cases + +2011-05-06 16:11:18 +0200 Wim Taymans + + * gst/gstbin.c: + bin: let the pad clean up in activate + +2011-05-06 15:55:31 +0200 Wim Taymans + + * gst/gstelement.c: + element: don't mess with pad caps in activate + When deactivating a pad, let the pad decide what fields to clear. + +2011-05-06 15:51:11 +0200 Wim Taymans + + * gst/gstevent.c: + event: only allow fixed caps in caps event + +2011-05-06 13:01:24 +0200 Sebastian Dröge + + * gst/gstevent.c: + event: Improve documentation of gst_event_new_reconfigure() + +2011-05-06 12:23:01 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting doc + +2011-05-06 12:19:16 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstelement.h: + * libs/gst/base/gstbasesink.c: + * win32/common/libgstreamer.def: + element: rename gst_element_lost_state_full() + Rename gst_element_lost_state_full() to gst_element_lost_state() and + remove the old method name. + +2011-05-06 12:09:00 +0200 Wim Taymans + + * gst/gstpad.h: + pad: clean up the .h file a bit + +2011-05-06 11:14:02 +0200 Wim Taymans + + * gst/Makefile.am: + * gst/gst.c: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + pad: implement more sticky events + Remove the context again, adding an extra layer of refcounting and object + creation to manage an array is too complicated and inefficient. Use a simple + array again. + Also implement event updates when calling gst_pad_chain() and + gst_event_send_event() directly. + +2011-05-06 11:35:36 +0300 Stefan Kost + + * gst/gstinfo.h: + info: avoid redefinition of symbols when debugging is off + The refactoring of gst_debug_add_log_function() now causes build failure when + debug-logging is turned off. Just move it to the conditional part of the header. + +2011-05-06 11:00:18 +0200 Wim Taymans + + * gst/gstevent.h: + event: reorder events + Reorder the sticky events so that they are in the order they should be pushed. + +2011-05-05 19:24:46 +0200 Wim Taymans + + * gst/gstpad.c: + pad: simplify some more + If we get a context in the chain functions we always need to do a full update of + the context on the peer pad. + +2011-05-05 18:56:41 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve context passing some more + Pass the context downstream when it got updated. + Have two ways of informing downstream of events, do a full context update when + the CONTEXT_PENDING flag is set and simply forward the event otherwise. + Set the CONTENT_PENDING flag when linking pads. + We don't need to old context anymore when updating the context of a pad. + +2011-05-05 18:21:21 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Don't get the parent twice in the setcaps function + +2011-05-05 16:59:36 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix refcount leak of the parent in the default event dispatch function + +2011-05-05 16:32:11 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: improve passing around the context + Improve passing around the context, only send the context to the peer element + when the CONTEXT_PENDING flag is set. + +2011-05-05 16:05:20 +0200 Sebastian Dröge + + * win32/common/libgstreamer.def: + win32: Update exports + +2011-03-17 11:52:42 +0100 Sebastian Dröge + + * tests/check/elements/tee.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstiterator.c: + tests: Update for new GstIterator API + +2011-03-17 11:32:24 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + docs/def: Add new symbols, remove old symbols + +2011-03-17 11:32:11 +0100 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gsttee.c: + elements: Update everything for the new GstIterator API + +2011-03-17 11:31:59 +0100 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstquery.c: + * gst/gstutils.c: + * gst/gstvalue.c: + gst: Update everything for the new GstIterator API + +2011-03-16 10:50:39 +0100 Sebastian Dröge + + * gst/gstiterator.c: + * gst/gstiterator.h: + * gst/gstplugin.c: + iterator: Refactor GstIterator to be more binding friendly and have saner refcounting + Fixes bug #638987. + +2011-01-08 12:27:55 -0200 Johan Dahlin + + * gst/gstiterator.c: + * gst/gstiterator.h: + iterator: register as a boxed type + https://bugzilla.gnome.org/show_bug.cgi?id=638987 + +2011-01-08 12:14:40 -0200 Johan Dahlin + + * gst/gstiterator.c: + iterator: use GSlice + https://bugzilla.gnome.org/show_bug.cgi?id=638987 + +2011-01-08 12:12:41 -0200 Johan Dahlin + + * gst/gstbin.c: + * gst/gstiterator.c: + iterator: free struct in gst_iterator_free + https://bugzilla.gnome.org/show_bug.cgi?id=638987 + +2011-01-08 12:07:55 -0200 Johan Dahlin + + * gst/gstiterator.c: + * gst/gstiterator.h: + iterator: store size in the struct + https://bugzilla.gnome.org/show_bug.cgi?id=638987 + +2011-05-05 11:28:38 +0200 Sebastian Dröge + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + caps: Merge structures when intersecting instead of appending them + This prevents adding duplicates over and over again to the resulting + caps if they already describe the new intersection result. + While this changes intersection from O(n*m) to O(n^2*m), it results in + smaller caps, which in the end will decrease further processing times. + For example in an audioconvert ! audioconvert ! audioconvert pipeline, + when forwarding the downstream caps preference in basetransform + (see e26da72de25a91c3eaad9f7c8b2f53ba888a0394) this results in + 16 instead of 191 caps structures. + +2011-05-04 11:29:15 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: In getcaps() prefer the caps order and caps of downstream if possible + +2011-05-03 17:26:53 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Prefer caps order given by the subclass of the template caps order + +2011-05-03 14:13:59 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Use the reconfigure flag on the pad instead of the event + +2011-05-03 14:11:34 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Use new reconfigure flag on the pads instead of the reconfigure event + +2011-05-03 13:42:44 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Keep track of reconfigure events and the pad-needs-reconfiguring status + +2011-05-03 13:05:06 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + event: Rename renegotiate event to reconfigure + In 0.11 this event will also do reconfiguration of buffer pools + and similar things, not just renegotiation. + +2010-03-17 21:24:55 +0000 Olivier Crête + + * gst/gstpad.c: + pad: Send renegotiate event on link + +2010-03-17 21:17:10 +0000 Olivier Crête + + * gst/gstpad.c: + pad: Drop renegotiate event if there is no getcaps function on a sink pad + If there is no custom getcaps function on a sink pad, then changes in + downstream caps will never be propagated, so there is no point in trying to + renegotiate the capabilities. + +2011-04-26 16:39:56 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Only renegotiate once after receiving a renegotiate event + Also make this threadsafe. + +2011-01-17 14:13:46 -0300 Thiago Santos + + * libs/gst/base/gstbasesrc.c: + basesrc: Handle the new renegotiate event + Makes basesrc handle the new renegotiate event by using a + renegotiate flag. + +2011-04-26 16:48:05 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Also call gst_base_transform_reconfigure() on renegotiate events + +2011-01-17 14:13:46 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: Handle the new renegotiate event + Let basetransform push a renegotiate event upstream + when it gets a new suggestion + +2011-01-17 11:51:49 -0300 Thiago Santos + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + event: Adding new renegotiate event + +2011-05-05 13:10:42 +0200 Wim Taymans + + * gst/gstpad.c: + pad: pass the context around + Pass the context from srcpad to sinkpad before dataflow when something + changed. + +2011-05-05 11:17:20 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: update the context lazyly + +2011-05-05 11:16:48 +0200 Wim Taymans + + * gst/gst.c: + gst: init the GType early + +2011-05-05 11:16:23 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update defs + +2011-05-05 10:40:14 +0200 Wim Taymans + + * gst/gstcontext.c: + * gst/gstcontext.h: + context: add foreach function + Add a function to iterate over all stored events. + +2011-05-05 10:37:19 +0200 Wim Taymans + + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstevent.h: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstpad.c: + * tests/check/libs/transform1.c: + * tools/gst-launch.c: + Revert "context: use context on buffers instead of caps" + This reverts commit 9ef1346b1fa0bd2bb42cd991a52ff308a728bdb6. + Way to much for one commit and I'm not sure we want to get rid of the pad caps + just like that. It's nice to have the buffer and its type in onw nice bundle + without having to drag the complete context with it. + +2011-04-20 22:52:36 +0200 Miguel Angel Cabrera Moya + + * gst/parse/types.h: + * tests/check/pipelines/parse-launch.c: + parse: don't unescape inside quotes + Escaped characters inside quoted strings are supposed to be unescaped by + deserialization functions, not by parsing functions. + https://bugzilla.gnome.org/show_bug.cgi?id=648025 + +2011-04-18 14:26:33 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Only post EOS messages after reaching the PLAYING state + Fixes bug #647756. + +2011-04-18 10:04:24 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Remove unnecessary FIXME + Resetting the result is not necessary when resyncing because + pads that previously got the event will be skipped and we + need to consider the results of the previous pushes. + +2011-04-18 09:53:55 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: If activating one pad failed error out early instead of trying to activate the next pads + If one pad fails to activate the complete activation process will fail + anyway and trying to activate the other pads only wastes time. + +2011-04-18 09:49:04 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: If activating one pad failed error out early instead of trying to activate the next pads + If one pad fails to activate the complete activation process will fail + anyway and trying to activate the other pads only wastes time. + +2011-05-05 12:28:02 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Remove nowadays unused and uninitialized setcaps variable + +2011-05-05 12:27:51 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + docs/gst/gstreamer-sections.txt + gst/gstelementfactory.c + gst/gstminiobject.c + +2011-05-04 18:59:47 +0200 Wim Taymans + + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstevent.h: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/check/gstcheck.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/elements/selector.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstpad.c: + * tests/check/libs/transform1.c: + * tools/gst-launch.c: + context: use context on buffers instead of caps + Put the srcpad context on buffers instead of caps. This allows us to associate + all the relevant info contained in events with a buffer. + +2011-05-04 15:29:42 +0100 Tim-Philipp Müller + + * tests/check/gst/gstminiobject.c: + tests: fix compiler warning in new miniobject test + gst/gstminiobject.c: In function ‘test_dup_null_mini_object’: + gst/gstminiobject.c:459:7: warning: assignment from incompatible pointer type + +2011-05-04 15:53:21 +0200 Wim Taymans + + * gst/gstcontext.h: + * gst/gstevent.c: + * gst/gstpad.c: + * gst/gstpad.h: + pad: use the context to store sticky events + Store the sticky events in the context of a source pad. + +2011-05-04 15:20:10 +0200 Wim Taymans + + * gst/Makefile.am: + * gst/gstcontext.c: + * gst/gstcontext.h: + * gst/gstevent.h: + context: add helper object to manage events + Add a helper object to manage the events that define the context of a buffer and + a stream. + +2011-05-04 11:07:19 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update defs + +2011-05-04 11:03:05 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + event: add new CAPS event + Add a new CAPS event that will be used to negotiate downstream elements. It'll + also stick on pad so that we can remove the GstCaps field on pads and the + GstCaps field on buffers. + +2011-05-03 18:58:18 +0200 Wim Taymans + + * gst/gstevent.h: + * gst/gstpad.c: + * gst/gstpad.h: + pad: more sticky events work + Copy the sticky events from the srcpad to the sinkpad when linking pads. Set the + STICKY_PENDING flag to make sure that the sticky events are dispatched before + pushing the next buffer to the element. + +2011-05-03 16:11:12 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: improve porting doc + +2011-05-02 18:45:24 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting document + +2011-05-02 11:30:06 -0300 Thiago Santos + + * gst/gstminiobject.c: + * tests/check/gst/gstminiobject.c: + miniobject: Fix dup_mini_object function to handle NULL gvalues + g_value_dup_object handles gvalues that contain NULL pointers, + gst_value_dup_mini_object should do the same. + https://bugzilla.gnome.org/show_bug.cgi?id=649195 + +2011-05-03 13:55:43 +0300 Stefan Kost + + * libs/gst/base/gstbaseparse.c: + docs: it its %TRUE (constant) + As spotted by Tim. + +2011-05-02 16:22:56 +0300 Stefan Kost + + * gst/gstelementfactory.c: + docs: fix copy'n'paste doc header mistake + +2011-05-02 16:20:24 +0300 Stefan Kost + + * gst/gstelement.h: + * gst/gstpluginfeature.h: + docs: add two trivial doc blobs + +2011-05-02 16:03:29 +0300 Stefan Kost + + * libs/gst/base/gstbaseparse.c: + docs: add missing parameter docs + +2011-05-02 16:00:52 +0300 Stefan Kost + + * libs/gst/dataprotocol/dataprotocol.h: + docs: add docs for GstDPPacketizer + +2011-05-02 15:52:58 +0300 Stefan Kost + + * gst/gstcaps.h: + docs: improve the syntax for the capsintersectmode docs + +2011-05-02 15:48:01 +0300 Stefan Kost + + * gst/gstelement.c: + docs: fixup broken xref + +2011-05-02 15:46:59 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + docs: add new api to -section.txt + +2011-05-02 15:35:52 +0300 Stefan Kost + + * gst/gstatomicqueue.h: + docs: fix gtk-doc syntax + +2011-05-02 15:30:13 +0300 Stefan Kost + + * plugins/elements/gstfunnel.c: + docs: don't duplicate info that we take from element-details + +2011-04-28 15:37:02 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + docs: remove non existing symbol + +2011-04-28 15:05:28 +0300 Stefan Kost + + * gst/gstbufferlist.c: + * gst/gstsystemclock.h: + docs: we don't need to document private members in opaque structs + +2011-04-29 13:43:07 +0200 Philippe Normand + + * docs/random/porting-to-0.11.txt: + * gst/gstpreset.c: + * gst/gstregistry.c: + * tests/check/gst/gstpreset.c: + core: store presets, registry and plugins in XDG directories. + Presets and plugins moved to $XDG_DATA_HOME/gstreamer-0.11/ + root directory. Registry moved to $XDG_CACHE_HOME/gstreamer-0.11/. + Fixes bug #518597. + +2011-05-03 09:41:48 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + gst/gstbus.c + +2011-05-02 18:34:18 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstinfo.c: + * gst/gstpad.c: + * gst/gstpad.h: + event: add sticky flags to events + Add the sticky flag to events and a sticky index. + Keep sticky events in an array on each pad. + Remove GST_EVENT_SRC(), it is causing refcycles with sticky events, was not used + and is not very interesting anyway. + +2011-05-02 11:09:52 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + query: improve allocation parameters query + Use the same parameters as those used for the bufferpool. Make sure we can pass + a minimum and maximum amount of buffers needed. + +2011-04-30 16:55:36 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * docs/plugins/inspect/plugin-staticelements.xml: + * po/de.po: + * po/fr.po: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.32.4 pre-release + +2011-04-29 23:44:55 +0100 Tim-Philipp Müller + + * gst/gstpluginfeature.h: + pluginfeature: include plugin.h in header where we use a GstPlugin pointer + Should fix issue with gstreamermm build where is included + directly instead of gst/gst.h. + +2011-04-29 13:42:57 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + transform: do pad_alloc fallback correctly + +2011-04-29 13:26:19 +0200 Wim Taymans + + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gstvalve.c: + * tests/check/elements/funnel.c: + * tests/check/elements/tee.c: + * tests/check/elements/valve.c: + * tests/check/libs/test_transform.c: + * tests/check/libs/transform1.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + * win32/common/libgstreamer.def: + Remove pad_alloc, this can now be done better + Remove pad_alloc and all references. This can now be done more efficiently and + more flexible with the ALLOCATION query and the bufferpool objects. There is no + reverse negotiation yet but that will be done with an event later. + +2011-04-29 12:11:56 +0200 Wim Taymans + + * gst/gstquery.c: + query: init the ALLOCATION query correctly + Don't add the 'pool' property instead of adding it with a NULL array. + +2011-04-29 10:50:17 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: fix parsing of the ALLOCATION query + Add methods for parsing the caps and the need_pool boolean. + +2011-04-28 16:20:22 +0200 Wim Taymans + + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + query: fix typo in method name and improve docs + Fixed typo in method name and add/improve the docs. + +2011-04-28 15:31:48 +0200 Wim Taymans + + * docs/design/draft-allocation.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * win32/common/libgstreamer.def: + bufferpool: add query to request pool and configuration + Add a query to request allocation parameters and optionally a bufferpool as + well. This should allow elements to discover downstream capabilities and also + use the downstream allocators. + +2011-04-27 18:10:55 +0200 Wim Taymans + + * gst/gstbus.c: + bus: fix timeout handling + +2011-04-27 17:56:12 +0200 Wim Taymans + + * docs/design/draft-bufferpool.txt: + * gst/gstbufferpool.c: + bufferpool: fix some docs + +2011-04-27 17:55:20 +0200 Wim Taymans + + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + event: improve argument names of segments + +2011-04-27 11:49:11 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * po/bg.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.32.3 pre-release + +2011-04-26 15:42:46 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstbus.h: + Revert lockfree GstBus for the release + Drop in old GstBus code for the release to play it safe, since + regressions that are apparently hard to track down and reproduce + have been reported (on windows/OSX mostly) against the lockfree + version, and more time is needed to fix them. + This reverts commit 03391a897001d35d1d290f27dd12e98a8b729fb4. + This reverts commit 43cdbc17e6f944cdf02aeed78d1d5f6bde5190c9. + This reverts commit 80eb160e0f62350271f061daa5f289d9d4277cf4. + This reverts commit c41b0ade28790ffdb0e484b41cd7929c4e145dec. + This reverts commit 874d60e5899dd5b89854679d1a4ad016a58ba4e0. + This reverts commit 79370d4b1781af9c9a65f2d1e3498124d8c4c413. + This reverts commit 2cb3e5235196eb71fb25e0a4a4b8749d6d0a8453. + This reverts commit bd1c40011434c1efaa696dc98ef855ef9cce9b28. + This reverts commit 4bf8f1524f6e3374b3f3bc57322337723d06b928. + This reverts commit 14d7db1b527b05f029819057aef5c123ac7e013d. + https://bugzilla.gnome.org/show_bug.cgi?id=647493 + +2011-04-25 11:10:47 +0200 Josep Torra + + * gst/gstformat.c: + * gst/gstparse.c: + * gst/gstquery.c: + * gst/gsttagsetter.c: + * gst/gstutils.c: + * libs/gst/base/gstbaseparse.c: + Small cosmetic cleanups + Make sure the return values from g_return_* are of the right type. + +2011-04-25 10:56:06 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix mixing of return values + +2011-04-25 10:30:41 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-04-15 22:00:11 -0700 David Schleef + + * gst/gstutils.c: + minor inline documentation fix + +2011-04-24 14:02:51 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c3cafe1 to 46dfcea + +2011-04-24 11:44:19 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + tests: clean up properly in the bin test_link_structure_change unit test + Don't forget to set the pipeline back to NULL state, which makes + valgrind happy again. + +2011-04-24 09:58:53 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: when removing a cached-but-no-longer-existing plugin, only remove features that belong to it + When a plugin file no longer exists, e.g. because it's been removed or + renamed, don't remove all features in the registry based on the *name* + of the plugin they belong to, but only remove those who actually belong + to that particular plugin (object/pointer). + This fixes issues of plugin features disappearing when a plugin .so file + is renamed. + https://bugzilla.gnome.org/show_bug.cgi?id=604094 + +2011-04-24 09:53:39 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistrychunks.c: + * gst/gsttypefind.c: + pluginfeature: store pointer to plugin in addition to the plugin name + So we can reliably remove plugin features for a specific plugin later. + https://bugzilla.gnome.org/show_bug.cgi?id=604094 + +2011-04-24 11:05:58 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: use TRACE log level to log files that don't look like plugins + Cuts down the noise in uninstalled setups. + +2011-04-19 20:35:04 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: fix negotiation regression + Fixup patch for 83597767b169dd6c39a07b6144a650c1f098825a + Use a separate variable for knowing if a pad alloc has been made + instead of checking for the flow return that might not be the + result of the pad alloc + https://bugzilla.gnome.org/show_bug.cgi?id=648220 + +2011-04-21 12:33:10 +0100 Tim-Philipp Müller + + * tests/check/gst/gstpipeline.c: + tests: add simple pipeline-in-pipeline unit test + https://bugzilla.gnome.org/show_bug.cgi?id=648297 + +2011-04-20 15:39:16 +0200 Mark Nauwelaerts + + * gst/gstbus.c: + bus: also allow popping a message without timeout if no poll available + ... which happens in particular flushing a bus, possibly as part + of a state change, e.g. when having a pipeline in a pipeline + and then changing state back to NULL. The interior pipeline + will/might then flush the bus, which is a child bus from the + parent which does not have a poll anymore these days. + https://bugzilla.gnome.org/show_bug.cgi?id=648297 + +2011-04-20 19:08:40 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update defs + +2011-04-20 19:03:49 +0200 Wim Taymans + + * gst/gstelement.c: + element: remove unused variable + +2011-04-20 19:00:07 +0200 Wim Taymans + + * gst/gstelement.c: + element: don't touch base_time or clock in state change + Don't touch the base_time or the clock when setting an element to the READY or + NULL state. It is the parent that will manage this for us. + +2011-04-19 20:52:05 +0200 Sebastian Dröge + + * gst/gstbufferlist.c: + bufferlist: Implement gst_buffer_list_foreach() + +2011-04-19 19:30:28 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-04-19 18:57:43 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: add method to compare buffer data + Add method to compare the data in a buffer. + +2011-04-19 16:21:15 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + +2011-04-19 14:05:23 +0200 Havard Graff + + * gst/gstpad.c: + pad: unlock before freeing the cache to avoid deadlock + https://bugzilla.gnome.org/show_bug.cgi?id=648199 + +2011-04-14 10:15:26 +0200 Havard Graff + + * libs/gst/base/gstbasetransform.c: + basetransform: don't unref trans until the function is done using it + trans->priv->force_alloc = FALSE would crash if the ref held is the last + https://bugzilla.gnome.org/show_bug.cgi?id=648215 + +2011-04-19 13:23:19 +0100 Tim-Philipp Müller + + * gst/gstindex.c: + docs: add note/warning to gst_index_get_writer_id() docs about the OBJECT_LOCK + https://bugzilla.gnome.org/show_bug.cgi?id=646811 + +2011-04-19 13:05:53 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: don't deadlock when setting external index + Protect index with its own lock. gst_index_get_writer_id() may take + the object lock internally (the default resolver, GST_INDEX_RESOLVER_PATH, + will anyway), so if we're using that to protect the index as well, + we'll deadlock. + https://bugzilla.gnome.org/show_bug.cgi?id=646811 + +2011-04-19 11:51:30 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: make fmtlist constant + +2011-04-19 11:48:05 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + * gst/gstquery.h: + query: const-ify formats arguments to gst_query_set_formatsv() + +2011-04-18 18:19:51 +0200 Sebastian Dröge + + * tests/check/elements/fakesink.c: + * tests/check/gst/gstparamspecs.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/libs/test_transform.c: + * tests/check/pipelines/parse-launch.c: + tests: Use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-04-18 18:19:24 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base{sink,src}: Don't try to fixate ANY caps + +2011-04-18 18:07:06 +0200 Sebastian Dröge + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + elements: Use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-04-18 17:33:34 +0200 Sebastian Dröge + + * libs/gst/net/gstnetclientclock.c: + net: Use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-04-18 17:32:17 +0200 Sebastian Dröge + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstpushsrc.c: + base: Use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-04-18 17:28:37 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstutils.h: + utils: Remove GST_BOILERPLATE and friends + +2011-04-18 10:47:26 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Make the size parameter of gst_pad_alloc_buffer() unsigned + Internally guints were used everywhere already. + +2011-04-18 10:41:18 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Don't allow fixating ANY caps and remove FIXME + +2011-04-18 10:36:41 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstbin.c: + bin: Enable DURATION query caching + Elements must now post a DURATION message on the bus if they + change the duration in PAUSED or PLAYING. + +2011-04-16 15:20:08 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + docs: remove reference to baseparse API that didn't make it + +2011-04-16 16:06:02 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-04-16 15:28:53 +0200 Sebastian Dröge + + * tests/check/gst/gstelement.c: + element: Add test for inheriting metadata/pad templates + +2011-04-16 15:24:01 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base: Update docs to say class_init instead of base_init + And remove a useless base_init in basesrc + +2011-04-16 15:23:46 +0200 Sebastian Dröge + + * libs/gst/net/gstnettimeprovider.c: + net: Use G_DEFINE_TYPE + +2011-04-16 15:23:19 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstpipeline.c: + gst: Don't use base_init and use G_DEFINE_TYPE instead of GST_BOILERPLATE + +2011-04-16 15:03:33 +0200 Sebastian Dröge + + * docs/random/porting-to-0.11.txt: + * gst/gstelement.c: + * gst/gstpadtemplate.c: + element: Inherit element metadata and pad templates from parent classes + This allows to add pad templates and set metadata in class_init instead of + base_init. base_init is a concept that is not supported by almost all + languages and copying the templates/metadata for subclasses is the more + intuitive way of doing things. + Subclasses can override pad templates of parent classes by adding a new + template with the same now. + Also gst_element_class_add_pad_template() now takes ownership of the + pad template, which was assumed by all code before anyway. + Fixes bug #491501. + +2011-04-16 14:56:03 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + 0.10.32.2 pre-release + +2011-04-16 14:54:00 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2011-04-16 14:52:40 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: remove newline from translatable string + +2011-04-16 13:49:45 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + gst: gobject-introspection scanner doesn't need to scan or update plugin info + +2011-04-16 14:34:08 +0200 Sebastian Dröge + + * gst/Makefile.am: + gst: make sure gobject-introspection scanner calls gst_init() + https://bugzilla.gnome.org/show_bug.cgi?id=647922 + +2011-04-16 10:45:16 +0100 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/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-16 10:33:21 +0100 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + libs: make sure gobject-introspection scanner calls gst_init() + https://bugzilla.gnome.org/show_bug.cgi?id=647922 + +2011-04-16 10:17:24 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: add new baseparse API to libgstbase.def + +2011-04-16 09:33:06 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-04-16 09:32:17 +0200 Sebastian Dröge + + * win32/common/libgstreamer.def: + win32: Add exports for the GstParseContext and GstBufferListIterator types + +2011-04-16 08:59:58 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-04-15 20:58:51 +0100 Tim-Philipp Müller + + * gst/gstpluginloader.c: + pluginloader: only run gst-plugin-scanner with /usr/bin/arch wrapper on OS X >= 10.5 + Based on patch by: Daniel Macks + Earlier versions of OSX don't support proper multiarch and + trying to use /usr/bin/arch -foo with those versions would + just break things. + https://bugzilla.gnome.org/show_bug.cgi?id=615357 + +2011-04-15 19:07:55 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: expose gst_base_parse_frame_free() for completeness + API: gst_base_parse_frame_free() + +2011-04-15 18:52:18 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: init frames on the stack with gst_base_parse_frame_init() + Frames must now be inited this way, can't just zero them + out and use them. + +2011-04-15 18:38:46 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: more debug logging, minor clean-up + Trace frames, split out code to queue a frame for later. + +2011-04-15 18:00:21 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: change gst_base_parse_frame_init() to not take a GstBaseParse argument + +2011-04-15 17:41:02 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: make GstBaseParseFrame handling more bindings-friendly + Change semantics of gst_base_parse_push_frame() and make it take + ownership of the whole frame, not just the frame contents. This + is more in line with how gst_pad_push() etc. work. Just transfering + the content, but not the container of something that's not really + known to be a container is hard to annotate properly and probably + won't work. We mark frames allocated on the stack now with a private + flag in gst_base_parse_frame_init(), so gst_base_parse_frame_free() + only frees the contents in that case but not the frame struct itself. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + API: gst_base_parse_frame_new() + +2011-04-15 15:02:20 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: register boxed type for GstBaseFrameParse + To make this usable for bindings. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-15 13:57:47 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Add missing ) to the ring-buffer-max-size property description + +2011-04-15 10:53:56 +0200 Robert Swain + + * libs/gst/base/gstbaseparse.c: + baseparse: Remove unused but set variable + GCC 4.6.0 spits warnings about these. + +2011-04-14 16:06:16 +0200 Sebastian Dröge + + * gst/gst.c: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + bufferlist: Add boxed type for GstBufferListIterator for gobject-introspection + +2011-04-14 15:59:28 +0200 Sebastian Dröge + + * gst/gst.c: + * gst/gstparse.c: + * gst/gstparse.h: + parse: Add boxed type for GstParseContext for gobject-introspection + +2011-04-14 15:51:24 +0200 Sebastian Dröge + + * gst/gstbufferlist.c: + * gst/gstfilter.c: + * gst/gstinterface.c: + * gst/gstiterator.c: + * gst/gstminiobject.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gstutils.c: + gst: Add some more gobject-introspection annotations + +2011-04-14 09:07:48 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't leak the sinkpad name + +2011-04-14 09:07:25 +0200 Sebastian Dröge + + * tests/check/elements/multiqueue.c: + multiqueue: Don't leak pads in the named pads unit test + +2011-04-14 08:59:14 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Fix caps leaks in gst_element_factory_can_accept_{any,all}_caps_in_direction() + +2011-04-13 09:20:13 -0700 David Schleef + + * gst/parse/parse.l: + * tests/check/pipelines/parse-launch.c: + parser: Allow element names to begin with digits + +2011-04-13 10:24:33 -0700 David Schleef + + * tests/check/gst/gstutils.c: + tests: Add test for greatest common divisor + +2011-01-06 18:11:31 +0100 Ole André Vadla Ravnås + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + elements: 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-01-06 18:11:31 +0100 Ole André Vadla Ravnås + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + base: 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-01-06 18:11:31 +0100 Ole André Vadla Ravnås + + * gst/gstghostpad.c: + ghostpad: 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-04-13 17:26:54 +0200 Janne Grunau + + * plugins/elements/gstqueue2.c: + queue2: prevent calculation with GST_CLOCK_TIME_NONE in update_time_level() + +2011-04-11 15:08:30 +0100 Tim-Philipp Müller + + * tests/check/elements/multiqueue.c: + * tests/check/elements/queue2.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/test_transform.c: + tests: fix unusued-but-assigned-variable warnings with gcc 4.6 + +2011-04-11 13:04:32 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + tests: disable test_many_bins unit test for now + It fails on the OSX bot (both with git and the last release), and + it doesn't really test anything useful, so may just as well disable + it for now. + +2011-04-11 12:51:36 +0100 Tim-Philipp Müller + + * gst/gstpluginloader.c: + pluginloader: fix compiler warnings + Cast string constants to make compiler happy. + +2011-04-11 12:04:34 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + tests: allow more time for the test_many_bins pipeline to preroll + Hopefully makes this test work on the OSX build bot and other + not-so-powerful machines. + https://bugzilla.gnome.org/show_bug.cgi?id=646624 + +2011-04-11 11:29:00 +0100 Jan Schmidt + + * gst/gstpluginloader.c: + pluginloader: make sure gst-plugin-scanner is called with the right arch on OSX + On OSX, GStreamer might be built as a 'fat/universal' binary containing + both 32-bit and 64-bit code. We must take care that gst-plugin-scanner + is executed with the same architecture as the GStreamer core, otherwise + bad things may happen and core/scanner will not be able to communicate + properly. + Should fix issues with (32-bit) firefox using a 32-bit GStreamer core + which then spawns a 'universal' gst-plugin-scanner binary which gets + run in 64-bit mode, causing 100% cpu usage / busy loops or just hanging + firefox until killed. + https://bugzilla.gnome.org/show_bug.cgi?id=615357 + +2011-04-11 11:05:24 +0200 Robert Swain + + * gst/gstpad.c: + pad: Allow tracking of buffers in GST_SCHEDULING debug output + As GST_SCHEDULING reports when buffers pass through pads due to + gst_pad_push calls, they are a good way of tracking the progress of + buffers through pipelines. As such, adding output of the buffer pointers + to these messages allows tracking of specific buffers, easing debugging. + +2011-04-11 10:53:39 +0200 Wim Taymans + + * libs/gst/base/gstbaseparse.c: + baseparse: port to 0.11 + +2011-04-11 10:26:54 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + android/base.mk + android/controller.mk + android/dataprotocol.mk + android/elements.mk + android/gst-inspect.mk + android/gst-launch.mk + android/gst-plugin-scanner.mk + android/gst.mk + android/indexers.mk + android/net.mk + win32/common/libgstbase.def + +2011-04-11 10:20:10 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: add FIXME + +2011-01-27 14:33:08 +0100 Alessandro Decina + + * .gitignore: + * Android.mk: + * android/NOTICE: + * android/base.mk: + * android/controller.mk: + * android/dataprotocol.mk: + * android/elements.mk: + * android/gst-inspect.mk: + * android/gst-launch.mk: + * android/gst-plugin-scanner.mk: + * android/gst.mk: + * android/gst/gstconfig.h: + * android/gst/gstenumtypes.c: + * android/gst/gstenumtypes.h: + * android/gst/gstmarshal.c: + * android/gst/gstmarshal.h: + * android/gst/gstversion.h: + * android/gst/parse/grammar.output: + * android/gst/parse/grammar.tab.c: + * android/gst/parse/grammar.tab.h: + * android/gst/parse/lex._gst_parse_yy.c: + * android/indexers.mk: + * android/net.mk: + * android/tools.mk: + * gst/Makefile.am: + * gst/parse/Makefile.am: + * libs/Makefile.am: + * libs/gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/helpers/Makefile.am: + * libs/gst/net/Makefile.am: + * plugins/Makefile.am: + * plugins/elements/Makefile.am: + * plugins/indexers/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 23:54:20 +0100 Tim-Philipp Müller + + * gst/gsttrace.c: + trace: don't put code with side effects into g_return_if_fail() + +2011-04-09 22:57:46 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + docs: minor fixes for baseparse docs + Class vfunc references still aren't right, no idea what + the correct markup for those is. + +2011-04-09 18:04:55 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + element: unref event in default_send_event in case element has no pads + Spotted by Haakon Sporsheim. + +2011-04-09 04:07:04 +0200 Edward Hervey + + * tests/check/gst/.gitignore: + check: Ignore new gstmeta binary + +2011-04-09 04:05:48 +0200 Edward Hervey + + * docs/design/Makefile.am: + design: draft-buffer2.txt no longer exists + +2011-04-09 04:05:20 +0200 Edward Hervey + + * gst/Makefile.am: + gst: Don't forget to dist gstelementmetadata.h + +2011-04-08 19:07:02 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: minor variable name clean-up + +2011-04-08 15:31:14 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + * win32/common/libgstbase.def: + baseparse: rename _set_frame_props() to _set_frame_rate() + Seems like the best fit to what it does, and is shorter than + set_frame_properties() which might also have been confusing + because of GstBaseParseFrame. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-06 17:43:27 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: replace format flags with gst_base_parse_set_{passthrough,syncable,has_timing_info} + This is more in line with e.g. GstBaseTransform's API, and makes for nicer + to read code. No getters for now since I don't see any use case for them, + the API is for subclasses, which usually know what format they're + dealing with already and hence know what they've set. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-04 17:58:59 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: make DRAIN and SYNC flags on baseparse, not the frame, and change to DRAINING and LOST_SYNC + The first because it seems a better fit conceptually, the second + to express booleanness. Also change the accessor macros for subclasses + to GST_BASE_PARSE_DRAINING and GST_BASE_PARSE_LOST_SYNC. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-02 14:18:57 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.h: + baseparse: add some padding to GstBaseParseFrame + Esp. since it's usually allocated on the stack. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-02 14:08:46 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.h: + baseparse: fix typo in docs for GST_BASE_PARSE_FORMAT_FLAG_PASSTHROUGH + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-04-02 14:04:42 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: use GQueue instead of GList for queued frames + and make buffer metadata writable before setting caps on queued + buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=646341 + +2011-04-02 13:02:01 +0100 Zaheer Abbas Merali + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: add GST_BASE_PARSE_FLOW_QUEUED to queue buffers until caps are known + This is useful for parser like flacparse or h264parse which may need to process + some buffers before they can construct the final caps, in which case they may + want to delay pushing the initial buffers until the full and proper caps are + known. + https://bugzilla.gnome.org/show_bug.cgi?id=646341 + +2011-03-31 15:50:22 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: add to docs and fix up gtk-doc markup a little + And add Since markers. + +2011-03-31 14:48:47 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: replace set_seek() with _set_average_bitrate() and FLAG_SYNCABLE + This makes more sense conceptually, since the bitrate may be used + to estimate a seek position if there's no seek table or just for + duration reporting/estimation if we can't seek. Also, even if the + format is not syncable, we could still seek by pushing data from the + start and using the segment to make downstream clip. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-03-24 17:30:53 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: rename GstBaseFormat to GstBaseFormatFlags and fix up associated API + Also change gst_base_parse_set_format(parse,flags,switch_on) to + gst_base_parse_set_format_flags(parse,flags) which is more in line + with the rest of our API and how the function is used. + +2011-03-13 23:43:52 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: don't expose GstAdapter in public header + None of the existing subclasses needs access to that, so there's + no reason to expose it for now. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-03-13 23:38:12 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: move various segment-related members into the private instance struct + If none of the existing subclasses uses these, there's probably no + need to expose them at the moment. Keep the segment itself exposed + though. + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-03-13 23:30:51 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.h: + baseparse: remove unused GST_BASE_PARSE_{SINK,SRC}_NAME + https://bugzilla.gnome.org/show_bug.cgi?id=518857 + +2011-03-12 16:16:22 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.h: + baseparse: re-indent header + +2011-03-12 15:34:33 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: fix up GType name and make _get_type() function thread-safe + Rename GType from GstBaseParseBad to GstBaseParse. + +2011-03-12 15:29:38 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + libs: add GstBaseParse which was moved from -bad + +2011-02-23 17:24:14 -0800 David Schleef + + * libs/gst/base/gstbaseparse.c: + baseparse: make_metadata_writable() fix + +2011-02-21 13:24:03 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbaseparse.c: + baseparse: rename GType from GstAudioBaseParseBad to GstBaseParseBad + We use it for video as well now. + +2011-02-18 15:05:31 +0200 Stefan Kost + + * libs/gst/base/gstbaseparse.c: + baseparse: trim trailing whitespace + +2011-02-18 15:05:03 +0200 Stefan Kost + + * libs/gst/base/gstbaseparse.c: + baseparse: use delta-unit flags instead of none + +2011-02-17 13:22:28 -0800 David Schleef + + * libs/gst/base/gstbaseparse.h: + baseparse: update documentation for API changes + +2010-10-13 15:39:55 -0700 David Schleef + + * libs/gst/base/gstbaseparse.c: + * libs/gst/base/gstbaseparse.h: + baseparse: Create baseparse library + +2011-02-07 14:46:57 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: tune QUERY_SEEKING response + Even if we currently do not have a duration yet, assume seekable if + it looks like we'll likely be able to determine it later on + (which coincides with needed information to perform seeking). + Fixes #641047. + +2011-02-08 23:39:24 +0530 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Update min/max bitrate before first posting them + This avoids posting an initial min-bitrate of G_UINTMAX and max-bitrate + of 0. + https://bugzilla.gnome.org/show_bug.cgi?id=641857 + +2011-01-21 14:53:39 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: tune default duration estimate update interval + Rather than a fixed default frame count, estimate frame count to aim for + an interval duration depending on fps if available, otherwise use old + fixed default. + +2011-01-14 15:16:04 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: reverse playback; mind keyframes for fragment boundary + +2011-01-12 14:40:37 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: ensure non-empty candidate frames + +2011-01-11 15:24:23 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: clarify some debug statements + +2011-01-11 15:24:02 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: properly track upstream timestamps + ... rather than with a delay. + +2011-01-11 15:23:29 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: need proper frame duration to obtain sensible frame bitrate + +2011-01-11 15:22:51 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: proper initial values for index tracking variables + +2011-01-11 12:05:13 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: arrange for consistent event handling + +2011-01-10 16:59:59 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.h: + baseparse: header style cleaning + +2011-01-10 17:07:38 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: provide some more initial frame metadata in parse_frame + ... and document accordingly. + +2011-01-10 16:56:36 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: refactor passthrough into format flags + Also add a format flag to signal baseparse that subclass/format can provide + (parsed) timestamp rather than an estimated one. In particular, such "strong" + timestamp then allows to e.g. determine duration. + +2011-01-10 15:34:48 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: introduce a baseparse frame to serve as context + ... and adjust subclass parsers accordingly + +2011-01-07 16:39:51 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: restrict duration scanning to pull mode and avoid extra set_caps call + +2011-01-07 15:58:49 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: update some documentation + Also add some more debug. + +2011-01-06 11:41:44 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: allow increasing min_size for current frame parsing only + Also check that subclass actually either directs to skip bytes or + increases expected frame size to avoid going nowhere in bogus + indefinite looping. + +2011-01-14 15:26:37 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baesparse: fix refactor regression in loop based parsing + +2011-01-06 11:16:56 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: pass all available data to subclass rather than minimum + Also reduce some adapter calls and add a few debug statements. + +2010-12-10 15:59:49 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix reverse playback handling + +2010-12-10 14:56:13 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: minor typo and debug statement cleanup + +2010-12-10 14:40:05 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: reduce locking + ... which is either already mute and/or implicitly handled by STREAM_LOCK. + +2011-01-14 14:08:38 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: avoid loop in frame locating interpolation + +2011-01-14 16:30:11 -0300 Thiago Santos + + * gst/audioparsers/gstbaseparse.c: + audioparsers: baseparse: Be careful to not lose the event ref + Don't unref the event if it hasn't been handled, because the caller + assumes it is still valid and might reuse it. + I ran into this problem when transcoding an AVI (with mp3 inside) + to gpp. + https://bugzilla.gnome.org/show_bug.cgi?id=639555 + +2011-01-13 16:27:04 +0000 Tim-Philipp Müller + + * gst/audioparsers/gstbaseparse.c: + docs: minor baseparse docs/comment fixes + Remove copy'n'paste leftovers. + +2010-11-08 19:58:31 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: increase keyframe awareness + ... which is not particular relevant for audio parsing, but more so + in video cases. In particular, auto-determine if dealing with video (caps). + +2010-11-30 15:41:02 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: avoid unexpected stray metadata + +2010-11-30 15:40:28 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use proper _NONE output value when applicable + +2010-11-25 18:56:42 +0100 Edward Hervey + + * gst/audioparsers/gstbaseparse.c: + audioparsers: Remove dead assignments + +2010-11-25 17:14:23 +0100 Andoni Morales Alastruey + + * gst/audioparsers/gstbaseparse.c: + audioparse: fix possible division-by-zero + https://bugzilla.gnome.org/show_bug.cgi?id=635786 + +2010-11-17 16:23:42 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use correct offset when adding index entry + ... bearing in mind that BUFFER_OFFSET is media specific and may not + reflect the basic offset after having been parsed. + +2010-11-17 14:30:09 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: enhancements for timestamp marked framed formats + That is, as such formats allow subclass to extract position from frame, + it is possible to extract duration (if not otherwise provided) + from (near) last frame, and a seek can fairly accurately target the required + position. + Fixes #631389. + +2010-11-16 17:06:14 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: refactor frame scanning peformed by _loop + +2010-11-16 18:04:00 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: slightly optimize sending of pending newsegment events + +2010-11-16 17:04:35 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: minor fixes and enhancements + Arrange for upstream as well as downstream flushing when seeking. + Also determine upstream size as well as seekability. Adjust some comments + to reality and employ debug statement in proper order. + +2010-10-29 14:08:58 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use only upstream duration if it provides one + +2010-10-25 14:15:50 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: reflow update_bitrate code + ... which makes local variables represent real state better, and avoids + triggering unneeded updates/actions. + +2010-10-25 14:13:51 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: add some debug statements + +2010-10-11 17:49:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: perform bitrate handling and posting after newsegment sending + +2010-10-11 17:36:19 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: immediately post subclass provided bitrate + +2010-10-05 11:17:52 +0100 Tim-Philipp Müller + + * gst/audioparsers/gstbaseparse.c: + Revert "baseparse: add skip property" + This reverts commit b5a3d60363d837a10f0533c141ec93d10b742312. + Reverting this for now, since no one really seems to remember why this + property exists or what it could possibly be good for. It seems to have + been in the original mp3parse since the beginning of time and was back- + ported from there. + +2010-10-03 23:50:29 +0200 Sebastian Dröge + + * gst/audioparsers/gstbaseparse.c: + audioparser: Let the format string agree with the parameters to fix compiler warning + +2010-09-22 15:44:43 +0530 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Fix debug output + We lose the reference to the buffer after gst_pad_push(), so the debug + print should happen before. + https://bugzilla.gnome.org/show_bug.cgi?id=622276 + +2010-09-29 16:12:42 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: support reverse playback + ... in pull mode or upstream driven. + +2010-09-27 12:16:43 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: remove done TODOs and update documentation + +2010-09-25 14:40:54 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use determined seekability in answering SEEKING query + +2010-09-25 14:32:06 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: add skip property + +2010-09-22 15:07:09 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: use _set_frame_props to configure frame lead_in and lead_out + ... provided a corresponding decoder with sufficient leading and following + frames to carry out full decoding for a particular segment. + +2010-09-22 14:13:17 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: use _set_duration to configure duration update interval + ... as it logically belongs there as one or the other; either subclass + can provide a duration, or an estimate must be made (reguarly updated). + +2010-09-22 13:55:20 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: localize use of provided fps information + +2010-09-22 12:13:12 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: seek table and accurate seek support + +2010-09-21 13:57:10 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: proper and more extended segment and seek handling + That is, loop pause handling, segment seek support, newsegment for gaps, etc + +2010-09-21 10:57:04 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: add index support + +2010-09-21 09:59:56 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: refactor state reset + +2010-09-20 16:39:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: prevent indefinite resyncing + +2010-09-20 13:57:55 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: specific EOS handling if no output so far + +2010-09-20 13:31:57 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: adjust _set_frame_prop documentation and set default as claimed + +2010-09-20 13:30:54 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix bitrate copy-and-paste and update heuristic + +2010-09-17 18:33:29 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: post duration message if average bitrates is updated + +2010-09-17 18:24:22 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: remove is_seekable vmethod and use a set_seek instead + Seekability, like duration, etc is unlikely to change (frequently), and + the default assumption covers most cases, so let subclass set when needed. + At the same time, allow subclass to indicate if it has seek-metadata (table) + available, and possibly have it provide an average bitrate. + +2010-09-17 17:21:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: add another hook for subclass prior to pushing buffer + ... and allow subclass to perform custom segment clipping, or to + emit tags or messages at this time. + +2010-09-17 17:19:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: 0 converts to 0 by default + +2010-09-16 18:56:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: refactor conversion using helper function and export default convert + +2010-09-16 18:35:47 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: streamline query handling + +2010-09-16 11:51:20 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: cleanup struct and remove unused member + +2010-09-22 16:07:24 +0530 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Allow chaining of subclass event handlers + This allows the child class to chain its event handler with + GstBaseParse, so that subclasses don't have to duplicate all the default + event handling logic. + https://bugzilla.gnome.org/show_bug.cgi?id=622276 + +2010-08-27 18:35:10 +0200 Sebastian Dröge + + * gst/audioparsers/gstbaseparse.c: + baseparse: Don't use GST_FLOW_IS_FATAL() + Also don't post an error message for UNEXPECTED and do it + for NOT_LINKED. + +2010-09-06 14:12:00 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: non-TIME seek event is simply not handled + +2010-06-15 15:34:05 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix seek event ref handling + +2010-06-15 15:33:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: prevent arithmetic overflows in pull mode buffer cache handling + +2010-06-15 15:32:34 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix seek handling + Allow a few more seek event type combinations, and really use the result + of gst_segment_set_seek to perform the seek. Also add some debug. + +2010-03-26 18:56:49 +0000 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Don't emit bitrate tags too early + We wait to parse a minimum number of frames (10, arbitrarily) before + emiting bitrate tags so that our early estimates are not wildly + inaccurate for streams that start with a silence. If the stream ends + before that, we just emit the tags anyway. + While it _would_ be nicer to be specify the threshold to start pushing + the tags in terms of duration, this would introduce more complexity than + this merits. + https://bugzilla.gnome.org/show_bug.cgi?id=614991 + +2010-03-26 18:20:24 +0100 Sebastian Dröge + + * gst/audioparsers/gstbaseparse.c: + baseparse: Set the last stop to the buffer starttime if the duration is invalid + ...instead of not setting it at all. + +2010-03-26 18:19:00 +0100 Joshua M. Doe + + * gst/audioparsers/gstbaseparse.c: + baseparse: Send NEWSEGMENT event with correct start and position + Instead of taking the last stop (which could be buffer endtime instead + of starttime) always take the buffer starttime. + Fixes bug #614016. + +2010-03-25 17:09:17 +0000 Tim-Philipp Müller + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + audioparsers: remove unused GstBaseParseClassPrivate structure + +2010-03-25 11:22:58 +0000 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + audioparsers: Add bitrate calculation to baseparse + This makes baseparse keep a running average of the stream bitrate, as + well as the minimum and maximum bitrates. Subclasses can override a + vfunc to make sure that per-frame overhead from the container is not + accounted for in the bitrate calculation. + We take care not to override the bitrate, minimum-bitrate, and + maximum-bitrate tags if they have been posted upstream. We also + rate-limit the emission of bitrate so that it is only triggered by a + change of >10 kbps. + +2010-01-14 11:50:33 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + audioparsers: rename baseparse GType name to avoid possible conflicts + +2010-01-05 15:05:05 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + audioparsers: documentation fixes + +2009-12-21 18:18:39 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: adjust seek handling and newsegment sending + Perform sanity check on type of seek, and only perform one that is + appropriately supported. Adjust downstream newsegment event + to first buffer timestamp that is sent downstream. + +2009-12-21 11:59:45 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: minor refactor cleanup + Also add some debug logging. + +2009-12-18 21:02:40 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: implement leftover draining in pull mode + +2009-12-16 18:38:33 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: provide default conversion using bps if no fps available + Also store estimated duration as such, rather than pretending otherwise + (e.g. set by subclass). + +2009-12-18 13:30:29 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: check for remaining data when draining in push mode + +2009-12-18 13:30:07 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix pull mode cache size comparison + +2009-12-11 10:25:16 -0800 Michael Smith + + * gst/audioparsers/gstbaseparse.c: + audioparse: fix a format string as reported on irc. + +2009-10-29 15:18:37 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: custom bufferflag indicates not to count frame in stats + +2009-11-27 17:27:32 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + audioparsers: reference GstBaseParse now lives here + +2009-11-28 18:13:31 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + audioparsers: rename 'aacparse' plugin to generic 'audioparsers' plugin + +2009-10-29 16:05:00 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: reset passthrough mode to default (disabled) on activation + +2009-10-29 15:16:59 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: ensure buffer metadata is writable + +2009-10-28 14:06:13 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + * gst/aacparse/gstbaseparse.h: + baseparse: fix/enhance DISCONT marking + In particular, consider DISCONT == !sync, and allow subclass to query + sync state, as it may want to perform additional checks depending + on whether sync was achieved earlier on. + Also arrange for subclass to query whether leftover data is being drained. + +2009-11-23 15:48:25 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + * gst/aacparse/gstbaseparse.h: + baseparse: add timestamp handling, and default conversion + In particular, (optionally) provide baseparse with a notion of frames per second + (and therefore also frame duration) and have it track frame and byte counts. + This way, subclass can provide baseparse with fps and have it provide default + buffer time metadata and conversions, though subclass can still install + callbacks to handle such itself. + +2009-10-28 12:02:03 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: documentation fixes + +2009-10-28 12:00:08 +0100 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: use_fixed_caps for src pad + After all, stream is as-is, and there is little molding to downstream's + taste that can be done. If subclass can and wants to do so, it can + still override as such. + +2009-11-20 17:32:13 +0100 Julien Moutte + + * gst/aacparse/gstbaseparse.c: + aacparse: Fix compilation warnings + +2009-10-11 11:22:11 +0200 Josep Torra + + * gst/aacparse/gstbaseparse.c: + aacparse: fix warnings in macosx snow leopard + +2009-09-25 17:02:53 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + * gst/aacparse/gstbaseparse.h: + aacparse: forego (bogus) parsing of already parsed (raw) input + +2009-08-07 13:07:17 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: prevent infinite loop when draining + +2009-08-07 13:06:28 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: fix minor memory leak + +2009-07-14 14:08:04 +0200 Sebastian Dröge + + * gst/aacparse/gstbaseparse.c: + * gst/aacparse/gstbaseparse.h: + aacparse: Add function for the baseparse subclass to push buffers downstream + Also handle the case gracefully where the subclass decides to drop + the first buffers and has no caps set yet. It's still required to + have valid caps set when the first buffer should be passed downstream. + +2009-07-14 14:07:44 +0200 Sebastian Dröge + + * gst/aacparse/gstbaseparse.c: + baseparse: Fix seek event leaking + +2009-06-01 13:56:18 +0100 Tim-Philipp Müller + + * gst/aacparse/gstbaseparse.c: + baseparse: propagate return value of GstBaseParse::set_sink_caps() + gst_base_parse_sink_setcaps() presumably should fail if the subclass + returns FALSE from its ::set_sink_caps() function. + +2009-06-01 13:47:01 +0100 Tim-Philipp Müller + + * gst/aacparse/gstbaseparse.c: + baseparse: don't try to GST_LOG an already-freed caps string + The proper way to log caps is via GST_PTR_FORMAT anyway. + +2009-05-26 19:43:53 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: fix debug category + +2009-04-27 22:39:15 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: fix (regression in) newsegment handling + (aacparse, amrparse, flacparse). Fixes #580133. + +2009-04-07 04:53:02 +0300 René Stadler + + * gst/aacparse/gstbaseparse.c: + baseparse: Fix slightly broken buffer-in-segment check (aacparse, amrparse, flacparse) + +2009-04-05 03:50:19 +0300 René Stadler + + * gst/aacparse/gstbaseparse.c: + baseparse: Fix push mode seeking (aacparse, amrparse) + Sending the flush-start event forward before taking the stream lock actually + works, in contrast to deadlocking in downstream preroll_wait (hunk 1). + After that we get the chain function being stuck in a busy loop. This is fixed + by updating the minimum frame size inside the synchronization loop because the + subclass asks for more data in this way (hunk 2). + Finally, this leads to a very probable crash because the subclass can find a + valid frame with a size greater than the currently available data in the + adapter. This makes the subsequent gst_adapter_take_buffer call return NULL, + which is not expected (hunk 3). + +2009-03-31 16:07:46 +0200 Mark Nauwelaerts + + * gst/aacparse/gstbaseparse.c: + baseparse: Delay newsegment as long as possible. + If newsegment is sent (too) early, caps may not yet be fixed/set, + and downstream may not have been linked. + +2009-02-27 11:24:37 +0200 Stefan Kost + + * gst/aacparse/gstbaseparse.c: + baseparse: revert last change and properly fix + Baseparse internaly breaks the semantics of a _chain function by calling it with + buffer==NULL. The reson I belived it was okay to remove it was that there is + also an unchecked access to buffer later in _chain. Actually that code is wrong, + as it most probably wants to set discont on the outgoing buffer. + +2009-02-26 11:02:06 +0200 Stefan Kost + + * gst/aacparse/gstbaseparse.c: + baseparse: remove checks for buffer==NULL + Accordifn to docs for GstPadChainFunction buffer cannot be NULL. If we would + leave the check, we would also need more such check below. + +2009-01-30 18:18:10 +0000 Jan Schmidt + + * gst/aacparse/gstbaseparse.c: + Fix the return value of the default parse_frame function. + Fix the return value of the default parse_frame function in both + copies of GstBaseParse + +2008-11-13 14:21:39 +0000 Stefan Kost + + gst/: Fix baseparse type name. + Original commit message from CVS: + * gst/aacparse/gstbaseparse.c: + * gst/amrparse/gstbaseparse.c: + Fix baseparse type name. + +2008-11-13 12:59:34 +0000 Stefan Kost + + Add two new baseparse based parsers (aac and amr) from Bug #518857. + Original commit message from CVS: + * configure.ac: + * gst/aacparse/Makefile.am: + * gst/aacparse/gstaacparse.c: + * gst/aacparse/gstaacparse.h: + * gst/aacparse/gstbaseparse.c: + * gst/aacparse/gstbaseparse.h: + * gst/amrparse/Makefile.am: + * gst/amrparse/gstamrparse.c: + * gst/amrparse/gstamrparse.h: + * gst/amrparse/gstbaseparse.c: + * gst/amrparse/gstbaseparse.h: + Add two new baseparse based parsers (aac and amr) from Bug #518857. + +2011-03-20 00:56:08 +0100 Havard Graff + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue[2]: Make src query MT-safe + It is possible that the element might be going down while the event arrives + +2011-03-20 00:56:08 +0100 Havard Graff + + * libs/gst/base/gstbasesrc.c: + basesrc: Make src query MT-safe + It is possible that the element might be going down while the event arrives + +2011-04-08 14:56:37 +0200 Sebastian Dröge + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue[2]: Unref events if the parent element disappeared + +2011-03-21 16:01:05 +0100 Havard Graff + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + queue[2]: Make upstream events MT-safe + +2011-04-08 14:55:09 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + base: Unref events if the parent element disappeared + And also unref events if the basetransform subclass has no + event handler and the event is not forwarded at all. + +2011-03-21 16:01:05 +0100 Havard Graff + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + base: Make upstream events MT-safe + +2011-03-29 11:57:06 +0200 Stian Selnes + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + gstqueue, gstqueue2: check if parent of pad is NULL in _getcaps + Parent of the pad (the queue) may be set to NULL while there is + a buffer alloc going on. + +2011-04-08 14:50:10 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Fix getcaps and event function from last commit + Return ANY caps if the parent disappeared, i.e. the template caps + and don't leak events if the parent disappeared. + +2011-04-01 08:46:14 +0200 Havard Graff + + * plugins/elements/gstinputselector.c: + inputselector: Protect against pad-parent disappearing + +2010-12-14 16:06:46 +0100 Stian Selnes + + * gst/gstiterator.c: + iterator: resync to avoid infinite loop + +2011-04-08 09:20:28 +0200 Sebastian Dröge + + * tests/check/gst/gstutils.c: + utils: Fix uninitialized variable compiler warnings + +2011-04-08 09:15:10 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Removed unused GCond + +2011-04-08 09:07:59 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Add another check for the flushing flag after taking the lock + This prevents another potential deadlock when flushing the pad + at exactly the right time. + +2011-04-07 11:24:35 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Immediately drop messages after calling the sync handler if this is a synchronous bus + Otherwise we might wait forever for the message to be popped from + the queue if a sync handler returned GST_BUS_ASYNC. + https://bugzilla.gnome.org/show_bug.cgi?id=647005 + +2011-04-07 11:19:57 +0200 Sebastian Dröge + + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstbus.c: + bus: Use a construct-only property to distinguish between child buses and normal buses + This allows to only create the socketpair when it is really required instead + of always creating it and immediately destroying it again for child buses. + https://bugzilla.gnome.org/show_bug.cgi?id=647005 + +2011-04-07 20:47:25 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/queue2.c: + tests: add some basic unit tests for queue2 + +2011-04-07 20:45:22 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix buffer leak on eos when using the ring buffer + +2011-01-11 14:27:35 +0100 Idar Tollefsen + + * plugins/elements/gstqueue2.c: + queue2: Fixes memory leak on out_flushing error in gst_queue2_create_read. + https://bugzilla.gnome.org/show_bug.cgi?id=646972 + +2011-04-07 19:44:44 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: fix minor memory leak + +2011-04-07 17:34:10 +0100 Tim-Philipp Müller + + * plugins/elements/gstfunnel.c: + funnel: minor element description fix + +2011-04-07 16:13:56 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-04-07 16:02:43 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.h: + memory: add NO_SHARE flag to memory + Add a NO_SHARE flag to memory to indicate that it should not be shared + between buffers. + +2011-04-07 16:08:34 +0300 Stefan Kost + + * docs/random/draft-missing-plugins.txt: + docs: remove file as we have docs/design/part-missing-plugins.txt + +2011-04-07 10:48:04 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Handle tag and custom downstream events the same + Especially drop tag events when flushing to not send them over + and over again. + Should've been in the last commit already but I forgot to call + git rebase --continue... + +2011-04-07 10:40:16 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + bla + +2011-04-07 10:29:41 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Send syncronized custom downstream/both events downstream from the streaming thread + Instead of just silently dropping them. The same was done for tag events + before already. + Fixes bug #635718. + +2011-04-06 19:19:55 +0200 Wim Taymans + + * gst/gstmemory.c: + memory: don't follow the parent in the fallback share + +2011-04-06 18:57:57 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstminiobject.c: + buffer: make memory writable in _peek + Make the memory writable when we are asked to _peek with MAP_WRITE. + Improve debugging of miniobject. + +2011-04-06 16:37:40 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: fix debug + +2011-04-06 14:20:59 +0200 Sebastian Dröge + + Merge branch 'master' into 0.11 + +2011-04-06 14:06:49 +0200 Sebastian Dröge + + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstbus.c: + bus: Add private API to set a GstBus in child mode + This is used by GstBin to create a child bus without + a socketpair because child buses will always work + synchronous. Otherwise too many sockets could be + created and the limit of file descriptors for the + process could be reached. + Fixes bug #646624. + +2011-04-06 13:56:49 +0200 Sebastian Dröge + + * gst/gstbus.c: + Revert "bus: Only create the signalling socket pair when required" + This reverts commit 4bf8f1524f6e3374b3f3bc57322337723d06b928. + +2011-04-06 13:56:46 +0200 Sebastian Dröge + + * gst/gstbus.c: + Revert "bus: Check if pending messages are in the queue" + This reverts commit bd1c40011434c1efaa696dc98ef855ef9cce9b28. + +2011-04-06 11:38:57 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + checks: make tests_many_bins in bin unit test a bit faster + Not doing expensive checks when linking elements makes things + much faster. + +2011-04-06 11:30:18 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + checks: add some queues to test_many_bins unit test + To limit the number of calls in a row per thread. + +2011-04-06 12:03:18 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Check if pending messages are in the queue + We can't rely completely on the poll fd because the fd might be + created after messages were posted to the bus. + +2011-04-06 11:45:27 +0200 Sebastian Dröge + + * tests/check/gst/gstvalue.c: + value: GstDate/GDate has a abbreviation now + +2011-04-03 16:11:50 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbin.c: + checks: add GstBin unit test that creates a lot of bins + Currently fails (in normal circumstances) because we create a + socket pair for each bin's bus and exhaust the number of available + file descriptors. + https://bugzilla.gnome.org/show_bug.cgi?id=646624 + +2011-04-05 16:22:48 +0200 Sebastian Dröge + + * gst/gstbus.c: + bus: Only create the signalling socket pair when required + Otherwise a new one would be created for every single bus and + the process could easily run out of file descriptors. + Fixes bug #646624. + +2011-04-05 14:36:43 +0200 Sebastian Dröge + + * gst/gststructure.c: + structure: Add date as a type abbreviation of GDate + See bug #646696. + +2011-04-04 15:56:30 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 1ccbe09 to c3cafe1 + +2011-04-04 11:17:28 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-04-04 03:33:46 +0200 Andoni Morales Alastruey + + * gst/gstpoll.c: + gstpoll: retry reading the control socket to release properly all wakeups + if set->control_pending is set to 0 but we didn't not succed reading + the control socket, future calls to gst_poll_wait() will be awaiken + by the control socket which will not be released properly because + set->control_pending is already 0, causing an infinite loop. + +2011-04-04 10:18:14 +0200 Sebastian Dröge + + * gst/gststructure.c: + structure: Don't allow invalid GDates in all structures and don't allow NULL GDates in taglists + Some code (e.g. gstvorbistag.c) assumes non-NULL GDates in taglists and + explodes otherwise and NULL or invalid GDates don't make much sense anyway. + +2011-03-25 15:56:07 +0100 Thomas Kristensen + + * gst/gstpoll.c: + poll: don't call WSAWaitForMultipleEvents with no events + Fixes error caught by Microsoft Application Verifier. + +2011-04-03 16:18:54 +0100 Tim-Philipp Müller + + * gst/gstevent.h: + docs: add pointer to part-seeking.txt design docs to event seek flags docs + +2011-04-03 16:18:14 +0100 Tim-Philipp Müller + + * tests/check/elements/.gitignore: + checks: ignore new funnel unit test binary + +2011-04-02 14:51:18 +0100 Bastien Nocera + + * gst/gstutils.h: + utils: Avoid using "type" as name for a variable and a macro argument in GST_BOILERPLATE + This caused "re-declaration" problems. + ./clutter-gst-video-sink.c: In function ‘clutter_gst_video_sink_init_interfaces’: + ./clutter-gst-video-sink.c:231:1: warning: declaration of ‘ClutterGstVideoSink’ shadows a global declaration [-Wshadow] + ./clutter-gst-video-sink.h:64:44: warning: shadowed declaration is here [-Wshadow] + https://bugzilla.gnome.org/show_bug.cgi?id=646531 + +2011-04-01 13:56:09 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: When requesting an existing pad print a g_critical() instead of using an assertion + Some applications are requesting the same pad name multiple times + and the behaviour is undefined and different from element to element + but we don't want to break applications that work just fine. + In 0.11 this check should be an assertion again, although elements + have to do manual checking if the pad already exists again because + it can't be done in a threadsafe way here. + +2011-04-01 13:53:39 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Use gint64/guint64 string parsing functions + And check that the requested pad names are inside the valid + gint/guint range. + +2011-04-01 13:51:31 +0200 Josep Torra + + * gst/gstelement.c: + element: strto[u]l() returns a g[u]long + +2011-04-01 10:47:48 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-04-01 10:46:06 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting guide with bufferlist changes + +2011-03-31 19:25:30 +0100 Tim-Philipp Müller + + * docs/design/part-seeking.txt: + design docs: document expected behaviour for ACCURATE and KEY_UNIT seek flags + +2011-03-31 18:39:57 +0200 Wim Taymans + + * libs/gst/base/gstbytewriter.c: + bytewriter: don't add NULL data + +2011-03-31 17:55:22 +0200 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + tests/check/gst/struct_x86_64.h + +2011-03-31 17:51:02 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstpad.c: + * libs/gst/base/gstbasesink.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstpad.c: + * win32/common/libgstreamer.def: + bufferlist: simplify bufferlists + We now have multiple memory blocks as part of the buffers and we can therefore + reduce the bufferlist to a simple array of buffers. + +2011-03-31 10:53:03 +0200 Sebastian Dröge + + * tests/check/gst/struct_x86_64.h: + gstabi: Add some new structures for x86-64 + +2011-03-31 10:46:40 +0200 Sebastian Dröge + + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_x86_64.h: + libsabi: Add lots of new structures for x86-64 + +2011-03-31 10:31:22 +0200 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting doc + +2011-03-30 20:05:26 +0200 Wim Taymans + + * plugins/elements/gstfunnel.c: + funnel: fix for API change + +2011-03-30 19:58:52 +0200 Wim Taymans + + Merge branch 'master' into 0.11-fdo + Conflicts: + docs/plugins/gstreamer-plugins.hierarchy + gst/gstelement.c + +2011-03-30 19:01:13 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmeta.c: + docs: update docs + +2011-03-30 18:45:08 +0200 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/plugins/gstreamer-plugins.hierarchy: + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + docs: update documentation + +2011-03-30 16:47:55 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcompat.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesrc.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstmeta.c: + * tests/check/libs/adapter.c: + * win32/common/libgstreamer.def: + buffer: more API tweaks + _trim -> _resize + _create_sub -> copy_region + +2011-03-30 15:29:39 +0200 Wim Taymans + + * docs/design/part-buffer.txt: + * docs/design/part-bufferlist.txt: + design: update design docs + +2011-03-30 13:04:34 +0200 Wim Taymans + + * docs/design/part-meta.txt: + * gst/gstbuffer.c: + design: update docs + +2011-03-30 10:48:47 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + multiqueue: Make assignment of queue IDs and pad names threadsafe + Also add a test for naming pads by the caller and return NULL + when requesting an already existing pad. + +2011-03-29 23:58:43 +0200 Andreas Frisch + + * plugins/elements/gstmultiqueue.c: + multiqueue: Set the single queue ID to the ID of the requested pad if one was given by the caller + +2011-03-29 19:17:55 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + memory: further memory tweaking + Allow for automatic merging of memory block in the _map function and automatic + freeing of the temporary memory. + Remove some unneeded functions. + Add possibility to force writable spanned memory. + +2011-03-29 17:17:46 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: implement COPY_MERGE + +2011-03-29 16:52:21 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * win32/common/libgstreamer.def: + buffer: clean up _span and add more g_return_if.. + +2011-03-29 16:22:46 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Fix sanity checks for request pad templates without % + +2011-03-29 13:51:25 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: optimize memory handling + +2011-03-29 11:57:58 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Add some more sanity checks to the pad name checking of request pads in all cases + Especially check if a pad with that name already exists. + +2011-03-29 11:52:06 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Check %u too when trying to find a pad template for a request pad + +2011-03-29 11:31:30 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: move implementation details in private struct + +2011-03-28 21:01:13 +0200 Fraxinas + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix arbitrary sink + source pad naming + Use the string provided by the caller for the sinkpad name + if possible. Note that all sanity checking for this name + is already done in GstElement. + Fixes Bug #645931 + +2011-03-29 11:18:36 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Add some more documentation about the behaviour of funnel + +2011-03-29 11:08:57 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Send a newsegment event after flush-stop + +2011-03-29 11:07:48 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Some random cleanup + +2011-03-29 10:56:00 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + funnel: Use a GstPad subclass for the sinkpads instead of using the pad's element private data + +2011-03-29 10:42:31 +0200 Sebastian Dröge + + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-staticelements.xml: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfunnel.c: + * plugins/elements/gstfunnel.h: + * tests/check/Makefile.am: + * tests/check/elements/funnel.c: + funnel: Integrate into the build system and rename the types + +2011-03-29 10:39:42 +0200 Sebastian Dröge + + * plugins/elements/gstfunnel.c: + * plugins/elements/gstfunnel.h: + * tests/check/elements/funnel.c: + funnel: Import funnel element from farsight2 + +2011-03-29 11:07:36 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstpad.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + * tests/check/gst/gstbuffer.c: + * win32/common/libgstreamer.def: + buffer: more buffer updates + +2011-03-28 20:20:39 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: fix defs + +2011-03-28 20:11:20 +0200 Wim Taymans + + Merge branch 'master' into 0.11-fdo + Conflicts: + gst/gst.c + libs/gst/base/gstcollectpads.c + +2011-03-28 19:19:44 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * libs/gst/base/gstbasetransform.c: + buffer: fix subbuffers + +2011-03-28 16:40:24 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: implemet trim and set_size + +2011-03-28 15:52:17 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * win32/common/libgstreamer.def: + buffer: more fixes + +2011-03-28 10:28:02 +0200 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.h: + buffer: add more methods + +2011-03-24 21:21:00 +0100 Wim Taymans + + * gst/gst.c: + gst: add class init + +2011-03-24 21:18:52 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * libs/gst/base/gstadapter.c: + * tests/check/elements/filesrc.c: + * tests/check/gst/gstmeta.c: + * tests/check/gst/gstpad.c: + * tests/check/libs/adapter.c: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + buffer: fix remaining unit tests + +2011-03-24 20:09:02 +0100 Wim Taymans + + * gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + buffer: fix unit test + +2011-03-24 13:01:00 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * libs/gst/base/gstadapter.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstmeta.c: + * tests/check/gst/gstpad.c: + memory: remove memory metadata again + +2011-03-24 11:49:46 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmemory.c: + * tests/check/libs/adapter.c: + memory: more fixes + Automatically make the memory of a buffer writable when the buffer is writable + and the memory is asked to mapped WRITE. + Add docs + +2011-03-23 20:52:27 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbytewriter.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gstvalve.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstminiobject.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/typefindhelper.c: + memory: more work on implementing buffer memory + +2011-03-22 20:51:06 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + * tests/check/gst/gstbuffer.c: + * tests/check/libs/adapter.c: + * tests/check/libs/bitreader.c: + * tests/check/libs/bytereader.c: + * tests/check/libs/test_transform.c: + * tests/check/libs/transform1.c: + memory: more work on porting the unit tests + +2011-03-21 19:15:27 +0100 Wim Taymans + + * tests/check/elements/fakesrc.c: + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + * tests/check/elements/identity.c: + * tests/check/elements/multiqueue.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstelementfactory.c: + * tests/check/gst/gstmeta.c: + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/typefindhelper.c: + tests: make some tests compile + +2011-03-21 18:13:55 +0100 Wim Taymans + + * docs/manual/advanced-dataaccess.xml: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * gst/gstutils.c: + * gst/gstvalue.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * libs/gst/check/gstcheck.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + * tests/examples/adapter/adapter_test.c: + * tools/gst-launch.c: + memory: port code to new buffer data API + +2011-03-21 13:07:42 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferpool.c: + * gst/gstmemory.c: + * gst/gstmemory.h: + * gst/gstmeta.c: + * gst/gstpad.c: + memory: more fixes + Fix span and is_span + Implement buffer memory + +2011-03-21 09:51:53 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmemory.h: + WIP use memory in buffer + +2011-03-20 11:42:39 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: more improvements + +2011-03-19 10:45:37 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: more memory improvements + +2011-03-18 21:45:39 +0100 Wim Taymans + + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add more memory operations + +2011-03-18 19:28:17 +0100 Wim Taymans + + * gst/Makefile.am: + * gst/gst.h: + * gst/gstmemory.c: + * gst/gstmemory.h: + memory: add memory implementation + +2011-03-18 18:35:42 +0100 Wim Taymans + + * gst/gstmemory.h: + memory: add API for handling memory blocks + Adds some API to handle memory blocks. + +2011-03-08 18:18:24 +0000 Wim Taymans + + * gst/gstmeta.h: + meta: fix docs + +2011-03-28 21:21:00 +0530 Arun Raghavan + + * gst/gstbin.c: + * libs/gst/base/gstbasesrc.c: + basesrc: Return FALSE if we don't handle an event + basesrc's default event handler returns TRUE regardless of whether the + event is handled or not. This fixes the handler to conform with the + expected behaviour (which is to only return TRUE when the event has + actually benn handled). gst_bin_do_latency_func() depended on this + (incorrect) behaviour, and is now modified as well. + (Remaining 1-liner change in gstbasesrc.c is to keep gst-indent happy) + +2011-03-25 22:08:41 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 193b717 to 1ccbe09 + +2011-03-25 14:55:39 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From b77e2bf to 193b717 + +2011-03-25 09:27:58 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From d8814b6 to b77e2bf + +2011-03-25 08:59:37 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6aaa286 to d8814b6 + +2011-03-24 18:48:41 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 6aec6b9 to 6aaa286 + +2011-03-24 18:27:09 +0200 Stefan Kost + + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gstqueue.h: + docs: fix some gtk-doc warnings + Document the queue leaky enums. + +2011-03-24 18:25:08 +0200 Stefan Kost + + * plugins/elements/gstqueue2.c: + queue2: set max value for to the matching one for the datatype + The property is guint64, so use G_MAXUINT64 instead of G_MAXUINT. + +2011-03-24 13:22:57 +0200 Stefan Kost + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.c: + docs: cleanup and xref fixes + Deal with the hints from gtk-doc and fix the xrefs. Apply a work-around for () + precedence over @. Move "MT Safe" text to doc body in many places. Trim eol + whitespaces. + +2011-03-23 16:42:24 +0200 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: print flow return as a name in debug log + +2011-03-23 17:13:58 +0200 Stefan Kost + + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + docs: do xrefs for non installed books too + Get the xrefs from the builddir for the books in the same packages. This fixes + the cross references if one does not have the docs already installed. + +2010-04-19 20:39:53 +0200 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: Keep downstream caps order when fixating + This allows use to use the first intersecting format prefered by downstream. + https://bugzilla.gnome.org/show_bug.cgi?id=617045 + +2010-04-19 20:40:56 +0200 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: Retain caps order when getting caps + If the element gave us caps in a specific order, let's retain that + by intersecting against the template but retaining the order given + by the element. + https://bugzilla.gnome.org/show_bug.cgi?id=617045 + +2011-02-25 10:25:26 -0300 Thiago Santos + + * tests/check/gst/gstcaps.c: + tests: caps: Tests for the new caps intersection mode + Adds test cases for the caps 'first' intersect mode + Adds another test for the 'zigzag' mode + Fixes #617045 + +2011-02-25 08:50:12 -0300 Edward Hervey + + * gst/gst.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * win32/common/libgstreamer.def: + gstcaps: new API : gst_caps_intersect_full + Just like gst_caps_intersect, but adds a new parameter 'mode' + that allows selecting the intersection algorithm to use. + Currently we have GST_CAPS_INTERSECT_MODE_ZIG_ZAG (default) and + GST_CAPS_INTERSECT_MODE_FIRST. + API: gst_caps_intersect_full + API: GstCapsIntersectMode + API: GST_CAPS_INTERSECT_MODE_ZIG_ZAG + API: GST_CAPS_INTERSECT_MODE_FIRST + https://bugzilla.gnome.org/show_bug.cgi?id=617045 + +2011-03-12 17:01:39 +0000 Tim-Philipp Müller + + * 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-12 16:58:01 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.h: + * libs/gst/base/gstbytewriter.h: + bytereader, bytewriter: fix up inline functions to make g++ happy + gstbytereader.h: In function ‘guint8* gst_byte_reader_dup_data_unchecked(GstByteReader*, guint)’: + gstbytereader.h:249:75: error: invalid conversion from ‘void*’ to ‘guint8*’ + gstbytewriter.h: In function ‘gboolean _gst_byte_writer_ensure_free_space_inline(GstByteWriter*, guint)’: + gstbytewriter.h:196:75: error: invalid conversion from ‘void*’ to ‘guint8*’ + https://bugzilla.gnome.org/show_bug.cgi?id=645595 + +2011-03-22 16:26:56 -0300 Thiago Santos + + * gst/gstelement.h: + gstelement: Fix typo in the docs + GST_ELEMENT_INFO will post a INFO message, not a WARNING + +2011-03-18 08:22:23 -0300 Thiago Santos + + * gst/gsttagsetter.c: + tagsetter: Removing unused debug category + tagsetter's debug category had a typo and was unused. Removing it. + +2011-03-18 19:34:57 +0100 Luis de Bethencourt + + * autogen.sh: + autogen: wingo signed comment + +2011-03-22 11:04:20 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't leak objects when flushing after dequeueing and before pushing the object + +2011-03-21 17:54:10 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.h: + multiqueue: Really remove unused variable + +2011-03-21 17:52:13 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Increment unique item counter with atomic operations + Before it was only protected by the stream lock but every pad + has its own stream lock, making the protection rather useless. + +2011-03-21 17:17:22 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Unblock all waiting pads when shutting down + +2011-03-21 12:39:34 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Remove unused variable + +2011-03-21 16:28:37 +0100 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Exit loop function if the pad is flushing + Fixes possible deadlocks when flushing an unlinked pad that waits + for other pads to advance. + +2011-03-19 17:06:12 -0500 Jason D. Clinton + + * gst/gstpoll.c: + * libs/gst/controller/gstinterpolation.c: + * plugins/elements/gstfilesrc.c: + build: fix build with -Werror with GCC 4.6.0 + This touches three areas of code, removes unused variables and discards + return values from two functions with (void). + https://bugzilla.gnome.org/show_bug.cgi?id=645267 + +2011-03-19 10:39:28 +0100 Sebastian Dröge + + * gst/gstevent.h: + event: Add since marker to GST_EVENT_SINK_MESSAGE + +2011-03-19 08:55:57 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Stop waiting for a pad switch when the pad is flushing + +2011-03-19 08:50:06 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Move locking and signalling macros from the header to the source file + +2011-03-17 23:42:48 +0000 Tim-Philipp Müller + + * gst/gsttask.h: + task: fix GST_TASK_BROADCAST + Surprisingly enough, you can't "breadcast" on a GCond. + Spotted by Rune Sætre. + https://bugzilla.gnome.org/show_bug.cgi?id=645022 + +2011-03-17 14:21:17 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Hold the selector lock while reading properties of the active pad + +2011-03-17 14:10:49 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Make sure that EOS is always sent downstream for the active pad + It can happen that the currently active pad got the EOS event + before it was activated and the previously active pad got the + EOS event after it was deactivated. In that case we have to + send the EOS event from an inactive pad downstream. + +2011-03-16 18:19:11 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Return GST_FLOW_OK until the selected pad pushed something downstream + This makes sure that during switches at no point in time all pads + have returned not-linked, which can happen when playing an audio-only + file with playbin2 and switching between the streams for example. + Fixes bug #644935. + +2011-03-17 10:53:49 +0100 Sebastian Dröge + + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + utils: Remove deprecated gst_element_factory_can_{sink,src}_caps() + +2011-03-17 10:50:43 +0100 Sebastian Dröge + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstbufferlist.c + +2011-03-16 12:01:21 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Document that pad blocks only make sense for sink pads in pull mode and src pads in push mode + See bug #644907. + +2011-03-16 11:53:53 +0100 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: The internally linked pad of the proxypad is the ghostpad + Previously we were returning the peerpad, which is the target + of the ghostpad. + +2011-02-25 16:20:49 +0100 Jonas Holmberg + + * gst/gstbufferlist.c: + * tests/check/gst/gstbufferlist.c: + bufferlist: Use a GQueue instead of a GList + Adding a buffer to the end of a GstBufferList is supposed to be a fast + operation, but it was not since the iterator does not advance its + nextpointer when adding buffers and GList does not have a tail pointer. + Using a GQueue to store the buffers makes it easier to add buffers to + the end of the list and this operation will now be much more efficient. + Adding an entire GList of buffers using + gst_buffer_list_iterator_add_list() will however have to iterate over + the list being added to be able to update the tail pointer in the + GQueue. + +2011-03-10 17:48:26 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + * win32/common/libgstreamer.def: + utils: fix ABI break when compiling gstreamer with -DGST_DISABLE_DEPRECATED + GST_DISABLE_DEPRECATED should only affect visibility of declarations in headers, + not actually remove symbols. See GitDeveloperGuidelines and DeprecatingAPI + pages in wiki. + https://bugzilla.gnome.org/show_bug.cgi?id=402141 + +2011-03-10 16:46:04 +0100 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Update .def file for API addition + +2011-03-10 10:25:07 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-03-09 16:15:33 +0200 Stefan Kost + + * docs/pwg/advanced-types.xml: + pwg: fix element name "videodrop" to "videorate" + +2011-03-08 12:11:08 +0200 Stefan Kost + + * tests/check/gst/gstelementfactory.c: + test: add tests for new element_factory api. + +2010-06-23 22:00:04 +0200 Thijs Vermeir + + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + gstutils: replace gst_element_factory_can_{sink,src}_caps + Add new functions to clarify how the caps are compared to the template caps of + the element factory. Improve the docs to point out the difference. + Deprecate: gst_element_factory_can_{src|sink}_caps + API: add gst_element_factory_can_{src|sink}_{any|all}_capps + https://bugzilla.gnome.org/show_bug.cgi?id=402141 + +2011-03-07 23:13:56 +0200 Stefan Kost + + * tests/check/gst/gstcaps.c: + tests: add a unit test for gst_caps_new_simple + Add a test for the crash in bug #642271. + +2011-03-08 18:05:42 +0000 Wim Taymans + + * docs/design/part-meta.txt: + docs: rename draft to official doc + +2011-03-08 16:58:49 +0000 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * tests/check/gst/gstmeta.c: + meta: implement transform function + Replace subbuffer and copy vmethods by a more generic transform function that + can then be parametrised by transform specific data. This should allow us to + implement make-writable and more future transform functions. + +2011-03-08 17:06:30 +0000 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-03-08 11:55:29 +0200 Stefan Kost + + * tests/check/gst/gstelementfactory.c: + tests: add test to create a factory + +2011-03-08 10:36:30 +0200 Stefan Kost + + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstelementfactory.c: + tests: start a new test suite for element factories + Move one test from gstelement suite. + +2011-03-08 11:34:19 +0200 Stefan Kost + + * gst/gstpadtemplate.c: + padtemplate: add missing ; in example (and trim whitespace) + +2011-03-08 09:58:55 +0200 Stefan Kost + + * gst/gststructure.c: + structure: gst_structure_empty_new() does better error checking + No need to check for media_type!=NULL as the function we call that actual create + the structure does a full check anyway. + +2011-03-08 10:06:23 +0200 Stefan Kost + + * gst/gstcaps.c: + * gst/gststructure.c: + caps,structure: trim trailing whitespace + +2011-03-04 08:28:25 +1000 Jonathan Matthew + + * gst/gstcaps.c: + caps: don't create broken caps for invalid media types + Check if structure has been created before appending it to the caps. Free the + caps in the case of an error to not conceal it be returning empty caps. + Fixes #642271 + +2011-03-07 16:21:47 +0200 Stefan Kost + + * tests/examples/helloworld/helloworld.c: + examples: update hello world example + Our helloworld example thatw e reference from the manual has been a bit + complicated to serve a first contact with gstreamer. Since we have and + promote playbin2 as a playback api use it here. + Based on work from Mathias Hasselmann + Fixes #424143 + +2011-03-04 19:02:33 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: update metadata draft + +2011-03-04 18:11:19 +0100 Wim Taymans + + * gst/gstminiobject.c: + miniobject: remove FIXME + Now that we don't subclass buffers anymore, the FIXME about limited + functionality of the copy function is irrelevant. + +2011-03-04 17:43:24 +0100 Wim Taymans + + * gst/gst.c: + gst: add flag registration + +2011-03-04 17:25:02 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + pad: more preroll lock to basesink + Move the preroll lock to basesink where it belongs. + +2011-03-04 16:05:44 +0100 Wim Taymans + + * docs/design/draft-bufferpool.txt: + docs: update bufferpool draft + +2011-03-04 12:06:11 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferpool.c: + bufferpool: add more debug info + +2011-03-03 18:38:32 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: add debug + +2011-03-03 18:21:31 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: add some more debug info + +2011-03-03 16:31:49 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * gst/gstquark.c: + * gst/gstquark.h: + bufferpool: add caps to the config + Add the caps to the configuration parameters of the pool. + Initialize the private data + +2011-03-02 11:57:40 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update defs + +2011-03-02 11:57:06 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: release buffer to pool in dispose + Use the dispose method to release the buffer to the pool when it is configured. + +2011-02-22 12:35:45 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + buffer: add pool to buffer structure + Keep a pointer to the bufferpool. Release the buffer to the pool when + finalizing. Make sure the pool sets itself as the pool member of buffers that it + sends out. + +2011-02-22 12:35:06 +0100 Wim Taymans + + * gst/gst.c: + gst: add pool flags type + +2011-02-22 11:05:09 +0100 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + docs: update bufferpool docs + +2011-02-21 18:43:19 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: Refactor stopping of the pool + Move some methods around. + Make sure we check for config parsing errors. + Increment the outstanding buffers before calling acquire so that we can be sure + that set_active() doesn't free the pool from under us. + +2011-02-21 17:33:38 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: Rework buffer management a little + Add start/stop methods to allow for bulk allocation of buffers. + Free buffers only when all outstanding buffers returned. + Make things more threadsafe wrt flushing and starting/stopping by + keeping track of start and stop method calls. + +2011-02-21 12:18:41 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: memory management cleanups + Use a lock to protect concurrect execution of set_config and set_active. + Start freeing the buffers when flushing and all buffers are returned to the + pool. + Make a copy of the config to avoid crashing with concurrent access. + +2011-02-18 16:35:46 +0100 Stefan Kost + + * gst/gstbufferpool.c: + bufferpool: also allow NULL params in _acquire + +2011-02-18 16:15:30 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: more updates + Keep track if the buffer is configured and block activation when not configured + yet. + Keep track of outstanding buffers and disallow configuration when not all + buffers are returned to the pool. We need to do this or else we might end up + with wrong buffers in the pool. + Add return value to set_active. + Small cleanups. Fix finalize. + +2011-02-18 12:50:21 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: rename 'flushing' to 'active' + Rename the flushing variable and methods to active to better match + the other gstreamer name conventions + +2011-02-17 18:37:19 +0100 Wim Taymans + + * gst/gstbufferpool.c: + bufferpool: prealloc when unset flushing + According to the design doc we need to prealloc buffers when we unset the + flushing state, not in set_config. + Set the flushing state better. + +2011-02-17 17:29:27 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstquark.c: + * gst/gstquark.h: + bufferpool: use quarks for structure fields + +2011-02-17 16:46:51 +0100 Wim Taymans + + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + * win32/common/libgstreamer.def: + bufferpool: use GstStructure to configure the pool + Use a GstStructure to provide the pool with the right configuration. Also + provide some helper methods to configure such a structure. + don't pass the config in alloc_buffer, pool implementation will already have + parsed it during set_config. + Update defs + +2011-02-17 12:55:37 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + fix defs + +2010-11-02 18:56:29 +0100 Wim Taymans + + * gst/Makefile.am: + * gst/gst.h: + * gst/gstbufferpool.c: + * gst/gstbufferpool.h: + bufferpool: add simple bufferpool helper object + +2011-03-02 11:08:34 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + gst/gstregistry.h + +2011-03-02 13:55:36 +0530 Arun Raghavan + + * docs/faq/git.xml: + faq: Minor update to ssh key generation commands + fd.o requires RSA keys, and in general, users would probably want to + make a per-server key file rather than overwrite id_rsa, id_rsa.pub. + +2011-02-28 18:43:41 +0100 Mark Nauwelaerts + + * configure.ac: + configure.ac: export plugin description more platform independent + Fixes #642504. + +2011-02-28 18:32:07 +0100 Mark Nauwelaerts + + * common: + Automatic update of common submodule + From 1de7f6a to 6aec6b9 + +2011-02-28 15:01:54 +0000 Tim-Philipp Müller + + * gst/gstregistry.h: + * gst/gstutils.c: + * libs/gst/controller/gsthelper.c: + docs: typo fixes + convinience -> convenience + +2011-02-28 14:56:23 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: print "pad-added", "pad-removed" and "no-more-pads" signals for elements with sometimes pads + It's often not obvious to people that elements like e.g. uridecodebin + (or demuxers) automatically support the standard signals of the + GstElement class, so let's print the useful pad-related ones for + elements with sometimes pads. + +2011-02-28 16:27:01 +0200 Stefan Kost + + * gst/gstutils.c: + docs: small updates as suggested on a blog + Link from convinience api to the underlying api. + +2011-02-28 10:05:47 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: add timing metadata + +2011-02-28 10:05:38 +0100 Wim Taymans + + * gst/gstminiobject.h: + miniobject: fix whitespace + +2011-02-28 09:39:44 +0100 Wim Taymans + + * tests/check/gst/gstmeta.c: + tests: add memory unit test + +2011-02-27 20:54:58 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + meta: simplify a bit + +2011-02-27 20:42:15 +0100 Wim Taymans + + * gst/gstmeta.c: + * gst/gstmeta.h: + * win32/common/libgstreamer.def: + meta: add default memory metadata + Add a metadata implementation for normall malloced memory. + +2011-02-27 19:40:45 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstmeta.h: + * tests/check/gst/gstmeta.c: + * win32/common/libgstreamer.def: + meta: separate add and get methods + Make separate api for getting and adding metadata. This allows us to pass extra + parameters to the init functions when creating metadata, which is needed for + specific API implementations. + Add beginnings of memory metadata. + +2011-02-27 12:21:32 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + * gst/gstminiobject.h: + * win32/common/libgstreamer.def: + docs: update docs and defs + +2011-02-26 18:14:36 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: remove useless method + Remove the method to retrieve metadata by api. One will always use the + GstMetaInfo to get metadata. + +2011-02-25 16:31:11 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: remove owner_priv now that we have metadata + Now that we have metadata we can remove the owner_priv field. + +2011-02-25 13:23:19 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: fix defs + +2011-02-25 13:15:25 +0100 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbuffermeta.c: + * gst/gstmeta.c: + * gst/gstmeta.h: + * tests/check/Makefile.am: + * tests/check/gst/gstmeta.c: + metadata: Rename to GstMeta + Rename to the shorter GstMeta + Add docs + Add api to get metadata by API + +2011-02-25 10:37:07 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: fix defs + +2010-11-15 11:49:24 +0100 Philippe Normand + + * gst/gstbuffer.c: + buffer: fix memory corruption + +2010-04-07 11:34:23 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffermeta.c: + * tests/check/gst/gstbuffermeta.c: + buffermeta: fix compilation + +2010-02-26 13:11:43 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + * gst/gstbuffermeta.h: + updates + +2009-12-27 22:03:32 +0100 Wim Taymans + + * tests/check/gst/gstbuffermeta.c: + meta: improve test a little + +2009-12-17 12:34:42 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbuffermeta.c: + * gst/gstbuffermeta.h: + * tests/check/Makefile.am: + * tests/check/gst/gstbuffermeta.c: + * win32/common/libgstreamer.def: + buffermeta: add beginnings of buffer metadata + Add first implementation of arbitrary buffer metadata. We use a simple linked + linked of slice allocated metadata chunks. Future implementations could use + something more performant. + Add get, remove, iterate methods to handle the metadata. + +2011-02-25 10:19:25 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + design: add api tag + We want to find metadata based on the API it implements and based on the + specific implementation. + +2011-02-24 17:11:49 +0000 Tim-Philipp Müller + + * gst/gsturi.c: + uri: make win32 buildbot happy + gsturi.c:854:16: error: unused variable 'abs_clean' + gsturi.c:788:1: error: 'gst_file_utils_canonicalise_path' defined but not used + +2011-02-24 15:32:00 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * tests/check/elements/filesrc.c: + filesrc, filesink: fix URI creation regression for non-absolute locations + Passing e.g. location=foo would lead to warnings because g_filename_to_uri() + wants an absolute file path and returns NULL otherwise. Use brand-new + gst_filename_to_uri() instead, which will try harder to create a proper + URI for us. + Also add unit test. + +2011-02-24 15:18:43 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: + * gst/gsturi.h: + * win32/common/libgstreamer.def: + uri: add gst_filename_to_uri() that takes relative filenames + Add function that (unlike the GLib equivalent) also accepts paths that + aren't absolute and will clean up relative markers such as ./ and ../ + before forming a URI. + Fixes warnings with e.g. filesrc location=foo ! typefind caused by the + recent switch to g_filename_to_uri(), but also actually creates valid + URIs for the first time. + Windows code paths could need some more work, e.g. we don't clean up + the relative markers there for now (because path could have \ and / + as separators). + API: gst_filename_to_uri() + +2011-02-24 16:20:01 +0200 Stefan Kost + + * tests/check/gst/gstabi.c: + * tests/check/libs/libsabi.c: + tests: refix the tests (missing #endif) + +2011-02-24 16:11:17 +0200 Stefan Kost + + * tests/check/Makefile.am: + Makefile.am: add new abi headers to nodist_HEADERS + +2011-02-21 11:24:45 +0200 Stefan Kost + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + gst-launch: add index support + When option "-i" is given, set an index object on the pipeline and compute + statistics for all index writers. Print a sumary when shutting down the + pipeline. + +2011-02-24 15:12:14 +0200 Stefan Kost + + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_arm.h: + tests: add abi check data for ARM (libs) + +2011-02-24 15:02:37 +0200 Stefan Kost + + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_arm.h: + tests: add abi check data for ARM + +2011-02-24 13:55:35 +0100 Wim Taymans + + * gst/gstbuffer.h: + buffer: add owner private as intermediate solution + Add an owner private field where the owner of a buffer can store some extra + information. We can use this to implement most of the subclassing that happens + now. Later this will be removed and replaced by arbitrary buffer metadata. + +2011-02-24 10:28:20 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: remove poisoning + +2011-02-23 16:48:00 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstminiobject.h: + * gst/gstquery.c: + miniobject: cleanups + Use the stored size in the miniobject to free the miniobject. + Refactor some init methods. + +2011-02-23 15:43:49 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting guide + +2011-02-23 12:54:21 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting guide + +2011-02-23 12:44:54 +0100 Wim Taymans + + * gst/gstcaps.h: + caps: warn when make_writable result is ignored + +2011-02-23 12:08:03 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: fix defs + +2011-02-23 12:01:55 +0100 Wim Taymans + + * gst/gst.c: + gst: fix type registration + We need to have the types of the miniobjects before registering the + tranforms. + +2011-02-23 12:01:16 +0100 Wim Taymans + + * gst/gstelementfactory.c: + elementfactory: improve caps string management + +2011-02-23 12:00:42 +0100 Wim Taymans + + * gst/gstminiobject.c: + miniobject: clear flags in init + +2011-02-23 12:33:58 +0200 Stefan Kost + + * docs/gst/running.xml: + docs: tell that ORC_CODE can contain a list of flags + +2011-02-23 10:31:44 +0100 Wim Taymans + + * gst/gstbuffer.h: + * gst/gstminiobject.h: + miniobject: fix flags + +2011-02-22 19:30:59 +0100 Wim Taymans + + * gst/gstevent.c: + fix compilation after rebase + +2010-11-02 13:31:25 +0100 Wim Taymans + + * gst/gst.c: + * gst/gst_private.h: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * plugins/elements/gsttypefindelement.c: + improve type registration + +2010-11-02 12:58:14 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstcaps.c: + * gst/gstelementfactory.c: + * gst/gstminiobject.c: + * gst/gstregistrychunks.c: + fix compilation + +2009-12-07 20:32:12 +0100 Wim Taymans + + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstquery.h: + fix macros + +2009-12-05 15:18:09 +0100 Wim Taymans + + * gst/gstpad.c: + pad: set boxed type correctly + +2009-12-05 14:16:57 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstevent.c: + miniobject: small fixes + Make dataflow happen. + +2009-12-04 23:52:32 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstcaps.c: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstpad.c: + * gst/gstquery.c: + * gst/gsttaglist.c: + * gst/gstvalue.c: + * libs/gst/base/gstbasesink.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gsttypefindelement.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstutils.c: + * tests/check/gst/gstvalue.c: + * tests/check/gst/struct_x86_64.h: + * tools/gst-inspect.c: + miniobject: more boxed type fixing + More miniobject fixing, leaks horribly somewhere.. + +2009-12-04 22:32:38 +0100 Wim Taymans + + * gst/gstcaps.h: + * gst/gstevent.c: + * gst/gstmarshal.list: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstpad.c: + miniobject: make queries a boxed type + More minionject stuff. + +2009-12-03 20:49:30 +0100 Wim Taymans + + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstelementfactory.c: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + messages: make message a simple boxed type + +2009-12-02 21:21:48 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + miniobject: work on making caps a boxed type + More work on making miniobject a simple allocated struct. + +2009-11-29 00:21:24 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcaps.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstquery.h: + miniobject: make miniobject a boxed type + First attempt at making miniobject a simple boxed type. + +2011-02-22 19:09:48 +0100 Wim Taymans + + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + libs: cleanups for 0.11 + Remove deprecated stuff, fix padding, rearrange methods. + +2011-02-22 16:04:12 +0100 Wim Taymans + + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstindex.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstplugin.h: + * gst/gstregistry.h: + * gst/gstsegment.h: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + * gst/gsttask.c: + * gst/gsttask.h: + cleanups + Fix padding, remove deprecated symbols. + +2011-02-22 15:08:51 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2011-02-22 14:11:59 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + Conflicts: + configure.ac + gst/gstelement.c + gst/gstelement.h + gst/gstpad.c + gst/gstutils.c + libs/gst/base/Makefile.am + libs/gst/check/Makefile.am + libs/gst/controller/Makefile.am + libs/gst/dataprotocol/Makefile.am + libs/gst/net/Makefile.am + win32/common/libgstreamer.def + +2011-02-14 18:05:09 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + * tests/check/libs/transform1.c: + basetransform: Be smarter with pad allocs + Avoid doing unnecessary pad-allocs when on passthrough mode. + If multiple basetransform elements are on a pipeline, they + would do a pad-alloc for each received buffer, each element + would do this, so we would have lots of pad allocs on the + pipeline for a single buffer being pushed through it. + This patch attempts to reduce this amount by avoiding + doing pad-allocs if the element has already done it + after the last pushed buffer. So it will only be allowed + to do a new pad-alloc after it has pushed a buffer, so we get + 1x1 pad-alloc and buffer ratio + https://bugzilla.gnome.org/show_bug.cgi?id=642373 + +2011-02-21 13:39:38 +0100 Philip Jägenstedt + + * gst/gstindex.c: + docs: fix typo in gst_index_new() docs + https://bugzilla.gnome.org/show_bug.cgi?id=642869 + +2011-02-21 12:44:05 +0000 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + fakesink: print new MEDIA4 flag as well + +2011-01-03 11:37:05 +0100 Robert Swain + + * gst/gstbuffer.h: + * gst/gstminiobject.h: + miniobject, buffer: steal miniobject flag for use as MEDIA4 buffer flag + This was required to add a new MEDIA4 buffer flag for indicating + progressive/mixed telecine video buffers. There is no space for + additional flags in GstBuffer, so steal one from GstMiniObject. + https://bugzilla.gnome.org/show_bug.cgi?id=642671 + +2011-02-20 16:11:27 +0000 Tim-Philipp Müller + + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + docs: add some more Since: markers to atomic queue docs + +2011-02-21 11:55:50 +0100 Edward Hervey + + * gst/gstelement.c: + Revert "element: Call ->release_pad() to clean up pad" + This commit changes the request pad behaviour for plugins and applications. + Reopens Bug #402562 + The proper fix for that bug is to keep track of created request pads. + This reverts commit a5e44ffffaa6d7a8d7af8dcb77e37990996253a5. + +2011-02-21 10:03:16 +0200 Stefan Kost + + * gst/gstindex.c: + index: add FIXME-0.11: comments + +2011-02-15 10:57:08 +0200 Stefan Kost + + * gst/gstindex.c: + docs: improve index docs + +2011-02-18 17:09:14 +0200 Stefan Kost + + * docs/design/part-progress.txt: + docs: spell-check + +2011-02-15 19:15:16 -0800 David Schleef + + * plugins/elements/gstfakesink.c: + fakesink: print buffer flags + +2010-12-04 18:53:55 -0800 David Schleef + + * gst/gstelement.c: + element: Call ->release_pad() to clean up pad + Fixes #636011 and #402562. + +2011-02-17 14:50:40 +0200 Stefan Kost + + * gst/gstindex.c: + index: fix creation of writer id for unparented pads + Also do some cleanup in the impl. + +2011-02-17 10:34:37 +0000 Tim-Philipp Müller + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: add (de)serialisation function for uchar + .. since we sadly have a plugin in -good that has a uchar property + (cmmlenc) + https://bugzilla.gnome.org/show_bug.cgi?id=642522 + +2011-02-16 19:54:57 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix include order atomicqueue: fix include order# Please enter the commit message for your changes. Lines starting + +2010-10-28 13:27:43 +0100 Wim Taymans + + * gst/gstbus.c: + * gst/gstbus.h: + bus: make the bus almost lockfree + Use new GstPoll functionality to wakeup the mainloop. + Use an atomic queue on the writer side to post the messages. + The reader side it protected with the lock still because we don't want multiple + concurrent readers. + +2011-02-16 17:21:52 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: fix defs file for new symbols + +2011-02-16 17:14:11 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: use correct array sizes + +2011-02-16 16:21:58 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: fix docs some more + +2011-02-16 16:19:46 +0100 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + atomicqueue: add refcounting and docs + +2011-02-16 12:48:59 +0100 Wim Taymans + + * gst/gstatomicqueue.c: + atomicqueue: make sure a min initial_size is used + +2010-10-28 16:02:39 +0100 Wim Taymans + + * gst/Makefile.am: + * gst/gstatomicqueue.c: + * gst/gstatomicqueue.h: + atomicqueue: add an atomic queue + Add an atomic queue. The queue can be used from multiple threads simultaneously + and without taking any locks or doing any blocking operations. This makes it + highly scalable for things like the bus, bufferpools and object recycling. + +2011-02-16 17:14:46 +0100 Wim Taymans + + * tests/check/gst/gstbus.c: + check: fix a leak in the bus unit test + +2011-02-16 17:28:15 +0100 Wim Taymans + + * gst/gst.c: + deinit: add progress type class unref + +2011-02-16 15:13:05 +0200 Stefan Kost + + * gst/gstutils.c: + utils: tell also what pad a pad is already linked against + +2011-02-15 22:56:35 +0100 Sebastian Dröge + + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + file{sink,src}: Check if non-URI characters are escaped, but only for the URI not the location property + +2011-02-15 22:49:26 +0100 Sebastian Dröge + + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: + file{src,sink}: Fix unit tests + filesink and filesrc should return exactly the same URI as passed + and must not escape path separators. + +2011-02-15 22:48:44 +0100 Sebastian Dröge + + * plugins/elements/gstfilesink.c: + filesink: Fix escaping of URIs + Especially don't escape / as path separators + +2011-02-15 22:05:31 +0100 Andoni Morales Alastruey + + * plugins/elements/gstfilesrc.c: + filesrc: Fix escaping of file uris + Fixes bug #642393. + +2011-02-15 18:26:00 +0100 Wim Taymans + + * gst/gstmessage.c: + * gst/gstquark.c: + * gst/gstquark.h: + message: add timeout to progress message + Add a timeout member to the progress messages to let the application know about + the timeout so that it can do some gui things with it. + +2011-02-15 18:14:16 +0100 Wim Taymans + + * docs/design/part-progress.txt: + design: mention timeout in the progress message + +2011-02-15 17:20:08 +0100 Wim Taymans + + * docs/design/part-progress.txt: + design: make progress draft official + +2011-01-06 18:55:43 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + message: rename category to code + +2011-01-06 15:58:47 +0100 Wim Taymans + + * gst/gstmessage.c: + message: add new message quark + +2011-01-06 15:58:23 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + docs: add more standard categories + +2011-01-05 13:53:00 +0100 Wim Taymans + + * gst/gst.c: + gst: register new type + +2011-01-05 13:48:51 +0100 Wim Taymans + + * tests/check/gst/gstmessage.c: + check: add progress message unit test + +2011-01-05 13:41:08 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + message: add progress message functions + +2011-01-05 13:39:19 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + docs: update progress field + Avoid naming the progress free text field 'message' as it conflicts with the + message itself. + +2011-02-15 14:42:58 +0100 Mark Nauwelaerts + + * plugins/elements/gstqueue2.c: + queue2: don't read beyond the end of file upstream in pull mode + ... which could lead to a premature eos being reported downstream, + rather than a successful partial read which would result when + performed directly on e.g. basesrc. + +2011-01-26 16:46:25 +0800 Chen Rui + + * gst/gstutils.c: + utils: return real error in compatible link check + We need to ensure we call gst_pad_check_link() with the two pads in the correct + order. The order depends on wheter we iterate src or sink pads. + Signed-off-by: Chen Rui + +2011-02-14 17:31:25 +0100 Wim Taymans + + * gst/gstpad.c: + pad: Check sinkpad for flushing + Check the sinkpad for the flushing state before calling the chainfunction on the + pad. We do this by checking the cache (which is also cleared on the srcpad when + the sink is set to flushing). + Fixes #641928 + +2011-02-11 17:47:17 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: Check for pad alloc caps when suggestion is not fixed + If after computing the suggestion with downstream caps we still have + a non-fixed suggestion caps try to intersect with the input caps + of the pad alloc to avoid useless renegotiations. + https://bugzilla.gnome.org/show_bug.cgi?id=642130 + +2011-02-14 14:00:38 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve duration calculation + Keep track of the average distance between incomming timestamps and + use that to estimate the frame duration when buffers have no duration set on + them. + +2011-02-14 13:49:10 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve rate calculation + When there is no duration on input buffers, assume the rate is 1.0 + instead of (the undefined) 0.0. + +2011-02-14 13:47:02 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve average duration calculation + Improve the calculation of the duration. When we have no input duration set on + the input buffers stop is set to start and then we end up using a 0 duration in + the average calculation. + +2011-02-14 12:21:39 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: rename variable + Rename an internal variable to better reflact what its value means. + +2011-02-14 15:39:21 +0200 Stefan Kost + + * gst/parse/grammar.y: + parse-launch: trim whitespaces + +2011-02-14 15:37:23 +0200 Stefan Kost + + * gst/parse/grammar.y: + parse-launch: fix typo in pad-list length comparision + It was comparing the length with itself. + Fixes #642071. + +2011-02-14 12:52:30 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From f94d739 to 1de7f6a + +2011-02-13 22:56:15 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: pretty-print datetime tags + +2011-02-10 23:30:21 +0000 Tim-Philipp Müller + + * gstreamer.doap: + gstreamer.doap: update mailing list host + +2011-02-10 14:53:34 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix some comments + +2011-02-10 14:50:04 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: keep track of earliest QoS timestamp + Keep track of the earliest allowed timestamp according to the latest + QoS report and drop buffers before that time. Activate this filter + when throttling is enabled. We could later also activate this in the + other QoS cases. + See #638891 + +2011-02-10 14:17:12 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: use new QoS type + Use the new QoS type and send throttling QoS messages. + +2011-02-10 13:42:05 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * win32/common/libgstbase.def: + basesink: add property to configure a throttle-time + Add a property to configure the throttle time on a sink. The + property is not yet used. + See #638891 + +2011-02-10 12:02:03 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstevent.c: + * gst/gstevent.h: + * tests/check/gst/gstevent.c: + * win32/common/libgstreamer.def: + event: add QoS event type + Add a parameter to the QoS event to specify the QoS event type. + Update docs and add unit test. + See #638891 + +2011-02-10 12:00:47 +0100 Wim Taymans + + * gst/gstclock.c: + clock: fix parameter docs + +2011-02-10 10:49:22 +0100 Wim Taymans + + * docs/design/part-qos.txt: + design: tweak docs a little + +2011-02-10 10:34:57 +0100 Wim Taymans + + * docs/design/part-qos.txt: + design: update QoS document + Add new QoS types and talk about the new throttle QoS message. + +2011-02-10 13:46:08 +0000 Tim-Philipp Müller + + * docs/design/draft-bufferpool.txt: + docs: fix some typos in the bufferpool draft + +2011-02-10 10:19:38 +0000 Tim-Philipp Müller + + * gst/gstevent.c: + events: fix g-i annotation for gst_event_new_tag() which takes ownership of the tag list + +2011-02-10 00:02:23 +0000 Tim-Philipp Müller + + * docs/manual/basics-bins.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-pads.xml: + * gst/gstbin.c: + * gst/gstelement.c: + docs: mention that it's necessary to set the state of elements added to an already-running pipeline + https://bugzilla.gnome.org/show_bug.cgi?id=641631 + +2011-02-09 16:22:04 +0100 Wim Taymans + + * docs/design/draft-bufferpool.txt: + design: add draft for first ideas for a bufferpool feature + Add a first draft with some ideas and use cases for the implementation + for bufferpools. The purpose is to be able to make elements negotiate + their buffer requirements as well as provide an infrastructure to + preallocate and reuse buffers in an easy way. + +2011-02-09 15:23:13 +0200 Stefan Kost + + * gst/gsttaglist.h: + docs: clarify the NOMINAL_BITRATE docs + Tell that its a target bitrate and actual values might be different. + +2011-02-03 15:17:13 +0100 Mark Nauwelaerts + + * gst/gstpoll.c: + poll: trigger rebuild setup in _new + Failing to do so in the Windows case (implicitly triggered otherwise) + would have a subsequent _wait return immediately leading to high CPU + usage timeout loops. + Fixes #640675. + +2011-02-03 10:53:27 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + * gst/gstinfo.h: + info: make adding/removing of gst_debug_log_default() work properly + Make adding/removing gst_debug_log_default() work reliably in all + circumstances. The problem was that depending on platform and linker + flags the function argument might resolve to different addresses, + which made it impossible to remove the default log function added + in gst_init() from application code (because the pointer values + didn't match). The new approach should keep things simple by passing + NULL for the default function, which the code in libgstreamer can + then handle. + https://bugzilla.gnome.org/show_bug.cgi?id=625396 + https://bugzilla.gnome.org/show_bug.cgi?id=640771 + +2011-02-03 10:28:01 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + Revert "info: use the publicly visible address to fix the tests" + This reverts commit eb56687a6dfd207507a4ca000eae53f93b5e33ea. + While this commit may have fixed a problem on one of the build bots, + it didn't actually fix the original bug reported for win32. + Also, it causes other problems, such as the lookup failing when + called from C++ code (gst-phonon, amarok). + This needs to be fixed differently. + https://bugzilla.gnome.org/show_bug.cgi?id=640771 + https://bugzilla.gnome.org/show_bug.cgi?id=625396 + +2011-02-02 15:35:45 +0100 Mark Nauwelaerts + + * plugins/elements/gstqueue2.c: + queue2: properly identity dequeued event as such + ... which avoids terminating with ERROR rather than UNEXPECTED. + +2011-02-02 02:07:58 +0000 Peter Collingbourne + + * scripts/gst-uninstalled: + gst-uninstalled: use $GST_PREFIX variable + This makes it easier to change the prefix by editing the script. + https://bugzilla.gnome.org/show_bug.cgi?id=641212 + +2010-08-19 22:43:07 +0300 Sreerenj Balachandran + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: add a new "encoded-by" tag + Usecase: ID3v2 TENC ("Encoded by") frame. + API: GST_TAG_ENCODED_BY + https://bugzilla.gnome.org/show_bug.cgi?id=627268 + +2011-01-29 18:02:11 +0100 Mark Nauwelaerts + + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnettimeprovider.h: + net: 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-31 15:58:18 +0000 Tim-Philipp Müller + + * gst/gstbus.c: + * tests/check/gst/gstbus.c: + bus: honour any per-thread default main context set via g_main_thread_push_thread_default() + Makes gst_bus_add_watch(), gst_bus_add_watch_full(), gst_bus_add_signal_watch(), + and gst_bus_add_signal_watch_full() convenience functions automatically pick up + any non-default main contexts set for the current thread via + g_main_thread_push_thread_default(). + +2011-01-28 15:36:33 -0500 Olivier Crête + + * plugins/elements/gstvalve.c: + valve: Only set discont on the first buffer after drops + Reset the discont member after setting discont on the first buffer after + dropping. + +2011-01-28 19:08:08 +0000 Bastien Nocera + + * gst/gstelement.c: + GstElement: Fix warning with GCC 4.6 + gstelement.c: In function ‘gst_element_get_request_pad’: + gstelement.c:1052:18: error: variable ‘tmp’ set but not used [-Werror=unused-but-set-variable] + https://bugzilla.gnome.org/show_bug.cgi?id=640850 + +2011-01-27 09:28:07 +0000 Tim-Philipp Müller + + * plugins/elements/gstidentity.c: + identity: print unset buffer timestamps or durations as 'none' + Like fakesink and fakesrc do. + +2011-01-12 16:03:30 +0200 Stefan Kost + + * plugins/elements/gsttypefindelement.c: + typefind: don't take object lock for reading the found caps + Once we switch to normal mode, we're not typefinding anymore and thus the caps + will not change. Therefore can avoid the object lock in the data-flow path. + The locking was added in order to fix bug #608877. + +2011-01-25 09:39:45 +0800 Zhang Wanming + + * docs/design/part-gstbin.txt: + * docs/design/part-gstghostpad.txt: + * docs/random/caps: + * docs/random/omega/TODO-0.1.0: + * docs/random/thomasvs/capturing: + * docs/random/wtay/events: + * docs/random/wtay/events3: + * docs/slides/outline: + docs: fix a few more typos + https://bugzilla.gnome.org/show_bug.cgi?id=640502 + +2011-01-25 18:48:40 +0000 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + docs: flesh out typefindelement docs some more + Mention that have-type signal may be emitted from streaming + thread or application thread, and fix a typo. + +2011-01-12 16:03:57 +0200 Stefan Kost + + * plugins/elements/gsttypefindelement.c: + typefind: code and comment cleanups + Make code two places of the code the pushes the buffer store more similar. More + comments and debug logging. + +2011-01-12 13:05:06 +0200 Stefan Kost + + * gst/gsttrace.c: + trace: ensure messages are \0 terminated + +2011-01-12 12:58:44 +0200 Stefan Kost + + * libs/gst/net/gstnettimeprovider.c: + nettimeprovider: handle invalid network addresses earlier + Handle inet_aton() return code. + +2011-01-12 12:44:59 +0200 Stefan Kost + + * libs/gst/check/gstconsistencychecker.c: + checks: add a comment to indicate that we intentionally leave out the 'break' + +2011-01-12 12:43:04 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + registry: remove dead code + The GError is only used for the mmap operations. If we have an error we handle + and clean it there already. + +2011-01-12 09:33:53 +0200 Stefan Kost + + * libs/gst/controller/gstcontroller.c: + docs: small controller api docs improvement + +2011-01-11 15:09:52 +0200 Stefan Kost + + * plugins/elements/gsttypefindelement.c: + typefind: canonicalize signal name + +2011-01-11 15:09:30 +0200 Stefan Kost + + * plugins/elements/gsttypefindelement.c: + docs: mention have-type signal in the docs. + +2011-01-25 09:15:49 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + docs: minor gst-launch man page fix + Transmitter/receiver pipelines were mislabelled. Spotted by Majin. + +2011-01-25 16:09:18 +1000 Jan Schmidt + + * tests/check/elements/multiqueue.c: + multiqueue test: Remove workaround for pad_task hangs + Remove code that isn't needed any longer, which sets the multiqueue + to PLAYING and back before unreffing, in order to avoid a deadlock + waiting for gstpad tasks that were never started. The problem seems + to have been fixed long ago. + +2011-01-25 00:20:34 +0800 Cai Yuanqing + + * docs/design/part-MT-refcounting.txt: + design docs: fix 2 typos in part-MT-refcounting + +2011-01-24 17:46:15 +0800 Yang Xichuan + + * docs/design/part-gstbin.txt: + design docs: part-gstbin.txt fix typo + Signed-off-by: Yang Xichuan + +2011-01-19 15:48:26 +0000 Vincent Penquerc'h + + * docs/design/part-block.txt: + * docs/design/part-bufferlist.txt: + * docs/design/part-clocks.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-overview.txt: + * docs/design/part-preroll.txt: + * docs/design/part-push-pull.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + * docs/design/part-states.txt: + * docs/design/part-streams.txt: + * docs/design/part-synchronisation.txt: + design docs: fix a few typos and a thinko + +2011-01-11 17:43:57 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + clock: API: Add function to re-init periodic GstClockIDs + +2011-01-20 14:37:25 +0000 Vincent Penquerc'h + + * gst/gstpluginloader.c: + gstpluginloader: do not leak the description string + The description string was changed to an inlined string a while back. + (But: no need to intern the const strings here, we just use the interning + to avoid allocating duplicates and make memory management easier, + since the strings will be around for the life-time of the app anyway). + https://bugzilla.gnome.org/show_bug.cgi?id=640071 + +2011-01-22 15:33:58 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: clarify docs + +2011-01-11 10:33:32 +0100 Wim Taymans + + * docs/design/part-buffering.txt: + design: update buffering doc + Add strategies to buffering doc + +2011-01-24 11:53:12 +0200 Mart Raudsepp + + * gst/gstclock.c: + * gst/gstclock.h: + docs: add missing "Since: 0.10.32" markers for GstClock + Since tags were missing for gst_clock_single_shot_id_reinit() + and GST_CLOCK_DONE. + +2011-01-24 10:56:21 +0200 Mart Raudsepp + + * plugins/elements/gstqueue2.c: + docs: Fix GstQueue2:ring-buffer-max-size property Since tag (0.10.31, not 0.10.30) + +2011-01-24 10:26:45 +0200 Mart Raudsepp + + * gst/gststructure.c: + docs: add missing "Since: 0.10.31" marker for gst_structure_get_date_time() + +2011-01-24 14:22:27 +0000 Tim-Philipp Müller + + * tests/check/pipelines/parse-launch.c: + tests: add unit test for read-beyond-end-of-string bug + https://bugzilla.gnome.org/show_bug.cgi?id=639674 + +2011-01-24 14:16:37 +0000 Miguel Angel Cabrera Moya + + * gst/parse/types.h: + parse-launch: don't read past end of string if last character is an escape char + When the last character of a property value is a backslash + the unescaping code reads one byte pass the end of the string. + https://bugzilla.gnome.org/show_bug.cgi?id=639674 + +2011-01-14 09:21:23 +0000 Tim-Philipp Müller + + * docs/manuals.mak: + docs: hack a charset=utf-8 into pwg/adm html versions + So the encoding of the original document is respected and + displays properly in browsers where the encoding autodetection + fails to recognise that it's utf-8. + https://bugzilla.gnome.org/show_bug.cgi?id=639448 + +2011-01-13 15:41:50 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: don't leak xml file name if GST_CHECK_XML is set + Spotted by nvineeth@gmail.com + +2011-01-23 23:45:40 +0000 Tim-Philipp Müller + + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development + +=== release 0.10.32 === + +2011-01-21 10:25:32 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.32 + +2011-01-20 19:07:35 +0000 Tim-Philipp Müller + + * configure.ac: + Revert "configure: require gobject-introspection >= 0.9.12" + This reverts commit 3a59d416af6d0f8b61e2460830eb6f1138929ec2. + Reverting this, as the feature we bumped the requirement for + didn't actually work properly or help with the issue we were + trying to fix (and it was fixed differently in the end). + +2011-01-18 22:51:49 +0000 Tim-Philipp Müller + + * docs/manual/advanced-threads.xml: + docs: fix spelling of 'threshold' in app dev manual + +2011-01-18 10:10:05 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.31.4 pre-release + +2011-01-18 09:04:51 +0000 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + gobject-introspection: try harder to make g-ir-scanner use the right libgstreamer + Apply fix from libgstbase to all core libs now that we know that it + works. Should fix problems with g-ir-scanner using the wrong + (ie. system) libgstreamer, leading to linking errors such as + undefined reference to `gst_clock_single_shot_id_reinit'. + https://bugzilla.gnome.org/show_bug.cgi?id=637549 + +2011-01-14 00:20:43 +0000 Tim-Philipp Müller + + * docs/manuals.mak: + * docs/pwg/pwg.xml: + docs: fix garbled UTF-8 characters when generating app dev manual ps/pdf + https://bugzilla.gnome.org/show_bug.cgi?id=639448 + +2011-01-13 20:12:16 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + gobject-introspection: another attempt to make g-i find the right libgstreamer + Turns out g-i puts the additional -L we specify at the end, helpfully. + https://bugzilla.gnome.org/show_bug.cgi?id=637549 + +2011-01-12 15:46:00 +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. + +2011-01-12 10:17:05 +0000 Tim-Philipp Müller + + * libs/gst/controller/Makefile.am: + controller: update g-i include paths as well for header changes + Hopefully makes Lucid and Maverick build bots happy again + +2011-01-11 18:39:06 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.31.3 pre-release + +2011-01-11 18:38:37 +0000 Tim-Philipp Müller + + * po/LINGUAS: + * po/gl.po: + * po/pt_BR.po: + * po/sv.po: + po: update translations + +2011-01-11 19:26:40 +0100 Benjamin Otte + + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + controller: Fix headers to use < > in #include statements + The behavior of " " in include statements is implementation-defined - + see the C standard, section 6.10.2 or + http://stackoverflow.com/questions/21593 + +2011-01-11 19:14:28 +0100 Benjamin Otte + + * libs/gst/net/Makefile.am: + gstnet: Fix --c-include for gir generation + Previously it was - probably due to copy/paste error - looking for + gstbase headers. + It's changed now to only include the one public header for gstnet.h + +2011-01-11 13:47:38 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + gobject-introspection: make g-ir-scanner try harder to find the right libgstreamer + It's not quite clear to me why g-ir-scanner doesn't get this info from + the pkg-config file, nor why libtool doesn't get it from the .la. + https://bugzilla.gnome.org/show_bug.cgi?id=637549 + +2011-01-11 13:05:12 +0000 Tim-Philipp Müller + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + pkgconfig: also add libdir to -uninstalled .pc files + This way we can find the paths to pass e.g. g-ir-scanner for + uninstalled setups. + https://bugzilla.gnome.org/show_bug.cgi?id=639039 + +2011-01-11 15:49:23 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From e572c87 to f94d739 + +2011-01-11 15:10:32 +0200 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: fixe the property link and the sice docs + +2011-01-11 12:46:31 +0000 Raimo Järvi + + * gst/gstpoll.c: + gstpoll: fix compiler warning with MingW + gstpoll.c: In function 'gst_poll_get_read_gpollfd': + gstpoll.c:692:10: warning: assignment makes integer from pointer without a cast + https://bugzilla.gnome.org/show_bug.cgi?id=638900 + +2011-01-10 14:37:41 -0300 Thiago Santos + + * tests/check/elements/selector.c: + test: outputselector: Add another negotiation test + Adds an unit test to check that the output-selector works + when negotiating before srcpads are requested + +2011-01-10 14:19:17 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + outputselector: Improve get and set caps functions + Improve sink pad getcaps and setcaps by handling the case where + no src pads exist yet + +2011-01-10 16:35:25 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From ccbaa85 to e572c87 + +2011-01-10 14:52:40 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 46445ad to ccbaa85 + +2011-01-10 09:59:19 -0300 Thiago Santos + + * tests/check/elements/selector.c: + tests: selector: unref peer pad + Do not forget to unref peer's pad on output-selector negotiation + tests + +2011-01-10 13:18:16 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: make sure we wait and release the live lock + Make sure we release the live lock and wait in all cases when we need to wait + for the playing or flushing state change. + Fixes #635785 + +2011-01-08 14:52:27 +0100 Edward Hervey + + * gst/gstregistry.c: + registry: Don't replace valid existing plugins by blacklisted ones + Only replace existing plugins by blacklisted ones if they correspond + to the exact same plugin. If they're not the same, keep the existing + valid one. + Fixes #638941 + +2011-01-08 02:19:31 +0000 Tim-Philipp Müller + + * configure.ac: + * gst-element-check.m4.in: + * scripts/gst-uninstalled: + configure, gst-uninstalled: remove a few bashism + https://bugzilla.gnome.org/show_bug.cgi?id=638961 + +2011-01-07 12:13:37 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + 0.10.31.2 pre-release + +2011-01-07 02:18:37 +0000 Tim-Philipp Müller + + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + indexers: fix two small leaks + element factory plugin_names are interned strings these days. + +2011-01-07 00:53:11 +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, 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 19:40:27 +0000 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: ignore old libgstvalve.so and libgstselector.so plugins to minimize upgrade pain + Ignore plugins which have been moved into coreelements, so it's + still possible to just upgrade GStreamer core without having to + upgrade the whole stack. + +2011-01-06 19:21:56 +0000 Tim-Philipp Müller + + * gst/gstpadtemplate.c: + Revert "padtemplate: allow disablinbg the template name conformance checks" + This reverts commit f9039c22040e1a38a3691bc4d299af427c963255. + We use -DG_DISABLE_ASSERTS for releases and pre-releases, but + don't want to disable pad name checking for releases in general, + I think. Need a better solution here. Fixes pad unit test in + pre-release/release mode. + +2011-01-04 12:42:50 -0300 Thiago Santos + + output-selector: Add pad-negotiation-mode property + Adds getcaps/setcaps to output-selector and adds a property + to select which type of negotiation should be done. + The available modes are: + * none: no negotiation (current behavior), getcaps return ANY and + setcaps aren't set on any of the peers + * all: use all pads (default), getcaps returns the intersection of + peer pads and setcaps is set on all peers + * active: getcaps and setcaps are proxied to the active pad + https://bugzilla.gnome.org/show_bug.cgi?id=638381 + +2011-01-06 18:18:29 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + docs: mention extra input-selector pad properties + https://bugzilla.gnome.org/show_bug.cgi?id=638381 + +2011-01-06 17:47:38 +0000 Tim-Philipp Müller + + * po/LINGUAS: + * po/el.po: + po: update translations + +2010-09-23 12:49:59 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: avoid unnecessary malloc/free for each log function call on MSVC + Avoid unnecessary malloc/free to get the file basename on MSVC to avoid + unnecessary overhead when doing GST_DEBUG=foo:5 or so (since it would be + done before the category log level filtering). + +2011-01-06 17:29:46 +0000 christian schaller + + * gstreamer.spec.in: + Update spec file with latest changes and enable GIR + +2011-01-05 12:59:48 -0800 David Schleef + + * gst/gstobject.c: + object: Fix creation of default name + Change the fixed allocation (!) to g_strdup_printf(). + +2010-12-20 13:30:43 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstutils.c: + * win32/common/libgstreamer.def: + GstElement: Add a more flexible way to get request pads. + The new request_new_pad_full vmethod provides an additional caps field, + which allows elements to take better decision process. + Also, add a gst_element_request_pad() function to allow developers to be + able to specify which pad template they want a pad of. + Convert gstutils to use that new method instead of the old one when more + efficient. + This is useful for being able to request pads in a more flexible way, + especially when the element can provide pads whose caps depend on + runtime configuration and therefore can't provide pre-registered + pad templates. + API: GstElement::request_new_pad_full + API: gst_element_request_pad + https://bugzilla.gnome.org/show_bug.cgi?id=637300 + +2011-01-05 15:53:28 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + inputselector: remove "select-all" property + select-all mode is a bit broken (e.g. newsegment event + handling), so remove that for now. The funnel element + in farsight provides similar functionality. + https://bugzilla.gnome.org/show_bug.cgi?id=539042 + https://bugzilla.gnome.org/show_bug.cgi?id=638381 + +2011-01-05 15:36:55 +0000 Tim-Philipp Müller + + * gst/gst.c: + gst: remove safety check for GLib < 2.8 + Don't worry about accidentally using GLib < 2.8 at runtime anymore. + +2011-01-05 11:26:13 +0100 Edward Hervey + + * gst/gstdatetime.c: + gstdatetime: Disable usage of GDateTime on MacOSX + GLib's GDateTime doesn't handle properly the gmt offset. Therefore + use our own internal version instead on MacOSX. + See bug #638666 + +2011-01-05 10:56:37 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + design: more updates for the progress messages + +2011-01-04 18:36:41 +0100 Edward Hervey + + * docs/pwg/building-signals.xml: + pwg: Fix link to GObject documentation + Better have gnome.org than viagra :) + +2011-01-03 20:32:23 +0100 Edward Hervey + + * gst/gstpluginloader.c: + pluginloader: Always mark reception as complete after EXIT + Avoids waiting forever on gst_poll_wait when using the select + backend. + Fixes #637057 + +2011-01-04 00:48:15 +0000 Tim-Philipp Müller + + * gst/gstconfig.h.in: + gstinfo: don't use printf extensions if GLib isn't using the system printf + Might help with https://bugzilla.gnome.org/show_bug.cgi?id=638599 + +2011-01-03 20:19:05 +0100 Edward Hervey + + * gst/gstpoll.c: + gstpoll: Fix for (p)select backend + We need to reset the revents field of each pollfd when reading the results + from select else we'll end up with stray info from previous calls to + select. + +2011-01-03 01:06:06 +0000 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: make new gst_value_list_merge() work properly + Fix freeing of partially-inited list value when both values + passed are equal and we want to return a single non-list + value as result. Fixes unit test. Also fix up docs a bit. + https://bugzilla.gnome.org/show_bug.cgi?id=637776 + +2010-12-21 23:03:12 +0200 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstreamer.def: + tags: don't produce duplicated entries when merging same value twice + Add a variant of gst_value_list_concat() that skips duplicates and use that when + merging taglists. + API: gst_value_list_merge() + +2011-01-02 16:58:39 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + basesrc, basesink: add some FIXMEs for the type of the blocksize property + +2010-12-31 12:08:19 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + inputselector: make pad's get_type function thread-safe + +2010-12-31 11:37:56 +0000 Tim-Philipp Müller + + * plugins/elements/gstselector-marshal.list: + * plugins/elements/gstselector.c: + coreelements: remove unused files + +2010-12-31 12:27:45 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Protected g_object_notify() calls for the active-pad with a recursive mutex + This works around a thread safety problem in GLib < 2.26.0 and should + be removed when we depend on 2.26.0. + Fixes bug #607513. + +2010-12-31 16:52:54 +0800 Zhang Wanming + + * tests/check/gst/gstutils.c: + tests: fix typo + Signed-off-by: Zhang Wanming + +2010-12-31 16:50:57 +0800 Zhang Wanming + + * plugins/elements/gstfdsink.c: + gstfdsink: fix typo + Signed-off-by: Zhang Wanming + +2010-12-31 16:50:17 +0800 Zhang Wanming + + * docs/random/ensonic/draft-bufferpools.txt: + docs: fix typo + Signed-off-by: Zhang Wanming + +2010-12-30 18:02:06 -0800 David Schleef + + * plugins/elements/gstdataurisrc.c: + dataurisrc: use g_ascii_strcasecmp() + +2010-12-31 01:09:40 +0000 Tim-Philipp Müller + + * tests/icles/output-selector-test.c: + tests: remove output-selector test which needs elements from -base + Move it to -base instead. + +2010-12-31 00:59:53 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + checks: enable input-selector and output-selector unit tests after move + +2010-12-31 00:48:55 +0000 Tim-Philipp Müller + + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + docs: add input-selector and output-selector to docs + +2010-12-31 00:45:54 +0000 Tim-Philipp Müller + + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstqueue2.c: + coreelements: GST_BOILERPLATE already sets parent_class + +2010-12-31 00:43:37 +0000 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstoutputselector.c: + input-selector, output-selector: minor clean-ups + +2010-12-30 18:57:13 +0000 Tim-Philipp Müller + + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstinputselector.c: + coreelements: move input-selector and output-selector to core + Moved to core from gst-plugins-bad. + https://bugzilla.gnome.org/show_bug.cgi?id=614306 + +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. + +2010-09-17 09:52:12 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + outputselector: Avoid losing the last_buffer when switching + This patch makes outputselector take an extra ref when pushing + the last_buffer to avoid it losing it during the switch function. + This makes resend-latest properly work if the active-pad is changed + during the switch function buffer pushing (on a pad probe, for example). + https://bugzilla.gnome.org/show_bug.cgi?id=629917 + +2010-09-17 09:44:02 -0300 Thiago Santos + + * plugins/elements/gstoutputselector.c: + outputselector: Recheck pending switch after pushing buffer + This patch makes output-selector always recheck if there's a + pending pad switch after pushing a buffer, preventing that + it pushes a buffer on the 'wrong' pad. + https://bugzilla.gnome.org/show_bug.cgi?id=629917 + +2010-11-01 23:04:44 +0200 Stefan Kost + + * plugins/elements/gstinputselector.c: + inputselector: log times in human readable form + +2010-11-01 22:40:36 +0200 Stefan Kost + + * plugins/elements/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-10-19 13:43:14 +0300 Stefan Kost + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstoutputselector.c: + various (gst): add missing G_PARAM_STATIC_STRINGS flags + Canonicalize property names as needed. + +2010-09-06 11:03:07 +0300 Stefan Kost + + * plugins/elements/gstinputselector.c: + inputselector: sync with copy in -base + Use _get_caps_reffed to avoid copies. + +2010-08-24 11:50:47 +0300 Stefan Kost + + * plugins/elements/gstoutputselector.c: + outputselector: move the debug init to the boilerplate macro + +2010-08-24 11:50:09 +0300 Stefan Kost + + * plugins/elements/gstinputselector.c: + inputselector: use GST_BOILERPLATE macro + +2010-03-22 13:16:33 +0100 Benjamin Otte + + * tests/check/elements/selector.c: + Add -Wwrite-strings + and fix its warnings + +2010-03-21 21:39:18 +0100 Benjamin Otte + + * tests/check/elements/selector.c: + Add -Wmissing-declarations -Wmissing-prototypes to configure flags + And fix all warnings + +2010-03-18 17:30:26 +0100 Benjamin Otte + + * plugins/elements/gstinputselector.c: + * plugins/elements/gstoutputselector.c: + gst_element_class_set_details => gst_element_class_set_details_simple + +2010-01-25 12:21:34 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + Revert "inputselector: Protect g_object_notify() with the object's mutex" + This reverts commit 7e067615ffb5614f068f7753c10dde99afe49c3c, it's causing + deadlocks with playbin2. + +2010-01-24 20:53:00 +0100 Kipp Cannon + + * plugins/elements/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. + +2009-11-09 11:49:15 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Remove useless variables and fix a uninitialized variable compiler warnings + Merged from gst-plugins-base, dfd51aa82a9e1c9924375183796eab70e574a231. + +2009-11-09 11:48:39 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Make sure that running_time->timestamp calculation never becomes negative + Merged from gst-plugins-base, f3653854585864a09d35e037853407332ea6901f. + +2009-11-09 11:48:00 +0100 Sebastian Dröge + + * plugins/elements/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. + Merged from gst-plugins-base, 27034be4611231cc55fa3d3e253baa40c6bff41d. + +2009-11-09 11:47:15 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Improve debugging + Merged from gst-plugins-base. + +2009-11-05 13:53:46 +0100 Wim Taymans + + * plugins/elements/gstinputselector.c: + Revert "inputselector: use get_caps_reffed()" + This reverts commit 49ec4f796a0e3f88a851708782c853baf4b05724. + We can't use this new function yet. + +2009-11-05 13:29:55 +0100 Wim Taymans + + * plugins/elements/gstinputselector.c: + inputselector: use get_caps_reffed() + +2009-11-04 00:21:19 +0200 Stefan Kost + + * plugins/elements/gstinputselector.c: + inputselector: also add inline to the proto to fix the build + +2009-11-03 18:14:12 +0100 Edward Hervey + + * plugins/elements/gstinputselector.c: + gst: Remove dead assignments and resulting unused variables + Merged from gst-plugins-base, 8cd1b5209b68944e1be56ca8bb69e46d4abb7a34. + +2009-11-03 18:12:21 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Use the same iterate internal links function as in gst-plugins-base + +2009-11-03 18:11:13 +0100 Tim-Philipp Müller + + * plugins/elements/gstinputselector.c: + input-selector: 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. + Merged from gst-plugins-base, 6f4c1ac58341ee189225d313ddfe9ae24a65c88c. + +2009-11-03 18:09:55 +0100 David Schleef + + * plugins/elements/gstinputselector.c: + input-selector: Remove Ronald Bultje from Authors field + Replaced with "GStreamer maintainers + " or just removed, + depending on the number of other authors. + Merged from gst-plugins-base, 0e9bc5125aca546d773ed1002df573dd8e2dc136. + +2009-11-03 18:08:05 +0100 Wim Taymans + + * plugins/elements/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. + Merged from gst-plugins-base, bdfb4b46d746ef298fcf44260879c342af4cafa3. + +2009-11-03 18:06:11 +0100 Wim Taymans + + * plugins/elements/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. + Merged from gst-plugins-base, 5b72f2adf996739036e8d9b5f91005455d1fface. + +2009-10-27 11:51:05 -0700 Michael Smith + + * tests/icles/output-selector-test.c: + Remove executable bits from non-executable files. + +2009-09-25 11:07:02 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Use new single iterator for the internally linked pads + This fixes a deadlock and removes some useless code. + +2009-08-31 19:31:57 +0200 Havard Graff + + * plugins/elements/gstoutputselector.c: + outputselector: make GST_FORMAT_TIME the default segment format + +2009-08-19 17:05:32 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Use iterate internal links instead of deprecated get internal links + +2009-07-31 11:27:03 +0300 Tommi Myöhänen + + * plugins/elements/gstoutputselector.c: + outputselector: check for pending srcpad in _get_property() + If there is a pending srcpad, return it instead of active srcpad + in gst_output_selector_get_property() function. + +2009-06-12 10:14:27 +0300 Stefan Kost + + * plugins/elements/gstoutputselector.c: + outputselector: do the pad_alloc for the pad that is pending and have a fallback + We should do the pad_alloc for the pending pad if any, as we will switch to that + pad on next _chain() call. Also do a fallback alloc, if there is no output yet to + not fail state transitions in dynamic pipelines. + +2009-06-01 16:31:42 +0300 Lasse Laukkanen + + * plugins/elements/gstoutputselector.c: + output-selector: serialize setting and actual changing of new active pad + +2009-05-04 12:29:54 +0300 Lasse Laukkanen + + * plugins/elements/gstoutputselector.c: + output-selector: unref latest buffer also when resending has been disabled + +2009-04-16 17:32:03 +0300 Lasse Laukkanen + + * plugins/elements/gstoutputselector.c: + output-selector: keep ref to buffer for resending only if explicitly requested + +2009-06-04 19:08:16 +0200 Wim Taymans + + * plugins/elements/gstinputselector.c: + inputselector: don't leak pads in iterator + +2009-06-04 08:56:29 +0200 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Notify when the tags property of the selector sinkpads changes + First part of bug #584686. + +2009-05-28 10:38:50 +0300 Stefan Kost + + * plugins/elements/gstoutputselector.h: + selector: remove not needed instance var (previous commit). + +2009-05-28 10:12:58 +0300 Stefan Kost + + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstoutputselector.h: + outputselector: implement pad_alloc on active pad. + +2009-04-23 11:04:46 +0100 Jan Schmidt + + * plugins/elements/gstinputselector.c: + input-selector: Forward segment events for the active pad immediately. + When a segment event is received on the active pad, forward it downstream + immediately instead of deferring it until the next data buffer arrives. This + fixes problems with segment updates never being sent downstream, like those + needed for sparse streams, or for closing previously opened segments. + This fixes playback of DVD menus with a still video frame and an audio track, + for example. + Fixes: #577843 + +2009-03-27 11:20:02 +0100 Wim Taymans + + * plugins/elements/gstoutputselector.c: + outputselector: reset state when going to READY + Reset the last-buffer, the pending pad and the segment when going to the READY + state. + Fixes #576712. + +2009-03-24 15:23:03 +0100 Wim Taymans + + * plugins/elements/gstinputselector.c: + selector: merge the tags + Merge the tags received on the input-selector sinkpads instead of only keeping + the last one we saw. + +2009-02-25 11:45:05 +0200 Stefan Kost + + * plugins/elements/gstinputselector.c: + docs: various doc fixes + No short-desc as we have them in the element details. + Also keep things (Makefile.am and sections.txt) sorted. + Reword ambigous returns. No text after since please. + +2009-02-11 17:21:20 +0100 Sebastian Dröge + + * plugins/elements/gstinputselector.c: + inputselector: Fix compilation, activate_sinkpad() has no notify parameter + +2009-02-10 16:22:54 -0800 Michael Smith + + * plugins/elements/gstinputselector.c: + input-selector: Activate and notify pad before processing events. + Events should trigger pad selection if we don't already have an + explicitly selected pad, so that events prior to first buffer don't get + lost. + +2009-01-30 18:27:03 -0800 Michael Smith + + * plugins/elements/gstinputselector.c: + Unref event if we don't forward it, unref pads when done with them. + +2008-12-04 17:51:37 +0000 Michael Smith + + plugins/elements/gstinputselector.c: Ensure we emit notify::active-pad when auto-selecting a pad due to it having activit... + Original commit message from CVS: + * plugins/elements/gstinputselector.c: + Ensure we emit notify::active-pad when auto-selecting a pad + due to it having activity and us not having an existing active + pad. Fixes #563147 + +2008-10-15 17:45:37 +0000 Edward Hervey + + plugins/elements/gstinputselector.c: Gracefully handle the cases when we dont' have otherpad. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_input_selector_event), + (gst_input_selector_query): + Gracefully handle the cases when we dont' have otherpad. + Fixes #556430 + +2008-10-07 13:14:40 +0000 Stefan Kost + + plugins/elements/gstoutputselector.c: Choose right pad for sending events. Fixes #555244 + Original commit message from CVS: + * plugins/elements/gstoutputselector.c: + Choose right pad for sending events. Fixes #555244 + +2008-09-08 20:27:23 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Reset the selector state when going to READY. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_reset), + (gst_input_selector_reset), (gst_input_selector_change_state): + Reset the selector state when going to READY. + +2008-09-01 13:23:03 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Reuse the get_linked_pads for both source and sinkpads because they are the same. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_input_selector_init), + (gst_input_selector_event), (gst_input_selector_query): + Reuse the get_linked_pads for both source and sinkpads because they are + the same. + Implement a custum event handler and get the internally linked pad + directly instead of relying on the default (slower) implementation. + +2008-08-27 15:45:16 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Implement the LATENCY query in a better way by taking the latency of all sinkpads an... + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_input_selector_init), + (gst_input_selector_query): + Implement the LATENCY query in a better way by taking the latency of all + sinkpads and taking the min/max instead of just taking a random pad. + +2008-08-05 09:05:35 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Move the select-all logic into the activation of the currently selected pad. We want... + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_bufferalloc), + (gst_selector_pad_chain), (gst_input_selector_getcaps), + (gst_input_selector_activate_sinkpad): + Move the select-all logic into the activation of the currently selected + pad. We want to remember the last pad with activity in select-all mode. + Fix the getcaps function, we can produce the union of the upstream caps + in select-all mode, not the intersection like proxy_getcaps() does. + +2008-06-19 13:18:24 +0000 Stefan Kost + + output-selector: Use BOILERPLATE macro and update test to the latest api changes. + Original commit message from CVS: + * plugins/elements/gstoutputselector.c: + * tests/icles/output-selector-test.c: + Use BOILERPLATE macro and update test to the latest api changes. + +2008-06-12 14:49:18 +0000 Stefan Kost + + 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: + * plugins/elements/gstinputselector.c: + * plugins/elements/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-03-20 18:10:29 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Do g_object_notify() only when not holding the lock to get the property because othe... + Original commit message from CVS: + * plugins/elements/gstinputselector.c: + (gst_input_selector_set_active_pad), (gst_input_selector_switch): + Do g_object_notify() only when not holding the lock to get the property + because otherwise we run into a deadlock with the deep-notify handlers + that are possibly installed. + +2008-03-20 17:48:49 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Release the selector lock when pad alloc happens on a non selected pad. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_class_init), + (gst_selector_pad_event), (gst_selector_pad_bufferalloc), + (gst_selector_pad_chain), (gst_input_selector_set_active_pad): + Release the selector lock when pad alloc happens on a non selected pad. + +2008-03-20 17:07:07 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Add pad property to configure behaviour of the unselected pad, it can return OK or N... + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_class_init), + (gst_selector_pad_init), (gst_selector_pad_set_property), + (gst_selector_pad_get_property), (gst_selector_pad_event), + (gst_selector_pad_bufferalloc), (gst_selector_pad_chain), + (gst_input_selector_set_active_pad): + Add pad property to configure behaviour of the unselected pad, it can + return OK or NOT_LINKED, based on the use case. + +2008-03-20 16:48:46 +0000 Wim Taymans + + plugins/elements/gstinputselector.*: Figure out the locking a bit more. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: + (gst_selector_pad_get_running_time), (gst_selector_pad_reset), + (gst_selector_pad_event), (gst_selector_pad_bufferalloc), + (gst_input_selector_wait), (gst_selector_pad_chain), + (gst_input_selector_class_init), (gst_input_selector_init), + (gst_input_selector_dispose), (gst_segment_set_start), + (gst_input_selector_set_active_pad), + (gst_input_selector_set_property), + (gst_input_selector_get_property), + (gst_input_selector_get_linked_pad), + (gst_input_selector_is_active_sinkpad), + (gst_input_selector_activate_sinkpad), + (gst_input_selector_request_new_pad), + (gst_input_selector_release_pad), + (gst_input_selector_change_state), (gst_input_selector_block), + (gst_input_selector_switch): + * plugins/elements/gstinputselector.h: + Figure out the locking a bit more. + Mark buffers with discont after switching. + Fix initial segment forwarding, make sure to only forward one segment + regardless of what the sequence of buffers/segments is. See #522203. + Improve flushing when blocked. + Return NOT_LINKED when a stream is not selected. + Not API change for the switch signal in the docs. + Fix start/time/accum values of the new segment. + Correctly unlock and flush a blocking selector when going to READY. + +2008-03-14 17:22:21 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Add lots of debugging. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_event), + (gst_selector_pad_bufferalloc), (gst_selector_pad_chain), + (gst_input_selector_class_init), + (gst_input_selector_set_active_pad), + (gst_input_selector_set_property), + (gst_input_selector_push_pending_stop): + Add lots of debugging. + Fix time member in the newsegment event. + +2008-03-13 16:46:04 +0000 Wim Taymans + + plugins/elements/gstinputselector.*: Various cleanups. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_class_init), + (gst_selector_pad_finalize), (gst_selector_pad_get_property), + (gst_selector_pad_event), (gst_input_selector_class_init), + (gst_input_selector_init), (gst_input_selector_set_active_pad), + (gst_input_selector_set_property), + (gst_input_selector_get_property), + (gst_input_selector_request_new_pad), + (gst_input_selector_release_pad), + (gst_input_selector_push_pending_stop), + (gst_input_selector_switch): + * plugins/elements/gstinputselector.h: + Various cleanups. + Added tags to the pads. + Select active pad based on the pad object instead of its name. + Fix refcount in set_active_pad. + Add property to get the number of pads. + * plugins/elements/gstoutputselector.c: + (gst_output_selector_class_init), + (gst_output_selector_set_property), + (gst_output_selector_get_property): + Various cleanups. + Select the active pad based on the pad object instead of its name. + Fix locking when setting the active pad. + * plugins/elements/gstselector-marshal.list: + * tests/check/elements/selector.c: (cleanup_pad), + (selector_set_active_pad), (run_input_selector_buffer_count): + Fixes for pad instead of padname for pad selection. + +2008-02-26 12:01:37 +0000 Stefan Kost + + plugins/elements/gstoutputselector.c: Fix changing to same pad twice before a chain call. + Original commit message from CVS: + * plugins/elements/gstoutputselector.c: + Fix changing to same pad twice before a chain call. + +2008-02-25 08:53:51 +0000 Stefan Kost + + plugins/elements/gstinputselector.*: Added "select-all" property to make it work like aggregator in 0.8. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + Added "select-all" property to make it work like aggregator in 0.8. + * plugins/elements/gstoutputselector.c: + Fix resend-latest behavoiur. + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/selector.c: + Add unit tests for selector. + +2008-02-07 13:48:20 +0000 Stefan Kost + + gst/multifile/gstmultifilesink.c: Add a fixme comment. + Original commit message from CVS: + * gst/multifile/gstmultifilesink.c: + Add a fixme comment. + * plugins/elements/gstoutputselector.c: + Fix same leak as in input-selector. + * tests/icles/output-selector-test.c: + Improve the test. + +2008-02-01 17:08:18 +0000 Wim Taymans + + plugins/elements/gstinputselector.c: Don't leak event on pads that are not linked. Fixes #512826. + Original commit message from CVS: + * plugins/elements/gstinputselector.c: (gst_selector_pad_event): + Don't leak event on pads that are not linked. Fixes #512826. + +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-selectoo (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: + * plugins/elements/.cvsignore: + * plugins/elements/Makefile.am: + * plugins/elements/gstinputselector.c: + * plugins/elements/gstinputselector.h: + * plugins/elements/gstoutputselector.c: + * plugins/elements/gstoutputselector.h: + * plugins/elements/gstselector-marshal.list: + * plugins/elements/gstselector.c: + * plugins/elements/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 00:46:02 +0000 Tim-Philipp Müller + + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + docs: add valve element to documentation + +2010-12-30 00:41:09 +0000 Tim-Philipp Müller + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + valve: some minor clean-ups + +2010-12-30 00:30:18 +0000 Tim-Philipp Müller + + * plugins/elements/gstvalve.c: + valve: fix typo in property description + And rephrase while at it, to make it more concise. + +2010-12-30 00:26:43 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/valve.c: + tests: enable valve unit test + +2010-12-30 00:22:38 +0000 Tim-Philipp Müller + + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstvalve.c: + elements: add new valve element to build + Moved from gst-plugins-bad + https://bugzilla.gnome.org/show_bug.cgi?id=630808 + +2010-10-19 23:40:36 +0100 Tim-Philipp Müller + + * tests/check/elements/valve.c: + tests: fix valve unit test + gst_buffer_pad_alloc() needs simple caps or NULL caps, + ANY caps are not allowed. + +2010-09-28 13:52:29 +0300 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: no need to ref the object in _chain + Don't ref the pad in chain, like elsewhere + +2010-09-30 17:48:35 -0400 Olivier Crête + + * tests/check/elements/valve.c: + tests: Fix caps leak in the valve test + +2010-09-30 17:24:29 -0400 Olivier Crête + + * tests/check/elements/valve.c: + valve: Add unit tests + Add a unit test for the valve element. + +2010-09-30 16:26:19 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + valve: Make the drop variable into an atomic. + Using an atomic allows us to avoid locking the whole object all time time. + As suggested by Stefan Kost. + +2010-09-30 16:22:04 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + valve: Correctly set the DISCONT flag after dropping buffers + +2010-09-30 16:16:47 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + valve: Remove superflous checking casts + +2010-09-30 16:13:23 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + valve: Fix style, improve comments + Minor improvements to the comments and break a few overly long lines + +2010-09-28 14:26:11 +0300 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: move default: parst in the switch statement to the end + Now sure if it matters, but the previous form looks weired. + +2010-09-28 14:23:01 +0300 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: move debug-category registration to type init + +2010-09-28 14:15:13 +0300 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: use G_PARAM_STATIC_STRINGS on properties + +2010-09-28 14:07:39 +0300 Stefan Kost + + * plugins/elements/gstvalve.c: + valve: GST_BOILERPLATE already sets parent_class + +2010-03-18 17:30:26 +0100 Benjamin Otte + + * plugins/elements/gstvalve.c: + valve: gst_element_class_set_details => gst_element_class_set_details_simple + +2009-02-10 18:52:54 +0000 Olivier Crête + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + docs: document valve element + +2009-02-10 17:57:16 +0000 Olivier Crête + + * plugins/elements/gstvalve.c: + fsvalve: rename to valve + +2009-02-10 17:55:47 +0000 Olivier Crête + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + fsvalve: re-indent gst style + +2008-12-13 00:31:45 -0500 Olivier Crête + + * plugins/elements/gstvalve.c: + fsvalve: Ignore errors if dropping is set to true + +2008-12-10 17:00:33 -0500 Olivier Crête + + * plugins/elements/gstvalve.c: + fsvalve: Add getcaps proxying to the valve + +2008-08-20 14:11:02 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + fsvalve: Rebase valve onto gstelement instead of basetransform + +2008-08-19 18:49:51 -0400 Olivier Crête + + * plugins/elements/gstvalve.c: + fsvalve: Revert "Fix refcounting issues in prepare_output_buffer" + This reverts commit 65dd460f0a3a9c4882e638c86208f74ef62c3460. + +2008-08-05 11:30:57 +0000 sjoerd@luon.net + + * plugins/elements/gstvalve.c: + fsvalve: Fix refcounting issues in prepare_output_buffer + 20080805113057-be0f2-9dc270781f0a0f21c616ed11dbd1f198fd1b326e.gz + +2008-04-09 16:32:21 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Remove unused dispose method in valve + 20080409163221-3e2dc-92ccb2db874e46e0d92c15520577c1be0e2bc617.gz + +2007-12-19 20:32:30 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Dont hold the object lock while calling base alloc function + 20071219203230-3e2dc-6519175d8d81496515b2d9060ac316650560f691.gz + +2007-12-19 20:32:18 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + fsvalve: Set the DISCONT flag after dropping buffers + 20071219203218-3e2dc-bc5f03d88ff5837040b9214de016cc142776dfc2.gz + +2007-12-19 00:57:39 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + fsvalve: Use do the alloc_buffer function in the valve + 20071219005739-3e2dc-2a0fdfa2f38f03ab4791fe5c4ab85e8790113683.gz + +2007-11-21 20:08:58 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Only set passthrough to TRUE on newer versions of gst + 20071121200858-3e2dc-b16cdeabbc3c0562c6fc7b11b9b9792c910f569e.gz + +2007-11-21 18:17:29 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Compare minor, not major + 20071121181729-3e2dc-a5997c3b7f5c86966370969714facf8ee242659d.gz + +2007-10-26 22:37:49 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Make the valve element work with gst < 0.10.13 + 20071026223749-3e2dc-18f685a4e45fbdce677ac777586876fc719d7222.gz + +2007-10-24 22:42:46 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + fsvalve: Rename valve to fsvalve + 20071024224246-3e2dc-c54216af2ef0ef3f1a2206d723e87be2a23ab8ed.gz + +2007-10-24 22:41:47 +0000 Olivier Crete + + * plugins/elements/gstvalve.c: + * plugins/elements/gstvalve.h: + fsvalve: Add valve element + 20071024224147-3e2dc-f28ab0c073e283894b65c22c4f44397c897dec01.gz + +2010-12-30 18:31:11 +0000 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + fakesink: make variable static + +2010-12-29 11:48:18 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: fix deadlock + Only go into LIVE_WAIT when the are not live_running and only stop waiting when + live_running is TRUE. If we don't loop, we could deadlock when called from + outside of basesrc, such as baseaudiosrc. + Fixes #635785 + +2010-12-28 16:40:28 +0100 Wim Taymans + + * tests/check/generic/sinks.c: + check: add more sink unit tests + +2010-12-28 16:23:32 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: also preroll async=false sinks + Also preroll async=false sinks after a flush. + +2010-12-22 16:55:33 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + docs: fix typo + +2010-12-26 21:20:31 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstclock.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gstutils.c: + * plugins/elements/gstqueue.c: + Revert "micro-optim: if (x) is cheaper than if (x > 0) for unsigned integers" + This reverts commit 6aa8ca37eeb9debfa6919741a023250bf278248f. + See http://article.gmane.org/gmane.comp.video.gstreamer.devel/32282 + +2010-12-24 14:02:08 -0800 David Schleef + + * plugins/elements/Makefile.am: + elements: reenable fdsrc/fdsink on MSVC + +2010-12-22 16:36:09 -0800 Michael Smith + + * gst/glib-compat-private.h: + Fix GStatBuf definition for win32 when building against older glib. Now matches upstream glib definition. + +2010-12-22 22:36:05 +0000 Tim-Philipp Müller + + * gst/gstminiobject.c: + miniobject: add gobject-introspection annotation + +2010-12-22 16:42:04 +0100 Wim Taymans + + * docs/design/draft-progress.txt: + docs: add draft idea for progress reporting + +2010-12-21 10:33:59 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix typo + +2010-12-20 17:46:36 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 169462a to 46445ad + +2010-12-19 12:49:58 +0100 Sebastian Dröge + + * gst/gstplugin.c: + * gst/gsttaglist.c: + taglist: Don't leak copies of empty strings + +2010-12-17 19:19:40 +0100 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gsttypefindhelper.c: + base: documentation fixups and annotation + +2010-12-17 19:14:41 +0100 Edward Hervey + + * gst/gstbufferlist.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstplugin.c: + * gst/gsttaglist.c: + * gst/gstutils.c: + gst: documentation fixups and annotation + Reported by enabling the --warn-all option of g-ir-scanner + +2010-12-17 15:48:34 +0100 Edward Hervey + + * gst/gstdatetime.c: + gstdatetime: Fix documentation + second => seconds + microsecond argument was dropped + +2010-12-04 15:32:06 +0100 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: Use an atomic integer instead of a lock for checking tags presence + https://bugzilla.gnome.org/show_bug.cgi?id=636455 + +2010-12-16 10:55:20 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Handle downstream giving a buffer with new caps but invalid size + This can happen for example when downstream proposed new caps, later proposed + the previous caps again which in turn enables passthrough mode in upstream + elements and the wrong-sized buffer appears in an element where the caps + change never happened. Simply allocate a new buffer in this case. + See bug #635461. + +2010-12-15 23:19:54 +0200 Stefan Kost + + * gst/gstinfo.c: + info: use the publicly visible address to fix the tests + The -Bsymbolic change causes us to get a different address when internaly + looking up the function than what application would get when the use the symbol + that they see. This made removing the default loghandler to fail, as it is set + internally and removed externaly. + +2010-12-15 14:55:12 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 20742ae to 169462a + +2010-12-15 12:10:02 +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 19:00:14 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve last_stop calculation + Only update the last_stop value when we had a valid stop position for the + clipping or else the clipping code assumes the stop position extends to the end + of the segment, which makes the position reporting return weird values. + +2010-12-14 15:52:22 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix object type handling in queued preroll + Factor out the method to get the object type. + When preroll-queue-len > 0, use the right object type instead of ignoring + buffer-lists. + +2010-12-13 16:22:46 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 011bcc8 to 20742ae + +2010-12-11 10:10:04 +0100 Edward Hervey + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + libs: Fix GIR build for srcdir != builddir + +2010-12-08 17:51:10 +0100 Edward Hervey + + Merge commit '0eaa25cbf5c0e4bf86545fb67c181a0ecd2f19c7' into 0.11 + +2010-12-08 12:17:35 +0200 Stefan Kost + + * libs/gst/base/gstbasesink.c: + docs: fix wrong use of Since: keyword + +2010-12-08 11:52:31 +0200 Stefan Kost + + * gst/gstregistrychunks.c: + registry: maintain the typefind extension list order + +2010-12-08 11:51:59 +0200 Stefan Kost + + * gst/gsttypefindfactory.c: + docs: add () to xref the function. + +2010-12-07 19:35:55 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + utils: remove some dead code, GST_DEBUG_COLOR is never defined + +2010-12-07 19:35:24 +0000 Tim-Philipp Müller + + * gst/gstutils.c: + * gst/gstutils.h: + utils: const-ify arguments to gst_object_default_error() + +2010-12-07 18:46:01 +0000 Tim-Philipp Müller + + * gst/gsterror.c: + docs: gst_error_get_message() returns string in UTF-8, not current locale + We tell gettext to return everything in UTF-8 encoding. + +2010-12-05 20:17:08 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: register gst_pad_get_fixed_caps_func() with the debug log system + +2010-12-07 18:35:56 +0000 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytewriter-docs.h: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gsttypefindhelper.c: + docs: libgstbase: more gobject introspection annotations + Many of these are superfluous and were added for clarity. + +2010-12-07 18:35:04 +0000 Tim-Philipp Müller + + * gst/gst.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstdatetime.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstfilter.c: + * gst/gstfilter.h: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstinfo.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstparse.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpoll.c: + * gst/gstpreset.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstsegment.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttrace.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gsturi.h: + * gst/gstutils.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + docs: gst: more gobject introspection annotations + Many of these are superfluous, added for clarity. + +2010-12-07 18:40:12 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + docs: update docs + +2010-12-07 18:33:51 +0100 Wim Taymans + + * win32/common/libgstcontroller.def: + * win32/common/libgstdataprotocol.def: + * win32/common/libgstreamer.def: + defs: update defs + +2010-12-07 18:32:53 +0100 Wim Taymans + + * tests/check/Makefile.am: + check: disable ABI checks + +2010-12-07 18:32:34 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting document + +2010-12-07 18:14:38 +0100 Wim Taymans + + * gst/gstcompat.h: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * tests/check/gst/gstpad.c: + pad: remove get_caps_reffed variants + Make the _get_caps functions behave like the _get_caps_reffed variants and + remove the _reffed variants. This means that _get_caps doesn't return a writable + caps anymore and an explicit _make_writable() is needed before modifying the + caps. + +2010-12-07 18:12:53 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: update porting doc + +2010-12-07 16:52:47 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + pad: Clean up .h file + +2010-12-07 15:53:56 +0100 Wim Taymans + + Merge branch 'master' into 0.11 + +2010-12-07 15:33:04 +0100 Wim Taymans + + * gst/Makefile.am: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstcompat.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementdetails.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstelementmetadata.h: + * gst/gstpipeline.c: + * gst/gstregistrychunks.c: + * tests/check/gst/struct_x86_64.h: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + element: rework GstElementDetails + Clean up the GstElement structure + Replace GstElementDetails with metadata + +2010-12-07 15:31:27 +0100 Wim Taymans + + * gst/gstplugin.h: + * tests/check/gst/gstplugin.c: + plugin: remove deprecated methods + Remove more deprecated methods and fix unit test. + +2010-12-07 15:21:06 +0100 Wim Taymans + + * tests/check/libs/gdp.c: + check: remove deprecated tests + +2010-12-07 15:20:12 +0100 Wim Taymans + + * tests/check/gst/gstobject.c: + check: fix object unit test + +2010-12-07 15:19:34 +0100 Wim Taymans + + * gst/gstobject.c: + * gst/gstobject.h: + object: fix docs + +2010-12-07 13:19:10 +0100 Edward Hervey + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/net/Makefile.am: + libs: Add -I$(top_srcdir)/libs to g-ir-scanner commands + Without this, it will fail finding all headers. + +2010-12-07 12:57:40 +0200 Stefan Kost + + * gst/gstplugin.c: + plugin: recommend "--gst-disable-registry-fork" as well + Disabling forking helps with debugging the cause of the crash in gdb. + +2010-12-07 12:56:44 +0200 Stefan Kost + + * docs/random/ensonic/plugindocs.txt: + docs: some notes about our plugin docs workflow + +2010-12-07 11:58:34 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/random/porting-to-0.11.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpadtemplate.c: + object: Removed deprecated fields and methods + Make GstObject extend from GInitiallyUnowned, remove the FLOATING flag and use + GObject methods for managing the floating ref. + Remove class lock, it was a workaround for a glib < 2.8 bug. + Remove the parent-set and parent-unset signals, attempt to implement with notify + but disabled because deadlocks in deep-notify. + +2010-12-06 20:03:46 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: mention removal of protocol property + +2010-12-06 19:40:03 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/dataprotocol/dataprotocol.c: + * libs/gst/dataprotocol/dataprotocol.h: + libs: remove deprecated code + +2010-12-06 19:24:30 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + docs: update porting doc + +2010-12-06 19:18:31 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * docs/plugins/gstreamer-plugins.args: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstconfig.h.in: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstghostpad.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstxml.c: + * gst/gstxml.h: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-xmlinspect.c: + remove deprecated symbols and methods + +2010-12-06 13:51:50 +0100 Wim Taymans + + * docs/random/porting-to-0.11.txt: + porting: Add porting doc + +2010-12-06 13:48:31 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + plan: fix typo + +2010-11-11 10:38:57 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + plan: add something about GVariant registry + +2010-11-08 18:39:39 +0100 Wim Taymans + + * docs/random/use-cases-0.11.txt: + add some use-cases + +2010-11-08 14:08:36 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + more updates + +2010-11-08 12:14:12 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + more updates + +2010-11-08 11:18:05 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + more updates + +2010-11-04 19:30:58 +0100 Wim Taymans + + * docs/random/plan-0.11.txt: + work on todo list for 0.11 work + +2010-12-06 13:21:45 +0100 Wim Taymans + + * android/base.mk: + * android/controller.mk: + * android/dataprotocol.mk: + * android/elements.mk: + * android/gst-inspect.mk: + * android/gst-launch.mk: + * android/gst-plugin-scanner.mk: + * android/gst.mk: + * android/indexers.mk: + * android/net.mk: + * configure.ac: + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + * tools/gst-feedback-m.m: + * tools/gstreamer-completion: + more 0.10 -> 0.11 + +2010-12-06 12:03:29 +0100 Wim Taymans + + * configure.ac: + configure: open 0.11 branch + +2010-12-06 11:18:01 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: return wakeup event in GPollFD + +2010-12-06 11:07:38 +0100 Mark Nauwelaerts + + * gst/gstpad.c: + pad: add some debug to fast push path + ... so we don't loose track at times it is needed the most. + +2010-12-05 15:58:48 +0100 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Don't forget to unref the cached ClockId + +2010-12-05 14:46:28 +0100 Edward Hervey + + * libs/gst/check/gstcheck.c: + gstcheck: Don't check pad refcount too early + Because of the new pad caching system, the peer pad might still + have a reference on a pad. We therefore delay the refcount checking + til 'after' we unlink the pad from any potential peer. + +2010-12-05 14:11:45 +0100 Edward Hervey + + * gst/gstbin.c: + gstbin: Make element names clearer in debug statements + Replaces confusing messages like: + "Name name is not unique in bin bin, not adding" + by + "Name 'name' is not unique in bin 'bin', not adding" + +2010-12-04 21:06:34 -0800 David Schleef + + * gst/gstregistrybinary.c: + registry: Fix permissions if umask is broken + Fixes: #564056. + +2010-12-04 14:23:59 +0000 Tim-Philipp Müller + + * docs/design/Makefile.am: + build: remove trailing whitespaces after backslash in Makefile.am + +2010-12-04 13:14:39 +0000 Koop Mast + + * configure.ac: + configure: fix test so it works with FreeBSD's /bin/sh + Use '=' instead of '=='. Fixes: + configure: working c++ compiler found: yes + test: xyes: unexpected operator + http://bugzilla-attachments.gnome.org/attachment.cgi?id=175692 + +2010-12-03 11:29:30 -0800 David Schleef + + * gst/gstobject.c: + Use g_snprintf() instead of snprintf() + +2010-12-03 16:44:23 +0100 Benjamin Gaignard + + * Android.mk: + * android/NOTICE: + * android/base.mk: + * android/controller.mk: + * android/dataprotocol.mk: + * android/elements.mk: + * android/gst-inspect.mk: + * android/gst-launch.mk: + * android/gst-plugin-scanner.mk: + * android/gst.mk: + * android/gst/gstconfig.h: + * android/gst/gstenumtypes.c: + * android/gst/gstenumtypes.h: + * android/gst/gstmarshal.c: + * android/gst/gstmarshal.h: + * android/gst/gstversion.h: + * android/gst/parse/grammar.output: + * android/gst/parse/grammar.tab.c: + * android/gst/parse/grammar.tab.h: + * android/gst/parse/lex._gst_parse_yy.c: + * android/indexers.mk: + * android/net.mk: + * android/tools.mk: + Add build system for Android + +2010-12-03 16:02:09 +0100 Wim Taymans + + * gst/gstclock.c: + clock: init variables in _reinit() + Properly initialize variables in _reinit() too + +2010-10-21 18:08:51 +0200 Wim Taymans + + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstsystemclock.c: + clock: make sync clock wait lockfree + Make the common case lockfree. + +2010-12-03 12:04:23 +0000 Tim-Philipp Müller + + * gst/gstregistrybinary.c: + binaryregistry: use function introduced in GLib 2.22 unconditionally + +2010-12-03 12:42:10 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: small cleanups + +2010-11-03 18:38:11 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: make sure we remove the readfd messages + +2010-11-03 18:16:08 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpoll.c: + * gst/gstpoll.h: + * win32/common/libgstreamer.def: + poll: add method to get a GPollFD + +2010-11-03 17:56:24 +0100 Wim Taymans + + * gst/gstpoll.c: + poll: Refactor and make more lockfree + Refactor the wakeup of the poll thread. + Always make a control socket to make things easier. + Make more methods lockfree. + +2010-10-21 02:02:29 +0200 Wim Taymans + + * gst/gstpoll.c: + poll: move lock to where it makes more sense + +2010-10-21 01:15:44 +0200 Wim Taymans + + * gst/gstpoll.c: + poll: make timer polls lockfree + Make sure we don't take a mutex in the normal code path of the timer + poll. + +2010-12-02 17:51:58 +0100 Mark Nauwelaerts + + * plugins/elements/gstmultiqueue.c: + multiqueue: return upon input when already eos + ... rather than hanging incoming thread (as considered full in eos). + +2010-12-02 17:49:04 +0100 Mark Nauwelaerts + + * gst/gstcaps.c: + caps: fix doc typo + +2010-10-16 16:16:17 +0200 Mark Nauwelaerts + + * tools/gst-inspect.c: + gst-inspect: remove some commented code + +2010-12-03 13:52:03 +0200 Stefan Kost + + * gst/gstobject.c: + gstobject: add stdio.h for snprint + +2010-12-03 11:27:17 +0100 Edward Hervey + + * gst/gstpipeline.c: + pipeline: Use an object as first argument to GST_WARNING_OBJECT + +2009-04-11 15:04:41 +0200 Edward Hervey + + * gst/gstbuffer.c: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstclock.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gstutils.c: + * plugins/elements/gstqueue.c: + micro-optim: if (x) is cheaper than if (x > 0) for unsigned integers + +2009-04-10 09:01:22 +0200 Edward Hervey + + * gst/gstquery.c: + gstquery: Use structure property directly, avoid function variable. + All functions in this file can access the structure field of a query directly. + This avoids having to call gst_query_get_structure() to get it, along with being + able to remove some function variables that were used to store the result of that + function. + +2009-04-10 08:51:02 +0200 Edward Hervey + + * gst/gstinfo.c: + gstinfo: remove useless ternary operator usage. + +2010-09-14 13:08:57 +0200 Edward Hervey + + * gst/gstevent.c: + gstevent: Use structure property directly, avoid function variable. + All functions in this file can access the structure field of an event directly. + This avoids having to call gst_query_get_structure() to get it, along with being + able to remove some function variables that were used to store the result of that + function. + +2010-12-03 11:19:27 +0100 Wim Taymans + + * gst/gstpad.c: + pad: add push cache to bufferlists + Add the push cahce for the bufferlist push code path as well. + +2010-12-03 11:11:24 +0100 Wim Taymans + + * gst/gstpad.c: + pad: don't cache the peer chainfunc + There is no need to cache the peer chainfunction as we can just as efficiently + get to it from the peer object. Also not caching the chain function works better + because then we automatically get the new chainfunctions when they change. + +2010-12-03 10:52:39 +0100 Wim Taymans + + * gst/gst_private.h: + * gst/gstpad.c: + * gst/gstutils.c: + pad: clear pad cache when installing probes + Move the method to clear the pad cache into _private.h + Clear the pad cache when installing pad probes. + +2010-10-20 17:11:11 +0200 Wim Taymans + + * gst/gstpad.c: + pad: explicitly inline some functions + +2010-10-13 02:48:56 +0200 Wim Taymans + + * gst/gstpad.c: + pad: remove unused variable + +2010-10-13 02:42:23 +0200 Wim Taymans + + * gst/gstpad.c: + pad: invalidate caches on flush and pad block + +2010-10-13 02:20:43 +0200 Wim Taymans + + * gst/gstpad.c: + pad: don't unref NULL caps + +2010-10-13 02:17:28 +0200 Wim Taymans + + * gst/gstpad.c: + pad: add invalidate function + More small optimisations, remove the unneeded valid boolean. + Add function to invalide the cache. + Invalidate the cache on unlink. + +2010-10-13 01:37:52 +0200 Wim Taymans + + * gst/gstpad.c: + pad: small cleanup + +2010-10-13 01:25:27 +0200 Wim Taymans + + * gst/gstpad.c: + pad: improve pad push caching + Build the cache while we push data. When we don't have a cache, we run the + slowpath and collect cacheable properties. When all conditions are met, keep the + cached data around so that we can more efficiently push data around. + +2010-10-12 12:29:49 +0200 Wim Taymans + + * gst/gstpad.c: + pad: prototype of pad push cache + Prototype of how we can cache the peer and caps for a pad link. + +2010-12-03 12:23:27 +0200 Stefan Kost + + * tests/examples/manual/extract.pl: + docs: fix previous extract.pl commit + Make it also work in the srcdir=builddir case again. + +2010-10-20 11:58:06 +0200 Wim Taymans + + * gst/gsttask.c: + task: avoid task lock for each iteration + Make the task state an atomic variable so that we can avoid taking and releasing + the task lock for each iteration. + +2010-12-03 10:18:19 +0200 Stefan Kost + + * tests/examples/manual/extract.pl: + docs: fix example matching in extract.pl + When building with $srcdir != $builddir output would contain the builddir path. + Strip the path when scanning the xml for the example markers. + +2010-11-19 15:06:05 +0200 Stefan Kost + + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstquery.c: + docs: query doc improvements + More xrefs. Mentioned that some queries need a running pipeline. + +2010-11-19 11:43:40 +0200 Stefan Kost + + * gst/gstelementfactory.h: + elementfactory: clarify list item types in comments + +2010-11-19 10:29:34 +0200 Stefan Kost + + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + padtemplate: add two FIXME0.11: comments + +2010-11-19 10:23:54 +0200 Stefan Kost + + * gst/gstpadtemplate.c: + padtemplate: allow disablinbg the template name conformance checks + +2010-11-18 16:31:30 +0200 Stefan Kost + + * gst/gstpadtemplate.c: + padtemplate: the supplied caps may not be NULL + There is a earlier g_return_val_if_fail check. Also + gst_static_pad_template_get does not have such a check. + +2010-11-03 16:37:10 +0100 Andoni Morales Alastruey + + * plugins/elements/gstfakesink.c: + fakesink: Print sink-message events like a message and the GstMessage structure + +2010-11-01 15:32:43 +0200 Stefan Kost + + * docs/design/Makefile.am: + * docs/design/draft-buffer2.txt: + * docs/design/draft-klass.txt: + * docs/design/draft-metadata.txt: + * docs/design/draft-tagreading.txt: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-TODO.txt: + * docs/design/part-activation.txt: + * docs/design/part-block.txt: + * docs/design/part-buffering.txt: + * docs/design/part-bufferlist.txt: + * docs/design/part-clocks.txt: + * docs/design/part-conventions.txt: + * docs/design/part-dynamic.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-element-source.txt: + * docs/design/part-element-transform.txt: + * docs/design/part-events.txt: + * docs/design/part-framestep.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstghostpad.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-latency.txt: + * docs/design/part-live-source.txt: + * docs/design/part-messages.txt: + * docs/design/part-missing-plugins.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-overview.txt: + * docs/design/part-preroll.txt: + * docs/design/part-push-pull.txt: + * docs/design/part-qos.txt: + * docs/design/part-query.txt: + * docs/design/part-relations.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + * docs/design/part-sparsestreams.txt: + * docs/design/part-standards.txt: + * docs/design/part-states.txt: + * docs/design/part-stream-status.txt: + * docs/design/part-streams.txt: + * docs/design/part-synchronisation.txt: + * docs/design/part-trickmodes.txt: + design-docs: add html output using asciidoc + Unify the ad-hoc markup to be asciidoc style in many places. Add a "html" target + to Makefile to generate the output. + +2010-10-19 14:27:20 +0300 Stefan Kost + + * gst/gstobject.c: + gstobject: more default name generation more efficient + Save ~2000 malloc/memcpy/free pairs at startup by running to_lower in-place. + Also skip the numbers as we can. + +2010-10-18 14:45:16 +0300 Stefan Kost + + * gst/gstpluginfeature.c: + pluginfeature: use the parent_class from G_DEFINE_TYPE macro and drop extra copy + +2010-10-20 14:27:16 +0300 Stefan Kost + + * gst/gstelementfactory.c: + elementfactory: use g_intern_string for interface names + +2010-10-18 13:29:53 +0300 Stefan Kost + + * gst/gstelementfactory.c: + * gst/gstregistrychunks.c: + registry: also intern the static caps + +2010-12-03 00:00:09 +0200 Stefan Kost + + * gst/gstelementfactory.c: + elementfactory: meta-data can be NULL + +2010-12-02 16:28:43 -0300 Thiago Santos + + * gst/gstdatetime.c: + * tests/check/gst/gstdatetime.c: + gstdatetime: Fix handling of timezones + Fix returning of timezones on systems with gdatetime + to use floats on the math expression to avoid + truncating the fractional part. + Also adds a test for covering this case. + +2010-12-02 19:44:41 +0100 Edward Hervey + + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + gstdataqueue: Don't break ABI + The order of the field was wrong, and the size of the structure didn't + end up being the same. + +2010-11-25 18:48:09 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * tests/check/elements/fakesink.c: + * tests/check/generic/sinks.c: + basesink: rework position reporting code + Unify the different position reporting code paths to make it more + understandable. + Use start_time to get more accurate position reporting in paused. + Fix unit tests for more accurate reporting. + +2010-11-25 16:06:07 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: perform wait_preroll in a while loop + We need to continue calling wait_preroll() as long as the need_preroll variable + is true. + +2010-11-17 16:46:30 +0100 Wim Taymans + + * gst/gstutils.c: + utils: return immediately for -1 conversion + When we are asked to convert -1, we can return immediately with a -1 return + value. + +2010-11-17 16:42:00 +0100 Wim Taymans + + * gst/gstutils.c: + utils: a convert query can have a -1 input value + It is allowed to pass -1 to the src_val for a convert. + +2010-11-16 12:20:37 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * tests/check/generic/sinks.c: + basesink: also preroll after a flush with async=false + Make sure to preroll after a flush even when we are async=false. + Add unit test. + Fixes #634965 + +2010-11-15 18:20:27 +0100 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: improve docs a little. + +2010-11-15 18:17:36 +0100 Wim Taymans + + * tests/check/generic/sinks.c: + check: lock src state to avoid error cases + Lock the state of the src element or else the pipeline might go into the error + state when we set it to PAUSED later. + +2010-11-15 12:49:05 +0100 Wim Taymans + + * gst/gstpipeline.c: + pipeline: avoid using invalid clock times + Be extra careful to not use invalid clock times but give a warning instead. This + should make things work better with faulty clock implementations. + +2010-11-11 10:41:18 +0100 Wim Taymans + + * gst/gstcaps.c: + caps: improve some comments about the zigzag intersection + +2010-12-02 13:04:30 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + docs: Add unused symbols to proper sections + +2010-12-02 13:03:57 +0100 Edward Hervey + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + docs: Add GstDateTime section and update it for latest symbols + +2010-10-19 18:09:53 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Only call update_buffering if needed. + update_buffering is so big it will never be inlined (and shouldn't), + we therefore move the check outside of it. + +2010-10-19 17:45:16 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Avoid re-checking many times whether an item is a buffer + Avoids calling 6 times gst_buffer_get_type() for every item coming + through queue2 + +2010-10-19 17:43:56 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Reduce amount of time locks are taken + +2010-10-19 17:42:39 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Fixup documentation of some properties + +2010-10-19 17:40:13 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Avoid useless segment_to_running_time() calculations. + * Cache src and sink time + * Use a boolean to known whether src/sink time needs to be recalculated + Avoids 50% of calls to gst_segment_to_running_time() + +2010-10-20 17:41:28 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Re-using GstClockID instead of constantly recreating one + Makes _sink_wait_clock at least 2 times faster. + https://bugzilla.gnome.org/show_bug.cgi?id=632778 + +2010-10-20 17:40:43 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + * win32/common/libgstreamer.def: + gstclock: New API to re-use a single shot GstClockID + API: gst_clock_single_shot_id_reinit + https://bugzilla.gnome.org/show_bug.cgi?id=632778 + +2010-10-20 13:52:02 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Pass along miniobject type through various functions + Avoids doing useless GST_IS_* + https://bugzilla.gnome.org/show_bug.cgi?id=632778 + +2010-10-20 13:08:08 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Switch enable_last_buffer to an atomic int + Avoids having to take a lock to read/write it. + https://bugzilla.gnome.org/show_bug.cgi?id=632778 + +2010-10-19 15:53:26 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Remove useless checks from e406f7 + srcresult was being rechecked in places it couldn't have changed. + queue level was being rechecked in places it couldn't have changed. + https://bugzilla.gnome.org/show_bug.cgi?id=632780 + +2010-10-13 13:50:22 +0200 Edward Hervey + + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + gstdataqueue: Only emit g_cond_signal when needed + Keep track of which cond we're waiting for and only emit when needed. + https://bugzilla.gnome.org/show_bug.cgi?id=632779 + +2010-10-20 17:12:29 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: move g_return_if_fail to where it is needed + +2010-11-03 11:14:03 +0100 Sebastian Dröge + + * gst/gstversion.h.in: + version: Take nano version into account in GST_CHECK_VERSION() + If the nano is > 0 the current version should be handled the same as + micro + 1. + +2010-11-01 16:34:46 +0100 Sebastian Dröge + + * gst/gstpad.c: + pad: Set the event source object if none is set yet in gst_pad_push_event() + Otherwise the source will stay at NULL, the event is passed to the + peerpad via gst_pad_send_event() and then the peerpad is set as + source of the event instead of the originating pad. + +2010-10-31 18:48:19 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Remove dead assignment and unused variable + +2010-10-31 18:46:43 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Remove dead assignment and move variable declaration into inner block + +2010-10-31 18:23:00 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Remove redundant variable + Other than saving an immense amount of 4 bytes of memory this + prevents clang from complaining and keeps the ring buffer state + in a single variable instead of two. + +2010-10-20 10:18:18 +0200 David Hoyt + + * gst/gsttask.c: + gsttask: Set thread names on Windows with MSVC if a debugger is attached + Fixes bug #632168. + +2010-10-19 15:52:30 +0200 Sebastian Dröge + + * gst/gstmacros.h: + macros: Define restrict keyword if not available + This change always defines the restrict keyword if a + non-C99 C compiler is used. In the case of GCC >= 4 + it will be defined to __restrict__, in all other + cases to nothing. This allows to use the restrict + keyword unconditionally. + +2010-12-01 23:57:36 +0000 Tim-Philipp Müller + + * configure.ac: + Bump GLib requirement to >= 2.22 + See http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement + +2010-12-01 23:56:45 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development + +=== release 0.10.31 === + +2010-11-30 17:40:47 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.31 + +2010-11-27 19:13:35 +0000 Tim-Philipp Müller + + * gst/gstutils.h: + utils: avoid 'unused argument' warnings caused by GST_BOILERPLATE_FULL + The unused data parameter in the class_init trampoline function + seems to cause warnings with some c++ compilers. + https://bugzilla.gnome.org/show_bug.cgi?id=635869 + +2010-11-09 23:27:17 -0300 reynaldo + + * docs/pwg/building-boiler.xml: + docs: some small fixes to the plugin writer's guide + Fix wrongly placed example and weirdly phrased 'note' lacking proper + formatting. Fix missing hint for autogen.sh location and rephrase + 'built and installed' sentence. Fix wrongly phrased and redundant + paragraph in PWG + https://bugzilla.gnome.org/show_bug.cgi?id=634921 + +2010-11-27 11:02:48 -0300 Thiago Santos + + * docs/manual/basics-elements.xml: + manual: Improve states documentation + Be more explicit about being on NULL before unrefs + +2010-11-20 14:54:23 -0800 Evan Nemerson + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Include exported packages information in GIRs + https://bugzilla.gnome.org/show_bug.cgi?id=635389 + +2010-11-18 00:29:41 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.30.5 pre-release + +2010-11-18 00:29:19 +0000 Tim-Philipp Müller + + * gst/gstelementfactory.c: + elementfactory: fix caps leak in element factory list utility functions + +2010-11-17 23:55:45 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/ca.po: + * po/da.po: + * po/es.po: + * po/fi.po: + * po/hu.po: + * po/sk.po: + po: update translations + +2010-11-17 09:39:34 -0300 Thiago Santos + + * configure.ac: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * tests/check/gst/gstdatetime.c: + * win32/common/libgstreamer.def: + datetime: Add _from_unix_epoch variants + Adds 2 variants for the gst_date_time_from_unix_epoch function, + one for UTC and another for local time. + API: gst_date_time_new_from_unix_epoch_utc + API: gst_date_time_new_from_unix_epoch_local_time + Fixes #653031 + https://bugzilla.gnome.org/show_bug.cgi?id=635031 + +2010-11-03 14:21:02 +0000 Vladimir Eremeev + + * gst/math-compat.h: + math-compat: don't re-define _USE_MATH_DEFINES if already defined + This avoids compiler warnings. + https://bugzilla.gnome.org/show_bug.cgi?id=633886 + +2010-11-01 16:06:43 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.30.4 pre-release + +2010-11-01 15:36:54 +0000 Tim-Philipp Müller + + * po/de.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + po: update translations + +2010-10-31 20:17:05 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + queue2: don't leak pad ref in pull mode when flushing + Fix pad leak when queue2 is flushing or being shut down. + +2010-10-31 19:47:25 +0000 Tim-Philipp Müller + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: don't send seeks beyond the end of the file upstream in pull mode + If downstream is operating in pull mode, short-circuit any pulls beyond + the end of the file and return FLOW_UNEXPECTED immediately instead of + sending a seek beyond the end of the file upstream, since this might + confuse upstream elements (and/or http servers, for example). Fixes + playback of apple trailers in totem and youtube/html5 clips in + WebkitGTK+. + https://bugzilla.gnome.org/show_bug.cgi?id=632977 + +2010-10-28 23:28:15 +1000 Jonathan Matthew + + * libs/gst/base/gstbasetransform.c: + basetransform: use input position for queries if we have no output position + +2010-10-28 13:29:31 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix reverse negotiation + When the downstream element suggests a new format, pass the suggestion + upstream if we can't convert to it. + Fixes #633147 + +2010-10-27 18:12:36 +0200 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fix tracking of unlinked streams. + 33082eb9e42c52e4df848195946f1b7bbce768c5 introduced a bug + preventing sparse unlinked streams from advancing properly, + leading to the queue blocking. + Fixes: #633176 + +2010-10-27 18:11:35 +0200 Jan Schmidt + + * tests/check/elements/multiqueue.c: + tests: Add a multiqueue sparse streams test + +2010-10-27 13:16:11 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From 7bbd708 to 011bcc8 + +2010-10-22 17:35:23 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.30.3 pre-release + +2010-10-18 17:42:27 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bytereader: const-ify byte reader argument in peek/scan API + Because we can. + +2010-10-22 11:52:47 +0200 Edward Hervey + + * gst/gstelementfactory.h: + elementfactory: Fix 64bit constant + Basically we're not meant to put anything more complex than simple numbers, + due to the definition of G_GUINT64_CONSTANT: + G_GUINT64_CONSTANT(val) (val##UL) + Which previously resulted in .... 1 << 49UL + +2010-10-18 10:46:59 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: recompute correct running time for buffer ending flushing step + Prevents delaying/hanging when resuming PLAYING. + Fixes #632433. + +2010-10-16 19:19:47 +0100 Tim-Philipp Müller + + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbitreader-docs.h: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytewriter-docs.h: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimeprovider.h: + docs: fix misc. gtk-doc warnings in libs + (for gtk-doc 1.15) + +2010-10-16 18:26:20 +0100 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.c: + Revert "libs/gst/dataqueue: Document gst_data_queue_new_full" + This reverts commit 80727c117703507f790a86b0962ab3d915e5a491. + This doesn't make sense. gst_data_queue_new_full() is already + documented above. And we need the doc blurb for _new() here. + +2010-10-16 17:00:17 +0100 Tim-Philipp Müller + + * docs/random/release: + docs: flesh out release instructions a bit more + +2010-10-16 16:53:49 +0100 Tim-Philipp Müller + + * gst/gstparse.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * libs/gst/base/gstadapter.c: + docs: add some gtk-doc Since: markers + Add some gtk-doc Since: markers, fix one Since: marker, + fix typo. + +2010-10-16 00:25:52 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + 0.10.30.2 pre-release + +2010-10-16 00:14:13 +0100 Tim-Philipp Müller + + * po/LINGUAS: + * po/es.po: + * po/fr.po: + * po/lt.po: + * po/nl.po: + * po/ro.po: + * po/ru.po: + * po/sl.po: + * po/sv.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2010-10-15 19:45:14 +0200 Mark Nauwelaerts + + * tools/gst-inspect.c: + gst-inspect: useful factory names for uri-handlers output + Fixes #632236. + +2010-10-14 12:31:32 -0700 David Schleef + + * common: + Automatic update of common submodule + From 5a668bf to 7bbd708 + +2010-10-12 15:13:48 -0300 Thiago Santos + + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * gst/gstvalue.c: + * tests/check/gst/gstdatetime.c: + * tests/check/gst/gstvalue.c: + datetime: Use seconds as double + Use seconds as double to make API similar to glib's + gdatetime. Also move timezone parameter to the + first position, just like glib's. + https://bugzilla.gnome.org/show_bug.cgi?id=628408 + +2010-10-11 16:15:29 -0300 Thiago Santos + + * gst/gstdatetime.c: + gstdatetime: Move doc outside the ifdefs + Move the datetime documentation of the functions outside the + ifdefs + https://bugzilla.gnome.org/show_bug.cgi?id=628408 + +2010-09-27 19:35:08 -0300 Thiago Santos + + * gst/glib-compat-private.h: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + datetime: Use GDateTime if available + Use GDateTime internally on GstDateTime if glib already + provides it. + https://bugzilla.gnome.org/show_bug.cgi?id=628408 + +2010-09-28 17:46:29 -0300 Thiago Santos + + * gst/glib-compat-private.h: + glib-private: Add include protection macro + +2010-10-13 12:51:00 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: add guard to buffer_set_caps() that checks if caps are simple + +2010-10-13 15:56:26 +0300 Stefan Kost + + * gst/gstsystemclock.c: + systemclock: add a missing G_PARAM_STATIC_STRINGS + +2009-10-01 11:14:06 +0200 Edward Hervey + + * libs/gst/base/gstdataqueue.c: + libs/gst/dataqueue: Document gst_data_queue_new_full + +2009-09-28 13:35:35 +0200 Edward Hervey + + * libs/gst/base/gstdataqueue.c: + base/gstdataqueue: inline some functions, get levels with memcpy. + +2010-10-13 11:54:04 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Remove unused argument from find_range() + +2010-10-13 11:52:25 +0200 Edward Hervey + + * plugins/elements/gstfdsink.c: + fdsink: cleanup get_property/set_property + +2010-10-12 18:48:10 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: avoid g_cond_signal when we can + Keep track of what cond we are waiting on and only signal when some other thread + is waiting. + +2010-10-11 19:27:54 +0100 Tim-Philipp Müller + + * gst/gstminiobject.c: + miniobject: avoid duplicate type check when freeing miniobject + gst_mini_object_unref() has guards that check the type already, so + we don't really need to re-check it here again while getting the + class (there's not really much point to that anyway, since we don't + check the return value of the get_class, so we'd crash anyway if + we're not dealing with a mini object, the only question would + be if there'd be a warning before the crash or not). + +2010-10-11 18:55:14 +0200 Edward Hervey + + * gst/gstminiobject.c: + miniobject: Directly increate mini_object in mini_object_free() + Speeds up mini_object_unref by 25% by avoiding the typecheck which + is avoidable here since it is only called on existing miniobjects. + +2010-10-11 18:30:54 +0200 Edward Hervey + + * gst/gstminiobject.c: + miniobject: Remove confusing DEBUG_REFCOUNT define + the debugging statements will be silenced automatically if debugging + is disabled, and the type check is actually required. + +2010-10-11 18:10:07 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: release queue2 lock before notify + Make sure that we don't hold the lock when we notify the temp-location + property, + Fixes #631853 + +2010-10-11 16:45:16 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + queue: add debug statement + +2010-10-11 10:27:52 +0200 Ognyan Tonchev + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * tests/check/elements/queue.c: + queue: apply sink segment on the source if queue is empty + Apply the sink segment on the source immediatly when it is received + and there is nothing in the queue. + Solves #482147 + +2010-10-11 15:51:21 +0200 Wim Taymans + + * gst/gstbin.c: + bin: fix documentation for iterate_sources + +2010-10-11 16:41:26 +0300 Stefan Kost + + * libs/gst/base/gstadapter.c: + docs: use the gtk-doc shortcuts to get coloured and xrefed example + +2010-10-11 14:20:15 +0200 Sebastian Dröge + + * gst/gstbin.c: + bin: Initialize variable + +2010-10-11 10:56:56 +0200 Wim Taymans + + * gst/gstbin.c: + bin: Improve tracking of source elements + Track elements tagged with the IS_SOURCE flag in a similar way we track the sink + elements. This allows us to efficiently dispatch downstream events to the right + elements. + +2010-10-11 10:55:04 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: tag as a SOURCE element + Tag all elements deriving from the basesrc with the IS_SOURCE flag. + +2010-10-11 10:53:41 +0200 Wim Taymans + + * gst/gstelement.h: + element: add IS_SOURCE flag + Add the GST_ELEMENT_IS_SOURCE flag so that we can tag source elements like we + can with sink elements. + +2010-10-09 14:18:44 +0100 Vincent Penquerc'h + + * gst/gstregistrybinary.c: + registry: g_mapped_file_unref exists already since GLib 2.21.3 + +2010-10-10 18:14:40 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Report the output position on POSITION queries on the srcpad + There can be a difference between input and output last_stop. + Fixes bug #629410. + +2010-10-08 12:43:20 -0700 David Schleef + + * common: + Automatic update of common submodule + From c4a8adc to 5a668bf + +2010-10-08 12:54:52 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Remove unused variable and simplify code + oldid was only used when we were doing multiple pops per loop. + +2010-10-08 12:50:10 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 5e3c9bf to c4a8adc + +2010-10-08 12:48:42 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter-docs.h: + bytewriter: Add missing file + +2010-10-08 12:18:23 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbytewriter.h: + bytewriter: Add unchecked variants of the writing functions + These don't check if there's enough free space available and are + available as inline functions only. + API: gst_byte_writer_put_int8_unchecked + API: gst_byte_writer_put_int16_be_unchecked + API: gst_byte_writer_put_int16_le_unchecked + API: gst_byte_writer_put_int24_be_unchecked + API: gst_byte_writer_put_int24_le_unchecked + API: gst_byte_writer_put_int32_be_unchecked + API: gst_byte_writer_put_int32_le_unchecked + API: gst_byte_writer_put_int64_be_unchecked + API: gst_byte_writer_put_int64_le_unchecked + API: gst_byte_writer_put_uint8_unchecked + API: gst_byte_writer_put_uint16_be_unchecked + API: gst_byte_writer_put_uint16_le_unchecked + API: gst_byte_writer_put_uint24_be_unchecked + API: gst_byte_writer_put_uint24_le_unchecked + API: gst_byte_writer_put_uint32_be_unchecked + API: gst_byte_writer_put_uint32_le_unchecked + API: gst_byte_writer_put_uint64_be_unchecked + API: gst_byte_writer_put_uint64_le_unchecked + API: gst_byte_writer_put_float32_be_unchecked + API: gst_byte_writer_put_float32_le_unchecked + API: gst_byte_writer_put_float64_be_unchecked + API: gst_byte_writer_put_float64_le_unchecked + API: gst_byte_writer_put_data_unchecked + API: gst_byte_writer_fill_unchecked + +2010-10-08 09:34:47 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/dataprotocol/dataprotocol.c: + controller, dataprotocol: make public enum _get_type() functions thread-safe + Not that it is likely to matter in practice, but since these are public + API they should probably be thread-safe. + +2010-10-08 00:38:39 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/dataprotocol/dataprotocol.c: + dataprotocol, lfocontrolsource: 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=629946 + +2010-10-08 09:47:12 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter.h: + bytewriter: Fix possible infinite loop caused by an overflow + +2010-10-07 18:46:26 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gsttee.c: + elements: minor performance improvement when doing g_object_notify() for the "last-message" property + Make sure property names passed to g_object_notify() are in the canonical form + (ie. "last-message" not "last_message"), so that g_param_spec_pool_lookup() + doesn't have to do strdup/canonicalize/free for every single notify call. + This only applies when building against older GLib versions (< 2.26). + +2010-10-07 18:27:06 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + fakesink: use g_object_notify_by_pspec() and remove work-around for old GLib versions if possible + Use more efficient g_object_notify_by_pspec() if we're compiling against + GLib >= 2.26, and also remove work-around for g_object_notify() thread- + safety issues with older GLib versions if it's not needed any more. + +2010-10-07 18:21:13 +0100 Tim-Philipp Müller + + * plugins/elements/gsttee.c: + tee: use g_object_notify_by_pspec() if possible + Use more efficient g_object_notify_by_pspec() if we're compiling against + GLib >= 2.26. + +2010-10-07 18:19:31 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesrc.c: + fakesrc: use g_object_notify_by_pspec() if possible + Use more efficient g_object_notify_by_pspec() if we're compiling against + GLib >= 2.26. + +2010-10-07 17:53:18 +0100 Tim-Philipp Müller + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: use g_object_notify_by_pspec() and remove work-around for old GLib versions if possible + Use more efficient g_object_notify_by_pspec() if we're compiling against + GLib >= 2.26, and also remove work-around for g_object_notify() thread- + safety issues with older GLib versions if it's not needed any more. + +2010-10-07 17:23:10 +0100 Tim-Philipp Müller + + * gst/gstghostpad.c: + * gst/gstpad.c: + pads: use new g_object_notify_by_pspec() for caps notifies if available + If we're building against GLib >= 2.26.0, we can use the more efficient + g_object_notify_by_caps(), which avoids the param spec lookup. + +2010-10-07 16:27:20 +0100 Tim-Philipp Müller + + * gst/gstclock.c: + clock: remove unnecessary g_object_notify() call + GObject will do that for us when g_object_set*() is called. + +2010-10-07 19:18:03 +0200 Wim Taymans + + * docs/design/part-qos.txt: + docs: update qos design doc + Fix some typos. + change the definition of the quality field for video decoders to something that + makes more sense. + +2010-10-05 17:02:58 +0100 Tim-Philipp Müller + + * Makefile.am: + Add gobject-introspection temp directories to CRUFT_DIRS + +2010-10-05 15:05:43 +0100 Tim-Philipp Müller + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: use math-compat.h for M_PI + +2010-10-05 14:45:02 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.h: + gstinfo: remove random MSVC compatibility define for M_PI that doesn't belong here + Code that needs this should include gst/math-compat.h or use G_PI. + +2010-10-05 14:16:19 +0100 Tim-Philipp Müller + + * docs/gst/Makefile.am: + * gst/Makefile.am: + * gst/math-compat.h: + gst: add math-compat.h header + Add minimal math-compath.h header where we can define fallback + versions for miscellaneous math functions that aren't always + available, so we don't have to duplicate this in plugins. + The header is not included by default, so needs to be + included explicitly for now. + https://bugzilla.gnome.org/show_bug.cgi?id=630802 + +2010-10-05 11:47:59 +0200 Thijs Vermeir + + * tools/gst-plot-timeline.py: + tools: fix parsing of timestamp in gst-plot-timeline + +2010-09-25 14:24:46 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: don't take preroll-lock in get_property + Use atomic ops to read and write more properties. Taking the preroll lock in get_property + can lock up applications reading the property during preroll. + +2010-10-02 18:11:32 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.h: + basesink: add a fixme for 0.11 + +2010-10-04 15:49:18 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: format negative values better + Format negative values properly in the debug log. + +2010-10-03 23:41:26 +0200 Sebastian Dröge + + * tests/check/libs/bitreader.c: + bitreader: Fix uninitialized variable compiler warnings + gcc doesn't notice that the check assertion macros will abort + further execution of the tests. + +2010-10-03 23:32:06 +0200 Sebastian Dröge + + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + bytewriter: Add inline variants of all important functions + +2010-10-03 15:27:37 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbitreader-docs.h: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * tests/check/libs/bitreader.c: + bitreader: Add inlined and unchecked versions of the important functions + API: gst_bit_reader_skip_unchecked + API: gst_bit_reader_skip_to_byte_unchecked + API: gst_bit_reader_get_bits_uint16_unchecked + API: gst_bit_reader_get_bits_uint32_unchecked + API: gst_bit_reader_get_bits_uint64_unchecked + API: gst_bit_reader_get_bits_uint8_unchecked + API: gst_bit_reader_peek_bits_uint16_unchecked + API: gst_bit_reader_peek_bits_uint32_unchecked + API: gst_bit_reader_peek_bits_uint64_unchecked + API: gst_bit_reader_peek_bits_uint8_unchecked + This alone makes flacparse about 3 times faster. + +2010-10-03 14:59:47 +0200 Sebastian Dröge + + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bytewriter: Add guards to the inlined get_pos/get_remaining/get_size/etc functions + +2010-10-03 14:24:00 +0200 Sebastian Dröge + + * libs/gst/base/gstbitreader.c: + bitreader: Optimize peek_bits/get_bits a bit + Use local variables instead of dereferencing the bitreader + pointer all the time and don't copy the reader for peek_bits. + +2010-09-27 19:29:24 -0300 Thiago Santos + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + gstdatetime: Fix string serialization + Correctly serialize tzoffset as a gstvalue + +2010-09-24 12:22:33 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: improve adjust_time() + Add some more comments. + Make sure we don't end up with negative timestamps. + +2010-05-26 20:29:22 +0200 Havard Graff + + * libs/gst/base/gstbasesink.c: + basesink: renderdelay needs to be subtracted in adjust_time() + latency is already sink-latency + render-delay, and here we only + want to deal with the sink-latency. + Fixes #630436 + +2010-09-24 00:13:51 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstmarshal.c: + win32: define GST_PACKAGE_RELEASE_DATETIME in win32 config.h as well + +2010-09-23 20:57:49 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new strings + +2010-09-23 20:48:25 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: print GST_PARAM_MUTABLE_* property flags + +2010-05-04 09:36:43 +0200 Havard Graff + + * libs/gst/base/gstbasetransform.c: + basetransform: Make a WARNING into a DEBUG statement + Fixes bug #630437. + +2010-01-12 17:10:59 +0100 Trond Andersen + + * gst/gstsystemclock.c: + clock: fix racy shutdown clock id leak + Clock IDs were leaked if the clock got disposed before the worker thread + got a chance to reap unscheduled entries. + Fixes bug #630439. + +2010-09-23 18:18:54 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: avoid useless memcpy + Because of the awkward refcounting in prepare_output_buffer, we might end up + with writable buffers that point to the same data. Check for those cases so that + we avoid a useless memcpy and keep valgrind quiet. + Fixes #628176 + +2010-09-23 14:37:45 +0100 Tim-Philipp Müller + + * configure.ac: + * tests/check/Makefile.am: + tests: fix 'make check' build for setups where no c++ compiler is available + Only try to build (pseudo-)C++ unit test if a working C++ compiler has been + found, otherwise the build will fail. (We do this to make sure our headers + are 'C++ clean'). + +2010-09-23 10:08:05 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tag: Adds GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR + Adds a new tag to indicate the error in horizontal positioning + in meters. This is one of the available 'gps error' fields in + exif, for example. + API: GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR + +2010-09-23 15:34:54 +0300 Stefan Kost + + * gst/gstpad.c: + Revert "pad: use a nested lock to avoid reffing the peer" + This reverts commit 9b424b1570366b10746a762e8c9c4c1b35b21e91. + +2010-09-23 15:12:32 +0300 Stefan Kost + + * plugins/elements/gstqueue2.c: + queue2: remove var only used for debug statement + +2010-09-07 16:56:38 +0300 Stefan Kost + + * gst/gstpad.c: + pad: use a nested lock to avoid reffing the peer + Fixes #503592 + +2010-07-15 15:47:36 +0300 Stefan Kost + + * configure.ac: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstcpp.cc: + tests: rebuild one test using cpp + This aims to catch cpp issues in core. Add c++ boilerplate to configure. + +2010-09-21 18:33:26 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From aa0d1d0 to 5e3c9bf + +2010-09-19 16:10:16 +0200 Edward Hervey + + * tests/check/libs/adapter.c: + tests: Handle new assertion in gst_adapter_masked_scan_uint32 + +2010-09-18 19:29:09 -0700 David Schleef + + * libs/gst/base/gstadapter.c: + adapter: Add check for pattern bits not in mask + +2010-09-17 19:53:33 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Use g_file_test() instead of access() which does not exist on MSVC6 + Fixes bug #629494. + +2010-09-17 17:34:42 +0200 Wim Taymans + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: add function to add a list of buffers + Add a function to add a list of buffers to the bufferlist. + +2010-09-17 15:51:08 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: + * win32/common/libgstbase.def: + adapter: add function to get a list of buffers + Add a function to retrieve a list of buffers containing the first N bytes from + the adapter. This can be done without a memcpy and should make it possible to + transfer the list to a GstBufferList later. + +2010-09-17 15:07:50 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: reuse more data in _peek() + Optimize _peek() some more by reusing already assembled data when we can. + +2010-09-17 13:57:39 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: optimize _take() a little more + When we have already assembled some data before, reuse this data and only copy + the part that is new. + +2010-09-17 12:48:55 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: refactor adapter take + Move some common code into one place + +2010-09-17 12:40:12 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + adapter: add support for 0 sized buffers + Add support for 0 sized buffers. This is interesting in combination with the + timestamp functions. + Fixes #629553 + +2010-09-17 10:01:01 +0200 Edward Hervey + + * docs/pwg/advanced-scheduling.xml: + pwg: Make a sentence clearer. + +2010-09-16 19:27:57 +0100 Tim-Philipp Müller + + * gst/gstelementfactory.c: + elementfactory: make sure gstreamer has been initialized when creating elements + Add gst_is_initialized() guard to gst_element_factory_make(), so + people who forgot to call gst_init() get a useful warning for what + seems to be a common enough mistake. + +2010-09-16 00:37:59 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + query: minor gst_query_add_buffering_range() code reflow + Sprinkle some G_UNLIKELY(), return TRUE/FALSE constants, avoid an + unnecessary g_value_unset(), move g_value_init()+set_int64_range() + closer to where they're needed. + +2010-09-16 00:30:14 +0100 Tim-Philipp Müller + + * gst/gstquery.c: + query: gst_query_add_buffering_range() optimisations + Don't create a new GValueArray copy for every single _add_buffering_range() + call, but append to the existing value array owned by the structure instead. + +2010-09-16 00:03:38 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + structure: micro-optimisation for some setter functions + Split out functions that do the actual work, so we avoid doing + the same g_return_if_fail() checks multiple times for each call. + +2010-09-15 23:42:43 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: add gst_structure_{id_}take_value() + Add _set_value() variants that take ownership of the value passed + instead of making a copy of the value. This is useful for setting + values to things that aren't refcounted (e.g. GValueArrays or + strings or string arrays, etc.). + API: gst_structure_take_value() + API: gst_structure_id_take_value() + https://bugzilla.gnome.org/show_bug.cgi?id=629831 + +2010-09-16 19:19:21 +0200 Wim Taymans + + * gst/gstbin.c: + bin: fix doc string, we post element messages + +2010-09-16 19:06:35 +0200 Wim Taymans + + * gst/gstbin.c: + bin: add message-forward option + Add an option to forward all the internal messages that would otherwise be + filtered such as EOS, SEGMENT and ASYNC messages. + This allows the application to, for example, detect that a partial pipeline is + prerolled or reached eos. + The original messages are wrapped inside an element message because the parent + bins are not supposed to see those internal messages escape. + +2010-09-12 16:50:11 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + plugin: use strstr() instead of g_strstr_len() + Saves us a strlen() call. + +2010-09-15 13:29:52 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: only post buffering message when percent changed + +2010-09-15 13:15:19 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: always update buffering status + Update the buffering status even when we are not using a queue so that EOS can + properly finish the buffering. + +2010-09-13 20:39:50 -0300 Thiago Santos + + * gst/gstpad.c: + gstpad: Fix flush-stop event handling + A flush-stop event would make a pad unflushing, causing it + to start acting as an activated pad. This, for example, + could lead to the chain function being called when stuff + isn't initialized. + This could happend when setting qtdemux to NULL while a seek + was being handled in the upstream filesrc (in push mode). + This patch makes it check if it is activated before setting + it to unflushing. + +2010-09-13 11:17:34 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstdatetime.c: + * gst/gstelement.c: + * gst/gstelementfactory.h: + * gst/gstpad.c: + * gst/gsttaglist.h: + docs: fix warnings pointed out by gtk-doc + +2010-09-13 09:50:53 +0300 Stefan Kost + + * gst/gsttaskpool.c: + taskpool: make debug only code conditional + +2010-09-10 15:07:03 -0400 Colin Walters + + * gst/gsterror.h: + introspection: Build with latest g-i + Hide a compatibility typedef. + https://bugzilla.gnome.org/show_bug.cgi?id=629241 + https://bugzilla.gnome.org/show_bug.cgi?id=550616 + +2010-09-09 22:24:38 +0300 Stefan Kost + + * gst/gstpluginloader.c: + pluginloader: don't leak entries for blacklisted files + +2010-09-09 21:59:29 +0300 Stefan Kost + + * tests/check/generic/states.c: + checks: and check the right env-var (fixup last commit) + +2010-09-09 21:56:28 +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-06 15:16:16 +0200 Edward Hervey + + * gst/gstobject.c: + gstobject: avoid string creation when not needed + +2010-09-09 16:11:41 +0200 Sebastian Dröge + + * plugins/elements/gstidentity.c: + identity: identity is GAP flag aware, no need to let it be unset by basetransform + +2010-09-09 15:57:15 +0300 Stefan Kost + + * tools/gst-launch.c: + gst-launch: add a sync bus handler and move state-change logging there + The sync handler is called for all mesages, the event loop we previously used + was not. In the sync handler trigger pipeline dot dumps and call access for a + file in tmp-dir to add markers interceptable by strace and co. + +2010-09-08 18:41:18 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + caps: simplify code a bit + No need to call g_slist_length() here. + +2010-09-08 09:37:42 +0300 Stefan Kost + + * gst/gstpad.c: + pad: add a unchecked variant for pull + Add internal _get_range_unchecked thats is called from _get_range and + _pull_range. + +2010-09-07 23:48:56 +0100 Tim-Philipp Müller + + * scripts/gst-uninstalled: + gst-uninstalled: add ugly/bad/ffmpeg pkg-config dirs to PKG_CONFIG_PATH + So we can figure out plugin directories of other modules properly in + the uninstalled setup case, for unit tests that need elements from + other modules. + +2010-09-07 12:01:18 +0100 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + docs: update plugin docs for recent changes + And sorted hierarchy + +2010-09-07 11:41:37 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c2e10bf to aa0d1d0 + +2010-09-07 11:09:16 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: don't use gst_structure_foreach() on NULL pointers + +2010-09-06 20:19:27 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations for new strings + +2010-09-06 20:16:14 +0100 Tim-Philipp Müller + + * gst/gsterror.c: + gsterror: add default error message for GST_LIBRARY_ERROR_ENCODE + No idea though why we even have GST_LIBRARY_ERROR_ENCODE or when one + would want to use that instead of GST_STREAM_ERROR_ENCODE. + +2010-09-06 20:06:56 +0100 Tim-Philipp Müller + + * gst/gsterror.c: + gsterror: avoid pointless string copying + There's no need to create these tables with duplicates of the + untranslated error message string constants, we can just use + old-fashioned switch/case and call gettext directly. This also + makes things slightly more thread safe and more robust to bad + input (invalid error codes). + +2010-09-06 18:33:51 +0200 Edward Hervey + + * tests/check/gst/gstvalue.c: + check: Avoid error: array subscript is above array bounds + Could have come up with something better for my 2000th commit + to GStreamer... + +2010-09-06 17:01:19 +0300 Stefan Kost + + * gst/gstobject.c: + docs: give a practical example for the gst_object_has_anchestor + +2010-09-06 14:33:44 +0300 Stefan Kost + + * gst/gstelementfactory.c: + elementfactory: use the parent_class defined by G_DEFINE_TYPE + +2010-09-06 14:32:00 +0300 Stefan Kost + + * Makefile.am: + * tests/check/Makefile.am: + tests: tune skipping checks if we have disabled subsystems + Skip ABI tests if some subsystems are off. Remove DISABLE_GST_DEBUG from + skipping export checks as this is safe now. + +2010-09-06 14:09:52 +0300 Olivier Crête + + * gst/gstregistrychunks.c: + registrychunks: Use the correct variable for debug message + Debug print was using a variable that was not initialized. + +2010-08-10 14:05:22 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstregistrychunks.c: + * tools/gst-inspect.c: + * win32/common/libgstreamer.def: + element-details: allow for arbitrary element details + Add a GstStructure to GstElementClass and GstElementFactory. Add setters/getter. + Handle it in the registry code. Print items in gst-inspect. + Fixes #396774. + API: gst_element_class_set_meta_data(), gst_element_factory_get_meta_data_detail() + +2010-09-05 18:57:56 -0700 David Schleef + + * common: + Automatic update of common submodule + From d3d9acf to c2e10bf + +2010-09-05 12:13:00 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ca1c867 to d3d9acf + +2010-09-05 10:22:20 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Add new symbols from GstElementFactoryList + And here's a reminder since I forgot to put them in my previous + commit. + API: gst_element_factory_list_filter + API: gst_element_factory_list_get_elements + API: gst_element_factory_list_is_type + API: gst_plugin_feature_list_debug + API: gst_plugin_feature_rank_compare_func + API: GstElementFactoryListType + API: GST_ELEMENT_FACTORY_TYPE_ANY + API: GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS + API: GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER + API: GST_ELEMENT_FACTORY_TYPE_DECODABLE + API: GST_ELEMENT_FACTORY_TYPE_DECODER + API: GST_ELEMENT_FACTORY_TYPE_DEMUXER + API: GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER + API: GST_ELEMENT_FACTORY_TYPE_ENCODER + API: GST_ELEMENT_FACTORY_TYPE_FORMATTER + API: GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO + API: GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY + API: GST_ELEMENT_FACTORY_TYPE_MUXER + API: GST_ELEMENT_FACTORY_TYPE_PARSER + API: GST_ELEMENT_FACTORY_TYPE_PAYLOADER + API: GST_ELEMENT_FACTORY_TYPE_SINK + API: GST_ELEMENT_FACTORY_TYPE_SRC + API: GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER + +2010-08-31 11:37:42 +0200 Philippe Normand + + * plugins/elements/gstqueue2.c: + queue2: buffering_ranges query support + Fixes bug 623121 + +2010-09-03 19:58:49 +0200 Sebastian Dröge + + * gst/gstquery.c: + gstquery: Only fill the start/stop values of the buffering ranges if a non-NULL pointer was provided + +2010-08-31 11:35:12 +0200 Philippe Normand + + * docs/gst/gstreamer-sections.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gstquery.h: + * tests/check/gst/gstquery.c: + * win32/common/libgstreamer.def: + gstquery: new buffering_ranges API + Added a new query type to retrieve informations about the areas of the + media currently buffered. See bug 623121. + API: gst_query_add_buffering_range + API: gst_query_get_n_buffering_ranges + API: gst_query_parse_nth_buffering_range + +2010-08-16 19:01:15 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + GstElementFactory: Add listing features + https://bugzilla.gnome.org/show_bug.cgi?id=626181 + +2010-09-02 12:44:08 +0100 Tim-Philipp Müller + + * docs/gst/running.xml: + docs: mention GST_DEBUG_OPTIONS, ORC_CODE, G_DEBUG and G_SLICE environment variables + Mention a few more useful environment variables in the 'Running GStreamer + applications' section of the API reference. + +2010-09-02 14:15:29 +0300 Stefan Kost + + * plugins/elements/gstfakesrc.c: + fakesrc: fix use of empty subbuffers + Remove a short cut that was ignoring src->data allocation mode. All + the called code-path below handle size==0. + +2010-09-02 00:01:25 +0100 Jeffrey S. Smith + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstbufferlist.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstquery.h: + * gst/gstutils.h: + * libs/gst/base/gstbytewriter.h: + Fix casts in a bunch of inline functions to maintain correct const-ness + Make code including GStreamer headers compile with -Wcast-qual by + maintaining const-ness when casting. Also fix function signature of + gst_byte_writer_set_pos(): the byte writer should not be marked as + const. + https://bugzilla.gnome.org/show_bug.cgi?id=627910 + +2010-08-31 18:40:44 +0100 Tim-Philipp Müller + + * common: + * configure.ac: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/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). A useful side + effect of this is also that the PKG_CONFIG_PATH environment + is now logged in the configure output. + +2010-09-01 11:34:01 +0200 Wim Taymans + + * docs/manual/advanced-clocks.xml: + manual: improve clock docs a little + +2010-09-01 11:06:57 +0200 Sebastian Dröge + + * tests/check/gst/gstvalue.c: + gstvalue: Fix memory leaks in the int64range tests + +2010-08-24 12:27:30 +0200 Philippe Normand + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * tests/check/gst/gstvalue.c: + * win32/common/libgstreamer.def: + gstvalue: Add new GstInt64Range type + new GstInt64Range to store gint64 ranges. + API: GST_TYPE_INT64_RANGE + API: gst_value_set_int64_range + API: gst_value_get_int64_range_min + API: gst_value_get_int64_range_max + Fixes bug #627826. + +2010-08-30 21:26:18 -0300 Arun Raghavan + + * gst/gstinfo.h: + docs: Trivial cleanup for GST_DEBUG_CATEGORY_GET + +2010-08-30 16:02:55 +0200 Edward Hervey + + * gst/gstinfo.c: + info: Re-instate the default for color usage + This was accidently removed in 7a722091b6d1b5d7f9404fdef4c695a29a65a989 + +2010-08-30 12:47:31 +0200 Edward Hervey + + * libs/gst/check/gstcheck.h: + check: Use g_strcmp0 instead of strcmp + Avoids segfaults when using NULL arguments. + +2010-08-27 15:35:49 +0300 Stefan Kost + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: add silent property to suppress signal emission + Allow to turn off signal emission and therefore extra locking if this is not needed. + Fixes #621299 + +2010-08-28 10:16:05 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + utils: Add gst_util_fraction_compare() to the docs and exported symbols + +2010-08-28 17:51:14 +1000 Jan Schmidt + + * tests/check/gst/gstpad.c: + tests: Remove checks for deprecated flow check macros + GST_FLOW_IS_FATAL() and GST_FLOW_IS_SUCCESS() are deprecated, + so aren't available for the testsuite any more. + +2010-08-28 09:35:01 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Fix inverted assertion logic in gst_util_fraction_compare() + +2010-08-28 09:30:18 +0200 Sebastian Dröge + + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + utils: Add gst_util_fraction_compare() to compare fractions + And use it for the fraction comparisons in gstvalue.c instead + of using comparisons by first converting the fractions to double. + Should fix bug #628174. + API: gst_util_fraction_compare() + +2010-08-28 17:04:43 +1000 Jan Schmidt + + * tests/check/gst/capslist.h: + tests: Add a couple of extra caps strings to test + +2010-08-27 16:52:12 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't do an infinite loop in the loop function + Instead return after every iteration, which makes sure that the + stream lock is released for a short time after every iteration, + task state changes are checked, etc and this allows the task + to be stopped properly. + +2010-08-27 16:49:14 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Flush the data queue if downstream return WRONG_STATE too + +2010-08-26 23:39:06 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue2.c: + elements: Stop using GST_FLOW_IS_FATAL() + +2010-08-26 23:37:07 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + base: Stop using GST_FLOW_IS_FATAL() + And document the special handling of WRONG_STATE. + +2010-08-26 23:07:51 +0200 Sebastian Dröge + + * gst/gstpad.h: + pad: Deprecate GST_FLOW_IS_FATAL() and GST_FLOW_IS_SUCCESS() + The problem with both macros is, that they suggest something that isn't true. + If GST_FLOW_IS_FATAL is true, there could still be a problem for many elements + and they should stop what they're currently doing and return that value + upstream (e.g. not-linked in a parser). If GST_FLOW_IS_SUCCESS is false, it + could still be that this is "ok" for the element (e.g. not-linked for a demuxer + on a few of its pads but not all). + It's better to not have these "convenience" macros but instead let people + *think* about the handling of different flow returns, that makes sense for + their element. And we should document the expected handling of flow returns for + different classes of elements in the plugin writer's guide. + Fixes bug #628014. + +2010-08-27 11:11:00 +0300 Stefan Kost + + * plugins/elements/gstfakesink.c: + fakesink: keep properties in order + +2010-08-27 10:22:27 +0300 Stefan Kost + + * plugins/elements/gstqueue.c: + queue: ARG_ -> PROP_ for property constants + +2010-08-26 17:04:20 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix on-disk buffering again + +2010-08-26 15:12:49 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: recover from invalid downstream suggestions + When we are handling a buffer and need to allocate an output buffer, handle the + case when downstream suggests us a format that we can't convert the input buffer + to. In that case, check if there is another format available downstream instead + of failing. + Fixes #621332 and see also #614296 + +2010-08-26 13:46:34 +0200 Alessandro Decina + + * gst/gstplugin.c: + gstplugin: load the gst-python plugin loader with G_MODULE_BIND_LAZY. + +2010-08-16 14:12:35 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tag: Adds GST_TAG_APPLICATION_DATA + Adds GST_TAG_APPLICATION_DATA for representing arbitrary private + data that applications might want to store into tags. Exif/id3, + for example, have tags for this. + API: GST_TAG_APPLICATION_DATA + Fixes #626651 + +2010-08-24 12:46:38 -0700 David Schleef + + * tools/gst-launch.1.in: + gst-launch: Fix OIL_CPU_FLAGS docs for Orc + +2010-08-24 16:24:19 +0300 Stefan Kost + + * tools/gst-launch.1.in: + man: remove OIL_CPU_FLAGS from man page + We're using ORC instead of libOil now. + +2010-08-23 18:20:23 -0700 David Schleef + + * gst/gstinfo.c: + Valgrind define is HAVE_VALGRIND_VALGRIND_H + +2010-07-27 18:24:44 -0700 David Schleef + + * gst/gstinfo.c: + Allow gst_debug_set_default_threshold() before gst_init() + Calling gst_debug_set_default_threshold() before initialization + seems like the "obvious" order. + +2010-08-23 13:06:19 +0200 Jonas Holmberg + + * tests/check/elements/queue.c: + queue: fix segfault in test + +2010-08-23 10:58:16 +0200 Mark Nauwelaerts + + * gst/gstregistrychunks.c: + registrychunks: intern all GstPluginDesc members when unpacking + +2010-08-23 10:56:30 +0200 Mark Nauwelaerts + + * gst/gstobject.c: + gstobject: fix leak when naming parented object + +2010-08-20 03:07:58 +0530 Arun Raghavan + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gst.h: + * win32/common/libgstreamer.def: + gst: Add a gst_is_initialized() API + For one, this will allow libraries that expect applications to + initialize GStreamer before using their API to have a check for this + condition. + https://bugzilla.gnome.org/show_bug.cgi?id=627438 + +2010-08-20 18:04:52 +0200 Wim Taymans + + * gst/gstbin.c: + bin: relax the source element check + When there is a sink inside a bin, the SINK flag is set on the bin. When we are + trying to iterate the source elements, also include the bins with the SINK flag + because they could also contain source elements, in which case they are also a + source. + This solves the case where sending an EOS to a pipeline didn't get dispatched to + all source elements. + See #625597 + +2010-08-19 17:07:00 +0200 Jonas Holmberg + + * tests/check/elements/queue.c: + queue: added unit test for newsegment events + +2010-03-05 17:18:23 +0100 Jonas Holmberg + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: Push newsegment when linking in PLAYING + Fixes #611918 + +2010-08-12 20:23:45 -0300 Thiago Santos + + * gst/gstutils.c: + element: link_many should activate pads if needed + gst_element_link_many does some magic and creates ghostpads + if needed, but it didn't set the newly created ghostpad to + active if needed. This patch fixes it. + https://bugzilla.gnome.org/show_bug.cgi?id=626784 + +2010-08-19 11:11:28 +0200 Sebastian Dröge + + * tests/check/gst/gstdatetime.c: + datetime: Fix memory leak in the unit test by unreffing GstDateTime instance after usage + +2010-08-19 10:03:08 +0200 Wim Taymans + + * tests/check/elements/queue.c: + tests: fix comments in test + +2010-08-19 09:58:55 +0200 Edward Hervey + + * plugins/elements/gstqueue2.c: + queue2: Use G_GUINT64_FORMAT where needed + Fixes build on macosx + +2010-08-18 15:31:09 +0200 Wim Taymans + + * tests/check/Makefile.am: + check: enable queue test again + +2010-08-18 15:12:45 +0200 Jonas Holmberg + + * tests/check/elements/queue.c: + queue: fixed racy unit tests + Fixes #600004 + +2010-08-16 18:01:27 +0300 Stefan Kost + + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gsttee.c: + plugins: add example launch lines and more explanation to the docs. + The plugins where almost undocumented :/ ... + +2010-08-13 16:19:36 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix compilation + +2010-07-07 08:20:21 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: Fix a special case during range management + When a range contained no data, if it was new or newly empty, it would + be mishandled if it were the current range. + +2010-07-05 13:43:05 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: fix locking around init_ranges + This fixes a segfault where the ready to paused state change causes + freeing and allocation of new ranges while another thread is trying to + use them. + +2010-07-02 17:40:08 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: More ring buffer fixes + - Set reading_pos correctly in _create_read () + - Seek to data if it is further than QUEUE_MAX_BYTES (queue) - + cur_level.bytes away. This should avoid a situation where the ring + buffer is full but the data offset from which we shall read is not in + the ring buffer. + - Only update the max_reading_pos to a lower value to protect data when + necessary + - Always signal an ADD in _locked_enqueue () so that an EOS unlocks the + reader + - More useful debug output + +2010-06-28 17:50:06 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: ring buffer fixes + One must not affect the values of the current range based on a read + request before the correct range is activated. + +2010-06-25 12:58:27 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: Fix bugs + update_buffering () needs to be called every time we write to the ring + buffer so that applications don't get stuck waiting for a 100% buffered + message while queue2 is waiting for space + _create_write () must only be called for temp file/ring buffer cases + +2010-06-18 17:43:40 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: extend ring buffer to support ram mode + +2010-06-18 14:36:33 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: merge write buffer functions and fix bugs + Cached data could have been overwritten so it is now protected until + it is read. Similarly data was overread as _have_data () was always + looking for the originally requested data even if part of it had been + read already. + +2010-06-17 10:18:48 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: small cleanup + +2010-06-16 18:25:35 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: cleanup write_to_ring_buffer + Use cur_level.bytes to see how much space is free in the ringbuffer. + Simplyfy the write function, avoid taking subbuffers, move waiting for free + space in one spot, use simply counter to write data of a buffer. + +2010-06-16 17:03:49 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: cleanups + Add a macro to get the max size of the queue in bytes, which depends on the + max_level.bytes and the ring_buffer_max_size. + Some cleanups. + +2010-06-16 16:23:02 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: remove unused variable + +2010-06-16 16:13:28 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: cleanups + Make sure the cur_level.bytes is updated after we change the writing_pos or the + max_reading_pos. + Refactor get_free_space() + Add some comments + +2010-06-16 12:00:45 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: remove unneeded signal + +2010-06-16 12:00:30 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: set buffering mode correctly + +2010-06-16 11:20:00 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix calculation of available ringbuffer data + +2010-06-16 11:11:32 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: reading_pos is updated in create_read only + +2010-06-16 11:11:11 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: refactor and add debug + +2010-06-16 11:10:23 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix flushing + +2010-06-16 11:09:25 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add debug + +2010-06-15 17:26:15 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: don't try to write 0 bytes + +2010-06-15 16:12:02 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2; cleanups and fixes + Make a macro for some frequent checks + Emit the removed signal in all cases when we remove something + +2010-06-15 12:37:33 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: refactorings + Check and handle seek errors + Refactor the wait_free_space function. + +2010-06-16 12:24:25 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: Use ring-buffer-max-size prop to control ring buffer + +2010-06-06 09:30:48 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: Clean up and improve code + +2010-05-26 04:11:48 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: Fix conditions where behaviour should differ between ring buffer and temp file + +2010-05-19 16:04:15 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: add useful debug messages and fix an assumption in _have_data () + +2010-05-18 17:42:07 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: fix buffering percentage in ring buffer mode + +2010-05-18 17:21:40 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: various ring buffer fixes + - make _get_range () emit the del signal once a buffer has been read + - use do {} while (); for wait code as queue is locked and no data could + have been read in the mean time so it makes no sense to check before + waiting + - make _is_filled () more robust + +2010-05-07 09:30:44 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: ring buffer work in progress + +2010-05-05 10:21:55 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Add use-ring-buffer and ring-buffer-max-size properties + +2010-06-15 08:59:11 +0200 Robert Swain + + * plugins/elements/gstqueue2.c: + queue2: add ST-Ericsson copyright + +2010-08-13 17:23:31 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 3e8db1d to ec60217 + +2010-08-12 22:08:44 +0300 Stefan Kost + + * gst/gstinfo.c: + info: xrefs glib symbol in docs + +2010-08-12 16:05:35 -0300 Thiago Santos + + * libs/gst/base/gstcollectpads.h: + gstcollectpads: Fix docs about GstCollectData list + Add to the docs the fact that is only safe to iterate + GstCollectPad's data list inside the collected callback. + Fixes #610366 + +2010-08-10 10:56:38 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From bd2054b to 3e8db1d + +2010-08-04 11:24:12 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tag: Adds GST_TAG_APPLICATION_NAME tag + Adds a new tag for representing application used to create + a media + https://bugzilla.gnome.org/show_bug.cgi?id=626027 + +2010-08-08 17:57:52 +0200 Sebastian Dröge + + * gst/gstbufferlist.c: + bufferlist: Initialize the GType cache for the bufferlist again + This was accidentially removed with last commit. + +2010-08-06 19:38:22 +0200 Sebastian Dröge + + * gst/gstbufferlist.c: + bufferlist: Don't chain up finalize to the parent class + GstMiniObject::finalize does nothing and this prevents a + runtime-type-check cast and function call per buffer list. + +2010-07-20 09:23:11 -0500 Shixin Zeng + + * gst/gstbufferlist.c: + * gst/gstminiobject.c: + * gst/gstvalue.c: + gst: make _get_type() in gst/* thread safe + This is not really necessary here because everything is + initialized from gst_init() already but using G_DEFINE_TYPE() + removes some copy&paste boilerplate code. + +2010-08-06 19:34:42 +0200 Sebastian Dröge + + * plugins/elements/gstfilesrc.c: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + plugins: Add declarations for _get_type() functions to fix compiler warnings + +2010-07-20 09:23:54 -0500 Shixin Zeng + + * plugins/elements/gstfilesrc.c: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + plugins: Make *_get_type() in plugins/* thread safe + It's not really needed here but using G_DEFINE_TYPE() reduces + some copy&paste boilerplate code. + +2010-08-06 18:43:56 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Make sure the buffer metadata is writable before changing it + +2010-08-05 13:56:11 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 2004d03 to bd2054b + +2010-08-05 10:04:47 +0100 Tim-Philipp Müller + + * gst/gstutils.c: + utils: speed up pad linking utility functions by not trying pads that will never work + In gst_element_get_compatible_pad(), when trying to find a compatible pad on an + element for a given pad, there's no point in checking the element's sink pads + if the pad to link is a sink pad as well, or the element's source pads if the + given pad is a source pad already, since those would never be able to link + anyway. Should speed up linking using the convenience functions a little bit, + or at least reduce debug log output. + +2010-08-05 10:32:53 +0300 Stefan Kost + + * gst/gstinfo.c: + info: take the timestamp a tick later + The logging is not an atomic operation and because of the multi-threading we end + up with out-of-order log lines. Tools that present the log-file should probably + resort the lines. This change just takes the timestamp a bit closer to the + actual logging. + +2010-08-05 09:36:16 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + debug: logging improvements + Use the event serialisation. Log formats name instead of number. + +2010-07-15 15:46:24 +0300 Stefan Kost + + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + check: don't use c++ keywords as variable names + +2010-07-15 11:37:30 +0300 Stefan Kost + + * libs/gst/base/gstbasesrc.c: + basesrc: log seek event details + +2010-07-12 10:50:53 +0300 Stefan Kost + + * docs/manual/advanced-dparams.xml: + manual: update gst-controller chapter + The docs were still describing deprecated api. Update it to tell about + control-cources. + +2010-07-09 15:58:50 +0300 Stefan Kost + + * tests/benchmarks/controller.c: + * tests/examples/helloworld/helloworld.c: + * tests/examples/launch/mp3parselaunch.c: + * tests/examples/queue/queue.c: + * tests/examples/stepping/framestep1.c: + * tests/examples/streams/stream-status.c: + * tests/examples/typefind/typefind.c: + tests: clean up eventloop in examples + Don't leak the bus. Don't parse messages with the method for errors (triggers + gobject warning). + +2010-07-08 14:08:27 +0300 Stefan Kost + + * tests/benchmarks/capsnego.c: + benchmark: handle errors from the pipeline + Catch errors and warnings on the bus. This fixes hanging pipelines in the case + of bugs elsewhere. Also print state-change messages to give more detail on the progress. + +2010-07-06 18:20:40 +0300 Stefan Kost + + * tests/benchmarks/capsnego.c: + benchmark: cleanup last change in capsnego benchmark + A pad name is not a factory name. + +2010-07-06 14:29:39 +0300 Stefan Kost + + * gst/gstparse.c: + docs: more docs for gst_parse_launch and co + Tell about limited reusability of some parsed pipelines. + +2010-07-05 16:32:00 +0300 Stefan Kost + + * tools/gst-inspect.c: + inspect: pad info output improvements + Don't print empty query types. Also print caps-vmethods. + +2010-07-06 16:47:22 +0300 Stefan Kost + + * gst/gstpad.c: + pad: log element:pad names with caps + +2010-06-30 11:46:11 +0300 Stefan Kost + + * gst/gstutils.c: + utils: better error logging in link_pads_filtered + +2010-06-24 10:00:04 +0300 Stefan Kost + + * tests/check/libs/transform1.c: + tests: add comments telling the meaning of the abbreviations + +2010-07-05 12:19:29 +0300 Stefan Kost + + * libs/gst/base/gstbasesrc.c: + basesrc: avoid some caps manipulation + After the intersect we have writable caps. Copy the template caps so that also + there we have writable caps. + +2010-08-05 01:09:02 +0100 Tim-Philipp Müller + + * tests/check/gst/gstutils.c: + tests: add basic unit test for gst_pad_proxy_getcaps() + https://bugzilla.gnome.org/show_bug.cgi?id=624203 + +2010-08-05 01:06:57 +0100 Olivier Crête + + * gst/gstutils.c: + gstutils: Make gst_pad_proxy_getcaps() return empty caps if it's what the other side has + gst_pad_proxy_getcaps() would return the pad template caps if the other side + returned empty caps or if the intersection of all the caps on the other side + was empty. + https://bugzilla.gnome.org/show_bug.cgi?id=624203 + +2010-08-04 19:19:55 +0200 Sebastian Dröge + + * 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 13:47:23 -0300 Thiago Santos + + * libs/gst/base/gstbytereader.c: + bytereader: Fix docs + Fix typo in docs for the unsigned peek functions + +2010-07-05 10:00:02 +0200 Wim Taymans + + * gst/gst.c: + gst: remove \n from debug statements + +2010-08-03 11:37:13 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: fix build with gtk-doc from git + For some reason the static inline function GST_CAT_LEVEL_LOG_valist is + now picked up, which then breaks the build because it's not documented, + so add it to the sections file. + Based on patch by Víctor Manuel Jáquez Leal . + Fixes #625862. + +2010-07-15 23:05:09 +0300 Stefan Kost + + * plugins/elements/gsttypefindelement.c: + typefind: add comment and more logging + +2010-07-29 17:27:06 +0200 Mark Nauwelaerts + + * plugins/elements/gstqueue2.c: + queue2: download mode; prevent range corruption due to race + Current range was being updated in the thread performing seek, but as + no locks were kept for a short section, data flow could resume before + current range updated, so data for the new range would be accepted as + from the previous range. + Rather, range should be updated in serialized manner based on + newsegment event. + +2010-05-22 16:33:11 -0500 Rob Clark + + * libs/gst/base/gstbasetransform.c: + basetransform fix for upstream caps-renegotiation + If initially pass-through caps are negotiated between a transform element's + sink and src pads, but then the downstream element returns different caps + on a buffer from pad_alloc(), basetransform gets stuck with proxy_alloc=TRUE + even though the upstream peer doesn't accept the caps, causing + gst_pad_peer_accept_caps() to be called on each buffer in _buffer_alloc(): + if (!gst_caps_is_equal (newcaps, caps)) { + GST_DEBUG_OBJECT (trans, "caps are new"); + /* we have new caps, see if we can proxy downstream */ + >> if (gst_pad_peer_accept_caps (pad, newcaps)) { + /* peer accepts the caps, return a buffer in this format */ + GST_DEBUG_OBJECT (trans, "peer accepted new caps"); + which is taking ~40ms/frame. + This patch does two things. (1) if the buffer returned from pad_alloc() has + new caps, trigger the decision whether to proxy the buffer-alloc to be + revisited, and (2) disable proxy if peer does not accept new caps. (The first + part may not be strictly needed, but seemed like a good idea.) + Note that this issue would not arise except in case of downstream elements + who have on their template-caps, some that would be suitable for pass-through, + but at runtime pick more restrictive caps (for ex, after querying a driver for + what formats it actually supports). + +2010-07-27 14:30:51 +0200 Tim-Philipp Müller + + * gst/gstinfo.c: + info: fix compilation on windows + Fix mismatched brackets (#625295). + +2010-07-27 07:21:19 -0300 Thiago Santos + + * gst/gstdatetime.c: + gstdatetime: Fix localtime usage + localtime only takes one parameter and returns a statically + allocated tm struct. Use it correctly. + Fixes #625368 + +2010-03-29 18:05:40 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + * tests/check/libs/transform1.c: + basetransform: Try suggesting caps on bad caps pad_alloc + When basetransform received an unsupported caps on pad_alloc + it just returned not-negotiated. This patch makes it query + the allowed caps between his sinkpad and upstream's srcpad + to find a caps to suggest. + This happens when dinamically switching pipeline elements + and upstream pad_allocs with the previous caps that was + being used. + Fixes #614296 + +2010-07-26 18:53:57 +0200 Tim-Philipp Müller + + * gst/gstinfo.c: + info: flush again after every line of debug output + g_printerr() used to do this for us. Also use libc's fprintf() functions, + to make sure the stderr pointer we use is actually compatible with the + libc linked against by GStreamer (which apparently may not always be the + same as what GLib is linked against on windows), and we don't need the + functionality ensured by g_fprintf(). + Fixes #625295. + +2010-07-26 18:53:35 +0200 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new strings + +2010-06-23 11:31:33 -0300 Thiago Santos + + * tests/check/gst/gstvalue.c: + gstvalue: Adds tests for datetime + Adds tests for datetime fields in gstvalue tests + Fixes #594504 + +2010-06-23 11:30:02 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + gststructure: Adds datetime getter function + Adds gst_structure_get_date_time function + API: gst_structure_get_date_time + Fixes #594504 + +2010-06-21 23:42:44 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tag: Adds GST_TAG_DATE_TIME tag + Adds a new tag that represents a date and time a media was + created + API: GST_TAG_DATE_TIME + Fixes #594504 + +2010-07-21 22:08:21 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * win32/common/libgstreamer.def: + taglist: Add datetime get functions + Adds _date_time_get and _date_time_get_index functions to + taglist. + API: gst_tag_list_get_date_time + API: gst_tag_list_get_date_time_index + Fixes #594504 + +2010-07-21 22:04:23 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gst_private.h: + * gst/gstdatetime.c: + * gst/gststructure.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + * win32/common/libgstreamer.def: + gstvalue: Adds datetime functions + Adds a datetime functions to gstvalue + Fixes #594504 + +2010-07-16 14:09:12 -0300 Thiago Santos + + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstdatetime.c: + * gst/gstdatetime.h: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstdatetime.c: + * win32/common/libgstreamer.def: + gstdatetime: Adds GstDateTime + Adds GstDateTime to represent dates + time + timezone + information. + Tests included. + API: GstDateTime + API: gst_date_time_get_day + API: gst_date_time_get_month + API: gst_date_time_get_year + API: gst_date_time_get_hour + API: gst_date_time_get_microsecond + API: gst_date_time_get_minute + API: gst_date_time_get_second + API: gst_date_time_get_time_zone_offset + API: gst_date_time_new + API: gst_date_time_new_local_time + API: gst_date_time_new_from_unix_epoch + API: gst_date_time_new_now_local_time + API: gst_date_time_new_now_utc + API: gst_date_time_ref + API: gst_date_time_unref + Fixes #594504 + +2010-07-26 14:59:51 +0200 Sebastian Dröge + + * gst/gst.c: + gst: Fix usage of glib_check_version() + It returns NULL if the installed GLib version is as least as + new as the required version and some explanatory string otherwise. + +2010-07-23 20:46:10 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: make gst-inspect print the release date time stamp + +2010-06-21 17:34:49 +0100 Tim-Philipp Müller + + * common: + * configure.ac: + configure: use new AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO macro + +2010-06-20 01:55:00 +0100 Tim-Philipp Müller + + * gst/gstregistrybinary.h: + * gst/gstregistrychunks.c: + binaryregistry: save and load release date time in GstPluginDesc + https://bugzilla.gnome.org/show_bug.cgi?id=623040 + +2010-06-20 00:33:36 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + * gst/gstplugin.h: + * tests/check/gst/gstplugin.c: + plugin: add release datetime field to GstPluginDesc and set it if GST_PACKAGE_RELEASE_DATETIME is defined + This is a string describing a date and/or date/time in a simple subset of + the ISO-8601 format, namely either "YYYY-MM-DD" or "YYYY-MM-DDTHH:MMZ" (with + 'T' the date/time separator and the 'Z' indicating UTC). + The main purpose of this field is to keep track of plugin and element versions + on an absolute timeline, so it's possible to determine which one is newer when + comparing two date time numbers. This will allow us to express 'replaces'-type + relationships betweeen plugins and element factories in future, even across + different modules and plugin merges or splits (source module version numbers + aren't particularly useful here, since they can only meaningfully be compared + within the same module). It also allows applications and libraries to reliably + check that a plugin is recent enough without making assumptions about modules + or module versions. + We use a string here to keep things simple and clear, esp. on the build system + side of things. + https://bugzilla.gnome.org/show_bug.cgi?id=623040 + +2010-07-20 09:25:20 -0500 Shixin Zeng + + * tests/check/gst/gstobject.c: + * tests/check/gst/gstpreset.c: + * tests/check/libs/controller.c: + tests: make *_get_type() in tests thread safe + Even if it shouldn't be needed here. See #623491. + +2010-06-04 11:24:59 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: write debugging output to file if GST_DEBUG_FILE environment variable is set + This changes behaviour slightly in that we no longer output things + via g_printerr(), so any non-standard glib printerr handlers are no + longer called when GST_DEBUG is enabled. However, this seems not + really desirable in most cases anyway, and the GLib docs also say + that libraries should not use g_printerr() for logging. + Other stderr output (e.g. warnings, or application messages) will + of course not be captured in the log file this way. + GST_DEBUG_FILE=- will redirect debug output to stdout. + +2010-07-20 20:49:12 +0200 Edward Hervey + + * gst/gstpad.c: + gstpad: Assume pads are compatible if we don't have templates + This is the same behaviour as if we had a pad template caps of + GST_CAPS_ANY on any of the pads (i.e. the actual check will be done + during caps negotiation). + +2010-07-17 21:28:41 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Allow the subclass to add new fields to caps when getting new caps from downstream + This was already done in all other cases where new caps are handled + except upstream negotiation. + +2010-07-12 14:39:00 +0200 Michael Bunk + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-clocks.xml: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/advanced-dparams.xml: + * docs/manual/advanced-interfaces.xml: + * docs/manual/advanced-metadata.xml: + * docs/manual/advanced-threads.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-pads.xml: + * docs/manual/intro-basics.xml: + * docs/manual/manual.xml: + docs: fix some typos and add some missing links in the app dev manual + Fixes #624164. + +2010-07-12 14:22:50 +0200 Michael Bunk + + * tools/gst-inspect.1.in: + docs: fix typo on gst-inspect man page + See #624164. + +2010-07-03 15:08:12 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + gstcheck: fix some silly list iteration code + g_list_length() is not the best way to check if a list is empty or not. + +2010-07-16 17:53:38 +0100 Tim-Philipp Müller + + * gst/glib-compat-private.h: + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + registry: use GStatBuf unconditionally and add typedef for backwards compatibility + No need to clutter the code with #if #else #endif. + See #623875. + +2010-07-16 17:33:38 +0200 Sebastian Dröge + + * gst/gststructure.c: + * gst/gststructure.h: + structure: Use a const GstStructure * as parameter for some more gst_structure_get variants + +2010-07-14 19:47:43 +0200 Sebastian Dröge + + * tools/gst-launch.c: + Revert "-launch: disable CLOCK_LOST message handling" + This reverts commit 1f8eba611a63f45766c38c640288e42b27b10bd4. + This should be fixed now (and if not should be fixed) and the + clock-lost handling is now needed for playbin2 gapless playback. + See bug #579127. + +2010-07-08 21:04:54 +0200 David Hoyt + + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + registrybinary: Fix compatibility with GLib 2.25 when using MSVC + Newer GLib uses a new type for g_stat() and friends to improve + Windows compatibility. On POSIX this is a typedef to struct stat. + Fixes bug #623875. + +2010-07-08 07:48:07 +0200 Sebastian Dröge + + * gst/gstpipeline.c: + pipeline: If the currently used clock gets lost update it the next time when going from PAUSED to playing + Fixes bug #623806. + +2010-07-05 19:33:01 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Return values in stream time for the POSITION query + Fixes bug #623622. + +2010-07-05 18:54:45 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Implement GstElement::get_query_types() + +2010-07-06 10:13:04 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Only answer the SEGMENT query in pull mode + Otherwise the element handling the seeks should answer this query. + Fixes bug #623622. + +2010-07-05 10:36:05 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Implement POSITION query + Fixes bug #623541. + +2010-06-25 16:31:06 +0200 Edward Hervey + + * gst/gstpad.c: + GstPad: Do not call gst_pad_accept_caps() when caps change + Instead just check that the caps intersect with the pad template. + The elements should properly accept/refuse the caps in setcaps(). + Shaves off calling the default implementation of acceptcaps which does + an expensive gst_pad_get_caps() (so if you have 50 of those elements in + a row, you'd be doing factorial(50) gst_pad_get_caps...). + Does not break any module unit test and most apps work fine. + https://bugzilla.gnome.org/show_bug.cgi?id=622740 + +2010-07-08 16:24:21 +0200 Edward Hervey + + * gst/gstutils.c: + utils: Add more details about gst_element_get_compatible_pad + +2010-07-16 11:16:15 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development. + +=== release 0.10.30 === + +2010-07-14 23:59:43 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.30 + +2010-07-14 17:58:15 +0100 Tim-Philipp Müller + + * po/de.po: + * po/id.po: + * po/zh_CN.po: + po: update translations + +2010-07-15 12:01:24 +0300 Stefan Kost + + * gst/gstpad.h: + pad: remove comma at the end of the last enum value + Fixes the build for c++. + +2010-07-11 19:00:54 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttag.c: + checks: add unit test for recent taglist merge_strings_with_comma fix + See #624113. + +2010-07-11 18:59:53 +0100 Eduardo Dobay + + * gst/gsttaglist.c: + taglist: fix merge_strings_with_comma() for more than two strings + Fixes #624113. + +2010-07-08 13:46:56 +0100 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + .gitignore: ignore new basesink unit test binary + +2010-07-08 13:43:22 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + tools: remove -p shorthand for --no-sigusr-handler + It's not really needed, and doesn't map any longer after the long option + has been renamed. + +2010-07-06 15:47:40 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * tests/check/gst/.gitignore: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.29.4 pre-release + Also bump libtool versions now (which I meant to do for the first + pre-release but forgot). + +2010-07-06 23:44:26 +0100 Tim-Philipp Müller + + * po/LINGUAS: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/id.po: + * po/it.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/sl.po: + * po/sv.po: + * po/zh_CN.po: + po: update translations + +2010-07-06 16:21:05 +0200 Alessandro Decina + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * tests/check/libs/basesink.c: + * win32/common/libgstbase.def: + basesink: add accessors for the enable-last-buffer property. + API: gst_base_sink_set_last_buffer_enabled + API: gst_base_sink_is_last_buffer_enabled + +2010-07-06 12:18:45 +0200 Alessandro Decina + + * libs/gst/base/gstbasesink.c: + * tests/check/Makefile.am: + * tests/check/libs/basesink.c: + basesink: add new enable-last-buffer property. + Add a new enable-last-buffer property. When false, it disables storing the last + received buffer in basesink::last-buffer. This can be useful in cases where + buffers need to be released asap. + API: GstBaseSink::enable-last-buffer + +2010-07-06 10:48:27 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttagsetter.c: + checks: rewrite gsttagsetter test to use fewer g_usleep() + Something about that seems to interact badly with some schedulers, + so do things differently. + Fixes #623469. + +2010-07-06 10:19:09 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + docs: add new add gst_clock_id_wait_async_full() to docs + API: add gst_clock_id_wait_async_full + See #623589. + +2010-07-06 10:28:14 +0200 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Improve gst_value_{set|get}_caps docs + +2010-07-06 10:35:09 +0200 Alessandro Decina + + * win32/common/libgstreamer.def: + win32: export gst_clock_id_wait_async_full + +2010-07-06 10:31:25 +0200 Alessandro Decina + + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + tests: remove ABI checks for GstClockEntry. + +2010-07-05 18:45:55 +0200 Alessandro Decina + + * gst/gstclock.h: + clock: document that GstClockEntry should be treated as ana opaque structure. + +2010-07-05 13:10:09 +0200 Alessandro Decina + + * gst/gstclock.c: + * tests/check/Makefile.am: + * tests/check/gst/gstclock.c: + * tests/check/gst/gstsystemclock.c: + clock: use the new gst_clock_id_wait_async_full. + Use the new gst_clock_id_wait_async_full in gst_clock_set_master. + Also add some tests. + +2010-07-05 13:01:53 +0200 Alessandro Decina + + * gst/gstclock.c: + clock: fix refcounting bug in gst_clock_set_master. + Make sure clock->clockid is unreffed before clock->master. + gst_clock_id_unschedule (clock->clockid) tries to access clock->master. If + clock->master is unreffed before and it's deallocated, _unschedule could access + free'd memory. + +2010-07-05 12:56:40 +0200 Alessandro Decina + + * gst/gstclock.c: + * gst/gstclock.h: + clock: add gst_clock_id_wait_async_full. + Add gst_clock_id_wait_async_full. It's the same as gst_clock_id_wait_async but + allows passing a GDestroyNotify to destroy user_data. + +2010-07-05 17:50:33 +0300 Stefan Kost + + * gst/gstpad.h: + * gst/gstutils.c: + docs: improve the api docs for new GstPadLinkChecks and its use + +2010-07-05 12:21:51 +0300 Stefan Kost + + * tests/README: + README: update after removal of "old" dir. + Remove "old" and add a line about "examples". + +2010-07-04 17:34:30 +0100 Tim-Philipp Müller + + * tests/old/examples/Makefile.am: + * tests/old/examples/TODO: + * tests/old/examples/appreader/.gitignore: + * tests/old/examples/appreader/Makefile.am: + * tests/old/examples/appreader/appreader.c: + * tests/old/examples/cutter/.gitignore: + * tests/old/examples/cutter/Makefile.am: + * tests/old/examples/cutter/cutter.c: + * tests/old/examples/cutter/cutter.h: + * tests/old/examples/events/Makefile.am: + * tests/old/examples/events/seek.c: + * tests/old/examples/helloworld2/.gitignore: + * tests/old/examples/helloworld2/Makefile.am: + * tests/old/examples/helloworld2/helloworld2.c: + * tests/old/examples/manual/.gitignore: + * tests/old/examples/manual/Makefile.am: + * tests/old/examples/manual/extract.pl: + * tests/old/examples/mixer/.gitignore: + * tests/old/examples/mixer/Makefile.am: + * tests/old/examples/mixer/mixer.c: + * tests/old/examples/mixer/mixer.h: + * tests/old/examples/pingpong/.gitignore: + * tests/old/examples/pingpong/Makefile.am: + * tests/old/examples/pingpong/pingpong.c: + * tests/old/examples/plugins/.gitignore: + * tests/old/examples/plugins/Makefile.am: + * tests/old/examples/plugins/example.c: + * tests/old/examples/plugins/example.h: + * tests/old/examples/pwg/.gitignore: + * tests/old/examples/pwg/Makefile.am: + * tests/old/examples/pwg/extract.pl: + * tests/old/examples/queue2/.gitignore: + * tests/old/examples/queue2/Makefile.am: + * tests/old/examples/queue2/queue2.c: + * tests/old/examples/queue3/.gitignore: + * tests/old/examples/queue3/Makefile.am: + * tests/old/examples/queue3/queue3.c: + * tests/old/examples/queue4/.gitignore: + * tests/old/examples/queue4/Makefile.am: + * tests/old/examples/queue4/queue4.c: + * tests/old/examples/retag/.gitignore: + * tests/old/examples/retag/Makefile.am: + * tests/old/examples/retag/retag.c: + * tests/old/examples/retag/transcode.c: + * tests/old/examples/thread/.gitignore: + * tests/old/examples/thread/Makefile.am: + * tests/old/examples/thread/thread.c: + * tests/old/testsuite/.gitignore: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/Rules: + * tests/old/testsuite/caps/.gitignore: + * tests/old/testsuite/caps/Makefile.am: + * tests/old/testsuite/caps/app_fixate.c: + * tests/old/testsuite/caps/audioscale.c: + * tests/old/testsuite/caps/caps.c: + * tests/old/testsuite/caps/caps.h: + * tests/old/testsuite/caps/caps_strings: + * tests/old/testsuite/caps/compatibility.c: + * tests/old/testsuite/caps/deserialize.c: + * tests/old/testsuite/caps/enumcaps.c: + * tests/old/testsuite/caps/eratosthenes.c: + * tests/old/testsuite/caps/filtercaps.c: + * tests/old/testsuite/caps/fixed.c: + * tests/old/testsuite/caps/fraction-convert.c: + * tests/old/testsuite/caps/fraction-multiply-and-zero.c: + * tests/old/testsuite/caps/intersect2.c: + * tests/old/testsuite/caps/intersection.c: + * tests/old/testsuite/caps/normalisation.c: + * tests/old/testsuite/caps/random.c: + * tests/old/testsuite/caps/renegotiate.c: + * tests/old/testsuite/caps/sets.c: + * tests/old/testsuite/caps/simplify.c: + * tests/old/testsuite/caps/string-conversions.c: + * tests/old/testsuite/caps/structure.c: + * tests/old/testsuite/caps/subtract.c: + * tests/old/testsuite/caps/union.c: + * tests/old/testsuite/debug/.gitignore: + * tests/old/testsuite/debug/Makefile.am: + * tests/old/testsuite/debug/category.c: + * tests/old/testsuite/debug/commandline.c: + * tests/old/testsuite/debug/global.c: + * tests/old/testsuite/debug/output.c: + * tests/old/testsuite/debug/printf_extension.c: + * tests/old/testsuite/dlopen/.gitignore: + * tests/old/testsuite/dlopen/Makefile.am: + * tests/old/testsuite/dlopen/dlopen_gst.c: + * tests/old/testsuite/dlopen/loadgst.c: + * tests/old/testsuite/elements/.gitignore: + * tests/old/testsuite/elements/Makefile.am: + * tests/old/testsuite/elements/gst-inspect-check.in: + * tests/old/testsuite/elements/struct_i386.h: + * tests/old/testsuite/elements/struct_size.c: + * tests/old/testsuite/indexers/.gitignore: + * tests/old/testsuite/indexers/Makefile.am: + * tests/old/testsuite/indexers/cache1.c: + * tests/old/testsuite/indexers/indexdump.c: + * tests/old/testsuite/parse/.gitignore: + * tests/old/testsuite/parse/Makefile.am: + * tests/old/testsuite/parse/parse1.c: + * tests/old/testsuite/parse/parse2.c: + * tests/old/testsuite/plugin/.gitignore: + * tests/old/testsuite/plugin/Makefile.am: + * tests/old/testsuite/plugin/README: + * tests/old/testsuite/plugin/dynamic.c: + * tests/old/testsuite/plugin/linked.c: + * tests/old/testsuite/plugin/loading.c: + * tests/old/testsuite/plugin/registry.c: + * tests/old/testsuite/plugin/static.c: + * tests/old/testsuite/plugin/static2.c: + * tests/old/testsuite/plugin/testplugin.c: + * tests/old/testsuite/plugin/testplugin2.c: + * tests/old/testsuite/plugin/testplugin2_s.c: + * tests/old/testsuite/plugin/testplugin_s.c: + * tests/old/testsuite/refcounting/.gitignore: + * tests/old/testsuite/refcounting/Makefile.am: + * tests/old/testsuite/refcounting/bin.c: + * tests/old/testsuite/refcounting/element.c: + * tests/old/testsuite/refcounting/element_pad.c: + * tests/old/testsuite/refcounting/mainloop.c: + * tests/old/testsuite/refcounting/mem.c: + * tests/old/testsuite/refcounting/mem.h: + * tests/old/testsuite/refcounting/object.c: + * tests/old/testsuite/refcounting/pad.c: + * tests/old/testsuite/refcounting/sched.c: + * tests/old/testsuite/refcounting/thread.c: + * tests/old/testsuite/states/.gitignore: + * tests/old/testsuite/states/Makefile.am: + * tests/old/testsuite/states/bin.c: + * tests/old/testsuite/states/locked.c: + * tests/old/testsuite/states/parent.c: + * tests/old/testsuite/threads/.gitignore: + * tests/old/testsuite/threads/159566.c: + * tests/old/testsuite/threads/159852.c: + * tests/old/testsuite/threads/Makefile.am: + * tests/old/testsuite/threads/queue.c: + * tests/old/testsuite/threads/signals.c: + * tests/old/testsuite/threads/staticrec.c: + * tests/old/testsuite/threads/thread.c: + * tests/old/testsuite/threads/threadb.c: + * tests/old/testsuite/threads/threadc.c: + * tests/old/testsuite/threads/threadd.c: + * tests/old/testsuite/threads/threade.c: + * tests/old/testsuite/threads/threadf.c: + * tests/old/testsuite/threads/threadg.c: + * tests/old/testsuite/threads/threadh.c: + * tests/old/testsuite/threads/threadi.c: + Remove old 0.8 tests and examples from git tree + Doesn't really look like anything's worth keeping. + +2010-07-03 16:39:40 +0100 Tim-Philipp Müller + + * tests/check/gst/gstobject.c: + check: skip silly test that segfaults when in a CK_FORK=no environment + See #623469. + +2010-07-03 15:13:14 +0100 Tim-Philipp Müller + + * tests/check/elements/fakesrc.c: + checks: make fakesrc check work in a CK_FORK=no environment + Reset have_eos at the beginning of each test. + See #623469. + +2010-07-03 14:09:36 +0100 Tim-Philipp Müller + + * tests/check/gst/gst.c: + checks: run tests calling gst_deinit() last so things work with CK_FORK=no + Because gst_init() will fail once gst_deinit() has been called. + See #623469. + +2010-07-03 14:04:32 +0100 Tim-Philipp Müller + + * tests/check/gst/gstelement.c: + checks: don't assume element factory is not loaded yet + It may already be loaded if check is being run with CK_FORK=no. + See #623469. + +2010-07-01 19:58:09 +0100 Tim-Philipp Müller + + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-dparams.xml: + * docs/manual/advanced-interfaces.xml: + * docs/manual/advanced-position.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/basics-helloworld.xml: + docs: fix a couple of typos in the manual + Spotted by Alexander Saprykin. + Fixes #622379. + +2010-07-01 17:56:33 +0200 Edward Hervey + + * gst/gstcaps.c: + * tests/check/gst/gstcaps.c: + gstcaps: Make sure _normalize() is applied on all structures. + We need to use gst_caps_get_size() in the loop counter since some + structures could be added while iterating. + Fixes #623301 + +2010-06-30 13:16:35 +0100 Tim-Philipp Müller + + * docs/manual/highlevel-xml.xml: + docs: update 'XML in GStreamer' section in application developer's manual + +2010-06-29 18:48:05 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.29.3 pre-release + +2010-06-25 19:03:27 +0200 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: implement acceptcaps function + Our acceptcaps function can simply forward the query. + +2010-06-28 15:28:59 +0100 Tim-Philipp Müller + + * autogen.sh: + * configure.ac: + Bump automake requirement to 1.10 + For maintainability reasons and $(builddir). + Fixes #622944. + +2010-06-28 13:56:00 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + tools: mention --eos-on-shutdown on gst-launch man page + +2010-06-28 10:20:39 +0200 Sebastian Dröge + + * gst/gstutils.h: + utils: Don't use G_GNUC_CONST for the uint64 scaling functions + They are actually *not* const functions because on architectures + without int128 instructions the parameters were changed. + gcc re-used the parameters on the stack for multiple calls though + and the changed parameters were used for the second call then. + Fixes bug #623003. + +2010-06-26 17:48:31 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + 0.10.29.2 pre-release + +2010-06-26 17:47:55 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2010-06-26 10:16:36 +0100 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * tests/examples/xml/.gitignore: + * tests/examples/xml/Makefile.am: + * tests/examples/xml/createxml.c: + * tests/examples/xml/runxml.c: + examples: remove xml example build system bits and purge from tree + Fixes make distcheck. + +2010-06-26 09:59:31 +0100 Tim-Philipp Müller + + * gst/gstxml.c: + xml: keep dummy gst_xml_get_type() function for g-i even if rest of GstXML is removed + Add a minimal gst_xml_get_type() function, so that gobject-introspection doesn't + break the compilation if we're compiling with GST_REMOVE_DEPRECATED defined or + --disable-loadsave having been passed to configure. Until someone figures out + a better way at least. + +2010-06-26 01:01:49 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstcaps.c: + * gst/gstconfig.h.in: + * gst/gstelement.c: + * gst/gstghostpad.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstxml.c: + * plugins/indexers/gstfileindex.c: + Don't include from public headers if GST_DISABLE_DEPRECATED is defined + Since everything GstXML related has been deprecated, we can now skip the + libxml includes from the public headers when GST_DISABLE_DEPRECATED is + defined. + See #463435. + +2010-06-26 00:18:10 +0100 Tim-Philipp Müller + + * tests/examples/typefind/typefind.c: + examples: add missing stdlib.h include in typefind example + +2010-06-25 21:23:22 +0300 Stefan Kost + + * gst/gstdebugutils.c: + dot-dump: terminate truncated strings and escape special chars + Fixes syntax errors in generated dot files for caps with strings. + +2010-06-25 18:52:02 +0200 Edward Hervey + + * gst/gstpad.c: + * gst/gstpad.h: + pad: more documentation regarding the new flags + +2010-06-25 18:18:55 +0200 Wim Taymans + + * gst/gstpad.h: + pad: make the NOTHING link check flag be 0 + Make the pad link check of NOTHING be 0. This way we have a flag for each + feature and 0 when no flags are set. + +2010-06-25 18:24:47 +0200 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_sparc.h: + * tests/check/gst/struct_x86_64.h: + tests: Remove GstXML tests + +2010-06-25 18:13:57 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstelement.c: + * gst/gstghostpad.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstxml.c: + * gst/gstxml.h: + * tests/examples/Makefile.am: + * tests/examples/manual/Makefile.am: + * tools/Makefile.am: + * tools/gst-launch.c: + gstxml: Deprecate GstXml and related functions + Pipeline serialisation to and from XML is horribly broken for all + but the most simple use cases, and will likely never be fixed. + Make sure everyone playing around with these tools is aware of + this, to avoid frustration. See countless bug reports in bugzilla. + Fixes bug #622685. + +2010-06-25 18:11:30 +0200 Sebastian Dröge + + * libs/gst/controller/gstcontroller.c: + controller: Fix build with GST_REMOVE_DEPRECATED + +2010-06-24 12:19:20 +0200 Edward Hervey + + * tests/benchmarks/capsnego.c: + benchmarks: Use gst_element_link_pads_full + We're testing caps negotiation, not pad linking. Brings the startup + time down 100 fold. + +2010-06-24 17:53:36 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + * tools/gst-xmllaunch.1.in: + tools: deprecate gst-xmllaunch and print fat warning if someone tries to use it + Pipeline serialisation to and from XML is horribly broken for all + but the most simple use cases, and will likely never be fixed. + Make sure everyone playing around with these tools is aware of + this, to avoid frustration. See countless bug reports in bugzilla. + +2010-06-24 17:22:13 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + gst-launch: rename new --no-play command line option to --no-sigusr-handler + --no-play seems a bit confusing. + Fixes #621867. + +2010-06-24 15:07:11 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 73ff93a to a519571 + +2010-06-23 11:02:16 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstregistrybinary.c: + * gst/gstregistrybinary.h: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + binaryregistry: ignore the plugin cache if the filter environment has changed + Make sure that we properly update the registry and the cache file whenever + the filter environment changes or there's no more filter set. + +2010-05-27 12:36:10 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.c: + pluginloading: add support for whitelisting based on plugin or source module name and path + This feature is primarily intended for use in plugin modules' unit tests. + Consider the following situation: gst-plugins-good is built against an + installed GStreamer core. An older version of gst-plugins-good is also + installed in that prefix, along with random other plugin modules. Now, + when doing 'make check' in the just-built gst-plugins-good tree, we + want to only load plugins from GStreamer core, gst-plugins-base, and + gst-plugins-good, but not random other modules (we don't want any unit + tests to fail just because some module in gst-plugins-bad has a broken + plugin_init, for example). Also, we want to only load gst-plugins-good + modules from the locally-built source tree, but not any of the older + gst-plugins-good modules installed. This is usually assured by loading + the ones in the source tree first (by adding that path first to the + right environment variables), but it gets tricky when plugins are + moved, removed, merged, or renamed, or the plugin filename changes. + Note that 'make check' should really work right without doing + 'make install' or uninstalling the old gst-plugins-good package (or + any other gst-plugins-foo package) first. + Enter GST_PLUGIN_LOADING_WHITELIST. This environment variable may + contain source-package@path-prefix pairs separated by the platform + search path separator (G_SEARCHPATH_SEPARATOR_S). The source package + and path prefix are separated by the '@' character. The path prefix is + entirely optional, as is the '@' separator if no path is given. + It is also possible to filter based on plugin names instead of the name + of the source-package by specifying one or more plugin names separated + by commas before the optional path prefix. + In short, the following match patterns are possible: + plugin1,plugin2@pathprefix or + plugin1,plugin2@* or just + plugin1,plugin2 or + source-package@pathprefix or + source-package@* or just + source-package + So for our gst-plugins-good unit test example above, we would set the + environment variable on *nix to something like this (will likely be a + relative path in practice): + gstreamer:gst-plugins-base:gst-plugins-good@/path/to/src/gst-plugins-good + Fixes #619815 and #619717. + +2010-06-23 17:24:07 +0200 Edward Hervey + + * gst/gstghostpad.c: + gstghostpad: We don't need any checks when linking target pad + https://bugzilla.gnome.org/show_bug.cgi?id=622504 + +2010-06-23 17:00:17 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + gstutils: New gst_element_link_pads_full method + Links the elements with the specified pad linking checks. + API:gst_element_link_pads_full + https://bugzilla.gnome.org/show_bug.cgi?id=622504 + +2010-06-23 16:45:19 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + GstPad: Add new pad linking method with configurable checks. + To be used for cases where we don't need all checks to be validated. + API: gst_pad_link_full + API: GstPadLinkCheck + https://bugzilla.gnome.org/show_bug.cgi?id=622504 + +2010-06-15 18:26:01 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tag: Adds GST_TAG_IMAGE_ORIENTATION tag + Adds a new tag to inform about the image orientation and how + to rotate and flip it before display. + Note that this tag is a string with a predefined set of + possible values. + API: GST_TAG_IMAGE_ORIENTATION + Fixes #619508 + +2010-06-22 18:53:15 +0100 Tim-Philipp Müller + + * gst/gstobject.c: + * gst/gstobject.h: + gstobject: deprecate gst_object_{set|get}_name_prefix() + The name prefix stuff has never been used for anything and it doesn't + look like we'll ever want to use it for anything. + Fixes #621006. + +2010-06-22 10:20:53 -0300 Johan Dahlin + + * gst/gstpad.h: + Add gobject-introspection annotations for GstPadIntLinkFunction + Fixes build with latest gobject-introspection from git. + https://bugzilla.gnome.org/show_bug.cgi?id=622025 + +2010-06-21 11:41:46 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: fix merging of ranges + When we merge two ranges, don't updata the current range writing_pos with + whereever we were writing earlier in the merged range. Spotted by bilboed. + +2010-06-19 11:19:37 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: also skip .deps dirs when scanning for plugins + No need to descend into .deps dirs in uninstalled setups, we know + these don't contain any plugins. + +2010-06-17 11:39:04 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * win32/common/libgstreamer.def: + taglist: add gst_tag_list_peek_string_index to avoid a copy + Adds a variation of the _get_string_index function that doesn't copy + the string. + API: gst_tag_list_peek_string_index + https://bugzilla.gnome.org/show_bug.cgi?id=621896 + +2010-06-18 12:00:53 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefind: make sure buffers' metadata is writable before setting caps on them + Fixes warnings when using playbin2 with dvb:// streams, where typefind + comes after mpegtsparse. + +2010-06-17 15:52:57 +0100 Tim-Philipp Müller + + * common: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + docs: update introspected plugin docs for gstdoc-scanobj changes + Update common for latest gstdoc-scanobj and inspect xml files for + escaping and pad template order changes. + +2010-06-17 13:19:24 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Initialize jitter to prevent printing an uninitialized variable if waiting for the clock failed + +2010-06-17 10:34:51 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new strings + +2010-06-17 09:33:43 +0100 Tim-Philipp Müller + + * docs/manual/intro-basics.xml: + manual: fix another typo and some inaccuracies + Fix a wrong statement and flesh out section on messages and queries + a bit. + +2010-06-17 09:05:58 +0200 Alexander Saprykin + + * docs/manual/intro-basics.xml: + manual: Fix another typo + +2010-06-17 09:05:28 +0200 Alexander Saprykin + + * docs/manual/intro-basics.xml: + manual: Fix typo + +2010-06-16 13:11:06 -0300 Johan Dahlin + + * gst/gstelementfactory.c: + elementfactory: Add an allow-none annotation + https://bugzilla.gnome.org/show_bug.cgi?id=621773 + +2010-06-16 13:10:26 -0300 Johan Dahlin + + * gst/gstminiobject.h: + miniobject: Add introspection annotations + These are required to know how to unref/ref and + convert to/from a GValue. + https://bugzilla.gnome.org/show_bug.cgi?id=621773 + +2010-06-16 13:10:13 -0300 Johan Dahlin + + * gst/gstevent.c: + event: Add out annotations + https://bugzilla.gnome.org/show_bug.cgi?id=621773 + +2010-06-16 13:10:06 -0300 Johan Dahlin + + * gst/gstquery.c: + query: Add out annotations + https://bugzilla.gnome.org/show_bug.cgi?id=621773 + +2010-06-16 13:09:57 -0300 Johan Dahlin + + * gst/gstmessage.c: + message: Add out annotations + https://bugzilla.gnome.org/show_bug.cgi?id=621773 + +2010-06-16 13:00:30 +0200 Wim Taymans + + * plugins/elements/gstfdsink.c: + fdsink: make sync property work correctly + Don't override the default get_times vmethod so that we can use the sync + property. + Set the default sync property to FALSE. It used to be set to TRUE but because + the get_times was NULL, it always behaved like FALSE. + Fixes #621530 + +2010-06-15 18:48:53 +0200 Benjamin Gaignard + + * gst/gstelement.h: + element: Improve gst_element_get_name() docs + Fixes bug #621660. + +2010-06-15 16:49:04 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 9339ccc to 35617c2 + +2010-06-15 16:53:35 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 5adb1ca to 9339ccc + +2010-06-15 16:34:37 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 57c89b7 to 5adb1ca + +2010-06-15 15:31:12 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From c804988 to 57c89b7 + +2010-06-15 11:48:26 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + Revert "GstPad: Add GST_PAD_NEGOTIABLE GstPadFlag" + This reverts commit dc38e75d88bd8921895821f7afed01cab30e46c9. + boom + +2010-06-15 11:48:17 +0200 Edward Hervey + + * gst/gstpad.c: + * tests/check/gst/gstghostpad.c: + Revert "gstpad: Return pad template in get_caps if pad is not negotiable" + This reverts commit 7460321a600438966d7152ab2b4318be48eadce0. + crack + +2010-06-15 11:48:07 +0200 Edward Hervey + + * gst/gstpad.c: + Revert "pad: fix comment" + This reverts commit 8e92cb4a7d56cdfa4674315c64b58c1b1b9d8208. + whatever... + +2010-06-15 11:47:57 +0200 Edward Hervey + + * gst/gstelement.c: + Revert "element: only clear negotiable when going to NULL" + This reverts commit 8f5ec1f737c3b37538b2307aef160d9d21f1c422. + bleeeeh + +2010-06-15 10:46:08 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + info: add dummy TRACE log level macros for when debugging is disabled + Forgot those when adding the original API, just like the API markers + in the commit message: + API: GST_TRACE + API: GST_TRACE_OBJECT + API: GST_CAT_TRACE + API: GST_CAT_TRACE_OBJECT + API: GST_LEVEL_TRACE + Fixes compilation with --disable-gst-debug + +2010-06-15 01:15:54 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: print more errors to stderr and suppress more output in quiet mode + If --quiet is given, don't print anything but errors. Also, make + sure errors are always printed to stderr and not to stdout. + Fixes #621595. + +2010-06-14 18:07:23 +0200 Wim Taymans + + * gst/gstelement.c: + element: only clear negotiable when going to NULL + Don't clear the negotiable flag when going to READY because then it will never + be set to TRUE again. + +2010-06-14 17:33:16 +0200 Wim Taymans + + * gst/gstpad.c: + pad: fix comment + +2010-05-17 15:06:37 +0200 Edward Hervey + + * gst/gstpad.c: + * tests/check/gst/gstghostpad.c: + gstpad: Return pad template in get_caps if pad is not negotiable + https://bugzilla.gnome.org/show_bug.cgi?id=618644 + +2010-05-17 15:04:48 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpad.h: + * win32/common/libgstreamer.def: + GstPad: Add GST_PAD_NEGOTIABLE GstPadFlag + A pad is 'negotiable' when its container element is in a state greater + than GST_STATE_READY + API:gst_pad_is_negotiable + API:gst_pad_set_negotiable + API:GST_PAD_NEGOTIABLE + https://bugzilla.gnome.org/show_bug.cgi?id=618644 + +2010-06-14 16:51:39 +0200 Wim Taymans + + * plugins/elements/gstfakesink.c: + fakesink: use method to set sync property + Use the basesink method to configure the sync property instead of poking the + parent structure. + +2010-06-14 16:50:41 +0200 Wim Taymans + + * plugins/elements/gstfilesink.c: + filesink: use the default get_times function + Use the default get_times function of basesink so that we honour the sync + property instead of never synchronizing to the clock. + Fixes #621530 + +2010-06-14 16:20:18 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: reevaluate proxy_alloc when reconfigured + When we reconfigure the transform element, make sure we reevaluate the proxying + of buffer_alloc the next time around. + Fixes #621332 + +2010-06-14 15:39:57 +0200 Sebastian Dröge + + * tests/check/gst/capslist.h: + caps: Don't use invalid fraction range in the unit test + +2010-06-14 15:30:08 +0200 Sebastian Dröge + + * gst/gstvalue.c: + gstvalue: Add some more assertions and checks for valid input parameters + +2010-05-27 15:13:18 +0200 Mark Nauwelaerts + + * libs/gst/base/gstadapter.c: + adapter: optimize progressive masked_scan + Retain the last scanned buffer entry and offset, so we can resume buffer + scanning there in case of a typical progressive scan. + Also potentially optimize _copy subsequently occurring in that area. + +2010-05-27 12:15:22 +0200 Mark Nauwelaerts + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * win32/common/libgstbase.def: + adapter: add extended masked_scan_uint32_peek that also provides matching value + Also add to .def and docs. + Fixes #619828. + API: gst_adapter_masked_scan_uint32_peek + +2010-06-14 13:38:41 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: fix .def file + +2010-06-14 12:25:33 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + docs: add Since: tag for new gst_caps_steal_structure + +2010-06-11 15:36:10 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + docs: fix example to use a category name that actually exists + +2010-06-14 11:39:40 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * win32/common/libgstreamer.def: + gstcaps: New gst_caps_steal_structure() method + This allows removing structures from caps without them being freed. Helpful when + plugins need to move around structures without having to do an expensive structure + copy. + API:gst_caps_steal_structure + https://bugzilla.gnome.org/show_bug.cgi?id=621527 + +2010-06-14 13:10:07 +0200 Sebastian Dröge + + * configure.ac: + configure: Don't add G_THREADS_MANDATORY to GST_ALL_CFLAGS + It's already included in GLIB_EXTRA_CFLAGS + +2010-06-14 13:07:33 +0200 Sebastian Dröge + + * configure.ac: + configure: use GLIB_EXTRA_CFLAGS + +2010-06-14 13:02:08 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 7a0fdf5 to c804988 + +2010-06-14 13:01:55 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: fix printf format + +2010-06-14 12:39:47 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: implement custom accept_caps method + Implement a custom acceptcaps function. We can simply check if there is an + intersection with the new caps. This makes the accept caps function much faster. + See #621190 + +2010-06-14 12:36:54 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + basetransform: add accept_caps vmethod + Allow subclasses to override the acceptcaps function because in some cases a + custom implementation can be much much faster than the default one. + See #621190 + +2010-06-14 11:30:20 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6da3bab to 7a0fdf5 + +2010-06-11 18:49:02 -0400 Olivier Crête + + * plugins/elements/gstcapsfilter.c: + capsfilter: Remove transform_size + GstBaseTransform now assumes that the size is the same if there is not + transform_size. + https://bugzilla.gnome.org/show_bug.cgi?id=621334 + +2010-06-11 18:46:30 -0400 Olivier Crête + + * libs/gst/base/gstbasetransform.c: + basetransform: Assume size is the same if no transform_size/get_unit_size + Subclasses that don't implemen transform_size should be assumed to produce output + buffers of the same size. + https://bugzilla.gnome.org/show_bug.cgi?id=621334 + +2010-06-14 08:18:00 +0200 Sebastian Dröge + + * gst/gstvalue.c: + gstvalue: Don't initialize arrays from variables + +2010-06-14 08:11:35 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Store result of strtol in an unused variable to really fix a compiler warning... + +2010-06-13 20:52:36 +0200 Sebastian Dröge + + * gst/gstelement.c: + element: Cast return value to void to prevent compiler warning + +2010-06-13 18:12:47 +0200 Sebastian Dröge + + * tests/examples/streams/rtpool-test.c: + rtpool-test: Prevent NULL pointer dereference + +2010-06-13 18:05:41 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Make sure we have a valid object to render in _render_object() + +2010-06-13 18:00:22 +0200 Sebastian Dröge + + * gst/gstvalue.c: + gstvalue: Add some assertion guards against invalid parameters to public API + +2010-06-13 17:08:48 +0200 Sebastian Dröge + + * gst/gstelement.c: + * libs/gst/base/gstbasesrc.c: + Remove some dead assignments + +2010-06-13 17:06:44 +0200 Sebastian Dröge + + * tests/benchmarks/gstbufferstress.c: + bufferstress: Check if the number of threads and buffers makes sense + +2010-06-13 17:03:53 +0200 Sebastian Dröge + + * tests/examples/metadata/read-metadata.c: + read-metadata: Stop if setting the pipeline state back to NULL fails + +2010-06-13 16:59:40 +0200 Sebastian Dröge + + * tests/benchmarks/complexity.c: + complexity: Remove dead assignments and unused variables + +2010-06-13 16:31:21 +0200 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Don't ignore failure to open the temporary file location + And immediately leave the state change function on failures. + +2010-06-13 16:27:39 +0200 Sebastian Dröge + + * gst/gstpad.c: + pad: Fix iterator aggregation of all pads in the internal links fallback + g_list_prepend() returns the new head of the list and not + using this will create a memory leak and a single-element list. + +2010-06-13 15:25:24 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Add new FIXME for 0.11 and update gst_iterator_find_custom docs + The compare function should only unref the element if it's + not the matching element. + Also the FIXME in _fold() is not relevant because the ref/unref + happens in the fold function. + +2010-06-13 11:24:10 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: If the iterator resync in find_custom() just retry + +2010-06-12 08:25:24 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 733fca9 to 6da3bab + +2010-06-12 08:04:47 +0200 Sebastian Dröge + + * tests/check/gst/gstvalue.c: + value: Add test for deserializing fourccs + +2010-06-11 22:56:13 +0000 Martin Bisson + + * gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + value: Fixed serialization for short fourccs. + "Y16 " and "Y8 " were not displayed properly because the space + character is not alnum. A unit test is also included. + Fixes bug #621282. + +2010-06-11 16:12:33 -0700 David Schleef + + * tools/gst-inspect.c: + gst-inspect: print ranks with offsets from names + +2010-06-09 12:39:54 -0700 David Schleef + + * common: + Automatic update of common submodule + From fad145b to 733fca9 + +2010-06-09 12:30:49 -0700 David Schleef + + * common: + Automatic update of common submodule + From 47683c1 to fad145b + +2010-06-09 12:17:03 +0300 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: fix comment typo even more + +2010-06-09 12:06:52 +0300 Stefan Kost + + * gst/gstregistry.c: + docs: update docs (format and search path). + Remove obsolete xml registry cache extension. Tell that content and location is + internal detail. Docuemnt the plugin search order. + +2010-06-09 12:06:16 +0300 Stefan Kost + + * gst/gstpluginloader.c: + comments: add a few comments to the sparsely documented plugin loader + +2010-06-08 11:41:11 +0200 Zaheer Abbas Merali + + * gst/gstdebugutils.c: + debugutils: fix comment typo + +2010-06-08 12:12:42 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: use gst_caps_append_structure_unchecked() macro once more + +2010-06-08 12:10:36 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: use a safer name for temporary var. to not shadow one from outer scope + +2010-06-07 12:20:41 +0300 Stefan Kost + + * gst/gstvalue.c: + value: use glib types in more places + Do a bunch of char -> gchar, int -> gint, double -> gdouble changes. + +2010-06-07 12:07:30 +0300 Stefan Kost + + * gst/gstvalue.c: + value: just compute strlen() once + +2010-06-07 10:16:04 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: don't wait for data when EOS + When in download mode and we need to provide data for an offset that we don't + have, also perform a seek to the requested location when we are EOS. The reason + why we shouldn't wait for more data is because after EOS, there simply will be + no more data and we end up waiting forever. + Fixes #620500 + +2010-06-07 08:18:40 +0200 Martin Bisson + + * gst/gstvalue.c: + value: Add support for parsing short fourccs from strings + For example "Y16 " and "Y8 ". + +2010-06-06 23:19:58 +0300 Stefan Kost + + * libs/gst/check/gstcheck.c: + check: use globbing for selective test invocation via GST_CHECKS + Use glib globbing instead of simple string matching to allow e.g. + GST_CHECKS="test_inter*" make gst/gstcaps.check + +2010-06-06 21:20:21 +0300 Stefan Kost + + * tests/benchmarks/capsnego.c: + capsnego: also meassure pipeline building time + +2010-06-05 23:18:09 +0300 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + basetransform: avoid a caps-copy + We can simply truncate the caps, as 'othercaps' is the result of intersect + operations and thus ours and writable. + +2010-06-03 01:49:51 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstminiobject.c: + * gst/gstobject.c: + info: add new TRACE log level and move refcounting there from LOG level + This makes it possible to easily get a *:5 debug log without all + the refcounting noise, and drastically reduces the number of lines + output for a normal log (46m to 28m for a 20min video). The full log + including refcounting information can still be gotten using *:7. + Fixes #620460. + +2010-06-04 17:10:05 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Use G_PARAM_STATIC_STRINGS for standard properties + +2010-06-03 17:21:00 +0200 Philippe Normand + + * libs/gst/base/gstbasesink.c: + basesink: Make gst_base_sink_query return TRUE if the segment query succeeded. + Fixes bug #620490. + +2010-06-01 23:48:59 -0700 David Schleef + + * common: + Automatic update of common submodule + From 17f89e5 to 47683c1 + +2010-06-01 22:54:20 -0700 David Schleef + + * common: + Automatic update of common submodule + From fd7ca04 to 17f89e5 + +2010-05-24 17:25:52 +0300 Stefan Kost + + * gst/gstpad.c: + pads: Improve readability for gst_pad_fixate_caps() + Just truncate and then fixate. We check for empty caps in the begin and a + fixate-func that empties a caps would be broken. It also helps lazy caps impl. + in bug 618853 by avoiding the gst_caps_get_size(). + +2010-06-01 11:46:17 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + check: log plugins available to unit tests and their paths + +2010-06-01 11:45:11 +0100 Tim-Philipp Müller + + * Makefile.am: + win32: commit Makefile changes for win32-update as well + +2010-05-31 15:14:53 +0100 Tim-Philipp Müller + + * win32/common/gstmarshal.c: + * win32/common/gstmarshal.h: + win32: add pre-generated versions of gstmarshal.[ch] as well + and put them next to the pre-generated enumtypes files for those + not using autotools for buildling GStreamer. + +2010-05-27 15:10:34 +0200 Mark Nauwelaerts + + * tests/check/libs/adapter.c: + tests: also check for adapter buffer merging in unit test + +2010-05-27 12:50:22 +0200 Mark Nauwelaerts + + * libs/gst/base/gstadapter.c: + adapter: fix _try_to_merge_up + That is, provide correct return value (as documented), and actually + loop to consider more than the first 2 buffers. + +2010-05-27 12:48:18 +0200 Mark Nauwelaerts + + * libs/gst/base/gstcollectpads.c: + collectpads: fix documentation glitch + +2010-05-26 11:54:35 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 357b0db to fd7ca04 + +2010-05-25 19:17:44 +0200 Wim Taymans + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + gstbin: unlock _get_state() on error + When an error message is received on the bus, mark the bin as being in the error + state and unlock all current _get_state() calls with an error. + Fixes #505770 + +2010-05-24 19:07:35 +0100 Tim-Philipp Müller + + * tests/check/gst/gsttagsetter.c: + checks: add multi-thread test for tagsetter + See #619533. + +2010-05-24 19:06:45 +0100 Tim-Philipp Müller + + * gst/gsttagsetter.c: + tagsetter: make sure only one thread creates the TagData + +2010-05-24 18:16:19 +0100 Tim-Philipp Müller + + * gst/gsttagsetter.c: + tagsetter: protect tagsetter operations with a lock + So we don't crash when a muxer tries to add tags from two + threads at the same time, eg. because it received tag events + on two input pads simultaneously. + See #619533. + +2010-05-22 23:26:16 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: use our macros more often in the code + +2010-05-22 23:07:10 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: add append_structure_unchecked + This is useful when we know that caps is !NULL, writable and structure is + !NULL too. + +2010-05-22 22:46:40 +0300 Stefan Kost + + * tests/check/gst/gstcaps.c: + tests: rename testsuite + Previous name was only applicable to a few of the tests. + +2010-05-22 22:45:33 +0300 Stefan Kost + + * gst/gstpad.c: + docs: xref function name + +2010-05-22 22:44:02 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: use our macos more + +2010-05-22 22:33:09 +0300 Stefan Kost + + * docs/random/ensonic/lazycaps.txt: + design: more planning on lazy caps. + +2010-05-22 10:01:44 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: API: Add gst_structure_fixate_field_string() + +2010-05-19 16:21:49 +0300 Stefan Kost + + * docs/random/ensonic/lazycaps.txt: + design: collect ideas for having lazy caps + Design doc for having on the fly evaluated caps (see bug #618853). + +2010-05-19 15:57:08 +0300 Stefan Kost + + * gst/gstbus.c: + docs: add links for GSource priorities + Now it is xreffed with the glib docs, where the priority scale is explained. + +2010-05-19 14:08:26 +0300 Stefan Kost + + * tests/benchmarks/capsnego.c: + benchmark: add commandline parameters for capsnego + Allow to specify the graph size and offer two flavours (audio/video). + +2010-05-19 09:56:51 +0300 Stefan Kost + + * tests/benchmarks/.gitignore: + * tests/benchmarks/Makefile.am: + * tests/benchmarks/capsnego.c: + benchmarks: add a benchmark for capsnegotiation + The test builds a tree like graph having conversion and basetransform elements. + +2010-05-18 17:51:01 +0300 Stefan Kost + + * tests/benchmarks/caps.c: + * tests/benchmarks/complexity.c: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/mass-elements.c: + benchmarks: use gst_util_get_timestamp() instead of own implementation + +2010-05-18 18:38:14 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add jitter to debug output + +2010-05-18 18:35:58 +0200 Wim Taymans + + * gst/gstminiobject.c: + miniobject: cleanup type registration a little + We can make some structs const static with little effort. + +2010-05-17 13:09:15 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + pad: don't print WARNING debug statements for normal things like EOS, part II + +2010-05-14 18:22:41 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 4d67bd6 to 357b0db + +2010-05-14 11:52:03 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: comment and whitespace cleanup + Make comment more specific, reposition it and add more of the kind. + Move one ifdef'ed function around. + +2010-05-13 08:21:37 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Simplify fractions before doing calculations that could cause overflows + ... to prevent some unnecessary overflows from happenening. + +2010-05-13 08:00:08 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: GCD is 0 if both parameters are 0, don't divide by zero + And turn overflow checks from assertions into simple checks to + return FALSE. + +2010-05-13 07:51:14 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Simplify result of gst_fraction_multiply() + +2010-05-10 13:25:04 -0400 Tristan Matthews + + * docs/faq/using.xml: + faq: updated line about jack output + +2010-05-03 11:32:20 +0200 Edward Hervey + + * tests/check/libs/bytereader.c: + tests: Read return value to make clang/icc happy + +2010-05-06 16:41:09 +0200 Wim Taymans + + * gst/gstpad.c: + Revert "pad: don't check twice for changed caps per push" + We need to check the pad caps on the srcpad as well as on the sinkpad. Revert + this commit as it removes the check on the srcpad and can leave the srcpad + unnegotiated (or negotiated with wrong caps) + This reverts commit 07dc1e5b49580a89bfef27ff27476d51fb3ce2c2. + +2010-05-06 17:02:49 +0300 Stefan Kost + + * gst/gstpad.c: + pad: don't check twice for changed caps per push + gst_pad_chain_data_unchecked() does the same check already. + +2010-05-06 16:51:16 +0300 Stefan Kost + + * libs/gst/base/gstbasesrc.c: + basesrc: reflow to truncate caps just once + We get writable caps from the intersection (unless it failed). As we truncate + those anyway, we don't need to manualy copy the first structure. + +2010-05-04 13:29:02 +0400 Руслан Ижбулатов + + * tools/gst-run.c: + tools: fix gst-run wrapper to work on Windows + Fixes #617625 + +2010-05-03 00:26:04 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + docs: document that gst_byte_writer_put_string*() writes the terminator too + +2010-05-05 12:01:50 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * libs/gst/base/gstbasesrc.h: + docs: clarify the pull_range functions + Clarify the gst_pad_pull_range(), GstBaseSrc::create(), gst_pad_get_range() + and GstPadGetRange functions a little. + Fixes #617733 + +2010-05-04 11:45:02 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: improve debugging + +2010-04-30 11:27:12 +0200 Wim Taymans + + * gst/gstutils.c: + utils: use reffed _get_caps() version + We don't need to have a writable copy so we can use the _reffed + version instead. + +2010-04-29 21:57:15 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: Adds geo location direction tags + Adds 3 new geo location tags involving direction and + movement of capture. Those are: + API: GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION + API: GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION + API: GST_TAG_GEO_LOCATION_MOVEMENT_SPEED + Fixes #617223 + +2010-04-16 06:57:05 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: Adds GST_TAG_DEVICE_MANUFACTURER and GST_TAG_DEVICE_MODEL + Adds those new tags to describe the device manufacturer and + model used to create medias. + API: GST_TAG_DEVICE_MANUFACTURER + API: GST_TAG_DEVICE_MODEL + Fixes #615941 + +2010-05-02 19:43:55 +0100 Tim-Philipp Müller + + * docs/pwg/advanced-tagging.xml: + pwg: remove confusing metadata example with 0.8 code + Fixes #534314. + +2010-05-02 19:30:30 +0100 Tim-Philipp Müller + + * docs/manual/advanced-metadata.xml: + manual: add minimal tag reading example + Should probably put that into tests/examples and figure out how to + get it included automatically, but can't be bothered right now. + +2010-04-30 13:10:16 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/gst.c: + Bump GLib requirement to 2.20 + See http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement + +2010-04-29 23:29:30 +0100 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: only warn if metadata is not writable when it should be, don't return as well + Make sure we execute the same code path in git versions and in releases, + so just warn when metadata isn't writable when we want it to be instead + of bailing out. + +2010-04-29 23:26:54 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + element: make 'adding flushing pad' warning more useful + This is a pretty common issue with ghost pads, let's make + the warning more helpful and tell people what they need + to do to fix it. + +2010-04-28 17:15:41 +0300 Stefan Kost + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + gst-launch: add -p option to disable play handler. + Same logic as for the fault handler. This is useful for some debug/tracing tools + that need to grab SIGUSR1 and SIGUSR2 them self. + +2010-04-15 10:36:52 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: implement percentage position and duration queries + If upstream does not handle them, then implement those ourself. + +2010-04-14 17:47:36 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: use gst_pad_peer_query instead of reinventing. + +2010-04-14 17:46:55 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + queries: add more logging + Log human readable formats and log query result. + +2010-04-19 20:35:36 +0200 Benjamin Otte + + * gst/gstpad.c: + caps: Do not allow fixating empty caps + Passing empty caps to gst_pad_fixate_caps() is invalid, as empty caps + cannot be fixated. + +2010-04-26 21:52:07 +0200 Benjamin Otte + + * gst/gstcaps.h: + caps: Use G_GNUC_WARN_UNUSED_RESULT for make_writable() + People often call + gst_caps_make_writable (caps); + instead of + caps = gst_caps_make_writable (caps); + and cause a bug. Warning about an unused return value helps here. + See https://bugzilla.gnome.org/show_bug.cgi?id=616541#c2 for an example. + +2010-04-23 06:24:56 +0200 Sebastian Dröge + + * gst/gsterror.c: + gst: Use GError boxed type from GObject 2.25.2 instead of our own if possible + +2010-04-29 14:50:36 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development. + +2010-04-15 17:11:46 +0200 Wim Taymans + + * gst/gstevent.h: + docs: add some more docs for the events + +=== release 0.10.29 === + +2010-04-27 23:42:12 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.29 + +2010-04-27 23:40:41 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2010-04-27 09:42:05 +0300 Stefan Kost + + * tests/check/libs/controller.c: + tests: add more tests for controller + The tests verify that bug #616846 is indeed fixed. + +2010-04-26 15:43:17 +0200 Benjamin Otte + + * libs/gst/controller/gstinterpolation.c: + controller: Fix gst_interpolation_control_source_find_control_point_iter + The logic in that function is broken. Various NULL-checking bandaids for + guaranteed non-NULL variables didn't even help there. + This patch updates the function to check if a previous item exists + before fetching it instead of after. This makes all other tests + unnecessary. + In particular, it makes the check for an empty list unnecessary, because + for empty lists the only iter is the begin iter (and the end iter) and + so the new check catches that case. + https://bugzilla.gnome.org/show_bug.cgi?id=616846 + +2010-04-25 21:15:51 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + 0.10.28.3 pre-release + +2010-04-20 17:17:38 +0100 Tim-Philipp Müller + + * gstreamer.doap: + doap: update repository info from cvs->git and maintainers + +2010-04-23 14:39:20 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From fc85867 to 4d67bd6 + +2010-04-16 20:09:40 +0200 Sebastian Dröge + + * docs/pwg/building-boiler.xml: + * docs/pwg/pwg.xml: + docs: Consistently use MyFilter instead of sometimes ExampleFilter in the example + Fixes bug #615579. + +2010-04-16 14:22:18 +0100 Tim-Philipp Müller + + * gst/gstpad.h: + pad: add enums for custom flow return success and error codes + This way people can just #define their own custom flow returns to + one of these without having the compiler (esp. gcc-4.5) complain + about comparing integers to an enum or the enum not being listed + Fixes #615880. + API: GST_FLOW_CUSTOM_SUCCESS_1 + API: GST_FLOW_CUSTOM_SUCCESS_2 + API: GST_FLOW_CUSTOM_ERROR_1 + API: GST_FLOW_CUSTOM_ERROR_2 + +2010-04-15 22:05:38 +0200 Sebastian Dröge + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: Use correct setter for double GValues + +2010-04-15 11:08:03 -0300 Thiago Santos + + * gst/gsttaglist.h: + tags: doc fixes + Adds missing ':' to tags docs + +2010-04-15 11:38:19 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + bin: fix bogus variable type + The result of gst_iterator_find_custom() is not a GstIterator *. + +2010-04-14 12:20:13 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + 0.10.28.2 pre-release + +2010-04-14 12:12:56 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2010-04-14 12:43:41 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + structure: log what structure string we failed to parse + +2010-04-14 17:56:17 +0200 Wim Taymans + + * gst/gstbin.c: + * tests/check/gst/gstbin.c: + bin: fix refcount when removing elements during state change + When an element is removed from a bin because it caused a state change error, + don't unref the child twice. + Add some more debug info. + Add a unit test for this error. + Fixes #615756 + +2010-04-14 11:50:38 +0100 Tim-Philipp Müller + + * tests/benchmarks/Makefile.am: + * tests/examples/controller/Makefile.am: + tests: more LDFLAGS -> LDADD fixes + +2010-04-14 11:40:21 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + build: $(LIBM) belongs into LIBADD not LDFLAGS + +2010-04-08 09:14:24 +0100 Tim-Philipp Müller + + * libs/gst/helpers/Makefile.am: + * tools/Makefile.am: + build: when building executables, put libs to link to into LDADD instead of LDFLAGS + 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. See #615697. + +2010-04-14 11:19:14 +0200 Benjamin Otte + + * configure.ac: + configure: Remove -Wcast-align + 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. + https://bugzilla.gnome.org/show_bug.cgi?id=615698 + +2010-04-13 10:48:41 +0100 Tim-Philipp Müller + + * configure.ac: + configure: remove superfluous return statements at end of AC_TRY_{LINK,COMPILE} blocks + Spotted by JF Mertens. See #614767. + +2010-04-05 13:46:23 -0700 David Schleef + + * configure.ac: + configure: Change check for uint128_t + Check for ability to divide uint128_t values, since that what + we actually use it for (in gstutils.c). The existence of a + uint128_t type doesn't mean the compiler can actually generate + code for it. Also make sure that we can actually link the + result successfully. + Fixes bug #614767. + +2010-04-12 15:13:57 +0100 Tim-Philipp Müller + + * docs/random/moving-plugins: + docs: minor moving-plugins addition + +2010-04-09 15:48:00 +0200 Wim Taymans + + * tools/gst-launch.c: + launch: make -q be more quiet + Convert some g_print into PRINT so that they are not printed when the -q option + is selected. + +2010-04-09 15:19:12 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add some more debug info + +2010-04-09 13:12:38 +0200 Wim Taymans + + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfdsrc.h: + fdsrc: allow specifying the size in bytes on the uri + Parse a size=value from the query string to specify a size. This is interesting + when reading from a file descriptor that actually has a size (and is not + stat-able, such as the socket of an http connection) + +2010-04-09 12:35:47 +0200 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: when EOS we know the duration + When we are EOS, we don't need to do an upstream query for the duration in bytes + because we already know it is the offset of the last written byte. + +2010-04-09 13:08:13 +0200 Sebastian Dröge + + * gst/gstregistrychunks.c: + registrychunks: Initialize typefind/element factory registry chunks with zeroes + This makes valgrind stop complaining about reading unitializated memory, + which is not initialized because it's just compiler-added struct padding... + +2010-04-09 11:19:53 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From d66a8c3 to fc85867 + +2010-04-08 10:10:18 +0100 Tim-Philipp Müller + + * docs/gst/.gitignore: + .gitignore: add new .svg file in docs + +2010-04-08 10:47:03 +0300 Stefan Kost + + * gst/gstbufferlist.c: + docs: use informalfigure tag to not syntax highlight the content + +2010-03-25 10:35:13 +0200 Stefan Kost + + * docs/gst/Makefile.am: + * docs/gst/gst-universe.dot: + * docs/gst/gstreamer-docs.sgml: + docs: add concept map + Add a graphviz dot file. Add rules to render it to svg and include in docs. + Nodes are clickable. It is an attempt to show how things fit together. + +2010-04-07 19:30:49 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + docs: add a few code snippets that show how to use gst_message_parse_*(). + +2010-04-07 19:05:04 +0100 Tim-Philipp Müller + + * 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 12:29:52 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: fix more compiler warnings + Fix 'grammar.tab.c:815:6: warning: "YYENABLE_NLS" is not defined' + compiler warning and the same for YYLTYPE_IS_TRIVIAL. The two + translated strings aren't particularly helpful, so just define + YYENABLE_NLS to 0. + +2010-04-07 12:24:14 +0100 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse: fix compiler warning + Fix 'grammar.y:668: passing argument 1 of ‘g_free’ discards qualifiers + from pointer target type' compiler warning. + +2010-04-07 16:05:38 +0200 Wim Taymans + + * gst/gstmessage.h: + message: add Since: markers + +2010-04-07 09:31:39 +0200 Edward Hervey + + * tests/check/gst/gstsystemclock.c: + tests: gstsystemclock: don't leak the system clock + +2010-04-05 00:01:56 +0300 Stefan Kost + + * libs/gst/check/Makefile.am: + build: fix out of sourcedir build for check + Move the internal header to nodist (as we copy it around anyway). + Use builddir in pattern substitution for it. + Fixes #61483. + +2010-04-06 17:46:36 +0200 Wim Taymans + + * gst/gstevent.c: + docs: fix some typos + +2010-02-23 09:16:55 +0100 Jonas Holmberg + + * libs/gst/base/gstbasesrc.c: + basesrc: fix gst_base_src_new_seamless_segment() + Keep track of pending newsegment in gst_base_src_new_seamless_segment() + to avoid pushing newsegment update before newsegment. + +2010-04-04 15:21:16 +0300 Stefan Kost + + * gst/gstevent.c: + docs: improve event docs + Rephrase first paragraph of section docs. Add detail to eos event docs. + +2010-03-29 08:43:05 +0200 Edward Hervey + + * tools/gst-indent: + gst-indent: Add --leave-preprocessor-space for indent 2.2.11 + It was previously broken, which is why we never needed it. This keeps backward + compatibility with indent <= 2.2.11 + +2010-03-31 10:43:04 +0100 Tim-Philipp Müller + + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/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 + Based on patches by Vincent Untz and Alan Knowles. + Fixes #603710. + +2010-04-02 01:16:16 +0100 Philip Withnall + + * gst/gstutils.h: + utils: Use G_GNUC_CONST instead of G_GNUC_PURE for conversion functions + Fixes bug #614629. + +2010-04-01 13:19:06 +0200 Edward Hervey + + * tests/check/libs/basesrc.c: + tests: Don't forget to unref the newsegment event + +2010-04-01 12:34:53 +0200 Edward Hervey + + * common: + common: Update to latest revision for new suppressions + +2010-03-31 22:07:57 +0300 Stefan Kost + + * tests/check/libs/basesrc.c: + tests: add test for updating playback rate + Tests if a seek with both positions being GST_SEEK_TYPE_NONE is handled. + +2010-03-31 16:55:55 +0200 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: add copy and conv function to buffer2 draft + +2010-03-31 10:54:55 +0200 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: update buffer2 draft + +2010-03-31 11:26:28 +0300 Stefan Kost + + * docs/manual/communication.png: + * docs/manual/diagrams-general.svg: + * docs/manual/intro-basics.xml: + docs: improve communication picture and section + Indicate that only messages go via bus. Also add queries between elements. + +2010-03-31 10:24:11 +0200 Sebastian Dröge + + * gst/gstutils.h: + event: Use correct type for the message parameter in gst_event_{new,parse}_sink_message + The struct workaround was only necessary in gstevent.h, gstutils.h knows about GstMessage + +2010-03-31 09:56:50 +0300 Stefan Kost + + * docs/manual/communication.png: + * docs/manual/diagrams-general.svg: + * docs/manual/intro-basics.xml: + docs: add communication overview to docs + Add a section to the basics that show buffers, events, messages and queries + together and describe the basics. + +2010-03-30 15:56:39 +0100 Tim-Philipp Müller + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-base.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-controller.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-net.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + pkgconfig: add girdir and typelibdir variables to .pc files + So that the -base libs can figure out the right include paths for the + gobject-introspection tools even if core got installed into a prefix + that's not the same prefix as gobject-introspection is installed in + or it's being build in an uninstalled gstreamer setup. + +2010-03-30 15:22:54 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new string + +2010-03-30 15:20:07 +0100 Tim-Philipp Müller + + * Makefile.am: + * autogen.sh: + * configure.ac: + * m4/.gitignore: + * m4/Makefile.am: + * m4/check-checks.m4: + build: make autotools put its m4 files into m4/ instead of common/m4/ + This is how we do it in the other modules, and gets rid of the annoying + dirty status for common when doing git status (at least once you clean + out the old files from there). + +2010-03-30 12:33:01 +0100 Tim-Philipp Müller + + * common: + * tests/examples/Makefile.am: + build: build examples subdirectories in parallel if requested + +2010-03-28 20:55:09 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: Refactor caps suggestion on pad_alloc + Refactor the handling of sink suggestion caps variable + so that it always has a ref to the caps it points to. + Makes the code clearer. + +2010-03-29 16:34:03 +0300 Stefan Kost + + * gst/gstinfo.h: + gstinfo: add a comment explaining the reason for using fucntion protos here. + +2010-03-29 16:13:54 +0300 Stefan Kost + + * gst/gstinfo.h: + gstinfo: always define dummy debug category as a function prototype + It does not seem to make sense to define this as a function only if we have + varargs macros. + +2010-03-28 15:10:20 +0300 Stefan Kost + + * gst/gstinfo.h: + build: fix redeclaration erors when building with --gst-disable-gst-debug + Give dummy symbols a uniqe name. + +2010-03-28 14:49:03 +0300 Stefan Kost + + * gst/gstinfo.h: + build: move some prototypes out of #ifndef GST_DISABLE_GST_DEBUG + Move the prototypes up together. We only define the macros differently. + Fixes bug #614167 mostly. + +2010-03-29 16:05:44 +0300 Stefan Kost + + * gst/gstinfo.c: + * gst/gstinfo.h: + info: readd the use of GstDebugFuncPtr typedef and tell why + This reverts the related changes from 3f4954e42d0440a7a598a908325c45ea9db076e4 + and ffb0a4e1905a873191f8c802346261e8c4435065. + +2010-03-29 10:22:43 +0100 Alan Knowles + + * libs/gst/net/gstnetclientclock.h: + net: fix typo in net client clock structure + It's sockaddr_in, not sockaddr_id. + +2010-03-26 17:12:05 +0000 Tim-Philipp Müller + + * Makefile.am: + build: add cruft alert for common/shave* + +2010-03-28 21:02:41 +0200 Sebastian Dröge + + * gst/gstinfo.c: + info: Fix build at least until the correct fix is found + See bug #614167. + +2010-03-28 19:13:22 +0200 Sebastian Dröge + + * gst/gststructure.c: + structure: Make structure abbreviations array one-time initialization threadsafe + +2010-03-28 18:05:36 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Add FIXME 0.11 for using GSlice for allocation + +2010-03-28 18:05:36 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstformat.c: + * gst/gstindex.c: + * gst/gstinfo.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstplugin.c: + * gst/gstpluginloader.c: + * gst/gstquery.c: + * gst/gstregistrybinary.c: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttrace.c: + gst: Use GSlice instead of normal g_malloc in more places + +2010-03-28 13:14:06 +0300 Stefan Kost + + * gst/gstdebugutils.h: + * gst/gstinfo.h: + build: more some prototypes out if #ifndef GST_DISABLE_GST_DEBUG + The build was failing becasue of a new warning. There are still failures + (tracked via bug #614167). + +2010-03-25 20:04:37 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations for newly-added strings + +2010-03-25 19:56:00 +0000 Tim-Philipp Müller + + * docs/manuals.mak: + docs: fix intermittent make distcheck failures + Use .NOTPARALLEL when building docs. This avoids intermittent + make distcheck failures like 'cp: cannot create regular file + `build/image.entities': File exists' when using -jN. + Fixes #590718. + +2010-03-25 18:57:40 +0100 Sebastian Dröge + + * gst/gstelementfactory.h: + elementfactory: Add FIXME 0.11 to remove GstElementDetails from the public API + It's not necessary anymore to expose this as public API and this allows + easier extension of the element details by new fields. + +2010-03-25 18:43:04 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: handle write errors + Handle write errors to the temporary download file and post errors when + something went wrong. + +2010-03-25 18:13:02 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add element query function + Add an element query function that is a little more efficient than the generic + default query handler. + +2010-03-25 18:12:06 +0100 Wim Taymans + + * gst/gstbin.c: + bin: improve docs a little + Mention that a DURATION message does not mean that one can safely query the + duration on a bin, that only works when the bin is prerolled. + +2010-03-25 18:05:28 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: remove fixed FIXME + +2010-03-25 17:36:45 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: add the buffering percent in BUFFERING query + +2010-03-25 17:21:02 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: improve buffer level measurement in download mode + Keep track of the current buffer level in the current range in download mode so + that we post the correct buffering messages. + +2010-03-25 15:54:19 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + libs: don't use fancy shell features when invoking gobject-introspection scanner + It's POSIX, but tcsh doesn't seem to support it. + +2010-03-25 13:46:35 +0000 Tim-Philipp Müller + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + libs: fix PKG_CONFIG_PATH used when calling gobject-introspection scanner + Our own pkgconfig directory should come first, so that pkg-config uses + the in-tree libgstreamer and not some external one when --pkg=gstreamer-0.10 + is passed to g-ir-scanner. + See #603710. + +2010-03-25 10:27:00 +0100 Edward Hervey + + * libs/gst/base/gstadapter.c: + GstAdapter: add a unchecked variant of flush for internal usage + Trims off 10-20% cpu time when using gst_adapter_take[_buffer] + +2010-03-19 15:10:07 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: Add new _USER_RATING tag + Adds a new tag for user favorite media rating. + User rating informs how much (from 0 to 100) a user + 'likes' a media. + Having an percent uint range for this is easy to map into other scales, + like some players that allow users to attribute 'stars' to its + media. + API: GST_TAG_USER_RATING + Fixes #520697 + +2010-03-24 19:02:12 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add more info in the buffering query + Add the estimated download time and estimated time left to the buffering query + results along with the estimated download and playback speed. + +2010-03-24 18:18:13 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: implement flushing in download buffering + Maintain a separate variable to control src and sink flowreturn values so that + we can unlock the src part without shutting down the sink part. + Add flushing for upstream pull based elements that unblocks our getrange + function. This implements seeking when blocking for more data. + Add some arbitrary threshold before attempting a seek. Add a FIXME for this + because we need to find a sensible threshold based on the input rate. + +2010-03-24 18:50:02 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 55cd514 to c1d07dd + +2010-03-24 17:32:54 +0100 Benjamin Otte + + * configure.ac: + Remove unused code + OPT_CFLAGS was never AC_SUBST()'ed so it wasn't used. And the last time + it was touched was in 2005. + +2010-03-24 15:47:22 +0000 Tim-Philipp Müller + + * gst/parse/Makefile.am: + build: fix make distcheck + The change from GST_ALL_CFLAGS to GST_OPTION_CFLAGS dropped the includes, + putting them back fixes make distcheck. + +2010-03-24 15:15:23 +0100 Benjamin Otte + + * tests/check/pipelines/parse-launch.c: + Fix tests after set_element_details() deprecation + +2010-03-24 13:33:58 +0100 Robert Swain + + * scripts/git-update.sh: + git-update: Fix and restructure logic + +2010-03-19 22:36:07 +0100 Benjamin Otte + + * gst/gstelement.c: + * gst/gstelement.h: + Deprecated gst_element_class_set_details() + Use gst_element_class_set_details_simple() instead. If you want to + convert automatically, here's a script: + for file in `git grep -l GstElementDetails`; do + sed -i -n -r ' + 1h + 1!H + $ { + g + s/((\/\*[^\n]*\*\/)?\n)*[^\n]*GstElementDetails .* =\s*GST_ELEMENT_DETAILS\s*\((\"[^\"]*\",\s*\"[^\"]*\",\s*\"[^\"]*\",\s*(\"[^\"]*\"\s*)*)\);\n*(.*)gst_element_class_set_details \(([^,]*),\s*[^)]*\)/\n\n\5gst_element_class_set_details_simple (\6, \3)/ + s/((\/\*[^\n]*\*\/)?\n)*[^\n]*GstElementDetails .* =\s*\{\s*(\"[^\"]*\",\s*\"[^\"]*\",\s*\"[^\"]*\",\s*(\"[^\"]*\"\s*)*)\};\n*(.*)gst_element_class_set_details \(([^,]*),\s*[^)]*\)/\n\n\5gst_element_class_set_details_simple (\6, \3)/ + p + }' $file + ~/gst/gstreamer/tools/gst-indent $file + done + +2010-03-24 10:57:08 +0100 Philippe Normand + + * plugins/elements/gstqueue2.c: + queue2: Fix uninitialized variable compiler warning + +2010-03-23 19:25:08 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: remove unused CHECK_CFLAGS and CHECK_LIBS from Makefile.am + +2010-03-23 19:23:22 +0000 Tim-Philipp Müller + + * gst/gststructure.c: + * tests/check/gst/gststructure.c: + structure: add mapping for (uint) to allow deserialisation of unsigned integers + Unsigned ints are used in taglists, would be nice to be able to + deserialise them, esp. in connection with the taginject API. + +2010-03-23 19:25:29 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: implement seeking in download mode + When in download mode and the requested offset is too far away, attempt to do a + seek request to fetch the data. + Keep track of all downloaded parts and merge ranges when needed. + Fixes #600877 + +2010-03-22 11:06:21 -0300 André Dieb Martins + + * scripts/git-update.sh: + git-update.sh: use autogen.sh instead of autoregen.sh on fresh repositories. + Fixes #613593. + +2010-03-22 17:10:06 +0200 Stefan Kost + + * gst/gettext.h: + gettext: build fixes: #if -> #ifdef + +2010-03-22 13:16:33 +0100 Benjamin Otte + + * plugins/elements/gstdataurisrc.c: + Add -Wwrite-strings + and fix its warnings + +2010-03-18 10:22:09 +0200 Stefan Kost + + * gst/gstbin.c: + * gst/parse/grammar.y: + parse-launch: make delayed set recursive + Right now deleyed set would only try for first set of children. We need to keep + trying to support arbitrary deep hierarchies (like in playbin2 with auto*sinks). + Also GstBin would need to actualy emit the child-added/removed signal as it + implements the iface. Fixes #613215. + +2010-03-22 08:40:34 +0100 Sebastian Dröge + + * pkgconfig/gstreamer-check.pc.in: + pkgconfig: Use @LIBM@ instead of -lm + +2010-03-19 01:02:30 +0000 Tim-Philipp Müller + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + pkgconfig: add back support for builddir != srcdir case in uninstalled setup + Attempt to add back support for builddir != srcdir. Use absolute paths + instead of relative paths based on pcfiledir this time to make things + clearer - there's not really any need for uninstalled trees to be + relocatable without re-running configure. + +2010-03-18 11:18:39 +0000 Robert Swain + + * libs/gst/base/gstbasetransform.c: + basetransform: Implement QoS message posting + And some more for bug #322947 + +2010-03-18 13:41:35 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: catch, parse and store QoS event values + Catch, parse and store the QoS values from QoS events for later use. + +2010-03-17 15:29:48 +0000 Robert Swain + + * libs/gst/base/gstbasesink.c: + basesink: Implement QoS message posting in basesink + Post QoS messages when frames are dropped. + This goes a little further towards resolving bug #322947 + +2010-03-17 19:26:30 +0100 Wim Taymans + + * gst/gstmessage.c: + message: improve docs a little + +2010-03-17 19:16:42 +0100 Robert Swain + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * tests/check/gst/gstmessage.c: + * win32/common/libgstreamer.def: + message: add QoS message to inform apps of lost data + This has been implemented as per part-qos.txt and partially addresses + bug #322947 + +2010-03-17 16:44:05 +0100 Benjamin Otte + + * tests/benchmarks/controller.c: + test: Remove needless cast + GstValueArray.name is const now + +2010-03-17 14:33:35 +0000 Tim-Philipp Müller + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + Revert "Add srcdir to includes for out-of-source builds" + I don't know how this ever worked, as it seems to put -I./.. + and -I./../libs verbatim into the includes, at least with + current autotools versions. + This reverts commit 279a80ff27ba4c90f52981e89e710eb1181bc201. + +2010-03-17 15:46:46 +0100 Wim Taymans + + * docs/design/part-qos.txt: + docs: avoid confusion between events and messages + +2010-03-17 12:18:18 +0100 Sebastian Dröge + + * libs/gst/controller/gstcontrolsource.h: + controller: Mark property_name in GstValueArray as const + This won't and should not be changed from any API + +2010-03-17 12:45:49 +0200 Mart Raudsepp + + * gst/gstelement.h: + docs: fix typo + +2010-03-16 09:56:16 +0200 Mart Raudsepp + + * libs/gst/base/gstdataqueue.c: + docs: add missing "Since: 0.10.26" marker for gst_data_queue_new_full() + +2010-03-16 09:42:21 +0200 Mart Raudsepp + + * gst/gststructure.c: + docs: fix since tag for gst_structure_id_has_field_typed() + gst_structure_id_has_field_typed was added in 0.10.26, not 0.10.16. + Apparent typo in commit f9e3b72f when the API was added. + +2010-03-17 10:53:19 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytewriter.c: + docs: fix Since markers for gst_byte_writer_put_float*() + As the headers were broken in 0.10.26 the functions weren't really + usable back then, so we should advertise them as being there only + since 0.10.27. + Spotted by Mart Raudsepp. + +2010-03-16 17:56:13 +0000 Tim-Philipp Müller + + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + gst: use #if GLIB_CHECK_VERSION instead of #ifndef GLIBMACRO + for better greppability at the time we bump GLib version requirements. + +2010-03-14 11:47:23 +0100 Edward Hervey + + * plugins/elements/gsttypefindelement.c: + typefind: deactivate pad if we can't get length or it's a length of zero. + Fixes issues when re-using typefind after a file of length zero. + +2010-03-16 10:32:12 -0300 Thiago Santos + + * libs/gst/base/gstbasetransform.c: + basetransform: Accept non-fixed caps suggestions + When doing pad_allocs, use non-fixed caps suggestions and + try to fixate them before using. This makes possible to + have suggested buffer size with 0 in basetransform just + to signal upstream a renegotiation is needed + Fixes #576234 + Fixes #609046 + +2010-03-16 10:40:40 +0100 Wim Taymans + + * docs/design/part-qos.txt: + docs: merge QoS message fields + There was already a section about QoS messages that is now merged with the new + information. + +2010-03-16 10:44:01 +0200 Stefan Kost + + * docs/pwg/building-boiler.xml: + pwg: mention how to build after using the project stamp + +2010-03-16 09:56:41 +0200 Stefan Kost + + * gst/gsttask.c: + task: snprintf needs to include "stdio.h" + +2010-03-15 18:48:14 +0100 Wim Taymans + + * docs/design/part-qos.txt: + docs: update QOS docs to include QOS messages + Add some docs about the values needed for a QoS message and some use + cases. + See #322947 + +2010-03-15 17:07:59 +0100 Wim Taymans + + * configure.ac: + * gst/gsttask.c: + task: use bionic/libc friendly arguments to prctl + prctl is supposed to take 5 arguments. It used to work with 2 arguments on some + versions of libc because it is defined as a varags function there. + See #611911 + +2010-03-15 15:07:35 +0100 Wim Taymans + + * gst/gsttask.c: + task: update docs. + +2010-03-15 14:44:51 +0100 Sebastian Dröge + + * gst/gsttaglist.h: + taglist: Work around gtk-doc problem + +2010-03-15 14:44:16 +0100 Sebastian Dröge + + * libs/gst/base/gstbytewriter.h: + bytewriter: Use correct gtk-doc workaround + +2010-03-15 14:05:35 +0100 Sebastian Dröge + + * gst/gstutils.c: + utils: Handle iterator resyncs in gst_pad_proxy_setcaps() + Fixes bug #612881. + +2010-03-15 14:48:19 +0100 Wim Taymans + + * configure.ac: + * gst/gsttask.c: + task: configure the object name as thread name + When we have prctl available, use it to set the configured object name as the + thread name for better debugging. + Based on patch by Robert Swain. + +2010-03-15 13:48:30 +0100 Wim Taymans + + * gst/gstpad.c: + pad: set a good name on the task of the pad + Use the element:pad names to configure a good name for the pad task. + +2010-03-15 12:13:55 +0100 Wim Taymans + + * gst/gsttask.h: + task: retab + +2010-03-15 10:26:18 +0200 Stefan Kost + + * gst/gstpluginloader.c: + logging: remove extra newline + +2010-03-04 23:36:50 +0200 Stefan Kost + + * gst/gstbus.c: + bus: turn g_return_if_fail into g_assert. + This either must never happen (which makes sense in this case) and thus should + use assert() or we should use a traditional if (poll_data->message) return; + to avoid differnet behaviour of intenal api when compiling with + G_DISABLE_CHECKS. + +2010-03-03 23:37:01 +0200 Stefan Kost + + * gst/gstcaps.c: + caps: move the check to the public api. + This avoids creating empty caps and destroying them in the case of an error. We + also avoid double checking in other code path where we call the internal api. + +2010-03-03 23:34:58 +0200 Stefan Kost + + * gst/gstcaps.c: + caps: this is internal API where we need to ensure !NULL higher up + +2010-03-03 21:50:21 +0200 Stefan Kost + + * gst/gst.c: + gst: this is an internal function where we already ensure !NULL when calling + +2010-02-26 09:29:23 +0200 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: fix case of pad flag + Due to a typo the code was always showing the flag as 's' (lower case). + Fixes #611075 + +2010-02-23 23:50:36 +0200 Stefan Kost + + * gst/gstinfo.c: + debug: add pretty printer for events + Adder is using GST_PTR_FORMAT for events already, so we might actualy + implement this and print out some useful info. + +2010-03-13 11:03:59 +0100 Benjamin Otte + + * gst/gstplugin.h: + Add some 0.11 FIXMEs for GstPluginInitFunc + See 8fe63000de31bb2bcf346d59230dea06117997cd for why having a TRUE/FALSE + return value is a bad idea. + I've scanned a few plugins and they generally get it wrong and aren't + unloadable when they return FALSE. + +2010-03-12 19:07:22 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new strings + +2010-03-12 19:05:16 +0000 Leo Singer + + * gst/gstinfo.c: + gstinfo: fix compilation error if HAVE_REGISTER_PRINTF_SPECIFIER is undefined + Use #if HAVE_FOO instead of #ifdef HAVE_FOO. + Fixes #612733. + +2010-03-12 16:42:47 +0100 Benjamin Otte + + * gst/gstplugin.c: + plugins: Do not ever unload a plugin after calling into it + This is what can happen in a plugin_init function: + - An element based on GstBaseSink is registered + - Other elements fail to register + - The plugin_init function returns FALSE + Now if this the plugin is the first plugin to link against + libgstbase.so, it will have caused libgstbase.so to be loaded and static + strings from that library will have been added to gobject while + registering GstBaseSink. + So unloading the plugin will cause those strings to go stale and the + next plugin using GstBaseSink will crash. So we must not unload modules + after calling into them ever. + https://bugzilla.redhat.com/show_bug.cgi?id=572800 + +2010-03-12 15:36:38 +0100 Sebastian Dröge + + * libs/gst/controller/gstinterpolation.c: + interpolationcontrolsource: Don't pass NULL to the GSequence API + +2010-03-12 13:33:00 +0000 Robert Swain + + * scripts/git-update.sh: + git-update: Fix error return value and make the script exit on errors + Newer versions of BASH (4.x?) seem to dislike using -1 for a return. Even + though it's documented as being signed, BASH complains about it, so use + 255 instead. + +2010-03-12 13:54:29 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From e272f71 to 55cd514 + +2010-02-17 13:02:43 +0100 Edward Hervey + + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + gst: Use G_VALUE_COLLECT_INIT if available + This brings total call speedups between 5% and 25%. + gst_caps_set_simple_valist: +5% + gst_structure_set_valist: + 10% + gst_structure_id_set_valist: +25% + gst_tag_list_add_valist: +5% + Measured using valgrind when run over the discovery of 200 media files. + Fixes #610256 + +2010-03-11 20:29:29 +0100 Benjamin Otte + + * tests/check/elements/fdsrc.c: + * tests/check/gst/gstpoll.c: + * tests/check/libs/gstnettimeprovider.c: + win32: Fix build failures of tests + +2010-03-09 20:38:47 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: Adds new geo location tags + Adds new tags GST_TAG_GEO_LOCATION_COUNTRY, + GST_TAG_GEO_LOCATION_CITY and GST_TAG_GEO_LOCATION_SUBLOCATION. + API: GST_TAG_GEO_LOCATION_COUNTRY + API: GST_TAG_GEO_LOCATION_CITY + API: GST_TAG_GEO_LOCATION_SUBLOCATION + Fixes #612410 + +2010-03-11 18:36:32 +0100 Benjamin Otte + + * gst/gst.c: + win32: Add prototype for DllMain() + +2010-03-11 11:46:09 +0100 Edward Hervey + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2009-12-28 17:25:20 +0100 Edward Hervey + + * gst/gstchildproxy.c: + * gst/gstelement.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstutils.c: + * gst/parse/grammar.y: + gstreamer: remove unneeded casts + G_PARAM_SPEC_VALUE_TYPE does an expensive type check, whereas the + value_type field is a public field, so we can just use it directly. + +2010-03-11 11:39:40 +0100 Benjamin Otte + + * configure.ac: + Remove -Winline flag again + It triggers for a lot of GStreamer API (even though those triggers are + wrong most of the time). + I missed it because it only triggers with -O2, and I was using -O0. + +2010-03-11 11:20:35 +0100 Benjamin Otte + + * common: + Automatic update of common submodule + From df8a7c8 to e272f71 + +2010-03-11 11:10:44 +0100 Benjamin Otte + + * configure.ac: + Add a bunch more warning flags to configure + None of these flags cause warnings anymore, so no fixes necessary. + The flags are: + -Wformat-nonliteral + -Wformat-security + -Wold-style-definition + -Wcast-align + -Winline + -Winit-self + -Wmissing-include-dirs + -Waddress + -Waggregate-return + -Wno-multichar + -Wnested-externs + +2010-03-02 22:58:06 +0100 Benjamin Otte + + * configure.ac: + * docs/gst/Makefile.am: + * gst/Makefile.am: + * gst/gstelement.c: + * gst/gstelementdetails.h: + * gst/gstelementfactory.c: + * gst/gstpad.c: + * gst/gstparse.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gstutils.c: + * gst/parse/types.h: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/gstcontroller.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/indexers/Makefile.am: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstindexers.c: + * plugins/indexers/gstindexers.h: + * plugins/indexers/gstmemindex.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstminiobject.c: + * tests/check/libs/typefindhelper.c: + * win32/common/libgstreamer.def: + Fixes for -Wmissing-declarations -Wmissing-prototypes + Also adds those flags to the configure warning flags + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-11 09:39:23 +0000 Tim-Philipp Müller + + * gst/gstbuffer.c: + buffer: fix printf format + Use %u to print unsigned integers. + +2010-03-11 10:29:23 +0200 Stefan Kost + + * tests/check/libs/typefindhelper.c: + tests: cast the arg. to fix the build with new compiler opts. + This is ugly. I am not sure if we really want to have such casts all over the + place. + +2010-03-11 10:14:05 +0200 Stefan Kost + + * gst/gst-i18n-app.h: + * gst/gst-i18n-lib.h: + i18n: define dummy ngettext if i18n is disabled. + We cannot blindly use gettext function and not define them when not using gettext. + +2010-03-11 10:00:45 +0200 Stefan Kost + + * gst/gst-i18n-app.h: + * gst/gst-i18n-lib.h: + i18n: fix the build with i18n disabled. + Don't include gettext.h if !ENABLE_NLS. + +2010-03-04 10:44:52 +0200 Stefan Kost + + * configure.ac: + * gst/gstbuffer.c: + buffer: allow configurable memory alignment. Fixes #596832 + The alignment guaranteed by malloc is not always sufficient. E.g. vector + instructions or hardware subsystems want specifically aligned buffers. The + attached patch will use posix_memalign if available to allocate buffers. + The desired alignment can be set when running configure using the new + --with-buffer-alignment option. + +2010-03-10 21:51:50 +0100 Benjamin Otte + + * common: + Automatic update of common submodule + From 9720a7d to df8a7c8 + +2010-03-10 20:52:06 +0100 Benjamin Otte + + Merge branch 'work' + +2010-03-03 11:45:38 +0100 Benjamin Otte + + * configure.ac: + * gst/gst.c: + * gst/gstbufferlist.c: + * gst/gstdebugutils.c: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstinfo.c: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginloader.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gststructure.c: + * gst/gsttrace.c: + * gst/gsttrace.h: + * gst/gstvalue.c: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/helpers/gst-plugin-scanner.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * tests/benchmarks/controller.c: + * tests/benchmarks/mass-elements.c: + * tests/check/elements/tee.c: + * tests/check/gst/gstbufferlist.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpreset.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/controller.c: + * tests/check/libs/typefindhelper.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/parse-launch.c: + * tests/check/pipelines/simple-launch-lines.c: + * tools/gst-inspect.c: + Fixes for -Wwrite-strings + This changes some APIs in compatible ways: + - Some functions now take "const char *" arguments, not "char *" + - Some structs now have "conts char *" members, not "char *" + The changes may cause warnings when compiling with the right warning + flags. You've been warned. + Also adds -Wwrite-strings as a warning flag in configure.ac. + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-03 10:31:26 +0100 Benjamin Otte + + * configure.ac: + * gst/gstbuffer.c: + * tests/check/libs/transform1.c: + Fixes -Wundef warnings + ... and adds that flag to configure.ac + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-03 10:31:05 +0100 Benjamin Otte + + * tests/benchmarks/gstpollstress.c: + benchmarks: Remove unneeded g_thread_exit() + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-03 10:26:14 +0100 Benjamin Otte + + * gst/gst.c: + * gst/gstpluginloader.c: + * gst/gstregistry.c: + * tools/gst-inspect.c: + Fixes for -Wold-style-definition + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-02 23:51:18 +0100 Benjamin Otte + + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstelementfactory.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstobject.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.h: + * gst/gstsystemclock.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gstutils.h: + * gst/gstxml.c: + * gst/parse/grammar.y: + * libs/gst/base/gstcollectpads.c: + * libs/gst/controller/gstcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + * libs/gst/dataprotocol/dp-private.h: + * tests/check/elements/fakesink.c: + * tests/check/gst/gstparamspecs.c: + * tests/check/gst/gsttagsetter.c: + * tests/check/libs/test_transform.c: + * tests/examples/streams/testrtpool.c: + Make code safe for -Wredundant-decls + Adds that warning to configure.ac + Includes a tiny change of the GST_BOILERPLATE_FULL() macro: + The get_type() function is no longer declared before being defined. + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-10 20:43:35 +0100 Benjamin Otte + + * common: + Automatic update of common submodule + From 0b6e072 to 9720a7d + +2010-03-03 10:00:41 +0100 Benjamin Otte + + * gst/parse/Makefile.am: + Make sure generated code doesn't run with -Werror + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-10 17:03:29 +0100 Benjamin Otte + + * configure.ac: + Update to common/ changes to ERROR_CFLAGS + +2010-03-10 19:17:42 +0100 Benjamin Otte + + * gst/gstregistrybinary.c: + Revert "registry: remove unused function" + Turns out the function is not unused, but was in an #ifdef WIN32 + section. + Whoops. + This reverts commit 57d5db424c68ab5a61f33ce36ce0179eb30251ac. + +2010-03-10 16:09:33 +0100 Benjamin Otte + + * common: + Automatic update of common submodule + From 7cc5eb4 to 0b6e072 + +2010-03-02 21:07:33 +0100 Benjamin Otte + + * gst/gstregistrybinary.c: + registry: remove unused function + Actually, there was two functions with the same name, but only one was + used. + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-02 16:20:15 +0100 Benjamin Otte + + * gst/gstelement.c: + * win32/common/libgstreamer.def: + remove unused gst_element_default_error() + https://bugzilla.gnome.org/show_bug.cgi?id=611692 + +2010-03-10 07:15:15 +0000 Jeremy Huddleston + + * gst/gstutils.c: + utils: Use mulq instead of mul as some assemblers can't guess the size of the operands + Fixes bug #612370. + +2010-03-10 01:09:11 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 7aa65b5 to 7cc5eb4 + +2010-03-09 21:20:27 +0000 Sebastian Dröge + + * common: + Automatic update of common submodule + From 44ecce7 to 7aa65b5 + +2010-02-26 16:03:47 +0100 Sebastian Dröge + + * Makefile.am: + * gst/Makefile.am: + * gst/parse/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + * pkgconfig/Makefile.am: + * tools/Makefile.am: + build: Make some more rules silent if requested + +2010-02-26 15:32:14 +0100 Sebastian Dröge + + * 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-22 16:25:45 +0100 Sebastian Dröge + + * libs/gst/controller/gstlfocontrolsource.c: + lfocontrolsource: Optimize get_value_array() + Don't convert from GValue to the actual type for every single + value. + +2010-02-22 15:18:41 +0100 Sebastian Dröge + + * libs/gst/controller/gstinterpolation.c: + interpolationcontrolsource: Optimize get_value_array() + This makes it >10x faster if more than a single value is requested + by not searching in the GSequence for every value and converting + the value from GValue to the real value type. + +2010-02-21 17:36:55 +0100 Sebastian Dröge + + * tests/benchmarks/controller.c: + controller: Add benchmark for getting a value array of the control points + +2010-03-08 23:28:04 +0100 Benjamin Otte + + * gst/gstplugin.c: + Fix typos in documentation + +2010-03-08 23:04:26 +0100 Benjamin Otte + + * gst/gstvalue.c: + caps: Fail when fractions are followed by random text + Previous code treated "1/1yourmom" the same as "1/1" and "1wimsmom" the + same as "1". Now the code is stricter and will fail to convert a + fraction when followed by garbage text. + +2010-03-09 17:32:39 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + * win32/common/gstversion.h: + Back to development + +=== release 0.10.28 === + +2010-03-08 23:09:01 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.28 + +2010-03-08 23:06:48 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2010-03-08 22:05:29 +0100 Benjamin Otte + + * gst/gstvalue.c: + caps: Allow 1/max as the minimal fraction value > 0 + This is useful for formats that require a valid framerate (like + theoraenc). + +2010-03-04 15:21:37 +0100 Wim Taymans + + * gst/gstelement.c: + element: fix typo in comments + +=== release 0.10.27 === + +2010-03-05 23:43:26 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.27 + +2010-03-05 23:41:09 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2010-03-04 18:39:02 +0000 Tim-Philipp Müller + + * gst/gstpoll.c: + gstpoll: don't pass non-objects as first argument to GST_DEBUG_OBJECT() + This may cause crashes when logging is enabled, especially on windows. + It's not safe to pass random pointers to g_type_check_instance_is_a(). + Fixes #611719. + +2010-03-03 19:54:50 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.26.4 pre-release + +2010-03-03 19:49:34 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translations + +2010-03-03 12:06:30 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytewriter.c: + docs: fix up bytewriter doc chunks for float functions as well + +2010-03-03 11:28:27 +0000 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytewriter.h: + bytewriter: fix headers for float/double writing functions + The functions are called gst_byte_writer_put_{float32|float64}_*() and not + gst_byte_writer_put_{float|double}_*(). + Spotted by: Benjamin Otte + +2010-03-01 12:02:44 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + tags: try to make comment for translators more helpful + +2010-02-26 15:46:50 +0100 Mark Nauwelaerts + + * libs/gst/base/gstbasesink.c: + basesink: fix emergency rendering timestamp tracking + Specifically, if all (including initial) buffers turn up late, + emergency rendering should also kick in appropriately. + Fixes #611087. + +2010-02-24 00:30:02 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.26.3 pre-release + +2010-02-24 00:29:25 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/es.po: + * po/nl.po: + po: update translations + +2010-02-19 13:26:01 +0100 Sebastian Dröge + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * tests/check/libs/controller.c: + interpolationcontrolsource: Don't pass NULL pointers to GSequence API + This causes assertion failures. Fixes bug #610444. + +2010-02-19 13:20:36 +0100 Sebastian Dröge + + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsource.h: + interpolationcontrolsource: Add const qualifiers to values in the _set functions + The values are not modified and are copied, a const before the parameter + should make this even more obvious. + +2010-02-18 09:17:06 +0100 Sebastian Dröge + + * libs/gst/controller/gsthelper.c: + controller: Add some FIXME 0.11 comments + +2010-02-17 10:04:54 +0100 Sebastian Dröge + + * plugins/elements/gstelements.c: + corelements: Combine redundant code + +2010-02-17 01:27:22 +0100 Andoni Morales Alastruey + + * plugins/elements/gstelements.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + Fix compilation of fdsink and fdsrc with MSVC + +2010-02-18 14:58:52 +0000 Tim-Philipp Müller + + * configure.ac: + * po/vi.po: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.26.2 pre-release + +2010-02-18 13:12:39 +0000 Tim-Philipp Müller + + * docs/plugins/.gitignore: + .gitignore: ignore some more temporary docs cruft + +2010-02-18 13:09:17 +0000 Tim-Philipp Müller + + * Makefile.am: + build: fix indenting in win32-update target + No idea why we need to run gst-indent twice on that file, but it + only seems to settle on a final format with minimal diff to the + one in git after two runs. + +2010-02-18 13:08:32 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + gstcheck: more debug logging for gst_check_element_push_buffer_list() + +2010-02-18 11:52:28 -0300 Thiago Santos + + * libs/gst/base/gstcollectpads.h: + collectpads: Improve docs about 'data' attribute + Adds a reminder to 'data' attribute doc + Fixes #610366 + +2010-02-18 17:15:35 +0100 Mark Nauwelaerts + + * plugins/indexers/gstmemindex.c: + memindex: avoid busy loop when doing EXACT lookup + Fixes #610367. + +2009-12-22 11:09:10 +0800 Johan Bilien + + * gst/gstelement.c: + introspection: add annotation for gst_element_get_state + state and pending are "out" arguments. + Fixes #605189. + +2010-02-17 12:16:37 +0100 Edward Hervey + + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfilesrc.h: + filesrc: Don't use expensive cast checks in _create + _create() is a pad function set by ourselves, therefore we're sure basesrc + is a GstFileSrc. + Speeds up _create() by 17% and the total call by 8% (instruction calls measurements + done with valgrind). + Fixes #610246 + +2010-02-17 12:14:09 +0100 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: Don't use expensive cast checks in get_range. + _get_range() is a pad function set by ourselves, therefore we're certain that + the parent is a GstBaseSrc. + Speeds up _get_range by 38%, and the total call by 30%. (valgrind instruction + calls measurements). + Fixes #610246 + +2010-02-17 11:31:07 +0200 Stefan Kost + + * plugins/elements/gstfdsrc.c: + fdsrc: cleanup parameter initialisation and add comemnt+logging + Initialize new_fd with DEFAULT_FD and fd with -1. Setting the property will set + new_fd and in _update_fd() we cehck fd against -1. Also add a coment about the + warning we get in the log from gst_poll_remove_fd(). We could get rid of the + warning if we want by tracking if fd has been added to fdset. + +2010-02-17 09:55:52 +0200 Stefan Kost + + * docs/design/draft-metadata.txt: + design: write about the current state of tag-handling + Document the taghandling in gstreamer. List gaps and propose new mechanisms to + deal with them. + +2010-02-16 10:27:18 +0200 Stefan Kost + + * gst/gsttaglist.c: + taglist: remove blank lines in variable declarations + +2010-02-16 11:30:35 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + * tools/tools.h: + tools: call g_set_prgname() before doing the option parsing + g_setprgname is implicitly called by g_option_context_new() with a check + to see if it's been set already, so set it before g_option_context_new() + Move version printing back until after the options have been parsed, + otherwise it won't work, since it evaluates a flag set by the + option parser. + +2010-02-16 11:24:33 +0000 Tim-Philipp Müller + + * tools/gst-inspect.c: + * tools/gst-launch.c: + Revert "tools: Move gst_tools_print_version call to avoid warning from new GLib." + This reverts commit 93dd95f02ef3fa530f54ce81e8ffba96f3b679cb. + This commit made --version not work any longer. The g_setprgname() + warning is fixed in recent GLib versions. + +2010-02-16 08:26:59 +0000 Tim-Philipp Müller + + * configure.ac: + * gst/Makefile.am: + build: make sure gst-plugin-scanner gets installed where we expect it + Add check to make sure gst-plugin-scanner really gets installed where + we will look for it later, ie. paths and prefixes are set at configure + time and not specified via make. + Fixes #609941. + +2010-02-15 23:02:59 +0200 Stefan Kost + + * plugins/elements/gstqueue2.c: + docs: prefer short desc from GstElementDetails + +2010-02-15 01:24:25 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.c: + docs: fix gtk-doc chunk for gst_check_element_push_buffer_list() + +2010-02-13 15:28:39 +0000 Tim-Philipp Müller + + * tests/check/elements/dataurisrc.c: + tests: add unit test for dataurisrc + Requires fixes from core git, so bump core requirement to git as well. + +2010-02-15 00:31:16 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update po files for new comments + +2010-02-15 00:29:37 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + tags: wrap long string constants + And fix indenting issue + +2010-02-15 00:21:43 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + tags: add some comments for translators so tag mnemonics get translated correctly + We want 'preview image' translated as a noun, not as 'preview [the] image'. + +2010-02-04 17:43:32 +0000 Tim-Philipp Müller + + * gst/gstpad.c: + pad: don't print WARN debug statements for normal things like EOS + +2010-02-14 23:15:45 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 96dc793 to 44ecce7 + +2010-02-13 15:18:05 +0100 Edward Hervey + + * plugins/elements/gsttypefindelement.c: + typefind: Reset the working mode when going to READY/NULL + This allows properly re-using typefind (else it would think it's + already done the typefinding when being re-used with another + stream). + +2010-01-22 11:38:59 -0300 Thiago Santos + + * tests/check/libs/bytewriter.c: + bytewriter: Adds a test for _fill + +2010-01-22 09:19:31 -0300 Thiago Santos + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + * win32/common/libgstbase.def: + bytewriter: add _fill function + Adds a new function to GstByteWriter that writes + a constant value to a memory area (aka memset). + Useful for adding padding to buffers. + Also updates .def file and docs. + API: gst_byte_writer_fill() + +2010-01-28 11:57:33 -0300 Thiago Santos + + * plugins/elements/gsttypefindelement.c: + typefind: Avoid messing pads activation + Typefind might mess up pads modes (pull/push) if a + downstream element is plugged and its pads activated + in 'step 2' of typefind pads activation. + This happens because the following steps don't check + if we already emitted typefound due to upstream setting + caps on buffers being pulled in the typefind helpers. + Avoid that by checking if typefound is already emmited. + Fixes #608036 + +2010-02-12 14:49:52 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: Make locking of the segment a bit more strict and update documentation + Updating the segment values must only be done while holding the + STREAM_LOCK and OBJECT_LOCK. This means, reading can be done as + long as one of them is held, not both, which removes some lock-unlock + blocks from performance critical code paths. + Also document, that gst_base_src_set_format() *must* be called in + states <= READY and add an assertion for this. Changing the format + later will completely mess up the segment information. + +2010-02-08 09:12:01 +0530 Arun Raghavan + + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-dparams.xml: + * docs/pwg/advanced-interfaces.xml: + * docs/pwg/advanced-negotiation.xml: + * docs/pwg/advanced-request.xml: + * docs/pwg/advanced-scheduling.xml: + * docs/pwg/advanced-tagging.xml: + * docs/pwg/advanced-types.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/building-boiler.xml: + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/building-props.xml: + * docs/pwg/building-testapp.xml: + * docs/pwg/intro-basics.xml: + pwg: several typo fixes + Fixes #609286. + +2010-02-09 17:52:13 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesrc.c: + basesrc: Protect segment values from concurrent access from different threads + This could happen easily in the query functions or when the size is set + on appsrc from some non-streaming thread. + +2010-02-04 21:11:25 +0100 Sebastian Dröge + + * plugins/elements/gsttypefindelement.c: + typefindelement: Protect internal fields from concurrent changes from different threads + Fixes bug #608877. + +2010-02-11 20:14:59 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: don't leak timeout GSource + +2010-02-11 00:18:39 +0000 Tim-Philipp Müller + + * docs/random/release: + docs: flesh out release doc some more + +2010-02-11 01:10:38 +0000 Tim-Philipp Müller + + * MAINTAINERS: + Update MAINTAINERS, add myself + +2010-02-11 19:49:00 +0000 Tim-Philipp Müller + + * configure.ac: + configure: back to development + Slushy freeze remains in effect. + +=== release 0.10.26 === + +2010-02-10 19:17:28 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.26 + +2010-02-10 15:32:06 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2010-02-09 15:52:23 +0000 Tim-Philipp Müller + + * configure.ac: + configure: define GST_PLUGIN_SCANNER_INSTALLED in win32 config.h + Even if it's not used, it still needs to be defined for things to + compile. + +2010-02-09 10:19:04 +0000 Tim-Philipp Müller + + * gst/gst_private.h: + gst_private: MSVC doesn't seem to like #warning + Visual Studio complains about "invalid preprocessor command 'warning'" + even if the ifdef doesn't trigger, so just remove this again. + +2010-02-10 14:40:17 +0100 Edward Hervey + + * tests/check/elements/multiqueue.c: + tests: Fix multiqueue test for latest commits. + The problem lies in the fact that multiqueue will now operate somewhat + similarly to the flow aggregation logic of demuxers and therefore + will stopp whenever all downstream pads return NOT_LINKED and/or + UNEXPECTED and there's no more buffers to push. + The latest commits should not affect any regular use-case, but the bug + report will be kept open so the previous behaviour can be re-established + if needed. + Fixes #609486 + +2010-02-09 15:51:18 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + multiqueue: Don't stop threads on UNEXPECTED and forward flow returns. + When a downstream element returns GST_FLOW_UNEXPECTED we want to: + * let the dataqueue task running + * forward the flow return upstream. + This allows upstream elements to push EOS, and have that EOS event come + downstream. + Fixes #609274 + +2010-02-09 13:35:08 +0100 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + Revert "multiqueue: handle UNEXPECTED flowreturn better" + This reverts commit fbdf4dcedad8692f1e3d8838551188987e462e74. + Partly fixes #609274 + +2010-01-28 07:27:49 +0100 Robert Swain + + * scripts/git-update.sh: + git-update.sh: Fix issues + +2010-02-07 09:59:25 +0100 Tim-Philipp Müller + + * gst/gstbufferlist.c: + Revert "docs: fix ASCII art so that iterators are aligned property to the diagram" + This reverts commit ae60d06e9e401d1ed4de5ef25b5c283db0696a31 (fixes: #609166) + +2010-02-04 18:30:56 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.25.3 pre-release + +2010-02-04 17:45:46 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/de.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/pl.po: + * po/sv.po: + * po/zh_CN.po: + po: translation updates + +2010-02-01 12:50:40 +0000 Tim-Philipp Müller + + * gst/gstbufferlist.c: + docs: fix ASCII art so that iterators are aligned property to the diagram + +2010-02-01 17:40:08 -0300 Thiago Santos + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytewriter.h: + gstbytewriter: Fix different function names in .h and .c + gst_byte_writer_reset_and_get_buffer wasn't declared + in .h, instead there was _reset_and_get_data_as_buffer. + Replace it with the real function name, that is smaller + and matches gst_byte_writer_free_and_get_buffer + https://bugzilla.gnome.org/show_bug.cgi?id=608726 + +2010-01-31 17:30:54 +0000 Tim-Philipp Müller + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + docs: add some more Since: markers to buffer list docs + +2010-01-30 18:57:44 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesrc.c: + filesrc: fix typo in warning message + Spotted by bsreerenj@gmail.com. + Fixes #608442. + +2010-01-30 15:17:48 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 15d47a6 to 96dc793 + +2010-01-30 13:45:58 +0000 Tim-Philipp Müller + + * gst/gst.c: + init: don't spew warning about late g_thread_init()s if GLib >= 2.23.2 + Late g_thread_init() is fine with newer GLib versions and done automatically + from g_type_init() there, so don't warn if the application hasn't called + g_thread_init() yet when gst_init() is called with new GLib versions. + Fixes #608398. + +2010-01-29 09:41:30 +0000 Tim-Philipp Müller + + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + pkgconfig: don't put -DG_THREADS_MANDATORY into our pkg-config CFLAGS + If we force -DG_THREADS_MANDATORY onto apps, then g_thread_supported() + will always evaluate to TRUE, so the typical thread initialisation + boilerplate code if (!g_thread_supported()) g_thread_init(NULL); will + no longer work, and the threading system not be initialised and us + printing a warning in gst_init. This may be fine in most cases, since + late initialisation is allowed and automatically done in g_type_init() + since GLib 2.23.2, but let's be cautious and only use this define when + compiling GStreamer itself. + See #608398. + +2010-01-28 15:55:27 +0100 Wim Taymans + + * gst/gstpipeline.c: + pipeline: Take start_time after chaining up too + Refactor the code to take the current start_time when going to PAUSED. + Make sure we also call the start_time update code after we chained up to the + parent bin. + Fixes #607842 + +2010-01-28 00:07:14 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + dataurisrc: add start function so we can error out properly if no uri is set + Also save a set URI after it has been parsed successfully, so that _get_uri() + actually works. + +2010-01-27 23:46:32 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + dataurisrc: don't post error message when setting the URI failed + There's a gboolean return for that, and the messages don't really + add anything useful. + +2010-01-27 23:39:14 +0000 Tim-Philipp Müller + + * plugins/elements/gstdataurisrc.c: + dataurisrc: must release the object lock before using GST_ELEMENT_ERROR + +2010-01-26 18:59:50 +0000 Tim-Philipp Müller + + * configure.ac: + 0.10.25.2 pre-release + +2010-01-27 00:23:07 +0000 Tim-Philipp Müller + + * tests/check/gst/gstghostpad.c: + checks: fix spurious ghost pad check failure + +2010-01-26 19:35:52 +0000 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + win32: update windows headers to latest version + +2010-01-26 19:32:48 +0000 Tim-Philipp Müller + + * docs/random/release: + docs: minor update to release notes + +2010-01-26 18:45:38 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translation files + +2010-01-26 18:39:45 +0000 Tim-Philipp Müller + + * tests/examples/streams/rtpool-test.c: + tests: fix warning in rtpool-test + The stream status message object may be of a non-GObject type, e.g. + G_TYPE_POINTER (see GstAudioSrc), so print that properly instead + of assuming the value holds an object. + +2010-01-26 12:43:09 +0100 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * tests/check/elements/multiqueue.c: + multiqueue: handle UNEXPECTED flowreturn better + When we receive an UNEXPECTED flowreturn from downstream, we must not shutdown + the pushing thread because upstream will at some point push an EOS that we still + need to push further downstream. + To achieve this, convert the UNEXPECTED return value to OK. Add a fixme so that + we implement the right logic to propagate the flowreturn upstream at some point. + Also clean up the unit test a little. + Fixes #608136 + +2010-01-26 08:52:16 -0300 Thiago Santos + + * docs/manual/basics-bus.xml: + docs: Fix basics-bus docs + Fix wrong information about bus watch functions in the + application development manual. + Fixes #608127 + +2010-01-25 12:12:32 +0100 Sebastian Dröge + + * plugins/elements/gstdataurisrc.c: + dataurisrc: Remove role attribute from links + +2010-01-25 11:56:33 +0100 Sebastian Dröge + + * plugins/elements/gstdataurisrc.c: + dataurisrc: Add docs and integrate into build system + Fixes again bug #596885. + +2010-01-25 11:12:47 +0100 Sebastian Dröge + + * plugins/elements/gstdataurisrc.c: + * plugins/elements/gstdataurisrc.h: + dataurisrc: Add data: URI source element + This is slightly based on the WebKit data: URI source + but supports more parts of RFC 2397. + Fixes bug #596885. + +2010-01-24 23:12:22 +0200 Stefan Kost + + * win32/common/libgstreamer.def: + bin: also remove private function from def file + +2010-01-24 23:04:27 +0200 Stefan Kost + + * gst/gstbin.c: + bin: make a interface vmethod implementation static + This should not cause any troubles - the methods wasn't in any header. + +2010-01-24 22:22:07 +0200 Stefan Kost + + * gst/gstchildproxy.c: + childproxy: remove ; after } + +2010-01-22 18:00:53 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + queue2: add some docs to mark new property + +2010-01-22 17:55:39 +0100 Wim Taymans + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: add option to remove the temp-file + Add an option to automatically remove the temp file (TRUE by default). This + should make it possible for the application to keep the temp file by other means + than hardlinking or holding an fd open. + Fixes #607739 + +2010-01-22 02:02:01 +0000 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefind: don't leak uri string + +2010-01-21 16:19:44 +0100 Wim Taymans + + * gst/gstindex.h: + gstindex: retab .h file + +2010-01-20 14:13:11 +0100 Benjamin Otte + + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + tools: Run g_thread_init() unconditionally + Since we define G_THREADS_MANDATORY, g_thread_supported() evaluates to + TRUE unconditionally, so calling g_thread_init() never happened. + +2010-01-20 10:58:29 +0000 Tim-Philipp Müller + + * gst/gstpluginloader.c: + pluginloader: fix compiler warning on win32 + Move variable that's only used on unix into the unix block so that + the compiler doesn't complain about the unused variable on win32 + (see #597662). + +2010-01-20 09:45:06 +0000 Tim-Philipp Müller + + * gst/gstpluginloader.c: + pluginloader: try scanner set via env var before using the installed one + If the GST_PLUGIN_SCANNER environment variable is set, we should try + the scanner specified there first, to make sure the right scanner binary + is used for uninstalled setups and builds from source when there's + already an installed version. + +2010-01-20 06:58:28 +0100 Sebastian Dröge + + * configure.ac: + * gst/gst.c: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + build: Define G_THREADS_MANDATORY everywhere + We require threads to be supported in any case and defining this + will simplify the mutex, condition variable, etc. macros from gthread + to not always check if threads are really supported. + Fixes bug #607481. + +2010-01-08 20:56:18 +0100 Andoni Morales Alastruey + + * gst/gstpluginloader.c: + * gst/gstregistry.c: + pluginloader: disable external plugin loader on Windows until it is ported properly + See #597662. + +2010-01-20 01:09:55 +0000 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstpluginloader.c: + * gst/parse/grammar.y: + * gst/parse/parse.l: + * libs/gst/base/gstbasesink.c: + * libs/gst/helpers/gst-plugin-scanner.c: + * plugins/elements/gsttypefindelement.c: + gst_private.h: make sure gst_private.h is included before glib.h + For the reason outlined at the beginning of gst_private.h (inline + functions in glib may need the g_log_domain variable). Also include + gst_private.h before using any G_OS_* defines, esp. in plugin loader. + +2010-01-20 01:33:38 +0000 Tim-Philipp Müller + + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue2.c: + docs: minor gtk-doc markup fixes + +2010-01-20 00:53:01 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 14cec89 to 15d47a6 + +2010-01-19 16:39:38 +0100 Wim Taymans + + * docs/design/part-qos.txt: + * docs/design/part-seeking.txt: + docs: small docs updates + +2010-01-19 14:07:23 +0100 Thijs Vermeir + + * gst/gstpad.c: + gstpad: directly set the caps when pushing buffer with different caps. + This check is not necesarry as we are not negotiating anymore. And it can + be wrong if upstream can't produce this caps anymore, but downstream can + process them fine. + +2010-01-18 13:57:29 +0100 Sebastian Dröge + + * gst/gstminiobject.c: + miniobject: The GValue collection function can not assume that the destination is initialized + ...and it will usually be either filled by zeroes or random values. + Fixes bug #607283. + +2010-01-16 21:52:06 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Only use suggested caps in buffer allocation if a size was suggested too + +2010-01-16 19:41:29 +0000 Tim-Philipp Müller + + * gst/gststructure.c: + structure: remove superfluous guard against NULL + All callers of this static function already check for NULL-ness + themselves, so no need to do it again (and if we do it, we should + probably do so before dereferencing the pointer for the first time). + +2009-12-17 19:45:31 +0000 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gststructure.c: + structure: micro-optimise some getters + Avoid checking the GType of the value twice (once on our side and + once in g_value_get_*()) by by-passing g_value_get() and accessing + the GValue structure directly. + +2010-01-15 18:36:07 +0100 Wim Taymans + + * gst/gstmessage.h: + message: update docs a little + +2010-01-15 00:46:23 +0000 Tim-Philipp Müller + + * docs/random/release: + docs: minor release docs update + +2010-01-14 20:19:05 +0100 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Handle buffers with NULL caps correctly + This means that the caps didn't change so don't try to handle + the NULL caps as the new caps. + +2010-01-14 10:44:16 +0100 Sebastian Dröge + + * gst/gstbuffer.h: + * gst/gsturi.h: + docs: Move field specific Since markers at the same line + Fixes gobject-introspection warnings about Since being defined multiple times. + +2010-01-13 10:17:03 +0000 Tim-Philipp Müller + + * docs/faq/faq.xml: + faq: remove revision history that no one updates or cares about anyway + +2010-01-13 09:32:59 +0000 Tim-Philipp Müller + + * docs/faq/developing.xml: + * docs/faq/git.xml: + faq: fix link to gst-uninstalled on cgit + Fix link to gst-uninstalled now that it's been moved, and fix a typo + while we're at it. Also add a new section to 'Building GStreamer from + git' that points to the 'How do I develop against an uninstalled copy + of GStreamer' section. + +2010-01-13 10:32:46 +0200 Stefan Kost + + * README: + docs: we're in git since a while + +2010-01-13 10:31:26 +0200 Stefan Kost + + * Makefile.am: + * README: + * docs/faq/Makefile.am: + * docs/faq/developing.xml: + * docs/faq/faq.xml: + * scripts/gst-uninstalled: + scripts: move gst-uninstalled from docs/faq to scripts + Don't include the long gst-uninstalled script in verbatim in the faq anymore + (there is a link to cgit). Dist the script under its new location. + +2010-01-12 21:34:03 +0000 Tim-Philipp Müller + + * gst/gstregistrychunks.c: + registry: avoid some more unnecessary malloc/frees + +2010-01-12 20:21:32 +0000 Tim-Philipp Müller + + * gst/gstregistrychunks.c: + registry: avoid some unnecessary strdup/free when reading the binary registry + Strings in the binary registry are NUL-terminated, so we can just use them + directly if we only need them temporarily, and avoid unnecessary mallocs + and frees. + +2010-01-12 17:38:32 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + typefindelement: use new typefind function + Refactor a little. + Use the new typefind helper function that uses the extension to speed up + typefinding. + +2010-01-12 17:34:39 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * win32/common/libgstbase.def: + typefind: add a new method that also uses the file extension + Add a method to perform get_range typefinding that also uses the + uri/location extension as an extra hint. It will first try to call the + typefind functions of the factories that handle the given extension. The result + is that in the common case, we only call one typefind function, which speeds up + the typefinding a lot. + +2010-01-11 14:58:11 +0100 Wim Taymans + + * docs/design/part-qos.txt: + docs: update QoS documeent + Add some ideas about a new QoS message. + See also #322947 + +2010-01-11 11:38:32 +0100 Håvard Graff + + * plugins/elements/gsttee.c: + tee: make release_pad threadsafe + Protect the ->removed field with the object lock as well. Take the DYN lock + earlier so that we can mark the pad removed and avoid a race in pad_alloc. + Fixes #606435 + +2009-12-11 17:46:42 +0100 Wim Taymans + + * gst/gstbus.c: + * gst/gstbus.h: + bus: whitespace fixes + +2010-01-10 21:49:25 +0200 Stefan Kost + + * gst/gstutils.c: + utils: defer getting the classes until we actualy need them + This function has a lot of early returns. Give them soem more benefit. + +2010-01-10 21:40:24 +0200 Stefan Kost + + * gst/gstutils.c: + utils: avoid extra hop in gst_element_link + No need to call gst_element_link_pads_filtered with filter=NULL, which would + call gst_element_link_pads() in that way. Call it directly to save a call and + expensive gobject type checks. + +2010-01-10 17:39:55 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: remove some cruft from header file + Remove some cruft from the gstcheck header file that's not needed + any longer now that we ship with our own copy of libcheck. + +2010-01-07 17:41:26 +0200 Stefan Kost + + * docs/pwg/advanced-midi.xml: + * docs/pwg/pwg.xml: + pwg: remove empty midi section + +2010-01-07 13:48:24 +0000 Christian Schaller + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gstreamer + +2010-01-07 13:47:50 +0000 Christian Schaller + + * gstreamer.spec.in: + Update spec file + +2010-01-06 20:08:48 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update for new translated strings + +2010-01-06 20:06:47 +0000 Tim-Philipp Müller + + * gst/gsttaglist.h: + docs: minor documentation fixes for recently-added tags + Mention the type of the tag in the gtk-doc blurb, so people know + which accessor API to use, and fix up the doc blurbs to match the + actual tag define. + +2010-01-06 20:04:15 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + tags: fix up translated strings for some new tags + Fix up translated strings for some recently-added tags to match the + existing strings: we want short mnemonic-like strings here that start + with a lower case letter. + +2010-01-06 19:19:40 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + registry: deprecate useless gst_registry_xml_{read|write}_cache() + The only reason these two functions are still around is that at some + point in the past they were in a public header, so we can't really + remove them now even though they should have been private all along + (and aren't really particularly useful). Since these are just empty + stubs now that do nothing but return FALSE and will be removed in + 0.11 anyway, we may just as well deprecate them formally. + +2010-01-06 19:18:53 +0000 Tim-Philipp Müller + + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + docs: add Since markers to task pool docs and document task function + +2010-01-06 18:50:43 +0000 Tim-Philipp Müller + + * configure.ac: + configure: move SHAVE_INIT behind all checks + Move SHAVE_INIT behind all other checks, in particular AG_GST_CHECK_CHECKS. + This should fix problems with header checking and checking for localtime_r, + which causes compilation errors with clean checkouts where common/shave has + not been created yet when those checks are run. It seems like SHAVE_INIT + changes the environment so that checks depending on a compiler need shave + to exist at that point, which will fail if AC_OUTPUT hasn't created it yet. + Fixes #605930. + +2010-01-05 01:35:41 +0000 Tim-Philipp Müller + + * libs/gst/check/libcheck/check.c: + check: patch internal check copy some more so that failures actually fail + Include unistd.h so that _POSIX_VERSION is actually defined when + it should be defined. Without that, stuff like fail_if(1) doesn't + actually fail, presumably because other parts of the code do include + unistd.h and then have _POSIX_VERSION defined. + Fixes #604565 even more. + +2010-01-05 00:09:10 +0200 Stefan Kost + + * gst/gstevent.h: + docs: add missing returns: tag + +2009-12-30 22:56:57 +0100 Mark Nauwelaerts + + * plugins/elements/gstmultiqueue.c: + multiqueue: set iterate_interal_links function on source pad + +2009-12-27 19:33:25 +0100 Wim Taymans + + * gst/gstbuffer.c: + buffer: remove unneeded casts + +2009-12-02 19:47:46 +0100 Wim Taymans + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + buffer: remove subbuffer subclass + Move the parent buffer pointer into the GstBuffer struct so that we can + remove the subbuffer class and type. This is interesting because it allows us to + more naturally implement methods to get the real type and parent + of a subbuffer (See #545501). + It should also be slightly faster because there is no extra object hierarchy to + initialize and free. + +2009-12-24 19:25:52 +0100 Wim Taymans + + * libs/gst/base/gstcollectpads.c: + collectpads: don't keep buffers reffed longer than needed + Make sure we take ownership of the buffer early without increasing its refcount + when we go in the collect function. This reduces the amount of copies needed in + order to make the buffer writable in most cases. + +2009-12-24 17:22:46 +0100 Wim Taymans + + * gst/gstminiobject.c: + miniobject: avoid unneeded casts + +2009-12-24 16:53:15 +0100 Wim Taymans + + * libs/gst/base/gstcollectpads.c: + collectpads: avoid doing subbuffers when we can + In some cases we can avoid allocating a subbuffer and instead simply ref + the buffer. Callers should perform _make_metadata_writable() in all + cases now. + +2009-12-24 15:25:14 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * win32/common/libgstbase.def: + collectpads: add ability to install clipping functions + Add a method to install a clipping function that is called when a buffer is + received. Users of collectpads can then perform clipping on the incomming + buffers. + Also retab the header file a little. + See #590265 + +2009-12-24 15:13:49 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: add some more buffer2 ideas + +2009-12-24 14:40:54 +0100 Wim Taymans + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstobject.c: + * gst/gstpad.c: + avoid some more type checks + +2009-12-24 14:22:52 +0100 Wim Taymans + + * gst/gstpipeline.c: + pipeline: avoid some type checks + Avoid type checks when we can + Don't need to peek the parent_class, the boilerplate does that for us. + +2009-12-23 21:39:20 +0100 Wim Taymans + + * tools/gst-launch.c: + launch: also print leaked objects + Make the -T option also print the leaked objects + +2009-12-23 21:37:51 +0100 Wim Taymans + + * gst/gsttrace.c: + trace: include type name in leaked objects + When we are dealing with a GObject, print the type name along with + the pointer for easier debugging. + +2009-12-23 21:20:14 +0100 Wim Taymans + + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + pad: Fix problem with destroy callback not being called + When we unblock a pad with the same user_data, the destroy callback is not + called. This leads to refcounting leaks that cannot be avoided. Instead always + call the destroy notify whenever we install a new pad block. + In particular, this fixes a nasty pad leak in decodebin2. + Also update the unit test to have more accurate comments and test the required + behaviour. + +2009-12-22 22:52:02 +0100 Wim Taymans + + * plugins/elements/gsttee.c: + tee: small cleanups, use some G_LIKELY + +2009-12-22 15:29:26 -0500 Olivier Crête + + * plugins/elements/gsttee.c: + tee: Don't crash if there is no source pad + +2009-12-21 19:11:45 +0100 Mark Nauwelaerts + + * common: + Automatic update of common submodule + From 47cb23a to 14cec89 + +2009-12-21 11:58:12 -0300 Thiago Santos + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + gsttaglist: Adds new tags + Adds the following new tags: + GST_TAG_SHOW_NAME + GST_TAG_SHOW_SORTNAME + GST_TAG_SHOW_EPISODE_NUMBER + GST_TAG_SHOW_SEASON_NUMBER + GST_TAG_LYRICS + GST_TAG_COMPOSER_SORTNAME + GST_TAG_GROUPING + Fixes #599759 + +2009-12-19 14:27:05 +0000 Tim-Philipp Müller + + * configure.ac: + configure: always call our check checks for the SUBUNIT conditional + The SUBUNIT conditional needs to be set even if check is disabled. Also + remove a FIXME that is not needed any longer / after all. + +2009-12-18 21:28:35 +0000 Руслан Ижбулатов + + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + check: patch internal check copy so it works with our build system + Fixes #604565. + +2009-12-18 21:26:01 +0000 Руслан Ижбулатов + + * check-checks.m4: + * configure.ac: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/libcheck/Makefile.am: + check: update autotools and docs stuff for new check version + +2009-12-17 20:09:48 +0000 Tim-Philipp Müller + + * check-checks.m4: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_impl.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_log.h: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/check_str.h: + check: update internal libcheck to 0.9.8 + +2009-12-15 18:55:38 +0100 Mark Nauwelaerts + + * plugins/elements/gstfilesrc.c: + filesrc: printf format fixes + +2009-12-14 16:22:16 +0200 Stefan Kost + + * gst/gstbus.c: + * gst/gsttask.c: + docs: link bus and tasks + Add a link from bus section docs to the task docs. Add a paragraph to task docs + to tell about messages and the bus. + +2009-12-14 15:11:42 +0200 Stefan Kost + + * gst/gstelement.c: + * gst/gstelement.h: + docs: add more docs around GstState and GstStateChange + Take reviewed docs from docs/design/part-state to have that more prominent + inside the api docs. Add a few sentences to link things better together. + +2009-12-14 15:11:14 +0200 Stefan Kost + + * docs/design/part-states.txt: + docs: review and fix spelling + +2009-12-14 11:05:41 +0200 Stefan Kost + + * gst/gstelementfactory.c: + gstelementfactory: set object name earlier if applicable + Setting an object name is nice for proper debug logging. Ideally this would + still happens earlier (.e.g when pads are added to an element, its not yet set). + +2009-12-14 11:07:25 +0200 Stefan Kost + + * gst/gstobject.c: + gstobject: add fixme-0.11 comment + +2009-12-08 11:30:39 +0200 Stefan Kost + + * gst/gstobject.c: + comment: small comment correction + +2009-12-11 16:26:00 +0100 Wim Taymans + + * gst/gstbin.c: + bin: never skip a state change to PLAYING + Never skip the state change to playing, even if the element is already in the + right state. We need this because we also distribute the base_time while doing + the state change and skipping this step would leave some elements without a new + base_time. + Fixes #600313 + +2009-12-11 16:19:18 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add some more debugging + +2009-12-08 17:21:47 +0100 Havard Graff + + * plugins/elements/gsttee.c: + tee: release pads in dispose + Make sure to release all request-pads in the dispose-method, in case of a + shutdown-race, where a pad-alloc is about to happen. + Fixes #604091 + +2009-12-09 13:27:22 +0100 Wim Taymans + + * gst/gstelement.c: + element: use NULL instead of 0 for pointers + +2009-12-09 07:25:31 +0100 Sebastian Dröge + + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + tools: Move gst_tools_print_version() for the remaining tools + +2009-12-03 12:31:19 +0100 Ole André Vadla Ravnås + + * tools/gst-inspect.c: + * tools/gst-launch.c: + tools: Move gst_tools_print_version call to avoid warning from new GLib. + g_setprgname is implicitly called by g_option_context_new() with a check + to see if it's been set already. + Fixes bug #604093. + +2009-12-08 16:40:57 +0100 Sebastian Dröge + + * gst/gstutils.c: + utils: Fix proxy_setcaps to only iterate pads of other direction + +2009-12-08 16:21:41 +0100 Wim Taymans + + * gst/gstutils.c: + utils: fix proxy_getcaps + Make it return the padtemplate caps on errors and no parent. + Only intersect pads of the oposite direction of the source pad. + +2009-12-08 16:14:28 +0100 Sebastian Dröge + + * gst/gstutils.c: + utils: Rename proxy iterator fold functions to have a more meaningful name + +2009-12-08 16:09:02 +0100 Sebastian Dröge + + * gst/gstutils.c: + utils: If one intersection gave empty caps don't continue iterating over the other pads + +2009-12-08 15:24:43 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Allow update NEWSEGMENT events after EOS + This allows demuxers to update the segment stop of an already + finished stream. This might be needed if some stream goes to + EOS before the duration of the longest stream is known to properly + set the segment stop of all streams to the same value in the end. + +2009-12-07 20:52:22 +0100 Wim Taymans + + * gst/gstbufferlist.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstquery.h: + Use plain casting instead of typechecking + +2009-12-07 09:45:00 +0100 Edward Hervey + + * gst/gstvalue.c: + gstvalue: Use fast gst_value_list_{size|get_value} macro accessors + gst_value_list_size and gst_value_list_get_value will do a series of + extra checks due to being public methods. + When we use them from within gstvalue.c we can directly use them without + the extra checks. + +2009-12-07 09:44:06 +0100 Edward Hervey + + * gst/gsturi.c: + gsturi: Don't use g_signal_emit_by_name, use the signal ID directly + +2009-11-18 09:01:35 +0100 Edward Hervey + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + tee: avoid expensive typechecks, and avoid getting ref to parent. + Speeds up tee processing 2 to 5 times. + +2009-11-12 09:07:03 +0100 Edward Hervey + + * gst/gstobject.c: + gstobject: Avoid double strdup when setting NULL names. + Instead of chaining up to gst_object_set_name (which does typechecking + and strdup's the name again), just use the already allocated new + name. + +2009-12-04 12:16:32 -0800 Peter van Hardenberg + + * docs/pwg/building-props.xml: + pwg: make the enum example (based on videotestsrc) actually match videotestsrc + +2009-12-04 16:28:27 +0100 Sebastian Dröge + + * gst/gstbin.c: + bin: Ignore state change failures from children that were removed from the bin already + Fixes bug #584441. + +2009-12-04 15:00:44 +0100 Sebastian Dröge + + * gst/gstregistrybinary.c: + registry: Use GMappedFile for reading the registry + Fixes bug #603787. + +2009-12-03 19:48:11 +0100 Javier Jardón + + * gst/gstregistrybinary.c: + registry: Substitute deprecated GLib symbol: g_mapped_file_free + Use g_mapped_file_unref if Glib >= 2.22 is available + Fixes bug #560442. + +2009-11-27 20:16:15 +0100 Jan Schmidt + + * libs/gst/base/gstbasesrc.c: + basesrc: Shut down the pad task when the initial seek fails. + Set the pad flushing and stop the pad task when the initial seek fails + during activation. Avoids racy calls into the _create() function when + BaseSrc::stop() has already run. + Fixes: #603059 + Also, fix some misspelled comments. + +2009-12-03 20:55:37 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update .po files after string changes + (The queue2 strings could use some tidying up) + +2009-12-03 20:53:25 +0000 Tim-Philipp Müller + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + filesink, filesrc: printf format fixes + gstfilesink.c:399: error: format ‘%d’ expects type ‘int’, but argument 8 has type ‘size_t’ + gstfilesink.c:399: error: format ‘%d’ expects type ‘int’, but argument 9 has type ‘gsize’ + gstfilesrc.c:588: error: format ‘%08llx’ expects type ‘long long unsigned int’, but argument 8 has type ‘off_t’ + +2009-12-03 16:44:28 +0200 Stefan Kost + + * plugins/elements/gsttee.c: + tee: add special case for only one pad conected + It is not easy to setup a tee on the fly, thus apps need to add them always if + they might need them. This changes the code so, that if only one src-pad is + active, we push buffers directly. In the normal code path all buffers are pushed + with an extra ref, that forces followup inplace elements to copy the data. + +2009-12-03 16:11:59 +0200 Stefan Kost + + * plugins/elements/gsttee.c: + tee: only message once per received buffer + Avoids checking for each source pad. The messages would be almost identical + anyway. + +2009-12-03 15:27:21 +0200 Stefan Kost + + * docs/random/ensonic/draft-registry-change-hooks.txt: + drafts: planning + +2009-12-03 16:05:03 +0200 Stefan Kost + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + tee: remove unused offset member + +2009-12-03 16:02:35 +0200 Stefan Kost + + * plugins/elements/gsttee.c: + tee: only notify alloc-pad property if changed. + +2009-12-02 13:29:28 +0100 Wim Taymans + + * gst/gstevent.h: + event: fix docs for _copy() + +2009-12-01 22:37:51 -0800 David Schleef + + * tools/gst-launch.c: + tools: Fix check for Windows + +2009-12-01 18:09:04 -0800 David Schleef + + * gst/gsttrace.c: + Make gcc inline assembly conditional on gcc + +2009-12-01 19:29:25 +0100 Edward Hervey + + * plugins/elements/gstqueue.c: + queue: Register debug funcptr only once. + Makes creating queue elements 3-4 times faster and avoids contention on the + global funcptr lock. + +2009-12-01 19:27:47 +0100 Edward Hervey + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + basesrc/basesink: Register debug funcptr only once. + Makes basesrc/basesink initialization 3-4 times faster and avoids + contention on the global funcptr lock + +2009-12-01 17:54:56 +0100 Edward Hervey + + * gst/gstghostpad.c: + gstghostpad: Register debug funcptr only once. + This makes ghostpad/proxypad creation 5 times faster and avoids contention + over the global funcptr lock. + I also moved the two class init down in the code to avoid having to forward + declare all the various functions. + +2009-12-01 17:54:14 +0100 Edward Hervey + + * gst/gstpad.c: + gstpad: Only register debug funcptr once. + This makes pad initialization 2 times faster and without any contention + over the debug funcptr global lock. + +2009-12-01 17:53:03 +0100 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.h: + gstinfo: API: Add GST_DEBUG_REGISTER_FUNCPTR method. + This is a variant of GST_DEBUG_FUNCPTR which does not return anything. + +2009-12-01 15:05:34 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 87bf428 to 47cb23a + +2009-12-01 14:08:29 +0100 Sebastian Dröge + + * configure.ac: + configure: Use new AG_GST_PLATFORM macro + +2009-12-01 14:10:59 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From da4c75c to 87bf428 + +2009-11-28 22:29:29 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: clip stepping boundaries + Rounding errors with the floating point rate could make it so that we + don't end up exactly at the required stepping duration. + Use the segment clipping boundaries, which are not subject to rate + adjustements, instead to detect when we reached the stepping duration. + Add some debug info related to going to the PAUSED state. + +2009-11-28 17:02:17 +0100 Wim Taymans + + * docs/manual/basics-bus.xml: + docs: fix another typo + +2009-11-28 15:40:30 +0100 Wim Taymans + + * docs/manual/intro-basics.xml: + docs: fix typo + +2009-11-27 18:54:33 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 53a2485 to da4c75c + +2009-11-27 13:42:36 -0300 Thiago Santos + + * gst/gstevent.c: + gstevent: fix docs + Fix flush stops docs, those are serialized, not out of bounds. + Probably a copy and paste mistake. + +2009-11-27 16:39:37 +0200 Stefan Kost + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + docs: fix broken xrefs + +2009-11-27 16:39:37 +0200 Stefan Kost + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/dataprotocol/dataprotocol.c: + * libs/gst/net/gstnetclientclock.c: + docs: fix broken xrefs + +2009-11-27 16:39:01 +0200 Stefan Kost + + * docs/libs/gstreamer-libs-docs.sgml: + docs: add missing section to libs-docs + +2009-11-27 14:18:02 +0200 Stefan Kost + + * gst/gstxml.c: + docs: make links work (needs recent gtk-doc) + +2009-11-27 14:17:35 +0200 Stefan Kost + + * gst/gstplugin.h: + docs: add missing parameter docs + +2009-11-27 14:16:54 +0200 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.h: + docs: enable docs for GstObjectClass to fix links + +2009-11-27 14:15:08 +0200 Stefan Kost + + * gst/gstobject.h: + gstobject: add FIXME-0.11 comments + +2009-11-25 18:25:01 +0200 Stefan Kost + + * gst/gstxml.c: + docs: better way to link class methods + +2009-11-25 18:24:16 +0200 Stefan Kost + + * gst/gstquery.c: + docs: use '*' instead of xxx to avoid creating a broekn xref + +2009-11-25 17:37:33 +0200 Stefan Kost + + * gst/gstinfo.h: + * gst/gstregistry.c: + * gst/gstutils.c: + * gst/gstvalue.c: + docs: fix more bogus xrefs + +2009-11-25 17:27:30 +0200 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstplugin.h: + docs: add docs for GstPluginFlags + This also makes links to them work. + +2009-11-25 15:39:44 +0000 Tim-Philipp Müller + + * docs/manual/advanced-interfaces.xml: + docs: improve GstMixer and GstTuner docs + Mention that elements implementing GstMixer and GstTuner need to be + in the right state before they can be used. Also mention GLib + functions for converting filenames to and from URIs. + Fixes #602877. + +2009-11-25 16:44:05 +0200 Stefan Kost + + * gst/gstbuffer.h: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstdebugutils.h: + * gst/gstfilter.c: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + * gst/gstpipeline.c: + * gst/gstplugin.h: + * gst/gstquery.h: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.h: + * gst/gstutils.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + docs: fix xrefs in docs + Fix typos in xrefs, links to non existing functions and rework plural forms. + +2009-11-25 14:41:26 +0200 Stefan Kost + + * gst/gstmacros.h: + docs: remove gtkdoc header as these things don't come up on our docs even + +2009-11-25 14:23:53 +0200 Stefan Kost + + * gst/gstregistry.c: + docs: add missing parameter doc string + +2009-11-25 14:21:50 +0200 Stefan Kost + + * gst/gstevent.h: + docs: document new event in enum + +2009-11-25 14:18:14 +0200 Stefan Kost + + * gst/gstutils.c: + docs: fix gtk-doc syntax for doc-blob start + +2009-11-23 11:34:07 +0100 Wim Taymans + + * gst/gstquery.c: + query: whitespace fixes + +2009-11-23 11:33:48 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: fix grammar + +2009-11-21 16:37:34 +0100 Jan Schmidt + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * win32/common/libgstbase.def: + basesrc: Add gst_base_src_new_seamless_segment() + Merge new function from resindvd into the primary GstBaseSrc for + starting a new seamless segment. + API: gst_base_src_new_seamless_segment() + +2009-11-20 16:00:47 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbytewriter.c: + bytewriter: fix compiler warning + Some gcc versions warn about bytewriter writing to memory accessed + via a const guint8 pointer, despite our explicit cast to guint8 *. + Work around that by using an intermediary variable. + Fixes #598526. + +2009-11-20 09:33:48 +0100 Sebastian Dröge + + * configure.ac: + check: Only check for gmp/gsl if building of tests is not disabled + +2009-11-19 19:00:05 +0100 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + basesink: Clamp the base time correctly in position reporting + When clamping the base time, correctly use 'now', instead of + '-now' - the intent is to prevent 'now-base' ever being + negative, which would cause a position report outside the segment. + Fixes: #602419 + +2009-11-09 10:52:42 -0800 David Schleef + + * gst/gstplugin.h: + gstplugin: Add C++ escape for gst_plugin_desc define + In order to properly export the gst_plugin_desc symbol + from DLLs in MSVC, it needs to be extern "C". + +2009-11-19 12:59:28 +0000 Tim-Philipp Müller + + * gst/parse/grammar.y: + parse/grammar.y: remove unused ERROR define + +2009-11-19 10:29:38 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 1861252 to 53a2485 + +2009-11-16 15:47:57 +0200 Priit Laes + + * libs/gst/check/Makefile.am: + check: fix symbol exporting when building under et_EE locale + [A-Z] regexp fails under et_EE locale because Z in Estonian alphabet is + located after S and therefore characters starting with 'TUV...' are not + in the range anymore. + Fixes bug #602093. + +2009-11-18 07:59:36 +0100 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + basesink: Handle the new sink-message event + +2009-11-18 07:52:24 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstutils.h: + * win32/common/libgstreamer.def: + event: API: Add sink-message event + gst_event_new_sink_message() + gst_event_parse_sink_message() + This event is used for sending a GstMessage downstream and synchronized + with the stream, to be posted by the sink once it reaches the sink. + Fixes bug #602275. + +2009-11-16 00:12:22 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/faq/gst-uninstalled: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + * gst/gstpluginloader.c: + * libs/gst/helpers/.gitignore: + * libs/gst/helpers/Makefile.am: + * libs/gst/helpers/gst-plugin-scanner.c: + * tests/check/Makefile.am: + * tests/examples/manual/Makefile.am: + plugin-scanner: rename plugin-scanner helper binary to gst-plugin-scanner + and install into a different directory $(libexecdir/gstreamer-0.10) so that + everything is versioned properly. + NOTE: run 'make clean' after updating; if you are running an uninstalled setup, + you will need to update your gst-uninstalled script (unless it's symlinked + to gstreamer core master) and exit/enter your uninstalled environment to get + the updated environment. If you are running an installed setup, you should + run 'make uninstall' before merging this change or remove the old + plugin-scanner binary manually. + Fixes #601698. + +2009-11-18 09:10:37 +0000 Tim-Philipp Müller + + * gst/gststructure.c: + Revert "structure: don't check type twice" + This reverts commit f864187bf5fdfaf71f2e038949e403a42e6daf0e. + Reverting this as it changes behaviour and the documentation is + ambiguous about whether the caller must check the type first or + not (call must check type vs. returns NULL if not a string). If + GLib has been compiled with G_DISABLE_CHECKS then g_value_get_string() + may return complete garbage even if the value does not contain + a string. Better play it safe, esp. since the extra check is just + an integer comparison. For fundamental types we could return values + from the GValue structure directly if we really wanted to bypass + the extra check. + +2009-11-17 17:06:08 +0200 Stefan Kost + + * gst/gststructure.c: + structure: don't check type twice + +2009-11-17 18:35:55 +0100 Sebastian Dröge + + * gst/gstevent.c: + event: Add step event quark + +2009-11-17 10:02:36 +0000 Tim-Philipp Müller + + * docs/faq/gst-uninstalled: + gst-uninstalled: add paths for gst-qa-system + +2009-11-17 09:06:48 +0000 Tim-Philipp Müller + + * common: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + docs: set GST_PLUGIN_SCANNER when calling gtkdoc-scangobj + Otherwise the docs build won't work properly + +2009-11-16 13:58:10 +0200 Stefan Kost + + * gst/gststructure.c: + structure: remove some blank lines (previous gst-indent failure) + +2009-11-16 13:53:44 +0200 Stefan Kost + + * gst/gststructure.c: + structure: use local variable earlier + +2009-11-16 13:49:32 +0200 Stefan Kost + + * gst/gststructure.c: + structure: don't check enum types twice. + G_VALUE_HOLDS_ENUM(value) is defined as G_TYPE_CHECK_VALUE_TYPE (value, + G_TYPE_ENUM). Just check for the right enum-type right away. + +2009-11-14 22:35:07 +0000 Jan Schmidt + + * tests/check/gst/gstsystemclock.c: + check: Add a debug status to the systemclock test + Next time it fails on a buildbot we can see which clock id + return it is getting. + +2009-11-16 18:25:45 +0100 Wim Taymans + + * docs/design/part-TODO.txt: + TODO: remove stepping from TODO + Remove the frame stepping API from the TODO list. + +2009-11-16 14:02:07 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix position reporting + Only update the current stream time after we checked if we got a new step + event. This improves the position reporting by the sink. + See #595958 + +2009-11-16 09:49:46 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * win32/common/libgstreamer.def: + utils: API: Add multiplication and addition functions for fractions + gst_util_fraction_add() + gst_util_fraction_multiply() + These work on plain integers instead of GValues to + keep the overhead as low as possible. + +2009-11-16 09:29:10 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * win32/common/libgstreamer.def: + gstutils: API: Add fraction helper functions + gst_util_greatest_common_divisor() + gst_util_double_to_fraction() + gst_util_fraction_to_double() + Using these instead of going over GValue has much lower overhead. + Also add float<->fraction transform functions for GValue. + +2009-11-13 15:45:52 +0200 Stefan Kost + + * gst/gststructure.c: + debug: add more debug logging to help tracking parsing errors + +2009-11-13 11:42:02 +0100 Ole André Vadla Ravnås + + * gst/gstminiobject.c: + * tests/check/gst/gstminiobject.c: + miniobject: avoid race when recycling buffers + Avoid a race where a miniobject is recycled and quickly freed, which causes the + g_type_free_instance() to be called on the same object twice. + Ref the object before calling the finalize method and check if we still need to + free it afterward. + Also add a unit test for this case. + Fixes #601587 + +2009-11-12 17:02:40 +0200 Stefan Kost + + * gst/gstutils.c: + whitespace: remove blanks in doc-comment + +2009-11-06 15:42:57 +0300 Руслан Ижбулатов + + * gst/gstregistry.c: + registry: Import _priv_gst_dll_handle into gstregistry.c + Fixes bug #601668. + +2009-11-12 14:10:06 +0300 Руслан Ижбулатов + + * tests/examples/manual/Makefile.am: + tests: Do not list libgstcheck as a requirement for tests/examples/manual + Fixes bug #601669. + +2009-11-11 17:12:19 +0000 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + basesink: Fix treating base_time as unsigned in position calculation + Element base_time is a signed quantity, which leads to basesink returning + a position of 0 when dealing with a negative base time - which are quite + legal when clocks (such as the audio clock) are close to 0. + This doesn't manifest in normal pipelines, of course - but can happen + (at least) when manually setting the base time on a pipeline. + +2009-11-10 18:03:43 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstregistry.c: + * gst/gstregistry.h: + * win32/common/libgstreamer.def: + registry: API: Add gst_{default,}_registry_get_feature_list_cookie() + This returns the internal feature list cookie, which changes every + time a feature is added or removed. This can be used by elements + to check if they should update their cached feature lists. + +2009-11-10 11:55:34 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: fix printf format + Cast the variable to gint to conform to the printf format used. + It is casted rather than changing the format because the + message is created with a cast to gint too. + +2009-11-10 10:10:56 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: avoid crashing due to negative percent + queue2 would crash when using small buffer sizes because + it would overflow when calculating the percentage, resulting + in the buffering GstMessage not being created and trying to be + used. This patch uses a gint64 instead of a gint to do the + percentage math, making it harder to overflow. + +2009-11-10 09:52:30 -0300 Thiago Santos + + * plugins/elements/gstqueue2.c: + queue2: Fix small doc typo + +2009-11-10 00:57:00 +0000 Tim-Philipp Müller + + * gst/gstregistrychunks.c: + registrychunks: fix compilation with debugging disabled + Add ugly ifdef to fix unused variable warning when compiling with + debug logging disabled. + +2009-11-09 16:20:52 +0200 Stefan Kost + + * docs/random/ensonic/draft-bufferpools.txt: + * docs/random/ensonic/draft-registry-change-hooks.txt: + planning: add thoughts about foreign registry cache updates + +2009-11-09 14:55:54 +0200 Stefan Kost + + * tools/gst-inspect.c: + inspect: allow to get plugin-install-info for all installed plugins + If no plugin is given, print the info for all plugins. This can be used as a + starting point to generate a profile about what the gstreamer installation can + potentialy handle (e.g. for MTP or DLNA). + +2009-11-09 12:42:35 +0100 Wim Taymans + + * docs/manual/highlevel-components.xml: + docs: don't forget to unref the pad + +2009-11-07 20:22:49 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: wake up less often to check if we've been interrupted + Check if we've been interrupted only four times per second instead + of twenty times per second, to wake up the cpu less often and + save power (see bug #600922). + +2009-11-05 21:18:26 +0000 Tim-Philipp Müller + + * gst/gstconfig.h.in: + gstconfig.h: add define to force printf format checking for debug messages + Force printf format checking for debug messages if GST_DISABLE_PRINTF_EXTENSION + is defined. This is useful to quickly check code for printf format mismatches + in debugging messages that would usually not be caught (with glibc+gcc and + printf extensions being used). + To use: make clean; make CFLAGS='-g -O2 -DGST_DISABLE_PRINTF_EXTENSION' + +2009-11-05 21:09:28 +0100 Edward Hervey + + * tests/check/Makefile.am: + * tests/examples/manual/Makefile.am: + tests: Make sure we use the local libgstbase and not a stray outside one. + Theoretically we should also do this for all local libraries to make sure + we don't test with a 'stray' outside library. + +2009-11-05 18:36:38 +0000 Tim-Philipp Müller + + * gst/gstvalue.h: + docs: fix typo + +2009-11-05 15:59:31 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglist: avoid looking up GstTagInfo twice in a row + Pass the info structure to our internal function if already available. + Also clean up warnings for unknown tags. + +2009-11-05 18:55:30 +0100 Edward Hervey + + * gst/gstregistrychunks.c: + gstregistrychunks: We're certain plugin_name is an intern string. + The only place this method is called from creates the plugin_name argument + with g_intern_string(). + Shaves off 1% from registry loading. + +2009-11-04 19:33:58 +0000 Bastien Nocera + + * plugins/elements/gstqueue2.c: + implement buffering-left argument to buffer messages + Using the current fill level of the queue, and the average input + rate, we can determine how long it will take to finish downloading + the whole stream to the temporary file. + Fixes #600726 + +2009-11-05 15:13:04 +0100 Wim Taymans + + * gst/gstquery.h: + query: whitespace fixes + +2009-11-05 14:02:28 +0100 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: fix locking + +2009-11-05 14:29:50 +0200 Stefan Kost + + * gst/gstghostpad.c: + ghostpad: don't release mutex twice + +2009-11-05 14:29:12 +0200 Stefan Kost + + * gst/gstghostpad.c: + ghostpad: skip type check in internal api + +2009-11-05 12:36:10 +0100 Wim Taymans + + * gst/gstpad.h: + pad: indentation fix + +2009-11-05 12:54:32 +0200 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstreamer.def: + pad: rename new api from _refed to _reffed. + Due to popular demand rename the new api as we still can. + API: gst_pad_get_caps_reffed(), gst_pad_peer_get_caps_reffed() + +2009-11-04 22:42:52 +0200 Stefan Kost + + * gst/gstelement.c: + element: access padtemplate list directly to avoid call and type check. + +2009-11-04 18:58:26 +0100 Sebastian Dröge + + * gst/gstevent.c: + event: Add a FIXME 0.11 for having flush events that don't reset running time + +2009-11-04 17:52:21 +0000 Jan Schmidt + + * gst/gstregistrychunks.c: + registrychunks: Fix a printf compile warning on 64-bit platforms + +2009-11-04 17:15:59 +0100 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: Make sure that nobody sets the proxypad or ghostpad itself as target + Doing this will lead to very interesting crashes, like stack overflows. + +2009-11-04 11:35:46 +0000 Jan Schmidt + + * gst/gstpluginloader.c: + * gst/gstregistrychunks.c: + plugin loader: Don't fail after a short read/write + The logic to handle short reads/writes was incorrect, causing the + packet handler to attempt to handle incomplete packets. + Grow the packet transmit buffer in proportion to observed usage, + causing fewer reallocs. + Add some more debug in the registry chunks code. + +2009-11-04 01:51:38 +0000 Jan Schmidt + + * gst/gstpluginloader.c: + plugin loader: Don't crash on bogus plugin details + When invalid registry chunks are received from the child, and parsing + fails, don't access an invalid plugin pointer. Instead attempt to + figure out which plugin caused the problem and blacklist it. + +2009-11-04 01:54:36 +0000 Jan Schmidt + + * tools/gst-indent: + gst-indent: Use the same logic to find gnuindent as the git hook + +2009-11-03 17:30:14 +0200 Stefan Kost + + * plugins/elements/gstqueue2.h: + build: include stdio.h for FILE + +2009-11-03 01:18:42 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + docs: add another example to the gst-launch man page + Add an example that shows how to refer to specific pads by name + when constructing a pipeline string. Fixes #600382. + +2009-11-02 08:48:51 +0000 Tim-Philipp Müller + + * gst/gsttypefind.c: + gsttypefind: avoid one more run-time type check + +2009-11-02 09:22:37 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: API: Add gst_structure_id_has_field{,_typed} + +2009-11-02 08:28:20 +0100 Edward Hervey + + * gst/gsttypefind.c: + gsttypefind: Use _CAST variants when the type has alredy been checked. + This avoids checking the type n_typefinders * 4 times when loading the + registry. + +2009-11-01 11:24:40 +0100 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: Implement iterate internal links + The internally linked pad of the ghost pad is its + proxy pad, which is the pad that is linked to the ghost + pads target. + +2009-10-31 16:56:17 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parser: Make sure that signal user data is freed by setting a GClosureNotify + ...instead of using a second mechanism and storing the user data + inside the GObjects qdata. + +2009-10-31 16:49:03 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parser: Use GSlice for allocating the structs + +2009-10-31 16:43:26 +0100 Sebastian Dröge + + * gst/parse/grammar.y: + parser: Always get DelayedLink information from the objects qdata + This makes sure that it is always valid. + +2009-10-31 09:48:19 +0100 Edward Hervey + + * po/POTFILES.in: + po: queue2 has moved to core + +2009-10-29 11:41:33 +0100 Sebastian Dröge + + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + queue2: Add to the docs + +2009-10-29 11:38:21 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Use "Queue 2" as long name + +2009-10-29 11:35:08 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Use GST_BOILERPLATE_FULL() and add pad templates/set details in base_init + +2009-10-29 11:30:57 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Use gst_element_class_set_details_simple() + +2009-10-29 11:30:11 +0100 Sebastian Dröge + + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Integrate into coreplugins + +2009-10-29 11:21:36 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + * plugins/elements/gstqueue2.h: + queue2: Move struct declarations to a separate header + +2009-10-29 11:18:20 +0100 Sebastian Dröge + + * plugins/elements/gstqueue2.c: + queue2: Move queue2 to gstreamer coreplugins + Fixes bug #599996. + +2009-10-28 00:59:35 +0000 Tim-Philipp Müller + + * gst/playback/gstqueue2.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 + + * gst/playback/gstqueue2.c: + queue2: add custom acceptcaps function + +2009-08-06 12:18:36 +0200 Mark Nauwelaerts + + * 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-07-14 17:03:35 +0200 Wim Taymans + + * 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-10 21:01:39 +0100 Wim Taymans + + * 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 19:49:46 +0100 Wim Taymans + + * 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-03-20 14:17:19 +0100 LRN + + * gst/playback/gstqueue2.c: + win32: fix seeking in large files + Fix Seeking in large files by using the 64-bit seek functions. + Fixes #576019 + +2008-08-07 15:58:58 +0000 Frederic Crozat + + 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 + * 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-07-10 21:06:06 +0000 Stefan Kost + + 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-06-24 16:22:45 +0000 Stefan Kost + + 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-04-11 01:25:01 +0000 Wim Taymans + + 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:40:17 +0000 Wim Taymans + + 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-02 11:08:05 +0000 Wim Taymans + + 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-03-24 14:08:22 +0000 Wim Taymans + + 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-22 15:00:53 +0000 Sebastian Dröge + + 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. + +2007-12-14 18:46:12 +0000 Wim Taymans + + 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 09:24:55 +0000 Wim Taymans + + 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-11-30 17:47:15 +0000 Wim Taymans + + 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-16 15:44:48 +0000 Wim Taymans + + 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-10-15 11:38:39 +0000 Wim Taymans + + 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-09-21 14:37:26 +0000 Wim Taymans + + 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-17 17:24:55 +0000 Jan Schmidt + + 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 + + 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-08-10 10:08:05 +0000 Tim-Philipp Müller + + gst/: Printf format fixes (#465028). + Original commit message from CVS: + * gst/playback/gstqueue2.c: + * gst/videorate/gstvideorate.c: + Printf format fixes (#465028). + +2007-06-28 11:06:56 +0000 Wim Taymans + + 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 + + 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-16 03:42:14 +0000 David Schleef + + 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-13 18:20:57 +0000 Edward Hervey + + 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-12 08:38:06 +0000 Wim Taymans + + 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 + * 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 + + 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 + * 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 09:11:27 +0000 Wim Taymans + + 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 + + gst/playback/gstqueue2.c: Add pull based scheduling and fix some deadlocks. Fixes #444523. + Original commit message from CVS: + Patch by: Thiago Sousa Santos + * 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 + + 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-05 17:02:13 +0000 Wim Taymans + + 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:14:23 +0000 Thiago Sousa Santos + + gst/playback/gstqueue2.c: Add support for filebased buffering. Fixes #441264. + Original commit message from CVS: + Based on patch by: Thiago Sousa Santos + * 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-05-17 15:22:44 +0000 Wim Taymans + + 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 13:36:11 +0000 Wim Taymans + + 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 + + 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. + +2009-10-28 22:03:44 -0700 David Schleef + + * gst/parse/grammar.y: + parse: Fix memleak of unused delayed links + Attach the DelayedLink structure to the element, so that when + the element is disposed, the DelayedLink is freed. + +2009-09-09 15:37:11 -0500 Rob Clark + + * gst/gstpad.c: + pad: make _fixate_caps() also truncate when needed + The default gst_pad_fixate_caps() previously would only fixate each individual + struct. In case there are multiple structs, the resulting caps would still not + be fixed. In the spirit of how individual structs are fixated, this patch + changes gst_pad_fixate_caps() to remove all but the first struct. + Fixes #595886 + +2009-09-21 11:44:13 +0200 Wim Taymans + + * gst/gstinfo.h: + info: fix docs + +2009-10-28 09:26:32 +0100 Edward Hervey + + * gst/gstbus.c: + * gst/gstelementfactory.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstobject.c: + * gst/gstplugin.c: + * gst/gstpluginloader.c: + * gst/gstregistry.c: + * gst/gstregistrychunks.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttypefind.c: + * gst/gstxml.c: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstlfocontrolsource.c: + optimisation : Use g_object_newv where possible. + This avoids: + * triple-checking for the GType when type-checking is enabled (see #597260) + * Avoids going through an expensive no-argument checking which landed in + glib-2.22 + * Avoids going through 2 extrac functions (g_object_new -> g_object_new_valist) + +2009-10-28 10:15:12 +0200 Stefan Kost + + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + docs: include annotation glossary to have working links. + +2009-10-28 10:14:36 +0200 Stefan Kost + + * gst/gst.c: + annotations: add annotations to gst_init_check too + +2009-10-28 09:58:52 +0200 Stefan Kost + + * gst/gst.c: + docs: tell more about what happens in gst_init. + Add links to gst_update_registry and the env-vars. + +2009-10-28 09:21:01 +0200 Stefan Kost + + * gst/gst.c: + docs: remove reference to OGI and rephrase sections docs + The OGI links are dead, so remove them. Also remove the paragraph that pointed + to OGI and DS. Only mentioning DS there made it a but pointless. Add a generic + paragraph instead that tells a bit about the usecases gstreamer covers. + +2009-10-28 00:29:30 +0000 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstghostpad.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstregistry.c: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gstxml.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstdataqueue.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/indexers/gstmemindex.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 tenth of a polar bear. + +2009-10-28 00:07:48 +0000 Tim-Philipp Müller + + * plugins/elements/gstcapsfilter.c: + capsfilter: sprinkle some GST_DEBUG_FUNCPTR + +2009-10-27 15:47:39 +0100 Wim Taymans + + * docs/design/part-trickmodes.txt: + design: add some ideas for SKIP mode trickmodes + +2009-10-23 10:20:02 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: buffering is implemented now + +2009-10-22 21:24:24 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: make sure percent increases + Keep track of the last posted percent message and make sure the next percent + messages are strictly increasing. + +2009-10-22 16:38:12 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: refactor buffering code + Move the buffering update code to a separate function so that we can call it + when the buffering state changes due to EOS. + Avoid dividing by 0. + +2009-10-22 14:09:01 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: add buffering support + Add support for buffering mode where we post BUFFERING messages based on the + level of the queues. It currently operates on the first queue that goes over or + under the high/low thresholds. + +2009-10-22 14:07:31 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: don't check visible items in buffering + In buffering mode we want to ignore the max visible items to decide when the + queue is filled. Instead, we only look at the number of bytes and/or time in the + queue. + +2009-10-21 11:30:40 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: hook up low/high percent + Hook up the low/high percent properties for the buffering mode. + +2009-10-21 11:24:47 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: hook up property for buffering + +2009-10-22 15:21:39 +0100 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: small cleanups + Remove unused variable to avoid confusion + Fix some typo + +2009-10-22 09:41:52 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: add FIXME for wrong code + Needs further investigation + +2009-10-21 14:20:29 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: fix debug output + +2009-10-21 14:15:05 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: avoid shadowing function argument + Don't shadow the sq argument in the underrun_cb function but use + a different variable name to iterate the other queues. + Use the same variable name in the overrun_cb function. + +2009-10-21 14:12:12 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: make queue arg explicit + Make the queue argument to IS_FILLED explicit + +2009-10-21 11:17:08 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: fix properties + Fix properties, make the extra-size properties as not implemented. + +2009-10-25 21:35:09 +0200 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: allow to hide/show pad status with graphdetails flag + +2009-10-24 13:14:25 +0200 Sebastian Dröge + + * libs/gst/base/gsttypefindhelper.c: + typefindhelper: Remove obsolete FIXME + It's not necessary (and not a good idea) to cache the typefind factory + list anymore. + +2009-10-24 11:58:25 +0200 Sebastian Dröge + + * gst/gstregistry.c: + * gst/gstregistry.h: + registry: private is a C++ keyword, don't use it + ...otherwise C++ compilers will complain when including gstregistry.h + +2009-10-24 10:21:30 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstpluginfeature.c: + docs: add Since tag to docs for new API + And tell gtk-doc that GstRegistryPrivate is private. + +2009-10-21 09:48:41 +0200 Edward Hervey + + * gst/gstregistry.c: + * gst/gsttypefindfactory.c: + * libs/gst/base/gsttypefindhelper.c: + typefind: Keep typefind factories sorted in the registry. Fixes #599147 + This avoids having to do the sorting everytime we use typefind + The behaviour of gst_type_find_factory_get_list has subtlely changed + in the sense that the order was previously undefined, whereas now + it returns them sorted by rank and then by name. + +2009-10-21 09:45:47 +0200 Edward Hervey + + * gst/gstregistry.c: + registry: Cache element and typefind factories. Fixes 598896 + This avoids unneeded list/filtering if the registry hasn't changed + +2009-10-21 09:40:49 +0200 Edward Hervey + + * docs/gst/gstreamer-sections.txt: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * win32/common/libgstreamer.def: + gstpluginfeature: API : new gst_plugin_feature_list_copy() method + This allows copying AND incrementing the refcount at the same time, + avoiding a double iteratio of the GList + +2009-10-24 10:05:59 +0200 Edward Hervey + + * gst/gstregistry.c: + * gst/gstregistry.h: + gstregistry: Add a cookie for detecting feature list changes + We also create a private structure, since we will need to add more + data there in following patches. + +2009-10-23 13:19:04 -0400 Wim Taymans + + * gst/gstmessage.h: + message: don't use typechecking cast macros + Simply use casting macros for accessing the message fields like we do for + buffers and events. Avoids some costly typechecking that does not really buy us + much. + +2009-10-23 13:13:52 -0400 Wim Taymans + + * gst/gstmessage.c: + Revert "gstmessage: Avoid expensive src/type/timestamp fetch." + This reverts commit 61cf93a334b79a2d8493e531cc44ba45a4209805. + +2009-10-23 17:51:27 +0200 Edward Hervey + + * gst/gstmessage.c: + gstmessage: Avoid expensive src/type/timestamp fetch. + If we've already checked that we have a valid message, use the entries + directly. + +2009-10-23 17:47:43 +0200 Edward Hervey + + * gst/gstcaps.c: + gstcaps: Use inlined version of _is_any()/_is_empty() + CAPS_IS_ANY and CAPS_IS_EMPTY are the equivalent of their gst_caps_* + counterpart except that they avoid the typechecking and are inlined. + CAPS_IS_EMPTY_SIMPLE only checks for empty caps (without checking if + the caps is ANY). + +2009-10-22 16:42:13 -0400 Wim Taymans + + * docs/design/part-TODO.txt: + TODO: add item to TODO list + We currently do a little too much work when we push the first buffer around + resulting in excessive caps checking. We can probably make this a little less + expensive. + +2009-10-22 12:52:46 +0100 Jan Schmidt + + * gst/gstpipeline.c: + gstpipeline: Simplify base time checking slightly + Simplify checking and distribution of the base time - don't re-check + the value of a local variable that was set 3 lines earlier. + +2009-10-22 13:15:15 +0200 Edward Hervey + + * gst/gsturi.c: + gsturi: Optimisation: Avoid type-checking in sorting method. + We already know the list only contains plugin features + +2009-10-22 13:13:56 +0200 Edward Hervey + + * gst/gsturi.c: + gsturi: Optimisation : Cast when we're sure of the type. + Also directly access GstElementFactory->uri_type instead of going + through a function that will (once again) check whether it's a + GstElementFactory + +2009-10-22 12:33:37 +0200 Edward Hervey + + * tests/check/elements/fakesink.c: + tests/fakesink: Add some debugging + +2009-10-22 12:33:01 +0200 Edward Hervey + + * tests/check/elements/fakesink.c: + tests/faeksink: Lower the number of threads to avoid timeouts + We just end up with way too much contention in glib otherwise. + +2009-10-19 09:06:16 +0200 Edward Hervey + + * gst/gstregistry.c: + gstregistry: Use hash table when finding a feature. Fixes #598895 + +2009-10-21 16:26:01 -0400 Wim Taymans + + * plugins/elements/gsttee.c: + tee: implement custom acceptcaps function + Implement a custom acceptcaps function on the sinkpad. We can accept any caps as + long as it is accepted by all downstream peer elements. + +2009-10-21 13:38:57 -0400 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: avoid lock for taking the counter + The counter for incomming data is already protected with the STREAM_LOCK so we + don't need to add another lock around it. + +2009-10-20 23:28:54 -0400 Wim Taymans + + * gst/gstregistry.c: + * gst/gstregistry.h: + registry: hash the plugin basename + Maintain a hashtable of the plugin basename. We can then use this + hashtable to speedup the search for an existing plugin and avoid + a whole lot of strcmp calls. + +2009-10-20 23:27:41 -0400 Wim Taymans + + * gst/gstregistrychunks.c: + registry: speed up _strlen + Make the _strlen function a little tighter + +2009-10-20 21:43:58 -0400 Wim Taymans + + * gst/gstregistry.c: + registry: name is never NULL + When looking up a feature by name, we never call this internal + function with NULL so we don't have to check for it. + +2009-10-20 21:39:11 -0400 Wim Taymans + + * gst/gstregistry.c: + registry: refactor plugin lookup + We keep lookup plugins by their basename. Avoid creating a basename + from a filename if we can. + +2009-10-20 21:01:55 -0400 Wim Taymans + + * gst/gstregistry.c: + registry: do quick check for . files + Do a quick check for . files before calling the strcmp functions + +2009-10-20 12:21:09 -0700 Michael Smith + + * tests/check/gst/gstxml.c: + Remove executable bits on xml unit test. + +2009-10-19 16:47:10 +0200 Benjamin Otte + + * gst/gstcaps.c: + docs: Fix docs for gst_caps_set_simple() + +2009-10-19 13:02:30 +0100 Jan Schmidt + + * gst/gstcaps.c: + docs: Modify docs string slightly. + Apparently starting the last line of a docs string with 'returns' both + confuses and enrages gtk-doc. Use a slightly different wording instead. + +2009-10-19 12:29:35 +0100 Jan Schmidt + + * gst/gstpluginloader.c: + pluginloader: When a plugin is blacklisted, output a GST_ERROR line. + +2009-10-19 13:30:10 +0200 Edward Hervey + + * tools/gst-inspect.c: + tools/gst-inspect: Check we're not handling NULL pointers. + +2009-10-19 13:29:40 +0200 Edward Hervey + + * tools/gst-inspect.c: + tools/gst-inspect: Remove dead assignment + +2009-10-14 10:54:32 +0200 Peter Kjellerstedt + + * gst/gsttrace.h: + trace: Do not poison gst_trace_add_entry() + Since gst_trace_add_entry() is a macro, gcc will barf when it is + defined in case it has been poisoned due to trace support being + disabled. + +2009-10-18 23:18:58 +0300 Stefan Kost + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: just cast in internal API where we have checked parameters already + +2009-10-18 23:15:07 +0300 Stefan Kost + + * libs/gst/controller/gstcontroller.c: + controller: use g_slice for controlled property structures + Use g_slide instead of nomal g_new, Also don't init struct with 0 as we need to + init it anyway with the real values. + Also join the 3 flags checks into one. + +2009-10-18 17:17:17 +0200 Edward Hervey + + * libs/gst/base/gsttypefindhelper.c: + libs/base/typefindhelper: Remove useless typechecking in tight loop + The list against which we run the comparefunc will only contain + GstPluginFeature, therefore remove the 6 expensive type checks we do + for every single comparision. + +2009-10-16 12:39:54 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: fix typo in docs + +2009-10-16 09:43:08 +0200 Edward Hervey + + * win32/common/libgstreamer.def: + win32: Add new API symbol + +2009-10-16 10:13:53 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 85d1530 to 0702fe1 + +2009-10-07 15:32:18 +0200 Benjamin Otte + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + Improve caps setters API + This patch adds gst_caps_set_value() and allows gst_caps_set_simple() to + work on non-simple caps. See the API documentation for the functions + about what they do. + The intention of these changes is to ease working with caps in caps + transform functions. An example for this would be ffmpegcolorspace, + where the caps transform function could be changed to look roughly like + this (pseudocode ahead): + result = gst_caps_copy (template_caps); + value = gst_structure_get_value (gst_caps_get_structure (caps, 0), + "widh"); + gst_caps_set_value (result, value); + /* same for height, framerate and par */ + return caps; + which is much cleaner and easier to understand than the current code. + https://bugzilla.gnome.org/show_bug.cgi?id=597690 + +2009-10-02 10:15:55 +0200 Benjamin Otte + + * tests/examples/xml/Makefile.am: + Add XML_LIBS when building tests that use xml-specific functions + +2009-10-15 16:35:59 +0100 Jan Schmidt + + * 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 16:30:36 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: fix race in PLAYING->PAUSED->PLAYING + When we quickly switch from PLAYING to PAUSED and back to PLAYING it's possible + in some cases that the task refuses to start, This is because when we go to + PAUSED, we unschedule the clock timeout, which could return UNSCHEDULED when + we're back to PLAYING, causing the task to PAUSE again with a wrong-state. + This patch checks if we are running when we return with an UNSCHEDULED return + value and if we are, try to create a new buffer. + Fixes #597550 + +2009-10-15 12:16:05 +0300 Stefan Kost + + * gst/gstpreset.c: + docs: clarify preset api docs + +2009-10-14 17:57:40 +0300 Stefan Kost + + * libs/gst/controller/gstcontroller.c: + docs: fix controller sections docs + +2009-10-14 10:40:50 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 6380d4b to 85d1530 + +2009-10-14 10:16:31 +0200 Peter Kjellerstedt + + * gst/gstiterator.c: + iterator: Fix a documentation typo + +2009-10-14 08:57:52 +0200 Sebastian Dröge + + * Makefile.am: + build: ...and add missing endif + +2009-10-14 08:57:04 +0200 Sebastian Dröge + + * Makefile.am: + build: Also don't run make check-exports if debugging is disabled + +2009-10-14 08:50:31 +0200 Peter Kjellerstedt + + * Makefile.am: + build: Only run make check-exports if no public API was disabled + Fixes bug #598297. + +2009-10-14 08:30:07 +0200 Sebastian Dröge + + * gst/gstobject.c: + gstobject: Replace recursive gst_object_has_ancestor() with an iterative version + This is slightly more efficient because the compiler can't do tail + recursion here and has to keep all stack frames. + Not that efficiency is that important here but I already had + the iterative version somewhere else and both are easy to read. + +2009-10-14 08:29:32 +0200 Sebastian Dröge + + * tests/check/gst/gstobject.c: + gstobject: Add simple unit test for gst_object_has_ancestor() + +2009-10-13 19:12:50 +0300 Tommi Myöhänen + + * libs/gst/net/gstnetclientclock.c: + netclientclock: fix timestamp comparission, Fixes #597407 + +2009-10-12 21:51:55 +0100 Jan Schmidt + + * tests/check/gst/gstobject.c: + check: Disable the test_fail_abstract_new() test entirely on OS/X + Fixes a compiler warning from the function being compiled but not + used. + +2009-10-12 14:57:35 +0100 Jan Schmidt + + * gst/gst_private.h: + debug: Mark the GST_POLL symbol as extern to avoid multiply-defined error + +2009-10-12 14:47:30 +0100 Jan Schmidt + + * common: + Update common to 6380d4b370f078f0cca7240428ea9f6639571ff5 + +2009-10-12 14:24:04 +0100 Jan Schmidt + + * gst/gst_private.h: + * gst/gstinfo.c: + gstpoll: Make the new GST_POLL debug completely private + Make the GST_POLL debug category symbol private to libgstreamer, as + there should be no external users of it. + +2009-10-12 14:22:34 +0100 Jan Schmidt + + * tests/check/gst/gstobject.c: + checks: Disable a fairly silly gstobject test on OS/X + This test used to SIGBUS on OS/X but now SIGSEGV's instead on + Snow Leopard. It's not worth the effort to figure out which platform + should produce which error for what is fundamentally a pretty silly + test, so just disable it on OS/X + +2009-10-12 13:50:51 +0200 Edward Hervey + + * libs/gst/check/libcheck/check_pack.c: + libs/gst/check: Make writing threadsafe. Backported from libcheck trunk + +2009-10-12 13:49:35 +0200 Edward Hervey + + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + libs/gst/check: Run gst-indent on libcheck. + +2009-10-12 12:02:34 +0200 Edward Hervey + + * gst/gstpluginloader.c: + gstpluginloader: Don't wait forever on gst_poll_wait. + This allows the macosx versions to properly error out when fds are closed. + This is only a temporary fix until the pluginloader is switched to not + use GstPoll but GIOChannels. + +2009-10-12 12:01:59 +0200 Edward Hervey + + * gst/gstpoll.c: + gstpoll: Only take into account active fds + This is needed so that select properly errors out on macosx (sigh) + +2009-10-12 10:07:03 +0200 Edward Hervey + + * gst/gstpoll.c: + gstpoll: Add some debugging statements + +2009-10-12 10:01:01 +0200 Edward Hervey + + * gst/gstpoll.c: + gstpoll: Use the error fdset when using select/pselect. + This is needed to properly detect fds that are closed or that got + an error + +2009-10-12 09:50:46 +0200 Edward Hervey + + * gst/gstpoll.c: + gstpoll: Don't use poll on systems with broken poll + +2009-10-12 09:50:00 +0200 Edward Hervey + + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gstpoll.c: + gst: Add debugging category GST_POLL for gstpoll + +2009-10-12 09:47:59 +0200 Edward Hervey + + * configure.ac: + configure.ac: Detect broken poll() + +2009-10-09 17:44:28 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: lets keep -1 for segmenst as they are guint64 and not GstClockTime + +2009-10-09 17:11:27 +0300 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: use GST_CLOCK_TIME_NONE and GST_CLOCK_TIME_IS_VALID more + +2009-10-08 23:10:40 +0100 Jan Schmidt + + * gst/gstpluginloader.c: + pluginloader: Fix valgrind warnings by zeroing padding bytes. + +2009-10-08 17:19:38 +0100 Jan Schmidt + + * tests/check/libs/bytereader.c: + check: Hopefully fix an 'may be used uninitialized' warning on OS/X + +2009-10-08 16:21:45 +0100 Jan Schmidt + + * gst/gstregistrychunks.c: + registrychunks: Fix a debug format string harder to satisfy OS/X's gcc. + +2009-10-08 16:05:08 +0100 Jan Schmidt + + * gst/gstregistrychunks.c: + registrychunks: Fix format string for debug error message. + +2009-10-08 15:21:48 +0100 Jan Schmidt + + * gst/gstpluginloader.c: + pluginloader: Move stdin and stdout out of harm's way + In the plugin loader subprocess, move stdin and stdout to new fd's + so that plugins printing things during plugin init or (*gasp*) + possibly reading from stdin don't interfere with the data sent to + and from the parent. + +2009-10-08 11:17:14 +0100 Jan Schmidt + + * docs/plugins/Makefile.am: + plugin docs: Add GST_PLUGIN_SCANNER env var to the inspect environment + +2009-10-08 10:59:15 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From 37f898b to a3e3ce4 + +2009-10-08 10:39:28 +0100 Jan Schmidt + + * tests/check/libs/.gitignore: + gitignores: Ignore the bytewriter check binary + +2009-10-08 10:36:56 +0100 Jan Schmidt + + * gst/gstregistry.c: + registry: Fix error handling in the registry loader + When the plugin-scanner load fails (because the helper can't be + spawned), make sure to load the plugin that failed in-process, so + that all plugins do get loaded. + +2009-10-08 10:26:27 +0100 Jan Schmidt + + * tests/examples/manual/Makefile.am: + check: Fix test run in tests/examples/manual + Add the GST_PLUGIN_SCANNER env var to the check environment here too + so that it doesn't fail when no installed scanner is available. + +2009-10-08 09:34:47 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + gstinfo: add back fix that shouldn't have been reverted + +2009-10-08 10:47:44 +0300 Stefan Kost + + * plugins/elements/gstqueue.c: + queue: more queue optimizations + Split gst_queue_locked_enqueue() into variant for buffer and event to get rid of + the if() and make the code more readable (constant boolean parameters are never + nice). Removes the if (item) checks as we dereference the pointer before anyway. + Also apply the same idea of reusing the previous knowledge in + gst_queue_locked_dequeue to remove more type checks. + +2009-10-08 10:51:49 +0300 Stefan Kost + + * plugins/elements/gstmultiqueue.c: + multiqueue: split gst_multi_queue_item_new + Split gst_multi_queue_item_new into buffer and event variant to make save an if + and make code more readable. + +2009-10-08 08:55:59 +0200 Edward Hervey + + * plugins/elements/gstfilesrc.c: + plugins/gstfilesrc: Make a fast-path for length == 0 buffer creation. + If the requested length is 0, we don't need to read anything from the file. + +2009-10-08 08:55:23 +0200 Edward Hervey + + * libs/gst/check/gstconsistencychecker.c: + gst/check/consistencychecker: Check type of miniobject in probe + +2009-10-08 08:53:54 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + gst/base/basesink: Remove dead assignment. + The code was previously: + * checking if ret was != OK + * .. but if it was FLOW_STEP, swith it to OK + * .. and then not using ret + Instead we just make it more compact by checking if it's OK or STEP. + +2009-10-08 08:53:26 +0200 Edward Hervey + + * gst/gstobject.c: + gstobject: Remove dead assignment. + object is no longer used after that line + +2009-10-08 08:52:18 +0200 Edward Hervey + + * gst/gstindex.c: + gstindex: Make sure writer is non-NULL. + Fixes the NULL dereference a few lines lower (where it gets the object type). + +2009-09-29 08:13:40 +0200 Edward Hervey + + * tests/benchmarks/gstbufferstress.c: + benchmarks: Clean up gstbufferstress. + +2009-10-08 02:42:16 +0100 Jan Schmidt + + * tests/benchmarks/complexity.c: + * tests/benchmarks/mass-elements.c: + benchmarks: Fix the complexity and mass-elements benchmarks + +2009-10-08 02:20:51 +0100 Jan Schmidt + + * tests/check/gst/gstchildproxy.c: + checks: Fix string leaks in the new childproxy test + +2009-10-08 02:03:08 +0100 Jan Schmidt + + * gst/gstplugin.c: + plugin: Ignore an empty dependency list. + If a plugin registers an empty dependency set, just ignore it rather + than serialising and checking an empty set. + +2009-10-08 02:01:54 +0100 Jan Schmidt + + * gst/gstregistrychunks.c: + registrychunks: Fix off-by-one error. Improve debug. + Fix an off-by-one error in the size guard for unpack_element, and + improve various debug statements in the failure paths. + Also, swap some g_new0 to g_malloc0 for the fun of it. + +2009-10-07 16:02:58 -0700 Michael Smith + + * plugins/elements/gstfilesink.c: + filesink: Use _wfopen on win32 to open files with non-ascii filenames correctly. + +2009-10-07 23:31:20 +0100 Tim-Philipp Müller + + * gst/gstpad.c: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + docs: fix Since: tags in docs for newly-added API + +2009-10-08 00:08:47 +0300 Stefan Kost + + * gst/gstinfo.c: + info: revert two of the changes + It only needed for the non constant string. + +2009-10-07 23:36:45 +0300 Stefan Kost + + * gst/gstinfo.c: + info: use a "%s" format string when printing the memory dump line + We know that the content is save, but the compiler does not. + +2009-10-07 23:23:08 +0300 Rob Clark + + * gst/parse/grammar.y: + parse: don't format the string twice + We were formatting the string once and then passing the string as a format + string to the log functions. + +2009-10-07 11:43:54 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * win32/common/libgstreamer.def: + pad: add variants of gst_pad_get_caps() that don't copy caps. Fixes #590941 + In most places in core and baseclasses we just need the caps to do caps- + intersections. In that case ref'ed caps are enough (no need to copy). + This patch also switches the code to use the new functions. + API: gst_pad_get_caps_refed(), gst_pad_peer_get_caps_refed() + +2009-09-26 23:43:37 +0300 Stefan Kost + + * tests/check/gst/gstghostpad.c: + tests: add ghostpad test for setting target again after pad is linked + +2009-09-26 23:42:22 +0300 Stefan Kost + + * tests/check/gst/gstghostpad.c: + tests: remove empty lines from wrong indent run + +2009-10-07 20:38:49 +0100 Jan Schmidt + + * tests/check/libs/bytewriter.c: + check: Fix compilation of the bytewriter test + +2009-10-07 18:07:26 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: add new byte writer and reader API to .def file + API: gst_byte_writer_*() + +2009-08-20 14:24:19 -0700 Michael Smith + + * gst/gstelementfactory.c: + elementfactory: fix spelling in comment + +2009-10-07 18:40:46 +0200 Mark Nauwelaerts + + * plugins/elements/gstmultiqueue.c: + multiqueue: flush queue upon fatal flowreturn and release upstream thread + +2009-09-22 15:44:31 +0200 Mark Nauwelaerts + + * libs/gst/base/gstdataqueue.c: + dataqueue: fix API documentation typo + +2009-10-07 18:37:28 +0200 Sebastian Dröge + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + bytewriter: Add to the docs + +2009-10-05 11:24:35 +0200 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/libs/bytewriter.c: + bytewriter: Add unit test + +2009-10-03 13:30:54 +0200 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbytewriter.c: + * libs/gst/base/gstbytewriter.h: + bytewriter: Add a generic byte writer + Fixes bug #590669. + +2009-10-03 15:57:07 +0200 Sebastian Dröge + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bitreader/bytereader: API: Add gst_(bit|byte)_reader_get_size() + ... and GST_(BYTE|BIT)_READER() casts. + +2009-10-03 12:34:54 +0200 Sebastian Dröge + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + bytereader,bitreader: Remove FIXME 0.11 to remove non-inlined functions + The normal functions are always useful to have for bindings, especially + runtime-created bindings like Seed or new GObject-Introspection based + Python bindings. + +2009-10-07 16:36:31 +0100 Jan Schmidt + + * tests/check/gst/gstiterator.c: + check: Attempt to fix type-punning warning in the gstiterator test + +2009-10-07 16:00:12 +0100 Jan Schmidt + + * tests/check/libs/gdp.c: + check: Make sure to init the dataprotocol lib. + Call the gst_dp_init() function to ensure that the debug + category is initialised, to avoid g_criticals when running with + GST_DEBUG=5 + +2009-10-07 15:47:45 +0100 Jan Schmidt + + * tests/check/libs/gdp.c: + check: Use GST_DEBUG instead of g_message in the gdp test + +2009-10-07 15:14:46 +0100 Jan Schmidt + + * tests/check/Makefile.am: + check: Add GST_PLUGIN_SCANNER env var to the check environment + +2009-10-07 14:34:17 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: improve plugin loader failure message for uninstalled setups + Everyone running an uninstalled git setup is going to wonder about + this failure next time they update, so let's mention the solution + in the error message. + +2009-10-07 13:59:47 +0100 Jan Schmidt + + * configure.ac: + configure: Beef up the test for __uint128_t on GCC + GCC 3.4.3 on the SPARC buildbot crashes when actually + using __uint128_t. Beef up the configure test to detect that the + type is actually usable. + +2009-10-07 09:56:42 +0100 Tim-Philipp Müller + + * win32/common/libgstbase.def: + win32: add new API to .def file + And add API: marker in commit message that was omitted in the original + commit: + API: gst_data_queue_new_full() + +2009-10-07 09:55:15 +0100 Tim-Philipp Müller + + * tests/benchmarks/.gitignore: + benchmarks: add bufferstress binary to .gitignore + +2009-10-07 09:42:55 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump GLib requirement to 2.18 + Bump GLib requirement as per the release planning docs. + +2009-10-07 10:37:39 +0200 Wim Taymans + + * gst/gstmessage.h: + message: whitespace fixes + +2009-10-07 11:12:57 +0300 Stefan Kost + + * gst/gstutils.c: + pad: flip the G_UNLIKELY + Its likely that we have caps and unlikely (error) otherwise. + +2009-10-07 11:04:56 +0300 Stefan Kost + + * docs/libs/gstreamer-libs-sections.txt: + docs: add new queue api to the docs to fix the build + +2009-09-28 15:25:22 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + plugins/multiqueue: Avoid instance check + We know earlier on in the code whether we're handling an event or a buffer, + just pass that information through. + This commit and the previous commit reduce instruction fetch: + * when pushing buffer (_chain) by 10% + * when popping buffer (_loop) by 3% + +2009-09-28 15:24:02 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + plugins/multiqueue: Cache input/output time, avoid expensive calls. + * Cache the input/output time + * Only recalculate it when needed. + Avoids 50% calls to gst_segment_to_running_time + +2009-10-07 10:00:05 +0300 Stefan Kost + + * docs/manual/basics-init.xml: + * gst/gstpluginfeature.c: + * gst/gstvalue.c: + * plugins/elements/gstfilesink.h: + * tests/benchmarks/gstbufferstress.c: + * tests/benchmarks/gstclockstress.c: + * tests/benchmarks/gstpollstress.c: + * tests/examples/launch/mp3parselaunch.c: + * tools/gst-launch.c: + build: sprintf, sscanf need stdio.h + +2009-10-05 11:46:34 +0300 Stefan Kost + + * gst/gstchildproxy.c: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstchildproxy.c: + childproxy: initialize gvalue in _valist function. Fixes #595602 + Reflow the code to move error handling to the end of the functions. Initialize + gvalue like we do in the setter. Add a unit-test module with two simple tests + the catche this bug. + +2009-10-01 17:39:45 +0300 Stefan Kost + + * gst/gstutils.c: + pad: don't intersect with any in proxy_pad_get_caps + We initialize the caps with any and if a pad has NULL caps, just skip it instead + of intersecting with any. Also add branch prediction here. + +2009-09-30 16:41:07 +0300 Stefan Kost + + * gst/gstutils.c: + docs: rename aggregator to adder in the docs. + +2009-09-30 09:47:23 +0300 Stefan Kost + + * tools/gst-launch.1.in: + man: fix copy and past mistake for -q option + +2009-10-07 09:54:41 +0200 Sebastian Dröge + + * docs/faq/gst-uninstalled: + gst-uninstalled: Extend environment variables to allow using an uninstalled gstreamer-sharp + +2009-09-28 15:19:44 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + plugins/multiqueue: Use new GstDataQueue constructor + +2009-09-28 15:18:37 +0200 Edward Hervey + + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + gstdataqueue: new constructor which takes callbacks. + This allows us to avoid going through glib's signalling system + +2009-09-28 13:19:10 +0200 Edward Hervey + + * plugins/elements/gstmultiqueue.c: + plugins/multiqueue: Use cached value instead of expensive object get. + The task will always exist as long as its owner (i.e. the pad) and that + owner's owner (i.e. multiqueue) exist. + Reduces the number of instruction fetches by 36%. + +2009-09-28 15:41:52 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + plugins/queue: Use previous knowledge of data type to avoid typecheck. + We know whether we have a buffer or an event, use that instead of going + trough the expensive GLib typecheck. + The overall instruction fetch reduction introduced by this commit and the + 2 previous commits: + * receiving a buffer (_chain) by 20% + * popping a buffer (_loop) by 14% + Numbers acquired through callgrind passing 100000 buffers through queue. + +2009-09-28 15:20:06 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + plugins/queue: Avoid useless segment_to_running_time() calculations. + * Cache src and sink time + * Use a boolean to know whether src/sink time need to be recalculated + Avoids 50% calls to gst_segment_to_running_time() + +2009-09-28 13:21:07 +0200 Edward Hervey + + * plugins/elements/gstqueue.c: + plugins/queue: Just cast to the object parent instead of typechecking. + +2009-09-23 16:19:32 +0200 Edward Hervey + + * tests/benchmarks/Makefile.am: + * tests/benchmarks/gstbufferstress.c: + benchmark: New benchmark for testing contention when creating buffers + +2009-09-23 16:17:09 +0200 Edward Hervey + + * tools/gst-launch.c: + gst-launch: Don't activate tracing if not requested. + +2009-10-07 08:37:05 +0200 Edward Hervey + + * tests/check/libs/bytereader.c: + tests: init more variables to avoid compiler warning on osx + Init variable to avoid compiler warning and make the build bot happy + (the compiler most likely complains about this because it doesn't know + here that fail_unless will abort/exit in the path where it fails). + +2009-09-26 11:43:06 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + multiqueue: Improve iterate internal links function + Pads have their GstSingleQueue stored as element private data + so there's no need to iterate over the list of single queues + every time. Also every pad only has a single internal link so + use a single iterator instead of a complex custom iterator. + Set the element private data of the pad to NULL when freeing the + single queue. + +2009-09-17 16:30:43 -0400 Johan Bilien + + * gst/gstutils.c: + introspection: Add annotations for gst_element_query_{duration,position} + Fixes bug #595511. + +2009-10-05 00:11:20 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bytereader: add inline version of gst_byte_reader_skip + +2009-10-07 00:47:59 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update translation files for new and changed strings + +2009-09-28 22:43:51 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: take locks around smaller section + We don't need the hold the proxy mutex locked for getting the internal pad and + for linking the new target pad when we retarget. So take the lock a little later + and release it earlier. + Fixes #596366 + +2009-10-04 19:51:40 +0100 Tim-Philipp Müller + + * tests/check/libs/bytereader.c: + tests: init variable to avoid compiler warning on osx + Init variable to avoid compiler warning and make the build bot happy + (the compiler most likely complains about this because it doesn't know + here that fail_unless will abort/exit in the path where it fails). + +2009-10-03 21:08:54 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + * gst/gstindex.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstxml.c: + * gst/parse/grammar.y: + gst: remove more unnecessary cast when using g_signal_*() + +2009-10-03 20:49:54 +0100 Tim-Philipp Müller + + * libs/gst/base/gstdataqueue.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + dataqueue, elements: avoid unnecessary runtime type checks + +2009-10-05 16:41:50 +0100 Jan Schmidt + + * docs/random/release: + docs: Update the release script + Remove old cruft from the release script, and change some CVS + references to equivalent git commands + +2009-10-04 14:30:34 +0100 Jan Schmidt + + * gst/gstpluginloader.c: + pluginloader: Add a magic number and maximum size limit. + Guard against a hostile child process that sends bogus data + due to memory corruption by adding a magic number to each packet, + and limit the maximum size of any message to 32MB + +2009-02-09 13:33:07 +0000 Jan Schmidt + + * gst/gstpluginloader.c: + registry: Also check the binary registry chunk version of the child. + When trying to find a function plugin-scanner, include a check on the + version of the binary registry chunks it sends, to make sure it's + what we understand. + +2009-02-06 09:49:34 +0000 Jan Schmidt + + * configure.ac: + * docs/faq/gst-uninstalled: + * gst/gstpluginloader.c: + * libs/gst/helpers/Makefile.am: + registry: Support installed/uninstalled plugin-scanner helper + Add a simple version check when starting the plugin-scanner so we can + verify we're talking to one that talks the same language. + First try a plugin-scanner in the installed path, then try one via the + GST_PLUGIN_SCANNER env var if that doesn't work. + Update the uninstalled script. + Install the plugin-scanner to the libexec dir + +2009-01-30 14:18:13 +0000 Jan Schmidt + + * configure.ac: + * gst/gstregistry.c: + Remove checking for and mentions of fork where possible. + We no longer use fork() directly, instead using glib's spawn + functionality, so don't check for it, and don't use it in the + documentation notes. + +2009-01-30 13:06:13 +0000 Jan Schmidt + + * tests/check/gst/gstregistry.c: + Re-enable and fix disabled bit of the registry test + +2009-01-30 13:04:52 +0000 Jan Schmidt + + * gst/gstregistry.c: + Only load the registry cache once per process. + When updating the registry, we don't need to re-read the registry cache + and waste time replacing all our existing, hopefully identical, plugins + and features that we're about to re-scan anyway. + +2009-01-29 13:22:14 +0000 Jan Schmidt + + * gst/gstplugin.c: + * gst/gstregistry.c: + Add some more debug the registry. + Add the full set of debug about why it's decided that a given plugin is + stale or not, and include the plugin name when finalizing it. + +2009-01-23 21:15:43 +0000 Jan Schmidt + + * gst/gstplugin.h: + * gst/gstpluginloader.c: + * gst/gstregistrychunks.c: + * tools/gst-inspect.c: + Add restarting of the plugin loader and blacklisting of broken files + +2009-01-23 15:47:08 +0000 Jan Schmidt + + * gst/gstpluginloader.c: + * gst/gstpluginloader.h: + * gst/gstregistry.c: + Plugin loader phase 2 + phase 2 - make the plugin loader receive the list of plugins to load and + send back the results asynchronously, so we don't context switch back + and forth so much. + +2009-03-14 23:07:40 +0000 Jan Schmidt + + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst_private.h: + * gst/gstpluginloader.c: + * gst/gstpluginloader.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + * gst/gstregistrybinary.h: + * gst/gstregistrychunks.c: + * gst/gstregistrychunks.h: + * libs/gst/Makefile.am: + * libs/gst/helpers/.gitignore: + * libs/gst/helpers/Makefile.am: + * libs/gst/helpers/plugin-scanner.c: + * tests/check/gst/gstregistry.c: + * win32/common/libgstreamer.def: + registry: Add registry helper phase 1 + Phase 1 of adding the registry scan helper + +2009-09-14 23:31:10 +0100 Jan Schmidt + + * gst/gst.c: + * gst/gstregistry.c: + registry: Rearrange some things. + Prepare to land the external plugin helper process + +2009-10-06 19:41:38 +0100 Jan Schmidt + + * configure.ac: + Back to development -> 0.10.25.1 + +=== release 0.10.25 === + +2009-10-05 12:57:03 +0100 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + Release 0.10.25 + +2009-10-05 12:41:42 +0100 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2009-10-01 16:24:52 +0100 Jan Schmidt + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.24.4 pre-release + +2009-09-30 15:52:33 +0100 Jan Schmidt + + * libs/gst/check/Makefile.am: + libgstcheck: Don't use character classes in sed expressions + Apparently the sed that ships on Solaris 10 doesn't support character + classes like [:alnum:], so don't use them. We don't need them for the + symbol names that are being extracted anyway. + Also, use $(SED) instead of 'sed' + Fixes: #596877 + +2009-09-17 01:20:03 +0100 Jan Schmidt + + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.24.3 pre-release + +2009-09-15 09:41:28 +0200 Sebastian Dröge + + * tests/check/gst/gstutils.c: + utils: Fix GMP scaling unit test + GMP only uses "unsigned long int", which is 32 bit + on 32 bit architectures and can't hold a guint64. + This resulted in false unit test failures on 32 bit architectures. + Fixes bug #595133. + +2009-09-14 12:47:26 -0700 David Schleef + + * configure.ac: + * libs/gst/check/Makefile.am: + Fix out-of-tree build + +2009-09-14 14:07:55 +0300 Stefan Kost + + * gst/gstmessage.h: + docs: GST_MESSAGE_STREAM_STATUS is implemented nowadays. + Docs were still mention it as "not yet implemented". + +2009-09-12 13:52:00 +0200 Sebastian Dröge + + * Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/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 file. + +2009-09-12 13:51:29 +0200 Sebastian Dröge + + * gst/Makefile.am: + * gst/gsttaglist.h: + introspection: Don't typedef GstTagList to GstStructure for gobject-introspection + +2009-09-11 23:21:30 +0100 Jan Schmidt + + * ChangeLog: + * configure.ac: + * po/LINGUAS: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.24.2 pre-release + +2009-09-11 22:42:51 +0100 Jan Schmidt + + * gst/gstmessage.c: + Don't use C++ style comments + +2009-09-11 22:22:34 +0100 Jan Schmidt + + * gst/gstmessage.c: + message: Disable restriction that structure changes are sink pads + The structure_change message was originally emitted on source pads and + then recently changed to be sink pads. This causes a failure in the + gst-python testsuite. Disable the restriction so that the published + behaviour is still allowed. + +2009-09-11 18:24:18 +0100 Jan Schmidt + + * tests/check/gst/gstplugin.c: + check: Fix version check tests + Accomodate the slightly changed semantics in the plugin version check + where a CVS version just before a release is acceptable. + +2009-09-11 21:20:57 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + binaryregistry: don't crash in cleaning up on error. + Don't dereference NULL pointers. + +2009-07-20 12:54:00 -0700 David Schleef + + * gst/gstinfo.h: + debug: use dummy code to avoid spurious semicolons + Fixes bug #589173. + +2009-09-10 11:53:09 +0200 Wim Taymans + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstpluginfeature.h: + whitespace fixes + +2009-09-10 11:41:56 +0200 Wim Taymans + + * gst/gstpluginfeature.c: + pluginfeature: improve version check + Also parse the nano of the version and assume that X.Y.Z-1.1 >= X.Y.Z + With this change we can also check development versions against the version of + the upcomming release. + +2009-09-10 10:05:38 +0200 Sebastian Dröge + + * gst/gsttaglist.h: + taglist: Add FIXME for 0.11 to not typedef GstTagList to be a GstStructure + See bug #518934. + +2009-09-09 16:29:10 -0700 David Schleef + + * gst/gstelement.h: + Fix typo in inline documentation + +2009-09-09 17:57:54 +0100 Tim-Philipp Müller + + * common: + Update common + +2009-09-09 18:38:29 +0200 Sebastian Dröge + + * gst/gstutils.c: + utils: Add a comment to the scaling functions to explain why the rounding is correct + +2009-09-09 16:45:17 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: don't unref NULL caps + Caps can be NULL so don't call unref on it unconditionally, instead use an + existing exit pad for the function. + +2009-09-09 14:53:16 +0200 Sebastian Dröge + + * configure.ac: + * gst/gstutils.c: + utils: Use gcc's __uint128_t for 64bit unsigned integer scaling + This is available in newer gcc releases and it should only exist + on platforms that provide some native 128bit integer arithmetic + instructions. + The x86-64 assembly for this is still kept for non-gcc compilers + that don't provide __uint128_t magic. + +2009-09-09 09:38:54 +0300 Stefan Kost + + * docs/random/ensonic/draft-bufferpools.txt: + design: add ideas for buffer management + Right now we're operating suboptimal when talking to kernel interfaces. Write + doesn some ideas. + +2009-09-07 18:27:08 +0200 Wim Taymans + + * libs/gst/base/gstpushsrc.h: + * plugins/elements/gstfakesrc.c: + fix whitespace + +2009-09-03 19:06:28 +0200 Wim Taymans + + * libs/gst/base/gstadapter.h: + adapter: fix whitespace + +2009-09-07 16:14:57 +0200 Benjamin Otte + + * gst/gstvalue.c: + docs: Fix typo in gst_value_union() + +2009-09-06 19:43:47 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.c: + bitreader, bytereader: add some FIXME 0.11 comments and fix indenting + +2009-09-04 17:15:35 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bytereader: add unchecked and inline versions of the float getters/peekers + API: gst_byte_reader_get_float*_unchecked() + +2009-09-04 16:52:06 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + bytereader: add inline versions of the most common getters and setters + +2009-09-02 11:20:04 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbytereader-docs.h: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * tests/check/libs/bytereader.c: + bytereader: add inlined _unchecked() variants for some functions + API: gst_byte_reader_skip_unchecked() + API: gst_byte_reader_peek_*_unchecked() + API: gst_byte_reader_get_*_unchecked() + API: gst_byte_reader_{peek,get,dup}_data_unchecked() + +2009-09-05 12:30:07 +0200 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Strip Gst prefix from all types/functions + +2009-09-05 12:22:37 +0200 Sebastian Dröge + + * gst/Makefile.am: + introspection: Fix for out-of-tree builds + +2009-09-05 12:04:59 +0200 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Fix out-of-tree build + +2009-09-05 11:51:55 +0200 Sebastian Dröge + + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + introspection: Fix build if gir-repository is not installed + +2009-09-05 09:36:21 +0200 Sebastian Dröge + + * libs/gst/net/Makefile.am: + net: Add gobject-introspection support + +2009-09-05 09:34:30 +0200 Sebastian Dröge + + * libs/gst/dataprotocol/Makefile.am: + dataprotocol: Add gobject-introspection support + Because of a bug in gobject-introspection this is disabled for now. + +2009-09-05 09:28:48 +0200 Sebastian Dröge + + * libs/gst/controller/Makefile.am: + controller: Add gobject-introspection support + +2009-09-05 09:27:04 +0200 Sebastian Dröge + + * libs/gst/check/Makefile.am: + check: Add gobject-introspection support + +2009-09-05 09:23:19 +0200 Sebastian Dröge + + * .gitignore: + * gst/.gitignore: + * libs/gst/base/Makefile.am: + gstbase: Add gobject-introspection support + +2009-09-04 20:56:43 +0200 Sebastian Dröge + + * configure.ac: + * gst/.gitignore: + * gst/Makefile.am: + * gst/gst.c: + gst: Add gobject-introspection support + Partially fixes bug #550616. + +2009-09-05 10:19:23 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 94f95e3 to 19fa4f3 + +2009-09-04 19:37:15 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbytereader.c: + docs: fix docs for gst_byte_reader_{get|peek}_float*() + +2009-09-04 11:35:59 +0200 Wim Taymans + + * gst/gstevent.h: + event: whitespace fixes + +2009-09-04 09:51:26 +0200 Aurelien Grimaud + + * gst/gstbin.c: + bin: Only unref EOS message after it is not used anymore + Fixes bug #594107. + +2009-09-02 18:54:06 +0200 Wim Taymans + + * gst/gstbin.c: + * gst/gstmessage.c: + * gst/gstpad.c: + states: post structure change on sinkpads + Post the structure change messages on the sinkpads of the elements. This allows + us to catch unlinked pads earlier without ending up with inconsistent element + degrees. + +2009-09-02 18:13:22 +0200 Wim Taymans + + * gst/gstbin.c: + bin: avoid false 'loop detected' warnings + When we detect a pad unlink in progress, we will not be updating the degree of + the parent element. This can cause false loop detected warnings because the + degree counter is invalid. Handle this case by marking the iterator as 'dirty' + when we detect a pad unlink and avoid emiting the warning in this case. We have + to continue our state change as good as we can, we will eventually resync when + the pad unlink completed. + +2009-09-01 16:49:56 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + basesrc: whitespace fixes + +2009-09-01 16:49:22 +0200 Wim Taymans + + * gst/gstbuffer.h: + buffer: whitespace fixes + +2009-09-01 12:07:31 +0100 Jan Schmidt + + * tests/examples/Makefile.am: + dist: Don't list the streams subdir twice in examples Makefile + Listing the 'streams' subdir twice in DIST_SUBDIRS breaks distcheck. + +2009-09-01 12:05:51 +0100 Jan Schmidt + + * gst/gstbin.c: + gstbin: Don't propagate a NULL cached index to added elements + When an element is added to the bin, only set the index if we have a + cached index, rather than setting a NULL index on elements that might + have a default index object of their own. + +2009-07-19 21:23:18 +0100 Jan Schmidt + + * docs/random/release: + docs: Add a note about regenerating the changelog in the release script + +2009-09-01 10:03:35 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + element: don't take object lock for g_critical() and flesh out warning message some more + +2009-09-01 10:21:31 +0200 Sebastian Dröge + + * tests/check/gst/gstiterator.c: + iterator: Add unit test for the single iterator + +2009-09-01 10:20:59 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Only visit the element a single time in the single iterator + +2009-09-01 07:27:25 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Fix single iterator for NULL objects and non-GTypeInstance objects + Fixes bug #593719. + +2009-09-01 00:00:57 +0300 Stefan Kost + + * gst/gstelement.c: + debug: more detail in wrong-state-on-dispose error. + Also tell in which state the element actualy is and if it is eventualy + state-locked. + +2009-08-31 20:38:07 +0200 Wim Taymans + + * gst/gstiterator.c: + iterator: fix docs for _new_single(). + +2009-08-31 16:56:22 +0100 Tim-Philipp Müller + + * gst/gstghostpad.c: + * gst/gstiterator.c: + * gst/gstiterator.h: + docs: it's its + The panda says no! + +2009-08-29 20:44:36 +0200 Mark Nauwelaerts + + * gst/gstelementfactory.c: + registry: fill in elementfactory when registering element + elementfactory field is filled in by gst_element_base_class_init, + but it needs some info set on the element's type, so have it + available prior to class structure creation spinning up. + This affects elements that have a well-known/public type (e.g. pipeline) + and can be created by other means than gst_element_factory_make + (which will also fill in the element's factory). + +2009-08-31 11:45:17 +0200 Wim Taymans + + * gst/gstutils.c: + utils: use 128bits division on x86_64 + +2009-08-29 04:44:51 +0400 Руслан Ижбулатов + + * gst/gstsystemclock.c: + systemclock: fix compilation of win32 code + Fixes #593460. + +2009-08-28 18:37:44 +0200 Wim Taymans + + * gst/gstbin.c: + bin: cache index + Cache the last index that was set with _set_index() and return this in the + _get_index() call. + Set the cached index on newly added elements. + Fixes #566881 + +2009-08-28 18:35:54 +0200 Wim Taymans + + * gst/gstelement.c: + element: better type checks + Add GST_CLOCK typecheck for _set_clock(). + Allow setting NULL indexes on element (clear the current index) + Some whitespace fixes. + +2009-08-28 18:14:23 +0200 Wim Taymans + + * gst/gstelement.h: + element; whitespace fixes + +2009-08-28 18:06:45 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: add gst_iterator_new_single to defs + +2009-08-28 18:03:44 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: whitespace fixes + +2009-08-28 17:59:15 +0200 Thijs Vermeir + + * libs/gst/base/gstbasetransform.c: + Check suggested caps for proxy alloc + Because we are trying to resolve a suggestion here we don't need + to check on caps for proxy_alloc but we need to check on the + suggested caps instead. + +2009-08-28 17:49:11 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + queue: whitespace fixes + +2009-08-28 17:02:30 +0200 Wim Taymans + + * gst/gstsystemclock.c: + systemclock: use preformance counters on windows + Based on clock implementation by Håvard Graff + Try to get the time on windows using the performance counters. These have a much + higher resolution and accuracy than the regular getcurrenttime(). Be careful to + fall back to regular getcurrenttime() or posix clocks when performance counters + are not available. + +2009-08-28 16:07:16 +0200 Wim Taymans + + * gst/gstsystemclock.h: + systemclock: fix indentation + +2009-08-28 15:32:26 +0200 Wim Taymans + + * gst/gstutils.c: + utils: use shift instead of division + We can use a shift for scaling the denominator instead of a divide since the + denom is always positive. This avoids having the compiler generate code for the + different rounding rules when scaling negative values. + +2009-08-28 13:45:38 +0200 Wim Taymans + + * gst/gstutils.c: + utils: make inlining explicit + +2009-08-28 12:43:43 +0200 Wim Taymans + + * gst/gstutils.c: + utils: optimize for x86_64 with some inline asm + 64bit x86 has native 64x64->128 bit multiply that we can use with some inline + assembler to speed up large multiplications. + Use bsr to find the number of leading zeros more efficiently. + +2009-08-28 12:33:37 +0200 Wim Taymans + + * gst/gstutils.c: + utils: factor out the leading zero count code + +2009-08-28 12:30:41 +0200 Wim Taymans + + * gst/gstutils.c: + utils: pass correction factor around + Pass the correction factor around to get rid of the enum, some code + and some branches. + +2009-08-28 12:21:28 +0200 Wim Taymans + + * gst/gstutils.c: + utils: whitespace fixes + +2009-08-28 12:19:34 +0200 Wim Taymans + + * gst/gstutils.c: + utils: move common correction code in a macro + +2009-08-24 18:01:07 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.h: + basesink: whitespace fixes + +2009-08-26 16:51:32 +0200 Sebastian Dröge + + * gst/gstiterator.c: + iterator: Allow to use NULL as object for the single iterator + +2009-08-26 16:39:19 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstiterator.c: + * gst/gstiterator.h: + iterator: API: Add gst_iterator_new_single() + This allows "iteration" over a single object of some type, + which happens often for the GstPadIterIntLinksFunction for example. + +2009-08-24 17:57:16 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: return result of _set_caps() + +2009-08-24 17:56:32 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: whitespace fixes + +2009-08-22 14:22:31 -0700 David Schleef + + * gst/gstobject.h: + * gst/gsttrace.h: + * gst/gstxml.h: + It's __GNUC__, not _GNUC_ + This appears to be an 8 year old bug. + +2009-08-21 09:59:58 +0100 Tim-Philipp Müller + + * docs/pwg/building-boiler.xml: + docs: add link to cgit tarball download of gst-template in PWG + So people who can't use git for some reason still can get hold + of the code. See #591069. + +2009-08-20 11:54:40 +0100 Tim-Philipp Müller + + * gst/gstpluginfeature.c: + pluginfeature: add guard to gst_plugin_feature_type_name_filter + So we don't just crash if there's a refcounting bug somewhere else. + +2009-08-19 16:24:39 +0200 Sebastian Dröge + + * docs/manual/appendix-integration.xml: + docs: Don't talk about the deprecated libgnome and GNOME-VFS + Instead talk about GIO and change the option parsing example to + not initialize libgnome but only GTK. + Fixes bug #592233. + +2009-08-19 15:25:41 +0200 Sebastian Dröge + + * tests/examples/Makefile.am: + * tests/examples/streams/Makefile.am: + examples: Link rtpool-test to libpthread for using the POSIX threads + Also the other streams example can run without pthreads therefore + enable it even if pthreads are not available. + Fixes bug #592314. + +2009-08-18 14:45:23 +0200 Sebastian Dröge + + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + tools: Use iterate_internal_links instead of deprecated get_internal_links + +2009-08-18 14:45:02 +0200 Sebastian Dröge + + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + multiqueue: Use iterate_internal_links instead of deprecated get_internal_links + +2009-08-18 14:05:40 +0200 Sebastian Dröge + + * gst/gstpad.c: + * gst/gstpad.h: + gstpad: Add some DISABLE_DEPRECATED markers in the header too + The internal links function is deprecated since some time and + there already were GST_REMOVE_DEPRECATED markers in the source file, + now add them to the header too. + Fixes bug #592209. + +2009-08-18 11:38:38 +0200 Sebastian Dröge + + * docs/design/part-states.txt: + docs: Update the design docs for bin state changes according to last commit + +2009-08-18 11:36:36 +0200 Antoine Tremblay + + * gst/gstbin.c: + gstbin: Don't try to change children's state if they're already in the state we want + Fixes bug #368536. + +2009-08-18 11:33:17 +0200 Sebastian Dröge + + * gst/gstghostpad.c: + ghostpad: Always get the proxypad's ghostpad via the ghostpad in the src caps change notify handler + Before the signal handler would get the ghostpad passed as second + argument but it could've already been unreffed and destroyed. + This would then lead to crashes and all that. + Now we get the ghostpad from the proxy pad, which we get from the + target pad as it's peer. + Fixes bug #591318. + +2009-08-18 08:45:08 +0200 Laurent Glayal + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + filesink: Add property to allow to append to an already existing file + Fixes bug #591441. + +2009-08-14 11:53:14 +0200 Sebastian Dröge + + * configure.ac: + configure: Remove duplicated check for clock_gettime + +2009-08-14 11:12:50 +0200 Sebastian Dröge + + * configure.ac: + * tests/check/Makefile.am: + * tests/check/gst/gstutils.c: + gstutils: Add special random unit test for 64 scaling functions + This tests 100000 random multiplications/divisions of all scaling + function variants and compares the result with the result that is + generated by GMP on the same input. + For this check for GSL and GMP during configure but only use + it for this single unit test. + Testing functions were provided by Kipp Cannon + +2009-08-13 16:31:01 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + gstutils: Add new scaling functions to the docs + +2009-08-13 16:20:46 +0200 Sebastian Dröge + + * tests/check/gst/gstutils.c: + gstutils: Add (very) minimal unit test for the new rounding scaling functions + +2009-08-13 16:10:31 +0200 Kipp Cannon + + * gst/gstutils.c: + * gst/gstutils.h: + gstutils: API: Add rounding to nearest and next integer versions of the 64 bit integer scaling functions + The new functions are + gst_util_uint64_scale_int_round() + gst_util_uint64_scale_int_ceil() + gst_util_uint64_scale_round() + gst_util_uint64_scale_ceil() + Fixes bug #590919. + +2009-08-12 11:10:05 +0200 Kipp Cannon + + * gst/gstutils.c: + gstutils: Revert parts of last change to optimize the scaling functions again + Partially fixes bug #590919. + +2009-08-11 09:16:38 +0200 Sebastian Dröge + + * gst/gstutils.c: + gstutils: Fix violations of strict-aliasing rules in gst_util_uint64_scale() + +2009-08-11 09:10:47 +0200 Kipp Cannon + + * gst/gstutils.c: + gstutils: Refactor gst_util_uint64_scale() + This will later make it possible to provide rounding versions + of it without much code duplication. + Partially fixes bug #590919. + +2009-08-11 15:20:18 +0200 Jonas Holmberg + + * gst/gstbufferlist.c: + bufferlist: update doc string + +2009-08-11 13:21:35 +0200 Sebastian Dröge + + * gst/gstsegment.c: + * tests/check/gst/gstsegment.c: + gstsegment: Actually start==stop==segment_start is inside the segment + Still the old code was wrong as it claimed that start==stop + + * tests/check/gst/gstsegment.c: + gstsegment: Fix unit test and add an additional test + The previous test assumed that start=stop=segment_start will + be inside the segment but this is wrong. + +2009-08-11 12:59:13 +0200 Sebastian Dröge + + * gst/gstsegment.c: + gstsegment: Clipping should detect start=stop + + * tests/check/gst/gstbus.c: + gstbus: Unref pipeline after usage in test_custom_main_context unit test + This makes the core unit tests valgrind clean again. + +2009-08-11 02:54:55 +0100 Edward Hervey + + * docs/random/moving-plugins: + docs: add Edward's git plugin moving howto to moving-plugins document + +2009-08-10 14:30:34 +0100 Tim-Philipp Müller + + * tests/check/gst/gstobject.c: + checks: don't forget to include config.h in the GstObject unit test + +2009-08-10 13:05:57 +0100 Tim-Philipp Müller + + * configure.ac: + * tests/check/gst/gstobject.c: + checks: try to fix GstObject unit test on OSX + Seems like we get SIGBUS instead of SIGSEGV here when GLib crashes + where it shouldn't crash (and we even have a unit test for that!). + +2009-08-10 12:01:48 +0100 Tim-Philipp Müller + + * tests/check/pipelines/parse-launch.c: + checks: set pipelines to NULL state in parse-launch unit test + Fixes timeouts in gst_task_cleanup_all(). + +2009-08-10 11:42:25 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbus.c: + checks: set pipeline back to NULL state in GstBus unit test + Fixes timeout in gst_task_cleanup_all(). + +2009-08-10 11:43:52 +0100 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + check: add some logging before calling gst_task_cleanup_all() + +2009-08-08 22:27:06 +0200 Sebastian Dröge + + * libs/gst/check/gstcheck.h: + check: Call gst_task_cleanup_all() in GST_END_TEST + This fixes many unit tests under valgrind that shows + leaking GstTasks that are not really leaked but just + not unreffed by the task thread before the unit test + stopped. + Fixes bug #591045. + +2009-08-08 14:47:57 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink: Remove dead assignments + +2009-08-08 14:47:40 +0200 Edward Hervey + + * gst/gstdebugutils.c: + * gst/gstpad.c: + * gst/gsttask.c: + gst: Remove dead assignments + +2009-08-07 02:36:29 +0100 Tim-Philipp Müller + + * tests/check/pipelines/.gitignore: + gitignore: ignore new queue-error test + +2009-08-06 20:40:07 +0100 Tim-Philipp Müller + + * libs/gst/check/Makefile.am: + check: add internal-check.h to BUILT_SOURCES in attempt to fix the build + For some people the build of libgstcheck was broken because the make + target that creates the internal-check.h file wasn't executed for + some reason. This should hopefully fix this. + +2009-08-06 18:38:16 +0100 Tim-Philipp Müller + + * autogen.sh: + autogen.sh: older aclocals don't like -I. so use -I . instead + +2009-08-06 18:47:32 +0200 Wim Taymans + + * gst/gstbuffer.c: + gstbuffer: add additional checking for writability + Check for metadata writability when setting caps on buffer or when copying + metadata flags. Only enable these extra assertions in git versions. + This should help us find bad elements. + +2009-08-04 10:22:25 +0100 Tim-Philipp Müller + + * configure.ac: + check: disable unit test support on win32 for now + Until we make the internal libcheck work on windows. + +2009-07-19 17:04:58 +0100 Tim-Philipp Müller + + * .gitignore: + * libs/gst/check/Makefile.am: + check: fix symbol exporting + +2009-07-17 00:46:32 +0100 Tim-Philipp Müller + + * Makefile.am: + * check-checks.m4: + * libs/gst/check/libcheck/check_pack.c: + check: fix issues with 'make distcheck' + Seems to work now, at least on *nix. One of the configure checks + caused these weird issues - but which one? + +2009-08-06 17:27:12 +0100 Tim-Philipp Müller + + * Makefile.am: + * autogen.sh: + * check-checks.m4: + * configure.ac: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/.gitignore: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.h: + * libs/gst/check/libcheck/Makefile.am: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + check: use private copy of check for libgstcheck + See #577275. Seems to work fine, but doesn't distcheck yet. + +2009-07-16 18:39:16 +0100 Tim-Philipp Müller + + * libs/gst/check/libcheck/Makefile.am: + * libs/gst/check/libcheck/check.c: + * libs/gst/check/libcheck/check.h.in: + * libs/gst/check/libcheck/check_error.c: + * libs/gst/check/libcheck/check_error.h: + * libs/gst/check/libcheck/check_impl.h: + * libs/gst/check/libcheck/check_list.c: + * libs/gst/check/libcheck/check_list.h: + * libs/gst/check/libcheck/check_log.c: + * libs/gst/check/libcheck/check_log.h: + * libs/gst/check/libcheck/check_msg.c: + * libs/gst/check/libcheck/check_msg.h: + * libs/gst/check/libcheck/check_pack.c: + * libs/gst/check/libcheck/check_pack.h: + * libs/gst/check/libcheck/check_print.c: + * libs/gst/check/libcheck/check_print.h: + * libs/gst/check/libcheck/check_run.c: + * libs/gst/check/libcheck/check_str.c: + * libs/gst/check/libcheck/check_str.h: + check: add internal copy of check-0.9.6 + Not hooked up yet. See #577275. + +2009-08-06 14:11:46 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + docs: fix Since: tag for new gst_caps_can_intersect() function + +2009-07-22 11:24:59 +0300 Stefan Kost + + * gst/gstutils.c: + utils: use new _caps_can_intersect() + +2009-07-22 11:24:08 +0300 Stefan Kost + + * gst/gstpad.c: + pad: use new _caps_can_intersect() + +2009-07-22 09:54:55 +0300 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + basetransform: use new _caps_can_intersect() + +2009-07-22 09:38:10 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstcaps.h: + * win32/common/libgstreamer.def: + caps: add gst_caps_can_intersect() + Often we don't need the result of the intersection. Add a variant that only + tries to intersect. It can break out earlier and does less GValue copying. + API: gst_caps_can_intersect() + +2009-07-22 09:24:55 +0300 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + basetransform: only check caps_is_fixed() if they changed + The previous code could call gst_caps_is_fixed() for the same caps many times. + +2009-07-21 13:31:13 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: split callback for structure intersect into two functions + We call this separately. there is no much benefit in reusing the callback. + Splitting is let us remove a branch also. + +2009-07-21 13:27:09 +0300 Stefan Kost + + * gst/gstcaps.c: + logging: log if we copy caps to be able to track it + +2009-07-21 11:32:01 +0300 Stefan Kost + + * gst/gstcaps.c: + caps: add comments about g_ptr_array size behaviour + Just explain the behaviour to avoid that someone else is wasting time trying to + improve this too. + +2009-07-21 11:14:20 +0300 Stefan Kost + + * tests/examples/controller/audio-example.c: + example: unref the clock id + +2009-07-21 10:56:53 +0300 Stefan Kost + + * gst/gstpad.c: + pad: use correct variable in test + +2009-07-28 16:13:37 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + registry: add filename to debug message, like elsewhere + +2009-07-21 10:38:15 +0300 Stefan Kost + + * gst/gstbin.c: + bin: fix compiler warning about unused var when disabling debug logging + +2009-08-06 13:29:29 +0200 Mark Nauwelaerts + + * plugins/elements/gstqueue.c: + queue: post error message when pausing task + If downstream returns error and upstream has already delivered + everything (including EOS) and will no longer be around to find + out that we paused (and why), post error message. Fixes #589991. + +2009-07-28 12:03:36 +0200 Mark Nauwelaerts + + * tests/check/Makefile.am: + * tests/check/pipelines/queue-error.c: + queue: add unit test + Make a downstream element return an error after upstream has already + put all data into queue (including EOS). As such, upstream + will not be around to pick up the error, so it is up to queue to + act appropriately. See #589991. + Note there may be downstream fatal errors (e.g. negotiation) that do + not warrant an error message already having been posted. + +2009-08-05 18:02:31 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: clarify _caps_is_equal() + +2009-08-05 17:58:20 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: refactor metadata modifications + Check when we need to touch the metadata of the output buffer after selecting + the output buffer so that we have everything in one place. + Also take flags and timestamp modifications into account. + +2009-08-05 17:55:14 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: only set caps when different + When we have an input buffer with caps and when those caps are different from + the caps we want, only then make a writable copy of the input buffer as the + output buffer and set the caps on that output buffer. This avoids some cases + where we took a subbuffer for setting caps that were the same. + +2009-08-05 15:28:59 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: enable optimisation + When we have the same input as output caps, reuse the input caps object. After + the caps refcounting has been sorted out now, we can finally enable this + optimisation. + +2009-08-05 13:48:40 +0200 Wim Taymans + + * tests/check/gst/gstpad.c: + tests: don't set caps on unwritable buffers + Take the ref after setting the caps on a buffer because else the buffer is + techinically not writable. + +2009-08-05 13:47:33 +0200 Wim Taymans + + * plugins/elements/gstqueue.c: + queue: get caps after making writable + Get the caps of the buffer after we made the buffer writable. This did not + cause any problems but it's nicer this way. + +2009-08-05 13:46:42 +0200 Wim Taymans + + * plugins/elements/gstcapsfilter.c: + capsfilter: fix refcounting problem + Make sure the metadata is writable before setting the caps on a buffer. + +2009-08-05 13:44:51 +0200 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + basetransform: fix refcounting problem + Add some more debug info. + Make sure that the output buffer has writable metadata before we attempt to set + caps on it. + fixes #583999 + +2009-08-05 13:44:13 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: add some more debugging in _replace + +2009-08-05 13:43:10 +0200 Wim Taymans + + * gst/gstpad.c: + pad: Add some more debugging + +2009-08-05 13:41:33 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: small improvements + Unref the target pad after we used it for debugging. + Add some more debug. + Only replace caps when they changed. + +2009-07-29 13:46:35 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: cleanups in position queries + Use existing boolean flag to pass position queries upstream. Also add upstream + queries for the last position queries. + +2009-08-05 13:25:33 +0100 Tim-Philipp Müller + + * configure.ac: + configure.ac: fix libxml2 check, which is only needed for xml load/save now + Since the registry doesn't use libxml2 any longer, it's no longer necessary + to disable both xml load/save *and* the registry to get rid of the libxml2 + dependency, disabling just xml loading/saving is enough. Fixes #590841. + +2009-08-02 14:33:59 +0100 Tim-Philipp Müller + + * docs/faq/gst-uninstalled: + gst-uninstalled: rename uninstalled registry file to registry.dat + We're not using the xml registry any longer after all. + +2009-08-02 14:28:38 +0100 Tim-Philipp Müller + + * docs/faq/gst-uninstalled: + gst-uninstalled: refine search paths for uninstalled plugin modules + Use more refined search paths for our plugin modules. Not only does + this make things much faster in an uninstalled setup, it also makes + sure we're not accidentally using out-of-date plugins built ages + ago as part of a (failed) 'make distcheck' when we forget to clean + up the distcheck build directory. + +2009-07-29 23:42:39 +0100 Tim-Philipp Müller + + * docs/design/Makefile.am: + docs: dist GStreamer-1.0 buffer design draft + +2009-08-06 06:50:41 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + taglist: Add new ALBUM_ARTIST tag to the docs + +2009-08-04 14:13:34 +0200 John Millikin + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: Add support for ALBUM_ARTIST tag + The "album artist" tag is used when the artist of an entire + album differs from the artist of an individual track; for example, + when a "guest artist" appears on an album, or on compilations. + Fixes bug #590430. + +2009-07-29 13:33:11 +0200 Stian Selnes + + * libs/gst/base/gstbasesink.c: + basesink: Query upstream for the position if conversion in PAUSED failed + Fixes bug #590045. + +2009-07-28 20:42:20 +0200 Kipp Cannon + + * libs/gst/base/gstbasetransform.c: + basetransform: Improve debug output in gst_base_transform_acceptcaps() + Fixes bug #589524. + +2009-07-22 09:01:56 +0200 Sebastian Dröge + + * libs/gst/base/gstbasetransform.c: + basetransform: Don't unset GAP flag if working in passthrough mode + Fixes bug #589314. + +2009-08-06 01:43:57 +0100 Jan Schmidt + + * configure.ac: + back to development -> 0.10.24.1 + +=== release 0.10.24 === + +2009-08-05 00:51:16 +0100 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + Release 0.10.24 + +2009-08-04 23:05:27 +0100 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2009-08-03 15:31:22 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbytereader.c: + bytereader: avoid wrap-around in buffer size checks. Fixes #590622. + +2009-07-30 14:41:30 +0100 Jan Schmidt + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.24.5 pre-release + +2009-07-28 21:15:52 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Get the flushing state with the object lock taken. + Fixes #590056 + +2009-07-28 21:14:11 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Make sure the CollectData list is up-to-date when reading/setting it + Without this, we risked: + * Checking the flushing state on an unexisting list + * Not setting the flushing state on pads that had just been added + Partially fixes #590056 + +2009-07-28 21:12:25 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Split out _check_pads into a version without lock taking. + This is so we can use _check_pads in places where we've already taken + the lock in question. + Partially fixes #590056 + +2009-07-28 15:23:15 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstconsistencychecker.h: + check: make new GstStreamConsistency structure private + There's no need to have GstStreamConsistency in a public header for + the time being, so make it private. While we're at it, add a gtk-doc + blurb for it though. Re-fixes #588744. + +2009-07-24 13:50:19 +0100 Jan Schmidt + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.23.4 pre-release + +2009-07-24 09:50:19 +0100 Robin Stocker + + * libs/gst/base/gstbasesrc.c: + basesrc: don't handle SEEKING queries for formats that don't match the one the source operates in + Return FALSE in basesrc's default query handler when we get a SEEKING query for + a format that's not the one the source operates in. Previously (ie. before, in + the git version) we would return TRUE in that case and seekable=FALSE, which + is more correct, but causes backwards compatibility problems. (Before that + we would change the format of the query when answering, which was completely + broken since callers don't expect that or check for it). Since the SEEKING + query is a fairly recent addition, not all demuxers, parsers and decoders + implement it yet, in which case any SEEKING query by an application will + just be passed upstream where it will then be handled by basesrc. Now, if + e.g. totem does a SEEKING query for TIME format and we have a demuxer that + doesn't implement the query, basesrc would answer it with seekable=FALSE in + most cases, and totem can only take that as authoritative answer, not knowing + that the demuxer doesn't implement the SEEKING query. To avoid this, we make + basesrc return FALSE to SEEKING queries in unhandled formats. That way + applications like totem can fall back on assuming seekability depending on + whether a duration is available, or somesuch. Downstream elements doing + such queries are likely to equate an unhandled query with a non-seekable + response as well, so this should be an acceptable fix for the time being. + See #584838, #588944, #589423 and #589424. + +2009-07-24 00:41:55 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From fedaaee to 94f95e3 + +2009-07-20 16:11:02 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + gstregistrybinary: add +1 after error checking + The current code made the error checking pointless by changing -1 to 0 in error + cases. Also don't leak a pad template on error. + +2009-07-20 15:51:20 +0100 Jan Schmidt + + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + 0.10.23.3 pre-release + +2009-07-20 18:03:21 +0200 Wim Taymans + + * tests/check/gst/gsttask.c: + tests: make sure the tasks are joined + Call _clean_all() on the task to make sure everything is joined and stopped. + See #589127 + +2009-07-20 15:44:36 +0200 Wim Taymans + + * gst/gsttask.c: + task: fix taskpool leak + GstTaks does not always unref the taskpool it was created from because it + depends on when the pool provided an ID for joining the task. + Rework some code so that we always unref the pool and optionally join when the + pool provided an id. + Fixes #589127 + +2009-07-20 13:26:51 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: make tag queuing threadsafe + See #588745 + +2009-07-13 09:22:06 +0200 Edward Hervey + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstconsistencychecker.c: + * libs/gst/check/gstconsistencychecker.h: + gstcheck: Add a stream consistency checking helper routine. Fixes #588744 + +2009-07-20 11:04:05 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + binaryregistry: don't unref NULL if we have an early read error + +2009-07-12 10:04:01 +0200 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: Serialize tags into the dataflow. Fixes #588745 + +2009-07-16 14:17:03 +0100 Tim-Philipp Müller + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbytereader.c: + docs: fix API docs for gst_{adapter|byte_reader}_masked_scan_uint32 + Clarify byte reader docs a bit: offset is relative to the current + position of the reader, not to the start of the data. Also, the + examples in both the adapter docs and the byte reader docs have + the mask and pattern arguments swapped (see #587561). Spotted + by Carl-Anton Ingmarsson. + +2009-07-16 13:59:07 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + * tests/check/gst/gsttag.c: + tags: only emit a g_warning() for empty tag strings for git versions + For now, don't show a g_warning() for empty tag strings and NULL + tags with non-git versions; we should wait for the fixes in our + plugin modules to make it into a release before we enable this + unconditionally. + +2009-07-14 18:59:13 +0100 Jan Schmidt + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + 0.10.23.2 pre-release + +2009-07-14 12:15:05 +0300 Stefan Kost + + * gst/gstvalue.c: + value: add explanation for shortcut + +2009-07-10 20:04:48 +0100 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + basetransform: take size once + +2009-07-10 19:17:04 +0100 Stefan Kost + + * gst/gstvalue.c: + value: fix can_intersect to behave like intersect + Add a quick return if two types are the same. Change the check for the + intersection function to be the same as the one used in intersect(). The + later tries both directions. + +2009-07-14 00:04:22 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + gstinfo: maintain ABI compatibility even if debugging is disabled + +2009-07-02 12:40:05 +0100 Jan Schmidt + + * gst/gststructure.c: + * gst/gstvalue.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstvalue.c: + structure: Change NULL and empty string handling + Don't forbid the empty string "" in generic structures, only in taglists. + Properly allow the NULL string by adding special cases for serialising + and deserialising it. prop1=(string)NULL is the NULL string, + prop1=(string)"NULL" is the actual string with the value "NULL" + +2009-07-13 12:23:02 -0400 Olivier Crête + + * common: + Automatic update of common submodule + From 5845b63 to fedaaee + +2009-07-13 12:00:47 +0200 Andoni Morales + + * plugins/elements/gstfilesink.c: + filesink: Fix segfault with MSVC + Don't use deprecated fileno on MSVC but replace with _fileno + Fixes #587052 + +2009-07-13 09:32:57 +0200 Edward Hervey + + * docs/design/Makefile.am: + docs/design: Update Makefile.am for changed framestep document name. + +2009-07-10 19:27:21 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + tools: the plugin features listed by gst-inspect are typefinders, not types + +2009-07-10 18:46:39 +0100 Wim Taymans + + * docs/design/draft-buffer2.txt: + docs: add draft for arbitrary buffer metadata idea + +2009-07-10 18:35:21 +0100 Wim Taymans + + * docs/design/part-framestep.txt: + docs: more framestep docs out of draft + +2009-07-10 18:33:58 +0100 Wim Taymans + + * docs/design/draft-framestep.txt: + docs: update framestep document + Remove experimental status from the framestep draft. + +2009-07-08 15:15:04 +0200 Philip Jägenstedt + + * tools/gst-inspect.c: + * tools/gst-launch.c: + tools: Fix compilation if option parsing is disabled + Fixes bug #587976. + +2009-07-08 15:10:26 +0200 Sebastian Dröge + + * gst/gstregistry.c: + registry: Use g_build_filename() instead of g_strjoin() with / + This makes sure that the generated filenames use the platform + specific directory separator instead of /. + Fixes bug #587973. + +2009-07-07 20:13:48 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + docs: add 'Since' tag for new GST_DEBUG_CATEGORY_GET macro + +2009-07-07 00:23:41 +0100 Stefan Kost + + * libs/gst/base/gstcollectpads.c: + collectpads: make it the best of wims and edwards patch. + Check the right flushing flag, but still add it to the pad-list. + +2009-06-30 11:26:34 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + * win32/common/libgstreamer.def: + info: allow getting other log categories. Fixes #587417 + Add a new macro GST_DEBUG_CATEGORY_GET to get a log category by name. This + allows plugins to use e.g. core categories like PERFORMANCE or CLOCK. + API: GST_DEBUG_CATEGORY_GET + +2009-07-06 19:51:57 +0100 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + basetransform: make comment a FIXME comment + +2009-07-06 19:50:52 +0100 Stefan Kost + + * gst/gstminiobject.c: + logging: log object type in message + +2009-07-06 19:48:58 +0100 Stefan Kost + + * libs/gst/base/gstbasesink.c: + logging: use perf category for dropped buffers + +2009-06-29 11:26:57 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Don't forward FLUSH_STOP if some input streams are still flushing. + This guarantees that only one FLUSH_STOP event (the last one) will be sent + downstream when a flushing seek is being done through collectpads. + +2009-06-24 11:11:35 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Update the cookie when setting ourselves as flushing. + This forces the pad status to be re-evaluated on the next _check_pads(). + +2009-06-09 14:54:27 +0100 Tim-Philipp Müller + + * gst/gstbufferlist.c: + * gst/gstbus.h: + * gst/gstchildproxy.h: + * gst/gstelementfactory.h: + * gst/gstghostpad.h: + * gst/gstmessage.h: + * gst/gstquery.h: + * libs/gst/base/gstdataqueue.h: + docs: fix gtk-doc /*< private >*/ marker + +2009-06-09 14:48:56 +0100 Tim-Philipp Müller + + * plugins/elements/gsttypefindelement.c: + typefindelement: log probability in debug message + +2009-06-30 18:22:25 +0200 Wim Taymans + + * gst/gstmessage.c: + message: fix parsing of the step done message + Parse the duration field too. + +2009-06-29 11:24:25 +0200 Edward Hervey + + * gst/gstregistrybinary.c: + binaryregistry: Use local values in while/for loops, use branch prediction macros + +2009-06-29 11:23:31 +0200 Edward Hervey + + * gst/gstcaps.c: + * gst/gstpad.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + * gst/gststructure.c: + Spread branch prediction macros. + These are based on profiling several playback scenarios using playbin2. + +2009-06-29 11:20:12 +0200 Edward Hervey + + * gst/gstpad.c: + * gst/gstregistrybinary.c: + * gst/gstvalue.c: + Use local variables in for/while loops. + This makes the generated code faster since: + * It won't have to read an undirect value (which will most likely be + outside of the L1/L2 cache) + * We know that value never changes (the compiler has no clue that it doesn't). + +2009-06-09 19:08:26 +0200 Edward Hervey + + * libs/gst/controller/gstinterpolationcontrolsource.c: + libs/controller: Set default gst debugging category. + +2009-06-29 11:57:13 +0200 Wim Taymans + + * tests/benchmarks/mass-elements.scm: + tests: fix example + +2009-06-29 11:56:10 +0200 Wim Taymans + + * gst/gstpad.c: + * libs/gst/base/gstbasesink.c: + bufferlist: use faster gst_buffer_list_get() + Use the faster gst_buffer_list_get() to get the first buffer of a list. + +2009-06-29 11:55:14 +0200 Wim Taymans + + * gst/gstbufferlist.c: + bufferlist: fix example + The _do function now takes user_data in all cases. + +2009-06-29 11:46:00 +0200 Ognyan Tonchev + + * libs/gst/base/gstbasesink.c: + basesink: take timestamp later + Make sure we don't accidentally cast a bufferlist of a buffer and try to take + the timestamp of it. + Refixes #585960 + +2009-06-29 11:07:00 +0200 Jonas Holmberg + + * gst/gstbufferlist.c: + docs: fix some typos + +2009-06-29 11:24:04 +0300 Stefan Kost + + * gst/gst_private.h: + * gst/gstinfo.c: + * gst/gstminiobject.c: + * libs/gst/base/gstadapter.c: + * win32/common/libgstreamer.def: + logging: add a performace log category + This category can be used to log slow code path and help auditing the + performance. Add FIXME-0.11 to some questionable categories. + +2009-06-27 16:34:36 +0300 Stefan Kost + + * gst/gststructure.c: + structure: fix int->gint to be in sync with the *.h and usage + +2009-06-26 13:33:50 +0100 Jan Schmidt + + * 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:11 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From f810030 to 5845b63 + +2009-06-26 12:50:53 +0300 Stefan Kost + + * gst/gstelement.c: + request-pad: tell about ref counts in release_request_pad docs. + It is not too obvious that getting and releasing request pads is not entierly + symetrical regarding to the pad refcount. Add a note about that to the docs. + This might deserve a FIXME-0.11 too. + +2009-06-25 11:25:46 +0100 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: don't do things with side effects within a g_assert() + Make the bufferlist stuff work properly when things are compiled + with -DG_DISABLE_ASSERT. + +2009-06-24 18:31:08 +0200 Wim Taymans + + * gst/gstcaps.c: + caps: avoid doing logic in g_assert + Make sure we still do the right thing when glib is compiled without + assertions. + +2009-06-22 05:00:54 +0100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Fire the overrun signal on EOS + Fixes startup of some short MPEG files with decodebin2/playbin2 + where all the data fits in the multiqueue and EOS arrives before + the group is exposed. + +2009-06-24 15:13:37 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From f3bb51b to f810030 + +2009-03-28 13:59:08 +0100 Edward Hervey + + * gst/gststructure.c: + GstStructure: Use direct values for repetitive conditionals (for/while). + +2009-06-24 10:45:52 +0200 Edward Hervey + + * gst/gstbuffer.c: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstminiobject.c: + * gst/gstquery.c: + miniobjects: Don't chain up to empty finalize method. + If ever we do anything in mini_object_finalize, we should make sure the 4 + core miniobject finalize methods chain back up again. + +2009-03-27 20:17:15 +0100 Edward Hervey + + * gst/gstcaps.c: + gstcaps: Use direct values for repetitive conditionals (for/while). + +2009-06-24 09:28:01 +0100 Tim-Philipp Müller + + * Makefile.am: + * gst/gst.c: + make check: add check for enum type class unrefs in gst_deinit() too + Just because we can really. + +2009-06-23 13:44:50 +0200 Wim Taymans + + * gst/gsttrace.c: + * gst/gsttrace.h: + * win32/common/libgstreamer.def: + trace: use proper locking in GstTrace + Protect the allocated list of objects with a lock so that trace actually works + reliably. + Shortcut the alloc trace sooner when disabled. + +2009-06-23 13:34:35 +0200 Wim Taymans + + * gst/gstobject.c: + object: also add pointers to debug + Add the object pointers in the debug info for _replace. + +2009-06-23 12:56:59 +0200 Chad Hanna + + * plugins/elements/gstcapsfilter.c: + capsfilter: Add GAP flag support + capsfilter doesn't actually touch the data so we don't want the GAP flag to + be unset by basetransform. + Fixes bug #586566. + +2009-06-23 10:05:03 +0200 Wim Taymans + + * win32/common/libgstbase.def: + defs: add new byte reader methods + +2009-05-22 14:47:33 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * tests/check/libs/bytereader.c: + bytereader: add a bunch of utility functions for strings and a data dup function + API: gst_byte_reader_dup_data + API: gst_byte_reader_dup_string + API: gst_byte_reader_dup_string_utf8 + API: gst_byte_reader_dup_string_utf16 + API: gst_byte_reader_dup_string_utf32 + API: gst_byte_reader_skip_string + API: gst_byte_reader_skip_string_utf8 + API: gst_byte_reader_skip_string_utf16 + API: gst_byte_reader_skip_string_utf32 + API: gst_byte_reader_peek_string + API: gst_byte_reader_peek_string_utf8 + API: gst_byte_reader_get_string + API: gst_byte_reader_get_string_utf8 + And some basic unit tests. Fixes #586568. + +2009-06-22 18:17:28 +0300 Stefan Kost + + * gst/gsttaglist.c: + taglist: fix typo in tag description + +2009-06-21 00:26:33 +0100 Tim-Philipp Müller + + * tests/check/gst/gstbufferlist.c: + tests: fix crash and leak in bufferlists unit test + Don't access already-freed iterator, makes check-valgrind work and fixes + crash on PPC; unref buffer we're going to steal to make valgrind happy. + +2009-06-21 00:09:53 +0100 Jan Schmidt + + * gst/gst.c: + init: Fix indent, and ref the gst_buffer_list_item_get_type() class + Fix the check tests by reffing the GstBufferList class. Run gst-indent + to make git happy about some existing stuff + +2009-06-19 21:03:46 +0100 Tim-Philipp Müller + + * tools/gst-inspect.c: + gst-inspect: fix broken flags to flag string serialisation + e.g. cdparnoiasrc would show fragment|full for a flags value of 2. + +2009-06-19 19:35:04 +0200 Wim Taymans + + * plugins/elements/gsttee.c: + tee: add buffer-list support + +2009-06-19 19:24:56 +0200 Wim Taymans + + * gst/gstbufferlist.h: + bufferlist: remove old enum from docs + +2009-06-19 14:45:42 +0100 Tim-Philipp Müller + + * gst/gstinfo.h: + gstinfo: define __gst_debug_min to LOG_LEVEL_NONE if debugging is disabled + Just in case someone who clearly can't be deterred by any number of leading + underscores uses this very private but still somewhat documented symbol + directly in their code (*cough* qtdemux *cough*). + +2009-06-19 15:29:14 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: Various cleanups + Add new method to iterate a bufferlist without having to allocate an iterator. + Add convenience method for getting an item from the list based on the group and + index. + Remove redundant _do_data callback and method. + Update unit-tests and add some more for the new methods. + +2009-06-19 14:10:30 +0100 Tim-Philipp Müller + + * gst/gstmessage.c: + * gst/gststructure.c: + docs: make gtk-doc happy + +2009-06-19 13:51:59 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update .po files after string changes + +2009-06-19 13:48:48 +0100 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + fdsink: clean up some more error and debug messages + +2009-06-19 13:42:45 +0100 Tim-Philipp Müller + + * gst/gsttaskpool.c: + taskpool: fix unused variable warning in case debugging is disabled + +2009-06-19 13:40:13 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + gstinfo: fix export of GST_CAT_BUFFER_LIST when --gst-disable-debug is used + Move all the categories to export to one single place, so we don't + accidentally update or add vars in one place but not the other. + +2009-06-18 16:50:42 +0200 Wim Taymans + + * libs/gst/base/gstcollectpads.c: + collectpads: use the right flushing flag. + We need to use the pad private flag because the other pad flag is protected with + the pad lock instead. + +2009-06-18 16:41:46 +0200 Edward Hervey + + * libs/gst/base/gstcollectpads.c: + collectpads: Properly handle flushing pads. + If a pad is flushing, it should not be considered as either eos or + containing data. + +2009-06-18 11:27:21 +0100 Tim-Philipp Müller + + * plugins/elements/gstfdsink.c: + fdsink: fix error message + Users should never see the term 'file descriptor', much less a file + descriptor number, in an error message. Put that into the debug + string instead and use the default error message. + +2009-06-18 11:49:33 +0200 Wim Taymans + + * plugins/elements/gstfdsink.h: + fdsink: add the new field in the header + +2009-06-18 10:55:39 +0200 Benjamin Gaignard + + * plugins/elements/gstfdsink.c: + fdsink: make fdsink seekable + Implement the same logic as filesink to implement seeking. + Fixes #578908 + +2009-06-17 16:45:17 +0200 Josep Torra + + * gst/gstelement.c: + gstelement: moved the clock unref to the right place + +2009-06-17 16:17:27 +0200 Josep Torra + + * gst/gstelement.c: + gstelement: unref the clock when the element changes to null state + +2009-06-17 00:29:40 +0400 Руслан Ижбулатов + + * gst/gst.c: + Replaced deprecated win32-compatibility function with undeprecated one. + Fixes #560442. + +2009-06-16 18:32:12 +0200 Josep Torra + + * gst/gstbin.c: + gstbin: swap the lines of my previous commit + Fixes a bug introduced in my previous commit that released the + clock provider and after used it to create the clock lost message. + +2009-06-16 17:51:12 +0200 Josep Torra + + * gst/gstbin.c: + gstbin: remove clock references when clock lost happens + Remove reference to clock and clock provider stored in the bin + when the clockprovider element is removed from the bin. + +2009-06-16 13:34:38 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.h: + basesink: add Since tag for new method + +2009-06-16 13:32:37 +0200 Branko Subasic + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + basesink: add support for buffer list + Fixes #585960 + +2009-06-16 11:34:54 +0200 Branko Subasic + + * gst/gstghostpad.c: + ghostpad: Add support for GstBufferLists + Fixes #585834 + +2009-06-16 11:21:42 +0200 Christopher Halse Rogers + + * gst/gstiterator.c: + iterator: Explicitly mention refcounting in docs + Fixes #585938 + +2009-06-16 08:43:53 +0100 Tim-Philipp Müller + + * gst/gstelement.c: + * gst/gstutils.c: + gstxml: fix (de)serialisation of properties of type GstStructure + souphttpsrc has a property of type GstStructure, which causes an + assertion when serialising it to xml. Fixes #585137. + +2009-06-15 20:11:05 +0100 Tim-Philipp Müller + + * plugins/elements/gstqueue.c: + queue: fix compiler warning + The compiler suggests to add some () to indicate if the && or the || takes + priority, so reflow code a bit so we don't have to add yet another layer + of (). Hopefully this was the intended meaning of the code. + +2009-06-11 15:00:52 +0200 Arnout Vandecappelle + + * plugins/elements/gstqueue.c: + don't lock when min-threshold and max-size conflict. + When min-threshold is set on a queue, it is possible that one of + the minima remains unsatisfied while one of the maxima is already + reached. Therefore, always consider the queue non-empty if it is full. + Fixes #585433. + +2009-06-15 18:44:45 +0200 Wim Taymans + + * gst/gstbin.c: + bin: make sure we set the next state correctly + When the continue function is scheduled, make sure we set the next state instead + of the pending state. + Add some more debug info. + fixes #585569 + +2009-06-15 18:44:14 +0200 Wim Taymans + + * libs/gst/base/gstcollectpads.h: + collectpads: fix .h indentation + +2009-06-15 18:43:52 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: add some more debug + +2009-06-15 18:42:59 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstpad.c: + debug: add some more debug to element and pads + +2009-06-14 16:56:32 +0400 Руслан Ижбулатов + + * gst/gstsegment.c: + segment: fix include order to get config.h before _mingw.h + config.h must always be included before any other includes, either + directly or indirectly via gst_private.h. Fixes #585733. + +2009-06-14 16:17:50 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + * win32/common/libgstreamer.def: + taglist: add functions to create a new taglist with tags in one go + Add functions to create a new tag list and set tags in one go, which + is nice for use in combination with functions that take ownership of + the taglist, such as gst_event_new_tag() or gst_element_found_tags(). + API: add gst_tag_list_new_full() + API: add gst_tag_list_new_full_valist() + +2009-06-13 14:55:43 +0200 Thomas Vander Stichele + + * scripts/git-version.sh: + git-version.sh: make executable + +2009-06-13 14:53:24 +0200 Thomas Vander Stichele + + * scripts/git-update.sh: + * scripts/git-version.sh: + Update scripts/cvs-update.sh to git-update.sh; add git-version.sh + add script to get git versions + first update all, then build + add gnonlin too + specify where to pull from + also update submodule + rename and change cvs-update script to git-update + +2009-06-12 18:36:15 +0100 Tim-Philipp Müller + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytereader.c: + * libs/gst/base/gstbytereader.h: + * tests/check/libs/bytereader.c: + * win32/common/libgstbase.def: + bytereader: add gst_byte_reader_masked_scan_uint32() + Add a pattern scan function similar to the one recently added to + GstAdapter, and a unit test (based on the adapter one). + Fixes #585592. + API: add gst_byte_reader_masked_scan_uint32() + +2009-04-17 17:59:38 +0300 René Stadler + + * gst/gst_private.h: + * gst/gstinfo.c: + Fix remaining --disable-gst-debug ABI breakage. + Fixes #579177. + +2009-06-12 17:51:22 +0300 Stefan Kost + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + filesrc/sink: turn the bus messages into g_warning + Its a programming error. + +2009-06-12 15:48:35 +0200 Wim Taymans + + * gst/gstmessage.c: + message: fix docs + +2009-06-12 13:18:21 +0200 Wim Taymans + + * docs/design/draft-framestep.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * libs/gst/base/gstbasesink.c: + * tests/examples/stepping/framestep1.c: + stepping: more stepping improvements + Update design doc with step-start docs. + Add eos field to step done message + when stepping in reverse, update the segment time field. + Flush out the current step when we are flushing. + +2009-06-10 15:51:40 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: post step-start + when we clip, also stop the stepping. + Don't do QoS when stepping + Post step-start when queueing and activating the step. + +2009-06-10 15:48:35 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + message: add step-start message + +2009-06-11 14:18:03 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: more efficient value table lookup for fundamental types + Small micro-optimisation: look up value table for fundamental types + via an array dedicated to fundamental types instead of going through + a hash table lookup. Since there can be only 255 fundamental types, + the table size/efficiency trade-off should be acceptable, esp. since + the most commonly-used types are all fundamental types. The size of + the table could probably be minimised further if needed by allocating + the table dynamically and only expanding it on demand. + +2009-06-11 13:16:15 +0100 Tim-Philipp Müller + + * gst/gstvalue.c: + gstvalue: don't put GTypes into int variables + GTypes are not ints and as such are not guaranteed to fit into an int + (with the exception of fundamental types), so we really shouldn't put + them into int variables. Even if a rather unlikely obscure corner case, + this has actually been a problem at some point in the past, see commit + 99f16655f4cfbc8e06b5972417ba11279083a64e. + +2009-06-11 17:03:04 +0300 Stefan Kost + + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + filesrc/sink: improve warning message a bit (wrong state) + Unify and turn those into element warnings. + +2009-06-11 14:00:09 +0100 Jan Schmidt + + * gst/gstelementfactory.c: + elementfactory: Fix a compiler warning + Use (gpointer) instead of (gpointer *) to fix a strict-aliasing build warning. + +2009-06-11 13:16:29 +0100 Jan Schmidt + + * common: + * docs/faq/Makefile.am: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/manual/Makefile.am: + * docs/plugins/Makefile.am: + * docs/pwg/Makefile.am: + docs: Bump common, fix the upload logic inclusion + Update the common submodule, and fix the docs upload rules to include + the right makefile snippet from common. + +2009-06-09 11:13:04 +0100 Jan Schmidt + + * plugins/elements/gstmultiqueue.c: + multiqueue: Use the slice allocator for MultiQueueItems + +2009-06-10 20:29:41 +0100 Tim-Philipp Müller + + * gst/gst_private.h: + * gst/gstregistrybinary.h: + Make sure config.h is only included once + Fixes build problem on win32 (#585075). + +2009-06-10 18:05:47 +0300 Stefan Kost + + * gst/gstplugin.c: + plugin: add since: tags for the api docs. + The previous related commit added new API. + API: add gst_plugin_get_cache_data, gst_plugin_set_cache_data + +2009-06-10 12:02:23 +0300 Stefan Kost + + * gst/gstplugin.c: + plugin: fix leaks introduced by fix for #584389 + +2009-06-08 23:43:16 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: + * gst/gststructure.h: + * tests/check/gst/gststructure.c: + * win32/common/libgstreamer.def: + structure: add gst_structure_*_get*() vararg functions + Add a bunch of vararg getter convenience functions to complement + the vararg setter functions, and a basic unit test. Fixes #534208. + API: gst_structure_get() + API: gst_structure_id_get() + API: gst_structure_get_valist() + API: gst_structure_id_get_valist() + +2009-06-09 00:16:05 +0100 Tim-Philipp Müller + + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gsttaglist.c: + docs: a few small API doc fixes and additions + +2009-06-08 19:33:55 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + logging: when logging taglists, shorten long buffer dumps + Don't dump hundreds of kB of hexdata into debug logs when converting + taglists containing huge images into a string. Instead, shorten the + buffer data so that the string is still readable and debug logs + stay managable. Can be turned off with GST_DEBUG_OPTIONS=full-tags. + See #584988. + +2009-06-09 13:07:34 +0200 Wim Taymans + + * plugins/elements/gstmultiqueue.c: + multiqueue: check byte range even when we have timestamps + As found by thaytan on IRC. + Also check the byte limit, even if we have timestamps because there might just + not be a time limit. + +2009-06-09 12:06:35 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: update segment start/stop for clipping + When we start stepping, store the start/stop values of the segment before we + install new start/stop values for clipping in non-flushing steps. + for non-flushing steps, update the element start time. For flushing steps, it + does not change because running_time does not advance + Make sure we always perform the stop_stepping operations even when we drop + frames. + +2009-06-09 10:25:34 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: do proper clipping in stepping + Update the stop position of the segment so that we clip correctly. + After clipping in non-flushing mode, rerender the remainder of the buffer. + +2009-06-09 10:23:23 +0200 Wim Taymans + + * gst/gstsegment.c: + segment: make conversion more precise + Make sure the conversion from and the conversion to give the same results. + +2009-06-08 15:39:59 +0100 Tim-Philipp Müller + + * gst/gstutils.c: + utils: gst_util_uint64_scale*() micro-optimisations + Sprinkle G_LIKELY/G_UNLIKELY; add inlined _scale_int_unchecked() + so we don't do some checks twice when calling it from _scale(). + +2009-06-07 22:49:01 +0100 Tim-Philipp Müller + + * gst/gsturi.c: + * gst/gstvalue.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/libs/transform1.c: + Remove double semicolons at end of line + +2009-06-08 17:39:47 +0200 Wim Taymans + + * docs/design/draft-framestep.txt: + * libs/gst/base/gstbasesink.c: + stepping: do flushing steps correctly + Note in the docs that a flushing step in PLAYING brings the pipeline to the lost + state and skips the data before prerolling again. + Implement the flushing step correctly by invalidating the current step + operation, which would activate the new step operation. + +2009-06-08 16:16:27 +0100 Jan Schmidt + + * libs/gst/base/gstbasesink.c: + basesink: Change awkward wording in a translateable message. + +2009-06-08 16:27:36 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add non-flushing steps + Add support for non-flushing steps and with different rates. + Clear step info when flushing + +2009-06-07 23:46:54 +0300 Stefan Kost + + * docs/gst/gstreamer-sections.txt: + * gst/gst_private.h: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstregistrybinary.c: + * gst/gstregistrybinary.h: + * win32/common/libgstreamer.def: + registry: allow plugins to cache extra data in registry. Fixes #570233 + Add a GstStructure to GstPlugin. Plugins can retieve it in plugin_init and + access the cached info or build the cache and store it there. + +2009-06-07 22:09:14 +0300 Stefan Kost + + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstplugin.c: + * win32/common/libgstreamer.def: + registry: don't recreate features on first use. Fixes #584389 + The first time one calls gst_element_factory_make(), gst recreates the plugin + feature and the element factory. As a side effect we ref the class to fill + in detail we already have filled from the registry cache. This patch changes + the behaviour to just update the existing entries. The factory is now attached + to the type and set in gst_element_base_class_init(). + +2009-06-07 22:20:54 +0200 Wim Taymans + + * configure.ac: + * tests/examples/Makefile.am: + tests: conditionally compile the streams example + Detect pthreads.h in configure.ac + Only compile the streams example when pthreads.h is present. + Fixes #585039 + +2009-06-07 17:32:35 +0200 Wim Taymans + + * gst/gstvalue.c: + gstvalue: remove type checks and redundant code + +2009-06-07 15:43:57 +0200 Wim Taymans + + * gst/gstvalue.c: + value: fix fraction range lcopy function + This function seems to be broken for 3.5 years. Luckily nobody ever tried to + make a fraction range object property... + +2009-06-07 15:35:12 +0200 Wim Taymans + + * gst/gstvalue.c: + gstvalue: performance improvements + Add a GType->GstValueTable hashtable mapping. + Avoid _get_type() multiple times when we can. + Use GSlice for fraction range dynamic memory + Add G_LIKELY when we can + Improve lookup of the value table using the hashtable + +2009-06-07 14:30:28 +0200 Wim Taymans + + * gst/gststructure.c: + structure: no need to clear on init + We don't need to clear the field on init because we will do that again before we + are going to use the field later. + +2009-06-05 20:57:05 +0100 Jan Schmidt + + * gst/gststructure.c: + * gst/gstvalue.c: + gststructure: Fix some memory leaks. Sprinkle G_LIKELY/UNLIKELY + Fix some memory leaks shown by the new serialisation/deserialisation unit + test. Split the gst_string_wrap function in gstvalue.c into components and + use them to make gst_string_take_and_wrap, which takes ownership of the + string, avoiding a strdup. + Add some G_LIKELY/UNLIKELY, and clean up some leaks in error paths. + +2009-06-05 11:37:24 +0200 Mark Nauwelaerts + + * libs/gst/base/gstbasesrc.c: + basesrc: reply to QUERY_SEEKING with original format. Fixes #584838. + +2009-06-04 19:44:38 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + configure: remove AC_C_INLINE and update win32 files to git + Remove AC_C_INLINE check, so we don't end up with an #undef inline in + config.h, which causes problems with some versions of MSCV apparently. + GLib defines inline for us in a suitable way already anyway. + Fixes #584835. + While we're at it, also update the other win32 files to git (bump + version, add new defines and enums). + +2009-06-04 18:26:04 +0200 Wim Taymans + + * gst/gstghostpad.c: + ghostpad: avoid excessive notify for caps + Avoid an object property notify if the caps on the other pad were already + set (and thus notified). + +2009-06-04 17:27:03 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix clipped start/stop after step + Use the segment helpers to get a more accurate clipped start/stop position after + a stepping operation ended. + +2009-06-04 12:34:47 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: use more correct segment methods + Use the more correct new segment methods for updating the segment before and + after a step. + +2009-06-04 12:48:51 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: add gst_segment_set_running_time + Added new method for closing the segment to a specific running time. + API: GstSegment::gst_segment_set_running_time() + +2009-06-04 00:37:28 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update .po files for string changes + This makes sure that people who get themselves a fresh checkout + don't immediately have changed *po files after running make, which + would cause a bit of hassle next time the files are updated. Better + to keep them up-to-date when strings change. + +2009-06-04 00:54:24 +0100 Tim-Philipp Müller + + * gst/gsterror.c: + errors: reword state change failed error message and remove bugzilla link + Reword this message a bit to make it clearer what it means, namely that + the state change may have failed for good reasons, but that the element + just failed to post a proper error on the bus. This is not an internal + GStreamer bug, and we really don't need people to flood bugzilla with + bug reports if one such plugin bug ever makes it into the wild. + +2009-06-04 00:29:31 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: refer to element, pad, or object in some message strings + Revisit these strings now that the change regarding the message source + object in gst_element_found_tags_for_pad() got reverted. Try to refer + explicitly to what kind of element it is (element, pad, etc.) in some + cases, which is nicer than having to deduce this info (and we can + re-use the already existing translated strings for the most common + case). It also makes for better example code, since it's clear now + that the message source object doesn't have to be an element. + +2009-06-03 21:10:39 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.h: + API: add GST_MESSAGE_SRC_NAME macro + Add GST_MESSAGE_SRC_NAME macro that always returns a non-NULL string. + Useful for debugging and logging purposes. + +2009-06-03 19:06:30 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * tests/check/gst/gstsegment.c: + * win32/common/libgstreamer.def: + segment: add method for converting to position + Add gst_segment_to_position() that converts a running_time to a position in the + segment. A faulty variant of this function is currently used in inputselector + but we'll need it for frame stepping too. + API: GstSegment::gst_segment_to_position() + +2009-06-03 15:39:13 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink; handle EOS correctly. + Handle EOS and buffers without a timestamp gracefully. + Remove a warning that is not so much a warning now anymore. + +2009-06-03 09:45:25 +0100 Tim-Philipp Müller + + * autogen.sh: + * common: + * configure.ac: + Revert "go back to allowing gettext 0.11.5, but don't mix with libtool 2.2" + This reverts commit 31c09d738ce7f47bff9d292996e9489c275e55a1. + Reverting this, since it breaks autogen.sh for me on debian sid. + Failure is: "libtool 2.2 requires autopoint 0.17 or higher" even though + 0.17 was found. + +2009-06-03 09:41:21 +0100 Tim-Philipp Müller + + * autogen.sh: + Revert "only update submodule when it is not on a specific branch" + This reverts commit 93b83333aad519c5555156576f0baa3be7b263f3. + Reverting since this fails on a fresh checkout. Also, we shouldn't + depend on possibly translated strings. + +2009-06-03 01:56:10 +0100 Tim-Philipp Müller + + * docs/manual/highlevel-components.xml: + docs: fix up reference to gst-launch-0.8 + Also mention decodebin2, uridecodebin, and playbin2 + +2009-06-03 10:39:53 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: forget previous times when stepping + When we start a flushing step operation, forget about the previous stream time + so that the position reporting works correctly. + +2009-06-03 01:25:26 +0200 Thomas Vander Stichele + + * autogen.sh: + * common: + * configure.ac: + go back to allowing gettext 0.11.5, but don't mix with libtool 2.2 + +2009-06-03 01:01:57 +0200 Thomas Vander Stichele + + * autogen.sh: + only update submodule when it is not on a specific branch + +2009-06-02 13:45:52 -0700 David Schleef + + * tools/gst-launch.c: + tools: Set pipeline to PAUSED before waiting for main loop idle + When it is shutting down a pipeline after ctrl-c, set pipeline to + paused before waiting for the main loop to complete all pending + transactions. Fixes #584657. + If some part of the pipeline is generating signals or idle functions + at a fast rate, waiting for a main loop iteration may never return. + +2009-06-02 18:36:10 +0300 Stefan Kost + + * gst/gst_private.h: + * gst/gststructure.c: + * gst/gstvalue.c: + * tests/check/gst/gststructure.c: + structure: fix serialisation of nested structures. + Use string_warp/unwrap to escape delimiters, otherwise deserialisation fails. + Also move GST_ASCII_IS_STRING to private header to avoid keeping it in sync. + Also use '\0' when terminating a string for better readability. + +2009-06-02 15:37:22 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: fix regression in unit tests + Store the timestamp of the buffer after prerolling. While we are prerolled we + want to report the position of the segment start value. + +2009-06-01 20:26:53 +0100 Tim-Philipp Müller + + * gst/gstinfo.c: + info: widen log level strings to take into account the new MEMDUMP + +2009-06-01 19:37:14 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: post a warning on excessive framedrops + When we go into emergency rendering, post a warning informing the user about + this fact. + +2009-05-31 19:10:02 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: more stepping in reverse + Fix stepping and position reporting in reverse playback. + +2009-05-29 16:06:52 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: use start_time as the step start + Use the start_time of the element as the point from where the step operation + starts. This fixes stepping in all paused states. + +2009-05-19 19:45:06 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: catch step cases in _wait_preroll() + When a subclass is blocking in _wait_preroll() in the _render method, make sure + we can unlock the subclass and detect this return value from the render method. + +2009-05-19 10:50:57 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: more stepping in reverse fixes + +2009-05-18 18:41:45 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: small cleanups + +2009-05-18 15:48:20 +0200 Wim Taymans + + * docs/design/draft-framestep.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * libs/gst/base/gstbasesink.c: + * tests/examples/stepping/framestep1.c: + framestep: implement backwards framestep + Update framestep document, we want to pass the flush flag in the step-done + message. + Add flush flag to the gstmessage. + Update examples to use the new step-done message api. + Implement framestep with playback rates < 0.0 too. + +2009-05-15 15:25:06 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: add framestepping in time + +2009-05-15 15:24:30 +0200 Wim Taymans + + * tests/examples/stepping/framestep1.c: + examples: step in time as well + +2009-05-15 12:02:02 +0200 Wim Taymans + + * tests/examples/stepping/framestep1.c: + example: print step_done message and sync + Dump the step_done message contents. + Sync against the clock when going to PLAYING. + +2009-05-15 12:05:44 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: keep track of stepped time + Pass running_time around so that the stepping code can calculate the elapsed + time correctly. + +2009-05-14 19:29:08 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: move stuff around, more stepping + Make start and stop_stepping methods and move their invocation in the right + places. + Perform the atual stepping operation where we have full context about the + timestamps. + +2009-05-11 18:56:03 +0200 Wim Taymans + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/stepping/.gitignore: + * tests/examples/stepping/Makefile.am: + * tests/examples/stepping/framestep1.c: + Add frame stepping in PAUSED example + +2009-05-11 18:56:56 +0200 Wim Taymans + + * libs/gst/base/gstbasesink.c: + basesink: first stab at frame stepping in PAUSED + Unlock the prerolled frame and recheck if we need to step. + Keep a simple counter for the frames we're about to skip while stepping and + preroll/post step_done when stepping finished. + +2009-06-01 12:19:52 +0200 Wim Taymans + + * docs/design/draft-framestep.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstquark.c: + * gst/gstquark.h: + * win32/common/libgstreamer.def: + add new API for framestepping + Add new STEP event and methods for creating/parsing the event + Update design docs. + Add new STEP_DONE message and method to create/parse. + API: GstEvent::gst_event_new_step() + API: GstEvent::gst_event_parse_step() + API: GstMessage::gst_message_new_step_done() + API: GstMessage::gst_message_parse_step_done() + +2009-06-01 10:05:32 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + structures: don't leak invalid or empty strings when we warn + Fixes minor memory leak in unit tests caused by the recent changes. + Since we're expected to take ownership of the GValue in the structure + field struct here, we need to unset it if we don't use it. + +2009-06-01 11:08:31 +0300 Stefan Kost + + * tests/check/libs/controller.c: + controller: add test for cubic int. and too few control points + Added another tests to check some worries in Bug #582564. + +2009-05-28 12:31:08 +0300 Stefan Kost + + * plugins/elements/gstfakesrc.c: + fakesrc: add a FIXME comment for blocksize vs. size-max property issue + +2009-05-31 21:27:40 +0100 Tim-Philipp Müller + + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + identity: hack around g_object_notify() bug by protecting it with a lock + Out-of-band events might lead to us calling g_object_notify() from a + non-streaming thread, which can cause crashes if g_object_notify() is + being called from the streaming thread at the same time. See #554460. + +2009-05-31 22:37:59 +0300 Stefan Kost + + * tests/benchmarks/controller.c: + controller: use real world number in benchmark + +2009-05-31 22:37:03 +0300 Stefan Kost + + * gst/gstregistry.c: + registry: fix comment formatting + +2009-05-30 20:36:25 +0100 Tim-Philipp Müller + + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + * tests/check/Makefile.am: + * tests/check/elements/fakesink.c: + fakesink: hack around crasher bug in g_object_notify() for out-of-band events + GObject may crash if two threads do concurrent g_object_notify() on the same + object. This may happen if fakesink receives an out-of-band event such as + FLUSH_START while processing a buffer or serialised event in the streaming + thread. Since this may happen with the default settings during a common + operation like a seek, and there seems to be little chance of a timely fix + in GObject (see #166020), we should hack around this issue by protecting all + of fakesink's direct g_object_notify() calls with a lock. + Also add unit test for the above. + Fixes #554460. + +2009-05-31 16:17:45 +0100 Tim-Philipp Müller + + * gst/gsttaglist.c: + taglists: make _get_{string|pointer} return FALSE for NULL values + Make gst_tag_list_get_string() return FALSE for NULL strings and + empty strings, and gst_tag_list_get_pointer() return FALSE for + NULL pointers, like we do with dates and buffers. + Fixes #560345. + +2009-05-30 20:50:40 +0100 Tim-Philipp Müller + + * gst/gststructure.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gsttag.c: + taglists: warn if someone tries to add empty or NULL string tags to a taglist + Also warn if an element or application tries to add a field with an + empty string to a structure (NULL strings are still needed and + allowed though) and do all those checks in the right function. + Fixes #559643. + +2009-05-29 18:22:42 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquery.c: + * gst/gststructure.c: + * gst/gststructure.h: + * win32/common/libgstreamer.def: + structure: add gst_structure_id_new() convenience function + Add convenience wrapper for gst_structure_id_empty_new() plus + gst_structure_id_set() and use it in a few places. + API: gst_structure_id_new() + +2009-05-29 18:00:06 +0100 Tim-Philipp Müller + + * gst/gstevent.c: + * gst/gstmessage.c: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: + * gst/gsttaglist.c: + micro-optimisation: use GST_QUARK in more places + Use gst_structure_id_empty_new() in combination with GST_QUARK + rather than gst_structure_id_new() when creating message, event, + query and taglist structures. Mostly just because we can. + +2009-05-29 16:04:28 +0200 Wim Taymans + + * gst/gstelement.c: + element: reset start_time in lost state + +2009-05-29 13:03:15 +0200 Wim Taymans + + * gst/gstelement.c: + * gst/gstpipeline.c: + docs: update element an pipeline docs + +2009-05-29 12:48:28 +0200 Wim Taymans + + * docs/design/part-TODO.txt: + docs: remove a TODO item that is fixed now + +2009-05-29 12:21:36 +0200 Wim Taymans + + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * tests/check/gst/gstpipeline.c: + pipeline: deprecate old methods, fix test + Deprecate the old _set_stream_time and _get_last_stream_time methods because + they are now equivalent to the better named _set/_get_start_time. + +2009-05-28 16:30:52 +0200 Wim Taymans + + * gst/gstpipeline.c: + * gst/gstpipeline.h: + pipeline: use START_TIME to keep track of time + Use the element START_TIME to keep track of the running time when the pipeline + paused so that it can be used to restore the base_time. + Take the start_time before setting the children to PAUSED so that we can + distribute the start_time to the children. + +2009-05-28 15:40:01 +0200 Wim Taymans + + * gst/gstbin.c: + bin: set the base_time and start_time better + Simply set the start_time and base_time on the element instead of calling the + setters. + +2009-05-27 11:35:58 +0200 Wim Taymans + + * gst/gstbin.c: + bin: make the bin set the start_time on elements + Set the start_time of the bin on the elements when they are added to the + pipeline and when a state change happens. + +2009-05-26 11:53:05 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: add start_time field an methods + Add a start_time field and some methods. The start_time will contain the + running_time of when the element last went to paused. This time can be user to + report the position in PAUSED but also to do more correct clipping and + stepping later. + +2009-05-28 22:02:21 +0200 Arnout Vandecappelle + + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + adapter: fix _masked_scan_uint32() at boundaries + gst_adapter_masked_scan_uint32 could return values smaller than offset + if the first byte(s) of the mask are 0 and the pattern matches the + beginning of the adapter. + Added examples to documentation of gst_adapter_masked_scan_uint32(). + Also added some more masked boundary tests. + Fixes #584118 + +2009-05-28 16:36:32 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + pad: add pad private structure + Add pad private structure and move the new chainlistfunc into the private + struct. This avoids ABI breakage and allows us to expand in the future. + +2009-05-27 16:34:19 +0200 Sebastian Dröge + + * win32/common/libgstbase.def: + Add missing symbol to the win32 exports + This was accidentially removed by my last commit. + +2009-05-27 16:17:31 +0200 Wim Taymans + + * gst/gstbuffer.c: + buffer: avoid memory leaks + Avoid leaking the caps of the dest buffer and avoid doing needless caps + refs. + When the source and target buffers are the same, return immediatly. + +2009-05-27 14:32:51 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstutils.c: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + API: Add gst_message_{new,parse}_tag_full() to get/set the source pad + Fixes bug #582588. + +2009-05-27 14:06:13 +0200 Sebastian Dröge + + * gst/gstutils.c: + Revert "element: Set the originating pad as message source in gst_element_found_tags_for_pad ()" + This reverts commit bebfde75027e975b7e7c74c6358c5be83ea4ac9f. + This change shouldn't be done in a stable release series as + applications are actually expecting the sender to be an + GstElement. One example is totem. + +2009-05-26 11:35:49 +0100 Jan Schmidt + + * common: + Update common + +2009-05-26 10:41:28 +0100 Tim-Philipp Müller + + * Makefile.am: + Fix 'make distcheck' + The check-enum-gettypes rule didn't work for 'make distcheck' since + it makes assumptions about the location of the source files from the + current working directory which isn't true during distchecking. + +2009-05-26 10:38:56 +0100 Tim-Philipp Müller + + * docs/manuals.mak: + manuals.mak: attempt to make 'make distcheck' work with -jN + Attempt to fix the 'cannot create regular file build/image.entitites: + file exists' error I got. + +2009-05-25 23:58:37 +0100 Tim-Philipp Müller + + * tools/gst-launch.1.in: + docs: fix cdparanoia example pipeline in gst-launch man page + +2009-05-25 18:44:14 +0200 Wim Taymans + + * gst/gstelement.c: + element: fix typo in comments + +2009-05-25 17:43:32 +0100 Jan Schmidt + + * tests/examples/streams/Makefile.am: + dist: Fix the name of the header to dist: testrtpool.h, not rtpool-test.h + +2009-05-25 17:03:05 +0100 Jan Schmidt + + * common: + Update common + +2009-05-25 16:54:25 +0200 Wim Taymans + + * gst/gstclock.c: + clock: remove assertion + Remove an assertion, this is not really an error in all cases. + Fixes #582010 + +2009-05-25 16:21:55 +0200 Wim Taymans + + * gst/gstsystemclock.c: + clock: enable monotonic clock when we can + Enable the monotonic clock by default when we can. + Fixes #583554 + +2009-05-25 14:52:13 +0200 Wim Taymans + + * docs/design/draft-klass.txt: + docs: add Image to draft klass documentation + +2009-05-25 13:03:42 +0200 Wim Taymans + + * gst/gstpad.c: + pad: keep task ref before releasing the lock + Keep a ref to the task on the pad so that a concurrent stop can stop and join + the task. + +2009-05-25 11:56:47 +0200 Wim Taymans + + * gst/gsttask.c: + gsttask: avoid join to return early + Unset the running flag after we released the lock for posting the stream-status + message. If we set the running flag to FALSE too early, the join method will + just continue without waiting for the message to be posted, leading to potential + crashes. + +2009-05-24 23:14:26 +0300 Stefan Kost + + * gst/gstpreset.c: + preset: fix update rule + Only update the preset from system, if we had a preset before and system + version is newer. + +2009-05-22 23:47:30 +0300 Stefan Kost + + * tests/benchmarks/.gitignore: + * tests/benchmarks/Makefile.am: + * tests/benchmarks/controller.c: + controller: add a benchmark to verify the switch to gsequence + +2009-05-22 23:50:58 +0300 Stefan Kost + + * tests/examples/controller/audio-example.c: + controller: add more error handling to example + +2009-05-22 23:14:41 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + registry: don't free node-date and deref again. Fixes #580579 + When writing a cache chunk fails, we were freeing the node and jump to a final + cleanup which dereferenced a null pointer. Leve freeing the node to the cleanup + code in fail_free_list. (sorry for committing wrong fix before). + +2009-05-22 23:10:00 +0300 Stefan Kost + + * gst/gstregistrybinary.c: + registry: don't free node-date and deref again. Fixes #580579 + When writing a cache chunk fails, we were freeing the node and jump to a final + cleanup which dereferenced a null pointer. Leve freeing the node to the cleanup + code in fail_free_list. + +2009-05-22 14:17:56 +0300 Stefan Kost + + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: add G_LIKELY and join two if for same condition + A G_LIKELY for the sequence!=NULL checks. Join two ifs to an if-else. Add + indent guides to keep indent form breaking the function declaration + +2009-05-22 12:57:10 +0200 Edward Hervey + + * libs/gst/base/gsttypefindhelper.c: + gsttypefindhelper: Fix indentation + +2009-05-22 12:24:22 +0300 Stefan Kost + + * gst/gstclock.c: + * gst/gstmessage.c: + * gst/gstpad.c: + * gst/gstquery.c: + * gst/gsttask.c: + docs: fix gtk-doc warnings + Move MT safety to main description (it does not belong to Return: or Since: + statement). Add a few missing return docs. Downgrade a normal comment froma doc + comment. Fix a doc header to only contain symbol name. + +2009-05-22 10:19:36 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From d3a8fab to 888e0a2 + +2009-05-22 09:51:44 +0100 Jan Schmidt + + * tests/examples/streams/Makefile.am: + dist: Add rtpool-test.h to the sources list so it gets disted. + Fixes the distcheck + +2009-05-22 09:44:25 +0100 Jan Schmidt + + * tests/benchmarks/.gitignore: + gitignores: Ignore the clockstress benchmark binary + +2009-05-22 09:41:36 +0100 Jan Schmidt + + * libs/gst/controller/gstinterpolation.c: + controller: Silence a warning from the GSequence being NULL. + Fix a warning that occurs when the self->priv->values is NULL and + the code tries to retrieve an iterator from it. The warning was showing + up in the checks for the volume element. + +2009-05-22 09:33:02 +0100 Jan Schmidt + + * gst/gstelement.c: + * gst/gstmessage.c: + * gst/gstpad.c: + * gst/gsttask.c: + * gst/gstutils.h: + docs: Fix up some documentation warnings. + Since: tags should always be the last thing in a doc block, apparently. + Add some Returns: descriptions to some recent functions. + +2009-05-21 17:32:00 +0200 Wim Taymans + + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstpipeline.c: + docs: update docs for stream_time->running_time + Change some instances where we wrongly refer to stream time where it should have + been running time. + +2009-05-21 10:57:47 +0100 Tim-Philipp Müller + + * tools/gst-launch.c: + gst-launch: don't use G_GUINT32_FORMAT in translatable string + xgettext doesn't handle this very well. Fixes #583419. + +2009-05-20 17:07:37 +0100 Tim-Philipp Müller + + * autogen.sh: + autogen.sh: can remove the -Wno-portability from here now + since we added it to configure.ac. + +2009-05-20 22:18:16 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: improve the flush function + Remove a compare and branch from flush. + +2009-05-20 17:24:19 +0300 Stefan Kost + + * libs/gst/controller/gstinterpolationcontrolsource.c: + controller: fix assertion when freeing the control source + +2009-05-20 12:48:41 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: potentially save a memcpy in _take + Directly use the assembled_data in _take() functions when we can instead of + copying it out. + +2009-05-20 11:36:11 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: micro optimisations + +2009-05-20 11:12:43 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: avoid comparisions in fast path + Small tweaks to reduce the number of useless compares in loops. + +2009-05-20 10:28:08 +0200 Wim Taymans + + * tests/check/libs/adapter.c: + tests: one more adapter test + +2009-05-20 10:27:43 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: avoid branch in copy code + +2009-05-20 10:56:11 +0300 Hannes Bistry + + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstpad.c: + loadsave: fix requestpad handling and serialisation order. + Support request pads when loading. Reverse pad serialisation order to + preserve it when recreating the pipeline. + +2009-05-20 00:45:27 +0200 Wim Taymans + + * win32/common/libgstbase.def: + defs: add new symbol + +2009-05-20 00:44:11 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + docs: add new symbol to docs + +2009-05-20 00:37:53 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: + adapter: add _masked_scan_uint32 + Add a reasonably optimized new gst_adapter_masked_scan_uint32() function + to scan the adapter for a pattern after applying a mask. + Add some unit tests. + API: GstAdapter::gst_adapter_masked_scan_uint32() + Fixes #583187 + +2009-05-19 22:13:04 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: more optimisations + Remove duplicate copy code (_peek_into and _copy) and make a unified + optimized copy function. + +2009-05-19 17:12:41 +0100 Tim-Philipp Müller + + * configure.ac: + configure: pass -Wno-portability to automake to suppress warnings + GNU make is required, no point pretending otherwise. + +2009-05-18 01:00:36 +0100 Tim-Philipp Müller + + * gst/gstformat.h: + docs: mention that GST_FORMAT_{PERCENT|BUFFERS} are not implemented + +2009-05-17 10:46:39 +0200 Sebastian Dröge + + * gst/gstclock.c: + * gst/gstclock.h: + gstclock: Fix ABI breakage on 32 bit architectures + The padding of GstClock is a GstClockTime and not a + gpointer, so adding a pointer requires the padding + size to be changed depending on the pointer size. + Use an union instead. + Fixes bug #582878. + +2009-05-15 15:24:40 -0300 Thiago Santos + + * gst/gstvalue.h: + [gstvalue] adds safety parenthesis to macros missing them. + +2009-05-15 14:42:48 -0300 Thiago Santos + + * gst/gstutils.h: + [gstutils] Adds more safety to GST_WRITE_* and GST_READ_ macros. + Adds safety ( ) to parameters in _GST_PUT and _GST_GET macros. + Fixes #582708. + +2009-03-19 11:37:12 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + clock: use seqlocks to parallellize readers + +2009-04-16 15:53:29 +0200 Wim Taymans + + * tests/benchmarks/Makefile.am: + * tests/benchmarks/gstclockstress.c: + stress: add a clock stresstest + Add a stresstest for gst_clock_get_time(). + +2009-05-15 11:00:53 +0200 Edward Hervey + + * docs/design/Makefile.am: + * gst/Makefile.am: + Makefile.am: update for added/moved/removed files that weren't dist-ed. + +2009-05-12 11:29:21 +0100 Jan Schmidt + + * docs/random/release: + docs: Release script modifications + +2009-05-14 22:11:57 +0200 Sebastian Dröge + + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + controller: Use ordered GSequence instead of GList + This makes lookups and insertions O(log n) instead of + always O(n) for insertions and O(n) in worst case for + lookups. + Fixes bug #582564. + +2009-05-14 12:30:23 +0200 Wim Taymans + + * docs/design/draft-ghostpads.txt: + * docs/design/part-latency.txt: + * docs/design/part-missing-plugins.txt: + * docs/design/part-stream-status.txt: + docs: rename and delete some design docs + +2009-05-14 12:30:04 +0200 Sebastian Dröge + + * tools/gst-launch.c: + gst-launch: Print the path string for message sources + This reduces confusion if the message source is a pad + and only "src" is printed as source. + +2009-05-14 12:25:20 +0200 Sebastian Dröge + + * gst/gstutils.c: + element: Set the originating pad as message source in gst_element_found_tags_for_pad () + Fixes bug #582588. + +2009-05-14 11:36:28 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + * win32/common/libgstreamer.def: + element: add gst_element_lost_state_full() + Add a gst_element_lost_state_full() with an extra argument to control + distribution of a new base_time. We will need this for flushing step + operations. + API: GstElement::gst_element_lost_state_full() + +2009-05-13 23:52:02 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: don't use realloc, it does a memcpy + Don't use realloc to grow the scratch area because we don't want the memcpy the + old useless data into the new area before we write our new stuff in it. + +2009-05-13 23:38:08 +0200 Wim Taymans + + * docs/design/part-trickmodes.txt: + docs: update trickmode document + +2009-05-13 22:51:18 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: use g_realloc for resizing the buffer + Use g_realloc for resizing the internal buffer instead of a + less fancy _free/_malloc pair. + +2009-05-13 21:35:23 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: move new member to private struct + Move the new members to a private struct because we don't have enough padding + anymore on 32-bits platforms. + +2009-05-13 18:50:23 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + adapter: update some docs + +2009-05-13 17:09:32 +0200 Wim Taymans + + * tests/check/libs/adapter.c: + tests: add another test for adapter timestamps + +2009-05-13 16:48:38 +0200 Wim Taymans + + * tests/check/libs/adapter.c: + tests: add new timestamp unit test + +2009-05-13 16:26:00 +0200 Wim Taymans + + * win32/common/libgstbase.def: + defs: add new symbol + +2009-05-13 16:09:20 +0200 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: add method to keep track of timestamps + Keep track of the timestamp and offset associated with the current head of the + adapter. + API: GstAdapter::gst_adapter_prev_timestamp() + +2009-05-13 16:20:26 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + adapter: small cleanups + +2009-05-13 11:03:27 +0300 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: show more pad-details + Show pad activation mode and pad-flags inside the pad. Write down some ideas + about how we could improve the caps layout. + +2009-05-13 00:29:57 +0300 Stefan Kost + + * gst/gstdebugutils.c: + debugutils: layout improvement + dot does not take the head/tail labels into account. For unfixed caps they get + quite large. Double the padding to make it sort of readable in more cases. Also + make normal font bigger and caps-label font smaller to increase our luck. + +2009-05-12 21:00:15 +0100 Tim-Philipp Müller + + * Makefile.am: + checks: check for enum types not class_ref'ed in gst_init() in 'make check' + +2009-05-12 20:58:32 +0100 Tim-Philipp Müller + + * gst/gst.c: + Initialise some more types in gst_init(), esp. the new enum types + Possibly fixes GObject class creation/unref race conditions when + creating the last-message string in fakesink for events with + structures that have fields with these enum types. + +2009-05-12 20:56:06 +0100 Tim-Philipp Müller + + * gst/gstsystemclock.c: + systemclock: remove duplicate _get_type() function for GstClockType + Remove the static gst_clock_type_get_type() function in the + systemclock code in favour of the public one in gstenumtypes.c. + +2009-04-22 10:53:37 +0300 Stefan Kost + + * gst/gstghostpad.c: + ghostpad: remove deprecated API + _internal_link_function() is deprecated and _iterate_internal_links_function() + is already provided. + +2009-04-21 11:33:43 +0300 Stefan Kost + + * gst/parse/grammar.y: + parse-launch: allow specifying GstElement properties via gst_parse_bin_from_description + If deserializing a property fails, check if the value type is a string and if so + attempt to create a bin from the string value. This allows to e.g. specify + audio-sink/video-sink for playbin on gst-launch commandline. + +2009-05-12 17:29:15 +0200 Wim Taymans + + * docs/design/part-bufferlist.txt: + docs: add some docs about buffer lists + +2009-05-12 16:18:48 +0200 Wim Taymans + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + bufferlist: make objects opaque + +2009-05-12 15:33:25 +0200 Wim Taymans + + * gst/gstbufferlist.c: + bufferlist: fix a comment + +2009-05-12 13:10:55 +0200 Jonas Holmberg + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + * win32/common/libgstreamer.def: + bufferlist: hook up the pad functions + Reuse buffer code for bufferlists. Not sure if this measurably impacts performance + for the simple buffer case, if it does after doing some benchmarks, we can + decouple it later. + Fixes #572285 + +2009-05-12 12:08:56 +0200 Jonas Holmberg + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstinfo.c: + * tests/check/Makefile.am: + * tests/check/gst/.gitignore: + * tests/check/gst/gstbufferlist.c: + * win32/common/libgstreamer.def: + bufferlist: add docs/build/debug/unittest + See #572285 + +2009-05-12 11:51:37 +0200 Jonas Holmberg + + * gst/gstbufferlist.c: + * gst/gstbufferlist.h: + bufferlist: add bufferlist code + Buffer lists are a means to manage disjoint buffers as one buffer. It's also + possible to put many of those buffers into a list. + The idea is that when support is added to various elements, we will be able to + more efficiently slice and dice buffers, reduce the amount of memcpy and also + reduce data passing overhead. + The implementation is kept simple on purpose, reusing all of the memory + management features we have for miniobjects and buffers. + Access to the bufferlist object is done with an iterator, which allows for + efficient iteration and modification of the list. + See #572285 + +2009-05-11 07:49:34 +0200 Edward Hervey + + * gst/gstbuffer.c: + gstbuffer: copy new buffer flags when copying metadata. + +2009-04-27 10:13:01 +0200 Wim Taymans + + * libs/gst/base/gstadapter.c: + * tests/check/libs/adapter.c: + adapter: optimize taking the headbuffer + When a are requested to take a buffer from the adapter that is exactly the + headbuffer, don't make a subbuffer of it but return that head buffer. + Add a unit-test for this new optimisation. + +2009-05-05 17:41:24 +0200 Arnout Vandecappelle + + * plugins/elements/gsttypefindelement.c: + typefind: don't leak the force-caps property + Fixes #581321 + +2009-04-28 19:20:31 +0200 Wim Taymans + + * gst/gstelement.c: + element: fix posting of async-start messages + When an element lost its state but was busy doing a state change, still post the + async-start message with the base_time reset flag or else we might end up with + an old base_time. + this can happen when a sink is goin async to paused and then a flushing seek is + performed. This would cause the base_time to remain unmodified because the + async-start message was not sent. + +2009-05-10 17:28:36 +0200 Sebastian Dröge + + * win32/common/libgstreamer.def: + Add new functions to the win32 exports + +2009-05-10 11:17:27 +0200 Marc-Andre Lureau + + * autogen.sh: + Run libtoolize before aclocal + This unbreaks the build in some cases. Fixes bug #582021 + +2009-05-07 16:37:37 +0200 José Alburquerque + + * docs/gst/gstreamer-sections.txt: + * gst/gstplugin.c: + * gst/gstplugin.h: + API: Add gst_plugin_register_static_full() + This is mainly useful for bindings that need to provide + some additional user data to the registration function. + Fixes bug #545787. + +2009-05-07 16:01:57 +0200 Sebastian Dröge + + * plugins/elements/gstfilesrc.c: + filesrc: Improve debugging a bit on invalid URIs + +2009-05-07 10:36:50 +0200 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + docs: Add new functions to the docs + +2009-05-07 09:31:01 +0200 Sebastian Dröge + + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + tags: API: Add functions to add single tags to GstTagList or GstTagSetter + The new functions are gst_tag_setter_add_tag_value() + and gst_tag_list_add_value()). This fixes bug #581198. + +2009-05-07 09:28:15 +0200 Sebastian Dröge + + * gst/gsturi.c: + GstURIHandler: Use get_type_full() vmethod if specified instead of get_type() + This fixes bug #581281 and makes it easier for bindings to + implement GstURIHandlers. get_protocols_full() was already used + like this. + +2009-05-12 01:48:36 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update .po files for new strings from container-format tag + +2009-05-12 01:30:13 +0100 Tim-Philipp Müller + + * docs/random/release: + docs: small update to release docs + +2009-05-12 01:13:02 +0100 Tim-Philipp Müller + + * common: + * configure.ac: + configure: rename CVS -> git in a couple of places + +2009-05-12 00:47:46 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump the GLib requirement to GLib >= 2.16 + as per the New Regime (see wiki). + +2009-05-12 00:09:58 +0100 Tim-Philipp Müller + + * configure.ac: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst_private.h: + * gst/gstregistryxml.c: + xmlregistry: remove the old xml registry + No point in keeping it around really. Fixes #577926. + +2009-05-07 16:08:43 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + tags: add a tag for the container format + API: add GST_TAG_CONTAINER_FORMAT + +2009-05-08 16:28:03 +0100 Tim-Philipp Müller + + * gst/gstbin.c: + bin: fix debug message + Make the debug message show what's actually happening (the message + replaced here is not necessarily of the same type as the one that + replaces it). + +2009-05-12 00:34:44 +0200 Wim Taymans + + * gst/gsttask.c: + GstTask: fix compilation + +2009-04-24 19:32:33 +0200 Wim Taymans + + * tests/examples/streams/rtpool-test.c: + tests: set the latency-time to something low + +2009-04-24 13:55:13 +0200 Wim Taymans + + * tests/examples/streams/rtpool-test.c: + * tests/examples/streams/testrtpool.c: + tests: improve the example + +2009-04-24 12:35:08 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + * tests/examples/streams/.gitignore: + * tests/examples/streams/testrtpool.c: + * win32/common/libgstreamer.def: + TaskPool: remove _set_func() + Remove the static function set on the TaskPool before _prepare() is called and + allow for assigning a function to a Task when we _push(). + Update the examples + +2009-04-23 19:42:47 +0200 Wim Taymans + + * tests/examples/streams/Makefile.am: + * tests/examples/streams/rtpool-test.c: + * tests/examples/streams/testrtpool.c: + * tests/examples/streams/testrtpool.h: + tests: add example of custom taskpools + Add an example to demonstrate the use of a custom taskpool and how to configure + it on the task. Currently the taskpool does not do much yet but it'll create + some custom threads later on. + +2009-04-23 19:41:36 +0200 Wim Taymans + + * gst/gsttaskpool.h: + taskpool: fix a comment + +2009-04-23 19:41:01 +0200 Wim Taymans + + * tests/examples/streams/stream-status.c: + tests: cleanup some code + +2009-04-23 17:48:08 +0200 Wim Taymans + + * gst/gstpad.c: + * tests/check/gst/gstbin.c: + Pad: post STREAM_STATUS_TYPE_CREATE + Post a stream-status message indicating that a new task was created so that the + application has a chance to change the properties of the task. + Fix unit test to take into account the new ref of the message. + +2009-04-23 17:24:58 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: add new task methods + +2009-04-23 17:19:11 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttask.h: + GstTask: add methods for configuring the pool + Add getter and setter for configuring the GstTaskPool to use for a GstTask. + +2009-04-23 17:05:21 +0200 Wim Taymans + + * gst/gsttask.c: + Task: remember pool + Remember the pool we currently have our task running so that we can use it to + join the task later on. + Fix a leak of the taskpool. + +2009-04-23 16:53:34 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: update .defs file with taskpool methods + +2009-04-23 16:53:14 +0200 Wim Taymans + + * gst/gsttask.c: + task: fix deadlock due to typo + +2009-05-12 00:25:11 +0200 Wim Taymans + + * gst/gsttask.c: + * gst/gsttask.h: + GstTask: use GstTaskPool for managing threads + Use the new GstTaskPool to handle streaming threads. + +2009-04-23 16:00:56 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + taskpool: fix docs, make push/join generic + Fix some more docs. + Make _push() return a generic id (this can be something else than a GThread in + some cases) and make _join() use that generic id. + +2009-04-23 15:44:13 +0200 Wim Taymans + + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gsttaskpool.c: + * gst/gsttaskpool.h: + taskpool: add new object to manage threads + Add a new object GstTaskPool to manage the streaming threads. + This will allow us to create and use custom configured threads. + +2009-04-22 12:04:36 +0200 Wim Taymans + + * tests/examples/streams/stream-status.c: + examples: set bus handler before state change + We need to set the bus handler before starting the pipeline or we might just + miss the message we are looking for. + +2009-04-22 10:16:26 +0200 Wim Taymans + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/streams/.gitignore: + * tests/examples/streams/Makefile.am: + * tests/examples/streams/stream-status.c: + tests: add example app for stream-status + Add an example application that adjusts the thread priority of a task using the + stream-status messages. + +2009-04-21 19:15:48 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttask.h: + * win32/common/libgstreamer.def: + Task: add method to set the priority + Add a method to configure a priority for the threads used by GstTask. + +2009-04-21 16:30:34 +0200 Wim Taymans + + * tests/check/gst/gstmessage.c: + tests: add a unit-test for the stream-status + Add a unit test for the STREAM_STATUS messages. + +2009-05-12 00:05:12 +0200 Wim Taymans + + * gst/gstpad.c: + * gst/gsttask.c: + * gst/gsttask.h: + GstTask: improve documentation + Improve the documentation for the callbacks. + +2009-04-21 15:25:12 +0200 Wim Taymans + + * tests/check/gst/gstbin.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/simple-launch-lines.c: + tests: fix unit-tests for new stream-status + Fix the unit-tests so that they don't fail on the new stream-status messages + that are emited now. + +2009-04-21 14:46:29 +0200 Wim Taymans + + * gst/gstpad.c: + GstPad: install thread callbacks of the task + Install thread status callbacks on the task object of a pad and post + STREAM_STATUS messages. + +2009-04-22 10:14:46 +0200 Wim Taymans + + * gst/gstmessage.c: + message: clarify some docs + +2009-04-21 14:42:05 +0200 Wim Taymans + + * gst/gsttask.c: + Task: call leave_thread before signaling + Call the leave_thread callback before we signal the thread performing the _join + so that we can be sure that the listener still has valid info in the callback. + +2009-04-21 13:42:01 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * win32/common/libgstreamer.def: + GstMessage: Add STREAM_STATUS message methods + Add methods to handle the stream_status message types. + +2009-04-21 13:05:17 +0200 Wim Taymans + + * gst/gstquark.c: + * gst/gstquark.h: + quark: add "object" quark + Add the object quark that will be used for the STREAM_STATUS messages. + +2009-05-11 23:44:42 +0200 Wim Taymans + + * gst/gsttask.h: + Task: remove create/join methods + Prepare for using the GstTaskPool object. We don't need the create and join + callbacks anymore, they will be handled by the pool. + +2009-04-20 17:07:50 +0200 Wim Taymans + + * gst/gsttask.c: + GstTask: add private data, fix parent_class + Use the parent class that the glib macro gave us + Actually add the private data to the task. + +2009-04-20 17:19:21 +0200 Wim Taymans + + * gst/gsttask.c: + GstTask: hook up enter/leave/notify callbacks + Hoop up the notify/enter/leave callbacks. + +2009-05-11 23:23:20 +0200 Wim Taymans + + * win32/common/libgstreamer.def: + defs: add new symbol to defs file + +2009-05-11 23:19:53 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttask.h: + GstTask: allow setting callbacks + Allow setting thread callbacks that will allow us to control the threads used by + the task. + +2009-04-23 19:40:11 +0200 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + basesrc: don't ignore pad_start return value + +2009-04-21 13:34:18 +0200 Wim Taymans + + * docs/design/draft-stream-status.txt: + design: more STREAM_STATUS updates + Pass the thread object in a GValue, which would allow the application to figure + out the type of the object instead of us having to explicitly code it in a + message field. + +2009-04-21 09:45:08 +0200 Wim Taymans + + * docs/design/draft-stream-status.txt: + design: update stream-status document some more + +2009-04-20 15:55:09 +0200 Wim Taymans + + * docs/design/draft-stream-status.txt: + design: add first version of stream-status + Add the first version of the STREAM_STATUS message design docs. + This message will be used to give applications more control over the + streaming threads. + +2009-04-21 17:53:07 +0200 Wim Taymans + + * gst/gsttask.c: + GstTask: add some more docs + +2009-04-21 17:14:34 +0200 Wim Taymans + + * gst/gstpad.c: + GstPad: use new task function + Use the new task_set_state function and actually return its result to + the caller. + +2009-05-11 22:59:35 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gsttask.c: + * gst/gsttask.h: + * win32/common/libgstreamer.def: + GstTask: unify task state functions + Add new gst_task_set_state() to change the state of the task instead of + duplicating the code in each function. + API: GstTask::gst_task_set_state() + +2009-04-21 13:37:22 +0200 Wim Taymans + + * gst/gstmessage.h: + Message: small indentation change. + +2009-05-02 14:43:11 +0200 Wim Taymans + + * gst/gstelementfactory.c: + * gst/gstobject.c: + * gst/gstpluginfeature.c: + * gst/gstregistry.c: + * gst/gstregistrybinary.c: + Avoid unneeded type checks + +2009-05-02 14:39:48 +0200 Wim Taymans + + * gst/gstregistry.c: + registry: avoid calling _get_name() too much + Avoid calling gst_plugin_get_name() too many times but instead cache + the value. + +2009-05-02 14:36:50 +0200 Wim Taymans + + * gst/gstpadtemplate.c: + * gst/gstregistry.c: + * gst/gstsystemclock.c: + Use new _ref_sink when we can + +2009-05-02 14:33:01 +0200 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + * gst/gstobject.h: + * win32/common/libgstreamer.def: + gstobject: add gst_object_ref_sink + Add the gst_object_ref_sink() method to match the glib one. + API: GstObject::gst_object_ref_sink() + +2009-05-02 13:06:10 +0200 Wim Taymans + + * gst/gstobject.c: + gstobject: avoid type checks + +2009-05-02 13:02:10 +0200 Wim Taymans + + * gst/gstbuffer.c: + gstbuffer: avoid typechecks in finalize + Avoid useless typechecking in the finalize of buffers and subbuffers. + +2009-05-02 12:59:54 +0200 Wim Taymans + + * plugins/elements/gstfakesink.c: + fakesink: avoid typecheck + +2009-04-20 14:01:01 +0200 Wim Taymans + + * tools/gst-launch.c: + -launch: connect to deep-notify with right name + Connect to the right signal name with - instead of _. + +2009-04-24 22:06:19 +0100 Jan Schmidt + + * configure.ac: + * gst/gstinfo.c: + info: Support new printf extensions in glibc 2.10 + The printf extension mechanism changed in glibc 2.10, and the older + register_printf_function is deprecated. Detect and use the new + mechanism where available. + +2009-04-20 12:25:57 +0100 Jan Schmidt + + * docs/random/release: + docs: Fix a typo in the release script + +2009-05-11 21:11:49 +0100 Jan Schmidt + + * configure.ac: + Back to development -> 0.10.23.1 + +=== release 0.10.23 === + +2009-05-10 22:41:04 +0100 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/common/gstversion.h: + Release 0.10.23 + +2009-05-10 22:38:45 +0100 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + +2009-05-06 16:10:11 +0100 Jan Schmidt + + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.22.4 pre-release + +2009-04-24 19:36:22 +0200 Wim Taymans + + * gst/gstbin.c: + GstBin: set PENDING_STATE correctly + Set the pending state correctly when we are going to perform an async + state_continue on the bin. + Fixes #580121 + +2009-04-21 20:50:55 +0100 Jan Schmidt + + * configure.ac: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + * win32/common/config.h: + * win32/common/gstversion.h: + 0.10.22.3 pre-release + +2009-04-21 22:12:04 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From b3941ea to 6ab11d1 + +2009-04-17 15:46:52 +0100 Tim-Philipp Müller + + * configure.ac: + win32: define __MSVCRT_VERSION__ when compiling with MingW, for __stat64 + Need to define this when using MingW, so that the includes provide + __stat64 and friends. We need at least Windows XP SP2 for this. + Fixes #568632. + +2009-04-16 22:26:00 +0300 Stefan Kost + + * gst/gstinfo.c: + * gst/gstinfo.h: + gstdebug: compete stubs. Fixes #579177. + Avoid defines when including gstinfo.h ourself and complete stubs. Sync stub + returns with the defines. + +2009-04-17 11:44:11 +0100 Yaakov Selkowitz + + * configure.ac: + configure.ac: fork() during registry scanning is unsafe on Cygwin + Fixes #555978. + +2009-04-17 11:39:59 +0100 Yaakov Selkowitz + + * gst/gst.c: + gst_init: relocatability is unnecessary on Cygwin + See #555978. + +2009-04-17 10:11:21 +0100 Brian Cameron + + * gst/gstinfo.h: + gstinfo: don't assume G_HAVE_ISO_VARARGS implies ISO C99 + Makes headers C++ clean, esp. with the Sun compilers. + Fixes #567692. + +2009-04-17 09:17:40 +0100 Tim-Philipp Müller + + * gst/gstplugin.c: + GstPlugin: fix compilation if both HAVE_WIN32 and HAVE_SIGACTION are defined + Move _gst_plugin_fault_handler_is_setup into the ifdef block where it's + used. Fixes #578201. + +2009-04-16 12:01:50 +0200 Wim Taymans + + * tools/gst-launch.c: + -launch: disable CLOCK_LOST message handling + Disable the handling of the CLOCK_LOST messages until we fixed and released the + elements (rtspsrc) that break when we quickly PAUSE/PLAY the pipeline. + Fixes #579127 + +2009-04-15 22:24:45 +0100 Jan Schmidt + + * configure.ac: + release: Bump version to 0.10.22.2 for pre-release + +2009-04-16 00:08:20 +0100 Jan Schmidt + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + win32: Update win32 build files + +2009-04-15 23:27:31 +0100 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: Update translations from TP + +2009-04-15 22:17:10 +0100 Jan Schmidt + + * ChangeLog: + ChangeLog: regenerate changelog with the gen-changelog script + +2009-04-15 23:26:13 +0100 Jan Schmidt + + * gst/gstutils.c: + docs: remove errant gtk-doc comment marker triggering a warning + +2009-04-16 00:02:07 +0100 Jan Schmidt + + * docs/gst/gstreamer-sections.txt: + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + * plugins/elements/gstfilesrc.c: + paramspecs: revert gst_param_spec_is_mutable() for release + Revert the gst_param_spec_is_mutable API for this release so we can + discuss it a bit further first. + +2009-04-15 23:33:20 +0300 Stefan Kost + + * libs/gst/base/gstbasetransform.c: + logging: fix unused variable warning when disabling debug logs. + The var was NULL anyway, bacause of the ifdefs there, the message makes no + sense including it. + +2009-04-15 23:12:11 +0300 Stefan Kost + + * configure.ac: + * gst/gstinfo.c: + * gst/gstinfo.h: + gstdebug: show enabled/disabled in configure and fix build for disabled + When its disabled, we poison some symbols to force a build error if they are + used. Dunno how useful this acually is, but we need to disable the poisoning + when we include this ourself. Also don't define some of the dummies, as they + are getting replaced with defines and that creates code that does not compile. + +2009-04-15 19:58:34 +0200 Sebastian Dröge + + * gst/Makefile.am: + Use g_once_init_*() instead of GOnce for the enum types + +2009-04-15 13:05:16 +0200 Sebastian Dröge + + * gst/gstpadtemplate.c: + staticpadtemplate: Update docs of gst_static_pad_template_get_caps () + gst_static_pad_template_get_caps () actually returns a reference to the + caps and it's cleaner to unref them after usage. The core will, however, + always hold a reference to the caps so this didn't result in a memory + leak. + +2009-04-14 22:32:21 +0300 Stefan Kost + + * gst/gstclock.h: + * gst/gstparamspecs.c: + docs: use real tags as they look nice in new gtk-doc + +2009-04-14 12:20:37 -0700 David Schleef + + * gst/gstparamspecs.c: + Fix locking in gst_param_spec_is_mutable + +2009-04-14 22:07:38 +0300 Stefan Kost + + * libs/gst/controller/gstcontroller.c: + * tests/check/libs/controller.c: + controller: factor out duplicated code and add a description for it. + Also fix typo in the tests while reviewing them. + +2009-04-14 19:12:52 +0200 Wim Taymans + + * gst/gstsystemclock.h: + docs: add simple doc blurb + +2009-04-14 19:11:44 +0200 Wim Taymans + + * gst/gstparamspecs.c: + paramspecs: add note about racyness + Add a note about potential racyness in _is_mutable(). + +2009-04-14 10:32:07 +0200 LRN + + * gst/gstinfo.c: + info: use mutex to do console colors on windows + Use a static mutex to keep the console colors and context together when + debugging with colors on Windows. + Fixes #517231. + +2009-04-13 14:27:49 +0100 Tim-Philipp Müller + + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + docs: add Since: tags to gtk-doc chunks for new param spec API + And, for our release manager, the in-commit-message keywords + for the previous commit: + API: GST_PARAM_MUTABLE_READY + API: GST_PARAM_MUTABLE_PAUSED + API: GST_PARAM_MUTABLE_PLAYING + API: gst_param_spec_is_mutable + +2009-02-20 11:09:19 -0800 David Schleef + + * docs/gst/gstreamer-sections.txt: + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + * plugins/elements/gstfilesrc.c: + Add param spec flags for when a property can be changed + Adds GST_PARAM_MUTABLE* flags to indicate in which states a + property can be changed and take effect. Fixes #571559 + +2009-04-10 14:15:36 +0200 Wim Taymans + + * tools/gst-launch.c: + -launch: handle clock-lost messages + When we receive a clock-lost message, we need to select a new clock in the + pipeline by setting the pipeline to PAUSED and back to PLAYING. + +2009-04-09 18:27:21 +0200 Olivier Crete + + * plugins/elements/gsttee.c: + tee: add property to control the alloc pad + Add a property to control the pad used for proxying the buffer_alloc function on + the sinkpad. + Fixes #577891. + +2009-04-09 11:51:43 +0200 Wim Taymans + + * gst/gstbin.c: + bin: always mark pending_async_done + When we get an ASYNC_DONE message when a state change was busy, set the + pending_async_done flag so that after the state change completes, the bin can + check if all async elements are finished. Don't only do this for the bin itself + but for all elements. + This fixes some bins in bins that simulate async state changes by posting ASYNC + messages (such as sdpparse in uridecodebin/playbin2). + +2009-04-09 11:42:48 +0200 Wim Taymans + + * gst/gstinfo.c: + info: fix compilation, %08x needs an unsigned int + %08x needs an unsigned int, so give it that. + +2009-04-06 01:27:26 +0100 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + * gst/gstinfo.h: + * tests/check/gst/gstinfo.c: + * win32/common/libgstreamer.def: + API: add FIXME and DUMPMEM log levels and convenience macros + Two new log levels to dump FIXMEs into the log and to log data + in form of a hex dump (#578114). + API: GST_CAT_FIXME_OBJECT + API: GST_CAT_MEMDUMP_OBJECT + API: GST_CAT_FIXME + API: GST_CAT_MEMDUMP + API: GST_FIXME_OBJECT + API: GST_MEMDUMP_OBJECT + API: GST_FIXME + API: GST_MEMDUMP + +2009-04-08 18:13:42 +0300 Stefan Kost + + * gst/gstbin.c: + * gst/gstclock.c: + docs: xref more + +2009-04-08 17:49:18 +0300 Stefan Kost + + * gst/gstutils.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstpad.c: + tests: remove the hacks to workaround the pad-leak + +2009-04-08 15:24:58 +0300 Stefan Kost + + * gst/gstpadtemplate.c: + padtemplate: enable code to fix the leak, now that the deps have been released + Good and ffmpeg are actually multiple releases beyond, so that this is now safe + to do. + +2009-04-04 21:18:23 +0300 Felipe Contreras + + * common: + Automatic update of common submodule + From d0ea89e to b3941ea + +2009-04-04 14:53:21 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From f8b3d91 to d0ea89e + +2009-04-04 14:42:04 +0200 Edward Hervey + + * tools/gst-inspect.c: + gst-inspect: remove dead assignment + first_flag will be either: + * rewritten without being read if we loop again (line 284) + * not read again if we don't loop + +2009-04-04 14:39:51 +0200 Edward Hervey + + basesink: Remove dead assignments. + sstart/sstop/rstart/rstop are all either: + * assigned values later on before being used in 'do_times:' (EOS and buffers) + * not used (non-EOS events) + +2009-04-04 14:38:52 +0200 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + basesrc: remove dead assignment. + The variable will not be read before it's assigned a value line 942/945 + +2009-04-04 14:37:13 +0200 Edward Hervey + + * gst/gsttaglist.c: + gsttaglist: Remove unused variable. + We don't need to allocate a variable if it's the return of a function call + and we only check it once. + +2009-04-04 14:35:34 +0200 Edward Hervey + + * gst/gststructure.c: + gststructure: Only use methods used in g_* checks if glib checks are disabled + +2009-04-04 10:59:39 +0200 Sebastian Dröge + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstdataqueue.c: + * libs/gst/controller/gstcontroller.c: + gst: Use g_once_init* or G_DEFINE_TYPE + +2009-04-04 10:20:36 +0200 Sebastian Dröge + + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstchildproxy.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstevent.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstinterface.c: + * gst/gstmessage.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstpipeline.c: + * gst/gstpreset.c: + * gst/gstquery.c: + * gst/gstsystemclock.c: + * gst/gsttagsetter.c: + * gst/gsttask.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gstxml.c: + gst: Use G_DEFINE_TYPE and friends or at least g_once_init_* in the _get_type() functions + +2009-04-04 10:18:42 +0200 Sebastian Dröge + + * gst/gstbus.c: + * gst/gstclock.c: + gst: Use G_DEFINE_TYPE and don't call g_thread_init() from class_init + class_init is too late for calling g_thread_init() as g_thread_init() + needs to be called before any GObject function. + +2009-04-03 13:46:18 +0200 Mark Nauwelaerts + + * gst/gstsegment.c: + Use g_slice_copy instead of g_slice_dup. + A (buggy) glib g_slice_dup macro may cause compiler warnings on e.g. x86_64. + +2009-04-03 12:21:55 +0200 Edward Hervey + + * libs/gst/controller/gstcontroller.c: + controller: remove dead assignment. + The value of prop is being overwritten just after without being read. + +2009-04-03 12:20:36 +0200 Edward Hervey + + * gst/gststructure.c: + gststructure: Remove dead assignment. + 'type' is never used until line 1847 where it's overwritten. + +2009-04-03 12:19:40 +0200 Edward Hervey + + * libs/gst/base/gstadapter.c: + adapter: remove dead assignment. + The value set to to_copy at that line is never used, and is overwritten + further down before being read. + +2009-04-03 12:17:33 +0200 Edward Hervey + + * gst/gstbin.c: + gstbin: Remove unused variable. + The return value of gst_element_change_state isn't used after that call. + +2009-04-03 12:15:38 +0200 Edward Hervey + + * gst/gstpipeline.c: + pipeline: remove redundant assignment. + If that block is entered, then start_time becomes GST_CLOCK_TIME_NONE. + Since start_time is invalid, the code will enter the block at line 434 and + new_base_time will be set there. + +2009-04-03 12:13:38 +0200 Edward Hervey + + * gst/gstregistrybinary.c: + gstregistrybinary: remove variable only used for a check. + that variable isn't used anywhere else within that block. + +2009-04-03 12:13:00 +0200 Edward Hervey + + * libs/gst/base/gstbasesink.c: + basesink : Remove unused variable. + sync is never used anywhere in that code. + +2009-04-03 12:12:08 +0200 Edward Hervey + + * libs/gst/base/gstbasetransform.c: + basetransform: move unused variable in the #if 0 block. + That variable is only used by the code which has been if 0'd + +2009-04-03 11:56:48 +0200 Edward Hervey + + * gst/gsturi.c: + * gst/gstvalue.c: + Remove unused increments as detect by LLVM's CLang static analyzer. + +2009-04-03 11:52:49 +0200 Edward Hervey + + * gst/gstbus.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstindexfactory.c: + * gst/gstinterface.c: + * gst/gstobject.c: + * gst/gstsystemclock.c: + * gst/gsttask.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstcollectpads.c: + * plugins/elements/gstidentity.c: + Remove unused variables detected by LLVM's Clang static analyzer. + +2009-04-03 11:19:42 +0100 Tim-Philipp Müller + + * gst/gstcaps.c: + docs: improve API reference for gst_caps_get_structure() + +2009-04-02 13:32:58 +0200 Thomas Vander Stichele + + * gst/gstbin.h: + docs: explain ref ownership for handle_message implementations + +2009-04-02 10:43:16 +0200 Sebastian Dröge + + * libs/gst/check/gstcheck.h: + gstcheck: Call gst_check_init() before creating the suite + This allows using the GStreamer or GObject API in the suite + creation function. + +2009-03-31 18:14:08 -0300 Thiago Santos + + * tools/gst-launch.c: + gst-launch: Fixes error when DISABLE_FAULT_HANDLER is defined + When defined, this macro prevented the declaration of 'waiting_eos', causing an error. + +2009-03-26 17:25:08 +0100 Edward Hervey + + * plugins/elements/gstcapsfilter.c: + capsfilter. Always calls _suggest, even with NULL caps. Fixes #574805 + +2009-03-30 15:45:02 +0200 Sebastian Dröge + + * tests/check/elements/queue.c: + tests: Don't define global buffers variable, it's already defined by libgstcheck + +2009-03-30 10:33:51 +0200 Peter Kjellerstedt + + * docs/gst/building.xml: + docs: Some grammar and typo corrections. + +2009-03-29 13:41:22 +0200 Thomas Vander Stichele + + * docs/gst/building.xml: + Fix typo. + +2009-03-27 17:30:23 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + binaryregistry: init variable, that is referenced in error case below the fail: label + +2009-03-27 16:15:55 +0100 Wim Taymans + + * gst/gstsystemclock.c: + clock: wakeup the async thread a bit more + Also wake up the async thread when it is doing an async wait for an entry. + +2009-03-27 16:15:10 +0100 Wim Taymans + + * gst/gstelement.c: + element: Fix a little debug message + +2009-03-26 13:07:56 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + binaryregistry: check for not reading beyond the data area. Fixes #576842 + Check all reads against the end of the data region. Roll back registration of + partial reads. + +2009-03-25 11:03:22 +0200 Stefan Kost + + * docs/gst/Makefile.am: + * docs/gst/building.xml: + * docs/gst/gstreamer-docs.sgml: + docs: add a page about building gstreamer and apps + +2009-03-26 13:08:01 -0300 Thiago Santos + + * tools/gst-launch.c: + Adds flag for eos on shutdown in gst-launch. Fixes #575814. + +2009-03-26 22:05:31 +0100 Wim Taymans + + * gst/gstclock.c: + * gst/gstsystemclock.c: + clock: make UNSCHEDULED checks threadsafe + Move the checks for using an unscheduled entry from the unsafe GstClock to the + SystemClock object so that we can perform the correct locking. + fix a leak and potential deadlock then the async thread fails to start. + Sprinkle some G_LIKELY around because we can. + +2009-03-26 21:40:20 +0100 Wim Taymans + + * gst/gstsystemclock.c: + clock: remove pending async wakeup sooner + Remove a pending async wakeup before we check if the next entry is UNSCHEDULED + because we might leave the control socket busy. + +2009-03-26 19:33:41 +0100 Peter Kjellerstedt + + * gst/gstpoll.c: + gstpoll: Corrected a documentation typo. + +2009-03-26 19:13:55 +0100 Wim Taymans + + * gst/gstsystemclock.c: + clock: add some more comments. + +2009-03-26 18:46:35 +0100 Wim Taymans + + * gst/gstsystemclock.c: + clock: rework the wakeup of entries. + Keep a counter for the amount of outstanding wakeups that we produce and only + perform a write/read to the control socket when 1 or 0 respectively. + don't poll when waiting for the entries to be unblocked and clear their wakeup + counts, just act on the signal when the wakeup count is 0. + unscheduled entries will clear their wakeup count themselves. + Keep track of when we wakeup the async thread because the list of entries has + changed. + don't try to see if the list changed because we can't really know when one entry + is added multiple times. + Only wake up the async thread when we add an async entry to the head of the list + and the old entry was BUSY. + +2009-03-25 17:31:16 +0000 Jan Schmidt + + * gst/gstpoll.c: + gstpoll: Fix up documentation strings. + Note the changed behaviour of gst_poll_wait for timer GstPoll's, and + fix a couple of spelling errors. + +2009-03-26 15:55:02 +0100 Wim Taymans + + * gst/gstsystemclock.c: + * tests/check/gst/gstsystemclock.c: + clock: fix 2 wakeup races. + when an entry being waited on in the async thread is unscheduled, clear the + wakeup queue so we can continue waiting on other entries. + When an entry being waited on in the async thread is unlocked because an earlier + entry was added to the list, set the entry to OK again. This makes sure that + only the entries being waited on have the BUSY flag set and wake up the timer + poll when they are unscheduled. + +2009-03-26 14:44:04 +0000 Tim-Philipp Müller + + * gst/gstregistry.c: + registry: ignore .git directory when recursively scanning plugin paths for plugins + Saves some cycles/pandas for those of us who run uninstalled setups. + +2009-03-26 14:16:55 +0000 Tim-Philipp Müller + + * gst/gstregistrybinary.c: + * gst/gstregistryxml.c: + registry: do fsync() before close() and rename() + This helps prevent filesystem/data inconsistencies in certain + circumstances on certain filesystems (like ext4, xfs, ubifs). + Also see bug #562976. + +2009-03-26 01:09:03 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * tests/check/gst/gsttag.c: + * win32/common/libgstreamer.def: + API: add gst_tag_list_get_buffer{_index} + Convenience API, mostly for image tags, so people don't have to + figure out the whole GValue/GstValue thing just for this. + +2009-03-25 23:03:38 +0000 Jan Schmidt + + * tests/check/gst/gstsystemclock.c: + systemclock: Clean up the tests a bit. + Add some cleanups to the system clock tests, to free all the memory and + unschedule/unref all clock IDs we allocate. + Use a mutex in one test to avoid potential threading problems on multicore + machines. + +2009-03-25 21:37:38 +0000 Jan Schmidt + + * tests/check/gst/gstsystemclock.c: + systemclock: Add a test for sync/async clockid interactions + This test randomly hangs if there are problems with the reliability of + unscheduling sync and async clockID's on the system clock. + +2009-03-26 11:17:01 +0100 Sebastian Dröge + + * gst/gstsegment.c: + segment: Use g_slice_dup() now + +2009-03-26 11:08:27 +0100 Sebastian Dröge + + * gst/glib-compat.h: + * gst/gstutils.h: + Remove some compatibility stuff for GLib < 2.14 + +2009-03-25 00:50:07 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + API: add GST_TAG_SUBTITLE_CODEC + Yes, 'codec' isn't exactly the best word, but let's be consistent with AUDIO_CODEC + and VIDEO_CODEC (which may be 'raw' formats as well after all). Prerequisite for + bug #576552. + +2009-03-24 21:39:21 +0000 Tim-Philipp Müller + + * tools/gst-launch.1.in: + docs: gst-launch man page fix + The command line option is --gst-debug-disable, not --gst-disable-debug. + Fixes #576556. Spotted by Bogdan Harjoc. + +2009-03-24 19:33:56 +0100 Wim Taymans + + * gst/gstutils.c: + gstutils: improve property set and convert code + Use string deserialisation instead of custom parsing code to allow for all + supported ways of specifying property values. + fixes #576582. + +2009-03-23 15:18:21 +0200 Stefan Kost + + * gst/gstdebugutils.c: + * gst/gstinfo.c: + build: define stubs when disabling gst-debug subsystem. Fixes #575922 + Running configure with e.g. --disable-dst-debug was compiling out the debug + system (ABI break). Now stubs are added and only if one does e.g. + make CFLAGS="-DGST_REMOVE_DISABLED" the symbols are ommitted. + +2009-03-23 12:34:34 +0000 Tim-Philipp Müller + + * libs/gst/base/gstbasesink.c: + basesink: fix once-per-second 'emergency rendering' for case where all buffers but the very first are late + Due to a typo basesink didn't do any emergency rendering of late buffers + if the only buffer ever rendered was the first one with timestamp 0. This + means that in cases where the decoder is very very slow, we'd never see + any buffers but the very first one rendered. Fixes #576381. + +2009-03-21 02:34:04 +0000 Jan Schmidt + + * docs/random/release: + docs: tweak the release procedure script + +2009-03-20 14:12:55 +0100 LRN + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + win32: fix seeking in files >4GB + Use 64-bit functions on windows to implement seeking in files bigger + than 4GB. + Fixes #575988 + +2009-03-20 11:26:30 +0200 Stefan Kost + + * libs/gst/controller/gstinterpolation.c: + controller: Fix generation of control-change arrays. + When generating arrays of control changes timestamp variable was used instead + the local ts variable that we increment when stepping through the array. + Pointed out by Martin Pokorny. + +2009-03-20 00:42:51 +0000 Tim-Philipp Müller + + * gst/gstinfo.c: + debugging: make GST_PTR_FORMAT work for queries as well + +2009-03-20 00:39:41 +0000 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.h: + API: add GST_QUERY_CAST + because we can, and for consistency. + +2009-03-19 21:27:48 +0000 Tim-Philipp Müller + + * libs/gst/check/gstcheck.h: + gstcheck: fix for check versions > 0.9.6 + A new argument allowed_exit_value was added in SVN recently (#574213). + +2009-03-19 17:19:49 +0100 Wim Taymans + + * gst/gstpad.c: + gstpad: fix gst_pad_can_link + We were converting the GstPadLinkReturn to a gboolean, which is not what we want + to do. + +2009-03-19 10:44:13 +0000 Tim-Philipp Müller + + * docs/faq/gst-uninstalled: + gst-uninstalled: add gst-rtsp-server bits and break up overly long lines + Add some of the bits needed for an uninstalled gst-rtsp-server (so gdb works + on the examples etc.). Python bits are still missing, and we might need an + -uninstalled.pc file as well in the future. Break up very long lines to make + them easier to read and maintain. Also remove gst-plugins paths from the + old days. + +2009-03-19 11:46:11 +0100 Wim Taymans + + * docs/random/wtay/rwlocks: + docs: interesting idea for fast rw locks + -- + +2009-03-19 11:11:43 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + defs: add new symbol to windows .def file + Add the new windows cmd.exe coloring method to the .def file. + +2009-03-18 16:38:51 +0200 Stefan Kost + + * gst/gstelement.c: + docs: more info about when state changes can be async and when not. + +2009-03-18 19:07:00 +0100 Damien Lespiau + + * gst/gstinfo.h: + info: more indentation fixes + Fixes #517231. + +2009-03-18 19:06:23 +0100 Wim Taymans + + * gst/gstinfo.h: + info: indentation fix + +2009-03-18 18:57:16 +0100 Wim Taymans + + * gst/gstinfo.c: + info: simply some more + +2009-03-18 18:45:41 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstinfo.c: + info: refactor debug colors for win32 and other + Refactor the debug line code to use as much code as possible for the win32 and + other color codings. + Update docs with new symbol. + +2009-03-18 17:30:12 +0100 Wim Taymans + + * gst/gst.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + windows: initial commit for terminal colors + +2009-03-18 17:01:16 +0100 Zeeshan Ali (Khattak) + + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstutils.c: + * gst/gstutils.h: + gstpad: fix gst_pad_can_link() + Move the gst_pad_can_link() implementation from gstutils to gstpad and use + gst_pad_link_prepare() to make it work correctly and also check the caps. + Make the broken implementation in gstutils static. + Small cleanups in the _get_fixed_caps() function. + Fixes #575682. + +2009-03-17 20:41:44 +0000 David Adam + + * gst/gst.c: + config.h needs to be included first, either directly or via gst_private.h + Fixes build with -Werror caused by '_FILE_OFFSET_BITS redefined' warning on + OpenSolaris where _FILE_OFFSET_BITS may be defined both in our config.h + and via stdio.h (#575695). + +2009-03-17 19:02:26 +0000 Tim-Philipp Müller + + * docs/faq/developing.xml: + faq: remove outdated bits from indenting section + +2009-03-17 12:05:33 +0200 Stefan Kost + + * gst/gstbin.c: + bin: forward segment-start like segment-done if parent is also a bin, fixes #575598. + Bin collects segment-start messages and segent-done messages. it posts a + segment-done message to its parent, once it has received a segment-done for + each segment-start. Imho it should also send a segment-start if it receives the + first segment start and if parent is !=NULL. This is needed for bins in bins, + so that also higher order bins can group segment-starts and segment-dones. + Right now higher order bins will post a segment-done for each segment-done + received. + +2009-03-16 20:12:45 +0100 Edward Hervey + + * docs/faq/git.xml: + faq: fix typo in git command + +2009-03-15 23:40:36 +0200 Stefan Kost + + * gst/gstsystemclock.c: + systemclock: these warnings are serious, give more detail in the message + +2009-03-15 23:37:29 +0200 Stefan Kost + + * libs/gst/base/gstcollectpads.c: + collectpads: add debug logging to make it easier to trace it + +2009-03-13 10:56:54 +0100 Wim Taymans + + * gst/gstutils.h: + Fix indentation of .h files + -- + +2009-03-12 12:20:25 +0200 Stefan Kost + + * gst/gsttaglist.c: + taglists: apply fix for replace all also to gst_tag_list_add_valist_values. Fixes #574241 + +2009-03-12 10:48:21 +0100 Wim Taymans + + * gst/gstbuffer.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstpad.h: + * gst/gstquery.h: + docs: Improve some docs + Rename some function variables and add some Return: to make the docs more happy. + +2009-03-12 00:41:24 +0200 Stefan Kost + + * gst/gstiterator.c: + docs: fix linking to constant and functions + +2009-03-11 15:20:36 +0200 Stefan Kost + + * gst/gstdebugutils.c: + dump2dot: ellipsize caps fields, better placement of unnegotiated caps + Long caps fields like enums are ellipsised. If caps are not negotiated, use + head- and taillabel to place them closer to the pads. Use smarter way to indent. + +2009-03-11 10:27:16 +0200 Laszlo Pandy + + * gst/gstdebugutils.c: + dump2dot: make caps in DOT debug graphs more readable. Fixes 574484 + Use a monospace font for edge labels and indent. + +2009-03-11 14:11:30 +0100 Sebastian Dröge + + * gst/gstpadtemplate.c: + padtemplate: Allow %u as conversion modifier additional to %d and %s + +2009-03-11 11:23:05 +0100 Edward Hervey + + * libs/gst/base/gstbasesrc.c: + gstbasesrc: unsigned long is "%lu", not "%ul". Fixes build on macosx + +2009-03-10 21:08:34 +0200 Stefan Kost + + * gst/gstghostpad.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstcapsfilter.c: + logging: some additional logging for tracing caps negotiation. + Demote one log that can come quite often. Remove one fixme that is done. Apply + gst-indent changes. + +2009-03-10 21:03:44 +0200 Stefan Kost + + * gst/gstobject.c: + comment: add a fixme-0.11 + +2009-03-10 21:01:21 +0200 Stefan Kost + + * docs/design/part-block.txt: + formatting: tabs to spaces + +2009-03-09 23:11:24 +0000 Jan Schmidt + + * common: + Automatic update of common submodule + From 7032163 to f8b3d91 + +2009-03-09 20:07:12 +0000 Tim-Philipp Müller + + * gstreamer.spec.in: + gstreamer.spec: fix stray @GLIB2_REQ@ that didn't get expanded properly + +2009-03-09 16:09:38 +0100 Wim Taymans + + * docs/manual/basics-bus.xml: + docs: reword stuff about custom mainloops + Fixes #574229. + +2009-03-09 16:01:20 +0200 Stefan Kost + + * gst/gstdebugutils.c: + dump2dot: don't use GST_TIME_FORMAT when building filenames. fixes #574623 + +2009-03-09 11:39:34 +0100 Wim Taymans + + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/gst/gstpad.c: + pad: call new callbacks set in the block callback + Keep track of when a new callback is installed in the callback and call the new + callback in that case. + Add unit test for checking pad blocking. + Fixes #573823. + +2009-03-08 17:22:43 +0000 Tim-Philipp Müller + + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + win32: update enumtypes and config.h + +2009-03-08 17:15:33 +0000 Tim-Philipp Müller + + * gst/gsttaglist.c: + docs: improve docs for gst_tag_list_get_date*() + Mention that the date value needs to be freed and how to free it. + +2009-03-08 12:02:15 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From ffa738d to 7032163 + +2009-03-08 11:17:50 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 3f13e4e to ffa738d + +2009-03-08 00:27:26 +0200 Stefan Kost + + * gst/gstdebugutils.c: + dump2dot: improve caps logging + Factor out code to describe caps. Improve formating (no \n in caps fields). + Check peer caps too and show both if they differ. + +2009-03-07 11:43:31 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 3c7456b to 3f13e4e + +2009-03-07 10:43:32 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 57c83f2 to 3c7456b + +2009-03-06 22:10:10 +0200 Stefan Kost + + * libs/gst/base/gstcollectpads.c: + collectpads: revert accidential commit from the queue (me should start using branches) + +2009-03-06 21:59:20 +0200 Stefan Kost + + * gst/gstcaps.c: + * gst/gststructure.c: + apidocs: markup example as highlightable example and copy same for structure + structures can be printed like we can do for caps. Mark the example so that + gtk-doc can pretty print and xref it. + +2009-03-04 21:21:56 +0200 Stefan Kost + + * libs/gst/base/gstcollectpads.c: + collectpads: reliably go to eos. Fixes #574160 + Update collectpads status when removing pads. + +2009-03-06 12:08:42 +0100 Alessandro Decina + + * plugins/elements/gstidentity.c: + identity: ignore the return value of gst_pad_event_default when sending out the newsegment event in single-segment mode. + This makes identity single-segment=true ! oggmux work again after a change in + oggmux (commit b0e3d449 in -base). + +2009-03-05 17:42:22 +0100 Andy Wingo + + basesink: propagate UPSTREAM events in pull mode too + * libs/gst/base/gstbasesink.c (gst_base_sink_send_event): Propagate + upstream events in pull mode too. + +2009-03-05 11:29:48 +0100 Antoine Tremblay + + * gst/gstpad.c: + GstPad: relax failure to deactivate unlinked pads + When de/activating a pad in pull mode the pad needs to de/activate the + peer pad it is connected to, failure to be able to do this in activation mode + is an error. + However if there is no peerpad, we can still deactivate the pad correctly and + assume the application will deactivate the unlinked peer pad eventually. + Fixes #574163. + +2009-03-05 11:02:59 +0100 LRN + + * gst/gstpoll.c: + GstPoll: set the return value on windows + Make sure that the return value of the functions _read/_write_control() + return the actual result instead of always FALSE on windows. + Fixes #574211. + +2009-03-04 10:46:15 +0000 Tim-Philipp Müller + + * docs/pwg/advanced-negotiation.xml: + * docs/pwg/building-boiler.xml: + pwg: update for CVS-to-git migration + Fixes #573946. + +2009-03-04 09:20:43 +0100 Edward Hervey + + * libs/gst/base/gstadapter.c: + GstAdapter: Discard empty buffers in _push(). Fixes #574024 + +2009-03-03 20:01:43 +0000 Tim-Philipp Müller + + * .gitignore: + Update .gitignore + +2009-03-03 19:58:53 +0000 Tim-Philipp Müller + + * docs/faq/gst-uninstalled: + gst-uninstalled: add bits for uninstalled checkouts of gst-openmax and totem + +2009-03-02 16:17:45 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gstutils.c: + * gst/gstutils.h: + * tests/check/gst/gstutils.c: + * win32/common/libgstreamer.def: + API: Add gst_util_array_binary_search() for binary searchs on a sorted array + This will be mostly useful in all elements that have some kind of internal + seek/index table. Currently almost all of them (or even all of them) + are using a linear search although the used array is already sorted, + wasting some CPU time without good reason. + Fixes bug #573623. + +2009-02-28 11:15:29 -0800 David Schleef + + * configure.ac: + * gst/gstutils.h: + Bump glib requirement to 2.14 + Also remove code conditional on < 2.14. + +2009-02-28 13:34:08 -0500 Olivier Crête + + * win32/MANIFEST: + Remove win32/common/config.h.in from MANIFEST, it no longer exists + +2009-02-27 13:35:35 +0100 Edward Hervey + + * plugins/elements/gstcapsfilter.c: + capsfilter: Properly reset the capsfilter when setting caps ANY. + +2009-02-27 12:34:29 +0100 Wim Taymans + + * docs/design/draft-framestep.txt: + design: update the framestep draft + Update the docs a little. + Add property to allow incremental stepping so that we can reduce excessive + queueing. + +2009-02-26 15:40:26 +0200 Stefan Kost + + * libs/gst/base/gstbasesink.c: + basesink: move left over handling of the error case to the activate_failed label. + If was left as dead code. + +2009-02-25 19:59:57 +0000 Jan Schmidt + + * common: + * configure.ac: + build: Update shave init statement for changes in common. Bump common. + +2009-02-25 10:51:57 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + binary registry: Don't attempt to parse empty caps + +2009-02-25 14:19:08 +0100 Sebastian Dröge + + * gst/gstregistrybinary.c: + registry: Set typefind factory caps to NULL instead of empty caps if they originally were NULL + +2009-02-25 11:31:38 +0000 Jan Schmidt + + * common: + Automatic update of common submodule + From 9cf8c9b to a6ce5c6 + +2009-02-24 15:10:15 +0100 Sebastian Dröge + + * gst/gstregistrybinary.c: + registrybinary: Check if typefind factory caps are NULL before copying them + +2009-02-24 11:40:14 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + Remove undeclared symbols from docs + Remove some undeclared symbols from the docs. + +2009-02-23 13:01:11 -0800 David Schleef + + * 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. + +2009-02-23 10:52:14 -0800 David Flynn + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-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 + +2009-02-23 17:36:23 +0100 Wim Taymans + + * libs/gst/base/gstbasesrc.c: + Error out more specifically on empty caps + When we get empty caps from the getcaps function in the default negotiate + function, post a more descriptive error. + +2009-02-23 15:24:00 +0100 Andy Wingo + + fix uri handler iteration in gst-inspect + * tools/gst-inspect.c (print_all_uri_handlers): Whoops, fix iteration. + I'm stupid. + +2009-02-23 12:33:13 +0100 LRN + + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimeprovider.c: + Fix signed when compiling with MSys/MinGW + fix signed issues when compiling with MSys/MinGW. + Fixes #572591. + +2009-02-23 10:53:17 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + Don't forward LATENCY event when not ready + When we are not ready to handle a latency query (we are not yet prerolled) we + also don't try to forward the latency event because that might cause unexpected + errors when upstream is not yet linked. + +2009-02-22 22:09:39 +0100 Edward Hervey + + * tests/check/core: + Remove core file from previous commit + +2009-02-22 20:01:05 +0100 Alessandro Decina + + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + * tests/check/core: + * tests/check/gst/gstpad.c: + * win32/common/libgstreamer.def: + GstPad: Add gst_pad_set_blocked_async_full + This allows connecting a GDestroyNotify for when the callback is removed/replaced. + Partially fixes #514717 + +2009-02-22 19:05:20 +0100 Sebastian Dröge + + * gst/gstutils.h: + Include floating point write/read functions in the docs by working around a gtk-doc bug + +2009-02-22 18:53:10 +0100 Ali Sabil + + * plugins/elements/gstqueue.c: + Use the correct unref function + +2009-02-22 18:51:08 +0100 Ali Sabil + + * gst/gstbuffer.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstquery.h: + Convert unref/copy functions of GstMiniObject subclasses to static inline functions + unref and copy functions are sometimes used as function + pointers for example in the case of g_hash_table_new_full + as a GDestroyNotify function. + Currently GstBuffer, GstEvent, GstMessage and GstQuery + define their respective unref and copy functions as + macros, making use of gst_mini_object_unref/copy. + This approach works very well for most cases, except + for some automatically generated bindings (currently Vala), + where the memory management semantics are defined + declaratively. + The possible solutions would be to either convert all + the macros into static inline function, or change the + signature of gst_mini_object_unref to take a void* + instead of a GstMiniObject*. + Fixes bug #572480. + +2009-02-22 15:22:16 +0000 Jan Schmidt + + * configure.ac: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Use shave (http://git.lespiau.name/cgit/shave/) to simplify build output + +2009-02-22 15:44:35 +0000 Jan Schmidt + + * common: + Automatic update of common submodule + From 5d7c9cc to 9cf8c9b + +2009-02-21 11:13:30 -0800 David Schleef + + * common: + Automatic update of common submodule + From 80c627d to 5d7c9cc + +2009-02-19 18:05:07 +0100 Edward Hervey + + * gst/gstbuffer.h: + GstBufferFlags: Add "Since: 0.10.23" for the newly added flags + +2009-02-19 16:04:43 +0100 Edward Hervey + + * gst/gstbuffer.h: + GstBufferFlags: Add 3 new media-specific buffer flags. + Partially fixes #163577 + +2009-02-19 12:57:17 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: print normal output to stdout, and only errors and warnings to stderr in gst-launch + Let's not print everything to stderr. Suppress some more 'normal' messages when --quiet was passed. + +2009-02-19 12:45:53 +0000 Tim-Philipp Müller + + * tools/gst-launch.c: + tools: use g_print*() instead of *printf() in gst-launch + We should use GLib's g_print*() functions for printing stuff in gst-launch, not printf and friends, since we're printing + translated strings, which we get in UTF-8 encoding, and GLib's print functions expect UTF-8 encoded strings whereas printf + et al. expect strings in the locale encoding, which may or may not be UTF-8. + Also add a PRINT convenience macro so we don't have to litter the code with if (!quiet) statements. + +2009-02-19 11:18:07 +0000 Tim-Philipp Müller + + * docs/pwg/advanced-types.xml: + * docs/pwg/intro-basics.xml: + * docs/random/mimetypes: + docs: fix constants for G_LITTLE_ENDIAN and G_BIG_ENDIAN + We got the constants for G_LITTLE_ENDIAN and G_BIG_ENDIAN the wrong way around in some docs (fixes: #572392). Also mention + G_BYTE_ORDER in the audio types section. + +2009-02-19 10:25:34 +0100 Wim Taymans + + * win32/common/libgstreamer.def: + Add new symbols to def files + Add the new request_message symbols to the windows def file. + +2009-02-18 15:31:55 +0100 Wim Taymans + + * docs/design/part-messages.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * tests/check/gst/gstmessage.c: + * tools/gst-launch.c: + Add message to request a state change + Add a GST_MESSAGE_REQUEST_STATE that can be posted by element when they would + like to have the application change the state of the pipeline. the primary use + case is to pause the pipeline when an audio mixer is mixing a higher priority + stream but it can also be used for other purposes. + Add some docs and a unit test. + Implement the REQUEST_STATE message in gst-launch. + API: gst_message_new_request_state() + API: gst_message_parse_request_state() + API: GST_MESSAGE_REQUEST_STATE + +2009-02-16 12:58:34 +0100 Wim Taymans + + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + Clear target when the target pad disappears + When the target pad disappears (because it was explicitly unlinked or the + element was removed/unreffed) make sure we receive a notify with the unlink + function on the proxy pad and clear the target. We use a simple flag to not do + this and cause deadlocks when the target was changed explicitly using the + ghostpad functions. + Update the unit test because we now unref the target sooner (and correctly). + +2009-02-15 16:37:17 +0200 Stefan Kost + + * gst/gstelementfactory.c: + * gst/gstpluginfeature.c: + docs: format and indent examples. + +2009-02-09 22:49:05 +0200 Stefan Kost + + * tools/gst-launch.1.in: + * tools/gst-launch.c: + gst-launch: add -q/--quiet option to supress any non error output. + Having no output is nice for scripting. Also update the manpage. + +2009-02-14 13:35:48 +0000 Tim-Philipp Müller + + * docs/faq/developing.xml: + * docs/faq/faq.xml: + * docs/faq/getting.xml: + * docs/faq/git.xml: + * docs/faq/gst-uninstalled: + * docs/faq/start.xml: + * docs/faq/troubleshooting.xml: + * docs/faq/using.xml: + FAQ: update for git and miscellaneous small fixes and additions + Replace all mentions of CVS with git. Add link to gst-uninstalled script in cgit and to SubmittingPatches page in wiki. Fix some typos. Update indenting rules to what we actually use (#571646). + +2009-02-13 16:17:03 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + po: update *.po files for newly-added translatable strings + The only people who should get conflicts now are people who have cloned and built gstreamer between the time those strings + were added and this commit. + +2009-02-12 10:38:05 +0100 Sebastian Dröge + + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + taglist: API: Add HOMEPAGE tag + This tag will list a homepage for the media, + i.e. the artist's or movie's homepage. + This is different to GST_TAG_LOCATION as the latter + lists the original location of the media. + Fixes bug #571227. + +2009-02-09 12:00:43 +0100 Edward Hervey + + * common: + Bump revision to use for common submodule. + +2009-02-08 10:28:16 +0100 Sebastian Dröge + + * gst/gst.c: + * gst/gstversion.h.in: + Replace some mentions of CVS by GIT + +2009-02-06 10:51:28 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + binary registry: Rewrite sanity check to actualy catch something. + The previous commit was bogus, as was the check before. We just point m to the file data, + so neither it nor its members will be NULL. Better check if we have enough data. + +2009-02-05 23:11:07 +0000 Tim-Philipp Müller + + * po/Makevars: + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.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 is likely to 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. + +2009-02-05 15:22:46 +0000 Tim-Philipp Müller + + * win32/common/libgstreamer.def: + win32: add new GstPoll API to libgstreamer.def + +2009-02-05 17:23:44 +0200 Stefan Kost + + * gst/gstclock.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + cleanup: remove unused variables in _class_init() and reindent. + +2009-02-05 17:05:56 +0200 Stefan Kost + + * gst/gstbus.c: + bus: remove unused set/get property functions + +2009-02-05 15:56:19 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + binary registry: comparing arrays against NULL is useless + +2009-02-05 13:59:48 +0200 Stefan Kost + + * plugins/elements/gstqueue.c: + queue: remove unused code + Skip looping thru a dummy implementation. + +2009-02-05 13:57:05 +0200 Stefan Kost + + * tests/check/gst/gstpipeline.c: + tests: GstClockTime is always >= 0 + +2009-02-05 13:42:30 +0200 Stefan Kost + + * libs/gst/controller/gsthelper.c: + controller: remove unused variable + +2009-02-04 17:20:21 +0200 Stefan Kost + + * gst/gstghostpad.c: + cleanup: Either check always for internal being NULL or don't. + IMHO the ghostpad is borked if internal is NULL. So the check can go and it is + used later unchecked anyway. + +2009-02-04 16:26:23 +0200 Stefan Kost + + * gst/gsttaglist.c: + crash: Don't crash on non existent tags. + +2009-02-04 16:17:34 +0200 Stefan Kost + + * gst/gstregistrybinary.c: + leak: Don't leak type name in failure cases. + +2009-02-04 16:07:30 +0200 Stefan Kost + + * libs/gst/check/gstcheck.c: + check: Don't assume gst_pad_get_peer returns non NULL value. + +2009-02-04 15:41:24 +0200 Stefan Kost + + * gst/gstutils.c: + leak: don't return without calling va_end + +2009-02-03 18:04:46 +0100 Jonas Holmberg + + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + Implement the systemclock with gstpoll + Add a property to select the clock type, currently REALTIME and MONOTONIC when + posix timers are available. + Implement the systemclock with GstPoll instead of GCond. This allows us to + schedule timeouts with nanosecond precission on newer kernels and with ppoll + support. It's also resilient to changes to the systemclock because of NTP or + similar. + +2009-02-03 17:49:02 +0100 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + * gst/gstpoll.c: + * gst/gstpoll.h: + GstPoll: add methods to use gstpoll for timeouts + Add a special timer mode in GstPoll that makes it only use the control socket + with a timeout to schedule timeouts. Also add a pair of methods to wakeup the + timeout thread. + API: GstPoll::gst_poll_new_timer() + API: GstPoll::gst_poll_write_control() + API: GstPoll::gst_poll_read_control() + +2009-02-03 15:27:34 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + GstBaseSink: use new variable to schedule preroll + Use a separate variable to keep track if we need to call the preroll method + instead of abusing the commited variable. + +2009-02-03 12:52:49 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + * tests/check/elements/fakesink.c: + GstBaseSink: avoid calling preroll multiple times + Fix a regression introduced by fix for #567725 in commit + 1c7ab4ed4f19b63ba046a6f2fe7d09a6c17357c5. We should only call the preroll + function once namely when we did not yet commit the state change. + Add a unit test to check that we call the preroll function when interrupting the + clock_wait (see #567725). + Add a unit test to check that we only call the preroll function once. + +2009-01-29 13:30:45 +0100 Thijs Vermeir + + * libs/gst/base/gstbasetransform.c: + Force reconfigure of basetransform to recheck alloc request + While reconfiguring a basetransform element we need also to recheck + the alloc request. Because it's possible that due to caps changes + the proxy_alloc state is not correct anymore. + (Re-commit after discusion with Wim on IRC) + +2009-02-02 14:19:57 +0100 Peter Kjellerstedt + + * gst/gstregistrybinary.c: + gstregistrybinary: Make it compile with GST_DISABLE_GST_DEBUG. + +2009-01-31 21:34:28 +0000 Jan Schmidt + + * docs/.gitignore: + * docs/libs/tmpl/.gitignore: + * docs/plugins/tmpl/.gitignore: + repo: Rearrange gitignores in docs subdir + tmpl directories are removed by make clean, which deletes the + .gitignore. Use a .gitignore higher up to ignore the tmpl dirs instead. + +2009-01-31 21:32:36 +0000 Jan Schmidt + + * tests/check/pipelines/stress.c: + check: Fix comment about the timeout for generic stress test. + Setting the timeout to 0 makes it infinite, so fix the comment + above accordingly. + +2009-01-31 21:31:48 +0000 Jan Schmidt + + * tests/check/elements/tee.c: + check: Increase timeout for the tee test + The tee stress test keeps timing out for me on one of the slower + machines, so increase the timeout to 3 mins. + +2009-01-30 14:56:08 +0000 Jan Schmidt + + * win32/common/config.h.in: + Update the win32 config.h.in template from the main config.h.in + +2009-01-30 22:18:17 +0200 Stefan Kost + + * docs/libs/gstreamer-libs-docs.sgml: + * docs/plugins/gstreamer-plugins-docs.sgml: + Add releaseinfo with online url. + +2009-01-30 18:17:03 +0000 Tim-Philipp Müller + + * gst/gstinterface.h: + * gst/gsturi.h: + Remove broken class to interface cast macros from GstUriHandler and GstImplementsInterface headers + Remove class-to-interface-struct cast macros which don't work, + don't make sense, and in some cases wouldn't even compile if + used. Removal should be ok seeing that code which uses any of + these is broken and bound to crash. Fixes #565607. + API: remove GST_IMPLEMENTS_INTERFACE_CLASS + API: remove GST_IS_IMPLEMENTS_INTERFACE_CLASS + API: remove GST_URI_HANDLER_CLASS + +2009-01-30 16:28:14 +0000 Jan Schmidt + + * docs/gst/tmpl/.gitignore: + Remove gitignore in docs/gst/tmpl. + This gitignore file seems to get deleted by the build, and doesn't + seem to be doing anything useful anyway. + +2009-01-30 16:21:55 +0000 Jan Schmidt + + * common: + Bump common + +2009-01-30 14:59:07 +0000 Jan Schmidt - Sun Microsystems - Dublin Ireland + + * gst/gstghostpad.c: + Fix compilation warning with Forte. + +2009-01-30 10:43:55 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + Revert "Check suggested caps for proxy alloc" + This reverts commit 50afd459579191772f42d1a44f3959e530c5c269. + It breaks the interactive test-scale unit test. + +2009-01-30 10:42:50 +0100 Wim Taymans + + * libs/gst/base/gstbasetransform.c: + Revert "Force reconfigure of basetransform to recheck alloc request" + This reverts commit 3a4602d7719de3c3ef7aece68b5f9489d0780162. + It breaks the interactive test-scale unit test. + +2009-01-30 10:29:56 +0100 Sebastian Dröge + + * gst/gstregistrybinary.c: + Allocate everything that is written to the registry with g_malloc0() + Allocate every structure that is directly written to the binary + registry with g_malloc0(). Otherwise some parts of it will be + uninitialized (struct padding because of alignment, etc) and + valgrind will complain about it. + +2009-01-30 08:30:28 +0100 Edward Hervey + + * autogen.sh: + * common: + Use a symbolic link for the pre-commit client-side hook + +2009-01-29 15:49:24 +0000 Jan Schmidt + + * gst/gstregistrybinary.c: + Make sure to take a copy of the strings we're going to free later. + +2009-01-26 17:15:15 +0200 Stefan Kost + + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + Add logging in failure case. Add more details to a todo comment. + +2009-01-26 17:14:07 +0200 Stefan Kost + + * tests/benchmarks/Makefile.am: + * tests/benchmarks/init.c: + Add a trivial source for tracking gst_init time accross versions. + +2009-01-26 17:13:09 +0200 Stefan Kost + + * libs/gst/controller/gstcontroller.c: + Add todo comments. + +2009-01-29 13:39:29 +0100 Thijs Vermeir + + * libs/gst/base/gstbasetransform.c: + Check suggested caps for proxy alloc + Because we are trying to resolve a suggestion here we don't need + to check on caps for proxy_alloc but we need to check on the suggested + caps instead. + +2009-01-29 13:30:45 +0100 Thijs Vermeir + + * libs/gst/base/gstbasetransform.c: + Force reconfigure of basetransform to recheck alloc request + While reconfiguring a basetransform element we need also to recheck + the alloc request. Because it's possible that due to caps changes + the proxy_alloc state is not correct anymore. + +2009-01-27 23:14:49 +0200 Stefan Kost + + * gst/gstclock.c: + Improve the docs for gst_clock_id_wait_async(). + Its mentioned in the section docs, but lets repeat at the function docs that the callback can be invoked from any thread. + +2009-01-27 17:53:01 +0000 Tim-Philipp Müller + + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + docs: don't use ERROR_CFLAGS when building $docmodule-scan.c + We don't want to use -Wall -Werror and friends when building the gtk-doc-generated + $docmodule-scan.c, since we can't easily fix stuff if a certain gtk-doc/compiler + combination breaks the build. Fixes build on ubuntu intrepid. + +2009-01-27 17:52:14 +0000 Tim-Philipp Müller + + * .gitignore: + Make git ignore backup files. + +2009-01-26 21:29:02 +0200 Stefan Kost + + * libs/gst/controller/gsthelper.c: + Don't check timestamp here, its done in the called function anyway. + +2009-01-26 12:52:12 +0100 Wim Taymans + + * gst/gstpoll.c: + Avoid unneeded reads from the control socket + Add a new variable that keeps track of the status of the control socket. This + allows us to avoid doing a read() on the control socket when we did not write + anything to it. + Fixes #568438. + +2009-01-25 22:17:31 +0200 Stefan Kost + + * gst/gstutils.c: + Add more debug logging for failure cases. + +2009-01-25 22:11:32 +0200 Stefan Kost + + * gst/gstplugin.h: + Document that GST_PLUGIN_DEFINE macros use PACKAGE define. Fixes #559722. + PACKAGE is defined by autofoo. If people use something different, they might want to define it themself. + +2009-01-25 17:58:52 +0100 Thijs Vermeir + + * libs/gst/base/gstbasetransform.c: + Fix typo + +2009-01-24 21:50:08 +0100 Thijs Vermeir + + * libs/gst/check/gstcheck.c: + Only free list of buffers once + +2009-01-24 14:37:14 +0100 Thijs Vermeir + + * docs/README: + Fix typo + +2009-01-23 23:08:03 +0000 Jan Schmidt + + * po/.gitignore: + Ignore another file + +2009-01-23 21:44:11 +0000 Jan Schmidt + + * win32/common/libgstbase.def: + add gst_type_find_helper_for_extension to the win32 defs file + +2009-01-23 16:09:35 +0000 Jan Schmidt + + * win32/common/config.h: + Update win32 config.h for 0.10.22.1 dev cycle... + +2009-01-23 16:08:09 +0000 Jan Schmidt + + * .gitignore: + * docs/gst/.gitignore: + * docs/libs/.gitignore: + * docs/libs/tmpl/.gitignore: + * libs/gst/base/.gitignore: + * libs/gst/check/.gitignore: + * libs/gst/controller/.gitignore: + * libs/gst/dataprotocol/.gitignore: + * libs/gst/net/.gitignore: + * plugins/indexers/.gitignore: + * tests/check/libs/.gitignore: + Update a bunch of gitignores to clean up my git status output + +2009-01-23 09:54:53 +0100 Brian Cameron + + * configure.ac: + * gst/Makefile.am: + Fix linking failures on Solaris. Fixes bug #568481. + Link libgstreamer with $(LIBM) as it uses math functions. + Add a configure check for socket and nsl library and add + them to LIBS if they're found. This is needed on Solaris + for socket() and gethostbyname(). + +2009-01-22 18:02:19 +0200 Stefan Kost + + * common: + Update common snapshot. + +2009-01-22 13:58:57 +0100 Sebastian Dröge + + * plugins/elements/gstfilesrc.c: + Improve debug output by logging the offsets. Fixes bug #568678. + In create() also log the offsets and not only the + buffer size. + +2009-01-22 13:51:02 +0100 Sebastian Dröge + + * common: + Fix pre-commit hook + +2009-01-22 12:52:50 +0100 Wim Taymans + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gstreamer + +2009-01-22 11:54:41 +0100 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + Add Doc for new typefind method. + +2009-01-22 10:45:59 +0000 Jan Schmidt + + * configure.ac: + Back to development -> 0.10.22.1 + +2009-01-22 10:16:03 +0100 Wim Taymans + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gstreamer + +2009-01-22 05:35:02 +0100 Edward Hervey + + * autogen.sh: + * common: + Install and use pre-commit indentation hook from common + +2009-01-21 12:50:29 +0100 Wim Taymans + + * plugins/elements/gsttypefindelement.c: + If no type was found using the typefind functions, try doing an upstream URI query to guess the type from the extension. See #566661. + +2009-01-21 12:48:18 +0100 Wim Taymans + + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + Add new typefing helper function to guess the caps based on the file extension. See #566661. API: gst_type_find_helper_for_extension() + +2009-01-21 12:45:45 +0100 Wim Taymans + + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + Allow adding a typefinder without a typefind function so that it can be used to map the caps to the extension. See #566661. + +2009-01-21 12:43:55 +0100 Wim Taymans + + * libs/gst/base/gstbasesink.c: + Update the last_buffer exactly with the buffer that caused the preroll and also call the preroll method with that preroll buffer. Fixes #567725. + +2009-01-21 12:21:49 +0100 Wim Taymans + + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + do not call the unlink function on the target pad when the ghostpad is unlinked. Add some unit tests for this behaviour. Fixes #566936. + +2009-01-21 04:29:25 +0100 Edward Hervey + + * autogen.sh: + autogen.sh : Use git submodule + +=== release 0.10.22 === + +2009-01-19 22:58:59 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * po/LINGUAS: + * win32/common/config.h: + Release 0.10.22 + Original commit message from CVS: + Release 0.10.22 + +2009-01-19 21:20:40 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2009-01-17 21:04:41 +0000 Tim-Philipp Müller + + gst/gstbus.c: Fix order of members in GstBusSource structure - the first member must be the parent structure ie. GSou... + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_set_main_context), (gst_bus_create_watch): + Fix order of members in GstBusSource structure - the first member + must be the parent structure ie. GSource. Should make bus sources + attached to non-default main contexts work in all cases now (ie. + primarily in cases where the callback has a non-NULL user data + argument). Fixes #562170. + * tests/check/gst/gstbus.c: (test_custom_main_context): + Add unit test for the above, based on code by + Justin Karneges . + +2009-01-15 10:04:37 +0000 Jonas Holmberg + + gst/gstpad.h: A small documentation fix. + Original commit message from CVS: + Patch by: Jonas Holmberg + * gst/gstpad.h: + A small documentation fix. + +2009-01-11 09:46:52 +0000 Sebastian Dröge + + gst/gstutils.h: Initialize g_once_init* data with 0. Fixes bug #567225. + Original commit message from CVS: + * gst/gstutils.h: + Initialize g_once_init* data with 0. Fixes bug #567225. + +2009-01-09 23:37:19 +0000 Jan Schmidt + + configure.ac: pre-release 0.10.21.3 + Original commit message from CVS: + * configure.ac: + pre-release 0.10.21.3 + +2009-01-09 15:43:17 +0000 Wim Taymans + + libs/gst/base/gstbasesink.*: Fix documentation for the wait_clock method, rename basesink -> sink for consistency. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_wait_clock): + * libs/gst/base/gstbasesink.h: + Fix documentation for the wait_clock method, rename basesink -> sink + for consistency. + +2009-01-08 13:41:19 +0000 Stefan Kost + + gst/gst.c: Create a registry if there is none also when the option for gst-disable-registry-update has been selected.... + Original commit message from CVS: + * gst/gst.c: + Create a registry if there is none also when the option for + gst-disable-registry-update has been selected. Fixes #567002 + +2009-01-06 18:10:22 +0000 Tim-Philipp Müller + + gst/gst.c: Ref new enum type in gst_init. + Original commit message from CVS: + * gst/gst.c: (init_post): + Ref new enum type in gst_init. + * win32/common/libgstreamer.def: + Add recently-added API. + +2009-01-06 17:58:59 +0000 Tim-Philipp Müller + + Add API for making a GStreamer plugin 'dependent' on external files, directories or environment variables, so that GS... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt:: + * gst/gst_private.h: (GstPluginDep), (_GstPluginPrivate): + * gst/gstplugin.c: (gst_plugin_init), (gst_plugin_finalize), + (gst_plugin_class_init), (gst_plugin_list_free), + (gst_plugin_ext_dep_get_env_vars_hash), + (_priv_plugin_deps_env_vars_changed), + (gst_plugin_ext_dep_extract_env_vars_paths), + (gst_plugin_ext_dep_get_hash_from_stat_entry), + (gst_plugin_ext_dep_direntry_matches), + (gst_plugin_ext_dep_scan_dir_and_match_names), + (gst_plugin_ext_dep_scan_path_with_filenames), + (gst_plugin_ext_dep_get_stat_hash), + (_priv_plugin_deps_files_changed), (gst_plugin_ext_dep_free), + (gst_plugin_ext_dep_strv_equal), (gst_plugin_ext_dep_equals), + (gst_plugin_add_dependency), (gst_plugin_add_dependency_simple): + * gst/gstplugin.h: (GstPluginPrivate), (GstPluginFlags), + (GST_PLUGIN_DEPENDENCY_FLAG_NONE), + (GST_PLUGIN_DEPENDENCY_FLAG_RECURSE), + (GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY), + (GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX), + (GstPluginDependencyFlags), (GstPluginFilter): + * gst/gstregistry.c: (gst_registry_scan_path_level): + * gst/gstregistrybinary.c: (gst_registry_binary_save_feature), + (gst_registry_binary_save_plugin_dep), + (gst_registry_binary_save_plugin), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin_dep_strv), + (gst_registry_binary_load_plugin_dep), + (gst_registry_binary_load_plugin): + * gst/gstregistrybinary.h: (GST_MAGIC_BINARY_VERSION_STR), + (GstBinaryPluginElement), (_GstBinaryDep), (GstBinaryDep): + * gst/gstregistryxml.c: (gst_registry_xml_save_plugin): + Add API for making a GStreamer plugin 'dependent' on external files, + directories or environment variables, so that GStreamer knows when + it needs to re-load GStreamer plugins that wrap other plugin systems. + Fixes bug #350477. + API: add gst_plugin_add_dependency() + API: add gst_plugin_add_dependency_simple() + +2009-01-06 13:00:11 +0000 Tim-Philipp Müller + + docs/faq/gst-uninstalled: Add libgstapp-0.10 from -base to search path and remove the old lib from -bad from the sear... + Original commit message from CVS: + * docs/faq/gst-uninstalled: + Add libgstapp-0.10 from -base to search path and remove the old + lib from -bad from the search path. + +2009-01-05 15:42:53 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Release the object lock before calling the query convert pad functions to avoid deadlocks. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position_last), + (gst_base_sink_get_position_paused), (gst_base_sink_get_position): + Release the object lock before calling the query convert pad functions + to avoid deadlocks. + +2009-01-05 15:41:00 +0000 Wim Taymans + + gst/gstbus.c: The lock order should be maincontext > OBJECT_LOCK so we need to release the object lock when waking up... + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_wakeup_main_context): + The lock order should be maincontext > OBJECT_LOCK so we need to release + the object lock when waking up the mainloop to avoid deadlocks. + +2009-01-05 10:14:28 +0000 Wim Taymans + + gst/gstbin.c: Use an iterator to set the clock and the index so that we can release the object lock appropriately. Fi... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_set_index_func), (gst_bin_set_clock_func), + (gst_bin_change_state_func): + Use an iterator to set the clock and the index so that we can release + the object lock appropriately. Fixes #566393. + +2009-01-03 18:39:38 +0000 Edward Hervey + + libs/gst/base/gstcollectpads.c: Use the name of the pads instead of a pointer, helps in debugging. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_available): + Use the name of the pads instead of a pointer, helps in debugging. + +2009-01-03 18:16:54 +0000 Edward Hervey + + gst/gstindex.c: Add a debugging category for GstIndex, first little step in making indexing top-notch. + Original commit message from CVS: + * gst/gstindex.c: (gst_index_get_type): + Add a debugging category for GstIndex, first little step in making + indexing top-notch. + +2009-01-03 18:10:08 +0000 Edward Hervey + + gst/: Assign debug statements to relevant categories instead of the 'default' category so they don't get lost in debu... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_message_full), + (gst_element_pads_activate): + * gst/gstobject.c: (gst_object_dispatch_properties_changed): + * gst/gstutils.c: (gst_pad_proxy_getcaps), (gst_pad_proxy_setcaps), + (gst_pad_add_data_probe_full), (gst_pad_add_event_probe_full), + (gst_pad_add_buffer_probe_full), (gst_pad_remove_data_probe), + (gst_pad_remove_event_probe), (gst_pad_remove_buffer_probe): + Assign debug statements to relevant categories instead of the 'default' + category so they don't get lost in debugging. + +2009-01-01 21:27:06 +0000 Stefan Kost + + gst/gstdebugutils.c: Add some ideas, how to make the graph smaller. + Original commit message from CVS: + * gst/gstdebugutils.c: + Add some ideas, how to make the graph smaller. + * gst/gstutils.c: + Add a comment from a debug session. + * libs/gst/base/gstbasetransform.c: + Log more context. + * libs/gst/controller/gstinterpolationcontrolsource.c: + Indet. + * plugins/elements/gstcapsfilter.c: + Fix typo in docs. + +2008-12-27 17:41:11 +0000 Tim-Philipp Müller + + gst/gstbus.c: Make GstBusSource work with non-default main contexts (#562170). + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_dispose), (gst_bus_get_property), + (gst_bus_wakeup_main_context), (gst_bus_set_main_context), + (gst_bus_post), (gst_bus_source_prepare), (gst_bus_source_finalize), + (gst_bus_create_watch): + Make GstBusSource work with non-default main contexts (#562170). + * tests/check/gst/gstbus.c: (message_func_eos), (message_func_app), + (test_watch), (test_watch_with_custom_context), (gst_bus_suite): + Add test case for GstBusSource with a non-default main context. + * tests/check/libs/.cvsignore: + Ignore more. + +2008-12-27 16:23:12 +0000 Tim-Philipp Müller + + gst/gstregistrybinary.c: Wrap multi-line macros in G_STMT_{START|END}. + Original commit message from CVS: + * gst/gstregistrybinary.c: (unpack_element), (unpack_const_string), + (unpack_string):: + Wrap multi-line macros in G_STMT_{START|END}. + +2008-12-20 17:33:44 +0000 Sebastian Dröge + + API: Add URI query type. This is useful to query the URI of a sink/source element and can be used by demuxers that ne... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: (gst_query_new_uri), (gst_query_set_uri), + (gst_query_parse_uri): + * gst/gstquery.h: + API: Add URI query type. This is useful to query the URI + of a sink/source element and can be used by demuxers that + need to get data from other files. + This query should go upstream by default. + Fixes bug #562949. + * plugins/elements/gstfdsink.c: (gst_fd_sink_query): + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init), + (gst_fd_src_query): + * plugins/elements/gstfilesink.c: (gst_file_sink_query): + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init), + (gst_file_src_query): + Implement URI query. + +2008-12-19 15:11:06 +0000 Alessandro Decina + + Don't forward gst_pad_set_caps() on a source ghostpad to its target. + Original commit message from CVS: + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + Don't forward gst_pad_set_caps() on a source ghostpad to its target. + That would cause the ghostpad to emit notify::caps two times (fist + from gst_pad_set_caps() and after from on_src_target_notify()). + +2008-12-19 11:24:36 +0000 Wim Taymans + + tests/check/gst/gstghostpad.c: Add some more unit-tests for the ghostpad notify signal, one of which currently fails. + Original commit message from CVS: + * tests/check/gst/gstghostpad.c: (ghost_notify_caps), + (GST_START_TEST): + Add some more unit-tests for the ghostpad notify signal, one of which + currently fails. + +2008-12-19 09:44:49 +0000 Sebastian Dröge + + win32/common/libgstreamer.def: Add gst_tag_setter_reset_tags to the list of exported symbols. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add gst_tag_setter_reset_tags to the list of exported symbols. + +2008-12-17 16:16:45 +0000 Alessandro Decina + + In a source ghostpad, when caps are changed in the target pad, the change needs to be reflected in the ghostpad. + Original commit message from CVS: + * gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + In a source ghostpad, when caps are changed in the target pad, the + change needs to be reflected in the ghostpad. + Fixes #564863. + +2008-12-17 09:37:47 +0000 Sebastian Dröge + + gst/gstutils.c: Add FIXME for 0.11 to set the pad as message source and not the element. Otherwise it's impossible to... + Original commit message from CVS: + * gst/gstutils.c: (gst_element_found_tags_for_pad): + Add FIXME for 0.11 to set the pad as message source and not + the element. Otherwise it's impossible to detect for which + pad the tags were found without adding an event probe + or something similar to the pad. + +2008-12-16 21:33:57 +0000 Wim Taymans + + docs/faq/general.xml: Update the faq. + Original commit message from CVS: + * docs/faq/general.xml: + Update the faq. + +2008-12-16 15:51:52 +0000 Stefan Kost + + Rename api added in previous commit and add since tag to docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + Rename api added in previous commit and add since tag to docs. + API: gst_tag_setter_reset_tags() + +2008-12-16 14:05:40 +0000 Stefan Kost + + Add function to reset tagsetter for element reuse. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + Add function to reset tagsetter for element reuse. + API: gst_tag_setter_flush() + +2008-12-16 09:37:53 +0000 Stefan Kost + + gst/gsttaglist.c: Avoid copy of empty taglist. + Original commit message from CVS: + * gst/gsttaglist.c: + Avoid copy of empty taglist. + +2008-12-16 09:23:21 +0000 Stefan Kost + + More complete unit tests. Fix handling of empty taglists (they were not merged before). + Original commit message from CVS: + * gst/gsttaglist.c: + * tests/check/gst/gsttag.c: + More complete unit tests. Fix handling of empty taglists (they were + not merged before). + +2008-12-16 07:07:36 +0000 Stefan Kost + + gst/: Update GstTagSetter and GstTagMergeMode documentation. Mention that tags can come from events and from applicat... + Original commit message from CVS: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + Update GstTagSetter and GstTagMergeMode documentation. Mention + that tags can come from events and from application. Fix example. + +2008-12-15 15:27:06 +0000 Wim Taymans + + docs/design/part-TODO.txt: Remove the seqnum entry that we implemented in 0.10 already. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Remove the seqnum entry that we implemented in 0.10 already. + Add entry about removing the format return value for queries. + +2008-12-15 12:47:59 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Expose the render-delay as a property so things like appsink can use it to tweak the syn... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_set_property), + (gst_base_sink_get_property): + Expose the render-delay as a property so things like appsink can use it + to tweak the synchronisation. + +2008-12-10 15:19:45 +0000 Peter Kjellerstedt + + libs/gst/check/gstcheck.h: Allow check tests to use + Original commit message from CVS: + * libs/gst/check/gstcheck.h: Allow check tests to use + MAIN_START_THREADS()/MAIN_STOP_THREADS() multiple times. Also allows + CK_FORK=no to be used with multiple check test that use threads. + +2008-12-09 16:23:58 +0000 Sebastian Dröge + + gst/gstutils.c: Fix a caps memory leak introduced by the last change. + Original commit message from CVS: + * gst/gstutils.c: (gst_element_get_compatible_pad): + Fix a caps memory leak introduced by the last change. + +2008-12-09 15:45:36 +0000 Sebastian Dröge + + gst/gstutils.c: Check if the caps of the pads are compatible before returning a pad and claiming it is compatible. Th... + Original commit message from CVS: + * gst/gstutils.c: (gst_element_get_compatible_pad): + Check if the caps of the pads are compatible before returning + a pad and claiming it is compatible. This, among other things, + fixes a bug with gst-launch where an incompatible pad is chosen + and linking fails. Fixes bug #544003. + +2008-12-09 14:46:24 +0000 Sebastian Dröge + + libs/gst/check/gstcheck.c: Revert accidentially commited patch for bug #404631 which tries to print a backtrace if a ... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_init): + Revert accidentially commited patch for bug #404631 which + tries to print a backtrace if a testcase is terminated by + a signal. This code was never activated as the corresponding + configure.ac change wasn't committed. + +2008-12-09 10:58:01 +0000 Sebastian Dröge + + tests/check/libs/controller.c: This test should return TRUE now as syncing an uncontrolled object will succeed now (t... + Original commit message from CVS: + * tests/check/libs/controller.c: (GST_START_TEST): + This test should return TRUE now as syncing an uncontrolled + object will succeed now (there's nothing to sync). + +2008-12-09 09:56:25 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Aggregate return value for gst_controller_sync_values(). More info in logging. A... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + Aggregate return value for gst_controller_sync_values(). More info in + logging. Always set values on first sync-call. + * libs/gst/controller/gstcontrolsource.c: + Microoptimizations. + * libs/gst/controller/gsthelper.c: + Fix return code and comment. + +2008-12-09 09:00:57 +0000 Stefan Kost + + tools/gst-launch.1.in: Fix description of how to specify a type in caps. Fixes #553873. + Original commit message from CVS: + * tools/gst-launch.1.in: + Fix description of how to specify a type in caps. Fixes #553873. + Also ranges and list contain values and not property-assignments. + +2008-12-08 22:28:05 +0000 Wim Taymans + + plugins/elements/gsttee.c: Check for changed pads-list before checking the last returned + Original commit message from CVS: + * plugins/elements/gsttee.c: (gst_tee_handle_buffer): + Check for changed pads-list before checking the last returned + GstFlowReturn because the pad could have been removed and we + need to ignore the value in that case. + +2008-12-08 18:35:44 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.*: Add vmethod that is called before we start the transform and which can be used to c... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_getrange), (gst_base_transform_chain): + * libs/gst/base/gstbasetransform.h: + Add vmethod that is called before we start the transform and which can + be used to configure the transform, such as dynamic properties. + +2008-12-05 20:32:03 +0000 David Schleef + + gst/gst.c: Search for plugins on win32 based on the location of the gstreamer DLL. Fixes #548786 + Original commit message from CVS: + * gst/gst.c: + Search for plugins on win32 based on the location of the + gstreamer DLL. Fixes #548786 + +2008-12-04 20:10:42 +0000 Sebastian Dröge + + 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:45:05 +0000 Sebastian Dröge + + 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-11-29 13:29:14 +0000 Sebastian Dröge + + 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 + + * 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-27 11:12:30 +0000 이문형 + + gst/gstpoll.c: Adds support for FD_CONNECT event (win32). See #562258. + Original commit message from CVS: + Patch by: 이문형 + * gst/gstpoll.c: (gst_poll_fd_ctl_write), (gst_poll_fd_has_error): + Adds support for FD_CONNECT event (win32). See #562258. + +2008-11-24 20:02:55 +0000 Stefan Kost + + libs/gst/base/gstbasesink.c: Turn comment into gtk-doc comment. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + Turn comment into gtk-doc comment. + +2008-11-24 15:27:55 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Revert quick accepcaps attempt, it's not fully equivalent to the old behaviour and ... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_acceptcaps): + Revert quick accepcaps attempt, it's not fully equivalent to the old + behaviour and thus causes regressions. + +2008-11-24 11:56:44 +0000 Edward Hervey + + plugins/elements/gstfilesrc.c: Fix memory leak. + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_uri_set_uri): + Fix memory leak. + +2008-11-24 09:59:07 +0000 Simon Holm Thøgersen + + gst/gstregistry.c: Reduce the number of stat() calls for every file from three times to one time. Fixes bug #560360. + Original commit message from CVS: + Patch by: Simon Holm Thøgersen + * gst/gstregistry.c: (gst_registry_scan_path_level): + Reduce the number of stat() calls for every file from three times + to one time. Fixes bug #560360. + +2008-11-22 15:09:20 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Rename a variable to make the code clearer. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_acceptcaps): + Rename a variable to make the code clearer. + +2008-11-21 20:57:16 +0000 Stefan Kost + + plugins/elements/gstidentity.c: Don't warning on offset==-1. Taken from _check_imperfect_offset(). + Original commit message from CVS: + * plugins/elements/gstidentity.c: + Don't warning on offset==-1. Taken from _check_imperfect_offset(). + +2008-11-21 18:26:14 +0000 Michael Smith + + plugins/elements/gstfilesrc.c: Check for localhost in URI was backwards, fix it. Fixes unit test. + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: + Check for localhost in URI was backwards, fix it. Fixes unit test. + +2008-11-21 17:14:48 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Add beginnings of a more optimized acceptcaps function than the default core one. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_getcaps), (gst_base_transform_find_transform), + (gst_base_transform_acceptcaps), (gst_base_transform_getrange): + Add beginnings of a more optimized acceptcaps function than the default + core one. + +2008-11-21 16:48:48 +0000 Wim Taymans + + gst/gstpad.c: Avoid getting the acceptcaps function too early. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_accept_caps): + Avoid getting the acceptcaps function too early. + +2008-11-21 08:09:00 +0000 Wim Taymans + + tools/gst-launch.c: Make gst-launch handle LATENCY messages and make it recalculate the latency. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Make gst-launch handle LATENCY messages and make it recalculate the + latency. + +2008-11-20 21:05:14 +0000 Michael Smith + + plugins/elements/gstfilesrc.c: Use g_filename_from_uri() for URI parsing in filesrc rather than rolling out own sligh... + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: + Use g_filename_from_uri() for URI parsing in filesrc rather than rolling + out own slightly incorrect version. Fixes use of some paths on + win32. + +2008-11-20 20:44:56 +0000 Michael Smith + + gst/gstregistrybinary.c: In win32 codepath, if we fail to write the registry, create the directory for it and try aga... + Original commit message from CVS: + * gst/gstregistrybinary.c: + In win32 codepath, if we fail to write the registry, create the + directory for it and try again, matching the behaviour in non-win32 + codepaths. + +2008-11-20 14:23:05 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Changing the render delay changes the latency and so we must post a latency message. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_render_delay): + Changing the render delay changes the latency and so we must post a + latency message. + +2008-11-20 10:35:50 +0000 Wim Taymans + + gst/gstquery.*: Add GstQueryType for custom queries instead of having to use the not-so-very-convenient registration ... + Original commit message from CVS: + * gst/gstquery.c: + * gst/gstquery.h: + Add GstQueryType for custom queries instead of having to use the + not-so-very-convenient registration infrastructure to register new + types. + +2008-11-19 12:20:03 +0000 Andrew Feren + + gst/gstobject.c: Unref the GEnumClass after usage again. Fixes bug #561501. + Original commit message from CVS: + Patch by: Andrew Feren + * gst/gstobject.c: (gst_object_default_deep_notify): + Unref the GEnumClass after usage again. Fixes bug #561501. + +2008-11-19 12:06:41 +0000 Wim Taymans + + gst/gstbin.*: Add do-latency signal with the old default fallback implementation. This allows for custom latency calc... + Original commit message from CVS: + * gst/gstbin.c: (_gst_boolean_accumulator), (gst_bin_class_init), + (gst_bin_recalculate_latency), (gst_bin_do_latency_func), + (gst_bin_change_state_func): + * gst/gstbin.h: + Add do-latency signal with the old default fallback implementation. This + allows for custom latency calculations for when the default is not + sufficient. + API: GstBin::do-latency signal. + +2008-11-18 13:36:29 +0000 Wim Taymans + + win32/common/libgstreamer.def: Add new symbols to .def file. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add new symbols to .def file. + +2008-11-18 09:58:33 +0000 Wim Taymans + + Add method to recalculate and redistribute the latency on a bin. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: (gst_bin_recalculate_latency), + (gst_bin_change_state_func): + * gst/gstbin.h: + Add method to recalculate and redistribute the latency on a bin. + API: gst_bin_recalculate_latency(). + +2008-11-18 09:52:41 +0000 Wim Taymans + + gst/gstbuffer.h: Document the free_func. + Original commit message from CVS: + * gst/gstbuffer.h: + Document the free_func. + +2008-11-17 21:43:06 +0000 Sebastian Dröge + + libs/gst/controller/: Use gst_guint64_to_gdouble instead of gst_util_guint64_to_gdouble as it is mapped to a cast on ... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstlfocontrolsource.c: + Use gst_guint64_to_gdouble instead of gst_util_guint64_to_gdouble + as it is mapped to a cast on non-win32 platforms. + +2008-11-17 21:41:35 +0000 Stefan Kost + + libs/gst/controller/: Keep last-value and only call set_property if value has changed. This supresses all the g_objec... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontrollerprivate.h: + Keep last-value and only call set_property if value has changed. This + supresses all the g_object_notifies we would trigger otherwise. It + also allows the user to chage the value while there is no controller + change. + +2008-11-17 21:25:39 +0000 Stefan Kost + + gst/gstvalue.c: Don't crash if either of the string GValues is empty. + Original commit message from CVS: + * gst/gstvalue.c: + Don't crash if either of the string GValues is empty. + +2008-11-17 15:48:14 +0000 Andy Wingo + + tools/gst-inspect.c (print_all_uri_handlers): New function, prints a summary of what URI schemes are supported by wha... + Original commit message from CVS: + 2008-11-17 Andy Wingo + * tools/gst-inspect.c (print_all_uri_handlers): New function, + prints a summary of what URI schemes are supported by what + elements. + (main): Plumb in support for --uri-handlers or -u, and fix the + argc check for -a and -u. + +2008-11-17 04:49:06 +0000 Sebastian Dröge + + gst/gstutils.h: Add G_GNUC_PURE to gst_util_uint64_scale* and the double<->uint64 conversion functions. + Original commit message from CVS: + * gst/gstutils.h: + Add G_GNUC_PURE to gst_util_uint64_scale* and the double<->uint64 + conversion functions. + +2008-11-13 18:09:45 +0000 Wim Taymans + + gst/gstbuffer.c: Avoid costly typechecking for trivially correct pointers. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_finalize): + Avoid costly typechecking for trivially correct pointers. + * gst/gstpoll.c: (gst_poll_wait): + Add some G_LIKELY here and there. + * libs/gst/base/gstadapter.c: (gst_adapter_push): + Add some debug info. + +2008-11-13 18:05:40 +0000 Wim Taymans + + docs/random/wtay/poll-timeout: Small tweaks. + Original commit message from CVS: + * docs/random/wtay/poll-timeout: + Small tweaks. + +2008-11-13 18:03:23 +0000 Wim Taymans + + tests/old/testsuite/: Remove references to deprecated API g_mem_chunk*. + Original commit message from CVS: + * tests/old/testsuite/caps/intersection.c: (main): + * tests/old/testsuite/plugin/loading.c: (main): + Remove references to deprecated API g_mem_chunk*. + Fixes #560442. + +2008-11-12 16:55:00 +0000 Wim Taymans + + tools/gst-inspect.c: Add --plugin option. Fixes #560301. + Original commit message from CVS: + * tools/gst-inspect.c: (main): + Add --plugin option. Fixes #560301. + +2008-11-12 12:45:46 +0000 Wim Taymans + + docs/random/wtay/poll-timeout: Quick braindump for a possible (not totally verified) atomic case. + Original commit message from CVS: + * docs/random/wtay/poll-timeout: + Quick braindump for a possible (not totally verified) atomic case. + +2008-11-12 10:39:25 +0000 Sebastian Dröge + + gst/gstregistrybinary.*: Don't write and check a CRC for the binary registry file. It's guaranteed that the registry ... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write_chunk), + (gst_registry_binary_initialize_magic), + (gst_registry_binary_write_cache), + (gst_registry_binary_check_magic): + * gst/gstregistrybinary.h: + Don't write and check a CRC for the binary registry file. It's + guaranteed that the registry is completely written (it's first written + to a temporary file and then moved) and if the registry was corrupted + by some hardware failure we would have bigger problems. + Bump binary registry version to 0.10.21.1 for this as it's an + incompatible change and to ensure that the registry gets rebuild + after the update. + This saves some milliseconds for reading/writing the registry. + Fixes bug #560399. + +2008-11-11 14:50:24 +0000 Wim Taymans + + docs/random/wtay/poll-timeout: Some pseudo code for how we could implement clock timeouts with GstPoll. + Original commit message from CVS: + * docs/random/wtay/poll-timeout: + Some pseudo code for how we could implement clock timeouts with GstPoll. + +2008-11-10 13:56:51 +0000 Thomas Vander Stichele + + plugins/elements/gstfilesink.c: Update Author string to match others. + Original commit message from CVS: + * plugins/elements/gstfilesink.c: + Update Author string to match others. + +2008-11-06 15:37:16 +0000 Wim Taymans + + gst/gstvalue.c: Reorganize some more, be more conservative with the GST_TYPE_ARRAY not being fixed and inline the tri... + Original commit message from CVS: + * gst/gstvalue.c: (gst_type_is_fixed), (gst_value_is_fixed): + Reorganize some more, be more conservative with the GST_TYPE_ARRAY not + being fixed and inline the trivial check. + +2008-11-06 15:09:34 +0000 Wim Taymans + + gst/gstcaps.c: Callgrind micro optimisations. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_copy), (_gst_caps_free), + (gst_caps_merge_structure), (gst_caps_get_structure), + (gst_caps_copy_nth), (gst_caps_set_simple), + (gst_caps_set_simple_valist), (gst_caps_is_fixed), + (gst_caps_is_equal_fixed), (gst_caps_intersect), + (gst_caps_subtract), (gst_caps_normalize), (gst_caps_do_simplify), + (gst_caps_to_string): + Callgrind micro optimisations. + Avoid array bounds checks and force inline of trivial function. + * gst/gstobject.c: (gst_object_set_name_default): + -1 is equivalent to letting glib to the strlen but then there is more + room for optimisations and it's not our fault. + * gst/gststructure.c: (gst_structure_id_empty_new_with_size): + no need to clear the array, we're cool. + * gst/gstvalue.c: (gst_type_is_fixed), (gst_value_is_fixed): + The most common _is_fixed() check is done on fundamental glib base + types so we check this first instead of doing a huge amount of + useless GST_TYPE_ARRAY calls. + +2008-11-06 12:03:17 +0000 Wim Taymans + + gst/gstevent.h: Add a SKIP seek flag for use with advanced trickmodes. + Original commit message from CVS: + * gst/gstevent.h: + Add a SKIP seek flag for use with advanced trickmodes. + API: GstSeekFlags::GST_SEEK_FLAG_SKIP + +2008-11-05 16:57:35 +0000 Wim Taymans + + gst/gststructure.c: No need to memset, we can clear the value ourselves. + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_id_empty_new_with_size): + No need to memset, we can clear the value ourselves. + * gst/gstvalue.c: (gst_type_is_fixed), + (gst_value_get_compare_func): + Some optimisations from a few callgrind sessions: + When checking if a type is fixed, check for trivial fundamental types + first before checking types for which we need to get the type followed + by the heavy duty type checks, this reduces the amount of + g_type_fundamental() calls a lot. + When getting the compare function, first check for our registered types. + If that fails, do the heavy duty g_type_is_a() checks, reduces the + amount of g_type_is_a() considerably. + +2008-11-05 11:17:24 +0000 Wim Taymans + + docs/design/part-TODO.txt: Mumble something about removing GstXML. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Mumble something about removing GstXML. + +2008-11-04 18:10:04 +0000 Wim Taymans + + gst/gstbin.c: Get the seqnum before we dispose the message. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_handle_message_func): + Get the seqnum before we dispose the message. + +2008-11-04 16:10:04 +0000 Wim Taymans + + docs/design/part-TODO.txt: Refer to the framestepping document. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Refer to the framestepping document. + +2008-11-04 15:56:55 +0000 Wim Taymans + + Copy seqnums from events to messages so that they can all be related back to eachother. + Original commit message from CVS: + * gst/gstbin.c: (bin_handle_async_start), + (gst_bin_handle_message_func), (gst_bin_query): + * libs/gst/base/gstbasesink.c: (gst_base_sink_render_object), + (gst_base_sink_event), (gst_base_sink_change_state): + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_loop), (gst_base_src_change_state): + Copy seqnums from events to messages so that they can all be related + back to eachother. + +2008-11-04 15:52:09 +0000 Wim Taymans + + tools/gst-launch.c: Print the message seqnums. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Print the message seqnums. + +2008-11-04 13:56:37 +0000 Andy Wingo + + gst/gstutils.c (gst_util_seqnum_next): Refactor for clarity. + Original commit message from CVS: + 2008-11-04 Andy Wingo + * gst/gstutils.c (gst_util_seqnum_next): Refactor for clarity. + Also add API: to previous changelog entry. + +2008-11-04 12:22:53 +0000 Andy Wingo + + Add sequence numbers to events and messages. See #559250. + Original commit message from CVS: + 2008-11-04 Andy Wingo + Add sequence numbers to events and messages. See #559250. + * gst/gstutils.c (gst_util_seqnum_next, gst_util_seqnum_compare): + New functions. + * gst/gstevent.h: + * gst/gstevent.c (_gst_event_copy, gst_event_new): Initialize new + events with a new sequence number, and copy it when copying. + (gst_event_get_seqnum, gst_event_set_seqnum): Accessors for an + event's sequence number. + * gst/gstmessage.h: + * gst/gstmessage.c (_gst_message_copy, gst_message_new_custom): + (gst_event_get_seqnum, gst_event_set_seqnum): As with events, so + with messages. + * docs/gst/gstreamer-sections.txt: Add new functions to the docs. + +2008-11-04 11:55:08 +0000 Wim Taymans + + docs/manual/: Some Application Development Manual fixes thanks to + Original commit message from CVS: + * docs/manual/advanced-position.xml: + * docs/manual/basics-bins.xml: + * docs/manual/basics-bus.xml: + * docs/manual/basics-pads.xml: + * docs/manual/intro-gstreamer.xml: + * docs/manual/intro-preface.xml: + Some Application Development Manual fixes thanks to + Andrew Feren. Fixes #558459. + +2008-11-03 12:29:10 +0000 Stefan Kost + + gst/gstregistrybinary.c: Don't bother with the GTimer if we don't output the results. + Original commit message from CVS: + * gst/gstregistrybinary.c: + Don't bother with the GTimer if we don't output the results. + +2008-11-03 10:59:49 +0000 David Schleef + + libs/gst/net/Makefile.am: Add WIN32_LIBS to libgstnet LIBADD. Fixes #557300. + Original commit message from CVS: + Patch by: David Schleef + * libs/gst/net/Makefile.am: + Add WIN32_LIBS to libgstnet LIBADD. Fixes #557300. + +2008-10-31 15:54:44 +0000 Stefan Kost + + gst/gstregistrybinary.c: Oh my, studip, stupid me. Remove double stat() call. + Original commit message from CVS: + * gst/gstregistrybinary.c: + Oh my, studip, stupid me. Remove double stat() call. + +2008-10-31 14:24:49 +0000 Stefan Kost + + gst/gstpreset.c: Use g_unlink instead of unlink. + Original commit message from CVS: + * gst/gstpreset.c: + Use g_unlink instead of unlink. + * gst/gststructure.c: + Use glib type. + * gst/gstutils.c: + Add a FIXME:. + * gst/gsttaglist.c: + * gst/gsttypefind.c: + * gst/gstvalue.c: + Formatting & whitespaces. + +2008-10-31 08:53:27 +0000 Stefan Kost + + plugins/elements/gstidentity.c: Doc typo. Use return value of parent_class->event. + Original commit message from CVS: + * plugins/elements/gstidentity.c: + Doc typo. Use return value of parent_class->event. + * plugins/elements/gsttypefindelement.c: + Chain up at the end for consistency. + +2008-10-30 15:29:51 +0000 Stefan Kost + + docs/: Change to xinclude based build - its faster and easier to maintain. + Original commit message from CVS: + * docs/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/running.xml: + * docs/libs/gstreamer-libs-docs.sgml: + Change to xinclude based build - its faster and easier to maintain. + +2008-10-30 14:15:14 +0000 Stefan Kost + + gst/: Use g_unlink() as none of these are directories. + Original commit message from CVS: + * gst/gstregistrybinary.c: + * gst/gstregistryxml.c: + Use g_unlink() as none of these are directories. + +2008-10-29 17:04:50 +0000 Wim Taymans + + gst/gstpipeline.c: Some more comments. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_provide_clock_func): + Some more comments. + +2008-10-27 15:02:48 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: If we have a fixate function, call it even if we already have fixed caps because th... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_find_transform), (gst_base_transform_getrange): + If we have a fixate function, call it even if we already have fixed caps + because the subclass might add some caps. Makes audioconvert add a + default channel layout. + +2008-10-24 09:41:19 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Clear the output buffer variable. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_getrange): + Clear the output buffer variable. + Cleanups to the error path in the getrange function. + Fixes #557649. + +2008-10-23 12:52:58 +0000 Sebastian Dröge + + plugins/elements/: Use gst_buffer_try_new_and_alloc() and handle errors instead of using gst_buffer_new_and_alloc() w... + Original commit message from CVS: + * plugins/elements/gstfdsrc.c: (gst_fd_src_create): + * plugins/elements/gstfilesrc.c: (gst_file_src_create_read): + Use gst_buffer_try_new_and_alloc() and handle errors instead of + using gst_buffer_new_and_alloc() which aborts if the buffer couldn't + be allocated. + +2008-10-23 09:49:07 +0000 Wim Taymans + + gst/gstsegment.c: Set the last_stop to a more meaningful position when configuring the segment. ie. the start/stop of... + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_newsegment_full): + Set the last_stop to a more meaningful position when configuring the + segment. ie. the start/stop of the segment or clipped against the + updated segment boundaries. + * tests/check/gst/gstsegment.c: (GST_START_TEST): + Add some unit tests for the last_stop. + +2008-10-23 07:11:54 +0000 Sebastian Dröge + + libs/gst/base/gstbytereader.c: Use GST_(READ|WRITE)_(FLOAT|DOUBLE)_(LE|BE) instead of our own copies of them. + Original commit message from CVS: + * libs/gst/base/gstbytereader.c: + Use GST_(READ|WRITE)_(FLOAT|DOUBLE)_(LE|BE) instead of our own + copies of them. + +2008-10-23 07:09:21 +0000 Sebastian Dröge + + API: Move float endianness conversion macros from libgstfloatcast to core as it's useful in general, even in core. Fi... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.h: + API: Move float endianness conversion macros from libgstfloatcast + to core as it's useful in general, even in core. Fixes bug #555196. + This adds GDOUBLE_FROM_BE, GDOUBLE_FROM_LE, GDOUBLE_TO_BE, + GDOUBLE_TO_LE, GDOUBLE_SWAP_LE_BE, GFLOAT_FROM_BE, GFLOAT_FROM_LE, + GFLOAT_TO_BE, GFLOAT_TO_LE, GFLOAT_SWAP_LE_BE. + Also add GST_READ_ and GST_WRITE_ macros for floats and doubles: + GST_READ_FLOAT_LE, GST_READ_FLOAT_BE, GST_READ_DOUBLE_LE, + GST_READ_DOUBLE_BE, GST_WRITE_FLOAT_LE, GST_WRITE_FLOAT_BE, + GST_WRITE_DOUBLE_LE, GST_WRITE_DOUBLE_BE. + +2008-10-22 14:47:04 +0000 Sebastian Dröge + + API: Add gst_byte_reader_get_data and gst_byte_reader_peek_data to get a pointer to the data at the current position ... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbytereader.c: (gst_byte_reader_get_data), + (gst_byte_reader_peek_data): + * libs/gst/base/gstbytereader.h: + * win32/common/libgstbase.def: + API: Add gst_byte_reader_get_data and gst_byte_reader_peek_data + to get a pointer to the data at the current position and have + a guaranteed size. + +2008-10-22 14:25:16 +0000 Jan Schmidt + + configure.ac: Fix a bug in the output of the configure script summary when --gst-disable-registry is supplied + Original commit message from CVS: + * configure.ac: + Fix a bug in the output of the configure script summary + when --gst-disable-registry is supplied + +2008-10-22 13:47:20 +0000 Jan Schmidt + + libs/gst/base/: Fix the names of 2 functions in the docs strings. + Original commit message from CVS: + * libs/gst/base/gstbitreader.c: + * libs/gst/base/gstbytereader.c: + Fix the names of 2 functions in the docs strings. + +2008-10-21 16:30:41 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Protect sink_alloc caps with the sinkpad lock to avoid nasty caps refcount problems... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_buffer_alloc), (gst_base_transform_suggest): + Protect sink_alloc caps with the sinkpad lock to avoid nasty caps + refcount problems as seen in banshee and maybe also in farsight2. + Remove atomic int now that we need to take the lock anyways. + +2008-10-20 15:18:14 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Implement more seeking in pull mode. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_default_do_seek), + (gst_base_sink_default_prepare_seek_segment), + (gst_base_sink_perform_seek), (gst_base_sink_get_position_last), + (gst_base_sink_get_position_paused), (gst_base_sink_get_position), + (gst_base_sink_query): + Implement more seeking in pull mode. + Use pad convert functions to convert position to the requested format. + Fix position/duration reporting in pull mode. + Implement position and duration reporting in other formats than time. + * libs/gst/base/gstbasesink.h: + Add member to keep track of when the segment is playing. + +2008-10-20 13:32:07 +0000 Wim Taymans + + gst/gstpad.c: When we use gst_pad_alloc_buffer() without wanting to set the caps we also don't need to check if the c... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_configure_src): + When we use gst_pad_alloc_buffer() without wanting to set the caps we + also don't need to check if the caps are compatible because the caller + presumably is going to perform its own custom checks. Fixes some cases + where basetransform elements would error out when it was not needed. + +2008-10-20 13:29:06 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Update comment. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek): + Update comment. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_handle_buffer), + (gst_base_transform_reconfigure): + Add some debug info. + * win32/common/libgstbase.def: + Add new method. + +2008-10-19 19:57:25 +0000 Stefan Kost + + libs/gst/base/gstbasesrc.c: (gst_base_src_default_do_seek); + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_do_seek); + Remove duplicated assignment and log a message in failure case. + +2008-10-19 10:13:39 +0000 Dig Ge + + tests/examples/helloworld/helloworld.c: Fix copy'n'paste bug in hello world example (#556900). + Original commit message from CVS: + Patch by: Dig Ge + * tests/examples/helloworld/helloworld.c: (main): + Fix copy'n'paste bug in hello world example (#556900). + +2008-10-17 13:27:59 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Query the total number of bytes when activating the pad in pull mode. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_pad_activate_pull), + (gst_base_sink_query): + Query the total number of bytes when activating the pad in pull mode. + Implement duration query in pull mode by using the installed pad convert + function to convert from bytes to the requested format. + +2008-10-16 14:09:18 +0000 Wim Taymans + + Add method to commit the state in subclasses. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_do_preroll), + (gst_base_sink_flush_start), (gst_base_sink_flush_stop), + (gst_base_sink_event), (gst_base_sink_perform_seek), + (gst_base_sink_loop), (gst_base_sink_pad_activate_pull), + (gst_base_sink_send_event), (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + Add method to commit the state in subclasses. + Refactor the flush_start and flush_stop code because we need it for + flushing while seeking too. + Implement the beginnings of seeking in pull mode. + Use the segment last_stop field for the pulling offset. + Fix the pause method in pull mode. + Configure the segment to BYTES for pull mode. + API: GstBaseSink::gst_base_sink_do_preroll() + +2008-10-16 13:56:52 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Update some docs. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init): + Update some docs. + +2008-10-14 17:10:43 +0000 Tim-Philipp Müller + + gst/gstquark.c: Fix printf format warning. + Original commit message from CVS: + * gst/gstquark.c: (_priv_gst_quarks_initialize): + Fix printf format warning. + +2008-10-14 12:34:56 +0000 Sebastian Dröge + + plugins/elements/gsttee.c: Fix flow aggregation of tee. Error out immediately for all flow returns except OK and NOT_... + Original commit message from CVS: + * plugins/elements/gsttee.c: (gst_tee_handle_buffer): + Fix flow aggregation of tee. Error out immediately for all flow returns + except OK and NOT_LINKED, return NOT_LINKED if all pads are not linked + and return OK if at least one pad is linked. + Before we errored out on "fatal" flow returns (i.e. not for WRONG_STATE) + and otherwise returned the flow return of the last pad, which is wrong. + * tests/check/elements/tee.c: (_fake_chain), (_fake_chain_error), + (GST_START_TEST), (tee_suite): + Add unit tests for the flow aggregation. + +2008-10-13 17:19:25 +0000 Wim Taymans + + docs/design/part-TODO.txt: Remove item from the todo list because it was fixed with the latency state change rewrites. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Remove item from the todo list because it was fixed with the latency + state change rewrites. + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + Update some docs. + * gst/gstevent.c: (gst_event_new_new_segment_full), + (gst_event_parse_new_segment_full), (gst_event_new_buffer_size), + (gst_event_parse_buffer_size), (gst_event_new_qos), + (gst_event_parse_qos), (gst_event_new_seek), + (gst_event_parse_seek), (gst_event_new_latency), + (gst_event_parse_latency): + Use quarks to construct and parse events. + * gst/gstquark.c: (_priv_gst_quarks_initialize): + * gst/gstquark.h: + Add some more quarks to the table. + Emit a warning when the quark tables are not in sync. + * tests/check/gst/gstbus.c: (GST_START_TEST): + Add an assert. + +2008-10-13 16:47:51 +0000 Stefan Kost + + plugins/: Don't install static libs for plugins. Fixes #550851 for core. + Original commit message from CVS: + * plugins/elements/Makefile.am: + * plugins/indexers/Makefile.am: + Don't install static libs for plugins. Fixes #550851 for core. + +2008-10-13 10:50:17 +0000 Wim Taymans + + gst/gstbus.c: Fix deadlock, g_source_get_id() cannot be called in finalize. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_source_finalize), + (gst_bus_add_watch_full_unlocked), (gst_bus_add_watch_full), + (gst_bus_enable_sync_message_emission), + (gst_bus_disable_sync_message_emission), + (gst_bus_add_signal_watch_full), (gst_bus_remove_signal_watch): + Fix deadlock, g_source_get_id() cannot be called in finalize. + Keep track of the watch source by keeping a pointer to the source object + instead. + Use the bus lock to protect access to the pointer to the current + watch source. + +2008-10-13 09:22:22 +0000 Olivier Crete + + gst/gstbus.c: Only allow one bus watch to be set at a time. This is necessary because the dispatcher pops the message... + Original commit message from CVS: + Base on Patch by: Olivier Crete + * gst/gstbus.c: (gst_bus_source_finalize), + (gst_bus_add_watch_full), (gst_bus_add_signal_watch_full): + Only allow one bus watch to be set at a time. This is necessary + because the dispatcher pops the message from the bus and the second + watcher will then get NULL or the next message (and the first won't + get this next message then, etc). If more than one "watcher" is + required signal watches should be used. Fixes bug #526044. + +2008-10-12 22:16:00 +0000 Jan Schmidt + + tools/gst-launch.c: Change the printing of the 'buffering...' output to avoid putting a \r in a translateable string ... + Original commit message from CVS: + * tools/gst-launch.c: + Change the printing of the 'buffering...' output to avoid putting + a \r in a translateable string (flagged by the TP). + +2008-10-10 15:38:06 +0000 Sebastian Dröge + + gst/gstxml.c: Clarify that the save_thyself() and restore_thyself() virtual functions of GstObject need to be overrid... + Original commit message from CVS: + * gst/gstxml.c: + Clarify that the save_thyself() and restore_thyself() virtual + functions of GstObject need to be overriden, not + gst_object_(save|restore)_thyself() which is impossible. + Fixes bug #555700. + +2008-10-10 15:27:37 +0000 Wim Taymans + + gst/gstpad.c: Revert a patch from 21 months ago that broke caps negotiation in pull mode. Basically, having a buffer ... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_range), (gst_pad_pull_range): + Revert a patch from 21 months ago that broke caps negotiation in pull + mode. Basically, having a buffer pass over a pad will trigger the + setcaps function when caps change, just like in push mode. + +2008-10-10 15:12:11 +0000 Wim Taymans + + docs/design/part-negotiation.txt: Update the docs some more. + Original commit message from CVS: + * docs/design/part-negotiation.txt: + Update the docs some more. + * libs/gst/base/gsttypefindhelper.c: (helper_find_peek): + If we pull a buffer with non-trivial caps, suggest those caps with the + max probability. + +2008-10-10 14:31:03 +0000 Edward Hervey + + docs/design/part-TODO.txt: Add another limitation of pad-blocking with segment seeks not pushing + Original commit message from CVS: + * docs/design/part-TODO.txt: + Add another limitation of pad-blocking with segment seeks not pushing + EOS events. + +2008-10-10 13:24:13 +0000 Jan Schmidt + + win32/common/: Add new symbols to the win32 defs files + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + Add new symbols to the win32 defs files + +2008-10-10 10:38:12 +0000 Wim Taymans + + gst/gstbin.c: The message src can be NULL, don't try to print the object names in that case. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_remove_func), (update_degree), + (gst_bin_handle_message_func): + The message src can be NULL, don't try to print the object names in that + case. + * libs/gst/base/gstbasesink.c: (gst_base_sink_pad_activate): + Add some more debug info. + * tests/check/pipelines/simple-launch-lines.c: (run_pipeline), + (GST_START_TEST): + Add some debug. + Fix the test, pull based sinks go ASYNC to PAUSED, just like other + scheduling modes. + +2008-10-10 10:01:36 +0000 Wim Taymans + + docs/design/part-negotiation.txt: Small doc update. + Original commit message from CVS: + * docs/design/part-negotiation.txt: + Small doc update. + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_pad_getcaps), (gst_base_sink_pad_setcaps), + (gst_base_sink_init), (gst_base_sink_set_blocksize), + (gst_base_sink_get_blocksize), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_needs_preroll), + (gst_base_sink_loop), (gst_base_sink_pad_activate), + (gst_base_sink_negotiate_pull), (gst_base_sink_pad_activate_pull), + (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + Add blocksize property and methods to control the amount of data + to pull. + Negotiate first before activating upstream in pull mode so that they can + negotiate themselves. + When we operate in pull mode, we only accept the caps that we + negotiated. + Make the sink go ASYNC to PAUSED, like all other sinks. + API: GstBaseSink::gst_base_sink_set_blocksize() + API: GstBaseSink::gst_base_sink_get_blocksize() + API: GstBaseSink::blocksize + * libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing), + (gst_base_src_set_live), (gst_base_src_is_live), + (gst_base_src_set_format), (gst_base_src_query_latency), + (gst_base_src_set_blocksize), (gst_base_src_get_blocksize), + (gst_base_src_set_do_timestamp), (gst_base_src_get_do_timestamp), + (gst_base_src_set_property), (gst_base_src_get_property): + * libs/gst/base/gstbasesrc.h: + Add typechecking in public API functions. + Add methods to control the blocksize in subclasses. + API: GstBaseSrc::gst_base_src_set_blocksize() + API: GstBaseSrc::gst_base_src_get_blocksize() + +2008-10-10 09:11:10 +0000 Edward Hervey + + tests/check/gst/gstutils.c: We now see 3 events go through our pad, since basesink now sends upstream latency events. + Original commit message from CVS: + * tests/check/gst/gstutils.c: (probe_do_nothing), (data_probe), + (buffer_probe), (event_probe), (GST_START_TEST): + We now see 3 events go through our pad, since basesink now sends + upstream latency events. + +2008-10-08 15:21:12 +0000 Wim Taymans + + gst/gstpipeline.c: Release the object lock before trying to flush the bus. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_change_state): + Release the object lock before trying to flush the bus. + +2008-10-08 14:21:13 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Forward LATENCY events upstreams so that elements know about the total pipeline latency.... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_send_event): + Forward LATENCY events upstreams so that elements know about the total + pipeline latency. Fixes #555307. + +2008-10-08 11:20:17 +0000 Jan Schmidt + + plugins/elements/gstqueue.c: Allow through queries when we don't know how as otherwise it's not possible to query the... + Original commit message from CVS: + * plugins/elements/gstqueue.c: + Allow through queries when we don't know how + to adjust them (not TIME or BYTES), as otherwise it's + not possible to query the current position in order + to seek in other formats at all. + +2008-10-08 11:12:15 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2008-10-08 11:11:25 +0000 Andy Wingo + + docs/gst/gstreamer-sections.txt: Placate doc pendants. + Original commit message from CVS: + 2008-10-08 Andy Wingo + * docs/gst/gstreamer-sections.txt: Placate doc pendants. + +2008-10-08 10:39:24 +0000 Wim Taymans + + gst/gstghostpad.*: Unbreak -good build, private is a reserved c++ keyword. + Original commit message from CVS: + * gst/gstghostpad.c: + * gst/gstghostpad.h: + Unbreak -good build, private is a reserved c++ keyword. + +2008-10-08 10:19:11 +0000 Andy Wingo + + gst/gstghostpad.*: Fix unintended API removal: re-add GST_GHOST_PAD_CAST to the header. + Original commit message from CVS: + 2008-10-08 Andy Wingo + * gst/gstghostpad.h (GST_GHOST_PAD_CAST): + * gst/gstghostpad.c (GST_GHOST_PAD_CAST): Fix unintended API + removal: re-add GST_GHOST_PAD_CAST to the header. + +2008-10-08 10:12:45 +0000 Andy Wingo + + gst/gstghostpad.h (GstProxyPad, GstProxyPadClass, GstGhostPad) + Original commit message from CVS: + 2008-10-08 Andy Wingo + * gst/gstghostpad.h (GstProxyPad, GstProxyPadClass, GstGhostPad) + (GstGhostPadClass): Publically expose these structures so as to + allow easy subclassing from C. Hide the member data behind a + private opaque data pointer. + * gst/gstghostpad.c: Adapt to store instance data in the type + instance's private data region, not in the public struct. + +2008-10-08 10:07:15 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: If we can't get a cache file don't try to save something to it. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write_cache): + If we can't get a cache file don't try to save something to it. + Dereferencing NULL pointers usually isn't a good idea. + +2008-10-08 08:54:55 +0000 Andy Wingo + + gst/gstghostpad.c (gst_ghost_pad_construct): If we got a template via g_object_get(), be sure to unref it. + Original commit message from CVS: + 2008-10-08 Andy Wingo + * gst/gstghostpad.c (gst_ghost_pad_construct): If we got a + template via g_object_get(), be sure to unref it. + * gst/gstbuffer.h (GST_BUFFER_FREE_FUNC): Fix incorrect doc. + +2008-10-07 15:12:21 +0000 Jan Schmidt + + tests/check/: Add Sparc ABI checks + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_sparc.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_sparc.h: + Add Sparc ABI checks + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Cast signed integer to unsigned to avoid a compiler warning. + +2008-10-07 12:26:40 +0000 Sebastian Dröge + + libs/gst/base/gstbytereader.c: Use new GST_READ_UINT24_(LE|BE) macros. + Original commit message from CVS: + * libs/gst/base/gstbytereader.c: (gst_byte_reader_get_uint24_le), + (gst_byte_reader_get_uint24_be), (gst_byte_reader_get_int24_le), + (gst_byte_reader_get_int24_be), (gst_byte_reader_peek_uint24_le), + (gst_byte_reader_peek_uint24_be), (gst_byte_reader_peek_int24_le), + (gst_byte_reader_peek_int24_be): + Use new GST_READ_UINT24_(LE|BE) macros. + +2008-10-07 12:00:49 +0000 Sebastian Dröge + + Always use the unaligned variants of GST_READ_UINT* and GST_WRITE_UINT* as it's too easy to break the ISO C strict al... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.h: + Always use the unaligned variants of GST_READ_UINT* and GST_WRITE_UINT* + as it's too easy to break the ISO C strict aliasing rules with simple + casts to the corresponding type and this would introduce hard to debug + bugs. Fixes bug #545714. + API: Add GST_READ_UINT24_(LE|BE) and GST_WRITE_UINT24_(LE|BE). + +2008-10-07 06:56:11 +0000 Tim-Philipp Müller + + gst/: Add 'Since' bits to gtk-doc chunks for new API. + Original commit message from CVS: + * gst/gstbuffer.h: (GST_BUFFER_FREE_FUNC): + * gst/gstghostpad.c: (gst_ghost_pad_construct): + Add 'Since' bits to gtk-doc chunks for new API. + +2008-10-06 21:52:57 +0000 Thijs Vermeir + + docs/gst/gstreamer-sections.txt: Fix documentation + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Fix documentation + +2008-10-06 18:03:58 +0000 Andy Wingo + + * ChangeLog: + changelog, doh + Original commit message from CVS: + changelog, doh + +2008-10-06 18:01:42 +0000 Andy Wingo + + gst/gstbuffer.h (GST_BUFFER_FREE_FUNC): New API, a free function that will be called on the malloc_data to free it. B... + Original commit message from CVS: + 2008-10-06 Andy Wingo + * gst/gstbuffer.h (GST_BUFFER_FREE_FUNC): New API, a free function + that will be called on the malloc_data to free it. Basically a way + to avoid subclassing when all you need is a different free + function, i.e. free() instead of g_free(). + * gst/gstbuffer.c (gst_buffer_finalize): Free malloc_data via + calling the free function. + (gst_buffer_init): Initialize the free function to g_free. + +2008-10-06 17:57:25 +0000 Andy Wingo + + gst/gstghostpad.*: New function, finishes the initialization of ghost pad. Useful for language bindings and subclasse... + Original commit message from CVS: + 2008-10-06 Andy Wingo + * gst/gstghostpad.h: + * gst/gstghostpad.c (gst_ghost_pad_construct): New function, + finishes the initialization of ghost pad. Useful for language + bindings and subclassers of GstGhostPad. Fixes #539108. + (gst_ghost_pad_new_full): Use the new constructor. + +2008-10-06 16:15:02 +0000 Olivier Crete + + gst/gstbin.c: Keep track of pads that are being linked/unlinked and resync the state changes. + Original commit message from CVS: + Base on Patch by: Olivier Crete + * gst/gstbin.c: (gst_bin_init), (gst_bin_add_func), + (gst_bin_remove_func), (update_degree), + (gst_bin_sort_iterator_new), (gst_bin_handle_message_func): + Keep track of pads that are being linked/unlinked and resync the state + changes. + * gst/gstpad.c: (gst_pad_get_direction), + (gst_pad_set_chain_function), (gst_pad_set_getrange_function), + (gst_pad_set_checkgetrange_function), (gst_pad_unlink), + (gst_pad_link_prepare), (gst_pad_link), + (gst_pad_event_default_dispatch), (gst_pad_chain), (gst_pad_push), + (gst_pad_check_pull_range), (gst_pad_get_range), + (gst_pad_pull_range): + Some code cleanups, use macros to check pad direction. + Don't need to take the lock on the pad direction. + Post structure change when pads are linked/unlinked. + Change some checks into _return_if_fail(). + * tests/check/gst/gstbin.c: + (test_link_structure_change_state_changed_sync_cb), + (GST_START_TEST), (gst_bin_suite): + Add testcase for pad link/unlinke resync during a state change. + Fixes #510354. + +2008-10-06 15:31:49 +0000 Wim Taymans + + Implement STRUCTURE_CHANGED messages. These messages will be used to signal the parent bin of link/unlink operations ... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: (gst_message_new_structure_change), + (gst_message_parse_structure_change): + * gst/gstmessage.h: + Implement STRUCTURE_CHANGED messages. These messages will be used to + signal the parent bin of link/unlink operations that could require a + resync when doing a state change. See ##510354. + API: gst_message_new_structure_change() + API: gst_message_parse_structure_change() + +2008-10-06 15:21:14 +0000 Wim Taymans + + gst/gstquark.*: Add some more quarks for new message. See #510354. + Original commit message from CVS: + * gst/gstquark.c: + * gst/gstquark.h: + Add some more quarks for new message. See #510354. + +2008-10-06 12:57:39 +0000 Sebastian Dröge + + * ChangeLog: + ChangeLog surgery: add API tag + Original commit message from CVS: + ChangeLog surgery: add API tag + +2008-10-06 12:41:53 +0000 Sebastian Dröge + + Add bit reader and byte reader classes, including documentation and an extensive unit test suite. Fixes bug #553554. + Original commit message from CVS: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbitreader.c: (gst_bit_reader_new), + (gst_bit_reader_new_from_buffer), (gst_bit_reader_free), + (gst_bit_reader_init), (gst_bit_reader_init_from_buffer), + (gst_bit_reader_set_pos), (gst_bit_reader_get_pos), + (gst_bit_reader_get_remaining), (gst_bit_reader_skip), + (gst_bit_reader_skip_to_byte): + * libs/gst/base/gstbitreader.h: + * libs/gst/base/gstbytereader.c: (GDOUBLE_SWAP_LE_BE), + (GFLOAT_SWAP_LE_BE), (gst_byte_reader_new), + (gst_byte_reader_new_from_buffer), (gst_byte_reader_free), + (gst_byte_reader_init), (gst_byte_reader_init_from_buffer), + (gst_byte_reader_set_pos), (gst_byte_reader_get_pos), + (gst_byte_reader_get_remaining), (gst_byte_reader_skip), + (gst_byte_reader_get_uint8), (gst_byte_reader_get_int8), + (gst_byte_reader_peek_uint8), (gst_byte_reader_peek_int8), + (gst_byte_reader_get_uint24_le), (gst_byte_reader_get_uint24_be), + (gst_byte_reader_get_int24_le), (gst_byte_reader_get_int24_be), + (gst_byte_reader_peek_uint24_le), (gst_byte_reader_peek_uint24_be), + (gst_byte_reader_peek_int24_le), (gst_byte_reader_peek_int24_be): + * libs/gst/base/gstbytereader.h: + * tests/check/Makefile.am: + * tests/check/libs/bitreader.c: (GST_START_TEST), + (gst_bit_reader_suite): + * tests/check/libs/bytereader.c: (GST_START_TEST), + (gst_byte_reader_suite): + Add bit reader and byte reader classes, including documentation + and an extensive unit test suite. Fixes bug #553554. + +2008-10-06 08:58:25 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Improve position reporting while flushing and other intermediate state changes. Fixes #5... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position), + (gst_base_sink_query): + Improve position reporting while flushing and other intermediate state + changes. Fixes #553874. + +2008-10-06 08:45:42 +0000 Antoine Tremblay + + gst/gstpad.c: Fix small refount leak in caps compatibility check. + Original commit message from CVS: + Patch by: Antoine Tremblay + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked): + Original patch by : Simon Descaries + Fix small refount leak in caps compatibility check. + Fixes #551676. + +2008-10-06 07:30:57 +0000 Stefan Kost + + docs/pwg/advanced-request.xml: Fix 0.8 api usage in example. Fixes #554561 + Original commit message from CVS: + * docs/pwg/advanced-request.xml: + Fix 0.8 api usage in example. Fixes #554561 + * docs/pwg/appendix-porting.xml: + Change 0.9 to 0.10 here. + +2008-10-06 07:13:02 +0000 Stefan Kost + + docs/manual/basics-data.xml: Change "event-event interaction" to "element-element interaction". + Original commit message from CVS: + * docs/manual/basics-data.xml: + Change "event-event interaction" to "element-element interaction". + Fixes #552448. Also fix sample code for seeking and do more 0.8->0.10 + updates. + +2008-10-05 10:01:50 +0000 Jan Schmidt + + configure.ac: Back to development -> 0.10.21.1 + Original commit message from CVS: + * configure.ac: + Back to development -> 0.10.21.1 + +=== release 0.10.21 === + +2008-10-02 23:59:53 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.10.21 + Original commit message from CVS: + Release 0.10.21 + +2008-10-02 22:42:18 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-09-28 22:49:56 +0000 Jan Schmidt + + configure.ac: 0.10.20.4 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.20.4 pre-release + +2008-09-28 21:19:15 +0000 Jan Schmidt + + Fix assertion in basetransform when the subclass chooses not to allocate a buffer in prepare_buffer(), and make capsf... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + * plugins/elements/gstcapsfilter.c: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/capsfilter.c: + Fix assertion in basetransform when the subclass chooses not to + allocate a buffer in prepare_buffer(), and make capsfilter error out + cleanly if requested to apply caps that don't completely specify the + buffer. Fixes #551509 + +2008-09-24 15:03:40 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Take new caps ref because our old one might have been gone when the subclass perfor... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer): + Take new caps ref because our old one might have been gone when the + subclass performs a gst_pad_set_caps() on the srcpad. See #548764. + +2008-09-16 15:35:04 +0000 Jan Schmidt + + * ChangeLog: + Also commit ChangeLog + Original commit message from CVS: + Also commit ChangeLog + +2008-09-16 15:24:04 +0000 Jan Schmidt + + Gah. Commit pre-release info that should have gone in last week already. + Original commit message from CVS: + Gah. Commit pre-release info that should have gone in last week already. + 2008-09-10 Jan Schmidt + * configure.ac: + 0.10.20.2 pre-release + * po/LINGUAS: + * po/id.po: + * po/pt_BR.po: + New translations. + +2008-09-15 15:18:07 +0000 Stefan Kost + + configure.ac: Do not probe availability of check unit test library when cross compiling, as test would not work anywa... + Original commit message from CVS: + * configure.ac: + Do not probe availability of check unit test library when cross + compiling, as test would not work anyway. Also cleanup verbose output + of the check test. Fixes #551952. + +2008-09-14 22:01:30 +0000 Antoine Tremblay + + gst/gstelement.c: Avoid leaking the parent ref when we fail changing the state of the element using gst_element_sync_... + Original commit message from CVS: + Based on patch by: Antoine Tremblay + * gst/gstelement.c: (gst_element_sync_state_with_parent): + Avoid leaking the parent ref when we fail changing the state of the + element using gst_element_sync_state_with_parent(). Fixes #551978. + +2008-09-11 16:56:48 +0000 Tim-Philipp Müller + + docs/manual/intro-motivation.xml: Remove some bits that no longer apply, update others (#551642). + Original commit message from CVS: + * docs/manual/intro-motivation.xml:: + Remove some bits that no longer apply, update others (#551642). + +2008-09-09 18:47:27 +0000 Tim-Philipp Müller + + win32/common/config.h.in: Add GST_DATADIR, hard-code cpu to x86. + Original commit message from CVS: + * win32/common/config.h.in: + Add GST_DATADIR, hard-code cpu to x86. + * win32/common/libgstreamer.def: + Spaces to tabs. + +2008-09-03 05:52:40 +0000 Tim-Philipp Müller + + gst/gsttaglist.h: Fix Since: markers for new geo tags. + Original commit message from CVS: + * gst/gsttaglist.h: + Fix Since: markers for new geo tags. + +2008-09-02 20:00:28 +0000 Stefan Kost + + gst/gsttaglist.h: Fix actual tag name define after renaming from altitude to elevation. + Original commit message from CVS: + * gst/gsttaglist.h: + Fix actual tag name define after renaming from altitude to elevation. + +2008-09-01 14:05:45 +0000 Wim Taymans + + gst/gstpad.c: Add fallback when calling the deprecated function on an element that implements the new internal_link h... + Original commit message from CVS: + * gst/gstpad.c: (add_unref_pad_to_list), + (gst_pad_get_internal_links_default): + Add fallback when calling the deprecated function on an element that + implements the new internal_link handler. + +2008-09-01 13:35:32 +0000 Stefan Kost + + Add new tags for geo location and clarify purpose of existing location tag. Fixes #481169 + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + Add new tags for geo location and clarify purpose of existing location + tag. Fixes #481169 + +2008-09-01 11:27:45 +0000 Olivier Crete + + gst/gstpad.c: Use thread-safe internal links iterator. Fixes #549504. + Original commit message from CVS: + Patch by: Olivier Crete + * gst/gstpad.c: (gst_pad_iterate_internal_links_default), + (gst_pad_event_default_dispatch), (gst_pad_dispatcher): + Use thread-safe internal links iterator. Fixes #549504. + +2008-09-01 10:42:04 +0000 Olivier Crete + + Add threadsafe replacement functions for getting internal links of an element. Deprecate the old internal links funct... + Original commit message from CVS: + Based on patch by: Olivier Crete + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + * gst/gstpad.c: (gst_pad_init), + (gst_pad_set_iterate_internal_links_function), + (int_link_iter_data_free), (iterate_pad), + (gst_pad_iterate_internal_links_default), + (gst_pad_iterate_internal_links), (gst_pad_get_internal_links): + * gst/gstpad.h: + Add threadsafe replacement functions for getting internal links of an + element. Deprecate the old internal links functions. + API:GstPad::gst_pad_set_iterate_internal_links_function() + API:GstPad::GstPadIterIntLinkFunction + API:GstPad::gst_pad_iterate_internal_links() + API:GstPad::gst_pad_iterate_internal_links_default() + * gst/gstghostpad.c: (gst_proxy_pad_do_iterate_internal_links), + (gst_proxy_pad_init): + Implement threadsafe internal links. + * tests/check/elements/tee.c: (GST_START_TEST), (tee_suite): + Unit test for internal links on tee. See #549504. + +2008-08-30 12:57:47 +0000 Edward Hervey + + tests/check/Makefile.am: libs/transform1 test requires libs/test_transform.c + Original commit message from CVS: + * tests/check/Makefile.am: + libs/transform1 test requires libs/test_transform.c + +2008-08-30 12:07:41 +0000 Edward Hervey + + gst/gstpad.c: Die evil deadlock, die ! + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_internal_links_default): + Die evil deadlock, die ! + +2008-08-30 11:55:59 +0000 Edward Hervey + + Fix all leaks due to the bug in gst_pad_template_new() by which it does not steal the refcount of the given caps as s... + Original commit message from CVS: + * gst/gstutils.c: (gst_element_get_compatible_pad): + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + * tests/check/gst/gstpad.c: (name_is_valid), (GST_START_TEST): + Fix all leaks due to the bug in gst_pad_template_new() by which it does + not steal the refcount of the given caps as stated. + REVERT THIS COMMIT ONCE FIXED ! + REVERT THIS COMMIT ONCE FIXED ! + REVERT THIS COMMIT ONCE FIXED ! + REVERT THIS COMMIT ONCE FIXED ! + REVERT THIS COMMIT ONCE FIXED ! + REVERT THIS COMMIT ONCE FIXED ! + +2008-08-29 17:58:25 +0000 Wim Taymans + + gst/gstiterator.*: After 3 years it's about time to revise the documentation of the iterator objects. + Original commit message from CVS: + * gst/gstiterator.c: + * gst/gstiterator.h: + After 3 years it's about time to revise the documentation of the + iterator objects. + +2008-08-29 16:10:56 +0000 Wim Taymans + + gst/gstpad.c: Make the internal links function less thread-unsafe and add some comments, dunno why. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_internal_links_default): + Make the internal links function less thread-unsafe and add some + comments, dunno why. + +2008-08-29 14:12:02 +0000 Tim-Philipp Müller + + gst/gst_private.h: Include gstinfo.h even if GST_DISABLE_GST_DEBUG is defined. Fixes build with --disable-gst-debug. + Original commit message from CVS: + * gst/gst_private.h: + Include gstinfo.h even if GST_DISABLE_GST_DEBUG is defined. Fixes + build with --disable-gst-debug. + +2008-08-29 00:34:58 +0000 David Schleef + + gst/gstpadtemplate.c: Revert last change, since it breaks a few plugins, ffmpeg, alaw, and mulaw. Code is correct, b... + Original commit message from CVS: + * gst/gstpadtemplate.c: Revert last change, since it breaks + a few plugins, ffmpeg, alaw, and mulaw. Code is correct, + but shouldn't be enabled until we've released fixed versions + of -good and -ffmpeg. + +2008-08-28 20:12:54 +0000 Stefan Kost + + gst/gstobject.c: Put the gst_object_get_name() back in. + Original commit message from CVS: + * gst/gstobject.c: + Put the gst_object_get_name() back in. + +2008-08-28 12:32:19 +0000 Stefan Kost + + gst/gstpadtemplate.c: The old behaviour was that gst_pad_template_new() takes ownership of the caps. As we now call g... + Original commit message from CVS: + * gst/gstpadtemplate.c: + The old behaviour was that gst_pad_template_new() takes ownership of + the caps. As we now call g_object_new() which calls g_object_set() and + which copies the caps, we have to unref them to not leak them. Fixes + make valgrid for me. + +2008-08-28 10:45:04 +0000 Stefan Kost + + gst/gsturi.c: Don't segfault on input like "tel:+1-123-555-1234". + Original commit message from CVS: + * gst/gsturi.c: + Don't segfault on input like "tel:+1-123-555-1234". + +2008-08-27 07:18:37 +0000 Stefan Kost + + gst/gstobject.c: Due to popular request also include ObjectType in gst_object_get_path_string(). Makes gst-launch -v ... + Original commit message from CVS: + * gst/gstobject.c: + Due to popular request also include ObjectType in + gst_object_get_path_string(). Makes gst-launch -v bit more useful. + +2008-08-27 03:04:23 +0000 David Schleef + + gst/gstutils.c: Remove check in gst_pad_query_convert() that src_val must be positive, because that's not a requirement. + Original commit message from CVS: + * gst/gstutils.c: Remove check in gst_pad_query_convert() that + src_val must be positive, because that's not a requirement. + This causes problems with converting negative granulepos + values for Dirac. + * gst/gstquery.c: Same, gst_query_new_convert(). + +2008-08-27 02:59:59 +0000 David Schleef + + gst/gstutils.c: Remove check in gst_pad_query_convert() that src_val must be positive, because that's not a requirement. + Original commit message from CVS: + * gst/gstutils.c: Remove check in gst_pad_query_convert() that + src_val must be positive, because that's not a requirement. + This causes problems with converting negative granulepos + values for Dirac. + +2008-08-25 11:06:34 +0000 Wim Taymans + + gst/gstclock.c: Add some more debugging to the clock slaving code. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_add_observation): + Add some more debugging to the clock slaving code. + * win32/common/libgstbase.def: + Add new basetransform method. + +2008-08-25 11:00:13 +0000 Wim Taymans + + gst/gstbin.c: Take the (recursive) state lock between getting the locked state of an element and changing the element... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_element_set_state): + Take the (recursive) state lock between getting the locked state of an + element and changing the element state. This allows the application to + lock an element's state and then change its state without races. + +2008-08-25 10:52:47 +0000 Wim Taymans + + gst/gstbin.c: When an element is in the locked state we still want to update the base_time of the element. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_element_set_state): + When an element is in the locked state we still want to update the + base_time of the element. + +2008-08-21 11:17:05 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Use the result from gst_pad_set_caps() instead of assuming the element always accepted th... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_negotiate): + Use the result from gst_pad_set_caps() instead of assuming the element + always accepted the caps computed by the default negotiate function. + +2008-08-20 10:52:09 +0000 Wim Taymans + + Implement method for reconfiguring basetransform. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_handle_buffer), (gst_base_transform_getrange), + (gst_base_transform_chain), (gst_base_transform_suggest), + (gst_base_transform_reconfigure): + * libs/gst/base/gstbasetransform.h: + Implement method for reconfiguring basetransform. + API: GstBaseTransform::gst_base_transform_reconfigure() + +2008-08-20 07:22:11 +0000 Murray Cumming + + gst/gstutils.c: Mention that this is just like gst_buffer_merge() but with extra unreffing for C coders. Advise langu... + Original commit message from CVS: + patch by: Murray Cumming + * gst/gstutils.c: + Mention that this is just like gst_buffer_merge() but with extra + unreffing for C coders. Advise language bindings not to wrap it. + Fixes Bug #533856. + Also fix file comment. + +2008-08-20 07:03:40 +0000 Stefan Kost + + plugins/elements/: Call super::event() when not handling it. Fixes #544855. + Original commit message from CVS: + reviewed by: Wim Taymans + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + Call super::event() when not handling it. Fixes #544855. + +2008-08-19 17:23:18 +0000 Alessandro Decina + + plugins/elements/gstfilesrc.c: Use 64 bit variants of stat functions on win32, to enable support of large files there. + Original commit message from CVS: + Patch by: Alessandro Decina + * plugins/elements/gstfilesrc.c: + Use 64 bit variants of stat functions on win32, to enable support + of large files there. + Fixes #547277. + +2008-08-19 16:47:07 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Improve position reporting in the flushing state. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_render_object), + (gst_base_sink_event), (gst_base_sink_chain_unlocked), + (gst_base_sink_negotiate_pull), (gst_base_sink_pad_activate_pull), + (gst_base_sink_get_position), (gst_base_sink_change_state): + Improve position reporting in the flushing state. + Also report the position when we are not yet prerolled but we + have a newsegment event. Fixes #543444. + Improve the pull-based negotiation code. + * tests/check/elements/fakesink.c: (GST_START_TEST), + (fakesink_suite): + Add testcase for position reporting while flushing in PAUSED and + PLAYING. + * tests/check/generic/sinks.c: (GST_START_TEST): + Update unit-test, we can now query the position as soon as we receive a + NEWSEGMENT event. + +2008-08-19 08:52:05 +0000 Jason Zhao + + libs/gst/base/gstbasesink.c: When the subclass event handler releases the PREROLL_LOCK, we could be in the flushing s... + Original commit message from CVS: + Based on patch by: Jason Zhao + * libs/gst/base/gstbasesink.c: (gst_base_sink_render_object): + When the subclass event handler releases the PREROLL_LOCK, we could be + in the flushing state and we have to ignore the event. Fixes #548394. + +2008-08-18 11:28:00 +0000 Tim-Philipp Müller + + tools/gst-launch.1.in: Document GST_REGISTRY_UPDATE environment variable. + Original commit message from CVS: + * tools/gst-launch.1.in: + Document GST_REGISTRY_UPDATE environment variable. + +2008-08-18 09:59:18 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: If the element is configured in passthrough mode but the prepare_output_buffer gave... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer): + If the element is configured in passthrough mode but the + prepare_output_buffer gave us a new output buffer, discard that buffer + and reuse the input buffer. + +2008-08-15 17:01:07 +0000 Ole André Vadla Ravnås + + plugins/elements/gsttee.*: Protect pad_alloc with a new lock so that we can be sure that nothing is performing a pad_... + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + * plugins/elements/gsttee.c: (gst_tee_finalize), (gst_tee_init), + (gst_tee_request_new_pad), (gst_tee_release_pad), + (gst_tee_find_buffer_alloc), (gst_tee_buffer_alloc): + * plugins/elements/gsttee.h: + Protect pad_alloc with a new lock so that we can be sure that nothing is + performing a pad_alloc when removing the pad. Fixes #547835. + * tests/check/elements/tee.c: (buffer_alloc_harness_setup), + (buffer_alloc_harness_teardown), (app_thread_func), + (final_sinkpad_bufferalloc), (GST_START_TEST), (tee_suite): + Added testcase for shutdown race. + +2008-08-14 20:05:33 +0000 Thijs Vermeir + + gst/gstpad.h: Add doc + Original commit message from CVS: + * gst/gstpad.h: + Add doc + +2008-08-14 16:37:29 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Go over the buffer_alloc function again and make sure we always end up allocating a... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_buffer_alloc): + Go over the buffer_alloc function again and make sure we always end up + allocating a buffer. + Add some more docs. + Avoid doing pad alloc when we have a pending suggestion because we + cannot yet deal with changing caps in that case. Fixes #547728 + +2008-08-14 14:26:20 +0000 Luc Pionchon + + docs/manual/: Add one more image showing different times together with a describing paragraph. Fixes #547729. + Original commit message from CVS: + patch by: Luc Pionchon + * docs/manual/advanced-clocks.xml: + * docs/manual/clocks.png: + * docs/manual/diagrams-clocks.svg: + Add one more image showing different times together with a describing + paragraph. Fixes #547729. + +2008-08-14 14:04:58 +0000 Wim Taymans + + win32/common/libgstbase.def: Add new method. + Original commit message from CVS: + * win32/common/libgstbase.def: + Add new method. + +2008-08-14 13:57:58 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Don't overwrite the outsize when calculating the expected size of a new buffer beca... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps), + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_buffer_alloc), (gst_base_transform_suggest): + Don't overwrite the outsize when calculating the expected size of a new + buffer because we still need it in case we cannot process the new + buffer. + When converting the size of the new buffer to an upstream size, actually + use the expected size of the buffer, not some other random value. + Use an atomic int to signal that a new upstream caps suggestion is + available. + When we can convert the current buffer to a new format, check if the + buffer size is of the expected size and allocate a new buffer of the + expected size when this is not the case. + * tests/check/libs/transform1.c: (GST_START_TEST): + remove ifdeffed code from the unit test. + +2008-08-12 18:48:42 +0000 Stefan Kost + + pkgconfig/: Remove -lgstcontrol-0.10 which never worked anyway as the lib is called gstcontroller-0.10. + Original commit message from CVS: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + Remove -lgstcontrol-0.10 which never worked anyway as the lib is + called gstcontroller-0.10. + +2008-08-12 06:27:35 +0000 Stefan Kost + + gst/: Remove double interface from doc-string. + Original commit message from CVS: + * gst/gstchildproxy.h: + * gst/gstpreset.h: + Remove double interface from doc-string. + +2008-08-12 06:16:02 +0000 Stefan Kost + + libs/gst/base/: Fix headings in docs and gtk-doc warnings. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + Fix headings in docs and gtk-doc warnings. + +2008-08-11 19:04:04 +0000 Michael Smith + + gst/gstregistrybinary.c: Don't use g_mkstmp() on win32, it's unsafe if glib is using a different libc. + Original commit message from CVS: + * gst/gstregistrybinary.c: + Don't use g_mkstmp() on win32, it's unsafe if glib is using a different + libc. + Fixes #544776. + +2008-08-11 15:14:28 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Fix a "may be used unitialized" warning. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Fix a "may be used unitialized" warning. + +2008-08-11 08:06:20 +0000 Stefan Kost + + Document preset-iface vmethods. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpreset.h: + Document preset-iface vmethods. + +2008-08-11 07:07:45 +0000 Stefan Kost + + docs/manual/advanced-interfaces.xml: Turn thoughts about HAL into a note-tag. Remove mentioning that is only used to ... + Original commit message from CVS: + * docs/manual/advanced-interfaces.xml: + Turn thoughts about HAL into a note-tag. Remove mentioning that is + only used to discover devices. + +2008-08-07 15:49:00 +0000 Frederic Crozat + + gst/gst.c: Make sure gettext returns translations in UTF-8 encoding rather than in the current locale encoding (#5468... + Original commit message from CVS: + Patch by: Frederic Crozat + * gst/gst.c: (init_pre): + Make sure gettext returns translations in UTF-8 encoding rather + than in the current locale encoding (#546822). + +2008-08-07 12:28:28 +0000 Wim Taymans + + gst/gstcaps.c: Fix subset test. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_structure_is_subset_field): + Fix subset test. + * tests/check/gst/gstcaps.c: (GST_START_TEST): + Improve unit test subset tests and add a testcase for the subset failure + cases. + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Improve subtraction unit test. + +2008-08-07 07:01:15 +0000 Stefan Kost + + plugins/elements/gsttee.c: Unlock, instead of locking again. + Original commit message from CVS: + * plugins/elements/gsttee.c: + Unlock, instead of locking again. + +2008-08-05 16:50:27 +0000 Wim Taymans + + gst/gstpad.h: Clarify the docs a bit more. + Original commit message from CVS: + * gst/gstpad.h: + Clarify the docs a bit more. + +2008-08-05 15:42:00 +0000 Stefan Kost + + tests/examples/metadata/read-metadata.c: Don't leak old taglist. + Original commit message from CVS: + * tests/examples/metadata/read-metadata.c: + Don't leak old taglist. + +2008-08-05 15:03:27 +0000 Olivier Crete + + gst/gststructure.c: Avoid overflows in fixation code when dealing with MAXINT values, which v4l2src seems to do. + Original commit message from CVS: + Patch by: Olivier Crete + * gst/gststructure.c: + (gst_structure_fixate_field_nearest_fraction): + Avoid overflows in fixation code when dealing with MAXINT values, which + v4l2src seems to do. + Fixes #546328. + * tests/check/gst/gststructure.c: (GST_START_TEST): + Make a unit test to check the fix. + +2008-08-05 11:12:29 +0000 Wim Taymans + + plugins/elements/gstcapsfilter.c: Use new caps suggestion feature of basetransform to request a caps negotiation upst... + Original commit message from CVS: + * plugins/elements/gstcapsfilter.c: (copy_func), + (gst_capsfilter_set_property): + Use new caps suggestion feature of basetransform to request a caps + negotiation upstream. + +2008-08-05 11:11:00 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: Add new function: + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add new function: + API: GstBaseTransform::gst_base_transform_suggest() + * libs/gst/base/gstbasetransform.c: (gst_base_transform_finalize), + (gst_base_transform_init), (gst_base_transform_transform_caps), + (gst_base_transform_transform_size), + (gst_base_transform_configure_caps), + (gst_base_transform_can_transform), + (gst_base_transform_find_transform), (gst_base_transform_setcaps), + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer), (gst_base_transform_getrange), + (gst_base_transform_chain), (gst_base_transform_activate), + (gst_base_transform_set_passthrough), + (gst_base_transform_is_passthrough), + (gst_base_transform_set_in_place), + (gst_base_transform_is_in_place), (gst_base_transform_update_qos), + (gst_base_transform_set_qos_enabled), + (gst_base_transform_is_qos_enabled), + (gst_base_transform_set_gap_aware), (gst_base_transform_suggest), + (gst_base_transform_reconfigure): + * libs/gst/base/gstbasetransform.h: + Rewrite of basetransform to perform negotiation outside of the + buffer_alloc functions. Fixes #545853. + * tests/check/libs/transform1.c: (GST_START_TEST), + (buffer_alloc_ct2): + Update unit test. + +2008-08-05 05:44:02 +0000 Stefan Kost + + tests/check/gst/gstpreset.c: Only run preset tests when $HOME is writable. Preliminary fix for #545433. + Original commit message from CVS: + * tests/check/gst/gstpreset.c: + Only run preset tests when $HOME is writable. Preliminary fix for + #545433. + +2008-08-04 15:49:13 +0000 Wim Taymans + + gst/gstbin.c: Fix race for bins that simulate ASYNC state changes by inserting + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_change_state_func), (bin_handle_async_done), + (gst_bin_handle_message_func): + Fix race for bins that simulate ASYNC state changes by inserting + ASYNC_START and ASYNC_DONE messages in their bus. We need to check for + pending ASYNC messages even when the bin does not have ASYNC children. + We note detect this behaviour because we will receive an ASYNC message + that is originating from the bin itself. + Fixes races with decodebin2 state changes. + * tests/check/gst/gstbin.c: (GST_START_TEST): + Add some more debug. + +2008-08-04 13:01:35 +0000 Tim-Philipp Müller + + gst/gsttaglist.c: Fix typo. + Original commit message from CVS: + * gst/gsttaglist.c: (_gst_tag_initialize): + Fix typo. + +2008-08-04 12:46:23 +0000 Stefan Kost + + gst/gsttaglist.c: Argh. actually save the text before committing. Now adds gst_tag_merge_strings_with_comma() to gst_... + Original commit message from CVS: + * gst/gsttaglist.c: + Argh. actually save the text before committing. Now adds + gst_tag_merge_strings_with_comma() to gst_tag_register(). + +2008-08-04 12:30:26 +0000 Stefan Kost + + gst/gsttaglist.*: Do as tim pointed out and actually register the new tag. Also improve te docs and use gst_tag_merge... + Original commit message from CVS: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + Do as tim pointed out and actually register the new tag. Also improve + te docs and use gst_tag_merge_strings_with_comma() method to allow + retriving all keywords merged in one list. + +2008-08-01 11:57:40 +0000 Stefan Kost + + Revert 'accidential' change of the configure option removal. We still need to generate the types file in configure --... + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer.types: + Revert 'accidential' change of the configure option removal. We still + need to generate the types file in configure --disable-load-save. + +2008-08-01 11:34:06 +0000 Stefan Kost + + Add new taglist item GST_TAG_KEYWORDS, needed for #520694 . + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.h: + Add new taglist item GST_TAG_KEYWORDS, needed for #520694 . + +2008-08-01 10:02:49 +0000 Tim-Philipp Müller + + gst/gstpadtemplate.c: Add "name-template", "direction", "presence" and "caps" properties, so that gst_pad_template_ne... + Original commit message from CVS: + * gst/gstpadtemplate.c: + (gst_pad_template_class_init), (gst_static_pad_template_get), + (gst_pad_template_new), (gst_pad_template_pad_created), + (gst_pad_template_set_property), (gst_pad_template_get_property): + Add "name-template", "direction", "presence" and "caps" properties, + so that gst_pad_template_new() is just a thin wrapper around + g_object_new(), which is better for bindings. (Fixes: #539772) + +2008-07-31 17:16:50 +0000 Michael Smith + + gst/gsturi.c: Be more liberal in what URIs we accept. + Original commit message from CVS: + * gst/gsturi.c: + Be more liberal in what URIs we accept. + Do not unescape bits of the URI for no apparent reason before passing to + the element. Fixes #545352. + +2008-07-31 15:24:21 +0000 Robert Schwebel + + gst/gst.c: Include gstconfig.h as macros from it are used. Fixes bug #545607. + Original commit message from CVS: + Patch by: Robert Schwebel + * gst/gst.c: + Include gstconfig.h as macros from it are used. Fixes bug #545607. + +2008-07-31 15:20:32 +0000 Sebastian Dröge + + Remove GST_DISABLE_(ENUMTYPES|INDEX|URI) everywhere. + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_index_func): + * gst/gstconfig.h.in: + * gst/gstelement.c: (gst_element_get_index): + * gst/gstregistrybinary.c: (gst_registry_binary_save_feature), + (gst_registry_binary_load_feature), + (gst_registry_binary_read_cache): + * gst/gstregistryxml.c: (load_feature), + (gst_registry_xml_read_cache), (gst_registry_xml_save_feature): + * plugins/Makefile.am: + * tools/gst-indent: + * tools/gst-inspect.c: (print_index_info), (print_element_list), + (print_plugin_features), (print_element_features): + * tools/gst-xmlinspect.c: (print_event_masks), + (print_element_info): + * win32/common/gstconfig.h: + Remove GST_DISABLE_(ENUMTYPES|INDEX|URI) everywhere. + Disabling the indexers and URI handler code will only reduce the + required amount of memory by a very small amount but on the other hand + requires much more maintaince work. Apart from that many places of + code are broken when disabling them. + Disabling the enum types doesn't reduce the required amount of memory + by more than a few bytes and makes it hard to fix bugs like #539772, + i.e. use the enums as GObject properties. + +2008-07-31 13:06:56 +0000 Wim Taymans + + docs/design/part-TODO.txt: Add some thoughts and problems with upstream renegotiation. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Add some thoughts and problems with upstream renegotiation. + +2008-07-31 12:50:52 +0000 Wim Taymans + + gst/gstpad.c: Remove silly redundant debug. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_acceptcaps_default), + (gst_pad_configure_src), (gst_pad_alloc_buffer_full): + Remove silly redundant debug. + Add some more debug info. + Clarify the docs regarding new caps received from pad_alloc. + +2008-07-31 09:55:14 +0000 Wim Taymans + + plugins/elements/gstcapsfilter.c: Make setting the caps more threadsafe. + Original commit message from CVS: + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_set_property), + (gst_capsfilter_get_property), (gst_capsfilter_transform_caps): + Make setting the caps more threadsafe. + +2008-07-31 08:39:15 +0000 Wim Taymans + + docs/design/part-element-transform.txt: Update docs. + Original commit message from CVS: + * docs/design/part-element-transform.txt: + Update docs. + +2008-07-31 08:37:04 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Add and use a custom acceptcaps function instead of falling back to the potentially less... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_init), + (gst_queue_acceptcaps): + Add and use a custom acceptcaps function instead of falling back to the + potentially less optimized default implementation. + +2008-07-29 15:32:11 +0000 Tim-Philipp Müller + + gst/gstpad.c: Only sanity-check the buffer size if requested_caps == buffer_caps (ie. don't take pad caps into accoun... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer_full): + Only sanity-check the buffer size if requested_caps == buffer_caps + (ie. don't take pad caps into account, they're not relevant here) + +2008-07-29 14:32:51 +0000 Stefan Kost + + plugins/elements/gsttee.*: Reverting as not everything is clear yet. Needs some general design work. + Original commit message from CVS: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + Reverting as not everything is clear yet. Needs some general design + work. + +2008-07-29 13:36:39 +0000 Stefan Kost + + ChangeLog: ChangeLog surgery for tee commit. + Original commit message from CVS: + * ChangeLog: + ChangeLog surgery for tee commit. + +2008-07-29 13:30:02 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: Cleanup section-file. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Cleanup section-file. + +2008-07-29 11:57:11 +0000 Stefan Kost + + plugins/elements/gsttee.*: Relay tag events in tee. Fixes parts of #474016. + Original commit message from CVS: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + Relay tag events in tee. Fixes parts of #474016. + +2008-07-29 00:45:29 +0000 Michael Smith + + Build the net library if we have winsock2. + Original commit message from CVS: + * configure.ac: + * libs/gst/Makefile.am: + Build the net library if we have winsock2. + +2008-07-26 12:00:36 +0000 Luc Pionchon + + docs/manual/: Replace one diagram with two separate ones and updates others. + Original commit message from CVS: + patch by: Luc Pionchon + * docs/manual/advanced-threads.xml: + * docs/manual/diagrams-pipelines.svg: + * docs/manual/hello-world.png: + * docs/manual/linked-elements.png: + * docs/manual/mime-world.png: + * docs/manual/queue.png: + * docs/manual/thread-buffering.png: + * docs/manual/thread-synchronizing.png: + Replace one diagram with two separate ones and updates others. + Fixes #542401. + +2008-07-25 10:24:43 +0000 Thijs Vermeir + + gst/gstelement.h: Fix link in documentation. + Original commit message from CVS: + * gst/gstelement.h: + Fix link in documentation. + +2008-07-24 17:38:43 +0000 Thijs Vermeir + + gst/gstmessage.c: Fix confusing documentation. + Original commit message from CVS: + * gst/gstmessage.c: + Fix confusing documentation. + +2008-07-24 15:13:24 +0000 Thijs Vermeir + + libs/gst/base/gstbasesrc.h: revert the changes to the header file for the ABI. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.h: + revert the changes to the header file for the ABI. + +2008-07-24 14:47:58 +0000 Thijs Vermeir + + libs/gst/base/gstbasesrc.*: Don't cache the seekable status. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + Don't cache the seekable status. + Fixes bug #544174 + +2008-07-24 12:36:20 +0000 Rene Stadler + + docs/manual/advanced-autoplugging.xml: Add fakesink to example code to close the pipeline graph. This prevents the p... + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: Add fakesink to example + code to close the pipeline graph. This prevents the program from + printing internal data flow errors. + +2008-07-23 15:44:04 +0000 Sebastian Dröge + + docs/manual/basics-bus.xml: Correct typo. Fixes bug #544320. + Original commit message from CVS: + * docs/manual/basics-bus.xml: + Correct typo. Fixes bug #544320. + +2008-07-22 18:12:54 +0000 Michael Smith + + configure.ac: Remove AC_ISC_POSIX macro; it's broken on some platforms and not needed. + Original commit message from CVS: + * configure.ac: + Remove AC_ISC_POSIX macro; it's broken on some platforms and not needed. + Add check (taken from -base) for winsock, adds WIN32_LIBS + * gst/Makefile.am: + Add WIN32_LIBS to LIBADD for libgstreamer. Needed now that gstpoll uses + winsock. + Define GST_EXPORTS when building libgstreamer (only used on win32) + * gst/gst_private.h: + * gst/gstinfo.h: + Use GST_EXPORT instead of locally-defined (and incorrect IMPORT_SYMBOL) + for symbols that we need to export in both these files. + * gst/gstpoll.c: + Include gst_private.h higher up to avoid some compile problems on win32. + +2008-07-22 09:24:37 +0000 Sebastian Dröge + + gst/gstvalue.c: Fix typos. + Original commit message from CVS: + * gst/gstvalue.c: + Fix typos. + +2008-07-22 00:29:55 +0000 Thijs Vermeir + + gst/gstcaps.c: Previous commit was wrong NULL caps does not exist and indicate an error, so also add a FIXME to gst_c... + Original commit message from CVS: + * gst/gstcaps.c: + Previous commit was wrong NULL caps does not exist + and indicate an error, so also add a FIXME to + gst_caps_is_equal where NULL caps are accepted. + +2008-07-21 23:02:40 +0000 Thijs Vermeir + + gst/gstcaps.c: Allow passing of NULL to gst_caps_union + Original commit message from CVS: + * gst/gstcaps.c: + Allow passing of NULL to gst_caps_union + +2008-07-21 21:32:06 +0000 Thijs Vermeir + + gst/gstghostpad.c: Add in doc that gst_ghost_pad_set_target can accept + Original commit message from CVS: + * gst/gstghostpad.c: + Add in doc that gst_ghost_pad_set_target can accept + NULL to clear target + +2008-07-15 22:53:00 +0000 Michael Smith + + gst/: GstRegistryPool doesn't exist; don't refer to it in docs. + Original commit message from CVS: + * gst/gstplugin.c: + * gst/gstregistry.c: + GstRegistryPool doesn't exist; don't refer to it in docs. + Don't refer to functions that don't exist in docs, it's + unhelpful. + +2008-07-12 17:51:16 +0000 Sebastian Dröge + + gst/gst.c: Fix scanning of paths given via --gst-plugin-path. Fixes bug #542175. + Original commit message from CVS: + * gst/gst.c: + Fix scanning of paths given via --gst-plugin-path. Fixes bug #542175. + +2008-07-12 17:43:15 +0000 tmatth + + docs/pwg/building-testapp.xml: Don't use an undeclared variable in the example program. + Original commit message from CVS: + Patch by: tmatth + * docs/pwg/building-testapp.xml: + Don't use an undeclared variable in the example program. + Fixes bug #542573. + +2008-07-12 09:59:32 +0000 Stefan Kost + + gst/gstdebugutils.c: Squeeze ghost-pad links and remove <> from classname labels to save more horizontal space. + Original commit message from CVS: + * gst/gstdebugutils.c: + Squeeze ghost-pad links and remove <> from classname labels to save + more horizontal space. + +2008-07-11 19:30:48 +0000 Stefan Kost + + gst/gstdebugutils.c: Give request and sometimes pads a different shpe style. Condense the graphs a little more. + Original commit message from CVS: + * gst/gstdebugutils.c: + Give request and sometimes pads a different shpe style. Condense the + graphs a little more. + +2008-07-10 00:30:02 +0000 Michael Smith + + configure.ac: Don't require flex and bison if the parser is disabled. + Original commit message from CVS: + * configure.ac: + Don't require flex and bison if the parser is disabled. + +2008-07-08 11:20:22 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolationcontrolsource.c: Don't use declarations after statements. + Original commit message from CVS: + * libs/gst/controller/gstinterpolationcontrolsource.c: + (_list_find_sorted_custom): + Don't use declarations after statements. + +2008-07-08 09:04:25 +0000 Sebastian Dröge + + gst/gstchildproxy.c: Add FIXMEs for 0.11 to use GST_TYPE_OBJECT in the signature of the the child-added / -removed si... + Original commit message from CVS: + * gst/gstchildproxy.c: (gst_child_proxy_base_init): + Add FIXMEs for 0.11 to use GST_TYPE_OBJECT in the signature + of the the child-added / -removed signals as GstChildProxy + only supports GstObjects. + +2008-07-07 11:01:26 +0000 Thijs Vermeir + + gst/gstdebugutils.c: Fix memleak + Original commit message from CVS: + * gst/gstdebugutils.c: + Fix memleak + +2008-07-06 12:49:43 +0000 Alessandro Decina + + gst/gstpoll.c: Fix "ignored return value" compiler warning with newer glibc. + Original commit message from CVS: + Patch by: Alessandro Decina + * gst/gstpoll.c: + Fix "ignored return value" compiler warning with newer glibc. + +2008-07-05 16:28:28 +0000 Sebastian Dröge + + gst/gstchildproxy.c: Fix copy&paste error in gst_child_proxy_removed() documentation. + Original commit message from CVS: + * gst/gstchildproxy.c: + Fix copy&paste error in gst_child_proxy_removed() documentation. + +2008-07-02 14:43:40 +0000 Tim-Philipp Müller + + gst/gstplugin.c: Print error debug message if plugin description fields that should be set are NULL. + Original commit message from CVS: + * gst/gstplugin.c: (CHECK_PLUGIN_DESC_FIELD), (gst_plugin_load_file): + Print error debug message if plugin description fields that should + be set are NULL. + * gst/gstregistrybinary.c: (gst_registry_binary_save_const_string): + Don't crash if the string to serialise is NULL (it really should + not be, but apparently this used to work with the xml registry ...). + +2008-07-02 12:23:12 +0000 Thijs Vermeir + + tools/gst-plot-timeline.py: Fix parsing of log messages + Original commit message from CVS: + * tools/gst-plot-timeline.py: + Fix parsing of log messages + +2008-07-01 09:27:47 +0000 Tim-Philipp Müller + + win32/common/libgstbase.def: Sort alphabetically so make check-exports doesn't barf. + Original commit message from CVS: + * win32/common/libgstbase.def:: + Sort alphabetically so make check-exports doesn't barf. + +2008-07-01 05:53:32 +0000 Stefan Kost + + gst/gstevent.c: Use gst_format_get_name() to improve debug output. + Original commit message from CVS: + * gst/gstevent.c: + Use gst_format_get_name() to improve debug output. + * gst/gstpreset.c: + Remove #ifdef'ed code. Add TODO comment. + * gst/gstsegment.c: + Add debug output to ease spotting format != segment.format assertions. + +2008-06-30 09:42:43 +0000 Sebastian Dröge + + tests/check/libs/gdp.c: Also enable the GDP unit test again on PPC now that the bug is fixed. + Original commit message from CVS: + * tests/check/libs/gdp.c: (gst_dp_suite): + Also enable the GDP unit test again on PPC now that the bug + is fixed. + +2008-06-30 09:38:45 +0000 Sebastian Dröge + + libs/gst/dataprotocol/dataprotocol.c: Don't write to the same region of memory as a uint64 and uint16 as this breaks ... + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + Don't write to the same region of memory as a uint64 and uint16 + as this breaks strict aliasing rules and apparantly breaks on PPC + and s390. Thanks to Sjoerd Simons for analysing. Fixes bug #348114. + +2008-06-29 16:11:24 +0000 Stefan Kost + + libs/gst/controller/gstinterpolationcontrolsource.c: Optimize list handling. Use own find function. Exploit that fact... + Original commit message from CVS: + * libs/gst/controller/gstinterpolationcontrolsource.c: + Optimize list handling. Use own find function. Exploit that fact that + the list is sorted. Also pass back the node before, so that we can + insert quickly. Have a fast path for append. + +2008-06-29 15:00:26 +0000 Stefan Kost + + docs/design/: Fix two typos. + Original commit message from CVS: + * docs/design/draft-framestep.txt: + * docs/design/part-negotiation.txt: + Fix two typos. + +2008-06-27 09:02:51 +0000 Stefan Kost + + configure.ac: + Original commit message from CVS: + * configure.ac: + Show configuration sumary after configure run. Based on patch by + Luc Pionchon . Fixes: #540134 + +2008-06-27 07:03:05 +0000 Luc Pionchon + + docs/manual/: Add scale factor for pdf output. + Original commit message from CVS: + patch by: Luc Pionchon + * docs/manual/advanced-autoplugging.xml: + * docs/manual/advanced-threads.xml: + * docs/manual/basics-bins.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-pads.xml: + Add scale factor for pdf output. + * docs/manual/intro-basics.xml: + Switched sections "pads" and "bins" and added a pipeline diagram. + * docs/manual/intro-gstreamer.xml: + Added more info on gstreamer. + * docs/manual/intro-motivation.xml: + Commented out the whole section "current problem", which sounds + historical and somehow osolete; it could be turned in a positive + way and reused to improve the design principles. + * docs/manual/intro-preface.xml: + - Update URLs to library.gnome.org. + - Do not mention GTK+ in preliminary reading (irrelevant). + - Mention Plugin Writer's Manual and further reading only in the + previous section. + - Added a list of most relevant GObject/glib topics. + * docs/manual/Makefile.am: + * docs/manual/bin-element-ghost.fig: + * docs/manual/bin-element-ghost.png: + * docs/manual/bin-element-noghost.fig: + * docs/manual/bin-element-noghost.png: + * docs/manual/bin-element.fig: + * docs/manual/bin-element.png: + * docs/manual/filter-element-multi.fig: + * docs/manual/filter-element-multi.png: + * docs/manual/filter-element.fig: + * docs/manual/filter-element.png: + * docs/manual/gstreamer-overview.png: + * docs/manual/hello-world.fig: + * docs/manual/hello-world.png: + * docs/manual/linked-elements.fig: + * docs/manual/linked-elements.png: + * docs/manual/mime-world.fig: + * docs/manual/mime-world.png: + * docs/manual/queue.fig: + * docs/manual/queue.png: + * docs/manual/simple-player.png: + * docs/manual/sink-element.fig: + * docs/manual/sink-element.png: + * docs/manual/src-element.fig: + * docs/manual/src-element.png: + * docs/manual/diagrams-general.svg: + * docs/manual/diagrams-pipelines.svg: + Removed .fig, added .png counterpart. + Fixes: #539137 + +2008-06-26 20:27:00 +0000 Thijs Vermeir + + plugins/elements/gstmultiqueue.*: revert extra-size-buffers stuff, caused some race conditions and extra-size-buffers... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + revert extra-size-buffers stuff, caused some race conditions + and extra-size-buffers is not used anymore. Docs needs some updates + +2008-06-26 12:52:41 +0000 Tim-Philipp Müller + + win32/common/: Update win32 files. + Original commit message from CVS: + * win32/common/config.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Update win32 files. + +2008-06-26 12:24:08 +0000 Tim-Philipp Müller + + gst/gstdebugutils.h: Add missing Since' markers to gtk-doc blurbs. + Original commit message from CVS: + * gst/gstdebugutils.h: (GstDebugGraphDetails), + (GST_DEBUG_BIN_TO_DOT_FILE): + Add missing Since' markers to gtk-doc blurbs. + +2008-06-26 11:59:40 +0000 Wim Taymans + + tests/check/libs/transform1.c: Add some more tests with switching caps in buffer_alloc. + Original commit message from CVS: + * tests/check/libs/transform1.c: (buffer_alloc_pt1), + (set_caps_pt1), (GST_START_TEST), (set_caps_pt2), (transform_ip_1), + (set_caps_1), (set_caps_ct1), (transform_ct1), + (transform_caps_ct1), (transform_size_ct1), (buffer_alloc_ct1), + (set_caps_ct2), (transform_ct2), (transform_caps_ct2), + (transform_size_ct2), (buffer_alloc_ct2): + Add some more tests with switching caps in buffer_alloc. + +2008-06-25 17:27:30 +0000 Wim Taymans + + tests/check/libs/: More tests, prepare for tests with switching caps in buffer_alloc. + Original commit message from CVS: + * tests/check/libs/test_transform.c: (gst_test_trans_base_init), + (gst_test_trans_class_init), (result_sink_chain), + (result_buffer_alloc), (gst_test_trans_new), (gst_test_trans_free), + (gst_test_trans_push), (gst_test_trans_pop): + * tests/check/libs/transform1.c: (buffer_alloc_pt1), + (set_caps_pt1), (GST_START_TEST), (set_caps_pt2), (transform_ip_1), + (set_caps_1), (set_caps_ct1), (transform_ct1), + (transform_caps_ct1), (transform_size_ct1), (buffer_alloc_ct1), + (set_caps_ct2), (transform_ct2), (transform_caps_ct2), + (transform_size_ct2), (buffer_alloc_ct2), + (gst_basetransform_suite): + More tests, prepare for tests with switching caps in buffer_alloc. + +2008-06-25 15:39:02 +0000 Thijs Vermeir + + plugins/elements/gstmultiqueue.*: Fix dead-lock in underrun_cb + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstmultiqueue.h: + Fix dead-lock in underrun_cb + +2008-06-25 14:49:08 +0000 Wim Taymans + + docs/design/part-states.txt: Fix device open/close docs. + Original commit message from CVS: + * docs/design/part-states.txt: + Fix device open/close docs. + +2008-06-25 14:47:11 +0000 Stefan Kost + + ChangeLog: Mention bugnumber for last commit. + Original commit message from CVS: + * ChangeLog: + Mention bugnumber for last commit. + +2008-06-25 14:44:52 +0000 Luc Pionchon + + docs/manual/manual.xml: - Reorganised the previous "introduction" bundle into Foreword, + Original commit message from CVS: + patch by: Luc Pionchon + * docs/manual/manual.xml: + - Reorganised the previous "introduction" bundle into Foreword, + Introduction, and About GStreamer. The two first are + docbook elements. The later is the first part of the book. + - added intro-gstreamer.xml (content partially from + intro-preface.xml) + - moved appendix-win32.xml into appendix-integration.xml + * docs/manual/intro-preface.xml: gstreamer section moved... + * docs/manual/intro-gstreamer.xml: ...here. new file. + * docs/manual/appendix-win32.xml: removed file. Content moved... + * docs/manual/appendix-integration.xml: ...here. + * docs/manual/highlevel-components.xml: section about GstEditor moved... + * docs/manual/appendix-checklist.xml: ...here. + +2008-06-25 14:32:53 +0000 Luc Pionchon + + docs/manual/: - Explicitely include glib.h. + Original commit message from CVS: + patch by: Luc Pionchon + * docs/manual/basics-helloworld.xml: + * docs/manual/hello-world.fig: + - Explicitely include glib.h. + - Do not use global variables. + - Use g_printerr() instead of g_print(). + - Minor formating/renaming to increase readibility. + - Renamed new_pad() to on_pad_added() + - Improved explenatory comments. + - renamed ogg parser to ogg demuxer + - Use "autoaudiosink" instead of "alsasink". + Fixes: #538619 + +2008-06-25 14:27:37 +0000 Stefan Kost + + ChangeLog: Remove cvs conflict marker. + Original commit message from CVS: + * ChangeLog: + Remove cvs conflict marker. + +2008-06-25 14:25:49 +0000 Stefan Kost + + docs/README: Document that for plgin-docs we extraxt he short-desc from the element details. + Original commit message from CVS: + * docs/README: + Document that for plgin-docs we extraxt he short-desc from the element + details. + * docs/design/part-states.txt: + Tell that devices should be closed in PAUSED -> READY. + * docs/manual/README: + Document how tests in the manual are handled. + * docs/manuals.mak: + Typo in comment. + +2008-06-25 11:50:06 +0000 Wim Taymans + + gst/gstbin.c: Only care about latency min and max when the sink is actually a live sink. + Original commit message from CVS: + * gst/gstbin.c: (bin_query_latency_fold): + Only care about latency min and max when the sink is actually a live + sink. + +2008-06-25 10:53:52 +0000 Wim Taymans + + docs/design/part-block.txt: Fix typo. + Original commit message from CVS: + * docs/design/part-block.txt: + Fix typo. + * docs/design/part-element-transform.txt: + Add notes about why transform needs to know input/output sizes. + Add some issues that need to be solved. + Add some more use cases. + * tests/check/libs/test_transform.c: (gst_test_trans_base_init), + (gst_test_trans_class_init), (result_sink_chain), + (result_buffer_alloc), (gst_test_trans_new), (gst_test_trans_free), + (gst_test_trans_push), (gst_test_trans_pop): + * tests/check/libs/transform1.c: (buffer_alloc_pt1), + (set_caps_pt1), (GST_START_TEST), (set_caps_pt2), (transform_ip_1), + (set_caps_1), (set_caps_ct1), (transform_ct1), + (transform_caps_ct1), (transform_size_ct1), (buffer_alloc_ct1), + (gst_basetransform_suite): + Add suport for different pad templates and buffer-alloc. + Add more checks for caps and buffer-alloc. + Add checks for proxy buffer alloc. + Add unit test for copy transform. + +2008-06-24 19:56:51 +0000 Luc Pionchon + + docs/manual/: Typo and formatting fixes (#538594). + Original commit message from CVS: + Patch by: Luc Pionchon + * docs/manual/appendix-integration.xml: + * docs/manual/appendix-licensing.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-pads.xml: + * docs/manual/highlevel-components.xml: + * docs/manual/highlevel-xml.xml: + * docs/manual/intro-basics.xml: + * docs/manual/intro-preface.xml: + Typo and formatting fixes (#538594). + +2008-06-24 07:49:36 +0000 Sebastian Dröge + + tests/check/gst/gstghostpad.c: Fix some memory leaks and uses of object instances that we don't actually own. + Original commit message from CVS: + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + Fix some memory leaks and uses of object instances that we don't + actually own. + +2008-06-22 19:19:35 +0000 Thijs Vermeir + + plugins/elements/gstmultiqueue.c: Add functionality to extra-size-buffers property. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + Add functionality to extra-size-buffers property. + +2008-06-22 14:35:13 +0000 Thijs Vermeir + + plugins/elements/gstmultiqueue.c: Don't update the cur_time on GST_CLOCK_TIME_NONE (#537804) and don't activate the p... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + Don't update the cur_time on GST_CLOCK_TIME_NONE (#537804) and don't + activate the pads if they are added in STATE_NULL. + +2008-06-21 21:20:13 +0000 Thijs Vermeir + + docs/libs/gstreamer-libs-sections.txt: Add new API to doc + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add new API to doc + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + API: gst_check_teardown_pad_by_name + +2008-06-21 19:48:53 +0000 Thijs Vermeir + + libs/gst/check/gstcheck.*: Also setup request pads and allow setup pads by name (#537812) + Original commit message from CVS: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + Also setup request pads and allow setup pads by name (#537812) + API: gst_check_setup_src_pad_by_name + API: gst_check_setup_sink_pad_by_name + +2008-06-20 21:08:47 +0000 Thomas Vander Stichele + + tests/check/: Use HAVE_VALGRIND_H some more. + Original commit message from CVS: + * tests/check/gst/gstbuffer.c: + * tests/check/pipelines/parse-launch.c: + Use HAVE_VALGRIND_H some more. + +2008-06-20 16:29:23 +0000 Thomas Vander Stichele + + scripts/cvs-update.sh: Pass arguments to make. + Original commit message from CVS: + * scripts/cvs-update.sh: + Pass arguments to make. + Run autoregen.sh if Makefile is not there. + +2008-06-20 15:54:43 +0000 Thomas Vander Stichele + + Don't assume that exists just because the binary is there. + Original commit message from CVS: + * configure.ac: + * gst/gstinfo.c: + Don't assume that exists just because + the binary is there. + +2008-06-20 12:06:54 +0000 Wim Taymans + + tests/check/: Add some test basetransform element and the beginnings of various unit tests for it. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/test_transform.c: (gst_test_trans_base_init), + (gst_test_trans_class_init), (gst_test_trans_init), + (gst_test_trans_set_data), (result_sink_chain), + (gst_test_trans_new), (gst_test_trans_free), (gst_test_trans_push), + (gst_test_trans_pop): + * tests/check/libs/transform1.c: (GST_START_TEST), + (transform_ip_1), (set_caps_1), (gst_basetransform_suite): + Add some test basetransform element and the beginnings of various + unit tests for it. + +2008-06-20 11:24:03 +0000 Wim Taymans + + libs/gst/base/gsttypefindhelper.c: Increase code readability. + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (helper_find_peek): + Increase code readability. + Don't try to compare buffer offsets when ther are invalid. + +2008-06-20 11:07:05 +0000 Tim-Philipp Müller + + docs/design/Makefile.am: Dist some more design docs. + Original commit message from CVS: + * docs/design/Makefile.am: + Dist some more design docs. + * docs/random/moving-plugins: + Small addition: good plugins mustn't have functional code + within assertion macros. + +2008-06-20 10:32:34 +0000 Wim Taymans + + docs/design/draft-framestep.txt: Some ideas about a framestep API + Original commit message from CVS: + * docs/design/draft-framestep.txt: + Some ideas about a framestep API + * docs/design/part-element-transform.txt: + Start design and use cases for basetransform in order to get it + fixed soon. + +2008-06-20 10:20:08 +0000 Tim-Philipp Müller + + gst/gstbus.c: Make it known that gst_bus_poll() is pure evil (fixes #538810). + Original commit message from CVS: + * gst/gstbus.c: + Make it known that gst_bus_poll() is pure evil (fixes #538810). + +2008-06-20 10:14:54 +0000 Stefan Kost + + plugins/elements/: Remove short_description. Add basic docs for gsttypefindelement. + Original commit message from CVS: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + Remove short_description. Add basic docs for gsttypefindelement. + Simplify markup for fakesrc/fdsrc. + +2008-06-20 10:07:28 +0000 Wim Taymans + + plugins/elements/gstfdsrc.c: Added Since doc. + Original commit message from CVS: + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init): + Added Since doc. + +2008-06-20 10:02:14 +0000 joel larsson + + Add timeout property like udpsrc. Fixes #538628. + Original commit message from CVS: + Patch by: joel larsson + * docs/plugins/gstreamer-plugins.args: + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init), + (gst_fd_src_init), (gst_fd_src_update_fd), + (gst_fd_src_set_property), (gst_fd_src_get_property), + (gst_fd_src_create): + * plugins/elements/gstfdsrc.h: + Add timeout property like udpsrc. Fixes #538628. + Add some more docs and example pipelines. + +2008-06-20 08:54:45 +0000 Wim Taymans + + Add method to allow sinks to specify additional delay between the sync times and the actual rendering of the data. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_query_latency), (gst_base_sink_set_render_delay), + (gst_base_sink_get_render_delay), (gst_base_sink_wait_eos), + (gst_base_sink_do_sync): + * libs/gst/base/gstbasesink.h: + * win32/common/libgstbase.def: + Add method to allow sinks to specify additional delay between the sync + times and the actual rendering of the data. + API: gst_base_sink_set_render_delay() + API: gst_base_sink_get_render_delay() + +2008-06-20 08:45:01 +0000 Jan Schmidt + + configure.ac: Bump version number back to dev -> 0.10.20.1 + Original commit message from CVS: + * configure.ac: + Bump version number back to dev -> 0.10.20.1 + +2008-06-20 08:39:54 +0000 Sebastian Dröge + + API: Add GST_TAG_ATTACHMENT for generic file attachments to streams. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + API: Add GST_TAG_ATTACHMENT for generic file attachments to streams. + Fixes bug #538568. + +2008-06-20 08:36:46 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Revert one change, that make ret value possible uninitialized. + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + Revert one change, that make ret value possible uninitialized. + +2008-06-20 08:32:36 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Use freeze/thaw notify to sync notify emission a bit (its also more efficient). ... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + Use freeze/thaw notify to sync notify emission a bit (its also more + efficient). Move debug output to LOG (is called a lot in a loop). + Always unset g_values if the have been initialized. + +2008-06-20 08:28:46 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: If we have not seen a buffer before EOS, use the segment values to report the current po... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_wait_eos), (gst_base_sink_event): + If we have not seen a buffer before EOS, use the segment values to + report the current position instead of invalid positions. + +2008-06-20 08:21:48 +0000 Stefan Kost + + Ignore more. + Original commit message from CVS: + * docs/plugins/tmpl/.cvsignore: + * tests/check/gst/.cvsignore: + Ignore more. + +2008-06-20 08:17:08 +0000 Stefan Kost + + Rewrite handling of default values. Fix overflow with unsigned types in linear interpolation. Remove now obsolete _fi... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + * tests/check/libs/controller.c: + Rewrite handling of default values. Fix overflow with unsigned types + in linear interpolation. Remove now obsolete _first_value() function. + Add more tests. Fixes #538201. + +2008-06-20 08:14:23 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Add debug info. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_class_init), (gst_base_transform_init), + (gst_base_transform_transform_caps), + (gst_base_transform_prepare_output_buffer): + Add debug info. + When a buffer is writable, its metadata is also writable so we don't + need to subbuffer (which then makes the buffer not-writable anymore). + +=== release 0.10.20 === + +2008-06-18 10:58:35 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.10.20 + Original commit message from CVS: + Release 0.10.20 + +2008-06-18 10:56:18 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-06-11 21:14:17 +0000 Jan Schmidt + + 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:07:31 +0000 David Schleef + + Rename DATADIR to GST_DATADIR to avoid build problems + Original commit message from CVS: + * configure.ac: + * gst/gstpreset.c: + Rename DATADIR to GST_DATADIR to avoid build problems + on win32. Patch By: David Schleef + Fixes: #536857 + +2008-06-05 10:13:45 +0000 Sebastian Dröge + + configure.ac: Explicitely link with -ldl if dladdr() is found there. Before it was implicitely linked by the gmodule ... + Original commit message from CVS: + * configure.ac: + Explicitely link with -ldl if dladdr() is found there. Before it was + implicitely linked by the gmodule pkgconfig file but in glib 2.17.0 + -ldl has moved from Libs to Libs.private. Fixes bug #536744. + +2008-06-05 09:42:31 +0000 Jan Schmidt + + * ChangeLog: + Put pre-release chaneglog entry where it actually happened + Original commit message from CVS: + Put pre-release chaneglog entry where it actually happened + +2008-06-05 09:41:25 +0000 Jan Schmidt + + configure.ac: 0.10.19.2 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.19.2 pre-release + +2008-06-05 08:55:41 +0000 Tim-Philipp Müller + + gst/gsterror.c: Fix typo (spotted by Fabricio Godoy, #536723). + Original commit message from CVS: + * gst/gsterror.c: (_gst_stream_errors_init): + Fix typo (spotted by Fabricio Godoy, #536723). + +2008-06-04 11:47:16 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Add some debug. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_async_enabled), + (gst_base_sink_set_ts_offset), (gst_base_sink_perform_qos): + Add some debug. + Make sure we don't generate invalid QoS messages. + +2008-06-04 11:31:15 +0000 Wim Taymans + + gst/gstevent.c: Add some assert and docs for invalid input to the qos function. + Original commit message from CVS: + * gst/gstevent.c: (gst_event_new_qos): + Add some assert and docs for invalid input to the qos function. + +2008-05-30 15:48:52 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: The reported position must always be smaller than the last seen timestamps (or timestamp... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_get_position): + The reported position must always be smaller than the last seen + timestamps (or timestamp + duration for reverse). + +2008-05-30 07:36:17 +0000 Rob Bradford + + gst/gstregistry.c: Don't recurse into .debug directories as some distros install the debugging symbols next to the pl... + Original commit message from CVS: + Patch by: Rob Bradford + * gst/gstregistry.c: (gst_registry_scan_path_level): + Don't recurse into .debug directories as some distros install + the debugging symbols next to the plugins in .debug directories + and dlopen() crashes on them sometimes. Fixes bug #508070. + Add FIXME for 0.11 to not recurse into directories at all because + it's very inconsistent to the behaviour of other PATH environment + variables. + +2008-05-29 16:34:22 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Fix position query range checks in reverse playback. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_get_position_last), (gst_base_sink_get_position): + Fix position query range checks in reverse playback. + +2008-05-29 07:19:47 +0000 Sebastian Dröge + + gst/gstelement.*: Deprecated gst_element_get_pad() as it can't be used sanely. It's not clear of the reference to the... + Original commit message from CVS: + * gst/gstelement.c: + * gst/gstelement.h: + Deprecated gst_element_get_pad() as it can't be used sanely. It's not + clear of the reference to the resulting pad must be released later + or not, resulting in possible leaks. Fixes bug #533865. + +2008-05-28 16:46:07 +0000 José Alburquerque + + gst/gstelementfactory.c: Small doc fix. Fixes #535285. + Original commit message from CVS: + Patch by: José Alburquerque + * gst/gstelementfactory.c: + Small doc fix. Fixes #535285. + +2008-05-28 13:48:17 +0000 Bjarne Rosengren + + libs/gst/base/gstbasesrc.c: Make sending an EOS event to the basesrc non-blocking even if the implementation does blo... + Original commit message from CVS: + Based on patch by: Bjarne Rosengren + * libs/gst/base/gstbasesrc.c: (gst_base_src_send_event), + (gst_base_src_get_range), (gst_base_src_pad_get_range), + (gst_base_src_loop), (gst_base_src_set_flushing), + (gst_base_src_change_state): + Make sending an EOS event to the basesrc non-blocking even if the + implementation does blocking waits in the create function. This is done + by unlocking the create function when EOS is sent. + Fixes #535218. + +2008-05-28 10:44:15 +0000 Sebastian Dröge + + tools/gst-inspect.c: If possible print the element type of GValueArray properties. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + If possible print the element type of GValueArray properties. + +2008-05-28 07:47:22 +0000 Sebastian Dröge + + gst/gstiterator.c: Remove an unused field from the private GstListIterator struct. + Original commit message from CVS: + * gst/gstiterator.c: + Remove an unused field from the private GstListIterator struct. + +2008-05-27 20:19:17 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Add parameter guards. + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + Add parameter guards. + +2008-05-27 19:47:49 +0000 Stefan Kost + + tests/check/gst/gstpipeline.c: Revert test change and add comment why it should not work. + Original commit message from CVS: + * tests/check/gst/gstpipeline.c: + Revert test change and add comment why it should not work. + +2008-05-27 18:31:39 +0000 Stefan Kost + + tests/check/gst/gstpipeline.c: Extending the test a little to verify that we also get the NULL state- change message. + Original commit message from CVS: + * tests/check/gst/gstpipeline.c: + Extending the test a little to verify that we also get the NULL state- + change message. + +2008-05-27 16:37:32 +0000 Tim-Philipp Müller + + gst/gstpreset.c: Add Since: markers to docs blurbs. + Original commit message from CVS: + * gst/gstpreset.c: (gst_preset_default_get_meta), + (gst_preset_get_preset_names), (gst_preset_get_property_names), + (gst_preset_load_preset), (gst_preset_save_preset), + (gst_preset_rename_preset), (gst_preset_delete_preset), + (gst_preset_set_meta): + Add Since: markers to docs blurbs. + * win32/common/libgstreamer.def: + Add recently-added API. + +2008-05-27 15:11:35 +0000 Stefan Kost + + configure.ac: Add DATADIR for storing presets. + Original commit message from CVS: + Patch by: Stefan Kost + * configure.ac: + Add DATADIR for storing presets. + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + Add GstPreset to docs. + * gst/Makefile.am: + * gst/gst.h: + * gst/gstpreset.c: (preset_get_paths), (preset_skip_property), + (preset_open_and_parse_header), (preset_parse_version), + (preset_merge), (preset_get_keyfile), + (gst_preset_default_get_preset_names), + (gst_preset_default_get_property_names), + (gst_preset_default_load_preset), + (gst_preset_default_save_presets_file), + (gst_preset_default_save_preset), + (gst_preset_default_rename_preset), + (gst_preset_default_delete_preset), (gst_preset_default_set_meta), + (gst_preset_default_get_meta), (gst_preset_default_randomize), + (gst_preset_default_reset), (gst_preset_get_preset_names), + (gst_preset_get_property_names), (gst_preset_load_preset), + (gst_preset_save_preset), (gst_preset_rename_preset), + (gst_preset_delete_preset), (gst_preset_set_meta), + (gst_preset_get_meta), (gst_preset_class_init), + (gst_preset_base_init), (gst_preset_get_type): + * gst/gstpreset.h: + Add GstPreset to core. Fixes #396779 + * tests/check/Makefile.am: + * tests/check/gst/gstpreset.c: (gst_preset_test_get_property), + (gst_preset_test_set_property), (gst_preset_test_class_init), + (gst_preset_test_base_init), (gst_preset_test_get_type), + (gst_preset_test_plugin_init), (GST_START_TEST), + (remove_preset_file), (test_setup), (test_teardown), + (gst_preset_suite): + Add GstPreset unit tests. + +2008-05-27 10:59:38 +0000 Wim Taymans + + gst/gstpad.c: The default event function on a sinkpad should return TRUE when there are no internal links but should ... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_event_default_dispatch): + The default event function on a sinkpad should return TRUE when + there are no internal links but should collect the return values from + the internal links otherwise. + +2008-05-27 10:57:11 +0000 Wim Taymans + + plugins/elements/gsttypefindelement.c: Use faster and safer _pad_push_event(). + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_src_event), + (gst_type_find_element_handle_event): + Use faster and safer _pad_push_event(). + +2008-05-27 10:50:49 +0000 Tim-Philipp Müller + + API: add gst_bin_find_unlinked_pad() + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: (element_find_unlinked_pad), + (gst_bin_find_unlinked_pad), (gst_bin_find_unconnected_pad), + * gst/gstutils.h: + API: add gst_bin_find_unlinked_pad() + API: deprecate gst_bin_find_unconnected_pad() (#401456) + +2008-05-26 10:07:09 +0000 Peter Kjellerstedt + + gst/: Fixed a bunch of typos. + Original commit message from CVS: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gsttask.c: + * gst/gsttask.h: + Fixed a bunch of typos. + +2008-05-25 16:34:32 +0000 Tim-Philipp Müller + + gst/: 'unconnected pad' -> 'unlinked pad' for consistency (#401456). + Original commit message from CVS: + * gst/gstpad.h: + * gst/gstutils.c: (gst_element_unlink), (element_find_unlinked_pad), + (gst_bin_find_unconnected_pad), (gst_parse_bin_from_description), + (gst_parse_bin_from_description_full): + * gst/gstutils.h: + 'unconnected pad' -> 'unlinked pad' for consistency (#401456). + +2008-05-25 16:13:38 +0000 Tim-Philipp Müller + + docs/pwg/advanced-tagging.xml: Small docs update, can't be bothered to rewrite the nonsensical examples right now. + Original commit message from CVS: + * docs/pwg/advanced-tagging.xml: + Small docs update, can't be bothered to rewrite the nonsensical + examples right now. + +2008-05-25 14:44:44 +0000 Tim-Philipp Müller + + gst/gstevent.h: Clarify docs for GST_SEEK_TYPE_CUR (#534505). + Original commit message from CVS: + * gst/gstevent.h: + Clarify docs for GST_SEEK_TYPE_CUR (#534505). + +2008-05-25 14:13:22 +0000 Tim-Philipp Müller + + gst/parse/grammar.y: Remove unneeded casts. + Original commit message from CVS: + * gst/parse/grammar.y: + Remove unneeded casts. + +2008-05-25 13:56:38 +0000 Tim-Philipp Müller + + Get all missing elements from a parse launch string if possible (ie. if the FATAL_ERRORS flag has been specified). Fi... + Original commit message from CVS: + * gst/parse/grammar.y: + * tests/check/pipelines/parse-launch.c: + Get all missing elements from a parse launch string if possible + (ie. if the FATAL_ERRORS flag has been specified). Fixes #528178. + +2008-05-24 16:38:15 +0000 Tim-Philipp Müller + + tests/check/: Add some unit tests for the new gst_parse_launch*_full() API. (Exposes a previously-existing memory lea... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/pipelines/parse-launch.c: + Add some unit tests for the new gst_parse_launch*_full() API. + (Exposes a previously-existing memory leak in the error code + path, so adding to VALGRIND_TO_FIX for now). + +2008-05-24 15:33:53 +0000 Tim-Philipp Müller + + API: gst_parse_launch_full() + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: (init_post): + * gst/gst_private.h: (_GstParseContext): + * gst/gstparse.c: (gst_parse_error_quark), (gst_parse_context_new), + (gst_parse_context_free), (gst_parse_context_get_missing_elements), + (gst_parse_launchv), (gst_parse_launchv_full), (gst_parse_launch), + (gst_parse_launch_full): + * gst/gstparse.h: (GST_PARSE_FLAG_NONE), (GST_PARSE_FLAG_FATAL_ERRORS), + (GstParseFlags), (GstParseContext): + * gst/gstutils.c: (gst_parse_bin_from_description), + (gst_parse_bin_from_description_full): + * gst/gstutils.h: + * gst/parse/grammar.y: + * gst/parse/types.h: + * win32/common/libgstreamer.def: + Add new gst_parse_*_full API (#528178): + API: gst_parse_launch_full() + API: gst_parse_launchv_full() + API: gst_parse_bin_from_description_full() + API: gst_parse_context_new() + API: gst_parse_context_free() + API: gst_parse_context_get_missing_elements() + +2008-05-23 06:50:10 +0000 Suresh Kumar P + + docs/faq/gst-uninstalled: Also support ffmpeg in gst-uninstalled. + Original commit message from CVS: + patch by: Suresh Kumar P + * docs/faq/gst-uninstalled: + Also support ffmpeg in gst-uninstalled. + +2008-05-22 20:29:20 +0000 Sebastian Dröge + + configure.ac: After discussion on IRC use the binary registry as default but allow to disable it with --disable-binar... + Original commit message from CVS: + * configure.ac: + After discussion on IRC use the binary registry as default + but allow to disable it with --disable-binary-registry. + * win32/common/libgstreamer.def: + Add the two new symbols for the binary registry. + +2008-05-22 15:38:54 +0000 Tim-Philipp Müller + + gst/: More guards against bad input; typo fix; some minor clean-ups. + Original commit message from CVS: + * gst/gstparse.c: (_gst_parse_escape), (gst_parse_launchv): + * gst/gstutils.c: (gst_parse_bin_from_description): + * gst/parse/grammar.y: (graph): + More guards against bad input; typo fix; some minor clean-ups. + +2008-05-22 08:33:27 +0000 Sjoerd Simons + + libs/gst/base/gstbasesink.c: If nothing else can be used, use the last buffer's start time as the segment's last stop... + Original commit message from CVS: + Patch by: Sjoerd Simons + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + If nothing else can be used, use the last buffer's start time as + the segment's last stop. Fixes bug #534258. + +2008-05-21 18:33:08 +0000 Tim-Philipp Müller + + gst/gstpad.c: Move size sanity check to the right place: downstream may return a buffer with a smaller size if the bu... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer_full): + Move size sanity check to the right place: downstream may return + a buffer with a smaller size if the buffer caps are different than + the requested ones, as may happen when doing reverse negotiation. + +2008-05-21 16:06:53 +0000 Wim Taymans + + plugins/elements/: Small cleanups. Add note adbout g_fopen() on windows and why we don't use it yet. + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_set_location), + (gst_file_sink_render): + * plugins/elements/gstfilesrc.c: (gst_file_src_set_location), + (gst_file_src_start): + Small cleanups. Add note adbout g_fopen() on windows and why we don't + use it yet. + +2008-05-21 15:57:52 +0000 Wim Taymans + + Don't use gst_element_get_pad(). + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_load_and_link): + * gst/gstutils.c: (gst_element_link_pads), + (gst_element_unlink_pads): + * libs/gst/check/gstcheck.c: (gst_check_setup_src_pad), + (gst_check_teardown_src_pad), (gst_check_setup_sink_pad), + (gst_check_teardown_sink_pad), + (gst_check_element_push_buffer_list): + * tests/check/elements/fakesink.c: (GST_START_TEST): + * tests/check/elements/filesink.c: + * tests/check/elements/filesrc.c: (GST_START_TEST): + * tests/check/elements/multiqueue.c: (setup_multiqueue), + (mq_sinkpad_to_srcpad): + * tests/check/elements/tee.c: (GST_START_TEST): + * tests/check/generic/sinks.c: (GST_START_TEST): + * tests/check/gst/gstbin.c: (GST_START_TEST): + * tests/check/gst/gstevent.c: (GST_START_TEST): + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + * tests/check/gst/gstpipeline.c: (GST_START_TEST): + * tests/check/gst/gstquery.c: (GST_START_TEST): + * tests/check/gst/gstutils.c: (GST_START_TEST): + * tests/check/libs/basesrc.c: (GST_START_TEST): + * tests/check/pipelines/parse-launch.c: (run_delayed_test), + (gst_parse_test_element_change_state): + Don't use gst_element_get_pad(). + +2008-05-21 15:54:28 +0000 Felipe Contreras + + 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 15:51:25 +0000 Wim Taymans + + docs/manual/: Avoid using a bad function in the example code. + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-pads.xml: + * docs/manual/highlevel-components.xml: + Avoid using a bad function in the example code. + +2008-05-21 15:49:21 +0000 Wim Taymans + + gst/gstclock.c: Fix debug of the new clock rate. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_set_calibration): + Fix debug of the new clock rate. + +2008-05-21 11:10:32 +0000 Sebastian Dröge + + win32/common/libgstbase.def: Add gst_base_sink_wait_clock() to the exported symbols. + Original commit message from CVS: + * win32/common/libgstbase.def: + Add gst_base_sink_wait_clock() to the exported symbols. + +2008-05-20 08:28:24 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasetransform.c: Unref events that the GstBaseTransform::event vfunc didn't want to have forwarded b... + Original commit message from CVS: + Patch by: Tim-Philipp Müller + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_event): + Unref events that the GstBaseTransform::event vfunc didn't want to + have forwarded by the base class. Closes a leak in identity. + Fixes bug #446763. + +2008-05-19 16:36:51 +0000 Wim Taymans + + Expose a method that was previously used internally to synchronize against the clock because it can be useful for sub... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_wait_clock): + * libs/gst/base/gstbasesink.h: + Expose a method that was previously used internally to synchronize + against the clock because it can be useful for subclasses too. + GstBaseSink::gst_base_sink_wait_clock() + +2008-05-19 11:59:34 +0000 Tim-Philipp Müller + + gst/gstpad.c: Add sanity check to make sure we don't get smaller buffers than requested (and fallback to normal buffe... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_buffer_alloc_unchecked): + Add sanity check to make sure we don't get smaller buffers + than requested (and fallback to normal buffer alloc if we do). + +2008-05-19 11:11:49 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Refactor adjusting the running_time with latency and offset into a separate method. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_adjust_time), + (gst_base_sink_wait_clock), (gst_base_sink_wait_eos), + (gst_base_sink_do_sync), (gst_base_sink_chain_unlocked): + Refactor adjusting the running_time with latency and offset into a + separate method. + When doing clipping, we still want to use the subclass get_times method, + just in case the DURATION or TIMESTAMP are not set. + +2008-05-19 10:46:44 +0000 Tim-Philipp Müller + + API: add gst_type_find_suggest_simple(), #533740. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttypefind.c: (gst_type_find_suggest_simple): + * gst/gsttypefind.h: + * win32/common/libgstreamer.def: + API: add gst_type_find_suggest_simple(), #533740. + +2008-05-19 10:29:57 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.c: Use right error code when typefinding fails, so we can use the default (translated) error... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_start): + Use right error code when typefinding fails, so we can use + the default (translated) error messages. + +2008-05-19 10:03:09 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: When the subclass did not set caps on outgoing buffers, configure the caps we negotiated ... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_range), + (gst_base_src_start): + When the subclass did not set caps on outgoing buffers, configure the + caps we negotiated on the source pad. + When the typefind helper does not find caps, error out properly instead + of doing things with NULL caps. + +2008-05-18 18:53:50 +0000 Tim-Philipp Müller + + gst/gsttypefind.h: Tabs to spaces, oh yes! + Original commit message from CVS: + * gst/gsttypefind.h: + Tabs to spaces, oh yes! + +2008-05-18 12:13:42 +0000 Tim-Philipp Müller + + * ChangeLog: + ChangeLog surgery + Original commit message from CVS: + ChangeLog surgery + +2008-05-18 11:52:39 +0000 Tim-Philipp Müller + + tests/check/gst/gstcaps.c: Add David's and Benjamin's tests for array subtraction to the unit test suite, which sugge... + Original commit message from CVS: + * tests/check/gst/gstcaps.c: (test_intersect2), (gst_caps_suite): + Add David's and Benjamin's tests for array subtraction to the + unit test suite, which suggests that #147931 is fixed these days. + +2008-05-18 11:35:43 +0000 Tim-Philipp Müller + + gst/gstevent.c: Document that gst_event_new_tag() and gst_event_new_navigation() take ownership of the taglist/struct... + Original commit message from CVS: + * gst/gstevent.c: + Document that gst_event_new_tag() and gst_event_new_navigation() + take ownership of the taglist/structure passed to them. (#533635). + +2008-05-17 17:20:51 +0000 Jan Schmidt + + docs/Makefile.am: Don't descend into the plugins dir if plugin docs building is disabled. + Original commit message from CVS: + * docs/Makefile.am: + Don't descend into the plugins dir if plugin docs building + is disabled. + * docs/README: + Add a note about the new type:GTypeName syntax for the plugin + documentation .types file. + +2008-05-17 13:54:52 +0000 Sebastian Dröge + + gst/gstmessage.*: Mark the debug string parameters as const. Fixes bug #533490. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_info): + * gst/gstmessage.h: + Mark the debug string parameters as const. Fixes bug #533490. + +2008-05-16 21:09:45 +0000 Sebastian Dröge + + libs/gst/base/gsttypefindhelper.c: Sort buffer cache list by end offsets. This makes sure that we don't stop to searc... + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (helper_find_peek): + Sort buffer cache list by end offsets. This makes sure that we don't + stop to search for a cached buffer that contains the requested data + too early. + Also read a minimum of 4k bytes instead of 512 bytes as this is a bit + more efficient. Fixes bug #459862. + +2008-05-14 18:17:34 +0000 Stefan Kost + + gst/gstinfo.c: Explain why we copy the list. + Original commit message from CVS: + * gst/gstinfo.c: + Explain why we copy the list. + * gst/gstpipeline.c: + Improve docs. + * gst/gstutils.c: + Add one debug-log statement to help tracing probelms with linking pads. + +2008-05-14 18:09:01 +0000 Stefan Kost + + tests/check/gst/gstinfo.c: Add a test for removing the default log handler. Seems to fail under windows. + Original commit message from CVS: + * tests/check/gst/gstinfo.c: + Add a test for removing the default log handler. Seems to fail under + windows. + +2008-05-14 13:52:59 +0000 Wim Taymans + + gst/gstpad.c: Release pad lock before calling out to avoid a possible deadlock. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_peer_accept_caps): + Release pad lock before calling out to avoid a possible deadlock. + +2008-05-14 10:22:17 +0000 Wim Taymans + + gst/parse/grammar.y: Remove unneeded value unset. + Original commit message from CVS: + * gst/parse/grammar.y: + Remove unneeded value unset. + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Add unit test for de/serialization of caps. + +2008-05-13 12:54:00 +0000 Sebastian Dröge + + plugins/elements/: Use custom marshalers that take GstMiniObject as first parameter. + Original commit message from CVS: + * plugins/elements/gstfakesink.c: + (marshal_VOID__MINIOBJECT_OBJECT), (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (marshal_VOID__MINIOBJECT_OBJECT), + (gst_fake_src_class_init): + Use custom marshalers that take GstMiniObject as first parameter. + Using OBJECT as parameter while a GstMiniObject is given will lead + to assertions if built with G_ENABLE_DEBUG. Fixes bug #525532. + +2008-05-13 12:38:31 +0000 Sebastian Dröge + + plugins/elements/gsttypefindelement.c: Clean up on FLUSH_STOP and not FLUSH_START. Forward both events immediately. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event), + (gst_type_find_element_send_cached_events), + (gst_type_find_element_change_state): + Clean up on FLUSH_STOP and not FLUSH_START. Forward both events + immediately. + +2008-05-13 11:45:24 +0000 Sebastian Dröge + + plugins/elements/gsttypefindelement.c: Forward FLUSH_START events immediately and clean up instead of caching them. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_handle_src_query), (stop_typefinding), + (gst_type_find_element_handle_event), + (gst_type_find_element_send_cached_events), + (gst_type_find_element_change_state): + Forward FLUSH_START events immediately and clean up instead of + caching them. + +2008-05-13 07:11:05 +0000 Sjoerd Simons + + libs/gst/base/gstbasetransform.c: Check the caps of the buffer returned by gst_pad_alloc_buffer() and fall back to de... + Original commit message from CVS: + Patch by: Sjoerd Simons + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Check the caps of the buffer returned by gst_pad_alloc_buffer() and + fall back to default negotiation in the chain function if the caps + are different from what was requested. Fixes bug #526768. + +2008-05-09 20:48:24 +0000 Tim-Philipp Müller + + No, let's not use g_slice_{dup|copy} here, since they only exist since GLib 2.14 and we still depend only on >= 2.12.... + Original commit message from CVS: + * gst/gstsegment.c: + * tests/check/gst/gstsegment.c: + No, let's not use g_slice_{dup|copy} here, since they only exist + since GLib 2.14 and we still depend only on >= 2.12. Also add + unit test for gst_segment_copy(). + +2008-05-09 18:25:44 +0000 Tim-Philipp Müller + + gst/gstutils.h: Try to fix 'dereferencing type-punned pointer will break strict aliasing rules' warnings with C++ com... + Original commit message from CVS: + * gst/gstutils.h: (GST_BOILERPLATE_FULL): + Try to fix 'dereferencing type-punned pointer will break strict + aliasing rules' warnings with C++ compilers and GLib >= 2.14.0: GLib + changed the default GType typedef from gulong to gsize at some point, + but kept GType typedef'ed to gulong for C++ for ABI reasons; the + g_once_* functions all take a gsize * though, so work around the type + mismatch for C++ by doing everything in gsize and casting to GType + later. + +2008-05-09 14:02:53 +0000 Jan Schmidt + + plugins/elements/gstmultiqueue.c: Add documentation for the signals to push our core plugin docs coverage back up to ... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + Add documentation for the signals to push our core plugin docs + coverage back up to 100%. + +2008-05-08 14:23:16 +0000 Ole André Vadla Ravnås + + gst/gstinfo.h (GST_FUNCTION): Reverted GST_FUNCTION to the old version as we don't want the full signature in C++ cod... + Original commit message from CVS: + * gst/gstinfo.h (GST_FUNCTION): + Reverted GST_FUNCTION to the old version as we don't want the + full signature in C++ code. Also added support for MSVC. + +2008-05-08 11:37:03 +0000 Sebastian Dröge + + gst/gstutils.h: Intern the type name string, similar to what G_DEFINE_TYPE does. + Original commit message from CVS: + * gst/gstutils.h: + Intern the type name string, similar to what G_DEFINE_TYPE does. + +2008-05-08 11:27:56 +0000 Sebastian Dröge + + gst/gstutils.h: Make GST_BOILERPLATE thread-safe if building with GLib 2.14 or newer. + Original commit message from CVS: + * gst/gstutils.h: + Make GST_BOILERPLATE thread-safe if building with GLib 2.14 or newer. + +2008-05-08 05:55:34 +0000 Sjoerd Simons + + libs/gst/base/gstbasetransform.c: Don't passthrough buffer allocation too easily if the caps change. + Original commit message from CVS: + Based on a patch by: Sjoerd Simons + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Don't passthrough buffer allocation too easily if the caps change. + This breaks when working in passthrough mode and upstream changes + it's caps. Fixes bug #526768. + +2008-05-07 19:24:44 +0000 Ole André Vadla Ravnås + + gst/gstinfo.c (gst_debug_log_valist): Improved the __FILE__ part of debug output for MSVC. + Original commit message from CVS: + * gst/gstinfo.c (gst_debug_log_valist): + Improved the __FILE__ part of debug output for MSVC. + +2008-05-07 19:15:14 +0000 Ole André Vadla Ravnås + + libs/gst/base/gstbasesrc.c (gst_base_src_default_query): Declaration after statement fix for compilers like MSVC. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c (gst_base_src_default_query): + Declaration after statement fix for compilers like MSVC. + +2008-05-07 19:09:08 +0000 Ole André Vadla Ravnås + + 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 18:51:22 +0000 Ole André Vadla Ravnås + + gst/gstinfo.h (GST_FUNCTION): Made GST_FUNCTION an alias for G_STRFUNC to avoid duplication. + Original commit message from CVS: + * gst/gstinfo.h (GST_FUNCTION): + Made GST_FUNCTION an alias for G_STRFUNC to avoid duplication. + +2008-05-07 09:47:27 +0000 Wim Taymans + + libs/gst/base/gstadapter.c: Small code cleanup. + Original commit message from CVS: + * libs/gst/base/gstadapter.c: (gst_adapter_available_fast): + Small code cleanup. + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency), + (gst_base_sink_set_flushing): + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek): + Fix some comments. + +2008-05-07 09:34:58 +0000 Wim Taymans + + plugins/elements/gstfakesrc.*: Added format property to control the format of the newsegment events. + Original commit message from CVS: + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_init), (gst_fake_src_set_property), + (gst_fake_src_get_property), (gst_fake_src_start): + * plugins/elements/gstfakesrc.h: + Added format property to control the format of the newsegment events. + API: GstFakeSrc:format + +2008-05-06 08:45:07 +0000 Sebastian Dröge + + win32/common/libgstreamer.def: Add gst_pad_has_name() to the exported symbols. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add gst_pad_has_name() to the exported symbols. + +2008-05-06 08:43:57 +0000 Sebastian Dröge + + Don't allow negative sizes when allocating new buffers. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer_full): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer): + Don't allow negative sizes when allocating new buffers. + Fixes bug #461253. + +2008-05-05 16:47:29 +0000 Sjoerd Simons + + gst/gstbus.c: Don't print a warning if the queue is empty when we try to pop here. That could happen if another threa... + Original commit message from CVS: + Patch by: Sjoerd Simons + * gst/gstbus.c: (gst_bus_source_dispatch): + Don't print a warning if the queue is empty when we try to pop + here. That could happen if another thread or callback set the + bus to flushing between the source's check/prepare and the + dispatch being called (#531538). + +2008-05-05 16:25:23 +0000 Tim-Philipp Müller + + plugins/elements/gstmultiqueue.c: Small docs fix. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + Small docs fix. + +2008-05-05 15:50:36 +0000 Sebastian Dröge + + tests/check/gst/gstvalue.c: Add unit test for deserializing uint64s and check some really large numbers in the int64 ... + Original commit message from CVS: + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Add unit test for deserializing uint64s and check some really large + numbers in the int64 test. + +2008-05-04 19:07:21 +0000 Sebastian Dröge + + tools/gst-inspect.c: Use "%s" as format string instead of printing strings directly. + Original commit message from CVS: + * tools/gst-inspect.c: (n_print), (print_hierarchy), + (print_interfaces), (print_element_properties_info), + (print_signal_info): + Use "%s" as format string instead of printing strings directly. + +2008-05-04 14:25:07 +0000 Sebastian Dröge + + gst/gstclock.c: Make some checks actually useful. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_set_calibration): + Make some checks actually useful. + * gst/gstregistrybinary.c: (gst_registry_binary_load_plugin): + Remove some unused code. Unsigned integers tend to be >= 0. + +2008-05-03 19:23:43 +0000 Tim-Philipp Müller + + gst/gstminiobject.c: Fix 'Since:' version in gst_value_dup_mini_object() docs blurb: this function was not in the uns... + Original commit message from CVS: + * gst/gstminiobject.c: (gst_value_get_mini_object): + Fix 'Since:' version in gst_value_dup_mini_object() docs blurb: this + function was not in the unscheduled 0.10.19 release. + +2008-05-03 19:13:47 +0000 Tim-Philipp Müller + + gst/gstregistry.c: Only print one log message per non-plugin file. + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_scan_path_level): + Only print one log message per non-plugin file. + +2008-05-03 19:08:50 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Fix alignment of debug log columns on 64-bit. + Original commit message from CVS: + * gst/gstinfo.c: (gst_debug_log_default): + Fix alignment of debug log columns on 64-bit. + +2008-05-03 16:52:16 +0000 Tim-Philipp Müller + + docs/libs/: Ignore private controller headers for docs. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-sections.txt: + Ignore private controller headers for docs. + +2008-05-03 15:25:25 +0000 Sebastian Dröge + + libs/gst/controller/: Move some private declarations into private headers. + Original commit message from CVS: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstinterpolationcontrolsource.c: + (gst_interpolation_control_source_set_interpolation_mode): + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + * libs/gst/controller/lib.c: + Move some private declarations into private headers. + +2008-05-02 10:12:33 +0000 Sebastian Dröge + + gst/gstdebugutils.c: Remove some code that is unused after Stefan's refactoring and uses uninitialized variables now,... + Original commit message from CVS: + * gst/gstdebugutils.c: (debug_dump_element_pad): + Remove some code that is unused after Stefan's refactoring and uses + uninitialized variables now, resulting in a compiler warning. + +2008-05-01 13:03:51 +0000 Tim-Philipp Müller + + gst/gstregistry.c: Run g_str_has_suffix() only on the file name, not the entire file path. + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_scan_path_level): + Run g_str_has_suffix() only on the file name, not the + entire file path. + +2008-04-30 14:20:48 +0000 Tim-Philipp Müller + + plugins/elements/gstqueue.c: Since we're not called only from the chain function any longer, we can't assume that the... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_leak_downstream): + Since we're not called only from the chain function any longer, + we can't assume that there's always data in the queue, so move + the is_full check to the beginning of the loop (otherwise we'd + hit the assert when changing the limit properties while the + queue is empty or not running yet). + Also, only set a discont if items were actually removed from + the queue. + * tests/check/elements/queue.c: (test_leaky_downstream): + Test case for the above. + +2008-04-30 09:35:43 +0000 Jonas Holmberg + + plugins/elements/gstqueue.c: When changing thr max capacity of a leaky queue, immediatly drop buffers instead of wait... + Original commit message from CVS: + Patch by: Jonas Holmberg + * plugins/elements/gstqueue.c: (gst_queue_leak_downstream), + (gst_queue_chain), (queue_capacity_change), + (gst_queue_set_property): + When changing thr max capacity of a leaky queue, immediatly drop buffers + instead of waiting for a push on the sinkpad. Fixes #530637. + +2008-04-30 07:56:39 +0000 Stefan Kost + + gst/gstdebugutils.c: Refactor code and fix handling of ghostpads and their proxypads. + Original commit message from CVS: + * gst/gstdebugutils.c: + Refactor code and fix handling of ghostpads and their proxypads. + +2008-04-29 11:23:51 +0000 Wim Taymans + + Add method to conveniently check the name of a custom event with gst_event_has_name(). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: (gst_event_has_name): + * gst/gstevent.h: + * tests/check/gst/gstevent.c: (GST_START_TEST): + Add method to conveniently check the name of a custom event with + gst_event_has_name(). + Reformat the event docs so that related methods are put together instead + of the default alphabetical sort. + Update unit test with new method. + API: GstEvent::gst_event_has_name() + +2008-04-28 18:44:48 +0000 Michael Smith + + libs/gst/check/Makefile.am: Don't add an explicit link to libgstreamer-0.10.la; it's already included in GST_OBJ_LIBS. + Original commit message from CVS: + * libs/gst/check/Makefile.am: + Don't add an explicit link to libgstreamer-0.10.la; it's already + included in GST_OBJ_LIBS. + +2008-04-28 09:21:33 +0000 Sebastian Dröge + + gst/gst.c: Register GstClock type from a type-safe context. Fixes bug #530317. + Original commit message from CVS: + * gst/gst.c: + Register GstClock type from a type-safe context. Fixes bug #530317. + +2008-04-26 00:13:03 +0000 Edward Hervey + + tools/gst-run.c: Include conditionally on HAVE_UNISTD_H as elsewhere. + Original commit message from CVS: + Patch by Edward Hervey + * tools/gst-run.c: + Include conditionally on HAVE_UNISTD_H as elsewhere. + +2008-04-25 17:54:28 +0000 Antoine Tremblay + + gst/gstbin.c: Use the GLib stuff to create a private structure. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), + (gst_bin_dispose): + Use the GLib stuff to create a private structure. + Add some locking around some dispose methods to make them a little + safer, see #529723. Patch by: Antoine Tremblay + +2008-04-25 13:22:32 +0000 Stefan Kost + + libs/gst/base/: Fix doc typos and unify caps a bit. + Original commit message from CVS: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.h: + Fix doc typos and unify caps a bit. + +2008-04-25 13:09:40 +0000 Stefan Kost + + tools/gst-launch.1.in: Forgot to also add the envvar docs here. + Original commit message from CVS: + * tools/gst-launch.1.in: + Forgot to also add the envvar docs here. + +2008-04-25 10:01:46 +0000 Tim-Philipp Müller + + Ref some more classes in gst_init() to work around thread-safety issues in pre-2.16 GLibs, and add basic unit test. + Original commit message from CVS: + * gst/gst.c: (init_post), (gst_deinit): + * tests/check/gst/gstpipeline.c: (GST_START_TEST), (pipeline_thread), + (test_concurrent_create), (gst_pipeline_suite): + Ref some more classes in gst_init() to work around thread-safety + issues in pre-2.16 GLibs, and add basic unit test. + +2008-04-25 07:22:16 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Rearrange the latency query code. We always want to do the upstream query, even if we ar... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency), + (gst_base_sink_send_event): + Rearrange the latency query code. We always want to do the upstream + query, even if we are not live so that the upstream elements can get the + latency results too. If we fail doing the query and we are live, we + return TRUE afterwards. + +2008-04-24 15:14:54 +0000 Jason Zhao + + Enable/disable scan_and_update_registry() based on commandline switch or environment variable. Fixes #520468. + Original commit message from CVS: + patch by: Jason Zhao + * docs/gst/running.xml: + * gst/gst.c: + Enable/disable scan_and_update_registry() based on commandline switch + or environment variable. Fixes #520468. + * ChangeLog: + Fix typo in my previous commit. + +2008-04-24 08:27:59 +0000 Stefan Kost + + gst/gstregistrybinary.c: Add a warning of we hit unhandled factories when saving. + Original commit message from CVS: + * gst/gstregistrybinary.c: + Add a warning of we hit unhandled factories when saving. + More debug logging detail, but move to LOG category. + +2008-04-24 06:46:54 +0000 Stefan Kost + + gst/gstregistry.c: Tell the *truth* when improving the documentation. + Original commit message from CVS: + * gst/gstregistry.c: + Tell the *truth* when improving the documentation. + +2008-04-23 14:54:20 +0000 Sebastian Dröge + + gst/gstelementfactory.c: Unref the factory after it was used the last time, not before. + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_make): + Unref the factory after it was used the last time, not before. + * gst/gstindexfactory.c: (gst_index_factory_make): + Improve debugging a bit and don't leak a ref to the index factory with + each call. + +2008-04-23 13:55:01 +0000 Stefan Kost + + gst/gstregistry.c: Improve the documentation. + Original commit message from CVS: + * gst/gstregistry.c: + Improve the documentation. + +2008-04-23 10:14:38 +0000 Stefan Kost + + gst/gstsegment.c: The glib macro seems to be borked. Use g_slice_copy directly and cast in the hope that this fixes t... + Original commit message from CVS: + * gst/gstsegment.c: + The glib macro seems to be borked. Use g_slice_copy directly and cast + in the hope that this fixes the warning on 64bit. + +2008-04-23 07:08:53 +0000 Stefan Kost + + gst/gstsegment.c: Document the new function. Use g_slice_dup() (no need for gst_segment_init()). + Original commit message from CVS: + * gst/gstsegment.c: + Document the new function. Use g_slice_dup() (no need for + gst_segment_init()). + +2008-04-23 06:57:30 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: Move GParamSepc macros to standart section. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Move GParamSepc macros to standart section. + * gst/gstbin.c: + Dn't document _get_type - its in private section in docs anyway and + this doc-blob was incomplete. + * gst/gstclock.h: + Fix wrong symbol names in docs. + * gst/gstmacros.h: + Add once doc sentence. + * tests/check/gst/.cvsignore: + Ignore more. + +2008-04-21 10:25:02 +0000 Stefan Kost + + docs/gst/Makefile.am: And remove those libs here. + Original commit message from CVS: + * docs/gst/Makefile.am: + And remove those libs here. + +2008-04-21 09:29:37 +0000 Tim-Philipp Müller + + docs/libs/Makefile.am: Fix docs build again by adding libgstnet-0.10.so to SCANOBJ_DEPS. + Original commit message from CVS: + * docs/libs/Makefile.am: + Fix docs build again by adding libgstnet-0.10.so to SCANOBJ_DEPS. + +2008-04-21 08:34:09 +0000 Olivier Crete + + plugins/elements/gstqueue.c: Add the min-threshold to the min latency if possible. Fixes #529148. + Original commit message from CVS: + Patch by: Olivier Crete + * plugins/elements/gstqueue.c: (gst_queue_handle_src_query): + Add the min-threshold to the min latency if possible. Fixes #529148. + +2008-04-21 07:45:48 +0000 Stefan Kost + + docs/gst/gstreamer.types.in: Stupid editor, I removed that line as it should go in yet. + Original commit message from CVS: + * docs/gst/gstreamer.types.in: + Stupid editor, I removed that line as it should go in yet. + +2008-04-21 07:42:14 +0000 Stefan Kost + + docs/: Remove library types fro core docs and have them in libs docs. + Original commit message from CVS: + * docs/gst/gstreamer.types.in: + * docs/libs/gstreamer-libs.types: + Remove library types fro core docs and have them in libs docs. + Reformat and cleanup. Add comment for miniobject types. + +2008-04-20 16:32:03 +0000 Tim-Philipp Müller + + gst/gsturi.c: Fix leak: g_strdown operates on the string in place, while g_ascii_strdown() returns a newly-allocated ... + Original commit message from CVS: + * gst/gsturi.c: (gst_uri_get_protocol): + Fix leak: g_strdown operates on the string in place, while + g_ascii_strdown() returns a newly-allocated string. + +2008-04-20 09:55:25 +0000 Sebastian Dröge + + tools/gst-inspect.c: Print the URI protocols and the URI type supported by the element. + Original commit message from CVS: + * tools/gst-inspect.c: (print_uri_handler_info), + (print_element_info): + Print the URI protocols and the URI type supported by the element. + +2008-04-19 16:05:58 +0000 Sebastian Dröge + + gst/gsttaglist.c: Use g_value_take_string() instead of the deprecated g_value_set_string_take_ownership(). + Original commit message from CVS: + * gst/gsttaglist.c: (gst_tag_merge_strings_with_comma): + Use g_value_take_string() instead of the deprecated + g_value_set_string_take_ownership(). + +2008-04-19 15:42:19 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Return the old CRC instead of 0 if we give a NULL buffer or a buffer with a length of 0. + Original commit message from CVS: + * gst/gstregistrybinary.c: (_gst_crc32): + Return the old CRC instead of 0 if we give a NULL buffer + or a buffer with a length of 0. + +2008-04-19 15:36:20 +0000 Sebastian Dröge + + gst/gsturi.c: A valid URI scheme can also include '+', '-' and '.' additional to alphanumeric characters as per RFC 3... + Original commit message from CVS: + * gst/gsturi.c: (gst_uri_protocol_check_internal), + (gst_uri_get_protocol), (gst_uri_has_protocol), + (gst_uri_construct), (gst_uri_handler_set_uri): + A valid URI scheme can also include '+', '-' and '.' additional + to alphanumeric characters as per RFC 3986 Section 3.1. + Handle URI schemes case insensitive in all places and convert + to lower-case when constructing an URI or setting an URI with + the GstURIHandler interface. Fixes bug #528868. + All elements can still assume (as before) that they will + get passed URIs with a lower-case URI scheme by the GstURIHandler + interface. + +2008-04-17 10:09:39 +0000 Tim-Philipp Müller + + gst/: Don't use g_atomic_set_int where it's not needed. + Original commit message from CVS: + * gst/gstcaps.c: (gst_static_caps_get): + * gst/gstclock.c: (gst_clock_entry_new): + Don't use g_atomic_set_int where it's not needed. + +2008-04-17 08:45:19 +0000 Wim Taymans + + gst/: Fix 2 caps leaks. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_deserialize_caps): + * gst/parse/grammar.y: + Fix 2 caps leaks. + +2008-04-17 08:34:14 +0000 Sebastian Dröge + + gst/gstutils.c: Use g_atomic_int_set() here too instead of assignment + g_atomic_int_get(). + Original commit message from CVS: + * gst/gstutils.c: (gst_atomic_int_set): + Use g_atomic_int_set() here too instead of assignment + + g_atomic_int_get(). + +2008-04-17 07:14:46 +0000 Sebastian Dröge + + gst/gstutils.*: API: Deprecate gst_atomic_int_set(), g_atomic_int_set() should be used now that we depend on new enou... + Original commit message from CVS: + * gst/gstutils.c: + * gst/gstutils.h: + API: Deprecate gst_atomic_int_set(), g_atomic_int_set() should be used + now that we depend on new enough GLib. + * gst/gstcaps.c: (gst_static_caps_get): + * gst/gstclock.c: (gst_clock_entry_new): + * gst/gstinfo.c: (_gst_debug_init), (gst_debug_set_colored), + (gst_debug_set_default_threshold), (_gst_debug_category_new), + (gst_debug_category_set_threshold): + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_set_qos_enabled): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_set_property): + Use g_atomic_int_set() instead of gst_atomic_int_set(). + +2008-04-16 18:48:03 +0000 Stefan Kost + + gst/gstquery.c: Also use G_GINT64_CONSTANT for the queries. + Original commit message from CVS: + * gst/gstquery.c: + Also use G_GINT64_CONSTANT for the queries. + +2008-04-16 18:38:16 +0000 Stefan Kost + + gst/gstmessage.c: Use G_GINT64_CONSTANT in varargs function. + Original commit message from CVS: + * gst/gstmessage.c: + Use G_GINT64_CONSTANT in varargs function. + +2008-04-16 15:51:17 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Initialize the registry magic with zeroes. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_initialize_magic): + Initialize the registry magic with zeroes. + +2008-04-16 14:18:58 +0000 Sebastian Dröge + + gst/gstregistrybinary.*: Add crc32 checksum to the binary registry file and check this before accepting a registry file. + Original commit message from CVS: + * gst/gstregistrybinary.c: (_gst_crc32), + (gst_registry_binary_write), + (gst_registry_binary_initialize_magic), + (gst_registry_binary_write_cache), + (gst_registry_binary_check_magic), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + Add crc32 checksum to the binary registry file and check this before + accepting a registry file. + Also free the data list when writing to the registry file fails. + +2008-04-16 13:16:44 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: If an element supports the Uri interface, returns a valid pointer to the supported URI proto... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_save_feature), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin): + If an element supports the Uri interface, returns a valid pointer + to the supported URI protocols but this pointer contains nothing + don't try to save that as it will corrupt the registry. + Don't unref the plugin if we added it to the registry already but + fail to load a feature as gst_registry_add_plugin() takes ownership + of the plugin. + Improve debugging a bit. + +2008-04-16 08:30:57 +0000 Stefan Kost + + gst/gsttaglist.h: Clarify some tag item docs after discussion on irc. + Original commit message from CVS: + * gst/gsttaglist.h: + Clarify some tag item docs after discussion on irc. + +2008-04-15 06:23:14 +0000 Stefan Kost + + docs/gst/gstreamer-docs.sgml: Remove commented out plugins (they have their own docs). Update comments. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + Remove commented out plugins (they have their own docs). Update + comments. + +2008-04-15 06:16:33 +0000 Stefan Kost + + Add GST_PARAM_CONTROLLABLE and GST_PARAM_USER_SHIFT. Move paramspec docs to own section. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstparamspecs.c: + * gst/gstparamspecs.h: + Add GST_PARAM_CONTROLLABLE and GST_PARAM_USER_SHIFT. Move paramspec + docs to own section. + * gst/gstvalue.c: + This now only documents GValue. + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gstcontroller.h: + Remove GST_PARAM_CONTROLLABLE. + +2008-04-15 05:54:13 +0000 Stefan Kost + + docs/README: Correct file path. Tell about how to use -overrides.txt. + Original commit message from CVS: + * docs/README: + Correct file path. Tell about how to use -overrides.txt. + * docs/design/draft-tagreading.txt: + Small design update. + +2008-04-14 12:12:22 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Fix a typo in a debug message and revert change from yesterday as gst_registry_add_plugin() ... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin): + Fix a typo in a debug message and revert change from yesterday as + gst_registry_add_plugin() will only fail if something is really wrong + already and we can't survive it anyway. + +2008-04-14 08:48:50 +0000 Tim-Philipp Müller + + gst/gst.c: Pre-register GstGError GType from a thread-safe context (fixes #527967); unref enum type classes in deinit. + Original commit message from CVS: + * gst/gst.c: (init_post), (gst_deinit): + Pre-register GstGError GType from a thread-safe context + (fixes #527967); unref enum type classes in deinit. + +2008-04-13 19:58:43 +0000 Rene Stadler + + gst/gsttagsetter.c: Merging an empty list with another list in KEEP_ALL mode should yield an empty list as result and... + Original commit message from CVS: + Patch by: Rene Stadler + * gst/gsttagsetter.c: (gst_tag_setter_merge_tags): + Merging an empty list with another list in KEEP_ALL mode should + yield an empty list as result and not the second list (#512578). + * tests/check/gst/gsttagsetter.c: + Add unit test for tag merge modes and the aforementioned bug. + +2008-04-13 18:50:05 +0000 Rene Stadler + + gst/gsttaglist.h: Fix description to match the order in the table (#512577). + Original commit message from CVS: + Patch by: Rene Stadler + * gst/gsttaglist.h: + Fix description to match the order in the table (#512577). + +2008-04-13 17:51:02 +0000 Kwang Yul Seo + + Define socklen_t as int if it's not defined yet. Fixes compilation with MSVC6 and other versions where socklen_t is n... + Original commit message from CVS: + Patch by: Kwang Yul Seo + * libs/gst/net/gstnettimepacket.h: + * docs/libs/gstreamer-libs-sections.txt: + Define socklen_t as int if it's not defined yet. Fixes compilation + with MSVC6 and other versions where socklen_t is not defined in + the windows headers (#518022). + +2008-04-13 13:54:55 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: If gst_registry_add_plugin() fails our reference to the plugin is invalid so don't try to us... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_load_plugin): + If gst_registry_add_plugin() fails our reference to the plugin is + invalid so don't try to use it anymore and instead error out. + +2008-04-12 20:52:58 +0000 Tim-Philipp Müller + + tools/gst-xmlinspect.c: De-cruft a bit. If no argument is specified, print all elements in + Original commit message from CVS: + * tools/gst-xmlinspect.c: (print_element_info), (main): + De-cruft a bit. If no argument is specified, print all elements in + XML syntax rather than a freestyle list of elements like gst-inspect. + Also, don't print XML header chunk unless we actually have something + to print (ie. don't print it before an error message); print error + message to stderr not stdout. Remove support for printing plugin + info (it would just output something freestyle along the lines of + gst-inspect so far), which fixes #514507. Also add license header. + +2008-04-11 09:27:44 +0000 Julien Moutte + + Mac OS X love... + Original commit message from CVS: + 2008-04-11 Julien Moutte + Mac OS X love... + * configure.ac: Merge platform specific defines, introduce a new + define on OS X to remember that forking when updating registry is + unsafe. + * docs/faq/gst-uninstalled: Updated to include gst-libs in the bad + module. + * gst/gst.c: Don't fork when updating registry if GST_HAVE_UNSAFE_FORK + is defined. + * gst/gstregistry.c: (gst_registry_scan_path_level): Fixed a bogus + condition that leads to absolutely no plugins being registered on + OS X. + +2008-04-10 20:46:51 +0000 José Alburquerque + + Add gst_pad_add_*_probe_full() functions with a notify callback that lets the caller free the data it passes to the p... + Original commit message from CVS: + Based on patch by: José Alburquerque + * gst/gstutils.c: (gst_pad_add_data_probe), + (gst_pad_add_data_probe_full), (gst_pad_add_event_probe), + (gst_pad_add_event_probe_full), (gst_pad_add_buffer_probe), + (gst_pad_add_buffer_probe_full): + * gst/gstutils.h: + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + Add gst_pad_add_*_probe_full() functions with a notify callback that + lets the caller free the data it passes to the probe functions. This + is useful for bindings such as gst-python or gstreamermm (#526814). + API: gst_pad_add_data_probe_full + API: gst_pad_add_buffer_probe_full + API: gst_pad_add_event_probe_full + * tests/check/gst/gstutils.c: + Add minimal unit test to make sure freeing the data actually works + as expected. + * tests/benchmarks/.cvsignore: + Random cvsignore addendum. + +2008-04-10 19:13:46 +0000 Tim-Philipp Müller + + gst/gstdebugutils.h: Mention GstDebugGraphDetails enum type in doc blurb so we get a link to it in the docs (since th... + Original commit message from CVS: + * gst/gstdebugutils.h: (GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS), + (GST_DEBUG_BIN_TO_DOT_FILE): + Mention GstDebugGraphDetails enum type in doc blurb so we get a link + to it in the docs (since these are macros the types of the arguments + won't be shown in the docs otherwise). + +2008-04-10 14:10:51 +0000 Stefan Kost + + gst/gstpad.c: Do not abort on out of memory for pad_alloc_buffer. + Original commit message from CVS: + * gst/gstpad.c: + Do not abort on out of memory for pad_alloc_buffer. + +2008-04-10 13:59:24 +0000 Stefan Kost + + libs/gst/check/gstcheck.c: Remove blank line between symbol name ad parameters to fix gtkdoc warning. + Original commit message from CVS: + * libs/gst/check/gstcheck.c: + Remove blank line between symbol name ad parameters to fix gtkdoc + warning. + +2008-04-09 22:37:22 +0000 José Alburquerque + + Expose gst_segment_copy() to make things easier for the c++ bindings. + Original commit message from CVS: + Patch by: José Alburquerque + * docs/gst/gstreamer-sections.txt: + * gst/gstsegment.c: + * gst/gstsegment.h: + * win32/common/libgstreamer.def: + Expose gst_segment_copy() to make things easier for the c++ bindings. + Fixes #518932. + API: gst_segment_copy() + +2008-04-09 21:27:40 +0000 Tim-Philipp Müller + + gst/gst.c: Fix const position; ref GType classes for enum types to work around thread-safety issues in GLib versions ... + Original commit message from CVS: + * gst/gst.c: (gst_init_get_option_group), (init_post): + Fix const position; ref GType classes for enum types to work + around thread-safety issues in GLib versions < 2.16. + +2008-04-09 18:26:15 +0000 Wim Taymans + + docs/design/part-buffering.txt: Fix some typos and set the estimated total for push mode to -1. + Original commit message from CVS: + * docs/design/part-buffering.txt: + Fix some typos and set the estimated total for push mode to -1. + * gst/gstquery.c: (gst_query_new_buffering): + Set buffering-left to 0 as we're not buffering by default. + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_query): + Implement BUFFERING query. + +2008-04-09 17:34:54 +0000 Milosz Derezynski + + gst/gsterror.*: Add two new error codes for encrypted content. Fixes #524659. + Original commit message from CVS: + Based on patch by: Milosz Derezynski + * gst/gsterror.c: (_gst_stream_errors_init): + * gst/gsterror.h: + Add two new error codes for encrypted content. Fixes #524659. + API: GST_STREAM_ERROR_DECRYPT + API: GST_STREAM_ERROR_DECRYPT_NOKEY + +2008-04-09 13:15:33 +0000 Tim-Philipp Müller + + gst/gstquery.h: Fix typo. + Original commit message from CVS: + * gst/gstquery.h: + Fix typo. + * win32/common/libgstreamer.def: + Add new functions. + +2008-04-09 08:19:36 +0000 Sebastian Dröge + + plugins/elements/gstidentity.c: Fix imperfect timestamp/offset checks when we get another NEWSEGMENT event after proc... + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_event), + (gst_identity_start): + Fix imperfect timestamp/offset checks when we get another NEWSEGMENT + event after processing some data. Fixes bug #526042. + +2008-04-08 20:28:21 +0000 Wim Taymans + + Rename _avail -> _range + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstquery.c: (gst_query_parse_latency), + (gst_query_set_buffering_percent), + (gst_query_parse_buffering_percent), + (gst_query_set_buffering_range), (gst_query_parse_buffering_range): + * gst/gstquery.h: + Rename _avail -> _range + API: gst_query_set_buffering_range + API: gst_query_parse_buffering_range + +2008-04-08 20:17:49 +0000 Wim Taymans + + Add busy field and quark for the buffering query so that the app can only use the query to see if buffering is in pro... + Original commit message from CVS: + * docs/design/part-buffering.txt: + * gst/gstquark.c: + * gst/gstquark.h: + * gst/gstquery.c: (gst_query_parse_latency), + (gst_query_new_buffering), (gst_query_set_buffering_percent), + (gst_query_parse_buffering_percent): + * gst/gstquery.h: + Add busy field and quark for the buffering query so that the app can + only use the query to see if buffering is in progress. + +2008-04-08 19:59:06 +0000 Wim Taymans + + Reorder the message docs and headers for clarity. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: (gst_message_set_buffering_stats), + (gst_message_parse_buffering_stats): + * gst/gstmessage.h: + * gst/gstquery.c: (gst_query_new_latency), (gst_query_set_latency), + (gst_query_parse_latency), (gst_query_new_buffering), + (gst_query_set_buffering_percent), + (gst_query_parse_buffering_percent), + (gst_query_set_buffering_stats), (gst_query_parse_buffering_stats), + (gst_query_set_buffering_avail), (gst_query_parse_buffering_avail): + * gst/gstquery.h: + Reorder the message docs and headers for clarity. + Add aditional buffering stats API for messages. + Add buffering query. + Convert some leftover queries to use GstQuark. + API: gst_message_set_buffering_stats + API: gst_message_parse_buffering_stats + API: GST_QUERY_BUFFERING + API: GstBufferingMode + API: gst_query_new_buffering + API: gst_query_set_buffering_percent + API: gst_query_parse_buffering_percent + API: gst_query_set_buffering_stats + API: gst_query_parse_buffering_stats + API: gst_query_set_buffering_avail + API: gst_query_parse_buffering_avail + +2008-04-08 19:52:22 +0000 Wim Taymans + + gst/gstmessage.c: Use GstQuark for messages. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_info), + (gst_message_new_buffering), (gst_message_new_state_changed), + (gst_message_new_clock_provide), (gst_message_new_clock_lost), + (gst_message_new_new_clock), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_new_duration), + (gst_message_new_async_start), (gst_message_parse_buffering), + (gst_message_parse_state_changed), + (gst_message_parse_clock_provide), (gst_message_parse_clock_lost), + (gst_message_parse_new_clock), (gst_message_parse_error), + (gst_message_parse_warning), (gst_message_parse_info), + (gst_message_parse_segment_start), + (gst_message_parse_segment_done), (gst_message_parse_duration), + (gst_message_parse_async_start): + Use GstQuark for messages. + +2008-04-08 19:39:28 +0000 Wim Taymans + + gst/gstquark.*: Add some more quarks needed for messages and queries. + Original commit message from CVS: + * gst/gstquark.c: (_priv_gst_quarks_initialize): + * gst/gstquark.h: + Add some more quarks needed for messages and queries. + +2008-04-08 19:14:49 +0000 Wim Taymans + + docs/design/part-buffering.txt: Remove the "none" buffering mode, STREAM is a good default. + Original commit message from CVS: + * docs/design/part-buffering.txt: + Remove the "none" buffering mode, STREAM is a good default. + Move estimated-time to the avail query, that's when it will be needed. + Other small typo fixes and updates. + +2008-04-07 13:27:32 +0000 Tim-Philipp Müller + + gst/gstindex.c: Don't put descriptions into the nick field of a GEnumValue: it's not meant for that and some language... + Original commit message from CVS: + * gst/gstindex.c: (gst_index_resolver_get_type): + Don't put descriptions into the nick field of a GEnumValue: it's not + meant for that and some language bindings rely on the nick field to + construct constants and the like. Fixes #526705. + +2008-04-07 10:48:51 +0000 Tim-Philipp Müller + + Merge other changes from 0.10.19 release branch. + Original commit message from CVS: + * NEWS: + * RELEASE: + * gstreamer.doap: + Merge other changes from 0.10.19 release branch. + +2008-04-06 08:54:47 +0000 Damien Lespiau + + configure.ac: Actually build dlls when cross-compiling with mingw32. + Original commit message from CVS: + Patch by: Damien Lespiau + * configure.ac: + Actually build dlls when cross-compiling with mingw32. + Fixes bug #526247. + +2008-04-05 10:58:11 +0000 Damien Lespiau + + gst/gstpoll.c: Fix compilation of GstPoll with mingw32. Fixes bug #526236. + Original commit message from CVS: + Patch by: Damien Lespiau + * gst/gstpoll.c: + Fix compilation of GstPoll with mingw32. Fixes bug #526236. + +2008-04-04 13:43:26 +0000 Wim Taymans + + docs/design/draft-latency.txt: Fix typo. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Fix typo. + * docs/design/part-buffering.txt: + Update design docs with more buffering ideas. + +2008-04-03 21:15:09 +0000 Tim-Philipp Müller + + configure.ac: Bump version to 0.10.19.1 after the unscheduled 0.10.19 release. + Original commit message from CVS: + * configure.ac: + Bump version to 0.10.19.1 after the unscheduled 0.10.19 release. + +2008-04-03 16:45:02 +0000 Christian Schaller + + * gstreamer.spec.in: + update spec to work with docs + Original commit message from CVS: + update spec to work with docs + +2008-04-03 14:49:06 +0000 Stefan Kost + + configure.ac: Revert part that belongs to the preset patch. + Original commit message from CVS: + * configure.ac: + Revert part that belongs to the preset patch. + +2008-04-03 14:26:55 +0000 Stefan Kost + + configure.ac: Add qoutes to the define. Fixes # 525961. + Original commit message from CVS: + * configure.ac: + Add qoutes to the define. Fixes # 525961. + +2008-04-03 07:52:31 +0000 Sebastian Dröge + + plugins/indexers/: Use GSlice when possible. + Original commit message from CVS: + * plugins/indexers/gstfileindex.c: (_file_index_id_free), + (gst_file_index_load), (gst_file_index_add_id), + (gst_file_index_get_assoc_entry): + * plugins/indexers/gstmemindex.c: (gst_mem_index_free_format), + (gst_mem_index_free_id), (gst_mem_index_add_id), + (gst_mem_index_index_format): + Use GSlice when possible. + +2008-04-02 17:45:08 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolationcontrolsource.c: Use GSlice for allocating the control points. + Original commit message from CVS: + * libs/gst/controller/gstinterpolationcontrolsource.c: + (gst_control_point_free), + (gst_interpolation_control_source_set_internal): + Use GSlice for allocating the control points. + +2008-04-02 17:21:40 +0000 Wim Taymans + + plugins/elements/gsttypefindelement.*: Cleanup properties. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_class_init), + (gst_type_find_element_set_property), + (gst_type_find_element_get_property), + (gst_type_find_element_activate): + * plugins/elements/gsttypefindelement.h: + Cleanup properties. + Fix pad leak when peer query fails. + We can still typefind when the peer returns -1. + Add property to force caps and bypass typefinding. This will be used in + uridecodebin. + API::force-caps + +2008-04-01 13:55:20 +0000 Sebastian Dröge + + configure.ac: Require GLib 2.12. + Original commit message from CVS: + * configure.ac: + Require GLib 2.12. + * gst/glib-compat-private.h: + * gst/gstcaps.c: (gst_caps_new_empty), (_gst_caps_free): + * gst/gstclock.c: (gst_clock_entry_new), (_gst_clock_id_free): + Unconditionally use GSlice for allocation. + * gst/gstpoll.c: (gst_poll_new), (gst_poll_free): + * gst/gstsegment.c: (gst_segment_new), (gst_segment_free): + * gst/gststructure.c: (gst_structure_id_empty_new_with_size), + (gst_structure_free): + Use GSlice for allocation. + +2008-04-01 13:48:59 +0000 Sebastian Dröge + + gst/parse/: Require a new enough flex and bison and remove the parser hacks to use a pre-regenerated version. + Original commit message from CVS: + * gst/parse/Makefile.am: + * gst/parse/grammar.tab.pre.c: + * gst/parse/grammar.tab.pre.h: + * gst/parse/lex._gst_parse_yy.pre.c: + Require a new enough flex and bison and remove the parser hacks to use + a pre-regenerated version. + +2008-04-01 10:25:35 +0000 Jason Zhao + + configure.ac: Add a configure switch to disable option parsing in gst_init. + Original commit message from CVS: + 2008-04-01 Julien Moutte + patch by: Jason Zhao + * configure.ac: Add a configure switch to disable option parsing + in gst_init. + Fixes #522882. + +2008-03-31 13:47:22 +0000 Stefan Kost + + MacOS has plugins under .so or under .dylib. Add detection for MacOS and handle this case. + Original commit message from CVS: + * configure.ac: + * gst/gstregistry.c: + MacOS has plugins under .so or under .dylib. Add detection for MacOS + and handle this case. + * gst/gst.c: + Add a comment here describing, why we stat each plugin and not try to + be smart. + +2008-03-31 10:21:57 +0000 Sebastian Dröge + + libs/gst/base/gstbasetransform.c: Also unset the GAP flag on buffers if we're working inplace but the element is not ... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer): + Also unset the GAP flag on buffers if we're working inplace but + the element is not GAP-aware. + Mark a comment as FIXME 0.11. + +2008-03-31 08:32:26 +0000 Stefan Kost + + gst/gst.c: Fix type in log message and add one to ease seeing how long registry cache verification takes. + Original commit message from CVS: + * gst/gst.c: + Fix type in log message and add one to ease seeing how long registry + cache verification takes. + * gst/gstregistry.c: + Only test plugin filenames against G_MODULE_SUFFIX. + +2008-03-31 07:49:26 +0000 Stefan Kost + + gst/gstdebugutils.c: Improve handling ghost/proxy pads. + Original commit message from CVS: + * gst/gstdebugutils.c: + Improve handling ghost/proxy pads. + +2008-03-27 19:13:45 +0000 Stefan Kost + + Expose macro to docs and fix link to it. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: + * gst/gstpad.h: + Expose macro to docs and fix link to it. + +2008-03-27 15:23:55 +0000 Michael Smith + + libs/gst/dataprotocol/dataprotocol.c: When calculating GDP body CRC, use the correct pointer. + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_packet_from_event_1_0): + When calculating GDP body CRC, use the correct pointer. + Fixes part of #522401. + +2008-03-24 16:56:36 +0000 Mark Nauwelaerts + + plugins/elements/gstidentity.c: Identity is not always a passthrough element, it can modify the buffer timestamps whe... + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * plugins/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_init), (gst_identity_prepare_output_buffer): + Identity is not always a passthrough element, it can modify the buffer + timestamps when it has a datarate and operates in single-segment mode. + We therefore make it an in_place filter with a custom buffer prepare + function that conditionally makes the input buffer metadata writable + when needed. Fixes #523985. + +2008-03-24 16:44:25 +0000 Mark Nauwelaerts + + Small documentation fixes. Fixes #523978. + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * gst/gstclock.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/check/gstcheck.c: + Small documentation fixes. Fixes #523978. + +2008-03-24 16:31:30 +0000 Wim Taymans + + plugins/elements/: Also retry our poll_wait when we get EAGAIN. Fixes #524041. + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_render): + * plugins/elements/gstfdsrc.c: (gst_fd_src_create): + Also retry our poll_wait when we get EAGAIN. Fixes #524041. + +2008-03-24 10:38:31 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: When trying to make room in the queue, bump the max allowed buffers bigger than the... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (single_queue_overrun_cb), + (single_queue_underrun_cb): + When trying to make room in the queue, bump the max allowed buffers + bigger than the current amount of buffers in the queue. this fixes some + nasty deadlocks in multiqueue when dynamically changing the limits of + the queue. + +2008-03-24 10:33:41 +0000 José Alburquerque + + gst/gstcaps.*: Constify the field gchar * params in set_simple and friends. + Original commit message from CVS: + Patch by: José Alburquerque + * gst/gstcaps.c: (gst_caps_set_simple), + (gst_caps_set_simple_valist), (gst_caps_intersect): + * gst/gstcaps.h: + Constify the field gchar * params in set_simple and friends. + Fixes #522326. + +2008-03-24 10:29:05 +0000 Wim Taymans + + gst/gstvalue.c: Transform a GstObject to a more meaningfull string that includes the object type in addition to its n... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_transform_object_string): + Transform a GstObject to a more meaningfull string that includes the + object type in addition to its name. + +2008-03-23 15:17:24 +0000 Stefan Kost + + ChangeLog: ChangeLog surgery to add bugnumber to commit. + Original commit message from CVS: + * ChangeLog: + ChangeLog surgery to add bugnumber to commit. + +2008-03-23 14:24:48 +0000 Rene Stadler + + libs/gst/base/gstbasetransform.c: Fix confusing documentation. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_set_gap_aware): Fix confusing documentation. + +2008-03-23 11:40:54 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Rename constant everywhere and don't forget one occurence. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write): + Rename constant everywhere and don't forget one occurence. + +2008-03-23 11:29:54 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Align memory to the pointer size even if the architecture allows unaligned memory access. Un... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write): + Align memory to the pointer size even if the architecture allows + unaligned memory access. Unaligned memory access usually comes with + performance penality. + +2008-03-23 11:23:30 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Align memory to the pointer size instead of always 32 bit. Fixes unaligned memory accesses o... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write), + (gst_registry_binary_check_magic), + (gst_registry_binary_load_pad_template), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin): + Align memory to the pointer size instead of always 32 bit. Fixes + unaligned memory accesses on ia64 and friends. + * gst/gstregistrybinary.h: + Bump binary registry format version for this as it changes the + format on those architectures that don't have unaligned access + and 64 bit pointers. + +2008-03-22 14:56:17 +0000 Sebastian Dröge + + Define G_PARAM_STATIC_STRINGS if it's undefined (GLib < 2.13.0) and use it everywhere for GParamSpecs that use static... + Original commit message from CVS: + * docs/pwg/advanced-dparams.xml: + * docs/pwg/building-props.xml: + * docs/pwg/other-source.xml: + * gst/glib-compat.h: + * gst/gstbin.c: (gst_bin_class_init): + * gst/gstclock.c: (gst_clock_class_init): + * gst/gstindex.c: (gst_index_class_init): + * gst/gstobject.c: (gst_object_class_init): + * gst/gstpad.c: (gst_pad_class_init): + * gst/gstpipeline.c: (gst_pipeline_class_init): + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init): + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_class_init): + * libs/gst/base/gstdataqueue.c: (gst_data_queue_class_init): + * libs/gst/check/gstcheck.c: (_gst_check_fault_handler_restore), + (_gst_check_fault_handler_sighandler), + (_gst_check_fault_handler_setup), (gst_check_init): + * libs/gst/controller/gstcontroller.c: + (_gst_controller_class_init): + * libs/gst/controller/gstlfocontrolsource.c: + (gst_lfo_control_source_class_init): + * libs/gst/net/gstnetclientclock.c: + (gst_net_client_clock_class_init): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_class_init): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_class_init): + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init): + * plugins/elements/gstfdsink.c: (gst_fd_sink_class_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init): + * plugins/elements/gstfilesink.c: (gst_file_sink_class_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init): + * plugins/elements/gstidentity.c: (gst_identity_class_init): + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_class_init): + * plugins/elements/gstqueue.c: (gst_queue_class_init): + * plugins/elements/gsttee.c: (gst_tee_class_init): + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_class_init): + * plugins/indexers/gstfileindex.c: (gst_file_index_class_init): + Define G_PARAM_STATIC_STRINGS if it's undefined (GLib < 2.13.0) and + use it everywhere for GParamSpecs that use static strings (i.e. all). + This gives us less memory usage, fewer allocations and thus less + memory defragmentation. Fixes bug #523806. + +2008-03-22 14:51:17 +0000 Sebastian Dröge + + API: Add GST_IS_PARAM_SPEC_MINI_OBJECT, GST_PARAM_SPEC_MINI_OBJECT + Original commit message from CVS: + * gst/gstminiobject.c: (gst_value_dup_mini_object), + (gst_param_spec_mini_object): + * gst/gstminiobject.h: + * win32/common/libgstreamer.def: + * docs/gst/gstreamer-sections.txt: + API: Add GST_IS_PARAM_SPEC_MINI_OBJECT, GST_PARAM_SPEC_MINI_OBJECT + GST_TYPE_PARAM_MINI_OBJECT and gst_value_dup_mini_object. Also move + GstParamSpecMiniObject into a public header for this. + This make GstMiniObject a bit more consistent with GObject and makes + it possible to extend the param specs. + gst_value_dup_mini_object is mainly useful for set_property methods. + Fixes bug #523798. + * tools/gst-inspect.c: (print_element_properties_info): + Print something useful for GstMiniObject properties and not just + "unknown type". + +2008-03-21 16:11:51 +0000 Sebastian Dröge + + Call the version GST_MAGIC_BINARY_VERSION_STR to be more consistent and add it to the (private part) of the docs to f... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstregistrybinary.c: (gst_registry_binary_initialize_magic), + (gst_registry_binary_check_magic): + * gst/gstregistrybinary.h: + Call the version GST_MAGIC_BINARY_VERSION_STR to be more consistent + and add it to the (private part) of the docs to fix the build. + +2008-03-21 15:52:14 +0000 Sebastian Dröge + + gst/gstregistrybinary.*: Don't use GST_MAJORMINOR for the binary registry version. Instead hardcode a value that must... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_initialize_magic), + (gst_registry_binary_check_magic), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + Don't use GST_MAJORMINOR for the binary registry version. Instead + hardcode a value that must be changed whenever the format changes + in an incompatible way. + Also don't GST_ERROR when there is a version mismatch, just + regenerate the registry silently. + +2008-03-21 00:35:10 +0000 Jan Schmidt + + 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:20:59 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.10.18 + Original commit message from CVS: + Release 0.10.18 + +2008-03-20 23:26:05 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-03-18 12:17:58 +0000 Jan Schmidt + + 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 10:54:52 +0000 Ole André Vadla Ravnås + + Add new function gst_poll_fd_ignored() for improved Windows compatibility. + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + + * docs/gst/gstreamer-sections.txt: + * gst/gstpoll.c: (gst_poll_winsock_error_to_errno), + (gst_poll_update_winsock_event_mask), + (gst_poll_prepare_winsock_active_sets), + (gst_poll_collect_winsock_events), (gst_poll_new), (gst_poll_free), + (gst_poll_add_fd_unlocked), (gst_poll_fd_ctl_write), + (gst_poll_fd_ctl_read_unlocked), (gst_poll_fd_ignored), + (gst_poll_fd_has_error), (gst_poll_fd_can_read_unlocked), + (gst_poll_check_ctrl_commands), (gst_poll_wait): + * gst/gstpoll.h: + * win32/common/libgstreamer.def: + Add new function gst_poll_fd_ignored() for improved Windows + compatibility. + Various minor fixes and cleanups. See #520808. + +2008-03-17 10:21:59 +0000 Tim-Philipp Müller + + gst/gstindex.*: Don't free key strings which we don't own. Fixes crash in gst_index_entry_free() (#522741). + Original commit message from CVS: + * gst/gstindex.c: (gst_index_entry_free): + * gst/gstindex.h: + Don't free key strings which we don't own. Fixes crash in + gst_index_entry_free() (#522741). + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gstindex.c: (test_index_entries), + (gst_index_suite), (gst_index): + Add unit test for the above. + +2008-03-11 14:09:46 +0000 Sebastian Dröge + + win32/common/libgstreamer.def: Remove symbols that were removed recently. Fixes bug #521740. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Remove symbols that were removed recently. Fixes bug #521740. + +2008-03-11 00:24:18 +0000 Jan Schmidt + + 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-11 00:23:02 +0000 Jan Schmidt + + configure.ac: Release 0.10.17.3 + Original commit message from CVS: + * configure.ac: + Release 0.10.17.3 + +2008-03-07 15:39:45 +0000 Ole André Vadla Ravnås + + Remove GstPollMode from the API, it does not make sense to let the application control this. + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + + * docs/gst/gstreamer-sections.txt: + * gst/gstpoll.c: (find_index), (gst_poll_free_winsock_event), + (gst_poll_update_winsock_event_mask), (gst_poll_new), + (gst_poll_free), (gst_poll_fd_init), (gst_poll_add_fd_unlocked), + (gst_poll_remove_fd), (gst_poll_fd_ctl_write), + (gst_poll_fd_ctl_read_unlocked), (gst_poll_fd_has_closed), + (gst_poll_fd_has_error), (gst_poll_fd_can_read_unlocked), + (gst_poll_fd_can_write), (gst_poll_wait), + (gst_poll_set_controllable), (gst_poll_restart), + (gst_poll_set_flushing): + * gst/gstpoll.h: + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_new): + * libs/gst/net/gstnettimeprovider.c: (gst_net_time_provider_start), + (gst_net_time_provider_new): + * plugins/elements/gstfdsink.c: (gst_fd_sink_start): + * plugins/elements/gstfdsrc.c: (gst_fd_src_start): + * tests/benchmarks/gstpollstress.c: (main): + * tests/check/gst/gstpoll.c: (GST_START_TEST), (gst_poll_suite): + Remove GstPollMode from the API, it does not make sense to let the + application control this. + Add support for Win32. + Fix the testsuite. Fixes #520671. + +2008-03-07 13:19:12 +0000 Ole André Vadla Ravnås + + gst/gstregistrybinary.c: Include io.h for write() and close() when building with MSVC. Fixes bug #520877. + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + + * gst/gstregistrybinary.c: + Include io.h for write() and close() when building with MSVC. Fixes + bug #520877. + +2008-03-07 11:12:59 +0000 Stefan Kost + + Move registry backend API to private headers where we can. Add fixme-0.11 comments for the others. Add stubs for the ... + Original commit message from CVS: + * configure.ac: + * gst/gst_private.h: + * gst/gstconfig.h.in: + * gst/gstregistry.h: + * gst/gstregistrybinary.c: + * win32/common/gstconfig.h: + Move registry backend API to private headers where we can. Add + fixme-0.11 comments for the others. Add stubs for the xml backend when + using the binary to ensure they functions exists (they should not be + used though). Fixes #520756. + +2008-03-04 00:14:52 +0000 Jan Schmidt + + 0.10.17.2 prelease + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + 0.10.17.2 prelease + +2008-03-03 18:42:04 +0000 Edward Hervey + + Switch to using portabl gsize/gssize instead of size_t/ssize_t + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write), + (gst_registry_binary_read_cache): + * gst/gstregistryxml.c: (gst_registry_save): + * gst/gsturi.c: (unescape_string), (gst_uri_has_protocol): + * plugins/elements/gstfilesink.c: (gst_file_sink_open_file): + * plugins/elements/gstfilesrc.c: (gst_file_src_map_region), + (gst_file_src_map_small_region), (gst_file_src_create_mmap): + Switch to using portabl gsize/gssize instead of size_t/ssize_t + Fixes #520152 + +2008-03-03 18:14:33 +0000 Edward Hervey + + gst/gstminiobject.c: Import gst_private.h before any other header that might include other glib headers. This fixes t... + Original commit message from CVS: + * gst/gstminiobject.c: + Import gst_private.h before any other header that might include other + glib headers. This fixes the build on windows using native compilers. + +2008-03-03 14:48:50 +0000 Tim-Philipp Müller + + win32/common/gstconfig.h: Add here too, just for completeness. + Original commit message from CVS: + * win32/common/gstconfig.h: + Add here too, just for completeness. + +2008-03-03 14:43:26 +0000 Tim-Philipp Müller + + Fix broken use of config.h-defined preprocessor directive in a public header file. Add a corresponding define to gstc... + Original commit message from CVS: + * configure.ac: + * gst/gstconfig.h.in: + * gst/gstregistry.h: + Fix broken use of config.h-defined preprocessor directive in a public + header file. Add a corresponding define to gstconfig.h, since we can't + really remove those function declarations from the header file now + (or can we? and why are they there in the first place?). + +2008-03-03 10:07:21 +0000 Andy Wingo + + tests/check/gst/gststructure.c (GST_START_TEST): Add a check for the new warning. + Original commit message from CVS: + 2008-03-03 Andy Wingo + * tests/check/gst/gststructure.c (GST_START_TEST): Add a check for + the new warning. + * gst/gststructure.c (gst_structure_from_string): Warn if + structure_from_string didn't consume the whole string, but the + caller did not provide an end pointer. + +2008-03-01 11:21:30 +0000 Fabrizio Gennari + + gst/gstregistryxml.c: Strings allocated by libxml2 should be freed with xmlFree(), not with g_free(). Fixes issues on... + Original commit message from CVS: + Patch by: Fabrizio Gennari + * gst/gstregistryxml.c: (read_string), (load_feature): + Strings allocated by libxml2 should be freed with xmlFree(), not + with g_free(). Fixes issues on windows in certain contexts (#519698). + +2008-02-29 18:38:54 +0000 Tim-Philipp Müller + + gst/gstinterface.c: Don't crash if the element supports the interface queried, but does not implement GstImplementsIn... + Original commit message from CVS: + * gst/gstinterface.c: (gst_element_implements_interface): + Don't crash if the element supports the interface queried, but does + not implement GstImplementsInterface. Fixes #519584. + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gstinterface.c: + Add unit test for the above. + +2008-02-29 15:39:44 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Small doc update. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init): + Small doc update. + +2008-02-29 15:22:34 +0000 Wim Taymans + + gst/gstsegment.c: Improve some comment. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_seek), + (gst_segment_to_stream_time): + Improve some comment. + Update variables where it makes more sense. + +2008-02-29 14:23:17 +0000 Rene Stadler + + gst/gsturi.c: Use the get_protocols_full vfunc if get_protocols is NULL. Fixes + Original commit message from CVS: + * gst/gsturi.c: (gst_uri_handler_get_protocols): + Use the get_protocols_full vfunc if get_protocols is NULL. Fixes + URIHandlers implemented using language bindings. + +2008-02-29 13:59:24 +0000 Sebastian Dröge + + And correct even more valid sparse warnings. + Original commit message from CVS: + * gst/gstelementfactory.h: + * tests/check/elements/fakesink.c: + * tests/check/elements/fakesrc.c: (setup_fakesrc): + * tests/check/elements/fdsrc.c: (setup_fdsrc): + * tests/check/elements/filesink.c: (setup_filesink): + * tests/check/elements/filesrc.c: (setup_filesrc): + * tests/check/elements/identity.c: (setup_identity): + * tests/check/elements/tee.c: + * tests/check/generic/sinks.c: + * tests/check/generic/states.c: (setup), (teardown): + * tests/check/gst/gst.c: + * tests/check/gst/gstabi.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbus.c: (pull_messages): + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstevent.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gstminiobject.c: (my_foo_init): + * tests/check/gst/gstobject.c: (thread_name_object), + (gst_object_suite): + * tests/check/gst/gstpad.c: + * tests/check/gst/gstplugin.c: + * tests/check/gst/gstpoll.c: + * tests/check/gst/gstquery.c: + * tests/check/gst/gstsegment.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttask.c: + * tests/check/gst/gstutils.c: + * tests/check/gst/gstvalue.c: + * tests/check/gst/struct_hppa.h: + * tests/check/gst/struct_i386.h: + * tests/check/gst/struct_ppc32.h: + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_x86_64.h: + * tests/check/libs/adapter.c: (create_and_fill_adapter): + * tests/check/libs/basesrc.c: + * tests/check/libs/controller.c: (GST_START_TEST): + * tests/check/libs/gdp.c: + * tests/check/libs/gstnetclientclock.c: + * tests/check/libs/gstnettimeprovider.c: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_hppa.h: + * tests/check/libs/struct_i386.h: + * tests/check/libs/struct_ppc32.h: + * tests/check/libs/struct_ppc64.h: + * tests/check/libs/struct_x86_64.h: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/simple-launch-lines.c: + * tests/check/pipelines/stress.c: + And correct even more valid sparse warnings. + * win32/common/libgstreamer.def: + Add gst_poll_fd_init to the list of symbols. + +2008-02-29 12:41:33 +0000 Sebastian Dröge + + Correct all relevant warnings found by the sparse semantic code analyzer. This include marking several symbols static... + Original commit message from CVS: + * gst/gstconfig.h.in: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_read_buffer): + * libs/gst/check/gstcheck.c: (gst_check_log_message_func), + (gst_check_log_critical_func), (gst_check_drop_buffers), + (gst_check_element_push_buffer_list): + * libs/gst/controller/gstcontroller.c: (gst_controller_get), + (gst_controller_get_type): + * libs/gst/controller/gsthelper.c: (gst_object_control_properties), + (gst_object_get_controller), (gst_object_get_control_source): + * libs/gst/controller/gstinterpolationcontrolsource.c: + (gst_interpolation_control_source_new): + * libs/gst/controller/gstlfocontrolsource.c: + (gst_lfo_control_source_new): + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_event_from_packet_0_2): + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstmultiqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * plugins/indexers/gstfileindex.c: (_file_index_id_save_xml), + (gst_file_index_add_association): + * plugins/indexers/gstmemindex.c: + * tests/benchmarks/gstpollstress.c: (mess_some_more): + * tests/check/elements/queue.c: (setup_queue): + * tests/check/gst/gstpipeline.c: + * tests/check/libs/collectpads.c: (setup), (teardown), + (gst_collect_pads_suite): + * tests/examples/adapter/adapter_test.c: + * tests/examples/metadata/read-metadata.c: (make_pipeline): + * tests/examples/xml/createxml.c: + * tests/examples/xml/runxml.c: + * tools/gst-inspect.c: + * tools/gst-run.c: + Correct all relevant warnings found by the sparse semantic code + analyzer. This include marking several symbols static, using + NULL instead of 0 for pointers, not using variable sized arrays + on the stack, moving variable declarations to the beginning of + a block and using "foo (void)" instead of "foo ()" for declarations. + +2008-02-29 12:05:55 +0000 Sebastian Dröge + + plugins/elements/: Don't reset GstPollFDs, this is not necessary at all. + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_update_fd): + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd): + Don't reset GstPollFDs, this is not necessary at all. + * tests/check/gst/gstpoll.c: (test_poll_wait), (GST_START_TEST), + (delayed_restart), (delayed_control): + Use GST_POLL_FD_INIT. + +2008-02-29 11:57:42 +0000 Wim Taymans + + gst/gstpoll.*: Added Since tags. + Original commit message from CVS: + * gst/gstpoll.c: (gst_poll_fd_init): + * gst/gstpoll.h: + Added Since tags. + * plugins/elements/gstfdsink.c: (gst_fd_sink_update_fd): + Use some more init macros. + +2008-02-29 11:20:01 +0000 Wim Taymans + + plugins/elements/: Use init macros and functions. + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_start): + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd): + Use init macros and functions. + +2008-02-29 11:00:43 +0000 Wim Taymans + + Add INIT macro and _init method for initializing the GstPollFD. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpoll.c: (gst_poll_fd_init): + * gst/gstpoll.h: + Add INIT macro and _init method for initializing the GstPollFD. + +2008-02-28 19:58:26 +0000 Sebastian Dröge + + Initialize some uninitialized variables as spotted by valgrind. + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_start), + (gst_fd_sink_update_fd): + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd): + * tests/check/gst/gstpoll.c: (test_poll_wait), (GST_START_TEST), + (delayed_restart), (delayed_control): + Initialize some uninitialized variables as spotted by valgrind. + +2008-02-28 15:25:59 +0000 Wim Taymans + + tests/benchmarks/: Add poll stress test. + Original commit message from CVS: + * tests/benchmarks/Makefile.am: + * tests/benchmarks/gstpollstress.c: (mess_some_more), (run_test), + (main): + Add poll stress test. + +2008-02-28 10:18:02 +0000 Peter Kjellerstedt + + plugins/elements/: Port to GstPoll. See #505417. + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * plugins/elements/gstfdsink.c: (gst_fd_sink_render), + (gst_fd_sink_start), (gst_fd_sink_stop), (gst_fd_sink_unlock), + (gst_fd_sink_unlock_stop), (gst_fd_sink_update_fd): + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd), + (gst_fd_src_start), (gst_fd_src_stop), (gst_fd_src_unlock), + (gst_fd_src_unlock_stop), (gst_fd_src_create), + (gst_fd_src_uri_set_uri): + * plugins/elements/gstfdsrc.h: + Port to GstPoll. See #505417. + +2008-02-27 21:18:33 +0000 Jan Schmidt + + win32/common/libgstreamer.def: Add new gst_poll_ symbols to win32 defs. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add new gst_poll_ symbols to win32 defs. + +2008-02-27 19:01:12 +0000 Wim Taymans + + Use a private stuct to not break ABI. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/net/gstnetclientclock.c: + (gst_net_client_clock_class_init), (gst_net_client_clock_init), + (gst_net_client_clock_finalize), (gst_net_client_clock_do_select), + (gst_net_client_clock_thread), (gst_net_client_clock_start), + (gst_net_client_clock_stop), (gst_net_client_clock_new): + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_class_init), (gst_net_time_provider_init), + (gst_net_time_provider_finalize), (gst_net_time_provider_thread), + (gst_net_time_provider_start), (gst_net_time_provider_stop), + (gst_net_time_provider_new): + * libs/gst/net/gstnettimeprovider.h: + Use a private stuct to not break ABI. + +2008-02-27 18:27:59 +0000 Peter Kjellerstedt + + libs/gst/net/: Massive code removal and cleanups because of GstPoll. + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_init), + (gst_net_client_clock_finalize), (gst_net_client_clock_do_select), + (gst_net_client_clock_thread), (gst_net_client_clock_start), + (gst_net_client_clock_stop), (gst_net_client_clock_new): + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimeprovider.c: (gst_net_time_provider_init), + (gst_net_time_provider_finalize), (gst_net_time_provider_thread), + (gst_net_time_provider_start), (gst_net_time_provider_stop), + (gst_net_time_provider_new): + * libs/gst/net/gstnettimeprovider.h: + Massive code removal and cleanups because of GstPoll. + Fixes #505417. + +2008-02-27 18:00:04 +0000 Wim Taymans + + configure.ac: Add checks for poll, ppoll and pselect. + Original commit message from CVS: + * configure.ac: + Add checks for poll, ppoll and pselect. + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + Add docs for GstPoll. + * gst/Makefile.am: + * gst/gst.h: + * gst/gstpoll.c: (find_index), (selectable_fds), + (pollable_timeout), (choose_mode), (pollfd_to_fd_set), + (fd_set_to_pollfd), (gst_poll_new), (gst_poll_free), + (gst_poll_set_mode), (gst_poll_get_mode), + (gst_poll_add_fd_unlocked), (gst_poll_add_fd), + (gst_poll_remove_fd), (gst_poll_fd_ctl_write), + (gst_poll_fd_ctl_read_unlocked), (gst_poll_fd_ctl_read), + (gst_poll_fd_has_closed), (gst_poll_fd_has_error), + (gst_poll_fd_can_read_unlocked), (gst_poll_fd_can_read), + (gst_poll_fd_can_write), (gst_poll_wait), + (gst_poll_set_controllable), (gst_poll_restart), + (gst_poll_set_flushing): + * gst/gstpoll.h: + Add generic poll abstraction. We ideally don't want to have this in core + here but in glib intead... + This code will be used in various network elements and ultimately for + the nanosecond precision monotonic clock (that's why it's here in core). + It'll allow us to implement cancelable socket operations for windows too. + * tests/check/Makefile.am: + * tests/check/gst/gstpoll.c: (test_poll_wait), (GST_START_TEST), + (delayed_stop), (delayed_restart), (delayed_flush), + (delayed_control), (gst_poll_suite): + Add GstPoll unit test. + +2008-02-25 15:37:36 +0000 Tim-Philipp Müller + + gst/gstfilter.c: Improve documentation of gst_filter_run(). Fixes #518627. + Original commit message from CVS: + * gst/gstfilter.c: + Improve documentation of gst_filter_run(). Fixes #518627. + +2008-02-23 16:03:37 +0000 Tim-Philipp Müller + + docs/README: Add a few lines about the new 'check-inspected-versions' target. + Original commit message from CVS: + * docs/README: + Add a few lines about the new 'check-inspected-versions' target. + +2008-02-21 10:30:50 +0000 Stefan Kost + + tests/check/gst/gstevent.c: Add qos to the event test. Rename tcase/tsuite; is not only about custom events. + Original commit message from CVS: + * tests/check/gst/gstevent.c: + Add qos to the event test. Rename tcase/tsuite; is not only about + custom events. + +2008-02-21 10:22:36 +0000 Stefan Kost + + plugins/elements/gstqueue.c: Ensure that buffer metadata is writeable, before modifying. Spotted by + Original commit message from CVS: + * plugins/elements/gstqueue.c: + Ensure that buffer metadata is writeable, before modifying. Spotted by + Mike. + +2008-02-20 15:44:33 +0000 Stefan Kost + + plugins/elements/gstqueue.*: When dropping buffers in leaky modes, mark next buffers we sent as + Original commit message from CVS: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + When dropping buffers in leaky modes, mark next buffers we sent as + DISCONT. + +2008-02-20 12:31:50 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesrc.c: Also, if mmap() fails that would be a READ error, not OPEN_READ. + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_map_region): + Also, if mmap() fails that would be a READ error, not OPEN_READ. + +2008-02-20 12:26:19 +0000 Tim-Philipp Müller + + plugins/elements/: Remove GstBufferStore, no idea why we were still building it. + Original commit message from CVS: + * plugins/elements/Makefile.am: + * plugins/elements/gstbufferstore.c: + * plugins/elements/gstbufferstore.h: + * plugins/elements/gsttypefindelement.h: + Remove GstBufferStore, no idea why we were still building it. + It's not used anywhere and superseded by GstAdapter. + * plugins/elements/gstfilesrc.c: (gst_file_src_map_region), + (gst_file_src_create_mmap): + * plugins/indexers/gstfileindex.c: (gst_file_index_add_association): + Printf format fixes for 64-bit integers. + +2008-02-19 13:00:14 +0000 Sebastian Dröge + + configure.ac: Don't set GST_CACHE_DIR and allow to set it by a configure parameter. + Original commit message from CVS: + * configure.ac: + Don't set GST_CACHE_DIR and allow to set it by a configure parameter. + We're not in 0.8 times anymore. + +2008-02-19 12:56:28 +0000 Jan Schmidt + + libs/gst/check/gstcheck.*: Make the declaration in the header for gst_check_element_push_buffer_list match the implem... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_drop_buffers), + (gst_check_element_push_buffer_list): + * libs/gst/check/gstcheck.h: + Make the declaration in the header for + gst_check_element_push_buffer_list match the implementation. + Fix up spelling, grammar and wording of the documentation in a few + places, and add the Since keyword to new API functions. + Use g_list_delete_link instead of g_list_remove in + gst_check_drop_buffers, since it's immeasurably more efficient. + * tests/check/elements/fakesrc.c: (GST_START_TEST): + Use new gst_check_drop_buffers function where appropriate. + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + Add new symbols gst_collect_pads_take_buffer, + gst_collect_pads_read_buffer, gst_index_set_resolver_full to the + exports + Changelog surgery to add API keyword to new gst_check API. + +2008-02-19 08:05:15 +0000 Sebastian Dröge + + gst/parse/lex._gst_parse_yy.pre.c: Update pre-generated flex files with flex 2.3.34. + Original commit message from CVS: + * gst/parse/lex._gst_parse_yy.pre.c: (yy_get_next_buffer), + (_gst_parse_yyensure_buffer_stack), (_gst_parse_yylex_init_extra): + Update pre-generated flex files with flex 2.3.34. + +2008-02-19 05:49:32 +0000 Sebastian Dröge + + gst/gstminiobject.c: Add FIXME for 0.11 to make GstMiniObjectClass::copy() a bit more friendly to subclasses and not ... + Original commit message from CVS: + * gst/gstminiobject.c: + Add FIXME for 0.11 to make GstMiniObjectClass::copy() a bit more + friendly to subclasses and not require them to know all internals + of their parent class. + +2008-02-15 13:15:17 +0000 Stefan Kost + + Add sub-buffer functions to collectpads. Fixes #516187. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + Add sub-buffer functions to collectpads. Fixes #516187. + API: gst_collect_pads_take_buffer(), gst_collect_pads_read_buffer() + +2008-02-15 12:33:00 +0000 Stefan Kost + + gst/gstbuffer.c: Copy selected buffer-flags when creating subbuffers. + Original commit message from CVS: + * gst/gstbuffer.c: + Copy selected buffer-flags when creating subbuffers. + Fixes #516395. + +2008-02-12 12:04:43 +0000 Sebastian Dröge + + Properly chain up finalize functions to the parent class. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_class_init), (gst_buffer_finalize): + * gst/gstevent.c: (gst_event_class_init), (gst_event_finalize): + * gst/gstmessage.c: (gst_message_class_init), + (gst_message_finalize): + * gst/gstquery.c: (gst_query_class_init), (gst_query_finalize): + * plugins/elements/gstfilesrc.c: (gst_mmap_buffer_class_init), + (gst_mmap_buffer_finalize): + Properly chain up finalize functions to the parent class. + +2008-02-11 17:53:57 +0000 Siavash Safi + + gst/gstindex.*: Add new function with option to dispose of user_data in resolver. + Original commit message from CVS: + Patch by: Siavash Safi + * gst/gstindex.c: (gst_index_finalize), (gst_index_set_resolver), + (gst_index_set_resolver_full): + * gst/gstindex.h: + Add new function with option to dispose of user_data in resolver. + Actually call the dispose function when finalizing the object and not + just when changing the resolver/filter. + API: GstIndex::gst_index_set_resolver_full() + * docs/gst/gstreamer-sections.txt: + Add new function to docs. Fixes #515469. + +2008-02-11 08:53:04 +0000 Sebastian Dröge + + gst/gstindex.c: Chain up finalize to the parent class. Fixes leaking the GstObject name and other things. + Original commit message from CVS: + * gst/gstindex.c: (gst_index_finalize): + Chain up finalize to the parent class. Fixes leaking the GstObject + name and other things. + +2008-02-10 19:48:04 +0000 Jan Schmidt + + * ChangeLog: + * common: + ChangeLog surgery: Fix Josep's surname in previous commits + Original commit message from CVS: + ChangeLog surgery: Fix Josep's surname in previous commits + +2008-02-08 00:54:28 +0000 Jan Schmidt + + 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. + * docs/faq/gst-uninstalled: + Add gst-plugins-gl + * docs/random/release: + Change one of the steps - we only upload core & base to Gnome FTP + +2008-02-06 12:21:05 +0000 Stefan Kost + + gst/gstconfig.h.in: Add 'id' for example. + Original commit message from CVS: + * gst/gstconfig.h.in: + Add 'id' for example. + * gst/gstpad.c: + * gst/gstutils.c: + * plugins/elements/gstfdsink.c: + Link to signals. Doc and comment fixes. + +2008-02-05 21:22:47 +0000 Tim-Philipp Müller + + gst/: Some minor docs fixes: fix typo, mention that GST_FLOW_RESEND is unused and unimplemented; finally, it is plugi... + Original commit message from CVS: + * gst/gstpad.h: (GST_PAD_LINK_SUCCESSFUL): + * gst/gstpluginfeature.h: (GstPluginFeatureClass): + Some minor docs fixes: fix typo, mention that GST_FLOW_RESEND is + unused and unimplemented; finally, it is plugin features, not + plugins, that have ranks. + +2008-02-05 19:42:31 +0000 Stefan Kost + + gst/gstpluginfeature.h: Clarify GstRank range docs. + Original commit message from CVS: + * gst/gstpluginfeature.h: + Clarify GstRank range docs. + +2008-02-05 18:37:08 +0000 David Schleef + + gst/gst.c: Add a separate gst_deinitialized that prevents gst_init() from being called after gst_deinit(). Fixes #50... + Original commit message from CVS: + * gst/gst.c: Add a separate gst_deinitialized that prevents + gst_init() from being called after gst_deinit(). Fixes #509559 + +2008-02-05 14:15:15 +0000 Sebastian Dröge + + Revert previous changes to the behaviour of GstPadTemplates, etc and the possiblity to call them in class_init as it ... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_base_init), + (gst_bin_class_init): + * gst/gstelement.c: (gst_element_base_class_init), + (gst_element_class_add_pad_template): + * gst/gstpadtemplate.c: (gst_pad_template_init): + * gst/gstpipeline.c: (gst_pipeline_get_type), + (gst_pipeline_base_init), (gst_pipeline_class_init): + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_type), + (gst_base_src_base_init), (gst_base_src_class_init): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_base_init), + (gst_capsfilter_class_init): + * plugins/elements/gstfakesink.c: (gst_fake_sink_base_init), + (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_base_init), + (gst_fake_src_class_init): + * plugins/elements/gstfdsink.c: (gst_fd_sink_base_init), + (gst_fd_sink_class_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_base_init), + (gst_fd_src_class_init): + * plugins/elements/gstfilesink.c: (gst_file_sink_base_init), + (gst_file_sink_class_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_base_init), + (gst_file_src_class_init): + * plugins/elements/gstidentity.c: (gst_identity_base_init), + (gst_identity_class_init): + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_base_init), + (gst_multi_queue_class_init): + * plugins/elements/gstqueue.c: (gst_queue_base_init), + (gst_queue_class_init): + * plugins/elements/gsttee.c: (gst_tee_base_init), + (gst_tee_class_init): + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_base_init), + (gst_type_find_element_class_init): + * tests/check/gst/gstelement.c: (gst_element_suite): + Revert previous changes to the behaviour of GstPadTemplates, etc + and the possiblity to call them in class_init as it breaks too + many elements. Reopens bug #491501. + Should be applied again for 0.11, thus added a few FIXME 0.11 at + several places. + +2008-02-05 09:24:18 +0000 Stefan Kost + + tools/gst-launch.c: Dump one graph per pipeline state-change and state change name (if GST_DEBUG_DUMP_DOT_DIR is set). + Original commit message from CVS: + * tools/gst-launch.c: + Dump one graph per pipeline state-change and state change name + (if GST_DEBUG_DUMP_DOT_DIR is set). + +2008-02-04 14:14:42 +0000 Thijs Vermeir + + Be sure that we have a new copy of the caps and not reffed caps from a template + Original commit message from CVS: + * gst/gstpad.c: + * tests/check/gst/gstpad.c: + Be sure that we have a new copy of the caps and not + reffed caps from a template + +2008-02-03 12:04:37 +0000 Sebastian Dröge + + Don't use base_init where not absolutely necessary. For example it's not necessary anymore for adding pad templates o... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_class_init): + * gst/gstpipeline.c: (gst_pipeline_get_type), + (gst_pipeline_class_init): + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_type), + (gst_base_sink_class_init): + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_type), + (gst_base_src_class_init): + * libs/gst/base/gstbasetransform.c: (gst_base_transform_get_type), + (gst_base_transform_class_init): + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_base_init), + (gst_collect_pads_class_init): + * libs/gst/base/gstdataqueue.c: (gst_data_queue_get_type): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_base_init), + (gst_net_time_provider_class_init): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_base_init), + (gst_capsfilter_class_init): + * plugins/elements/gstfakesink.c: (gst_fake_sink_base_init), + (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_base_init), + (gst_fake_src_class_init): + * plugins/elements/gstfdsink.c: (gst_fd_sink_base_init), + (gst_fd_sink_class_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_base_init), + (gst_fd_src_class_init): + * plugins/elements/gstfilesink.c: (gst_file_sink_base_init), + (gst_file_sink_class_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_base_init), + (gst_file_src_class_init): + * plugins/elements/gstidentity.c: (gst_identity_base_init), + (gst_identity_class_init): + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_base_init), + (gst_multi_queue_class_init): + * plugins/elements/gstqueue.c: (gst_queue_base_init), + (gst_queue_class_init): + * plugins/elements/gsttee.c: (gst_tee_base_init), + (gst_tee_class_init): + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_base_init), + (gst_type_find_element_class_init): + Don't use base_init where not absolutely necessary. For example it's + not necessary anymore for adding pad templates or setting element + details. + Leave empty base_init functions in several places as GST_BOILERPLATE + still defines and uses them. + +2008-02-03 10:48:01 +0000 Sebastian Dröge + + gst/: Make it possible (and recommended) to set element details and add pad templates in the class_init functions by ... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_base_class_init), + (gst_element_class_add_pad_template): + * gst/gstpadtemplate.c: + Make it possible (and recommended) to set element details and add + pad templates in the class_init functions by copying the details/pad + templates in GstElement's base_init. + Also make it possible to replace existing pad templates by adding + a new one with the same name. This was done in a hackish fashion + in same elements before already. + Don't reference pad templates that are added a second time. A + new pad template has a refcount of one and is not floating anymore + and to be owned by the element's class. Make this more explicit by + mentioning it in the docs of gst_element_class_add_pad_template(). + These changes are backwards compatible. Fixes bug #491501. + * tests/check/gst/gstelement.c: + Add unit test for setting element details, adding pad templates and + replacing them in a subclass. + +2008-02-02 06:48:37 +0000 Sebastian Dröge + + tools/gst-inspect.c: Fix a few memory leaks. + Original commit message from CVS: + * tools/gst-inspect.c: (print_interfaces), + (print_element_properties_info), (print_pad_info), + (print_signal_info), (print_element_info): + Fix a few memory leaks. + +2008-02-01 17:16:26 +0000 Thijs Vermeir + + Add more functions for unit testing: gst_check_drop_buffers, gst_check_caps_equal, gst_check_element_push_buffer_list... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + Add more functions for unit testing: gst_check_drop_buffers, + gst_check_caps_equal, gst_check_element_push_buffer_list, + gst_check_element_push_buffer + +2008-02-01 16:37:22 +0000 Julien Moutte + + docs/gst/gstreamer-sections.txt: Add GST_CHECK_VERSION to the docs + Original commit message from CVS: + 2008-02-01 Julien Moutte + * docs/gst/gstreamer-sections.txt: Add GST_CHECK_VERSION to the + docs + * gst/gstindex.c: (gst_index_class_init), + (gst_index_free_writer), + (gst_index_finalize), (gst_index_entry_free), + (gst_index_add_association): Fix memory leaks. + * gst/gstversion.h.in: Add GST_CHECK_VERSION macro. + * plugins/indexers/gstmemindex.c: (gst_mem_index_class_init), + (gst_mem_index_free_format), (gst_mem_index_free_id), + (gst_mem_index_finalize): Fix memory leaks. + * win32/common/config.h: Updated to CVS HEAD. + +2008-02-01 12:25:17 +0000 Stefan Kost + + docs/README: Some more details about how the plugin docs works. + Original commit message from CVS: + * docs/README: + Some more details about how the plugin docs works. + * docs/plugins/gstreamer-plugins-sections.txt: + Whitespace cleanup. + +2008-02-01 12:10:17 +0000 Stefan Kost + + gst/parse/: Add delayed set-property. This allows to set properties on dynamicaly created objects (pads in videomxer). + Original commit message from CVS: + * gst/parse/grammar.tab.pre.c: + * gst/parse/grammar.tab.pre.h: + * gst/parse/grammar.y: + * gst/parse/lex._gst_parse_yy.pre.c: + Add delayed set-property. This allows to set properties on dynamicaly + created objects (pads in videomxer). + +2008-02-01 11:27:32 +0000 Thijs Vermeir + + gst/gstutils.c: Check if caps are not NULL (fix bug #510194) + Original commit message from CVS: + * gst/gstutils.c: + Check if caps are not NULL (fix bug #510194) + +2008-02-01 10:27:10 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Add fixme regarding EOS in pull mode. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_loop), + (gst_base_sink_get_position_paused): + Add fixme regarding EOS in pull mode. + Fix position reporting in PAUSED for negative rates. + +2008-02-01 10:23:56 +0000 Wim Taymans + + gst/gstminiobject.c: When replacing a miniobject, do a quick equality check first so that we can avoid a ref/unref pair. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_mini_object_replace): + When replacing a miniobject, do a quick equality check first so that we + can avoid a ref/unref pair. + +2008-02-01 10:17:40 +0000 Wim Taymans + + docs/design/part-synchronisation.txt: Update some docs. + Original commit message from CVS: + * docs/design/part-synchronisation.txt: + Update some docs. + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/gstmultiqueue.c: + Add multiqueue to the docs. + +2008-01-30 14:38:43 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.17 === + +2008-01-30 14:05:45 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + Release 0.10.17 + Original commit message from CVS: + Release 0.10.17 + +2008-01-30 13:13:49 +0000 Jan Schmidt + + * ChangeLog: + add ChangeLog entry for previous commit + Original commit message from CVS: + add ChangeLog entry for previous commit + +2008-01-30 13:12:24 +0000 Jan Schmidt + + gst/gstutils.c: Check if caps are not NULL (fix bug #510194) + Original commit message from CVS: + * gst/gstutils.c: + Check if caps are not NULL (fix bug #510194) + +2008-01-30 12:55:42 +0000 Thijs Vermeir + + gst/gstutils.c: Check if caps are not NULL (fix bug #510194) + Original commit message from CVS: + * gst/gstutils.c: + Check if caps are not NULL (fix bug #510194) + +2008-01-30 12:44:13 +0000 Cygwin Ports maintainer + + gst/gstutils.c: Fix compilation on systems that have posix timers but no monotonic clock. + Original commit message from CVS: + * gst/gstutils.c: + Fix compilation on systems that have posix timers but no + monotonic clock. + Fixes: #512715 + Patch By: Cygwin Ports maintainer + +2008-01-30 12:39:51 +0000 Jan Schmidt + + tools/gst-inspect.c: Revert previous commit in preparation for an impromptu 0.10.17 release + Original commit message from CVS: + * tools/gst-inspect.c: + Revert previous commit in preparation for an impromptu 0.10.17 release + +2008-01-29 09:43:11 +0000 Sebastian Dröge + + tools/gst-inspect.c: Fix a few memory leaks. + Original commit message from CVS: + * tools/gst-inspect.c: (print_interfaces), + (print_element_properties_info), (print_pad_info), + (print_signal_info), (print_element_info): + Fix a few memory leaks. + +2008-01-28 23:30:45 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.16 === + +2008-01-28 23:27:13 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.interfaces: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * po/LINGUAS: + * win32/common/config.h: + Release 0.10.16 + Original commit message from CVS: + Release 0.10.16 + +2008-01-28 21:20:16 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-01-24 23:28:54 +0000 Tim-Philipp Müller + + configure.ac: Use AC_TRY_COMPILE instead of AC_TRY_RUN to check for _POSIX_TIMER, _POSIX_MONOTONIC_CLOCK, etc. Makes ... + Original commit message from CVS: + * configure.ac: + Use AC_TRY_COMPILE instead of AC_TRY_RUN to check for + _POSIX_TIMER, _POSIX_MONOTONIC_CLOCK, etc. Makes configure + not fail when trying to crosscompile on OpenEmbedded (#511750). + +2008-01-20 17:08:54 +0000 Sebastian Dröge + + docs/manuals.mak: Use $(MAKE) instead of make to fix the build if GNU make is called different. Fixes bug #510747. + Original commit message from CVS: + * docs/manuals.mak: + Use $(MAKE) instead of make to fix the build if GNU make is + called different. Fixes bug #510747. + +2008-01-20 15:04:33 +0000 Tim-Philipp Müller + + gst/gstplugin.c: Fix old-style static plugins via GST_PLUGIN_DEFINE_STATIC again, which I broke two commits ago when ... + Original commit message from CVS: + * gst/gstplugin.c: (_gst_plugin_initialize): + Fix old-style static plugins via GST_PLUGIN_DEFINE_STATIC + again, which I broke two commits ago when changing the API + of gst_plugin_register_static(): the g_list_foreach() in + _gst_plugin_register_static still assumed the old function + signature and would therefore fail (re-fixes #510187). + * gst/gstplugin.c: (_num_static_plugins), (_static_plugins), + (_gst_plugin_register_static), (gst_plugin_register_static): + Revert the (technically correct) change to call g_thread_init() from + the pre-main() constructor. This will break programs which call + g_thread_init() without an if (!g_thread_supported()) guard in their + main function. We could just blame it on GLib or the application, but + it's probably best to just avoid this altogether and simply not use + any GLib functions here and use plain old malloc() with a simple + array to store the plugins to register later when gst_init() is + finally called (re-fixes #510187). + * tests/check/gst/gstplugin.c: (GST_GNUC_CONSTRUCTOR_DEFINED), + (GST_GNUC_CONSTRUCTOR_DEFINED), (plugin_init_counter), + (plugin1_init), (plugin2_init), (plugin3_init), (GST_START_TEST), + (GST_START_TEST), (gst_plugin_suite): + Dumb unit test to make sure the old GST_PLUGIN_DEFINE_STATIC still + works. + +2008-01-17 22:22:58 +0000 Tim-Philipp Müller + + gst/gstplugin.h: Remove deprecation guards around GST_PLUGIN_DEFINE_STATIC. + Original commit message from CVS: + * gst/gstplugin.h: (GST_PLUGIN_DEFINE_STATIC): + Remove deprecation guards around GST_PLUGIN_DEFINE_STATIC. + This makes gtk-doc complain, but results in slightly better + compiler errors. The old _gst_plugin_register_static() is + still guarded, so there'll be a compiler warning about that + instead. Fixes #510187 too. + +2008-01-17 22:17:15 +0000 Tim-Philipp Müller + + gst/: Change API of gst_plugin_register_static() to not take a GstPluginDesc, but rather just take all the arguments ... + Original commit message from CVS: + * gst/gst.c: (init_post): + * gst/gstplugin.c: (_gst_plugin_register_static), + (gst_plugin_register_static), (_gst_plugin_initialize): + * gst/gstplugin.h: (GstPluginFilter): + Change API of gst_plugin_register_static() to not take + a GstPluginDesc, but rather just take all the arguments + in a GstPluginDesc directly. This is more intuitive and + avoids certain mistakes when porting code from + GST_PLUGIN_DEFINE_STATIC to gst_plugin_register_static(). + Fixes #510187. + * tests/check/gst/gstplugin.c: + Fix up for changed API. + +2008-01-17 18:50:31 +0000 Thomas Vander Stichele + + docs/faq/legal.xml: Update FAQ, Totem actually has an exception these days. + Original commit message from CVS: + * docs/faq/legal.xml: + Update FAQ, Totem actually has an exception these days. + +2008-01-14 22:20:44 +0000 Jan Schmidt + + win32/common/libgstreamer.def: Add new API declarations + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add new API declarations + +2008-01-14 13:18:37 +0000 Stefan Kost + + gst/gstminiobject.c: Spelling fixes for the API docs. + Original commit message from CVS: + * gst/gstminiobject.c: + Spelling fixes for the API docs. + +2008-01-14 11:47:32 +0000 Jan Schmidt + + * ChangeLog: + Add API keyword for gst_util_get_timestamp, and remove the tag for GST_GET_TIMESTMAP which didn't survive. + Original commit message from CVS: + Add API keyword for gst_util_get_timestamp, and remove the tag for GST_GET_TIMESTMAP which didn't survive. + +2008-01-14 11:40:55 +0000 Stefan Kost + + libs/gst/base/gstbasetransform.c: Fix long property description for QoS. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + Fix long property description for QoS. + +2008-01-12 20:22:30 +0000 Jan Schmidt + + gst/gst.c: _gst_trace_on is already provided by gsttrace.h, no need to declare it ourselves. + Original commit message from CVS: + * gst/gst.c: + _gst_trace_on is already provided by gsttrace.h, no need to declare + it ourselves. + * docs/libs/gstreamer-libs-sections.txt: + Add 'buffers', 'check_cond' and 'check_mutex' from libgstcheck + and remove strange tcase_add_test which is outputting a warning. + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + Properly declare 'buffers', 'check_cond', 'check_mutex' extern + and define them in gstcheck.c instead of having every .c file whcih + includes gstcheck.h be defining its own copy and relying on symbol + interposing to marry them all, which doesn't work on Solaris. + * tests/check/elements/identity.c: (GST_START_TEST): + Don't define 'buffers' locally, it comes from libgstcheck. + * tests/check/generic/sinks.c: (send_buffer): + Fix type of variable (GstFlowReturn, not GstStateChangeReturn) + * tests/check/gst/gststructure.c: (GST_START_TEST): + * tests/check/gst/gstsystemclock.c: (GST_START_TEST): + * tests/check/gst/gstutils.c: (GST_START_TEST): + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Add a bunch of casts to make various constants fit the types + they're being assigned to. + +2008-01-10 21:06:58 +0000 Stefan Kost + + gst/gstchildproxy.c: Improve docs and add some ideas for making this more general-purpose. + Original commit message from CVS: + * gst/gstchildproxy.c: + Improve docs and add some ideas for making this more general-purpose. + +2008-01-10 15:55:32 +0000 Tim-Philipp Müller + + gst/gst_private.h: Add GST_CAT_TYPES, for consistency, and so that the other debug categories don't make fun of it. S... + Original commit message from CVS: + * gst/gst_private.h: (GST_CAT_TYPES): + Add GST_CAT_TYPES, for consistency, and so that the other + debug categories don't make fun of it. Spotted by Saur on IRC. + +2008-01-10 13:03:35 +0000 Sebastian Dröge + + gst/parse/Makefile.am: Move types.h from EXTRA_DIST to noinst_HEADERS. + Original commit message from CVS: + * gst/parse/Makefile.am: + Move types.h from EXTRA_DIST to noinst_HEADERS. + +2008-01-10 12:14:04 +0000 Sebastian Dröge + + 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-09 18:23:39 +0000 Tim-Philipp Müller + + API: add gst_plugin_register_static() and deprecate + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: (init_post): + * gst/gstplugin.c: (_gst_plugin_register_static), + (gst_plugin_register_static), (_gst_plugin_initialize), + (gst_plugin_register_func): + * gst/gstplugin.h: (GST_PLUGIN_DEFINE_STATIC): + API: add gst_plugin_register_static() and deprecate + GST_PLUGIN_DEFINE_STATIC, since it's not portable + (#498924). + Also, in _gst_plugin_register_static(), make sure to call + g_thread_init() before calling GLib functions such as + g_list_append() if we're not initialised yet, since that + may lead to random crashes with older GSlice/GLib versions. + * tests/check/gst/gstplugin.c: + Adapt unit test to above changes. + +2008-01-09 16:36:34 +0000 Tim-Philipp Müller + + gst/: Yet another gratuitous GString micro-optimisation: add a (private) function that serialises a structure appendi... + Original commit message from CVS: + * gst/gst_private.h: (STRUCTURE_ESTIMATED_STRING_LEN): + * gst/gstcaps.c: (gst_caps_to_string): + * gst/gststructure.c: (GST_ASCII_IS_STRING), + (priv_gst_structure_append_to_gstring), (gst_structure_to_string): + Yet another gratuitous GString micro-optimisation: add a (private) + function that serialises a structure appending to an existing + GString, so that when we serialise caps we don't need to alloc+free + a throwaway GString for each structure (each of which also entailing + multiple reallocs on the way); also use g_string_sized_new() in + various places with an approximate string length to avoid reallocs + within GString. See #500143. + +2008-01-09 15:05:21 +0000 Tim-Philipp Müller + + gst/gststructure.c: Always check UTF-8 conformance of structure strings and not only if the debugging system is enabl... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_id_set_value): + Always check UTF-8 conformance of structure strings and not only + if the debugging system is enabled; reasoning: the behaviour of + the actual code shouldn't really change depending on whether the + debugging system is enabled or not (#508291). + +2008-01-09 13:48:03 +0000 Stefan Kost + + Makefile.am: Remove old coverage target in favour of "make lcov". + Original commit message from CVS: + * Makefile.am: + Remove old coverage target in favour of "make lcov". + +2008-01-09 12:25:17 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: The start segment for reverse playback goes from start to last_stop. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_loop): + The start segment for reverse playback goes from start to last_stop. + +2008-01-09 12:22:22 +0000 Peter Kjellerstedt + + gst/gstclock.h: Cast the results from the timeval/spec_to_time macros to what the docs say it casts to, a GstClockTim... + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * gst/gstclock.h: + Cast the results from the timeval/spec_to_time macros to what the + docs say it casts to, a GstClockTime. fixes #508175. + +2008-01-09 12:19:31 +0000 Wim Taymans + + gst/gstbuffer.c: Update some comments. + Original commit message from CVS: + * gst/gstbuffer.c: + Update some comments. + * tools/gst-inspect.c: (print_element_properties_info): + Improve printing of flags. + +2008-01-08 21:13:58 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasetransform.c: Print element name with g_warning() if there's a problem with the unit size. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_size): + Print element name with g_warning() if there's a problem + with the unit size. + +2008-01-08 02:07:38 +0000 Damien Lespiau + + libs/gst/: Fix empty prototypes. Fixes bug #507957. + Original commit message from CVS: + Patch by: Damien Lespiau + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrolsource.h: + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/dataprotocol/dataprotocol.h: + Fix empty prototypes. Fixes bug #507957. + +2008-01-08 02:01:34 +0000 David Schleef + + docs/faq/dependencies.xml: Fix typo. + Original commit message from CVS: + * docs/faq/dependencies.xml: Fix typo. + +2008-01-07 11:23:00 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Don't update the last_stop position in do_seek, that's the position we did a seek to. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_do_seek), + (gst_base_src_loop): + Don't update the last_stop position in do_seek, that's the position we + did a seek to. + Read backwards when we have a negative rate. + * tests/check/elements/filesrc.c: (event_func), (wait_eos), + (setup_filesrc), (cleanup_filesrc), (GST_START_TEST), + (filesrc_suite): + Add check for reverse reading. + +2008-01-07 09:47:49 +0000 Alexis Ballier + + tests/check/: Decide which header to include based on the userland ABI target and not the kernel/cpu. Fix up structur... + Original commit message from CVS: + Patch by: Alexis Ballier + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_ppc64.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_ppc64.h: + Decide which header to include based on the userland ABI target + and not the kernel/cpu. Fix up structure sizes of ppc64 header + for 64-bit userland (#503590). Might need something similar for + x86 too. + +2008-01-05 13:45:22 +0000 Tim-Philipp Müller + + gst/gstdebugutils.c: Log the reason why fopen fails in addition to the fact that it failed. + Original commit message from CVS: + * gst/gstdebugutils.c: (_gst_debug_bin_to_dot_file): + Log the reason why fopen fails in addition to the fact that it failed. + +2008-01-04 18:44:03 +0000 Sebastian Dröge + + gst/parse/parse.l: Use "%option never-interactive" to prevent useless calls to isatty() on every input when parsing. ... + Original commit message from CVS: + * gst/parse/parse.l: + Use "%option never-interactive" to prevent useless calls to isatty() + on every input when parsing. Also use "%option noinput" to not define + the static input/yyinput functions which we don't use anyway. This + removes a compiler warning with gcc 4.3 and saves some bytes in the + library. + * gst/parse/lex._gst_parse_yy.pre.c: + Regenerated for the above change. + +2008-01-04 18:39:15 +0000 Wim Taymans + + gst/gstpad.c: Don't crash when trying to fixate and empty list. + Original commit message from CVS: + * gst/gstpad.c: (fixate_value): + Don't crash when trying to fixate and empty list. + Fixes #506643. + +2008-01-03 09:43:41 +0000 Sebastian Dröge + + docs/faq/gst-uninstalled: Clarify the comments to make the usage of this script and what it does easier to understand. + Original commit message from CVS: + * docs/faq/gst-uninstalled: + Clarify the comments to make the usage of this script and what it + does easier to understand. + +2008-01-01 17:10:32 +0000 Thijs Vermeir + + tools/gst-plot-timeline.py: Add more options to gst-plot-timeline + Original commit message from CVS: + * tools/gst-plot-timeline.py: + Add more options to gst-plot-timeline + +2007-12-31 19:11:39 +0000 Wim Taymans + + docs/design/part-synchronisation.txt: Some more info on how the stream_time in GstBaseSink is done. + Original commit message from CVS: + * docs/design/part-synchronisation.txt: + Some more info on how the stream_time in GstBaseSink is done. + +2007-12-30 13:36:30 +0000 Tim-Philipp Müller + + * ChangeLog: + ChangeLog surgery: remove bogus changelog entry + Original commit message from CVS: + ChangeLog surgery: remove bogus changelog entry + +2007-12-30 13:31:17 +0000 Tim-Philipp Müller + + tests/check/generic/sinks.c: Put back the tcase_set_timeout(), apparently it's needed after all; fix it up in a way t... + Original commit message from CVS: + * tests/check/generic/sinks.c: (gst_sinks_suite): + Put back the tcase_set_timeout(), apparently it's needed after + all; fix it up in a way that makes things work with valgrind too. + +2007-12-30 12:22:49 +0000 Thijs Vermeir + + gst/gstdebugutils.c: add warning when failed to open file for writing + Original commit message from CVS: + * gst/gstdebugutils.c: + add warning when failed to open file for writing + +2007-12-28 14:34:34 +0000 Laurent Glayal + + gst/gstvalue.c: Optimisation: bail out of the loop as early as possible (#500143). + Original commit message from CVS: + Based on patch by: Laurent Glayal + * gst/gstvalue.c: (gst_value_is_fixed): + Optimisation: bail out of the loop as early as possible (#500143). + +2007-12-28 14:15:53 +0000 Tim-Philipp Müller + + gst/: Bunch of gratuitous nano-optimisations. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_to_string): + * gst/gstinfo.c: (gst_debug_construct_term_color): + * gst/gstparse.c: (gst_parse_launchv): + * gst/gstutils.c: (gst_util_dump_mem): + * gst/gstvalue.c: (gst_value_serialize_any_list), + (gst_value_transform_any_list_string): + Bunch of gratuitous nano-optimisations. + +2007-12-28 13:57:05 +0000 Tim-Philipp Müller + + tests/check/generic/sinks.c: Fix leak in unit test (bus sync handler must unref the message if it returns GST_BUS_DRO... + Original commit message from CVS: + * tests/check/generic/sinks.c: (async_done_func), + (async_done_eos_func): + Fix leak in unit test (bus sync handler must unref the message + if it returns GST_BUS_DROP). Don't fiddle with the default test + timeout, this is smaller than the current preconfigured value + via CK_DEFAULT_TIMEOUT, and also breaks things with valgrind + because it overrides the value specified in CK_DEFAULT_TIMEOUT. + +2007-12-24 19:21:32 +0000 Wim Taymans + + * ChangeLog: + Add bug that was fixed with last commit. + Original commit message from CVS: + Add bug that was fixed with last commit. + +2007-12-24 19:11:29 +0000 Laurent Glayal + + configure.ac: Check for stdio_ext.h for the filesink changes. + Original commit message from CVS: + Based on Patch by: Laurent Glayal + * configure.ac: + Check for stdio_ext.h for the filesink changes. + * plugins/elements/gstfilesink.c: (buffer_mode_get_type), + (gst_file_sink_class_init), (gst_file_sink_init), + (gst_file_sink_dispose), (gst_file_sink_set_property), + (gst_file_sink_get_property), (gst_file_sink_open_file), + (gst_file_sink_close_file): + * plugins/elements/gstfilesink.h: + Add two properties to control the buffering mode and size. + API: GstFileSink::buffer-mode + API: GstFileSink::buffer-size + +2007-12-24 14:35:24 +0000 Wim Taymans + + gst/gstsystemclock.c: Add some more docs to explain why a FIXME was wrongly added. + Original commit message from CVS: + * gst/gstsystemclock.c: (gst_system_clock_id_wait_jitter_unlocked): + Add some more docs to explain why a FIXME was wrongly added. + +2007-12-22 12:48:26 +0000 Sebastian Dröge + + gst/gstobject.c: Fix typo in the gst_object_{ref,unref} documentation. + Original commit message from CVS: + * gst/gstobject.c: + Fix typo in the gst_object_{ref,unref} documentation. + +2007-12-21 21:17:32 +0000 Tim-Philipp Müller + + tests/check/: Don't use GST_PLUGIN_DEFINE_STATIC, it is not portable and is going to be deprecated (see #498924). + Original commit message from CVS: + * tests/check/libs/controller.c: + * tests/check/libs/typefindhelper.c: + * tests/check/pipelines/parse-launch.c: + Don't use GST_PLUGIN_DEFINE_STATIC, it is not portable and is + going to be deprecated (see #498924). + +2007-12-21 20:58:23 +0000 Tim-Philipp Müller + + gst/gsttypefind.c: Make gst_type_find_register work for static typefind functions, ie. allow passing plugin == NULL (... + Original commit message from CVS: + * gst/gsttypefind.c: (gst_type_find_register): + Make gst_type_find_register work for static typefind functions, + ie. allow passing plugin == NULL (prerequisite for #498924). + * gst/gstelementfactory.c: (gst_element_register): + Small docs addition. + +2007-12-21 13:54:07 +0000 Wim Taymans + + gst/gstpad.c: Really unlink the peer pad instead of setting the peer pointer to NULL when we dispose the pad. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_dispose): + Really unlink the peer pad instead of setting the peer pointer to NULL + when we dispose the pad. + This correctly calls the unlink functions and makes sure that the peer + does not have a handle to invalid memory. See #504671. + * tests/check/gst/gstpad.c: (GST_START_TEST), (gst_pad_suite): + Add testsuite for above case. + +2007-12-20 09:20:27 +0000 Peter Kjellerstedt + + libs/gst/check/gstcheck.h: Fix detection of the check version we're compiling against (would otherwise break if check... + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * libs/gst/check/gstcheck.h: + Fix detection of the check version we're compiling against (would + otherwise break if check goes v0.10.0); correctly report the + name of the failed test again in case of failure, instead of + just 'tf' (fixes #504499). + +2007-12-19 17:49:38 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Allow sending EOS to the source to make it send out an EOS event from the streaming thread. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_send_event), + (gst_base_src_get_range), (gst_base_src_pad_get_range), + (gst_base_src_loop), (gst_base_src_set_flushing), + (gst_base_src_change_state): + Allow sending EOS to the source to make it send out an EOS event from + the streaming thread. + Update docs and deprecate the old NULL/READY shutdown method. + * tests/check/libs/basesrc.c: (GST_START_TEST), + (gst_basesrc_suite): + Add unit test for controlled shutdown. + +2007-12-19 12:48:18 +0000 Wim Taymans + + docs/design/part-synchronisation.txt: Small updates. + Original commit message from CVS: + * docs/design/part-synchronisation.txt: + Small updates. + * gst/gstsegment.c: (gst_segment_set_seek), + (gst_segment_set_newsegment_full), (gst_segment_to_stream_time), + (gst_segment_to_running_time): + The seek format can be different from the segment format when the start + and stop values are not to be updated, when we only do a rate change for + example. + * tests/check/gst/gstsegment.c: (GST_START_TEST), + (gst_segment_suite): + Add a testcase for the rate-only seeks, checking that the format is + correctly ignored when start and stop are not updated. + +2007-12-18 13:38:31 +0000 Sebastian Dröge + + * ChangeLog: + ChangeLog surgery, gstenumtypes.c changes were not committed because there were none + Original commit message from CVS: + * ChangeLog surgery, gstenumtypes.c changes were not committed because there were none + +2007-12-18 13:18:35 +0000 Matthias Bolte + + win32/common/gstenumtypes.c: Some indention fixes by gst-indent. + Original commit message from CVS: + * win32/common/gstenumtypes.c: (register_gst_buffer_flag), + (register_gst_buffer_copy_flags), (register_gst_clock_flags), + (register_gst_debug_graph_details), + (register_gst_state_change_return), (register_gst_state_change), + (register_gst_element_flags), (register_gst_core_error), + (register_gst_library_error), (register_gst_resource_error), + (register_gst_stream_error), (register_gst_event_type_flags), + (register_gst_event_type), (register_gst_index_entry_type), + (register_gst_assoc_flags), (register_gst_message_type), + (register_gst_mini_object_flags), (register_gst_pad_link_return), + (register_gst_flow_return), (register_gst_pad_template_flags), + (register_gst_pipeline_flags), (register_gst_plugin_error), + (register_gst_tag_merge_mode), (register_gst_alloc_trace_flags), + (register_gst_type_find_probability), (register_gst_parse_error): + Some indention fixes by gst-indent. + Patch by: Matthias Bolte + * win32/vs8/grammar.vcproj: + * win32/vs8/libgstcontroller.vcproj: + * win32/vs8/libgstreamer.vcproj: + Fix compilation with VS8 and include some missing files. + +2007-12-18 12:03:18 +0000 Tim-Philipp Müller + + gst/gsttaglist.c: Small docs addition: mention that the strings returned by gst_tag_list_get_string*() are in UTF-8 e... + Original commit message from CVS: + * gst/gsttaglist.c: + Small docs addition: mention that the strings returned by + gst_tag_list_get_string*() are in UTF-8 encoding. + +2007-12-17 19:59:42 +0000 Tim-Philipp Müller + + Makefile.am: The check-exports stuff moved to common/win32.mak, so include that. + Original commit message from CVS: + * Makefile.am: + The check-exports stuff moved to common/win32.mak, so include that. + +2007-12-17 16:38:40 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Make _wait_playing() not check any variables so that we can call this function from subcl... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing), + (gst_base_src_perform_seek), (gst_base_src_get_range), + (gst_base_src_set_playing), (gst_base_src_change_state): + Make _wait_playing() not check any variables so that we can call this + function from subclasses. Move the checks elsewhere similar to + _wait_preroll() in basesink. + Add some debugging. + Only signal the LIVE cond when we are going back to PLAYING. + +2007-12-16 18:29:25 +0000 Tim-Philipp Müller + + gst/gstregistrybinary.c: Use g_remove() and g_rename(). Check result of g_rename(), and don't leak the open file desc... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write_cache): + Use g_remove() and g_rename(). Check result of g_rename(), and + don't leak the open file descriptor if we error out when writing. + * gst/gstregistryxml.c: (load_plugin), (gst_registry_xml_write_cache): + Must check the return value of close() after writing out the new + registry file. Sometimes write problems such as out-of-diskspace + are only reported when the file is closed and not already during + the write. This may have caused partial/broken registry files in + some rare circumstances. Should fix #503675. + +2007-12-16 17:37:11 +0000 Edward Hervey + + docs/: Ignore files generated by new common/* modifications + Original commit message from CVS: + * docs/gst/.cvsignore: + * docs/libs/.cvsignore: + * docs/plugins/.cvsignore: + Ignore files generated by new common/* modifications + +2007-12-15 15:19:32 +0000 Stefan Kost + + win32/common/libgstbase.def: Yes, you can also have a if you want. + Original commit message from CVS: + * win32/common/libgstbase.def: + Yes, you can also have a if you want. + +2007-12-15 14:58:59 +0000 Stefan Kost + + win32/common/libgstbase.def: Add new basetransform API to win export file. + Original commit message from CVS: + * win32/common/libgstbase.def: + Add new basetransform API to win export file. + +2007-12-15 14:42:25 +0000 Stefan Kost + + tests/check/gst/gstbin.c: Adjust the test to the refcount change two days ago. + Original commit message from CVS: + * tests/check/gst/gstbin.c: + Adjust the test to the refcount change two days ago. + +2007-12-14 21:36:50 +0000 David Schleef + + docs/faq/getting.xml: Fix typo. + Original commit message from CVS: + * docs/faq/getting.xml: Fix typo. + +2007-12-14 16:52:38 +0000 Sebastian Dröge + + API: Add gst_base_transform_set_gap_aware() to control whether the element correctly handles GST_BUFFER_FLAG_GAP or s... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_set_gap_aware): + * libs/gst/base/gstbasetransform.h: + API: Add gst_base_transform_set_gap_aware() to control whether + the element correctly handles GST_BUFFER_FLAG_GAP or shouldn't + get buffers with this flag at all. Fixes #503231. + +2007-12-13 16:49:54 +0000 Stefan Kost + + libs/gst/base/: Replace gst_pad_get_parent by GST_OBJECT_PARENT inside streaming thread. Correct log message in gstba... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasetransform.c: + Replace gst_pad_get_parent by GST_OBJECT_PARENT inside streaming + thread. Correct log message in gstbasesrc.c. + +2007-12-13 13:59:04 +0000 Tim-Philipp Müller + + gst/gstutils.c: Fix possible compiler warning (#503417). + Original commit message from CVS: + * gst/gstutils.c: (element_find_unconnected_pad): + Fix possible compiler warning (#503417). + +2007-12-13 11:41:05 +0000 Tim-Philipp Müller + + gst/gstobject.c: Don't use GST_CAT_EVENT here for logging, it makes no sense. + Original commit message from CVS: + * gst/gstobject.c: (gst_object_dispatch_properties_changed): + Don't use GST_CAT_EVENT here for logging, it makes no sense. + +2007-12-13 10:31:33 +0000 Sebastian Dröge + + tools/gst-inspect.c: Add support for GstFraction properties. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + Add support for GstFraction properties. + +2007-12-12 23:20:00 +0000 Tim-Philipp Müller + + Makefile.am: Add check-exports target and run it as part of 'make check' (see #499140 and #493983). + Original commit message from CVS: + * Makefile.am: + Add check-exports target and run it as part of 'make check' + (see #499140 and #493983). + * gst/gst_private.h: + * gst/gstelementfactory.h: + * gst/gstghostpad.c: (gst_proxy_pad_class_init): + * gst/gstinfo.c: (_priv_gst_in_valgrind), (_gst_debug_init), + (_priv_gst_in_valgrind): + * gst/gstinfo.h: (GstLogFunction): + * gst/gsttypefind.c: (type_find_debug), (GST_CAT_DEFAULT), + (gst_type_find_register): + * gst/gsttypefindfactory.c: (type_find_debug), (GST_CAT_DEFAULT), + (gst_type_find_factory_get_type): + * libs/gst/controller/gstcontroller.c: (GST_CAT_DEFAULT), + (GST_CAT_DEFAULT), (parent_class), (priv_gst_controller_key), + (gst_controller_new_valist), (gst_controller_new_list), + (_gst_controller_dispose), (_gst_controller_class_init): + * libs/gst/controller/gstcontrolsource.c: (GST_CAT_DEFAULT): + * libs/gst/controller/gsthelper.c: (GST_CAT_DEFAULT), + (GST_CAT_DEFAULT), (gst_object_uncontrol_properties), + (gst_object_get_controller), (gst_object_set_controller), + (gst_object_suggest_next_sync), (gst_object_sync_values), + (gst_object_set_control_source), (gst_object_get_control_source), + (gst_object_get_value_arrays), (gst_object_get_value_array), + (gst_object_get_control_rate), (gst_object_set_control_rate): + * libs/gst/controller/gstinterpolation.c: (GST_CAT_DEFAULT): + * libs/gst/controller/lib.c: (GST_CAT_DEFAULT): + Make some functions that should be static static; rename some + private symbols so that they don't get exported; add some FIXME + comments so we can move accidentally exported functions into + our private section in 0.11. + * win32/common/libgstreamer.def: + Add gst_utils_get_timestamp(). + +2007-12-12 14:04:14 +0000 Stefan Kost + + gst/gstvalue.*: Add more missing "Since:" tags to docs. + Original commit message from CVS: + * gst/gstvalue.c: + * gst/gstvalue.h: + Add more missing "Since:" tags to docs. + +2007-12-12 06:58:56 +0000 Stefan Kost + + gst/gstutils.c: Add mising "Since:" to docs. + Original commit message from CVS: + * gst/gstutils.c: + Add mising "Since:" to docs. + +2007-12-11 22:03:58 +0000 Stefan Kost + + gst/gstplugin.c: Include "glib-compat-private.h" to fix the build on system with glib < 2.10. Fixes #503131. + Original commit message from CVS: + * gst/gstplugin.c: + Include "glib-compat-private.h" to fix the build on system with + glib < 2.10. Fixes #503131. + +2007-12-11 20:32:29 +0000 Stefan Kost + + gst/gstutils.*: Actually its not PURE as it gets the time from elsewhere. + Original commit message from CVS: + * gst/gstutils.c: + * gst/gstutils.h: + Actually its not PURE as it gets the time from elsewhere. + +2007-12-11 20:23:58 +0000 Stefan Kost + + Change GST_GET_TIMESTAMP into gst_util_get_timestamp and replace all uses as we don't have HAVE_POSIX_TIMERS in publi... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.h: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbasesink.c: + * tools/gst-launch.c: + Change GST_GET_TIMESTAMP into gst_util_get_timestamp and replace all + uses as we don't have HAVE_POSIX_TIMERS in public headers. + Thanks Tim for spotting. + +2007-12-11 15:29:26 +0000 Christian Schaller + + * gstreamer.spec.in: + update spec file by mirroring latest Fedora one + Original commit message from CVS: + update spec file by mirroring latest Fedora one + +2007-12-09 04:28:03 +0000 Sebastian Dröge + + 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 12:54:53 +0000 Tim-Philipp Müller + + gst/gststructure.c: Don't crash in _from_string() if the structure name is not valid (fixes #501560). Allow structur... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_validate_name), + (gst_structure_new_valist), (gst_structure_parse_value), + (gst_structure_from_string): + Don't crash in _from_string() if the structure name is not valid + (fixes #501560). Allow structure names to start with a number + again (this apparently broke the ubuntu codec installer). + * tests/check/gst/gststructure.c: (GST_START_TEST), (GST_START_TEST), + (GST_START_TEST): + Add unit test for the crash; update unit tests for new behaviour. + +2007-12-03 11:04:09 +0000 Wim Taymans + + gst/gstutils.c: Clarify gst_element_get_compatible_pad() documentation. + Original commit message from CVS: + * gst/gstutils.c: + Clarify gst_element_get_compatible_pad() documentation. + Fixes #500919. + +2007-12-02 20:33:49 +0000 Sebastian Dröge + + tests/check/Makefile.am: Don't forget to dist {gst,libs}/struct_hppa.h. + Original commit message from CVS: + * tests/check/Makefile.am: + Don't forget to dist {gst,libs}/struct_hppa.h. + +2007-11-28 13:02:30 +0000 Stefan Kost + + libs/gst/base/gstbasesink.c: Use new API to get elapsed time. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + Use new API to get elapsed time. + +2007-11-28 12:52:42 +0000 Stefan Kost + + gst/: Fix wrong order of args in GST_CLOCK_DIFF() usage. + Original commit message from CVS: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + Fix wrong order of args in GST_CLOCK_DIFF() usage. + * tools/gst-launch.c: + Use new API to get elapsed time. + +2007-11-28 12:35:14 +0000 Stefan Kost + + Rename new API + ChangeLog surgery to remove old name from last entry.. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.h: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + Rename new API + ChangeLog surgery to remove old name from last entry.. + API: GST_GET_TIMESTAMP + +2007-11-28 12:11:59 +0000 Stefan Kost + + Now hide the different clock stuff behind a macro. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.h: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + Now hide the different clock stuff behind a macro. + API: GST_GET_CURRENT_TIME + +2007-11-28 11:39:35 +0000 Stefan Kost + + Apply the posix-timer check from #361155. Conditionally use the posix timer for logging. This gives better timestamp ... + Original commit message from CVS: + * configure.ac: + * gst/gstdebugutils.c: + * gst/gstinfo.c: + Apply the posix-timer check from #361155. Conditionally use the posix + timer for logging. This gives better timestamp precission, less + overhead and no ntp jitter. + +2007-11-28 11:11:58 +0000 Sebastian Dröge + + gst/gstminiobject.c: Some cleanup and checking against invalid function parameters. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_mini_object_get_type), + (gst_mini_object_class_init), (gst_mini_object_copy_default), + (gst_mini_object_finalize), (gst_mini_object_copy), + (gst_mini_object_is_writable), (gst_mini_object_make_writable), + (gst_mini_object_replace), (param_mini_object_validate), + (gst_param_spec_mini_object_get_type): + Some cleanup and checking against invalid function parameters. + +2007-11-28 10:58:39 +0000 Wim Taymans + + Start merging in the easy bits of #361155, the monotonic clock patch. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.h: + * tests/check/gst/gstsystemclock.c: (GST_START_TEST), + (gst_systemclock_suite): + Start merging in the easy bits of #361155, the monotonic clock patch. + This one adds a few handy macros with docs and a testsuite. + +2007-11-27 18:45:38 +0000 Wim Taymans + + plugins/elements/gstfilesink.c: Be a bit smarter when seeking, like, don't try to do a seek when it's not needed. Thi... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_event): + Be a bit smarter when seeking, like, don't try to do a seek when it's + not needed. This avoids errors when the file is not seekable. + Fixes #499771. + +2007-11-26 13:16:00 +0000 Stefan Kost + + Due to popular request remove preset interface again. :-(. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstpreset.c: + * gst/gstpreset.h: + * plugins/elements/gstqueue.c: + Due to popular request remove preset interface again. :-(. + +2007-11-22 21:32:09 +0000 Stefan Kost + + tools/gst-inspect.c: Print 'default value' for enums and flags too. + Original commit message from CVS: + * tools/gst-inspect.c: + Print 'default value' for enums and flags too. + +2007-11-22 15:59:01 +0000 Stefan Kost + + docs/random/ensonic/profiling.txt: More ideas. + Original commit message from CVS: + * docs/random/ensonic/profiling.txt: + More ideas. + * gst/gstbin.c: + Fix typo and give better log output. + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + More ideas, make graphs a bit smaller and fix param name in macro. + +2007-11-22 13:56:24 +0000 Stefan Kost + + gst/gstpreset.c: Try harder to use the return value from fgets(). + Original commit message from CVS: + * gst/gstpreset.c: + Try harder to use the return value from fgets(). + +2007-11-21 16:08:25 +0000 Stefan Kost + + gst/gstpreset.c: For theses two fgets we handle the error below. + Original commit message from CVS: + * gst/gstpreset.c: + For theses two fgets we handle the error below. + +2007-11-21 13:47:52 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Only send upstream events upstream. Fixes #498746. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_send_event): + Only send upstream events upstream. Fixes #498746. + +2007-11-21 13:27:50 +0000 Laurent Glayal + + plugins/elements/gstidentity.*: Add property to disable handoff signal emission. Fixes #498694. + Original commit message from CVS: + Patch by: Laurent Glayal + * plugins/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_init), (gst_identity_transform_ip), + (gst_identity_set_property), (gst_identity_get_property): + * plugins/elements/gstidentity.h: + Add property to disable handoff signal emission. Fixes #498694. + API: GstIdentity::signal-handoffs + +2007-11-21 09:46:50 +0000 Julien Moutte + + docs/faq/gst-uninstalled: Yet another missing library for the uninstalled script (fft) + Original commit message from CVS: + 2007-11-21 Julien Moutte + * docs/faq/gst-uninstalled: Yet another missing library for the + uninstalled script (fft) + +2007-11-21 00:24:04 +0000 Jan Schmidt + + docs/faq/developing.xml: Add a question about how to submit new translations. + Original commit message from CVS: + * docs/faq/developing.xml: + Add a question about how to submit new translations. + * docs/random/release: + Update the contact email address for the Translation Project + * plugins/elements/gstfdsrc.c: + The parent_class for fdsrc is pushsrc, not GstElement. + +2007-11-20 16:34:38 +0000 Stefan Kost + + gst/gstpreset.c: Plug a leak and fix saving. + Original commit message from CVS: + * gst/gstpreset.c: + Plug a leak and fix saving. + +2007-11-20 16:10:21 +0000 Sebastian Dröge + + docs/gst/gstreamer-sections.txt: Add new gst_preset__get_property_names() function to the docs to fix the build. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add new gst_preset__get_property_names() function to the docs + to fix the build. + +2007-11-20 15:46:39 +0000 Stefan Kost + + gst/gstpreset.*: Change _get_preset_names API to return a strv with copies. Add _get_property_names to allow implemen... + Original commit message from CVS: + * gst/gstpreset.c: + * gst/gstpreset.h: + Change _get_preset_names API to return a strv with copies. Add + _get_property_names to allow implementations to filter and provide + good default implementation. + +2007-11-20 11:46:35 +0000 Julien Moutte + + docs/faq/gst-uninstalled: Add another library to the uninstalled script (sdp). + Original commit message from CVS: + 2007-11-20 Julien MOUTTE + * docs/faq/gst-uninstalled: Add another library to the uninstalled + script (sdp). + +2007-11-19 15:23:44 +0000 Stefan Kost + + gst/gstpreset.c: More cleanups, docs, and TODOs from comments that now slowly come in. + Original commit message from CVS: + * gst/gstpreset.c: + More cleanups, docs, and TODOs from comments that now slowly come in. + +2007-11-19 14:38:49 +0000 Julien Moutte + + docs/faq/gst-uninstalled: Add new base libraries in the LD search path. + Original commit message from CVS: + 2007-11-19 Julien MOUTTE + * docs/faq/gst-uninstalled: Add new base libraries in the LD + search path. + +2007-11-19 11:54:13 +0000 Stefan Kost + + gst/gstpreset.c: Fix bogus warning and make the property type specific code more similar. + Original commit message from CVS: + * gst/gstpreset.c: + Fix bogus warning and make the property type specific code more + similar. + +2007-11-19 09:33:05 +0000 Julien Moutte + + gst/gstpreset.c: Make it build on OS X. + Original commit message from CVS: + 2007-11-19 Julien MOUTTE + * gst/gstpreset.c: (gst_preset_default_create_preset): Make + it build on OS X. + +2007-11-19 08:50:04 +0000 Wim Taymans + + gst/gstbin.c: Change email, cleanups add some more debug and comments. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), + (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_change_state_func), (gst_bin_continue_func): + Change email, cleanups add some more debug and comments. + Also set bus and clock on new elements when the pipeline was in error. + +2007-11-18 19:30:10 +0000 Stefan Kost + + gst/: Fix build with --disable-gst-debug. Fixes #497859. + Original commit message from CVS: + * gst/gstbin.c: + * gst/gstdebugutils.c: + Fix build with --disable-gst-debug. Fixes #497859. + Spotted by Sameer Naik. + +2007-11-17 17:50:21 +0000 Stefan Kost + + gst/gstevent.c: Little documentation improvment. + Original commit message from CVS: + * gst/gstevent.c: + Little documentation improvment. + * gst/gstpreset.c: + More TODO cleanups. Remove c++ comments. + * libs/gst/controller/gstcontroller.c: + Add TODO and use quark from static string. + * tests/check/gst/gstmessage.c: + * tests/check/gst/gststructure.c: + Use quark from static string. + +2007-11-17 17:24:53 +0000 Stefan Kost + + gst/gstpreset.c: Add some comments and TODOs. + Original commit message from CVS: + * gst/gstpreset.c: + Add some comments and TODOs. + * gst/gstpreset.h: + Add padding for future changes. + * plugins/elements/gstqueue.c: + Implement the iface. + +2007-11-17 16:43:12 +0000 Stefan Kost + + Add the preset interface (Fixes #396779). Do some doc cleanups along. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstpreset.c: + * gst/gstpreset.h: + Add the preset interface (Fixes #396779). Do some doc cleanups along. + +2007-11-16 00:23:18 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.15 === + +2007-11-16 00:07:54 +0000 Jan Schmidt + + configure.ac: releasing 0.10.15, "October" + Original commit message from CVS: + === release 0.10.15 === + 2007-11-15 Jan Schmidt + * configure.ac: + releasing 0.10.15, "October" + +2007-11-15 23:31:11 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/be.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/nb.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/rw.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/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-11-14 12:24:09 +0000 Jan Schmidt + + win32/vs6/libgstreamer.dsp: Convert line endings back to DOS. + Original commit message from CVS: + * win32/vs6/libgstreamer.dsp: + Convert line endings back to DOS. + +2007-11-13 11:30:09 +0000 Stefan Kost + + docs/: Update fast tagreading draft and performance profiling ideas. + Original commit message from CVS: + * docs/design/draft-tagreading.txt: + * docs/random/ensonic/profiling.txt: + Update fast tagreading draft and performance profiling ideas. + +2007-11-09 14:05:02 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't hold the object lock when unreffing a buffer because it could cause a deadlock whe... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_last_buffer): + Don't hold the object lock when unreffing a buffer because it could + cause a deadlock when the finalize function wants to grab the object + lock too. Fixes #495133. + +2007-11-09 11:56:41 +0000 Wim Taymans + + gst/gstsegment.c: Also accumulate time correctly when doing reverse playback. Fixes #488201, + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_newsegment_full), + (gst_segment_to_stream_time), (gst_segment_to_running_time): + Also accumulate time correctly when doing reverse playback. Fixes + #488201, + When converting to running and stream time, use default values for + start/stop/time/accum when comparing different formats. Fixes #494245. + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Do running/stream time in TIME format. + * tests/check/gst/gstsegment.c: (GST_START_TEST), + (gst_segment_suite): + 2 new unit tests for segment accumulation. + +2007-11-07 15:53:52 +0000 Tim-Philipp Müller + + gst/: Move getenv() back into gst_init, so everyone can live happily ever after. Make sure the symbol isn't exported ... + Original commit message from CVS: + * gst/gst.c: (init_pre): + * gst/gstdebugutils.c: (priv_gst_dump_dot_dir), (debug_dump_element), + (_gst_debug_bin_to_dot_file): + Move getenv() back into gst_init, so everyone can live happily + ever after. Make sure the symbol isn't exported though. + +2007-11-06 23:17:09 +0000 Sebastien Moutte + + win32/common/gstenumtypes.*: Update enum types. + Original commit message from CVS: + Patch by: Sebastien Moutte + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + Update enum types. + * win32/vs6/libgstreamer.dsp: + Update vs6 project files (#494343). + +2007-11-06 17:18:14 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Unify flushing code, remove some old unlock code that is no longer used. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_query), + (gst_base_src_perform_seek), (gst_base_src_default_event), + (gst_base_src_set_flushing), (gst_base_src_activate_push), + (gst_base_src_activate_pull): + Unify flushing code, remove some old unlock code that is no longer used. + Take the streaming lock when seeking to avoid races. Fixes #492729. + Added some more comments. + +2007-11-06 15:10:36 +0000 Tim-Philipp Müller + + gst/gst.c: Make _gst_disable_segtrap static, it's only used in gstplugin.c and we can use gst_segtrap_is_enabled() t... + Original commit message from CVS: + * gst/gst.c: (_gst_disable_segtrap): + Make _gst_disable_segtrap static, it's only used in gstplugin.c and + we can use gst_segtrap_is_enabled() there now that we have that API. + Move _gst_debug_dump_dot_dir into gstdebugutils.c, there's no reason + to do the getenv here (and export the variable). + * gst/gstdebugutils.c: (debug_dump_element), + (_gst_debug_bin_to_dot_file), (_gst_debug_bin_to_dot_file_with_ts): + Don't use VLAs which is a C99ism and throws off MSVC (#493983). + * gst/gstinfo.c: (_priv_gst_info_start_time), (_gst_debug_init), + (gst_debug_log_default): + Rename _gst_info_start_time to priv_gst_info_start_time so it + doesn't get exported (was never in any header). + * gst/gstplugin.c: (_gst_plugin_fault_handler_setup), + (gst_plugin_loading_mutex): + Make static mutex gst_plugin_loading_mutex really static (was never + in any header), and use gst_segtrap_is_enabled() instead of + _gst_disable_segtrap. + * gst/gsttrace.c: (_gst_trace_default): + Make local _gst_trace_default static (was never in any header). + +2007-11-06 14:43:14 +0000 Ole André Vadla Ravnås + + win32/common/: Add more missing symbols, remove some duplicates, and sort as the 'sort' command sorts it (partially f... + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + * win32/common/libgstbase.def: + * win32/common/libgstcontroller.def: + * win32/common/libgstdataprotocol.def: + * win32/common/libgstnet.def: + * win32/common/libgstreamer.def: + Add more missing symbols, remove some duplicates, and sort + as the 'sort' command sorts it (partially fixes #493983). + +2007-11-06 12:28:17 +0000 Wim Taymans + + gst/gstelement.c: Only change the state cookie if a different state was set on the element. See #492729. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_set_state_func): + Only change the state cookie if a different state was set on the + element. See #492729. + +2007-11-06 11:41:32 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Remove unused and uninitialised type variables that were still exported for some reason (they were ne... + Original commit message from CVS: + * gst/gstvalue.c: + Remove unused and uninitialised type variables that were still + exported for some reason (they were never in any header files + though). + +2007-11-06 10:33:22 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't try to report a 0 position when we don't know, return -1 and FALSE instead. This m... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_do_sync), (gst_base_sink_preroll_object), + (gst_base_sink_event), (gst_base_sink_get_position_last), + (gst_base_sink_get_position_paused), (gst_base_sink_get_position), + (gst_base_sink_change_state): + Don't try to report a 0 position when we don't know, return -1 and FALSE + instead. This mostly happens when we are prerolling. + Make sure we can report the right position before we post the ASYNC_DONE + message so that a message handler can query position without races. + * tests/check/generic/sinks.c: (send_eos), (GST_START_TEST), + (async_done_handoff), (async_done_func), (send_buffer), + (async_done_eos_func), (gst_sinks_suite): + Add two tests for the above. + +2007-11-06 10:21:01 +0000 Wim Taymans + + MAINTAINERS: Update with new email address. + Original commit message from CVS: + * MAINTAINERS: + Update with new email address. + * docs/design/part-TODO.txt: + Add some more info about future pad-block and negotiation changes. + * docs/design/part-buffering.txt: + Add some ideas about buffering reporting. + +2007-11-06 10:01:07 +0000 Christian Schaller + + * Makefile.am: + * common: + * gstreamer.spec.in: + update SPEC file with latest changes, also add MAINTAINERS file to EXTRA_DIST, the ommission of this cause a weird RP... + Original commit message from CVS: + update SPEC file with latest changes, also add MAINTAINERS file to EXTRA_DIST, the ommission of this cause a weird RPM build error on FC8 + +2007-11-06 00:59:54 +0000 Jan Schmidt + + tests/check/gst/gstobject.c: Disable silly racy test that always fails on this combination of CPU and kernel. + Original commit message from CVS: + * tests/check/gst/gstobject.c: + Disable silly racy test that always fails on this combination of CPU + and kernel. + +2007-11-04 10:16:38 +0000 Tim-Philipp Müller + + * ChangeLog: + ChangeLog surgery: mention bug number + Original commit message from CVS: + ChangeLog surgery: mention bug number + +2007-11-04 10:13:33 +0000 Murray Cumming + + gst/gstobject.c: Corrected the registration of the parent-set and parent-unset signals: The parameter is a GstObject,... + Original commit message from CVS: + Patch by: Murray Cumming + * gst/gstobject.c: + Corrected the registration of the parent-set and parent-unset + signals: The parameter is a GstObject, not a GObject. + +2007-11-02 18:35:37 +0000 Tim-Philipp Müller + + gst/: Move declaration of private _gst_foo_initialize() functions into our private header file where they should have... + Original commit message from CVS: + * gst/gst_private.h: + * gst/gstbuffer.h: + * gst/gstevent.h: + * gst/gstformat.h: + * gst/gstmessage.h: + * gst/gstplugin.h: + * gst/gstquery.h: + * gst/gsttaglist.h: + * gst/gstvalue.h: + Move declaration of private _gst_foo_initialize() functions into + our private header file where they should have been all along. + +2007-11-02 17:43:25 +0000 Tim-Philipp Müller + + gtk-doc fixes; trailing-comma-in-enum fix. + Original commit message from CVS: + * docs/plugins/gstreamer-plugins-sections.txt: + * gst/gstdebugutils.h: + * gst/gstxml.h: + * plugins/elements/gstqueue.c: + gtk-doc fixes; trailing-comma-in-enum fix. + +2007-11-02 16:27:56 +0000 Tim-Philipp Müller + + gst/gst.c: Clean up on deinit (not the external ones though, doesn't seem to be needed for some reason). + Original commit message from CVS: + * gst/gst.c: (gst_deinit): + Clean up on deinit (not the external ones though, doesn't seem to be + needed for some reason). + +2007-11-01 23:51:55 +0000 Tim-Philipp Müller + + gst/gstinfo.h: Remove __declspec(dllimport) for MSVC that was copied over into core from a plugin, obviously without ... + Original commit message from CVS: + * gst/gstinfo.h: (GST_DEBUG_CATEGORY_EXTERN): + Remove __declspec(dllimport) for MSVC that was copied over into core + from a plugin, obviously without ever having been tested (note the + single underscore in _declspec in the initial commit), and that doesn't + really make sense. See #492077. + +2007-11-01 21:50:05 +0000 Tim-Philipp Müller + + g_type_class_ref() other types as well, see #349410 and #64764. + Original commit message from CVS: + * gst/gst.c: (init_post): + * gst/gstevent.c: (_gst_event_initialize): + * gst/gstquery.c: (_gst_query_initialize): + * libs/gst/dataprotocol/dataprotocol.c (gst_dp_init): + g_type_class_ref() other types as well, see #349410 and #64764. + * gst/gstbuffer.c: (_gst_buffer_initialize): + * gst/gstmessage.c: (_gst_message_initialize): + Simplify existing g_type_class_ref(). + +2007-11-01 20:10:48 +0000 Tim-Philipp Müller + + gst/gstformat.c: g_type_class_ref() our GstFormat type to make sure we avoid the thread-unsafe bits of the GObject/GT... + Original commit message from CVS: + * gst/gstformat.c: (_gst_format_initialize): + g_type_class_ref() our GstFormat type to make sure we avoid the + thread-unsafe bits of the GObject/GType system, ie. bug #349410 and + bug #64764. Should fix intermittent tee unit test failures (#474823). + +2007-11-01 19:19:10 +0000 Tim-Philipp Müller + + tests/check/elements/tee.c: Simplify, simplify, simplify - or not. Rewrite unit test not to use gst_parse_launch(); ... + Original commit message from CVS: + * tests/check/elements/tee.c: (test_num_buffers): + Simplify, simplify, simplify - or not. Rewrite unit test + not to use gst_parse_launch(); allow N sub-streams. Increasing + the number of sub-streams seems to reproduce #474823 more easily. + +2007-10-31 22:01:03 +0000 Ole André Vadla Ravnås + + Fix a couple of missing includes for MSVC2005 and a C99 issue. Also, starting with 2.14.0, GLib won't provide a pipe(... + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås + * gst/gsttrace.c: + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_new): + * libs/gst/net/gstnettimepacket.c: (gst_net_time_packet_send): + * libs/gst/net/gstnettimeprovider.c: (gst_net_time_provider_new): + Fix a couple of missing includes for MSVC2005 and a C99 issue. Also, + starting with 2.14.0, GLib won't provide a pipe() macro any longer, + so use _pipe() directly (#492077). + * win32/common/dirent.c: (_treaddir): + Add a couple of casts to make it build without warnings with MSVC. + * win32/common/libgstreamer.def: + Add some more symbols that need to be exported. + +2007-10-31 18:08:21 +0000 Tim-Philipp Müller + + tests/examples/metadata/read-metadata.c: Use _KEEP as merge mode rather than _KEEP_ALL, so tags arriving in a second ... + Original commit message from CVS: + * tests/examples/metadata/read-metadata.c: (message_loop): + Use _KEEP as merge mode rather than _KEEP_ALL, so tags + arriving in a second or third tag message are added to + the tag list as well. + +2007-10-31 13:01:34 +0000 Stefan Kost + + libs/gst/base/gstbasesrc.c: Its "Since:" and not "@Since:". And remove an superflous cast. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: + Its "Since:" and not "@Since:". And remove an superflous cast. + +2007-10-30 18:30:13 +0000 Wim Taymans + + Add a new last-buffer property that contains the last buffer used in basesink for preroll or rendering. useful for ma... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_get_last_buffer), (gst_base_sink_set_last_buffer), + (gst_base_sink_get_property), (gst_base_sink_render_object), + (gst_base_sink_preroll_object), + (gst_base_sink_queue_object_unlocked), (gst_base_sink_event), + (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + Add a new last-buffer property that contains the last buffer used in + basesink for preroll or rendering. useful for making snapshots. + API: gst_base_sink_get_last_buffer() + API: GstBaseSink::last-buffer + +2007-10-29 13:46:25 +0000 Stefan Kost + + Improve bin graph dumping, by using the envvar to specify a path. + Original commit message from CVS: + * docs/gst/running.xml: + * gst/gst.c: + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + * tools/gst-launch.c: + Improve bin graph dumping, by using the envvar to specify a path. + Rename the envvar to GST_DEBUG_DUMP_DOT_DIR. + +2007-10-29 13:10:01 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Post special error message if we can't determine the type of a stream because ... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event), + (gst_type_find_element_activate): + Post special error message if we can't determine the type of a stream + because it's empty. + +2007-10-29 10:05:55 +0000 Stefan Kost + + Document new env-var. Add one log-line after dumpng a graph. + Original commit message from CVS: + * docs/gst/running.xml: + * gst/gstdebugutils.c: + Document new env-var. Add one log-line after dumpng a graph. + +2007-10-26 18:39:03 +0000 Tim-Philipp Müller + + configure.ac: Ugly hack to put the (recently removed and non-portable, apparently) + Original commit message from CVS: + * configure.ac: + Ugly hack to put the (recently removed and non-portable, apparently) + -Wl,--export-dynamic back into libgstcheck's LDFLAGS when we're using + GNU ld, because without that 'make check' fails miserably on my debian + stable box. Someone with more knowledge of linker intricacies and + portability issues than me fix this properly please. + +2007-10-25 17:20:47 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Reset last seen position after flushing so that we don't report the old position anymore. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_event): + Reset last seen position after flushing so that we don't report the old + position anymore. + +2007-10-25 16:19:05 +0000 Alessandro Decina + + gst/: Patch from Alessandro Decina adding get_type_full and get_protocols_full private vfuncs to the URIHandler inter... + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_register): + * gst/gsturi.h: + Patch from Alessandro Decina adding get_type_full and + get_protocols_full private vfuncs to the URIHandler interface + to allow bindings to support creating URI handlers. + Partially fixes: #339279 + API: GstURIHandlerInterface::get_type_full + API: GstURIHandlerInterface::get_protocols_full + +2007-10-25 15:14:02 +0000 Jan Schmidt + + plugins/elements/gstmultiqueue.c: Make it so that pads are considered linked until a buffer is pushed and discovered ... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_set_property), + (gst_multi_queue_request_new_pad), (gst_single_queue_flush), + (gst_multi_queue_loop), (gst_multi_queue_sink_activate_push): + Make it so that pads are considered linked until a buffer is pushed + and discovered otherwise. This avoids problems with decodebin2 hanging + after a seek in the filesrc ! decodebin2 name=d ! fakesink d. ! fakesink + case. + Make sure we lock the multiqueue when updating the max-size properties. + Fix a crash on Solaris in a debug statement in get_request_pad that + passes a NULL string to GST_DEBUG. + * tests/check/elements/multiqueue.c: (mq_dummypad_chain), + (run_output_order_test): + Fix the test to allow the first buffer on not-linked pads to come out + of sequence while multiqueue discovers that they are not-linked. + +2007-10-25 14:50:48 +0000 Jan Schmidt + + Use a custom export symbol regex for libgstcheck, as it needs to export symbols that don't match the standard GStream... + Original commit message from CVS: + * configure.ac: + * libs/gst/check/Makefile.am: + Use a custom export symbol regex for libgstcheck, as it needs + to export symbols that don't match the standard GStreamer gst_* + pattern, and --export-dynamic is not portable (only works on + GNU ld) + * libs/gst/check/gstcheck.c: (gst_check_setup_src_pad), + (gst_check_setup_sink_pad): + Make sure to pass a message parameter to the fail_* macros. + * tests/check/gst/gstinfo.c: (GST_START_TEST): + Fix some compiler warnings. + +2007-10-25 14:41:01 +0000 Tim-Philipp Müller + + tests/check/gst/gststructure.c: Disable test that checks that white spaces are not allowed in structure names or fiel... + Original commit message from CVS: + * tests/check/gst/gststructure.c: (test_to_string): + Disable test that checks that white spaces are not allowed + in structure names or field names, since we need to + support that for now for backwards compatibility reasons. + +2007-10-24 13:13:56 +0000 Tim-Philipp Müller + + API: add GST_TAG_ARTIST_SORTNAME + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + API: add GST_TAG_ARTIST_SORTNAME + API: add GST_TAG_ALBUM_SORTNAME + API: add GST_TAG_TITLE_SORTNAME + Add tag variants for sorting (#414539). + +2007-10-24 13:00:58 +0000 Tim-Philipp Müller + + gst/gststructure.c: Also allow white space for names so we don't break backwards compatibility. + Original commit message from CVS: + * gst/gststructure.c: + Also allow white space for names so we don't break + backwards compatibility. + +2007-10-22 15:37:43 +0000 Wim Taymans + + docs/design/: Small updates. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-segments.txt: + * docs/design/part-streams.txt: + Small updates. + +2007-10-22 11:32:14 +0000 Edgard Lima + + docs/gst/gstreamer-sections.txt: Fixed documentation from my previous commit (added new API add gst_value_set_structu... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Fixed documentation from my previous commit (added new API add + gst_value_set_structure(), add gst_value_get_structure() and + GST_VALUE_HOLDS_STRUCTURE). + +2007-10-22 11:10:28 +0000 Stefan Kost + + gst/gstdebugutils.c: Reflow code to fix uninitialized variable warning. + Original commit message from CVS: + * gst/gstdebugutils.c: + Reflow code to fix uninitialized variable warning. + +2007-10-22 08:53:26 +0000 Edgard Lima + + Added GstStructure to gst_value_table and its related functions. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_to_string), + (gst_caps_from_string_inplace): + * gst/gststructure.c: (gst_structure_get_abbrs), + (gst_structure_to_string), (gst_structure_from_string): + * gst/gstvalue.c: (gst_value_set_structure), + (gst_value_get_structure), (gst_value_serialize_structure), + (gst_value_deserialize_structure), (_gst_value_initialize): + * gst/gstvalue.h: + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Added GstStructure to gst_value_table and its related functions. + Changed gst_structure_to_string to print ';' in the end. + Changed gst_caps_to_string to not print ';' beteween its + fields (structures) anymore and remove the lastes ';' from latest + structure. Now it is possible to have nested structures. + In addition, backward compatibilty is assured by accepting '\0' as + end delimiter. Fixes: #487969. + API: add gst_value_set_structure() + API: add gst_value_get_structure() + +2007-10-19 09:48:38 +0000 Tim-Philipp Müller + + gst/gstbus.c: When no GSource callback has been set up, tell developer to use a function that actually exists. + Original commit message from CVS: + * gst/gstbus.c: + When no GSource callback has been set up, tell developer + to use a function that actually exists. + +2007-10-17 12:58:23 +0000 Stefan Kost + + Allow dumping pipelines as dot graphs. Fixes #456573. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gstdebugutils.c: + * gst/gstdebugutils.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * tools/gst-launch.c: + Allow dumping pipelines as dot graphs. Fixes #456573. + +2007-10-16 21:48:23 +0000 Tim-Philipp Müller + + gst/gststructure.c: Allow '+' as well, it can be part of media or mime types such as image/svg+xml. + Original commit message from CVS: + * gst/gststructure.c: + Allow '+' as well, it can be part of media or mime types + such as image/svg+xml. + +2007-10-16 20:30:13 +0000 Tim-Philipp Müller + + API: add gst_bus_pop_filtered + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbus.c: + * gst/gstbus.h: + API: add gst_bus_pop_filtered + API: add gst_bus_timed_pop_filtered + Two new functions for waiting for specific message types on the + bus for a specified amount of time without iterating any main + loops or main contexts. + * tests/check/gst/gstbus.c: + Some tests for the new functions. + +2007-10-16 17:21:38 +0000 Tim-Philipp Müller + + docs/libs/gstreamer-libs-sections.txt: Make gtk-doc ignore stuff it should ignore. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Make gtk-doc ignore stuff it should ignore. + +2007-10-16 16:12:36 +0000 Tim-Philipp Müller + + libs/gst/check/gstcheck.*: Allow runtime selection of unit tests to run via the GST_CHECKS environment variable (test... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + Allow runtime selection of unit tests to run via the GST_CHECKS + environment variable (test case function names, comma-separated). + +2007-10-16 13:58:43 +0000 Stefan Kost + + Revert serialisation change and constrain structure-names after consensus on irc. Update api documentation to reflect... + Original commit message from CVS: + * gst/gststructure.c: + * tests/check/gst/gststructure.c: + Revert serialisation change and constrain structure-names after + consensus on irc. Update api documentation to reflect the change. + +2007-10-16 06:32:07 +0000 Stefan Kost + + gst/gststructure.c: Improve serialization and fix tests. + Original commit message from CVS: + * gst/gststructure.c: + Improve serialization and fix tests. + * tests/check/gst/gststructure.c: + Add another test that covers why I actually did the previous structure + change. + +2007-10-15 14:33:16 +0000 Wim Taymans + + tools/gst-inspect.c: Don't crash when inspecting an element. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_info): + Don't crash when inspecting an element. + +2007-10-15 11:58:16 +0000 Tim-Philipp Müller + + tests/check/gst/gststructure.c: Add unit test for escaping of structure name when serialising and deserialising to/fr... + Original commit message from CVS: + * tests/check/gst/gststructure.c: + Add unit test for escaping of structure name when serialising + and deserialising to/from strings. + +2007-10-15 11:36:37 +0000 Wim Taymans + + plugins/elements/: Fix queue negotiation. If acceptcaps unconditionally returns TRUE, upstream is tricked into thinki... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_push_one), + (gst_single_queue_new): + * plugins/elements/gstqueue.c: (gst_queue_init), + (gst_queue_push_one): + Fix queue negotiation. If acceptcaps unconditionally returns TRUE, + upstream is tricked into thinking it can suggest a format downstream + while downstream does not support that format. The real problem is that + core calls acceptcaps when pushing a buffer with new caps, for which we + do a little workaround by setting the caps on the srcpad ourselves + before pushing the buffer (until this is figured out). Fixes #486758. + +2007-10-15 11:19:36 +0000 Stefan Kost + + gst/: Add some more comments and debug output. Quote structure name to fix deserialisation of some strings. + Original commit message from CVS: + * gst/gststructure.c: + * gst/gstvalue.c: + Add some more comments and debug output. Quote structure name to fix + deserialisation of some strings. + +2007-10-15 07:37:37 +0000 Stefan Kost + + gst/gstbuffer.h: Define GST_BUFFER_FLAG_GAP more strictly to enable optimizations based on it. Fix docs for GST_BUFFE... + Original commit message from CVS: + * gst/gstbuffer.h: + Define GST_BUFFER_FLAG_GAP more strictly to enable optimizations based + on it. Fix docs for GST_BUFFER_MALLOCDATA and GstBuffer.malloc_data. + +2007-10-15 07:11:04 +0000 Stefan Kost + + tools/gst-inspect.c: Save approx. 400 1 byte allocs when printing. Use API to acces element details. + Original commit message from CVS: + * tools/gst-inspect.c: + Save approx. 400 1 byte allocs when printing. Use API to acces element + details. + * tools/gst-run.c: + Avoid a strdup. + * tools/gst-xmlinspect.c: + Use API to acces element details. + +2007-10-15 06:52:01 +0000 Stefan Kost + + gst/gstinfo.c: Fix some spelling errors. + Original commit message from CVS: + * gst/gstinfo.c: + Fix some spelling errors. + +2007-10-14 15:54:02 +0000 Wim Taymans + + gst/gstbin.c: Correctly set the next state if all of our async children commited their state. This makes sure we can ... + Original commit message from CVS: + * gst/gstbin.c: (bin_handle_async_done): + Correctly set the next state if all of our async children commited their + state. This makes sure we can actually cancel the state change in + progress. Fixes a regression in Rhythmbox when seeking. + +2007-10-13 17:43:27 +0000 Tim-Philipp Müller + + gst/gstbin.c: Don't shadow local variable. + Original commit message from CVS: + * gst/gstbin.c: + Don't shadow local variable. + * gst/gstinfo.c: + Don't shadow global function name. + +2007-10-13 17:20:09 +0000 Tim-Philipp Müller + + gst/: Use already-interned string for the private GstPluginFeature plugin_name field. + Original commit message from CVS: + * gst/gstelementfactory.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistrybinary.c: + * gst/gstregistryxml.c: + * gst/gsttypefind.c: + Use already-interned string for the private GstPluginFeature + plugin_name field. + +2007-10-10 22:43:11 +0000 Tim-Philipp Müller + + docs/libs/gstreamer-libs-sections.txt: Add new API to docs; fixes the build. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add new API to docs; fixes the build. + +2007-10-10 15:18:44 +0000 Wim Taymans + + libs/gst/base/gstbasesink.*: Add function to wait for EOS, subclasses can use this to correctly wait for devices to d... + Original commit message from CVS: + Patch inspired by: Benoit Fouet + * libs/gst/base/gstbasesink.c: (gst_base_sink_wait_eos), + (gst_base_sink_event): + * libs/gst/base/gstbasesink.h: + Add function to wait for EOS, subclasses can use this to correctly wait + for devices to drain before performing the EOS logic. Fixes #485343. + API: gst_base_sink_wait_eos() + +2007-10-10 10:53:39 +0000 Tim-Philipp Müller + + gst/gstplugin.h: Cast description string constants in GST_PLUGIN_DEFINE macros to a (gchar*) to make C++ code using t... + Original commit message from CVS: + * gst/gstplugin.h: + Cast description string constants in GST_PLUGIN_DEFINE macros + to a (gchar*) to make C++ code using these macros compile + without warning with g++-4.2 (see #462737). Even if slightly + ugly, this seems preferable to putting the description strings + into the GLib quark table or making the structure member a + const gchar * and doing casts in core code that allocs and + frees these strings, or requiring a cast in the C++ code. + +2007-10-09 20:45:13 +0000 Tim-Philipp Müller + + gst/gstinfo.h: Use __FUNCTION__ instead of __PRETTY_FUNCTION__, it's silly to print the entire class/function signatu... + Original commit message from CVS: + * gst/gstinfo.h: + Use __FUNCTION__ instead of __PRETTY_FUNCTION__, it's silly + to print the entire class/function signature into the log + file for C++ code. This only affects C++ code, for C code + everything remains the same. + +2007-10-09 16:20:59 +0000 Wim Taymans + + gst/gstbin.c: Work around a problem with pipelines containing (semi)loops until a proper, more complicated solution i... + Original commit message from CVS: + * gst/gstbin.c: (remove_from_queue): + Work around a problem with pipelines containing (semi)loops until a + proper, more complicated solution is ready. See #475455. + +2007-10-09 14:18:39 +0000 Tim-Philipp Müller + + gst/: Put more strings into the GLib quark table. No need to keep a hundred-something copies of identical version str... + Original commit message from CVS: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstregistrybinary.c: + * gst/gstregistryxml.c: + Put more strings into the GLib quark table. No need to keep + a hundred-something copies of identical version strings, + license strings, package name strings and package origin + strings around. + +2007-10-09 10:41:41 +0000 Tim-Philipp Müller + + docs/manual/advanced-dataaccess.xml: Don't imply that it's okay to unconditionally change buffer data or buffer metad... + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + Don't imply that it's okay to unconditionally change + buffer data or buffer metadata in a pad probe callback, + and a bunch of other comments. Fixes #430031. + +2007-10-08 20:45:07 +0000 Tim-Philipp Müller + + win32/common/: Update generated files. + Original commit message from CVS: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + Update generated files. + +2007-10-08 17:59:35 +0000 Tim-Philipp Müller + + docs/manual/advanced-autoplugging.xml: Prefix section with broken code with a warning (see #342432). + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + Prefix section with broken code with a warning (see #342432). + +2007-10-08 17:26:09 +0000 Tim-Philipp Müller + + docs/manual/: Call g_thread_init() before g_option_context_new() to avoid warnings. Spotted by Ritesh Khadgaray. Fixe... + Original commit message from CVS: + * docs/manual/appendix-integration.xml: + * docs/manual/basics-init.xml: + Call g_thread_init() before g_option_context_new() to + avoid warnings. Spotted by Ritesh Khadgaray. Fixes #484225. + +2007-10-08 17:05:06 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: When we received EOS and are waiting for when to post the EOS message, our state is prer... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush), + (gst_base_sink_queue_object_unlocked), + (gst_base_sink_queue_object), (gst_base_sink_event), + (gst_base_sink_needs_preroll), (gst_base_sink_chain_unlocked): + When we received EOS and are waiting for when to post the EOS message, + our state is prerolled and we should not return ASYNC. + Reorganize some code paths to implement this behavior. + * tests/check/generic/sinks.c: (send_eos), (GST_START_TEST), + (gst_sinks_suite): + Add unit test to verify above EOS fix. + +2007-10-08 10:28:18 +0000 Wim Taymans + + plugins/elements/gsttypefindelement.c: Move detecting the input caps of the sinkpad to the setcaps function. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_have_type), (gst_type_find_element_init), + (gst_type_find_element_setcaps), (gst_type_find_element_chain): + Move detecting the input caps of the sinkpad to the setcaps function. + This allows us to update the output caps when we receive new input caps + instead of always using the first detected caps. + +2007-10-08 10:21:15 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't try to preroll non-async elements after a flush. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_event), + (gst_base_sink_get_position): + Don't try to preroll non-async elements after a flush. + Subtract latency form clock times when reporting position. + +2007-10-05 14:44:18 +0000 Wim Taymans + + gst/: Small comment and documentation update. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_pause_task): + * gst/gstutils.c: + Small comment and documentation update. + +2007-10-05 14:40:06 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Rework the locking of basesrc in a similar fashion to basesink. We basically have one loc... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing), + (gst_base_src_set_live), (gst_base_src_is_live), + (gst_base_src_query_latency), (gst_base_src_perform_seek), + (gst_base_src_default_event), (gst_base_src_wait), + (gst_base_src_do_sync), (gst_base_src_get_range), + (gst_base_src_pad_get_range), (gst_base_src_loop), + (gst_base_src_unlock), (gst_base_src_unlock_stop), + (gst_base_src_set_flushing), (gst_base_src_set_playing), + (gst_base_src_activate_push), (gst_base_src_activate_pull), + (gst_base_src_change_state): + Rework the locking of basesrc in a similar fashion to basesink. We + basically have one lock (LIVE_LOCK) protecting the dataflow. This allows + us to handle live sources and semi live ones much better. + Simplify flushing. + Fix unlocking when seeking, shutting down and pausing in live sources. + +2007-10-05 11:52:39 +0000 Wim Taymans + + tests/check/pipelines/simple-launch-lines.c: Fix compilation again. + Original commit message from CVS: + * tests/check/pipelines/simple-launch-lines.c: (run_pipeline): + Fix compilation again. + +2007-10-03 15:27:24 +0000 Stefan Kost + + gst/gstelement.c: Use meaningful categories for the logs to clean the default one. + Original commit message from CVS: + * gst/gstelement.c: + Use meaningful categories for the logs to clean the default one. + +2007-10-03 15:05:30 +0000 Stefan Kost + + tests/check/pipelines/cleanup.c: Print message name and not just number. + Original commit message from CVS: + * tests/check/pipelines/cleanup.c: + Print message name and not just number. + +2007-10-03 15:02:43 +0000 Stefan Kost + + docs/design/draft-tagreading.txt: Add some more thoughts. + Original commit message from CVS: + * docs/design/draft-tagreading.txt: + Add some more thoughts. + +2007-10-03 14:51:03 +0000 Stefan Kost + + 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-03 12:05:17 +0000 Stefan Kost + + libs/gst/base/gsttypefindhelper.c: Speedup typefinding. This is work in progress (see #459862). + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: + Speedup typefinding. This is work in progress (see #459862). + +2007-10-03 11:36:14 +0000 Stefan Kost + + gst/gstplugin.c: Fix docs that mention 'plugin_desc' instead of 'gst_plugin_desc'. + Original commit message from CVS: + * gst/gstplugin.c: + Fix docs that mention 'plugin_desc' instead of 'gst_plugin_desc'. + Spotted by Josep Torra Valles . + +2007-10-03 11:16:48 +0000 Tim-Philipp Müller + + gst/gstclock.h: Fix up broken GST_CLOCK_FLAGS macro and GstClock docs. The flags field has moved to GstObject. + Original commit message from CVS: + * gst/gstclock.h: + Fix up broken GST_CLOCK_FLAGS macro and GstClock docs. The flags + field has moved to GstObject. + +2007-10-02 15:20:58 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Call unlock for live sources so that they can't get stuck in _create and produce a buffer... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_do_sync), + (gst_base_src_get_range), (gst_base_src_change_state): + Call unlock for live sources so that they can't get stuck in _create and + produce a buffer before they are set back to PLAYING. + +2007-10-02 09:21:48 +0000 Edward Hervey + + plugins/elements/gstqueue.c: Comment the segment-related code... in the PROPER function. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_locked_enqueue), + (gst_queue_locked_dequeue): + Comment the segment-related code... in the PROPER function. + See #482147 and my commit from yesterday. + +2007-10-01 17:59:21 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Also initialize the counter that calculates the first timestamp on a buffer correctly for... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_change_state): + Also initialize the counter that calculates the first timestamp on a + buffer correctly for non-live sources. + +2007-10-01 12:31:28 +0000 Edward Hervey + + plugins/elements/gstqueue.c: Disable code that's breaking the current-time-level reporting. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_locked_dequeue): + Disable code that's breaking the current-time-level reporting. + See #482147 + +2007-09-30 18:16:34 +0000 Sebastian Dröge + + docs/gst/gstreamer-sections.txt: Add M_PI and IMPORT_SYMBOL to the private part of the GstInfo section as they should... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add M_PI and IMPORT_SYMBOL to the private part of the GstInfo section + as they shouldn't show up. Fixes the docs build. + +2007-09-29 11:46:31 +0000 Sébastien Moutte + + gst/gstinfo.h: Add an explicit variable importation needed on VS6 (only for MSC_VER) + Original commit message from CVS: + * gst/gstinfo.h: + Add an explicit variable importation needed on VS6 (only for MSC_VER) + Define M_PI which is used in files which are including gstinfo.h. + VS6 includes doesn't define it. + * win32/common/libgstbase.def: + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + Add new exported functions and variables. + * win32/vs6/libgstcontroller.dsp: + * win32/vs6/libgstreamer.dsp: + Update the list of files to build. + +2007-09-28 10:22:40 +0000 Felipe Contreras + + plugins/elements/gstqueue.c: Improve debugging. Fixes #480858. + Original commit message from CVS: + Patch by: Felipe Contreras + * plugins/elements/gstqueue.c: (update_time_level), (apply_buffer), + (gst_queue_locked_dequeue), (gst_queue_handle_sink_event), + (gst_queue_chain), (gst_queue_loop), (gst_queue_src_activate_push): + Improve debugging. Fixes #480858. + +2007-09-28 10:15:23 +0000 Felipe Contreras + + plugins/elements/gstqueue.c: First patch of code cleanups, use the macros and right arguments in the macros to signal... + Original commit message from CVS: + Patch by: Felipe Contreras + * plugins/elements/gstqueue.c: (gst_queue_handle_sink_event): + First patch of code cleanups, use the macros and right arguments in the + macros to signal and lock the queue. See #480858. + +2007-09-26 18:06:42 +0000 Wim Taymans + + gst/gstbus.c: Improve debugging when dealing with _poll(). + Original commit message from CVS: + * gst/gstbus.c: (poll_func): + Improve debugging when dealing with _poll(). + +2007-09-26 18:04:42 +0000 Tim-Philipp Müller + + gst/gstregistryxml.c: Fix memory leak I introduced a few days ago. + Original commit message from CVS: + * gst/gstregistryxml.c: + Fix memory leak I introduced a few days ago. + +2007-09-26 17:00:22 +0000 Michael Smith + + gst/gstbuffer.c: Make it once again possible to free GstBuffers in the default build. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_finalize): + Make it once again possible to free GstBuffers in the default + build. + The poisoning scribbles on parts of the miniobject we need in + order to free it. + Fixes #480341 + +2007-09-25 18:35:39 +0000 Tim-Philipp Müller + + API: add GST_TAG_COMPOSER, fixes #459809. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + API: add GST_TAG_COMPOSER, fixes #459809. + +2007-09-24 17:41:25 +0000 Sebastian Dröge + + gst/gstplugin.*: Add the 3-clause BSD license and the MIT/X11 license to the license list. Fixes #479784. + Original commit message from CVS: + * gst/gstplugin.c: + * gst/gstplugin.h: + Add the 3-clause BSD license and the MIT/X11 license to the license + list. Fixes #479784. + +2007-09-24 17:22:21 +0000 Tim-Philipp Müller + + docs/faq/getting.xml: Add Q+A about different GStreamer versions (#364056). + Original commit message from CVS: + * docs/faq/getting.xml: + Add Q+A about different GStreamer versions (#364056). + +2007-09-24 12:46:17 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Return correct gboolean from query function. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency), + (gst_base_sink_event), (gst_base_sink_change_state): + Return correct gboolean from query function. + +2007-09-24 12:29:23 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Simplify latency query. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency), + (gst_base_sink_event), (gst_base_sink_query), + (gst_base_sink_change_state): + Simplify latency query. + When not synchronizing, we can report latency without querying the peer + element. + +2007-09-24 11:46:35 +0000 Wim Taymans + + gst/: Fix small typos in the docs. + Original commit message from CVS: + * gst/gstobject.h: + * gst/gstvalue.c: + Fix small typos in the docs. + +2007-09-24 11:22:26 +0000 Wim Taymans + + docs/design/: Documentation updates and typo fixes. + Original commit message from CVS: + * docs/design/draft-latency.txt: + * docs/design/draft-push-pull.txt: + * docs/design/draft-tagreading.txt: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-activation.txt: + * docs/design/part-block.txt: + * docs/design/part-element-source.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * docs/design/part-preroll.txt: + * docs/design/part-push-pull.txt: + * docs/design/part-qos.txt: + * docs/design/part-query.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-seeking.txt: + * docs/design/part-segments.txt: + * docs/design/part-states.txt: + Documentation updates and typo fixes. + +2007-09-23 10:16:49 +0000 Tim-Philipp Müller + + plugins/elements/gstfakesink.c: Add some debug text to error message to indicate that we errored out on request. + Original commit message from CVS: + * plugins/elements/gstfakesink.c: + Add some debug text to error message to indicate that + we errored out on request. + * tools/gst-launch.c: + When the state change to PLAYING fails, check for an + error message on the bus and print it. + +2007-09-22 17:22:10 +0000 Thomas Vander Stichele + + * po/cs.po: + * po/hu.po: + * po/uk.po: + updated translations + Original commit message from CVS: + updated translations + +2007-09-22 17:18:52 +0000 Thomas Vander Stichele + + po/: Added Spanish translation. + Original commit message from CVS: + translated by: Jorge González González + * po/LINGUAS: + * po/es.po: + Added Spanish translation. + +2007-09-21 14:37:38 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Fix printf arguments. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_push_one): + Fix printf arguments. + +2007-09-20 10:36:23 +0000 Stefan Kost + + 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-20 07:42:35 +0000 Stefan Kost + + gst/gstbin.h: Move priv to the right place. + Original commit message from CVS: + * gst/gstbin.h: + Move priv to the right place. + * gst/gstsystemclock.c: + Add FIXME: and improve log. + * tests/check/Makefile.am: + * tests/examples/manual/Makefile.am: + Work with all types of registries. + +2007-09-19 20:39:52 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Don't unref the event after pushing it. Fixes #478401. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_send_event): + Don't unref the event after pushing it. Fixes #478401. + +2007-09-19 18:07:18 +0000 Stefan Kost + + Ignore registries in any format. + Original commit message from CVS: + * .cvsignore: + * tests/examples/manual/.cvsignore: + Ignore registries in any format. + +2007-09-19 13:28:40 +0000 Tim-Philipp Müller + + gst/glib-compat-private.h: Add compatibility macro for g_intern_string() for + Original commit message from CVS: + * gst/glib-compat-private.h: + Add compatibility macro for g_intern_string() for + GLib-2.8 (any reason we can't just bump the + requirement to at least 2.10?) + * gst/gstpadtemplate.h: + * gst/gstelementfactory.c: + * gst/gstregistryxml.c: + * gst/gstregistrybinary.c: + Make GstStaticPadTemplate's templ_name field a const gchar * and fix + up the internal code accordingly. This shouldn't be a problem, since + there is no reason external code could ever assume the string in such + a structure is dynamically allocated unless it did that itself; the + use of g_strdup() is private to element factories. The new code also + saves some memory by putting pad template name strings into the GLib + quark table instead of allocating them dynamically. + Declaring this field constant fixes warnings with g++-4.2 when using + the GST_STATIC_PAD_TEMPLATE macro in c++ code (#478092). + +2007-09-19 12:31:16 +0000 Stefan Kost + + gst/gstelementfactory.c: Release static caps. Fixes #475723. + Original commit message from CVS: + * gst/gstelementfactory.c: + Release static caps. Fixes #475723. + +2007-09-18 22:13:57 +0000 Tim-Philipp Müller + + gst/gstinfo.*: Make some internal API take const gchar * instead of just gchar * to avoid compiler warnings with g++-... + Original commit message from CVS: + * gst/gstinfo.c: + * gst/gstinfo.h: + Make some internal API take const gchar * instead of just + gchar * to avoid compiler warnings with g++-4.2.2 when + passing string constants (partially fixes #478092). + +2007-09-17 20:55:23 +0000 Wim Taymans + + gst/gstbin.c: A latency query fails when one of the sinks fail. + Original commit message from CVS: + * gst/gstbin.c: (bin_query_latency_fold), (gst_bin_query): + A latency query fails when one of the sinks fail. + * gst/gstelement.c: (gst_element_set_base_time): + Improve debugging. + +2007-09-17 17:17:29 +0000 Jan Schmidt + + Fix minor compilation warnings shown with Forte. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_continue_func): + * libs/gst/base/gstbasesrc.c: (gst_base_src_do_sync): + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_add_pad_full): + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_loop): + Fix minor compilation warnings shown with Forte. + +2007-09-17 06:01:53 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Measure queue level based on the diff between head and tail timestamps even when pushing... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (apply_buffer), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue): + Measure queue level based on the diff between head and tail timestamps + even when pushing the first buffer. + +2007-09-14 23:06:31 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Sinks that don't preroll can always be queried for the latency. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush), + (gst_base_sink_event), (gst_base_sink_change_state): + Sinks that don't preroll can always be queried for the latency. + Don't post ASYNC start when we are not async. + +2007-09-14 20:24:22 +0000 Wim Taymans + + plugins/elements/gstqueue.*: When downstream returns UNEXPECTED from pushing a buffer, don't try to push more buffers... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_locked_enqueue), + (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_push_one), (gst_queue_handle_src_query), + (gst_queue_sink_activate_push), (gst_queue_src_activate_push): + * plugins/elements/gstqueue.h: + When downstream returns UNEXPECTED from pushing a buffer, don't try to + push more buffers but allow pushing of EOS and NEWSEGMENT. + Add some more debug info here and there. Fixes #476514. + +2007-09-14 15:52:27 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Latency query is allowed after we are prerolled. Introduce a new flag for this and stop ... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_preroll_queue_flush), (gst_base_sink_commit_state), + (gst_base_sink_wait_preroll), (gst_base_sink_needs_preroll), + (gst_base_sink_set_flushing), (gst_base_sink_query), + (gst_base_sink_change_state): + Latency query is allowed after we are prerolled. Introduce a new flag + for this and stop abusing other variables. + +2007-09-13 23:53:48 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Push OOB events downstream when we get them in send_event. This allows the application to... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_send_event): + Push OOB events downstream when we get them in send_event. This allows + the application to insert events in the pipeline. + Add some more comments. + +2007-09-13 21:27:33 +0000 Wim Taymans + + gst/: Move latency query from GstPipeline to GstBin so that we can also use it when async-handling is enabled on bins. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (clear_queue), + (do_bin_latency), (gst_bin_change_state_func): + * gst/gstpipeline.c: (gst_pipeline_change_state): + Move latency query from GstPipeline to GstBin so that we can also + use it when async-handling is enabled on bins. + +2007-09-13 21:19:08 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Update docs. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_query_latency), + (gst_base_src_do_sync), (gst_base_src_change_state): + Update docs. + Clean up the timestamping and syncing code for pseudo live sources. + +2007-09-13 19:27:53 +0000 Steve Fink + + docs/manual/appendix-checklist.xml: Mention less -R switch in the section about debug output (#474055). + Original commit message from CVS: + Patch by: Steve Fink + * docs/manual/appendix-checklist.xml: + Mention less -R switch in the section about debug output (#474055). + +2007-09-13 17:15:38 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Queue can latency to the pipeline up to the configured max size in time. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_handle_src_query): + Queue can latency to the pipeline up to the configured max size in time. + Report this fact in the latency query. + +2007-09-13 09:08:23 +0000 Sebastien Moutte + + libs/gst/controller/: Use gst_guint64_to_gdouble() when converting from a uint64 or + Original commit message from CVS: + Patch by: Sebastien Moutte + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/gstlfocontrolsource.c: + Use gst_guint64_to_gdouble() when converting from a uint64 or + GstClockTime to double to fix the build on win32. Fixes #474371. + +2007-09-13 08:42:55 +0000 Sebastian Dröge + + gst/gstbuffer.c: Implement poisoning for GstBuffer if --enable-poisoning is specified. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_finalize): + Implement poisoning for GstBuffer if --enable-poisoning is specified. + When finalizing a buffer the complete struct is filled with 0xff, + thus making a use of the buffer after the final unref impossible. + +2007-09-13 08:36:37 +0000 Sebastian Dröge + + tests/check/libs/controller.c: Use fail_unless_equals_int(a, b) instead of fail_unless_equals (a == b) to get better ... + Original commit message from CVS: + * tests/check/libs/controller.c: (GST_START_TEST): + Use fail_unless_equals_int(a, b) instead of + fail_unless_equals (a == b) to get better output on failures. + +2007-09-12 16:35:48 +0000 Tim-Philipp Müller + + tests/check/gst/gsturi.c: Also check for the other file URI variant on win32. + Original commit message from CVS: + * tests/check/gst/gsturi.c: + Also check for the other file URI variant on win32. + +2007-09-12 12:36:51 +0000 Tim-Philipp Müller + + gst/gsturi.c: If there's no hostname, we want to return 'c:/foo/bar.txt' and not '/c:/foo/bar.txt' on Windows. Fixes ... + Original commit message from CVS: + * gst/gsturi.c: (gst_uri_get_location): + If there's no hostname, we want to return 'c:/foo/bar.txt' + and not '/c:/foo/bar.txt' on Windows. Fixes #469402. + * tests/check/gst/gsturi.c: + Unit test for the above and a few more things. + +2007-09-11 23:27:42 +0000 Wim Taymans + + docs/design/part-live-source.txt: Add docs on how live sources should timestamp. + Original commit message from CVS: + * docs/design/part-live-source.txt: + Add docs on how live sources should timestamp. + * libs/gst/base/gstbasesrc.c: (gst_base_src_do_sync): + Add some more debug info. + For subclasses that are live and like to sync, add aditional startup + latency to sync time and timestamps so that we timstamp according to the + design doc. + +2007-09-11 18:59:09 +0000 Tim-Philipp Müller + + gst/gstbuffer.c: Also do a g_type_class_ref() for the subbuffer type in the init function. + Original commit message from CVS: + * gst/gstbuffer.c: + Also do a g_type_class_ref() for the subbuffer type in + the init function. + +2007-09-11 15:55:50 +0000 Wim Taymans + + Add function to perform a query on the peer of a pad. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: (gst_pad_peer_query): + * gst/gstpad.h: + Add function to perform a query on the peer of a pad. + API: gst_pad_peer_query() + +2007-09-11 13:43:53 +0000 Stefan Kost + + tests/check/gst/gstsystemclock.c: Cleanup the test a little (use gst-logging and not g_message). Improve test to chec... + Original commit message from CVS: + * tests/check/gst/gstsystemclock.c: + Cleanup the test a little (use gst-logging and not g_message). Improve + test to check if a wait reached the target. + +2007-09-11 10:33:14 +0000 Tim-Philipp Müller + + docs/libs/gstreamer-libs-sections.txt: Add new API to docs and fix the build. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add new API to docs and fix the build. + +2007-09-10 16:50:11 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.*: Add property to make the basesrc timestamp buffers based on the current running time. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_set_do_timestamp), + (gst_base_src_get_do_timestamp), (gst_base_src_set_property), + (gst_base_src_get_property), (gst_base_src_do_sync): + * libs/gst/base/gstbasesrc.h: + Add property to make the basesrc timestamp buffers based on the current + running time. + API: GstBaseSrc::do-timestamp + API: gst_base_src_set_do_timestamp() + API: gst_base_src_get_do_timestamp() + +2007-09-08 20:25:57 +0000 Tim-Philipp Müller + + docs/random/release: Really make sure translations are up-to-date before a release (#465010). + Original commit message from CVS: + * docs/random/release: + Really make sure translations are up-to-date before + a release (#465010). + +2007-09-07 14:46:52 +0000 Christian Schaller + + * gstreamer.spec.in: + add latest header files + Original commit message from CVS: + add latest header files + +2007-09-07 04:50:23 +0000 Sebastian Dröge + + gst/gstregistrybinary.c: Always destroy the timer, also in error cases. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): + Always destroy the timer, also in error cases. + +2007-09-05 22:29:58 +0000 Wim Taymans + + docs/manual/highlevel-xml.xml: Fix XML example code. Fixes #472714. + Original commit message from CVS: + * docs/manual/highlevel-xml.xml: + Fix XML example code. Fixes #472714. + +2007-09-05 22:12:42 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Protect eos and have_preroll with the OBJECT lock so we don't need to take the PREROLL l... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush), + (gst_base_sink_wait_preroll), (gst_base_sink_needs_preroll), + (gst_base_sink_query): + Protect eos and have_preroll with the OBJECT lock so we don't need to + take the PREROLL lock when querying the latency. Fixes #473846. + +2007-09-05 13:24:31 +0000 Stefan Kost + + gst/gstelement.c: Give some log-messages a category. + Original commit message from CVS: + * gst/gstelement.c: + Give some log-messages a category. + +2007-09-05 01:00:50 +0000 Wim Taymans + + gst/gststructure.c: Fix fraction list fixation code. Take the fraction with the smallest difference with the target i... + Original commit message from CVS: + * gst/gststructure.c: + (gst_structure_fixate_field_nearest_fraction): + Fix fraction list fixation code. Take the fraction with the smallest + difference with the target instead of the first one in the list. + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + Added test to verify correct fraction list fixation behaviour. + +2007-09-02 20:30:16 +0000 Tim-Philipp Müller + + win32/common/libgstreamer.def: Export gst_bus_add_signal_watch too. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Export gst_bus_add_signal_watch too. + +2007-08-30 17:50:54 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: Add new methods to docs. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add new methods to docs. + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_set_ts_offset), + (gst_base_sink_get_ts_offset), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_wait_clock): + * libs/gst/base/gstbasesink.h: + Add ts-offset property to fine-tune the synchronisation. + API: GstBaseSink::ts-offset property + API: gst_base_sink_set_ts_offset() + API: gst_base_sink_get_ts_offset() + +2007-08-29 20:57:58 +0000 Wim Taymans + + libs/gst/base/gstbasesink.*: Add async property to instruct the sink never to inform the parent about + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_set_sync), + (gst_base_sink_get_sync), (gst_base_sink_set_max_lateness), + (gst_base_sink_get_max_lateness), (gst_base_sink_set_qos_enabled), + (gst_base_sink_is_qos_enabled), (gst_base_sink_set_async_enabled), + (gst_base_sink_is_async_enabled), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + Add async property to instruct the sink never to inform the parent about + ASYNC state changes, update docs. + Check argument with g_return_* for the public functions. + API: GstBaseSink::async property + API: gst_base_sink_set_async_enabled() + API: gst_base_sink_is_async_enabled() + +2007-08-28 15:02:19 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Improve debugging. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_loop): + Improve debugging. + * libs/gst/base/gstbasesrc.c: (gst_base_src_query_latency), + (gst_base_src_default_query), (gst_base_src_wait), + (gst_base_src_do_sync), (gst_base_src_change_state): + Rearrange some code so that we can add support for measuring the + startup latency. + +2007-08-27 20:00:39 +0000 Stefan Kost + + docs/random/ensonic/dynlink.txt: More thoughs on this. + Original commit message from CVS: + * docs/random/ensonic/dynlink.txt: + More thoughs on this. + * plugins/elements/gstcapsfilter.c: + Add bugzilla ticket number to FIXME comment. + +2007-08-26 18:30:55 +0000 Thomas Vander Stichele + + * MAINTAINERS: + remove temp files again + Original commit message from CVS: + remove temp files again + +2007-08-26 16:42:36 +0000 Thomas Vander Stichele + + * MAINTAINERS: + test commit + Original commit message from CVS: + test commit + +2007-08-26 15:58:18 +0000 Thomas Vander Stichele + + * AUTHORS: + * MAINTAINERS: + test commit + Original commit message from CVS: + test commit + +2007-08-24 21:53:39 +0000 Wim Taymans + + docs/design/: Update some docs. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-block.txt: + Update some docs. + +2007-08-24 16:39:06 +0000 Jan Schmidt + + gst/Makefile.am: Revert patch which uses $(gst_headers) instead of $^ because it breaks make dist. + Original commit message from CVS: + * gst/Makefile.am: + Revert patch which uses $(gst_headers) instead of $^ because it + breaks make dist. + +2007-08-24 14:55:46 +0000 Jan Schmidt + + tests/check/gst/gstbin.c: Fix leaks in the new unit test. + Original commit message from CVS: + * tests/check/gst/gstbin.c: (GST_START_TEST): + Fix leaks in the new unit test. + +2007-08-23 20:41:30 +0000 Tim-Philipp Müller + + gst/gst.c: Don't use GST_INFO before the debug system is actually initialised (shouldn't do any harm, but won't print... + Original commit message from CVS: + * gst/gst.c: + Don't use GST_INFO before the debug system is actually initialised + (shouldn't do any harm, but won't print anything either, so we can + just as well remove it). + * gst/gstinfo.h: + GST_CAT_LEVEL_LOG_valist(), which is our inline helper function for + compilers that don't support variadic macros (such as MSVC), should + check for debug_level <= __gst_debug_min as well, since that's the + function called from all the level-specific GST_CAT_*_LOG_OBJECT() + inline helper functions. Should improve performance a bit, but also + makes sure uses of GST_INFO et.al are ignored if the debugging + system isn't initialised yet (instead of printing an assertion + failure). + +2007-08-23 07:10:33 +0000 David Nečas + + gst/Makefile.am: Replace some non portable makefile constructs. + Original commit message from CVS: + patch by: David Nečas + * gst/Makefile.am: + Replace some non portable makefile constructs. + +2007-08-21 14:10:09 +0000 Stefan Kost + + common/gtk-doc-plugins.mak: Grrrrr. Don't remove the types file on make clean. + Original commit message from CVS: + * common/gtk-doc-plugins.mak: + Grrrrr. Don't remove the types file on make clean. + +2007-08-20 17:51:35 +0000 Wim Taymans + + tools/gst-launch.1.in: Add colorspace to example pipeline. Fixes #458274. + Original commit message from CVS: + * tools/gst-launch.1.in: + Add colorspace to example pipeline. Fixes #458274. + +2007-08-20 12:31:54 +0000 Tim-Philipp Müller + + docs/random/release: The release manager should run 'make download-po' before making a release to make sure translati... + Original commit message from CVS: + * docs/random/release: + The release manager should run 'make download-po' before making a + release to make sure translations are up-to-date. + * po/LINGUAS: + * po/be.po: + * po/pl.po: + * po/rw.po: + Add some new translations. + +2007-08-17 13:48:24 +0000 Wim Taymans + + tools/gst-launch.c: Don´t try to do any state management when a live pipeline posts buffering messages. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop), (main): + Don´t try to do any state management when a live pipeline posts + buffering messages. + Also make the buffering string translatable. + +2007-08-16 11:04:40 +0000 Wim Taymans + + gst/gstbin.c: Improve debugging. + Original commit message from CVS: + * gst/gstbin.c: (is_eos), (gst_bin_add_func), + (bin_handle_async_start), (gst_bin_handle_message_func): + Improve debugging. + When adding elements, insert messages into the bus of the newly added + element and make sure the element is the source of the message. This + allows the parent bin to intercept the message and do the + right thing. It also avoids us posting ASYNC_START and CLOCK_PROVIDE + messages to the app (which is not allowed). + Update some docs. + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + Fix testsuite so that is does not work around messages that should not + have been posted in the first place. + +2007-08-16 10:27:16 +0000 Wim Taymans + + gst/gstbin.c: Fix annoying bug in the sorted iterator where a sink that is not really a sink (when it has downstream ... + Original commit message from CVS: + * gst/gstbin.c: (add_to_queue), (remove_from_queue), (clear_queue), + (update_degree), (gst_bin_sort_iterator_next): + Fix annoying bug in the sorted iterator where a sink that is not really + a sink (when it has downstream links) screwed up the iterator. + * tests/check/gst/gstbin.c: (GST_START_TEST), (gst_bin_suite): + Unit test to verify the fix. + +2007-08-16 10:07:48 +0000 Wim Taymans + + gst/gstmessage.h: Add some more docs for the messages. + Original commit message from CVS: + * gst/gstmessage.h: + Add some more docs for the messages. + * libs/gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_query): + Add some more debugging. + * tools/gst-launch.c: (event_loop): + When interrupting, don't try to set pipeline to PAUSED twice. + +2007-08-14 14:10:36 +0000 Wim Taymans + + gst/gstbin.c: Move ASYNC_START message posting to where it belongs, similar to async_done. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_element_set_state), + (bin_handle_async_start), (gst_bin_handle_message_func): + Move ASYNC_START message posting to where it belongs, similar to + async_done. + Don't post ASYNC_START when we are in error. + Post ASYNC_START when we added an async element to a bin. + +2007-08-14 13:43:44 +0000 Julien Moutte + + gst/gstindex.c: Fix index entry generation from vargs. Fixes #466595. + Original commit message from CVS: + 2007-08-14 Julien MOUTTE + * gst/gstindex.c: (gst_index_add_association): Fix index entry + generation from vargs. Fixes #466595. + +2007-08-14 13:37:16 +0000 Wim Taymans + + gst/gstbin.c: Always change the state of a NO_PREROLL element even if it has ASYNC elements inside (in case of a bin). + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_element_set_state): + Always change the state of a NO_PREROLL element even if it has ASYNC + elements inside (in case of a bin). + * tests/check/generic/sinks.c: (GST_START_TEST), (gst_sinks_suite): + Unit test for this case. + +2007-08-13 13:33:07 +0000 Stefan Kost + + Add more missing docs. + Original commit message from CVS: + * libs/gst/check/gstbufferstraw.c: + * libs/gst/check/gstcheck.h: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontrolsource.h: + * libs/gst/controller/gstlfocontrolsource.h: + * plugins/elements/gstcapsfilter.h: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.h: + Add more missing docs. + +2007-08-12 16:44:07 +0000 Wim Taymans + + gst/gststructure.c: Add Since tag to docs. + Original commit message from CVS: + * gst/gststructure.c: + Add Since tag to docs. + +2007-08-12 16:40:59 +0000 Wim Taymans + + Add function to get uint from a structure. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: (gst_structure_get_uint): + * gst/gststructure.h: + Add function to get uint from a structure. + API: gst_structure_get_uint() + +2007-08-12 16:38:40 +0000 Wim Taymans + + gst/gstcaps.c: Fix proper check for simple caps. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_set_simple_valist), + (gst_caps_intersect): + Fix proper check for simple caps. + +2007-08-10 17:35:30 +0000 Stefan Kost + + docs/: Remove cruft and do some cleanups. + Original commit message from CVS: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + Remove cruft and do some cleanups. + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + Prepare for comming gtkdoc features (rebase against online docs). + +2007-08-10 14:52:41 +0000 Michael Smith + + docs/gst/gstreamer-sections.txt: Add gst_registry_add_path to docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add gst_registry_add_path to docs. + Also fix formatting of an older changelog entry + +2007-08-10 14:40:26 +0000 Michael Smith + + gst/gstregistry.h: Add gst_registry_add_path, which was missing from this header. + Original commit message from CVS: + * gst/gstregistry.h: + Add gst_registry_add_path, which was missing from this header. + +2007-08-10 10:30:22 +0000 Tim-Philipp Müller + + libs/gst/controller/gstlfocontrolsource.c: Printf format fix. + Original commit message from CVS: + * libs/gst/controller/gstlfocontrolsource.c: + Printf format fix. + +2007-08-09 21:50:19 +0000 Philippe Kalaf + + libs/gst/base/gstbasesink.c: Don't send an async_start message during downwards state change if target state is less ... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + Don't send an async_start message during downwards state change if target + state is less than READY + +2007-08-09 10:50:22 +0000 Thomas Vander Stichele + + po/: Added Hungarian translation. + Original commit message from CVS: + translated by: Gabor Kelemen + * po/LINGUAS: + * po/hu.po: + Added Hungarian translation. + +2007-08-09 10:48:53 +0000 Thomas Vander Stichele + + po/: Updated translations. + Original commit message from CVS: + * po/fi.po: + * po/it.po: + * po/nl.po: + * po/sv.po: + * po/uk.po: + Updated translations. + +2007-08-07 16:06:47 +0000 Jan Schmidt + + libs/gst/controller/Makefile.am: Dist gstlfocontrolsourceprivate.h + Original commit message from CVS: + * libs/gst/controller/Makefile.am: + Dist gstlfocontrolsourceprivate.h + +2007-08-07 15:15:40 +0000 Jan Schmidt + + docs/libs/gstreamer-libs.types: Don't register the enum type gst_lfo_waveform_get_type() in the .types file - only GO... + Original commit message from CVS: + * docs/libs/gstreamer-libs.types: + Don't register the enum type gst_lfo_waveform_get_type() in the + .types file - only GObject derived types belong. + +2007-08-07 14:04:22 +0000 Wim Taymans + + gst/gstbuffer.h: Remove comma from last element in enum to avoid compile errors when using -pendantic. Fixes #464366. + Original commit message from CVS: + Patch by: + * gst/gstbuffer.h: + Remove comma from last element in enum to avoid compile errors when + using -pendantic. Fixes #464366. + +2007-08-07 09:56:08 +0000 Wim Taymans + + docs/design/part-TODO.txt: Add some more TODO items + Original commit message from CVS: + * docs/design/part-TODO.txt: + Add some more TODO items + * gst/gstbin.c: (find_message), (gst_bin_change_state_func): + Improve debugging. + * gst/gstcaps.c: (gst_caps_intersect): + Optimize trivial intersection case between identical caps pointers. + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_set_state_func): + * gst/gstpad.c: + Fix spelling and grammar mistakes. + +2007-08-05 14:48:06 +0000 Stefan Kost + + po/POTFILES.*: Update POTFILES. Fixes #461599. + Original commit message from CVS: + * po/POTFILES.in: + * po/POTFILES.skip: + Update POTFILES. Fixes #461599. + +2007-08-03 19:25:45 +0000 Sebastian Dröge + + gst/gst.c: Fix confusing typo in debug output. + Original commit message from CVS: + * gst/gst.c: + Fix confusing typo in debug output. + +2007-08-03 15:47:17 +0000 Sebastian Dröge + + libs/gst/controller/: API: Add GstLFOControlSource, a control source that gives values for specific timestamps based ... + Original commit message from CVS: + reviewed by: Stefan Kost + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstlfocontrolsource.c: (_calculate_pos), + (gst_lfo_waveform_get_type), (gst_lfo_control_source_reset), + (gst_lfo_control_source_new), + (gst_lfo_control_source_set_waveform), + (gst_lfo_control_source_bind), (gst_lfo_control_source_init), + (gst_lfo_control_source_finalize), + (gst_lfo_control_source_dispose), + (gst_lfo_control_source_set_property), + (gst_lfo_control_source_get_property), + (gst_lfo_control_source_class_init): + * libs/gst/controller/gstlfocontrolsource.h: + * libs/gst/controller/gstlfocontrolsourceprivate.h: + API: Add GstLFOControlSource, a control source that gives values + for specific timestamps based on several periodic waveforms. + Fixes #459717. + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + Add documentation and unit tests for GstLFOControlSource. + +2007-08-03 14:40:22 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.14 === + +2007-08-03 14:39:15 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * docs/random/release: + * gstreamer.doap: + * win32/common/config.h: + Release 0.10.14 + Original commit message from CVS: + Release 0.10.14 + +2007-08-03 13:20:50 +0000 Jan Schmidt + + * 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/fi.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-08-02 11:51:17 +0000 Tim-Philipp Müller + + gst/gstelement.*: Make strings passed to gst_element_class_set_details_simple() constant, as they should be (#462752). + Original commit message from CVS: + * gst/gstelement.c: (gst_element_class_set_details_simple): + * gst/gstelement.h: + Make strings passed to gst_element_class_set_details_simple() + constant, as they should be (#462752). + +2007-08-02 11:15:46 +0000 Wim Taymans + + gst/gstbin.c: Don't forget about the fact that some element went ASYNC even after a resync. This makes us post the AS... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_change_state_func), + (bin_handle_async_done), (gst_bin_handle_message_func): + Don't forget about the fact that some element went ASYNC even after a + resync. This makes us post the ASYNC_DONE message correctly. + Fixes #462558. + +2007-07-31 11:51:38 +0000 Jan Schmidt + + gst/gstregistry.c: When replacing an existing feature in the registry, make sure to continue holding a reference unti... + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_add_feature): + When replacing an existing feature in the registry, make sure to + continue holding a reference until we've replaced the name string + within our feature hash table. Make sure to use g_hash_table_replace + instead of g_hash_table_insert to ensure the new name string is used + as a key instead of the old one that we're about to free. + Fixes: #462085 + +2007-07-31 10:10:27 +0000 Jan Schmidt + + gst/gstpluginfeature.c: Revert patch from #459466 until after the release and we can work out exactly what the proble... + Original commit message from CVS: + * gst/gstpluginfeature.c: (gst_plugin_feature_finalize), + (gst_plugin_feature_set_name): + Revert patch from #459466 until after the release and we can work + out exactly what the problem is (if any). + +2007-07-26 15:48:40 +0000 Tim-Philipp Müller + + API: add GST_TAG_LICENSE_URI and GST_TAG_COPYRIGHT_URI (#451939). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + API: add GST_TAG_LICENSE_URI and GST_TAG_COPYRIGHT_URI (#451939). + +2007-07-26 14:05:23 +0000 Jan Schmidt + + docs/libs/Makefile.am: Include our build-prefix libs and includes before the generic ones to avoid linking against th... + Original commit message from CVS: + * docs/libs/Makefile.am: + Include our build-prefix libs and includes before the generic ones to + avoid linking against the installed libs when we want the build-tree + ones. + +2007-07-26 08:46:46 +0000 Steve Fink + + docs/pwg/building-testapp.xml: Mention that GST_PLUGIN_PATH or --gst-plugin-path might be needed if people try to bui... + Original commit message from CVS: + Patch by: Steve Fink + * docs/pwg/building-testapp.xml: + Mention that GST_PLUGIN_PATH or --gst-plugin-path might be needed + if people try to build or install the example from the plugin + template against a GStreamer from package using the configure + defaults. + +2007-07-25 22:29:57 +0000 Steve Fink + + tools/gst-inspect.1.in: Document --print-all and --print-plugin-auto-install-info command line options in man page. + Original commit message from CVS: + Patch by: Steve Fink + * tools/gst-inspect.1.in: + Document --print-all and --print-plugin-auto-install-info command + line options in man page. + +2007-07-25 18:46:49 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Add docs for new api function. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add docs for new api function. + +2007-07-25 18:37:12 +0000 Wim Taymans + + gst/gstelementfactory.*: API: gst_element_factory_has_interface() + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_has_interface): + * gst/gstelementfactory.h: + API: gst_element_factory_has_interface() + Added method to check if an element factory implements a named + interface. + +2007-07-25 13:00:23 +0000 Stefan Kost + + Another conditional doc check. + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer.types.in: + Another conditional doc check. + * gst/gstmessage.c: + * gst/gstparamspecs.h: + * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): + * gst/gstvalue.c: + * gst/gstxml.h: + API-doc fixes. + +2007-07-24 13:44:04 +0000 Stefan Kost + + gst/gstregistrybinary.c: Print error just once and with additional info. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_check_magic), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + Print error just once and with additional info. + +2007-07-24 13:38:21 +0000 Stefan Kost + + libs/gst/base/gsttypefindhelper.c: Cleanup the typefindhelper code and add private doc comments. + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (helper_find_peek), + (helper_find_suggest), (helper_find_get_length), + (gst_type_find_helper_get_range), (buf_helper_find_suggest), + (gst_type_find_helper_for_buffer): + Cleanup the typefindhelper code and add private doc comments. + +2007-07-24 12:32:31 +0000 Edward Hervey + + plugins/elements/gstcapsfilter.c: Fix capsfilter for cases where the caps set on capsfilter will provide additional i... + Original commit message from CVS: + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_class_init), + (gst_capsfilter_transform_size), (gst_capsfilter_prepare_buf): + Fix capsfilter for cases where the caps set on capsfilter will provide + additional information. + Fixes #449197 + +2007-07-24 11:31:09 +0000 Stefan Kost + + gst/gsttypefindfactory.c: Fix docs that recommened wrong function to use. + Original commit message from CVS: + * gst/gsttypefindfactory.c: + Fix docs that recommened wrong function to use. + +2007-07-23 13:03:43 +0000 Stefan Kost + + tools/gst-inspect.c: Also give media-type for typefinders in element output. + Original commit message from CVS: + * tools/gst-inspect.c: (print_plugin_features): + Also give media-type for typefinders in element output. + +2007-07-23 11:42:12 +0000 Stefan Kost + + gst/gstregistry.*: Speed up gst_registry_lookup_feature_locked() by using a hashmap. + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_init), (gst_registry_finalize), + (gst_registry_remove_features_for_plugin_unlocked), + (gst_registry_add_feature), (gst_registry_remove_feature), + (gst_registry_lookup_feature_locked): + * gst/gstregistry.h: + Speed up gst_registry_lookup_feature_locked() by using a hashmap. + Fixes #459501. + +2007-07-23 10:39:10 +0000 Stefan Kost + + gst/gstpluginfeature.c: Avoid double memory usage for pluginfeature names. Fixes #459466. + Original commit message from CVS: + * gst/gstpluginfeature.c: (gst_plugin_feature_finalize), + (gst_plugin_feature_set_name): + Avoid double memory usage for pluginfeature names. Fixes #459466. + +2007-07-22 18:26:32 +0000 Tim-Philipp Müller + + gst/gstpad.h: Small addition to GST_FLOW_IS_FATAL() docs: mention that elements driving the pipeline may need to expl... + Original commit message from CVS: + * gst/gstpad.h: + Small addition to GST_FLOW_IS_FATAL() docs: mention that elements + driving the pipeline may need to explicitly check for NOT_LINKED as + well, since IS_FATAL doesn't cover that. + +2007-07-22 18:16:19 +0000 Tim-Philipp Müller + + docs/pwg/advanced-types.xml: Fix typo and duplicate entry in video formats list. + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Fix typo and duplicate entry in video formats list. + +2007-07-22 12:18:46 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolation.c: Also round to the nearest int when using cubic interpolation. + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + Also round to the nearest int when using cubic interpolation. + +2007-07-21 21:20:37 +0000 Jan Schmidt + + libs/gst/controller/gstinterpolation.c: When linearly interpolating integer types, round to the nearest int by adding... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + When linearly interpolating integer types, round to the nearest int + by adding 0.5. Don't do it for float/double types. + Fixes the failing controller test on my machine, which is somehow + rounding differently than on the buildbots. + +2007-07-20 07:36:44 +0000 Stefan Kost + + tools/gst-plot-timeline.py: Better log parsing (categories can have -). Adjust text vs. lines, so that they span the ... + Original commit message from CVS: + * tools/gst-plot-timeline.py: + Better log parsing (categories can have -). Adjust text vs. lines, so + that they span the same y-range. + +2007-07-20 07:26:39 +0000 Stefan Kost + + docs/random/ensonic/: Save my thoughts. + Original commit message from CVS: + * docs/random/ensonic/audiobaseclasses.txt: + * docs/random/ensonic/dynlink.txt: + * docs/random/ensonic/profiling.txt: + Save my thoughts. + * docs/random/moving-plugins: + Add note to use g_assert type macros. + +2007-07-20 07:09:11 +0000 Stefan Kost + + Add libm check as we use in for plugins. + Original commit message from CVS: + * configure.ac: + * libs/gst/check/Makefile.am: + Add libm check as we use in for plugins. + +2007-07-18 14:31:21 +0000 Jan Schmidt + + gst/gstbin.c: Check that the state_cookie hasn't changed since the continue_func was scheduled. Avoids problems where... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_continue_func): + Check that the state_cookie hasn't changed since the continue_func + was scheduled. Avoids problems where the state changes back to + something it shouldn't be because it was changed in the meantime. + +2007-07-17 09:44:51 +0000 Stefan Kost + + gst/gstregistrybinary.c: Fix memory leak. Be less verbose in the log. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_save_const_string), + (gst_registry_binary_save_string), + (gst_registry_binary_save_pad_template), + (gst_registry_binary_save_feature), + (gst_registry_binary_save_plugin), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + Fix memory leak. Be less verbose in the log. + +2007-07-16 16:44:31 +0000 Jan Schmidt + + tests/check/elements/.cvsignore: Add file to cvsignore as commanded. + Original commit message from CVS: + * tests/check/elements/.cvsignore: + Add file to cvsignore as commanded. + +2007-07-16 16:04:49 +0000 Jan Schmidt + + tests/check/elements/multiqueue.c: Use a GStaticMutex to protect all cases where libcheck fail_if/fail_unless macros ... + Original commit message from CVS: + * tests/check/elements/multiqueue.c: (mq_dummypad_chain), + (mq_dummypad_event), (run_output_order_test): + Use a GStaticMutex to protect all cases where libcheck + fail_if/fail_unless macros might be called from multiple threads + simultaneously to avoid errors like: + "check_pack.c:107: :-1081725400:Bad message type arg" + +2007-07-16 15:19:06 +0000 Jan Schmidt + + tests/check/pipelines/stress.c: Make sure we set the pipeline back to the NULL state before dropping our final refere... + Original commit message from CVS: + * tests/check/pipelines/stress.c: (GST_START_TEST): + Make sure we set the pipeline back to the NULL state before + dropping our final reference. + +2007-07-16 14:55:26 +0000 Jan Schmidt + + tests/check/elements/tee.c: Make the tee stress-test a little less stressful so it doesn't just time out on slow-mach... + Original commit message from CVS: + * tests/check/elements/tee.c: (GST_START_TEST): + Make the tee stress-test a little less stressful so it doesn't just + time out on slow-machines, and remove a small race when it's starting + up by adding a get_state() call. + +2007-07-16 12:36:18 +0000 Stefan Kost + + gst/gst.c: Avoid reading registry twice on startup. Fixes #457322. + Original commit message from CVS: + * gst/gst.c: + Avoid reading registry twice on startup. Fixes #457322. + +2007-07-13 14:11:22 +0000 Jan Schmidt + + pkgconfig/: Substitute the CFLAGS for libcheck into our .pc file too so that dependent modules will pick it up proper... + Original commit message from CVS: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + Substitute the CFLAGS for libcheck into our .pc file too so that + dependent modules will pick it up properly if libcheck is installed + into some other prefix. + +2007-07-13 13:49:14 +0000 Jan Schmidt + + configure.ac: Revert the pkg-config check for libcheck, since it pulls in the wrong non-PIC libcheck.a on Ubuntu and ... + Original commit message from CVS: + * configure.ac: + Revert the pkg-config check for libcheck, since it pulls in the + wrong non-PIC libcheck.a on Ubuntu and probably Fedora too. We need + a proper solution, either from the check project, or something else. + +2007-07-12 11:10:22 +0000 Stefan Kost + + configure.ac: Use pkg-config to locate check. + Original commit message from CVS: + * configure.ac: + Use pkg-config to locate check. + +2007-07-10 20:10:16 +0000 Stefan Kost + + gst/gsttaglist.c: Fix doc syntax. + Original commit message from CVS: + * gst/gsttaglist.c: + Fix doc syntax. + * gst/gstutils.c: + * gst/gstutils.h: + Add deprecation guards. + * libs/gst/base/gstcollectpads.h: + Don't document object (this is implicitly private). + +2007-07-08 14:11:53 +0000 Tim-Philipp Müller + + gst/gststructure.c: When deserialising foo=bar without a type cast, check if it's a boolean before falling back to a ... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_parse_value): + When deserialising foo=bar without a type cast, check if it's a + boolean before falling back to a string type, otherwise things like + audiotestsrc ! audio/x-raw-int,signed=true ! fakesink won't work, + because the filtercaps end up having a signed=(string)true field, + which causes problems later when intersection caps. + * tests/check/gst/gststructure.c: (GST_START_TEST): + Add a unit test for this. + +2007-07-06 21:50:02 +0000 Sebastian Dröge + + libs/gst/controller/: API: Refactor GstController into the core controller which can take a GstControlSource for prov... + Original commit message from CVS: + Reviewed by: Stefan Kost + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_add_interpolation_control_source), + (gst_controlled_property_new), (gst_controlled_property_free), + (gst_controller_find_controlled_property), + (gst_controller_new_valist), (gst_controller_new_list), + (gst_controller_new), (gst_controller_remove_properties_valist), + (gst_controller_remove_properties_list), + (gst_controller_remove_properties), + (gst_controller_set_property_disabled), + (gst_controller_set_disabled), (gst_controller_set_control_source), + (gst_controller_get_control_source), (gst_controller_get), + (gst_controller_sync_values), (gst_controller_get_value_array), + (_gst_controller_dispose), (gst_controller_get_type), + (gst_controlled_property_set_interpolation_mode), + (gst_controller_set), (gst_controller_set_from_list), + (gst_controller_unset), (gst_controller_unset_all), + (gst_controller_get_all), (gst_controller_set_interpolation_mode): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstcontrolsource.c: + (gst_control_source_class_init), (gst_control_source_init), + (gst_control_source_get_value), + (gst_control_source_get_value_array), (gst_control_source_bind): + * libs/gst/controller/gstcontrolsource.h: + * libs/gst/controller/gsthelper.c: (gst_object_set_control_source), + (gst_object_get_control_source): + * libs/gst/controller/gstinterpolation.c: + (gst_interpolation_control_source_find_control_point_node), + (gst_interpolation_control_source_get_first_value), + (_interpolate_none_get), (interpolate_none_get), + (interpolate_none_get_boolean_value_array), + (interpolate_none_get_enum_value_array), + (interpolate_none_get_string_value_array), + (_interpolate_trigger_get), (interpolate_trigger_get), + (interpolate_trigger_get_boolean_value_array), + (interpolate_trigger_get_enum_value_array), + (interpolate_trigger_get_string_value_array): + * libs/gst/controller/gstinterpolationcontrolsource.c: + (gst_control_point_free), (gst_interpolation_control_source_reset), + (gst_interpolation_control_source_new), + (gst_interpolation_control_source_set_interpolation_mode), + (gst_interpolation_control_source_bind), + (gst_control_point_compare), (gst_control_point_find), + (gst_interpolation_control_source_set_internal), + (gst_interpolation_control_source_set), + (gst_interpolation_control_source_set_from_list), + (gst_interpolation_control_source_unset), + (gst_interpolation_control_source_unset_all), + (gst_interpolation_control_source_get_all), + (gst_interpolation_control_source_get_count), + (gst_interpolation_control_source_init), + (gst_interpolation_control_source_finalize), + (gst_interpolation_control_source_dispose), + (gst_interpolation_control_source_class_init): + * libs/gst/controller/gstinterpolationcontrolsource.h: + * libs/gst/controller/gstinterpolationcontrolsourceprivate.h: + API: Refactor GstController into the core controller which can take + a GstControlSource for providing actual values for timestamps. + Implement a interpolation control source and use this for backward + compatibility, deprecate a bunch of functions that are now handled + by GstControlSource or GstInterpolationControlSource. + Make it possible to disable the controller completely or only for + specific properties. Fixes #450711. + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + Add new functions and classes to the docs. + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + * tests/examples/controller/audio-example.c: (main): + Port unit test and example to the new API and add some new + unit tests. + +2007-07-05 09:06:02 +0000 Mark Nauwelaerts + + plugins/elements/gstmultiqueue.c: Implement non-default GstPadIntLinkFunction for multiqueue pads so that the pipelin... + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * plugins/elements/gstmultiqueue.c: + (gst_multi_queue_get_internal_links), (apply_buffer), + (single_queue_overrun_cb), (gst_single_queue_new): + Implement non-default GstPadIntLinkFunction for multiqueue pads so that + the pipeline layout can be tracked correctly. Fixes #453732. + +2007-07-05 08:42:42 +0000 Stefan Kost + + docs/: Simplity --extra-dir as gtkdoc scans recursively. + Original commit message from CVS: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Simplity --extra-dir as gtkdoc scans recursively. + +2007-07-03 17:01:51 +0000 Wim Taymans + + tools/gst-launch.c: When we got an error, there is no point in waiting for preroll when shutting down. + Original commit message from CVS: + * tools/gst-launch.c: (main): + When we got an error, there is no point in waiting for preroll when + shutting down. + +2007-07-03 16:26:29 +0000 Wim Taymans + + plugins/elements/gsttee.c: Be a lot smarter when deciding what srcpad to use for proxying the buffer_alloc. Also hand... + Original commit message from CVS: + * plugins/elements/gsttee.c: (gst_tee_base_init), + (gst_tee_request_new_pad), (gst_tee_release_pad), + (gst_tee_find_buffer_alloc), (gst_tee_buffer_alloc), + (gst_tee_do_push), (clear_pads), (gst_tee_handle_buffer), + (gst_tee_chain): + Be a lot smarter when deciding what srcpad to use for proxying + the buffer_alloc. Also handle pad added/removed when doing so. + Fixes #357959. + Keep track of what pads we already pushed on in case we have pads + added/removed while pushing. Fixes #374639 + * tests/check/Makefile.am: + * tests/check/elements/tee.c: (handoff), (GST_START_TEST), + (tee_suite): + Added unit test for pad resync. + +2007-07-01 21:31:18 +0000 Thomas Vander Stichele + + po/: Updated translations. + Original commit message from CVS: + * po/nl.po: + * po/sv.po: + Updated translations. + +2007-07-01 21:30:09 +0000 Thomas Vander Stichele + + po/: Added new Finnish translation. + Original commit message from CVS: + translation by: Tommi Vainikainen + * po/LINGUAS: + * po/fi.po: + Added new Finnish translation. + +2007-06-28 11:25:17 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: When figuring out when a queue is filled, use our internal time estimate based on s... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (apply_buffer), + (single_queue_overrun_cb): + When figuring out when a queue is filled, use our internal time estimate + based on segments, just like check_full does. + +2007-06-27 11:47:46 +0000 Jan Schmidt + + * ChangeLog: + Mention bug 430682 closed by previous commit. + Original commit message from CVS: + Mention bug 430682 closed by previous commit. + +2007-06-27 11:43:04 +0000 Stefan Kost + + gst/gstminiobject.c: Remove 3 do-nothing methods. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_mini_object_get_type): + Remove 3 do-nothing methods. + +2007-06-27 11:24:08 +0000 Tim Angus + + plugins/elements/gstcapsfilter.c: Take a reference instead of a copy when setting "caps". + Original commit message from CVS: + Patch by: Tim Angus + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_class_init), + (gst_capsfilter_set_property): + Take a reference instead of a copy when setting "caps". + Fix documentation to clarify this behaviour. Fixes #449414. + +2007-06-27 10:12:14 +0000 Stefan Kost + + gst/: Remove empty instance_init() functions to save relocs and lessen the noise. Remove some of the function prototy... + Original commit message from CVS: + * gst/gstindexfactory.c: (gst_index_factory_get_type): + * gst/gstplugin.c: (gst_plugin_init): + * gst/gstpluginfeature.c: (gst_plugin_feature_init): + * gst/gstquery.c: (gst_query_get_type): + * gst/gstregistry.c: (gst_registry_init): + * gst/gsturi.c: (gst_uri_handler_base_init): + Remove empty instance_init() functions to save relocs and lessen the + noise. Remove some of the function prototypes that are doubled by + G_DEFINE_TYPE. + +2007-06-27 09:34:01 +0000 Étienne Noreau-Hébert + + gst/gstghostpad.c: Add peer and direction in the XML serialisation of ghostpads. + Original commit message from CVS: + Patch by: Étienne Noreau-Hébert + * gst/gstghostpad.c: (gst_proxy_pad_save_thyself): + Add peer and direction in the XML serialisation of ghostpads. + Fixes #449226. + +2007-06-26 16:24:20 +0000 Stefan Kost + + configure.ac: Preserve useful information, thanks Tim. + Original commit message from CVS: + * configure.ac: + Preserve useful information, thanks Tim. + +2007-06-26 14:45:15 +0000 Jan Schmidt + + plugins/elements/gstmultiqueue.*: Take the multiqueue lock when updating the fill level so we don't get confused. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_init), + (gst_single_queue_flush), (apply_segment), (apply_buffer), + (gst_single_queue_push_one), (gst_multi_queue_loop), + (gst_multi_queue_sink_activate_push), (gst_multi_queue_sink_event), + (gst_multi_queue_src_activate_push), (wake_up_next_non_linked), + (compute_high_id), (gst_single_queue_new): + * plugins/elements/gstmultiqueue.h: + Take the multiqueue lock when updating the fill level so we don't get + confused. + After applying a buffer or event on the src pad segment, make sure to + call gst_data_queue_limits_changed() to get the data queue to unblock + and check the filled state again. + Rework the not-linked pad handling so the logic is that not-linked + pads can push as fast as they like, but only so they never get + ahead of any linked pads. + * tests/check/elements/multiqueue.c: (mq_sinkpad_to_srcpad), + (mq_dummypad_getcaps), (mq_dummypad_chain), (mq_dummypad_event), + (run_output_order_test), (GST_START_TEST), (multiqueue_suite): + Add a test to check that not-linked pads always stay behind + linked pads. + +2007-06-26 11:57:23 +0000 Jan Schmidt + + docs/random/release: Some updates to the release procedure. + Original commit message from CVS: + * docs/random/release: + Some updates to the release procedure. + +2007-06-26 08:26:36 +0000 Stefan Kost + + gst/gstelementfactory.c: Microoptimization that saves stunning 80 bytes. + Original commit message from CVS: + * gst/gstelementfactory.c: (__gst_element_details_clear): + Microoptimization that saves stunning 80 bytes. + +2007-06-25 12:35:46 +0000 Stefan Kost + + docs/plugins/: Update docs with caps info. + Original commit message from CVS: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + Update docs with caps info. + +2007-06-23 22:56:28 +0000 Thomas Vander Stichele + + po/it.po: Updated Italian translation. + Original commit message from CVS: + * po/it.po: + Updated Italian translation. + +2007-06-23 11:19:16 +0000 Thomas Vander Stichele + + * win32/common/config.h: + fix win32 arch + Original commit message from CVS: + fix win32 arch + +2007-06-23 11:18:46 +0000 Thomas Vander Stichele + + * gst/gstelement.h: + 80 line fix + Original commit message from CVS: + 80 line fix + +2007-06-23 11:15:11 +0000 Thomas Vander Stichele + + po/: Update Vietnamese translations. + Original commit message from CVS: + * ChangeLog: + * po/vi.po: + Update Vietnamese translations. + +2007-06-21 22:37:27 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesink.c: Remove unused signal enum. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + Remove unused signal enum. + +2007-06-21 18:00:58 +0000 Christian Schaller + + * MAINTAINERS: + update MAINTAINERS file to reflect current realities better + Original commit message from CVS: + update MAINTAINERS file to reflect current realities better + +2007-06-21 16:39:01 +0000 Jan Schmidt + + Beef up and include the docs for gst_type_register_static_full and gst_element_class_set_details_simple and add the A... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstutils.c: (gst_type_register_static_full): + Beef up and include the docs for gst_type_register_static_full and + gst_element_class_set_details_simple and add the API keyword + in the ChangeLog. + +2007-06-21 14:35:03 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Fix setting max-* properties after adding queues. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_set_property), + (update_time_level), (gst_single_queue_push_one), + (gst_multi_queue_chain), (gst_multi_queue_sink_event), + (single_queue_overrun_cb), (single_queue_underrun_cb), + (single_queue_check_full): + Fix setting max-* properties after adding queues. + Use IS_FILLED for checking visible items. + Signal overrun if multiple queues overrun. + Add extra debug output. + Patch by: Wim Taymans + +2007-06-21 14:29:05 +0000 Stefan Kost + + Saving relocations for GTypeInfo and GstElementDetails. Fixes #437457. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_class_set_details_simple): + * gst/gstelement.h: + * gst/gstutils.c: (gst_type_register_static_full): + * gst/gstutils.h: + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_base_init): + * plugins/elements/gstfakesink.c: (gst_fake_sink_base_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_base_init): + * plugins/elements/gstfdsink.c: (gst_fd_sink_base_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_base_init): + * plugins/elements/gstfilesink.c: (gst_file_sink_base_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_base_init): + * plugins/elements/gstidentity.c: (gst_identity_base_init): + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_base_init): + * plugins/elements/gstqueue.c: (gst_queue_base_init), + (apply_buffer), (gst_queue_chain): + * plugins/elements/gsttee.c: (gst_tee_base_init): + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_base_init), + (gst_type_find_element_class_init): + Saving relocations for GTypeInfo and GstElementDetails. Fixes #437457. + +2007-06-21 09:46:02 +0000 Tim-Philipp Müller + + docs/pwg/advanced-types.xml: Fix typo in iana.org URI. + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Fix typo in iana.org URI. + +2007-06-19 21:58:30 +0000 Andy Wingo + + tests/check/pipelines/simple-launch-lines.c + Original commit message from CVS: + 2007-06-19 Andy Wingo + * tests/check/pipelines/simple-launch-lines.c + (test_state_change_returns): Enable pull-mode tests now that + basesink has been fixed. + * libs/gst/base/gstbasesink.c (gst_base_sink_needs_preroll): + Changed from gst_base_sink_is_prerolled, reversing the sense of + the return value. Returns FALSE also if the sink is in pull mode, + in which case it needs no preroll. + (gst_base_sink_query, gst_base_sink_change_state): Update for + needs_preroll change. + (gst_base_sink_change_state): Add a case for READY_TO_PAUSED after + chaining up, in which we return SUCCESS directly if we activated + in pull mode instead of ASYNC. Involves countering an async_start + message sent before chaining up; not sure if this is correct, in + an ideal world we only send async-start when activating in push + mode. + +2007-06-19 21:28:54 +0000 Andy Wingo + + * ChangeLog: + * tests/check/pipelines/simple-launch-lines.c: + * win32/common/config.h: + tests/check/pipelines/simple-launch-lines.c + Original commit message from CVS: + 2007-06-19 Andy Wingo + * tests/check/pipelines/simple-launch-lines.c + (test_state_change_returns): New test, partially disabled until + basesink is fixed. + +2007-06-19 16:05:11 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Fix event leak. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (apply_buffer), + (gst_multi_queue_sink_event): + Fix event leak. + +2007-06-19 10:41:33 +0000 Wim Taymans + + gst/gstbin.c: Move the common code for posting state-change messages into one function. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_change_state_func), (bin_push_state_continue), + (bin_handle_async_start), (bin_handle_async_done), + (gst_bin_handle_message_func): + Move the common code for posting state-change messages into + one function. + Broadcast the state signal after we posted the messages. + Mark the bin as busy when it's doing a state-change. + Make sure async-start/done messages don't interfere with the bin's + state when it's busy. + After the state change, let the bin check which elements completed the + state change while it was busy so that it can update its state. + +2007-06-19 10:38:39 +0000 Jan Schmidt + + docs/random/release: Add a note about updating the doap file to the release checklist + Original commit message from CVS: + * docs/random/release: + Add a note about updating the doap file to the release checklist + +2007-06-18 16:44:07 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Make sure we don't reference the buffer/event after we have given away ownership in... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (apply_buffer), + (gst_single_queue_push_one), (gst_multi_queue_chain), + (gst_multi_queue_sink_event): + Make sure we don't reference the buffer/event after we have given away + ownership in the queue. + +2007-06-18 15:15:32 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Update queue state _after_ adding the item in the queue because else we could end u... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_flush), + (gst_multi_queue_chain), (gst_multi_queue_sink_event): + Update queue state _after_ adding the item in the queue because else we + could end up being full without the element added yet. + +2007-06-18 15:12:28 +0000 Wim Taymans + + gst/gstbin.*: Immediatly commit the toplevel bin state when receiving an async-done message. This enables us to avoid... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_init), (gst_bin_add_func), + (gst_bin_remove_func), (gst_bin_get_state_func), + (gst_bin_element_set_state), (gst_bin_continue_func), + (bin_push_state_continue), (bin_handle_async_start), + (bin_handle_async_done), (gst_bin_handle_message_func): + * gst/gstbin.h: + Immediatly commit the toplevel bin state when receiving an async-done + message. This enables us to avoid spawning a thread to commit the state + in some common cases and it also avoids some races. + Avoid spawning a state thread when adding/removing async elements to a + toplevel bin. Instead we immediatly update the bin state. + Get rid of iterating all the children when getting the state in the bin + because it is now always up-to-date. + Fix bug where locked elements would always return _SUCCESS even it they + returned NO_PREROLL before being locked. + Fix the order of the state_change, async-start/done messages that was + sometimes incorrect. + Mark the state_dirty field as deprecated, we don't need it anymore as we + are always up-to-date. + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_continue_state): + Small debug inprovements. + Return the previous element state return when nothing is pending instead + of blindly returning SUCCESS. + * tests/check/generic/sinks.c: (GST_START_TEST), (pad_blocked_cb), + (gst_sinks_suite): + Add a whole bunch of new testcases. + +2007-06-17 17:26:48 +0000 Thomas Vander Stichele + + po/: Update translations. + Original commit message from CVS: + * po/uk.po: + * po/vi.po: + Update translations. + +2007-06-15 14:37:28 +0000 Jan Schmidt + + gst/gstpad.c: Fix typo in the docs. + Original commit message from CVS: + * gst/gstpad.c: + Fix typo in the docs. + +2007-06-15 11:49:24 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: Add docs for new methods. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add docs for new methods. + +2007-06-15 11:35:22 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Don't use GSlice because we don't depend on >= 2.10 yet. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_item_destroy), + (gst_multi_queue_item_new): + Don't use GSlice because we don't depend on >= 2.10 yet. + +2007-06-15 11:09:38 +0000 Wim Taymans + + plugins/elements/gstmultiqueue.c: Remove debug printf. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_flush), + (update_time_level), (apply_segment), (apply_buffer), + (gst_single_queue_push_one), (gst_multi_queue_item_new), + (gst_multi_queue_loop), (gst_multi_queue_sink_activate_push), + (gst_multi_queue_sink_event), (single_queue_overrun_cb), + (single_queue_underrun_cb), (single_queue_check_full): + Remove debug printf. + +2007-06-15 11:00:32 +0000 Wim Taymans + + libs/gst/base/gstdataqueue.*: Various cleanups. + Original commit message from CVS: + * libs/gst/base/gstdataqueue.c: (gst_data_queue_cleanup), + (gst_data_queue_finalize), (gst_data_queue_locked_is_empty), + (gst_data_queue_set_flushing), (gst_data_queue_push), + (gst_data_queue_pop), (gst_data_queue_drop_head), + (gst_data_queue_limits_changed), (gst_data_queue_get_level): + * libs/gst/base/gstdataqueue.h: + Various cleanups. + Added methods to get the current levels and to inform the queue that the + 'full' limits changed. + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_init), + (gst_multi_queue_finalize), (gst_multi_queue_set_property), + (gst_single_queue_flush), (update_time_level), (apply_segment), + (apply_buffer), (gst_single_queue_push_one), + (gst_multi_queue_item_steal_object), + (gst_multi_queue_item_destroy), (gst_multi_queue_item_new), + (gst_multi_queue_loop), (gst_multi_queue_chain), + (gst_multi_queue_sink_activate_push), (gst_multi_queue_sink_event), + (gst_multi_queue_getcaps), (gst_multi_queue_src_activate_push), + (gst_multi_queue_src_query), (single_queue_overrun_cb), + (single_queue_underrun_cb), (single_queue_check_full), + (gst_single_queue_new): + Keep track of time in the queue by measuring the difference between + running_time on input and output. This gives more accurate results and + can compensate for segments correctly. + Make a queue by default only 5 buffers deep. We will now increase the + buffer size depending on the filledness of the other queues. + Factor out commong flush code. + Make sure we don't add additional refcounts to buffers when we can avoid + it. + Propagate GstFlowReturn differently. + Use GSlice for intermediate GstMultiQueueItems. + Keep track of EOS. + Resize queues on over and underruns based on filled level of other + queues. + When checking if the queue is filled, prefer to measure in time if we + can and fall back to bytes when no time is known. + * plugins/elements/gstqueue.c: + Fix return value. + +2007-06-15 10:48:19 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Work around the brokenness of the event vmethod in basetransform. Prefer to return ... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_event): + Work around the brokenness of the event vmethod in basetransform. Prefer + to return TRUE when the subclass returned FALSE (meaning don't forward + the event). + * libs/gst/base/gstbasetransform.h: + Clarify the docs. + +2007-06-15 10:43:51 +0000 Wim Taymans + + Improve debugging. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_push_event), (gst_pad_send_event): + * libs/gst/base/gstbasesrc.c: (gst_base_src_query_latency), + (gst_base_src_default_query), (gst_base_src_get_range), + (gst_base_src_start): + * tests/check/pipelines/parse-launch.c: (setup_pipeline): + Improve debugging. + +2007-06-15 07:27:00 +0000 Stefan Kost + + docs/pwg/advanced-types.xml: Added more formats to caps table. + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Added more formats to caps table. + +2007-06-15 07:02:04 +0000 Stefan Kost + + tools/gst-launch.c: Remove crufy code. GOption does not need this workaround. + Original commit message from CVS: + * tools/gst-launch.c: (main): + Remove crufy code. GOption does not need this workaround. + +2007-06-14 20:29:09 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Fix wrong getter for enums in controller. + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode): + Fix wrong getter for enums in controller. + +2007-06-14 17:36:19 +0000 Tim-Philipp Müller + + libs/gst/check/gstcheck.c: Intercept criticals and warnings in the Gst-Phonon log domain, so + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_init): + Intercept criticals and warnings in the Gst-Phonon log domain, so + ASSERT_CRITICAL() etc. can be used in gst-phonon's unit tests as + well. + +2007-06-14 16:07:09 +0000 Edward Hervey + + gst/gstparamspecs.c: Since this file doesn't include "gst.h" it will not go through the macros that disable GST_LOG i... + Original commit message from CVS: + * gst/gstparamspecs.c: (_gst_param_fraction_validate): + Since this file doesn't include "gst.h" it will not go through the + macros that disable GST_LOG if debugging was disabled. + +2007-06-14 15:56:03 +0000 Tim-Philipp Müller + + Ugly 'fix' for the controller unit test on the p5 bot: in fail_unless_equals_float() check whether the values are 'al... + Original commit message from CVS: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.h: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + Ugly 'fix' for the controller unit test on the p5 bot: in + fail_unless_equals_float() check whether the values are 'almost + equal' by allowing a small absolute error, which should be good + enough for our use cases (normal numbers and values close to 0). + Proper fixage left to floating point arithmetic aficionados. + +2007-06-14 12:03:44 +0000 Stefan Kost + + libs/gst/base/gstbasesink.c: Add two breaks thats where missing. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_reset_qos), + (gst_base_sink_render_object), (gst_base_sink_get_position): + Add two breaks thats where missing. + +2007-06-14 11:56:44 +0000 Tim-Philipp Müller + + API: add fail_unless_equals_float() and assert_equals_float(). + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstcheck.h: + API: add fail_unless_equals_float() and assert_equals_float(). + Add documentation for some of the macros. + * tests/check/libs/controller.c: (GST_START_TEST): + Use newly-added asserts. + +2007-06-14 10:33:28 +0000 Stefan Kost + + gst/gstpad.c: Show the caps change in the log to help spotting the case of not exactly matching caps. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer_full), (gst_pad_push): + Show the caps change in the log to help spotting the case of not + exactly matching caps. + +2007-06-14 08:52:51 +0000 Tim-Philipp Müller + + docs/pwg/building-boiler.xml: Fix typos, spotted by Thijs Vermeir (#447190). + Original commit message from CVS: + * docs/pwg/building-boiler.xml: + Fix typos, spotted by Thijs Vermeir (#447190). + +2007-06-13 16:15:23 +0000 Jan Schmidt + + docs/plugins/tmpl/.cvsignore: Ignore file to keep the buildbots happy + Original commit message from CVS: + * docs/plugins/tmpl/.cvsignore: + Ignore file to keep the buildbots happy + +2007-06-13 15:39:53 +0000 Jan Schmidt + + docs/plugins/: Pull fdsink into the docs too. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + Pull fdsink into the docs too. + +2007-06-11 07:14:53 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolation.c: Actually use the new functions with min/max checks for the trigger and none i... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + Actually use the new functions with min/max checks for the trigger and + none interpolation modes for get() and get_value_array() instead of + just the latter. + +2007-06-10 12:38:11 +0000 Sebastian Dröge + + libs/gst/controller/gstcontroller.c: Unset the minimum and maximum GValues when freeing the corresponding + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_free): + Unset the minimum and maximum GValues when freeing the corresponding + GstControllerProperty struct. + +2007-06-09 16:58:30 +0000 Sebastian Dröge + + libs/gst/controller/: Protect against values larger or smaller than the minimum or maximum allowed value for the prop... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_new): + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + (gst_controlled_property_find_control_point_node), + (interpolate_none_get), (interpolate_none_get_enum_value_array), + (interpolate_none_get_string_value_array), + (interpolate_trigger_get), + (interpolate_trigger_get_enum_value_array), + (interpolate_trigger_get_string_value_array): + Protect against values larger or smaller than the minimum or maximum + allowed value for the property when using values that can be compared. + Optimize trigger interpolator a bit by taking the last requested value + into account instead of always looping through the complete list. + Fix coding style a bit, everywhere else we use "return foo" instead + of "return (foo)". + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add unit test for the protection against too large or too small + values. + +2007-06-08 21:08:24 +0000 Sebastian Dröge + + docs/random/slomo/controller.txt: Add some thoughts about the future of the controller. + Original commit message from CVS: + * docs/random/slomo/controller.txt: + Add some thoughts about the future of the controller. + +2007-06-08 11:00:59 +0000 Wim Taymans + + plugins/elements/gstidentity.c: Don't overflow in retimestamping code. + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + Don't overflow in retimestamping code. + +2007-06-07 20:51:35 +0000 Sébastien Moutte + + libs/gst/controller/gstinterpolation.c: Use gst_util_guint64_to_gdouble for conversions. + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: (DEFINE_CUBIC_GET): + Use gst_util_guint64_to_gdouble for conversions. + * win32/common/libgstreamer.def: + Add new exported functions. + +2007-06-07 17:22:47 +0000 Tim-Philipp Müller + + gst/gstutils.c: Small docs addition. + Original commit message from CVS: + * gst/gstutils.c: + Small docs addition. + +2007-06-07 14:49:00 +0000 Stefan Kost + + README: Remove that test line again. + Original commit message from CVS: + * README: + Remove that test line again. + +2007-06-07 14:36:02 +0000 Stefan Kost + + README: Test commit mail sending. + Original commit message from CVS: + * README: + Test commit mail sending. + +2007-06-07 14:17:46 +0000 Stefan Kost + + configure.ac: Fix typo and test commit mail sending. + Original commit message from CVS: + * configure.ac: + Fix typo and test commit mail sending. + +2007-06-07 14:12:07 +0000 Stefan Kost + + tests/examples/controller/audio-example.c: Improve comment and test commit mail sending. + Original commit message from CVS: + * tests/examples/controller/audio-example.c: + Improve comment and test commit mail sending. + +2007-06-07 10:11:47 +0000 Wim Taymans + + gst/gstbin.c: Add helper function to find messages. + Original commit message from CVS: + * gst/gstbin.c: (find_message), (bin_replace_message), (is_eos), + (gst_bin_remove_func), (gst_bin_element_set_state), + (bin_handle_async_start), (bin_handle_async_done), + (gst_bin_handle_message_func): + Add helper function to find messages. + Generate the async-done messages together with the state change + messages. + Small cleanups in handling toplevel bins. + +2007-06-06 18:11:10 +0000 Tim-Philipp Müller + + Fix multiqueue leaking buffers and events when downstream or the queue are flushing. Make refcounting assumptions exp... + Original commit message from CVS: + * libs/gst/base/gstdataqueue.c: + * libs/gst/base/gstdataqueue.h: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_push_one), + (gst_multi_queue_item_new), (gst_multi_queue_chain), + (gst_multi_queue_sink_event): + * tests/check/elements/multiqueue.c: (multiqueue_suite): + Fix multiqueue leaking buffers and events when downstream or the + queue are flushing. Make refcounting assumptions explicit and + document them (shouldn't break existing code that uses it other than + maybe leak miniobjects, but that already happens anyway). Add unit + test for the most common flushing case. Fixes #423700. + +2007-06-06 14:20:01 +0000 Sebastian Dröge + + libs/gst/controller/gstcontroller.c: Clarify docs: The get_all, get_value_array(s) functions don't modify the GObject... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + Clarify docs: The get_all, get_value_array(s) functions + don't modify the GObject properties. + +2007-06-06 14:01:56 +0000 Sebastian Dröge + + libs/gst/controller/: Factor out the 'set' logic into gst_controller_set_unlocked for the gst_controller_set and gst_... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_prepend_default), + (gst_controlled_property_new), (gst_controller_set_unlocked), + (gst_controller_set), (gst_controller_set_from_list), + (gst_controller_unset), (gst_controller_unset_all): + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + Factor out the 'set' logic into gst_controller_set_unlocked for the + gst_controller_set and gst_controller_set_from_list functions. + To make life of the interpolators easier always add a control point + at timestamp zero with the default value. + In the linear interpolator make things more obvious by better variable + naming (slope). + Implement cubic interpolation mode (by using a natural cubic spline) + and map the quadratic interpolation mode to this too (as quadratic + doesn't make much sense, see discussion on the list). + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add unit test for the cubic interpolation mode and check everywhere + if the interpolation mode could be set as expected. + +2007-06-06 11:38:25 +0000 Tim-Philipp Müller + + gst/gstparamspecs.c: Don't use GLib-2.10 functions, we still depend on + Original commit message from CVS: + * gst/gstparamspecs.c: (gst_param_spec_fraction_get_type): + Don't use GLib-2.10 functions, we still depend on + GLib-how-old-is-it-again-2.8. + +2007-06-06 11:18:12 +0000 Tim-Philipp Müller + + API: add GstParamSpecFraction, so elements can have fraction properties without lots of painful string parsing (#4446... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gstparamspecs.c: (_gst_param_fraction_init), + (_gst_param_fraction_set_default), (_gst_param_fraction_validate), + (_gst_param_fraction_values_cmp), + (gst_param_spec_fraction_get_type), (gst_param_spec_fraction): + * gst/gstparamspecs.h: + * gst/gstvalue.c: + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gstparamspecs.c: (gst_dummy_obj_base_init), + (gst_dummy_obj_class_init), (gst_dummy_obj_init), + (gst_dummy_obj_set_property), (gst_dummy_obj_get_property), + (GST_START_TEST), (gst_param_spec_suite): + API: add GstParamSpecFraction, so elements can have fraction + properties without lots of painful string parsing (#444648). + +2007-06-05 16:25:06 +0000 Wim Taymans + + gst/gstobject.c: Fix signal signature. + Original commit message from CVS: + * gst/gstobject.c: (gst_object_class_init): + Fix signal signature. + * gst/gstsegment.c: + Add small clarification in the api docs. + * plugins/elements/gstfilesrc.c: (gst_file_src_set_location): + States are protected with object lock. + +2007-06-05 14:11:59 +0000 Jan Schmidt + + AUTHORS: I should probably be listed as an author by now. + Original commit message from CVS: + * AUTHORS: + I should probably be listed as an author by now. + * docs/random/release: + Update the release doc + +2007-06-05 13:49:10 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Make docs for gst_value_compare() mention return enums that actually exist. + Original commit message from CVS: + * gst/gstvalue.c: + Make docs for gst_value_compare() mention return enums that + actually exist. + +2007-06-05 13:21:41 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.13 === + +2007-06-05 12:47:23 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gstreamer.doap: + * win32/common/config.h: + * win32/vs6/grammar.dsp: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstcontroller.dsp: + * win32/vs6/libgstcoreelements.dsp: + * win32/vs6/libgstdataprotocol.dsp: + * win32/vs6/libgstnet.dsp: + * win32/vs6/libgstreamer.dsp: + Release 0.10.13 "With or without you" + Original commit message from CVS: + Release 0.10.13 "With or without you" + +2007-06-05 12:06:44 +0000 Jan Schmidt + + * 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/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-05-29 15:50:49 +0000 Thomas Vander Stichele + + * README: + trigger a mail + Original commit message from CVS: + trigger a mail + +2007-05-29 14:49:57 +0000 Thomas Vander Stichele + + * README: + trigger a mail + Original commit message from CVS: + trigger a mail + +2007-05-29 14:48:55 +0000 Thomas Vander Stichele + + * README: + trigger a mail + Original commit message from CVS: + trigger a mail + +2007-05-29 14:37:28 +0000 Thomas Vander Stichele + + * README: + send a mail + Original commit message from CVS: + send a mail + +2007-05-29 11:52:28 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 11:40:36 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 11:00:14 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 10:43:23 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 10:35:40 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 10:34:15 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-29 10:20:12 +0000 Thomas Vander Stichele + + * README: + test commit + Original commit message from CVS: + test commit + +2007-05-25 15:36:52 +0000 Wim Taymans + + gst/gstbin.c: Make sure that the child bin stops after completing the async state change so that the parent can conti... + Original commit message from CVS: + * gst/gstbin.c: (bin_handle_async_done): + Make sure that the child bin stops after completing the async state + change so that the parent can continue the state change to PLAYING. + Fixes #441159. + +2007-05-25 09:26:20 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: Use additional refcounting to avoid crashes when dynamically adding and removing pads... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize), + (unref_data), (gst_collect_pads_remove_pad), + (gst_collect_pads_check_pads): + Use additional refcounting to avoid crashes when dynamically adding and + removing pads. Fixes #420206. + +2007-05-24 15:00:55 +0000 Wim Taymans + + tools/gst-launch.c: When buffering goes from a two digit to a single digit number, make sure to remove the old second... + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + When buffering goes from a two digit to a single digit number, make sure + to remove the old second digit by writing a blank over it. + +2007-05-24 12:19:01 +0000 Tim-Philipp Müller + + libs/gst/base/gstdataqueue.c: Eliminate tabs and trailing comma in enum list; fix some typos. + Original commit message from CVS: + * libs/gst/base/gstdataqueue.c: + Eliminate tabs and trailing comma in enum list; fix some typos. + +2007-05-24 11:50:47 +0000 Wim Taymans + + tests/check/gst/gstbin.c: Allow refcount of 3 and 4 because some state thread might still be busy with it. + Original commit message from CVS: + * tests/check/gst/gstbin.c: (GST_START_TEST): + Allow refcount of 3 and 4 because some state thread might still be busy + with it. + +2007-05-24 09:41:51 +0000 Tim-Philipp Müller + + plugins/elements/: These are not installed headers, no need for padding. + Original commit message from CVS: + * plugins/elements/Makefile.am: + * plugins/elements/gstmultiqueue.h: + * plugins/elements/gstqueue.h: + These are not installed headers, no need for padding. + +2007-05-24 08:35:04 +0000 Wim Taymans + + gst/gstbin.c: Enable latency for next release. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_get_state_func), + (gst_bin_continue_func): + Enable latency for next release. + Restore STATE_LOCK around recalc_state that was left out during the + rewrite and could result in racy behaviour when _get_state and + recalc_state are run concurrently. See #440463. + +2007-05-23 13:56:25 +0000 Wim Taymans + + tests/check/gst/gstsystemclock.c: Improve test_async_order to also work when both timers are already expired when we ... + Original commit message from CVS: + * tests/check/gst/gstsystemclock.c: (store_callback), + (GST_START_TEST): + Improve test_async_order to also work when both timers are already + expired when we get scheduled to check it. + +2007-05-22 17:10:04 +0000 Tim-Philipp Müller + + gst/gstbin.*: 'private' is a c++ keyword, let's not use that in header files, otherwise c++ compilers will throw a ta... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_init), (gst_bin_dispose), + (gst_bin_set_property), (gst_bin_get_property), + (gst_bin_remove_func), (gst_bin_handle_message_func): + * gst/gstbin.h: + 'private' is a c++ keyword, let's not use that in header files, + otherwise c++ compilers will throw a tantrum. + +2007-05-22 11:55:33 +0000 Tim-Philipp Müller + + plugins/: Use #ifdef for HAVE_XYZ for consistency. + Original commit message from CVS: + * plugins/elements/gstelements.c: + * plugins/elements/gstfilesink.c: (gst_file_sink_do_seek), + (gst_file_sink_get_current_offset): + * plugins/indexers/gstindexers.c: (plugin_init): + Use #ifdef for HAVE_XYZ for consistency. + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/filesink.c: (setup_filesink), + (cleanup_filesink), (GST_START_TEST), (filesink_suite): + Add some unit tests for filesink. + +2007-05-22 11:43:07 +0000 Mark Nauwelaerts + + plugins/elements/gstfilesink.*: Fix position reporting; rename data_written member to current_pos to reflect its real... + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * plugins/elements/gstfilesink.c: (gst_file_sink_open_file), + (gst_file_sink_query), (gst_file_sink_do_seek), + (gst_file_sink_get_current_offset), (gst_file_sink_render): + * plugins/elements/gstfilesink.h: + Fix position reporting; rename data_written member to current_pos to + reflect its real meaning (fixes #412648). + +2007-05-22 11:09:45 +0000 Edward Hervey + + Add a property for bins that handle the state change of their childs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), + (gst_bin_dispose), (gst_bin_set_property), (gst_bin_get_property), + (gst_bin_remove_func), (gst_bin_handle_message_func): + * gst/gstbin.h: + Add a property for bins that handle the state change of their childs. + Fixes #435880 + +2007-05-22 10:21:31 +0000 Thomas Vander Stichele + + * docs/manual/appendix-quotes.xml: + * docs/manual/manual.xml: + add quote + Original commit message from CVS: + add quote + +2007-05-22 09:56:25 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolation.c: Use an array of the correct type when using _get_value_array with linear inte... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + Use an array of the correct type when using _get_value_array with + linear interpolation. + +2007-05-22 06:37:37 +0000 Stefan Kost + + * ChangeLog: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpipeline.c: + gst/gstelement.c (gst_element_requires_clock, gst_element_provides_clock, gst_element_request_pad, gst_element_class_... + Original commit message from CVS: + * gst/gstelement.c (gst_element_requires_clock, + gst_element_provides_clock, gst_element_request_pad, + gst_element_class_set_details, gst_element_class_set_details_simple, + gst_element_default_send_event, gst_element_abort_state, + gst_element_continue_state, gst_element_set_state, + gst_element_set_state_func, iterator_activate_fold_with_resync): + * gst/gstpad.c (gst_pad_activate_pull, gst_pad_set_getcaps_function, + gst_pad_fixate_caps, gst_pad_configure_sink, gst_pad_configure_src, + gst_pad_query, gst_pad_save_thyself, handle_pad_block, gst_pad_push, + gst_pad_get_range, gst_pad_pull_range): + * gst/gstpad.h (GST_PAD_LINK_SUCCESSFUL, GST_FLOW_CUSTOM_SUCCESS, + GST_FLOW_NOT_SUPPORTED, GST_FLOW_IS_FATAL, GstPadActivateFunction, + GstPadActivateModeFunction, GstPadChainFunction, + GstPadGetCapsFunction, GstPadAcceptCapsFunction, + GstPadFixateCapsFunction, GstPadTemplate): + * gst/gstpipeline.c (gst_pipeline_change_state, + gst_pipeline_set_new_stream_time, gst_pipeline_use_clock, + gst_pipeline_set_clock, gst_pipeline_auto_clock, + gst_pipeline_get_delay): + Whitespace and docs fixes. + +2007-05-21 21:48:07 +0000 Sebastian Dröge + + libs/gst/controller/gstinterpolation.c: Add support for retrieving value arrays when using the trigger interpolation ... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + (interpolate_trigger_get_enum_value_array), + (interpolate_trigger_get_string_value_array): + Add support for retrieving value arrays when using the trigger + interpolation mode. + +2007-05-21 21:34:49 +0000 Sebastian Dröge + + libs/gst/controller/gstcontroller.*: Clarify the docs of gst_controller_get_value_array(): The array where the values... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controller_get_value_array): + * libs/gst/controller/gstcontroller.h: + Clarify the docs of gst_controller_get_value_array(): The array where + the values should be written to must be allocated as there seems to be + no way to get the size of a random GType. This doesn't change any + behaviour. Also fix some typos all over the place and remove an unused, + commented function that is not necessary as g_object_set() could be + used instead. + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add unit test for gst_controller_get_value_array(). + +2007-05-21 14:50:51 +0000 Jan Schmidt + + tests/check/gst/gstbuffer.c: Disable part of the gst_buffer_try_new_and_alloc test, because it can happily succeed on... + Original commit message from CVS: + * tests/check/gst/gstbuffer.c: (GST_START_TEST): + Disable part of the gst_buffer_try_new_and_alloc test, because + it can happily succeed on 64-bit systems where there's more address + space available. + +2007-05-21 12:05:56 +0000 Sebastian Dröge + + tests/check/gst/gstpad.c: Add unit test for the improved caps checking from bug #421543. + Original commit message from CVS: + * tests/check/gst/gstpad.c: (GST_START_TEST), (gst_pad_suite): + Add unit test for the improved caps checking from bug #421543. + +2007-05-21 12:05:14 +0000 Wim Taymans + + docs/design/part-synchronisation.txt: Small addition. + Original commit message from CVS: + * docs/design/part-synchronisation.txt: + Small addition. + * gst/gstbin.c: (gst_bin_query): + * plugins/elements/gstqueue.c: (apply_segment): + Improve debugging. + * gst/gstmessage.h: + Improve docs. + +2007-05-21 12:00:42 +0000 Wim Taymans + + gst/gstpad.c: Added simple version of improved caps checking. It was previously assumed that a setcaps function would... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_caps_unlocked), + (gst_pad_acceptcaps_default), (gst_pad_configure_sink), + (gst_pad_configure_src): + Added simple version of improved caps checking. It was previously + assumed that a setcaps function would check the validity of the caps but + people prefer us to check caps against the template automatically. + Fixes #421543. + +2007-05-21 11:29:28 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.h: Fix macro for locking/unlocking the transform lock. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.h: + Fix macro for locking/unlocking the transform lock. + +2007-05-19 13:53:23 +0000 Tim-Philipp Müller + + docs/plugins/tmpl/.cvsignore: Ignore more. + Original commit message from CVS: + * docs/plugins/tmpl/.cvsignore: + Ignore more. + +2007-05-18 16:53:18 +0000 Edward Hervey + + plugins/elements/gstqueue.c: Hello, I am Mr Taymans' personal debugger. Today I will introduce a fix for the subtle a... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_loop): + Hello, I am Mr Taymans' personal debugger. Today I will introduce a fix + for the subtle art of warning a potentially blocking thread that it + should check the source pad return value, and relay the information + upstream. + +2007-05-18 11:20:33 +0000 Edward Hervey + + plugins/elements/gstqueue.c: Release the queue lock ! + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_handle_sink_event): + Release the queue lock ! + +2007-05-17 17:55:48 +0000 Sebastian Dröge + + docs/libs/gstreamer-libs-sections.txt: Add the two new controller functions to the appropiate places. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Add the two new controller functions to the appropiate places. + +2007-05-17 17:37:58 +0000 Sebastian Dröge + + libs/gst/controller/: API: gst_controller_suggest_next_sync(), gst_object_suggest_next_sync() + Original commit message from CVS: + reviewed by: Stefan Kost + * libs/gst/controller/gstcontroller.c: + (gst_controller_suggest_next_sync), (gst_controller_sync_values), + (_gst_controller_get_property), (_gst_controller_set_property), + (_gst_controller_init), (_gst_controller_class_init): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: (gst_object_suggest_next_sync), + (gst_object_get_control_rate), (gst_object_set_control_rate): + API: gst_controller_suggest_next_sync(), gst_object_suggest_next_sync() + Add API that provides sync suggestion timestamps for elements that + call gst_object_sync_values() from which those elements can subdivide + their processing loop to get the best results for the controlled + properties. For now it just suggests last_sync + control_rate as + new timestamp but this will be improved in the future. + While doing that change the control-rate property to a GstClockTime + from guint and change it's meaning from samples to nanoseconds as + the GstController doesn't know anything about sampling rate. Strictly + speaking this breaks ABI but as the control-rate property didn't do + anything in the past and as such couldn't be used this should be no + problem. + +2007-05-17 17:16:09 +0000 Sebastian Dröge + + libs/gst/controller/: Save last synced value from the list to continue searching from there in future syncs. This spe... + Original commit message from CVS: + reviewed by: Stefan Kost + * libs/gst/controller/gstcontroller.c: (gst_controller_unset), + (gst_controller_unset_all): + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + (gst_controlled_property_find_control_point_node): + Save last synced value from the list to continue searching from there + in future syncs. This speeds everything up a bit. + +2007-05-17 17:05:36 +0000 Sebastian Dröge + + libs/gst/controller/: Add a new private GstControlPoint struct which "inherits" from + Original commit message from CVS: + reviewed by: Stefan Kost + * libs/gst/controller/gstcontroller.c: (gst_control_point_compare), + (gst_control_point_find), (gst_controlled_property_new), + (gst_control_point_free), (gst_controlled_property_free), + (gst_controller_set), (gst_controller_set_from_list), + (gst_controller_unset), (gst_controller_unset_all), + (gst_controller_sync_values): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + (gst_controlled_property_find_control_point_node), + (interpolate_none_get), (interpolate_trigger_get): + Add a new private GstControlPoint struct which "inherits" from + GstTimedValue to allow different interpolators to store internal + values next to each control point. From the outside everything is + still a GstControlPoint so we don't loose binary compatibility. + Also fixup all the GValue handling to not leak GValues or list nodes. + * tests/check/libs/controller.c: (GST_START_TEST): + Free the list nodes and GValues in the controller_misc test. + +2007-05-17 11:05:22 +0000 Edward Hervey + + gst/gstsegment.c: Small doc fix. + Original commit message from CVS: + * gst/gstsegment.c: + Small doc fix. + +2007-05-16 19:35:46 +0000 Tim-Philipp Müller + + gst/gstplugin.c: If we fail to load a plugin because of unresolved symbols or missing libraries and spew a warning to... + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + If we fail to load a plugin because of unresolved symbols or missing + libraries and spew a warning to stderr, we may just as well mention + which plugin it was that failed to load. + +2007-05-13 20:28:14 +0000 David Schleef + + docs/Makefile.am: the gtk-doc makefile snippet correctly handles the case when ENABLE_GTK_DOC is false, and installs ... + Original commit message from CVS: + * docs/Makefile.am: the gtk-doc makefile snippet correctly + handles the case when ENABLE_GTK_DOC is false, and installs + the prebuilt documentation. So gtk-doc subdirs are + unconditionally enabled. Fixes: #349099. + +2007-05-13 20:11:27 +0000 David Schleef + + gst/gstutils.h: Reword some documentation. + Original commit message from CVS: + * gst/gstutils.h: Reword some documentation. + +2007-05-13 00:20:35 +0000 David Schleef + + gst/gstplugin.c: gst_plugin_register_func() doesn't actually do anything with the passed "module" parameter, so remov... + Original commit message from CVS: + * gst/gstplugin.c: gst_plugin_register_func() doesn't actually + do anything with the passed "module" parameter, so remove it. + Allows removal of additional vestigal code. + +2007-05-13 00:09:00 +0000 David Schleef + + gst/gstplugin.c: Using sigaction should depend on HAVE_SIGACTION, not HAVE_WIN32. + Original commit message from CVS: + * gst/gstplugin.c: + Using sigaction should depend on HAVE_SIGACTION, not HAVE_WIN32. + Switch to using g_stat() because it's more portable. + +2007-05-12 23:53:08 +0000 David Schleef + + gst/gst.c: Add GST_DISABLE_OPTION_PARSING, in order to disable option parsing for embedded systems. + Original commit message from CVS: + * gst/gst.c: + Add GST_DISABLE_OPTION_PARSING, in order to disable option + parsing for embedded systems. + * gst/gstelementfactory.c: + Allow gst_element_register() to be called with plugin==NULL. + Did nobody notice that static elements were broken? + +2007-05-12 15:38:02 +0000 Wim Taymans + + tools/gst-launch.c: Give more interesting info when buffering starts and stops. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Give more interesting info when buffering starts and stops. + Fix case where buffering starts but we fail to update the buffering flag + because the target state is not PLAYING. + +2007-05-12 15:35:40 +0000 Wim Taymans + + plugins/elements/gstqueue.*: Refactor an cleanup queue a bit. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_init), + (gst_queue_finalize), (update_time_level), (apply_segment), + (apply_buffer), (gst_queue_locked_flush), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue), + (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_push_one), (gst_queue_loop): + * plugins/elements/gstqueue.h: + Refactor an cleanup queue a bit. + Do better time level calculations that also work when the srcpad is not + yet running. + Remove some unneeded debug lines. + * tests/check/elements/queue.c: (GST_START_TEST), (queue_suite): + Added testcase for time level measurement. + Try to make some stuff more racefree. + +2007-05-11 14:46:10 +0000 Tim-Philipp Müller + + gst/gsturi.c: Don't leak plugin feature. + Original commit message from CVS: + * gst/gsturi.c: (gst_element_make_from_uri): + Don't leak plugin feature. + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gsturi.c: (GST_START_TEST), (gst_uri_suite): + Add brain-dead unit test. + +2007-05-11 14:28:55 +0000 Jeroen Wouters + + gst/gsturi.c: Treat protocol strings in a case-insensitive way (#437563). + Original commit message from CVS: + Patch by: Jeroen Wouters + * gst/gsturi.c: (gst_uri_get_protocol), (search_by_entry): + Treat protocol strings in a case-insensitive way (#437563). + +2007-05-11 10:56:48 +0000 Michael Smith + + gst/: Don't print a g_warning for any failure to load a shared object. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + * gst/gstregistry.c: (gst_registry_scan_path_level): + Don't print a g_warning for any failure to load a shared object. + Instead, push this down into gstplugin.c, and warn _only_ if we + failed to open the module (i.e. failure to link). + Avoids warnings on normal, working, non-plugin .so files. + +2007-05-11 08:29:10 +0000 Stefan Kost + + gst/gstplugin.c (gst_plugin_load_file): gst/gstregistry.c (GST_CAT_DEFAULT, gst_registry_lookup_feature_locked, gst_r... + Original commit message from CVS: + * gst/gstplugin.c (gst_plugin_load_file): + * gst/gstregistry.c (GST_CAT_DEFAULT, + gst_registry_lookup_feature_locked, gst_registry_scan_path_level): + Print a g_warning if there was an error when loading a plugins during + registry scan. The shuld help beginners starting with gst-plugin + template. + +2007-05-10 15:21:20 +0000 Wim Taymans + + plugins/elements/gstqueue.*: Be smarter when calculating the current amount of data in the queue by measuring the dif... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_class_init), + (update_time_level), (gst_queue_locked_flush), + (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_push_one), (gst_queue_loop): + * plugins/elements/gstqueue.h: + Be smarter when calculating the current amount of data in the queue by + measuring the difference between start and end timestamps (in running + time) inside the queue. Fixes #432876. + API: GstQueue::pushing to notify elements that we are pushing data again + since the running signal is rather broken for this purpose. + +2007-05-10 12:40:12 +0000 Stefan Kost + + * ChangeLog: + * common: + * plugins/elements/gstqueue.c: + plugins/elements/gstqueue.c (_do_init, gst_queue_signals, gst_queue_base_init, gst_queue_init): use GST_BOILERPLATE + Original commit message from CVS: + * plugins/elements/gstqueue.c (_do_init, gst_queue_signals, + gst_queue_base_init, gst_queue_init): + use GST_BOILERPLATE + +2007-05-09 21:06:06 +0000 Sébastien Moutte + + win32/common/libgstreamer.def: Add new exported functions. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add new exported functions. + * win32/vs6/grammar.dsp: + Use grammar pre-generated files. + +2007-05-09 16:32:07 +0000 Peter Kjellerstedt + + gst/: Maintain API and ABI when --disable-parse is used. Now that we have an appropriate error code, we can just retu... + Original commit message from CVS: + Based on patch by: Peter Kjellerstedt + * gst/Makefile.am: + * gst/gstparse.c: (gst_parse_launchv), (gst_parse_launch): + * gst/gstparse.h: + * gst/gstutils.c: (gst_parse_bin_from_description): + * gst/gstutils.h: + Maintain API and ABI when --disable-parse is used. Now that + we have an appropriate error code, we can just return NULL and the + appropriate error when gst_parse_launch() is used despite it having + been disabled (#342564). + * tests/check/Makefile.am: + * tests/check/pipelines/.cvsignore: + * tests/check/pipelines/parse-disabled.c: + Make sure these functions exist and return NULL plus a GError when + --disable-parse is used. + +2007-05-09 10:01:35 +0000 Tim-Philipp Müller + + tests/benchmarks/: Set a good example and don't leak messages. + Original commit message from CVS: + * tests/benchmarks/complexity.c: (main): + * tests/benchmarks/mass-elements.c: (main): + Set a good example and don't leak messages. + +2007-05-06 18:27:25 +0000 Stefan Kost + + docs/: Correct fixxrefs options. + Original commit message from CVS: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + Correct fixxrefs options. + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * plugins/elements/Makefile.am: + * plugins/elements/gstcapsfilter.c (gst_capsfilter_details): + * plugins/elements/gstcapsfilter.h (__GST_CAPSFILTER_H__, + GST_TYPE_CAPSFILTER, GST_CAPSFILTER, GST_CAPSFILTER_CLASS, + GST_IS_CAPSFILTER, GST_IS_CAPSFILTER_CLASS, GstCapsFilter, + GstCapsFilterClass, _GstCapsFilter, trans, filter_caps, + _GstCapsFilterClass, trans_class): + * plugins/elements/gstelements.c (name, rank, type, _elements): + * plugins/elements/gstidentity.c + (gst_identity_check_imperfect_timestamp, + gst_identity_check_imperfect_offset): + Document capsfilter and add doc-blurb to identity. + +2007-05-04 12:37:01 +0000 Tim-Philipp Müller + + libs/gst/controller/: Don't crash if someone tries to set an interpolation mode that is invalid or that isn't support... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode): + * libs/gst/controller/gstinterpolation.c: + Don't crash if someone tries to set an interpolation mode that + is invalid or that isn't supported yet. Fixes #422295. + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add a test case for the above. + +2007-05-03 16:44:34 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Properly set the last_stop position on GstSegment. This will only happen if there i... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_chain): + Properly set the last_stop position on GstSegment. This will only happen + if there is a buffer to push out. + +2007-05-03 14:58:05 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: always_in_place does not mean that the sink and source caps are the same! Make sure... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + always_in_place does not mean that the sink and source caps are the + same! Make sure we don't blindly proxy the buffer_alloc in this case. + +2007-05-03 14:54:34 +0000 Wim Taymans + + API: gst_base_src_query_latency(). Added method so that subclasses can easily get the latency values of the base sour... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: (gst_base_src_query_latency), + (gst_base_src_default_query), (gst_base_src_get_range): + * libs/gst/base/gstbasesrc.h: + API: gst_base_src_query_latency(). Added method so that subclasses can + easily get the latency values of the base source class. + +2007-05-03 09:24:58 +0000 Zaheer Abbas Merali + + tools/gst-inspect.c (print_implementation_info): Remove 0.8 cruft. + Original commit message from CVS: + * tools/gst-inspect.c (print_implementation_info): + Remove 0.8 cruft. + +2007-05-02 17:09:30 +0000 Tim-Philipp Müller + + tools/: Don't create a customised man page based on the host architecture, describe the default registry path generic... + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-launch.1.in: + Don't create a customised man page based on the host architecture, + describe the default registry path generically. That way the man + page is the same for all architectures and packagers have one + multilib issue less to deal with. Fixes #434926. + +2007-05-02 15:14:32 +0000 Wim Taymans + + gst/gstpad.c: Fix documentation as spotted by rg on IRC. + Original commit message from CVS: + * gst/gstpad.c: + Fix documentation as spotted by rg on IRC. + +2007-04-29 17:36:18 +0000 Stefan Kost + + gst/gstutils.c: Improve docs for gst_element_{link,unlink}. + Original commit message from CVS: + * gst/gstutils.c: + Improve docs for gst_element_{link,unlink}. + +2007-04-29 14:04:26 +0000 Thomas Vander Stichele + + * common: + * docs/README: + update README + Original commit message from CVS: + update README + +2007-04-28 11:29:54 +0000 Tim-Philipp Müller + + Typo fixes; minor docs addition. + Original commit message from CVS: + * docs/design/part-events.txt: + * docs/design/part-overview.txt: + * gst/gstevent.c: + * gst/gsturi.c: + * gst/gsturi.h: + * libs/gst/base/gstbasesink.c: + Typo fixes; minor docs addition. + +2007-04-27 08:30:59 +0000 Sebastian Dröge + + API: Add gst_uri_protocol_is_supported(), which checks if an sink or src that supports a given URI protocol exists. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: (get_element_factories_from_uri_protocol), + (gst_uri_protocol_is_supported), (gst_element_make_from_uri): + * gst/gsturi.h: + API: Add gst_uri_protocol_is_supported(), which checks if an sink + or src that supports a given URI protocol exists. + +2007-04-27 07:34:10 +0000 Sebastian Dröge + + plugins/elements/: Set the location to NULL if "file://" is set as URI. Otherwise some random previous URI would stil... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_uri_set_uri): + * plugins/elements/gstfilesrc.c: (gst_file_src_uri_set_uri): + Set the location to NULL if "file://" is set as URI. Otherwise + some random previous URI would still be set if "file://" is + set on an already used filesink/filesrc. + +2007-04-27 07:27:36 +0000 Sebastian Dröge + + plugins/elements/: Special case the "file://" URI as as this is used by some applications to test with gst_element_ma... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_uri_set_uri): + * plugins/elements/gstfilesrc.c: (gst_file_src_uri_set_uri): + Special case the "file://" URI as as this is used by some + applications to test with gst_element_make_from_uri if there's + an element that supports the URI protocol. + Also move the g_path_is_absolute() check for the location part + of the URI to also check this for "file://localhost/bla" URIs. + +2007-04-26 10:00:49 +0000 Tim-Philipp Müller + + API: add gst_buffer_try_new_and_alloc() plus unit test (#431940). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: (gst_buffer_try_new_and_alloc): + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: (GST_START_TEST), + (gst_buffer_suite): + API: add gst_buffer_try_new_and_alloc() plus unit test (#431940). + +2007-04-26 07:32:08 +0000 Stefan Kost + + gst/gstregistrybinary.*: Implement no-mmap alternative for registry reading. Do code cleanups. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write_cache), + (gst_registry_binary_load_pad_template), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + Implement no-mmap alternative for registry reading. Do code cleanups. + Add more comments about avoiding strdups for all text data. Comments + welcome. + +2007-04-25 12:30:27 +0000 Stefan Kost + + * ChangeLog: + * gst/gstregistrybinary.h: + gst/gstregistrybinary.h (GstBinaryPluginElement, + Original commit message from CVS: + * gst/gstregistrybinary.h (GstBinaryPluginElement, + GstBinaryPluginFeature, _GstBinaryElementFactory, plugin_feature, + GstBinaryElementFactory, _GstBinaryTypeFindFactory, plugin_feature): + Comment structs and reformat to fix the build (that stuff should go + into a priv. header). + +2007-04-25 11:44:29 +0000 Stefan Kost + + gst/gstregistrybinary.*: Refactor so that we can implement multiple features. Add support for + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_save_feature), + (gst_registry_binary_load_feature): + * gst/gstregistrybinary.h: + Refactor so that we can implement multiple features. Add support for + TypeFindFactory features. + +2007-04-24 06:14:35 +0000 Peter Kjellerstedt + + configure.ac: Fix AM_CONDITIONAL(GST_DISABLE_GST_DEBUG,...) and update comment. + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * configure.ac: + Fix AM_CONDITIONAL(GST_DISABLE_GST_DEBUG,...) and update comment. + +2007-04-23 07:30:38 +0000 Stefan Kost + + gst/gstbin.c: Fix build with --gst-disable-gst-debug + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_element_set_state), + (iterator_activate_fold_with_resync), (gst_bin_continue_func), + (bin_handle_async_done), (gst_bin_handle_message_func): + Fix build with --gst-disable-gst-debug + +2007-04-21 13:27:16 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasetransform.c: Make sure streaming has finished before calling the ::stop() vfunc, since that vfun... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_activate): + Make sure streaming has finished before calling the ::stop() vfunc, + since that vfunc might clear state which is being used in the + streaming thread. This fixes a race that caused crashes in + audioresample when shutting down a pipeline (#420106). + +2007-04-20 08:53:41 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: That was one byte missing. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + That was one byte missing. + +2007-04-20 08:39:35 +0000 Stefan Kost + + 2nd attempt to have a xml-less build as a joined effort of #413123 and #421480. + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstconfig.h.in: + * gst/gstobject.c: (gst_object_class_init), + (gst_signal_object_class_init): + * gst/gstobject.h: + 2nd attempt to have a xml-less build as a joined effort of #413123 + and #421480. + +2007-04-20 08:21:19 +0000 Stefan Kost + + docs/design/draft-tagreading.txt: Added open issues/thoughts to draft. + Original commit message from CVS: + * docs/design/draft-tagreading.txt: + Added open issues/thoughts to draft. + +2007-04-19 14:32:49 +0000 Sebastian Dröge + + gst/parse/: Update the prebuild parser sources. + Original commit message from CVS: + * gst/parse/grammar.tab.pre.c: + * gst/parse/grammar.tab.pre.h: + * gst/parse/lex._gst_parse_yy.pre.c: + Update the prebuild parser sources. + +2007-04-19 14:23:25 +0000 Sebastian Dröge + + gst/parse/Makefile.am: And now fix the building of the flex sources. Now everything should work as expected. + Original commit message from CVS: + * gst/parse/Makefile.am: + And now fix the building of the flex sources. Now everything should + work as expected. + +2007-04-19 14:06:52 +0000 Sebastian Dröge + + gst/parse/Makefile.am: Now hopefully fix the build failures by setting proper rule dependencies and moving instead of... + Original commit message from CVS: + * gst/parse/Makefile.am: + Now hopefully fix the build failures by setting proper rule + dependencies and moving instead of copying. + +2007-04-19 10:43:14 +0000 Stefan Kost + + tests/benchmarks/: Total licensification. + Original commit message from CVS: + * tests/benchmarks/complexity.gnuplot: + * tests/benchmarks/complexity.scm: + * tests/benchmarks/mass-elements.gnuplot: + * tests/benchmarks/mass-elements.scm: + Total licensification. + +2007-04-19 10:22:29 +0000 Stefan Kost + + gst/parse/Makefile.am: Fix the build by correcting the rule that gave wrong files to flex. + Original commit message from CVS: + * gst/parse/Makefile.am: + Fix the build by correcting the rule that gave wrong files to flex. + +2007-04-19 08:40:33 +0000 Stefan Kost + + tests/benchmarks/: Change licence to LGPL as granted by Benjamin and Andy. + Original commit message from CVS: + * tests/benchmarks/complexity.c: + * tests/benchmarks/mass-elements.c: + Change licence to LGPL as granted by Benjamin and Andy. + +2007-04-19 06:18:24 +0000 Sebastian Dröge + + gst/parse/Makefile.am: Add correct grammar.tab.h dependency if compiling without new enough flex. Fixes #431150. + Original commit message from CVS: + * gst/parse/Makefile.am: + Add correct grammar.tab.h dependency if compiling without new enough + flex. Fixes #431150. + +2007-04-18 13:34:48 +0000 Sebastian Dröge + + gst/parse/Makefile.am: Fix typo and use outdated sources if the flex/bison sources are newer than the pregenerated on... + Original commit message from CVS: + * gst/parse/Makefile.am: + Fix typo and use outdated sources if the flex/bison sources are newer + than the pregenerated ones but flex is too old. Print a warning in + that case. This should fix the build on the build bot. + +2007-04-18 12:34:51 +0000 Marc-Andre Lureau + + gst/parse/: Make the parser reentrant and recursively callable. This requires flex >= 2.5.31, for older versions preg... + Original commit message from CVS: + Patch by: Marc-Andre Lureau + * gst/parse/Makefile.am: + * gst/parse/grammar.y: + * gst/parse/parse.l: + Make the parser reentrant and recursively callable. This requires flex + >= 2.5.31, for older versions pregenerated sources are used as we + can't bump the build dependency. Finally fixes #349180. + * gst/gstparse.c: (gst_parse_launch): + Drop the HAVE_MT_SAVE_FLEX #ifdefs as we always use a new enough flex + now anyway. + * docs/gst/Makefile.am: + * docs/gst/Makefile.am: + * gst/parse/grammar.tab.pre.c: (__gst_parse_strdup), + (__gst_parse_strfree), (__gst_parse_link_new), + (__gst_parse_link_free), (__gst_parse_chain_new), + (__gst_parse_chain_free), (SET_ERROR), (YYPRINTF), + (gst_parse_element_set), (gst_parse_free_link), + (gst_parse_found_pad), (gst_parse_perform_delayed_link), + (gst_parse_perform_link), (yytnamerr), (yysyntax_error), (yyerror), + (_gst_parse_launch): + * gst/parse/grammar.tab.pre.h: + * gst/parse/lex._gst_parse_yy.pre.c: (PRINT), (yy_get_next_buffer), + (yy_get_previous_state), (yy_try_NUL_trans), (input), + (_gst_parse_yyrestart), (_gst_parse_yy_switch_to_buffer), + (_gst_parse_yy_load_buffer_state), (_gst_parse_yy_create_buffer), + (_gst_parse_yy_delete_buffer), (_gst_parse_yy_init_buffer), + (_gst_parse_yy_flush_buffer), (_gst_parse_yypush_buffer_state), + (_gst_parse_yypop_buffer_state), + (_gst_parse_yyensure_buffer_stack), (_gst_parse_yy_scan_buffer), + (_gst_parse_yy_scan_string), (_gst_parse_yy_scan_bytes), + (yy_fatal_error), (_gst_parse_yyget_extra), + (_gst_parse_yyget_lineno), (_gst_parse_yyget_column), + (_gst_parse_yyget_in), (_gst_parse_yyget_out), + (_gst_parse_yyget_leng), (_gst_parse_yyget_text), + (_gst_parse_yyset_extra), (_gst_parse_yyset_lineno), + (_gst_parse_yyset_column), (_gst_parse_yyset_in), + (_gst_parse_yyset_out), (_gst_parse_yyget_debug), + (_gst_parse_yyset_debug), (_gst_parse_yyget_lval), + (_gst_parse_yyset_lval), (_gst_parse_yylex_init), + (yy_init_globals), (_gst_parse_yylex_destroy), (yy_flex_strncpy), + (yy_flex_strlen), (_gst_parse_yyalloc), (_gst_parse_yyrealloc), + (_gst_parse_yyfree): + If the installed flex version is too old use pre-generated parser + sources. These pre-generated parser sources are always updated when + the actual flex/bison sources change but require everybody who wants + to change something in the parser to have flex >= 2.5.31 installed. + +2007-04-18 10:58:31 +0000 Stefan Kost + + Make --disable-nls to work + Original commit message from CVS: + * common/m4/gst-gettext.m4: + * gst/gst-i18n-lib.h: + Make --disable-nls to work + +2007-04-17 16:12:46 +0000 Wim Taymans + + gst/gstconfig.h.in: Revert previous change that broke the build. + Original commit message from CVS: + * gst/gstconfig.h.in: + Revert previous change that broke the build. + +2007-04-17 14:36:35 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + MANPATH fix + Original commit message from CVS: + MANPATH fix + +2007-04-17 10:46:46 +0000 Stefan Kost + + Drop libxml2 dependency when building with + Original commit message from CVS: + * configure.ac: + * gst/Makefile.am: + * gst/gstconfig.h.in: + Drop libxml2 dependency when building with + --enable-binary-registry --disable-loadsave + +2007-04-16 21:41:45 +0000 Thomas Vander Stichele + + * gstreamer.doap: + fix the release date in the doap file + Original commit message from CVS: + fix the release date in the doap file + +2007-04-16 19:45:31 +0000 Tim-Philipp Müller + + gst/gstregistrybinary.*: Remove unnecessary include which broke the win32 build with MingW; move include... + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write_cache), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + Remove unnecessary include which broke the win32 build + with MingW; move includes from header file to .c file, even if the + header file isn't installed; use g_strerror() where UTF-8 strings + are expected, such as in GST_DEBUG messages. + +2007-04-13 15:15:50 +0000 Jan Schmidt + + docs/libs/gstreamer-libs-sections.txt: Remove bogus addition for API I didn't end up keeping. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Remove bogus addition for API I didn't end up keeping. + * libs/gst/base/gstbasesrc.h: + Mention Since: 0.10.13 in the documentation. + Add the API keyword to the previous ChangeLog entry. + +2007-04-13 14:18:44 +0000 Jan Schmidt + + Allow basesrc derived classes to execute seeks in other formats by providing a prepare_seek_segment vmethod. Sub-clas... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_default_prepare_seek_segment), + (gst_base_src_prepare_seek_segment), (gst_base_src_perform_seek): + * libs/gst/base/gstbasesrc.h: + Allow basesrc derived classes to execute seeks in other formats + by providing a prepare_seek_segment vmethod. Sub-classes can choose + to prepare the GstSegment in any format that their perform_seek method + will be able to understand. The default implementation provides the + old behaviour of attempting to convert the seek offsets to the + configured native format. + +2007-04-13 11:53:00 +0000 Jan Schmidt + + gst/gstelement.c: Don't output the same debug statement twice. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_state_func): + Don't output the same debug statement twice. + * libs/gst/base/gstadapter.c: (gst_adapter_try_to_merge_up), + (gst_adapter_peek), (gst_adapter_take_buffer): + Optimise the case where we have buffers at the head of the queue that + can be joined quickly (because they're contiguous sub-buffers) by + merging them together rather than copying data out into new memory. + * gst/parse/grammar.y: + * tests/check/pipelines/parse-launch.c: + Fix a leak in an error path for parse_launch, and add a check + for it to the testsuite. + +2007-04-13 11:20:48 +0000 Jan Schmidt + + plugins/elements/gstmultiqueue.c: Don't deadlock when releasing a pad - gst_pad_set_active may try and take the multi... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_release_pad): + Don't deadlock when releasing a pad - gst_pad_set_active may try + and take the multiqueue lock too. + +2007-04-12 12:59:49 +0000 Tim-Philipp Müller + + gst/gsterror.*: API: add GST_CORE_ERROR_DISABLED (#392804). + Original commit message from CVS: + * gst/gsterror.c: (_gst_core_errors_init): + * gst/gsterror.h: + API: add GST_CORE_ERROR_DISABLED (#392804). + +2007-04-12 10:32:38 +0000 Thomas Vander Stichele + + docs/faq/gst-uninstalled: don't get empty paths on the PATH variables + Original commit message from CVS: + * docs/faq/gst-uninstalled: + don't get empty paths on the PATH variables + * gst/gstpad.c (gst_pad_is_active, gst_pad_set_blocked_async): + Don't format for the uncommon terminal width of 84 characters. + +2007-04-09 11:59:28 +0000 Thomas Vander Stichele + + * win32/common/config.h: + back to head + Original commit message from CVS: + back to head + +2007-04-09 08:17:13 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + don't format for the uncommon editor width of 84 characters + Original commit message from CVS: + don't format for the uncommon editor width of 84 characters + +2007-04-06 11:48:17 +0000 Wim Taymans + + gst/gstpipeline.c: Only try to select a different pipeline clock when we went back to + Original commit message from CVS: + * gst/gstpipeline.c: (reset_stream_time), + (gst_pipeline_change_state), (gst_pipeline_set_new_stream_time): + Only try to select a different pipeline clock when we went back to + PAUSED and not when we merely got flushed. + +2007-04-05 16:17:24 +0000 Michael Smith + + tools/gst-launch.1.in: fractions are better supported in gstreamer than ractions, so suggest using those. + Original commit message from CVS: + * tools/gst-launch.1.in: + fractions are better supported in gstreamer than ractions, so + suggest using those. + +2007-04-05 13:49:42 +0000 Thomas Vander Stichele + + * po/nl.po: + update dutch + Original commit message from CVS: + update dutch + +2007-04-05 13:46:54 +0000 Thomas Vander Stichele + + po/: Added Danish translation. + Original commit message from CVS: + Submitted by: Mogens Jaeger + * po/LINGUAS: + * po/da.po: + Added Danish translation. + +2007-04-05 11:16:09 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Fix leak caused when refusing newsegment after EOS. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + (gst_base_sink_queue_object_unlocked), (gst_base_sink_event): + Fix leak caused when refusing newsegment after EOS. + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init), + (gst_fake_sink_init), (gst_fake_sink_set_property), + (gst_fake_sink_get_property), (gst_fake_sink_preroll), + (gst_fake_sink_render), (gst_fake_sink_change_state): + * plugins/elements/gstfakesink.h: + Add num-buffers property to make the element generate EOS after a + configurable amount of buffers. + API: fakesink::num-buffers property. + * tests/check/elements/fakesink.c: (GST_START_TEST), + (fakesink_suite): + Fix GstBus leak in test. + Test for fakesink num-buffers. + +2007-04-05 10:10:08 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't accept anything after an EOS, return UNEXPECTED instead. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + (gst_base_sink_queue_object_unlocked), (gst_base_sink_event), + (gst_base_sink_change_state): + Don't accept anything after an EOS, return UNEXPECTED instead. + * tests/check/elements/fakesink.c: (GST_START_TEST), + (fakesink_suite): + Unit test for new EOS behaviour. + +2007-04-05 10:08:21 +0000 Wim Taymans + + gst/gstelement.c: Make padtemplates also work when they don't contain %s or %d. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_request_pad): + Make padtemplates also work when they don't contain %s or %d. + +2007-04-05 10:06:20 +0000 Wim Taymans + + Improve _adjust_unlocked() so that it overflows less. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: (gst_clock_adjust_unlocked), + (gst_clock_unadjust_unlocked), (gst_clock_set_calibration): + * gst/gstclock.h: + Improve _adjust_unlocked() so that it overflows less. + Add gst_clock_unadjust_unlocked to convert from external time to + internal time based on calibration. + Add some more debug. + API: GstClock::gst_clock_unadjust_unlocked() + +2007-04-03 11:02:41 +0000 Tommi Myöhänen + + plugins/elements/gstmultiqueue.c: Deactivate pads and free GstSingleQueue with gst_single_queue_free() when releasing... + Original commit message from CVS: + Patch by: Tommi Myöhänen + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_release_pad): + Deactivate pads and free GstSingleQueue with gst_single_queue_free() + when releasing sink pad. Fixes #425400. + +2007-04-02 14:48:12 +0000 Stefan Kost + + docs/random/ensonic/dynlink.txt: More work on proposal for new core api. + Original commit message from CVS: + * docs/random/ensonic/dynlink.txt: + More work on proposal for new core api. + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.h: + API: GST_BASE_TRANSFORM_LOCK/UNLOCK added + * libs/gst/controller/gstcontroller.c: + (on_object_controlled_property_changed), + (gst_controller_sync_values), + (gst_controller_set_interpolation_mode): + * libs/gst/controller/gstcontroller.h: + Less verbose logging add docs for unimplemented parts and correctly + return when using unavailable parts. + +2007-03-29 16:04:45 +0000 Jan Schmidt + + gst/gstclock.c: Move all the debug to the CLOCK category, and associate it with the clock object. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_set_master), (do_linear_regression): + Move all the debug to the CLOCK category, and associate it with + the clock object. + +2007-03-29 15:53:03 +0000 Jan Schmidt + + libs/gst/base/gstadapter.c: Make take_buffer a bit quicker by removing redundant checks caused by calling gst_adapter... + Original commit message from CVS: + * libs/gst/base/gstadapter.c: (gst_adapter_take_buffer): + Make take_buffer a bit quicker by removing redundant checks + caused by calling gst_adapter_take. + +2007-03-28 18:38:11 +0000 Tim-Philipp Müller + + plugins/elements/gstmultiqueue.c: Don't leak GCond. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_free): + Don't leak GCond. + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/multiqueue.c: (setup_multiqueue), + (GST_START_TEST), (multiqueue_suite): + Add some dead simple unit tests for the 'multiqueue' element + (some bits don't work yet and are disabled for now). + +2007-03-28 18:25:16 +0000 Tim-Philipp Müller + + gst/gstelement.c: Make gst_element_get_request_pad() create request pads only for request pad templates and not for, ... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_request_pad), + (gst_element_class_get_request_pad_template): + Make gst_element_get_request_pad() create request pads only for + request pad templates and not for, say, sometimes pad templates. + +2007-03-28 13:44:41 +0000 Stefan Kost + + docs/design/draft-klass.txt: Add example that needs more thinking. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Add example that needs more thinking. + * docs/design/draft-missing-plugins.txt: + More thoughts about wtrapper plugins. + * docs/random/ensonic/embedded.txt: + * docs/random/ensonic/profiling.txt: + More design work. + +2007-03-25 15:33:35 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Only push the segment events in the PLAYING state for live sources. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_range), + (gst_base_src_loop): + Only push the segment events in the PLAYING state for live sources. + +2007-03-23 17:52:19 +0000 Jan Schmidt + + gst/gstpipeline.c: Modify the clock distribution path in PAUSED->PLAYING so that we never attempt to choose a new clo... + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_change_state): + Modify the clock distribution path in PAUSED->PLAYING so that we + never attempt to choose a new clock unless we're actually leaving + the PAUSED state for the first time. This prevents choosing a + different clock when the state_change gets called for a 2nd time due + to some element doing an async state change. + +2007-03-22 18:28:00 +0000 Sebastian Dröge + + gst/gstpad.c: Revert last commit. This needs some more thoughts. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_caps), (gst_pad_configure_sink), + (gst_pad_configure_src), (gst_pad_alloc_buffer_full), + (gst_pad_chain_unchecked), (gst_pad_push): + Revert last commit. This needs some more thoughts. + +2007-03-22 17:12:23 +0000 Sebastian Dröge + + gst/gstpad.c: Check in set_caps if the caps are compatible with the pad and remove two functions that are redundant n... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_caps), (gst_pad_alloc_buffer_full), + (gst_pad_chain_unchecked), (gst_pad_push): + Check in set_caps if the caps are compatible with the pad and remove + two functions that are redundant now. Fixes #421543. + +2007-03-22 12:31:54 +0000 Wim Taymans + + tests/check/gst/gstsystemclock.c: Unref some more to make valgrind happy. + Original commit message from CVS: + * tests/check/gst/gstsystemclock.c: (GST_START_TEST), + (mixed_thread), (mixed_async_cb), (gst_systemclock_suite): + Unref some more to make valgrind happy. + +2007-03-22 11:58:08 +0000 Wim Taymans + + gst/gstsystemclock.c: Fix anoying regression that survived a few releases. When adding an async entry while blocking ... + Original commit message from CVS: + * gst/gstsystemclock.c: (gst_system_clock_id_wait_jitter_unlocked), + (gst_system_clock_id_wait_jitter), + (gst_system_clock_id_wait_async), (gst_system_clock_id_unschedule): + Fix anoying regression that survived a few releases. When adding an + async entry while blocking on a sync entry, the sync entry will unblock + but still be busy, so it should continue to wait instead of returning + _BUSY to the app. + Add some comments here and there. + * tests/check/gst/gstsystemclock.c: (mixed_thread), + (mixed_async_cb), (GST_START_TEST), (gst_systemclock_suite): + Add testcase for this. + +2007-03-22 11:19:32 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Handle errors from the clock sync better, only UNSCHEDULED indicates a + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_range): + Handle errors from the clock sync better, only UNSCHEDULED indicates a + WRONG_STATE and can silently pause the task. All other cases should + error out. + +2007-03-22 08:23:41 +0000 Wim Taymans + + gst/gstpad.c: Fix possible deadlock if pad eventfunc is not specified. Fixes #421177. + Original commit message from CVS: + Patch by: + * gst/gstpad.c: (gst_pad_alloc_buffer_full), (gst_pad_send_event): + Fix possible deadlock if pad eventfunc is not specified. Fixes #421177. + Improve debugging. + +2007-03-21 18:13:40 +0000 Michael Smith + + docs/pwg/advanced-types.xml: Fix some errors in the typefinding docs pointed out on irc. + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Fix some errors in the typefinding docs pointed out on irc. + +2007-03-21 17:50:46 +0000 Jan Schmidt + + libs/gst/base/gstbasesrc.c: Clarify FIXME comment in the face of having added unlock_stop() + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: + Clarify FIXME comment in the face of having added unlock_stop() + +2007-03-21 11:52:04 +0000 Wim Taymans + + gst/gstbin.c: Prepare for release where we warn against possible app breakage in the case of live pipelines along wit... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_element_set_state): + Prepare for release where we warn against possible app breakage in the + case of live pipelines along with an env var to enable/disable live + preroll mode (GST_COMPAT=[no-]live-preroll). + +2007-03-20 14:25:15 +0000 Zaheer Abbas Merali + + plugins/elements/gstidentity.c (gst_identity_check_imperfect_offset): So we should use correct constants for checking... + Original commit message from CVS: + * plugins/elements/gstidentity.c (gst_identity_check_imperfect_offset): + So we should use correct constants for checking for None offset. + +2007-03-20 14:17:47 +0000 Wim Taymans + + docs/design/part-block.txt: Mention the fact that the newly switched element should be set to at least PAUSED. + Original commit message from CVS: + * docs/design/part-block.txt: + Mention the fact that the newly switched element should be set to at + least PAUSED. + +2007-03-20 10:23:25 +0000 Wim Taymans + + gst/gst.c: Fix compilation with registry disabled as spotted by Saur. + Original commit message from CVS: + * gst/gst.c: + Fix compilation with registry disabled as spotted by Saur. + +2007-03-20 09:46:11 +0000 Olivier Crete + + gst/gstelement.c: Look at the pending state too when syncing the element state to the parent. Fixes #420133. + Original commit message from CVS: + Patch by: Olivier Crete + * gst/gstelement.c: (gst_element_sync_state_with_parent): + Look at the pending state too when syncing the element state to the + parent. Fixes #420133. + +2007-03-19 15:01:40 +0000 Jan Schmidt + + libs/gst/base/: Add ::unlock_stop to basesrc and basesink. This allows an opportunity for sub-classes to correctly cl... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_flushing), + (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_default_event), (gst_base_src_unlock_stop), + (gst_base_src_deactivate): + * libs/gst/base/gstbasesrc.h: + Add ::unlock_stop to basesrc and basesink. This allows an opportunity + for sub-classes to correctly clear any state they set trying to + unlock, such as clearing out unlock commands from a command fd. + * plugins/elements/gstfdsink.c: (gst_fd_sink_class_init), + (gst_fd_sink_render), (gst_fd_sink_unlock), + (gst_fd_sink_unlock_stop): + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init), + (gst_fd_src_init), (gst_fd_src_unlock), (gst_fd_src_unlock_stop), + (gst_fd_src_create), (gst_fd_src_get_size), (gst_fd_src_do_seek): + Implement unlock_stop in fdsrc and fdsink. + Implement seeking in fdsrc when a seekable fd is passed, as in + gst-launch-0.10 fdsrc ! ... ! xvimagesink < /path/to/file + +2007-03-19 12:07:32 +0000 Evan Nemerson + + gst/gstelement.c: Fix pad-added and pad-removed signal signatures so that the pad type is stated as GST_TYPE_PAD inst... + Original commit message from CVS: + Patch by: Evan Nemerson + * gst/gstelement.c: (gst_element_class_init): + Fix pad-added and pad-removed signal signatures so that the pad type is + stated as GST_TYPE_PAD instead of G_TYPE_OBJECT. Fixes #419851. + +2007-03-19 10:47:56 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Add new element field and method. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add new element field and method. + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), + (bin_remove_messages), (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_recalc_state), (gst_bin_get_state_func), + (gst_bin_element_set_state), (gst_bin_change_state_func), + (gst_bin_continue_func), (bin_bus_handler), + (bin_push_state_continue), (bin_handle_async_start), + (bin_handle_async_done), (gst_bin_handle_message_func): + Make async state changes a bit smarter by using new ASYNC_START and + ASYNC_DONE messages. This reduces the number of times we run the state + recalculation thread. + Don't change state of element with a pending ASYNC_START message. + Deprecate STATE_DIRTY messages. + * gst/gstelement.c: (gst_element_init), (gst_element_send_event), + (gst_element_get_state_func), (gst_element_continue_state), + (gst_element_lost_state), (gst_element_set_state_func), + (gst_element_change_state): + * gst/gstelement.h: + Keep the state that was last set by the app in a new element field. + Don't allow state changes when handling an element event. + Post ASYNC_START and ASYNC_DONE messages. + Change lost_state so that we go to PAUSED and wait for the parent to set + us to PLAYING again (so latency calculation can be performed) + Export gst_element_change_state() method so that subclasses can use it. + API: gst_element_change_state() + API: GST_STATE_TARGET + * gst/gstpipeline.c: (gst_pipeline_class_init), + (reset_stream_time), (gst_pipeline_change_state), + (gst_pipeline_handle_message), (gst_pipeline_set_new_stream_time): + Using the new ASYNC_START message we can reset the base_time when + needed. This can then be used to implement base_time redistribution in + flushing seeks so that we can remove the explicit seek handling. + Perform latency query and configuration when going to PLAYING. + * libs/gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_query), (gst_base_sink_change_state): + Post new ASYNC_START/ASYNC_DONE messages. + * tests/check/generic/sinks.c: (GST_START_TEST): + Fix test because the bin will not set the async element to PLAYING right + away. + * tests/check/gst/gstbin.c: (pop_async_done), (GST_START_TEST): + Make the message check a little stronger. + Handle ASYNC messages. + * tests/check/pipelines/cleanup.c: (GST_START_TEST): + * tests/check/pipelines/simple-launch-lines.c: (GST_START_TEST): + Expect ASYNC_DONE messages. + +2007-03-19 09:55:02 +0000 Wim Taymans + + Add ASYNC_START and ASYNC_DONE messages to prepare for latency support. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: (gst_message_new_async_start), + (gst_message_new_async_done), (gst_message_parse_info), + (gst_message_parse_async_start): + * gst/gstmessage.h: + Add ASYNC_START and ASYNC_DONE messages to prepare for latency + support. + +2007-03-15 22:33:14 +0000 Thomas Vander Stichele + + * docs/design/part-synchronisation.txt: + typos + Original commit message from CVS: + typos + +2007-03-15 12:37:50 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Now that we don't check for the 'Codec' keyword any longer in the klass, we shouldn't spew a war... + Original commit message from CVS: + * tools/gst-inspect.c: + (print_plugin_automatic_install_info_codecs): + Now that we don't check for the 'Codec' keyword any longer in the + klass, we shouldn't spew a warning if the klass isn't a decoder or + encoder (since it might be a Source/Network, for example). + +2007-03-14 17:24:18 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Don't require decoder/demuxer/depayloader elements or encoder/muxer/paylader elements to have 'C... + Original commit message from CVS: + * tools/gst-inspect.c: + (print_plugin_automatic_install_info_codecs): + Don't require decoder/demuxer/depayloader elements or + encoder/muxer/paylader elements to have 'Codec' as part of their + factory class string when introspecting a plugin's capabilities. + draft-klass.txt mentions that it might be removed in future, and + flump3dec doesn't have it as part of its class string, so chances + are others might also not have it. + +2007-03-14 15:42:01 +0000 Thomas Vander Stichele + + * docs/random/i18n: + update i18n doc + Original commit message from CVS: + update i18n doc + +2007-03-14 15:17:09 +0000 Thomas Vander Stichele + + * plugins/elements/gstqueue.c: + reformat + Original commit message from CVS: + reformat + +2007-03-14 15:15:45 +0000 Thomas Vander Stichele + + po/: Update translations from translation project + Original commit message from CVS: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update translations from translation project + +2007-03-14 13:40:28 +0000 Stefan Kost + + gst/gstchildproxy.c: Invert precondition check to be alike the ones in the mimiced gobject api. + Original commit message from CVS: + * gst/gstchildproxy.c: (gst_child_proxy_get_property), + (gst_child_proxy_set_property): + Invert precondition check to be alike the ones in the mimiced gobject + api. + +2007-03-14 11:21:48 +0000 Thomas Vander Stichele + + * libs/gst/base/gstbasesink.c: + fix misleading log statement + Original commit message from CVS: + fix misleading log statement + +2007-03-13 14:53:21 +0000 Stefan Kost + + docs/: Do some Architect work. + Original commit message from CVS: + * docs/design/draft-tagreading.txt: + * docs/random/ensonic/audiobaseclasses.txt: + Do some Architect work. + * gst/gstobject.c: (gst_object_set_name): + Add a WARNING. + * gst/gstpad.c: + Add docs that point from gst_pad_get_range to gst_pad_pull_range + +2007-03-12 15:27:05 +0000 Jan Schmidt + + gst/gstsystemclock.c: Defer starting the async system clock thread until the first async wait is scheduled. Fixes #41... + Original commit message from CVS: + * gst/gstsystemclock.c: (gst_system_clock_init), + (gst_system_clock_start_async), (gst_system_clock_id_wait_async): + Defer starting the async system clock thread until the first async + wait is scheduled. Fixes #414986. + +2007-03-12 14:23:16 +0000 Tim-Philipp Müller + + plugins/elements/gstmultiqueue.c: Fix small leak (free GstSingleQueue structure too, not only contents). + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_finalize), + (gst_single_queue_free): + Fix small leak (free GstSingleQueue structure too, not only contents). + +2007-03-10 15:44:44 +0000 Sébastien Moutte + + gst/gstbin.c: Use GST_STR_NULL to prevent NULL pointer to be passed to GST_CAT_DEBUG. + Original commit message from CVS: + * gst/gstbin.c:(gst_bin_add): + Use GST_STR_NULL to prevent NULL pointer to be passed to GST_CAT_DEBUG. + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + Add new exported functions. + +2007-03-09 16:39:29 +0000 Wim Taymans + + docs/plugins/gstreamer-plugins-sections.txt: Fix GstTee docs. + Original commit message from CVS: + * docs/plugins/gstreamer-plugins-sections.txt: + Fix GstTee docs. + +2007-03-09 16:30:38 +0000 Wim Taymans + + Add metadata copy functions. Fixes #393099. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: (gst_buffer_copy_metadata), (_gst_buffer_copy): + * gst/gstbuffer.h: + Add metadata copy functions. Fixes #393099. + * gst/gstutils.c: (gst_buffer_stamp): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer): + Use new metadata copy functions. + +2007-03-09 14:20:25 +0000 Thomas Vander Stichele + + plugins/elements/gstidentity.*: Separate out check-imperfect-timestamp and check-imperfect-offset. + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_init), (gst_identity_check_perfect), + (gst_identity_check_imperfect_timestamp), + (gst_identity_check_imperfect_offset), (gst_identity_transform_ip), + (gst_identity_set_property), (gst_identity_get_property): + * plugins/elements/gstidentity.h: + Separate out check-imperfect-timestamp and check-imperfect-offset. + Put back check-perfect as it was to keep compatibility. + +2007-03-09 12:34:46 +0000 Jan Schmidt + + gst/gstelement.c: There's no need to warn if VOID_PENDING is not NONE here, as long as the state is NULL it's ok, and... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_dispose): + There's no need to warn if VOID_PENDING is not NONE here, as + long as the state is NULL it's ok, and that's checked immediately + above. + +2007-03-08 17:58:57 +0000 Zaheer Abbas Merali + + plugins/elements/gstidentity.c: Fix check for perfect stream to ignore buffers with -1 offsets/offset ends when check... + Original commit message from CVS: + 2007-03-08 Zaheer Abbas Merali + * plugins/elements/gstidentity.c: (gst_identity_check_perfect): + Fix check for perfect stream to ignore buffers with -1 + offsets/offset ends when checking data contiguity. + +2007-03-08 16:26:44 +0000 Wim Taymans + + tools/gst-launch.c: Print INFO messages. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Print INFO messages. + +2007-03-08 11:40:18 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.*: Add support for dropping buffers with custom GstFlowReturn. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_eventfunc), + (gst_base_transform_handle_buffer), (gst_base_transform_chain), + (gst_base_transform_activate): + * libs/gst/base/gstbasetransform.h: + Add support for dropping buffers with custom GstFlowReturn. + Set DISCONT flags on outgoing buffers based on QoS, incomming DISCONT + buffers or dropped buffers. + * docs/libs/gstreamer-libs-sections.txt: + docs for new custom return code. + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + Use drop support in base class to implement drop-probability. + +2007-03-07 17:26:49 +0000 Tim-Philipp Müller + + gst/: Remove newlines at end of debug log strings. + Original commit message from CVS: + * gst/gst.c: (load_plugin_func): + * gst/gstplugin.c: (gst_plugin_load_by_name), (gst_plugin_load): + * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): + * gst/gsttrace.c: (gst_trace_new), (gst_alloc_trace_set_flags_all): + Remove newlines at end of debug log strings. + +2007-03-07 17:14:53 +0000 Zaheer Abbas Merali + + plugins/elements/gstidentity.c: Only post bus message at max, once per buffer received. + Original commit message from CVS: + 2007-03-07 Zaheer Abbas Merali + * plugins/elements/gstidentity.c: (gst_identity_check_perfect): + Only post bus message at max, once per buffer received. + +2007-03-07 17:13:17 +0000 Wim Taymans + + docs/design/: Add doc about synchronisation + Original commit message from CVS: + * docs/design/Makefile.am: + * docs/design/part-synchronisation.txt: + Add doc about synchronisation + * docs/design/draft-latency.txt: + * docs/design/part-TODO.txt: + * docs/design/part-clocks.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-live-source.txt: + * docs/design/part-messages.txt: + * docs/design/part-overview.txt: + * docs/design/part-streams.txt: + * docs/design/part-trickmodes.txt: + Documentation updates. + +2007-03-07 17:09:57 +0000 Jan Schmidt + + gstreamer.doap: Update the doap file. + Original commit message from CVS: + * gstreamer.doap: + Update the doap file. + +2007-03-07 17:02:51 +0000 Zaheer Abbas Merali + + plugins/elements/gstidentity.c: Rename non-perfect to imperfect for Mike and for the sanctity of the language. + Original commit message from CVS: + 2007-03-07 Zaheer Abbas Merali + * plugins/elements/gstidentity.c: (gst_identity_check_perfect): + Rename non-perfect to imperfect for Mike and for the sanctity of + the language. + Also make sure bus message gets emitted for data-incontiguities. + +2007-03-07 16:58:42 +0000 Zaheer Abbas Merali + + plugins/elements/gstidentity.*: Emit bus message if check-perfect is true and we encounter a non-perfect stream betwe... + Original commit message from CVS: + 2007-03-07 Zaheer Abbas Merali + * plugins/elements/gstidentity.c: (gst_identity_check_perfect), + (gst_identity_start): + * plugins/elements/gstidentity.h: + Emit bus message if check-perfect is true and we encounter a + non-perfect stream between 2 consecutive buffers. + Fixes #415394. + +2007-03-07 16:55:02 +0000 Jan Schmidt + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.12 === + +2007-03-07 16:44:04 +0000 Jan Schmidt + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + Release 0.10.12 + Original commit message from CVS: + Release 0.10.12 + +2007-03-07 16:31:30 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-03-07 12:51:20 +0000 Jan Schmidt + + * common: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-03-01 18:46:36 +0000 Jan Schmidt + + configure.ac: Version 0.10.11.2 (0.10.12 pre-release) + Original commit message from CVS: + * configure.ac: + Version 0.10.11.2 (0.10.12 pre-release) + Bump libtool versioning. + +2007-03-01 14:49:41 +0000 Stefan Kost + + libs/gst/base/gstbasesrc.c: Log flow-names and not numbers. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_loop): + Log flow-names and not numbers. + +2007-02-28 19:25:48 +0000 Thomas Vander Stichele + + configure.ac: Convert to new AG_GST style. + Original commit message from CVS: + * configure.ac: + Convert to new AG_GST style. + +2007-02-28 18:51:47 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't unref query twice. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency): + Don't unref query twice. + +2007-02-28 16:57:49 +0000 Wim Taymans + + gst/gstvalue.c: Implement GstObject -> string transform so we print object names when serializing GValues containing ... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_transform_object_string), + (_gst_value_initialize): + Implement GstObject -> string transform so we print object names + when serializing GValues containing GstObjects. + +2007-02-28 16:55:53 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Add new stuff to docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add new stuff to docs. + +2007-02-28 16:46:07 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Improve latency query code. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_query_latency), + (gst_base_sink_queue_object_unlocked), (gst_base_sink_send_event), + (gst_base_sink_change_state): + Improve latency query code. + Don't leak latency events. + * tests/check/gst/gstbin.c: (GST_START_TEST): + Improve debugging. + +2007-02-28 16:43:43 +0000 Wim Taymans + + gst/gstelement.*: Improve docs a little. Added Since: for new macro. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_message_full), + (gst_element_get_state_func): + * gst/gstelement.h: + Improve docs a little. Added Since: for new macro. + * gst/gstobject.c: (gst_object_sink): + * gst/gstpipeline.c: (gst_pipeline_change_state), + (gst_pipeline_set_new_stream_time): + * gst/gstpipeline.h: + Improve debugging and docs. + * gst/gstutils.c: (gst_element_state_change_return_get_name): + Improve debugging. + +2007-02-28 16:40:02 +0000 Wim Taymans + + gst/gstelement.c: Handle INFO messages from the GST_ELEMENT_INFO macro as well. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_message_full), + (gst_element_set_locked_state), (gst_element_get_state_func), + (gst_element_change_state): + Handle INFO messages from the GST_ELEMENT_INFO macro as well. + Documentation updates. + Small code cleanups. + * gst/gstmessage.c: (gst_message_new_info), + (gst_message_parse_info): + * gst/gstmessage.h: + API: gst_message_new_info() + API: gst_message_parse_info() + Add INFO message create and parse code. + +2007-02-28 16:35:48 +0000 Wim Taymans + + gst/gstbin.c: Also report the live parameter of a latency query. + Original commit message from CVS: + * gst/gstbin.c: (bin_query_min_max_init), (bin_query_latency_fold), + (bin_query_latency_done): + Also report the live parameter of a latency query. + +2007-02-28 12:57:42 +0000 Thomas Vander Stichele + + * tests/check/generic/states.c: + plug test leak + Original commit message from CVS: + plug test leak + +2007-02-28 12:43:57 +0000 Thomas Vander Stichele + + * tests/check/Makefile.am: + actually use the env var for tests + Original commit message from CVS: + actually use the env var for tests + +2007-02-28 12:40:45 +0000 Thomas Vander Stichele + + tests/check/generic/states.c: Copy the current generic/states example from -base and adapt so we can use the exact sa... + Original commit message from CVS: + * tests/check/generic/states.c: (GST_START_TEST), (states_suite): + Copy the current generic/states example from -base and adapt so + we can use the exact same code everywhere. + Check a STATES_IGNORE_ELEMENTS env var which can be used + to ignore certain element factories for this test, which is + what is being done in -base + * tests/check/Makefile.am: + Mention this environment variable. + +2007-02-27 17:22:07 +0000 Wim Taymans + + API: gst_bus_timed_pop() + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbus.c: (gst_bus_init), (gst_bus_dispose), (gst_bus_post), + (gst_bus_timed_pop), (gst_bus_pop): + * gst/gstbus.h: + API: gst_bus_timed_pop() + Implement gst_bus_timed_pop() to do a blocking timed wait for a + message to arrive on the bus. + * tests/check/gst/gstbus.c: (GST_START_TEST), (pop_thread), + (gst_bus_suite): + Two unit tests for new _timed_pop() function. + +2007-02-23 17:42:06 +0000 Wim Taymans + + gst/gstpipeline.c: Don't ref a NULL clock in _provide_clock_func(). + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_change_state), + (gst_pipeline_provide_clock_func), (gst_pipeline_set_delay): + Don't ref a NULL clock in _provide_clock_func(). + Don't allow an INVALID delay. + Don't try to calculate base_time with an invalid start_time. + Also distribute and notify a NULL clock when it was selected. + * tools/gst-launch.c: (event_loop): + Don't crash when a NULL clock was selected in the pipeline. + +2007-02-23 13:42:19 +0000 Tim-Philipp Müller + + docs/: Some small updates: update plugin system identifier prefix mention our new install + Original commit message from CVS: + * docs/design/Makefile.am: + * docs/design/draft-missing-plugins.txt: + * docs/random/draft-missing-plugins.txt: + Some small updates: update plugin system identifier prefix + ('gstreamer.net' to 'gstreamer'), mention our new install + API in libgstbaseutils rather than libgimme-codec, add + reference to the online docs. + +2007-02-21 15:35:19 +0000 Thomas Vander Stichele + + win32/common/config.h: Pretty sure Bill never made a powerpc version. Powerpc hackers, use moap cl ci to only check ... + Original commit message from CVS: + * win32/common/config.h: + Pretty sure Bill never made a powerpc version. Powerpc hackers, + use moap cl ci to only check in what is mentioned in the ChangeLog. + +2007-02-21 15:34:14 +0000 Thomas Vander Stichele + + Fix up documentation to link to the correct GstGError section. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.h: + Fix up documentation to link to the correct GstGError section. + Add GST_ELEMENT_INFO macro since someone else added a Info message. + +2007-02-21 15:30:53 +0000 Thomas Vander Stichele + + tools/gst-launch.c: Make sure that we actually show the important message part of a warning message. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Make sure that we actually show the important message part of a + warning message. + No need to check if the gerror is not NULL to free; first of all + g_free accepts NULL; and second the default error handler would + segfault if gerror was NULL. + +2007-02-21 12:10:14 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Removed docs as well. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Removed docs as well. + +2007-02-21 12:01:41 +0000 Wim Taymans + + gst/gstmessage.*: Remove new messages for release. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_parse_duration): + * gst/gstmessage.h: + Remove new messages for release. + +2007-02-20 18:02:50 +0000 Wim Taymans + + Make the ghostpad a parent of the internal pad again for better backward compatibility. Don't write code that relies ... + Original commit message from CVS: + * docs/design/part-gstghostpad.txt: + * gst/gstghostpad.c: (gst_ghost_pad_dispose), + (gst_ghost_pad_new_full): + Make the ghostpad a parent of the internal pad again for better backward + compatibility. Don't write code that relies on this however. + * gst/gstpad.c: (gst_pad_activate_pull), (gst_pad_activate_push), + (gst_pad_link_check_hierarchy): + Require that parents should be GstElements in the hierarchy check. + +2007-02-20 10:45:13 +0000 Wim Taymans + + gst/gstbin.c: Improve debug info. + Original commit message from CVS: + * gst/gstbin.c: (bin_replace_message), (gst_bin_add_func), + (gst_bin_change_state_func), (bin_query_min_max_init), + (bin_query_latency_fold), (bin_query_latency_done), + (gst_bin_query): + Improve debug info. + Implement latency query. + +2007-02-20 10:16:27 +0000 Wim Taymans + + Do not set the internal pad as a parent anymore so we can avoid hierarchy linking errors when the ghostpad has no par... + Original commit message from CVS: + * docs/design/part-gstghostpad.txt: + * gst/gstghostpad.c: (gst_ghost_pad_class_init), + (gst_ghost_pad_internal_do_activate_push), + (gst_ghost_pad_internal_do_activate_pull), + (gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull), + (gst_ghost_pad_do_link), (gst_ghost_pad_dispose), + (gst_ghost_pad_new_full), (gst_ghost_pad_set_target): + Do not set the internal pad as a parent anymore so we can avoid + hierarchy linking errors when the ghostpad has no parent yet. This also + fixes failed activation because of unlinked internal pads, which in + turn fixes the impossible case where you have to activate a pad before + you can add it to a running element. + Also fix the docs. + * gst/gstpad.c: (pre_activate), (post_activate), + (gst_pad_set_active), (gst_pad_activate_pull), + (gst_pad_activate_push), (gst_pad_check_pull_range): + Add some more debug info. + Mark activation mode in pre_activate so that we don't try to activate in + endless loops. Fixes #385084. + +2007-02-19 18:08:59 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Implement a checkgetrange function instead of relying on the default core behaviour... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_check_get_range): + Implement a checkgetrange function instead of relying on the default + core behaviour that assumes we can operate in pull mode if we have a + getrange function. First step at fixing #385084. + +2007-02-15 12:05:09 +0000 Stefan Kost + + More docs coverage and some ChangeLog surgery (add missing names) + Original commit message from CVS: + * gst/gstchildproxy.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + More docs coverage and some ChangeLog surgery (add missing names) + +2007-02-15 11:32:02 +0000 Wim Taymans + + docs/design/: Some doc updates. Start renaming from stream_time to running_time where it was used wrongly. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-activation.txt: + * docs/design/part-block.txt: + * docs/design/part-buffering.txt: + * docs/design/part-clocks.txt: + * docs/design/part-element-source.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-live-source.txt: + * docs/design/part-messages.txt: + * docs/design/part-overview.txt: + * docs/design/part-qos.txt: + * docs/design/part-query.txt: + * docs/design/part-states.txt: + * docs/design/part-trickmodes.txt: + Some doc updates. Start renaming from stream_time to running_time where + it was used wrongly. + +2007-02-15 09:07:25 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Answer LATENCY query. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_query): + Answer LATENCY query. + +2007-02-15 08:40:38 +0000 Wim Taymans + + tests/check/gst/gstevent.c: Improve debugging. + Original commit message from CVS: + * tests/check/gst/gstevent.c: (event_probe), (test_event), + (GST_START_TEST): + Improve debugging. + +2007-02-15 08:37:19 +0000 Wim Taymans + + gst/gstpad.c: Improve debugging of default pad dispatcher and query functions. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_internal_links_default), + (gst_pad_dispatcher): + Improve debugging of default pad dispatcher and query functions. + +2007-02-15 08:31:25 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Remove old unused method. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Remove old unused method. + +2007-02-13 15:51:00 +0000 Wim Taymans + + tests/check/gst/gstsegment.c: Fix check + Original commit message from CVS: + * tests/check/gst/gstsegment.c: (GST_START_TEST): + Fix check + +2007-02-13 15:34:15 +0000 Wim Taymans + + docs/design/part-seeking.txt: Some small update. + Original commit message from CVS: + * docs/design/part-seeking.txt: + Some small update. + * gst/gstsegment.c: (gst_segment_set_seek): + Revert old bogus change that should make seeking work again. + +2007-02-13 14:52:47 +0000 Stefan Kost + + docs/random/ensonic/: Possible dynamic reconnection api, plus some type fixes the other two docs. + Original commit message from CVS: + * docs/random/ensonic/dynlink.txt: + * docs/random/ensonic/interfaces.txt: + * docs/random/ensonic/receipies.txt: + Possible dynamic reconnection api, plus some type fixes the other two + docs. + +2007-02-13 13:40:05 +0000 Sebastian Dröge + + plugins/elements/: Also check for an absolute path following file:// in the filesrc element. Remove redundant check a... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_uri_set_uri): + * plugins/elements/gstfilesrc.c: (gst_file_src_uri_set_uri): + Also check for an absolute path following file:// in the filesrc + element. Remove redundant check and call g_path_is_absolute() on the + unescaped location. + +2007-02-13 09:10:53 +0000 Stefan Kost + + docs/design/draft-klass.txt: Add existing category analysis. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Add existing category analysis. + * gst/gstcaps.c: + Fix doc example, framerate is a fraction. + +2007-02-12 19:55:24 +0000 Stefan Kost + + Add crossreferences to glib/gobject docs. + Original commit message from CVS: + * configure.ac: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Add crossreferences to glib/gobject docs. + +2007-02-12 11:32:22 +0000 Wim Taymans + + docs/design/draft-latency.txt: Small update. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Small update. + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_get_latency), (gst_base_sink_query_latency), + (gst_base_sink_wait_clock), (gst_base_sink_send_qos), + (gst_base_sink_perform_qos), (gst_base_sink_queue_object_unlocked), + (gst_base_sink_chain_unlocked), (gst_base_sink_send_event), + (gst_base_sink_get_position), (gst_base_sink_query), + (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + API: gst_base_sink_query_latency() to let subclasses query the upstream + latency. + API: gst_base_sink_get_latency() to let subclasses query the configured + latency in the sink. + Implement query and set latency. + Update some docs. + As spotted by Will Newton : Make sure we + don't continue preroll when we are flushing. Fixes #405284. + * tests/check/pipelines/stress.c: (change_state_timeout), + (quit_timeout), (GST_START_TEST), (stress_suite): + Test for #405284. + +2007-02-12 10:50:20 +0000 René Stadler + + API: add GST_TAG_REFERENCE_LEVEL (#403597). + Original commit message from CVS: + Patch by: René Stadler + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + API: add GST_TAG_REFERENCE_LEVEL (#403597). + +2007-02-11 19:59:12 +0000 Stefan Kost + + docs/libs/Makefile.am: Fix path to core docs. + Original commit message from CVS: + * docs/libs/Makefile.am: + Fix path to core docs. + * gst/gstbin.c: (gst_bin_get_by_interface), + (gst_bin_iterate_all_by_interface): + Refix docs by also renaming 'interface' to 'iface' in implementation. + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: + * gst/gstchildproxy.c: (gst_child_proxy_base_init): + * gst/gstchildproxy.h: + * gst/gstelementfactory.c: + * gst/gstpadtemplate.h: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_new): + Document more. + +2007-02-10 18:31:12 +0000 Sébastien Moutte + + gst/gstbin.h: Replace interface parameter name by iface as interface is a reserved keyword in Visual Studio for C++ p... + Original commit message from CVS: + * gst/gstbin.h:(gst_bin_get_by_interface), + (gst_bin_iterate_all_by_interface): + Replace interface parameter name by iface as interface is + a reserved keyword in Visual Studio for C++ projects so it removes + a build error for application developpers using VS. + * plugins/elements/gstfilesrc.c:(gst_file_src_uri_set_uri): + Fix a bug on Windows in uri format check. Now the prefix checked + is file:// and next we check if the path after file:// is absolute. + * win32/common/libgstbase.def: + * win32/common/libgstdataprotocol.def: + * win32/common/libgstgstreamer.def: + Add new exported functions. + +2007-02-09 15:25:45 +0000 Andy Wingo + + * ChangeLog: + * tests/check/pipelines/simple-launch-lines.c: + tests/check/pipelines/simple-launch-lines.c + Original commit message from CVS: + 2007-02-09 Andy Wingo + * tests/check/pipelines/simple-launch-lines.c + (simple_launch_lines_suite, test_tee): Disable tee test until I + have time to fix it :-( + +2007-02-09 13:59:32 +0000 Andy Wingo + + tests/check/: Add ABI checks for PPC32. + Original commit message from CVS: + 2007-02-09 Andy Wingo + * tests/check/Makefile.am (noinst_HEADERS): + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_ppc32.h: Add ABI checks for PPC32. + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_ppc32.h: Add ABI checks for PPC32. + +2007-02-09 13:45:27 +0000 Andy Wingo + + tests/check/pipelines/simple-launch-lines.c (test_tee): Add tests for push and pull tee behavior. + Original commit message from CVS: + 2007-02-09 Andy Wingo + * tests/check/pipelines/simple-launch-lines.c (test_tee): Add + tests for push and pull tee behavior. + * plugins/elements/gsttee.h: + * plugins/elements/gsttee.c: Describe has-sink-loop better, and + mark as deprecated as well as unimplemented. It was a crack idea. + Add support for tee operating in pull mode, off by default. + +2007-02-09 13:41:24 +0000 Andy Wingo + + gst/gstregistryxml.c (load_feature, load_plugin): Drop some normal-case logs down to LOG, raise errors to WARNING. + Original commit message from CVS: + 2007-02-09 Andy Wingo + * gst/gstregistryxml.c (load_feature, load_plugin): Drop some + normal-case logs down to LOG, raise errors to WARNING. + (gst_registry_xml_read_cache): Don't log before calling a function + that logs. + * gst/gstregistry.c (gst_registry_finalize): Less debug on program + exit (registry finalize). + (gst_registry_add_plugin, gst_registry_add_feature): No need for a + DEBUG log when we emit signals that people don't even have the + chance to connect to. + (gst_registry_scan_path_level): Less logging in the normal case. + +2007-02-05 13:15:44 +0000 Michal Benes + + plugins/elements/gstfilesrc.c: Correctly generate EOS for non-seekable files. We don't have a total length for them a... + Original commit message from CVS: + Patch by: Michal Benes + * plugins/elements/gstfilesrc.c: (gst_file_src_create_read): + Correctly generate EOS for non-seekable files. We don't have a total + length for them and would get an unexpected end of file if we only + special-cased for regular files. (Fixes: #404569) + +2007-02-05 08:15:26 +0000 Sebastian Dröge + + tests/check/elements/filesrc.c: Add unit test for the GstURIHandler interface in filesrc. This also tests the newly a... + Original commit message from CVS: + * tests/check/elements/filesrc.c: (GST_START_TEST), + (filesrc_suite): + Add unit test for the GstURIHandler interface in filesrc. This also + tests the newly added file://localhost/foo/bar support. + +2007-02-04 16:14:19 +0000 Tim-Philipp Müller + + gst/gstelementfactory.h: The klass string is not a hierarchy. Add reference to the design doc for more information an... + Original commit message from CVS: + * gst/gstelementfactory.h: + The klass string is not a hierarchy. Add reference to the design doc + for more information and common types. + +2007-02-02 18:08:32 +0000 Wim Taymans + + gst/gstquery.c: Remove old structure field. + Original commit message from CVS: + * gst/gstquery.c: (gst_query_new_latency): + Remove old structure field. + +2007-02-02 12:27:16 +0000 Stefan Kost + + tools/gst-launch.1.in: Give example for network streaming (#351998) + Original commit message from CVS: + * tools/gst-launch.1.in: + Give example for network streaming (#351998) + +2007-02-02 11:48:48 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Add docs for new methods. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add docs for new methods. + * gst/gstevent.c: (gst_event_new_latency), + (gst_event_parse_latency): + * gst/gstevent.h: + Add new LATENCY event to configure latency in a pipeline. + API: gst_event_new_latency + API: gst_event_parse_latency + * gst/gstmessage.c: (gst_message_new_buffering), + (gst_message_new_lost_preroll), (gst_message_new_prerolled), + (gst_message_new_latency), (gst_message_parse_buffering), + (gst_message_parse_lost_preroll): + * gst/gstmessage.h: + Added messages used in draft-latency. + API: gst_message_new_lost_preroll + API: gst_message_parse_lost_preroll + API: gst_message_new_prerolled + API: gst_message_new_latency + * gst/gstquery.c: (gst_query_new_latency), (gst_query_set_latency), + (gst_query_parse_latency): + * gst/gstquery.h: + Implemented new latency query as in design doc. + API: gst_query_new_latency + API: gst_query_set_latency + API: gst_query_parse_latency + +2007-02-02 11:33:19 +0000 Wim Taymans + + docs/design/draft-latency.txt: Slight redesign to allow for dynamic latency adjustments. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Slight redesign to allow for dynamic latency adjustments. + * docs/design/part-negotiation.txt: + Fix some typos. + +2007-02-02 10:41:29 +0000 Sebastian Dröge + + plugins/elements/: Allow file://localhost/foo/bar URLs and correctly fail for every other hostname that one sets. Thi... + Original commit message from CVS: + reviewed by: Wim Taymans + * plugins/elements/gstfilesink.c: (gst_file_sink_uri_set_uri): + * plugins/elements/gstfilesrc.c: (gst_file_src_uri_set_uri): + Allow file://localhost/foo/bar URLs and correctly fail for every other + hostname that one sets. This was gnomevfssrc is linked for those if + installed as it can handle it (#403172) + +2007-02-01 19:00:48 +0000 Sebastian Dröge + + libs/gst/base/gstcollectpads.*: Don't put the previously added destroy notify in the GstCollectData struct as all it'... + Original commit message from CVS: + reviewed by: Tim-Philipp Müller + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize), + (unref_data), (gst_collect_pads_add_pad_full): + * libs/gst/base/gstcollectpads.h: + Don't put the previously added destroy notify in the GstCollectData + struct as all it's padding is already used and we don't want to break + ABI. Instead put in the pad's GObject data for now. This should be + cleaned up for 0.11 (#402393). + +2007-02-01 17:52:11 +0000 Sebastian Dröge + + API: Add function to specify a destroy notification for custom + Original commit message from CVS: + reviewed by: Wim Taymans + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize), + (unref_data), (gst_collect_pads_add_pad), + (gst_collect_pads_add_pad_full): + * libs/gst/base/gstcollectpads.h: + API: Add function to specify a destroy notification for custom + GstCollectData when adding new pads in GstCollectPads (#402393). + +2007-02-01 17:10:25 +0000 Tim-Philipp Müller + + po/sv.po: Update Swedish translation (#378255). + Original commit message from CVS: + * po/sv.po: + Update Swedish translation (#378255). + +2007-01-31 11:42:53 +0000 Stefan Kost + + docs/design/draft-klass.txt: Fix the previous change, this is a list of categories and not a hierarchy. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Fix the previous change, this is a list of categories and not a hierarchy. + +2007-01-31 11:02:29 +0000 Stefan Kost + + docs/design/draft-klass.txt: Add info about how to get a list of used classes. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Add info about how to get a list of used classes. + +2007-01-30 19:12:54 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Don't leak found caps in chain function (no idea why that never showed up as a... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain_do_typefinding), + (gst_type_find_element_change_state): + Don't leak found caps in chain function (no idea why that never + showed up as a leak anywhere). + +2007-01-30 15:04:33 +0000 Stefan Kost + + gst/gstplugin.h: Fix and expand GstPluginDesc API docs. + Original commit message from CVS: + * gst/gstplugin.h: + Fix and expand GstPluginDesc API docs. + +2007-01-29 15:54:09 +0000 Stefan Kost + + configure.ac: comment about refining the xml deps + Original commit message from CVS: + * configure.ac: + comment about refining the xml deps + * docs/manuals.mak: + comments about moving away from jade for docs + * gst/gst.c: + recommit the ifdefs to use the binary registry + * gst/gstbin.c: (gst_bin_change_state_func): + this break is obsolete + * gst/gstelementfactory.h: + better GST_ELEMENT_DETAILS docs, add comment about translation + * gst/gstinfo.h: + remove eol slash + * gst/gstobject.c: (gst_signal_object_get_type): + add G_UNLIKELY as usual + * gst/gstpad.c: (gst_pad_event_default): + add fall trhu comment + * gst/gstregistrybinary.c: (gst_registry_binary_write), + (gst_registry_binary_initialize_magic), + (gst_registry_binary_save_string), + (gst_registry_binary_save_pad_template), + (gst_registry_binary_save_feature), + (gst_registry_binary_save_plugin), + (gst_registry_binary_write_cache), + (gst_registry_binary_check_magic), + (gst_registry_binary_load_pad_template), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + comment typo and formatting + * gst/gstutils.c: (gst_element_state_get_name), + (gst_element_state_change_return_get_name): + remove obsolete breaks + * gst/gstvalue.c: (gst_date_get_type), (_gst_value_initialize): + add FIXME 0.11 and remove cpp comment + +2007-01-29 15:02:11 +0000 Edward Hervey + + gst/gstregistrybinary.c: Fix print statement in an even more portable way. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): + Fix print statement in an even more portable way. + +2007-01-29 13:40:38 +0000 Tim-Philipp Müller + + API: add GST_ROUND_DOWN_* macros (#401781). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.h: + API: add GST_ROUND_DOWN_* macros (#401781). + +2007-01-27 18:44:11 +0000 Tim-Philipp Müller + + Document registry signals and make gtk-doc pick them up (#401381). + Original commit message from CVS: + * docs/gst/gstreamer.types.in: + * gst/gstregistry.c: (gst_registry_class_init): + Document registry signals and make gtk-doc pick them up (#401381). + +2007-01-26 18:24:56 +0000 Tim-Philipp Müller + + docs/pwg/building-testapp.xml: Add some audioconverts and audioresample to the pipeline, and some more comments and e... + Original commit message from CVS: + * docs/pwg/building-testapp.xml: + Add some audioconverts and audioresample to the pipeline, and some + more comments and error handling. + +2007-01-26 13:07:36 +0000 Tim-Philipp Müller + + docs/: Fix typo (#400987). + Original commit message from CVS: + * docs/manual/manual.xml: + * docs/pwg/pwg.xml: + Fix typo (#400987). + +2007-01-26 09:37:03 +0000 Wim Taymans + + gst/gstcaps.c: Init caps flags too. + Original commit message from CVS: + * gst/gstcaps.c: (gst_static_caps_get): + Init caps flags too. + +2007-01-25 17:54:07 +0000 Jindrich Makovicka + + plugins/elements/gstfilesrc.c: If not using mmap'ed files try to seek to the end instead of the start to determine wh... + Original commit message from CVS: + Patch by: Jindrich Makovicka + * plugins/elements/gstfilesrc.c: (gst_file_src_start): + If not using mmap'ed files try to seek to the end instead of the + start to determine whether we can seek at all. This fixes the case + of 2GB+ files over NFS, where seeks in the first 2GB can succeed but + seeks for everything afterwards fail. Fixes #400656 + +2007-01-25 17:41:39 +0000 Wim Taymans + + gst/gstcaps.c: Add some refcount debugging. + Original commit message from CVS: + * gst/gstcaps.c: (_gst_caps_free), (gst_static_caps_get): + Add some refcount debugging. + Make gst_static_caps_get threadsafe, which is needed when autoplugging + in multiple streaming threads. + +2007-01-25 10:50:03 +0000 David Schleef + + API: gst_adapter_copy() that can reduce the amount of memcpy when getting data from the adapter. Fixes #388201. + Original commit message from CVS: + Patch by: David Schleef + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: (gst_adapter_copy): + * libs/gst/base/gstadapter.h: + API: gst_adapter_copy() that can reduce the amount of memcpy when + getting data from the adapter. Fixes #388201. + +2007-01-25 10:14:09 +0000 Edward Hervey + + gst/gstregistrybinary.c: In print statements, "%x" is for guint. Fixes build on macosx. + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): + In print statements, "%x" is for guint. Fixes build on macosx. + +2007-01-24 11:32:00 +0000 Edward Hervey + + plugins/elements/gstmultiqueue.c: Small fix. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + (gst_multi_queue_loop): + Small fix. + (single_queue_overrun_cb), (single_queue_underrun_cb), + (single_queue_check_full), (gst_single_queue_new): + Implement single queue growth system. + This uses the extra-size properties, and will grow single queues by + that much if one goes full whereas there are others empty. This is + called extra-mode in the code. + When a single queue's levels go back below the initial max-size + limits, it is no longer in extra-mode. This is to ensure we don't + consume too much memory. + Fixes #399875 + +2007-01-23 13:50:42 +0000 Tim-Philipp Müller + + gst/gst.c: Make warning about late g_thread_init() calls a bit more explicit, so that it's more obvious to applicatio... + Original commit message from CVS: + * gst/gst.c: (gst_init_get_option_group): + Make warning about late g_thread_init() calls a bit more explicit, + so that it's more obvious to application developers what they need + to do if a user files a bug against their application. + +2007-01-22 16:00:39 +0000 Edward Hervey + + plugins/elements/gstmultiqueue.c: Remove previous hack of unsetting the flushing flag for the source pad instead of a... + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: + (gst_multi_queue_src_activate_push), (gst_single_queue_new): + Remove previous hack of unsetting the flushing flag for the source pad + instead of activating it. Instead, fix the source pad activate function + so that it no longer depends on having a parent set or not. + +2007-01-22 14:30:27 +0000 Carlos Sanmartin Dominguez + + docs/manual/basics-bus.xml: Fix example code, gst_element_unref() doesn't exist any longer. + Original commit message from CVS: + Patch by: Carlos Sanmartin Dominguez + * docs/manual/basics-bus.xml: + Fix example code, gst_element_unref() doesn't exist any longer. + +2007-01-21 20:24:11 +0000 Mark Nauwelaerts + + gst/gstpad.c: Fix two docs typoes (#399094). + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * gst/gstpad.c: + Fix two docs typoes (#399094). + +2007-01-19 09:15:21 +0000 Edward Hervey + + docs/faq/gst-uninstalled: Add gst-plugins-base/gst/utils/ to LD_LIBRARY_PATH so that plugins depending on libgstbaseu... + Original commit message from CVS: + * docs/faq/gst-uninstalled: + Add gst-plugins-base/gst/utils/ to LD_LIBRARY_PATH so that plugins + depending on libgstbaseutils can work in uninstalled environment. + +2007-01-18 12:00:23 +0000 Stefan Kost + + gst/: Add more docs regarding tag merge-modes and when to send tags. Fix 'since' statement for new tag. + Original commit message from CVS: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + Add more docs regarding tag merge-modes and when to send tags. Fix 'since' + statement for new tag. + +2007-01-17 14:33:39 +0000 Edward Hervey + + plugins/elements/gstmultiqueue.c: When dynamically creating single queues, activate sinkpad before adding it. + Original commit message from CVS: + * plugins/elements/gstmultiqueue.c: (gst_single_queue_new): + When dynamically creating single queues, activate sinkpad before adding + it. + We should be doing the same thing for the source pad, but we can't + since it would call a method which needs the parent to be set in order + to work propertly. Instead of activating the source pad, we just unset + the flushing flag, which is the minimal requirement for adding a pad + to an element in a state greater than READY. + +2007-01-17 14:26:46 +0000 Edward Hervey + + docs/faq/gst-uninstalled: Add DYLD_LIBRARY_PATH declarations so we can also use this script on + Original commit message from CVS: + * docs/faq/gst-uninstalled: + Add DYLD_LIBRARY_PATH declarations so we can also use this script on + Mac OS X. + +2007-01-17 12:31:01 +0000 Tim-Philipp Müller + + tests/check/: Add ABI structs for HPPA (see #393796). + Original commit message from CVS: + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_hppa.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_hppa.h: + Add ABI structs for HPPA (see #393796). + +2007-01-16 09:57:50 +0000 Tim-Philipp Müller + + libs/gst/check/gstcheck.c: Actually write ABI structs to the file specified in the GST_ABI environment variable, as t... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_abi_list): + Actually write ABI structs to the file specified in the GST_ABI + environment variable, as the message we print claims we would. + +2007-01-15 14:51:09 +0000 Stefan Kost + + tests/check/gst/gsttask.c: Fix header comment. + Original commit message from CVS: + * tests/check/gst/gsttask.c: + Fix header comment. + +2007-01-15 14:39:51 +0000 Stefan Kost + + gst/gsttaglist.c: Change tag type from STRING to DOUBLE. Apply ChangeLog surgery for my previous two entries. + Original commit message from CVS: + * gst/gsttaglist.c: (_gst_tag_initialize): + Change tag type from STRING to DOUBLE. Apply ChangeLog surgery for my + previous two entries. + +2007-01-15 13:57:12 +0000 Stefan Kost + + add tag support for beat-per-minute + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + add tag support for beat-per-minute + +2007-01-15 12:18:46 +0000 Stefan Kost + + gst/gstregistrybinary.*: use glib types, cleanup comments, impement interfaces and uri-types + Original commit message from CVS: + * gst/gstregistrybinary.c: (gst_registry_binary_write), + (gst_registry_binary_initialize_magic), + (gst_registry_binary_save_string), (gst_registry_binary_make_data), + (gst_registry_binary_save_pad_template), + (gst_registry_binary_save_feature), + (gst_registry_binary_save_plugin), + (gst_registry_binary_write_cache), + (gst_registry_binary_check_magic), + (gst_registry_binary_load_pad_template), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + use glib types, cleanup comments, impement interfaces and uri-types + +2007-01-13 10:33:41 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_get_range, gst_pad_pull_range): Allow getrange() to return buffers with other caps, while we fi... + Original commit message from CVS: + 2007-01-13 Andy Wingo + * gst/gstpad.c (gst_pad_get_range, gst_pad_pull_range): Allow + getrange() to return buffers with other caps, while we fix + demuxers and typefind, or otherwise change part-negotiation.txt. + +2007-01-12 21:13:32 +0000 Andy Wingo + + libs/gst/base/gstbasetransform.c (gst_base_transform_activate): Factor start/stop into this private function instead ... + Original commit message from CVS: + 2007-01-12 Andy Wingo + * libs/gst/base/gstbasetransform.c (gst_base_transform_activate): + Factor start/stop into this private function instead of partially + in activate functions and partially in the change_state function. + Fixes setup before the element has changed from READY->PAUSED, as + is the case in pull-mode pipelines. + (gst_base_transform_sink_activate_push) + (gst_base_transform_src_activate_pull): Refactor to use + gst_base_transform_activate(). + (gst_base_transform_change_state): Removed, not needed any more. + * libs/gst/base/gstbasesink.c (gst_base_sink_negotiate_pull): + Truncate before fixating. + +2007-01-12 18:06:29 +0000 Andy Wingo + + libs/gst/base/gstbasesink.c (gst_base_sink_negotiate_pull): Don't set_caps() if the result of fixating is ANY, as it'... + Original commit message from CVS: + 2007-01-12 Andy Wingo + * libs/gst/base/gstbasesink.c (gst_base_sink_negotiate_pull): + Don't set_caps() if the result of fixating is ANY, as it's not + supported, and not necessary in the case of a link with no + template caps on either side. Fixes tests/check/libs/basesrc in + some pull-mode tests. + +2007-01-12 15:56:00 +0000 Andy Wingo + + libs/gst/base/gstbasetransform.c (_GstBaseTransformPrivate): (gst_base_transform_init, gst_base_transform_sink_activa... + Original commit message from CVS: + 2007-01-12 Andy Wingo + * libs/gst/base/gstbasetransform.c (_GstBaseTransformPrivate): + (gst_base_transform_init, gst_base_transform_sink_activate_push) + (gst_base_transform_src_activate_pull): + Track the activation mode. + (gst_base_transform_setcaps): In pull mode, when activating the + src pad, after activating the sink pad, activate the sink pad's + peer, as discussed in part-negotiation.txt. + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasesrc.c (gst_base_src_fixate): Add fixate + vmethod, as in basesink. + * libs/gst/base/gstbasesink.h: Reformat docs, add fixate vmethod. + * libs/gst/base/gstbasesink.c (gst_base_sink_pad_setcaps): In pull + mode, first proxy the setcaps to the peer pad. + (gst_base_sink_pad_fixate): Add a fixate function that calls the + new fixate vmethod. + (gst_base_sink_default_activate_pull): Rename from + gst_base_sink_activate_pull. + (gst_base_sink_negotiate_pull): New function, performs negotiation + in pull mode before calling ::activate_pull(). + (gst_base_sink_pad_activate_pull): Actually call the activate_pull + vmethod instead of the default implementation. I have no idea how + this worked before. Negotiate before calling activate_pull. + +2007-01-12 15:48:00 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_activate_pull): Refuse to activate unlinked sink pads in pull mode. In addition to being correc... + Original commit message from CVS: + 2007-01-12 Andy Wingo + * gst/gstpad.c (gst_pad_activate_pull): Refuse to activate unlinked + sink pads in pull mode. In addition to being correct, fixes + filesrc ! decodebin ! identity ! fakesink. + (gst_pad_get_range, gst_pad_pull_range): Don't call + gst_pad_set_caps() if the caps changes; instead error out with + GST_FLOW_NOT_NEGOTIATED, as discussed in part-negotiation.txt. + +2007-01-12 15:39:57 +0000 Andy Wingo + + docs/design/part-negotiation.txt: Update with more policy. + Original commit message from CVS: + 2007-01-12 Andy Wingo + * docs/design/part-negotiation.txt: Update with more policy. + +2007-01-12 12:48:25 +0000 Tim-Philipp Müller + + libs/gst/check/: Add G_BEGIN_DECLS and G_END_DECLS. Move GST_CHECK_MAIN where it belongs. + Original commit message from CVS: + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstcheck.h: + Add G_BEGIN_DECLS and G_END_DECLS. Move GST_CHECK_MAIN where it + belongs. + +2007-01-12 10:53:54 +0000 Tim-Philipp Müller + + tests/check/: Add minimal unit test for beforementioned GstTagSetter bug. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gsttagsetter.c: (gst_dummy_enc_add_interfaces), + (gst_dummy_enc_base_init), (gst_dummy_enc_class_init), + (gst_dummy_enc_init), (tag_list_foreach), (tag_setter_list_length), + (GST_START_TEST), (gst_tag_setter_suite): + Add minimal unit test for beforementioned GstTagSetter bug. + +2007-01-12 10:48:49 +0000 René Stadler + + gst/gsttagsetter.c: gst_tag_list_merge() returns a new list, so it's not the best idea to ingore its return value. Ef... + Original commit message from CVS: + Patch by: René Stadler + * gst/gsttagsetter.c: (gst_tag_setter_merge_tags): + gst_tag_list_merge() returns a new list, so it's not the best idea + to ingore its return value. Effectively meant that tags could only + be merged on a GstTagSetter once using _merge_tags(). Fixes #395554. + Also add function guard to require a non-NULL taglist as input (has + always been so due to gst_tag_list_copy(), just making it explicit). + +2007-01-11 15:03:07 +0000 Tim-Philipp Müller + + docs/random/draft-missing-plugins.txt: Some additions: mention new API that is supposed to be used at the various sta... + Original commit message from CVS: + * docs/random/draft-missing-plugins.txt: + Some additions: mention new API that is supposed to be used at the + various stages; short blob about new gst-inspect introspection + option; mention potential future problem with plugins that have + a dynamic list of elements (such as ladspa, pitfdll, libvisual). + +2007-01-11 14:16:23 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Add --print-plugin-auto-install-info option to gst-inspect, so we can introspect plugin files an... + Original commit message from CVS: + * tools/gst-inspect.c: + (print_plugin_automatic_install_info_codecs), + (print_plugin_automatic_install_info_protocols), + (print_plugin_automatic_install_info), (main): + Add --print-plugin-auto-install-info option to gst-inspect, so we can + introspect plugin files and get machine-parsable output that corresponds + to the last bit of the missing-plugin installer string (small gotcha: + doesn't take into account ranks). + +2007-01-11 13:45:51 +0000 Stefan Kost + + commit binary registry (disabled by default, see #359653) + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstregistry.c: (gst_registry_lookup_feature_locked), + (gst_registry_lookup_locked): + * gst/gstregistry.h: + * gst/gstregistrybinary.c: (gst_registry_binary_write), + (gst_registry_binary_initialize_magic), + (gst_registry_binary_save_string), + (gst_registry_binary_save_pad_template), + (gst_registry_binary_save_feature), + (gst_registry_binary_save_plugin), + (gst_registry_binary_write_cache), + (gst_registry_binary_check_magic), + (gst_registry_binary_load_pad_template), + (gst_registry_binary_load_feature), + (gst_registry_binary_load_plugin), + (gst_registry_binary_read_cache): + * gst/gstregistrybinary.h: + * gst/gstregistryxml.c: (load_feature), + (gst_registry_xml_read_cache): + commit binary registry (disabled by default, see #359653) + +2007-01-11 10:48:59 +0000 Tim-Philipp Müller + + tests/check/gst/gstpad.c: Fix 'make check' too. + Original commit message from CVS: + * tests/check/gst/gstpad.c: (test_get_allowed_caps): + Fix 'make check' too. + +2007-01-10 21:24:08 +0000 Andy Wingo + + docs/design/part-negotiation.txt: Fix a typo, add a couple notes. + Original commit message from CVS: + 2007-01-10 Andy Wingo + * docs/design/part-negotiation.txt: Fix a typo, add a couple + notes. + +2007-01-10 21:15:08 +0000 Andy Wingo + + docs/design/part-negotiation.txt: Update with, um, one way that pull-mode negotiation might work? + Original commit message from CVS: + 2007-01-10 Andy Wingo + * docs/design/part-negotiation.txt: Update with, um, one way that + pull-mode negotiation might work? + * gst/gstpad.h: + * gst/gstpad.c (gst_pad_get_allowed_caps): Remove the restriction + that the pad must be a src pad; makes sense to call it the other + way in pull mode, and the logic is symmetric anyway. + +2007-01-10 19:25:09 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesink.c: Include for fseeko(). + Original commit message from CVS: + * plugins/elements/gstfilesink.c: + Include for fseeko(). + +2007-01-10 10:21:47 +0000 Wim Taymans + + gst/gstevent.*: Reserve LATENCY event. + Original commit message from CVS: + * gst/gstevent.c: + * gst/gstevent.h: + Reserve LATENCY event. + +2007-01-09 18:09:54 +0000 Wim Taymans + + docs/design/draft-latency.txt: Updates. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Updates. + +2007-01-09 15:38:58 +0000 Wim Taymans + + docs/design/draft-latency.txt: Updates. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Updates. + * gst/gstelement.h: + * gst/gststructure.c: + * gst/gsttrace.c: + Small typo fixes. + +2007-01-09 14:38:11 +0000 Tim-Philipp Müller + + tests/check/.cvsignore: Ignore test-registry.xml as well. + Original commit message from CVS: + * tests/check/.cvsignore: + Ignore test-registry.xml as well. + +2007-01-09 12:34:45 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: unref data at the end when we are done with the pad. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_remove_pad): + unref data at the end when we are done with the pad. + +2007-01-08 20:30:12 +0000 Tim-Philipp Müller + + API: add gst_update_registry() (#391296). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: (load_plugin_func), (scan_and_update_registry), + (init_post), (gst_deinit), (gst_update_registry): + * gst/gst.h: + API: add gst_update_registry() (#391296). + * tests/check/Makefile.am: + * tests/check/gst/gstregistry.c: + * tests/check/gst/.cvsignore: + Simple unit test for the above. + +2007-01-08 16:23:03 +0000 Tim-Philipp Müller + + gst/gstregistry.c: Plugin extension on HP-UX is .sl, add that to the list of approved plugin extensions (see #393796). + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_scan_path_level): + Plugin extension on HP-UX is .sl, add that to the list of approved + plugin extensions (see #393796). + * tests/check/gst/gstpad.c: (GST_START_TEST): + ulong => gulong. Fixes compilation with HP-UX compiler. + * tests/check/pipelines/parse-launch.c: (GST_START_TEST): + Fix compilation if valgrind headers are not available. + +2007-01-07 10:21:33 +0000 Sébastien Moutte + + win32/common/libgstreamer.def: Add new exported function. + Original commit message from CVS: + * win32/common/libgstreamer.def: + Add new exported function. + * win32/vs6/libgstbase.dsp: + Add gstdataqueue.c to the build. + * win32/vs6/libgstcoreelements.dsp: + Add gstmultiqueue.c to the build. + +2007-01-06 17:18:03 +0000 Andy Wingo + + libs/gst/base/gstbasesink.h: New GstBaseSinkClass vmethod, activate_pull(), providing for a way to specialize the pro... + Original commit message from CVS: + 2007-01-06 Andy Wingo + * libs/gst/base/gstbasesink.h: New GstBaseSinkClass vmethod, + activate_pull(), providing for a way to specialize the process of + spawning a thread to pull on the sink pad. There is a default + implementation. + * libs/gst/base/gstbasesink.c (gst_base_sink_pad_activate_pull) + (gst_base_sink_pad_activate_push, gst_base_sink_pad_activate) + (gst_base_sink_init): Renamed pad activation functions (inserting + "_pad" in their names). Refactor to use the new activate_pull + vmethod, as appropriate. + (gst_base_sink_class_init, gst_base_sink_activate_pull): Set the + default activate_pull function to start a task pulling from the + sink pad, as before. + +2007-01-06 17:09:10 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_get_range, gst_pad_pull_range): Set caps on the pads if necessary, as in push()/chain(). Update... + Original commit message from CVS: + 2007-01-06 Andy Wingo + * gst/gstpad.c (gst_pad_get_range, gst_pad_pull_range): Set caps + on the pads if necessary, as in push()/chain(). Update docs. + Shouldn't affect existing pull() usage as it is currently only + being used on buffers without caps. + +2007-01-05 16:36:36 +0000 Tim-Philipp Müller + + gst/gst.c: Call g_thread_init() first thing in gst_init() / gst_check_init(). + Original commit message from CVS: + * gst/gst.c: (gst_init_get_option_group), (gst_init_check), + (init_pre): + Call g_thread_init() first thing in gst_init() / gst_check_init(). + When initialisation is done via gst_init_get_option_group() and + GOption parsing, issue a warning if the GLib thread system has not + been initialised yet by the time gst_init_get_option_group() is + called, as it's quite likely other GLib functions such as + g_option_context_new() have been called already then, and + g_thread_init() must be called before any other GLib function. The + application in question must be fixed in that case, since memory + corruption might happen otherwise. + We issue the warning because even if the GLib folks decide to work + around the problem on their end in future, this is still an issue + with all GLib versions >= 2.10.0, so we should warn until we depend + on a GLib version we know to be safe. + Update documentation as well. + Closes bug #391278. + +2007-01-05 15:55:16 +0000 Tim-Philipp Müller + + tools/: Call g_thread_init() really really early, before any other GLib function (see #342564 and recent discussion o... + Original commit message from CVS: + * tools/gst-inspect.c: (main): + * tools/gst-launch.c: (main): + * tools/gst-typefind.c: (main): + * tools/gst-xmlinspect.c: (main): + Call g_thread_init() really really early, before any other GLib + function (see #342564 and recent discussion on gtk-devel-list). + +2007-01-05 13:23:02 +0000 Vincent Torri + + gst/: On win32, all the __declspec stuff for symbol exporting is apparently only needed with MSVC, but doesn't work w... + Original commit message from CVS: + Patch by: Vincent Torri + * gst/gst_private.h: + * gst/gstconfig.h.in: + * gst/gstinfo.h: + On win32, all the __declspec stuff for symbol exporting is + apparently only needed with MSVC, but doesn't work with MingW. + Fixes compilation with MingW and #391909. + +2007-01-05 11:57:49 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.c: Change some GST_ERROR_OBJECT that aren't really errors to + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_activate_push): + Change some GST_ERROR_OBJECT that aren't really errors to + GST_WARNING_OBJECT in order to reduce terminal spam. + +2007-01-04 13:54:25 +0000 Stefan Kost + + tests/check/Makefile.am: disable test again, as there seem to be still race problems + Original commit message from CVS: + * tests/check/Makefile.am: + disable test again, as there seem to be still race problems + +2007-01-04 13:37:08 +0000 Stefan Kost + + tests/check/: enable queue test again, add tests for the leaky behaviour + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/queue.c: (queue_overrun), (queue_underrun), + (GST_START_TEST), (queue_suite): + enable queue test again, add tests for the leaky behaviour + +2007-01-02 17:01:33 +0000 Tim-Philipp Müller + + Compile adapter test/example only if the required headers are available (fixes #391915). + Original commit message from CVS: + * configure.ac: + * tests/examples/Makefile.am: + Compile adapter test/example only if the required headers are + available (fixes #391915). + +2007-01-02 09:31:45 +0000 Thomas Vander Stichele + + * gst/gstvalue.c: + tell us what's not implemented + Original commit message from CVS: + tell us what's not implemented + +2007-01-02 09:31:11 +0000 Thomas Vander Stichele + + * win32/common/config.h: + bump to CVS + Original commit message from CVS: + bump to CVS + +2007-01-02 06:14:06 +0000 David Schleef + + gst/gstplugin.c: Restore the previous signal handler for SIGSEGV instead of setting to default, since we may have sto... + Original commit message from CVS: + * gst/gstplugin.c: + Restore the previous signal handler for SIGSEGV instead of + setting to default, since we may have stolen it away from + someone. (i.e., Mono) + +2006-12-26 15:55:24 +0000 Tim-Philipp Müller + + docs/random/draft-missing-plugins.txt: Some small additions and clarifications. + Original commit message from CVS: + * docs/random/draft-missing-plugins.txt: + Some small additions and clarifications. + +2006-12-26 15:06:52 +0000 Tim-Philipp Müller + + gst/gstregistryxml.c: Make sure we don't pass non-UTF-8 strings to g_markup_escape(), since that can lead to random m... + Original commit message from CVS: + * gst/gstregistryxml.c: (gst_registry_save_escaped): + Make sure we don't pass non-UTF-8 strings to g_markup_escape(), + since that can lead to random memory corruptions and crashes + (may or may not be related to #383244, #386711, and #386711). + +2006-12-21 15:54:06 +0000 Stefan Kost + + tests/check/: sync .cvsignome and CLEANFILES + Original commit message from CVS: + * tests/check/.cvsignore: + * tests/check/Makefile.am: + sync .cvsignome and CLEANFILES + +2006-12-21 15:32:00 +0000 Stefan Kost + + tests/check/Makefile.am: fix distcheck + Original commit message from CVS: + * tests/check/Makefile.am: + fix distcheck + +2006-12-21 15:00:08 +0000 Stefan Kost + + docs/design/part-states.txt: two tiny additional comments + Original commit message from CVS: + * docs/design/part-states.txt: + two tiny additional comments + * gst/gststructure.c: + doc fixing + * tests/check/Makefile.am: + * tests/check/elements/queue.c: (queue_overrun), (queue_underrun), + (GST_START_TEST): + disable test for now, unless it gets fixed + +2006-12-21 14:24:54 +0000 Stefan Kost + + tests/check/elements/queue.c: fix race in underrun test + Original commit message from CVS: + * tests/check/elements/queue.c: (queue_overrun), (queue_underrun), + (GST_START_TEST): + fix race in underrun test + +2006-12-21 09:58:25 +0000 Stefan Kost + + tests/check/elements/.cvsignore: ignore more + Original commit message from CVS: + * tests/check/elements/.cvsignore: + ignore more + * tests/check/elements/queue.c: (queue_overrun), (queue_underrun), + (GST_START_TEST): + try to narrow test failure + +2006-12-21 09:37:56 +0000 David Schleef + + plugins/elements/gstfakesrc.c: Use g_random_int_range(), since it produces better random numbers in a range than almo... + Original commit message from CVS: + * plugins/elements/gstfakesrc.c: + Use g_random_int_range(), since it produces better random + numbers in a range than almost-correct floating point code. + +2006-12-21 08:12:28 +0000 Stefan Kost + + libs/gst/check/gstcheck.c: do not automatically (de)activate pads + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_setup_src_pad), + (gst_check_teardown_src_pad), (gst_check_setup_sink_pad), + (gst_check_teardown_sink_pad): + do not automatically (de)activate pads + * tests/check/Makefile.am: + * tests/check/elements/queue.c: (queue_overrun), (queue_underrun), + (setup_queue), (cleanup_queue), (GST_START_TEST), (queue_suite): + add new, yet simple tests for queue + * tests/check/elements/fakesrc.c: (cleanup_fakesrc): + * tests/check/elements/fdsrc.c: (cleanup_fdsrc): + * tests/check/elements/filesrc.c: (cleanup_filesrc), + (GST_START_TEST): + * tests/check/elements/identity.c: (cleanup_identity): + consistent pad (de)activation + +2006-12-20 19:06:02 +0000 Sebastian Dröge + + libs/gst/base/gstcollectpads.c: Fix two doc typos (#387866). + Original commit message from CVS: + Patch by: Sebastian Dröge + * libs/gst/base/gstcollectpads.c: + Fix two doc typos (#387866). + +2006-12-19 15:06:42 +0000 Tim-Philipp Müller + + docs/manual/advanced-dparams.xml: Fix typo (g_object_control_properties() doesn't exist). + Original commit message from CVS: + * docs/manual/advanced-dparams.xml: + Fix typo (g_object_control_properties() doesn't exist). + +2006-12-19 12:38:00 +0000 Edward Hervey + + gst/gstsegment.c: Fine tune the cases where the segment start/stop values are really updated. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_seek): + Fine tune the cases where the segment start/stop values are really + updated. + * tests/check/gst/gstsegment.c: (GST_START_TEST): + Add tests for the return values of gst_segment_set_seek(). + +2006-12-19 11:04:49 +0000 Tim-Philipp Müller + + gst/gst.c: Docs typo fix. + Original commit message from CVS: + * gst/gst.c: + Docs typo fix. + * plugins/elements/gstqueue.c: (gst_queue_class_init), + (gst_queue_init): + Fix incorrect documentation and flesh it out a bit more. + Set default values for the max properties on the GParamSpec as well, + so it shows up correctly in gst-inspect. + +2006-12-18 16:01:32 +0000 Stefan Kost + + plugins/elements/gstqueue.c: Correct docs of queue, add more detail and crosslink it more. + Original commit message from CVS: + * plugins/elements/gstqueue.c: (queue_leaky_get_type): + Correct docs of queue, add more detail and crosslink it more. + +2006-12-16 19:33:26 +0000 Tim-Philipp Müller + + plugins/elements/gstidentity.c: Print additional debug info when the stream isn't perfectly timestamped; don't try to... + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_check_perfect): + Print additional debug info when the stream isn't perfectly + timestamped; don't try to use invalid durations. + +2006-12-16 16:14:01 +0000 Tim-Philipp Müller + + docs/design/Makefile.am: Dist new design docs. + Original commit message from CVS: + * docs/design/Makefile.am: + Dist new design docs. + +2006-12-16 15:17:54 +0000 Sjoerd Simons + + libs/gst/base/gstcollectpads.*: Add refcounting to the collectpads data so we can track when it's safe to free the da... + Original commit message from CVS: + Patch by: Sjoerd Simons + * libs/gst/base/gstcollectpads.c: (ref_data), (unref_data), + (gst_collect_pads_add_pad), (gst_collect_pads_remove_pad), + (gst_collect_pads_stop), (gst_collect_pads_event), + (gst_collect_pads_chain): + * libs/gst/base/gstcollectpads.h: + Add refcounting to the collectpads data so we can track when it's safe + to free the data. Fixes #383382. + +2006-12-15 17:09:59 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: Automatically activate/deactivate pads when they are added to a started/stoped collec... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_add_pad), + (gst_collect_pads_remove_pad): + Automatically activate/deactivate pads when they are added to a + started/stoped collectpads. + +2006-12-15 16:01:58 +0000 Wim Taymans + + gst/: Set pads to FLUSHING when they are created. Check, warn and fix when a demuxer adds an inactive pad to itself w... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_add_pad): + * gst/gstghostpad.c: (gst_ghost_pad_new_full): + * gst/gstpad.c: (gst_pad_init): + Set pads to FLUSHING when they are created. Check, warn and fix when a + demuxer adds an inactive pad to itself when running. Fixes #339326. + +2006-12-15 15:49:29 +0000 Wim Taymans + + gst/gstelement.c: Expose default element send_event and query handling as vmethods that subclasses can chain up to. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_class_init), + (gst_element_default_send_event), (gst_element_send_event), + (gst_element_default_query), (gst_element_query): + Expose default element send_event and query handling as vmethods that + subclasses can chain up to. + +2006-12-15 15:39:28 +0000 Wim Taymans + + gst/gstelement.c: Small documentation fixes. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_set_state_func): + Small documentation fixes. + +2006-12-15 15:26:46 +0000 Wim Taymans + + docs/design/draft-latency.txt: Checked in draft for handling latency in pipelines. + Original commit message from CVS: + * docs/design/draft-latency.txt: + Checked in draft for handling latency in pipelines. + +2006-12-15 00:16:57 +0000 Thomas Vander Stichele + + adding .doap file + Original commit message from CVS: + * Makefile.am: + * gstreamer.doap: + * gstreamer.spec.in: + adding .doap file + +2006-12-14 14:06:38 +0000 Tim-Philipp Müller + + gst/gst.c: init_pre() and init_post() might be called via our GOptionGroup or from gst_init(), and we should skip bot... + Original commit message from CVS: + * gst/gst.c: (init_pre), (init_post): + init_pre() and init_post() might be called via our GOptionGroup or + from gst_init(), and we should skip both of them if we've already + been initialised, otherwise we will init some things twice or add + two default log functions. + +2006-12-13 12:46:28 +0000 Edward Hervey + + docs/manual/basics-bus.xml: No, gst_main_loop does not exist. Its g_main_loop. + Original commit message from CVS: + * docs/manual/basics-bus.xml: + No, gst_main_loop does not exist. Its g_main_loop. + Discovered by somebody who abused the copy-paste technique of coding :) + +2006-12-13 11:05:20 +0000 Tim-Philipp Müller + + gst/gstghostpad.c: Log ghostpad debug stuff to the GST_PADS category as well rather than just to the default category. + Original commit message from CVS: + * gst/gstghostpad.c: + Log ghostpad debug stuff to the GST_PADS category as well rather + than just to the default category. + +2006-12-12 13:53:04 +0000 Tim-Philipp Müller + + Add some basic system details such as OS and architecture to the debug output if possible, courtesy of uname(). + Original commit message from CVS: + * configure.ac: + * gst/gst.c: (init_pre): + Add some basic system details such as OS and architecture + to the debug output if possible, courtesy of uname(). + +2006-12-11 13:40:32 +0000 Tim-Philipp Müller + + docs/gst/running.xml: Document GST_REGISTRY_FORK and GST_DEBUG_NO_COLOR environment variables. + Original commit message from CVS: + * docs/gst/running.xml: + Document GST_REGISTRY_FORK and GST_DEBUG_NO_COLOR + environment variables. + +2006-12-09 20:23:10 +0000 Jan Schmidt + + tests/check/gst/gstbin.c: It is acceptable to have a refcount of 2 or 3 at this point in the test, because the pipeli... + Original commit message from CVS: + * tests/check/gst/gstbin.c: (GST_START_TEST): + It is acceptable to have a refcount of 2 or 3 at this point in the + test, because the pipeline might be just posting its state_change + message. The next line then waits for that message to appear using + bus_poll, so that should be fine too. + +2006-12-09 18:48:57 +0000 Jan Schmidt + + gst/gst.c: Ignore EINTR when reading from the child registry pipe. + Original commit message from CVS: + * gst/gst.c: (ensure_current_registry_forking): + Ignore EINTR when reading from the child registry pipe. + Explicitly ignore the return value from close, since it makes no + difference. + * gst/gstminiobject.c: (gst_mini_object_ref), + (gst_mini_object_unref): + When debugging refcounts, check GST_IS_MINI_OBJECT and warn. + * gst/gstregistry.c: (_priv_gst_registry_remove_cache_plugins): + When removing cached plugins, remove their features too, so they're + not visible after they've disappeared. + * gst/gstutils.c: (prepare_link_maybe_ghosting): + In the unlikely case that we are linking pads with no parents, don't + crash trying to get the non-existent parent bin. + * gst/parse/grammar.y: + Output debug in the PIPELINE category + +2006-12-08 16:12:44 +0000 René Stadler + + gst/gstclock.c: Reject invalid clock times for interval of periodic ids. + Original commit message from CVS: + Patch by: René Stadler + * gst/gstclock.c: (gst_clock_new_periodic_id): + Reject invalid clock times for interval of periodic ids. + Fixes ##383506. + +2006-12-07 12:11:14 +0000 Jan Schmidt + + Fix refcounting of gst_plugin_feature_load to match the docs. + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_create): + * gst/gstpluginfeature.c: (gst_plugin_feature_load): + * gst/gsttypefindfactory.c: (gst_type_find_factory_call_function): + * tools/gst-inspect.c: (print_element_info): + Fix refcounting of gst_plugin_feature_load to match the docs. + Fixes: #380129 + +2006-12-07 10:59:05 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Improve debugging of events. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_event), + (gst_base_sink_get_position): + Improve debugging of events. + +2006-12-07 10:51:36 +0000 René Stadler + + gst/gstclock.c: Make period ids add the interval to the origial requested time instead of the possibly updated time w... + Original commit message from CVS: + Patch by: René Stadler + * gst/gstclock.c: (gst_clock_id_wait): + Make period ids add the interval to the origial requested time instead + of the possibly updated time which can be wrong when there are multiple + waiters for the same id. Fixes #382592. + * gst/gstsystemclock.c: (gst_system_clock_async_thread), + (gst_system_clock_id_wait_jitter_unlocked), + (gst_system_clock_id_wait_jitter): + Fix restart in the async notify thread when an async entry is added to + the front of the list. Fixes #381492. + * tests/check/gst/gstsystemclock.c: (store_callback), + (notify_callback), (GST_START_TEST), (gst_systemclock_suite): + Added test for multiple async waits. + Added test for async wait order. + +2006-12-07 10:02:19 +0000 Wim Taymans + + gst/gstbin.c: Add some more docs about the POSITION query. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_query): + Add some more docs about the POSITION query. + +2006-12-07 02:37:18 +0000 Jan Schmidt + + 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:33:54 +0000 Jan Schmidt + + configure.ac: releasing 0.10.11, "Love never runs on time" + Original commit message from CVS: + === release 0.10.11 === + 2006-12-06 Jan Schmidt + * configure.ac: + releasing 0.10.11, "Love never runs on time" + +2006-12-01 10:23:26 +0000 Sergey Scobich + + win32/: Fix compilation on win32 under VS8 + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + * win32/vs8/libgstbase.vcproj: + * win32/vs8/libgstcoreelements.vcproj: + * win32/vs8/libgstreamer.vcproj: + Fix compilation on win32 under VS8 + Patch by: Sergey Scobich + Partially fixes #381175 + +2006-11-30 22:55:08 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-11-29 16:39:32 +0000 Jan Schmidt + + gst/gstvalue.c: If someone is foolish enough to compare 2 fractions with denominator = 0, return UNORDERED rather tha... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_compare_fraction): + If someone is foolish enough to compare 2 fractions with denominator = + 0, return UNORDERED rather than aborting. + +2006-11-28 12:07:06 +0000 Edward Hervey + + libs/gst/base/: New GstDataQueue object for threadsafe queueing. Most useful for elements that need some queueing fun... + Original commit message from CVS: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstdataqueue.c: (gst_data_queue_get_type), + (gst_data_queue_base_init), (gst_data_queue_class_init), + (gst_data_queue_init), (gst_data_queue_new), + (gst_data_queue_cleanup), (gst_data_queue_finalize), + (gst_data_queue_locked_flush), (gst_data_queue_locked_is_empty), + (gst_data_queue_locked_is_full), (gst_data_queue_flush), + (gst_data_queue_is_empty), (gst_data_queue_is_full), + (gst_data_queue_set_flushing), (gst_data_queue_push), + (gst_data_queue_pop), (gst_data_queue_drop_head), + (gst_data_queue_set_property), (gst_data_queue_get_property): + * libs/gst/base/gstdataqueue.h: + New GstDataQueue object for threadsafe queueing. Most useful for + elements that need some queueing functionnality. + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + Insert documentation for GstDataQueue + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstmultiqueue.c: (gst_multi_queue_base_init), + (gst_multi_queue_class_init), (gst_multi_queue_init), + (gst_multi_queue_finalize), (gst_multi_queue_set_property), + (gst_multi_queue_get_property), (gst_multi_queue_request_new_pad), + (gst_multi_queue_release_pad), (gst_single_queue_push_one), + (gst_multi_queue_item_destroy), (gst_multi_queue_item_new), + (gst_multi_queue_loop), (gst_multi_queue_chain), + (gst_multi_queue_sink_activate_push), (gst_multi_queue_sink_event), + (gst_multi_queue_getcaps), (gst_multi_queue_bufferalloc), + (gst_multi_queue_src_activate_push), (gst_multi_queue_acceptcaps), + (gst_multi_queue_src_event), (gst_multi_queue_src_query), + (wake_up_next_non_linked), (compute_next_non_linked), + (single_queue_overrun_cb), (single_queue_underrun_cb), + (single_queue_check_full), (gst_single_queue_new): + * plugins/elements/gstmultiqueue.h: + New multiqueue element, using GstDataQueue. Used for queuing multiple + streams. + Closes #344639 and #347785 + +2006-11-22 12:29:41 +0000 Stefan Kost + + docs/pwg/advanced-types.xml: add more missing type details + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + add more missing type details + * tools/gst-run.c: (main): + remove unused variable + +2006-11-21 08:30:20 +0000 Stefan Kost + + docs/libs/: add types of base classes to enable gobject specific stuff in the docs + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs.types: + add types of base classes to enable gobject specific stuff in the docs + * docs/random/ensonic/embedded.txt: + more ideas about isolating platform specific things + +2006-11-20 11:11:20 +0000 Sebastian Droege + + libs/gst/check/gstcheck.h: Fix compilation and running against 0.9.4. Fixes #377332. + Original commit message from CVS: + Patch by: Sebastian Droege + * libs/gst/check/gstcheck.h: + Fix compilation and running against 0.9.4. Fixes #377332. + +2006-11-20 10:27:49 +0000 Wim Taymans + + gst/gstsegment.c: Fix boundary checking in to_running_time() and to_stream_time(). + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_seek), + (gst_segment_set_newsegment_full), (gst_segment_to_stream_time), + (gst_segment_to_running_time): + Fix boundary checking in to_running_time() and to_stream_time(). + Fixes #377183. + * tests/check/gst/gstsegment.c: (GST_START_TEST): + stream and running time can now be calculated for the complete + clipped segment. + +2006-11-15 17:38:13 +0000 Tim-Philipp Müller + + gst/gstpad.c: Can't access event structure after giving away ownership of the event. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_push_event): + Can't access event structure after giving away ownership of + the event. + +2006-11-15 13:00:16 +0000 Stefan Kost + + docs/random/ensonic/: more thinking + Original commit message from CVS: + * docs/random/ensonic/embedded.txt: + * docs/random/ensonic/profiling.txt: + * docs/random/ensonic/receipies.txt: + more thinking + +2006-11-13 18:03:35 +0000 Mark Nauwelaerts + + gst/gstpad.c: Fix documentation for gst_pad_dispatcher. Fixes #374475. + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * gst/gstpad.c: + Fix documentation for gst_pad_dispatcher. Fixes #374475. + +2006-11-13 17:54:58 +0000 Jonathan Matthew + + libs/gst/base/gstbasesrc.c: Store new length in segment duration so we don't keep on calling the potentially expensiz... + Original commit message from CVS: + Patch by: Jonathan Matthew + * libs/gst/base/gstbasesrc.c: (gst_base_src_update_length): + Store new length in segment duration so we don't keep on calling the + potentially expensize get_size() call. Fixes #370865. + +2006-11-10 18:56:44 +0000 Sergey Scobich + + win32/common/libgstreamer.def: Add two missing symbols (#366492). + Original commit message from CVS: + Patch by: Sergey Scobich + * win32/common/libgstreamer.def: + Add two missing symbols (#366492). + +2006-11-10 10:50:19 +0000 Jan Schmidt + + libs/gst/base/gstadapter.c: Fix format string to use all its arguments. + Original commit message from CVS: + * libs/gst/base/gstadapter.c: (gst_adapter_flush), + (gst_adapter_take_buffer): + Fix format string to use all its arguments. + Remove useless >= check on a guint + +2006-11-09 15:25:39 +0000 Jan Schmidt + + tests/examples/adapter/.cvsignore: Ignore build file as commanded by the build-bot + Original commit message from CVS: + * tests/examples/adapter/.cvsignore: + Ignore build file as commanded by the build-bot + +2006-11-09 14:38:59 +0000 Jan Schmidt + + tests/examples/adapter/: Add new files from the previous commit + Original commit message from CVS: + * tests/examples/adapter/Makefile.am: + * tests/examples/adapter/adapter_test.c: (run_test_take), + (run_test_take_buffer), (run_tests), (main): + Add new files from the previous commit + +2006-11-09 14:37:38 +0000 Jan Schmidt + + Do some optimisation work in GstAdapter to avoid copies in more cases. + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * libs/gst/base/gstadapter.c: (gst_adapter_clear), + (gst_adapter_push), (gst_adapter_peek_into), (gst_adapter_peek), + (gst_adapter_flush), (gst_adapter_take), (gst_adapter_take_buffer): + * libs/gst/base/gstadapter.h: + * tests/check/libs/adapter.c: (create_and_fill_adapter), + (GST_START_TEST), (gst_adapter_suite): + * tests/examples/Makefile.am: + Do some optimisation work in GstAdapter to avoid copies in more cases. + It could still do slightly better by merging buffers when + gst_buffer_is_span_fast is true, but is already faster. + Also, avoid traversing a single-linked list to append each incoming + buffer inside the adapter. + Add simple test app that times the adapter behaviour in different + situations, and extend the unit test to check that bytes enter and + exit the adapter in their original order. + +2006-11-08 19:27:15 +0000 Tim-Philipp Müller + + docs/random/draft-missing-plugins.txt: Update: use element message instead of adding a new message type to the core; ... + Original commit message from CVS: + * docs/random/draft-missing-plugins.txt: + Update: use element message instead of adding a new message + type to the core; don't provide GStreamer API to initiate the + plugin download, just provide API to compose the strings needed + and let an external libgimmestuff handle the rest. + +2006-11-08 11:41:13 +0000 Jan Schmidt + + tools/gst-inspect.c: Print a string instead of 'unknown type' for GValueArray properties + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + Print a string instead of 'unknown type' for GValueArray properties + +2006-11-08 10:35:24 +0000 Jan Schmidt + + * ChangeLog: + Fix Christian's email address in Changelog + Original commit message from CVS: + Fix Christian's email address in Changelog + +2006-11-08 02:04:52 +0000 Christian Schaller + + docs/random/draft-missing-plugins.txt: More small fixes. + Original commit message from CVS: + * docs/random/draft-missing-plugins.txt: + More small fixes. + +2006-11-08 02:03:48 +0000 Tim-Philipp Müller + + tests/examples/typefind/typefind.c: Make typefind element example work again (#371894); add a license header. + Original commit message from CVS: + * tests/examples/typefind/typefind.c: (type_found), (main): + Make typefind element example work again (#371894); add a + license header. + +2006-11-08 01:40:27 +0000 Tim-Philipp Müller + + docs/random/draft-missing-plugins.txt: Commit initial draft about how to deal with missing plugins, needs work (API t... + Original commit message from CVS: + * docs/random/draft-missing-plugins.txt: + Commit initial draft about how to deal with missing plugins, + needs work (API too). + +2006-11-07 07:34:43 +0000 Stefan Kost + + docs/pwg/advanced-types.xml: documents the new caps elements (see #363118) + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + documents the new caps elements (see #363118) + +2006-11-06 17:53:24 +0000 Tim-Philipp Müller + + Use g_strerror() instead of strerror() - we want UTF-8. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + * plugins/elements/gstfilesrc.c: (gst_mmap_buffer_finalize), + (gst_file_src_map_region), (gst_file_src_start): + * plugins/indexers/gstfileindex.c: (gst_file_index_load), + (gst_file_index_commit): + Use g_strerror() instead of strerror() - we want UTF-8. + +2006-11-06 17:25:01 +0000 Peter Kjellerstedt + + plugins/elements/gstfdsrc.c: Another printf fix (#371493). + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * plugins/elements/gstfdsrc.c: (gst_fd_src_create): + Another printf fix (#371493). + +2006-11-06 15:22:40 +0000 Stefan Kost + + tests/check/gst/gsttag.c: relicence (okay with author=company) + Original commit message from CVS: + * tests/check/gst/gsttag.c: + relicence (okay with author=company) + +2006-11-06 15:18:57 +0000 Stefan Kost + + gst/gstpad.c: Enhance debug and improve docs + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_event_default_dispatch), + (gst_pad_push_event): + Enhance debug and improve docs + * gst/gsturi.c: + Fix docs + +2006-11-06 15:17:35 +0000 Stefan Kost + + docs/random/ensonic/: more ideas + Original commit message from CVS: + * docs/random/ensonic/distributed.txt: + * docs/random/ensonic/profiling.txt: + more ideas + +2006-11-06 15:14:46 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: add new API and fix the build + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + add new API and fix the build + * gst/gstbin.c: (gst_bin_recalc_state): + * gst/gstelement.c: (gst_element_message_full), + (gst_element_get_state_func), (gst_element_set_state_func): + use new API and improve logging + * gst/gstutils.c: (gst_element_state_change_return_get_name): + * gst/gstutils.h: + API: add function to get StateChangereturn names to improve logs + +2006-11-06 12:01:27 +0000 Zaheer Abbas Merali + + * docs/random/zaheerm/dvb-interface.txt: + Notes taken while discussing dvb channel selection with Wim + Original commit message from CVS: + Notes taken while discussing dvb channel selection with Wim + +2006-11-04 12:54:08 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/random/moving-plugins: + * plugins/elements/gstfilesrc.c: + don't put strerror in translatable message + Original commit message from CVS: + don't put strerror in translatable message + +2006-11-03 15:04:40 +0000 Wim Taymans + + plugins/elements/gstfdsrc.c: Get the type and printf conversion specifiers right. + Original commit message from CVS: + * plugins/elements/gstfdsrc.c: (gst_fd_src_create): + Get the type and printf conversion specifiers right. + +2006-11-03 13:57:28 +0000 Mark Nauwelaerts + + gst/gstpad.c: Some small cleanups. Improve debugging. + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * gst/gstpad.c: (gst_pad_init), (pre_activate), + (gst_pad_set_blocked_async), (gst_pad_acceptcaps_default), + (gst_pad_accept_caps), (handle_pad_block), (gst_pad_push_event): + Some small cleanups. Improve debugging. + * gst/gstpad.h: + Signal all waiting threads with a broadcast instead of just one. + Fixes #369942. + +2006-11-03 09:40:03 +0000 Wim Taymans + + plugins/elements/gstfdsrc.c: Add some debugging. + Original commit message from CVS: + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd), + (gst_fd_src_create): + Add some debugging. + Only update fd when it's different from the old. + +2006-11-02 20:52:21 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesrc.c: Printf fixes for PPC/OSX, take two (#369366). + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_create_mmap): + Printf fixes for PPC/OSX, take two (#369366). + +2006-11-02 13:00:38 +0000 Jan David Mol + + plugins/elements/: Printf fixes for gsize parameters on PPC/OSX (#369366). Also, don't cast to long long for portabil... + Original commit message from CVS: + Based on patch by: Jan David Mol + * plugins/elements/gstfilesink.c: (gst_file_sink_class_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init), + (gst_file_src_map_small_region), (gst_file_src_create_mmap): + Printf fixes for gsize parameters on PPC/OSX (#369366). Also, + don't cast to long long for portability reasons, but use + GLib's types instead. + +2006-10-30 18:43:12 +0000 Michael Smith + + plugins/elements/gstfdsrc.c: Get the arguments to lseek() the right way around. + Original commit message from CVS: + * plugins/elements/gstfdsrc.c: (gst_fd_src_update_fd): + Get the arguments to lseek() the right way around. + Fixes 367677. + +2006-10-30 07:51:13 +0000 gorshkov + + gst/gstinfo.h: _declspec should be __declspec (two underscores, not one). Fixes 366572. + Original commit message from CVS: + Patch by: gorshkov + * gst/gstinfo.h: + _declspec should be __declspec (two underscores, not one). Fixes 366572. + +2006-10-28 15:42:29 +0000 Kjartan Maraas + + Typo fixes (#366212). + Original commit message from CVS: + Patch by: Kjartan Maraas + * docs/design/part-MT-refcounting.txt: + * docs/random/wtay/capsnego2-docs: + * gst/gstclock.c: + * gst/gstxml.c: + Typo fixes (#366212). + +2006-10-28 15:10:26 +0000 Sergey Scobich + + Add needed entries in .def files. + Original commit message from CVS: + Patch by: Sergey Scobich + * gst/gst.c: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + * win32/vs8/libgstbase.vcproj: + * win32/vs8/libgstcontroller.vcproj: + Add needed entries in .def files. + Use HAVE_UNISTD_H. + Rearrange def files in vs8 solutions. Fixes #366286. + +2006-10-28 15:03:19 +0000 Tim-Philipp Müller + + win32/common/gstconfig.h: Add GST_SEGMENT_FORMAT and GST_USING_PRINTF_EXTENSION to the hand-made win32 gstconfig.h. F... + Original commit message from CVS: + * win32/common/gstconfig.h: + Add GST_SEGMENT_FORMAT and GST_USING_PRINTF_EXTENSION to the + hand-made win32 gstconfig.h. Fixes #366321. + +2006-10-27 16:31:15 +0000 Wim Taymans + + gst/gstghostpad.c: Make acceptcaps return TRUE when we don't have a target, just like setcaps does. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_do_acceptcaps), + (gst_ghost_pad_new_full): + Make acceptcaps return TRUE when we don't have a target, just like + setcaps does. + +2006-10-27 10:10:26 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Revert previous commit, 0 sized buffers are allowed. Reopens #363095. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_chain): + Revert previous commit, 0 sized buffers are allowed. Reopens #363095. + +2006-10-26 08:49:52 +0000 Tim-Philipp Müller + + gst/gststructure.c: If someone tries to set a non-UTF8 string field on a structure, don't just print a warning, but a... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_id_set_value): + If someone tries to set a non-UTF8 string field on a structure, + don't just print a warning, but also ignore the request and do + not change/add that field to the structure. + * tests/check/gst/gsttag.c: (GST_START_TEST), (gst_tag_suite): + Test for the above. + +2006-10-26 00:00:34 +0000 David Schleef + + gst/gstinfo.c: g_hash_table_insert() needs a cast to a non-const pointer duh. + Original commit message from CVS: + * gst/gstinfo.c: + g_hash_table_insert() needs a cast to a non-const pointer duh. + +2006-10-25 23:47:40 +0000 David Schleef + + gst/gstinfo.*: Change name parameter of _gst_debug_register_funcptr to const to reflect the constness of its use in t... + Original commit message from CVS: + * gst/gstinfo.c: + * gst/gstinfo.h: + Change name parameter of _gst_debug_register_funcptr to const + to reflect the constness of its use in the function as well + as to quiet a gcc warning. + +2006-10-25 13:41:44 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Don't push the buffer if it's empty. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_chain): + Don't push the buffer if it's empty. + Closes #363095 + +2006-10-24 08:22:19 +0000 Wim Taymans + + gst/gstevent.h: Add small comment. + Original commit message from CVS: + * gst/gstevent.h: + Add small comment. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_eventfunc): + Debug segment values *after* updating them as this is more + interesting. + +2006-10-23 15:21:12 +0000 Wim Taymans + + docs/design/part-events.txt: Update some docs. + Original commit message from CVS: + * docs/design/part-events.txt: + Update some docs. + * docs/design/part-block.txt: + * gst/gstpad.c: (gst_pad_is_blocking), (handle_pad_block), + (gst_pad_push_event): + Revert BLOCKING patch, it tries to be smart without really having a + clear idea what or how. So, now we discard all FLUSHING events again on + a blocking pad. Should fix gnonlin again. + +2006-10-23 14:51:30 +0000 Sergey Scobich + + libs/gst/base/gstbasesrc.c: Make sure size is always initialized. Fixes #364388. + Original commit message from CVS: + Patch by: Sergey Scobich + * libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing), + (gst_base_src_start), (gst_base_src_activate_push): + Make sure size is always initialized. Fixes #364388. + +2006-10-20 11:36:56 +0000 Stefan Kost + + docs/random/ensonic/distributed.txt: add some ideas about doing distributed processing + Original commit message from CVS: + * docs/random/ensonic/distributed.txt: + add some ideas about doing distributed processing + * docs/random/ensonic/profiling.txt: + get_rusage look promising + +2006-10-18 19:43:46 +0000 Stefan Kost + + docs/manual/basics-helloworld.xml: Add a cast in example to fix compile warning + Original commit message from CVS: + * docs/manual/basics-helloworld.xml: + Add a cast in example to fix compile warning + +2006-10-18 15:28:19 +0000 Wim Taymans + + gst/gstsegment.c: Relax arg checking again, -1 is allowed. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_last_stop), + (gst_segment_set_seek), (gst_segment_set_newsegment_full): + Relax arg checking again, -1 is allowed. + +2006-10-18 13:27:39 +0000 Wim Taymans + + gst/gstsegment.c: _set_last_stop() must be with a value != -1 + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_last_stop), + (gst_segment_set_seek), (gst_segment_set_newsegment_full): + _set_last_stop() must be with a value != -1 + A _TYPE_SET to -1 means seek to 0. + Calc last_stop correctly for negative rates. + Make sure we work with positive durations when updating a segment. + +2006-10-18 13:21:56 +0000 Wim Taymans + + Small docs fixes. + Original commit message from CVS: + * docs/design/part-live-source.txt: + * gst/gstclock.h: + Small docs fixes. + +2006-10-18 10:08:45 +0000 Tim-Philipp Müller + + gst/gstbuffer.h: Add an explicit cast to GstBuffer** to keep old code that added an explicit cast to GstMiniObject** ... + Original commit message from CVS: + * gst/gstbuffer.h: + Add an explicit cast to GstBuffer** to keep old code that added an + explicit cast to GstMiniObject** for gst_mini_object_replace() + compiling without warning. + +2006-10-18 08:54:30 +0000 Stefan Kost + + gst/gstvalue.c: check for validity of dates + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_set_date), (gst_date_copy): + check for validity of dates + +2006-10-17 12:09:35 +0000 Tim-Philipp Müller + + docs/gst/gstreamer-sections.txt: Forgot this one, makes gtk-doc shut up. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Forgot this one, makes gtk-doc shut up. + +2006-10-17 11:57:32 +0000 Peter Kjellerstedt + + gst/gstobject.h: Don't define xmlNodePtr to gpointer if the core was built with + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * gst/gstobject.h: + Don't define xmlNodePtr to gpointer if the core was built with + --disable-loadsave and --disable-registry, this will break + applications that want to use libxml2 but are buildling against a + core that doesn't use libxml2. Use an intermediary type GstXmlNodePtr + instead so we don't have to mess with the libxml2 namespace + (#361675). + +2006-10-17 10:30:27 +0000 Tim-Philipp Müller + + gst/gstbuffer.h: Fix gst_buffer_replace() macro to avoid gst_mini_object_replace()-related type-punned pointer warnings. + Original commit message from CVS: + * gst/gstbuffer.h: + Fix gst_buffer_replace() macro to avoid gst_mini_object_replace()-related + type-punned pointer warnings. + +2006-10-16 20:02:38 +0000 Tim-Philipp Müller + + gst/gstelement.h: Add casts to the correct return type to state <=> state transition macros. + Original commit message from CVS: + * gst/gstelement.h: + Add casts to the correct return type to state <=> state transition + macros. + +2006-10-16 13:53:55 +0000 Stefan Kost + + docs/design/part-live-source.txt: describe howto handle latency + Original commit message from CVS: + * docs/design/part-live-source.txt: + describe howto handle latency + * docs/random/ensonic/profiling.txt: + more ideas + * tools/gst-plot-timeline.py: + fix log parsing for solaris, remove unused function + +2006-10-16 11:46:04 +0000 Wim Taymans + + Update some docs regarding reverse playback. + Original commit message from CVS: + * docs/design/part-trickmodes.txt: + * gst/gstevent.c: + Update some docs regarding reverse playback. + +2006-10-15 12:47:13 +0000 Marcus Granado + + win32/vs8/grammar.vcproj: Error out with a warning if glib-genmarshal.exe is not in path, instead of creating bogus g... + Original commit message from CVS: + Patch by: Marcus Granado + * win32/vs8/grammar.vcproj: + Error out with a warning if glib-genmarshal.exe is not in path, + instead of creating bogus gstmarshal.[ch] files. Fixes #361720. + +2006-10-13 16:09:53 +0000 Wim Taymans + + gst/gstsegment.c: When seeking to stop -1, set last_stop (current position) to the duration of the segment. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_seek): + When seeking to stop -1, set last_stop (current position) to the + duration of the segment. + +2006-10-13 13:27:46 +0000 Yves Lefebvre + + gst/gstelement.h: Clarify _NO_PREROLL a bit more. + Original commit message from CVS: + * gst/gstelement.h: + Clarify _NO_PREROLL a bit more. + * gst/gstevent.c: + Fix docs. + * gst/gstpad.c: (gst_pad_link_check_hierarchy), + (gst_pad_get_caps_unlocked), (gst_pad_save_thyself), + (handle_pad_block), (gst_pad_push_event), (gst_pad_send_event): + Patch by: Yves Lefebvre Fix possible deadlock + due to wrong locking order. Fixes #361769. + Remove some redundant/misplaced checks in pad_block. + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position): + For negative rates, count backwards from the duration. + +2006-10-13 09:37:59 +0000 Tim-Philipp Müller + + gst/gsterror.c: Fix error message for GST_LIBRARY_ERROR_SETTINGS (feel free to come up with something better). + Original commit message from CVS: + * gst/gsterror.c: (_gst_library_errors_init): + Fix error message for GST_LIBRARY_ERROR_SETTINGS (feel free to come + up with something better). + +2006-10-12 22:35:52 +0000 Tim-Philipp Müller + + win32/: Don't reference glib-compat.c which is currently not used and not disted; add gstquark.c which was recently a... + Original commit message from CVS: + * win32/vs6/libgstreamer.dsp: + * win32/vs7/libgstreamer.vcproj: + * win32/vs8/libgstreamer.vcproj: + Don't reference glib-compat.c which is currently not used and not + disted; add gstquark.c which was recently added. Fixes #361730. + +2006-10-12 16:09:24 +0000 Tim-Philipp Müller + + win32/common/: Add gst_caps_merge() and a bunch of other recently-added functions. + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + Add gst_caps_merge() and a bunch of other recently-added functions. + Fixes #361732. + +2006-10-11 16:30:14 +0000 Wim Taymans + + docs/plugins/: Update element args. + Original commit message from CVS: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + Update element args. + * gst/gstsystemclock.c: + Small comment update. + * plugins/elements/gsttee.c: (gst_tee_class_init), (gst_tee_init), + (gst_tee_request_new_pad), (gst_tee_release_pad), + (gst_tee_buffer_alloc), (gst_tee_sink_activate_push), + (gst_tee_sink_activate_pull): + * plugins/elements/gsttee.h: + Some tee loving: + Add default property defines. + Implement release pad function. + Give properties better blubs etc. + Activate pads before adding them to a running tee. + Do simple buffer_alloc on the first requested pad. + Post error when activation fails. + +2006-10-11 12:16:05 +0000 Tim-Philipp Müller + + gst/gst.c: Check return value of write() to make compiler happy. + Original commit message from CVS: + * gst/gst.c: (ensure_current_registry_forking): + Check return value of write() to make compiler happy. + +2006-10-11 10:10:37 +0000 Sjoerd Simons + + plugins/elements/gstqueue.c: Recheck queue filledness after signalling the overrun when we're about to leak downstrea... + Original commit message from CVS: + Patch by: Sjoerd Simons + * plugins/elements/gstqueue.c: (gst_queue_chain): + Recheck queue filledness after signalling the overrun when we're about + to leak downstream because we released the lock when emitting the signal + and the queue could be empty again. Fixes #352345. + +2006-10-11 09:13:26 +0000 Tim-Philipp Müller + + libs/gst/controller/gstcontroller.c: Fix refcounting here too, just like we did for _new_valist() a few days ago (#35... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_list): + Fix refcounting here too, just like we did for _new_valist() a few + days ago (#357180) (thanks to René Stadler). Also remove all those + 'Since: 0.9' from the gtk-doc blobs. + * tests/check/libs/controller.c: (controller_refcount_new_list), + (gst_controller_suite): + Unit test for the above. + +2006-10-10 14:47:40 +0000 Sebastien Cote + + gst/gstpad.c: Update some docs. + Original commit message from CVS: + Patch by: Sebastien Cote + * gst/gstpad.c: (gst_pad_get_caps_unlocked), + (gst_pad_save_thyself): + Update some docs. + Write pad direction in XML output. Fixes #345496. + +2006-10-10 14:13:08 +0000 René Stadler + + libs/gst/controller/gstcontroller.c: Take ref to controlled object so that it cannot disappear. + Original commit message from CVS: + Patch by: René Stadler + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist), + (gst_controller_new_list), (_gst_controller_dispose), + (_gst_controller_finalize), (_gst_controller_class_init): + Take ref to controlled object so that it cannot disappear. + Fixes #357432. + +2006-10-10 14:09:43 +0000 Wim Taymans + + libs/gst/check/gstcheck.c: Activate/deactivate pads in setup/teardown respectively. + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_setup_src_pad), + (gst_check_teardown_src_pad), (gst_check_setup_sink_pad), + (gst_check_teardown_sink_pad): + Activate/deactivate pads in setup/teardown respectively. + +2006-10-10 12:12:44 +0000 Josep Torre Valles + + gst/Makefile.am: Cast values when making gstenumtypes.h. This pacifies Forte so it doesn't warn about the ~0 as GST_... + Original commit message from CVS: + 2006-10-10 Zaheer Abbas Merali + Patch by: Josep Torre Valles + * gst/Makefile.am: + Cast values when making gstenumtypes.h. This pacifies Forte + so it doesn't warn about the ~0 as GST_MESSAGE_ANY not fitting + in the enumeration. + +2006-10-09 17:15:39 +0000 Wim Taymans + + gst/gstevent.c: Rename some more @cur to @start to fix docs. + Original commit message from CVS: + * gst/gstevent.c: (gst_event_new_seek), (gst_event_parse_seek): + Rename some more @cur to @start to fix docs. + * gst/gstsegment.c: (gst_segment_set_seek): + Fix typo. + time and start must always stay in sync as defined in design doc. + * gst/gsttaglist.c: (gst_tag_list_is_empty): + Rename param to fix docs. + * tests/check/gst/gstsegment.c: (GST_START_TEST): + Check that start and time are in sync. + * tests/check/pipelines/parse-launch.c: + (gst_parse_test_element_change_state): + Activate pad before adding to the element. + +2006-10-09 16:33:29 +0000 Wim Taymans + + docs/design/part-qos.txt: Fix typo. + Original commit message from CVS: + * docs/design/part-qos.txt: + Fix typo. + * gst/gstevent.c: + * gst/gstevent.h: + Update seek event docs regarding negative rates. + Rename @cur to @start. + * gst/gstsegment.c: (gst_segment_set_seek): + * gst/gstsegment.h: + Update set_seek docs regarding negative rates. + Correctly update last_stop to @stop when dealing with negative + rates. + Rename @cur to @start. + * tests/check/gst/gstpad.c: (GST_START_TEST): + Activate pads before trying to use them. + * tests/check/gst/gstsegment.c: (GST_START_TEST), + (gst_segment_suite): + Add simple check for segments and negative rates. + +2006-10-09 11:20:44 +0000 Tim-Philipp Müller + + API: add gst_tag_list_is_empty() (#360467). + Original commit message from CVS: + * gst/gsttaglist.c: (gst_tag_list_is_empty): + * gst/gsttaglist.h: + * docs/gst/gstreamer-sections.txt: + API: add gst_tag_list_is_empty() (#360467). + * tests/check/gst/gsttag.c: (GST_START_TEST): + And a test case. + +2006-10-09 11:06:50 +0000 Zaheer Abbas Merali + + gst/gstmessage.h: Revert change from earlier wrt GST_MESSAGE_TYPE_ANY having a value that doesn't fit on enumeration. + Original commit message from CVS: + 2006-10-09 Zaheer Abbas Merali + * gst/gstmessage.h: + Revert change from earlier wrt GST_MESSAGE_TYPE_ANY having + a value that doesn't fit on enumeration. + +2006-10-09 10:14:28 +0000 Zaheer Abbas Merali + + libs/gst/net/gstnetclientclock.c: Remove local debugging system and use Gstreamer's instead. + Original commit message from CVS: + 2006-10-09 Zaheer Abbas Merali + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_thread): + Remove local debugging system and use Gstreamer's instead. + +2006-10-09 09:32:29 +0000 Josep Torre Valles + + common/m4/gst-error.m4: Disable warning of statement not reached on Forte. + Original commit message from CVS: + 2006-10-09 Zaheer Abbas Merali + Patch by: Josep Torre Valles + * common/m4/gst-error.m4: + Disable warning of statement not reached on Forte. + * gst/gstmessage.h: + Fix warning on Forte (value doesn't fit on enumeration). + * libs/gst/base/gstbasesink.c: (gst_base_sink_chain_unlocked): + Fix warning on Forte (value doesn't fit on enumeration). + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_thread): + DEBUG macro says it takes minimum of 2 args and so Forte + complains about the use with just 1 arg. + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + Use correct return type for the uri handler implementations. + All these fix warnings in Forte. Fixes bug #360860. + +2006-10-08 13:27:17 +0000 Tim-Philipp Müller + + gst/gstelement.h: gcc versions prior to gcc 3.3 apparently complain about a NULL printf format string, so don't use G... + Original commit message from CVS: + * gst/gstelement.h: + gcc versions prior to gcc 3.3 apparently complain about a NULL printf + format string, so don't use G_GNUC_PRINTF for those versions. + +2006-10-07 18:41:19 +0000 Tim-Philipp Müller + + gst/gsttaglist.*: Minor fixes to GST_IS_TAG_LIST and gst_is_tag_list(). + Original commit message from CVS: + * gst/gsttaglist.c: (gst_is_tag_list): + * gst/gsttaglist.h: + Minor fixes to GST_IS_TAG_LIST and gst_is_tag_list(). + * tests/check/gst/gsttag.c: (GST_START_TEST), (gst_tag_suite): + Small test for the above. + +2006-10-07 18:11:03 +0000 Tim-Philipp Müller + + gst/gsttaglist.h: Less tabs, more spaces. + Original commit message from CVS: + * gst/gsttaglist.h: + Less tabs, more spaces. + +2006-10-06 17:21:33 +0000 Tim-Philipp Müller + + gst/gstinfo.h: Those two function declarations do actually belong there, revert commit from yesterday that turned the... + Original commit message from CVS: + * gst/gstinfo.h: + Those two function declarations do actually belong there, revert + commit from yesterday that turned them intro macros. + +2006-10-06 14:46:04 +0000 Josep Torre Valles + + gst/gst.c: Fix empty declaration and type mismatch. + Original commit message from CVS: + 2006-10-06 Zaheer Abbas Merali + Patch by: Josep Torre Valles + * gst/gst.c: (gst_init_get_option_group): + Fix empty declaration and type mismatch. + * gst/gstbin.c: (gst_bin_change_state_func): + Fix type mismatch. + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_set_state_func), (gst_element_change_state), + (gst_element_change_state_func): + Fix type mismatches. + * gst/gstinfo.c: (gst_debug_compare_log_function_by_func), + (gst_debug_remove_log_function), (_gst_debug_nameof_funcptr): + Cast as appropriate. + * gst/gstobject.c: (gst_class_signal_connect): + Cast as appropriate. The function pointer parameter really + has the wrong type but would break API if we change it. + * gst/gstquery.c: + Fix redefinition of _FILE_OFFSET_BITS caused on Solaris wrt + order of including string.h. + * gst/gstutils.c: (gst_element_state_get_name): + Remove unreachable line. + * gst/gstxml.c: (gst_xml_parse_doc): + Fix type mismatch. + All these caught by Forte. + +2006-10-06 14:00:49 +0000 Josep Torre Valles + + common/m4/gst-error.m4: Fixed bug #360151. + Original commit message from CVS: + 2006-10-06 Zaheer Abbas Merali + Patch by: Josep Torre Valles + * common/m4/gst-error.m4: + Fixed bug #360151. + We need to disable warnings on Forte for empty declarations + due to gst-indent adding ;s to lines that just use macros + where the macro actually doesn't need a ; at end to end + statement. + +2006-10-06 13:01:30 +0000 Wim Taymans + + plugins/elements/gstfilesink.c: Add some FIXME for the NEWSEGMENT handling. + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_open_file), + (gst_file_sink_close_file), (gst_file_sink_event), + (gst_file_sink_render): + Add some FIXME for the NEWSEGMENT handling. + +2006-10-05 15:47:44 +0000 Zaheer Abbas Merali + + gst/parse/grammar.y: Remove static function gst_parse_element_lock as all it does is return. Looks like cruft from 0.8. + Original commit message from CVS: + 2006-10-05 Zaheer Abbas Merali + * gst/parse/grammar.y: + Remove static function gst_parse_element_lock as all it does + is return. Looks like cruft from 0.8. + +2006-10-05 15:31:16 +0000 Josep Torre Valles + + Fix a compilation issue with Forte on Solaris. inet_aton is in libresolv. + Original commit message from CVS: + 2006-10-05 Zaheer Abbas Merali + Patch by: Josep Torre Valles + * common/m4/gst-error.m4: + * configure.ac: + * libs/gst/net/Makefile.am: + Fix a compilation issue with Forte on Solaris. inet_aton is in + libresolv. + +2006-10-05 14:26:08 +0000 Tim-Philipp Müller + + Printf fixes. + Original commit message from CVS: + * gst/gstpad.c: (pre_activate): + * gst/gstregistry.c: (gst_registry_scan_path_level): + * gst/gstregistryxml.c: (load_plugin): + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode): + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_packet_from_event_1_0): + * libs/gst/net/gstnetclientclock.c: + (gst_net_client_clock_observe_times): + * plugins/elements/gstfdsrc.c: (gst_fd_src_create): + Printf fixes. + +2006-10-05 12:31:07 +0000 Tim-Philipp Müller + + Add GST_USING_PRINTF_EXTENSION to gstconfig.h so that we know whether we can use G_GNUC_PRINTF in other header files ... + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/gstconfig.h.in: + * gst/gstelement.h: + * gst/gstinfo.h: + Add GST_USING_PRINTF_EXTENSION to gstconfig.h so that we know + whether we can use G_GNUC_PRINTF in other header files and at + least check the printf format/arguments of debug messages and + GST_ELEMENT_ERROR messages when the printf extension is not + being used. + Replace more tabs with spaces in gstinfo.h and remove two spurious + function declarations in GST_DISABLE_DEBUG part with macros. + +2006-10-03 19:13:36 +0000 Tim-Philipp Müller + + gst/gstbus.c: More docs for the sync-message signal (mention that it is not emitted by default); log message structur... + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_class_init), (gst_bus_post): + More docs for the sync-message signal (mention that it is not + emitted by default); log message structures of messages posted on + the bus as well. + +2006-10-03 15:10:51 +0000 Jan Schmidt + + gst/gst.c: Use a pipe pair to receive status results from the forked child, and ignore the result from waitpid. Fixes... + Original commit message from CVS: + * gst/gst.c: (ensure_current_registry_forking): + Use a pipe pair to receive status results from the forked child, and + ignore the result from waitpid. Fixes #355499 + +2006-10-02 16:46:16 +0000 Wim Taymans + + tests/check/gst/gstghostpad.c: Fix leak in check. + Original commit message from CVS: + * tests/check/gst/gstghostpad.c: (GST_START_TEST), + (gst_ghost_pad_suite): + Fix leak in check. + +2006-10-02 16:37:56 +0000 Tim-Philipp Müller + + gst/gstpad.c: Add 'Since: 0.10.11' to gst_pad_is_blocking() gtk-doc blurb. + Original commit message from CVS: + * gst/gstpad.c: + Add 'Since: 0.10.11' to gst_pad_is_blocking() gtk-doc blurb. + +2006-10-02 16:01:54 +0000 Edward Hervey + + docs/design/part-block.txt: Further explain the use of flushing on blocked pads. + Original commit message from CVS: + * docs/design/part-block.txt: + Further explain the use of flushing on blocked pads. + * docs/gst/gstreamer-sections.txt: + * gst/gstpad.c: (gst_pad_is_blocking), (handle_pad_block), + (gst_pad_push_event): + * gst/gstpad.h: + Added new GstPadFlag : GST_PAD_BLOCKING. + Adds the notion of pads really blocking, which enables to properly + handle FLUSH_START/FLUSH_STOP events on blocked pads. + Fixes #358999 + API: gst_pad_is_blocking() + API: GST_PAD_IS_BLOCKING() macro + API: GST_PAD_BLOCKING GstPadFlag + +2006-10-02 10:06:17 +0000 mrcgran + + gst/gstghostpad.c: Filter the proxied caps against the padtemplate if we have one. + Original commit message from CVS: + Patch by: mrcgran + * gst/gstghostpad.c: (gst_proxy_pad_do_getcaps): + Filter the proxied caps against the padtemplate if we have one. + * gst/gstquery.c: (gst_query_new_segment): + Add include for gstinfo.h so that compilation with + -DGST_DISABLE_GST_DEBUG works again. Fixes #358436. + +2006-10-02 09:44:03 +0000 Wim Taymans + + * ChangeLog: + Give credit + Original commit message from CVS: + Give credit + +2006-10-02 09:41:09 +0000 Wim Taymans + + plugins/elements/gstfilesink.c: Set file to NULL when closing filesink so that we can set a new filename in READY. Fi... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_init), + (gst_file_sink_set_location), (gst_file_sink_open_file), + (gst_file_sink_close_file), (gst_file_sink_event), + (gst_file_sink_render): + Set file to NULL when closing filesink so that we can set a new filename + in READY. Fixes #358613. + +2006-10-02 08:37:24 +0000 Alessandro Decina + + gst/gstevent.c: Fix gst_mini_object_make_writable() and gst_event_copy() for events with event structures by setting ... + Original commit message from CVS: + Patch by: Alessandro Decina + * gst/gstevent.c: (_gst_event_copy): + Fix gst_mini_object_make_writable() and gst_event_copy() for events + with event structures by setting the parent refcount address of the + copied structure to the address of the refcount member of the newly + copied event rather than the address of the refcount member of the + original event. Fixes #358737. + * tests/check/gst/gstevent.c: (GST_START_TEST): + Unit test for the above. + +2006-09-29 20:29:49 +0000 Stefan Kost + + docs/design/Makefile.am: Dist some more files. + Original commit message from CVS: + * docs/design/Makefile.am: + Dist some more files. + +2006-09-29 12:31:18 +0000 Tim-Philipp Müller + + tests/check/libs/controller.c: Add test for the previous fix; add some more tests for correct refcounting behaviour; ... + Original commit message from CVS: + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add test for the previous fix; add some more tests + for correct refcounting behaviour; fix a few leaks + in test cases; call gst_controller_init() at start + of all tests. + +2006-09-29 12:24:50 +0000 Tim-Philipp Müller + + libs/gst/controller/gstcontroller.c: Don't g_return_val_if_fail() on timed values with invalid timestamps inside a cr... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist), + (gst_controller_set_from_list): + Don't g_return_val_if_fail() on timed values with invalid timestamps + inside a critical section without unlocking the mutex. Spotted by + René Stadler. (#357617) + Also, fix up refcounting properly: when returning an existing + controller, we should increase the reference only once and not + once per property and when trying to control a property again + we should also increase the refcount. + +2006-09-29 08:22:22 +0000 Wim Taymans + + libs/gst/net/: Stop reading commands when EOF as well. + Original commit message from CVS: + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_thread): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_thread): + Stop reading commands when EOF as well. + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init): + * plugins/elements/gstidentity.c: (gst_identity_class_init): + Unify description of the dump property. + +2006-09-28 17:20:17 +0000 Jan Schmidt + + * ChangeLog: + Mention bug number in previous commit + Original commit message from CVS: + Mention bug number in previous commit + +2006-09-28 15:52:04 +0000 Jan Schmidt + + tests/examples/manual/.cvsignore: OK, so it's actually cvsignore that needs changing. Stop laughing. + Original commit message from CVS: + * tests/examples/manual/.cvsignore: + OK, so it's actually cvsignore that needs changing. Stop laughing. + +2006-09-28 15:27:12 +0000 Jan Schmidt + + tests/examples/manual/Makefile.am: Gah, declare vars *before* using them + Original commit message from CVS: + * tests/examples/manual/Makefile.am: + Gah, declare vars *before* using them + +2006-09-28 14:00:43 +0000 Jan Schmidt + + gst/: Re-commit the registry changes, along with an extra fix: + Original commit message from CVS: + * gst/gst.c: (init_pre), (scan_and_update_registry), + (ensure_current_registry_nonforking), + (ensure_current_registry_forking), (ensure_current_registry), + (init_post), (gst_debug_help), (gst_deinit): + * gst/gst_private.h: + * gst/gstregistry.c: (gst_registry_finalize), + (gst_registry_remove_features_for_plugin_unlocked), + (gst_registry_remove_plugin), (gst_registry_scan_path_level), + (gst_registry_scan_path), + (_priv_gst_registry_remove_cache_plugins), + (_priv_gst_registry_cleanup): + * gst/gstregistry.h: + Re-commit the registry changes, along with an extra fix: + When a cached plugin is encountered at a different file path, + update the stored path in the registry cache so that the parent + process knows where it actually is now when it re-reads the registry + cache. Fixes the thing that broke distcheck with the previous commit. + * tests/check/Makefile.am: + Clean up files named 'core' too when running make clean. + * tests/examples/manual/Makefile.am: + Set up a registry path for running these tests, and clean it properly + for distcheck. + +2006-09-28 11:11:28 +0000 Jan Schmidt + + configure.ac: Don't pull in gmodule-2.0.pc as a dependency in our .pc files - we want gmodule-no-export-2.0.pc instea... + Original commit message from CVS: + * configure.ac: + Don't pull in gmodule-2.0.pc as a dependency in our .pc files - we + want gmodule-no-export-2.0.pc instead so that we don't drag in + --export-dynamic on every project that links to GStreamer. + Also, make our export regex only match the start of symbols, rather + than any symbol that contains '_gst' somewhere. + * libs/gst/check/Makefile.am: + The libgstcheck we build does however need export-dynamic, as it + produces some symbols that don't match our _gst... style regex. + +2006-09-27 17:42:47 +0000 Jan Schmidt + + gst/: Revert previous change until I figure out why it breaks distcheck. + Original commit message from CVS: + * gst/gst.c: (init_pre), (scan_and_update_registry), + (ensure_current_registry_nonforking), + (ensure_current_registry_forking), (ensure_current_registry), + (init_post), (gst_debug_help), (gst_deinit): + * gst/gst_private.h: + * gst/gstregistry.c: (gst_registry_finalize), + (gst_registry_remove_plugin), (gst_registry_scan_path_level), + (gst_registry_scan_path), (_gst_registry_remove_cache_plugins), + (_gst_registry_cleanup): + * gst/gstregistry.h: + Revert previous change until I figure out why it breaks distcheck. + +2006-09-27 16:52:59 +0000 Jan Schmidt + + gst/gst.c: Make init_pre and init_post take the full complement of GOptionFunc args so they can return useful GErrors... + Original commit message from CVS: + * gst/gst.c: (init_pre), (scan_and_update_registry), + (ensure_current_registry_nonforking), + (ensure_current_registry_forking), (ensure_current_registry), + (init_post), (gst_debug_help), (gst_deinit): + Make init_pre and init_post take the full complement of GOptionFunc + args so they can return useful GErrors. Make the registry updating + functions do so. + Call _priv_gst_registry_remove_cache_plugins after scanning files to + ensure that the registry we're about to write out doesn't contain + stale information about old-deleted plugin files. + Make _priv_gst_registry_remove_cache_plugins return a boolean so + that deletion of plugin files is considered a registry change. + * gst/gst_private.h: + * gst/gstregistry.c: (gst_registry_finalize), + (gst_registry_remove_features_for_plugin_unlocked), + (gst_registry_remove_plugin), (gst_registry_scan_path_level), + (gst_registry_scan_path), + (_priv_gst_registry_remove_cache_plugins), + (_priv_gst_registry_cleanup): + * gst/gstregistry.h: + Rename _gst_registry_remove_cache_plugins and _gst_registry_cleanup + by adding _priv prefix, so that they won't appear in the global + symbol table. They still do atm though because of #318031. Move the + prototypes to gst_private.h + When removing a plugin, remove all features for that plugin too. + Fixes #340878. + +2006-09-27 13:19:55 +0000 Wim Taymans + + docs/random/moving-plugins: Make it clear that the "compiled-in descriptions" really mean the element details. + Original commit message from CVS: + * docs/random/moving-plugins: + Make it clear that the "compiled-in descriptions" really mean + the element details. + * libs/gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_wait_preroll): + Update docs. + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesrc.c: (gst_base_src_wait_playing), + (gst_base_src_get_range), (gst_base_src_activate_push): + * libs/gst/base/gstbasesrc.h: + Added function to block while waiting for PLAYING, this function + is used by live sources that block on the clock. + API: gst_base_src_wait_playing() + +2006-09-27 10:13:13 +0000 Peter Kjellerstedt + + Makefile.am: gst-element-check.m4 is generated and should therefore be copied from the build dir rather than the sour... + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * Makefile.am: + gst-element-check.m4 is generated and should therefore be + copied from the build dir rather than the source dir (#357593). + 'make distcheck' hasn't noticed this because we were disting + the file as well, so stop doing that. + +2006-09-27 09:23:18 +0000 Tim-Philipp Müller + + tests/check/gst/gstcaps.c: Add some tests for gst_caps_intersect(). + Original commit message from CVS: + * tests/check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite): + Add some tests for gst_caps_intersect(). + * tools/gst-launch.c: (event_loop): + Print all buffering percentages we get, even the 100% one. + +2006-09-26 12:39:26 +0000 Wim Taymans + + tools/gst-inspect.c: Fix printing of flags to match the look of enums. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info), + (print_signal_info): + Fix printing of flags to match the look of enums. + +2006-09-25 13:08:29 +0000 Tim-Philipp Müller + + gst/gstelementfactory.c: Fix typo in docs blurb. + Original commit message from CVS: + * gst/gstelementfactory.c: + Fix typo in docs blurb. + +2006-09-25 11:16:37 +0000 Tim-Philipp Müller + + gst/gsturi.c: Don't assert/crash here if a uri handler doesn't return any supported protocols. The list of protocols ... + Original commit message from CVS: + * gst/gsturi.c: (search_by_entry): + Don't assert/crash here if a uri handler doesn't return any + supported protocols. The list of protocols could be generated + dynamically at runtime or at plugin registration, and an error + in the underlying library shouldn't be fatal (#353301). + +2006-09-25 10:36:23 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Fix warning if HAVE_PRINTF_EXTENSION is undefined (spotted by Peter Kjellerstedt). + Original commit message from CVS: + * gst/gstinfo.c: + Fix warning if HAVE_PRINTF_EXTENSION is undefined + (spotted by Peter Kjellerstedt). + +2006-09-23 09:30:40 +0000 Antoine Tremblay + + libs/gst/base/gstbasesrc.c: Match _start/_stop calls in the activate functions. Remove redundant _stop call from the ... + Original commit message from CVS: + Based on patch by: Antoine Tremblay + * libs/gst/base/gstbasesrc.c: + (gst_base_src_default_check_get_range), (gst_base_src_start), + (gst_base_src_activate_push), (gst_base_src_activate_pull), + (gst_base_src_change_state): + Match _start/_stop calls in the activate functions. Remove redundant + _stop call from the state change function. Fixes #356910. + Turn failure DEBUG into ERROR. + +2006-09-22 15:29:23 +0000 Wim Taymans + + Update docs about buffering. + Original commit message from CVS: + * docs/design/part-buffering.txt: + * gst/gstmessage.c: (gst_message_new_buffering), + (gst_message_parse_buffering): + Update docs about buffering. + * docs/design/part-trickmodes.txt: + Fix typo. + +2006-09-22 14:30:49 +0000 Thomas Vander Stichele + + * docs/manual/basics-elements.xml: + audiotestsrc is not part of core, fakesrc is + Original commit message from CVS: + audiotestsrc is not part of core, fakesrc is + +2006-09-22 13:32:43 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: Ref instances when returning them again (fixes #357180) + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist), + (gst_controller_new_list): + Ref instances when returning them again (fixes #357180) + +2006-09-22 10:17:15 +0000 Tim-Philipp Müller + + gst/gstghostpad.c: Don't forget to release proxy lock when there's an error. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_ghost_pad_set_target): + Don't forget to release proxy lock when there's an error. + +2006-09-20 16:17:26 +0000 Jan Schmidt + + gst/gstcaps.h: Add extra initialisers for Caps things, to fix some plugin warnings when using -Wextra + Original commit message from CVS: + * gst/gstcaps.h: + Add extra initialisers for Caps things, to fix some plugin warnings + when using -Wextra + +2006-09-18 13:56:26 +0000 Wim Taymans + + gst/gstghostpad.c: Also set template on the internal pad so that a getcaps from the target pad returns the template c... + Original commit message from CVS: + * gst/gstghostpad.c: (gst_ghost_pad_new_full): + Also set template on the internal pad so that a getcaps from the target + pad returns the template caps. + +2006-09-18 13:44:12 +0000 Wim Taymans + + gst/gstelement.c: Use _DEBUG_OBJECT some more. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_post_message), + (gst_element_dispose): + Use _DEBUG_OBJECT some more. + * libs/gst/base/gstbasesrc.c: (gst_base_src_loop): + Avoid typechecks. + * tools/gst-launch.c: (main): + If the toplevel element is not a GstPipeline, it must be put in a + pipeline so that a bus and clock is selected. + +2006-09-17 19:31:27 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.c: JITTER, RATE, and LATENCY query should be handled by the default case and not by the CONV... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_default_query): + JITTER, RATE, and LATENCY query should be handled by the + default case and not by the CONVERT query code. + +2006-09-17 19:26:16 +0000 Tim-Philipp Müller + + gst/gstformat.c: Fix locking order (must take lock before using n_values). + Original commit message from CVS: + * gst/gstformat.c: (gst_format_register): + Fix locking order (must take lock before using n_values). + * gst/gstvalue.c: (gst_value_serialize_enum), + (gst_value_deserialize_enum_iter_cmp), + (gst_value_deserialize_enum): + Fix serialisation/deserialisation of custom registered GstFormats. + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Unit test for custom format serialisation/deserialisation. + +2006-09-16 21:38:09 +0000 Stefan Kost + + More G_OBJECT macro fixing. Also Fix some details on the plugin-stamp section. + Original commit message from CVS: + * docs/pwg/building-boiler.xml: + * plugins/elements/gstcapsfilter.c: + More G_OBJECT macro fixing. Also Fix some details on the plugin-stamp + section. + +2006-09-16 12:49:02 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Check if requested caps are the same as the sinks caps IF + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Check if requested caps are the same as the sinks caps IF + ->have_same_caps is TRUE. If they are not, act as if have_same_caps + is FALSE. + This fixes the renegotiation issues stated in #352827. + +2006-09-16 10:49:47 +0000 Thomas Vander Stichele + + Extract the manual examples again like we used to do. + Original commit message from CVS: + * configure.ac: + * docs/manual/advanced-autoplugging.xml: + * tests/examples/Makefile.am: + * tests/examples/manual/.cvsignore: + * tests/examples/manual/Makefile.am: + * tests/examples/manual/extract.pl: + Extract the manual examples again like we used to do. + Fix one of them. + +2006-09-16 10:47:36 +0000 Thomas Vander Stichele + + win32/common/config.h: update for version + Original commit message from CVS: + * win32/common/config.h: + update for version + +2006-09-15 21:30:00 +0000 Stefan Kost + + gst/gsterror.c: Documents how to receive errors. + Original commit message from CVS: + * gst/gsterror.c: + Documents how to receive errors. + +2006-09-15 10:43:16 +0000 Wim Taymans + + tools/gst-launch.c: Added some comments here and there. + Original commit message from CVS: + * tools/gst-launch.c: (sigint_handler_sighandler), (check_intr), + (event_loop), (main): + Added some comments here and there. + Post an application message when an interrupt is caught instead of doing + an uncontrolled state change. + Clean up the event loop. + Handle buffering messages, pause/resume the pipeline. + Make shutdown because of an interrupt more reliable. + +2006-09-15 09:49:14 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Make sure that our internal state is correct when we commit our state asynchronously. Th... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_wait_preroll), (gst_base_sink_do_sync), + (gst_base_sink_preroll_object): + Make sure that our internal state is correct when we commit our state + asynchronously. This solves a race where a state change to PLAYING + could cause the sink to remain blocked in preroll in some situations. + +2006-09-15 08:50:21 +0000 Wim Taymans + + tools/gst-inspect.c: List flags as hex so it's easier to deal with. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info), + (print_signal_info): + List flags as hex so it's easier to deal with. + +2006-09-15 08:47:36 +0000 Wim Taymans + + Expose logic to wait for preroll so that subclasses such as audiosink can also use this method. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasesink.c: (gst_base_sink_wait_preroll), + (gst_base_sink_do_sync): + * libs/gst/base/gstbasesink.h: + Expose logic to wait for preroll so that subclasses such as audiosink + can also use this method. + API: gst_base_sink_wait_preroll() + +2006-09-15 08:43:44 +0000 Wim Taymans + + gst/: Small cleanups in docs and code. + Original commit message from CVS: + * gst/gstobject.c: (gst_object_set_parent): + * gst/gstpipeline.c: (do_pipeline_seek): + Small cleanups in docs and code. + * gst/gstsegment.c: (gst_segment_clip): + * tests/check/gst/gstsegment.c: (GST_START_TEST): + if stop == start and start is in the segment, no clipping should be + done. Also add a test for this. + +2006-09-15 08:39:56 +0000 Wim Taymans + + Added methods to create and parse BUFFERING messages. + Original commit message from CVS: + * docs/design/part-buffering.txt: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: (gst_message_new_buffering), + (gst_message_parse_buffering): + * gst/gstmessage.h: + Added methods to create and parse BUFFERING messages. + Added preliminary docs about buffering. + API: gst_message_new_buffering + API: gst_message_parse_buffering + +2006-09-15 08:32:57 +0000 Wim Taymans + + gst/gstbin.c: Update documentation. + Original commit message from CVS: + * gst/gstbin.c: + Update documentation. + * gst/gstelement.c: (gst_element_class_init), + (gst_element_release_request_pad), (gst_element_set_clock), + (gst_element_get_index), (gst_element_add_pad), + (gst_element_remove_pad), (gst_element_get_random_pad), + (gst_element_send_event), (gst_element_get_query_types), + (gst_element_query), (gst_element_post_message), + (gst_element_message_full), (gst_element_continue_state), + (gst_element_lost_state), (gst_element_save_thyself), + (gst_element_restore_thyself): + Documentation updates. + Rename last bit of the new-pad -> pad-added signal rename. + Fix the case where an element query would only work if the source + pad was linked. + Avoid some useless type checking in message handling. + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstutils.c: + Documentation updates. + +2006-09-14 20:12:04 +0000 Thomas Vander Stichele + + * ChangeLog: + * plugins/elements/gstfdsrc.c: + add an INFO line for when we actually update the fd + Original commit message from CVS: + add an INFO line for when we actually update the fd + +2006-09-14 20:11:10 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to trunk + Original commit message from CVS: + back to trunk + +=== release 0.10.10 === + +2006-09-14 20:08:14 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * gst/gst.c: + * gst/gstcaps.c: + * gst/gstclock.h: + * gst/gststructure.c: + * win32/common/config.h: + releasing 0.10.10 + Original commit message from CVS: + releasing 0.10.10 + +2006-09-09 16:08:17 +0000 Thomas Vander Stichele + + * configure.ac: + * win32/common/config.h: + first prerelease + Original commit message from CVS: + first prerelease + +2006-09-09 16:07:34 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + translation updates + Original commit message from CVS: + translation updates + +2006-09-05 14:11:06 +0000 Tim-Philipp Müller + + docs/manual/advanced-position.xml: Fix typo in sample code. + Original commit message from CVS: + * docs/manual/advanced-position.xml: + Fix typo in sample code. + +2006-09-05 08:35:20 +0000 Wim Taymans + + libs/gst/net/: Make stuff compile on windows. Fixes #345295. + Original commit message from CVS: + * libs/gst/net/gstnetclientclock.c: (inet_aton), + (gst_net_client_clock_init), (gst_net_client_clock_finalize), + (gst_net_client_clock_do_select), (gst_net_client_clock_new): + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.c: (gst_net_time_packet_send): + * libs/gst/net/gstnettimepacket.h: + * libs/gst/net/gstnettimeprovider.c: (inet_aton), + (gst_net_time_provider_init), (gst_net_time_provider_finalize), + (gst_net_time_provider_thread), (gst_net_time_provider_new): + * libs/gst/net/gstnettimeprovider.h: + Make stuff compile on windows. Fixes #345295. + +2006-09-03 11:16:50 +0000 Tim-Philipp Müller + + gst/gst.c: Print better details when child was terminated by signal. + Original commit message from CVS: + * gst/gst.c: (ensure_current_registry_forking): + Print better details when child was terminated by signal. + +2006-09-03 11:06:52 +0000 Tim-Philipp Müller + + gst/gstregistryxml.c: Print a warning rather than g_assert() if a plugin feature is a URI handler but returns no prot... + Original commit message from CVS: + * gst/gstregistryxml.c: (gst_registry_xml_save_feature): + Print a warning rather than g_assert() if a plugin feature + is a URI handler but returns no protocols (#353976). + +2006-09-02 19:10:56 +0000 Stefan Kost + + docs/random/moving-plugins: Fix two typos. + Original commit message from CVS: + * docs/random/moving-plugins: + Fix two typos. + +2006-09-02 19:03:41 +0000 Thomas Vander Stichele + + * docs/random/moving-plugins: + document process some more + Original commit message from CVS: + document process some more + +2006-09-02 13:40:41 +0000 Thomas Vander Stichele + + * gst/gsterror.c: + clarify error message + Original commit message from CVS: + clarify error message + +2006-09-02 13:36:44 +0000 Thomas Vander Stichele + + * docs/random/moving-plugins: + document process some more + Original commit message from CVS: + document process some more + +2006-09-01 16:03:49 +0000 Tim-Philipp Müller + + * ChangeLog: + ChangeLog surgery: fix typo + Original commit message from CVS: + ChangeLog surgery: fix typo + +2006-09-01 15:55:20 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Fix locking order, handle NULL function values properly. + Original commit message from CVS: + * gst/gstinfo.c: (_gst_debug_nameof_funcptr): + Fix locking order, handle NULL function values properly. + * gst/gstinfo.h: + Fix docs. + * gst/gstpad.c: (gst_pad_buffer_alloc_unchecked): + Initialised variable before using it and fix debug statement to + print the address of the function rather than the address of the + variable on the stack holding the address of the function. + +2006-09-01 10:33:03 +0000 Wim Taymans + + gst/gstghostpad.c: More cleanups. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_do_event), + (gst_proxy_pad_do_bufferalloc), (gst_proxy_pad_do_chain), + (gst_proxy_pad_do_getrange), (gst_proxy_pad_do_checkgetrange), + (gst_proxy_pad_set_target_unlocked), (gst_ghost_pad_parent_set), + (gst_ghost_pad_parent_unset), + (gst_ghost_pad_internal_do_activate_push), + (gst_ghost_pad_internal_do_activate_pull), + (gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull), + (gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink), + (gst_ghost_pad_init), (gst_ghost_pad_dispose), + (gst_ghost_pad_new_full), (gst_ghost_pad_new_no_target), + (gst_ghost_pad_new), (gst_ghost_pad_new_from_template), + (gst_ghost_pad_new_no_target_from_template), + (gst_ghost_pad_get_target), (gst_ghost_pad_set_target): + More cleanups. + Avoid needless typechecking in macros. + Since the internal pad is always present and never changes, there is + no need to locking or ref when retrieving it. + Improve debugging a bit. + Handle link errors when setting the target. Fixes #341029. + +2006-09-01 10:26:52 +0000 Wim Taymans + + docs/: Fix docs some more. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * docs/plugins/gstreamer-plugins-sections.txt: + Fix docs some more. + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_remove_pad), + (gst_collect_pads_event): + * libs/gst/base/gstcollectpads.h: + Documentation updates. + Free queued buffer when removing a pad. + +2006-08-31 17:13:34 +0000 Michael Smith + + gst/gstutils.c: Ensure that we set a capsfilter to NULL if we failed to link it when doing filtered linking, to avoid... + Original commit message from CVS: + * gst/gstutils.c: (gst_element_link_pads), + (gst_element_link_pads_filtered): + Ensure that we set a capsfilter to NULL if we failed to link it + when doing filtered linking, to avoid criticals. + No need to check for unreffing srcpad, which is explicly NULLed + above (a trivial code cleanup). + +2006-08-31 15:19:44 +0000 Wim Taymans + + docs/design/part-gstghostpad.txt: Update ascii art in documentation. + Original commit message from CVS: + * docs/design/part-gstghostpad.txt: + Update ascii art in documentation. + * gst/gstghostpad.c: (gst_proxy_pad_do_internal_link), + (gst_proxy_pad_set_target_unlocked), (gst_proxy_pad_init), + (gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset), + (gst_ghost_pad_internal_do_activate_push), + (gst_ghost_pad_internal_do_activate_pull), + (gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull), + (gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink), + (gst_ghost_pad_dispose), (gst_ghost_pad_new_full), + (gst_ghost_pad_set_target): + Small cleanups and leak fixes. + Remove some checks now that the internal pad is never NULL. + Fix the case where linking pads without a target would create nasty + criticals. Fixes #341029. + Don't assign a GstPadLinkReturn to a gboolean and mess up the return + value of _set_target(). + * tests/check/gst/gstghostpad.c: (GST_START_TEST), + (gst_ghost_pad_suite): + Some more tests for creating and linking untargeted ghostpads. + +2006-08-31 10:59:11 +0000 Edward Hervey + + Refactored *_new() functions. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstghostpad.c: (gst_proxy_pad_do_getcaps), + (gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked), + (gst_proxy_pad_dispose), (gst_ghost_pad_new_full), + (gst_ghost_pad_new_no_target), (gst_ghost_pad_new), + (gst_ghost_pad_new_from_template), + (gst_ghost_pad_new_no_target_from_template): + * gst/gstghostpad.h: + Refactored *_new() functions. + Templates are now used as a g_object_new() parameter. + Use template in _do_getcaps() if we don't have a target. + Small documentation cleanups. + Added two new constructors: + gst_ghost_pad_new_from_template() + gst_ghost_pad_new_no_target_from_template() + * tests/check/gst/gstghostpad.c: (GST_START_TEST), + (gst_ghost_pad_suite): + Added tests for new ghostpad instanciation functions. + API additions: gst_ghost_pad_new_from_template, + gst_ghost_pad_new_no_target_from_template + +2006-08-30 12:28:55 +0000 Stefan Kost + + docs/random/ensonic/profiling.txt: Ideas about qos profiling. + Original commit message from CVS: + * docs/random/ensonic/profiling.txt: + Ideas about qos profiling. + +2006-08-29 14:39:42 +0000 Wim Taymans + + gst/gstcaps.c: Code cleanups. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_structure_is_subset_field): + Code cleanups. + Fix memleak. + +2006-08-29 10:49:03 +0000 Tim-Philipp Müller + + gst/gstxml.c: Improve and detypofy docs. + Original commit message from CVS: + * gst/gstxml.c: + Improve and detypofy docs. + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gstxml.c: (GST_START_TEST), (gst_xml_suite): + Add a basic test suite for GstXML. + +2006-08-29 09:56:57 +0000 Wim Taymans + + gst/gstelement.c: Clear the pad caps when the element shut down all of the pads and is not streaming data that could ... + Original commit message from CVS: + * gst/gstelement.c: (activate_pads), (clear_caps), + (iterator_activate_fold_with_resync), (gst_element_pads_activate): + Clear the pad caps when the element shut down all of the pads and + is not streaming data that could modify the caps. + Fixes #352958. + +2006-08-29 08:02:41 +0000 Thomas Vander Stichele + + * win32/common/config.h: + I don't even know which arch that is + Original commit message from CVS: + I don't even know which arch that is + +2006-08-28 23:16:33 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + more logical to log the sending pad, and the pad it is sending to + Original commit message from CVS: + more logical to log the sending pad, and the pad it is sending to + +2006-08-28 18:20:00 +0000 Michael Smith + + plugins/elements/gstidentity.c: Revert previous change; I misunderstood single-segment mode. + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + Revert previous change; I misunderstood single-segment mode. + +2006-08-28 18:08:09 +0000 Michael Smith + + plugins/elements/gstidentity.c: Unset DISCONT on buffers when using single-segment mode. + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + Unset DISCONT on buffers when using single-segment mode. + +2006-08-28 16:39:20 +0000 Wim Taymans + + gst/gstcaps.*: Fix docs and indentation again. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_merge_structure): + * gst/gstcaps.h: + Fix docs and indentation again. + * tests/check/gst/gstquery.c: (GST_START_TEST): + Fix leak in tests and add some more tests. + +2006-08-28 15:57:39 +0000 Edward Hervey + + libs/gst/base/gstbasesink.c: Inform GstSegment of the last stop position in order for the current segment to have a p... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Inform GstSegment of the last stop position in order for the current + segment to have a proper duration if it doesn't have a specific stop + position from which a duration could be calculated. + This bug was noticeable when a non-flushing, non-update new segment was + followed by another segment (all buffers from the new segment were being + dropped). + +2006-08-28 15:48:24 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Small comment update. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek): + Small comment update. + * plugins/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_transform_ip): + Drop-probability is broken, mention this in the code with a + FIXME and also in the property description. + Make silent also be silent about the drop messages. + +2006-08-28 11:06:05 +0000 Tim-Philipp Müller + + docs/manual/appendix-win32.xml: Remove mention of popt, we don't depend on that any longer (#353136). Add some commen... + Original commit message from CVS: + * docs/manual/appendix-win32.xml: + Remove mention of popt, we don't depend on that any + longer (#353136). Add some comments pointing out that + this section is slightly outdated. + +2006-08-28 08:44:29 +0000 Torsten Schoenfeld + + Initialize variables when creating a new segment query. + Original commit message from CVS: + Patch by: Torsten Schoenfeld + * gst/gstquery.c: (gst_query_new_segment): + * tests/check/gst/gstquery.c: (GST_START_TEST): + Initialize variables when creating a new segment query. + Fixes #353121. + +2006-08-28 08:35:31 +0000 Torsten Schoenfeld + + Check for NULL before _reffing the bus. Fixes #353122. + Original commit message from CVS: + Patch by: Torsten Schoenfeld + * gst/gstelement.c: (gst_element_get_bus): + * tests/check/gst/gstelement.c: (GST_START_TEST): + Check for NULL before _reffing the bus. Fixes #353122. + +2006-08-25 16:46:09 +0000 Tim-Philipp Müller + + docs/manual/basics-bus.xml: Docs update: fix wrong callback return value explanation; add some lines about the implic... + Original commit message from CVS: + * docs/manual/basics-bus.xml: + Docs update: fix wrong callback return value explanation; add + some lines about the implicit relationship between main loop + and main context; remove duplicate main loop variable declaration. + +2006-08-24 12:30:04 +0000 Tim-Philipp Müller + + tests/check/gst/gstcaps.c: Don't leak caps in unit test; add a few more simple checks. + Original commit message from CVS: + * tests/check/gst/gstcaps.c: (GST_START_TEST): + Don't leak caps in unit test; add a few more simple + checks. + +2006-08-24 10:40:31 +0000 Stefan Kost + + implement caps merging (fixes #352580) + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: (gst_caps_structure_is_subset_field), + (gst_caps_structure_is_subset), (gst_caps_merge), + (gst_caps_merge_structure): + * gst/gstcaps.h: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps): + * tests/check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite): + implement caps merging (fixes #352580) + +2006-08-23 18:53:44 +0000 Stefan Kost + + tools/: add debug-log plotting developer tool (#340674) + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-plot-timeline.py: + add debug-log plotting developer tool (#340674) + +2006-08-23 16:51:19 +0000 Wim Taymans + + gst/gstpad.c: Improve debugging for task functions. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_start_task), (gst_pad_pause_task), + (gst_pad_stop_task): + Improve debugging for task functions. + * gst/gsttask.c: (gst_task_func), (gst_task_set_lock), + (gst_task_start), (gst_task_pause), (gst_task_join): + Make sure that the task function started and finished after a + join(). + Don't try to push the task function on the threadpool multiple + times. + Improve the g_warning message with some useful suggestions + about how to fix the problem. + +2006-08-23 10:59:47 +0000 Wim Taymans + + gst/gstutils.c: Handle RESYNC correctly in _proxy_getcaps. + Original commit message from CVS: + * gst/gstutils.c: (gst_pad_proxy_getcaps): + Handle RESYNC correctly in _proxy_getcaps. + +2006-08-23 09:47:32 +0000 Thomas Vander Stichele + + * gst/gstbuffer.h: + word refcounting more precisely for gst_value_*_buffer + Original commit message from CVS: + word refcounting more precisely for gst_value_*_buffer + +2006-08-21 15:19:40 +0000 Tim-Philipp Müller + + gst/gstxml.c: Chain up to parent class in dispose function and also unref the elements in the toplevel_elements GList. + Original commit message from CVS: + * gst/gstxml.c: (gst_xml_dispose), (gst_xml_parse_file), + (gst_xml_parse_memory), (gst_xml_get_element): + Chain up to parent class in dispose function and also + unref the elements in the toplevel_elements GList. + Don't leak XmlDocPtr in _parse_file() and _parse_memory(). + Always return a reference in gst_xml_get_element() rather + than only sometimes. + * tools/gst-launch.c: (xmllaunch_parse_cmdline): + Don't leak GstXml object. + +2006-08-21 14:54:31 +0000 Stefan Kost + + API: Add gst_caps_merge() and use it in basetransform, fixes #345444 in a better way + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.c: (gst_structure_is_equal_foreach), + (gst_caps_merge): + * gst/gstcaps.h: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps): + API: Add gst_caps_merge() and use it in basetransform, fixes #345444 + in a better way + +2006-08-21 14:03:33 +0000 Edward Hervey + + gst/gstxml.c: Implement GObject::dispose virtual method in GstXML so we can free the top_elements GList. + Original commit message from CVS: + * gst/gstxml.c: (gst_xml_class_init), (gst_xml_dispose): + Implement GObject::dispose virtual method in GstXML so we can free the + top_elements GList. + +2006-08-21 09:30:04 +0000 Wim Taymans + + gst/gstbuffer.c: Copy duration/offset_end/caps when creating a subbuffer of the complete parent. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_make_metadata_writable), + (gst_buffer_create_sub): + Copy duration/offset_end/caps when creating a subbuffer of the + complete parent. + Make the subbuffer read-only when we make the metadata writable for + now. Fixes #351768. + * tests/check/gst/gstbuffer.c: (GST_START_TEST): + Added check for metadata copy when creating subbuffers. + +2006-08-21 09:20:42 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Only call downstream buffer_alloc if transform element is passthrough or always_in_... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Only call downstream buffer_alloc if transform element is passthrough + or always_in_place. Closes #350449. + +2006-08-20 19:36:21 +0000 Stefan Kost + + ChangeLog: ChangeLog surgery to add comments to previous changes + Original commit message from CVS: + * ChangeLog: + ChangeLog surgery to add comments to previous changes + +2006-08-20 19:30:09 +0000 Stefan Kost + + Simplify caps to get rid of duplicates, fixes #345444 + Original commit message from CVS: + * gst/gst.c: + * gst/gstpad.c: (gst_pad_set_active): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps): + Simplify caps to get rid of duplicates, fixes #345444 + +2006-08-20 15:55:12 +0000 Stefan Kost + + gst/gstvalue.*: Use these optimizations only internaly. + Original commit message from CVS: + * gst/gstvalue.c: + * gst/gstvalue.h: + Use these optimizations only internaly. + +2006-08-20 14:30:20 +0000 Stefan Kost + + gst/gstvalue.*: Saves the expensive lookup of the compare function in many cases (#345444) + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_compare_list), + (gst_value_compare_fraction_range), + (gst_value_intersect_fraction_fraction_range), + (gst_value_intersect_fraction_range_fraction_range), + (gst_value_subtract_fraction_fraction_range), + (gst_value_subtract_fraction_range_fraction_range), + (gst_value_get_compare_func), (gst_value_compare), + (gst_value_compare_with_func): + * gst/gstvalue.h: + Saves the expensive lookup of the compare function in many cases + (#345444) + +2006-08-18 13:41:02 +0000 Edward Hervey + + tests/check/gst/gstinfo.c: Disable test that require gstdebug if it wasn't built in core. + Original commit message from CVS: + * tests/check/gst/gstinfo.c: (gst_info_suite): + Disable test that require gstdebug if it wasn't built in core. + +2006-08-18 10:52:33 +0000 Stefan Kost + + docs/random/ensonic/logging.txt: update ideas + Original commit message from CVS: + * docs/random/ensonic/logging.txt: + update ideas + * gst/gstinfo.c: (gst_debug_log_default): + reorder fields, save some columns, add optinal color codes for log- + levels + +2006-08-18 08:07:12 +0000 Stefan Kost + + docs/random/ensonic/logging.txt: add ideas about making the logs abit more useful + Original commit message from CVS: + * docs/random/ensonic/logging.txt: + add ideas about making the logs abit more useful + +2006-08-17 18:11:11 +0000 Tim-Philipp Müller + + docs/pwg/: Update for 0.10 API (#340627). Add myself to authors list. + Original commit message from CVS: + * docs/pwg/advanced-events.xml: + * docs/pwg/titlepage.xml: + Update for 0.10 API (#340627). Add myself + to authors list. + +2006-08-17 10:46:19 +0000 Tim-Philipp Müller + + Make gstcheck stuff show up in docs (still needs to be documented properly though). + Original commit message from CVS: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/check/gstbufferstraw.c: + Make gstcheck stuff show up in docs (still needs to + be documented properly though). + +2006-08-16 11:47:54 +0000 Jan Schmidt + + Add internal helpers for pre-registering quarks from static strings and using the quark values directly instead of lo... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.c: (init_post): + * gst/gst_private.h: + * gst/gstquark.c: (_priv_gst_quarks_initialize): + * gst/gstquark.h: + * gst/gstquery.c: (gst_query_new_position), + (gst_query_set_position), (gst_query_parse_position), + (gst_query_new_duration), (gst_query_set_duration), + (gst_query_parse_duration), (gst_query_new_convert), + (gst_query_set_convert), (gst_query_parse_convert), + (gst_query_new_segment), (gst_query_set_segment), + (gst_query_parse_segment), (gst_query_new_seeking), + (gst_query_set_seeking), (gst_query_parse_seeking): + Add internal helpers for pre-registering quarks from static strings + and using the quark values directly instead of looking them up when + creating and parsing queries. Can be used for event construction too. + Closes #350432. + +2006-08-16 08:54:56 +0000 Wim Taymans + + gst/gstbin.c: Fix bogus docs. + Original commit message from CVS: + * gst/gstbin.c: + Fix bogus docs. + +2006-08-15 18:45:39 +0000 Tim-Philipp Müller + + gst/gstutils.c: Fix memleak (#351502). + Original commit message from CVS: + * gst/gstutils.c: (gst_util_set_value_from_string): + Fix memleak (#351502). + * tests/check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + Add unit test for most of gst_util_set_value_from_string() + (not that one would want to encourage use of this function). + +2006-08-15 18:29:22 +0000 Tim-Philipp Müller + + libs/gst/check/gstcheck.h: Use const gchar * variables in fail_unless_equals_string macro to avoid compiler warnings ... + Original commit message from CVS: + * libs/gst/check/gstcheck.h: + Use const gchar * variables in fail_unless_equals_string + macro to avoid compiler warnings (and don't use tabs for + indenting). + +2006-08-15 10:08:34 +0000 Tim-Philipp Müller + + tools/gst-launch.c: More space on the left for the tag names, to cater for the 'extended comment' tag (not touching t... + Original commit message from CVS: + * tools/gst-launch.c: (print_tag): + More space on the left for the tag names, to cater + for the 'extended comment' tag (not touching the + string for the first line since it's translated). + +2006-08-15 09:44:58 +0000 Tim-Philipp Müller + + * ChangeLog: + ChangeLog surgery: don't forget to mention the other change in the ChangeLog + Original commit message from CVS: + ChangeLog surgery: don't forget to mention the other change in the ChangeLog + +2006-08-15 09:33:24 +0000 Tim-Philipp Müller + + libs/gst/check/gstcheck.h: Fix ASSERT_CRITICAL and ASSERT_WARNING macros to actually print something when they fail. + Original commit message from CVS: + * libs/gst/check/gstcheck.h: + Fix ASSERT_CRITICAL and ASSERT_WARNING macros to actually + print something when they fail. + +2006-08-14 19:04:56 +0000 Tim-Philipp Müller + + API: add GST_TAG_EXTENDED_COMMENT (#350935). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + API: add GST_TAG_EXTENDED_COMMENT (#350935). + +2006-08-14 17:29:31 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Make GST_PTR_FORMAT print messages as well. + Original commit message from CVS: + * gst/gstinfo.c: (gst_debug_print_object): + Make GST_PTR_FORMAT print messages as well. + * tests/check/gst/gstinfo.c: (printf_extension_log_func), + (GST_START_TEST), (gst_info_suite): + More tests. + +2006-08-14 15:33:17 +0000 Edward Hervey + + gst/gstelementfactory.c: If the GstElementClass doesn't have a GstElementDetails with all fields then error out nicel... + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_register): + If the GstElementClass doesn't have a GstElementDetails with all fields + filled up correctly (longname, description AND author), then error out + nicely instead of crashing. + +2006-08-14 12:35:06 +0000 Tim-Philipp Müller + + gst/gststructure.c: Fix typo in docs and re-wrap docs blurb to not exceed 80 chars/line. + Original commit message from CVS: + * gst/gststructure.c: + Fix typo in docs and re-wrap docs blurb to not exceed 80 chars/line. + * gst/gstvalue.h: + Expand on the difference between arrays and lists as we use them. + +2006-08-14 07:44:14 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: If the parent state change function failed, don't assume we can safely stop the source, t... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_change_state): + If the parent state change function failed, don't assume we can safely + stop the source, this will be done when the pads are deactivated. + +2006-08-14 07:35:09 +0000 Wim Taymans + + gst/: Small doc updates. + Original commit message from CVS: + * gst/gstbuffer.c: + * gst/gsttask.c: (gst_task_join): + Small doc updates. + * gst/gstpad.c: (gst_pad_activate_pull), (gst_pad_activate_push), + (gst_pad_stop_task): + When pad (de)activation failed for some reason, restore the old + activation mode and set the pad to flushing instead of assuming the + pad is deactivated. + If the _task_join() failed, reinstall the task on the pad so that it can + be stopped later and return an error. + +2006-08-11 15:26:33 +0000 Andy Wingo + + GST_DISABLE_DEPRECATED is only for users of API that don't want to see deprecated functions in the headers; people th... + Original commit message from CVS: + 2006-08-11 Andy Wingo + * configure.ac: + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packetizer_new): + * tests/check/libs/gdp.c: (gst_dp_suite): GST_DISABLE_DEPRECATED + is only for users of API that don't want to see deprecated + functions in the headers; people that want to compile out + deprecated code should pass -DGST_REMOVE_DEPRECATED into the + CFLAGS. Fixes the build of multifdsink, or will soon.. + +2006-08-11 15:24:03 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Add GstClockClass vmethod docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add GstClockClass vmethod docs. + * gst/gstcaps.h: + Mark #endif with comment for associated #if + * gst/gstclock.c: (gst_clock_id_wait): + * gst/gstclock.h: + Add vmethod wait_jitter to avoid an unneeded _get_time() for + most clock implementations. + Document vmethods. + Flesh out docs about resolution methods. + API: GstClockClass::wait_jitter + * gst/gstsystemclock.c: (gst_system_clock_class_init), + (gst_system_clock_async_thread), + (gst_system_clock_id_wait_jitter_unlocked), + (gst_system_clock_id_wait_jitter): + Use base class wait_jitter variant for improved performance + due to less clock polling. + +2006-08-11 15:07:58 +0000 Edward Hervey + + gst/gst.c: Set gst as being initialized before scanning/updating the registry, since there might be some plugins that... + Original commit message from CVS: + * gst/gst.c: (gst_init_check), (init_post): + Set gst as being initialized before scanning/updating the registry, + since there might be some plugins that call gst_init() and we don't + want to loop back in. + Closes #350879 + +2006-08-11 13:13:06 +0000 Wim Taymans + + * ChangeLog: + Mention that we fixed bug #349943 with the last commit. + Original commit message from CVS: + Mention that we fixed bug #349943 with the last commit. + +2006-08-11 13:05:30 +0000 Wim Taymans + + docs/design/part-qos.txt: Bring docs in line with the code. Mostly the sign of the jitter was wrong in the docs. + Original commit message from CVS: + * docs/design/part-qos.txt: + Bring docs in line with the code. Mostly the sign of the jitter was + wrong in the docs. + * gst/gstclock.c: + Fix the docs for the jitter. + * gst/gstevent.c: (gst_event_new_custom), (gst_event_new_tag), + (gst_event_parse_tag), (gst_event_new_buffer_size), + (gst_event_parse_buffer_size), (gst_event_parse_qos), + (gst_event_new_seek), (gst_event_parse_seek), + (gst_event_new_navigation): + Make sure the GstStructure has no parent when creating custom + events. + Add some more argument checking so that we avoid 0.0 rates. + Flesh out the docs for the QoS event some more. + +2006-08-11 10:21:36 +0000 Wim Taymans + + * ChangeLog: + Forgot to mention fixed bug. + Original commit message from CVS: + Forgot to mention fixed bug. + +2006-08-11 10:19:51 +0000 Wim Taymans + + Doc updates. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: (gst_init_get_option_group), (gst_init_check), + (ensure_current_registry_forking), (ensure_current_registry), + (parse_one_option), (parse_goption_arg), (gst_deinit), + (gst_registry_fork_is_enabled), (gst_registry_fork_set_enabled): + * gst/gst.h: + Doc updates. + Added API and command line option to disable registry forking in + addition to the environment variable. + Constify some static arrays. + Added some more debug. + Don't deinit twice. + API: gst_registry_fork_is_enabled() + API: gst_registry_fork_set_enabled() + API: --gst-disable-registry-fork command line option + +2006-08-11 09:59:29 +0000 Tim-Philipp Müller + + gst/gst.c: Fix typo in error message. + Original commit message from CVS: + * gst/gst.c: (gst_init): + Fix typo in error message. + +2006-08-10 20:05:30 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.h: fix ABI size-correction + Original commit message from CVS: + * libs/gst/controller/gstcontroller.h: + fix ABI size-correction + * tests/check/libs/gdp.c: (gst_dp_suite): + make tests that use deprecated API conditional + +2006-08-10 19:46:14 +0000 Stefan Kost + + API: add gst_object_{s,g}et_control_rate(), add private data section, fix docs + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gstcontroller.c: + (_gst_controller_get_property), (_gst_controller_set_property), + (_gst_controller_init), (_gst_controller_class_init): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: (gst_object_get_control_rate), + (gst_object_set_control_rate): + API: add gst_object_{s,g}et_control_rate(), add private data section, + fix docs + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packetizer_new): + * libs/gst/dataprotocol/dataprotocol.h: + add deprecation guards to make gtk-doc happy and allow disabling cruft + +2006-08-09 15:26:54 +0000 Tim-Philipp Müller + + tests/check/: Let's enable the new unit test as well. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + Let's enable the new unit test as well. + +2006-08-09 15:13:14 +0000 Tim-Philipp Müller + + API: add GST_SEGMENT_FORMAT, which is a printf extension we register that lets us easily dump GstSegments into debug ... + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/gstconfig.h.in: + * gst/gstinfo.c: (_gst_debug_init), (gst_debug_print_segment), + (_gst_info_printf_extension_ptr), + (_gst_info_printf_extension_segment): + API: add GST_SEGMENT_FORMAT, which is a printf extension we + register that lets us easily dump GstSegments into debug + logs (#350419). + * tests/check/gst/gstinfo.c: (segment_printf_extension_log_func), + (info_segment_format_printf_extension), (gst_info_suite): + Add simple unit test that logs a bunch of different segments (not + valgrinded at the moment because of leaks in gst_debug_add_log_function). + +2006-08-09 11:01:20 +0000 Edward Hervey + + libs/gst/base/gstbasetransform.c: Even if we can't figure out the proper format to request downstream, call buffer_al... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Even if we can't figure out the proper format to request downstream, + call buffer_alloc() downstream with the input parameters without setting + the caps on the srcpad. This will force negotiation in the chain + function. + Closes #350449 + +2006-08-08 16:24:58 +0000 Edward Hervey + + gst/gstghostpad.c: Unlinking from a pad without a target is now a perfectly valid case which should NOT raise an asse... + Original commit message from CVS: + * gst/gstghostpad.c: (gst_ghost_pad_do_unlink): + Unlinking from a pad without a target is now a perfectly valid case + which should NOT raise an assertion. + This case would happen if a linked ghostpad its target set to NULL after + it was previously linked. + +2006-08-08 09:56:45 +0000 Edward Hervey + + tests/check/libs/gdp.c: Also comment out the test (see below). + Original commit message from CVS: + * tests/check/libs/gdp.c: + Also comment out the test (see below). + +2006-08-08 09:07:34 +0000 Edward Hervey + + tests/check/libs/gdp.c: Use the architecture information from config.h and not gcc macros in order to properly disabl... + Original commit message from CVS: + * tests/check/libs/gdp.c: (gst_dp_suite): + Use the architecture information from config.h and not gcc macros + in order to properly disable a test that fails on PPC64. + +2006-08-04 15:15:24 +0000 Tim-Philipp Müller + + gst/gstelement.c: Don't crash printing the warning if the pad has no parent. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_remove_pad): + Don't crash printing the warning if the pad has no parent. + +2006-08-02 15:19:30 +0000 Wim Taymans + + libs/gst/dataprotocol/dataprotocol.c: Make debug category static + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer_any), (gst_dp_packet_from_caps_any), + (gst_dp_crc), (gst_dp_header_payload_length), + (gst_dp_header_payload_type), (gst_dp_packet_from_event), + (gst_dp_packet_from_event_1_0), (gst_dp_buffer_from_header), + (gst_dp_caps_from_packet), (gst_dp_event_from_packet_0_2), + (gst_dp_event_from_packet), (gst_dp_validate_header), + (gst_dp_validate_payload): + Make debug category static + Constify the crc table. + Do some more arg checking in public functions. + Fix some docs and do some small cleanups. + * tests/check/libs/gdp.c: (GST_START_TEST), (gst_dp_suite): + Add some more checks to see if GDP deals with bogus input. + +2006-07-31 16:34:41 +0000 Wim Taymans + + gst/gstvalue.c: Fix GstValueList comparison code. Fixes #347293. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_compare_list): + Fix GstValueList comparison code. Fixes #347293. + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Check to test GstValueList comparison. + +2006-07-31 15:12:59 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Use OBJECT_LOCK and refcounting to get the pad caps in the buffer_alloc function be... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Use OBJECT_LOCK and refcounting to get the pad caps in the + buffer_alloc function because the caps could change while we are + busy with them. Fixes #349105 + +2006-07-31 15:12:01 +0000 Wim Taymans + + gst/gstelementfactory.c: Remove unnecessary ref/unref pair + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_create): + Remove unnecessary ref/unref pair + * gst/parse/grammar.y: + Make sure to free the parse buffer on all code paths. + Move a g_free up to the error handler where it's easier to see. + * tests/check/gst/gstevent.c: (test_event): + Extending timeout for downstream travelling events to 10 seconds to + hopefully avoid intermittent failure on the buildbots. + * tests/check/pipelines/parse-launch.c: (run_delayed_test): + Don't manually set the state of the src element - it will happen as a + natural consequence of the pipeline changing state, and that way it + will do it in the right order too. + +2006-07-31 15:07:30 +0000 Jan Schmidt + + gst/gstelementfactory.c: Remove unnecessary ref/unref pair + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_create): + Remove unnecessary ref/unref pair + * gst/parse/grammar.y: + Make sure to free the parse buffer on all code paths. + Move a g_free up to the error handler where it's easier to see. + * tests/check/gst/gstevent.c: (test_event): + Extending timeout for downstream travelling events to 10 seconds to + hopefully avoid intermittent failure on the buildbots. + * tests/check/pipelines/parse-launch.c: (run_delayed_test): + Don't manually set the state of the src element - it will happen as a + natural consequence of the pipeline changing state, and that way it + will do it in the right order too. + +2006-07-31 14:23:26 +0000 Wim Taymans + + gst/gstutils.c: Protect _PAD_CAPS with OBJECT_LOCK. + Original commit message from CVS: + * gst/gstutils.c: (gst_pad_get_fixed_caps_func): + Protect _PAD_CAPS with OBJECT_LOCK. + +2006-07-31 14:21:10 +0000 Wim Taymans + + gst/gstpad.c: Use _DEBUG_OBJECT when it makes sense. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_class_init), (gst_pad_dispose), + (gst_pad_get_property), (gst_pad_activate_pull), + (gst_pad_activate_push), (gst_pad_set_blocked_async), + (gst_pad_set_activate_function), + (gst_pad_set_activatepull_function), + (gst_pad_set_activatepush_function), (gst_pad_set_chain_function), + (gst_pad_set_getrange_function), + (gst_pad_set_checkgetrange_function), (gst_pad_set_event_function), + (gst_pad_set_query_function), (gst_pad_set_query_type_function), + (gst_pad_set_internal_link_function), (gst_pad_set_link_function), + (gst_pad_set_unlink_function), (gst_pad_set_getcaps_function), + (gst_pad_set_acceptcaps_function), + (gst_pad_set_fixatecaps_function), (gst_pad_set_setcaps_function), + (gst_pad_set_bufferalloc_function), (gst_pad_link_check_hierarchy), + (gst_pad_get_caps_unlocked), (gst_pad_get_caps), + (gst_pad_peer_get_caps), (gst_pad_accept_caps), + (gst_pad_peer_accept_caps), (gst_pad_set_caps), + (gst_pad_configure_sink), (gst_pad_configure_src), + (gst_pad_get_allowed_caps), (gst_pad_get_negotiated_caps), + (gst_pad_buffer_alloc_unchecked), (gst_pad_alloc_buffer_full), + (gst_pad_query), (gst_pad_load_and_link), (handle_pad_block), + (gst_pad_chain_unchecked), (gst_pad_push), (gst_pad_get_range), + (gst_pad_send_event): + Use _DEBUG_OBJECT when it makes sense. + Protect GST_PAD_CAPS with the OBJECT_LOCK. + Small cleanups and code reflows. + Avoid caps refcounting in _accept_caps. + Refactor alloc_buffer so that the code performed on the peer is in a + separate function. Also if the pad does not implement a buffer alloc + function, we should still check if the pad is flushing before falling + back to the default allocator. + +2006-07-30 22:20:42 +0000 Jan Schmidt + + tests/check/pipelines/parse-launch.c: Make all uses of identity and fakesink have silent=true to avoid serialising ev... + Original commit message from CVS: + * tests/check/pipelines/parse-launch.c: (GST_START_TEST): + Make all uses of identity and fakesink have silent=true to avoid + serialising every passing data structure, which is breaking tests + on FC4 for some unknown reason. + +2006-07-30 18:58:28 +0000 Stefan Kost + + gst/parse/: Reverted previous patch as it required to bump the flex dependency to 2.5.31, where fc4/5 seem to ship on... + Original commit message from CVS: + * gst/parse/Makefile.am: + * gst/parse/grammar.y: + * gst/parse/parse.l: + Reverted previous patch as it required to bump the flex dependency to + 2.5.31, where fc4/5 seem to ship only the ancient 2.5.4a :( + +2006-07-30 18:32:49 +0000 Marc-Andre Lureau + + gst/parse/: push & pop the state of the lexer for reentrant use case + Original commit message from CVS: + Patch by: Marc-Andre Lureau + * gst/parse/Makefile.am: + * gst/parse/grammar.y: + * gst/parse/parse.l: + push & pop the state of the lexer for reentrant use case + Fixes #349180 + +2006-07-29 13:45:09 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.h: Note in the docs that the ::newsegment vfunc is not actually used by + Original commit message from CVS: + * libs/gst/base/gstbasesrc.h: + Note in the docs that the ::newsegment vfunc is not actually used by + GstBaseSrc. + +2006-07-28 14:09:10 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: When flushing a pad, also clear the queued buffer so that we don't accidentally use i... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: + (gst_collect_pads_set_flushing_unlocked), (gst_collect_pads_pop), + (gst_collect_pads_clear), (gst_collect_pads_flush), + (gst_collect_pads_event), (gst_collect_pads_chain): + When flushing a pad, also clear the queued buffer so that we don't + accidentally use it when we shouldn't. + Fix leaks by inreffing incomming buffer. + Flush out queued buffers in case of errors. + Fixes #347452. + +2006-07-28 10:17:54 +0000 Wim Taymans + + docs/random/phonon-gst: Random notes about a Phonon backend. + Original commit message from CVS: + * docs/random/phonon-gst: + Random notes about a Phonon backend. + +2006-07-27 14:32:01 +0000 Jan Schmidt + + libs/gst/base/gstbasetransform.c: Extra debug output + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: (gst_base_transform_setcaps): + Extra debug output + * tests/check/libs/gdp.c: (gst_dp_suite): + Take a whack at fixing the ppc compile using a different define to + disable the broken test. + * tests/check/pipelines/parse-launch.c: (GST_START_TEST): + Remove excess g_print() + +2006-07-27 13:44:22 +0000 Jan Schmidt + + tests/check/pipelines/parse-launch.c: Oops, meant to uncomment this line too to dampen the noise a bit. + Original commit message from CVS: + * tests/check/pipelines/parse-launch.c: (expected_fail_pipe): + Oops, meant to uncomment this line too to dampen the noise a bit. + +2006-07-27 13:26:27 +0000 Jan Schmidt + + Fix some of the leaks exposed by extending the parse-launch testsuite, and move the 3 I can't figure out into a separ... + Original commit message from CVS: + * gst/parse/grammar.y: + * gst/parse/parse.l: + * tests/check/pipelines/parse-launch.c: (expected_fail_pipe), + (GST_START_TEST), (parse_suite): + Fix some of the leaks exposed by extending the parse-launch testsuite, + and move the 3 I can't figure out into a separate test that won't run + the pipelines unless the appropriate line is uncommented. + +2006-07-27 12:39:42 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesrc.c: Requesting 0 bytes before the end of the file should result in + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_create_read): + Requesting 0 bytes before the end of the file should result in + FLOW_OK and an empty buffer, not FLOW_UNEXPECTED. Thank you + unit test. + +2006-07-27 11:00:21 +0000 Wim Taymans + + gst/gstcaps.c: Fix useless assert, a uint is always positive. + Original commit message from CVS: + * gst/gstcaps.c: (gst_static_caps_get), (gst_caps_get_structure): + Fix useless assert, a uint is always positive. + * gst/gststructure.c: (gst_structure_nth_field_name), + (gst_structure_foreach), (gst_structure_map_in_place): + Check input arguments for public functions to avoid obvious crashes. + * plugins/elements/gstfakesink.c: (gst_fake_sink_render): + * plugins/elements/gstfakesink.h: + Do less useless typechecking. + +2006-07-27 10:54:29 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesrc.c: Do not use mmap() by default since there are a number of error conditions that we woul... + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init): + Do not use mmap() by default since there are a number of error + conditions that we would like to handle in a non-fatal way that + will result in a SIGBUS if we use mmap(). Examples: external + devices (USB harddrive, portable music player) being unplugged + while in use; file on mounted CD/DVD that can't be read because + the medium is partly damaged. Fixes #348455 and #348475. + +2006-07-26 22:59:19 +0000 Jan Schmidt + + gst/gstquery.h: Delete unused and misleading define of GST_QUERY_TYPE_RATE_DEN - rates are a gdouble + Original commit message from CVS: + * gst/gstquery.h: + Delete unused and misleading define of GST_QUERY_TYPE_RATE_DEN - + rates are a gdouble + +2006-07-26 20:30:55 +0000 Stefan Kost + + gst/gstregistry.c: Move big documentation comment into class section header, so that it appears in the API docs. + Original commit message from CVS: + * gst/gstregistry.c: + Move big documentation comment into class section header, so that it + appears in the API docs. + +2006-07-26 17:18:25 +0000 Jan Schmidt + + docs/gst/gstreamer-sections.txt: Oops. Commit the docs additions too for new API. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Oops. Commit the docs additions too for new API. + Also, remove the mention of the non-existent GST_QUERY_TYPE_RATE_DEN + +2006-07-26 17:04:45 +0000 Jan Schmidt + + gst/gststructure.*: Add API for setting values into structures without performing a quark lookup, if the appropriate ... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_id_set), + (gst_structure_id_set_valist): + * gst/gststructure.h: + Add API for setting values into structures without performing + a quark lookup, if the appropriate quark is already known. + API: gst_structure_id_set + API: gst_structure_id_set_valist + * gst/parse/grammar.y: + * gst/parse/parse.l: + Remove some dead code shown by the coverage information. + Don't throw a critical g_warning when encountering a syntax error, + just warn and let the normal error path handle it. + * plugins/elements/gstelements.c: + Bump the rank of filesink up to PRIMARY so that it is preferred over + gnomevfssink for file:// sink uri's + * tests/check/pipelines/parse-launch.c: (expected_fail_pipe), + (GST_START_TEST), (run_delayed_test), + (gst_parse_test_element_base_init), + (gst_parse_test_element_class_init), (gst_parse_test_element_init), + (gst_parse_test_element_change_state), + (gst_register_parse_element), (parse_suite): + Beef up the tests for parse syntax to check that more error cases + fail as they are supposed to. Increases the test coverage a bit. + +2006-07-26 11:43:23 +0000 Tim-Philipp Müller + + docs/manual/basics-elements.xml: Fix gst_element_link() example. + Original commit message from CVS: + * docs/manual/basics-elements.xml: + Fix gst_element_link() example. + * gst/gstutils.c: + Mention in API docs that one should usually gst_bin_add() + elements to a bin or pipeline before doing the linking. + +2006-07-26 10:47:17 +0000 Thomas Vander Stichele + + * win32/common/config.h: + back to 32 bit + Original commit message from CVS: + back to 32 bit + +2006-07-26 10:39:58 +0000 Wim Taymans + + gst/gstbuffer.c: Avoid function call for known types by keeping the buffer and subbuffer GType global. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_get_type), (gst_buffer_new), + (gst_subbuffer_get_type), (gst_buffer_create_sub): + Avoid function call for known types by keeping the buffer and + subbuffer GType global. + * plugins/elements/gstfilesrc.c: (gst_file_src_create_read): + Random silly optimisations in read() path. + +2006-07-26 06:18:44 +0000 Jan Schmidt + + tools/gst-launch.c: If the top-level of the parse is a normal bin, it doesn't do the right logic to run as a top-leve... + Original commit message from CVS: + * tools/gst-launch.c: (main): + If the top-level of the parse is a normal bin, it doesn't do the + right logic to run as a top-level element, so place it inside a + pipeline. + +2006-07-25 19:37:05 +0000 Tim-Philipp Müller + + plugins/elements/gstfilesrc.c: Remove superfluous g_object_notify() calls, GObject does that for us automatically. + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_set_property): + Remove superfluous g_object_notify() calls, GObject does + that for us automatically. + +2006-07-25 15:07:58 +0000 Christian Schaller + + * gstreamer.spec.in: + add latest .h addition + Original commit message from CVS: + add latest .h addition + +2006-07-25 13:06:14 +0000 Stefan Kost + + gst/gstinfo.h: Move the Win32 version from gst-plugins-good/gst/avi/avidemux.c to here. + Original commit message from CVS: + * gst/gstinfo.h: + Move the Win32 version from gst-plugins-good/gst/avi/avidemux.c to + here. + +2006-07-24 16:33:31 +0000 Tim-Philipp Müller + + gst/gsttaglist.c: Allow more than one GST_TAG_IMAGE per taglist. + Original commit message from CVS: + * gst/gsttaglist.c: (_gst_tag_initialize): + Allow more than one GST_TAG_IMAGE per taglist. + +2006-07-24 07:40:13 +0000 Thomas Vander Stichele + + gst/gstminiobject.c: update docs + Original commit message from CVS: + * gst/gstminiobject.c: + update docs + * plugins/elements/gstfdsrc.c: (gst_fd_src_set_property), + (gst_fd_src_create): + log recurring events at LOG level + add more debug for when the fd gets set + +2006-07-24 07:37:52 +0000 Thomas Vander Stichele + + * autogen.sh: + * common: + remove --enable-docs + Original commit message from CVS: + remove --enable-docs + +2006-07-23 09:41:30 +0000 Tim-Philipp Müller + + * ChangeLog: + * common: + ChangeLog surgery: add bug reference + Original commit message from CVS: + ChangeLog surgery: add bug reference + +2006-07-21 18:52:30 +0000 Stefan Kost + + gst/gstparse.c: Also remove reentrance checks if flex is MT save (#348179) + Original commit message from CVS: + * gst/gstparse.c: (gst_parse_launch): + Also remove reentrance checks if flex is MT save (#348179) + Fix my empty ChangeLog entry below + +2006-07-21 16:01:34 +0000 Andy Wingo + + docs/libs/gstreamer-libs-sections.txt: Attempt to pacify buildbot. + Original commit message from CVS: + 2006-07-21 Andy Wingo + * docs/libs/gstreamer-libs-sections.txt: Attempt to pacify buildbot. + +2006-07-21 15:48:04 +0000 Andy Wingo + + libs/gst/check/Makefile.am (libgstcheck_@GST_MAJORMINOR@include_HEADERS) + Original commit message from CVS: + 2006-07-21 Andy Wingo + * libs/gst/check/Makefile.am + (libgstcheck_@GST_MAJORMINOR@include_HEADERS) + (libgstcheck_@GST_MAJORMINOR@_la_SOURCES): + * libs/gst/check/gstbufferstraw.h: + * libs/gst/check/gstbufferstraw.c: Add some new hype testing + functions, thus proving I am still a GStreamer haxor. OK I wrote + them a long time ago, but anyways. + +2006-07-21 13:11:33 +0000 Stefan Kost + + * ChangeLog: + * common: + * configure.ac: + * gst/gstparse.c: + Original commit message from CVS: * configure.ac: * gst/gstparse.c: (gst_parse_launch): + +2006-07-21 10:40:25 +0000 Wim Taymans + + gst/gstparse.c: Protect recursive calls to _parse with a recursive mutex and busy flag. + Original commit message from CVS: + * gst/gstparse.c: (gst_parse_launch): + Protect recursive calls to _parse with a recursive mutex + and busy flag. + +2006-07-21 10:38:53 +0000 Wim Taymans + + tests/check/gst/gstpad.c: Fix leak in test. + Original commit message from CVS: + * tests/check/gst/gstpad.c: (GST_START_TEST): + Fix leak in test. + +2006-07-20 20:02:55 +0000 Stefan Kost + + gst/gstparse.c: Do not hange on recursive uasge of gst_parse_launch() + Original commit message from CVS: + * gst/gstparse.c: (gst_parse_launch): + Do not hange on recursive uasge of gst_parse_launch() + +2006-07-20 16:10:17 +0000 Tim-Philipp Müller + + gst/gsttaglist.c: Add some more docs, comments and FIXME 0.11s here and there and also fix some typos. + Original commit message from CVS: + * gst/gsttaglist.c: + Add some more docs, comments and FIXME 0.11s here and there + and also fix some typos. + +2006-07-20 10:50:20 +0000 Tim-Philipp Müller + + gst/gstsegment.h: Convert tabs to spaces for better readability. + Original commit message from CVS: + * gst/gstsegment.h: + Convert tabs to spaces for better readability. + +2006-07-20 10:25:28 +0000 Edward Hervey + + tests/check/libs/gdp.c: the test_buffer test fails at line 140 on ppc64 at the following check: "GST_BUFFER_IN_CAPS f... + Original commit message from CVS: + * tests/check/libs/gdp.c: (gst_dp_suite): + the test_buffer test fails at line 140 on ppc64 at the following + check: + fail_unless (GST_BUFFER_FLAG_IS_SET (newbuffer, GST_BUFFER_FLAG_IN_CAPS), + "GST_BUFFER_IN_CAPS flag should have been copied !"); + See bug #348114 for more details. + +2006-07-19 12:40:54 +0000 Tim-Philipp Müller + + Fix typos (#348000). + Original commit message from CVS: + * docs/pwg/advanced-scheduling.xml: + * gst/gstpad.c: + Fix typos (#348000). + +2006-07-18 20:38:45 +0000 Tim-Philipp Müller + + docs/pwg/intro-basics.xml: Fix wrong links (#347927). + Original commit message from CVS: + * docs/pwg/intro-basics.xml: + Fix wrong links (#347927). + +2006-07-18 19:01:25 +0000 Stefan Kost + + make --disable-index work (#342564) + Original commit message from CVS: + * gst/gstregistry.h: + * gst/gstregistryxml.c: (load_feature), + (gst_registry_xml_read_cache), (gst_registry_xml_save_feature): + * win32/common/config.h: + make --disable-index work (#342564) + +2006-07-18 09:42:31 +0000 Peter Kjellerstedt + + gst/: The attached patch adds two missing defines to gsttrace.h when tracing is disabled. It also corrects one exist... + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * gst/Makefile.am: + * gst/gsttrace.h: + The attached patch adds two missing defines to gsttrace.h when tracing + is disabled. It also corrects one existing define. + Fixes #347756. + +2006-07-17 17:40:52 +0000 Wim Taymans + + Add two functions to check and change the SIGSEGV behaviour when loading plugins. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: (gst_segtrap_is_enabled), (gst_segtrap_set_enabled): + * gst/gst.h: + * gst/gstplugin.c: (_gst_plugin_fault_handler_restore): + Add two functions to check and change the SIGSEGV behaviour + when loading plugins. + Don't mess with the SIGSEGV handler when we were told not to. + Fixes #347794. + API: gst_segtrap_is_enabled + API: gst_segtrap_set_enabled + +2006-07-14 16:42:20 +0000 Wim Taymans + + Revert fix for regression in #347408 after release. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_update_length): + * tests/check/elements/filesrc.c: (GST_START_TEST): + Revert fix for regression in #347408 after release. + +2006-07-14 16:20:18 +0000 Antoine Tremblay + + gst/gstutils.c: Free iterator when done (#347311). + Original commit message from CVS: + Patch by: Antoine Tremblay + * gst/gstutils.c: (gst_element_unlink): + Free iterator when done (#347311). + * tests/check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + And add a test case for this. + +2006-07-14 15:52:55 +0000 Jan Schmidt + + 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:50:19 +0000 Jan Schmidt + + configure.ac: releasing 0.10.9, "On the road again" + Original commit message from CVS: + 2006-07-13 Jan Schmidt + * configure.ac: + releasing 0.10.9, "On the road again" + +2006-07-13 19:47:14 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-07-13 15:51:05 +0000 Wim Taymans + + Revert pull-0 fix for release. Disable check. Fixes #347408. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_update_length): + * tests/check/elements/filesrc.c: (GST_START_TEST): + Revert pull-0 fix for release. Disable check. Fixes #347408. + +2006-07-13 14:02:16 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/dataprotocol.c: Fixes #347337: failure to deserialize event packets with empty payload (only ev... + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_event_from_packet_1_0): + Fixes #347337: failure to deserialize event packets with + empty payload (only event type) + +2006-07-13 13:57:33 +0000 Thomas Vander Stichele + + gst/Makefile.am: do not install a .c file in the header directory + Original commit message from CVS: + * gst/Makefile.am: + do not install a .c file in the header directory + +2006-07-13 10:47:00 +0000 Edward Hervey + + gst/gstghostpad.c: GhostPad no longer implicitely use the padtemplates of the targets. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_set_target_unlocked): + GhostPad no longer implicitely use the padtemplates of the targets. + Fixes #347384 + +2006-07-11 22:55:40 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-07-11 20:44:46 +0000 Jan Schmidt + + * ChangeLog: + Mention bug #341029 fixed by bilboed's previous commit + Original commit message from CVS: + Mention bug #341029 fixed by bilboed's previous commit + +2006-07-11 20:14:20 +0000 Jan Schmidt + + Make GstValueArray comparison be order dependent as designed. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_compare_list), + (gst_value_compare_array), (_gst_value_initialize): + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Make GstValueArray comparison be order dependent as designed. + Add checks for value lists and value array comparisons. + Fixes #347221 + +2006-07-11 16:20:09 +0000 Edward Hervey + + gst/gstbin.c: (de)activate src pads before calling state_change on the childs. + Original commit message from CVS: + * gst/gstbin.c: (activate_pads), + (iterator_activate_fold_with_resync), (gst_bin_src_pads_activate), + (gst_bin_change_state_func): + (de)activate src pads before calling state_change on the childs. + This is to avoid the case where a src ghostpad is blocked (holding the + stream lock), which would block the deactivation of the ghostpad's + target pad. + * gst/gstghostpad.c: (gst_proxy_pad_do_query_type), + (gst_proxy_pad_do_event), (gst_proxy_pad_do_query), + (gst_proxy_pad_do_internal_link), (gst_proxy_pad_do_bufferalloc), + (gst_proxy_pad_do_chain), (gst_proxy_pad_do_getrange), + (gst_proxy_pad_do_checkgetrange), (gst_proxy_pad_do_getcaps), + (gst_proxy_pad_do_acceptcaps), (gst_proxy_pad_do_fixatecaps), + (gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked), + (gst_proxy_pad_set_target), (gst_proxy_pad_get_internal), + (gst_proxy_pad_dispose), (gst_proxy_pad_init), + (gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset), + (gst_ghost_pad_class_init), + (gst_ghost_pad_internal_do_activate_push), + (gst_ghost_pad_internal_do_activate_pull), + (gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull), + (gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink), + (gst_ghost_pad_dispose), (gst_ghost_pad_new_no_target), + (gst_ghost_pad_new), (gst_ghost_pad_set_target): + GhostPads now create their internal GstProxyPad at creation (and not + when they're linked, as it was being done previously). + The internal and target pads are linked straight away. + The data will also travel through the other pad in order to make + pad blocking and probes non-hackish (the probe/block now really happens + on the GhostPad and not on the target). + * gst/gstpad.c: (gst_pad_set_blocked_async), + (gst_pad_link_prepare), (gst_pad_push_event): + Remove previous ghostpad cruft. + * gst/gstutils.c: (gst_pad_add_data_probe), + (gst_pad_add_event_probe), (gst_pad_add_buffer_probe), + (gst_pad_remove_data_probe), (gst_pad_remove_event_probe), + (gst_pad_remove_buffer_probe): + Remove previous ghost pad cruft. + Added more detailed debug statements. + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + Fix the testsuite for refcounting changes. + The comments about who has references were correct, but the refcount + being checked wasn't the same (!?!). + +2006-07-10 19:35:32 +0000 Stefan Kost + + More docs for configuration options, add docs to gtk-doc. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstconfig.h.in: + More docs for configuration options, add docs to gtk-doc. + +2006-07-10 18:27:40 +0000 Stefan Kost + + Fix build when disabling tracing (fixes #344016). Also start to document the defines that disable the sub-systems. + Original commit message from CVS: + * gst/Makefile.am: + * gst/gstconfig.h.in: + * win32/common/config.h: + Fix build when disabling tracing (fixes #344016). Also start to document + the defines that disable the sub-systems. + +2006-07-10 09:42:20 +0000 Edward Hervey + + gst/gst.c: let's make valgrind happy... + Original commit message from CVS: + * gst/gst.c: (ensure_current_registry_forking): + let's make valgrind happy... + +2006-07-09 16:56:48 +0000 Wim Taymans + + gst/gstelement.c: Better pad activation code: Reset the collect value too on resync. + Original commit message from CVS: + * gst/gstelement.c: (activate_pads), + (iterator_activate_fold_with_resync), (gst_element_pads_activate): + Better pad activation code: Reset the collect value too on resync. + Add some comments. + +2006-07-09 13:26:06 +0000 Wim Taymans + + gst/gstpad.c: Use some more macros where it makes sense. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_init), (gst_pad_activate_pull), + (gst_pad_activate_push): + Use some more macros where it makes sense. + Allow pad mode switching instead of asserting. When a pad + is activated in one mode and we activate it in another, + deactivate it first before activating it in a different mode. + Fixes #329198. + +2006-07-08 13:22:32 +0000 Andy Wingo + + tools/gst-launch.c (main): Handle err == NULL. gst/gst.c (init_post, ensure_current_registry) (ensure_current_registr... + Original commit message from CVS: + 2006-07-08 Andy Wingo + * tools/gst-launch.c (main): Handle err == NULL. + * gst/gst.c (init_post, ensure_current_registry) + (ensure_current_registry_forking) + (ensure_current_registry_nonforking): Reduce #ifdef ratnest by + factoring out the registry scanning into separate functions. Don't + fork for the rescan is GST_REGISTRY_FORK=no; useful in debugging. + Better environment var name/interface suggestions accepted. + +2006-07-07 17:16:26 +0000 Tim-Philipp Müller + + gst/gstobject.c: Random micro-optimisation: don't use a hash table with strings as keys and the usual strdup/strcmp i... + Original commit message from CVS: + * gst/gstobject.c: (gst_object_set_name_default), + (gst_object_set_name): + Random micro-optimisation: don't use a hash table + with strings as keys and the usual strdup/strcmp + involved, but rather just use the GQuark of the + type name as key, since it needs to be looked up + anyway to get the type name string. + * tests/check/gst/gstobject.c: (GST_START_TEST): + Fix various leaks. + +2006-07-07 15:42:08 +0000 Tim-Philipp Müller + + gst/gstbin.c: Can't use GPOINTER_TO_INT and GINT_TO_POINTER with GTypes. + Original commit message from CVS: + * gst/gstbin.c: (compare_interface), (gst_bin_get_by_interface), + (gst_bin_iterate_all_by_interface): + Can't use GPOINTER_TO_INT and GINT_TO_POINTER with GTypes. + GTypes are gulongs and thus the top 4 bytes might be cut + off on some platforms when doing GPOINTER_TO_INT, leading + to invalid GTypes and bad things happening. + Also add a check to make sure the type passed in is really + an interface type. + +2006-07-07 09:47:19 +0000 Tim-Philipp Müller + + .cvsignore: Ignore more. + Original commit message from CVS: + * .cvsignore: + Ignore more. + +2006-07-07 09:09:10 +0000 Tim-Philipp Müller + + Make gst-element-check-$VERSION.m4 call gst-inspect-$VERSION instead of the unversioned gst-inspect (#324176, #168659). + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * gst-element-check.m4: + * gst-element-check.m4.in: + Make gst-element-check-$VERSION.m4 call gst-inspect-$VERSION + instead of the unversioned gst-inspect (#324176, #168659). + +2006-07-06 16:17:20 +0000 Wim Taymans + + gst/gstmessage.h: Use a valid int for the _MESSAGE_ANY enum value to avoid compiler warnings. + Original commit message from CVS: + * gst/gstmessage.h: + Use a valid int for the _MESSAGE_ANY enum value to avoid compiler + warnings. + +2006-07-06 15:46:25 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Update docs. blocksize == 0 now means the default blocksize when working in push based mode. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_wait), (gst_base_src_update_length), + (gst_base_src_get_range), (gst_base_src_default_check_get_range), + (gst_base_src_check_get_range), (gst_base_src_pad_check_get_range), + (gst_base_src_loop), (gst_base_src_start), + (gst_base_src_activate_pull): + Update docs. + blocksize == 0 now means the default blocksize when working in push + based mode. + Remove some pointless asserts in _wait function. + Fix offset/length calculations and EOS handling. We can now pull 0 + bytes as well, which is allowed. + use _check_get_range() to decide if we can operate in _pull based + mode. + Fix refcounting leak when check_get_range function was not + implemented. + API GstBaseSrc::blocksize range can be 0 too now (default) + * tests/check/elements/filesrc.c: (GST_START_TEST), + (filesrc_suite): + Added check to test _get_range() behaviour. + +2006-07-06 15:21:46 +0000 Wim Taymans + + gst/gstpad.*: Lots of comments and docs added to the pad functions. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_chain_unchecked), (gst_pad_chain), + (gst_pad_push), (gst_pad_check_pull_range), (gst_pad_get_range), + (gst_pad_pull_range): + * gst/gstpad.h: + Lots of comments and docs added to the pad functions. + Flesh out the expected behaviour of the get_range() functions. + +2006-07-06 09:21:03 +0000 Wim Taymans + + gst/: Remove comma at end of enumerator list. + Original commit message from CVS: + * gst/gstbus.h: + * gst/gstclock.h: + * gst/gstevent.h: + * gst/gstiterator.h: + * gst/gstpad.h: + * gst/gstplugin.h: + * gst/gsttask.h: + Remove comma at end of enumerator list. + +2006-07-05 19:56:08 +0000 Sébastien Moutte + + win32/common/: Add new exported functions. + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstdataprotocol.def: + * win32/common/libsgtreamer.def: + Add new exported functions. + +2006-07-05 18:20:58 +0000 Wim Taymans + + libs/gst/base/gstpushsrc.c: Add some more docs here and there. + Original commit message from CVS: + * libs/gst/base/gstpushsrc.c: (gst_push_src_check_get_range): + Add some more docs here and there. + +2006-07-05 18:18:47 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: When operating in pull mode update the offset so that we read sequentially. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_preroll_object), + (gst_base_sink_loop), (gst_base_sink_get_position): + When operating in pull mode update the offset so that we + read sequentially. + +2006-07-05 18:17:01 +0000 Wim Taymans + + gst/gstregistryxml.c: Avoid strdup. (will happen in libxml, but hey!) + Original commit message from CVS: + * gst/gstregistryxml.c: (read_string): + Avoid strdup. (will happen in libxml, but hey!) + * gst/gsturi.c: + Add some more docs. + +2006-07-05 17:09:18 +0000 Wim Taymans + + No point in checking if the size of the subbuffer > 0, the code handles it correclty as demonstrated by unit test. + Original commit message from CVS: + * gst/gstbuffer.c: (_gst_buffer_copy), (gst_buffer_create_sub): + * tests/check/gst/gstbuffer.c: (GST_START_TEST), + (gst_buffer_suite): + No point in checking if the size of the subbuffer > 0, the + code handles it correclty as demonstrated by unit test. + Also add a unit test for the zero sized _new_and_alloc and + _copy. Fixes #346663. + +2006-07-05 08:16:12 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Make sure the buffer we pass to transform_ip has a refcount of 1 and thus is writab... + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer): + Make sure the buffer we pass to transform_ip has a refcount of + 1 and thus is writable. Fixes #343196 + +2006-07-04 09:01:51 +0000 Jan Schmidt + + plugins/elements/gstfilesrc.*: Add "sequential" property, off by default, to use madvise and hint to the kernel that ... + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init), + (gst_file_src_init), (gst_file_src_set_property), + (gst_file_src_get_property), (gst_file_src_map_region): + * plugins/elements/gstfilesrc.h: + Add "sequential" property, off by default, to use madvise and hint + to the kernel that sequential access is desired. + Touch all retrieved pages by default to ensure they are pulled + into memory. (Closes #345720) + +2006-07-03 17:44:09 +0000 Wim Taymans + + docs/design/: Small docs updates. + Original commit message from CVS: + * docs/design/part-block.txt: + * docs/design/part-dynamic.txt: + Small docs updates. + +2006-07-03 16:57:54 +0000 Wim Taymans + + gst/: Use GSlice when the glib we build against is >= 2.10 + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_new_empty), (_gst_caps_free), + (gst_caps_unref), (gst_static_caps_get), + (gst_caps_append_structure): + * gst/gstclock.c: (gst_clock_entry_new), (_gst_clock_id_free): + Use GSlice when the glib we build against is >= 2.10 + +2006-07-03 16:46:07 +0000 Wim Taymans + + gst/gstelement.c: Small cleanup in pad activation code. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_pads_activate): + Small cleanup in pad activation code. + +2006-07-03 14:14:48 +0000 Peter Kjellerstedt + + The attached patch will make the inclusion of gettext.h unconditional in gst/gst-i18n-app.h and gst/gst-i18n-lib.h, a... + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * gst/gst-i18n-app.h: + * gst/gst-i18n-lib.h: + * tools/gst-inspect.c: (print_signal_info): + The attached patch will make the inclusion of gettext.h unconditional in + gst/gst-i18n-app.h and gst/gst-i18n-lib.h, and it will remove the inclusion of + libintl.h in tools/gst-inspect.c. + This allows use of --disable-nls again and fixes #344642. + +2006-07-03 11:10:43 +0000 Thomas Vander Stichele + + * tests/check/gst/gstbin.c: + fix leak + Original commit message from CVS: + fix leak + +2006-07-03 10:30:49 +0000 Edward Hervey + + gst/gstpad.c: Implement pad blocking on events according to part-block.txt. + Original commit message from CVS: + * gst/gstpad.c: (handle_pad_block), (gst_pad_push_event): + Implement pad blocking on events according to part-block.txt. + More comments on behaviour. + * tests/check/gst/gstevent.c: (test_event): + Send event to peer pad of blocked pad (else it will block). + +2006-07-02 23:22:31 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.c: if we get the wrong message, give us the types as string + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_message_error), + (gst_check_run_suite): + if we get the wrong message, give us the types as string + * plugins/elements/gstfilesrc.c: (gst_file_src_start): + Fix a translatable + * tests/check/elements/filesrc.c: (GST_START_TEST): + add a test for trying to open a non-existing file + +2006-07-02 22:44:24 +0000 Thomas Vander Stichele + + * docs/libs/gstreamer-libs-sections.txt: + add macros + Original commit message from CVS: + add macros + +2006-07-02 22:28:38 +0000 Thomas Vander Stichele + + * tests/check/Makefile.am: + remove double var + Original commit message from CVS: + remove double var + +2006-07-02 22:27:32 +0000 Thomas Vander Stichele + + * plugins/elements/Makefile.am: + clean more + Original commit message from CVS: + clean more + +2006-07-02 22:20:20 +0000 Thomas Vander Stichele + + * docs/gst/.gitignore: + * docs/libs/.gitignore: + * tests/benchmarks/.gitignore: + * tests/check/elements/.gitignore: + * tests/check/generic/.gitignore: + * tests/check/gst/.gitignore: + * tests/check/libs/.gitignore: + * tests/check/pipelines/.gitignore: + * tests/examples/controller/.gitignore: + * tests/examples/helloworld/.gitignore: + * tests/examples/launch/.gitignore: + * tests/examples/metadata/.gitignore: + * tests/examples/queue/.gitignore: + * tests/examples/typefind/.gitignore: + * tests/examples/xml/.gitignore: + moap ignore + Original commit message from CVS: + moap ignore + +2006-07-02 22:17:31 +0000 Thomas Vander Stichele + + tests/check/gst/gstbin.c: add a test for adding self + Original commit message from CVS: + * tests/check/gst/gstbin.c: (GST_START_TEST), (gst_bin_suite): + add a test for adding self + +2006-07-02 22:05:48 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.h: add some assert_ as alias for fail_unless_* + Original commit message from CVS: + * libs/gst/check/gstcheck.h: + add some assert_ as alias for fail_unless_* + * tests/check/gst/gst.c: (GST_START_TEST), (gst_suite): + increase test coverage + +2006-07-02 21:54:43 +0000 Thomas Vander Stichele + + Makefile.am: include lcov.mak for lcov coverage generation + Original commit message from CVS: + * Makefile.am: + include lcov.mak for lcov coverage generation + * tools/Makefile.am: + add to CLEANFILES + +2006-07-02 21:52:57 +0000 Thomas Vander Stichele + + * common: + * gst/gstevent.h: + * gst/gstmessage.h: + whitespace/doc fixes + Original commit message from CVS: + whitespace/doc fixes + +2006-07-02 16:27:14 +0000 Edward Hervey + + tests/check/elements/.cvsignore: moaping + Original commit message from CVS: + * tests/check/elements/.cvsignore: + moaping + +2006-07-02 14:39:12 +0000 Thomas Vander Stichele + + configure.ac: don't set CFLAGS and friends for gcov, done from GST_GCOV now + Original commit message from CVS: + * configure.ac: + don't set CFLAGS and friends for gcov, done from GST_GCOV now + * tests/check/Makefile.am: + clean up gcov files + +2006-07-02 14:37:10 +0000 Thomas Vander Stichele + + gst/gstcaps.c: remove gst_caps_simplify; it was not declared and not used and deprecated in 0.8 + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_remove_and_get_structure): + remove gst_caps_simplify; it was not declared and not used + and deprecated in 0.8 + +2006-07-02 14:05:54 +0000 Thomas Vander Stichele + + docs/faq/gst-uninstalled: don't put empty paths on PYTHONPATH + Original commit message from CVS: + * docs/faq/gst-uninstalled: + don't put empty paths on PYTHONPATH + * docs/gst/gstreamer-sections.txt: + remove some symbols that are not there + +2006-07-02 12:57:19 +0000 Thomas Vander Stichele + + * tests/check/gst/gstcaps.c: + unbreak test + Original commit message from CVS: + unbreak test + +2006-07-02 12:54:03 +0000 Thomas Vander Stichele + + gst/gstcaps.c: whitespace fixes + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_compare_structures): + whitespace fixes + * tests/check/gst/gstbuffer.c: (GST_START_TEST): + * tests/check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite): + add more tests + +2006-07-02 12:52:09 +0000 Thomas Vander Stichele + + * gst/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2006-07-02 09:04:45 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/Makefile.am: build dataprotocol test by linking to the lib, instead of compiling the source, so... + Original commit message from CVS: + * libs/gst/dataprotocol/Makefile.am: + build dataprotocol test by linking to the lib, instead of + compiling the source, so we get coverage + * tests/check/Makefile.am: + * tests/check/elements/filesrc.c: (event_func), (setup_filesrc), + (cleanup_filesrc), (GST_START_TEST), (filesrc_suite): + add a test for filesrc + +2006-07-02 08:26:48 +0000 Thomas Vander Stichele + + tests/check/gst/gststructure.c: Push coverage from 59.04% to 70.00% + Original commit message from CVS: + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + Push coverage from 59.04% to 70.00% + +2006-07-02 00:40:56 +0000 Thomas Vander Stichele + + tests/check/gst/gststructure.c: Push coverage from 59.04% to 70.00% + Original commit message from CVS: + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + Push coverage from 59.04% to 70.00% + +2006-07-02 00:39:28 +0000 Thomas Vander Stichele + + * libs/gst/base/.gitignore: + * libs/gst/check/.gitignore: + * libs/gst/dataprotocol/.gitignore: + moap ignore + Original commit message from CVS: + moap ignore + +2006-07-02 00:38:35 +0000 Thomas Vander Stichele + + * libs/gst/base/.gitignore: + moap ignore + Original commit message from CVS: + moap ignore + +2006-07-02 00:33:51 +0000 Thomas Vander Stichele + + tests/check/Makefile.am: gst-inspect every element; this makes sure that we also get coverage on element's get/set fu... + Original commit message from CVS: + * tests/check/Makefile.am: + gst-inspect every element; this makes sure that we also get + coverage on element's get/set functions + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + Push coverage from 59.04% to 70.00% + +2006-07-01 23:26:06 +0000 Thomas Vander Stichele + + configure.ac: set CFLAGS and friends to -O0 if gcov is being used add GCOV LIBS + Original commit message from CVS: + * configure.ac: + set CFLAGS and friends to -O0 if gcov is being used + add GCOV LIBS + * gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/net/Makefile.am: + * plugins/elements/Makefile.am: + * plugins/indexers/Makefile.am: + add makefile rules to generate gcov data and clean up + * tests/check/Makefile.am: + add a coverage target that generates an html overview + of coverage data + +2006-07-01 23:19:28 +0000 Thomas Vander Stichele + + * docs/libs/gstreamer-libs-sections.txt: + fix docs build + Original commit message from CVS: + fix docs build + +2006-07-01 20:56:56 +0000 Thomas Vander Stichele + + tests/check/: use the new macro + Original commit message from CVS: + * tests/check/elements/fakesink.c: + * tests/check/elements/fakesrc.c: + * tests/check/elements/fdsrc.c: + * tests/check/elements/identity.c: + * tests/check/generic/sinks.c: (gst_sinks_suite): + * tests/check/generic/states.c: + * tests/check/gst/gst.c: + * tests/check/gst/gstabi.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbuffer.c: (gst_buffer_suite): + * tests/check/gst/gstbus.c: (gst_bus_suite): + * tests/check/gst/gstcaps.c: (GST_START_TEST): + * tests/check/gst/gstelement.c: + * tests/check/gst/gstevent.c: (gst_event_suite): + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstiterator.c: (gst_iterator_suite): + * tests/check/gst/gstmessage.c: (gst_message_suite): + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gstpipeline.c: + * tests/check/gst/gstplugin.c: + * tests/check/gst/gstquery.c: (gst_query_suite): + * tests/check/gst/gstsegment.c: (gst_segment_suite): + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gsttask.c: (gst_task_suite): + * tests/check/gst/gstutils.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/adapter.c: + * tests/check/libs/basesrc.c: + * tests/check/libs/collectpads.c: + * tests/check/libs/controller.c: + * tests/check/libs/gdp.c: (gst_dp_suite): + * tests/check/libs/gstnetclientclock.c: + * tests/check/libs/gstnettimeprovider.c: + * tests/check/libs/libsabi.c: (libsabi_suite): + * tests/check/libs/typefindhelper.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/parse-launch.c: + * tests/check/pipelines/simple-launch-lines.c: + * tests/check/pipelines/stress.c: (stress_suite): + use the new macro + +2006-07-01 20:54:25 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.*: create a macro and function so that the simple unit test case can be just one macro to cre... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_run_suite): + * libs/gst/check/gstcheck.h: + create a macro and function so that the simple unit test + case can be just one macro to create main() + +2006-06-30 13:17:46 +0000 Tim-Philipp Müller + + gst/: Fix deserialisation from XML. Set parent manually instead of using gst_bin_add(), since gst_bin_add() will unli... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_restore_thyself): + * gst/gstxml.c: (gst_xml_make_element): + Fix deserialisation from XML. Set parent manually + instead of using gst_bin_add(), since gst_bin_add() + will unlink all pads of the element being added. + Fixes #341667. + +2006-06-28 15:19:08 +0000 Peter Kjellerstedt + + gst/gst.c: Fix missing g_strdup() and double free when using the + Original commit message from CVS: + Patch by: Peter Kjellerstedt + * gst/gst.c: (prepare_for_load_plugin_func), (split_and_iterate): + Fix missing g_strdup() and double free when using the + --gst-plugin-load command line option (#346097). + +2006-06-23 13:16:46 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Promote GST_DEBUG_CATEGORY_STATIC in example in docs. + Original commit message from CVS: + * gst/gstinfo.c: + Promote GST_DEBUG_CATEGORY_STATIC in example in docs. + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + Use GST_DEBUG_CATEGORY_STATIC here too (#342503). + +2006-06-23 10:30:09 +0000 Tim-Philipp Müller + + docs/manual/advanced-dataaccess.xml: Fix buffer probe example compilation in + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + Fix buffer probe example compilation in + ADM (#345708). + +2006-06-22 17:09:13 +0000 Edward Hervey + + gst/gstelement.c: We need to deactivate src pads first and then sink pads. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_pads_activate): + We need to deactivate src pads first and then sink pads. + The reason is the src pads might be blocking while holding the streaming + lock, so we need to deactivate them first so that deactivating the sink + pads doesn't block (since it will require the streaming lock). + +2006-06-22 15:12:50 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Forgot to remove two unneeded unrefs. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Forgot to remove two unneeded unrefs. + Simplify a check _is_equal allready checks the obvious case. + +2006-06-22 14:09:41 +0000 Wim Taymans + + docs/design/part-block.txt: Some docs about what pad_block should do. + Original commit message from CVS: + * docs/design/part-block.txt: + Some docs about what pad_block should do. + +2006-06-22 13:51:19 +0000 Wim Taymans + + gst/gstcaps.c: Fix crasher when passed NULL. Doc clarification. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_replace): + Fix crasher when passed NULL. Doc clarification. + Optimize for the trivial case. + * gst/gstpipeline.c: (gst_pipeline_change_state): + Small cleanups. + * libs/gst/base/gstbasesrc.c: (gst_base_src_loop): + Small documentation cleanup. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_buffer_alloc): + Don't use silly gst_pad_get_negotiated_caps, GST_PAD_CAPS + is what we need and it avoids a whole lot of redundant + refcount operations. + +2006-06-22 08:53:40 +0000 Philip Jägenstedt + + docs/manual/advanced-dataaccess.xml: Fix 'Embedding static elements' section to use + Original commit message from CVS: + Patch by: Philip Jägenstedt + * docs/manual/advanced-dataaccess.xml: + Fix 'Embedding static elements' section to use + GST_PLUGIN_DEFINE_STATIC (#345607). + +2006-06-21 11:12:24 +0000 Tim-Philipp Müller + + tests/check/pipelines/simple-launch-lines.c: Attempt to 'fix' spuriously failing test case: it seems like the timeout... + Original commit message from CVS: + * tests/check/pipelines/simple-launch-lines.c: (test_stop_from_app): + Attempt to 'fix' spuriously failing test case: it seems like the + timeout of half a second is simply too small when the system is under + load otherwise, and the timeout doesn't really seem to serve any + particular purpose here. Give the pipeline a few seconds to preroll + first, and then give it another half a second to go from PAUSED to + PLAYING and marshal the message into the main thread. + +2006-06-21 10:14:00 +0000 Tim-Philipp Müller + + tools/gst-feedback-m.m: Don't only use unversioned tools, try versioned tools as well (#345086). + Original commit message from CVS: + * tools/gst-feedback-m.m: + Don't only use unversioned tools, try versioned tools as well + (#345086). + +2006-06-21 10:01:58 +0000 Tim-Philipp Müller + + gst/gstbus.c: Fix some typos, make docs more explicit. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_class_init): + Fix some typos, make docs more explicit. + +2006-06-20 08:40:40 +0000 Wim Taymans + + tests/check/gst/gstghostpad.c: Added some more ghostpad tests, mainly blocking and probes. + Original commit message from CVS: + * tests/check/gst/gstghostpad.c: (block_callback), + (GST_START_TEST), (gst_ghost_pad_suite): + Added some more ghostpad tests, mainly blocking + and probes. + +2006-06-19 08:56:48 +0000 Christian Schaller + + * gstreamer.spec.in: + latest updates + Original commit message from CVS: + latest updates + +2006-06-16 16:28:37 +0000 Wim Taymans + + plugins/elements/gstfilesink.*: Check if we can seek in the file instead of assuming we always can. Post an error whe... + Original commit message from CVS: + * plugins/elements/gstfilesink.c: (gst_file_sink_open_file), + (gst_file_sink_close_file), (gst_file_sink_do_seek), + (gst_file_sink_event), (gst_file_sink_render): + * plugins/elements/gstfilesink.h: + Check if we can seek in the file instead of assuming + we always can. Post an error when we are asked to seek in a + non-seekable file (like a fifo). Fixes #343312. + Some cleanups. + +2006-06-16 14:31:07 +0000 Tim-Philipp Müller + + tools/gst-launch.1.in: Un-garble (fourcc) bit in filtered caps section. + Original commit message from CVS: + * tools/gst-launch.1.in: + Un-garble (fourcc) bit in filtered caps section. + +2006-06-16 09:39:54 +0000 Tim-Philipp Müller + + docs/manual/: Don't leak bus reference in sample code. + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/highlevel-components.xml: + Don't leak bus reference in sample code. + +2006-06-16 08:30:47 +0000 Tim-Philipp Müller + + autogen.sh: Add default for new --enable-plugin-docs switch. + Original commit message from CVS: + * autogen.sh: + Add default for new --enable-plugin-docs switch. + * configure.ac: + Use new GST_PLUGIN_DOCS macro to check for pyxml etc. + Fixes #344039. + * docs/Makefile.am: + Use new ENABLE_PLUGIN_DOCS conditional. + +2006-06-14 10:34:14 +0000 Wim Taymans + + gst/gstbin.c: Make it clear with a FIXME and a real define what the #if 0 previously disabled. + Original commit message from CVS: + * gst/gstbin.c: (bin_query_duration_done), (gst_bin_query): + Make it clear with a FIXME and a real define what the #if 0 + previously disabled. + +2006-06-14 10:31:43 +0000 Wim Taymans + + libs/gst/base/: Don't randomly and silently reset a segment when the format changes as this is a bug somewhere upstre... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment), + (gst_base_sink_preroll_object), (gst_base_sink_get_position): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_eventfunc): + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_event): + Don't randomly and silently reset a segment when the format + changes as this is a bug somewhere upstream. Fixes #330379. + +2006-06-14 08:26:53 +0000 Wouter Paesen + + libs/gst/controller/gstcontroller.c: Fix controlling of float properties (#344849). + Original commit message from CVS: + Patch by: Wouter Paesen + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_new): + Fix controlling of float properties (#344849). + * tests/check/libs/controller.c: + (gst_test_mono_source_get_property), + (gst_test_mono_source_set_property), + (gst_test_mono_source_class_init), (GST_START_TEST): + While we're at it, add some float stuff to unit test. + +2006-06-13 19:24:34 +0000 Thomas Vander Stichele + + docs/: add a gdp image + Original commit message from CVS: + * docs/README: + * docs/images/gdp-header.svg: + add a gdp image + * docs/libs/Makefile.am: + * docs/libs/gdp-header.png: + * libs/gst/dataprotocol/dataprotocol.c: + add it to the API docs + * docs/manual/intro-motivation.xml: + fix typo + +2006-06-13 16:41:37 +0000 Tim-Philipp Müller + + gst/gst.c: If the fork()'ed child process can't write the updated registry cache file to disk for some reason, make i... + Original commit message from CVS: + * gst/gst.c: (scan_and_update_registry), (init_post): + If the fork()'ed child process can't write the updated registry cache + file to disk for some reason, make it exit with a failure exit code, + so that the parent can then re-scan the plugins itself and update the + registry structures in memory and work with that (rather than failing + when creating elements because seemingly no plugins are available). + Refactor registry scanning code into separate function for this and + also separate fork() and non-fork() code paths. Fixes #344748. + +2006-06-13 16:24:43 +0000 Wim Taymans + + docs/manual/advanced-dataaccess.xml: Fix wrong PluginDesc. Fixes #344755. + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + Fix wrong PluginDesc. Fixes #344755. + +2006-06-13 13:30:46 +0000 Tim-Philipp Müller + + gst/gstregistryxml.c: Fix silly bug that prevented us from creating ~/.gstreamer-0.10 and writing the registry in one... + Original commit message from CVS: + * gst/gstregistryxml.c: (gst_registry_xml_write_cache): + Fix silly bug that prevented us from creating + ~/.gstreamer-0.10 and writing the registry in one + go (the first call to g_mkstemp() would overwrite the + placeholder in the template string, so the second call + to g_mkstemp() after creating the missing directory + would then error out with 'invalid argument'). + +2006-06-13 11:17:02 +0000 Edward Hervey + + gst/gst.c: Free string. + Original commit message from CVS: + * gst/gst.c: (init_post): + Free string. + +2006-06-13 08:20:24 +0000 Thomas Vander Stichele + + gst/: remove GLib 2.6 compatibility code + Original commit message from CVS: + * gst/glib-compat-private.h: + * gst/glib-compat.c: + * gst/glib-compat.h: + * gst/gstvalue.c: (gst_value_serialize_flags): + remove GLib 2.6 compatibility code + +2006-06-12 16:50:09 +0000 Tim-Philipp Müller + + gst/parse/Makefile.am: Fix build with 'make -j N' even more (#340016). + Original commit message from CVS: + * gst/parse/Makefile.am: + Fix build with 'make -j N' even more (#340016). + +2006-06-12 09:37:58 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Fix docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Fix docs. + +2006-06-12 09:29:49 +0000 Wim Taymans + + gst/gstsegment.c: Use G_UNLIKELY to help the compiler a bit. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_set_duration), + (gst_segment_set_last_stop), (gst_segment_set_seek), + (gst_segment_set_newsegment_full), (gst_segment_to_stream_time), + (gst_segment_to_running_time), (gst_segment_clip): + Use G_UNLIKELY to help the compiler a bit. + +2006-06-12 09:28:35 +0000 Stefan Kost + + gst/: constify quark registration strings. Fixes #344115 + Original commit message from CVS: + Patch by: Stefan Kost + * gst/gstevent.c: (gst_event_get_type): + * gst/gstmessage.c: + * gst/gstpad.c: (gst_pad_chain_unchecked), (gst_pad_chain), + (gst_pad_push): + constify quark registration strings. Fixes #344115 + Avoid unneeded type checking is _pad_push() by internally + calling gst_pad_chain_unchecked(). + +2006-06-12 09:23:43 +0000 Wim Taymans + + gst/gstbuffer.c: Init _type for consistency. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_get_type), (gst_buffer_finalize), + (_gst_buffer_copy), (gst_buffer_is_metadata_writable), + (gst_subbuffer_finalize), (gst_buffer_create_sub), + (gst_buffer_is_span_fast), (gst_buffer_span): + Init _type for consistency. + Use _FLAGS macro to avoid type check. + Avoid unneeded type checks in subbufer code. + +2006-06-12 09:17:44 +0000 Wim Taymans + + gst/: Use _CAST macros to avoid unneeded type checking. + Original commit message from CVS: + * gst/gst.c: (gst_debug_help): + * gst/gstplugin.c: (gst_plugin_finalize), (gst_plugin_list_free): + * gst/gstpluginfeature.c: (gst_plugin_feature_finalize), + (gst_plugin_feature_list_free): + * gst/gstregistry.c: (gst_registry_add_plugin), + (gst_registry_add_feature), (gst_registry_plugin_filter), + (gst_registry_feature_filter), (gst_registry_find_plugin), + (gst_registry_find_feature), (gst_registry_get_plugin_list), + (gst_registry_lookup_feature_locked), (gst_registry_lookup_locked): + * gst/gstregistryxml.c: (load_feature), + (gst_registry_xml_read_cache), (gst_registry_xml_write_cache): + * gst/gstminiobject.c: (gst_mini_object_unref), + (gst_mini_object_replace), (gst_value_mini_object_free), + (gst_value_mini_object_copy): + Use _CAST macros to avoid unneeded type checking. + Added some more G_UNLIKELY. + +2006-06-12 09:11:44 +0000 Wim Taymans + + gst/gstbuffer.h: Avoid unneeded type checking. + Original commit message from CVS: + * gst/gstbuffer.h: + Avoid unneeded type checking. + API: GST_BUFFER_IS_DISCONT + * gst/gstminiobject.h: + Avoid type check in flag accessor. + * gst/gstelementfactory.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.h: + Add _CAST macros. + API: GST_ELEMENT_FACTORY_CAST + API: GST_PLUGIN_CAST + API: GST_PLUGIN_FEATURE_CAST + +2006-06-12 09:06:01 +0000 Wim Taymans + + gst/gstobject.c: Add G_UNLIKELY in type registration. + Original commit message from CVS: + * gst/gstobject.c: (gst_object_get_type), (gst_object_ref), + (gst_object_unref): + Add G_UNLIKELY in type registration. + Avoid type check in _ref/_unref since that is also + done in glib. + +2006-06-12 08:55:21 +0000 Wim Taymans + + Add G_UNLIKELY in type registration. + Original commit message from CVS: + * gst/gsterror.c: (gst_g_error_get_type): + * gst/gstpadtemplate.c: (gst_pad_template_get_type), + (gst_static_pad_template_get_type): + * gst/gsttaglist.c: (gst_tag_list_get_type): + * gst/gsttagsetter.c: (gst_tag_setter_get_type): + * gst/gsttypefindfactory.c: (gst_type_find_factory_get_type): + * gst/gsturi.c: (gst_uri_handler_get_type): + * gst/gstvalue.c: (gst_date_get_type): + * gst/gstxml.c: (gst_xml_get_type): + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_type), + (gst_base_sink_preroll_object), (gst_base_sink_get_position): + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_type): + Add G_UNLIKELY in type registration. + +2006-06-12 08:51:20 +0000 Wim Taymans + + tools/gst-inspect.c: Properly print enum values. + Original commit message from CVS: + * tools/gst-inspect.c: (print_signal_info): + Properly print enum values. + +2006-06-12 08:47:16 +0000 Wim Taymans + + gst/gstinfo.*: Add some G_[UN]LIKELY. + Original commit message from CVS: + * gst/gstinfo.c: (gst_debug_set_active), + (gst_debug_category_set_threshold), (_gst_debug_nameof_funcptr): + * gst/gstinfo.h: + Add some G_[UN]LIKELY. + Maintain __gst_debug_min to avoid formatting the arguments of + debug messages that will be dropped anyway to avoid a lot of + overhead from the debugging system. + +2006-06-11 20:37:41 +0000 Stefan Kost + + po/POTFILES.*: add missing files containing translatable strings, tell intltool about one exception + Original commit message from CVS: + * po/POTFILES.in: + * po/POTFILES.skip: + add missing files containing translatable strings, tell intltool about + one exception + +2006-06-11 17:28:19 +0000 Stefan Kost + + tests/check/libs/.cvsignore: add test-binary to ignore list + Original commit message from CVS: + * tests/check/libs/.cvsignore: + add test-binary to ignore list + +2006-06-11 17:03:06 +0000 Stefan Kost + + docs/libs/gstreamer-libs-docs.sgml: reorder (put dp into a chapter) and indent + Original commit message from CVS: + * docs/libs/gstreamer-libs-docs.sgml: + reorder (put dp into a chapter) and indent + +2006-06-11 11:56:36 +0000 Thomas Vander Stichele + + * common: + * docs/random/autotools: + add notes on our autotools setup + Original commit message from CVS: + add notes on our autotools setup + +2006-06-10 17:32:53 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + * win32/common/config.h: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.8 === + +2006-06-10 17:06:33 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + * win32/common/config.h: + releasing 0.10.8 + Original commit message from CVS: + releasing 0.10.8 + +2006-06-10 11:51:58 +0000 Thomas Vander Stichele + + gst/gst.c: move pid declaration to declaration block + Original commit message from CVS: + * gst/gst.c: (init_post): + move pid declaration to declaration block + +2006-06-10 11:47:42 +0000 Thomas Vander Stichele + + gst/gst.c: use _exit() instead of exit() in our forked child; this ensures that none of the registered exit handlers ... + Original commit message from CVS: + * gst/gst.c: (init_post): + use _exit() instead of exit() in our forked child; this ensures + that none of the registered exit handlers from whatever is using + GStreamer get executed. This fixes gnome-mixer-applet failing + to load, because ORBit would shut down. + Spotted by: Edward Hervey + Fix suggested by: Tim-Philipp Müller + Fixes #344474 + +2006-06-09 18:52:02 +0000 Thomas Vander Stichele + + configure.ac: back to TRUNK + Original commit message from CVS: + 2006-06-09 Thomas Vander Stichele + * configure.ac: + back to TRUNK + +=== release 0.10.7 === + +2006-06-09 18:49:25 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + releasing 0.10.7 + Original commit message from CVS: + releasing 0.10.7 + +2006-06-07 10:46:04 +0000 Thomas Vander Stichele + + 0.10.6.2 prerelease + Original commit message from CVS: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + * win32/common/config.h: + 0.10.6.2 prerelease + +2006-06-07 08:38:30 +0000 Wim Taymans + + Fix leak spotted by coverity checker. Fixes #343827 + Original commit message from CVS: + * gst/gstindex.c: (gst_index_gtype_resolver): + * tools/gst-xmlinspect.c: (print_plugin_info): + Fix leak spotted by coverity checker. Fixes #343827 + Fix another other leak found by paolo borelli. + +2006-06-06 16:52:59 +0000 Thomas Vander Stichele + + * tests/check/gst/struct_ppc64.h: + * tests/check/gst/struct_x86_64.h: + ifdef LOADSAVE + Original commit message from CVS: + ifdef LOADSAVE + +2006-06-06 15:18:26 +0000 Thomas Vander Stichele + + * docs/libs/tmpl/gstcontrol.sgml: + remove old docs + Original commit message from CVS: + remove old docs + +2006-06-06 14:51:45 +0000 Thomas Vander Stichele + + * tests/check/libs/libsabi.c: + terminate ifdef + Original commit message from CVS: + terminate ifdef + +2006-06-06 14:32:55 +0000 Thomas Vander Stichele + + * docs/libs/tmpl/gstbytestream.sgml: + remove unused tmpl + Original commit message from CVS: + remove unused tmpl + +2006-06-06 14:29:54 +0000 Thomas Vander Stichele + + * docs/libs/tmpl/gstdataprotocol.sgml: + * libs/gst/dataprotocol/dataprotocol.c: + add note to docs about GDP versioning; remove tmpl file + Original commit message from CVS: + add note to docs about GDP versioning; remove tmpl file + +2006-06-06 14:24:00 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/dataprotocol.*: API: add a GstDPPacketizer object, and create/free functions + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer_any), (gst_dp_packet_from_caps_any), + (gst_dp_version_get_type), (gst_dp_init), + (gst_dp_header_from_buffer), (gst_dp_header_from_buffer_1_0), + (gst_dp_packet_from_caps), (gst_dp_packet_from_caps_1_0), + (gst_dp_packet_from_event), (gst_dp_packet_from_event_1_0), + (gst_dp_event_from_packet_0_2), (gst_dp_event_from_packet_1_0), + (gst_dp_event_from_packet), (gst_dp_packetizer_new), + (gst_dp_packetizer_free): + * libs/gst/dataprotocol/dataprotocol.h: + API: add a GstDPPacketizer object, and create/free functions + API: add GstDPVersion enum + Add 1.0 event function that uses the string serialization + Serialize more useful buffer flags + Fixes #343988 + +2006-06-06 14:21:10 +0000 Thomas Vander Stichele + + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/tmpl/gstdataprotocol.sgml: + add symbol + Original commit message from CVS: + add symbol + +2006-06-06 14:16:33 +0000 Thomas Vander Stichele + + * gst/gstbuffer.h: + width respectationizing + Original commit message from CVS: + width respectationizing + +2006-06-06 14:10:09 +0000 Thomas Vander Stichele + + tests/check/: add ppc64 structure sizes + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_ppc64.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_ppc64.h: + add ppc64 structure sizes + +2006-06-06 13:59:10 +0000 Thomas Vander Stichele + + tests/check/: generate and add structure size lists for x86_64 + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/gstabi.c: + * tests/check/gst/struct_x86_64.h: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_x86_64.h: + generate and add structure size lists for x86_64 + +2006-06-06 13:53:25 +0000 Thomas Vander Stichele + + * libs/gst/check/gstcheck.c: + cosmetics + Original commit message from CVS: + cosmetics + +2006-06-06 13:48:20 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.*: factor out the method from tests that checks size of structures, and add code to generate ... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_abi_list): + * libs/gst/check/gstcheck.h: + factor out the method from tests that checks size of structures, + and add code to generate the header containing these sizes + * tests/check/gst/gstabi.c: (GST_START_TEST): + * tests/check/gst/struct_i386.h: + * tests/check/libs/libsabi.c: (GST_START_TEST): + * tests/check/libs/struct_i386.h: + use it + +2006-06-06 13:11:03 +0000 Michael Smith + + gst/gstsegment.h: Don't use c++-style comments, fixes #343929 + Original commit message from CVS: + * gst/gstsegment.h: + Don't use c++-style comments, fixes #343929 + +2006-06-06 09:47:40 +0000 Thomas Vander Stichele + + * gst/gstelement.h: + whitespace/width fixes + Original commit message from CVS: + whitespace/width fixes + +2006-06-06 08:50:40 +0000 Thomas Vander Stichele + + * gst/gstbuffer.c: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2006-06-06 08:50:25 +0000 Thomas Vander Stichele + + * common: + * gst/gsterror.c: + remove an extra space + Original commit message from CVS: + remove an extra space + +2006-06-05 13:05:37 +0000 Edward Hervey + + gst/gst.c: plugin_paths is not used if we build without registry support. + Original commit message from CVS: + * gst/gst.c: + plugin_paths is not used if we build without registry support. + * gst/gstsegment.c: (gst_segment_copy): + _copy() was always returning NULL... + +2006-06-05 12:55:58 +0000 Edward Hervey + + gst/gstsegment.c: _copy() was always returning NULL... + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_copy): + _copy() was always returning NULL... + +2006-06-02 16:46:19 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/dataprotocol.c: factor out CRC code + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer), (gst_dp_packet_from_caps), + (gst_dp_packet_from_event): + factor out CRC code + +2006-06-02 16:45:08 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.c: make sure we unset caps + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_teardown_src_pad): + make sure we unset caps + +2006-06-02 16:41:02 +0000 Michael Smith + + libs/gst/check/gstcheck.*: Add a cond/mutex to the check support lib, signal this whenever we add to the buffers list... + Original commit message from CVS: + * libs/gst/check/gstcheck.c: (gst_check_init), + (gst_check_chain_func): + * libs/gst/check/gstcheck.h: + Add a cond/mutex to the check support lib, signal this whenever we + add to the buffers list. This will allow tests to not busy-wait on + the buffer-list. + +2006-06-02 10:58:47 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/dataprotocol.c: factor out some common header init code + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer), (gst_dp_packet_from_caps), + (gst_dp_packet_from_event): + factor out some common header init code + +2006-06-02 10:08:31 +0000 Thomas Vander Stichele + + API: make gst_dp_crc() public + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/tmpl/gstdataprotocol.sgml: + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_crc): + * libs/gst/dataprotocol/dataprotocol.h: + API: make gst_dp_crc() public + +2006-06-02 09:13:56 +0000 Thomas Vander Stichele + + * gst/gstevent.c: + debug change + Original commit message from CVS: + debug change + +2006-06-01 18:30:19 +0000 Stefan Kost + + plugins/indexers/gstindexers.c: conditionally register fileindexer (fixes #343598) + Original commit message from CVS: + * plugins/indexers/gstindexers.c: (plugin_init): + conditionally register fileindexer (fixes #343598) + +2006-06-01 18:22:14 +0000 Stefan Kost + + gst/gsttagsetter.h: Can't cast ifaces to a class + Original commit message from CVS: + * gst/gsttagsetter.h: + Can't cast ifaces to a class + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimeprovider.h: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstfilesink.h: + * plugins/elements/gstfilesrc.h: + * plugins/elements/gstidentity.h: + * plugins/elements/gstqueue.h: + * plugins/elements/gsttee.h: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + * tests/old/examples/plugins/example.h: + Fix more gobject macros: obj<->klass, GstXXX<->GstXXXClass + +2006-06-01 11:13:44 +0000 Thomas Vander Stichele + + libs/gst/dataprotocol/dataprotocol.c: make sure we zero the whole ABI-compatible area + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer): + make sure we zero the whole ABI-compatible area + +2006-06-01 09:02:23 +0000 Alessandro Decina + + libs/gst/base/gstcollectpads.c: Make sure the EOS flag is cleared from pads after a flush or stop. Fixes #343538. + Original commit message from CVS: + Patch by: Alessandro Decina + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_stop): + Make sure the EOS flag is cleared from pads after a flush + or stop. Fixes #343538. + * tests/check/libs/collectpads.c: (GST_START_TEST), + (gst_collect_pads_suite): + Added test for collectpads reusage after EOS. + +2006-05-30 20:25:03 +0000 Sébastien Moutte + + gst/gst.c: set #include in a #ifdef #ifdef HAVE_FORK + Original commit message from CVS: + * gst/gst.c: + set #include in a #ifdef #ifdef HAVE_FORK + * win32/common/libgstbase.def: + export gst_collect_pads_set_flushing + * win32/common/libgstreamer.def: + export gst_pad_set_acceptcaps_function, gst_structure_empty_new, + gst_value_fraction_multiply + * win32/vs6/gst_inspect.dsp: + add a link to intl.lib + +2006-05-30 15:55:19 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: Handle the case where a pad is removed from the collection that could cause the other... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_remove_pad), + (gst_collect_pads_chain): + Handle the case where a pad is removed from the collection + that could cause the other pads to become collectable. + +2006-05-30 15:53:40 +0000 Wim Taymans + + gst/gstelement.c: Clarify the use of _release_request_pad() and _get_request_pad() a bit better. + Original commit message from CVS: + * gst/gstelement.c: + Clarify the use of _release_request_pad() and + _get_request_pad() a bit better. + * libs/gst/base/gstadapter.c: (gst_adapter_peek), + (gst_adapter_take_buffer): + Fix some doc and comment typos. + +2006-05-30 14:43:35 +0000 Thomas Vander Stichele + + docs/: add declared symbols + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + add declared symbols + +2006-05-30 14:41:15 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + update po files + Original commit message from CVS: + update po files + +2006-05-30 14:40:48 +0000 Thomas Vander Stichele + + * tests/check/Makefile.am: + fix build + Original commit message from CVS: + fix build + +2006-05-30 14:03:58 +0000 Thomas Vander Stichele + + * win32/common/config.h: + added HAVE_FORK + Original commit message from CVS: + added HAVE_FORK + +2006-05-30 12:04:29 +0000 Jan Schmidt + + gst/gstsystemclock.c: Add debug that can be enabled using a #define at the top of the file, for dumping stats about h... + Original commit message from CVS: + * gst/gstsystemclock.c: (gst_system_clock_id_wait_unlocked): + Add debug that can be enabled using a #define at the top of the file, + for dumping stats about how late/early we were when waking up from + waiting on the clock. + +2006-05-30 11:43:43 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: When rebuilding the pad list, don't leak the previous list. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_check_pads): + When rebuilding the pad list, don't leak the previous list. + +2006-05-30 10:57:44 +0000 Lutz Mueller + + libs/gst/base/gstbasesrc.c: Publish supported query types. + Original commit message from CVS: + Patch by: Lutz Mueller + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_get_query_types), (gst_base_src_update_length): + Publish supported query types. + Update last_stop field in get_range mode so the position + query works. Fixes #342321. + +2006-05-30 10:12:02 +0000 Tim-Philipp Müller + + API: add GST_TAG_PREVIEW_IMAGE (#343341). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + API: add GST_TAG_PREVIEW_IMAGE (#343341). + +2006-05-30 09:42:09 +0000 Alessandro Decina + + libs/gst/base/gstcollectpads.c: Unlock mutex when removing an unknown pad. + Original commit message from CVS: + Patch by: Alessandro Decina + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_remove_pad): + Unlock mutex when removing an unknown pad. + Fixes #343334. + * tests/check/Makefile.am: + * tests/check/libs/collectpads.c: (collected_cb), (push_buffer), + (push_event), (setup), (teardown), (GST_START_TEST), + (gst_collect_pads_suite), (main): + Added collecpads check, disabled for now as check crashes for + some reason. + +2006-05-29 17:20:03 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: Don't leak pads lists. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize): + Don't leak pads lists. + +2006-05-29 16:00:13 +0000 Wim Taymans + + API: gst_collect_pads_set_flushing + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstcollectpads.c: + (gst_collect_pads_set_flushing_unlocked), + (gst_collect_pads_set_flushing), (gst_collect_pads_start), + (gst_collect_pads_stop): + * libs/gst/base/gstcollectpads.h: + API: gst_collect_pads_set_flushing + Added api to set the pads to flushing, usefull for seeking + code in elements using collectpads. + Clear segment when receiving a flush. + +2006-05-29 11:52:50 +0000 Tim-Philipp Müller + + gst/gst.c: Don't scan registry paths passed via --gst-plugin--path immediately (will crash, because absolutely nothin... + Original commit message from CVS: + * gst/gst.c: (add_path_func), (init_post): + Don't scan registry paths passed via --gst-plugin--path immediately + (will crash, because absolutely nothing is set up and no types are + registered etc.); do this later in init_post(). Fixes #343057. + +2006-05-28 09:09:03 +0000 Thomas Vander Stichele + + gst/gst.c: if we have fork, fork while reading/rebuilding the registry so the parent doesn't take the hit of having a... + Original commit message from CVS: + * gst/gst.c: (init_post): + if we have fork, fork while reading/rebuilding the registry + so the parent doesn't take the hit of having all plugins loaded + in memory. Fixes #342777. + * configure.ac: + Check if we have fork() + * win32/common/config.h.in: + no fork() on win32 + +2006-05-26 13:52:03 +0000 Jan Schmidt + + plugins/elements/: Add a use-mmap property to enable easier testing of all code paths. + Original commit message from CVS: + * plugins/elements/gstelements.c: + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init), + (gst_file_src_init), (gst_file_src_set_property), + (gst_file_src_get_property), (gst_file_src_start): + * plugins/elements/gstfilesrc.h: + Add a use-mmap property to enable easier testing of all code paths. + Bump rank to PRIMARY, so filesrc is the preferred file reader and used + in the absence of gnomevfssrc. (Closes #340501) + +2006-05-26 10:35:34 +0000 Zaheer Abbas Merali + + tools/gst-inspect.c: Add missing include, removes warning of ngettext not being defined on some arches. + Original commit message from CVS: + 2006-05-26 Zaheer Abbas Merali + * tools/gst-inspect.c: + Add missing include, removes warning of ngettext not being defined on + some arches. + +2006-05-26 09:19:24 +0000 Jan Schmidt + + gst/gstvalue.c: Handle NULL input and output pointers silently as a failed conversion, rather than g_warnings. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_deserialize_fraction): + Handle NULL input and output pointers silently as a failed conversion, + rather than g_warnings. + +2006-05-25 15:52:19 +0000 Wim Taymans + + libs/gst/net/gstnetclientclock.c: Initialize variable before using. Fixes #342820. + Original commit message from CVS: + * libs/gst/net/gstnetclientclock.c: (gst_net_client_clock_start): + Initialize variable before using. Fixes #342820. + +2006-05-24 17:11:06 +0000 Tim-Philipp Müller + + libs/gst/base/gsttypefindhelper.c: Fix off-by-one bug that would only allow peeks of N-1 bytes from the start even if... + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (buf_helper_find_peek): + Fix off-by-one bug that would only allow peeks of N-1 bytes + from the start even if the buffer to typefind on contains + in fact N bytes of data (makes vorbis typefinding from a + vorbis identification header buffer work). + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/typefindhelper.c: (GST_START_TEST), + (gst_typefindhelper_suite), (main), (foobar_typefind), + (plugin_init): + Add very basic unit test for gst_type_find_helper_for_buffer() + that checks for the problem fixed above. + +2006-05-24 09:00:47 +0000 Thomas Vander Stichele + + * gst/gsttypefind.c: + doc indent fix + Original commit message from CVS: + doc indent fix + +2006-05-24 09:00:10 +0000 Thomas Vander Stichele + + * ChangeLog: + * tools/gst-inspect.c: + mark more strings for translation + Original commit message from CVS: + mark more strings for translation + +2006-05-23 14:23:49 +0000 Julien Moutte + + docs/gst/gstreamer-sections.txt: Make new GST_FLOW_IS_SUCCESS macro visible in docs. + Original commit message from CVS: + Patch by: Julien Moutte + * docs/gst/gstreamer-sections.txt: + Make new GST_FLOW_IS_SUCCESS macro visible in docs. + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init), + (gst_fake_sink_preroll): + * plugins/elements/gstfakesink.h: + Add new ::preroll-handoff signal (#337100). + +2006-05-23 11:13:51 +0000 Wim Taymans + + gst/gstpad.*: Added _CUSTOM error and success GstFlowReturn that can be used be elements internally. + Original commit message from CVS: + * gst/gstpad.c: (gst_flow_get_name), (gst_flow_to_quark): + * gst/gstpad.h: + Added _CUSTOM error and success GstFlowReturn that can be + used be elements internally. + Added macro to check for SUCCESS flowreturns. + API: GST_FLOW_CUSTOM_SUCCESS + API: GST_FLOW_CUSTOM_ERROR + API: GST_FLOW_IS_SUCCESS + * tests/check/gst/gstpad.c: (GST_START_TEST), (gst_pad_suite): + Added check for GstFlowReturn sanity. + +2006-05-23 09:40:14 +0000 Mark Nauwelaerts + + libs/gst/base/gstcollectpads.c: clear/reset segment info in FLUSH_STOP. + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_remove_pad), + (gst_collect_pads_event): + clear/reset segment info in FLUSH_STOP. + Fixes #336929. + +2006-05-22 16:30:34 +0000 Stefan Kost + + libs/gst/base/gstcollectpads.c: Flush queued buffer on _stop(), fixes playing again (#342454) + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_stop), + (gst_collect_pads_check_collected): + Flush queued buffer on _stop(), fixes playing again (#342454) + +2006-05-22 13:34:03 +0000 Thomas Vander Stichele + + tests/check/gst/gststructure.c: add a test for a complete structure + Original commit message from CVS: + * tests/check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + add a test for a complete structure + +2006-05-22 13:31:48 +0000 Thomas Vander Stichele + + * libs/gst/check/gstcheck.c: + debugging changes + Original commit message from CVS: + debugging changes + +2006-05-19 15:35:41 +0000 Tim-Philipp Müller + + docs/faq/: Some minor FAQ updates that won't change the fact that our FAQ is badly structured, full of information ha... + Original commit message from CVS: + * docs/faq/developing.xml: + * docs/faq/faq.xml: + * docs/faq/troubleshooting.xml: + * docs/faq/using.xml: + Some minor FAQ updates that won't change the fact that + our FAQ is badly structured, full of information hardly + anyone new to GStreamer needs to know and lacking lots + of information people constantly ask for. + +2006-05-19 13:46:10 +0000 Jan Schmidt + + gst/gstpad.c: Short-circuit gst_pad_set_caps if setting the existing caps pointer again, and avoid printing debug and... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_caps): + Short-circuit gst_pad_set_caps if setting the existing + caps pointer again, and avoid printing debug and + reffing/unreffing the caps. + * plugins/elements/gstqueue.c: (gst_queue_push_one): + There's actually no need to set the caps before pushing - + the acceptcaps method will handle it anyway. + +2006-05-19 10:29:07 +0000 Tim-Philipp Müller + + API: add gst_element_seek_simple() (#342238). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + * gst/gstutils.c: (gst_element_seek_simple): + * gst/gstutils.h: + API: add gst_element_seek_simple() (#342238). + +2006-05-18 14:25:00 +0000 Edward Hervey + + gst/gsttypefind.*: Added GST_TYPE_TYPE_FIND and gst_type_find_get_type() so a GType gets registered for GstTypeFind p... + Original commit message from CVS: + * gst/gsttypefind.c: (gst_type_find_get_type): + * gst/gsttypefind.h: + Added GST_TYPE_TYPE_FIND and gst_type_find_get_type() so a GType gets + registered for GstTypeFind pointers. This allows wrapping the structure + in bindings (i.e. gst-python). + +2006-05-18 14:01:03 +0000 Tim-Philipp Müller + + gst/gsttagsetter.c: Docs additions and fixes (see #339918). + Original commit message from CVS: + * gst/gsttagsetter.c: + Docs additions and fixes (see #339918). + +2006-05-18 09:07:55 +0000 Jan Schmidt + + plugins/elements/gstcapsfilter.c: The caps intersection algorithm can produce multiple copies of the caps. Until that... + Original commit message from CVS: + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + The caps intersection algorithm can produce multiple copies of the + caps. Until that is fixed, we need to simplify the result to be + sure whether the allowed caps are fixed or not. + * plugins/elements/gstqueue.c: (gst_queue_init), + (gst_queue_bufferalloc), (gst_queue_acceptcaps), + (gst_queue_push_one): + Proxied buffer alloc should not set the caps on the source pad. + When pushing buffers, we always accept the caps change that triggers. + This prevents negotiation errors caused by caps changing mid-stream + and then being refused on our source pad (because upstream is now + refusing those caps). + +2006-05-18 08:48:21 +0000 Tim-Philipp Müller + + tests/examples/helloworld/helloworld.c: Must plug audioconvert and audioresample between decoder and audio sink. + Original commit message from CVS: + * tests/examples/helloworld/helloworld.c: (main): + Must plug audioconvert and audioresample between decoder + and audio sink. + +2006-05-17 14:18:12 +0000 Jan Schmidt + + * ChangeLog: + Mention bug fixed by previous commit + Original commit message from CVS: + Mention bug fixed by previous commit + +2006-05-17 14:01:33 +0000 Jan Schmidt + + gst/gstregistryxml.c: Allow empty strings for some of the plugin fields so we don't drop valid plugin entries that we... + Original commit message from CVS: + * gst/gstregistryxml.c: (read_string), (load_pad_template), + (load_feature), (load_plugin): + Allow empty strings for some of the plugin fields so we don't + drop valid plugin entries that were written out correctly. + +2006-05-17 13:40:20 +0000 Sébastien Moutte + + gst/gstregistryxml.c: Use g_remove and g_rename instead of remove and rename that don't handle utf8 characters. renam... + Original commit message from CVS: + * gst/gstregistryxml.c: (gst_registry_xml_write_cache): + Use g_remove and g_rename instead of remove and rename that don't + handle utf8 characters. rename was failing for users who had specific + characters in their name then the registry was built at each gstreamer init. + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstcoreelements.dsp: + * win32/vs6/libgstreamer.dsp: + Use a debug version of libxml2 (libxml2D.lib,libxml2D.dll) for DEBUG build + of libgstreamer and clean unused libraries in project links settings. + +2006-05-17 09:24:34 +0000 Edward Hervey + + plugins/elements/gstqueue.c: The queue is not responsible for pushing an EOS when receiving a fatal flow error. It's ... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_push_one): + The queue is not responsible for pushing an EOS when receiving a fatal + flow error. It's up to the real element driving the pipeline to do that. + +2006-05-16 17:15:02 +0000 Edward Hervey + + plugins/elements/gstqueue.c: The queue was posting a non-needed GST_MESSAGE_ERROR when pushing a buffer returned a fa... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_push_one): + The queue was posting a non-needed GST_MESSAGE_ERROR when pushing a + buffer returned a fatal error. It should just send an EOS and stop + it's task. + Upstream elements will then properly receive the GST_FLOW_UNEXPECTED + when pushing buffers on the queue and will be able to handle the event. + +2006-05-16 16:10:38 +0000 Tim-Philipp Müller + + docs/manual/: Fix typos and minor errors in sample code (#341856). + Original commit message from CVS: + * docs/manual/basics-bins.xml: + * docs/manual/basics-init.xml: + Fix typos and minor errors in sample code (#341856). + +2006-05-16 13:31:32 +0000 Wim Taymans + + docs/design/part-qos.txt: Fix indexes in formulas to make more sense. + Original commit message from CVS: + * docs/design/part-qos.txt: + Fix indexes in formulas to make more sense. + +2006-05-15 11:54:22 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't report POSITION based on clock time if sync is disabled in a sink. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position): + Don't report POSITION based on clock time if sync is + disabled in a sink. + +2006-05-15 08:16:09 +0000 Tim-Philipp Müller + + gst/gstobject.h: Add cast to make compiler happy - refcount variable was a gint in GstObject but is a guint in GObjec... + Original commit message from CVS: + * gst/gstobject.h: + Add cast to make compiler happy - refcount variable was a gint + in GstObject but is a guint in GObject and g_atomic_int_get() + wants a gint *. + +2006-05-14 23:23:56 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/parse/Makefile.am: + fix parallel make + Original commit message from CVS: + fix parallel make + +2006-05-14 21:18:23 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update config.h + Original commit message from CVS: + update config.h + +2006-05-14 21:16:58 +0000 Thomas Vander Stichele + + * gst/gstpad.h: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2006-05-14 21:16:50 +0000 Thomas Vander Stichele + + * docs/random/streamheader: + some streamheader updates + Original commit message from CVS: + some streamheader updates + +2006-05-14 19:25:51 +0000 Tim-Philipp Müller + + Minor docs fixes. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.h: + Minor docs fixes. + +2006-05-14 16:03:20 +0000 Jan Schmidt + + * common: + * configure.ac: + Back to CVS + Original commit message from CVS: + Back to CVS + +=== release 0.10.6 === + +2006-05-14 15:20:24 +0000 Jan Schmidt + + configure.ac: releasing 0.10.6, "Take the cannoli" + Original commit message from CVS: + 2006-05-14 Jan Schmidt + * configure.ac: + releasing 0.10.6, "Take the cannoli" + +2006-05-14 15:18:02 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-05-13 17:50:11 +0000 Tim-Philipp Müller + + tools/gst-launch.c: Fix use of uninitialized variable in the hypothetical case that some broken plugin creates a GST_... + Original commit message from CVS: + * tools/gst-launch.c: (print_tag): + Fix use of uninitialized variable in the hypothetical + case that some broken plugin creates a GST_TAG_IMAGE + tag containing a NULL buffer (#341667). + +2006-05-12 16:50:37 +0000 Tim-Philipp Müller + + tools/gst-launch.c: Print something more intelligible for image tags when using the -t switch (#341556). + Original commit message from CVS: + * tools/gst-launch.c: (print_tag): + Print something more intelligible for image tags when + using the -t switch (#341556). + +2006-05-12 14:53:49 +0000 Thomas Vander Stichele + + Makefile.am: updates for win32 + Original commit message from CVS: + * Makefile.am: + updates for win32 + * configure.ac: + define GST_MAJORMINOR so we have it available in win32/common/config.h + Possibly remove it from our Makefile.am files later + * win32/common/config.h: + * win32/common/config.h.in: + added GST_MAJORMINOR + * win32/common/gstenumtypes.c: (register_gst_resource_error): + * win32/common/gstversion.h: + updated + +2006-05-12 13:42:54 +0000 Thomas Vander Stichele + + * docs/random/streamheader: + adding notes about current implementation and ideas about streamheader + Original commit message from CVS: + adding notes about current implementation and ideas about streamheader + +2006-05-12 10:50:42 +0000 Sébastien Moutte + + win32/MANIFEST: Update win32 files listing. + Original commit message from CVS: + * win32/MANIFEST: + Update win32 files listing. + * win32/common/gstversion.h: + Add GST_MAJORMINOR definition. + * win32/common/libgstreamer.def: + Add new exported functions. + +2006-05-12 09:28:22 +0000 Michael Smith + + gst/gstplugin.c: If an so file has no plugin entry point, unload the module. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + If an so file has no plugin entry point, unload the module. + +2006-05-11 19:07:48 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Don't forget to signal the _chain or _loop function when the queue size or thresholds ch... + Original commit message from CVS: + * plugins/elements/gstqueue.c: (gst_queue_chain), (gst_queue_loop), + (gst_queue_set_property): + Don't forget to signal the _chain or _loop function + when the queue size or thresholds change since that might + cause them to make progres again. + +2006-05-11 18:10:34 +0000 Stefan Kost + + G_OBJECT_CLASS macro usage batch cleanup, fixes #337747 for core + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_class_init): + * gst/gstindex.c: (gst_index_class_init): + * gst/gstobject.c: (gst_object_class_init): + * gst/gstpad.c: (gst_pad_class_init): + * gst/gstpipeline.c: (gst_pipeline_class_init): + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init): + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_class_init): + * libs/gst/net/gstnetclientclock.c: + (gst_net_client_clock_class_init): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_class_init): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_class_init): + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init): + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init): + * plugins/elements/gstfdsink.c: (gst_fd_sink_class_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init): + * plugins/elements/gstfilesink.c: (gst_file_sink_class_init): + * plugins/elements/gstfilesrc.c: (gst_file_src_class_init): + * plugins/elements/gstidentity.c: (gst_identity_class_init): + * plugins/elements/gsttee.c: (gst_tee_class_init): + * tests/old/examples/plugins/example.c: (gst_example_class_init): + * tests/old/testsuite/threads/signals.c: (gst_test_class_init): + G_OBJECT_CLASS macro usage batch cleanup, fixes #337747 for core + +2006-05-11 10:35:14 +0000 Wim Taymans + + gst/gstbuffer.c: Register subbufer along with the buffer type so that it does not accidentally gets registered from N... + Original commit message from CVS: + * gst/gstbuffer.c: (_gst_buffer_initialize): + Register subbufer along with the buffer type so that + it does not accidentally gets registered from N + different streaming threads in a non threadsafe way. + +2006-05-10 16:44:15 +0000 Tim-Philipp Müller + + gst/: Make gtk-doc generate docs for our inlined gst_buffer_ref(), gst_event_ref() and gst_message_ref() functions ag... + Original commit message from CVS: + * gst/gstbuffer.h: + * gst/gstevent.h: + * gst/gstmessage.h: + Make gtk-doc generate docs for our inlined gst_buffer_ref(), + gst_event_ref() and gst_message_ref() functions again + (ugly hack, please do fix if there's a better way besides + overrides.txt, which doesn't seem to work). + +2006-05-10 15:49:30 +0000 Thomas Vander Stichele + + libs/gst/check/gstcheck.h: add an assert for setting state to avoid lots of repetitive code in the future + Original commit message from CVS: + 2006-05-10 Thomas Vander Stichele + * libs/gst/check/gstcheck.h: + add an assert for setting state to avoid lots of repetitive code + in the future + +2006-05-10 15:38:53 +0000 Thomas Vander Stichele + + gst/gstvalue.c: fix a leak if no flags are set + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_serialize_flags): + fix a leak if no flags are set + * tests/check/gst/gstvalue.c: (GST_START_TEST): + fix leak in tests + +2006-05-10 15:00:32 +0000 Tim-Philipp Müller + + docs/manual/basics-pads.xml: Expand a bit on caps and filtered links and update examples that were still using the no... + Original commit message from CVS: + * docs/manual/basics-pads.xml: + Expand a bit on caps and filtered links and update + examples that were still using the no longer existing + gst_pad_link_filtered() (#338206). + +2006-05-10 14:51:33 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.*: No need to call _stop in _finalize. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize), + (gst_collect_pads_add_pad), (gst_collect_pads_remove_pad), + (gst_collect_pads_set_flushing), (gst_collect_pads_start), + (gst_collect_pads_stop): + * libs/gst/base/gstcollectpads.h: + No need to call _stop in _finalize. + Iterate the main pad list in _finalize. + Added some more debug. + Free lists and data in the right order. + Also free data whem doing _remove_pad when stopped for + backward compatibility protect ::started with PAD_LOCK as + well. + +2006-05-10 14:12:14 +0000 Thomas Vander Stichele + + gst/gststructure.c: add some comments rename a method so that it actually says what it does better + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_gtype_from_abbr), + (gst_structure_parse_value): + add some comments + rename a method so that it actually says what it does better + +2006-05-10 14:05:46 +0000 Thomas Vander Stichele + + gst/: make sure some essential types used by events are registered as part of gst_init() + Original commit message from CVS: + * gst/gstevent.c: (_gst_event_initialize): + * gst/gstformat.c: (_gst_format_initialize): + make sure some essential types used by events are registered + as part of gst_init() + * gst/gstvalue.c: (gst_value_serialize_flags): + if no flags are set, serialize them to a value that represents NONE + so that deserializing them works + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + add tests for serialization and deserialization of flags + +2006-05-10 13:53:48 +0000 Thomas Vander Stichele + + * docs/design/part-TODO.txt: + limit to 80 chars add note about changing divider for flags + Original commit message from CVS: + limit to 80 chars + add note about changing divider for flags + +2006-05-10 11:24:55 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.c: Update docs. + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_collect), + (gst_collect_pads_collect_range), (gst_collect_pads_available), + (gst_collect_pads_check_pads), (gst_collect_pads_check_collected), + (gst_collect_pads_event), (gst_collect_pads_chain): + Update docs. + Better debug info. + Catch and return errors from the collect function + Refuse data on eos pads. + +2006-05-10 10:26:55 +0000 Edward Hervey + + gst/gstinterface.h: GST_IMPLEMENTS_INTERFACE and GST_IS_IMPLEMENTS_INTERFACE use the normal + Original commit message from CVS: + * gst/gstinterface.h: + GST_IMPLEMENTS_INTERFACE and GST_IS_IMPLEMENTS_INTERFACE use the normal + GInterface type checking. + They were previously using non-defined macros. + +2006-05-09 20:47:23 +0000 Wim Taymans + + libs/gst/base/gstcollectpads.*: Clean up the mess that is collectpads, add comments and + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_init), + (gst_collect_pads_finalize), (gst_collect_pads_add_pad), + (gst_collect_pads_remove_pad), (gst_collect_pads_set_flushing), + (gst_collect_pads_start), (gst_collect_pads_stop), + (gst_collect_pads_peek), (gst_collect_pads_pop), + (gst_collect_pads_available), (gst_collect_pads_read), + (gst_collect_pads_flush), (gst_collect_pads_check_pads), + (gst_collect_pads_is_collected), (gst_collect_pads_event), + (gst_collect_pads_chain): + * libs/gst/base/gstcollectpads.h: + Clean up the mess that is collectpads, add comments and + FIXMEs where needed. + Maintain a separate pad list so we can add pads while + collecting the other ones. For this we need a new separate + lock (see comics). + Fix memory leak in finalize. + Refactor some weird code to set/unset pad flushing flags, mark + with comments. + Don't crash in _available, _read, _flush when we're EOS. + * tests/check/libs/.cvsignore: + Ignore adapter check binary. + +2006-05-09 19:14:55 +0000 Thomas Vander Stichele + + * gst/gstevent.h: + doc whitespace fixes + Original commit message from CVS: + doc whitespace fixes + +2006-05-09 17:58:35 +0000 Tim-Philipp Müller + + Const-ify GEnumValue arrays. + Original commit message from CVS: + * gst/gstindex.c: (gst_index_resolver_get_type): + * plugins/elements/gstfakesink.c: + (gst_fake_sink_state_error_get_type): + * plugins/elements/gstfakesrc.c: (gst_fake_src_data_get_type), + (gst_fake_src_sizetype_get_type), (gst_fake_src_filltype_get_type): + * plugins/elements/gstqueue.c: (queue_leaky_get_type): + Const-ify GEnumValue arrays. + +2006-05-09 13:23:06 +0000 Tim-Philipp Müller + + tests/check/gst/gstbuffer.c: Add test case for flags + gst_buffer_make_metadata_writable(). + Original commit message from CVS: + * tests/check/gst/gstbuffer.c: (GST_START_TEST): + Add test case for flags + gst_buffer_make_metadata_writable(). + +2006-05-09 12:01:32 +0000 Tim-Philipp Müller + + gst/gstbuffer.c: gst_buffer_make_metadata_writable() should maintain the buffer flags (those that make sense at least... + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_make_metadata_writable): + gst_buffer_make_metadata_writable() should maintain the + buffer flags (those that make sense at least) (see #340859). + +2006-05-09 10:53:18 +0000 Tim-Philipp Müller + + tools/: Fix up includes: need to include stdlib.h in tools.h for exit(). + Original commit message from CVS: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + * tools/tools.h: + Fix up includes: need to include stdlib.h in tools.h for exit(). + +2006-05-09 10:02:51 +0000 Tim-Philipp Müller + + gst/gsttaglist.*: API: add GST_TAG_IMAGE tag (#340721). + Original commit message from CVS: + * gst/gsttaglist.c: (_gst_tag_initialize): + * gst/gsttaglist.h: + API: add GST_TAG_IMAGE tag (#340721). + +2006-05-08 17:12:08 +0000 Wim Taymans + + gst/gstquery.c: Added some docs for the segment query. + Original commit message from CVS: + * gst/gstquery.c: + Added some docs for the segment query. + +2006-05-08 17:03:13 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Always push non-flushing serialized events in the streaming thread. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_loop), (gst_base_src_change_state): + Always push non-flushing serialized events in the streaming + thread. + +2006-05-08 15:53:12 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + * gst/gstutils.c: + * libs/gst/dataprotocol/dataprotocol.c: + * libs/gst/dataprotocol/dataprotocol.h: + whitespace, comment, doc fixup + Original commit message from CVS: + whitespace, comment, doc fixup + +2006-05-08 15:52:28 +0000 Thomas Vander Stichele + + gst/gsterror.c: Add a missing error string. + Original commit message from CVS: + * gst/gsterror.c: (_gst_stream_errors_init): + Add a missing error string. + +2006-05-08 14:55:26 +0000 Jan Schmidt + + libs/gst/base/gstbasesink.c: Add applied_rate to the debug + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment): + Add applied_rate to the debug + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek): + Copy applied_rate into the outgoing NEWSEGMENT event + +2006-05-08 11:49:43 +0000 Philippe Rouquier + + libs/gst/base/gstbasesink.c: call ::unlock before taking the PREROLL_LOCK so we can safely handle elements that lock ... + Original commit message from CVS: + Patch by: Philippe Rouquier + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_flushing), + (gst_base_sink_change_state): + call ::unlock before taking the PREROLL_LOCK so we can safely + handle elements that lock in ::render. + Fixes #340174. + +2006-05-08 11:43:19 +0000 Edward Hervey + + autogen.sh: Darwin's libtoolize is in fact called glibtoolize. + Original commit message from CVS: + * autogen.sh: (CONFIGURE_DEF_OPT): + Darwin's libtoolize is in fact called glibtoolize. + Adding glibtoolize to the list of accepted names for libtoolize. + +2006-05-08 11:35:29 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Unify error handling, don't post an error message when a push() returns EOS but perform o... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_loop): + Unify error handling, don't post an error message + when a push() returns EOS but perform our normal EOS + handling code. Fixes #340772. + +2006-05-08 09:52:33 +0000 Wim Taymans + + docs/design/part-overview.txt: Make upsteam/downstream concepts more clear. + Original commit message from CVS: + * docs/design/part-overview.txt: + Make upsteam/downstream concepts more clear. + Give an example of serialized/non-serialized events. + * docs/design/part-events.txt: + * docs/design/part-streams.txt: + Mention applied_rate. + * docs/design/part-trickmodes.txt: + Mention applied rate, flesh out some more use cases. + * gst/gstevent.c: (gst_event_new_new_segment), + (gst_event_parse_new_segment), (gst_event_new_new_segment_full), + (gst_event_parse_new_segment_full), (gst_event_new_tag), + (gst_event_parse_tag), (gst_event_new_buffer_size), + (gst_event_parse_buffer_size), (gst_event_new_qos), + (gst_event_parse_qos), (gst_event_parse_seek), + (gst_event_new_navigation): + * gst/gstevent.h: + Add applied_rate field to NEWSEGMENT event. + API: gst_event_new_new_segment_full() + API: gst_event_parse_new_segment_full() + * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_seek), + (gst_segment_set_newsegment), (gst_segment_set_newsegment_full), + (gst_segment_to_stream_time), (gst_segment_to_running_time): + * gst/gstsegment.h: + Add applied_rate to GstSegment structure. + Make calculation of stream_time and running_time more correct + wrt rate/applied_rate. + Add some more docs. + API: GstSegment::applied_rate field + API: gst_segment_set_newsegment_full(); + * libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment), + (gst_base_sink_get_sync_times), (gst_base_sink_get_position): + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_eventfunc), + (gst_base_transform_handle_buffer): + Parse and use applied_rate in the GstSegment field. + * tests/check/gst/gstevent.c: (GST_START_TEST): + Add check for applied_rate field. + * tests/check/gst/gstsegment.c: (GST_START_TEST), + (gstsegments_suite): + Add more checks for various GstSegment operations. + +2006-05-08 09:16:01 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Store the sync time of the buffer end position separatly in a new variable eos_rtime so ... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_do_sync), (gst_base_sink_chain_unlocked), + (gst_base_sink_get_position), (gst_base_sink_change_state): + Store the sync time of the buffer end position separatly in a + new variable eos_rtime so we can properly sync the EOS event. + Fixes #340697. + Fix the docs for gst_base_sink_set_qos_enabled(). + Don't set segment start to invalid value when we receive a + non TIME newsegment. + get closer to handling position reporting for negative rates + correctly. + +2006-05-07 19:57:48 +0000 Stefan Kost + + gst/gstcaps.c: Docs about how to print caps for debug purposes. + Original commit message from CVS: + * gst/gstcaps.c: + Docs about how to print caps for debug purposes. + * gst/gstpadtemplate.c: (gst_static_pad_template_get): + use gst_caps_make_writable instead of gst_caps_copy, Fixes #340608 + +2006-05-06 21:45:27 +0000 Stefan Kost + + gst/gstelement.c: use full enum names and preprend a '%' in docs strings to make recent gtk-doc turn that into a link + Original commit message from CVS: + * gst/gstelement.c: + use full enum names and preprend a '%' in docs strings to make recent + gtk-doc turn that into a link + +2006-05-05 21:44:57 +0000 Tim-Philipp Müller + + docs/manual/: Some typo fixes, some additions, some clarifications. + Original commit message from CVS: + * docs/manual/basics-bins.xml: + * docs/manual/basics-bus.xml: + * docs/manual/basics-pads.xml: + Some typo fixes, some additions, some clarifications. + +2006-05-05 17:45:41 +0000 Tim-Philipp Müller + + tools/: Use the string passed to g_option_context_new() for what it's intended for - the program name is already prin... + Original commit message from CVS: + * tools/gst-inspect.c: (main): + * tools/gst-launch.c: (main): + * tools/gst-run.c: (main): + * tools/gst-typefind.c: (main): + * tools/gst-xmlinspect.c: (main): + Use the string passed to g_option_context_new() for + what it's intended for - the program name is already + printed elsewhere. + +2006-05-05 17:07:42 +0000 Tim-Philipp Müller + + tools/: Add back --version command line option (#340460). + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-inspect.c: (main): + * tools/gst-launch.c: (main): + * tools/gst-xmlinspect.c: (main): + * tools/tools.h: + Add back --version command line option (#340460). + * tools/gst-typefind.c: (have_type_handler), (typefind_file), (main): + Add --version option and use GOption for argument parsing; refactor a + bit; accept directories as arguments and recurse into them; lastly, + print a decent error message when things go wrong. + +2006-05-05 14:38:01 +0000 Maciej Katafiasz + + * ChangeLog: + * docs/manual/basics-bins.xml: + * docs/manual/basics-elements.xml: + Don't mention GstThread (#340611) + Original commit message from CVS: + Don't mention GstThread (#340611) + Update link to GObject tutorial (#340607) + +2006-05-05 14:27:31 +0000 Wim Taymans + + gst/: Add note about refcounting and miniobject/buffer writeability to docs. Fixes #340604 + Original commit message from CVS: + * gst/gstbuffer.h: + * gst/gstminiobject.c: + Add note about refcounting and miniobject/buffer writeability + to docs. Fixes #340604 + * gst/gstelementfactory.h: + Added some explanation about @klass. + +2006-05-05 14:09:21 +0000 Maciej Katafiasz + + * ChangeLog: + * docs/manual/intro-motivation.xml: + * docs/manual/manual.xml: + Avoid CORBA & Bonobo references (#340598) + Original commit message from CVS: + Avoid CORBA & Bonobo references (#340598) + +2006-05-05 13:53:28 +0000 Maciej Katafiasz + + * ChangeLog: + * docs/manual/basics-bus.xml: + * docs/manual/basics-pads.xml: + Fix up some inaccuracies and omissions in ADM (#340609) + Original commit message from CVS: + Fix up some inaccuracies and omissions in ADM (#340609) + +2006-05-05 12:53:33 +0000 Maciej Katafiasz + + * ChangeLog: + * gst/gstghostpad.c: + Small typo in docs (#340625) + Original commit message from CVS: + Small typo in docs (#340625) + +2006-05-05 09:01:52 +0000 Tim-Philipp Müller + + gst/parse/Makefile.am: Make 'make -j' proof (see #340698). + Original commit message from CVS: + * gst/parse/Makefile.am: + Make 'make -j' proof (see #340698). + +2006-05-05 08:56:32 +0000 Tim-Philipp Müller + + configure.ac: Require GLib-2.8 here as well. + Original commit message from CVS: + * configure.ac: + Require GLib-2.8 here as well. + +2006-05-05 08:17:22 +0000 Wim Taymans + + gst/: Remove pre glib2.8 compatibility, fixes #340508 + Original commit message from CVS: + * gst/glib-compat.c: + * gst/gst.c: (init_pre): + * gst/gstobject.c: (gst_object_init), (gst_object_ref), + (gst_object_unref), (gst_object_replace), (gst_object_dispose), + (gst_object_dispatch_properties_changed): + * gst/gstobject.h: + * gst/gstregistryxml.c: (gst_registry_xml_read_cache): + * gst/gststructure.c: (gst_structure_set_valist): + * gst/gstvalue.c: (gst_date_get_type), (_gst_value_initialize): + Remove pre glib2.8 compatibility, fixes #340508 + +2006-05-04 18:14:31 +0000 Tim-Philipp Müller + + gst/gsttaglist.h: Mention type of tags in doc blurbs. + Original commit message from CVS: + * gst/gsttaglist.h: + Mention type of tags in doc blurbs. + +2006-05-04 16:34:20 +0000 Jan Schmidt + + gst/gstpad.c: Restore acceptcaps checking behaviour now that good plugins have been released. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_init), (gst_pad_configure_sink), + (gst_pad_configure_src), (gst_pad_push): + Restore acceptcaps checking behaviour now that good plugins have + been released. + +2006-05-04 15:20:14 +0000 James Andrewartha + + Make sure gstprivate.h and/or config.h are always included first, otherwise some of our defines (like _FILE_OFFSET_BI... + Original commit message from CVS: + Patch by: James Andrewartha + * gst/gst.c: + * gst/gstbus.c: + * gst/gstclock.c: + * gst/gstevent.c: + * gst/gstformat.c: + * gst/gstmessage.c: + * gst/gstparse.c: + * gst/gstquery.c: + * gst/gstutils.c: + * gst/parse/Makefile.am: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gsttypefindhelper.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + Make sure gstprivate.h and/or config.h are + always included first, otherwise some of our + defines (like _FILE_OFFSET_BITS) might be + redefined in the system headers. Fixes build + on opensolaris (#340016). + +2006-05-04 14:19:53 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: API: addition: gst_adapter_take_buffer() + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + API: addition: gst_adapter_take_buffer() + * libs/gst/base/gstadapter.c: (gst_adapter_push), + (gst_adapter_peek), (gst_adapter_take), (gst_adapter_take_buffer), + (gst_adapter_available_fast): + * libs/gst/base/gstadapter.h: + Prepare for optimizing the hell out of this hugely inefficient + piece of code. + Added gst_adapter_take_buffer() so we can at least start thinking + about subbuffering and merging. + Added some comments. + * tests/check/Makefile.am: + * tests/check/libs/adapter.c: (GST_START_TEST), + (gst_adapter_suite), (main): + Added GstAdapter check. + +2006-05-04 13:30:30 +0000 Wim Taymans + + docs/design/part-overview.txt: Fix some typos, add blurb about buffer flags. + Original commit message from CVS: + * docs/design/part-overview.txt: + Fix some typos, add blurb about buffer flags. + +2006-05-03 16:45:11 +0000 Thomas Vander Stichele + + docs/libs/gstreamer-libs-sections.txt: make sure GstBaseTransformClass shows up in the docs + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + make sure GstBaseTransformClass shows up in the docs + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + move docs so gtk-doc picks it up now + +2006-05-03 16:42:08 +0000 Thomas Vander Stichele + + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + whitespace removal and width coercion + Original commit message from CVS: + whitespace removal and width coercion + +2006-05-03 16:40:57 +0000 Thomas Vander Stichele + + * Makefile.am: + whitespace moving + Original commit message from CVS: + whitespace moving + +2006-05-02 17:29:07 +0000 Stefan Kost + + docs/libs/gstreamer-libs-sections.txt: add missing symbols to docs + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + add missing symbols to docs + +2006-05-02 17:17:22 +0000 Stefan Kost + + libs/gst/base/gstcollectpads.c: back out the newsegment handling change, see #340060 for ongoing discussion + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_event): + back out the newsegment handling change, see #340060 for ongoing + discussion + +2006-04-29 23:15:40 +0000 Tim-Philipp Müller + + tools/gst-run.c: Fix wrong g_file_test() usage (see glib docs for why it doesn't work); fix typo in error message. Fi... + Original commit message from CVS: + * tools/gst-run.c: (get_candidates), (main): + Fix wrong g_file_test() usage (see glib docs for why it doesn't + work); fix typo in error message. Fixes #340079. + +2006-04-29 00:38:06 +0000 Thomas Vander Stichele + + * docs/plugins/tmpl/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2006-04-29 00:36:47 +0000 Thomas Vander Stichele + + move upload.mak to common + Original commit message from CVS: + * common/Makefile.am: + * docs/Makefile.am: + * docs/faq/Makefile.am: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + * docs/manual/Makefile.am: + * docs/plugins/Makefile.am: + * docs/pwg/Makefile.am: + * docs/slides/Makefile.am: + * docs/upload.mak: + * common/upload.mak: + move upload.mak to common + +2006-04-29 00:35:48 +0000 Thomas Vander Stichele + + * docs/random/moving-plugins: + add more notes on moving + Original commit message from CVS: + add more notes on moving + +2006-04-29 00:33:44 +0000 Thomas Vander Stichele + + tests/check/gst/gstghostpad.c: add more asserts on refcounts do more cleanup at end of tests fix test leaks showing i... + Original commit message from CVS: + 2006-04-29 Thomas Vander Stichele + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + add more asserts on refcounts + do more cleanup at end of tests + fix test leaks showing in FC5 + +2006-04-28 22:56:28 +0000 Stefan Kost + + plugins/elements/gsttypefindelement.c: reverted wrong change and reflowed code to avoid others falling into this trap + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + reverted wrong change and reflowed code to avoid others falling into + this trap + +2006-04-28 20:55:33 +0000 Stefan Kost + + libs/gst/base/gstcollectpads.c: fix changelog entry about last collectpads change, add notes about proper fix + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_event): + fix changelog entry about last collectpads change, + add notes about proper fix + +2006-04-28 20:47:23 +0000 Stefan Kost + + gst/: only write out registry if it has changed, fixes #338339 + Original commit message from CVS: + * gst/gst.c: + * gst/gstregistry.c: (gst_registry_scan_path_level), + (gst_registry_scan_path): + * gst/gstregistry.h: + only write out registry if it has changed, fixes #338339 + +2006-04-28 20:44:21 +0000 Stefan Kost + + gst/: only write out registry if it has changed, fixes #338339 + Original commit message from CVS: + * gst/gst.c: + * gst/gstregistry.c: (gst_registry_scan_path_level), + (gst_registry_scan_path): + * gst/gstregistry.h: + only write out registry if it has changed, fixes #338339 + +2006-04-28 18:55:17 +0000 Stefan Kost + + make GstElementDetails const + Original commit message from CVS: + * gst/gstbin.c: + * gst/gstpipeline.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + make GstElementDetails const + +2006-04-28 18:48:38 +0000 Stefan Kost + + libs/gst/base/: more detailed debug and formatting cleanup + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_event): + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_base_init), + (gst_collect_pads_is_collected), (gst_collect_pads_event): + more detailed debug and formatting cleanup + +2006-04-28 17:52:13 +0000 Stefan Kost + + gst/gstutils.c: cleanup double code + Original commit message from CVS: + * gst/gstutils.c: (gst_element_link_pads): + cleanup double code + +2006-04-28 17:33:41 +0000 Stefan Kost + + libs/gst/controller/gstcontroller.c: some little tuning + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controller_sync_values): + some little tuning + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + a new test for live value handling + +2006-04-28 15:51:56 +0000 Wim Taymans + + * ChangeLog: + Give credit to Tapi Paavola for last patch + Original commit message from CVS: + Give credit to Tapi Paavola for last patch + +2006-04-28 15:48:50 +0000 Wim Taymans + + gst/gstutils.c: Added some more docs. + Original commit message from CVS: + * gst/gstutils.c: (push_and_ref): + Added some more docs. + Fix refcount issue whith gst_element_found_tags() helper + function. Fixes #338335 + * tests/check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + Added testsuite for gst_element_found_tags(). + +2006-04-28 13:51:00 +0000 Michael Smith + + gst/gstvalue.c: Avoid NULL dereference when trying to serialize flags containing invalid values. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_serialize_flags): + Avoid NULL dereference when trying to serialize flags containing + invalid values. + +2006-04-28 13:44:20 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + small doc fix + Original commit message from CVS: + small doc fix + +2006-04-28 13:43:03 +0000 Michael Smith + + plugins/elements/gsttypefindelement.c: If we get EOS before any data is accumulated, don't use uninitialised local va... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + If we get EOS before any data is accumulated, don't use + uninitialised local variables. + +2006-04-28 13:40:15 +0000 Michael Smith + + libs/gst/dataprotocol/dataprotocol.c: Fixes in reading/writing events over GDP (not currently used?) - dereferencing ... + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), + (gst_dp_event_from_packet): + Fixes in reading/writing events over GDP (not currently used?) - + dereferencing NULL events for unknown/invalid event types, memory + leak, and change g_warning to GST_WARNING. + +2006-04-28 13:25:58 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: When frame dropping is enabled, we should not ignore frames without a duration. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_is_too_late), + (gst_base_sink_do_render_stats), (gst_base_sink_render_object), + (gst_base_sink_get_position), (gst_base_sink_change_state): + When frame dropping is enabled, we should not ignore frames + without a duration. + Update some documentation. + +2006-04-28 13:18:41 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Documentation updates. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_send_event), (gst_base_src_change_state): + Documentation updates. + +2006-04-28 13:16:03 +0000 Wim Taymans + + plugins/elements/gstfdsink.c: handle EAGAIN, EINTR and short writes correctly. Also clean up some error cases, avoid ... + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_render), + (gst_fd_sink_check_fd), (gst_fd_sink_update_fd): + handle EAGAIN, EINTR and short writes correctly. Also clean + up some error cases, avoid a deadlock on bad file descriptors and + use GST_DEBUG_OBJECT. + Fixes #339843 + +2006-04-28 13:13:23 +0000 Wim Taymans + + gst/gstvalue.c: Don't try to serialize a GValue with a NULL buffer. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_serialize_buffer), + (gst_value_deserialize_buffer): + Don't try to serialize a GValue with a NULL buffer. + Fixes #339821. + * tests/check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Added check for serialisation of NULL buffers. + +2006-04-28 13:10:07 +0000 Wim Taymans + + gst/gstminiobject.c: Taking a NULL miniobject is valid, fix the case where we try to unref the NULL miniobject. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_value_take_mini_object): + Taking a NULL miniobject is valid, fix the case where + we try to unref the NULL miniobject. + +2006-04-28 13:05:19 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update win32 config.h + Original commit message from CVS: + update win32 config.h + +2006-04-28 13:04:07 +0000 Stefan Kost + + gst/gstbin.c: Update docs. + Original commit message from CVS: + Patch by: Stefan Kost + * gst/gstbin.c: (gst_bin_handle_message_func): + Update docs. + Don't leak bin refcount when a state recalc is + in progress and we delay another one #339808. + +2006-04-28 12:58:15 +0000 Wim Taymans + + docs/design/part-TODO.txt: Mention QoS as an ongoing work item. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Mention QoS as an ongoing work item. + * docs/design/part-buffering.txt: + New doc about buffering that needs to be fleshed out + at some point. + * docs/design/part-qos.txt: + More QoS policy for decoders/demuxers/transforms + * docs/design/part-trickmodes.txt: + Small update. + +2006-04-28 10:56:04 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.5 === + +2006-04-28 10:53:33 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * win32/common/config.h: + releasing 0.10.5 + Original commit message from CVS: + releasing 0.10.5 + +2006-04-28 09:48:09 +0000 Thomas Vander Stichele + + * docs/plugins/gstreamer-plugins.signals: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * docs/upload.mak: + fix upload.mak; should move to common + Original commit message from CVS: + fix upload.mak; should move to common + +2006-04-28 09:20:26 +0000 Thomas Vander Stichele + + * win32/MANIFEST: + adding missing dsp files + Original commit message from CVS: + adding missing dsp files + +2006-04-26 13:54:48 +0000 Thomas Vander Stichele + + * configure.ac: + * win32/common/config.h: + prerelease + Original commit message from CVS: + prerelease + +2006-04-22 21:34:23 +0000 Wim Taymans + + gst/: Fix internal data flow errors. Fixes #338711. + Original commit message from CVS: + patch by: Wim Taymans + * gst/gstpad.c: (gst_pad_init), (gst_pad_configure_sink), + (gst_pad_configure_src), (gst_pad_push): + * gst/gstpipeline.c: (gst_pipeline_init): + Fix internal data flow errors. Fixes #338711. + +2006-04-12 11:58:43 +0000 Wim Taymans + + tests/check/gst/gstelement.c: Don't leak the factory. + Original commit message from CVS: + * tests/check/gst/gstelement.c: (GST_START_TEST): + Don't leak the factory. + +2006-04-12 11:06:44 +0000 Thomas Vander Stichele + + * po/bg.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_TW.po: + updated translations + Original commit message from CVS: + updated translations + +2006-04-12 11:04:36 +0000 Thomas Vander Stichele + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + update libtool versioning + Original commit message from CVS: + update libtool versioning + +2006-04-12 10:57:26 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + * win32/common/config.h: + prerelease + Original commit message from CVS: + prerelease + +2006-04-12 10:28:53 +0000 Tim-Philipp Müller + + libs/gst/controller/gstcontroller.c: Free allocated GstTimedValues when freeing list nodes. + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_unset), + (gst_controller_unset_all): + Free allocated GstTimedValues when freeing list nodes. + Should fix leaks 'make check-valgrind' complains about. + * win32/common/libgstcontroller.def: + Add gst_controller_unset_all. + +2006-04-12 10:15:12 +0000 Thomas Vander Stichele + + * ChangeLog: + fix ChangeLog + Original commit message from CVS: + fix ChangeLog + +2006-04-11 21:07:26 +0000 Stefan Kost + + Added new method _unset_all() and fixed _unset() + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gstcontroller.c: (gst_controller_unset), + (gst_controller_unset_all): + * libs/gst/controller/gstcontroller.h: + Added new method _unset_all() and fixed _unset() + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Added two testcases for new and fixed method + +2006-04-11 18:43:04 +0000 Tim-Philipp Müller + + libs/gst/net/gstnettimepacket.c: MSG_DONTWAIT is not defined on Cygwin, so work around that (fixes #317048). + Original commit message from CVS: + * libs/gst/net/gstnettimepacket.c: (gst_net_time_packet_send): + MSG_DONTWAIT is not defined on Cygwin, so work + around that (fixes #317048). + +2006-04-11 14:48:34 +0000 Christian Schaller + + * gstreamer.spec.in: + fix versioning macro + Original commit message from CVS: + fix versioning macro + +2006-04-11 11:47:39 +0000 Wim Taymans + + gst/gstelementfactory.c: Some cleanups. + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_register), + (gst_element_factory_create), (gst_element_factory_make): + Some cleanups. + Fixed a FIXME. + Updated docs (Fixes #131079) + * gst/gstpluginfeature.c: (gst_plugin_feature_load): + Small cleanups. + * tests/check/gst/gstelement.c: (GST_START_TEST), + (gst_element_suite): + Added testcase for elementfactory class field. + +2006-04-10 10:46:44 +0000 Wim Taymans + + gst/gstsegment.c: Added some more docs. + Original commit message from CVS: + * gst/gstsegment.c: + Added some more docs. + * libs/gst/base/gstbasesink.c: (gst_base_sink_perform_qos), + (gst_base_sink_reset_qos): + Calculate more accurate rate values. + +2006-04-09 16:57:34 +0000 Sébastien Moutte + + gst/gst_private.h: add a new #ifdef to use __declspec(dllimport) only for other modules and not for gstreamer core + Original commit message from CVS: + * gst/gst_private.h: + add a new #ifdef to use __declspec(dllimport) only for + other modules and not for gstreamer core + * gst/gstbasesink.c: (gst_base_sink_perform_qos): + use gst_guint64_to_gdouble for conversion + * win32/common/libgstreamer.def: + add new exported functions + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstcontroller.dsp: + * win32/vs6/libgstcoreelements.dsp: + * win32/vs6/libgstdataprotocol.dsp: + * win32/vs6/libgstnet.dsp: + update project files + +2006-04-08 20:57:31 +0000 Stefan Kost + + Fix #337365 (g_type_class_ref <-> g_type_class_peek_parent) + Original commit message from CVS: + * gst/gstbuffer.c: (gst_subbuffer_class_init): + * gst/gstclock.c: (gst_clock_class_init): + * gst/gstelement.c: (gst_element_class_init): + * gst/gstindex.c: (gst_index_class_init): + * gst/gstindexfactory.c: (gst_index_factory_class_init): + * gst/gstobject.c: (gst_object_class_init), + (gst_signal_object_class_init): + * gst/gstpad.c: (gst_pad_class_init): + * gst/gstpadtemplate.c: (gst_pad_template_class_init): + * gst/gstpluginfeature.c: (gst_plugin_feature_class_init): + * gst/gstregistry.c: (gst_registry_class_init): + * gst/gstsystemclock.c: (gst_system_clock_class_init): + * gst/gsttask.c: (gst_task_class_init): + * gst/gstxml.c: (gst_xml_class_init): + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init): + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_loop): + * libs/gst/controller/gstcontroller.c: + (_gst_controller_class_init): + * plugins/elements/gstfdsrc.c: (gst_fd_src_class_init): + * plugins/indexers/gstfileindex.c: (gst_file_index_class_init): + * plugins/indexers/gstmemindex.c: (gst_mem_index_class_init): + * tests/old/examples/plugins/example.c: (gst_example_class_init): + * tests/old/testsuite/threads/signals.c: (gst_test_class_init): + Fix #337365 (g_type_class_ref <-> g_type_class_peek_parent) + +2006-04-08 18:11:56 +0000 Tim-Philipp Müller + + gst/gstpad.c: Must set peer pads before calling the link function, otherwise a task started from a link function migh... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_link): + Must set peer pads before calling the link function, otherwise + a task started from a link function might get a flow-not-linked + result when trying to push because the other thread where the + linking happens hasn't had a chance to set the peers yet. This + might happen for example when a queue gets linked to a downstream + element, as queue starts a streaming task when its source pad + gets linked. Happens in real life when playing back flac/musepack + files in playbin (#332390). + +2006-04-08 18:05:16 +0000 Stefan Kost + + Fix broken GObject macros + Original commit message from CVS: + * gst/gstindex.h: + * gst/gstxml.h: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstpushsrc.h: + Fix broken GObject macros + +2006-04-07 15:19:08 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Initialize start and stop times, thanks valgrind. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Initialize start and stop times, thanks valgrind. + +2006-04-07 14:50:06 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Be a bit nicer to badly behaving upstream elements that expect us to deal with non TIME ... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Be a bit nicer to badly behaving upstream elements that expect + us to deal with non TIME segments and timestamps (such as fakesrc + in the testsuite). + +2006-04-07 14:02:12 +0000 Wim Taymans + + gst/gstbus.c: Small documentation clarification about the signal watch. + Original commit message from CVS: + * gst/gstbus.c: + Small documentation clarification about the signal watch. + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times), + (gst_base_sink_wait_clock), (gst_base_sink_do_sync), + (gst_base_sink_perform_qos), (gst_base_sink_reset_qos), + (gst_base_sink_do_render_stats), (gst_base_sink_render_object), + (gst_base_sink_get_position_last), + (gst_base_sink_get_position_paused), (gst_base_sink_change_state): + Convert and store timestamps in stream time and running time, the + raw timestamps are not usefull, also document this better. + Use different window sizes for good and bad QoS observations so + we react to badness a little quicker. + Keep track of the amount of rendered and dropped buffers. + Send QoS timestamps in running time. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_sink_eventfunc), + (gst_base_transform_handle_buffer): + Compare QoS timestamps against running time. + +2006-04-06 17:36:27 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + add gnonlin + Original commit message from CVS: + add gnonlin + +2006-04-06 15:46:04 +0000 Tim-Philipp Müller + + gst/gstpad.c: Typo fixes in docs. + Original commit message from CVS: + * gst/gstpad.c: + Typo fixes in docs. + +2006-04-06 15:07:12 +0000 Michael Smith + + gst/gstpad.c: Use g_value_get_object() instead of g_value_dup_gst_object(), to avoid double-reffing the pad template ... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_property): + Use g_value_get_object() instead of g_value_dup_gst_object(), + to avoid double-reffing the pad template (which we then sink, + so this worked previously if (and only if) the pad template + was floating. + * gst/gstpadtemplate.c: (gst_pad_template_init), + (gst_pad_template_pad_created): + Never return floating references to pad templates, create + them as initially-sunken. + Document an extra function (and make this stop sinking our + pad template, since that is now guaranteed to do nothing, + since we created it sunken). + * gst/gstghostpad.c: + Fix docs typo. + +2006-04-06 11:27:24 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Add some newlines. + Original commit message from CVS: + * gst/gstinfo.c: (__gst_in_valgrind): + Add some newlines. + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain): + Don't leak buffer caps. + +2006-04-06 10:38:54 +0000 Michael Smith + + gst/parse/grammar.y: Fix a leak in parse-launch for any source-or-sink named element references used. + Original commit message from CVS: + * gst/parse/grammar.y: + Fix a leak in parse-launch for any source-or-sink named element + references used. + * tests/check/pipelines/parse-launch.c: (expected_fail_pipe): + Unref the pipeline if it exists after we've failed parsing. + +2006-04-05 15:46:00 +0000 Michael Smith + + gst/gstpipeline.c: When we create a pipeline bus, initially create it in flushing mode. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_init): + When we create a pipeline bus, initially create it in flushing mode. + Fixes leaks in at least one test, and makes a new pipeline work the + same as one that has gone to READY and then back to NULL. + * gst/gstelement.c: + Typo fix in docs. + +2006-04-05 15:12:39 +0000 Michael Smith + + tests/check/gst/gstghostpad.c: Unref a pad we reffed. + Original commit message from CVS: + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + Unref a pad we reffed. + * tests/check/gst/gstutils.c: (GST_START_TEST): + Unref bins + +2006-04-05 13:18:29 +0000 Michael Smith + + gst/gstquery.c: Fix leaking GValues in queries, as shown by valgrind/testsuite. + Original commit message from CVS: + * gst/gstquery.c: (gst_query_set_formats), + (gst_query_set_formatsv): + Fix leaking GValues in queries, as shown by valgrind/testsuite. + +2006-04-05 12:11:20 +0000 Michael Smith + + tests/check/generic/sinks.c: Fix a variety of memleaks in sinks check, which are only sometimes shown by running the ... + Original commit message from CVS: + * tests/check/generic/sinks.c: (GST_START_TEST): + Fix a variety of memleaks in sinks check, which are only sometimes + shown by running the tests under valgrind (weird?). + +2006-04-05 11:04:19 +0000 Jan Schmidt + + docs/version.entities.in: Fix the substituted entity name after thomas' changes on the weekend. + Original commit message from CVS: + * docs/version.entities.in: + Fix the substituted entity name after thomas' changes on the + weekend. + +2006-04-05 10:31:20 +0000 Zaheer Abbas Merali + + gst/gstinfo.c: Use printf instead of + Original commit message from CVS: + 2006-04-05 Zaheer Abbas Merali + * gst/gstinfo.c: (__gst_in_valgrind): Use printf instead of + VALGRIND_PRINTF + +2006-04-05 10:26:29 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_set_blocked_async): More debug. libs/gst/base/gstbasetransform.c + Original commit message from CVS: + 2006-04-05 Andy Wingo + * gst/gstpad.c (gst_pad_set_blocked_async): More debug. + * libs/gst/base/gstbasetransform.c + (gst_base_transform_sink_eventfunc): When resetting our segment on + FLUSH_STOP, also update the flag saying we haven't seen a + newsegment. + +2006-04-04 18:02:07 +0000 Paolo Borelli + + gst/gstplugin.c: minor clean-ups: G_DEFINE_TYPE already takes care of the parent_class stuff, no need to do it twice.... + Original commit message from CVS: + Patch by: Paolo Borelli + * gst/gstplugin.c: (gst_plugin_finalize), (gst_plugin_class_init), + (gst_plugin_check_license): + minor clean-ups: G_DEFINE_TYPE already takes care of the + parent_class stuff, no need to do it twice. Mark array of + license strings as constant. (#337103) + +2006-04-04 17:54:30 +0000 Michael Smith + + tools/gst-inspect.c: Free the right plugin list; fixes a memory leak. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_list): + Free the right plugin list; fixes a memory leak. + +2006-04-04 15:45:36 +0000 Mark Nauwelaerts + + plugins/elements/gstfilesink.c: Don't error out on empty buffers (#336945). + Original commit message from CVS: + Patch by: Mark Nauwelaerts + * plugins/elements/gstfilesink.c: (gst_file_sink_render): + Don't error out on empty buffers (#336945). + +2006-04-04 14:58:50 +0000 Jan Schmidt + + Documentation updates. Make BaseSink and BaseSrc docs contain the class structure so that people can actually see the... + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * gst/gsttaglist.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + Documentation updates. Make BaseSink and BaseSrc docs contain the + class structure so that people can actually see the prototypes for + virtual functions they're supposed to be overriding. + +2006-04-04 08:55:44 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: More debug info; when skipping typefinding, send cached events in all cases. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain): + More debug info; when skipping typefinding, send cached + events in all cases. + +2006-04-03 17:05:31 +0000 Michael Smith + + * gst/gstpad.c: + Fix typo in docs. + Original commit message from CVS: + Fix typo in docs. + +2006-04-03 08:59:52 +0000 Thomas Vander Stichele + + * common: + * docs/faq/gst-uninstalled: + * win32/common/config.h: + update win32 common dir; update uninstalled script + Original commit message from CVS: + update win32 common dir; update uninstalled script + +2006-04-01 15:30:49 +0000 Thomas Vander Stichele + + * common: + * configure.ac: + disable use of AS_LIBTOOL_TAGS, it doesn't work correctly + Original commit message from CVS: + disable use of AS_LIBTOOL_TAGS, it doesn't work correctly + +2006-04-01 09:41:43 +0000 Thomas Vander Stichele + + configure.ac: use new AS_VERSION and AS_NANO macros + Original commit message from CVS: + * configure.ac: + use new AS_VERSION and AS_NANO macros + * gst/gst-i18n-lib.h: + * gst/gst.c: + * gst/gsterror.c: + * gst/gstversion.h.in: + * win32/common/config.h: + * win32/common/config.h.in: + update accordingly + +2006-03-31 15:26:04 +0000 Michael Smith + + plugins/elements/gsttypefindelement.c: Do not typefind content if the buffers already have caps. and the right thing ... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain): + Do not typefind content if the buffers already have caps. + Neccesary for icydemux (#333657), and the right thing to do anyway. + +2006-03-30 16:36:12 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: More QoS measurements as described in the design doc. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_finalize), (gst_base_sink_set_qos_enabled), + (gst_base_sink_is_qos_enabled), (gst_base_sink_do_sync), + (gst_base_sink_record_qos_observation), + (gst_base_sink_perform_qos), (gst_base_sink_reset_qos), + (gst_base_sink_is_too_late), (gst_base_sink_render_object), + (gst_base_sink_change_state): + More QoS measurements as described in the design doc. + Get rid of ringbuffer with observations, running average is + more simple and equally good. + Calculates valid proportion now. + Added beginning of flood measurement. + +2006-03-29 13:45:15 +0000 Wim Taymans + + Small documentation updates and additions. + Original commit message from CVS: + * docs/design/part-qos.txt: + * gst/gstclock.c: + Small documentation updates and additions. + +2006-03-29 13:39:05 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Perform the EOS logic when we reach the segment stop position. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_finalize), + (gst_base_src_send_event), (gst_base_src_loop), + (gst_base_src_change_state): + Perform the EOS logic when we reach the segment stop position. + Fix compilation on gcc4.1 + +2006-03-29 11:02:33 +0000 Tommi Myöhänen + + plugins/elements/gstqueue.*: In queue, when EOS is received, if minimum threshold > max_size - current_level, there i... + Original commit message from CVS: + Patch by Tommi Myöhänen + * plugins/elements/gstqueue.c: (gst_queue_init), + (gst_queue_locked_flush), (gst_queue_handle_sink_event), + (gst_queue_set_property): + * plugins/elements/gstqueue.h: + In queue, when EOS is received, if minimum threshold > max_size - + current_level, there is chance that queue blocks forever in conditional item + del wait. This is because the queue is not emptied completely due to minimum + threshold. + Here is another approach. Instead of setting cur_levels to max in EOS, just + zero all minimum threshold levels. This should make sure that queue gives out + all data. When going to READY (stop) state, just reset the original minimum + threshold levels. + Fixes #336336. + +2006-03-29 10:33:19 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.*: When typefinding is done in push mode, we should cache events we receive durin... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (stop_typefinding), + (gst_type_find_element_handle_event), + (gst_type_find_element_send_cached_events), + (gst_type_find_element_change_state): + * plugins/elements/gsttypefindelement.h: + When typefinding is done in push mode, we should cache + events we receive during typefinding instead of just + dropping them (e.g. newsegment, custom events from + dvdreadsrc etc.) and then send them out once we've + determined the type of the stream (and decodebin + has had a chance to plug in a decoder/demuxer). + +2006-03-27 18:38:49 +0000 Wim Taymans + + docs/design/part-qos.txt: First QoS ideas. + Original commit message from CVS: + * docs/design/part-qos.txt: + First QoS ideas. + +2006-03-27 11:48:10 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Handle element seek correctly when we are streaming. + Original commit message from CVS: + Inspired by a patch of: Lutz Mueller + * libs/gst/base/gstbasesrc.c: (gst_base_src_finalize), + (gst_base_src_send_event), (gst_base_src_change_state): + Handle element seek correctly when we are streaming. + Fixes #326998. + +2006-03-24 18:38:12 +0000 Michael Smith + + docs/faq/gst-uninstalled: Set up LD_LIBRARY_PATH to point at all the gstreamer libs. This will allow you to correctly... + Original commit message from CVS: + * docs/faq/gst-uninstalled: + Set up LD_LIBRARY_PATH to point at all the gstreamer libs. This will + allow you to correctly run intalled applications built against old core, using plugins that require updated core (e.g. running + installed totem against a full uninstalled gstreamer stack) + +2006-03-24 17:29:25 +0000 Thomas Vander Stichele + + * ChangeLog: + add API: marker in ChangeLog + Original commit message from CVS: + add API: marker in ChangeLog + +2006-03-24 17:10:46 +0000 Stefan Kost + + libs/gst/base/gstcollectpads.c: more debug details + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_is_collected): + more debug details + +2006-03-24 11:02:42 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Rearrange the order of the methods so that related methods are grouped together in s... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Rearrange the order of the methods so that related methods + are grouped together in sections. + +2006-03-24 10:44:17 +0000 Stefan Kost + + gst/gstelement.c: Little clarification in the docs + Original commit message from CVS: + * gst/gstelement.c: + Little clarification in the docs + +2006-03-24 10:38:20 +0000 Stefan Kost + + docs/README: formatting fix + Original commit message from CVS: + * docs/README: + formatting fix + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + GST_ELEMENT_DETAILS formatting + +2006-03-24 09:48:33 +0000 Wim Taymans + + libs/gst/base/gstbasesink.h: Only add fields, not insert or we break ABI. + Original commit message from CVS: + * libs/gst/base/gstbasesink.h: + Only add fields, not insert or we break ABI. + +2006-03-23 18:51:05 +0000 Tim-Philipp Müller + + win32/common/: Update, add recently added functions. + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + Update, add recently added functions. + +2006-03-23 18:45:02 +0000 Tim-Philipp Müller + + API: add some new utility functions: + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: (gst_pad_query_peer_position), + (gst_pad_query_peer_duration), (gst_pad_query_peer_convert): + * gst/gstutils.h: + API: add some new utility functions: + - gst_pad_query_peer_position + - gst_pad_query_peer_duration + - gst_pad_query_peer_convert + +2006-03-23 16:32:41 +0000 Wim Taymans + + * ChangeLog: + Forgot to mention the previous commit fixed #326311 + Original commit message from CVS: + Forgot to mention the previous commit fixed #326311 + +2006-03-23 16:20:40 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Decouple max-lateness and the fact that QoS messages are generated with a new property (... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_finalize), + (gst_base_sink_set_qos_enabled), (gst_base_sink_is_qos_enabled), + (gst_base_sink_set_property), (gst_base_sink_get_property), + (gst_base_sink_commit_state), (gst_base_sink_get_sync_times), + (gst_base_sink_wait_clock), (gst_base_sink_do_sync), + (gst_base_sink_add_qos_observation), (gst_base_sink_send_qos), + (gst_base_sink_perform_qos), (gst_base_sink_reset_qos), + (gst_base_sink_is_too_late), (gst_base_sink_render_object), + (gst_base_sink_preroll_object), (gst_base_sink_event), + (gst_base_sink_chain_unlocked), (gst_base_sink_get_position_last), + (gst_base_sink_get_position_paused), (gst_base_sink_get_position), + (gst_base_sink_query), (gst_base_sink_change_state): + Decouple max-lateness and the fact that QoS messages are generated + with a new property (qos). + Add vmethod so subclasses can be notified of ASYNC playing + state changes. + Collect timestamp start and stop to report better current + position in EOS/PLAYING/PAUSED/READY/NULL. + Refactor QoS/frame dropping and other measurements. + API: GstBaseSrc::qos + * libs/gst/base/gstbasesink.h: + Added Private struct. + API: gst_base_sink_set_qos_enabled + API: gst_base_sink_is_qos_enabled + +2006-03-23 11:54:51 +0000 Tim-Philipp Müller + + gst/gstregistryxml.c: If compiling against GLib-2.8 or newer, try to read the registry file using GMappedFile first b... + Original commit message from CVS: + * gst/gstregistryxml.c: (gst_registry_xml_read_cache): + If compiling against GLib-2.8 or newer, try to read the + registry file using GMappedFile first before falling back + to fopen() + fread() (#332151). + +2006-03-22 18:25:04 +0000 Wim Taymans + + gst/gstinfo.c: Disable debugging unless explicitly activated. + Original commit message from CVS: + * gst/gstinfo.c: (gst_debug_set_active), + (gst_debug_category_set_threshold): + Disable debugging unless explicitly activated. + Fixes #335480. + +2006-03-22 13:10:16 +0000 Wim Taymans + + gst/gstelement.c: Cleanup the error case. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_set_locked_state), + (gst_element_dispose): + Cleanup the error case. + * gst/gstobject.c: (gst_object_dispose): + print a critical when some object was disposed with + a parent, also revive the object since it might + crash the parent. + +2006-03-22 09:03:10 +0000 Tim-Philipp Müller + + tools/gst-launch.1.in: Fix another typo. + Original commit message from CVS: + * tools/gst-launch.1.in: + Fix another typo. + +2006-03-21 19:27:15 +0000 Thomas Vander Stichele + + disable some tests when we don't have a registry + Original commit message from CVS: + * configure.ac: + * tests/check/Makefile.am: + disable some tests when we don't have a registry + * tests/check/gst/gstutils.c: (gst_utils_suite): + don't build the part that needs parsing + +2006-03-21 17:25:22 +0000 Thomas Vander Stichele + + gst/Makefile.am + Original commit message from CVS: + * gst/Makefile.am + * tests/examples/Makefile.am: + fix --disable-parse build + +2006-03-21 17:24:30 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer.types: + the .in file is in cvs + Original commit message from CVS: + the .in file is in cvs + +2006-03-21 15:42:02 +0000 Tim-Philipp Müller + + tools/gst-feedback.1.in: Fix typo: s/feeback/feedback/ (#133494). + Original commit message from CVS: + * tools/gst-feedback.1.in: + Fix typo: s/feeback/feedback/ (#133494). + +2006-03-21 15:04:20 +0000 Tim-Philipp Müller + + tools/: Add FILES section and correct entry about GST_REGISTRY_PATH environment variable (#133495; #133494). + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-launch.1.in: + Add FILES section and correct entry about GST_REGISTRY_PATH + environment variable (#133495; #133494). + +2006-03-21 14:41:58 +0000 Tim-Philipp Müller + + tools/: Remove gst-md5sum and man page (the md5sink element required was removed ages ago) + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-md5sum.1.in: + * tools/gst-md5sum.c: + Remove gst-md5sum and man page (the md5sink element + required was removed ages ago) + +2006-03-21 14:24:41 +0000 Tim-Philipp Müller + + gst/gststructure.c: Make sure that string fields in structures/taglists contain valid UTF-8 - we don't want to pass r... + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_id_set_value): + Make sure that string fields in structures/taglists + contain valid UTF-8 - we don't want to pass rubbish to + applications because of a buggy plugin (cp. #334167). + +2006-03-21 14:14:49 +0000 Edward Hervey + + Series of fixes for dereferenced pointers that gcc 4.1 complains about. + Original commit message from CVS: + reviewed by: + * gst/gstbin.c: (gst_bin_dispose), (gst_bin_provide_clock_func), + (gst_bin_handle_message_func): + * gst/gstclock.c: (gst_clock_dispose), (gst_clock_set_master): + * gst/gstelement.c: (gst_element_set_clock), (gst_element_dispose), + (gst_element_set_bus_func): + * gst/gstghostpad.c: (gst_proxy_pad_dispose): + * gst/gstminiobject.c: (gst_value_set_mini_object), + (gst_value_take_mini_object): + * gst/gstpad.c: (gst_pad_set_pad_template): + * gst/gstpipeline.c: (gst_pipeline_dispose), + (gst_pipeline_use_clock), (gst_pipeline_auto_clock): + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_pop), + (gst_collect_pads_chain): + * libs/gst/net/gstnettimeprovider.c: + (gst_net_time_provider_set_property): + Series of fixes for dereferenced pointers that gcc 4.1 complains about. + It's in fact all issues with gst_*object_replace(). + +2006-03-21 13:55:44 +0000 Loïc Minier + + pkgconfig/: Use @CHECK_LIBS@ here instead of hard-coding -lcheck (#334109). + Original commit message from CVS: + Patch by: Loïc Minier + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + Use @CHECK_LIBS@ here instead of hard-coding -lcheck (#334109). + +2006-03-21 13:50:52 +0000 Edward Hervey + + gst/: gst_[buffer|event|message]_ref() macros are replaced by a static inline functions because gcc-4.1 will about if... + Original commit message from CVS: + * gst/gstbuffer.h: + * gst/gstevent.h: + * gst/gstmessage.h: + gst_[buffer|event|message]_ref() macros are replaced by a static + inline functions because gcc-4.1 will about if the return value + isn't used. + * tests/check/gst/gstevent.c: (event_probe): + gst_event_ref now has to be given a GstEvent* , fix check accordingly. + +2006-03-20 16:47:35 +0000 Jan Schmidt + + * docs/plugins/tmpl/.gitignore: + Remove irritating file that keeps breaking my checkouts + Original commit message from CVS: + Remove irritating file that keeps breaking my checkouts + +2006-03-20 16:45:15 +0000 Jan Schmidt + + gst/gstutils.h: Add G_UNLIKELY to our boilerplate to optimise the 'already registered the type' case. (Closes: #33519... + Original commit message from CVS: + * gst/gstutils.h: + Add G_UNLIKELY to our boilerplate to optimise the 'already registered + the type' case. (Closes: #335195 for now). In the future, when we + depend on GLib 2.10, we could also intern the type name using + g_intern_static_string() + +2006-03-20 10:56:08 +0000 Wim Taymans + + gst/gstbin.c: Position query should also take max of all streams. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_handle_message_func), + (bin_query_max_init), (bin_query_position_fold), + (bin_query_position_done), (gst_bin_query): + Position query should also take max of all streams. + +2006-03-20 09:28:41 +0000 Wim Taymans + + plugins/elements/gstfakesrc.c: Fix leaks in fakesrc. + Original commit message from CVS: + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_finalize): + Fix leaks in fakesrc. + * tests/check/pipelines/parse-launch.c: (GST_START_TEST): + Fix leaks in the testcase. + +2006-03-19 21:39:21 +0000 Sébastien Moutte + + gst/gst_private.h: add win32 specific import decoration(__declspec(dllimport)) for all extern GstDebugCategory * vari... + Original commit message from CVS: + * gst/gst_private.h: + add win32 specific import decoration(__declspec(dllimport)) + for all extern GstDebugCategory * variables + * win32/common/libgstbase.def: + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + Add some exports, remove empty lines + * win32/common/libgstdataprotocol.def: + * win32/common/libgstdataprotocol.dsp: + * win32/common/libgstnet.def: + * win32/common/libgstnet.dsp: + new project files and exportation files added + +2006-03-19 16:05:23 +0000 Wim Taymans + + tests/check/libs/basesrc.c: Use proper return value for probe. + Original commit message from CVS: + * tests/check/libs/basesrc.c: (eos_event_counter): + Use proper return value for probe. + +2006-03-17 19:27:51 +0000 Wim Taymans + + gst/gstpad.c: Don't leak buffers, caps and pads on negotiation errors. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_alloc_buffer_full), + (gst_pad_push): + Don't leak buffers, caps and pads on negotiation errors. + +2006-03-16 15:33:55 +0000 Stefan Kost + + docs/faq/: Faq review and update. + Original commit message from CVS: + * docs/faq/cvs.xml: + * docs/faq/dependencies.xml: + * docs/faq/developing.xml: + * docs/faq/faq.xml: + * docs/faq/general.xml: + * docs/faq/getting.xml: + * docs/faq/legal.xml: + * docs/faq/troubleshooting.xml: + * docs/faq/using.xml: + Faq review and update. + +2006-03-16 10:18:27 +0000 Jan Schmidt + + gst/gstpad.c: Don't pound the cpu to pieces by checking get_caps when accept_caps is called with the same caps as the... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_alloc_buffer_full), + (gst_pad_push): + Don't pound the cpu to pieces by checking get_caps when accept_caps + is called with the same caps as the pad already has. + Use GST_DEBUG_OBJECT when outputting caps change information. + +2006-03-15 20:17:40 +0000 Wim Taymans + + gst/gstclock.c: Fix docs. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_class_init): + Fix docs. + +2006-03-15 16:29:02 +0000 Jan Schmidt + + gst/gstbuffer.h: Documentation fix. + Original commit message from CVS: + * gst/gstbuffer.h: + Documentation fix. + * gst/gstpad.c: (gst_pad_init), (gst_pad_acceptcaps_default), + (gst_pad_accept_caps), (gst_pad_configure_sink), + (gst_pad_configure_src), (gst_pad_chain), (gst_pad_push): + Make the default acceptcaps behaviour be to check the requested + caps against the gst_pad_get_caps output. + Ensure that gst_pad_accept_caps is used to check caps when a pad + doesn't have a setcaps function, so that pads automatically refuse + caps that they don't allow in their pad template. (Fixes #332986) + When a buffer with attached caps is pushed, ensure that the source + pad receives those caps even if the element didn't call + gst_pad_set_caps first. + +2006-03-15 16:22:26 +0000 Wim Taymans + + libs/gst/base/gstadapter.c: Add some docs. + Original commit message from CVS: + * libs/gst/base/gstadapter.c: + Add some docs. + +2006-03-15 15:57:51 +0000 Tim-Philipp Müller + + win32/common/: Add a whole bunch of missing functions (#334434). + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstcontroller.def: + * win32/common/libgstreamer.def: + Add a whole bunch of missing functions (#334434). + +2006-03-14 19:36:05 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Better debug info when we receive a segment event. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_configure_segment), + (gst_base_sink_get_sync_times), (gst_base_sink_wait_clock), + (gst_base_sink_do_sync), (gst_base_sink_do_qos): + Better debug info when we receive a segment event. + Reorganize a bit so we can pass the get_times() results around. + Use the segment format when calculating the running time. + Don't do QoS is sync is disabled or we have no clock or the + element does not want us to sync to the clock. + Don't drop buffers if QoS is disabled for now. + +2006-03-14 19:28:20 +0000 Wim Taymans + + gst/gstclock.c: Marked the stats property as unimplemented so people don't get wild ideas. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_class_init), (do_linear_regression): + Marked the stats property as unimplemented so people don't get + wild ideas. + Add debug message when regression goes wrong. + Added some more docs. + +2006-03-14 19:26:17 +0000 Wim Taymans + + gst/gstsegment.c: Return correct return type in case of errors. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_to_stream_time): + Return correct return type in case of errors. + +2006-03-14 19:16:45 +0000 Wim Taymans + + gst/gstformat.c: Don't segfault on invalid formats. + Original commit message from CVS: + * gst/gstformat.c: (gst_format_get_name), (gst_format_to_quark): + Don't segfault on invalid formats. + +2006-03-14 18:25:54 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesink.c: Can't use gst_segment_to_running_time() when the segment is not in GST_TIME_FORMAT (like... + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Can't use gst_segment_to_running_time() when the segment + is not in GST_TIME_FORMAT (like with filesink, for example). + Stops flac encoding pipelines from spewing critical warnings + at EOS (#331248). + +2006-03-14 16:32:58 +0000 Tim-Philipp Müller + + gst/gstpipeline.c: Add 'Since: 0.10.5' to gtk-doc blurb for added property. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_class_init): + Add 'Since: 0.10.5' to gtk-doc blurb for added property. + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + Don't try to typefind empty streams. + +2006-03-14 11:18:07 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Separate QoS calculation. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_do_sync), + (gst_base_sink_do_qos): + Separate QoS calculation. + Only drop buffers when lateness is bigger than the + duration of the buffer. + +2006-03-13 15:17:45 +0000 Wim Taymans + + gst/gstpipeline.c: Don't deadlock when reading properties. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_set_property), + (gst_pipeline_get_property), (do_pipeline_seek), + (gst_pipeline_change_state), (gst_pipeline_set_delay), + (gst_pipeline_get_delay): + Don't deadlock when reading properties. + +2006-03-13 11:27:57 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.*: Make basetransform virtual method for src events too. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_class_init), (gst_base_transform_init), + (gst_base_transform_sink_event), + (gst_base_transform_sink_eventfunc), + (gst_base_transform_src_event), (gst_base_transform_src_eventfunc), + (gst_base_transform_handle_buffer), (gst_base_transform_chain), + (gst_base_transform_set_property), + (gst_base_transform_get_property), + (gst_base_transform_change_state), (gst_base_transform_update_qos), + (gst_base_transform_set_qos_enabled), + (gst_base_transform_is_qos_enabled): + * libs/gst/base/gstbasetransform.h: + Make basetransform virtual method for src events too. + Handle QOS in basetransform. + API: gst_base_transform_update_qos + API: gst_base_transform_set_qos_enabled + API: gst_base_transform_is_qos_enabled + +2006-03-13 11:16:45 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Small cleanups. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_do_sync): + Small cleanups. + Use QOS debug category. + +2006-03-13 11:11:16 +0000 Wim Taymans + + plugins/elements/gstqueue.c: Very small doc update. + Original commit message from CVS: + * plugins/elements/gstqueue.c: + Very small doc update. + +2006-03-13 11:08:28 +0000 Wim Taymans + + gst/: Added QOS debug category + Original commit message from CVS: + * gst/gst_private.h: + * gst/gstinfo.c: (_gst_debug_init): + Added QOS debug category + +2006-03-13 11:04:38 +0000 Wim Taymans + + Documentation updates. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: (bin_bus_handler), (gst_bin_handle_message_func): + * gst/gstbin.h: + * gst/gstbus.c: (gst_bus_class_init): + * gst/gstbus.h: + * gst/gstclock.c: + * gst/gstelement.c: (gst_element_set_locked_state): + * gst/gstsegment.c: + Documentation updates. + * gst/gstpipeline.c: (gst_pipeline_get_type), + (gst_pipeline_class_init), (gst_pipeline_init), + (gst_pipeline_dispose), (gst_pipeline_set_property), + (gst_pipeline_get_property), (do_pipeline_seek), + (gst_pipeline_send_event), (gst_pipeline_change_state), + (gst_pipeline_provide_clock_func), (gst_pipeline_set_delay), + (gst_pipeline_get_delay): + * gst/gstpipeline.h: + Added methods for setting the delay. + API: gst_pipeline_set_delay + API: gst_pipeline_get_delay + Add pipeline debug category + Various cleanups. + Updated docs. + Don't reset stream time when seek failed. + +2006-03-13 10:32:26 +0000 Wim Taymans + + docs/design/: Documentation updates. + Original commit message from CVS: + * docs/design/draft-klass.txt: + * docs/design/part-clocks.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-overview.txt: + * docs/design/part-preroll.txt: + * docs/design/part-seeking.txt: + * docs/design/part-states.txt: + * docs/design/part-streams.txt: + Documentation updates. + +2006-03-12 20:44:46 +0000 Julien Moutte + + gst/gsttaglist.c: Fix rubbish docs that are encouraging us to leak strings... + Original commit message from CVS: + 2006-03-12 Julien MOUTTE + * gst/gsttaglist.c: Fix rubbish docs that are encouraging + us to leak strings... + +2006-03-12 20:40:19 +0000 Thomas Vander Stichele + + libs/gst/net/gstnettimeprovider.c: fix docs + Original commit message from CVS: + * libs/gst/net/gstnettimeprovider.c: + fix docs + * win32/common/config.h: + update + +2006-03-12 14:32:37 +0000 Julio M. Merino Vidal + + configure.ac: Don't check for libgnomeui (leftover from old examples that aren't built or disted any longer) (#334303). + Original commit message from CVS: + Patch by: Julio M. Merino Vidal + * configure.ac: + Don't check for libgnomeui (leftover from old examples + that aren't built or disted any longer) (#334303). + +2006-03-11 13:02:28 +0000 Tim-Philipp Müller + + plugins/elements/: Emit RESOURCE_NO_SPACE_LEFT error here as well when there's no space left on the device. + Original commit message from CVS: + * plugins/elements/gstfdsink.c: (gst_fd_sink_render): + * plugins/elements/gstfilesink.c: (gst_file_sink_render): + Emit RESOURCE_NO_SPACE_LEFT error here as well when + there's no space left on the device. + +2006-03-10 23:44:00 +0000 Tim-Philipp Müller + + gst/gstclock.h: Fix GST_CLOCK_TIME_IS_VALID signedness issues - we need to cast the input to GstClockTime before comp... + Original commit message from CVS: + * gst/gstclock.h: + Fix GST_CLOCK_TIME_IS_VALID signedness issues - we need + to cast the input to GstClockTime before comparing with + another GstClockTime value. + +2006-03-10 19:12:01 +0000 Thomas Vander Stichele + + * ChangeLog: + * libs/gst/base/gstbasesink.c: + log what we're waiting on + Original commit message from CVS: + log what we're waiting on + +2006-03-10 19:11:34 +0000 Thomas Vander Stichele + + * configure.ac: + back to head + Original commit message from CVS: + back to head + +=== release 0.10.4 === + +2006-03-10 19:03:13 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/manual/README: + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * docs/upload.mak: + * win32/common/config.h: + releasing 0.10.4 + Original commit message from CVS: + releasing 0.10.4 + +2006-03-10 15:30:27 +0000 Michael Smith + + libs/gst/dataprotocol/dataprotocol.c: Fix docs for dataprocotol to not get the return types completely wrong for a fe... + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + Fix docs for dataprocotol to not get the return types completely + wrong for a few functions. + +2006-03-09 19:00:21 +0000 Thomas Vander Stichele + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + * win32/common/config.h: + prereleasing + Original commit message from CVS: + prereleasing + +2006-03-09 16:53:05 +0000 Tim-Philipp Müller + + Add new API: gst_pipeline_set_auto_flush_bus() and gst_pipeline_get_auto_flush_bus() to disable automatic flushing of... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_init), (gst_pipeline_set_property), + (gst_pipeline_get_property), (gst_pipeline_change_state), + (gst_pipeline_set_auto_flush_bus), + (gst_pipeline_get_auto_flush_bus): + * gst/gstpipeline.h: + Add new API: gst_pipeline_set_auto_flush_bus() and + gst_pipeline_get_auto_flush_bus() to disable automatic + flushing of the pipeline's GstBus when going from READY + to NULL state (#332045). + +2006-03-09 12:08:54 +0000 Tim-Philipp Müller + + Add new API: gst_uri_has_protocol() (#333779). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: (gst_uri_has_protocol): + * gst/gsturi.h: + Add new API: gst_uri_has_protocol() (#333779). + +2006-03-09 11:45:14 +0000 Wim Taymans + + gst/gstclock.*: Review docs. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_entry_new), + (gst_clock_id_compare_func), (gst_clock_id_wait), + (gst_clock_id_wait_async), (gst_clock_id_unschedule), + (gst_clock_init), (gst_clock_get_internal_time), + (gst_clock_set_master), (do_linear_regression), + (gst_clock_add_observation), (gst_clock_set_property): + * gst/gstclock.h: + Review docs. + Small cleanups. + Fix a possible segfault when the window-size is made smaller. + Calculate jitter before performing the clock wait. Ideally + the clock implementation should calculate jitter but we need + API breakage for that. + * gst/gstsystemclock.c: (gst_system_clock_init): + Docs review. + * libs/gst/base/gstbasesink.c: (gst_base_sink_do_sync): + Remove leftover else + * tests/check/gst/gstsystemclock.c: (GST_START_TEST), + (gst_systemclock_suite): + Added check to test GST_CLOCK_DIFF. + +2006-03-09 10:46:35 +0000 Tim-Philipp Müller + + libs/gst/base/gsttypefindhelper.c: If we are provided with the size, we should implement + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (helper_find_get_length), + (gst_type_find_helper_get_range): + If we are provided with the size, we should implement + GstTypeFind::get_length, so that typefind functions who + want to can actually peek at the middle of a file. + +2006-03-08 14:30:40 +0000 Tim-Philipp Müller + + docs/manual/advanced-dataaccess.xml: Add some very very basic error checking. + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + Add some very very basic error checking. + * docs/pwg/appendix-checklist.xml: + Some updates to the list of things to check when writing an element. + +2006-03-08 13:44:55 +0000 Wim Taymans + + docs/design/part-element-transform.txt: Added some docs about the design of tranform elements. + Original commit message from CVS: + * docs/design/part-element-transform.txt: + Added some docs about the design of tranform elements. + * libs/gst/base/gstbasesrc.c: (gst_base_src_perform_seek), + (gst_base_src_loop), (gst_base_src_change_state): + Mark buffers with the DISCONT flag. + +2006-03-08 12:57:37 +0000 Michael Smith + + gst/: Rewrite registry-saving to avoid race conditions and check for failed writes. + Original commit message from CVS: + * gst/gstregistry.h: + * gst/gstregistryxml.c: (gst_registry_save), + (gst_registry_save_escaped), (gst_registry_xml_save_caps), + (gst_registry_xml_save_pad_template), + (gst_registry_xml_save_feature), (gst_registry_xml_save_plugin), + (gst_registry_xml_write_cache): + Rewrite registry-saving to avoid race conditions and check for + failed writes. + +2006-03-08 10:17:41 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c: Cleanups, separate normal flow from errors, add sensible + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps), + (gst_base_transform_transform_size), + (gst_base_transform_prepare_output_buffer), + (gst_base_transform_get_unit_size), + (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer), + (gst_base_transform_change_state): + Cleanups, separate normal flow from errors, add sensible + DEBUG lines. + Don't try to renegotiate when allocating an output buffer. + Also copy DISCONT buffer flag when copying a buffer. + Reset the transform after we finish streaming, not during. + +2006-03-08 09:46:54 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Use last buffer timestamp in qos message. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_do_sync): + Use last buffer timestamp in qos message. + +2006-03-07 17:06:53 +0000 Wim Taymans + + docs/pwg/: Applied patch from Christophe Fergeau, fixes #333416 + Original commit message from CVS: + * docs/pwg/advanced-tagging.xml: + * docs/pwg/building-pads.xml: + Applied patch from Christophe Fergeau, fixes #333416 + +2006-03-07 16:21:02 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: Added basesink new methods. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Added basesink new methods. + * gst/gstevent.c: + * gst/gstevent.h: + Docs updates. Flesh out the QoS docs. + * libs/gst/base/gstadapter.c: + Small doc clarification about ownership and flushing. + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_sync), + (gst_base_sink_get_sync), (gst_base_sink_set_max_lateness), + (gst_base_sink_get_max_lateness), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_do_sync): + * libs/gst/base/gstbasesink.h: + Added new methods to allow subclass to control max-lateness + and sync. + Generate very basic QoS events based on last sync observation. + Updated docs, fix typo, added some QoS blurb. + * libs/gst/base/gstbasesrc.c: + Remove obsolete _get_state() calls from docs. + +2006-03-07 15:14:51 +0000 Wim Taymans + + Fix #333669, Add pad accessor defines for GstBaseTransform + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstbasetransform.h: + Fix #333669, Add pad accessor defines for GstBaseTransform + Fix docs for GstBaseSrc. + +2006-03-07 15:08:57 +0000 Wim Taymans + + Small documentation fixes. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstvalue.c: + * libs/gst/base/gstbasetransform.h: + Small documentation fixes. + +2006-03-07 11:47:24 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Document thread-unsafety of gst_value_register_foo_func() when used at the same time as gst_value_foo... + Original commit message from CVS: + * gst/gstvalue.c: + Document thread-unsafety of gst_value_register_foo_func() + when used at the same time as gst_value_foo() (#322628). + +2006-03-07 10:19:25 +0000 Thomas Vander Stichele + + * README: + update README + Original commit message from CVS: + update README + +2006-03-07 09:28:44 +0000 Tim-Philipp Müller + + libs/gst/base/gstpushsrc.c: Push sources don't support pull mode by default. + Original commit message from CVS: + * libs/gst/base/gstpushsrc.c: (gst_push_src_class_init), + (gst_push_src_check_get_range): + Push sources don't support pull mode by default. + +2006-03-06 19:55:06 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.*: Add ::check_get_range() vfunc to GstBaseSrc (#332611), provide default implementation, an... + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_pad_check_get_range), + (gst_base_src_default_check_get_range): + * libs/gst/base/gstbasesrc.h: + Add ::check_get_range() vfunc to GstBaseSrc (#332611), + provide default implementation, and rename + gst_base_src_check_get_range() to + gst_base_src_pad_check_get_range() for clarity. + +2006-03-06 16:24:34 +0000 Thomas Vander Stichele + + * docs/random/styleguide: + style guide + Original commit message from CVS: + style guide + +2006-03-06 16:10:42 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Make property overridable. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init): + Make property overridable. + +2006-03-06 16:02:37 +0000 Wim Taymans + + libs/gst/base/gstbasesink.*: Make max-lateness a property. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_do_sync): + * libs/gst/base/gstbasesink.h: + Make max-lateness a property. + +2006-03-06 15:16:23 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Don't ever draw a frame that is >10ms late. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_wait_clock), + (gst_base_sink_do_sync), (gst_base_sink_render_object): + Don't ever draw a frame that is >10ms late. + +2006-03-06 14:51:36 +0000 Michael Smith + + gst/gstmessage.c: When copying a message, set the parent_refcount of the enclosed structure to point at the copy, not... + Original commit message from CVS: + * gst/gstmessage.c: (_gst_message_copy): + When copying a message, set the parent_refcount of the enclosed + structure to point at the copy, not the original message. + +2006-03-06 14:46:31 +0000 Christophe Fergeau + + gst/gstutils.h: Do proper cast here to make GST_BOILERPLATE_WITH_INTERFACE + Original commit message from CVS: + * gst/gstutils.h: + Do proper cast here to make GST_BOILERPLATE_WITH_INTERFACE + usable in c++ code (#333417; patch by: Christophe Fergeau) + +2006-03-06 14:34:49 +0000 Thomas Vander Stichele + + gst/gstclock.h: Show GST_CLOCK_TIME_NONE as 99:99:99.999999999 + Original commit message from CVS: + * gst/gstclock.h: + Show GST_CLOCK_TIME_NONE as 99:99:99.999999999 + +2006-03-06 14:23:56 +0000 Thomas Vander Stichele + + * docs/manual/appendix-quotes.xml: + add another quote + Original commit message from CVS: + add another quote + +2006-03-05 20:56:55 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasetransform.c: Make sure caps are writable before passing them to gst_caps_append(). + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_transform_caps): + Make sure caps are writable before passing them to + gst_caps_append(). + +2006-03-04 14:45:40 +0000 Tim-Philipp Müller + + gst/gsterror.h: Fix some minor docs errors. + Original commit message from CVS: + * gst/gsterror.h: + Fix some minor docs errors. + +2006-03-04 13:54:26 +0000 Ross Burton + + gst/gsterror.*: Add GST_RESOURCE_ERROR_NO_SPACE_LEFT (for #333352; + Original commit message from CVS: + * gst/gsterror.c: (_gst_resource_errors_init): + * gst/gsterror.h: + Add GST_RESOURCE_ERROR_NO_SPACE_LEFT (for #333352; + patch by: Ross Burton ). + +2006-03-03 16:58:51 +0000 Jan Schmidt + + gst/gst.c: Add a check and output a g_warning when GStreamer is built against GLib 2.6 but running against 2.8 or hig... + Original commit message from CVS: + * gst/gst.c: + Add a check and output a g_warning when GStreamer is built + against GLib 2.6 but running against 2.8 or higher, and vice + versa. (Closes: #323542) + +2006-03-03 15:32:30 +0000 Jan Schmidt + + gst/parse/parse.l: Commit patch for parse_launch syntax from #331255. Removes support for quoted strings and mimetype... + Original commit message from CVS: + * gst/parse/parse.l: + Commit patch for parse_launch syntax from #331255. Removes + support for quoted strings and mimetypes when writing filtered + caps. See the bug report for more details - I'm pretty sure this + obscure feature is not in use by _anyone_ anywhere. + With this simple change, the size of the gstreamer.so here + drops from 2193KB to 1565KB. + +2006-03-03 14:18:01 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.*: Use gst_type_find_helper_for_buffer() for chain-based typefinding. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.h: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_src_event), (start_typefinding), + (stop_typefinding), (gst_type_find_element_handle_event), + (gst_type_find_element_chain), + (gst_type_find_element_chain_do_typefinding): + Use gst_type_find_helper_for_buffer() for chain-based + typefinding. + +2006-03-03 11:42:40 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Deprecate "maximum" property (not only was it only taken into account for type... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_class_init), + (gst_type_find_element_set_property), + (gst_type_find_element_get_property): + Deprecate "maximum" property (not only was it only taken into + account for typefinding in push-mode anyway, it also was never + actually possible to set it in the first place because the + property was registered with the numeric property ID for the + "minimum" property). Register "maximum" property correctly, + for the sake of future copy'n'pasters. Remove some cruft + from property get/set functions. + +2006-03-03 11:27:02 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Use gst_type_find_helper_get_range() here, so we can honour the min-probabilit... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_activate): + Use gst_type_find_helper_get_range() here, so we + can honour the min-probability property and also emit + the signal with the correct probability of the found caps. + +2006-03-02 13:45:32 +0000 Tim-Philipp Müller + + New API: gst_type_find_helper_get_range() (#333042). + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gsttypefindhelper.c: (helper_find_peek), + (helper_find_suggest), (gst_type_find_helper_get_range), + (gst_type_find_helper): + * libs/gst/base/gsttypefindhelper.h: + New API: gst_type_find_helper_get_range() (#333042). + +2006-03-02 11:04:58 +0000 Michael Smith + + gst/gstregistryxml.c: Asserting on a failure to read part of the registry is Not Cool. + Original commit message from CVS: + * gst/gstregistryxml.c: (load_feature): + Asserting on a failure to read part of the registry is Not Cool. + Just log a warning and return NULL (which is already handled) + +2006-02-28 20:57:10 +0000 Sébastien Moutte + + win32/common/libgstbase.def: added export of gst_type_find_helper_for_buffer + Original commit message from CVS: + * win32/common/libgstbase.def: + added export of gst_type_find_helper_for_buffer + * win32/common/libgstbase.def: + added some exports : gst_bin_iterate_elements, gst_iterator_resync, + gst_ghost_pad_get_target + +2006-02-28 17:24:10 +0000 Wim Taymans + + docs/design/draft-klass.txt: We use Filter now. + Original commit message from CVS: + * docs/design/draft-klass.txt: + We use Filter now. + Added Connector to mark elements that are only used to + allow pipeline connections. + Moved Debug to extra feature since most of them are + functionally something else. + +2006-02-28 17:03:32 +0000 Wim Taymans + + docs/design/draft-klass.txt: Some updates and clarifications. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Some updates and clarifications. + +2006-02-28 15:54:06 +0000 Wim Taymans + + docs/design/draft-klass.txt: Proposal for klass field values. + Original commit message from CVS: + * docs/design/draft-klass.txt: + Proposal for klass field values. + * docs/design/part-streams.txt: + Start of a doc describing stream anatomy. + +2006-02-28 10:52:02 +0000 Wim Taymans + + gst/gstbin.c: Help the compiler a bit with type registration. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_handle_message_func): + Help the compiler a bit with type registration. + Use existing forward cod path instead of duplicating it when + handling a message. + * gst/gstbus.c: (gst_bus_get_type): + * gst/gstcaps.c: (gst_caps_get_type), (gst_static_caps_get_type): + * gst/gstchildproxy.c: (gst_child_proxy_get_type): + * gst/gstclock.c: (gst_clock_get_type): + * gst/gstelement.c: (gst_element_get_type), + * gst/gstelementfactory.c: (gst_element_factory_get_type): + * gst/gstindexfactory.c: (gst_index_factory_get_type): + * gst/gstminiobject.c: (gst_mini_object_get_type): + * gst/gstpad.c: (gst_pad_get_type): + * gst/gstsegment.c: (gst_segment_get_type): + * gst/gststructure.c: (gst_structure_get_type): + * gst/gstsystemclock.c: (gst_system_clock_get_type): + * gst/gsttask.c: (gst_task_get_type), (gst_task_join): + * gst/gstvalue.c: + Help compiler with type registration. + * plugins/elements/gstqueue.c: (gst_queue_handle_sink_event): + Small doc update. + +2006-02-27 20:01:53 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: When we get an EOS event and have not found a type yet (most likely because we... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + When we get an EOS event and have not found a type yet + (most likely because we had not yet accumulated + TYPE_FIND_MIN_SIZE of data yet), try to determine the + type given the data we have so far. Fixes typefinding + for very short streams again, most notably quicktime + redirections as used on Apple's trailer site (#331701). + +2006-02-27 19:45:31 +0000 Tim-Philipp Müller + + libs/gst/base/gsttypefindhelper.c: Try typefinding factories with the highest rank first. + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (type_find_factory_rank_cmp), + (gst_type_find_helper): + Try typefinding factories with the highest rank first. + +2006-02-27 19:19:40 +0000 Tim-Philipp Müller + + Add section for typefind helper and add documentation for the old and the new function. + Original commit message from CVS: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gsttypefindhelper.c: + Add section for typefind helper and add documentation + for the old and the new function. + +2006-02-27 18:43:26 +0000 Tim-Philipp Müller + + libs/gst/base/gsttypefindhelper.*: New API: gst_type_find_helper_for_buffer() (#332723). + Original commit message from CVS: + * libs/gst/base/gsttypefindhelper.c: (buf_helper_find_peek), + (buf_helper_find_suggest), (type_find_factory_rank_cmp), + (gst_type_find_helper_for_buffer): + * libs/gst/base/gsttypefindhelper.h: + New API: gst_type_find_helper_for_buffer() (#332723). + +2006-02-27 15:43:10 +0000 Loïc Minier + + Patch from Loïc Minier to prevent CVS directories getting disted. + Original commit message from CVS: + * configure.ac: + * docs/Makefile.am: + * docs/slides/Makefile.am: + Patch from Loïc Minier to prevent CVS directories getting disted. + +2006-02-27 12:10:47 +0000 Christian Schaller + + * gstreamer.spec.in: + update + Original commit message from CVS: + update + +2006-02-27 11:01:06 +0000 Tim-Philipp Müller + + gst/gstcaps.c: Use the REFCOUNTING category for caps refcounting. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_ref), (gst_caps_unref): + Use the REFCOUNTING category for caps refcounting. + +2006-02-26 19:20:51 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: This should be 0 not GST_CLOCK_TIME_NONE (see #331701). + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (stop_typefinding): + This should be 0 not GST_CLOCK_TIME_NONE (see #331701). + +2006-02-26 14:42:29 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Use gst_pad_check_pull_range() before _activate_pull() to avoid unnecessary op... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_activate): + Use gst_pad_check_pull_range() before _activate_pull() + to avoid unnecessary open/close (see #331690). + +2006-02-24 16:54:27 +0000 Tim-Philipp Müller + + gst/gstutils.c: Docs enhancement: make it crystal clear what the gst_pad_add_*_probe() callbacks should look like. + Original commit message from CVS: + * gst/gstutils.c: + Docs enhancement: make it crystal clear what the + gst_pad_add_*_probe() callbacks should look like. + +2006-02-24 10:57:42 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.c: Document how applications can stop recording from live sources (see #330996). + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: + Document how applications can stop recording from + live sources (see #330996). + +2006-02-23 18:06:31 +0000 Tim-Philipp Müller + + Ignore more stuff. + Original commit message from CVS: + * docs/gst/tmpl/.cvsignore: + * docs/plugins/tmpl/.cvsignore: + * tests/check/gst/.cvsignore: + * tests/check/libs/.cvsignore: + * tests/check/pipelines/.cvsignore: + Ignore more stuff. + +2006-02-23 17:39:20 +0000 Tim-Philipp Müller + + tests/check/: ... and add some tests for the base source EOS stuff. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/basesrc.c: (eos_event_counter), + (basesrc_eos_events_pull), (basesrc_eos_events_push), + (basesrc_eos_events_push_live_op), (basesrc_eos_events_pull_live_op), + (gst_basesrc_suite), (main): + ... and add some tests for the base source EOS stuff. + +2006-02-23 16:56:18 +0000 Tim-Philipp Müller + + tests/check/gst/gstutils.c: Test case originally showed the problem fixed below, but was then amended. Add checks bac... + Original commit message from CVS: + * tests/check/gst/gstutils.c: (test_buffer_probe_n_times): + Test case originally showed the problem fixed below, + but was then amended. Add checks back at the place + where they used to be. + +2006-02-23 16:24:36 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.*: Don't unconditionally send EOS when going from PAUSED to + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_loop), + (gst_base_src_activate_push), (gst_base_src_activate_pull), + (gst_base_src_change_state): + * libs/gst/base/gstbasesrc.h: + Don't unconditionally send EOS when going from PAUSED to + READY state, esp. make sure we don't send two EOS events + in some cases (e.g. one when reaching EOS and one when + going from PAUSED to READY). Also, we don't want to send + EOS events when operating in pull mode. However, we do + want to send an EOS event when shutting down a live + source explicitly, for example (fixes #330996). + +2006-02-23 10:24:13 +0000 Renchi Raju + + plugins/elements/gstfilesrc.c: Update src->read_position after a seek when not using mmap. + Original commit message from CVS: + * plugins/elements/gstfilesrc.c: (gst_file_src_create_read): + Update src->read_position after a seek when not using mmap. + Fixes #332277, patch by: Renchi Raju + +2006-02-20 23:34:40 +0000 Jan Schmidt + + gst/: Make things work with --disable-parse as they do with + Original commit message from CVS: + * gst/Makefile.am: + * gst/gstparse.h: + * gst/gstutils.c: + * gst/gstutils.h: + Make things work with --disable-parse as they do with + --disable-load-save - the symbols involved disappear, but the + header is still installed and GST_DISABLE_PARSE is included via + gstconfig.h + +2006-02-20 16:07:42 +0000 Julien Moutte + + libs/gst/base/gstbasetransform.c: Fix a stupid bug. I was sure i compiled that. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_change_state): Fix a stupid bug. I was + sure i compiled that. + ------------------------------------------------------ + +2006-02-20 15:07:33 +0000 Julien Moutte + + gst/: Make those function act on the ghostpad target when it's a ghostpad. (Closes #331727) + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_blocked_async): + * gst/gstutils.c: (gst_pad_add_data_probe), + (gst_pad_add_event_probe), (gst_pad_add_buffer_probe), + (gst_pad_remove_data_probe), (gst_pad_remove_event_probe), + (gst_pad_remove_buffer_probe): Make those function act on the + ghostpad target when it's a ghostpad. (Closes #331727) + ------------------------------------------------------ + +2006-02-20 15:01:14 +0000 Julien Moutte + + libs/gst/base/gstbasetransform.c: Make basetransform reusable. (Closes #331898) + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_change_state): Make basetransform reusable. + (Closes #331898) + ------------------------------------------------------ + +2006-02-20 12:26:50 +0000 Jan Schmidt + + docs/random/release: Move the current documentation of how to do a release to the top of the file. + Original commit message from CVS: + * docs/random/release: + Move the current documentation of how to do a release to the top + of the file. + * gst/gstbin.c: (gst_bin_class_init), + (gst_bin_handle_message_func): + Allow multiple state-recalculation threads. (Closes #328873) + +2006-02-19 12:25:01 +0000 Julien Moutte + + gst/gstinfo.h: Add GST_STR_NULL to the second string. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE + * gst/gstinfo.h: Add GST_STR_NULL to the second string. + * gst/gstpad.c: (gst_pad_set_event_function), + (gst_pad_set_query_function), (gst_pad_set_query_type_function), + (gst_pad_set_getcaps_function): GST_DEBUG_PAD_NAME evaluates to + 2 strings. You can't use the STR_NULL macro on that. + +2006-02-19 12:00:38 +0000 Sébastien Moutte + + gst/gstpad.c: (gst_pad_set_getcaps_function) + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_event_function), + (gst_pad_set_query_function), (gst_pad_set_query_type_function), + (gst_pad_set_getcaps_function) + * gst/parse/grammar.y: (gst_parse_found_pad), (gst_parse_perform_delayed_link) + Fixed NULL pointer used in GST_CAT_DEBUG using GST_STR_NULL macro + So now, we can use --gst-debug-level=5 on Windows + * win32/common/libgstcontroller.def: + Added export of gst_controller_init + * win32/vs6/libgstcontroller.dsp: + Fixed Release post build configuration + +2006-02-17 15:25:39 +0000 Wim Taymans + + tests/check/gst/gstquery.c: Added another check. + Original commit message from CVS: + * tests/check/gst/gstquery.c: (GST_START_TEST): + Added another check. + +2006-02-15 12:17:50 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: We can do peeks at non-zero offsets, as long as they fall within the buffer we... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (find_peek): + We can do peeks at non-zero offsets, as long as they + fall within the buffer we have. + +2006-02-15 01:02:11 +0000 Jan Schmidt + + tests/check/: Add testsuite for parse launch syntax + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/pipelines/parse-launch.c: (setup_pipeline), + (expected_fail_pipe), (check_pipeline_runs), (GST_START_TEST), + (parse_suite), (main): + Add testsuite for parse launch syntax + +2006-02-14 20:57:31 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: When typefinding is unsuccessful in the chain function, don't error out immedi... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain): + When typefinding is unsuccessful in the chain function, don't + error out immediately. Only error out with NO_CAPS_FOUND if + the amount of data is at least MAX_TYPEFIND_SIZE bytes, + otherwise simply wait for more data so we can try typefinding + again with more data later. Also, don't attempt to typefind + if we have less than MIN_TYPEFIND_SIZE data available. Overall, + this should improve typefinding from network sources where the + size of the first buffer can be somewhat random. + +2006-02-14 18:26:19 +0000 Wim Taymans + + Fix padtemplate docs, fixes #328805. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + Fix padtemplate docs, fixes #328805. + +2006-02-14 17:25:11 +0000 Wim Taymans + + tools/gst-launch.c: NO_PREROLL is not an ERROR so don't send confusing messages to the user. + Original commit message from CVS: + * tools/gst-launch.c: (main): + NO_PREROLL is not an ERROR so don't send confusing messages + to the user. + +2006-02-14 16:15:05 +0000 Torsten Schoenfeld + + gst/gstregistry.c: Protect default registry with lock and ref/sink it. + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_get_default), + (_gst_registry_cleanup): + Protect default registry with lock and ref/sink it. + Fixes #324818, patch by Torsten Schoenfeld. + +2006-02-14 13:07:10 +0000 Wim Taymans + + Docs fixes. + Original commit message from CVS: + * gst/gstbuffer.c: + * gst/gstquery.c: (gst_query_list_add_format), + (gst_query_set_formatsv), (gst_query_parse_formats_length), + (gst_query_parse_formats_nth): + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_sync_times): + Docs fixes. + +2006-02-14 12:07:16 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Reworked query docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Reworked query docs. + * gst/gstquery.c: (gst_query_new_formats), + (gst_query_list_add_format), (gst_query_set_formats), + (gst_query_set_formatsv), (gst_query_parse_formats_length), + (gst_query_parse_formats_nth): + * gst/gstquery.h: + Flesh out formats query, added some new methods. + Fix part of #324398. + * tests/check/gst/gstquery.c: (GST_START_TEST), (gstquery_suite): + Added query creation tests. + +2006-02-14 11:38:50 +0000 Jan Schmidt + + gst/gstpad.c: Add a default fixation for fraction lists. + Original commit message from CVS: + * gst/gstpad.c: (fixate_value): + Add a default fixation for fraction lists. + +2006-02-13 17:03:23 +0000 Wim Taymans + + gst/gsttask.*: Detect and warn for obvious deadlocks. fixes #320340 + Original commit message from CVS: + * gst/gsttask.c: (gst_task_init), (gst_task_func), + (gst_task_set_lock), (gst_task_start), (gst_task_pause), + (gst_task_join): + * gst/gsttask.h: + Detect and warn for obvious deadlocks. fixes #320340 + Fix error case where lock was not released. + * tests/check/Makefile.am: + * tests/check/gst/gsttask.c: (task_func2), (GST_START_TEST), + (task_func), (gst_element_suite), (main): + Add task check. + +2006-02-13 14:00:33 +0000 Wim Taymans + + * ChangeLog: + Forgot changelog + Original commit message from CVS: + Forgot changelog + +2006-02-13 13:57:29 +0000 Wim Taymans + + Add new functions to docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbus.c: + Add new functions to docs. + +2006-02-13 11:52:43 +0000 Wim Taymans + + docs/design/part-TODO.txt: Updated TODO list, basesrc supports seeking to non-bytes formats. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Updated TODO list, basesrc supports seeking to non-bytes + formats. + * docs/design/part-element-sink.txt: + Update docs. + * gst/gstbin.c: (bin_replace_message), + (gst_bin_handle_message_func): + * gst/gstbus.c: (gst_bus_post), (gst_bus_pop): + * gst/gstevent.c: (gst_event_finalize): + * gst/gstpad.c: (gst_pad_event_default_dispatch), + (gst_pad_send_event): + Use shiny new _TYPE_NAME macros. + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_range): + Move debug statement up. + * gst/gstelement.c: (gst_element_set_locked_state): + Add some debugging. + +2006-02-13 11:19:32 +0000 Tim-Philipp Müller + + New API: add GST_MESSAGE_TYPE_NAME and GST_QUERY_TYPE_NAME macros (#330906). Also, document the already existing + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.h: + * gst/gstquery.h: + New API: add GST_MESSAGE_TYPE_NAME and GST_QUERY_TYPE_NAME + macros (#330906). Also, document the already existing + GST_QUERY_TYPE macro. + +2006-02-13 10:54:03 +0000 Wim Taymans + + tests/check/gst/gstutils.c: Only events up to the pipeline EOS are counted, there are some more when going to NULL cu... + Original commit message from CVS: + * tests/check/gst/gstutils.c: (data_probe), (buffer_probe), + (event_probe), (GST_START_TEST): + Only events up to the pipeline EOS are counted, there are + some more when going to NULL currently which we don't care + about for now. + +2006-02-13 09:59:03 +0000 Wim Taymans + + gst/gstpad.c: Correctly check flushing and emit probes. fixes #330125 + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_send_event): + Correctly check flushing and emit probes. fixes #330125 + +2006-02-12 13:11:53 +0000 Thomas Vander Stichele + + * win32/common/config.h: + revert wrong commit + Original commit message from CVS: + revert wrong commit + +2006-02-10 16:04:59 +0000 Andy Wingo + + gst/gstbus.c (gst_bus_class_init): Declare our private data structure. + Original commit message from CVS: + 2006-02-10 Andy Wingo + * gst/gstbus.c (gst_bus_class_init): Declare our private data + structure. + (gst_bus_init): Cache the location of the private data in the + instance structure. + (gst_bus_enable_sync_message_emission) + (gst_bus_disable_sync_message_emission): Implement new public + functions. + (gst_bus_post): Emit the sync-message signal if the user asked for + it. Fixes #330684. + * gst/gstbus.h (GstBus): Use a padding pointer to cache the + location of the bus-private structuure. + (gst_bus_enable_sync_message_emission) + (gst_bus_disable_sync_message_emission): New public functions. + +2006-02-09 23:40:43 +0000 Vincent Torri + + docs/pwg/building-boiler.xml: + Original commit message from CVS: + * docs/pwg/building-boiler.xml: + PWG patch from #326800 (Patch by Vincent Torri) + +2006-02-09 18:30:51 +0000 Tim-Philipp Müller + + * ChangeLog: + * docs/design/Makefile.am: + ChangeLog surgery and add missing new file + Original commit message from CVS: + ChangeLog surgery and add missing new file + +2006-02-09 18:28:33 +0000 Tim-Philipp Müller + + docs/design/Makefile.am + Original commit message from CVS: + * configure.ac: + * docs/Makefile.am: + * docs/design/Makefile.am + Dist design docs. + +2006-02-08 17:34:43 +0000 Jan Schmidt + + configure.ac: back to CVS + Original commit message from CVS: + * configure.ac: + back to CVS + +=== release 0.10.3 === + +2006-02-08 17:31:34 +0000 Jan Schmidt + + configure.ac: releasing 0.10.3, "Like a virgin" + Original commit message from CVS: + === release 0.10.3 === + 2006-02-08 Jan Schmidt + * configure.ac: + releasing 0.10.3, "Like a virgin" + +2006-02-08 11:12:07 +0000 Jan Schmidt + + configure.ac: 2nd prerelease of 0.10.3 + Original commit message from CVS: + 2006-02-08 Jan Schmidt + * configure.ac: + 2nd prerelease of 0.10.3 + Bump libtool versioning. + +2006-02-07 15:49:40 +0000 Andy Wingo + + libs/gst/base/gstcollectpads.c (gst_collect_pads_chain): Only update last_stop if we're in TIME format and the timest... + Original commit message from CVS: + 2006-02-07 Andy Wingo + * libs/gst/base/gstcollectpads.c (gst_collect_pads_chain): Only + update last_stop if we're in TIME format and the timestamp is + valid. + * libs/gst/base/gstcollectpads.c (gst_collect_pads_event) + * libs/gst/base/gstbasetransform.c (gst_base_transform_eventfunc): + * libs/gst/base/gstbasesink.c (gst_base_sink_configure_segment): + If we get a new newsegment with a different format, adapt + accordingly. + * gst/gstclock.c (gst_clock_set_calibration): Accept a numerator + of 0. Not a problem, really. + +2006-02-07 13:20:16 +0000 Andy Wingo + + libs/gst/base/gstbasesink.c (gst_base_sink_chain_unlocked): Only warn if sync=true. + Original commit message from CVS: + 2006-02-07 Andy Wingo + * libs/gst/base/gstbasesink.c (gst_base_sink_chain_unlocked): Only + warn if sync=true. + +2006-02-07 10:51:24 +0000 Christian Schaller + + * gstreamer.spec.in: + update spec file + Original commit message from CVS: + update spec file + +2006-02-06 22:01:23 +0000 Jan Schmidt + + configure.ac: Prelease of 0.10.3 + Original commit message from CVS: + * configure.ac: + Prelease of 0.10.3 + +2006-02-06 21:53:05 +0000 Jan Schmidt + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-02-06 21:29:04 +0000 Sébastien Moutte + + win32/vs7: project files updated to the default vs7 configuration + Original commit message from CVS: + * win32/vs7: + project files updated to the default vs7 configuration + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + added new symbols, + removed empty lines, + sorted all exported symbols alphabetically + * win32/common/dirent.c: + * win32/common/dirent.h: + * win32/common/gchar.h: + use windows line end. + +2006-02-06 15:25:26 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + doc sub80 fixes + Original commit message from CVS: + doc sub80 fixes + +2006-02-06 14:57:40 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.c: Send EOS event when stopping. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_change_state): + Send EOS event when stopping. + +2006-02-06 10:42:01 +0000 Tim-Philipp Müller + + docs/README: Tell folks what to do if the plugin-foobar.xml file hasn't been generated for a newly-added plugin. + Original commit message from CVS: + * docs/README: + Tell folks what to do if the plugin-foobar.xml file + hasn't been generated for a newly-added plugin. + +2006-02-05 18:13:28 +0000 Julien Moutte + + libs/gst/base/gstcollectpads.c: Collectpads now holds a reference to the GstPad that was added. Indeed we don't want ... + Original commit message from CVS: + 2006-02-05 Julien MOUTTE + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_finalize), + (gst_collect_pads_add_pad), (gst_collect_pads_remove_pad), + (gst_collect_pads_start), (gst_collect_pads_stop), + (gst_collect_pads_event): Collectpads now holds a reference + to the GstPad that was added. Indeed we don't want to look + at pads that might just go away with no warning... + +2006-02-05 16:18:37 +0000 Julien Moutte + + libs/gst/base/gstcollectpads.*: Handle flush. Adapted from + Original commit message from CVS: + 2006-02-05 Julien MOUTTE + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_add_pad), + (gst_collect_pads_start), (gst_collect_pads_stop), + (gst_collect_pads_event), (gst_collect_pads_chain): + * libs/gst/base/gstcollectpads.h: Handle flush. Adapted from + Mark Nauwelaerts's patch on bug #328491. + +2006-02-04 12:49:53 +0000 Tim-Philipp Müller + + tests/check/gst/gstutils.c: Add some simple tests for gst_parse_bin_from_description() and gst_bin_find_unconnected_p... + Original commit message from CVS: + * tests/check/gst/gstutils.c: (test_parse_bin_from_description), + (gst_utils_suite): + Add some simple tests for gst_parse_bin_from_description() and + gst_bin_find_unconnected_pad() (#329069). + +2006-02-04 11:56:18 +0000 Tim-Philipp Müller + + tools/gst-launch.c: Catch errors during preroll (#320084). + Original commit message from CVS: + * tools/gst-launch.c: (event_loop), (main): + Catch errors during preroll (#320084). + +2006-02-03 21:14:57 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Post TYPE_NOT_FOUND error message when typefinding is unsuccessful in the acti... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_activate): + Post TYPE_NOT_FOUND error message when typefinding + is unsuccessful in the activate function as well. + +2006-02-02 16:15:17 +0000 Wim Taymans + + docs/design/part-element-sink.txt: Updated doc. + Original commit message from CVS: + * docs/design/part-element-sink.txt: + Updated doc. + +2006-02-02 16:12:35 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Only keep track of prerollable items when we are prerolling. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_do_sync), + (gst_base_sink_render_object), + (gst_base_sink_queue_object_unlocked): + Only keep track of prerollable items when we are + prerolling. + Before rendering after preroll, always check if we + have queued items. + Added some more debugging. + +2006-02-02 13:58:12 +0000 Wim Taymans + + gst/gstelement.c: Fixed #326576, been running this for quite some time with no regressions at all. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_set_state_func), (gst_element_change_state): + Fixed #326576, been running this for quite some time with + no regressions at all. + +2006-02-02 13:44:04 +0000 Wim Taymans + + common/gst.supp: Added more suppressions + Original commit message from CVS: + * common/gst.supp: + Added more suppressions + +2006-02-02 12:07:48 +0000 Wim Taymans + + docs/design/part-element-sink.txt: Updated document. + Original commit message from CVS: + * docs/design/part-element-sink.txt: + Updated document. + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_finalize), (gst_base_sink_preroll_queue_flush), + (gst_base_sink_configure_segment), (gst_base_sink_commit_state), + (gst_base_sink_get_sync_times), (gst_base_sink_wait_clock), + (gst_base_sink_do_sync), (gst_base_sink_render_object), + (gst_base_sink_preroll_object), + (gst_base_sink_queue_object_unlocked), + (gst_base_sink_queue_object), (gst_base_sink_event), + (gst_base_sink_chain_unlocked), (gst_base_sink_chain), + (gst_base_sink_loop), (gst_base_sink_activate_pull), + (gst_base_sink_get_position), (gst_base_sink_change_state): + * libs/gst/base/gstbasesink.h: + Totally refactored matching the design doc. + Use two segments, one to clip incomming buffers and another to + perform sync. + Handle queueing correctly, bypass the queue when playing. + Make EOS cancelable. + Handle errors correctly when operating in pull based mode. + * tests/check/elements/fakesink.c: (GST_START_TEST), + (fakesink_suite): + Added new check for sinks. + +2006-02-02 11:59:27 +0000 Wim Taymans + + gst/gstsegment.c: No reason to refuse to clip when start == -1 + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_clip): + No reason to refuse to clip when start == -1 + +2006-02-02 11:24:19 +0000 Stefan Kost + + docs/: describe dparams (controller) for plugins unify docs a little more + Original commit message from CVS: + * docs/README: + * docs/manual/intro-basics.xml: + * docs/manual/intro-preface.xml: + * docs/manual/manual.xml: + * docs/pwg/advanced-dparams.xml: + * docs/pwg/intro-basics.xml: + * docs/pwg/intro-preface.xml: + * docs/pwg/pwg.xml: + describe dparams (controller) for plugins + unify docs a little more + +2006-02-02 09:51:18 +0000 Tim-Philipp Müller + + Add new API: gst_parse_bin_from_description() and gst_bin_find_unconnected_pad() (#329069). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: (element_find_unconnected_pad), + (gst_bin_find_unconnected_pad), (gst_parse_bin_from_description): + * gst/gstutils.h: + Add new API: gst_parse_bin_from_description() and + gst_bin_find_unconnected_pad() (#329069). + +2006-02-01 22:43:17 +0000 Stefan Kost + + docs/manual/README: uncover a nasty detail of the docs build + Original commit message from CVS: + * docs/manual/README: + uncover a nasty detail of the docs build + +2006-02-01 08:27:24 +0000 Thomas Vander Stichele + + * docs/README: + updates for plugin docs + Original commit message from CVS: + updates for plugin docs + +2006-01-31 18:46:15 +0000 Wim Taymans + + gst/gstbin.c: Don't cache duration messages if we're not going to use or free them. + Original commit message from CVS: + * gst/gstbin.c: (bin_remove_messages), (bin_query_duration_done): + Don't cache duration messages if we're not going to use or + free them. + +2006-01-31 16:56:28 +0000 Stefan Kost + + docs/: more dparam docs + Original commit message from CVS: + * docs/manual/advanced-dparams.xml: + * docs/pwg/advanced-dparams.xml: + more dparam docs + * gst/gstindex.c: + fix docs + * libs/gst/controller/lib.c: (gst_controller_init): + init just once + +2006-01-31 10:16:49 +0000 Thomas Vander Stichele + + gst/gstelement.c: also show file/line/func if no additional debug was given + Original commit message from CVS: + * gst/gstelement.c: (gst_element_message_full): + also show file/line/func if no additional debug was given + +2006-01-30 23:52:52 +0000 Sébastien Moutte + + win32/vs7/grammar.vcproj: activate copy of autogenerated files for Release mode + Original commit message from CVS: + * win32/vs7/grammar.vcproj: + activate copy of autogenerated files for Release mode + +2006-01-30 22:29:03 +0000 Sébastien Moutte + + win32/common/libgstreamer.def: export gst_value_compare + Original commit message from CVS: + * win32/common/libgstreamer.def: + export gst_value_compare + +2006-01-30 21:57:00 +0000 Philippe Rouquier + + plugins/elements/: + Original commit message from CVS: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfdsink.c: (_do_init), + (gst_fd_sink_base_init), (gst_fd_sink_class_init), + (gst_fd_sink_init), (gst_fd_sink_dispose), (gst_fd_sink_query), + (gst_fd_sink_render), (gst_fd_sink_check_fd), (gst_fd_sink_start), + (gst_fd_sink_stop), (gst_fd_sink_unlock), (gst_fd_sink_update_fd), + (gst_fd_sink_set_property), (gst_fd_sink_uri_get_type), + (gst_fd_sink_uri_get_protocols), (gst_fd_sink_uri_get_uri), + (gst_fd_sink_uri_set_uri), (gst_fd_sink_uri_handler_init): + * plugins/elements/gstfdsink.h: + Port fdsink to 0.10 (patch by Philippe Rouquier) (Fixes #325490) + +2006-01-30 21:11:38 +0000 Stefan Kost + + docs/manual/advanced-dparams.xml: describe controller + Original commit message from CVS: + * docs/manual/advanced-dparams.xml: + describe controller + * docs/manual/advanced-position.xml: + * docs/manual/basics-init.xml: + * docs/manual/manual.xml: + * docs/manual/titlepage.xml: + * docs/pwg/pwg.xml: + * docs/pwg/titlepage.xml: + cleanup xml (more to come) + * libs/gst/controller/gstcontroller.c: + fix typo + +2006-01-30 20:36:51 +0000 Sébastien Moutte + + win32/vs6/grammar.dsp: add autogen of gstmarshal.c,h for Release mode + Original commit message from CVS: + * win32/vs6/grammar.dsp: + add autogen of gstmarshal.c,h for Release mode + +2006-01-30 16:07:48 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Basesink cleanups, remove some old code. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_init), + (gst_base_sink_preroll_queue_empty), (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_event), + (gst_base_sink_is_prerolled), (gst_base_sink_wait), + (gst_base_sink_do_sync), (gst_base_sink_handle_event), + (gst_base_sink_handle_buffer), (gst_base_sink_set_flushing), + (gst_base_sink_deactivate), (gst_base_sink_activate), + (gst_base_sink_activate_pull), (gst_base_sink_get_position), + (gst_base_sink_query), (gst_base_sink_change_state): + Basesink cleanups, remove some old code. + Handle the case where a subclass can preroll in the render + method (mostly audiosinks). + Handle more events. + Remove some locks around variables that are now protected + with the PREROLL_LOCK (clock_id, flushing, ..). + Optimize position query some more, do correct locking. + Remove old code to push queue in state change, this is not + needed anymore since preroll blocks on all prerollable items + now. + Almost implemented as described in design doc. + +2006-01-30 15:57:43 +0000 Wim Taymans + + tests/check/gst/gstbin.c: Wait for refcount to settle down before checking. + Original commit message from CVS: + * tests/check/gst/gstbin.c: (GST_START_TEST): + Wait for refcount to settle down before checking. + +2006-01-30 15:15:47 +0000 Wim Taymans + + docs/design/part-element-sink.txt: Pseudo code overview of desired sink behaviour regarding preroll. + Original commit message from CVS: + * docs/design/part-element-sink.txt: + Pseudo code overview of desired sink behaviour regarding + preroll. + +2006-01-30 14:28:03 +0000 Jan Schmidt + + * ChangeLog: + Bleh, forgot to commit the changelog entry on Saturday. + Original commit message from CVS: + Bleh, forgot to commit the changelog entry on Saturday. + +2006-01-29 21:56:00 +0000 Sébastien Moutte + + win32/vs6/grammar.dsp: fix some bugs in autogenerated files for Release mode + Original commit message from CVS: + * win32/vs6/grammar.dsp: + fix some bugs in autogenerated files for Release mode + +2006-01-29 19:24:18 +0000 Sébastien Moutte + + win32/common/: export some new symbols: gst_base_src_set_format, gst_iterator_next, gst_structure_set_valist + Original commit message from CVS: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + export some new symbols: gst_base_src_set_format, + gst_iterator_next, gst_structure_set_valist + +2006-01-29 17:37:08 +0000 Julien Moutte + + gst/gstghostpad.c: Set pad functions unconditionally. Fixes #329105. + Original commit message from CVS: + 2006-01-29 Julien MOUTTE + * gst/gstghostpad.c: (gst_proxy_pad_set_target_unlocked): + Set pad functions unconditionally. Fixes #329105. + +2006-01-29 16:54:40 +0000 Sébastien Moutte + + 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-28 00:59:37 +0000 Jan Schmidt + + gst/gstutils.c: Don't leak pad references. + Original commit message from CVS: + * gst/gstutils.c: (gst_element_unlink_pads): + Don't leak pad references. + * tests/check/elements/fakesink.c: (GST_START_TEST): + * tests/check/generic/sinks.c: (GST_START_TEST): + * tests/check/generic/states.c: (GST_START_TEST): + * tests/check/gst/gstbin.c: (GST_START_TEST): + * tests/check/gst/gstcaps.c: (GST_START_TEST): + * tests/check/gst/gstelement.c: (GST_START_TEST): + * tests/check/gst/gstghostpad.c: (GST_START_TEST): + * tests/check/gst/gstiterator.c: (GST_START_TEST): + * tests/check/gst/gstvalue.c: (GST_START_TEST): + Fix a bunch of leaks. Make generic/sinks.c + use a bit less cpu by slowing the buffer rate + between fakesrc and fakesink. + +2006-01-27 22:34:51 +0000 Stefan Kost + + doc fixes, to link to function, just write gst_cool_function(), don't prefix with '#' + Original commit message from CVS: + * gst/gstcaps.c: + * gst/gstelement.c: (gst_element_send_event): + * gst/gstevent.c: + * gst/gstinfo.c: + * gst/gstiterator.c: + * gst/gstiterator.h: + * gst/gstpad.c: (gst_pad_send_event): + * gst/gststructure.c: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstvalue.c: + * libs/gst/base/gstadapter.c: + doc fixes, to link to function, just write gst_cool_function(), don't + prefix with '#' + +2006-01-27 16:59:57 +0000 Jan Schmidt + + plugins/elements/gsttee.c: Always prefer an actual return value from a src pad in place of NOT_LINKED. This means we ... + Original commit message from CVS: + * plugins/elements/gsttee.c: (gst_tee_do_push), + (gst_tee_handle_buffer): + Always prefer an actual return value from a src + pad in place of NOT_LINKED. This means we return + WRONG_STATE when all src pads are WRONG_STATE + instead of NOT_LINKED. + Lock when replacing the last message to prevent + racing with the get_property method. + Add debug output + +2006-01-27 11:53:20 +0000 Jan Schmidt + + tests/check/: Add a very simple check that should have caught the memleak I fixed last night (if not for the slice al... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/gstquery.c: (GST_START_TEST), (gstquery_suite), + (main): + Add a very simple check that should have caught the memleak I fixed + last night (if not for the slice allocator hiding it) + +2006-01-27 01:48:37 +0000 Jan Schmidt + + gst/gstbin.c: Clean up references to the clock provider when disposed or when handling a clock-lost message from it. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_dispose), (gst_bin_provide_clock_func), + (gst_bin_remove_func), (gst_bin_handle_message_func), + (bin_query_duration_fold), (bin_query_generic_fold): + Clean up references to the clock provider when disposed or when + handling a clock-lost message from it. + Unref sinks when performing a query via gst_iterator_fold, as the + gst_bin_iterate_sinks iterator refs each item. (Fixes #323874) + * gst/gstclock.c: (gst_clock_class_init), (gst_clock_dispose), + (gst_clock_set_master): + Drop our reference to the master clock, if any, when we are disposed. + * gst/gsttypefindfactory.c: (gst_type_find_factory_dispose): + Chain up in dispose. + +2006-01-27 01:13:10 +0000 Thomas Vander Stichele + + * docs/random/i18n: + add notes on i18n + Original commit message from CVS: + add notes on i18n + +2006-01-26 12:59:48 +0000 Wim Taymans + + libs/gst/base/gstbasesrc.c: Add some debugging. + Original commit message from CVS: + * libs/gst/base/gstbasesrc.c: (gst_base_src_get_range): + Add some debugging. + +2006-01-26 12:40:17 +0000 Julien Moutte + + plugins/elements/gsttee.c: Apply patch from #328715. Tee now handles pad being NOT_LINKED or in WRONG_STATE. + Original commit message from CVS: + 2006-01-26 Julien MOUTTE + * plugins/elements/gsttee.c: (gst_tee_do_push), + (gst_tee_handle_buffer): Apply patch from #328715. Tee now + handles pad being NOT_LINKED or in WRONG_STATE. + +2006-01-26 08:57:40 +0000 Stefan Kost + + win32/MANIFEST: more updating + Original commit message from CVS: + * win32/MANIFEST: + more updating + +2006-01-26 08:39:20 +0000 Stefan Kost + + win32/MANIFEST: remove obsolete entry + Original commit message from CVS: + * win32/MANIFEST: + remove obsolete entry + +2006-01-26 06:57:14 +0000 Stefan Kost + + added code for downstream events, reviewed docs in gstevent.c + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: (bin_element_is_src), (src_iterator_filter), + (gst_bin_iterate_sources), (gst_bin_send_event): + * gst/gstbin.h: + * gst/gstelement.c: (gst_element_send_event): + * gst/gstevent.c: + * gst/gstpad.c: (gst_pad_send_event): + added code for downstream events, reviewed docs in gstevent.c + +2006-01-25 18:07:02 +0000 Julien Moutte + + libs/gst/base/gstbasesink.c: We only query position using the clock in the playing state. + Original commit message from CVS: + 2006-01-25 Julien MOUTTE + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position): + We only query position using the clock in the playing state. + Query peer in the other cases. + * win32/common/config.h: Updates. + +2006-01-24 16:23:17 +0000 Wim Taymans + + gst/gstsystemclock.c: A clock entry that is scheduled for the exact time of the clock is still in time. + Original commit message from CVS: + * gst/gstsystemclock.c: (gst_system_clock_id_wait_unlocked): + A clock entry that is scheduled for the exact time of the + clock is still in time. + * libs/gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync): + Add some more debug info. + +2006-01-23 12:37:33 +0000 Sébastien Moutte + + win32/vs7: Add new vs7 project files and solution. + Original commit message from CVS: + * win32/vs7 : + Add new vs7 project files and solution. + +2006-01-23 12:23:00 +0000 Sébastien Moutte + + win32/vs7: all files removed as they were out-dated. + Original commit message from CVS: + * win32/vs7: + all files removed as they were out-dated. + +2006-01-20 19:01:59 +0000 Thomas Vander Stichele + + docs/random/release: update notes + Original commit message from CVS: + * docs/random/release: + update notes + * gst/gstbin.c: (gst_bin_init): + * gst/gstbus.c: (gst_bus_new): + * gst/gstbus.h: + * gst/gstpipeline.c: (gst_pipeline_init): + use gst_bus_new(), improve logging, fix docs + * win32/common/config.h: + update for cvs build + +2006-01-20 18:59:00 +0000 Thomas Vander Stichele + + autogen.sh: up required version of automake to 1.7 + Original commit message from CVS: + * autogen.sh: + up required version of automake to 1.7 + +2006-01-20 12:53:40 +0000 Sébastien Moutte + + win32/common/libgstreamer.def: export gst_buffer_is_metadata_writable + Original commit message from CVS: + * win32/common/libgstreamer.def: + export gst_buffer_is_metadata_writable + +2006-01-20 11:46:03 +0000 Tim-Philipp Müller + + Add gst_event_replace() (#327001) + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.h: + Add gst_event_replace() (#327001) + +2006-01-20 09:56:38 +0000 Wim Taymans + + gst/gstpad.c: Make it actually compile too.. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked): + Make it actually compile too.. + +2006-01-20 09:53:24 +0000 Wim Taymans + + gst/gstcaps.c: Clarify behaviour of _is_equal() when passing NULL parameters. + Original commit message from CVS: + * gst/gstcaps.c: + Clarify behaviour of _is_equal() when passing NULL parameters. + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked), + (gst_pad_set_caps): + Cleanups. Don't unref NULL caps. + When setting the same caps, protect caps of the pad with + proper lock. + Use full functionality of _is_equal() when comparing caps. + +2006-01-20 09:26:00 +0000 Jan Schmidt + + libs/gst/base/gstcollectpads.c: Don't loop infinitely if there are no buffers to present. Partially fixes #327197, bu... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_is_collected): + Don't loop infinitely if there are no buffers to present. Partially + fixes #327197, but collectpads is just broken for reusing elements + to do multiple encodes atm. + +2006-01-20 09:12:10 +0000 Jan Schmidt + + tools/: URL_HANDLER is not a plugin feature we can search for in the registry. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_features): + * tools/gst-xmlinspect.c: (main): + URL_HANDLER is not a plugin feature we can search for in + the registry. + +2006-01-19 18:06:18 +0000 Edward Hervey + + gst/gstelement.c: When activating, do src pads first, then sink pads. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_pads_activate): + When activating, do src pads first, then sink pads. + When de-activating, do sink pads first, then src pads. + +2006-01-19 14:02:04 +0000 Jan Schmidt + + docs/gst/gstreamer-sections.txt: Add gst_index_add_associationv to the docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add gst_index_add_associationv to the docs + +2006-01-19 13:30:31 +0000 Jan Schmidt + + gst/gstevent.c: Fix docs typo + Original commit message from CVS: + * gst/gstevent.c: + Fix docs typo + * plugins/elements/gstqueue.c: (gst_queue_handle_sink_event), + (gst_queue_chain), (gst_queue_push_one), (gst_queue_loop): + Do some refactoring. Doesn't actually change functionality, + but makes landing the DRAIN event easier later. + +2006-01-19 10:39:27 +0000 Tim-Philipp Müller + + docs/pwg/advanced-scheduling.xml: Update from 0.9.x to 0.10 API and make example a bit clearer. + Original commit message from CVS: + * docs/pwg/advanced-scheduling.xml: + Update from 0.9.x to 0.10 API and make example a bit + clearer. + +2006-01-19 09:24:03 +0000 Jan Schmidt + + docs/gst/gstreamer-sections.txt: Add gst_buffer_(is|make)_metadata_writable methods. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add gst_buffer_(is|make)_metadata_writable methods. + +2006-01-19 09:08:15 +0000 Jan Schmidt + + docs/design/part-sparsestreams.txt: Update sparse streams doc + Original commit message from CVS: + * docs/design/part-sparsestreams.txt: + Update sparse streams doc + +2006-01-19 09:02:12 +0000 Jan Schmidt + + docs/design/part-events.txt: Remove mention of FILLER events. + Original commit message from CVS: + * docs/design/part-events.txt: + Remove mention of FILLER events. + Add DRAIN event. + * docs/design/part-sparsestreams.txt: + Write some things about using NEWSEGMENT to keep sparse streams + flowing. + +2006-01-18 18:56:44 +0000 Tim-Philipp Müller + + gst/gstbin.c: Guard gst_object_unref call against a NULL object (dispose can theoretically be called multiple times). + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_dispose): + Guard gst_object_unref call against a NULL object (dispose + can theoretically be called multiple times). + +2006-01-18 18:05:43 +0000 Jan Schmidt + + docs/design/part-events.txt: Remove mention of FILLER events. + Original commit message from CVS: + * docs/design/part-events.txt: + Remove mention of FILLER events. + Add DRAIN event. + * docs/design/part-sparsestreams.txt: + Write some things about using NEWSEGMENT to keep sparse streams + flowing. + +2006-01-18 18:01:54 +0000 Wim Taymans + + gst/: Added some more debug info. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_element_set_state): + * gst/gstclock.c: (gst_clock_id_wait): + Added some more debug info. + * libs/gst/base/gstadapter.c: + Added more docs. + * libs/gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync), (gst_base_sink_chain): + Added some comments. + +2006-01-18 17:59:09 +0000 Wim Taymans + + * tests/check/elements/.gitignore: + Ignore fakesink test. + Original commit message from CVS: + Ignore fakesink test. + +2006-01-18 17:57:57 +0000 Wim Taymans + + tests/check/: Added fakesink test that checks prerolling and clipping behaviour. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/fakesink.c: (chain_async_buffer), + (chain_async), (chain_async_return), (GST_START_TEST), + (fakesink_suite), (main): + Added fakesink test that checks prerolling and clipping + behaviour. + * tests/check/gst/gstutils.c: (GST_START_TEST): + Make check run faster so that buildbots don't timeout. + +2006-01-18 17:18:39 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Some cleanups. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync): + Some cleanups. + When the sink finishes blocking on the preroll buffer, it can + immediatly render it instead of rendering when the next buffer + arrives. + +2006-01-18 16:40:16 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Small cleanups. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_do_sync), + (gst_base_sink_chain): + Small cleanups. + GST_ELEMENT_CLOCK and sync are protected with LOCK. + Don't store _last_stop if the buffer is dropped. + +2006-01-18 16:31:49 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: 'have-type' signal needs to be G_SIGNAL_RUN_FIRST, as it is the object method ... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_class_init): + 'have-type' signal needs to be G_SIGNAL_RUN_FIRST, as it is the + object method handler that sets the caps on the pad and we want + that to happen before we emit the signal (fixes e.g. feeding a + plain text file to decodebin). + +2006-01-18 11:44:55 +0000 Christian Schaller + + * ChangeLog: + * gst/gstplugin.c: + add MPL and Properietart to list of licenses + Original commit message from CVS: + add MPL and Properietart to list of licenses + +2006-01-18 09:42:12 +0000 Torsten Schoenfeld + + gst/gstindex.h (gst_index_add_associationv): Add to header. The symbol was exported before, it appears this was just ... + Original commit message from CVS: + 2006-01-18 Andy Wingo + * gst/gstindex.h (gst_index_add_associationv): Add to header. The + symbol was exported before, it appears this was just an oversight. + Fixes #168703. + Patch by: Torsten Schoenfeld + * gst/gstindex.c (gst_index_add_associationv): Changed int in + prototype to gint. OK since this prototype was not in the header. + +2006-01-17 16:39:23 +0000 Christian Schaller + + * docs/manual/appendix-licensing.xml: + small fix to the proposed license clause + Original commit message from CVS: + small fix to the proposed license clause + +2006-01-17 12:53:07 +0000 Andy Wingo + + gst/gstregistry.c (_gst_registry_remove_cache_plugins): Lock the registry while we remove plugins. + Original commit message from CVS: + 2006-01-17 Andy Wingo + * gst/gstregistry.c (_gst_registry_remove_cache_plugins): Lock the + registry while we remove plugins. + * tools/gst-inspect.c (print_element_info): Don't unref the + factory arg, that should be the responsibility of whatever code + received the ref. Fixes a double-free when called from + print_element_list via gst-inspect-0.10 -a. Fixes #327324. + (main): Unref the factory if we have one. + (print_element_list): No change -- relies on the + plugin_feature_list_free to free the list of features. + +2006-01-17 12:14:20 +0000 Jan Schmidt + + Replace gst_buffer_(make|is)_metadata_writable patch now that the release is out. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_is_metadata_writable), + (gst_buffer_make_metadata_writable): + * gst/gstbuffer.h: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + * tests/check/gst/gstbuffer.c: (GST_START_TEST), (gst_test_suite): + Replace gst_buffer_(make|is)_metadata_writable patch now + that the release is out. + +2006-01-17 12:08:43 +0000 Andy Wingo + + gst/gstregistry.c: Reflow design comment. Update so as to speak in the present tense without reference to versions. + Original commit message from CVS: + 2006-01-17 Andy Wingo + * gst/gstregistry.c: Reflow design comment. Update so as to speak + in the present tense without reference to versions. + * gst/gstregistry.c (gst_registry_add_plugin) + (gst_registry_remove_plugin, gst_registry_remove_feature) + (gst_registry_find_feature, gst_registry_get_feature_list) + (gst_registry_get_plugin_list, gst_registry_lookup_feature) + (gst_registry_lookup, gst_registry_scan_path) + (_gst_registry_remove_cache_plugins) + (gst_registry_get_feature_list_by_plugin): Add argument + validation. + +2006-01-16 21:00:53 +0000 Thomas Vander Stichele + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.2 === + +2006-01-16 20:59:38 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + releasing 0.10.2 + Original commit message from CVS: + releasing 0.10.2 + +2006-01-16 15:42:08 +0000 Jan Schmidt + + Back out patch until after the release. + Original commit message from CVS: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + * tests/check/gst/gstbuffer.c: (gst_test_suite): + Back out patch until after the release. + +2006-01-16 14:37:54 +0000 Jan Schmidt + + gst/gstminiobject.c: Spelling fix in docs. + Original commit message from CVS: + * gst/gstminiobject.c: + Spelling fix in docs. + * ChangeLog - remove conflict indicator + +2006-01-16 14:37:01 +0000 Jan Schmidt + + (Missed plugins/elements/gstcapsfilter.c in previous commit) + Original commit message from CVS: + (Missed plugins/elements/gstcapsfilter.c in previous commit) + Reviewed By: Andy Wingo + * gst/gstbuffer.c: (gst_buffer_is_metadata_writable), + (gst_buffer_make_metadata_writable): + * gst/gstbuffer.h: + Add gst_buffer_(is|make)_metadata_writable as analogues of + gst_buffer_(is|make)_writable. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + Use name gst_buffer_(is|make)_metadata_writable functions. + * tests/check/gst/gstbuffer.c: (GST_START_TEST), (gst_test_suite): + Test gst_buffer_(is|make)_metadata_writable + (Closes: #324162) + +2006-01-16 14:32:33 +0000 Jan Schmidt + + gst/gstbuffer.*: Add gst_buffer_(is|make)_metadata_writable as analogues of gst_buffer_(is|make)_writable. + Original commit message from CVS: + Reviewed By: Andy Wingo + * gst/gstbuffer.c: (gst_buffer_is_metadata_writable), + (gst_buffer_make_metadata_writable): + * gst/gstbuffer.h: + Add gst_buffer_(is|make)_metadata_writable as analogues of + gst_buffer_(is|make)_writable. + * libs/gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf): + * plugins/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + Use name gst_buffer_(is|make)_metadata_writable functions. + * tests/check/gst/gstbuffer.c: (GST_START_TEST), (gst_test_suite): + Test gst_buffer_(is|make)_metadata_writable + (Closes: #324162) + +2006-01-14 22:59:46 +0000 Thomas Vander Stichele + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + * win32/common/config.h: + prerelease + Original commit message from CVS: + prerelease + +2006-01-14 14:12:26 +0000 Thomas Vander Stichele + + * tests/check/gst/gstbus.c: + * tests/check/gst/gstelement.c: + add unlink and some asserts + Original commit message from CVS: + add unlink and some asserts + +2006-01-14 11:20:40 +0000 Thomas Vander Stichele + + docs/manual/Makefile.am: don't do parallel make + Original commit message from CVS: + * docs/manual/Makefile.am: + don't do parallel make + * configure.ac: + AC_SUBST HOST_CPU + * win32/common/config.h.in: + add generations for HOST_CPU and GST_MAJORMINOR + * win32/common/config.h: commit generated result + +2006-01-13 19:51:48 +0000 Thomas Vander Stichele + + * docs/random/release: + updates to release doc + Original commit message from CVS: + updates to release doc + +2006-01-13 19:17:05 +0000 Tim-Philipp Müller + + docs/manual/appendix-integration.xml: Update GNOME integration section to use gst_init_get_option_group() instead of ... + Original commit message from CVS: + * docs/manual/appendix-integration.xml: + Update GNOME integration section to use gst_init_get_option_group() + instead of the old popt stuff (#322911). Also, GNOME applications + should now use gconf*sink and gconf*src instead of the old gconf + helper lib we had. + +2006-01-13 16:16:24 +0000 Christian Schaller + + * gstreamer.spec.in: + removing 010 suffixing of package name as Fedora only use it for 0.8, want to have the packages be interchangeable + Original commit message from CVS: + removing 010 suffixing of package name as Fedora only use it for 0.8, want + to have the packages be interchangeable + +2006-01-13 14:59:00 +0000 Thomas Vander Stichele + + * configure.ac: + * po/LINGUAS: + readd zh_TW and force an autogen + Original commit message from CVS: + readd zh_TW and force an autogen + +2006-01-13 14:21:48 +0000 Stefan Kost + + docs/: add new API entries to the docs + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + add new API entries to the docs + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + move private structs to private header + * po/README: + gstreamer-0.7 -> gstreamer-0.10 + * tests/check/libs/struct_i386.h: + remove private structs + +2006-01-13 14:19:37 +0000 Thomas Vander Stichele + + * po/POTFILES.in: + trigger a rebuild + Original commit message from CVS: + trigger a rebuild + +2006-01-13 14:19:11 +0000 Thomas Vander Stichele + + * po/LINGUAS: + trigger a rebuild + Original commit message from CVS: + trigger a rebuild + +2006-01-13 14:12:55 +0000 Thomas Vander Stichele + + plugins/indexers/Makefile.am: Fixes as part of #317048 + Original commit message from CVS: + * plugins/indexers/Makefile.am: + Fixes as part of #317048 + +2006-01-13 13:41:55 +0000 Thomas Vander Stichele + + plugins/indexers/Makefile.am: fix #316086 - compilation when mmap is missing + Original commit message from CVS: + * plugins/indexers/Makefile.am: + fix #316086 - compilation when mmap is missing + +2006-01-12 22:04:58 +0000 Sébastien Moutte + + libs/gst/base/gstbasesink.c: *cur = (now - base) * basesink->segment.abs_rate + time; replaced by + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: + *cur = (now - base) * basesink->segment.abs_rate + time; replaced by + *cur = gst_guint64_to_gdouble(now - base) * basesink->segment.abs_rate + time; for vs6 + * win32/common/config.h: + added some defines GST_MAJORMINOR and HOST_CPU + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + added some exported functions + +2006-01-12 21:55:42 +0000 Stefan Kost + + libs/gst/controller/: make G_TYPE_STRING controlable + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_new): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstinterpolation.c: + (interpolate_none_get_string_value_array): + make G_TYPE_STRING controlable + +2006-01-12 16:31:35 +0000 Stefan Kost + + tools/: cleanup man-pages, remove reference to gst-register, document env-vars + Original commit message from CVS: + * tools/README: + * tools/gst-feedback.1.in: + * tools/gst-inspect.1.in: + * tools/gst-launch.1.in: + * tools/gst-md5sum.1.in: + * tools/gst-typefind.1.in: + * tools/gst-xmlinspect.1.in: + * tools/gst-xmllaunch.1.in: + cleanup man-pages, remove reference to gst-register, document env-vars + +2006-01-12 16:07:50 +0000 Jan Schmidt + + gst/gstbuffer.c: gst_buffer_span should copy the timestamp of the first buffer if they were both originally overlappi... + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_span): + gst_buffer_span should copy the timestamp of the first buffer + if they were both originally overlapping subbuffers of the + same parent, using the same logic as the 'slow copy' case. + +2006-01-11 21:32:21 +0000 Jan Schmidt + + libs/gst/base/gstcollectpads.c: Need to awaken ALL the pads when we pop a buffer, otherwise collectpads only works wh... + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_pop): + Need to awaken ALL the pads when we pop a buffer, otherwise + collectpads only works when there is 2 input streams. + +2006-01-11 19:18:27 +0000 Stefan Kost + + docs/random/ensonic/media-device-daemon.txt: more ideas (dbus) + Original commit message from CVS: + * docs/random/ensonic/media-device-daemon.txt: + more ideas (dbus) + * gst/gstbuffer.c: + fix doc example, add clarification + * tools/gst-launch.1.in: + add initial info about GST_PLUGIN_PATH, needs more work + +2006-01-11 10:38:56 +0000 Tim-Philipp Müller + + docs/manual/: Some more minor docs additions and updates. + Original commit message from CVS: + * docs/manual/basics-bins.xml: + * docs/manual/basics-elements.xml: + * docs/manual/intro-basics.xml: + Some more minor docs additions and updates. + +2006-01-11 10:20:06 +0000 Wim Taymans + + docs/manual/: Some small fixes as pointed out by Ser-ver on IRC. + Original commit message from CVS: + * docs/manual/basics-bins.xml: + * docs/manual/basics-elements.xml: + Some small fixes as pointed out by Ser-ver on IRC. + +2006-01-10 15:42:29 +0000 Edward Hervey + + plugins/elements/gstidentity.c: Set the buffer offset/offset_end to GST_CLOCK_TIME_NONE when using the single-segment... + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + Set the buffer offset/offset_end to GST_CLOCK_TIME_NONE when using + the single-segment mode. + +2006-01-10 09:23:11 +0000 Tim-Philipp Müller + + libs/gst/base/gstbasesrc.*: Name (private) union; makes Sun's Forte compiler happy (#324900). + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * libs/gst/base/gstbasesrc.c: (gst_base_src_init), + (gst_base_src_perform_seek), (gst_base_src_send_event), + (gst_base_src_set_property), (gst_base_src_get_property), + (gst_base_src_loop), (gst_base_src_start), + (gst_base_src_activate_push): + * libs/gst/base/gstbasesrc.h: + Name (private) union; makes Sun's Forte compiler happy (#324900). + +2006-01-09 10:47:17 +0000 Tim-Philipp Müller + + README: gst-register is gone. + Original commit message from CVS: + * README: + gst-register is gone. + +2006-01-07 11:07:42 +0000 Thomas Vander Stichele + + * po/LINGUAS: + remove and readd + Original commit message from CVS: + remove and readd + +2006-01-07 11:07:14 +0000 Thomas Vander Stichele + + * common: + * po/LINGUAS: + remove and readd + Original commit message from CVS: + remove and readd + +2006-01-07 10:04:36 +0000 Thomas Vander Stichele + + gst/gstvalue.c: make the G_TYPE_DATE instantiation work if debug is disabled + Original commit message from CVS: + * gst/gstvalue.c: (_gst_value_initialize): + make the G_TYPE_DATE instantiation work if debug is disabled + +2006-01-07 09:56:01 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * po/zh_TW.po: + update translations + Original commit message from CVS: + update translations + +2006-01-06 17:16:40 +0000 Tim-Philipp Müller + + gst/gstmessage.c: Don't crash when return location for error/warning debug string is NULL; add fact that return locat... + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_parse_tag), + (gst_message_parse_error), (gst_message_parse_warning): + Don't crash when return location for error/warning debug + string is NULL; add fact that return locations can be + NULL to docs where appropriate. + +2006-01-05 10:43:02 +0000 Wim Taymans + + gst/gstplugin.c: Replace strdup by g_strdup as suggested by Ser-ver. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + Replace strdup by g_strdup as suggested by Ser-ver. + +2006-01-04 23:53:01 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update config for .1 + Original commit message from CVS: + update config for .1 + +2006-01-04 23:52:35 +0000 Thomas Vander Stichele + + docs/pwg/advanced-types.xml: fix doc borkage + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + fix doc borkage + +2006-01-04 23:50:18 +0000 Thomas Vander Stichele + + submitted by: Abel Cheung + Original commit message from CVS: + submitted by: Abel Cheung + * po/LINGUAS: + * po/zh_TW.po: + Added Chinese (traditional) translation + +2006-01-04 12:41:35 +0000 Wim Taymans + + Small updates to various docs. + Original commit message from CVS: + * docs/manual/basics-pads.xml: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-scheduling.xml: + * docs/pwg/advanced-types.xml: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstidentity.c: (gst_identity_class_init): + * plugins/elements/gstidentity.h: + * plugins/elements/gstqueue.h: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_class_init): + * plugins/elements/gsttypefindelement.h: + Small updates to various docs. + Added core plugins to docs. + +2006-01-03 18:08:04 +0000 Thomas Vander Stichele + + common/gst.supp: add a suppression for liboil's uninitialized variable + Original commit message from CVS: + * common/gst.supp: + add a suppression for liboil's uninitialized variable + +2006-01-02 20:26:06 +0000 Tim-Philipp Müller + + gst/gstutils.h: Add prototype for _get_type() function to GST_BOILERPLATE_FULL macro, so that gcc doesn't complain if... + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstutils.h: + Add prototype for _get_type() function to GST_BOILERPLATE_FULL + macro, so that gcc doesn't complain if the -Wmissing-prototypes + compiler switch is being used (#325429). + +2005-12-29 16:47:27 +0000 Tim-Philipp Müller + + gst/gstbin.c: Disable duration query caching in bins until it gets fixed (see #324807). + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_query): + Disable duration query caching in bins until it gets + fixed (see #324807). + +2005-12-27 18:04:58 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Handle properties of POINTER and BOXED type. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + Handle properties of POINTER and BOXED type. + +2005-12-27 12:11:19 +0000 Tim-Philipp Müller + + gst/gst.c: Init tags stuff and some other things before loading any static plugins (there may be other static plugins... + Original commit message from CVS: + * gst/gst.c: (init_post): + Init tags stuff and some other things before loading + any static plugins (there may be other static plugins + than just the GStreamer ones, and they may want to + register their own tags or formats or whatever, and + preferably without segfaulting). + * plugins/elements/gstqueue.c: (gst_queue_handle_src_query): + Print at least a warning in the debug logs if we drop a + query just because we don't know how to adjust the value + in the particular format. + +2005-12-25 03:45:45 +0000 David Schleef + + tools/gstreamer-completion: Replacement for gst-complete written in sh and sed. Only completes names of features, bu... + Original commit message from CVS: + * tools/gstreamer-completion: + Replacement for gst-complete written in sh and sed. Only + completes names of features, but that's 90% of what I want + it for. Properties are not available in registry.xml. (Maybe + they should be...) + +2005-12-23 18:15:48 +0000 Thomas Vander Stichele + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.1 === + +2005-12-23 18:04:49 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * libs/gst/base/gstbasesrc.c: + * win32/common/config.h: + releasing 0.10.1 + Original commit message from CVS: + releasing 0.10.1 + +2005-12-23 14:53:12 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.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 + Original commit message from CVS: + Update .po files + +2005-12-23 13:45:22 +0000 Thomas Vander Stichele + + * tests/check/libs/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-12-22 14:48:14 +0000 Tim-Philipp Müller + + docs/faq/cvs.xml: Add missing quote, should be make ERROR_CFLAGS="". + Original commit message from CVS: + * docs/faq/cvs.xml: + Add missing quote, should be make ERROR_CFLAGS="". + +2005-12-20 16:01:09 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.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/config.h: + prereleasing + Original commit message from CVS: + prereleasing + +2005-12-20 12:50:56 +0000 Wim Taymans + + docs/design/part-trickmodes.txt: More documentation on trickmodes. + Original commit message from CVS: + * docs/design/part-trickmodes.txt: + More documentation on trickmodes. + +2005-12-20 11:12:53 +0000 Edward Hervey + + gst/gstcaps.*: Added gpointer GType for GstStaticCaps so we can wrap them in bindings. + Original commit message from CVS: + * gst/gstcaps.c: (gst_static_caps_get_type): + * gst/gstcaps.h: + Added gpointer GType for GstStaticCaps so we can wrap them in bindings. + * gst/gstpadtemplate.c: (gst_static_pad_template_get_type): + * gst/gstpadtemplate.h: + Added gpointer GType for GstStaticPadTemplate so we can wrap them in + bindings. + +2005-12-18 16:04:41 +0000 Wim Taymans + + libs/gst/: Documentation updates. + Original commit message from CVS: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_get_position): + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_default_query), (gst_base_src_default_do_seek), + (gst_base_src_do_seek), (gst_base_src_perform_seek), + (gst_base_src_send_event), (gst_base_src_update_length), + (gst_base_src_get_range), (gst_base_src_loop), + (gst_base_src_start): + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + * libs/gst/dataprotocol/dataprotocol.c: + * libs/gst/dataprotocol/dataprotocol.h: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimeprovider.h: + Documentation updates. + +2005-12-18 14:28:25 +0000 Tim-Philipp Müller + + docs/manual/basics-helloworld.xml: Remove superfluous closing bracket in helloworld example. + Original commit message from CVS: + * docs/manual/basics-helloworld.xml: + Remove superfluous closing bracket in helloworld example. + +2005-12-17 14:19:27 +0000 Tim-Philipp Müller + + tools/gst-launch.1.in: Update gst-launch man page; add a section with useful environment variables. Fixes #323882. + Original commit message from CVS: + * tools/gst-launch.1.in: + Update gst-launch man page; add a section with useful + environment variables. Fixes #323882. + +2005-12-16 21:59:12 +0000 Stefan Kost + + gst/: change some char* into char[] + Original commit message from CVS: + * gst/gst.c: + * gst/gst_private.h: + change some char* into char[] + +2005-12-16 19:24:24 +0000 Wim Taymans + + gst/gstregistryxml.c: Cleanups. + Original commit message from CVS: + * gst/gstregistryxml.c: (load_feature): + Cleanups. + Don't use g_object_unref on GstObjects so that we avoid + leaks on unsafe glibs. + +2005-12-16 18:20:58 +0000 Wim Taymans + + gst/gstbin.c: Small doc updates. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_recalc_state): + Small doc updates. + +2005-12-16 18:10:04 +0000 Wim Taymans + + common/check.mak: Added make forever target for check. + Original commit message from CVS: + * common/check.mak: + Added make forever target for check. + +2005-12-16 17:34:19 +0000 Thomas Vander Stichele + + gst/gst.c: make the registry cache file HOST_CPU-dependent + Original commit message from CVS: + * gst/gst.c: (init_post): + make the registry cache file HOST_CPU-dependent + +2005-12-16 14:44:49 +0000 Andy Wingo + + * ChangeLog: + * plugins/elements/gstbufferstore.c: + * tests/check/gst/gstobject.c: + plugins/elements/gstbufferstore.c + Original commit message from CVS: + 2005-12-16 Andy Wingo + * plugins/elements/gstbufferstore.c + (gst_buffer_store_cleared_func): Pay attention to g_list_append + return value. + * tests/check/gst/gstobject.c + (test_fake_object_name_threaded_unique): Pay attention to + g_list_sort return value. + +2005-12-16 11:52:00 +0000 Tim-Philipp Müller + + tools/gst-feedback-m.m: Update for 0.9/0.10 (fixes #323870). + Original commit message from CVS: + * tools/gst-feedback-m.m: + Update for 0.9/0.10 (fixes #323870). + +2005-12-15 12:22:38 +0000 Tim-Philipp Müller + + gst/gstminiobject.c: Fix lcopy for mini objects, the mini object needs to be ref'ed. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_value_mini_object_lcopy): + Fix lcopy for mini objects, the mini object needs to be ref'ed. + * tests/check/gst/gstminiobject.c: (my_foo_init), + (my_foo_get_property), (my_foo_set_property), (my_foo_class_init), + (test_value_collection), (gst_mini_object_suite): + Add test to ensure refcounts end up as expected when passing + GstMiniObjects through g_object_get() and g_object_set(). + +2005-12-14 17:08:36 +0000 Julien Moutte + + libs/gst/base/gstcollectpads.c: Refactoring of collectpads. This version removes a lot of races without touching API/... + Original commit message from CVS: + 2005-12-14 Julien MOUTTE + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_base_init), + (gst_collect_pads_remove_pad), (gst_collect_pads_is_collected), + (gst_collect_pads_event), (gst_collect_pads_chain): Refactoring + of collectpads. This version removes a lot of races without + touching API/ABI. Yay ! + +2005-12-14 10:09:35 +0000 Jan Schmidt + + gst/gstpad.c: Don't allow activation of a srcpad in pull_range if it has no getrange function. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_activate_pull), (gst_pad_link_prepare): + Don't allow activation of a srcpad in pull_range if it has no + getrange function. + Change some debug statements to be a little clearer + * plugins/elements/gsttypefindelement.c: + (gst_type_find_handle_src_query): + Check that we have a peer before executing queries thereupon. + * tests/examples/metadata/read-metadata.c: (message_loop): + Use gst_bus_pop instead of gst_bus_poll when we just want it to + immediately return us any available message with 0 timeout. + +2005-12-12 19:09:49 +0000 Michael Smith + + gst/gsttypefindfactory.c: Don't unref factories after calling them. + Original commit message from CVS: + * gst/gsttypefindfactory.c: (gst_type_find_factory_call_function): + Don't unref factories after calling them. + * libs/gst/base/gsttypefindhelper.c: (gst_type_find_helper): + * plugins/elements/gsttypefindelement.c: + (gst_type_find_element_chain): + Free lists of factories after using them. Fixing typefinding memory + leaks. + +2005-12-12 18:12:13 +0000 Stefan Kost + + gst/gstpluginfeature.c: more meaningful debug output + Original commit message from CVS: + * gst/gstpluginfeature.c: (gst_plugin_feature_finalize), + (gst_plugin_feature_load): + more meaningful debug output + * configure.ac: + * tests/Makefile.am: + * tests/old/examples/Makefile.am: + make make distcheck happy again + +2005-12-12 17:37:17 +0000 Thomas Vander Stichele + + * configure.ac: + remove all tests/old Makefiles from the build + Original commit message from CVS: + remove all tests/old Makefiles from the build + +2005-12-12 17:09:04 +0000 Tim-Philipp Müller + + plugins/elements/gsttypefindelement.c: Catch the special case where we are operating chain-based, but the downstream ... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (stop_typefinding): + Catch the special case where we are operating chain-based, + but the downstream peer pad has no chain function. Emit a + custom error message in this case instead of letting the + core generate one implying that this is some sort of core + bug. It's not, it just means that whatever got plugged + into the pipeline downstream when we announced the type + can only operate pull-based, while our source can only + operate push-based (e.g. http://foo/bar.mov ! qtdemux ! ...) + Error string has not been marked for translation yet, as + it probably needs some more work first. + (gst_type_find_element_get_best_possibility): + Add helper function to find the best of all available + found possibilities that qualify given the min. threshold. + (gst_type_find_element_handle_event): + Fix the case where we get an EOS while still in TYPEFIND + mode (we want to chose the best of all possible types, + not just the first type that happens to be in our unsorted + list of possible types). + (gst_type_find_element_chain): + Make sure we return GST_FLOW_ERROR when we errored out + in stop_typefinding(); also, don't just find the best of + all found type entries and then use the last examined + type entry, but actually use the best entry. + +2005-12-12 17:07:05 +0000 Tim-Philipp Müller + + tests/examples/: More gcc4 fixes and a mem leak fix. + Original commit message from CVS: + * tests/examples/typefind/typefind.c: (type_found): + * tests/examples/xml/runxml.c: (xml_loaded): + More gcc4 fixes and a mem leak fix. + +2005-12-12 16:20:47 +0000 Stefan Kost + + * tests/examples/xml/runxml.c: + more gcc 4 warning fixes + Original commit message from CVS: + more gcc 4 warning fixes + +2005-12-12 16:04:45 +0000 Stefan Kost + + * tests/examples/xml/createxml.c: + another gcc4 fix + Original commit message from CVS: + another gcc4 fix + +2005-12-12 15:59:48 +0000 Stefan Kost + + tests/examples/xml/createxml.c: gcc 4 fixes + Original commit message from CVS: + * tests/examples/xml/createxml.c: (object_saved): + gcc 4 fixes + +2005-12-12 15:46:16 +0000 Stefan Kost + + tests/Makefile.am: enable the examples even more + Original commit message from CVS: + * tests/Makefile.am: + enable the examples even more + +2005-12-12 15:02:02 +0000 Andy Wingo + + libs/gst/net/gstnettimeprovider.c (gst_net_time_provider_class_init, gst_net_time_provider_init) (gst_net_time_provid... + Original commit message from CVS: + 2005-12-12 Andy Wingo + * libs/gst/net/gstnettimeprovider.c + (gst_net_time_provider_class_init, gst_net_time_provider_init) + (gst_net_time_provider_set_property) + (gst_net_time_provider_get_property): Export "active" as a GObject + property. + (gst_net_time_provider_thread): Only respond to time queries if + the time provider is active. + * libs/gst/net/gstnettimeprovider.h: Add an "active" boolean to + NetTimeProvider, preserving binary compat. + +2005-12-12 14:46:06 +0000 Stefan Kost + + tests/examples/: convert comments again + Original commit message from CVS: + * tests/examples/controller/audio-example.c: (main): + * tests/examples/launch/Makefile.am: + convert comments again + +2005-12-12 14:43:57 +0000 Wim Taymans + + libs/gst/base/gstpushsrc.c: Fix typo. + Original commit message from CVS: + * libs/gst/base/gstpushsrc.c: + Fix typo. + +2005-12-12 14:42:11 +0000 Wim Taymans + + * ChangeLog: + Forgot the Changelog... + Original commit message from CVS: + Forgot the Changelog... + +2005-12-12 14:41:05 +0000 Wim Taymans + + docs/libs/gstreamer-libs-sections.txt: Added new symbol to docs. + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + Added new symbol to docs. + * libs/gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_set_format), + (gst_base_src_default_query), (gst_base_src_query), + (gst_base_src_default_do_seek), (gst_base_src_do_seek), + (gst_base_src_perform_seek), (gst_base_src_send_event), + (gst_base_src_default_event), (gst_base_src_event_handler), + (gst_base_src_set_property), (gst_base_src_get_property), + (gst_base_src_wait), (gst_base_src_do_sync), + (gst_base_src_update_length), (gst_base_src_get_range), + (gst_base_src_check_get_range), (gst_base_src_loop), + (gst_base_src_default_negotiate), (gst_base_src_start), + (gst_base_src_activate_push), (gst_base_src_activate_pull), + (gst_base_src_change_state): + * libs/gst/base/gstbasesrc.h: + Implement seeking to other formats than _BYTES. + Implement more seeking methods correctly. + Doc updates. + Added query vmethod. + Added do_seek vmethod to make life easier for subclasses + when seeking. + API addition: gst_base_src_set_format() + +2005-12-12 14:08:09 +0000 Stefan Kost + + tests/examples/Makefile.am: added that too + Original commit message from CVS: + * tests/examples/Makefile.am: + added that too + +2005-12-12 14:02:18 +0000 Stefan Kost + + applied some simple fixing to some examples re-enabled the working examples + Original commit message from CVS: + * configure.ac: + * docs/random/ensonic/media-device-daemon.txt: + * tests/examples/controller/.cvsignore: + * tests/examples/controller/Makefile.am: + * tests/examples/controller/audio-example.c: (main): + * tests/examples/helloworld/.cvsignore: + * tests/examples/helloworld/Makefile.am: + * tests/examples/helloworld/helloworld.c: (event_loop), (main): + * tests/examples/launch/.cvsignore: + * tests/examples/launch/Makefile.am: + * tests/examples/launch/mp3parselaunch.c: (event_loop), (main): + * tests/examples/metadata/.cvsignore: + * tests/examples/metadata/Makefile.am: + * tests/examples/metadata/read-metadata.c: (message_loop), + (make_pipeline), (print_tag), (main): + * tests/examples/queue/.cvsignore: + * tests/examples/queue/Makefile.am: + * tests/examples/queue/queue.c: (event_loop), (main): + * tests/examples/typefind/.cvsignore: + * tests/examples/typefind/Makefile.am: + * tests/examples/typefind/typefind.c: (type_found), (event_loop), + (main): + * tests/examples/xml/.cvsignore: + * tests/examples/xml/Makefile.am: + * tests/examples/xml/createxml.c: (object_saved), (main): + * tests/examples/xml/runxml.c: (xml_loaded), (event_loop), (main): + * tests/old/examples/Makefile.am: + * tests/old/examples/TODO: + * tests/old/examples/controller/.cvsignore: + * tests/old/examples/controller/Makefile.am: + * tests/old/examples/controller/audio-example.c: + * tests/old/examples/helloworld/.cvsignore: + * tests/old/examples/helloworld/Makefile.am: + * tests/old/examples/helloworld/helloworld.c: + * tests/old/examples/launch/.cvsignore: + * tests/old/examples/launch/Makefile.am: + * tests/old/examples/launch/mp3parselaunch.c: + * tests/old/examples/launch/mp3play: + * tests/old/examples/manual/Makefile.am: + * tests/old/examples/metadata/Makefile.am: + * tests/old/examples/metadata/read-metadata.c: + * tests/old/examples/queue/.cvsignore: + * tests/old/examples/queue/Makefile.am: + * tests/old/examples/queue/queue.c: + * tests/old/examples/typefind/.cvsignore: + * tests/old/examples/typefind/Makefile.am: + * tests/old/examples/typefind/typefind.c: + * tests/old/examples/xml/.cvsignore: + * tests/old/examples/xml/Makefile.am: + * tests/old/examples/xml/createxml.c: + * tests/old/examples/xml/runxml.c: + applied some simple fixing to some examples + re-enabled the working examples + +2005-12-12 12:48:35 +0000 Wim Taymans + + gst/gstsegment.c: Added more documentation. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_init), + (gst_segment_set_last_stop), (gst_segment_set_seek), + (gst_segment_set_newsegment), (gst_segment_to_stream_time), + (gst_segment_to_running_time): + Added more documentation. + Make sure the last_pos value is updated properly. + Make sure to_stream_time and to_running_time don't + operate on wrong values. + * tests/check/gst/gstsegment.c: (GST_START_TEST): + Update check. + +2005-12-12 12:32:04 +0000 Michael Smith + + plugins/elements/gsttypefindelement.c: Now that we're not leaking factories, make sure we keep references to them whi... + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (free_entry), + (gst_type_find_element_chain): + Now that we're not leaking factories, make sure we keep references + to them while we need them. + +2005-12-12 11:40:11 +0000 Thomas Vander Stichele + + tests/check/gst/struct_i386.h: ifdef out the XML structs + Original commit message from CVS: + * tests/check/gst/struct_i386.h: + ifdef out the XML structs + +2005-12-12 10:59:12 +0000 Thomas Vander Stichele + + gst/gstvalue.c: floor is not needed, F is always positive; this obviates the need for adding -lm when building withou... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_transform_double_fraction): + floor is not needed, F is always positive; this obviates the + need for adding -lm when building without libxml + +2005-12-12 10:57:37 +0000 Thomas Vander Stichele + + * docs/random/aspectratio: + * tests/check/gst/gstbus.c: + add a ; and an example + Original commit message from CVS: + add a ; and an example + +2005-12-12 10:16:11 +0000 Wim Taymans + + libs/gst/base/gstbasesink.c: Take current playback rate into account when reporting the position. + Original commit message from CVS: + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position): + Take current playback rate into account when reporting + the position. + +2005-12-11 19:35:02 +0000 Tim-Philipp Müller + + docs/manual/mime-world.fig: Let's try this again, this time with a file that is actually in XFig format. + Original commit message from CVS: + * docs/manual/mime-world.fig: + Let's try this again, this time with a file that is + actually in XFig format. + +2005-12-11 19:19:09 +0000 Tim-Philipp Müller + + docs/manual/mime-world.fig: Add audioconvert element to diagram so that it matches the text and the code (fixes #3195... + Original commit message from CVS: + * docs/manual/mime-world.fig: + Add audioconvert element to diagram so that it + matches the text and the code (fixes #319526). + +2005-12-11 18:24:27 +0000 Tim-Philipp Müller + + docs/pwg/: Update state change stuff for 0.10 (fixes #322969). + Original commit message from CVS: + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/building-state.xml: + * docs/pwg/other-source.xml: + Update state change stuff for 0.10 (fixes #322969). + +2005-12-11 17:49:10 +0000 Tim-Philipp Müller + + docs/manual/: Update for 0.10: s/0.9/0.10/; s/audioscale/audiorsample/; add converters in front of pipelines; remove ... + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/appendix-programs.xml: + * docs/manual/basics-pads.xml: + * docs/manual/highlevel-components.xml: + * docs/manual/manual.xml: + Update for 0.10: s/0.9/0.10/; s/audioscale/audiorsample/; + add converters in front of pipelines; remove curly + brackets for threads stuff, they no longer exist; use + GST_TYPE_FRACTION for framerates; update some pieces of + code to 0.10, but there's plenty more to do. + * docs/manual/appendix-porting.xml: + Expand on asynchroneous state changes; s/0.9/0.10/; + mention disappearance of gst_init_get_popt_table() + (fixes #322916). + +2005-12-11 11:53:56 +0000 Tim-Philipp Müller + + docs/faq/using.xml: Spider no longer exists, and neither does gst-launch-ext. + Original commit message from CVS: + * docs/faq/using.xml: + Spider no longer exists, and neither does gst-launch-ext. + Update examples to use decodebin and playbin and put + converters in front of sinks (fixes #323726). + +2005-12-09 17:26:31 +0000 Michael Smith + + plugins/elements/gsttypefindelement.c: Fix leaking element factories in typefinding. + Original commit message from CVS: + * plugins/elements/gsttypefindelement.c: (find_peek), + (gst_type_find_element_chain): + Fix leaking element factories in typefinding. + Fix problem where we forgot about a probable type on non-seekable + files, and thus later mis-typefound it. + +2005-12-09 15:09:42 +0000 Michael Smith + + Remove makecontext stuff; not used in 0.10 and causes problems on + Original commit message from CVS: + * common/m4/gst-makecontext.m4: + * common/m4/gst-mcsc.m4: + * configure.ac: + * win32/common/config.h: + * win32/common/config.h.in: + Remove makecontext stuff; not used in 0.10 and causes problems on + HPUX according to bug #322441 + +2005-12-07 19:03:54 +0000 Wim Taymans + + tests/check/: Added ABI check for libs, this time for real + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/libsabi.c: (GST_START_TEST), (gstabi_suite), + (main): + * tests/check/libs/struct_i386.h: + Added ABI check for libs, this time for real + +2005-12-07 19:03:08 +0000 Wim Taymans + + tests/check/: Added ABI check for libs + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/libsabi.c: (GST_START_TEST), (gstabi_suite), + (main): + * tests/check/libs/struct_i386.h: + Added ABI check for libs + +2005-12-07 17:59:21 +0000 Wim Taymans + + tests/check/Makefile.am: And add the struct_i386.h to dist. + Original commit message from CVS: + * tests/check/Makefile.am: + And add the struct_i386.h to dist. + +2005-12-07 17:36:44 +0000 Wim Taymans + + tests/check/: Added check for ABI compatibility. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/gstabi.c: (GST_START_TEST), (gstabi_suite), + (main): + * tests/check/gst/struct_i386.h: + Added check for ABI compatibility. + +2005-12-07 15:33:42 +0000 Wim Taymans + + plugins/elements/gstfakesrc.c: Fix broken sync option, fixes #323259 + Original commit message from CVS: + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_get_times), (gst_fake_src_create): + Fix broken sync option, fixes #323259 + +2005-12-07 15:16:43 +0000 Wim Taymans + + gst/gstbuffer.c: Small docs update. + Original commit message from CVS: + * gst/gstbuffer.c: + Small docs update. + * gst/gstcaps.c: (gst_caps_is_equal): + Don't assert on NULL <--> X. Fixes #323260 + * gst/gstminiobject.c: (gst_mini_object_replace): + If we're doing atomic operations, we might just as well use + the proper way to get an atomic pointer. + * libs/gst/base/gstbasesink.c: (gst_base_sink_get_position): + Clean up debugging. + +2005-12-07 11:52:05 +0000 Michael Smith + + gst/parse/grammar.y: Remove handling of { } for threads. + Original commit message from CVS: + * gst/parse/grammar.y: + Remove handling of { } for threads. + +2005-12-06 23:32:01 +0000 David Schleef + + libs/gst/base/gstbasetransform.c: speling fix. + Original commit message from CVS: + * libs/gst/base/gstbasetransform.c: speling fix. + +2005-12-06 19:29:15 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/random/omega/testing/gstobject.c: + * gst/gst.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstghostpad.c: + * gst/gstinfo.c: + * gst/gstpadtemplate.c: + * gst/gstregistryxml.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttypefind.c: + * gst/gstvalue.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnettimeprovider.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + * tests/check/gst/gsttag.c: + * tests/old/examples/cutter/cutter.c: + * tests/old/examples/mixer/mixer.c: + * tests/old/examples/xml/runxml.c: + * tests/old/testsuite/caps/normalisation.c: + * tests/old/testsuite/debug/global.c: + * tests/old/testsuite/parse/parse1.c: + * tools/gst-xmlinspect.c: + * win32/common/dirent.c: + expand tabs + Original commit message from CVS: + expand tabs + +2005-12-06 19:04:49 +0000 Thomas Vander Stichele + + * win32/common/config.h: + back to cvs + Original commit message from CVS: + back to cvs + +2005-12-05 18:13:00 +0000 Thomas Vander Stichele + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.0 === + +2005-12-05 18:05:01 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + releasing 0.10.0 + Original commit message from CVS: + releasing 0.10.0 + +2005-12-05 15:57:48 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.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 + Original commit message from CVS: + Update .po files + +2005-12-05 14:36:05 +0000 Thomas Vander Stichele + + po/: added Chinese (Traditional) translation + Original commit message from CVS: + submitted by: Funda Wang + * po/LINGUAS: + * po/zh_CN.po: + added Chinese (Traditional) translation + +2005-12-05 14:14:39 +0000 Thomas Vander Stichele + + * po/af.po: + updated Afrikaans translation + Original commit message from CVS: + updated Afrikaans translation + +2005-12-05 14:14:02 +0000 Thomas Vander Stichele + + * gst/gstpad.h: + remove deprecation guard from docstring + Original commit message from CVS: + remove deprecation guard from docstring + +2005-12-05 13:10:44 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + update translations + Original commit message from CVS: + update translations + +2005-12-05 13:06:37 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/random/thomasvs/TODO: + * gst/gstutils.c: + * gst/gstutils.h: + fix docs + Original commit message from CVS: + fix docs + +2005-12-05 13:01:35 +0000 Wim Taymans + + libs/gst/base/gstbasetransform.c (gst_base_transform_prepare_output_buf) + Original commit message from CVS: + 2005-12-05 Andy Wingo + patch by: Wim Taymans + * libs/gst/base/gstbasetransform.c + (gst_base_transform_prepare_output_buf) + (gst_base_transform_buffer_alloc): + * plugins/elements/gstqueue.c (gst_queue_bufferalloc): Call + alloc_buffer_and_set_caps. + * gst/gstpad.c (gst_pad_alloc_buffer): Changed to not call + set_caps on the source pad. + (gst_pad_alloc_buffer_and_set_caps): New function, does what + alloc_buffer used to do. Fixes #322874. + * docs/gst/gstreamer-sections.txt: + * docs/design/part-negotiation.txt: + * docs/pwg/advanced-negotiation.xml: Update for the alloc_buffer + changes. + +2005-12-05 12:33:44 +0000 Thomas Vander Stichele + + * tests/check/gst/gstutils.c: + really add the tests for the 64/double conversion + Original commit message from CVS: + really add the tests for the 64/double conversion + +2005-12-05 12:09:43 +0000 Thomas Vander Stichele + + * win32/common/libgstcontroller.def: + add def for controller + Original commit message from CVS: + add def for controller + +2005-12-05 12:09:01 +0000 Sebastien Moutte + + win32/: win32 build fixes + Original commit message from CVS: + patch by: Sebastien Moutte + * win32/MANIFEST: + * win32/common/config.h.in: + * win32/vs6/libgstcontroller.dsp: + win32 build fixes + +2005-12-05 10:59:17 +0000 Wim Taymans + + Back out previous code changes, leave doc updates, file bugs instead. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_is_equal): + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_create): + Back out previous code changes, leave doc updates, file bugs + instead. + +2005-12-05 10:27:59 +0000 Wim Taymans + + plugins/elements/gstfakesrc.*: Fix broken sync code. + Original commit message from CVS: + * plugins/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_get_times), (gst_fake_src_create): + * plugins/elements/gstfakesrc.h: + Fix broken sync code. + +2005-12-05 10:22:55 +0000 Wim Taymans + + gst/gstcaps.c: Comparing NULL against !NULL yields different caps, not a failure. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_is_equal): + Comparing NULL against !NULL yields different caps, not a + failure. + +2005-12-05 10:18:27 +0000 Wim Taymans + + gst/gstpipeline.c: Fix small typo in docs. + Original commit message from CVS: + * gst/gstpipeline.c: + Fix small typo in docs. + +2005-12-05 09:53:54 +0000 Thomas Vander Stichele + + gst/gst.c (init_post): remove hard-coded 0.9 location for registries/plugins with a MAJORMINOR one. + Original commit message from CVS: + 2005-12-05 Andy Wingo + patch by: Thomas Vander Stichele + * gst/gst.c (init_post): remove hard-coded 0.9 location for + registries/plugins with a MAJORMINOR one. + (plugin_desc): Rename library from gstcoreleements to + staticelements. Fixes #323222. + +2005-12-05 09:45:29 +0000 Tim-Philipp Müller + + libs/gst/base/gstcollectpads.c: Change debug category to 'collectpads' from 'collect_pads' (fixes #323250). + Original commit message from CVS: + * libs/gst/base/gstcollectpads.c: (gst_collect_pads_base_init): + Change debug category to 'collectpads' from 'collect_pads' + (fixes #323250). + +2005-12-04 19:57:26 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + rename two exports + Original commit message from CVS: + rename two exports + +2005-12-04 18:54:19 +0000 Sebastien Moutte + + libs/gst/controller/gstinterpolation.c: use convert function for uint64/double + Original commit message from CVS: + patch by: Sebastien Moutte + * libs/gst/controller/gstinterpolation.c: + use convert function for uint64/double + * win32/vs6/libgstcontroller.dsp: + link to GLib + +2005-12-04 09:57:11 +0000 Thomas Vander Stichele + + add tests that seem to show that the guint64/gdouble conversions are correct. + Original commit message from CVS: + * gst/gstutils.c: (gst_util_guint64_to_gdouble), + (gst_util_gdouble_to_guint64), (gst_util_uint64_scale_int64): + * gst/gstutils.h: + * tests/check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + add tests that seem to show that the guint64/gdouble conversions + are correct. + +2005-12-02 12:44:53 +0000 Christian Schaller + + * gstreamer.spec.in: + make version number a little less hopefull + Original commit message from CVS: + make version number a little less hopefull + +2005-12-02 12:34:47 +0000 Wim Taymans + + gst/: Fix docs again. + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_add_path): + * gst/gstregistry.h: + * gst/gstregistryxml.c: + Fix docs again. + Removed old code from gstregistryxml.c + +2005-12-02 12:19:55 +0000 Christian Schaller + + * gstreamer.spec.in: + fix updating gstreamer spec file making it 0.10 ready + Original commit message from CVS: + fix updating gstreamer spec file making it 0.10 ready + +2005-12-02 11:36:50 +0000 Wim Taymans + + gst/gstutils.c: Small cleanup. + Original commit message from CVS: + * gst/gstutils.c: (gst_util_uint64_scale_int64), + (gst_util_uint64_scale_int): + Small cleanup. + * libs/gst/base/gstbasesink.c: (gst_base_sink_handle_object): + Add debug log line. + * libs/gst/base/gstbasetransform.c: (gst_base_transform_event): + Add FIXME. + +2005-12-02 09:48:17 +0000 Thomas Vander Stichele + + win32/: renamed core elements plugin + Original commit message from CVS: + * win32/MANIFEST: + * win32/common/config.h: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstcoreelements.dsp: + * win32/vs6/libgstelements.dsp: + renamed core elements plugin + +2005-12-02 01:35:22 +0000 Thomas Vander Stichele + + tools/gst-run.c: do piece-wise major/minor comparison so 0.9 < 0.10 also allow .exe extensions for tools + Original commit message from CVS: + * tools/gst-run.c: (compare_major_minor), (find_highest_version), + (get_candidates): + do piece-wise major/minor comparison so 0.9 < 0.10 + also allow .exe extensions for tools + +2005-12-01 23:57:07 +0000 Michael Smith + + gst/gst.c: Escape a % to make gtkdoc happier; bug 322958. + Original commit message from CVS: + * gst/gst.c: + Escape a % to make gtkdoc happier; bug 322958. + +2005-12-01 19:18:57 +0000 Thomas Vander Stichele + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.9.7 === + +2005-12-01 19:11:56 +0000 Thomas Vander Stichele + + * CHANGES-0.9: + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * win32/common/config.h: + releasing 0.9.7 + Original commit message from CVS: + releasing 0.9.7 + +2005-12-01 16:51:23 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * configure.ac: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/random/release: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * win32/common/config.h: + * win32/common/config.h.in: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstelements.dsp: + * win32/vs6/libgstreamer.dsp: + * win32/vs7/GStreamer.vcproj: + * win32/vs7/gst-inspect.vcproj: + * win32/vs7/gst-launch.vcproj: + * win32/vs7/libgstbase.vcproj: + bump GST_MAJORMINOR to 0.10 reset libtool version + Original commit message from CVS: + bump GST_MAJORMINOR to 0.10 + reset libtool version + +2005-12-01 15:28:25 +0000 Thomas Vander Stichele + + * tools/gst-feedback-0.7: + remove old file + Original commit message from CVS: + remove old file + +2005-12-01 15:18:41 +0000 Thomas Vander Stichele + + * docs/plugins/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-12-01 15:08:09 +0000 Thomas Vander Stichele + + * ChangeLog: + * po/LINGUAS: + * po/bg.po: + Added Bulgarian translation by (Alexander Shopov) + Original commit message from CVS: + Added Bulgarian translation by (Alexander Shopov) + +2005-12-01 15:04:03 +0000 Thomas Vander Stichele + + * docs/plugins/inspect-build.stamp: + commit final stamp file + Original commit message from CVS: + commit final stamp file + +2005-12-01 14:51:07 +0000 Thomas Vander Stichele + + * docs/plugins/gstreamer-plugins.hierarchy: + * docs/plugins/gstreamer-plugins.interfaces: + * docs/plugins/gstreamer-plugins.prerequisites: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + add more files for distcheck + Original commit message from CVS: + add more files for distcheck + +2005-12-01 14:40:47 +0000 Thomas Vander Stichele + + * docs/plugins/gstreamer-plugins.args: + * docs/plugins/gstreamer-plugins.signals: + add signals and args + Original commit message from CVS: + add signals and args + +2005-12-01 12:36:10 +0000 Thomas Vander Stichele + + * ChangeLog: + * tests/check/gst/gstplugin.c: + fix test + Original commit message from CVS: + fix test + +2005-12-01 12:29:34 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * configure.ac: + * docs/Makefile.am: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/gstreamer.types.in: + * docs/plugins/Makefile.am: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.types: + * docs/plugins/inspect.stamp: + * docs/plugins/inspect/plugin-coreelements.xml: + * docs/plugins/inspect/plugin-coreindexers.xml: + * docs/plugins/scanobj-build.stamp: + * gstreamer.spec.in: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstqueue.c: + * plugins/indexers/Makefile.am: + * plugins/indexers/gstindexers.c: + document core plugins in a separate document just like all the others rename these plugins to something starting with... + Original commit message from CVS: + document core plugins in a separate document just like all the + others + rename these plugins to something starting with core + +2005-12-01 12:00:56 +0000 Andy Wingo + + gst/gstevent.h (struct _GstEvent): Meant to remove the extra padding here before, but it missed the commit. + Original commit message from CVS: + 2005-12-01 Andy Wingo + * gst/gstevent.h (struct _GstEvent): Meant to remove the extra + padding here before, but it missed the commit. + +2005-12-01 10:07:26 +0000 Thomas Vander Stichele + + * libs/gst/controller/gsthelper.c: + * win32/common/libgstreamer.def: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstcontroller.dsp: + add libgstcontroller to the build + Original commit message from CVS: + add libgstcontroller to the build + +2005-12-01 09:54:56 +0000 Thomas Vander Stichele + + libs/gst/controller/gstinterpolation.c: whitespace prices have crashed, we should feel free to use some now use gst_g... + Original commit message from CVS: + * libs/gst/controller/gstinterpolation.c: + whitespace prices have crashed, we should feel free to use some now + use gst_guint64_to_gdouble + +2005-12-01 09:32:17 +0000 Thomas Vander Stichele + + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + fix typo + Original commit message from CVS: + fix typo + +2005-12-01 09:23:20 +0000 Thomas Vander Stichele + + * ChangeLog: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/lib.c: + wrap config.h include + Original commit message from CVS: + wrap config.h include + +2005-12-01 02:08:18 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + update docs + Original commit message from CVS: + update docs + +2005-12-01 00:54:54 +0000 Thomas Vander Stichele + + plugins/elements/: more anal cleanup + Original commit message from CVS: + * plugins/elements/gstelements.c: + * plugins/elements/gstfdsink.c: (gst_fd_sink__base_init), + (gst_fd_sink__class_init), (gst_fd_sink__init), + (gst_fd_sink__chain), (gst_fd_sink__set_property), + (gst_fd_sink__get_property): + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.c: (_do_init), (gst_fd_src_base_init), + (gst_fd_src_class_init), (gst_fd_src_init), (gst_fd_src_dispose), + (gst_fd_src_update_fd), (gst_fd_src_start), (gst_fd_src_stop), + (gst_fd_src_unlock), (gst_fd_src_set_property), + (gst_fd_src_get_property), (gst_fd_src_create), + (gst_fd_src_is_seekable), (gst_fd_src_get_size), + (gst_fd_src_uri_get_type), (gst_fd_src_uri_get_protocols), + (gst_fd_src_uri_get_uri), (gst_fd_src_uri_set_uri), + (gst_fd_src_uri_handler_init): + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstqueue.c: (gst_queue_get_type): + more anal cleanup + +2005-11-30 19:36:54 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/Makefile.am: + * docs/gst/gstreamer.types.in: + * gst/Makefile.am: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + fix the docs build + Original commit message from CVS: + fix the docs build + +2005-11-30 19:03:59 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer.types.in: + add new input types file + Original commit message from CVS: + add new input types file + +2005-11-30 19:01:53 +0000 Thomas Vander Stichele + + various fixes to make + Original commit message from CVS: + * configure.ac: + * gst/Makefile.am: + * gst/gst.c: + * gst/gstplugin.h: + * gst/gstregistry.h: + * tests/benchmarks/complexity.c: + * tests/benchmarks/mass-elements.c: + * tests/check/Makefile.am: + * tools/Makefile.am: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + various fixes to make + --disable-nls --disable-registry --disable-loadsave --disable-parse --disable-gst-debug + work and get the core .so down to 360444 bytes after stripping + +2005-11-30 17:05:29 +0000 Thomas Vander Stichele + + * docs/libs/tmpl/gstdataprotocol.sgml: + * tests/check/Makefile.am: + move location of test registry + Original commit message from CVS: + move location of test registry + +2005-11-30 16:45:54 +0000 Thomas Vander Stichele + + * tests/check/pipelines/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-11-30 16:45:15 +0000 Thomas Vander Stichele + + * tests/misc/Makefile.am: + missing makefile + Original commit message from CVS: + missing makefile + +2005-11-30 16:43:16 +0000 Thomas Vander Stichele + + * scripts/cvs-update.sh: + prune empty dirs when updating + Original commit message from CVS: + prune empty dirs when updating + +2005-11-30 16:42:27 +0000 Thomas Vander Stichele + + * DOCBUILDING: + * docs/README: + remove empty dirs; move docbuilding notes + Original commit message from CVS: + remove empty dirs; move docbuilding notes + +2005-11-30 16:39:04 +0000 Thomas Vander Stichele + + descend into tests + Original commit message from CVS: + * Makefile.am: + * configure.ac: + descend into tests + * docs/random/thomasvs/TODO: + * tests/Makefile.am: + * tests/README: + add a README + +2005-11-30 16:32:22 +0000 Thomas Vander Stichele + + * tests/benchmarks/.gitignore: + * tests/check/generic/.gitignore: + * tests/check/libs/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-11-30 16:30:41 +0000 Thomas Vander Stichele + + * README: + update README + Original commit message from CVS: + update README + +2005-11-30 16:29:28 +0000 Thomas Vander Stichele + + * common: + * tests/check/Makefile.am: + don't fail on missing registry + Original commit message from CVS: + don't fail on missing registry + +2005-11-30 16:28:17 +0000 Thomas Vander Stichele + + * win32/README.txt: + add a README + Original commit message from CVS: + add a README + +2005-11-30 16:26:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * win32/GStreamer.vcproj: + * win32/MANIFEST: + * win32/Makefile: + * win32/Makefile.inspect: + * win32/Makefile.launch: + * win32/Makefile.register: + * win32/README.txt: + * win32/gst-inspect.vcproj: + * win32/gst-launch.vcproj: + * win32/gst-register.vcproj: + * win32/gstelements.vcproj: + * win32/gstgetbits.def: + * win32/gstgetbits.vcproj: + * win32/gstreamer-dbg.def: + * win32/gstreamer.def: + * win32/libgstbase.def: + * win32/libgstbase.vcproj: + * win32/link_oldruntime.c: + * win32/mman.c: + * win32/mman.h: + * win32/mman.inl: + * win32/msvc71.sln: + move even more stuff, win32/ is nice and clean now + Original commit message from CVS: + move even more stuff, win32/ is nice and clean now + +2005-11-30 16:17:23 +0000 Thomas Vander Stichele + + * ChangeLog: + * libs/gst/control/.gitignore: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * win32/MANIFEST: + * win32/config.h: + * win32/dirent.c: + * win32/dirent.h: + * win32/gstbytestream.def: + * win32/gstbytestream.vcproj: + * win32/gstconfig.h: + * win32/gstenumtypes.c: + * win32/gstenumtypes.h: + * win32/gstoptimalscheduler.vcproj: + * win32/gstversion.h: + * win32/gtchar.h: + * win32/testsuite/bins.vcproj: + * win32/testsuite/bytestream.vcproj: + * win32/testsuite/caps.vcproj: + * win32/testsuite/cleanup.vcproj: + * win32/testsuite/clock.vcproj: + * win32/testsuite/debug.vcproj: + * win32/testsuite/dlopen.vcproj: + * win32/testsuite/dynparams.vcproj: + * win32/testsuite/elements.vcproj: + * win32/testsuite/ghostpads.vcproj: + * win32/testsuite/indexers.vcproj: + * win32/testsuite/negotiation.vcproj: + * win32/testsuite/parse.vcproj: + * win32/testsuite/plugin.vcproj: + * win32/testsuite/refcounting.vcproj: + * win32/testsuite/schedulers.vcproj: + * win32/testsuite/states.vcproj: + * win32/testsuite/tags.vcproj: + * win32/testsuite/threads.vcproj: + remove old win32 stuff that isn't maintained and should be reorganized + Original commit message from CVS: + remove old win32 stuff that isn't maintained and should be + reorganized + +2005-11-30 16:12:48 +0000 Thomas Vander Stichele + + * libs/gst/getbits/.gitignore: + remove getbits + Original commit message from CVS: + remove getbits + +2005-11-30 16:10:57 +0000 Andy Wingo + + configure.ac (GST_PKG_DEPS): Revert previous patch, makes loading the gst.interfaces python module bork. + Original commit message from CVS: + 2005-11-30 Andy Wingo + * configure.ac (GST_PKG_DEPS): Revert previous patch, makes + loading the gst.interfaces python module bork. + * configure.ac (GST_PKG_DEPS): Use gmodule-no-export-2.0.pc, + available since GLib 2.2. Fixes #318031. + +2005-11-30 16:08:31 +0000 Thomas Vander Stichele + + * ChangeLog: + * Makefile.am: + * check/.gitignore: + * check/Makefile.am: + * check/elements/.gitignore: + * check/elements/fakesrc.c: + * check/elements/fdsrc.c: + * check/elements/identity.c: + * check/generic/.gitignore: + * check/generic/states.c: + * check/gst-libs/.gitignore: + * check/gst-libs/controller.c: + * check/gst-libs/gdp.c: + * check/gst/.gitignore: + * check/gst/capslist.h: + * check/gst/gst.c: + * check/gst/gstbin.c: + * check/gst/gstbuffer.c: + * check/gst/gstbus.c: + * check/gst/gstcaps.c: + * check/gst/gstelement.c: + * check/gst/gstevent.c: + * check/gst/gstghostpad.c: + * check/gst/gstiterator.c: + * check/gst/gstmessage.c: + * check/gst/gstminiobject.c: + * check/gst/gstobject.c: + * check/gst/gstpad.c: + * check/gst/gstpipeline.c: + * check/gst/gstplugin.c: + * check/gst/gstsegment.c: + * check/gst/gststructure.c: + * check/gst/gstsystemclock.c: + * check/gst/gsttag.c: + * check/gst/gstutils.c: + * check/gst/gstvalue.c: + * check/net/.gitignore: + * check/net/gstnetclientclock.c: + * check/net/gstnettimeprovider.c: + * check/pipelines/.gitignore: + * check/pipelines/cleanup.c: + * check/pipelines/simple_launch_lines.c: + * check/pipelines/stress.c: + * check/states/.gitignore: + * check/states/sinks.c: + * configure.ac: + * examples/Makefile.am: + * examples/appreader/.gitignore: + * examples/appreader/Makefile.am: + * examples/appreader/appreader.c: + * examples/controller/.gitignore: + * examples/controller/Makefile.am: + * examples/controller/audio-example.c: + * examples/cutter/.gitignore: + * examples/cutter/Makefile.am: + * examples/cutter/cutter.c: + * examples/cutter/cutter.h: + * examples/events/Makefile.am: + * examples/events/seek.c: + * examples/helloworld/.gitignore: + * examples/helloworld/Makefile.am: + * examples/helloworld/helloworld.c: + * examples/helloworld2/.gitignore: + * examples/helloworld2/Makefile.am: + * examples/helloworld2/helloworld2.c: + * examples/launch/.gitignore: + * examples/launch/Makefile.am: + * examples/launch/mp3parselaunch.c: + * examples/launch/mp3play: + * examples/manual/.gitignore: + * examples/manual/Makefile.am: + * examples/manual/extract.pl: + * examples/metadata/Makefile.am: + * examples/metadata/read-metadata.c: + * examples/mixer/.gitignore: + * examples/mixer/Makefile.am: + * examples/mixer/mixer.c: + * examples/mixer/mixer.h: + * examples/pingpong/.gitignore: + * examples/pingpong/Makefile.am: + * examples/pingpong/pingpong.c: + * examples/plugins/.gitignore: + * examples/plugins/Makefile.am: + * examples/plugins/example.c: + * examples/plugins/example.h: + * examples/pwg/.gitignore: + * examples/pwg/Makefile.am: + * examples/pwg/extract.pl: + * examples/queue/.gitignore: + * examples/queue/Makefile.am: + * examples/queue/queue.c: + * examples/queue2/.gitignore: + * examples/queue2/Makefile.am: + * examples/queue2/queue2.c: + * examples/queue3/.gitignore: + * examples/queue3/Makefile.am: + * examples/queue3/queue3.c: + * examples/queue4/.gitignore: + * examples/queue4/Makefile.am: + * examples/queue4/queue4.c: + * examples/retag/.gitignore: + * examples/retag/Makefile.am: + * examples/retag/retag.c: + * examples/retag/transcode.c: + * examples/thread/.gitignore: + * examples/thread/Makefile.am: + * examples/thread/thread.c: + * examples/typefind/.gitignore: + * examples/typefind/Makefile.am: + * examples/typefind/typefind.c: + * examples/xml/.gitignore: + * examples/xml/Makefile.am: + * examples/xml/createxml.c: + * examples/xml/runxml.c: + * tests/Makefile.am: + * tests/check/Makefile.am: + * testsuite/.gitignore: + * testsuite/Makefile.am: + * testsuite/Rules: + * testsuite/caps/.gitignore: + * testsuite/caps/Makefile.am: + * testsuite/caps/app_fixate.c: + * testsuite/caps/audioscale.c: + * testsuite/caps/caps.c: + * testsuite/caps/caps.h: + * testsuite/caps/caps_strings: + * testsuite/caps/compatibility.c: + * testsuite/caps/deserialize.c: + * testsuite/caps/enumcaps.c: + * testsuite/caps/eratosthenes.c: + * testsuite/caps/filtercaps.c: + * testsuite/caps/fixed.c: + * testsuite/caps/fraction-convert.c: + * testsuite/caps/fraction-multiply-and-zero.c: + * testsuite/caps/intersect2.c: + * testsuite/caps/intersection.c: + * testsuite/caps/normalisation.c: + * testsuite/caps/random.c: + * testsuite/caps/renegotiate.c: + * testsuite/caps/sets.c: + * testsuite/caps/simplify.c: + * testsuite/caps/string-conversions.c: + * testsuite/caps/structure.c: + * testsuite/caps/subtract.c: + * testsuite/caps/union.c: + * testsuite/debug/.gitignore: + * testsuite/debug/Makefile.am: + * testsuite/debug/category.c: + * testsuite/debug/commandline.c: + * testsuite/debug/global.c: + * testsuite/debug/output.c: + * testsuite/debug/printf_extension.c: + * testsuite/dlopen/.gitignore: + * testsuite/dlopen/Makefile.am: + * testsuite/dlopen/dlopen_gst.c: + * testsuite/dlopen/loadgst.c: + * testsuite/elements/.gitignore: + * testsuite/elements/Makefile.am: + * testsuite/elements/gst-inspect-check.in: + * testsuite/elements/struct_i386.h: + * testsuite/elements/struct_size.c: + * testsuite/indexers/.gitignore: + * testsuite/indexers/Makefile.am: + * testsuite/indexers/cache1.c: + * testsuite/indexers/indexdump.c: + * testsuite/parse/.gitignore: + * testsuite/parse/Makefile.am: + * testsuite/parse/parse1.c: + * testsuite/parse/parse2.c: + * testsuite/plugin/.gitignore: + * testsuite/plugin/Makefile.am: + * testsuite/plugin/README: + * testsuite/plugin/dynamic.c: + * testsuite/plugin/linked.c: + * testsuite/plugin/loading.c: + * testsuite/plugin/registry.c: + * testsuite/plugin/static.c: + * testsuite/plugin/static2.c: + * testsuite/plugin/testplugin.c: + * testsuite/plugin/testplugin2.c: + * testsuite/plugin/testplugin2_s.c: + * testsuite/plugin/testplugin_s.c: + * testsuite/refcounting/.gitignore: + * testsuite/refcounting/Makefile.am: + * testsuite/refcounting/bin.c: + * testsuite/refcounting/element.c: + * testsuite/refcounting/element_pad.c: + * testsuite/refcounting/mainloop.c: + * testsuite/refcounting/mem.c: + * testsuite/refcounting/mem.h: + * testsuite/refcounting/object.c: + * testsuite/refcounting/pad.c: + * testsuite/refcounting/sched.c: + * testsuite/refcounting/thread.c: + * testsuite/states/.gitignore: + * testsuite/states/Makefile.am: + * testsuite/states/bin.c: + * testsuite/states/locked.c: + * testsuite/states/parent.c: + * testsuite/threads/.gitignore: + * testsuite/threads/159566.c: + * testsuite/threads/159852.c: + * testsuite/threads/Makefile.am: + * testsuite/threads/queue.c: + * testsuite/threads/signals.c: + * testsuite/threads/staticrec.c: + * testsuite/threads/thread.c: + * testsuite/threads/threadb.c: + * testsuite/threads/threadc.c: + * testsuite/threads/threadd.c: + * testsuite/threads/threade.c: + * testsuite/threads/threadf.c: + * testsuite/threads/threadg.c: + * testsuite/threads/threadh.c: + * testsuite/threads/threadi.c: + move all of these under tests + Original commit message from CVS: + move all of these under tests + +2005-11-30 15:37:36 +0000 Christian Schaller + + * gstreamer.spec.in: + update after thomas's CVS surgery + Original commit message from CVS: + update after thomas's CVS surgery + +2005-11-30 15:34:37 +0000 Thomas Vander Stichele + + * tests/benchmarks/.gitignore: + * tests/benchmarks/Makefile.am: + add Makefile.am + Original commit message from CVS: + add Makefile.am + +2005-11-30 15:29:05 +0000 Thomas Vander Stichele + + fix distcheck + Original commit message from CVS: + * configure.ac: + * tests/Makefile.am: + fix distcheck + +2005-11-30 15:20:29 +0000 Thomas Vander Stichele + + * tests/old/testsuite/caps/deserialize.c: + * tests/old/testsuite/caps/intersection.c: + * tests/old/testsuite/caps/union.c: + * testsuite/caps/deserialize.c: + * testsuite/caps/intersection.c: + * testsuite/caps/union.c: + compile warning fixes + Original commit message from CVS: + compile warning fixes + +2005-11-30 13:28:13 +0000 Thomas Vander Stichele + + * tests/old/testsuite/elements/Makefile.am: + * tests/old/testsuite/elements/gst-compprep-check.in: + * testsuite/elements/Makefile.am: + * testsuite/elements/gst-compprep-check.in: + remove compprep + Original commit message from CVS: + remove compprep + +2005-11-30 13:25:05 +0000 Andy Wingo + + configure.ac (GST_PKG_DEPS): Use gmodule-no-export-2.0.pc, available since GLib 2.2. Fixes #318031. + Original commit message from CVS: + 2005-11-30 Andy Wingo + * configure.ac (GST_PKG_DEPS): Use gmodule-no-export-2.0.pc, + available since GLib 2.2. Fixes #318031. + +2005-11-30 13:08:08 +0000 Thomas Vander Stichele + + First pass at cleaning up tests/ dir before moving the rest + Original commit message from CVS: + * configure.ac: + * tests/bench-complexity.scm: + * tests/bench-mass_elements.scm: + * tests/complexity.c: + * tests/complexity.gnuplot: + * tests/instantiate/.cvsignore: + * tests/instantiate/Makefile.am: + * tests/instantiate/caps.c: + * tests/mass_elements.c: + * tests/network-clock-utils.scm: + * tests/network-clock.scm: + * tests/plot-data: + First pass at cleaning up tests/ dir before moving the rest + Combined with CVS surgery + +2005-11-30 13:07:15 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + move includes + Original commit message from CVS: + move includes + +2005-11-30 11:55:32 +0000 Thomas Vander Stichele + + * README: + remove norwegianism + Original commit message from CVS: + remove norwegianism + +2005-11-30 10:50:57 +0000 Thomas Vander Stichele + + * Makefile.am: + make not having check non-fatal for extra targets + Original commit message from CVS: + make not having check non-fatal for extra targets + +2005-11-30 10:15:08 +0000 Thomas Vander Stichele + + po/POTFILES.in: queue has moved, update + Original commit message from CVS: + * po/POTFILES.in: + queue has moved, update + +2005-11-30 10:13:54 +0000 Thomas Vander Stichele + + * gst/gstvalue.c: + * win32/vs6/grammar.dsp: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstelements.dsp: + * win32/vs6/libgstreamer.dsp: + add some explicit casts update dsp files; also installs the debug build in \gstreamer\debug to separate it from the n... + Original commit message from CVS: + add some explicit casts + update dsp files; also installs the debug build in \gstreamer\debug to separate it from the non-debug build + +2005-11-30 10:03:46 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add more symbols to def file + Original commit message from CVS: + add more symbols to def file + +2005-11-30 09:59:04 +0000 Thomas Vander Stichele + + docs/gst/gstreamer-sections.txt: remove double entries from the docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + remove double entries from the docs + * gst/gst_private.h: + * gst/gstinfo.c: (_gst_debug_init): + remove the THREAD debug category + * gst/Makefile.am: + * gst/gstqueue.c: + * gst/gstqueue.h: + * docs/gst/gstreamer.types: + * plugins/elements/gstqueue.c: (gst_queue_get_type), + (gst_queue_init), (gst_queue_finalize), (gst_queue_change_state): + completely move queue and fix up debugging categories + +2005-11-30 09:38:42 +0000 Thomas Vander Stichele + + plugins/elements/gstidentity.c: make initialization portable, using LL is not + Original commit message from CVS: + * plugins/elements/gstidentity.c: (gst_identity_transform_ip): + make initialization portable, using LL is not + +2005-11-30 09:36:19 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add more symbols to def file + Original commit message from CVS: + add more symbols to def file + +2005-11-30 09:30:50 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add more symbols to def file + Original commit message from CVS: + add more symbols to def file + +2005-11-30 09:27:47 +0000 Thomas Vander Stichele + + win32/common/gstconfig.h: add large padding + Original commit message from CVS: + * win32/common/gstconfig.h: + add large padding + +2005-11-30 09:22:45 +0000 Thomas Vander Stichele + + win32/common/libgstreamer.def: rename symbols; sort base section + Original commit message from CVS: + * win32/common/libgstreamer.def: + rename symbols; sort base section + +2005-11-30 09:18:15 +0000 Thomas Vander Stichele + + gst/gstclock.c: remove crack non-portable handrolled DEBUG macro + Original commit message from CVS: + 2005-11-30 Thomas Vander Stichele + * gst/gstclock.c: (do_linear_regression): + remove crack non-portable handrolled DEBUG macro + +2005-11-30 09:12:57 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/random/release: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + update visual studio generated files + Original commit message from CVS: + update visual studio generated files + +2005-11-30 08:56:59 +0000 Thomas Vander Stichele + + win32/vs6/: update project files for new locations + Original commit message from CVS: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstelements.dsp: + update project files for new locations + +2005-11-30 08:52:41 +0000 Thomas Vander Stichele + + Makefile.am: remove some files + Original commit message from CVS: + * Makefile.am: + remove some files + * README: + reinstate and update + * DEVEL: + * REQUIREMENTS: + removed + * LICENSE: + * docs/random/LICENSE: + moved to random + +2005-11-30 08:36:47 +0000 Thomas Vander Stichele + + * README: + put the README back + Original commit message from CVS: + put the README back + +2005-11-30 08:33:33 +0000 Thomas Vander Stichele + + * TODO: + clean up TODO + Original commit message from CVS: + clean up TODO + +2005-11-30 08:29:14 +0000 Thomas Vander Stichele + + * libs/ext/Makefile.am: + removing ext, was not used anymore + Original commit message from CVS: + removing ext, was not used anymore + +2005-11-29 23:56:20 +0000 Edward Hervey + + gst/: Fix memory leak in GstTypeFindFactory. + Original commit message from CVS: + * gst/gsttypefind.c: (gst_type_find_register): + * gst/gsttypefind.h: + * gst/gsttypefindfactory.c: (gst_type_find_factory_init), + (gst_type_find_factory_dispose): + * gst/gsttypefindfactory.h: + Fix memory leak in GstTypeFindFactory. + +2005-11-29 20:16:40 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + updated translations + Original commit message from CVS: + updated translations + +2005-11-29 19:47:00 +0000 Thomas Vander Stichele + + move queue from core to the elements plugin ç + Original commit message from CVS: + * gst/gst.c: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstqueue.c: + move queue from core to the elements plugin + ç + +2005-11-29 19:44:56 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + update uninstalled pc files + Original commit message from CVS: + update uninstalled pc files + +2005-11-29 19:37:49 +0000 Andy Wingo + + libs/gst/base/: en-LARGE the padding. + Original commit message from CVS: + 2005-11-29 Andy Wingo + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasesink.h: en-LARGE the padding. + * gst/gstconfig.h.in (GST_PADDING_LARGE): New define, the number + of pointers by which to pad very extensible base classes (like the + ones in libs/gst/base). + +2005-11-29 19:34:24 +0000 Thomas Vander Stichele + + docs/: moving documentation from core to lib + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + moving documentation from core to lib + +2005-11-29 19:12:30 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * configure.ac: + * docs/gst/Makefile.am: + * gst/Makefile.am: + * gst/base/.gitignore: + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstadapter.c: + * gst/base/gstadapter.h: + * gst/base/gstbasesink.c: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.c: + * gst/base/gstbasetransform.h: + * gst/base/gstcollectpads.c: + * gst/base/gstcollectpads.h: + * gst/base/gstpushsrc.c: + * gst/base/gstpushsrc.h: + * gst/base/gsttypefindhelper.c: + * gst/base/gsttypefindhelper.h: + * gst/check/Makefile.am: + * gst/check/gstcheck.c: + * gst/check/gstcheck.h: + * gst/net/Makefile.am: + * gst/net/gstnet.h: + * gst/net/gstnetclientclock.c: + * gst/net/gstnetclientclock.h: + * gst/net/gstnettimepacket.c: + * gst/net/gstnettimepacket.h: + * gst/net/gstnettimeprovider.c: + * gst/net/gstnettimeprovider.h: + * libs/gst/Makefile.am: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbasetransform.c: + * libs/gst/check/Makefile.am: + * plugins/elements/Makefile.am: + * po/POTFILES.in: + * tests/check/Makefile.am: + CVS surgery + support to move base, check, and net out of gst and into libs/gst + Original commit message from CVS: + CVS surgery + support to move base, check, and net out of gst + and into libs/gst + +2005-11-29 18:57:59 +0000 Andy Wingo + + gst/gstevent.h (struct _GstEvent): Only one pointer of padding. + Original commit message from CVS: + 2005-11-29 Andy Wingo + * gst/gstevent.h (struct _GstEvent): Only one pointer of padding. + * gst/gststructure.h (struct _GstStructure): Only one pointer of + padding. + * gst/gstquery.h (struct _GstQuery): Only one pointer of padding. + * gst/gstpluginfeature.h: Remove a comment in PluginFeature. + * gst/gstplugin.h (struct _GstPluginClass): Add some padding. + * gst/gstobject.h: (struct _GstObject): Only one pointer of + padding; reduces object size by about 30%. We don't expect + anything else to go into gstobject. + * gst/gstminiobject.h (struct _GstMiniObject) + (struct _GstMiniObjectClass): Only one pointer of padding; the + payload is only a pointer and two ints anyway. For the class there + are only two methods as well. + * gst/gstelement.h (struct _GstElementClass): Removed + the state_changed signal callback, it is not used. + +2005-11-29 18:49:19 +0000 Andy Wingo + + * components/bonobo-gstmediaplay/.gitignore: + * components/bonobo-gstmediaplay/Makefile.am: + * components/bonobo-gstmediaplay/bonobo-gstmediaplay-ui.xml: + * components/bonobo-gstmediaplay/bonobo-gstmediaplay.c: + * components/bonobo-gstmediaplay/gstmediaplay.oafinfo: + * components/bonobo-media/Makefile.am: + * components/bonobo-media/bonobo-media-gstreamer-factory.c: + * components/bonobo-media/bonobo-media-gstreamer.gob: + * components/bonobo-media/bonobo-media-gstreamer.oafinfo: + * components/bonobo-media/bonobo-media-gstreamervideo.gob: + whack a mole + Original commit message from CVS: + whack a mole + +2005-11-29 18:38:46 +0000 Thomas Vander Stichele + + * po/POTFILES.in: + these files were moved + Original commit message from CVS: + these files were moved + +2005-11-29 18:21:17 +0000 Thomas Vander Stichele + + docs/gst/gstreamer.types: fix includes, though they are a little dinky + Original commit message from CVS: + * docs/gst/gstreamer.types: + fix includes, though they are a little dinky + +2005-11-29 18:14:35 +0000 Thomas Vander Stichele + + check/Makefile.am: look in the right place for elements, a lot more chance of success + Original commit message from CVS: + * check/Makefile.am: + look in the right place for elements, a lot more chance of + success + * gst/Makefile.am: + remove indexers and elements subdirs + * plugins/Makefile.am: + make indexers conditional + +2005-11-29 18:08:15 +0000 Thomas Vander Stichele + + * plugins/Makefile.am: + add missing Makefile.am + Original commit message from CVS: + add missing Makefile.am + +2005-11-29 18:04:28 +0000 Thomas Vander Stichele + + * docs/gst/Makefile.am: + fix doc build for stuff moved around + Original commit message from CVS: + fix doc build for stuff moved around + +2005-11-29 18:03:52 +0000 Thomas Vander Stichele + + * gst/elements/.gitignore: + * gst/elements/Makefile.am: + * gst/elements/gstbufferstore.c: + * gst/elements/gstbufferstore.h: + * gst/elements/gstcapsfilter.c: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesink.h: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfdsink.c: + * gst/elements/gstfdsink.h: + * gst/elements/gstfdsrc.c: + * gst/elements/gstfdsrc.h: + * gst/elements/gstfilesink.c: + * gst/elements/gstfilesink.h: + * gst/elements/gstfilesrc.c: + * gst/elements/gstfilesrc.h: + * gst/elements/gstidentity.c: + * gst/elements/gstidentity.h: + * gst/elements/gsttee.c: + * gst/elements/gsttee.h: + * gst/elements/gsttypefindelement.c: + * gst/elements/gsttypefindelement.h: + * gst/indexers/.gitignore: + * gst/indexers/Makefile.am: + * gst/indexers/gstfileindex.c: + * gst/indexers/gstindexers.c: + * gst/indexers/gstmemindex.c: + remove moved dirs + Original commit message from CVS: + remove moved dirs + +2005-11-29 18:02:45 +0000 Thomas Vander Stichele + + * gst/registries/.gitignore: + * gst/schedulers/.gitignore: + remove empty dirs + Original commit message from CVS: + remove empty dirs + +2005-11-29 18:00:15 +0000 Thomas Vander Stichele + + do CVS surgery and related build fixery to move elements and indexers in a new gstreamer/plugins directory, out of th... + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * plugins/elements/Makefile.am: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/indexers/Makefile.am: + do CVS surgery and related build fixery to move elements + and indexers in a new gstreamer/plugins directory, out of the + gst/ directory + +2005-11-29 17:47:06 +0000 Andy Wingo + + Rename gstnet-tempname to gstnet. Fixes #322257. + Original commit message from CVS: + 2005-11-29 Andy Wingo + * check/Makefile.am: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/gstreamer-net.pc.in: + * gst/net/Makefile.am: Rename gstnet-tempname to gstnet. Fixes + #322257. + +2005-11-29 17:35:03 +0000 Thomas Vander Stichele + + * check/elements/.gitignore: + * tests/check/elements/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-11-29 17:33:55 +0000 Thomas Vander Stichele + + * gstreamer.spec.in: + remove some more complete + Original commit message from CVS: + remove some more complete + +2005-11-29 17:32:36 +0000 Thomas Vander Stichele + + tools/: removing -compprep and -complete + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-complete.1.in: + * tools/gst-complete.c: + * tools/gst-compprep.1.in: + * tools/gst-compprep.c: + removing -compprep and -complete + +2005-11-29 17:23:56 +0000 Thomas Vander Stichele + + gst/gstevent.*: fix #320529 - clean up new_segment API and structure. + Original commit message from CVS: + * gst/gstevent.c: (gst_event_new_new_segment), + (gst_event_parse_new_segment): + * gst/gstevent.h: + fix #320529 - clean up new_segment API and structure. + Let's hope everyone was using the methods, and not the structure. + +2005-11-29 17:13:44 +0000 Edward Hervey + + gst/base/gstbasesink.c: Properly handle non GST_FORMAT_TIME segment + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_do_sync), + (gst_base_sink_activate_pull), (gst_base_sink_change_state): + Properly handle non GST_FORMAT_TIME segment + * gst/elements/gstidentity.c: (gst_identity_transform_ip): + Properly handle non GST_FORMAT_TIME segment + * gst/gstsegment.c: + This function is valid if the accumulator is 0 and the format + is different from the requested format. + +2005-11-29 15:50:50 +0000 Jan Schmidt + + docs/gst/gstreamer-sections.txt: Add gst_query_new_seeking and gst_query_parse_seeking to the docs. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Add gst_query_new_seeking and gst_query_parse_seeking to the + docs. + +2005-11-29 15:15:38 +0000 Jan Schmidt + + * ChangeLog: + Fix conflict marker + Original commit message from CVS: + Fix conflict marker + +2005-11-29 15:12:22 +0000 Jan Schmidt + + gst/base/gstbasetransform.c: Treat a pad alloc with new caps the same as if we were not negotiated, in order to allow... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_buffer_alloc): + Treat a pad alloc with new caps the same as if we were not + negotiated, in order to allow a changing upstream output + to produce a new format of data. + +2005-11-29 14:47:07 +0000 Edward Hervey + + gst/base/gstbasetransform.c: The event virtual method is now properly implemented, with a default handler + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_class_init), + (gst_base_transform_event), (gst_base_transform_eventfunc): + The event virtual method is now properly implemented, with a default + handler + Sub classes should call the parent_class event method. They should + return FALSE if they had a problem handling the given event, or don't + want GstBaseTransform to send that even downstream + * gst/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_init), (gst_identity_event), + (gst_identity_transform_ip), (gst_identity_set_property), + (gst_identity_get_property): + * gst/elements/gstidentity.h: + Added the single-segment boolean property. + If set to TRUE, it will output a single segment of data, starting from + 0, will eat up all incoming newsegment, and modify the timestamp of the + buffers accordingly + +2005-11-29 14:43:53 +0000 Thomas Vander Stichele + + * docs/random/thomasvs/0.10: + further review + Original commit message from CVS: + further review + +2005-11-29 13:10:38 +0000 Tim-Philipp Müller + + gst/gstghostpad.c: Don't ref NULL target pad (#322751). Improve docs. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_get_target): + Don't ref NULL target pad (#322751). Improve docs. + +2005-11-29 11:07:54 +0000 Michael Smith + + gst/gstregistryxml.c: Don't crash if we failed to load a feature from a plugin. + Original commit message from CVS: + * gst/gstregistryxml.c: (load_plugin): + Don't crash if we failed to load a feature from a plugin. + +2005-11-29 00:51:54 +0000 Thomas Vander Stichele + + * docs/random/thomasvs/0.10: + add my todos for 0.10 + Original commit message from CVS: + add my todos for 0.10 + +2005-11-28 21:51:37 +0000 Thomas Vander Stichele + + check/pipelines/simple_launch_lines.c: use more check API and less GLib API + Original commit message from CVS: + * check/pipelines/simple_launch_lines.c: (setup_pipeline), + (GST_START_TEST): + use more check API and less GLib API + +2005-11-28 21:48:19 +0000 Thomas Vander Stichele + + * check/pipelines/simple_launch_lines.c: + * tests/check/pipelines/simple-launch-lines.c: + cosmetic changes + Original commit message from CVS: + cosmetic changes + +2005-11-28 19:58:56 +0000 Thomas Vander Stichele + + Makefile.am: don't run checks if we don't have check + Original commit message from CVS: + * Makefile.am: + don't run checks if we don't have check + * common/check.mak: + remove the registry when running make torture + * docs/gst/gstreamer-sections.txt: + remove second multiply + * gst/gstqueue.c: (gst_queue_loop): + fix a compile warning when disabling debug + +2005-11-28 19:43:27 +0000 Jan Schmidt + + gst/gstinfo.h: Hey! Let's print the pad name if the pointer != NULL instead of when it == NULL :-) + Original commit message from CVS: + * gst/gstinfo.h: + Hey! Let's print the pad name if the pointer != NULL instead + of when it == NULL :-) + +2005-11-28 18:44:11 +0000 Wim Taymans + + check/gst/gstutils.c: Updated check, add some scaling accuracy checking code. + Original commit message from CVS: + * check/gst/gstutils.c: (GST_START_TEST): + Updated check, add some scaling accuracy checking code. + * gst/gstutils.c: (gst_util_div128_64), + (gst_util_uint64_scale_int64), (gst_util_uint64_scale), + (gst_util_uint64_scale_int): + Fix 6 times faster division code. Optimize for common + 1/1 and less common X/1 cases. + +2005-11-28 17:59:25 +0000 Thomas Vander Stichele + + * gst/gstclock.c: + doc updates + Original commit message from CVS: + doc updates + +2005-11-28 16:05:35 +0000 Wim Taymans + + check/gst/gstutils.c: More checks. + Original commit message from CVS: + * check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + More checks. + * gst/gstclock.c: (gst_clock_finalize), (gst_clock_set_master), + (do_linear_regression), (gst_clock_add_observation): + Cleanups. + Release lock when the clock cannot be slaved. + Catch the case where the regression returned an invalid denominator. + * gst/gstutils.c: (gst_util_div128_64_iterate), + (gst_util_div128_64), (gst_util_uint64_scale_int64), + (gst_util_uint64_scale), (gst_util_uint64_scale_int): + Add protentially more performant non-iterative 128/64 divide function + that unfortunatly does not work yet. + Shortcut the trivial 0/X = 0 case. + Remove the warnings on overflow. + +2005-11-28 14:18:22 +0000 Thomas Vander Stichele + + gst/gstplugin.c: everything causing a plugin not to load should be at least a WARNING + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_register_func): + everything causing a plugin not to load should be at least a WARNING + +2005-11-28 14:02:54 +0000 Thomas Vander Stichele + + * gst/elements/gstcapsfilter.c: + * plugins/elements/gstcapsfilter.c: + log caps + Original commit message from CVS: + log caps + +2005-11-28 14:01:52 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + fix docs + Original commit message from CVS: + fix docs + +2005-11-28 13:25:14 +0000 Stefan Kost + + docs/random/ensonic/dparams.txt: some TODOs for the next dev cycle + Original commit message from CVS: + * docs/random/ensonic/dparams.txt: + some TODOs for the next dev cycle + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_new): + * libs/gst/controller/gstcontroller.h: + use base type to assign acccessor functions + +2005-11-28 11:31:31 +0000 Jan Schmidt + + check/Makefile.am: Oops, that should have been top_srcdir + Original commit message from CVS: + * check/Makefile.am: + Oops, that should have been top_srcdir + +2005-11-28 10:29:37 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * check/gst/gstpipeline.c: + * tests/check/Makefile.am: + * tests/check/gst/gstpipeline.c: + disable pipeline test until someone fixes the unreliable errors + Original commit message from CVS: + disable pipeline test until someone fixes the unreliable errors + +2005-11-28 10:07:38 +0000 Jan Schmidt + + check/: Use a cmdline define to specify the location of a file to use for testing, to avoid breaking distcheck. + Original commit message from CVS: + * check/Makefile.am: + * check/elements/fdsrc.c: (GST_START_TEST): + Use a cmdline define to specify the location of a file to use for + testing, to avoid breaking distcheck. + +2005-11-28 10:04:45 +0000 Andy Wingo + + gst/gstpad.c (fixate_value): Use array functions for arrays. + Original commit message from CVS: + 2005-11-28 Andy Wingo + * gst/gstpad.c (fixate_value): Use array functions for arrays. + +2005-11-28 09:55:19 +0000 Edward Hervey + + tools/gst-launch.c: Clarify the output strings, makes it easier to translate. + Original commit message from CVS: + * tools/gst-launch.c: (main): + Clarify the output strings, makes it easier to translate. + Fixes #322626 + +2005-11-28 08:20:48 +0000 Thomas Vander Stichele + + gst/Makefile.am: don't try and build net if we don't even have + Original commit message from CVS: + * gst/Makefile.am: + don't try and build net if we don't even have + +2005-11-27 22:50:09 +0000 Jan Schmidt + + check/: Add tests for fdsrc seekability + Original commit message from CVS: + * check/Makefile.am: + * check/elements/fdsrc.c: (event_func), (setup_fdsrc), + (cleanup_fdsrc), (GST_START_TEST), (fdsrc_suite), (main): + Add tests for fdsrc seekability + * gst/elements/gstfdsrc.c: (gst_fdsrc_class_init), + (gst_fdsrc_init), (gst_fdsrc_update_fd), (gst_fdsrc_start), + (gst_fdsrc_set_property), (gst_fdsrc_is_seekable), + (gst_fdsrc_get_size), (gst_fdsrc_uri_set_uri): + * gst/elements/gstfdsrc.h: + fdsrc should not be a 'live' source. + Implement seeking on seekable fd's. + * gst/gstquery.c: (gst_query_new_seeking), + (gst_query_parse_seeking): + * gst/gstquery.h: + Implement SEEKING query functions: + *_new_seeking and *_parse_seeking + +2005-11-27 22:43:08 +0000 Stefan Kost + + gst/gstelement.c: don't loop forever + Original commit message from CVS: + * gst/gstelement.c: (gst_element_dispose): + don't loop forever + * gst/gstiterator.c: + * gst/gststructure.c: + doc fixes + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstinterpolation.c: + (interpolate_none_get_enum_value_array): + support controlling enums + +2005-11-27 19:52:49 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Improve documentation for gst_value_union(). + Original commit message from CVS: + * gst/gstvalue.c: + Improve documentation for gst_value_union(). + * gst/gstvalue.h: + Change return value for union, intersect and subtract functions + from gint to gboolean. + +2005-11-27 18:11:02 +0000 Tim-Philipp Müller + + gst/gstvalue.*: Use gint, gdouble and gchar in our API instead of int, double and char (and make usage in gstvalue.c ... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_serialize_any_list), + (gst_value_transform_any_list_string), + (gst_value_deserialize_list), (gst_value_deserialize_array), + (gst_value_set_int_range), (gst_value_deserialize_int_range), + (gst_value_set_double_range), (gst_value_deserialize_double_range), + (gst_value_set_fraction_range_full), + (gst_value_deserialize_fraction_range), + (gst_value_deserialize_caps), (gst_value_deserialize_buffer), + (gst_value_deserialize_boolean), + (gst_value_deserialize_int_helper), (gst_value_deserialize_double), + (gst_value_serialize_float), (gst_value_deserialize_float), + (gst_string_wrap), (gst_value_deserialize_string), + (gst_value_deserialize_enum), (gst_value_deserialize_flags), + (gst_value_union_int_range_int_range), + (gst_value_intersect_int_range_int_range), + (gst_value_intersect_double_range_double_range), + (gst_value_create_new_range), (gst_value_subtract_int_range_int), + (gst_value_subtract_int_range_int_range), + (gst_value_subtract_double_double_range), + (gst_value_subtract_double_range_double_range), + (gst_value_deserialize_fraction): + * gst/gstvalue.h: + Use gint, gdouble and gchar in our API instead of int, double and + char (and make usage in gstvalue.c more consistent). + +2005-11-27 17:05:38 +0000 Thomas Vander Stichele + + * gst/Makefile.am: + add undefined for core + Original commit message from CVS: + add undefined for core + +2005-11-27 16:46:48 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * tests/check/Makefile.am: + fix up Makefile.am and remove GST_ENABLE_NEW + Original commit message from CVS: + fix up Makefile.am and remove GST_ENABLE_NEW + +2005-11-27 15:15:35 +0000 Thomas Vander Stichele + + update LDFLAGS use some more + Original commit message from CVS: + * configure.ac: + * gst/Makefile.am: + * gst/base/Makefile.am: + * gst/check/Makefile.am: + * gst/elements/Makefile.am: + * gst/net/Makefile.am: + update LDFLAGS use some more + +2005-11-27 14:19:38 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + Fixes #312589 + Original commit message from CVS: + Fixes #312589 + +2005-11-27 14:03:22 +0000 Thomas Vander Stichele + + * check/gst/gstpipeline.c: + * tests/check/gst/gstpipeline.c: + add some additional fail_if's + Original commit message from CVS: + add some additional fail_if's + +2005-11-26 11:28:32 +0000 Edward Hervey + + gst/gstpluginfeature.c: This shouldn't issue a g_warning since it returns NULL if it couldn't find the plugin, and al... + Original commit message from CVS: + * gst/gstpluginfeature.c: (gst_plugin_feature_load): + This shouldn't issue a g_warning since it returns NULL if it + couldn't find the plugin, and all functions using this behave + properly on a NULL return. Switching to a GST_WARNING. + +2005-11-25 17:06:36 +0000 Jan Schmidt + + gst/gstbin.c: Don't leak clock messages. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_handle_message_func): + Don't leak clock messages. + +2005-11-25 11:38:38 +0000 Wim Taymans + + gst/gstutils.c: Optimisations, remove unneeded vars. + Original commit message from CVS: + * gst/gstutils.c: (gst_util_uint64_scale_int64), + (gst_util_uint64_scale_int): + Optimisations, remove unneeded vars. + +2005-11-25 00:02:05 +0000 Wim Taymans + + check/gst/gstutils.c: Added more checks for the high precision uint64 cases. + Original commit message from CVS: + * check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + Added more checks for the high precision uint64 cases. + * gst/gstutils.c: (gst_util_uint64_scale_int64), + (gst_util_uint64_scale), (gst_util_uint64_scale_int): + Implement high precission (guint64 * guint64) / guint64. + +2005-11-24 19:06:58 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Fix wrong percentage query. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_query): + Fix wrong percentage query. + * gst/gstutils.c: (gst_util_uint64_scale), + (gst_util_uint64_scale_int): + Add some more common cases that can be handled + efficiently to _scale. + +2005-11-24 18:44:43 +0000 Thomas Vander Stichele + + * check/gst/gstminiobject.c: + * tests/check/gst/gstminiobject.c: + remove wrongly commited comments + Original commit message from CVS: + remove wrongly commited comments + +2005-11-24 18:40:58 +0000 Thomas Vander Stichele + + check/gst/gstminiobject.c: don't use check calls from threads; check probably isn't threadsafe and using a lock to ma... + Original commit message from CVS: + * check/gst/gstminiobject.c: (thread_ref), (GST_START_TEST), + (gst_mini_object_suite): + don't use check calls from threads; check probably isn't + threadsafe and using a lock to make it threadsafe would + defeat the purpose of this check + * gst/check/gstcheck.c: + * gst/check/gstcheck.h: + use GST_DEBUG some more + +2005-11-24 18:03:15 +0000 Wim Taymans + + gst/gstutils.c: Chain trivial case to _scale_int. + Original commit message from CVS: + * gst/gstutils.c: (gst_util_uint64_scale), + (gst_util_uint64_scale_int): + Chain trivial case to _scale_int. + +2005-11-24 17:44:57 +0000 Wim Taymans + + check/gst/gstutils.c: Added test for scaling. + Original commit message from CVS: + * check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite): + Added test for scaling. + * gst/gstclock.h: + Small doc fix. + * gst/gstutils.c: (gst_util_uint64_scale_int): + Implemented high precision scaling code. + +2005-11-24 16:56:28 +0000 Stefan Kost + + gst/gstinfo.h: do not crash on pad==NULL + Original commit message from CVS: + * gst/gstinfo.h: + do not crash on pad==NULL + +2005-11-24 16:32:26 +0000 Stefan Kost + + Fix distcheck issues for the libraries docs build + Original commit message from CVS: + Patch by: Stefan Kost + * common/gtk-doc.mak: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + Fix distcheck issues for the libraries docs build + Closes #319599 + +2005-11-24 14:39:59 +0000 Michael Smith + + docs/manual/basics-helloworld.xml: Fix bug #315027: memory leak in example code in docs. + Original commit message from CVS: + * docs/manual/basics-helloworld.xml: + Fix bug #315027: memory leak in example code in docs. + +2005-11-24 12:44:25 +0000 Michael Smith + + gst/base/gstbasesink.c: Unlock the PREROLL_LOCK in a failure case. + Original commit message from CVS: + 2005-11-24 Michael Smith + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + Unlock the PREROLL_LOCK in a failure case. + +2005-11-24 11:16:32 +0000 Thomas Vander Stichele + + * check/gst/.gitignore: + * check/net/.gitignore: + * tests/check/gst/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-11-24 09:44:07 +0000 Wim Taymans + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * gst/base/gstadapter.h: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.h: + * gst/base/gstpushsrc.h: + * gst/elements/gstfakesink.h: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesink.h: + * gst/elements/gstfilesrc.h: + * gst/gst.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbus.h: + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstevent.c: + * gst/gstghostpad.h: + * gst/gstindex.h: + * gst/gstinterface.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstpipeline.h: + * gst/gstpluginfeature.h: + * gst/gstquery.h: + * gst/gstqueue.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * gst/gsttrace.c: + * gst/gsttrace.h: + * gst/gsttypefind.h: + * gst/gsturi.h: + * gst/gstvalue.c: + * gst/net/gstnetclientclock.c: + * gst/net/gstnetclientclock.h: + * gst/net/gstnettimepacket.c: + * gst/net/gstnettimeprovider.c: + * gst/net/gstnettimeprovider.h: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/net/gstnetclientclock.c: + * libs/gst/net/gstnetclientclock.h: + * libs/gst/net/gstnettimepacket.c: + * libs/gst/net/gstnettimeprovider.c: + * libs/gst/net/gstnettimeprovider.h: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfilesink.h: + * plugins/elements/gstfilesrc.h: + * plugins/elements/gstqueue.h: + Doc fixes. + Original commit message from CVS: + Doc fixes. + +2005-11-23 22:54:54 +0000 Thomas Vander Stichele + + * configure.ac: + removed directories + Original commit message from CVS: + removed directories + +2005-11-23 22:21:25 +0000 Thomas Vander Stichele + + * tests/instantiate/Makefile.am: + fix dist + Original commit message from CVS: + fix dist + +2005-11-23 21:24:46 +0000 Thomas Vander Stichele + + * Makefile.am: + * win32/common/config.h: + add a torture target + Original commit message from CVS: + add a torture target + +2005-11-23 21:18:44 +0000 Thomas Vander Stichele + + * tests/instantiate/create.c: + * tests/negotiation/.gitignore: + * tests/negotiation/Makefile.am: + * tests/negotiation/capsnego1.c: + remove obsolete tests + Original commit message from CVS: + remove obsolete tests + +2005-11-23 21:16:58 +0000 Thomas Vander Stichele + + * tests/Makefile.am: + * tests/lat.c: + * tests/muxing/.gitignore: + * tests/muxing/Makefile.am: + * tests/muxing/case1.c: + * tests/probes/.gitignore: + * tests/probes/Makefile.am: + * tests/probes/probetest.c: + remove obsolete tests + Original commit message from CVS: + remove obsolete tests + +2005-11-23 21:13:59 +0000 Thomas Vander Stichele + + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/trigger/Makefile.am: + * tests/old/testsuite/trigger/README: + * tests/old/testsuite/trigger/trigger.c: + * testsuite/Makefile.am: + * testsuite/trigger/Makefile.am: + * testsuite/trigger/README: + * testsuite/trigger/trigger.c: + remove trigger subdir + Original commit message from CVS: + remove trigger subdir + +2005-11-23 21:12:22 +0000 Thomas Vander Stichele + + * tests/old/testsuite/elements/Makefile.am: + * tests/old/testsuite/elements/fake.c: + * tests/old/testsuite/elements/name.c: + * tests/old/testsuite/elements/property.c: + * tests/old/testsuite/elements/property.h: + * tests/old/testsuite/elements/tee.c: + * testsuite/elements/Makefile.am: + * testsuite/elements/fake.c: + * testsuite/elements/name.c: + * testsuite/elements/property.c: + * testsuite/elements/property.h: + * testsuite/elements/tee.c: + remove tests replaced by checks + Original commit message from CVS: + remove tests replaced by checks + +2005-11-23 20:04:25 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.9.6 === + +2005-11-23 19:55:09 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/random/moving-plugins: + * win32/common/config.h: + releasing 0.9.6 + Original commit message from CVS: + releasing 0.9.6 + +2005-11-23 18:07:18 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2005-11-23 17:59:00 +0000 Thomas Vander Stichele + + * docs/upload.mak: + Christian, learn to configure your .ssh/config file, and STOP committing to thisfile + Original commit message from CVS: + Christian, learn to configure your .ssh/config file, and STOP committing to thisfile + +2005-11-23 16:10:38 +0000 Wim Taymans + + Doc updates. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/glib-compat.c: + * gst/gsttagsetter.c: + * gst/gstvalue.c: + * gst/net/gstnetclientclock.c: + * gst/net/gstnettimepacket.h: + Doc updates. + +2005-11-23 15:49:06 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/faq/using.xml: + * docs/libs/tmpl/gstcontrol.sgml: + * docs/manual/advanced-dparams.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/basics-elements.xml: + * docs/pwg/other-source.xml: + * docs/random/moving-plugins: + * gst/gstpad.c: + * tools/gst-launch.1.in: + remove mentions of sinesrc + Original commit message from CVS: + remove mentions of sinesrc + +2005-11-23 14:52:31 +0000 Michael Smith + + docs/gst/gstreamer-sections.txt: Update for new API and API changes. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Update for new API and API changes. + * gst/gstobject.h: + Documentation fix: GST_TRYLOCK -> GST_OBJECT_TRYLOCK + * gst/gstvalue.c: + Documentation typo fix. + * gst/net/gstnettimepacket.c: + Documentation fixes for arguments. + +2005-11-23 13:22:21 +0000 Jan Schmidt + + API Changes. + Original commit message from CVS: + * gst/gststructure.c: (gst_structure_get_fraction), + (gst_structure_parse_value), + (gst_structure_fixate_field_nearest_fraction): + * gst/gststructure.h: + * gst/gstutils.c: (gst_util_uint64_scale_int): + * gst/gstutils.h: + * scripts/update-funcnames: + API Changes. + Rename gst_util_clock_time_scale to gst_util_uint64_scale_int + Make gst_structure_fixate_field_nearest_fraction take a numerator + and denominator argument instead of a GValue + add gst_structure_get_fraction helper function. + +2005-11-23 13:14:46 +0000 Wim Taymans + + docs/design/part-TODO.txt: Update TODO. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Update TODO. + * gst/net/gstnetclientclock.c: (gst_net_client_clock_thread): + * gst/net/gstnetclientclock.h: + Use parent fields for timeout and window_size. + +2005-11-23 12:39:36 +0000 Christian Schaller + + * docs/upload.mak: + * gst/registries/.gitignore: + * gst/schedulers/.gitignore: + * libs/gst/control/.gitignore: + * libs/gst/getbits/.gitignore: + add missing cvsignores so CVS shuts up + Original commit message from CVS: + add missing cvsignores so CVS shuts up + +2005-11-23 12:36:00 +0000 Andy Wingo + + check/net/gstnetclientclock.c (test_functioning): Adjust to rate_num/rate_denom change. + Original commit message from CVS: + 2005-11-23 Andy Wingo + * check/net/gstnetclientclock.c (test_functioning): Adjust to + rate_num/rate_denom change. + * gst/net/gstnetclientclock.c + (gst_net_client_clock_observe_times): Take the SLAVE_LOCK not the + OBJECT_LOCK. Don't call add_observation with the lock. + * gst/gstclock.c (gst_clock_init): Initialize the rate as a + fraction. + (gst_clock_adjust_unlocked): Adjust using uint64_scale and the + rate fraction. + (gst_clock_set_calibration, gst_clock_get_calibration): Change to + deal with rate as a fraction whose numerator and denominator are + GstClockTime values. + (gst_clock_set_master): Only use the OBJECT_LOCK to set the + master; the other fields are protected by the SLAVE_LOCK. + (do_linear_regression): Note that this must be called with the + SLAVE_LOCK. + (gst_clock_add_observation): Take the SLAVE_LOCK, not the + OBJECT_LOCK. Call set_calibration instead of touching the + variables directly. + (gst_clock_set_property, gst_clock_get_property): Protect + master/slave parameters with the SLAVE_LOCK. + * gst/gstclock.h (GstClock): Remove rate, add rate_numerator and + rate_denominator. PR3C1S3. Add a new lock, the SLAVE_LOCK, and + note that all of the instance variables that add_observation and + the set_master functions use are protected by that lock and not + the OBJECT_LOCK. + (GST_CLOCK_SLAVE_LOCK, GST_CLOCK_SLAVE_UNLOCK): New macros. + * gst/gstclock.c (gst_clock_add_observation): No longer requires + the caller to take the object lock. + +2005-11-23 11:22:39 +0000 Wim Taymans + + gst/gsterror.*: Add error for clock stuff. + Original commit message from CVS: + * gst/gsterror.c: (_gst_core_errors_init): + * gst/gsterror.h: + Add error for clock stuff. + * gst/gstpipeline.c: (gst_pipeline_change_state), + (gst_pipeline_set_clock): + Post clock error when clock cannot be used in a pipeline. + +2005-11-23 11:05:37 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: make two symbols from gstinfo private for the docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + make two symbols from gstinfo private for the docs + * gst/base/gstcollectpads.h: + * gst/gstutils.c: + fix doc typos, update docs + +2005-11-22 18:28:44 +0000 Wim Taymans + + gst/base/gstbasesink.*: No need to store the clock, the parent element class already has it. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_wait), (gst_base_sink_do_sync), + (gst_base_sink_handle_event): + * gst/base/gstbasesink.h: + No need to store the clock, the parent element class already + has it. + * gst/gstbin.c: (gst_bin_set_clock_func), (gst_bin_add_func): + Updates for clock_set returning a gboolean + * gst/gstclock.c: (gst_clock_entry_new), (gst_clock_id_wait), + (gst_clock_id_wait_async), (gst_clock_class_init), + (gst_clock_init), (gst_clock_finalize), + (gst_clock_get_internal_time), (gst_clock_get_time), + (gst_clock_slave_callback), (gst_clock_set_master), + (gst_clock_get_master), (do_linear_regression), + (gst_clock_add_observation), (gst_clock_set_property), + (gst_clock_get_property): + * gst/gstclock.h: + Implement master/slave. When setting a clock as a slave, a + periodic timeout is scheduled to sample master and slave times. + Then the slave clock is recalibrated to match offset and rate + of the master clock. + Update logging a bit. + Add flag so that a clock can state that is cannot be slaved to + another clock. + * gst/gstelement.c: (gst_element_set_clock): + * gst/gstelement.h: + The set_clock returns a gboolean for when an element cannot + deal with the selected clock in the pipeline. + * gst/gstpipeline.c: (gst_pipeline_change_state), + (gst_pipeline_set_clock): + * gst/gstpipeline.h: + Handle the case where the selected clock cannot be set on + the pipeline. + * gst/net/gstnetclientclock.c: (gst_net_client_clock_class_init), + (gst_net_client_clock_init), (gst_net_client_clock_finalize), + (gst_net_client_clock_set_property), + (gst_net_client_clock_get_property), + (gst_net_client_clock_observe_times): + * gst/net/gstnetclientclock.h: + Use regression code in GstClock parent, remove duplicated + functionality. + +2005-11-22 16:31:08 +0000 Michael Smith + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: + * gst/gstutils.h: + Add underscores + Original commit message from CVS: + Add underscores + +2005-11-22 15:52:03 +0000 Thomas Vander Stichele + + gst/: correctly fix GEnumValues so that nick is the short lowercase dashed tag + Original commit message from CVS: + * gst/elements/Makefile.am: + * gst/elements/gstfakesink.c: (gst_fake_sink_state_error_get_type): + * gst/elements/gstfakesrc.c: (gst_fake_src_data_get_type), + (gst_fake_src_sizetype_get_type), (gst_fake_src_filltype_get_type), + (gst_fake_src_init), (gst_fake_src_prepare_buffer), + (gst_fake_src_alloc_buffer), (gst_fake_src_get_size): + * gst/elements/gstfakesrc.h: + * gst/gstqueue.c: (queue_leaky_get_type): + correctly fix GEnumValues so that nick is the short lowercase + dashed tag + * tools/gst-inspect.c: (print_element_properties_info): + also show the nick, since it's useful to use from parse_launch + syntax + Fixes #322139 + +2005-11-22 15:15:53 +0000 Michael Smith + + Add util method for scaling a clocktime by a fraction. Useful implementation is left as an exercise for the reader. + Original commit message from CVS: + * gst/gstutils.c: (gst_util_clocktime_scale): + * gst/gstutils.h: + * docs/gst/gstreamer-sections.txt: + Add util method for scaling a clocktime by a fraction. Useful + implementation is left as an exercise for the reader. + +2005-11-22 14:29:10 +0000 Jan Schmidt + + gst/gstvalue.c: If needed, allocate storage in the destination value during collection. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_collect_fraction_range): + If needed, allocate storage in the destination value during + collection. + +2005-11-22 13:58:00 +0000 Edward Hervey + + Removed GstURI , closes bug #321061 + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gst.h: + * gst/gsturitype.c: + * gst/gsturitype.h: + * gst/gstutils.c: (gst_util_set_object_arg): + * tools/gst-compprep.c: (main): + * tools/gst-inspect.c: (print_element_properties_info): + Removed GstURI , closes bug #321061 + +2005-11-22 13:14:51 +0000 Jan Schmidt + + Oops, broke automatic string type parsing. + Original commit message from CVS: + * check/gst/gststructure.c: (GST_START_TEST): + * gst/gststructure.c: (gst_structure_parse_value): + Oops, broke automatic string type parsing. + Add a test to catch it in future. + +2005-11-22 13:02:12 +0000 Andy Wingo + + * ChangeLog: + * gst/gsttagsetter.c: + gst/gsttagsetter.c (gst_tag_setter_get_tag_merge_mode) + Original commit message from CVS: + 2005-11-22 Andy Wingo + * gst/gsttagsetter.c (gst_tag_setter_get_tag_merge_mode) + (gst_tag_setter_set_tag_merge_mode, gst_tag_setter_get_tag_list): + Actually rename the function implementations. Grr. + +2005-11-22 12:51:18 +0000 Andy Wingo + + * scripts/update-funcnames: + fix borked commit + Original commit message from CVS: + fix borked commit + +2005-11-22 12:35:42 +0000 Jan Schmidt + + check/gst/capslist.h: Comment test cases + Original commit message from CVS: + * check/gst/capslist.h: + Comment test cases + * check/gst/gststructure.c: (GST_START_TEST), + (gst_structure_suite): + Test automatic value type detection in gst_structure_from_string. + * gst/gststructure.c: (gst_structure_parse_value): + Add fraction as a type we try and guess automatically in + caps/structure strings. + +2005-11-22 12:35:35 +0000 Andy Wingo + + * scripts/update-funcnames: + update update-funcs for tagsetter + Original commit message from CVS: + update update-funcs for tagsetter + +2005-11-22 12:20:04 +0000 Torsten Schoenfeld + + gst/gsttagsetter.*: (gst_tag_setter_merge_tags) (gst_tag_setter_add_tags, gst_tag_setter_add_tag_values) (gst_tag_set... + Original commit message from CVS: + 2005-11-22 Andy Wingo + patch by: Torsten Schoenfeld + * gst/gsttagsetter.h: + * gst/gsttagsetter.c: (gst_tag_setter_merge_tags) + (gst_tag_setter_add_tags, gst_tag_setter_add_tag_values) + (gst_tag_setter_add_tag_valist) + (gst_tag_setter_add_tag_valist_values): Renamed from _merge, _add, + _add_values, _add_valist, and _add_valist_values. Since this is an + interface the function suffixes should be more explicit so + language binding don't end up with element.add_valist -> + gst_tag_setter_add_valist, for example. Fixes #322069. + +2005-11-22 12:15:19 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + don't valgrind the stress test, takes too long + Original commit message from CVS: + don't valgrind the stress test, takes too long + +2005-11-22 11:56:01 +0000 Jan Schmidt + + check/gst/gstcaps.c: Extend caps string tests to check that a caps to string conversion is reversible and produces th... + Original commit message from CVS: + * check/gst/gstcaps.c: (GST_START_TEST): + Extend caps string tests to check that a caps to string + conversion is reversible and produces the same caps. + * gst/gststructure.c: (gst_structure_value_get_generic_type): + Output "fraction" as the generic type fraction range, so caps + serialisation and deserialisation works. + * check/gst/capslist.h: + * gst/gstvalue.c: (gst_value_deserialize_fraction): + Support 'MIN' and 'MAX' for deserialising fractions. + +2005-11-22 11:50:12 +0000 Michael Smith + + * gst/gststructure.c: + Minor doc fix. + Original commit message from CVS: + Minor doc fix. + +2005-11-22 11:48:58 +0000 Andy Wingo + + gst/gstevent.h (gst_event_new_new_segment) (gst_event_parse_new_segment, gst_event_new_buffer_size) + Original commit message from CVS: + 2005-11-22 Andy Wingo + * gst/gstevent.h (gst_event_new_new_segment) + (gst_event_parse_new_segment, gst_event_new_buffer_size) + (gst_event_parse_buffer_size, gst_ghost_pad_new_no_target): + Renamed from *_newsegment, *_buffersize, *_notarget. + * scripts/update-funcnames: New script, performs the changes + listed above. + +2005-11-22 11:25:01 +0000 Wim Taymans + + gst/base/gstbasesink.c: Make sure the GstFlowReturn is returned. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + Make sure the GstFlowReturn is returned. + * gst/gstbus.c: (gst_bus_add_signal_watch_full), + (gst_bus_add_signal_watch): + * gst/gstbus.h: + add gst_bus_add_signal_watch_full. + * gst/gstplugin.c: (gst_plugin_load_file): + Small style cleanup. + +2005-11-22 10:24:31 +0000 Jan Schmidt + + check/gst/gstevent.c: Block the fakesrc srcpad when we send an event, to avoid contention on the stream_lock causing ... + Original commit message from CVS: + * check/gst/gstevent.c: (test_event), (GST_START_TEST): + Block the fakesrc srcpad when we send an event, to avoid + contention on the stream_lock causing random test failures. + +2005-11-22 09:42:17 +0000 Jan Schmidt + + Fix subtraction. + Original commit message from CVS: + * check/gst/gstvalue.c: (GST_START_TEST): + * gst/gstvalue.c: (gst_value_fraction_subtract): + Fix subtraction. + +2005-11-22 09:35:25 +0000 Stefan Kost + + gst/gst.h: include "gstchildproxy.h" + Original commit message from CVS: + * gst/gst.h: + include "gstchildproxy.h" + * gst/gstchildproxy.h: + * libs/gst/controller/gstcontroller.h: + use G_GNUC_NULL_TERMINATED + +2005-11-21 23:54:59 +0000 Jan Schmidt + + Implement fraction ranges and extend GstFraction to support arithmetic subtraction, as well as deserialization from i... + Original commit message from CVS: + * check/gst/capslist.h: + * check/gst/gstcaps.c: (GST_START_TEST): + * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + * gst/gststructure.c: (gst_structure_parse_range), + (gst_structure_fixate_field_nearest_fraction): + * gst/gststructure.h: + * gst/gstvalue.c: (gst_value_init_fraction_range), + (gst_value_free_fraction_range), (gst_value_copy_fraction_range), + (gst_value_collect_fraction_range), + (gst_value_lcopy_fraction_range), (gst_value_set_fraction_range), + (gst_value_set_fraction_range_full), + (gst_value_get_fraction_range_min), + (gst_value_get_fraction_range_max), + (gst_value_serialize_fraction_range), + (gst_value_transform_fraction_range_string), + (gst_value_compare_fraction_range), + (gst_value_deserialize_fraction_range), + (gst_value_intersect_fraction_fraction_range), + (gst_value_intersect_fraction_range_fraction_range), + (gst_value_subtract_fraction_fraction_range), + (gst_value_subtract_fraction_range_fraction), + (gst_value_subtract_fraction_range_fraction_range), + (gst_value_collect_fraction), (gst_value_fraction_multiply), + (gst_value_fraction_subtract), (gst_value_deserialize_fraction), + (gst_value_transform_string_fraction), (_gst_value_initialize): + * gst/gstvalue.h: + Implement fraction ranges and extend GstFraction to support + arithmetic subtraction, as well as deserialization from integer + strings such as "100" + Add a testsuite as for int and double range set operations + +2005-11-21 19:58:23 +0000 Andy Wingo + + gst/: Add glib-compat.h. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gsttaglist.h: + * gst/gstcaps.h: + * gst/gststructure.h: Add glib-compat.h. + +2005-11-21 19:13:13 +0000 Wim Taymans + + gst/gstbin.c: Fix for #321595 + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_change_state_func): + Fix for #321595 + +2005-11-21 19:00:28 +0000 Wim Taymans + + gst/gstsegment.h: And add a nice define too. + Original commit message from CVS: + * gst/gstsegment.h: + And add a nice define too. + +2005-11-21 18:53:06 +0000 Wim Taymans + + gst/gstsegment.*: Make binding friendly. + Original commit message from CVS: + * gst/gstsegment.c: (gst_segment_copy), (gst_segment_get_type), + (gst_segment_new), (gst_segment_free), (gst_segment_init), + (gst_segment_set_duration), (gst_segment_set_last_stop), + (gst_segment_set_seek), (gst_segment_set_newsegment), + (gst_segment_to_stream_time), (gst_segment_to_running_time), + (gst_segment_clip): + * gst/gstsegment.h: + Make binding friendly. + +2005-11-21 18:41:39 +0000 Andy Wingo + + gst/: Sprinkle NULL_TERMINATED to taste. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gsttagsetter.h: + * gst/gsttaglist.h: + * gst/gststructure.h: + * gst/gstcaps.h: + * gst/gstutils.h: Sprinkle NULL_TERMINATED to taste. + +2005-11-21 18:27:26 +0000 Andy Wingo + + gst/gsterror.*: New error category. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gsterror.c (_gst_core_errors_init): + * gst/gsterror.h (GST_CORE_ERROR_MISSING_PLUGIN): New error + category. + +2005-11-21 18:16:00 +0000 Andy Wingo + + gst/Makefile.am (gst_headers): Add glib-compat.h. noinst the -private. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/Makefile.am (gst_headers): Add glib-compat.h. + (noinst_HEADERS): noinst the -private. + +2005-11-21 18:10:13 +0000 Michael Smith + + gst/: Remove unimplemented declarations for which we can see no sensible use. + Original commit message from CVS: + * gst/gstplugin.h: + * gst/gstregistry.h: + Remove unimplemented declarations for which we can see no sensible + use. + +2005-11-21 18:03:22 +0000 Andy Wingo + + gst/gst.h: Include glib-compat.h. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gst.h: Include glib-compat.h. + * gst/glib-compat.h: Add G_GNUC_NULL_TERMINATED. + * gst/glib-compat.c: Include the public and the private header. + * gst/glib-compat-private.h: Copied here from glib-compat.h. + * gst/gstvalue.c: + * gst/gstpad.c: + * gst/gstregistryxml.c: s/glib-compat/glib-compat-private/. + +2005-11-21 17:21:15 +0000 Andy Wingo + + check/gst/gstevent.c (create_custom_events): Check that + Original commit message from CVS: + 2005-11-21 Andy Wingo + * check/gst/gstevent.c (create_custom_events): Check that + FLUSH_STOP is serialized. + * check/elements/identity.c (event_func): + * check/elements/fakesrc.c (event_func): No stream lock, the core + takes it. + * gst/base/gstbasetransform.c (gst_base_transform_event): No more + stream lock taking, yay. + * gst/gstevent.h (GST_EVENT_FLUSH_STOP): Marked as serialized to + ensure that core takes the stream lock. + * gst/base/gstbasesrc.c (gst_base_src_do_seek): Update for stream + lock name change. + * gst/base/gstbasesink.c (gst_base_sink_event): No need to take + the stream lock for EOS, NEWSEGMENT, or FLUSH_STOP, the core does + it already. For the flush start we do take it though so we get the + right preroll state change messages. + * gst/gstqueue.c (gst_queue_sink_activate_push): No need to take + the stream lock here, the core does it for us. + * gst/gstpad.h (GST_PAD_GET_STREAM_LOCK): Renamed from + GST_STREAM_GET_LOCK. + (GST_PAD_STREAM_LOCK, GST_PAD_STREAM_TRYLOCK) + (GST_PAD_STREAM_UNLOCK, GST_PAD_STREAM_UNLOCK_FULL) + (GST_PAD_STREAM_LOCK_FULL): Renamed from GST_STREAM_*. + (GST_PAD_GET_PREROLL_LOCK): Renamed from GST_PREROLL_GET_LOCK. + (GST_PAD_PREROLL_LOCK, GST_PAD_PREROLL_TRYLOCK) + (GST_PAD_PREROLL_UNLOCK): Renamed from GST_PREROLL_*. + * gst/gstpad.c: Update for stream lock name change. + * gst/base/gstbasesink.c: Update for preroll lock name change. + +2005-11-21 17:12:50 +0000 Wim Taymans + + gst/: Convert Clock flags to object flags. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_init), (gst_clock_set_master), + (gst_clock_get_master): + * gst/gstclock.h: + * gst/gstsystemclock.c: (gst_system_clock_init): + Convert Clock flags to object flags. + Added methods to manage master/slave clocks. + +2005-11-21 17:09:45 +0000 Wim Taymans + + More segment updates, replace code in plugins with segment helper functions. + Original commit message from CVS: + * check/gst/gstsegment.c: (GST_START_TEST): + * docs/design/part-TODO.txt: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_do_sync), + (gst_base_sink_activate_pull), (gst_base_sink_get_position), + (gst_base_sink_query), (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query), + (gst_base_src_default_newsegment), + (gst_base_src_configure_segment), (gst_base_src_do_seek), + (gst_base_src_get_range), (gst_base_src_loop), + (gst_base_src_change_state): + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf), + (gst_base_transform_event), (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + * gst/base/gstcollectpads.c: (gst_collect_pads_add_pad), + (gst_collect_pads_event): + * gst/base/gstcollectpads.h: + * gst/elements/gstfakesrc.c: (gst_fake_src_init), + (gst_fake_src_create): + * gst/elements/gstfakesrc.h: + * gst/elements/gstidentity.c: (gst_identity_transform_ip): + * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration), + (gst_segment_set_last_stop), (gst_segment_set_seek), + (gst_segment_set_newsegment), (gst_segment_to_stream_time), + (gst_segment_to_running_time), (gst_segment_clip): + * gst/gstsegment.h: + More segment updates, replace code in plugins with segment + helper functions. + +2005-11-21 16:46:07 +0000 Jan Schmidt + + gst/elements/gstfdsrc.c: Don't ignore sscanf results + Original commit message from CVS: + * gst/elements/gstfdsrc.c: (gst_fdsrc_uri_set_uri): + Don't ignore sscanf results + +2005-11-21 16:41:16 +0000 Andy Wingo + + gst/gstpad.h (GST_IS_PAD_FAST): Removed. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstpad.h (GST_IS_PAD_FAST): Removed. + +2005-11-21 16:34:26 +0000 Andy Wingo + + *.*: Ran scripts/update-macros. Oh yes. gst/gstobject.h (GST_OBJECT_GET_LOCK, GST_OBJECT_LOCK) + Original commit message from CVS: + 2005-11-21 Andy Wingo + * *.h: + * *.c: Ran scripts/update-macros. Oh yes. + * gst/gstobject.h (GST_OBJECT_GET_LOCK, GST_OBJECT_LOCK) + (GST_OBJECT_TRYLOCK, GST_OBJECT_UNLOCK): Renamed from + GST_GET_LOCK, etc. + * scripts/update-macros: New script. Run it on your files to + change GST_LOCK to GST_OBJECT_LOCK, and the same for UNLOCK as + well. + +2005-11-21 15:47:09 +0000 Stefan Kost + + more docs fixes, add new api to the docs + Original commit message from CVS: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * gst/gstinfo.h: + more docs fixes, add new api to the docs + +2005-11-21 15:01:48 +0000 Andy Wingo + + gst/gstbin.c (gst_bin_remove_func): Wim claims I can remove this state_broadcast call. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstbin.c (gst_bin_remove_func): Wim claims I can remove this + state_broadcast call. + +2005-11-21 14:53:34 +0000 Andy Wingo + + gst/gstsegment.c (gst_segment_init): Initialize abs_rate. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstsegment.c (gst_segment_init): Initialize abs_rate. + +2005-11-21 14:52:56 +0000 Julien Moutte + + gst/gstvalue.c: Fix wrong function calls for arrays. + Original commit message from CVS: + 2005-11-21 Julien MOUTTE + * gst/gstvalue.c: (gst_value_intersect_array): Fix wrong + function calls for arrays. + +2005-11-21 14:50:22 +0000 Stefan Kost + + docs/random/ensonic/media-device-daemon.txt: wild idea, can this be done? + Original commit message from CVS: + * docs/random/ensonic/media-device-daemon.txt: + wild idea, can this be done? + * docs/gst/gstreamer-sections.txt: + * gst/gsterror.h: + * gst/gstfilter.c: + * gst/gstfilter.h: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gsttrace.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + doc fixes and additions + +2005-11-21 14:41:26 +0000 Andy Wingo + + * ChangeLog: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + gst/base/gstbasesrc.c (GST_LIVE_BROADCAST, GST_LIVE_SIGNAL) (GST_LIVE_TIMED_WAIT, GST_LIVE_WAIT, GST_LIVE_GET_COND) (... + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/base/gstbasesrc.c (GST_LIVE_BROADCAST, GST_LIVE_SIGNAL) + (GST_LIVE_TIMED_WAIT, GST_LIVE_WAIT, GST_LIVE_GET_COND) + (GST_LIVE_UNLOCK, GST_LIVE_TRYLOCK, GST_LIVE_LOCK) + (GST_LIVE_GET_LOCK): Moved here from gstbasesrc.h. They are + private to the basesrc implementation. + +2005-11-21 14:34:07 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_send_event): Doc more. Take stream lock on behalf of event function if necessary. It should no ... + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstpad.c (gst_pad_send_event): Doc more. Take stream lock on + behalf of event function if necessary. It should no longer be + necessary to take the stream lock in pad's event functions. Fixes + #320299. + +2005-11-21 14:28:21 +0000 Jan Schmidt + + Rename gst_caps_structure_fixate_* to gst_structure_fixate_* (#322027) + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: (gst_structure_fixate_field_nearest_int), + (gst_structure_fixate_field_nearest_double), + (gst_structure_fixate_field_boolean): + * gst/gststructure.h: + * win32/common/libgstreamer.def: + * win32/gstreamer.def: + Rename gst_caps_structure_fixate_* to gst_structure_fixate_* + (#322027) + +2005-11-21 14:25:21 +0000 Jan Schmidt + + gst/elements/gstfdsrc.*: Port fd:// URI handler from 0.8 to fdsrc + Original commit message from CVS: + * gst/elements/gstfdsrc.c: (_do_init), (gst_fdsrc_class_init), + (gst_fdsrc_init), (gst_fdsrc_dispose), (gst_fdsrc_set_property), + (gst_fdsrc_uri_get_type), (gst_fdsrc_uri_get_protocols), + (gst_fdsrc_uri_get_uri), (gst_fdsrc_uri_set_uri), + (gst_fdsrc_uri_handler_init): + * gst/elements/gstfdsrc.h: + Port fd:// URI handler from 0.8 to fdsrc + +2005-11-21 13:26:51 +0000 Wim Taymans + + More segment updates and more checks. + Original commit message from CVS: + * check/gst/gstsegment.c: (GST_START_TEST), (gstsegments_suite), + (main): + * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration), + (gst_segment_set_last_stop), (gst_segment_set_seek), + (gst_segment_set_newsegment), (gst_segment_to_stream_time), + (gst_segment_to_running_time), (gst_segment_clip): + * gst/gstsegment.h: + More segment updates and more checks. + +2005-11-21 13:26:40 +0000 Tim-Philipp Müller + + gst/gstvalue.*: Drop leading '%' from GST_FOURCC_FORMAT, thus making it consistent with our other format defines (#32... + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_transform_fourcc_string), + (gst_value_serialize_fourcc): + * gst/gstvalue.h: + Drop leading '%' from GST_FOURCC_FORMAT, thus making it + consistent with our other format defines (#320324). + +2005-11-21 13:12:18 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Revert previous commit. Value lists are by definition not fixed, as they are a list of possible values. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_is_fixed): + Revert previous commit. Value lists are by definition + not fixed, as they are a list of possible values. + +2005-11-21 13:03:36 +0000 Andy Wingo + + gst/gstevent.h (GST_EVENT_FILLER): Removed. Can be added back during the stable series if we need it. Fixes #319178. + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstevent.h (GST_EVENT_FILLER): Removed. Can be added back + during the stable series if we need it. Fixes #319178. + * gst/gstevent.c (gst_event_new_filler): Removed. + * check/gst/gstevent.c: Update comment about filler events. + +2005-11-21 12:42:41 +0000 Tim-Philipp Müller + + gst/gstvalue.c: Should handle both value arrays and value lists. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_is_fixed): + Should handle both value arrays and value lists. + +2005-11-21 12:27:01 +0000 Alessandro Dessina + + gst/gstvalue.c (gst_value_is_fixed): Use gst_value_array functions to access arrays. Fixes #321962. + Original commit message from CVS: + 2005-11-21 Andy Wingo + patch by: Alessandro Dessina + * gst/gstvalue.c (gst_value_is_fixed): Use gst_value_array + functions to access arrays. Fixes #321962. + +2005-11-21 11:26:07 +0000 Tim-Philipp Müller + + docs/gst/gstreamer.types: gst_collectpads_get_type => gst_collect_pads_get_type. + Original commit message from CVS: + * docs/gst/gstreamer.types: + gst_collectpads_get_type => gst_collect_pads_get_type. + * gst/base/gstbasetransform.c: + Remove unused SIGNAL_HANDOFF enum. + +2005-11-21 11:06:42 +0000 Andy Wingo + + gst/gstevent.h (GstEventTypeFlags): New data type, the flags of the event type (upstream, downstream, serialized). Re... + Original commit message from CVS: + 2005-11-21 Andy Wingo + * gst/gstevent.h (GstEventTypeFlags): New data type, the flags of + the event type (upstream, downstream, serialized). Renamed + GST_EVDIR_* and GST_EVSER to GST_EVENT_TYPE_*. + (GstEventType): Use GstEventTypeFlags. Rename CUSTOM_UP to + CUSTOM_UPSTREAM, CUSTOM_DS to CUSTOM_DOWNSTREAM, etc. + * gst/gstevent.c: Update for new CUSTOM event names. + * check/gst/gstevent.c: Update check for new CUSTOM event names. + * gst/gstevent.h: + * gst/gstevent.c (gst_event_type_get_flags): New function. Fixes + bug #319392. + +2005-11-21 11:00:03 +0000 Tim-Philipp Müller + + Rename gst_collecpads_foo() => gst_collect_pads_foo(). Document unimplemented functions as unimplemented (#320766). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstbase.def: + * win32/libgstbase.def: + * gst/base/gstcollectpads.c: (gst_collect_pads_base_init), + (gst_collect_pads_class_init), (gst_collect_pads_init), + (gst_collect_pads_finalize), (gst_collect_pads_new), + (gst_collect_pads_set_function), (gst_collect_pads_add_pad), + (gst_collect_pads_remove_pad), (gst_collect_pads_is_active), + (gst_collect_pads_collect), (gst_collect_pads_collect_range), + (gst_collect_pads_start), (gst_collect_pads_stop), + (gst_collect_pads_peek), (gst_collect_pads_pop), + (gst_collect_pads_available), (gst_collect_pads_read), + (gst_collect_pads_flush), (gst_collect_pads_event), + (gst_collect_pads_chain): + * gst/base/gstcollectpads.h: + Rename gst_collecpads_foo() => gst_collect_pads_foo(). Document + unimplemented functions as unimplemented (#320766). + +2005-11-21 10:41:03 +0000 Tim-Philipp Müller + + gst/gstmessage.c: Improve docs for DURATION message (usage of duration parameter) (#320113) + Original commit message from CVS: + * gst/gstmessage.c: + Improve docs for DURATION message (usage of duration parameter) + (#320113) + +2005-11-21 10:04:18 +0000 Thomas Vander Stichele + + * docs/random/moving-plugins: + update + Original commit message from CVS: + update + +2005-11-21 09:44:46 +0000 Christian Schaller + + * gstreamer.spec.in: + add latest .pc file to spec + Original commit message from CVS: + add latest .pc file to spec + +2005-11-20 19:11:09 +0000 Wim Taymans + + Added segment helper structure and methods. Not fully implemented yet. + Original commit message from CVS: + * check/Makefile.am: + * check/gst/gstsegment.c: (GST_START_TEST), (gstevents_suite), + (main): + * gst/Makefile.am: + * gst/gst.h: + * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration), + (gst_segment_set_seek), (gst_segment_set_newsegment), + (gst_segment_to_stream_time), (gst_segment_to_running_time), + (gst_segment_clip): + * gst/gstsegment.h: + Added segment helper structure and methods. Not fully implemented + yet. + Added segment check. + +2005-11-20 17:12:49 +0000 Jan Schmidt + + check/gst/gstvalue.c: Add a deserialisation test for fractions + Original commit message from CVS: + * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Add a deserialisation test for fractions + * examples/metadata/read-metadata.c: (message_loop), + (make_pipeline), (main): + Fix up metadata reading sample. + * gst/base/gstbasesink.c: (gst_base_sink_do_sync): + Debug format fix + * gst/base/gstbasesrc.c: (gst_base_src_default_negotiate): + Don't try and fixate empty caps + * gst/gst_private.h: + Wrap in G_BEGIN_DECLS/G_END_DECLS + * gst/gstvalue.c: (gst_value_collect_fraction), + (gst_value_set_fraction), (gst_value_get_fraction_denominator), + (gst_value_transform_string_fraction), + (gst_value_compare_fraction): + Add some extra guards to ensure that we don't end up + with an invalid denominator of 0 in a gstfraction and + that fractions always get reduced. + +2005-11-20 14:56:13 +0000 Wim Taymans + + * ChangeLog: + Something went wrong with changelog in last commit + Original commit message from CVS: + Something went wrong with changelog in last commit + +2005-11-20 14:50:43 +0000 Wim Taymans + + Doc fixes. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.h: + * gst/gstelement.c: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstindex.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstvalue.c: + Doc fixes. + +2005-11-20 13:28:11 +0000 Wim Taymans + + Make a proper enum of the flag. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * gst/gstcaps.h: + Make a proper enum of the flag. + +2005-11-19 18:57:00 +0000 Wim Taymans + + Add type to quark and type to string conversions. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * gst/gstformat.c: (_gst_format_initialize), (gst_format_get_name), + (gst_format_to_quark), (gst_format_register): + * gst/gstformat.h: + * gst/gstquery.c: (_gst_query_initialize), + (gst_query_type_get_name), (gst_query_type_to_quark), + (gst_query_type_register): + * gst/gstquery.h: + Add type to quark and type to string conversions. + +2005-11-19 18:32:01 +0000 Andy Wingo + + gst/gstbuffer.h (GST_BUFFER_FLAG_ORIGINAL): Removed. Fixes #320097. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstbuffer.h (GST_BUFFER_FLAG_ORIGINAL): Removed. Fixes + #320097. + +2005-11-19 18:28:40 +0000 Wim Taymans + + Make message handling overridable. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_provide_clock_func), + (gst_bin_add_func), (gst_bin_remove_func), (bin_bus_handler), + (gst_bin_handle_message_func): + * gst/gstbin.h: + Make message handling overridable. + +2005-11-19 18:26:35 +0000 Andy Wingo + + gst/gstpad.h (GST_PAD_IS_USABLE): Removed. Fixes #321235. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstpad.h (GST_PAD_IS_USABLE): Removed. Fixes #321235. + +2005-11-19 18:17:29 +0000 Andy Wingo + + gst/gstclock.*: Change resolution to be a GstClockTime. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstclock.h: + * gst/gstclock.c (GstClock, GstClockClass): Change resolution to + be a GstClockTime. + (gst_clock_set_resolution, gst_clock_get_resolution): Resolution + is a GstClockTime. Fixes #321710. + +2005-11-19 18:06:56 +0000 Andy Wingo + + gst/gstclock.h (GstClock): Remove offset property. Add internal_calibration and external_calibration. Fix padding. Pa... + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstclock.h (GstClock): Remove offset property. Add + internal_calibration and external_calibration. Fix padding. Pad + also by GstClockTime so we don't run into problems. + * gst/gstclock.c (gst_clock_set_rate_offset): Remove. + (gst_clock_get_rate_offset): Remove. + (gst_clock_set_time_adjust): Remove. Fixes #321712. + +2005-11-19 17:50:52 +0000 Andy Wingo + + gst/gstutils.h: gst/gstutils.c (g_static_rec_cond_wait) + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstutils.h: + * gst/gstutils.c (g_static_rec_cond_wait) + (g_static_rec_cond_timed_wait): Removed, no longer needed. + * gst/gstbin.c: Remove terrible continue_state prototype. + * gst/gstelement.h (gst_element_continue_state): Make public. + * gst/gstelement.h: + * gst/gstelement.c (gst_element_commit_state): Removed, replaced + by continue_state. Fixes #319389. + +2005-11-19 17:28:58 +0000 Andy Wingo + + gst/gstindex.h (GstIndexFilter): Actually pass on the user_data. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstindex.h (GstIndexFilter): Actually pass on the user_data. + Really fixes #168438. However I don't see anywhere where the + filter function is called... stupid GStreamer... + +2005-11-19 17:26:27 +0000 Andy Wingo + + gst/gstindex.h (GstIndex): Add field for user_data_destroy. We don't have a dispose function, so it won't get called ... + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstindex.h (GstIndex): Add field for user_data_destroy. We + don't have a dispose function, so it won't get called when the + object is unreffed, but oh well! + * gst/gstindex.c (gst_index_set_filter_full): New API function, + allows a destroy function to be set so user_data can be freed. + Fixes #168438. + (gst_index_set_filter): Call gst_index_set_filter_full. + +2005-11-19 17:08:23 +0000 Andy Wingo + + check/gst/gstvalue.c (test_string): Add test for bug #165650. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * check/gst/gstvalue.c (test_string): Add test for bug #165650. + * gst/gstvalue.c (gst_string_wrap): Trying to serialize a NULL + string should produce an error, given the lack of a way to + represent NULL strings. Fixes #165650. + +2005-11-19 16:46:30 +0000 Andy Wingo + + gst/gstvalue.h: gst/gstvalue.c (gst_value_array_append_value) (gst_value_array_prepend_value, gst_value_array_get_size) + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gstvalue.h: + * gst/gstvalue.c (gst_value_array_append_value) + (gst_value_array_prepend_value, gst_value_array_get_size) + (gst_value_array_get_value): New API, copied from + gst_value_list_*, only operates on arrays. + (gst_value_list_append_value, gst_value_list_prepend_value) + (gst_value_list_concat, gst_value_list_get_size) + (gst_value_list_get_value): Only operate on lists. Fixes #156633. + * gst/gstvalue.c (gst_value_init_list_or_array): Renamed from + init_list, because it works on both. + (copy_garray_of_gstvalue): Renamed from gst_value_list_copy_array. + (gst_value_copy_list_or_array): Renamed from copy_list. + (gst_value_free_list_or_array): Renamed from free_list. + (gst_value_collect_list_or_array): Renamed from collect_list. + (gst_value_lcopy_list_or_array): Renamed from lcopy_list. + (gst_value_list_or_array_peek_pointer): Renamed from + list_peek_pointer. + (_gst_value_array_value_table, _gst_value_list_value_table): + Update value table functions. + (gst_value_compare_list_or_array): Renamed from compare_list. + +2005-11-19 16:05:11 +0000 Andy Wingo + + gsttaglist.h: Whoops, foreach function returns void. Also fix some constness. + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gsttaglist.h: Whoops, foreach function returns void. Also fix + some constness. + +2005-11-19 15:51:41 +0000 Andy Wingo + + gst/gsttaglist.*: Operates on a const + Original commit message from CVS: + 2005-11-19 Andy Wingo + * gst/gsttaglist.c: + * gst/gsttaglist.h (gst_tag_list_foreach): Operates on a const + GstTagList*. Fixes #143472. + * gst/gststructure.h: Clarify what the foreach/map functions can + or can't do to their arguments. + +2005-11-18 19:21:50 +0000 Wim Taymans + + gst/gstclock.c: Doc and API fixes. + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_set_calibration), + (gst_clock_get_calibration): + Doc and API fixes. + Callibration can be set with internal time equal to current + internal time too. + +2005-11-18 18:55:24 +0000 Thomas Vander Stichele + + gst/gsterror.*: document + Original commit message from CVS: + * gst/gsterror.c: + * gst/gsterror.h: + document + +2005-11-18 18:38:41 +0000 Thomas Vander Stichele + + * docs/random/moving-plugins: + document on requirements for moving plugins to good + Original commit message from CVS: + document on requirements for moving plugins to good + +2005-11-18 16:24:56 +0000 Andy Wingo + + Add net pkgconfig files. + Original commit message from CVS: + 2005-11-18 Andy Wingo + * configure.ac: + * pkgconfig/gstreamer-net.pc.in: + * pkgconfig/gstreamer-net-uninstalled.pc.in: + * pkgconfig/Makefile.am: Add net pkgconfig files. + +2005-11-18 16:04:28 +0000 Stefan Kost + + gst/: docs fixes + Original commit message from CVS: + * gst/gstcaps.c: + * gst/gstghostpad.c: + * gst/gsttrace.c: + * gst/gstvalue.c: + * gst/gstvalue.h: + docs fixes + +2005-11-18 15:52:24 +0000 Andy Wingo + + gst/net/gstnetclientclock.c: Turn off debugging. + Original commit message from CVS: + 2005-11-18 Andy Wingo + * gst/net/gstnetclientclock.c: Turn off debugging. + * check/net/gstnetclientclock.c (test_functioning): Assert that the + times connverge somewhat. Can't make a real test. + +2005-11-18 15:30:18 +0000 Andy Wingo + + gst/net/gstnetclientclock.c (do_linear_regression): Use all integer arithmetic. Return the minimum of the domain, whi... + Original commit message from CVS: + 2005-11-18 Andy Wingo + * gst/net/gstnetclientclock.c (do_linear_regression): Use all + integer arithmetic. Return the minimum of the domain, which can be + set as "internal" for gst_clock_set_calibration. + (gst_net_client_clock_observe_times): Call _set_calibration. + (gst_net_client_clock_new): Call _set_calibration instead of + rate_offset. + * check/net/gstnetclientclock.c (test_functioning): Use the right + adjustment api. + * gst/gstclock.h: + * gst/gstclock.c (gst_clock_get_calibration) + (gst_clock_set_calibration): New functions, obsolete the ones I + added yesterday. Doh. Precision issues mean we have to extrapolate + from a point in the more recent past than 1970. + (gst_clock_get_rate_offset, gst_clock_set_rate_offset): Mark as + obsolete. + (gst_clock_adjust_unlocked): Use the right calibration data. + +2005-11-18 14:49:28 +0000 Edward Hervey + + gst/base/gstbasesink.c: Also reset the ->current_* values in READY->PAUSED + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_change_state): + Also reset the ->current_* values in READY->PAUSED + +2005-11-18 14:13:28 +0000 Andy Wingo + + gst/net/gstnetclientclock.c (gst_net_client_clock_thread): Whoops, check the right fd. Also add some debugging. + Original commit message from CVS: + 2005-11-18 Andy Wingo + * gst/net/gstnetclientclock.c (gst_net_client_clock_thread): + Whoops, check the right fd. Also add some debugging. + (gst_net_client_clock_observe_times): Adjust for int64 offset. + (do_linear_regression): Add a crapload of debugging. Subtract off + the minimum values from the input series to discard unneeded bits. + Use only int arithmetic. There is still double arithmetic when + calculating the intercept that needs fixing. Return boolean to + indicate success; FALSE would mean the domain or range is too + great. Still needs fixes. + +2005-11-18 13:18:44 +0000 Wim Taymans + + gst/base/gstbasesink.c: For the current position in stream time, we need to subtract accumulated time. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_get_position): + For the current position in stream time, we need to subtract + accumulated time. + * gst/gstsystemclock.c: (gst_system_clock_async_thread): + Release lock before calling the callback function of async + entries. + +2005-11-18 11:57:30 +0000 Andy Wingo + + gst/net/gstnetclientclock.c (gst_net_client_clock_class_init): Port goes all the way to MAXUINT16. + Original commit message from CVS: + 2005-11-18 Andy Wingo + * gst/net/gstnetclientclock.c (gst_net_client_clock_class_init): + Port goes all the way to MAXUINT16. + * gst/net/gstnettimeprovider.c: Make the port range the same as + for the kernel: 0 assigns, otherwise ports are less than + MAXUINT16. + * check/net/gstnettimeprovider.c: Adapt for 0 == kernel assigns + port change. + * check/net/gstnetclientclock.c (test_functioning): Add the start + of another test. + +2005-11-18 11:03:10 +0000 Wim Taymans + + gst/gstbin.*: Removing a clock provider from a bin, triggers a clock lost message so that a new clock will be selected. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_provide_clock_func), (gst_bin_add_func), + (gst_bin_remove_func), (bin_bus_handler): + * gst/gstbin.h: + Removing a clock provider from a bin, triggers a clock lost message + so that a new clock will be selected. + Adding a clock to a bin triggers a clock provider message. + Make sure we reselect a clock when we received a clock lost message. + Keep a reference to the element that provided the clock. + +2005-11-18 10:54:55 +0000 Andy Wingo + + gst/net/gstnetclientclock.c (gst_net_client_clock_new): Adjust the clock initially so it produces values around the b... + Original commit message from CVS: + 2005-11-18 Andy Wingo + * gst/net/gstnetclientclock.c (gst_net_client_clock_new): Adjust + the clock initially so it produces values around the base time. + (gst_net_client_clock_class_init): Typo fix. + (gst_net_client_clock_thread): Add note on when the socket gets + closed. + +2005-11-17 18:50:14 +0000 Wim Taymans + + gst/net/gstnetclientclock.c: Free remote and local time arrays. + Original commit message from CVS: + * gst/net/gstnetclientclock.c: (gst_net_client_clock_finalize): + Free remote and local time arrays. + +2005-11-17 18:18:41 +0000 Wim Taymans + + gst/net/gstnetclientclock.c: Fix compilation, uninitialized vars and a forgotten continue. + Original commit message from CVS: + * gst/net/gstnetclientclock.c: (do_linear_regression), + (gst_net_client_clock_do_select), (gst_net_client_clock_thread): + Fix compilation, uninitialized vars and a forgotten continue. + +2005-11-17 17:55:17 +0000 Andy Wingo + + check/: Add a most minimal test for the net client clock. More to come later. + Original commit message from CVS: + 2005-11-17 Andy Wingo + * check/Makefile.am (check_PROGRAMS): + * check/net/gstnetclientclock.c: Add a most minimal test for the + net client clock. More to come later. + * gst/net/gstnet.h: + * gst/net/Makefile.am: Add netclientclock. + * gst/net/gstnetclientclock.h: + * gst/net/gstnetclientclock.c: New files, implement an untested + GstClock that takes its time from a network time provider. + Implements the algorithm in network-clock.scm. + * tests/network-clock.scm (*window-size*): Rename from + *queue-length*. + * tests/network-clock.scm (network-time): + * tests/network-clock-utils.scm (q-push): Update callers. + +2005-11-17 16:02:48 +0000 Wim Taymans + + gst/gstbin.c: And unref the child too.. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_provide_clock_func), + (gst_bin_sort_iterator_new): + And unref the child too.. + +2005-11-17 14:51:11 +0000 Wim Taymans + + gst/gstbin.c: Refactor the sort iterator so it can be used while holding the + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_dispose), (gst_bin_provide_clock_func), + (gst_bin_sort_iterator_new), (gst_bin_iterate_sorted): + Refactor the sort iterator so it can be used while holding the + LOCK too. + Make clock selection select a clock closest to the source. + +2005-11-17 12:36:30 +0000 Michael Smith + + gst/gstclock.*: Anonymous structs are a gcc (and some other compilers) extension, so don't use them. Since this is on... + Original commit message from CVS: + * gst/gstclock.c: (gst_clock_init), (gst_clock_adjust_unlocked), + (gst_clock_set_rate_offset), (gst_clock_get_rate_offset): + * gst/gstclock.h: + Anonymous structs are a gcc (and some other compilers) extension, so + don't use them. Since this is only for ABI-compatibility, and our + API/ABI freeze is over in a few days, this whole thing will only + last a few days, so don't bother trying to think up a meaningful + name for the struct. + +2005-11-17 11:51:49 +0000 Andy Wingo + + gst/gstclock.h (GstClock): Add rate and offset properties, preserving ABI stability. Add rate/offset accessors. Will ... + Original commit message from CVS: + 2005-11-17 Andy Wingo + * gst/gstclock.h (GstClock): Add rate and offset properties, + preserving ABI stability. Add rate/offset accessors. Will file bug + for the freeze break. + * gst/gstclock.c (gst_clock_adjust_unlocked): Implement using rate + and offset, trying to keep precision and avoiding + underflow/overflow. + (gst_clock_set_rate_offset, gst_clock_get_rate_offset): New + functions. Make gst_clock_set_time_adjust obsolete. + (gst_clock_set_time_adjust): Note that this function is obsolete. + Will file bug soon. + * gst/base/gstbasetransform.h: Make the ABI-stability hack + greppable by using GST_PADDING-1+1. + +2005-11-17 11:25:34 +0000 Thomas Vander Stichele + + * docs/random/NOTES-0.1.1: + * docs/random/NOTES-0.2.0: + * docs/random/TODO-post-0.1.0: + * docs/random/arch: + * docs/random/coroutines: + * docs/random/design: + * docs/random/factoryinfo: + * docs/random/gboolean: + * docs/random/padarch: + * docs/random/sequence: + * docs/random/state-transitions: + * docs/random/states: + * docs/random/states.new: + * docs/random/states.old: + * docs/random/walkthrough: + remove completely outdated random docs + Original commit message from CVS: + remove completely outdated random docs + +2005-11-17 09:37:55 +0000 Tim-Philipp Müller + + gst/gstmessage.c: Assertion should check for CLOCK_LOST, not NEW_CLOCK (#321648). + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstmessage.c: (gst_message_parse_clock_lost): + Assertion should check for CLOCK_LOST, not NEW_CLOCK (#321648). + * gst/gstpadtemplate.h: + * gst/gstpluginfeature.h: + Don't use c++ style comments in headers (#321638). + +2005-11-16 18:37:57 +0000 Andy Wingo + + gst/net/gstnettimepacket.c (gst_net_time_packet_send): Free buffer. + Original commit message from CVS: + 2005-11-16 Andy Wingo + * gst/net/gstnettimepacket.c (gst_net_time_packet_send): Free + buffer. + +2005-11-16 18:16:51 +0000 Andy Wingo + + check/net/gstnettimeprovider.c: Check to see that the time provider actually provides times. Works, yo! + Original commit message from CVS: + 2005-11-16 Andy Wingo + * check/net/gstnettimeprovider.c: Check to see that the time + provider actually provides times. Works, yo! + +2005-11-16 18:09:47 +0000 Wim Taymans + + check/Makefile.am: Enable more tests. + Original commit message from CVS: + * check/Makefile.am: + Enable more tests. + * check/elements/fakesrc.c: (GST_START_TEST): + Set element to NULL before disposing it. + +2005-11-16 17:53:54 +0000 Andy Wingo + + * gst/net/Makefile.am: + * libs/gst/net/Makefile.am: + fix + Original commit message from CVS: + fix + +2005-11-16 17:52:04 +0000 Andy Wingo + + gst/net/: Use the timepacket stuff in the provider, include it from gstnet.h, and add it to the build. + Original commit message from CVS: + 2005-11-16 Andy Wingo + * gst/net/Makefile.am: + * gst/net/gstnet.h: + * gst/net/gstnettimeprovider.c: + * gst/net/gstnettimeprovider.h: Use the timepacket stuff in the + provider, include it from gstnet.h, and add it to the build. + * gst/net/gstnettimepacket.h: + * gst/net/gstnettimepacket.c: New files, abstracts out the packet + sending and receiving. + +2005-11-16 17:35:07 +0000 Wim Taymans + + check/Makefile.am: Enable valgrind check. + Original commit message from CVS: + * check/Makefile.am: + Enable valgrind check. + * gst/elements/gstfakesrc.c: (gst_fake_src_alloc_parent), + (gst_fake_src_alloc_buffer): + Fix memleak. + +2005-11-16 17:22:36 +0000 Wim Taymans + + gst/net/gstnettimeprovider.c: Call parent finalize too. + Original commit message from CVS: + * gst/net/gstnettimeprovider.c: (gst_net_time_provider_finalize): + Call parent finalize too. + +2005-11-16 17:18:34 +0000 Wim Taymans + + check/Makefile.am: Enable valgrind check that should work fine now. + Original commit message from CVS: + * check/Makefile.am: + Enable valgrind check that should work fine now. + * gst/elements/gsttypefindelement.c: (gst_type_find_element_init): + * gst/gstqueue.c: (gst_queue_init): + Fix memleaks in pad allocation. + +2005-11-16 16:49:49 +0000 Andy Wingo + + gst/net/: New part of core to hold network elements and objects. Put in core because it exposes API that applications... + Original commit message from CVS: + 2005-11-16 Andy Wingo + * gst/net/Makefile.am: + * gst/net/gstnet.h: New part of core to hold network elements and + objects. Put in core because it exposes API that applications want + to use. The library is named libgstnet-tempname right now because + of the existing libgstnet in gst-plugins-base. Solution is + probably to rename the one in plugins-base; will file a bug for + the freeze break. + * gst/net/gstnettimeprovider.c: + * gst/net/gstnettimeprovider.h: New object to export a GstClock's + get_time call over the network. + * configure.ac: + * gst/Makefile.am (lib_LTLIBRARIES): Add gstnet to the build. + * check/Makefile.am: + * check/net/gstnettimeprovider.c: A most minimal test suite. Will + get additions shortly. + +2005-11-16 16:09:49 +0000 Thomas Vander Stichele + + gst/gstpad.*: add gst_pad_new_from_static_template functions + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_new_from_static_template): + * gst/gstpad.h: + add gst_pad_new_from_static_template functions + * gst/check/gstcheck.c: (gst_check_setup_src_pad), + (gst_check_setup_sink_pad): + * gst/elements/gsttee.c: (gst_tee_init): + and use them + +2005-11-16 16:06:06 +0000 Wim Taymans + + gst/gstpad.c: Removed warning, it's not realy an error either. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_pause_task): + Removed warning, it's not realy an error either. + +2005-11-16 14:27:20 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Check if the caps are NULL, this can happen if the element is shutting down and the pad ... + Original commit message from CVS: + * gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf), + (gst_base_transform_event): + Check if the caps are NULL, this can happen if the element + is shutting down and the pad caps are set to NULL. + +2005-11-16 12:57:51 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/elements/gsttee.c: + * plugins/elements/gsttee.c: + fix pad tempalte leak in tee + Original commit message from CVS: + fix pad tempalte leak in tee + +2005-11-16 12:40:18 +0000 Thomas Vander Stichele + + gst/: use gst_object_ref when setting the pad template; this will trigger the pad template leaks on GLib 2.6 and the ... + Original commit message from CVS: + * gst/glib-compat.c: (g_value_dup_gst_object): + * gst/glib-compat.h: + * gst/gstpad.c: (gst_pad_set_property): + use gst_object_ref when setting the pad template; this will + trigger the pad template leaks on GLib 2.6 and the slaves + +2005-11-16 12:25:22 +0000 Thomas Vander Stichele + + gst/: remove functions copied from GLib 2.6 + Original commit message from CVS: + * gst/glib-compat.c: (gst_flags_get_first_value): + * gst/glib-compat.h: + * gst/gstregistryxml.c: + remove functions copied from GLib 2.6 + +2005-11-16 11:29:57 +0000 Michael Smith + + gst/Makefile.am: Don't link against VALGRIND_LIBS. That was always the wrong thing to do, but only breaks with newer ... + Original commit message from CVS: + * gst/Makefile.am: + Don't link against VALGRIND_LIBS. That was always the wrong thing to + do, but only breaks with newer valgrind versions. We're not a + valgrind tool, we have no link-time dependencies on libcoregrind. + +2005-11-16 11:06:07 +0000 Thomas Vander Stichele + + gst/base/gstbasesrc.c: some debug changes + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_default_negotiate): + some debug changes + * gst/gstmessage.h: + typo fixes + +2005-11-15 23:53:08 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/base/gstbasesrc.c: + * gst/elements/gsttypefindelement.c: + * gst/gstqueue.c: + * gst/gstregistryxml.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + Revert all these unrefs, they don't even pass make check ! + Original commit message from CVS: + Revert all these unrefs, they don't even pass make check ! + +2005-11-15 19:48:40 +0000 Johan Dahlin + + * gst/base/gstbasesrc.c: + * gst/elements/gsttypefindelement.c: + * gst/gstqueue.c: + * gst/gstregistryxml.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + And gst_object_unref here too + Original commit message from CVS: + And gst_object_unref here too + +2005-11-15 19:31:05 +0000 Johan Dahlin + + gst/: Free pad templates, fixes a couple of leaks. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_init): + * gst/elements/gsttypefindelement.c: (gst_type_find_element_init): + * gst/gstqueue.c: (gst_queue_init): + Free pad templates, fixes a couple of leaks. + +2005-11-15 19:24:46 +0000 Tim-Philipp Müller + + gst/gstpad.c: GST_PAD_PAD_TEMPLATE(pad) gets the pad template, while + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstpad.c: (gst_pad_get_property): + GST_PAD_PAD_TEMPLATE(pad) gets the pad template, while + GST_PAD_TEMPLATE(pad) does a cast. We want the former here. + (#321452) + +2005-11-15 18:34:28 +0000 Wim Taymans + + gst/gstevent.c: Small doc update. + Original commit message from CVS: + * gst/gstevent.c: + Small doc update. + +2005-11-15 17:57:51 +0000 Andy Wingo + + gst/gstelement.c (gst_element_set_base_time): Add debugging. + Original commit message from CVS: + 2005-11-15 Andy Wingo + * gst/gstelement.c (gst_element_set_base_time): Add debugging. + * gst/gstpipeline.c (gst_pipeline_set_new_stream_time): Document + using GST_CLOCK_TIME_NONE to disable base time management. + (do_pipeline_seek, gst_pipeline_change_state): Don't reset stream + time if it was NONE before. + (gst_pipeline_change_state): Only munge the base time if + stream_time != GST_CLOCK_TIME_NONE. + * check/gst/gstpipeline.c (test_base_time): Punt around the + problem of the probe not being called, because that's not the + issue I'm looking at. Add a check that setting stream_time to NONE + disables base time management. + +2005-11-15 17:18:10 +0000 Wim Taymans + + gst/base/gstbasesink.c: segment_stop == -1 at startup. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_change_state): + segment_stop == -1 at startup. + * gst/base/gstbasetransform.c: (gst_base_transform_event), + (gst_base_transform_change_state): + Init segment values at start. + +2005-11-15 16:52:46 +0000 Andy Wingo + + check/gst/gstpipeline.c (test_base_time): Punt around the problem of the probe not being called, because that's not t... + Original commit message from CVS: + 2005-11-15 Andy Wingo + * check/gst/gstpipeline.c (test_base_time): Punt around the + problem of the probe not being called, because that's not the + issue I'm looking at... + +2005-11-15 16:47:07 +0000 Wim Taymans + + gst/base/gstbasesink.c: 0 segment values are 0 in any format. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + 0 segment values are 0 in any format. + * gst/base/gstbasetransform.c: (gst_base_transform_event): + * gst/base/gstbasetransform.h: + Parse newsegment correctly in basetransform + * gst/elements/gstidentity.c: (gst_identity_transform_ip): + Sync to clock using updated segment values. + +2005-11-15 16:27:04 +0000 Andy Wingo + + check/gst/gstpipeline.c (test_base_time): Add check that the base time and stream time are reset correctly. + Original commit message from CVS: + 2005-11-15 Andy Wingo + * check/gst/gstpipeline.c (test_base_time): Add check that the + base time and stream time are reset correctly. + +2005-11-15 15:44:46 +0000 Wim Taymans + + docs/design/part-TODO.txt: Some more TODO items. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Some more TODO items. + +2005-11-15 12:35:45 +0000 Andy Wingo + + gst/elements/gstfakesrc.c (gst_fake_src_create): It's not an error if the user selected "no clock" as the clocking me... + Original commit message from CVS: + 2005-11-15 Andy Wingo + * gst/elements/gstfakesrc.c (gst_fake_src_create): It's not an + error if the user selected "no clock" as the clocking method. + +2005-11-15 12:29:07 +0000 Andy Wingo + + check/gst/gstpipeline.c (test_base_time): New test for buffer timestamps with live capture. + Original commit message from CVS: + 2005-11-15 Andy Wingo + * check/gst/gstpipeline.c (test_base_time): New test for buffer + timestamps with live capture. + * gst/elements/gstfakesrc.c (gst_fake_src_create): If the datarate + is 0 but we are a live source, timestamp the buffers using the + element's clock. + +2005-11-14 15:15:43 +0000 Stefan Kost + + more section docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsterror.c: + * gst/gstghostpad.c: + * gst/gstobject.h: + * gst/gstxml.c: + more section docs + +2005-11-14 14:45:43 +0000 Wim Taymans + + common/gst.supp: add suppressions from Wim's Debian machine + Original commit message from CVS: + * common/gst.supp: + add suppressions from Wim's Debian machine + +2005-11-14 14:36:17 +0000 Thomas Vander Stichele + + common/gst.supp: add suppressions from Andy's AMD64 Ubuntu machine + Original commit message from CVS: + * common/gst.supp: + add suppressions from Andy's AMD64 Ubuntu machine + +2005-11-14 12:43:43 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_set_active): Change docs; parent's + Original commit message from CVS: + 2005-11-14 Andy Wingo + * gst/gstpad.c (gst_pad_set_active): Change docs; parent's + STATE_LOCK not necessary. Fixes #311489. + +2005-11-14 12:17:46 +0000 Andy Wingo + + gst/gsterror.c (FILE_A_BUG): Be polite *and* helpful. Fixes #305291. + Original commit message from CVS: + 2005-11-14 Andy Wingo + * gst/gsterror.c (FILE_A_BUG): Be polite *and* helpful. Fixes + #305291. + +2005-11-14 11:58:44 +0000 Andy Wingo + + gst/gstindex.c (gst_index_add_object): Note in the docs that this function is not implemented. + Original commit message from CVS: + 2005-11-14 Andy Wingo + * gst/gstindex.c (gst_index_add_object): Note in the docs that + this function is not implemented. + +2005-11-14 10:49:35 +0000 Julien Moutte + + gst/base/gstbasetransform.c: Ref the source pad caps while we need them. + Original commit message from CVS: + 2005-11-14 Julien MOUTTE + * gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf): + Ref the source pad caps while we need them. + Fixes (#321386) + +2005-11-12 10:23:52 +0000 Thomas Vander Stichele + + * check/pipelines/.gitignore: + * tests/check/pipelines/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-11-12 10:04:01 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update win32 files for HEAD + Original commit message from CVS: + update win32 files for HEAD + +2005-11-12 10:03:08 +0000 Thomas Vander Stichele + + * gst/gsttask.c: + debug task join + Original commit message from CVS: + debug task join + +2005-11-12 10:00:03 +0000 Thomas Vander Stichele + + * docs/manual/appendix-quotes.xml: + found another quote + Original commit message from CVS: + found another quote + +2005-11-11 20:12:42 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Added some docs for GstCollectData. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Added some docs for GstCollectData. + * gst/base/gstadapter.c: + Some small code example fix. + * gst/base/gstcollectpads.c: + * gst/base/gstcollectpads.h: + Document some more. + +2005-11-11 19:26:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to head + Original commit message from CVS: + back to head + +=== release 0.9.5 === + +2005-11-11 19:24:30 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * win32/common/config.h: + releasing 0.9.5 + Original commit message from CVS: + releasing 0.9.5 + +2005-11-11 18:25:50 +0000 Wim Taymans + + gst/gstbuffer.c: Copy more flags. + Original commit message from CVS: + * gst/gstbuffer.c: (_gst_buffer_copy): + Copy more flags. + * gst/gstcaps.c: (gst_caps_is_equal): + Fix some docs. + Make _is_equal fast in the trivial cases. + * gst/gstminiobject.c: + * gst/gstminiobject.h: + More docs. Spifify .h file. + * gst/gstutils.c: + Small doc update. + +2005-11-11 17:16:18 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2005-11-11 16:37:11 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Small cleanups. + Original commit message from CVS: + * gst/base/gstbasetransform.c: + (gst_base_transform_prepare_output_buf), + (gst_base_transform_handle_buffer): + Small cleanups. + If we're processing a buffer and need to allocate an output + buffer, we cannot accept a format change. If we did get a + format change, we have to alloc a buffer ourselves of the + right size. + +2005-11-11 16:34:15 +0000 Wim Taymans + + gst/gstpad.c: While checking the flag for reentrancy in the gstcaps function is nice to detect recursive invocations,... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_caps), (gst_pad_peer_get_caps): + While checking the flag for reentrancy in the gstcaps function + is nice to detect recursive invocations, it also makes it + impossible to call getcaps from multiple threads, which must be + possible. So, checking for recursive calls has to go. + +2005-11-11 15:19:37 +0000 Michael Smith + + gst/base/gstbasesink.c: Don't sync on buffers that fall partially outside our current segment. Prevents an assertion ... + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_do_sync): + Don't sync on buffers that fall partially outside our current + segment. Prevents an assertion failure/abort playing some files. + +2005-11-10 18:15:24 +0000 Andy Wingo + + check/gst/gstbin.c (test_message_state_changed_children): Style fix.. + Original commit message from CVS: + 2005-11-10 Andy Wingo + * check/gst/gstbin.c (test_message_state_changed_children): Style + fix.. + * gst/gstbus.c (poll_destroy, poll_func, gst_bus_poll): Implement + gst_bus_poll with the signal watch. Ensures that poll and a signal + watch see the same messages. + * check/gst/gstbus.c (test_watch_with_poll): New test, checks that + a poll and a watch at the same time get the same messages. + +2005-11-10 17:37:39 +0000 Thomas Vander Stichele + + gst/: Don't call gst_caps_do_simplify - it doesn't respect order of caps and it's not needed. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps): + * gst/gstcaps.c: (gst_caps_intersect): + Don't call gst_caps_do_simplify - it doesn't respect order of caps + and it's not needed. + +2005-11-10 15:07:46 +0000 Wim Taymans + + docs/design/part-TODO.txt: Updated todo. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Updated todo. + +2005-11-10 14:45:27 +0000 Wim Taymans + + gst/base/: Implement clock sync in base class. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_do_sync): + * gst/base/gstbasesrc.c: (gst_base_src_wait), + (gst_base_src_do_sync), (gst_base_src_get_range): + Implement clock sync in base class. + +2005-11-10 12:32:57 +0000 Tim-Philipp Müller + + gst/gststructure.c: Forward-port a 0.8 patch to handle escaped spaces in structure string, so that gst_parse... + Original commit message from CVS: + patch by: Tim-Philipp Müller + * gst/gststructure.c: (gst_structure_parse_field), + (gst_structure_from_string): + Forward-port a 0.8 patch to handle escaped spaces in structure string, so that gst_parse_launch() can deal with spaces in filtered link + caps (fixes #164479) + * check/gst/capslist.h: + * check/gst/gststructure.c: (GST_START_TEST): + add unit tests for this change + +2005-11-10 11:17:26 +0000 Wim Taymans + + Fix docs, move some STATE macros to private. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstelement.h: + Fix docs, move some STATE macros to private. + +2005-11-10 10:17:01 +0000 Michael Smith + + * gst/gstquery.c: + * gst/gstquery.h: + Further improve query docs. Still not happy with this. + Original commit message from CVS: + Further improve query docs. Still not happy with this. + +2005-11-10 09:19:12 +0000 Wim Taymans + + check/gst/gstghostpad.c: Added check for bug #317341 + Original commit message from CVS: + * check/gst/gstghostpad.c: (GST_START_TEST), (gst_ghost_pad_suite): + Added check for bug #317341 + * gst/gstbuffer.c: + * gst/gstbuffer.h: + Some more spiffifying. + * gst/gstghostpad.c: (gst_ghost_pad_do_link): + Call peer linkfunction if we are a source pad. Totally fixes + #317341 + * gst/gstpad.c: + Update docs, source pads should call the peer linkfunction + so they can atomically perform the pad link. + +2005-11-09 19:32:32 +0000 Michael Smith + + * gst/gstquery.c: + Improve/fix documentation for GstQuery. + Original commit message from CVS: + Improve/fix documentation for GstQuery. + This still needs some more work to explain what the queries actually mean. + +2005-11-09 18:41:53 +0000 Michael Smith + + * gst/base/gstadapter.c: + * libs/gst/base/gstadapter.c: + Slightly polish docs for GstAdapter. + Original commit message from CVS: + Slightly polish docs for GstAdapter. + +2005-11-09 18:10:53 +0000 Wim Taymans + + gst/gstbuffer.*: Uber-spiffy-spiffify some more. + Original commit message from CVS: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + Uber-spiffy-spiffify some more. + +2005-11-09 17:55:13 +0000 Tim-Philipp Müller + + gst/: Use GST_DEBUG_FUNCPTR() more extensively. + Original commit message from CVS: + * gst/base/gstcollectpads.c: (gst_collectpads_add_pad): + * gst/elements/gstfilesink.c: (gst_file_sink_init): + * gst/elements/gsttypefindelement.c: (gst_type_find_element_init): + * gst/gstghostpad.c: (gst_ghost_pad_set_internal), + (gst_ghost_pad_init), (gst_ghost_pad_new_notarget): + * gst/gstpad.c: (gst_pad_init): + Use GST_DEBUG_FUNCPTR() more extensively. + +2005-11-09 17:32:10 +0000 Wim Taymans + + gst/gstobject.*: Documentation fixes. + Original commit message from CVS: + * gst/gstobject.c: (gst_object_class_init): + * gst/gstobject.h: + Documentation fixes. + +2005-11-09 17:06:20 +0000 Edward Hervey + + gst/gsttypefindfactory.c: Fix docs. + Original commit message from CVS: + * gst/gsttypefindfactory.c: + Fix docs. + +2005-11-09 16:44:40 +0000 Edward Hervey + + gst/: + Original commit message from CVS: + * gst/base/gsttypefindhelper.c: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + +2005-11-09 16:32:49 +0000 Wim Taymans + + gst/gstiterator.c: Fix revision data. + Original commit message from CVS: + * gst/gstiterator.c: + Fix revision data. + * gst/gsttask.c: + * gst/gsttask.h: + Fix docs. + +2005-11-09 16:16:41 +0000 Wim Taymans + + gst/: Fix docs. + Original commit message from CVS: + * gst/gstevent.h: + * gst/gsturi.h: + Fix docs. + +2005-11-09 16:00:05 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Moved the message async delivery private lock and cond to the private section. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Moved the message async delivery private lock and cond + to the private section. + * gst/gstmessage.c: + * gst/gstmessage.h: + Fixed docs. + +2005-11-09 15:34:46 +0000 Edward Hervey + + Document GstURIHandler + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsturi.c: + * gst/gsturi.h: + Document GstURIHandler + +2005-11-09 15:31:08 +0000 Wim Taymans + + gst/gstiterator.*: Fix iterator docs. + Original commit message from CVS: + * gst/gstiterator.c: (gst_iterator_fold), (gst_iterator_foreach), + (gst_iterator_find_custom): + * gst/gstiterator.h: + Fix iterator docs. + +2005-11-09 15:10:32 +0000 Wim Taymans + + gst/gstbin.h: Document another field. + Original commit message from CVS: + * gst/gstbin.h: + Document another field. + * gst/gststructure.c: + * gst/gststructure.h: + Document. + +2005-11-09 13:14:27 +0000 Wim Taymans + + gst/gstbin.h: Documented structs. + Original commit message from CVS: + * gst/gstbin.h: + Documented structs. + +2005-11-09 12:36:17 +0000 Wim Taymans + + docs/gst/gstreamer-sections.txt: Added some new macros. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + Added some new macros. + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstobject.h: + Docs updates. + +2005-11-09 12:01:46 +0000 Wim Taymans + + docs/design/part-TODO.txt: Some more items for the TODO + Original commit message from CVS: + * docs/design/part-TODO.txt: + Some more items for the TODO + * gst/gstcaps.c: + * gst/gstcaps.h: + Document GstCaps. + +2005-11-09 10:06:30 +0000 Andy Wingo + + gst/base/gstbasesink.c: Add the beginning of docs here -- have to work on something else now tho... + Original commit message from CVS: + 2005-11-09 Andy Wingo + * gst/base/gstbasesink.c: Add the beginning of docs here -- have + to work on something else now tho... + +2005-11-09 09:48:16 +0000 Andy Wingo + + * ChangeLog: + * gst/base/gstadapter.c: + * gst/base/gstadapter.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstadapter.h: + gst/elements/gstfilesink.c (gst_file_sink_start) + Original commit message from CVS: + 2005-11-09 Andy Wingo + * gst/elements/gstfilesink.c (gst_file_sink_start) + (gst_file_sink_stop): New functions, replace the state change + handler. + (gst_file_sink_class_init): Hook up the start and stop functions. + (gst_file_sink_base_init): Don't set the state change handler any + more. It was a bit ugly too, being set from here... + (gst_file_sink_get_property, gst_file_sink_set_property): + Cleanups... + (gst_file_sink_set_location): More robust check that doesn't call + GST_STATE. Ugggggg. + +2005-11-09 09:47:12 +0000 Andy Wingo + + * ChangeLog: + * gst/elements/gstfilesink.c: + * plugins/elements/gstfilesink.c: + gst/elements/gstfilesink.c (gst_file_sink_start) + Original commit message from CVS: + 2005-11-09 Andy Wingo + * gst/elements/gstfilesink.c (gst_file_sink_start) + (gst_file_sink_stop): New functions, replace the state change + handler. + (gst_file_sink_class_init): Hook up the start and stop functions. + (gst_file_sink_base_init): Don't set the state change handler any + more. It was a bit ugly too, being set from here... + (gst_file_sink_get_property, gst_file_sink_set_property): + Cleanups... + (gst_file_sink_set_location): More robust check that doesn't call + GST_STATE. Ugggggg. + +2005-11-08 12:33:09 +0000 Tim-Philipp Müller + + gst/base/gstbasetransform.c: Hold STREAM_LOCK while pushing newsegment or tag events as well. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_event): + Hold STREAM_LOCK while pushing newsegment or tag events as well. + +2005-11-08 11:52:24 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + revert part of the patch so that paths are correct + Original commit message from CVS: + revert part of the patch so that paths are correct + +2005-11-08 11:13:07 +0000 Wim Taymans + + gst/: Avoid excessive typechecking in macros. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty), + (gst_base_sink_do_sync), (gst_base_sink_handle_event), + (gst_base_sink_chain), (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.h: + * gst/gstelement.h: + * gst/gstevent.h: + Avoid excessive typechecking in macros. + * gst/gstminiobject.c: (gst_mini_object_get_type), + (gst_mini_object_init), (gst_mini_object_new), + (gst_mini_object_free): + * gst/gstobject.c: (gst_object_class_init), (gst_object_init), + (gst_object_finalize): + Remove cruft code, optimize alloc_trace. + +2005-11-07 18:16:13 +0000 Thomas Vander Stichele + + docs/faq/gst-uninstalled: fix up PS1 for systems that try to reset it + Original commit message from CVS: + * docs/faq/gst-uninstalled: + fix up PS1 for systems that try to reset it + +2005-11-07 10:33:07 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Set the segment_end to -1 initially. Fixed typefind. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_init), + (gst_base_src_get_range): + Set the segment_end to -1 initially. Fixed typefind. + +2005-11-07 10:13:47 +0000 Tim-Philipp Müller + + gst/base/gstadapter.c: Debug category should be 'adapter', not 'GstAdapter'. + Original commit message from CVS: + * gst/base/gstadapter.c: + Debug category should be 'adapter', not 'GstAdapter'. + * gst/base/gstcollectpads.c: (gst_collectpads_base_init), + (gst_collectpads_class_init), (gst_collectpads_init), + (gst_collectpads_peek), (gst_collectpads_pop), + (gst_collectpads_event), (gst_collectpads_chain): + Add debug category and some debugging output. Use boilerplate + macros. Remove some extraneous words from docs. + +2005-11-05 15:14:33 +0000 Andy Wingo + + gst/base/gstpushsrc.c: Shorten by 30% via use of boilerplate macro. + Original commit message from CVS: + 2005-11-05 Andy Wingo + * gst/base/gstpushsrc.c: Shorten by 30% via use of boilerplate + macro. + +2005-11-04 20:12:01 +0000 Stefan Kost + + more docs added + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstcaps.h: + * gst/gstinfo.c: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstutils.h: + more docs added + +2005-11-04 15:33:40 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Small update to stop at the configured segment_end position. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_get_range): + Small update to stop at the configured segment_end + position. + +2005-11-04 15:02:48 +0000 Stefan Kost + + gst/gstregistry.*: added missing docs + Original commit message from CVS: + * gst/gstregistry.c: + * gst/gstregistry.h: + added missing docs + +2005-11-04 14:35:10 +0000 Edward Hervey + + gst/base/gstbasesrc.c: Check if we are doing a segment seek and have arrived at the end of that segment. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_get_range): + Check if we are doing a segment seek and have arrived at the + end of that segment. + +2005-11-04 12:08:19 +0000 Wim Taymans + + gst/gstbus.c: Don't leak a mutex unlock in case of an error. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_post), (gst_bus_set_sync_handler): + Don't leak a mutex unlock in case of an error. + * gst/gstbus.h: + Doc fixes. + +2005-11-04 11:43:10 +0000 Wim Taymans + + gst/gstbus.c: Get the context to wake up only once. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_class_init), (gst_bus_init), + (gst_bus_post): + Get the context to wake up only once. + +2005-11-03 20:17:24 +0000 Stefan Kost + + check/states/sinks.c: Uncomment fixed check. + Original commit message from CVS: + * check/states/sinks.c: (GST_START_TEST): + Uncomment fixed check. + * docs/design/part-TODO.txt: + Updated TODO. + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_do_sync), + (gst_base_sink_get_position): + If we are going to PLAYING, post the right pending state + when we post the intermediate paused message. + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_set_state_func), (gst_element_change_state): + Don't post state changes that were between the same state + and were not ASYNC. + +2005-11-03 20:14:24 +0000 Wim Taymans + + check/states/sinks.c: Uncomment fixed check. + Original commit message from CVS: + * check/states/sinks.c: (GST_START_TEST): + Uncomment fixed check. + * docs/design/part-TODO.txt: + Updated TODO. + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_do_sync), + (gst_base_sink_get_position): + If we are going to PLAYING, post the right pending state + when we post the intermediate paused message. + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_set_state_func), (gst_element_change_state): + Don't post state changes that were between the same state + and were not ASYNC. + +2005-11-03 19:38:48 +0000 Stefan Kost + + doc fixes + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: + * gst/gstminiobject.c: + doc fixes + +2005-11-03 17:53:27 +0000 Andy Wingo + + check/states/sinks.c (test_livesrc_sink): Add checks that the state-changed messages actually have the right order an... + Original commit message from CVS: + 2005-11-03 Andy Wingo + * check/states/sinks.c (test_livesrc_sink): Add checks that the + state-changed messages actually have the right order and the right + values. + +2005-11-03 17:12:00 +0000 Wim Taymans + + check/states/sinks.c: Added some more checks. Specifically the case where NO_PREROLL elements are in the pipeline. + Original commit message from CVS: + * check/states/sinks.c: (GST_START_TEST), (gst_object_suite): + Added some more checks. Specifically the case where NO_PREROLL + elements are in the pipeline. + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_do_sync), + (gst_base_sink_get_position): + Post READY->PAUSED state change messages too. + Fix bug where VOID was posted as pending state... + * gst/gstbin.c: (gst_bin_recalc_state): + use _element_continue_state() to continue the state change. + * gst/gstelement.c: (gst_element_continue_state), + (gst_element_commit_state), (gst_element_set_state_func), + (gst_element_change_state), (gst_element_change_state_func): + Lots of state change cleanups, assign the STATE_RETURN in + a new continue_state() function that also propagates the + last return value from a state change to the app. + Update some debug statements with proper category. + +2005-11-03 14:22:44 +0000 Wim Taymans + + docs/: Small docs updates. + Original commit message from CVS: + * docs/design/part-events.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * docs/design/part-overview.txt: + * docs/design/part-seeking.txt: + * docs/design/part-states.txt: + * docs/design/part-trickmodes.txt: + * docs/manual/advanced-position.xml: + Small docs updates. + * gst/gstobject.h: + People think !! is ugly, this looks better. + * gst/gstpad.c: (gst_pad_set_blocked_async): + Remove !! since it's fixed elsewhere now. + +2005-11-03 13:52:59 +0000 Tim-Philipp Müller + + gst/: Add !! to _FLAG_IS_SET macros to make the result boolean. + Original commit message from CVS: + * gst/gstminiobject.h: + * gst/gstobject.h: + Add !! to _FLAG_IS_SET macros to make the result boolean. + +2005-11-03 12:48:30 +0000 Edward Hervey + + gst/gstpad.c: comparing a flag and a gboolean rarely returns coherent results... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_blocked_async): + comparing a flag and a gboolean rarely returns coherent results... + Added two characters (!!) to make that work correctly. + +2005-11-03 12:16:49 +0000 Tim-Philipp Müller + + gst/gstbus.c: Fix some typos. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_class_init): + Fix some typos. + * gst/gstqueue.c: (gst_queue_loop): + Don't assume a miniobject that isn't a buffer is an + event (it could be that there is a refcounting + problem somewhere and the pointer is stale and + refers to an already destroyed miniobject). + +2005-11-03 10:56:23 +0000 Julien Moutte + + gst/gstpad.c: Fix some typos. + Original commit message from CVS: + 2005-11-03 Julien MOUTTE + * gst/gstpad.c: (gst_pad_alloc_buffer): Fix some typos. + +2005-11-03 09:18:53 +0000 Tim-Philipp Müller + + docs/manual/advanced-position.xml: Update seek example and explanations to current 0.9 API. + Original commit message from CVS: + * docs/manual/advanced-position.xml: + Update seek example and explanations to current 0.9 API. + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_activate): + Remove FIXME comment now that the found caps + are unreffed. + +2005-11-03 00:39:54 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstregistryxml.c: + Add another GST_STR_NULL instance + Original commit message from CVS: + Add another GST_STR_NULL instance + +2005-11-02 19:04:20 +0000 Edward Hervey + + gst/gstpad.c: Follow-up to Wim's patch, solves deadlock for blocked and flushing pads + Original commit message from CVS: + * gst/gstpad.c: (handle_pad_block): + Follow-up to Wim's patch, solves deadlock for blocked and flushing pads + +2005-11-02 18:44:20 +0000 Wim Taymans + + gst/gstbin.c: Fix typo in docs. + Original commit message from CVS: + * gst/gstbin.c: + Fix typo in docs. + * gst/gstelement.c: (gst_element_commit_state): + Remove unused value. + * gst/gstiterator.c: + Mention that the returned element is reffed in the docs. + +2005-11-02 18:33:00 +0000 Wim Taymans + + gst/gstpad.c: Unlock blocked pads when they are flushed. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer), (handle_pad_block), + (gst_pad_push), (gst_pad_push_event): + Unlock blocked pads when they are flushed. + +2005-11-02 15:34:23 +0000 Thomas Vander Stichele + + doc updates + Original commit message from CVS: + * docs/README: + * docs/gst/gstreamer-sections.txt: + * gst/gstbin.c: + doc updates + * gst/gstregistry.c: (gst_registry_scan_path_level): + fix for a nasty little missed situation where an installed plug-in + which was in the cache did not get overridden by an uninstalled one + which was earlier in the plugin path because the newly created plugin + for the uninstalled one (not in the registry) didn't get its + ->registered set to TRUE + +2005-11-02 15:08:05 +0000 Tim-Philipp Müller + + gst/base/gstcollectpads.c: Guard public API with assertions. + Original commit message from CVS: + * gst/base/gstcollectpads.c: (gst_collectpads_set_function), + (gst_collectpads_add_pad), (gst_collectpads_remove_pad), + (gst_collectpads_is_active), (gst_collectpads_collect), + (gst_collectpads_collect_range), (gst_collectpads_start), + (gst_collectpads_stop), (gst_collectpads_peek), + (gst_collectpads_pop), (gst_collectpads_available), + (gst_collectpads_read), (gst_collectpads_flush): + Guard public API with assertions. + * gst/gstpad.c: + Fix docs for gst_pad_set_link_function(). + +2005-11-02 14:28:02 +0000 Johan Dahlin + + gst/elements/gsttypefindelement.c (gst_type_find_element_activate): Unref found_caps after we used it. + Original commit message from CVS: + * gst/elements/gsttypefindelement.c (gst_type_find_element_activate): + Unref found_caps after we used it. + +2005-11-02 12:20:54 +0000 Tim-Philipp Müller + + gst/base/gstcollectpads.c: Don't try to ref NULL. + Original commit message from CVS: + * gst/base/gstcollectpads.c: (gst_collectpads_peek): + Don't try to ref NULL. + +2005-11-02 09:31:02 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add more symbols + Original commit message from CVS: + add more symbols + +2005-11-02 09:27:33 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add more symbols + Original commit message from CVS: + add more symbols + +2005-11-02 09:24:58 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update generated config + Original commit message from CVS: + update generated config + +2005-11-02 09:24:03 +0000 Thomas Vander Stichele + + * ChangeLog: + * win32/common/config.h.in: + provide a GST_FUNCTION that just gives a string for now + Original commit message from CVS: + provide a GST_FUNCTION that just gives a string for now + +2005-11-02 08:56:00 +0000 Thomas Vander Stichele + + * ChangeLog: + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + update win32 copies + Original commit message from CVS: + update win32 copies + +2005-11-01 19:16:58 +0000 Thomas Vander Stichele + + * gst/gstbin.c: + more doc updates + Original commit message from CVS: + more doc updates + +2005-11-01 17:45:46 +0000 Luca Ognibene + + gst/gst.c: fix docs. popt is death, long live GOption. + Original commit message from CVS: + * gst/gst.c: + fix docs. popt is death, long live GOption. + +2005-10-31 11:44:32 +0000 Wim Taymans + + gst/gstbuffer.h: Small doc fix. + Original commit message from CVS: + * gst/gstbuffer.h: + Small doc fix. + +2005-10-31 09:52:13 +0000 Andy Wingo + + Boo! + Original commit message from CVS: + 2005-10-31 Andy Wingo + * Boo! + * gst/gstqueue.c (gst_queue_chain): Fix downstream leaky mode. + * gst/gstobject.c (gst_object_dispatch_properties_changed): No + need to serialize property notifications on GLib 2.8. GLib 2.6 has + the possibility of deadlocks here if code calling notify() or + set() has a lock that can be taken in another notify handler (ABBA + with class lock and e.g. python GIL state lock). + +2005-10-28 18:18:23 +0000 Julien Moutte + + gst/gstbus.c: Doc updates. + Original commit message from CVS: + 2005-10-28 Julien MOUTTE + * gst/gstbus.c: Doc updates. + +2005-10-28 18:14:24 +0000 Wim Taymans + + Doc updates. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * gst/gstiterator.c: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + Doc updates. + +2005-10-28 18:10:41 +0000 Edward Hervey + + docs/gst/: the GstURIType documentation page is private, it only defines GstURIType which should be defined in the Gs... + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + the GstURIType documentation page is private, it only defines GstURIType + which should be defined in the GstURIHandler page + +2005-10-28 17:35:43 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstutils.c: + Documentation updates. + Original commit message from CVS: + Documentation updates. + +2005-10-28 17:35:05 +0000 Wim Taymans + + Documented the clocks. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstclock.c: + * gst/gstclock.h: + Documented the clocks. + +2005-10-28 17:34:32 +0000 Thomas Vander Stichele + + * common: + * win32/common/config.h: + updated config + Original commit message from CVS: + updated config + +2005-10-28 17:20:45 +0000 Michael Smith + + * gst/gstbuffer.h: + Work around gtkdoc deficiencies, document a macro differently. + Original commit message from CVS: + Work around gtkdoc deficiencies, document a macro differently. + +2005-10-28 17:01:14 +0000 Michael Smith + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstutils.c: + Improve GstBuffer documentation. It's now 100% Spiffier. + Original commit message from CVS: + Improve GstBuffer documentation. It's now 100% Spiffier. + +2005-10-28 16:54:15 +0000 Thomas Vander Stichele + + * docs/README: + some style fixes + Original commit message from CVS: + some style fixes + +2005-10-28 16:46:58 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: move some macros to private sections + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + move some macros to private sections + * gst/gstminiobject.c: + * gst/gstminiobject.h: + add descriptions provided by ds and some more + * gst/gstpad.h: + mark macro as to be removed + +2005-10-28 16:21:29 +0000 Wim Taymans + + docs/design/part-TODO.txt: Add an item to TODO. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Add an item to TODO. + * gst/gstiterator.c: (gst_iterator_fold), + (gst_iterator_find_custom): + * gst/gstiterator.h: + Add iterator docs. + +2005-10-28 16:08:52 +0000 Thomas Vander Stichele + + * docs/README: + add style guide + Original commit message from CVS: + add style guide + +2005-10-28 10:45:33 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Don't leak class. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_class_init), + (gst_base_transform_init): + Don't leak class. + * gst/gstqueue.c: (gst_queue_handle_sink_event), (gst_queue_loop): + An EOS event marks the queue as completely filled. + +2005-10-27 20:59:00 +0000 Wim Taymans + + gst/base/gstbasesink.c: Some more debugging. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync), (gst_base_sink_get_position): + Some more debugging. + * gst/base/gstbasetransform.c: (gst_base_transform_finalize), + (gst_base_transform_init), (gst_base_transform_buffer_alloc), + (gst_base_transform_event), (gst_base_transform_getrange), + (gst_base_transform_chain): + * gst/base/gstbasetransform.h: + Fix debugging, + Protect transform and concurrent buffer alloc with a new lock. + Try not to break ABI/API. + +2005-10-27 19:37:25 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Move some stuff around and cleanup things. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_query), + (gst_base_src_default_newsegment), + (gst_base_src_configure_segment), (gst_base_src_do_seek), + (gst_base_src_send_event), (gst_base_src_event_handler), + (gst_base_src_pad_get_range), (gst_base_src_loop), + (gst_base_src_unlock), (gst_base_src_default_negotiate), + (gst_base_src_start), (gst_base_src_deactivate), + (gst_base_src_activate_push), (gst_base_src_change_state): + Move some stuff around and cleanup things. + +2005-10-27 15:48:56 +0000 Tim-Philipp Müller + + gst/base/gstbasesrc.c: Add missing break statements. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_query): + Add missing break statements. + +2005-10-27 13:47:33 +0000 Wim Taymans + + check/gst/gstbin.c: An extra refcount is taken in basesrc. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + An extra refcount is taken in basesrc. + * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query), + (gst_base_src_get_range), (gst_base_src_pad_get_range), + (gst_base_src_loop): + Small cleanups, check for flushing after being unlocked from the + LIVE_LOCK. take refcounts correctly (not yet everywhere). + Don't send out EOS when going to READY. + +2005-10-27 08:55:44 +0000 Wim Taymans + + gst/base/gstbasesink.c: Some more debug. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_get_position): + Some more debug. + * gst/gstbin.c: (message_check), (bin_replace_message), + (bin_remove_messages), (is_eos), (gst_bin_add_func), + (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), + (bin_query_duration_init), (bin_query_duration_fold), + (bin_query_duration_done), (bin_query_generic_fold), + (gst_bin_query): + * tools/gst-launch.c: (main): + Remove old option. + +2005-10-26 18:57:43 +0000 Stefan Kost + + fixing examples fixing docs typos changing log priority in error situations + Original commit message from CVS: + * examples/controller/audio-example.c: (main): + * examples/queue/queue.c: (event_loop): + * gst/base/gstbasetransform.h: + * gst/gstelement.c: (gst_element_send_event): + * gst/gstevent.h: + * gst/gstpad.c: (gst_pad_send_event): + fixing examples + fixing docs typos + changing log priority in error situations + +2005-10-26 10:11:25 +0000 Thomas Vander Stichele + + * scripts/cvs-update.sh: + make sure dirs get checked out + Original commit message from CVS: + make sure dirs get checked out + +2005-10-26 09:56:43 +0000 Thomas Vander Stichele + + * win32/MANIFEST: + fix dist + Original commit message from CVS: + fix dist + +2005-10-25 17:41:24 +0000 Wim Taymans + + gst/gstbin.c: Some doc and debug updates. + Original commit message from CVS: + * gst/gstbin.c: (message_check), (bin_replace_message), + (bin_remove_messages), (is_eos), (gst_bin_add_func), + (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), + (bin_query_duration_init), (bin_query_duration_fold), + (bin_query_duration_done), (bin_query_generic_fold), + (gst_bin_query): + Some doc and debug updates. + Cache previously requested query DURATION for speed. invalidate + cached duration if element posts a DURATION message. + +2005-10-25 15:39:36 +0000 Wim Taymans + + docs/design/part-TODO.txt: Update TODO. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Update TODO. + * gst/gstbin.c: (message_check), (bin_replace_message), + (bin_remove_messages), (is_eos), (gst_bin_add_func), + (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), + (bin_query_duration_init), (bin_query_duration_fold), + (bin_query_duration_done), (bin_query_generic_fold), + (gst_bin_query): + Handle SEGMENT_START/DONE messages correctly. + More evolved query algorithm that handles duration queries + correctly. + * gst/gstelement.c: (gst_element_send_event), (gst_element_query), + (gst_element_get_state_func), (gst_element_abort_state), + (gst_element_commit_state), (gst_element_lost_state): + Some more debugging. + * gst/gstmessage.h: + Added doc. + +2005-10-25 10:15:45 +0000 Wim Taymans + + gst/base/gstbasesink.c: Don't use invalid stream_time. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_get_position): + Don't use invalid stream_time. + * gst/gstevent.c: (gst_event_new_newsegment): + stream_time in newsegment cannot be undefined. + +2005-10-25 10:12:13 +0000 Wim Taymans + + * ChangeLog: + Forgot the changelog last time + Original commit message from CVS: + Forgot the changelog last time + +2005-10-24 15:41:48 +0000 Wim Taymans + + gst/gstbus.c: Doc fix. + Original commit message from CVS: + * gst/gstbus.c: + Doc fix. + * gst/gstqueue.c: (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_loop): + Fix potential deadlock when QUEUE_LOCK is taken before STREAM_LOCK. + +2005-10-24 11:56:03 +0000 Stefan Kost + + docs/libs/tmpl/: these are obsolete + Original commit message from CVS: + * docs/libs/tmpl/gstdparam.sgml: + * docs/libs/tmpl/gstdplinint.sgml: + * docs/libs/tmpl/gstdpman.sgml: + * docs/libs/tmpl/gstdpsmooth.sgml: + * docs/libs/tmpl/gstunitconvert.sgml: + these are obsolete + +2005-10-24 09:13:27 +0000 Michael Smith + + * gst/gstelement.h: + * gst/gstqueue.c: + * gst/gstutils.c: + * plugins/elements/gstqueue.c: + Fix some minor documentation typos + Original commit message from CVS: + Fix some minor documentation typos + +2005-10-23 23:04:38 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.9.4 === + +2005-10-23 22:30:17 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/random/release: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * win32/common/config.h: + time to release + Original commit message from CVS: + time to release + +2005-10-23 10:49:26 +0000 Thomas Vander Stichele + + * win32/MANIFEST: + add more files + Original commit message from CVS: + add more files + +2005-10-23 10:29:51 +0000 Tim-Philipp Müller + + gst/elements/gstfilesink.c: Use fseeko() and ftello() if available. When falling back on lseek() to get the current o... + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_file_sink_do_seek), + (gst_file_sink_get_current_offset): + Use fseeko() and ftello() if available. When falling back on + lseek() to get the current offset, fflush() first to make sure + everything is up-to-date and we get the right offset. + +2005-10-23 09:08:44 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/base/gstbasesink.c: + * gst/base/gstbasesrc.c: + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstqueue.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstqueue.c: + * po/POTFILES.in: + remove prematurely added error category and clean up the instances + Original commit message from CVS: + remove prematurely added error category and clean up the instances + +2005-10-21 17:53:31 +0000 Wim Taymans + + gst/base/gstbasesink.c: Simply set the right flag when going to playing, that's all we need to do instead of calling ... + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_get_position), (gst_base_sink_query), + (gst_base_sink_change_state): + Simply set the right flag when going to playing, that's all + we need to do instead of calling a function inside the object + lock (that could take the lock as well and deadlock) + +2005-10-21 16:18:54 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Don't warn, the peer element knows what to do best when the seek failed, it might try somethin... + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_do_seek), + (gst_base_src_loop): + Don't warn, the peer element knows what to do best when + the seek failed, it might try something else. + +2005-10-21 16:14:34 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Fix seeking. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_init), + (gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start): + Fix seeking. + +2005-10-21 15:13:08 +0000 Wim Taymans + + docs/design/part-segments.txt: More docs. + Original commit message from CVS: + * docs/design/part-segments.txt: + More docs. + * gst/elements/gstcapsfilter.c: (gst_capsfilter_prepare_buf): + Correctly set caps, even on the subbufer. + +2005-10-21 11:36:32 +0000 Wim Taymans + + And 2% more doc coverage. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstpad.h: + * gst/gstparse.h: + * gst/gsttask.c: (gst_task_finalize), (gst_task_func): + * gst/gsttask.h: + * gst/gstutils.c: + * gst/gstutils.h: + And 2% more doc coverage. + +2005-10-21 09:24:28 +0000 Andy Wingo + + gst/base/gstbasesrc.c (gst_base_src_query): Clean up percent position reporting. + Original commit message from CVS: + 2005-10-21 Andy Wingo + * gst/base/gstbasesrc.c (gst_base_src_query): Clean up percent + position reporting. + +2005-10-20 21:08:47 +0000 Wim Taymans + + gst/: More docs. + Original commit message from CVS: + * gst/gsterror.c: (gst_error_get_message): + * gst/gstparse.h: + * gst/gstquery.h: + * gst/gststructure.c: + * gst/gsttrace.c: + * gst/gstutils.c: + More docs. + +2005-10-20 20:46:17 +0000 Wim Taymans + + gst/: Another 1% more coverage. + Original commit message from CVS: + * gst/gstbuffer.h: + * gst/gstpad.c: + * gst/gstparse.c: + Another 1% more coverage. + +2005-10-20 20:25:55 +0000 Wim Taymans + + Yay! 1% more docs coverage. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_abort_state), (gst_element_commit_state), + (gst_element_lost_state): + * gst/gstevent.h: + * gst/gstquery.c: (gst_query_set_position), + (gst_query_parse_position), (gst_query_set_duration), + (gst_query_parse_duration), (gst_query_new_convert): + * gst/gstutils.c: + Yay! 1% more docs coverage. + +2005-10-20 19:47:07 +0000 Wim Taymans + + gst/: Docs and consistency fixes. + Original commit message from CVS: + * gst/gstpad.h: + * gst/gstquery.c: (gst_query_set_position), + (gst_query_parse_position), (gst_query_set_duration), + (gst_query_parse_duration), (gst_query_new_convert): + * gst/gstquery.h: + * gst/gstutils.c: (gst_element_query_convert): + * gst/gstutils.h: + Docs and consistency fixes. + +2005-10-20 19:30:57 +0000 Wim Taymans + + gst/gsttask.*: More docs. + Original commit message from CVS: + * gst/gsttask.c: + * gst/gsttask.h: + More docs. + +2005-10-20 17:22:40 +0000 Wim Taymans + + gst/gstbin.c: Reworked the message handling a bit, cache the messages instead of only the senders. alows us to do mor... + Original commit message from CVS: + * gst/gstbin.c: (message_check), (bin_replace_message), + (bin_remove_messages), (is_eos), (gst_bin_add_func), + (update_degree), (gst_bin_sort_iterator_next), + (gst_bin_change_state_func), (gst_bin_dispose), (bin_bus_handler): + Reworked the message handling a bit, cache the messages instead of + only the senders. alows us to do more in the future. + +2005-10-20 17:18:12 +0000 Wim Taymans + + docs/design/part-TODO.txt: Update TODO + Original commit message from CVS: + * docs/design/part-TODO.txt: + Update TODO + * gst/base/gstbasesink.c: (gst_base_sink_get_position), + (gst_base_sink_query): + Don't use clock time to report position when in EOS. + +2005-10-20 13:10:13 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Fix interface output with gst-inspect -a; don't print newlines after double/float properties. + Original commit message from CVS: + * tools/gst-inspect.c: (print_interfaces), + (print_element_properties_info), (print_element_info): + Fix interface output with gst-inspect -a; don't print + newlines after double/float properties. + +2005-10-20 11:48:53 +0000 Wim Taymans + + gst/base/gstbasesink.c: Speed up current position calculation. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_get_position), + (gst_base_sink_query): + Speed up current position calculation. + * gst/base/gstbasesrc.c: (gst_base_src_query), + (gst_base_src_default_newsegment): + Correctly set stream position in newsegment. + * gst/gstbin.c: (gst_bin_add_func), (add_to_queue), + (update_degree), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free): + * gst/gstmessage.c: (gst_message_new_custom): + Clean up debugging info + * gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain), + (gst_queue_loop), (gst_queue_handle_src_query): + Pause task faster. + +2005-10-19 17:06:56 +0000 Wim Taymans + + gst/base/gstbasesink.c: Fix query handling again. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_query), (do_playing): + Fix query handling again. + +2005-10-19 15:50:10 +0000 Wim Taymans + + gst/: API change fix. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_query), (do_playing): + * gst/base/gstbasesrc.c: (gst_base_src_query): + * gst/elements/gstfilesink.c: (gst_file_sink_query): + * gst/elements/gsttypefindelement.c: + (gst_type_find_handle_src_query), (find_element_get_length), + (gst_type_find_element_activate): + API change fix. + * gst/gstquery.c: (gst_query_new_position), + (gst_query_set_position), (gst_query_parse_position), + (gst_query_new_duration), (gst_query_set_duration), + (gst_query_parse_duration), (gst_query_set_segment), + (gst_query_parse_segment): + * gst/gstquery.h: + Bundling query position/duration is not a good idea since duration + does not change much and we don't want to recalculate it for every + position query, so they are separated again.. + Base value in segment query is not needed. + * gst/gstqueue.c: (gst_queue_handle_src_query): + * gst/gstutils.c: (gst_element_query_position), + (gst_element_query_duration), (gst_pad_query_position), + (gst_pad_query_duration): + * gst/gstutils.h: + Updates for query API change. + Added some docs here and there. + +2005-10-19 11:43:42 +0000 Thomas Vander Stichele + + check/: wait on thread to die so we can check refcount correctly + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstghostpad.c: (GST_START_TEST): + * check/pipelines/cleanup.c: (GST_START_TEST): + wait on thread to die so we can check refcount correctly + +2005-10-19 11:43:18 +0000 Christian Schaller + + * gstreamer.spec.in: + update tools package naming + Original commit message from CVS: + update tools package naming + +2005-10-19 11:42:39 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + log an if branch + Original commit message from CVS: + log an if branch + +2005-10-18 17:30:50 +0000 Wim Taymans + + check/pipelines/stress.c: Make check a little more time consuming. + Original commit message from CVS: + * check/pipelines/stress.c: (GST_START_TEST): + Make check a little more time consuming. + +2005-10-18 17:06:29 +0000 Wim Taymans + + check/: Small state change torture test. + Original commit message from CVS: + * check/Makefile.am: + * check/pipelines/stress.c: (GST_START_TEST), + (simple_launch_lines_suite), (main): + Small state change torture test. + * docs/design/part-states.txt: + * gst/base/gstbasesink.c: (gst_base_sink_commit_state), + (gst_base_sink_handle_object), (gst_base_sink_event), (do_playing), + (gst_base_sink_change_state): + Never take state lock from streaming thread, clean up ugly + hacks. Unfortunatly core does not yet support nice ways to + async commit state. + * gst/gstbin.c: (gst_bin_remove_func), (gst_bin_recalc_state), + (bin_bus_handler): + Start state recalc if a STATE_DIRTY message is posted, but only + on the toplevel bin. + * gst/gstelement.c: (gst_element_sync_state_with_parent), + (gst_element_get_state_func), (gst_element_abort_state), + (gst_element_commit_state), (gst_element_lost_state), + (gst_element_set_state_func), (gst_element_change_state): + * gst/gstelement.h: + State variables are now protected with the LOCK, the state + lock is only used to serialize _set_state(). + +2005-10-18 16:25:38 +0000 Wim Taymans + + Seriously, this is better than a previous commit as we only need to notify the fact that an element changed state in ... + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstmessage.c: (GST_START_TEST): + * check/gst/gstpipeline.c: (GST_START_TEST), (message_received): + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_recalc_func), + (bin_bus_handler): + * gst/gstelement.c: (gst_element_abort_state), + (gst_element_commit_state), (gst_element_lost_state): + * gst/gstmessage.c: (gst_message_new_state_changed), + (gst_message_new_state_dirty), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_new_duration), + (gst_message_parse_state_changed), + (gst_message_parse_segment_start), + (gst_message_parse_segment_done), (gst_message_parse_duration): + * gst/gstmessage.h: + * tools/gst-launch.c: (event_loop): + Seriously, this is better than a previous commit as we only need + to notify the fact that an element changed state in a streaming + thread, marking the state of the parents dirty, hence the + STATE_DIRTY message instead of abusing a boolean in a STATE_CHANGE + message. + +2005-10-18 15:15:11 +0000 Wim Taymans + + gst/: Cleanups, prepare for state change fixes. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_get_state_func), + (gst_bin_recalc_func): + * gst/gstelement.c: (gst_element_set_clock), + (gst_element_abort_state), (gst_element_lost_state): + Cleanups, prepare for state change fixes. + +2005-10-18 14:29:21 +0000 Wim Taymans + + gst/: Pending ABI changes. + Original commit message from CVS: + * gst/gstbin.h: + * gst/gstelement.c: (gst_element_class_init), + (gst_element_set_state), (gst_element_set_state_func): + * gst/gstelement.h: + Pending ABI changes. + GThreadPool in GstBinClass to monitor async state changes. + state_cookie in GstElement to detect concurrent gst/set state. + set_state is now virtual too in case a very complicated element + has to be constructed. + +2005-10-18 13:19:16 +0000 Wim Taymans + + Make messages future proof. state-change gets a flag if it was a message comming from the streaming thread. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstmessage.c: (GST_START_TEST): + * check/gst/gstpipeline.c: (GST_START_TEST), (message_received): + * gst/gstbin.c: (bin_bus_handler): + * gst/gstelement.c: (gst_element_commit_state), + (gst_element_lost_state): + * gst/gstmessage.c: (gst_message_new_state_changed), + (gst_message_new_segment_start), (gst_message_new_segment_done), + (gst_message_new_duration), (gst_message_parse_state_changed), + (gst_message_parse_segment_start), + (gst_message_parse_segment_done), (gst_message_parse_duration): + * gst/gstmessage.h: + * tools/gst-launch.c: (event_loop): + Make messages future proof. + state-change gets a flag if it was a message comming from the + streaming thread. + segment-start/stop can also be specified in other formats. + A message to notify an app that a pipeline changed playback + duration. + Also fix a GstMessage leak in -launch + +2005-10-18 10:32:48 +0000 Andy Wingo + + gst/gstelement.c (gst_element_dispose): More helpful message. + Original commit message from CVS: + 2005-10-18 Andy Wingo + * gst/gstelement.c (gst_element_dispose): More helpful message. + +2005-10-18 08:20:25 +0000 Thomas Vander Stichele + + * common: + * configure.ac: + remove info messages + Original commit message from CVS: + remove info messages + +2005-10-18 07:13:25 +0000 Thomas Vander Stichele + + gst/gstregistry.c: unref a plug-in we get that was already initialized + Original commit message from CVS: + * gst/gstregistry.c: (gst_registry_scan_path_level): + unref a plug-in we get that was already initialized + +2005-10-17 20:16:55 +0000 Stefan Kost + + add new api entries hide internal macro + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + * gst/gstelement.h: + add new api entries + hide internal macro + +2005-10-17 18:09:32 +0000 Andy Wingo + + gst/base/gstcollectpads.c (gst_collectpads_chain): Slight cleanup. + Original commit message from CVS: + 2005-10-17 Andy Wingo + * gst/base/gstcollectpads.c (gst_collectpads_chain): Slight + cleanup. + * gst/Makefile.am (gstenumtypes.c): Threadsafe now. + * gst/gstevent.c (gst_event_new, gst_event_finalize): LOG. + * gst/gstelement.c (gst_element_get_state_func): s/INFO/DEBUG/. + (gst_element_get_state_func): Better debug message. + (gst_element_commit_state): s/INFO/DEBUG/. + (gst_element_lost_state, gst_element_change_state): + * gst/gstmessage.c (gst_message_init): s/INFO/LOG/. + (gst_message_new_custom): s/INFO/LOG/. + +2005-10-17 17:46:37 +0000 Michael Smith + + * ChangeLog: + * gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.c: + Check validity of end time based on end time variable, not start time. + Original commit message from CVS: + Check validity of end time based on end time variable, not start time. + +2005-10-17 17:05:38 +0000 Stefan Kost + + merge controller testsuites fix broken tests remove mem-chunk from docs + Original commit message from CVS: + * check/gst-libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstinterpolation.c: + * testsuite/controller/.cvsignore: + * testsuite/controller/Makefile.am: + * testsuite/controller/interpolator.c: + merge controller testsuites + fix broken tests + remove mem-chunk from docs + +2005-10-17 14:42:22 +0000 Thomas Vander Stichele + + gst/: out. get out. you're fired. to the Attic ! + Original commit message from CVS: + * gst/gstmemchunk.c: + * gst/gstmemchunk.h: + * gst/gsttrashstack.c: + * gst/gsttrashstack.h: + out. get out. you're fired. to the Attic ! + +2005-10-17 14:37:06 +0000 Thomas Vander Stichele + + gst/gstcaps.c: fix signedness issues in a (hopefully) correct way + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_intersect): + fix signedness issues in a (hopefully) correct way + * gst/gstelement.c: (gst_element_pads_activate): + some debugging + * gst/gstobject.c: (gst_object_set_parent): + some debugging + +2005-10-17 10:37:13 +0000 Michael Smith + + * gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.c: + Fix a doc typo. + Original commit message from CVS: + Fix a doc typo. + +2005-10-17 09:28:35 +0000 Julien Moutte + + gst/gstvalue.h: Fix prototypes. + Original commit message from CVS: + 2005-10-17 Julien MOUTTE + * gst/gstvalue.h: Fix prototypes. + +2005-10-16 14:32:57 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gst.h: + * gst/gstversion.h.in: + * win32/common/libgstreamer.def: + add gst_version_string () + Original commit message from CVS: + add gst_version_string () + +2005-10-16 13:55:41 +0000 Thomas Vander Stichele + + * configure.ac: + * win32/common/config.h: + comment; update win32 config.h + Original commit message from CVS: + comment; update win32 config.h + +2005-10-16 12:37:14 +0000 Thomas Vander Stichele + + * scripts/cvs-update.sh: + Dear Andy: here's a script to update stuff from CVS + Original commit message from CVS: + Dear Andy: + here's a script to update stuff from CVS + Love, + Thomas + +2005-10-16 12:28:20 +0000 Thomas Vander Stichele + + configure.ac: clean up further + Original commit message from CVS: + * configure.ac: + clean up further + * gst/gst.c: (init_post): + * win32/common/config.h.in: + it's PLUGINDIR now + * gst/gstcaps.c: (gst_caps_intersect): + use gint64, the range could be bigger than a guint + +2005-10-16 11:48:09 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * gst/gstclock.h: + GStreamer consultants will make a lot of money in 2038 + Original commit message from CVS: + GStreamer consultants will make a lot of money in 2038 + +2005-10-16 10:58:41 +0000 Thomas Vander Stichele + + gst/gstcaps.c: Fix guint j diving under 0 + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_intersect): + Fix guint j diving under 0 + +2005-10-16 10:38:02 +0000 Thomas Vander Stichele + + check for process.h, declares getpid() on Windows + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + * win32/common/config.h.in: + check for process.h, declares getpid() on Windows + * gst/gstinfo.c: + include process.h if we have it + * gst/gstmemchunk.c: (populate), (gst_mem_chunk_new): + * gst/gstmemchunk.h: + fix signedness issues + * win32/common/libgstreamer.def: + fix get_type's + +2005-10-16 10:22:29 +0000 Thomas Vander Stichele + + * gst/gstcaps.c: + fix signedness + Original commit message from CVS: + fix signedness + +2005-10-16 10:18:36 +0000 Thomas Vander Stichele + + * win32/common/config.h: + * win32/common/config.h.in: + fix GST_VERSION + Original commit message from CVS: + fix GST_VERSION + +2005-10-16 10:15:24 +0000 Thomas Vander Stichele + + * win32/common/config.h: + * win32/common/config.h.in: + fix inline + Original commit message from CVS: + fix inline + +2005-10-16 10:12:34 +0000 Thomas Vander Stichele + + * win32/common/config.h: + * win32/common/config.h.in: + define PACKAGE + Original commit message from CVS: + define PACKAGE + +2005-10-16 10:10:25 +0000 Thomas Vander Stichele + + * win32/common/config.h: + * win32/common/config.h.in: + update available headers + Original commit message from CVS: + update available headers + +2005-10-16 09:56:33 +0000 Julien Moutte + + gst/gstcaps.c: Fix a bad bug with a simple fix. Because of unsigned ints, caps intersection was going nuts and trying... + Original commit message from CVS: + 2005-10-16 Julien MOUTTE + * gst/gstcaps.c: (gst_caps_intersect): Fix a bad bug with a + simple + fix. Because of unsigned ints, caps intersection was going nuts + and + trying to access structures with G_MAXUINT index. That fixes + videotestsrc ! ffmpegcolorspace ! fakesink + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked): logs + consistency. + +2005-10-16 09:55:24 +0000 Thomas Vander Stichele + + * win32/common/config.h: + update + Original commit message from CVS: + update + +2005-10-16 09:54:22 +0000 Thomas Vander Stichele + + * win32/common/config.h.in: + typo + Original commit message from CVS: + typo + +2005-10-16 09:51:25 +0000 Thomas Vander Stichele + + * win32/common/config.h: + * win32/common/config.h.in: + updates for 2in32 + Original commit message from CVS: + updates for 2in32 + +2005-10-16 09:44:04 +0000 Thomas Vander Stichele + + * check/gst-libs/controller.c: + * check/gst/gstplugin.c: + * configure.ac: + * tests/check/gst/gstplugin.c: + * tests/check/libs/controller.c: + more define fixes + Original commit message from CVS: + more define fixes + +2005-10-16 09:20:52 +0000 Thomas Vander Stichele + + configure.ac: use the gettext macro + Original commit message from CVS: + 2005-10-16 Thomas Vander Stichele + * configure.ac: + use the gettext macro + * gst/elements/gstelements.c: + * gst/gst.c: + * gst/indexers/gstindexers.c: + update for GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN + * win32/common/config.h: + updated config.h + * win32/common/config.h.in: + add the template to generate config.h + * win32/common/gstenumtypes.c: + * win32/common/gstversion.h: + updated copies + +2005-10-16 09:11:57 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol.pc.in: + remove more PKG_CFLAGS + Original commit message from CVS: + remove more PKG_CFLAGS + +2005-10-16 09:10:17 +0000 Thomas Vander Stichele + + gst/: add the nano + Original commit message from CVS: + * gst/gst.c: (gst_version): + * gst/gstversion.h.in: + add the nano + +2005-10-16 08:59:34 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + remove GST_PKG_CFLAGS + Original commit message from CVS: + remove GST_PKG_CFLAGS + +2005-10-15 22:24:20 +0000 Tim-Philipp Müller + + gst/gstevent.h: Oops, add missing closing bracket. + Original commit message from CVS: + * gst/gstevent.h: + Oops, add missing closing bracket. + +2005-10-15 21:41:20 +0000 Thomas Vander Stichele + + configure.ac: use common m4's for argument checking + Original commit message from CVS: + * configure.ac: + use common m4's for argument checking + +2005-10-15 20:33:09 +0000 Tim-Philipp Müller + + Add GST_EVENT_TYPE_NAME() macro. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.h: + Add GST_EVENT_TYPE_NAME() macro. + +2005-10-15 20:00:30 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + update defs + Original commit message from CVS: + update defs + +2005-10-15 19:57:03 +0000 Thomas Vander Stichele + + gst/: privatize more symbols + Original commit message from CVS: + * gst/gstinfo.c: + * gst/gstpluginfeature.c: + * gst/gsttask.c: + privatize more symbols + +2005-10-15 18:22:31 +0000 Thomas Vander Stichele + + configure.ac: add srcdir, builddir includes to GST_ALL_CFLAGS, since everything that uses GStreamer API should have t... + Original commit message from CVS: + * configure.ac: + add srcdir, builddir includes to GST_ALL_CFLAGS, since + everything that uses GStreamer API should have the includes + +2005-10-15 17:59:07 +0000 Thomas Vander Stichele + + give each value a _get_type, removes the DATA exports + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstvalue.c: (gst_date_get_type), (_gst_value_initialize): + * gst/gstvalue.h: + give each value a _get_type, removes the DATA exports + +2005-10-15 17:22:34 +0000 Thomas Vander Stichele + + * gst/base/Makefile.am: + * libs/gst/base/Makefile.am: + fix link flags + Original commit message from CVS: + fix link flags + +2005-10-15 16:39:57 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + update defs file + Original commit message from CVS: + update defs file + +2005-10-15 16:37:22 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + update defs + Original commit message from CVS: + update defs + +2005-10-15 16:33:09 +0000 Thomas Vander Stichele + + gst/gst.*: remove _gst_registry_auto_load, not used anymore + Original commit message from CVS: + * gst/gst.c: + * gst/gst.h: + remove _gst_registry_auto_load, not used anymore + * gst/gstbin.c: (gst_bin_get_type): + * gst/gstbin.h: + * gst/gstelement.c: (gst_element_get_type): + * gst/gstelement.h: + * gst/gstobject.c: (gst_object_get_type): + * gst/gstobject.h: + * gst/gstpad.c: (gst_pad_get_type): + * gst/gstpad.h: + make _get_type functions similar, fixes data export from library + +2005-10-15 16:16:04 +0000 Thomas Vander Stichele + + * gst/check/gstcheck.c: + * gst/gst.c: + * gst/gstbuffer.c: + * gst/gstcaps.c: + * gst/gstelementfactory.c: + * gst/gstpadtemplate.c: + * gst/gstplugin.c: + * gst/gsttypefindfactory.c: + * libs/gst/check/gstcheck.c: + I'm too lazy to comment this + Original commit message from CVS: + gtk-doc insists on inserting at every empty line, sigh + +2005-10-15 16:01:57 +0000 Thomas Vander Stichele + + * gst/gst.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstconfig.h.in: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gsterror.c: + * gst/gstevent.c: + * gst/gstfilter.c: + * gst/gstformat.c: + * gst/gstghostpad.c: + * gst/gstindex.c: + * gst/gstindexfactory.c: + * gst/gstinfo.c: + * gst/gstinterface.c: + * gst/gstiterator.c: + * gst/gstmemchunk.c: + * gst/gstmessage.c: + * gst/gstobject.c: + * gst/gstpad.c: + * gst/gstpadtemplate.c: + * gst/gstparse.c: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstquery.c: + * gst/gstqueue.c: + * gst/gstregistry.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttrace.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * gst/gsturitype.c: + * gst/gstutils.c: + * gst/gstxml.c: + * plugins/elements/gstqueue.c: + various style fixes + Original commit message from CVS: + various style fixes + +2005-10-15 15:53:59 +0000 Thomas Vander Stichele + + * check/gst/gstbin.c: + * check/gst/gstcaps.c: + * check/gst/gstvalue.c: + * examples/appreader/appreader.c: + * examples/controller/audio-example.c: + * examples/cutter/cutter.c: + * examples/cutter/cutter.h: + * examples/mixer/mixer.c: + * examples/mixer/mixer.h: + * examples/retag/retag.c: + * examples/retag/transcode.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstvalue.c: + * tests/old/examples/appreader/appreader.c: + * tests/old/examples/controller/audio-example.c: + * tests/old/examples/cutter/cutter.c: + * tests/old/examples/cutter/cutter.h: + * tests/old/examples/mixer/mixer.c: + * tests/old/examples/mixer/mixer.h: + * tests/old/examples/retag/retag.c: + * tests/old/examples/retag/transcode.c: + * win32/common/gstconfig.h: + * win32/common/gstversion.h: + * win32/dirent.c: + * win32/gstconfig.h: + * win32/gstversion.h: + * win32/gtchar.h: + * win32/mman.h: + * win32/vs7/mman.h: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2005-10-15 15:53:14 +0000 Thomas Vander Stichele + + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/bytestream/.gitignore: + * tests/old/testsuite/bytestream/Makefile.am: + * tests/old/testsuite/bytestream/filepadsink.c: + * tests/old/testsuite/bytestream/gstbstest.c: + * tests/old/testsuite/bytestream/test1.c: + * tests/old/testsuite/bytestream/testfile1: + * tests/old/testsuite/caps/normalisation.c: + * tests/old/testsuite/caps/random.c: + * tests/old/testsuite/cleanup/.gitignore: + * tests/old/testsuite/cleanup/Makefile.am: + * tests/old/testsuite/cleanup/cleanup1.c: + * tests/old/testsuite/cleanup/cleanup2.c: + * tests/old/testsuite/cleanup/cleanup3.c: + * tests/old/testsuite/cleanup/cleanup4.c: + * tests/old/testsuite/cleanup/cleanup5.c: + * tests/old/testsuite/controller/interpolator.c: + * tests/old/testsuite/debug/printf_extension.c: + * tests/old/testsuite/elements/tee.c: + * tests/old/testsuite/negotiation/.gitignore: + * tests/old/testsuite/negotiation/Makefile.am: + * tests/old/testsuite/negotiation/pad_link.c: + * tests/old/testsuite/pad/Makefile.am: + * tests/old/testsuite/pad/chainnopull.c: + * tests/old/testsuite/pad/getnopush.c: + * tests/old/testsuite/pad/link.c: + * tests/old/testsuite/refcounting/sched.c: + * tests/old/testsuite/registry/Makefile.am: + * tests/old/testsuite/registry/gst-print-formats.c: + * tests/old/testsuite/schedulers/.gitignore: + * tests/old/testsuite/schedulers/142183-2.c: + * tests/old/testsuite/schedulers/142183.c: + * tests/old/testsuite/schedulers/143777-2.c: + * tests/old/testsuite/schedulers/143777.c: + * tests/old/testsuite/schedulers/147713.c: + * tests/old/testsuite/schedulers/147819.c: + * tests/old/testsuite/schedulers/147894-2.c: + * tests/old/testsuite/schedulers/147894.c: + * tests/old/testsuite/schedulers/Makefile.am: + * tests/old/testsuite/schedulers/group_link.c: + * tests/old/testsuite/schedulers/queue_link.c: + * tests/old/testsuite/schedulers/relink.c: + * tests/old/testsuite/schedulers/unlink.c: + * tests/old/testsuite/schedulers/unref.c: + * tests/old/testsuite/schedulers/useless_iteration.c: + * tests/old/testsuite/states/bin.c: + * testsuite/Makefile.am: + * testsuite/bytestream/.gitignore: + * testsuite/bytestream/Makefile.am: + * testsuite/bytestream/filepadsink.c: + * testsuite/bytestream/gstbstest.c: + * testsuite/bytestream/test1.c: + * testsuite/bytestream/testfile1: + * testsuite/caps/normalisation.c: + * testsuite/caps/random.c: + * testsuite/cleanup/.gitignore: + * testsuite/cleanup/Makefile.am: + * testsuite/cleanup/cleanup1.c: + * testsuite/cleanup/cleanup2.c: + * testsuite/cleanup/cleanup3.c: + * testsuite/cleanup/cleanup4.c: + * testsuite/cleanup/cleanup5.c: + * testsuite/controller/interpolator.c: + * testsuite/debug/printf_extension.c: + * testsuite/elements/tee.c: + * testsuite/negotiation/.gitignore: + * testsuite/negotiation/Makefile.am: + * testsuite/negotiation/pad_link.c: + * testsuite/pad/Makefile.am: + * testsuite/pad/chainnopull.c: + * testsuite/pad/getnopush.c: + * testsuite/pad/link.c: + * testsuite/refcounting/sched.c: + * testsuite/registry/Makefile.am: + * testsuite/registry/gst-print-formats.c: + * testsuite/schedulers/.gitignore: + * testsuite/schedulers/142183-2.c: + * testsuite/schedulers/142183.c: + * testsuite/schedulers/143777-2.c: + * testsuite/schedulers/143777.c: + * testsuite/schedulers/147713.c: + * testsuite/schedulers/147819.c: + * testsuite/schedulers/147894-2.c: + * testsuite/schedulers/147894.c: + * testsuite/schedulers/Makefile.am: + * testsuite/schedulers/group_link.c: + * testsuite/schedulers/queue_link.c: + * testsuite/schedulers/relink.c: + * testsuite/schedulers/unlink.c: + * testsuite/schedulers/unref.c: + * testsuite/schedulers/useless_iteration.c: + * testsuite/states/bin.c: + remove obsolete tests whitespace fixes + Original commit message from CVS: + remove obsolete tests + whitespace fixes + +2005-10-15 15:52:08 +0000 Thomas Vander Stichele + + configure.ac: correctly make conditionals + Original commit message from CVS: + * configure.ac: + correctly make conditionals + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + fix typo causing fdsrc not to build + +2005-10-15 15:30:24 +0000 Thomas Vander Stichele + + * gst/base/gstadapter.c: + * gst/base/gstbasesink.c: + * gst/base/gstbasetransform.c: + * gst/base/gstbasetransform.h: + * gst/base/gstcollectpads.c: + * gst/base/gstcollectpads.h: + * gst/base/gstpushsrc.h: + * gst/base/gsttypefindhelper.c: + * gst/base/gsttypefindhelper.h: + * gst/elements/gstbufferstore.c: + * gst/elements/gstcapsfilter.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfdsink.c: + * gst/elements/gstfdsink.h: + * gst/elements/gstfdsrc.c: + * gst/elements/gstfdsrc.h: + * gst/elements/gstfilesrc.c: + * gst/elements/gstidentity.c: + * gst/elements/gstidentity.h: + * gst/elements/gsttee.c: + * gst/elements/gsttee.h: + * gst/elements/gsttypefindelement.c: + * gst/elements/gsttypefindelement.h: + * gst/glib-compat.c: + * gst/gst.c: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstbus.c: + * gst/gstbus.h: + * gst/gstcaps.c: + * gst/gstchildproxy.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstghostpad.c: + * gst/gstindex.c: + * gst/gstindex.h: + * gst/gstindexfactory.c: + * gst/gstindexfactory.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstinterface.c: + * gst/gstiterator.c: + * gst/gstmacros.h: + * gst/gstmemchunk.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpadtemplate.c: + * gst/gstpadtemplate.h: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstqueue.c: + * gst/gstqueue.h: + * gst/gstregistry.h: + * gst/gstregistryxml.c: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstsystemclock.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gsttrace.c: + * gst/gsttrace.h: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.c: + * gst/gsttypefindfactory.h: + * gst/gsturi.c: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * gst/gstvalue.h: + * gst/indexers/gstfileindex.c: + * gst/indexers/gstmemindex.c: + * gst/parse/types.h: + * libs/gst/base/gstadapter.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstbasetransform.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/base/gstpushsrc.h: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * plugins/elements/gstbufferstore.c: + * plugins/elements/gstcapsfilter.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsink.h: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfdsrc.h: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + * plugins/indexers/gstfileindex.c: + * plugins/indexers/gstmemindex.c: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2005-10-15 15:01:39 +0000 Thomas Vander Stichele + + configure.ac: check for some headers + Original commit message from CVS: + * configure.ac: + check for some headers + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + don't compile fdsrc without sys/socket.h + * gst/indexers/Makefile.am: + * gst/indexers/gstindexers.c: (plugin_init): + don't compile fileindex without mmap + +2005-10-15 13:58:18 +0000 Thomas Vander Stichele + + configure.ac: reorganize clean up document more remove cruft + Original commit message from CVS: + * configure.ac: + reorganize + clean up + document more + remove cruft + * check/Makefile.am: + * docs/gst/Makefile.am: + * examples/helloworld/Makefile.am: + * gst/Makefile.am: + * gst/base/Makefile.am: + * gst/check/Makefile.am: + * gst/elements/Makefile.am: + * gst/indexers/Makefile.am: + * gst/parse/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * examples/helloworld/helloworld.c: (event_loop): + compile fixes, though it's not being compiled currently + +2005-10-15 13:24:54 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-base-uninstalled.pc.in: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + clean up pc files + Original commit message from CVS: + clean up pc files + +2005-10-15 12:03:32 +0000 Thomas Vander Stichele + + * libs/gst/getbits/.gitignore: + remove dir + Original commit message from CVS: + remove dir + +2005-10-15 10:34:17 +0000 Thomas Vander Stichele + + * common: + * gst/schedulers/.gitignore: + remove directory + Original commit message from CVS: + remove directory + +2005-10-15 00:22:02 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + * gst/gstplugin.h: + * gst/gststructure.c: + * gst/gsturi.c: + signedness/type fixes + Original commit message from CVS: + signedness/type fixes + +2005-10-15 00:20:45 +0000 Thomas Vander Stichele + + * gst/gstvalue.c: + signedness/type fixes + Original commit message from CVS: + signedness/type fixes + +2005-10-15 00:15:43 +0000 Thomas Vander Stichele + + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + * gst/gstpad.c: + signedness fixes + Original commit message from CVS: + signedness fixes + +2005-10-15 00:12:22 +0000 Thomas Vander Stichele + + * gst/gstcaps.c: + * gst/gstcaps.h: + signedness fixes + Original commit message from CVS: + signedness fixes + +2005-10-14 17:01:56 +0000 Tim-Philipp Müller + + check/gst/gsttag.c: Add some simple tests for the new taglist date API. + Original commit message from CVS: + * check/gst/gsttag.c: (test_date_tags), (gst_tag_suite): + Add some simple tests for the new taglist date API. + +2005-10-14 14:10:24 +0000 Tim-Philipp Müller + + gst/elements/: Beautify 'last-message' output: print 'none' for buffer timestamps and durations if none is set; impro... + Original commit message from CVS: + * gst/elements/gstfakesink.c: (gst_fake_sink_render): + * gst/elements/gstfakesrc.c: (gst_fake_src_create): + Beautify 'last-message' output: print 'none' for buffer timestamps + and durations if none is set; improve alignment with next messages. + +2005-10-14 11:09:29 +0000 Tim-Philipp Müller + + Add new API to check plugin feature version requirements. + Original commit message from CVS: + * gst/gstpluginfeature.c: (gst_plugin_feature_check_version): + * gst/gstpluginfeature.h: + * gst/gstregistry.c: (gst_default_registry_check_feature_version): + * gst/gstregistry.h: + * docs/gst/gstreamer-sections.txt: + Add new API to check plugin feature version requirements. + * check/gst/gstplugin.c: (test_version_checks), (gst_plugin_suite): + Some basic tests for the above. + +2005-10-13 21:27:57 +0000 Thomas Vander Stichele + + gst/gststructure.c: guard against NULL printf - happens when for example a message structure with GstClock gets seria... + Original commit message from CVS: + 2005-10-13 Thomas Vander Stichele + * gst/gststructure.c: (gst_structure_to_string): + guard against NULL printf - happens when for example + a message structure with GstClock gets serialized + +2005-10-13 18:33:27 +0000 Tim-Philipp Müller + + gst/base/gstcollectpads.c: Fix presumable copy'n'pasto. + Original commit message from CVS: + * gst/base/gstcollectpads.c: (gst_collectpads_event): + Fix presumable copy'n'pasto. + +2005-10-13 17:51:51 +0000 Thomas Vander Stichele + + * gst/elements/gstelements.c: + * gst/elements/gstfilesrc.c: + * plugins/elements/gstelements.c: + * plugins/elements/gstfilesrc.c: + add correct header for WIN32 + Original commit message from CVS: + add correct header for WIN32 + +2005-10-13 17:43:36 +0000 Thomas Vander Stichele + + gst/elements/: fix some signedness + Original commit message from CVS: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: (gst_file_src_create_read): + * gst/elements/gsttypefindelement.c: + fix some signedness + * gst/elements/gstfilesink.c: (gst_file_sink_render): + I wonder if this could actually write +2GB files before + +2005-10-13 17:24:53 +0000 Thomas Vander Stichele + + * win32/common/libgstreamer.def: + add an export + Original commit message from CVS: + add an export + +2005-10-13 17:20:44 +0000 Thomas Vander Stichele + + * gst/glib-compat.h: + * gst/gstpad.c: + include header correctly; show me the name + Original commit message from CVS: + include header correctly; show me the name + +2005-10-13 16:34:04 +0000 Andy Wingo + + * ChangeLog: + foo + Original commit message from CVS: + foo + +2005-10-13 16:26:12 +0000 Andy Wingo + + libs/gst/dataprotocol/dataprotocol.c (gst_dp_packet_from_caps): Fix Timmeke Waymans bug. + Original commit message from CVS: + 2005-10-13 Andy Wingo + * libs/gst/dataprotocol/dataprotocol.c (gst_dp_packet_from_caps): + Fix Timmeke Waymans bug. + (gst_dp_caps_from_packet): Make sure we pass a NUL-terminated + string of the proper length to gst_caps_from_string. There's a + potential for, before this fix, that this could cause someone + connecting over the network to cause a segfault if the payload is + not NUL-terminated. + +2005-10-13 15:27:40 +0000 Stefan Kost + + fixed typos + Original commit message from CVS: + * docs/design/draft-push-pull.txt: + * docs/design/part-overview.txt: + * docs/random/TODO-pre-0.9: + * docs/random/old/ChangeLog.gstreamer: + * gst/base/gstpushsrc.c: + * gst/gstclock.c: + fixed typos + +2005-10-13 15:23:51 +0000 Thomas Vander Stichele + + gst/: GLib 2.6 g_flags_get_first_value has a bug that triggers an infinite loop + Original commit message from CVS: + * gst/glib-compat.c: (gst_flags_get_first_value): + * gst/glib-compat.h: + * gst/gstvalue.c: (gst_value_deserialize_int_helper), + (gst_value_compare_double), (gst_value_serialize_flags): + GLib 2.6 g_flags_get_first_value has a bug that triggers an + infinite loop + +2005-10-13 15:22:26 +0000 Thomas Vander Stichele + + gst/base/: fix up debugging + Original commit message from CVS: + 2005-10-13 Thomas Vander Stichele + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + * gst/base/gstbasesrc.c: (gst_base_src_get_range): + fix up debugging + * tools/gst-launch.c: (event_loop): + print out clock nicely + +2005-10-13 15:13:32 +0000 Tim-Philipp Müller + + Added gst_tag_list_get_date() and gst_tag_list_get_date_index(). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttaglist.h: + * gst/gsttaglist.c: (_gst_tag_initialize), (gst_tag_list_get_date), + (gst_tag_list_get_date_index): + Added gst_tag_list_get_date() and gst_tag_list_get_date_index(). + GST_TAG_DATE now has a tag type of GST_TYPE_DATE (#170777). + +2005-10-13 14:55:17 +0000 Julien Moutte + + gst/base/gstcollectpads.*: Handle newsegment and store informations in CollectData. + Original commit message from CVS: + 2005-10-13 Julien MOUTTE + * gst/base/gstcollectpads.c: (gst_collectpads_event), + (gst_collectpads_chain): + * gst/base/gstcollectpads.h: Handle newsegment and store + informations + in CollectData. + +2005-10-13 09:57:15 +0000 Stefan Kost + + fix GOption context leaks doc fixes + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gst.c: + * gst/gsterror.h: + * tools/gst-inspect.c: (main): + * tools/gst-launch.c: (main): + * tools/gst-run.c: (main): + * tools/gst-xmlinspect.c: (main): + fix GOption context leaks + doc fixes + +2005-10-12 22:34:47 +0000 Thomas Vander Stichele + + gst/gstbus.c: use HAVE_UNISTD_H + Original commit message from CVS: + * gst/gstbus.c: + use HAVE_UNISTD_H + * win32/common/config.h: + update config + * win32/vs6/grammar.dsp: + * win32/vs6/libgstelements.dsp: + * win32/vs6/libgstreamer.dsp: + update vs6 files + +2005-10-12 22:00:54 +0000 Thomas Vander Stichele + + * win32/common/libgstbase.def: + had a few too many 0D bytes + Original commit message from CVS: + had a few too many 0D bytes + +2005-10-12 21:56:52 +0000 Thomas Vander Stichele + + gst/base/: fix more guint64<->gdouble conversions + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + * gst/base/gstbasesrc.c: (gst_base_src_query): + fix more guint64<->gdouble conversions + +2005-10-12 20:23:42 +0000 Thomas Vander Stichele + + Makefile.am: add win32-update target + Original commit message from CVS: + * Makefile.am: + add win32-update target + * win32/common/gstconfig.h: + * win32/common/gstenumtypes.c: + * win32/common/gstenumtypes.h: + * win32/common/gstversion.h: + add files that visual studio can't generate + +2005-10-12 19:38:44 +0000 Wim Taymans + + gst/: Protect flags with proper lock. unref provided cached clock in dispose. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (reset_degree), (gst_bin_dispose), (bin_bus_handler): + * gst/gstelement.c: (gst_element_commit_state), + (gst_element_set_state): + Protect flags with proper lock. + unref provided cached clock in dispose. + +2005-10-12 19:14:23 +0000 Thomas Vander Stichele + + * gst/gstconfig.h.in: + layout cleanup + Original commit message from CVS: + layout cleanup + +2005-10-12 19:10:46 +0000 Stefan Kost + + removed unused flags from miniobject doc fixes + Original commit message from CVS: + * gst/gst.c: + * gst/gstminiobject.h: + * gst/gstpad.h: + * win32/gstenumtypes.c: (gst_mini_object_flags_get_type): + removed unused flags from miniobject + doc fixes + +2005-10-12 18:03:18 +0000 Thomas Vander Stichele + + * win32/vs6/grammar.dsp: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstelements.dsp: + * win32/vs6/libgstreamer.dsp: + convert to unix line ends; since the source is also unix-style line ends, developers don't need to fiddle and special... + Original commit message from CVS: + convert to unix line ends; since the source is also unix-style line ends, developers don't need to fiddle and special-case, but can just allow translation on the fly + +2005-10-12 16:03:39 +0000 Wim Taymans + + gst/elements/gstfilesink.c: Flush before seeking. + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_file_sink_do_seek), + (gst_file_sink_event), (gst_file_sink_render): + Flush before seeking. + +2005-10-12 15:58:24 +0000 Andy Wingo + + gst/gst.c (gst_init_check): Ignore unknown options, as has always been the case. + Original commit message from CVS: + 2005-10-12 Andy Wingo + * gst/gst.c (gst_init_check): Ignore unknown options, as has + always been the case. + +2005-10-12 14:28:39 +0000 Stefan Kost + + renamed GST_FLAGS macros to GST_OBJECT_FLAGS moved bitshift from macro to enum definition + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * docs/gst/gstreamer-sections.txt: + * gst/base/gstbasesink.c: (gst_base_sink_init): + * gst/base/gstbasesrc.c: (gst_base_src_init), + (gst_base_src_get_range), (gst_base_src_check_get_range), + (gst_base_src_start), (gst_base_src_stop): + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.c: (gst_fake_src_set_property): + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (bin_element_is_sink), (reset_degree), (gst_bin_element_set_state), + (bin_bus_handler): + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbus.c: (gst_bus_post), (gst_bus_set_flushing): + * gst/gstbus.h: + * gst/gstelement.c: (gst_element_is_locked_state), + (gst_element_set_locked_state), (gst_element_commit_state), + (gst_element_set_state): + * gst/gstelement.h: + * gst/gstindex.c: (gst_index_init): + * gst/gstindex.h: + * gst/gstminiobject.h: + * gst/gstobject.c: (gst_object_init), (gst_object_sink), + (gst_object_set_parent): + * gst/gstobject.h: + * gst/gstpad.c: (gst_pad_set_blocked_async), (gst_pad_is_blocked), + (gst_pad_get_caps_unlocked), (gst_pad_set_caps): + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstpipeline.c: (gst_pipeline_provide_clock_func), + (gst_pipeline_use_clock), (gst_pipeline_auto_clock): + * gst/gstpipeline.h: + * gst/indexers/gstfileindex.c: (gst_file_index_load), + (gst_file_index_commit): + * testsuite/bytestream/filepadsink.c: (gst_fp_sink_init): + * testsuite/pad/link.c: (gst_test_src_init), + (gst_test_filter_init), (gst_test_sink_init): + * testsuite/states/locked.c: (main): + renamed GST_FLAGS macros to GST_OBJECT_FLAGS + moved bitshift from macro to enum definition + +2005-10-12 14:12:37 +0000 Wim Taymans + + gst/: Some more debugging info. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_buffer): + * gst/elements/gstfilesink.c: (gst_file_sink_event), + (gst_file_sink_render): + Some more debugging info. + +2005-10-12 12:58:55 +0000 Wim Taymans + + Some doc updates. + Original commit message from CVS: + * docs/design/part-states.txt: + * tools/gst-launch.c: (main): + Some doc updates. + Revert non-intentional change. + +2005-10-12 12:18:48 +0000 Wim Taymans + + Use GstClockTime in _get_state() instead of GTimeVal. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstelement.c: (GST_START_TEST): + * check/gst/gstevent.c: (GST_START_TEST), (test_event): + * check/gst/gstghostpad.c: (GST_START_TEST): + * check/gst/gstpipeline.c: (GST_START_TEST): + * check/pipelines/simple_launch_lines.c: (run_pipeline): + * check/states/sinks.c: (GST_START_TEST): + * gst/elements/gsttypefindelement.c: (stop_typefinding): + * gst/gstbin.c: (gst_bin_provide_clock_func), (gst_bin_add_func), + (gst_bin_remove_func), (gst_bin_get_state_func), + (gst_bin_recalc_state), (gst_bin_change_state_func), + (bin_bus_handler): + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_get_state), (gst_element_abort_state), + (gst_element_commit_state), (gst_element_set_state), + (gst_element_change_state), (gst_element_change_state_func): + * gst/gstelement.h: + * gst/gstpipeline.c: (gst_pipeline_class_init), (do_pipeline_seek), + (gst_pipeline_provide_clock_func): + * gst/gstutils.c: (gst_element_link_pads_filtered): + * tools/gst-launch.c: (main): + * tools/gst-typefind.c: (main): + Use GstClockTime in _get_state() instead of GTimeVal. + Remove old code in gstutils.c + +2005-10-12 11:49:35 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_pause_task): Actually return FALSE if there is no task. Shouldn't affect any code, as nothing i... + Original commit message from CVS: + 2005-10-12 Andy Wingo + * gst/gstpad.c (gst_pad_pause_task): Actually return FALSE if + there is no task. Shouldn't affect any code, as nothing in our + plugins checks this return value. + (gst_pad_stop_task): Also take the stream lock if the pad has no + task. Docs updated. + +2005-10-12 10:05:36 +0000 Wim Taymans + + gst/gstpad.c: Cleanup activation code. Reset old state if activation failed. + Original commit message from CVS: + * gst/gstpad.c: (pre_activate), (post_activate), + (gst_pad_activate_pull), (gst_pad_activate_push): + Cleanup activation code. Reset old state if + activation failed. + +2005-10-12 09:02:42 +0000 Wim Taymans + + gst/base/gstbasesink.c: No need to prerol after receiving EOS. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_change_state): + No need to prerol after receiving EOS. + * gst/elements/gstfakesink.c: (gst_fake_sink_event): + * gst/elements/gstfakesrc.c: (gst_fake_src_event_handler): + * gst/elements/gstidentity.c: (gst_identity_event): + Print events more verbosely. + +2005-10-12 08:38:06 +0000 Wim Taymans + + check/: Moved sinks2 testcode in sinks check. + Original commit message from CVS: + * check/Makefile.am: + * check/states/sinks.c: (GST_START_TEST), (gst_object_suite): + * check/states/sinks2.c: + Moved sinks2 testcode in sinks check. + * gst/gstbin.c: (gst_bin_provide_clock_func), (gst_bin_add_func), + (gst_bin_remove_func), (gst_bin_recalc_state), + (gst_bin_change_state_func), (bin_bus_handler): + Fix potential race condition when _get_state() iterated over an + ASYNC element right before it posted a state completion. + * gst/gstclock.h: + Do proper cast here. + * gst/gstevent.c: (gst_event_new_newsegment), + (gst_event_parse_newsegment): + A playback rate of 0.0 is not allowed. + +2005-10-12 02:26:44 +0000 Thomas Vander Stichele + + * autogen.sh: + autoconf for freebsd + Original commit message from CVS: + autoconf for freebsd + +2005-10-12 02:25:18 +0000 Thomas Vander Stichele + + * autogen.sh: + autoconf for freebsd + Original commit message from CVS: + autoconf for freebsd + +2005-10-12 02:23:29 +0000 Thomas Vander Stichele + + * autogen.sh: + autoconf for freebsd + Original commit message from CVS: + autoconf for freebsd + +2005-10-12 02:19:38 +0000 Thomas Vander Stichele + + * autogen.sh: + autoconf for freebsd + Original commit message from CVS: + autoconf for freebsd + +2005-10-12 02:16:26 +0000 Thomas Vander Stichele + + * autogen.sh: + autoconf for freebsd + Original commit message from CVS: + autoconf for freebsd + +2005-10-11 18:03:13 +0000 Thomas Vander Stichele + + win32/: Visual Studio 6 project files, and a new common directory. + Original commit message from CVS: + 2005-10-11 Thomas Vander Stichele + * win32/common/config.h: + * win32/common/dirent.c: (_topendir), (_treaddir), (_tclosedir), + (_trewinddir), (_ttelldir), (_tseekdir): + * win32/common/dirent.h: + * win32/common/gtchar.h: + * win32/common/libgstbase.def: + * win32/common/libgstreamer.def: + * win32/vs6/grammar.dsp: + * win32/vs6/gst_inspect.dsp: + * win32/vs6/gst_launch.dsp: + * win32/vs6/gstreamer.dsw: + * win32/vs6/libgstbase.dsp: + * win32/vs6/libgstelements.dsp: + * win32/vs6/libgstreamer.dsp: + Visual Studio 6 project files, and a new common directory. + Phear. + +2005-10-11 17:33:25 +0000 Wim Taymans + + * gst/base/gstbasesink.h: + * libs/gst/base/gstbasesink.h: + forgot this one + Original commit message from CVS: + forgot this one + +2005-10-11 17:32:00 +0000 Wim Taymans + + gst/base/gstbasesink.*: Correctly parse newsegment info. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync), (gst_base_sink_query), + (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + Correctly parse newsegment info. + +2005-10-11 16:54:41 +0000 Thomas Vander Stichele + + gst/gst.c: split plugin paths correctly + Original commit message from CVS: + 2005-10-11 Thomas Vander Stichele + * gst/gst.c: (init_post): + split plugin paths correctly + +2005-10-11 16:28:49 +0000 Wim Taymans + + Added extra flag to newsegment for future API freeze. + Original commit message from CVS: + * check/gst/gstevent.c: (GST_START_TEST): + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_change_state): + * gst/base/gstbasesrc.c: (gst_base_src_default_newsegment): + * gst/base/gstbasetransform.c: (gst_base_transform_event): + * gst/elements/gstfilesink.c: (gst_file_sink_event): + * gst/gstevent.c: (gst_event_new_newsegment), + (gst_event_parse_newsegment): + * gst/gstevent.h: + Added extra flag to newsegment for future API freeze. + Updated check and base elements. + +2005-10-11 16:25:35 +0000 Julien Moutte + + gst/base/gstcollectpads.*: Handle EOS correctly. + Original commit message from CVS: + 2005-10-11 Julien MOUTTE + * gst/base/gstcollectpads.c: (gst_collectpads_init), + (gst_collectpads_add_pad), (gst_collectpads_pop), + (gst_collectpads_event), (gst_collectpads_chain): + * gst/base/gstcollectpads.h: Handle EOS correctly. + +2005-10-11 16:21:05 +0000 Thomas Vander Stichele + + * ChangeLog: + * tools/gst-launch.c: + more str null protection + Original commit message from CVS: + more str null protection + +2005-10-11 16:05:16 +0000 Thomas Vander Stichele + + gst/gst-i18n-lib.h: check for ENABLE_NLS, not GETTEXT_PACKAGE + Original commit message from CVS: + * gst/gst-i18n-lib.h: + check for ENABLE_NLS, not GETTEXT_PACKAGE + * gst/gstregistry.c: (gst_registry_add_plugin), + (gst_registry_scan_path_level), + (_gst_registry_remove_cache_plugins): + protect possibly NULL strings + * gst/parse/types.h: + config.h already included before + * tools/gst-inspect.c: (main): + sys/wait.h also doesn�t exist on mingw, so change the ifdef check + check for ENABLE_NLS, not GETTEXT_PACKAGE + * tools/gst-launch.c: (main): + check for ENABLE_NLS, not GETTEXT_PACKAGE + This commit brought to you from msys/mingw + +2005-10-11 15:26:58 +0000 Thomas Vander Stichele + + configure.ac: if we don't have glib, fail before testing 2.8 + Original commit message from CVS: + * configure.ac: + if we don't have glib, fail before testing 2.8 + * gst/base/gstbasetransform.c: (gst_base_transform_change_state): + fix a leak, should fix plugins-base testsuite + +2005-10-11 15:23:10 +0000 Andy Wingo + + gst/gstpad.c (pre_activate): Renamed from pre_activate_switch, take the mode we're going to as an arg. Go head and se... + Original commit message from CVS: + 2005-10-11 Andy Wingo + * gst/gstpad.c (pre_activate): Renamed from pre_activate_switch, + take the mode we're going to as an arg. Go head and set the mode + and flushing flags now, so that if the activate function starts a + thread all the flags will be in the right state. + (post_activate): Renamed also. Just handle making sure streaming + finishes for the deactivation case, and setting the deactivated + mode. + (gst_pad_set_active): Complain loudly if deactivation fails. + (gst_pad_activate_pull): Adapt to pre/post_activate changes. + (gst_pad_activate_push): Adapt to pre/post_activate changes, + remove the terrible hack. + +2005-10-11 15:05:55 +0000 Wim Taymans + + gst/gstbin.*: Prepare to make current EOS message queue more generic. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_init), (gst_bin_provide_clock_func), + (is_eos), (gst_bin_add_func), (gst_bin_remove_func), + (gst_bin_recalc_state), (gst_bin_change_state_func), + (gst_bin_dispose), (bin_bus_handler): + * gst/gstbin.h: + Prepare to make current EOS message queue more generic. + Fix some typos. + * gst/gstevent.c: (gst_event_new_newsegment), + (gst_event_parse_newsegment): + * gst/gstevent.h: + Rename base to stream_time. + * gst/gstmessage.h: + Fix typo in docs. + +2005-10-11 12:58:44 +0000 Wim Taymans + + gst/gstbin.*: Work on proper clock selection. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_init), (gst_bin_provide_clock_func), + (gst_bin_add_func), (gst_bin_remove_func), (gst_bin_recalc_state), + (gst_bin_change_state_func), (bin_bus_handler): + * gst/gstbin.h: + Work on proper clock selection. + +2005-10-11 12:42:23 +0000 Edward Hervey + + libs/gst/controller/gstcontroller.*: Added GList* version of _remove_properties() in order to be able to wrap it in b... + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_remove_properties_list): + * libs/gst/controller/gstcontroller.h: + Added GList* version of _remove_properties() in order to be able to wrap + it in bindings. + +2005-10-11 11:08:52 +0000 Wim Taymans + + docs/design/part-states.txt: Some more docs. + Original commit message from CVS: + * docs/design/part-states.txt: + Some more docs. + * gst/gstbin.c: (gst_bin_set_clock_func), (gst_bin_recalc_state), + (gst_bin_change_state_func), (bin_bus_handler): + Doc updates. Don't distribute the same clock over and over again. + * gst/gstclock.c: + * gst/gstclock.h: + Doc updates. + * gst/gstpad.c: (gst_flow_get_name), (gst_flow_to_quark), + (gst_pad_get_type), (gst_pad_push), (gst_pad_push_event), + (gst_pad_send_event): + * gst/gstpad.h: + Make probe emission threadsafe again. + Register quarks and move _get_name() from utils. + Doc updates. + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_change_state), (gst_pipeline_provide_clock_func): + Only redistribute the clock of it changed. + * gst/gstsystemclock.h: + Doc updates. + * gst/gstutils.c: + * gst/gstutils.h: + Moved the _flow_get_name() to GstPad. + +2005-10-11 09:14:59 +0000 Thomas Vander Stichele + + * common: + * gst/gstbuffer.c: + if we log our init, should also log finalize + Original commit message from CVS: + if we log our init, should also log finalize + +2005-10-10 23:55:39 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst-libs/gdp.c: + * check/gst/gstcaps.c: + * common: + * libs/gst/dataprotocol/dataprotocol.c: + * tests/check/gst/gstcaps.c: + * tests/check/libs/gdp.c: + fix more valgrind warnings before turning up the heat + Original commit message from CVS: + fix more valgrind warnings before turning up the heat + +2005-10-10 23:11:33 +0000 Thomas Vander Stichele + + * gst/parse/grammar.y: + don't declare on the proper define + Original commit message from CVS: + don't declare on the proper define + +2005-10-10 22:59:22 +0000 Thomas Vander Stichele + + * gst/parse/grammar.y: + unmangle the nesting a little + Original commit message from CVS: + unmangle the nesting a little + +2005-10-10 22:49:42 +0000 Thomas Vander Stichele + + gst/parse/grammar.y: some cleanup before the hacking + Original commit message from CVS: + * gst/parse/grammar.y: + some cleanup before the hacking + +2005-10-10 18:16:37 +0000 Thomas Vander Stichele + + gst/base/gstbasesrc.c: use conversions + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_query): + use conversions + * gst/gstutils.c: (gst_guint64_to_gdouble), + (gst_gdouble_to_guint64), (gst_util_uint64_scale): + * gst/gstutils.h: + externalize, basesrc uses it + obviously the implementation needs testing + +2005-10-10 17:05:04 +0000 Thomas Vander Stichele + + * gst/gstutils.c: + another cast bites the dust + Original commit message from CVS: + another cast bites the dust + +2005-10-10 16:45:45 +0000 Thomas Vander Stichele + + * gst/gstutils.c: + another cast bites the dust + Original commit message from CVS: + another cast bites the dust + +2005-10-10 16:43:32 +0000 Wim Taymans + + tests/sched/: + Original commit message from CVS: + * tests/sched/Makefile.am: + * tests/sched/sort.c: (make_pipeline1), (make_pipeline2), + (make_pipeline3), (make_pipeline4), (print_elem), (main): + +2005-10-10 16:38:59 +0000 Thomas Vander Stichele + + gst/gstutils.c: apparently converting from guint64 to double is not implemented on MSVC + Original commit message from CVS: + * gst/gstutils.c: (guint64_to_gdouble), (gst_util_uint64_scale): + apparently converting from guint64 to double is not implemented + on MSVC + +2005-10-10 16:38:26 +0000 Wim Taymans + + check/: Check fixes, use API as stated in design docs, remove hacks. + Original commit message from CVS: + * check/Makefile.am: + * check/generic/states.c: (GST_START_TEST): + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstpipeline.c: (GST_START_TEST), (gst_pipeline_suite): + * check/states/sinks.c: (GST_START_TEST): + * check/states/sinks2.c: (GST_START_TEST), (gst_object_suite), + (main): + Check fixes, use API as stated in design docs, remove hacks. + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_change_state): + Catch stopping our task while we're shutting down. + * gst/gstbin.c: (gst_bin_init), (gst_bin_add_func), + (gst_bin_remove_func), (gst_bin_get_state_func), + (gst_bin_recalc_state), (gst_bin_change_state_func), + (bin_bus_handler): + * gst/gstbin.h: + * gst/gstelement.c: (gst_element_init), + (gst_element_get_state_func), (gst_element_abort_state), + (gst_element_commit_state), (gst_element_lost_state), + (gst_element_set_state), (gst_element_change_state), + (gst_element_change_state_func): + * gst/gstelement.h: + New state change algorithm (see #318116) + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_init), (gst_pipeline_set_property), + (gst_pipeline_get_property), (do_pipeline_seek), + (gst_pipeline_change_state), (gst_pipeline_provide_clock_func): + * gst/gstpipeline.h: + Remove crude state change hacks. + * gst/gstutils.h: + Remove crude hacks. + * tools/gst-launch.c: (main): + Fixes for state change. Needs some more work to fully use the + new stuff. + +2005-10-10 16:20:41 +0000 Andy Wingo + + tests/Makefile.am (noinst_PROGRAMS): No more init.c. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * tests/Makefile.am (noinst_PROGRAMS): No more init.c. + +2005-10-10 16:04:28 +0000 Andy Wingo + + gst/gst.c (G_OPTION_FLAG_NO_ARG): Apparently GLib 2.8 requires this flag, but it's not even in GLib 2.6. Odd. Hack ar... + Original commit message from CVS: + 2005-10-10 Andy Wingo + * gst/gst.c (G_OPTION_FLAG_NO_ARG): Apparently GLib 2.8 requires + this flag, but it's not even in GLib 2.6. Odd. Hack around the + issue. + +2005-10-10 15:58:32 +0000 Tim-Philipp Müller + + gst/gstiterator.c: Fix my previous commit: GTypes passed to gst_iterator_new() can be fundamental types. + Original commit message from CVS: + * gst/gstiterator.c: (gst_iterator_new): + Fix my previous commit: GTypes passed to gst_iterator_new() + can be fundamental types. + +2005-10-10 15:55:37 +0000 Wim Taymans + + gst/gstelement.c: Use src/sink pads lists for the respective iterators instead of filtering. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_iterate_pad_list), + (gst_element_iterate_pads), (gst_element_iterate_src_pads), + (gst_element_iterate_sink_pads): + Use src/sink pads lists for the respective iterators instead + of filtering. + +2005-10-10 15:53:59 +0000 Ronald + + Merged in popt removal + GOption addition patch from Ronald, bug #169772. + Original commit message from CVS: + 2005-10-10 Andy Wingo + Merged in popt removal + GOption addition patch from Ronald, bug + #169772. + * docs/gst/gstreamer-sections.txt: Add STATE_(UN)LOCK_FULL, move + GstElement macros around, remove popt-related symbols, add goption + stuff. + * configure.ac: Remove popt checks, require GLib 2.6 for GOption. + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: No POPT_CFLAGS. + * examples/manual/Makefile.am: + * docs/manual/basics-init.xml: Doc updates with an example. + * gst/gst.c: (gst_init_get_option_group), (gst_init_check), + (gst_init), (parse_one_option), (parse_goption_arg): + * gst/gst.h: Removed gst_init_with_popt_table and friends. Took a + bit of hand merging and debugging to get the GOption stuff working + tho. + * tests/Makefile.am: + * tools/Makefile.am: + * tools/gst-inspect.c: (main): + * tools/gst-launch.c: (main): + * tools/gst-run.c: (main): + * tools/gst-xmlinspect.c: (main): Thanks Ronald! + +2005-10-10 15:30:45 +0000 Tim-Philipp Müller + + gst/gstiterator.c: Add assertions to make sure passed GType is likely to really be a GType (as the compiler won't cat... + Original commit message from CVS: + * gst/gstiterator.c: (gst_iterator_new): + Add assertions to make sure passed GType is likely to really + be a GType (as the compiler won't catch it if the size and + GType arguments get mixed up, see #318447). + +2005-10-10 15:27:12 +0000 Tim-Philipp Müller + + gst/gstbin.c: Pass GType and size arguments to gst_iterator_new() in the right order (maybe we should make _new() tak... + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstbin.c: (gst_bin_iterate_sorted): + Pass GType and size arguments to gst_iterator_new() in the right + order (maybe we should make _new() take the GType as first argument + just like _new_list()?) (#318447). + +2005-10-10 15:17:35 +0000 Wim Taymans + + gst/gstelement.c: And free the GStaticRecMutex too + Original commit message from CVS: + * gst/gstelement.c: (gst_element_finalize): + And free the GStaticRecMutex too + +2005-10-10 14:33:38 +0000 Thomas Vander Stichele + + * win32/GStreamer.vcproj: + * win32/vs7/GStreamer.vcproj: + don't echo path + Original commit message from CVS: + don't echo path + +2005-10-10 14:33:13 +0000 Andy Wingo + + gst/gstelement.c (gst_element_init, gst_element_finalize): Allocate and free the mutex properly. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * gst/gstelement.c (gst_element_init, gst_element_finalize): + Allocate and free the mutex properly. + * gst/gstelement.h (GST_STATE_UNLOCK_FULL, GST_STATE_LOCK_FULL): + New macros. + (GstElement): The state_lock is now recursive. Rebuild your + plugins, suckers. Old macros adapted. + +2005-10-10 14:23:57 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2005-10-10 14:23:26 +0000 Andy Wingo + + docs/gst/gstreamer-sections.txt: Doc updates. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * docs/gst/gstreamer-sections.txt: Doc updates. + * gst/gstutils.h: + * gst/gstutils.c (g_static_rec_cond_timed_wait) + (g_static_rec_cond_wait): Ported from state changes patch, while + we wait on bug #317802 to be solved in a well-distributed GLib. + +2005-10-10 14:15:15 +0000 Thomas Vander Stichele + + * win32/MANIFEST: + * win32/libgstbase.def: + * win32/libgstbase.vcproj: + * win32/link_oldruntime.c: + * win32/vs7/libgstbase.def: + * win32/vs7/libgstbase.vcproj: + * win32/vs7/link_oldruntime.c: + add more win32 build files + Original commit message from CVS: + add more win32 build files + +2005-10-10 14:03:25 +0000 Andy Wingo + + gst/gstelement.c (gst_element_change_state_func): Renamed from gst_element_change_state, variable name changes. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * gst/gstelement.c (gst_element_change_state_func): Renamed from + gst_element_change_state, variable name changes. + (gst_element_change_state): Split out of gst_element_set_state in + preparation for the state change merge. Doesn't pay attention to + the 'transition' argument. + (gst_element_set_state): Updates, hopefully purely cosmetic. + (gst_element_sync_state_with_parent): MT-safety. Ported from the + state change patch. + (gst_element_get_state_func): Renamed from get_state, cosmetic + changes. + +2005-10-10 13:52:18 +0000 Sebastien Moutte + + updates for the win32 build (patch from Sebastien Moutte) + Original commit message from CVS: + * gst/elements/gstelements.c: + * win32/GStreamer.vcproj: + * win32/config.h: + * win32/dirent.c: (_tseekdir): + * win32/gst-inspect.vcproj: + * win32/gst-launch.vcproj: + * win32/gstconfig.h: + * win32/gstelements.vcproj: + * win32/gstenumtypes.c: (gst_object_flags_get_type): + * win32/gstreamer.def: + * win32/msvc71.sln: + updates for the win32 build (patch from Sebastien Moutte) + +2005-10-10 11:52:58 +0000 Andy Wingo + + gst/gstbin.c (gst_bin_get_state_func): Renamed from gst_bin_get_state, cleaned up (but no logic changes). + Original commit message from CVS: + 2005-10-10 Andy Wingo + * gst/gstbin.c (gst_bin_get_state_func): Renamed from + gst_bin_get_state, cleaned up (but no logic changes). + (bin_element_is_sink): Comment updates. + (sink_iterator_filter): Remove needless cast. + (gst_bin_iterate_sinks): Doc update. + (gst_bin_change_state_func): Renamed from gst_bin_change_state, + cleaned up (but no logic changes). + +2005-10-10 11:04:55 +0000 Andy Wingo + + check/states/sinks.c (test_src_sink): Cleanups from the state change patch. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * check/states/sinks.c (test_src_sink): Cleanups from the state + change patch. + (test_livesrc_sink): Sync on the state. + +2005-10-10 10:59:33 +0000 Andy Wingo + + check/pipelines/simple_launch_lines.c (run_pipeline): Merge from the state change patch. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * check/pipelines/simple_launch_lines.c (run_pipeline): Merge from + the state change patch. + +2005-10-10 10:57:40 +0000 Andy Wingo + + check/gst/gstghostpad.c (test_ghost_pads): Merge from the state change patch. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * check/gst/gstghostpad.c (test_ghost_pads): Merge from the state + change patch. + +2005-10-10 10:50:12 +0000 Andy Wingo + + check/gst/gstbin.c: Merge in some style fixes and additional checks from Wim's state change patch. + Original commit message from CVS: + 2005-10-10 Andy Wingo + * check/gst/gstbin.c: Merge in some style fixes and additional + checks from Wim's state change patch. + +2005-10-10 10:43:15 +0000 Tim-Philipp Müller + + gst/base/gsttypefindhelper.c: Check whether we have the requested data already in our list of cached buffers before p... + Original commit message from CVS: + * gst/base/gsttypefindhelper.c: (helper_find_peek), + (gst_type_find_helper): + Check whether we have the requested data already in our list of + cached buffers before pulling a new buffer; also make the buffer + list a GSList. Speeds up typefinding by ca. 5-10% altogether. + +2005-10-10 09:48:21 +0000 Thomas Vander Stichele + + gst/: doc updates + Original commit message from CVS: + * gst/gstcaps.c: + * gst/gstevent.c: + doc updates + * gst/gstvalue.c: (gst_value_deserialize_int_helper): + don't use long long, it's not portable. Replacing with + gint64 seems to work; let's hope no skeletons fall out of the closet. + +2005-10-10 08:51:59 +0000 Andy Wingo + + autogen.sh (CONFIGURE_DEF_OPT): No more --plugin-buiddir, yay + Original commit message from CVS: + 2005-10-10 Andy Wingo + * autogen.sh (CONFIGURE_DEF_OPT): No more --plugin-buiddir, yay + +2005-10-09 20:49:46 +0000 Stefan Kost + + more docs, fix compilation + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstmessage.c: (gst_message_parse_state_changed): + * gst/gstpad.c: + * gst/gstpad.h: + more docs, fix compilation + +2005-10-09 20:19:48 +0000 Philippe Kalaf + + gst/gstmessage.c: Fixed a few forgotten variables on previous commit + Original commit message from CVS: + 2005-10-09 Philippe Khalaf + * gst/gstmessage.c: + Fixed a few forgotten variables on previous commit + +2005-10-09 17:59:08 +0000 Tim-Philipp Müller + + gst/base/gsttypefindhelper.c: Fix evil typefind crasher: getrange() might return a short buffer at the end of a file,... + Original commit message from CVS: + * gst/base/gsttypefindhelper.c: (helper_find_peek): + Fix evil typefind crasher: getrange() might return a short + buffer at the end of a file, but gst_type_find_peek() must + either return the full data as requested or NULL, but + never a short buffer. + +2005-10-09 17:53:33 +0000 Thomas Vander Stichele + + gst/gstmessage.*: don't use new, it's a C++ keyword + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_state_changed), + (gst_message_parse_state_changed): + * gst/gstmessage.h: + don't use new, it's a C++ keyword + +2005-10-09 17:22:33 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + once is enough + Original commit message from CVS: + once is enough + +2005-10-08 18:21:20 +0000 Wim Taymans + + gst/: Small docs and debug updates. + Original commit message from CVS: + * gst/gstbin.c: (is_eos), (update_degree), (gst_bin_query): + * gst/gstelement.c: (gst_element_post_message): + * gst/gstpipeline.c: (gst_pipeline_change_state): + Small docs and debug updates. + +2005-10-08 18:07:20 +0000 Stefan Kost + + more docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstelementfactory.c: + * gst/gstevent.c: + * gst/gsttaglist.c: + more docs + +2005-10-08 18:01:04 +0000 Wim Taymans + + gst/gstbin.c: Fix typos, add comments. + Original commit message from CVS: + * gst/gstbin.c: (is_eos), (update_degree), (gst_bin_change_state), + (gst_bin_dispose), (bin_bus_handler): + Fix typos, add comments. + Clear EOS list when going to PAUSED from any direction and do it + in a threadsafe way. + Get base time in a threadsafe way too. + Fix confusing debug in the change_state function. + Various other mall cleanups. + * gst/gstelement.c: (gst_element_post_message): + Fix very verbose bus posting code. + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_set_property), (gst_pipeline_get_property), + (gst_pipeline_change_state): + Small ARG_ -> PROP_ cleanup + +2005-10-08 17:30:29 +0000 Wim Taymans + + gst/gstbin.c: Do a less CPU demanding EOS check because we can. + Original commit message from CVS: + * gst/gstbin.c: (is_eos), (bin_bus_handler): + Do a less CPU demanding EOS check because we can. + +2005-10-08 17:17:25 +0000 Wim Taymans + + libs/gst/dataprotocol/: It's about time we bump the version number. + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer), (gst_dp_packet_from_caps), + (gst_dp_packet_from_event): + * libs/gst/dataprotocol/dataprotocol.h: + * libs/gst/dataprotocol/dp-private.h: + It's about time we bump the version number. + Since event types don't fit in the guint8 anymore describing + the payload type, make payload type 16 bits wide. + +2005-10-08 16:49:15 +0000 Wim Taymans + + docs/design/: Many doc updates. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-clocks.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-live-source.txt: + * docs/design/part-messages.txt: + * docs/design/part-overview.txt: + * docs/design/part-states.txt: + Many doc updates. + +2005-10-08 16:13:50 +0000 Wim Taymans + + gst/gstevent.*: Fix event quark registration. + Original commit message from CVS: + * gst/gstevent.c: + * gst/gstevent.h: + Fix event quark registration. + Add some space between events so we can insert them in the + right groups. + +2005-10-08 14:57:09 +0000 Wim Taymans + + gst/base/gstbasesink.c: Better log message. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_handle_buffer): + Better log message. + * gst/gstbus.h: + * gst/gstelement.h: + More docs. + * gst/gstqueue.c: (gst_queue_class_init), (gst_queue_init), + (gst_queue_set_property), (gst_queue_get_property): + * gst/gstqueue.h: + Remove old unused properties. + +2005-10-08 14:48:17 +0000 Stefan Kost + + lots of new docs and doc fixes + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstminiobject.c: + * gst/gstminiobject.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstutils.h: + lots of new docs and doc fixes + +2005-10-08 14:41:56 +0000 Thomas Vander Stichele + + * gst/gstregistry.c: + fix a leak I introduced + Original commit message from CVS: + fix a leak I introduced + +2005-10-08 13:57:17 +0000 Thomas Vander Stichele + + gst/: Only ever load one plugin for a given plugin basename. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_finalize), (gst_plugin_load_file): + * gst/gstplugin.h: + * gst/gstregistry.c: (gst_registry_lookup_locked), + (gst_registry_scan_path_level): + * gst/gstregistryxml.c: (load_plugin): + Only ever load one plugin for a given plugin basename. + This ensures correct overriding of GST_PLUGIN_PATH over + GST_PLUGIN_SYSTEM_PATH and of home dir plugins over + system installed plugins. + +2005-10-08 13:39:02 +0000 Wim Taymans + + gst/base/gstbasesink.c: Prepare for doing QOS. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync), (gst_base_sink_handle_buffer): + Prepare for doing QOS. + +2005-10-08 13:10:34 +0000 Wim Taymans + + check/: Allow new clock message too. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/pipelines/cleanup.c: (GST_START_TEST): + * check/pipelines/simple_launch_lines.c: (GST_START_TEST): + Allow new clock message too. + +2005-10-08 12:56:37 +0000 Wim Taymans + + gst/gstmessage.*: Also carry the clock in question. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_clock_provide), + (gst_message_new_clock_lost), (gst_message_new_new_clock), + (gst_message_new_segment_start), (gst_message_new_segment_done), + (gst_message_parse_state_changed), + (gst_message_parse_clock_provide), (gst_message_parse_clock_lost), + (gst_message_parse_new_clock): + * gst/gstmessage.h: + Also carry the clock in question. + +2005-10-08 12:36:36 +0000 Wim Taymans + + gst/gstmessage.*: Clean up. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_custom), + (gst_message_new_eos), (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_clock_provide), + (gst_message_new_new_clock), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_parse_state_changed), + (gst_message_parse_clock_provide), (gst_message_parse_new_clock): + * gst/gstmessage.h: + Clean up. + Added clock related messages. + * gst/gstpipeline.c: (gst_pipeline_change_state): + Post message when the clock changed. + * tools/gst-launch.c: (event_loop): + Print new clock. + +2005-10-08 11:16:03 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Can't pass NULL strings to g_print() on windows. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + Can't pass NULL strings to g_print() on windows. + +2005-10-08 11:12:26 +0000 Thomas Vander Stichele + + docs/: add a chapter on running GStreamer. + Original commit message from CVS: + * docs/Makefile.am: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/running.xml: + * docs/version.entities.in: + add a chapter on running GStreamer. + document GST_DEBUG and GST_PLUGIN* env vars + +2005-10-08 11:10:17 +0000 Thomas Vander Stichele + + Makefile.am: remove include dir + Original commit message from CVS: + * Makefile.am: + remove include dir + * configure.ac: + remove PLUGINS_BUILDDIR stuff + * gst/gst.c: (init_post): + reorder parsing of GST_PLUGIN_PATH and GST_PLUGIN_SYSTEM_PATH + * idiottest.mak: + remove, it was condescending and not needed + +2005-10-08 09:58:30 +0000 Wim Taymans + + gst/base/gstbasesink.*: Repost EOS message while going to PLAYING if still EOS. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush), + (gst_base_sink_handle_object), (gst_base_sink_event), + (gst_base_sink_wait), (gst_base_sink_handle_event), + (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + Repost EOS message while going to PLAYING if still EOS. + Make sure that when receiving a FLUSH_START we don't attempt + to sync on the clock anymore. + +2005-10-08 09:38:19 +0000 Wim Taymans + + tools/gst-launch.c: Better message printout. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Better message printout. + +2005-10-08 09:24:25 +0000 Wim Taymans + + gst/: Make ChildProxy threadsafe and fix mem leaks. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_child_proxy_get_child_by_index), + (gst_bin_child_proxy_get_children_count): + * gst/gstchildproxy.c: (gst_child_proxy_get_child_by_name), + (gst_child_proxy_lookup), (gst_child_proxy_get_property), + (gst_child_proxy_get_valist), (gst_child_proxy_set_property), + (gst_child_proxy_set_valist): + * gst/parse/grammar.y: + Make ChildProxy threadsafe and fix mem leaks. + +2005-10-08 09:09:55 +0000 Thomas Vander Stichele + + gst/gst.c: debug the GST_PLUGIN_ env vars + Original commit message from CVS: + * gst/gst.c: (init_post): + debug the GST_PLUGIN_ env vars + +2005-10-08 08:58:45 +0000 Wim Taymans + + Added extra field to STATE_CHANGE message with the pending state, which will be different from the new state soon. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * check/gst/gstmessage.c: (GST_START_TEST): + * check/gst/gstpipeline.c: (GST_START_TEST), (message_received): + * gst/gstelement.c: (gst_element_commit_state), + (gst_element_lost_state): + * gst/gstmessage.c: (gst_message_new_state_changed), + (gst_message_parse_state_changed): + * gst/gstmessage.h: + * tools/gst-launch.c: (event_loop): + Added extra field to STATE_CHANGE message with the pending + state, which will be different from the new state soon. + +2005-10-08 08:00:37 +0000 Wim Taymans + + gst/: Small cleanups and doc updates. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_pop): + * gst/gstclock.c: + * gst/gstsystemclock.c: (gst_system_clock_async_thread): + Small cleanups and doc updates. + +2005-10-08 06:49:09 +0000 Thomas Vander Stichele + + gst/: log distributing clocks and base time + Original commit message from CVS: + * gst/gst.c: (init_pre): + * gst/gstbin.c: (gst_bin_add_func): + log distributing clocks and base time + * gst/gstregistry.c: (gst_registry_add_plugin), + (gst_registry_scan_path_level), (gst_registry_scan_path): + clean up the debugging output a little + * gst/gstutils.c: (gst_element_state_get_name): + warn about a memleak (I've actually seen this be used, though + it was probably a bug) + +2005-10-08 06:42:30 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + add two new functions + Original commit message from CVS: + add two new functions + +2005-10-07 18:17:23 +0000 Wim Taymans + + gst/base/gstbasesrc.*: Make the newsegment event customizable by subclasses. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_default_newsegment), + (gst_base_src_newsegment), (gst_base_src_do_seek), + (gst_base_src_loop), (gst_base_src_start): + * gst/base/gstbasesrc.h: + Make the newsegment event customizable by subclasses. + +2005-10-07 18:02:14 +0000 Wim Taymans + + gst/gstevent.*: New event for future idea. + Original commit message from CVS: + * gst/gstevent.c: (gst_event_new_buffersize), + (gst_event_parse_buffersize): + * gst/gstevent.h: + New event for future idea. + +2005-10-07 16:28:56 +0000 Andy Wingo + + gst/gstelement.c (gst_element_post_message): Doc update. + Original commit message from CVS: + 2005-10-07 Andy Wingo + * gst/gstelement.c (gst_element_post_message): Doc update. + +2005-10-07 16:13:51 +0000 Andy Wingo + + docs/gst/gstreamer-sections.txt: Update. + Original commit message from CVS: + 2005-10-07 Andy Wingo + * docs/gst/gstreamer-sections.txt: Update. + * gst/gstmessage.c (gst_message_new_application): Made into a + function like honest API calls. + (gst_message_new_element): New message type. + * gst/gstmessage.h (enum): Add GST_MESSAGE_ELEMENT type. + +2005-10-07 15:25:49 +0000 Thomas Vander Stichele + + * gst/elements/gstelements.c: + * plugins/elements/gstelements.c: + fdsrc does not build currently on win32 due to socketpair + Original commit message from CVS: + fdsrc does not build currently on win32 due to socketpair + +2005-10-07 15:22:38 +0000 Andy Wingo + + check/elements/fakesrc.c (test_no_preroll): New check, checks that setting a live fakesrc to PAUSED returns NO_PREROL... + Original commit message from CVS: + 2005-10-07 Andy Wingo + * check/elements/fakesrc.c (test_no_preroll): New check, checks + that setting a live fakesrc to PAUSED returns NO_PREROLL both + times. + * gst/base/gstbasesrc.c (gst_base_src_change_state): Allow a + NO_PREROLL from gst_element_change_state to fall through. + +2005-10-07 15:13:25 +0000 Thomas Vander Stichele + + * tools/gst-launch.c: + don't use if not declared + Original commit message from CVS: + don't use if not declared + +2005-10-07 12:52:15 +0000 Wim Taymans + + gst/gstghostpad.c: Activating a ghostpad with no internal pad in push mode is ok. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_ghost_pad_get_internal), + (gst_ghost_pad_do_activate_push): + Activating a ghostpad with no internal pad in push mode + is ok. + +2005-10-07 12:45:49 +0000 Thomas Vander Stichele + + gst/gstobject.h: there's no point in wrapping FLAG_SET/_UNSET in STMT macros. + Original commit message from CVS: + * gst/gstobject.h: + there's no point in wrapping FLAG_SET/_UNSET in STMT macros. + Fixes compilation on Windows. + +2005-10-07 10:32:24 +0000 Michael Smith + + * ChangeLog: + * common: + * tools/gst-inspect.c: + Print out feature and plugin count at the end when printing out all features. + Original commit message from CVS: + Print out feature and plugin count at the end when printing out + all features. + Also add a changelog entry which I'd written but not committed? + +2005-10-07 00:14:45 +0000 Johan Dahlin + + Add a GType to GstIterator, update callsites and tests. + Original commit message from CVS: + * check/gst/gstiterator.c: (GST_START_TEST): + * gst/gstbin.c: (gst_bin_iterate_elements), + (gst_bin_iterate_recurse), (gst_bin_iterate_sorted): + * gst/gstelement.c: (gst_element_iterate_pads): + * gst/gstformat.c: (gst_format_iterate_definitions): + * gst/gstiterator.c: (gst_iterator_init), (gst_iterator_new), + (gst_iterator_new_list), (gst_iterator_filter): + * gst/gstiterator.h: + * gst/gstquery.c: (gst_query_type_iterate_definitions): + Add a GType to GstIterator, update callsites and tests. + +2005-10-06 21:09:11 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + doh. use correct variable + Original commit message from CVS: + doh. use correct variable + +2005-10-06 17:00:50 +0000 Christian Schaller + + * gstreamer.spec.in: + version gstreamer-tools package + Original commit message from CVS: + version gstreamer-tools package + +2005-10-06 14:20:15 +0000 Thomas Vander Stichele + + * gst/gstevent.c: + initialize quarks + Original commit message from CVS: + initialize quarks + +2005-10-06 14:01:44 +0000 Thomas Vander Stichele + + gst/gstpad.c: give events a chance to be handled by event probes when the pad is not linked + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_event_default_dispatch): + give events a chance to be handled by event probes when the pad + is not linked + +2005-10-06 13:55:43 +0000 Thomas Vander Stichele + + gst/gstevent.*: add string representations for event types + Original commit message from CVS: + * gst/gstevent.c: (gst_event_type_get_name), + (gst_event_type_to_quark), (gst_event_finalize), (gst_event_new): + * gst/gstevent.h: + add string representations for event types + +2005-10-06 13:42:56 +0000 Thomas Vander Stichele + + * gst/gstevent.h: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2005-10-06 13:24:28 +0000 Wim Taymans + + gst/elements/gstfilesink.c: Don't use NULL pointers. + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_file_sink_close_file): + Don't use NULL pointers. + +2005-10-06 09:49:42 +0000 Thomas Vander Stichele + + gst/: widen the debug category in output to fit the biggest one we have add a bus category and use it play with the c... + Original commit message from CVS: + * gst/gst_private.h: + * gst/gstbus.c: + * gst/gstelement.c: + * gst/gstinfo.c: + * gst/gstpluginfeature.c: + widen the debug category in output to fit the biggest one we have + add a bus category and use it + play with the colors + fix up some categories + +2005-10-06 07:42:41 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + first stab at reorganizing docs for pad + Original commit message from CVS: + first stab at reorganizing docs for pad + +2005-10-06 07:13:01 +0000 Thomas Vander Stichele + + gst/gstghostpad.c: add push activation of sink ghost pads. + Original commit message from CVS: + 2005-10-06 Thomas Vander Stichele + * gst/gstghostpad.c: (gst_ghost_pad_internal_do_activate_push): + add push activation of sink ghost pads. + Andye, please verify + +2005-10-05 22:35:14 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstpad.c: + doc updates + Original commit message from CVS: + doc updates + +2005-10-05 21:34:42 +0000 Thomas Vander Stichele + + gst/gstutils.c: fix a bug in the case where neither element has a pad + Original commit message from CVS: + * gst/gstutils.c: (gst_element_link_pads): + fix a bug in the case where neither element has a pad + * check/gst/gstelement.c: (GST_START_TEST), (gst_element_suite): + add a test for that case + +2005-10-05 17:01:44 +0000 Thomas Vander Stichele + + * check/gst/gstpad.c: + * tests/check/gst/gstpad.c: + unref our test buffers + Original commit message from CVS: + unref our test buffers + +2005-10-05 16:16:58 +0000 Thomas Vander Stichele + + gst/gstpad.c: emit have-data before checking for peers. This allows for probe handlers to connect elements. This he... + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_push), (gst_pad_push_event): + emit have-data before checking for peers. This allows + for probe handlers to connect elements. This helps autopluggers. + * check/gst/gstpad.c: (GST_START_TEST), (_probe_handler), + (gst_pad_suite): + add six checks, linked/unlinked with no/true/false probe + +2005-10-05 11:50:49 +0000 Thomas Vander Stichele + + * gst/gstobject.c: + indent ifdefs + Original commit message from CVS: + indent ifdefs + +2005-10-04 18:46:09 +0000 Wim Taymans + + gst/elements/: Protect last_message with lock. + Original commit message from CVS: + * gst/elements/gstfakesink.c: (gst_fake_sink_get_property), + (gst_fake_sink_event), (gst_fake_sink_preroll), + (gst_fake_sink_render), (gst_fake_sink_change_state): + * gst/elements/gstfakesrc.c: (gst_fake_src_event_handler), + (gst_fake_src_get_property), (gst_fake_src_create), + (gst_fake_src_stop): + * gst/elements/gstidentity.c: (gst_identity_stop): + Protect last_message with lock. + +2005-10-04 15:04:50 +0000 Edward Hervey + + gst/gstformat.h: Added precision in the comments for GST_FORMAT_DEFAULT + Original commit message from CVS: + * gst/gstformat.h: + Added precision in the comments for GST_FORMAT_DEFAULT + +2005-10-04 13:19:47 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + update uninstalled script + Original commit message from CVS: + update uninstalled script + +2005-10-04 12:02:34 +0000 Christian Schaller + + * gstreamer.spec.in: + remove some files that are no longer there from spec file + Original commit message from CVS: + remove some files that are no longer there from spec file + +2005-10-04 11:51:37 +0000 Tim-Philipp Müller + + tools/gst-launch.c: Don't try to run erroneous pipelines. + Original commit message from CVS: + * tools/gst-launch.c: (main): + Don't try to run erroneous pipelines. + +2005-10-04 11:10:04 +0000 Michael Smith + + gst/gsterror.c: Add another error string used in a few existing plugins. + Original commit message from CVS: + * gst/gsterror.c: (_gst_stream_errors_init): + Add another error string used in a few existing plugins. + * gst/gstplugin.c: + * gst/gstpluginfeature.c: (gst_plugin_feature_load): + * tools/gst-inspect.c: (print_element_info): + When a feature disappears from a plugin (and the feature exists in + the cached registry file), things went horribly wrong. This isn't a + complete fix, we should actually be removing the 'missing' features + from the features list when we load the actual plugin. That's not + yet implemented. + +2005-10-04 11:09:41 +0000 Julien Moutte + + gst/gstbus.c: We don't need this header. + Original commit message from CVS: + 2005-10-04 Julien MOUTTE + * gst/gstbus.c: We don't need this header. + +2005-10-03 17:57:32 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + back to head + Original commit message from CVS: + back to head + +=== release 0.9.3 === + +2005-10-03 17:47:21 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * README: + * configure.ac: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + release time + Original commit message from CVS: + release time + +2005-10-02 23:24:25 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_activate_push): There is a race condition whereby calling a pad's activatepush() function can s... + Original commit message from CVS: + 2005-10-03 Andy Wingo + * gst/gstpad.c (gst_pad_activate_push): There is a race condition + whereby calling a pad's activatepush() function can start a thread + that starts to push or pull before the pad gets the FLUSHING flag + unset. Hack around it by holding the stream lock until the flag is + set. Need to replace this with a proper solution. Together with + the ghost pad fixes, this fixes mp3 playing/tagreading. + +2005-10-02 23:21:04 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2005-10-02 23:20:26 +0000 Andy Wingo + + docs/design/part-gstghostpad.txt: Add a note about activation of proxy pads outside of ghost pads. + Original commit message from CVS: + 2005-10-03 Andy Wingo + * docs/design/part-gstghostpad.txt: Add a note about activation of + proxy pads outside of ghost pads. + * gst/gstghostpad.c: Implement the ghost pad activation design. + +2005-10-02 18:57:07 +0000 Andy Wingo + + gst/gstobject.h (GST_OBJECT_REFCOUNT_VALUE): Just use the int. + Original commit message from CVS: + 2005-10-02 Andy Wingo + * gst/gstobject.h (GST_OBJECT_REFCOUNT_VALUE): Just use the int. + It is volatile, after all. + * docs/design/part-gstghostpad.txt: Flesh out activation with + ghost pads. + * gst/base/gstbasesrc.c (gst_base_src_init): Use + GST_DEBUG_FUNCPTR. + +2005-10-02 18:30:27 +0000 Tim-Philipp Müller + + configure.ac: Fix (unused) AM_CONDITIONAL tests. + Original commit message from CVS: + * configure.ac: + Fix (unused) AM_CONDITIONAL tests. + +2005-10-01 17:11:07 +0000 Tim-Philipp Müller + + gst/gstutils.c: Add assertion that makes sure src_val is >=0, just like gst_query_new_convert() has. (#315895) + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstutils.c: (gst_pad_query_convert): + Add assertion that makes sure src_val is >=0, just like + gst_query_new_convert() has. (#315895) + +2005-09-30 15:43:03 +0000 Edward Hervey + + gst/elements/gsttee.c: Let's not iterate pads we're not interested in, it avoids getting sky-high refcounts on sinkpad. + Original commit message from CVS: + * gst/elements/gsttee.c: (gst_tee_do_push), (gst_tee_handle_buffer): + Let's not iterate pads we're not interested in, it avoids getting + sky-high refcounts on sinkpad. + +2005-09-30 08:29:02 +0000 Wim Taymans + + gst/gstelement.c: Small tweak, element in ASYNC remains ASYNC. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_set_state), + (gst_element_change_state): + Small tweak, element in ASYNC remains ASYNC. + +2005-09-30 08:00:12 +0000 Wim Taymans + + gst/base/gstbasesink.c: Only error is an error. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_change_state): + Only error is an error. + * gst/gstbin.c: (gst_bin_change_state): + Better debugging. + * gst/gstpad.c: (gst_pad_alloc_buffer), (gst_pad_chain): + Also call pad_block in pad alloc. + * gst/gstutils.c: (gst_flow_get_name): + Better debugging. + +2005-09-29 20:26:12 +0000 Tim-Philipp Müller + + gst/base/gstbasesrc.c: Fix documentation typos. Add some more debug info. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_get_range): + Fix documentation typos. Add some more debug info. + +2005-09-29 20:16:42 +0000 Thomas Vander Stichele + + * check/gst/gstpipeline.c: + * tests/check/gst/gstpipeline.c: + disable refcount checks until we track the dangling ref + Original commit message from CVS: + disable refcount checks until we track the dangling ref + +2005-09-29 19:45:27 +0000 David Schleef + + gst/gstplugin.c: Make some error messages more end-user friendly. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): Make some error messages + more end-user friendly. + * tools/gst-inspect.c: (main): Check if command-line argument is + a file and attempt to load that file as a plugin. + +2005-09-29 18:37:48 +0000 Thomas Vander Stichele + + check/: fix tests for the new warning + Original commit message from CVS: + * check/gst/gstbin.c: + * check/states/sinks.c: + fix tests for the new warning + * check/gst/gstpipeline.c: + add a test for pipeline and bus interaction + * gst/gstelement.c: + elements should be NULL if they get disposed; add a warning if not + +2005-09-29 18:35:38 +0000 Thomas Vander Stichele + + gst/gstobject.c: for 2.6 refcounting, make debug log more correct by printing the actual refcounts at the time of swa... + Original commit message from CVS: + * gst/gstobject.c: + for 2.6 refcounting, make debug log more correct by printing + the actual refcounts at the time of swap (Wim) + +2005-09-29 18:25:50 +0000 Thomas Vander Stichele + + * common: + * gst/gstbin.c: + * gst/gstbus.c: + * gst/gstmessage.c: + use message type names + Original commit message from CVS: + use message type names + +2005-09-29 16:06:18 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2005-09-29 16:04:31 +0000 Andy Wingo + + gst/gstbus.c (gst_bus_remove_signal_watch): New function, removes signal watches previously added via gst_bus_add_sig... + Original commit message from CVS: + 2005-09-29 Andy Wingo + * gst/gstbus.c (gst_bus_remove_signal_watch): New function, + removes signal watches previously added via + gst_bus_add_signal_watch. + (gst_bus_add_signal_watch): Don't return the source id, just store + it on the bus if there wasn't an id already. + * gst/gstbus.h (GstBus): Add a couple new fields. API changes for + add_signal_watch and remove_signal_watch. + +2005-09-29 15:39:22 +0000 Edward Hervey + + libs/gst/controller/gstcontroller.c: Better if we actually iterate the list :) + Original commit message from CVS: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_list): + Better if we actually iterate the list :) + +2005-09-29 13:07:37 +0000 Wim Taymans + + check/gst/gstbin.c: Change for new bus API. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Change for new bus API. + * check/gst/gstbus.c: (message_func_eos), (message_func_app), + (send_messages), (GST_START_TEST), (gstbus_suite): + Change for new bus signal API. + * gst/gstbus.c: (gst_bus_class_init), (gst_bus_have_pending), + (gst_bus_source_prepare), (gst_bus_source_check), + (gst_bus_create_watch), (gst_bus_add_watch_full), + (gst_bus_add_watch), (gst_bus_poll), (gst_bus_async_signal_func), + (gst_bus_sync_signal_handler), (gst_bus_add_signal_watch): + * gst/gstbus.h: + Remove support for multiple GSources operating on different + message types as it is too complex and unneeded when using + signals. + Added support for receiving signals from the bus. + +2005-09-29 12:37:38 +0000 Thomas Vander Stichele + + rename filter-caps to caps property + Original commit message from CVS: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/manual/advanced-dataaccess.xml: + * gst/elements/gstcapsfilter.c: + * gst/gstutils.c: + rename filter-caps to caps property + +2005-09-29 12:05:51 +0000 Tim-Philipp Müller + + gst/gstvalue.c: More robust fraction string parsing. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_deserialize_fraction): + More robust fraction string parsing. + * docs/pwg/appendix-porting.xml: + Mention gst_pad_use_explicit_caps() => gst_pad_use_fixed_caps() + +2005-09-29 10:56:57 +0000 Tim-Philipp Müller + + gst/gstcaps.c: Thou shalt not free a structure and then continue using it in the next loop iteration. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_do_simplify): + Thou shalt not free a structure and then continue using it + in the next loop iteration. + * check/gst/gstcaps.c: (check_fourcc_list), (test_simplify), + (gst_caps_suite): + Add test case for caps simplification. + +2005-09-29 09:44:35 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + remove two removed functions + Original commit message from CVS: + remove two removed functions + +2005-09-29 09:42:15 +0000 Wim Taymans + + check/gst/gstbin.c: Oops. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Oops. + +2005-09-29 09:39:36 +0000 Wim Taymans + + check/gst/gstbin.c: Add bus to bin. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Add bus to bin. + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), + (add_to_queue), (clear_queue), (reset_degree), (update_degree), + (find_element), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free), + (gst_bin_iterate_sorted), (gst_bin_element_set_state), + (gst_bin_change_state), (gst_bin_dispose): + A bin does not have a bus, it gets the bus from the parent. + * gst/gstelement.c: (gst_element_requires_clock), + (gst_element_provides_clock), (gst_element_is_indexable), + (gst_element_is_locked_state), (gst_element_change_state), + (gst_element_set_bus_func): + Small cleanups. + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_init), (gst_pipeline_provide_clock_func): + The pipeline provides a bus. + +2005-09-29 02:32:37 +0000 Johan Dahlin + + gst/gstmessage.c (gst_message_parse_state_changed): Use gst_structure_get_enum instead of gst_structure_get_int + Original commit message from CVS: + * gst/gstmessage.c (gst_message_parse_state_changed): Use + gst_structure_get_enum instead of gst_structure_get_int + * gst/gststructure.c (gst_structure_get_enum): Impl. + * gst/gststructure.h (gst_structure_get_enum): Add + * docs/gst/gstreamer-sections.txt: Ditto + +2005-09-29 01:57:00 +0000 Johan Dahlin + + gst/gstmessage.c (gst_message_new_state_changed): Use + Original commit message from CVS: + * gst/gstmessage.c (gst_message_new_state_changed): Use + GST_TYPE_STATE instead of G_TYPE_INT, mainly for language bindings + which does introspection. + Reviewed by Christian Schaller + +2005-09-28 18:14:13 +0000 Stefan Kost + + * ChangeLog: + fixed umlauts in ChangeLog again + Original commit message from CVS: + fixed umlauts in ChangeLog again + +2005-09-28 17:30:13 +0000 Stefan Kost + + gst/gstinfo.c: don't do dummy g_strdup()s + Original commit message from CVS: + * gst/gstinfo.c: (gst_debug_log_default): + don't do dummy g_strdup()s + * libs/gst/controller/gstcontroller.c: + (on_object_controlled_property_changed), + (gst_controlled_property_new), (gst_controller_new_valist), + (gst_controller_new_list), + (gst_controller_remove_properties_valist), (gst_controller_set), + (gst_controller_get), (gst_controller_sync_values), + (gst_controller_get_value_array), (_gst_controller_class_init), + (gst_controller_get_type): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstinterpolation.c: + (gst_controlled_property_find_timed_value_node): + convert // to /**/ comments + +2005-09-28 16:43:20 +0000 Wim Taymans + + gst/gstbus.*: Added async-message and sync-message signals to the bus. + Original commit message from CVS: + * gst/gstbus.c: (marshal_VOID__MINIOBJECT), (gst_bus_class_init), + (gst_bus_post), (poll_func), (gst_bus_async_signal_func), + (gst_bus_sync_signal_handler): + * gst/gstbus.h: + Added async-message and sync-message signals to the bus. + Added helper BusFunc to emit signals for all posted messages. + * gst/gstmessage.c: (gst_message_type_get_name), + (gst_message_type_to_quark), (gst_message_get_type): + * gst/gstmessage.h: + Register quarks for message names. + +2005-09-28 16:39:29 +0000 Stefan Kost + + added another constructor for language bindings + Original commit message from CVS: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist), + (gst_controller_new_list): + * libs/gst/controller/gstcontroller.h: + added another constructor for language bindings + +2005-09-28 15:45:21 +0000 Thomas Vander Stichele + + check/gst/gstpipeline.c: add another check + Original commit message from CVS: + * check/gst/gstpipeline.c: (GST_START_TEST), (gst_pipeline_suite): + add another check + * gst/gstbus.c: + add some doc + * gst/gstinfo.c: (_gst_debug_init): + slightly more readable color for refcount debugging + +2005-09-28 13:41:27 +0000 Wim Taymans + + gst/gstbin.c: Small doc fixes. get_clock -> provide_clock. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_provide_clock_func), + (add_to_queue), (clear_queue), (reset_degree), (update_degree), + (find_element), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free), + (gst_bin_iterate_sorted), (gst_bin_element_set_state), + (gst_bin_change_state), (gst_bin_dispose): + Small doc fixes. get_clock -> provide_clock. + * gst/gstelement.c: (gst_element_class_init), + (gst_element_provides_clock), (gst_element_provide_clock), + (gst_element_get_clock), (gst_element_commit_state), + (gst_element_lost_state): + * gst/gstelement.h: + Make get/set_clock() symetric. Add provide_clock vmethod since + that is actually what this function does. + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_change_state), (gst_pipeline_provide_clock_func), + (gst_pipeline_get_clock): + get_clock -> provide_clock. + +2005-09-28 13:05:12 +0000 Andy Wingo + + gst/base/gstbasesrc.c (gst_base_src_unlock): Comment a bit in lieu of real docs... + Original commit message from CVS: + 2005-09-28 Andy Wingo + * gst/base/gstbasesrc.c (gst_base_src_unlock): Comment a bit in + lieu of real docs... + * gst/elements/gstfdsrc.c: Cleaned up a bit. + +2005-09-28 12:52:51 +0000 Tim-Philipp Müller + + gst/elements/: Make element details static. + Original commit message from CVS: + * gst/elements/gstcapsfilter.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfdsink.c: + * gst/elements/gstfdsrc.c: + * gst/elements/gstfilesink.c: + * gst/elements/gstfilesrc.c: + * gst/elements/gstidentity.c: + * gst/elements/gsttee.c: + * gst/elements/gsttypefindelement.c: + Make element details static. + +2005-09-28 11:03:58 +0000 Wim Taymans + + gst/gstbin.c: Some documentation updates. + Original commit message from CVS: + * gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree), + (update_outdegree), (find_element), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free), + (gst_bin_iterate_sorted), (gst_bin_element_set_state), + (gst_bin_change_state), (gst_bin_dispose): + Some documentation updates. + Clean up dispose handlers. + * gst/gstobject.c: (gst_object_ref), (gst_object_unref): + * gst/gstpad.c: (gst_pad_dispose): + Clean up dispose handler. + * gst/gstpipeline.c: (gst_pipeline_change_state): + Removed spurious UNLOCK. + +2005-09-27 20:40:35 +0000 Stefan Kost + + added two new functions to the docs documents all undocumented GstXXXFlags completed some incomplete docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/base/gstbasesrc.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstobject.h: + * gst/gstpad.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstutils.h: + * gst/gstxml.h: + added two new functions to the docs + documents all undocumented GstXXXFlags + completed some incomplete docs + +2005-09-27 18:33:48 +0000 Thomas Vander Stichele + + gst/: remove now useless and leaky resurrection code in dispose + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_dispose): + * gst/gstelement.c: (gst_element_dispose): + remove now useless and leaky resurrection code in dispose + * gst/base/gstbasesrc.c: (gst_base_src_init): + * gst/gstelementfactory.c: (gst_element_factory_create): + * gst/gstobject.c: (gst_object_set_parent): + add some debugging + +2005-09-27 17:00:13 +0000 Wim Taymans + + docs/design/part-TODO.txt: Update TODO. + Original commit message from CVS: + * docs/design/part-TODO.txt: + Update TODO. + * gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree), + (update_outdegree), (find_element), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free), + (gst_bin_iterate_sorted), (gst_bin_element_set_state), + (gst_bin_change_state): + * gst/gstelement.h: + Remove element variable, we keep element info in the iterator now. + +2005-09-27 16:30:26 +0000 Andy Wingo + + libs/gst/dataprotocol/dataprotocol.c: Fix error-checking return values. + Original commit message from CVS: + 2005-09-27 Andy Wingo + * libs/gst/dataprotocol/dataprotocol.c: Fix error-checking return + values. + +2005-09-27 16:16:39 +0000 Wim Taymans + + check/gst/gstbin.c: Enable check that works now. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Enable check that works now. + * gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree), + (update_outdegree), (find_element), (gst_bin_sort_iterator_next), + (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free), + (gst_bin_iterate_sorted), (gst_bin_element_set_state), + (gst_bin_change_state): + * gst/gstbin.h: + Redid the state change algorithm using a topological sort algo. + Handles all cases correctly. + Exposed iterator for state change order. + * gst/gstelement.h: + Temp storage for state changes. Need to get rid of this soon. + +2005-09-27 15:37:40 +0000 Wim Taymans + + gst/: Leak fixes, the fold functions need to unref the passed object and _get_parent_*() returns ref to parent. + Original commit message from CVS: + * gst/elements/gsttee.c: (gst_tee_init), (gst_tee_do_push): + * gst/gstutils.c: (intersect_caps_func), (gst_pad_proxy_getcaps), + (link_fold_func), (gst_pad_proxy_setcaps): + Leak fixes, the fold functions need to unref the passed object and + _get_parent_*() returns ref to parent. + +2005-09-27 13:25:18 +0000 Tim-Philipp Müller + + check/gst/gstbuffer.c: Plug leak in test case and fix 'make check-valgrind' + Original commit message from CVS: + * check/gst/gstbuffer.c: (test_make_writable): + Plug leak in test case and fix 'make check-valgrind' + +2005-09-27 13:07:14 +0000 Tim-Philipp Müller + + gst/gstbuffer.c: Set READONLY flag on subbuffers, so that gst_buffer_make_writable() works correctly in all circumsta... + Original commit message from CVS: + * gst/gstbuffer.c: (gst_subbuffer_init): + Set READONLY flag on subbuffers, so that gst_buffer_make_writable() + works correctly in all circumstances (we could have just copied + the parent buffer's readonly flag, but conceptually it seems + cleaner to mark all subbuffers as read-only). (based on patch + by Alessandro Decina, #314710). + * check/gst/gstbuffer.c: (create_read_only_buffer), + (test_make_writable), (test_subbuffer_make_writable), + (gst_test_suite): + Add some tests for gst_buffer_make_writable(). + +2005-09-27 09:57:20 +0000 Wim Taymans + + gst/gstbin.c: use gst_object_has_ancestor(). + Original commit message from CVS: + * gst/gstbin.c: (bin_element_is_semi_sink), (gst_bin_change_state): + use gst_object_has_ancestor(). + * gst/gstobject.c: (gst_object_has_ancestor): + * gst/gstobject.h: + gst_object_has_ancestor() copied from gstbin.c as it is a + usefull function. + * tests/instantiate/create.c: (create_all_elements): + * tests/lat.c: (handoff_src), (handoff_sink): + * tests/sched/runxml.c: (main): + * tests/seeking/seeking1.c: (main): + * tests/threadstate/threadstate2.c: (bus_handler), (timeout_func), + (main): + Fix compilation of some tests. + +2005-09-27 09:29:04 +0000 Tim-Philipp Müller + + gst/gsterror.h: Remove comment. GST_TYPE_G_ERROR is here to stay, + Original commit message from CVS: + * gst/gsterror.h: + Remove comment. GST_TYPE_G_ERROR is here to stay, + G_TYPE_ERROR has been WONTFIX'ed by the GLib folks + (#316961, #300610). + +2005-09-26 18:22:07 +0000 Wim Taymans + + check/gst/gstbin.c: Added check that shows error in state change order. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST), (gst_bin_suite): + Added check that shows error in state change order. + +2005-09-26 17:46:27 +0000 Wim Taymans + + gst/gstbin.c: Make state change function use 3 queues again, we were adding elements in the wrong order. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_change_state): + Make state change function use 3 queues again, we were + adding elements in the wrong order. + * gst/gstghostpad.c: (gst_ghost_pad_do_unlink): + Some debug info, + * gst/gstpad.c: (gst_pad_dispose): + Added some debug info first. + +2005-09-26 17:40:39 +0000 Tim-Philipp Müller + + docs/design/: Replace all _pull_region() with _pull_range() + Original commit message from CVS: + * docs/design/draft-push-pull.txt: + * docs/design/part-events.txt: + * docs/design/part-overview.txt: + * docs/design/part-scheduling.txt: + Replace all _pull_region() with _pull_range() + +2005-09-26 16:19:27 +0000 Andy Wingo + + * gst/gstvalue.c: + try the fourth + Original commit message from CVS: + try the fourth + +2005-09-26 16:12:07 +0000 Andy Wingo + + * gst/gstvalue.c: + foo + Original commit message from CVS: + foo + +2005-09-26 16:07:54 +0000 Andy Wingo + + gst/gstvalue.c (_gst_value_initialize): Better fakeout. + Original commit message from CVS: + 2005-09-26 Andy Wingo + * gst/gstvalue.c (_gst_value_initialize): Better fakeout. + +2005-09-26 15:49:23 +0000 Andy Wingo + + check/gst-libs/controller.c: Update for controller api change. + Original commit message from CVS: + 2005-09-26 Andy Wingo + * check/gst-libs/controller.c: Update for controller api change. + +2005-09-26 15:43:30 +0000 Andy Wingo + + Remove memchunk benchmark stuff, this is taken over by GLib bug 118439. + Original commit message from CVS: + 2005-09-26 Andy Wingo + * configure.ac: + * tests/Makefile.am: + * tests/memchunk: Remove memchunk benchmark stuff, this is taken + over by GLib bug 118439. + * gst/base/gstbasesink.c (gst_base_sink_wait): Factor out the wait + routines to a function. + * docs/libs/gstreamer-libs-sections.txt: I am a good person today. + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstcontroller.h (gst_controller_sync_values) + (gst_object_sync_values): Renamed from sink_values. Ugh. + * libs/gst/controller/gsthelper.c: Update for __gst_controller_key. + * libs/gst/controller/gstcontroller.c (__gst_controller_key): + Renamed from controller_key, as it is exported. + * gst/gstvalue.c (_gst_value_initialize): Fake out the compiler. + +2005-09-26 15:03:43 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstpad.h: + * gst/gstpadtemplate.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstqueryutils.c: + * gst/gstqueryutils.h: + remove queryutils headers after moving the two used functions to gstquery. also fixes build problem for gstsiddec + Original commit message from CVS: + remove queryutils headers after moving the two used functions + to gstquery. also fixes build problem for gstsiddec + +2005-09-26 13:40:21 +0000 Michael Smith + + * ChangeLog: + * tools/gst-launch.1.in: + Correct syntax for debug option in gst-launch manpage + Original commit message from CVS: + Correct syntax for debug option in gst-launch manpage + +2005-09-26 11:21:42 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Some more debugging info. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_get_range), + (gst_base_src_is_seekable), (gst_base_src_change_state): + Some more debugging info. + +2005-09-25 18:34:49 +0000 Stefan Kost + + added more docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/base/gstbasetransform.h: + * gst/gstindex.h: + added more docs + +2005-09-25 12:11:39 +0000 Stefan Kost + + inlined the last two docs files removed the tmpl directory from cvs (no more conflicts here!) + Original commit message from CVS: + * docs/gst/.cvsignore: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * gst/gstpipeline.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + inlined the last two docs files + removed the tmpl directory from cvs (no more conflicts here!) + +2005-09-25 11:19:22 +0000 Stefan Kost + + inlined two more docs factored gstpadtemplate out of gstpad + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * gst/Makefile.am: + * gst/gstpad.c: (gst_pad_class_init), (gst_pad_dispose), + (gst_pad_finalize), (gst_pad_set_pad_template): + * gst/gstpad.h: + * gst/gstpadtemplate.c: (gst_pad_template_get_type), + (gst_pad_template_class_init), (gst_pad_template_init), + (gst_pad_template_dispose), (name_is_valid), + (gst_static_pad_template_get), (gst_pad_template_new), + (gst_static_pad_template_get_caps), (gst_pad_template_get_caps), + (gst_pad_template_pad_created): + * gst/gstpadtemplate.h: + inlined two more docs + factored gstpadtemplate out of gstpad + +2005-09-24 14:35:07 +0000 Tim-Philipp Müller + + check/gst/gstbin.c: Fix test case: we can't rely on a fixed state change order when going from READY => PAUSED becaus... + Original commit message from CVS: + * check/gst/gstbin.c: (test_children_state_change_order_flagged_sink), + (test_children_state_change_order_semi_sink): + Fix test case: we can't rely on a fixed state change order when + going from READY => PAUSED because the sink might commit its + new state first when the first buffer created by the source + reaches the sink before the source has finished its change state. + (Test case still fails at times, see #316856, comment 5 onwards) + +2005-09-24 14:14:03 +0000 Wim Taymans + + Various documentation updates. + Original commit message from CVS: + * docs/design/part-events.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * docs/design/part-overview.txt: + * docs/design/part-segments.txt: + * gst/gstbin.c: + * gst/gstbuffer.c: + * gst/gstclock.c: + * gst/gstelement.c: + * gst/gstevent.c: + * gst/gstfilter.c: + * gst/gstiterator.c: + Various documentation updates. + +2005-09-24 11:41:01 +0000 Thomas Vander Stichele + + gst/gstclock.h: Well, that's embarassing. Luckily we weren't using + Original commit message from CVS: + * gst/gstclock.h: + Well, that's embarassing. Luckily we weren't using + GST_CLOCK_DIFF anywhere. + +2005-09-23 18:08:59 +0000 Thomas Vander Stichele + + common/gtk-doc.mak: don't fail on building XML, FC4 slave shows a bunch of doc missing bits that I don't get + Original commit message from CVS: + * common/gtk-doc.mak: + don't fail on building XML, FC4 slave shows a bunch of doc + missing bits that I don't get + * gst/gstpad.c: + * gst/gstpipeline.c: + * gst/gststructure.c: + some doc updates + +2005-09-23 18:02:18 +0000 Tim-Philipp Müller + + Add blurb about how the bus goes into flushing mode and drops all messages when its bin goes from READY into NULL state. + Original commit message from CVS: + * docs/design/part-gstbin.txt: + * docs/design/part-gstbus.txt: + * gst/gstbus.c: + Add blurb about how the bus goes into flushing mode and + drops all messages when its bin goes from READY into NULL + state. + +2005-09-23 17:46:06 +0000 Thomas Vander Stichele + + add a method to get a GstClockTime out of a structure + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: (gst_structure_get_clock_time): + * gst/gststructure.h: + add a method to get a GstClockTime out of a structure + +2005-09-23 17:17:42 +0000 Tim-Philipp Müller + + check/gst/gstbin.c: Added test to check state change order in bins (can still be made to fail here under heavy disk l... + Original commit message from CVS: + * check/gst/gstbin.c: (test_children_state_change_order_flagged_sink), + (test_children_state_change_order_semi_sink), (gst_bin_suite): + Added test to check state change order in bins (can still be made + to fail here under heavy disk load; bails out with 'Push on pad + fakesink:sink0, but it was not activated in push mode'). + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_change_state): + Fix state change order when there is only a semi sink (#316856) + * gst/gstbus.c: (gst_bus_class_init): + Use _class_peek_parent(), not _class_ref(); fix docs to say + 'default main context' instead of 'mainloop' where that is + what's meant. + * gst/gstelement.c: (gst_element_commit_state), + (gst_element_set_state): + Fix typos in debug messages + +2005-09-23 16:35:43 +0000 Thomas Vander Stichele + + * common: + * docs/gst/gstreamer-sections.txt: + * docs/libs/gstreamer-libs-sections.txt: + * gst/gstclock.h: + * gst/gstelement.h: + * gst/gstinfo.h: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstvalue.c: + fix docs + Original commit message from CVS: + fix docs + +2005-09-23 15:48:14 +0000 Thomas Vander Stichele + + * gst/gstpluginfeature.c: + don't break docs build + Original commit message from CVS: + don't break docs build + +2005-09-23 15:36:28 +0000 Thomas Vander Stichele + + various doc updates + Original commit message from CVS: + * docs/README: + * gst/gstpad.c: (gst_pad_class_init), (gst_pad_chain): + * gst/gstpluginfeature.c: + * gst/gstutils.c: + various doc updates + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + change an assert into an error until it gets fixed properly + +2005-09-23 14:31:21 +0000 Stefan Kost + + inlined 3 more biiiig doc files and added some missing docs on the fly + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstobject.sgml: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstobject.c: (gst_object_class_init): + * gst/gstobject.h: + inlined 3 more biiiig doc files and added some missing docs on the fly + +2005-09-23 11:41:30 +0000 Thomas Vander Stichele + + put back source in registry. add checks for find_plugin. + Original commit message from CVS: + * check/gst/.cvsignore: + * check/gst/gstplugin.c: (GST_START_TEST), (gst_plugin_suite): + * gst/gstregistryxml.c: (load_plugin), + (gst_registry_xml_save_plugin): + put back source in registry. add checks for find_plugin. + * testsuite/states/bin.c: (assert_state), (empty_bin), + (test_adding_one_element), (main): + * testsuite/states/locked.c: (main): + some compile/run fixes + +2005-09-22 20:02:11 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/gstvalue.c: + * tests/check/gst/gstvalue.c: + fix leak in the test itself + Original commit message from CVS: + fix leak in the test itself + +2005-09-22 18:07:22 +0000 Wim Taymans + + gst/base/gstbasesink.c: Prepare for more accurate position reporting and query handling. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_send_event), (gst_base_sink_peer_query), + (gst_base_sink_query): + Prepare for more accurate position reporting and query + handling. + * gst/gstelement.c: (gst_element_send_event), + (gst_element_set_state): + Add some comment. + +2005-09-22 17:40:42 +0000 Wim Taymans + + gst/gstquery.*: More documentation. + Original commit message from CVS: + * gst/gstquery.c: (gst_query_new_segment), (gst_query_set_segment), + (gst_query_parse_segment): + * gst/gstquery.h: + More documentation. + Add segment query for future use. + +2005-09-22 16:51:27 +0000 Wim Taymans + + gst/gstbin.c: Some more debug info. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func): + Some more debug info. + * gst/gstelement.c: (gst_element_send_event): + Simplify send_event + * gst/gstelement.h: + Don't know how flags got broken. + * gst/gstquery.h: + Added new query. + +2005-09-22 15:38:12 +0000 Tim-Philipp Müller + + check/gst/gstvalue.c: Add simplistic test suite for GST_TYPE_DATE serialisation and deserialisation. + Original commit message from CVS: + * check/gst/gstvalue.c: (test_date), (gst_value_suite): + Add simplistic test suite for GST_TYPE_DATE serialisation and + deserialisation. + +2005-09-22 15:08:02 +0000 Tim-Philipp Müller + + Add GST_TYPE_DATE, a boxed type that wraps GDate, and the usual bunch of utility functions along with a hack that che... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gststructure.c: (gst_structure_set_valist), + (gst_structure_get_date): + * gst/gststructure.h: + * gst/gstvalue.c: (gst_value_set_date), (gst_value_get_date), + (gst_date_copy), (gst_value_compare_date), + (gst_value_serialize_date), (gst_value_deserialize_date), + (gst_value_transform_date_string), + (gst_value_transform_string_date), (_gst_value_initialize): + * gst/gstvalue.h: + Add GST_TYPE_DATE, a boxed type that wraps GDate, and the usual + bunch of utility functions along with a hack that checks that + developers don't accidentally use G_TYPE_DATE where GST_TYPE_DATE + is required. Part of the grand scheme in #170777. + +2005-09-22 12:05:05 +0000 Andy Wingo + + gst/gstconfig.h.in: Psych out gtk-doc. + Original commit message from CVS: + 2005-09-22 Andy Wingo + * gst/gstconfig.h.in: Psych out gtk-doc. + * docs/gst/gstreamer-sections.txt: Add GST_HAVE_GLIB_2_8. + * check/Makefile.am (check_PROGRAMS): Add gstplugin to the tests. + * tools/gst-inspect.c (print_element_list): Plug some + inconsequential leaks. + * gst/gstregistry.c (gst_registry_get_default): Doc. + * gst/gsttypefindfactory.c (gst_type_find_factory_call_function): + * gst/gstelementfactory.c (gst_element_factory_create): + * gst/gstindexfactory.c (gst_index_factory_create): Update for + refcount changes. + * gst/gstpluginfeature.c (gst_plugin_feature_list_free): Doc. + (gst_plugin_feature_load): Doc, don't eat refs. + * gst/gstplugin.c (gst_plugin_load): Doc, don't eat refs. + (gst_plugin_list_free): Doc. + (gst_plugin_load_file): Doc updates. + +2005-09-22 09:30:41 +0000 Andy Wingo + + gst/gstbuffer.c (gst_buffer_get_caps): Like all our _get accessors returning refcounted objects, return a ref. + Original commit message from CVS: + 2005-09-22 Andy Wingo + * gst/gstbuffer.c (gst_buffer_get_caps): Like all our _get + accessors returning refcounted objects, return a ref. + * check/gst/gstbuffer.c (GST_START_TEST): Use refcount-idempotent + accessor for caps. IDEMPOTENCE. Oh yes. + +2005-09-21 21:39:06 +0000 Tim-Philipp Müller + + gst/gstinfo.c: Add mutex to serialise access to the hash table with the function pointer => function name string mapp... + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller + * gst/gstinfo.c: (_gst_debug_nameof_funcptr), + (_gst_debug_register_funcptr): + Add mutex to serialise access to the hash table with + the function pointer => function name string mapping; + make that hash table static scope (#316809). + * gst/registries/.cvsignore: + Remove left-over file. + +2005-09-21 15:55:12 +0000 Tim-Philipp Müller + + docs/pwg/appendix-porting.xml: And something about newsegment events and caps-on-buffers to the porting guide (feel f... + Original commit message from CVS: + * docs/pwg/appendix-porting.xml: + And something about newsegment events and caps-on-buffers to + the porting guide (feel free to improve). + +2005-09-21 13:24:33 +0000 Andy Wingo + + * ChangeLog: + * check/gst/gstutils.c: + * tests/check/gst/gstutils.c: + Test that removing probes from within the probe functions works. + Original commit message from CVS: + (test_buffer_probe_once): Test that removing probes from within + the probe functions works. + +2005-09-21 13:11:22 +0000 Andy Wingo + + check/gst/gstutils.c (test_buffer_probe_n_times): Add tests for data and event probes on the same pad. + Original commit message from CVS: + 2005-09-21 Andy Wingo + * check/gst/gstutils.c (test_buffer_probe_n_times): Add tests for + data and event probes on the same pad. + +2005-09-21 12:21:10 +0000 Andy Wingo + + check/gst/gstutils.c: New file. + Original commit message from CVS: + 2005-09-21 Andy Wingo + * check/gst/gstutils.c: New file. + (test_buffer_probe_n_times): A simple buffer probe test. More to + come, foolios. + * gst/gstutils.c (gst_pad_add_buffer_probe): Connect to + have-data::buffer, not have-data. + (gst_pad_add_event_probe): Likewise for have-data::event. + (gst_pad_add_data_probe): More docs. The part about 'resolving the + peer' isn't quite right yet though. + (gst_pad_remove_buffer_probe, gst_pad_remove_event_probe) + (gst_pad_remove_data_probe): Change to take the guint handler_id + as their arg, not the function+data, which is more glib-like. + * gst/gstpad.c (gst_pad_emit_have_data_signal): Add a detail to + the signal emission to indicate if the data is a buffer or an + event. + (gst_pad_get_type): Initialize buffer and event quarks. + (gst_pad_class_init): have-data is now a detailed signal, yes it + is. + +2005-09-21 11:52:04 +0000 Tim-Philipp Müller + + gst/: Don't put functional code in g_return_if_fail() or g_return_val_if_fail() statements, otherwise things will bre... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_transform_size): + * gst/gstutils.c: (gst_util_set_value_from_string), + (gst_util_set_object_arg): + Don't put functional code in g_return_if_fail() or + g_return_val_if_fail() statements, otherwise things will + break when G_DISABLE_CHECKS is defined during compilation. + +2005-09-21 09:48:40 +0000 Stefan Kost + + inlied another one and added some obvious docs + Original commit message from CVS: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstvalue.sgml: + * gst/gstvalue.c: + * gst/gstvalue.h: + inlied another one and added some obvious docs + +2005-09-21 09:13:32 +0000 Wim Taymans + + gst/elements/gstfdsrc.*: Properly implement fdsrc. Removed signal and timeout, better implemented somewhere else. + Original commit message from CVS: + * gst/elements/gstfdsrc.c: (gst_fdsrc_class_init), + (gst_fdsrc_init), (gst_fdsrc_start), (gst_fdsrc_stop), + (gst_fdsrc_unlock), (gst_fdsrc_set_property), + (gst_fdsrc_get_property), (gst_fdsrc_create): + * gst/elements/gstfdsrc.h: + Properly implement fdsrc. Removed signal and timeout, + better implemented somewhere else. + +2005-09-21 08:58:48 +0000 Stefan Kost + + inlined more docs + Original commit message from CVS: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * gst/gstinterface.c: + inlined more docs + +2005-09-21 08:40:55 +0000 Stefan Kost + + docs/gst/: remove obsolete doc file + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstenumtypes.sgml: + remove obsolete doc file + +2005-09-21 07:37:02 +0000 David Schleef + + gst/gstelementfactory.c: Drink a little beer, fix a little leak. + Original commit message from CVS: + * gst/gstelementfactory.c: (gst_element_factory_make): Drink a + little beer, fix a little leak. + +2005-09-20 20:54:37 +0000 Stefan Kost + + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gstvalue.sgml: + remove files + Original commit message from CVS: + remove files + +2005-09-20 20:40:00 +0000 Stefan Kost + + more docs inlined, splitted gstindex.{c,h} + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstelement.h: + * gst/gstindex.c: (gst_index_class_init): + * gst/gstindex.h: + * gst/gstindexfactory.c: (gst_index_factory_get_type), + (gst_index_factory_class_init), (gst_index_factory_init), + (gst_index_factory_finalize), (gst_index_factory_new), + (gst_index_factory_destroy), (gst_index_factory_find), + (gst_index_factory_create), (gst_index_factory_make): + * gst/gstindexfactory.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist): + more docs inlined, splitted gstindex.{c,h} + +2005-09-20 20:19:52 +0000 Thomas Vander Stichele + + * ChangeLog: + * libs/gst/controller/gstcontroller.c: + fix a leak in controller + Original commit message from CVS: + fix a leak in controller + +2005-09-20 19:16:43 +0000 Tim-Philipp Müller + + gst/elements/gstfilesink.c: Set sync to FALSE by default. + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_file_sink_init): + Set sync to FALSE by default. + +2005-09-20 17:38:51 +0000 Wim Taymans + + gst/base/gstbasesink.c: Make sync property settable from subclass. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init): + Make sync property settable from subclass. + * gst/elements/gstfakesink.c: (gst_fake_sink_init), + (gst_fake_sink_change_state): + Set sync to FALSE by default. + +2005-09-20 17:30:35 +0000 Wim Taymans + + The timeout handler should have lower priority than the source so we don't timeout before popping a message with 0 ti... + Original commit message from CVS: + * gst/gstbus.c: (poll_func), (poll_timeout), (gst_bus_poll): + * tools/gst-launch.c: (main): + The timeout handler should have lower priority than the source + so we don't timeout before popping a message with 0 timeout. + Dump error messages after failed state change. + +2005-09-20 17:21:13 +0000 Tim-Philipp Müller + + tools/gst-inspect.c: Fix two typos. + Original commit message from CVS: + * tools/gst-inspect.c: (print_element_properties_info): + Fix two typos. + +2005-09-20 15:45:42 +0000 Thomas Vander Stichele + + remove the sync property from fakesink. + Original commit message from CVS: + * check/gst/gstevent.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesink.h: + remove the sync property from fakesink. + has the side effect of setting sync TRUE + for fakesink, which is a change. Anyone who knows how + to fix this nicely in a GObject-y way, feel free. + +2005-09-20 15:19:08 +0000 Stefan Kost + + docs/gst/gstreamer-docs.sgml: remove probe refsection + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + remove probe refsection + +2005-09-20 12:50:23 +0000 Stefan Kost + + check/Makefile.am: disable valgrinding the controller test again + Original commit message from CVS: + * check/Makefile.am: + disable valgrinding the controller test again + * docs/gst/gstreamer-sections.txt: + update for api-changes + +2005-09-20 12:05:47 +0000 Wim Taymans + + gst/base/gstbasesink.*: Added sync property to basesink to disable clock sync. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_set_property), (gst_base_sink_get_property), + (gst_base_sink_do_sync): + * gst/base/gstbasesink.h: + Added sync property to basesink to disable clock sync. + +2005-09-20 11:09:50 +0000 Andy Wingo + + gst/gstelementfactory.c (gst_element_factory_create): Avoid eating the caller's refcount. + Original commit message from CVS: + 2005-09-20 Andy Wingo + * gst/gstelementfactory.c (gst_element_factory_create): Avoid + eating the caller's refcount. + * gst/gstobject.h (GST_OBJECT_REFCOUNT) + (GST_OBJECT_REFCOUNT_VALUE): Conditionally fondle the right + refcount. + * gst/gstconfig.h.in (GST_HAVE_GLIB_2_8): + * configure.ac (GST_HAVE_GLIB_2_8_DEFINE): Make the availability + of GLib 2.8 public, so we can know which refcount to check in + tests. + * gst/gstobject.c: Use the GST_HAVE_GLIB_2_8 define. + (gst_object_init): Only set the gst refcount if we're going ahead + with the refcount hack. + +2005-09-20 10:41:03 +0000 Stefan Kost + + more leaks plumbed, added more debug-logging + Original commit message from CVS: + * check/gst-libs/controller.c: (plugin_init), (GST_START_TEST): + * libs/gst/controller/gstcontroller.c: (gst_controller_new_valist): + more leaks plumbed, added more debug-logging + * gst/gstmacros.h: + whitespace fix + +2005-09-20 09:47:13 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstmessage.c: + remove include of removed header + Original commit message from CVS: + remove include of removed header + +2005-09-20 09:28:56 +0000 Thomas Vander Stichele + + gst/gstclock.c: Commit from the Political Party For More Atomic CVS Commits, so that people don't waste too much of t... + Original commit message from CVS: + * gst/gstclock.c: (_gst_clock_id_free): + Commit from the Political Party For More Atomic CVS Commits, + so that people don't waste too much of their day fishing + out obvious leaks out of massive commits. + Oh, and fix a pretty damn obvious leak in the memchunk + removal code. + +2005-09-20 09:23:39 +0000 Stefan Kost + + check/: plug mem-leak, re-add to valgrindable tests + Original commit message from CVS: + * check/Makefile.am: + * check/gst-libs/controller.c: (plugin_init), (GST_START_TEST): + plug mem-leak, re-add to valgrindable tests + +2005-09-20 09:08:25 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstplugin.h: + unbreak the build for those who have chronic arthritis and typing "make check" is just too taxing on the hands + Original commit message from CVS: + unbreak the build for those who have chronic arthritis + and typing "make check" is just too taxing on the hands + +2005-09-20 08:25:32 +0000 Andy Wingo + + gst/gst.h: Re-add marshal to gst.h's include list -- if we really want it out, you should fix plugins at the same time. + Original commit message from CVS: + 2005-09-20 Andy Wingo + * gst/gst.h: Re-add marshal to gst.h's include list -- if we + really want it out, you should fix plugins at the same time. + +2005-09-20 07:32:48 +0000 Stefan Kost + + added missing symbols to api docs disable ref-count hack if we have glib >= 2.8 + Original commit message from CVS: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * gst/gstobject.c: + added missing symbols to api docs + disable ref-count hack if we have glib >= 2.8 + +2005-09-20 06:28:33 +0000 David Schleef + + docs/gst/Makefile.am: Ignore a few more internal headers + Original commit message from CVS: + * docs/gst/Makefile.am: Ignore a few more internal headers + * docs/gst/gstreamer-docs.sgml: Remove old sections + * docs/gst/gstreamer-sections.txt: Remove old sections + * docs/gst/tmpl/gstobject.sgml: update + * docs/gst/tmpl/gstplugin.sgml: update + * docs/gst/tmpl/gstpluginfeature.sgml: update + * docs/random/ds/0.9-suggested-changes: update. + * gst/Makefile.am: remove memchunk and trashstack, since they're + not used. + * gst/gst.c: (gst_deinit): rename gst_registry_deinit to _cleanup + * gst/gst.h: don't include some headers + * gst/gstchildproxy.c: add gstmarshal.h + * gst/gstclock.c: Don't use memchunks + * gst/gstminiobject.c: Add some docs + * gst/gstobject.c: remove DESTROYED flag, since it's redundant + * gst/gstobject.h: same + * gst/gstplugin.c: include gstmacros.h + * gst/gstplugin.h: don't include gstmacros.h, since it's private + * gst/gstquery.c: don't use memchunks + * gst/gstregistry.c: rename gst_registry_deinit() + * gst/gstregistry.h: same + +2005-09-20 05:13:30 +0000 David Schleef + + docs/libs/gstreamer-libs-docs.sgml: Remove docs for getbits + Original commit message from CVS: + * docs/libs/gstreamer-libs-docs.sgml: Remove docs for getbits + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/tmpl/gstgetbits.sgml: + * docs/libs/tmpl/gstputbits.sgml: + +2005-09-20 00:27:37 +0000 Jan Schmidt + + check/generic/states.c: Add a sleep to ensure elements have a chance to start their pad tasks before shutdown. Reduce... + Original commit message from CVS: + * check/generic/states.c: (GST_START_TEST), (states_suite): + Add a sleep to ensure elements have a chance to start their + pad tasks before shutdown. Reduces racy test results. + * gst/elements/gstfdsrc.c: (gst_fdsrc_init), (gst_fdsrc_create): + Time out the select every now and then to check for shutdown. + +2005-09-19 20:01:45 +0000 Tim-Philipp Müller + + win32/gstenumtypes.*: Update. + Original commit message from CVS: + * win32/gstenumtypes.c: + * win32/gstenumtypes.h: + Update. + +2005-09-19 16:32:44 +0000 Wim Taymans + + gst/gstpipeline.c: Automatically PAUSE and RESUME a pipeline when a flushing seek is performed. + Original commit message from CVS: + * gst/gstpipeline.c: (do_pipeline_seek), (gst_pipeline_send_event): + Automatically PAUSE and RESUME a pipeline when a flushing seek + is performed. + Removed old files. + +2005-09-19 16:28:58 +0000 Thomas Vander Stichele + + * gst/gstbus.c: + whitespace fix + Original commit message from CVS: + whitespace fix + +2005-09-19 15:12:25 +0000 Andy Wingo + + gst/gstregistry.h: Spacing fixen. + Original commit message from CVS: + 2005-09-19 Andy Wingo + * gst/gstregistry.h: Spacing fixen. + +2005-09-19 14:55:26 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Handle state change failure more correctly. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_change_state): + Handle state change failure more correctly. + +2005-09-19 14:41:57 +0000 Thomas Vander Stichele + + check/: enable cleanup again after fixing the leak + Original commit message from CVS: + * check/Makefile.am: + * check/pipelines/cleanup.c: (run_pipeline): + * check/pipelines/simple_launch_lines.c: (run_pipeline), + (GST_START_TEST): + enable cleanup again after fixing the leak + * docs/README: + some more info on docs + +2005-09-19 14:20:37 +0000 Thomas Vander Stichele + + * gst/gstplugin.c: + don't complain about my ARM .so files. Another reason why it does make sense to have plugins follow a standard file ... + Original commit message from CVS: + don't complain about my ARM .so files. Another reason why it does make sense + to have plugins follow a standard file name pattern like libgst(whatever).so + +2005-09-19 14:09:54 +0000 Thomas Vander Stichele + + check/Makefile.am: re-enable tests now that leaks are plugged + Original commit message from CVS: + * check/Makefile.am: + re-enable tests now that leaks are plugged + * check/gst/gst.c: + * check/gst/gstbin.c: + * check/gst/gstpipeline.c: + add some more tests while fixing leaks + * common/check.mak: + make sure binaries are uptodate when valgrinding/gdbing + * gst/gst.c: + * gst/gstelementfactory.c: + remove a ref too many, and add a FIXME for when we get + round to disposing of classes + * gst/gstplugin.c: + fix the refcounting when loading a plugin from a file and + the code pretends that the pointer is the same even though + of course it can change + * gst/gstpluginfeature.c: + unref plugins marked cached (a bit confusing as a name) + as the docs state should be done + various doc additions to explain refcounting + * gst/gstregistry.c: + * gst/gstregistryxml.c: + debugging + +2005-09-19 14:09:37 +0000 Christian Schaller + + * gstreamer.spec.in: + update spec file + Original commit message from CVS: + update spec file + +2005-09-19 11:18:03 +0000 Wim Taymans + + GstBusHandler -> GstBusFunc, return value has the same meaning as any other GSource (FALSE == remove source). + Original commit message from CVS: + * check/gst/gstbin.c: (pop_messages), (GST_START_TEST): + * check/gst/gstbus.c: (message_func_eos), (message_func_app), + (send_messages), (GST_START_TEST), (gstbus_suite): + * check/gst/gstpipeline.c: (GST_START_TEST): + * check/pipelines/cleanup.c: (run_pipeline): + * check/pipelines/simple_launch_lines.c: (run_pipeline), + (GST_START_TEST): + * gst/gstbus.c: (gst_bus_have_pending), (gst_bus_source_prepare), + (gst_bus_source_check), (gst_bus_source_dispatch), + (gst_bus_create_watch), (gst_bus_add_watch_full), + (gst_bus_add_watch), (poll_func), (poll_timeout), (gst_bus_poll): + * gst/gstbus.h: + * tools/gst-launch.c: (event_loop): + * tools/gst-md5sum.c: (event_loop): + GstBusHandler -> GstBusFunc, return value has the same meaning as + any other GSource (FALSE == remove source). + _add_watch() and _add_watch_full() now take a MessageType mask to + only handle specific types of messages. + _poll() returns the GstMessage instead of the message type to avoid + race conditions. + _have_pending() takes a MessageType mask now too. + Added testsuite for multiple bus watches. + Fix testsuites and applications for new bus API. + +2005-09-18 22:15:23 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * tests/check/Makefile.am: + mark a bunch of the tests as to fix until we fix them + Original commit message from CVS: + mark a bunch of the tests as to fix until we fix them + +2005-09-18 21:40:58 +0000 Thomas Vander Stichele + + common/check.mak: use GST_PLUGIN settings for valgrind tests as well, so we're valgrinding the correct thing + Original commit message from CVS: + * common/check.mak: + use GST_PLUGIN settings for valgrind tests as well, so we're + valgrinding the correct thing + * gst/gst.c: (init_post): + plug another leak + +2005-09-18 21:24:55 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/gst.c: + * gst/gst.c: + * gst/gstelementfactory.c: + * gst/gstindex.c: + * gst/gstobject.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistryxml.c: + * tests/check/gst/gst.c: + various cleanups and memleak plugging. make valgrind is happy now. + Original commit message from CVS: + various cleanups and memleak plugging. make valgrind is happy now. + +2005-09-18 21:23:13 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/.gitignore: + * common: + * tests/check/gst/.gitignore: + add check-valgrind target + Original commit message from CVS: + add check-valgrind target + +2005-09-18 09:15:10 +0000 Thomas Vander Stichele + + * gst/gstregistry.c: + loading a plugin can return NULL + Original commit message from CVS: + loading a plugin can return NULL + +2005-09-18 07:41:28 +0000 David Schleef + + tools/gst-inspect.c: Revert the GOption code. + Original commit message from CVS: + * tools/gst-inspect.c: Revert the GOption code. + +2005-09-18 06:59:25 +0000 David Schleef + + check/Makefile.am: Fix environment variables. + Original commit message from CVS: + * check/Makefile.am: Fix environment variables. + * check/gst/gstplugin.c: Fix for API changes. + * tools/gst-inspect.c: Fix for API changes. + * tools/gst-xmlinspect.c: Fix for API changes. + * gst/gstelementfactory.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistryxml.c: + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/indexers/gstfileindex.c: + * gst/indexers/gstmemindex.c: + * gst/schedulers/Makefile.am: + Change registry to keep track of both plugins and features, + removing the feature tracking from plugins themselves. + +2005-09-17 18:14:40 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + add valgrind target; disable gstplugin until it passes + Original commit message from CVS: + add valgrind target; disable gstplugin until it passes + +2005-09-17 18:11:27 +0000 Thomas Vander Stichele + + * Makefile.am: + * check/Makefile.am: + * common: + * tests/check/Makefile.am: + add valgrind target; disable gstplugin until it passes + Original commit message from CVS: + add valgrind target; disable gstplugin until it passes + +2005-09-16 11:24:10 +0000 Thomas Vander Stichele + + * gst/gstplugin.h: + add mising include + Original commit message from CVS: + add mising include + +2005-09-16 08:17:49 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + set the right var + Original commit message from CVS: + set the right var + +2005-09-16 08:14:54 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * tests/check/Makefile.am: + * tools/gst-register.1.in: + remove gst-register + Original commit message from CVS: + remove gst-register + +2005-09-16 04:54:24 +0000 David Schleef + + Getting tired of debugging. Disabled all the unreffing of plugins and features, which fixes the segfaults, but of co... + Original commit message from CVS: + * check/gst/gstplugin.c: + * gst/gstelementfactory.c: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstregistry.c: + Getting tired of debugging. Disabled all the unreffing of + plugins and features, which fixes the segfaults, but of + course leaks like crazy. At least playbin works. + +2005-09-16 03:46:14 +0000 David Schleef + + check/gst/gstplugin.c: More testing + Original commit message from CVS: + * check/gst/gstplugin.c: (register_check_elements), + (GST_START_TEST), (peek), (suggest), (gst_plugin_suite): + More testing + * gst/elements/gsttypefindelement.c: Fix refcounting. + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsttypefindfactory.h: + +2005-09-16 00:37:51 +0000 Thomas Vander Stichele + + * check/gst/gstplugin.c: + * tests/check/gst/gstplugin.c: + unverbosify + Original commit message from CVS: + unverbosify + +2005-09-16 00:08:15 +0000 Thomas Vander Stichele + + * gst/base/gstbasesrc.h: + * libs/gst/base/gstbasesrc.h: + some whitespace to trigger a build + Original commit message from CVS: + some whitespace to trigger a build + +2005-09-16 00:02:27 +0000 David Schleef + + gst/gstindex.c: get refcounting correct. + Original commit message from CVS: + * gst/gstindex.c: get refcounting correct. + * gst/gstregistry.c: Handle the case where a feature/plugin is + not found. + +2005-09-15 23:51:24 +0000 David Schleef + + check/: Add test + Original commit message from CVS: + * check/Makefile.am: + * check/gst/gstplugin.c: Add test + * gst/gstplugin.c: Fix problems noticed by testsuite + * gst/gstplugin.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + +2005-09-15 20:56:30 +0000 David Schleef + + gst/gstplugin.c: Implement semi-decent recounting and locking in plugins and plugin features. + Original commit message from CVS: + * gst/gstplugin.c: Implement semi-decent recounting and locking + in plugins and plugin features. + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + +2005-09-15 14:21:08 +0000 Michael Smith + + * ChangeLog: + * common: + * gst/gstregistry.c: + Implement missing function. This is enough to get the basics of typefinding working - oggdemux succeeds now. decodebi... + Original commit message from CVS: + Implement missing function. This is enough to get the basics of + typefinding working - oggdemux succeeds now. decodebin is still broken. + +2005-09-15 05:58:37 +0000 David Schleef + + configure.ac: Add -no-undefined to GST_PLUGIN_LDFLAGS (bug #316076) + Original commit message from CVS: + * configure.ac: Add -no-undefined to GST_PLUGIN_LDFLAGS (bug + #316076) + * gst/base/Makefile.am: Add -no-undefined to LDFLAGS for libs + * gst/check/Makefile.am: + * libs/gst/controller/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + +2005-09-15 05:48:30 +0000 David Schleef + + configure.ac: Remove getbits library. Nothing uses it, and it should be in something like liboil if someone did want... + Original commit message from CVS: + * configure.ac: Remove getbits library. Nothing uses it, and + it should be in something like liboil if someone did want + to use it. + * libs/gst/Makefile.am: + * libs/gst/getbits/Makefile.am: + * libs/gst/getbits/gbtest.c: + * libs/gst/getbits/getbits.c: + * libs/gst/getbits/getbits.h: + * libs/gst/getbits/gstgetbits_generic.c: + * libs/gst/getbits/gstgetbits_i386.s: + * libs/gst/getbits/gstgetbits_inl.h: + +2005-09-15 05:42:13 +0000 David Schleef + + gst/Makefile.am: Dist glib-compat.h + Original commit message from CVS: + * gst/Makefile.am: Dist glib-compat.h + +2005-09-15 03:20:49 +0000 David Schleef + + configure.ac: Remove gst/registries, since it's no longer used. + Original commit message from CVS: + * configure.ac: Remove gst/registries, since it's no longer used. + * gst/registries/Makefile.am: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstlibxmlregistry.h: + * gst/registries/gstxmlregistry.c: + * gst/registries/gstxmlregistry.h: + * gst/registries/registrytest.c: + +2005-09-15 01:38:33 +0000 David Schleef + + gst/: Convergence is near. Seriously. + Original commit message from CVS: + * gst/glib-compat.h: + * gst/gstregistryxml.c: + Convergence is near. Seriously. + +2005-09-15 01:34:52 +0000 David Schleef + + gst/glib-compat.*: Attempt #4 to appease the buildbots. + Original commit message from CVS: + * gst/glib-compat.c: (g_mkdir_with_parents), (g_mkdir), (g_stat): + * gst/glib-compat.h: + Attempt #4 to appease the buildbots. + +2005-09-15 01:26:42 +0000 David Schleef + + gst/glib-compat.c: Attempt #3. + Original commit message from CVS: + * gst/glib-compat.c: (g_mkdir_with_parents), (g_mkdir), (g_stat): + Attempt #3. + +2005-09-15 01:20:22 +0000 David Schleef + + gst/glib-compat.c: Attempt #2. + Original commit message from CVS: + * gst/glib-compat.c: (g_mkdir_with_parents), (g_mkdir), (g_stat): + Attempt #2. + +2005-09-15 01:14:17 +0000 David Schleef + + gst/Makefile.am: Oh yeah, libgstreamer.so needs to contain the new functions. + Original commit message from CVS: + * gst/Makefile.am: Oh yeah, libgstreamer.so needs to contain + the new functions. + +2005-09-15 01:10:52 +0000 David Schleef + + gst/glib-compat.*: Add some functions that are in newer versions of glib than we care to require. + Original commit message from CVS: + * gst/glib-compat.c: (g_mkdir_with_parents), (g_mkdir), (g_stat): + * gst/glib-compat.h: Add some functions that are in newer versions + of glib than we care to require. + * gst/gstregistryxml.c: Use them. + +2005-09-15 00:48:45 +0000 David Schleef + + po/POTFILES.in: remove gst-register.c + Original commit message from CVS: + * po/POTFILES.in: remove gst-register.c + +2005-09-15 00:42:03 +0000 David Schleef + + docs/gst/: Documentation updates for registry changes. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + Documentation updates for registry changes. + +2005-09-15 00:35:11 +0000 David Schleef + + gst/gstregistryxml.c: Copy g_mkdir_with_parent() from glib, because we don't require glib-2.8. + Original commit message from CVS: + * gst/gstregistryxml.c: Copy g_mkdir_with_parent() from glib, + because we don't require glib-2.8. + +2005-09-15 00:20:14 +0000 David Schleef + + gst/gstregistryxml.c: Added. Essentially moved out of the registries directory. + Original commit message from CVS: + * gst/gstregistryxml.c: Added. Essentially moved out of the + registries directory. + +2005-09-15 00:13:26 +0000 David Schleef + + remove + Original commit message from CVS: + * check/Makefile.am: + * check/generic/states.c: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstelementfactory.c: + * gst/gstindex.c: + * gst/gstinfo.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstregistry.c: + * gst/gstregistry.h: + * gst/gstregistrypool.c: remove + * gst/gstregistrypool.h: remove + * gst/gsttypefind.c: + * gst/gsttypefindfactory.c: + * gst/gsturi.c: + * tools/Makefile.am: + * tools/gst-compprep.c: + * tools/gst-inspect.c: + * tools/gst-register.c: remove + * tools/gst-xmlinspect.c: + Registry rewrite. Changes registry from being a file created + by a tool into a simple cache file created automatically by + libgstreamer. Removed gst-register (because it's no longer + needed). Remove registry pools, because we only have one + registry implementation (XML). Fix up other subsystems as + necessary. + +2005-09-14 22:05:54 +0000 Thomas Vander Stichele + + * common: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/libs/tmpl/gstgetbits.sgml: + whoops, wrong commit + Original commit message from CVS: + whoops, wrong commit + +2005-09-14 22:01:45 +0000 Thomas Vander Stichele + + * common: + * docs/README: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/libs/tmpl/gstgetbits.sgml: + notes on documenting elements and plugins + Original commit message from CVS: + notes on documenting elements and plugins + +2005-09-14 15:16:33 +0000 Michael Smith + + * common: + * gst/Makefile.am: + Rest of the fix for 316155: don't confuse MinGW when running glib-mkenums + Original commit message from CVS: + Rest of the fix for 316155: don't confuse MinGW when running glib-mkenums + +2005-09-13 15:03:05 +0000 Steve Lhomme + + file gst-typefind.vcproj was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file gst-typefind.vcproj was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-09-13 14:49:23 +0000 Michael Smith + + * ChangeLog: + * gst/gstconfig.h.in: + Don't use windows linking attributes in MinGW + Original commit message from CVS: + Don't use windows linking attributes in MinGW + +2005-09-13 11:00:44 +0000 Thomas Vander Stichele + + gst/gstutils.c: Apparently people think it's better if this function doesn't try to set the state to whatever state w... + Original commit message from CVS: + * gst/gstutils.c: (set_state_async_thread_func), + (gst_element_set_state_async): + Apparently people think it's better if this function doesn't + try to set the state to whatever state was asked for on the first + call to this function for any object. Seriously. + +2005-09-12 18:14:03 +0000 Thomas Vander Stichele + + add a gst_element_set_state_async method that sets the state and starts a thread to make sure the state change comple... + Original commit message from CVS: + * check/gst/gstpipeline.c: (GST_START_TEST): + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: (set_state_async_thread_func), + (gst_element_set_state_async): + * gst/gstutils.h: + add a gst_element_set_state_async method that + sets the state and starts a thread to make sure the state + change completes as best as it can + +2005-09-12 17:01:18 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/gstpipeline.c: + * tests/check/gst/gstpipeline.c: + codify design+behaviour in testsuite after discussion + Original commit message from CVS: + codify design+behaviour in testsuite after discussion + +2005-09-12 16:10:18 +0000 Thomas Vander Stichele + + docs/: add a quote + Original commit message from CVS: + * docs/gst/tmpl/gstelement.sgml: + * docs/manual/appendix-quotes.xml: + add a quote + * gst/gstelement.c: (gst_element_set_state): + add some debug + +2005-09-12 13:45:04 +0000 Jan Schmidt + + gst/: Remove the requirement for sub-classes to call the parent implementation of prepare_output_buffer with a wrappe... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_class_init), + (gst_base_transform_prepare_output_buf), + (gst_base_transform_handle_buffer): + * gst/elements/gstcapsfilter.c: (gst_capsfilter_transform_ip), + (gst_capsfilter_prepare_buf): + Remove the requirement for sub-classes to call the parent + implementation of prepare_output_buffer with a wrapper function. + * gst/gsttaglist.h: + * gst/gsttagsetter.h: + Fix #define wrapper + +2005-09-11 19:22:23 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: more doc cleanups + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + more doc cleanups + +2005-09-11 13:07:25 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * gst/gstminiobject.c: + * gst/gstvalue.h: + doc build clean, hurray + Original commit message from CVS: + doc build clean, hurray + +2005-09-11 12:57:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * gst/base/gstadapter.h: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.h: + * gst/gstbin.h: + * gst/gstbuffer.h: + * gst/gstbus.h: + * gst/gstcaps.h: + * gst/gstclock.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstmessage.h: + * gst/gstpad.h: + * gst/gststructure.c: + * gst/registries/gstlibxmlregistry.h: + * libs/gst/base/gstadapter.h: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + various doc fixes + Original commit message from CVS: + various doc fixes + +2005-09-11 12:02:02 +0000 Thomas Vander Stichele + + * configure.ac: + fix silly bug that caused build to fail when check is missing + Original commit message from CVS: + fix silly bug that caused build to fail when check is missing + +2005-09-11 12:01:12 +0000 Thomas Vander Stichele + + docs/gst/: rearrange gstvalue section + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstvalue.sgml: + rearrange gstvalue section + * gst/gstutils.c: (gst_element_state_get_name): + NONE -> VOID + * gst/gstvalue.c: (_gst_value_initialize): + * gst/gstvalue.h: + doc updates + +2005-09-11 11:57:08 +0000 Thomas Vander Stichele + + * gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.c: + debug fixes + Original commit message from CVS: + debug fixes + +2005-09-09 23:45:15 +0000 Jan Schmidt + + check/gst-libs/controller.c: Header include fix. + Original commit message from CVS: + * check/gst-libs/controller.c: + Header include fix. + * gst/base/gstbasetransform.c: + (gst_base_transform_default_prepare_buf), + (gst_base_transform_handle_buffer): + * gst/base/gstbasetransform.h: + Some more basetransform changes and fixes to enable sub-classes + that modify buffer metadata only. + * gst/elements/gstcapsfilter.c: (gst_capsfilter_class_init), + (gst_capsfilter_init), (gst_capsfilter_transform_ip), + (gst_capsfilter_prepare_buf): + If the output pad has fixed allowed caps and input buffers + don't have any, set the fixed caps on outgoing buffers. + +2005-09-09 18:05:40 +0000 Thomas Vander Stichele + + * gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.c: + object debugging is good + Original commit message from CVS: + object debugging is good + +2005-09-09 17:42:20 +0000 Jan Schmidt + + check/elements/identity.c: Make the error a little clearer when the test fails because identity made a copy of the bu... + Original commit message from CVS: + * check/elements/identity.c: (GST_START_TEST): + Make the error a little clearer when the test fails because + identity made a copy of the buffer. + * docs/gst/gstreamer-sections.txt: + New symbols in gstbasetransform.h + * gst/base/gstbasetransform.c: (gst_base_transform_class_init), + (gst_base_transform_init), (gst_base_transform_transform_size), + (gst_base_transform_configure_caps), (gst_base_transform_setcaps), + (gst_base_transform_default_prepare_buf), + (gst_base_transform_get_unit_size), + (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer), (gst_base_transform_chain), + (gst_base_transform_change_state), + (gst_base_transform_set_passthrough), + (gst_base_transform_set_in_place), + (gst_base_transform_is_in_place): + * gst/base/gstbasetransform.h: + Change BaseTransform to separate in_place operate from same_caps + output. in_place implies that the element can perform the transform + on incoming buffers in-place, even if the caps on the output are + different. + Sub-class elements can now implement special buffer allocation + methods for outgoing buffers if they wish to. + Big documentation addition. + * gst/elements/gstcapsfilter.c: (gst_capsfilter_transform_ip): + * gst/elements/gstelements.c: + Changes for basetransform modifications. + * gst/elements/Makefile.am: + * gst/elements/gstfdsrc.c: (gst_fdsrc_init), (gst_fdsrc_create): + Compile fix. Extra debug output. + +2005-09-09 15:19:24 +0000 Steve Lhomme + + file gstcontrol.vcproj was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file gstcontrol.vcproj was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-09-09 14:34:43 +0000 Thomas Vander Stichele + + check/gst/gstpad.c: add tests for valid pad naming + Original commit message from CVS: + * check/gst/gstpad.c: (GST_START_TEST), (name_is_valid), + (gst_pad_suite): + add tests for valid pad naming + * gst/check/gstcheck.c: (gst_check_log_message_func), + (gst_check_log_critical_func): + add ASSERT_WARNING + remove printing of code, it is fragile when the code contains + % and the line number is enough info + * gst/check/gstcheck.h: + * gst/gstpad.c: (gst_pad_template_new): + fix memleaks + +2005-09-09 13:28:06 +0000 Thomas Vander Stichele + + * ChangeLog: + and the changelog + Original commit message from CVS: + and the changelog + +2005-09-09 13:26:54 +0000 Thomas Vander Stichele + + configure.ac: say what CHECK flags we use + Original commit message from CVS: + * configure.ac: + say what CHECK flags we use + * docs/libs/gstreamer-libs.types: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gst-interpolation.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + * tools/gst-inspect.c: (print_plugin_info): + we don't use dashes in header names + +2005-09-09 12:02:41 +0000 Thomas Vander Stichele + + check/: adding a test for pipelines and state changes + Original commit message from CVS: + * check/Makefile.am: + * check/gst/.cvsignore: + * check/gst/gstpipeline.c: (pop_messages), (GST_START_TEST), + (gst_pipeline_suite), (main): + adding a test for pipelines and state changes + * gst/gstutils.c: (get_state_func): + add some debugging + * gstreamer.spec.in: + fix up spec file + +2005-09-08 17:23:57 +0000 Michael Smith + + * ChangeLog: + * gst/elements/gstfilesrc.c: + * gst/elements/gstfilesrc.h: + * gst/gstevent.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfilesrc.h: + Various fixes for unseekable, unmmapable, and non-normal files, so that fallback to read() rather than mmap() works. + Original commit message from CVS: + Various fixes for unseekable, unmmapable, and non-normal files, so that + fallback to read() rather than mmap() works. + Allow newsegment events with start == end, so that cases where that's + correct work (e.g. filesrc on a zero-size file). + +2005-09-08 11:45:12 +0000 Michael Smith + + * docs/pwg/building-state.xml: + Update the manual section on state changes for wingo's new API + Original commit message from CVS: + Update the manual section on state changes for wingo's new API + +2005-09-07 15:22:29 +0000 Jan Schmidt + + gst/gstplugin.c: Call g_module_close when we don't load the module + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_load_file): + Call g_module_close when we don't load the module + * gst/registries/gstlibxmlregistry.c: + (gst_xml_registry_get_property): + Port leak fix from 0.8 + +2005-09-07 14:08:46 +0000 Stefan Kost + + * po/POTFILES.in: + more rename fixing ... + Original commit message from CVS: + more rename fixing ... + +2005-09-07 13:22:16 +0000 Stefan Kost + + renamed gsttag -> gsttaglist, gsttaginterface -> gsttagsetter inlined docs for gsttrace, gsttrashstack + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gsttrace.sgml: + * docs/gst/tmpl/gsttrashstack.sgml: + * gst/Makefile.am: + * gst/gst.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gsttag.c: + * gst/gsttag.h: + * gst/gsttaginterface.c: + * gst/gsttaginterface.h: + * gst/gsttaglist.c: + * gst/gsttaglist.h: + * gst/gsttagsetter.c: + * gst/gsttagsetter.h: + * gst/gsttrace.c: + * gst/gsttrace.h: + * gst/gsttrashstack.c: + renamed gsttag -> gsttaglist, gsttaginterface -> gsttagsetter + inlined docs for gsttrace, gsttrashstack + +2005-09-07 12:35:23 +0000 Stefan Kost + + gst/: splitted gsttypefind into gsttypefind, gsttypefindfactory + Original commit message from CVS: + * gst/Makefile.am: + * gst/elements/gstbufferstore.h: + * gst/elements/gsttypefindelement.c: + * gst/elements/gsttypefindelement.h: + * gst/gst.h: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + * gst/gsttypefindfactory.c: (gst_type_find_factory_get_type), + (gst_type_find_factory_class_init), (gst_type_find_factory_init), + (gst_type_find_factory_dispose), + (gst_type_find_factory_unload_thyself), + (gst_type_find_load_plugin), (gst_type_find_factory_get_list), + (gst_type_find_factory_get_caps), + (gst_type_find_factory_get_extensions), + (gst_type_find_factory_call_function): + * gst/gsttypefindfactory.h: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstxmlregistry.c: + splitted gsttypefind into gsttypefind, gsttypefindfactory + +2005-09-07 10:06:56 +0000 Andy Wingo + + gst/base/gstbasesink.c (gst_base_sink_activate_pull): Fix a race condition whereby the pad's task function is entered... + Original commit message from CVS: + 2005-09-07 Andy Wingo + * gst/base/gstbasesink.c (gst_base_sink_activate_pull): Fix a race + condition whereby the pad's task function is entered before the + pad_mode variable was set. + +2005-09-06 22:57:05 +0000 Jan Schmidt + + gst/gstpad.c: Catch misbehaving pad_alloc functions that don't set up caps and do it for them. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer): + Catch misbehaving pad_alloc functions that don't + set up caps and do it for them. + +2005-09-06 22:03:01 +0000 Stefan Kost + + check/pipelines/simple_launch_lines.c: test for pipe!=NULL + Original commit message from CVS: + * check/pipelines/simple_launch_lines.c: (run_pipeline): + test for pipe!=NULL + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstmemchunk.sgml: + * docs/gst/tmpl/gstparse.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gsttagsetter.sgml: + * docs/gst/tmpl/gsttypefind.sgml: + * docs/gst/tmpl/gsttypefindfactory.sgml: + * gst/gstmemchunk.c: + * gst/gstparse.c: + * gst/gsttag.c: + * gst/gsttaginterface.c: + * gst/gsttypefind.c: + * gst/gsttypefind.h: + inlined more docs + +2005-09-06 18:18:48 +0000 Thomas Vander Stichele + + * check/gst/gstghostpad.c: + * tests/check/gst/gstghostpad.c: + add a check for a ghostpad that doesn't have a target being linked + Original commit message from CVS: + add a check for a ghostpad that doesn't have a target being linked + +2005-09-06 14:11:21 +0000 Thomas Vander Stichele + + * configure.ac: + back to head + Original commit message from CVS: + back to head + +=== release 0.9.2 === + +2005-09-06 14:02:17 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * README: + * RELEASE: + * configure.ac: + releasing 0.9.2 + Original commit message from CVS: + releasing 0.9.2 + +2005-09-06 11:45:00 +0000 Thomas Vander Stichele + + * README: + * common: + update readme with explanation of modules + Original commit message from CVS: + update readme with explanation of modules + +2005-09-06 09:52:23 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * docs/random/ChangeLog-0.8: + changelog split + Original commit message from CVS: + changelog split + +2005-09-05 17:55:10 +0000 Thomas Vander Stichele + + * autogen.sh: + * docs/gst/tmpl/gstplugin.sgml: + maintenance updates + Original commit message from CVS: + maintenance updates + +2005-09-05 17:53:24 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + adding -bad + Original commit message from CVS: + adding -bad + +2005-09-05 16:54:54 +0000 Andy Wingo + + gst/registries/gstxmlregistry.*: and update to newer API. + Original commit message from CVS: + * gst/registries/gstxmlregistry.h: + * gst/registries/gstxmlregistry.c: and update to newer API. + Incidentally they should be a bit faster now that they don't have + to parse the caps. + +2005-09-05 16:52:56 +0000 Andy Wingo + + gst/registries/gstxmlregistry.*: Um... resurrect... + Original commit message from CVS: + 2005-09-05 Andy Wingo + * gst/registries/gstxmlregistry.h: + * gst/registries/gstxmlregistry.c: Um... resurrect... + +2005-09-05 16:36:47 +0000 Andy Wingo + + gst/registries/gstxmlregistry.*: Remove from CVS, they were replaced by the libxml registry a while back + Original commit message from CVS: + 2005-09-05 Andy Wingo + * gst/registries/gstxmlregistry.h: + * gst/registries/gstxmlregistry.c: Remove from CVS, they were + replaced by the libxml registry a while back + +2005-09-05 11:54:55 +0000 Thomas Vander Stichele + + * check/generic/.gitignore: + * check/gst/.gitignore: + * docs/README: + * examples/pwg/.gitignore: + * tests/check/generic/.gitignore: + * tests/check/gst/.gitignore: + * tests/old/examples/pwg/.gitignore: + maintenance updates + Original commit message from CVS: + maintenance updates + +2005-09-05 09:38:38 +0000 Christian Schaller + + * docs/gst/gstreamer-docs.sgml: + Rever to 1.80 version of this file as GstUtils is not as dead as it seemed + Original commit message from CVS: + Rever to 1.80 version of this file as GstUtils is not as dead as it seemed + +2005-09-05 09:23:44 +0000 Christian Schaller + + * common: + * docs/gst/gstreamer-docs.sgml: + remove GstUtils mention as it is now gone + Original commit message from CVS: + remove GstUtils mention as it is now gone + +2005-09-04 11:01:44 +0000 Thomas Vander Stichele + + * common: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + need to add -lcheck to the pkgconfig file + Original commit message from CVS: + need to add -lcheck to the pkgconfig file + +2005-09-03 17:36:20 +0000 Thomas Vander Stichele + + * gst/gstplugin.c: + fix for a critical when a module returns NULL on opening + Original commit message from CVS: + fix for a critical when a module returns NULL on opening + +2005-09-03 17:00:52 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/tmpl/gstplugin.sgml: + * gst/elements/gstelements.c: + * gst/gst.c: + * gst/gstplugin.c: + * gst/gstplugin.h: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstxmlregistry.c: + * plugins/elements/gstelements.c: + * tools/gst-inspect.c: + add a source plugin description field, to represent the source module this plugin is a part of. By default GST_PLUGI... + Original commit message from CVS: + add a source plugin description field, to represent the source + module this plugin is a part of. By default GST_PLUGIN_DEFINE + will set it to PACKAGE, which is automake's idea of the name of + the source project. + +2005-09-03 16:16:15 +0000 Thomas Vander Stichele + + * common: + * docs/htmlinstall.mak: + fix distcheck + Original commit message from CVS: + fix distcheck + +2005-09-03 14:20:10 +0000 Thomas Vander Stichele + + * Makefile.am: + * docs/htmlinstall.mak: + enable docs build for distcheck + Original commit message from CVS: + enable docs build for distcheck + +2005-09-03 13:54:26 +0000 Thomas Vander Stichele + + * docs/plugins/.gitignore: + * docs/plugins/Makefile.am: + * docs/plugins/gstdoc-mkdb: + * docs/plugins/gstdoc-mktmpl: + * docs/plugins/gstdoc-scanobj: + * docs/plugins/gstreamer-plugins-docs.sgml: + * docs/plugins/gstreamer-plugins-sections.txt: + * docs/plugins/gstreamer-plugins.types.in: + * docs/plugins/tmpl/ac3dec.sgml: + * docs/plugins/tmpl/ac3parse.sgml: + * docs/plugins/tmpl/audioscale.sgml: + * docs/plugins/tmpl/cobin.sgml: + * docs/plugins/tmpl/dvdsrc.sgml: + * docs/plugins/tmpl/example.sgml: + * docs/plugins/tmpl/gstaviencoder.sgml: + * docs/plugins/tmpl/gstjpeg.sgml: + * docs/plugins/tmpl/gstjpegdec.sgml: + * docs/plugins/tmpl/gstjpegenc.sgml: + * docs/plugins/tmpl/gstmpeg1encoder.sgml: + * docs/plugins/tmpl/gstmpeg2enc.sgml: + * docs/plugins/tmpl/gstmpeg2play.sgml: + * docs/plugins/tmpl/gstmpeg_play.sgml: + * docs/plugins/tmpl/gstmpegaudio.sgml: + * docs/plugins/tmpl/gstmpg123.sgml: + * docs/plugins/tmpl/gstparseau.sgml: + * docs/plugins/tmpl/gstparseavi.sgml: + * docs/plugins/tmpl/gstparsewav.sgml: + * docs/plugins/tmpl/gstreamer-plugins-unused.sgml: + * docs/plugins/tmpl/gstspectrum.sgml: + * docs/plugins/tmpl/gstv4lsrc.sgml: + * docs/plugins/tmpl/gstwincodec.sgml: + * docs/plugins/tmpl/gstwindec.sgml: + * docs/plugins/tmpl/gstwinenc.sgml: + * docs/plugins/tmpl/gstxa.sgml: + * docs/plugins/tmpl/gstxing.sgml: + * docs/plugins/tmpl/median.sgml: + * docs/plugins/tmpl/mp1videoparse.sgml: + * docs/plugins/tmpl/mp2videoparse.sgml: + * docs/plugins/tmpl/mp3parse.sgml: + * docs/plugins/tmpl/mpeg1parse.sgml: + * docs/plugins/tmpl/mpeg2parse.sgml: + * docs/plugins/tmpl/mpeg2subt.sgml: + * docs/plugins/tmpl/rtjpegdec.sgml: + * docs/plugins/tmpl/rtjpegenc.sgml: + * docs/plugins/tmpl/smooth.sgml: + * docs/plugins/tmpl/smoothwave.sgml: + * docs/plugins/tmpl/spindentity.sgml: + * docs/plugins/tmpl/stereo.sgml: + * docs/plugins/tmpl/synaesthesia.sgml: + * docs/plugins/tmpl/system_encode.sgml: + * docs/plugins/tmpl/vcdsrc.sgml: + * docs/plugins/tmpl/videoscale.sgml: + * docs/plugins/tmpl/videosink.sgml: + * docs/plugins/tmpl/volume.sgml: + * docs/plugins/tmpl/vorbisdec.sgml: + * docs/plugins/tmpl/vorbisenc.sgml: + * docs/plugins/tmpl/vumeter.sgml: + remove old plugins docs + Original commit message from CVS: + remove old plugins docs + +2005-09-03 13:49:49 +0000 Thomas Vander Stichele + + * ChangeLog: + * Makefile.am: + * autogen.sh: + * common: + * configure.ac: + * docs/Makefile.am: + * docs/faq/Makefile.am: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/htmlinstall.mak: + * docs/manual/Makefile.am: + * docs/pwg/Makefile.am: + * gstreamer.spec.in: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + clean up docs build a little; have docdir be an overridable install location; separate gtk-doc and docbook bits + Original commit message from CVS: + clean up docs build a little; have docdir be an overridable install location; separate gtk-doc and docbook bits + +2005-09-02 23:36:24 +0000 Thomas Vander Stichele + + * gst/gsturi.h: + whitespace cleanups + Original commit message from CVS: + whitespace cleanups + +2005-09-02 23:17:26 +0000 Tim-Philipp Müller + + gst/base/gstbasesink.c: Add comment. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_pad_buffer_alloc): + Add comment. + * gst/elements/gstfakesink.c: (gst_fake_sink_init), + (gst_fake_sink_change_state): + Make state change function thread-safe. + * gst/gstpad.c: (gst_pad_alloc_buffer): + Set offset on generic buffer allocated by fallback. + +2005-09-02 23:03:36 +0000 Thomas Vander Stichele + + * gst/gsttrashstack.h: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2005-09-02 21:37:55 +0000 Stefan Kost + + run the wingo-magic script against the docs + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstelement.sgml: + * gst/gstpad.c: + * libs/gst/controller/gst-controller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_new), + (gst_controller_find_controlled_property): + run the wingo-magic script against the docs + +2005-09-02 18:36:09 +0000 Stefan Kost + + * docs/gst/tmpl/gstqueue.sgml: + removed file again + Original commit message from CVS: + removed file again + +2005-09-02 17:23:06 +0000 Stefan Kost + + merged elementdetails docs into elementfactory docs inlined both + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstelementdetails.sgml: + * docs/gst/tmpl/gstelementfactory.sgml: + * gst/gst.c: + * gst/gstbus.c: + * gst/gstelementfactory.c: + * gst/gstelementfactory.h: + merged elementdetails docs into elementfactory docs + inlined both + +2005-09-02 16:44:57 +0000 Andy Wingo + + gst/gstelement.h: Add magical pixie dust to make glib-mkenums consider this enum an enum and not a flags. + Original commit message from CVS: + 2005-09-02 Andy Wingo + * gst/gstelement.h: Add magical pixie dust to make glib-mkenums + consider this enum an enum and not a flags. + +2005-09-02 16:17:23 +0000 Stefan Kost + + more docs inlined + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstiterator.sgml: + * docs/gst/tmpl/gstmacros.sgml: + * docs/gst/tmpl/gstrealpad.sgml: + * docs/gst/tmpl/gstregistry.sgml: + * docs/gst/tmpl/gstregistrypool.sgml: + * docs/gst/tmpl/gststructure.sgml: + * docs/gst/tmpl/gstsystemclock.sgml: + * docs/gst/tmpl/gsttrace.sgml: + * gst/gstghostpad.c: + * gst/gstmacros.h: + * gst/gstmemchunk.c: + * gst/gstmemchunk.h: + * gst/gstqueue.c: + * gst/gstregistry.c: + * gst/gstregistrypool.c: + * gst/gststructure.c: + * gst/gstsystemclock.c: + more docs inlined + +2005-09-02 15:42:00 +0000 Andy Wingo + + gst/gstelement.h (GstState): Renamed from GstElementState, changed to be a normal enum instead of flags. + Original commit message from CVS: + 2005-09-02 Andy Wingo + * gst/gstelement.h (GstState): Renamed from GstElementState, + changed to be a normal enum instead of flags. + (GstStateChangeReturn): Renamed from GstElementStateReturn, names + munged to be GST_STATE_CHANGE_*. + (GST_STATE_CHANGE): Renamed from GST_STATE_TRANSITION, updated to + work with the new state representation. + (GstStateChange): New enumeration of possible state transitions. + Replaces GST_STATE_FOO_TO_BAR with GST_STATE_CHANGE_FOO_TO_BAR. + (GstElementClass::change_state): Pass the GstStateChange along as + an argument. Helps language bindings, so they don't have to use + tricky lock-needing macros like GST_STATE_CHANGE (). + * scripts/update-states (file): New script. Run it on a file to + update it for state naming and API changes. Updates files in + place. + * All files updated for the new API. + +2005-09-02 12:11:54 +0000 Thomas Vander Stichele + + * gstreamer.spec.in: + clean up spec some more + Original commit message from CVS: + clean up spec some more + +2005-09-02 12:08:45 +0000 Thomas Vander Stichele + + gst/: fix a bunch of unchecked return values + Original commit message from CVS: + * gst/gsttrace.c: (gst_trace_flush), (gst_trace_text_flush): + * gst/gstutils.c: (gst_util_set_value_from_string), + (gst_util_set_object_arg): + fix a bunch of unchecked return values + * tools/gst-complete.c: (main): + * gstreamer.spec.in: + clean up a little + +2005-09-01 19:06:39 +0000 Stefan Kost + + * docs/gst/tmpl/.gitignore: + * docs/gst/tmpl/gsttaglist.sgml: + updated .cvsignore + Original commit message from CVS: + updated .cvsignore + +2005-09-01 18:12:18 +0000 Wim Taymans + + gst/base/gstbasesink.*: Handle newsegments more correctly. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_do_sync), + (gst_base_sink_handle_event): + * gst/base/gstbasesink.h: + Handle newsegments more correctly. + * gst/gstbus.c: + Fix docs. + * gst/gstevent.c: (gst_event_new_newsegment): + A newsegment cannot have a start_time of -1 + +2005-09-01 16:53:14 +0000 Tim-Philipp Müller + + win32/gstenumtypes.*: Update + Original commit message from CVS: + * win32/gstenumtypes.c: + * win32/gstenumtypes.h: + Update + +2005-08-31 21:01:35 +0000 Michael Smith + + * docs/pwg/building-boiler.xml: + Remove extraneous 'co' from cvs command in PWG, as reported on irc. + Original commit message from CVS: + Remove extraneous 'co' from cvs command in PWG, as reported on irc. + +2005-08-31 18:45:41 +0000 Stefan Kost + + libs/gst/controller/gst-controller.c: fixed boolean again + Original commit message from CVS: + * libs/gst/controller/gst-controller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_new): + fixed boolean again + +2005-08-31 15:27:55 +0000 Thomas Vander Stichele + + docs/faq/gst-uninstalled: add -good + Original commit message from CVS: + * docs/faq/gst-uninstalled: + add -good + * gst/gstevent.c: + * gst/gstevent.h: + remove wrong docs + * gst/gstutils.c: (gst_element_link_filtered): + * gst/gstutils.h: + add gst_element_link_filtered + +2005-08-31 14:08:45 +0000 Stefan Kost + + inlined more docs, fixed double id-ref + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gsterror.sgml: + * docs/gst/tmpl/gstfilter.sgml: + * docs/gst/tmpl/gsturihandler.sgml: + * docs/gst/tmpl/gsturitype.sgml: + * docs/gst/tmpl/gstutils.sgml: + * docs/gst/tmpl/gstxml.sgml: + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstfilter.c: + * gst/gsturi.c: + * gst/gsturitype.c: + * gst/gstutils.c: + * gst/gstxml.c: + inlined more docs, fixed double id-ref + +2005-08-31 13:53:39 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Passthrough elements don't need the caps as they don't care. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_setcaps), + (gst_base_transform_handle_buffer): + Passthrough elements don't need the caps as they don't care. + +2005-08-31 13:50:40 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Don't leak refcounts on buffers. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_setcaps), + (gst_base_transform_handle_buffer), (gst_base_transform_chain): + Don't leak refcounts on buffers. + +2005-08-31 13:41:19 +0000 Wim Taymans + + gst/base/gstbasetransform.*: Handle the case where we are not negotiated more gracefully. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_configure_caps), + (gst_base_transform_setcaps), (gst_base_transform_handle_buffer), + (gst_base_transform_chain), (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + Handle the case where we are not negotiated more gracefully. + +2005-08-31 12:55:54 +0000 Tim-Philipp Müller + + gst/elements/gstfilesrc.c: Set READONLY flag on mmap'ed buffers, otherwise gst_buffer_make_writable() won't work prop... + Original commit message from CVS: + * gst/elements/gstfilesrc.c: (gst_mmap_buffer_init), + (gst_file_src_map_region): + Set READONLY flag on mmap'ed buffers, otherwise + gst_buffer_make_writable() won't work properly (#314708). + +2005-08-31 10:07:24 +0000 Wim Taymans + + gst/base/gstbasetransform.c: passthrough elements can even do inplace on non writable buffers (as they don't touch th... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_handle_buffer): + passthrough elements can even do inplace on non writable + buffers (as they don't touch them). + +2005-08-31 10:00:08 +0000 Stefan Kost + + check/gst-libs/controller.c: more tests (hehe I have the most) + Original commit message from CVS: + * check/gst-libs/controller.c: (gst_test_mono_source_get_property), + (gst_test_mono_source_set_property), + (gst_test_mono_source_class_init), (GST_START_TEST), + (gst_controller_suite): + more tests (hehe I have the most) + * gst/gstbus.c: + describe popping messages whenusing mulltiple sources + * libs/gst/controller/gst-controller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_new): + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-interpolation.c: + implement boolean properties + +2005-08-31 08:57:14 +0000 Wim Taymans + + gst/gstminiobject.c: Cannot assert that the refcount has to be positive since a disposed object can be resurected. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_mini_object_ref): + Cannot assert that the refcount has to be positive + since a disposed object can be resurected. + +2005-08-31 08:38:39 +0000 Wim Taymans + + gst/gstpad.c: Revert change, need to first fix badly behaving apps. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_init): + Revert change, need to first fix badly behaving + apps. + +2005-08-30 19:45:38 +0000 Wim Taymans + + check/elements/: Activate pads before using them. + Original commit message from CVS: + * check/elements/fakesrc.c: (setup_fakesrc): + * check/elements/identity.c: (setup_identity): + Activate pads before using them. + +2005-08-30 19:29:59 +0000 Wim Taymans + + gst/base/gstadapter.c: Flushing out 0 bytes is ok for this function. + Original commit message from CVS: + * gst/base/gstadapter.c: (gst_adapter_flush): + Flushing out 0 bytes is ok for this function. + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + no newsegment gives a warning and sets the start/stop to + invalid. + * gst/base/gstbasetransform.c: (gst_base_transform_change_state), + (gst_base_transform_set_passthrough): + Some debug info. + * gst/gstminiobject.c: (gst_mini_object_ref): + Check refcount here too. + * gst/gstpad.c: (gst_pad_init): + Pads are initially flushing and refusing data. + * gst/gstutils.c: (gst_element_link_pads_filtered): + When adding a capsfilter element make sure it has the + same state as the parent bin. + +2005-08-30 17:23:19 +0000 Stefan Kost + + more docs and two more inlined + Original commit message from CVS: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstformat.sgml: + * docs/gst/tmpl/gstversion.sgml: + * gst/gstbus.h: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstversion.h.in: + more docs and two more inlined + +2005-08-30 17:12:33 +0000 Wim Taymans + + gst/elements/gstfilesink.c: Don't sync to clock. + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_file_sink_class_init): + Don't sync to clock. + +2005-08-30 08:17:48 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: ultral33t func10ns deserve to appear in the docs actualy + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + ultral33t func10ns deserve to appear in the docs actualy + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstcompat.sgml: + * docs/gst/tmpl/gstconfig.sgml: + * gst/check/gstcheck.c: + * gst/gstcompat.h: + * gst/gstconfig.h.in: + inlined more docs + +2005-08-29 21:41:02 +0000 Stefan Kost + + inlined and extended docs + Original commit message from CVS: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gstutils.sgml: + * gst/gstquery.c: + * gst/gstquery.h: + inlined and extended docs + +2005-08-29 19:59:52 +0000 Stefan Kost + + check/gst-libs/controller.c: more tests + Original commit message from CVS: + * check/gst-libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + more tests + * docs/gst/tmpl/gstutils.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/tmpl/gstdataprotocol.sgml: + include path fixes + * examples/controller/audio-example.c: (main): + controller example works now + * gst/gstclock.h: + doc fixes + * tools/gst-inspect.c: (print_element_properties_info): + show param spec flags + +2005-08-29 16:10:36 +0000 Andy Wingo + + gst/gstutils.c (gst_util_uint64_scale): New 3733t funct10n. + Original commit message from CVS: + 2005-08-29 Andy Wingo + * gst/gstutils.c (gst_util_uint64_scale): New 3733t funct10n. + +2005-08-29 09:52:44 +0000 Michael Smith + + * docs/faq/cvs.xml: + Minor updates to developer cvs instructions, to more closely match what the freedesktop people want. Also, test my cv... + Original commit message from CVS: + Minor updates to developer cvs instructions, to more closely match what + the freedesktop people want. Also, test my cvs commit access... + +2005-08-28 17:45:58 +0000 Andy Wingo + + gst/gstutils.h (GST_BOILERPLATE_FULL): Prototype instance_init as having two arguments instead of just one. Allows su... + Original commit message from CVS: + 2005-08-28 Andy Wingo + * gst/gstutils.h (GST_BOILERPLATE_FULL): Prototype instance_init + as having two arguments instead of just one. Allows superclasses + to access information on subclasses -- see the terrible for() loop + in gtype.c:g_type_create_instance for the reason why. All callers + changed. + +2005-08-27 10:57:00 +0000 Stefan Kost + + docs/design/part-messages.txt: update info + Original commit message from CVS: + * docs/design/part-messages.txt: + update info + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gstclock.sgml: + * gst/gstbus.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstmessage.c: + added descriptions for bus and message + inline caps and clock docs + +2005-08-26 22:32:51 +0000 Stefan Kost + + gst/gstmessage.*: doc fixes + Original commit message from CVS: + * gst/gstmessage.c: + * gst/gstmessage.h: + doc fixes + +2005-08-26 21:23:51 +0000 Stefan Kost + + gst/base/gstbasetransform.c: fix div-by-zero + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_transform_size): + fix div-by-zero + +2005-08-26 14:21:43 +0000 Andy Wingo + + check/pipelines/simple_launch_lines.c (run_pipeline): Check element_set_state's return val. + Original commit message from CVS: + 2005-08-26 Andy Wingo + * check/pipelines/simple_launch_lines.c (run_pipeline): Check + element_set_state's return val. + (test_2_elements): Add test that's been disabled for months. + * gst/elements/gstfakesink.c: Cleanups. Add can-activate-push and + can-activate-pull properties. + * gst/elements/gstfakesrc.c: Cleanups. Add can-activate-push and + can-activate-pull properties. Implement is_seekable so fakesrc can + operate in pull mode. + * gst/base/gstbasesink.c (GstBaseSink): Remove has-loop, has-chain + properties. + (gst_base_sink_activate, gst_base_sink_activate_pull) + (gst_base_sink_activate_push): Make activation mode choosing work. + Cleanups. + (gst_base_sink_chain, gst_base_sink_loop): Assert activation mode + is right. Make pull mode work. Post an eos before pausing in pull + mode. + (gst_base_sink_change_state): Pay attention to the core's + change_state() return val. + * gst/base/gstbasesrc.c (GstBaseSrc): Remove has-loop, + has-getrange properties. Cleanups. + * gst/base/gstbasesrc.h (GstBaseSrc): Remove has_loop, + has_getrange and replace with can_activate_pull and + can_activate_push. + * gst/base/gstbasesink.h (GstBaseSink): Rearrange fields, add + locking comments. Remove has_loop, has_chain and replace with + can_activate_pull and can_activate_push. + +2005-08-26 13:28:01 +0000 Jan Schmidt + + Add metadata reading example that loops over a list of filenames, dumping any tags found. + Original commit message from CVS: + * configure.ac: + * examples/Makefile.am: + * examples/metadata/Makefile.am: + * examples/metadata/read-metadata.c: (message_loop), + (have_pad_handler), (make_pipeline), (print_tag), (main): + Add metadata reading example that loops over a list of filenames, + dumping any tags found. + * gst/gstbus.c: (gst_bus_dispose): + * gst/gstelement.c: (gst_element_dispose): + Release a few potentially-held references in dispose. + +2005-08-26 13:21:47 +0000 Stefan Kost + + docs/gst/tmpl/gstminiobject.sgml: do *not* add tmpl/*.sgml files to CVS! + Original commit message from CVS: + * docs/gst/tmpl/gstminiobject.sgml: + do *not* add tmpl/*.sgml files to CVS! + +2005-08-26 13:17:54 +0000 Stefan Kost + + libs/gst/bytestream/: removing obsolete files + Original commit message from CVS: + * libs/gst/bytestream/.cvsignore: + * libs/gst/bytestream/Makefile.am: + * libs/gst/bytestream/adapter.c: + * libs/gst/bytestream/adapter.h: + * libs/gst/bytestream/bytestream.c: + * libs/gst/bytestream/bytestream.h: + * libs/gst/bytestream/filepad.c: + * libs/gst/bytestream/filepad.h: + removing obsolete files + +2005-08-26 12:48:29 +0000 Stefan Kost + + docs/: disabed additional index entries again, as this makes docs-gen just slow and they aren't useful yet + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + disabed additional index entries again, as this makes docs-gen just + slow and they aren't useful yet + * docs/libs/gstreamer-libs-sections.txt: + little -section.txt cleanup for libs + +2005-08-26 11:56:11 +0000 Thomas Vander Stichele + + gst/base/: fix up some debugging + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + * gst/base/gstbasetransform.c: (gst_base_transform_transform_size), + fix up some debugging + (gst_base_transform_get_unit_size), + (gst_base_transform_buffer_alloc), (gst_base_transform_event), + (gst_base_transform_handle_buffer): + * gst/base/gstbasetransform.h: + handle and store timed NEWSEGMENT events so that subclasses that + calculate time by counting samples have a segment_start time they + need to add to their timestamps - see audioresample + +2005-08-26 11:19:22 +0000 Thomas Vander Stichele + + * common: + * gst/base/gstbasetransform.c: + * gst/gstbuffer.h: + * gst/gstpad.c: + * libs/gst/base/gstbasetransform.c: + whitespace, doc and debug fixing/additions + Original commit message from CVS: + whitespace, doc and debug fixing/additions + +2005-08-25 23:17:18 +0000 Stefan Kost + + gst/gstbin.h: removed ';' from the end of macro defs + Original commit message from CVS: + * gst/gstbin.h: + removed ';' from the end of macro defs + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * gst/gstbus.h: + * gst/gstelement.c: (gst_element_class_init), + (gst_element_set_state), (activate_pads), + (gst_element_save_thyself): + * gst/gstevent.c: (gst_event_new_newsegment): + * gst/gstevent.h: + * gst/gstiterator.c: + * gst/gstiterator.h: + * gst/gstpad.c: + * gst/gstprobe.h: + * gst/gstutils.c: (gst_pad_query_convert): + * gst/gstutils.h: + fixed parameter name mismatches between source, header and docs + added some more docs, resolved the last batch of unused elements in + docs (now someone needs to doc them) + +2005-08-25 20:52:07 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstxmlregistry.c: + respect order of plugin dirs when loading pllugins and rebuilding registry + Original commit message from CVS: + respect order of plugin dirs when loading pllugins and rebuilding registry + +2005-08-25 19:36:05 +0000 Wim Taymans + + gst/base/gstbasetransform.*: Cache caps unit_size. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_transform_size), + (gst_base_transform_configure_caps), + (gst_base_transform_get_unit_size), + (gst_base_transform_buffer_alloc), + (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + Cache caps unit_size. + Make sure we cannot negotiate up and downstream at the + same time. + +2005-08-25 18:55:34 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gst.c: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstxmlregistry.c: + make registry respect order of GST_PLUGIN_PATH; make the installed location go last + Original commit message from CVS: + make registry respect order of GST_PLUGIN_PATH; make the installed location go last + +2005-08-25 18:54:00 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/base/gstbasetransform.h: + * gst/gstpad.c: + * libs/gst/base/gstbasetransform.h: + add docs + Original commit message from CVS: + add docs + +2005-08-25 16:27:44 +0000 Thomas Vander Stichele + + * gst/check/gstcheck.c: + * gst/check/gstcheck.h: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + add a uint64 checking method + Original commit message from CVS: + add a uint64 checking method + +2005-08-25 13:52:13 +0000 Wim Taymans + + gst/gstbin.c: Be a bit more conservative about the posted message. + Original commit message from CVS: + * gst/gstbin.c: (bin_bus_handler): + Be a bit more conservative about the posted message. + * gst/gstbus.c: (gst_bus_post): + Some cleanups, warn wrong return values. + +2005-08-25 10:51:14 +0000 Jan Schmidt + + Revert unpopular change for GST_MESSAGE_SRC to GObject. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * gst/gstbin.c: (bin_bus_handler): + * gst/gstmessage.c: (gst_message_finalize), (_gst_message_copy), + (gst_message_new), (gst_message_new_eos), (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_new_custom): + * gst/gstmessage.h: + * tools/gst-launch.c: (event_loop): + * tools/gst-md5sum.c: (event_loop): + Revert unpopular change for GST_MESSAGE_SRC to GObject. + +2005-08-25 10:35:46 +0000 Thomas Vander Stichele + + * gst/gstbuffer.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + fix docs by fixing enum typedef + Original commit message from CVS: + fix docs by fixing enum typedef + +2005-08-25 10:16:21 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + wim fixed the task, yay + Original commit message from CVS: + wim fixed the task, yay + +2005-08-25 10:01:47 +0000 Wim Taymans + + check/generic/states.c: Cleanup can be done at the end. + Original commit message from CVS: + * check/generic/states.c: (GST_START_TEST): + Cleanup can be done at the end. + * gst/gsttask.c: (gst_task_get_type), (gst_task_finalize), + (gst_task_func), (gst_task_cleanup_all), (gst_task_set_lock), + (gst_task_get_state), (gst_task_start), (gst_task_pause): + Oh boy.. Thanks for finding this, Thomas. + +2005-08-24 22:01:41 +0000 Stefan Kost + + * docs/gst/gstreamer.types: + grmpf, another try to fix it + Original commit message from CVS: + grmpf, another try to fix it + +2005-08-24 21:57:05 +0000 Stefan Kost + + * docs/gst/gstreamer.types: + another fix + Original commit message from CVS: + another fix + +2005-08-24 21:45:13 +0000 Stefan Kost + + docs/gst/gstreamer.types: added missing types + Original commit message from CVS: + * docs/gst/gstreamer.types: + added missing types + +2005-08-24 21:35:43 +0000 Stefan Kost + + added miissing classes and symbols (123 more to go) removed removed symbols from section file fixed many doc-comments + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * gst/gstbin.c: + * gst/gstiterator.c: + * gst/gstutils.c: + * gst/registries/gstxmlregistry.h: + added miissing classes and symbols (123 more to go) + removed removed symbols from section file + fixed many doc-comments + +2005-08-24 20:49:53 +0000 Wim Taymans + + check/generic/states.c: Make sure all tasks are stopped. + Original commit message from CVS: + * check/generic/states.c: (GST_START_TEST): + Make sure all tasks are stopped. + * check/gst/gstbin.c: (GST_START_TEST): + Unref after usage for proper valgrinding. + * gst/gstpad.c: (gst_pad_finalize), (gst_pad_stop_task): + Really wait for the task to stop before destroying the + mutex. + * gst/gstqueue.c: (gst_queue_sink_activate_push), + (gst_queue_src_activate_push): + Small cleanups. Don't stop the task when we did not start + it. + * gst/gsttask.c: (gst_task_get_type), (gst_task_init), + (gst_task_func), (gst_task_cleanup_all), (gst_task_set_lock), + (gst_task_get_state), (gst_task_start), (gst_task_pause), + (gst_task_join): + * gst/gsttask.h: + Protect the stream lock with the object lock. + Disallow setting the stream lock when running. + Add cleanup_all to wait for the threadpool to finish. + Remove code to autoallocate a mutex if none was provided. + Add _join() to wait for a task to stop. + Protect the thread pool with a global lock. + +2005-08-24 17:57:36 +0000 Wim Taymans + + gst/base/gstbasesink.*: Handle newsegment events correctly. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_get_times), (gst_base_sink_do_sync), + (gst_base_sink_handle_buffer), (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + Handle newsegment events correctly. + Drop buffers out of the segment range. + +2005-08-24 17:24:21 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + disable test while wim is fixing + Original commit message from CVS: + disable test while wim is fixing + +2005-08-24 16:46:10 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-uninstalled.pc.in: + * pkgconfig/gstreamer.pc.in: + add pluginsdir to pkgconfig files + Original commit message from CVS: + add pluginsdir to pkgconfig files + +2005-08-24 16:41:45 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2005-08-24 16:09:50 +0000 Thomas Vander Stichele + + check/: add a test that does a bunch of state changes on elements needs some fixing for valgrind + Original commit message from CVS: + * check/Makefile.am: + * check/generic/states.c: (GST_START_TEST), (states_suite), (main): + add a test that does a bunch of state changes on elements + needs some fixing for valgrind + * check/states/sinks.c: (gst_object_suite): + whitespace + * gst/gstcaps.h: + add prototype for gst_caps_is_equal_fixed + * gst/gstplugin.c: + * gst/gstregistrypool.c: + doc fixes + +2005-08-24 15:49:03 +0000 Andy Wingo + + gst/gstquery.c (gst_query_new_convert): Spew if we try to convert a negative value. Doesn't make much sense. Mostly t... + Original commit message from CVS: + 2005-08-24 Andy Wingo + * gst/gstquery.c (gst_query_new_convert): Spew if we try to + convert a negative value. Doesn't make much sense. Mostly this is + here to force callers to ensure -1 maps to -1. + +2005-08-24 15:10:41 +0000 Jan Schmidt + + docs/pwg/advanced-types.xml: Well done to Michael for catching my deliberate introduction of this spelling mistake. + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Well done to Michael for catching my deliberate introduction + of this spelling mistake. + * gst/gstbin.c: (gst_bin_remove_func), (bin_bus_handler): + * gst/gstelement.h: + Add GST_ELEMENT_UNPARENTING to prevent races so that we can + unlink pads before removing the element from the bin. + +2005-08-24 13:49:21 +0000 Andy Wingo + + gst/gst.c (parse_debug_list): Accept e.g. GST_DEBUG=4 to mean the same thing as GST_DEBUG=*:4. + Original commit message from CVS: + 2005-08-24 Andy Wingo + * gst/gst.c (parse_debug_list): Accept e.g. GST_DEBUG=4 to mean + the same thing as GST_DEBUG=*:4. + (parse_debug_level, parse_debug_category): New helper parsers. + +2005-08-24 13:33:21 +0000 Thomas Vander Stichele + + gst/base/gstbasetransform.c: use gboolean return values and pointers to size so we can use the full GST_BUFFER_SIZE r... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps), + (gst_base_transform_transform_size), (gst_base_transform_getcaps), + (gst_base_transform_setcaps), (gst_base_transform_get_unit_size), + (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer): + use gboolean return values and pointers to size so we can use the + full GST_BUFFER_SIZE range (guint) for buffer sizes + use GstPadDirection for transform_caps + * gst/base/gstbasetransform.h: + rename get_size to get_unit_size since that's what it is + * gst/elements/gstcapsfilter.c: (gst_capsfilter_transform_caps): + use GstPadDirection for transform_caps + * gst/gstbuffer.c: (gst_buffer_new_and_alloc): + * gst/gstutils.h: + cleanup and debugging + +2005-08-24 13:04:31 +0000 Stefan Kost + + Fixed long standing mem-leak + Original commit message from CVS: + * gst/gstelement.c: (gst_element_class_init), + (gst_element_set_state), (activate_pads), + (gst_element_save_thyself): + * tools/gst-compprep.c: (main): + * tools/gst-inspect.c: (print_element_properties_info): + * tools/gst-xmlinspect.c: (print_element_properties): + Fixed long standing mem-leak + +2005-08-24 11:54:37 +0000 Jan Schmidt + + Change GST_MESSAGE_SRC to be a GObject rather than a GstObject, so that applications can sensibly post custom message... + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + * gst/gstbin.c: (bin_bus_handler): + * gst/gstmessage.c: (gst_message_finalize), (_gst_message_copy), + (gst_message_new), (gst_message_new_eos), (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_new_custom): + * gst/gstmessage.h: + * tools/gst-launch.c: (event_loop): + * tools/gst-md5sum.c: (event_loop): + Change GST_MESSAGE_SRC to be a GObject rather than a GstObject, so + that applications can sensibly post custom messages with references + to their own objects. + +2005-08-24 11:44:24 +0000 Wim Taymans + + gst/base/gstbasetransform.*: Many fixes and new features added by Thomas. Can now also do transforms with variable si... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_transform_caps), + (gst_base_transform_transform_size), + (gst_base_transform_configure_caps), (gst_base_transform_setcaps), + (gst_base_transform_get_size), (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer): + * gst/base/gstbasetransform.h: + Many fixes and new features added by Thomas. Can now also do + transforms with variable sizes and a custom fixate_caps function. + +2005-08-24 11:36:49 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_fixate_caps): Check if the caps is fixed already. + Original commit message from CVS: + 2005-08-24 Andy Wingo + * gst/gstpad.c (gst_pad_fixate_caps): Check if the caps is fixed + already. + +2005-08-24 11:22:32 +0000 Wim Taymans + + gst/gstbuffer.c: Some debugging. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_new_and_alloc): + Some debugging. + * gst/gstclock.h: + Cast to ClockTime before formatting to time. + * gst/gstutils.h: + Cleanups. + +2005-08-23 21:32:31 +0000 Stefan Kost + + gracefully handle helper method calls to objects that are not beeing controlled, added test case for that + Original commit message from CVS: + * check/gst-libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gstutils.sgml: + * libs/gst/controller/gst-helper.c: (gst_object_set_controller), + (gst_object_sink_values), (gst_object_get_value_arrays), + (gst_object_get_value_array): + gracefully handle helper method calls to objects that are not beeing + controlled, added test case for that + +2005-08-23 18:17:01 +0000 Wim Taymans + + gst/gstevent.*: Some more debugging output and doc cleanups. + Original commit message from CVS: + * gst/gstevent.c: (_gst_event_copy), (gst_event_new_custom), + (gst_event_new_newsegment), (gst_event_parse_newsegment), + (gst_event_new_tag), (gst_event_parse_tag), (gst_event_new_qos), + (gst_event_parse_qos), (gst_event_new_seek), + (gst_event_parse_seek): + * gst/gstevent.h: + Some more debugging output and doc cleanups. + * gst/gstqueue.c: (gst_queue_handle_sink_event): + Fix possible deadlock. + +2005-08-23 14:25:55 +0000 Stefan Kost + + added about 100 symbols from gstreamer-unused.txt to the right sections fixed more broken comments added GstBus to docs + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/.cvsignore: + * gst/gstbin.h: + * gst/gstbus.c: + * gst/gstelement.c: + * gst/gstevent.h: + added about 100 symbols from gstreamer-unused.txt to the right sections + fixed more broken comments + added GstBus to docs + +2005-08-23 11:53:58 +0000 Stefan Kost + + inlined more doc comments, added missing comments and fixed comments fixed typos + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.cvsignore: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstbuffer.sgml: + * gst/base/gstbasesrc.c: + * gst/gstbin.c: (gst_bin_get_type), (gst_bin_class_init): + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * tools/gst-launch.1.in: + inlined more doc comments, added missing comments and fixed comments + fixed typos + +2005-08-23 11:38:28 +0000 Thomas Vander Stichele + + gst/gstbuffer.c: some debugging + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_new_and_alloc): + some debugging + * gst/gstcaps.h: + whitespace fixes + * gst/gstpad.c: (gst_pad_activate_push), (gst_pad_alloc_buffer): + more debugging + * gst/gststructure.c: (gst_caps_structure_fixate_field_boolean): + * gst/gststructure.h: + add a fixate function for booleans; add a FIXME that these func + names should probably be gst_structure_fixate_* + +2005-08-22 21:03:33 +0000 Stefan Kost + + ported gstchildproxy over from 0.8 ported gst-inspect fixes and enhancements over from 0.8 + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * gst/Makefile.am: + * gst/gstbin.c: (gst_bin_get_type), + (gst_bin_child_proxy_get_child_by_index), + (gst_bin_child_proxy_get_children_count), + (gst_bin_child_proxy_init): + * gst/gstchildproxy.c: (gst_child_proxy_get_child_by_name), + (gst_child_proxy_get_child_by_index), + (gst_child_proxy_get_children_count), (gst_child_proxy_lookup), + (gst_child_proxy_get_property), (gst_child_proxy_get_valist), + (gst_child_proxy_get), (gst_child_proxy_set_property), + (gst_child_proxy_set_valist), (gst_child_proxy_set), + (gst_child_proxy_child_added), (gst_child_proxy_child_removed), + (gst_child_proxy_base_init), (gst_child_proxy_get_type): + * gst/gstchildproxy.h: + * gst/parse/grammar.y: + * tools/gst-inspect.c: (print_interfaces), + (print_element_properties_info), (print_element_info): + ported gstchildproxy over from 0.8 + ported gst-inspect fixes and enhancements over from 0.8 + +2005-08-22 19:48:46 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Also call the transform function if we have ANY caps. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps), + (gst_base_transform_handle_buffer): + Also call the transform function if we have ANY caps. + * gst/gstpipeline.c: (gst_pipeline_set_new_stream_time): + Fix debug info. + +2005-08-22 19:22:34 +0000 Jan Schmidt + + gst/base/gstbasesrc.c: (gst_base_src_event_handler) + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_event_handler) + Don't pretend to handle seek events if the source is not seekable + +2005-08-22 18:48:48 +0000 Jan Schmidt + + gst/base/gstbasesink.c: Remove extra parameter to debug output + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + Remove extra parameter to debug output + * gst/base/gstbasesrc.c: (gst_base_src_send_discont), + (gst_base_src_do_seek), (gst_base_src_activate_push): + Fix seek event handling. + * gst/gstpipeline.c: (gst_pipeline_change_state): + * gst/gstqueue.c: (gst_queue_handle_sink_event), + (gst_queue_src_activate_push): + Don't start the src pad task on FLUSH_STOP if the pad + isn't linked. + Debug changes. + +2005-08-22 15:12:56 +0000 Andy Wingo + + gst/gstutils.h (GST_BOILERPLATE_WITH_INTERFACE): New ghetto macro, implements an interface and gstimplementsinterface... + Original commit message from CVS: + 2005-08-22 Andy Wingo + * gst/gstutils.h (GST_BOILERPLATE_WITH_INTERFACE): New ghetto + macro, implements an interface and gstimplementsinterface for a + new type. + +2005-08-22 15:08:44 +0000 Wim Taymans + + check/gst/gstcaps.c: Added check for gst_static_caps_get() refcounting. + Original commit message from CVS: + * check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite): + Added check for gst_static_caps_get() refcounting. + +2005-08-22 14:35:42 +0000 Wim Taymans + + gst/gstcaps.c: Make _static_caps_get() refcounting sane. + Original commit message from CVS: + * gst/gstcaps.c: (gst_static_caps_get), (gst_caps_to_string): + Make _static_caps_get() refcounting sane. + * gst/gstelement.c: (gst_element_set_state): + Add g_return_val_if_fail() to protect against segfaults. + +2005-08-22 10:37:02 +0000 Stefan Kost + + inlined remaining docs, added missing doc comments + Original commit message from CVS: + * docs/gst/tmpl/gstevent.sgml: + * gst/gstevent.c: + * gst/gstevent.h: + inlined remaining docs, added missing doc comments + +2005-08-22 09:25:51 +0000 Thomas Vander Stichele + + check/gst/gstbin.c: since we don't know when preroll is done, use refcount range check for the sink + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + since we don't know when preroll is done, use refcount range + check for the sink + * gst/check/gstcheck.h: + add macro for checking refcount range + +2005-08-21 16:53:08 +0000 Thomas Vander Stichele + + * check/gst/gstbin.c: + * tests/check/gst/gstbin.c: + figure this out for HT machines + Original commit message from CVS: + figure this out for HT machines + +2005-08-21 15:21:49 +0000 Thomas Vander Stichele + + * check/gst/gstbin.c: + * tests/check/gst/gstbin.c: + some funky HT/multicpu vs single difference + Original commit message from CVS: + some funky HT/multicpu vs single difference + +2005-08-21 15:01:18 +0000 Thomas Vander Stichele + + check/Makefile.am: clean up environment for when registry gets built versus when actual tests are run; valgrind seems... + Original commit message from CVS: + * check/Makefile.am: + clean up environment for when registry gets built versus + when actual tests are run; valgrind seems to not report + leaks if GST_PLUGIN_PATH is set to some specific values + * check/gst/gstbin.c: (GST_START_TEST): + add more refcounting checks; maybe this exposes a + preroll lock bug ? + * common/check.mak: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + * gst/check/gstcheck.h: + * gst/gstbin.c: (bin_element_is_semi_sink), (gst_bin_get_state), + (gst_bin_change_state): + * gst/gstpad.c: (gst_pad_activate_push), (gst_pad_chain): + add/fix debugging/whitespace + +2005-08-21 11:40:44 +0000 Jan Schmidt + + check/gst/gstevent.c: Er, don't call gst_bin_watch_for_state_change you idiot. + Original commit message from CVS: + * check/gst/gstevent.c: (event_probe), (test_event), + (GST_START_TEST): + Er, don't call gst_bin_watch_for_state_change you idiot. + +2005-08-21 11:15:57 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * common: + * tests/check/Makefile.am: + run valgrind with proper env + Original commit message from CVS: + run valgrind with proper env + +2005-08-21 10:54:47 +0000 Jan Schmidt + + check/Makefile.am: Use CHECK_CFLAGS and CHECK_LIBS + Original commit message from CVS: + * check/Makefile.am: + Use CHECK_CFLAGS and CHECK_LIBS + * check/gst/gstevent.c: (event_probe), (test_event), + (GST_START_TEST): + Don't leak events. + * gst/base/gstbasesrc.c: (gst_base_src_send_discont), + (gst_base_src_start), (gst_base_src_stop), + (gst_base_src_activate_push), (gst_base_src_activate_pull), + (gst_base_src_change_state): + Sprinkle gst_base_src_stop liberally around error paths to fix + problems reusing a source after failed state changes. + * gst/base/gsttypefindhelper.c: (helper_find_peek), + (helper_find_suggest), (gst_type_find_helper): + Extra debug output. Don't segfault on GST_PAD_GETRANGEFUNC = NULL + * gst/gstevent.h: + * docs/gst/tmpl/gstevent.sgml: + Migrate part of the docs from the SGML file. Wait for ensonic to + tell me how I did it wrong ;) + * tools/gst-typefind.c: (main): + Extra robustness to state changes between files. + +2005-08-21 10:39:39 +0000 Thomas Vander Stichele + + check/Makefile.am: don't valgrind the controller test - it's leaking - Stefan, HELP + Original commit message from CVS: + * check/Makefile.am: + don't valgrind the controller test - it's leaking - Stefan, HELP + * gst/check/gstcheck.c: (gst_check_message_error), + (gst_check_chain_func), (gst_check_setup_element), + (gst_check_teardown_element), (gst_check_setup_src_pad), + (gst_check_teardown_src_pad), (gst_check_setup_sink_pad), + (gst_check_teardown_sink_pad): + * gst/check/gstcheck.h: + add a bunch of methods to set up elements, and src and sink pads + * check/elements/fakesrc.c: (setup_fakesrc), (cleanup_fakesrc): + * check/elements/identity.c: (setup_identity), (cleanup_identity), + (GST_START_TEST): + use them + * gst/gstmessage.c: + * gst/gsttag.h: + whitespace/doc fixes + +2005-08-20 20:30:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstelement.h: + make GST_ELEMENT_ERROR not do GST_ERROR_OBJECT - these errors should be handled by the application and not always pri... + Original commit message from CVS: + make GST_ELEMENT_ERROR not do GST_ERROR_OBJECT - these errors should + be handled by the application and not always printed as well + +2005-08-20 20:15:53 +0000 Thomas Vander Stichele + + check/Makefile.am: set GST_TOOLS_DIR + Original commit message from CVS: + * check/Makefile.am: + set GST_TOOLS_DIR + * gst/check/gstcheck.c: (gst_check_message_error): + * gst/check/gstcheck.h: + add a fail_unless_equals_int + add fail_unless for error messages + +2005-08-20 14:00:11 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/gst.supp: + * common: + * tests/check/Makefile.am: + * tests/check/gst.supp: + factor out the common stuff + Original commit message from CVS: + factor out the common stuff + +2005-08-20 13:17:42 +0000 Thomas Vander Stichele + + * gst/Makefile.am: + work on builds without check + Original commit message from CVS: + work on builds without check + +2005-08-20 12:47:08 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + renamed test + Original commit message from CVS: + renamed test + +2005-08-20 12:43:18 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * check/gst/gstevent.c: + * tests/check/Makefile.am: + * tests/check/gst/gstevent.c: + put some make-up on the gstevent test + Original commit message from CVS: + put some make-up on the gstevent test + +2005-08-20 12:39:05 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/gst/gstiterator.c: + * check/gst/gstsystemclock.c: + * check/gst/gsttag.c: + * gst/gstclock.c: + * gst/gstiterator.c: + * tests/check/Makefile.am: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + valgrind more tests + Original commit message from CVS: + valgrind more tests + +2005-08-20 12:14:28 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/elements/.gitignore: + * check/elements/fakesrc.c: + * check/elements/identity.c: + * check/gst-libs/controller.c: + * check/gst-libs/gdp.c: + * check/gst/gst.c: + * check/gst/gstbin.c: + * check/gst/gstbuffer.c: + * check/gst/gstbus.c: + * check/gst/gstcaps.c: + * check/gst/gstelement.c: + * check/gst/gstghostpad.c: + * check/gst/gstiterator.c: + * check/gst/gstmessage.c: + * check/gst/gstminiobject.c: + * check/gst/gstobject.c: + * check/gst/gstpad.c: + * check/gst/gststructure.c: + * check/gst/gstsystemclock.c: + * check/gst/gsttag.c: + * check/gst/gstvalue.c: + * check/pipelines/cleanup.c: + * check/pipelines/simple_launch_lines.c: + * check/states/sinks.c: + * configure.ac: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstpad.sgml: + * gst/Makefile.am: + * gst/check/Makefile.am: + * gst/check/gstcheck.c: + * gst/check/gstcheck.h: + * gst/gstminiobject.c: + * libs/gst/check/Makefile.am: + * libs/gst/check/gstcheck.c: + * libs/gst/check/gstcheck.h: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-check-uninstalled.pc.in: + * pkgconfig/gstreamer-check.pc.in: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/fakesrc.c: + * tests/check/elements/identity.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gst.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstbus.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gstminiobject.c: + * tests/check/gst/gstobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gstvalue.c: + * tests/check/libs/controller.c: + * tests/check/libs/gdp.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/simple-launch-lines.c: + move check stuff to its own library to be used by other modules + Original commit message from CVS: + move check stuff to its own library to be used by other modules + +2005-08-19 09:58:42 +0000 Stefan Kost + + eliminate another tmpl file, fix spelling in the long-description + Original commit message from CVS: + * docs/gst/tmpl/gst.sgml: + * gst/gst.c: + eliminate another tmpl file, fix spelling in the long-description + +2005-08-18 16:42:49 +0000 Jan Schmidt + + check/gst/gstevents.c: Should fix build on 64-bit arch's + Original commit message from CVS: + * check/gst/gstevents.c: (GST_START_TEST), (event_probe), + (test_event), (timediff), (gstevents_suite): + Should fix build on 64-bit arch's + +2005-08-18 16:20:24 +0000 Andy Wingo + + Make sure that when a pipeline goes to PLAYING, that data has actually hit the sink. + Original commit message from CVS: + 2005-08-18 Andy Wingo + Make sure that when a pipeline goes to PLAYING, that data has + actually hit the sink. + * check/states/sinks.c (test_sink): A sink that doesn't get any + data shouldn't return SUCCESS for going to either PLAYING or + PAUSED. Test also the return values on the way back down. + * gst/gstelement.c (gst_element_set_state): When changing the + state of an element currently changing state asynchronously, go to + lost-state after commiting the pending state. Makes future calls + to get_state continue to return ASYNC. + * gst/base/gstbasesink.c (gst_base_sink_change_state): Return + ASYNC when going to PLAYING if we still don't have preroll, as can + happen with live sources. + +2005-08-18 16:15:28 +0000 Jan Schmidt + + docs/pwg/advanced-types.xml: Hack long paragraph into 2 chunks as a workaround for buggy jadetex version in sid and b... + Original commit message from CVS: + * docs/pwg/advanced-types.xml: + Hack long paragraph into 2 chunks as a workaround for buggy + jadetex version in sid and breezy that loops infinitely and + eats all RAM. + +2005-08-18 16:00:34 +0000 Jan Schmidt + + check/gst/gstevents.c: Provide more error margin in clock measurements to allow for g_get_current_time inaccuracies. + Original commit message from CVS: + * check/gst/gstevents.c: (GST_START_TEST), (event_probe), + (test_event), (timediff), (gstevents_suite): + Provide more error margin in clock measurements to allow for + g_get_current_time inaccuracies. + +2005-08-18 15:47:16 +0000 Jan Schmidt + + check/gst/gstevents.c: Fix error message output so I might be able to tell why the test works here but fails on the b... + Original commit message from CVS: + * check/gst/gstevents.c: (GST_START_TEST), (event_probe), + (test_event), (timediff), (gstevents_suite): + Fix error message output so I might be able to tell why the + test works here but fails on the build farm. + +2005-08-18 15:31:28 +0000 Jan Schmidt + + check/: I wrote a test! + Original commit message from CVS: + * check/Makefile.am: + * check/gst/gstevents.c: (GST_START_TEST), (event_probe), + (test_event), (timediff), (gstevents_suite), (main): + I wrote a test! + * docs/design/part-seeking.txt: + Spelling correction + * docs/gst/tmpl/gstevent.sgml: + Docs updates. + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + Treat a buffer-without-newsegment the same as a receiving + a newsegment not in time format, and disable syncing to the clock + with a warning. + * gst/gstbus.c: (gst_bus_set_sync_handler): + Assert if anyone tries to replace the existing sync_handler for bus, + as only the owner should be setting it. + * gst/gstevent.h: + Have a fixed set of custom event enums with events identified by + their structure name (as in 0.8), rather than a free-for-all + allowing collisions between enum values from different plugins. + * gst/gstpad.c: (gst_pad_class_init): + Docs change. + * gst/gstqueue.c: (gst_queue_handle_sink_event): + Handle out-of-band downstream events from the sending thread. + +2005-08-17 16:57:01 +0000 Andy Wingo + + gst/gstpipeline.c (gst_pipeline_change_state): Interpret play-timeout==0 to mean no timeout at all. In that case, don... + Original commit message from CVS: + 2005-08-17 Andy Wingo + * gst/gstpipeline.c (gst_pipeline_change_state): Interpret + play-timeout==0 to mean no timeout at all. In that case, don't + bother with a get_state or a warning, just return directly, even + if it's ASYNC. + +2005-08-17 16:33:27 +0000 Andy Wingo + + gst/base/gstbasetransform.c: Debug changes. + Original commit message from CVS: + 2005-08-17 Andy Wingo + * gst/base/gstbasetransform.c: Debug changes. + * gst/gstutils.h: + * gst/gstutils.c (gst_bin_watch_for_state_change): Add function to + ensure bins post state change messages. A bit of a hack but I can't + think of a way to avoid it. + * check/gst/gstbin.c (test_watch_for_state_change): Added test. + +2005-08-16 17:23:55 +0000 Andy Wingo + + gst/base/gstadapter.*: New function, like peek() but you own the data. Not terribly efficient atm. + Original commit message from CVS: + 2005-08-16 Andy Wingo + * gst/base/gstadapter.h: + * gst/base/gstadapter.c (gst_adapter_take): New function, like + peek() but you own the data. Not terribly efficient atm. + +2005-08-16 16:29:04 +0000 Ronald S. Bultje + + gst/gstutils.*: Add two utility functions for tag handling. + Original commit message from CVS: + * gst/gstutils.c: (gst_element_found_tags_for_pad), (push_and_ref), + (gst_element_found_tags): + * gst/gstutils.h: + Add two utility functions for tag handling. + +2005-08-16 12:15:46 +0000 Ronald S. Bultje + + docs/manual/: Fix docs to use _bin_add() before _link(), which fixes the examples with recent core versions (reported... + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + * docs/manual/basics-helloworld.xml: + Fix docs to use _bin_add() before _link(), which fixes the examples + with recent core versions (reported by Madhan Raj M + , #313199). + +2005-08-16 09:42:50 +0000 Wim Taymans + + check/gst/gstvalue.c: Added subtract checks. + Original commit message from CVS: + * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + Added subtract checks. + * docs/design/part-events.txt: + Some more docs about newsegment + * gst/gstbin.c: (gst_bin_change_state), (bin_bus_handler): + Fix FIXME + * gst/gstcaps.c: (gst_caps_to_string): + Add comments, cleanups. + * gst/gstelement.c: (gst_element_save_thyself): + cleanups + * gst/gstvalue.c: (gst_value_collect_int_range), + (gst_string_unwrap), (gst_value_union_int_int_range), + (gst_value_union_int_range_int_range), + (gst_value_intersect_int_int_range), + (gst_value_intersect_int_range_int_range), + (gst_value_intersect_double_double_range), + (gst_value_intersect_double_range_double_range), + (gst_value_intersect_list), (gst_value_subtract_int_int_range), + (gst_value_subtract_int_range_int), + (gst_value_subtract_double_range_double), + (gst_value_subtract_double_range_double_range), + (gst_value_subtract_from_list), (gst_value_subtract_list), + (gst_value_can_compare), (gst_value_compare_fraction): + Cleanups, add comments, remove unneeded asserts. + +2005-08-15 18:15:38 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstbus.c: + * tools/gst-launch.c: + don't convert NULL structures to strings + Original commit message from CVS: + don't convert NULL structures to strings + +2005-08-15 16:57:34 +0000 Stefan Kost + + docs/gst/gstreamer-sections.txt: made some defines private + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + made some defines private + * docs/gst/tmpl/gstconfig.sgml: + * docs/gst/tmpl/gstqueue.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gstutils.sgml: + * docs/pwg/appendix-porting.xml: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesink.c: (gst_fake_sink_class_init): + * gst/elements/gstfakesrc.c: (gst_fake_src_class_init): + * gst/gstelement.c: (gst_element_class_init): + * gst/gstpad.c: (gst_pad_class_init): + * gst/gstqueue.c: (gst_queue_class_init): + * gst/gstxml.c: (gst_xml_class_init): + documented all undocumented signal inline + * libs/gst/controller/gst-controller.h: + added padding + +2005-08-15 09:56:19 +0000 Ronald S. Bultje + + docs/pwg/appendix-porting.xml: Document _set_link_function -> _set_setcaps_function. + Original commit message from CVS: + * docs/pwg/appendix-porting.xml: + Document _set_link_function -> _set_setcaps_function. + +2005-08-14 22:29:07 +0000 Thomas Vander Stichele + + check/Makefile.am: add a .check target for running the check + Original commit message from CVS: + * check/Makefile.am: + add a .check target for running the check + * check/gst-libs/controller.c: (GST_START_TEST): + cosmetic fixups + * check/gst/gstbuffer.c: (GST_START_TEST), (gst_test_suite): + complete checks for gstbuffer; would be nice if I could get the + gcov stuff to work so I can see if I actually completed gstbuffer.c + * check/gstcheck.h: + add ASSERT_BUFFER_REFCOUNT + +2005-08-13 11:45:50 +0000 Thomas Vander Stichele + + * win32/MANIFEST: + remove spider from dist + Original commit message from CVS: + remove spider from dist + +2005-08-13 11:43:13 +0000 Thomas Vander Stichele + + * win32/gstspider.vcproj: + removed from HEAD + Original commit message from CVS: + removed from HEAD + +2005-08-13 10:33:22 +0000 Tim-Philipp Müller + + Add GST_TAG_LANGUAGE_CODE as we have in 0.8, and don't spew out a warning if a tag that is already registered is re-r... + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gsttag.c: (_gst_tag_initialize), (gst_tag_register): + * gst/gsttag.h: + Add GST_TAG_LANGUAGE_CODE as we have in 0.8, and don't + spew out a warning if a tag that is already registered + is re-registered, unless it is re-registered with a + different type (#308438). + +2005-08-12 14:30:31 +0000 Tim-Philipp Müller + + docs/pwg/: Add some paragraphs about state changes in 0.9 to the PWG and the porting guide, in particular about the n... + Original commit message from CVS: + * docs/pwg/appendix-porting.xml: + * docs/pwg/building-state.xml: + Add some paragraphs about state changes in 0.9 to the PWG + and the porting guide, in particular about the new meaning + of GST_STATE_PAUSED and how to write state change functions + with concurrent access by multiple threads in mind. + +2005-08-11 17:39:48 +0000 Stefan Kost + + * ChangeLog: + * docs/gst/gstreamer-docs.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gsthelper.c: + added deprecation and since indexes added since tags + Original commit message from CVS: + added deprecation and since indexes + added since tags + +2005-08-11 14:24:58 +0000 Wim Taymans + + gst/gstghostpad.c: Actually implement (re)setting the target on a ghostpad as described in the docs. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_set_target_unlocked), + (gst_proxy_pad_set_target), (gst_proxy_pad_get_target), + (gst_proxy_pad_dispose), (gst_ghost_pad_do_activate_push), + (gst_ghost_pad_do_link), (gst_ghost_pad_set_internal), + (gst_ghost_pad_new_notarget), (gst_ghost_pad_get_target), + (gst_ghost_pad_set_target): + Actually implement (re)setting the target on a ghostpad + as described in the docs. + +2005-08-10 21:19:01 +0000 Tim-Philipp Müller + + gst/gst.c: Check whether GST_DEBUG_NO_COLOR environment variable is set and disable coloured debug output if that is ... + Original commit message from CVS: + * gst/gst.c: (gst_init_check_with_popt_table), (init_pre): + Check whether GST_DEBUG_NO_COLOR environment variable is + set and disable coloured debug output if that is the case. + +2005-08-10 15:08:03 +0000 Tim-Philipp Müller + + gst/base/gsttypefindhelper.c: The memory returned by gst_type_find_peek() needs to stay valid until the end of a type... + Original commit message from CVS: + * gst/base/gsttypefindhelper.c: (helper_find_peek), + (gst_type_find_helper): + The memory returned by gst_type_find_peek() needs to + stay valid until the end of a typefind function, and + typefind functions may keep results from different + offsets around, so we can't just unref the buffer from + the previous _peek(), but have to save all buffers + returned by _peek() until typefinding is done and only + free them then. + +2005-08-09 16:25:45 +0000 Tim-Philipp Müller + + New macros: GST_ROUND_UP_2() through GST_ROUND_UP_64(). + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.h: + New macros: GST_ROUND_UP_2() through GST_ROUND_UP_64(). + +2005-08-08 16:01:12 +0000 Christian Schaller + + * gstreamer.spec.in: + fix up spec for latest CVS changes + Original commit message from CVS: + fix up spec for latest CVS changes + +2005-08-08 15:08:14 +0000 Ronald S. Bultje + + gst/base/gstbasetransform.c: Fix a pretty good memleak. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_buffer_alloc): + Fix a pretty good memleak. + +2005-08-08 13:55:37 +0000 Tim-Philipp Müller + + gst/gstiterator.h: Fix wrong include and 'make distcheck'. + Original commit message from CVS: + * gst/gstiterator.h: + Fix wrong include and 'make distcheck'. + +2005-08-08 13:38:34 +0000 Ronald S. Bultje + + gst/gstbin.c: Use gst_element_post_message() instead. + Original commit message from CVS: + * gst/gstbin.c: (bin_bus_handler): + Use gst_element_post_message() instead. + +2005-08-08 13:31:09 +0000 Tim-Philipp Müller + + gst/: Add padding to our base elements' class and instance structs and to GstIterator (you will need to rebuild all p... + Original commit message from CVS: + * gst/base/gstadapter.h: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.h: + * gst/base/gstcollectpads.h: + * gst/base/gstpushsrc.h: + * gst/gstiterator.h: + Add padding to our base elements' class and instance structs and + to GstIterator (you will need to rebuild all plugins and apps!) + +2005-08-08 13:17:07 +0000 Ronald S. Bultje + + gst/gstbin.c: Make default message forwarding from child->bus to bin->bus threadsafe and make it not emit warnings if... + Original commit message from CVS: + * gst/gstbin.c: (bin_bus_handler): + Make default message forwarding from child->bus to bin->bus + threadsafe and make it not emit warnings if the parent has no bus. + +2005-08-08 12:14:20 +0000 Ronald S. Bultje + + gst/gstelement.c: On paused->ready, set pad->caps to NULL, as is the documented behaviour in this state change. Fixes... + Original commit message from CVS: + * gst/gstelement.c: (activate_pads): + On paused->ready, set pad->caps to NULL, as is the documented + behaviour in this state change. Fixes playback of series of + media files when visualization is enabled in Totem. + +2005-08-07 13:37:08 +0000 Ronald S. Bultje + + gst/elements/gstcapsfilter.c: Allow NULL as filter-caps (which means "any"). + Original commit message from CVS: + * gst/elements/gstcapsfilter.c: (gst_capsfilter_set_property): + Allow NULL as filter-caps (which means "any"). + +2005-08-05 17:28:30 +0000 Stefan Kost + + * ChangeLog: + * common: + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + adding more entries to the docs and fix small doc-bugs + Original commit message from CVS: + adding more entries to the docs and fix small doc-bugs + +2005-08-05 13:42:10 +0000 Stefan Kost + + * check/gst-libs/.gitignore: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/.gitignore: + * docs/gst/tmpl/gstfakesink.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstfilesink.sgml: + * docs/gst/tmpl/gstfilesrc.sgml: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfilesink.c: + * gst/elements/gstfilesrc.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * tests/check/libs/.gitignore: + migrated some more docs to be inlined in the sources + Original commit message from CVS: + migrated some more docs to be inlined in the sources + +2005-08-05 12:59:46 +0000 Stefan Kost + + * ChangeLog: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbasetransform.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * gst/base/gstcollectpads.c: + * gst/base/gstcollectpads.h: + * libs/gst/base/gstcollectpads.c: + * libs/gst/base/gstcollectpads.h: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gst-interpolation.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/lib.c: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + added long/short desc for controller docs added collectpads base class docs added correct includes to base-class docs + Original commit message from CVS: + added long/short desc for controller docs + added collectpads base class docs + added correct includes to base-class docs + +2005-08-05 10:02:44 +0000 Stefan Kost + + * ChangeLog: + * check/gst-libs/controller.c: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gst.sgml: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbasetransform.sgml: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstbuffer.sgml: + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gstclock.sgml: + * docs/gst/tmpl/gstcompat.sgml: + * docs/gst/tmpl/gstconfig.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstelementdetails.sgml: + * docs/gst/tmpl/gstelementfactory.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gsterror.sgml: + * docs/gst/tmpl/gstevent.sgml: + * docs/gst/tmpl/gstfakesink.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstfilesink.sgml: + * docs/gst/tmpl/gstfilesrc.sgml: + * docs/gst/tmpl/gstfilter.sgml: + * docs/gst/tmpl/gstformat.sgml: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstiterator.sgml: + * docs/gst/tmpl/gstmacros.sgml: + * docs/gst/tmpl/gstmemchunk.sgml: + * docs/gst/tmpl/gstminiobject.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstparse.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gstqueue.sgml: + * docs/gst/tmpl/gstregistry.sgml: + * docs/gst/tmpl/gstregistrypool.sgml: + * docs/gst/tmpl/gststructure.sgml: + * docs/gst/tmpl/gstsystemclock.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gsttagsetter.sgml: + * docs/gst/tmpl/gsttrace.sgml: + * docs/gst/tmpl/gsttrashstack.sgml: + * docs/gst/tmpl/gsttypefind.sgml: + * docs/gst/tmpl/gsttypefindfactory.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gsturihandler.sgml: + * docs/gst/tmpl/gsturitype.sgml: + * docs/gst/tmpl/gstutils.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/gst/tmpl/gstversion.sgml: + * docs/gst/tmpl/gstxml.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/libs/tmpl/gstgetbits.sgml: + * gst/base/gstadapter.c: + * libs/gst/base/gstadapter.c: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + * tests/check/libs/controller.c: + more tests (and fixes) for the controller more docs for the controller integrated companies docs for the adapter + Original commit message from CVS: + more tests (and fixes) for the controller + more docs for the controller + integrated companies docs for the adapter + +2005-08-05 06:57:27 +0000 Thomas Vander Stichele + + * check/gst-libs/controller.c: + * tests/check/libs/controller.c: + cosmetic fixes + Original commit message from CVS: + cosmetic fixes + +2005-08-05 06:55:03 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/elements/gstfakesrc.c: + * docs/gst/tmpl/gst.sgml: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbasetransform.sgml: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstbuffer.sgml: + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gstclock.sgml: + * docs/gst/tmpl/gstcompat.sgml: + * docs/gst/tmpl/gstconfig.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstelementdetails.sgml: + * docs/gst/tmpl/gstelementfactory.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gsterror.sgml: + * docs/gst/tmpl/gstevent.sgml: + * docs/gst/tmpl/gstfakesink.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstfilesink.sgml: + * docs/gst/tmpl/gstfilesrc.sgml: + * docs/gst/tmpl/gstfilter.sgml: + * docs/gst/tmpl/gstformat.sgml: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstiterator.sgml: + * docs/gst/tmpl/gstmacros.sgml: + * docs/gst/tmpl/gstmemchunk.sgml: + * docs/gst/tmpl/gstminiobject.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstparse.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gstqueue.sgml: + * docs/gst/tmpl/gstregistry.sgml: + * docs/gst/tmpl/gstregistrypool.sgml: + * docs/gst/tmpl/gststructure.sgml: + * docs/gst/tmpl/gstsystemclock.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gsttagsetter.sgml: + * docs/gst/tmpl/gsttrace.sgml: + * docs/gst/tmpl/gsttrashstack.sgml: + * docs/gst/tmpl/gsttypefind.sgml: + * docs/gst/tmpl/gsttypefindfactory.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gsturihandler.sgml: + * docs/gst/tmpl/gsturitype.sgml: + * docs/gst/tmpl/gstutils.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/gst/tmpl/gstversion.sgml: + * docs/gst/tmpl/gstxml.sgml: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/libs/tmpl/gstgetbits.sgml: + * tests/check/elements/gstfakesrc.c: + add sizetype tests for fakesrc + Original commit message from CVS: + add sizetype tests for fakesrc + +2005-08-04 19:40:43 +0000 Andy Wingo + + gst/elements/gstcapsfilter.c: Reimplement using basetransform, fixes buffer_alloc proxying among other things. + Original commit message from CVS: + 2005-08-04 Andy Wingo + * gst/elements/gstcapsfilter.c: Reimplement using basetransform, + fixes buffer_alloc proxying among other things. + * gst/base/gstbasetransform.c: + * gst/base/gstbasetransform.h: + Revert patch to gstbasetransform from 7-28 removing + delay_configure. + * gst/base/gstbasetransform.h (GstBaseTransformClass.get_size): + * gst/base/gstbasetransform.c (gst_base_transform_get_size): + Semantics changed, should return not the size of the output buffer + but the byte size of a buffer with a given caps. + * gst/base/gstbasetransform.c (gst_base_transform_getcaps): Better + debug object. + (gst_base_transform_configure_caps): Don't set out_size here: (in, + out) are not the pad caps until setcaps finishes. + (gst_base_transform_buffer_alloc): Proxy the buffer_alloc for the + not-in-place case as well. Deal with changing from in-place to + not-in-place within calling pad_alloc_buffer. Still a bit + concerned about the overhead here... + +2005-08-04 11:56:57 +0000 Edward Hervey + + gst/base/gstadapter.h: Added gst_adapter_get_type() to the header + Original commit message from CVS: + * gst/base/gstadapter.h: + Added gst_adapter_get_type() to the header + +2005-08-03 16:10:06 +0000 Stefan Kost + + * check/Makefile.am: + * tests/check/Makefile.am: + fixed distcheck breakage + Original commit message from CVS: + fixed distcheck breakage + +2005-08-03 15:59:11 +0000 Stefan Kost + + * ChangeLog: + * check/Makefile.am: + * check/gst-libs/controller.c: + * gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gstcontroller.c: + * tests/check/Makefile.am: + * tests/check/libs/controller.c: + added check test suite for the controller fixed a doc typo + Original commit message from CVS: + added check test suite for the controller + fixed a doc typo + +2005-08-03 13:30:18 +0000 Stefan Kost + + * ChangeLog: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstfakesrc.sgml: + * gst/base/README: + * gst/base/gstbasesink.c: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.c: + * gst/base/gstpushsrc.c: + * gst/base/gstpushsrc.h: + * libs/gst/base/README: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + add short/long description docs to base classes add pushsrc to the docs remove consolidated doc fragments + Original commit message from CVS: + add short/long description docs to base classes + add pushsrc to the docs + remove consolidated doc fragments + +2005-08-02 21:39:34 +0000 Stefan Kost + + * pkgconfig/gstreamer-controller-uninstalled.pc.in: + that one too + Original commit message from CVS: + that one too + +2005-08-02 21:38:14 +0000 Stefan Kost + + * pkgconfig/gstreamer-controller.pc.in: + added missing pc files + Original commit message from CVS: + added missing pc files + +2005-08-02 21:35:34 +0000 Stefan Kost + + * ChangeLog: + * configure.ac: + * docs/gst/tmpl/gstevent.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/libs/Makefile.am: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * examples/Makefile.am: + * examples/controller/.gitignore: + * examples/controller/Makefile.am: + * examples/controller/audio-example.c: + * libs/gst/Makefile.am: + * libs/gst/controller/.gitignore: + * libs/gst/controller/Makefile.am: + * libs/gst/controller/gst-controller.c: + * libs/gst/controller/gst-controller.h: + * libs/gst/controller/gst-helper.c: + * libs/gst/controller/gst-interpolation.c: + * libs/gst/controller/gstcontroller.c: + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gsthelper.c: + * libs/gst/controller/gstinterpolation.c: + * libs/gst/controller/lib.c: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-control-uninstalled.pc.in: + * pkgconfig/gstreamer-control.pc.in: + * tests/old/examples/Makefile.am: + * tests/old/examples/controller/.gitignore: + * tests/old/examples/controller/Makefile.am: + * tests/old/examples/controller/audio-example.c: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/controller/.gitignore: + * tests/old/testsuite/controller/Makefile.am: + * tests/old/testsuite/controller/interpolator.c: + * testsuite/Makefile.am: + * testsuite/controller/.gitignore: + * testsuite/controller/Makefile.am: + * testsuite/controller/interpolator.c: + added controller code removed dparam pc files + Original commit message from CVS: + added controller code + removed dparam pc files + +2005-08-01 21:17:01 +0000 Jan Schmidt + + gst/base/gstcollectpads.c: Broadcast the condition when shutting down, to make sure we wake all threads up. Shut down... + Original commit message from CVS: + * gst/base/gstcollectpads.c: (gst_collectpads_finalize), + (gst_collectpads_stop): + Broadcast the condition when shutting down, to make sure we wake all + threads up. Shut down pads on finalize, for safety. + +2005-08-01 17:26:00 +0000 Jan Schmidt + + gst/base/gstbasetransform.c: Handle PAUSED->READY->PAUSED transition after negotiation occurred already. + Original commit message from CVS: + 2005-08-01 Jan Schmidt + * gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_handle_buffer), + (gst_base_transform_change_state): + Handle PAUSED->READY->PAUSED transition after negotiation + occurred already. + * gst/gstmessage.c: (gst_message_init): + Extra piece of debug for new messages. + +2005-08-01 16:43:58 +0000 Stefan Kost + + * docs/libs/Makefile.am: + remove dparams deps from the docs + Original commit message from CVS: + remove dparams deps from the docs + +2005-08-01 16:17:31 +0000 Stefan Kost + + * ChangeLog: + * configure.ac: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstevent.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstformat.sgml: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gststructure.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: + * docs/libs/gstreamer-libs.types: + * libs/gst/Makefile.am: + * libs/gst/control/.gitignore: + * libs/gst/control/Makefile.am: + * libs/gst/control/control.c: + * libs/gst/control/control.h: + * libs/gst/control/dparam.c: + * libs/gst/control/dparam.h: + * libs/gst/control/dparam_smooth.c: + * libs/gst/control/dparam_smooth.h: + * libs/gst/control/dparamcommon.h: + * libs/gst/control/dparammanager.c: + * libs/gst/control/dparammanager.h: + * libs/gst/control/dplinearinterp.c: + * libs/gst/control/dplinearinterp.h: + * libs/gst/control/unitconvert.c: + * libs/gst/control/unitconvert.h: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/dynparams/.gitignore: + * tests/old/testsuite/dynparams/Makefile.am: + * tests/old/testsuite/dynparams/dparamstest.c: + * testsuite/Makefile.am: + * testsuite/dynparams/.gitignore: + * testsuite/dynparams/Makefile.am: + * testsuite/dynparams/dparamstest.c: + * tools/Makefile.am: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + deactivate and remove dparams (libgstcontrol) + Original commit message from CVS: + deactivate and remove dparams (libgstcontrol) + +2005-08-01 11:15:47 +0000 Tim-Philipp Müller + + gst/elements/gsttypefindelement.*: Set caps on all outgoing buffers, not just the first one. + Original commit message from CVS: + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_have_type), (gst_type_find_element_init), + (stop_typefinding), (gst_type_find_element_handle_event), + (gst_type_find_element_chain), (gst_type_find_element_getrange): + * gst/elements/gsttypefindelement.h: + Set caps on all outgoing buffers, not just the first one. + +2005-08-01 09:10:01 +0000 Tim-Philipp Müller + + gst/elements/gsttypefindelement.*: Set caps on first outgoing buffer when we've found the type. + Original commit message from CVS: + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_have_type), + (gst_type_find_element_check_set_buffer_caps), + (gst_type_find_element_init), (stop_typefinding), + (gst_type_find_element_handle_event), + (gst_type_find_element_chain), (gst_type_find_element_getrange): + * gst/elements/gsttypefindelement.h: + Set caps on first outgoing buffer when we've found the type. + +2005-08-01 08:52:31 +0000 Tim-Philipp Müller + + docs/gst/: Remove some old cruft from docs. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstscheduler.sgml: + * docs/gst/tmpl/gstschedulerfactory.sgml: + Remove some old cruft from docs. + +2005-07-31 11:59:33 +0000 Tim-Philipp Müller + + gst/gstpad.h: Fix inline docs for GstPadLinkReturn. + Original commit message from CVS: + * gst/gstpad.h: + Fix inline docs for GstPadLinkReturn. + * gst/gststructure.c: (gst_structure_has_name): + * gst/gststructure.h: + * docs/gst/gstreamer-sections.txt: + New API: gst_structure_has_name(). + +2005-07-30 15:00:07 +0000 Tim-Philipp Müller + + configure.ac: Use AC_SYS_LARGEFILE, which will set _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE in config.h as required... + Original commit message from CVS: + * configure.ac: + Use AC_SYS_LARGEFILE, which will set _FILE_OFFSET_BITS=64 + and _LARGEFILE_SOURCE in config.h as required. Do not + export those flags in our .pc files any longer (#142209). + Remove unused GST_DISABLE_OMEGA_COTHREADS stuff. + * gst/elements/gstfilesink.c: (gst_file_sink_class_init), + (gst_file_sink_do_seek), (gst_file_sink_event), + (gst_file_sink_get_current_offset), (gst_file_sink_render): + Redo seek/tell calls with large file support in mind; add some + debugging messages; add log message that tells us when large + file support is unavailable or not enabled for some reason. + * gst/elements/gstfilesrc.c: (gst_file_src_class_init): + Add log message that tells us when large file support + is unavailable or not enabled for some reason. + +2005-07-29 19:22:28 +0000 Wim Taymans + + check/gst/gstghostpad.c: Added test for removing an element with ghostpad from a bin. + Original commit message from CVS: + * check/gst/gstghostpad.c: (GST_START_TEST), (gst_ghost_pad_suite): + Added test for removing an element with ghostpad from a bin. + Fixed test as current implementation does the right thing. + * gst/gstghostpad.c: (gst_proxy_pad_class_init), + (gst_proxy_pad_do_query_type), (gst_proxy_pad_do_event), + (gst_proxy_pad_do_query), (gst_proxy_pad_do_internal_link), + (gst_proxy_pad_do_bufferalloc), (gst_proxy_pad_do_activate), + (gst_proxy_pad_do_activatepull), (gst_proxy_pad_do_activatepush), + (gst_proxy_pad_do_chain), (gst_proxy_pad_do_getrange), + (gst_proxy_pad_do_checkgetrange), (gst_proxy_pad_do_getcaps), + (gst_proxy_pad_do_acceptcaps), (gst_proxy_pad_do_fixatecaps), + (gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target), + (gst_proxy_pad_get_target), (gst_proxy_pad_init), + (gst_proxy_pad_dispose), (gst_proxy_pad_finalize), + (gst_ghost_pad_class_init), (gst_ghost_pad_do_activate_push), + (gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink), + (gst_ghost_pad_set_internal), (gst_ghost_pad_dispose), + (gst_ghost_pad_new_notarget), (gst_ghost_pad_new), + (gst_ghost_pad_get_target), (gst_ghost_pad_set_target): + * gst/gstghostpad.h: + Clean up ghostpads, remove properties for internal stuff. + Make threadsafe. + Fix refcounting. + Prepare for switching targets, not all use cases work yet. + +2005-07-29 19:19:29 +0000 Wim Taymans + + docs/design/part-gstghostpad.txt: Small update. + Original commit message from CVS: + * docs/design/part-gstghostpad.txt: + Small update. + * gst/gstbin.c: (unlink_pads), (gst_bin_add_func), + (gst_bin_remove_func): + Unlinking pads while holding the bin LOCK is not a good + idea. + * gst/gstpad.c: (gst_pad_class_init), + (gst_pad_link_check_hierarchy), (gst_pad_get_caps_unlocked), + (gst_pad_accept_caps), (gst_pad_set_caps), (gst_pad_send_event): + No prob setting template after creating the pad. + +2005-07-29 15:34:52 +0000 Jan Schmidt + + gst/gstbus.c: gst_bus_poll may be called from other threads. Handle this nicely by not making poll_data disappear off... + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_set_flushing), (gst_bus_pop), + (gst_bus_peek), (gst_bus_source_dispatch), + (gst_bus_add_watch_full), (poll_handler), (poll_timeout), + (poll_destroy), (poll_destroy_timeout), (gst_bus_poll): + gst_bus_poll may be called from other threads. Handle + this nicely by not making poll_data disappear off the + stack once gst_bus_poll returns. + gst_bus_peek now increments the refcount on the returned + message. + +2005-07-29 11:29:52 +0000 Wim Taymans + + docs/design/part-gstghostpad.txt: Overview of current GhostPad datastructures and use cases for changing the target. + Original commit message from CVS: + * docs/design/part-gstghostpad.txt: + Overview of current GhostPad datastructures and use + cases for changing the target. + +2005-07-28 15:38:46 +0000 Wim Taymans + + check/gst/gstbin.c: Added checks for hierarchy consistency whan adding linked elements to bins. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST), (gst_bin_suite): + Added checks for hierarchy consistency whan adding linked + elements to bins. + * check/gst/gstelement.c: (GST_START_TEST), (gst_element_suite): + Added check to test element scheduling without bin/pipeline. + * check/pipelines/simple_launch_lines.c: (GST_START_TEST): + First add elements to bin, then link. + * gst/gstbin.c: (unlink_pads), (gst_bin_add_func), + (gst_bin_remove_func): + Unlink pads from elements added/removed from bin to maintain + hierarchy consistency. + +2005-07-28 11:49:56 +0000 Ronald S. Bultje + + gst/base/gstbasetransform.*: Remove broken delay_configure (fixes renegotiation of software scaling pipelines); remov... + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_setcaps), + (gst_base_transform_handle_buffer): + * gst/base/gstbasetransform.h: + Remove broken delay_configure (fixes renegotiation of software + scaling pipelines); remove some leftover printf()s. + +2005-07-28 11:24:33 +0000 Wim Taymans + + check/gst/gstghostpad.c: Added some more tests for wrong hierarchy + Original commit message from CVS: + * check/gst/gstghostpad.c: (GST_START_TEST), (gst_ghost_pad_suite): + Added some more tests for wrong hierarchy + * docs/design/part-overview.txt: + Some updates. + * gst/gstbin.c: (gst_bin_remove_func), (gst_bin_dispose): + Cleanups. + * gst/gstelement.c: (gst_element_remove_pad), (gst_element_seek), + (gst_element_dispose): + Some more cleanups. + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked), + (gst_pad_link_check_hierarchy), (gst_pad_link_prepare), + (gst_pad_get_caps_unlocked), (gst_pad_accept_caps), + (gst_pad_set_caps), (gst_pad_send_event): + Check for correct hierarchy when linking pads. Moving to + strict requirement for ghostpads when linking elements in + different bins. + * gst/gstpad.h: + Clean ups. Added WRONG_HIERARCHY return value. + +2005-07-28 10:38:02 +0000 Ronald S. Bultje + + gst/base/gstbasetransform.c: Better debug if no transform is possible. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_setcaps): + Better debug if no transform is possible. + +2005-07-27 20:22:48 +0000 Wim Taymans + + docs/random/wtay/network-transp: Some old doc I had. + Original commit message from CVS: + * docs/random/wtay/network-transp: + Some old doc I had. + +2005-07-27 19:00:36 +0000 Wim Taymans + + libs/gst/dataprotocol/dataprotocol.c: Fix serialization of seek events. + Original commit message from CVS: + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), + (gst_dp_event_from_packet): + Fix serialization of seek events. + +2005-07-27 18:47:48 +0000 Wim Taymans + + Fix compilation and fix event serialization. + Original commit message from CVS: + * check/gst-libs/gdp.c: (GST_START_TEST): + * gst/elements/gstfakesink.c: (gst_fake_sink_event): + Fix compilation and fix event serialization. + +2005-07-27 18:33:03 +0000 Wim Taymans + + Some docs updates + Original commit message from CVS: + * CHANGES-0.9: + * docs/design/part-TODO.txt: + * docs/design/part-events.txt: + Some docs updates + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_do_sync), + (gst_base_sink_activate_push), (gst_base_sink_activate_pull): + * gst/base/gstbasesrc.c: (gst_base_src_send_discont), + (gst_base_src_do_seek), (gst_base_src_event_handler), + (gst_base_src_loop): + * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps), + (gst_base_transform_configure_caps), (gst_base_transform_setcaps), + (gst_base_transform_get_size), (gst_base_transform_buffer_alloc), + (gst_base_transform_event), (gst_base_transform_handle_buffer), + (gst_base_transform_set_passthrough), + (gst_base_transform_is_passthrough): + * gst/elements/gstfakesink.c: (gst_fake_sink_event): + * gst/elements/gstfilesink.c: (gst_file_sink_event): + Event updates. + * gst/gstbuffer.h: + Use faster casts. + * gst/gstelement.c: (gst_element_seek): + * gst/gstelement.h: + Update gst_element_seek. + * gst/gstevent.c: (gst_event_finalize), (_gst_event_copy), + (gst_event_new), (gst_event_new_custom), (gst_event_get_structure), + (gst_event_new_flush_start), (gst_event_new_flush_stop), + (gst_event_new_eos), (gst_event_new_newsegment), + (gst_event_parse_newsegment), (gst_event_new_tag), + (gst_event_parse_tag), (gst_event_new_filler), (gst_event_new_qos), + (gst_event_parse_qos), (gst_event_new_seek), + (gst_event_parse_seek), (gst_event_new_navigation): + * gst/gstevent.h: + Make GstEvent use GstStructure. Add parsing code, make sure the + API is sufficiently generic. + Mark possible directions of events and serialization. + * gst/gstmessage.c: (gst_message_init), (gst_message_finalize), + (_gst_message_copy), (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_new_custom), + (gst_message_parse_segment_start), + (gst_message_parse_segment_done): + Small cleanups. + * gst/gstpad.c: (gst_pad_get_caps_unlocked), (gst_pad_accept_caps), + (gst_pad_set_caps), (gst_pad_send_event): + Update for new events. + Catch events sent in wrong directions. + * gst/gstqueue.c: (gst_queue_link_src), + (gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop), + (gst_queue_handle_src_query): + Event updates. + * gst/gsttag.c: + * gst/gsttag.h: + Remove event code from this file. + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_event), + (gst_dp_event_from_packet): + Event updates. + +2005-07-27 15:05:45 +0000 Ronald S. Bultje + + gst/base/gstbasetransform.c: Make debugging actually useful. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_getcaps), + (gst_base_transform_configure_caps), (gst_base_transform_setcaps), + (gst_base_transform_get_size), (gst_base_transform_handle_buffer): + Make debugging actually useful. + +2005-07-25 12:31:08 +0000 Ronald S. Bultje + + gst/gstpad.c: Implement default fixation once again, so that gst_pad_fixate() actually does anything at all. This pro... + Original commit message from CVS: + * gst/gstpad.c: (fixate_value), (gst_pad_default_fixate), + (gst_pad_fixate_caps): + Implement default fixation once again, so that gst_pad_fixate() + actually does anything at all. This probably needs to be some + sort of a last resort, and use profile-based fixation first, but + since that doesn't exist yet, this is the best we have. Fixes + visualization in Totem. + +2005-07-22 11:47:10 +0000 Wim Taymans + + docs/design/part-events.txt: Small update. + Original commit message from CVS: + * docs/design/part-events.txt: + Small update. + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync), (gst_base_sink_activate_push), + (gst_base_sink_activate_pull): + Some more comments. + * gst/elements/gstfakesrc.c: (gst_fake_src_class_init), + (gst_fake_src_create): + Fix handoff marshall. + * gst/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_transform_ip): + We're a real inplace element. + * gst/gstbus.c: (gst_bus_post): + Added some comments. + * tests/lat.c: (fakesrc), (fakesink), (simple), (queue), (main): + * tests/muxing/case1.c: (main): + * tests/sched/dynamic-pipeline.c: (main): + * tests/sched/interrupt1.c: (main): + * tests/sched/interrupt2.c: (main): + * tests/sched/interrupt3.c: (main): + * tests/sched/runxml.c: (main): + * tests/sched/sched-stress.c: (main): + * tests/seeking/seeking1.c: (event_received), (main): + * tests/threadstate/threadstate2.c: (bus_handler), (timeout_func), + (main): + * tests/threadstate/threadstate3.c: (main): + * tests/threadstate/threadstate4.c: (main): + * tests/threadstate/threadstate5.c: (main): + Fix the tests. + +2005-07-21 17:22:13 +0000 Wim Taymans + + docs/design/part-seeking.txt: Some small additions. + Original commit message from CVS: + * docs/design/part-seeking.txt: + Some small additions. + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_get_times), (gst_base_sink_do_sync), + (gst_base_sink_activate_push), (gst_base_sink_activate_pull): + * gst/base/gstbasesink.h: + discont values are gint64, handle the math correctly. + * gst/base/gstbasesrc.c: (gst_base_src_loop): + Make the basesrc report error if the source pad is not linked. + * gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain), + (gst_queue_loop), (gst_queue_handle_src_query), + (gst_queue_src_activate_push): + Make queue collect data even if the srcpad is not linked. + Start pushing out data as soon as it is linked. + * gst/gstutils.c: (gst_element_unlink), (gst_flow_get_name): + * gst/gstutils.h: + Added gst_flow_get_name() to ease error reporting. + +2005-07-20 18:02:13 +0000 Wim Taymans + + gst/gstmessage.*: Added a bunch of messages for advanced seeking. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_segment_start), + (gst_message_new_segment_done), (gst_message_parse_segment_start), + (gst_message_parse_segment_done): + * gst/gstmessage.h: + Added a bunch of messages for advanced seeking. + * gst/parse/grammar.y: + * libs/gst/control/dparammanager.c: (gst_dpman_set_parent), + (gst_dpman_state_changed): + Fix some new-pad -> pad-added signals + +2005-07-20 17:22:27 +0000 Ronald S. Bultje + + docs/: Document new-pad/state-change signal renames and the FixedList type rename. + Original commit message from CVS: + * docs/manual/appendix-porting.xml: + * docs/pwg/appendix-porting.xml: + Document new-pad/state-change signal renames and the FixedList + type rename. + +2005-07-20 17:16:44 +0000 Ronald S. Bultje + + GstElement::new-pad -> pad-added, GstElement::state-change -> state-changed, GstValueFixedList -> GstValueArray, add ... + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-pads.xml: + * docs/random/ds/0.9-suggested-changes: + * gst/gstelement.c: (gst_element_class_init), (gst_element_seek): + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstformat.h: + * gst/gstquery.h: + * gst/gststructure.c: (gst_structure_value_get_generic_type), + (gst_structure_parse_array), (gst_structure_parse_value): + * gst/gstvalue.c: (gst_type_is_fixed), + (gst_value_list_prepend_value), (gst_value_list_append_value), + (gst_value_list_get_size), (gst_value_list_get_value), + (gst_value_transform_array_string), (gst_value_serialize_array), + (gst_value_deserialize_array), (gst_value_intersect_array), + (gst_value_is_fixed), (_gst_value_initialize): + * gst/gstvalue.h: + GstElement::new-pad -> pad-added, GstElement::state-change -> + state-changed, GstValueFixedList -> GstValueArray, add format and + flags as their own arguments in gst_element_seek() (should improve + "bindeability"), remove function generators since they don't work + under a whole bunch of compilers (they were deprecated already + anyway). + +2005-07-20 17:15:19 +0000 Thomas Vander Stichele + + * check/gst.supp: + * common: + * tests/check/gst.supp: + patch from Edgard to properly suppress these warnings + Original commit message from CVS: + patch from Edgard to properly suppress these warnings + +2005-07-20 16:20:39 +0000 Ronald S. Bultje + + gst/gstinfo.*: Fix illegal cast on some platforms (#309253). + Original commit message from CVS: + * gst/gstinfo.c: (_gst_debug_nameof_funcptr), + (_gst_debug_register_funcptr): + * gst/gstinfo.h: + Fix illegal cast on some platforms (#309253). + +2005-07-20 11:35:18 +0000 Ronald S. Bultje + + gst/gstmessage.*: Add _new_custom, make _new_application a macro to _new_custom. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_custom): + * gst/gstmessage.h: + Add _new_custom, make _new_application a macro to _new_custom. + +2005-07-20 10:58:10 +0000 Wim Taymans + + gst/base/gstbasesrc.*: Add a gboolean to decide when to push out a discont. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_init), + (gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start): + * gst/base/gstbasesrc.h: + Add a gboolean to decide when to push out a discont. + * gst/gstqueue.c: (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_loop), (gst_queue_handle_src_query), + (gst_queue_sink_activate_push), (gst_queue_src_activate_push), + (gst_queue_set_property), (gst_queue_get_property): + Some cleanups. + * tests/threadstate/threadstate1.c: (main): + Make a thread test compile and run... very silly.. + +2005-07-20 10:13:46 +0000 Ronald S. Bultje + + docs/manual/appendix-porting.xml: Mention removal of libgstgconf-0.9.la and existence of gconf elements. + Original commit message from CVS: + * docs/manual/appendix-porting.xml: + Mention removal of libgstgconf-0.9.la and existence of gconf + elements. + +2005-07-20 08:29:06 +0000 Ronald S. Bultje + + docs/pwg/: Document base classes, update sections of n-to-1 and 1-to-n (muxer, fix some code examples and links and u... + Original commit message from CVS: + * docs/pwg/advanced-clock.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/intro-preface.xml: + * docs/pwg/other-base.xml: + * docs/pwg/other-manager.xml: + * docs/pwg/other-nton.xml: + * docs/pwg/other-ntoone.xml: + * docs/pwg/other-oneton.xml: + * docs/pwg/pwg.xml: + Document base classes, update sections of n-to-1 and 1-to-n (muxer, + demuxer), remove n-to-n (was never written), fix some code examples + and links and update the porting section to include all this. + +2005-07-19 17:46:37 +0000 Wim Taymans + + gst/gstqueue.*: Propagate GstFlowReturn more intelligently upstream and output an ERROR/EOS when streaming stopped du... + Original commit message from CVS: + * gst/gstqueue.c: (gst_queue_init), (gst_queue_handle_sink_event), + (gst_queue_chain), (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_get_property): + * gst/gstqueue.h: + Propagate GstFlowReturn more intelligently upstream and output + an ERROR/EOS when streaming stopped due to fatal error. + +2005-07-19 14:52:59 +0000 Wim Taymans + + tools/gst-launch.c: Don't block forever for the state change to complete, the pipeline already did with a sensible ti... + Original commit message from CVS: + * tools/gst-launch.c: (check_intr), (event_loop), (main): + Don't block forever for the state change to complete, the + pipeline already did with a sensible timeout. + +2005-07-19 13:43:50 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Make sure we never call the create function is we got deactivated. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_get_range): + Make sure we never call the create function is we + got deactivated. + +2005-07-19 11:27:07 +0000 Christian Schaller + + * gstreamer.spec.in: + update for latest changes + Original commit message from CVS: + update for latest changes + +2005-07-19 10:40:49 +0000 Andy Wingo + + gst/parse/parse.l: Attempt to solve bug #172815. + Original commit message from CVS: + 2005-07-19 Andy Wingo + * gst/parse/parse.l: Attempt to solve bug #172815. + +2005-07-19 09:19:06 +0000 Wim Taymans + + Small docs updates. + Original commit message from CVS: + * docs/design/part-clocks.txt: + * docs/design/part-events.txt: + * gst/base/gstbasesrc.c: (gst_base_src_do_seek): + Small docs updates. + Only update the seeking values when we are not + busy streaming. + +2005-07-18 17:43:52 +0000 Jan Schmidt + + * ChangeLog: + * gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.c: + Oops, ignore the result of gst_pad_push_event here. + Original commit message from CVS: + Oops, ignore the result of gst_pad_push_event here. + +2005-07-18 17:12:36 +0000 Jan Schmidt + + gst/base/gstbasesrc.c: Send discont event from the loop function, as pads aren't activated yet in the activate_push h... + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_loop), + (gst_base_src_activate_push): + Send discont event from the loop function, as pads + aren't activated yet in the activate_push handler. + * gst/gstbin.c: (bin_bus_handler): + Don't leak element name. + +2005-07-18 14:47:39 +0000 Andy Wingo + + configure.ac: Use AS_LIBTOOL_TAGS. + Original commit message from CVS: + 2005-07-18 Andy Wingo + * configure.ac: Use AS_LIBTOOL_TAGS. + +2005-07-18 12:58:27 +0000 Wim Taymans + + docs/gst/gstreamer.types: Remove deleted types. + Original commit message from CVS: + * docs/gst/gstreamer.types: + Remove deleted types. + +2005-07-18 12:49:53 +0000 Wim Taymans + + * ChangeLog: + * check/elements/gstfakesrc.c: + * configure.ac: + * gst/Makefile.am: + * gst/gst.c: + * gst/gst.h: + * gst/gst_private.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstbus.h: + * gst/gstconfig.h.in: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gsterror.c: + * gst/gsterror.h: + * gst/gstevent.h: + * gst/gstghostpad.c: + * gst/gstindex.c: + * gst/gstinfo.c: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstminiobject.h: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstparse.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstpluginfeature.h: + * gst/gstquery.h: + * gst/gstscheduler.c: + * gst/gstscheduler.h: + * gst/gststructure.h: + * gst/gsttask.c: + * gst/gsttask.h: + * gst/gsttypefind.h: + * gst/gsttypes.h: + * gst/registries/gstlibxmlregistry.c: + * gst/registries/gstxmlregistry.c: + * gst/schedulers/threadscheduler.c: + * libs/gst/control/dparammanager.h: + * tests/check/elements/gstfakesrc.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + Removed plugable schedulers. + Original commit message from CVS: + Removed plugable schedulers. + Removed Scheduler/Manager from elements. + Removed gsttypes.h, rearranged includes. + Removed dependency pad<->element, element<>pipeline, and + various others, fix includes. + implement gst_pad_get_parent() with gst_object_get_parent() + Make GstTask sefcontained. + Fix _get_state() on GstBin, it did not return ASYNC with a 0 + timeout. + Fix endless loop in iterator_fold_with_resync. + +2005-07-18 09:22:55 +0000 Wim Taymans + + gst/: Remove old file. + Original commit message from CVS: + * gst/Makefile.am: + * gst/gstarch.h: + Remove old file. + +2005-07-18 08:51:31 +0000 Wim Taymans + + gst/Makefile.am: No more cothreads.h + Original commit message from CVS: + * gst/Makefile.am: + No more cothreads.h + +2005-07-18 08:43:27 +0000 Wim Taymans + + gst/cothreads.*: Let's remove these. + Original commit message from CVS: + * gst/cothreads.c: + * gst/cothreads.h: + Let's remove these. + +2005-07-18 08:28:48 +0000 Wim Taymans + + docs/design/: Some more docs in the works. + Original commit message from CVS: + * docs/design/part-dynamic.txt: + * docs/design/part-events.txt: + * docs/design/part-seeking.txt: + Some more docs in the works. + * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps), + (gst_base_transform_getcaps), (gst_base_transform_configure_caps), + (gst_base_transform_setcaps), (gst_base_transform_get_size), + (gst_base_transform_buffer_alloc), (gst_base_transform_event), + (gst_base_transform_handle_buffer), + (gst_base_transform_sink_activate_push), + (gst_base_transform_src_activate_pull), + (gst_base_transform_set_passthrough), + (gst_base_transform_is_passthrough): + Refcounting fixes. + * gst/gstbus.c: (gst_bus_source_dispatch), (gst_bus_poll): + Cleanups. + * gst/gstevent.c: (gst_event_finalize): + Set SRC to NULL. + * gst/gstutils.c: (gst_element_unlink), + (gst_pad_get_parent_element), (gst_pad_proxy_getcaps), + (gst_pad_proxy_setcaps): + * gst/gstutils.h: + Add _get_parent_element() to get a pads parent as an element. + +2005-07-17 22:44:00 +0000 Wim Taymans + + check/gst/gstbin.c: Remove bogus test. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Remove bogus test. + +2005-07-17 22:26:02 +0000 Wim Taymans + + gst/base/gstbasesink.c: Refcounting fixes. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_pad_getcaps), + (gst_base_sink_pad_setcaps), (gst_base_sink_pad_buffer_alloc), + (gst_base_sink_preroll_queue_flush), (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_do_sync), + (gst_base_sink_chain), (gst_base_sink_loop), + (gst_base_sink_deactivate), (gst_base_sink_activate_push), + (gst_base_sink_activate_pull), (gst_base_sink_change_state): + Refcounting fixes. + Fix logic for returning ASYNC when not prerolled. + +2005-07-17 22:22:52 +0000 Wim Taymans + + gst/gstqueue.c: Fix nasty refcount bug. + Original commit message from CVS: + * gst/gstqueue.c: (gst_queue_handle_sink_event): + Fix nasty refcount bug. + +2005-07-16 19:25:41 +0000 Philippe Kalaf + + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + Moved fdsrc to gst-plugins. + Original commit message from CVS: + Moved fdsrc to gst-plugins. + +2005-07-16 15:43:10 +0000 Philippe Kalaf + + * ChangeLog: + Forgot changelog entry + Original commit message from CVS: + Forgot changelog entry + +2005-07-16 15:41:04 +0000 Philippe Kalaf + + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * gst/elements/gstfdsrc.c: + * gst/elements/gstfdsrc.h: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfdsrc.h: + gst/elements/gstfdsrc.c gst/elements/gstfdsrc.h gst/elements/gstelements.c gst/elements/Makefile.am + Original commit message from CVS: + 2005-07-16 Philippe Khalaf + * gst/elements/gstfdsrc.c + * gst/elements/gstfdsrc.h + * gst/elements/gstelements.c + * gst/elements/Makefile.am + Ported fdsrc to 0.9. + +2005-07-16 14:52:15 +0000 Wim Taymans + + gst/base/gstbasesink.c: Fix compile error. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_do_sync): + Fix compile error. + +2005-07-16 14:41:25 +0000 Wim Taymans + + gst/base/gstbasesink.*: Store and use discont values when syncing buffers as described in design docs. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_event), (gst_base_sink_get_times), + (gst_base_sink_do_sync), (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + Store and use discont values when syncing buffers as described + in design docs. + * gst/base/gstbasesrc.c: (gst_base_src_send_discont), + (gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start), + (gst_base_src_activate_push): + Push discont event when starting. + * gst/elements/gstidentity.c: (gst_identity_transform): + Small cleanups. + * gst/gstbin.c: (gst_bin_change_state): + Small cleanups in base_time distribution. + * gst/gstelement.c: (gst_element_set_base_time), + (gst_element_get_base_time), (gst_element_change_state): + * gst/gstelement.h: + Added methods for the base_time of the element. + Some MT fixes. + * gst/gstpipeline.c: (gst_pipeline_send_event), + (gst_pipeline_change_state), (gst_pipeline_set_new_stream_time), + (gst_pipeline_get_last_stream_time): + * gst/gstpipeline.h: + MT fixes. + Handle seeking as described in design doc, remove stream_time + hack. + Cleanups clock and stream_time selection code. Added accessors + for the stream_time. + +2005-07-16 14:06:21 +0000 Andy Wingo + + gst/gsterror.c (_gst_core_errors_init): Use the magic word.. + Original commit message from CVS: + 2005-07-16 Andy Wingo + * gst/gsterror.c (_gst_core_errors_init): Use the magic word.. + +2005-07-16 13:50:37 +0000 Wim Taymans + + check/gst/gstbin.c: Make elements silent as the deep_notify refs the parent, which might make the test fail. + Original commit message from CVS: + * check/gst/gstbin.c: (GST_START_TEST): + Make elements silent as the deep_notify refs the + parent, which might make the test fail. + * gst/gstghostpad.c: (gst_ghost_pad_do_activate_push): + Don't hold the lock for too long. + +2005-07-16 12:33:13 +0000 Tim-Philipp Müller + + gst/base/gstbasesrc.c: Don't unref the caps we passed to gst_caps_make_writable() after passing them. gst_caps_make_w... + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_default_negotiate): + Don't unref the caps we passed to gst_caps_make_writable() after + passing them. gst_caps_make_writable() will do that for us. + +2005-07-15 16:10:41 +0000 Andy Wingo + + gst/gstcaps.h (gst_caps_is_simple): Removed deprecated macro (#157311). + Original commit message from CVS: + 2005-07-15 Andy Wingo + * gst/gstcaps.h (gst_caps_is_simple): Removed deprecated macro + (#157311). + +2005-07-15 14:59:22 +0000 Andy Wingo + + gst/elements/gstidentity.c (marshal_VOID__MINIOBJECT): Write our own marshalling function for the handoff signal. Pro... + Original commit message from CVS: + 2005-07-15 Andy Wingo + * gst/elements/gstidentity.c (marshal_VOID__MINIOBJECT): Write our + own marshalling function for the handoff signal. Properly type the + buffer as a buffer. Fixes some warnings. Should do a more general + solution. + (gst_identity_class_init): Plug into the right marshaller. + +2005-07-15 13:44:19 +0000 Wim Taymans + + docs/design/: Updated docs, mostly DISCONT related. + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-clocks.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-events.txt: + * docs/design/part-gstpipeline.txt: + Updated docs, mostly DISCONT related. + +2005-07-15 12:55:30 +0000 Tim-Philipp Müller + + docs/pwg/building-pads.xml: s/GST_PAD_LINK_REFUSED/FALSE/ in gst_my_filter_setcaps() + Original commit message from CVS: + * docs/pwg/building-pads.xml: + s/GST_PAD_LINK_REFUSED/FALSE/ in gst_my_filter_setcaps() + +2005-07-15 11:05:52 +0000 Andy Wingo + + * tools/gst-typefind.c: + remove irrelevant code + Original commit message from CVS: + remove irrelevant code + +2005-07-15 11:04:18 +0000 Andy Wingo + + tools/gst-typefind.c: Update, add copyright block. + Original commit message from CVS: + 2005-07-15 Andy Wingo + * tools/gst-typefind.c: Update, add copyright block. + * gst/base/gstbasesrc.c (gst_base_src_default_negotiate): + Normalize and truncate caps before fixation. + * gst/gstcaps.h: + * gst/gstcaps.c (gst_caps_truncate): New function, destructively + discards all but the first structure from its argument. + +2005-07-15 10:41:32 +0000 Wim Taymans + + gst/base/gstbasetransform.*: Make passthrough work using the bufferpools. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_init), + (gst_base_transform_transform_caps), (gst_base_transform_getcaps), + (gst_base_transform_configure_caps), (gst_base_transform_setcaps), + (gst_base_transform_get_size), (gst_base_transform_buffer_alloc), + (gst_base_transform_handle_buffer), (gst_base_transform_getrange), + (gst_base_transform_chain), (gst_base_transform_change_state), + (gst_base_transform_set_passthrough), + (gst_base_transform_is_passthrough): + * gst/base/gstbasetransform.h: + Make passthrough work using the bufferpools. + Changed API a bit, subclasses have to write into a buffer + provided by the base class. + More debug info in nego functions. + * gst/elements/gstidentity.c: (gst_identity_init), + (gst_identity_transform): + Port to new base class. + +2005-07-15 10:30:49 +0000 Wim Taymans + + Totally dump messages in -launch with the -m option. + Original commit message from CVS: + * gst/gstmessage.c: (gst_message_new_state_changed): + * tools/gst-launch.c: (event_loop), (main): + Totally dump messages in -launch with the -m option. + Fix message name for State messages, + +2005-07-14 18:45:51 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Post error messages on errors. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_loop): + Post error messages on errors. + +2005-07-14 18:10:04 +0000 Wim Taymans + + gst/gstcaps.c: Remove debug info. + Original commit message from CVS: + * gst/gstcaps.c: (gst_caps_do_simplify): + Remove debug info. + * gst/gsterror.h: + Define error for stream stopped. + * gst/gstghostpad.c: (gst_proxy_pad_do_bufferalloc), + (gst_proxy_pad_do_chain), (gst_proxy_pad_do_getrange): + Do proper return values. + * gst/gstpad.c: (gst_pad_get_caps_unlocked), (gst_pad_accept_caps), + (gst_pad_set_caps), (gst_pad_chain), (gst_pad_push), + (gst_pad_get_range): + Better return values. + * gst/gstpad.h: + Reorganise return values, add macro to check for fatal errors. + * gst/gstqueue.c: (gst_queue_chain): + Return proper GstFlowReturn values, + +2005-07-14 09:35:12 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gst.sgml: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbasetransform.sgml: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstbuffer.sgml: + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gstclock.sgml: + * docs/gst/tmpl/gstcompat.sgml: + * docs/gst/tmpl/gstconfig.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstelementdetails.sgml: + * docs/gst/tmpl/gstelementfactory.sgml: + * docs/gst/tmpl/gstenumtypes.sgml: + * docs/gst/tmpl/gsterror.sgml: + * docs/gst/tmpl/gstevent.sgml: + * docs/gst/tmpl/gstfakesink.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstfilesink.sgml: + * docs/gst/tmpl/gstfilesrc.sgml: + * docs/gst/tmpl/gstfilter.sgml: + * docs/gst/tmpl/gstformat.sgml: + * docs/gst/tmpl/gstghostpad.sgml: + * docs/gst/tmpl/gstimplementsinterface.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/gst/tmpl/gstindexfactory.sgml: + * docs/gst/tmpl/gstinfo.sgml: + * docs/gst/tmpl/gstiterator.sgml: + * docs/gst/tmpl/gstmacros.sgml: + * docs/gst/tmpl/gstmemchunk.sgml: + * docs/gst/tmpl/gstminiobject.sgml: + * docs/gst/tmpl/gstobject.sgml: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstpadtemplate.sgml: + * docs/gst/tmpl/gstparse.sgml: + * docs/gst/tmpl/gstpipeline.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * docs/gst/tmpl/gstpluginfeature.sgml: + * docs/gst/tmpl/gstquery.sgml: + * docs/gst/tmpl/gstqueue.sgml: + * docs/gst/tmpl/gstregistry.sgml: + * docs/gst/tmpl/gstregistrypool.sgml: + * docs/gst/tmpl/gstscheduler.sgml: + * docs/gst/tmpl/gstschedulerfactory.sgml: + * docs/gst/tmpl/gststructure.sgml: + * docs/gst/tmpl/gstsystemclock.sgml: + * docs/gst/tmpl/gsttaglist.sgml: + * docs/gst/tmpl/gsttagsetter.sgml: + * docs/gst/tmpl/gsttrace.sgml: + * docs/gst/tmpl/gsttrashstack.sgml: + * docs/gst/tmpl/gsttypefind.sgml: + * docs/gst/tmpl/gsttypefindfactory.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * docs/gst/tmpl/gsturihandler.sgml: + * docs/gst/tmpl/gsturitype.sgml: + * docs/gst/tmpl/gstutils.sgml: + * docs/gst/tmpl/gstvalue.sgml: + * docs/gst/tmpl/gstversion.sgml: + * docs/gst/tmpl/gstxml.sgml: + * docs/libs/tmpl/gstcontrol.sgml: + * docs/libs/tmpl/gstdataprotocol.sgml: + * docs/libs/tmpl/gstdparam.sgml: + * docs/libs/tmpl/gstdplinint.sgml: + * docs/libs/tmpl/gstdpman.sgml: + * docs/libs/tmpl/gstdpsmooth.sgml: + * docs/libs/tmpl/gstgetbits.sgml: + * docs/libs/tmpl/gstunitconvert.sgml: + * gst/base/gstpushsrc.c: + * gst/base/gstpushsrc.h: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesink.h: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesink.c: + * gst/elements/gstfilesink.h: + * gst/elements/gstfilesrc.c: + * gst/elements/gstfilesrc.h: + * libs/gst/base/gstpushsrc.c: + * libs/gst/base/gstpushsrc.h: + * plugins/elements/gstelements.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesink.h: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstfilesrc.h: + more autistic cleanliness in functions/names/defines + Original commit message from CVS: + more autistic cleanliness in functions/names/defines + +2005-07-13 18:29:41 +0000 Thomas Vander Stichele + + * gst/gstqueue.c: + * plugins/elements/gstqueue.c: + fix debug ifdef + Original commit message from CVS: + fix debug ifdef + +2005-07-13 16:26:07 +0000 Andy Wingo + + gst/base/gstbasesrc.c (gst_base_src_start): Post an error if the source couldn't negotiate. + Original commit message from CVS: + 2005-07-13 Andy Wingo + * gst/base/gstbasesrc.c (gst_base_src_start): Post an error if the + source couldn't negotiate. + +2005-07-13 13:14:57 +0000 Thomas Vander Stichele + + * check/gst.supp: + * tests/check/gst.supp: + add a suppression from Edgard + Original commit message from CVS: + add a suppression from Edgard + +2005-07-13 13:10:18 +0000 Thomas Vander Stichele + + move two testsuite apps over to the check dir + Original commit message from CVS: + * testsuite/caps/Makefile.am: + * testsuite/caps/value_compare.c: + * testsuite/caps/value_intersect.c: + * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + move two testsuite apps over to the check dir + +2005-07-12 17:17:34 +0000 Wim Taymans + + gst/base/gstbasetransform.c: Added more debug info in the negotiate process. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_setcaps): + Added more debug info in the negotiate process. + * gst/gstmessage.h: + Prepare for segment playback. + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_set_caps): + Better debugging. + * gst/gstutils.c: + Some more docs. + * tools/gst-launch.c: (main): + NULL pipeline on errors. + +2005-07-12 17:04:41 +0000 Andy Wingo + + gst/gstbuffer.c (_gst_buffer_copy): Copy the buffer whether or not it comes from a malloc region. Make sure our copy ... + Original commit message from CVS: + 2005-07-12 Andy Wingo + * gst/gstbuffer.c (_gst_buffer_copy): Copy the buffer whether or + not it comes from a malloc region. Make sure our copy gets freed. + +2005-07-12 16:28:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/gstelement.c: + * check/gst/gstmessage.c: + * check/gst/gststructure.c: + * gst/gstelement.c: + * gst/gstmessage.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gststructure.c: + fix refcounting of warning and error messages + Original commit message from CVS: + fix refcounting of warning and error messages + +2005-07-12 13:26:22 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + re-enable leak checking :) + Original commit message from CVS: + re-enable leak checking :) + +2005-07-12 12:20:01 +0000 Thomas Vander Stichele + + check/Makefile.am: add per-test valgrind targets + Original commit message from CVS: + * check/Makefile.am: + add per-test valgrind targets + * check/gst-libs/gdp.c: (GST_START_TEST), + (gst_data_protocol_suite), (main): + clean up + +2005-07-12 09:41:00 +0000 Thomas Vander Stichele + + check/Makefile.am: instate more valgrindable tests + Original commit message from CVS: + 2005-07-12 Thomas Vander Stichele + * check/Makefile.am: + instate more valgrindable tests + * check/elements/gstfakesrc.c: (chain_func), (event_func), + (GST_START_TEST), (fakesrc_suite): + * check/gst/gstpad.c: (GST_START_TEST): + * check/gst/gststructure.c: (GST_START_TEST): + fix test leaks + * docs/gst/tmpl/gstminiobject.sgml: + * gst/gstpad.c: (gst_pad_finalize): + fix the static mutex leak + +2005-07-11 18:41:49 +0000 Thomas Vander Stichele + + check/Makefile.am: add two more tests for valgrinding + Original commit message from CVS: + * check/Makefile.am: + add two more tests for valgrinding + * check/gst/gstvalue.c: (GST_START_TEST): + test refcount of deserialized buffer, found a leak + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstminiobject.sgml: + add miniobject to docs + * gst/gstminiobject.c: + add some docs + * gst/gstvalue.c: (gst_value_deserialize_buffer), + (gst_string_unwrap): + fix a hard-to-find invalid write for one of the tests + fix a leak for deserialized buffers + +2005-07-11 15:41:07 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + don't valgrind as part of make check for now + Original commit message from CVS: + don't valgrind as part of make check for now + +2005-07-11 15:22:24 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + specify tool + Original commit message from CVS: + specify tool + +2005-07-11 15:18:32 +0000 Ronald S. Bultje + + docs/pwg/: Rewrite scheduling-chapter for scheduling model in 0.9. Add lots of example code and explanation for pad a... + Original commit message from CVS: + * docs/pwg/advanced-events.xml: + * docs/pwg/advanced-request.xml: + * docs/pwg/advanced-scheduling.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/building-boiler.xml: + * docs/pwg/intro-preface.xml: + * docs/pwg/other-ntoone.xml: + Rewrite scheduling-chapter for scheduling model in 0.9. Add lots + of example code and explanation for pad activation, loop() and + getrange() functions and a bit more. Remove old comments pointing + to loop-functions. + * examples/pwg/Makefile.am: + Add loop/getrange examples. + +2005-07-11 15:10:40 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/gst.supp: + * check/gst/gst.c: + * check/gst/gstbuffer.c: + * check/gst/gstghostpad.c: + * check/gst/gstminiobject.c: + * configure.ac: + * gst/gst.c: + * gst/gst.h: + * gst/gstsystemclock.c: + * tests/check/Makefile.am: + * tests/check/gst.supp: + * tests/check/gst/gst.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstminiobject.c: + * tools/gst-launch.c: + valgrind unit tests as check-local; add gst_deinit + Original commit message from CVS: + valgrind unit tests as check-local; add gst_deinit + +2005-07-11 15:06:27 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfakesrc.c: + add num-buffers property to basesrc + Original commit message from CVS: + add num-buffers property to basesrc + +2005-07-10 12:03:13 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * gst/base/gstbasesink.c: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesink.c: + * gst/elements/gstfilesink.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfilesink.c: + more macro splitting + Original commit message from CVS: + more macro splitting + +2005-07-10 00:07:51 +0000 Thomas Vander Stichele + + gst/gstelement.c: add debug + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_bus): + add debug + * tools/gst-launch.c: (check_intr), (event_loop): + fix bus leaks + +2005-07-09 23:52:07 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + fix caps leak in both cases + Original commit message from CVS: + fix caps leak in both cases + +2005-07-09 23:48:45 +0000 Thomas Vander Stichele + + * gst/gstpad.c: + duh, remove unused var + Original commit message from CVS: + duh, remove unused var + +2005-07-09 23:47:23 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstpad.c: + fix a caps leak + Original commit message from CVS: + fix a caps leak + +2005-07-09 23:33:24 +0000 Thomas Vander Stichele + + gst/base/gstbasesrc.c: add finalize method and clean up properly + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_finalize): + add finalize method and clean up properly + * gst/gstpipeline.c: (gst_pipeline_dispose): + add debug + +2005-07-09 23:15:27 +0000 Thomas Vander Stichele + + * gst/gstbin.c: + don't get src for all messages; only for eos + Original commit message from CVS: + don't get src for all messages; only for eos + +2005-07-09 22:54:28 +0000 Thomas Vander Stichele + + check/gst/gstbin.c: add more things to check + Original commit message from CVS: + * check/gst/gstbin.c: (pop_messages), (GST_START_TEST), + (gst_bin_suite): + add more things to check + * gst/gstbin.c: (gst_bin_change_state), (bin_bus_handler): + * gst/gstelement.c: + more debug + +2005-07-09 16:36:18 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/elements/gstfakesrc.c: + * check/gst-libs/gdp.c: + * check/gst/gst.c: + * check/gst/gstbin.c: + * check/gst/gstbuffer.c: + * check/gst/gstbus.c: + * check/gst/gstcaps.c: + * check/gst/gstdata.c: + * check/gst/gstelement.c: + * check/gst/gstghostpad.c: + * check/gst/gstiterator.c: + * check/gst/gstmessage.c: + * check/gst/gstobject.c: + * check/gst/gstpad.c: + * check/gst/gststructure.c: + * check/gst/gstsystemclock.c: + * check/gst/gsttag.c: + * check/gst/gstvalue.c: + * check/gstcheck.c: + * check/gstcheck.h: + * check/pipelines/cleanup.c: + * check/pipelines/simple_launch_lines.c: + * check/states/sinks.c: + * tests/check/elements/gstfakesrc.c: + * tests/check/generic/sinks.c: + * tests/check/gst/gst.c: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstbuffer.c: + * tests/check/gst/gstbus.c: + * tests/check/gst/gstcaps.c: + * tests/check/gst/gstdata.c: + * tests/check/gst/gstelement.c: + * tests/check/gst/gstghostpad.c: + * tests/check/gst/gstiterator.c: + * tests/check/gst/gstmessage.c: + * tests/check/gst/gstobject.c: + * tests/check/gst/gstpad.c: + * tests/check/gst/gststructure.c: + * tests/check/gst/gstsystemclock.c: + * tests/check/gst/gsttag.c: + * tests/check/gst/gstvalue.c: + * tests/check/gstcheck.c: + * tests/check/gstcheck.h: + * tests/check/libs/gdp.c: + * tests/check/pipelines/cleanup.c: + * tests/check/pipelines/simple-launch-lines.c: + add debugging category use GST_START_TEST now, so we add a debug line + Original commit message from CVS: + add debugging category + use GST_START_TEST now, so we add a debug line + +2005-07-09 15:18:53 +0000 Thomas Vander Stichele + + check/gst/gstbin.c: add test for state change message on a bin + Original commit message from CVS: + * check/gst/gstbin.c: (START_TEST), (gst_bin_suite): + add test for state change message on a bin + * check/gst/gstelement.c: (START_TEST), (gst_element_suite): + add another test + * gst/gstbin.c: (gst_bin_init): + * gst/gstbus.c: (gst_bus_init), (gst_bus_post): + * gst/gstelement.c: (gst_element_post_message), + (gst_element_set_state): + * gst/gstelementfactory.c: (gst_element_factory_create): + * gst/gstmessage.c: (gst_message_new): + * gst/gstscheduler.c: + various debugging additions and cleanups + +2005-07-08 16:41:45 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/gst/gstelement.c: + * gst/gstelement.c: + * tests/check/Makefile.am: + * tests/check/gst/gstelement.c: + adding tests for elements + Original commit message from CVS: + adding tests for elements + +2005-07-08 16:16:29 +0000 Thomas Vander Stichele + + gst/registries/gstlibxmlregistry.c: plug more leaks. A simple gst_init() now is leakfree, yay. + Original commit message from CVS: + * gst/registries/gstlibxmlregistry.c: (load_feature): + plug more leaks. A simple gst_init() now is leakfree, yay. + +2005-07-08 16:08:16 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/registries/gstlibxmlregistry.c: + plug another memleak in registry loading - I have NO idea why this was returning a GstPlugin + Original commit message from CVS: + plug another memleak in registry loading - I have NO idea why this was returning a GstPlugin + +2005-07-08 14:50:44 +0000 Thomas Vander Stichele + + * gst/registries/gstlibxmlregistry.c: + I need to learn to stop doing this + Original commit message from CVS: + I need to learn to stop doing this + +2005-07-08 14:39:01 +0000 Thomas Vander Stichele + + * configure.ac: + add right variable + Original commit message from CVS: + add right variable + +2005-07-08 14:35:57 +0000 Thomas Vander Stichele + + configure.ac: use GST_SET_ERROR_CFLAGS + Original commit message from CVS: + * configure.ac: + use GST_SET_ERROR_CFLAGS + * docs/faq/cvs.xml: + change to ERROR_CFLAGS + +2005-07-08 14:01:31 +0000 Thomas Vander Stichele + + configure.ac: make GST_ERROR_CFLAGS overridable and re-enable Werror + Original commit message from CVS: + * configure.ac: + make GST_ERROR_CFLAGS overridable and re-enable Werror + * docs/faq/cvs.xml: + add a note about error CFLAGS + * docs/gst/tmpl/gstfakesrc.sgml: + * gst/elements/gstfakesrc.c: + comment out some unused code + * gst/gst.c: (split_and_iterate): + * gst/registries/gstlibxmlregistry.c: (load_pad_template), + (load_feature): + plug some memleaks + +2005-07-07 15:07:21 +0000 Thomas Vander Stichele + + * docs/libs/Makefile.am: + make libs use same gtk-doc.mak + Original commit message from CVS: + make libs use same gtk-doc.mak + +2005-07-07 14:16:40 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * docs/gst/Makefile.am: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + factor out gtk-doc + Original commit message from CVS: + factor out gtk-doc + +2005-07-07 14:01:47 +0000 Wim Taymans + + gst/schedulers/threadscheduler.c: Unlock the STREAM_LOCK completely. + Original commit message from CVS: + * gst/schedulers/threadscheduler.c: (gst_thread_scheduler_func), + (gst_thread_scheduler_dispose): + Unlock the STREAM_LOCK completely. + +2005-07-07 13:14:40 +0000 Thomas Vander Stichele + + * examples/pwg/.gitignore: + * tests/old/examples/pwg/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-07-07 13:12:43 +0000 Thomas Vander Stichele + + * tests/instantiate/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-07-07 11:59:37 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/elements/.gitignore: + * check/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/gstfakesrc.c: + adding an element test + Original commit message from CVS: + adding an element test + +2005-07-07 11:09:32 +0000 Andy Wingo + + gst/gstbus.c (gst_bus_have_pending): Remove intensely irritating debug message. + Original commit message from CVS: + 2005-07-07 Andy Wingo + * gst/gstbus.c (gst_bus_have_pending): Remove intensely irritating + debug message. + +2005-07-07 10:03:06 +0000 Thomas Vander Stichele + + * docs/gst/Makefile.am: + another doc fix + Original commit message from CVS: + another doc fix + +2005-07-07 09:10:17 +0000 Thomas Vander Stichele + + * docs/manual/BUILD: + * docs/manual/Makefile.am: + more macosx madness fixing + Original commit message from CVS: + more macosx madness fixing + +2005-07-07 08:43:17 +0000 Wim Taymans + + gst/gstquery.*: Remove old types + Original commit message from CVS: + * gst/gstquery.c: + * gst/gstquery.h: + Remove old types + +2005-07-07 08:16:54 +0000 Wim Taymans + + gst/base/gstbasesrc.c: Allow subclasses to implement their own negotiation. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_base_src_get_range), + (gst_base_src_default_negotiate), (gst_base_src_negotiate): + Allow subclasses to implement their own negotiation. + +2005-07-06 17:17:59 +0000 Jan Schmidt + + docs/design/: Update design notes to reflect the movement of responsibility for bus handling from GstPipeline to + Original commit message from CVS: + * docs/design/part-gstbin.txt: + * docs/design/part-gstpipeline.txt: + Update design notes to reflect the movement of + responsibility for bus handling from GstPipeline to + GstBin + +2005-07-06 16:45:45 +0000 Jan Schmidt + + configure.ac: Remove unnecessary queue2/3/4 examples. + Original commit message from CVS: + * configure.ac: + Remove unnecessary queue2/3/4 examples. + +2005-07-06 16:22:47 +0000 Jan Schmidt + + examples/: Update a couple of the examples to work again. + Original commit message from CVS: + * examples/Makefile.am: + * examples/helloworld/helloworld.c: (event_loop), (main): + * examples/queue/queue.c: (event_loop), (main): + * examples/queue2/queue2.c: (main): + Update a couple of the examples to work again. + * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty), + (gst_base_sink_preroll_queue_flush), (gst_base_sink_handle_event): + Spelling corrections and extra debug. + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_init), (is_eos), + (gst_bin_add_func), (bin_element_is_sink), (gst_bin_get_state), + (gst_bin_change_state), (gst_bin_dispose), (bin_bus_handler): + * gst/gstbin.h: + * gst/gstpipeline.c: (gst_pipeline_init), (gst_pipeline_dispose), + (gst_pipeline_change_state): + * gst/gstpipeline.h: + Move the bus handler for children to the GstBin, and create a + separate bus for receiving messages from children to the one the + bus sends 'upwards' on. + +2005-07-06 13:25:26 +0000 Wim Taymans + + gst/base/: Make basesrc negotiate. + Original commit message from CVS: + * gst/base/README: + * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty), + (gst_base_sink_handle_object), (gst_base_sink_loop), + (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: (gst_base_src_class_init), + (gst_base_src_init), (gst_base_src_setcaps), + (gst_base_src_getcaps), (gst_base_src_loop), + (gst_base_src_default_negotiate), (gst_base_src_negotiate), + (gst_base_src_start), (gst_base_src_change_state): + * gst/base/gstbasesrc.h: + Make basesrc negotiate. + Handle the case where preroll fails in basesink. + Update README. + +2005-07-06 13:20:47 +0000 Wim Taymans + + gst/gstpad.c: Implement the fixate function. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_fixate_caps), (gst_pad_accept_caps): + Implement the fixate function. + Clean up acceptcaps. + +2005-07-06 12:24:50 +0000 Ronald S. Bultje + + docs/pwg/: Remove never-written filter-factory chapter; I'll add the various base classes to part 4 ("other element t... + Original commit message from CVS: + * docs/pwg/building-filterfactory.xml: + * docs/pwg/pwg.xml: + Remove never-written filter-factory chapter; I'll add the various + base classes to part 4 ("other element types") later on. + +2005-07-06 12:18:00 +0000 Ronald S. Bultje + + Add a chapter on caps negotiation, simplify the original code samples a bit w.r.t. caps negotiation, add link to the ... + Original commit message from CVS: + * docs/pwg/advanced-negotiation.xml: + * docs/pwg/building-boiler.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/pwg.xml: + * examples/pwg/Makefile.am: + Add a chapter on caps negotiation, simplify the original code + samples a bit w.r.t. caps negotiation, add link to the advanced + section. Add a bunch of examples showing different use cases of + different types of caps negotiation. Upstream renegotiation isn't + fully documented yet since nobody knows how that works. + +2005-07-06 11:34:06 +0000 Thomas Vander Stichele + + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol.pc.in: + pc file cleanups + Original commit message from CVS: + pc file cleanups + +2005-07-06 11:31:57 +0000 Thomas Vander Stichele + + if pad has no parent, return NULL as list of internal links + Original commit message from CVS: + * check/gst/gstpad.c: + * check/gstcheck.c: + * gst/gstpad.c: (gst_pad_get_internal_links_default): + if pad has no parent, return NULL as list of internal links + +2005-07-05 16:38:13 +0000 Andy Wingo + + gst/: s/BASESRC/BASE_SRC/g. + Original commit message from CVS: + 2005-07-05 Andy Wingo + * gst/elements/gstfilesrc.c: + * gst/elements/gstfakesrc.c: + * gst/base/gstpushsrc.c: + * gst/base/gstbasesrc.h: + * gst/base/gstbasesrc.c: s/BASESRC/BASE_SRC/g. + +2005-07-05 15:28:18 +0000 Christian Schaller + + * configure.ac: + * gstreamer.spec.in: + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + update spec file + Original commit message from CVS: + update spec file + +2005-07-05 12:17:24 +0000 Stefan Kost + + * ChangeLog: + * Makefile.am: + better report genration target (lcov needs a patch) + Original commit message from CVS: + better report genration target (lcov needs a patch) + +2005-07-05 10:58:21 +0000 Andy Wingo + + gst/elements, testsuite: Null if we got it... + Original commit message from CVS: + 2005-07-05 Andy Wingo + * gst/elements, testsuite: Null if we got it... + +2005-07-05 10:20:14 +0000 Wim Taymans + + Ported dataprotol to 0.9. + Original commit message from CVS: + * configure.ac: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_validate_packet): + * libs/gst/dataprotocol/dataprotocol.h: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in: + * pkgconfig/gstreamer-dataprotocol.pc.in: + Ported dataprotol to 0.9. + Added pkgconfig files. + +2005-07-05 09:35:22 +0000 Andy Wingo + + gst/base/gstbasetransform.c (gst_base_transform_setcaps): Default to returning TRUE for the case when tranform_caps r... + Original commit message from CVS: + 2005-07-05 Andy Wingo + * gst/base/gstbasetransform.c (gst_base_transform_setcaps): + Default to returning TRUE for the case when tranform_caps returns + a fixed caps, like for identity or volume. + +2005-07-05 08:47:40 +0000 Andy Wingo + + check/: Application message API change. + Original commit message from CVS: + 2005-07-05 Andy Wingo + * check/gst/gstbus.c (pound_bus_with_messages): + * check/gst/gstmessage.c (START_TEST): + * check/pipelines/simple_launch_lines.c (got_handoff): Application + message API change. + * gst/base/gstbasetransform.c (gst_base_transform_setcaps): More + logic weaks here: always run transform_caps, trying passthrough + operation only if the original caps intersects with the transform. + * gst/gstpad.c (gst_pad_link_check_compatible_unlocked): Debug + source and sink caps. + * gst/base/gstbasetransform.c (gst_base_transform_getcaps): + Intersect the peer caps with the pad template before going into + transform_caps. + (gst_base_transform_transform_caps): More debugging. + * gst/gstmessage.h (gst_message_new_application): Take a GstObject + src argument. + +2005-07-04 15:08:30 +0000 Edward Hervey + + gst/gstutils.*: now returns the signal id for better wrapping in bindings. + Original commit message from CVS: + * gst/gstutils.c: + * gst/gstutils.h: + (gst_pad_add_*_probe): now returns the signal id for better wrapping + in bindings. + +2005-07-04 09:22:51 +0000 Andy Wingo + + check/gst/gstpad.c: Only set explicit caps on pads. + Original commit message from CVS: + 2005-07-04 Andy Wingo + * check/gst/gstpad.c: Only set explicit caps on pads. + +2005-07-01 16:46:59 +0000 Andy Wingo + + tests/network-clock.scm: Commentary update. + Original commit message from CVS: + 2005-07-01 Andy Wingo + * tests/network-clock.scm: Commentary update. + * gst/elements/gstidentity.c (PROP_DUPLICATE): Gone daddy gone. + Didn't really make sense, not implementable with basetransform, + etc. + (gst_identity_transform): Unref inbuf via make_writable. Feeble + attempt at implementing the sync property, needs an unlock method. + * gst/base/gstbasetransform.c (gst_base_transform_transform_caps): + New func, by default returns the same caps (the identity + transformation). + (gst_base_transform_getcaps): Uses transform_caps to return + something sensible. + (gst_base_transform_setcaps): Complicated logic to get caps on + both pads, even if they are different, and to call set_caps once + for every time both pads get their caps set. + (gst_base_transform_handle_buffer): Give the ref to the transform + function. Allows in-place modification of the buffer. + * gst/base/gstbasetransform.h (transform_caps): New class method. + Given caps on one side, what can I do on the other. + (set_caps): Take two caps, one for each side of the element. + * gst/gstpad.h: + * gst/gstpad.c (gst_pad_fixate_caps): Change prototype to modify + caps in place. This is safe because we can check the mutability of + the caps, and a good idea because fixate functions are just called + as a matter of last resort. (Not actually implemented.) + (gst_pad_set_caps): If the caps we're setting is actually the same + as the existing pad caps, just update the pointer without calling + setcaps. Assert that caps is either NULL or fixed, as per the + docs. + * gst/gstghostpad.c: Update for fixate changes. + +2005-07-01 14:36:12 +0000 Jan Schmidt + + gst/gstpad.c: Put the mini_object into GValue as a mini_object, not a gpointer. + Original commit message from CVS: + 2005-07-02 Jan Schmidt + * gst/gstpad.c: (gst_pad_emit_have_data_signal): + Put the mini_object into GValue as a mini_object, + not a gpointer. + +2005-07-01 14:20:19 +0000 Ronald S. Bultje + + examples/pwg/Makefile.am: Fix buildbot again. + Original commit message from CVS: + * examples/pwg/Makefile.am: + Fix buildbot again. + +2005-07-01 13:01:47 +0000 Ronald S. Bultje + + docs/pwg/building-testapp.xml: Add extra check. + Original commit message from CVS: + * docs/pwg/building-testapp.xml: + Add extra check. + * examples/pwg/Makefile.am: + Fix buildbot. + +2005-07-01 12:43:03 +0000 Ronald S. Bultje + + Enable building the PWG examples. + Original commit message from CVS: + * configure.ac: + * examples/Makefile.am: + * examples/pwg/Makefile.am: + * examples/pwg/extract.pl: + Enable building the PWG examples. + * docs/pwg/advanced-interfaces.xml: + Add URI interface stub. + * docs/pwg/advanced-types.xml: + * docs/pwg/other-autoplugger.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/pwg.xml: + Add porting guide (mostly stubs), remove autoplugging (see ADM). + * docs/pwg/building-boiler.xml: + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/building-props.xml: + * docs/pwg/building-state.xml: + * docs/pwg/building-testapp.xml: + Update the building-*.xml parts for 0.9 changes. All examples + code blocks compile in examples/pwg/*. + +2005-06-30 12:32:17 +0000 Ronald S. Bultje + + docs/manual/: Fix playbin/decodebin examples, update docs a bit, mention bus instead of signals in various places, me... + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/appendix-checklist.xml: + * docs/manual/appendix-integration.xml: + * docs/manual/highlevel-components.xml: + Fix playbin/decodebin examples, update docs a bit, mention bus + instead of signals in various places, mention kmplayer and + kaffeine since they have a working GStreamer backend in the KDE + section. + +2005-06-30 12:26:26 +0000 Thomas Vander Stichele + + * gst/gstqueue.c: + * plugins/elements/gstqueue.c: + debug disable fixes + Original commit message from CVS: + debug disable fixes + +2005-06-30 12:18:19 +0000 Wim Taymans + + Added CHANGES-0.9 doc, updated status of other docs. + Original commit message from CVS: + * CHANGES-0.9: + * docs/design/draft-ghostpads.txt: + * docs/design/draft-push-pull.txt: + * docs/design/draft-query.txt: + * docs/design/part-TODO.txt: + * docs/design/part-query.txt: + Added CHANGES-0.9 doc, updated status of other docs. + * gst/gstquery.h: + Remove "hmm" macro + +2005-06-30 12:14:47 +0000 Wim Taymans + + gst/base/gstbasesink.*: Some tweaks, only EOS and a buffer complete a preroll. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty), + (gst_base_sink_preroll_queue_flush), (gst_base_sink_handle_object), + (gst_base_sink_change_state): + * gst/base/gstbasesink.h: + Some tweaks, only EOS and a buffer complete a preroll. + +2005-06-30 11:39:34 +0000 Andy Wingo + + gst/gstghostpad.c (gst_ghost_pad_do_activate_push): Proxy activate_push down to the internal pad as well. + Original commit message from CVS: + 2005-06-30 Andy Wingo + * gst/gstghostpad.c (gst_ghost_pad_do_activate_push): Proxy + activate_push down to the internal pad as well. + +2005-06-30 10:59:34 +0000 Ronald S. Bultje + + gst/gsttaginterface.c: Some documentation fixes (#307394 and #307397). + Original commit message from CVS: + Reviewed by: Ronald S. Bultje + * gst/gsttaginterface.c: + Some documentation fixes (#307394 and #307397). + +2005-06-30 10:23:16 +0000 Thomas Vander Stichele + + * check/gst/.gitignore: + * check/states/.gitignore: + * tests/check/gst/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-06-30 10:22:15 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + go back to the circular dependency for now + Original commit message from CVS: + go back to the circular dependency for now + +2005-06-30 10:10:00 +0000 Ronald S. Bultje + + gst/gstvalue.c: Fix memleak (#309125). + Original commit message from CVS: + Reviewed by: Ronald S. Bultje + * gst/gstvalue.c: (gst_value_intersect_list): + Fix memleak (#309125). + +2005-06-30 09:59:27 +0000 Ronald S. Bultje + + docs/manual/advanced-dataaccess.xml: Fix fakesrc example to compile; doesn't work, bug somewhere...? + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + Fix fakesrc example to compile; doesn't work, bug somewhere...? + * docs/manual/basics-pads.xml: + Add reference for filtered caps to above chapter. + +2005-06-30 09:41:15 +0000 Wim Taymans + + gst/gstbin.c: Lame attempt at making the state change function a bit more readable. + Original commit message from CVS: + * gst/gstbin.c: (clear_queue), (remove_all_from_queue), + (gst_bin_change_state): + Lame attempt at making the state change function a bit + more readable. + +2005-06-30 09:33:45 +0000 Wim Taymans + + docs/design/: Some more tweeks and additions to the docs. + Original commit message from CVS: + * docs/design/part-clocks.txt: + * docs/design/part-element-sink.txt: + * docs/design/part-events.txt: + * docs/design/part-preroll.txt: + * docs/design/part-states.txt: + Some more tweeks and additions to the docs. + +2005-06-30 09:23:54 +0000 Wim Taymans + + gst/: Removed atomic operations, use existing LOCK. + Original commit message from CVS: + * gst/gstpad.c: (_gst_do_pass_data_accumulator), + (default_have_data), (gst_pad_class_init), (gst_pad_init), + (gst_pad_emit_have_data_signal), (gst_pad_chain), (gst_pad_push), + (gst_pad_check_pull_range), (gst_pad_get_range), + (gst_pad_pull_range), (gst_pad_push_event), (gst_pad_send_event): + * gst/gstpad.h: + * gst/gstutils.c: (gst_atomic_int_set), (gst_pad_add_data_probe), + (gst_pad_add_event_probe), (gst_pad_add_buffer_probe), + (gst_pad_remove_data_probe), (gst_pad_remove_event_probe), + (gst_pad_remove_buffer_probe): + Removed atomic operations, use existing LOCK. + Move exception handling out of main code path. + +2005-06-30 07:45:55 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + drop circular reference + Original commit message from CVS: + drop circular reference + +2005-06-29 19:20:07 +0000 Ronald S. Bultje + + gst/gstpad.c: Fix accumulator, add default value by using _emitv() instead of _emit() for signal emission. + Original commit message from CVS: + * gst/gstpad.c: (_gst_do_pass_data_accumulator), + (silly_return_true_function), (gst_pad_class_init), + (gst_pad_emit_have_data_signal), (gst_pad_chain), (gst_pad_push), + (gst_pad_get_range), (gst_pad_pull_range), (gst_pad_push_event), + (gst_pad_send_event): + Fix accumulator, add default value by using _emitv() instead + of _emit() for signal emission. + +2005-06-29 16:57:59 +0000 Ronald S. Bultje + + Add probe example. + Original commit message from CVS: + * docs/manual/advanced-dataaccess.xml: + * examples/manual/Makefile.am: + Add probe example. + * gst/gstpad.c: (_gst_do_pass_data_accumulator): + Make work (??). + +2005-06-29 16:45:58 +0000 Thomas Vander Stichele + + * gst/gstminiobject.c: + fix for ppc, hopefully + Original commit message from CVS: + fix for ppc, hopefully + +2005-06-29 16:11:12 +0000 Tim-Philipp Müller + + gst/elements/gstfilesink.c: Simplify code so that we don't have to handle short writes and return GST_FLOW_ERROR if a... + Original commit message from CVS: + * gst/elements/gstfilesink.c: (gst_filesink_render): + Simplify code so that we don't have to handle short + writes and return GST_FLOW_ERROR if an error occured. + +2005-06-29 16:05:26 +0000 Ronald S. Bultje + + docs/gst/gstreamer-docs.sgml: Remove probes more. + Original commit message from CVS: + * docs/gst/gstreamer-docs.sgml: + Remove probes more. + +2005-06-29 15:51:25 +0000 Ronald S. Bultje + + Remove old probes, add new g-signal-based probes and some utility functions. + Original commit message from CVS: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstpad.sgml: + * docs/gst/tmpl/gstprobe.sgml: + * gst/Makefile.am: + * gst/gstpad.c: (_gst_do_pass_data_accumulator), + (gst_pad_class_init), (gst_pad_init), (gst_pad_chain), + (gst_pad_push), (gst_pad_get_range), (gst_pad_pull_range), + (gst_pad_push_event), (gst_pad_send_event): + * gst/gstpad.h: + * gst/gstutils.c: (gst_pad_add_data_probe), + (gst_pad_add_event_probe), (gst_pad_add_buffer_probe), + (gst_pad_remove_data_probe), (gst_pad_remove_event_probe), + (gst_pad_remove_buffer_probe): + * gst/gstutils.h: + Remove old probes, add new g-signal-based probes and some utility + functions. + +2005-06-29 15:17:25 +0000 Edward Hervey + + gst/: Moved gst_element_factory_can_[sink|src]_caps() to gstutils and added the definition to the header file. + Original commit message from CVS: + * gst/gstelementfactory.c: + * gst/gstutils.h: + * gst/gstutils.c: + Moved gst_element_factory_can_[sink|src]_caps() to gstutils and added + the definition to the header file. + +2005-06-29 14:56:08 +0000 Andy Wingo + + docs/gst/Makefile.am (scan-build.stamp): Totally only check plugins from the source directory. + Original commit message from CVS: + 2005-06-29 Andy Wingo + * docs/gst/Makefile.am (scan-build.stamp): Totally only check + plugins from the source directory. + +2005-06-29 14:52:44 +0000 Wim Taymans + + docs/gst/tmpl/: Some fixings for blantently wrong text. + Original commit message from CVS: + * docs/gst/tmpl/gstbuffer.sgml: + * docs/gst/tmpl/gstclock.sgml: + Some fixings for blantently wrong text. + +2005-06-29 12:40:39 +0000 Thomas Vander Stichele + + * gst/gst.c: + logic was reversed, duh + Original commit message from CVS: + logic was reversed, duh + +2005-06-29 12:25:05 +0000 Thomas Vander Stichele + + add A GST_PLUGIN_PATH_ONLY env var; if it is set, it will only scan the GST_PLUGIN_PATH locations, and not add system... + Original commit message from CVS: + * check/Makefile.am: + * gst/gst.c: (add_path_func), (init_pre): + * gst/gstregistry.c: (gst_registry_add_path): + add A GST_PLUGIN_PATH_ONLY env var; if it is set, it will + only scan the GST_PLUGIN_PATH locations, and not add + system locations + +2005-06-29 12:23:35 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstelement.sgml: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstutils.c: + doc fixes + Original commit message from CVS: + doc fixes + +2005-06-29 12:02:13 +0000 Ronald S. Bultje + + docs/manual/advanced-autoplugging.xml: Fix autoplugging example. + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + Fix autoplugging example. + +2005-06-29 11:46:16 +0000 Ronald S. Bultje + + docs/manual/: Try to get autoplugging working, fix type detection. Fix text in hello-world image. + Original commit message from CVS: + * docs/manual/advanced-autoplugging.xml: + * docs/manual/mime-world.fig: + Try to get autoplugging working, fix type detection. Fix text + in hello-world image. + +2005-06-29 11:10:44 +0000 Wim Taymans + + gst/base/gstbasesink.c: Small debug line. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object), + (gst_base_sink_change_state): + Small debug line. + * gst/gstclock.h: + map SIGNAL and BROADCAST to the right function. + * gst/gstobject.h: + Remove redundant braces. + * gst/gstpad.c: (gst_pad_set_caps): + Don't call setcaps function when reseting caps to NULL. + * gst/gstsystemclock.c: (gst_system_clock_dispose), + (gst_system_clock_async_thread), (gst_system_clock_id_wait_async), + (gst_system_clock_id_unschedule): + Use BROADCAST as this is what we do. + +2005-06-29 10:24:08 +0000 Wim Taymans + + gst/base/gstbasesink.c: We are actually prerolling before commiting the state change. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_base_sink_handle_object): + We are actually prerolling before commiting the state + change. + +2005-06-29 09:25:51 +0000 Ronald S. Bultje + + docs/manual/: Update (until threads/scheduling) Application Development Manual; remove GstThread, add GstBus, add sim... + Original commit message from CVS: + * docs/manual/advanced-clocks.xml: + * docs/manual/advanced-interfaces.xml: + * docs/manual/advanced-metadata.xml: + * docs/manual/advanced-position.xml: + * docs/manual/advanced-schedulers.xml: + * docs/manual/advanced-threads.xml: + * docs/manual/appendix-porting.xml: + * docs/manual/basics-bins.xml: + * docs/manual/basics-bus.xml: + * docs/manual/basics-elements.xml: + * docs/manual/basics-helloworld.xml: + * docs/manual/basics-pads.xml: + * docs/manual/highlevel-components.xml: + * docs/manual/manual.xml: + * docs/manual/thread.fig: + Update (until threads/scheduling) Application Development Manual; + remove GstThread, add GstBus, add simple porting checklist, add + documentation for tag writing, clocks, make all examples until this + part compile and run. + * examples/manual/Makefile.am: + Update from changes to Application Development Manual; add bus + example, remove thread example. + +2005-06-28 19:45:26 +0000 Wim Taymans + + gst/gstbus.c: Add debugging messages. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_post), (gst_bus_have_pending), + (gst_bus_set_flushing), (gst_bus_pop), (gst_bus_peek), + (gst_bus_source_dispatch): + Add debugging messages. + Make internal methods static. + Handle the case where the bus is flushed in the handler. + * gst/gstelement.c: (gst_element_get_bus): + Fix refcount in _get_bus(); + * gst/gstpipeline.c: (gst_pipeline_change_state), + (gst_pipeline_get_clock_func): + Clock refcounting fixes. + Handle the case where preroll timed out more gracefully. + * gst/gstsystemclock.c: (gst_system_clock_dispose): + Clean up the internal thread in dispose. This is needed + for subclasses that actually get disposed. + * gst/schedulers/threadscheduler.c: + (gst_thread_scheduler_class_init), (gst_thread_scheduler_func), + (gst_thread_scheduler_dispose): + Free thread pool in dispose. + +2005-06-28 16:57:27 +0000 Andy Wingo + + tests/network-clock-utils.scm (debug, print-event): New utils. + Original commit message from CVS: + 2005-06-28 Andy Wingo + * tests/network-clock-utils.scm (debug, print-event): New utils. + * tests/network-clock.scm (*debug*, *with-graph*): New parameters. + (*packet-loss*): Unified loss probability. + (network-time): Report out-of-band events. + * tests/plot-data: Add support for out-of-band events. Hack it + into this script instead of passing it down the pipe; should fix + this later. + +2005-06-28 15:36:37 +0000 Wim Taymans + + docs/gst/: Docs fixes. + Original commit message from CVS: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstpad.sgml: + Docs fixes. + +2005-06-28 13:40:12 +0000 Wim Taymans + + gst/gstghostpad.c: Correctly proxy the check_pull_range function. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_do_bufferalloc), + (gst_proxy_pad_do_checkgetrange), (gst_proxy_pad_do_acceptcaps), + (gst_proxy_pad_do_fixatecaps): + Correctly proxy the check_pull_range function. + +2005-06-28 12:45:21 +0000 Thomas Vander Stichele + + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + fix fake elements too + Original commit message from CVS: + fix fake elements too + +2005-06-28 12:01:49 +0000 Thomas Vander Stichele + + * gst/base/gstbasesink.c: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + did s/bases(rc/ink)_/base_s(rc/ink)_/; wim wants to remove base completely, but that's for later + Original commit message from CVS: + did s/bases(rc/ink)_/base_s(rc/ink)_/; wim wants to remove base completely, but that's for later + +2005-06-28 11:48:57 +0000 Andy Wingo + + tests/network-clock.scm: Removed need for slib. + Original commit message from CVS: + 2005-06-28 Andy Wingo + * tests/network-clock.scm: Removed need for slib. + +2005-06-28 11:36:43 +0000 Wim Taymans + + gst/: The deprecated pad loop function is removed now. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_set_pad_functions), + (gst_basesink_preroll_queue_flush): + * gst/base/gstbasesrc.c: (gst_basesrc_set_dataflow_funcs): + * gst/elements/gsttee.c: (gst_tee_update_pad_functions): + * gst/gstghostpad.c: (gst_proxy_pad_do_bufferalloc), + (gst_proxy_pad_do_acceptcaps), (gst_proxy_pad_do_fixatecaps), + (gst_proxy_pad_set_property): + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstqueue.c: (gst_queue_init): + The deprecated pad loop function is removed now. + +2005-06-28 11:33:22 +0000 Andy Wingo + + tests/network-clock.scm (*timeout*, *send-loss*, *recv-loss*): New parameters, simulate network packet loss. + Original commit message from CVS: + 2005-06-28 Andy Wingo + * tests/network-clock.scm (*timeout*, *send-loss*, *recv-loss*): + New parameters, simulate network packet loss. + * tests/network-clock-utils.scm: Initialize the RNG. + +2005-06-28 11:02:18 +0000 Wim Taymans + + gst/base/gstbasesink.c: Flushing the preroll queue always needs to unlock the waiters. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_flush), + (gst_basesink_event), (gst_basesink_deactivate): + Flushing the preroll queue always needs to unlock the waiters. + +2005-06-28 10:45:48 +0000 Edward Hervey + + gst/gstpipeline.c: Wheen a seek was successful on a pipeline, set the stream_time to the seek offset in order to have... + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_send_event): + Wheen a seek was successful on a pipeline, set the stream_time to the + seek offset in order to have a synchronized stream_time. + +2005-06-28 10:37:24 +0000 Wim Taymans + + gst/gstghostpad.c: Call wrapper function instead of just calling the function pointers. This takes care of any lockin... + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_do_bufferalloc), + (gst_proxy_pad_do_getrange), (gst_proxy_pad_do_checkgetrange), + (gst_proxy_pad_do_getcaps), (gst_proxy_pad_do_acceptcaps), + (gst_proxy_pad_do_fixatecaps): + Call wrapper function instead of just calling the function + pointers. This takes care of any locking and whatmore. + +2005-06-28 10:28:31 +0000 Wim Taymans + + gst/gstpad.*: CONNECTED -> LINKED. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer), (gst_pad_push), + (gst_pad_pull_range): + * gst/gstpad.h: + CONNECTED -> LINKED. + +2005-06-28 09:59:01 +0000 Andy Wingo + + *.c: Don't cast to GST_OBJECT when reffing or unreffing. Large source-munging commit!!! + Original commit message from CVS: + 2005-06-28 Andy Wingo + * *.c: Don't cast to GST_OBJECT when reffing or unreffing. Large + source-munging commit!!! + +2005-06-28 09:17:14 +0000 Andy Wingo + + * ChangeLog: + * docs/gst/tmpl/gstobject.sgml: + * gst/gstobject.c: + * gst/gstobject.h: + gst/gstobject.c (gst_object_unref, gst_object_ref) + Original commit message from CVS: + 2005-06-28 Andy Wingo + * gst/gstobject.c (gst_object_unref, gst_object_ref) + (gst_object_sink): Take gpointer arguments, not GstObject -- + avoids casts. Like GLib. + +2005-06-28 08:41:43 +0000 Andy Wingo + + gst/gstghostpad.c (gst_proxy_pad_do_activate): Don't proxy activate. + Original commit message from CVS: + 2005-06-28 Andy Wingo + * gst/gstghostpad.c (gst_proxy_pad_do_activate): Don't proxy + activate. + +2005-06-27 18:39:41 +0000 Andy Wingo + + * gst/gstpad.c: + shut up gcc3 + Original commit message from CVS: + shut up gcc3 + +2005-06-27 18:35:05 +0000 Andy Wingo + + gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer. + Original commit message from CVS: + 2005-06-27 Andy Wingo + * gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any + remaining buffer. + * gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper, + returns a sorted copy of the trace list. + (gst_alloc_trace_print_live): New API, only prints traces with + live objects. Sort the list. + (gst_alloc_trace_print_all): Sort the list. + (gst_alloc_trace_print): Align columns. + * gst/elements/gstttypefindelement.c: + * gst/elements/gsttee.c: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesink.c: + * gst/base/gstbasetransform.c: + * gst/gstqueue.c: Adapt for pad activation changes. + * gst/gstpipeline.c (gst_pipeline_init): Unref after parenting + sched. + (gst_pipeline_dispose): Drop ref on sched. + * gst/gstpad.c (gst_pad_init): Set the default activate func. + (gst_pad_activate_default): Push mode by default. + (pre_activate_switch, post_activate_switch): New stubs, things to + do before and after switching activation modes on pads. + (gst_pad_set_active): Take a boolean and not a mode, dispatch to + the pad's activate function to choose which mode to activate. + Shortcut on deactivation and call the right function directly. + (gst_pad_activate_pull): New API, (de)activates a pad in pull + mode. + (gst_pad_activate_push): New API, same for push mode. + (gst_pad_set_activate_function) + (gst_pad_set_activatepull_function) + (gst_pad_set_activatepush_function): Setters for new API. + * gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free): + Trace all miniobjects. + (gst_mini_object_make_writable): Unref the arg if we copy, like + gst_caps_make_writable. + * gst/gstmessage.c (_gst_message_initialize): No trace init. + * gst/gstghostpad.c (gst_proxy_pad_do_activate) + (gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush): + Adapt for new pad API. + * gst/gstevent.c (_gst_event_initialize): Don't initialize trace. + * gst/gstelement.h: + * gst/gstelement.c (gst_element_iterate_src_pads) + (gst_element_iterate_sink_pads): New API functions. + * gst/gstelement.c (iterator_fold_with_resync): New utility, + should fold into gstiterator.c in some form. + (gst_element_pads_activate): Simplified via use of fold and + delegation of decisions to gstpad->activate. + * gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL, + help in debugging. + * gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type + class once in init, like gstmessage. Didn't run into this issue + but it seems correct. Don't initialize a trace, gstminiobject does + that. + * check/pipelines/simple_launch_lines.c (test_stop_from_app): New + test, runs fakesrc ! fakesink, stopping on ::handoff via a message + to the bus. + (assert_live_count): New util function, uses alloc traces to check + cleanup. + * check/gst/gstghostpad.c (test_ghost_pads): More refcount checks. + To be modified when unlink drops the internal pad. + +2005-06-27 18:11:24 +0000 Wim Taymans + + gst/gstbin.c: Cleanup the get_state() function a little, make sure it iterates the same set of elements. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_get_state), (gst_bin_iterate_state_order), + (gst_bin_change_state): + Cleanup the get_state() function a little, make sure it + iterates the same set of elements. + Added stub iterate_state_order(). + +2005-06-27 14:40:09 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbasetransform.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstiterator.sgml: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.h: + * gst/gstelement.c: + * gst/gstiterator.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.h: + adding basetransform and iterator docs + Original commit message from CVS: + adding basetransform and iterator docs + +2005-06-27 13:25:44 +0000 Andy Wingo + + docs/design/part-activation.txt: Notes on how activation should work -- not quite implemented yet. + Original commit message from CVS: + 2005-06-27 Andy Wingo + * docs/design/part-activation.txt: Notes on how activation should + work -- not quite implemented yet. + +2005-06-27 08:54:16 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gstregistry.sgml: + remove stuff that isn't there anymore + Original commit message from CVS: + remove stuff that isn't there anymore + +2005-06-27 08:16:51 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstelement.sgml: + * docs/gst/tmpl/gsttypes.sgml: + * gst/base/gstbasesrc.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstelement.h: + * libs/gst/base/gstbasesrc.h: + more doc and whitespace fixes + Original commit message from CVS: + more doc and whitespace fixes + +2005-06-25 19:53:02 +0000 Wim Taymans + + gst/gstghostpad.c: At least get the chain function correct, needs more fixing. + Original commit message from CVS: + * gst/gstghostpad.c: (gst_proxy_pad_do_chain): + At least get the chain function correct, needs more + fixing. + +2005-06-25 19:37:59 +0000 Wim Taymans + + gst/: Right, two problems here: ghostpads don't take locks and glib _rec_mutex_lock_full() with depth==0 still locks. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_empty), + (gst_basesink_handle_object), (gst_basesink_event), + (gst_basesink_do_sync), (gst_basesink_handle_event), + (gst_basesink_change_state): + * gst/gsttask.h: + Right, two problems here: ghostpads don't take locks and + glib _rec_mutex_lock_full() with depth==0 still locks. + Catch illegal locking and g_warn them. + +2005-06-25 19:14:51 +0000 Wim Taymans + + check/states/sinks.c: Have to check for completion now... + Original commit message from CVS: + * check/states/sinks.c: (START_TEST), (gst_object_suite): + Have to check for completion now... + +2005-06-25 19:09:28 +0000 Wim Taymans + + gst/: Unlock STREAM_LOCK whatever the recursion was. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_empty), + (gst_basesink_handle_object), (gst_basesink_event), + (gst_basesink_do_sync), (gst_basesink_handle_event), + (gst_basesink_change_state): + * gst/gstpad.h: + Unlock STREAM_LOCK whatever the recursion was. + +2005-06-25 17:54:58 +0000 Wim Taymans + + gst/base/gstbasesink.c: Reworked the base sink, handle event and buffer serialisation correctly and removed possible ... + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_set_property), + (gst_basesink_preroll_queue_empty), + (gst_basesink_preroll_queue_flush), (gst_basesink_handle_object), + (gst_basesink_event), (gst_basesink_do_sync), + (gst_basesink_handle_event), (gst_basesink_handle_buffer), + (gst_basesink_chain), (gst_basesink_loop), (gst_basesink_activate), + (gst_basesink_change_state): + Reworked the base sink, handle event and buffer serialisation + correctly and removed possible deadlock. + Handle EOS correctly. + +2005-06-25 17:51:12 +0000 Wim Taymans + + Allow elements to post EOS in the state change function. + Original commit message from CVS: + * gst/gstpipeline.c: (is_eos), (pipeline_bus_handler), + (gst_pipeline_change_state): + * tools/gst-launch.c: (check_intr), (event_loop), (main): + Allow elements to post EOS in the state change function. + Fix up -launch, make it exit the poll loop when the + pipeline actually changed state. + Fix up warning parsing in -launch. + +2005-06-25 17:44:39 +0000 Wim Taymans + + gst/elements/gsttee.c: Core takes STREAM_LOCK for us now. + Original commit message from CVS: + * gst/elements/gsttee.c: (gst_tee_chain), (gst_tee_loop), + (gst_tee_sink_activate): + Core takes STREAM_LOCK for us now. + +2005-06-25 17:42:17 +0000 Wim Taymans + + gst/: Keep track of current target state while performing a state change so that subclasses can do something interest... + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_set_state): + * gst/gstelement.h: + * gst/gstmessage.c: (gst_message_parse_error), + (gst_message_parse_warning): + Keep track of current target state while performing a state + change so that subclasses can do something interesting. + Fix parsing of warning/error messages when GError is NULL. + +2005-06-24 18:16:14 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/gstreamer.types: + * docs/gst/tmpl/gstbasesink.sgml: + * docs/gst/tmpl/gstbasesrc.sgml: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstcompat.sgml: + * docs/gst/tmpl/gstfakesink.sgml: + * docs/gst/tmpl/gstfakesrc.sgml: + * docs/gst/tmpl/gstfilesink.sgml: + * docs/gst/tmpl/gstfilesrc.sgml: + * docs/gst/tmpl/gstindex.sgml: + * docs/manual/appendix-quotes.xml: + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.h: + * gst/gstmessage.h: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfakesrc.h: + start pulling in base classes and elements for docs + Original commit message from CVS: + start pulling in base classes and elements for docs + +2005-06-24 07:49:40 +0000 Stefan Kost + + * ChangeLog: + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: + fixed make distcheck with gtk-doc 1.3 + Original commit message from CVS: + fixed make distcheck with gtk-doc 1.3 + +2005-06-23 17:11:49 +0000 Wim Taymans + + gst/gstelement.c: When the state did not change, also report NO_PREROLL when it matters. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_set_state), (gst_element_change_state): + When the state did not change, also report NO_PREROLL + when it matters. + +2005-06-23 17:09:21 +0000 Wim Taymans + + gst/: No unsafe task pausing please. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_event_default): + * gst/gstqueue.c: (gst_queue_loop): + No unsafe task pausing please. + +2005-06-23 17:07:08 +0000 Wim Taymans + + gst/schedulers/threadscheduler.c: Ref the task before pushing it on the threadpool. This makes sure that we have a re... + Original commit message from CVS: + * gst/schedulers/threadscheduler.c: + (gst_thread_scheduler_task_start), + (gst_thread_scheduler_task_pause), (gst_thread_scheduler_func): + Ref the task before pushing it on the threadpool. This + makes sure that we have a ref when the threadfunction is + actually called. + +2005-06-23 15:26:09 +0000 Andy Wingo + + gst/base/gstbasesrc.c (gst_basesrc_get_range): Check if the offset is greater than the file's size. + Original commit message from CVS: + 2005-06-23 Andy Wingo + * gst/base/gstbasesrc.c (gst_basesrc_get_range): Check if the + offset is greater than the file's size. + +2005-06-23 15:04:48 +0000 Andy Wingo + + gst/gstobject.h (GST_CLASS_LOCK, GST_CLASS_TRYLOCK) (GST_CLASS_UNLOCK, GST_CLASS_GET_LOCK, GstObjectClass) + Original commit message from CVS: + 2005-06-23 Andy Wingo + * gst/gstobject.h (GST_CLASS_LOCK, GST_CLASS_TRYLOCK) + (GST_CLASS_UNLOCK, GST_CLASS_GET_LOCK, GstObjectClass) + * gst/gstobject.c (gst_object_class_init): Make the class lock + recursive. Wim won't let me drop deep_notify. Decodebin works + again, whoopdy doo. + +2005-06-23 14:18:15 +0000 Andy Wingo + + gst/gstghostpad.c (on_int_notify): Catches notify::caps on the internal pad, and hacks accordingly. Doesn't do it on ... + Original commit message from CVS: + 2005-06-23 Andy Wingo + * gst/gstghostpad.c (on_int_notify): Catches notify::caps on the + internal pad, and hacks accordingly. Doesn't do it on the target + pad because we change its caps. Probably catches all cases of + interest tho. + (gst_ghost_pad_set_property): Connect to notify::caps as + appropritate. + +2005-06-23 13:20:44 +0000 Andy Wingo + + tests/network-clock.scm (plot-simulation): Pipe data to the elite python skript. + Original commit message from CVS: + 2005-06-23 Andy Wingo + * tests/network-clock.scm (plot-simulation): Pipe data to the + elite python skript. + * tests/network-clock-utils.scm (define-parameter): New macro, + defines a parameter that can be set via the command line. + (set-parameter!, parse-parameter-arguments): Command line args + parser. + * tests/plot-data: Simple matplotlib-based plotter, takes input on + stdin. + +2005-06-23 13:20:00 +0000 Thomas Vander Stichele + + * docs/manual/appendix-quotes.xml: + add more important documentation + Original commit message from CVS: + add more important documentation + +2005-06-23 11:43:39 +0000 Jan Schmidt + + gst/elements/gsttypefindelement.c: Don't restart typefinding on a discont. + Original commit message from CVS: + 2005-06-23 Jan Schmidt + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_handle_event): + Don't restart typefinding on a discont. + * gst/gstelement.c: (gst_element_set_state): + Debug spelling fix. + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_send_event): + Allow changing mode of an active pad. + Debug output fixes. + * gst/registries/gstlibxmlregistry.c: (load_feature): + Don't cast a static pad template to a normal pad template. + +2005-06-23 11:25:29 +0000 Thomas Vander Stichele + + remove gst_strtoll completely, since it didn't actually do anything more than what g_ascii_strtoull already does. + Original commit message from CVS: + * check/gst/gstvalue.c: (START_TEST), (gst_value_suite): + * gst/gstvalue.c: (gst_value_deserialize_int_helper): + remove gst_strtoll completely, since it didn't actually do + anything more than what g_ascii_strtoull already does. + check for range errors when deserializing + do a cast for the unsigned cases; but further fixing needs + a decision on what the interpretation of "(int)" and + deserialization should be for values that fall outside the + type's boundaries (ie, refuse, or interpret as casting) + +2005-06-23 10:37:09 +0000 Wim Taymans + + * ChangeLog: + * check/Makefile.am: + * check/states/sinks.c: + * docs/design/part-live-source.txt: + * docs/design/part-states.txt: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.c: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gsttypes.h: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * plugins/elements/gstfakesrc.c: + * tests/check/Makefile.am: + * tests/check/generic/sinks.c: + * tools/gst-launch.c: + Added support for live sources and other elements that cannot do preroll. + Original commit message from CVS: + Added support for live sources and other elements that + cannot do preroll. + Updated design docs, added live-source design doc. + Implemented live source functionality in basesrc + Fix error condition in _bin_get_state() + Implement live source handling in -launch. + Added check for live sources. + Fixed case in GstBin where elements were changed state + multiple times. + +2005-06-23 09:59:33 +0000 Andy Wingo + + check/gst/gstpad.c (test_get_allowed_caps, test_refcount): Fix borken refcounting. + Original commit message from CVS: + 2005-06-23 Andy Wingo + * check/gst/gstpad.c (test_get_allowed_caps, test_refcount): Fix + borken refcounting. + +2005-06-23 09:41:41 +0000 Andy Wingo + + * gst/gstpad.c: + commit the file + Original commit message from CVS: + commit the file + +2005-06-23 09:41:09 +0000 Andy Wingo + + gst/gstpad.c (gst_pad_set_caps): Remove needless refs, gst_caps_replace takes care of this for us. + Original commit message from CVS: + 2005-06-23 Andy Wingo + * gst/gstpad.c (gst_pad_set_caps): Remove needless refs, + gst_caps_replace takes care of this for us. + +2005-06-23 09:28:27 +0000 Andy Wingo + + gst/gstghostpad.c (gst_proxy_pad_do_setcaps): Call the full gst_pad_set_caps on the target, not just its setcaps() fu... + Original commit message from CVS: + 2005-06-23 Andy Wingo + * gst/gstghostpad.c (gst_proxy_pad_do_setcaps): Call the full + gst_pad_set_caps on the target, not just its setcaps() function. + +2005-06-23 00:39:26 +0000 Andy Wingo + + tests/: A network clock simulator. + Original commit message from CVS: + 2005-06-23 Andy Wingo + * tests/network-clock.scm: + * tests/network-clock-utils.scm: A network clock simulator. + Something of an algorithmic testbed before doing something in C. + +2005-06-22 19:57:12 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + make sure capslist.h gets disted + Original commit message from CVS: + make sure capslist.h gets disted + +2005-06-22 19:48:54 +0000 Thomas Vander Stichele + + file fromstring.c was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file fromstring.c was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-06-22 19:22:34 +0000 Thomas Vander Stichele + + check/: copy over from 0.8, and add two with bitmasks specified with (int) 0xFF... + Original commit message from CVS: + * check/Makefile.am: + * check/gst/capslist.h: + copy over from 0.8, and add two with bitmasks specified with + (int) 0xFF... + * check/gst/gstcaps.c: (START_TEST), (gst_caps_suite): + add test to parse everything from capslist.h + * check/gst/gststructure.c: (START_TEST), (gst_value_suite), + (main): + add test for structure deserialization + * check/gst/gstvalue.c: (START_TEST), (gst_value_suite): + add tests for deserialization of strings to int types + * gst/gststructure.c: (gst_structure_nth_field_name): + * gst/gststructure.h: + add a way to get the name of a field referenced by index + * gst/gstvalue.c: (gst_value_deserialize_int_helper): + instead of checking if the resulting long long lies between + min and max, we check if the long long would fit into + a number of bytes for the final type. + This fixes cases where a string represents 2^32 - 1, which + when cast to int would be the (valid) -1, but is bigger than + G_MAXINT + +2005-06-22 11:02:57 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/parse/grammar.y: + add a log line for type deserialization + Original commit message from CVS: + add a log line for type deserialization + +2005-06-22 10:52:18 +0000 Thomas Vander Stichele + + return long long, not int, so gint64 deserialization actually works. Is there any flag that makes the compiler check... + Original commit message from CVS: + * check/gst/gstvalue.c: (START_TEST): + * gst/gstvalue.c: (gst_value_deserialize): + return long long, not int, so gint64 deserialization actually + works. Is there any flag that makes the compiler check this ? + Fixes #308559 + +2005-06-22 09:55:16 +0000 Wim Taymans + + gst/gstbuffer.h: Added convenience macros for setting buffers in GValue. + Original commit message from CVS: + * gst/gstbuffer.h: + Added convenience macros for setting buffers in GValue. + +2005-06-21 17:41:35 +0000 Thomas Vander Stichele + + check/gst/: add a test deserializing int64, and comment part out because it fails, yay ! + Original commit message from CVS: + * check/gst/.cvsignore: + * check/gst/gstvalue.c: (START_TEST), (gst_value_suite): + add a test deserializing int64, and comment part out because + it fails, yay ! + +2005-06-21 16:53:14 +0000 Thomas Vander Stichele + + * check/gst/gst.c: + * tests/check/gst/gst.c: + commit a file I forgot + Original commit message from CVS: + commit a file I forgot + +2005-06-21 16:48:46 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/Makefile.am: + * check/gst/gstvalue.c: + * tests/check/Makefile.am: + * tests/check/gst/gstvalue.c: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/caps/Makefile.am: + * tests/old/testsuite/caps/value_serialize.c: + * tests/old/testsuite/test_gst_init.c: + * testsuite/Makefile.am: + * testsuite/caps/Makefile.am: + * testsuite/caps/value_serialize.c: + * testsuite/test_gst_init.c: + move over a value_serialize test + Original commit message from CVS: + move over a value_serialize test + +2005-06-20 15:18:17 +0000 Wim Taymans + + gst/gstpad.c: Small doc updates. + Original commit message from CVS: + * gst/gstpad.c: + Small doc updates. + * gst/gstvalue.c: (gst_value_compare_buffer), + (gst_value_serialize_buffer), (gst_value_deserialize_buffer), + (gst_value_compare_flags), (gst_value_serialize_flags), + (gst_value_deserialize_flags), (_gst_value_initialize): + Fix serialisation of buffers, they are not boxed types anymore + +2005-06-20 15:14:58 +0000 Wim Taymans + + check/gst/gstcaps.c: Testcase to show error in buffer-on-caps serialisation. + Original commit message from CVS: + * check/gst/gstcaps.c: (START_TEST), (gst_caps_suite): + Testcase to show error in buffer-on-caps serialisation. + +2005-06-20 15:13:43 +0000 Andy Wingo + + docs/random/wingo/porting-plugins-to-0.9: A pitiful document I will be adding to later. + Original commit message from CVS: + 2005-06-20 Andy Wingo + * docs/random/wingo/porting-plugins-to-0.9: A pitiful document I + will be adding to later. + +2005-06-20 11:41:17 +0000 Andy Wingo + + gst/gstsystemclock.c (gst_system_clock_init): Unlock the clock if its socks fill with rocks. + Original commit message from CVS: + 2005-06-20 Andy Wingo + * gst/gstsystemclock.c (gst_system_clock_init): Unlock the clock + if its socks fill with rocks. + (gst_system_clock_obtain): Set the name on object construction. + Avoid double-checked locking. + +2005-06-20 11:32:14 +0000 Tim-Philipp Müller + + gst/gsturi.c: Fix potential endless loop. + Original commit message from CVS: + * gst/gsturi.c: (gst_element_make_from_uri): + Fix potential endless loop. + +2005-06-20 11:27:36 +0000 Thomas Vander Stichele + + * configure.ac: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/ghostpads/.gitignore: + * tests/old/testsuite/ghostpads/Makefile.am: + * tests/old/testsuite/ghostpads/ghostpads.c: + * testsuite/Makefile.am: + * testsuite/ghostpads/.gitignore: + * testsuite/ghostpads/Makefile.am: + * testsuite/ghostpads/ghostpads.c: + remove another test that's obsolete + Original commit message from CVS: + remove another test that's obsolete + +2005-06-20 11:23:59 +0000 Thomas Vander Stichele + + * configure.ac: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/clock/.gitignore: + * tests/old/testsuite/clock/Makefile.am: + * tests/old/testsuite/clock/clock1.c: + * tests/old/testsuite/clock/clock2.c: + * tests/old/testsuite/clock/signedness.c: + * testsuite/Makefile.am: + * testsuite/clock/.gitignore: + * testsuite/clock/Makefile.am: + * testsuite/clock/clock1.c: + * testsuite/clock/clock2.c: + * testsuite/clock/signedness.c: + remove clock testsuite, important stuff already moved to check + Original commit message from CVS: + remove clock testsuite, important stuff already moved to check + +2005-06-20 11:18:40 +0000 Thomas Vander Stichele + + * configure.ac: + * tests/old/testsuite/Makefile.am: + * tests/old/testsuite/bins/.gitignore: + * tests/old/testsuite/bins/Makefile.am: + * tests/old/testsuite/bins/interface.c: + * testsuite/Makefile.am: + * testsuite/bins/.gitignore: + * testsuite/bins/Makefile.am: + * testsuite/bins/interface.c: + remove test that was already moved to check + Original commit message from CVS: + remove test that was already moved to check + +2005-06-19 11:32:42 +0000 Thomas Vander Stichele + + check/Makefile.am: add gsttag + Original commit message from CVS: + * check/Makefile.am: + add gsttag + * check/gst/gsttag.c: (check_tags), (START_TEST), (gst_tag_suite), + (main): + move over from testsuite dir and clean up + * configure.ac: + * gst/gsttag.c: + * testsuite/Makefile.am: + * testsuite/tags/.cvsignore: + * testsuite/tags/Makefile.am: + * testsuite/tags/merge.c: + remove testsuite/tags + +2005-06-19 10:54:12 +0000 Thomas Vander Stichele + + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstbin.sgml: + * docs/gst/tmpl/gstbuffer.sgml: + * docs/gst/tmpl/gstcaps.sgml: + * docs/gst/tmpl/gststructure.sgml: + * gst/gstbin.h: + * gst/gstbuffer.h: + some more docs cleanup + Original commit message from CVS: + some more docs cleanup + +2005-06-19 10:31:42 +0000 Thomas Vander Stichele + + * configure.ac: + * tests/Makefile.am: + * tests/bufspeed/.gitignore: + * tests/bufspeed/Makefile.am: + * tests/bufspeed/README: + * tests/bufspeed/gstmempool.c: + * tests/bufspeed/gstmempool.h: + * tests/bufspeed/test1.c: + * tests/bufspeed/test2.c: + * tests/spidey_bench.c: + remove bufspeed and spidey_bench + Original commit message from CVS: + remove bufspeed and spidey_bench + +2005-06-19 10:22:47 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstenumtypes.sgml: + * win32/gstenumtypes.c: + clean up docs a little + Original commit message from CVS: + clean up docs a little + +2005-06-19 00:52:31 +0000 Thomas Vander Stichele + + check/gstcheck.h: add macros for checking refcounts on objects and caps + Original commit message from CVS: + * check/gstcheck.h: + add macros for checking refcounts on objects and caps + * check/gst/gstpad.c: (START_TEST), (gst_pad_suite): + add some more unit tests + * gst/gstpad.c: (gst_pad_link_check_compatible_unlocked), + (gst_pad_link_prepare), (gst_pad_link), (gst_pad_get_allowed_caps): + fix leaked refcounts (I hope :)) so unittest works + * gst/gstpad.h: + whitespace removal + +2005-06-18 22:33:14 +0000 Thomas Vander Stichele + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + back to head + Original commit message from CVS: + back to head + +2005-06-17 12:00:35 +0000 Andy Wingo + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2005-06-17 11:58:48 +0000 Andy Wingo + + gst/base/gstbasesink.c (gst_basesink_chain): Remove bogus assert; it's always possible that the pad gets deactivated ... + Original commit message from CVS: + 2005-06-17 Andy Wingo + * gst/base/gstbasesink.c (gst_basesink_chain): Remove bogus + assert; it's always possible that the pad gets deactivated in + between the checks in gstpad.c and the implementation. Rely on + finish_preroll() to return a FLUSHING or similar instead of on the + assert. + +2005-06-17 11:33:27 +0000 Andy Wingo + + gst/base/gstbasesink.c (gst_basesink_event): Only wait for the clock and post an EOS message if we come out of finish... + Original commit message from CVS: + 2005-06-17 Andy Wingo + * gst/base/gstbasesink.c (gst_basesink_event): Only wait for the + clock and post an EOS message if we come out of finish_preroll in + the playing state. + +2005-06-17 09:58:38 +0000 Thomas Vander Stichele + + * README: + incorporate plugins stuff and uninstalled stuff + Original commit message from CVS: + incorporate plugins stuff and uninstalled stuff + +2005-06-17 09:32:19 +0000 Thomas Vander Stichele + + * gst/indexers/.gitignore: + * plugins/indexers/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-06-17 09:12:33 +0000 Thomas Vander Stichele + + * check/gst/.gitignore: + * gst/base/.gitignore: + * gst/elements/.gitignore: + * gst/parse/.gitignore: + * gst/registries/.gitignore: + * gst/schedulers/.gitignore: + * libs/gst/base/.gitignore: + * libs/gst/bytestream/.gitignore: + * libs/gst/control/.gitignore: + * libs/gst/dataprotocol/.gitignore: + * libs/gst/getbits/.gitignore: + * plugins/elements/.gitignore: + * tests/check/gst/.gitignore: + * tools/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2005-06-17 08:59:41 +0000 Thomas Vander Stichele + + * .gitignore: + * ChangeLog: + * README: + * check/.gitignore: + * examples/manual/.gitignore: + * gst/.gitignore: + * tests/check/.gitignore: + * tests/old/examples/manual/.gitignore: + ignore more; fix README + Original commit message from CVS: + ignore more; fix README + +2005-06-16 17:50:16 +0000 David Schleef + + gst/elements/gstcapsfilter.c: Allow NULL as possible value for filter_caps property, indicating GST_CAPS_ANY. + Original commit message from CVS: + * gst/elements/gstcapsfilter.c: (gst_capsfilter_class_init), + (gst_capsfilter_set_property): Allow NULL as possible value + for filter_caps property, indicating GST_CAPS_ANY. + +2005-06-09 13:33:00 +0000 Thomas Vander Stichele + + gst/elements/gstfakesrc.c: fix debug output + Original commit message from CVS: + * gst/elements/gstfakesrc.c: (gst_fakesrc_create): + fix debug output + * gst/schedulers/Makefile.am: + use libgst prefix + * gstreamer.spec.in: + fix spec for it + +2005-06-09 12:23:05 +0000 Thomas Vander Stichele + + gstreamer.spec.in: clean up + Original commit message from CVS: + * gstreamer.spec.in: + clean up + +2005-06-09 12:09:56 +0000 Thomas Vander Stichele + + gstreamer.spec.in: clean up + Original commit message from CVS: + * gstreamer.spec.in: + clean up + +2005-06-09 12:03:04 +0000 Thomas Vander Stichele + + * TODO: + * docs/random/TODO-pre-0.9: + have a real TODO, move old TODO + Original commit message from CVS: + have a real TODO, move old TODO + +2005-06-09 12:00:27 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + po updates + Original commit message from CVS: + po updates + +2005-06-09 11:12:57 +0000 Thomas Vander Stichele + + * po/af.po: + * po/az.po: + * po/ca.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/fr.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/ru.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + update translations + Original commit message from CVS: + update translations + +2005-06-08 22:16:27 +0000 Andy Wingo + + gst/gstutils.c: RPAD fixes all around. + Original commit message from CVS: + 2005-06-08 Andy Wingo + * gst/gstutils.c: RPAD fixes all around. + (gst_element_link_pads): Refcounting fixes. + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + * parse/grammar.y: + * gst/base/gsttypefindhelper.c: + * gst/base/gstbasesink.c: + * gst/gstqueue.c: RPAD fixes. + * gst/gstghostpad.h: + * gst/gstghostpad.c: New ghost pad implementation as full proxy + pads. The tricky thing is they provide both source and sink + interfaces, since they proxy the internal pad for the external + pad, and vice versa. Implement with lower-level ProxyPad objects, + with the interior proxy pad as a child of the exterior ghost pad. + Should write a doc on this. + * gst/gstpad.h: s/RPAD/PAD/, s/RealPad/Pad/. + (gst_pad_set_name, gst_pad_set_parent): Macros removed, use + gst_object API. + * gst/gstpad.c: Big changes. No more stub base GstPad, now all + pads are real pads. No ghost pads in this file. Not documenting + the myriad s/RPAD/PAD/ and REALIZE fixes. + (gst_pad_class_init): Add properties for "direction" and + "template". Both are construct-only, so they can't change during + the life of the pad. Fixes properly deriving from GstPad. + (gst_pad_custom_new, gst_pad_custom_new_from_template): Gone. For + derived objects, just set properties when creating the objects via + g_object_new. + (gst_pad_get_parent): Implement as a function, return NULL if the + parent is not an element. + (gst_pad_get_real_parent, gst_pad_add_ghost_pad) + (gst_pad_remove_ghost_pad, gst_pad_realize): Removed. + * gst/gstobject.c (gst_object_class_init): Make name a construct + property. Don't set it in the object init. + * gst/gstelement.c (gst_element_add_pad): Don't allow adding pads + with UNKNOWN direction. + (gst_element_add_ghost_pad): Remove non-orthogonal API. Replace + with gst_element_add_pad (e, gst_ghost_pad_new (name, pad)). + (gst_element_remove_pad): Remove ghost-pad special cases. + (gst_element_pads_activate): Remove rpad cruft. + * gst/gstbin.c (gst_bin_change_state): Use gst_pad_get_parent to + catch the pad's-parent-not-an-element case. + * gst/gst.h: Include gstghostpad.h. + * gst/gst.c (init_post): No more real, ghost pads. + * gst/Makefile.am: Add gstghostpad.[ch]. + * check/Makefile.am: + * check/gst/gstbin.c: + * check/gst/gstghostpad.c (test_ghost_pads): Check that linking + into a bin creates ghost pads, and that the refcounts are right. + Partly moved from gstbin.c. + +2005-06-08 14:00:21 +0000 Thomas Vander Stichele + + check/: ignore more + Original commit message from CVS: + * check/gst-libs/.cvsignore: + * check/gst/.cvsignore: + * check/pipelines/.cvsignore: + ignore more + * check/pipelines/cleanup.c: (setup_pipeline), (run_pipeline), + (START_TEST), (cleanup_suite), (main): + add some tests related to cleanup after running pipelines + +2005-06-08 13:57:13 +0000 Thomas Vander Stichele + + * ChangeLog: + * check/gst/gstbuffer.c: + * tests/check/gst/gstbuffer.c: + add a GstBuffer unit test + Original commit message from CVS: + add a GstBuffer unit test + +2005-06-08 13:45:26 +0000 Thomas Vander Stichele + + * ChangeLog: + previous commit accidentally also added refcount defines for gstminiobject, logging that now + Original commit message from CVS: + previous commit accidentally also added refcount defines for gstminiobject, logging that now + +2005-06-08 13:42:52 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * docs/faq/gst-uninstalled: + * gst/gstminiobject.h: + * tests/check/Makefile.am: + add a 'plugins' dir to the PLUGIN_PATH in the uninstalled script to drop random other plugin-having projects in + Original commit message from CVS: + add a 'plugins' dir to the PLUGIN_PATH in the uninstalled script to drop random other plugin-having projects in + +2005-06-08 13:41:48 +0000 Thomas Vander Stichele + + * configure.ac: + we did a prerelease + Original commit message from CVS: + we did a prerelease + +2005-06-08 13:41:31 +0000 Thomas Vander Stichele + + * gst/gstobject.h: + OBJECT acts on obj not caps + Original commit message from CVS: + OBJECT acts on obj not caps + +2005-06-08 13:41:05 +0000 Thomas Vander Stichele + + * gst/gstelementfactory.c: + add a debug line + Original commit message from CVS: + add a debug line + +2005-06-08 13:40:46 +0000 Thomas Vander Stichele + + * gst/gstbuffer.c: + * gst/gstbuffer.h: + white space fixes + Original commit message from CVS: + white space fixes + +2005-06-03 18:26:59 +0000 Stefan Kost + + * ChangeLog: + * Makefile.am: + * common: + added support for html unit test coverage reports + Original commit message from CVS: + added support for html unit test coverage reports + +2005-06-02 15:45:16 +0000 Jan Schmidt + + gst/elements/gstcapsfilter.c: Free existing caps if the capsfilter changes. Add a FIXME about setting those caps on t... + Original commit message from CVS: + * gst/elements/gstcapsfilter.c: (gst_capsfilter_set_property): + Free existing caps if the capsfilter changes. Add a FIXME about + setting those caps on the pads. + * gst/gstutils.c: (gst_element_get_compatible_pad), (ghost_up): + Before adding a ghost pad to a parent bin, check that there isn't + already one for the element on the bin. Prevents infinite recursion + when using decodebin in parse pipelines. Andy says he'll rewrite the + way this works anyway, so ignore the hack. + +2005-06-02 11:12:34 +0000 Andy Wingo + + gst/elements/gsttypefindelement.c (do_pull_typefind): Query the file size, pass it on to the type find helper. + Original commit message from CVS: + 2005-06-02 Andy Wingo + * gst/elements/gsttypefindelement.c (do_pull_typefind): Query the + file size, pass it on to the type find helper. + * gst/base/gstbasesrc.c (gst_basesrc_do_seek): Set the + segment_start and segment_end properly according to the seek + method. Segment_end is still a bit flaky because offset can be + negative for CUR and END cases, but it takes -1 as an "unset" + value. + +2005-06-02 09:42:02 +0000 Wim Taymans + + gst/: Bufferalloc: return GstFlowReturn to more accuratly report why allocation failed. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_pad_buffer_alloc), + (gst_base_sink_buffer_alloc), (gst_basesink_preroll_queue_push), + (gst_basesink_activate): + * gst/base/gstbasesink.h: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare), + (gst_pad_link), (gst_pad_accept_caps), (gst_pad_alloc_buffer), + (gst_pad_query), (gst_pad_start_task): + * gst/gstpad.h: + * gst/gstqueue.c: (gst_queue_bufferalloc), + (gst_queue_handle_sink_event), (gst_queue_chain): + Bufferalloc: return GstFlowReturn to more accuratly report + why allocation failed. + +2005-06-02 09:39:21 +0000 Wim Taymans + + gst/gstpipeline.c: Take snapshot of state without blocking. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_send_event): + Take snapshot of state without blocking. + +2005-06-02 08:26:58 +0000 Wim Taymans + + docs/design/: Small doc updates + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-caps.txt: + * docs/design/part-clocks.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-preroll.txt: + Small doc updates + +2005-05-30 16:28:41 +0000 Wim Taymans + + gst/elements/gstidentity.c: Protect last_message property as it is accessed from multiple threads. + Original commit message from CVS: + * gst/elements/gstidentity.c: (gst_identity_event), + (gst_identity_transform), (gst_identity_get_property): + Protect last_message property as it is accessed from + multiple threads. + +2005-05-30 15:53:04 +0000 Wim Taymans + + gst/gstelement.c: Slicker pad activation code. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_init), + (gst_element_pads_activate), (gst_element_change_state): + Slicker pad activation code. + +2005-05-30 15:51:40 +0000 Wim Taymans + + gst/: Move elementfactory methods to separate .h file. + Original commit message from CVS: + * gst/Makefile.am: + * gst/gstelement.h: + * gst/gstelementfactory.h: + * gst/gsttypes.h: + Move elementfactory methods to separate .h file. + +2005-05-30 15:48:45 +0000 Wim Taymans + + Small typo fixes, doc updates. + Original commit message from CVS: + * docs/design/part-overview.txt: + * gst/gstsystemclock.h: + Small typo fixes, doc updates. + +2005-05-30 15:46:15 +0000 Wim Taymans + + gst/gst.c: Remove cpu-opt flag. + Original commit message from CVS: + * gst/gst.c: (gst_init_get_popt_table), (init_post), + (init_popt_callback): + Remove cpu-opt flag. + +2005-05-30 15:44:50 +0000 Wim Taymans + + gst/gstbuffer.*: Avoid typechecking in places where not needed. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_subbuffer_finalize), + (gst_buffer_create_sub), (gst_buffer_is_span_fast): + * gst/gstbuffer.h: + Avoid typechecking in places where not needed. + Added accessor for malloc_data. + +2005-05-30 15:41:54 +0000 Wim Taymans + + gst/gstpad.c: Propagate errors from _set_caps() in configure_src/sink functions instead of returning TRUE. + Original commit message from CVS: + * gst/gstpad.c: (gst_real_pad_init), (gst_pad_set_active), + (gst_pad_link_prepare), (gst_pad_link), (gst_pad_accept_caps), + (gst_pad_configure_sink), (gst_pad_configure_src), + (gst_pad_alloc_buffer), (gst_pad_query), (gst_pad_send_event), + (gst_pad_start_task): + Propagate errors from _set_caps() in configure_src/sink + functions instead of returning TRUE. + FLUSH events can travel up and downstream + +2005-05-30 15:36:09 +0000 Wim Taymans + + gst/base/gstbasesink.c: Handle EOS in preroll. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_push), + (gst_basesink_activate): + Handle EOS in preroll. + +2005-05-30 15:34:13 +0000 Wim Taymans + + gst/gstqueue.c: Remove old pieces of code + Original commit message from CVS: + * gst/gstqueue.c: (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_loop), (gst_queue_handle_src_event): + Remove old pieces of code + Flushing the queue in an upstream event is a very bad idea. + +2005-05-29 13:56:55 +0000 Benjamin Otte + + file gstsimplescheduler.c was initially added on branch BRANCH-COMPANY. + Original commit message from CVS: + file gstsimplescheduler.c was initially added on branch BRANCH-COMPANY. + +2005-05-27 09:28:05 +0000 Andy Wingo + + * ChangeLog: + remove conflict doobers + Original commit message from CVS: + remove conflict doobers + +2005-05-27 09:27:35 +0000 Andy Wingo + + gst/gstminiobject.c (gst_value_mini_object_collect): Use gst_value_set_mini_object so as to add a ref on the object (... + Original commit message from CVS: + 2005-05-26 Andy Wingo + * gst/gstminiobject.c (gst_value_mini_object_collect): Use + gst_value_set_mini_object so as to add a ref on the object (which + will be removed when the value is unset). + * gst/elements/gstfakesink.c (gst_fakesink_class_init): Fix signal + arg type in ::handoff. + * gst/gstelement.c (gst_element_change_state): Also deactivate + pads in READY->NULL, just in case the element didn't make it to + PAUSED. Wingo tested, Wim approved. + +2005-05-26 10:50:12 +0000 Wim Taymans + + gst/gstpad.c: A flushing pad cannot be used to alloc_buffer from. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare), + (gst_pad_link), (gst_pad_accept_caps), (gst_pad_alloc_buffer), + (gst_pad_query), (gst_pad_send_event), (gst_pad_start_task): + A flushing pad cannot be used to alloc_buffer from. + +2005-05-26 10:48:53 +0000 Wim Taymans + + gst/gstbus.*: Implement a real GSource and use g_main_context_wakeup() to signal new messages instead of the socketpair. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_init), (gst_bus_dispose), (gst_bus_post), + (gst_bus_pop), (gst_bus_source_prepare), (gst_bus_source_check), + (gst_bus_source_dispatch), (gst_bus_source_finalize), + (gst_bus_create_watch), (gst_bus_add_watch_full): + * gst/gstbus.h: + Implement a real GSource and use g_main_context_wakeup() to + signal new messages instead of the socketpair. + +2005-05-25 19:33:39 +0000 Wim Taymans + + gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest. + Original commit message from CVS: + * gst/gstbin.c: (bin_element_is_sink), (has_ancestor), + (bin_element_is_semi_sink), (append_child), (gst_bin_change_state): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare), + (gst_pad_link), (gst_pad_accept_caps), (gst_pad_query), + (gst_pad_send_event), (gst_pad_start_task): + * gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush), + (gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop), + (gst_queue_sink_activate), (gst_queue_src_activate), + (gst_queue_change_state): + * gst/gstqueue.h: + Fix state changes for non sinks. We now change sinks, then elements + with unconnected srcpads, then the rest. + More efficient queue unlocking in flush and state changes. + Set the pad activate mode even if it does not have an activate + function. + +2005-05-25 16:09:34 +0000 Ronald S. Bultje + + * ChangeLog: + * gst/elements/gsttypefindelement.h: + * plugins/elements/gsttypefindelement.h: + happify buildbot + Original commit message from CVS: + happify buildbot + +2005-05-25 15:57:57 +0000 Ronald S. Bultje + + gst/base/gstbasesrc.c: Don't go in pull mode for non-seekable sources. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_basesrc_activate): + Don't go in pull mode for non-seekable sources. + * gst/elements/gsttypefindelement.c: (gst_type_find_element_init), + (gst_type_find_element_dispose), (gst_type_find_handle_src_query), + (free_entry), (stop_typefinding), + (gst_type_find_element_handle_event), (find_peek), + (gst_type_find_element_chain), (do_pull_typefind), + (gst_type_find_element_change_state): + Allow typefinding (w/o seeking) in push-mode, simplified version + of what was in 0.8. + * gst/gstutils.c: (gst_buffer_join): + * gst/gstutils.h: + gst_buffer_join() from 0.8. + +2005-05-25 13:59:18 +0000 Wim Taymans + + gst/gstpad.c: Disable attempt at mode switching until it is figured out. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare), + (gst_pad_link), (gst_pad_accept_caps), (gst_pad_query), + (gst_pad_send_event), (gst_pad_start_task): + Disable attempt at mode switching until it is figured out. + +2005-05-25 11:50:11 +0000 Wim Taymans + + gst/: Implement gst_pad_pause/start/stop_task(), take STREAM lock in task function. + Original commit message from CVS: + * gst/base/gstadapter.c: (gst_adapter_peek), (gst_adapter_flush): + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_push), + (gst_basesink_finish_preroll), (gst_basesink_chain), + (gst_basesink_loop), (gst_basesink_activate), + (gst_basesink_change_state): + * gst/base/gstbasesrc.c: (gst_basesrc_do_seek), + (gst_basesrc_get_range), (gst_basesrc_loop), + (gst_basesrc_activate): + * gst/elements/gsttee.c: (gst_tee_sink_activate): + * gst/gstpad.c: (gst_pad_dispose), (gst_real_pad_class_init), + (gst_real_pad_init), (gst_real_pad_set_property), + (gst_real_pad_get_property), (gst_pad_set_active), + (gst_pad_is_active), (gst_pad_get_query_types), (gst_pad_unlink), + (gst_pad_link_prepare), (gst_pad_link), (gst_pad_get_real_parent), + (gst_real_pad_get_caps_unlocked), (gst_pad_peer_get_caps), + (gst_pad_accept_caps), (gst_pad_get_peer), (gst_pad_realize), + (gst_pad_event_default_dispatch), (gst_pad_event_default), + (gst_pad_dispatcher), (gst_pad_query), (gst_real_pad_dispose), + (gst_pad_save_thyself), (handle_pad_block), (gst_pad_chain), + (gst_pad_push), (gst_pad_get_range), (gst_pad_pull_range), + (gst_pad_send_event), (gst_pad_start_task), (gst_pad_pause_task), + (gst_pad_stop_task): + * gst/gstpad.h: + * gst/gstqueue.c: (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_loop), (gst_queue_src_activate): + * gst/gsttask.c: (gst_task_init), (gst_task_set_lock), + (gst_task_get_state): + * gst/gsttask.h: + * gst/schedulers/threadscheduler.c: + (gst_thread_scheduler_task_start), (gst_thread_scheduler_func): + Implement gst_pad_pause/start/stop_task(), take STREAM lock + in task function. + Remove ACTIVE pad flag, use FLUSHING everywhere + Added _pad_chain(), _pad_get_range() to call chain/getrange + functions. + Add locks around IS_FLUSHING when reading. + Take STREAM lock in chain(), get_range() functions so plugins + don't need to take it anymore. + +2005-05-25 11:26:14 +0000 Wim Taymans + + tools/gst-launch.c: Unref message after using its contents instead of before. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Unref message after using its contents instead of + before. + +2005-05-24 16:47:06 +0000 Wim Taymans + + docs/design/: Docs updates. + Original commit message from CVS: + * docs/design/draft-ghostpads.txt: + * docs/design/draft-push-pull.txt: + * docs/design/draft-query.txt: + * docs/design/part-overview.txt: + Docs updates. + Added general overview doc. + Added draft ghostpad replacement idea. + +2005-05-22 04:26:41 +0000 David Schleef + + docs/gst/tmpl/old/: I didn't intend to add these or check them in. + Original commit message from CVS: + * docs/gst/tmpl/old/GstBin.sgml: + * docs/gst/tmpl/old/GstBuffer.sgml: + * docs/gst/tmpl/old/GstCaps.sgml: + * docs/gst/tmpl/old/GstClock.sgml: + * docs/gst/tmpl/old/GstCompat.sgml: + * docs/gst/tmpl/old/GstData.sgml: + * docs/gst/tmpl/old/GstElement.sgml: + * docs/gst/tmpl/old/GstEvent.sgml: + * docs/gst/tmpl/old/GstIndex.sgml: + * docs/gst/tmpl/old/GstStructure.sgml: + * docs/gst/tmpl/old/GstTag.sgml: + * docs/gst/tmpl/old/cothreads.sgml: + * docs/gst/tmpl/old/cothreads_compat.sgml: + * docs/gst/tmpl/old/gettext.sgml: + * docs/gst/tmpl/old/gobject2gtk.sgml: + * docs/gst/tmpl/old/grammar.tab.sgml: + * docs/gst/tmpl/old/gst-i18n-app.sgml: + * docs/gst/tmpl/old/gst-i18n-lib.sgml: + * docs/gst/tmpl/old/gst_private.sgml: + * docs/gst/tmpl/old/gstaggregator.sgml: + * docs/gst/tmpl/old/gstarch.sgml: + * docs/gst/tmpl/old/gstatomic_impl.sgml: + * docs/gst/tmpl/old/gstbufferstore.sgml: + * docs/gst/tmpl/old/gstdata_private.sgml: + * docs/gst/tmpl/old/gstdisksink.sgml: + * docs/gst/tmpl/old/gstdisksrc.sgml: + * docs/gst/tmpl/old/gstelementfactory.sgml: + * docs/gst/tmpl/old/gstextratypes.sgml: + * docs/gst/tmpl/old/gstfakesink.sgml: + * docs/gst/tmpl/old/gstfakesrc.sgml: + * docs/gst/tmpl/old/gstfdsink.sgml: + * docs/gst/tmpl/old/gstfdsrc.sgml: + * docs/gst/tmpl/old/gstfilesink.sgml: + * docs/gst/tmpl/old/gstfilesrc.sgml: + * docs/gst/tmpl/old/gsthttpsrc.sgml: + * docs/gst/tmpl/old/gstidentity.sgml: + * docs/gst/tmpl/old/gstindexfactory.sgml: + * docs/gst/tmpl/old/gstmarshal.sgml: + * docs/gst/tmpl/old/gstmd5sink.sgml: + * docs/gst/tmpl/old/gstmultidisksrc.sgml: + * docs/gst/tmpl/old/gstmultifilesrc.sgml: + * docs/gst/tmpl/old/gstpadtemplate.sgml: + * docs/gst/tmpl/old/gstpipefilter.sgml: + * docs/gst/tmpl/old/gstschedulerfactory.sgml: + * docs/gst/tmpl/old/gstsearchfuncs.sgml: + * docs/gst/tmpl/old/gstshaper.sgml: + * docs/gst/tmpl/old/gstspider.sgml: + * docs/gst/tmpl/old/gstspideridentity.sgml: + * docs/gst/tmpl/old/gststatistics.sgml: + * docs/gst/tmpl/old/gsttee.sgml: + * docs/gst/tmpl/old/gsttimecache.sgml: + * docs/gst/tmpl/old/gsttypefindfactory.sgml: + * docs/gst/tmpl/old/gstxmlregistry.sgml: + * docs/gst/tmpl/old/gthread-cothreads.sgml: + * docs/gst/tmpl/old/types.sgml: + I didn't intend to add these or check them in. + +2005-05-20 12:47:05 +0000 Christian Schaller + + * gstreamer.spec.in: + update spec file + Original commit message from CVS: + update spec file + +2005-05-19 19:54:01 +0000 David Schleef + + configure.ac: Use -no-common everywhere. In a sane world, it would be the default in libtool, because without it, yo... + Original commit message from CVS: + * configure.ac: Use -no-common everywhere. In a sane world, it + would be the default in libtool, because without it, you can't + build DLLs on Windows. + * docs/gst/gstreamer-docs.sgml: Remove GstCpu, GstData, GstThread + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstcpu.sgml: + * docs/gst/tmpl/gstdata.sgml: + * docs/gst/tmpl/gstthread.sgml: + +2005-05-19 19:41:12 +0000 David Schleef + + gst/gstminiobject.*: Add GValue set/get functions. + Original commit message from CVS: + * gst/gstminiobject.c: (gst_value_set_mini_object), + (gst_value_take_mini_object), (gst_value_get_mini_object): + * gst/gstminiobject.h: Add GValue set/get functions. + +2005-05-19 16:26:50 +0000 Wim Taymans + + gst/: Make subbufer unref the parent in finalize. some more debugging info. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_init), (gst_subbuffer_get_type), + (gst_subbuffer_class_init), (gst_subbuffer_finalize), + (gst_subbuffer_init), (gst_buffer_is_span_fast): + * gst/gstbuffer.h: + * gst/gstbus.c: (gst_bus_post): + * gst/gstelement.c: (gst_element_get_random_pad): + * gst/gstmessage.c: (gst_message_init), (gst_message_finalize): + Make subbufer unref the parent in finalize. + some more debugging info. + +2005-05-19 16:23:04 +0000 Wim Taymans + + gst/base/gstbasesink.c: Don't free preroll queue too early. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_class_init), + (gst_basesink_init), (gst_basesink_finalize), + (gst_basesink_activate), (gst_basesink_change_state): + Don't free preroll queue too early. + +2005-05-19 14:52:16 +0000 Ronald S. Bultje + + gst/: Hi, I'm outdated. Please shoot me. + Original commit message from CVS: + * gst/Makefile.am: + * gst/ROADMAP: + Hi, I'm outdated. Please shoot me. + +2005-05-19 12:07:35 +0000 Ronald S. Bultje + + gst/gstpipeline.c: Do not access variables after they have been deleted. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_send_event): + Do not access variables after they have been deleted. + +2005-05-19 08:41:42 +0000 Wim Taymans + + tools/gst-inspect.c: A plugin feature does unfortunatly not use the object name yet... + Original commit message from CVS: + * tools/gst-inspect.c: (print_plugin_features): + A plugin feature does unfortunatly not use the + object name yet... + +2005-05-18 17:35:23 +0000 Wim Taymans + + gst/gstbuffer.c: Port _span() functions to new subbuffers. + Original commit message from CVS: + * gst/gstbuffer.c: (gst_buffer_is_span_fast), (gst_buffer_span): + Port _span() functions to new subbuffers. + +2005-05-18 13:49:08 +0000 Ronald S. Bultje + + gst/gstbin.c: Fix clock settery in bins when adding kids after the clock has been selected. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func): + Fix clock settery in bins when adding kids after the clock has + been selected. + +2005-05-18 13:23:24 +0000 Ronald S. Bultje + + gst/elements/gstidentity.c: Workaround until signals support GstMiniObject. + Original commit message from CVS: + * gst/elements/gstidentity.c: (gst_identity_class_init): + Workaround until signals support GstMiniObject. + +2005-05-18 11:34:45 +0000 Jan Schmidt + + gst/gstbuffer.c: Oops, fix a typo GST_TYPE_BUFFER -> GST_TYPE_SUBBUFFER. + Original commit message from CVS: + * gst/gstbuffer.c: + Oops, fix a typo GST_TYPE_BUFFER -> GST_TYPE_SUBBUFFER. + +2005-05-18 09:55:43 +0000 Wim Taymans + + gst/base/: Ported and added adapter to the base classes. + Original commit message from CVS: + * gst/base/Makefile.am: + * gst/base/gstadapter.c: (gst_adapter_base_init), + (gst_adapter_class_init), (gst_adapter_init), + (gst_adapter_dispose), (gst_adapter_finalize), (gst_adapter_new), + (gst_adapter_clear), (gst_adapter_push), (gst_adapter_peek), + (gst_adapter_flush), (gst_adapter_available), + (gst_adapter_available_fast): + * gst/base/gstadapter.h: + Ported and added adapter to the base classes. + +2005-05-17 17:50:41 +0000 Thomas Vander Stichele + + gst/: Make sure the class is reffed/unreffed once before threads can be used. Fixes #304551. + Original commit message from CVS: + * gst/gst.c: + * gst/gstmessage.c: + Make sure the class is reffed/unreffed once before threads can be + used. Fixes #304551. + +2005-05-17 17:37:43 +0000 Wim Taymans + + gst/: Don't queue buffers in basesink when we are flushing. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_finish_preroll), + (gst_basesink_chain_unlocked), (gst_basesink_activate): + * gst/gstminiobject.c: (gst_mini_object_get_type), + (gst_mini_object_free): + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_query), + (gst_pad_push), (gst_pad_push_event): + * gst/gstqueue.c: (gst_queue_change_state): + Don't queue buffers in basesink when we are flushing. + Unref buffer when flushing in basesink. + Flush queue when going to READY + Unref buffer when _push() returns an error. + Don't free MiniObject instance when refcount is incremented + in _finalize() so that we can recover objects. + +2005-05-17 17:22:31 +0000 Thomas Vander Stichele + + * ChangeLog: + * common: + * docs/manual/advanced-schedulers.xml: + * docs/manual/appendix-checklist.xml: + * docs/pwg/advanced-clock.xml: + * docs/pwg/advanced-interfaces.xml: + * docs/pwg/advanced-request.xml: + * docs/pwg/advanced-types.xml: + * docs/pwg/intro-preface.xml: + * examples/plugins/example.c: + * examples/plugins/example.h: + * tests/old/examples/plugins/example.c: + * tests/old/examples/plugins/example.h: + small doc fixes + Original commit message from CVS: + small doc fixes + +2005-05-17 14:11:32 +0000 Wim Taymans + + gst/: Clear queue when going to READY. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_set_caps), + (gst_pad_alloc_buffer), (gst_pad_query), (gst_pad_push): + * gst/gstqueue.c: (gst_queue_change_state): + Clear queue when going to READY. + Remove IN_SETCAPS flag too. + +2005-05-17 14:01:51 +0000 Tim-Philipp Müller + + gst/base/gstbasesrc.c: Remove implicit cast from gboolean to GstElementStateReturn; make sure we still return failure... + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_basesrc_change_state): + Remove implicit cast from gboolean to GstElementStateReturn; + make sure we still return failure in paused => ready case if + the parent class fails to change state and our own stop + vfunc succeeds. + +2005-05-17 10:41:51 +0000 Wim Taymans + + tools/gst-launch.c: Message was unreffed too soon. + Original commit message from CVS: + * tools/gst-launch.c: (event_loop): + Message was unreffed too soon. + +2005-05-16 21:17:14 +0000 Andy Wingo + + gst/gstbin.c (sink_iterator_filter): Err... um... + Original commit message from CVS: + 2005-05-16 Andy Wingo + * gst/gstbin.c (sink_iterator_filter): Err... um... + * check/gst/gstbin.c (test_ghost_pads): New test for the + ghosting-if-elements-not-in-same-bin behavior. + +2005-05-16 21:05:21 +0000 David Schleef + + gst/gstminiobject.c: Use g_atomic_int_get() instead of accessing refcount directly. + Original commit message from CVS: + * gst/gstminiobject.c: Use g_atomic_int_get() instead of + accessing refcount directly. + +2005-05-16 20:21:55 +0000 David Schleef + + check/Makefile.am: remove GstData checks + Original commit message from CVS: + * check/Makefile.am: remove GstData checks + * check/gst-libs/gdp.c: (START_TEST): fix for API changes + * gst/Makefile.am: add miniobject, remove data + * gst/gst.h: add miniobject, remove data + * gst/gstdata.c: remove + * gst/gstdata.h: remove + * gst/gstdata_private.h: remove + * gst/gsttypes.h: remove GstEvent and GstMessage + * gst/gstelement.c: (gst_element_post_message): fix for API changes + * gst/gstmarshal.list: change BOXED -> OBJECT + Implement GstMiniObject. + * gst/gstminiobject.c: + * gst/gstminiobject.h: + Modify to be subclasses of GstMiniObject. + * gst/gstbuffer.c: (_gst_buffer_initialize), (gst_buffer_get_type), + (gst_buffer_class_init), (gst_buffer_finalize), (_gst_buffer_copy), + (gst_buffer_init), (gst_buffer_new), (gst_buffer_new_and_alloc), + (gst_subbuffer_get_type), (gst_subbuffer_init), + (gst_buffer_create_sub), (gst_buffer_is_span_fast), + (gst_buffer_span): + * gst/gstbuffer.h: + * gst/gstevent.c: (_gst_event_initialize), (gst_event_get_type), + (gst_event_class_init), (gst_event_init), (gst_event_finalize), + (_gst_event_copy), (gst_event_new): + * gst/gstevent.h: + * gst/gstmessage.c: (_gst_message_initialize), + (gst_message_get_type), (gst_message_class_init), + (gst_message_init), (gst_message_finalize), (_gst_message_copy), + (gst_message_new), (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_application): + * gst/gstmessage.h: + * gst/gstprobe.c: (gst_probe_perform), + (gst_probe_dispatcher_dispatch): + * gst/gstprobe.h: + * gst/gstquery.c: (_gst_query_initialize), (gst_query_get_type), + (gst_query_class_init), (gst_query_finalize), (gst_query_init), + (_gst_query_copy), (gst_query_new): + Update elements for GstData -> GstMiniObject changes + * gst/gstquery.h: + * gst/gstqueue.c: (gst_queue_finalize), (gst_queue_locked_flush), + (gst_queue_chain), (gst_queue_loop): + * gst/elements/gstbufferstore.c: + (gst_buffer_store_add_buffer_func), + (gst_buffer_store_cleared_func), (gst_buffer_store_get_buffer): + * gst/elements/gstfakesink.c: (gst_fakesink_class_init), + (gst_fakesink_render): + * gst/elements/gstfakesrc.c: (gst_fakesrc_class_init): + * gst/elements/gstfilesrc.c: (gst_mmap_buffer_get_type), + (gst_mmap_buffer_class_init), (gst_mmap_buffer_init), + (gst_mmap_buffer_finalize), (gst_filesrc_map_region), + (gst_filesrc_create_read): + * gst/elements/gstidentity.c: (gst_identity_class_init): + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_src_event), (free_entry_buffers), + (gst_type_find_element_handle_event): + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer): + * libs/gst/dataprotocol/dataprotocol.h: + * libs/gst/dataprotocol/dp-private.h: + +2005-05-15 23:18:40 +0000 David Schleef + + gst/elements/gstelements.c: Don't include headers that were just removed. + Original commit message from CVS: + * gst/elements/gstelements.c: Don't include headers that were + just removed. + +2005-05-15 23:16:29 +0000 David Schleef + + gst/elements/Makefile.am: Remove some elements that don't need to be in the core (or even exist at all). + Original commit message from CVS: + * gst/elements/Makefile.am: Remove some elements that don't + need to be in the core (or even exist at all). + * gst/elements/gstaggregator.c: + * gst/elements/gstaggregator.h: + * gst/elements/gstmd5sink.c: + * gst/elements/gstmd5sink.h: + * gst/elements/gstmultifilesrc.c: + * gst/elements/gstmultifilesrc.h: + * gst/elements/gstpipefilter.c: + * gst/elements/gstpipefilter.h: + * gst/elements/gstshaper.c: + * gst/elements/gstshaper.h: + * gst/elements/gststatistics.c: + * gst/elements/gststatistics.h: + * po/POTFILES.in: Remove above files. + +2005-05-14 18:01:12 +0000 Andy Wingo + + gst/gstbin.c (gst_bin_iterate_sinks): Use sink_iterator_filter so as to get the refs right. + Original commit message from CVS: + 2005-05-14 Andy Wingo + * gst/gstbin.c (gst_bin_iterate_sinks): Use sink_iterator_filter + so as to get the refs right. + (sink_iterator_filter): New function, wraps bin_element_is_sink, + unreffing objects that don't pass the filter. + +2005-05-14 17:12:11 +0000 Andy Wingo + + gst/gstpipeline.c (gst_pipeline_init): Drop ref on bus after gst_element_set_bus. + Original commit message from CVS: + 2005-05-14 Andy Wingo + * gst/gstpipeline.c (gst_pipeline_init): Drop ref on bus after + gst_element_set_bus. + (gst_pipeline_dispose): Set the bus on the pipeline to NULL. In + normal cases, this will destroy the bus. + * gst/gstutils.c (prepare_link_maybe_ghosting): Drop ref on root + object. + +2005-05-14 15:54:49 +0000 Andy Wingo + + gst/gstbin.c (gst_bin_change_state): Fix state changes if a bin has no sinks. + Original commit message from CVS: + 2005-05-14 Andy Wingo + * gst/gstbin.c (gst_bin_change_state): Fix state changes if a bin + has no sinks. + +2005-05-14 15:32:36 +0000 Andy Wingo + + gst/gstutils.c (gst_element_link_pads): Instead of calling gst_pad_link, call pad_link_maybe_ghosting, + Original commit message from CVS: + 2005-05-13 Andy Wingo + * gst/gstutils.c (gst_element_link_pads): Instead of calling + gst_pad_link, call pad_link_maybe_ghosting, + (pad_link_maybe_ghosting): Links pads, making sure that the + elements being linked are in the same bin. + (find_common_root, object_has_ancestor, ghost_up, remove_pad): + Helpers for pad_link_maybe_ghosting. + +2005-05-13 12:53:47 +0000 Tim-Philipp Müller + + * ChangeLog: + * configure.ac: + Require GLib >= 2.4.0 (for the g_atomic_* funcs) + Original commit message from CVS: + Require GLib >= 2.4.0 (for the g_atomic_* funcs) + +2005-05-13 10:18:41 +0000 Christian Schaller + + * gstreamer.spec.in: + add missing .h file to spec file + Original commit message from CVS: + add missing .h file to spec file + +2005-05-13 09:27:24 +0000 Tim-Philipp Müller + + * ChangeLog: + * docs/design/part-element-source.txt: + Mention GstPushSrc + Original commit message from CVS: + Mention GstPushSrc + +2005-05-12 19:45:44 +0000 Wim Taymans + + gst/: Identify sinks by their flag to avoid overly complicated checks (fow now). + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_init), + (gst_basesink_activate): + * gst/base/gstbasesrc.c: (gst_basesrc_unlock), + (gst_basesrc_is_seekable): + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (bin_element_is_sink), (gst_bin_change_state): + * gst/gstelement.c: (gst_element_add_pad), (gst_element_query): + * gst/gstelement.h: + Identify sinks by their flag to avoid overly complicated + checks (fow now). + Do state changes even for elements not reachable from the + sinks. + BaseSink is a sink now :) + Some more debugging info in the basesrc. + +2005-05-12 15:09:17 +0000 Ronald S. Bultje + + gst/gstbin.c: Implement _query on a bin, similar to _send_event. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_query): + Implement _query on a bin, similar to _send_event. + +2005-05-12 13:59:58 +0000 Tim-Philipp Müller + + gst/base/gstbasesrc.c: Discont event offset format should be GST_FORMAT_BYTES, not GST_FORMAT_TIME. + Original commit message from CVS: + * gst/base/gstbasesrc.c: (gst_basesrc_do_seek): + Discont event offset format should be GST_FORMAT_BYTES, + not GST_FORMAT_TIME. + +2005-05-12 13:18:14 +0000 Wim Taymans + + gst/gstbin.c: Same fix as Ronald's but without the signal. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_remove_func), (gst_bin_get_state): + Same fix as Ronald's but without the signal. + +2005-05-12 12:27:07 +0000 Ronald S. Bultje + + gst/gstutils.c: No, an element is not a pad. + Original commit message from CVS: + * gst/gstutils.c: (gst_element_query_position): + No, an element is not a pad. + +2005-05-12 12:17:23 +0000 Ronald S. Bultje + + gst/gstbin.c: If a child is removed from a bin while we remove the child from the bin and while we're retrieving its ... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_add_func), (cb_parent_unset), + (gst_bin_get_state): + If a child is removed from a bin while we remove the child from + the bin and while we're retrieving its state, signal this to the + get_state function so we abort the wait (instead of waiting for + a timeout) and can immediately re-iterate over all other elements. + +2005-05-12 10:43:14 +0000 Wim Taymans + + gst/base/: Added is_seekable to BaseSrc + Original commit message from CVS: + * gst/base/Makefile.am: + * gst/base/gstbasesrc.c: (gst_basesrc_is_seekable), + (gst_basesrc_start): + * gst/base/gstbasesrc.h: + * gst/base/gstpushsrc.c: (gst_pushsrc_get_type), + (gst_pushsrc_base_init), (gst_pushsrc_class_init), + (gst_pushsrc_init), (gst_pushsrc_create): + * gst/base/gstpushsrc.h: + Added is_seekable to BaseSrc + Added simple PushSrc. + +2005-05-11 09:21:24 +0000 Wim Taymans + + gst/: Fix refcounting in utils function. + Original commit message from CVS: + * gst/gstelement.c: (gst_element_add_pad), (gst_element_query): + * gst/gstutils.c: (gst_element_get_compatible_pad_template), + (gst_element_link_pads), (gst_element_query_position), + (gst_element_query_convert), (intersect_caps_func), + (gst_pad_query_position), (gst_pad_query_convert): + Fix refcounting in utils function. + No point in trying to activate a pad when it's added, it could + be added from the state change function and then we deadlock, the + element has to decide what to do. + +2005-05-11 03:37:10 +0000 Andy Wingo + + gst/elements/gstfakesink.c (gst_fakesink_render): Er, emit with + Original commit message from CVS: + 2005-05-10 Andy Wingo + * gst/elements/gstfakesink.c (gst_fakesink_render): Er, emit with + *all* the arguments. + * gst/base/gstbasetransform.c (gst_base_transform_event): Grab the + stream lock if it's a FLUSH_DONE; normal flushes don't get the + lock (according to the docs -- if this is wrong change the docs). + * gst/gstpipeline.c (gst_pipeline_change_state): Set the bus to + flush messages in the NULL state. + * gst/gstbus.c (gst_bus_post): If a bus is flushing, unref the + message immediately and return. + (gst_bus_set_flushing): New function. If a bus is flushing, it + flushes out any queued messages and immediately unrefs new + messages. This is so when an element goes to NULL, all of the + unhandled messages coming from it can be freed, and their + references to the element dropped. In other words: message source + ref considered harmful :P + * gst/gstbin.c (gst_bin_change_state): Unref peer element when + we're finished with it. + * gst/gstmessage.c (gst_message_new_state_changed): + +2005-05-10 14:51:49 +0000 Wim Taymans + + * gst/gstvalue.c: + remove stupid printf + Original commit message from CVS: + remove stupid printf + +2005-05-10 14:50:55 +0000 Wim Taymans + + gst/gstvalue.c: Added flags serialize/deserialize/compare code. + Original commit message from CVS: + * gst/gstvalue.c: (gst_value_compare_flags), + (gst_value_serialize_flags), (gst_value_deserialize_flags), + (_gst_value_initialize): + Added flags serialize/deserialize/compare code. + +2005-05-09 21:37:54 +0000 Andy Wingo + + gst/base/gstbasetransform.c (gst_base_transform_proxy_getcaps): Intersect the peer's caps with our caps. + Original commit message from CVS: + 2005-05-09 Andy Wingo + * gst/base/gstbasetransform.c (gst_base_transform_proxy_getcaps): + Intersect the peer's caps with our caps. + +2005-05-09 15:54:26 +0000 Ronald S. Bultje + + gst/: Handle negative offsets better. Fixes decodebin. + Original commit message from CVS: + * gst/base/gsttypefindhelper.c: (helper_find_peek): + * gst/elements/gsttypefindelement.c: (find_peek): + Handle negative offsets better. Fixes decodebin. + +2005-05-09 14:47:15 +0000 Wim Taymans + + gst/: Implement accept_caps. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_proxy_getcaps), + (gst_base_transform_event): + * gst/gstpad.c: (gst_pad_accept_caps), (gst_pad_query): + Implement accept_caps. + Fix silly lock/unlock mismatch in base class. + +2005-05-09 10:53:13 +0000 Wim Taymans + + * ChangeLog: + * docs/design/draft-push-pull.txt: + * gst/base/gstbasesrc.c: + * gst/elements/gstfilesink.c: + * gst/elements/gsttypefindelement.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstqueryutils.c: + * gst/gstqueryutils.h: + * gst/gstqueue.c: + * gst/gstutils.c: + * gst/gstutils.h: + * libs/gst/base/gstbasesrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttypefindelement.c: + * tools/gst-inspect.c: + * tools/gst-xmlinspect.c: + Remove old query functions. Ported old code. + Original commit message from CVS: + Remove old query functions. Ported old code. + Added position/convert helper functions to gstutils. + Reordered gstpad.c code, grouping relevant things. + Remove gst_message_new(), always need to speficy a specific + message. + +2005-05-09 06:21:10 +0000 Andy Wingo + + gst/gstiterator.h: Add some includes. + Original commit message from CVS: + 2005-05-09 Andy Wingo + * gst/gstiterator.h: Add some includes. + * gst/gstqueryutils.h: Include more headers. + * gst/gstpad.h: + * gst/gstpad.c (gst_pad_query_position): New routine, replaces + some uses of gst_pad_query. + * gst/gstqueryutils.c: Build fixes. Make parse functions ignore + NULL out parameters. + (gst_query_new_position): New proc, allocates a new position + query. + * gst/Makefile.am (libgstreamer_@GST_MAJORMINOR@_la_SOURCES): Add + gstqueryutils.c to the build. + * gst/gststructure.c (gst_structure_set_valist): Implement with + the generic G_VALUE_COLLECT. + +2005-05-08 17:07:05 +0000 Edward Hervey + + gst/Makefile.am: Added gstqueryutils.h to the list of headers to install, that was a 'nachty' move wingo :) + Original commit message from CVS: + * gst/Makefile.am: (gst_headers): + Added gstqueryutils.h to the list of headers to install, that was + a 'nachty' move wingo :) + +2005-05-06 21:41:22 +0000 Andy Wingo + + gst/gstquery.h + Original commit message from CVS: + 2005-05-06 Andy Wingo + * gst/gstquery.h + * gst/gstquery.c (_gst_query_initialize): Extend GstQuery from + GstData, init a memchunk. + (standard_definitions): Add a few query types, deprecate a few. + (gst_query_get_type): New proc. + (_gst_query_copy, _gst_query_free, gst_query_new): GstData + implementation. + (gst_query_new_application, gst_query_get_structure): New public + procs. + * docs/design/draft-query.txt: Removed LINKS from the query types, + because all the rest can be dispatched to other pads -- seemed + ugly to have a query that couldn't be dispatched. internal_links + is fine as a pad method. + * gst/gstpad.h: Add query2 as a pad method, add the new functions + in gstpad.c, but maintain binary compatibility for the moment. + Will fix before 0.9 is out. + * gst/gstqueryutils.c: + * gst/gstqueryutils.h: New files, implement 3 methods for each + query type: parse_query, parse_response, and set. Probably need an + allocator as well. + * gst/gst.h: Add gstquery.h and gstqueryutils.h to the list. + * gst/elements/gstfilesink.c (gst_filesink_query2): + * gst/base/gstbasesrc.c (gst_basesrc_query2): Replace old query, + query_types, and formats methods. + * gst/gstpad.c (gst_pad_query2, gst_pad_query2_default) + (gst_pad_set_query2_function): New functions. + (gst_real_pad_init): Set query2_default as the default query2 + function. Basically just dispatches to internally linked pads. + Needs review! + * gst/gstdata_private.h (_GST_DATA_INIT): Set data->refcount to 1 + without using the atomic operations. Only one thread can possibly + be accessing the data at this point. Changed so as to avoid + gst_atomic operations. + +2005-05-06 19:50:23 +0000 Wim Taymans + + gst/gstpad.c: Also set caps if we use the fallback buffer alloc. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_alloc_buffer), (gst_pad_push): + Also set caps if we use the fallback buffer alloc. + +2005-05-06 17:33:55 +0000 Tim-Philipp Müller + + Purge GstAtomic stuff from docs and win32 makefiles as well + Original commit message from CVS: + * docs/gst/Makefile.am: + * docs/gst/gstreamer-docs.sgml: + * docs/gst/gstreamer-sections.txt: + * docs/gst/tmpl/gstatomic.sgml: + * docs/gst/tmpl/gstmemchunk.sgml: + * testsuite/elements/struct_i386.h: + * win32/GStreamer.vcproj: + * win32/Makefile: + Purge GstAtomic stuff from docs and win32 makefiles as well + +2005-05-06 17:10:49 +0000 Wim Taymans + + gst/: Fix gst_pad_peer_get_caps(), make it return NULL if no peer. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_proxy_getcaps): + * gst/elements/gstcapsfilter.c: (gst_capsfilter_getcaps): + * gst/gstpad.c: (gst_pad_peer_get_caps): + * gst/gstqueue.c: (gst_queue_init), (gst_queue_getcaps), + (gst_queue_bufferalloc), (gst_queue_handle_sink_event), + (gst_queue_src_activate), (gst_queue_change_state): + * gst/gstqueue.h: + * gst/gstutils.c: (gst_element_get_compatible_pad_template), + (intersect_caps_func): + Fix gst_pad_peer_get_caps(), make it return NULL if no peer. + Always take QUEUE_LOCK after STREAM_LOCK or we might deadlock. + Some fixes for the peer_get_caps() change. + +2005-05-06 16:19:59 +0000 Wim Taymans + + gst/base/gstbasesink.c: Actually do something with error codes returned from the push functions. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_preroll_queue_empty), + (gst_basesink_handle_buffer), (gst_basesink_chain_unlocked), + (gst_basesink_activate): + Actually do something with error codes returned from the push + functions. + +2005-05-06 08:25:19 +0000 Wim Taymans + + Some more documentation. + Original commit message from CVS: + * docs/design/part-element-sink.txt: + * docs/design/part-element-source.txt: + * gst/base/gstbasesink.c: (gst_basesink_class_init), + (gst_basesink_event), (gst_basesink_activate): + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: (gst_basesrc_init), (gst_basesrc_unlock), + (gst_basesrc_activate): + * gst/base/gstbasesrc.h: + * gst/gstelement.c: (gst_element_pads_activate): + Some more documentation. + Fixed scheduling decision in _pads_activate(). + +2005-05-05 21:59:53 +0000 Andy Wingo + + * gst/gstelement.c: + * gst/gstpad.c: + final cruft fixage + Original commit message from CVS: + final cruft fixage + +2005-05-05 21:45:54 +0000 Andy Wingo + + * gst/elements/gsttee.c: + * gst/elements/gsttypefindelement.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + cruft removal + Original commit message from CVS: + cruft removal + +2005-05-05 21:42:24 +0000 Andy Wingo + + * gst/base/gstbasesink.c: + * gst/base/gstbasesrc.c: + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.c: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.h: + * libs/gst/base/gstbasetransform.c: + revert cruft + Original commit message from CVS: + revert cruft + +2005-05-05 21:37:34 +0000 Andy Wingo + + * gst/gstpad.c: + * gst/gstpad.h: + revert accidental commit of cruft -- doh + Original commit message from CVS: + revert accidental commit of cruft -- doh + +2005-05-05 15:02:40 +0000 Andy Wingo + + check/pipelines/simple_launch_lines.c (test_2_elements): "Fix" the test suite. + Original commit message from CVS: + 2005-05-05 Andy Wingo + * check/pipelines/simple_launch_lines.c (test_2_elements): "Fix" + the test suite. + +2005-05-05 11:43:06 +0000 Christian Schaller + + * gstreamer.spec.in: + fix broken spec file + Original commit message from CVS: + fix broken spec file + +2005-05-05 09:31:59 +0000 Wim Taymans + + gst/: Added object to help in making collect pad based elements. + Original commit message from CVS: + * gst/base/Makefile.am: + * gst/base/gstbasesink.h: + * gst/base/gstbasesrc.c: (gst_basesrc_init), + (gst_basesrc_set_dataflow_funcs), (gst_basesrc_query): + * gst/base/gstcollectpads.c: (gst_collectpads_get_type), + (gst_collectpads_class_init), (gst_collectpads_init), + (gst_collectpads_finalize), (gst_collectpads_new), + (gst_collectpads_set_function), (gst_collectpads_add_pad), + (find_pad), (gst_collectpads_remove_pad), + (gst_collectpads_is_active), (gst_collectpads_collect), + (gst_collectpads_collect_range), (gst_collectpads_start), + (gst_collectpads_stop), (gst_collectpads_peek), + (gst_collectpads_pop), (gst_collectpads_available), + (gst_collectpads_read), (gst_collectpads_flush), + (gst_collectpads_chain): + * gst/base/gstcollectpads.h: + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: (gst_fakesink_class_init), + (gst_fakesink_get_times), (gst_fakesink_event), + (gst_fakesink_preroll), (gst_fakesink_render): + * gst/elements/gstfilesink.c: (gst_filesink_class_init), + (gst_filesink_init), (gst_filesink_set_location), + (gst_filesink_open_file), (gst_filesink_close_file), + (gst_filesink_pad_query), (gst_filesink_event), + (gst_filesink_render), (gst_filesink_change_state): + * gst/elements/gstfilesink.h: + Added object to help in making collect pad based elements. + Ported filesink. + Make event function in sink baseclass return gboolean. + +2005-05-05 09:28:01 +0000 Wim Taymans + + gst/: Fix name lookup in GstBin. + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_send_event), (compare_name), + (gst_bin_get_by_name): + * gst/gstbuffer.h: + * gst/gstclock.c: (gst_clock_entry_new), (gst_clock_class_init), + (gst_clock_finalize): + * gst/gstdata.c: (gst_data_replace): + * gst/gstdata.h: + * gst/gstelement.c: (gst_element_request_pad), + (gst_element_pads_activate): + * gst/gstobject.c: (gst_object_init), (gst_object_ref), + (gst_object_unref): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_set_checkgetrange_function), + (gst_pad_link_check_compatible_unlocked), (gst_pad_set_caps), + (gst_pad_check_pull_range), (gst_pad_pull_range), + (gst_static_pad_template_get_caps), (gst_pad_start_task), + (gst_pad_pause_task), (gst_pad_stop_task): + * gst/gstutils.c: (gst_element_get_compatible_pad_template), + (gst_element_request_pad), (gst_pad_proxy_getcaps): + Fix name lookup in GstBin. + Added _data_replace() function and _buffer_replace() + Use finalize method to clean up clock. + Fix refcounting on request pads. + Fix pad schedule mode error. + Some more object refcounting debug info, + +2005-05-04 21:29:44 +0000 Andy Wingo + + GCC 4 fixen. + Original commit message from CVS: + 2005-05-04 Andy Wingo + * check/Makefile.am: + * docs/gst/tmpl/gstatomic.sgml: + * docs/gst/tmpl/gstplugin.sgml: + * gst/base/gstbasesink.c: (gst_basesink_activate): + * gst/base/gstbasesrc.c: (gst_basesrc_class_init), + (gst_basesrc_init), (gst_basesrc_set_dataflow_funcs), + (gst_basesrc_query), (gst_basesrc_set_property), + (gst_basesrc_get_property), (gst_basesrc_check_get_range), + (gst_basesrc_activate): + * gst/base/gstbasesrc.h: + * gst/base/gstbasetransform.c: (gst_base_transform_sink_activate), + (gst_base_transform_src_activate): + * gst/elements/gstelements.c: + * gst/elements/gstfakesrc.c: (gst_fakesrc_class_init), + (gst_fakesrc_set_property), (gst_fakesrc_get_property): + * gst/elements/gsttee.c: (gst_tee_sink_activate): + * gst/elements/gsttypefindelement.c: (find_element_get_length), + (gst_type_find_element_checkgetrange), + (gst_type_find_element_activate): + * gst/gstbin.c: (gst_bin_save_thyself), (gst_bin_restore_thyself): + * gst/gstcaps.c: (gst_caps_do_simplify), (gst_caps_save_thyself), + (gst_caps_load_thyself): + * gst/gstelement.c: (gst_element_pads_activate), + (gst_element_save_thyself), (gst_element_restore_thyself): + * gst/gstpad.c: (gst_pad_load_and_link), (gst_pad_save_thyself), + (gst_ghost_pad_save_thyself), (gst_pad_check_pull_range): + * gst/gstpad.h: + * gst/gstxml.c: (gst_xml_write), (gst_xml_parse_doc), + (gst_xml_parse_file), (gst_xml_parse_memory), + (gst_xml_get_element), (gst_xml_make_element): + * gst/indexers/gstfileindex.c: (gst_file_index_load), + (_file_index_id_save_xml), (gst_file_index_commit): + * gst/registries/gstlibxmlregistry.c: (read_string), (read_uint), + (read_enum), (load_pad_template), (load_feature), (load_plugin), + (load_paths): + * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_caps), + (gst_dp_packet_from_event), (gst_dp_caps_from_packet): + * tools/gst-complete.c: (main): + * tools/gst-compprep.c: (main): + * tools/gst-inspect.c: (print_element_properties_info): + * tools/gst-launch.c: (xmllaunch_parse_cmdline): + * tools/gst-xmlinspect.c: (print_element_properties): + GCC 4 fixen. + +2005-05-04 19:41:05 +0000 Christian Schaller + + * gstreamer.spec.in: + fix up spec file to work for 0.9 branch + Original commit message from CVS: + fix up spec file to work for 0.9 branch + +2005-05-03 12:46:47 +0000 Thomas Vander Stichele + + gst/gstplugin.c: apply patch from #172526 to make register work on MacOSX + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_check_module), + (gst_plugin_check_file), (gst_plugin_load_file): + apply patch from #172526 to make register work on MacOSX + +2005-05-02 16:50:31 +0000 Thomas Vander Stichele + + file .cvsignore was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file .cvsignore was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-05-02 15:31:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * tests/old/testsuite/indexers/cache1.c: + * tests/old/testsuite/indexers/indexdump.c: + * testsuite/indexers/cache1.c: + * testsuite/indexers/indexdump.c: + more print format fixes + Original commit message from CVS: + more print format fixes + +2005-05-02 15:20:30 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/gstconfig.h.in: + * tests/old/testsuite/debug/printf_extension.c: + * tests/old/testsuite/elements/property.h: + * testsuite/debug/printf_extension.c: + * testsuite/elements/property.h: + merges from 0.8 for 64 bit issues + Original commit message from CVS: + merges from 0.8 for 64 bit issues + +2005-05-02 13:55:21 +0000 Wim Taymans + + Added draft for new query API. + Original commit message from CVS: + * docs/design/draft-push-pull.txt: + * docs/design/draft-query.txt: + * gst/base/gstbasesrc.c: (gst_basesrc_get_range_unlocked), + (gst_basesrc_start): + Added draft for new query API. + Added draft for better selecting scheduling methods. + Make basesrc ignore length if the subclass does not support + it. + +2005-05-02 11:54:32 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/Makefile.am: + automake 1.5 fixes + Original commit message from CVS: + automake 1.5 fixes + +2005-05-02 11:47:17 +0000 Thomas Vander Stichele + + * ChangeLog: + * docs/faq/Makefile.am: + * docs/manual/Makefile.am: + * docs/manuals.mak: + * docs/pwg/Makefile.am: + * gst/Makefile.am: + possible fixes for automake-1.5 + Original commit message from CVS: + possible fixes for automake-1.5 + +2005-04-28 16:28:28 +0000 Wim Taymans + + gst/: Better debugging of clocking info. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_base_init), + (gst_basesink_pad_getcaps), (gst_basesink_init), + (gst_basesink_do_sync): + * gst/gstclock.c: (gst_clock_entry_new): + * gst/gstevent.c: (gst_event_discont_get_value): + * gst/gstpipeline.c: (pipeline_bus_handler), + (gst_pipeline_change_state): + * gst/gstsystemclock.c: (gst_system_clock_id_wait_unlocked): + Better debugging of clocking info. + Allow NULL values when getting discont values. + +2005-04-27 14:19:46 +0000 Wim Taymans + + check/gst/: Increase timeout for checks. + Original commit message from CVS: + * check/gst/gstobject.c: (START_TEST), (gst_object_suite): + * check/gst/gstpad.c: (gst_pad_suite): + Increase timeout for checks. + +2005-04-27 13:52:42 +0000 Thomas Vander Stichele + + check/Makefile.am: fix the broken rule for cleanup. Apparently this rule is only needed on FC2, so maybe this warran... + Original commit message from CVS: + * check/Makefile.am: + fix the broken rule for cleanup. Apparently this rule is + only needed on FC2, so maybe this warrants further autotool + inspection. + +2005-04-26 18:07:45 +0000 Wim Taymans + + gst/gsttrashstack.h: Ooohh. a nasty one! After having a failed pop() from the stack, it's possible that the stack is ... + Original commit message from CVS: + * gst/gsttrashstack.h: + Ooohh. a nasty one! After having a failed pop() from the stack, + it's possible that the stack is empty. In that case, don't + follow the NULL pointer. + +2005-04-25 13:00:47 +0000 Wim Taymans + + gst/: Remove gst_library_load as it does more harm than good with the new g_module flags. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_set_checkgetrange_function), + (gst_pad_link_check_compatible_unlocked), (gst_pad_link_prepare), + (gst_pad_check_pull_range), (gst_pad_pull_range), + (gst_static_pad_template_get_caps), (gst_pad_start_task), + (gst_pad_pause_task), (gst_pad_stop_task): + * gst/gstplugin.c: (gst_plugin_load): + * gst/gstplugin.h: + Remove gst_library_load as it does more harm than good with + the new g_module flags. + Revert bogus caps template check in pad linking, pad caps + are important when linking not the template, which is more + general than the current caps. + +2005-04-25 11:51:09 +0000 Thomas Vander Stichele + + * tests/Makefile.am: + there is no speed. really. + Original commit message from CVS: + there is no speed. really. + +2005-04-25 09:51:06 +0000 Ronald S. Bultje + + gst/autoplug/: Die, spider, die. + Original commit message from CVS: + * gst/autoplug/.cvsignore: + * gst/autoplug/Makefile.am: + * gst/autoplug/gstsearchfuncs.c: + * gst/autoplug/gstsearchfuncs.h: + * gst/autoplug/gstspider.c: + * gst/autoplug/gstspider.h: + * gst/autoplug/gstspideridentity.c: + * gst/autoplug/gstspideridentity.h: + * gst/autoplug/spidertest.c: + Die, spider, die. + +2005-04-25 09:45:35 +0000 Wim Taymans + + gst/gstpad.*: Added stubs for unimplemented functions. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_set_checkgetrange_function), (gst_pad_check_pull_range), + (gst_pad_pull_range), (gst_static_pad_template_get_caps), + (gst_pad_start_task), (gst_pad_pause_task), (gst_pad_stop_task): + * gst/gstpad.h: + Added stubs for unimplemented functions. + +2005-04-25 03:54:28 +0000 Jan Schmidt + + file python-elements.txt was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file python-elements.txt was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-04-24 23:53:06 +0000 David Schleef + + gst/gstpad.h: Disable some unimplemented functions. Wim, please fix. + Original commit message from CVS: + * gst/gstpad.h: Disable some unimplemented functions. Wim, + please fix. + +2005-04-24 22:49:45 +0000 David Schleef + + Convert everything from GstAtomicInt to g_atomic_int_*, and remove gstatomic. + Original commit message from CVS: + Convert everything from GstAtomicInt to g_atomic_int_*, and + remove gstatomic. + * gst/Makefile.am: + * gst/gstatomic.c: + * gst/gstatomic.h: + * gst/gstatomic_impl.h: + * gst/gstbuffer.c: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstdata.c: + * gst/gstdata.h: + * gst/gstdata_private.h: + * gst/gstevent.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstmessage.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstutils.c: Add gst_atomic_int_set() compaitibility function. + * gst/gstutils.h: + +2005-04-24 22:44:13 +0000 David Schleef + + check/gst/gstpad.c: Oh yeah, it's always nice to make the regressions tests work. Remove some code that is no longer... + Original commit message from CVS: + * check/gst/gstpad.c: (START_TEST): Oh yeah, it's always nice to + make the regressions tests work. Remove some code that is no + longer true. + * gst/gstpad.c: (gst_pad_link_check_templates_compatible_unlocked): + Disable warning for pads without templates. + +2005-04-24 21:16:45 +0000 David Schleef + + gst/gstpad.c: Remove handling of filtered caps. Fix/merge functions that handle filtered links. + Original commit message from CVS: + * gst/gstpad.c: Remove handling of filtered caps. Fix/merge + functions that handle filtered links. + * gst/gstpad.h: Remove 'appfilter' field and prototypes of + removed functions. + * gst/gstutils.c: Fix/remove utility functions that handle + filtered caps. + * gst/gstutils.h: + * gst/gstvalue.c: Add serialization/deserialization of caps + * gst/parse/grammar.y: Ignore filtered caps when linking. This + requires fixing so that the filter caps notation creates + a capsfilter element and sets the filter_caps property. I + think everyone probably wants to keep the shorthand notation. + * docs/gst/tmpl/gstelement.sgml: updates for API changes. + * docs/gst/tmpl/gstpad.sgml: + * gst/elements/gstelements.c: Register capsfilter element. + * gst/Makefile.am: fix spacing + * docs/random/ds/0.9-suggested-changes: random + +2005-04-23 23:29:47 +0000 David Schleef + + gst/elements/: New element that acts like an identity, but filters caps. Will eventually replace filtered caps in pa... + Original commit message from CVS: + * gst/elements/Makefile.am: + * gst/elements/gstcapsfilter.c: New element that acts like an + identity, but filters caps. Will eventually replace filtered + caps in pad linking. + * gst/gstutils.c: (gst_element_create_all_pads): New function + to create all the ALWAYS pads that are registered with an + element class. This functionality should eventually be + merged in with GstElement initialization. + * gst/gstutils.h: + * testsuite/trigger/README: part of trigger test code that should + have been checked in a long time ago. + +2005-04-23 23:25:08 +0000 David Schleef + + gst/Makefile.am: Remove as-libtool stuff. It's likely not and hard to carry around. + Original commit message from CVS: + * gst/Makefile.am: Remove as-libtool stuff. It's likely not + needed with new versions of libtool (nobody will confirm this), + and hard to carry around. + * gst/autoplug/Makefile.am: + * gst/base/Makefile.am: + * gst/elements/Makefile.am: + * gst/indexers/Makefile.am: + * gst/schedulers/Makefile.am: + * libs/gst/bytestream/Makefile.am: + * libs/gst/control/Makefile.am: + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/getbits/Makefile.am: + +2005-04-21 17:10:09 +0000 Stefan Kost + + file Makefile.am was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file Makefile.am was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-04-21 09:37:34 +0000 Wim Taymans + + docs/design/: Some more docs. + Original commit message from CVS: + * docs/design/draft-push-pull.txt: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-TODO.txt: + * docs/design/part-caps.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * docs/design/part-push-pull.txt: + * docs/design/part-query.txt: + Some more docs. + +2005-04-21 09:33:31 +0000 Wim Taymans + + gst/: Use parent refcount in GstMessage to ensure GstStructure consistency. + Original commit message from CVS: + * gst/gstmessage.c: (_gst_message_copy), (_gst_message_free), + (gst_message_new), (gst_message_new_error), + (gst_message_new_warning), (gst_message_new_tag), + (gst_message_new_state_changed), (gst_message_new_application), + (gst_message_get_structure): + * gst/gstmessage.h: + * gst/gststructure.c: (gst_structure_set_parent_refcount), + (gst_structure_copy_conditional): + Use parent refcount in GstMessage to ensure GstStructure + consistency. + Cleaned up headers a bit. + +2005-04-20 09:10:42 +0000 Wim Taymans + + gst/: Make gst_caps_replace() work like other _replace() functions. + Original commit message from CVS: + * gst/base/gstbasesink.c: (gst_basesink_base_init), + (gst_basesink_pad_getcaps), (gst_basesink_init), + (gst_basesink_chain_unlocked): + * gst/base/gsttypefindhelper.c: (helper_find_suggest), + (gst_type_find_helper): + * gst/elements/gsttypefindelement.c: + (gst_type_find_element_have_type), (gst_type_find_element_init), + (stop_typefinding), (gst_type_find_element_handle_event), + (find_suggest), (gst_type_find_element_chain), + (gst_type_find_element_checkgetrange), + (gst_type_find_element_getrange), (do_typefind), + (gst_type_find_element_activate): + * gst/gstbuffer.c: (_gst_buffer_sub_free), + (gst_buffer_default_free), (gst_buffer_default_copy), + (gst_buffer_set_caps): + * gst/gstcaps.c: (gst_caps_ref), (gst_caps_unref), + (gst_caps_replace): + * gst/gstmessage.c: (gst_message_new), + (gst_message_new_state_changed): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_set_checkgetrange_function), + (gst_pad_link_prepare_filtered), (gst_pad_relink_filtered), + (gst_pad_set_caps), (gst_pad_check_pull_range), + (gst_pad_pull_range), (gst_static_pad_template_get_caps): + * gst/gstpad.h: + * gst/gsttypefind.c: (gst_type_find_register): + Make gst_caps_replace() work like other _replace() functions. + Use _caps_replace() where possible. + Make sure _message_new() initialises its field. + Add gst_static_pad_template_get_caps() + +2005-04-18 08:53:02 +0000 Andy Wingo + + gst/elements/gstfakesrc.c: s/ARG_/PROP_/. + Original commit message from CVS: + 2005-04-18 Andy Wingo + * gst/elements/gstfakesrc.c: s/ARG_/PROP_/. + +2005-04-18 08:24:30 +0000 Andy Wingo + + * ChangeLog: + * gst/base/gstbasesrc.c: + * libs/gst/base/gstbasesrc.c: + gst/base/gstbasesrc.c (gst_basesrc_set_property) + Original commit message from CVS: + 2005-04-18 Andy Wingo + * gst/base/gstbasesrc.c (gst_basesrc_set_property) + (gst_basesrc_get_property): BLOCKSIZE is a ULONG. Rename ARG_... + to PROP_.... + +2005-04-16 20:27:55 +0000 Thomas Vander Stichele + + * NEWS: + * tests/Makefile.am: + NEWS build + Original commit message from CVS: + NEWS build + +2005-04-16 20:16:38 +0000 Thomas Vander Stichele + + removed some line + Original commit message from CVS: + removed some line + +2005-04-16 16:28:07 +0000 Thomas Vander Stichele + + * docs/faq/gst-uninstalled: + add gst-plugins-base to pkgconfig path + Original commit message from CVS: + add gst-plugins-base to pkgconfig path + +2005-04-14 17:17:30 +0000 Ronald S. Bultje + + docs/faq/using.xml: Add note on gstreamer-properties (#154996). + Original commit message from CVS: + * docs/faq/using.xml: + Add note on gstreamer-properties (#154996). + +2005-04-13 17:41:29 +0000 Ronald S. Bultje + + docs/random/bbb/optional-properties: Some analysis on optional properties. + Original commit message from CVS: + * docs/random/bbb/optional-properties: + Some analysis on optional properties. + +2005-04-12 15:00:30 +0000 Ronald S. Bultje + + Use libxml2 for registry parsing, use staticpadtemplates in elementfactories. Makes gst_init() +/- 10x faster. + Original commit message from CVS: + * docs/gst/tmpl/gstelementfactory.sgml: + * gst/gstelement.h: + * gst/gstelementfactory.c: (gst_element_factory_init), + (gst_element_factory_cleanup), (gst_element_register), + (__gst_element_factory_add_static_pad_template), + (gst_element_factory_get_static_pad_templates), + (gst_element_factory_can_src_caps), + (gst_element_factory_can_sink_caps): + * gst/registries/Makefile.am: + * gst/registries/gstlibxmlregistry.c: (gst_xml_registry_get_type), + (gst_xml_registry_class_init), (gst_xml_registry_init), + (gst_xml_registry_new), (gst_xml_registry_set_property), + (gst_xml_registry_get_property), (get_time), (make_dir), + (gst_xml_registry_get_perms_func), + (plugin_times_older_than_recurse), (plugin_times_older_than), + (gst_xml_registry_open_func), (gst_xml_registry_load_func), + (gst_xml_registry_save_func), (gst_xml_registry_close_func), + (add_to_char_array), (read_string), (read_uint), (read_enum), + (load_pad_template), (load_feature), (load_plugin), (load_paths), + (gst_xml_registry_load), (gst_xml_registry_load_plugin), + (gst_xml_registry_save_caps), (gst_xml_registry_save_pad_template), + (gst_xml_registry_save_feature), (gst_xml_registry_save_plugin), + (gst_xml_registry_save), (gst_xml_registry_rebuild_recurse), + (gst_xml_registry_rebuild): + * gst/registries/gstlibxmlregistry.h: + * tools/gst-compprep.c: (main): + * tools/gst-inspect.c: (print_pad_templates_info): + * tools/gst-xmlinspect.c: (print_element_info): + Use libxml2 for registry parsing, use staticpadtemplates in + elementfactories. Makes gst_init() +/- 10x faster. + +2005-04-12 10:52:55 +0000 Wim Taymans + + * ChangeLog: + * gst/base/Makefile.am: + * gst/base/gstbasesink.c: + * gst/base/gstbasesrc.c: + * gst/base/gsttypefindhelper.c: + * gst/base/gsttypefindhelper.h: + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: + * gst/elements/gsttypefindelement.c: + * gst/elements/gsttypefindelement.h: + * gst/gstpipeline.c: + * libs/gst/base/Makefile.am: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesrc.c: + * libs/gst/base/gsttypefindhelper.c: + * libs/gst/base/gsttypefindhelper.h: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gsttypefindelement.c: + * plugins/elements/gsttypefindelement.h: + Added typefind helper. + Original commit message from CVS: + Added typefind helper. + Small preroll fix in the base sink. + Disable typefind code in basesrc. + Crude port of typefindelement. + Fakesrc cleanups. + +2005-04-12 09:16:00 +0000 Wim Taymans + + * check/gst/gstdata.c: + * tests/check/gst/gstdata.c: + Increase timeout some more + Original commit message from CVS: + Increase timeout some more + +2005-04-11 12:02:13 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + only dirs + Original commit message from CVS: + only dirs + +2005-04-11 11:40:11 +0000 Thomas Vander Stichele + + * check/Makefile.am: + * tests/check/Makefile.am: + fix distcheck + Original commit message from CVS: + fix distcheck + +2005-04-11 11:24:53 +0000 Wim Taymans + + check/: Fix up the timeout so that the test does not fail. + Original commit message from CVS: + * check/gst/gstbus.c: (gstbus_suite): + * check/gst/gstdata.c: (thread_ref), (gst_data_suite): + * check/gstcheck.h: + Fix up the timeout so that the test does not fail. + +2005-04-11 09:53:44 +0000 Thomas Vander Stichele + + * tests/old/testsuite/Makefile.am: + * testsuite/Makefile.am: + dist trigger + Original commit message from CVS: + dist trigger + +2005-04-10 21:42:32 +0000 Thomas Vander Stichele + + * gst/gstelement.c: + work with debug disabled + Original commit message from CVS: + work with debug disabled + +2005-04-10 20:29:44 +0000 Thomas Vander Stichele + + * gst/gstobject.c: + work with debug disabled + Original commit message from CVS: + work with debug disabled + +2005-04-10 18:19:18 +0000 Thomas Vander Stichele + + * autogen.sh: + ignore already applied patch + Original commit message from CVS: + ignore already applied patch + +2005-04-08 11:34:14 +0000 Stefan Kost + + file gstparent.c was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file gstparent.c was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-04-08 11:34:14 +0000 Stefan Kost + + file gstparent.h was initially added on branch BRANCH-GSTREAMER-0_8. + Original commit message from CVS: + file gstparent.h was initially added on branch BRANCH-GSTREAMER-0_8. + +2005-04-06 17:30:48 +0000 Wim Taymans + + gst/: More work on the generic source base class, implement seeking, query. + Original commit message from CVS: + * gst/base/README: + * gst/base/gstbasesrc.c: (gst_basesrc_get_type), + (gst_basesrc_init), (gst_basesrc_get_formats), (gst_basesrc_query), + (gst_basesrc_get_event_mask), (gst_basesrc_do_seek), + (gst_basesrc_event_handler), (gst_basesrc_get_range_unlocked), + (gst_basesrc_check_get_range), (gst_basesrc_loop), + (gst_basesrc_unlock), (gst_basesrc_get_size), (gst_basesrc_start), + (gst_basesrc_stop), (gst_basesrc_activate), + (gst_basesrc_change_state), (basesrc_find_peek), + (basesrc_find_suggest), (gst_basesrc_type_find): + * gst/base/gstbasesrc.h: + * gst/elements/gstfilesrc.c: (gst_filesrc_base_init), + (gst_filesrc_class_init), (gst_filesrc_init), + (gst_filesrc_finalize), (gst_filesrc_set_location), + (gst_filesrc_set_property), (gst_filesrc_get_property), + (gst_filesrc_free_parent_mmap), (gst_filesrc_map_region), + (gst_filesrc_map_small_region), (gst_filesrc_create_mmap), + (gst_filesrc_create_read), (gst_filesrc_create), + (gst_filesrc_get_size), (gst_filesrc_start), (gst_filesrc_stop): + * gst/elements/gstfilesrc.h: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_lost_state), (gst_element_pads_activate): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_set_checkgetrange_function), (gst_pad_check_pull_range), + (gst_pad_pull_range): + * gst/gstpad.h: + More work on the generic source base class, implement seeking, + query. + Make filesrc extend the base source class. + Added gst_pad_set_checkgetrange_function to GstPad. + +2005-04-06 11:08:07 +0000 Andy Wingo + + pkgconfig/: New files. + Original commit message from CVS: + 2005-04-06 Andy Wingo + * pkgconfig/gstreamer-base.pc.in: + * pkgconfig/gstreamer-base-uninstalled.pc.in: New files. + * pkgconfig/Makefile.am: + * configure.ac (AC_OUTPUT): Add gstreamer-base pkgconfig files. + +2005-04-05 17:41:51 +0000 Thomas Vander Stichele + + * docs/faq/cvs.xml: + add a note + Original commit message from CVS: + add a note + +2005-04-05 08:44:20 +0000 Wim Taymans + + gst/: Made base source class, make fakesrc extend it. + Original commit message from CVS: + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstbasesink.c: (gst_basesink_base_init), + (gst_basesink_pad_getcaps), (gst_basesink_pad_setcaps), + (gst_basesink_pad_buffer_alloc), (gst_basesink_init), + (gst_basesink_do_sync), (gst_basesink_chain_unlocked): + * gst/base/gstbasesrc.c: (gst_basesrc_get_type), + (gst_basesrc_base_init), (gst_basesrc_class_init), + (gst_basesrc_init), (gst_basesrc_get_formats), + (gst_basesrc_get_query_types), (gst_basesrc_query), + (gst_basesrc_get_event_mask), (gst_basesrc_event_handler), + (gst_basesrc_set_property), (gst_basesrc_get_property), + (gst_basesrc_get_range_unlocked), (gst_basesrc_get_range), + (gst_basesrc_loop), (gst_basesrc_activate), + (gst_basesrc_change_state): + * gst/base/gstbasesrc.h: + * gst/elements/gstfakesrc.c: (gst_fakesrc_base_init), + (gst_fakesrc_class_init), (gst_fakesrc_init), + (gst_fakesrc_event_handler), (gst_fakesrc_set_property), + (gst_fakesrc_get_property), (gst_fakesrc_create): + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: (gst_filesrc_getrange), + (gst_filesrc_open_file), (gst_filesrc_loop), + (gst_filesrc_activate), (filesrc_find_peek), + (gst_filesrc_type_find): + Made base source class, make fakesrc extend it. + Add comments to basesink class. + Some filesrc cleanup. + +2005-04-01 10:14:45 +0000 Andy Wingo + + * tests/memchunk/gmemchunktest.c: + add support for google malloc if available + Original commit message from CVS: + add support for google malloc if available + +2005-04-01 02:41:35 +0000 David Schleef + + gst/gstplugin.c: Switch to using G_MODULE_BIND_LOCAL, which means plugins are now expected to link against libgstreamer. + Original commit message from CVS: + * gst/gstplugin.c: (gst_plugin_check_file), (gst_plugin_load_file): + Switch to using G_MODULE_BIND_LOCAL, which means plugins are now + expected to link against libgstreamer. + * gst/base/Makefile.am: link against libgstreamer + * gst/elements/Makefile.am: same + +2005-03-31 15:00:11 +0000 Andy Wingo + + tests/instantiate/: Add test to test speed of caps copy and free. + Original commit message from CVS: + 2005-03-31 Andy Wingo + * tests/instantiate/Makefile.am: + * tests/instantiate/caps.c: Add test to test speed of caps copy + and free. + * tests/memchunk/gmemchunktest.c (main): Use alloc only on the + GMemChunk to be fair. + * gst/gsttrashstack.h: Remove warning about using the fallback + trash stack implementation, it's still faster than malloc. + +2005-03-31 10:10:55 +0000 Wim Taymans + + gst/: Added start/stop methods to transform base class so subclasses don't need to deal with state changes even. + Original commit message from CVS: + * gst/base/gstbasetransform.c: (gst_base_transform_base_init), + (gst_base_transform_class_init), (gst_base_transform_init), + (gst_base_transform_setcaps), (gst_base_transform_handle_buffer), + (gst_base_transform_get_property), + (gst_base_transform_sink_activate), + (gst_base_transform_src_activate), + (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + * gst/elements/gstidentity.c: (gst_identity_class_init), + (gst_identity_event), (gst_identity_check_perfect), + (gst_identity_transform), (gst_identity_start), + (gst_identity_stop): + Added start/stop methods to transform base class so subclasses + don't need to deal with state changes even. + +2005-03-31 10:10:21 +0000 Andy Wingo + + * tests/memchunk/gmemchunktest.c: + add per-thread stats + Original commit message from CVS: + add per-thread stats + +2005-03-31 09:46:28 +0000 Wim Taymans + + gst/: Added rate to the discont event to prepare for variable speed and reverse playback. + Original commit message from CVS: + * gst/gstevent.c: (gst_event_new_discontinuous_valist), + (gst_event_new_discontinuous), (gst_event_discont_get_value): + * gst/gstevent.h: + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_pull_range): + Added rate to the discont event to prepare for variable speed + and reverse playback. + +2005-03-30 14:09:01 +0000 Andy Wingo + + * tests/memchunk/gmemchunktest.c: + Commit mem chunk test; probably will be removed later. + Original commit message from CVS: + Commit mem chunk test; probably will be removed later. + +2005-03-30 03:57:39 +0000 David Schleef + + A little example program to show how trigger-based elements can work. + Original commit message from CVS: + * configure.ac: + * testsuite/trigger/Makefile.am: + * testsuite/trigger/trigger.c: A little example program to show + how trigger-based elements can work. + +2005-03-29 16:18:12 +0000 Wim Taymans + + gst/: Simplify pad activation. + Original commit message from CVS: + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstbasesink.c: (gst_basesink_get_type), + (gst_basesink_base_init), (gst_basesink_class_init), + (gst_basesink_pad_getcaps), (gst_basesink_init), + (gst_basesink_activate), (gst_basesink_change_state): + * gst/base/gstbasesink.h: + * gst/base/gstbasetransform.c: (gst_base_transform_get_type), + (gst_base_transform_base_init), (gst_base_transform_finalize), + (gst_base_transform_class_init), (gst_base_transform_init), + (gst_base_transform_proxy_getcaps), (gst_base_transform_setcaps), + (gst_base_transform_event), (gst_base_transform_getrange), + (gst_base_transform_chain), (gst_base_transform_handle_buffer), + (gst_base_transform_set_property), + (gst_base_transform_get_property), + (gst_base_transform_sink_activate), + (gst_base_transform_src_activate), + (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + * gst/elements/gstidentity.c: (gst_identity_finalize), + (gst_identity_class_init), (gst_identity_init), + (gst_identity_event), (gst_identity_check_perfect), + (gst_identity_transform), (gst_identity_set_property), + (gst_identity_get_property), (gst_identity_change_state): + * gst/elements/gstidentity.h: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_lost_state), (gst_element_pads_activate): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_check_pull_range), (gst_pad_pull_range): + * gst/gstpad.h: + Simplify pad activation. + Added function to check if pull_range can be performed. + Error out when pulling inactive or flushing pads. + Removed const from refcounted types as it does not make sense. + Simplify pad templates in basesink + Added base class for simple 1-to-1 transforms. + Make identity subclass the base transform. + +2005-03-29 14:34:51 +0000 Andy Wingo + + docs/: Add these files to CVS. Now I really don't understand what's going on, but like whatever. I want green buildbot! + Original commit message from CVS: + 2005-03-29 Andy Wingo + * docs/libs/gstreamer-libs-overrides.txt: + * docs/gst/gstreamer-overrides.txt: Add these files to CVS. Now I + really don't understand what's going on, but like whatever. I want + green buildbot! + +2005-03-29 14:12:48 +0000 Andy Wingo + + docs/: Dist the overrides files. + Original commit message from CVS: + 2005-03-29 Andy Wingo + * docs/gst/Makefile.am: + * docs/libs/Makefile.am: Dist the overrides files. + * check/Makefile.am (clean-local): Remove .libs directories. + * gst/elements/Makefile.am (EXTRA_DIST): Add all the attic + elements to EXTRA_DIST, so po/ files are happy. + +2005-03-29 13:10:25 +0000 Andy Wingo + + po/POTFILES: Remove gstspider.c. + Original commit message from CVS: + 2005-03-29 Andy Wingo + * po/POTFILES: Remove gstspider.c. + * configure.ac (AC_OUTPUT): Add missing testsuite makefiles. + * docs/libs/gstreamer-libs-docs.sgml: + * docs/libs/gstreamer-libs-sections.txt: Remove the section on + bytestream. + * tests/complexity.c (main): Set the length of the preroll queue + on the sinks to prevent a lockup. + +2005-03-29 11:39:17 +0000 Andy Wingo + + libs/gst/dataprotocol/: Remove test, it's the same as the one in check/gst-libs/gdp.c. + Original commit message from CVS: + 2005-03-29 Andy Wingo + * libs/gst/dataprotocol/Makefile.am: + * libs/gst/dataprotocol/dataprotocol-test.c: Remove test, it's + the same as the one in check/gst-libs/gdp.c. + +2005-03-29 10:55:39 +0000 Andy Wingo + + po/, docs/gst/: Commit automatic changes to docs and po files. + Original commit message from CVS: + 2005-03-29 Andy Wingo + * po/, docs/gst/: Commit automatic changes to docs and po files. + * gst/elements/Makefile.am (libgstelements_la_LDFLAGS): Link to + the versioned libgstbase. + * check/Makefile.am: Depend on an unversioned gst-register, seems + to make autoconf happier. + * gst/base/Makefile.am: Make libgstbase a versioned lib. + +2005-03-28 14:54:33 +0000 Wim Taymans + + * ChangeLog: + * configure.ac: + * docs/design/part-gstelement.txt: + * docs/design/part-negotiation.txt: + * docs/design/part-preroll.txt: + * docs/design/part-scheduling.txt: + * docs/design/part-states.txt: + * gst/Makefile.am: + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstbasesink.c: + * gst/base/gstbasesink.h: + * gst/elements/Makefile.am: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesink.h: + * gst/gstbin.c: + * gst/gstelement.c: + * gst/gstpad.c: + * gst/gstpipeline.c: + * libs/gst/base/Makefile.am: + * libs/gst/base/README: + * libs/gst/base/gstbasesink.c: + * libs/gst/base/gstbasesink.h: + * plugins/elements/Makefile.am: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesink.h: + Added state change code. + Original commit message from CVS: + Added state change code. + Added/updated docs. + Added sink base class, make fakesink extend the base class. + Small cleanups in GstPipeline. + +2005-03-26 22:07:53 +0000 David Schleef + + gst/Makefile.am: remove gstcpu.[ch]. The gst_cpu functionality is broken and should be implemented in a different li... + Original commit message from CVS: + * gst/Makefile.am: remove gstcpu.[ch]. The gst_cpu functionality + is broken and should be implemented in a different library. + * gst/gst.c: (init_post): don't call _gst_cpu_initialize() + * gst/gst.h: remove gstcpu.h + * gst/gstcpu.c: remove + * gst/gstcpu.h: remove + * gst/Makefile.am.future: Remove this file. It's ancient. + +2005-03-25 09:57:42 +0000 Ronald S. Bultje + + gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu... + Original commit message from CVS: + * gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager), + (gst_bin_send_event): + Add default event/set_manager handlers. The set_manager handler + takes care that the manager is distributed over kids that were + already in the bin before the manager was set. The event handler + is a utility virtual function that sends the event over all sinks, + so that gst_element_send_event (bin, event); has the expected + behaviour. + * gst/gstpad.c: (gst_pad_event_default): + Re-install default event handling for discontinuities, so that + seeking works without requiring hacks in applications or extra + code in sinks. + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_send_event): + Half hack, half utility: set a pipeline to PAUSED for seek events, + since that is the only way we can guarantee a/v sync. Means that + you can do gst_element_seek (pipeline, method, pos); on a pipeline + and it "just works". + +2005-03-25 09:35:01 +0000 Ronald S. Bultje + + gst/gstpipeline.c: Lock/unlock mismatch. + Original commit message from CVS: + * gst/gstpipeline.c: (gst_pipeline_use_clock): + Lock/unlock mismatch. + +2005-03-25 00:35:44 +0000 Thomas Vander Stichele + + docs/faq/gst-uninstalled: add gst-plugins-base + Original commit message from CVS: + * docs/faq/gst-uninstalled: + add gst-plugins-base + * docs/gst/Makefile.am: + don't error out until docs are fixed + * docs/gst/gstreamer.types: + remove thread + +2005-03-22 14:23:49 +0000 Wim Taymans + + Activated more tests. + Original commit message from CVS: + * check/Makefile.am: + * check/gst/gstmessage.c: (START_TEST), (gst_data_suite), (main): + * gst/gststructure.c: (gst_structure_set_valist), + (gst_structure_copy_conditional): + Activated more tests. + Added message test. + Added G_TYPE_POINTER to GstStructure. + +2005-03-22 11:32:59 +0000 Wim Taymans + + Docs updates + Original commit message from CVS: + * docs/design/part-TODO.txt: + * docs/design/part-events.txt: + * docs/design/part-gstbin.txt: + * docs/design/part-gstbus.txt: + * docs/design/part-gstpipeline.txt: + * docs/design/part-messages.txt: + * gst/gstbus.c: + * gst/gstmessage.c: + Docs updates + +2005-03-21 18:17:57 +0000 Wim Taymans + + gst/gstbus.c: Fix copy-and-paste error. + Original commit message from CVS: + * gst/gstbus.c: (gst_bus_post): + Fix copy-and-paste error. + +2005-03-21 17:34:02 +0000 Wim Taymans + + * ChangeLog: + * check/Makefile.am: + * common: + * gst/Makefile.am: + * gst/elements/Makefile.am: + * gst/elements/gstelements.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfakesrc.h: + * gst/elements/gstfilesrc.c: + * gst/elements/gstidentity.c: + * gst/elements/gstidentity.h: + * gst/elements/gsttee.c: + * gst/elements/gsttee.h: + * gst/gst.c: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstbus.c: + * gst/gstbus.h: + * gst/gstcaps.h: + * gst/gstdata.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstevent.c: + * gst/gstevent.h: + * gst/gstmessage.c: + * gst/gstmessage.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstprobe.h: + * gst/gstqueue.c: + * gst/gstqueue.h: + * gst/gstscheduler.c: + * gst/gstscheduler.h: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gsttaginterface.h: + * gst/gsttagsetter.h: + * gst/gsttask.c: + * gst/gsttask.h: + * gst/gstthread.c: + * gst/gstthread.h: + * gst/gsttypes.h: + * gst/schedulers/Makefile.am: + * gst/schedulers/cothreads_compat.h: + * gst/schedulers/entryscheduler.c: + * gst/schedulers/faircothreads.c: + * gst/schedulers/faircothreads.h: + * gst/schedulers/fairscheduler.c: + * gst/schedulers/gstbasicscheduler.c: + * gst/schedulers/gstoptimalscheduler.c: + * gst/schedulers/gthread-cothreads.h: + * gst/schedulers/threadscheduler.c: + * libs/gst/Makefile.am: + * libs/gst/bytestream/bytestream.c: + * libs/gst/bytestream/filepad.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/Makefile.am: + * plugins/elements/gstelements.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfakesrc.h: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstidentity.h: + * plugins/elements/gstqueue.c: + * plugins/elements/gstqueue.h: + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + * tests/benchmarks/complexity.c: + * tests/benchmarks/mass-elements.c: + * tests/check/Makefile.am: + * tests/complexity.c: + * tests/mass_elements.c: + * tests/old/testsuite/states/locked.c: + * tests/old/testsuite/states/parent.c: + * testsuite/states/locked.c: + * testsuite/states/parent.c: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-md5sum.c: + * tools/gst-typefind.c: + * tools/gst-xmlinspect.c: + Next big merge. + Original commit message from CVS: + Next big merge. + Added GstBus for mainloop integration. + Added GstMessage for sending notifications on the bus. + Added GstTask as an abstraction for pipeline entry points. + Removed GstThread. + Removed Schedulers. + Simplified GstQueue for multithreaded core. + Made _link threadsafe, removed old capsnego. + Added STREAM_LOCK and PREROLL_LOCK in GstPad. + Added pad blocking functions. + Reworked scheduling functions in GstPad to prepare for + scheduling updates soon. + Moved events out of data stream. + Simplified GstEvent types. + Added return values to push/pull. + Removed clocking from GstElement. + Added prototypes for state change function for next merge. + Removed iterate from bins and state change management. + Fixed some elements, disabled others for now. + Fixed -inspect and -launch. + Added check for GstBus. + +2005-03-10 12:51:45 +0000 Wim Taymans + + Doc updates. + Original commit message from CVS: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-clocks.txt: + * docs/design/part-gstelement.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-standards.txt: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_add), + (gst_bin_remove_func), (gst_bin_remove): + * gst/gstbin.h: + * gst/gstbuffer.c: + * gst/gstcaps.h: + * testsuite/clock/clock1.c: (main): + * testsuite/clock/clock2.c: (gst_clock_debug), (element_wait), + (main): + * testsuite/dlopen/loadgst.c: (do_test): + * testsuite/refcounting/bin.c: (add_remove_test1), + (add_remove_test2), (main): + * testsuite/refcounting/element.c: (main): + * testsuite/refcounting/element_pad.c: (main): + * testsuite/refcounting/pad.c: (main): + * tools/gst-launch.c: (sigint_handler_sighandler): + * tools/gst-typefind.c: (main): + Doc updates. + Added doc about clock. + removed gst_bin_iterate_recurse_up(), marked methods + for removal. + Fix more testsuites. + +2005-03-09 17:28:52 +0000 Wim Taymans + + Fix _pad_get_direction wrt ghostpads. + Original commit message from CVS: + * gst/gstpad.c: (gst_pad_get_direction), + (_gst_pad_default_fixate_foreach), (gst_pad_collectv), + (gst_pad_collect_valist): + * testsuite/bins/interface.c: (main): + * testsuite/caps/audioscale.c: (test_caps): + * testsuite/caps/caps.c: (test1), (test2), (test3): + * testsuite/caps/deserialize.c: (main): + * testsuite/caps/enumcaps.c: (main): + * testsuite/caps/filtercaps.c: (main): + * testsuite/caps/intersect2.c: (main): + * testsuite/caps/random.c: (main): + * testsuite/caps/renegotiate.c: (my_fixate), (main): + * testsuite/caps/sets.c: (check_caps): + * testsuite/caps/simplify.c: (check_caps), (main): + * testsuite/caps/subtract.c: (check_caps): + Fix _pad_get_direction wrt ghostpads. + Fix caps testsuite. + +2005-03-09 16:10:59 +0000 Wim Taymans + + * ChangeLog: + * check/Makefile.am: + * check/gst/gstbin.c: + * check/gst/gstsystemclock.c: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstiterator.c: + * gst/gstpad.c: + * gst/gstpipeline.c: + * gst/gstutils.h: + * gst/schedulers/entryscheduler.c: + * gst/schedulers/gstbasicscheduler.c: + * tests/check/Makefile.am: + * tests/check/gst/gstbin.c: + * tests/check/gst/gstsystemclock.c: + * tests/old/testsuite/bins/interface.c: + * testsuite/bins/interface.c: + Added GstBin test. + Original commit message from CVS: + Added GstBin test. + Added GstSystemClock test. + Implemented clock distribution code in GstBin. + Implemented iterate sinks method for future use. + Rearranged gstelement.h + Fix GstIterator comparison bug. + Moved some code to GstPipeline, mostly clocking related. + +2005-03-09 11:08:18 +0000 Wim Taymans + + Bump version number, we're now 0.9.0 + Original commit message from CVS: + * configure.ac: + * gst/gst_private.h: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_add), + (gst_bin_remove_func), (gst_bin_remove), + (gst_bin_get_by_name_recurse_up): + * gst/gstclock.c: (gst_clock_id_ref), (gst_clock_id_unref), + (gst_clock_id_compare_func), (gst_clock_id_wait), + (gst_clock_id_wait_async), (gst_clock_init), + (gst_clock_adjust_unlocked), (gst_clock_get_time): + * gst/gstelement.h: + * gst/gstinfo.c: (_gst_debug_init): + * gst/gstobject.h: + * gst/gstpad.c: (_gst_pad_default_fixate_foreach), + (gst_pad_collectv), (gst_pad_collect_valist), (gst_pad_query): + * gst/gstpad.h: + Bump version number, we're now 0.9.0 + Add future debugging category. + Fix NULL _unref() in _get_by_name_recurse_up + Rearrange gstpad.h. + Update some docs. + +2005-03-08 17:42:29 +0000 Wim Taymans + + * ChangeLog: + * gst/elements/gstaggregator.c: + * gst/elements/gstfakesink.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstfdsink.c: + * gst/elements/gstfdsrc.c: + * gst/elements/gstfilesink.c: + * gst/elements/gstfilesrc.c: + * gst/elements/gstidentity.c: + * gst/elements/gstmd5sink.c: + * gst/elements/gstmultifilesrc.c: + * gst/elements/gstshaper.c: + * gst/elements/gststatistics.c: + * gst/elements/gsttee.c: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstqueue.c: + * gst/gstthread.c: + * gst/schedulers/gstbasicscheduler.c: + * gst/schedulers/gstoptimalscheduler.c: + * plugins/elements/gstaggregator.c: + * plugins/elements/gstfakesink.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstfdsink.c: + * plugins/elements/gstfdsrc.c: + * plugins/elements/gstfilesink.c: + * plugins/elements/gstfilesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstmd5sink.c: + * plugins/elements/gstmultifilesrc.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gstshaper.c: + * plugins/elements/gststatistics.c: + * plugins/elements/gsttee.c: + Remove threadsafe properties. Fix elements because GObject complains when installing a property before declaring a se... + Original commit message from CVS: + Remove threadsafe properties. Fix elements because GObject + complains when installing a property before declaring a + set/get_property handler. + Rearrange gstelement.h file, use STATE macros for state locks. + Free mutexes in the finalize method instead of dispose. + +2005-03-08 15:57:15 +0000 Wim Taymans + + Added parentage check. + Original commit message from CVS: + * check/gst/gstobject.c: (START_TEST), (gst_object_suite): + * gst/gstthread.c: (gst_thread_release_children_locks): + Added parentage check. + Fix build og GstThread again. + +2005-03-08 14:38:06 +0000 Wim Taymans + + Docs updates, clean up some headers. + Original commit message from CVS: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-conventions.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-relations.txt: + * docs/design/part-standards.txt: + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_add), + (gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse), + (gst_bin_get_by_name), (gst_bin_get_by_interface), + (gst_bin_iterate_all_by_interface): + * gst/gstbuffer.h: + * gst/gstclock.h: + * gst/gstelement.c: (gst_element_class_init), + (gst_element_change_state), (gst_element_set_loop_function): + * gst/gstelement.h: + * gst/gstiterator.c: + * gst/gstobject.c: (gst_object_class_init), (gst_object_ref), + (gst_object_unref), (gst_object_sink), (gst_object_dispose), + (gst_object_dispatch_properties_changed), (gst_object_set_name), + (gst_object_set_parent), (gst_object_unparent), + (gst_object_check_uniqueness): + * gst/gstobject.h: + Docs updates, clean up some headers. + Free iterators in GstBin. + GstObject is now looking good. + +2005-03-07 18:33:37 +0000 Wim Taymans + + check/: Added checks. + Original commit message from CVS: + * check/.cvsignore: + * check/Makefile.am: + * check/gst-libs/.cvsignore: + * check/gst-libs/gdp.c: (START_TEST), (gst_object_suite), (main): + * check/gst/.cvsignore: + * check/gst/gstbus.c: (pound_bus_with_messages), (pull_messages), + (START_TEST), (gstbus_suite), (main): + * check/gst/gstcaps.c: (START_TEST), (gst_caps_suite), (main): + * check/gst/gstdata.c: (START_TEST), (thread_ref), (thread_unref), + (gst_data_suite), (main): + * check/gst/gstiterator.c: (make_list_of_ints), (START_TEST), + (add_fold_func), (gstiterator_suite), (main): + * check/gst/gstobject.c: (gst_fake_object_get_type), (START_TEST), + (thread_name_object), (thread_name_object_default), + (gst_object_name_compare), (gst_object_suite), (main): + * check/gst/gstpad.c: (START_TEST), (thread_link_unlink), + (gst_pad_suite), (main): + * check/gstcheck.c: (gst_check_log_message_func), + (gst_check_log_critical_func), (gst_check_init): + * check/gstcheck.h: + * check/pipelines/simple_launch_lines.c: (setup_pipeline), + (run_pipeline), (START_TEST), (simple_launch_lines_suite), (main): + Added checks. + +2005-03-07 18:29:36 +0000 Wim Taymans + + gst/gstiterator.*: Added missing files. + Original commit message from CVS: + * gst/gstiterator.c: (gst_iterator_init), (gst_iterator_new), + (gst_list_iterator_next), (gst_list_iterator_resync), + (gst_list_iterator_free), (gst_iterator_new_list), + (gst_iterator_pop), (gst_iterator_next), (gst_iterator_resync), + (gst_iterator_free), (gst_iterator_push), (filter_next), + (filter_resync), (filter_uninit), (filter_free), + (gst_iterator_filter), (gst_iterator_fold), (foreach_fold_func), + (gst_iterator_foreach), (find_custom_fold_func), + (gst_iterator_find_custom): + * gst/gstiterator.h: + Added missing files. + +2005-03-07 18:27:42 +0000 Wim Taymans + + * ChangeLog: + * Makefile.am: + * configure.ac: + * docs/design/part-MT-refcounting.txt: + * docs/design/part-conventions.txt: + * docs/design/part-gstobject.txt: + * docs/design/part-relations.txt: + * examples/mixer/mixer.c: + * examples/thread/thread.c: + * gst/Makefile.am: + * gst/autoplug/gstsearchfuncs.c: + * gst/autoplug/gstspider.c: + * gst/autoplug/gstspideridentity.c: + * gst/elements/gstfakesrc.c: + * gst/elements/gstidentity.c: + * gst/elements/gsttee.c: + * gst/elements/gsttypefindelement.c: + * gst/gst.c: + * gst/gst.h: + * gst/gstbin.c: + * gst/gstbin.h: + * gst/gstbuffer.c: + * gst/gstbuffer.h: + * gst/gstcaps.c: + * gst/gstcaps.h: + * gst/gstclock.c: + * gst/gstclock.h: + * gst/gstcompat.h: + * gst/gstcpu.c: + * gst/gstdata.c: + * gst/gstdata.h: + * gst/gstelement.c: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstformat.c: + * gst/gstformat.h: + * gst/gstindex.c: + * gst/gstinfo.c: + * gst/gstinfo.h: + * gst/gstmemchunk.c: + * gst/gstobject.c: + * gst/gstobject.h: + * gst/gstpad.c: + * gst/gstpad.h: + * gst/gstpipeline.c: + * gst/gstpipeline.h: + * gst/gstplugin.c: + * gst/gstpluginfeature.c: + * gst/gstpluginfeature.h: + * gst/gstprobe.c: + * gst/gstquery.c: + * gst/gstquery.h: + * gst/gstqueue.c: + * gst/gstscheduler.c: + * gst/gststructure.c: + * gst/gststructure.h: + * gst/gstsystemclock.c: + * gst/gstsystemclock.h: + * gst/gsttag.c: + * gst/gsttaginterface.c: + * gst/gsttaglist.c: + * gst/gsttagsetter.c: + * gst/gstthread.c: + * gst/gsttrashstack.h: + * gst/gsttypefind.c: + * gst/gsttypes.h: + * gst/gstutils.c: + * gst/gstutils.h: + * gst/gstvalue.c: + * gst/parse/grammar.y: + * gst/schedulers/gstbasicscheduler.c: + * gst/schedulers/gstoptimalscheduler.c: + * libs/gst/bytestream/bytestream.c: + * libs/gst/dataprotocol/dataprotocol.c: + * plugins/elements/gstfakesrc.c: + * plugins/elements/gstidentity.c: + * plugins/elements/gstqueue.c: + * plugins/elements/gsttee.c: + * plugins/elements/gsttypefindelement.c: + * po/nb.po: + * po/ru.po: + * tests/old/examples/mixer/mixer.c: + * tests/old/examples/thread/thread.c: + * tests/threadstate/threadstate2.c: + * tools/gst-compprep.c: + * tools/gst-inspect.c: + * tools/gst-launch.c: + * tools/gst-md5sum.c: + * tools/gst-xmlinspect.c: + First THREADED backport attempt, focusing on adding locks and making sure the API is threadsafe. Needs more work. Mor... + Original commit message from CVS: + First THREADED backport attempt, focusing on adding locks and + making sure the API is threadsafe. Needs more work. More docs + follow this week. + +2005-02-25 00:10:05 +0000 Thomas Vander Stichele + + * gst/gstinfo.c: + * gst/gstinfo.h: + another no-debug build fix + Original commit message from CVS: + another no-debug build fix + +2005-02-24 23:41:57 +0000 Thomas Vander Stichele + + * gst/schedulers/faircothreads.c: + disable debug build fix + Original commit message from CVS: + disable debug build fix + +2005-02-24 17:12:19 +0000 Andy Wingo + + tests/: New files, good for running complexity benchmarks. + Original commit message from CVS: + 2005-02-24 Andy Wingo + * tests/bench-complexity.scm: + * tests/complexity.gnuplot: New files, good for running complexity + benchmarks. + +2005-02-24 15:36:22 +0000 Andy Wingo + + tests/: New test, sets up N elements, at each level teeing into M streams per element. Eeeenteresting. + Original commit message from CVS: + 2005-02-24 Andy Wingo + * tests/Makefile.am: + * tests/complexity.c: New test, sets up N elements, at each level + teeing into M streams per element. Eeeenteresting. + +2005-02-24 12:31:12 +0000 Andy Wingo + + tests/mass_elements.gnuplot: gnuplot file for the mass_elements benchmark. Run as gnuplot mass_elements.gnuplot > foo... + Original commit message from CVS: + 2005-02-24 Andy Wingo + * tests/mass_elements.gnuplot: gnuplot file for the mass_elements + benchmark. Run as gnuplot mass_elements.gnuplot > foo.ps, after + running bench-mass_elements.scm. + * tests/bench-mass_elements.scm: New script, runs mass_elements + for various numbers of identities, outputting the results to a + file. Requires guile 1.6. Just for testing. + +2005-02-23 15:14:01 +0000 Thomas Vander Stichele + + * gst/schedulers/fairscheduler.c: + one more fix + Original commit message from CVS: + one more fix + +2005-02-23 15:06:36 +0000 Thomas Vander Stichele + + * ChangeLog: + * gst/schedulers/fairscheduler.c: + compile with debug disabled + Original commit message from CVS: + compile with debug disabled + +2005-02-22 16:34:10 +0000 Thomas Vander Stichele + + * ChangeLog: + * configure.ac: + hunting season on 0.9 is now OPEN + Original commit message from CVS: + hunting season on 0.9 is now OPEN + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..8865734 --- /dev/null +++ b/INSTALL @@ -0,0 +1,368 @@ +Installation Instructions +************************* + + Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software +Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell command './configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the 'README' file for +instructions specific to this package. Some packages provide this +'INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + 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, and a +file 'config.log' containing compiler output (useful mainly for +debugging 'configure'). + + It can also use an optional file (typically called 'config.cache' and +enabled with '--cache-file=config.cache' or simply '-C') that saves the +results of its tests to speed up reconfiguring. Caching is disabled by +default to prevent problems with accidental use of stale cache files. + + 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 you are using the cache, and at +some point 'config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file 'configure.ac' (or 'configure.in') is used to create +'configure' by a program called 'autoconf'. You need 'configure.ac' 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. + + Running 'configure' might take a while. 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, generally using the just-built uninstalled binaries. + + 4. Type 'make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the 'make install' phase executed with root + privileges. + + 5. Optionally, type 'make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior 'make install' required + root privileges, verifies that the installation completed + correctly. + + 6. 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. + + 7. Often, you can also type 'make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide 'make + distcheck', which can by used by developers to test that all other + targets like 'make install' and 'make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the 'configure' script does not know about. Run './configure --help' +for details on some of the pertinent environment variables. + + You can give 'configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here is +an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +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 can use 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 '..'. This is known +as a "VPATH" build. + + With a non-GNU 'make', it is safer 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. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple '-arch' options to the +compiler but only a single '-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the 'lipo' tool if you have problems. + +Installation Names +================== + + By default, 'make install' installs the package's commands under +'/usr/local/bin', include files under '/usr/local/include', etc. You +can specify an installation prefix other than '/usr/local' by giving +'configure' the option '--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option '--exec-prefix=PREFIX' to 'configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like '--bindir=DIR' 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. In general, the default +for these options is expressed in terms of '${prefix}', so that +specifying just '--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to 'configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +'make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, 'make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +'${prefix}'. Any directories that were specified during 'configure', +but not in terms of '${prefix}', must each be overridden at install time +for the entire installation to be relocated. The approach of makefile +variable overrides for each directory variable is required by the GNU +Coding Standards, and ideally causes no recompilation. However, some +platforms have known limitations with the semantics of shared libraries +that end up requiring recompilation when using this method, particularly +noticeable in packages that use GNU Libtool. + + The second method involves providing the 'DESTDIR' variable. For +example, 'make install DESTDIR=/alternate/directory' will prepend +'/alternate/directory' before all installation names. The approach of +'DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of '${prefix}' +at 'configure' time. + +Optional Features +================= + + 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'. + + 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. + + Some packages offer the ability to configure how verbose the +execution of 'make' will be. For these packages, running './configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with 'make V=1'; while running './configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with 'make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC +is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX 'make' updates targets which have the same time stamps as their +prerequisites, which makes it generally unusable when shipped generated +files such as 'configure' are involved. Use GNU 'make' instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its '' header file. The option '-nodtk' can be used as a +workaround. If GNU CC is not installed, it is therefore recommended to +try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put '/usr/ucb' early in your 'PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in '/usr/bin'. So, if you need '/usr/ucb' +in your 'PATH', put it _after_ '/usr/bin'. + + On Haiku, software installed for all users goes in '/boot/common', +not '/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features 'configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, 'configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +'--build=TYPE' option. TYPE can either be a short name for the system +type, such as 'sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + 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 machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option '--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with '--host=TYPE'. + +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. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to 'configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the 'configure' command line, using 'VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified 'gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an +Autoconf limitation. Until the limitation is lifted, you can use this +workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +'configure' Invocation +====================== + + 'configure' recognizes the following options to control how it +operates. + +'--help' +'-h' + Print a summary of all of the options to 'configure', and exit. + +'--help=short' +'--help=recursive' + Print a summary of the options unique to this package's + 'configure', and exit. The 'short' variant lists options used only + in the top level, while the 'recursive' variant lists options also + present in any nested packages. + +'--version' +'-V' + Print the version of Autoconf used to generate the 'configure' + script, and exit. + +'--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally 'config.cache'. FILE defaults to '/dev/null' to + disable caching. + +'--config-cache' +'-C' + Alias for '--cache-file=config.cache'. + +'--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. + +'--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: for + more details, including other options available for fine-tuning the + installation locations. + +'--no-create' +'-n' + Run the configure checks, but stop before creating any output + files. + +'configure' also accepts some other, not widely useful, options. Run +'configure --help' for more details. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..72aac8e --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,12 @@ +GStreamer is currently maintained by the consensus of a number +of people, including, but not limited to: + + Jan Schmidt + Wim Taymans + David Schleef + Tim-Philipp Müller + Sebastian Dröge + +Maintainer-related issues should be addressed to: + + gstreamer-devel@lists.freedesktop.org diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..de057c4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,206 @@ +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc + +# note: keep in sync with configure.ac +ACLOCAL_AMFLAGS = -I m4 -I common/m4 + +aclocaldir = $(datadir)/aclocal +aclocal_DATA = gst-element-check-1.0.m4 + +SUBDIRS = pkgconfig \ + gst libs plugins tests \ + docs \ + po \ + m4 \ + common \ + data + +if BUILD_TOOLS +SUBDIRS += tools +endif + +# These are all the possible subdirs +DIST_SUBDIRS = pkgconfig \ + gst libs plugins tools tests \ + docs \ + po \ + m4 \ + common \ + data + +# include before EXTRA_DIST for win32 assignment +include $(top_srcdir)/common/win32.mak + +EXTRA_DIST = \ + gst-element-check-1.0.m4 \ + configure.ac autogen.sh depcomp \ + MAINTAINERS ABOUT-NLS RELEASE gstreamer.doap \ + scripts/gst-uninstalled \ + $(shell find "$(top_srcdir)" -type f -name meson.build ! -path "$(top_srcdir)/gstreamer-*" ) \ + gst/gstenumtypes.c.template gst/gstenumtypes.h.template \ + libs/gst/controller/controller_mkenum.py \ + meson_options.txt \ + gst/parse/gen_lex.py.in gst/parse/gen_grammar.py.in \ + $(win32) + +DISTCLEANFILES = _stdint.h + +include $(top_srcdir)/common/release.mak +include $(top_srcdir)/common/po.mak + +if GST_GCOV_ENABLED +clean-gcov: + find -name "*.da" -o -name "*.gcov" | xargs rm || true + +clean-bbg: + find -name "*.bbg" -o -name "*.bb" | xargs rm || true + +GCOV_DIRS=gst libs + +## .PHONY so it always rebuilds it +.PHONY: coverage-report.txt + +coverage-report.txt: + BBG_FILES=`find $(GCOV_DIRS) -name "*.bbg"` ; \ + C_FILES= ; \ + for F in $$BBG_FILES ; do \ + F_nolibs=`echo $$F | sed -e 's/.libs\///g'` ; \ + C=`echo $$F_nolibs | sed -e 's/.bbg/.c/g'` ; \ + B=`basename $$F .bbg` ; \ + D=`dirname $$F` ; \ + DA=`echo $$F | sed -e 's/.bbg/.da/g'` ; \ + DA_libs=`echo $$D/.libs/$$B/.da` ; \ + if test -e $$DA || test -e $$DA_libs; then \ + C_FILES="$$C_FILES $$C" ; \ + fi ; \ + done ; \ + echo $$C_FILES ; \ + $(top_builddir)/testsuite/decode-gcov --report $$C_FILES > coverage-report.txt + +check-coverage: clean-gcov all check coverage-report.txt + cat coverage-report.txt + +else +coverage-report.txt: + echo "Need to reconfigure with --enable-gcov" + +check-coverage: + echo "Need to reconfigure with --enable-gcov" +endif + +if HAVE_CHECK +check-valgrind: + $(MAKE) -C tests/check check-valgrind + +check-torture: + $(MAKE) -C tests/check torture + +build-checks: + $(MAKE) -C tests/check build-checks +else +check-valgrind: + echo "'check' library not installed, skipping" + +check-torture: + echo "'check' library not installed, skipping" + +build-checks: + echo "'check' library not installed, skipping" +endif + +check-enum-gettypes: $(top_builddir)/gst/gstenumtypes.h + @echo 'Checking if all enum and flag _get_type() funcs are inited in gst_init()'; \ + FUNCS=`grep '_get_type (' gst/gstenumtypes.h | sed -e 's/^.*gst_/gst_/' -e 's/_get_type.*$$/_get_type/'`;\ + MISSING_FUNCS=''; \ + for f in $$FUNCS; do \ + INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_ref`; \ + if test "x$$INIT_LINE" = "x"; then \ + MISSING_FUNCS="$$MISSING_FUNCS $$f"; \ + fi; \ + done; \ + if test "x$$MISSING_FUNCS" != "x"; then \ + echo "FIXME: please add to the following to gst/gst.c init_post():"; \ + for f in $$MISSING_FUNCS; do \ + echo " g_type_class_ref ($$f ());"; \ + done; \ + exit 1; \ + fi; \ + echo 'Checking if all enum and flag _get_type() funcs are deinited in gst_deinit()'; \ + MISSING_FUNCS=''; \ + for f in $$FUNCS; do \ + INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_unref`; \ + if test "x$$INIT_LINE" = "x"; then \ + MISSING_FUNCS="$$MISSING_FUNCS $$f"; \ + fi; \ + done; \ + if test "x$$MISSING_FUNCS" != "x"; then \ + echo "FIXME: please add to the following to gst/gst.c gst_deinit():"; \ + for f in $$MISSING_FUNCS; do \ + echo " g_type_class_unref (g_type_class_peek ($$f ()));"; \ + done; \ + exit 1; \ + fi + +include $(top_srcdir)/common/coverage/lcov.mak + +# Do not run the check-exports test in case any option which causes the API to +# change has been used +if !GST_DISABLE_REGISTRY +CHECK_EXPORTS = check-exports +endif + +check: $(CHECK_EXPORTS) check-enum-gettypes + +# cruft: plugins that have been merged or moved or renamed + +CRUFT_FILES = \ + $(top_builddir)/win32/common/config.h-new \ + $(top_builddir)/common/shave \ + $(top_builddir)/common/shave-libtool \ + $(top_builddir)/common/m4/codeset.m4 \ + $(top_builddir)/common/m4/gettext.m4 \ + $(top_builddir)/common/m4/glibc2.m4 \ + $(top_builddir)/common/m4/glibc21.m4 \ + $(top_builddir)/common/m4/iconv.m4 \ + $(top_builddir)/common/m4/intdiv0.m4 \ + $(top_builddir)/common/m4/intl.m4 \ + $(top_builddir)/common/m4/intldir.m4 \ + $(top_builddir)/common/m4/intlmacosx.m4 \ + $(top_builddir)/common/m4/intmax.m4 \ + $(top_builddir)/common/m4/inttypes-pri.m4 \ + $(top_builddir)/common/m4/inttypes_h.m4 \ + $(top_builddir)/common/m4/lcmessage.m4 \ + $(top_builddir)/common/m4/lib-ld.m4 \ + $(top_builddir)/common/m4/lib-link.m4 \ + $(top_builddir)/common/m4/lib-prefix.m4 \ + $(top_builddir)/common/m4/libtool.m4 \ + $(top_builddir)/common/m4/lock.m4 \ + $(top_builddir)/common/m4/longlong.m4 \ + $(top_builddir)/common/m4/ltoptions.m4 \ + $(top_builddir)/common/m4/ltsugar.m4 \ + $(top_builddir)/common/m4/ltversion.m4 \ + $(top_builddir)/common/m4/lt~obsolete.m4 \ + $(top_builddir)/common/m4/nls.m4 \ + $(top_builddir)/common/m4/po.m4 \ + $(top_builddir)/common/m4/printf-posix.m4 \ + $(top_builddir)/common/m4/progtest.m4 \ + $(top_builddir)/common/m4/size_max.m4 \ + $(top_builddir)/common/m4/stdint_h.m4 \ + $(top_builddir)/common/m4/uintmax_t.m4 \ + $(top_builddir)/common/m4/visibility.m4 \ + $(top_builddir)/common/m4/wchar_t.m4 \ + $(top_builddir)/common/m4/wint_t.m4 \ + $(top_builddir)/common/m4/xsize.m4 + +CRUFT_DIRS = \ + $(top_builddir)/tests/examples/xml \ + $(top_builddir)/tests/examples/launch \ + $(top_builddir)/tests/examples/metadata \ + $(top_builddir)/tests/examples/queue \ + $(top_builddir)/tests/examples/typefind \ + $(top_builddir)/gst/tmp-introspect* \ + $(top_builddir)/libs/gst/*/tmp-introspect* \ + $(top_srcdir)/docs/plugins/tmpl + +include $(top_srcdir)/common/cruft.mak + +all-local: check-cruft diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..5809d8b --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1489 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# various tests to make sure we dist the win32 stuff (for MSVC builds) right + +# include this snippet to add a common release: target by using +# include $(top_srcdir)/common/release.mak + +# 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 + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@BUILD_TOOLS_TRUE@am__append_1 = tools +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = data/bash-completion/helpers/gst stamp.h +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(aclocaldir)" +DATA = $(aclocal_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/stamp.h.in $(top_srcdir)/common/coverage/lcov.mak \ + $(top_srcdir)/common/cruft.mak $(top_srcdir)/common/po.mak \ + $(top_srcdir)/common/release.mak \ + $(top_srcdir)/common/win32.mak \ + $(top_srcdir)/data/bash-completion/helpers/gst.in ABOUT-NLS \ + AUTHORS COPYING ChangeLog INSTALL NEWS README TODO compile \ + config.guess config.rpath config.sub install-sh ltmain.sh \ + missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ + +# note: keep in sync with configure.ac +ACLOCAL_AMFLAGS = -I m4 -I common/m4 +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc +aclocaldir = $(datadir)/aclocal +aclocal_DATA = gst-element-check-1.0.m4 +SUBDIRS = pkgconfig gst libs plugins tests docs po m4 common data \ + $(am__append_1) + +# These are all the possible subdirs +DIST_SUBDIRS = pkgconfig \ + gst libs plugins tools tests \ + docs \ + po \ + m4 \ + common \ + data + + +# 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') + +# include before EXTRA_DIST for win32 assignment +EXTRA_DIST = \ + gst-element-check-1.0.m4 \ + configure.ac autogen.sh depcomp \ + MAINTAINERS ABOUT-NLS RELEASE gstreamer.doap \ + scripts/gst-uninstalled \ + $(shell find "$(top_srcdir)" -type f -name meson.build ! -path "$(top_srcdir)/gstreamer-*" ) \ + gst/gstenumtypes.c.template gst/gstenumtypes.h.template \ + libs/gst/controller/controller_mkenum.py \ + meson_options.txt \ + gst/parse/gen_lex.py.in gst/parse/gen_grammar.py.in \ + $(win32) + +DISTCLEANFILES = _stdint.h +@GST_GCOV_ENABLED_TRUE@GCOV_DIRS = gst libs + +# Do not run the check-exports test in case any option which causes the API to +# change has been used +@GST_DISABLE_REGISTRY_FALSE@CHECK_EXPORTS = check-exports + +# cruft: plugins that have been merged or moved or renamed +CRUFT_FILES = \ + $(top_builddir)/win32/common/config.h-new \ + $(top_builddir)/common/shave \ + $(top_builddir)/common/shave-libtool \ + $(top_builddir)/common/m4/codeset.m4 \ + $(top_builddir)/common/m4/gettext.m4 \ + $(top_builddir)/common/m4/glibc2.m4 \ + $(top_builddir)/common/m4/glibc21.m4 \ + $(top_builddir)/common/m4/iconv.m4 \ + $(top_builddir)/common/m4/intdiv0.m4 \ + $(top_builddir)/common/m4/intl.m4 \ + $(top_builddir)/common/m4/intldir.m4 \ + $(top_builddir)/common/m4/intlmacosx.m4 \ + $(top_builddir)/common/m4/intmax.m4 \ + $(top_builddir)/common/m4/inttypes-pri.m4 \ + $(top_builddir)/common/m4/inttypes_h.m4 \ + $(top_builddir)/common/m4/lcmessage.m4 \ + $(top_builddir)/common/m4/lib-ld.m4 \ + $(top_builddir)/common/m4/lib-link.m4 \ + $(top_builddir)/common/m4/lib-prefix.m4 \ + $(top_builddir)/common/m4/libtool.m4 \ + $(top_builddir)/common/m4/lock.m4 \ + $(top_builddir)/common/m4/longlong.m4 \ + $(top_builddir)/common/m4/ltoptions.m4 \ + $(top_builddir)/common/m4/ltsugar.m4 \ + $(top_builddir)/common/m4/ltversion.m4 \ + $(top_builddir)/common/m4/lt~obsolete.m4 \ + $(top_builddir)/common/m4/nls.m4 \ + $(top_builddir)/common/m4/po.m4 \ + $(top_builddir)/common/m4/printf-posix.m4 \ + $(top_builddir)/common/m4/progtest.m4 \ + $(top_builddir)/common/m4/size_max.m4 \ + $(top_builddir)/common/m4/stdint_h.m4 \ + $(top_builddir)/common/m4/uintmax_t.m4 \ + $(top_builddir)/common/m4/visibility.m4 \ + $(top_builddir)/common/m4/wchar_t.m4 \ + $(top_builddir)/common/m4/wint_t.m4 \ + $(top_builddir)/common/m4/xsize.m4 + +CRUFT_DIRS = \ + $(top_builddir)/tests/examples/xml \ + $(top_builddir)/tests/examples/launch \ + $(top_builddir)/tests/examples/metadata \ + $(top_builddir)/tests/examples/queue \ + $(top_builddir)/tests/examples/typefind \ + $(top_builddir)/gst/tmp-introspect* \ + $(top_builddir)/libs/gst/*/tmp-introspect* \ + $(top_srcdir)/docs/plugins/tmpl + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/win32.mak $(top_srcdir)/common/release.mak $(top_srcdir)/common/po.mak $(top_srcdir)/common/coverage/lcov.mak $(top_srcdir)/common/cruft.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/win32.mak $(top_srcdir)/common/release.mak $(top_srcdir)/common/po.mak $(top_srcdir)/common/coverage/lcov.mak $(top_srcdir)/common/cruft.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +data/bash-completion/helpers/gst: $(top_builddir)/config.status $(top_srcdir)/data/bash-completion/helpers/gst.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +stamp.h: $(top_builddir)/config.status $(srcdir)/stamp.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-aclocalDATA: $(aclocal_DATA) + @$(NORMAL_INSTALL) + @list='$(aclocal_DATA)'; test -n "$(aclocaldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(aclocaldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(aclocaldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(aclocaldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(aclocaldir)" || exit $$?; \ + done + +uninstall-aclocalDATA: + @$(NORMAL_UNINSTALL) + @list='$(aclocal_DATA)'; test -n "$(aclocaldir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(aclocaldir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && $(MAKE) $(AM_MAKEFLAGS) distcheck-hook \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(aclocaldir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-aclocalDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-aclocalDATA + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ + dist-tarZ dist-xz dist-zip distcheck distclean \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-aclocalDATA \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-aclocalDATA \ + uninstall-am + +.PRECIOUS: Makefile + + +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_API_VERSION@.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 \ + echo "$$libdef"; \ + if test "$$libbase" != "libgstgl"; then \ + fail=1; \ + fi; \ + fi; \ + fi; \ + done ; \ + if test $$fail != 0; then \ + echo '-----------------------------------------------------------'; \ + echo 'Run this to update the .def files:'; \ + echo 'make update-exports'; \ + echo '-----------------------------------------------------------'; \ + fi; \ + exit $$fail + +update-exports: + make check-exports 2>&1 | patch -p1 + if test -f "$(top_srcdir)/win32/common/libgstgl.def"; then \ + git checkout "$(top_srcdir)/win32/common/libgstgl.def"; \ + fi + git add $(top_srcdir)/win32/common/lib*.def + git diff --cached -- $(top_srcdir)/win32/common/ + echo '^^^--- updated and staged changes above' + +# 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 + +release: dist + @$(MAKE) $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo + @echo "=================================================================================================" + @echo "http://gstreamer.freedesktop.org/src/$(PACKAGE)/$(PACKAGE)-$(VERSION).tar.xz" + @cat $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo "=================================================================================================" + @if [ -d ~/releases/ ]; then \ + cp -v $(PACKAGE)-$(VERSION).tar.xz ~/releases/; \ + fi + @if [ -d ../www/data/src ]; then \ + mv -v $(PACKAGE)-$(VERSION).tar.xz ../www/data/src/$(PACKAGE)/ ; \ + mv -v $(PACKAGE)-$(VERSION).tar.xz.sha256sum ../www/data/src/$(PACKAGE)/ ; \ + elif [ -d ../../www/data/src ]; then \ + mv -v $(PACKAGE)-$(VERSION).tar.xz ../../www/data/src/$(PACKAGE)/ ; \ + mv -v $(PACKAGE)-$(VERSION).tar.xz.sha256sum ../../www/data/src/$(PACKAGE)/ ; \ + fi + @echo "=================================================================================================" + +# generate sha256 sum files +%.sha256sum: % + @sha256sum $< > $@ + +# 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 ) + +dist-hook: + @if test -f meson.build && ! $(GREP) -e "version.*'$(VERSION)'" meson.build >/dev/null ; then \ + echo "*******************************************************"; \ + echo "* meson.build needs to be updated for version $(VERSION)"; \ + echo "*******************************************************"; \ + false; \ + fi + +# rule to download the latest .po files +download-po: $(top_srcdir)/common/download-translations + $(top_srcdir)/common/download-translations $(PACKAGE) + for f in po/*.po; do \ + num_changed=`git diff $$f | grep -e '^[+-][^+-]' | wc -l`; \ + num_date=`git diff $$f | grep -e '^[+-][^+-]' | grep POT-Creation-Date | wc -l`; \ + if [ $num_date == $num_changed ]; then \ + git checkout $$f; \ + fi; \ + done + +@GST_GCOV_ENABLED_TRUE@clean-gcov: +@GST_GCOV_ENABLED_TRUE@ find -name "*.da" -o -name "*.gcov" | xargs rm || true + +@GST_GCOV_ENABLED_TRUE@clean-bbg: +@GST_GCOV_ENABLED_TRUE@ find -name "*.bbg" -o -name "*.bb" | xargs rm || true + +@GST_GCOV_ENABLED_TRUE@.PHONY: coverage-report.txt + +@GST_GCOV_ENABLED_TRUE@coverage-report.txt: +@GST_GCOV_ENABLED_TRUE@ BBG_FILES=`find $(GCOV_DIRS) -name "*.bbg"` ; \ +@GST_GCOV_ENABLED_TRUE@ C_FILES= ; \ +@GST_GCOV_ENABLED_TRUE@ for F in $$BBG_FILES ; do \ +@GST_GCOV_ENABLED_TRUE@ F_nolibs=`echo $$F | sed -e 's/.libs\///g'` ; \ +@GST_GCOV_ENABLED_TRUE@ C=`echo $$F_nolibs | sed -e 's/.bbg/.c/g'` ; \ +@GST_GCOV_ENABLED_TRUE@ B=`basename $$F .bbg` ; \ +@GST_GCOV_ENABLED_TRUE@ D=`dirname $$F` ; \ +@GST_GCOV_ENABLED_TRUE@ DA=`echo $$F | sed -e 's/.bbg/.da/g'` ; \ +@GST_GCOV_ENABLED_TRUE@ DA_libs=`echo $$D/.libs/$$B/.da` ; \ +@GST_GCOV_ENABLED_TRUE@ if test -e $$DA || test -e $$DA_libs; then \ +@GST_GCOV_ENABLED_TRUE@ C_FILES="$$C_FILES $$C" ; \ +@GST_GCOV_ENABLED_TRUE@ fi ; \ +@GST_GCOV_ENABLED_TRUE@ done ; \ +@GST_GCOV_ENABLED_TRUE@ echo $$C_FILES ; \ +@GST_GCOV_ENABLED_TRUE@ $(top_builddir)/testsuite/decode-gcov --report $$C_FILES > coverage-report.txt + +@GST_GCOV_ENABLED_TRUE@check-coverage: clean-gcov all check coverage-report.txt +@GST_GCOV_ENABLED_TRUE@ cat coverage-report.txt + +@GST_GCOV_ENABLED_FALSE@coverage-report.txt: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +@GST_GCOV_ENABLED_FALSE@check-coverage: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +@HAVE_CHECK_TRUE@check-valgrind: +@HAVE_CHECK_TRUE@ $(MAKE) -C tests/check check-valgrind + +@HAVE_CHECK_TRUE@check-torture: +@HAVE_CHECK_TRUE@ $(MAKE) -C tests/check torture + +@HAVE_CHECK_TRUE@build-checks: +@HAVE_CHECK_TRUE@ $(MAKE) -C tests/check build-checks +@HAVE_CHECK_FALSE@check-valgrind: +@HAVE_CHECK_FALSE@ echo "'check' library not installed, skipping" + +@HAVE_CHECK_FALSE@check-torture: +@HAVE_CHECK_FALSE@ echo "'check' library not installed, skipping" + +@HAVE_CHECK_FALSE@build-checks: +@HAVE_CHECK_FALSE@ echo "'check' library not installed, skipping" + +check-enum-gettypes: $(top_builddir)/gst/gstenumtypes.h + @echo 'Checking if all enum and flag _get_type() funcs are inited in gst_init()'; \ + FUNCS=`grep '_get_type (' gst/gstenumtypes.h | sed -e 's/^.*gst_/gst_/' -e 's/_get_type.*$$/_get_type/'`;\ + MISSING_FUNCS=''; \ + for f in $$FUNCS; do \ + INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_ref`; \ + if test "x$$INIT_LINE" = "x"; then \ + MISSING_FUNCS="$$MISSING_FUNCS $$f"; \ + fi; \ + done; \ + if test "x$$MISSING_FUNCS" != "x"; then \ + echo "FIXME: please add to the following to gst/gst.c init_post():"; \ + for f in $$MISSING_FUNCS; do \ + echo " g_type_class_ref ($$f ());"; \ + done; \ + exit 1; \ + fi; \ + echo 'Checking if all enum and flag _get_type() funcs are deinited in gst_deinit()'; \ + MISSING_FUNCS=''; \ + for f in $$FUNCS; do \ + INIT_LINE=`grep $$f $(top_srcdir)/gst/*.c | grep g_type_class_unref`; \ + if test "x$$INIT_LINE" = "x"; then \ + MISSING_FUNCS="$$MISSING_FUNCS $$f"; \ + fi; \ + done; \ + if test "x$$MISSING_FUNCS" != "x"; then \ + echo "FIXME: please add to the following to gst/gst.c gst_deinit():"; \ + for f in $$MISSING_FUNCS; do \ + echo " g_type_class_unref (g_type_class_peek ($$f ()));"; \ + done; \ + exit 1; \ + fi +.PHONY: lcov-reset lcov lcov-run lcov-report lcov-upload lcov-clean + +# 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 + +# reset lcov stats +@GST_GCOV_ENABLED_TRUE@lcov-clean: +@GST_GCOV_ENABLED_TRUE@ @-rm -rf lcov +@GST_GCOV_ENABLED_TRUE@ lcov --directory . --zerocounters + +# reset run coverage tests +@GST_GCOV_ENABLED_TRUE@lcov-run: +@GST_GCOV_ENABLED_TRUE@ -$(MAKE) lcov-clean +@GST_GCOV_ENABLED_TRUE@ -if test -d tests/check; then $(MAKE) -C tests/check inspect; fi +@GST_GCOV_ENABLED_TRUE@ -$(MAKE) check + +# generate report based on current coverage data +@GST_GCOV_ENABLED_TRUE@lcov-report: +@GST_GCOV_ENABLED_TRUE@ mkdir lcov +@GST_GCOV_ENABLED_TRUE@ lcov --compat-libtool --directory . --capture --output-file lcov/lcov.info +@GST_GCOV_ENABLED_TRUE@ lcov --list-full-path -l lcov/lcov.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d\| -f1 > lcov/remove +@GST_GCOV_ENABLED_TRUE@ lcov --list-full-path -l lcov/lcov.info | grep "tests/check/" | cut -d\| -f1 >> lcov/remove +@GST_GCOV_ENABLED_TRUE@ lcov --list-full-path -l lcov/lcov.info | grep "docs/plugins/" | cut -d\| -f1 >> lcov/remove +@GST_GCOV_ENABLED_TRUE@ lcov -r lcov/lcov.info `cat lcov/remove` > lcov/lcov.cleaned.info +@GST_GCOV_ENABLED_TRUE@ rm lcov/remove +@GST_GCOV_ENABLED_TRUE@ mv lcov/lcov.cleaned.info lcov/lcov.info +@GST_GCOV_ENABLED_TRUE@ genhtml -t "$(PACKAGE_STRING)" -o lcov --num-spaces 2 lcov/lcov.info + +@GST_GCOV_ENABLED_TRUE@lcov-upload: lcov +@GST_GCOV_ENABLED_TRUE@ rsync -rvz -e ssh --delete lcov/* gstreamer.freedesktop.org:/srv/gstreamer.freedesktop.org/www/data/coverage/lcov/$(PACKAGE) + +@GST_GCOV_ENABLED_FALSE@lcov-run: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +@GST_GCOV_ENABLED_FALSE@lcov-report: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +check: $(CHECK_EXPORTS) check-enum-gettypes + +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 + +all-local: check-cruft + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..ab08164 --- /dev/null +++ b/NEWS @@ -0,0 +1,1340 @@ + + +GSTREAMER 1.14 RELEASE NOTES + + +GStreamer 1.14.0 was originally released on 19 March 2018. + +The latest bug-fix release in the 1.14 series is 1.14.1 and was released +on 17 May 2018. + +See https://gstreamer.freedesktop.org/releases/1.14/ for the latest +version of this document. + +_Last updated: Thursday 17 May 2018, 12:00 UTC (log)_ + + +Introduction + +The GStreamer team is proud to announce a new major feature release in +the stable 1.x API series of your favourite cross-platform multimedia +framework! + +As always, this release is again packed with new features, bug fixes and +other improvements. + + +Highlights + +- WebRTC support: real-time audio/video streaming to and from web + browsers + +- Experimental support for the next-gen royalty-free AV1 video codec + +- Video4Linux: encoding support, stable element names and faster + device probing + +- Support for the Secure Reliable Transport (SRT) video streaming + protocol + +- RTP Forward Error Correction (FEC) support (ULPFEC) + +- RTSP 2.0 support in rtspsrc and gst-rtsp-server + +- ONVIF audio backchannel support in gst-rtsp-server and rtspsrc + +- playbin3 gapless playback and pre-buffering support + +- tee, our stream splitter/duplication element, now does allocation + query aggregation which is important for efficient data handling and + zero-copy + +- QuickTime muxer has a new prefill recording mode that allows file + import in Adobe Premiere and FinalCut Pro while the file is still + being written. + +- rtpjitterbuffer fast-start mode and timestamp offset adjustment + smoothing + +- souphttpsrc connection sharing, which allows for connection reuse, + cookie sharing, etc. + +- nvdec: new plugin for hardware-accelerated video decoding using the + NVIDIA NVDEC API + +- Adaptive DASH trick play support + +- ipcpipeline: new plugin that allows splitting a pipeline across + multiple processes + +- Major gobject-introspection annotation improvements for large parts + of the library API + +- GStreamer C# bindings have been revived and seen many updates and + fixes + +- The externally maintained GStreamer Rust bindings had many usability + improvements and cover most of the API now. Coinciding with the 1.14 + release, a new release with the 1.14 API additions is happening. + + +Major new features and changes + +WebRTC support + +There is now basic support for WebRTC in GStreamer in form of a new +webrtcbin element and a webrtc support library. This allows you to build +applications that set up connections with and stream to and from other +WebRTC peers, whilst leveraging all of the usual GStreamer features such +as hardware-accelerated encoding and decoding, OpenGL integration, +zero-copy and embedded platform support. And it's easy to build and +integrate into your application too! + +WebRTC enables real-time communication of audio, video and data with web +browsers and native apps, and it is supported or about to be support by +recent versions of all major browsers and operating systems. + +GStreamer's new WebRTC implementation uses libnice for Interactive +Connectivity Establishment (ICE) to figure out the best way to +communicate with other peers, punch holes into firewalls, and traverse +NATs. + +The implementation is not complete, but all the basics are there, and +the code sticks fairly close to the PeerConnection API. Where +functionality is missing it should be fairly obvious where it needs to +go. + +For more details, background and example code, check out Nirbheek's blog +post _GStreamer has grown a WebRTC implementation_, as well as Matthew's +_GStreamer WebRTC_ talk from last year's GStreamer Conference in Prague. + +New Elements + +- webrtcbin handles the transport aspects of webrtc connections (see + WebRTC section above for more details) + +- New srtsink and srtsrc elements for the Secure Reliable Transport + (SRT) video streaming protocol, which aims to be easy to use whilst + striking a new balance between reliability and latency for low + latency video streaming use cases. More details about SRT and the + implementation in GStreamer in Olivier's blog post _SRT in + GStreamer_. + +- av1enc and av1dec elements providing experimental support for the + next-generation royalty free video AV1 codec, alongside Matroska + support for it. + +- hlssink2 is a rewrite of the existing hlssink element, but unlike + its predecessor hlssink2 takes elementary streams as input and + handles the muxing to MPEG-TS internally. It also leverages + splitmuxsink internally to do the splitting. This allows more + control over the chunk splitting and sizing process and relies less + on the co-operation of an upstream muxer. Different to the old + hlssink it also works with pre-encoded streams and does not require + close interaction with an upstream encoder element. + +- audiolatency is a new element for measuring audio latency end-to-end + and is useful to measure roundtrip latency including both the + GStreamer-internal latency as well as latency added by external + components or circuits. + +- 'fakevideosink is basically a null sink for video data and very + similar to fakesink, only that it will answer allocation queries and + will advertise support for various video-specific things such + GstVideoMeta, GstVideoCropMeta and GstVideoOverlayCompositionMeta + like a normal video sink would. This is useful for throughput + testing and testing the zero-copy path when creating a new pipeline. + +- ipcpipeline: new plugin that allows the splitting of a pipeline into + multiple processes. Usually a GStreamer pipeline runs in a single + process and parallelism is achieved by distributing workloads using + multiple threads. This means that all elements in the pipeline have + access to all the other elements' memory space however, including + that of any libraries used. For security reasons one might therefore + want to put sensitive parts of a pipeline such as DRM and decryption + handling into a separate process to isolate it from the rest of the + pipeline. This can now be achieved with the new ipcpipeline plugin. + Check out George's blog post _ipcpipeline: Splitting a GStreamer + pipeline into multiple processes_ or his lightning talk from last + year's GStreamer Conference in Prague for all the gory details. + +- proxysink and proxysrc are new elements to pass data from one + pipeline to another within the same process, very similar to the + existing inter elements, but not limited to raw audio and video + data. These new proxy elements are very special in how they work + under the hood, which makes them extremely powerful, but also + dangerous if not used with care. The reason for this is that it's + not just data that's passed from sink to src, but these elements + basically establish a two-way wormhole that passes through queries + and events in both directions, which means caps negotiation and + allocation query driven zero-copy can work through this wormhole. + There are scheduling considerations as well: proxysink forwards + everything into the proxysrc pipeline directly from the proxysink + streaming thread. There is a queue element inside proxysrc to + decouple the source thread from the sink thread, but that queue is + not unlimited, so it is entirely possible that the proxysink + pipeline thread gets stuck in the proxysrc pipeline, e.g. when that + pipeline is paused or stops consuming data for some other reason. + This means that one should always shut down down the proxysrc + pipeline before shutting down the proxysink pipeline, for example. + Or at least take care when shutting down pipelines. Usually this is + not a problem though, especially not in live pipelines. For more + information see Nirbheek's blog post _Decoupling GStreamer + Pipelines_, and also check out out the new ipcpipeline plugin for + sending data from one process to another process (see above). + +- lcms is a new LCMS-based ICC color profile correction element + +- openmptdec is a new OpenMPT-based decoder for module music formats, + such as S3M, MOD, XM, IT. It is built on top of a new + GstNonstreamAudioDecoder base class which aims to unify handling of + files which do not operate a streaming model. The wildmidi plugin + has also been revived and is also implemented on top of this new + base class. + +- The curl plugin has gained a new curlhttpsrc element, which is + useful for testing HTTP protocol version 2.0 amongst other things. + +- The msdk plugin has gained a MPEG-2 video decoder(msdkmpeg2dec), VP8 + decoder(msdkvp8dec) and a VC1/WMV decoder(msdkvc1dec) + +Noteworthy new API + +- GstPromise provides future/promise-like functionality. This is used + in the GStreamer WebRTC implementation. + +- GstReferenceTimestampMeta is a new meta that allows you to attach + additional reference timestamps to a buffer. These timestamps don't + have to relate to the pipeline clock in any way. Examples of this + could be an NTP timestamp when the media was captured, a frame + counter on the capture side or the (local) UNIX timestamp when the + media was captured. The decklink elements make use of this. + +- GstVideoRegionOfInterestMeta: it's now possible to attach generic + free-form element-specific parameters to a region of interest meta, + for example to tell a downstream encoder to use certain codec + parameters for a certain region. + +- gst_bus_get_pollfd can be used to obtain a file descriptor for the + bus that can be poll()-ed on for new messages. This is useful for + integration with non-GLib event loops. + +- gst_get_main_executable_path() can be used by wrapper plugins that + need to find things in the directory where the application + executable is located. In the same vein, + GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE can be used to + signal that plugin dependency paths are relative to the main + executable. + +- pad templates can be told about the GType of the pad subclass of the + pad via newly-added GstPadTemplate API API or the + gst_element_class_add_static_pad_template_with_gtype() convenience + function. gst-inspect-1.0 will use this information to print pad + properties. + +- new convenience functions to iterate over element pads without using + the GstIterator API: gst_element_foreach_pad(), + gst_element_foreach_src_pad(), and gst_element_foreach_sink_pad(). + +- GstBaseSrc and appsrc have gained support for buffer lists: + GstBaseSrc subclasses can use gst_base_src_submit_buffer_list(), and + applications can use gst_app_src_push_buffer_list() to push a buffer + list into appsrc. + +- The GstHarness unit test harness has a couple of new convenience + functions to retrieve all pending data in the harness in form of a + single chunk of memory. + +- GstAudioStreamAlign is a new helper object for audio elements that + handles discontinuity detection and sample alignment. It will align + samples after the previous buffer's samples, but keep track of the + divergence between buffer timestamps and sample position (jitter). + If it exceeds a configurable threshold the alignment will be reset. + This simply factors out code that was duplicated in a number of + elements into a common helper API. + +- The GstVideoEncoder base class implements Quality of Service (QoS) + now. This is disabled by default and must be opted in by setting the + "qos" property, which will make the base class gather statistics + about the real-time performance of the pipeline from downstream + elements (usually sinks that sync the pipeline clock). Subclasses + can then make use of this by checking whether input frames are late + already using gst_video_encoder_get_max_encode_time() If late, they + can just drop them and skip encoding in the hope that the pipeline + will catch up. + +- The GstVideoOverlay interface gained a few helper functions for + installing and handling a "render-rectangle" property on elements + that implement this interface, so that this functionality can also + be used from the command line for testing and debugging purposes. + The property wasn't added to the interface itself as that would + require all implementors to provide it which would not be + backwards-compatible. + +- A new base class, GstNonstreamAudioDecoder for non-stream audio + decoders was added to gst-plugins-bad. This base-class is meant to + be used for audio decoders that require the whole stream to be + loaded first before decoding can start. Examples of this are module + formats (MOD/S3M/XM/IT/etc), C64 SID tunes, video console music + files (GYM/VGM/etc), MIDI files and others. The new openmptdec + element is based on this. + +- Full list of API new in 1.14: +- GStreamer core API new in 1.14 +- GStreamer base library API new in 1.14 +- gst-plugins-base libraries API new in 1.14 +- gst-plugins-bad: no list, mostly GstWebRTC library and new + non-stream audio decoder base class. + +New RTP features and improvements + +- rtpulpfecenc and rtpulpfecdec are new elements that implement + Generic Forward Error Correction (FEC) using Uneven Level Protection + (ULP) as described in RFC 5109. This can be used to protect against + certain types of (non-bursty) packet loss, and important packets + such as those containing codec configuration data or key frames can + be protected with higher redundancy. Equally, packets that are not + particularly important can be given low priority or not be protected + at all. If packets are lost, the receiver can then hopefully restore + the lost packet(s) from the surrounding packets which were received. + This is an alternative to, or rather complementary to, dealing with + packet loss using _retransmission (rtx)_. GStreamer has had + retransmission support for a long time, but Forward Error Correction + allows for different trade-offs: The advantage of Forward Error + Correction is that it doesn't add latency, whereas retransmission + requires at least one more roundtrip to request and hopefully + receive lost packets; Forward Error Correction increases the + required bandwidth however, even in situations where there is no + packet loss at all, so one will typically want to fine-tune the + overhead and mechanisms used based on the characteristics of the + link at the time. + +- New _Redundant Audio Data (RED)_ encoders and decoders for RTP as + per RFC 2198 are also provided (rtpredenc and rtpreddec), mostly for + chrome webrtc compatibility, as chrome will wrap ULPFEC-protected + streams in RED packets, and such streams need to be wrapped and + unwrapped in order to use ULPFEC with chrome. + +- a few new buffer flags for FEC support: + GST_BUFFER_FLAG_NON_DROPPABLE can be used to mark important buffers, + e.g. to flag RTP packets carrying keyframes or codec setup data for + RTP Forward Error Correction purposes, or to prevent still video + frames from being dropped by elements due to QoS. There already is a + GST_BUFFER_FLAG_DROPPABLE. GST_RTP_BUFFER_FLAG_REDUNDANT is used to + signal internally that a packet represents a redundant RTP packet + and used in rtpstorage to hold back the packet and use it only for + recovery from packet loss. Further work is still needed in + payloaders to make use of these. + +- rtpbin now has an option for increasing timestamp offsets gradually: + Sudden large changes to the internal ts_offset may cause timestamps + to move backwards and may also cause visible glitches in media + playback. The new "max-ts-offset-adjustment" and "max-ts-offset" + properties let the application control the rate to apply changes to + ts_offset. There have also been some EOS/BYE handling improvements + in rtpbin. + +- rtpjitterbuffer has a new fast start mode: in many scenarios the + jitter buffer will have to wait for the full configured latency + before it can start outputting packets. The reason for that is that + it often can't know what the sequence number of the first expected + RTP packet is, so it can't know whether a packet earlier than the + earliest packet received will still arrive in future. This behaviour + can now be bypassed by setting the "faststart-min-packets" property + to the number of consecutive packets needed to start, and the jitter + buffer will start output packets as soon as it has N consecutive + packets queued internally. This is particularly useful to get a + first video frame decoded and rendered as quickly as possible. + +- rtpL8pay and rtpL8depay provide RTP payloading and depayloading for + 8-bit raw audio + +New element features + +- playbin3 has gained support or gapless playback via the + "about-to-finish" signal where users can set the uri for the next + item to play. For non-live streams this will be emitted as soon as + the first uri has finished downloading, so with sufficiently large + buffers it is now possible to pre-buffer the next item well ahead of + time (unlike playbin where there would not be a lot of time between + "about-to-finish" emission and the end of the stream). If the stream + format of the next stream is the same as that of the previous + stream, the data will be concatenated via the concat element. + Whether this will result in true gaplessness depends on the + container format and codecs used, there might still be codec-related + gaps between streams with some codecs. + +- tee now does allocation query aggregation, which is important for + zero-copy and efficient data handling, especially for video. Those + who want to drop allocation queries on purpose can use the identity + element's new "drop-allocation" property for that instead. + +- audioconvert now has a "mix-matrix" property, which obsoletes the + audiomixmatrix element. There's also mix matrix support in the audio + conversion and channel mixing API. + +- x264enc: new "insert-vui" property to disable VUI (Video Usability + Information) parameter insertion into the stream, which allows + creation of streams that are compatible with certain legacy hardware + decoders that will refuse to decode in certain combinations of + resolution and VUI parameters; the max. allowed number of B-frames + was also increased from 4 to 16. + +- dvdlpcmdec: has gained support for Blu-Ray audio LPCM. + +- appsrc has gained support for buffer lists (see above) and also seen + some other performance improvements. + +- flvmux has been ported to the GstAggregator base class which means + it can work in defined-latency mode with live input sources and + continue streaming if one of the inputs stops producing data. + +- jpegenc has gained a "snapshot" property just like pngenc to make it + easier to output just a single encoded frame. + +- jpegdec will now handle interlaced MJPEG streams properly and also + handles frames without an End of Image marker better. + +- v4l2: There are now video encoders for VP8, VP9, MPEG4, and H263. + The v4l2 video decoder handles dynamic resolution changes, and the + video4linux device provider now does much faster device probing. The + plugin also no longer uses the libv4l2 library by default, as it has + prevented a lot of interesting use cases like CREATE_BUFS, DMABuf, + usage of TRY_FMT. As the libv4l2 library is totally inactive and not + really maintained, we decided to disable it. This might affect a + small number of cheap/old webcams with custom vendor formats for + which we do not provide conversion in GStreamer. It is possible to + re-enable support for libv4l2 at run-time however, by setting the + environment variable GST_V4L2_USE_LIBV4L2=1. + +- rtspsrc now has support for RTSP protocol version 2.0 as well as + ONVIF audio backchannels (see below for more details). It also + sports a new "accept-certificate" signal for "manually" checking a + TLS certificate for validity. It now also prints RTSP/SDP messages + to the gstreamer debug log instead of stdout. + +- shout2send now uses non-blocking I/O and has a configurable network + operations timeout. + +- splitmuxsink has gained a "split-now" action signal and new + "alignment-threshold" and "use-robust-muxing" properties. If robust + muxing is enabled, it will check and set the muxer's reserved space + properties if present. This is primarily for use with mp4mux's + robust muxing mode. + +- qtmux has a new _prefill recording mode_ which sets up a moov header + with the correct sample positions beforehand, which then allows + software like Adobe Premiere and FinalCut Pro to import the files + while they are still being written to. This only works with constant + framerate I-frame only streams, and for now only support for ProRes + video and raw audio is implemented. Adding support for additional + codecs is just a matter of defining appropriate maximum frame sizes + though. + +- qtmux also supports writing of svmi atoms with stereoscopic video + information now. Trak timescales can be configured on a per-stream + basis using the "trak-timescale" property on the sink pads. Various + new formats can be muxed: MPEG layer 1 and 2, AC3 and Opus, as well + as PNG and VP9. + +- souphttpsrc now does connection sharing by default: it shares its + SoupSession with other elements in the same pipeline via a + GstContext if possible (session-wide settings are all the defaults). + This allows for connection reuse, cookie sharing, etc. Applications + can also force a context to use. In other news, HTTP headers + received from the server are posted as element messages on the bus + now for easier diagnostics, and it's also possible now to use other + types of proxy servers such as SOCKS4 or SOCKS5 proxies, support for + which is implemented directly in gio. Before only HTTP proxies were + allowed. + +- qtmux, mp4mux and matroskamux will now refuse caps changes of input + streams at runtime. This isn't really supported with these + containers (or would have to be implemented differently with a + considerable effort) and doesn't produce valid and spec-compliant + files that will play everywhere. So if you can't guarantee that the + input caps won't change, use a container format that does support on + the fly caps changes for a stream such as MPEG-TS or use + splitmuxsink which can start a new file when the caps change. What + would happen before is that e.g. rtph264depay or rtph265depay would + simply send new SPS/PPS inband even for AVC format, which would then + get muxed into the container as if nothing changed. Some decoders + will handle this just fine, but that's often more luck than by + design. In any case, it's not right, so we disallow it now. + +- matroskamux has Table of Content (TOC) support now (chapters etc.) + and matroskademux TOC support has been improved. matroskademux has + also seen seeking improvements searching for the right cluster and + position. + +- videocrop now uses GstVideoCropMeta if downstream supports it, which + means cropping can be handled more efficiently without any copying. + +- compositor now has support for _crossfade blending_, which can be + used via the new "crossfade-ratio" property on the sink pads. + +- The avwait element has a new "end-timecode" property and posts + "avwait-status" element messages now whenever avwait starts or stops + passing through data (e.g. because target-timecode and end-timecode + respectively have been reached). + +- 'alsamidisrc' element has been broken for many many years and has + now been repaired allowing live capture from your MIDI HW. + +- h265parse and h265parse will try harder to make upstream output the + same caps as downstream requires or prefers, thus avoiding + unnecessary conversion. The parsers also expose chroma format and + bit depth in the caps now. + +- The dtls elements now longer rely on or require the application to + run a GLib main loop that iterates the default main context + (GStreamer plugins should never rely on the application running a + GLib main loop). + +- openh264enc allows to change the encoding bitrate dynamically at + runtime now + +- nvdec is a new plugin for hardware-accelerated video decoding using + the NVIDIA NVDEC API (which replaces the old VDPAU API which is no + longer supported by NVIDIA) + +- The NVIDIA NVENC hardware-accelerated video encoders now support + dynamic bitrate and preset reconfiguration and support the I420 + 4:2:0 video format. It's also possible to configure the gop size via + the new "gop-size" property. + +- The MPEG-TS muxer and demuxer (tsmux, tsdemux) now have support for + JPEG2000 + +- openjpegdec and jpeg2000parse support 2-component images now (gray + with alpha), and jpeg2000parse has gained limited support for + conversion between JPEG2000 stream-formats. (JP2, J2C, JPC) and also + extracts more details such as colorimetry, interlace-mode, + field-order, multiview-mode and chroma siting. + +- The decklink plugin for Blackmagic capture and playback cards have + seen numerous improvements: + +- decklinkaudiosrc and decklinkvideosrc now put hardware reference + timestamp on buffers in form of GstReferenceTimestampMetas. + This can be useful to know on multi-channel cards which frames from + different channels were captured at the same time. + +- decklinkvideosink has gained support for Decklink hardware keying + with two new properties ("keyer-mode" and "keyer-level") to control + the built-in hardware keyer of Decklink cards. + +- decklinkaudiosink has been re-implemented around GstBaseSink instead + of the GstAudioBaseSink base class, since the Decklink APIs don't + fit very well with the GstAudioBaseSink APIs, which used to cause + various problems due to inaccuracies in the clock calculations. + Problems were audio drop-outs and A/V sync going wrong after + pausing/seeking. + +- support for more than 16 devices, without any artificial limit + +- work continued on the msdk plugin for Intel's Media SDK which + enables hardware-accelerated video encoding and decoding on Intel + graphics hardware on Windows or Linux. Added the video memory, + buffer pool, and context/session sharing support which helps to + improve the performance and resource utilization. Rendernode support + is in place which helps to avoid the constraint of having a running + graphics server as DRM-Master. Encoders are exposing a number rate + control algorithms now. More encoder tuning options like + trellis-quantiztion (h264), slice size control (h264), B-pyramid + prediction(h264), MB-level bitrate control, frame partitioning and + adaptive I/B frame insertion were added, and more pixel formats and + video codecs are supported now. The encoder now also handles + force-key-unit events and can insert frame-packing SEIs for + side-by-side and top-bottom stereoscopic 3D video. + +- dashdemux can now do adaptive trick play of certain types of DASH + streams, meaning it can do fast-forward/fast-rewind of normal (non-I + frame only) streams even at high speeds without saturating network + bandwidth or exceeding decoder capabilities. It will keep statistics + and skip keyframes or fragments as needed. See Sebastian's blog post + _DASH trick-mode playback in GStreamer_ for more details. It also + supports webvtt subtitle streams now and has seen improvements when + seeking in live streams. + +- kmssink has seen lots of fixes and improvements in this cycle, + including: + +- Raspberry Pi (vc4) and Xilinx DRM driver support + +- new "render-rectangle" property that can be used from the command + line as well as "display-width" and "display-height", and + "can-scale" properties + +- GstVideoCropMeta support + +Plugin and library moves + +MPEG-1 audio (mp1, mp2, mp3) decoders and encoders moved to -good + +Following the expiration of the last remaining mp3 patents in most +jurisdictions, and the termination of the mp3 licensing program, as well +as the decision by certain distros to officially start shipping full mp3 +decoding and encoding support, these plugins should now no longer be +problematic for most distributors and have therefore been moved from +-ugly and -bad to gst-plugins-good. Distributors can still disable these +plugins if desired. + +In particular these are: + +- mpg123audiodec: an mp1/mp2/mp3 audio decoder using libmpg123 +- lamemp3enc: an mp3 encoder using LAME +- twolamemp2enc: an mp2 encoder using TwoLAME + +GstAggregator moved from -bad to core + +GstAggregator has been moved from gst-plugins-bad to the base library in +GStreamer and is now stable API. + +GstAggregator is a new base class for mixers and muxers that have to +handle multiple input pads and aggregate streams into one output stream. +It improves upon the existing GstCollectPads API in that it is a proper +base class which was also designed with live streaming in mind. +GstAggregator subclasses will operate in a mode with defined latency if +any of the inputs are live streams. This ensures that the pipeline won't +stall if any of the inputs stop producing data, and that the configured +maximum latency is never exceeded. + +GstAudioAggregator, audiomixer and audiointerleave moved from -bad to -base + +GstAudioAggregator is a new base class for raw audio mixers and muxers +and is based on GstAggregator (see above). It provides defined-latency +mixing of raw audio inputs and ensures that the pipeline won't stall +even if one of the input streams stops producing data. + +As part of the move to stabilise the API there were some last-minute API +changes and clean-ups, but those should mostly affect internal elements. + +It is used by the audiomixer element, which is a replacement for +'adder', which did not handle live inputs very well and did not align +input streams according to running time. audiomixer should behave much +better in that respect and generally behave as one would expected in +most scenarios. + +Similarly, audiointerleave replaces the 'interleave' element which did +not handle live inputs or non-aligned inputs very robustly. + +GstAudioAggregator and its subclases have gained support for input +format conversion, which does not include sample rate conversion though +as that would add additional latency. Furthermore, GAP events are now +handled correctly. + +We hope to move the video equivalents (GstVideoAggregator and +compositor) to -base in the next cycle, i.e. for 1.16. + +GStreamer OpenGL integration library and plugin moved from -bad to -base + +The GStreamer OpenGL integration library and opengl plugin have moved +from gst-plugins-bad to -base and are now part of the stable API canon. +Not all OpenGL elements have been moved; a few had to be left behind in +gst-plugins-bad in the new openglmixers plugin, because they depend on +the GstVideoAggregator base class which we were not able to move in this +cycle. We hope to reunite these elements with the rest of their family +for 1.16 though. + +This is quite a milestone, thanks to everyone who worked to make this +happen! + +Qt QML and GTK plugins moved from -bad to -good + +The Qt QML-based qmlgl plugin has moved to -good and provides a +qmlglsink video sink element as well as a qmlglsrc element. qmlglsink +renders video into a QQuickItem, and qmlglsrc captures a window from a +QML view and feeds it as video into a pipeline for further processing. +Both elements leverage GStreamer's OpenGL integration. In addition to +the move to -good the following features were added: + +- A proxy object is now used for thread-safe access to the QML widget + which prevents crashes in corner case scenarios: QML can destroy the + video widget at any time, so without this we might be left with a + dangling pointer. + +- EGL is now supported with the X11 backend, which works e.g. on + Freescale imx6 + +The GTK+ plugin has also moved from -bad to -good. It includes gtksink +and gtkglsink which both render video into a GtkWidget. gtksink uses +Cairo for rendering the video, which will work everywhere in all +scenarios but involves an extra memory copy, whereas gtkglsink fully +leverages GStreamer's OpenGL integration, but might not work properly in +all scenarios, e.g. where the OpenGL driver does not properly support +multiple sharing contexts in different threads; on Linux Nouveau is +known to be broken in this respect, whilst NVIDIA's proprietary drivers +and most other drivers generally work fine, and the experience with +Intel's driver seems to be mixed; some proprietary embedded Linux +drivers don't work; macOS works. + +GstPhysMemoryAllocator interface moved from -bad to -base + +GstPhysMemoryAllocator is a marker interface for allocators with +physical address backed memory. + +Plugin removals + +- the sunaudio plugin was removed, since it couldn't ever have been + built or used with GStreamer 1.0, but no one even noticed in all + these years. + +- the schroedinger-based Dirac encoder/decoder plugin has been + removed, as there is no longer any upstream or anyone else + maintaining it. Seeing that it's quite a fringe codec it seemed best + to simply remove it. + +API removals + +- some MPEG video parser API in the API unstable codecutils library in + gst-plugins-bad was removed after having been deprecated for 5 + years. + + +Miscellaneous changes + +- The video support library has gained support for a few new pixel + formats: +- NV16_10LE32: 10-bit variant of NV16, packed into 32bit words (plus 2 + bits padding) +- NV12_10LE32: 10-bit variant of NV12, packed into 32bit words (plus 2 + bits padding) +- GRAY10_LE32: 10-bit grayscale, packed in 32bit words (plus 2 bits + padding) + +- decodebin, playbin and GstDiscoverer have seen stability + improvements in corner cases such as shutdown while still starting + up or shutdown in error cases (hat tip to the oss-fuzz project). + +- floating reference handling was inconsistent and has been cleaned up + across the board, including annotations. This solves various + long-standing memory leaks in language bindings, which e.g. often + caused elements and pads to be leaked. + +- major gobject-introspection annotation improvements for large parts + of the library API, including nullability of return types and + function parameters, correct types (e.g. strings vs. filenames), + ownership transfer, array length parameters, etc. This allows to use + bigger parts of the GStreamer API to be safely used from dynamic + language bindings (e.g. Python, Javascript) and allows static + bindings (e.g. C#, Rust, Vala) to autogenerate more API bindings + without manual intervention. + +OpenGL integration + +- The GStreamer OpenGL integration library has moved to + gst-plugins-base and is now part of our stable API. + +- new MESA3D GBM BACKEND. On devices with working libdrm support, it + is possible to use Mesa3D's GBM library to set up an EGL context + directly on top of KMS. This makes it possible to use the GStreamer + OpenGL elements without a windowing system if a libdrm- and + Mesa3D-supported GPU is present. + +- Prefer wayland display over X11: As most Wayland compositors support + XWayland, the X11 backend would get selected. + +- gldownload can export dmabufs now, and glupload will advertise + dmabuf as caps feature. + + +Tracing framework and debugging improvements + +- NEW MEMORY RINGBUFFER BASED DEBUG LOGGER, useful for long-running + applications or to retrieve diagnostics when encountering an error. + The GStreamer debug logging system provides in-depth debug logging + about what is going on inside a pipeline. When enabled, debug logs + are usually written into a file, printed to the terminal, or handed + off to a log handler installed by the application. However, at + higher debug levels the volume of debug output quickly becomes + unmanageable, which poses a problem in disk-space or bandwidth + restricted environments or with long-running pipelines where a + problem might only manifest itself after multiple days. In those + situations, developers are usually only interested in the most + recent debug log output. The new in-memory ringbuffer logger makes + this easy: just installed it with gst_debug_add_ring_buffer_logger() + and retrieve logs with gst_debug_ring_buffer_logger_get_logs() when + needed. It is possible to limit the memory usage per thread and set + a timeout to determine how long messages are kept around. It was + always possible to implement this in the application with a custom + log handler of course, this just provides this functionality as part + of GStreamer. + +- 'fakevideosink is a null sink for video data that advertises + video-specific metas and behaves like a video sink. See above for + more details. + +- gst_util_dump_buffer() prints the content of a buffer to stdout. + +- gst_pad_link_get_name() and gst_state_change_get_name() print pad + link return values and state change transition values as strings. + +- The LATENCY TRACER has seen a few improvements: trace records now + contain timestamps which is useful to plot things over time, and + downstream synchronisation time is now excluded from the measured + values. + +- Miniobject refcount tracing and logging was not entirley + thread-safe, there were duplicates or missing entries at times. This + has now been made reliable. + +- The netsim element, which can be used to simulate network jitter, + packet reordering and packet loss, received new features and + improvements: it can now also simulate network congestion using a + token bucket algorithm. This can be enabled via the "max-kbps" + property. Packet reordering can be disabled now via the + "allow-reordering" property: Reordering of packets is not very + common in networks, and the delay functions will always introduce + reordering if delay > packet-spacing, so by setting + "allow-reordering" to FALSE you guarantee that the packets are in + order, while at the same time introducing delay/jitter to them. By + using the new "delay-distribution" property the user can control how + the delay applied to delayed packets is distributed: This is either + the uniform distribution (as before) or the normal distribution; in + addition there is also the gamma distribution which simulates the + delay on wifi networks better. + + +Tools + +- gst-inspect-1.0 now prints pad properties for elements that have pad + subclasses with special properties, such as compositor or + audiomixer. This only works for elements that use the newly-added + GstPadTemplate API API or the + gst_element_class_add_static_pad_template_with_gtype() convenience + function to tell GStreamer about the special pad subclass. + +- gst-launch-1.0 now generates a gstreamer pipeline diagram (.dot + file) whenever SIGHUP is sent to it on Linux/*nix systems. + +- gst-discoverer-1.0 can now analyse live streams such as rtsp:// URIs + + +GStreamer RTSP server + +- Initial support for RTSP protocol version 2.0 was added, which is to + the best of our knowledge the first RTSP 2.0 implementation ever! + +- ONVIF audio backchannel support. This is an extension specified by + ONVIF that allows RTSP clients (e.g. a control room operator) to + send audio back to the RTSP server (e.g. an IP camera). + Theoretically this could have been done also by using the RECORD + method of the RTSP protocol, but ONVIF chose not to do that, so the + backchannel is set up alongside the other streams. Format + negotiation needs to be done out of band, if needed. Use the new + ONVIF-specific subclasses GstRTSPOnvifServer and + GstRTSPOnvifMediaFactory to enable this functionality. + +- The internal server streaming pipeline is now dynamically + reconfigured on PLAY based on the transports needed. This means that + the server no longer adds the pipeline plumbing for all possible + transports from the start, but only if needed as needed. This + improves performance and memory footprint. + +- rtspclientsink has gained an "accept-certificate" signal for + manually checking a TLS certificate for validity. + +- Fix keep-alive/timeout issue for certain clients using TCP + interleave as transport who don't do keep-alive via some other + method such as periodic RTSP OPTION requests. We now put netaddress + metas on the packets from the TCP interleaved stream, so can map + RTCP packets to the right stream in the server and can handle them + properly. + +- Language bindings improvements: in general there were quite a few + improvements in the gobject-introspection annotations, but we also + extended the permissions API which was not usable from bindings + before. + +- Fix corner case issue where the wrong mount point was found when + there were multiple mount points with a common prefix. + + +GStreamer VAAPI + +- Improve DMABuf's usage, both upstream and dowstream, and + memory:DMABuf caps feature is also negotiated when the dmabuf-based + buffer cannot be mapped onto user-space. + +- VA initialization was fixed when it is used in headless systems. + +- VA display sharing, through GstContext, among the pipeline, has been + improved, adding the possibility to the application share its VA + display (external display) via gst.vaapi.app.Display context. + +- VA display cache was removed. + +- libva's log messages are now redirected into the GStreamer log + handler. + +- Decoders improved their upstream re-negotiation by avoiding to + re-instantiate the internal decoder if stream caps are compatible + with the previous one. + +- When downstream doesn't support GstVideoMeta and the decoded frames + don't have standard strides, they are copied onto system + memory-based buffers. + +- H.264 decoder has a low-latency property, for live streams which + doesn't conform the H.264 specification but still it is required to + push the frames to downstream as soon as possible. + +- As part of the Google Summer of Code 2017 the H.264 decoder drops + MVC and SVC frames when base-only property is enabled. + +- Added support for libva-2.0 (VA-API 1.0). + +- H.264 and H.265 encoders handle Region-Of-Interest metas by adding a + delta-qp for every rectangle within the frame specified by those + metas. + +- Encoders for H.264 and H.265 set the media profile by the downstream + caps. + +- H.264 encoder inserts an AU delimiter for each encoded frame when + aud property is enabled (it is only available for certain drivers + and platforms). + +- H.264 encoder supports for P and B hierarchical prediction modes. + +- All encoders handles a quality-level property, which is a number + from 1 to 8, where a lower number means higher quality, but slower + processing, and vice-versa. + +- VP8 and VP9 encoders support constant bit-rate mode (CBR). + +- VP8, VP9 and H.265 encoders support variable bit-rate mode (VBR). + +- Resurrected GstGLUploadTextureMeta handling for EGL backends. + +- H.265 encoder can configure its number of reference frames via the + refs property. + +- Add H.264 encoder mbbrc property, which controls the macro-block + bitrate as auto, on or off. + +- Add H.264 encoder temporal-levels property, to select the number of + temporal levels to be included. + +- Add to H.264 and H.265 encoders the properties qp-ip and qp-ib, to + handle the QP (quality parameter) difference between the I and P + frames, and the I and B frames, respectively. + +- vaapisink was demoted to marginal rank on Wayland because COGL + cannot display YUV surfaces. + +More details in Víctor's blog post _GStreamer VA-API 1.14: what’s new?_. + + +GStreamer Editing Services and NLE + +- Handle crossfade in complex scenarios by using the new + compositorpad::crossfade-ratio property + +- Add API allowing to stop using proxies for clips in the timeline + +- Allow management of none square pixel aspect ratios by allowing + application to deal with them in the way they want + +- Misc fixes around the timeline editing API + + +GStreamer validate + +- Handle running scenarios on live pipelines (in the "content sense", + not the GStreamer one) + +- Implement RTSP support with a basic server based on gst-rtsp-server, + and add RTSP 1.0 and 2.0 integration tests + +- Implement a plugin that allows users to implement configurable + tests. It currently can check if a particular element is added a + configurable number of time in the pipeline. In the future that + plugin should allow us to implement specific tests of any kind in a + descriptive way + +- Add a verbosity configuration which behaves in a similare way as the + gst-launch-1.0 verbose flags allowing the informations to be + outputed on any running pipeline when enabling GstValidate. + +- Misc optimization in the launcher, making the tests run much faster. + + +GStreamer C# bindings + +- Port to the meson build system, autotools support has been removed + +- Use a new GlibSharp version, set as a meson subproject + +- Update wrapped API to GStreamer 1.14 + +- Removed the need for "glue" code + +- Provide a nuget + +- Misc API fixes + + +Build and Dependencies + +- the new WebRTC support in gst-plugins-bad depends on the GStreamer + elements that ship as part of libnice, and libnice version 1.1.14 is + required. Also the dtls and srtp plugins. + +- gst-plugins-bad no longer depends on the libschroedinger Dirac codec + library. + +- The srtp plugin can now also be built against libsrtp2. + +- some plugins and libraries have moved between modules, see the + _Plugin and_ _library moves_ section above, and their respective + dependencies have moved with them of course, e.g. the GStreamer + OpenGL integration support library and plugin is now in + gst-plugins-base, and mpg123, LAME and twoLAME based audio decoder + and encoder plugins are now in gst-plugins-good. + +- Unify static and dynamic plugin interface and remove plugin specific + static build option: Static and dynamic plugins now have the same + interface. The standard --enable-static/--enable-shared toggle is + sufficient. This allows building static and shared plugins from the + same object files, instead of having to build everything twice. + +- The default plugin entry point has changed. This will only affect + plugins that are recompiled against new GStreamer headers. Binary + plugins using the old entry point will continue to work. However, + plugins that are recompiled must have matching plugin names in + GST_PLUGIN_DEFINE and filenames, as the plugin entry point for + shared plugins is now deduced from the plugin filename. This means + you can no longer have a plugin called foo living in a file called + libfoobar.so or such, the plugin filename needs to match. This might + cause problems with some external third party plugin modules when + they get rebuilt against GStreamer 1.14. + + +Note to packagers and distributors + +A number of libraries, APIs and plugins moved between modules and/or +libraries in different modules between version 1.12.x and 1.14.x, see +the _Plugin and_ _library moves_ section above. Some APIs have seen +minor ABI changes in the course of moving them into the stable APIs +section. + +This means that you should try to ensure that all major GStreamer +modules are synced to the same major version (1.12 or 1.13/1.14) and can +only be upgraded in lockstep, so that your users never end up with a mix +of major versions on their system at the same time, as this may cause +breakages. + +Also, plugins compiled against >= 1.14 headers will not load with +GStreamer <= 1.12 owing to a new plugin entry point (but plugin binaries +built against older GStreamer versions will continue to load with newer +versions of GStreamer of course). + +There is also a small structure size related ABI breakage introduced in +the gst-plugins-bad codecparsers library between version 1.13.90 and +1.13.91. This should "only" affect gstreamer-vaapi, so anyone who ships +the release candidates is advised to upgrade those two modules at the +same time. + + +Platform-specific improvements + +Android + +- ahcsrc (Android camera source) does autofocus now + +macOS and iOS + +- no major changes in macOS and iOS support, only bugfixes + +Windows + +- The GStreamer wasapi plugin was rewritten and should not only be + usable now, but in top shape and suitable for low-latency use cases. + The Windows Audio Session API (WASAPI) is Microsoft's most modern + method for talking with audio devices, and now that the wasapi + plugin is up to scratch it is preferred over the directsound plugin. + The ranks of the wasapisink and wasapisrc elements have been updated + to reflect this. Further improvements include: + +- support for more than 2 channels + +- a new "low-latency" property to enable low-latency operation (which + should always be safe to enable) + +- support for the AudioClient3 API which is only available on Windows + 10: in wasapisink this will be used automatically if available; in + wasapisrc it will have to be enabled explicitly via the + "use-audioclient3" property, as capturing audio with low latency and + without glitches seems to require setting the realtime priority of + the entire pipeline to "critical", which cannot be done from inside + the element, but has to be done in the application. + +- set realtime thread priority to avoid glitches + +- allow opening devices in exclusive mode, which provides much lower + latency compared to shared mode where WASAPI's engine period is + 10ms. This can be activated via the "exclusive" property. + +- Also see Nirbheek's blog post _Low Latency Audio on Windows with + GStreamer_. + +- There are now GstDeviceProvider implementations for the wasapi and + directsound plugins, so it's now possible to discover both audio + sources and audio sinks on Windows via the GstDeviceMonitor API + +- debug log timestamps are now higher granularity owing to + g_get_monotonic_time() now being used as fallback in + gst_utils_get_timestamp(). Before that, there would sometimes be + 10-20 lines of debug log output sporting the same timestamp. + + +Contributors + +Aaron Boxer, Adrián Pardini, Adrien SCH, Akinobu Mita, Alban Bedel, +Alessandro Decina, Alex Ashley, Alicia Boya García, Alistair Buxton, +Alvaro Margulis, Anders Jonsson, Andreas Frisch, Andrejs Vasiljevs, +Andrew Bott, Antoine Jacoutot, Antonio Ospite, Antoni Silvestre, Anton +Obzhirov, Anuj Jaiswal, Arjen Veenhuizen, Arnaud Bonatti, Arun Raghavan, +Ashish Kumar, Aurélien Zanelli, Ayaka, Branislav Katreniak, Branko +Subasic, Brion Vibber, Carlos Rafael Giani, Cassandra Rommel, Chris +Bass, Chris Paulson-Ellis, Christoph Reiter, Claudio Saavedra, Clemens +Lang, Cyril Lashkevich, Daniel van Vugt, Dave Craig, Dave Johnstone, +David Evans, David Schleef, Deepak Srivastava, Dimitrios Katsaros, +Dmitry Zhadinets, Dongil Park, Dustin Spicuzza, Eduard Sinelnikov, +Edward Hervey, Enrico Jorns, Eunhae Choi, Ezequiel Garcia, fengalin, +Filippo Argiolas, Florent Thiéry, Florian Zwoch, Francisco Velazquez, +François Laignel, fvanzile, George Kiagiadakis, Georg Lippitsch, Graham +Leggett, Guillaume Desmottes, Gurkirpal Singh, Gwang Yoon Hwang, Gwenole +Beauchesne, Haakon Sporsheim, Haihua Hu, Håvard Graff, Heekyoung Seo, +Heinrich Fink, Holger Kaelberer, Hoonhee Lee, Hosang Lee, Hyunjun Ko, +Ian Jamison, James Stevenson, Jan Alexander Steffens (heftig), Jan +Schmidt, Jason Lin, Jens Georg, Jeremy Hiatt, Jérôme Laheurte, Jimmy +Ohn, Jochen Henneberg, John Ludwig, John Nikolaides, Jonathan Karlsson, +Josep Torra, Juan Navarro, Juan Pablo Ugarte, Julien Isorce, Jun Xie, +Jussi Kukkonen, Justin Kim, Lasse Laursen, Lubosz Sarnecki, Luc +Deschenaux, Luis de Bethencourt, Marcin Lewandowski, Mario Alfredo +Carrillo Arevalo, Mark Nauwelaerts, Martin Kelly, Matej Knopp, Mathieu +Duponchelle, Matteo Valdina, Matt Fischer, Matthew Waters, Matthieu +Bouron, Matthieu Crapet, Matt Staples, Michael Catanzaro, Michael +Olbrich, Michael Shigorin, Michael Tretter, Michał Dębski, Michał Górny, +Michele Dionisio, Miguel París, Mikhail Fludkov, Munez, Nael Ouedraogo, +Neos3452, Nicholas Panayis, Nick Kallen, Nicola Murino, Nicolas +Dechesne, Nicolas Dufresne, Nirbheek Chauhan, Ognyan Tonchev, Ole André +Vadla Ravnås, Oleksij Rempel, Olivier Crête, Omar Akkila, Orestis +Floros, Patricia Muscalu, Patrick Radizi, Paul Kim, Per-Erik Brodin, +Peter Seiderer, Philip Craig, Philippe Normand, Philippe Renon, Philipp +Zabel, Pierre Pouzol, Piotr Drąg, Ponnam Srinivas, Pratheesh Gangadhar, +Raimo Järvi, Ramprakash Jelari, Ravi Kiran K N, Reynaldo H. Verdejo +Pinochet, Rico Tzschichholz, Robert Rosengren, Roland Peffer, Руслан +Ижбулатов, Sam Hurst, Sam Thursfield, Sangkyu Park, Sanjay NM, Satya +Prakash Gupta, Scott D Phillips, Sean DuBois, Sebastian Cote, Sebastian +Dröge, Sebastian Rasmussen, Sejun Park, Sergey Borovkov, Seungha Yang, +Shakin Chou, Shinya Saito, Simon Himmelbauer, Sky Juan, Song Bing, +Sreerenj Balachandran, Stefan Kost, Stefan Popa, Stefan Sauer, Stian +Selnes, Thiago Santos, Thibault Saunier, Thijs Vermeir, Tim Allen, +Tim-Philipp Müller, Ting-Wei Lan, Tomas Rataj, Tom Bailey, Tonu Jaansoo, +U. Artie Eoff, Umang Jain, Ursula Maplehurst, VaL Doroshchuk, Vasilis +Liaskovitis, Víctor Manuel Jáquez Leal, vijay, Vincent Penquerc'h, +Vineeth T M, Vivia Nikolaidou, Wang Xin-yu (王昕宇), Wei Feng, Wim +Taymans, Wonchul Lee, Xabier Rodriguez Calvar, Xavier Claessens, +XuGuangxin, Yasushi SHOJI, Yi A Wang, Youness Alaoui, + +... and many others who have contributed bug reports, translations, sent +suggestions or helped testing. + + +Bugs fixed in 1.14 + +More than 800 bugs have been fixed during the development of 1.14. + +This list does not include issues that have been cherry-picked into the +stable 1.12 branch and fixed there as well, all fixes that ended up in +the 1.12 branch are also included in 1.14. + +This list also does not include issues that have been fixed without a +bug report in bugzilla, so the actual number of fixes is much higher. + + +Stable 1.14 branch + +After the 1.14.0 release there will be several 1.14.x bug-fix releases +which will contain bug fixes which have been deemed suitable for a +stable branch, but no new features or intrusive changes will be added to +a bug-fix release usually. The 1.14.x bug-fix releases will be made from +the git 1.14 branch, which is a stable branch. + +1.14.0 + +1.14.0 was released on 19 March 2018. + +1.14.1 + +The first 1.14 bug-fix release (1.14.1) was released on 17 May 2018. + +This release only contains bugfixes and it should be safe to update from +1.14.0. + +Noteworthy bugfixes in 1.14.1 + +- GstPad: Fix race condition causing the same probe to be called + multiple times +- Fix occasional deadlocks on windows when outputting debug logging +- Fix debug levels being applied in the wrong order +- GIR annotation fixes for bindings +- audiomixer, audioaggregator: fix some negotiation issues +- gst-play-1.0: fix leaving stdin in non-blocking mode after exit +- flvmux: wait for caps on all input pads before writing header even + if source is live +- flvmux: don't wake up the muxer unless there is data, fixes busy + looping if there's no input data +- flvmux: fix major leak of input buffers +- rtspsrc, rtsp-server: revert to RTSP RFC handling of + sendonly/recvonly attributes +- rtpvrawpay: fix payloading with very large mtu sizes where + everything fits into a single RTP packet +- v4l2: Fix hard-coded enabled v4l2 probe on Linux/ARM +- v4l2: Disable DMABuf for emulated formats when using libv4l2 +- v4l2: Always set colorimetry in S_FMT +- asfdemux: Set stream-format field for H264 streams and handle H.264 + in bytestream format +- x265enc: Fix tagging of keyframes on output buffers +- ladspa: Fix critical during plugin load on Windows +- decklink: Fix COM initialisation on Windows +- h264parse: fix re-use across pipeline stop/restart +- mpegtsmux: fix force-keyframe event handling and PCR/PMT changes + that would confuse some players with generated HLS streams +- adaptivedemux: Support period change in live playlist +- rfbsrc: Fix support for applevncserver and support NULL pool in + decide_allocation +- jpegparse: Fix APP1 marker segment parsing +- h265parse: Make caps writable before modifying them, fixes criticals +- fakevideosink: request an extra buffer if enable-last-sample is + enabled +- wasapisrc: Don't provide a clock based on WASAPI's clock +- wasapi: Only use audioclient3 when low-latency, as it might + otherwise glitch with slow CPUs or VMs +- wasapi: Don't derive device period from latency time, should make it + more robust against glitches +- audiolatency: Fix wave detection in buffers and avoid bogus pts + values while starting +- msdk: fix plugin load on implementations with only HW support +- msdk: dec: set framerate to the driver only if provided, not in 0/1 + case +- msdk: Don't set extended coding options for JPEG encode +- rtponviftimestamp: fix state change function init/reset causing + races/crashes on shutdown +- decklink: fix initialization failure in windows binary +- ladspa: Fix critical warnings during plugin load on Windows and fix + dependencies in meson build +- gl: fix cross-compilation error with viv-fb +- qmlglsink: make work with eglfs_kms +- rtspclientsink: Don't deadlock in preroll on early close +- rtspclientsink: Fix client ports for the RTCP backchannel +- rtsp-server: Fix session timeout when streaming data to client over + TCP +- vaapiencode: h264: find best profile in those available, fixing + negotiation errors +- vaapi: remove custom GstGL context handling, use GstGL instead. + Fixes GL Context sharing with WebkitGtk on wayland +- gst-editing-services: various fixes +- gst-python: bump pygobject req to 3.8; fix + GstPad.set_query_function(); dist autogen.sh and configure.ac in + tarball +- g-i: pick up GstVideo-1.0.gir from local build directory in GstGL + build +- g-i: update constant values for bindings +- avoid duplicate symbols in plugins across modules in static builds +- ... and many, many more! + +Cerbero build tool and packaging changes in 1.14.1 + +Toolchain updates on iOS and Android necessitated a fairly large number +of changes in our cerbero build tool used to create our binary packages +for the various platforms we support: + +- Add support for Ubuntu 18.04 in cerbero +- Fix generation of fat shared libraries on macOS +- gnutls: also rename assembly functions on macos/ios to fix link + errors +- gnutls: fix assembly symbol names for windows x86 +- openssl: fix linking on android/armv7 +- openssl: fix linker issue with Android NDK's r16 binutils +- ffmpeg: disable asm for android x86 to fix issues when linking with + apps +- x264: disable asm for android x86 to fix issues when linking with + apps +- gnutls: rename private symbols for armv8, x86 to not conflict with + openssl +- mpg123: disable assembly on android/x86 to fix linker problems with + relocations +- Check built version while loading recipe and rebuild if needed +- Fix packaging of libgcc_s_sjlj which was missing in Windows packages +- Make not-found in library search fatal so we don't accidentally ship + broken packages +- ship the proxy plugin which was new in 1.14 +- Fix git commands accidentally pulling in locally built libraries and + failing + +Contributors to 1.14.1 + +Antonio Ospite, Aurélien Zanelli, Brendan Shanks, Carlos Rafael Giani, +Edward Hervey, Emilio Pozuelo Monfort, Enrique Ocaña González, Garima +Gaur, Georg Lippitsch, Guillaume Desmottes, Havard Graff, Hoonhee Lee, +Hyunjun Ko, James Stevenson, Jan Alexander Steffens (heftig), Jan +Schmidt, Joakim Johansson, Jun Xie, Kai Kang, Kirill Marinushkin, Mark +Nauwelaerts, Matej Knopp, Mathieu Duponchelle, Matthew Waters, Matthias +Fend, Michael Olbrich, Mikhail Fludkov, Nicolas Dufresne, Nirbheek +Chauhan, Olivier Crête, Omar Akkila, Patrik Nilsson, Philippe Normand, +Pierre Labastie, Sebastian Dröge, Seungha Yang, Sreerenj Balachandran, +Stian Selnes, Takeshi Sato, Thibault Saunier, Tim-Philipp Müller, U. +Artie Eoff, Víctor Manuel Jáquez Leal, Vivia Nikolaidou, Whoopie, Xabier +Rodriguez Calvar, Xavier Claessens, Zeeshan Ali, and countless others. + +List of bugs fixed in 1.14.1 + +For a full list of bugfixes see Bugzilla. Note that this is not the full +list of changes. For the full list of changes please refer to the GIT +logs or ChangeLogs of the particular modules. + +1.14.2 + +The second 1.14 bug-fix release (1.14.2) is scheduled to be released +around mid-June 2018. + +This release only contains bugfixes and it should be safe to update from +1.14.x. + + +Known Issues + +- The webrtcdsp element (which is unrelated to the newly-landed + GStreamer webrtc support) is currently not shipped as part of the + Windows binary packages due to a build system issue. + +- The gst-libav module currently won't build against the + newly-released ffmpeg 4.0 (as in F28). Use the internal ffmpeg copy + instead, if you build using autotools. + + +Schedule for 1.16 + +Our next major feature release will be 1.16, and 1.15 will be the +unstable development version leading up to the stable 1.16 release. The +development of 1.15/1.16 will happen in the git master branch. + +The plan for the 1.16 development cycle is yet to be confirmed, but it +is expected that feature freeze will be around August 2018 followed by +several 1.15 pre-releases and the new 1.16 stable release in September. + +1.16 will be backwards-compatible to the stable 1.14, 1.12, 1.10, 1.8, +1.6, 1.4, 1.2 and 1.0 release series. + +------------------------------------------------------------------------ + +_These release notes have been prepared by Tim-Philipp Müller with_ +_contributions from Sebastian Dröge, Sreerenj Balachandran, Thibault +Saunier_ _and Víctor Manuel Jáquez Leal._ + +_License: CC BY-SA 4.0_ diff --git a/README b/README new file mode 100644 index 0000000..cf32843 --- /dev/null +++ b/README @@ -0,0 +1,255 @@ +GStreamer 1.13.x development series + +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 1.0 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 BSDs should work too +- Solaris is reported to work; a specific sunaudiosink plugin has been written +- MacOSX works, binary 1.x packages can be built using the cerbero build tool +- Windows works; binary 1.x packages can be built using the cerbero build tool + - MSys/MinGW builds + - Microsoft Visual Studio builds are not yet available or supported +- Android works, binary 1.x packages can be built using the cerbero build tool +- iOS works + +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 git. + +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 GIT +------------------ + +When building from git 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 git, +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 + +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 git stack uninstalled in your home directory, +so that you can quickly test changes without affecting your system setup or +interfering with GStreamer installed from packages. Many GStreamer developers +use an uninstalled setup for their work. + +There is a 'create-uninstalled-setup.sh' script in + + http://cgit.freedesktop.org/gstreamer/gstreamer/tree/scripts/ + +to easily create an uninstalled setup from scratch. + + +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/RELEASE b/RELEASE new file mode 100644 index 0000000..58b04f2 --- /dev/null +++ b/RELEASE @@ -0,0 +1,84 @@ +This is GStreamer core 1.14.1. + +The GStreamer team is pleased to announce a new bug-fix release in the +stable 1.x API series of your favourite cross-platform multimedia framework! + +The 1.14 release series adds new features on top of the 1.12 series and is +part of the API and ABI-stable 1.x release series of the GStreamer multimedia +framework. + +Full release notes can be found at: + + https://gstreamer.freedesktop.org/releases/1.14/ + +Binaries for Android, iOS, Mac OS X and Windows will be provided shortly +after the release. + +This module will not be very useful by itself and should be used in conjunction +with other GStreamer modules for a complete multimedia experience. + + - gstreamer: provides the core GStreamer libraries and some generic plugins + + - gst-plugins-base: a basic set of well-supported plugins and additional + media-specific GStreamer helper libraries for audio, + video, rtsp, rtp, tags, OpenGL, etc. + + - gst-plugins-good: a set of well-supported plugins under our preferred + license + + - gst-plugins-ugly: a set of well-supported plugins which might pose + problems for distributors + + - gst-plugins-bad: a set of plugins of varying quality that have not made + their way into one of core/base/good/ugly yet, for one + reason or another. Many of these are are production quality + elements, but may still be missing documentation or unit + tests; others haven't passed the rigorous quality testing + we expect yet. + + - gst-libav: a set of codecs plugins based on the ffmpeg library. This is + where you can find audio and video decoders and encoders + for a wide variety of formats including H.264, AAC, etc. + + - gstreamer-vaapi: hardware-accelerated video decoding and encoding using + VA-API on Linux. Primarily for Intel graphics hardware. + + - gst-omx: hardware-accelerated video decoding and encoding, primarily for + embedded Linux systems that provide an OpenMax + implementation layer such as the Raspberry Pi. + + - gst-rtsp-server: library to serve files or streaming pipelines via RTSP + + - gst-editing-services: library an plugins for non-linear editing + +==== Download ==== + +You can find source releases of gstreamer in the download +directory: https://gstreamer.freedesktop.org/src/gstreamer/ + +The git repository and details how to clone it can be found at +https://cgit.freedesktop.org/gstreamer/gstreamer/ + +==== Homepage ==== + +The project's website is https://gstreamer.freedesktop.org/ + +==== Support and Bugs ==== + +We use GNOME's bugzilla for bug reports and feature requests: +https://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer + +Please submit patches via bugzilla as well. + +For help and support, please subscribe to and send questions to the +gstreamer-devel mailing list (see below for details). + +There is also a #gstreamer IRC channel on the Freenode IRC network. + +==== Developers ==== + +GStreamer is stored in Git, hosted at git.freedesktop.org, and can be cloned +from there (see link above). + +Interested developers of the core library, plugins, and applications should +subscribe to the gstreamer-devel list. diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/TODO diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..9bfea57 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1518 @@ +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Figure out how to run the assembler. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_AS +# ---------- +AC_DEFUN([AM_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS +AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) +AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) +_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for 'mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl FIXME we are no longer going to remove this! adjust warning +dnl FIXME message accordingly. +AC_DIAGNOSE([obsolete], +[$0: this macro is deprecated, and will soon be removed. +You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, +and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------- +# 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, AM_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. +AC_DEFUN([AM_PATH_PYTHON], + [ + dnl Find a Python interpreter. Python versions prior to 2.0 are not + dnl supported. (2.0 was released on October 16, 2000). + dnl FIXME: Remove the need to hard-code Python versions here. + m4_define_default([_AM_PYTHON_INTERPRETER_LIST], +[python python2 python3 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl + python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) + + AC_ARG_VAR([PYTHON], [the Python interpreter]) + + m4_if([$1],[],[ + dnl No version check is needed. + # Find any Python interpreter. + if test -z "$PYTHON"; then + AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) + fi + am_display_PYTHON=python + ], [ + dnl A version check is needed. + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + AC_MSG_CHECKING([whether $PYTHON version is >= $1]) + AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Python interpreter is too old])]) + am_display_PYTHON=$PYTHON + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + AC_CACHE_CHECK([for a Python interpreter with version >= $1], + [am_cv_pathless_PYTHON],[ + for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do + test "$am_cv_pathless_PYTHON" = none && break + AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) + done]) + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + if test "$am_cv_pathless_PYTHON" = none; then + PYTHON=: + else + AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) + fi + am_display_PYTHON=$am_cv_pathless_PYTHON + fi + ]) + + if test "$PYTHON" = :; then + dnl Run any user-specified action, or abort. + m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) + else + + 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. + + AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], + [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) + AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) + + 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], ['${prefix}']) + AC_SUBST([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_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], + [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) + AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + 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 behavior + dnl is more consistent with lispdir.m4 for example. + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON script directory], + [am_cv_python_pythondir], + [if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pythondir], [$am_cv_python_pythondir]) + + 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. + + AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], + [am_cv_python_pyexecdir], + [if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + + AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) + + dnl Run any user-specified action. + $2 + fi + +]) + + +# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# This test uses sys.hexversion instead of the string equivalent (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). +AC_DEFUN([AM_PYTHON_CHECK_VERSION], + [prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] +sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([common/m4/as-ac-expand.m4]) +m4_include([common/m4/as-auto-alt.m4]) +m4_include([common/m4/as-compiler-flag.m4]) +m4_include([common/m4/as-libtool.m4]) +m4_include([common/m4/as-version.m4]) +m4_include([common/m4/ax_create_stdint_h.m4]) +m4_include([common/m4/ax_pthread.m4]) +m4_include([common/m4/gst-arch.m4]) +m4_include([common/m4/gst-args.m4]) +m4_include([common/m4/gst-check.m4]) +m4_include([common/m4/gst-error.m4]) +m4_include([common/m4/gst-feature.m4]) +m4_include([common/m4/gst-function.m4]) +m4_include([common/m4/gst-gettext.m4]) +m4_include([common/m4/gst-glib2.m4]) +m4_include([common/m4/gst-package-release-datetime.m4]) +m4_include([common/m4/gst-parser.m4]) +m4_include([common/m4/gst-platform.m4]) +m4_include([common/m4/gst-plugin-docs.m4]) +m4_include([common/m4/gst-plugindir.m4]) +m4_include([common/m4/gst.m4]) +m4_include([common/m4/gtk-doc.m4]) +m4_include([common/m4/introspection.m4]) +m4_include([common/m4/pkg.m4]) +m4_include([m4/check-checks.m4]) +m4_include([m4/gettext.m4]) +m4_include([m4/iconv.m4]) +m4_include([m4/intlmacosx.m4]) +m4_include([m4/inttypes_h.m4]) +m4_include([m4/lib-ld.m4]) +m4_include([m4/lib-link.m4]) +m4_include([m4/lib-prefix.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/longlong.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/nls.m4]) +m4_include([m4/po.m4]) +m4_include([m4/progtest.m4]) +m4_include([m4/stdint_h.m4]) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e2e6f74 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,124 @@ +#!/bin/sh +# +# gstreamer autogen.sh +# +# Run this to generate all the initial makefiles, etc. +# +# This file has been generated from common/autogen.sh.in via common/update-autogen + + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +olddir=`pwd` +cd "$srcdir" + +package=gstreamer +srcfile=gstreamer.doap + +# Make sure we have common +if test ! -f common/gst-autogen.sh; +then + echo "+ Setting up common submodule" + git submodule init +fi +git submodule update + +# 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 + +# install pre-commit hook for doing clean commits +if test ! \( -x .git/hooks/pre-commit -a -L .git/hooks/pre-commit \); +then + rm -f .git/hooks/pre-commit + if ! ln -s ../../common/hooks/pre-commit.hook .git/hooks/pre-commit 2> /dev/null + then + echo "Failed to create commit hook symlink, copying instead ..." + cp common/hooks/pre-commit.hook .git/hooks/pre-commit + fi +fi + +# GNU gettext automake support doesn't get along with git. +# https://bugzilla.gnome.org/show_bug.cgi?id=661128 +if test -d po ; then + touch -t 200001010000 po/gstreamer-1.0.pot +fi + +CONFIGURE_DEF_OPT='--enable-maintainer-mode --enable-gtk-doc' + +if test "x$package" = "xgstreamer"; then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --enable-failing-tests --enable-poisoning" +elif test "x$package" = "xgst-plugins-bad"; then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-player-tests" +fi + +autogen_options $@ + +printf "+ check for build tools" +if test -z "$NOCHECK"; then + echo + + printf " checking for autoreconf ... " + echo + which "autoreconf" 2>/dev/null || { + echo "not found! Please install the autoconf package." + exit 1 + } + + printf " checking for pkg-config ... " + echo + which "pkg-config" 2>/dev/null || { + echo "not found! Please install pkg-config." + exit 1 + } +else + echo ": skipped version checks" +fi + +# if no arguments specified then this will be printed +if test -z "$*" && test -z "$NOCONFIGURE"; 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 +if test -d po && grep ^AM_GNU_GETTEXT_VERSION configure.ac >/dev/null ; then + tool_run "autopoint" "--force" +fi + +# aclocal +if test -f acinclude.m4; then rm acinclude.m4; fi + +autoreconf --force --install || exit 1 + +test -n "$NOCONFIGURE" && { + echo "+ skipping configure stage for package $package, as requested." + echo "+ autogen.sh done." + exit 0 +} + +cd "$olddir" + +echo "+ running configure ... " +test ! -z "$CONFIGURE_DEF_OPT" && echo " default flags: $CONFIGURE_DEF_OPT" +test ! -z "$CONFIGURE_EXT_OPT" && echo " external flags: $CONFIGURE_EXT_OPT" +echo + +echo "$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT +"$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT || { + echo " configure failed" + exit 1 +} + +echo "Now type 'make' to compile $package." diff --git a/common/ChangeLog b/common/ChangeLog new file mode 100644 index 0000000..92d0d25 --- /dev/null +++ b/common/ChangeLog @@ -0,0 +1,1712 @@ +2008-12-17 Edward Hervey + + * gst.supp: + And yet another variation of the GstAudioFilter leak. + +2008-12-15 Sebastian Dröge + + Patch by: Roland Illig + + * 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 + + * gst.supp: + And yet another variant of the GstAudioFilter leak. + +2008-12-13 Edward Hervey + + * 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 + + * gst.supp: + Fix leak in GIO called by gnomevfs. Nothing we can do about this. + +2008-12-12 Edward Hervey + + * 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 + + * 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 + + * 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 + + * gst.supp: + Add suppression variant for Ubuntu Hardy x86/64bit. + +2008-12-01 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Simplily uninstall rule. Its closer to upstream and fixes #150331. + +2008-11-29 Sebastian Dröge + + * m4/glib-gettext.m4: + Update glib-gettext.m4 from latest stable GLib release. + +2008-11-29 Sebastian Dröge + + Patch by: Cygwin Ports maintainer + + + * 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 + + * m4/gtk-doc.m4: + * m4/pkg.m4: + Update gtk-doc and pkg-config m4 macros from their latest releases. + +2008-11-20 Michael Smith + + * m4/as-objc.m4: + Fix objective C test macro when none of the compilers are found at all. + +2008-10-30 Stefan Kost + + * 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 + + * gtk-doc.mak: + Don't clobber the real registry cache file when + building docs. + +2008-10-07 Jan Schmidt - Sun Microsystems + + * m4/gst-error.m4: + Also disable the bogus "loop not entered at top" warnings appearing on Sparc Forte builds. + +2008-10-06 Stefan Kost + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * gst.supp: + Add suppressions for Ubunty Hardy x86/64bit, similar to earlier + versions and 32bit variant. + +2008-07-31 Sebastian Dröge + + * m4/gst-feature.m4: + Remove GST_DISABLE_(ENUMTYPES|INDEX|URI). + +2008-07-21 Tim-Philipp Müller + + * 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 + + * 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 + + * plugins.xsl: + Split refsect2 also here to make "Element Pads" subtitle visible. + +2008-07-08 Sebastian Dröge + + * 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 + + * gtk-doc-plugins.mak: + Only clean doc maintainer stamps in maintainer-clean. Fixes #539977. + +2008-06-20 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * plugins.xsl: + The class was not shown in plugin docs. Fix typo in changelog below. + +2008-05-22 Jan Schmidt + + * gstdoc-scangobj: + Emit warnings if one of the GTypes we're expecting is 0 + when scanning. + +2008-05-21 Felipe Contreras + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix installing png images when gtk-doc is disabled. + +2008-05-21 Felipe Contreras + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix make clean when gtk-doc is disabled and other cleanups. + +2008-05-17 Jan Schmidt + + * gtk-doc-plugins.mak: + Be more quiet when the files don't yet exist. + +2008-05-16 Jan Schmidt + + * 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 + + * 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 + + * gst.supp: + Add suppression for glibc bug on gutsy/x86-64 + +2008-05-12 Stefan Kost + + * plugins.xsl: + Improve the layout of the caps, but splitting them on ";". + +2008-05-09 Sebastian Dröge + + Patch by: Brian Cameron + + * 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 + + * check.mak: (help): + Document GST_CHECKS environment variable in checks 'make help'. + +2008-05-06 Sebastian Dröge + + Patch by: Marc-Andre Lureau + + * 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 + + * 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 + + * gst.supp: Make tls leak suppression a bit more generic. + +2008-04-22 Edward Hervey + + * 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 + + * 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 + + * Makefile.am: + * m4/Makefile.am: + Dist all files in common. Fixes bug #527984. + +2008-04-14 Tim-Philipp Müller + + * 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 + + * 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 + + * m4/gst-default.m4: + Add --with-default-{audiosink|audiosrc|videosink|videosrc|visualizer} + configure switches (#519417). + +2008-04-03 Tim-Philipp Müller + + * m4/gst-args.m4: + Add --disable-foo switch for dependency-less plugins (#525586). + +2008-04-01 Sebastian Dröge + + * m4/gst-parser.m4: + Unconditionally require flex 2.5.31 and bison 1.875. + +2008-03-23 Sebastian Dröge + + * m4/gst-arch.m4: + amd64/x86_64 allows unaligned memory access too. + +2008-03-21 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * m4/ax_create_stdint_h.m4: Oops, checked in the wrong copy of + this file. (Update from upstream) + +2008-03-03 David Schleef + + * m4/ax_create_stdint_h.m4: Update from upstream. Fixes a bug + compiling with MSVC. + +2008-03-03 Edward Hervey + + * 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 + + * 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 + + * gst.supp: + Add another glibc suppression. + +2008-02-29 Peter Kjellerstedt + + * m4/gst-feature.m4: + Make the comment before defines generated via AG_GST_CHECK_FEATURE + look nicer. (#498222) + +2008-02-26 Jan Schmidt + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * gst.supp: + Add even more glibc 2.7 suppressions. + +2008-02-22 Sebastian Dröge + + * gst.supp: + Add another suppression for GLib caching some values after + the first call. + +2008-02-12 Sebastian Dröge + + Patch by: + Tim Mooney + + * m4/gst-error.m4: + Use no%E_MACRO_REDEFINED on Solaris to prevent compiler warnings. + Fixes bug #515905. + +2008-02-11 Sebastian Dröge + + * 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 + + * ChangeLog: + Changelog surgery for last commit. + +2008-02-08 Stefan Kost + + * m4/gtk-doc.m4: + Conditionally check for SED. Also sync a bit with upstream macro. + +2008-02-08 Stefan Kost + + * 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 + + * 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 + + * 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 + + * ChangeLog: + ChangeLog surgery. + + * gstdoc-scangobj: + Sync the object scanner with gtk-doc fixes. Update args and hierarchy + files. + +2008-01-20 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * gst.supp: + Add some glibc 2.7 supressions as found on Debian/unstable. + +2008-01-14 Jan Schmidt + + * download-translations: + Apparently I have problems with leaving things commented out when + I edit shell scripts. + +2008-01-12 Jan Schmidt + + * download-translations: + Remove bash-isms + +2008-01-12 Jan Schmidt + + * check-exports: + Restore the cleanup rm of our tmp file which I didn't mean to leave + commented out. + +2008-01-12 Jan Schmidt + + * 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 + + Patch by: Peter Kjellerstedt + + * 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 + + * coverage/lcov.mak: + Update coverage make-rules: use them conditionaly, use libtool mode + and use lcov to cleanup. + +2007-12-18 Sebastian Dröge + + * glib-gen.mak: + Also use #include "header" instead of #include
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 + + * glib-gen.mak: + Use #include "header" instead of #include
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 + + * 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 + + * Makefile.am: + Don't forget to dist the new win32.mak. + +2007-12-17 Tim-Philipp Müller + + * win32.mak: (win32), (win32defs): + Move common win32 Makefile foo into this new file. + +2007-12-15 Stefan Kost + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + We should have never forked this that much :/. + +2007-12-13 Tim-Philipp Müller + + * check-exports: + Fix build on the ppc64 build bot. + +2007-12-13 Tim-Philipp Müller + + * 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 + + * Makefile.am: + check-exports should be disted. + +2007-12-12 Tim-Philipp Müller + + * 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 + + * 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 + + * 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 + + * gtk-doc-plugins.mak: + Just use the normal 'check' target and avoid a circular + dependency. + +2007-09-06 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Add rule to error out if .hierarchy file contains tabs. + +2007-08-20 Tim-Philipp Müller + + * download-translations: + * po.mak: + If there are new languages, they need to be added to po/LINGUAS. + +2007-08-20 Tim-Philipp Müller + + * 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 + + * gst.supp: + Add a suppression for GLib caching the tmp dir seen on an + Ubuntu Feisty system. + +2007-07-13 Jan Schmidt + + * 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 + + * 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 + + * gst-xmlinspect.py: + * plugins.xsl: + Also extract element caps for plugin-docs. Fixes parts of #117692. + +2007-06-21 Tim-Philipp Müller + + Patch by: Andreas Schwab + + * m4/gst-feature.m4: + Fix quoting (#449493). + +2007-06-10 Sebastian Dröge + + * 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 + + * gst.supp: + Suppression variant for our good friend the TLS leak, this time for + Ubuntu Feisty/x86. + +2007-05-09 Tim-Philipp Müller + + * gtk-doc-plugins.mak: + Fix make distcheck again; change some spaces to tabs in makefile. + +2007-04-29 Thomas Vander Stichele + + * gtk-doc-plugins.mak (-module): + Error out when the html build step gives warnings, so they get + fixed properly. + +2007-04-23 Stefan Kost + + * 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 + + Patch by: Vincent Torri + + * 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 + + * 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 + + * 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 + + * m4/gst-parser.m4: + Fix the flex version check. It ignored the micro version before. + +2007-03-09 Jan Schmidt + + * 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 + + * 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 + + * gst.supp: + add a suppression for this GConf flup on the FC5 buildbot. + +2007-03-06 Jan Schmidt + + * gst.supp: + Make the suppression a little more generic, to catch the FC5 + backtrace too. + +2007-03-06 Jan Schmidt + + * 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 + + * m4/gst-arch.m4: + Move a line that was in the wrong macro + +2007-02-28 Thomas Vander Stichele + + * 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 + + * 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 + + Patch by: Will Newton + + * 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 + + * 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 + + * 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 + + * 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 + + * gst.supp: + More suppressions for edgy. + +2006-09-28 Jan Schmidt + + * 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 + + * gst.supp: + Some suppressions for the more recent ld.so in ubuntu edgy. + +2006-08-23 Tim-Philipp Müller + + * gst.supp: + Shorten function trail so the suppression works on + my ubuntu dapper system with core cvs as well. + +2006-07-28 Jan Schmidt + + * gst.supp: + Extra suppressions from my Ubuntu x86_64 machine + +2006-07-24 Tim-Philipp Müller + + Patch by: Frederic Peters + + * 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 + + * 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 + + Patch by: Frederic Peters + + * m4/gst-parser.m4: + Fix bison detection (#348354) + +2006-07-21 Stefan Kost + + * m4/gst-parser.m4: + check for bison and flex + +2006-07-13 Thomas Vander Stichele + + * 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 + + * 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 + + * 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 + + * m4/gst-args.m4: + when building with gcov, reset CFLAGS and friends to O0 + +2006-07-02 Thomas Vander Stichele + + * 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 + + * 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 + + * 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 + + Patch by: Peter Kjellerstedt + + * 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 + + * 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 + + * 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 + + * m4/gst-arch.m4: + add PPC64 so we can have separate structure sizes for it + +2006-06-05 Edward Hervey + + * gtk-doc.mak: + Check for the proper .devhelp2 file to remove. + +2006-05-31 Thomas Vander Stichele + + * gtk-doc.mak: + allow a magic variable to suppress errors from docbuilding + +2006-05-30 Thomas Vander Stichele + + * gtk-doc.mak: + error out if gtkdoc-mktmpl finds unused declarations + +2006-05-28 Edward Hervey + + * gst.supp: + Reverting previous commit. That's good to know, Edward, but why ? + +2006-05-28 Edward Hervey + + * gst.supp: + Added suppresion for memleak in g_option_context_parse on fc5-64 + +2006-05-19 Thomas Vander Stichele + + * m4/gst-check.m4: + set GSTPB_PLUGINS_DIR just like GST_PLUGINS_DIR + +2006-05-18 Tim-Philipp Müller + + * 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 + + Patch by: Peter Kjellerstedt + + * m4/gst-arch.m4: + add support for CRIS and CRISv32. + +2006-05-17 Jan Schmidt + + * 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 + + * gtk-doc.mak: + Add uninstall rule to remove .devhelp2 files. + +2006-05-09 Edward Hervey + + * gst.supp: + Add suppression for GSlice version of + g_type_init calloc leak + +2006-04-05 Michael Smith + + * gst.supp: + Delete a bogus suppression for the registry code. + Generalise a suppression for a glib bug (see #337404) + +2006-04-04 Michael Smith + + * gst.supp: + Add a leak suppression: the existing glibc-doesn't-free-TLS one + wasn't triggering here. + +2006-04-04 Michael Smith + + * gst.supp: + Add some minimally-neccesary suppressions for my x86/dapper system. + +2006-04-01 Thomas Vander Stichele + + * plugins.xsl: + Do not display an origin link if origin does not start with http + See #323798 + +2006-04-01 Thomas Vander Stichele + + * m4/gst-args.m4: + * m4/gst-feature.m4: + add more macros + * m4/gst-x11.m4: + X11-related checks + +2006-04-01 Thomas Vander Stichele + + * 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 + + * gst.supp: + add a suppression for g_parse_debug_string + +2006-03-23 Stefan Kost + + * gstdoc-scangobj: + sync fully with gtkdoc-0.15 + +2006-03-23 Stefan Kost + + * gstdoc-scangobj: + * gtk-doc.mak: + sync a little with gtk-doc mainline + +2006-03-17 Wim Taymans + + * gst.supp: + add another clone suppression + change all glibc suppressions to match 2.3.* + +2006-03-09 Thomas Vander Stichele + + * 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 + + * check.mak: + Set G_SLICE=always-malloc when valgrinding tests + (closes #333272) + +2006-02-21 Jan Schmidt + + * m4/gst-glib2.m4: + Fix debug output when the GLib version prerequisite is not found + +2006-02-13 Andy Wingo + + * 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 + + * m4/gst-default.m4: + switch to auto* sinks for defaults + +2006-02-02 Wim Taymans + + * 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 + + * gtk-doc-plugins.mak: + only add srcdir/gst if it exists + +2006-01-30 Thomas Vander Stichele + + * release.mak: + don't complain about disted enums in win32 + +2006-01-20 Thomas Vander Stichele + + * 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 + + * 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 + + * m4/pkg.m4: + update with a more recent version + +2006-01-07 Thomas Vander Stichele + + * gettext.patch: + make Makefile depend on LINGUAS, so rebuilds work when adding + a language + +2006-01-03 Michael Smith + + * check.mak: + Clarify error message from valgrind test runs. + +2005-12-16 Thomas Vander Stichele + + * m4/gst-arch.m4: + define HOST_CPU + +2005-11-29 Thomas Vander Stichele + + * check.mak: + add a valgrind-forever target for tests + +2005-11-28 Thomas Vander Stichele + + * 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 + + * 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 + + * m4/gst-check.m4: + check for tools correctly + +2005-10-18 Thomas Vander Stichele + + * gtk-doc.mak: + only enable breaking on new API when make distcheck passes, + not before + +2005-10-18 Thomas Vander Stichele + + * m4/gst-check.m4: + Resurrect Julien's dead body and wipe his mind clean + +2005-10-18 Thomas Vander Stichele + + * m4/gst-check.m4: + Kill Julien + +2005-10-17 Julien MOUTTE + + * 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 + + * gtk-doc.mak: + make build break on new api that has not been added to the + sections file + +2005-10-17 Thomas Vander Stichele + + * 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 + + * m4/gst-glib2.m4: + update, warn in error cases + +2005-10-16 Thomas Vander Stichele + + * m4/gst-error.m4: + add GST_SET_DEFAULT_LEVEL + +2005-10-16 Thomas Vander Stichele + + * 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 + + * m4/Makefile.am: + * m4/gst-gettext.m4: + add macro for setting up gettext + +2005-10-15 Thomas Vander Stichele + + * m4/gst-args.m4: + add some .m4's for argument checking that can be shared among modules + +2005-10-15 Thomas Vander Stichele + + * m4/as-libtool.m4: + set _LT_LDFLAGS + * m4/gst-libxml2.m4: + document + +2005-10-15 Thomas Vander Stichele + + * m4/gst-arch.m4: + indent a little + add AC_REQUIRE + * m4/gst-error.m4: + clean up + +2005-10-12 Thomas Vander Stichele + + * gst-autogen.sh: + update version detection expression to catch stuff like + Libtool (libtool15) 1.5.0 + +2005-10-11 Thomas Vander Stichele + + * gst.supp: + commit 6 new suppressions related to g_module_open; can these + really not be folded into one ? + +2005-10-11 Edward Hervey + + * gst.supp: + made the suppression more generic + Added pthread memleak suppresions + Added nss_parse_* memleak suppresion (used by g_option_context_parse) + +2005-10-11 Thomas Vander Stichele + + * check.mak: + be more strict, more leak resolution + * gst.supp: + clean up the g_type_init suppressions + +2005-10-07 Thomas Vander Stichele + + * m4/Makefile.am: + * m4/gst-valgrind.m4: + put the valgrind detection in an .m4 + +2005-09-29 Thomas Vander Stichele + + * check.mak: + add some more targets, like "help", but also more intensive tests + +2005-09-23 Thomas Vander Stichele + + * gtk-doc.mak: + make certain doc warnings fatal so people maintain docs again + +2005-09-23 Thomas Vander Stichele + + * 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 + + * 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 + + * gst-xmlinspect.py: + * gstdoc-scangobj: + some fixes for new API + * gtk-doc-plugins.mak: + set environment properly + +2005-09-17 David Schleef + + * gtk-doc-plugins.mak: Use new environment variables. + +2005-09-16 Michael Smith + + * gstdoc-scangobj: + Make the scanobj code reflect registry/plugin API changes + +2005-09-15 Thomas Vander Stichele + + * 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 + + * 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 + + * 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 + + * gtk-doc-plugins.mak: + error out on inspect failure + +2005-09-14 Michael Smith + + * glib-gen.mak: + Don't call glib-mkenums with arguments that confuse/break MinGW, + fixes 316155. + +2005-09-03 Thomas Vander Stichele + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * m4/gst-doc.m4: + s/pdf/eps/ in test for whether we output EPS images (#309379). + +2005-07-18 Andy Wingo + + * 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 + + * m4/gst-error.m4: + add macro to set ERROR_CFLAGS + +2005-06-30 Jan Schmidt + + * 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 + + * m4/gtk-doc.m4: + added + +2005-06-03 Stefan Kost + + * gst-autogen.sh: create autoregen.sh *before* shifting the options + +2005-05-17 Thomas Vander Stichele + + * gst-autogen.sh: only update autoregen.sh on actual runs + +2005-03-11 Thomas Vander Stichele + + * m4/check.m4: m4 from the check unit test suite + +2004-12-14 David Schleef + + * m4/gst-arch.m4: remove MMX stuff, since it doesn't work and + isn't needed anywhere + +2004-12-08 Thomas Vander Stichele + + * gst-autogen.sh: + allow failure command to be run so we can clean upfrom autopoint + +2004-09-03 Zeeshan Ali Khattak + * m4/gst-feature.m4: Trying to correct the GST_CHECK_CONFIGPROG macro + +2004-07-21 Benjamin Otte + + * m4/.cvsignore: exciting updates for libtool m4 files + +2004-07-12 David Schleef + + * m4/as-objc.m4: Add a macro to test for objective C + +2004-06-12 Thomas Vander Stichele + + * m4/gst-feature.m4: + not all of them support --plugin-libs, so redirect stderr + +2004-06-12 Thomas Vander Stichele + + * m4/as-scrub-include.m4: + sync with upstream to 0.1.4. Fixes #132440 + +2004-06-07 Benjamin Otte + + * 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 + + * 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 + + * m4/as-scrub-include.m4: synced with upstream + +2004-05-03 Thomas Vander Stichele + + * po.mak: + snippet for updating .po files + +2004-03-18 Thomas Vander Stichele + + * Makefile.am: + * m4/Makefile.am: + integrate these with the dist + +2004-03-17 Thomas Vander Stichele + + * release.mak: add a release target + +2004-03-09 Thomas Vander Stichele + + patch by: Stephane Loeuillet + + * m4/ax_create_stdint_h.m4: + use head -n instead of head - (#136500) + +2004-03-05 Thomas Vander Stichele + + * m4/gst-doc.m4: don't build PS without dvips binary + +2004-02-22 Julio M. Merino Vidal + + reviewed by: Benjamin Otte + + * m4/as-docbook.m4: + don't use == operator with test(1) (fixes #135115) + +2004-02-16 Thomas Vander Stichele + + * common/m4/gst-arch.m4: x86_64 is x86 too (clue from Fedora 2 test) + +2004-02-13 Thomas Vander Stichele + + * 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 + + * m4/gst-libxml2.m4: + take required version as argument, and default to 2.4.9 if not + specified + +2004-02-12 Thomas Vander Stichele + + * m4/gst-feature.m4: + rename and fix up GST_CHECK_DISABLE_SUBSYSTEM + +2004-02-11 Thomas Vander Stichele + + * 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 + + * gst-autogen.sh: Use A-Z instead of A-z in sed expression to + avoid a warning + +2004-02-05 Thomas Vander Stichele + + * 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 + + * 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 + + * glib-gen.mak: added; used to generate enums and marshal code + +2004-01-13 Thomas Vander Stichele + + * 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/common/Makefile.am b/common/Makefile.am new file mode 100644 index 0000000..1eac7d8 --- /dev/null +++ b/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-db.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/common/Makefile.in b/common/Makefile.in new file mode 100644 index 0000000..893e865 --- /dev/null +++ b/common/Makefile.in @@ -0,0 +1,833 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = common +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in ChangeLog README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +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-db.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 + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu common/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/common/README b/common/README new file mode 100644 index 0000000..83a1b88 --- /dev/null +++ b/common/README @@ -0,0 +1,255 @@ +GStreamer @SERIES_VERSION@ + +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 1.0 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 BSDs should work too +- Solaris is reported to work; a specific sunaudiosink plugin has been written +- MacOSX works, binary 1.x packages can be built using the cerbero build tool +- Windows works; binary 1.x packages can be built using the cerbero build tool + - MSys/MinGW builds + - Microsoft Visual Studio builds are not yet available or supported +- Android works, binary 1.x packages can be built using the cerbero build tool +- iOS works + +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 git. + +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 GIT +------------------ + +When building from git 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 git, +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 + +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 git stack uninstalled in your home directory, +so that you can quickly test changes without affecting your system setup or +interfering with GStreamer installed from packages. Many GStreamer developers +use an uninstalled setup for their work. + +There is a 'create-uninstalled-setup.sh' script in + + http://cgit.freedesktop.org/gstreamer/gstreamer/tree/scripts/ + +to easily create an uninstalled setup from scratch. + + +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/common/c-to-xml.py b/common/c-to-xml.py new file mode 100644 index 0000000..7a7a35b --- /dev/null +++ b/common/c-to-xml.py @@ -0,0 +1,36 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +Convert a C program to valid XML to be included in docbook +""" + +from __future__ import print_function, unicode_literals + +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 ('') + print ('') + print () + print ('') + + # print content + print (saxutils.escape(content)) + print ('') + +main() diff --git a/common/check-exports b/common/check-exports new file mode 100755 index 0000000..8d617ff --- /dev/null +++ b/common/check-exports @@ -0,0 +1,54 @@ +#!/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 + +# _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_|Gst|GST_|ges_|Ges|GES_).*/) + { + 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/common/check.mak b/common/check.mak new file mode 100644 index 0000000..9336c44 --- /dev/null +++ b/common/check.mak @@ -0,0 +1,251 @@ +# 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 +AM_TESTS_ENVIRONMENT = CK_DEFAULT_TIMEOUT=20 + +# run any given test by running make test.check +# if the test fails, run it again at at least debug level 2 +%.check: % + @$(AM_TESTS_ENVIRONMENT) \ + $* || \ + $(AM_TESTS_ENVIRONMENT) \ + GST_DEBUG=$$GST_DEBUG,*:2 \ + $* + +# just like 'check', but don't run it again if it fails (useful for debugging) +%.check-norepeat: % + @$(AM_TESTS_ENVIRONMENT) \ + $* + +# run any given test in a loop +%.torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(AM_TESTS_ENVIRONMENT) \ + $*; done + +# run any given test in an infinite loop +%.forever: % + @while true; do \ + $(AM_TESTS_ENVIRONMENT) \ + $* || break; done + +# valgrind any given test by running make test.valgrind +%.valgrind: % + @valgrind_log=$(subst /,-,$*-valgrind.log); \ + $(AM_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 \ + --show-possibly-lost=no \ + --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: % + @$(AM_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 \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + --gen-suppressions=all \ + ./$* 2>&1 | tee suppressions.log + +# valgrind torture any given test +%.valgrind-torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) $*.valgrind || \ + (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 + +# 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: % + @$(AM_TESTS_ENVIRONMENT) \ + CK_FORK=no \ + $(LIBTOOL) --mode=execute \ + gdb $(GDB_ARGS) $* + +%.gdb-forever: % + @while $(MAKE) GDB_ARGS="-ex run -ex quit" $*.gdb ; do \ + sleep 1; done + +%.lcov-reset: + $(MAKE) $*.lcov-run + $(MAKE) $*.lcov-report + +%.lcov: % + $(MAKE) $*.lcov-reset + +if GST_GCOV_ENABLED +%.lcov-clean: + $(MAKE) -C $(top_builddir) lcov-clean + +%.lcov-run: + $(MAKE) $*.lcov-clean + $(MAKE) $*.check + +%.lcov-report: + $(MAKE) -C $(top_builddir) lcov-report +else +%.lcov-run: + echo "Need to reconfigure with --enable-gcov" + +%.lcov-report: + echo "Need to reconfigure with --enable-gcov" +endif + +# torture tests +torture: $(TESTS) + -rm test-registry.* + @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.* + @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; valgrind_targets=""; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + valgrind_targets="$$valgrind_targets $$t.valgrind"; \ + done; \ + if ! $(MAKE) $$valgrind_targets ; then \ + echo "Some tests had leaks or errors under valgrind"; \ + false; \ + fi + +# valgrind all tests until failure +valgrind-forever: $(TESTS) + -rm test-registry.* + @echo "Forever valgrinding tests ..." + @while true; do \ + $(MAKE) valgrind || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind torture all tests +valgrind-torture: $(TESTS) + -rm test-registry.* + @echo "Torturing and valgrinding tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) valgrind || \ + (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 + +# 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_API_VERSION) +inspect: + @echo "Inspecting features ..." + @for e in `$(AM_TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 \ + | cut -d: -f2`; \ + do echo Inspecting $$e; \ + $(GST_INSPECT) $$e > /dev/null 2>&1; done + +# build all tests +build-checks: $(TESTS) + +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, repeat with GST_DEBUG=*:2 if it fails" + @echo "make (dir)/(test).check-norepeat -- run the given check once, but don't run it again if it fails" + @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-forever -- valgrind all tests forever" + @echo "make valgrind-torture -- valgrind all tests $(LOOPS) times" + @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-torture -- valgrind the given test $(LOOPS) times" + @echo "make (dir)/(test).valgrind.gen-suppressions -- generate suppressions" + @echo " and save to suppressions.log" + @echo "make inspect -- inspect all plugin features" + @echo "make build-checks -- build all checks (but don't run them)" + @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/common/coverage/coverage-report-entry.pl b/common/coverage/coverage-report-entry.pl new file mode 100644 index 0000000..d0036b3 --- /dev/null +++ b/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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +print < + +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/common/coverage/coverage-report.pl b/common/coverage/coverage-report.pl
new file mode 100644
index 0000000..18bd6f1
--- /dev/null
+++ b/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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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/common/coverage/coverage-report.xsl b/common/coverage/coverage-report.xsl
new file mode 100644
index 0000000..3fe124b
--- /dev/null
+++ b/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/common/coverage/lcov.mak b/common/coverage/lcov.mak new file mode 100644 index 0000000..b45728a --- /dev/null +++ b/common/coverage/lcov.mak @@ -0,0 +1,47 @@ +## .PHONY so it always rebuilds it +.PHONY: lcov-reset lcov lcov-run lcov-report lcov-upload lcov-clean + +# 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 lcov stats +lcov-clean: + @-rm -rf lcov + lcov --directory . --zerocounters + +# reset run coverage tests +lcov-run: + -$(MAKE) lcov-clean + -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/common/cruft.mak b/common/cruft.mak new file mode 100644 index 0000000..53eec24 --- /dev/null +++ b/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/common/download-translations b/common/download-translations new file mode 100755 index 0000000..55e124c --- /dev/null +++ b/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 ast az be bg pt_BR bs ca zh_CN cs cy da de el eo es et eu fa fi fr fur "\ +"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/common/extract-release-date-from-doap-file b/common/extract-release-date-from-doap-file new file mode 100755 index 0000000..f57e307 --- /dev/null +++ b/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 ~ /<\/release>/) {x=0; print chunk} +}' < "$2" | \ +\ +grep ''"$1"'' | \ +\ +sed -e 's/^.*//' -e 's/<\/created>.*$//' + diff --git a/common/gettext.patch b/common/gettext.patch new file mode 100644 index 0000000..682b905 --- /dev/null +++ b/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/common/glib-gen.mak b/common/glib-gen.mak new file mode 100644 index 0000000..ef93a5f --- /dev/null +++ b/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/common/gst-autogen.sh b/common/gst-autogen.sh new file mode 100644 index 0000000..71049e6 --- /dev/null +++ b/common/gst-autogen.sh @@ -0,0 +1,135 @@ +# 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 +} + + +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/common/gst-glib-gen.mak b/common/gst-glib-gen.mak new file mode 100644 index 0000000..1028b21 --- /dev/null +++ b/common/gst-glib-gen.mak @@ -0,0 +1,47 @@ +# 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 +#glib_gen_decl_banner=GST_EXPORT +#glib_gen_decl_include=\#include + +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$(glib_gen_decl_include)\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "$(glib_gen_decl_banner)\nGType @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/common/gst-indent b/common/gst-indent new file mode 100755 index 0000000..b5e808f --- /dev/null +++ b/common/gst-indent @@ -0,0 +1,55 @@ +#!/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=`gindent --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 + else + INDENT=indent + fi + else + INDENT=gindent + fi +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/common/gst.supp b/common/gst.supp new file mode 100644 index 0000000..bdcaf84 --- /dev/null +++ b/common/gst.supp @@ -0,0 +1,4036 @@ +### 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@@* +} + +{ + + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls +} + +# 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:*alloc + fun:_dl_close_worker + ... + fun:snd_config_searcha_hooks +} + +{ + + 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 everything allocated by gst-libav plugin init +{ + + Memcheck:Leak + fun:*alloc + ... + fun:gst_ffmpeg_cfg_init +} + +## 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 +} + +{ + + Memcheck:Addr8 + ... + 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 +} + +{ + + Memcheck:Cond + fun:*strcasecmp* + ... + fun:__dcigettext +} + +{ + + Memcheck:Value8 + fun:*strcasecmp* + ... + fun:__dcigettext +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:gst_poll_new + fun:gst_poll_new_timer + fun:gst_system_clock_init +} + +{ + + Memcheck:Leak + fun:calloc + ... + fun:gobject_init_ctor +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:g_quark_from*_string +} + +{ + + Memcheck:Param + timer_create(evp) + fun:timer_create@@GLIBC_2.3.3 +} + +{ + closures aren't valgrind friendly (bgo#739850) + Memcheck:Leak + fun:calloc + ... + fun:g_cclosure_new +} + +{ + closures aren't valgrind friendly (bgo#739850) + Memcheck:Leak + fun:malloc + ... + fun:g_closure_add_invalidate_notifier +} + +{ + closures aren't valgrind friendly (bgo#739850) + Memcheck:Leak + fun:calloc + ... + fun:g_closure_new_simple +} + +{ + glib/giomodules2 (from libsoup.supp) + Memcheck:Leak + ... + fun:_g_io_module_get_default +} + +{ + + Memcheck:Addr8 + fun:__GI___strncasecmp_l + fun:____strtod_l_internal + fun:gst_value_deserialize_double +} + +{ + + Memcheck:Addr8 + fun:do_lookup_x +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:g_quark_init +} + +{ + Leak of debug function list + Memcheck:Leak + fun:*alloc + ... + fun:g_slist_prepend + fun:gst_debug_add_log_function +} \ No newline at end of file diff --git a/common/gstdoc-scangobj b/common/gstdoc-scangobj new file mode 100755 index 0000000..9d9fee4 --- /dev/null +++ b/common/gstdoc-scangobj @@ -0,0 +1,1813 @@ +#!/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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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; + +# Options + +# name of documentation module +my $MODULE; +my $OUTPUT_DIR; +my $INSPECT_DIR; +my $VERBOSE; +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, + 'verbose' => \$VERBOSE, + '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", "verbose", "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 <$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"; +my $old_sections_filename = "$OUTPUT_DIR/$MODULE-sections"; +my $new_sections_filename = "$OUTPUT_DIR/$MODULE-sections.new"; + +my $debug_log="g_message"; +if (!defined($VERBOSE) or $VERBOSE eq "0") { + $debug_log="//$debug_log"; +} + +# 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 + +#include +EOT + +if ($includes) { + print OUTPUT $includes; +} else { + for (@types) { + print OUTPUT "extern GType $_ (void);\n"; + } +} + +print OUTPUT < +#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) +{ + const gchar *name_a = gst_plugin_feature_get_name ((GstPluginFeature *) a); + const gchar *name_b = gst_plugin_feature_get_name ((GstPluginFeature *) b); + return strcmp (name_a, name_b); +} + +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 ()); + + 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); + 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; + + $debug_log ("plugin: %s source: %s", gst_plugin_get_name (plugin), source); + + if (reinspect) { + gchar *basename; + + inspect_name = g_strdup_printf ("$INSPECT_DIR" G_DIR_SEPARATOR_S "plugin-%s.xml", + gst_plugin_get_name (plugin)); + 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); + + basename = g_path_get_basename (gst_plugin_get_filename (plugin)); + + /* output plugin data */ + fputs ("\\n",inspect); + fputs (xmlprint(2, "name", gst_plugin_get_name (plugin)),inspect); + fputs (xmlprint(2, "description", gst_plugin_get_description (plugin)),inspect); + fputs (xmlprint(2, "filename", gst_plugin_get_filename (plugin)),inspect); + fputs (xmlprint(2, "basename", basename),inspect); + fputs (xmlprint(2, "version", gst_plugin_get_version (plugin)),inspect); + fputs (xmlprint(2, "license", gst_plugin_get_license (plugin)),inspect); + fputs (xmlprint(2, "source", gst_plugin_get_source (plugin)),inspect); + fputs (xmlprint(2, "package", gst_plugin_get_package (plugin)),inspect); + fputs (xmlprint(2, "origin", gst_plugin_get_origin (plugin)),inspect); + fputs (" \\n", inspect); + + g_free (basename); + } + + features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + + /* 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)); + } + factories = g_list_prepend (factories, feature); + + if (GST_IS_ELEMENT_FACTORY (feature)) { + const gchar *pad_dir[] = { "unknown","source","sink" }; + const gchar *pad_pres[] = { "always","sometimes","request" }; + GList *pads, *pad; + + $debug_log (" feature: %s", gst_plugin_feature_get_name (feature)); + + factory = GST_ELEMENT_FACTORY (feature); + + if (reinspect) { + /* output element data */ + fputs (" \\n", inspect); + fputs (xmlprint(6, "name", gst_plugin_feature_get_name (feature)),inspect); + fputs (xmlprint(6, "longname", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)),inspect); + fputs (xmlprint(6, "class", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS)),inspect); + fputs (xmlprint(6, "description", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION)),inspect); + fputs (xmlprint(6, "author", gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_AUTHOR)),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); + } + } else if (GST_IS_TRACER_FACTORY (feature)) { + $debug_log (" feature: %s", gst_plugin_feature_get_name (feature)); + + if (reinspect) { + /* output element data */ + fputs (" \\n", inspect); + fputs (xmlprint(6, "name", gst_plugin_feature_get_name (feature)),inspect); + + fputs (" \\n", inspect); + } + } + features = g_list_next (features); + } + + if (reinspect) { + fputs (" \\n", inspect); + fclose (inspect); + } + } + + g_string_free (xmlstr, TRUE); + + $debug_log ("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) { + const gchar *name = NULL; + type = 0; + if (GST_IS_ELEMENT_FACTORY (l->data)) { + factory = GST_ELEMENT_FACTORY (l->data); + type = gst_element_factory_get_element_type (factory); + name = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME); + } else if (GST_IS_TRACER_FACTORY (l->data)) { + GstTracerFactory *t = GST_TRACER_FACTORY (l->data); + type = gst_tracer_factory_get_tracer_type (t); + name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (t)); + } + if (type != 0) { + $debug_log ("adding type for factory %s", name); + object_types[i++] = type; + } else { + g_message ("type info for factory %s not found", name); + } + 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); +} + +static int +compare_types (const void *a, const void *b) +{ + const char *na = g_type_name (*((GType *)a)); + const char *nb = g_type_name (*((GType *)b)); + + return g_strcmp0 (na, nb); +} + + +/* 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); + qsort (children, n_children, sizeof (GType), compare_types); + + + 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; + } +} + +static void +output_sections (void) +{ + FILE *fp; + gint i; + + fp = fopen (sections_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", sections_filename, g_strerror(errno)); + return; + } + + for (i = 0; object_types[i]; i++) { } + qsort (object_types, i, sizeof (GType), compare_types); + + for (i = 0; object_types[i]; i++) { + output_object_section (fp, object_types[i]); + } + + fclose (fp); +} + +static gboolean +find_by_type (GstPluginFeature *f, gpointer data) { + return (GST_IS_ELEMENT_FACTORY(f) && + ((GType)data == gst_element_factory_get_element_type (GST_ELEMENT_FACTORY(f)))); +} + +static void +output_object_section (FILE *fp, GType object_type) +{ + /* e.g. GstFakeSink */ + const gchar *tn = g_type_name (object_type); + const gchar *cct = &tn[3]; /* cut 'Gst' */ + gchar *title, *lct, *uct; + gint i, j, l = strlen(cct); + gpointer class; + GParamSpec **properties; + guint n_properties; + const gchar *ptn; + gchar *ptns; + GString *strbuf = g_string_new (NULL); + GList *fl; + GstPluginFeature *f = NULL; + gboolean need_unserscore = TRUE, have_abbrev = FALSE; + + fl = gst_registry_feature_filter (gst_registry_get(), find_by_type, TRUE, + (gpointer)object_type); + if (fl) { + f = fl->data; + g_list_free(fl); + } + if (f) { + title = g_strdup (gst_plugin_feature_get_name(f)); + g_object_unref (f); + } else { + title = g_ascii_strdown(cct, -1); + } + + /* turn CamelCase into '_' separated all lower, resulting string is atmost + * twice as long, special casing for abbevs like GstTCPClientSink */ + lct = g_malloc(2*l); + for (i = 0, j = 0; i < l; i++) { + if (g_ascii_isupper (cct[i])) { + if (need_unserscore) { + if (i > 0) { + lct[j++] = '_'; + } + } else { + have_abbrev = TRUE; + } + lct[j++] = g_ascii_tolower(cct[i]); + need_unserscore = FALSE; + } else { + if (have_abbrev) { + lct[j] = lct[j-1]; + lct[j-1] = '_'; + j++; + have_abbrev = FALSE; + } + lct[j++] = cct[i]; + need_unserscore = TRUE; + } + } + lct[j] = '\\0'; + uct = g_ascii_strup(lct, -1); + + /* scan properties and find local enums */ + class = g_type_class_peek (object_type); + properties = g_object_class_list_properties (class, &n_properties); + qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs); + for (i = 0; i < n_properties; i++) { + GParamSpec *spec = properties[i]; + if (!(G_IS_PARAM_SPEC_ENUM (spec) || G_IS_PARAM_SPEC_FLAGS (spec))) { + continue; + } + ptn = g_type_name(spec->value_type); + // does it start with tn? + if (strncmp(tn, ptn, strlen(tn))) { + continue; + } + g_string_append_c(strbuf, '\\n'); + g_string_append(strbuf, ptn); + } + ptns = g_string_free (strbuf, FALSE); + + /* later we can remove the SUBSECTION Standart/Private, since we only need to + * highlight what is public API */ + fprintf (fp, "
\\n" + "element-%s\\n" + "%s\\n" + "Gst%s%s\\n" + "\\n" + "Gst%sClass\\n" + "GST_%s\\n" + "GST_%s_CAST\\n" + "GST_IS_%s\\n" + "GST_%s_CLASS\\n" + "GST_IS_%s_CLASS\\n" + "GST_TYPE_%s\\n" + "\\n" + "gst_%s_get_type\\n" + "
\\n\\n", + title, title, cct, ptns, + cct, uct, uct, uct, uct, uct, uct, lct); + g_free (title); + g_free (lct); + g_free (uct); + g_free (ptns); +} + +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" +} + +my $stdout=""; +if (!defined($VERBOSE) or $VERBOSE eq "0") { + $stdout=">/dev/null"; +} + +# Compiling scanner +$command = "$CC $stdout $CFLAGS -c -o $o_file $MODULE-scan.c"; +system("($command)") == 0 or die "Compilation of scanner failed: $!\n"; + +# Linking scanner +$command = "$LD $stdout -o $MODULE-scan $o_file $LDFLAGS"; +system($command) == 0 or die "Linking of scanner failed: $!\n"; + +# Running scanner $MODULE-scan "; +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"; +} + +# Copied from gtk-doc 1db161bd708cdfb88b362ea0b5d047034d9c3272 +############################################################################# +# Function : UpdateFileIfChanged +# Description : Compares the old version of the file with the new version and +# if the file has changed it moves the new version into the old +# versions place. This is used so we only change files if +# needed, so we can do proper dependency tracking and we don't +# needlessly check files into version control systems that haven't +# changed. +# It returns 0 if the file hasn't changed, and 1 if it has. +# Arguments : $old_file - the pathname of the old file. +# $new_file - the pathname of the new version of the file. +# $make_backup - 1 if a backup of the old file should be kept. +# It will have the .bak suffix added to the file name. +############################################################################# + +sub UpdateFileIfChanged { + my ($old_file, $new_file, $make_backup) = @_; + + #@TRACE@("Comparing $old_file with $new_file..."); + + # If the old file doesn't exist we want this to default to 1. + my $exit_code = 1; + + if (-e $old_file) { + `cmp -s "$old_file" "$new_file"`; + $exit_code = $? >> 8; + #@TRACE@(" cmp exit code: $exit_code ($?)"); + } + + if ($exit_code > 1) { + die "Error running 'cmp $old_file $new_file'"; + } + + if ($exit_code == 1) { + #@TRACE@(" files changed - replacing old version with new version."); + if ($make_backup && -e $old_file) { + rename ($old_file, "$old_file.bak") + || die "Can't move $old_file to $old_file.bak: $!"; + } + rename ($new_file, $old_file) + || die "Can't move $new_file to $old_file: $!"; + + return 1; + } else { + #@TRACE@(" files the same - deleting new version."); + unlink ("$new_file") + || die "Can't delete file: $new_file: $!"; + + return 0; + } +} + +&UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0); +# we will merge these in scangobj-merge.py +#&UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0); +#&UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0); +#&UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0); +#&UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0); +#&UpdateFileIfChanged ($old_sections_filename, $new_sections_filename, 0); diff --git a/common/gtk-doc-plugins.mak b/common/gtk-doc-plugins.mak new file mode 100644 index 0000000..8cf6e15 --- /dev/null +++ b/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: scanobj-update + $(MAKE) check-outdated-docs + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = +endif + +# 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_API_VERSION@ + +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 \ + sgml-build.stamp \ + html-build.stamp \ + scan.stamp \ + sgml.stamp \ + html.stamp + +# files generated/updated by gtkdoc-scangobj +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + $(DOC_MODULE).types + +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 + +CLEANFILES = \ + $(SCANOBJ_FILES_O) \ + $(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_1_0= \ + GST_PLUGIN_PATH_1_0=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(top_builddir)/plugins:$(top_builddir)/src:$(top_builddir)/gnl \ + GST_REGISTRY_1_0=$(INSPECT_REGISTRY) \ + PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INSPECT_EXTRA_ENVIRONMENT) + +#### scan gobjects; done by documentation maintainer #### +scanobj-update: + -rm scanobj-build.stamp + $(MAKE) scanobj-build.stamp + +# gstdoc-scanobj produces 5 output files (.new) +# scangobj-merge.py merges them into the file which we commit later +# TODO: also merge the hierarchy +scanobj-build.stamp: $(SCANOBJ_DEPS) $(basefiles) + @echo " DOC Introspecting 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 . || cp $(srcdir)/$$f . ; \ + fi; \ + done; \ + fi; \ + mkdir -p $(INSPECT_DIR); \ + scanobj_options=""; \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + $(INSPECT_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS) $(WARNING_CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + $(GST_DOC_SCANOBJ) $$scanobj_options --type-init-func="gst_init(NULL,NULL)" \ + --module=$(DOC_MODULE) --source=$(PACKAGE) --inspect-dir=$(INSPECT_DIR) && \ + echo " DOC Merging introspection data" && \ + $(PYTHON) \ + $(top_srcdir)/common/scangobj-merge.py $(DOC_MODULE) || exit 1; \ + 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 ' DOC Scanning header 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 . || cp $(srcdir)/$$f .; \ + fi; \ + done; \ + fi + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + $${_source_dir} \ + --ignore-headers="$(IGNORE_HFILES)"; \ + touch scan-build.stamp + +#### xml #### + +sgml-build.stamp: scan-build.stamp $(CFILE_GLOB) $(top_srcdir)/common/plugins.xsl $(expand_content_files) + @echo ' DOC Building XML' + @-mkdir -p xml + @for a in $(inspect_files); 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 + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb \ + --module=$(DOC_MODULE) \ + $${_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) + @$(PYTHON) $(top_srcdir)/common/mangle-db.py xml + @cp ../version.entities xml + @touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo ' DOC Building HTML' + @rm -rf html + @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 + @mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(DOC_MODULE)-@GST_API_VERSION@ $(DOC_MAIN_SGML_FILE) + @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 ' DOC Fixing cross-references' + @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)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(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/common/gtk-doc.mak b/common/gtk-doc.mak new file mode 100644 index 0000000..3f83491 --- /dev/null +++ b/common/gtk-doc.mak @@ -0,0 +1,248 @@ +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = +endif + +# 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_API_VERSION@ + +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 \ + 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-build.stamp: $(content_files) + -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + echo ' DOC Preparing build'; \ + files=`echo $(DOC_MAIN_SGML_FILE) $(DOC_OVERRIDES) $(DOC_MODULE)-sections.txt $(DOC_MODULE).types $(content_files)`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + test -f $(abs_srcdir)/$$file && \ + cp -pu $(abs_srcdir)/$$file $(abs_builddir)/ || true; \ + done; \ + fi; \ + fi + @touch setup-build.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 ' DOC Scanning header files' + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + $${_source_dir} \ + --ignore-headers="$(IGNORE_HFILES)" + @if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; then \ + echo " DOC Introspecting gobjects"; \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + GST_PLUGIN_SYSTEM_PATH_1_0=`cd $(top_builddir) && pwd` \ + GST_PLUGIN_PATH_1_0= \ + GST_REGISTRY_1_0=doc-registry.xml \ + $(GTKDOC_EXTRA_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ + $$scanobj_options --module=$(DOC_MODULE) ; \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + $(MKDIR_P) $(dirname $$i) ; \ + test -f $$i || touch $$i ; \ + done \ + fi + @touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) + @echo ' DOC Building XML' + @_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) $${_source_dir} --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) + @cp ../version.entities xml + @touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo ' DOC Building HTML' + @rm -rf html + @mkdir html + @cp -pr xml html + @cp ../version.entities ./ + @mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$(?)" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + @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)-@GST_API_VERSION@ ../$(DOC_MAIN_SGML_FILE) + @rm -rf html/xml + @rm -f version.entities + @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) + @echo ' DOC Fixing cross-references' + @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_MAIN_SGML_FILE) ; \ + rm -f $(DOC_OVERRIDES) ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -f $(content_files) ; \ + 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)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(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/common/m4/Makefile.am b/common/m4/Makefile.am new file mode 100644 index 0000000..cdcec8c --- /dev/null +++ b/common/m4/Makefile.am @@ -0,0 +1,41 @@ +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-python.m4 \ + as-version.m4 \ + ax_create_stdint_h.m4 \ + ax_pthread.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/common/m4/Makefile.in b/common/m4/Makefile.in new file mode 100644 index 0000000..26ea643 --- /dev/null +++ b/common/m4/Makefile.in @@ -0,0 +1,673 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = common/m4 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +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-python.m4 \ + as-version.m4 \ + ax_create_stdint_h.m4 \ + ax_pthread.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 + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu common/m4/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu common/m4/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/common/m4/README b/common/m4/README new file mode 100644 index 0000000..867a344 --- /dev/null +++ b/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/common/m4/as-ac-expand.m4 b/common/m4/as-ac-expand.m4 new file mode 100644 index 0000000..d6c9e33 --- /dev/null +++ b/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/common/m4/as-auto-alt.m4 b/common/m4/as-auto-alt.m4 new file mode 100644 index 0000000..3f7920d --- /dev/null +++ b/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/common/m4/as-compiler-flag.m4 b/common/m4/as-compiler-flag.m4 new file mode 100644 index 0000000..8bb853a --- /dev/null +++ b/common/m4/as-compiler-flag.m4 @@ -0,0 +1,96 @@ +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]) +]) + +dnl AS_OBJC_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_OBJC_COMPILER_FLAG], +[ + AC_REQUIRE([AC_PROG_OBJC]) + + AC_MSG_CHECKING([to see if Objective C compiler understands $1]) + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $1" + + AC_LANG_PUSH([Objective 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([Objective C]) + + AC_MSG_RESULT([$flag_ok]) +]) + diff --git a/common/m4/as-compiler.m4 b/common/m4/as-compiler.m4 new file mode 100644 index 0000000..309a060 --- /dev/null +++ b/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/common/m4/as-docbook.m4 b/common/m4/as-docbook.m4 new file mode 100644 index 0000000..2e27050 --- /dev/null +++ b/common/m4/as-docbook.m4 @@ -0,0 +1,78 @@ +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 -n "$XML_CATALOG_FILES"; then + oldIFS=$IFS + IFS=' ' + for xml_catalog_file in $XML_CATALOG_FILES; do + if test -f $xml_catalog_file; then + XML_CATALOG=$xml_catalog_file + CAT_ENTRY_START='' + break + fi + done + IFS=$oldIFS + elif 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/common/m4/as-gcc-inline-assembly.m4 b/common/m4/as-gcc-inline-assembly.m4 new file mode 100644 index 0000000..af32104 --- /dev/null +++ b/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/common/m4/as-libtool-tags.m4 b/common/m4/as-libtool-tags.m4 new file mode 100644 index 0000000..06f0ae4 --- /dev/null +++ b/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/common/m4/as-libtool.m4 b/common/m4/as-libtool.m4 new file mode 100644 index 0000000..3b16095 --- /dev/null +++ b/common/m4/as-libtool.m4 @@ -0,0 +1,46 @@ +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) + + LT_PREREQ([2.2.6]) + LT_INIT([dlopen win32-dll disable-static]) +]) diff --git a/common/m4/as-python.m4 b/common/m4/as-python.m4 new file mode 100644 index 0000000..eb9b175 --- /dev/null +++ b/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/common/m4/as-version.m4 b/common/m4/as-version.m4 new file mode 100644 index 0000000..22ff774 --- /dev/null +++ b/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/common/m4/ax_create_stdint_h.m4 b/common/m4/ax_create_stdint_h.m4 new file mode 100644 index 0000000..13bf699 --- /dev/null +++ b/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/common/m4/ax_pthread.m4 b/common/m4/ax_pthread.m4 new file mode 100644 index 0000000..4c4051e --- /dev/null +++ b/common/m4/ax_pthread.m4 @@ -0,0 +1,485 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# 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 3 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, see . +# +# 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 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. + +#serial 23 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/common/m4/check.m4 b/common/m4/check.m4 new file mode 100644 index 0000000..afd26eb --- /dev/null +++ b/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/common/m4/glib-gettext.m4 b/common/m4/glib-gettext.m4 new file mode 100644 index 0000000..f8d442f --- /dev/null +++ b/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/common/m4/gst-arch.m4 b/common/m4/gst-arch.m4 new file mode 100644 index 0000000..4ad7680 --- /dev/null +++ b/common/m4/gst-arch.m4 @@ -0,0 +1,147 @@ +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], +[ + dnl Determine CPU + case "x${target_cpu}" in + xi?86 | xk? | xi?86_64) + case $target_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 target 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 target CPU is a x86_64]) + fi + ;; + *) + HAVE_CPU_I386=yes + AC_DEFINE(HAVE_CPU_I386, 1, [Define if the target CPU is an x86]) + + dnl FIXME could use some better detection + dnl (ie CPUID) + case "x${target_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 target CPU is a PowerPC]) ;; + xpowerpc64) + HAVE_CPU_PPC64=yes + AC_DEFINE(HAVE_CPU_PPC64, 1, [Define if the target CPU is a 64 bit PowerPC]) ;; + xalpha*) + HAVE_CPU_ALPHA=yes + AC_DEFINE(HAVE_CPU_ALPHA, 1, [Define if the target CPU is an Alpha]) ;; + xarc*) + HAVE_CPU_ARC=yes + AC_DEFINE(HAVE_CPU_ARC, 1, [Define if the target CPU is an ARC]) ;; + xarm*) + HAVE_CPU_ARM=yes + AC_DEFINE(HAVE_CPU_ARM, 1, [Define if the target CPU is an ARM]) ;; + xaarch64*) + HAVE_CPU_AARCH64=yes + AC_DEFINE(HAVE_CPU_AARCH64, 1, [Define if the target CPU is AARCH64]) ;; + xsparc*) + HAVE_CPU_SPARC=yes + AC_DEFINE(HAVE_CPU_SPARC, 1, [Define if the target CPU is a SPARC]) ;; + xmips*) + HAVE_CPU_MIPS=yes + AC_DEFINE(HAVE_CPU_MIPS, 1, [Define if the target CPU is a MIPS]) ;; + xhppa*) + HAVE_CPU_HPPA=yes + AC_DEFINE(HAVE_CPU_HPPA, 1, [Define if the target CPU is a HPPA]) ;; + xs390*) + HAVE_CPU_S390=yes + AC_DEFINE(HAVE_CPU_S390, 1, [Define if the target CPU is a S390]) ;; + xia64*) + HAVE_CPU_IA64=yes + AC_DEFINE(HAVE_CPU_IA64, 1, [Define if the target CPU is a IA64]) ;; + xm68k*) + HAVE_CPU_M68K=yes + AC_DEFINE(HAVE_CPU_M68K, 1, [Define if the target CPU is a M68K]) ;; + xx86_64) + HAVE_CPU_X86_64=yes + AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the target CPU is a x86_64]) ;; + xcris) + HAVE_CPU_CRIS=yes + AC_DEFINE(HAVE_CPU_CRIS, 1, [Define if the target CPU is a CRIS]) ;; + xcrisv32) + HAVE_CPU_CRISV32=yes + AC_DEFINE(HAVE_CPU_CRISV32, 1, [Define if the target 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_ARC, test "x$HAVE_CPU_ARC" = "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]) + AC_DEFINE_UNQUOTED(TARGET_CPU, "$target_cpu", [the target 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*|arc*|arm*|aarch64*|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/common/m4/gst-args.m4 b/common/m4/gst-args.m4 new file mode 100644 index 0000000..0628123 --- /dev/null +++ b/common/m4/gst-args.m4 @@ -0,0 +1,386 @@ +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 + +dnl AG_GST_ARG_DISABLE_FATAL_WARNINGS +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") + 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="$CFLAGS -O0" + AC_SUBST(CFLAGS) + CXXFLAGS="$CXXFLAGS -O0" + AC_SUBST(CXXFLAGS) + FFLAGS="$FFLAGS -O0" + AC_SUBST(FFLAGS) + CCASFLAGS="$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="" + GST_PLUGINS_NONPORTED="" + + AC_SUBST(GST_PLUGINS_ALL) + AC_SUBST(GST_PLUGINS_SELECTED) + AC_SUBST(GST_PLUGINS_NONPORTED) +]) + +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]) + + dnl First check inclusion + if [[ -z "$WITH_PLUGINS" ]] || echo " [$WITH_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED="$GST_PLUGINS_SELECTED [$1]" + fi + dnl Then check exclusion + if echo " [$WITHOUT_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + fi + dnl Finally check if the plugin is ported or not + if echo " [$GST_PLUGINS_NONPORTED] " | 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]) + ]) +]) + +dnl allow people (or build tools) to override default behaviour +dnl for fatal compiler warnings +dnl Enable fatal warnings by default only for development versions +AC_DEFUN([AG_GST_ARG_DISABLE_FATAL_WARNINGS], +[ + AC_ARG_ENABLE(fatal-warnings, + AC_HELP_STRING([--disable-fatal-warnings], + [Don't turn compiler warnings into fatal errors]), + [ + case "${enableval}" in + yes) FATAL_WARNINGS=yes ;; + no) FATAL_WARNINGS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-fatal-warnings) ;; + esac + ], + [ + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + FATAL_WARNINGS=yes + else + FATAL_WARNINGS=no + fi + ]) +]) + +dnl Enable extra checks by default only for development versions +AC_DEFUN([AG_GST_ARG_ENABLE_EXTRA_CHECKS], +[ + AC_ARG_ENABLE(extra-check, + AC_HELP_STRING([--enable-extra-checks], + [Enable extra runtime checks]), + [ + case "${enableval}" in + yes) EXTRA_CHECKS=yes ;; + no) EXTRA_CHECKS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-extra-checks) ;; + esac + ], + [ + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + EXTRA_CHECKS=yes + else + EXTRA_CHECKS=no + fi + ]) + + if test "x$EXTRA_CHECKS" = "xyes"; then + AC_DEFINE(GST_ENABLE_EXTRA_CHECKS, 1, [Define if extra runtime checks should be enabled]) + fi +]) diff --git a/common/m4/gst-check.m4 b/common/m4/gst-check.m4 new file mode 100644 index 0000000..4277053 --- /dev/null +++ b/common/m4/gst-check.m4 @@ -0,0 +1,294 @@ +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_CONTROLLER([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_NET([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_CONTROLLER], +[ + AG_GST_CHECK_MODULES(GST_CONTROLLER, gstreamer-controller-[$1], [$2], + [GStreamer Controller Library], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_NET], +[ + AG_GST_CHECK_MODULES(GST_NET, gstreamer-net-[$1], [$2], + [GStreamer Network 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_UNINSTALLED_SETUP([ACTION-IF-UNINSTALLED], [ACTION-IF-NOT]) +dnl +dnl ACTION-IF-UNINSTALLED (optional) extra actions to perform if the setup +dnl is an uninstalled setup +dnl ACTION-IF-NOT (optional) extra actions to perform if the setup +dnl is not an uninstalled setup +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_UNINSTALLED_SETUP], +[ + AC_MSG_CHECKING([whether this is an uninstalled GStreamer setup]) + AC_CACHE_VAL(gst_cv_is_uninstalled_setup,[ + gst_cv_is_uninstalled_setup=no + if (set -u; : $GST_PLUGIN_SYSTEM_PATH) 2>/dev/null ; then + if test -z "$GST_PLUGIN_SYSTEM_PATH" \ + -a -n "$GST_PLUGIN_SCANNER" \ + -a -n "$GST_PLUGIN_PATH" \ + -a -n "$GST_REGISTRY" \ + -a -n "$DYLD_LIBRARY_PATH" \ + -a -n "$LD_LIBRARY_PATH"; then + gst_cv_is_uninstalled_setup=yes; + fi + fi + ]) + AC_MSG_RESULT($gst_cv_is_uninstalled_setup) + if test "x$gst_cv_is_uninstalled_setup" = "xyes"; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_BASE([GST-API_VERSION], [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-API_VERSION], [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-API_VERSION], [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-API_VERSION], [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_LIBAV([GST-API_VERSION], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_LIBAV_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -libav 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_LIBAV], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_LIBAV, gstreamer-plugins-libav-[$1], [$2], + [GStreamer Libav Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_LIBAV" = "xyes"; then + dnl check for where libav plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_LIBAV_DIR; then + GST_PLUGINS_LIBAV_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-libav-[$1]` + if test -z $GST_PLUGINS_LIBAV_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Libav Plugins pkg-config file]) + fi + fi + GST_PLUGINS_LIBAV_DIR="$GST_PLUGINS_LIBAV_DIR/ext/libav" + AC_MSG_NOTICE([using GStreamer Libav Plugins in $GST_PLUGINS_LIBAV_DIR]) + AC_SUBST(GST_PLUGINS_LIBAV_DIR) + fi +]) diff --git a/common/m4/gst-debuginfo.m4 b/common/m4/gst-debuginfo.m4 new file mode 100644 index 0000000..b48854d --- /dev/null +++ b/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/common/m4/gst-default.m4 b/common/m4/gst-default.m4 new file mode 100644 index 0000000..8de9756 --- /dev/null +++ b/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/common/m4/gst-doc.m4 b/common/m4/gst-doc.m4 new file mode 100644 index 0000000..5d3f0fd --- /dev/null +++ b/common/m4/gst-doc.m4 @@ -0,0 +1,92 @@ +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_API_VERSION" + + 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_XSLTPROC, xsltproc, yes, no) + AC_CHECK_PROG(HAVE_JADETEX, jadetex, yes, no) + AC_CHECK_PROG(HAVE_PS2PDF, ps2pdf, yes, no) + + 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) + + 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_XSLTPROC" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "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_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/common/m4/gst-dowhile.m4 b/common/m4/gst-dowhile.m4 new file mode 100644 index 0000000..069808d --- /dev/null +++ b/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/common/m4/gst-error.m4 b/common/m4/gst-error.m4 new file mode 100644 index 0000000..0067588 --- /dev/null +++ b/common/m4/gst-error.m4 @@ -0,0 +1,221 @@ +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") + 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") + ]) + 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 WARNING_OBJCFLAGS and ERROR_OBJCFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_OBJCFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_OBJCFLAGS 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_OBJCFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_OBJCFLAGS], +[ + AC_REQUIRE([AC_PROG_OBJC]) + AC_REQUIRE([AS_OBJC_COMPILER_FLAG]) + + ERROR_OBJCFLAGS="" + WARNING_OBJCFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_OBJC_COMPILER_FLAG(-Wall, WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS -Wall") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_OBJC_COMPILER_FLAG(-Werror, ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -Werror") + + if test "x$ERROR_OBJCFLAGS" != "x" + then + 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_OBJC_COMPILER_FLAG([-fno-strict-aliasing], + ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -fno-strict-aliasing") + ]) + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_OBJC_COMPILER_FLAG($each, + WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_OBJCFLAGS) + AC_SUBST(ERROR_OBJCFLAGS) + AC_MSG_NOTICE([set WARNING_OBJCFLAGS to $WARNING_OBJCFLAGS]) + AC_MSG_NOTICE([set ERROR_OBJCFLAGS to $ERROR_OBJCFLAGS]) +]) + +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/common/m4/gst-feature.m4 b/common/m4/gst-feature.m4 new file mode 100644 index 0000000..876215e --- /dev/null +++ b/common/m4/gst-feature.m4 @@ -0,0 +1,297 @@ +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 *** Check if it is ported or not +if echo " [$GST_PLUGINS_NONPORTED] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + USE_[$1]="no" + AC_MSG_WARN(*** $3 not ported) +fi + +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 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-1.0`"/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 AG_GST_CHECK_GST_DEBUG_DISABLED(ACTION-IF-DISABLED, ACTION-IF-NOT-DISABLED) +dnl +dnl Checks if the GStreamer debugging system is disabled in the core version +dnl we are compiling against (by checking gstconfig.h) +dnl +AC_DEFUN([AG_GST_CHECK_GST_DEBUG_DISABLED], +[ + AC_REQUIRE([AG_GST_CHECK_GST]) + + AC_MSG_CHECKING([whether the GStreamer debugging system is enabled]) + AC_LANG_PUSH([C]) + save_CFLAGS="$CFLAGS" + CFLAGS="$GST_CFLAGS $CFLAGS" + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + #ifdef GST_DISABLE_GST_DEBUG + #error "debugging disabled, make compiler fail" + #endif]])], [ debug_system_enabled=yes], [debug_system_enabled=no]) + CFLAGS="$save_CFLAGS" + AC_LANG_POP([C]) + + AC_MSG_RESULT([$debug_system_enabled]) + + if test "x$debug_system_enabled" = "xyes" ; then + $2 + true + else + $1 + true + fi +]) + +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" + +printf "configure: *** Plug-ins that have NOT been ported:\n" +( for i in $GST_PLUGINS_NONPORTED; do + printf '\t'$i'\n' + 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/common/m4/gst-function.m4 b/common/m4/gst-function.m4 new file mode 100644 index 0000000..61adfd3 --- /dev/null +++ b/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/common/m4/gst-gettext.m4 b/common/m4/gst-gettext.m4 new file mode 100644 index 0000000..df817eb --- /dev/null +++ b/common/m4/gst-gettext.m4 @@ -0,0 +1,28 @@ +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 make sure po/Makevars is kept in sync with GETTEXT_PACKAGE + if test -e "${srcdir}/po/Makevars"; then + if ! grep -e "$1" "${srcdir}/po/Makevars"; then + AC_MSG_ERROR([DOMAIN in po/Makevars does not match GETTEXT_PACKAGE $1]) + fi + fi + + dnl define LOCALEDIR in config.h + AS_AC_EXPAND(LOCALEDIR, $datadir/locale) + AC_DEFINE_UNQUOTED([LOCALEDIR], "$LOCALEDIR", + [gettext locale dir]) +]) diff --git a/common/m4/gst-glib2.m4 b/common/m4/gst-glib2.m4 new file mode 100644 index 0000000..5b72507 --- /dev/null +++ b/common/m4/gst-glib2.m4 @@ -0,0 +1,121 @@ +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 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 development versions + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "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=$enableval], + [enable_gobject_cast_checks=auto]) + + if test "x$enable_gobject_cast_checks" = "xauto"; then + dnl Turn on cast checks only for development versions + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "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/yes@:>@]], + [Enable GLib assertion]),[enable_glib_assertions=$enableval], + [enable_glib_assertions=yes]) + + if test "x$enable_glib_assertions" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_ASSERT" + fi + + dnl Find location of glib utils. People may want to or have to override these, + dnl e.g. in a cross-compile situation where PATH is a bit messed up. We need + dnl for these tools to work on the host, so can't just use the one from the + dnl GLib installation that pkg-config picks up, as that might be for a + dnl different target architecture. + dnl + dnl glib-genmarshal: + AC_MSG_CHECKING(for glib-genmarshal) + if test "x$GLIB_GENMARSHAL" != "x"; then + AC_MSG_RESULT([$GLIB_GENMARSHAL (from environment)]) + else + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + if $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + AC_MSG_RESULT([$GLIB_GENMARSHAL (from pkg-config path)]) + else + AC_PATH_PROG(GLIB_GENMARSHAL, [glib-genmarshal], [glib-genmarshal]) + AC_MSG_RESULT([$GLIB_GENMARSHAL]) + fi + fi + if ! $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + AC_MSG_WARN([$GLIB_GENMARSHAL does not seem to work!]) + fi + AC_SUBST(GLIB_GENMARSHAL) + + dnl glib-mkenums: + AC_MSG_CHECKING(for glib-mkenums) + if test "x$GLIB_MKENUMS" != "x"; then + AC_MSG_RESULT([$GLIB_MKENUMS (from environment)]) + else + dnl glib-mkenums is written in perl so should always work really + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + AC_MSG_RESULT([$GLIB_MKENUMS]) + fi + if ! $GLIB_MKENUMS --version 2>/dev/null >/dev/null; then + AC_MSG_WARN([$GLIB_MKENUMS does not seem to work!]) + fi + AC_SUBST(GLIB_MKENUMS) + + AC_SUBST(GLIB_EXTRA_CFLAGS) + + dnl Now check for GIO + PKG_CHECK_MODULES(GIO, gio-2.0 >= $GLIB_REQ) + if test "x$HAVE_GIO" = "xno"; then + AC_MSG_ERROR([This package requires GIO >= $GLIB_REQ to compile.]) + fi + + 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.]) + GIO_PREFIX="`$PKG_CONFIG --variable=prefix gio-2.0`" + AC_DEFINE_UNQUOTED(GIO_PREFIX, "$GIO_PREFIX", + [The GIO install prefix.]) + + AC_SUBST(GIO_CFLAGS) + AC_SUBST(GIO_LIBS) + AC_SUBST(GIO_LDFLAGS) +]) diff --git a/common/m4/gst-libxml2.m4 b/common/m4/gst-libxml2.m4 new file mode 100644 index 0000000..4a843f0 --- /dev/null +++ b/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/common/m4/gst-package-release-datetime.m4 b/common/m4/gst-package-release-datetime.m4 new file mode 100644 index 0000000..4cf44e6 --- /dev/null +++ b/common/m4/gst-package-release-datetime.m4 @@ -0,0 +1,93 @@ +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([no]...) + 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([yes], [YYYY-MM-DD]) + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [DOAP-FILE], [RELEASE-VERSION]) +changequote(<<, >>)dnl + if ( echo $2 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then +changequote([, ])dnl + GST_PACKAGE_RELEASE_DATETIME=$2 + 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]) +changequote(<<, >>)dnl + elif ( echo $1 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then +changequote([, ])dnl + 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/common/m4/gst-parser.m4 b/common/m4/gst-parser.m4 new file mode 100644 index 0000000..382ef72 --- /dev/null +++ b/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 >= 2.4 for the '<>' support + dnl in the parser. + dnl First lines observed: 'bison (GNU Bison) 2.3' or 'GNU Bison version 1.28' + bison_min_version=2.4 + 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 | awk '{print $2}'` + 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/common/m4/gst-platform.m4 b/common/m4/gst-platform.m4 new file mode 100644 index 0000000..40d6faf --- /dev/null +++ b/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/common/m4/gst-plugin-docs.m4 b/common/m4/gst-plugin-docs.m4 new file mode 100644 index 0000000..0e2ab6e --- /dev/null +++ b/common/m4/gst-plugin-docs.m4 @@ -0,0 +1,25 @@ +dnl AG_GST_PLUGIN_DOCS([MINIMUM-GTK-DOC-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_REQUIRE([AM_PATH_PYTHON])dnl find python first + + build_plugin_docs=no + AC_MSG_CHECKING([whether to build plugin documentation]) + if test x$enable_gtk_doc = xyes; then + if test x$PYTHON != x; then + build_plugin_docs=yes + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no (python not found)]) + fi + 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/common/m4/gst-plugindir.m4 b/common/m4/gst-plugindir.m4 new file mode 100644 index 0000000..c9e1301 --- /dev/null +++ b/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_API_VERSION) + 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_API_VERSION" + AC_SUBST(plugindir) +]) diff --git a/common/m4/gst-valgrind.m4 b/common/m4/gst-valgrind.m4 new file mode 100644 index 0000000..5c0d608 --- /dev/null +++ b/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/common/m4/gst-x11.m4 b/common/m4/gst-x11.m4 new file mode 100644 index 0000000..c41ddff --- /dev/null +++ b/common/m4/gst-x11.m4 @@ -0,0 +1,74 @@ +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 + HAVE_X="no" + AC_CHECK_HEADER([X11/Xlib.h], [ + dnl and then the library with the most uniquitous function + AC_CHECK_LIB(X11, [XSync], [HAVE_X="yes"], [], [$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS]) + ], [], [AC_INCLUDES_DEFAULT]) + + 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/common/m4/gst.m4 b/common/m4/gst.m4 new file mode 100644 index 0000000..d4c53cb --- /dev/null +++ b/common/m4/gst.m4 @@ -0,0 +1,36 @@ +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 +dnl +dnl We call AC_CANONICAL_TARGET and AC_CANONICAL_HOST so that +dnl it is valid before AC_ARG_PROGRAM is called + +AC_DEFUN([AG_GST_INIT], +[ + m4_pattern_forbid(^_?AG_GST_) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use host_ variables + AC_REQUIRE([AC_CANONICAL_TARGET]) dnl we use target_ variables +]) + +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/common/m4/gtk-doc.m4 b/common/m4/gtk-doc.m4 new file mode 100644 index 0000000..b243f1c --- /dev/null +++ b/common/m4/gtk-doc.m4 @@ -0,0 +1,70 @@ +dnl -*- mode: autoconf -*- + +# serial 1 + +dnl Usage: +dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) +AC_DEFUN([GTK_DOC_CHECK], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + + dnl check for tools we added during development + AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check]) + AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) + AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) + + 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 $PACKAGE_NAME]))]) + dnl don't check for glib if we build glib + if test "x$PACKAGE_NAME" != "xglib"; then + dnl don't fail if someone does not have glib + PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,) + fi + dnl don't rely on sed being pulled in implicitly. Fixes Solaris build. + 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) + + dnl enable/disable output formats + AC_ARG_ENABLE([gtk-doc-html], + AS_HELP_STRING([--enable-gtk-doc-html], + [build documentation in html format [[default=yes]]]),, + [enable_gtk_doc_html=yes]) + AC_ARG_ENABLE([gtk-doc-pdf], + AS_HELP_STRING([--enable-gtk-doc-pdf], + [build documentation in pdf format [[default=no]]]),, + [enable_gtk_doc_pdf=no]) + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + + AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) + AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) +]) diff --git a/common/m4/introspection.m4 b/common/m4/introspection.m4 new file mode 100644 index 0000000..162be57 --- /dev/null +++ b/common/m4/introspection.m4 @@ -0,0 +1,96 @@ +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)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + INTROSPECTION_INIT="extern void gst_init(gint*,gchar**); gst_init(NULL,NULL);" + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + AC_SUBST(INTROSPECTION_INIT) + + 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/common/m4/orc.m4 b/common/m4/orc.m4 new file mode 100644 index 0000000..26b2459 --- /dev/null +++ b/common/m4/orc.m4 @@ -0,0 +1,70 @@ +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]) + HAVE_ORC=yes + if test "x$ORCC" = "x" ; then + AC_MSG_CHECKING(for usable orcc) + ORCC=`$PKG_CONFIG --variable=orcc orc-0.4` + dnl check whether the orcc found by pkg-config can be run from the build environment + dnl if this is not the case (e.g. when cross-compiling) fall back to orcc from PATH + AS_IF([$ORCC --version 1> /dev/null 2> /dev/null], [], [ORCC=`which orcc`]) + AC_MSG_RESULT($ORCC) + fi + AC_SUBST(ORCC) + ORCC_FLAGS="--compat $ORC_REQ" + AC_SUBST(ORCC_FLAGS) + AS_IF([test "x$ORCC" = "x"], [HAVE_ORCC=no], [HAVE_ORCC=yes]) + ], [ + 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/common/m4/pkg.m4 b/common/m4/pkg.m4 new file mode 100644 index 0000000..996e294 --- /dev/null +++ b/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/common/mangle-db.py b/common/mangle-db.py new file mode 100644 index 0000000..463e5bc --- /dev/null +++ b/common/mangle-db.py @@ -0,0 +1,71 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +Insert includes for the element-*-details.xml files into the related docbook +files. +""" + +from __future__ import print_function, unicode_literals + +import codecs +import glob +import os +import sys + +import xml.dom.minidom + +def patch(related, details): + try: + doc = xml.dom.minidom.parse(related) + except IOError: + return + + # find the insertion point + elem = None + for e in doc.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'refentry': + elem = e + break + if elem == None: + return + + elem2 = None + for e in elem.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'refsect1': + id = e.getAttributeNode('id') + role = e.getAttributeNode('role') + if id and id.nodeValue.endswith('.description') and role and role.nodeValue == 'desc': + elem2 = e + break + if elem2 == None: + return + + # insert include + include = doc.createElement('include') + include.setAttribute('xmlns', 'http://www.w3.org/2003/XInclude') + include.setAttribute('href', details) + fallback = doc.createElement('fallback') + fallback.setAttribute('xmlns', 'http://www.w3.org/2003/XInclude') + include.appendChild(fallback) + elem2.appendChild(include) + + # store patched file + result = codecs.open(related, mode="w", encoding="utf-8") + #result = open(related, "wb") + doc.writexml(result) + result.close() + +def main(): + if not len(sys.argv) == 2: + sys.stderr.write('Please specify the xml/ dir') + sys.exit(1) + + xmldir = sys.argv[1] + + # parse all *-details.xml files and patch includes into the corresponding + # xml files + for details in glob.glob("%s/element-*-details.xml" % xmldir): + patch (details.replace("-details", ""), os.path.basename(details)) + +main() diff --git a/common/orc.mak b/common/orc.mak new file mode 100644 index 0000000..3d35488 --- /dev/null +++ b/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_@AM_V@) +orcc_v_gen_ = $(orcc_v_gen_@AM_DEFAULT_V@) +orcc_v_gen_0 = @echo " ORCC $@"; + +cp_v_gen = $(cp_v_gen_@AM_V@) +cp_v_gen_ = $(cp_v_gen_@AM_DEFAULT_V@) +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/common/parallel-subdirs.mak b/common/parallel-subdirs.mak new file mode 100644 index 0000000..36885df --- /dev/null +++ b/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/common/plugins.xsl b/common/plugins.xsl new file mode 100644 index 0000000..2c50203 --- /dev/null +++ b/common/plugins.xsl @@ -0,0 +1,248 @@ + + + + + + + + + + + + -plugins- + + + + + + + + + + + + + + Element Information + + + + + plugin + + + + plugin- + + + + + + + + author + + + + + + + class + + + + + + + + + + Element Pads + + + + + name + + + + + + + direction + + + + + + + presence + + + + + + + + + details + + + + + + + + + + + + + + + + + + + + + + + -plugins-tracer + + + + + + + + + + + Tracer Information + + + + + plugin + + + + plugin- + + + + + + + + + + + + + + + -plugins-plugin- + + + + + + 3 + FIXME Library + + + + + + + + + + plugin- + + + + + + + Plugin Information + + + + filename + + + + + + + version + + + + + + + run-time license + + + + + + + package + + + + + + + origin + + + + + + + + + + + + + + + + + + + + + + + Elements + + + + + + + + + + + + + + diff --git a/common/po.mak b/common/po.mak new file mode 100644 index 0000000..ee84f1e --- /dev/null +++ b/common/po.mak @@ -0,0 +1,11 @@ +# rule to download the latest .po files +download-po: $(top_srcdir)/common/download-translations + $(top_srcdir)/common/download-translations $(PACKAGE) + for f in po/*.po; do \ + num_changed=`git diff $$f | grep -e '^[+-][^+-]' | wc -l`; \ + num_date=`git diff $$f | grep -e '^[+-][^+-]' | grep POT-Creation-Date | wc -l`; \ + if [ $num_date == $num_changed ]; then \ + git checkout $$f; \ + fi; \ + done + diff --git a/common/release.mak b/common/release.mak new file mode 100644 index 0000000..78572e9 --- /dev/null +++ b/common/release.mak @@ -0,0 +1,45 @@ +# include this snippet to add a common release: target by using +# include $(top_srcdir)/common/release.mak + +release: dist + @$(MAKE) $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo + @echo "=================================================================================================" + @echo "http://gstreamer.freedesktop.org/src/$(PACKAGE)/$(PACKAGE)-$(VERSION).tar.xz" + @cat $(PACKAGE)-$(VERSION).tar.xz.sha256sum + @echo "=================================================================================================" + @if [ -d ~/releases/ ]; then \ + cp -v $(PACKAGE)-$(VERSION).tar.xz ~/releases/; \ + fi + @if [ -d ../www/data/src ]; then \ + mv -v $(PACKAGE)-$(VERSION).tar.xz ../www/data/src/$(PACKAGE)/ ; \ + mv -v $(PACKAGE)-$(VERSION).tar.xz.sha256sum ../www/data/src/$(PACKAGE)/ ; \ + elif [ -d ../../www/data/src ]; then \ + mv -v $(PACKAGE)-$(VERSION).tar.xz ../../www/data/src/$(PACKAGE)/ ; \ + mv -v $(PACKAGE)-$(VERSION).tar.xz.sha256sum ../../www/data/src/$(PACKAGE)/ ; \ + fi + @echo "=================================================================================================" + +# generate sha256 sum files +%.sha256sum: % + @sha256sum $< > $@ + +# 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 ) + +dist-hook: + @if test -f meson.build && ! $(GREP) -e "version.*'$(VERSION)'" meson.build >/dev/null ; then \ + echo "*******************************************************"; \ + echo "* meson.build needs to be updated for version $(VERSION)"; \ + echo "*******************************************************"; \ + false; \ + fi diff --git a/common/scangobj-merge.py b/common/scangobj-merge.py new file mode 100755 index 0000000..46736b4 --- /dev/null +++ b/common/scangobj-merge.py @@ -0,0 +1,314 @@ +#!/usr/bin/python +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +parse, merge and write gstdoc-scanobj files +""" + +from __future__ import print_function, unicode_literals + +import codecs +import os +import sys + +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): + self._keys = [] + dict.__init__(self) + + 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 signal.name in self._signals: + 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 arg.name in self._args: + 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 = codecs.open(filename, encoding='utf-8').readlines() + self.load_data("".join(lines)) + except IOError: + print ("WARNING - could not read from %s" % filename) + except UnicodeDecodeError as e: + print ("WARNING - could not parse %s: %s" % (filename, e)) + + def save_file(self, filename, backup=False): + """ + Save the information to the given file if the file content changed. + """ + olddata = None + try: + lines = codecs.open(filename, encoding='utf-8').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 = codecs.open(filename, "w", encoding='utf-8') + 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 o not in self._objects: + 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 o not in self._objects: + 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' + +class SingleLine(GDoc): + def __init__(self): + self._objects = [] + + def load_data(self, data): + """ + Load the .interfaces/.prerequisites lines, merge duplicates + """ + # split data on '\n' + lines = data.splitlines(); + # merge them into self._objects + for line in lines: + if line not in self._objects: + self._objects.append(line) + + def get_data(self): + lines = sorted(self._objects) + 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) + + 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') + + ifaces = SingleLine() + ifaces.load_file(modulename + '.interfaces') + ifaces.load_file(modulename + '.interfaces.new') + ifaces.save_file(modulename + '.interfaces', backup=True) + os.unlink(modulename + '.interfaces.new') + + prereq = SingleLine() + prereq.load_file(modulename + '.prerequisites') + prereq.load_file(modulename + '.prerequisites.new') + prereq.save_file(modulename + '.prerequisites', backup=True) + os.unlink(modulename + '.prerequisites.new') + +main(sys.argv) diff --git a/common/upload-doc.mak b/common/upload-doc.mak new file mode 100644 index 0000000..c1c4945 --- /dev/null +++ b/common/upload-doc.mak @@ -0,0 +1,64 @@ +# 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 X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(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; \ + \ + 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/common/win32.mak b/common/win32.mak new file mode 100644 index 0000000..5d818bd --- /dev/null +++ b/common/win32.mak @@ -0,0 +1,84 @@ +# 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_API_VERSION@.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 \ + echo "$$libdef"; \ + if test "$$libbase" != "libgstgl"; then \ + fail=1; \ + fi; \ + fi; \ + fi; \ + done ; \ + if test $$fail != 0; then \ + echo '-----------------------------------------------------------'; \ + echo 'Run this to update the .def files:'; \ + echo 'make update-exports'; \ + echo '-----------------------------------------------------------'; \ + fi; \ + exit $$fail + +update-exports: + make check-exports 2>&1 | patch -p1 + if test -f "$(top_srcdir)/win32/common/libgstgl.def"; then \ + git checkout "$(top_srcdir)/win32/common/libgstgl.def"; \ + fi + git add $(top_srcdir)/win32/common/lib*.def + git diff --cached -- $(top_srcdir)/win32/common/ + echo '^^^--- updated and staged changes above' + +# 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/compile b/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# 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. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..31e01ef --- /dev/null +++ b/config.guess @@ -0,0 +1,1463 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2017 Free Software Foundation, Inc. + +timestamp='2017-11-07' + +# This file 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 3 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, see . +# +# 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. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; + *:MidnightBSD:*:*) + echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; + *:Redox:*:*) + echo ${UNAME_MACHINE}-unknown-redox + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = hppa2.0w ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..0fcdaf2 --- /dev/null +++ b/config.h.in @@ -0,0 +1,562 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* poll doesn't work on devices */ +#undef BROKEN_POLL + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Subunit protocol result output */ +#undef ENABLE_SUBUNIT + +/* gettext package name */ +#undef GETTEXT_PACKAGE + +/* The GIO library directory. */ +#undef GIO_LIBDIR + +/* The GIO modules directory. */ +#undef GIO_MODULE_DIR + +/* The GIO install prefix. */ +#undef GIO_PREFIX + +/* GStreamer API Version */ +#undef GST_API_VERSION + +/* location of the installed gst-completion-helper */ +#undef GST_COMPLETION_HELPER_INSTALLED + +/* data dir */ +#undef GST_DATADIR + +/* Define if tracing subsystem hooks is disabled */ +#undef GST_DISABLE_GST_TRACER_HOOKS + +/* Define if option parsing is disabled */ +#undef GST_DISABLE_OPTION_PARSING + +/* Define if pipeline parsing code is disabled */ +#undef GST_DISABLE_PARSE + +/* Define if extra runtime checks should be enabled */ +#undef GST_ENABLE_EXTRA_CHECKS + +/* Extra platform specific plugin suffix */ +#undef GST_EXTRA_MODULE_SUFFIX + +/* macro to use to show function name */ +#undef GST_FUNCTION + +/* Defined if gcov is enabled to force a rebuild due to config.h changing */ +#undef GST_GCOV_ENABLED + +/* Defined when registry scanning through fork is unsafe */ +#undef GST_HAVE_UNSAFE_FORK + +/* Default errorlevel to use */ +#undef GST_LEVEL_DEFAULT + +/* GStreamer license */ +#undef GST_LICENSE + +/* package name in plugins */ +#undef GST_PACKAGE_NAME + +/* package origin */ +#undef GST_PACKAGE_ORIGIN + +/* GStreamer package release date/time for plugins as YYYY-MM-DD */ +#undef GST_PACKAGE_RELEASE_DATETIME + +/* location of the installed gst-plugin-scanner */ +#undef GST_PLUGIN_SCANNER_INSTALLED + +/* libexecdir path component, used to find plugin-scanner on relocatable + builds on windows */ +#undef GST_PLUGIN_SCANNER_SUBDIR + +/* location of the installed gst-ptp-helper */ +#undef GST_PTP_HELPER_INSTALLED + +/* Define to 1 if you have the `alarm' function. */ +#undef HAVE_ALARM + +/* Have backtrace */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#undef HAVE_CFLOCALECOPYCURRENT + +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#undef HAVE_CFPREFERENCESCOPYAPPVALUE + +/* Have clock_gettime */ +#undef HAVE_CLOCK_GETTIME + +/* Define if the target CPU is AARCH64 */ +#undef HAVE_CPU_AARCH64 + +/* Define if the target CPU is an Alpha */ +#undef HAVE_CPU_ALPHA + +/* Define if the target CPU is an ARC */ +#undef HAVE_CPU_ARC + +/* Define if the target CPU is an ARM */ +#undef HAVE_CPU_ARM + +/* Define if the target CPU is a CRIS */ +#undef HAVE_CPU_CRIS + +/* Define if the target CPU is a CRISv32 */ +#undef HAVE_CPU_CRISV32 + +/* Define if the target CPU is a HPPA */ +#undef HAVE_CPU_HPPA + +/* Define if the target CPU is an x86 */ +#undef HAVE_CPU_I386 + +/* Define if the target CPU is a IA64 */ +#undef HAVE_CPU_IA64 + +/* Define if the target CPU is a M68K */ +#undef HAVE_CPU_M68K + +/* Define if the target CPU is a MIPS */ +#undef HAVE_CPU_MIPS + +/* Define if the target CPU is a PowerPC */ +#undef HAVE_CPU_PPC + +/* Define if the target CPU is a 64 bit PowerPC */ +#undef HAVE_CPU_PPC64 + +/* Define if the target CPU is a S390 */ +#undef HAVE_CPU_S390 + +/* Define if the target CPU is a SPARC */ +#undef HAVE_CPU_SPARC + +/* Define if the target CPU is a x86_64 */ +#undef HAVE_CPU_X86_64 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the declaration of `alarm', and to 0 if you don't. + */ +#undef HAVE_DECL_ALARM + +/* Define to 1 if you have the declaration of `localtime_r', and to 0 if you + don't. */ +#undef HAVE_DECL_LOCALTIME_R + +/* Define to 1 if you have the declaration of `strdup', and to 0 if you don't. + */ +#undef HAVE_DECL_STRDUP + +/* Define to 1 if you have the declaration of `strsignal', and to 0 if you + don't. */ +#undef HAVE_DECL_STRSIGNAL + +/* Defined if we have dladdr () */ +#undef HAVE_DLADDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* libdw available */ +#undef HAVE_DW + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the `fgetpos' function. */ +#undef HAVE_FGETPOS + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#undef HAVE_FSEEKO + +/* Define to 1 if you have the `fsetpos' function. */ +#undef HAVE_FSETPOS + +/* Define to 1 if you have the `ftello' function. */ +#undef HAVE_FTELLO + +/* defined if the compiler implements __func__ */ +#undef HAVE_FUNC + +/* defined if the compiler implements __FUNCTION__ */ +#undef HAVE_FUNCTION + +/* getifaddrs() and AF_LINK is available */ +#undef HAVE_GETIFADDRS_AF_LINK + +/* Define to 1 if you have the `getline' function. */ +#undef HAVE_GETLINE + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Have GMP library */ +#undef HAVE_GMP + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Have GSL library */ +#undef HAVE_GSL + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define to 1 if the system has the type `intmax_t'. */ +#undef HAVE_INTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if exists, doesn't clash with , and + declares uintmax_t. */ +#undef HAVE_INTTYPES_H_WITH_UINTMAX + +/* Define to 1 if you have the `rt' library (-lrt). */ +#undef HAVE_LIBRT + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if the system has the type long long */ +#undef HAVE_LONG_LONG + +/* Define to 1 if the system has the type `long long int'. */ +#undef HAVE_LONG_LONG_INT + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Have a monotonic clock */ +#undef HAVE_MONOTONIC_CLOCK + +/* Defined if compiling for OSX */ +#undef HAVE_OSX + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Have posix timers */ +#undef HAVE_POSIX_TIMERS + +/* Define to 1 if you have the `ppoll' function. */ +#undef HAVE_PPOLL + +/* defined if the compiler implements __PRETTY_FUNCTION__ */ +#undef HAVE_PRETTY_FUNCTION + +/* Define to 1 if you have the header file. */ +#undef HAVE_PROCESS_H + +/* Define to 1 if you have the `pselect' function. */ +#undef HAVE_PSELECT + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Have function pthread_setname_np(const char*) */ +#undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID + +/* PTP support available */ +#undef HAVE_PTP + +/* Use capabilities for permissions in PTP helper */ +#undef HAVE_PTP_HELPER_CAPABILITIES + +/* Use setuid-root for permissions in PTP helper */ +#undef HAVE_PTP_HELPER_SETUID + +/* PTP helper setuid group */ +#undef HAVE_PTP_HELPER_SETUID_GROUP + +/* PTP helper setuid user */ +#undef HAVE_PTP_HELPER_SETUID_USER + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#undef HAVE_PTRDIFF_T + +/* Define if RDTSC is available */ +#undef HAVE_RDTSC + +/* Define to 1 if you have the `setitimer' function. */ +#undef HAVE_SETITIMER + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR is available */ +#undef HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if exists, doesn't clash with , and declares + uintmax_t. */ +#undef HAVE_STDINT_H_WITH_UINTMAX + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_EXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasestr' function. */ +#undef HAVE_STRCASESTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strsignal' function. */ +#undef HAVE_STRSIGNAL + +/* Define to 1 if `it_interval' is a member of `struct itimerspec'. */ +#undef HAVE_STRUCT_ITIMERSPEC_IT_INTERVAL + +/* Define to 1 if `it_value' is a member of `struct itimerspec'. */ +#undef HAVE_STRUCT_ITIMERSPEC_IT_VALUE + +/* Define to 1 if `tv_nsec' is a member of `struct timespec'. */ +#undef HAVE_STRUCT_TIMESPEC_TV_NSEC + +/* Define to 1 if `tv_sec' is a member of `struct timespec'. */ +#undef HAVE_STRUCT_TIMESPEC_TV_SEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PRCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIMES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Have tm_gmtoff field in struct tm */ +#undef HAVE_TM_GMTOFF + +/* Define to 1 if you have the header file. */ +#undef HAVE_UCONTEXT_H + +/* Have __uint128_t type */ +#undef HAVE_UINT128_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#undef HAVE_UNSIGNED_LONG_LONG_INT + +/* libunwind available */ +#undef HAVE_UNWIND + +/* Define if valgrind should be used */ +#undef HAVE_VALGRIND + +/* Define to 1 if you have the header file. */ +#undef HAVE_VALGRIND_VALGRIND_H + +/* Defined if compiling for Windows */ +#undef HAVE_WIN32 + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if you have the `_getpid' function. */ +#undef HAVE__GETPID + +/* Define to 1 if you have the `_strdup' function. */ +#undef HAVE__STRDUP + +/* the host CPU */ +#undef HOST_CPU + +/* library dir */ +#undef LIBDIR + +/* gettext locale dir */ +#undef LOCALEDIR + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Memory alignment to use */ +#undef MEMORY_ALIGNMENT + +/* Memory alignment by malloc default */ +#undef MEMORY_ALIGNMENT_MALLOC + +/* Memory alignment by pagesize */ +#undef MEMORY_ALIGNMENT_PAGESIZE + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* directory where plugins are located */ +#undef PLUGINDIR + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* The size of `char', as computed by sizeof. */ +#undef SIZEOF_CHAR + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `void*', as computed by sizeof. */ +#undef SIZEOF_VOIDP + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Need to define the itimerspec structure */ +#undef STRUCT_ITIMERSPEC_DEFINITION_MISSING + +/* Need to define the timespec structure */ +#undef STRUCT_TIMESPEC_DEFINITION_MISSING + +/* the target CPU */ +#undef TARGET_CPU + +/* Define if we should poison deallocated memory */ +#undef USE_POISONING + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#undef _LARGEFILE_SOURCE + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* We need at least WinXP SP2 for __stat64 */ +#undef __MSVCRT_VERSION__ + +/* clockid_t */ +#undef clockid_t + +/* Define to the widest signed integer type if and do + not define. */ +#undef intmax_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* timer_t */ +#undef timer_t diff --git a/config.rpath b/config.rpath new file mode 100755 index 0000000..c547c68 --- /dev/null +++ b/config.rpath @@ -0,0 +1,666 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2007 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + darwin*) + case $cc_basename in + xlc*) + wl='-Wl,' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + wl='-Wl,' + ;; + pgcc | pgf77 | pgf90) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + wl='-Wl,' + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we cannot use + # them. + ld_shlibs=no + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if test "$GCC" = yes ; then + : + else + case $cc_basename in + xlc*) + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd1*) + ld_shlibs=no + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix4* | aix5*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + library_names_spec='$libname.a' + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd1*) + ;; + freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + nto-qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. +# +# 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. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + wasm32) + basic_machine=wasm32-unknown + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..40dbea1 --- /dev/null +++ b/configure @@ -0,0 +1,31773 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for GStreamer 1.14.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='GStreamer' +PACKAGE_TARNAME='gstreamer' +PACKAGE_VERSION='1.14.1' +PACKAGE_STRING='GStreamer 1.14.1' +PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer' +PACKAGE_URL='' + +ac_unique_file="gst/gst.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +gt_needs= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +SUBUNIT_FALSE +SUBUNIT_TRUE +ENABLE_SUBUNIT +HAVE_CLOCK_GETTIME_FALSE +HAVE_CLOCK_GETTIME_TRUE +HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE +HAVE_TIMER_CREATE_SETTIME_DELETE_TRUE +HAVE_STRSIGNAL_FALSE +HAVE_STRSIGNAL_TRUE +HAVE_ALARM_FALSE +HAVE_ALARM_TRUE +HAVE_FORK +HAVE_GETLINE_FALSE +HAVE_GETLINE_TRUE +HAVE_STRDUP_FALSE +HAVE_STRDUP_TRUE +HAVE_GETTIMEOFDAY_FALSE +HAVE_GETTIMEOFDAY_TRUE +HAVE_LOCALTIME_R_FALSE +HAVE_LOCALTIME_R_TRUE +CHECK_VERSION +CHECK_MICRO_VERSION +CHECK_MINOR_VERSION +CHECK_MAJOR_VERSION +GST_PTP_HELPER_INSTALLED +GST_COMPLETION_HELPER_INSTALLED +GST_PLUGIN_SCANNER_INSTALLED +GST_PLUGIN_LDFLAGS +GST_OBJ_LIBS +GST_OBJ_CXXFLAGS +GST_OBJ_CFLAGS +GST_LIB_LDFLAGS +GST_ALL_LDFLAGS +GST_ALL_LIBS +GST_ALL_CXXFLAGS +GST_ALL_CFLAGS +GST_OPTION_CXXFLAGS +GST_OPTION_CFLAGS +DEPRECATED_CFLAGS +PROFILE_CFLAGS +GST_LEVEL_DEFAULT +EXTRA_CFLAGS +PRINTF_CFLAGS +ERROR_CFLAGS +WARNING_CFLAGS +plugindir +PLUGINDIR +DATADIR +LIBDIR +GST_LICENSE +HAVE_CHECK_FALSE +HAVE_CHECK_TRUE +DW_REQUIRE +DW_LIBS +DW_CFLAGS +UNWIND_REQUIRE +UNWIND_LIBS +UNWIND_CFLAGS +HAVE_GTK_FALSE +HAVE_GTK_TRUE +GTK_LIBS +GTK_CFLAGS +GLIB_PREFIX +GIO_LDFLAGS +GIO_LIBS +GIO_CFLAGS +GLIB_EXTRA_CFLAGS +GLIB_MKENUMS +GLIB_GENMARSHAL +GLIB_LIBS +GLIB_CFLAGS +GLIB_REQ +GST_HAVE_MONOTONIC_CLOCK_FALSE +GST_HAVE_MONOTONIC_CLOCK_TRUE +GST_HAVE_MONOTONIC_CLOCK_DEFINE +GST_HAVE_POSIX_TIMERS_FALSE +GST_HAVE_POSIX_TIMERS_TRUE +GST_HAVE_POSIX_TIMERS_DEFINE +SOCKET_LIBS +HAVE_GETRUSAGE_FALSE +HAVE_GETRUSAGE_TRUE +HAVE_GSL +GSL_LIBS +HAVE_GMP +GMP_LIBS +WIN32_LIBS +HAVE_WINSOCK2_H_FALSE +HAVE_WINSOCK2_H_TRUE +HAVE_PTHREAD_FALSE +HAVE_PTHREAD_TRUE +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +ax_pthread_config +HAVE_SYS_TIMES_H_AND_UNISTD_H_FALSE +HAVE_SYS_TIMES_H_AND_UNISTD_H_TRUE +HAVE_SYS_SOCKET_H_FALSE +HAVE_SYS_SOCKET_H_TRUE +LIBM +ENABLE_PLUGIN_DOCS_FALSE +ENABLE_PLUGIN_DOCS_TRUE +pkgpyexecdir +pyexecdir +pkgpythondir +pythondir +PYTHON_PLATFORM +PYTHON_EXEC_PREFIX +PYTHON_PREFIX +PYTHON_VERSION +PYTHON +GTK_DOC_USE_LIBTOOL_FALSE +GTK_DOC_USE_LIBTOOL_TRUE +GTK_DOC_BUILD_PDF_FALSE +GTK_DOC_BUILD_PDF_TRUE +GTK_DOC_BUILD_HTML_FALSE +GTK_DOC_BUILD_HTML_TRUE +ENABLE_GTK_DOC_FALSE +ENABLE_GTK_DOC_TRUE +GTKDOC_DEPS_LIBS +GTKDOC_DEPS_CFLAGS +HTML_DIR +GTKDOC_MKPDF +GTKDOC_REBASE +GTKDOC_CHECK +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +INTROSPECTION_INIT +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +HAVE_VALGRIND_FALSE +HAVE_VALGRIND_TRUE +VALGRIND_PATH +FLEX_PATH +BISON_PATH +PERL_PATH +HAVE_CXX_FALSE +HAVE_CXX_TRUE +CXXCPP +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXX +am__fastdepCCAS_FALSE +am__fastdepCCAS_TRUE +CCASDEPMODE +CCAS +HAVE_CPU_CRISV32_FALSE +HAVE_CPU_CRISV32_TRUE +HAVE_CPU_CRIS_FALSE +HAVE_CPU_CRIS_TRUE +HAVE_CPU_X86_64_FALSE +HAVE_CPU_X86_64_TRUE +HAVE_CPU_M68K_FALSE +HAVE_CPU_M68K_TRUE +HAVE_CPU_IA64_FALSE +HAVE_CPU_IA64_TRUE +HAVE_CPU_S390_FALSE +HAVE_CPU_S390_TRUE +HAVE_CPU_MIPS_FALSE +HAVE_CPU_MIPS_TRUE +HAVE_CPU_HPPA_FALSE +HAVE_CPU_HPPA_TRUE +HAVE_CPU_SPARC_FALSE +HAVE_CPU_SPARC_TRUE +HAVE_CPU_ARM_FALSE +HAVE_CPU_ARM_TRUE +HAVE_CPU_ARC_FALSE +HAVE_CPU_ARC_TRUE +HAVE_CPU_ALPHA_FALSE +HAVE_CPU_ALPHA_TRUE +HAVE_CPU_PPC64_FALSE +HAVE_CPU_PPC64_TRUE +HAVE_CPU_PPC_FALSE +HAVE_CPU_PPC_TRUE +HAVE_CPU_I386_FALSE +HAVE_CPU_I386_TRUE +HAVE_PTP_HELPER_CAPABILITIES_FALSE +HAVE_PTP_HELPER_CAPABILITIES_TRUE +HAVE_PTP_HELPER_SETUID_FALSE +HAVE_PTP_HELPER_SETUID_TRUE +HAVE_PTP_FALSE +HAVE_PTP_TRUE +SETCAP +HAVE_CAP +CAP_LIBS +BUILD_TOOLS_FALSE +BUILD_TOOLS_TRUE +BUILD_BENCHMARKS_FALSE +BUILD_BENCHMARKS_TRUE +BUILD_FAILING_TESTS_FALSE +BUILD_FAILING_TESTS_TRUE +BUILD_TESTS_FALSE +BUILD_TESTS_TRUE +ENABLE_BASH_COMPLETION_FALSE +ENABLE_BASH_COMPLETION_TRUE +BASH_HELPERS_DIR +BASH_COMPLETION_DIR +BASH_COMPLETION_LIBS +BASH_COMPLETION_CFLAGS +GSTCONFIG_BUILT_WITH_MSVC +GST_PKG_CONFIG_PATH +GST_PACKAGE_ORIGIN +GST_PACKAGE_NAME +BUILD_EXAMPLES_FALSE +BUILD_EXAMPLES_TRUE +GST_GCOV_ENABLED_FALSE +GST_GCOV_ENABLED_TRUE +CCASFLAGS +FFLAGS +CXXFLAGS +GCOV +GCOV_LIBS +GCOV_CFLAGS +VALGRIND_LIBS +VALGRIND_CFLAGS +PKG_CONFIG +GST_DISABLE_PLUGIN_FALSE +GST_DISABLE_PLUGIN_TRUE +GST_DISABLE_PLUGIN_DEFINE +GST_REGISTRY_DOC_TYPES +GST_DISABLE_REGISTRY_FALSE +GST_DISABLE_REGISTRY_TRUE +GST_DISABLE_REGISTRY_DEFINE +GST_DISABLE_OPTION_PARSING_FALSE +GST_DISABLE_OPTION_PARSING_TRUE +GST_DISABLE_OPTION_PARSING_DEFINE +GST_DISABLE_PARSE_FALSE +GST_DISABLE_PARSE_TRUE +GST_DISABLE_PARSE_DEFINE +GST_DISABLE_GST_TRACER_HOOKS_FALSE +GST_DISABLE_GST_TRACER_HOOKS_TRUE +GST_DISABLE_GST_TRACER_HOOKS_DEFINE +GST_DISABLE_GST_DEBUG_FALSE +GST_DISABLE_GST_DEBUG_TRUE +GST_DISABLE_GST_DEBUG_DEFINE +LOCALEDIR +GETTEXT_PACKAGE +POSUB +LTLIBINTL +LIBINTL +INTLLIBS +LTLIBICONV +LIBICONV +INTL_MACOSX_LIBS +XGETTEXT_EXTRA_OPTIONS +MSGMERGE +XGETTEXT_015 +XGETTEXT +GMSGFMT_015 +MSGFMT_015 +GMSGFMT +MSGFMT +GETTEXT_MACRO_VERSION +USE_NLS +ACLOCAL_AMFLAGS +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +LIBTOOL +OBJDUMP +DLLTOOL +AS +GST_LT_LDFLAGS +GST_LIBVERSION +GST_AGE +GST_REVISION +GST_CURRENT +GST_API_VERSION +GST_VERSION_NANO +GST_VERSION_MICRO +GST_VERSION_MINOR +GST_VERSION_MAJOR +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +PACKAGE_VERSION_RELEASE +PACKAGE_VERSION_NANO +PACKAGE_VERSION_MICRO +PACKAGE_VERSION_MINOR +PACKAGE_VERSION_MAJOR +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +enable_dependency_tracking +with_gnu_ld +with_sysroot +enable_libtool_lock +with_autoconf +with_autoheader +with_automake +with_aclocal +enable_nls +enable_rpath +with_libiconv_prefix +with_libintl_prefix +enable_fatal_warnings +enable_extra_check +enable_gst_debug +enable_gst_tracer_hooks +enable_parse +enable_option_parsing +enable_registry +enable_plugin +enable_debug +enable_profiling +enable_valgrind +enable_gcov +enable_examples +with_pkg_config_path +with_package_name +with_package_origin +with_bash_completion_dir +enable_tests +enable_failing_tests +enable_benchmarks +enable_tools +enable_poisoning +with_ptp_helper_setuid_user +with_ptp_helper_setuid_group +with_ptp_helper_permissions +enable_largefile +enable_introspection +with_html_dir +enable_gtk_doc +enable_gtk_doc_html +enable_gtk_doc_pdf +enable_gobject_cast_checks +enable_glib_asserts +with_unwind +with_dw +enable_check +with_memory_alignment +enable_Bsymbolic +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +PKG_CONFIG +VALGRIND_CFLAGS +VALGRIND_LIBS +BASH_COMPLETION_CFLAGS +BASH_COMPLETION_LIBS +CCAS +CCASFLAGS +CXX +CXXFLAGS +CCC +CXXCPP +GTKDOC_DEPS_CFLAGS +GTKDOC_DEPS_LIBS +PYTHON +GLIB_CFLAGS +GLIB_LIBS +GIO_CFLAGS +GIO_LIBS +GTK_CFLAGS +GTK_LIBS +UNWIND_CFLAGS +UNWIND_LIBS +DW_CFLAGS +DW_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures GStreamer 1.14.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/gstreamer] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of GStreamer 1.14.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --disable-maintainer-mode + disable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-nls do not use Native Language Support + --disable-rpath do not hardcode runtime library paths + --disable-fatal-warnings + Don't turn compiler warnings into fatal errors + --enable-extra-checks Enable extra runtime checks + --disable-gst-debug disable debugging subsystem + --disable-gst-tracer-hooks + disable tracing subsystem hooks + --disable-parse disable command-line parser + --disable-option-parsing + disable option parsing when gst_init + --disable-registry disable plugin registry + --disable-plugin disable plugin + --disable-debug disable addition of -g debugging info + --enable-profiling adds -pg to compiler commandline, for profiling + --disable-valgrind disable run-time valgrind detection + --enable-gcov compile with coverage profiling instrumentation (gcc + only) + --disable-examples disable building examples + --disable-tests disable building test apps + --disable-failing-tests disable building tests known to fail + --disable-benchmarks disable building benchmarks apps + --disable-tools disable building tools + --enable-poisoning enable poisoning of deallocated objects + --disable-largefile omit support for large files + --enable-introspection=[no/auto/yes] + Enable introspection for this build + --enable-gtk-doc use gtk-doc to build documentation [[default=no]] + --enable-gtk-doc-html build documentation in html format [[default=yes]] + --enable-gtk-doc-pdf build documentation in pdf format [[default=no]] + --enable-gobject-cast-checks=[no/auto/yes] + Enable GObject cast checks + --enable-glib-asserts=[no/yes] + Enable GLib assertion + --disable-check disable building unit test libraries + --disable-Bsymbolic avoid linking with -Bsymbolic + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-autoconf use a different autoconf for regeneration of + Makefiles + --with-autoheader use a different autoheader for regeneration of + Makefiles + --with-automake use a different automake for regeneration of + Makefiles + --with-aclocal use a different aclocal for regeneration of + Makefiles + --with-gnu-ld assume the C compiler uses GNU ld default=no + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib + --without-libintl-prefix don't search for libintl in includedir and libdir + --with-pkg-config-path colon-separated list of pkg-config(1) dirs + --with-package-name specify package name to use in plugins + --with-package-origin specify package origin URL to use in plugins + --with-bash-completion-dir=PATH + Install the bash auto-completion script in this + directory. [default=yes] + --with-ptp-helper-setuid-user + User to switch to when installing gst-ptp-helper + setuid root + --with-ptp-helper-setuid-group + Group to switch to when installing gst-ptp-helper + setuid root + --with-ptp-helper-permissions + how to gain PTP permissions (none, setuid-root, + capabilities, auto) + --with-html-dir=PATH path to installed docs + --with-unwind=yes|no|auto + use libunwind + --with-dw=yes|no|auto use libdw + --with-memory-alignment 8,N,malloc,pagesize (default is 32) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + VALGRIND_CFLAGS + C compiler flags for VALGRIND, overriding pkg-config + VALGRIND_LIBS + linker flags for VALGRIND, overriding pkg-config + BASH_COMPLETION_CFLAGS + C compiler flags for BASH_COMPLETION, overriding pkg-config + BASH_COMPLETION_LIBS + linker flags for BASH_COMPLETION, overriding pkg-config + CCAS assembler compiler command (defaults to CC) + CCASFLAGS assembler compiler flags (defaults to CFLAGS) + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + GTKDOC_DEPS_CFLAGS + C compiler flags for GTKDOC_DEPS, overriding pkg-config + GTKDOC_DEPS_LIBS + linker flags for GTKDOC_DEPS, overriding pkg-config + PYTHON the Python interpreter + GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config + GLIB_LIBS linker flags for GLIB, overriding pkg-config + GIO_CFLAGS C compiler flags for GIO, overriding pkg-config + GIO_LIBS linker flags for GIO, overriding pkg-config + GTK_CFLAGS C compiler flags for GTK, overriding pkg-config + GTK_LIBS linker flags for GTK, overriding pkg-config + UNWIND_CFLAGS + C compiler flags for UNWIND, overriding pkg-config + UNWIND_LIBS linker flags for UNWIND, overriding pkg-config + DW_CFLAGS C compiler flags for DW, overriding pkg-config + DW_LIBS linker flags for DW, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +GStreamer configure 1.14.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_preproc LINENO HEADER VAR +# ---------------------------------------------- +# Tests whether HEADER is present, setting the cache variable VAR accordingly. +ac_fn_c_check_header_preproc () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_preproc + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------------------------------ ## +## Report this to http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer ## +## ------------------------------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by GStreamer $as_me 1.14.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +gt_needs="$gt_needs " +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='gstreamer' + VERSION='1.14.1' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + + + PACKAGE_VERSION_MAJOR=$(echo 1.14.1 | cut -d'.' -f1) + PACKAGE_VERSION_MINOR=$(echo 1.14.1 | cut -d'.' -f2) + PACKAGE_VERSION_MICRO=$(echo 1.14.1 | cut -d'.' -f3) + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking nano version" >&5 +$as_echo_n "checking nano version... " >&6; } + + NANO=$(echo 1.14.1 | cut -d'.' -f4) + + if test x"$NANO" = x || test "x$NANO" = "x0" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: 0 (release)" >&5 +$as_echo "0 (release)" >&6; } + NANO=0 + PACKAGE_VERSION_RELEASE=1 + GST_GIT="no" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NANO" >&5 +$as_echo "$NANO" >&6; } + PACKAGE_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S` + if test "x$NANO" != "x1" ; then + GST_GIT="no" + else + GST_GIT="yes" + fi + fi + PACKAGE_VERSION_NANO=$NANO + + + + + + +ac_config_headers="$ac_config_headers config.h" + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +GST_VERSION_MAJOR=$PACKAGE_VERSION_MAJOR +GST_VERSION_MINOR=$PACKAGE_VERSION_MINOR +GST_VERSION_MICRO=$PACKAGE_VERSION_MICRO +GST_VERSION_NANO=$PACKAGE_VERSION_NANO + + + + + +GST_API_VERSION=1.0 + + +cat >>confdefs.h <<_ACEOF +#define GST_API_VERSION "$GST_API_VERSION" +_ACEOF + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + GST_CURRENT=1401 + GST_REVISION=0 + GST_AGE=1401 + GST_LIBVERSION=1401:0:1401 + + + + + + GST_LT_LDFLAGS="$GST_LT_LDFLAGS -version-info $GST_LIBVERSION" + if test ! -z "" + then + GST_LT_LDFLAGS="$GST_LT_LDFLAGS -release " + fi + + + + + + + +# Set options +enable_dlopen=yes +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + + + + +# Check whether --with-autoconf was given. +if test "${with_autoconf+set}" = set; then : + withval=$with_autoconf; + unset AUTOCONF + +AUTOCONF=${AUTOCONF-"${am_missing_run}${withval}"} + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $AUTOCONF as autoconf" >&5 +$as_echo "$as_me: Using $AUTOCONF as autoconf" >&6;} + +fi + + + +# Check whether --with-autoheader was given. +if test "${with_autoheader+set}" = set; then : + withval=$with_autoheader; + unset AUTOHEADER + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}${withval}"} + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $AUTOHEADER as autoheader" >&5 +$as_echo "$as_me: Using $AUTOHEADER as autoheader" >&6;} + +fi + + + +# Check whether --with-automake was given. +if test "${with_automake+set}" = set; then : + withval=$with_automake; + unset AUTOMAKE + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}${withval}"} + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $AUTOMAKE as automake" >&5 +$as_echo "$as_me: Using $AUTOMAKE as automake" >&6;} + +fi + + + +# Check whether --with-aclocal was given. +if test "${with_aclocal+set}" = set; then : + withval=$with_aclocal; + unset ACLOCAL + +ACLOCAL=${ACLOCAL-"${am_missing_run}${withval}"} + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $ACLOCAL as aclocal" >&5 +$as_echo "$as_me: Using $ACLOCAL as aclocal" >&6;} + +fi + + + +ACLOCAL_AMFLAGS="-I m4 -I common/m4" + + + + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.17 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 +$as_echo_n "checking for ld used by GCC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$acl_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : +else + enable_rpath=yes +fi + + + + acl_libdirstem=lib + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBICONV_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +$as_echo_n "checking for GNU gettext in libc... " >&6; } +if eval \${$gt_func_gnugettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libc=yes" +else + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int main () +{ + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + return 1; + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + return 1; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +else + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test "${with_libintl_prefix+set}" = set; then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBINTL_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +$as_echo_n "checking for GNU gettext in libintl... " >&6; } +if eval \${$gt_func_gnugettext_libintl+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libintl=yes" +else + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +$as_echo_n "checking whether to use NLS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +$as_echo_n "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +$as_echo "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +$as_echo_n "checking how to link with libintl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +$as_echo "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + +$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + + INTLLIBS="$LIBINTL" + + + + + + + + if test "$USE_NLS" = "yes"; then + GETTEXT_PACKAGE=gstreamer-$GST_API_VERSION + else + GETTEXT_PACKAGE=NULL + fi + + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + + if test -e "${srcdir}/po/Makevars"; then + if ! grep -e "gstreamer-$GST_API_VERSION" "${srcdir}/po/Makevars"; then + as_fn_error $? "DOMAIN in po/Makevars does not match GETTEXT_PACKAGE gstreamer-$GST_API_VERSION" "$LINENO" 5 + fi + fi + + + EXP_VAR=LOCALEDIR + FROM_VAR=$datadir/locale + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + LOCALEDIR="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define LOCALEDIR "$LOCALEDIR" +_ACEOF + + + + + + # Check whether --enable-fatal-warnings was given. +if test "${enable_fatal_warnings+set}" = set; then : + enableval=$enable_fatal_warnings; + case "${enableval}" in + yes) FATAL_WARNINGS=yes ;; + no) FATAL_WARNINGS=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-fatal-warnings" "$LINENO" 5 ;; + esac + +else + + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + FATAL_WARNINGS=yes + else + FATAL_WARNINGS=no + fi + +fi + + + + # Check whether --enable-extra-check was given. +if test "${enable_extra_check+set}" = set; then : + enableval=$enable_extra_check; + case "${enableval}" in + yes) EXTRA_CHECKS=yes ;; + no) EXTRA_CHECKS=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-extra-checks" "$LINENO" 5 ;; + esac + +else + + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + EXTRA_CHECKS=yes + else + EXTRA_CHECKS=no + fi + +fi + + + if test "x$EXTRA_CHECKS" = "xyes"; then + +$as_echo "#define GST_ENABLE_EXTRA_CHECKS 1" >>confdefs.h + + fi + + + + + + # Check whether --enable-gst-debug was given. +if test "${enable_gst_debug+set}" = set; then : + enableval=$enable_gst_debug; + case "${enableval}" in + yes) GST_DISABLE_GST_DEBUG=no ;; + no) GST_DISABLE_GST_DEBUG=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-gst-debug" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_GST_DEBUG=no +fi + + if test x$GST_DISABLE_GST_DEBUG = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem debugging subsystem" >&5 +$as_echo "$as_me: disabled subsystem debugging subsystem" >&6;} + GST_DISABLE_GST_DEBUG_DEFINE="#define GST_DISABLE_GST_DEBUG 1" + else + GST_DISABLE_GST_DEBUG_DEFINE="/* #undef GST_DISABLE_GST_DEBUG */" + fi + + + + if test "x$GST_DISABLE_GST_DEBUG" = "xyes"; then + GST_DISABLE_GST_DEBUG_TRUE= + GST_DISABLE_GST_DEBUG_FALSE='#' +else + GST_DISABLE_GST_DEBUG_TRUE='#' + GST_DISABLE_GST_DEBUG_FALSE= +fi + + + + + # Check whether --enable-gst-tracer-hooks was given. +if test "${enable_gst_tracer_hooks+set}" = set; then : + enableval=$enable_gst_tracer_hooks; + case "${enableval}" in + yes) GST_DISABLE_GST_TRACER_HOOKS=no ;; + no) GST_DISABLE_GST_TRACER_HOOKS=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-gst-tracer-hooks" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_GST_TRACER_HOOKS=no +fi + + if test x$GST_DISABLE_GST_TRACER_HOOKS = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem tracing subsystem hooks" >&5 +$as_echo "$as_me: disabled subsystem tracing subsystem hooks" >&6;} + GST_DISABLE_GST_TRACER_HOOKS_DEFINE="#define GST_DISABLE_GST_TRACER_HOOKS 1" + else + GST_DISABLE_GST_TRACER_HOOKS_DEFINE="/* #undef GST_DISABLE_GST_TRACER_HOOKS */" + fi + + + + if test "x$GST_DISABLE_GST_TRACER_HOOKS" = "xyes"; then + GST_DISABLE_GST_TRACER_HOOKS_TRUE= + GST_DISABLE_GST_TRACER_HOOKS_FALSE='#' +else + GST_DISABLE_GST_TRACER_HOOKS_TRUE='#' + GST_DISABLE_GST_TRACER_HOOKS_FALSE= +fi + +if test "x$GST_DISABLE_GST_TRACER_HOOKS" = xyes; then + +$as_echo "#define GST_DISABLE_GST_TRACER_HOOKS 1" >>confdefs.h + +fi + + + + # Check whether --enable-parse was given. +if test "${enable_parse+set}" = set; then : + enableval=$enable_parse; + case "${enableval}" in + yes) GST_DISABLE_PARSE=no ;; + no) GST_DISABLE_PARSE=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-parse" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_PARSE=no +fi + + if test x$GST_DISABLE_PARSE = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem command-line parser" >&5 +$as_echo "$as_me: disabled subsystem command-line parser" >&6;} + GST_DISABLE_PARSE_DEFINE="#define GST_DISABLE_PARSE 1" + else + GST_DISABLE_PARSE_DEFINE="/* #undef GST_DISABLE_PARSE */" + fi + + + + if test "x$GST_DISABLE_PARSE" = "xyes"; then + GST_DISABLE_PARSE_TRUE= + GST_DISABLE_PARSE_FALSE='#' +else + GST_DISABLE_PARSE_TRUE='#' + GST_DISABLE_PARSE_FALSE= +fi + +if test "x$GST_DISABLE_PARSE" = xyes; then + +$as_echo "#define GST_DISABLE_PARSE 1" >>confdefs.h + +fi + + + + # Check whether --enable-option-parsing was given. +if test "${enable_option_parsing+set}" = set; then : + enableval=$enable_option_parsing; + case "${enableval}" in + yes) GST_DISABLE_OPTION_PARSING=no ;; + no) GST_DISABLE_OPTION_PARSING=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-option-parsing" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_OPTION_PARSING=no +fi + + if test x$GST_DISABLE_OPTION_PARSING = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem option parsing when gst_init" >&5 +$as_echo "$as_me: disabled subsystem option parsing when gst_init" >&6;} + GST_DISABLE_OPTION_PARSING_DEFINE="#define GST_DISABLE_OPTION_PARSING 1" + else + GST_DISABLE_OPTION_PARSING_DEFINE="/* #undef GST_DISABLE_OPTION_PARSING */" + fi + + + + if test "x$GST_DISABLE_OPTION_PARSING" = "xyes"; then + GST_DISABLE_OPTION_PARSING_TRUE= + GST_DISABLE_OPTION_PARSING_FALSE='#' +else + GST_DISABLE_OPTION_PARSING_TRUE='#' + GST_DISABLE_OPTION_PARSING_FALSE= +fi + +if test "x$GST_DISABLE_OPTION_PARSING" = xyes; then + +$as_echo "#define GST_DISABLE_OPTION_PARSING 1" >>confdefs.h + +fi + + + + # Check whether --enable-registry was given. +if test "${enable_registry+set}" = set; then : + enableval=$enable_registry; + case "${enableval}" in + yes) GST_DISABLE_REGISTRY=no ;; + no) GST_DISABLE_REGISTRY=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-registry" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_REGISTRY=no +fi + + if test x$GST_DISABLE_REGISTRY = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem plugin registry" >&5 +$as_echo "$as_me: disabled subsystem plugin registry" >&6;} + GST_DISABLE_REGISTRY_DEFINE="#define GST_DISABLE_REGISTRY 1" + else + GST_DISABLE_REGISTRY_DEFINE="/* #undef GST_DISABLE_REGISTRY */" + fi + + + + if test "x$GST_DISABLE_REGISTRY" = "xyes"; then + GST_DISABLE_REGISTRY_TRUE= + GST_DISABLE_REGISTRY_FALSE='#' +else + GST_DISABLE_REGISTRY_TRUE='#' + GST_DISABLE_REGISTRY_FALSE= +fi + +if test "x$GST_DISABLE_REGISTRY" = "xyes" +then + GST_REGISTRY_DOC_TYPES="%" +else + GST_REGISTRY_DOC_TYPES= +fi + + + + + # Check whether --enable-plugin was given. +if test "${enable_plugin+set}" = set; then : + enableval=$enable_plugin; + case "${enableval}" in + yes) GST_DISABLE_PLUGIN=no ;; + no) GST_DISABLE_PLUGIN=yes ;; + *) as_fn_error $? "bad value ${enableval} for --enable-plugin" "$LINENO" 5 ;; + esac + +else + GST_DISABLE_PLUGIN=no +fi + + if test x$GST_DISABLE_PLUGIN = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: disabled subsystem plugin" >&5 +$as_echo "$as_me: disabled subsystem plugin" >&6;} + GST_DISABLE_PLUGIN_DEFINE="#define GST_DISABLE_PLUGIN 1" + else + GST_DISABLE_PLUGIN_DEFINE="/* #undef GST_DISABLE_PLUGIN */" + fi + + + + if test "x$GST_DISABLE_PLUGIN" = "xyes"; then + GST_DISABLE_PLUGIN_TRUE= + GST_DISABLE_PLUGIN_FALSE='#' +else + GST_DISABLE_PLUGIN_TRUE='#' + GST_DISABLE_PLUGIN_FALSE= +fi + + + + # Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; + case "${enableval}" in + yes) USE_DEBUG=yes ;; + no) USE_DEBUG=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;; + esac + +else + USE_DEBUG=yes +fi + + + # Check whether --enable-profiling was given. +if test "${enable_profiling+set}" = set; then : + enableval=$enable_profiling; + case "${enableval}" in + yes) USE_PROFILING=yes ;; + no) USE_PROFILING=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-profiling" "$LINENO" 5 ;; + esac + +else + USE_PROFILING=no +fi + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi + +fi + + # Check whether --enable-valgrind was given. +if test "${enable_valgrind+set}" = set; then : + enableval=$enable_valgrind; + case "${enableval}" in + yes) USE_VALGRIND="$USE_DEBUG" ;; + no) USE_VALGRIND=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-valgrind" "$LINENO" 5 ;; + esac + +else + USE_VALGRIND="$USE_DEBUG" +fi + VALGRIND_REQ="3.0" + if test "x$USE_VALGRIND" = xyes; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND" >&5 +$as_echo_n "checking for VALGRIND... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$VALGRIND_CFLAGS"; then + pkg_cv_VALGRIND_CFLAGS="$VALGRIND_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind >= \$VALGRIND_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "valgrind >= $VALGRIND_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VALGRIND_CFLAGS=`$PKG_CONFIG --cflags "valgrind >= $VALGRIND_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$VALGRIND_LIBS"; then + pkg_cv_VALGRIND_LIBS="$VALGRIND_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind >= \$VALGRIND_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "valgrind >= $VALGRIND_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VALGRIND_LIBS=`$PKG_CONFIG --libs "valgrind >= $VALGRIND_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + VALGRIND_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "valgrind >= $VALGRIND_REQ"` + else + VALGRIND_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "valgrind >= $VALGRIND_REQ"` + fi + # Put the nasty error message in config.log where it belongs + echo "$VALGRIND_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + USE_VALGRIND="no" +elif test $pkg_failed = untried; then + USE_VALGRIND="no" +else + VALGRIND_CFLAGS=$pkg_cv_VALGRIND_CFLAGS + VALGRIND_LIBS=$pkg_cv_VALGRIND_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + USE_VALGRIND="yes" +fi + fi + if test "x$USE_VALGRIND" = xyes; then + +$as_echo "#define HAVE_VALGRIND 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using extra code paths for valgrind" >&5 +$as_echo "$as_me: Using extra code paths for valgrind" >&6;} + fi + + + # Check whether --enable-gcov was given. +if test "${enable_gcov+set}" = set; then : + enableval=$enable_gcov; enable_gcov=$enableval +else + enable_gcov=no +fi + + if test x$enable_gcov = xyes ; then + if test "x$GCC" != "xyes" + then + as_fn_error $? "gcov only works if gcc is used" "$LINENO" 5 + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands \"-fprofile-arcs\"" >&5 +$as_echo_n "checking to see if compiler understands \"-fprofile-arcs\"... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS "-fprofile-arcs"" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs" + true + else + true + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands \"-ftest-coverage\"" >&5 +$as_echo_n "checking to see if compiler understands \"-ftest-coverage\"... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS "-ftest-coverage"" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + GCOV_CFLAGS="$GCOV_CFLAGS -ftest-coverage" + true + else + true + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[0-9]*//g'` + GCOV_LIBS=-lgcov + + + GCOV=`echo $CC | sed s/gcc/gcov/g` + + + GST_GCOV_ENABLED=yes + +cat >>confdefs.h <<_ACEOF +#define GST_GCOV_ENABLED 1 +_ACEOF + + if test "x$GST_GCOV_ENABLED" = "xyes" + then + CFLAGS="$CFLAGS -O0" + + CXXFLAGS="$CXXFLAGS -O0" + + FFLAGS="$FFLAGS -O0" + + CCASFLAGS="$CCASFLAGS -O0" + + { $as_echo "$as_me:${as_lineno-$LINENO}: gcov enabled, setting CFLAGS and friends to $CFLAGS" >&5 +$as_echo "$as_me: gcov enabled, setting CFLAGS and friends to $CFLAGS" >&6;} + fi + fi + if test x$enable_gcov = xyes; then + GST_GCOV_ENABLED_TRUE= + GST_GCOV_ENABLED_FALSE='#' +else + GST_GCOV_ENABLED_TRUE='#' + GST_GCOV_ENABLED_FALSE= +fi + + + + + # Check whether --enable-examples was given. +if test "${enable_examples+set}" = set; then : + enableval=$enable_examples; + case "${enableval}" in + yes) BUILD_EXAMPLES=yes ;; + no) BUILD_EXAMPLES=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-examples" "$LINENO" 5 ;; + esac + +else + BUILD_EXAMPLES=yes +fi + if test "x$BUILD_EXAMPLES" = "xyes"; then + BUILD_EXAMPLES_TRUE= + BUILD_EXAMPLES_FALSE='#' +else + BUILD_EXAMPLES_TRUE='#' + BUILD_EXAMPLES_FALSE= +fi + + + + + +# Check whether --with-pkg-config-path was given. +if test "${with_pkg_config_path+set}" = set; then : + withval=$with_pkg_config_path; + export PKG_CONFIG_PATH=${withval} + { $as_echo "$as_me:${as_lineno-$LINENO}: Set PKG_CONFIG_PATH to $PKG_CONFIG_PATH" >&5 +$as_echo "$as_me: Set PKG_CONFIG_PATH to $PKG_CONFIG_PATH" >&6;} + +fi + + + + +# Check whether --with-package-name was given. +if test "${with_package_name+set}" = set; then : + withval=$with_package_name; + case "${withval}" in + yes) as_fn_error $? "bad value ${withval} for --with-package-name" "$LINENO" 5 ;; + no) as_fn_error $? "bad value ${withval} for --with-package-name" "$LINENO" 5 ;; + *) GST_PACKAGE_NAME="${withval}" ;; + esac + +else + + P= + 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 + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $GST_PACKAGE_NAME as package name" >&5 +$as_echo "$as_me: Using $GST_PACKAGE_NAME as package name" >&6;} + +cat >>confdefs.h <<_ACEOF +#define GST_PACKAGE_NAME "$GST_PACKAGE_NAME" +_ACEOF + + + + + +# Check whether --with-package-origin was given. +if test "${with_package_origin+set}" = set; then : + withval=$with_package_origin; + case "${withval}" in + yes) as_fn_error $? "bad value ${withval} for --with-package-origin" "$LINENO" 5 ;; + no) as_fn_error $? "bad value ${withval} for --with-package-origin" "$LINENO" 5 ;; + *) GST_PACKAGE_ORIGIN="${withval}" ;; + esac + +else + GST_PACKAGE_ORIGIN="Unknown package origin" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $GST_PACKAGE_ORIGIN as package origin" >&5 +$as_echo "$as_me: Using $GST_PACKAGE_ORIGIN as package origin" >&6;} + +cat >>confdefs.h <<_ACEOF +#define GST_PACKAGE_ORIGIN "$GST_PACKAGE_ORIGIN" +_ACEOF + + + + + + 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 + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using GST_PKG_CONFIG_PATH = $GST_PKG_CONFIG_PATH" >&5 +$as_echo "$as_me: Using GST_PKG_CONFIG_PATH = $GST_PKG_CONFIG_PATH" >&6;} + + + + if test "x$PACKAGE_VERSION_NANO" = "x0"; then + + if test "xyes" = "xno" -o "xyes" = "x"; then + GST_PACKAGE_RELEASE_DATETIME=`date -u "+%Y-%m-%dT%H:%MZ"` + elif test "xyes" = "xyes"; then + if ( echo "${srcdir}/gstreamer.doap" | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME= "${srcdir}/gstreamer.doap" + else + YYYY_MM_DD=`sh "${srcdir}/common/extract-release-date-from-doap-file" $PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO "${srcdir}/gstreamer.doap" `; + if test "x$YYYY_MM_DD" != "x"; then + GST_PACKAGE_RELEASE_DATETIME=$YYYY_MM_DD + else + as_fn_error $? "SET_PACKAGE_RELEASE_DATETIME: could not extract + release date for release version $PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO from \"${srcdir}/gstreamer.doap\" " "$LINENO" 5 + GST_PACKAGE_RELEASE_DATETIME="" + fi + fi + elif ( echo yes | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SET_PACKAGE_RELEASE_DATETIME: invalid first argument" >&5 +$as_echo "$as_me: WARNING: SET_PACKAGE_RELEASE_DATETIME: invalid first argument" >&2;} + GST_PACKAGE_RELEASE_DATETIME="" + fi + + if test "x$GST_PACKAGE_RELEASE_DATETIME" = "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME" >&5 +$as_echo "$as_me: WARNING: Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME" >&2;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME" >&5 +$as_echo "$as_me: Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME" >&6;} + + +cat >>confdefs.h <<_ACEOF +#define GST_PACKAGE_RELEASE_DATETIME "$GST_PACKAGE_RELEASE_DATETIME" +_ACEOF + + fi + + else + + if test "xno" = "xno" -o "xno" = "x"; then + GST_PACKAGE_RELEASE_DATETIME=`date -u "+%Y-%m-%dT%H:%MZ"` + elif test "xno" = "xyes"; then + if ( echo | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME= + else + YYYY_MM_DD=`sh "${srcdir}/common/extract-release-date-from-doap-file" `; + if test "x$YYYY_MM_DD" != "x"; then + GST_PACKAGE_RELEASE_DATETIME=$YYYY_MM_DD + else + as_fn_error $? "SET_PACKAGE_RELEASE_DATETIME: could not extract + release date for release version from " "$LINENO" 5 + GST_PACKAGE_RELEASE_DATETIME="" + fi + fi + elif ( echo no | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SET_PACKAGE_RELEASE_DATETIME: invalid first argument" >&5 +$as_echo "$as_me: WARNING: SET_PACKAGE_RELEASE_DATETIME: invalid first argument" >&2;} + GST_PACKAGE_RELEASE_DATETIME="" + fi + + if test "x$GST_PACKAGE_RELEASE_DATETIME" = "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME" >&5 +$as_echo "$as_me: WARNING: Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME" >&2;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME" >&5 +$as_echo "$as_me: Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME" >&6;} + + +cat >>confdefs.h <<_ACEOF +#define GST_PACKAGE_RELEASE_DATETIME "$GST_PACKAGE_RELEASE_DATETIME" +_ACEOF + + fi + + fi + + +# We only use this when building with MSVC, which is only done with the +# alternate Meson build system files +GSTCONFIG_BUILT_WITH_MSVC=0 + + + +# Check whether --with-bash-completion-dir was given. +if test "${with_bash_completion_dir+set}" = set; then : + withval=$with_bash_completion_dir; +else + with_bash_completion_dir=yes +fi + + +if test "x$with_bash_completion_dir" = "xyes" +then + extra_args= + + if test "x$prefix" != "xNONE" + then + extra_args="--define-variable=prefix=\"$prefix\"" + fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BASH_COMPLETION" >&5 +$as_echo_n "checking for BASH_COMPLETION... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$BASH_COMPLETION_CFLAGS"; then + pkg_cv_BASH_COMPLETION_CFLAGS="$BASH_COMPLETION_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bash-completion >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bash-completion >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_BASH_COMPLETION_CFLAGS=`$PKG_CONFIG --cflags "bash-completion >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$BASH_COMPLETION_LIBS"; then + pkg_cv_BASH_COMPLETION_LIBS="$BASH_COMPLETION_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bash-completion >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bash-completion >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_BASH_COMPLETION_LIBS=`$PKG_CONFIG --libs "bash-completion >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + BASH_COMPLETION_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "bash-completion >= 2.0"` + else + BASH_COMPLETION_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "bash-completion >= 2.0"` + fi + # Put the nasty error message in config.log where it belongs + echo "$BASH_COMPLETION_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + BASH_COMPLETION_DIR="$datadir/bash-completion/completions" + BASH_HELPERS_DIR="$datadir/bash-completion/helpers" + +elif test $pkg_failed = untried; then + + BASH_COMPLETION_DIR="$datadir/bash-completion/completions" + BASH_HELPERS_DIR="$datadir/bash-completion/helpers" + +else + BASH_COMPLETION_CFLAGS=$pkg_cv_BASH_COMPLETION_CFLAGS + BASH_COMPLETION_LIBS=$pkg_cv_BASH_COMPLETION_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + BASH_COMPLETION_DIR="`eval pkg-config $extra_args --variable=completionsdir bash-completion`" + BASH_HELPERS_DIR="`eval pkg-config $extra_args --variable=helpersdir bash-completion`" + +fi +else + BASH_COMPLETION_DIR="$with_bash_completion_dir/completions" + BASH_HELPERS_DIR="$with_bash_completion_dir/helpers" +fi + + + + if test "x$with_bash_completion_dir" != "xno"; then + ENABLE_BASH_COMPLETION_TRUE= + ENABLE_BASH_COMPLETION_FALSE='#' +else + ENABLE_BASH_COMPLETION_TRUE='#' + ENABLE_BASH_COMPLETION_FALSE= +fi + + +if test x$enable_static = xyes -a x$enable_shared = xno; then + GST_OBJ_STATIC_CFLAGS="-DGST_STATIC_COMPILATION" +fi + +# Check whether --enable-tests was given. +if test "${enable_tests+set}" = set; then : + enableval=$enable_tests; + case "${enableval}" in + yes) BUILD_TESTS=yes ;; + no) BUILD_TESTS=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-tests" "$LINENO" 5 ;; + esac + +else + BUILD_TESTS=yes +fi + if test "x$BUILD_TESTS" = "xyes"; then + BUILD_TESTS_TRUE= + BUILD_TESTS_FALSE='#' +else + BUILD_TESTS_TRUE='#' + BUILD_TESTS_FALSE= +fi + + +# Check whether --enable-failing-tests was given. +if test "${enable_failing_tests+set}" = set; then : + enableval=$enable_failing_tests; + case "${enableval}" in + yes) BUILD_FAILING_TESTS=yes ;; + no) BUILD_FAILING_TESTS=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-failing-tests" "$LINENO" 5 ;; + esac + +else + BUILD_FAILING_TESTS=no +fi + if test "x$BUILD_FAILING_TESTS" = "xyes"; then + BUILD_FAILING_TESTS_TRUE= + BUILD_FAILING_TESTS_FALSE='#' +else + BUILD_FAILING_TESTS_TRUE='#' + BUILD_FAILING_TESTS_FALSE= +fi + +if test x$BUILD_FAILING_TESTS = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: building tests known to fail, use --disable-failing-tests to disable" >&5 +$as_echo "$as_me: WARNING: building tests known to fail, use --disable-failing-tests to disable" >&2;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Sissy ! By asking to not build the tests known to fail, you hereby waive your right to customer support. If you do not agree with this EULA, please press Ctrl-C before the next line is printed. By allowing the next line to be printed, you expressly acknowledge your acceptance of this EULA." >&5 +$as_echo "$as_me: WARNING: Sissy ! By asking to not build the tests known to fail, you hereby waive your right to customer support. If you do not agree with this EULA, please press Ctrl-C before the next line is printed. By allowing the next line to be printed, you expressly acknowledge your acceptance of this EULA." >&2;} +fi + +# Check whether --enable-benchmarks was given. +if test "${enable_benchmarks+set}" = set; then : + enableval=$enable_benchmarks; + case "${enableval}" in + yes) BUILD_BENCHMARKS=yes ;; + no) BUILD_BENCHMARKS=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-benchmarks" "$LINENO" 5 ;; + esac + +else + BUILD_BENCHMARKS=yes +fi + if test "x$BUILD_BENCHMARKS" = "xyes"; then + BUILD_BENCHMARKS_TRUE= + BUILD_BENCHMARKS_FALSE='#' +else + BUILD_BENCHMARKS_TRUE='#' + BUILD_BENCHMARKS_FALSE= +fi + + +# Check whether --enable-tools was given. +if test "${enable_tools+set}" = set; then : + enableval=$enable_tools; + case "${enableval}" in + yes) BUILD_TOOLS=yes ;; + no) BUILD_TOOLS=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-tools" "$LINENO" 5 ;; + esac + +else + BUILD_TOOLS=yes +fi + if test "x$BUILD_TOOLS" = "xyes"; then + BUILD_TOOLS_TRUE= + BUILD_TOOLS_FALSE='#' +else + BUILD_TOOLS_TRUE='#' + BUILD_TOOLS_FALSE= +fi + + +# Check whether --enable-poisoning was given. +if test "${enable_poisoning+set}" = set; then : + enableval=$enable_poisoning; + case "${enableval}" in + yes) USE_POISONING=yes ;; + no) USE_POISONING=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-poisoning" "$LINENO" 5 ;; + esac + +else + USE_POISONING=no +fi + if test "x$USE_POISONING" = xyes; then + +$as_echo "#define USE_POISONING 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether PTP support can be enabled" >&5 +$as_echo_n "checking whether PTP support can be enabled... " >&6; } +case "$host_os" in + *android*) + HAVE_PTP=no + ;; + mingw*|pw32*|cygwin*) + HAVE_PTP=no + ;; + darwin*) + ac_fn_c_check_header_preproc "$LINENO" "MobileCoreServices/MobileCoreServices.h" "ac_cv_header_MobileCoreServices_MobileCoreServices_h" +if test "x$ac_cv_header_MobileCoreServices_MobileCoreServices_h" = xyes; then : + HAVE_PTP="no" +else + HAVE_PTP="yes" +fi + + + ;; + linux*|darwin*|solaris*|netbsd*|freebsd*|openbsd*|kfreebsd*|dragonfly*|gnu*) + HAVE_PTP=yes + ;; + *) + HAVE_PTP=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_PTP" >&5 +$as_echo "$HAVE_PTP" >&6; } + + +# Check whether --with-ptp-helper-setuid-user was given. +if test "${with_ptp_helper_setuid_user+set}" = set; then : + withval=$with_ptp_helper_setuid_user; + if test "x$withval" != "x" + then + +cat >>confdefs.h <<_ACEOF +#define HAVE_PTP_HELPER_SETUID_USER "$withval" +_ACEOF + + fi + +fi + + + +# Check whether --with-ptp-helper-setuid-group was given. +if test "${with_ptp_helper_setuid_group+set}" = set; then : + withval=$with_ptp_helper_setuid_group; + if test "x$withval" != "x" + then + +cat >>confdefs.h <<_ACEOF +#define HAVE_PTP_HELPER_SETUID_GROUP "$withval" +_ACEOF + + fi + +fi + + + +# Check whether --with-ptp-helper-permissions was given. +if test "${with_ptp_helper_permissions+set}" = set; then : + withval=$with_ptp_helper_permissions; +else + with_ptp_helper_permissions=auto +fi + + +gst_ptp_have_cap=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_init in -lcap" >&5 +$as_echo_n "checking for cap_init in -lcap... " >&6; } +if ${ac_cv_lib_cap_cap_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cap_init (); +int +main () +{ +return cap_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cap_cap_init=yes +else + ac_cv_lib_cap_cap_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_init" >&5 +$as_echo "$ac_cv_lib_cap_cap_init" >&6; } +if test "x$ac_cv_lib_cap_cap_init" = xyes; then : + HAVE_CAP=yes +else + HAVE_CAP=no +fi + + if test "x$HAVE_CAP" = "xyes"; then + ac_fn_c_check_header_mongrel "$LINENO" "sys/capability.h" "ac_cv_header_sys_capability_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_capability_h" = xyes; then : + : +else + HAVE_CAP=no +fi + + + if test "x$HAVE_CAP" = "xyes"; then + CAP_LIBS="-lcap" + + gst_ptp_have_cap=yes + else + : + fi + else + : + fi + + + + +# Extract the first word of "setcap", so it can be a program name with args. +set dummy setcap; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SETCAP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SETCAP in + [\\/]* | ?:[\\/]*) + ac_cv_path_SETCAP="$SETCAP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="$PATH:/usr/bin:/bin:/usr/sbin:/sbin" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SETCAP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SETCAP" && ac_cv_path_SETCAP="no" + ;; +esac +fi +SETCAP=$ac_cv_path_SETCAP +if test -n "$SETCAP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETCAP" >&5 +$as_echo "$SETCAP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +if test "x$HAVE_PTP" = "xyes"; then + +$as_echo "#define HAVE_PTP 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR" >&5 +$as_echo_n "checking for SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + struct ifreq ifr; + struct ifconf ifc; + ioctl(0, SIOCGIFCONF, &ifc); + ioctl(0, SIOCGIFFLAGS, &ifr); + ioctl(0, SIOCGIFHWADDR, &ifr); + int dummy = ifr.ifr_hwaddr.sa_data[0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getifaddrs() and AF_LINK" >&5 +$as_echo_n "checking for getifaddrs() and AF_LINK... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #include + +int +main () +{ + + struct ifaddrs *ifaddr; + getifaddrs(&ifaddr); + int dummy = (ifaddr->ifa_flags & IFF_LOOPBACK) && ifaddr->ifa_addr->sa_family != AF_LINK; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GETIFADDRS_AF_LINK 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to install gst-ptp-helper" >&5 +$as_echo_n "checking how to install gst-ptp-helper... " >&6; } +if test "x$with_ptp_helper_permissions" = "xauto"; then + if test "x$gst_ptp_have_cap" = "xyes" -a "x$SETCAP" != "xno"; then + with_ptp_helper_permissions="capabilities" + else + with_ptp_helper_permissions="setuid-root" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_ptp_helper_permissions" >&5 +$as_echo "$with_ptp_helper_permissions" >&6; } + +case "$with_ptp_helper_permissions" in + none) + ;; + setuid-root) + +$as_echo "#define HAVE_PTP_HELPER_SETUID 1" >>confdefs.h + + ;; + capabilities) + +$as_echo "#define HAVE_PTP_HELPER_CAPABILITIES 1" >>confdefs.h + + ;; + *) + as_fn_error $? "Invalid parameter $with_ptp_helper_permissions" "$LINENO" 5 + ;; +esac + +fi + + if test "x$HAVE_PTP" = "xyes"; then + HAVE_PTP_TRUE= + HAVE_PTP_FALSE='#' +else + HAVE_PTP_TRUE='#' + HAVE_PTP_FALSE= +fi + + if test "x$with_ptp_helper_permissions" = "xsetuid-root"; then + HAVE_PTP_HELPER_SETUID_TRUE= + HAVE_PTP_HELPER_SETUID_FALSE='#' +else + HAVE_PTP_HELPER_SETUID_TRUE='#' + HAVE_PTP_HELPER_SETUID_FALSE= +fi + + if test "x$with_ptp_helper_permissions" = "xcapabilities"; then + HAVE_PTP_HELPER_CAPABILITIES_TRUE= + HAVE_PTP_HELPER_CAPABILITIES_FALSE='#' +else + HAVE_PTP_HELPER_CAPABILITIES_TRUE='#' + HAVE_PTP_HELPER_CAPABILITIES_FALSE= +fi + + + + + + case "x${target_cpu}" in + xi?86 | xk? | xi?86_64) + case $target_os in + solaris*) + ac_fn_c_check_decl "$LINENO" "__i386" "ac_cv_have_decl___i386" "$ac_includes_default" +if test "x$ac_cv_have_decl___i386" = xyes; then : + I386_ABI="yes" +else + I386_ABI="no" +fi + + ac_fn_c_check_decl "$LINENO" "__amd64" "ac_cv_have_decl___amd64" "$ac_includes_default" +if test "x$ac_cv_have_decl___amd64" = xyes; then : + AMD64_ABI="yes" +else + AMD64_ABI="no" +fi + + + if test "x$I386_ABI" = "xyes" ; then + HAVE_CPU_I386=yes + +$as_echo "#define HAVE_CPU_I386 1" >>confdefs.h + + fi + if test "x$AMD64_ABI" = "xyes" ; then + HAVE_CPU_X86_64=yes + +$as_echo "#define HAVE_CPU_X86_64 1" >>confdefs.h + + fi + ;; + *) + HAVE_CPU_I386=yes + +$as_echo "#define HAVE_CPU_I386 1" >>confdefs.h + + + case "x${target_cpu}" in + xi386 | xi486) ;; + *) + +$as_echo "#define HAVE_RDTSC 1" >>confdefs.h + ;; + esac + ;; + esac + ;; + xpowerpc) + HAVE_CPU_PPC=yes + +$as_echo "#define HAVE_CPU_PPC 1" >>confdefs.h + ;; + xpowerpc64) + HAVE_CPU_PPC64=yes + +$as_echo "#define HAVE_CPU_PPC64 1" >>confdefs.h + ;; + xalpha*) + HAVE_CPU_ALPHA=yes + +$as_echo "#define HAVE_CPU_ALPHA 1" >>confdefs.h + ;; + xarc*) + HAVE_CPU_ARC=yes + +$as_echo "#define HAVE_CPU_ARC 1" >>confdefs.h + ;; + xarm*) + HAVE_CPU_ARM=yes + +$as_echo "#define HAVE_CPU_ARM 1" >>confdefs.h + ;; + xaarch64*) + HAVE_CPU_AARCH64=yes + +$as_echo "#define HAVE_CPU_AARCH64 1" >>confdefs.h + ;; + xsparc*) + HAVE_CPU_SPARC=yes + +$as_echo "#define HAVE_CPU_SPARC 1" >>confdefs.h + ;; + xmips*) + HAVE_CPU_MIPS=yes + +$as_echo "#define HAVE_CPU_MIPS 1" >>confdefs.h + ;; + xhppa*) + HAVE_CPU_HPPA=yes + +$as_echo "#define HAVE_CPU_HPPA 1" >>confdefs.h + ;; + xs390*) + HAVE_CPU_S390=yes + +$as_echo "#define HAVE_CPU_S390 1" >>confdefs.h + ;; + xia64*) + HAVE_CPU_IA64=yes + +$as_echo "#define HAVE_CPU_IA64 1" >>confdefs.h + ;; + xm68k*) + HAVE_CPU_M68K=yes + +$as_echo "#define HAVE_CPU_M68K 1" >>confdefs.h + ;; + xx86_64) + HAVE_CPU_X86_64=yes + +$as_echo "#define HAVE_CPU_X86_64 1" >>confdefs.h + ;; + xcris) + HAVE_CPU_CRIS=yes + +$as_echo "#define HAVE_CPU_CRIS 1" >>confdefs.h + ;; + xcrisv32) + HAVE_CPU_CRISV32=yes + +$as_echo "#define HAVE_CPU_CRISV32 1" >>confdefs.h + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + + if test "x$HAVE_CPU_I386" = "xyes"; then + HAVE_CPU_I386_TRUE= + HAVE_CPU_I386_FALSE='#' +else + HAVE_CPU_I386_TRUE='#' + HAVE_CPU_I386_FALSE= +fi + + if test "x$HAVE_CPU_PPC" = "xyes"; then + HAVE_CPU_PPC_TRUE= + HAVE_CPU_PPC_FALSE='#' +else + HAVE_CPU_PPC_TRUE='#' + HAVE_CPU_PPC_FALSE= +fi + + if test "x$HAVE_CPU_PPC64" = "xyes"; then + HAVE_CPU_PPC64_TRUE= + HAVE_CPU_PPC64_FALSE='#' +else + HAVE_CPU_PPC64_TRUE='#' + HAVE_CPU_PPC64_FALSE= +fi + + if test "x$HAVE_CPU_ALPHA" = "xyes"; then + HAVE_CPU_ALPHA_TRUE= + HAVE_CPU_ALPHA_FALSE='#' +else + HAVE_CPU_ALPHA_TRUE='#' + HAVE_CPU_ALPHA_FALSE= +fi + + if test "x$HAVE_CPU_ARC" = "xyes"; then + HAVE_CPU_ARC_TRUE= + HAVE_CPU_ARC_FALSE='#' +else + HAVE_CPU_ARC_TRUE='#' + HAVE_CPU_ARC_FALSE= +fi + + if test "x$HAVE_CPU_ARM" = "xyes"; then + HAVE_CPU_ARM_TRUE= + HAVE_CPU_ARM_FALSE='#' +else + HAVE_CPU_ARM_TRUE='#' + HAVE_CPU_ARM_FALSE= +fi + + if test "x$HAVE_CPU_SPARC" = "xyes"; then + HAVE_CPU_SPARC_TRUE= + HAVE_CPU_SPARC_FALSE='#' +else + HAVE_CPU_SPARC_TRUE='#' + HAVE_CPU_SPARC_FALSE= +fi + + if test "x$HAVE_CPU_HPPA" = "xyes"; then + HAVE_CPU_HPPA_TRUE= + HAVE_CPU_HPPA_FALSE='#' +else + HAVE_CPU_HPPA_TRUE='#' + HAVE_CPU_HPPA_FALSE= +fi + + if test "x$HAVE_CPU_MIPS" = "xyes"; then + HAVE_CPU_MIPS_TRUE= + HAVE_CPU_MIPS_FALSE='#' +else + HAVE_CPU_MIPS_TRUE='#' + HAVE_CPU_MIPS_FALSE= +fi + + if test "x$HAVE_CPU_S390" = "xyes"; then + HAVE_CPU_S390_TRUE= + HAVE_CPU_S390_FALSE='#' +else + HAVE_CPU_S390_TRUE='#' + HAVE_CPU_S390_FALSE= +fi + + if test "x$HAVE_CPU_IA64" = "xyes"; then + HAVE_CPU_IA64_TRUE= + HAVE_CPU_IA64_FALSE='#' +else + HAVE_CPU_IA64_TRUE='#' + HAVE_CPU_IA64_FALSE= +fi + + if test "x$HAVE_CPU_M68K" = "xyes"; then + HAVE_CPU_M68K_TRUE= + HAVE_CPU_M68K_FALSE='#' +else + HAVE_CPU_M68K_TRUE='#' + HAVE_CPU_M68K_FALSE= +fi + + if test "x$HAVE_CPU_X86_64" = "xyes"; then + HAVE_CPU_X86_64_TRUE= + HAVE_CPU_X86_64_FALSE='#' +else + HAVE_CPU_X86_64_TRUE='#' + HAVE_CPU_X86_64_FALSE= +fi + + if test "x$HAVE_CPU_CRIS" = "xyes"; then + HAVE_CPU_CRIS_TRUE= + HAVE_CPU_CRIS_FALSE='#' +else + HAVE_CPU_CRIS_TRUE='#' + HAVE_CPU_CRIS_FALSE= +fi + + if test "x$HAVE_CPU_CRISV32" = "xyes"; then + HAVE_CPU_CRISV32_TRUE= + HAVE_CPU_CRISV32_FALSE='#' +else + HAVE_CPU_CRISV32_TRUE='#' + HAVE_CPU_CRISV32_FALSE= +fi + + + +cat >>confdefs.h <<_ACEOF +#define HOST_CPU "$host_cpu" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define TARGET_CPU "$target_cpu" +_ACEOF + + + + + + + case $host_os in + rhapsody*) + +cat >>confdefs.h <<_ACEOF +#define GST_EXTRA_MODULE_SUFFIX ".dylib" +_ACEOF + + ;; + darwin*) + +cat >>confdefs.h <<_ACEOF +#define GST_EXTRA_MODULE_SUFFIX ".dylib" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define HAVE_OSX 1 +_ACEOF + + ;; + cygwin*) + +cat >>confdefs.h <<_ACEOF +#define GST_HAVE_UNSAFE_FORK 1 +_ACEOF + + ;; + mingw* | msvc* | mks*) + +cat >>confdefs.h <<_ACEOF +#define HAVE_WIN32 1 +_ACEOF + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + return __MSVCRT_VERSION__; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #if __MSVCRT_VERSION__ < 0x0601 + #error "MSVCRT too old" + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: MSVCRT version looks ok" >&5 +$as_echo "$as_me: MSVCRT version looks ok" >&6;} + +else + + as_fn_error $? "MSVCRT version too old, need at least WinXP SP2" "$LINENO" 5 + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting MSVCRT version to 0x0601" >&5 +$as_echo "$as_me: Setting MSVCRT version to 0x0601" >&6;} + +cat >>confdefs.h <<_ACEOF +#define __MSVCRT_VERSION__ 0x0601 +_ACEOF + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; + *) + ;; + esac + + + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + case $ac_cv_prog_cc_stdc in #( + no) : + ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 +else + ac_cv_prog_cc_stdc=no +fi + +fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 +$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } + if ${ac_cv_prog_cc_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +fi + + case $ac_cv_prog_cc_stdc in #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; #( + '') : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 +$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; +esac + + + + +# By default we simply use the C compiler to build assembly code. + +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS + + + +depcc="$CCAS" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CCAS_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CCAS_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CCAS_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } +CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then + am__fastdepCCAS_TRUE= + am__fastdepCCAS_FALSE='#' +else + am__fastdepCCAS_TRUE='#' + am__fastdepCCAS_FALSE= +fi + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + + +func_stripname_cnf () +{ + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; + esac +} # func_stripname_cnf + + if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct_CXX=no + hardcode_direct_absolute_CXX=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec_CXX='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + no_undefined_flag_CXX='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' $wl-bernotok' + allow_undefined_flag_CXX=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='$wl--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + if test yes != "$lt_cv_apple_cc_single_mod"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + os2*) + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_minus_L_CXX=yes + allow_undefined_flag_CXX=unsupported + shrext_cmds=.dll + archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes_CXX=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='$wl-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='$wl-E' + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + no_undefined_flag_CXX=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='$wl-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='$wl-z,text' + allow_undefined_flag_CXX='$wl-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test no = "$ld_shlibs_CXX" && can_build_shared=no + + GCC_CXX=$GXX + LD_CXX=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX=$prev$p + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX=$prev$p + else + postdeps_CXX="${postdeps_CXX} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX=$p + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX=$p + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + lt_prog_compiler_pic_CXX='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static_CXX='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs_CXX=no + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test no = "$ld_shlibs_CXX" && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec_CXX='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test yes = "$hardcode_automatic_CXX"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct_CXX" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && + test no != "$hardcode_minus_L_CXX"; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test relink = "$hardcode_action_CXX" || + test yes = "$inherit_rpath_CXX"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + class Foo { int bar; }; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + working_cxx=yes +else + working_cxx=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: working c++ compiler found: $working_cxx" >&5 +$as_echo "$as_me: working c++ compiler found: $working_cxx" >&6;} + if test "x$working_cxx" = "xyes"; then + HAVE_CXX_TRUE= + HAVE_CXX_FALSE='#' +else + HAVE_CXX_TRUE='#' + HAVE_CXX_FALSE= +fi + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PERL_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PERL_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL_PATH="$PERL_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PERL_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PERL_PATH" && ac_cv_path_PERL_PATH="no" + ;; +esac +fi +PERL_PATH=$ac_cv_path_PERL_PATH +if test -n "$PERL_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_PATH" >&5 +$as_echo "$PERL_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test x$PERL_PATH = xno; then + as_fn_error $? "Could not find perl" "$LINENO" 5 +fi + +if test "x$GST_DISABLE_PARSE" != xyes; then + + # Extract the first word of "bison", so it can be a program name with args. +set dummy bison; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BISON_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BISON_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_BISON_PATH="$BISON_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BISON_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BISON_PATH" && ac_cv_path_BISON_PATH="no" + ;; +esac +fi +BISON_PATH=$ac_cv_path_BISON_PATH +if test -n "$BISON_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BISON_PATH" >&5 +$as_echo "$BISON_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x$BISON_PATH = xno; then + as_fn_error $? "Could not find bison" "$LINENO" 5 + fi + + bison_min_version=2.4 + bison_version=`$BISON_PATH --version | head -n 1 | sed 's/^[^0-9]*//' | sed 's/[^0-9]*$//' | cut -d' ' -f1` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking bison version $bison_version >= $bison_min_version" >&5 +$as_echo_n "checking bison version $bison_version >= $bison_min_version... " >&6; } + + if perl -we "exit (('v$bison_version' ge 'v$bison_min_version') ? 0 : 1)"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + as_fn_error $? "no" "$LINENO" 5 + fi + + + # Extract the first word of "flex", so it can be a program name with args. +set dummy flex; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_FLEX_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $FLEX_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_FLEX_PATH="$FLEX_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_FLEX_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FLEX_PATH" && ac_cv_path_FLEX_PATH="no" + ;; +esac +fi +FLEX_PATH=$ac_cv_path_FLEX_PATH +if test -n "$FLEX_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX_PATH" >&5 +$as_echo "$FLEX_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x$FLEX_PATH = xno; then + as_fn_error $? "Could not find flex" "$LINENO" 5 + fi + + flex_min_version=2.5.31 + flex_version=`$FLEX_PATH --version | head -n 1 | awk '{print }'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flex version $flex_version >= $flex_min_version" >&5 +$as_echo_n "checking flex version $flex_version >= $flex_min_version... " >&6; } + 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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + as_fn_error $? "no" "$LINENO" 5 + fi + +fi + +# Extract the first word of "valgrind", so it can be a program name with args. +set dummy valgrind; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VALGRIND_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VALGRIND_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_VALGRIND_PATH="$VALGRIND_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VALGRIND_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_VALGRIND_PATH" && ac_cv_path_VALGRIND_PATH="no" + ;; +esac +fi +VALGRIND_PATH=$ac_cv_path_VALGRIND_PATH +if test -n "$VALGRIND_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND_PATH" >&5 +$as_echo "$VALGRIND_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test ! "x$VALGRIND_PATH" = "xno"; then + HAVE_VALGRIND_TRUE= + HAVE_VALGRIND_FALSE='#' +else + HAVE_VALGRIND_TRUE='#' + HAVE_VALGRIND_FALSE= +fi + + + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.31.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.31.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= 1.31.1 installed to build GStreamer" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.31.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.31.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + 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)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + INTROSPECTION_INIT="extern void gst_init(gint*,gchar**); gst_init(NULL,NULL);" + fi + + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + + + + + # Extract the first word of "gtkdoc-check", so it can be a program name with args. +set dummy gtkdoc-check; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_CHECK+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_CHECK in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_CHECK="$GTKDOC_CHECK" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_CHECK="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_CHECK=$ac_cv_path_GTKDOC_CHECK +if test -n "$GTKDOC_CHECK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5 +$as_echo "$GTKDOC_CHECK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + for ac_prog in gtkdoc-rebase +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_REBASE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_REBASE in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE +if test -n "$GTKDOC_REBASE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5 +$as_echo "$GTKDOC_REBASE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GTKDOC_REBASE" && break +done +test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true" + + # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args. +set dummy gtkdoc-mkpdf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_MKPDF+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_MKPDF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF +if test -n "$GTKDOC_MKPDF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5 +$as_echo "$GTKDOC_MKPDF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +# Check whether --with-html-dir was given. +if test "${with_html_dir+set}" = set; then : + withval=$with_html_dir; +else + with_html_dir='${datadir}/gtk-doc/html' +fi + + HTML_DIR="$with_html_dir" + + + # Check whether --enable-gtk-doc was given. +if test "${enable_gtk_doc+set}" = set; then : + enableval=$enable_gtk_doc; +else + enable_gtk_doc=no +fi + + + if test x$enable_gtk_doc = xyes; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk-doc >= 1.12\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk-doc >= 1.12") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "You need to have gtk-doc >= 1.12 installed to build $PACKAGE_NAME" "$LINENO" 5 +fi + if test "x$PACKAGE_NAME" != "xglib"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 +$as_echo_n "checking for GTKDOC_DEPS... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GTKDOC_DEPS_CFLAGS"; then + pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GTKDOC_DEPS_LIBS"; then + pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0"` + else + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0) were not met: + +$GTKDOC_DEPS_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GTKDOC_DEPS_CFLAGS +and GTKDOC_DEPS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "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. + +Alternatively, you may set the environment variables GTKDOC_DEPS_CFLAGS +and GTKDOC_DEPS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS + GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + fi + if test -z "$SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5 +$as_echo_n "checking whether to build gtk-doc documentation... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5 +$as_echo "$enable_gtk_doc" >&6; } + + # Check whether --enable-gtk-doc-html was given. +if test "${enable_gtk_doc_html+set}" = set; then : + enableval=$enable_gtk_doc_html; +else + enable_gtk_doc_html=yes +fi + + # Check whether --enable-gtk-doc-pdf was given. +if test "${enable_gtk_doc_pdf+set}" = set; then : + enableval=$enable_gtk_doc_pdf; +else + enable_gtk_doc_pdf=no +fi + + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + + if test x$enable_gtk_doc = xyes; then + ENABLE_GTK_DOC_TRUE= + ENABLE_GTK_DOC_FALSE='#' +else + ENABLE_GTK_DOC_TRUE='#' + ENABLE_GTK_DOC_FALSE= +fi + + if test x$enable_gtk_doc_html = xyes; then + GTK_DOC_BUILD_HTML_TRUE= + GTK_DOC_BUILD_HTML_FALSE='#' +else + GTK_DOC_BUILD_HTML_TRUE='#' + GTK_DOC_BUILD_HTML_FALSE= +fi + + if test x$enable_gtk_doc_pdf = xyes; then + GTK_DOC_BUILD_PDF_TRUE= + GTK_DOC_BUILD_PDF_FALSE='#' +else + GTK_DOC_BUILD_PDF_TRUE='#' + GTK_DOC_BUILD_PDF_FALSE= +fi + + if test -n "$LIBTOOL"; then + GTK_DOC_USE_LIBTOOL_TRUE= + GTK_DOC_USE_LIBTOOL_FALSE='#' +else + GTK_DOC_USE_LIBTOOL_TRUE='#' + GTK_DOC_USE_LIBTOOL_FALSE= +fi + + + + + + + + + # Find any Python interpreter. + if test -z "$PYTHON"; then + for ac_prog in python python2 python3 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PYTHON" && break +done +test -n "$PYTHON" || PYTHON=":" + + fi + am_display_PYTHON=python + + + if test "$PYTHON" = :; then + as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 + else + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 +$as_echo_n "checking for $am_display_PYTHON version... " >&6; } +if ${am_cv_python_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 +$as_echo "$am_cv_python_version" >&6; } + PYTHON_VERSION=$am_cv_python_version + + + + PYTHON_PREFIX='${prefix}' + + PYTHON_EXEC_PREFIX='${exec_prefix}' + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 +$as_echo_n "checking for $am_display_PYTHON platform... " >&6; } +if ${am_cv_python_platform+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 +$as_echo "$am_cv_python_platform" >&6; } + PYTHON_PLATFORM=$am_cv_python_platform + + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[:3] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 +$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } +if ${am_cv_python_pythondir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 +$as_echo "$am_cv_python_pythondir" >&6; } + pythondir=$am_cv_python_pythondir + + + + pkgpythondir=\${pythondir}/$PACKAGE + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 +$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } +if ${am_cv_python_pyexecdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 +$as_echo "$am_cv_python_pyexecdir" >&6; } + pyexecdir=$am_cv_python_pyexecdir + + + + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + + + fi + + + + + build_plugin_docs=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build plugin documentation" >&5 +$as_echo_n "checking whether to build plugin documentation... " >&6; } + if test x$enable_gtk_doc = xyes; then + if test x$PYTHON != x; then + build_plugin_docs=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (python not found)" >&5 +$as_echo "no (python not found)" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (gtk-doc disabled or not available)" >&5 +$as_echo "no (gtk-doc disabled or not available)" >&6; } + fi + + if test x$build_plugin_docs = xyes; then + ENABLE_PLUGIN_DOCS_TRUE= + ENABLE_PLUGIN_DOCS_FALSE='#' +else + ENABLE_PLUGIN_DOCS_TRUE='#' + ENABLE_PLUGIN_DOCS_FALSE= +fi + + + + +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5 +$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; } +if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmw $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _mwvalidcheckl (); +int +main () +{ +return _mwvalidcheckl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mw__mwvalidcheckl=yes +else + ac_cv_lib_mw__mwvalidcheckl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mw__mwvalidcheckl" >&5 +$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; } +if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then : + LIBM=-lmw +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM="$LIBM -lm" +fi + + ;; +*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM=-lm +fi + + ;; +esac + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + + +for ac_header in ucontext.h +do : + ac_fn_c_check_header_compile "$LINENO" "ucontext.h" "ac_cv_header_ucontext_h" "$ac_includes_default +" +if test "x$ac_cv_header_ucontext_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UCONTEXT_H 1 +_ACEOF + +fi + +done + + +for ac_header in sys/socket.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_socket_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SOCKET_H 1 +_ACEOF + HAVE_SYS_SOCKET_H=yes +else + HAVE_SYS_SOCKET_H=no +fi + +done + + if test "x$HAVE_SYS_SOCKET_H" = "xyes"; then + HAVE_SYS_SOCKET_H_TRUE= + HAVE_SYS_SOCKET_H_FALSE='#' +else + HAVE_SYS_SOCKET_H_TRUE='#' + HAVE_SYS_SOCKET_H_FALSE= +fi + + +for ac_header in sys/times.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/times.h" "ac_cv_header_sys_times_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_times_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_TIMES_H 1 +_ACEOF + HAVE_SYS_TIMES_H=yes +else + HAVE_SYS_TIME_H=no +fi + +done + +for ac_header in unistd.h +do : + ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default +" +if test "x$ac_cv_header_unistd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UNISTD_H 1 +_ACEOF + HAVE_UNISTD_H=yes +else + HAVE_UNISTD_H=no +fi + +done + + if test "x$HAVE_SYS_TIMES_H" = "xyes" -a "x$HAVE_UNISTD_H" = "xyes"; then + HAVE_SYS_TIMES_H_AND_UNISTD_H_TRUE= + HAVE_SYS_TIMES_H_AND_UNISTD_H_FALSE='#' +else + HAVE_SYS_TIMES_H_AND_UNISTD_H_TRUE='#' + HAVE_SYS_TIMES_H_AND_UNISTD_H_FALSE= +fi + + +for ac_header in process.h +do : + ac_fn_c_check_header_compile "$LINENO" "process.h" "ac_cv_header_process_h" "$ac_includes_default +" +if test "x$ac_cv_header_process_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PROCESS_H 1 +_ACEOF + +fi + +done + + +for ac_header in sys/utsname.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/utsname.h" "ac_cv_header_sys_utsname_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_utsname_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UTSNAME_H 1 +_ACEOF + +fi + +done + + +for ac_header in stdio_ext.h +do : + ac_fn_c_check_header_compile "$LINENO" "stdio_ext.h" "ac_cv_header_stdio_ext_h" "$ac_includes_default +" +if test "x$ac_cv_header_stdio_ext_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDIO_EXT_H 1 +_ACEOF + +fi + +done + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + : +else + ax_pthread_ok=no + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + if test "x$ax_pthread_ok" = "xyes"; then + HAVE_PTHREAD_TRUE= + HAVE_PTHREAD_FALSE='#' +else + HAVE_PTHREAD_TRUE='#' + HAVE_PTHREAD_FALSE= +fi + + +for ac_header in sys/prctl.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_prctl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PRCTL_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np(const char*)" >&5 +$as_echo_n "checking for pthread_setname_np(const char*)... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_setname_np("example") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +for ac_header in sys/uio.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_uio_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UIO_H 1 +_ACEOF + +fi + +done + + +for ac_header in valgrind/valgrind.h +do : + ac_fn_c_check_header_compile "$LINENO" "valgrind/valgrind.h" "ac_cv_header_valgrind_valgrind_h" "$ac_includes_default +" +if test "x$ac_cv_header_valgrind_valgrind_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VALGRIND_VALGRIND_H 1 +_ACEOF + +fi + +done + + +for ac_header in winsock2.h +do : + ac_fn_c_check_header_compile "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default +" +if test "x$ac_cv_header_winsock2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINSOCK2_H 1 +_ACEOF + HAVE_WINSOCK2_H=yes +else + HAVE_WINSOCK2_H=no +fi + +done + + if test "x$HAVE_WINSOCK2_H" = "xyes"; then + HAVE_WINSOCK2_H_TRUE= + HAVE_WINSOCK2_H_FALSE='#' +else + HAVE_WINSOCK2_H_TRUE='#' + HAVE_WINSOCK2_H_FALSE= +fi + +if test "x$HAVE_WINSOCK2_H" = "xyes"; then + WIN32_LIBS="-lws2_32" + +fi + +if test "x$BUILD_TESTS" = "xyes"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_init_set_d in -lgmp" >&5 +$as_echo_n "checking for __gmpz_init_set_d in -lgmp... " >&6; } +if ${ac_cv_lib_gmp___gmpz_init_set_d+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgmp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __gmpz_init_set_d (); +int +main () +{ +return __gmpz_init_set_d (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gmp___gmpz_init_set_d=yes +else + ac_cv_lib_gmp___gmpz_init_set_d=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_init_set_d" >&5 +$as_echo "$ac_cv_lib_gmp___gmpz_init_set_d" >&6; } +if test "x$ac_cv_lib_gmp___gmpz_init_set_d" = xyes; then : + HAVE_GMP=yes +else + HAVE_GMP=no +fi + + if test "x$HAVE_GMP" = "xyes"; then + ac_fn_c_check_header_mongrel "$LINENO" "gmp.h" "ac_cv_header_gmp_h" "$ac_includes_default" +if test "x$ac_cv_header_gmp_h" = xyes; then : + : +else + HAVE_GMP=no +fi + + + if test "x$HAVE_GMP" = "xyes"; then + GMP_LIBS="-lgmp" + + +$as_echo "#define HAVE_GMP 1" >>confdefs.h + + else + : + fi + else + : + fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gsl_rng_uniform_int in -lgsl" >&5 +$as_echo_n "checking for gsl_rng_uniform_int in -lgsl... " >&6; } +if ${ac_cv_lib_gsl_gsl_rng_uniform_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgsl -lgslcblas $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gsl_rng_uniform_int (); +int +main () +{ +return gsl_rng_uniform_int (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gsl_gsl_rng_uniform_int=yes +else + ac_cv_lib_gsl_gsl_rng_uniform_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gsl_gsl_rng_uniform_int" >&5 +$as_echo "$ac_cv_lib_gsl_gsl_rng_uniform_int" >&6; } +if test "x$ac_cv_lib_gsl_gsl_rng_uniform_int" = xyes; then : + HAVE_GSL=yes +else + HAVE_GSL=no +fi + + if test "x$HAVE_GSL" = "xyes"; then + ac_fn_c_check_header_mongrel "$LINENO" "gsl/gsl_rng.h" "ac_cv_header_gsl_gsl_rng_h" "$ac_includes_default" +if test "x$ac_cv_header_gsl_gsl_rng_h" = xyes; then : + : +else + HAVE_GSL=no +fi + + + if test "x$HAVE_GSL" = "xyes"; then + GSL_LIBS="-lgsl -lgslcblas" + + +$as_echo "#define HAVE_GSL 1" >>confdefs.h + + else + : + fi + else + : + fi + + + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __uint128_t" >&5 +$as_echo_n "checking for __uint128_t... " >&6; } +if ${gst_cv_uint128_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + static __uint128_t v1 = 100; + static __uint128_t v2 = 10; + static __uint128_t u; + u = v1 / v2; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + gst_cv_uint128_t=yes + +else + + gst_cv_uint128_t=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_uint128_t" >&5 +$as_echo "$gst_cv_uint128_t" >&6; } +if test x$gst_cv_uint128_t = xyes; then + +$as_echo "#define HAVE_UINT128_T 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tm_gmtoff" >&5 +$as_echo_n "checking for tm_gmtoff... " >&6; } +if test "$cross_compiling" = yes; then : + have_tm_gmtoff="no (cross compiling)" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + int main(void) { + struct tm t; + t.tm_gmtoff = 0; + exit(0); + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + have_tm_gmtoff=yes + +$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h + +else + have_tm_gmtoff=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_tm_gmtoff" >&5 +$as_echo "$have_tm_gmtoff" >&6; } + + + +for ac_func in strcasestr +do : + ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr" +if test "x$ac_cv_func_strcasestr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRCASESTR 1 +_ACEOF + +fi +done + + +for ac_func in gmtime_r +do : + ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" +if test "x$ac_cv_func_gmtime_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GMTIME_R 1 +_ACEOF + +fi +done + +for ac_func in localtime_r +do : + ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALTIME_R 1 +_ACEOF + +fi +done + +for ac_func in sigaction +do : + ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" +if test "x$ac_cv_func_sigaction" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SIGACTION 1 +_ACEOF + +fi +done + +for ac_func in getrusage +do : + ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage" +if test "x$ac_cv_func_getrusage" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETRUSAGE 1 +_ACEOF + +fi +done + + if test "x$ac_cv_func_getrusage" = "xyes"; then + HAVE_GETRUSAGE_TRUE= + HAVE_GETRUSAGE_FALSE='#' +else + HAVE_GETRUSAGE_TRUE='#' + HAVE_GETRUSAGE_FALSE= +fi + +for ac_header in sys/resource.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_resource_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_RESOURCE_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } +if ${ac_cv_sys_largefile_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=no; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=1; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 +$as_echo "$ac_cv_sys_largefile_source" >&6; } +case $ac_cv_sys_largefile_source in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF +;; +esac +rm -rf conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +if test $ac_cv_sys_largefile_source != unknown; then + +$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h + +fi + +for ac_func in ftello +do : + ac_fn_c_check_func "$LINENO" "ftello" "ac_cv_func_ftello" +if test "x$ac_cv_func_ftello" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FTELLO 1 +_ACEOF + +fi +done + + +for ac_func in fgetpos +do : + ac_fn_c_check_func "$LINENO" "fgetpos" "ac_cv_func_fgetpos" +if test "x$ac_cv_func_fgetpos" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FGETPOS 1 +_ACEOF + +fi +done + +for ac_func in fsetpos +do : + ac_fn_c_check_func "$LINENO" "fsetpos" "ac_cv_func_fsetpos" +if test "x$ac_cv_func_fsetpos" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FSETPOS 1 +_ACEOF + +fi +done + + +for ac_header in sys/poll.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$ac_includes_default +" +if test "x$ac_cv_header_sys_poll_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_POLL_H 1 +_ACEOF + +fi + +done + +for ac_header in poll.h +do : + ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default +" +if test "x$ac_cv_header_poll_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_POLL_H 1 +_ACEOF + +fi + +done + +for ac_func in poll +do : + ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" +if test "x$ac_cv_func_poll" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_POLL 1 +_ACEOF + +fi +done + +for ac_func in ppoll +do : + ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll" +if test "x$ac_cv_func_ppoll" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PPOLL 1 +_ACEOF + +fi +done + +for ac_func in pselect +do : + ac_fn_c_check_func "$LINENO" "pselect" "ac_cv_func_pselect" +if test "x$ac_cv_func_pselect" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PSELECT 1 +_ACEOF + +fi +done + + +ac_fn_c_check_func "$LINENO" "socketpair" "ac_cv_func_socketpair" +if test "x$ac_cv_func_socketpair" = xyes; then : + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socketpair in -lsocket" >&5 +$as_echo_n "checking for socketpair in -lsocket... " >&6; } +if ${ac_cv_lib_socket_socketpair+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socketpair (); +int +main () +{ +return socketpair (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_socketpair=yes +else + ac_cv_lib_socket_socketpair=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socketpair" >&5 +$as_echo "$ac_cv_lib_socket_socketpair" >&6; } +if test "x$ac_cv_lib_socket_socketpair" = xyes; then : + + SOCKET_LIBS="-lsocket" + + +fi + + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken poll" >&5 +$as_echo_n "checking for broken poll... " >&6; } +if test "$cross_compiling" = yes; then : + broken_poll="no (cross compiling)" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #ifdef HAVE_SYS_POLL_H + #include + #endif + #ifdef HAVE_POLL_H + #include + #endif + int main(void) { + struct pollfd fds[1]; + int fd; + fd = open("/dev/null", 1); + fds[0].fd = fd; + fds[0].events = POLLIN; + fds[0].revents = 0; + if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) { + exit(1); /* Does not work for devices -- fail */ + } + exit(0); + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + broken_poll=no +else + broken_poll=yes + +$as_echo "#define BROKEN_POLL 1" >>confdefs.h + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $broken_poll" >&5 +$as_echo "$broken_poll" >&6; } + +for ac_func in getpagesize +do : + ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" +if test "x$ac_cv_func_getpagesize" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPAGESIZE 1 +_ACEOF + +fi +done + + +CLOCK_GETTIME_FOUND="no" +ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + CLOCK_GETTIME_FOUND="yes" +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if ${ac_cv_lib_rt_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 +$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } +if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : + + CLOCK_GETTIME_FOUND="yes" + LIBS="$LIBS -lrt" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lpthread" >&5 +$as_echo_n "checking for clock_gettime in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_clock_gettime=yes +else + ac_cv_lib_pthread_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_clock_gettime" >&5 +$as_echo "$ac_cv_lib_pthread_clock_gettime" >&6; } +if test "x$ac_cv_lib_pthread_clock_gettime" = xyes; then : + + CLOCK_GETTIME_FOUND="yes" + LIBS="$LIBS -lpthread" + +fi + + +fi + + +fi + + +# With XCode 8, clock_gettime will be incorrectly detected as being available +# regardless of what version of OS X you target because the symbol is available +# in the .tbd file as a weak symbol. +# See: https://bugzilla.gnome.org/show_bug.cgi?id=772451 +# +# We cannot simply do AC_CHECK_FUNCS with -Wl,-no_weak_imports because the +# autoconf check does its own prototype declaration that doesn't trigger that +# compiler flag. +# +# It's only starting from macOS 10.12 and iOS 10.0 that clock_gettime is +# actually available, so we can unconditionally disable it for older versions. +case "$host_os" in + darwin*) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#if defined(TARGET_OS_MAC) +# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 +# error "Not compiling for OS X 10.12 or later" +# endif +#else +# if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 +# error "Not compiling for iOS 10.0 or later" +# endif +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + + if test "$CLOCK_GETTIME_FOUND" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Disabling incorrectly detected clock_gettime on OS X" >&5 +$as_echo "$as_me: Disabling incorrectly detected clock_gettime on OS X" >&6;} + fi + CLOCK_GETTIME_FOUND="no" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; +esac + +if test "$CLOCK_GETTIME_FOUND" = "yes"; then + +$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for posix timers" >&5 +$as_echo_n "checking for posix timers... " >&6; } +if ${gst_cv_posix_timers+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +int +main () +{ + +#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 || !defined(CLOCK_REALTIME) +#error Either _POSIX_TIMERS or CLOCK_REALTIME not defined +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + gst_cv_posix_timers=yes + +else + + gst_cv_posix_timers=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_posix_timers" >&5 +$as_echo "$gst_cv_posix_timers" >&6; } + +if test "$gst_cv_posix_timers" = "yes"; then + +$as_echo "#define HAVE_POSIX_TIMERS 1" >>confdefs.h + + GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 1" +else + GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 0" +fi + + if test "$gst_cv_posix_timers" = "yes"; then + GST_HAVE_POSIX_TIMERS_TRUE= + GST_HAVE_POSIX_TIMERS_FALSE='#' +else + GST_HAVE_POSIX_TIMERS_TRUE='#' + GST_HAVE_POSIX_TIMERS_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for monotonic clock" >&5 +$as_echo_n "checking for monotonic clock... " >&6; } +if ${gst_cv_monotonic_clock+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +int +main () +{ + +#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 || !defined(CLOCK_MONOTONIC) +#error Either _POSIX_MONOTONIC_CLOCK or CLOCK_MONOTONIC not defined +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + gst_cv_monotonic_clock=yes + +else + + gst_cv_monotonic_clock=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_monotonic_clock" >&5 +$as_echo "$gst_cv_monotonic_clock" >&6; } + +if test "$gst_cv_monotonic_clock" = "yes"; then + +$as_echo "#define HAVE_MONOTONIC_CLOCK 1" >>confdefs.h + + GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 1" +else + GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 0" +fi + + if test "$gst_cv_monotonic_clock" = "yes"; then + GST_HAVE_MONOTONIC_CLOCK_TRUE= + GST_HAVE_MONOTONIC_CLOCK_FALSE='#' +else + GST_HAVE_MONOTONIC_CLOCK_TRUE='#' + GST_HAVE_MONOTONIC_CLOCK_FALSE= +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __PRETTY_FUNCTION__" >&5 +$as_echo_n "checking whether $CC implements __PRETTY_FUNCTION__... " >&6; } + if ${gst_cv_have_pretty_function+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +printf("%s", __PRETTY_FUNCTION__); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gst_cv_have_pretty_function=yes +else + gst_cv_have_pretty_function=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_have_pretty_function" >&5 +$as_echo "$gst_cv_have_pretty_function" >&6; } + if test "$gst_cv_have_pretty_function" = yes; then + +$as_echo "#define HAVE_PRETTY_FUNCTION 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5 +$as_echo_n "checking whether $CC implements __FUNCTION__... " >&6; } + if ${gst_cv_have_function+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +printf("%s", __FUNCTION__); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gst_cv_have_function=yes +else + gst_cv_have_function=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_have_function" >&5 +$as_echo "$gst_cv_have_function" >&6; } + if test "$gst_cv_have_function" = yes; then + +$as_echo "#define HAVE_FUNCTION 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5 +$as_echo_n "checking whether $CC implements __func__... " >&6; } + if ${gst_cv_have_func+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +printf("%s", __func__); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gst_cv_have_func=yes +else + gst_cv_have_func=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gst_cv_have_func" >&5 +$as_echo "$gst_cv_have_func" >&6; } + if test "$gst_cv_have_func" = yes; then + +$as_echo "#define HAVE_FUNC 1" >>confdefs.h + + fi + + 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 + +cat >>confdefs.h <<_ACEOF +#define GST_FUNCTION $function +_ACEOF + + + +save_cflags="$CFLAGS" +CFLAGS="$CFLAGS -D_GNU_SOURCE" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dladdr in -ldl" >&5 +$as_echo_n "checking for dladdr in -ldl... " >&6; } +if ${ac_cv_lib_dl_dladdr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dladdr (); +int +main () +{ +return dladdr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dladdr=yes +else + ac_cv_lib_dl_dladdr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dladdr" >&5 +$as_echo "$ac_cv_lib_dl_dladdr" >&6; } +if test "x$ac_cv_lib_dl_dladdr" = xyes; then : + +$as_echo "#define HAVE_DLADDR 1" >>confdefs.h + + LIBS="$LIBS -ldl" +fi + +CFLAGS="$save_cflags" + +if test "x${GST_DISABLE_GST_DEBUG}" != "xyes"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 +$as_echo_n "checking for long long int... " >&6; } +if ${ac_cv_type_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if test "$cross_compiling" = yes; then : + ac_cv_type_long_long_int=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #ifndef LLONG_MAX + # define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + # define LLONG_MAX (HALF - 1 + HALF) + #endif +int +main () +{ +long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_type_long_long_int=yes +else + ac_cv_type_long_long_int=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + ac_cv_type_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 +$as_echo "$ac_cv_type_long_long_int" >&6; } + if test $ac_cv_type_long_long_int = yes; then + +$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 +$as_echo_n "checking for unsigned long long int... " >&6; } +if ${ac_cv_type_unsigned_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_type_unsigned_long_long_int=yes +else + ac_cv_type_unsigned_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 +$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } + if test $ac_cv_type_unsigned_long_long_int = yes; then + +$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h + + fi + + + if test x$ac_cv_type_long_long_int$ac_cv_type_unsigned_long_long_int = xyesyes; then + +$as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inttypes.h" >&5 +$as_echo_n "checking for inttypes.h... " >&6; } +if ${gl_cv_header_inttypes_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_inttypes_h=yes +else + gl_cv_header_inttypes_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_inttypes_h" >&5 +$as_echo "$gl_cv_header_inttypes_h" >&6; } + if test $gl_cv_header_inttypes_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint.h" >&5 +$as_echo_n "checking for stdint.h... " >&6; } +if ${gl_cv_header_stdint_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_stdint_h=yes +else + gl_cv_header_stdint_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_stdint_h" >&5 +$as_echo "$gl_cv_header_stdint_h" >&6; } + if test $gl_cv_header_stdint_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" +if test "x$ac_cv_type_ptrdiff_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_PTRDIFF_T 1 +_ACEOF + + +fi + + + + + ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "$ac_includes_default" +if test "x$ac_cv_type_intmax_t" = xyes; then : + +$as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h + +else + test $ac_cv_type_long_long_int = yes \ + && ac_type='long long int' \ + || ac_type='long int' + +cat >>confdefs.h <<_ACEOF +#define intmax_t $ac_type +_ACEOF + +fi + + + ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +fi + + +GLIB_REQ=2.40.0 + + + + GLIB_REQ=$GLIB_REQ + if test "x$GLIB_REQ" = "x" + then + as_fn_error $? "Please specify a required version for GLib 2.0" "$LINENO" 5 + fi + + + + which="glib-2.0 >= $GLIB_REQ gobject-2.0 gmodule-no-export-2.0" + required="no" + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 +$as_echo_n "checking for GLIB... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GLIB_CFLAGS"; then + pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$which\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$which") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "$which" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GLIB_LIBS"; then + pkg_cv_GLIB_LIBS="$GLIB_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$which\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$which") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "$which" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$which"` + else + GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$which"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + HAVE_GLIB="no" + if test "x$required" = "xyes"; then + as_fn_error $? "$GLIB_PKG_ERRORS" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: $GLIB_PKG_ERRORS" >&5 +$as_echo "$as_me: $GLIB_PKG_ERRORS" >&6;} + fi + +elif test $pkg_failed = untried; then + + HAVE_GLIB="no" + if test "x$required" = "xyes"; then + as_fn_error $? "$GLIB_PKG_ERRORS" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: $GLIB_PKG_ERRORS" >&5 +$as_echo "$as_me: $GLIB_PKG_ERRORS" >&6;} + fi + +else + GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS + GLIB_LIBS=$pkg_cv_GLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + HAVE_GLIB="yes" + +fi + + + + if test "x$HAVE_GLIB" = "xno"; then + as_fn_error $? "This package requires GLib >= $GLIB_REQ to compile." "$LINENO" 5 + fi + + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_THREADS_MANDATORY" + + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_DEPRECATED" + fi + + # Check whether --enable-gobject-cast-checks was given. +if test "${enable_gobject_cast_checks+set}" = set; then : + enableval=$enable_gobject_cast_checks; enable_gobject_cast_checks=$enableval +else + enable_gobject_cast_checks=auto +fi + + + if test "x$enable_gobject_cast_checks" = "xauto"; then + if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "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 + + # Check whether --enable-glib-asserts was given. +if test "${enable_glib_asserts+set}" = set; then : + enableval=$enable_glib_asserts; enable_glib_assertions=$enableval +else + enable_glib_assertions=yes +fi + + + if test "x$enable_glib_assertions" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_ASSERT" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glib-genmarshal" >&5 +$as_echo_n "checking for glib-genmarshal... " >&6; } + if test "x$GLIB_GENMARSHAL" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_GENMARSHAL (from environment)" >&5 +$as_echo "$GLIB_GENMARSHAL (from environment)" >&6; } + else + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + if $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_GENMARSHAL (from pkg-config path)" >&5 +$as_echo "$GLIB_GENMARSHAL (from pkg-config path)" >&6; } + else + # Extract the first word of "glib-genmarshal", so it can be a program name with args. +set dummy glib-genmarshal; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GLIB_GENMARSHAL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GLIB_GENMARSHAL in + [\\/]* | ?:[\\/]*) + ac_cv_path_GLIB_GENMARSHAL="$GLIB_GENMARSHAL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GLIB_GENMARSHAL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GLIB_GENMARSHAL" && ac_cv_path_GLIB_GENMARSHAL="glib-genmarshal" + ;; +esac +fi +GLIB_GENMARSHAL=$ac_cv_path_GLIB_GENMARSHAL +if test -n "$GLIB_GENMARSHAL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_GENMARSHAL" >&5 +$as_echo "$GLIB_GENMARSHAL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_GENMARSHAL" >&5 +$as_echo "$GLIB_GENMARSHAL" >&6; } + fi + fi + if ! $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $GLIB_GENMARSHAL does not seem to work!" >&5 +$as_echo "$as_me: WARNING: $GLIB_GENMARSHAL does not seem to work!" >&2;} + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glib-mkenums" >&5 +$as_echo_n "checking for glib-mkenums... " >&6; } + if test "x$GLIB_MKENUMS" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_MKENUMS (from environment)" >&5 +$as_echo "$GLIB_MKENUMS (from environment)" >&6; } + else + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_MKENUMS" >&5 +$as_echo "$GLIB_MKENUMS" >&6; } + fi + if ! $GLIB_MKENUMS --version 2>/dev/null >/dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $GLIB_MKENUMS does not seem to work!" >&5 +$as_echo "$as_me: WARNING: $GLIB_MKENUMS does not seem to work!" >&2;} + fi + + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GIO" >&5 +$as_echo_n "checking for GIO... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GIO_CFLAGS"; then + pkg_cv_GIO_CFLAGS="$GIO_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= \$GLIB_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gio-2.0 >= $GLIB_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GIO_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= $GLIB_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GIO_LIBS"; then + pkg_cv_GIO_LIBS="$GIO_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= \$GLIB_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gio-2.0 >= $GLIB_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GIO_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= $GLIB_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gio-2.0 >= $GLIB_REQ"` + else + GIO_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gio-2.0 >= $GLIB_REQ"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GIO_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gio-2.0 >= $GLIB_REQ) were not met: + +$GIO_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GIO_CFLAGS +and GIO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "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. + +Alternatively, you may set the environment variables GIO_CFLAGS +and GIO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GIO_CFLAGS=$pkg_cv_GIO_CFLAGS + GIO_LIBS=$pkg_cv_GIO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + if test "x$HAVE_GIO" = "xno"; then + as_fn_error $? "This package requires GIO >= $GLIB_REQ to compile." "$LINENO" 5 + fi + + GIO_MODULE_DIR="`$PKG_CONFIG --variable=giomoduledir gio-2.0`" + +cat >>confdefs.h <<_ACEOF +#define GIO_MODULE_DIR "$GIO_MODULE_DIR" +_ACEOF + + GIO_LIBDIR="`$PKG_CONFIG --variable=libdir gio-2.0`" + +cat >>confdefs.h <<_ACEOF +#define GIO_LIBDIR "$GIO_LIBDIR" +_ACEOF + + GIO_PREFIX="`$PKG_CONFIG --variable=prefix gio-2.0`" + +cat >>confdefs.h <<_ACEOF +#define GIO_PREFIX "$GIO_PREFIX" +_ACEOF + + + + + + + +GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" + + +HAVE_GTK=no +GTK_REQ=3.10 +if test "x$BUILD_EXAMPLES" = "xyes"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5 +$as_echo_n "checking for GTK... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GTK_CFLAGS"; then + pkg_cv_GTK_CFLAGS="$GTK_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= \$GTK_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= $GTK_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-3.0 >= $GTK_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GTK_LIBS"; then + pkg_cv_GTK_LIBS="$GTK_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= \$GTK_REQ\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= $GTK_REQ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-3.0 >= $GTK_REQ" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gtk+-3.0 >= $GTK_REQ"` + else + GTK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gtk+-3.0 >= $GTK_REQ"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTK_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_GTK=no +elif test $pkg_failed = untried; then + HAVE_GTK=no +else + GTK_CFLAGS=$pkg_cv_GTK_CFLAGS + GTK_LIBS=$pkg_cv_GTK_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_GTK=yes +fi + + +fi + if test "x$HAVE_GTK" = "xyes"; then + HAVE_GTK_TRUE= + HAVE_GTK_FALSE='#' +else + HAVE_GTK_TRUE='#' + HAVE_GTK_FALSE= +fi + + + +# Check whether --with-unwind was given. +if test "${with_unwind+set}" = set; then : + withval=$with_unwind; +else + with_unwind=auto +fi + +if test "x${with_unwind}" != "xno" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for UNWIND" >&5 +$as_echo_n "checking for UNWIND... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$UNWIND_CFLAGS"; then + pkg_cv_UNWIND_CFLAGS="$UNWIND_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libunwind\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libunwind") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_UNWIND_CFLAGS=`$PKG_CONFIG --cflags "libunwind" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$UNWIND_LIBS"; then + pkg_cv_UNWIND_LIBS="$UNWIND_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libunwind\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libunwind") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_UNWIND_LIBS=`$PKG_CONFIG --libs "libunwind" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + UNWIND_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libunwind"` + else + UNWIND_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libunwind"` + fi + # Put the nasty error message in config.log where it belongs + echo "$UNWIND_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + HAVE_UNWIND=no + if test "x${with_unwind}" = "xyes" ; then + as_fn_error $? "could not find libunwind" "$LINENO" 5 + fi + +elif test $pkg_failed = untried; then + + HAVE_UNWIND=no + if test "x${with_unwind}" = "xyes" ; then + as_fn_error $? "could not find libunwind" "$LINENO" 5 + fi + +else + UNWIND_CFLAGS=$pkg_cv_UNWIND_CFLAGS + UNWIND_LIBS=$pkg_cv_UNWIND_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + HAVE_UNWIND=yes + +$as_echo "#define HAVE_UNWIND 1" >>confdefs.h + + UNWIND_REQUIRE=libunwind + + +fi +else + HAVE_UNWIND=no +fi + + +# Check whether --with-dw was given. +if test "${with_dw+set}" = set; then : + withval=$with_dw; +else + with_dw=auto +fi + +if test "x${with_dw}" != "xno" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DW" >&5 +$as_echo_n "checking for DW... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$DW_CFLAGS"; then + pkg_cv_DW_CFLAGS="$DW_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdw\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libdw") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DW_CFLAGS=`$PKG_CONFIG --cflags "libdw" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$DW_LIBS"; then + pkg_cv_DW_LIBS="$DW_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdw\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libdw") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DW_LIBS=`$PKG_CONFIG --libs "libdw" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + DW_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libdw"` + else + DW_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libdw"` + fi + # Put the nasty error message in config.log where it belongs + echo "$DW_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + HAVE_DW=no + if test "x${with_dw}" = "xyes" ; then + as_fn_error $? "could not find libdw" "$LINENO" 5 + fi + +elif test $pkg_failed = untried; then + + HAVE_DW=no + if test "x${with_dw}" = "xyes" ; then + as_fn_error $? "could not find libdw" "$LINENO" 5 + fi + +else + DW_CFLAGS=$pkg_cv_DW_CFLAGS + DW_LIBS=$pkg_cv_DW_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + HAVE_DW=yes + +$as_echo "#define HAVE_DW 1" >>confdefs.h + + DW_REQUIRE=libdw + + +fi +else + HAVE_DW=no +fi + +ac_fn_c_check_func "$LINENO" "backtrace" "ac_cv_func_backtrace" +if test "x$ac_cv_func_backtrace" = xyes; then : + + for ac_header in execinfo.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" +if test "x$ac_cv_header_execinfo_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXECINFO_H 1 +_ACEOF + + +$as_echo "#define HAVE_BACKTRACE 1" >>confdefs.h + + +fi + +done + + +fi + + +# Check whether --enable-check was given. +if test "${enable_check+set}" = set; then : + enableval=$enable_check; + case "${enableval}" in + yes) BUILD_CHECK=yes ;; + no) BUILD_CHECK=no ;; + *) as_fn_error $? "bad value ${enableval} for --disable-check" "$LINENO" 5 ;; + esac + +else + + case $host_os in + mingw* | msvc* | mks*) BUILD_CHECK=no ;; + *) BUILD_CHECK=yes ;; + esac + +fi + + if test "x$BUILD_CHECK" = "xyes"; then + HAVE_CHECK_TRUE= + HAVE_CHECK_FALSE='#' +else + HAVE_CHECK_TRUE='#' + HAVE_CHECK_FALSE= +fi + + + +# Check whether --with-memory-alignment was given. +if test "${with_memory_alignment+set}" = set; then : + withval=$with_memory_alignment; + if test "x$withval" = "xyes" + then + +$as_echo "#define MEMORY_ALIGNMENT 32" >>confdefs.h + + else + case "${withval}" in + malloc) +$as_echo "#define MEMORY_ALIGNMENT_MALLOC 1" >>confdefs.h + ;; + pagesize) +$as_echo "#define MEMORY_ALIGNMENT_PAGESIZE 1" >>confdefs.h + ;; + *) +cat >>confdefs.h <<_ACEOF +#define MEMORY_ALIGNMENT ${withval} +_ACEOF + ;; + esac + fi + +else + + +$as_echo "#define MEMORY_ALIGNMENT_MALLOC 1" >>confdefs.h + + + +fi + + +# Check whether --enable-Bsymbolic was given. +if test "${enable_Bsymbolic+set}" = set; then : + enableval=$enable_Bsymbolic; +else + SAVED_LDFLAGS="${LDFLAGS}" SAVED_LIBS="${LIBS}" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Bsymbolic-functions linker flag" >&5 +$as_echo_n "checking for -Bsymbolic-functions linker flag... " >&6; } + LDFLAGS=-Wl,-Bsymbolic-functions + LIBS= + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 0 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_Bsymbolic=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + enable_Bsymbolic=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="${SAVED_LDFLAGS}" LIBS="${SAVED_LIBS}" +fi + + + + +GST_LICENSE="LGPL" + +cat >>confdefs.h <<_ACEOF +#define GST_LICENSE "$GST_LICENSE" +_ACEOF + + + + + EXP_VAR=LIBDIR + FROM_VAR=$libdir + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + LIBDIR="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define LIBDIR "$LIBDIR" +_ACEOF + + + EXP_VAR=DATADIR + FROM_VAR=$datadir + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + DATADIR="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define GST_DATADIR "$DATADIR" +_ACEOF + + + + + EXP_VAR=PLUGINDIR + FROM_VAR=${libdir}/gstreamer-$GST_API_VERSION + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + PLUGINDIR="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define PLUGINDIR "$PLUGINDIR" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $PLUGINDIR as the plugin install location" >&5 +$as_echo "$as_me: Using $PLUGINDIR as the plugin install location" >&6;} + + plugindir="\$(libdir)/gstreamer-$GST_API_VERSION" + + + +NO_WARNINGS="" +if test "x${GST_DISABLE_GST_DEBUG}" = "xyes"; then + NO_WARNINGS="-Wno-unused" +fi + + + + + + WARNING_CFLAGS="" + ERROR_CFLAGS="" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wall" >&5 +$as_echo_n "checking to see if compiler understands -Wall... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wall" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + WARNING_CFLAGS="$WARNING_CFLAGS -Wall" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wdeclaration-after-statement" >&5 +$as_echo_n "checking to see if compiler understands -Wdeclaration-after-statement... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wdeclaration-after-statement" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + WARNING_CFLAGS="$WARNING_CFLAGS -Wdeclaration-after-statement" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wvla" >&5 +$as_echo_n "checking to see if compiler understands -Wvla... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wvla" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + WARNING_CFLAGS="$WARNING_CFLAGS -Wvla" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wpointer-arith" >&5 +$as_echo_n "checking to see if compiler understands -Wpointer-arith... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wpointer-arith" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + WARNING_CFLAGS="$WARNING_CFLAGS -Wpointer-arith" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + if test "x$FATAL_WARNINGS" != "xno" + then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror" >&5 +$as_echo_n "checking to see if compiler understands -Werror... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + ERROR_CFLAGS="$ERROR_CFLAGS -Werror" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + fi + + if test "x-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar -Wnested-externs $NO_WARNINGS" != "x" + then + UNSUPPORTED="" + list="-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar -Wnested-externs $NO_WARNINGS" + for each in $list + do + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands $each" >&5 +$as_echo_n "checking to see if compiler understands $each... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + WARNING_CFLAGS="$WARNING_CFLAGS $each" + true + else + UNSUPPORTED="$UNSUPPORTED $each" + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + done + if test "X$UNSUPPORTED" != X ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: unsupported compiler flags: $UNSUPPORTED" >&5 +$as_echo "$as_me: unsupported compiler flags: $UNSUPPORTED" >&6;} + fi + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: set WARNING_CFLAGS to $WARNING_CFLAGS" >&5 +$as_echo "$as_me: set WARNING_CFLAGS to $WARNING_CFLAGS" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: set ERROR_CFLAGS to $ERROR_CFLAGS" >&5 +$as_echo "$as_me: set ERROR_CFLAGS to $ERROR_CFLAGS" >&6;} + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wno-format-nonliteral" >&5 +$as_echo_n "checking to see if compiler understands -Wno-format-nonliteral... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wno-format-nonliteral" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + PRINTF_CFLAGS="-Wno-format-nonliteral" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -fno-strict-aliasing" >&5 +$as_echo_n "checking to see if compiler understands -fno-strict-aliasing... " >&6; } + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-strict-aliasing" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + EXTRA_CFLAGS="-fno-strict-aliasing" + true + else + + true + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 +$as_echo "$flag_ok" >&6; } + + + + + if test "x$GST_GIT" = "xyes"; then + GST_LEVEL_DEFAULT=GST_LEVEL_ERROR + else + GST_LEVEL_DEFAULT=GST_LEVEL_NONE + fi + +cat >>confdefs.h <<_ACEOF +#define GST_LEVEL_DEFAULT $GST_LEVEL_DEFAULT +_ACEOF + + + + + + +if test "x$USE_DEBUG" = xyes; then + PROFILE_CFLAGS="-g" +fi + + +# GST_DISABLE_DEPRECATED: hide the visibility of deprecated +# functionality from the API that gstreamer uses +# GST_REMOVE_DEPRECATED: don't compile deprecated functionality (breaks ABI) +if test "x$PACKAGE_VERSION_NANO" = "x1"; then + DEPRECATED_CFLAGS="-DGST_DISABLE_DEPRECATED" +else + DEPRECATED_CFLAGS="" +fi + + +GST_OPTION_CFLAGS="\$(WARNING_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)" +GST_OPTION_CFLAGS="$GST_OPTION_CFLAGS" +GST_OPTION_CXXFLAGS="$GST_OPTION_CXXFLAGS" + + + +GST_ALL_CXXFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CXXFLAGS) \$(ERROR_CXXFLAGS)" +GST_ALL_CFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CFLAGS) \$(ERROR_CFLAGS)" + +GST_ALL_LIBS="$GLIB_LIBS $LTLIBINTL \$(GCOV_LIBS)" + +GST_ALL_LDFLAGS="-no-undefined" +if test "x${enable_Bsymbolic}" = "xyes"; then + GST_ALL_LDFLAGS="$GST_ALL_LDFLAGS -Wl,-Bsymbolic-functions" +fi + + + + + + +GST_LIB_LDFLAGS="-export-symbols-regex \^_?\(gst_\|Gst\|GST_\).*" + + +GST_OBJ_CFLAGS="\$(GST_ALL_CFLAGS) $GST_OBJ_STATIC_CFLAGS" +GST_OBJ_CXXFLAGS="\$(GST_ALL_CXXFLAGS) $GST_OBJ_STATIC_CFLAGS" +GST_OBJ_LIBS="\$(top_builddir)/gst/libgstreamer-$GST_API_VERSION.la \$(GST_ALL_LIBS)" + + + + +GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^_*gst_plugin_.*' $GST_ALL_LDFLAGS" +GST_PLUGIN_LDFLAGS="$GST_PLUGIN_LDFLAGS" + + + + EXP_VAR=GST_PLUGIN_SCANNER_INSTALLED + FROM_VAR=${libexecdir}/gstreamer-$GST_API_VERSION/gst-plugin-scanner + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + GST_PLUGIN_SCANNER_INSTALLED="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define GST_PLUGIN_SCANNER_INSTALLED "$GST_PLUGIN_SCANNER_INSTALLED" +_ACEOF + + + +case "${libexecdir}" in + *libexec) + GST_PLUGIN_SCANNER_SUBDIR="libexec";; + *lib) + GST_PLUGIN_SCANNER_SUBDIR="lib";; + *) + GST_PLUGIN_SCANNER_SUBDIR=`basename ${libexecdir}`; + if test -z "$GST_PLUGIN_SCANNER_SUBDIR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Couldn't determined libexecdir suffix, using \"lib\"" >&5 +$as_echo "$as_me: WARNING: Couldn't determined libexecdir suffix, using \"lib\"" >&2;} + GST_PLUGIN_SCANNER_SUBDIR="lib"; + fi + ;; +esac + +cat >>confdefs.h <<_ACEOF +#define GST_PLUGIN_SCANNER_SUBDIR "$GST_PLUGIN_SCANNER_SUBDIR" +_ACEOF + + + + + EXP_VAR=GST_COMPLETION_HELPER_INSTALLED + FROM_VAR=${libexecdir}/gstreamer-$GST_API_VERSION/gst-completion-helper + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + GST_COMPLETION_HELPER_INSTALLED="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define GST_COMPLETION_HELPER_INSTALLED "$GST_COMPLETION_HELPER_INSTALLED" +_ACEOF + + + + + EXP_VAR=GST_PTP_HELPER_INSTALLED + FROM_VAR=${libexecdir}/gstreamer-$GST_API_VERSION/gst-ptp-helper + + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + 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 + + full_var=$new_full_var + GST_PTP_HELPER_INSTALLED="$full_var" + + + prefix=$prefix_save + exec_prefix=$exec_prefix_save + + +cat >>confdefs.h <<_ACEOF +#define GST_PTP_HELPER_INSTALLED "$GST_PTP_HELPER_INSTALLED" +_ACEOF + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Running check unit test framework checks now..." >&5 +$as_echo "$as_me: Running check unit test framework checks now..." >&6;} + +CHECK_MAJOR_VERSION=0 +CHECK_MINOR_VERSION=10 +CHECK_MICRO_VERSION=0 +CHECK_VERSION=$CHECK_MAJOR_VERSION.$CHECK_MINOR_VERSION.$CHECK_MICRO_VERSION + + + + + + +for ac_header in unistd.h sys/wait.h sys/time.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in localtime_r +do : + ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALTIME_R 1 +_ACEOF + +fi +done + + if test "x$ac_cv_func_localtime_r" = "xyes"; then + HAVE_LOCALTIME_R_TRUE= + HAVE_LOCALTIME_R_FALSE='#' +else + HAVE_LOCALTIME_R_TRUE='#' + HAVE_LOCALTIME_R_FALSE= +fi + + +for ac_func in gettimeofday +do : + ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETTIMEOFDAY 1 +_ACEOF + +fi +done + + if test "x$ac_cv_func_gettimeofday" = "xyes"; then + HAVE_GETTIMEOFDAY_TRUE= + HAVE_GETTIMEOFDAY_FALSE='#' +else + HAVE_GETTIMEOFDAY_TRUE='#' + HAVE_GETTIMEOFDAY_FALSE= +fi + + +for ac_func in getpid _getpid +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_fn_c_check_decl "$LINENO" "strdup" "ac_cv_have_decl_strdup" "$ac_includes_default" +if test "x$ac_cv_have_decl_strdup" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRDUP $ac_have_decl +_ACEOF + +for ac_func in _strdup +do : + ac_fn_c_check_func "$LINENO" "_strdup" "ac_cv_func__strdup" +if test "x$ac_cv_func__strdup" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE__STRDUP 1 +_ACEOF + +fi +done + + if test "x$ac_cv_have_decl_strdup" = "xyes" -o "x$ac_cv_func__strdup" = "xyes"; then + HAVE_STRDUP_TRUE= + HAVE_STRDUP_FALSE='#' +else + HAVE_STRDUP_TRUE='#' + HAVE_STRDUP_FALSE= +fi + + +for ac_func in getline +do : + ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" +if test "x$ac_cv_func_getline" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETLINE 1 +_ACEOF + +fi +done + + if test "x$ac_cv_func_getline" = "xyes"; then + HAVE_GETLINE_TRUE= + HAVE_GETLINE_FALSE='#' +else + HAVE_GETLINE_TRUE='#' + HAVE_GETLINE_FALSE= +fi + + +for ac_func in mkstemp +do : + ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" +if test "x$ac_cv_func_mkstemp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MKSTEMP 1 +_ACEOF + +fi +done + + +for ac_func in fork +do : + ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork" +if test "x$ac_cv_func_fork" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FORK 1 +_ACEOF + HAVE_FORK=1 +else + HAVE_FORK=0 +fi +done + + + +for ac_header in time.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" +if test "x$ac_cv_header_time_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TIME_H 1 +_ACEOF + +fi + +done + +ac_fn_c_check_decl "$LINENO" "alarm" "ac_cv_have_decl_alarm" " + $ac_includes_default +#if HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ + +" +if test "x$ac_cv_have_decl_alarm" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ALARM $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " + $ac_includes_default +#if HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ + +" +if test "x$ac_cv_have_decl_localtime_r" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_LOCALTIME_R $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "strsignal" "ac_cv_have_decl_strsignal" " + $ac_includes_default +#if HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ + +" +if test "x$ac_cv_have_decl_strsignal" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRSIGNAL $ac_have_decl +_ACEOF + +for ac_func in alarm setitimer strsignal +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + if test "x$ac_cv_func_alarm" = "xyes"; then + HAVE_ALARM_TRUE= + HAVE_ALARM_FALSE='#' +else + HAVE_ALARM_TRUE='#' + HAVE_ALARM_FALSE= +fi + + if test "x$ac_cv_func_localtime_r" = "xyes"; then + HAVE_LOCALTIME_R_TRUE= + HAVE_LOCALTIME_R_FALSE='#' +else + HAVE_LOCALTIME_R_TRUE='#' + HAVE_LOCALTIME_R_FALSE= +fi + + if test "x$ac_cv_func_strsignal" = "xyes"; then + HAVE_STRSIGNAL_TRUE= + HAVE_STRSIGNAL_FALSE='#' +else + HAVE_STRSIGNAL_TRUE='#' + HAVE_STRSIGNAL_FALSE= +fi + + +ac_fn_c_check_member "$LINENO" "struct timespec" "tv_sec" "ac_cv_member_struct_timespec_tv_sec" " +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_member_struct_timespec_tv_sec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TIMESPEC_TV_SEC 1 +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define STRUCT_TIMESPEC_DEFINITION_MISSING 1 +_ACEOF + +fi +ac_fn_c_check_member "$LINENO" "struct timespec" "tv_nsec" "ac_cv_member_struct_timespec_tv_nsec" " +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_member_struct_timespec_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TIMESPEC_TV_NSEC 1 +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define STRUCT_TIMESPEC_DEFINITION_MISSING 1 +_ACEOF + +fi + +ac_fn_c_check_member "$LINENO" "struct itimerspec" "it_interval" "ac_cv_member_struct_itimerspec_it_interval" " +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_member_struct_itimerspec_it_interval" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ITIMERSPEC_IT_INTERVAL 1 +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define STRUCT_ITIMERSPEC_DEFINITION_MISSING 1 +_ACEOF + +fi +ac_fn_c_check_member "$LINENO" "struct itimerspec" "it_value" "ac_cv_member_struct_itimerspec_it_value" " +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_member_struct_itimerspec_it_value" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ITIMERSPEC_IT_VALUE 1 +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define STRUCT_ITIMERSPEC_DEFINITION_MISSING 1 +_ACEOF + +fi + + +ac_fn_c_check_type "$LINENO" "timer_t" "ac_cv_type_timer_t" " + $ac_includes_default +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_type_timer_t" = xyes; then : + +else + + +$as_echo "#define timer_t int" >>confdefs.h + + +fi + +ac_fn_c_check_type "$LINENO" "clockid_t" "ac_cv_type_clockid_t" " + $ac_includes_default +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ + +" +if test "x$ac_cv_type_clockid_t" = xyes; then : + +else + + +$as_echo "#define clockid_t int" >>confdefs.h + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for timer_create, timer_settime, timer_delete in -lrt" >&5 +$as_echo_n "checking for timer_create, timer_settime, timer_delete in -lrt... " >&6; } +if ${ac_cv_lib_rt_timer_create__timer_settime__timer_delete+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char timer_create, timer_settime, timer_delete (); +int +main () +{ +return timer_create, timer_settime, timer_delete (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_timer_create__timer_settime__timer_delete=yes +else + ac_cv_lib_rt_timer_create__timer_settime__timer_delete=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_timer_create__timer_settime__timer_delete" >&5 +$as_echo "$ac_cv_lib_rt_timer_create__timer_settime__timer_delete" >&6; } +if test "x$ac_cv_lib_rt_timer_create__timer_settime__timer_delete" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBRT 1 +_ACEOF + + LIBS="-lrt $LIBS" + +fi + + if test "x$ac_cv_lib_rt_timer_create__timer_settime__timer_delete" = "xyes"; then + HAVE_TIMER_CREATE_SETTIME_DELETE_TRUE= + HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE='#' +else + HAVE_TIMER_CREATE_SETTIME_DELETE_TRUE='#' + HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE= +fi + + + if test "x$CLOCK_GETTIME_FOUND" = "xyes"; then + HAVE_CLOCK_GETTIME_TRUE= + HAVE_CLOCK_GETTIME_FALSE='#' +else + HAVE_CLOCK_GETTIME_TRUE='#' + HAVE_CLOCK_GETTIME_FALSE= +fi + + +# ------ AX CREATE STDINT H ------------------------------------- +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint types" >&5 +$as_echo_n "checking for stdint types... " >&6; } +ac_stdint_h=`echo _stdint.h` +# try to shortcircuit - if the default include path of the compiler +# can find a "stdint.h" header then we assume that all compilers can. +if ${ac_cv_header_stdint_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + +old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" +old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" +old_CFLAGS="$CFLAGS" ; CFLAGS="" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int_least32_t v = 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_stdint_result="(assuming C99 compatible system)" + ac_cv_header_stdint_t="stdint.h"; +else + ac_cv_header_stdint_t="" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then +CFLAGS="-std=c99" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int_least32_t v = 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: your GCC compiler has a defunct stdint.h for its default-mode" >&5 +$as_echo "$as_me: WARNING: your GCC compiler has a defunct stdint.h for its default-mode" >&2;} +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +CXXFLAGS="$old_CXXFLAGS" +CPPFLAGS="$old_CPPFLAGS" +CFLAGS="$old_CFLAGS" +fi + + +v="... $ac_cv_header_stdint_h" +if test "$ac_stdint_h" = "stdint.h" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (are you sure you want them in ./stdint.h?)" >&5 +$as_echo "(are you sure you want them in ./stdint.h?)" >&6; } +elif test "$ac_stdint_h" = "inttypes.h" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (are you sure you want them in ./inttypes.h?)" >&5 +$as_echo "(are you sure you want them in ./inttypes.h?)" >&6; } +elif test "_$ac_cv_header_stdint_t" = "_" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (putting them into $ac_stdint_h)$v" >&5 +$as_echo "(putting them into $ac_stdint_h)$v" >&6; } +else + ac_cv_header_stdint="$ac_cv_header_stdint_t" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint (shortcircuit)" >&5 +$as_echo "$ac_cv_header_stdint (shortcircuit)" >&6; } +fi + +if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. + + +inttype_headers=`echo | sed -e 's/,/ /g'` + +ac_cv_stdint_result="(no helpful system typedefs seen)" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uintptr_t" >&5 +$as_echo_n "checking for stdint uintptr_t... " >&6; } +if ${ac_cv_header_stdint_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 +$as_echo "(..)" >&6; } + for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers + do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <$i> +" +if test "x$ac_cv_type_uintptr_t" = xyes; then : + ac_cv_header_stdint_x=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include<$i> +" +if test "x$ac_cv_type_uint64_t" = xyes; then : + and64="/uint64_t" +else + and64="" +fi + + ac_cv_stdint_result="(seen uintptr_t$and64 in $i)" + break + done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uintptr_t" >&5 +$as_echo_n "checking for stdint uintptr_t... " >&6; } + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_x" >&5 +$as_echo "$ac_cv_header_stdint_x" >&6; } + + +if test "_$ac_cv_header_stdint_x" = "_" ; then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uint32_t" >&5 +$as_echo_n "checking for stdint uint32_t... " >&6; } +if ${ac_cv_header_stdint_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 +$as_echo "(..)" >&6; } + for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers + do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include <$i> +" +if test "x$ac_cv_type_uint32_t" = xyes; then : + ac_cv_header_stdint_o=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include<$i> +" +if test "x$ac_cv_type_uint64_t" = xyes; then : + and64="/uint64_t" +else + and64="" +fi + + ac_cv_stdint_result="(seen uint32_t$and64 in $i)" + break + break; + done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uint32_t" >&5 +$as_echo_n "checking for stdint uint32_t... " >&6; } + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_o" >&5 +$as_echo "$ac_cv_header_stdint_o" >&6; } + +fi + +if test "_$ac_cv_header_stdint_x" = "_" ; then +if test "_$ac_cv_header_stdint_o" = "_" ; then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint u_int32_t" >&5 +$as_echo_n "checking for stdint u_int32_t... " >&6; } +if ${ac_cv_header_stdint_u+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 +$as_echo "(..)" >&6; } + for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include <$i> +" +if test "x$ac_cv_type_u_int32_t" = xyes; then : + ac_cv_header_stdint_u=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include<$i> +" +if test "x$ac_cv_type_u_int64_t" = xyes; then : + and64="/u_int64_t" +else + and64="" +fi + + ac_cv_stdint_result="(seen u_int32_t$and64 in $i)" + break + break; + done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint u_int32_t" >&5 +$as_echo_n "checking for stdint u_int32_t... " >&6; } + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_u" >&5 +$as_echo "$ac_cv_header_stdint_u" >&6; } + +fi fi + +if test "_$ac_cv_header_stdint_x" = "_" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint datatype model" >&5 +$as_echo_n "checking for stdint datatype model... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 +$as_echo "(..)" >&6; } + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 +$as_echo_n "checking size of char... " >&6; } +if ${ac_cv_sizeof_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_char" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (char) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_char=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 +$as_echo "$ac_cv_sizeof_char" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR $ac_cv_sizeof_char +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void*" >&5 +$as_echo_n "checking size of void*... " >&6; } +if ${ac_cv_sizeof_voidp+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void*))" "ac_cv_sizeof_voidp" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_voidp" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (void*) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_voidp=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_voidp" >&5 +$as_echo "$ac_cv_sizeof_voidp" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOIDP $ac_cv_sizeof_voidp +_ACEOF + + + 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" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking data model" >&5 +$as_echo_n "checking data model... " >&6; } + 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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_data_model ($ac_cv_long_data_model, $n)" >&5 +$as_echo "$ac_cv_data_model ($ac_cv_long_data_model, $n)" >&6; } + +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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra inttypes in chosen header" >&5 +$as_echo_n "checking for extra inttypes in chosen header... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ($ac_cv_header_stdint)" >&5 +$as_echo "($ac_cv_header_stdint)" >&6; } +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include <$ac_cv_header_stdint> +" +if test "x$ac_cv_type_int_least32_t" = xyes; then : + +fi + +ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include<$ac_cv_header_stdint> +" +if test "x$ac_cv_type_int_fast32_t" = xyes; then : + +fi + +ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "#include <$ac_cv_header_stdint> +" +if test "x$ac_cv_type_intmax_t" = xyes; then : + +fi + + +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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: make use of $ac_cv_header_stdint in $ac_stdint_h $ac_cv_stdint_result" >&5 +$as_echo "make use of $ac_cv_header_stdint in $ac_stdint_h $ac_cv_stdint_result" >&6; } + +# ----------------- DONE inttypes.h checks START header ------------- +ac_config_commands="$ac_config_commands $ac_stdint_h" + + + +enable_subunit=false + +if test xfalse = x"$enable_subunit"; then +ENABLE_SUBUNIT="0" +else +ENABLE_SUBUNIT="1" +fi + + +cat >>confdefs.h <<_ACEOF +#define ENABLE_SUBUNIT $ENABLE_SUBUNIT +_ACEOF + + + if test x"$enable_subunit" != "xfalse"; then + SUBUNIT_TRUE= + SUBUNIT_FALSE='#' +else + SUBUNIT_TRUE='#' + SUBUNIT_FALSE= +fi + + + + +ac_config_files="$ac_config_files Makefile data/Makefile data/bash-completion/helpers/gst gst/Makefile gst/gstconfig.h gst/gstversion.h gst/parse/Makefile gst/printf/Makefile libs/Makefile libs/gst/Makefile libs/gst/base/Makefile libs/gst/check/Makefile libs/gst/check/libcheck/Makefile libs/gst/check/internal-check.h:libs/gst/check/libcheck/check.h.in libs/gst/controller/Makefile libs/gst/helpers/Makefile libs/gst/net/Makefile plugins/Makefile plugins/elements/Makefile plugins/tracers/Makefile po/Makefile.in tests/Makefile tests/benchmarks/Makefile tests/check/Makefile tests/misc/Makefile tests/examples/Makefile tests/examples/adapter/Makefile tests/examples/controller/Makefile tests/examples/stepping/Makefile tests/examples/helloworld/Makefile tests/examples/memory/Makefile tests/examples/netclock/Makefile tests/examples/ptp/Makefile tests/examples/streamiddemux/Makefile tests/examples/streams/Makefile tools/Makefile common/Makefile common/m4/Makefile docs/Makefile docs/gst/Makefile docs/gst/gstreamer.types docs/libs/Makefile docs/plugins/Makefile docs/version.entities m4/Makefile pkgconfig/Makefile stamp.h pkgconfig/gstreamer.pc pkgconfig/gstreamer-uninstalled.pc pkgconfig/gstreamer-base.pc pkgconfig/gstreamer-base-uninstalled.pc pkgconfig/gstreamer-check.pc pkgconfig/gstreamer-check-uninstalled.pc pkgconfig/gstreamer-controller.pc pkgconfig/gstreamer-controller-uninstalled.pc pkgconfig/gstreamer-net.pc pkgconfig/gstreamer-net-uninstalled.pc" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_GST_DEBUG_TRUE}" && test -z "${GST_DISABLE_GST_DEBUG_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_GST_DEBUG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_GST_TRACER_HOOKS_TRUE}" && test -z "${GST_DISABLE_GST_TRACER_HOOKS_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_GST_TRACER_HOOKS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_PARSE_TRUE}" && test -z "${GST_DISABLE_PARSE_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_PARSE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_OPTION_PARSING_TRUE}" && test -z "${GST_DISABLE_OPTION_PARSING_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_OPTION_PARSING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_REGISTRY_TRUE}" && test -z "${GST_DISABLE_REGISTRY_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_REGISTRY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_DISABLE_PLUGIN_TRUE}" && test -z "${GST_DISABLE_PLUGIN_FALSE}"; then + as_fn_error $? "conditional \"GST_DISABLE_PLUGIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_GCOV_ENABLED_TRUE}" && test -z "${GST_GCOV_ENABLED_FALSE}"; then + as_fn_error $? "conditional \"GST_GCOV_ENABLED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_EXAMPLES_TRUE}" && test -z "${BUILD_EXAMPLES_FALSE}"; then + as_fn_error $? "conditional \"BUILD_EXAMPLES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_BASH_COMPLETION_TRUE}" && test -z "${ENABLE_BASH_COMPLETION_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_BASH_COMPLETION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TESTS_TRUE}" && test -z "${BUILD_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_FAILING_TESTS_TRUE}" && test -z "${BUILD_FAILING_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FAILING_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_BENCHMARKS_TRUE}" && test -z "${BUILD_BENCHMARKS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_BENCHMARKS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TOOLS_TRUE}" && test -z "${BUILD_TOOLS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TOOLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PTP_TRUE}" && test -z "${HAVE_PTP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PTP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PTP_HELPER_SETUID_TRUE}" && test -z "${HAVE_PTP_HELPER_SETUID_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PTP_HELPER_SETUID\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PTP_HELPER_CAPABILITIES_TRUE}" && test -z "${HAVE_PTP_HELPER_CAPABILITIES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PTP_HELPER_CAPABILITIES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${HAVE_CPU_I386_TRUE}" && test -z "${HAVE_CPU_I386_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_I386\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_PPC_TRUE}" && test -z "${HAVE_CPU_PPC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_PPC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_PPC64_TRUE}" && test -z "${HAVE_CPU_PPC64_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_PPC64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_ALPHA_TRUE}" && test -z "${HAVE_CPU_ALPHA_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_ALPHA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_ARC_TRUE}" && test -z "${HAVE_CPU_ARC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_ARC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_ARM_TRUE}" && test -z "${HAVE_CPU_ARM_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_ARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_SPARC_TRUE}" && test -z "${HAVE_CPU_SPARC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_SPARC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_HPPA_TRUE}" && test -z "${HAVE_CPU_HPPA_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_HPPA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_MIPS_TRUE}" && test -z "${HAVE_CPU_MIPS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_MIPS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_S390_TRUE}" && test -z "${HAVE_CPU_S390_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_S390\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_IA64_TRUE}" && test -z "${HAVE_CPU_IA64_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_IA64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_M68K_TRUE}" && test -z "${HAVE_CPU_M68K_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_M68K\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_X86_64_TRUE}" && test -z "${HAVE_CPU_X86_64_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_X86_64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_CRIS_TRUE}" && test -z "${HAVE_CPU_CRIS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_CRIS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CPU_CRISV32_TRUE}" && test -z "${HAVE_CPU_CRISV32_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CPU_CRISV32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CXX_TRUE}" && test -z "${HAVE_CXX_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_VALGRIND_TRUE}" && test -z "${HAVE_VALGRIND_FALSE}"; then + as_fn_error $? "conditional \"HAVE_VALGRIND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_PLUGIN_DOCS_TRUE}" && test -z "${ENABLE_PLUGIN_DOCS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_PLUGIN_DOCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYS_SOCKET_H_TRUE}" && test -z "${HAVE_SYS_SOCKET_H_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYS_SOCKET_H\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYS_TIMES_H_AND_UNISTD_H_TRUE}" && test -z "${HAVE_SYS_TIMES_H_AND_UNISTD_H_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYS_TIMES_H_AND_UNISTD_H\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PTHREAD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_WINSOCK2_H_TRUE}" && test -z "${HAVE_WINSOCK2_H_FALSE}"; then + as_fn_error $? "conditional \"HAVE_WINSOCK2_H\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GETRUSAGE_TRUE}" && test -z "${HAVE_GETRUSAGE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GETRUSAGE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_HAVE_POSIX_TIMERS_TRUE}" && test -z "${GST_HAVE_POSIX_TIMERS_FALSE}"; then + as_fn_error $? "conditional \"GST_HAVE_POSIX_TIMERS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GST_HAVE_MONOTONIC_CLOCK_TRUE}" && test -z "${GST_HAVE_MONOTONIC_CLOCK_FALSE}"; then + as_fn_error $? "conditional \"GST_HAVE_MONOTONIC_CLOCK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GTK_TRUE}" && test -z "${HAVE_GTK_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GTK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CHECK_TRUE}" && test -z "${HAVE_CHECK_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CHECK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LOCALTIME_R_TRUE}" && test -z "${HAVE_LOCALTIME_R_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LOCALTIME_R\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GETTIMEOFDAY_TRUE}" && test -z "${HAVE_GETTIMEOFDAY_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GETTIMEOFDAY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_STRDUP_TRUE}" && test -z "${HAVE_STRDUP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_STRDUP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GETLINE_TRUE}" && test -z "${HAVE_GETLINE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GETLINE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_ALARM_TRUE}" && test -z "${HAVE_ALARM_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ALARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LOCALTIME_R_TRUE}" && test -z "${HAVE_LOCALTIME_R_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LOCALTIME_R\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_STRSIGNAL_TRUE}" && test -z "${HAVE_STRSIGNAL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_STRSIGNAL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_TIMER_CREATE_SETTIME_DELETE_TRUE}" && test -z "${HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_TIMER_CREATE_SETTIME_DELETE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CLOCK_GETTIME_TRUE}" && test -z "${HAVE_CLOCK_GETTIME_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CLOCK_GETTIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUBUNIT_TRUE}" && test -z "${SUBUNIT_FALSE}"; then + as_fn_error $? "conditional \"SUBUNIT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by GStreamer $as_me 1.14.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +GStreamer config.status 1.14.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in AS \ +DLLTOOL \ +OBJDUMP \ +SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + + +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + +# variables for create stdint.h replacement +PACKAGE="$PACKAGE" +VERSION="$VERSION" +ac_stdint_h="$ac_stdint_h" +_ac_stdint_h=`$as_echo "_$PACKAGE-$ac_stdint_h" | $as_tr_cpp` +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" + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; + "$ac_stdint_h") CONFIG_COMMANDS="$CONFIG_COMMANDS $ac_stdint_h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; + "data/bash-completion/helpers/gst") CONFIG_FILES="$CONFIG_FILES data/bash-completion/helpers/gst" ;; + "gst/Makefile") CONFIG_FILES="$CONFIG_FILES gst/Makefile" ;; + "gst/gstconfig.h") CONFIG_FILES="$CONFIG_FILES gst/gstconfig.h" ;; + "gst/gstversion.h") CONFIG_FILES="$CONFIG_FILES gst/gstversion.h" ;; + "gst/parse/Makefile") CONFIG_FILES="$CONFIG_FILES gst/parse/Makefile" ;; + "gst/printf/Makefile") CONFIG_FILES="$CONFIG_FILES gst/printf/Makefile" ;; + "libs/Makefile") CONFIG_FILES="$CONFIG_FILES libs/Makefile" ;; + "libs/gst/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/Makefile" ;; + "libs/gst/base/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/base/Makefile" ;; + "libs/gst/check/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/check/Makefile" ;; + "libs/gst/check/libcheck/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/check/libcheck/Makefile" ;; + "libs/gst/check/internal-check.h") CONFIG_FILES="$CONFIG_FILES libs/gst/check/internal-check.h:libs/gst/check/libcheck/check.h.in" ;; + "libs/gst/controller/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/controller/Makefile" ;; + "libs/gst/helpers/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/helpers/Makefile" ;; + "libs/gst/net/Makefile") CONFIG_FILES="$CONFIG_FILES libs/gst/net/Makefile" ;; + "plugins/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/Makefile" ;; + "plugins/elements/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/elements/Makefile" ;; + "plugins/tracers/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/tracers/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "tests/benchmarks/Makefile") CONFIG_FILES="$CONFIG_FILES tests/benchmarks/Makefile" ;; + "tests/check/Makefile") CONFIG_FILES="$CONFIG_FILES tests/check/Makefile" ;; + "tests/misc/Makefile") CONFIG_FILES="$CONFIG_FILES tests/misc/Makefile" ;; + "tests/examples/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/Makefile" ;; + "tests/examples/adapter/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/adapter/Makefile" ;; + "tests/examples/controller/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/controller/Makefile" ;; + "tests/examples/stepping/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/stepping/Makefile" ;; + "tests/examples/helloworld/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/helloworld/Makefile" ;; + "tests/examples/memory/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/memory/Makefile" ;; + "tests/examples/netclock/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/netclock/Makefile" ;; + "tests/examples/ptp/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/ptp/Makefile" ;; + "tests/examples/streamiddemux/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/streamiddemux/Makefile" ;; + "tests/examples/streams/Makefile") CONFIG_FILES="$CONFIG_FILES tests/examples/streams/Makefile" ;; + "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; + "common/Makefile") CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; + "common/m4/Makefile") CONFIG_FILES="$CONFIG_FILES common/m4/Makefile" ;; + "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; + "docs/gst/Makefile") CONFIG_FILES="$CONFIG_FILES docs/gst/Makefile" ;; + "docs/gst/gstreamer.types") CONFIG_FILES="$CONFIG_FILES docs/gst/gstreamer.types" ;; + "docs/libs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/libs/Makefile" ;; + "docs/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES docs/plugins/Makefile" ;; + "docs/version.entities") CONFIG_FILES="$CONFIG_FILES docs/version.entities" ;; + "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; + "pkgconfig/Makefile") CONFIG_FILES="$CONFIG_FILES pkgconfig/Makefile" ;; + "stamp.h") CONFIG_FILES="$CONFIG_FILES stamp.h" ;; + "pkgconfig/gstreamer.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer.pc" ;; + "pkgconfig/gstreamer-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-uninstalled.pc" ;; + "pkgconfig/gstreamer-base.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-base.pc" ;; + "pkgconfig/gstreamer-base-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-base-uninstalled.pc" ;; + "pkgconfig/gstreamer-check.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-check.pc" ;; + "pkgconfig/gstreamer-check-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-check-uninstalled.pc" ;; + "pkgconfig/gstreamer-controller.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-controller.pc" ;; + "pkgconfig/gstreamer-controller-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-controller-uninstalled.pc" ;; + "pkgconfig/gstreamer-net.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-net.pc" ;; + "pkgconfig/gstreamer-net-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gstreamer-net-uninstalled.pc" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + "po-directories":C) + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; 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 + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done ;; + "$ac_stdint_h":C) +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_stdint_h : $_ac_stdint_h" >&5 +$as_echo "$as_me: creating $ac_stdint_h : $_ac_stdint_h" >&6;} +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) */ + + +#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 + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_stdint_h is unchanged" >&5 +$as_echo "$as_me: $ac_stdint_h is unchanged" >&6;} + else + ac_dir=`$as_dirname -- "$ac_stdint_h" || +$as_expr X"$ac_stdint_h" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_stdint_h" : 'X\(//\)[^/]' \| \ + X"$ac_stdint_h" : 'X\(//\)$' \| \ + X"$ac_stdint_h" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_stdint_h" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + rm -f $ac_stdint_h + mv $ac_stdint $ac_stdint_h + fi + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +if test "x${GST_DISABLE_GST_DEBUG}" = "xno"; then enable_gst_debug="yes"; fi +if test "x${GST_DISABLE_GST_TRACER_HOOKS}" = "xno"; then enable_gst_tracer_hooks="yes"; fi +if test "x${GST_DISABLE_PARSE}" = "xno"; then enable_parse="yes"; fi +if test "x${GST_DISABLE_OPTION_PARSING}" = "xno"; then enable_option_parsing="yes"; fi +if test "x${GST_DISABLE_PLUGIN}" = "xno"; then enable_plugin="yes"; fi +if test "x${GST_DISABLE_REGISTRY}" = "xno"; then enable_registry="yes"; fi + +echo " + +Configuration + Version : ${VERSION} + Source code location : ${srcdir} + Prefix : ${prefix} + Compiler : ${CC} + Package name : ${GST_PACKAGE_NAME} + Package origin : ${GST_PACKAGE_ORIGIN} + + API Documentation : ${enable_gtk_doc} + + Debug logging : ${enable_gst_debug} + Tracing subsystem hooks : ${enable_gst_tracer_hooks} + Command-line parser : ${enable_parse} + Option parsing in gst_init : ${enable_option_parsing} + Plugin registry : ${enable_registry} + Plugin support : ${enable_plugin} + Static plugins : ${enable_static_plugins} + Unit testing support : ${BUILD_CHECK} + PTP clock support : ${HAVE_PTP} + libunwind support : ${HAVE_UNWIND} + libdw support : ${HAVE_DW} + + Debug : ${USE_DEBUG} + Profiling : ${USE_PROFILING} + + Building benchmarks : ${BUILD_BENCHMARKS} + Building examples : ${BUILD_EXAMPLES} + Building test apps : ${BUILD_TESTS} + Building tests that fail : ${BUILD_FAILING_TESTS} + Building tools : ${BUILD_TOOLS} +" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..25a0924 --- /dev/null +++ b/configure.ac @@ -0,0 +1,1170 @@ +AC_PREREQ([2.69]) + +dnl initialize autoconf +dnl when going to/from release please set the nano (fourth number) right ! +dnl releases only do Wall, git and prerelease does Werror too +dnl +AC_INIT([GStreamer],[1.14.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer],[gstreamer]) +AG_GST_INIT + +dnl initialize automake (we require GNU make) +AM_INIT_AUTOMAKE([-Wno-portability 1.14 no-dist-gzip dist-xz tar-ustar subdir-objects]) + +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/gst.c]) + +dnl define the output header for config +AC_CONFIG_HEADERS([config.h]) + +dnl AM_MAINTAINER_MODE only provides the option to configure to enable it +AM_MAINTAINER_MODE([enable]) + +dnl sets host_* variables +AC_CANONICAL_HOST + +dnl use pretty build output by default +AM_SILENT_RULES([yes]) + +dnl GStreamer versioning, this is mostly informational +GST_VERSION_MAJOR=$PACKAGE_VERSION_MAJOR +GST_VERSION_MINOR=$PACKAGE_VERSION_MINOR +GST_VERSION_MICRO=$PACKAGE_VERSION_MICRO +GST_VERSION_NANO=$PACKAGE_VERSION_NANO +AC_SUBST(GST_VERSION_MAJOR) +AC_SUBST(GST_VERSION_MINOR) +AC_SUBST(GST_VERSION_MICRO) +AC_SUBST(GST_VERSION_NANO) + +dnl our libraries and install dirs use GST_API_VERSION in the filename +dnl to allow side-by-side installation of different API versions +GST_API_VERSION=1.0 +AC_SUBST(GST_API_VERSION) +AC_DEFINE_UNQUOTED(GST_API_VERSION, "$GST_API_VERSION", + [GStreamer API Version]) + +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 +dnl Keep CURRENT as MINOR * 100 + MICRO +dnl Ex : 1.0.0 => 0 +dnl 1.0.3 => 3 +dnl 1.1.0 => 100 +dnl 1.2.5 => 205 +dnl 1.10.9 (who knows) => 1009 +dnl +dnl sets GST_LT_LDFLAGS +AS_LIBTOOL(GST, 1401, 0, 1401) + +dnl *** autotools stuff **** + +dnl allow for different autotools +AS_AUTOTOOLS_ALTERNATE + +dnl Add parameters for aclocal (keep in sync with Makefile.am) +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.17]) +AM_GNU_GETTEXT([external]) +AG_GST_GETTEXT([gstreamer-$GST_API_VERSION]) + +dnl *** check for arguments to configure *** + +AG_GST_ARG_DISABLE_FATAL_WARNINGS +AG_GST_ARG_ENABLE_EXTRA_CHECKS + +dnl subsystems - can influence other decisions so needs to be high up +dnl we need to AM_CONDITIONAL them here for automake 1.6.x compatibility +AG_GST_CHECK_SUBSYSTEM_DISABLE(GST_DEBUG,[debugging subsystem]) +AM_CONDITIONAL(GST_DISABLE_GST_DEBUG, test "x$GST_DISABLE_GST_DEBUG" = "xyes") +AG_GST_CHECK_SUBSYSTEM_DISABLE(GST_TRACER_HOOKS,[tracing subsystem hooks]) +AM_CONDITIONAL(GST_DISABLE_GST_TRACER_HOOKS, test "x$GST_DISABLE_GST_TRACER_HOOKS" = "xyes") +if test "x$GST_DISABLE_GST_TRACER_HOOKS" = xyes; then + AC_DEFINE(GST_DISABLE_GST_TRACER_HOOKS, 1, + [Define if tracing subsystem hooks is disabled]) +fi +AG_GST_CHECK_SUBSYSTEM_DISABLE(PARSE,[command-line parser]) +AM_CONDITIONAL(GST_DISABLE_PARSE, test "x$GST_DISABLE_PARSE" = "xyes") +if test "x$GST_DISABLE_PARSE" = xyes; then + AC_DEFINE(GST_DISABLE_PARSE, 1, + [Define if pipeline parsing code is disabled]) +fi +AG_GST_CHECK_SUBSYSTEM_DISABLE(OPTION_PARSING,[option parsing when gst_init]) +AM_CONDITIONAL(GST_DISABLE_OPTION_PARSING, test "x$GST_DISABLE_OPTION_PARSING" = "xyes") +if test "x$GST_DISABLE_OPTION_PARSING" = xyes; then + AC_DEFINE(GST_DISABLE_OPTION_PARSING, 1, + [Define if option parsing is disabled]) +fi +AG_GST_CHECK_SUBSYSTEM_DISABLE(REGISTRY,[plugin registry]) +AM_CONDITIONAL(GST_DISABLE_REGISTRY, test "x$GST_DISABLE_REGISTRY" = "xyes") +dnl define a substitution to use in docs/gst/gstreamer.types +if test "x$GST_DISABLE_REGISTRY" = "xyes" +then + GST_REGISTRY_DOC_TYPES="%" +else + GST_REGISTRY_DOC_TYPES= +fi +AC_SUBST(GST_REGISTRY_DOC_TYPES) +AG_GST_CHECK_SUBSYSTEM_DISABLE(PLUGIN,[plugin]) +AM_CONDITIONAL(GST_DISABLE_PLUGIN, test "x$GST_DISABLE_PLUGIN" = "xyes") + +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 + +AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO], + ["${srcdir}/gstreamer.doap"], + [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO]) + +# We only use this when building with MSVC, which is only done with the +# alternate Meson build system files +GSTCONFIG_BUILT_WITH_MSVC=0 +AC_SUBST(GSTCONFIG_BUILT_WITH_MSVC) + +dnl check for bash completion +AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) + +if test "x$with_bash_completion_dir" = "xyes" +then + extra_args= + + if test "x$prefix" != "xNONE" + then + extra_args="--define-variable=prefix=\"$prefix\"" + fi + + PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [ + BASH_COMPLETION_DIR="`eval pkg-config $extra_args --variable=completionsdir bash-completion`" + BASH_HELPERS_DIR="`eval pkg-config $extra_args --variable=helpersdir bash-completion`" + ], + [ + BASH_COMPLETION_DIR="$datadir/bash-completion/completions" + BASH_HELPERS_DIR="$datadir/bash-completion/helpers" + ]) +else + BASH_COMPLETION_DIR="$with_bash_completion_dir/completions" + BASH_HELPERS_DIR="$with_bash_completion_dir/helpers" +fi + +AC_SUBST([BASH_COMPLETION_DIR]) +AC_SUBST([BASH_HELPERS_DIR]) +AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) + +dnl If only building static libraries, define GST_STATIC_COMPILATION. This is +dnl needed only on Windows, but it doesn't hurt to have it everywhere. +if test x$enable_static = xyes -a x$enable_shared = xno; then + GST_OBJ_STATIC_CFLAGS="-DGST_STATIC_COMPILATION" +fi + +dnl building of tests +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--disable-tests],[disable building test apps]), + [ + case "${enableval}" in + yes) BUILD_TESTS=yes ;; + no) BUILD_TESTS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;; + esac + ], +[BUILD_TESTS=yes]) dnl Default value +AM_CONDITIONAL(BUILD_TESTS, test "x$BUILD_TESTS" = "xyes") + +dnl tests known to fail +AC_ARG_ENABLE(failing-tests, + AS_HELP_STRING([--disable-failing-tests],[disable building tests known to fail]), + [ + case "${enableval}" in + yes) BUILD_FAILING_TESTS=yes ;; + no) BUILD_FAILING_TESTS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-failing-tests) ;; + esac + ], + [BUILD_FAILING_TESTS=no]) dnl Default value +AM_CONDITIONAL(BUILD_FAILING_TESTS, test "x$BUILD_FAILING_TESTS" = "xyes") +if test x$BUILD_FAILING_TESTS = xyes; then + AC_MSG_WARN([building tests known to fail, use --disable-failing-tests to disable]) +else + AC_MSG_WARN([Sissy ! By asking to not build the tests known to fail, you hereby waive your right to customer support. If you do not agree with this EULA, please press Ctrl-C before the next line is printed. By allowing the next line to be printed, you expressly acknowledge your acceptance of this EULA.]) +fi + +dnl building of benchmarks +AC_ARG_ENABLE(benchmarks, + AS_HELP_STRING([--disable-benchmarks],[disable building benchmarks apps]), + [ + case "${enableval}" in + yes) BUILD_BENCHMARKS=yes ;; + no) BUILD_BENCHMARKS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-benchmarks) ;; + esac + ], +[BUILD_BENCHMARKS=yes]) dnl Default value +AM_CONDITIONAL(BUILD_BENCHMARKS, test "x$BUILD_BENCHMARKS" = "xyes") + +dnl building of tools +AC_ARG_ENABLE(tools, + AS_HELP_STRING([--disable-tools],[disable building tools]), + [ + case "${enableval}" in + yes) BUILD_TOOLS=yes ;; + no) BUILD_TOOLS=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-tools) ;; + esac + ], +[BUILD_TOOLS=yes]) dnl Default value +AM_CONDITIONAL(BUILD_TOOLS, test "x$BUILD_TOOLS" = "xyes") + +dnl poison destroyed objects +AC_ARG_ENABLE(poisoning, + AS_HELP_STRING([--enable-poisoning],[enable poisoning of deallocated objects]), + [ + case "${enableval}" in + yes) USE_POISONING=yes ;; + no) USE_POISONING=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-poisoning) ;; + esac + ], + [USE_POISONING=no]) dnl Default value +if test "x$USE_POISONING" = xyes; then + AC_DEFINE(USE_POISONING, 1, + [Define if we should poison deallocated memory]) +fi + +dnl PTP support parts +AC_MSG_CHECKING([whether PTP support can be enabled]) +case "$host_os" in + *android*) + dnl Can't run on Android because of permissions + HAVE_PTP=no + ;; + mingw*|pw32*|cygwin*) + dnl Not ported to Windows yet + HAVE_PTP=no + ;; + darwin*) + dnl Can't run on iOS because of permissions + AC_CHECK_HEADER(MobileCoreServices/MobileCoreServices.h, HAVE_PTP="no", HAVE_PTP="yes", [-]) + ;; + linux*|darwin*|solaris*|netbsd*|freebsd*|openbsd*|kfreebsd*|dragonfly*|gnu*) + HAVE_PTP=yes + ;; + *) + HAVE_PTP=no + ;; +esac +AC_MSG_RESULT([$HAVE_PTP]) + +dnl user/group to change to in gst-ptp-helper +AC_ARG_WITH([ptp-helper-setuid-user], + AS_HELP_STRING([--with-ptp-helper-setuid-user],[User to switch to when installing gst-ptp-helper setuid root]), + [ + if test "x$withval" != "x" + then + AC_DEFINE_UNQUOTED(HAVE_PTP_HELPER_SETUID_USER, "$withval", [PTP helper setuid user]) + fi + ], [] +) + +dnl group/group to change to in gst-ptp-helper +AC_ARG_WITH([ptp-helper-setuid-group], + AS_HELP_STRING([--with-ptp-helper-setuid-group],[Group to switch to when installing gst-ptp-helper setuid root]), + [ + if test "x$withval" != "x" + then + AC_DEFINE_UNQUOTED(HAVE_PTP_HELPER_SETUID_GROUP, "$withval", [PTP helper setuid group]) + fi + ], [] +) + +AC_ARG_WITH( + ptp-helper-permissions, + AC_HELP_STRING( + [--with-ptp-helper-permissions], + [how to gain PTP permissions (none, setuid-root, capabilities, auto)]), + [], + [with_ptp_helper_permissions=auto]) + +gst_ptp_have_cap=no +AG_GST_CHECK_LIBHEADER(CAP, cap, + cap_init, , + sys/capability.h, + CAP_LIBS="-lcap" + AC_SUBST(CAP_LIBS) + gst_ptp_have_cap=yes) + +AC_PATH_PROG([SETCAP], [setcap], [no], [$PATH:/usr/bin:/bin:/usr/sbin:/sbin]) + +if test "x$HAVE_PTP" = "xyes"; then +AC_DEFINE(HAVE_PTP, 1, [PTP support available]) + +AC_MSG_CHECKING([for SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[ + #include + #include + ]], + [[ + struct ifreq ifr; + struct ifconf ifc; + ioctl(0, SIOCGIFCONF, &ifc); + ioctl(0, SIOCGIFFLAGS, &ifr); + ioctl(0, SIOCGIFHWADDR, &ifr); + int dummy = ifr.ifr_hwaddr.sa_data[0]; + ]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR, 1, [SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR is available]) + ], [ + AC_MSG_RESULT(no) +]) + +AC_MSG_CHECKING([for getifaddrs() and AF_LINK]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[ + #include + #include + #include + ]], + [[ + struct ifaddrs *ifaddr; + getifaddrs(&ifaddr); + int dummy = (ifaddr->ifa_flags & IFF_LOOPBACK) && ifaddr->ifa_addr->sa_family != AF_LINK; + ]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GETIFADDRS_AF_LINK, 1, [getifaddrs() and AF_LINK is available]) + ], [ + AC_MSG_RESULT(no) + ]) + +AC_MSG_CHECKING([how to install gst-ptp-helper]) +if test "x$with_ptp_helper_permissions" = "xauto"; then + if test "x$gst_ptp_have_cap" = "xyes" -a "x$SETCAP" != "xno"; then + with_ptp_helper_permissions="capabilities" + else + with_ptp_helper_permissions="setuid-root" + fi +fi +AC_MSG_RESULT([$with_ptp_helper_permissions]) + +case "$with_ptp_helper_permissions" in + none) + ;; + setuid-root) + AC_DEFINE(HAVE_PTP_HELPER_SETUID, 1, + [Use setuid-root for permissions in PTP helper]) + ;; + capabilities) + AC_DEFINE(HAVE_PTP_HELPER_CAPABILITIES, 1, + [Use capabilities for permissions in PTP helper]) + ;; + *) + AC_MSG_ERROR(Invalid parameter [$with_ptp_helper_permissions]) + ;; +esac + +fi + +AM_CONDITIONAL(HAVE_PTP, test "x$HAVE_PTP" = "xyes") +AM_CONDITIONAL(HAVE_PTP_HELPER_SETUID, test "x$with_ptp_helper_permissions" = "xsetuid-root") +AM_CONDITIONAL(HAVE_PTP_HELPER_CAPABILITIES, test "x$with_ptp_helper_permissions" = "xcapabilities") + +dnl *** checks for platform *** + +dnl * hardware/architecture * + +dnl common/m4/gst-arch.m4 +dnl check CPU type +AG_GST_ARCH + +dnl check for platform specific settings +AG_GST_PLATFORM + +dnl * software * + +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 find an assembler +AM_PROG_AS + +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_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 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") + +dnl Perl is used in building documentation and in the version checks +AC_PATH_PROG(PERL_PATH, perl, no) +if test x$PERL_PATH = xno; then + AC_MSG_ERROR(Could not find perl) +fi + +dnl we require flex and bison for building the parser +if test "x$GST_DISABLE_PARSE" != xyes; then + AG_GST_BISON_CHECK + AG_GST_FLEX_CHECK +fi + +AC_PATH_PROG(VALGRIND_PATH, valgrind, no) +AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno") + +dnl check for gobject-introspection +GOBJECT_INTROSPECTION_CHECK([1.31.1]) + +dnl check for documentation tools +GTK_DOC_CHECK([1.12]) +AG_GST_PLUGIN_DOCS([1.12]) + +dnl *** checks for libraries *** + +dnl check for libm, for sin() +LT_LIB_M +AC_SUBST(LIBM) + +dnl *** checks for header files *** + +dnl check if we have ANSI C header files +AC_HEADER_STDC + +dnl Check for ucontext.h +AC_CHECK_HEADERS([ucontext.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl Check for sys/socket.h +AC_CHECK_HEADERS([sys/socket.h], [HAVE_SYS_SOCKET_H=yes], [HAVE_SYS_SOCKET_H=no], [AC_INCLUDES_DEFAULT]) +AM_CONDITIONAL(HAVE_SYS_SOCKET_H, test "x$HAVE_SYS_SOCKET_H" = "xyes") + +dnl check for sys/times.h for tests/examples/adapter/ +AC_CHECK_HEADERS([sys/times.h], [HAVE_SYS_TIMES_H=yes], [HAVE_SYS_TIME_H=no], [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([unistd.h], [HAVE_UNISTD_H=yes], [HAVE_UNISTD_H=no], [AC_INCLUDES_DEFAULT]) +AM_CONDITIONAL(HAVE_SYS_TIMES_H_AND_UNISTD_H, test "x$HAVE_SYS_TIMES_H" = "xyes" -a "x$HAVE_UNISTD_H" = "xyes") + +dnl Check for process.h for getpid() on win32 +AC_CHECK_HEADERS([process.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl Check for sys/utsname.h for uname +AC_CHECK_HEADERS([sys/utsname.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl Check for stdio_ext.f for __fbufsize +AC_CHECK_HEADERS([stdio_ext.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl check for pthreads +dnl without arguments AX_PTHREAD() will do AC_DEFINE(HAVE_PTHREAD) +dnl which later checks use in their test code +AX_PTHREAD() +AM_CONDITIONAL(HAVE_PTHREAD, test "x$ax_pthread_ok" = "xyes") + +dnl check for sys/prctl for setting thread name on Linux +AC_CHECK_HEADERS([sys/prctl.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl check for pthread_setname_np(const char*) +dnl which is present on OS X 10.6, iOS 3.2 and above +AC_MSG_CHECKING(for pthread_setname_np(const char*)) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [pthread_setname_np("example")])], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID,1, + [Have function pthread_setname_np(const char*)])], + [AC_MSG_RESULT(no)]) + +dnl check for sys/uio.h for writev() +AC_CHECK_HEADERS([sys/uio.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl Check for valgrind.h +dnl separate from HAVE_VALGRIND because you can have the program, but not +dnl the dev package +AC_CHECK_HEADERS([valgrind/valgrind.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl used in gst/gstpoll.c +AC_CHECK_HEADERS([winsock2.h], [HAVE_WINSOCK2_H=yes], [HAVE_WINSOCK2_H=no], [AC_INCLUDES_DEFAULT]) +AM_CONDITIONAL(HAVE_WINSOCK2_H, test "x$HAVE_WINSOCK2_H" = "xyes") +if test "x$HAVE_WINSOCK2_H" = "xyes"; then + WIN32_LIBS="-lws2_32" + AC_SUBST(WIN32_LIBS) +fi + +dnl check for GMP/GSL, used by the gst_util_uint64_scale unit test only +if test "x$BUILD_TESTS" = "xyes"; then + AG_GST_CHECK_LIBHEADER(GMP, gmp, + __gmpz_init_set_d, , + gmp.h, + GMP_LIBS="-lgmp" + AC_SUBST(GMP_LIBS) + AC_DEFINE(HAVE_GMP, [1],[Have GMP library])) + AG_GST_CHECK_LIBHEADER(GSL, gsl, + gsl_rng_uniform_int, -lgslcblas, + gsl/gsl_rng.h, + GSL_LIBS="-lgsl -lgslcblas" + AC_SUBST(GSL_LIBS) + AC_DEFINE(HAVE_GSL, [1],[Have GSL library])) +fi + +dnl *** checks for types/defines *** + +dnl *** checks for structures *** + +dnl *** checks for compiler characteristics *** + +dnl check if the compiler supports __uint128_t (gcc) +dnl Actually check for 128-bit division, since that's what we use +dnl uint128_t for. +AC_CACHE_CHECK(for __uint128_t, gst_cv_uint128_t, + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ ]], [[ + static __uint128_t v1 = 100; + static __uint128_t v2 = 10; + static __uint128_t u; + u = v1 / v2; + ]])],[ + gst_cv_uint128_t=yes + ],[ + gst_cv_uint128_t=no + ]) +) +if test x$gst_cv_uint128_t = xyes; then + AC_DEFINE(HAVE_UINT128_T, 1, [Have __uint128_t type]) +fi + +dnl *** checking for tm_gmtoff *** +AC_MSG_CHECKING([for tm_gmtoff]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + int main(void) { + struct tm t; + t.tm_gmtoff = 0; + exit(0); + }]])], + [have_tm_gmtoff=yes + AC_DEFINE(HAVE_TM_GMTOFF,1,[Have tm_gmtoff field in struct tm])], + [have_tm_gmtoff=no], + [have_tm_gmtoff="no (cross compiling)"]) +AC_MSG_RESULT($have_tm_gmtoff) + + +dnl *** checks for library functions *** + +AC_CHECK_FUNCS([strcasestr]) + +AC_CHECK_FUNCS([gmtime_r]) +AC_CHECK_FUNCS([localtime_r]) +AC_CHECK_FUNCS([sigaction]) +AC_CHECK_FUNCS([getrusage]) +AM_CONDITIONAL(HAVE_GETRUSAGE, test "x$ac_cv_func_getrusage" = "xyes") +AC_CHECK_HEADERS([sys/resource.h]) + +dnl check for fseeko() +AC_FUNC_FSEEKO +dnl check for ftello() +AC_CHECK_FUNCS([ftello]) + +AC_CHECK_FUNCS([fgetpos]) +AC_CHECK_FUNCS([fsetpos]) + +dnl check for poll(), ppoll() and pselect() +AC_CHECK_HEADERS([sys/poll.h], [], [], [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([poll.h], [], [], [AC_INCLUDES_DEFAULT]) +AC_CHECK_FUNCS([poll]) +AC_CHECK_FUNCS([ppoll]) +AC_CHECK_FUNCS([pselect]) + +dnl check for socketpair() +AC_CHECK_FUNC(socketpair, [], [ + AC_CHECK_LIB(socket, socketpair, [ + SOCKET_LIBS="-lsocket" + AC_SUBST(SOCKET_LIBS) + ]) +]) + +dnl **************************************** +dnl *** GLib POLL* compatibility defines *** +dnl **************************************** + +AC_MSG_CHECKING([for broken poll]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + #include + #ifdef HAVE_SYS_POLL_H + #include + #endif + #ifdef HAVE_POLL_H + #include + #endif + int main(void) { + struct pollfd fds[1]; + int fd; + fd = open("/dev/null", 1); + fds[0].fd = fd; + fds[0].events = POLLIN; + fds[0].revents = 0; + if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) { + exit(1); /* Does not work for devices -- fail */ + } + exit(0); + }]])], + [broken_poll=no], + [broken_poll=yes + AC_DEFINE(BROKEN_POLL,1,[poll doesn't work on devices])], + [broken_poll="no (cross compiling)"]) +AC_MSG_RESULT($broken_poll) + +dnl check for getpagesize() +AC_CHECK_FUNCS([getpagesize]) + +dnl Check for POSIX timers +CLOCK_GETTIME_FOUND="no" +AC_CHECK_FUNC(clock_gettime, [CLOCK_GETTIME_FOUND="yes"], [ + AC_CHECK_LIB(rt, clock_gettime, [ + CLOCK_GETTIME_FOUND="yes" + LIBS="$LIBS -lrt" + ], [ + AC_CHECK_LIB(pthread, clock_gettime, [ + CLOCK_GETTIME_FOUND="yes" + LIBS="$LIBS -lpthread" + ]) + ]) +]) + +# With XCode 8, clock_gettime will be incorrectly detected as being available +# regardless of what version of OS X you target because the symbol is available +# in the .tbd file as a weak symbol. +# See: https://bugzilla.gnome.org/show_bug.cgi?id=772451 +# +# We cannot simply do AC_CHECK_FUNCS with -Wl,-no_weak_imports because the +# autoconf check does its own prototype declaration that doesn't trigger that +# compiler flag. +# +# It's only starting from macOS 10.12 and iOS 10.0 that clock_gettime is +# actually available, so we can unconditionally disable it for older versions. +case "$host_os" in + darwin*) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#if defined(TARGET_OS_MAC) +# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 +# error "Not compiling for OS X 10.12 or later" +# endif +#else +# if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 +# error "Not compiling for iOS 10.0 or later" +# endif +#endif + ]])], [], [ + if test "$CLOCK_GETTIME_FOUND" = "yes"; then + AC_MSG_NOTICE([Disabling incorrectly detected clock_gettime on OS X]) + fi + CLOCK_GETTIME_FOUND="no" + ]) + ;; +esac + +if test "$CLOCK_GETTIME_FOUND" = "yes"; then + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Have clock_gettime]) +fi + +AC_CACHE_CHECK(for posix timers, gst_cv_posix_timers, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_UNISTD_H +#include +#endif + ]], [[ +#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 || !defined(CLOCK_REALTIME) +#error Either _POSIX_TIMERS or CLOCK_REALTIME not defined +#endif + ]])],[ + gst_cv_posix_timers=yes + ],[ + gst_cv_posix_timers=no + ]) +) + +if test "$gst_cv_posix_timers" = "yes"; then + AC_DEFINE(HAVE_POSIX_TIMERS,1,[Have posix timers]) + GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 1" +else + GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 0" +fi +AC_SUBST(GST_HAVE_POSIX_TIMERS_DEFINE) +AM_CONDITIONAL(GST_HAVE_POSIX_TIMERS, test "$gst_cv_posix_timers" = "yes") + +AC_CACHE_CHECK(for monotonic clock, gst_cv_monotonic_clock, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_UNISTD_H +#include +#endif + ]], [[ +#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 || !defined(CLOCK_MONOTONIC) +#error Either _POSIX_MONOTONIC_CLOCK or CLOCK_MONOTONIC not defined +#endif + ]])],[ + gst_cv_monotonic_clock=yes + ],[ + gst_cv_monotonic_clock=no + ]) +) + +if test "$gst_cv_monotonic_clock" = "yes"; then + AC_DEFINE(HAVE_MONOTONIC_CLOCK,1,[Have a monotonic clock]) + GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 1" +else + GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 0" +fi +AC_SUBST(GST_HAVE_MONOTONIC_CLOCK_DEFINE) +AM_CONDITIONAL(GST_HAVE_MONOTONIC_CLOCK, test "$gst_cv_monotonic_clock" = "yes") + +dnl Check for a way to display the function name in debug output +AG_GST_CHECK_FUNCTION + +dnl test if we have dladdr(); we use it for debugging; see gst/gstinfo.c +save_cflags="$CFLAGS" +CFLAGS="$CFLAGS -D_GNU_SOURCE" +AC_CHECK_LIB(dl, dladdr, + AC_DEFINE(HAVE_DLADDR, 1, [Defined if we have dladdr ()]) + LIBS="$LIBS -ldl") +CFLAGS="$save_cflags" + +dnl Check printf stuff +if test "x${GST_DISABLE_GST_DEBUG}" != "xyes"; then + AC_TYPE_LONG_LONG_INT + AC_TYPE_UNSIGNED_LONG_LONG_INT + + if test x$ac_cv_type_long_long_int$ac_cv_type_unsigned_long_long_int = xyesyes; then + AC_DEFINE([HAVE_LONG_LONG], [1], [Define to 1 if the system has the type long long]) + fi + + dnl /usr/share/aclocal/inttypes_h.m4 - ships with gettext apparently + gl_AC_HEADER_INTTYPES_H + + dnl /usr/share/aclocal/stdint_h.m4 - ships with gettext apparently + gl_AC_HEADER_STDINT_H + + AC_CHECK_TYPES(ptrdiff_t) + + AC_TYPE_INTMAX_T + AC_TYPE_SIZE_T +fi + +dnl *** checks for dependency libraries *** + +dnl GLib +GLIB_REQ=2.40.0 +AG_GST_GLIB_CHECK([$GLIB_REQ]) + +dnl Check for documentation xrefs +GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" +AC_SUBST(GLIB_PREFIX) + +dnl GTK is optional and only used in examples +HAVE_GTK=no +GTK_REQ=3.10 +if test "x$BUILD_EXAMPLES" = "xyes"; then + PKG_CHECK_MODULES(GTK, gtk+-3.0 >= $GTK_REQ, HAVE_GTK=yes, HAVE_GTK=no) + AC_SUBST(GTK_LIBS) + AC_SUBST(GTK_CFLAGS) +fi +AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes") + +dnl libunwind is optionally used by the leaks tracer +AC_ARG_WITH([unwind],[AS_HELP_STRING([--with-unwind=yes|no|auto],[use libunwind])], + [], [with_unwind=auto]) +if [ test "x${with_unwind}" != "xno" ]; then + PKG_CHECK_MODULES(UNWIND, [libunwind], + [ + HAVE_UNWIND=yes + AC_DEFINE(HAVE_UNWIND, 1, [libunwind available]) + UNWIND_REQUIRE=libunwind + AC_SUBST(UNWIND_REQUIRE) + ], + [ + HAVE_UNWIND=no + if [ test "x${with_unwind}" = "xyes" ]; then + AC_MSG_ERROR([could not find libunwind]) + fi + ]) +else + HAVE_UNWIND=no +fi + +dnl libdw is optionally used to add source lines and numbers to backtraces +AC_ARG_WITH([dw],[AS_HELP_STRING([--with-dw=yes|no|auto],[use libdw])], + [], [with_dw=auto]) +if [ test "x${with_dw}" != "xno" ]; then + PKG_CHECK_MODULES(DW, [libdw], + [ + HAVE_DW=yes + AC_DEFINE(HAVE_DW, 1, [libdw available]) + DW_REQUIRE=libdw + AC_SUBST(DW_REQUIRE) + ], + [ + HAVE_DW=no + if [ test "x${with_dw}" = "xyes" ]; then + AC_MSG_ERROR([could not find libdw]) + fi + ]) +else + HAVE_DW=no +fi + +dnl Check for backtrace() from libc +AC_CHECK_FUNC(backtrace, [ + AC_CHECK_HEADERS([execinfo.h], [ + AC_DEFINE(HAVE_BACKTRACE,1,[Have backtrace]) + ], [], []) +]) + +dnl building of unit test libraries +AC_ARG_ENABLE(check, + AS_HELP_STRING([--disable-check],[disable building unit test libraries]), + [ + case "${enableval}" in + yes) BUILD_CHECK=yes ;; + no) BUILD_CHECK=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-check) ;; + esac + ], [ + dnl Default value + case $host_os in + mingw* | msvc* | mks*) BUILD_CHECK=no ;; + *) BUILD_CHECK=yes ;; + esac +]) +dnl bit of a misnomer, but keep the conditional named like this so we don't +dnl have to change too much elsewhere +AM_CONDITIONAL(HAVE_CHECK, test "x$BUILD_CHECK" = "xyes") + +dnl configure the desired memory alignment +AC_ARG_WITH([memory-alignment], + AS_HELP_STRING([--with-memory-alignment],[8,N,malloc,pagesize (default is 32)]), + [ + if test "x$withval" = "xyes" + then + AC_DEFINE(MEMORY_ALIGNMENT, 32, [Memory alignment to use]) + else + case "${withval}" in + malloc) AC_DEFINE(MEMORY_ALIGNMENT_MALLOC, 1, [Memory alignment by malloc default]) ;; + pagesize) AC_DEFINE(MEMORY_ALIGNMENT_PAGESIZE, 1, [Memory alignment by pagesize]) ;; + *) AC_DEFINE_UNQUOTED(MEMORY_ALIGNMENT, ${withval}, [Memory alignment to use]) ;; + esac + fi + ], [ + AC_DEFINE(MEMORY_ALIGNMENT_MALLOC, 1, [Memory alignment by malloc default]) + ] +) + +dnl Check for -Bsymbolic-functions linker flag used to avoid +dnl intra-library PLT jumps, if available. +AC_ARG_ENABLE(Bsymbolic, + [AS_HELP_STRING([--disable-Bsymbolic],[avoid linking with -Bsymbolic])],, + [SAVED_LDFLAGS="${LDFLAGS}" SAVED_LIBS="${LIBS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + LIBS= + AC_TRY_LINK([], [return 0], + AC_MSG_RESULT(yes) + enable_Bsymbolic=yes, + AC_MSG_RESULT(no) + enable_Bsymbolic=no) + LDFLAGS="${SAVED_LDFLAGS}" LIBS="${SAVED_LIBS}"]) + + +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 define LIBDIR, GST_DATADIR so we can inform people where we live +AS_AC_EXPAND(LIBDIR, $libdir) +AC_DEFINE_UNQUOTED(LIBDIR, "$LIBDIR", [library dir]) +AS_AC_EXPAND(DATADIR, $datadir) +AC_DEFINE_UNQUOTED(GST_DATADIR, "$DATADIR", [data dir]) + +dnl set location of plugin directory +AG_GST_SET_PLUGINDIR + +dnl make sure it doesn't complain about unused variables if debugging is disabled +NO_WARNINGS="" +if test "x${GST_DISABLE_GST_DEBUG}" = "xyes"; then + NO_WARNINGS="-Wno-unused" +fi + +dnl define an ERROR_CFLAGS Makefile variable +AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return -Wno-multichar -Wnested-externs $NO_WARNINGS]) + +dnl special warning flags for gst/printf +AS_COMPILER_FLAG([-Wno-format-nonliteral], [PRINTF_CFLAGS="-Wno-format-nonliteral"]) +AC_SUBST(PRINTF_CFLAGS) + +dnl disable strict aliasing +AS_COMPILER_FLAG([-fno-strict-aliasing], [EXTRA_CFLAGS="-fno-strict-aliasing"]) +AC_SUBST(EXTRA_CFLAGS) + +dnl define correct level for debugging messages +AG_GST_SET_LEVEL_DEFAULT($GST_GIT) + +dnl *** finalize CFLAGS, LDFLAGS, LIBS + +dnl Overview: +dnl GST_OPTION_CFLAGS: common cflags for profiling, debugging, errors, ... +dnl GST_ALL_*: vars shared by all built objects +dnl GST_LIB_LDFLAGS: additional linker flags for all libaries +dnl GST_OBJ_*: additional vars to link to the core library +dnl include GST_ALL_* +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) + +# GST_DISABLE_DEPRECATED: hide the visibility of deprecated +# functionality from the API that gstreamer uses +# GST_REMOVE_DEPRECATED: don't compile deprecated functionality (breaks ABI) +if test "x$PACKAGE_VERSION_NANO" = "x1"; then + dnl Define _only_ when compiling from git (not for pre-releases or releases) + DEPRECATED_CFLAGS="-DGST_DISABLE_DEPRECATED" +else + DEPRECATED_CFLAGS="" +fi +AC_SUBST(DEPRECATED_CFLAGS) + +dnl every flag in GST_OPTION_CFLAGS can be overridden at make time via e.g. +dnl make DEPRECATED_CFLAGS='' +GST_OPTION_CFLAGS="\$(WARNING_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)" +GST_OPTION_CFLAGS="$GST_OPTION_CFLAGS" +GST_OPTION_CXXFLAGS="$GST_OPTION_CXXFLAGS" +AC_SUBST(GST_OPTION_CFLAGS) +AC_SUBST(GST_OPTION_CXXFLAGS) + +dnl GST_ALL_* +dnl vars common to for all internal objects (core libs, elements, applications) +dnl CFLAGS: +dnl - src and build dirs need to be added because every piece that gets built +dnl will need the GStreamer source and generated headers +dnl LIBS: XML doesn't need to be added because we don't explicitly use symbols +dnl from LibXML except for in the core library +GST_ALL_CXXFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CXXFLAGS) \$(ERROR_CXXFLAGS)" +GST_ALL_CFLAGS="-I\$(top_srcdir)/libs -I\$(top_srcdir) -I\$(top_builddir)/libs -I\$(top_builddir) $GLIB_CFLAGS \$(GLIB_EXTRA_CFLAGS) $EXTRA_CFLAGS \$(GST_OPTION_CFLAGS) \$(ERROR_CFLAGS)" + +dnl FIXME: check if LTLIBINTL is needed everywhere +dnl I presume it is given that it contains the symbols that _() stuff maps to +GST_ALL_LIBS="$GLIB_LIBS $LTLIBINTL \$(GCOV_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_CFLAGS) +AC_SUBST(GST_ALL_CXXFLAGS) +AC_SUBST(GST_ALL_LIBS) +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 +GST_LIB_LDFLAGS="-export-symbols-regex \^[_]?\(gst_\|Gst\|GST_\).*" +AC_SUBST(GST_LIB_LDFLAGS) + +dnl GST_OBJ_* +dnl default vars for all internal objects built on libgstreamer +dnl includes GST_ALL_* +GST_OBJ_CFLAGS="\$(GST_ALL_CFLAGS) $GST_OBJ_STATIC_CFLAGS" +GST_OBJ_CXXFLAGS="\$(GST_ALL_CXXFLAGS) $GST_OBJ_STATIC_CFLAGS" +GST_OBJ_LIBS="\$(top_builddir)/gst/libgstreamer-$GST_API_VERSION.la \$(GST_ALL_LIBS)" +AC_SUBST(GST_OBJ_CFLAGS) +AC_SUBST(GST_OBJ_CXXFLAGS) +AC_SUBST(GST_OBJ_LIBS) + +dnl GST_PLUGIN_LDFLAGS +dnl LDFLAGS for plugins; includes GST_ALL_LDFLAGS +GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_.*' $GST_ALL_LDFLAGS" +AC_SUBST(GST_PLUGIN_LDFLAGS, "$GST_PLUGIN_LDFLAGS") + +dnl plugin scanner locations +AS_AC_EXPAND(GST_PLUGIN_SCANNER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-plugin-scanner) +AC_DEFINE_UNQUOTED(GST_PLUGIN_SCANNER_INSTALLED, + "$GST_PLUGIN_SCANNER_INSTALLED", [location of the installed gst-plugin-scanner]) +AC_SUBST(GST_PLUGIN_SCANNER_INSTALLED) + +case "${libexecdir}" in + *libexec) + GST_PLUGIN_SCANNER_SUBDIR="libexec";; + *lib) + GST_PLUGIN_SCANNER_SUBDIR="lib";; + *) + GST_PLUGIN_SCANNER_SUBDIR=`basename ${libexecdir}`; + if test -z "$GST_PLUGIN_SCANNER_SUBDIR"; then + AC_MSG_WARN([Couldn't determined libexecdir suffix, using "lib"]) + GST_PLUGIN_SCANNER_SUBDIR="lib"; + fi + ;; +esac +AC_DEFINE_UNQUOTED(GST_PLUGIN_SCANNER_SUBDIR, + "$GST_PLUGIN_SCANNER_SUBDIR", [libexecdir path component, used to find plugin-scanner on relocatable builds on windows]) + + +dnl completion helper locations +AS_AC_EXPAND(GST_COMPLETION_HELPER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-completion-helper) +AC_DEFINE_UNQUOTED(GST_COMPLETION_HELPER_INSTALLED, + "$GST_COMPLETION_HELPER_INSTALLED", [location of the installed gst-completion-helper]) +AC_SUBST(GST_COMPLETION_HELPER_INSTALLED) + +dnl ptp helper locations +AS_AC_EXPAND(GST_PTP_HELPER_INSTALLED,${libexecdir}/gstreamer-$GST_API_VERSION/gst-ptp-helper) +AC_DEFINE_UNQUOTED(GST_PTP_HELPER_INSTALLED, + "$GST_PTP_HELPER_INSTALLED", [location of the installed gst-ptp-helper]) +AC_SUBST(GST_PTP_HELPER_INSTALLED) + +dnl things for our internal libcheck (must be called even if building +dnl libcheck is disabled because it defines conditionals) +AG_GST_CHECK_CHECKS + +AC_CONFIG_FILES( +Makefile +data/Makefile +data/bash-completion/helpers/gst +gst/Makefile +gst/gstconfig.h +gst/gstversion.h +gst/parse/Makefile +gst/printf/Makefile +libs/Makefile +libs/gst/Makefile +libs/gst/base/Makefile +libs/gst/check/Makefile +libs/gst/check/libcheck/Makefile +libs/gst/check/internal-check.h:libs/gst/check/libcheck/check.h.in +libs/gst/controller/Makefile +libs/gst/helpers/Makefile +libs/gst/net/Makefile +plugins/Makefile +plugins/elements/Makefile +plugins/tracers/Makefile +po/Makefile.in +tests/Makefile +tests/benchmarks/Makefile +tests/check/Makefile +tests/misc/Makefile +tests/examples/Makefile +tests/examples/adapter/Makefile +tests/examples/controller/Makefile +tests/examples/stepping/Makefile +tests/examples/helloworld/Makefile +tests/examples/memory/Makefile +tests/examples/netclock/Makefile +tests/examples/ptp/Makefile +tests/examples/streamiddemux/Makefile +tests/examples/streams/Makefile +tools/Makefile +common/Makefile +common/m4/Makefile +docs/Makefile +docs/gst/Makefile +docs/gst/gstreamer.types +docs/libs/Makefile +docs/plugins/Makefile +docs/version.entities +m4/Makefile +pkgconfig/Makefile +stamp.h +pkgconfig/gstreamer.pc +pkgconfig/gstreamer-uninstalled.pc +pkgconfig/gstreamer-base.pc +pkgconfig/gstreamer-base-uninstalled.pc +pkgconfig/gstreamer-check.pc +pkgconfig/gstreamer-check-uninstalled.pc +pkgconfig/gstreamer-controller.pc +pkgconfig/gstreamer-controller-uninstalled.pc +pkgconfig/gstreamer-net.pc +pkgconfig/gstreamer-net-uninstalled.pc +) + +AC_OUTPUT + +dnl negate for output +if test "x${GST_DISABLE_GST_DEBUG}" = "xno"; then enable_gst_debug="yes"; fi +if test "x${GST_DISABLE_GST_TRACER_HOOKS}" = "xno"; then enable_gst_tracer_hooks="yes"; fi +if test "x${GST_DISABLE_PARSE}" = "xno"; then enable_parse="yes"; fi +if test "x${GST_DISABLE_OPTION_PARSING}" = "xno"; then enable_option_parsing="yes"; fi +if test "x${GST_DISABLE_PLUGIN}" = "xno"; then enable_plugin="yes"; fi +if test "x${GST_DISABLE_REGISTRY}" = "xno"; then enable_registry="yes"; fi + +echo " + +Configuration + Version : ${VERSION} + Source code location : ${srcdir} + Prefix : ${prefix} + Compiler : ${CC} + Package name : ${GST_PACKAGE_NAME} + Package origin : ${GST_PACKAGE_ORIGIN} + + API Documentation : ${enable_gtk_doc} + + Debug logging : ${enable_gst_debug} + Tracing subsystem hooks : ${enable_gst_tracer_hooks} + Command-line parser : ${enable_parse} + Option parsing in gst_init : ${enable_option_parsing} + Plugin registry : ${enable_registry} + Plugin support : ${enable_plugin} + Static plugins : ${enable_static_plugins} + Unit testing support : ${BUILD_CHECK} + PTP clock support : ${HAVE_PTP} + libunwind support : ${HAVE_UNWIND} + libdw support : ${HAVE_DW} + + Debug : ${USE_DEBUG} + Profiling : ${USE_PROFILING} + + Building benchmarks : ${BUILD_BENCHMARKS} + Building examples : ${BUILD_EXAMPLES} + Building test apps : ${BUILD_TESTS} + Building tests that fail : ${BUILD_FAILING_TESTS} + Building tools : ${BUILD_TOOLS} +" diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..16214fc --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,7 @@ +if ENABLE_BASH_COMPLETION +bashhelpersdir = $(BASH_HELPERS_DIR) +dist_bashhelpers_DATA = bash-completion/helpers/gst +bashcompletiondir = $(BASH_COMPLETION_DIR) +dist_bashcompletion_DATA = bash-completion/completions/gst-inspect-1.0 \ + bash-completion/completions/gst-launch-1.0 +endif diff --git a/data/Makefile.in b/data/Makefile.in new file mode 100644 index 0000000..4715a44 --- /dev/null +++ b/data/Makefile.in @@ -0,0 +1,724 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(am__dist_bashcompletion_DATA_DIST) \ + $(am__dist_bashhelpers_DATA_DIST) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__dist_bashcompletion_DATA_DIST = \ + bash-completion/completions/gst-inspect-1.0 \ + bash-completion/completions/gst-launch-1.0 +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bashcompletiondir)" \ + "$(DESTDIR)$(bashhelpersdir)" +am__dist_bashhelpers_DATA_DIST = bash-completion/helpers/gst +DATA = $(dist_bashcompletion_DATA) $(dist_bashhelpers_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@ENABLE_BASH_COMPLETION_TRUE@bashhelpersdir = $(BASH_HELPERS_DIR) +@ENABLE_BASH_COMPLETION_TRUE@dist_bashhelpers_DATA = bash-completion/helpers/gst +@ENABLE_BASH_COMPLETION_TRUE@bashcompletiondir = $(BASH_COMPLETION_DIR) +@ENABLE_BASH_COMPLETION_TRUE@dist_bashcompletion_DATA = bash-completion/completions/gst-inspect-1.0 \ +@ENABLE_BASH_COMPLETION_TRUE@ bash-completion/completions/gst-launch-1.0 + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_bashcompletionDATA: $(dist_bashcompletion_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_bashcompletion_DATA)'; test -n "$(bashcompletiondir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bashcompletiondir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bashcompletiondir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(bashcompletiondir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(bashcompletiondir)" || exit $$?; \ + done + +uninstall-dist_bashcompletionDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_bashcompletion_DATA)'; test -n "$(bashcompletiondir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(bashcompletiondir)'; $(am__uninstall_files_from_dir) +install-dist_bashhelpersDATA: $(dist_bashhelpers_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_bashhelpers_DATA)'; test -n "$(bashhelpersdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bashhelpersdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bashhelpersdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(bashhelpersdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(bashhelpersdir)" || exit $$?; \ + done + +uninstall-dist_bashhelpersDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_bashhelpers_DATA)'; test -n "$(bashhelpersdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(bashhelpersdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(bashcompletiondir)" "$(DESTDIR)$(bashhelpersdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_bashcompletionDATA \ + install-dist_bashhelpersDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_bashcompletionDATA \ + uninstall-dist_bashhelpersDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_bashcompletionDATA install-dist_bashhelpersDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am \ + uninstall-dist_bashcompletionDATA \ + uninstall-dist_bashhelpersDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/data/bash-completion/completions/gst-inspect-1.0 b/data/bash-completion/completions/gst-inspect-1.0 new file mode 100644 index 0000000..667e503 --- /dev/null +++ b/data/bash-completion/completions/gst-inspect-1.0 @@ -0,0 +1,104 @@ +# GStreamer +# Copyright (C) 2015 Mathieu Duponchelle +# +# bash/zsh completion support for gst-inspect +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301, USA. + +_GST_HELPERDIR="${BASH_SOURCE[0]%/*}/../helpers" + +if [[ ! -d "$_GST_HELPERDIR" ]]; then + _GST_HELPERDIR="$(pkg-config --variable=bashhelpersdir gstreamer-1.0)" +else + _GST_HELPERDIR=`cd "$_GST_HELPERDIR"; pwd` +fi + +# Common definitions +. "$_GST_HELPERDIR"/gst + +_gst_inspect_all_arguments () +{ + _gst_all_arguments gst-inspect-1.0 +} + +_gst_inspect_all_elements () +{ + COMPREPLY=( $(compgen -W "$($_GST_HELPER -l)" -- $cur) ) +} + +_gstinspect___atleast_version () { _gst_mandatory_argument gst-inspect-1.0; } + +_gstinspect___exists () +{ + _gst_inspect_all_elements +} + +__inspect_main () +{ + local i=1 command function_exists completion_func + + while [[ $i -ne $COMP_CWORD ]]; + do + local var + var="${COMP_WORDS[i]}" + if [[ "$var" == "-"* ]] + then + command="$var" + fi + i=$(($i+1)) + done + + if [[ "$command" == "--gst"* ]]; then + completion_func="_${command//-/_}" + else + completion_func="_gstinspect_${command//-/_}" + fi + + declare -f $completion_func >/dev/null 2>&1 + + function_exists=$? + + if [[ "$cur" == "-"* ]] + then + _gst_inspect_all_arguments + elif [ $function_exists -eq 0 ] + then + $completion_func + else + _gst_inspect_all_elements + fi +} + +_gst_inspect_func_wrap () +{ + local cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + $1 +} + +# Setup completion for certain functions defined above by setting common +# variables and workarounds. +# This is NOT a public function; use at your own risk. +_gst_inspect_complete () +{ + local wrapper="__inspect_wrap${2}" + eval "$wrapper () { _gst_inspect_func_wrap $2 ; }" + complete -o bashdefault -o default -o nospace -F $wrapper $1 2>/dev/null \ + || complete -o default -o nospace -F $wrapper $1 +} + +_gst_inspect_complete gst-inspect-1.0 __inspect_main diff --git a/data/bash-completion/completions/gst-launch-1.0 b/data/bash-completion/completions/gst-launch-1.0 new file mode 100644 index 0000000..80ad34c --- /dev/null +++ b/data/bash-completion/completions/gst-launch-1.0 @@ -0,0 +1,141 @@ +# GStreamer +# Copyright (C) 2015 Mathieu Duponchelle +# +# bash/zsh completion support for gst-launch +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301, USA. + +_GST_HELPERDIR="${BASH_SOURCE[0]%/*}/../helpers" + +if [[ ! -d "$_GST_HELPERDIR" ]]; then + _GST_HELPERDIR="$(pkg-config --variable=bashhelpersdir gstreamer-1.0)" +else + _GST_HELPERDIR=`cd "$_GST_HELPERDIR"; pwd` +fi + +# Common definitions +. "$_GST_HELPERDIR"/gst + +_gst_launch_all_arguments () +{ + _gst_all_arguments gst-launch-1.0 +} + +_gst_complete_compatible_elements () +{ + COMPREPLY=( $(compgen -W "$($_GST_HELPER --compatible-with $previous_element)" -- $cur) ) +} + +_gst_complete_all_elements () +{ + COMPREPLY=( $(compgen -W "$($_GST_HELPER -l)" -- $cur) ) +} + +_gst_complete_element_properties () +{ + COMPREPLY=( $(compgen -W "$($_GST_HELPER --element-properties $previous_element)" -- $cur) ) +} + +_gstlaunch___exclude_ () { _gst_mandatory_argument gst-launch-1.0; } + +_gst_launch_main () +{ + local i=1 command function_exists previous_element have_previous_element=0 completion_func + + while [[ $i -ne $COMP_CWORD ]]; + do + local var + var="${COMP_WORDS[i]}" + if [[ "$var" == "-"* ]] + then + command="$var" + fi + i=$(($i+1)) + done + + i=1 + while [[ $i -ne $COMP_CWORD ]]; + do + local var + var="${COMP_WORDS[i]}" + + if [[ "$var" == "-"* ]] + then + i=$(($i+1)) + continue + fi + + $(gst-inspect-1.0 --exists $var) + if [ $? -eq 0 ] + then + previous_element="$var" + have_previous_element=1 + fi + i=$(($i+1)) + done + + if [[ "$command" == "--gst"* ]]; then + completion_func="_${command//-/_}" + else + completion_func="_gstlaunch_${command//-/_}" + fi + + # Seems like bash doesn't like "exclude" in function names + if [[ "$completion_func" == "_gstlaunch___exclude" ]] + then + completion_func="_gstlaunch___exclude_" + fi + + declare -f $completion_func >/dev/null 2>&1 + + function_exists=$? + + if [[ "$cur" == "-"* ]]; then + _gst_launch_all_arguments + elif [ $function_exists -eq 0 ] + then + $completion_func + elif [ $have_previous_element -ne 0 ] && [[ "$prev" == "!" ]] + then + _gst_complete_compatible_elements + elif [ $have_previous_element -ne 0 ] + then + _gst_complete_element_properties + else + _gst_complete_all_elements + fi +} + +_gst_launch_func_wrap () +{ + local cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + $1 +} + +# Setup completion for certain functions defined above by setting common +# variables and workarounds. +# This is NOT a public function; use at your own risk. +_gst_launch_complete () +{ + local wrapper="__launch_wrap${2}" + eval "$wrapper () { _gst_launch_func_wrap $2 ; }" + complete -o bashdefault -o default -o nospace -F $wrapper $1 2>/dev/null \ + || complete -o default -o nospace -F $wrapper $1 +} + +_gst_launch_complete gst-launch-1.0 _gst_launch_main diff --git a/data/bash-completion/helpers/gst b/data/bash-completion/helpers/gst new file mode 100644 index 0000000..b2176ed --- /dev/null +++ b/data/bash-completion/helpers/gst @@ -0,0 +1,57 @@ +# GStreamer +# Copyright (C) 2015 Mathieu Duponchelle +# +# bash/zsh completion support for common gstreamer options +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301, USA. + +_GST_HELPER="/usr/local/libexec/gstreamer-1.0/gst-completion-helper" +if [[ ! -x "$_GST_HELPER" ]] +then + helper="$(pkg-config --variable=helpersdir gstreamer-1.0)/gst-completion-helper" + + if [ -x "$helper" ] + then + _GST_HELPER=$helper + fi +fi + +___gst_debug_level () { _gst_mandatory_argument; } +___gst_debug () { _gst_mandatory_argument; } +___gst_debug_color_mode () { _gst_mandatory_argument; } +___gst_plugin_path () { _gst_mandatory_argument; } +___gst_plugin_load () { _gst_mandatory_argument; } + +_gst_all_arguments () +{ + COMPREPLY=( $(compgen -W "$($1 --help-all | grep "^ -" | grep -oh '[[:graph:]]*--[[:graph:]]*\|-[[:alpha:]],' | cut -d'=' -f1 | cut -d',' -f1)" -- $cur) ) +} + +_gst_mandatory_argument () +{ + __app=$1 + if [[ -z $__app ]] + then + __app=gst-launch-1.0 + fi + + if [[ "$prev" != "$command" ]] + then + _gst_all_arguments $__app + else + COMPREPLY=("$cur") + fi +} diff --git a/data/bash-completion/helpers/gst.in b/data/bash-completion/helpers/gst.in new file mode 100644 index 0000000..42cfb26 --- /dev/null +++ b/data/bash-completion/helpers/gst.in @@ -0,0 +1,57 @@ +# GStreamer +# Copyright (C) 2015 Mathieu Duponchelle +# +# bash/zsh completion support for common gstreamer options +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301, USA. + +_GST_HELPER="@GST_COMPLETION_HELPER_INSTALLED@" +if [[ ! -x "$_GST_HELPER" ]] +then + helper="$(pkg-config --variable=helpersdir gstreamer-@GST_API_VERSION@)/gst-completion-helper" + + if [ -x "$helper" ] + then + _GST_HELPER=$helper + fi +fi + +___gst_debug_level () { _gst_mandatory_argument; } +___gst_debug () { _gst_mandatory_argument; } +___gst_debug_color_mode () { _gst_mandatory_argument; } +___gst_plugin_path () { _gst_mandatory_argument; } +___gst_plugin_load () { _gst_mandatory_argument; } + +_gst_all_arguments () +{ + COMPREPLY=( $(compgen -W "$($1 --help-all | grep "^ -" | grep -oh '[[:graph:]]*--[[:graph:]]*\|-[[:alpha:]],' | cut -d'=' -f1 | cut -d',' -f1)" -- $cur) ) +} + +_gst_mandatory_argument () +{ + __app=$1 + if [[ -z $__app ]] + then + __app=gst-launch-1.0 + fi + + if [[ "$prev" != "$command" ]] + then + _gst_all_arguments $__app + else + COMPREPLY=("$cur") + fi +} diff --git a/data/bash-completion/helpers/meson.build b/data/bash-completion/helpers/meson.build new file mode 100644 index 0000000..c5399bf --- /dev/null +++ b/data/bash-completion/helpers/meson.build @@ -0,0 +1,9 @@ +bash_helper_conf = configuration_data() +bash_helper_conf.set('GST_COMPLETION_HELPER_INSTALLED', + join_paths(prefix, helpers_install_dir, 'gst-completion-helper')) +bash_helper_conf.set('GST_API_VERSION', apiversion) + +configure_file(input : 'gst.in', + output : 'gst', + install_dir : bash_helpers_dir, + configuration : bash_helper_conf) diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 0000000..c9130e0 --- /dev/null +++ b/data/meson.build @@ -0,0 +1,5 @@ +if (bashcomp_found) + subdir('bash-completion/helpers') + install_data('bash-completion/completions/gst-launch-1.0', install_dir : bash_completions_dir) + install_data('bash-completion/completions/gst-inspect-1.0', install_dir : bash_completions_dir) +endif diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..b39f98f --- /dev/null +++ b/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# 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. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..4772ebc --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,23 @@ +if ENABLE_GTK_DOC +if ENABLE_PLUGIN_DOCS +PLUGIN_DOCS_DIRS = plugins +else +PLUGIN_DOCS_DIRS = +endif +else +PLUGIN_DOCS_DIRS = plugins +endif + +BUILT_SOURCES = version.entities + +SUBDIRS = gst libs $(PLUGIN_DOCS_DIRS) +DIST_SUBDIRS = gst libs plugins + +EXTRA_DIST = version.entities.in list-ulink.xsl + +upload: + @if test "x$(SUBDIRS)" != x; then for a in $(SUBDIRS); do cd $$a; make upload; cd ..; done; fi + +libs: gst + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/docs/Makefile.in b/docs/Makefile.in new file mode 100644 index 0000000..81613a6 --- /dev/null +++ b/docs/Makefile.in @@ -0,0 +1,845 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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. +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = docs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = version.entities +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/version.entities.in \ + $(top_srcdir)/common/parallel-subdirs.mak README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@ENABLE_GTK_DOC_FALSE@PLUGIN_DOCS_DIRS = plugins +@ENABLE_GTK_DOC_TRUE@@ENABLE_PLUGIN_DOCS_FALSE@PLUGIN_DOCS_DIRS = +@ENABLE_GTK_DOC_TRUE@@ENABLE_PLUGIN_DOCS_TRUE@PLUGIN_DOCS_DIRS = plugins +BUILT_SOURCES = version.entities +SUBDIRS = gst libs $(PLUGIN_DOCS_DIRS) +DIST_SUBDIRS = gst libs plugins +EXTRA_DIST = version.entities.in list-ulink.xsl +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/parallel-subdirs.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/parallel-subdirs.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +version.entities: $(top_builddir)/config.status $(srcdir)/version.entities.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +upload: + @if test "x$(SUBDIRS)" != x; then for a in $(SUBDIRS); do cd $$a; make upload; cd ..; done; fi + +libs: gst + +.PHONY: independent-subdirs $(SUBDIRS) + +independent-subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ + +all-recursive: independent-subdirs + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/README b/docs/README new file mode 100644 index 0000000..a7b46fe --- /dev/null +++ b/docs/README @@ -0,0 +1,368 @@ +GStreamer documentation notes + +IMPORTANT +========= + +Please make sure you've read and understood everything in this file +before you try changing documentation. + +Some of the docbook-related bits in this README might be out of date now that +quite a bit of the documentation has moved into the gst-docs repository. + +OVERVIEW +======== + +GStreamer has two sets of documentation that we maintain: +* API references, using gtk-doc (gstreamer, gstreamer-libs) +* FAQ / Application Development Manual / Plugin Writer's Guide / Tutorials - + these are maintained in markdown format and live in the gst-docs repository. + +DOCBOOK NOTES +============= + +OK, I've grown so tired of having to coax the docs to build every time I +get round to it that I've decided to note down some of the things that +are important to know. + +OVERVIEW +-------- +* Our documentation should all be Docbook/XML. No SGML. +* The source for the documentation is: + - one or more .xml files, with the main one being gstreamer-(whatever).xml + - image files + - in .svg + - in .png (and maybe others) +* We want to generate docs in HTML, PS and PDF +* We want to use xml to to generate these + +CONVENTIONS +----------- +We stick to some simple conventions for writing docbook documentation. +* id names: + - all id's start with chapter-, part-, section-, or misc- + - verify this is the case by looking at the generated file names in html/ + - sections should also include the chapter name; + for example in a chapter called chapter-example, a section would be + called section-example-hello-world + +HOW IMAGES ARE HANDLED +---------------------- +* the format of images used is: + - PNG for html + - EPS for ps + - PDF for pdf + +* images may need to be converted from their source format to the end format + +* a file called image.entities is generated that provides two entities: + ℑ and &IMAGE; + ℑ is the file extension (png, ps, pdf) +* all generated images will be put in images/ + +HOW THE BUILD WORKS FOR EACH FORMAT +----------------------------------- +* HTML: + - xmlto html gstreamer-whatever.xml should produce the html docs. + - We do this in the html subdir of the doc builddir. + - images are copied to (builddir)/html/images + - PNGS should be set to all of the png's referenced for html, both + already there and auto-generated + +* PS : + - images are converted to .ps files in EPS format. Generated images are + put in images/ + - xmlto ps gstreamer-whatever.xml generates the ps file + +* PDF : + There are two ways: + - ps2pdf is the easiest + - we specify ps, PS as the image type, but using xmlto the build will fail + because it uses ps2pdf internally and it fails to generate the images + By hand-generating .pdf images before xmlto we can make the build succeed. + (This is why image-pdf has file ext pdf but type EPS; this tricks xmlto in + doing the right thing) + xmlto pdf gstreamer-whatever.xml generates pdf (but seems to fail on the + FAQ, so for now we use ps2pdf) + +HOW THE BUILD SYSTEM IS SET UP +------------------------------ +* make all should build html, ps, and pdf +* html is built in a subdir, with the png/ps images copied there +* ps and pdf are built in the current dir, in one file + +SPELL CHECKING +-------------- +* with aspell + * aspell -b -c --mode=sgml --lang=en .xml + unfortunately the curses-ui of aspell (0.50.5) has problems with the xml tags + + +GTK-DOC NOTES +============= + +* files under revision control: + - Makefile.am + - gstreamer-sections.txt + describes which symbols later appear on one api-doc page + configure which symbols are shown/invisible/private + - gstreamer.types + the types file lists all get_type() functions that register the GObject types + - gstreamer-docs.sgml + defines the overall structure of the api documentation + - tmpl/ + - only add the file to CVS if you have at least filled the short description + (filename corresponds to the tag in the sections file) + - document as much as possible in the source (*.c files) + +* what to do when adding a new piece of API: + - add both an entity and use the entity in gstreamer-docs.sgml + - add a new
to gstreamer-sections.txt in the correct alphabetical + position related to the other sections (so that it is easier to locate) + - add all documented symbols to gstreamer-sections.txt in the proper section + (default),, + - document at least the Short_Description in tmpl/.sgml + - document symbols where they are defined, so that when one changes the + definition, the chaces are good that docs are updated. + - document functions, signals in the .c files + - document structs, typedefs, enums in the .h files + +* checklist: + - make sure *-sections.txt has a set for each <FILE> + - add only *one* <TITLE> to each file, when you have multiple classes in one + source-file, create one <FILE> section for each class + - the <TITLE> *must* be named like the type of the GType, when it gets + registered (otherwise gtkdoc introspection fails) + - for clarity name the <FILE> like the <TITLE>, but all lowercase + +* what to do when trying to improve the docs + - compare the output of + grep "_get_type" gstreamer-sections.txt | sort + with the types in XXX.types to detect entries that + are maybe missing + - gtk docs does not warns about empty member docs!, run + find . -name "*.[c,h]" -exec egrep -Hn "^ +\* +@.*: *$" {} \; + in the project root to find them + - gtk docs does not warns about empty Returns: docs!, run + find . -name "*.[c,h]" -exec egrep -Hn "^ +\* +@Returns: *$" {} \; + in the project root to find them + +* what happens during a gtk-doc build ? + - Scan step: + - based on a $(MODULE).types file: + - gtkdoc-scangobj creates a gtkdoc-scan binary + - using CC, LD, CFLAGS, LDFLAGS env var + - using --type-init-func and --module parameters + - gtkdoc-scan creates + - $MODULE.signals.new + - $MODULE.hierarchy.new + - $MODULE.interfaces.new + - $MODULE.prerequisites.new + - $MODULE.args.new + - generated source and objects get deleted + - gtkdoc-scangobj merges changes into the original files + - gtkdoc-scan + - extracts decls of functions, macros, enums, structs, unions from headers + - generates + - $MODULE-decl.txt + - $MODULE-decl-list.txt + - $MODULE-decl-list.txt then should get copied to $MODULE-sections.txt + - scan-build.stamp gets created + + - Template generation step: + - gtkdoc-mktmpl --module=$MODULE + - reads in tmpl/*.sgml + - moves them to tmpl/*.sgml.bak + - recreates tmpl/*.sgml according to $MODULE-sections.txt + - moves unused stuff to $MODULE-unused.txt + - tmpl-build.stamp gets generated + +* Possible errors and how to fix them + - Warning: multiple "IDs" for constraint linkend: gst-tag-register. + - check if gst_tag_register is listed more than once in -sections.txt + +STYLE GUIDE FOR GTK-DOC +======================= +- this is in addition to gtk-doc's style-guide.txt + +- when documenting signals, use "the #Gst..." for the object receiving the + signal; no trailing dot, and no "that received the signal" +- function/macro descriptions are descriptive, not imperative + ie, it uses the third person verb +- synopsis and description should have most-used/application functions at the + top +- functions that can return FALSE/NULL or fail should describe their failure + conditions like this: + * Returns NULL if no element with the given name is found in the bin, if + * the frobble was stuck in the froob, or the frizzle was frazzed. +- a line with function attributes should be added before Returns: + - can contain: + "MT safe." - the function is verified to be multithreadingsafe + "Caller owns returned reference" for refcounted classes + "Caller owns returned value" for other types (iterators, ..) + - we do this because, in contrast with GLib/GTK, we are more explicit + about threadsafety and related issues +- link to signals from the description like this: + * The <link linkend="GstBin-element-added">element-added</link> signal + +WEBSITE DOCUMENTATION +===================== + +Updating the online documentation is pretty simple. +Make sure that you +a) have a working freedesktop.org account +b) $HOME/.ssh/config set up so that it has the right User for the Host + (for example, I have: +Host freedesktop.org + User thomasvs +c) verify this works by doing ssh freedesktop.org and being logged in without + a password prompt +d) have verified your changes build documentation locally. + +Then, after updating any of the docs, run "make upload" from that directory. +Or, run "make upload" from this (docs) directory. + +DOCUMENTING ELEMENTS +==================== +As of september 2005 we have some system to document plugins and elements +in the various plugin packages. + +- in a submodule, docs go in docs/plugins +- template can be copied from gst-plugins-base +- to add plugins documentation: + - create docs/plugins + - create Makefile.am and friends, add to configure.ac + - create docs/version.entities.in, add to configure.ac + - in docs/plugins: + - create $(module)-plugins.types with #include <gst/gst.h> + - run make + - edit the -docs.sgml + - add to cvs: + cvs add *-plugins-docs.sgml *-plugins.args *-plugins.hierarchy *-plugins.interfaces *-plugins.prerequisites *-plugins.signals *-plugins.types inspect-build.stamp inspect.stamp scanobj-build.stamp + cvs add inspect + cvs add inspect/*.xml + - Additional types can be added to the documentation by placing them in + the .types file like this: + type:GstPlayBaseBin + This is useful for documenting plugin-private types that implement + signals or properties. The GType is looked up by name after all the + element classes have been printed - so this is only useful for types + that are created as a consequence of loading plugins and registering + the element(s). + +- to add a plugin to be documented: + - make sure inspect/ has generated a inspect/plugin-xxx.xml file for it. + - if it has not, make sure you have pygst installed and run 'make update'. + and add it to CVS. + - add an xi:include in -docs.sgml in the Plugins chapter for that plugin + +- to add an element to be documented: + - add an xi:include in the Elements chapter for the element + in the main -docs.sgml + - add a section for it in -sections.txt with + <SECTION> + <FILE>element-(element)</FILE> + <TITLE>(element) + GstXxx + + GstXxxClass + GST_XXX + GST_XXX_CLASS + GST_IS_XXX + GST_IS_XXX_CLASS + GST_TYPE_XXX + gst_xxx_get_type +
+ - add a gtk-doc section to the source code like: +/** + * SECTION:element-multifdsink + + and fill it with documentation about the element, preferably inside + a docbook container. + - add an example: + - either a few pipelines, inside + - or a piece of code: + - create an example program (element)-example.c in the plugin dir + - add the full path (starting with $(top_srcdir)) for this example + to the EXAMPLE_CFILES variable in Makefile.am + - add an xinclude of a file named "element-(element)-example.xml" + to the docbook documentation piece in the element source code + - add the header to EXTRA_HFILES in Makefile.am to be able to document + signals and args; in that case, the object struct needs to be in + -sections.txt outside of the Standard Subsection (which is annoying, + but ...) + (FIXME: are we sure we can both do the xinclude from the tmpl/ sgml, + as well as an override from the source itself ? maybe we should just + make sure the xinclude is in the source itself instead ?) + - if the plugin has no public header, don't add the c-file, add entries to the + -overrides.txt file (see playbin docs in plugins-base). + - to rebuild the docs, do: + make clean + make update + make + - examples will only show up using gtk-doc 1.4 or later - it relies on + merging stuff from .sgml with inline docs. We might want to change + this to only get stuff from the source. + - you need to commit resulting files to git: + - changes to *.signals and *.args + - new files for your plugin created in inspect/ + - if you get this warning: + " Documentation in template xxx for ./tmpl/element-yyy:Short_Description + being overridden by inline comments" + per-default the description from the GST_ELEMENT_DETAILS is put to the + Short_Description. This warning mean you have a different one in the section + docs as "@short_description:". + +- the plugin-doc-list on the gstreamer homepage is updated along with other + web site updates. + +- maintainer tricks: + - in gst-plugins-foo/docs/plugins/, run + make check-inspected-versions + to show plugins whose inspect information is not up-to-date (which is + usually either because they have been moved to a different module or + because they are not built on the maintainer's machine for some reason). + Whether it really makes sense to update the version number is debatable + (after all, the inspected information may be outdated and things may have + changed, in which case it would be bad to change the version number) + - find files that have docs + for file in `find . -name "*.c" -exec grep -l " * SECTION:element-" {} \; | sort`; do if [ -e ${file/.c/.h} ]; then echo ${file/.c/.h}; else echo "no header for $file"; fi; done + for file in `find . -name "*.cc" -exec grep -l " * SECTION:element-" {} \; | sort`; do if [ -e ${file/.cc/.h} ]; then echo ${file/.cc/.h}; else echo "no header for $file"; fi; done + - add those .h files to EXTRA_HFILES in Makefile.am + - update gst-plugins-xxx-docs.sgml + cd docs/plugins + ls -1 xml/plugin-*.xml | sort | sed -e "s/\(.*\)/ \/" + ls -1 xml/element-*.xml | grep -v -- "-details.xml" | sort | sed -e "s/\(.*\)/ \/" + - maybe we can generate these lists after "make update" and just xi:include + them in gst-plugins-xxx-docs.sgml. They should be committed to the vcs. + +- possible errors: + - "multiple constraints for linkend ID": + check if each section in -sections.txt actually starts and ends with +
and
+ - if a plugin does not show up: + - check inspect/plugin-xxx.xml and tmpl/elements- + +RANDOM THINGS I'VE LEARNED +========================== + +* for clean builddir != srcdir separation, I wanted to use xmlto --searchpath + so the source xml could find the built entity file. + But xmlto --searchpath is (right now) for TeX input, not xml input. + xsltproc has a --path option (that xmlto doesn't use yet), but it + resolves single files to $(specified_path)/$(srcdir)/$(file) + For now, we need to hack around it by copying xml to the build dir. + + +DEVHELP INTEGRATION +------------------- +Check https://wiki.gnome.org/Apps/Devhelp +It's a really nice development app allowing you to look up API stuff +from various gtk-doc'd libraries. GStreamer is one of these ;) + +gtk-doc generates both html API docs and the matching .devhelp(2) books. + +IMAGES +------ +It's important to keep the original source format for images, to be able +to change and regenerate later on. Original files go in +docs/images diff --git a/docs/gst/Makefile.am b/docs/gst/Makefile.am new file mode 100644 index 0000000..af93687 --- /dev/null +++ b/docs/gst/Makefile.am @@ -0,0 +1,96 @@ +## Process this file with automake to produce Makefile.in + +# The name of the module, e.g. 'glib'. +# DOC_MODULE=gstreamer-@GST_API_VERSION@ +DOC_MODULE=gstreamer + +# don't want $(DOC_MODULE)-scan.c to be built with -Werror +ERROR_CFLAGS= + +BUILT_SOURCES=gstreamer.types + +# for upload-doc.mak +DOC=gstreamer +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The files 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 + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED" \ + --ignore-decorators='GST_API' + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode --output-format=xml --ignore-files=parse + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(top_srcdir)/gst/*.h +CFILE_GLOB=$(top_srcdir)/gst/*.c + +# Header files to ignore when scanning. Use base file name, no paths +IGNORE_HFILES= \ + gettext.h \ + glib-compat-private.h \ + glib-compat.h \ + gst-i18n-app.h \ + gst-i18n-lib.h \ + gst_private.h \ + gstelementdetails.h \ + gstmacros.h \ + gstmarshal.h \ + math-compat.h \ + \ + grammar.tab.h \ + grammar.tab.pre.h \ + parse_lex.h \ + types.h \ + \ + gst-printf.h \ + printf-args.h \ + printf-extension.h \ + printf-parse.h \ + vasnprintf.h + +gst-universe.svg: gst-universe.dot + -dot -Tsvg $< | sed 's/\(font-size:[0-9]*\.[0-9]*\);/\1px;/g' >$@ + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = building.xml running.xml gst-universe.svg + +# Other files to distribute. +extra_files = gst-universe.dot + +# 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_OBJ_CFLAGS) -DGST_USE_UNSTABLE_API +GTKDOC_LIBS = $(GST_OBJ_LIBS) \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la + +GTKDOC_EXTRA_ENVIRONMENT= \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt + +include $(top_srcdir)/common/gtk-doc.mak + +# gtk-doc.mak defines CLEANFILES +CLEANFILES += gst-universe.svg + diff --git a/docs/gst/Makefile.in b/docs/gst/Makefile.in new file mode 100644 index 0000000..d5518fe --- /dev/null +++ b/docs/gst/Makefile.in @@ -0,0 +1,1039 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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 + +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = docs/gst +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = gstreamer.types +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/gstreamer.types.in \ + $(top_srcdir)/common/gtk-doc.mak \ + $(top_srcdir)/common/upload-doc.mak +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ + +# don't want $(DOC_MODULE)-scan.c to be built with -Werror +ERROR_CFLAGS = +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# The name of the module, e.g. 'glib'. +# DOC_MODULE=gstreamer-@GST_API_VERSION@ +DOC_MODULE = gstreamer +BUILT_SOURCES = gstreamer.types + +# for upload-doc.mak +DOC = gstreamer +FORMATS = html + +# 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) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml + +# The files 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 + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS = --deprecated-guards="GST_DISABLE_DEPRECATED" \ + --ignore-decorators='GST_API' + + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --sgml-mode --output-format=xml --ignore-files=parse + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS = --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB = $(top_srcdir)/gst/*.h +CFILE_GLOB = $(top_srcdir)/gst/*.c + +# Header files to ignore when scanning. Use base file name, no paths +IGNORE_HFILES = \ + gettext.h \ + glib-compat-private.h \ + glib-compat.h \ + gst-i18n-app.h \ + gst-i18n-lib.h \ + gst_private.h \ + gstelementdetails.h \ + gstmacros.h \ + gstmarshal.h \ + math-compat.h \ + \ + grammar.tab.h \ + grammar.tab.pre.h \ + parse_lex.h \ + types.h \ + \ + gst-printf.h \ + printf-args.h \ + printf-extension.h \ + printf-parse.h \ + vasnprintf.h + + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = building.xml running.xml gst-universe.svg + +# Other files to distribute. +extra_files = gst-universe.dot + +# 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_OBJ_CFLAGS) -DGST_USE_UNSTABLE_API +GTKDOC_LIBS = $(GST_OBJ_LIBS) \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la + +GTKDOC_EXTRA_ENVIRONMENT = \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute + +# 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_API_VERSION@ +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 \ + 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 + + +# gtk-doc.mak defines CLEANFILES +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) \ + doc-registry.xml gst-universe.svg +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/gst/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/gst/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +gstreamer.types: $(top_builddir)/config.status $(srcdir)/gstreamer.types.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile all-local +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: all check install install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-local + +.PRECIOUS: Makefile + +html: html-build.stamp + +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 X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(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; \ + \ + 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 + +gst-universe.svg: gst-universe.dot + -dot -Tsvg $< | sed 's/\(font-size:[0-9]*\.[0-9]*\);/\1px;/g' >$@ + +@ENABLE_GTK_DOC_TRUE@all-local: html-build.stamp + +#### setup #### + +@ENABLE_GTK_DOC_TRUE@setup-build.stamp: $(content_files) +@ENABLE_GTK_DOC_TRUE@ -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ +@ENABLE_GTK_DOC_TRUE@ echo ' DOC Preparing build'; \ +@ENABLE_GTK_DOC_TRUE@ files=`echo $(DOC_MAIN_SGML_FILE) $(DOC_OVERRIDES) $(DOC_MODULE)-sections.txt $(DOC_MODULE).types $(content_files)`; \ +@ENABLE_GTK_DOC_TRUE@ if test "x$$files" != "x" ; then \ +@ENABLE_GTK_DOC_TRUE@ for file in $$files ; do \ +@ENABLE_GTK_DOC_TRUE@ test -f $(abs_srcdir)/$$file && \ +@ENABLE_GTK_DOC_TRUE@ cp -pu $(abs_srcdir)/$$file $(abs_builddir)/ || true; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch setup-build.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 +@ENABLE_GTK_DOC_TRUE@scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Scanning header files' +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scan \ +@ENABLE_GTK_DOC_TRUE@ $(SCAN_OPTIONS) $(EXTRA_HFILES) \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $${_source_dir} \ +@ENABLE_GTK_DOC_TRUE@ --ignore-headers="$(IGNORE_HFILES)" +@ENABLE_GTK_DOC_TRUE@ @if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; then \ +@ENABLE_GTK_DOC_TRUE@ echo " DOC Introspecting gobjects"; \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$$?" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options="--verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0=`cd $(top_builddir) && pwd` \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_PATH_1_0= \ +@ENABLE_GTK_DOC_TRUE@ GST_REGISTRY_1_0=doc-registry.xml \ +@ENABLE_GTK_DOC_TRUE@ $(GTKDOC_EXTRA_ENVIRONMENT) \ +@ENABLE_GTK_DOC_TRUE@ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" \ +@ENABLE_GTK_DOC_TRUE@ CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ +@ENABLE_GTK_DOC_TRUE@ $$scanobj_options --module=$(DOC_MODULE) ; \ +@ENABLE_GTK_DOC_TRUE@ else \ +@ENABLE_GTK_DOC_TRUE@ for i in $(SCANOBJ_FILES) ; do \ +@ENABLE_GTK_DOC_TRUE@ $(MKDIR_P) $(dirname $$i) ; \ +@ENABLE_GTK_DOC_TRUE@ test -f $$i || touch $$i ; \ +@ENABLE_GTK_DOC_TRUE@ done \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch scan-build.stamp + +@ENABLE_GTK_DOC_TRUE@$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### xml #### + +@ENABLE_GTK_DOC_TRUE@sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building XML' +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkdb --module=$(DOC_MODULE) $${_source_dir} --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities xml +@ENABLE_GTK_DOC_TRUE@ @touch sgml-build.stamp + +@ENABLE_GTK_DOC_TRUE@sgml.stamp: sgml-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### html #### + +@ENABLE_GTK_DOC_TRUE@html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building HTML' +@ENABLE_GTK_DOC_TRUE@ @rm -rf html +@ENABLE_GTK_DOC_TRUE@ @mkdir html +@ENABLE_GTK_DOC_TRUE@ @cp -pr xml html +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities ./ +@ENABLE_GTK_DOC_TRUE@ @mkhtml_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options="$$mkhtml_options --verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options=--path="$(abs_srcdir)"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE)-@GST_API_VERSION@ ../$(DOC_MAIN_SGML_FILE) +@ENABLE_GTK_DOC_TRUE@ @rm -rf html/xml +@ENABLE_GTK_DOC_TRUE@ @rm -f version.entities +@ENABLE_GTK_DOC_TRUE@ @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Fixing cross-references' +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @touch html-build.stamp + +@ENABLE_GTK_DOC_TRUE@clean-local-gtkdoc: +@ENABLE_GTK_DOC_TRUE@ @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ rm -rf $(DOC_MODULE).types; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_FALSE@all-local: +@ENABLE_GTK_DOC_FALSE@clean-local-gtkdoc: + +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_MAIN_SGML_FILE) ; \ + rm -f $(DOC_OVERRIDES) ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -f $(content_files) ; \ + 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)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(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 +# +@ENABLE_GTK_DOC_TRUE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@ @echo "*** gtk-doc must be installed and enabled in order to make dist" +@ENABLE_GTK_DOC_FALSE@ @false + +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: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/gst/building.xml b/docs/gst/building.xml new file mode 100644 index 0000000..a7f8fc5 --- /dev/null +++ b/docs/gst/building.xml @@ -0,0 +1,100 @@ + + +%version-entities; + +]> + + +Building GStreamer and GStreamer Applications +3 +GStreamer Core + + + +Building GStreamer and GStreamer Applications + +How to build the GStreamer framework and applications using it. + + + + +Building GStreamer on UNIX + + + + On UNIX, GStreamer uses the standard GNU build system, + using autoconf for package + configuration and resolving portability issues, + automake for building makefiles + that comply with the GNU Coding Standards, and + libtool for building shared + libraries on multiple platforms. The normal sequence for + compiling and installing the GStreamer library is thus: + + + ./configure + make + make install + + + + + The standard options provided by GNU + autoconf may be passed to the + configure script. Please see the + autoconf documentation or run + ./configure --help for information about + the standard options. + + + + In addition there are several options to activate or deactivate features. + E.g. passing to configure + will turn the debugging subsystem into a non-functional stub and remove all + macro based invocations from within the library (and anything compiled + against the library afterwards.) + + + If library size matters and one builds in a controlled environment, it is + also possible to totally remove subsystem code. This is intentionally not + offered as a configure option as it causes an ABI break. Code built against + a version of GStreamer without these modifications needs to be recompiled. + + + make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED" + + + + + + GST_REMOVE_DEPRECATED - Omit deprecated functions + from the library. + + + + + GST_REMOVE_DISABLED - Omit stubs for disabled + subsystems from the library. + + + + + + + + +Building GStreamer Applications + + +Applications and libraries can use pkg-config to get all the +needed compiler and linker flags to build against GStreamer. Please note that +GStreamer is split into several libraries itself. +pkg-config --list-all | grep gstreamer will list the +available libraries. + + + + + diff --git a/docs/gst/gst-universe.dot b/docs/gst/gst-universe.dot new file mode 100644 index 0000000..46f6b5c --- /dev/null +++ b/docs/gst/gst-universe.dot @@ -0,0 +1,74 @@ +/* dot -Tpng gst-universe.dot -ogst-universe.png + * + * other layouts: + * circo -Tpng gst-universe.dot -ogst-universe.circo.png + * neato -Tpng gst-universe.dot -ogst-universe.neato.png + * + * todo: + * - add urls to api docs + * - use color + */ +digraph pipeline { + node [style="filled", shape="box", fillcolor="#eeeeee", fontsize="9px", fontname="Bitstream Vera Sans", target="_top"]; + edge [labelfontsize="7px", fontsize="7px", labelfontname="Bitstream Vera Sans", fontname="Bitstream Vera Sans"]; + labelloc=t; + nodesep=0.25; + + /* + fontname="Bitstream Vera Sans"; + fontsize="10px"; + label="GStreamer Universe"; + */ + + /* objects */ + application [color=black, fillcolor="#ffdddd"]; + bin [href="GstBin.html", color=black, fillcolor="#ccccff"]; + bus [href="GstBus.html"]; + buffer [href="gstreamer-GstBuffer.html", color=black, fillcolor="#ddffdd"]; + caps [href="gstreamer-GstCaps.html"]; + clock [href="GstClock.html"]; + element [href="GstElement.html", color=black, fillcolor="#ccccff"]; + element_factory [href="GstElementFactory.html", label="element factory"]; + event [href="gstreamer-GstEvent.html", color=black, fillcolor="#ddffdd"]; + message [href="gstreamer-GstMessage.html", color=black, fillcolor="#ddffdd"]; + pad [href="GstPad.html", color=black, fillcolor="#ccccff"]; + pad_template [href="GstPadTemplate.html", label="pad template"]; + pipeline [href="GstPipeline.html", color=black, fillcolor="#ccccff"]; + plugin [href="GstPlugin.html"]; + plugin_feature [href="GstPluginFeature.html", label="plugin feature"]; + query [href="gstreamer-GstQuery.html", color=black, fillcolor="#ddffdd"]; + registry [href="GstRegistry.html"]; + structure [href="gstreamer-GstStructure.html"]; + + /* relations */ + bin -> element [label="is-a"]; + pipeline -> bin [label="is-a"]; + pipeline -> bus [label="has 1"]; + pipeline -> clock [label="has 1"]; + element -> pad_template [label="has n"]; + element -> pad [label="has n"]; + element -> clock [label="may provide"]; + pad -> caps [label="has n"]; + pad_template -> caps [label="has n"]; + buffer -> caps [label="has n"]; + caps -> structure [label="has n"]; + bin -> element [label="has n"]; + + pad -> pad_template [label="is created from"]; + element -> element_factory [label="is created from"]; + + element -> query [label="answers"]; + element -> event [label="send & receive"]; + element -> buffer [label="send & receive"]; + element -> message [label="send"]; + bus -> message [label="receive"]; + + registry -> plugin [label="has n"]; + plugin -> plugin_feature [label="has n"]; + element_factory -> plugin_feature [label="is-a"]; + + application -> pipeline [label="has"]; + application -> bus [label="listen on"]; + application -> query [label="send"]; + application -> event [label="send"]; +} diff --git a/docs/gst/gst-universe.svg b/docs/gst/gst-universe.svg new file mode 100644 index 0000000..3e8c065 --- /dev/null +++ b/docs/gst/gst-universe.svg @@ -0,0 +1,310 @@ + + + + + + +pipeline + + +application + +application + + +bus + + +bus + + + + +application->bus + + +listen on + + +event + + +event + + + + +application->event + + +send + + +pipeline + + +pipeline + + + + +application->pipeline + + +has + + +query + + +query + + + + +application->query + + +send + + +bin + + +bin + + + + +element + + +element + + + + +bin->element + + +is-a + + +bin->element + + +has n + + +message + + +message + + + + +bus->message + + +receive + + +buffer + + +buffer + + + + +caps + + +caps + + + + +buffer->caps + + +has n + + +structure + + +structure + + + + +caps->structure + + +has n + + +clock + + +clock + + + + +element->buffer + + +send & receive + + +element->clock + + +may provide + + +element_factory + + +element factory + + + + +element->element_factory + + +is created from + + +element->event + + +send & receive + + +element->message + + +send + + +pad + + +pad + + + + +element->pad + + +has n + + +pad_template + + +pad template + + + + +element->pad_template + + +has n + + +element->query + + +answers + + +plugin_feature + + +plugin feature + + + + +element_factory->plugin_feature + + +is-a + + +pad->caps + + +has n + + +pad->pad_template + + +is created from + + +pad_template->caps + + +has n + + +pipeline->bin + + +is-a + + +pipeline->bus + + +has 1 + + +pipeline->clock + + +has 1 + + +plugin + + +plugin + + + + +plugin->plugin_feature + + +has n + + +registry + + +registry + + + + +registry->plugin + + +has n + + + diff --git a/docs/gst/gstreamer-docs.sgml b/docs/gst/gstreamer-docs.sgml new file mode 100644 index 0000000..c2f6511 --- /dev/null +++ b/docs/gst/gstreamer-docs.sgml @@ -0,0 +1,202 @@ + + +%version-entities; + + +]> + + + GStreamer &GST_API_VERSION; Core Reference Manual + + for GStreamer Core &GST_API_VERSION; (&GST_VERSION;) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/. + + + + + + GStreamer Overview + +GStreamer is a streaming media framework. +It uses graphs of elements which operate on data. +The functionality to process media is provided by plug-ins which provide +features like elements, typefinding, and so on. +This allows new functionality to be added simply by installing new plug-ins. + + + +GStreamer is cross-platform and works on most UNIX-like platforms as well as +Windows. It is released under the GNU Library General Public License +(GNU LGPL). + + + + + + + + Relation between gstreamer core objects. + + + + + + + + + GStreamer Core Library + + + libgstreamer-&GST_API_VERSION;.so provides all the core GStreamer services, + including initialization, plugin management and types, + as well as the object hierarchy that defines elements and bins, + along with some more specialized elements. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GStreamer Device Discovery and Device Probing + + + + + + + + GStreamer Core Support + + Theses modules support the gstreamer core and plugin development. + Application developers will rarely need to know about it. + + + + + + + + + + + Object Hierarchy + + + + + API Index + + + + Index of deprecated API + + + + Index of new API in 1.14 + + + + Index of new API in 1.12 + + + + Index of new API in 1.10 + + + + Index of new API in 1.8 + + + + Index of new API in 1.6 + + + + Index of new API in 1.4 + + + + Index of new API in 1.2.3 + + + + Index of new API in 1.2 + + + + Index of new API in 1.0.10 + + + + Index of new API in 1.0.5 + + + + + + diff --git a/docs/gst/gstreamer-overrides.txt b/docs/gst/gstreamer-overrides.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/gst/gstreamer-overrides.txt diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt new file mode 100644 index 0000000..42c7c4c --- /dev/null +++ b/docs/gst/gstreamer-sections.txt @@ -0,0 +1,3975 @@ +# GStreamer API reference sections + +# please add sections in alphabetical order using the following template +# leave two empty lines between sections +#
+# gstxxx +# GstXxx +# typedefs +# macros +# constructor +# methods +# +# +#
+ +gst/gst.h + + +
+gst +Gst +gst_init +gst_init_check +gst_init_get_option_group +gst_is_initialized +gst_deinit +gst_version +gst_version_string +gst_segtrap_is_enabled +gst_segtrap_set_enabled +gst_registry_fork_is_enabled +gst_registry_fork_set_enabled +gst_update_registry +gst_get_main_executable_path + +GST_QUARK +GstQuarkId +GstPluginLoader +GstPluginLoaderFuncs +
+ +
+gstatomicqueue +GstAtomicQueue +GstAtomicQueue +gst_atomic_queue_new + +gst_atomic_queue_ref +gst_atomic_queue_unref + +gst_atomic_queue_push +gst_atomic_queue_peek +gst_atomic_queue_pop + +gst_atomic_queue_length + + +GST_TYPE_ATOMIC_QUEUE +gst_atomic_queue_get_type +
+ +
+gstbin +GstBin +GstBin +GstBinClass + +gst_bin_new +gst_bin_add +gst_bin_remove + +gst_bin_get_by_name +gst_bin_get_by_name_recurse_up +gst_bin_get_by_interface + +gst_bin_iterate_elements +gst_bin_iterate_recurse +gst_bin_iterate_sinks +gst_bin_iterate_sorted +gst_bin_iterate_sources +gst_bin_iterate_all_by_interface + +gst_bin_recalculate_latency + +gst_bin_get_suppressed_flags +gst_bin_set_suppressed_flags + + +gst_bin_add_many +gst_bin_remove_many +gst_bin_find_unlinked_pad +gst_bin_sync_children_states + + +GstBinFlags + +GST_BIN_IS_NO_RESYNC + +GST_BIN_CHILDREN +GST_BIN_CHILDREN_COOKIE +GST_BIN_NUMCHILDREN + + +GST_BIN +GST_IS_BIN +GST_TYPE_BIN +GST_BIN_CLASS +GST_IS_BIN_CLASS +GST_BIN_GET_CLASS +GST_TYPE_BIN_FLAGS +GST_BIN_CAST + +gst_bin_get_type +gst_bin_flags_get_type +GstBinPrivate +
+ + +
+gstbus +GstBus +GstBus +GstBusFlags +GstBusSyncReply +GstBusFunc +GstBusSyncHandler +gst_bus_new +gst_bus_post +gst_bus_have_pending +gst_bus_peek +gst_bus_pop +gst_bus_pop_filtered +gst_bus_timed_pop +gst_bus_timed_pop_filtered +gst_bus_set_flushing +gst_bus_set_sync_handler +gst_bus_sync_signal_handler +gst_bus_get_pollfd +gst_bus_create_watch +gst_bus_add_watch_full +gst_bus_add_watch +gst_bus_remove_watch +gst_bus_disable_sync_message_emission +gst_bus_enable_sync_message_emission +gst_bus_async_signal_func +gst_bus_add_signal_watch +gst_bus_add_signal_watch_full +gst_bus_remove_signal_watch +gst_bus_poll + +GstBusClass +GST_BUS +GST_IS_BUS +GST_TYPE_BUS +GST_BUS_CLASS +GST_IS_BUS_CLASS +GST_BUS_GET_CLASS +GST_TYPE_BUS_FLAGS +GST_TYPE_BUS_SYNC_REPLY +GST_BUS_CAST + +gst_bus_get_type +gst_bus_flags_get_type +gst_bus_sync_reply_get_type +GstBusPrivate +
+ + +
+gstbuffer +GstBuffer +GstBuffer +GstBufferFlags +GST_BUFFER_FLAGS +GST_BUFFER_FLAG_IS_SET +GST_BUFFER_FLAG_SET +GST_BUFFER_FLAG_UNSET + +GST_BUFFER_PTS +GST_BUFFER_DTS +GST_BUFFER_DTS_OR_PTS +GST_BUFFER_DURATION +GST_BUFFER_OFFSET +GST_BUFFER_OFFSET_END +GST_BUFFER_OFFSET_NONE +GST_BUFFER_DURATION_IS_VALID +GST_BUFFER_PTS_IS_VALID +GST_BUFFER_DTS_IS_VALID +GST_BUFFER_OFFSET_IS_VALID +GST_BUFFER_OFFSET_END_IS_VALID +GST_BUFFER_IS_DISCONT + +gst_buffer_new +gst_buffer_new_allocate +gst_buffer_new_wrapped +gst_buffer_new_wrapped_full + +gst_buffer_ref +gst_buffer_unref + +gst_buffer_get_sizes +gst_buffer_get_size +gst_buffer_get_sizes_range +gst_buffer_resize_range +gst_buffer_resize +gst_buffer_set_size +gst_buffer_get_max_memory + +gst_buffer_peek_memory + +gst_buffer_n_memory +gst_buffer_insert_memory +gst_buffer_replace_memory_range +gst_buffer_get_memory_range +gst_buffer_remove_memory_range +gst_buffer_find_memory + +gst_buffer_prepend_memory +gst_buffer_append_memory +gst_buffer_replace_memory +gst_buffer_replace_all_memory +gst_buffer_get_memory +gst_buffer_get_all_memory +gst_buffer_remove_memory +gst_buffer_remove_all_memory + +gst_buffer_is_all_memory_writable +gst_buffer_is_memory_range_writable + +gst_buffer_map +gst_buffer_map_range +gst_buffer_unmap + +gst_buffer_memcmp +gst_buffer_extract +gst_buffer_extract_dup +gst_buffer_fill +gst_buffer_memset + +GstBufferCopyFlags +GST_BUFFER_COPY_METADATA +GST_BUFFER_COPY_ALL +gst_buffer_copy +gst_buffer_copy_into +gst_buffer_copy_region +gst_buffer_copy_deep + +gst_buffer_is_writable +gst_buffer_make_writable +gst_buffer_replace + +gst_buffer_append +gst_buffer_append_region + +gst_buffer_get_meta +gst_buffer_get_n_meta +gst_buffer_add_meta +gst_buffer_remove_meta +gst_buffer_iterate_meta +gst_buffer_iterate_meta_filtered +GstBufferForeachMetaFunc +gst_buffer_foreach_meta + +GstParentBufferMeta +gst_buffer_add_parent_buffer_meta +gst_buffer_get_parent_buffer_meta + +GstReferenceTimestampMeta +gst_buffer_add_reference_timestamp_meta +gst_buffer_get_reference_timestamp_meta + +gst_buffer_get_flags +gst_buffer_set_flags +gst_buffer_unset_flags +gst_buffer_has_flags + + +GstBufferClass +GST_BUFFER +GST_IS_BUFFER +GST_TYPE_BUFFER +GST_TYPE_BUFFER_FLAGS +GST_TYPE_BUFFER_COPY_FLAGS +GST_BUFFER_CAST +GST_PARENT_BUFFER_META_INFO +GST_PARENT_BUFFER_META_API_TYPE +GST_TYPE_PARENT_BUFFER_META_API_TYPE +gst_parent_buffer_meta_get_info +GST_REFERENCE_TIMESTAMP_META_INFO +GST_REFERENCE_TIMESTAMP_META_API_TYPE +gst_reference_timestamp_meta_get_info + +gst_buffer_get_type +gst_buffer_flags_get_type +gst_buffer_copy_flags_get_type +gst_parent_buffer_meta_api_get_type +gst_reference_timestamp_meta_api_get_type +GST_BUFFER_TIMESTAMP +GST_BUFFER_TIMESTAMP_IS_VALID +
+ +
+gstmeta +GstMeta +GstMeta +GstMetaFlags +GST_META_FLAGS +GST_META_FLAG_IS_SET +GST_META_FLAG_SET +GST_META_FLAG_UNSET +GstMetaInfo +GstMetaInitFunction +GstMetaFreeFunction +GstMetaTransformFunction +GstMetaTransformCopy +GST_META_TRANSFORM_IS_COPY +gst_meta_api_type_register +gst_meta_api_type_has_tag +gst_meta_api_type_get_tags +GST_META_TAG_MEMORY +GST_META_TAG_MEMORY_STR +gst_meta_register +gst_meta_get_info + +GST_META_CAST + +GST_TYPE_META_FLAGS +gst_meta_flags_get_type +
+ + +
+gstbufferpool +GstBufferPool +GstBufferPool +GstBufferPoolClass +GST_BUFFER_POOL_IS_FLUSHING +gst_buffer_pool_new + +gst_buffer_pool_config_get_params +gst_buffer_pool_config_set_params +gst_buffer_pool_config_validate_params +gst_buffer_pool_config_get_allocator +gst_buffer_pool_config_set_allocator + +gst_buffer_pool_config_n_options +gst_buffer_pool_config_add_option +gst_buffer_pool_config_get_option +gst_buffer_pool_config_has_option + +gst_buffer_pool_get_options +gst_buffer_pool_has_option + +gst_buffer_pool_get_config +gst_buffer_pool_set_config + +gst_buffer_pool_set_active +gst_buffer_pool_is_active +gst_buffer_pool_set_flushing + +GstBufferPoolAcquireFlags +GstBufferPoolAcquireParams +gst_buffer_pool_acquire_buffer +gst_buffer_pool_release_buffer + +GST_BUFFER_POOL_CLASS +GST_BUFFER_POOL_CAST +GST_BUFFER_POOL +GST_IS_BUFFER_POOL +GST_TYPE_BUFFER_POOL +GST_TYPE_BUFFER_POOL_ACQUIRE_FLAGS +gst_buffer_pool_acquire_flags_get_type +GST_IS_BUFFER_POOL_CLASS +GST_BUFFER_POOL_GET_CLASS + +gst_buffer_pool_get_type +GstBufferPoolPrivate +
+ +
+gstbufferlist +GstBufferList +GstBufferList + +gst_buffer_list_new +gst_buffer_list_new_sized +gst_buffer_list_length +gst_buffer_list_add +gst_buffer_list_insert +gst_buffer_list_remove + +gst_buffer_list_ref +gst_buffer_list_unref +gst_buffer_list_copy +gst_buffer_list_copy_deep +gst_buffer_list_is_writable +gst_buffer_list_make_writable + +GstBufferListFunc +gst_buffer_list_foreach +gst_buffer_list_get +gst_buffer_list_get_writable + +gst_buffer_list_calculate_size + + +GST_BUFFER_LIST +GST_IS_BUFFER_LIST +GST_TYPE_BUFFER_LIST +GST_BUFFER_LIST_CAST + +gst_buffer_list_get_type +
+ +
+gstcaps +GstCaps +GstCaps +GstStaticCaps +GstCapsIntersectMode + +GstCapsFlags +GST_CAPS_ANY +GST_CAPS_NONE +GST_CAPS_REFCOUNT +GST_CAPS_REFCOUNT_VALUE +GST_STATIC_CAPS_ANY +GST_STATIC_CAPS_NONE +GST_CAPS_IS_SIMPLE +GST_STATIC_CAPS +GST_CAPS_FLAGS +GST_CAPS_FLAG_IS_SET +GST_CAPS_FLAG_SET +GST_CAPS_FLAG_UNSET + +GstCapsForeachFunc +GstCapsMapFunc +GstCapsFilterMapFunc + +gst_caps_new_empty +gst_caps_new_empty_simple +gst_caps_new_any +gst_caps_new_simple +gst_caps_new_full +gst_caps_new_full_valist +gst_caps_is_writable +gst_caps_copy +gst_caps_copy_nth +gst_static_caps_get +gst_static_caps_cleanup +gst_caps_append +gst_caps_merge +gst_caps_append_structure +gst_caps_append_structure_full +gst_caps_remove_structure +gst_caps_steal_structure +gst_caps_merge_structure +gst_caps_merge_structure_full +gst_caps_get_size +gst_caps_get_structure +gst_caps_get_features +gst_caps_set_features +gst_caps_set_value +gst_caps_set_simple +gst_caps_set_simple_valist +gst_caps_foreach +gst_caps_map_in_place +gst_caps_filter_and_map_in_place +gst_caps_is_any +gst_caps_is_empty +gst_caps_is_fixed +gst_caps_is_equal +gst_caps_is_equal_fixed +gst_caps_is_strictly_equal +gst_caps_is_always_compatible +gst_caps_is_subset +gst_caps_is_subset_structure +gst_caps_is_subset_structure_full +gst_caps_can_intersect +gst_caps_intersect +gst_caps_intersect_full +gst_caps_normalize +gst_caps_simplify +gst_caps_replace +gst_caps_take +gst_caps_to_string +gst_caps_from_string +gst_caps_subtract +gst_caps_make_writable +gst_caps_truncate +gst_caps_fixate +gst_caps_ref +gst_caps_unref + +GST_CAPS +GST_IS_CAPS +GST_TYPE_CAPS +GST_TYPE_CAPS_FLAGS +GST_TYPE_CAPS_INTERSECT_MODE +GST_CAPS_CAST + +gst_caps_flags_get_type +gst_caps_get_type +gst_caps_intersect_mode_get_type +
+ +
+gstcapsfeatures +GstCapsFeatures +GstCapsFeatures +GST_CAPS_FEATURES_ANY +GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY +GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY +gst_caps_features_new +gst_caps_features_new_empty +gst_caps_features_new_any +gst_caps_features_new_id +gst_caps_features_new_id_valist +gst_caps_features_new_valist + +gst_caps_features_copy +gst_caps_features_free + +gst_caps_features_from_string +gst_caps_features_to_string + +gst_caps_features_set_parent_refcount + +gst_caps_features_is_equal +gst_caps_features_is_any + +gst_caps_features_contains +gst_caps_features_contains_id + +gst_caps_features_get_size + +gst_caps_features_get_nth +gst_caps_features_get_nth_id + +gst_caps_features_add +gst_caps_features_add_id +gst_caps_features_remove +gst_caps_features_remove_id + +GST_CAPS_FEATURES +GST_CAPS_FEATURES_CAST +GST_IS_CAPS_FEATURES +GST_TYPE_CAPS_FEATURES +gst_is_caps_features + +gst_caps_features_get_type +
+ +
+gstsample +GstSample +GstSample +gst_sample_get_buffer +gst_sample_get_buffer_list +gst_sample_get_caps +gst_sample_get_info +gst_sample_get_segment +gst_sample_set_buffer_list +gst_sample_new +gst_sample_ref +gst_sample_unref +gst_sample_copy + +GST_IS_SAMPLE +GST_SAMPLE +GST_TYPE_SAMPLE +gst_sample_get_type +GST_SAMPLE_CAST +
+ +
+gstchildproxy +GstChildProxy +GstChildProxy +GstChildProxyInterface +gst_child_proxy_get_children_count +gst_child_proxy_get_child_by_name +gst_child_proxy_get_child_by_index +gst_child_proxy_lookup +gst_child_proxy_get_property +gst_child_proxy_get_valist +gst_child_proxy_get +gst_child_proxy_set_property +gst_child_proxy_set_valist +gst_child_proxy_set +gst_child_proxy_child_added +gst_child_proxy_child_removed + +GST_CHILD_PROXY +GST_IS_CHILD_PROXY +GST_CHILD_PROXY_GET_INTERFACE +GST_TYPE_CHILD_PROXY + +gst_child_proxy_get_type +
+ + +
+gstclock +GstClock +GstClock +GstClockClass +GstClockTime +GstClockTimeDiff +GstClockID +GST_CLOCK_TIME_NONE +GST_CLOCK_TIME_IS_VALID +GST_CLOCK_STIME_NONE +GST_CLOCK_STIME_IS_VALID +GST_SECOND +GST_MSECOND +GST_USECOND +GST_NSECOND +GST_TIME_AS_SECONDS +GST_TIME_AS_MSECONDS +GST_TIME_AS_USECONDS +GST_TIME_AS_NSECONDS +GST_CLOCK_DIFF +GST_TIMEVAL_TO_TIME +GST_TIME_TO_TIMEVAL +GST_TIMESPEC_TO_TIME +GST_TIME_TO_TIMESPEC +GstClockEntry +GstClockCallback +GstClockEntryType +GST_CLOCK_ENTRY +GST_CLOCK_ENTRY_CLOCK +GST_CLOCK_ENTRY_TYPE +GST_CLOCK_ENTRY_TIME +GST_CLOCK_ENTRY_INTERVAL +GST_CLOCK_ENTRY_STATUS +GstClockReturn +GstClockFlags +GST_CLOCK_FLAGS +gst_clock_add_observation +gst_clock_add_observation_unapplied +gst_clock_set_master +gst_clock_get_master +gst_clock_set_resolution +gst_clock_get_resolution +gst_clock_get_time +gst_clock_new_single_shot_id +gst_clock_new_periodic_id +gst_clock_single_shot_id_reinit +gst_clock_periodic_id_reinit +gst_clock_get_internal_time +gst_clock_adjust_unlocked +gst_clock_unadjust_unlocked +gst_clock_adjust_with_calibration +gst_clock_unadjust_with_calibration +gst_clock_get_calibration +gst_clock_set_calibration +gst_clock_get_timeout +gst_clock_set_timeout +gst_clock_wait_for_sync +gst_clock_is_synced +gst_clock_set_synced +gst_clock_id_get_time +gst_clock_id_wait +gst_clock_id_wait_async +gst_clock_id_unschedule +gst_clock_id_compare_func +gst_clock_id_ref +gst_clock_id_unref + +GST_CLOCK +GST_IS_CLOCK +GST_TYPE_CLOCK +GST_CLOCK_CLASS +GST_IS_CLOCK_CLASS +GST_CLOCK_GET_CLASS +GST_CLOCK_CAST +GST_TYPE_CLOCK_ENTRY_TYPE +GST_TYPE_CLOCK_FLAGS +GST_TYPE_CLOCK_RETURN +GST_TYPE_CLOCK_TIME + +GstClockPrivate +GST_CLOCK_SLAVE_LOCK +GST_CLOCK_SLAVE_UNLOCK +gst_clock_get_type +gst_clock_entry_type_get_type +gst_clock_flags_get_type +gst_clock_return_get_type +
+ + +
+gstcompat +GstCompat + +gst_element_class_set_details_simple +gst_element_factory_get_author +gst_element_factory_get_description +gst_element_factory_get_documentation_uri +gst_element_factory_get_icon_name +gst_element_factory_get_klass +gst_element_factory_get_longname +gst_pad_get_caps_reffed +gst_pad_peer_get_caps_reffed +gst_pad_set_caps +gst_buffer_new_and_alloc +GST_BUFFER_TIMESTAMP +GST_BUFFER_TIMESTAMP_IS_VALID +GST_MESSAGE_DURATION +gst_message_new_duration +gst_message_parse_duration +gst_adapter_prev_timestamp + +
+ + +
+gstconfig +GstConfig +GST_DISABLE_GST_DEBUG +GST_DISABLE_PARSE +GST_DISABLE_REGISTRY +GST_DISABLE_PLUGIN + +GST_HAVE_GLIB_2_8 +GST_EXPORT +GST_PLUGIN_EXPORT +GST_PADDING +GST_PADDING_LARGE +GST_PADDING_INIT +
+ +
+gstcontext +GstContext +GstContext +gst_context_new +gst_context_ref +gst_context_unref +gst_context_copy +gst_context_get_context_type +gst_context_has_context_type +gst_context_is_persistent +gst_context_get_structure +gst_context_writable_structure +gst_context_make_writable +gst_context_is_writable +gst_context_replace + +GST_CONTEXT +GST_CONTEXT_CAST +GST_IS_CONTEXT +GST_TYPE_CONTEXT + +gst_context_get_type +
+ +
+gstcontrolbinding +GstControlBinding +GstControlBinding +GstControlBindingClass +gst_control_binding_sync_values +gst_control_binding_get_value +gst_control_binding_get_value_array +gst_control_binding_get_g_value_array +gst_control_binding_set_disabled +gst_control_binding_is_disabled + +GST_CONTROL_BINDING +GST_IS_CONTROL_BINDING +GST_CONTROL_BINDING_CLASS +GST_IS_CONTROL_BINDING_CLASS +GST_CONTROL_BINDING_GET_CLASS +GST_TYPE_CONTROL_BINDING +GST_CONTROL_BINDING_PSPEC + +GstControlBindingConvert +GstControlBindingPrivate +gst_control_binding_get_type +
+ +
+gstcontrolsource +GstControlSource +GstValueArray +GstControlSource +GstControlSourceClass +GstControlSourceGetValue +GstControlSourceGetValueArray +GstTimedValue +gst_control_source_get_value +gst_control_source_get_value_array + +GST_CONTROL_SOURCE +GST_IS_CONTROL_SOURCE +GST_CONTROL_SOURCE_CLASS +GST_IS_CONTROL_SOURCE_CLASS +GST_CONTROL_SOURCE_GET_CLASS +GST_TYPE_CONTROL_SOURCE + +gst_control_source_get_type +
+ +
+gstdynamictypefactory +GstDynamicTypeFactory +GstDynamicTypeFactory +gst_dynamic_type_factory_load +gst_dynamic_type_register + +GstDynamicTypeFactoryClass +GST_TYPE_DYNAMIC_TYPE_FACTORY +GST_DYNAMIC_TYPE_FACTORY +GST_DYNAMIC_TYPE_CLASS +GST_IS_DYNAMIC_TYPE_FACTORY +GST_IS_DYNAMIC_TYPE_FACTORY_CLASS +GST_DYNAMIC_TYPE_FACTORY_CAST + +gst_dynamic_type_factory_get_type +
+ +
+gstelement +GstElement +GstElement +GstElementClass +GstElementFlags +GstState +GstStateChange +GstStateChangeReturn + +GST_STATE +GST_STATE_GET_NEXT +GST_STATE_NEXT +GST_STATE_PENDING +GST_STATE_RETURN +GST_STATE_TARGET +GST_STATE_TRANSITION +GST_STATE_TRANSITION_CURRENT +GST_STATE_TRANSITION_NEXT + +GST_STATE_GET_LOCK +GST_STATE_GET_COND + +GST_ELEMENT_NAME +GST_ELEMENT_PARENT +GST_ELEMENT_BUS +GST_ELEMENT_CLOCK +GST_ELEMENT_PADS +GST_ELEMENT_START_TIME +GST_ELEMENT_ERROR +GST_ELEMENT_ERROR_WITH_DETAILS +GST_ELEMENT_FLOW_ERROR +GST_ELEMENT_WARNING +GST_ELEMENT_WARNING_WITH_DETAILS +GST_ELEMENT_INFO +GST_ELEMENT_INFO_WITH_DETAILS +GST_ELEMENT_IS_LOCKED_STATE + + +GST_ELEMENT_METADATA_AUTHOR +GST_ELEMENT_METADATA_DESCRIPTION +GST_ELEMENT_METADATA_DOC_URI +GST_ELEMENT_METADATA_ICON_NAME +GST_ELEMENT_METADATA_KLASS +GST_ELEMENT_METADATA_LONGNAME + + +gst_element_class_add_pad_template +gst_element_class_add_static_pad_template +gst_element_class_add_static_pad_template_with_gtype +gst_element_class_get_pad_template +gst_element_class_get_pad_template_list +gst_element_class_set_metadata +gst_element_class_set_static_metadata +gst_element_class_add_metadata +gst_element_class_add_static_metadata + + +gst_element_add_pad +gst_element_create_all_pads +gst_element_get_compatible_pad +gst_element_get_compatible_pad_template +gst_element_get_request_pad +gst_element_get_static_pad +gst_element_request_pad +gst_element_no_more_pads +gst_element_release_request_pad +gst_element_remove_pad +gst_element_iterate_pads +gst_element_iterate_sink_pads +gst_element_iterate_src_pads +GstElementForeachPadFunc +gst_element_foreach_pad +gst_element_foreach_sink_pad +gst_element_foreach_src_pad + + +gst_element_link +gst_element_unlink +gst_element_link_many +gst_element_unlink_many +gst_element_link_pads +gst_element_link_pads_full +gst_element_unlink_pads +gst_element_link_pads_filtered +gst_element_link_filtered + + +gst_element_class_get_metadata +gst_element_get_metadata +gst_element_set_base_time +gst_element_get_base_time +gst_element_set_start_time +gst_element_get_start_time +gst_element_set_bus +gst_element_get_bus +gst_element_set_context +gst_element_get_context +gst_element_get_context_unlocked +gst_element_get_contexts +gst_element_get_factory +gst_element_set_name +gst_element_get_name +gst_element_set_parent +gst_element_get_parent +gst_element_get_pad_template +gst_element_get_pad_template_list + + +gst_element_set_clock +gst_element_get_clock +gst_element_provide_clock + + +gst_element_set_state +gst_element_get_state +gst_element_set_locked_state +gst_element_is_locked_state +gst_element_abort_state +gst_element_continue_state +gst_element_lost_state +gst_element_state_get_name +gst_element_state_change_return_get_name +gst_element_sync_state_with_parent +gst_element_change_state +gst_state_change_get_name + + +gst_element_message_full +gst_element_message_full_with_details +gst_make_element_message_details +gst_element_post_message + + +gst_element_query +gst_element_query_convert +gst_element_query_position +gst_element_query_duration + + +gst_element_send_event +gst_element_seek_simple +gst_element_seek + + +gst_element_add_property_notify_watch +gst_element_add_property_deep_notify_watch +gst_element_remove_property_notify_watch + + +GstElementCallAsyncFunc +gst_element_call_async + + +GST_ELEMENT +GST_IS_ELEMENT +GST_ELEMENT_CLASS +GST_IS_ELEMENT_CLASS +GST_ELEMENT_GET_CLASS +GST_TYPE_ELEMENT +GST_TYPE_ELEMENT_FLAGS +GST_ELEMENT_CAST +GST_TYPE_STATE +GST_TYPE_STATE_CHANGE +GST_TYPE_STATE_CHANGE_RETURN + +GST_STATE_LOCK +GST_STATE_TRYLOCK +GST_STATE_UNLOCK +GST_STATE_UNLOCK_FULL +GST_STATE_LOCK_FULL +GST_STATE_WAIT +GST_STATE_WAIT_UNTIL +GST_STATE_SIGNAL +GST_STATE_BROADCAST + +GST_ELEMENT_MESSAGE_MAKE_DETAILS + +gst_element_get_type +gst_element_flags_get_type +gst_state_get_type +gst_state_change_get_type +gst_state_change_return_get_type +
+ + +
+gstelementfactory +GstElementFactory +GstElementFactory +gst_element_register +gst_element_factory_find +gst_element_factory_get_element_type +gst_element_factory_get_metadata +gst_element_factory_get_metadata_keys +gst_element_factory_get_num_pad_templates +gst_element_factory_get_uri_type +gst_element_factory_get_uri_protocols +gst_element_factory_has_interface +gst_element_factory_create +gst_element_factory_make +gst_element_factory_can_sink_all_caps +gst_element_factory_can_src_all_caps +gst_element_factory_can_sink_any_caps +gst_element_factory_can_src_any_caps +gst_element_factory_get_static_pad_templates +GstElementFactoryListType +GST_ELEMENT_FACTORY_TYPE_ANY +GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS +GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER +GST_ELEMENT_FACTORY_TYPE_DECODABLE +GST_ELEMENT_FACTORY_TYPE_DECODER +GST_ELEMENT_FACTORY_TYPE_DECRYPTOR +GST_ELEMENT_FACTORY_TYPE_DEMUXER +GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER +GST_ELEMENT_FACTORY_TYPE_ENCODER +GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR +GST_ELEMENT_FACTORY_TYPE_FORMATTER +GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS +GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO +GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE +GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA +GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE +GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO +GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY +GST_ELEMENT_FACTORY_TYPE_MUXER +GST_ELEMENT_FACTORY_TYPE_PARSER +GST_ELEMENT_FACTORY_TYPE_PAYLOADER +GST_ELEMENT_FACTORY_TYPE_SINK +GST_ELEMENT_FACTORY_TYPE_SRC +GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER +gst_element_factory_list_filter +gst_element_factory_list_get_elements +gst_element_factory_list_is_type + +GstElementFactoryClass +GST_ELEMENT_FACTORY +GST_ELEMENT_FACTORY_CAST +GST_IS_ELEMENT_FACTORY +GST_ELEMENT_FACTORY_CLASS +GST_IS_ELEMENT_FACTORY_CLASS +GST_TYPE_ELEMENT_FACTORY + +gst_element_factory_get_type +GST_ELEMENT_FACTORY_KLASS_DECODER +GST_ELEMENT_FACTORY_KLASS_DECRYPTOR +GST_ELEMENT_FACTORY_KLASS_DEMUXER +GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER +GST_ELEMENT_FACTORY_KLASS_ENCODER +GST_ELEMENT_FACTORY_KLASS_ENCRYPTOR +GST_ELEMENT_FACTORY_KLASS_FORMATTER +GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO +GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE +GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA +GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE +GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO +GST_ELEMENT_FACTORY_KLASS_MUXER +GST_ELEMENT_FACTORY_KLASS_PARSER +GST_ELEMENT_FACTORY_KLASS_PAYLOADER +GST_ELEMENT_FACTORY_KLASS_SINK +GST_ELEMENT_FACTORY_KLASS_SRC +
+ + +
+gsterror +GstGError +GstCoreError +GstLibraryError +GstResourceError +GstStreamError +GST_CORE_ERROR +GST_LIBRARY_ERROR +GST_RESOURCE_ERROR +GST_STREAM_ERROR +GST_ERROR_SYSTEM +gst_error_get_message + +GST_TYPE_CORE_ERROR +GST_TYPE_LIBRARY_ERROR +GST_TYPE_RESOURCE_ERROR +GST_TYPE_STREAM_ERROR + +gst_core_error_get_type +gst_library_error_get_type +gst_resource_error_get_type +gst_stream_error_get_type +gst_core_error_quark +gst_library_error_quark +gst_resource_error_quark +gst_stream_error_quark +
+ + +
+gstevent +GstEvent +GstEvent + +GstEventTypeFlags +GST_EVENT_TYPE_BOTH +GST_EVENT_MAKE_TYPE + +GstEventType + +GST_EVENT_TYPE +GST_EVENT_TYPE_NAME +GST_EVENT_TIMESTAMP +GST_EVENT_SEQNUM + +GST_EVENT_IS_UPSTREAM +GST_EVENT_IS_DOWNSTREAM +GST_EVENT_IS_SERIALIZED +GST_EVENT_IS_STICKY + +gst_event_type_get_flags +gst_event_type_get_name +gst_event_type_to_quark + +gst_event_ref +gst_event_unref +gst_event_replace +gst_event_copy +gst_event_steal +gst_event_take + +gst_event_is_writable +gst_event_make_writable +gst_event_writable_structure + +gst_event_new_custom +gst_event_get_structure +gst_event_has_name + +gst_event_get_seqnum +gst_event_set_seqnum + +gst_event_get_running_time_offset +gst_event_set_running_time_offset + +gst_event_new_flush_start +gst_event_new_flush_stop +gst_event_parse_flush_stop + +gst_event_new_eos + +gst_event_new_gap +gst_event_parse_gap + +gst_event_new_stream_start +gst_event_parse_stream_start +GstStreamFlags +gst_event_set_stream_flags +gst_event_parse_stream_flags +gst_event_set_group_id +gst_event_parse_group_id + +gst_event_set_stream +gst_event_parse_stream + +gst_event_new_segment +gst_event_parse_segment +gst_event_copy_segment + +gst_event_new_tag +gst_event_parse_tag + +gst_event_new_buffer_size +gst_event_parse_buffer_size + +GstQOSType +gst_event_new_qos +gst_event_parse_qos + +GstSeekType +GstSeekFlags +gst_event_new_seek +gst_event_parse_seek + +gst_event_new_navigation + +gst_event_new_latency +gst_event_parse_latency + +gst_event_new_step +gst_event_parse_step + +gst_event_new_sink_message +gst_event_parse_sink_message + +gst_event_new_reconfigure + +gst_event_new_caps +gst_event_parse_caps + +gst_event_new_toc +gst_event_parse_toc + +gst_event_new_toc_select +gst_event_parse_toc_select + +gst_event_new_segment_done +gst_event_parse_segment_done + +gst_event_new_protection +gst_event_parse_protection + +gst_event_new_select_streams +gst_event_parse_select_streams + +gst_event_new_stream_collection +gst_event_parse_stream_collection + +gst_event_new_stream_group_done +gst_event_parse_stream_group_done + +GstEventClass +GST_EVENT +GST_EVENT_CAST +GST_IS_EVENT +GST_IS_EVENT_CLASS +GST_EVENT_CLASS +GST_EVENT_GET_CLASS +GST_TYPE_EVENT +GST_TYPE_EVENT_TYPE +GST_TYPE_SEEK_TYPE +GST_TYPE_SEEK_FLAGS +GST_TYPE_QOS_TYPE +GST_TYPE_EVENT_TYPE_FLAGS +GST_TYPE_STREAM_FLAGS + +GST_EVENT_TYPE_SHIFT +GST_EVENT_MAX_STICKY +GST_EVENT_NUM_SHIFT +GST_EVENT_STICKY_IDX +GST_EVENT_STICKY_IDX_TYPE +GST_EVENT_STICKY_SHIFT +FLAG +gst_event_get_type +gst_event_type_get_type +gst_seek_type_get_type +gst_seek_flags_get_type +gst_qos_type_get_type +gst_event_type_flags_get_type +gst_stream_flags_get_type +
+ +
+gstformat +GstFormat +GstFormat +GST_FORMAT_PERCENT_MAX +GST_FORMAT_PERCENT_SCALE +GstFormatDefinition + +gst_format_get_name +gst_format_to_quark +gst_format_register +gst_format_get_by_nick +gst_formats_contains +gst_format_get_details +gst_format_iterate_definitions + +GST_TYPE_FORMAT + +gst_format_get_type +
+ + +
+gstghostpad +GstGhostPad +GstProxyPad +GstGhostPad + +gst_ghost_pad_new +gst_ghost_pad_new_no_target +gst_ghost_pad_new_from_template +gst_ghost_pad_new_no_target_from_template + +gst_ghost_pad_set_target +gst_ghost_pad_get_target + +gst_ghost_pad_construct + +gst_ghost_pad_activate_mode_default + +gst_ghost_pad_internal_activate_mode_default + +gst_proxy_pad_get_internal + +gst_proxy_pad_iterate_internal_links_default +gst_proxy_pad_chain_default +gst_proxy_pad_chain_list_default +gst_proxy_pad_getrange_default + +GstGhostPadClass +GST_GHOST_PAD +GST_IS_GHOST_PAD +GST_GHOST_PAD_CLASS +GST_IS_GHOST_PAD_CLASS +GST_TYPE_GHOST_PAD +GST_GHOST_PAD_CAST + +GST_IS_PROXY_PAD +GST_IS_PROXY_PAD_CLASS +GST_PROXY_PAD +GST_PROXY_PAD_CLASS +GST_TYPE_PROXY_PAD +GstGhostPadPrivate +GstProxyPadClass +GstProxyPadPrivate +gst_proxy_pad_get_type +gst_ghost_pad_get_type +
+ + +
+gstinfo +GstInfo +GstDebugLevel +GST_LEVEL_DEFAULT +GST_LEVEL_MAX +GstDebugColorFlags +GstDebugColorMode +GstDebugCategory +GstDebugGraphDetails +GST_STR_NULL +GST_DEBUG_PAD_NAME +GST_FUNCTION +GstLogFunction +GstStackTraceFlags +gst_debug_log +gst_debug_log_valist +gst_debug_message_get +gst_debug_log_default +gst_debug_level_get_name +gst_debug_add_log_function +gst_debug_remove_log_function +gst_debug_remove_log_function_by_data +gst_debug_add_ring_buffer_logger +gst_debug_remove_ring_buffer_logger +gst_debug_ring_buffer_logger_get_logs +gst_debug_set_active +gst_debug_is_active +gst_debug_set_colored +gst_debug_set_color_mode +gst_debug_set_color_mode_from_string +gst_debug_is_colored +gst_debug_get_color_mode +gst_debug_set_default_threshold +gst_debug_set_threshold_from_string +gst_debug_get_default_threshold +gst_debug_set_threshold_for_name +gst_debug_unset_threshold_for_name +GST_DEBUG_CATEGORY +GST_DEBUG_CATEGORY_EXTERN +GST_DEBUG_CATEGORY_STATIC +GST_DEBUG_CATEGORY_INIT +GST_DEBUG_CATEGORY_GET +gst_debug_category_free +gst_debug_category_set_threshold +gst_debug_category_reset_threshold +gst_debug_category_get_threshold +gst_debug_category_get_name +gst_debug_category_get_color +gst_debug_category_get_description +gst_debug_get_all_categories +gst_debug_construct_term_color +gst_debug_construct_win_color +GST_CAT_LEVEL_LOG +GST_CAT_ERROR_OBJECT +GST_CAT_WARNING_OBJECT +GST_CAT_INFO_OBJECT +GST_CAT_DEBUG_OBJECT +GST_CAT_LOG_OBJECT +GST_CAT_FIXME_OBJECT +GST_CAT_TRACE_OBJECT +GST_CAT_MEMDUMP_OBJECT +GST_CAT_DEFAULT +GST_CAT_ERROR +GST_CAT_WARNING +GST_CAT_INFO +GST_CAT_DEBUG +GST_CAT_LOG +GST_CAT_FIXME +GST_CAT_TRACE +GST_CAT_MEMDUMP +GST_ERROR_OBJECT +GST_WARNING_OBJECT +GST_INFO_OBJECT +GST_DEBUG_OBJECT +GST_LOG_OBJECT +GST_FIXME_OBJECT +GST_TRACE_OBJECT +GST_MEMDUMP_OBJECT +GST_ERROR +GST_WARNING +GST_INFO +GST_DEBUG +GST_LOG +GST_FIXME +GST_TRACE +GST_MEMDUMP +GST_DEBUG_REGISTER_FUNCPTR +GST_DEBUG_FUNCPTR +GST_DEBUG_FUNCPTR_NAME +GST_DEBUG_BIN_TO_DOT_FILE +GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS +gst_debug_print_stack_trace +gst_debug_get_stack_trace +GST_TIME_FORMAT +GST_TIME_ARGS +GST_STIME_FORMAT +GST_STIME_ARGS +GST_PTR_FORMAT +GST_SEGMENT_FORMAT +gst_debug_bin_to_dot_data +gst_debug_bin_to_dot_file +gst_debug_bin_to_dot_file_with_ts +gst_info_vasprintf +gst_info_strdup_vprintf +gst_info_strdup_printf +gst_print +gst_println +gst_printerr +gst_printerrln + +GST_TYPE_DEBUG_COLOR_FLAGS +GST_TYPE_DEBUG_COLOR_MODE +GST_TYPE_DEBUG_LEVEL +GST_TYPE_DEBUG_GRAPH_DETAILS +GST_TYPE_STACK_TRACE_FLAGS + +GST_DEBUG_FG_MASK +GST_DEBUG_BG_MASK +GST_DEBUG_FORMAT_MASK +GstDebugFuncPtr +GstDebugMessage +gst_debug_color_flags_get_type +gst_debug_color_mode_get_type +gst_debug_level_get_type +gst_debug_graph_details_get_type +GST_CAT_LEVEL_LOG_valist +gst_stack_trace_flags_get_type +
+ +
+gstiterator +GstIterator +GstIterator + +GstIteratorItem +GstIteratorResult + +GstIteratorCopyFunction +GstIteratorNextFunction +GstIteratorItemFunction +GstIteratorResyncFunction +GstIteratorFreeFunction +GstIteratorForeachFunction +GstIteratorFoldFunction + +GST_ITERATOR +GST_ITERATOR_LOCK +GST_ITERATOR_COOKIE +GST_ITERATOR_ORIG_COOKIE + +gst_iterator_new +gst_iterator_new_list +gst_iterator_new_single + +gst_iterator_copy +gst_iterator_free + +gst_iterator_next +gst_iterator_resync +gst_iterator_push +gst_iterator_filter +gst_iterator_fold +gst_iterator_foreach +gst_iterator_find_custom + + +GST_TYPE_ITERATOR +GST_TYPE_ITERATOR_ITEM +GST_TYPE_ITERATOR_RESULT + +gst_iterator_get_type +gst_iterator_item_get_type +gst_iterator_result_get_type +
+ +
+gstallocator +GstAllocator +gst_memory_alignment + +GstAllocator +GstAllocatorClass +GstAllocatorFlags +GstAllocationParams + +GST_ALLOCATOR_SYSMEM +gst_allocator_find +gst_allocator_register +gst_allocator_set_default + +gst_allocation_params_init +gst_allocation_params_copy +gst_allocation_params_free + +gst_allocator_alloc +gst_allocator_free + +gst_memory_new_wrapped + + +GST_ALLOCATOR +GST_ALLOCATOR_CAST +GST_ALLOCATOR_CLASS +GST_ALLOCATOR_GET_CLASS +GST_IS_ALLOCATOR +GST_IS_ALLOCATOR_CLASS + +GST_TYPE_ALLOCATOR_FLAGS +GstAllocatorPrivate +GST_TYPE_ALLOCATION_PARAMS +gst_allocation_params_get_type +GST_TYPE_ALLOCATOR +gst_allocator_get_type +gst_allocator_flags_get_type +
+ +
+gstmemory +GstMemory + +GstMemoryFlags +GST_MEMORY_FLAGS +GST_MEMORY_FLAG_IS_SET +GST_MEMORY_FLAG_UNSET +GST_MEMORY_IS_READONLY +GST_MEMORY_IS_NO_SHARE +GST_MEMORY_IS_ZERO_PADDED +GST_MEMORY_IS_ZERO_PREFIXED +GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS +GST_MEMORY_IS_NOT_MAPPABLE + +GstMemory + +GstMapFlags +GST_MAP_READWRITE + +GstMapInfo +GST_MAP_INFO_INIT + +GstMemoryMapFunction +GstMemoryMapFullFunction +GstMemoryUnmapFunction +GstMemoryUnmapFullFunction +GstMemoryCopyFunction +GstMemoryShareFunction +GstMemoryIsSpanFunction + +gst_memory_init + +gst_memory_is_type + +gst_memory_ref +gst_memory_unref + +gst_memory_get_sizes +gst_memory_resize + +gst_memory_lock +gst_memory_unlock +gst_memory_is_writable +gst_memory_make_writable + +gst_memory_make_mapped +gst_memory_map +gst_memory_unmap + +gst_memory_copy +gst_memory_share + +gst_memory_is_span + +GST_TYPE_MEMORY +gst_memory_get_type +GST_MEMORY_CAST +GST_TYPE_LOCK_FLAGS +gst_lock_flags_get_type +GST_TYPE_MAP_FLAGS +gst_map_flags_get_type +GST_TYPE_MEMORY_FLAGS +gst_memory_flags_get_type +
+ +
+gstmessage +GstMessage +GstMessage +GstMessageType +GST_MESSAGE_SRC +GST_MESSAGE_SRC_NAME +GST_MESSAGE_TIMESTAMP +GST_MESSAGE_SEQNUM +GST_MESSAGE_TYPE +GST_MESSAGE_TYPE_IS_EXTENDED +GST_MESSAGE_TYPE_NAME +gst_message_type_to_quark +gst_message_type_get_name +gst_message_ref +gst_message_unref +gst_message_copy +gst_message_get_structure +gst_message_writable_structure +gst_message_make_writable +gst_message_get_seqnum +gst_message_set_seqnum +gst_message_has_name +gst_message_is_writable +gst_message_replace + +gst_message_new_eos +gst_message_new_error +gst_message_new_error_with_details +gst_message_parse_error +gst_message_parse_error_details +gst_message_new_warning +gst_message_new_warning_with_details +gst_message_parse_warning +gst_message_parse_warning_details +gst_message_new_info +gst_message_new_info_with_details +gst_message_parse_info +gst_message_parse_info_details +gst_message_new_tag +gst_message_parse_tag +gst_message_new_buffering +gst_message_parse_buffering +gst_message_set_buffering_stats +gst_message_parse_buffering_stats +gst_message_new_state_changed +gst_message_parse_state_changed +gst_message_new_state_dirty +gst_message_new_step_done +gst_message_parse_step_done +gst_message_new_clock_provide +gst_message_parse_clock_provide +gst_message_new_clock_lost +gst_message_parse_clock_lost +gst_message_new_new_clock +gst_message_parse_new_clock +gst_message_new_application +gst_message_new_element +gst_message_new_custom +gst_message_new_segment_start +gst_message_parse_segment_start +gst_message_new_segment_done +gst_message_parse_segment_done +gst_message_new_duration_changed +gst_message_new_latency +gst_message_new_async_start +gst_message_new_async_done +gst_message_parse_async_done +gst_message_new_step_start +gst_message_parse_step_start +gst_message_new_qos +gst_message_set_qos_values +gst_message_set_qos_stats +gst_message_parse_qos +gst_message_parse_qos_values +gst_message_parse_qos_stats +gst_message_new_toc +gst_message_parse_toc +gst_message_new_reset_time +gst_message_parse_reset_time + +gst_message_new_stream_start +gst_message_set_group_id +gst_message_parse_group_id + +gst_message_new_stream_collection +gst_message_parse_stream_collection +GstStructureChangeType +gst_message_new_structure_change +gst_message_parse_structure_change +gst_message_new_request_state +gst_message_parse_request_state + +GstStreamStatusType +gst_message_new_stream_status +gst_message_parse_stream_status +gst_message_set_stream_status_object +gst_message_get_stream_status_object + +GstProgressType +gst_message_new_progress +gst_message_parse_progress + +gst_message_new_need_context +gst_message_parse_context_type +gst_message_new_have_context +gst_message_parse_have_context + +gst_message_new_device_added +gst_message_new_device_removed +gst_message_parse_device_added +gst_message_parse_device_removed + +gst_message_new_property_notify +gst_message_parse_property_notify + +gst_message_new_streams_selected +gst_message_parse_streams_selected +gst_message_streams_selected_add +gst_message_streams_selected_get_size +gst_message_streams_selected_get_stream + +gst_message_new_redirect +gst_message_add_redirect_entry +gst_message_parse_redirect_entry +gst_message_get_num_redirect_entries + + +GstMessageClass +GST_MESSAGE +GST_MESSAGE_CAST +GST_IS_MESSAGE +GST_TYPE_MESSAGE +GST_MESSAGE_CLASS +GST_IS_MESSAGE_CLASS +GST_MESSAGE_GET_CLASS +GST_TYPE_MESSAGE_TYPE +GST_TYPE_STRUCTURE_CHANGE_TYPE +GST_TYPE_STREAM_STATUS_TYPE +GST_TYPE_PROGRESS_TYPE + +gst_message_get_type +gst_message_type_get_type +gst_structure_change_type_get_type +gst_stream_status_type_get_type +gst_progress_type_get_type +GST_MESSAGE_GET_COND +GST_MESSAGE_GET_LOCK +GST_MESSAGE_LOCK +GST_MESSAGE_SIGNAL +GST_MESSAGE_UNLOCK +GST_MESSAGE_WAIT +
+ + +
+gstminiobject +GstMiniObject +GstMiniObject +GstMiniObjectCopyFunction +GstMiniObjectDisposeFunction +GstMiniObjectFreeFunction +GstMiniObjectNotify + +GST_MINI_OBJECT_TYPE + +GstMiniObjectFlags +GST_MINI_OBJECT_FLAGS +GST_MINI_OBJECT_FLAG_IS_SET +GST_MINI_OBJECT_FLAG_SET +GST_MINI_OBJECT_FLAG_UNSET +GST_MINI_OBJECT_IS_LOCKABLE + +GstLockFlags +GST_LOCK_FLAG_READWRITE + +GST_MINI_OBJECT_REFCOUNT +GST_MINI_OBJECT_REFCOUNT_VALUE + +GST_DEFINE_MINI_OBJECT_TYPE +gst_mini_object_init + +gst_mini_object_ref +gst_mini_object_unref + +gst_mini_object_weak_ref +gst_mini_object_weak_unref + +gst_mini_object_lock +gst_mini_object_unlock +gst_mini_object_is_writable +gst_mini_object_make_writable + +gst_mini_object_copy + +gst_mini_object_set_qdata +gst_mini_object_get_qdata +gst_mini_object_steal_qdata + +gst_mini_object_replace +gst_mini_object_take +gst_mini_object_steal + + +GST_MINI_OBJECT +GST_IS_MINI_OBJECT_TYPE +GST_TYPE_MINI_OBJECT_FLAGS +GST_MINI_OBJECT_CAST +GST_MINI_OBJECT_CONST_CAST + + +gst_mini_object_flags_get_type +
+ + +
+gstobject +GstObject +GstObject +GstObjectClass +GstObjectFlags +GST_OBJECT_FLAGS +GST_OBJECT_FLAG_IS_SET +GST_OBJECT_FLAG_SET +GST_OBJECT_FLAG_UNSET +GST_OBJECT_NAME +GST_OBJECT_PARENT +GST_OBJECT_REFCOUNT +GST_OBJECT_REFCOUNT_VALUE +GST_OBJECT_LOCK +GST_OBJECT_TRYLOCK +GST_OBJECT_UNLOCK +GST_OBJECT_GET_LOCK + +gst_object_set_name +gst_object_get_name +gst_object_set_parent +gst_object_get_parent +gst_object_has_as_parent +gst_object_unparent +gst_object_default_deep_notify +gst_object_default_error +gst_object_check_uniqueness +gst_object_has_as_ancestor +gst_object_has_ancestor +gst_object_ref +gst_object_unref +gst_object_ref_sink +gst_object_replace +gst_object_get_path_string + +gst_object_suggest_next_sync +gst_object_sync_values +gst_object_has_active_control_bindings +gst_object_set_control_bindings_disabled +gst_object_set_control_binding_disabled +gst_object_add_control_binding +gst_object_get_control_binding +gst_object_remove_control_binding +gst_object_get_value +gst_object_get_value_array +gst_object_get_g_value_array +gst_object_get_control_rate +gst_object_set_control_rate + + +GST_OBJECT +GST_IS_OBJECT +GST_OBJECT_CLASS +GST_IS_OBJECT_CLASS +GST_OBJECT_GET_CLASS +GST_TYPE_OBJECT +GST_TYPE_OBJECT_FLAGS +GST_OBJECT_CAST +GST_OBJECT_CLASS_CAST + +gst_object_get_type +gst_object_flags_get_type +
+ + +
+gstpad +GstPad +GstPad + +GstPadDirection +GstPadFlags +GstPadLinkReturn +gst_pad_link_get_name +GST_PAD_LINK_FAILED +GST_PAD_LINK_SUCCESSFUL +GstPadLinkCheck +GstFlowReturn +gst_flow_get_name +gst_flow_to_quark +GstPadMode +gst_pad_mode_get_name +gst_pad_store_sticky_event + + +gst_pad_get_name +gst_pad_get_direction +gst_pad_get_parent +gst_pad_get_parent_element +gst_pad_get_pad_template + +gst_pad_link +gst_pad_link_full +gst_pad_link_maybe_ghosting +gst_pad_link_maybe_ghosting_full +gst_pad_unlink +gst_pad_is_linked +gst_pad_can_link + +gst_pad_get_allowed_caps +gst_pad_get_current_caps +gst_pad_get_pad_template_caps + +gst_pad_get_peer +gst_pad_use_fixed_caps +gst_pad_has_current_caps + +gst_pad_get_sticky_event +GstPadStickyEventsForeachFunction +gst_pad_sticky_events_foreach + +gst_pad_is_active +gst_pad_get_last_flow_return + + +GstPadProbeReturn +GstPadProbeType + +GstPadProbeInfo +GST_PAD_PROBE_INFO_TYPE +GST_PAD_PROBE_INFO_ID +GST_PAD_PROBE_INFO_DATA + +GST_PAD_PROBE_INFO_BUFFER +GST_PAD_PROBE_INFO_BUFFER_LIST +GST_PAD_PROBE_INFO_EVENT +GST_PAD_PROBE_INFO_QUERY + +gst_pad_probe_info_get_buffer +gst_pad_probe_info_get_buffer_list +gst_pad_probe_info_get_event +gst_pad_probe_info_get_query + +GST_PAD_PROBE_INFO_OFFSET +GST_PAD_PROBE_INFO_SIZE + +GST_PAD_PROBE_INFO_FLOW_RETURN + +GstPadProbeCallback +gst_pad_add_probe +gst_pad_remove_probe + +gst_pad_is_blocked +gst_pad_is_blocking + + +gst_pad_get_offset +gst_pad_set_offset + + +gst_pad_new +gst_pad_new_from_template +gst_pad_new_from_static_template + +gst_pad_set_chain_function +gst_pad_set_chain_function_full +GstPadChainFunction + +gst_pad_set_chain_list_function +gst_pad_set_chain_list_function_full +GstPadChainListFunction + +gst_pad_get_range +gst_pad_set_getrange_function +gst_pad_set_getrange_function_full +GstPadGetRangeFunction + +gst_pad_set_event_function +gst_pad_set_event_function_full +GstPadEventFunction + +gst_pad_set_event_full_function +gst_pad_set_event_full_function_full +GstPadEventFullFunction + +gst_pad_set_link_function +gst_pad_set_link_function_full +GstPadLinkFunction +gst_pad_set_unlink_function +gst_pad_set_unlink_function_full +GstPadUnlinkFunction + +gst_pad_proxy_query_caps +gst_pad_proxy_query_accept_caps + +gst_pad_set_activate_function +gst_pad_set_activate_function_full +GstPadActivateFunction + +gst_pad_set_activatemode_function +gst_pad_set_activatemode_function_full +GstPadActivateModeFunction + +gst_pad_needs_reconfigure +gst_pad_check_reconfigure +gst_pad_mark_reconfigure + +gst_pad_push +gst_pad_push_event +gst_pad_push_list +gst_pad_pull_range +gst_pad_activate_mode +gst_pad_send_event +gst_pad_event_default + +gst_pad_query +gst_pad_peer_query + +gst_pad_query_default + +gst_pad_query_position +gst_pad_query_duration +gst_pad_query_convert +gst_pad_query_accept_caps +gst_pad_query_caps + +gst_pad_peer_query_position +gst_pad_peer_query_duration +gst_pad_peer_query_convert +gst_pad_peer_query_accept_caps +gst_pad_peer_query_caps + +gst_pad_set_query_function +gst_pad_set_query_function_full +GstPadQueryFunction +gst_pad_set_iterate_internal_links_function +gst_pad_set_iterate_internal_links_function_full +GstPadIterIntLinkFunction +gst_pad_iterate_internal_links +gst_pad_iterate_internal_links_default + +gst_pad_set_element_private +gst_pad_get_element_private + +gst_pad_create_stream_id +gst_pad_create_stream_id_printf +gst_pad_create_stream_id_printf_valist + +gst_pad_get_stream_id +gst_pad_get_stream + +GstPadForwardFunction +gst_pad_forward + +gst_pad_chain +gst_pad_chain_list + +gst_pad_start_task +gst_pad_pause_task +gst_pad_stop_task +gst_pad_get_task_state + +gst_pad_set_active + +GST_PAD_GET_STREAM_LOCK +GST_PAD_STREAM_LOCK +GST_PAD_STREAM_TRYLOCK +GST_PAD_STREAM_UNLOCK + +GST_PAD_NAME +GST_PAD_PARENT +GST_PAD_ELEMENT_PRIVATE +GST_PAD_PAD_TEMPLATE +GST_PAD_DIRECTION +GST_PAD_LAST_FLOW_RETURN + +GST_PAD_TASK +GST_PAD_MODE +GST_PAD_ACTIVATEFUNC +GST_PAD_ACTIVATEMODEFUNC +GST_PAD_CHAINFUNC +GST_PAD_CHAINLISTFUNC +GST_PAD_EVENTFUNC +GST_PAD_EVENTFULLFUNC +GST_PAD_GETRANGEFUNC +GST_PAD_QUERYFUNC +GST_PAD_ITERINTLINKFUNC +GST_PAD_PEER +GST_PAD_LINKFUNC +GST_PAD_UNLINKFUNC + +GST_PAD_IS_LINKED +GST_PAD_IS_SRC +GST_PAD_IS_SINK +GST_PAD_IS_ACTIVE +GST_PAD_IS_BLOCKED +GST_PAD_IS_BLOCKING +GST_PAD_IS_FLUSHING +GST_PAD_SET_FLUSHING +GST_PAD_UNSET_FLUSHING +GST_PAD_IS_EOS +GST_PAD_NEEDS_RECONFIGURE +GST_PAD_HAS_PENDING_EVENTS +GST_PAD_IS_FIXED_CAPS +GST_PAD_NEEDS_PARENT +GST_PAD_IS_PROXY_CAPS +GST_PAD_SET_PROXY_CAPS +GST_PAD_UNSET_PROXY_CAPS +GST_PAD_IS_PROXY_ALLOCATION +GST_PAD_SET_PROXY_ALLOCATION +GST_PAD_UNSET_PROXY_ALLOCATION +GST_PAD_SET_PROXY_SCHEDULING +GST_PAD_UNSET_PROXY_SCHEDULING +GST_PAD_IS_PROXY_SCHEDULING +GST_PAD_IS_ACCEPT_INTERSECT +GST_PAD_SET_ACCEPT_INTERSECT +GST_PAD_UNSET_ACCEPT_INTERSECT +GST_PAD_IS_ACCEPT_TEMPLATE +GST_PAD_SET_ACCEPT_TEMPLATE +GST_PAD_UNSET_ACCEPT_TEMPLATE + + +GstPadClass +GstPadPrivate +GST_PAD +GST_IS_PAD +GST_PAD_CLASS +GST_IS_PAD_CLASS +GST_TYPE_PAD +GST_TYPE_PAD_DIRECTION +GST_TYPE_PAD_FLAGS +GST_TYPE_PAD_LINK_RETURN +GST_TYPE_PAD_LINK_CHECK +GST_TYPE_PAD_PRESENCE +GST_TYPE_PAD_MODE +GST_TYPE_FLOW_RETURN +GST_TYPE_PAD_PROBE_RETURN +GST_TYPE_PAD_PROBE_TYPE + + +gst_pad_get_type +gst_pad_direction_get_type +gst_pad_flags_get_type +gst_pad_link_return_get_type +gst_pad_link_check_get_type +gst_pad_presence_get_type +gst_flow_return_get_type +gst_pad_mode_get_type +gst_pad_probe_return_get_type +gst_pad_probe_type_get_type + +GST_PAD_IS_IN_GETCAPS +GST_PAD_MODE_ACTIVATE +GST_PAD_BLOCK_BROADCAST +GST_PAD_BLOCK_GET_COND +GST_PAD_BLOCK_SIGNAL +GST_PAD_BLOCK_WAIT +GST_PAD_CAST +GST_PAD_DO_BUFFER_SIGNALS +GST_PAD_DO_EVENT_SIGNALS +GST_PAD_IS_IN_SETCAPS + +GST_PAD_QUERYTYPEFUNC +
+ + +
+gstpadtemplate +GstPadTemplate +GstStaticPadTemplate +GST_STATIC_PAD_TEMPLATE +gst_static_pad_template_get +gst_static_pad_template_get_caps +GstPadTemplate +GstPadTemplateFlags +GstPadPresence +GST_PAD_TEMPLATE_NAME_TEMPLATE +GST_PAD_TEMPLATE_DIRECTION +GST_PAD_TEMPLATE_PRESENCE +GST_PAD_TEMPLATE_CAPS +GST_PAD_TEMPLATE_IS_FIXED +GST_PAD_TEMPLATE_GTYPE +gst_pad_template_new +gst_pad_template_new_from_static_pad_template_with_gtype +gst_pad_template_get_caps + + +GstPadTemplateClass +GST_PAD_TEMPLATE +GST_IS_PAD_TEMPLATE +GST_PAD_TEMPLATE_CLASS +GST_IS_PAD_TEMPLATE_CLASS +GST_TYPE_PAD_TEMPLATE +GST_TYPE_PAD_TEMPLATE_FLAGS +GST_TYPE_STATIC_CAPS +GST_TYPE_STATIC_PAD_TEMPLATE + + +gst_pad_template_get_type +gst_pad_template_flags_get_type +gst_pad_template_pad_created +gst_static_pad_template_get_type +gst_static_caps_get_type + +
+ + +
+gstparamspec +GstParamSpec + +GST_PARAM_CONTROLLABLE +GST_PARAM_USER_SHIFT +GST_PARAM_MUTABLE_PAUSED +GST_PARAM_MUTABLE_PLAYING +GST_PARAM_MUTABLE_READY + + +GstParamSpecFraction +gst_param_spec_fraction + + +GstParamSpecArray +gst_param_spec_array + + + +GST_IS_PARAM_SPEC_FRACTION +GST_PARAM_SPEC_FRACTION +GST_TYPE_PARAM_FRACTION +gst_param_spec_fraction_get_type + +GST_IS_PARAM_SPEC_ARRAY_LIST +GST_PARAM_SPEC_ARRAY_LIST +GST_TYPE_PARAM_ARRAY_LIST +gst_param_spec_array_get_type +
+ + +
+gstparse +GstParse +gst_parse_error_quark +GST_PARSE_ERROR +GstParseError +GstParseContext +GstParseFlags +gst_parse_launch +gst_parse_launch_full +gst_parse_launchv +gst_parse_launchv_full +gst_parse_bin_from_description +gst_parse_bin_from_description_full + +gst_parse_context_new +gst_parse_context_copy +gst_parse_context_free +gst_parse_context_get_missing_elements + +GST_TYPE_PARSE_ERROR +GST_TYPE_PARSE_FLAGS +GST_TYPE_PARSE_CONTEXT + +gst_parse_context_get_type +gst_parse_error_get_type +gst_parse_flags_get_type +
+ + +
+gstpipeline +GstPipeline +GstPipeline +GstPipelineFlags + +gst_pipeline_new + +gst_pipeline_get_bus + +gst_pipeline_set_clock +gst_pipeline_get_pipeline_clock +gst_pipeline_get_clock + +gst_pipeline_use_clock +gst_pipeline_auto_clock + +gst_pipeline_set_auto_flush_bus +gst_pipeline_get_auto_flush_bus + +gst_pipeline_set_delay +gst_pipeline_get_delay + +gst_pipeline_set_latency +gst_pipeline_get_latency + + +GstPipelineClass +GST_PIPELINE +GST_IS_PIPELINE +GST_PIPELINE_CLASS +GST_IS_PIPELINE_CLASS +GST_PIPELINE_GET_CLASS +GST_TYPE_PIPELINE +GST_TYPE_PIPELINE_FLAGS +GST_PIPELINE_CAST + +GstPipelinePrivate +gst_pipeline_get_type +gst_pipeline_flags_get_type +
+ + +
+gstplugin +GstPlugin +gst_plugin_error_quark +GST_PLUGIN_ERROR +GstPluginError +GstPlugin +GstPluginDesc +GstPluginInitFunc +GstPluginInitFullFunc +GST_PLUGIN_DEFINE +GST_PLUGIN_STATIC_DECLARE +GST_PLUGIN_STATIC_REGISTER +GST_LICENSE_UNKNOWN +GstPluginFilter +gst_plugin_get_name +gst_plugin_get_description +gst_plugin_get_filename +gst_plugin_get_license +gst_plugin_get_package +gst_plugin_get_origin +gst_plugin_get_source +gst_plugin_get_version +gst_plugin_get_release_date_string +gst_plugin_is_loaded +gst_plugin_get_cache_data +gst_plugin_set_cache_data +gst_plugin_load_file +gst_plugin_load +gst_plugin_load_by_name +gst_plugin_list_free +gst_plugin_register_static +gst_plugin_register_static_full + +GstPluginFlags +GstPluginDependencyFlags +gst_plugin_add_dependency +gst_plugin_add_dependency_simple + +GstPluginClass +GST_PLUGIN +GST_PLUGIN_CAST +GST_PLUGIN_CLASS +GST_PLUGIN_GET_CLASS +GST_TYPE_PLUGIN +GST_TYPE_PLUGIN_ERROR +GST_IS_PLUGIN +GST_IS_PLUGIN_CLASS +GST_TYPE_PLUGIN_FLAGS +GST_TYPE_PLUGIN_DEPENDENCY_FLAGS +GstPluginPrivate +gst_plugin_dependency_flags_get_type + +gst_plugin_get_type + +gst_plugin_error_get_type +gst_plugin_flags_get_type +
+ + +
+gstpluginfeature +GstPluginFeature +GstPluginFeature +GstPluginFeatureFilter +GstRank + +gst_plugin_feature_set_rank +gst_plugin_feature_set_name +gst_plugin_feature_get_rank +gst_plugin_feature_get_name +gst_plugin_feature_get_plugin +gst_plugin_feature_get_plugin_name +gst_plugin_feature_load +gst_plugin_feature_list_copy +gst_plugin_feature_list_free +GST_PLUGIN_FEATURE_LIST_DEBUG +gst_plugin_feature_check_version +gst_plugin_feature_rank_compare_func + +GstPluginFeatureClass +GST_PLUGIN_FEATURE +GST_PLUGIN_FEATURE_CAST +GST_IS_PLUGIN_FEATURE +GST_PLUGIN_FEATURE_CLASS +GST_IS_PLUGIN_FEATURE_CLASS +GST_PLUGIN_FEATURE_GET_CLASS +GST_TYPE_PLUGIN_FEATURE +GST_TYPE_RANK + +gst_plugin_feature_get_type +gst_plugin_feature_list_debug +gst_rank_get_type +
+ + +
+gstpoll +GstPoll +GstPoll +GstPollFD +GST_POLL_FD_INIT +gst_poll_add_fd +gst_poll_fd_can_read +gst_poll_fd_can_write +gst_poll_fd_ctl_read +gst_poll_fd_ctl_write +gst_poll_fd_has_closed +gst_poll_fd_has_error +gst_poll_fd_ignored +gst_poll_fd_init +gst_poll_free +gst_poll_new +gst_poll_new_timer +gst_poll_get_read_gpollfd +gst_poll_remove_fd +gst_poll_restart +gst_poll_set_controllable +gst_poll_set_flushing +gst_poll_wait +gst_poll_read_control +gst_poll_write_control +
+ +
+gstpreset +GstPreset +GstPreset +GstPresetInterface +gst_preset_get_preset_names +gst_preset_get_property_names +gst_preset_load_preset +gst_preset_save_preset +gst_preset_rename_preset +gst_preset_delete_preset +gst_preset_set_meta +gst_preset_get_meta +gst_preset_set_app_dir +gst_preset_get_app_dir +gst_preset_is_editable + +GST_PRESET +GST_IS_PRESET +GST_TYPE_PRESET +GST_PRESET_GET_INTERFACE +gst_preset_get_type +
+ +
+gstprotection +GstProtectionMeta +gst/gstprotection.h +GstProtectionMeta +gst_buffer_add_protection_meta +gst_buffer_get_protection_meta +gst_protection_select_system +gst_protection_filter_systems_by_available_decryptors +GST_PROTECTION_SYSTEM_ID_CAPS_FIELD + +GST_PROTECTION_META_API_TYPE +GST_PROTECTION_META_INFO +gst_protection_meta_get_info +gst_protection_meta_api_get_type +
+ +
+gstquery +GstQuery +GstQuery + +GstQueryTypeFlags +GST_QUERY_TYPE_BOTH +GST_QUERY_MAKE_TYPE + +GstQueryType + +GST_QUERY_TYPE +GST_QUERY_TYPE_NAME + +GST_QUERY_IS_UPSTREAM +GST_QUERY_IS_DOWNSTREAM +GST_QUERY_IS_SERIALIZED + +gst_query_type_get_flags +gst_query_type_get_name +gst_query_type_to_quark + +gst_query_ref +gst_query_unref +gst_query_copy +gst_query_make_writable +gst_query_is_writable +gst_query_replace +gst_query_writable_structure + +gst_query_new_custom +gst_query_get_structure + +gst_query_new_convert +gst_query_set_convert +gst_query_parse_convert + +gst_query_new_position +gst_query_set_position +gst_query_parse_position + +gst_query_new_duration +gst_query_set_duration +gst_query_parse_duration + +gst_query_new_latency +gst_query_parse_latency +gst_query_set_latency + +gst_query_new_seeking +gst_query_set_seeking +gst_query_parse_seeking + +gst_query_new_formats +gst_query_set_formats +gst_query_set_formatsv +gst_query_parse_n_formats +gst_query_parse_nth_format + +gst_query_new_segment +gst_query_set_segment +gst_query_parse_segment + +gst_query_new_caps +gst_query_parse_caps +gst_query_set_caps_result +gst_query_parse_caps_result + +gst_query_new_accept_caps +gst_query_parse_accept_caps +gst_query_set_accept_caps_result +gst_query_parse_accept_caps_result + +GstBufferingMode +gst_query_new_buffering +gst_query_set_buffering_percent +gst_query_parse_buffering_percent +gst_query_set_buffering_stats +gst_query_parse_buffering_stats +gst_query_set_buffering_range +gst_query_parse_buffering_range +gst_query_add_buffering_range +gst_query_get_n_buffering_ranges +gst_query_parse_nth_buffering_range + +gst_query_new_uri +gst_query_parse_uri +gst_query_set_uri +gst_query_parse_uri_redirection +gst_query_set_uri_redirection +gst_query_parse_uri_redirection_permanent +gst_query_set_uri_redirection_permanent + +gst_query_new_allocation +gst_query_parse_allocation + +gst_query_add_allocation_pool +gst_query_get_n_allocation_pools +gst_query_parse_nth_allocation_pool +gst_query_set_nth_allocation_pool +gst_query_remove_nth_allocation_pool + +gst_query_add_allocation_param +gst_query_get_n_allocation_params +gst_query_parse_nth_allocation_param +gst_query_set_nth_allocation_param +gst_query_remove_nth_allocation_param + +gst_query_add_allocation_meta +gst_query_get_n_allocation_metas +gst_query_parse_nth_allocation_meta +gst_query_remove_nth_allocation_meta +gst_query_find_allocation_meta + +GstSchedulingFlags +gst_query_new_scheduling +gst_query_parse_scheduling +gst_query_set_scheduling +gst_query_add_scheduling_mode +gst_query_get_n_scheduling_modes +gst_query_parse_nth_scheduling_mode +gst_query_has_scheduling_mode +gst_query_has_scheduling_mode_with_flags + +gst_query_new_drain + +gst_query_new_context +gst_query_set_context +gst_query_parse_context +gst_query_parse_context_type + +GstQueryClass +GST_QUERY +GST_QUERY_CAST +GST_IS_QUERY +GST_QUERY_CLASS +GST_IS_QUERY_CLASS +GST_TYPE_QUERY +GST_TYPE_QUERY_TYPE +GST_QUERY_GET_CLASS +GST_TYPE_QUERY_TYPE_FLAGS +gst_query_type_flags_get_type +GST_TYPE_BUFFERING_MODE +gst_buffering_mode_get_type +GST_TYPE_SCHEDULING_FLAGS +gst_scheduling_flags_get_type + +GST_QUERY_NUM_SHIFT +gst_query_get_type +gst_query_type_get_type +
+ + +
+gstregistry +GstRegistry +GstRegistry +gst_registry_get +gst_registry_get_feature_list +gst_registry_get_feature_list_cookie +gst_registry_get_feature_list_by_plugin +gst_registry_get_plugin_list +gst_registry_add_plugin +gst_registry_remove_plugin +gst_registry_plugin_filter +gst_registry_feature_filter +gst_registry_find_plugin +gst_registry_find_feature +gst_registry_lookup_feature +gst_registry_add_path +gst_registry_get_path_list +gst_registry_scan_path +gst_registry_lookup +gst_registry_remove_feature +gst_registry_add_feature +gst_registry_check_feature_version + +GstRegistryClass +GST_REGISTRY +GST_IS_REGISTRY +GST_REGISTRY_CLASS +GST_IS_REGISTRY_CLASS +GST_REGISTRY_GET_CLASS +GST_TYPE_REGISTRY + +GST_MAGIC_BINARY_REGISTRY_LEN +GST_MAGIC_BINARY_REGISTRY_STR +GST_MAGIC_BINARY_VERSION_STR +GST_MAGIC_BINARY_VERSION_LEN +gst_registry_get_type +GstRegistryPrivate +
+ + +
+gstpromise +GstPromise +GstPromiseResult +GstPromiseChangeFunc +GstPromise +gst_promise_new +gst_promise_new_with_change_func +gst_promise_ref +gst_promise_unref +gst_promise_wait +gst_promise_reply +gst_promise_interrupt +gst_promise_expire +gst_promise_get_reply + +GST_PROMISE +GST_TYPE_PROMISE +gst_promise_get_type +GST_TYPE_PROMISE_RESULT +gst_promise_result_get_type +
+ + +
+gstsegment +GstSegment +GstSegment +GstSegmentFlags +gst_segment_clip +gst_segment_init +gst_segment_new +gst_segment_copy +gst_segment_free +gst_segment_do_seek +gst_segment_position_from_stream_time +gst_segment_position_from_stream_time_full +gst_segment_to_running_time +gst_segment_to_running_time_full +gst_segment_to_stream_time +gst_segment_to_stream_time_full +gst_segment_position_from_running_time +gst_segment_position_from_running_time_full +gst_segment_to_position +gst_segment_set_running_time +gst_segment_copy_into +gst_segment_offset_running_time +gst_segment_is_equal + +GST_TYPE_SEGMENT +GST_TYPE_SEGMENT_FLAGS +gst_segment_get_type +gst_segment_flags_get_type + +
+ +
+gststreams +GstStream +GstStream +GstStreamClass +GstStreamType +gst_stream_new +gst_stream_get_caps +gst_stream_get_stream_flags +gst_stream_get_stream_id +gst_stream_get_stream_type +gst_stream_get_tags +gst_stream_set_caps +gst_stream_set_stream_flags +gst_stream_set_stream_type +gst_stream_set_tags +gst_stream_type_get_name + +GST_IS_STREAM +GST_IS_STREAM_CLASS +GST_STREAM +GST_STREAM_CAST +GST_STREAM_CLASS +GST_STREAM_GET_CLASS +GST_TYPE_STREAM +GST_TYPE_STREAM_TYPE +gst_stream_get_type +gst_stream_type_get_type + +GstStreamPrivate +
+ +
+gststreamcollection +GstStreamCollection +GstStreamCollection +GstStreamCollectionClass +gst_stream_collection_new +gst_stream_collection_add_stream +gst_stream_collection_get_upstream_id +gst_stream_collection_get_size +gst_stream_collection_get_stream + +gst_stream_collection_get_type +GST_IS_STREAM_COLLECTION +GST_IS_STREAM_COLLECTION_CLASS +GST_STREAM_COLLECTION +GST_STREAM_COLLECTION_CAST +GST_STREAM_COLLECTION_CLASS +GST_STREAM_COLLECTION_GET_CLASS +GST_TYPE_STREAM_COLLECTION + +GstStreamCollectionPrivate +
+ +
+gststructure +GstStructure +GstStructure +GstStructureForeachFunc +GstStructureMapFunc +GstStructureFilterMapFunc +gst_structure_new_empty +gst_structure_new_id_empty +gst_structure_new +gst_structure_new_valist +gst_structure_new_id +gst_structure_new_from_string +gst_structure_copy +gst_structure_free +gst_structure_get_name +gst_structure_has_name +gst_structure_set_name +gst_structure_get_name_id +gst_structure_id_get +gst_structure_id_get_valist +gst_structure_id_get_value +gst_structure_id_set_value +gst_structure_id_take_value +gst_structure_get +gst_structure_get_valist +gst_structure_get_value +gst_structure_set_value +gst_structure_set_array +gst_structure_set_list +gst_structure_take_value +gst_structure_set +gst_structure_set_valist +gst_structure_id_set +gst_structure_id_set_valist +gst_structure_remove_field +gst_structure_remove_fields +gst_structure_remove_fields_valist +gst_structure_remove_all_fields +gst_structure_get_field_type +gst_structure_n_fields +gst_structure_has_field +gst_structure_has_field_typed +gst_structure_is_equal +gst_structure_is_subset +gst_structure_can_intersect +gst_structure_intersect +gst_structure_id_has_field +gst_structure_id_has_field_typed +gst_structure_get_boolean +gst_structure_get_int +gst_structure_get_uint +gst_structure_get_int64 +gst_structure_get_uint64 +gst_structure_get_double +gst_structure_get_string +gst_structure_get_date +gst_structure_get_date_time +gst_structure_get_clock_time +gst_structure_get_enum +gst_structure_get_fraction +gst_structure_get_array +gst_structure_get_list +gst_structure_foreach +gst_structure_map_in_place +gst_structure_filter_and_map_in_place +gst_structure_nth_field_name +gst_structure_set_parent_refcount +gst_structure_to_string +gst_structure_from_string +gst_structure_fixate +gst_structure_fixate_field +gst_structure_fixate_field_nearest_int +gst_structure_fixate_field_nearest_double +gst_structure_fixate_field_nearest_fraction +gst_structure_fixate_field_boolean +gst_structure_fixate_field_string + +GST_STRUCTURE +GST_STRUCTURE_CAST +GST_IS_STRUCTURE +GST_TYPE_STRUCTURE + +gst_structure_get_type +
+ +
+gstsystemclock +GstSystemClock +GstClockType +GstSystemClock +gst_system_clock_obtain +gst_system_clock_set_default + +GstSystemClockClass +GstSystemClockPrivate +GST_SYSTEM_CLOCK +GST_IS_SYSTEM_CLOCK +gst_system_clock_get_type +GST_SYSTEM_CLOCK_CLASS +GST_IS_SYSTEM_CLOCK_CLASS +GST_SYSTEM_CLOCK_GET_CLASS +GST_TYPE_SYSTEM_CLOCK +GST_SYSTEM_CLOCK_CAST +GST_TYPE_CLOCK_TYPE +gst_clock_type_get_type +
+ +
+gsttaglist +GstTagList +GstTagList +GstTagMergeMode +GstTagFlag +GstTagForeachFunc +GstTagMergeFunc + +GstTagScope + +GST_TAG_TITLE +GST_TAG_TITLE_SORTNAME +GST_TAG_ARTIST +GST_TAG_ARTIST_SORTNAME +GST_TAG_ALBUM +GST_TAG_ALBUM_SORTNAME +GST_TAG_ALBUM_ARTIST +GST_TAG_ALBUM_ARTIST_SORTNAME +GST_TAG_DATE +GST_TAG_DATE_TIME +GST_TAG_GENRE +GST_TAG_COMMENT +GST_TAG_EXTENDED_COMMENT +GST_TAG_TRACK_NUMBER +GST_TAG_TRACK_COUNT +GST_TAG_ALBUM_VOLUME_NUMBER +GST_TAG_ALBUM_VOLUME_COUNT +GST_TAG_LOCATION +GST_TAG_HOMEPAGE +GST_TAG_DESCRIPTION +GST_TAG_VERSION +GST_TAG_ISRC +GST_TAG_ORGANIZATION +GST_TAG_COPYRIGHT +GST_TAG_COPYRIGHT_URI +GST_TAG_ENCODED_BY +GST_TAG_COMPOSER +GST_TAG_CONDUCTOR +GST_TAG_CONTACT +GST_TAG_LICENSE +GST_TAG_LICENSE_URI +GST_TAG_PERFORMER +GST_TAG_DURATION +GST_TAG_CODEC +GST_TAG_VIDEO_CODEC +GST_TAG_AUDIO_CODEC +GST_TAG_SUBTITLE_CODEC +GST_TAG_CONTAINER_FORMAT +GST_TAG_BITRATE +GST_TAG_NOMINAL_BITRATE +GST_TAG_MINIMUM_BITRATE +GST_TAG_MAXIMUM_BITRATE +GST_TAG_SERIAL +GST_TAG_ENCODER +GST_TAG_ENCODER_VERSION +GST_TAG_TRACK_GAIN +GST_TAG_TRACK_PEAK +GST_TAG_ALBUM_GAIN +GST_TAG_ALBUM_PEAK +GST_TAG_REFERENCE_LEVEL +GST_TAG_LANGUAGE_CODE +GST_TAG_LANGUAGE_NAME +GST_TAG_IMAGE +GST_TAG_PREVIEW_IMAGE +GST_TAG_ATTACHMENT +GST_TAG_BEATS_PER_MINUTE +GST_TAG_KEYWORDS +GST_TAG_GEO_LOCATION_NAME +GST_TAG_GEO_LOCATION_LATITUDE +GST_TAG_GEO_LOCATION_LONGITUDE +GST_TAG_GEO_LOCATION_ELEVATION +GST_TAG_GEO_LOCATION_CITY +GST_TAG_GEO_LOCATION_COUNTRY +GST_TAG_GEO_LOCATION_SUBLOCATION +GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR +GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION +GST_TAG_GEO_LOCATION_MOVEMENT_SPEED +GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION +GST_TAG_SHOW_NAME +GST_TAG_SHOW_SORTNAME +GST_TAG_SHOW_EPISODE_NUMBER +GST_TAG_SHOW_SEASON_NUMBER +GST_TAG_LYRICS +GST_TAG_COMPOSER_SORTNAME +GST_TAG_GROUPING +GST_TAG_USER_RATING +GST_TAG_DEVICE_MANUFACTURER +GST_TAG_DEVICE_MODEL +GST_TAG_APPLICATION_NAME +GST_TAG_APPLICATION_DATA +GST_TAG_IMAGE_ORIENTATION +GST_TAG_PUBLISHER +GST_TAG_INTERPRETED_BY +GST_TAG_MIDI_BASE_NOTE +GST_TAG_PRIVATE_DATA + +gst_tag_register +gst_tag_register_static +gst_tag_merge_use_first +gst_tag_merge_strings_with_comma +gst_tag_exists +gst_tag_get_type +gst_tag_get_nick +gst_tag_get_description +gst_tag_get_flag +gst_tag_is_fixed +gst_tag_list_new +gst_tag_list_new_empty +gst_tag_list_new_valist +gst_tag_list_new_from_string +gst_tag_list_free +gst_tag_list_get_scope +gst_tag_list_set_scope +gst_tag_list_to_string +gst_tag_list_is_empty +gst_tag_list_is_equal +gst_tag_list_copy +gst_tag_list_ref +gst_tag_list_unref +gst_tag_list_is_writable +gst_tag_list_make_writable +gst_tag_list_insert +gst_tag_list_merge +gst_tag_list_get_tag_size +gst_tag_list_n_tags +gst_tag_list_nth_tag_name +gst_tag_list_add +gst_tag_list_add_value +gst_tag_list_add_values +gst_tag_list_add_valist +gst_tag_list_add_valist_values +gst_tag_list_remove_tag +gst_tag_list_foreach +gst_tag_list_get_value_index +gst_tag_list_copy_value +gst_tag_list_get_boolean +gst_tag_list_get_boolean_index +gst_tag_list_get_int +gst_tag_list_get_int_index +gst_tag_list_get_uint +gst_tag_list_get_uint_index +gst_tag_list_get_int64 +gst_tag_list_get_int64_index +gst_tag_list_get_uint64 +gst_tag_list_get_uint64_index +gst_tag_list_get_float +gst_tag_list_get_float_index +gst_tag_list_get_double +gst_tag_list_get_double_index +gst_tag_list_get_string +gst_tag_list_get_string_index +gst_tag_list_peek_string_index +gst_tag_list_get_pointer +gst_tag_list_get_pointer_index +gst_tag_list_get_date +gst_tag_list_get_date_index +gst_tag_list_get_date_time +gst_tag_list_get_date_time_index +gst_tag_list_get_sample +gst_tag_list_get_sample_index + +GST_TAG_LIST +GST_IS_TAG_LIST +GST_TAG_FLAG_IS_VALID +GST_TAG_MODE_IS_VALID +GST_TYPE_TAG_LIST +GST_TYPE_TAG_FLAG +GST_TYPE_TAG_MERGE_MODE +GST_TYPE_TAG_SCOPE + +gst_tag_list_get_type +gst_tag_flag_get_type +gst_tag_merge_mode_get_type +gst_tag_scope_get_type +
+ + +
+gsttagsetter +GstTagSetter +GstTagSetter +GstTagSetterInterface +gst_tag_setter_reset_tags +gst_tag_setter_merge_tags +gst_tag_setter_add_tags +gst_tag_setter_add_tag_value +gst_tag_setter_add_tag_values +gst_tag_setter_add_tag_valist +gst_tag_setter_add_tag_valist_values +gst_tag_setter_get_tag_list +gst_tag_setter_set_tag_merge_mode +gst_tag_setter_get_tag_merge_mode + +GST_TAG_SETTER +GST_IS_TAG_SETTER +GST_TAG_SETTER_GET_INTERFACE +GST_TYPE_TAG_SETTER + +gst_tag_setter_get_type +
+ +
+gsttaskpool +GstTaskPool +GstTaskPool +GstTaskPoolClass +GstTaskPoolFunction +gst_task_pool_new +gst_task_pool_prepare +gst_task_pool_push +gst_task_pool_join +gst_task_pool_cleanup + +GST_IS_TASK_POOL +GST_IS_TASK_POOL_CLASS +GST_TASK_POOL +GST_TASK_POOL_CAST +GST_TASK_POOL_CLASS +GST_TASK_POOL_GET_CLASS +GST_TYPE_TASK_POOL + +gst_task_pool_get_type +
+ + +
+gsttask +GstTask +GstTask +GstTaskFunction +GstTaskState + +GST_TASK_BROADCAST +GST_TASK_GET_COND +GST_TASK_GET_LOCK +GST_TASK_SIGNAL +GST_TASK_STATE +GST_TASK_WAIT + +gst_task_new +gst_task_set_lock + +gst_task_set_pool +gst_task_get_pool + +GstTaskThreadFunc +gst_task_set_enter_callback +gst_task_set_leave_callback + +gst_task_get_state +gst_task_set_state +gst_task_pause +gst_task_start +gst_task_stop +gst_task_join + +gst_task_cleanup_all + + +GstTaskClass +GstTaskPrivate +GST_TASK +GST_IS_TASK +GST_TYPE_TASK +GST_TASK_CLASS +GST_IS_TASK_CLASS +GST_TASK_GET_CLASS +GST_TASK_CAST +GST_TYPE_TASK_STATE + +gst_task_get_type +gst_task_state_get_type +
+ + +
+gsttoc +GstToc +GstToc +GstTocScope +GstTocEntry +GstTocEntryType +GstTocLoopType +gst_toc_new +gst_toc_ref +gst_toc_unref +gst_toc_copy +gst_toc_make_writable +gst_toc_get_scope +gst_toc_get_entries +gst_toc_append_entry +gst_toc_get_tags +gst_toc_merge_tags +gst_toc_set_tags +gst_toc_dump +gst_toc_entry_new +gst_toc_entry_ref +gst_toc_entry_unref +gst_toc_entry_copy +gst_toc_entry_make_writable +gst_toc_find_entry +gst_toc_entry_get_toc +gst_toc_entry_get_uid +gst_toc_entry_get_parent +gst_toc_entry_get_sub_entries +gst_toc_entry_append_sub_entry +gst_toc_entry_get_loop +gst_toc_entry_set_loop +gst_toc_entry_get_start_stop_times +gst_toc_entry_set_start_stop_times +gst_toc_entry_get_tags +gst_toc_entry_merge_tags +gst_toc_entry_set_tags +gst_toc_entry_type_get_nick +gst_toc_entry_get_entry_type +gst_toc_entry_is_alternative +gst_toc_entry_is_sequence +GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE +GST_TOC_ENTRY_TYPE_IS_SEQUENCE +GST_TOC_REPEAT_COUNT_INFINITE + +GST_TYPE_TOC +GST_TYPE_TOC_ENTRY +GST_TYPE_TOC_ENTRY_TYPE +GST_TYPE_TOC_LOOP_TYPE +GST_TYPE_TOC_SCOPE + +gst_toc_get_type +gst_toc_entry_get_type +gst_toc_entry_type_get_type +gst_toc_loop_type_get_type +gst_toc_scope_get_type +
+ + +
+gsttracer +GstTracer +GstTracer +gst_tracer_register +gst_tracing_register_hook + +GstTracerHookBinAddPost +GstTracerHookBinAddPre +GstTracerHookBinRemovePost +GstTracerHookBinRemovePre +GstTracerHookElementAddPad +GstTracerHookElementChangeStatePost +GstTracerHookElementChangeStatePre +GstTracerHookElementNew +GstTracerHookElementPostMessagePost +GstTracerHookElementPostMessagePre +GstTracerHookElementQueryPost +GstTracerHookElementQueryPre +GstTracerHookElementRemovePad +GstTracerHookMiniObjectCreated +GstTracerHookMiniObjectDestroyed +GstTracerHookMiniObjectReffed +GstTracerHookMiniObjectUnreffed +GstTracerHookObjectCreated +GstTracerHookObjectDestroyed +GstTracerHookObjectReffed +GstTracerHookObjectUnreffed +GstTracerHookPadLinkPost +GstTracerHookPadLinkPre +GstTracerHookPadPullRangePost +GstTracerHookPadPullRangePre +GstTracerHookPadPushEventPost +GstTracerHookPadPushEventPre +GstTracerHookPadPushListPost +GstTracerHookPadPushListPre +GstTracerHookPadPushPost +GstTracerHookPadPushPre +GstTracerHookPadQueryPost +GstTracerHookPadQueryPre +GstTracerHookPadUnlinkPost +GstTracerHookPadUnlinkPre + +GST_TRACER +GST_IS_TRACER +GST_TYPE_TRACER +GST_TRACER_CLASS +GST_IS_TRACER_CLASS +GST_TRACER_GET_CLASS +GST_TRACER_CAST + +GST_TRACER_ARGS +GST_TRACER_DISPATCH +GST_TRACER_IS_ENABLED +GST_TRACER_QUARK +GST_TRACER_TS +GST_TRACER_BIN_ADD_POST +GST_TRACER_BIN_ADD_PRE +GST_TRACER_BIN_REMOVE_POST +GST_TRACER_BIN_REMOVE_PRE +GST_TRACER_ELEMENT_ADD_PAD +GST_TRACER_ELEMENT_CHANGE_STATE_POST +GST_TRACER_ELEMENT_CHANGE_STATE_PRE +GST_TRACER_ELEMENT_NEW +GST_TRACER_ELEMENT_POST_MESSAGE_POST +GST_TRACER_ELEMENT_POST_MESSAGE_PRE +GST_TRACER_ELEMENT_QUERY_POST +GST_TRACER_ELEMENT_QUERY_PRE +GST_TRACER_ELEMENT_REMOVE_PAD +GST_TRACER_MINI_OBJECT_CREATED +GST_TRACER_MINI_OBJECT_DESTROYED +GST_TRACER_MINI_OBJECT_REFFED +GST_TRACER_MINI_OBJECT_UNREFFED +GST_TRACER_OBJECT_CREATED +GST_TRACER_OBJECT_DESTROYED +GST_TRACER_OBJECT_REFFED +GST_TRACER_OBJECT_UNREFFED +GST_TRACER_PAD_LINK_POST +GST_TRACER_PAD_LINK_PRE +GST_TRACER_PAD_PULL_RANGE_POST +GST_TRACER_PAD_PULL_RANGE_PRE +GST_TRACER_PAD_PUSH_EVENT_POST +GST_TRACER_PAD_PUSH_EVENT_PRE +GST_TRACER_PAD_PUSH_LIST_POST +GST_TRACER_PAD_PUSH_LIST_PRE +GST_TRACER_PAD_PUSH_POST +GST_TRACER_PAD_PUSH_PRE +GST_TRACER_PAD_QUERY_POST +GST_TRACER_PAD_QUERY_PRE +GST_TRACER_PAD_UNLINK_POST +GST_TRACER_PAD_UNLINK_PRE +GstTracerHook +GstTracerQuarkId +gst_tracer_get_type +GstTracerPrivate +
+ + +
+gsttracerfactory +GstTracerFactory +GstTracerFactory +gst_tracer_factory_get_list +gst_tracer_factory_get_tracer_type + +GstTracerFactoryClass +GST_TRACER_FACTORY +GST_IS_TRACER_FACTORY +GST_TRACER_FACTORY_CLASS +GST_IS_TRACER_FACTORY_CLASS +GST_TRACER_FACTORY_GET_CLASS +GST_TRACER_FACTORY_CAST +GST_TYPE_TRACER_FACTORY + +gst_tracer_factory_get_type +
+ + +
+gsttracerrecord +GstTracerRecord +GstTracerRecord +GstTracerValueFlags +GstTracerValueScope +gst_tracer_record_new +gst_tracer_record_log + +GstTracerRecordClass +GST_TRACER_RECORD +GST_IS_TRACER_RECORD +GST_TRACER_RECORD_CLASS +GST_IS_TRACER_RECORD_CLASS +GST_TRACER_RECORD_GET_CLASS +GST_TRACER_RECORD_CAST +GST_TYPE_TRACER_RECORD +GST_TYPE_TRACER_VALUE_FLAGS +GST_TYPE_TRACER_VALUE_SCOPE + +gst_tracer_record_get_type +gst_tracer_value_flags_get_type +gst_tracer_value_scope_get_type +
+ + +
+gsttocsetter +GstTocSetter +GstTocSetter +GstTocSetterInterface +gst_toc_setter_set_toc +gst_toc_setter_get_toc +gst_toc_setter_reset + +GST_IS_TOC_SETTER +GST_TOC_SETTER +GST_TOC_SETTER_GET_IFACE +GST_TYPE_TOC_SETTER + +gst_toc_setter_get_type +
+ + +
+gsttypefind +GstTypeFind +GstTypeFind +GstTypeFindFunction +GstTypeFindProbability +gst_type_find_peek +gst_type_find_suggest +gst_type_find_suggest_simple +gst_type_find_get_length +gst_type_find_register + +GST_TYPE_TYPE_FIND_PROBABILITY + +gst_type_find_probability_get_type +gst_type_find_get_type +GST_TYPE_TYPE_FIND +
+ + +
+gsttypefindfactory +GstTypeFindFactory +GstTypeFindFactory +gst_type_find_factory_get_list +gst_type_find_factory_get_extensions +gst_type_find_factory_get_caps +gst_type_find_factory_has_function +gst_type_find_factory_call_function + +GstTypeFindFactoryClass +GST_TYPE_FIND_FACTORY +GST_IS_TYPE_FIND_FACTORY +GST_TYPE_FIND_FACTORY_CLASS +GST_IS_TYPE_FIND_FACTORY_CLASS +GST_TYPE_FIND_FACTORY_GET_CLASS +GST_TYPE_TYPE_FIND_FACTORY + +gst_type_find_factory_get_type +
+ + +
+gsturihandler +GstUriHandler +GstURIHandler +GstURIHandlerInterface +GstURIType +GstURIError +gst_uri_error_quark +GST_URI_TYPE_IS_VALID +GST_URI_NO_PORT +gst_uri_protocol_is_valid +gst_uri_protocol_is_supported +gst_uri_is_valid +gst_uri_has_protocol +gst_uri_get_protocol +gst_uri_get_location +gst_uri_construct +gst_filename_to_uri +gst_element_make_from_uri +gst_uri_handler_get_uri_type +gst_uri_handler_get_protocols +gst_uri_handler_get_uri +gst_uri_handler_set_uri + +GST_URI_HANDLER +GST_IS_URI_HANDLER +GST_URI_HANDLER_GET_INTERFACE +GST_TYPE_URI_HANDLER +GST_TYPE_URI_TYPE +gst_uri_error_get_type +GST_TYPE_URI_ERROR +GST_URI_ERROR + +gst_uri_handler_get_type +gst_uri_type_get_type +
+ +
+gsturi +GstUri +GST_URI_CAST +GST_URI_CONST_CAST +GstUri +gst_uri_new +gst_uri_new_with_base +gst_uri_from_string +gst_uri_from_string_with_base +gst_uri_copy +gst_uri_equal +gst_uri_join +gst_uri_join_strings +gst_uri_is_writable +gst_uri_make_writable +gst_uri_to_string +gst_uri_ref +gst_uri_unref +gst_uri_is_normalized +gst_uri_normalize +gst_uri_get_scheme +gst_uri_set_scheme +gst_uri_get_userinfo +gst_uri_set_userinfo +gst_uri_get_host +gst_uri_set_host +gst_uri_get_port +gst_uri_set_port +gst_uri_get_path +gst_uri_set_path +gst_uri_get_path_string +gst_uri_set_path_string +gst_uri_get_path_segments +gst_uri_set_path_segments +gst_uri_append_path +gst_uri_append_path_segment +gst_uri_get_query_string +gst_uri_set_query_string +gst_uri_get_query_table +gst_uri_set_query_table +gst_uri_get_query_value +gst_uri_set_query_value +gst_uri_remove_query_key +gst_uri_query_has_key +gst_uri_get_query_keys +gst_uri_get_fragment +gst_uri_set_fragment +gst_uri_get_media_fragment_table + +GST_IS_URI +GST_TYPE_URI +GST_URI +gst_uri_get_type +
+ +
+gstutils +GstUtils +GST_CALL_PARENT +GST_CALL_PARENT_WITH_DEFAULT +GST_READ_UINT8 +GST_READ_UINT16_LE +GST_READ_UINT16_BE +GST_READ_UINT24_LE +GST_READ_UINT24_BE +GST_READ_UINT32_LE +GST_READ_UINT32_BE +GST_READ_UINT64_LE +GST_READ_UINT64_BE +GST_READ_FLOAT_LE +GST_READ_FLOAT_BE +GST_READ_DOUBLE_LE +GST_READ_DOUBLE_BE +GST_WRITE_UINT8 +GST_WRITE_UINT16_LE +GST_WRITE_UINT16_BE +GST_WRITE_UINT24_LE +GST_WRITE_UINT24_BE +GST_WRITE_UINT32_LE +GST_WRITE_UINT32_BE +GST_WRITE_UINT64_LE +GST_WRITE_UINT64_BE +GST_WRITE_FLOAT_LE +GST_WRITE_FLOAT_BE +GST_WRITE_DOUBLE_LE +GST_WRITE_DOUBLE_BE +GST_ROUND_UP_2 +GST_ROUND_UP_4 +GST_ROUND_UP_8 +GST_ROUND_UP_16 +GST_ROUND_UP_32 +GST_ROUND_UP_64 +GST_ROUND_UP_128 +GST_ROUND_UP_N +GST_ROUND_DOWN_2 +GST_ROUND_DOWN_4 +GST_ROUND_DOWN_8 +GST_ROUND_DOWN_16 +GST_ROUND_DOWN_32 +GST_ROUND_DOWN_64 +GST_ROUND_DOWN_128 +GST_ROUND_DOWN_N +GDOUBLE_FROM_BE +GDOUBLE_FROM_LE +GDOUBLE_SWAP_LE_BE +GDOUBLE_TO_BE +GDOUBLE_TO_LE +GFLOAT_FROM_BE +GFLOAT_FROM_LE +GFLOAT_SWAP_LE_BE +GFLOAT_TO_BE +GFLOAT_TO_LE +GST_SEQNUM_INVALID +GST_GROUP_ID_INVALID + +gst_guint64_to_gdouble +gst_gdouble_to_guint64 +gst_util_dump_buffer +gst_util_dump_mem +gst_util_uint64_scale +gst_util_uint64_scale_round +gst_util_uint64_scale_ceil +gst_util_uint64_scale_int +gst_util_uint64_scale_int_round +gst_util_uint64_scale_int_ceil +gst_util_greatest_common_divisor +gst_util_greatest_common_divisor_int64 +gst_util_fraction_to_double +gst_util_double_to_fraction +gst_util_fraction_multiply +gst_util_fraction_add +gst_util_fraction_compare +gst_util_seqnum_next +gst_util_seqnum_compare +gst_util_group_id_next +gst_util_set_object_arg +gst_util_set_value_from_string +gst_util_set_object_array +gst_util_get_object_array +gst_util_get_timestamp +GstSearchMode +gst_util_array_binary_search + +GST_HAVE_UNALIGNED_ACCESS +gst_util_guint64_to_gdouble +gst_util_gdouble_to_guint64 +GST_TYPE_SEARCH_MODE +gst_search_mode_get_type +gst_calculate_linear_regression +
+ +
+gstdatetime +GstDateTime +GstDateTime +GST_TYPE_DATE_TIME +gst_date_time_get_day +gst_date_time_get_month +gst_date_time_get_hour +gst_date_time_get_microsecond +gst_date_time_get_minute +gst_date_time_get_time_zone_offset +gst_date_time_get_second +gst_date_time_get_year +gst_date_time_new +gst_date_time_new_ymd +gst_date_time_new_ym +gst_date_time_new_y +gst_date_time_new_from_unix_epoch_local_time +gst_date_time_new_from_unix_epoch_utc +gst_date_time_new_local_time +gst_date_time_new_now_local_time +gst_date_time_new_now_utc +gst_date_time_ref +gst_date_time_unref + +gst_date_time_has_day +gst_date_time_has_month +gst_date_time_has_second +gst_date_time_has_time +gst_date_time_has_year + + +gst_date_time_new_from_iso8601_string +gst_date_time_to_iso8601_string + +gst_date_time_new_from_g_date_time +gst_date_time_to_g_date_time +
+ +
+gstvalue +GstValue + + +GST_MAKE_FOURCC +GST_STR_FOURCC +GST_FOURCC_FORMAT +GST_FOURCC_ARGS + + +GST_VALUE_HOLDS_INT_RANGE +GST_TYPE_INT_RANGE +gst_value_set_int_range +gst_value_get_int_range_min +gst_value_get_int_range_max +gst_value_set_int_range_step +gst_value_get_int_range_step + + +GST_VALUE_HOLDS_BITMASK +GST_TYPE_BITMASK +gst_value_set_bitmask +gst_value_get_bitmask + + +GST_VALUE_HOLDS_FLAG_SET +GST_TYPE_FLAG_SET +gst_structure_get_flagset +gst_value_get_flagset_flags +gst_value_get_flagset_mask +gst_value_set_flagset +GST_FLAG_SET_MASK_EXACT + + +GST_VALUE_HOLDS_INT64_RANGE +GST_TYPE_INT64_RANGE +gst_value_set_int64_range +gst_value_get_int64_range_min +gst_value_get_int64_range_max +gst_value_set_int64_range_step +gst_value_get_int64_range_step + + +GST_VALUE_HOLDS_DOUBLE_RANGE +GST_TYPE_DOUBLE_RANGE +gst_value_set_double_range +gst_value_get_double_range_min +gst_value_get_double_range_max + + +GST_VALUE_HOLDS_LIST +GST_TYPE_LIST +GST_VALUE_HOLDS_ARRAY +GST_TYPE_ARRAY +gst_value_list_append_value +gst_value_list_append_and_take_value +gst_value_list_prepend_value +gst_value_list_concat +gst_value_list_merge +gst_value_list_get_size +gst_value_list_get_value + + +GST_VALUE_HOLDS_FRACTION +GST_TYPE_FRACTION +gst_value_set_fraction +gst_value_get_fraction_numerator +gst_value_get_fraction_denominator +gst_value_fraction_multiply +gst_value_fraction_subtract + + +GST_VALUE_HOLDS_FRACTION_RANGE +GST_TYPE_FRACTION_RANGE +gst_value_set_fraction_range +gst_value_get_fraction_range_min +gst_value_get_fraction_range_max +gst_value_set_fraction_range_full + + +GST_VALUE_HOLDS_DATE_TIME + + +GST_VALUE_HOLDS_CAPS +gst_value_set_caps +gst_value_get_caps + + +GST_VALUE_HOLDS_CAPS_FEATURES +gst_value_set_caps_features +gst_value_get_caps_features + + +GST_VALUE_HOLDS_STRUCTURE +gst_value_set_structure +gst_value_get_structure + + +GST_VALUE_HOLDS_BUFFER +gst_value_get_buffer +gst_value_set_buffer +gst_value_take_buffer + + +GST_VALUE_HOLDS_SAMPLE +gst_value_get_sample +gst_value_set_sample +gst_value_take_sample + + +GST_VALUE_LESS_THAN +GST_VALUE_EQUAL +GST_VALUE_GREATER_THAN +GST_VALUE_UNORDERED + +GstValueCompareFunc +GstValueSerializeFunc +GstValueDeserializeFunc +GstValueTable + +gst_value_is_fixed +gst_value_register +gst_value_init_and_copy +gst_value_serialize +gst_value_deserialize +gst_value_compare +gst_value_can_compare +gst_value_union +gst_value_can_union +gst_value_subtract +gst_value_can_subtract +gst_value_intersect +gst_value_can_intersect +gst_value_is_subset +gst_value_array_append_value +gst_value_array_append_and_take_value +gst_value_array_get_size +gst_value_array_get_value +gst_value_array_prepend_value +gst_value_fixate + +gst_flagset_register + + +GST_TYPE_G_THREAD + +gst_date_get_type +gst_date_time_get_type +gst_double_range_get_type +gst_fraction_get_type +gst_fraction_range_get_type +gst_g_thread_get_type +gst_int_range_get_type +gst_int64_range_get_type +gst_value_array_get_type +gst_value_list_get_type +gst_bitmask_get_type +gst_flagset_get_type +
+ +
+gstversion +GstVersion +GST_VERSION_MAJOR +GST_VERSION_MINOR +GST_VERSION_MICRO +GST_VERSION_NANO +GST_CHECK_VERSION +
+ +
+gstdevice +GstDevice + +GstDevice +GstDeviceClass + +gst_device_create_element +gst_device_get_caps +gst_device_get_device_class +gst_device_get_display_name +gst_device_has_classes +gst_device_has_classesv +gst_device_reconfigure_element +gst_device_get_properties + + +GST_DEVICE +GST_DEVICE_CAST +GST_DEVICE_CLASS +GST_DEVICE_GET_CLASS +GST_IS_DEVICE +GST_IS_DEVICE_CLASS +GST_TYPE_DEVICE +gst_device_get_type +
+ +
+gstdeviceprovider +GstDeviceProvider +GstDeviceProvider +GstDeviceProviderClass +gst_device_provider_can_monitor +gst_device_provider_class_add_metadata +gst_device_provider_class_add_static_metadata +gst_device_provider_class_get_metadata +gst_device_provider_class_set_metadata +gst_device_provider_class_set_static_metadata +gst_device_provider_device_add +gst_device_provider_device_remove +gst_device_provider_get_bus +gst_device_provider_get_devices +gst_device_provider_get_factory +gst_device_provider_get_metadata +gst_device_provider_register +gst_device_provider_start +gst_device_provider_stop + + +GstDevicePrivate +GST_DEVICE_PROVIDER +GST_DEVICE_PROVIDER_CAST +GST_DEVICE_PROVIDER_CLASS +GST_DEVICE_PROVIDER_GET_CLASS +GST_IS_DEVICE_PROVIDER +GST_IS_DEVICE_PROVIDER_CLASS +GST_TYPE_DEVICE_PROVIDER +gst_device_provider_get_type +
+ +
+gstdeviceproviderfactory +GstDeviceProviderFactory +GstDeviceProviderFactory +GstDeviceProviderFactoryClass +gst_device_provider_factory_find +gst_device_provider_factory_get +gst_device_provider_factory_get_by_name +gst_device_provider_factory_get_device_provider_type +gst_device_provider_factory_get_metadata +gst_device_provider_factory_get_metadata_keys +gst_device_provider_factory_has_classes +gst_device_provider_factory_has_classesv +gst_device_provider_factory_list_get_device_providers + + +GstDeviceProviderPrivate +GST_DEVICE_PROVIDER_FACTORY +GST_DEVICE_PROVIDER_FACTORY_CAST +GST_DEVICE_PROVIDER_FACTORY_CLASS +GST_TYPE_DEVICE_PROVIDER_FACTORY +GST_IS_DEVICE_PROVIDER_FACTORY +GST_IS_DEVICE_PROVIDER_FACTORY_CLASS +gst_device_provider_factory_get_type +
+ +
+gstdevicemonitor +GstDeviceMonitor +GstDeviceMonitor +GstDeviceMonitorClass +gst_device_monitor_new +gst_device_monitor_get_bus +gst_device_monitor_add_filter +gst_device_monitor_remove_filter +gst_device_monitor_start +gst_device_monitor_stop +gst_device_monitor_get_devices +gst_device_monitor_get_providers +gst_device_monitor_get_show_all_devices +gst_device_monitor_set_show_all_devices +gst_device_provider_get_hidden_providers +gst_device_provider_hide_provider +gst_device_provider_unhide_provider + + +GstDeviceMonitorPrivate +GST_DEVICE_MONITOR +GST_DEVICE_MONITOR_CAST +GST_DEVICE_MONITOR_CLASS +GST_DEVICE_MONITOR_GET_CLASS +GST_IS_DEVICE_MONITOR +GST_IS_DEVICE_MONITOR_CLASS +GST_TYPE_DEVICE_MONITOR +gst_device_monitor_get_type +
+ diff --git a/docs/gst/gstreamer.types b/docs/gst/gstreamer.types new file mode 100644 index 0000000..02895b6 --- /dev/null +++ b/docs/gst/gstreamer.types @@ -0,0 +1,51 @@ +% add a _get_type for every GObject whose properties and signals you want +% documented +% add the relevant includes to be able to call those _get_type functions + +% adding a get_type here will: +% - change output file name from gstreamer-(whatever).html to (whatever).html +% - document properties and signals + +#include +#include +#include + +gst_bin_get_type +gst_buffer_pool_get_type +gst_bus_get_type +gst_child_proxy_get_type +gst_clock_get_type +gst_control_binding_get_type +gst_control_source_get_type +gst_element_factory_get_type +gst_element_get_type +gst_ghost_pad_get_type +gst_object_get_type +gst_pad_get_type +gst_pad_template_get_type +gst_pipeline_get_type +gst_plugin_feature_get_type +gst_preset_get_type +gst_promise_get_type +gst_registry_get_type +gst_system_clock_get_type +gst_tag_setter_get_type +gst_task_get_type +gst_tracer_get_type +gst_tracer_factory_get_type +gst_tracer_record_get_type +gst_type_find_factory_get_type +gst_uri_handler_get_type + +gst_buffer_get_type +gst_buffer_list_get_type +gst_caps_get_type +gst_context_get_type +gst_event_get_type +gst_memory_get_type +gst_message_get_type +gst_query_get_type +gst_sample_get_type +gst_tag_list_get_type +gst_toc_get_type +gst_toc_entry_get_type diff --git a/docs/gst/gstreamer.types.in b/docs/gst/gstreamer.types.in new file mode 100644 index 0000000..02895b6 --- /dev/null +++ b/docs/gst/gstreamer.types.in @@ -0,0 +1,51 @@ +% add a _get_type for every GObject whose properties and signals you want +% documented +% add the relevant includes to be able to call those _get_type functions + +% adding a get_type here will: +% - change output file name from gstreamer-(whatever).html to (whatever).html +% - document properties and signals + +#include +#include +#include + +gst_bin_get_type +gst_buffer_pool_get_type +gst_bus_get_type +gst_child_proxy_get_type +gst_clock_get_type +gst_control_binding_get_type +gst_control_source_get_type +gst_element_factory_get_type +gst_element_get_type +gst_ghost_pad_get_type +gst_object_get_type +gst_pad_get_type +gst_pad_template_get_type +gst_pipeline_get_type +gst_plugin_feature_get_type +gst_preset_get_type +gst_promise_get_type +gst_registry_get_type +gst_system_clock_get_type +gst_tag_setter_get_type +gst_task_get_type +gst_tracer_get_type +gst_tracer_factory_get_type +gst_tracer_record_get_type +gst_type_find_factory_get_type +gst_uri_handler_get_type + +gst_buffer_get_type +gst_buffer_list_get_type +gst_caps_get_type +gst_context_get_type +gst_event_get_type +gst_memory_get_type +gst_message_get_type +gst_query_get_type +gst_sample_get_type +gst_tag_list_get_type +gst_toc_get_type +gst_toc_entry_get_type diff --git a/docs/gst/html/GstAllocator.html b/docs/gst/html/GstAllocator.html new file mode 100644 index 0000000..6d19d45 --- /dev/null +++ b/docs/gst/html/GstAllocator.html @@ -0,0 +1,717 @@ + + + + +GstAllocator: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstAllocator

+

GstAllocator — allocate memory blocks

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstAllocator * + +gst_allocator_find () +
+void + +gst_allocator_register () +
+void + +gst_allocator_set_default () +
+void + +gst_allocation_params_init () +
+GstAllocationParams * + +gst_allocation_params_copy () +
+void + +gst_allocation_params_free () +
+GstMemory * + +gst_allocator_alloc () +
+void + +gst_allocator_free () +
+GstMemory * + +gst_memory_new_wrapped () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
externgst_memory_alignment
 GstAllocator
structGstAllocatorClass
enumGstAllocatorFlags
structGstAllocationParams
#defineGST_ALLOCATOR_SYSMEM
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstAllocationParams
+    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstAllocator
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Memory is usually created by allocators with a gst_allocator_alloc() +method call. When NULL is used as the allocator, the default allocator will +be used.

+

New allocators can be registered with gst_allocator_register(). +Allocators are identified by name and can be retrieved with +gst_allocator_find(). gst_allocator_set_default() can be used to change the +default allocator.

+

New memory can be created with gst_memory_new_wrapped() that wraps the memory +allocated elsewhere.

+
+
+

Functions

+
+

gst_allocator_find ()

+
GstAllocator *
+gst_allocator_find (const gchar *name);
+

Find a previously registered allocator with name +. When name + is NULL, the +default allocator will be returned.

+
+

Parameters

+
+++++ + + + + + +

name

the name of the allocator.

[allow-none]
+
+
+

Returns

+

a GstAllocator or NULL when +the allocator with name +was not registered. Use gst_object_unref() +to release the allocator after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_allocator_register ()

+
void
+gst_allocator_register (const gchar *name,
+                        GstAllocator *allocator);
+

Registers the memory allocator + with name +. This function takes ownership of +allocator +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

the name of the allocator

 

allocator

GstAllocator.

[transfer full]
+
+
+
+
+

gst_allocator_set_default ()

+
void
+gst_allocator_set_default (GstAllocator *allocator);
+

Set the default allocator. This function takes ownership of allocator +.

+
+

Parameters

+
+++++ + + + + + +

allocator

a GstAllocator.

[transfer full]
+
+
+
+
+

gst_allocation_params_init ()

+
void
+gst_allocation_params_init (GstAllocationParams *params);
+

Initialize params + to its default values

+
+

Parameters

+
+++++ + + + + + +

params

a GstAllocationParams

 
+
+
+
+
+

gst_allocation_params_copy ()

+
GstAllocationParams *
+gst_allocation_params_copy (const GstAllocationParams *params);
+

Create a copy of params +.

+

Free-function: gst_allocation_params_free

+
+

Parameters

+
+++++ + + + + + +

params

a GstAllocationParams.

[transfer none][nullable]
+
+
+

Returns

+

a new #GstAllocationParams, free with +gst_allocation_params_free().

+

[transfer full][nullable]

+
+
+
+
+

gst_allocation_params_free ()

+
void
+gst_allocation_params_free (GstAllocationParams *params);
+

Free params +

+
+

Parameters

+
+++++ + + + + + +

params

a GstAllocationParams.

[in][transfer full]
+
+
+
+
+

gst_allocator_alloc ()

+
GstMemory *
+gst_allocator_alloc (GstAllocator *allocator,
+                     gsize size,
+                     GstAllocationParams *params);
+

Use allocator + to allocate a new memory block with memory that is at least +size + big.

+

The optional params + can specify the prefix and padding for the memory. If +NULL is passed, no flags, no extra prefix/padding and a default alignment is +used.

+

The prefix/padding will be filled with 0 if flags contains +GST_MEMORY_FLAG_ZERO_PREFIXED and GST_MEMORY_FLAG_ZERO_PADDED respectively.

+

When allocator + is NULL, the default allocator will be used.

+

The alignment in params + is given as a bitmask so that align + + 1 equals +the amount of bytes to align to. For example, to align to 8 bytes, +use an alignment of 7.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

allocator

a GstAllocator to use.

[transfer none][allow-none]

size

size of the visible memory area

 

params

optional parameters.

[transfer none][allow-none]
+
+
+

Returns

+

a new GstMemory.

+

[transfer full][nullable]

+
+
+
+
+

gst_allocator_free ()

+
void
+gst_allocator_free (GstAllocator *allocator,
+                    GstMemory *memory);
+

Free memory + that was previously allocated with gst_allocator_alloc().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

allocator

a GstAllocator to use.

[transfer none]

memory

the memory to free.

[transfer full]
+
+
+
+
+

gst_memory_new_wrapped ()

+
GstMemory *
+gst_memory_new_wrapped (GstMemoryFlags flags,
+                        gpointer data,
+                        gsize maxsize,
+                        gsize offset,
+                        gsize size,
+                        gpointer user_data,
+                        GDestroyNotify notify);
+

Allocate a new memory block that wraps the given data +.

+

The prefix/padding must be filled with 0 if flags + contains +GST_MEMORY_FLAG_ZERO_PREFIXED and GST_MEMORY_FLAG_ZERO_PADDED respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

flags

GstMemoryFlags

 

data

data to +wrap.

[array length=size][element-type guint8][transfer none]

maxsize

allocated size of data +

 

offset

offset in data +

 

size

size of valid data

 

user_data

user_data.

[allow-none]

notify

called with user_data +when the memory is freed.

[allow-none][scope async][closure user_data]
+
+
+

Returns

+

a new GstMemory.

+

[transfer full][nullable]

+
+
+
+
+

Types and Values

+
+

gst_memory_alignment

+
GST_API gsize gst_memory_alignment;
+
+

The default memory alignment in bytes - 1 +an alignment of 7 would be the same as what malloc() guarantees.

+
+
+
+

GstAllocator

+
typedef struct {
+  GstMemoryMapFunction       mem_map;
+  GstMemoryUnmapFunction     mem_unmap;
+
+  GstMemoryCopyFunction      mem_copy;
+  GstMemoryShareFunction     mem_share;
+  GstMemoryIsSpanFunction    mem_is_span;
+
+  GstMemoryMapFullFunction   mem_map_full;
+  GstMemoryUnmapFullFunction mem_unmap_full;
+} GstAllocator;
+
+

The GstAllocator is used to create new memory.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMemoryMapFunction mem_map;

the implementation of the GstMemoryMapFunction

 

GstMemoryUnmapFunction mem_unmap;

the implementation of the GstMemoryUnmapFunction

 

GstMemoryCopyFunction mem_copy;

the implementation of the GstMemoryCopyFunction

 

GstMemoryShareFunction mem_share;

the implementation of the GstMemoryShareFunction

 

GstMemoryIsSpanFunction mem_is_span;

the implementation of the GstMemoryIsSpanFunction

 

GstMemoryMapFullFunction mem_map_full;

the implementation of the GstMemoryMapFullFunction. +Will be used instead of mem_map +if present. (Since 1.6)

 

GstMemoryUnmapFullFunction mem_unmap_full;

the implementation of the GstMemoryUnmapFullFunction. +Will be used instead of mem_unmap +if present. (Since 1.6)

 
+
+
+
+
+

struct GstAllocatorClass

+
struct GstAllocatorClass {
+  GstObjectClass object_class;
+
+  GstMemory *  (*alloc)      (GstAllocator *allocator, gsize size,
+                              GstAllocationParams *params);
+  void         (*free)       (GstAllocator *allocator, GstMemory *memory);
+};
+
+

The GstAllocator is used to create new memory.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GstObjectClass object_class;

Object parent class

 

alloc ()

implementation that acquires memory

 

free ()

implementation that releases memory

 
+
+
+
+
+

enum GstAllocatorFlags

+

Flags for allocators.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_ALLOCATOR_FLAG_CUSTOM_ALLOC

+

The allocator has a custom alloc function.

+
 

GST_ALLOCATOR_FLAG_LAST

+

first flag that can be used for custom purposes

+
 
+
+
+
+
+

struct GstAllocationParams

+
struct GstAllocationParams {
+  GstMemoryFlags flags;
+  gsize          align;
+  gsize          prefix;
+  gsize          padding;
+};
+
+

Parameters to control the allocation of memory

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstMemoryFlags flags;

flags to control allocation

 

gsize align;

the desired alignment of the memory

 

gsize prefix;

the desired prefix

 

gsize padding;

the desired padding

 
+
+
+
+
+

GST_ALLOCATOR_SYSMEM

+
#define GST_ALLOCATOR_SYSMEM   "SystemMemory"
+
+

The allocator name for the default system memory allocator

+
+
+
+

See Also

+

GstMemory

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstBin.html b/docs/gst/html/GstBin.html new file mode 100644 index 0000000..b66701d --- /dev/null +++ b/docs/gst/html/GstBin.html @@ -0,0 +1,1617 @@ + + + + +GstBin: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBin

+

GstBin — Base class and element that can contain other elements

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstElement * + +gst_bin_new () +
+gboolean + +gst_bin_add () +
+gboolean + +gst_bin_remove () +
+GstElement * + +gst_bin_get_by_name () +
+GstElement * + +gst_bin_get_by_name_recurse_up () +
+GstElement * + +gst_bin_get_by_interface () +
+GstIterator * + +gst_bin_iterate_elements () +
+GstIterator * + +gst_bin_iterate_recurse () +
+GstIterator * + +gst_bin_iterate_sinks () +
+GstIterator * + +gst_bin_iterate_sorted () +
+GstIterator * + +gst_bin_iterate_sources () +
+GstIterator * + +gst_bin_iterate_all_by_interface () +
+gboolean + +gst_bin_recalculate_latency () +
+GstElementFlags + +gst_bin_get_suppressed_flags () +
+void + +gst_bin_set_suppressed_flags () +
+void + +gst_bin_add_many () +
+void + +gst_bin_remove_many () +
+GstPad * + +gst_bin_find_unlinked_pad () +
+gboolean + +gst_bin_sync_children_states () +
#define +GST_BIN_IS_NO_RESYNC() +
#define +GST_BIN_CHILDREN() +
#define +GST_BIN_CHILDREN_COOKIE() +
#define +GST_BIN_NUMCHILDREN() +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
gbooleanasync-handlingRead / Write
gbooleanmessage-forwardRead / Write
+
+
+

Signals

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstBin
structGstBinClass
enumGstBinFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBin
+                    ╰── GstPipeline
+
+
+
+

Implemented Interfaces

+

+GstBin implements + GstChildProxy.

+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstBin is an element that can contain other GstElement, allowing them to be +managed as a group. +Pads from the child elements can be ghosted to the bin, see GstGhostPad. +This makes the bin look like any other elements and enables creation of +higher-level abstraction elements.

+

A new GstBin is created with gst_bin_new(). Use a GstPipeline instead if you +want to create a toplevel bin because a normal bin doesn't have a bus or +handle clock distribution of its own.

+

After the bin has been created you will typically add elements to it with +gst_bin_add(). You can remove elements with gst_bin_remove().

+

An element can be retrieved from a bin with gst_bin_get_by_name(), using the +elements name. gst_bin_get_by_name_recurse_up() is mainly used for internal +purposes and will query the parent bins when the element is not found in the +current bin.

+

An iterator of elements in a bin can be retrieved with +gst_bin_iterate_elements(). Various other iterators exist to retrieve the +elements in a bin.

+

gst_object_unref() is used to drop your reference to the bin.

+

The “element-added” signal is fired whenever a new element is added to +the bin. Likewise the “element-removed” signal is fired whenever an +element is removed from the bin.

+
+

Notes

+

A GstBin internally intercepts every GstMessage posted by its children and +implements the following default behaviour for each of them:

+
    +
  • GST_MESSAGE_EOS: This message is only posted by sinks in the PLAYING +state. If all sinks posted the EOS message, this bin will post and EOS +message upwards.

  • +
  • GST_MESSAGE_SEGMENT_START: Just collected and never forwarded upwards. +The messages are used to decide when all elements have completed playback +of their segment.

  • +
  • GST_MESSAGE_SEGMENT_DONE: Is posted by GstBin when all elements that posted +a SEGMENT_START have posted a SEGMENT_DONE.

  • +
  • GST_MESSAGE_DURATION_CHANGED: Is posted by an element that detected a change +in the stream duration. The default bin behaviour is to clear any +cached duration values so that the next duration query will perform +a full duration recalculation. The duration change is posted to the +application so that it can refetch the new duration with a duration +query. Note that these messages can be posted before the bin is +prerolled, in which case the duration query might fail.

  • +
  • GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it +can no longer provide a clock. The default bin behaviour is to +check if the lost clock was the one provided by the bin. If so and +the bin is currently in the PLAYING state, the message is forwarded to +the bin parent. +This message is also generated when a clock provider is removed from +the bin. If this message is received by the application, it should +PAUSE the pipeline and set it back to PLAYING to force a new clock +distribution.

  • +
  • GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element +can provide a clock. This mostly happens when a new clock +provider is added to the bin. The default behaviour of the bin is to +mark the currently selected clock as dirty, which will perform a clock +recalculation the next time the bin is asked to provide a clock. +This message is never sent tot the application but is forwarded to +the parent of the bin.

  • +
  • OTHERS: posted upwards.

  • +
+

A GstBin implements the following default behaviour for answering to a +GstQuery:

+
    +
  • GST_QUERY_DURATION:If the query has been asked before with the same format +and the bin is a toplevel bin (ie. has no parent), +use the cached previous value. If no previous value was cached, the +query is sent to all sink elements in the bin and the MAXIMUM of all +values is returned. If the bin is a toplevel bin the value is cached. +If no sinks are available in the bin, the query fails.

  • +
  • GST_QUERY_POSITION:The query is sent to all sink elements in the bin and the +MAXIMUM of all values is returned. If no sinks are available in the bin, +the query fails.

  • +
  • OTHERS:the query is forwarded to all sink elements, the result +of the first sink that answers the query successfully is returned. If no +sink is in the bin, the query fails.

  • +
+

A GstBin will by default forward any event sent to it to all sink +(GST_EVENT_TYPE_DOWNSTREAM) or source (GST_EVENT_TYPE_UPSTREAM) elements +depending on the event type. +If all the elements return TRUE, the bin will also return TRUE, else FALSE +is returned. If no elements of the required type are in the bin, the event +handler will return TRUE.

+
+
+
+

Functions

+
+

gst_bin_new ()

+
GstElement *
+gst_bin_new (const gchar *name);
+

Creates a new bin with the given name.

+
+

Parameters

+
+++++ + + + + + +

name

the name of the new bin.

[allow-none]
+
+
+

Returns

+

a new GstBin.

+

[transfer floating]

+
+
+
+
+

gst_bin_add ()

+
gboolean
+gst_bin_add (GstBin *bin,
+             GstElement *element);
+

Adds the given element to the bin. Sets the element's parent, and thus +takes ownership of the element. An element can only be added to one bin.

+

If the element's pads are linked to other pads, the pads will be unlinked +before the element is added to the bin.

+

When you add an element to an already-running pipeline, you will have to +take care to set the state of the newly-added element to the desired +state (usually PLAYING or PAUSED, same you set the pipeline to originally) +with gst_element_set_state(), or use gst_element_sync_state_with_parent(). +The bin or pipeline will not take care of this for you.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

element

the GstElement to add.

[transfer floating]
+
+
+

Returns

+

TRUE if the element could be added, FALSE if +the bin does not want to accept the element.

+
+
+
+
+

gst_bin_remove ()

+
gboolean
+gst_bin_remove (GstBin *bin,
+                GstElement *element);
+

Removes the element from the bin, unparenting it as well. +Unparenting the element means that the element will be dereferenced, +so if the bin holds the only reference to the element, the element +will be freed in the process of removing it from the bin. If you +want the element to still exist after removing, you need to call +gst_object_ref() before removing it from the bin.

+

If the element's pads are linked to other pads, the pads will be unlinked +before the element is removed from the bin.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

element

the GstElement to remove.

[transfer none]
+
+
+

Returns

+

TRUE if the element could be removed, FALSE if +the bin does not want to remove the element.

+
+
+
+
+

gst_bin_get_by_name ()

+
GstElement *
+gst_bin_get_by_name (GstBin *bin,
+                     const gchar *name);
+

Gets the element with the given name from a bin. This +function recurses into child bins.

+

Returns NULL if no element with the given name is found in the bin.

+

MT safe. Caller owns returned reference.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

name

the element name to search for

 
+
+
+

Returns

+

the GstElement with the given +name, or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_get_by_name_recurse_up ()

+
GstElement *
+gst_bin_get_by_name_recurse_up (GstBin *bin,
+                                const gchar *name);
+

Gets the element with the given name from this bin. If the +element is not found, a recursion is performed on the parent bin.

+

Returns NULL if:

+
  • no element with the given name is found in the bin

+

MT safe. Caller owns returned reference.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

name

the element name to search for

 
+
+
+

Returns

+

the GstElement with the given +name, or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_get_by_interface ()

+
GstElement *
+gst_bin_get_by_interface (GstBin *bin,
+                          GType iface);
+

Looks for an element inside the bin that implements the given +interface. If such an element is found, it returns the element. +You can cast this element to the given interface afterwards. If you want +all elements that implement the interface, use +gst_bin_iterate_all_by_interface(). This function recurses into child bins.

+

MT safe. Caller owns returned reference.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

iface

the GType of an interface

 
+
+
+

Returns

+

A GstElement inside the bin +implementing the interface.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_elements ()

+
GstIterator *
+gst_bin_iterate_elements (GstBin *bin);
+

Gets an iterator for the elements in this bin.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

a GstIterator of GstElement, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_recurse ()

+
GstIterator *
+gst_bin_iterate_recurse (GstBin *bin);
+

Gets an iterator for the elements in this bin. +This iterator recurses into GstBin children.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

a GstIterator of GstElement, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_sinks ()

+
GstIterator *
+gst_bin_iterate_sinks (GstBin *bin);
+

Gets an iterator for all elements in the bin that have the +GST_ELEMENT_FLAG_SINK flag set.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

a GstIterator of GstElement, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_sorted ()

+
GstIterator *
+gst_bin_iterate_sorted (GstBin *bin);
+

Gets an iterator for the elements in this bin in topologically +sorted order. This means that the elements are returned from +the most downstream elements (sinks) to the sources.

+

This function is used internally to perform the state changes +of the bin elements and for clock selection.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

a GstIterator of GstElement, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_sources ()

+
GstIterator *
+gst_bin_iterate_sources (GstBin *bin);
+

Gets an iterator for all elements in the bin that have the +GST_ELEMENT_FLAG_SOURCE flag set.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

a GstIterator of GstElement, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_iterate_all_by_interface ()

+
GstIterator *
+gst_bin_iterate_all_by_interface (GstBin *bin,
+                                  GType iface);
+

Looks for all elements inside the bin that implements the given +interface. You can safely cast all returned elements to the given interface. +The function recurses inside child bins. The iterator will yield a series +of GstElement that should be unreffed after use.

+

MT safe. Caller owns returned value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

iface

the GType of an interface

 
+
+
+

Returns

+

a GstIterator of GstElement +for all elements in the bin implementing the given interface, +or NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_recalculate_latency ()

+
gboolean
+gst_bin_recalculate_latency (GstBin *bin);
+

Query bin + for the current latency using and reconfigures this latency to all the +elements with a LATENCY event.

+

This method is typically called on the pipeline when a GST_MESSAGE_LATENCY +is posted on the bus.

+

This function simply emits the 'do-latency' signal so any custom latency +calculations will be performed.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

TRUE if the latency could be queried and reconfigured.

+
+
+
+
+

gst_bin_get_suppressed_flags ()

+
GstElementFlags
+gst_bin_get_suppressed_flags (GstBin *bin);
+

Return the suppressed flags of the bin.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

the bin's suppressed GstElementFlags.

+
+

Since: 1.10

+
+
+
+

gst_bin_set_suppressed_flags ()

+
void
+gst_bin_set_suppressed_flags (GstBin *bin,
+                              GstElementFlags flags);
+

Suppress the given flags on the bin. GstElementFlags of a +child element are propagated when it is added to the bin. +When suppressed flags are set, those specified flags will +not be propagated to the bin.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

a GstBin

 

flags

the GstElementFlags to suppress

 
+
+

Since: 1.10

+
+
+
+

gst_bin_add_many ()

+
void
+gst_bin_add_many (GstBin *bin,
+                  GstElement *element_1,
+                  ...);
+

Adds a NULL-terminated list of elements to a bin. This function is +equivalent to calling gst_bin_add() for each member of the list. The return +value of each gst_bin_add() is ignored.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

a GstBin

 

element_1

the GstElement element to add to the bin.

[transfer floating]

...

additional elements to add to the bin

 
+
+
+
+
+

gst_bin_remove_many ()

+
void
+gst_bin_remove_many (GstBin *bin,
+                     GstElement *element_1,
+                     ...);
+

Remove a list of elements from a bin. This function is equivalent +to calling gst_bin_remove() with each member of the list.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

a GstBin

 

element_1

the first GstElement to remove from the bin.

[transfer none]

...

NULL-terminated list of elements to remove from the bin.

[transfer none]
+
+
+
+
+

gst_bin_find_unlinked_pad ()

+
GstPad *
+gst_bin_find_unlinked_pad (GstBin *bin,
+                           GstPadDirection direction);
+

Recursively looks for elements with an unlinked pad of the given +direction within the specified bin and returns an unlinked pad +if one is found, or NULL otherwise. If a pad is found, the caller +owns a reference to it and should use gst_object_unref() on the +pad when it is not needed any longer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

bin in which to look for elements with unlinked pads

 

direction

whether to look for an unlinked source or sink pad

 
+
+
+

Returns

+

unlinked pad of the given +direction, NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_bin_sync_children_states ()

+
gboolean
+gst_bin_sync_children_states (GstBin *bin);
+

Synchronizes the state of every child of bin + with the state +of bin +. See also gst_element_sync_state_with_parent().

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+

Returns

+

TRUE if syncing the state was successful for all children, +otherwise FALSE.

+
+

Since: 1.6

+
+
+
+

GST_BIN_IS_NO_RESYNC()

+
#define GST_BIN_IS_NO_RESYNC(bin)        (GST_OBJECT_FLAG_IS_SET(bin,GST_BIN_FLAG_NO_RESYNC))
+
+

Check if bin + will resync its state change when elements are added and +removed.

+
+

Parameters

+
+++++ + + + + + +

bin

A GstBin

 
+
+

Since: 1.0.5

+
+
+
+

GST_BIN_CHILDREN()

+
#define GST_BIN_CHILDREN(bin)		(GST_BIN_CAST(bin)->children)
+
+

Gets the list with children in a bin.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+
+
+

GST_BIN_CHILDREN_COOKIE()

+
#define GST_BIN_CHILDREN_COOKIE(bin) (GST_BIN_CAST(bin)->children_cookie)
+
+

Gets the children cookie that watches the children list.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+
+
+

GST_BIN_NUMCHILDREN()

+
#define GST_BIN_NUMCHILDREN(bin) (GST_BIN_CAST(bin)->numchildren)
+
+

Gets the number of children in a bin.

+
+

Parameters

+
+++++ + + + + + +

bin

a GstBin

 
+
+
+
+
+

Types and Values

+
+

struct GstBin

+
struct GstBin {
+  /* our children, subclass are supposed to update these
+   * fields to reflect their state with _iterate_*() */
+  gint		 numchildren;
+  GList		*children;
+  guint32	 children_cookie;
+
+  GstBus        *child_bus;
+  GList         *messages;
+
+  gboolean	 polling;
+  gboolean       state_dirty;
+
+  gboolean       clock_dirty;
+  GstClock *provided_clock;
+  GstElement    *clock_provider;
+};
+
+

The GstBin base class. Subclasses can access these fields provided +the LOCK is taken.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gint numchildren;

the number of children in this bin

 

GList *children;

the list of children in this bin.

[element-type Gst.Element]

guint32 children_cookie;

updated whenever children +changes

 

GstBus *child_bus;

internal bus for handling child messages

 

GList *messages;

queued and cached messages.

[element-type Gst.Message]

gboolean polling;

the bin is currently calculating its state

 

gboolean state_dirty;

the bin needs to recalculate its state (deprecated)

 

gboolean clock_dirty;

the bin needs to select a new clock

 

GstClock *provided_clock;

the last clock selected

 

GstElement *clock_provider;

the element that provided provided_clock +

 
+
+
+
+
+

struct GstBinClass

+
struct GstBinClass {
+  GstElementClass parent_class;
+
+  /* virtual methods for subclasses */
+  gboolean (*add_element)		(GstBin *bin, GstElement *element);
+  gboolean (*remove_element) (GstBin *bin, GstElement *element);
+
+  void		(*handle_message) (GstBin *bin, GstMessage *message);
+
+  /* signal */
+  void          (*deep_element_added)   (GstBin *bin, GstBin *sub_bin, GstElement *child);
+  void          (*deep_element_removed) (GstBin *bin, GstBin *sub_bin, GstElement *child);
+};
+
+

Subclasses can override the add_element + and remove_element + to +update the list of children in the bin.

+

The handle_message + method can be overridden to implement custom +message handling. handle_message + takes ownership of the message, just like +gst_element_post_message.

+

The deep_element_added + vfunc will be called when a new element has been +added to any bin inside this bin, so it will also be called if a new child +was added to a sub-bin of this bin. GstBin implementations that override +this message should chain up to the parent class implementation so the +element-added-deep signal is emitted on all parents.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

add_element ()

method to add an element to a bin

 

remove_element ()

method to remove an element from a bin

 

handle_message ()

method to handle a message from the children

 

deep_element_added ()

method called when an element was added somewhere +in the bin hierarchy

 

deep_element_removed ()

method called when an element was removed somewhere +in the bin hierarchy

 
+
+
+
+
+

enum GstBinFlags

+

GstBinFlags are a set of flags specific to bins. Most are set/used +internally. They can be checked using the GST_OBJECT_FLAG_IS_SET() macro, +and (un)set using GST_OBJECT_FLAG_SET() and GST_OBJECT_FLAG_UNSET().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_BIN_FLAG_NO_RESYNC

+

don't resync a state change when elements are + added or linked in the bin (Since 1.0.5)

+
 

GST_BIN_FLAG_STREAMS_AWARE

+

Indicates whether the bin can handle elements + that add/remove source pads at any point in time without + first posting a no-more-pads signal (Since 1.10)

+
 

GST_BIN_FLAG_LAST

+

the last enum in the series of flags for bins. +Derived classes can use this as first value in a list of flags.

+
 
+
+
+
+
+

Property Details

+
+

The “async-handling” property

+
  “async-handling”           gboolean
+

If set to TRUE, the bin will handle asynchronous state changes. +This should be used only if the bin subclass is modifying the state +of its children on its own.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “message-forward” property

+
  “message-forward”          gboolean
+

Forward all children messages, even those that would normally be filtered by +the bin. This can be interesting when one wants to be notified of the EOS +state of individual elements, for example.

+

The messages are converted to an ELEMENT message with the bin as the +source. The structure of the message is named 'GstBinForwarded' and contains +a field named 'message' of type GST_TYPE_MESSAGE that contains the original +forwarded message.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “deep-element-added” signal

+
void
+user_function (GstBin     *bin,
+               GstBin     *sub_bin,
+               GstElement *element,
+               gpointer    user_data)
+

Will be emitted after the element was added to sub_bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

bin

the GstBin

 

sub_bin

the GstBin the element was added to

 

element

the GstElement that was added to sub_bin +

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 1.10

+
+
+
+

The “deep-element-removed” signal

+
void
+user_function (GstBin     *bin,
+               GstBin     *sub_bin,
+               GstElement *element,
+               gpointer    user_data)
+

Will be emitted after the element was removed from sub_bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

bin

the GstBin

 

sub_bin

the GstBin the element was removed from

 

element

the GstElement that was removed from sub_bin +

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 1.10

+
+
+
+

The “do-latency” signal

+
gboolean
+user_function (GstBin  *bin,
+               gpointer user_data)
+

Will be emitted when the bin needs to perform latency calculations. This +signal is only emitted for toplevel bins or when async-handling is +enabled.

+

Only one signal handler is invoked. If no signals are connected, the +default handler is invoked, which will query and distribute the lowest +possible latency to all sinks.

+

Connect to this signal if the default latency calculations are not +sufficient, like when you need different latencies for different sinks in +the same pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the GstBin

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “element-added” signal

+
void
+user_function (GstBin     *bin,
+               GstElement *element,
+               gpointer    user_data)
+

Will be emitted after the element was added to the bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

the GstBin

 

element

the GstElement that was added to the bin

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “element-removed” signal

+
void
+user_function (GstBin     *bin,
+               GstElement *element,
+               gpointer    user_data)
+

Will be emitted after the element was removed from the bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

the GstBin

 

element

the GstElement that was removed from the bin

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstBuffer.html b/docs/gst/html/GstBuffer.html new file mode 100644 index 0000000..7ef102b --- /dev/null +++ b/docs/gst/html/GstBuffer.html @@ -0,0 +1,4261 @@ + + + + +GstBuffer: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBuffer

+

GstBuffer — Data-passing buffer type

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_BUFFER_FLAGS() +
#define +GST_BUFFER_FLAG_IS_SET() +
#define +GST_BUFFER_FLAG_SET() +
#define +GST_BUFFER_FLAG_UNSET() +
#define +GST_BUFFER_PTS() +
#define +GST_BUFFER_DTS() +
#define +GST_BUFFER_DTS_OR_PTS() +
#define +GST_BUFFER_DURATION() +
#define +GST_BUFFER_OFFSET() +
#define +GST_BUFFER_OFFSET_END() +
#define +GST_BUFFER_DURATION_IS_VALID() +
#define +GST_BUFFER_PTS_IS_VALID() +
#define +GST_BUFFER_DTS_IS_VALID() +
#define +GST_BUFFER_OFFSET_IS_VALID() +
#define +GST_BUFFER_OFFSET_END_IS_VALID() +
#define +GST_BUFFER_IS_DISCONT() +
+GstBuffer * + +gst_buffer_new () +
+GstBuffer * + +gst_buffer_new_allocate () +
+GstBuffer * + +gst_buffer_new_wrapped () +
+GstBuffer * + +gst_buffer_new_wrapped_full () +
+GstBuffer * + +gst_buffer_ref () +
+void + +gst_buffer_unref () +
+gsize + +gst_buffer_get_sizes () +
+gsize + +gst_buffer_get_size () +
+gsize + +gst_buffer_get_sizes_range () +
+gboolean + +gst_buffer_resize_range () +
+void + +gst_buffer_resize () +
+void + +gst_buffer_set_size () +
+guint + +gst_buffer_get_max_memory () +
+GstMemory * + +gst_buffer_peek_memory () +
+guint + +gst_buffer_n_memory () +
+void + +gst_buffer_insert_memory () +
+void + +gst_buffer_replace_memory_range () +
+GstMemory * + +gst_buffer_get_memory_range () +
+void + +gst_buffer_remove_memory_range () +
+gboolean + +gst_buffer_find_memory () +
+void + +gst_buffer_prepend_memory () +
+void + +gst_buffer_append_memory () +
+void + +gst_buffer_replace_memory () +
+void + +gst_buffer_replace_all_memory () +
+GstMemory * + +gst_buffer_get_memory () +
+GstMemory * + +gst_buffer_get_all_memory () +
+void + +gst_buffer_remove_memory () +
+void + +gst_buffer_remove_all_memory () +
+gboolean + +gst_buffer_is_all_memory_writable () +
+gboolean + +gst_buffer_is_memory_range_writable () +
+gboolean + +gst_buffer_map () +
+gboolean + +gst_buffer_map_range () +
+void + +gst_buffer_unmap () +
+gint + +gst_buffer_memcmp () +
+gsize + +gst_buffer_extract () +
+void + +gst_buffer_extract_dup () +
+gsize + +gst_buffer_fill () +
+gsize + +gst_buffer_memset () +
+GstBuffer * + +gst_buffer_copy () +
+gboolean + +gst_buffer_copy_into () +
+GstBuffer * + +gst_buffer_copy_region () +
+GstBuffer * + +gst_buffer_copy_deep () +
#define +gst_buffer_is_writable() +
#define +gst_buffer_make_writable() +
+gboolean + +gst_buffer_replace () +
+GstBuffer * + +gst_buffer_append () +
+GstBuffer * + +gst_buffer_append_region () +
+GstMeta * + +gst_buffer_get_meta () +
+guint + +gst_buffer_get_n_meta () +
+GstMeta * + +gst_buffer_add_meta () +
+gboolean + +gst_buffer_remove_meta () +
+GstMeta * + +gst_buffer_iterate_meta () +
+GstMeta * + +gst_buffer_iterate_meta_filtered () +
+gboolean + +(*GstBufferForeachMetaFunc) () +
+gboolean + +gst_buffer_foreach_meta () +
+GstParentBufferMeta * + +gst_buffer_add_parent_buffer_meta () +
#define +gst_buffer_get_parent_buffer_meta() +
+GstReferenceTimestampMeta * + +gst_buffer_add_reference_timestamp_meta () +
+GstReferenceTimestampMeta * + +gst_buffer_get_reference_timestamp_meta () +
+GstBufferFlags + +gst_buffer_get_flags () +
+gboolean + +gst_buffer_set_flags () +
+gboolean + +gst_buffer_unset_flags () +
+gboolean + +gst_buffer_has_flags () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstBuffer
enumGstBufferFlags
#defineGST_BUFFER_OFFSET_NONE
enumGstBufferCopyFlags
#defineGST_BUFFER_COPY_METADATA
#defineGST_BUFFER_COPY_ALL
structGstParentBufferMeta
structGstReferenceTimestampMeta
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstBuffer
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Buffers are the basic unit of data transfer in GStreamer. They contain the +timing and offset along with other arbitrary metadata that is associated +with the GstMemory blocks that the buffer contains.

+

Buffers are usually created with gst_buffer_new(). After a buffer has been +created one will typically allocate memory for it and add it to the buffer. +The following example creates a buffer that can hold a given video frame +with a given width, height and bits per plane.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
GstBuffer *buffer;
+GstMemory *memory;
+gint size, width, height, bpp;
+...
+size = width * height * bpp;
+buffer = gst_buffer_new ();
+memory = gst_allocator_alloc (NULL, size, NULL);
+gst_buffer_insert_memory (buffer, -1, memory);
+...
+
+ +

+

Alternatively, use gst_buffer_new_allocate() to create a buffer with +preallocated data of a given size.

+

Buffers can contain a list of GstMemory objects. You can retrieve how many +memory objects with gst_buffer_n_memory() and you can get a pointer +to memory with gst_buffer_peek_memory()

+

A buffer will usually have timestamps, and a duration, but neither of these +are guaranteed (they may be set to GST_CLOCK_TIME_NONE). Whenever a +meaningful value can be given for these, they should be set. The timestamps +and duration are measured in nanoseconds (they are GstClockTime values).

+

The buffer DTS refers to the timestamp when the buffer should be decoded and +is usually monotonically increasing. The buffer PTS refers to the timestamp when +the buffer content should be presented to the user and is not always +monotonically increasing.

+

A buffer can also have one or both of a start and an end offset. These are +media-type specific. For video buffers, the start offset will generally be +the frame number. For audio buffers, it will be the number of samples +produced so far. For compressed data, it could be the byte offset in a +source or destination file. Likewise, the end offset will be the offset of +the end of the buffer. These can only be meaningfully interpreted if you +know the media type of the buffer (the preceding CAPS event). Either or both +can be set to GST_BUFFER_OFFSET_NONE.

+

gst_buffer_ref() is used to increase the refcount of a buffer. This must be +done when you want to keep a handle to the buffer after pushing it to the +next element. The buffer refcount determines the writability of the buffer, a +buffer is only writable when the refcount is exactly 1, i.e. when the caller +has the only reference to the buffer.

+

To efficiently create a smaller buffer out of an existing one, you can +use gst_buffer_copy_region(). This method tries to share the memory objects +between the two buffers.

+

If a plug-in wants to modify the buffer data or metadata in-place, it should +first obtain a buffer that is safe to modify by using +gst_buffer_make_writable(). This function is optimized so that a copy will +only be made when it is necessary.

+

Several flags of the buffer can be set and unset with the +GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use +GST_BUFFER_FLAG_IS_SET() to test if a certain GstBufferFlags flag is set.

+

Buffers can be efficiently merged into a larger buffer with +gst_buffer_append(). Copying of memory will only be done when absolutely +needed.

+

Arbitrary extra metadata can be set on a buffer with gst_buffer_add_meta(). +Metadata can be retrieved with gst_buffer_get_meta(). See also GstMeta

+

An element should either unref the buffer or push it out on a src pad +using gst_pad_push() (see GstPad).

+

Buffers are usually freed by unreffing them with gst_buffer_unref(). When +the refcount drops to 0, any memory and metadata pointed to by the buffer is +unreffed as well. Buffers allocated from a GstBufferPool will be returned to +the pool when the refcount drops to 0.

+

The GstParentBufferMeta is a meta which can be attached to a GstBuffer +to hold a reference to another buffer that is only released when the child +GstBuffer is released.

+

Typically, GstParentBufferMeta is used when the child buffer is directly +using the GstMemory of the parent buffer, and wants to prevent the parent +buffer from being returned to a buffer pool until the GstMemory is available +for re-use. (Since 1.6)

+
+
+

Functions

+
+

GST_BUFFER_FLAGS()

+
#define GST_BUFFER_FLAGS(buf)                   GST_MINI_OBJECT_FLAGS(buf)
+
+

A flags word containing GstBufferFlags flags set on this buffer.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+
+
+

GST_BUFFER_FLAG_IS_SET()

+
#define GST_BUFFER_FLAG_IS_SET(buf,flag)        GST_MINI_OBJECT_FLAG_IS_SET (buf, flag)
+
+

Gives the status of a specific flag on a buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buf

a GstBuffer.

 

flag

the GstBufferFlags flag to check.

 
+
+
+
+
+

GST_BUFFER_FLAG_SET()

+
#define GST_BUFFER_FLAG_SET(buf,flag)           GST_MINI_OBJECT_FLAG_SET (buf, flag)
+
+

Sets a buffer flag on a buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buf

a GstBuffer.

 

flag

the GstBufferFlags flag to set.

 
+
+
+
+
+

GST_BUFFER_FLAG_UNSET()

+
#define GST_BUFFER_FLAG_UNSET(buf,flag)         GST_MINI_OBJECT_FLAG_UNSET (buf, flag)
+
+

Clears a buffer flag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buf

a GstBuffer.

 

flag

the GstBufferFlags flag to clear.

 
+
+
+
+
+

GST_BUFFER_PTS()

+
#define GST_BUFFER_PTS(buf)                     (GST_BUFFER_CAST(buf)->pts)
+
+

The presentation timestamp (pts) in nanoseconds (as a GstClockTime) +of the data in the buffer. This is the timestamp when the media should be +presented to the user. +Value will be GST_CLOCK_TIME_NONE if the pts is unknown.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.:

 
+
+
+
+
+

GST_BUFFER_DTS()

+
#define GST_BUFFER_DTS(buf)                     (GST_BUFFER_CAST(buf)->dts)
+
+

The decoding timestamp (dts) in nanoseconds (as a GstClockTime) +of the data in the buffer. This is the timestamp when the media should be +decoded or processed otherwise. +Value will be GST_CLOCK_TIME_NONE if the dts is unknown.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.:

 
+
+
+
+
+

GST_BUFFER_DTS_OR_PTS()

+
#define GST_BUFFER_DTS_OR_PTS(buf)              (GST_BUFFER_DTS_IS_VALID(buf) ? GST_BUFFER_DTS(buf) : GST_BUFFER_PTS (buf))
+
+

Returns the buffer decoding timestamp (dts) if valid, else the buffer +presentation time (pts)

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.:

 
+
+

Since: 1.8

+
+
+
+

GST_BUFFER_DURATION()

+
#define GST_BUFFER_DURATION(buf)                (GST_BUFFER_CAST(buf)->duration)
+
+

The duration in nanoseconds (as a GstClockTime) of the data in the buffer. +Value will be GST_CLOCK_TIME_NONE if the duration is unknown.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+
+
+

GST_BUFFER_OFFSET()

+
#define GST_BUFFER_OFFSET(buf)                  (GST_BUFFER_CAST(buf)->offset)
+
+

The offset in the source file of the beginning of this buffer.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+
+
+

GST_BUFFER_OFFSET_END()

+
#define GST_BUFFER_OFFSET_END(buf)              (GST_BUFFER_CAST(buf)->offset_end)
+
+

The offset in the source file of the end of this buffer.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+
+
+

GST_BUFFER_DURATION_IS_VALID()

+
#define GST_BUFFER_DURATION_IS_VALID(buffer)    (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
+
+

Tests if the duration is known.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

GST_BUFFER_PTS_IS_VALID()

+
#define GST_BUFFER_PTS_IS_VALID(buffer)   (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer)))
+
+

Tests if the pts is known.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

GST_BUFFER_DTS_IS_VALID()

+
#define GST_BUFFER_DTS_IS_VALID(buffer)   (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer)))
+
+

Tests if the dts is known.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

GST_BUFFER_OFFSET_IS_VALID()

+
#define GST_BUFFER_OFFSET_IS_VALID(buffer)      (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE)
+
+

Tests if the start offset is known.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

GST_BUFFER_OFFSET_END_IS_VALID()

+
#define GST_BUFFER_OFFSET_END_IS_VALID(buffer)  (GST_BUFFER_OFFSET_END (buffer) != GST_BUFFER_OFFSET_NONE)
+
+

Tests if the end offset is known.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

GST_BUFFER_IS_DISCONT()

+
#define GST_BUFFER_IS_DISCONT(buffer)   (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
+
+

Tests if the buffer marks a discontinuity in the stream.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+
+
+

gst_buffer_new ()

+
GstBuffer *
+gst_buffer_new (void);
+

Creates a newly allocated buffer without any data.

+

MT safe.

+
+

Returns

+

the new GstBuffer.

+

[transfer full]

+
+
+
+
+

gst_buffer_new_allocate ()

+
GstBuffer *
+gst_buffer_new_allocate (GstAllocator *allocator,
+                         gsize size,
+                         GstAllocationParams *params);
+

Tries to create a newly allocated buffer with data of the given size and +extra parameters from allocator +. If the requested amount of memory can't be +allocated, NULL will be returned. The allocated buffer memory is not cleared.

+

When allocator + is NULL, the default memory allocator will be used.

+

Note that when size + == 0, the buffer will not have memory associated with it.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

allocator

the GstAllocator to use, or NULL to use the +default allocator.

[transfer none][allow-none]

size

the size in bytes of the new buffer's data.

 

params

optional parameters.

[transfer none][allow-none]
+
+
+

Returns

+

a new GstBuffer, or NULL if +the memory couldn't be allocated.

+

[transfer full][nullable]

+
+
+
+
+

gst_buffer_new_wrapped ()

+
GstBuffer *
+gst_buffer_new_wrapped (gpointer data,
+                        gsize size);
+

Creates a new buffer that wraps the given data +. The memory will be freed +with g_free and will be marked writable.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

data to wrap.

[array length=size][element-type guint8][transfer full]

size

allocated size of data +

 
+
+
+

Returns

+

a new GstBuffer.

+

[transfer full]

+
+
+
+
+

gst_buffer_new_wrapped_full ()

+
GstBuffer *
+gst_buffer_new_wrapped_full (GstMemoryFlags flags,
+                             gpointer data,
+                             gsize maxsize,
+                             gsize offset,
+                             gsize size,
+                             gpointer user_data,
+                             GDestroyNotify notify);
+

Allocate a new buffer that wraps the given memory. data + must point to +maxsize + of memory, the wrapped buffer will have the region from offset + and +size + visible.

+

When the buffer is destroyed, notify + will be called with user_data +.

+

The prefix/padding must be filled with 0 if flags + contains +GST_MEMORY_FLAG_ZERO_PREFIXED and GST_MEMORY_FLAG_ZERO_PADDED respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

flags

GstMemoryFlags

 

data

data to wrap.

[array length=size][element-type guint8][transfer none]

maxsize

allocated size of data +

 

offset

offset in data +

 

size

size of valid data

 

user_data

user_data.

[allow-none]

notify

called with user_data +when the memory is freed.

[allow-none][scope async][closure user_data]
+
+
+

Returns

+

a new GstBuffer.

+

[transfer full]

+
+
+
+
+

gst_buffer_ref ()

+
GstBuffer *
+gst_buffer_ref (GstBuffer *buf);
+

Increases the refcount of the given buffer by one.

+

Note that the refcount affects the writability +of buf + and its metadata, see gst_buffer_is_writable(). +It is important to note that keeping additional references to +GstBuffer instances can potentially increase the number +of memcpy operations in a pipeline.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+

Returns

+

buf +.

+

[transfer full]

+
+
+
+
+

gst_buffer_unref ()

+
void
+gst_buffer_unref (GstBuffer *buf);
+

Decreases the refcount of the buffer. If the refcount reaches 0, the buffer +with the associated metadata and memory will be freed.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

[transfer full]
+
+
+
+
+

gst_buffer_get_sizes ()

+
gsize
+gst_buffer_get_sizes (GstBuffer *buffer,
+                      gsize *offset,
+                      gsize *maxsize);
+

Get the total size of the memory blocks in b +.

+

When not NULL, offset + will contain the offset of the data in the +first memory block in buffer + and maxsize + will contain the sum of +the size and offset + and the amount of extra padding on the last +memory block. offset + and maxsize + can be used to resize the +buffer memory blocks with gst_buffer_resize().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

a pointer to the offset.

[out][allow-none]

maxsize

a pointer to the maxsize.

[out][allow-none]
+
+
+

Returns

+

total size of the memory blocks in buffer +.

+
+
+
+
+

gst_buffer_get_size ()

+
gsize
+gst_buffer_get_size (GstBuffer *buffer);
+

Get the total size of the memory blocks in buffer +.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer.

 
+
+
+

Returns

+

total size of the memory blocks in buffer +.

+
+
+
+
+

gst_buffer_get_sizes_range ()

+
gsize
+gst_buffer_get_sizes_range (GstBuffer *buffer,
+                            guint idx,
+                            gint length,
+                            gsize *offset,
+                            gsize *maxsize);
+

Get the total size of length + memory blocks stating from idx + in buffer +.

+

When not NULL, offset + will contain the offset of the data in the +memory block in buffer + at idx + and maxsize + will contain the sum of the size +and offset + and the amount of extra padding on the memory block at idx + + +length + -1. +offset + and maxsize + can be used to resize the buffer memory blocks with +gst_buffer_resize_range().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length

 

offset

a pointer to the offset.

[out][allow-none]

maxsize

a pointer to the maxsize.

[out][allow-none]
+
+
+

Returns

+

total size of length +memory blocks starting at idx +in buffer +.

+
+
+
+
+

gst_buffer_resize_range ()

+
gboolean
+gst_buffer_resize_range (GstBuffer *buffer,
+                         guint idx,
+                         gint length,
+                         gssize offset,
+                         gssize size);
+

Set the total size of the length + memory blocks starting at idx + in +buffer +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length

 

offset

the offset adjustment

 

size

the new size or -1 to just adjust the offset

 
+
+
+

Returns

+

TRUE if resizing succeeded, FALSE otherwise.

+
+
+
+
+

gst_buffer_resize ()

+
void
+gst_buffer_resize (GstBuffer *buffer,
+                   gssize offset,
+                   gssize size);
+

Set the offset and total size of the memory blocks in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

the offset adjustment

 

size

the new size or -1 to just adjust the offset

 
+
+
+
+
+

gst_buffer_set_size ()

+
void
+gst_buffer_set_size (GstBuffer *buffer,
+                     gssize size);
+

Set the total size of the memory blocks in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

size

the new size

 
+
+
+
+
+

gst_buffer_get_max_memory ()

+
guint
+gst_buffer_get_max_memory (void);
+

Get the maximum amount of memory blocks that a buffer can hold. This is a +compile time constant that can be queried with the function.

+

When more memory blocks are added, existing memory blocks will be merged +together to make room for the new block.

+
+

Returns

+

the maximum amount of memory blocks that a buffer can hold.

+
+

Since: 1.2

+
+
+
+

gst_buffer_peek_memory ()

+
GstMemory *
+gst_buffer_peek_memory (GstBuffer *buffer,
+                        guint idx);
+

Get the memory block at idx + in buffer +. The memory block stays valid until +the memory block in buffer + is removed, replaced or merged, typically with +any call that modifies the memory in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 
+
+
+

Returns

+

the GstMemory at idx +.

+

[transfer none][nullable]

+
+
+
+
+

gst_buffer_n_memory ()

+
guint
+gst_buffer_n_memory (GstBuffer *buffer);
+

Get the amount of memory blocks that this buffer has. This amount is never +larger than what gst_buffer_get_max_memory() returns.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer.

 
+
+
+

Returns

+

the number of memory blocks this buffer is made of.

+
+
+
+
+

gst_buffer_insert_memory ()

+
void
+gst_buffer_insert_memory (GstBuffer *buffer,
+                          gint idx,
+                          GstMemory *mem);
+

Insert the memory block mem + to buffer + at idx +. This function takes ownership +of mem + and thus doesn't increase its refcount.

+

Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is +added, existing memory blocks will automatically be merged to make room for +the new memory.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

the index to add the memory at, or -1 to append it to the end

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_replace_memory_range ()

+
void
+gst_buffer_replace_memory_range (GstBuffer *buffer,
+                                 guint idx,
+                                 gint length,
+                                 GstMemory *mem);
+

Replaces length + memory blocks in buffer + starting at idx + with mem +.

+

If length + is -1, all memory starting from idx + will be removed and +replaced with mem +.

+

buffer + should be writable.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length should not be 0

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_get_memory_range ()

+
GstMemory *
+gst_buffer_get_memory_range (GstBuffer *buffer,
+                             guint idx,
+                             gint length);
+

Get length + memory blocks in buffer + starting at idx +. The memory blocks will +be merged into one large GstMemory.

+

If length + is -1, all memory starting from idx + is merged.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length

 
+
+
+

Returns

+

a GstMemory that contains the merged data of length +blocks starting at idx +. Use gst_memory_unref() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_buffer_remove_memory_range ()

+
void
+gst_buffer_remove_memory_range (GstBuffer *buffer,
+                                guint idx,
+                                gint length);
+

Remove length + memory blocks in buffer + starting from idx +.

+

length + can be -1, in which case all memory starting from idx + is removed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length

 
+
+
+
+
+

gst_buffer_find_memory ()

+
gboolean
+gst_buffer_find_memory (GstBuffer *buffer,
+                        gsize offset,
+                        gsize size,
+                        guint *idx,
+                        guint *length,
+                        gsize *skip);
+

Find the memory blocks that span size + bytes starting from offset + +in buffer +.

+

When this function returns TRUE, idx + will contain the index of the first +memory block where the byte for offset + can be found and length + contains the +number of memory blocks containing the size + remaining bytes. skip + contains +the number of bytes to skip in the memory block at idx + to get to the byte +for offset +.

+

size + can be -1 to get all the memory blocks after idx +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

an offset

 

size

a size

 

idx

pointer to index.

[out]

length

pointer to length.

[out]

skip

pointer to skip.

[out]
+
+
+

Returns

+

TRUE when size +bytes starting from offset +could be found in +buffer +and idx +, length +and skip +will be filled.

+
+
+
+
+

gst_buffer_prepend_memory ()

+
void
+gst_buffer_prepend_memory (GstBuffer *buffer,
+                           GstMemory *mem);
+

Prepend the memory block mem + to buffer +. This function takes +ownership of mem + and thus doesn't increase its refcount.

+

This function is identical to gst_buffer_insert_memory() with an index of 0. +See gst_buffer_insert_memory() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_append_memory ()

+
void
+gst_buffer_append_memory (GstBuffer *buffer,
+                          GstMemory *mem);
+

Append the memory block mem + to buffer +. This function takes +ownership of mem + and thus doesn't increase its refcount.

+

This function is identical to gst_buffer_insert_memory() with an index of -1. +See gst_buffer_insert_memory() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_replace_memory ()

+
void
+gst_buffer_replace_memory (GstBuffer *buffer,
+                           guint idx,
+                           GstMemory *mem);
+

Replaces the memory block at index idx + in buffer + with mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_replace_all_memory ()

+
void
+gst_buffer_replace_all_memory (GstBuffer *buffer,
+                               GstMemory *mem);
+

Replaces all memory in buffer + with mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

mem

a GstMemory.

[transfer full]
+
+
+
+
+

gst_buffer_get_memory ()

+
GstMemory *
+gst_buffer_get_memory (GstBuffer *buffer,
+                       guint idx);
+

Get the memory block at index idx + in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 
+
+
+

Returns

+

a GstMemory that contains the data of the +memory block at idx +. Use gst_memory_unref() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_buffer_get_all_memory ()

+
GstMemory *
+gst_buffer_get_all_memory (GstBuffer *buffer);
+

Get all the memory block in buffer +. The memory blocks will be merged +into one large GstMemory.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer.

 
+
+
+

Returns

+

a GstMemory that contains the merged memory. +Use gst_memory_unref() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_buffer_remove_memory ()

+
void
+gst_buffer_remove_memory (GstBuffer *buffer,
+                          guint idx);
+

Remove the memory block in b + at index i +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 
+
+
+
+
+

gst_buffer_remove_all_memory ()

+
void
+gst_buffer_remove_all_memory (GstBuffer *buffer);
+

Remove all the memory blocks in buffer +.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer.

 
+
+
+
+
+

gst_buffer_is_all_memory_writable ()

+
gboolean
+gst_buffer_is_all_memory_writable (GstBuffer *buffer);
+

Check if all memory blocks in buffer + are writable.

+

Note that this function does not check if buffer + is writable, use +gst_buffer_is_writable() to check that if needed.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer.

 
+
+
+

Returns

+

TRUE if all memory blocks in buffer +are writable

+
+

Since: 1.4

+
+
+
+

gst_buffer_is_memory_range_writable ()

+
gboolean
+gst_buffer_is_memory_range_writable (GstBuffer *buffer,
+                                     guint idx,
+                                     gint length);
+

Check if length + memory blocks in buffer + starting from idx + are writable.

+

length + can be -1 to check all the memory blocks after idx +.

+

Note that this function does not check if buffer + is writable, use +gst_buffer_is_writable() to check that if needed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length should not be 0

 
+
+
+

Returns

+

TRUE if the memory range is writable

+
+

Since: 1.4

+
+
+
+

gst_buffer_map ()

+
gboolean
+gst_buffer_map (GstBuffer *buffer,
+                GstMapInfo *info,
+                GstMapFlags flags);
+

This function fills info + with the GstMapInfo of all merged memory +blocks in buffer +.

+

flags + describe the desired access of the memory. When flags + is +GST_MAP_WRITE, buffer + should be writable (as returned from +gst_buffer_is_writable()).

+

When buffer + is writable but the memory isn't, a writable copy will +automatically be created and returned. The readonly copy of the +buffer memory will then also be replaced with this writable copy.

+

The memory in info + should be unmapped with gst_buffer_unmap() after +usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

info

info about the mapping.

[out]

flags

flags for the mapping

 
+
+
+

Returns

+

TRUE if the map succeeded and info +contains valid data.

+
+
+
+
+

gst_buffer_map_range ()

+
gboolean
+gst_buffer_map_range (GstBuffer *buffer,
+                      guint idx,
+                      gint length,
+                      GstMapInfo *info,
+                      GstMapFlags flags);
+

This function fills info + with the GstMapInfo of length + merged memory blocks +starting at idx + in buffer +. When length + is -1, all memory blocks starting +from idx + are merged and mapped.

+

flags + describe the desired access of the memory. When flags + is +GST_MAP_WRITE, buffer + should be writable (as returned from +gst_buffer_is_writable()).

+

When buffer + is writable but the memory isn't, a writable copy will +automatically be created and returned. The readonly copy of the buffer memory +will then also be replaced with this writable copy.

+

The memory in info + should be unmapped with gst_buffer_unmap() after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

idx

an index

 

length

a length

 

info

info about the mapping.

[out]

flags

flags for the mapping

 
+
+
+

Returns

+

TRUE if the map succeeded and info +contains valid +data.

+
+
+
+
+

gst_buffer_unmap ()

+
void
+gst_buffer_unmap (GstBuffer *buffer,
+                  GstMapInfo *info);
+

Release the memory previously mapped with gst_buffer_map().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

 

info

a GstMapInfo

 
+
+
+
+
+

gst_buffer_memcmp ()

+
gint
+gst_buffer_memcmp (GstBuffer *buffer,
+                   gsize offset,
+                   gconstpointer mem,
+                   gsize size);
+

Compare size + bytes starting from offset + in buffer + with the memory in mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

the offset in buffer +

 

mem

the memory to compare.

[array length=size][element-type guint8]

size

the size to compare

 
+
+
+

Returns

+

0 if the memory is equal.

+
+
+
+
+

gst_buffer_extract ()

+
gsize
+gst_buffer_extract (GstBuffer *buffer,
+                    gsize offset,
+                    gpointer dest,
+                    gsize size);
+

Copy size + bytes starting from offset + in buffer + to dest +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

the offset to extract

 

dest

the destination address.

[out caller-allocates][array length=size][element-type guint8]

size

the size to extract

 
+
+
+

Returns

+

The amount of bytes extracted. This value can be lower than size +when buffer +did not contain enough data.

+
+
+
+
+

gst_buffer_extract_dup ()

+
void
+gst_buffer_extract_dup (GstBuffer *buffer,
+                        gsize offset,
+                        gsize size,
+                        gpointer *dest,
+                        gsize *dest_size);
+

Extracts a copy of at most size + bytes the data at offset + into +newly-allocated memory. dest + must be freed using g_free() when done.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

offset

the offset to extract

 

size

the size to extract

 

dest

A pointer where +the destination array will be written. Might be NULL if the size is 0.

[array length=dest_size][element-type guint8][out]

dest_size

A location where the size of dest +can be written.

[out]
+
+

Since: 1.0.10

+
+
+
+

gst_buffer_fill ()

+
gsize
+gst_buffer_fill (GstBuffer *buffer,
+                 gsize offset,
+                 gconstpointer src,
+                 gsize size);
+

Copy size + bytes from src + to buffer + at offset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

the offset to fill

 

src

the source address.

[array length=size][element-type guint8]

size

the size to fill

 
+
+
+

Returns

+

The amount of bytes copied. This value can be lower than size +when buffer +did not contain enough data.

+
+
+
+
+

gst_buffer_memset ()

+
gsize
+gst_buffer_memset (GstBuffer *buffer,
+                   gsize offset,
+                   guint8 val,
+                   gsize size);
+

Fill buf + with size + bytes with val + starting from offset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

 

offset

the offset in buffer +

 

val

the value to set

 

size

the size to set

 
+
+
+

Returns

+

The amount of bytes filled. This value can be lower than size +when buffer +did not contain enough data.

+
+
+
+
+

gst_buffer_copy ()

+
GstBuffer *
+gst_buffer_copy (const GstBuffer *buf);
+

Create a copy of the given buffer. This will only copy the buffer's +data to a newly allocated memory if needed (if the type of memory +requires it), otherwise the underlying data is just referenced. +Check gst_buffer_copy_deep() if you want to force the data +to be copied to newly allocated memory.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+

Returns

+

a new copy of buf +.

+

[transfer full]

+
+
+
+
+

gst_buffer_copy_into ()

+
gboolean
+gst_buffer_copy_into (GstBuffer *dest,
+                      GstBuffer *src,
+                      GstBufferCopyFlags flags,
+                      gsize offset,
+                      gsize size);
+

Copies the information from src + into dest +.

+

If dest + already contains memory and flags + contains GST_BUFFER_COPY_MEMORY, +the memory from src + will be appended to dest +.

+

flags + indicate which fields will be copied.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

dest

a destination GstBuffer

 

src

a source GstBuffer

 

flags

flags indicating what metadata fields should be copied.

 

offset

offset to copy from

 

size

total size to copy. If -1, all data is copied.

 
+
+
+

Returns

+

TRUE if the copying succeeded, FALSE otherwise.

+
+
+
+
+

gst_buffer_copy_region ()

+
GstBuffer *
+gst_buffer_copy_region (GstBuffer *parent,
+                        GstBufferCopyFlags flags,
+                        gsize offset,
+                        gsize size);
+

Creates a sub-buffer from parent + at offset + and size +. +This sub-buffer uses the actual memory space of the parent buffer. +This function will copy the offset and timestamp fields when the +offset is 0. If not, they will be set to GST_CLOCK_TIME_NONE and +GST_BUFFER_OFFSET_NONE. +If offset + equals 0 and size + equals the total size of buffer +, the +duration and offset end fields are also copied. If not they will be set +to GST_CLOCK_TIME_NONE and GST_BUFFER_OFFSET_NONE.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

parent

a GstBuffer.

 

flags

the GstBufferCopyFlags

 

offset

the offset into parent GstBuffer at which the new sub-buffer +begins.

 

size

the size of the new GstBuffer sub-buffer, in bytes. If -1, all +data is copied.

 
+
+
+

Returns

+

the new GstBuffer or NULL if the arguments were +invalid.

+

[transfer full]

+
+
+
+
+

gst_buffer_copy_deep ()

+
GstBuffer *
+gst_buffer_copy_deep (const GstBuffer *buf);
+

Create a copy of the given buffer. This will make a newly allocated +copy of the data the source buffer contains.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

 
+
+
+

Returns

+

a new copy of buf +.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_buffer_is_writable()

+
#define         gst_buffer_is_writable(buf)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (buf))
+
+

Tests if you can safely write to a buffer's metadata or its memory array. +It is only safe to change buffer metadata when the current reference is +writable, i.e. nobody can see the modifications you will make.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer

 
+
+
+
+
+

gst_buffer_make_writable()

+
#define         gst_buffer_make_writable(buf)   GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (buf)))
+
+

Returns a writable copy of buf +. If the source buffer is +already writable, this will simply return the same buffer.

+

Use this function to ensure that a buffer can be safely modified before +making changes to it, including changing the metadata such as PTS/DTS.

+

If the reference count of the source buffer buf + is exactly one, the caller +is the sole owner and this function will return the buffer object unchanged.

+

If there is more than one reference on the object, a copy will be made using +gst_buffer_copy(). The passed-in buf + will be unreffed in that case, and the +caller will now own a reference to the new returned buffer object. Note +that this just copies the buffer structure itself, the underlying memory is +not copied if it can be shared amongst multiple buffers.

+

In short, this function unrefs the buf in the argument and refs the buffer +that it returns. Don't access the argument after calling this function unless +you have an additional reference to it.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer.

[transfer full]
+
+
+

Returns

+

a writable buffer which may or may not be the +same as buf +.

+

[transfer full]

+
+
+
+
+

gst_buffer_replace ()

+
gboolean
+gst_buffer_replace (GstBuffer **obuf,
+                    GstBuffer *nbuf);
+

Modifies a pointer to a GstBuffer to point to a different GstBuffer. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +buffer is unreffed, the new is reffed).

+

Either nbuf + or the GstBuffer pointed to by obuf + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obuf

pointer to a pointer to +a GstBuffer to be replaced.

[inout][transfer full][nullable]

nbuf

pointer to a GstBuffer that will +replace the buffer pointed to by obuf +.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE when obuf +was different from nbuf +.

+
+
+
+
+

gst_buffer_append ()

+
GstBuffer *
+gst_buffer_append (GstBuffer *buf1,
+                   GstBuffer *buf2);
+

Append all the memory from buf2 + to buf1 +. The result buffer will contain a +concatenation of the memory of buf1 + and buf2 +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buf1

the first source GstBuffer to append.

[transfer full]

buf2

the second source GstBuffer to append.

[transfer full]
+
+
+

Returns

+

the new GstBuffer that contains the memory +of the two source buffers.

+

[transfer full]

+
+
+
+
+

gst_buffer_append_region ()

+
GstBuffer *
+gst_buffer_append_region (GstBuffer *buf1,
+                          GstBuffer *buf2,
+                          gssize offset,
+                          gssize size);
+

Append size + bytes at offset + from buf2 + to buf1 +. The result buffer will +contain a concatenation of the memory of buf1 + and the requested region of +buf2 +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buf1

the first source GstBuffer to append.

[transfer full]

buf2

the second source GstBuffer to append.

[transfer full]

offset

the offset in buf2 +

 

size

the size or -1 of buf2 +

 
+
+
+

Returns

+

the new GstBuffer that contains the memory +of the two source buffers.

+

[transfer full]

+
+
+
+
+

gst_buffer_get_meta ()

+
GstMeta *
+gst_buffer_get_meta (GstBuffer *buffer,
+                     GType api);
+

Get the metadata for api + on buffer. When there is no such metadata, NULL is +returned. If multiple metadata with the given api + are attached to this +buffer only the first one is returned. To handle multiple metadata with a +given API use gst_buffer_iterate_meta() or gst_buffer_foreach_meta() instead +and check the meta->info.api member for the API type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

api

the GType of an API

 
+
+
+

Returns

+

the metadata for api +on +buffer +.

+

[transfer none][nullable]

+
+
+
+
+

gst_buffer_get_n_meta ()

+
guint
+gst_buffer_get_n_meta (GstBuffer *buffer,
+                       GType api_type);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

api_type

the GType of an API

 
+
+
+

Returns

+

number of metas of type api_type +on buffer +.

+
+

Since: 1.14

+
+
+
+

gst_buffer_add_meta ()

+
GstMeta *
+gst_buffer_add_meta (GstBuffer *buffer,
+                     const GstMetaInfo *info,
+                     gpointer params);
+

Add metadata for info + to buffer + using the parameters in params +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

info

a GstMetaInfo

 

params

params for info +

 
+
+
+

Returns

+

the metadata for the api in info +on buffer +.

+

[transfer none][nullable]

+
+
+
+
+

gst_buffer_remove_meta ()

+
gboolean
+gst_buffer_remove_meta (GstBuffer *buffer,
+                        GstMeta *meta);
+

Remove the metadata for meta + on buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

meta

a GstMeta

 
+
+
+

Returns

+

TRUE if the metadata existed and was removed, FALSE if no such +metadata was on buffer +.

+
+
+
+
+

gst_buffer_iterate_meta ()

+
GstMeta *
+gst_buffer_iterate_meta (GstBuffer *buffer,
+                         gpointer *state);
+

Retrieve the next GstMeta after current +. If state + points +to NULL, the first metadata is returned.

+

state + will be updated with an opaque state pointer

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

state

an opaque state pointer.

[out caller-allocates]
+
+
+

Returns

+

The next GstMeta or NULL +when there are no more items.

+

[transfer none][nullable]

+
+
+
+
+

gst_buffer_iterate_meta_filtered ()

+
GstMeta *
+gst_buffer_iterate_meta_filtered (GstBuffer *buffer,
+                                  gpointer *state,
+                                  GType meta_api_type);
+

Retrieve the next GstMeta of type meta_api_type + after the current one +according to state +. If state + points to NULL, the first metadata of +type meta_api_type + is returned.

+

state + will be updated with an opaque state pointer

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

state

an opaque state pointer.

[out caller-allocates]

meta_api_type

only return GstMeta of this type

 
+
+
+

Returns

+

The next GstMeta of type +meta_api_type +or NULL when there are no more items.

+

[transfer none][nullable]

+
+

Since: 1.12

+
+
+
+

GstBufferForeachMetaFunc ()

+
gboolean
+(*GstBufferForeachMetaFunc) (GstBuffer *buffer,
+                             GstMeta **meta,
+                             gpointer user_data);
+

A function that will be called from gst_buffer_foreach_meta(). The meta + +field will point to a the reference of the meta.

+

buffer + should not be modified from this callback.

+

When this function returns TRUE, the next meta will be +returned. When FALSE is returned, gst_buffer_foreach_meta() will return.

+

When meta + is set to NULL, the item will be removed from the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

meta

a pointer to a GstMeta.

[out][nullable]

user_data

user data passed to gst_buffer_foreach_meta()

 
+
+
+

Returns

+

FALSE when gst_buffer_foreach_meta() should stop

+
+
+
+
+

gst_buffer_foreach_meta ()

+
gboolean
+gst_buffer_foreach_meta (GstBuffer *buffer,
+                         GstBufferForeachMetaFunc func,
+                         gpointer user_data);
+

Call func + with user_data + for each meta in buffer +.

+

func + can modify the passed meta pointer or its contents. The return value +of func + define if this function returns or if the remaining metadata items +in the buffer should be skipped.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer

 

func

a GstBufferForeachMetaFunc to call.

[scope call]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

FALSE when func +returned FALSE for one of the metadata.

+
+
+
+
+

gst_buffer_add_parent_buffer_meta ()

+
GstParentBufferMeta *
+gst_buffer_add_parent_buffer_meta (GstBuffer *buffer,
+                                   GstBuffer *ref);
+

Add a GstParentBufferMeta to buffer + that holds a reference on +ref + until the buffer is freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer.

[transfer none]

ref

a GstBuffer to ref.

[transfer none]
+
+
+

Returns

+

The GstParentBufferMeta that was added to the buffer.

+

[transfer none][nullable]

+
+

Since: 1.6

+
+
+
+

gst_buffer_get_parent_buffer_meta()

+
#define             gst_buffer_get_parent_buffer_meta(b)
+

Find and return a GstParentBufferMeta if one exists on the +buffer

+
+

Parameters

+
+++++ + + + + + +

b

a GstBuffer

 
+
+
+
+
+

gst_buffer_add_reference_timestamp_meta ()

+
GstReferenceTimestampMeta *
+gst_buffer_add_reference_timestamp_meta
+                               (GstBuffer *buffer,
+                                GstCaps *reference,
+                                GstClockTime timestamp,
+                                GstClockTime duration);
+

Add a GstReferenceTimestampMeta to buffer + that holds a timestamp + and +optionally duration + based on a specific timestamp reference +. See the +documentation of GstReferenceTimestampMeta for details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

[transfer none]

reference

identifier for the timestamp reference.

[transfer none]

timestamp

timestamp

 

duration

duration, or GST_CLOCK_TIME_NONE

 
+
+
+

Returns

+

The GstReferenceTimestampMeta that was added to the buffer.

+

[transfer none][nullable]

+
+

Since: 1.14

+
+
+
+

gst_buffer_get_reference_timestamp_meta ()

+
GstReferenceTimestampMeta *
+gst_buffer_get_reference_timestamp_meta
+                               (GstBuffer *buffer,
+                                GstCaps *reference);
+

Find the first GstReferenceTimestampMeta on buffer + that conforms to +reference +. Conformance is tested by checking if the meta's reference is a +subset of reference +.

+

Buffers can contain multiple GstReferenceTimestampMeta metadata items.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

reference

a reference GstCaps.

[allow-none]
+
+
+

Returns

+

the GstReferenceTimestampMeta or NULL when there +is no such metadata on buffer +.

+

[transfer none][nullable]

+
+

Since: 1.14

+
+
+
+

gst_buffer_get_flags ()

+
GstBufferFlags
+gst_buffer_get_flags (GstBuffer *buffer);
+

Get the GstBufferFlags flags set on this buffer.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+

Returns

+

the flags set on this buffer.

+
+

Since: 1.10

+
+
+
+

gst_buffer_set_flags ()

+
gboolean
+gst_buffer_set_flags (GstBuffer *buffer,
+                      GstBufferFlags flags);
+

Sets one or more buffer flags on a buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

flags

the GstBufferFlags to set.

 
+
+
+

Returns

+

TRUE if flags +were successfully set on buffer.

+
+

Since: 1.10

+
+
+
+

gst_buffer_unset_flags ()

+
gboolean
+gst_buffer_unset_flags (GstBuffer *buffer,
+                        GstBufferFlags flags);
+

Clears one or more buffer flags.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

flags

the GstBufferFlags to clear

 
+
+
+

Returns

+

true if flags +is successfully cleared from buffer.

+
+

Since: 1.10

+
+
+
+

gst_buffer_has_flags ()

+
gboolean
+gst_buffer_has_flags (GstBuffer *buffer,
+                      GstBufferFlags flags);
+
+
+
+

Types and Values

+
+

struct GstBuffer

+
struct GstBuffer {
+  GstMiniObject          mini_object;
+
+  GstBufferPool         *pool;
+
+  /* timestamp */
+  GstClockTime           pts;
+  GstClockTime           dts;
+  GstClockTime           duration;
+
+  /* media specific offset */
+  guint64                offset;
+  guint64                offset_end;
+};
+
+

The structure of a GstBuffer. Use the associated macros to access the public +variables.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject mini_object;

the parent structure

 

GstBufferPool *pool;

pointer to the pool owner of the buffer

 

GstClockTime pts;

presentation timestamp of the buffer, can be GST_CLOCK_TIME_NONE when the +pts is not known or relevant. The pts contains the timestamp when the +media should be presented to the user.

 

GstClockTime dts;

decoding timestamp of the buffer, can be GST_CLOCK_TIME_NONE when the +dts is not known or relevant. The dts contains the timestamp when the +media should be processed.

 

GstClockTime duration;

duration in time of the buffer data, can be GST_CLOCK_TIME_NONE +when the duration is not known or relevant.

 

guint64 offset;

a media specific offset for the buffer data. +For video frames, this is the frame number of this buffer. +For audio samples, this is the offset of the first sample in this buffer. +For file data or compressed data this is the byte offset of the first +byte in this buffer.

 

guint64 offset_end;

the last offset contained in this buffer. It has the same +format as offset +.

 
+
+
+
+
+

enum GstBufferFlags

+

A set of buffer flags used to describe properties of a GstBuffer.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_BUFFER_FLAG_LIVE

+

the buffer is live data and should be discarded in + the PAUSED state.

+
 

GST_BUFFER_FLAG_DECODE_ONLY

+

the buffer contains data that should be dropped + because it will be clipped against the segment + boundaries or because it does not contain data + that should be shown to the user.

+
 

GST_BUFFER_FLAG_DISCONT

+

the buffer marks a data discontinuity in the stream. + This typically occurs after a seek or a dropped buffer + from a live or network source.

+
 

GST_BUFFER_FLAG_RESYNC

+

the buffer timestamps might have a discontinuity + and this buffer is a good point to resynchronize.

+
 

GST_BUFFER_FLAG_CORRUPTED

+

the buffer data is corrupted.

+
 

GST_BUFFER_FLAG_MARKER

+

the buffer contains a media specific marker. for + video this is typically the end of a frame boundary, for audio + this is usually the start of a talkspurt.

+
 

GST_BUFFER_FLAG_HEADER

+

the buffer contains header information that is + needed to decode the following data.

+
 

GST_BUFFER_FLAG_GAP

+

the buffer has been created to fill a gap in the + stream and contains media neutral data (elements can + switch to optimized code path that ignores the buffer + content).

+
 

GST_BUFFER_FLAG_DROPPABLE

+

the buffer can be dropped without breaking the + stream, for example to reduce bandwidth.

+
 

GST_BUFFER_FLAG_DELTA_UNIT

+

this unit cannot be decoded independently.

+
 

GST_BUFFER_FLAG_TAG_MEMORY

+

this flag is set when memory of the buffer + is added/removed

+
 

GST_BUFFER_FLAG_SYNC_AFTER

+

Elements which write to disk or permanent + storage should ensure the data is synced after + writing the contents of this buffer. (Since 1.6)

+
 

GST_BUFFER_FLAG_NON_DROPPABLE

+

This buffer is important and should not be dropped. + This can be used to mark important buffers, e.g. to flag + RTP packets carrying keyframes or codec setup data for RTP + Forward Error Correction purposes, or to prevent still video + frames from being dropped by elements due to QoS. (Since 1.14)

+
 

GST_BUFFER_FLAG_LAST

+

additional media specific flags can be added starting from + this flag.

+
 
+
+
+
+
+

GST_BUFFER_OFFSET_NONE

+
#define GST_BUFFER_OFFSET_NONE  ((guint64)-1)
+
+

Constant for no-offset return results.

+
+
+
+

enum GstBufferCopyFlags

+

A set of flags that can be provided to the gst_buffer_copy_into() +function to specify which items should be copied.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_BUFFER_COPY_NONE

+

copy nothing

+
 

GST_BUFFER_COPY_FLAGS

+

flag indicating that buffer flags should be copied

+
 

GST_BUFFER_COPY_TIMESTAMPS

+

flag indicating that buffer pts, dts, + duration, offset and offset_end should be copied

+
 

GST_BUFFER_COPY_META

+

flag indicating that buffer meta should be + copied

+
 

GST_BUFFER_COPY_MEMORY

+

flag indicating that buffer memory should be reffed + and appended to already existing memory. Unless the memory is marked as + NO_SHARE, no actual copy of the memory is made but it is simply reffed. + Add GST_BUFFER_COPY_DEEP + to force a real copy.

+
 

GST_BUFFER_COPY_MERGE

+

flag indicating that buffer memory should be + merged

+
 

GST_BUFFER_COPY_DEEP

+

flag indicating that memory should always be + copied instead of reffed (Since 1.2)

+
 
+
+
+
+
+

GST_BUFFER_COPY_METADATA

+
#define             GST_BUFFER_COPY_METADATA
+

Combination of all possible metadata fields that can be copied with +gst_buffer_copy_into().

+
+
+
+

GST_BUFFER_COPY_ALL

+
#define GST_BUFFER_COPY_ALL  ((GstBufferCopyFlags)(GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY))
+
+

Combination of all possible fields that can be copied with +gst_buffer_copy_into().

+
+
+
+

struct GstParentBufferMeta

+
struct GstParentBufferMeta {
+  GstMeta parent;
+
+  GstBuffer *buffer;
+};
+
+

The GstParentBufferMeta is a GstMeta which can be attached to a GstBuffer +to hold a reference to another buffer that is only released when the child +GstBuffer is released.

+

Typically, GstParentBufferMeta is used when the child buffer is directly +using the GstMemory of the parent buffer, and wants to prevent the parent +buffer from being returned to a buffer pool until the GstMemory is available +for re-use.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMeta parent;

the parent GstMeta structure

 

GstBuffer *buffer;

the GstBuffer on which a reference is being held.

 
+
+

Since: 1.6

+
+
+
+

struct GstReferenceTimestampMeta

+
struct GstReferenceTimestampMeta {
+  GstMeta parent;
+
+  GstCaps *reference;
+  GstClockTime timestamp, duration;
+};
+
+

GstReferenceTimestampMeta can be used to attach alternative timestamps and +possibly durations to a GstBuffer. These are generally not according to +the pipeline clock and could be e.g. the NTP timestamp when the media was +captured.

+

The reference is stored as a GstCaps in reference +. Examples of valid +references would be "timestamp/x-drivername-stream" for timestamps that are locally +generated by some driver named "drivername" when generating the stream, +e.g. based on a frame counter, or "timestamp/x-ntp, host=pool.ntp.org, +port=123" for timestamps based on a specific NTP server.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstMeta parent;

the parent GstMeta structure

 

GstCaps *reference;

identifier for the timestamp reference.

 

GstClockTime timestamp;

timestamp

 

GstClockTime duration;

duration, or GST_CLOCK_TIME_NONE

 
+
+

Since: 1.14

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstBufferList.html b/docs/gst/html/GstBufferList.html new file mode 100644 index 0000000..b063f12 --- /dev/null +++ b/docs/gst/html/GstBufferList.html @@ -0,0 +1,805 @@ + + + + +GstBufferList: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBufferList

+

GstBufferList — Lists of buffers for data-passing

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstBufferList * + +gst_buffer_list_new () +
+GstBufferList * + +gst_buffer_list_new_sized () +
+guint + +gst_buffer_list_length () +
#define +gst_buffer_list_add() +
+void + +gst_buffer_list_insert () +
+void + +gst_buffer_list_remove () +
+GstBufferList * + +gst_buffer_list_ref () +
+void + +gst_buffer_list_unref () +
+GstBufferList * + +gst_buffer_list_copy () +
+GstBufferList * + +gst_buffer_list_copy_deep () +
#define +gst_buffer_list_is_writable() +
#define +gst_buffer_list_make_writable() +
+gboolean + +(*GstBufferListFunc) () +
+gboolean + +gst_buffer_list_foreach () +
+GstBuffer * + +gst_buffer_list_get () +
+GstBuffer * + +gst_buffer_list_get_writable () +
+gsize + +gst_buffer_list_calculate_size () +
+
+
+

Types and Values

+
++++ + + + + +
 GstBufferList
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstBufferList
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Buffer lists are an object containing a list of buffers.

+

Buffer lists are created with gst_buffer_list_new() and filled with data +using a gst_buffer_list_insert().

+

Buffer lists can be pushed on a srcpad with gst_pad_push_list(). This is +interesting when multiple buffers need to be pushed in one go because it +can reduce the amount of overhead for pushing each buffer individually.

+
+
+

Functions

+
+

gst_buffer_list_new ()

+
GstBufferList *
+gst_buffer_list_new (void);
+

Creates a new, empty GstBufferList. The caller is responsible for unreffing +the returned GstBufferList.

+

Free-function: gst_buffer_list_unref

+
+

Returns

+

the new GstBufferList. gst_buffer_list_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_buffer_list_new_sized ()

+
GstBufferList *
+gst_buffer_list_new_sized (guint size);
+

Creates a new, empty GstBufferList. The caller is responsible for unreffing +the returned GstBufferList. The list will have size + space preallocated so +that memory reallocations can be avoided.

+

Free-function: gst_buffer_list_unref

+
+

Parameters

+
+++++ + + + + + +

size

an initial reserved size

 
+
+
+

Returns

+

the new GstBufferList. gst_buffer_list_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_buffer_list_length ()

+
guint
+gst_buffer_list_length (GstBufferList *list);
+

Returns the number of buffers in list +.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+

Returns

+

the number of buffers in the buffer list

+
+
+
+
+

gst_buffer_list_add()

+
#define gst_buffer_list_add(l,b) gst_buffer_list_insert((l),-1,(b));
+
+

Append b + at the end of l +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

l

a GstBufferList

 

b

a GstBuffer

 
+
+
+
+
+

gst_buffer_list_insert ()

+
void
+gst_buffer_list_insert (GstBufferList *list,
+                        gint idx,
+                        GstBuffer *buffer);
+

Insert buffer + at idx + in list +. Other buffers are moved to make room for +this new buffer.

+

A -1 value for idx + will append the buffer at the end.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstBufferList

 

idx

the index

 

buffer

a GstBuffer.

[transfer full]
+
+
+
+
+

gst_buffer_list_remove ()

+
void
+gst_buffer_list_remove (GstBufferList *list,
+                        guint idx,
+                        guint length);
+

Remove length + buffers starting from idx + in list +. The following buffers +are moved to close the gap.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstBufferList

 

idx

the index

 

length

the amount to remove

 
+
+
+
+
+

gst_buffer_list_ref ()

+
GstBufferList *
+gst_buffer_list_ref (GstBufferList *list);
+

Increases the refcount of the given buffer list by one.

+

Note that the refcount affects the writability of list + and its data, see +gst_buffer_list_make_writable(). It is important to note that keeping +additional references to GstBufferList instances can potentially increase +the number of memcpy operations in a pipeline.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+

Returns

+

list +.

+

[transfer full]

+
+
+
+
+

gst_buffer_list_unref ()

+
void
+gst_buffer_list_unref (GstBufferList *list);
+

Decreases the refcount of the buffer list. If the refcount reaches 0, the +buffer list will be freed.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList.

[transfer full]
+
+
+
+
+

gst_buffer_list_copy ()

+
GstBufferList *
+gst_buffer_list_copy (const GstBufferList *list);
+

Create a shallow copy of the given buffer list. This will make a newly +allocated copy of the source list with copies of buffer pointers. The +refcount of buffers pointed to will be increased by one.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+

Returns

+

a new copy of list +.

+

[transfer full]

+
+
+
+
+

gst_buffer_list_copy_deep ()

+
GstBufferList *
+gst_buffer_list_copy_deep (const GstBufferList *list);
+

Create a copy of the given buffer list. This will make a newly allocated +copy of the buffer that the source buffer list contains.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+

Returns

+

a new copy of list +.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_buffer_list_is_writable()

+
#define gst_buffer_list_is_writable(list) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (list))
+
+

Tests if you can safely add buffers and groups into a buffer list.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+
+
+

gst_buffer_list_make_writable()

+
#define gst_buffer_list_make_writable(list) GST_BUFFER_LIST_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (list)))
+
+

Makes a writable buffer list from the given buffer list. If the source buffer +list is already writable, this will simply return the same buffer list. A +copy will otherwise be made using gst_buffer_list_copy().

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList.

[transfer full]
+
+
+

Returns

+

a writable list, which may or may not be the +same as list +.

+

[transfer full]

+
+
+
+
+

GstBufferListFunc ()

+
gboolean
+(*GstBufferListFunc) (GstBuffer **buffer,
+                      guint idx,
+                      gpointer user_data);
+

A function that will be called from gst_buffer_list_foreach(). The buffer + +field will point to a the reference of the buffer at idx +.

+

When this function returns TRUE, the next buffer will be +returned. When FALSE is returned, gst_buffer_list_foreach() will return.

+

When buffer + is set to NULL, the item will be removed from the bufferlist. +When buffer + has been made writable, the new buffer reference can be assigned +to buffer +. This function is responsible for unreffing the old buffer when +removing or modifying.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

pointer the buffer.

[out][nullable]

idx

the index of buffer +

 

user_data

user data passed to gst_buffer_list_foreach()

 
+
+
+

Returns

+

FALSE when gst_buffer_list_foreach() should stop

+
+
+
+
+

gst_buffer_list_foreach ()

+
gboolean
+gst_buffer_list_foreach (GstBufferList *list,
+                         GstBufferListFunc func,
+                         gpointer user_data);
+

Call func + with data + for each buffer in list +.

+

func + can modify the passed buffer pointer or its contents. The return value +of func + define if this function returns or if the remaining buffers in +the list should be skipped.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstBufferList

 

func

a GstBufferListFunc to call.

[scope call]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

TRUE when func +returned TRUE for each buffer in list +or when +list +is empty.

+
+
+
+
+

gst_buffer_list_get ()

+
GstBuffer *
+gst_buffer_list_get (GstBufferList *list,
+                     guint idx);
+

Get the buffer at idx +.

+

You must make sure that idx + does not exceed the number of +buffers available.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

a GstBufferList

 

idx

the index

 
+
+
+

Returns

+

the buffer at idx +in group +or NULL when there is no buffer. The buffer remains valid as +long as list +is valid and buffer is not removed from the list.

+

[transfer none][nullable]

+
+
+
+
+

gst_buffer_list_get_writable ()

+
GstBuffer *
+gst_buffer_list_get_writable (GstBufferList *list,
+                              guint idx);
+

Gets the buffer at idx +, ensuring it is a writable buffer.

+

You must make sure that idx + does not exceed the number of +buffers available.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

a (writable) GstBufferList

 

idx

the index

 
+
+
+

Returns

+

the buffer at idx +in group +. +The returned buffer remains valid as long as list +is valid and +the buffer is not removed from the list.

+

[transfer none][nullable]

+
+

Since: 1.14

+
+
+
+

gst_buffer_list_calculate_size ()

+
gsize
+gst_buffer_list_calculate_size (GstBufferList *list);
+

Calculates the size of the data contained in buffer list by adding the +size of all buffers.

+
+

Parameters

+
+++++ + + + + + +

list

a GstBufferList

 
+
+
+

Returns

+

the size of the data contained in buffer list in bytes.

+
+

Since: 1.14

+
+
+
+

Types and Values

+
+

GstBufferList

+
typedef struct _GstBufferList GstBufferList;
+

Opaque list of grouped buffers.

+
+
+
+

See Also

+

GstPad, GstMiniObject

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstBufferPool.html b/docs/gst/html/GstBufferPool.html new file mode 100644 index 0000000..e1fd0f4 --- /dev/null +++ b/docs/gst/html/GstBufferPool.html @@ -0,0 +1,1290 @@ + + + + +GstBufferPool: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBufferPool

+

GstBufferPool — Pool for buffers

+
+ +
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
 GstBufferPool
structGstBufferPoolClass
enumGstBufferPoolAcquireFlags
structGstBufferPoolAcquireParams
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstBufferPool
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstBufferPool is an object that can be used to pre-allocate and recycle +buffers of the same size and with the same properties.

+

A GstBufferPool is created with gst_buffer_pool_new().

+

Once a pool is created, it needs to be configured. A call to +gst_buffer_pool_get_config() returns the current configuration structure from +the pool. With gst_buffer_pool_config_set_params() and +gst_buffer_pool_config_set_allocator() the bufferpool parameters and +allocator can be configured. Other properties can be configured in the pool +depending on the pool implementation.

+

A bufferpool can have extra options that can be enabled with +gst_buffer_pool_config_add_option(). The available options can be retrieved +with gst_buffer_pool_get_options(). Some options allow for additional +configuration properties to be set.

+

After the configuration structure has been configured, +gst_buffer_pool_set_config() updates the configuration in the pool. This can +fail when the configuration structure is not accepted.

+

After the a pool has been configured, it can be activated with +gst_buffer_pool_set_active(). This will preallocate the configured resources +in the pool.

+

When the pool is active, gst_buffer_pool_acquire_buffer() can be used to +retrieve a buffer from the pool.

+

Buffers allocated from a bufferpool will automatically be returned to the +pool with gst_buffer_pool_release_buffer() when their refcount drops to 0.

+

The bufferpool can be deactivated again with gst_buffer_pool_set_active(). +All further gst_buffer_pool_acquire_buffer() calls will return an error. When +all buffers are returned to the pool they will be freed.

+

Use gst_object_unref() to release the reference to a bufferpool. If the +refcount of the pool reaches 0, the pool will be freed.

+
+
+

Functions

+
+

GST_BUFFER_POOL_IS_FLUSHING()

+
#define GST_BUFFER_POOL_IS_FLUSHING(pool)  (g_atomic_int_get (&pool->flushing))
+
+

Check if the bufferpool is flushing. Subclasses might want to check the +state of the pool in the acquire function.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstBufferPool

 
+
+
+
+
+

gst_buffer_pool_new ()

+
GstBufferPool *
+gst_buffer_pool_new (void);
+

Creates a new GstBufferPool instance.

+
+

Returns

+

a new GstBufferPool instance.

+

[transfer full]

+
+
+
+
+

gst_buffer_pool_config_get_params ()

+
gboolean
+gst_buffer_pool_config_get_params (GstStructure *config,
+                                   GstCaps **caps,
+                                   guint *size,
+                                   guint *min_buffers,
+                                   guint *max_buffers);
+

Get the configuration values from config +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

config

a GstBufferPool configuration.

[transfer none]

caps

the caps of buffers.

[out][transfer none][allow-none]

size

the size of each buffer, not including prefix and padding.

[out][allow-none]

min_buffers

the minimum amount of buffers to allocate.

[out][allow-none]

max_buffers

the maximum amount of buffers to allocate or 0 for unlimited.

[out][allow-none]
+
+
+

Returns

+

TRUE if all parameters could be fetched.

+
+
+
+
+

gst_buffer_pool_config_set_params ()

+
void
+gst_buffer_pool_config_set_params (GstStructure *config,
+                                   GstCaps *caps,
+                                   guint size,
+                                   guint min_buffers,
+                                   guint max_buffers);
+

Configure config + with the given parameters.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

config

a GstBufferPool configuration

 

caps

caps for the buffers

 

size

the size of each buffer, not including prefix and padding

 

min_buffers

the minimum amount of buffers to allocate.

 

max_buffers

the maximum amount of buffers to allocate or 0 for unlimited.

 
+
+
+
+
+

gst_buffer_pool_config_validate_params ()

+
gboolean
+gst_buffer_pool_config_validate_params
+                               (GstStructure *config,
+                                GstCaps *caps,
+                                guint size,
+                                guint min_buffers,
+                                guint max_buffers);
+

Validate that changes made to config + are still valid in the context of the +expected parameters. This function is a helper that can be used to validate +changes made by a pool to a config when gst_buffer_pool_set_config() +returns FALSE. This expects that caps + haven't changed and that +min_buffers + aren't lower then what we initially expected. +This does not check if options or allocator parameters are still valid, +won't check if size have changed, since changing the size is valid to adapt +padding.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

config

a GstBufferPool configuration.

[transfer none]

caps

the excepted caps of buffers.

[transfer none]

size

the expected size of each buffer, not including prefix and padding

 

min_buffers

the expected minimum amount of buffers to allocate.

 

max_buffers

the expect maximum amount of buffers to allocate or 0 for unlimited.

 
+
+
+

Returns

+

TRUE, if the parameters are valid in this context.

+
+

Since: 1.4

+
+
+
+

gst_buffer_pool_config_get_allocator ()

+
gboolean
+gst_buffer_pool_config_get_allocator (GstStructure *config,
+                                      GstAllocator **allocator,
+                                      GstAllocationParams *params);
+

Get the allocator + and params + from config +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

config

a GstBufferPool configuration.

[transfer none]

allocator

a GstAllocator, or NULL.

[out][allow-none][transfer none]

params

GstAllocationParams, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE, if the values are set.

+
+
+
+
+

gst_buffer_pool_config_set_allocator ()

+
void
+gst_buffer_pool_config_set_allocator (GstStructure *config,
+                                      GstAllocator *allocator,
+                                      const GstAllocationParams *params);
+

Set the allocator + and params + on config +.

+

One of allocator + and params + can be NULL, but not both. When allocator + +is NULL, the default allocator of the pool will use the values in param + +to perform its allocation. When param + is NULL, the pool will use the +provided allocator + with its default GstAllocationParams.

+

A call to gst_buffer_pool_set_config() can update the allocator and params +with the values that it is able to do. Some pools are, for example, not able +to operate with different allocators or cannot allocate with the values +specified in params +. Use gst_buffer_pool_get_config() to get the currently +used values.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

config

a GstBufferPool configuration

 

allocator

a GstAllocator.

[allow-none]

params

GstAllocationParams.

[allow-none]
+
+
+
+
+

gst_buffer_pool_config_n_options ()

+
guint
+gst_buffer_pool_config_n_options (GstStructure *config);
+

Retrieve the number of values currently stored in the options array of the +config + structure.

+
+

Parameters

+
+++++ + + + + + +

config

a GstBufferPool configuration

 
+
+
+

Returns

+

the options array size as a guint.

+
+
+
+
+

gst_buffer_pool_config_add_option ()

+
void
+gst_buffer_pool_config_add_option (GstStructure *config,
+                                   const gchar *option);
+

Enabled the option in config +. This will instruct the bufferpool + to enable +the specified option on the buffers that it allocates.

+

The supported options by pool + can be retrieved with gst_buffer_pool_get_options().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

config

a GstBufferPool configuration

 

option

an option to add

 
+
+
+
+
+

gst_buffer_pool_config_get_option ()

+
const gchar *
+gst_buffer_pool_config_get_option (GstStructure *config,
+                                   guint index);
+

Parse an available config + and get the option at index + of the options API +array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

config

a GstBufferPool configuration

 

index

position in the option array to read

 
+
+
+

Returns

+

a gchar of the option at index +.

+
+
+
+
+

gst_buffer_pool_config_has_option ()

+
gboolean
+gst_buffer_pool_config_has_option (GstStructure *config,
+                                   const gchar *option);
+

Check if config + contains option +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

config

a GstBufferPool configuration

 

option

an option

 
+
+
+

Returns

+

TRUE if the options array contains option +.

+
+
+
+
+

gst_buffer_pool_get_options ()

+
const gchar **
+gst_buffer_pool_get_options (GstBufferPool *pool);
+

Get a NULL terminated array of string with supported bufferpool options for +pool +. An option would typically be enabled with +gst_buffer_pool_config_add_option().

+
+

Parameters

+
+++++ + + + + + +

pool

a GstBufferPool

 
+
+
+

Returns

+

a NULL terminated array +of strings.

+

[array zero-terminated=1][transfer none]

+
+
+
+
+

gst_buffer_pool_has_option ()

+
gboolean
+gst_buffer_pool_has_option (GstBufferPool *pool,
+                            const gchar *option);
+

Check if the bufferpool supports option +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstBufferPool

 

option

an option

 
+
+
+

Returns

+

TRUE if the buffer pool contains option +.

+
+
+
+
+

gst_buffer_pool_get_config ()

+
GstStructure *
+gst_buffer_pool_get_config (GstBufferPool *pool);
+

Get a copy of the current configuration of the pool. This configuration +can either be modified and used for the gst_buffer_pool_set_config() call +or it must be freed after usage.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstBufferPool

 
+
+
+

Returns

+

a copy of the current configuration of pool +. use +gst_structure_free() after usage or gst_buffer_pool_set_config().

+

[transfer full]

+
+
+
+
+

gst_buffer_pool_set_config ()

+
gboolean
+gst_buffer_pool_set_config (GstBufferPool *pool,
+                            GstStructure *config);
+

Set the configuration of the pool. If the pool is already configured, and +the configuration haven't change, this function will return TRUE. If the +pool is active, this method will return FALSE and active configuration +will remain. Buffers allocated form this pool must be returned or else this +function will do nothing and return FALSE.

+

config + is a GstStructure that contains the configuration parameters for +the pool. A default and mandatory set of parameters can be configured with +gst_buffer_pool_config_set_params(), gst_buffer_pool_config_set_allocator() +and gst_buffer_pool_config_add_option().

+

If the parameters in config + can not be set exactly, this function returns +FALSE and will try to update as much state as possible. The new state can +then be retrieved and refined with gst_buffer_pool_get_config().

+

This function takes ownership of config +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstBufferPool

 

config

a GstStructure.

[transfer full]
+
+
+

Returns

+

TRUE when the configuration could be set.

+
+
+
+
+

gst_buffer_pool_set_active ()

+
gboolean
+gst_buffer_pool_set_active (GstBufferPool *pool,
+                            gboolean active);
+

Control the active state of pool +. When the pool is inactive, new calls to +gst_buffer_pool_acquire_buffer() will return with GST_FLOW_FLUSHING.

+

Activating the bufferpool will preallocate all resources in the pool based on +the configuration of the pool.

+

Deactivating will free the resources again when there are no outstanding +buffers. When there are outstanding buffers, they will be freed as soon as +they are all returned to the pool.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstBufferPool

 

active

the new active state

 
+
+
+

Returns

+

FALSE when the pool was not configured or when preallocation of the +buffers failed.

+
+
+
+
+

gst_buffer_pool_is_active ()

+
gboolean
+gst_buffer_pool_is_active (GstBufferPool *pool);
+

Check if pool + is active. A pool can be activated with the +gst_buffer_pool_set_active() call.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstBufferPool

 
+
+
+

Returns

+

TRUE when the pool is active.

+
+
+
+
+

gst_buffer_pool_set_flushing ()

+
void
+gst_buffer_pool_set_flushing (GstBufferPool *pool,
+                              gboolean flushing);
+

Enable or disable the flushing state of a pool + without freeing or +allocating buffers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstBufferPool

 

flushing

whether to start or stop flushing

 
+
+

Since: 1.4

+
+
+
+

gst_buffer_pool_acquire_buffer ()

+
GstFlowReturn
+gst_buffer_pool_acquire_buffer (GstBufferPool *pool,
+                                GstBuffer **buffer,
+                                GstBufferPoolAcquireParams *params);
+

Acquire a buffer from pool +. buffer + should point to a memory location that +can hold a pointer to the new buffer.

+

params + can be NULL or contain optional parameters to influence the +allocation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pool

a GstBufferPool

 

buffer

a location for a GstBuffer.

[out]

params

parameters.

[transfer none][allow-none]
+
+
+

Returns

+

a GstFlowReturn such as GST_FLOW_FLUSHING when the pool is +inactive.

+
+
+
+
+

gst_buffer_pool_release_buffer ()

+
void
+gst_buffer_pool_release_buffer (GstBufferPool *pool,
+                                GstBuffer *buffer);
+

Release buffer + to pool +. buffer + should have previously been allocated from +pool + with gst_buffer_pool_acquire_buffer().

+

This function is usually called automatically when the last ref on buffer + +disappears.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstBufferPool

 

buffer

a GstBuffer.

[transfer full]
+
+
+
+
+

Types and Values

+
+

GstBufferPool

+
typedef struct _GstBufferPool GstBufferPool;
+

The structure of a GstBufferPool. Use the associated macros to access the public +variables.

+
+
+
+

struct GstBufferPoolClass

+
struct GstBufferPoolClass {
+  GstObjectClass    object_class;
+
+  const gchar ** (*get_options)    (GstBufferPool *pool);
+  gboolean       (*set_config)     (GstBufferPool *pool, GstStructure *config);
+
+  gboolean       (*start)          (GstBufferPool *pool);
+  gboolean       (*stop)           (GstBufferPool *pool);
+
+  GstFlowReturn  (*acquire_buffer) (GstBufferPool *pool, GstBuffer **buffer,
+                                    GstBufferPoolAcquireParams *params);
+  GstFlowReturn  (*alloc_buffer)   (GstBufferPool *pool, GstBuffer **buffer,
+                                    GstBufferPoolAcquireParams *params);
+  void           (*reset_buffer)   (GstBufferPool *pool, GstBuffer *buffer);
+  void           (*release_buffer) (GstBufferPool *pool, GstBuffer *buffer);
+  void           (*free_buffer)    (GstBufferPool *pool, GstBuffer *buffer);
+  void           (*flush_start)    (GstBufferPool *pool);
+  void           (*flush_stop)     (GstBufferPool *pool);
+};
+
+

The GstBufferPool class.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstObjectClass object_class;

Object parent class

 

get_options ()

get a list of options supported by this pool

 

set_config ()

apply the bufferpool configuration. The default configuration +will parse the default config parameters

 

start ()

start the bufferpool. The default implementation will preallocate +min-buffers buffers and put them in the queue

 

stop ()

stop the bufferpool. the default implementation will free the +preallocated buffers. This function is called when all the buffers are +returned to the pool.

 

acquire_buffer ()

get a new buffer from the pool. The default implementation +will take a buffer from the queue and optionally wait for a buffer to +be released when there are no buffers available.

 

alloc_buffer ()

allocate a buffer. the default implementation allocates +buffers from the configured memory allocator and with the configured +parameters. All metadata that is present on the allocated buffer will +be marked as GST_META_FLAG_POOLED and GST_META_FLAG_LOCKED and will +not be removed from the buffer in reset_buffer +. The buffer should +have the GST_BUFFER_FLAG_TAG_MEMORY cleared.

 

reset_buffer ()

reset the buffer to its state when it was freshly allocated. +The default implementation will clear the flags, timestamps and +will remove the metadata without the GST_META_FLAG_POOLED flag (even +the metadata with GST_META_FLAG_LOCKED). If the +GST_BUFFER_FLAG_TAG_MEMORY was set, this function can also try to +restore the memory and clear the GST_BUFFER_FLAG_TAG_MEMORY again.

 

release_buffer ()

release a buffer back in the pool. The default +implementation will put the buffer back in the queue and notify any +blocking acquire_buffer calls when the GST_BUFFER_FLAG_TAG_MEMORY +is not set on the buffer. If GST_BUFFER_FLAG_TAG_MEMORY is set, the +buffer will be freed with free_buffer +.

 

free_buffer ()

free a buffer. The default implementation unrefs the buffer.

 

flush_start ()

enter the flushing state. (Since 1.4)

 

flush_stop ()

leave the flushign state. (Since 1.4)

 
+
+
+
+
+

enum GstBufferPoolAcquireFlags

+

Additional flags to control the allocation of a buffer

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_BUFFER_POOL_ACQUIRE_FLAG_NONE

+

no flags

+
 

GST_BUFFER_POOL_ACQUIRE_FLAG_KEY_UNIT

+

buffer is keyframe

+
 

GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT

+

when the bufferpool is empty, acquire_buffer +will by default block until a buffer is released into the pool again. Setting +this flag makes acquire_buffer return GST_FLOW_EOS instead of blocking.

+
 

GST_BUFFER_POOL_ACQUIRE_FLAG_DISCONT

+

buffer is discont

+
 

GST_BUFFER_POOL_ACQUIRE_FLAG_LAST

+

last flag, subclasses can use private flags + starting from this value.

+
 
+
+
+
+
+

struct GstBufferPoolAcquireParams

+
struct GstBufferPoolAcquireParams {
+  GstFormat                 format;
+  gint64                    start;
+  gint64                    stop;
+  GstBufferPoolAcquireFlags flags;
+};
+
+

Parameters passed to the gst_buffer_pool_acquire_buffer() function to control the +allocation of the buffer.

+

The default implementation ignores the start + and stop + members but other +implementations can use this extra information to decide what buffer to +return.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstFormat format;

the format of start +and stop +

 

gint64 start;

the start position

 

gint64 stop;

the stop position

 

GstBufferPoolAcquireFlags flags;

additional flags

 
+
+
+
+
+

See Also

+

GstBuffer

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstBus.html b/docs/gst/html/GstBus.html new file mode 100644 index 0000000..2f489b0 --- /dev/null +++ b/docs/gst/html/GstBus.html @@ -0,0 +1,1551 @@ + + + + +GstBus: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBus

+

GstBus — Asynchronous message bus subsystem

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +(*GstBusFunc) () +
+GstBusSyncReply + +(*GstBusSyncHandler) () +
+GstBus * + +gst_bus_new () +
+gboolean + +gst_bus_post () +
+gboolean + +gst_bus_have_pending () +
+GstMessage * + +gst_bus_peek () +
+GstMessage * + +gst_bus_pop () +
+GstMessage * + +gst_bus_pop_filtered () +
+GstMessage * + +gst_bus_timed_pop () +
+GstMessage * + +gst_bus_timed_pop_filtered () +
+void + +gst_bus_set_flushing () +
+void + +gst_bus_set_sync_handler () +
+GstBusSyncReply + +gst_bus_sync_signal_handler () +
+void + +gst_bus_get_pollfd () +
+GSource * + +gst_bus_create_watch () +
+guint + +gst_bus_add_watch_full () +
+guint + +gst_bus_add_watch () +
+gboolean + +gst_bus_remove_watch () +
+void + +gst_bus_disable_sync_message_emission () +
+void + +gst_bus_enable_sync_message_emission () +
+gboolean + +gst_bus_async_signal_func () +
+void + +gst_bus_add_signal_watch () +
+void + +gst_bus_add_signal_watch_full () +
+void + +gst_bus_remove_signal_watch () +
+GstMessage * + +gst_bus_poll () +
+
+
+

Properties

+
+++++ + + + + + +
gbooleanenable-asyncWrite / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidmessageHas Details
voidsync-messageHas Details
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstBus
enumGstBusFlags
enumGstBusSyncReply
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstBus
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

The GstBus is an object responsible for delivering GstMessage packets in +a first-in first-out way from the streaming threads (see GstTask) to the +application.

+

Since the application typically only wants to deal with delivery of these +messages from one thread, the GstBus will marshall the messages between +different threads. This is important since the actual streaming of media +is done in another thread than the application.

+

The GstBus provides support for GSource based notifications. This makes it +possible to handle the delivery in the glib mainloop.

+

The GSource callback function gst_bus_async_signal_func() can be used to +convert all bus messages into signal emissions.

+

A message is posted on the bus with the gst_bus_post() method. With the +gst_bus_peek() and gst_bus_pop() methods one can look at or retrieve a +previously posted message.

+

The bus can be polled with the gst_bus_poll() method. This methods blocks +up to the specified timeout value until one of the specified messages types +is posted on the bus. The application can then gst_bus_pop() the messages +from the bus to handle them. +Alternatively the application can register an asynchronous bus function +using gst_bus_add_watch_full() or gst_bus_add_watch(). This function will +install a GSource in the default glib main loop and will deliver messages +a short while after they have been posted. Note that the main loop should +be running for the asynchronous callbacks.

+

It is also possible to get messages from the bus without any thread +marshalling with the gst_bus_set_sync_handler() method. This makes it +possible to react to a message in the same thread that posted the +message on the bus. This should only be used if the application is able +to deal with messages from different threads.

+

Every GstPipeline has one bus.

+

Note that a GstPipeline will set its bus into flushing state when changing +from READY to NULL state.

+
+
+

Functions

+
+

GstBusFunc ()

+
gboolean
+(*GstBusFunc) (GstBus *bus,
+               GstMessage *message,
+               gpointer user_data);
+

Specifies the type of function passed to gst_bus_add_watch() or +gst_bus_add_watch_full(), which is called from the mainloop when a message +is available on the bus.

+

The message passed to the function will be unreffed after execution of this +function so it should not be freed in the function.

+

Note that this function is used as a GSourceFunc which means that returning +FALSE will remove the GSource from the mainloop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

the GstBus that sent the message

 

message

the GstMessage

 

user_data

user data that has been given, when registering the handler

 
+
+
+

Returns

+

FALSE if the event source should be removed.

+
+
+
+
+

GstBusSyncHandler ()

+
GstBusSyncReply
+(*GstBusSyncHandler) (GstBus *bus,
+                      GstMessage *message,
+                      gpointer user_data);
+

Handler will be invoked synchronously, when a new message has been injected +into the bus. This function is mostly used internally. Only one sync handler +can be attached to a given bus.

+

If the handler returns GST_BUS_DROP, it should unref the message, else the +message should not be unreffed by the sync handler.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

the GstBus that sent the message

 

message

the GstMessage

 

user_data

user data that has been given, when registering the handler

 
+
+
+

Returns

+

GstBusSyncReply stating what to do with the message

+
+
+
+
+

gst_bus_new ()

+
GstBus *
+gst_bus_new (void);
+

Creates a new GstBus instance.

+
+

Returns

+

a new GstBus instance.

+

[transfer full]

+
+
+
+
+

gst_bus_post ()

+
gboolean
+gst_bus_post (GstBus *bus,
+              GstMessage *message);
+

Post a message on the given bus. Ownership of the message +is taken by the bus.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

a GstBus to post on

 

message

the GstMessage to post.

[transfer full]
+
+
+

Returns

+

TRUE if the message could be posted, FALSE if the bus is flushing.

+

MT safe.

+
+
+
+
+

gst_bus_have_pending ()

+
gboolean
+gst_bus_have_pending (GstBus *bus);
+

Check if there are pending messages on the bus that +should be handled.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus to check

 
+
+
+

Returns

+

TRUE if there are messages on the bus to be handled, FALSE +otherwise.

+

MT safe.

+
+
+
+
+

gst_bus_peek ()

+
GstMessage *
+gst_bus_peek (GstBus *bus);
+

Peek the message on the top of the bus' queue. The message will remain +on the bus' message queue. A reference is returned, and needs to be unreffed +by the caller.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus

 
+
+
+

Returns

+

the GstMessage that is on the +bus, or NULL if the bus is empty.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_pop ()

+
GstMessage *
+gst_bus_pop (GstBus *bus);
+

Get a message from the bus.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus to pop

 
+
+
+

Returns

+

the GstMessage that is on the +bus, or NULL if the bus is empty. The message is taken from +the bus and needs to be unreffed with gst_message_unref() after +usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_pop_filtered ()

+
GstMessage *
+gst_bus_pop_filtered (GstBus *bus,
+                      GstMessageType types);
+

Get a message matching type + from the bus. Will discard all messages on +the bus that do not match type + and that have been posted before the first +message that does match type +. If there is no message matching type + on +the bus, all messages will be discarded. It is not possible to use message +enums beyond GST_MESSAGE_EXTENDED in the events + mask.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

a GstBus to pop

 

types

message types to take into account

 
+
+
+

Returns

+

the next GstMessage matching +type +that is on the bus, or NULL if the bus is empty or there +is no message matching type +. The message is taken from the bus +and needs to be unreffed with gst_message_unref() after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_timed_pop ()

+
GstMessage *
+gst_bus_timed_pop (GstBus *bus,
+                   GstClockTime timeout);
+

Get a message from the bus, waiting up to the specified timeout.

+

If timeout + is 0, this function behaves like gst_bus_pop(). If timeout + is +GST_CLOCK_TIME_NONE, this function will block forever until a message was +posted on the bus.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

a GstBus to pop

 

timeout

a timeout

 
+
+
+

Returns

+

the GstMessage that is on the +bus after the specified timeout or NULL if the bus is empty +after the timeout expired. The message is taken from the bus +and needs to be unreffed with gst_message_unref() after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_timed_pop_filtered ()

+
GstMessage *
+gst_bus_timed_pop_filtered (GstBus *bus,
+                            GstClockTime timeout,
+                            GstMessageType types);
+

Get a message from the bus whose type matches the message type mask types +, +waiting up to the specified timeout (and discarding any messages that do not +match the mask provided).

+

If timeout + is 0, this function behaves like gst_bus_pop_filtered(). If +timeout + is GST_CLOCK_TIME_NONE, this function will block forever until a +matching message was posted on the bus.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

a GstBus to pop from

 

timeout

a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever

 

types

message types to take into account, GST_MESSAGE_ANY for any type

 
+
+
+

Returns

+

a GstMessage matching the +filter in types +, or NULL if no matching message was found on +the bus until the timeout expired. The message is taken from +the bus and needs to be unreffed with gst_message_unref() after +usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_set_flushing ()

+
void
+gst_bus_set_flushing (GstBus *bus,
+                      gboolean flushing);
+

If flushing +, flush out and unref any messages queued in the bus. Releases +references to the message origin objects. Will flush future messages until +gst_bus_set_flushing() sets flushing + to FALSE.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

a GstBus

 

flushing

whether or not to flush the bus

 
+
+
+
+
+

gst_bus_set_sync_handler ()

+
void
+gst_bus_set_sync_handler (GstBus *bus,
+                          GstBusSyncHandler func,
+                          gpointer user_data,
+                          GDestroyNotify notify);
+

Sets the synchronous handler on the bus. The function will be called +every time a new message is posted on the bus. Note that the function +will be called in the same thread context as the posting object. This +function is usually only called by the creator of the bus. Applications +should handle messages asynchronously using the gst_bus watch and poll +functions.

+

You cannot replace an existing sync_handler. You can pass NULL to this +function, which will clear the existing handler.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

bus

a GstBus to install the handler on

 

func

The handler function to install.

[allow-none]

user_data

User data that will be sent to the handler function.

 

notify

called when user_data +becomes unused

 
+
+
+
+
+

gst_bus_sync_signal_handler ()

+
GstBusSyncReply
+gst_bus_sync_signal_handler (GstBus *bus,
+                             GstMessage *message,
+                             gpointer data);
+

A helper GstBusSyncHandler that can be used to convert all synchronous +messages into signals.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

a GstBus

 

message

the GstMessage received

 

data

user data

 
+
+
+

Returns

+

GST_BUS_PASS

+
+
+
+
+

gst_bus_get_pollfd ()

+
void
+gst_bus_get_pollfd (GstBus *bus,
+                    GPollFD *fd);
+

Gets the file descriptor from the bus which can be used to get notified about +messages being available with functions like g_poll(), and allows integration +into other event loops based on file descriptors. +Whenever a message is available, the POLLIN / G_IO_IN event is set.

+

Warning: NEVER read or write anything to the returned fd but only use it +for getting notifications via g_poll() or similar and then use the normal +GstBus API, e.g. gst_bus_pop().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

A GstBus

 

fd

A GPollFD to fill

 
+
+

Since: 1.14

+
+
+
+

gst_bus_create_watch ()

+
GSource *
+gst_bus_create_watch (GstBus *bus);
+

Create watch for this bus. The GSource will be dispatched whenever +a message is on the bus. After the GSource is dispatched, the +message is popped off the bus and unreffed.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus to create the watch for

 
+
+
+

Returns

+

a GSource that can be added to a mainloop.

+

[transfer full][nullable]

+
+
+
+
+

gst_bus_add_watch_full ()

+
guint
+gst_bus_add_watch_full (GstBus *bus,
+                        gint priority,
+                        GstBusFunc func,
+                        gpointer user_data,
+                        GDestroyNotify notify);
+

Adds a bus watch to the default main context with the given priority + (e.g. +G_PRIORITY_DEFAULT). It is also possible to use a non-default main +context set up using g_main_context_push_thread_default() (before +one had to create a bus watch source and attach it to the desired main +context 'manually').

+

This function is used to receive asynchronous messages in the main loop. +There can only be a single bus watch per bus, you must remove it before you +can set a new one.

+

The bus watch will only work if a GLib main loop is being run.

+

When func + is called, the message belongs to the caller; if you want to +keep a copy of it, call gst_message_ref() before leaving func +.

+

The watch can be removed using gst_bus_remove_watch() or by returning FALSE +from func +. If the watch was added to the default main context it is also +possible to remove the watch using g_source_remove().

+

The bus watch will take its own reference to the bus +, so it is safe to unref +bus + using gst_object_unref() after setting the bus watch.

+

MT safe.

+

[rename-to gst_bus_add_watch]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

bus

a GstBus to create the watch for.

 

priority

The priority of the watch.

 

func

A function to call when a message is received.

 

user_data

user data passed to func +.

 

notify

the function to call when the source is removed.

 
+
+
+

Returns

+

The event source id or 0 if bus +already got an event source.

+
+
+
+
+

gst_bus_add_watch ()

+
guint
+gst_bus_add_watch (GstBus *bus,
+                   GstBusFunc func,
+                   gpointer user_data);
+

Adds a bus watch to the default main context with the default priority +(G_PRIORITY_DEFAULT). It is also possible to use a non-default main +context set up using g_main_context_push_thread_default() (before +one had to create a bus watch source and attach it to the desired main +context 'manually').

+

This function is used to receive asynchronous messages in the main loop. +There can only be a single bus watch per bus, you must remove it before you +can set a new one.

+

The bus watch will only work if a GLib main loop is being run.

+

The watch can be removed using gst_bus_remove_watch() or by returning FALSE +from func +. If the watch was added to the default main context it is also +possible to remove the watch using g_source_remove().

+

The bus watch will take its own reference to the bus +, so it is safe to unref +bus + using gst_object_unref() after setting the bus watch.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

a GstBus to create the watch for

 

func

A function to call when a message is received.

 

user_data

user data passed to func +.

 
+
+
+

Returns

+

The event source id or 0 if bus +already got an event source.

+
+
+
+
+

gst_bus_remove_watch ()

+
gboolean
+gst_bus_remove_watch (GstBus *bus);
+

Removes an installed bus watch from bus +.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus to remove the watch from.

 
+
+
+

Returns

+

TRUE on success or FALSE if bus +has no event source.

+
+

Since: 1.6

+
+
+
+

gst_bus_disable_sync_message_emission ()

+
void
+gst_bus_disable_sync_message_emission (GstBus *bus);
+

Instructs GStreamer to stop emitting the "sync-message" signal for this bus. +See gst_bus_enable_sync_message_emission() for more information.

+

In the event that multiple pieces of code have called +gst_bus_enable_sync_message_emission(), the sync-message emissions will only +be stopped after all calls to gst_bus_enable_sync_message_emission() were +"cancelled" by calling this function. In this way the semantics are exactly +the same as gst_object_ref() that which calls enable should also call +disable.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus on which you previously called +gst_bus_enable_sync_message_emission()

 
+
+
+
+
+

gst_bus_enable_sync_message_emission ()

+
void
+gst_bus_enable_sync_message_emission (GstBus *bus);
+

Instructs GStreamer to emit the "sync-message" signal after running the bus's +sync handler. This function is here so that code can ensure that they can +synchronously receive messages without having to affect what the bin's sync +handler is.

+

This function may be called multiple times. To clean up, the caller is +responsible for calling gst_bus_disable_sync_message_emission() as many times +as this function is called.

+

While this function looks similar to gst_bus_add_signal_watch(), it is not +exactly the same -- this function enables synchronous emission of +signals when messages arrive; gst_bus_add_signal_watch() adds an idle callback +to pop messages off the bus asynchronously. The sync-message signal +comes from the thread of whatever object posted the message; the "message" +signal is marshalled to the main thread via the main loop.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus on which you want to receive the "sync-message" signal

 
+
+
+
+
+

gst_bus_async_signal_func ()

+
gboolean
+gst_bus_async_signal_func (GstBus *bus,
+                           GstMessage *message,
+                           gpointer data);
+

A helper GstBusFunc that can be used to convert all asynchronous messages +into signals.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

a GstBus

 

message

the GstMessage received

 

data

user data

 
+
+
+

Returns

+

TRUE

+
+
+
+
+

gst_bus_add_signal_watch ()

+
void
+gst_bus_add_signal_watch (GstBus *bus);
+

Adds a bus signal watch to the default main context with the default priority +(G_PRIORITY_DEFAULT). It is also possible to use a non-default +main context set up using g_main_context_push_thread_default() (before +one had to create a bus watch source and attach it to the desired main +context 'manually').

+

After calling this statement, the bus will emit the "message" signal for each +message posted on the bus.

+

This function may be called multiple times. To clean up, the caller is +responsible for calling gst_bus_remove_signal_watch() as many times as this +function is called.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus on which you want to receive the "message" signal

 
+
+
+
+
+

gst_bus_add_signal_watch_full ()

+
void
+gst_bus_add_signal_watch_full (GstBus *bus,
+                               gint priority);
+

Adds a bus signal watch to the default main context with the given priority + +(e.g. G_PRIORITY_DEFAULT). It is also possible to use a non-default main +context set up using g_main_context_push_thread_default() +(before one had to create a bus watch source and attach it to the desired +main context 'manually').

+

After calling this statement, the bus will emit the "message" signal for each +message posted on the bus when the main loop is running.

+

This function may be called multiple times. To clean up, the caller is +responsible for calling gst_bus_remove_signal_watch() as many times as this +function is called.

+

There can only be a single bus watch per bus, you must remove any signal +watch before you can set another type of watch.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bus

a GstBus on which you want to receive the "message" signal

 

priority

The priority of the watch.

 
+
+
+
+
+

gst_bus_remove_signal_watch ()

+
void
+gst_bus_remove_signal_watch (GstBus *bus);
+

Removes a signal watch previously added with gst_bus_add_signal_watch().

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

bus

a GstBus you previously added a signal watch to

 
+
+
+
+
+

gst_bus_poll ()

+
GstMessage *
+gst_bus_poll (GstBus *bus,
+              GstMessageType events,
+              GstClockTime timeout);
+

Poll the bus for messages. Will block while waiting for messages to come. +You can specify a maximum time to poll with the timeout + parameter. If +timeout + is negative, this function will block indefinitely.

+

All messages not in events + will be popped off the bus and will be ignored. +It is not possible to use message enums beyond GST_MESSAGE_EXTENDED in the +events + mask

+

Because poll is implemented using the "message" signal enabled by +gst_bus_add_signal_watch(), calling gst_bus_poll() will cause the "message" +signal to be emitted for every message that poll sees. Thus a "message" +signal handler will see the same messages that this function sees -- neither +will steal messages from the other.

+

This function will run a main loop from the default main context when +polling.

+

You should never use this function, since it is pure evil. This is +especially true for GUI applications based on Gtk+ or Qt, but also for any +other non-trivial application that uses the GLib main loop. As this function +runs a GLib main loop, any callback attached to the default GLib main +context may be invoked. This could be timeouts, GUI events, I/O events etc.; +even if gst_bus_poll() is called with a 0 timeout. Any of these callbacks +may do things you do not expect, e.g. destroy the main application window or +some other resource; change other application state; display a dialog and +run another main loop until the user clicks it away. In short, using this +function may add a lot of complexity to your code through unexpected +re-entrancy and unexpected changes to your application's state.

+

For 0 timeouts use gst_bus_pop_filtered() instead of this function; for +other short timeouts use gst_bus_timed_pop_filtered(); everything else is +better handled by setting up an asynchronous bus watch and doing things +from there.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

a GstBus

 

events

a mask of GstMessageType, representing the set of message types to +poll for (note special handling of extended message types below)

 

timeout

the poll timeout, as a GstClockTime, or GST_CLOCK_TIME_NONE to poll +indefinitely.

 
+
+
+

Returns

+

the message that was received, +or NULL if the poll timed out. The message is taken from the +bus and needs to be unreffed with gst_message_unref() after +usage.

+

[transfer full][nullable]

+
+
+
+
+

Types and Values

+
+

struct GstBus

+
struct GstBus;
+

The opaque GstBus data structure.

+
+
+
+

enum GstBusFlags

+

The standard flags that a bus may have.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_BUS_FLUSHING

+

The bus is currently dropping all messages

+
 

GST_BUS_FLAG_LAST

+

offset to define more flags

+
 
+
+
+
+
+

enum GstBusSyncReply

+

The result values for a GstBusSyncHandler.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_BUS_DROP

+

drop the message

+
 

GST_BUS_PASS

+

pass the message to the async queue

+
 

GST_BUS_ASYNC

+

pass message to async queue, continue if message is handled

+
 
+
+
+
+
+

Property Details

+
+

The “enable-async” property

+
  “enable-async”             gboolean
+

Enable async message delivery for bus watches and gst_bus_pop().

+

Flags: Write / Construct Only

+

Default value: TRUE

+
+
+
+

Signal Details

+
+

The “message” signal

+
void
+user_function (GstBus     *bus,
+               GstMessage *message,
+               gpointer    user_data)
+

A message has been posted on the bus. This signal is emitted from a +GSource added to the mainloop. this signal will only be emitted when +there is a mainloop running.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

the object which received the signal

 

message

the message that has been posted asynchronously

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Has Details

+
+
+
+

The “sync-message” signal

+
void
+user_function (GstBus     *bus,
+               GstMessage *message,
+               gpointer    user_data)
+

A message has been posted on the bus. This signal is emitted from the +thread that posted the message so one has to be careful with locking.

+

This signal will not be emitted by default, you have to call +gst_bus_enable_sync_message_emission() before.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bus

the object which received the signal

 

message

the message that has been posted synchronously

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Has Details

+
+
+
+

See Also

+

GstMessage, GstElement

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstCaps.html b/docs/gst/html/GstCaps.html new file mode 100644 index 0000000..8cc7dac --- /dev/null +++ b/docs/gst/html/GstCaps.html @@ -0,0 +1,3131 @@ + + + + +GstCaps: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstCaps

+

GstCaps — Structure describing sets of media formats

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_CAPS_REFCOUNT() +
#define +GST_CAPS_REFCOUNT_VALUE() +
#define +GST_CAPS_IS_SIMPLE() +
#define +GST_STATIC_CAPS() +
#define +GST_CAPS_FLAGS() +
#define +GST_CAPS_FLAG_IS_SET() +
#define +GST_CAPS_FLAG_SET() +
#define +GST_CAPS_FLAG_UNSET() +
+gboolean + +(*GstCapsForeachFunc) () +
+gboolean + +(*GstCapsMapFunc) () +
+gboolean + +(*GstCapsFilterMapFunc) () +
+GstCaps * + +gst_caps_new_empty () +
+GstCaps * + +gst_caps_new_empty_simple () +
+GstCaps * + +gst_caps_new_any () +
+GstCaps * + +gst_caps_new_simple () +
+GstCaps * + +gst_caps_new_full () +
+GstCaps * + +gst_caps_new_full_valist () +
#define +gst_caps_is_writable() +
+GstCaps * + +gst_caps_copy () +
+GstCaps * + +gst_caps_copy_nth () +
+GstCaps * + +gst_static_caps_get () +
+void + +gst_static_caps_cleanup () +
+void + +gst_caps_append () +
+GstCaps * + +gst_caps_merge () +
+void + +gst_caps_append_structure () +
+void + +gst_caps_append_structure_full () +
+void + +gst_caps_remove_structure () +
+GstStructure * + +gst_caps_steal_structure () +
+GstCaps * + +gst_caps_merge_structure () +
+GstCaps * + +gst_caps_merge_structure_full () +
+guint + +gst_caps_get_size () +
+GstStructure * + +gst_caps_get_structure () +
+GstCapsFeatures * + +gst_caps_get_features () +
+void + +gst_caps_set_features () +
+void + +gst_caps_set_value () +
+void + +gst_caps_set_simple () +
+void + +gst_caps_set_simple_valist () +
+gboolean + +gst_caps_foreach () +
+gboolean + +gst_caps_map_in_place () +
+void + +gst_caps_filter_and_map_in_place () +
+gboolean + +gst_caps_is_any () +
+gboolean + +gst_caps_is_empty () +
+gboolean + +gst_caps_is_fixed () +
+gboolean + +gst_caps_is_equal () +
+gboolean + +gst_caps_is_equal_fixed () +
+gboolean + +gst_caps_is_strictly_equal () +
+gboolean + +gst_caps_is_always_compatible () +
+gboolean + +gst_caps_is_subset () +
+gboolean + +gst_caps_is_subset_structure () +
+gboolean + +gst_caps_is_subset_structure_full () +
+gboolean + +gst_caps_can_intersect () +
+GstCaps * + +gst_caps_intersect () +
+GstCaps * + +gst_caps_intersect_full () +
+GstCaps * + +gst_caps_normalize () +
+GstCaps * + +gst_caps_simplify () +
+gboolean + +gst_caps_replace () +
+gboolean + +gst_caps_take () +
+gchar * + +gst_caps_to_string () +
+GstCaps * + +gst_caps_from_string () +
+GstCaps * + +gst_caps_subtract () +
#define +gst_caps_make_writable() +
+GstCaps * + +gst_caps_truncate () +
+GstCaps * + +gst_caps_fixate () +
+GstCaps * + +gst_caps_ref () +
+void + +gst_caps_unref () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstCaps
structGstStaticCaps
enumGstCapsIntersectMode
enumGstCapsFlags
#defineGST_CAPS_ANY
#defineGST_CAPS_NONE
#defineGST_STATIC_CAPS_ANY
#defineGST_STATIC_CAPS_NONE
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstCaps
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Caps (capabilities) are lightweight refcounted objects describing media types. +They are composed of an array of GstStructure.

+

Caps are exposed on GstPadTemplate to describe all possible types a +given pad can handle. They are also stored in the GstRegistry along with +a description of the GstElement.

+

Caps are exposed on the element pads using the gst_pad_query_caps() pad +function. This function describes the possible types that the pad can +handle or produce at runtime.

+

A GstCaps can be constructed with the following code fragment:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
GstCaps *caps = gst_caps_new_simple ("video/x-raw",
+   "format", G_TYPE_STRING, "I420",
+   "framerate", GST_TYPE_FRACTION, 25, 1,
+   "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+   "width", G_TYPE_INT, 320,
+   "height", G_TYPE_INT, 240,
+   NULL);
+
+ +

+

A GstCaps is fixed when it has no properties with ranges or lists. Use +gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a +caps event to notify downstream elements of the current media type.

+

Various methods exist to work with the media types such as subtracting +or intersecting.

+

Be aware that the current GstCaps / GstStructure serialization into string +has limited support for nested GstCaps / GstStructure fields. It can only +support one level of nesting. Using more levels will lead to unexpected +behavior when using serialization features, such as gst_caps_to_string() or +gst_value_serialize() and their counterparts.

+
+
+

Functions

+
+

GST_CAPS_REFCOUNT()

+
#define GST_CAPS_REFCOUNT(caps)                 GST_MINI_OBJECT_REFCOUNT(caps)
+
+

Get access to the reference count field of the caps

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps

 
+
+
+
+
+

GST_CAPS_REFCOUNT_VALUE()

+
#define GST_CAPS_REFCOUNT_VALUE(caps)           GST_MINI_OBJECT_REFCOUNT_VALUE(caps)
+
+

Get the reference count value of the caps.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps

 
+
+
+
+
+

GST_CAPS_IS_SIMPLE()

+
#define GST_CAPS_IS_SIMPLE(caps) (gst_caps_get_size(caps) == 1)
+
+

Convenience macro that checks if the number of structures in the given caps +is exactly one.

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps instance to check

 
+
+
+
+
+

GST_STATIC_CAPS()

+
#define             GST_STATIC_CAPS(string)
+

Creates a new GstCaps static caps from an input string. +This can be used in pad templates.

+
+

Parameters

+
+++++ + + + + + +

string

the string describing the caps

 
+
+
+
+
+

GST_CAPS_FLAGS()

+
#define GST_CAPS_FLAGS(caps)                    GST_MINI_OBJECT_FLAGS(caps)
+
+

A flags word containing GstCapsFlags flags set on this caps.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps.

 
+
+
+
+
+

GST_CAPS_FLAG_IS_SET()

+
#define GST_CAPS_FLAG_IS_SET(caps,flag)        GST_MINI_OBJECT_FLAG_IS_SET (caps, flag)
+
+

Gives the status of a specific flag on a caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps.

 

flag

the GstCapsFlags to check.

 
+
+
+
+
+

GST_CAPS_FLAG_SET()

+
#define GST_CAPS_FLAG_SET(caps,flag)           GST_MINI_OBJECT_FLAG_SET (caps, flag)
+
+

Sets a caps flag on a caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps.

 

flag

the GstCapsFlags to set.

 
+
+
+
+
+

GST_CAPS_FLAG_UNSET()

+
#define GST_CAPS_FLAG_UNSET(caps,flag)         GST_MINI_OBJECT_FLAG_UNSET (caps, flag)
+
+

Clears a caps flag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps.

 

flag

the GstCapsFlags to clear.

 
+
+
+
+
+

GstCapsForeachFunc ()

+
gboolean
+(*GstCapsForeachFunc) (GstCapsFeatures *features,
+                       GstStructure *structure,
+                       gpointer user_data);
+

A function that will be called in gst_caps_foreach(). The function may +not modify features + or structure +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

features

the GstCapsFeatures

 

structure

the GstStructure

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the foreach operation should continue, FALSE if +the foreach operation should stop with FALSE.

+
+

Since: 1.6

+
+
+
+

GstCapsMapFunc ()

+
gboolean
+(*GstCapsMapFunc) (GstCapsFeatures *features,
+                   GstStructure *structure,
+                   gpointer user_data);
+

A function that will be called in gst_caps_map_in_place(). The function +may modify features + and structure +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

features

the GstCapsFeatures

 

structure

the GstStructure

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the map operation should continue, FALSE if +the map operation should stop with FALSE.

+
+
+
+
+

GstCapsFilterMapFunc ()

+
gboolean
+(*GstCapsFilterMapFunc) (GstCapsFeatures *features,
+                         GstStructure *structure,
+                         gpointer user_data);
+

A function that will be called in gst_caps_filter_and_map_in_place(). +The function may modify features + and structure +, and both will be +removed from the caps if FALSE is returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

features

the GstCapsFeatures

 

structure

the GstStructure

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the features and structure should be preserved, +FALSE if it should be removed.

+
+
+
+
+

gst_caps_new_empty ()

+
GstCaps *
+gst_caps_new_empty (void);
+

Creates a new GstCaps that is empty. That is, the returned +GstCaps contains no media formats. +The GstCaps is guaranteed to be writable. +Caller is responsible for unreffing the returned caps.

+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_new_empty_simple ()

+
GstCaps *
+gst_caps_new_empty_simple (const char *media_type);
+

Creates a new GstCaps that contains one GstStructure with name +media_type +. +Caller is responsible for unreffing the returned caps.

+
+

Parameters

+
+++++ + + + + + +

media_type

the media type of the structure

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_new_any ()

+
GstCaps *
+gst_caps_new_any (void);
+

Creates a new GstCaps that indicates that it is compatible with +any media format.

+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_new_simple ()

+
GstCaps *
+gst_caps_new_simple (const char *media_type,
+                     const char *fieldname,
+                     ...);
+

Creates a new GstCaps that contains one GstStructure. The +structure is defined by the arguments, which have the same format +as gst_structure_new(). +Caller is responsible for unreffing the returned caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

media_type

the media type of the structure

 

fieldname

first field to set

 

...

additional arguments

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_new_full ()

+
GstCaps *
+gst_caps_new_full (GstStructure *struct1,
+                   ...);
+

Creates a new GstCaps and adds all the structures listed as +arguments. The list must be NULL-terminated. The structures +are not copied; the returned GstCaps owns the structures.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

struct1

the first structure to add

 

...

additional structures to add

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_new_full_valist ()

+
GstCaps *
+gst_caps_new_full_valist (GstStructure *structure,
+                          va_list var_args);
+

Creates a new GstCaps and adds all the structures listed as +arguments. The list must be NULL-terminated. The structures +are not copied; the returned GstCaps owns the structures.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

the first structure to add

 

var_args

additional structures to add

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_is_writable()

+
#define         gst_caps_is_writable(caps)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (caps))
+
+

Tests if you can safely modify caps +. It is only safe to modify caps when +there is only one owner of the caps - ie, the object is writable.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps

 
+
+
+
+
+

gst_caps_copy ()

+
GstCaps *
+gst_caps_copy (const GstCaps *caps);
+

Creates a new GstCaps as a copy of the old caps +. The new caps will have a +refcount of 1, owned by the caller. The structures are copied as well.

+

Note that this function is the semantic equivalent of a gst_caps_ref() +followed by a gst_caps_make_writable(). If you only want to hold on to a +reference to the data, you should use gst_caps_ref().

+

When you are finished with the caps, call gst_caps_unref() on it.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps.

 
+
+
+

Returns

+

the new GstCaps

+
+
+
+
+

gst_caps_copy_nth ()

+
GstCaps *
+gst_caps_copy_nth (const GstCaps *caps,
+                   guint nth);
+

Creates a new GstCaps and appends a copy of the nth structure +contained in caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the GstCaps to copy

 

nth

the nth structure to copy

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_static_caps_get ()

+
GstCaps *
+gst_static_caps_get (GstStaticCaps *static_caps);
+

Converts a GstStaticCaps to a GstCaps.

+
+

Parameters

+
+++++ + + + + + +

static_caps

the GstStaticCaps to convert

 
+
+
+

Returns

+

a pointer to the GstCaps. Unref +after usage. Since the core holds an additional ref to the +returned caps, use gst_caps_make_writable() on the returned caps +to modify it.

+

[transfer full][nullable]

+
+
+
+
+

gst_static_caps_cleanup ()

+
void
+gst_static_caps_cleanup (GstStaticCaps *static_caps);
+

Clean up the cached caps contained in static_caps +.

+
+

Parameters

+
+++++ + + + + + +

static_caps

the GstStaticCaps to clean

 
+
+
+
+
+

gst_caps_append ()

+
void
+gst_caps_append (GstCaps *caps1,
+                 GstCaps *caps2);
+

Appends the structures contained in caps2 + to caps1 +. The structures in +caps2 + are not copied -- they are transferred to caps1 +, and then caps2 + is +freed. If either caps is ANY, the resulting caps will be ANY.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

the GstCaps that will be appended to

 

caps2

the GstCaps to append.

[transfer full]
+
+
+
+
+

gst_caps_merge ()

+
GstCaps *
+gst_caps_merge (GstCaps *caps1,
+                GstCaps *caps2);
+

Appends the structures contained in caps2 + to caps1 + if they are not yet +expressed by caps1 +. The structures in caps2 + are not copied -- they are +transferred to a writable copy of caps1 +, and then caps2 + is freed. +If either caps is ANY, the resulting caps will be ANY.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

the GstCaps that will take the new entries.

[transfer full]

caps2

the GstCaps to merge in.

[transfer full]
+
+
+

Returns

+

the merged caps.

+

[transfer full]

+
+
+
+
+

gst_caps_append_structure ()

+
void
+gst_caps_append_structure (GstCaps *caps,
+                           GstStructure *structure);
+

Appends structure + to caps +. The structure is not copied; caps + +becomes the owner of structure +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the GstCaps that will be appended to

 

structure

the GstStructure to append.

[transfer full]
+
+
+
+
+

gst_caps_append_structure_full ()

+
void
+gst_caps_append_structure_full (GstCaps *caps,
+                                GstStructure *structure,
+                                GstCapsFeatures *features);
+

Appends structure + with features + to caps +. The structure is not copied; caps + +becomes the owner of structure +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

the GstCaps that will be appended to

 

structure

the GstStructure to append.

[transfer full]

features

the GstCapsFeatures to append.

[transfer full][allow-none]
+
+

Since: 1.2

+
+
+
+

gst_caps_remove_structure ()

+
void
+gst_caps_remove_structure (GstCaps *caps,
+                           guint idx);
+

removes the structure with the given index from the list of structures +contained in caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the GstCaps to remove from

 

idx

Index of the structure to remove

 
+
+
+
+
+

gst_caps_steal_structure ()

+
GstStructure *
+gst_caps_steal_structure (GstCaps *caps,
+                          guint index);
+

Retrieves the structure with the given index from the list of structures +contained in caps +. The caller becomes the owner of the returned structure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the GstCaps to retrieve from

 

index

Index of the structure to retrieve

 
+
+
+

Returns

+

a pointer to the GstStructure +corresponding to index +.

+

[transfer full][nullable]

+
+
+
+
+

gst_caps_merge_structure ()

+
GstCaps *
+gst_caps_merge_structure (GstCaps *caps,
+                          GstStructure *structure);
+

Appends structure + to caps + if its not already expressed by caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the GstCaps to merge into.

[transfer full]

structure

the GstStructure to merge.

[transfer full]
+
+
+

Returns

+

the merged caps.

+

[transfer full]

+
+
+
+
+

gst_caps_merge_structure_full ()

+
GstCaps *
+gst_caps_merge_structure_full (GstCaps *caps,
+                               GstStructure *structure,
+                               GstCapsFeatures *features);
+

Appends structure + with features + to caps + if its not already expressed by caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

the GstCaps to merge into.

[transfer full]

structure

the GstStructure to merge.

[transfer full]

features

the GstCapsFeatures to merge.

[transfer full][allow-none]
+
+
+

Returns

+

the merged caps.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_get_size ()

+
guint
+gst_caps_get_size (const GstCaps *caps);
+

Gets the number of structures contained in caps +.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps

 
+
+
+

Returns

+

the number of structures that caps +contains

+
+
+
+
+

gst_caps_get_structure ()

+
GstStructure *
+gst_caps_get_structure (const GstCaps *caps,
+                        guint index);
+

Finds the structure in caps + that has the index index +, and +returns it.

+

WARNING: This function takes a const GstCaps *, but returns a +non-const GstStructure *. This is for programming convenience -- +the caller should be aware that structures inside a constant +GstCaps should not be modified. However, if you know the caps +are writable, either because you have just copied them or made +them writable with gst_caps_make_writable(), you may modify the +structure returned in the usual way, e.g. with functions like +gst_structure_set().

+

You do not need to free or unref the structure returned, it +belongs to the GstCaps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps

 

index

the index of the structure

 
+
+
+

Returns

+

a pointer to the GstStructure corresponding +to index +.

+

[transfer none]

+
+
+
+
+

gst_caps_get_features ()

+
GstCapsFeatures *
+gst_caps_get_features (const GstCaps *caps,
+                       guint index);
+

Finds the features in caps + that has the index index +, and +returns it.

+

WARNING: This function takes a const GstCaps *, but returns a +non-const GstCapsFeatures *. This is for programming convenience -- +the caller should be aware that structures inside a constant +GstCaps should not be modified. However, if you know the caps +are writable, either because you have just copied them or made +them writable with gst_caps_make_writable(), you may modify the +features returned in the usual way, e.g. with functions like +gst_caps_features_add().

+

You do not need to free or unref the structure returned, it +belongs to the GstCaps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps

 

index

the index of the structure

 
+
+
+

Returns

+

a pointer to the GstCapsFeatures +corresponding to index +.

+

[transfer none][nullable]

+
+

Since: 1.2

+
+
+
+

gst_caps_set_features ()

+
void
+gst_caps_set_features (GstCaps *caps,
+                       guint index,
+                       GstCapsFeatures *features);
+

Sets the GstCapsFeatures features + for the structure at index +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a GstCaps

 

index

the index of the structure

 

features

the GstCapsFeatures to set.

[allow-none][transfer full]
+
+

Since: 1.2

+
+
+
+

gst_caps_set_value ()

+
void
+gst_caps_set_value (GstCaps *caps,
+                    const char *field,
+                    const GValue *value);
+

Sets the given field + on all structures of caps + to the given value +. +This is a convenience function for calling gst_structure_set_value() on +all structures of caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a writable caps

 

field

name of the field to set

 

value

value to set the field to

 
+
+
+
+
+

gst_caps_set_simple ()

+
void
+gst_caps_set_simple (GstCaps *caps,
+                     const char *field,
+                     ...);
+

Sets fields in a GstCaps. The arguments must be passed in the same +manner as gst_structure_set(), and be NULL-terminated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

the GstCaps to set

 

field

first field to set

 

...

additional parameters

 
+
+
+
+
+

gst_caps_set_simple_valist ()

+
void
+gst_caps_set_simple_valist (GstCaps *caps,
+                            const char *field,
+                            va_list varargs);
+

Sets fields in a GstCaps. The arguments must be passed in the same +manner as gst_structure_set(), and be NULL-terminated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

the GstCaps to set

 

field

first field to set

 

varargs

additional parameters

 
+
+
+
+
+

gst_caps_foreach ()

+
gboolean
+gst_caps_foreach (const GstCaps *caps,
+                  GstCapsForeachFunc func,
+                  gpointer user_data);
+

Calls the provided function once for each structure and caps feature in the +GstCaps. The function must not modify the fields. +Also see gst_caps_map_in_place() and gst_caps_filter_and_map_in_place().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a GstCaps

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+
+

Returns

+

TRUE if the supplied function returns TRUE for each call, +FALSE otherwise.

+
+

Since: 1.6

+
+
+
+

gst_caps_map_in_place ()

+
gboolean
+gst_caps_map_in_place (GstCaps *caps,
+                       GstCapsMapFunc func,
+                       gpointer user_data);
+

Calls the provided function once for each structure and caps feature in the +GstCaps. In contrast to gst_caps_foreach(), the function may modify but not +delete the structures and features. The caps must be mutable.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a GstCaps

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+
+

Returns

+

TRUE if the supplied function returns TRUE for each call, +FALSE otherwise.

+
+

Since: 1.6

+
+
+
+

gst_caps_filter_and_map_in_place ()

+
void
+gst_caps_filter_and_map_in_place (GstCaps *caps,
+                                  GstCapsFilterMapFunc func,
+                                  gpointer user_data);
+

Calls the provided function once for each structure and caps feature in the +GstCaps. In contrast to gst_caps_foreach(), the function may modify the +structure and features. In contrast to gst_caps_filter_and_map_in_place(), +the structure and features are removed from the caps if FALSE is returned +from the function. +The caps must be mutable.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a GstCaps

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+

Since: 1.6

+
+
+
+

gst_caps_is_any ()

+
gboolean
+gst_caps_is_any (const GstCaps *caps);
+

Determines if caps + represents any media format.

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps to test

 
+
+
+

Returns

+

TRUE if caps +represents any format.

+
+
+
+
+

gst_caps_is_empty ()

+
gboolean
+gst_caps_is_empty (const GstCaps *caps);
+

Determines if caps + represents no media formats.

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps to test

 
+
+
+

Returns

+

TRUE if caps +represents no formats.

+
+
+
+
+

gst_caps_is_fixed ()

+
gboolean
+gst_caps_is_fixed (const GstCaps *caps);
+

Fixed GstCaps describe exactly one format, that is, they have exactly +one structure, and each field in the structure describes a fixed type. +Examples of non-fixed types are GST_TYPE_INT_RANGE and GST_TYPE_LIST.

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps to test

 
+
+
+

Returns

+

TRUE if caps +is fixed

+
+
+
+
+

gst_caps_is_equal ()

+
gboolean
+gst_caps_is_equal (const GstCaps *caps1,
+                   const GstCaps *caps2);
+

Checks if the given caps represent the same set of caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

a GstCaps

 

caps2

another GstCaps

 
+
+
+

Returns

+

TRUE if both caps are equal.

+
+
+
+
+

gst_caps_is_equal_fixed ()

+
gboolean
+gst_caps_is_equal_fixed (const GstCaps *caps1,
+                         const GstCaps *caps2);
+

Tests if two GstCaps are equal. This function only works on fixed +GstCaps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

the GstCaps to test

 

caps2

the GstCaps to test

 
+
+
+

Returns

+

TRUE if the arguments represent the same format

+
+
+
+
+

gst_caps_is_strictly_equal ()

+
gboolean
+gst_caps_is_strictly_equal (const GstCaps *caps1,
+                            const GstCaps *caps2);
+

Checks if the given caps are exactly the same set of caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

a GstCaps

 

caps2

another GstCaps

 
+
+
+

Returns

+

TRUE if both caps are strictly equal.

+
+
+
+
+

gst_caps_is_always_compatible ()

+
gboolean
+gst_caps_is_always_compatible (const GstCaps *caps1,
+                               const GstCaps *caps2);
+

A given GstCaps structure is always compatible with another if +every media format that is in the first is also contained in the +second. That is, caps1 + is a subset of caps2 +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

the GstCaps to test

 

caps2

the GstCaps to test

 
+
+
+

Returns

+

TRUE if caps1 +is a subset of caps2 +.

+
+
+
+
+

gst_caps_is_subset ()

+
gboolean
+gst_caps_is_subset (const GstCaps *subset,
+                    const GstCaps *superset);
+

Checks if all caps represented by subset + are also represented by superset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

subset

a GstCaps

 

superset

a potentially greater GstCaps

 
+
+
+

Returns

+

TRUE if subset +is a subset of superset +

+
+
+
+
+

gst_caps_is_subset_structure ()

+
gboolean
+gst_caps_is_subset_structure (const GstCaps *caps,
+                              const GstStructure *structure);
+

Checks if structure + is a subset of caps +. See gst_caps_is_subset() +for more information.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

a GstCaps

 

structure

a potential GstStructure subset of caps +

 
+
+
+

Returns

+

TRUE if structure +is a subset of caps +

+
+
+
+
+

gst_caps_is_subset_structure_full ()

+
gboolean
+gst_caps_is_subset_structure_full (const GstCaps *caps,
+                                   const GstStructure *structure,
+                                   const GstCapsFeatures *features);
+

Checks if structure + is a subset of caps +. See gst_caps_is_subset() +for more information.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps

a GstCaps

 

structure

a potential GstStructure subset of caps +

 

features

a GstCapsFeatures for structure +.

[allow-none]
+
+
+

Returns

+

TRUE if structure +is a subset of caps +

+
+

Since: 1.2

+
+
+
+

gst_caps_can_intersect ()

+
gboolean
+gst_caps_can_intersect (const GstCaps *caps1,
+                        const GstCaps *caps2);
+

Tries intersecting caps1 + and caps2 + and reports whether the result would not +be empty

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

a GstCaps to intersect

 

caps2

a GstCaps to intersect

 
+
+
+

Returns

+

TRUE if intersection would be not empty

+
+
+
+
+

gst_caps_intersect ()

+
GstCaps *
+gst_caps_intersect (GstCaps *caps1,
+                    GstCaps *caps2);
+

Creates a new GstCaps that contains all the formats that are common +to both caps1 + and caps2 +. Defaults to GST_CAPS_INTERSECT_ZIG_ZAG mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

a GstCaps to intersect

 

caps2

a GstCaps to intersect

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_intersect_full ()

+
GstCaps *
+gst_caps_intersect_full (GstCaps *caps1,
+                         GstCaps *caps2,
+                         GstCapsIntersectMode mode);
+

Creates a new GstCaps that contains all the formats that are common +to both caps1 + and caps2 +, the order is defined by the GstCapsIntersectMode +used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

caps1

a GstCaps to intersect

 

caps2

a GstCaps to intersect

 

mode

The intersection algorithm/mode to use

 
+
+
+

Returns

+

the new GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_normalize ()

+
GstCaps *
+gst_caps_normalize (GstCaps *caps);
+

Returns a GstCaps that represents the same set of formats as +caps +, but contains no lists. Each list is expanded into separate +GstStructures +.

+

This function takes ownership of caps + and will call gst_caps_make_writable() +on it so you must not use caps + afterwards unless you keep an additional +reference to it with gst_caps_ref().

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps to normalize.

[transfer full]
+
+
+

Returns

+

the normalized GstCaps.

+

[transfer full]

+
+
+
+
+

gst_caps_simplify ()

+
GstCaps *
+gst_caps_simplify (GstCaps *caps);
+

Converts the given caps + into a representation that represents the +same set of formats, but in a simpler form. Component structures that are +identical are merged. Component structures that have values that can be +merged are also merged.

+

This function takes ownership of caps + and will call gst_caps_make_writable() +on it if necessary, so you must not use caps + afterwards unless you keep an +additional reference to it with gst_caps_ref().

+

This method does not preserve the original order of caps +.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps to simplify.

[transfer full]
+
+
+

Returns

+

The simplified caps.

+

[transfer full]

+
+
+
+
+

gst_caps_replace ()

+
gboolean
+gst_caps_replace (GstCaps **old_caps,
+                  GstCaps *new_caps);
+

Modifies a pointer to a GstCaps to point to a different GstCaps. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +caps is unreffed, the new is reffed).

+

Either new_caps + or the GstCaps pointed to by old_caps + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_caps

pointer to a pointer +to a GstCaps to be replaced.

[inout][transfer full][nullable]

new_caps

pointer to a GstCaps that will +replace the caps pointed to by old_caps +.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if new_caps +was different from old_caps +

+
+
+
+
+

gst_caps_take ()

+
gboolean
+gst_caps_take (GstCaps **old_caps,
+               GstCaps *new_caps);
+

Modifies a pointer to a GstCaps to point to a different GstCaps. This +function is similar to gst_caps_replace() except that it takes ownership +of new_caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_caps

pointer to a pointer to a GstCaps to be +replaced.

[inout][transfer full]

new_caps

pointer to a GstCaps that will +replace the caps pointed to by old_caps +.

[transfer full][allow-none]
+
+
+

Returns

+

TRUE if new_caps +was different from old_caps +

+
+
+
+
+

gst_caps_to_string ()

+
gchar *
+gst_caps_to_string (const GstCaps *caps);
+

Converts caps + to a string representation. This string representation +can be converted back to a GstCaps by gst_caps_from_string().

+

For debugging purposes its easier to do something like this:

+
+ + + + + + + +
1
GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
+
+ +

+This prints the caps in human readable form.

+

The current implementation of serialization will lead to unexpected results +when there are nested GstCaps / GstStructure deeper than one level.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps

 
+
+
+

Returns

+

a newly allocated string representing caps +.

+

[transfer full]

+
+
+
+
+

gst_caps_from_string ()

+
GstCaps *
+gst_caps_from_string (const gchar *string);
+

Converts caps + from a string representation.

+

The current implementation of serialization will lead to unexpected results +when there are nested GstCaps / GstStructure deeper than one level.

+
+

Parameters

+
+++++ + + + + + +

string

a string to convert to GstCaps

 
+
+
+

Returns

+

a newly allocated GstCaps.

+

[transfer full][nullable]

+
+
+
+
+

gst_caps_subtract ()

+
GstCaps *
+gst_caps_subtract (GstCaps *minuend,
+                   GstCaps *subtrahend);
+

Subtracts the subtrahend + from the minuend +.

+

This function does not work reliably if optional properties for caps +are included on one caps and omitted on the other.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

minuend

GstCaps to subtract from

 

subtrahend

GstCaps to subtract

 
+
+
+

Returns

+

the resulting caps.

+

[transfer full]

+
+
+
+
+

gst_caps_make_writable()

+
#define         gst_caps_make_writable(caps)   GST_CAPS_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (caps)))
+
+

Returns a writable copy of caps +.

+

If there is only one reference count on caps +, the caller must be the owner, +and so this function will return the caps object unchanged. If on the other +hand there is more than one reference on the object, a new caps object will +be returned. The caller's reference on caps + will be removed, and instead the +caller will own a reference to the returned object.

+

In short, this function unrefs the caps in the argument and refs the caps +that it returns. Don't access the argument after calling this function. See +also: gst_caps_ref().

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps.

[transfer full]
+
+
+

Returns

+

a writable caps which may or may not be the +same as caps +.

+

[transfer full]

+
+
+
+
+

gst_caps_truncate ()

+
GstCaps *
+gst_caps_truncate (GstCaps *caps);
+

Discard all but the first structure from caps +. Useful when +fixating.

+

This function takes ownership of caps + and will call gst_caps_make_writable() +on it if necessary, so you must not use caps + afterwards unless you keep an +additional reference to it with gst_caps_ref().

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps to truncate.

[transfer full]
+
+
+

Returns

+

truncated caps.

+

[transfer full]

+
+
+
+
+

gst_caps_fixate ()

+
GstCaps *
+gst_caps_fixate (GstCaps *caps);
+

Modifies the given caps + into a representation with only fixed +values. First the caps will be truncated and then the first structure will be +fixated with gst_structure_fixate().

+

This function takes ownership of caps + and will call gst_caps_make_writable() +on it so you must not use caps + afterwards unless you keep an additional +reference to it with gst_caps_ref().

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps to fixate.

[transfer full]
+
+
+

Returns

+

the fixated caps.

+

[transfer full]

+
+
+
+
+

gst_caps_ref ()

+
GstCaps *
+gst_caps_ref (GstCaps *caps);
+

Add a reference to a GstCaps object.

+

From this point on, until the caller calls gst_caps_unref() or +gst_caps_make_writable(), it is guaranteed that the caps object will not +change. This means its structures won't change, etc. To use a GstCaps +object, you must always have a refcount on it -- either the one made +implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with +this function.

+
+

Parameters

+
+++++ + + + + + +

caps

the GstCaps to reference

 
+
+
+

Returns

+

the same GstCaps object.

+
+
+
+
+

gst_caps_unref ()

+
void
+gst_caps_unref (GstCaps *caps);
+

Unref a GstCaps and and free all its structures and the +structures' values when the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps.

 
+
+
+
+
+

Types and Values

+
+

struct GstCaps

+
struct GstCaps {
+  GstMiniObject mini_object;
+};
+
+

Object describing media types.

+
+

Members

+
+++++ + + + + + +

GstMiniObject mini_object;

the parent type

 
+
+
+
+
+

struct GstStaticCaps

+
struct GstStaticCaps {
+  GstCaps *caps;
+  const char *string;
+};
+
+

Datastructure to initialize GstCaps from a string description usually +used in conjunction with GST_STATIC_CAPS() and gst_static_caps_get() to +instantiate a GstCaps.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstCaps *caps;

the cached GstCaps

 

const char *string;

a string describing a caps

 
+
+
+
+
+

enum GstCapsIntersectMode

+

Modes of caps intersection

+

GST_CAPS_INTERSECT_ZIG_ZAG + tries to preserve overall order of both caps +by iterating on the caps' structures as the following matrix shows:

+
+ + + + + + + +
1
+2
+3
+4
+5
caps1
+      +-------------
+      | 1  2  4  7
+caps2 | 3  5  8 10
+      | 6  9 11 12
+
+ +

+Used when there is no explicit precedence of one caps over the other. e.g. +tee's sink pad getcaps function, it will probe its src pad peers' for their +caps and intersect them with this mode.

+

GST_CAPS_INTERSECT_FIRST + is useful when an element wants to preserve +another element's caps priority order when intersecting with its own caps. +Example: If caps1 is [A, B, C] and caps2 is [E, B, D, A], the result +would be [A, B], maintaining the first caps priority on the intersection.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_CAPS_INTERSECT_ZIG_ZAG

+

Zig-zags over both caps.

+
 

GST_CAPS_INTERSECT_FIRST

+

Keeps the first caps order.

+
 
+
+
+
+
+

enum GstCapsFlags

+

Extra flags for a caps.

+
+

Members

+
+++++ + + + + + +

GST_CAPS_FLAG_ANY

+

Caps has no specific content, but can contain + anything.

+
 
+
+
+
+
+

GST_CAPS_ANY

+
#define GST_CAPS_ANY              _gst_caps_any
+
+

Means that the element/pad can output 'anything'. Useful for elements +that output unknown media, such as filesrc. This macro returns a singleton and +should not be unreffed.

+
+
+
+

GST_CAPS_NONE

+
#define GST_CAPS_NONE             _gst_caps_none
+
+

The opposite of GST_CAPS_ANY: it means that the pad/element outputs an +undefined media type that can not be detected. This macro returns a singleton +and should not be unreffed.

+
+
+
+

GST_STATIC_CAPS_ANY

+
#define GST_STATIC_CAPS_ANY       GST_STATIC_CAPS("ANY")
+
+

Creates a new GstCaps static caps that matches anything. +This can be used in pad templates.

+
+
+
+

GST_STATIC_CAPS_NONE

+
#define GST_STATIC_CAPS_NONE      GST_STATIC_CAPS("NONE")
+
+

Creates a new GstCaps static caps that matches nothing. +This can be used in pad templates.

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstCapsFeatures.html b/docs/gst/html/GstCapsFeatures.html new file mode 100644 index 0000000..b6eaa79 --- /dev/null +++ b/docs/gst/html/GstCapsFeatures.html @@ -0,0 +1,1046 @@ + + + + +GstCapsFeatures: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstCapsFeatures

+

GstCapsFeatures — A set of features in caps

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstCapsFeatures * + +gst_caps_features_new () +
+GstCapsFeatures * + +gst_caps_features_new_empty () +
+GstCapsFeatures * + +gst_caps_features_new_any () +
+GstCapsFeatures * + +gst_caps_features_new_id () +
+GstCapsFeatures * + +gst_caps_features_new_id_valist () +
+GstCapsFeatures * + +gst_caps_features_new_valist () +
+GstCapsFeatures * + +gst_caps_features_copy () +
+void + +gst_caps_features_free () +
+GstCapsFeatures * + +gst_caps_features_from_string () +
+gchar * + +gst_caps_features_to_string () +
+gboolean + +gst_caps_features_set_parent_refcount () +
+gboolean + +gst_caps_features_is_equal () +
+gboolean + +gst_caps_features_is_any () +
+gboolean + +gst_caps_features_contains () +
+gboolean + +gst_caps_features_contains_id () +
+guint + +gst_caps_features_get_size () +
const gchar * + +gst_caps_features_get_nth () +
+GQuark + +gst_caps_features_get_nth_id () +
+void + +gst_caps_features_add () +
+void + +gst_caps_features_add_id () +
+void + +gst_caps_features_remove () +
+void + +gst_caps_features_remove_id () +
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstCapsFeatures
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstCapsFeatures can optionally be set on a GstCaps to add requirements +for additional features for a specific GstStructure. Caps structures with +the same name but with a non-equal set of caps features are not compatible. +If a pad supports multiple sets of features it has to add multiple equal +structures with different feature sets to the caps.

+

Empty GstCapsFeatures are equivalent with the GstCapsFeatures that only +contain GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY. ANY GstCapsFeatures as +created by gst_caps_features_new_any() are equal to any other GstCapsFeatures +and can be used to specify that any GstCapsFeatures would be supported, e.g. +for elements that don't touch buffer memory. GstCaps with ANY GstCapsFeatures +are considered non-fixed and during negotiation some GstCapsFeatures have +to be selected.

+

Examples for caps features would be the requirement of a specific GstMemory +types or the requirement of having a specific GstMeta on the buffer. Features +are given as a string of the format "memory:GstMemoryTypeName" or +"meta:GstMetaAPIName".

+
+
+

Functions

+
+

gst_caps_features_new ()

+
GstCapsFeatures *
+gst_caps_features_new (const gchar *feature1,
+                       ...);
+

Creates a new GstCapsFeatures with the given features. +The last argument must be NULL.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature1

name of first feature to set

 

...

additional features

 
+
+
+

Returns

+

a new, empty GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_new_empty ()

+
GstCapsFeatures *
+gst_caps_features_new_empty (void);
+

Creates a new, empty GstCapsFeatures.

+

Free-function: gst_caps_features_free

+
+

Returns

+

a new, empty GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_new_any ()

+
GstCapsFeatures *
+gst_caps_features_new_any (void);
+

Creates a new, ANY GstCapsFeatures. This will be equal +to any other GstCapsFeatures but caps with these are +unfixed.

+

Free-function: gst_caps_features_free

+
+

Returns

+

a new, ANY GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_new_id ()

+
GstCapsFeatures *
+gst_caps_features_new_id (GQuark feature1,
+                          ...);
+

Creates a new GstCapsFeatures with the given features. +The last argument must be 0.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature1

name of first feature to set

 

...

additional features

 
+
+
+

Returns

+

a new, empty GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_new_id_valist ()

+
GstCapsFeatures *
+gst_caps_features_new_id_valist (GQuark feature1,
+                                 va_list varargs);
+

Creates a new GstCapsFeatures with the given features.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature1

name of first feature to set

 

varargs

variable argument list

 
+
+
+

Returns

+

a new, empty GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_new_valist ()

+
GstCapsFeatures *
+gst_caps_features_new_valist (const gchar *feature1,
+                              va_list varargs);
+

Creates a new GstCapsFeatures with the given features.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature1

name of first feature to set

 

varargs

variable argument list

 
+
+
+

Returns

+

a new, empty GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_copy ()

+
GstCapsFeatures *
+gst_caps_features_copy (const GstCapsFeatures *features);
+

Duplicates a GstCapsFeatures and all its values.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + +

features

a GstCapsFeatures to duplicate

 
+
+
+

Returns

+

a new GstCapsFeatures.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_free ()

+
void
+gst_caps_features_free (GstCapsFeatures *features);
+

Frees a GstCapsFeatures and all its values. The caps features must not +have a parent when this function is called.

+
+

Parameters

+
+++++ + + + + + +

features

the GstCapsFeatures to free.

[in][transfer full]
+
+

Since: 1.2

+
+
+
+

gst_caps_features_from_string ()

+
GstCapsFeatures *
+gst_caps_features_from_string (const gchar *features);
+

Creates a GstCapsFeatures from a string representation.

+

Free-function: gst_caps_features_free

+
+

Parameters

+
+++++ + + + + + +

features

a string representation of a GstCapsFeatures.

 
+
+
+

Returns

+

a new GstCapsFeatures or +NULL when the string could not be parsed. Free with +gst_caps_features_free() after use.

+

[transfer full][nullable]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_to_string ()

+
gchar *
+gst_caps_features_to_string (const GstCapsFeatures *features);
+

Converts features + to a human-readable string representation.

+

For debugging purposes its easier to do something like this:

+
+ + + + + + + +
1
GST_LOG ("features is %" GST_PTR_FORMAT, features);
+
+ +

+This prints the features in human readable form.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

features

a GstCapsFeatures

 
+
+
+

Returns

+

a pointer to string allocated by g_malloc(). +g_free() after usage.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_set_parent_refcount ()

+
gboolean
+gst_caps_features_set_parent_refcount (GstCapsFeatures *features,
+                                       gint *refcount);
+

Sets the parent_refcount field of GstCapsFeatures. This field is used to +determine whether a caps features is mutable or not. This function should only be +called by code implementing parent objects of GstCapsFeatures, as described in +the MT Refcounting section of the design documents.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures

 

refcount

a pointer to the parent's refcount.

[in]
+
+
+

Returns

+

TRUE if the parent refcount could be set.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_is_equal ()

+
gboolean
+gst_caps_features_is_equal (const GstCapsFeatures *features1,
+                            const GstCapsFeatures *features2);
+

Check if features1 + and features2 + are equal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features1

a GstCapsFeatures.

 

features2

a GstCapsFeatures.

 
+
+
+

Returns

+

TRUE if features1 +and features2 +are equal.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_is_any ()

+
gboolean
+gst_caps_features_is_any (const GstCapsFeatures *features);
+

Check if features + is GST_CAPS_FEATURES_ANY.

+
+

Parameters

+
+++++ + + + + + +

features

a GstCapsFeatures.

 
+
+
+

Returns

+

TRUE if features +is GST_CAPS_FEATURES_ANY.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_contains ()

+
gboolean
+gst_caps_features_contains (const GstCapsFeatures *features,
+                            const gchar *feature);
+

Check if features + contains feature +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature

 
+
+
+

Returns

+

TRUE if features +contains feature +.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_contains_id ()

+
gboolean
+gst_caps_features_contains_id (const GstCapsFeatures *features,
+                               GQuark feature);
+

Check if features + contains feature +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature

 
+
+
+

Returns

+

TRUE if features +contains feature +.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_get_size ()

+
guint
+gst_caps_features_get_size (const GstCapsFeatures *features);
+

Returns the number of features in features +.

+
+

Parameters

+
+++++ + + + + + +

features

a GstCapsFeatures.

 
+
+
+

Returns

+

The number of features in features +.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_get_nth ()

+
const gchar *
+gst_caps_features_get_nth (const GstCapsFeatures *features,
+                           guint i);
+

Returns the i +-th feature of features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

i

index of the feature

 
+
+
+

Returns

+

The i +-th feature of features +.

+

[nullable]

+
+

Since: 1.2

+
+
+
+

gst_caps_features_get_nth_id ()

+
GQuark
+gst_caps_features_get_nth_id (const GstCapsFeatures *features,
+                              guint i);
+

Returns the i +-th feature of features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

i

index of the feature

 
+
+
+

Returns

+

The i +-th feature of features +.

+
+

Since: 1.2

+
+
+
+

gst_caps_features_add ()

+
void
+gst_caps_features_add (GstCapsFeatures *features,
+                       const gchar *feature);
+

Adds feature + to features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature.

 
+
+

Since: 1.2

+
+
+
+

gst_caps_features_add_id ()

+
void
+gst_caps_features_add_id (GstCapsFeatures *features,
+                          GQuark feature);
+

Adds feature + to features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature.

 
+
+

Since: 1.2

+
+
+
+

gst_caps_features_remove ()

+
void
+gst_caps_features_remove (GstCapsFeatures *features,
+                          const gchar *feature);
+

Removes feature + from features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature.

 
+
+

Since: 1.2

+
+
+
+

gst_caps_features_remove_id ()

+
void
+gst_caps_features_remove_id (GstCapsFeatures *features,
+                             GQuark feature);
+

Removes feature + from features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

features

a GstCapsFeatures.

 

feature

a feature.

 
+
+

Since: 1.2

+
+
+
+

Types and Values

+
+

GstCapsFeatures

+
typedef struct _GstCapsFeatures GstCapsFeatures;
+
+
+
+

GST_CAPS_FEATURES_ANY

+
#define GST_CAPS_FEATURES_ANY (_gst_caps_features_any)
+
+
+
+
+

GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY

+
#define GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY (_gst_caps_features_memory_system_memory)
+
+
+
+
+

GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY

+
#define GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY "memory:SystemMemory"
+
+
+
+
+

See Also

+

GstCaps

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstChildProxy.html b/docs/gst/html/GstChildProxy.html new file mode 100644 index 0000000..1346d3c --- /dev/null +++ b/docs/gst/html/GstChildProxy.html @@ -0,0 +1,831 @@ + + + + +GstChildProxy: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstChildProxy

+

GstChildProxy — Interface for multi child elements.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+guint + +gst_child_proxy_get_children_count () +
+GObject * + +gst_child_proxy_get_child_by_name () +
+GObject * + +gst_child_proxy_get_child_by_index () +
+gboolean + +gst_child_proxy_lookup () +
+void + +gst_child_proxy_get_property () +
+void + +gst_child_proxy_get_valist () +
+void + +gst_child_proxy_get () +
+void + +gst_child_proxy_set_property () +
+void + +gst_child_proxy_set_valist () +
+void + +gst_child_proxy_set () +
+void + +gst_child_proxy_child_added () +
+void + +gst_child_proxy_child_removed () +
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidchild-addedRun First
voidchild-removedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstChildProxy
structGstChildProxyInterface
+
+
+

Object Hierarchy

+
    GInterface
+    ╰── GstChildProxy
+
+
+
+

Prerequisites

+

+GstChildProxy requires + GObject.

+
+
+

Known Implementations

+

+GstChildProxy is implemented by + GstBin and GstPipeline.

+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

This interface abstracts handling of property sets for elements with +children. Imagine elements such as mixers or polyphonic generators. They all +have multiple GstPad or some kind of voice objects. Another use case are +container elements like GstBin. +The element implementing the interface acts as a parent for those child +objects.

+

By implementing this interface the child properties can be accessed from the +parent element by using gst_child_proxy_get() and gst_child_proxy_set().

+

Property names are written as "child-name::property-name". The whole naming +scheme is recursive. Thus "child1::child2::property" is valid too, if +"child1" and "child2" implement the GstChildProxy interface.

+
+
+

Functions

+
+

gst_child_proxy_get_children_count ()

+
guint
+gst_child_proxy_get_children_count (GstChildProxy *parent);
+

Gets the number of child objects this parent contains.

+
+

Parameters

+
+++++ + + + + + +

parent

the parent object

 
+
+
+

Returns

+

the number of child objects

+

MT safe.

+
+
+
+
+

gst_child_proxy_get_child_by_name ()

+
GObject *
+gst_child_proxy_get_child_by_name (GstChildProxy *parent,
+                                   const gchar *name);
+

Looks up a child element by the given name.

+

This virtual method has a default implementation that uses GstObject +together with gst_object_get_name(). If the interface is to be used with +GObjects, this methods needs to be overridden.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parent

the parent object to get the child from

 

name

the child's name

 
+
+
+

Returns

+

the child object or NULL if +not found. Unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_child_proxy_get_child_by_index ()

+
GObject *
+gst_child_proxy_get_child_by_index (GstChildProxy *parent,
+                                    guint index);
+

Fetches a child by its number.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parent

the parent object to get the child from

 

index

the child's position in the child list

 
+
+
+

Returns

+

the child object or NULL if +not found (index too high). Unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_child_proxy_lookup ()

+
gboolean
+gst_child_proxy_lookup (GstChildProxy *object,
+                        const gchar *name,
+                        GObject **target,
+                        GParamSpec **pspec);
+

Looks up which object and GParamSpec would be effected by the given name +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

object

child proxy object to lookup the property in

 

name

name of the property to look up

 

target

pointer to a GObject that +takes the real object to set property on.

[out][allow-none][transfer full]

pspec

pointer to take the GParamSpec +describing the property.

[out][allow-none][transfer none]
+
+
+

Returns

+

TRUE if target +and pspec +could be found. FALSE otherwise. In that +case the values for pspec +and target +are not modified. Unref target +after +usage. For plain GObjects target +is the same as object +.

+
+
+
+
+

gst_child_proxy_get_property ()

+
void
+gst_child_proxy_get_property (GstChildProxy *object,
+                              const gchar *name,
+                              GValue *value);
+

Gets a single property using the GstChildProxy mechanism. +You are responsible for freeing it by calling g_value_unset()

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

object to query

 

name

name of the property

 

value

a GValue that should take the result.

[out caller-allocates]
+
+
+
+
+

gst_child_proxy_get_valist ()

+
void
+gst_child_proxy_get_valist (GstChildProxy *object,
+                            const gchar *first_property_name,
+                            va_list var_args);
+

Gets properties of the parent object and its children.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object to query

 

first_property_name

name of the first property to get

 

var_args

return location for the first property, followed optionally by more name/return location pairs, followed by NULL

 
+
+
+
+
+

gst_child_proxy_get ()

+
void
+gst_child_proxy_get (GstChildProxy *object,
+                     const gchar *first_property_name,
+                     ...);
+

Gets properties of the parent object and its children.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the parent object

 

first_property_name

name of the first property to get

 

...

return location for the first property, followed optionally by more name/return location pairs, followed by NULL

 
+
+
+
+
+

gst_child_proxy_set_property ()

+
void
+gst_child_proxy_set_property (GstChildProxy *object,
+                              const gchar *name,
+                              const GValue *value);
+

Sets a single property using the GstChildProxy mechanism.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the parent object

 

name

name of the property to set

 

value

new GValue for the property

 
+
+
+
+
+

gst_child_proxy_set_valist ()

+
void
+gst_child_proxy_set_valist (GstChildProxy *object,
+                            const gchar *first_property_name,
+                            va_list var_args);
+

Sets properties of the parent object and its children.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the parent object

 

first_property_name

name of the first property to set

 

var_args

value for the first property, followed optionally by more name/value pairs, followed by NULL

 
+
+
+
+
+

gst_child_proxy_set ()

+
void
+gst_child_proxy_set (GstChildProxy *object,
+                     const gchar *first_property_name,
+                     ...);
+

Sets properties of the parent object and its children.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the parent object

 

first_property_name

name of the first property to set

 

...

value for the first property, followed optionally by more name/value pairs, followed by NULL

 
+
+
+
+
+

gst_child_proxy_child_added ()

+
void
+gst_child_proxy_child_added (GstChildProxy *parent,
+                             GObject *child,
+                             const gchar *name);
+

Emits the "child-added" signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parent

the parent object

 

child

the newly added child

 

name

the name of the new child

 
+
+
+
+
+

gst_child_proxy_child_removed ()

+
void
+gst_child_proxy_child_removed (GstChildProxy *parent,
+                               GObject *child,
+                               const gchar *name);
+

Emits the "child-removed" signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parent

the parent object

 

child

the removed child

 

name

the name of the old child

 
+
+
+
+
+

Types and Values

+
+

GstChildProxy

+
typedef struct _GstChildProxy GstChildProxy;
+

Opaque GstChildProxy data structure.

+
+
+
+

struct GstChildProxyInterface

+
struct GstChildProxyInterface {
+  GTypeInterface parent;
+
+  /* methods */
+  GObject * (*get_child_by_name)  (GstChildProxy * parent, const gchar * name);
+  GObject * (*get_child_by_index) (GstChildProxy * parent, guint index);
+  guint     (*get_children_count) (GstChildProxy * parent);
+};
+
+

GstChildProxy interface.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GTypeInterface parent;

parent interface type.

 

get_child_by_name ()

virtual method to fetch the child by name

 

get_child_by_index ()

virtual method to fetch the child by index

 

get_children_count ()

virtual method to get the children count

 
+
+
+
+
+

Signal Details

+
+

The “child-added” signal

+
void
+user_function (GstChildProxy *child_proxy,
+               GObject       *object,
+               gchar         *name,
+               gpointer       user_data)
+

Will be emitted after the object + was added to the child_proxy +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

child_proxy

the GstChildProxy

 

object

the GObject that was added

 

name

the name of the new child

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “child-removed” signal

+
void
+user_function (GstChildProxy *child_proxy,
+               GObject       *object,
+               gchar         *name,
+               gpointer       user_data)
+

Will be emitted after the object + was removed from the child_proxy +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

child_proxy

the GstChildProxy

 

object

the GObject that was removed

 

name

the name of the old child

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

GstBin

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstClock.html b/docs/gst/html/GstClock.html new file mode 100644 index 0000000..24e35ff --- /dev/null +++ b/docs/gst/html/GstClock.html @@ -0,0 +1,2784 @@ + + + + +GstClock: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstClock

+

GstClock — Abstract class for global clocks

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_CLOCK_TIME_IS_VALID() +
#define +GST_CLOCK_STIME_IS_VALID() +
#define +GST_TIME_AS_SECONDS() +
#define +GST_TIME_AS_MSECONDS() +
#define +GST_TIME_AS_USECONDS() +
#define +GST_TIME_AS_NSECONDS() +
#define +GST_CLOCK_DIFF() +
#define +GST_TIMEVAL_TO_TIME() +
#define +GST_TIME_TO_TIMEVAL() +
#define +GST_TIMESPEC_TO_TIME() +
#define +GST_TIME_TO_TIMESPEC() +
+gboolean + +(*GstClockCallback) () +
#define +GST_CLOCK_ENTRY() +
#define +GST_CLOCK_ENTRY_CLOCK() +
#define +GST_CLOCK_ENTRY_TYPE() +
#define +GST_CLOCK_ENTRY_TIME() +
#define +GST_CLOCK_ENTRY_INTERVAL() +
#define +GST_CLOCK_ENTRY_STATUS() +
#define +GST_CLOCK_FLAGS() +
+gboolean + +gst_clock_add_observation () +
+gboolean + +gst_clock_add_observation_unapplied () +
+gboolean + +gst_clock_set_master () +
+GstClock * + +gst_clock_get_master () +
+GstClockTime + +gst_clock_set_resolution () +
+GstClockTime + +gst_clock_get_resolution () +
+GstClockTime + +gst_clock_get_time () +
+GstClockID + +gst_clock_new_single_shot_id () +
+GstClockID + +gst_clock_new_periodic_id () +
+gboolean + +gst_clock_single_shot_id_reinit () +
+gboolean + +gst_clock_periodic_id_reinit () +
+GstClockTime + +gst_clock_get_internal_time () +
+GstClockTime + +gst_clock_adjust_unlocked () +
+GstClockTime + +gst_clock_unadjust_unlocked () +
+GstClockTime + +gst_clock_adjust_with_calibration () +
+GstClockTime + +gst_clock_unadjust_with_calibration () +
+void + +gst_clock_get_calibration () +
+void + +gst_clock_set_calibration () +
+GstClockTime + +gst_clock_get_timeout () +
+void + +gst_clock_set_timeout () +
+gboolean + +gst_clock_wait_for_sync () +
+gboolean + +gst_clock_is_synced () +
+void + +gst_clock_set_synced () +
+GstClockTime + +gst_clock_id_get_time () +
+GstClockReturn + +gst_clock_id_wait () +
+GstClockReturn + +gst_clock_id_wait_async () +
+void + +gst_clock_id_unschedule () +
+gint + +gst_clock_id_compare_func () +
+GstClockID + +gst_clock_id_ref () +
+void + +gst_clock_id_unref () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
guint64timeoutRead / Write
gintwindow-sizeRead / Write
gintwindow-thresholdRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidsyncedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstClock
structGstClockClass
typedefGstClockTime
typedefGstClockTimeDiff
typedefGstClockID
#defineGST_CLOCK_TIME_NONE
#defineGST_CLOCK_STIME_NONE
#defineGST_SECOND
#defineGST_MSECOND
#defineGST_USECOND
#defineGST_NSECOND
structGstClockEntry
enumGstClockEntryType
enumGstClockReturn
enumGstClockFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstClock
+                ╰── GstSystemClock
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GStreamer uses a global clock to synchronize the plugins in a pipeline. +Different clock implementations are possible by implementing this abstract +base class or, more conveniently, by subclassing GstSystemClock.

+

The GstClock returns a monotonically increasing time with the method +gst_clock_get_time(). Its accuracy and base time depend on the specific +clock implementation but time is always expressed in nanoseconds. Since the +baseline of the clock is undefined, the clock time returned is not +meaningful in itself, what matters are the deltas between two clock times. +The time returned by a clock is called the absolute time.

+

The pipeline uses the clock to calculate the running time. Usually all +renderers synchronize to the global clock using the buffer timestamps, the +newsegment events and the element's base time, see GstPipeline.

+

A clock implementation can support periodic and single shot clock +notifications both synchronous and asynchronous.

+

One first needs to create a GstClockID for the periodic or single shot +notification using gst_clock_new_single_shot_id() or +gst_clock_new_periodic_id().

+

To perform a blocking wait for the specific time of the GstClockID use the +gst_clock_id_wait(). To receive a callback when the specific time is reached +in the clock use gst_clock_id_wait_async(). Both these calls can be +interrupted with the gst_clock_id_unschedule() call. If the blocking wait is +unscheduled a return value of GST_CLOCK_UNSCHEDULED is returned.

+

Periodic callbacks scheduled async will be repeatedly called automatically +until it is unscheduled. To schedule a sync periodic callback, +gst_clock_id_wait() should be called repeatedly.

+

The async callbacks can happen from any thread, either provided by the core +or from a streaming thread. The application should be prepared for this.

+

A GstClockID that has been unscheduled cannot be used again for any wait +operation, a new GstClockID should be created and the old unscheduled one +should be destroyed with gst_clock_id_unref().

+

It is possible to perform a blocking wait on the same GstClockID from +multiple threads. However, registering the same GstClockID for multiple +async notifications is not possible, the callback will only be called for +the thread registering the entry last.

+

None of the wait operations unref the GstClockID, the owner is responsible +for unreffing the ids itself. This holds for both periodic and single shot +notifications. The reason being that the owner of the GstClockID has to +keep a handle to the GstClockID to unblock the wait on FLUSHING events or +state changes and if the entry would be unreffed automatically, the handle +might become invalid without any notification.

+

These clock operations do not operate on the running time, so the callbacks +will also occur when not in PLAYING state as if the clock just keeps on +running. Some clocks however do not progress when the element that provided +the clock is not PLAYING.

+

When a clock has the GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be +slaved to another GstClock with the gst_clock_set_master(). The clock will +then automatically be synchronized to this master clock by repeatedly +sampling the master clock and the slave clock and recalibrating the slave +clock with gst_clock_set_calibration(). This feature is mostly useful for +plugins that have an internal clock but must operate with another clock +selected by the GstPipeline. They can track the offset and rate difference +of their internal clock relative to the master clock by using the +gst_clock_get_calibration() function.

+

The master/slave synchronisation can be tuned with the “timeout”, +“window-size” and “window-threshold” properties. +The “timeout” property defines the interval to sample the master +clock and run the calibration functions. “window-size” defines the +number of samples to use when calibrating and “window-threshold” +defines the minimum number of samples before the calibration is performed.

+
+
+

Functions

+
+

GST_CLOCK_TIME_IS_VALID()

+
#define GST_CLOCK_TIME_IS_VALID(time)   (((GstClockTime)(time)) != GST_CLOCK_TIME_NONE)
+
+

Tests if a given GstClockTime represents a valid defined time.

+
+

Parameters

+
+++++ + + + + + +

time

clock time to validate

 
+
+
+
+
+

GST_CLOCK_STIME_IS_VALID()

+
#define GST_CLOCK_STIME_IS_VALID(time)   (((GstClockTimeDiff)(time)) != GST_CLOCK_STIME_NONE)
+
+

Tests if a given GstClockTimeDiff of gint64 represents a valid defined time.

+
+

Parameters

+
+++++ + + + + + +

time

signed clock time to validate

 
+
+

Since: 1.6

+
+
+
+

GST_TIME_AS_SECONDS()

+
#define GST_TIME_AS_SECONDS(time)  ((time) / GST_SECOND)
+
+

Convert a GstClockTime to seconds.

+
+

Parameters

+
+++++ + + + + + +

time

the time

 
+
+
+
+
+

GST_TIME_AS_MSECONDS()

+
#define GST_TIME_AS_MSECONDS(time) ((time) / G_GINT64_CONSTANT (1000000))
+
+

Convert a GstClockTime to milliseconds (1/1000 of a second).

+
+

Parameters

+
+++++ + + + + + +

time

the time

 
+
+
+
+
+

GST_TIME_AS_USECONDS()

+
#define GST_TIME_AS_USECONDS(time) ((time) / G_GINT64_CONSTANT (1000))
+
+

Convert a GstClockTime to microseconds (1/1000000 of a second).

+
+

Parameters

+
+++++ + + + + + +

time

the time

 
+
+
+
+
+

GST_TIME_AS_NSECONDS()

+
#define GST_TIME_AS_NSECONDS(time) (time)
+
+

Convert a GstClockTime to nanoseconds (1/1000000000 of a second).

+
+

Parameters

+
+++++ + + + + + +

time

the time

 
+
+
+
+
+

GST_CLOCK_DIFF()

+
#define GST_CLOCK_DIFF(s, e)            (GstClockTimeDiff)((e) - (s))
+
+

Calculate a difference between two clock times as a GstClockTimeDiff. +The difference is calculated as e + - s +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

s

the first time

 

e

the second time

 
+
+
+
+
+

GST_TIMEVAL_TO_TIME()

+
#define GST_TIMEVAL_TO_TIME(tv)         (GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
+
+

Convert a GTimeVal to a GstClockTime.

+
+

Parameters

+
+++++ + + + + + +

tv

the timeval to convert

 
+
+
+
+
+

GST_TIME_TO_TIMEVAL()

+
#define             GST_TIME_TO_TIMEVAL(t,tv)
+

Convert a GstClockTime to a GTimeVal

+

on 32-bit systems, a timeval has a range of only 2^32 - 1 seconds, +which is about 68 years. Expect trouble if you want to schedule stuff +in your pipeline for 2038.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

t

The GstClockTime to convert

 

tv

The target timeval

 
+
+
+
+
+

GST_TIMESPEC_TO_TIME()

+
#define GST_TIMESPEC_TO_TIME(ts)        (GstClockTime)((ts).tv_sec * GST_SECOND + (ts).tv_nsec * GST_NSECOND)
+
+

Convert a struct timespec (see man pselect) to a GstClockTime.

+
+

Parameters

+
+++++ + + + + + +

ts

the timespec to convert

 
+
+
+
+
+

GST_TIME_TO_TIMESPEC()

+
#define             GST_TIME_TO_TIMESPEC(t,ts)
+

Convert a GstClockTime to a struct timespec (see man pselect)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

t

The GstClockTime to convert

 

ts

The target timespec

 
+
+
+
+
+

GstClockCallback ()

+
gboolean
+(*GstClockCallback) (GstClock *clock,
+                     GstClockTime time,
+                     GstClockID id,
+                     gpointer user_data);
+

The function prototype of the callback.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

clock

The clock that triggered the callback

 

time

The time it was triggered

 

id

The GstClockID that expired

 

user_data

user data passed in the gst_clock_id_wait_async() function

 
+
+
+

Returns

+

TRUE or FALSE (currently unused)

+
+
+
+
+

GST_CLOCK_ENTRY()

+
#define GST_CLOCK_ENTRY(entry)          ((GstClockEntry *)(entry))
+
+

Cast to a clock entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to cast

 
+
+
+
+
+

GST_CLOCK_ENTRY_CLOCK()

+
#define GST_CLOCK_ENTRY_CLOCK(entry)    ((entry)->clock)
+
+

Get the owner clock of the entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to query

 
+
+
+
+
+

GST_CLOCK_ENTRY_TYPE()

+
#define GST_CLOCK_ENTRY_TYPE(entry)     ((entry)->type)
+
+

Get the type of the clock entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to query

 
+
+
+
+
+

GST_CLOCK_ENTRY_TIME()

+
#define GST_CLOCK_ENTRY_TIME(entry)     ((entry)->time)
+
+

Get the requested time of this entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to query

 
+
+
+
+
+

GST_CLOCK_ENTRY_INTERVAL()

+
#define GST_CLOCK_ENTRY_INTERVAL(entry) ((entry)->interval)
+
+

Get the interval of this periodic entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to query

 
+
+
+
+
+

GST_CLOCK_ENTRY_STATUS()

+
#define GST_CLOCK_ENTRY_STATUS(entry)   ((entry)->status)
+
+

The status of the entry

+
+

Parameters

+
+++++ + + + + + +

entry

the entry to query

 
+
+
+
+
+

GST_CLOCK_FLAGS()

+
#define GST_CLOCK_FLAGS(clock)  GST_OBJECT_FLAGS(clock)
+
+

Gets the GstClockFlags clock flags.

+
+

Parameters

+
+++++ + + + + + +

clock

the clock to query

 
+
+
+
+
+

gst_clock_add_observation ()

+
gboolean
+gst_clock_add_observation (GstClock *clock,
+                           GstClockTime slave,
+                           GstClockTime master,
+                           gdouble *r_squared);
+

The time master + of the master clock and the time slave + of the slave +clock are added to the list of observations. If enough observations +are available, a linear regression algorithm is run on the +observations and clock + is recalibrated.

+

If this functions returns TRUE, r_squared + will contain the +correlation coefficient of the interpolation. A value of 1.0 +means a perfect regression was performed. This value can +be used to control the sampling frequency of the master and slave +clocks.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock

 

slave

a time on the slave

 

master

a time on the master

 

r_squared

a pointer to hold the result.

[out]
+
+
+

Returns

+

TRUE if enough observations were added to run the +regression algorithm.

+

MT safe.

+
+
+
+
+

gst_clock_add_observation_unapplied ()

+
gboolean
+gst_clock_add_observation_unapplied (GstClock *clock,
+                                     GstClockTime slave,
+                                     GstClockTime master,
+                                     gdouble *r_squared,
+                                     GstClockTime *internal,
+                                     GstClockTime *external,
+                                     GstClockTime *rate_num,
+                                     GstClockTime *rate_denom);
+

Add a clock observation to the internal slaving algorithm the same as +gst_clock_add_observation(), and return the result of the master clock +estimation, without updating the internal calibration.

+

The caller can then take the results and call gst_clock_set_calibration() +with the values, or some modified version of them.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock

 

slave

a time on the slave

 

master

a time on the master

 

r_squared

a pointer to hold the result.

[out]

internal

a location to store the internal time.

[out][allow-none]

external

a location to store the external time.

[out][allow-none]

rate_num

a location to store the rate numerator.

[out][allow-none]

rate_denom

a location to store the rate denominator.

[out][allow-none]
+
+

Since: 1.6

+
+
+
+

gst_clock_set_master ()

+
gboolean
+gst_clock_set_master (GstClock *clock,
+                      GstClock *master);
+

Set master + as the master clock for clock +. clock + will be automatically +calibrated so that gst_clock_get_time() reports the same time as the +master clock.

+

A clock provider that slaves its clock to a master can get the current +calibration values with gst_clock_get_calibration().

+

master + can be NULL in which case clock + will not be slaved anymore. It will +however keep reporting its time adjusted with the last configured rate +and time offsets.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock

 

master

a master GstClock.

[allow-none]
+
+
+

Returns

+

TRUE if the clock is capable of being slaved to a master clock. +Trying to set a master on a clock without the +GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return FALSE.

+

MT safe.

+
+
+
+
+

gst_clock_get_master ()

+
GstClock *
+gst_clock_get_master (GstClock *clock);
+

Get the master clock that clock + is slaved to or NULL when the clock is +not slaved to any master clock.

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock

 
+
+
+

Returns

+

a master GstClock or NULL +when this clock is not slaved to a master clock. Unref after +usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_clock_set_resolution ()

+
GstClockTime
+gst_clock_set_resolution (GstClock *clock,
+                          GstClockTime resolution);
+

Set the accuracy of the clock. Some clocks have the possibility to operate +with different accuracy at the expense of more resource usage. There is +normally no need to change the default resolution of a clock. The resolution +of a clock can only be changed if the clock has the +GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock

 

resolution

The resolution to set

 
+
+
+

Returns

+

the new resolution of the clock.

+
+
+
+
+

gst_clock_get_resolution ()

+
GstClockTime
+gst_clock_get_resolution (GstClock *clock);
+

Get the accuracy of the clock. The accuracy of the clock is the granularity +of the values returned by gst_clock_get_time().

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock

 
+
+
+

Returns

+

the resolution of the clock in units of GstClockTime.

+

MT safe.

+
+
+
+
+

gst_clock_get_time ()

+
GstClockTime
+gst_clock_get_time (GstClock *clock);
+

Gets the current time of the given clock. The time is always +monotonically increasing and adjusted according to the current +offset and rate.

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock to query

 
+
+
+

Returns

+

the time of the clock. Or GST_CLOCK_TIME_NONE when +given invalid input.

+

MT safe.

+
+
+
+
+

gst_clock_new_single_shot_id ()

+
GstClockID
+gst_clock_new_single_shot_id (GstClock *clock,
+                              GstClockTime time);
+

Get a GstClockID from clock + to trigger a single shot +notification at the requested time. The single shot id should be +unreffed after usage.

+

Free-function: gst_clock_id_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

The GstClockID to get a single shot notification from

 

time

the requested time

 
+
+
+

Returns

+

a GstClockID that can be used to request the +time notification.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_clock_new_periodic_id ()

+
GstClockID
+gst_clock_new_periodic_id (GstClock *clock,
+                           GstClockTime start_time,
+                           GstClockTime interval);
+

Get an ID from clock + to trigger a periodic notification. +The periodic notifications will start at time start_time + and +will then be fired with the given interval +. id + should be unreffed +after usage.

+

Free-function: gst_clock_id_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

clock

The GstClockID to get a periodic notification id from

 

start_time

the requested start time

 

interval

the requested interval

 
+
+
+

Returns

+

a GstClockID that can be used to request the +time notification.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_clock_single_shot_id_reinit ()

+
gboolean
+gst_clock_single_shot_id_reinit (GstClock *clock,
+                                 GstClockID id,
+                                 GstClockTime time);
+

Reinitializes the provided single shot id + to the provided time. Does not +modify the reference count.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

clock

a GstClock

 

id

a GstClockID

 

time

The requested time.

 
+
+
+

Returns

+

TRUE if the GstClockID could be reinitialized to the provided +time +, else FALSE.

+
+
+
+
+

gst_clock_periodic_id_reinit ()

+
gboolean
+gst_clock_periodic_id_reinit (GstClock *clock,
+                              GstClockID id,
+                              GstClockTime start_time,
+                              GstClockTime interval);
+

Reinitializes the provided periodic id + to the provided start time and +interval. Does not modify the reference count.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock

 

id

a GstClockID

 

start_time

the requested start time

 

interval

the requested interval

 
+
+
+

Returns

+

TRUE if the GstClockID could be reinitialized to the provided +time +, else FALSE.

+
+
+
+
+

gst_clock_get_internal_time ()

+
GstClockTime
+gst_clock_get_internal_time (GstClock *clock);
+

Gets the current internal time of the given clock. The time is returned +unadjusted for the offset and the rate.

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock to query

 
+
+
+

Returns

+

the internal time of the clock. Or GST_CLOCK_TIME_NONE when +given invalid input.

+

MT safe.

+
+
+
+
+

gst_clock_adjust_unlocked ()

+
GstClockTime
+gst_clock_adjust_unlocked (GstClock *clock,
+                           GstClockTime internal);
+

Converts the given internal + clock time to the external time, adjusting for the +rate and reference time set with gst_clock_set_calibration() and making sure +that the returned time is increasing. This function should be called with the +clock's OBJECT_LOCK held and is mainly used by clock subclasses.

+

This function is the reverse of gst_clock_unadjust_unlocked().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock to use

 

internal

a clock time

 
+
+
+

Returns

+

the converted time of the clock.

+
+
+
+
+

gst_clock_unadjust_unlocked ()

+
GstClockTime
+gst_clock_unadjust_unlocked (GstClock *clock,
+                             GstClockTime external);
+

Converts the given external + clock time to the internal time of clock +, +using the rate and reference time set with gst_clock_set_calibration(). +This function should be called with the clock's OBJECT_LOCK held and +is mainly used by clock subclasses.

+

This function is the reverse of gst_clock_adjust_unlocked().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock to use

 

external

an external clock time

 
+
+
+

Returns

+

the internal time of the clock corresponding to external +.

+
+
+
+
+

gst_clock_adjust_with_calibration ()

+
GstClockTime
+gst_clock_adjust_with_calibration (GstClock *clock,
+                                   GstClockTime internal_target,
+                                   GstClockTime cinternal,
+                                   GstClockTime cexternal,
+                                   GstClockTime cnum,
+                                   GstClockTime cdenom);
+

Converts the given internal_target + clock time to the external time, +using the passed calibration parameters. This function performs the +same calculation as gst_clock_adjust_unlocked() when called using the +current calibration parameters, but doesn't ensure a monotonically +increasing result as gst_clock_adjust_unlocked() does.

+

Note: The clock + parameter is unused and can be NULL

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock to use.

[allow-none]

internal_target

a clock time

 

cinternal

a reference internal time

 

cexternal

a reference external time

 

cnum

the numerator of the rate of the clock relative to its +internal time

 

cdenom

the denominator of the rate of the clock

 
+
+
+

Returns

+

the converted time of the clock.

+
+

Since: 1.6

+
+
+
+

gst_clock_unadjust_with_calibration ()

+
GstClockTime
+gst_clock_unadjust_with_calibration (GstClock *clock,
+                                     GstClockTime external_target,
+                                     GstClockTime cinternal,
+                                     GstClockTime cexternal,
+                                     GstClockTime cnum,
+                                     GstClockTime cdenom);
+

Converts the given external_target + clock time to the internal time, +using the passed calibration parameters. This function performs the +same calculation as gst_clock_unadjust_unlocked() when called using the +current calibration parameters.

+

Note: The clock + parameter is unused and can be NULL

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock to use.

[allow-none]

external_target

a clock time

 

cinternal

a reference internal time

 

cexternal

a reference external time

 

cnum

the numerator of the rate of the clock relative to its +internal time

 

cdenom

the denominator of the rate of the clock

 
+
+
+

Returns

+

the converted time of the clock.

+
+

Since: 1.8

+
+
+
+

gst_clock_get_calibration ()

+
void
+gst_clock_get_calibration (GstClock *clock,
+                           GstClockTime *internal,
+                           GstClockTime *external,
+                           GstClockTime *rate_num,
+                           GstClockTime *rate_denom);
+

Gets the internal rate and reference time of clock +. See +gst_clock_set_calibration() for more information.

+

internal +, external +, rate_num +, and rate_denom + can be left NULL if the +caller is not interested in the values.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock

 

internal

a location to store the internal time.

[out][allow-none]

external

a location to store the external time.

[out][allow-none]

rate_num

a location to store the rate numerator.

[out][allow-none]

rate_denom

a location to store the rate denominator.

[out][allow-none]
+
+
+
+
+

gst_clock_set_calibration ()

+
void
+gst_clock_set_calibration (GstClock *clock,
+                           GstClockTime internal,
+                           GstClockTime external,
+                           GstClockTime rate_num,
+                           GstClockTime rate_denom);
+

Adjusts the rate and time of clock +. A rate of 1/1 is the normal speed of +the clock. Values bigger than 1/1 make the clock go faster.

+

internal + and external + are calibration parameters that arrange that +gst_clock_get_time() should have been external + at internal time internal +. +This internal time should not be in the future; that is, it should be less +than the value of gst_clock_get_internal_time() when this function is called.

+

Subsequent calls to gst_clock_get_time() will return clock times computed as +follows:

+
+ + + + + + + +
1
time = (internal_time - internal) * rate_num / rate_denom + external
+
+ +

+

This formula is implemented in gst_clock_adjust_unlocked(). Of course, it +tries to do the integer arithmetic as precisely as possible.

+

Note that gst_clock_get_time() always returns increasing values so when you +move the clock backwards, gst_clock_get_time() will report the previous value +until the clock catches up.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

clock

a GstClock to calibrate

 

internal

a reference internal time

 

external

a reference external time

 

rate_num

the numerator of the rate of the clock relative to its +internal time

 

rate_denom

the denominator of the rate of the clock

 
+
+
+
+
+

gst_clock_get_timeout ()

+
GstClockTime
+gst_clock_get_timeout (GstClock *clock);
+

Get the amount of time that master and slave clocks are sampled.

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock

 
+
+
+

Returns

+

the interval between samples.

+
+
+
+
+

gst_clock_set_timeout ()

+
void
+gst_clock_set_timeout (GstClock *clock,
+                       GstClockTime timeout);
+

Set the amount of time, in nanoseconds, to sample master and slave +clocks

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock

 

timeout

a timeout

 
+
+
+
+
+

gst_clock_wait_for_sync ()

+
gboolean
+gst_clock_wait_for_sync (GstClock *clock,
+                         GstClockTime timeout);
+

Waits until clock + is synced for reporting the current time. If timeout + +is GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out +after timeout + nanoseconds.

+

For asynchronous waiting, the GstClock::synced signal can be used.

+

This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC +is not set on the clock, or if the clock is already synced.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock

 

timeout

timeout for waiting or GST_CLOCK_TIME_NONE

 
+
+
+

Returns

+

TRUE if waiting was successful, or FALSE on timeout

+
+

Since: 1.6

+
+
+
+

gst_clock_is_synced ()

+
gboolean
+gst_clock_is_synced (GstClock *clock);
+

Checks if the clock is currently synced.

+

This returns if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is not set on the clock.

+
+

Parameters

+
+++++ + + + + + +

clock

a GstClock

 
+
+
+

Returns

+

TRUE if the clock is currently synced

+
+

Since: 1.6

+
+
+
+

gst_clock_set_synced ()

+
void
+gst_clock_set_synced (GstClock *clock,
+                      gboolean synced);
+

Sets clock + to synced and emits the GstClock::synced signal, and wakes up any +thread waiting in gst_clock_wait_for_sync().

+

This function must only be called if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC +is set on the clock, and is intended to be called by subclasses only.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock

a GstClock

 

synced

if the clock is synced

 
+
+

Since: 1.6

+
+
+
+

gst_clock_id_get_time ()

+
GstClockTime
+gst_clock_id_get_time (GstClockID id);
+

Get the time of the clock ID

+
+

Parameters

+
+++++ + + + + + +

id

The GstClockID to query

 
+
+
+

Returns

+

the time of the given clock id.

+

MT safe.

+
+
+
+
+

gst_clock_id_wait ()

+
GstClockReturn
+gst_clock_id_wait (GstClockID id,
+                   GstClockTimeDiff *jitter);
+

Perform a blocking wait on id +. +id + should have been created with gst_clock_new_single_shot_id() +or gst_clock_new_periodic_id() and should not have been unscheduled +with a call to gst_clock_id_unschedule().

+

If the jitter + argument is not NULL and this function returns GST_CLOCK_OK +or GST_CLOCK_EARLY, it will contain the difference +against the clock and the time of id + when this method was +called. +Positive values indicate how late id + was relative to the clock +(in which case this function will return GST_CLOCK_EARLY). +Negative values indicate how much time was spent waiting on the clock +before this function returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

id

The GstClockID to wait on

 

jitter

a pointer that will contain the jitter, +can be NULL.

[out][allow-none]
+
+
+

Returns

+

the result of the blocking wait. GST_CLOCK_EARLY will be returned +if the current clock time is past the time of id +, GST_CLOCK_OK if +id +was scheduled in time. GST_CLOCK_UNSCHEDULED if id +was +unscheduled with gst_clock_id_unschedule().

+

MT safe.

+
+
+
+
+

gst_clock_id_wait_async ()

+
GstClockReturn
+gst_clock_id_wait_async (GstClockID id,
+                         GstClockCallback func,
+                         gpointer user_data,
+                         GDestroyNotify destroy_data);
+

Register a callback on the given GstClockID id + with the given +function and user_data. When passing a GstClockID with an invalid +time to this function, the callback will be called immediately +with a time set to GST_CLOCK_TIME_NONE. The callback will +be called when the time of id + has been reached.

+

The callback func + can be invoked from any thread, either provided by the +core or from a streaming thread. The application should be prepared for this.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

id

a GstClockID to wait on

 

func

The callback function

 

user_data

User data passed in the callback

 

destroy_data

GDestroyNotify for user_data

 
+
+
+

Returns

+

the result of the non blocking wait.

+

MT safe.

+
+
+
+
+

gst_clock_id_unschedule ()

+
void
+gst_clock_id_unschedule (GstClockID id);
+

Cancel an outstanding request with id +. This can either +be an outstanding async notification or a pending sync notification. +After this call, id + cannot be used anymore to receive sync or +async notifications, you need to create a new GstClockID.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

id

The id to unschedule

 
+
+
+
+
+

gst_clock_id_compare_func ()

+
gint
+gst_clock_id_compare_func (gconstpointer id1,
+                           gconstpointer id2);
+

Compares the two GstClockID instances. This function can be used +as a GCompareFunc when sorting ids.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

id1

A GstClockID

 

id2

A GstClockID to compare with

 
+
+
+

Returns

+

negative value if a < b; zero if a = b; positive value if a > b

+

MT safe.

+
+
+
+
+

gst_clock_id_ref ()

+
GstClockID
+gst_clock_id_ref (GstClockID id);
+

Increase the refcount of given id +.

+
+

Parameters

+
+++++ + + + + + +

id

The GstClockID to ref

 
+
+
+

Returns

+

The same GstClockID with increased refcount.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_clock_id_unref ()

+
void
+gst_clock_id_unref (GstClockID id);
+

Unref given id +. When the refcount reaches 0 the +GstClockID will be freed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

id

The GstClockID to unref.

[transfer full]
+
+
+
+
+

Types and Values

+
+

struct GstClock

+
struct GstClock;
+

GstClock base structure. The values of this structure are +protected for subclasses, use the methods to use the GstClock.

+
+
+
+

struct GstClockClass

+
struct GstClockClass {
+  GstObjectClass        parent_class;
+
+  /* vtable */
+  GstClockTime          (*change_resolution)    (GstClock *clock,
+                                                 GstClockTime old_resolution,
+                                                 GstClockTime new_resolution);
+  GstClockTime          (*get_resolution)       (GstClock *clock);
+
+  GstClockTime          (*get_internal_time)    (GstClock *clock);
+
+  /* waiting on an ID */
+  GstClockReturn        (*wait)                 (GstClock *clock, GstClockEntry *entry,
+                                                 GstClockTimeDiff *jitter);
+  GstClockReturn        (*wait_async)           (GstClock *clock, GstClockEntry *entry);
+  void                  (*unschedule)           (GstClock *clock, GstClockEntry *entry);
+};
+
+

GStreamer clock class. Override the vmethods to implement the clock +functionality.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

change_resolution ()

change the resolution of the clock. Not all values might +be acceptable. The new resolution should be returned.

 

get_resolution ()

get the resolution of the clock.

 

get_internal_time ()

get the internal unadjusted time of the clock. +implement wait_jitter +instead.

 

wait ()

perform a blocking wait on the given GstClockEntry and return +the jitter.

 

wait_async ()

perform an asynchronous wait for the given GstClockEntry.

 

unschedule ()

unblock a blocking or async wait operation.

 
+
+
+
+
+

GstClockTime

+
typedef guint64 GstClockTime;
+
+

A datatype to hold a time, measured in nanoseconds.

+
+
+
+

GstClockTimeDiff

+
typedef gint64 GstClockTimeDiff;
+
+

A datatype to hold a time difference, measured in nanoseconds.

+
+
+
+

GstClockID

+
typedef gpointer GstClockID;
+
+

A datatype to hold the handle to an outstanding sync or async clock callback.

+
+
+
+

GST_CLOCK_TIME_NONE

+
#define GST_CLOCK_TIME_NONE             ((GstClockTime) -1)
+
+

Constant to define an undefined clock time.

+
+
+
+

GST_CLOCK_STIME_NONE

+
#define GST_CLOCK_STIME_NONE             ((GstClockTimeDiff)G_MININT64)
+
+

Constant to define an undefined clock time.

+
+
+
+

GST_SECOND

+
#define GST_SECOND  ((GstClockTimeDiff)(G_USEC_PER_SEC * G_GINT64_CONSTANT (1000)))
+
+

Constant that defines one GStreamer second.

+
+
+
+

GST_MSECOND

+
#define GST_MSECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000)))
+
+

Constant that defines one GStreamer millisecond.

+
+
+
+

GST_USECOND

+
#define GST_USECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000000)))
+
+

Constant that defines one GStreamer microsecond.

+
+
+
+

GST_NSECOND

+
#define GST_NSECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000000000)))
+
+

Constant that defines one GStreamer nanosecond

+
+
+
+

struct GstClockEntry

+
struct GstClockEntry {
+  gint                  refcount;
+};
+
+

All pending timeouts or periodic notifies are converted into +an entry. +Note that GstClockEntry should be treated as an opaque structure. It must +not be extended or allocated using a custom allocator.

+
+

Members

+
+++++ + + + + + +

gint refcount;

reference counter (read-only)

 
+
+
+
+
+

enum GstClockEntryType

+

The type of the clock entry

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_CLOCK_ENTRY_SINGLE

+

a single shot timeout

+
 

GST_CLOCK_ENTRY_PERIODIC

+

a periodic timeout request

+
 
+
+
+
+
+

enum GstClockReturn

+

The return value of a clock operation.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_CLOCK_OK

+

The operation succeeded.

+
 

GST_CLOCK_EARLY

+

The operation was scheduled too late.

+
 

GST_CLOCK_UNSCHEDULED

+

The clockID was unscheduled

+
 

GST_CLOCK_BUSY

+

The ClockID is busy

+
 

GST_CLOCK_BADTIME

+

A bad time was provided to a function.

+
 

GST_CLOCK_ERROR

+

An error occurred

+
 

GST_CLOCK_UNSUPPORTED

+

Operation is not supported

+
 

GST_CLOCK_DONE

+

The ClockID is done waiting

+
 
+
+
+
+
+

enum GstClockFlags

+

The capabilities of this clock

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC

+

clock can do a single sync timeout request

+
 

GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC

+

clock can do a single async timeout request

+
 

GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC

+

clock can do sync periodic timeout requests

+
 

GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC

+

clock can do async periodic timeout callbacks

+
 

GST_CLOCK_FLAG_CAN_SET_RESOLUTION

+

clock's resolution can be changed

+
 

GST_CLOCK_FLAG_CAN_SET_MASTER

+

clock can be slaved to a master clock

+
 

GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC

+

clock needs to be synced before it can be used + (Since 1.6)

+
 

GST_CLOCK_FLAG_LAST

+

subclasses can add additional flags starting from this flag

+
 
+
+
+
+
+

Property Details

+
+

The “timeout” property

+
  “timeout”                  guint64
+

The amount of time, in nanoseconds, to sample master and slave clocks.

+

Flags: Read / Write

+

Default value: 100000000

+
+
+
+

The “window-size” property

+
  “window-size”              gint
+

The size of the window used to calculate rate and offset.

+

Flags: Read / Write

+

Allowed values: [2,1024]

+

Default value: 32

+
+
+
+

The “window-threshold” property

+
  “window-threshold”         gint
+

The threshold to start calculating rate and offset.

+

Flags: Read / Write

+

Allowed values: [2,1024]

+

Default value: 4

+
+
+
+

Signal Details

+
+

The “synced” signal

+
void
+user_function (GstClock *clock,
+               gboolean  synced,
+               gpointer  user_data)
+

Signaled on clocks with GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once +the clock is synchronized, or when it completely lost synchronization. +This signal will not be emitted on clocks without the flag.

+

This signal will be emitted from an arbitrary thread, most likely not +the application's main thread.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

clock

the clock

 

synced

if the clock is synced now

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 1.6

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstContext.html b/docs/gst/html/GstContext.html new file mode 100644 index 0000000..17716c6 --- /dev/null +++ b/docs/gst/html/GstContext.html @@ -0,0 +1,574 @@ + + + + +GstContext: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstContext

+

GstContext — Lightweight objects to represent element contexts

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstContext * + +gst_context_new () +
+GstContext * + +gst_context_ref () +
+void + +gst_context_unref () +
+GstContext * + +gst_context_copy () +
const gchar * + +gst_context_get_context_type () +
+gboolean + +gst_context_has_context_type () +
+gboolean + +gst_context_is_persistent () +
const GstStructure * + +gst_context_get_structure () +
+GstStructure * + +gst_context_writable_structure () +
#define +gst_context_make_writable() +
#define +gst_context_is_writable() +
+gboolean + +gst_context_replace () +
+
+
+

Types and Values

+
++++ + + + + +
 GstContext
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstContext
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstContext is a container object used to store contexts like a device +context, a display server connection and similar concepts that should +be shared between multiple elements.

+

Applications can set a context on a complete pipeline by using +gst_element_set_context(), which will then be propagated to all +child elements. Elements can handle these in GstElementClass.set_context() +and merge them with the context information they already have.

+

When an element needs a context it will do the following actions in this +order until one step succeeds:

+
    +
  1. Check if the element already has a context

  2. +
  3. Query downstream with GST_QUERY_CONTEXT for the context

  4. +
  5. Query upstream with GST_QUERY_CONTEXT for the context

  6. +
  7. Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required +context types and afterwards check if a usable context was set now

  8. +
  9. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message +on the bus.

  10. +
+

Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously +known context on the element that asks for it if possible. Otherwise the +application should provide one if it can.

+

GstContexts can be persistent. +A persistent GstContext is kept in elements when they reach +GST_STATE_NULL, non-persistent ones will be removed. +Also, a non-persistent context won't override a previous persistent +context set to an element.

+
+
+

Functions

+
+

gst_context_new ()

+
GstContext *
+gst_context_new (const gchar *context_type,
+                 gboolean persistent);
+

Create a new context.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

context_type

Context type

 

persistent

Persistent context

 
+
+
+

Returns

+

The new context.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_context_ref ()

+
GstContext *
+gst_context_ref (GstContext *context);
+

Convenience macro to increase the reference count of the context.

+
+

Parameters

+
+++++ + + + + + +

context

the context to ref

 
+
+
+

Returns

+

context +(for convenience when doing assignments)

+
+
+
+
+

gst_context_unref ()

+
void
+gst_context_unref (GstContext *context);
+

Convenience macro to decrease the reference count of the context, possibly +freeing it.

+
+

Parameters

+
+++++ + + + + + +

context

the context to unref

 
+
+
+
+
+

gst_context_copy ()

+
GstContext *
+gst_context_copy (const GstContext *context);
+

Creates a copy of the context. Returns a copy of the context.

+
+

Parameters

+
+++++ + + + + + +

context

the context to copy

 
+
+
+

Returns

+

a new copy of context +.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_context_get_context_type ()

+
const gchar *
+gst_context_get_context_type (const GstContext *context);
+

Get the type of context +.

+
+

Parameters

+
+++++ + + + + + +

context

The GstContext.

 
+
+
+

Returns

+

The type of the context.

+
+

Since: 1.2

+
+
+
+

gst_context_has_context_type ()

+
gboolean
+gst_context_has_context_type (const GstContext *context,
+                              const gchar *context_type);
+

Checks if context + has context_type +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

context

The GstContext.

 

context_type

Context type to check.

 
+
+
+

Returns

+

TRUE if context +has context_type +.

+
+

Since: 1.2

+
+
+
+

gst_context_is_persistent ()

+
gboolean
+gst_context_is_persistent (const GstContext *context);
+

Check if context + is persistent.

+
+

Parameters

+
+++++ + + + + + +

context

The GstContext.

 
+
+
+

Returns

+

TRUE if the context is persistent.

+
+

Since: 1.2

+
+
+
+

gst_context_get_structure ()

+
const GstStructure *
+gst_context_get_structure (const GstContext *context);
+

Access the structure of the context.

+
+

Parameters

+
+++++ + + + + + +

context

The GstContext.

 
+
+
+

Returns

+

The structure of the context. The structure is +still owned by the context, which means that you should not modify it, +free it and that the pointer becomes invalid when you free the context.

+

[transfer none]

+
+

Since: 1.2

+
+
+
+

gst_context_writable_structure ()

+
GstStructure *
+gst_context_writable_structure (GstContext *context);
+

Get a writable version of the structure.

+
+

Parameters

+
+++++ + + + + + +

context

The GstContext.

 
+
+
+

Returns

+

The structure of the context. The structure is still +owned by the context, which means that you should not free it and +that the pointer becomes invalid when you free the context. +This function checks if context +is writable.

+
+

Since: 1.2

+
+
+
+

gst_context_make_writable()

+
#define         gst_context_make_writable(context)  GST_CONTEXT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (context)))
+
+

Checks if a context is writable. If not, a writable copy is made and +returned.

+
+

Parameters

+
+++++ + + + + + +

context

the context to make writable.

[transfer full]
+
+
+

Returns

+

a context (possibly a duplicate) that is writable.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_context_is_writable()

+
#define         gst_context_is_writable(context)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (context))
+
+

Tests if you can safely write into a context's structure or validly +modify the seqnum and timestamp fields.

+
+

Parameters

+
+++++ + + + + + +

context

a GstContext

 
+
+
+
+
+

gst_context_replace ()

+
gboolean
+gst_context_replace (GstContext **old_context,
+                     GstContext *new_context);
+

Modifies a pointer to a GstContext to point to a different GstContext. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +context is unreffed, the new one is reffed).

+

Either new_context + or the GstContext pointed to by old_context + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_context

pointer to a pointer to a GstContext +to be replaced.

[inout][transfer full]

new_context

pointer to a GstContext that will +replace the context pointed to by old_context +.

[allow-none][transfer none]
+
+
+

Returns

+

TRUE if new_context +was different from old_context +

+
+
+
+
+

Types and Values

+
+

GstContext

+
typedef struct _GstContext GstContext;
+
+
+
+

See Also

+

GstMiniObject, GstElement

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstControlBinding.html b/docs/gst/html/GstControlBinding.html new file mode 100644 index 0000000..64e140b --- /dev/null +++ b/docs/gst/html/GstControlBinding.html @@ -0,0 +1,527 @@ + + + + +GstControlBinding: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstControlBinding

+

GstControlBinding — attachment for control source sources

+
+ +
+

Properties

+
+++++ + + + + + + + + + + + + +
+gchar *nameRead / Write / Construct Only
+GstObject *objectRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstControlBinding
structGstControlBindingClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlBinding
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A base class for value mapping objects that attaches control sources to gobject +properties. Such an object is taking one or more GstControlSource instances, +combines them and maps the resulting value to the type and value range of the +bound property.

+
+
+

Functions

+
+

gst_control_binding_sync_values ()

+
gboolean
+gst_control_binding_sync_values (GstControlBinding *binding,
+                                 GstObject *object,
+                                 GstClockTime timestamp,
+                                 GstClockTime last_sync);
+

Sets the property of the object +, according to the GstControlSources that +handle them and for the given timestamp.

+

If this function fails, it is most likely the application developers fault. +Most probably the control sources are not setup correctly.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

binding

the control binding

 

object

the object that has controlled properties

 

timestamp

the time that should be processed

 

last_sync

the last time this was called

 
+
+
+

Returns

+

TRUE if the controller value could be applied to the object +property, FALSE otherwise

+
+
+
+
+

gst_control_binding_get_value ()

+
GValue *
+gst_control_binding_get_value (GstControlBinding *binding,
+                               GstClockTime timestamp);
+

Gets the value for the given controlled property at the requested time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

binding

the control binding

 

timestamp

the time the control-change should be read from

 
+
+
+

Returns

+

the GValue of the property at the given time, +or NULL if the property isn't controlled.

+

[nullable]

+
+
+
+
+

gst_control_binding_get_value_array ()

+
gboolean
+gst_control_binding_get_value_array (GstControlBinding *binding,
+                                     GstClockTime timestamp,
+                                     GstClockTime interval,
+                                     guint n_values,
+                                     gpointer values);
+

Gets a number of values for the given controlled property starting at the +requested time. The array values + need to hold enough space for n_values + of +the same type as the objects property's type.

+

This function is useful if one wants to e.g. draw a graph of the control +curve or apply a control curve sample by sample.

+

The values are unboxed and ready to be used. The similar function +gst_control_binding_get_g_value_array() returns the array as GValues and is +more suitable for bindings.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

binding

the control binding

 

timestamp

the time that should be processed

 

interval

the time spacing between subsequent values

 

n_values

the number of values

 

values

array to put control-values in.

[array length=n_values]
+
+
+

Returns

+

TRUE if the given array could be filled, FALSE otherwise

+
+
+
+
+

gst_control_binding_get_g_value_array ()

+
gboolean
+gst_control_binding_get_g_value_array (GstControlBinding *binding,
+                                       GstClockTime timestamp,
+                                       GstClockTime interval,
+                                       guint n_values,
+                                       GValue *values);
+

Gets a number of GValues for the given controlled property starting at the +requested time. The array values + need to hold enough space for n_values + of +GValue.

+

This function is useful if one wants to e.g. draw a graph of the control +curve or apply a control curve sample by sample.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

binding

the control binding

 

timestamp

the time that should be processed

 

interval

the time spacing between subsequent values

 

n_values

the number of values

 

values

array to put control-values in.

[array length=n_values]
+
+
+

Returns

+

TRUE if the given array could be filled, FALSE otherwise

+
+
+
+
+

gst_control_binding_set_disabled ()

+
void
+gst_control_binding_set_disabled (GstControlBinding *binding,
+                                  gboolean disabled);
+

This function is used to disable a control binding for some time, i.e. +gst_object_sync_values() will do nothing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

binding

the control binding

 

disabled

boolean that specifies whether to disable the controller +or not.

 
+
+
+
+
+

gst_control_binding_is_disabled ()

+
gboolean
+gst_control_binding_is_disabled (GstControlBinding *binding);
+

Check if the control binding is disabled.

+
+

Parameters

+
+++++ + + + + + +

binding

the control binding

 
+
+
+

Returns

+

TRUE if the binding is inactive

+
+
+
+
+

Types and Values

+
+

struct GstControlBinding

+
struct GstControlBinding {
+  gchar *name;
+  GParamSpec *pspec;
+};
+
+

The instance structure of GstControlBinding.

+
+

Members

+
+++++ + + + + + + + + + + + + +

gchar *name;

name of the property of this binding

 

GParamSpec *pspec;

GParamSpec for this property

 
+
+
+
+
+

struct GstControlBindingClass

+
struct GstControlBindingClass {
+  GstObjectClass parent_class;
+
+  gboolean (* sync_values) (GstControlBinding *binding, GstObject *object, GstClockTime timestamp, GstClockTime last_sync);
+  GValue * (* get_value) (GstControlBinding *binding, GstClockTime timestamp);
+  gboolean (* get_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, gpointer values);
+  gboolean (* get_g_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values);
+};
+
+

The class structure of GstControlBinding.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

sync_values ()

implementation for updating the target values

 

get_value ()

implementation to fetch a single control-value

 

get_value_array ()

implementation to fetch a series of control-values

 

get_g_value_array ()

implementation to fetch a series of control-values +as g_values

 
+
+
+
+
+

Property Details

+
+

The “name” property

+
  “name”                     gchar *
+

The name of the property.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “object” property

+
  “object”                   GstObject *
+

The object of the property.

+

Flags: Read / Write / Construct Only

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstControlSource.html b/docs/gst/html/GstControlSource.html new file mode 100644 index 0000000..41267be --- /dev/null +++ b/docs/gst/html/GstControlSource.html @@ -0,0 +1,416 @@ + + + + +GstControlSource: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstControlSource

+

GstControlSource — base class for control source sources

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
 GstValueArray
structGstControlSource
structGstControlSourceClass
structGstTimedValue
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlSource
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

The GstControlSource is a base class for control value sources that could +be used to get timestamp-value pairs. A control source essentially is a +function over time.

+

A GstControlSource is used by first getting an instance of a specific +control-source, creating a binding for the control-source to the target property +of the element and then adding the binding to the element. The binding will +convert the data types and value range to fit to the bound property.

+

For implementing a new GstControlSource one has to implement +GstControlSourceGetValue and GstControlSourceGetValueArray functions. +These are then used by gst_control_source_get_value() and +gst_control_source_get_value_array() to get values for specific timestamps.

+
+
+

Functions

+
+

GstControlSourceGetValue ()

+
gboolean
+(*GstControlSourceGetValue) (GstControlSource *self,
+                             GstClockTime timestamp,
+                             gdouble *value);
+

Function for returning a value for a given timestamp.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the GstControlSource instance

 

timestamp

timestamp for which a value should be calculated

 

value

a value which will be set to the result.

 
+
+
+

Returns

+

TRUE if the value was successfully calculated.

+
+
+
+
+

GstControlSourceGetValueArray ()

+
gboolean
+(*GstControlSourceGetValueArray) (GstControlSource *self,
+                                  GstClockTime timestamp,
+                                  GstClockTime interval,
+                                  guint n_values,
+                                  gdouble *values);
+

Function for returning an array of values for starting at a given timestamp.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the GstControlSource instance

 

timestamp

timestamp for which a value should be calculated

 

interval

the time spacing between subsequent values

 

n_values

the number of values

 

values

array to put control-values in

 
+
+
+

Returns

+

TRUE if the values were successfully calculated.

+
+
+
+
+

gst_control_source_get_value ()

+
gboolean
+gst_control_source_get_value (GstControlSource *self,
+                              GstClockTime timestamp,
+                              gdouble *value);
+

Gets the value for this GstControlSource at a given timestamp.

+

[method]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the GstControlSource object

 

timestamp

the time for which the value should be returned

 

value

the value.

[out]
+
+
+

Returns

+

FALSE if the value couldn't be returned, TRUE otherwise.

+
+
+
+
+

gst_control_source_get_value_array ()

+
gboolean
+gst_control_source_get_value_array (GstControlSource *self,
+                                    GstClockTime timestamp,
+                                    GstClockTime interval,
+                                    guint n_values,
+                                    gdouble *values);
+

Gets an array of values for for this GstControlSource. Values that are +undefined contain NANs.

+

[method]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the GstControlSource object

 

timestamp

the first timestamp

 

interval

the time steps

 

n_values

the number of values to fetch

 

values

array to put control-values in.

[array length=n_values]
+
+
+

Returns

+

TRUE if the given array could be filled, FALSE otherwise

+
+
+
+
+

Types and Values

+
+

GstValueArray

+
typedef struct _GstValueArray GstValueArray;
+
+
+
+

struct GstControlSource

+
struct GstControlSource {
+  GstControlSourceGetValue get_value;             /* Returns the value for a property at a given timestamp */
+  GstControlSourceGetValueArray get_value_array;  /* Returns values for a property in a given timespan */
+};
+
+

The instance structure of GstControlSource.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstControlSourceGetValue get_value;

Function for returning a value for a given timestamp

 

GstControlSourceGetValueArray get_value_array;

Function for returning a values array for a given timestamp

 
+
+
+
+
+

struct GstControlSourceClass

+
struct GstControlSourceClass {
+  GstObjectClass parent_class;
+};
+
+

The class structure of GstControlSource.

+
+

Members

+
+++++ + +
+
+
+
+
+

struct GstTimedValue

+
struct GstTimedValue {
+  GstClockTime timestamp;
+  gdouble      value;
+};
+
+

Structure for saving a timestamp and a value.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstClockTime timestamp;

timestamp of the value change

 

gdouble value;

the corresponding value

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstDateTime.html b/docs/gst/html/GstDateTime.html new file mode 100644 index 0000000..854fcdd --- /dev/null +++ b/docs/gst/html/GstDateTime.html @@ -0,0 +1,1271 @@ + + + + +GstDateTime: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDateTime

+

GstDateTime — A date, time and timezone structure

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gint + +gst_date_time_get_day () +
+gint + +gst_date_time_get_month () +
+gint + +gst_date_time_get_hour () +
+gint + +gst_date_time_get_microsecond () +
+gint + +gst_date_time_get_minute () +
+gfloat + +gst_date_time_get_time_zone_offset () +
+gint + +gst_date_time_get_second () +
+gint + +gst_date_time_get_year () +
+GstDateTime * + +gst_date_time_new () +
+GstDateTime * + +gst_date_time_new_ymd () +
+GstDateTime * + +gst_date_time_new_ym () +
+GstDateTime * + +gst_date_time_new_y () +
+GstDateTime * + +gst_date_time_new_from_unix_epoch_local_time () +
+GstDateTime * + +gst_date_time_new_from_unix_epoch_utc () +
+GstDateTime * + +gst_date_time_new_local_time () +
+GstDateTime * + +gst_date_time_new_now_local_time () +
+GstDateTime * + +gst_date_time_new_now_utc () +
+GstDateTime * + +gst_date_time_ref () +
+void + +gst_date_time_unref () +
+gboolean + +gst_date_time_has_day () +
+gboolean + +gst_date_time_has_month () +
+gboolean + +gst_date_time_has_second () +
+gboolean + +gst_date_time_has_time () +
+gboolean + +gst_date_time_has_year () +
+GstDateTime * + +gst_date_time_new_from_iso8601_string () +
+gchar * + +gst_date_time_to_iso8601_string () +
+GstDateTime * + +gst_date_time_new_from_g_date_time () +
+GDateTime * + +gst_date_time_to_g_date_time () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstDateTime
#defineGST_TYPE_DATE_TIME
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstDateTime
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Struct to store date, time and timezone information altogether. +GstDateTime is refcounted and immutable.

+

Date information is handled using the proleptic Gregorian calendar.

+

Provides basic creation functions and accessor functions to its fields.

+
+
+

Functions

+
+

gst_date_time_get_day ()

+
gint
+gst_date_time_get_day (const GstDateTime *datetime);
+

Returns the day of the month of this GstDateTime. +Call gst_date_time_has_day before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

The day of this GstDateTime

+
+
+
+
+

gst_date_time_get_month ()

+
gint
+gst_date_time_get_month (const GstDateTime *datetime);
+

Returns the month of this GstDateTime. January is 1, February is 2, etc.. +Call gst_date_time_has_month before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

The month of this GstDateTime

+
+
+
+
+

gst_date_time_get_hour ()

+
gint
+gst_date_time_get_hour (const GstDateTime *datetime);
+

Retrieves the hour of the day represented by datetime + in the gregorian +calendar. The return is in the range of 0 to 23. +Call gst_date_time_has_haur before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the hour of the day

+
+
+
+
+

gst_date_time_get_microsecond ()

+
gint
+gst_date_time_get_microsecond (const GstDateTime *datetime);
+

Retrieves the fractional part of the seconds in microseconds represented by +datetime + in the gregorian calendar.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the microsecond of the second

+
+
+
+
+

gst_date_time_get_minute ()

+
gint
+gst_date_time_get_minute (const GstDateTime *datetime);
+

Retrieves the minute of the hour represented by datetime + in the gregorian +calendar. +Call gst_date_time_has_minute before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the minute of the hour

+
+
+
+
+

gst_date_time_get_time_zone_offset ()

+
gfloat
+gst_date_time_get_time_zone_offset (const GstDateTime *datetime);
+

Retrieves the offset from UTC in hours that the timezone specified +by datetime + represents. Timezones ahead (to the east) of UTC have positive +values, timezones before (to the west) of UTC have negative values. +If datetime + represents UTC time, then the offset is zero.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the offset from UTC in hours

+
+
+
+
+

gst_date_time_get_second ()

+
gint
+gst_date_time_get_second (const GstDateTime *datetime);
+

Retrieves the second of the minute represented by datetime + in the gregorian +calendar. +Call gst_date_time_has_second before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the second represented by datetime +

+
+
+
+
+

gst_date_time_get_year ()

+
gint
+gst_date_time_get_year (const GstDateTime *datetime);
+

Returns the year of this GstDateTime +Call gst_date_time_has_year before, to avoid warnings.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

The year of this GstDateTime

+
+
+
+
+

gst_date_time_new ()

+
GstDateTime *
+gst_date_time_new (gfloat tzoffset,
+                   gint year,
+                   gint month,
+                   gint day,
+                   gint hour,
+                   gint minute,
+                   gdouble seconds);
+

Creates a new GstDateTime using the date and times in the gregorian calendar +in the supplied timezone.

+

year + should be from 1 to 9999, month + should be from 1 to 12, day + from +1 to 31, hour + from 0 to 23, minutes + and seconds + from 0 to 59.

+

Note that tzoffset + is a float and was chosen so for being able to handle +some fractional timezones, while it still keeps the readability of +representing it in hours for most timezones.

+

If value is -1 then all over value will be ignored. For example +if month + == -1, then GstDateTime will created only for year +. If +day + == -1, then GstDateTime will created for year + and month + and +so on.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

tzoffset

Offset from UTC in hours.

 

year

the gregorian year

 

month

the gregorian month

 

day

the day of the gregorian month

 

hour

the hour of the day

 

minute

the minute of the hour

 

seconds

the second of the minute

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full][nullable]

+
+
+
+
+

gst_date_time_new_ymd ()

+
GstDateTime *
+gst_date_time_new_ymd (gint year,
+                       gint month,
+                       gint day);
+

Creates a new GstDateTime using the date and times in the gregorian calendar +in the local timezone.

+

year + should be from 1 to 9999, month + should be from 1 to 12, day + from +1 to 31.

+

If value is -1 then all over value will be ignored. For example +if month + == -1, then GstDateTime will created only for year +. If +day + == -1, then GstDateTime will created for year + and month + and +so on.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

year

the gregorian year

 

month

the gregorian month

 

day

the day of the gregorian month

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full]

+
+
+
+
+

gst_date_time_new_ym ()

+
GstDateTime *
+gst_date_time_new_ym (gint year,
+                      gint month);
+

Creates a new GstDateTime using the date and times in the gregorian calendar +in the local timezone.

+

year + should be from 1 to 9999, month + should be from 1 to 12.

+

If value is -1 then all over value will be ignored. For example +if month + == -1, then GstDateTime will created only for year +.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

year

the gregorian year

 

month

the gregorian month

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full]

+
+
+
+
+

gst_date_time_new_y ()

+
GstDateTime *
+gst_date_time_new_y (gint year);
+

Creates a new GstDateTime using the date and times in the gregorian calendar +in the local timezone.

+

year + should be from 1 to 9999.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

year

the gregorian year

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full]

+
+
+
+
+

gst_date_time_new_from_unix_epoch_local_time ()

+
GstDateTime *
+gst_date_time_new_from_unix_epoch_local_time
+                               (gint64 secs);
+

Creates a new GstDateTime using the time since Jan 1, 1970 specified by +secs +. The GstDateTime is in the local timezone.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

secs

seconds from the Unix epoch

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full]

+
+
+
+
+

gst_date_time_new_from_unix_epoch_utc ()

+
GstDateTime *
+gst_date_time_new_from_unix_epoch_utc (gint64 secs);
+

Creates a new GstDateTime using the time since Jan 1, 1970 specified by +secs +. The GstDateTime is in the UTC timezone.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

secs

seconds from the Unix epoch

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full]

+
+
+
+
+

gst_date_time_new_local_time ()

+
GstDateTime *
+gst_date_time_new_local_time (gint year,
+                              gint month,
+                              gint day,
+                              gint hour,
+                              gint minute,
+                              gdouble seconds);
+

Creates a new GstDateTime using the date and times in the gregorian calendar +in the local timezone.

+

year + should be from 1 to 9999, month + should be from 1 to 12, day + from +1 to 31, hour + from 0 to 23, minutes + and seconds + from 0 to 59.

+

If month + is -1, then the GstDateTime created will only contain year +, +and all other fields will be considered not set.

+

If day + is -1, then the GstDateTime created will only contain year + and +month + and all other fields will be considered not set.

+

If hour + is -1, then the GstDateTime created will only contain year + and +month + and day +, and the time fields will be considered not set. In this +case minute + and seconds + should also be -1.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

year

the gregorian year

 

month

the gregorian month, or -1

 

day

the day of the gregorian month, or -1

 

hour

the hour of the day, or -1

 

minute

the minute of the hour, or -1

 

seconds

the second of the minute, or -1

 
+
+
+

Returns

+

the newly created GstDateTime.

+

[transfer full][nullable]

+
+
+
+
+

gst_date_time_new_now_local_time ()

+
GstDateTime *
+gst_date_time_new_now_local_time (void);
+

Creates a new GstDateTime representing the current date and time.

+

Free-function: gst_date_time_unref

+
+

Returns

+

the newly created GstDateTime which should +be freed with gst_date_time_unref().

+

[transfer full]

+
+
+
+
+

gst_date_time_new_now_utc ()

+
GstDateTime *
+gst_date_time_new_now_utc (void);
+

Creates a new GstDateTime that represents the current instant at Universal +coordinated time.

+

Free-function: gst_date_time_unref

+
+

Returns

+

the newly created GstDateTime which should +be freed with gst_date_time_unref().

+

[transfer full]

+
+
+
+
+

gst_date_time_ref ()

+
GstDateTime *
+gst_date_time_ref (GstDateTime *datetime);
+

Atomically increments the reference count of datetime + by one.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

the reference datetime +.

+

[transfer full]

+
+
+
+
+

gst_date_time_unref ()

+
void
+gst_date_time_unref (GstDateTime *datetime);
+

Atomically decrements the reference count of datetime + by one. When the +reference count reaches zero, the structure is freed.

+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime.

[transfer full]
+
+
+
+
+

gst_date_time_has_day ()

+
gboolean
+gst_date_time_has_day (const GstDateTime *datetime);
+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

TRUE if datetime +'s day field is set, otherwise FALSE

+
+
+
+
+

gst_date_time_has_month ()

+
gboolean
+gst_date_time_has_month (const GstDateTime *datetime);
+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

TRUE if datetime +'s month field is set, otherwise FALSE

+
+
+
+
+

gst_date_time_has_second ()

+
gboolean
+gst_date_time_has_second (const GstDateTime *datetime);
+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

TRUE if datetime +'s second field is set, otherwise FALSE

+
+
+
+
+

gst_date_time_has_time ()

+
gboolean
+gst_date_time_has_time (const GstDateTime *datetime);
+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

TRUE if datetime +'s hour and minute fields are set, +otherwise FALSE

+
+
+
+
+

gst_date_time_has_year ()

+
gboolean
+gst_date_time_has_year (const GstDateTime *datetime);
+
+

Parameters

+
+++++ + + + + + +

datetime

a GstDateTime

 
+
+
+

Returns

+

TRUE if datetime +'s year field is set (which should always +be the case), otherwise FALSE

+
+
+
+
+

gst_date_time_new_from_iso8601_string ()

+
GstDateTime *
+gst_date_time_new_from_iso8601_string (const gchar *string);
+

Tries to parse common variants of ISO-8601 datetime strings into a +GstDateTime. Possible input formats are (for example): +2012-06-30T22:46:43Z, 2012, 2012-06, 2012-06-30, 2012-06-30T22:46:43-0430, +2012-06-30T22:46Z, 2012-06-30T22:46-0430, 2012-06-30 22:46, +2012-06-30 22:46:43, 2012-06-00, 2012-00-00, 2012-00-30, 22:46:43Z, 22:46Z, +22:46:43-0430, 22:46-0430, 22:46:30, 22:46 +If no date is provided, it is assumed to be "today" in the timezone +provided (if any), otherwise UTC.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

string

ISO 8601-formatted datetime string.

 
+
+
+

Returns

+

a newly created GstDateTime, +or NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

gst_date_time_to_iso8601_string ()

+
gchar *
+gst_date_time_to_iso8601_string (GstDateTime *datetime);
+

Create a minimal string compatible with ISO-8601. Possible output formats +are (for example): 2012, 2012-06, 2012-06-23, 2012-06-23T23:30Z, +2012-06-23T23:30+0100, 2012-06-23T23:30:59Z, 2012-06-23T23:30:59+0100

+
+

Parameters

+
+++++ + + + + + +

datetime

GstDateTime.

 
+
+
+

Returns

+

a newly allocated string formatted according +to ISO 8601 and only including the datetime fields that are +valid, or NULL in case there was an error. The string should +be freed with g_free().

+

[nullable]

+
+
+
+
+

gst_date_time_new_from_g_date_time ()

+
GstDateTime *
+gst_date_time_new_from_g_date_time (GDateTime *dt);
+

Creates a new GstDateTime from a GDateTime object.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

dt

the GDateTime. The new GstDateTime takes ownership.

[transfer full]
+
+
+

Returns

+

a newly created GstDateTime, +or NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

gst_date_time_to_g_date_time ()

+
GDateTime *
+gst_date_time_to_g_date_time (GstDateTime *datetime);
+

Creates a new GDateTime from a fully defined GstDateTime object.

+

Free-function: g_date_time_unref

+
+

Parameters

+
+++++ + + + + + +

datetime

GstDateTime.

 
+
+
+

Returns

+

a newly created GDateTime, or +NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

Types and Values

+
+

GstDateTime

+
typedef struct _GstDateTime GstDateTime;
+

Opaque, immutable, refcounted struct that stores date, time and timezone +information. It currently supports ranges from 0001-01-01 to +9999-12-31 in the Gregorian proleptic calendar.

+

Use the accessor functions to get the stored values.

+
+
+
+

GST_TYPE_DATE_TIME

+
#define GST_TYPE_DATE_TIME (_gst_date_time_type)
+
+

a boxed GValue type for GstDateTime that represents a date and time.

+
+

Returns

+

the GType of GstDateTime

+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstDeviceProviderFactory.html b/docs/gst/html/GstDeviceProviderFactory.html new file mode 100644 index 0000000..fe7752b --- /dev/null +++ b/docs/gst/html/GstDeviceProviderFactory.html @@ -0,0 +1,493 @@ + + + + +GstDeviceProviderFactory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDeviceProviderFactory

+

GstDeviceProviderFactory — Create GstDeviceProviders from a factory

+
+ +
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ╰── GstDeviceProviderFactory
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

GstDeviceProviderFactory is used to create instances of device providers. A +GstDeviceProviderfactory can be added to a GstPlugin as it is also a +GstPluginFeature.

+

Use the gst_device_provider_factory_find() and +gst_device_provider_factory_get() functions to create device +provider instances or use gst_device_provider_factory_get_by_name() as a +convenient shortcut.

+
+
+

Functions

+
+

gst_device_provider_factory_find ()

+
GstDeviceProviderFactory *
+gst_device_provider_factory_find (const gchar *name);
+

Search for an device provider factory of the given name. Refs the returned +device provider factory; caller is responsible for unreffing.

+
+

Parameters

+
+++++ + + + + + +

name

name of factory to find

 
+
+
+

Returns

+

GstDeviceProviderFactory if +found, NULL otherwise.

+

[transfer full][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_get ()

+
GstDeviceProvider *
+gst_device_provider_factory_get (GstDeviceProviderFactory *factory);
+

Returns the device provider of the type defined by the given device +providerfactory.

+
+

Parameters

+
+++++ + + + + + +

factory

factory to instantiate

 
+
+
+

Returns

+

the GstDeviceProvider or NULL +if the device provider couldn't be created.

+

[transfer full][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_get_by_name ()

+
GstDeviceProvider *
+gst_device_provider_factory_get_by_name
+                               (const gchar *factoryname);
+

Returns the device provider of the type defined by the given device +provider factory.

+
+

Parameters

+
+++++ + + + + + +

factoryname

a named factory to instantiate

 
+
+
+

Returns

+

a GstDeviceProvider or NULL +if unable to create device provider.

+

[transfer full][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_get_device_provider_type ()

+
GType
+gst_device_provider_factory_get_device_provider_type
+                               (GstDeviceProviderFactory *factory);
+

Get the GType for device providers managed by this factory. The type can +only be retrieved if the device provider factory is loaded, which can be +assured with gst_plugin_feature_load().

+
+

Parameters

+
+++++ + + + + + +

factory

factory to get managed GType from

 
+
+
+

Returns

+

the GType for device providers managed by this factory.

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_get_metadata ()

+
const gchar *
+gst_device_provider_factory_get_metadata
+                               (GstDeviceProviderFactory *factory,
+                                const gchar *key);
+

Get the metadata on factory + with key +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstDeviceProviderFactory

 

key

a key

 
+
+
+

Returns

+

the metadata with key +on factory +or NULL +when there was no metadata with the given key +.

+

[nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_get_metadata_keys ()

+
gchar **
+gst_device_provider_factory_get_metadata_keys
+                               (GstDeviceProviderFactory *factory);
+

Get the available keys for the metadata on factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstDeviceProviderFactory

 
+
+
+

Returns

+

a NULL-terminated array of key strings, or NULL when there is no +metadata. Free with g_strfreev() when no longer needed.

+

[transfer full][element-type utf8][array zero-terminated=1][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_has_classes ()

+
gboolean
+gst_device_provider_factory_has_classes
+                               (GstDeviceProviderFactory *factory,
+                                const gchar *classes);
+

Check if factory + matches all of the given classes +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstDeviceProviderFactory

 

classes

a "/" separate list of classes to match, only match +if all classes are matched.

[allow-none]
+
+
+

Returns

+

TRUE if factory +matches or if classes +is NULL.

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_has_classesv ()

+
gboolean
+gst_device_provider_factory_has_classesv
+                               (GstDeviceProviderFactory *factory,
+                                gchar **classes);
+

Check if factory + matches all of the given classes

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstDeviceProviderFactory

 

classes

a NULL terminated array +of classes to match, only match if all classes are matched.

[array zero-terminated=1][allow-none]
+
+
+

Returns

+

TRUE if factory +matches.

+
+

Since: 1.4

+
+
+
+

gst_device_provider_factory_list_get_device_providers ()

+
GList *
+gst_device_provider_factory_list_get_device_providers
+                               (GstRank minrank);
+

Get a list of factories with a rank greater or equal to minrank +. +The list of factories is returned by decreasing rank.

+
+

Parameters

+
+++++ + + + + + +

minrank

Minimum rank

 
+
+
+

Returns

+

a GList of GstDeviceProviderFactory device providers. Use +gst_plugin_feature_list_free() after usage.

+

[transfer full][element-type Gst.DeviceProviderFactory]

+
+

Since: 1.4

+
+
+
+

Types and Values

+
+

GstDeviceProviderFactory

+
typedef struct _GstDeviceProviderFactory GstDeviceProviderFactory;
+

The opaque GstDeviceProviderFactory data structure.

+

Since: 1.4

+
+
+
+

GstDeviceProviderFactoryClass

+
typedef struct _GstDeviceProviderFactoryClass GstDeviceProviderFactoryClass;
+

The opaque GstDeviceProviderFactoryClass data structure.

+

Since: 1.4

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstDynamicTypeFactory.html b/docs/gst/html/GstDynamicTypeFactory.html new file mode 100644 index 0000000..10a6d05 --- /dev/null +++ b/docs/gst/html/GstDynamicTypeFactory.html @@ -0,0 +1,153 @@ + + + + +GstDynamicTypeFactory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDynamicTypeFactory

+

GstDynamicTypeFactory — Represents a registered dynamically loadable GType

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GType + +gst_dynamic_type_factory_load () +
+gboolean + +gst_dynamic_type_register () +
+
+
+

Types and Values

+
++++ + + + + +
 GstDynamicTypeFactory
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ╰── GstDynamicTypeFactory
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstDynamicTypeFactory is used to represent a type that can be +automatically loaded the first time it is used. For example, +a non-standard type for use in caps fields.

+

In general, applications and plugins don't need to use the factory +beyond registering the type in a plugin init function. Once that is +done, the type is stored in the registry, and ready as soon as the +registry is loaded.

+
+

Registering a type for dynamic loading

+
+ + + + + + + +
1
+2
+3
+4
+5
static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  return gst_dynamic_type_register (plugin, GST_TYPE_CUSTOM_CAPS_FIELD);
+}
+
+ +

+
+
+
+

Functions

+
+

gst_dynamic_type_factory_load ()

+
GType
+gst_dynamic_type_factory_load (const gchar *factoryname);
+
+
+
+

gst_dynamic_type_register ()

+
gboolean
+gst_dynamic_type_register (GstPlugin *plugin,
+                           GType type);
+
+
+
+

Types and Values

+
+

GstDynamicTypeFactory

+
typedef struct _GstDynamicTypeFactory GstDynamicTypeFactory;
+

The opaque GstDynamicTypeFactory data structure.

+
+
+
+

See Also

+

GstPlugin, GstPluginFeature.

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstElement.html b/docs/gst/html/GstElement.html new file mode 100644 index 0000000..62973ce --- /dev/null +++ b/docs/gst/html/GstElement.html @@ -0,0 +1,6025 @@ + + + + +GstElement: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstElement

+

GstElement — Abstract base class for all pipeline elements

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_STATE() +
#define +GST_STATE_GET_NEXT() +
#define +GST_STATE_NEXT() +
#define +GST_STATE_PENDING() +
#define +GST_STATE_RETURN() +
#define +GST_STATE_TARGET() +
#define +GST_STATE_TRANSITION() +
#define +GST_STATE_TRANSITION_CURRENT() +
#define +GST_STATE_TRANSITION_NEXT() +
#define +GST_STATE_GET_LOCK() +
#define +GST_STATE_GET_COND() +
#define +GST_ELEMENT_NAME() +
#define +GST_ELEMENT_PARENT() +
#define +GST_ELEMENT_BUS() +
#define +GST_ELEMENT_CLOCK() +
#define +GST_ELEMENT_PADS() +
#define +GST_ELEMENT_START_TIME() +
#define +GST_ELEMENT_ERROR() +
#define +GST_ELEMENT_ERROR_WITH_DETAILS() +
#define +GST_ELEMENT_FLOW_ERROR() +
#define +GST_ELEMENT_WARNING() +
#define +GST_ELEMENT_WARNING_WITH_DETAILS() +
#define +GST_ELEMENT_INFO() +
#define +GST_ELEMENT_INFO_WITH_DETAILS() +
#define +GST_ELEMENT_IS_LOCKED_STATE() +
+void + +gst_element_class_add_pad_template () +
+void + +gst_element_class_add_static_pad_template () +
+void + +gst_element_class_add_static_pad_template_with_gtype () +
+GstPadTemplate * + +gst_element_class_get_pad_template () +
+GList * + +gst_element_class_get_pad_template_list () +
+void + +gst_element_class_set_metadata () +
+void + +gst_element_class_set_static_metadata () +
+void + +gst_element_class_add_metadata () +
+void + +gst_element_class_add_static_metadata () +
+gboolean + +gst_element_add_pad () +
+void + +gst_element_create_all_pads () +
+GstPad * + +gst_element_get_compatible_pad () +
+GstPadTemplate * + +gst_element_get_compatible_pad_template () +
+GstPad * + +gst_element_get_request_pad () +
+GstPad * + +gst_element_get_static_pad () +
+GstPad * + +gst_element_request_pad () +
+void + +gst_element_no_more_pads () +
+void + +gst_element_release_request_pad () +
+gboolean + +gst_element_remove_pad () +
+GstIterator * + +gst_element_iterate_pads () +
+GstIterator * + +gst_element_iterate_sink_pads () +
+GstIterator * + +gst_element_iterate_src_pads () +
+gboolean + +(*GstElementForeachPadFunc) () +
+gboolean + +gst_element_foreach_pad () +
+gboolean + +gst_element_foreach_sink_pad () +
+gboolean + +gst_element_foreach_src_pad () +
+gboolean + +gst_element_link () +
+void + +gst_element_unlink () +
+gboolean + +gst_element_link_many () +
+void + +gst_element_unlink_many () +
+gboolean + +gst_element_link_pads () +
+gboolean + +gst_element_link_pads_full () +
+void + +gst_element_unlink_pads () +
+gboolean + +gst_element_link_pads_filtered () +
+gboolean + +gst_element_link_filtered () +
const gchar * + +gst_element_class_get_metadata () +
const gchar * + +gst_element_get_metadata () +
+void + +gst_element_set_base_time () +
+GstClockTime + +gst_element_get_base_time () +
+void + +gst_element_set_start_time () +
+GstClockTime + +gst_element_get_start_time () +
+void + +gst_element_set_bus () +
+GstBus * + +gst_element_get_bus () +
+void + +gst_element_set_context () +
+GstContext * + +gst_element_get_context () +
+GstContext * + +gst_element_get_context_unlocked () +
+GList * + +gst_element_get_contexts () +
+GstElementFactory * + +gst_element_get_factory () +
#define +gst_element_set_name() +
#define +gst_element_get_name() +
#define +gst_element_set_parent() +
#define +gst_element_get_parent() +
+GstPadTemplate * + +gst_element_get_pad_template () +
+GList * + +gst_element_get_pad_template_list () +
+gboolean + +gst_element_set_clock () +
+GstClock * + +gst_element_get_clock () +
+GstClock * + +gst_element_provide_clock () +
+GstStateChangeReturn + +gst_element_set_state () +
+GstStateChangeReturn + +gst_element_get_state () +
+gboolean + +gst_element_set_locked_state () +
+gboolean + +gst_element_is_locked_state () +
+void + +gst_element_abort_state () +
+GstStateChangeReturn + +gst_element_continue_state () +
+void + +gst_element_lost_state () +
const gchar * + +gst_element_state_get_name () +
const gchar * + +gst_element_state_change_return_get_name () +
+gboolean + +gst_element_sync_state_with_parent () +
+GstStateChangeReturn + +gst_element_change_state () +
const gchar * + +gst_state_change_get_name () +
+void + +gst_element_message_full () +
+void + +gst_element_message_full_with_details () +
+GstStructure * + +gst_make_element_message_details () +
+gboolean + +gst_element_post_message () +
+gboolean + +gst_element_query () +
+gboolean + +gst_element_query_convert () +
+gboolean + +gst_element_query_position () +
+gboolean + +gst_element_query_duration () +
+gboolean + +gst_element_send_event () +
+gboolean + +gst_element_seek_simple () +
+gboolean + +gst_element_seek () +
+gulong + +gst_element_add_property_notify_watch () +
+gulong + +gst_element_add_property_deep_notify_watch () +
+void + +gst_element_remove_property_notify_watch () +
+void + +(*GstElementCallAsyncFunc) () +
+void + +gst_element_call_async () +
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + +
voidno-more-padsRun Last
voidpad-addedRun Last
voidpad-removedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstElement
structGstElementClass
enumGstElementFlags
enumGstState
enumGstStateChange
enumGstStateChangeReturn
#defineGST_ELEMENT_METADATA_AUTHOR
#defineGST_ELEMENT_METADATA_DESCRIPTION
#defineGST_ELEMENT_METADATA_DOC_URI
#defineGST_ELEMENT_METADATA_ICON_NAME
#defineGST_ELEMENT_METADATA_KLASS
#defineGST_ELEMENT_METADATA_LONGNAME
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBin
+
+
+
+

Known Derived Interfaces

+

+GstElement is required by + GstTagSetter.

+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstElement is the abstract base class needed to construct an element that +can be used in a GStreamer pipeline. Please refer to the plugin writers +guide for more information on creating GstElement subclasses.

+

The name of a GstElement can be get with gst_element_get_name() and set with +gst_element_set_name(). For speed, GST_ELEMENT_NAME() can be used in the +core when using the appropriate locking. Do not use this in plug-ins or +applications in order to retain ABI compatibility.

+

Elements can have pads (of the type GstPad). These pads link to pads on +other elements. GstBuffer flow between these linked pads. +A GstElement has a GList of GstPad structures for all their input (or sink) +and output (or source) pads. +Core and plug-in writers can add and remove pads with gst_element_add_pad() +and gst_element_remove_pad().

+

An existing pad of an element can be retrieved by name with +gst_element_get_static_pad(). A new dynamic pad can be created using +gst_element_request_pad() with a GstPadTemplate. +An iterator of all pads can be retrieved with gst_element_iterate_pads().

+

Elements can be linked through their pads. +If the link is straightforward, use the gst_element_link() +convenience function to link two elements, or gst_element_link_many() +for more elements in a row. +Use gst_element_link_filtered() to link two elements constrained by +a specified set of GstCaps. +For finer control, use gst_element_link_pads() and +gst_element_link_pads_filtered() to specify the pads to link on +each element by name.

+

Each element has a state (see GstState). You can get and set the state +of an element with gst_element_get_state() and gst_element_set_state(). +Setting a state triggers a GstStateChange. To get a string representation +of a GstState, use gst_element_state_get_name().

+

You can get and set a GstClock on an element using gst_element_get_clock() +and gst_element_set_clock(). +Some elements can provide a clock for the pipeline if +the GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the +gst_element_provide_clock() method one can retrieve the clock provided by +such an element. +Not all elements require a clock to operate correctly. If the +GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the +element with gst_element_set_clock().

+

Note that clock selection and distribution is normally handled by the +toplevel GstPipeline so the clock functions are only to be used in very +specific situations.

+
+
+

Functions

+
+

GST_STATE()

+
#define GST_STATE(elem)                 (GST_ELEMENT_CAST(elem)->current_state)
+
+

This macro returns the current GstState of the element.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return state for.

 
+
+
+
+
+

GST_STATE_GET_NEXT()

+
#define GST_STATE_GET_NEXT(cur,pending)         ((GstState)((cur) + __GST_SIGN ((gint)(pending) - (gint)(cur))))
+
+

Given a current state cur + and a target state pending +, calculate the next (intermediate) +GstState.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cur

A starting GstState

 

pending

A target GstState

 
+
+
+
+
+

GST_STATE_NEXT()

+
#define GST_STATE_NEXT(elem)            (GST_ELEMENT_CAST(elem)->next_state)
+
+

This macro returns the next GstState of the element.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return the next state for.

 
+
+
+
+
+

GST_STATE_PENDING()

+
#define GST_STATE_PENDING(elem)         (GST_ELEMENT_CAST(elem)->pending_state)
+
+

This macro returns the currently pending GstState of the element.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return the pending state for.

 
+
+
+
+
+

GST_STATE_RETURN()

+
#define GST_STATE_RETURN(elem)          (GST_ELEMENT_CAST(elem)->last_return)
+
+

This macro returns the last GstStateChangeReturn value.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return the last state result for.

 
+
+
+
+
+

GST_STATE_TARGET()

+
#define GST_STATE_TARGET(elem)          (GST_ELEMENT_CAST(elem)->target_state)
+
+

This macro returns the target GstState of the element.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return the target state for.

 
+
+
+
+
+

GST_STATE_TRANSITION()

+
#define GST_STATE_TRANSITION(cur,next)          ((GstStateChange)(((cur)<<3)|(next)))
+
+

Given a current state cur + and a next state next +, calculate the associated +GstStateChange transition.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cur

A current state

 

next

A next state

 
+
+
+
+
+

GST_STATE_TRANSITION_CURRENT()

+
#define GST_STATE_TRANSITION_CURRENT(trans)     ((GstState)((trans)>>3))
+
+

Given a state transition trans +, extract the current GstState.

+
+

Parameters

+
+++++ + + + + + +

trans

A GstStateChange

 
+
+
+
+
+

GST_STATE_TRANSITION_NEXT()

+
#define GST_STATE_TRANSITION_NEXT(trans)        ((GstState)((trans)&0x7))
+
+

Given a state transition trans +, extract the next GstState.

+
+

Parameters

+
+++++ + + + + + +

trans

A GstStateChange

 
+
+
+
+
+

GST_STATE_GET_LOCK()

+
#define GST_STATE_GET_LOCK(elem)               (&(GST_ELEMENT_CAST(elem)->state_lock))
+
+

Get a reference to the state lock of elem +. +This lock is used by the core. It is taken while getting or setting +the state, during state changes, and while finalizing.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement

 
+
+
+
+
+

GST_STATE_GET_COND()

+
#define GST_STATE_GET_COND(elem)               (&GST_ELEMENT_CAST(elem)->state_cond)
+
+

Get the conditional used to signal the completion of a state change.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement

 
+
+
+
+
+

GST_ELEMENT_NAME()

+
#define GST_ELEMENT_NAME(elem)                  (GST_OBJECT_NAME(elem))
+
+

Gets the name of this element. This is not thread-safe by default +(i.e. you will have to make sure the object lock is taken yourself). +If in doubt use gst_element_get_name() instead.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

GST_ELEMENT_PARENT()

+
#define GST_ELEMENT_PARENT(elem)                (GST_ELEMENT_CAST(GST_OBJECT_PARENT(elem)))
+
+

Get the parent object of this element. This is not thread-safe by default +(i.e. you will have to make sure the object lock is taken yourself). +If in doubt use gst_object_get_parent() instead.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

GST_ELEMENT_BUS()

+
#define GST_ELEMENT_BUS(elem)                   (GST_ELEMENT_CAST(elem)->bus)
+
+

Get the message bus of this element. This is not thread-safe by default +(i.e. you will have to make sure the object lock is taken yourself). +If in doubt use gst_element_get_bus() instead.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

GST_ELEMENT_CLOCK()

+
#define GST_ELEMENT_CLOCK(elem)                 (GST_ELEMENT_CAST(elem)->clock)
+
+

Get the clock of this element.This is not thread-safe by default +(i.e. you will have to make sure it is safe yourself). +If in doubt use gst_element_get_clock() instead.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

GST_ELEMENT_PADS()

+
#define GST_ELEMENT_PADS(elem)                  (GST_ELEMENT_CAST(elem)->pads)
+
+

Get the pads of this elements.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

GST_ELEMENT_START_TIME()

+
#define GST_ELEMENT_START_TIME(elem)            (GST_ELEMENT_CAST(elem)->start_time)
+
+

This macro returns the start_time of the elem +. The start_time is the +running_time of the pipeline when the element went to PAUSED.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to return the start time for.

 
+
+
+
+
+

GST_ELEMENT_ERROR()

+
#define             GST_ELEMENT_ERROR(el,domain,code,text,debug)
+

Utility function that elements can use in case they encountered a fatal +data processing error. The pipeline will post an error message and the +application will be requested to stop further media processing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the error

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 
+
+
+
+
+

GST_ELEMENT_ERROR_WITH_DETAILS()

+
#define             GST_ELEMENT_ERROR_WITH_DETAILS(el,domain,code,text,debug,args)
+

Utility function that elements can use in case they encountered a fatal +data processing error. The pipeline will post an error message and the +application will be requested to stop further media processing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the error

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 

args

optional name, type, value triplets, which will be stored +in the associated GstStructure. NULL terminator required. +Must be enclosed within parentheses.

 
+
+

Since: 1.10

+
+
+
+

GST_ELEMENT_FLOW_ERROR()

+
#define             GST_ELEMENT_FLOW_ERROR(el,flow_return)
+

Utility function that elements can use in case they encountered a fatal +data processing error due to wrong flow processing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

el

the element that generates the error

 

flow_return

the GstFlowReturn leading to that ERROR message

 
+
+

Since: 1.10

+
+
+
+

GST_ELEMENT_WARNING()

+
#define             GST_ELEMENT_WARNING(el, domain, code, text, debug)
+

Utility function that elements can use in case they encountered a non-fatal +data processing problem. The pipeline will post a warning message and the +application will be informed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the warning

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 
+
+
+
+
+

GST_ELEMENT_WARNING_WITH_DETAILS()

+
#define             GST_ELEMENT_WARNING_WITH_DETAILS(el, domain, code, text, debug, args)
+

Utility function that elements can use in case they encountered a non-fatal +data processing problem. The pipeline will post a warning message and the +application will be informed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the warning

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 

args

optional name, type, value triplets, which will be stored +in the associated GstStructure. NULL terminator required. +Must be enclosed within parentheses.

 
+
+

Since: 1.10

+
+
+
+

GST_ELEMENT_INFO()

+
#define             GST_ELEMENT_INFO(el, domain, code, text, debug)
+

Utility function that elements can use in case they want to inform +the application of something noteworthy that is not an error. +The pipeline will post a info message and the +application will be informed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the information

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 
+
+
+
+
+

GST_ELEMENT_INFO_WITH_DETAILS()

+
#define             GST_ELEMENT_INFO_WITH_DETAILS(el, domain, code, text, debug, args)
+

Utility function that elements can use in case they want to inform +the application of something noteworthy that is not an error. +The pipeline will post a info message and the +application will be informed. +Optional name, type, value triplets may be supplied, and will be stored +in the associated GstStructure. NULL terminator required.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

el

the element that generates the information

 

domain

like CORE, LIBRARY, RESOURCE or STREAM (see gstreamer-GstGError)

 

code

error code defined for that domain (see gstreamer-GstGError)

 

text

the message to display (format string and args enclosed in +parentheses)

 

debug

debugging information for the message (format string and args +enclosed in parentheses)

 

args

optional name, type, value triplets, which will be stored +in the associated GstStructure. NULL terminator required. +Must be enclosed within parentheses.

 
+
+

Since: 1.10

+
+
+
+

GST_ELEMENT_IS_LOCKED_STATE()

+
#define GST_ELEMENT_IS_LOCKED_STATE(elem)        (GST_OBJECT_FLAG_IS_SET(elem,GST_ELEMENT_FLAG_LOCKED_STATE))
+
+

Check if the element is in the locked state and therefore will ignore state +changes from its parent object.

+
+

Parameters

+
+++++ + + + + + +

elem

A GstElement to query

 
+
+
+
+
+

gst_element_class_add_pad_template ()

+
void
+gst_element_class_add_pad_template (GstElementClass *klass,
+                                    GstPadTemplate *templ);
+

Adds a padtemplate to an element class. This is mainly used in the _class_init +functions of classes. If a pad template with the same name as an already +existing one is added the old one is replaced by the new one.

+

templ +'s reference count will be incremented, and any floating +reference will be removed (see gst_object_ref_sink())

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

klass

the GstElementClass to add the pad template to.

 

templ

a GstPadTemplate to add to the element class.

[transfer floating]
+
+
+
+
+

gst_element_class_add_static_pad_template ()

+
void
+gst_element_class_add_static_pad_template
+                               (GstElementClass *klass,
+                                GstStaticPadTemplate *static_templ);
+

Adds a pad template to an element class based on the static pad template +templ +. This is mainly used in the _class_init functions of element +implementations. If a pad template with the same name already exists, +the old one is replaced by the new one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

klass

the GstElementClass to add the pad template to.

 

static_templ

GstStaticPadTemplate to add as pad template to the element class.

 
+
+

Since: 1.8

+
+
+
+

gst_element_class_add_static_pad_template_with_gtype ()

+
void
+gst_element_class_add_static_pad_template_with_gtype
+                               (GstElementClass *klass,
+                                GstStaticPadTemplate *static_templ,
+                                GType pad_type);
+

Adds a pad template to an element class based on the static pad template +templ +. This is mainly used in the _class_init functions of element +implementations. If a pad template with the same name already exists, +the old one is replaced by the new one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

klass

the GstElementClass to add the pad template to.

 

static_templ

GstStaticPadTemplate to add as pad template to the element class.

 

pad_type

The GType of the pad to create

 
+
+

Since: 1.14

+
+
+
+

gst_element_class_get_pad_template ()

+
GstPadTemplate *
+gst_element_class_get_pad_template (GstElementClass *element_class,
+                                    const gchar *name);
+

Retrieves a padtemplate from element_class + with the given name.

+

If you use this function in the GInstanceInitFunc of an object class +that has subclasses, make sure to pass the g_class parameter of the +GInstanceInitFunc here.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element_class

a GstElementClass to get the pad template of.

 

name

the name of the GstPadTemplate to get.

 
+
+
+

Returns

+

the GstPadTemplate with the +given name, or NULL if none was found. No unreferencing is +necessary.

+

[transfer none][nullable]

+
+
+
+
+

gst_element_class_get_pad_template_list ()

+
GList *
+gst_element_class_get_pad_template_list
+                               (GstElementClass *element_class);
+

Retrieves a list of the pad templates associated with element_class +. The +list must not be modified by the calling code.

+

If you use this function in the GInstanceInitFunc of an object class +that has subclasses, make sure to pass the g_class parameter of the +GInstanceInitFunc here.

+
+

Parameters

+
+++++ + + + + + +

element_class

a GstElementClass to get pad templates of.

 
+
+
+

Returns

+

the GList of +pad templates.

+

[transfer none][element-type Gst.PadTemplate]

+
+
+
+
+

gst_element_class_set_metadata ()

+
void
+gst_element_class_set_metadata (GstElementClass *klass,
+                                const gchar *longname,
+                                const gchar *classification,
+                                const gchar *description,
+                                const gchar *author);
+

Sets the detailed information for a GstElementClass.

+

This function is for use in _class_init functions only.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

longname

The long English name of the element. E.g. "File Sink"

 

classification

String describing the type of element, as an unordered list +separated with slashes ('/'). See draft-klass.txt of the design docs +for more details and common types. E.g: "Sink/File"

 

description

Sentence describing the purpose of the element. +E.g: "Write stream to a file"

 

author

Name and contact details of the author(s). Use \n to separate +multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"

 
+
+
+
+
+

gst_element_class_set_static_metadata ()

+
void
+gst_element_class_set_static_metadata (GstElementClass *klass,
+                                       const gchar *longname,
+                                       const gchar *classification,
+                                       const gchar *description,
+                                       const gchar *author);
+

Sets the detailed information for a GstElementClass.

+

This function is for use in _class_init functions only.

+

Same as gst_element_class_set_metadata(), but longname +, classification +, +description +, and author + must be static strings or inlined strings, as +they will not be copied. (GStreamer plugins will be made resident once +loaded, so this function can be used even from dynamically loaded plugins.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

longname

The long English name of the element. E.g. "File Sink"

 

classification

String describing the type of element, as an unordered list +separated with slashes ('/'). See draft-klass.txt of the design docs +for more details and common types. E.g: "Sink/File"

 

description

Sentence describing the purpose of the element. +E.g: "Write stream to a file"

 

author

Name and contact details of the author(s). Use \n to separate +multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"

 
+
+
+
+
+

gst_element_class_add_metadata ()

+
void
+gst_element_class_add_metadata (GstElementClass *klass,
+                                const gchar *key,
+                                const gchar *value);
+

Set key + with value + as metadata in klass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

key

the key to set

 

value

the value to set

 
+
+
+
+
+

gst_element_class_add_static_metadata ()

+
void
+gst_element_class_add_static_metadata (GstElementClass *klass,
+                                       const gchar *key,
+                                       const gchar *value);
+

Set key + with value + as metadata in klass +.

+

Same as gst_element_class_add_metadata(), but value + must be a static string +or an inlined string, as it will not be copied. (GStreamer plugins will +be made resident once loaded, so this function can be used even from +dynamically loaded plugins.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

key

the key to set

 

value

the value to set

 
+
+
+
+
+

gst_element_add_pad ()

+
gboolean
+gst_element_add_pad (GstElement *element,
+                     GstPad *pad);
+

Adds a pad (link point) to element +. pad +'s parent will be set to element +; +see gst_object_set_parent() for refcounting information.

+

Pads are not automatically activated so elements should perform the needed +steps to activate the pad in case this pad is added in the PAUSED or PLAYING +state. See gst_pad_set_active() for more information about activating pads.

+

The pad and the element should be unlocked when calling this function.

+

This function will emit the “pad-added” signal on the element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to add the pad to.

 

pad

the GstPad to add to the element.

[transfer floating]
+
+
+

Returns

+

TRUE if the pad could be added. This function can fail when +a pad with the same name already existed or the pad already had another +parent.

+

MT safe.

+
+
+
+
+

gst_element_create_all_pads ()

+
void
+gst_element_create_all_pads (GstElement *element);
+

Creates a pad for each pad template that is always available. +This function is only useful during object initialization of +subclasses of GstElement.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to create pads for.

[transfer none]
+
+
+
+
+

gst_element_get_compatible_pad ()

+
GstPad *
+gst_element_get_compatible_pad (GstElement *element,
+                                GstPad *pad,
+                                GstCaps *caps);
+

Looks for an unlinked pad to which the given pad can link. It is not +guaranteed that linking the pads will work, though it should work in most +cases.

+

This function will first attempt to find a compatible unlinked ALWAYS pad, +and if none can be found, it will request a compatible REQUEST pad by looking +at the templates of element +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement in which the pad should be found.

[transfer none]

pad

the GstPad to find a compatible one for.

[transfer none]

caps

the GstCaps to use as a filter.

[allow-none]
+
+
+

Returns

+

the GstPad to which a link +can be made, or NULL if one cannot be found. gst_object_unref() +after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_get_compatible_pad_template ()

+
GstPadTemplate *
+gst_element_get_compatible_pad_template
+                               (GstElement *element,
+                                GstPadTemplate *compattempl);
+

Retrieves a pad template from element + that is compatible with compattempl +. +Pads from compatible templates can be linked together.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to get a compatible pad template for.

[transfer none]

compattempl

the GstPadTemplate to find a compatible +template for.

[transfer none]
+
+
+

Returns

+

a compatible GstPadTemplate, +or NULL if none was found. No unreferencing is necessary.

+

[transfer none][nullable]

+
+
+
+
+

gst_element_get_request_pad ()

+
GstPad *
+gst_element_get_request_pad (GstElement *element,
+                             const gchar *name);
+

Retrieves a pad from the element by name (e.g. "src_%d"). This version only +retrieves request pads. The pad should be released with +gst_element_release_request_pad().

+

This method is slower than manually getting the pad template and calling +gst_element_request_pad() if the pads should have a specific name (e.g. +name + is "src_1" instead of "src_%u").

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to find a request pad of.

 

name

the name of the request GstPad to retrieve.

 
+
+
+

Returns

+

requested GstPad if found, +otherwise NULL. Release after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_get_static_pad ()

+
GstPad *
+gst_element_get_static_pad (GstElement *element,
+                            const gchar *name);
+

Retrieves a pad from element + by name. This version only retrieves +already-existing (i.e. 'static') pads.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to find a static pad of.

 

name

the name of the static GstPad to retrieve.

 
+
+
+

Returns

+

the requested GstPad if +found, otherwise NULL. unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_request_pad ()

+
GstPad *
+gst_element_request_pad (GstElement *element,
+                         GstPadTemplate *templ,
+                         const gchar *name,
+                         const GstCaps *caps);
+

Retrieves a request pad from the element according to the provided template. +Pad templates can be looked up using +gst_element_factory_get_static_pad_templates().

+

The pad should be released with gst_element_release_request_pad().

+

[virtual request_new_pad]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to find a request pad of.

 

templ

a GstPadTemplate of which we want a pad of.

 

name

the name of the request GstPad +to retrieve. Can be NULL.

[transfer none][allow-none]

caps

the caps of the pad we want to +request. Can be NULL.

[transfer none][allow-none]
+
+
+

Returns

+

requested GstPad if found, +otherwise NULL. Release after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_no_more_pads ()

+
void
+gst_element_no_more_pads (GstElement *element);
+

Use this function to signal that the element does not expect any more pads +to show up in the current pipeline. This function should be called whenever +pads have been added by the element itself. Elements with GST_PAD_SOMETIMES +pad templates use this in combination with autopluggers to figure out that +the element is done initializing its pads.

+

This function emits the “no-more-pads” signal.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement

 
+
+
+
+
+

gst_element_release_request_pad ()

+
void
+gst_element_release_request_pad (GstElement *element,
+                                 GstPad *pad);
+

Makes the element free the previously requested pad as obtained +with gst_element_request_pad().

+

This does not unref the pad. If the pad was created by using +gst_element_request_pad(), gst_element_release_request_pad() needs to be +followed by gst_object_unref() to free the pad +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to release the request pad of.

 

pad

the GstPad to release.

 
+
+
+
+
+

gst_element_remove_pad ()

+
gboolean
+gst_element_remove_pad (GstElement *element,
+                        GstPad *pad);
+

Removes pad + from element +. pad + will be destroyed if it has not been +referenced elsewhere using gst_object_unparent().

+

This function is used by plugin developers and should not be used +by applications. Pads that were dynamically requested from elements +with gst_element_request_pad() should be released with the +gst_element_release_request_pad() function instead.

+

Pads are not automatically deactivated so elements should perform the needed +steps to deactivate the pad in case this pad is removed in the PAUSED or +PLAYING state. See gst_pad_set_active() for more information about +deactivating pads.

+

The pad and the element should be unlocked when calling this function.

+

This function will emit the “pad-removed” signal on the element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to remove pad from.

 

pad

the GstPad to remove from the element.

[transfer none]
+
+
+

Returns

+

TRUE if the pad could be removed. Can return FALSE if the +pad does not belong to the provided element.

+

MT safe.

+
+
+
+
+

gst_element_iterate_pads ()

+
GstIterator *
+gst_element_iterate_pads (GstElement *element);
+

Retrieves an iterator of element +'s pads. The iterator should +be freed after usage. Also more specialized iterators exists such as +gst_element_iterate_src_pads() or gst_element_iterate_sink_pads().

+

The order of pads returned by the iterator will be the order in which +the pads were added to the element.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to iterate pads of.

 
+
+
+

Returns

+

the GstIterator of GstPad.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_element_iterate_sink_pads ()

+
GstIterator *
+gst_element_iterate_sink_pads (GstElement *element);
+

Retrieves an iterator of element +'s sink pads.

+

The order of pads returned by the iterator will be the order in which +the pads were added to the element.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

the GstIterator of GstPad.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_element_iterate_src_pads ()

+
GstIterator *
+gst_element_iterate_src_pads (GstElement *element);
+

Retrieves an iterator of element +'s source pads.

+

The order of pads returned by the iterator will be the order in which +the pads were added to the element.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

the GstIterator of GstPad.

+

MT safe.

+

[transfer full]

+
+
+
+
+

GstElementForeachPadFunc ()

+
gboolean
+(*GstElementForeachPadFunc) (GstElement *element,
+                             GstPad *pad,
+                             gpointer user_data);
+

Function called for each pad when using gst_element_foreach_sink_pad(), +gst_element_foreach_src_pad(), or gst_element_foreach_pad().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

the GstElement

 

pad

a GstPad

 

user_data

user data passed to the foreach function

 
+
+
+

Returns

+

FALSE to stop iterating pads, TRUE to continue

+
+

Since: 1.14

+
+
+
+

gst_element_foreach_pad ()

+
gboolean
+gst_element_foreach_pad (GstElement *element,
+                         GstElementForeachPadFunc func,
+                         gpointer user_data);
+

Call func + with user_data + for each of element +'s pads. func + will be called +exactly once for each pad that exists at the time of this call, unless +one of the calls to func + returns FALSE in which case we will stop +iterating pads and return early. If new pads are added or pads are removed +while pads are being iterated, this will not be taken into account until +next time this function is used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to iterate pads of

 

func

function to call for each pad.

[scope call]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

FALSE if element +had no pads or if one of the calls to func +returned FALSE.

+
+

Since: 1.14

+
+
+
+

gst_element_foreach_sink_pad ()

+
gboolean
+gst_element_foreach_sink_pad (GstElement *element,
+                              GstElementForeachPadFunc func,
+                              gpointer user_data);
+

Call func + with user_data + for each of element +'s sink pads. func + will be +called exactly once for each sink pad that exists at the time of this call, +unless one of the calls to func + returns FALSE in which case we will stop +iterating pads and return early. If new sink pads are added or sink pads +are removed while the sink pads are being iterated, this will not be taken +into account until next time this function is used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to iterate sink pads of

 

func

function to call for each sink pad.

[scope call]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

FALSE if element +had no sink pads or if one of the calls to func +returned FALSE.

+
+

Since: 1.14

+
+
+
+

gst_element_foreach_src_pad ()

+
gboolean
+gst_element_foreach_src_pad (GstElement *element,
+                             GstElementForeachPadFunc func,
+                             gpointer user_data);
+

Call func + with user_data + for each of element +'s source pads. func + will be +called exactly once for each source pad that exists at the time of this call, +unless one of the calls to func + returns FALSE in which case we will stop +iterating pads and return early. If new source pads are added or source pads +are removed while the source pads are being iterated, this will not be taken +into account until next time this function is used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to iterate source pads of

 

func

function to call for each source pad.

[scope call]

user_data

user data passed to func +.

[closure]
+
+
+

Returns

+

FALSE if element +had no source pads or if one of the calls +to func +returned FALSE.

+
+

Since: 1.14

+
+
+
+

gst_element_link ()

+
gboolean
+gst_element_link (GstElement *src,
+                  GstElement *dest);
+

Links src + to dest +. The link must be from source to +destination; the other direction will not be tried. The function looks for +existing pads that aren't linked yet. It will request new pads if necessary. +Such pads need to be released manually when unlinking. +If multiple links are possible, only one is established.

+

Make sure you have added your elements to a bin or pipeline with +gst_bin_add() before trying to link them.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

a GstElement containing the source pad.

[transfer none]

dest

the GstElement containing the destination pad.

[transfer none]
+
+
+

Returns

+

TRUE if the elements could be linked, FALSE otherwise.

+
+
+
+
+

gst_element_unlink ()

+
void
+gst_element_unlink (GstElement *src,
+                    GstElement *dest);
+

Unlinks all source pads of the source element with all sink pads +of the sink element to which they are linked.

+

If the link has been made using gst_element_link(), it could have created an +requestpad, which has to be released using gst_element_release_request_pad().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

the source GstElement to unlink.

[transfer none]

dest

the sink GstElement to unlink.

[transfer none]
+
+
+
+
+

gst_element_link_many ()

+
gboolean
+gst_element_link_many (GstElement *element_1,
+                       GstElement *element_2,
+                       ...);
+

Chain together a series of elements. Uses gst_element_link(). +Make sure you have added your elements to a bin or pipeline with +gst_bin_add() before trying to link them.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element_1

the first GstElement in the link chain.

[transfer none]

element_2

the second GstElement in the link chain.

[transfer none]

...

the NULL-terminated list of elements to link in order.

 
+
+
+

Returns

+

TRUE on success, FALSE otherwise.

+
+
+
+
+

gst_element_unlink_many ()

+
void
+gst_element_unlink_many (GstElement *element_1,
+                         GstElement *element_2,
+                         ...);
+

Unlinks a series of elements. Uses gst_element_unlink().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element_1

the first GstElement in the link chain.

[transfer none]

element_2

the second GstElement in the link chain.

[transfer none]

...

the NULL-terminated list of elements to unlink in order.

 
+
+
+
+
+

gst_element_link_pads ()

+
gboolean
+gst_element_link_pads (GstElement *src,
+                       const gchar *srcpadname,
+                       GstElement *dest,
+                       const gchar *destpadname);
+

Links the two named pads of the source and destination elements. +Side effect is that if one of the pads has no parent, it becomes a +child of the parent of the other element. If they have different +parents, the link fails.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

a GstElement containing the source pad.

 

srcpadname

the name of the GstPad in source element +or NULL for any pad.

[allow-none]

dest

the GstElement containing the destination pad.

[transfer none]

destpadname

the name of the GstPad in destination element, +or NULL for any pad.

[allow-none]
+
+
+

Returns

+

TRUE if the pads could be linked, FALSE otherwise.

+
+
+
+
+

gst_element_link_pads_full ()

+
gboolean
+gst_element_link_pads_full (GstElement *src,
+                            const gchar *srcpadname,
+                            GstElement *dest,
+                            const gchar *destpadname,
+                            GstPadLinkCheck flags);
+

Links the two named pads of the source and destination elements. +Side effect is that if one of the pads has no parent, it becomes a +child of the parent of the other element. If they have different +parents, the link fails.

+

Calling gst_element_link_pads_full() with flags + == GST_PAD_LINK_CHECK_DEFAULT +is the same as calling gst_element_link_pads() and the recommended way of +linking pads with safety checks applied.

+

This is a convenience function for gst_pad_link_full().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

src

a GstElement containing the source pad.

 

srcpadname

the name of the GstPad in source element +or NULL for any pad.

[allow-none]

dest

the GstElement containing the destination pad.

[transfer none]

destpadname

the name of the GstPad in destination element, +or NULL for any pad.

[allow-none]

flags

the GstPadLinkCheck to be performed when linking pads.

 
+
+
+

Returns

+

TRUE if the pads could be linked, FALSE otherwise.

+
+
+
+
+

gst_element_unlink_pads ()

+
void
+gst_element_unlink_pads (GstElement *src,
+                         const gchar *srcpadname,
+                         GstElement *dest,
+                         const gchar *destpadname);
+

Unlinks the two named pads of the source and destination elements.

+

This is a convenience function for gst_pad_unlink().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

a (transfer none): GstElement containing the source pad.

 

srcpadname

the name of the GstPad in source element.

 

dest

a GstElement containing the destination pad.

[transfer none]

destpadname

the name of the GstPad in destination element.

 
+
+
+
+
+

gst_element_link_pads_filtered ()

+
gboolean
+gst_element_link_pads_filtered (GstElement *src,
+                                const gchar *srcpadname,
+                                GstElement *dest,
+                                const gchar *destpadname,
+                                GstCaps *filter);
+

Links the two named pads of the source and destination elements. Side effect +is that if one of the pads has no parent, it becomes a child of the parent of +the other element. If they have different parents, the link fails. If caps + +is not NULL, makes sure that the caps of the link is a subset of caps +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

src

a GstElement containing the source pad.

 

srcpadname

the name of the GstPad in source element +or NULL for any pad.

[allow-none]

dest

the GstElement containing the destination pad.

[transfer none]

destpadname

the name of the GstPad in destination element +or NULL for any pad.

[allow-none]

filter

the GstCaps to filter the link, +or NULL for no filter.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if the pads could be linked, FALSE otherwise.

+
+
+
+
+

gst_element_link_filtered ()

+
gboolean
+gst_element_link_filtered (GstElement *src,
+                           GstElement *dest,
+                           GstCaps *filter);
+

Links src + to dest + using the given caps as filtercaps. +The link must be from source to +destination; the other direction will not be tried. The function looks for +existing pads that aren't linked yet. It will request new pads if necessary. +If multiple links are possible, only one is established.

+

Make sure you have added your elements to a bin or pipeline with +gst_bin_add() before trying to link them.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

a GstElement containing the source pad.

 

dest

the GstElement containing the destination pad.

[transfer none]

filter

the GstCaps to filter the link, +or NULL for no filter.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if the pads could be linked, FALSE otherwise.

+
+
+
+
+

gst_element_class_get_metadata ()

+
const gchar *
+gst_element_class_get_metadata (GstElementClass *klass,
+                                const gchar *key);
+

Get metadata with key + in klass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

klass

class to get metadata for

 

key

the key to get

 
+
+
+

Returns

+

the metadata for key +.

+
+
+
+
+

gst_element_get_metadata ()

+
const gchar *
+gst_element_get_metadata (GstElement *element,
+                          const gchar *key);
+

Get metadata with key + in klass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

class to get metadata for

 

key

the key to get

 
+
+
+

Returns

+

the metadata for key +.

+
+

Since: 1.14

+
+
+
+

gst_element_set_base_time ()

+
void
+gst_element_set_base_time (GstElement *element,
+                           GstClockTime time);
+

Set the base time of an element. See gst_element_get_base_time().

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement.

 

time

the base time to set.

 
+
+
+
+
+

gst_element_get_base_time ()

+
GstClockTime
+gst_element_get_base_time (GstElement *element);
+

Returns the base time of the element. The base time is the +absolute time of the clock when this element was last put to +PLAYING. Subtracting the base time from the clock time gives +the running time of the element.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

the base time of the element.

+

MT safe.

+
+
+
+
+

gst_element_set_start_time ()

+
void
+gst_element_set_start_time (GstElement *element,
+                            GstClockTime time);
+

Set the start time of an element. The start time of the element is the +running time of the element when it last went to the PAUSED state. In READY +or after a flushing seek, it is set to 0.

+

Toplevel elements like GstPipeline will manage the start_time and +base_time on its children. Setting the start_time to GST_CLOCK_TIME_NONE +on such a toplevel element will disable the distribution of the base_time to +the children and can be useful if the application manages the base_time +itself, for example if you want to synchronize capture from multiple +pipelines, and you can also ensure that the pipelines have the same clock.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement.

 

time

the base time to set.

 
+
+
+
+
+

gst_element_get_start_time ()

+
GstClockTime
+gst_element_get_start_time (GstElement *element);
+

Returns the start time of the element. The start time is the +running time of the clock when this element was last put to PAUSED.

+

Usually the start_time is managed by a toplevel element such as +GstPipeline.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

the start time of the element.

+
+
+
+
+

gst_element_set_bus ()

+
void
+gst_element_set_bus (GstElement *element,
+                     GstBus *bus);
+

Sets the bus of the element. Increases the refcount on the bus. +For internal use only, unless you're testing elements.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to set the bus of.

 

bus

the GstBus to set.

[transfer none][allow-none]
+
+
+
+
+

gst_element_get_bus ()

+
GstBus *
+gst_element_get_bus (GstElement *element);
+

Returns the bus of the element. Note that only a GstPipeline will provide a +bus for the application.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to get the bus of.

 
+
+
+

Returns

+

the element's GstBus. unref after +usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_set_context ()

+
void
+gst_element_set_context (GstElement *element,
+                         GstContext *context);
+

Sets the context of the element. Increases the refcount of the context.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to set the context of.

 

context

the GstContext to set.

[transfer none]
+
+
+
+
+

gst_element_get_context ()

+
GstContext *
+gst_element_get_context (GstElement *element,
+                         const gchar *context_type);
+

Gets the context with context_type + set on the element or NULL.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to get the context of.

 

context_type

a name of a context to retrieve

 
+
+
+

Returns

+

A GstContext or NULL.

+

[transfer full]

+
+

Since: 1.8

+
+
+
+

gst_element_get_context_unlocked ()

+
GstContext *
+gst_element_get_context_unlocked (GstElement *element,
+                                  const gchar *context_type);
+

Gets the context with context_type + set on the element or NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to get the context of.

 

context_type

a name of a context to retrieve

 
+
+
+

Returns

+

A GstContext or NULL.

+

[transfer full][nullable]

+
+

Since: 1.8

+
+
+
+

gst_element_get_contexts ()

+
GList *
+gst_element_get_contexts (GstElement *element);
+

Gets the contexts set on the element.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to set the context of.

 
+
+
+

Returns

+

List of GstContext.

+

[element-type Gst.Context][transfer full]

+
+

Since: 1.8

+
+
+
+

gst_element_get_factory ()

+
GstElementFactory *
+gst_element_get_factory (GstElement *element);
+

Retrieves the factory that was used to create this element.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to request the element factory of.

 
+
+
+

Returns

+

the GstElementFactory used for creating this +element. no refcounting is needed.

+

[transfer none]

+
+
+
+
+

gst_element_set_name()

+
#define                 gst_element_set_name(elem,name) gst_object_set_name(GST_OBJECT_CAST(elem),name)
+
+

Sets the name of the element, getting rid of the old name if there was one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

elem

a GstElement to set the name of.

 

name

the new name

 
+
+
+
+
+

gst_element_get_name()

+
#define                 gst_element_get_name(elem)      gst_object_get_name(GST_OBJECT_CAST(elem))
+
+

Returns a copy of the name of elem +. +Caller should g_free() the return value after usage. +For a nameless element, this returns NULL, which you can safely g_free() +as well.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to get the name of elem +.

 
+
+
+

Returns

+

the name of elem +. g_free() +after usage. MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_set_parent()

+
#define                 gst_element_set_parent(elem,parent)     gst_object_set_parent(GST_OBJECT_CAST(elem),parent)
+
+

Sets the parent of an element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

elem

a GstElement to set the parent of.

 

parent

the new parent GstObject of the element.

 
+
+
+
+
+

gst_element_get_parent()

+
#define                 gst_element_get_parent(elem)    gst_object_get_parent(GST_OBJECT_CAST(elem))
+
+

Get the parent of an element.

+
+

Parameters

+
+++++ + + + + + +

elem

a GstElement to get the parent of.

 
+
+
+

Returns

+

the parent of an element.

+

[transfer full]

+
+
+
+
+

gst_element_get_pad_template ()

+
GstPadTemplate *
+gst_element_get_pad_template (GstElement *element,
+                              const gchar *name);
+

Retrieves a padtemplate from element + with the given name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to get the pad template of.

 

name

the name of the GstPadTemplate to get.

 
+
+
+

Returns

+

the GstPadTemplate with the +given name, or NULL if none was found. No unreferencing is +necessary.

+

[transfer none][nullable]

+
+

Since: 1.14

+
+
+
+

gst_element_get_pad_template_list ()

+
GList *
+gst_element_get_pad_template_list (GstElement *element);
+

Retrieves a list of the pad templates associated with element +. The +list must not be modified by the calling code.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to get pad templates of.

 
+
+
+

Returns

+

the GList of +pad templates.

+

[transfer none][element-type Gst.PadTemplate]

+
+

Since: 1.14

+
+
+
+

gst_element_set_clock ()

+
gboolean
+gst_element_set_clock (GstElement *element,
+                       GstClock *clock);
+

Sets the clock for the element. This function increases the +refcount on the clock. Any previously set clock on the object +is unreffed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to set the clock for.

 

clock

the GstClock to set for the element.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if the element accepted the clock. An element can refuse a +clock when it, for example, is not able to slave its internal clock to the +clock +or when it requires a specific clock to operate.

+

MT safe.

+
+
+
+
+

gst_element_get_clock ()

+
GstClock *
+gst_element_get_clock (GstElement *element);
+

Gets the currently configured clock of the element. This is the clock as was +last set with gst_element_set_clock().

+

Elements in a pipeline will only have their clock set when the +pipeline is in the PLAYING state.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to get the clock of.

 
+
+
+

Returns

+

the GstClock of the element. unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_provide_clock ()

+
GstClock *
+gst_element_provide_clock (GstElement *element);
+

Get the clock provided by the given element.

+

An element is only required to provide a clock in the PAUSED +state. Some elements can provide a clock in other states.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to query

 
+
+
+

Returns

+

the GstClock provided by the +element or NULL if no clock could be provided. Unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_set_state ()

+
GstStateChangeReturn
+gst_element_set_state (GstElement *element,
+                       GstState state);
+

Sets the state of the element. This function will try to set the +requested state by going through all the intermediary states and calling +the class's state change function for each.

+

This function can return GST_STATE_CHANGE_ASYNC, in which case the +element will perform the remainder of the state change asynchronously in +another thread. +An application can use gst_element_get_state() to wait for the completion +of the state change or it can wait for a GST_MESSAGE_ASYNC_DONE or +GST_MESSAGE_STATE_CHANGED on the bus.

+

State changes to GST_STATE_READY or GST_STATE_NULL never return +GST_STATE_CHANGE_ASYNC.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to change state of.

 

state

the element's new GstState.

 
+
+
+

Returns

+

Result of the state change using GstStateChangeReturn.

+

MT safe.

+
+
+
+
+

gst_element_get_state ()

+
GstStateChangeReturn
+gst_element_get_state (GstElement *element,
+                       GstState *state,
+                       GstState *pending,
+                       GstClockTime timeout);
+

Gets the state of the element.

+

For elements that performed an ASYNC state change, as reported by +gst_element_set_state(), this function will block up to the +specified timeout value for the state change to complete. +If the element completes the state change or goes into +an error, this function returns immediately with a return value of +GST_STATE_CHANGE_SUCCESS or GST_STATE_CHANGE_FAILURE respectively.

+

For elements that did not return GST_STATE_CHANGE_ASYNC, this function +returns the current and pending state immediately.

+

This function returns GST_STATE_CHANGE_NO_PREROLL if the element +successfully changed its state but is not able to provide data yet. +This mostly happens for live sources that only produce data in +GST_STATE_PLAYING. While the state change return is equivalent to +GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that +some sink elements might not be able to complete their state change because +an element is not producing data to complete the preroll. When setting the +element to playing, the preroll will complete and playback will start.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to get the state of.

 

state

a pointer to GstState to hold the state. +Can be NULL.

[out][allow-none]

pending

a pointer to GstState to hold the pending +state. Can be NULL.

[out][allow-none]

timeout

a GstClockTime to specify the timeout for an async +state change or GST_CLOCK_TIME_NONE for infinite timeout.

 
+
+
+

Returns

+

GST_STATE_CHANGE_SUCCESS if the element has no more pending state +and the last state change succeeded, GST_STATE_CHANGE_ASYNC if the +element is still performing a state change or +GST_STATE_CHANGE_FAILURE if the last state change failed.

+

MT safe.

+
+
+
+
+

gst_element_set_locked_state ()

+
gboolean
+gst_element_set_locked_state (GstElement *element,
+                              gboolean locked_state);
+

Locks the state of an element, so state changes of the parent don't affect +this element anymore.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement

 

locked_state

TRUE to lock the element's state

 
+
+
+

Returns

+

TRUE if the state was changed, FALSE if bad parameters were given +or the elements state-locking needed no change.

+
+
+
+
+

gst_element_is_locked_state ()

+
gboolean
+gst_element_is_locked_state (GstElement *element);
+

Checks if the state of an element is locked. +If the state of an element is locked, state changes of the parent don't +affect the element. +This way you can leave currently unused elements inside bins. Just lock their +state before changing the state from GST_STATE_NULL.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

TRUE, if the element's state is locked.

+
+
+
+
+

gst_element_abort_state ()

+
void
+gst_element_abort_state (GstElement *element);
+

Abort the state change of the element. This function is used +by elements that do asynchronous state changes and find out +something is wrong.

+

This function should be called with the STATE_LOCK held.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement to abort the state of.

 
+
+
+
+
+

gst_element_continue_state ()

+
GstStateChangeReturn
+gst_element_continue_state (GstElement *element,
+                            GstStateChangeReturn ret);
+

Commit the state change of the element and proceed to the next +pending state if any. This function is used +by elements that do asynchronous state changes. +The core will normally call this method automatically when an +element returned GST_STATE_CHANGE_SUCCESS from the state change function.

+

If after calling this method the element still has not reached +the pending state, the next state change is performed.

+

This method is used internally and should normally not be called by plugins +or applications.

+

This function must be called with STATE_LOCK held.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to continue the state change of.

 

ret

The previous state return value

 
+
+
+

Returns

+

The result of the commit state change.

+

MT safe.

+
+
+
+
+

gst_element_lost_state ()

+
void
+gst_element_lost_state (GstElement *element);
+

Brings the element to the lost state. The current state of the +element is copied to the pending state so that any call to +gst_element_get_state() will return GST_STATE_CHANGE_ASYNC.

+

An ASYNC_START message is posted. If the element was PLAYING, it will +go to PAUSED. The element will be restored to its PLAYING state by +the parent pipeline when it prerolls again.

+

This is mostly used for elements that lost their preroll buffer +in the GST_STATE_PAUSED or GST_STATE_PLAYING state after a flush, +they will go to their pending state again when a new preroll buffer is +queued. This function can only be called when the element is currently +not in error or an async state change.

+

This function is used internally and should normally not be called from +plugins or applications.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement the state is lost of

 
+
+
+
+
+

gst_element_state_get_name ()

+
const gchar *
+gst_element_state_get_name (GstState state);
+

Gets a string representing the given state.

+
+

Parameters

+
+++++ + + + + + +

state

a GstState to get the name of.

 
+
+
+

Returns

+

a string with the name of the state.

+

[transfer none]

+
+
+
+
+

gst_element_state_change_return_get_name ()

+
const gchar *
+gst_element_state_change_return_get_name
+                               (GstStateChangeReturn state_ret);
+

Gets a string representing the given state change result.

+
+

Parameters

+
+++++ + + + + + +

state_ret

a GstStateChangeReturn to get the name of.

 
+
+
+

Returns

+

a string with the name of the state +result.

+

[transfer none]

+
+
+
+
+

gst_element_sync_state_with_parent ()

+
gboolean
+gst_element_sync_state_with_parent (GstElement *element);
+

Tries to change the state of the element to the same as its parent. +If this function returns FALSE, the state of element is undefined.

+
+

Parameters

+
+++++ + + + + + +

element

a GstElement.

 
+
+
+

Returns

+

TRUE, if the element's state could be synced to the parent's state.

+

MT safe.

+
+
+
+
+

gst_element_change_state ()

+
GstStateChangeReturn
+gst_element_change_state (GstElement *element,
+                          GstStateChange transition);
+

Perform transition + on element +.

+

This function must be called with STATE_LOCK held and is mainly used +internally.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement

 

transition

the requested transition

 
+
+
+

Returns

+

the GstStateChangeReturn of the state transition.

+
+
+
+
+

gst_state_change_get_name ()

+
const gchar *
+gst_state_change_get_name (GstStateChange transition);
+

Gets a string representing the given state transition.

+
+

Parameters

+
+++++ + + + + + +

transition

a GstStateChange to get the name of.

 
+
+
+

Returns

+

a string with the name of the state +result.

+

[transfer none]

+
+

Since: 1.14

+
+
+
+

gst_element_message_full ()

+
void
+gst_element_message_full (GstElement *element,
+                          GstMessageType type,
+                          GQuark domain,
+                          gint code,
+                          gchar *text,
+                          gchar *debug,
+                          const gchar *file,
+                          const gchar *function,
+                          gint line);
+

Post an error, warning or info message on the bus from inside an element.

+

type + must be of GST_MESSAGE_ERROR, GST_MESSAGE_WARNING or +GST_MESSAGE_INFO.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to send message from

 

type

the GstMessageType

 

domain

the GStreamer GError domain this message belongs to

 

code

the GError code belonging to the domain

 

text

an allocated text string to be used +as a replacement for the default message connected to code, +or NULL.

[allow-none][transfer full]

debug

an allocated debug message to be +used as a replacement for the default debugging information, +or NULL.

[allow-none][transfer full]

file

the source code file where the error was generated

 

function

the source code function where the error was generated

 

line

the source code line where the error was generated

 
+
+
+
+
+

gst_element_message_full_with_details ()

+
void
+gst_element_message_full_with_details (GstElement *element,
+                                       GstMessageType type,
+                                       GQuark domain,
+                                       gint code,
+                                       gchar *text,
+                                       gchar *debug,
+                                       const gchar *file,
+                                       const gchar *function,
+                                       gint line,
+                                       GstStructure *structure);
+

Post an error, warning or info message on the bus from inside an element.

+

type + must be of GST_MESSAGE_ERROR, GST_MESSAGE_WARNING or +GST_MESSAGE_INFO.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to send message from

 

type

the GstMessageType

 

domain

the GStreamer GError domain this message belongs to

 

code

the GError code belonging to the domain

 

text

an allocated text string to be used +as a replacement for the default message connected to code, +or NULL.

[allow-none][transfer full]

debug

an allocated debug message to be +used as a replacement for the default debugging information, +or NULL.

[allow-none][transfer full]

file

the source code file where the error was generated

 

function

the source code function where the error was generated

 

line

the source code line where the error was generated

 

structure

optional details structure.

[transfer full]
+
+

Since: 1.10

+
+
+
+

gst_make_element_message_details ()

+
GstStructure *
+gst_make_element_message_details (const char *name,
+                                  ...);
+
+
+
+

gst_element_post_message ()

+
gboolean
+gst_element_post_message (GstElement *element,
+                          GstMessage *message);
+

Post a message on the element's GstBus. This function takes ownership of the +message; if you want to access the message after this call, you should add an +additional reference before calling.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement posting the message

 

message

a GstMessage to post.

[transfer full]
+
+
+

Returns

+

TRUE if the message was successfully posted. The function returns +FALSE if the element did not have a bus.

+

MT safe.

+
+
+
+
+

gst_element_query ()

+
gboolean
+gst_element_query (GstElement *element,
+                   GstQuery *query);
+

Performs a query on the given element.

+

For elements that don't implement a query handler, this function +forwards the query to a random srcpad or to the peer of a +random linked sinkpad of this element.

+

Please note that some queries might need a running pipeline to work.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to perform the query on.

 

query

the GstQuery.

[transfer none]
+
+
+

Returns

+

TRUE if the query could be performed.

+

MT safe.

+
+
+
+
+

gst_element_query_convert ()

+
gboolean
+gst_element_query_convert (GstElement *element,
+                           GstFormat src_format,
+                           gint64 src_val,
+                           GstFormat dest_format,
+                           gint64 *dest_val);
+

Queries an element to convert src_val + in src_format + to dest_format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to invoke the convert query on.

 

src_format

a GstFormat to convert from.

 

src_val

a value to convert.

 

dest_format

the GstFormat to convert to.

 

dest_val

a pointer to the result.

[out]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_element_query_position ()

+
gboolean
+gst_element_query_position (GstElement *element,
+                            GstFormat format,
+                            gint64 *cur);
+

Queries an element (usually top-level pipeline or playbin element) for the +stream position in nanoseconds. This will be a value between 0 and the +stream duration (if the stream duration is known). This query will usually +only work once the pipeline is prerolled (i.e. reached PAUSED or PLAYING +state). The application will receive an ASYNC_DONE message on the pipeline +bus when that is the case.

+

If one repeatedly calls this function one can also create a query and reuse +it in gst_element_query().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to invoke the position query on.

 

format

the GstFormat requested

 

cur

a location in which to store the current +position, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_element_query_duration ()

+
gboolean
+gst_element_query_duration (GstElement *element,
+                            GstFormat format,
+                            gint64 *duration);
+

Queries an element (usually top-level pipeline or playbin element) for the +total stream duration in nanoseconds. This query will only work once the +pipeline is prerolled (i.e. reached PAUSED or PLAYING state). The application +will receive an ASYNC_DONE message on the pipeline bus when that is the case.

+

If the duration changes for some reason, you will get a DURATION_CHANGED +message on the pipeline bus, in which case you should re-query the duration +using this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to invoke the duration query on.

 

format

the GstFormat requested

 

duration

A location in which to store the total duration, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_element_send_event ()

+
gboolean
+gst_element_send_event (GstElement *element,
+                        GstEvent *event);
+

Sends an event to an element. If the element doesn't implement an +event handler, the event will be pushed on a random linked sink pad for +downstream events or a random linked source pad for upstream events.

+

This function takes ownership of the provided event so you should +gst_event_ref() it if you want to reuse the event after this call.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement to send the event to.

 

event

the GstEvent to send to the element.

[transfer full]
+
+
+

Returns

+

TRUE if the event was handled. Events that trigger a preroll (such +as flushing seeks and steps) will emit GST_MESSAGE_ASYNC_DONE.

+
+
+
+
+

gst_element_seek_simple ()

+
gboolean
+gst_element_seek_simple (GstElement *element,
+                         GstFormat format,
+                         GstSeekFlags seek_flags,
+                         gint64 seek_pos);
+

Simple API to perform a seek on the given element, meaning it just seeks +to the given position relative to the start of the stream. For more complex +operations like segment seeks (e.g. for looping) or changing the playback +rate or seeking relative to the last configured playback segment you should +use gst_element_seek().

+

In a completely prerolled PAUSED or PLAYING pipeline, seeking is always +guaranteed to return TRUE on a seekable media type or FALSE when the media +type is certainly not seekable (such as a live stream).

+

Some elements allow for seeking in the READY state, in this +case they will store the seek event and execute it when they are put to +PAUSED. If the element supports seek in READY, it will always return TRUE when +it receives the event in the READY state.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to seek on

 

format

a GstFormat to execute the seek in, such as GST_FORMAT_TIME

 

seek_flags

seek options; playback applications will usually want to use +GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here

 

seek_pos

position to seek to (relative to the start); if you are doing +a seek in GST_FORMAT_TIME this value is in nanoseconds - +multiply with GST_SECOND to convert seconds to nanoseconds or +with GST_MSECOND to convert milliseconds to nanoseconds.

 
+
+
+

Returns

+

TRUE if the seek operation succeeded. Flushing seeks will trigger a +preroll, which will emit GST_MESSAGE_ASYNC_DONE.

+
+
+
+
+

gst_element_seek ()

+
gboolean
+gst_element_seek (GstElement *element,
+                  gdouble rate,
+                  GstFormat format,
+                  GstSeekFlags flags,
+                  GstSeekType start_type,
+                  gint64 start,
+                  GstSeekType stop_type,
+                  gint64 stop);
+

Sends a seek event to an element. See gst_event_new_seek() for the details of +the parameters. The seek event is sent to the element using +gst_element_send_event().

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to send the event to.

 

rate

The new playback rate

 

format

The format of the seek values

 

flags

The optional seek flags.

 

start_type

The type and flags for the new start position

 

start

The value of the new start position

 

stop_type

The type and flags for the new stop position

 

stop

The value of the new stop position

 
+
+
+

Returns

+

TRUE if the event was handled. Flushing seeks will trigger a +preroll, which will emit GST_MESSAGE_ASYNC_DONE.

+
+
+
+
+

gst_element_add_property_notify_watch ()

+
gulong
+gst_element_add_property_notify_watch (GstElement *element,
+                                       const gchar *property_name,
+                                       gboolean include_value);
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to watch for property changes

 

property_name

name of property to watch for changes, or +NULL to watch all properties.

[allow-none]

include_value

whether to include the new property value in the message

 
+
+
+

Returns

+

a watch id, which can be used in connection with +gst_element_remove_property_notify_watch() to remove the watch again.

+
+

Since: 1.10

+
+
+
+

gst_element_add_property_deep_notify_watch ()

+
gulong
+gst_element_add_property_deep_notify_watch
+                               (GstElement *element,
+                                const gchar *property_name,
+                                gboolean include_value);
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to watch (recursively) for property changes

 

property_name

name of property to watch for changes, or +NULL to watch all properties.

[allow-none]

include_value

whether to include the new property value in the message

 
+
+
+

Returns

+

a watch id, which can be used in connection with +gst_element_remove_property_notify_watch() to remove the watch again.

+
+

Since: 1.10

+
+
+
+

gst_element_remove_property_notify_watch ()

+
void
+gst_element_remove_property_notify_watch
+                               (GstElement *element,
+                                gulong watch_id);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

a GstElement being watched for property changes

 

watch_id

watch id to remove

 
+
+

Since: 1.10

+
+
+
+

GstElementCallAsyncFunc ()

+
void
+(*GstElementCallAsyncFunc) (GstElement *element,
+                            gpointer user_data);
+
+
+
+

gst_element_call_async ()

+
void
+gst_element_call_async (GstElement *element,
+                        GstElementCallAsyncFunc func,
+                        gpointer user_data,
+                        GDestroyNotify destroy_notify);
+

Calls func + from another thread and passes user_data + to it. This is to be +used for cases when a state change has to be performed from a streaming +thread, directly via gst_element_set_state() or indirectly e.g. via SEEK +events.

+

Calling those functions directly from the streaming thread will cause +deadlocks in many situations, as they might involve waiting for the +streaming thread to shut down from this very streaming thread.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement

 

func

Function to call asynchronously from another thread

 

user_data

Data to pass to func +

 

destroy_notify

GDestroyNotify for user_data +

 
+
+

Since: 1.10

+
+
+
+

Types and Values

+
+

struct GstElement

+
struct GstElement {
+  GRecMutex             state_lock;
+
+  /* element state */
+  GCond                 state_cond;
+  guint32               state_cookie;
+  GstState              target_state;
+  GstState              current_state;
+  GstState              next_state;
+  GstState              pending_state;
+  GstStateChangeReturn  last_return;
+
+  GstBus               *bus;
+
+  /* allocated clock */
+  GstClock             *clock;
+  GstClockTimeDiff      base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
+  GstClockTime          start_time;
+
+  /* element pads, these lists can only be iterated while holding
+   * the LOCK or checking the cookie after each LOCK. */
+  guint16               numpads;
+  GList                *pads;
+  guint16               numsrcpads;
+  GList                *srcpads;
+  guint16               numsinkpads;
+  GList                *sinkpads;
+  guint32               pads_cookie;
+
+  /* with object LOCK */
+  GList                *contexts;
+};
+
+

GStreamer element abstract base class.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GRecMutex state_lock;

Used to serialize execution of gst_element_set_state()

 

GCond state_cond;

Used to signal completion of a state change

 

guint32 state_cookie;

Used to detect concurrent execution of +gst_element_set_state() and gst_element_get_state()

 

GstState target_state;

the target state of an element as set by the application

 

GstState current_state;

the current state of an element

 

GstState next_state;

the next state of an element, can be GST_STATE_VOID_PENDING if +the element is in the correct state.

 

GstState pending_state;

the final state the element should go to, can be +GST_STATE_VOID_PENDING if the element is in the correct state

 

GstStateChangeReturn last_return;

the last return value of an element state change

 

GstBus *bus;

the bus of the element. This bus is provided to the element by the +parent element or the application. A GstPipeline has a bus of its own.

 

GstClock *clock;

the clock of the element. This clock is usually provided to the +element by the toplevel GstPipeline.

 

GstClockTimeDiff base_time;

the time of the clock right before the element is set to +PLAYING. Subtracting base_time +from the current clock time in the PLAYING +state will yield the running_time against the clock.

 

GstClockTime start_time;

the running_time of the last PAUSED state

 

guint16 numpads;

number of pads of the element, includes both source and sink pads.

 

GList *pads;

list of pads.

[element-type Gst.Pad]

guint16 numsrcpads;

number of source pads of the element.

 

GList *srcpads;

list of source pads.

[element-type Gst.Pad]

guint16 numsinkpads;

number of sink pads of the element.

 

GList *sinkpads;

list of sink pads.

[element-type Gst.Pad]

guint32 pads_cookie;

updated whenever the a pad is added or removed

 

GList *contexts;

list of contexts.

[element-type Gst.Context]
+
+
+
+
+

struct GstElementClass

+
struct GstElementClass {
+  GstObjectClass         parent_class;
+
+  /* the element metadata */
+  gpointer		 metadata;
+
+  /* factory that the element was created from */
+  GstElementFactory     *elementfactory;
+
+  /* templates for our pads */
+  GList                 *padtemplates;
+  gint                   numpadtemplates;
+  guint32                pad_templ_cookie;
+
+  /* virtual methods for subclasses */
+
+  /* request/release pads */
+  /* FIXME 2.0 harmonize naming with gst_element_request_pad */
+  GstPad*               (*request_new_pad)      (GstElement *element, GstPadTemplate *templ,
+                                                 const gchar* name, const GstCaps *caps);
+
+  void                  (*release_pad)          (GstElement *element, GstPad *pad);
+
+  /* state changes */
+  GstStateChangeReturn (*get_state)             (GstElement * element, GstState * state,
+                                                 GstState * pending, GstClockTime timeout);
+  GstStateChangeReturn (*set_state)             (GstElement *element, GstState state);
+  GstStateChangeReturn (*change_state)          (GstElement *element, GstStateChange transition);
+  void                 (*state_changed)         (GstElement *element, GstState oldstate,
+                                                 GstState newstate, GstState pending);
+
+  /* bus */
+  void                  (*set_bus)              (GstElement * element, GstBus * bus);
+
+  /* set/get clocks */
+  GstClock*             (*provide_clock)        (GstElement *element);
+  gboolean              (*set_clock)            (GstElement *element, GstClock *clock);
+
+  /* query functions */
+  gboolean              (*send_event)           (GstElement *element, GstEvent *event);
+
+  gboolean              (*query)                (GstElement *element, GstQuery *query);
+
+  gboolean              (*post_message)         (GstElement *element, GstMessage *message);
+
+  void                  (*set_context)          (GstElement *element, GstContext *context);
+};
+
+

GStreamer element class. Override the vmethods to implement the element +functionality.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gpointer metadata;

metadata for elements of this class

 

GstElementFactory *elementfactory;

the GstElementFactory that creates these elements

 

GList *padtemplates;

a GList of GstPadTemplate

 

gint numpadtemplates;

the number of padtemplates

 

guint32 pad_templ_cookie;

changed whenever the padtemplates change

 

request_new_pad ()

called when a new pad is requested

 

release_pad ()

called when a request pad is to be released

 

get_state ()

get the state of the element

 

set_state ()

set a new state on the element

 

change_state ()

called by set_state +to perform an incremental state change

 

state_changed ()

called immediately after a new state was set.

 

set_bus ()

set a GstBus on the element

 

provide_clock ()

gets the GstClock provided by the element

 

set_clock ()

set the GstClock on the element

 

send_event ()

send a GstEvent to the element

 

query ()

perform a GstQuery on the element

 

post_message ()

called when a message is posted on the element. Chain up to +the parent class' handler to have it posted on the bus.

 

set_context ()

set a GstContext on the element

 
+
+
+
+
+

enum GstElementFlags

+

The standard flags that an element may have.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_ELEMENT_FLAG_LOCKED_STATE

+

ignore state changes from parent

+
 

GST_ELEMENT_FLAG_SINK

+

the element is a sink

+
 

GST_ELEMENT_FLAG_SOURCE

+

the element is a source.

+
 

GST_ELEMENT_FLAG_PROVIDE_CLOCK

+

the element can provide a clock

+
 

GST_ELEMENT_FLAG_REQUIRE_CLOCK

+

the element requires a clock

+
 

GST_ELEMENT_FLAG_INDEXABLE

+

the element can use an index

+
 

GST_ELEMENT_FLAG_LAST

+

offset to define more flags

+
 
+
+
+
+
+

enum GstState

+

The possible states an element can be in. States can be changed using +gst_element_set_state() and checked using gst_element_get_state().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_STATE_VOID_PENDING

+

no pending state.

+
 

GST_STATE_NULL

+

the NULL state or initial state of an element.

+
 

GST_STATE_READY

+

the element is ready to go to PAUSED.

+
 

GST_STATE_PAUSED

+

the element is PAUSED, it is ready to accept and + process data. Sink elements however only accept one + buffer and then block.

+
 

GST_STATE_PLAYING

+

the element is PLAYING, the GstClock is running and + the data is flowing.

+
 
+
+
+
+
+

enum GstStateChange

+

These are the different state changes an element goes through. +GST_STATE_NULLGST_STATE_PLAYING is called an upwards state change +and GST_STATE_PLAYINGGST_STATE_NULL a downwards state change.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_STATE_CHANGE_NULL_TO_READY

+

state change from NULL to READY.

+
    +
  • The element must check if the resources it needs are available. Device +sinks and -sources typically try to probe the device to constrain their +caps.

  • +
  • The element opens the device (in case feature need to be probed).

  • +
+
 

GST_STATE_CHANGE_READY_TO_PAUSED

+

state change from READY to PAUSED.

+
    +
  • The element pads are activated in order to receive data in PAUSED. +Streaming threads are started.

  • +
  • Some elements might need to return GST_STATE_CHANGE_ASYNC and complete +the state change when they have enough information. It is a requirement +for sinks to return GST_STATE_CHANGE_ASYNC and complete the state change +when they receive the first buffer or GST_EVENT_EOS (preroll). +Sinks also block the dataflow when in PAUSED.

  • +
  • A pipeline resets the running_time to 0.

  • +
  • Live sources return GST_STATE_CHANGE_NO_PREROLL and don't generate data.

  • +
+
 

GST_STATE_CHANGE_PAUSED_TO_PLAYING

+

state change from PAUSED to PLAYING.

+
    +
  • Most elements ignore this state change.

  • +
  • The pipeline selects a GstClock and distributes this to all the children +before setting them to PLAYING. This means that it is only allowed to +synchronize on the GstClock in the PLAYING state.

  • +
  • The pipeline uses the GstClock and the running_time to calculate the +base_time. The base_time is distributed to all children when performing +the state change.

  • +
  • Sink elements stop blocking on the preroll buffer or event and start +rendering the data.

  • +
  • Sinks can post GST_MESSAGE_EOS in the PLAYING state. It is not allowed +to post GST_MESSAGE_EOS when not in the PLAYING state.

  • +
  • While streaming in PAUSED or PLAYING elements can create and remove +sometimes pads.

  • +
  • Live sources start generating data and return GST_STATE_CHANGE_SUCCESS.

  • +
+
 

GST_STATE_CHANGE_PLAYING_TO_PAUSED

+

state change from PLAYING to PAUSED.

+
    +
  • Most elements ignore this state change.

  • +
  • The pipeline calculates the running_time based on the last selected +GstClock and the base_time. It stores this information to continue +playback when going back to the PLAYING state.

  • +
  • Sinks unblock any GstClock wait calls.

  • +
  • When a sink does not have a pending buffer to play, it returns +GST_STATE_CHANGE_ASYNC from this state change and completes the state +change when it receives a new buffer or an GST_EVENT_EOS.

  • +
  • Any queued GST_MESSAGE_EOS items are removed since they will be reposted +when going back to the PLAYING state. The EOS messages are queued in +GstBin containers.

  • +
  • Live sources stop generating data and return GST_STATE_CHANGE_NO_PREROLL.

  • +
+
 

GST_STATE_CHANGE_PAUSED_TO_READY

+

state change from PAUSED to READY.

+
    +
  • Sinks unblock any waits in the preroll.

  • +
  • Elements unblock any waits on devices

  • +
  • Chain or get_range functions return GST_FLOW_FLUSHING.

  • +
  • The element pads are deactivated so that streaming becomes impossible and +all streaming threads are stopped.

  • +
  • The sink forgets all negotiated formats

  • +
  • Elements remove all sometimes pads

  • +
+
 

GST_STATE_CHANGE_READY_TO_NULL

+

state change from READY to NULL.

+
    +
  • Elements close devices

  • +
  • Elements reset any internal state.

  • +
+
 

GST_STATE_CHANGE_NULL_TO_NULL

+

state change from NULL to NULL. (Since 1.14)

+
 

GST_STATE_CHANGE_READY_TO_READY

+

state change from READY to READY, +This might happen when going to PAUSED asynchronously failed, in that case +elements should make sure they are in a proper, coherent READY state. (Since 1.14)

+
 

GST_STATE_CHANGE_PAUSED_TO_PAUSED

+

state change from PAUSED to PAUSED. +This might happen when elements were in PLAYING state and 'lost state', +they should make sure to go back to real 'PAUSED' state (prerolling for example). (Since 1.14)

+
 

GST_STATE_CHANGE_PLAYING_TO_PLAYING

+

state change from PLAYING to PLAYING. (Since 1.14)

+
 
+
+
+
+
+

enum GstStateChangeReturn

+

The possible return values from a state change function such as +gst_element_set_state(). Only GST_STATE_CHANGE_FAILURE + is a real failure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_STATE_CHANGE_FAILURE

+

the state change failed

+
 

GST_STATE_CHANGE_SUCCESS

+

the state change succeeded

+
 

GST_STATE_CHANGE_ASYNC

+

the state change will happen asynchronously

+
 

GST_STATE_CHANGE_NO_PREROLL

+

the state change succeeded but the element + cannot produce data in GST_STATE_PAUSED. + This typically happens with live sources.

+
 
+
+
+
+
+

GST_ELEMENT_METADATA_AUTHOR

+
#define GST_ELEMENT_METADATA_AUTHOR        "author"
+
+

Name and contact details of the author(s). Use \n to separate +multiple author details. +E.g: "Joe Bloggs <joe.blogs at foo.com>"

+
+
+
+

GST_ELEMENT_METADATA_DESCRIPTION

+
#define GST_ELEMENT_METADATA_DESCRIPTION   "description"
+
+

Sentence describing the purpose of the element. +E.g: "Write stream to a file"

+
+
+
+

GST_ELEMENT_METADATA_DOC_URI

+
#define GST_ELEMENT_METADATA_DOC_URI       "doc-uri"
+
+

Set uri pointing to user documentation. Applications can use this to show +help for e.g. effects to users.

+
+
+
+

GST_ELEMENT_METADATA_ICON_NAME

+
#define GST_ELEMENT_METADATA_ICON_NAME     "icon-name"
+
+

Elements that bridge to certain other products can include an icon of that +used product. Application can show the icon in menus/selectors to help +identifying specific elements.

+
+
+
+

GST_ELEMENT_METADATA_KLASS

+
#define GST_ELEMENT_METADATA_KLASS         "klass"
+
+

String describing the type of element, as an unordered list +separated with slashes ('/'). See draft-klass.txt of the design docs +for more details and common types. E.g: "Sink/File"

+
+
+
+

GST_ELEMENT_METADATA_LONGNAME

+
#define GST_ELEMENT_METADATA_LONGNAME      "long-name"
+
+

The long English name of the element. E.g. "File Sink"

+
+
+
+

Signal Details

+
+

The “no-more-pads” signal

+
void
+user_function (GstElement *gstelement,
+               gpointer    user_data)
+

This signals that the element will not generate more dynamic pads. +Note that this signal will usually be emitted from the context of +the streaming thread.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

gstelement

the object which received the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “pad-added” signal

+
void
+user_function (GstElement *gstelement,
+               GstPad     *new_pad,
+               gpointer    user_data)
+

a new GstPad has been added to the element. Note that this signal will +usually be emitted from the context of the streaming thread. Also keep in +mind that if you add new elements to the pipeline in the signal handler +you will need to set them to the desired target state with +gst_element_set_state() or gst_element_sync_state_with_parent().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

gstelement

the object which received the signal

 

new_pad

the pad that has been added

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “pad-removed” signal

+
void
+user_function (GstElement *gstelement,
+               GstPad     *old_pad,
+               gpointer    user_data)
+

a GstPad has been removed from the element

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

gstelement

the object which received the signal

 

old_pad

the pad that has been removed

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

See Also

+

GstElementFactory, GstPad

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstElementFactory.html b/docs/gst/html/GstElementFactory.html new file mode 100644 index 0000000..49faa9b --- /dev/null +++ b/docs/gst/html/GstElementFactory.html @@ -0,0 +1,1227 @@ + + + + +GstElementFactory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstElementFactory

+

GstElementFactory — Create GstElements from a factory

+
+ + +
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ╰── GstElementFactory
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstElementFactory is used to create instances of elements. A +GstElementFactory can be added to a GstPlugin as it is also a +GstPluginFeature.

+

Use the gst_element_factory_find() and gst_element_factory_create() +functions to create element instances or use gst_element_factory_make() as a +convenient shortcut.

+

The following code example shows you how to create a GstFileSrc element.

+
+

Using an element factory

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
#include <gst/gst.h>
+
+GstElement *src;
+GstElementFactory *srcfactory;
+
+gst_init (&argc, &argv);
+
+srcfactory = gst_element_factory_find ("filesrc");
+g_return_if_fail (srcfactory != NULL);
+src = gst_element_factory_create (srcfactory, "src");
+g_return_if_fail (src != NULL);
+...
+
+ +

+
+
+
+

Functions

+
+

gst_element_register ()

+
gboolean
+gst_element_register (GstPlugin *plugin,
+                      const gchar *name,
+                      guint rank,
+                      GType type);
+

Create a new elementfactory capable of instantiating objects of the +type + and add the factory to plugin +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

plugin

GstPlugin to register the element with, or NULL for +a static element.

[allow-none]

name

name of elements of this type

 

rank

rank of element (higher rank means more importance when autoplugging)

 

type

GType of element to register

 
+
+
+

Returns

+

TRUE, if the registering succeeded, FALSE on error

+
+
+
+
+

gst_element_factory_find ()

+
GstElementFactory *
+gst_element_factory_find (const gchar *name);
+

Search for an element factory of the given name. Refs the returned +element factory; caller is responsible for unreffing.

+
+

Parameters

+
+++++ + + + + + +

name

name of factory to find

 
+
+
+

Returns

+

GstElementFactory if found, +NULL otherwise.

+

[transfer full][nullable]

+
+
+
+
+

gst_element_factory_get_element_type ()

+
GType
+gst_element_factory_get_element_type (GstElementFactory *factory);
+

Get the GType for elements managed by this factory. The type can +only be retrieved if the element factory is loaded, which can be +assured with gst_plugin_feature_load().

+
+

Parameters

+
+++++ + + + + + +

factory

factory to get managed GType from

 
+
+
+

Returns

+

the GType for elements managed by this factory or 0 if +the factory is not loaded.

+
+
+
+
+

gst_element_factory_get_metadata ()

+
const gchar *
+gst_element_factory_get_metadata (GstElementFactory *factory,
+                                  const gchar *key);
+

Get the metadata on factory + with key +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstElementFactory

 

key

a key

 
+
+
+

Returns

+

the metadata with key +on factory +or NULL +when there was no metadata with the given key +.

+

[nullable]

+
+
+
+
+

gst_element_factory_get_metadata_keys ()

+
gchar **
+gst_element_factory_get_metadata_keys (GstElementFactory *factory);
+

Get the available keys for the metadata on factory +.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstElementFactory

 
+
+
+

Returns

+

a NULL-terminated array of key strings, or NULL when there is no +metadata. Free with g_strfreev() when no longer needed.

+

[transfer full][element-type utf8][array zero-terminated=1][nullable]

+
+
+
+
+

gst_element_factory_get_num_pad_templates ()

+
guint
+gst_element_factory_get_num_pad_templates
+                               (GstElementFactory *factory);
+

Gets the number of pad_templates in this factory.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstElementFactory

 
+
+
+

Returns

+

the number of pad_templates

+
+
+
+
+

gst_element_factory_get_uri_type ()

+
GstURIType
+gst_element_factory_get_uri_type (GstElementFactory *factory);
+

Gets the type of URIs the element supports or GST_URI_UNKNOWN if none.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstElementFactory

 
+
+
+

Returns

+

type of URIs this element supports

+
+
+
+
+

gst_element_factory_get_uri_protocols ()

+
const gchar * const *
+gst_element_factory_get_uri_protocols (GstElementFactory *factory);
+

Gets a NULL-terminated array of protocols this element supports or NULL if +no protocols are supported. You may not change the contents of the returned +array, as it is still owned by the element factory. Use g_strdupv() to +make a copy of the protocol string array if you need to.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstElementFactory

 
+
+
+

Returns

+

the supported protocols +or NULL.

+

[transfer none][array zero-terminated=1]

+
+
+
+
+

gst_element_factory_has_interface ()

+
gboolean
+gst_element_factory_has_interface (GstElementFactory *factory,
+                                   const gchar *interfacename);
+

Check if factory + implements the interface with name interfacename +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstElementFactory

 

interfacename

an interface name

 
+
+
+

Returns

+

TRUE when factory +implement the interface.

+
+
+
+
+

gst_element_factory_create ()

+
GstElement *
+gst_element_factory_create (GstElementFactory *factory,
+                            const gchar *name);
+

Create a new element of the type defined by the given elementfactory. +It will be given the name supplied, since all elements require a name as +their first argument.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

factory to instantiate

 

name

name of new element, or NULL to automatically create +a unique name.

[allow-none]
+
+
+

Returns

+

new GstElement or NULL +if the element couldn't be created.

+

[transfer floating][nullable]

+
+
+
+
+

gst_element_factory_make ()

+
GstElement *
+gst_element_factory_make (const gchar *factoryname,
+                          const gchar *name);
+

Create a new element of the type defined by the given element factory. +If name is NULL, then the element will receive a guaranteed unique name, +consisting of the element factory name and a number. +If name is given, it will be given the name supplied.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factoryname

a named factory to instantiate

 

name

name of new element, or NULL to automatically create +a unique name.

[allow-none]
+
+
+

Returns

+

new GstElement or NULL +if unable to create element.

+

[transfer floating][nullable]

+
+
+
+
+

gst_element_factory_can_sink_all_caps ()

+
gboolean
+gst_element_factory_can_sink_all_caps (GstElementFactory *factory,
+                                       const GstCaps *caps);
+

Checks if the factory can sink all possible capabilities.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

factory to query

 

caps

the caps to check

 
+
+
+

Returns

+

TRUE if the caps are fully compatible.

+
+
+
+
+

gst_element_factory_can_src_all_caps ()

+
gboolean
+gst_element_factory_can_src_all_caps (GstElementFactory *factory,
+                                      const GstCaps *caps);
+

Checks if the factory can src all possible capabilities.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

factory to query

 

caps

the caps to check

 
+
+
+

Returns

+

TRUE if the caps are fully compatible.

+
+
+
+
+

gst_element_factory_can_sink_any_caps ()

+
gboolean
+gst_element_factory_can_sink_any_caps (GstElementFactory *factory,
+                                       const GstCaps *caps);
+

Checks if the factory can sink any possible capability.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

factory to query

 

caps

the caps to check

 
+
+
+

Returns

+

TRUE if the caps have a common subset.

+
+
+
+
+

gst_element_factory_can_src_any_caps ()

+
gboolean
+gst_element_factory_can_src_any_caps (GstElementFactory *factory,
+                                      const GstCaps *caps);
+

Checks if the factory can src any possible capability.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

factory to query

 

caps

the caps to check

 
+
+
+

Returns

+

TRUE if the caps have a common subset.

+
+
+
+
+

gst_element_factory_get_static_pad_templates ()

+
const GList *
+gst_element_factory_get_static_pad_templates
+                               (GstElementFactory *factory);
+

Gets the GList of GstStaticPadTemplate for this factory.

+
+

Parameters

+
+++++ + + + + + +

factory

a GstElementFactory

 
+
+
+

Returns

+

the +static pad templates.

+

[transfer none][element-type Gst.StaticPadTemplate]

+
+
+
+
+

gst_element_factory_list_filter ()

+
GList *
+gst_element_factory_list_filter (GList *list,
+                                 const GstCaps *caps,
+                                 GstPadDirection direction,
+                                 gboolean subsetonly);
+

Filter out all the elementfactories in list + that can handle caps + in +the given direction.

+

If subsetonly + is TRUE, then only the elements whose pads templates +are a complete superset of caps + will be returned. Else any element +whose pad templates caps can intersect with caps + will be returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GList of +GstElementFactory to filter.

[transfer none][element-type Gst.ElementFactory]

caps

a GstCaps

 

direction

a GstPadDirection to filter on

 

subsetonly

whether to filter on caps subsets or not.

 
+
+
+

Returns

+

a GList of +GstElementFactory elements that match the given requisites. +Use gst_plugin_feature_list_free after usage.

+

[transfer full][element-type Gst.ElementFactory]

+
+
+
+
+

gst_element_factory_list_get_elements ()

+
GList *
+gst_element_factory_list_get_elements (GstElementFactoryListType type,
+                                       GstRank minrank);
+

Get a list of factories that match the given type +. Only elements +with a rank greater or equal to minrank + will be returned. +The list of factories is returned by decreasing rank.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

a GstElementFactoryListType

 

minrank

Minimum rank

 
+
+
+

Returns

+

a GList of +GstElementFactory elements. Use gst_plugin_feature_list_free() after +usage.

+

[transfer full][element-type Gst.ElementFactory]

+
+
+
+
+

gst_element_factory_list_is_type ()

+
gboolean
+gst_element_factory_list_is_type (GstElementFactory *factory,
+                                  GstElementFactoryListType type);
+

Check if factory + is of the given types.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

a GstElementFactory

 

type

a GstElementFactoryListType

 
+
+
+

Returns

+

TRUE if factory +is of type +.

+
+
+
+
+

Types and Values

+
+

GstElementFactory

+
typedef struct _GstElementFactory GstElementFactory;
+

The opaque GstElementFactory data structure.

+
+
+
+

GstElementFactoryListType

+
typedef guint64 GstElementFactoryListType;
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_ANY

+
#define  GST_ELEMENT_FACTORY_TYPE_ANY ((GstElementFactoryListType)((G_GUINT64_CONSTANT (1) << 49) - 1))
+
+

Elements of any of the defined GST_ELEMENT_FACTORY_LIST types

+
+
+
+

GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS

+
#define GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE))
+
+

All sinks handling audio, video or image media types

+
+
+
+

GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER

+
#define GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO))
+
+

All encoders handling audio media types

+
+
+
+

GST_ELEMENT_FACTORY_TYPE_DECODABLE

+
#define             GST_ELEMENT_FACTORY_TYPE_DECODABLE
+

All elements used to 'decode' streams (decoders, demuxers, parsers, depayloaders)

+
+
+
+

GST_ELEMENT_FACTORY_TYPE_DECODER

+
#define  GST_ELEMENT_FACTORY_TYPE_DECODER        ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 0))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_DECRYPTOR

+
#define  GST_ELEMENT_FACTORY_TYPE_DECRYPTOR      ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 10))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_DEMUXER

+
#define  GST_ELEMENT_FACTORY_TYPE_DEMUXER        ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 5))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER

+
#define  GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER    ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 8))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_ENCODER

+
#define  GST_ELEMENT_FACTORY_TYPE_ENCODER        ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 1))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR

+
#define  GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR      ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 11))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_FORMATTER

+
#define  GST_ELEMENT_FACTORY_TYPE_FORMATTER      ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 9))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS

+
#define  GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS   ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 48))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO

+
#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO    ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 50))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE

+
#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE    ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 51))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA

+
#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 53))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE

+
#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 52))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO

+
#define  GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO    ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 49))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY

+
#define GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY ((GstElementFactoryListType)(~G_GUINT64_CONSTANT (0) << 48))
+
+

Elements matching any of the defined GST_ELEMENT_FACTORY_TYPE_MEDIA types

+

Note: Do not use this if you wish to not filter against any of the defined +media types. If you wish to do this, simply don't specify any +GST_ELEMENT_FACTORY_TYPE_MEDIA flag.

+
+
+
+

GST_ELEMENT_FACTORY_TYPE_MUXER

+
#define  GST_ELEMENT_FACTORY_TYPE_MUXER          ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 4))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_PARSER

+
#define  GST_ELEMENT_FACTORY_TYPE_PARSER         ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 6))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_PAYLOADER

+
#define  GST_ELEMENT_FACTORY_TYPE_PAYLOADER      ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 7))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_SINK

+
#define  GST_ELEMENT_FACTORY_TYPE_SINK           ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 2))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_SRC

+
#define  GST_ELEMENT_FACTORY_TYPE_SRC            ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 3))
+
+
+
+
+

GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER

+
#define GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE))
+
+

All encoders handling video or image media types

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstEvent.html b/docs/gst/html/GstEvent.html new file mode 100644 index 0000000..4ca7e28 --- /dev/null +++ b/docs/gst/html/GstEvent.html @@ -0,0 +1,4227 @@ + + + + +GstEvent: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstEvent

+

GstEvent — Structure describing events that are passed up and down + a pipeline

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_EVENT_MAKE_TYPE() +
#define +GST_EVENT_TYPE() +
#define +GST_EVENT_TYPE_NAME() +
#define +GST_EVENT_TIMESTAMP() +
#define +GST_EVENT_SEQNUM() +
#define +GST_EVENT_IS_UPSTREAM() +
#define +GST_EVENT_IS_DOWNSTREAM() +
#define +GST_EVENT_IS_SERIALIZED() +
#define +GST_EVENT_IS_STICKY() +
+GstEventTypeFlags + +gst_event_type_get_flags () +
const gchar * + +gst_event_type_get_name () +
+GQuark + +gst_event_type_to_quark () +
+GstEvent * + +gst_event_ref () +
+void + +gst_event_unref () +
+gboolean + +gst_event_replace () +
+GstEvent * + +gst_event_copy () +
+GstEvent * + +gst_event_steal () +
+gboolean + +gst_event_take () +
#define +gst_event_is_writable() +
#define +gst_event_make_writable() +
+GstStructure * + +gst_event_writable_structure () +
+GstEvent * + +gst_event_new_custom () +
const GstStructure * + +gst_event_get_structure () +
+gboolean + +gst_event_has_name () +
+guint32 + +gst_event_get_seqnum () +
+void + +gst_event_set_seqnum () +
+gint64 + +gst_event_get_running_time_offset () +
+void + +gst_event_set_running_time_offset () +
+GstEvent * + +gst_event_new_flush_start () +
+GstEvent * + +gst_event_new_flush_stop () +
+void + +gst_event_parse_flush_stop () +
+GstEvent * + +gst_event_new_eos () +
+GstEvent * + +gst_event_new_gap () +
+void + +gst_event_parse_gap () +
+GstEvent * + +gst_event_new_stream_start () +
+void + +gst_event_parse_stream_start () +
+void + +gst_event_set_stream_flags () +
+void + +gst_event_parse_stream_flags () +
+void + +gst_event_set_group_id () +
+gboolean + +gst_event_parse_group_id () +
+void + +gst_event_set_stream () +
+void + +gst_event_parse_stream () +
+GstEvent * + +gst_event_new_segment () +
+void + +gst_event_parse_segment () +
+void + +gst_event_copy_segment () +
+GstEvent * + +gst_event_new_tag () +
+void + +gst_event_parse_tag () +
+GstEvent * + +gst_event_new_buffer_size () +
+void + +gst_event_parse_buffer_size () +
+GstEvent * + +gst_event_new_qos () +
+void + +gst_event_parse_qos () +
+GstEvent * + +gst_event_new_seek () +
+void + +gst_event_parse_seek () +
+GstEvent * + +gst_event_new_navigation () +
+GstEvent * + +gst_event_new_latency () +
+void + +gst_event_parse_latency () +
+GstEvent * + +gst_event_new_step () +
+void + +gst_event_parse_step () +
+GstEvent * + +gst_event_new_sink_message () +
+void + +gst_event_parse_sink_message () +
+GstEvent * + +gst_event_new_reconfigure () +
+GstEvent * + +gst_event_new_caps () +
+void + +gst_event_parse_caps () +
+GstEvent * + +gst_event_new_toc () +
+void + +gst_event_parse_toc () +
+GstEvent * + +gst_event_new_toc_select () +
+void + +gst_event_parse_toc_select () +
+GstEvent * + +gst_event_new_segment_done () +
+void + +gst_event_parse_segment_done () +
+GstEvent * + +gst_event_new_protection () +
+void + +gst_event_parse_protection () +
+GstEvent * + +gst_event_new_select_streams () +
+void + +gst_event_parse_select_streams () +
+GstEvent * + +gst_event_new_stream_collection () +
+void + +gst_event_parse_stream_collection () +
+GstEvent * + +gst_event_new_stream_group_done () +
+void + +gst_event_parse_stream_group_done () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstEvent
enumGstEventTypeFlags
#defineGST_EVENT_TYPE_BOTH
enumGstEventType
enumGstStreamFlags
enumGstQOSType
enumGstSeekType
enumGstSeekFlags
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstEvent
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

The event class provides factory methods to construct events for sending +and functions to query (parse) received events.

+

Events are usually created with gst_event_new_*() which takes event-type +specific parameters as arguments. +To send an event application will usually use gst_element_send_event() and +elements will use gst_pad_send_event() or gst_pad_push_event(). +The event should be unreffed with gst_event_unref() if it has not been sent.

+

Events that have been received can be parsed with their respective +gst_event_parse_*() functions. It is valid to pass NULL for unwanted details.

+

Events are passed between elements in parallel to the data stream. Some events +are serialized with buffers, others are not. Some events only travel downstream, +others only upstream. Some events can travel both upstream and downstream.

+

The events are used to signal special conditions in the datastream such as +EOS (end of stream) or the start of a new stream-segment. +Events are also used to flush the pipeline of any pending data.

+

Most of the event API is used inside plugins. Applications usually only +construct and use seek events. +To do that gst_event_new_seek() is used to create a seek event. It takes +the needed parameters to specify seeking time and mode.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
GstEvent *event;
+gboolean result;
+...
+// construct a seek event to play the media from second 2 to 5, flush
+// the pipeline to decrease latency.
+event = gst_event_new_seek (1.0,
+   GST_FORMAT_TIME,
+   GST_SEEK_FLAG_FLUSH,
+   GST_SEEK_TYPE_SET, 2 * GST_SECOND,
+   GST_SEEK_TYPE_SET, 5 * GST_SECOND);
+...
+result = gst_element_send_event (pipeline, event);
+if (!result)
+  g_warning ("seek failed");
+...
+
+ +

+
+
+

Functions

+
+

GST_EVENT_MAKE_TYPE()

+
#define             GST_EVENT_MAKE_TYPE(num,flags)
+

when making custom event types, use this macro with the num and +the given flags

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

num

the event number to create

 

flags

the event flags

 
+
+
+
+
+

GST_EVENT_TYPE()

+
#define GST_EVENT_TYPE(event)           (GST_EVENT_CAST(event)->type)
+
+

Get the GstEventType of the event.

+
+

Parameters

+
+++++ + + + + + +

event

the event to query

 
+
+
+
+
+

GST_EVENT_TYPE_NAME()

+
#define GST_EVENT_TYPE_NAME(event)      (gst_event_type_get_name(GST_EVENT_TYPE(event)))
+
+

Get a constant string representation of the GstEventType of the event.

+
+

Parameters

+
+++++ + + + + + +

event

the event to query

 
+
+
+
+
+

GST_EVENT_TIMESTAMP()

+
#define GST_EVENT_TIMESTAMP(event)      (GST_EVENT_CAST(event)->timestamp)
+
+

Get the GstClockTime timestamp of the event. This is the time when the event +was created.

+
+

Parameters

+
+++++ + + + + + +

event

the event to query

 
+
+
+
+
+

GST_EVENT_SEQNUM()

+
#define GST_EVENT_SEQNUM(event)         (GST_EVENT_CAST(event)->seqnum)
+
+

The sequence number of event +.

+
+

Parameters

+
+++++ + + + + + +

event

the event to query

 
+
+
+
+
+

GST_EVENT_IS_UPSTREAM()

+
#define GST_EVENT_IS_UPSTREAM(ev)       !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_UPSTREAM)
+
+

Check if an event can travel upstream.

+
+

Parameters

+
+++++ + + + + + +

ev

the event to query

 
+
+
+
+
+

GST_EVENT_IS_DOWNSTREAM()

+
#define GST_EVENT_IS_DOWNSTREAM(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_DOWNSTREAM)
+
+

Check if an event can travel downstream.

+
+

Parameters

+
+++++ + + + + + +

ev

the event to query

 
+
+
+
+
+

GST_EVENT_IS_SERIALIZED()

+
#define GST_EVENT_IS_SERIALIZED(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_SERIALIZED)
+
+

Check if an event is serialized with the data stream.

+
+

Parameters

+
+++++ + + + + + +

ev

the event to query

 
+
+
+
+
+

GST_EVENT_IS_STICKY()

+
#define GST_EVENT_IS_STICKY(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_STICKY)
+
+

Check if an event is sticky on the pads.

+
+

Parameters

+
+++++ + + + + + +

ev

the event to query

 
+
+
+
+
+

gst_event_type_get_flags ()

+
GstEventTypeFlags
+gst_event_type_get_flags (GstEventType type);
+

Gets the GstEventTypeFlags associated with type +.

+
+

Parameters

+
+++++ + + + + + +

type

a GstEventType

 
+
+
+

Returns

+

a GstEventTypeFlags.

+
+
+
+
+

gst_event_type_get_name ()

+
const gchar *
+gst_event_type_get_name (GstEventType type);
+

Get a printable name for the given event type. Do not modify or free.

+
+

Parameters

+
+++++ + + + + + +

type

the event type

 
+
+
+

Returns

+

a reference to the static name of the event.

+
+
+
+
+

gst_event_type_to_quark ()

+
GQuark
+gst_event_type_to_quark (GstEventType type);
+

Get the unique quark for the given event type.

+
+

Parameters

+
+++++ + + + + + +

type

the event type

 
+
+
+

Returns

+

the quark associated with the event type

+
+
+
+
+

gst_event_ref ()

+
GstEvent *
+gst_event_ref (GstEvent *event);
+

Increase the refcount of this event.

+
+

Parameters

+
+++++ + + + + + +

event

The event to refcount

 
+
+
+

Returns

+

event +(for convenience when doing assignments).

+

[transfer full]

+
+
+
+
+

gst_event_unref ()

+
void
+gst_event_unref (GstEvent *event);
+

Decrease the refcount of an event, freeing it if the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

event

the event to refcount.

[transfer full]
+
+
+
+
+

gst_event_replace ()

+
gboolean
+gst_event_replace (GstEvent **old_event,
+                   GstEvent *new_event);
+

Modifies a pointer to a GstEvent to point to a different GstEvent. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +event is unreffed, the new one is reffed).

+

Either new_event + or the GstEvent pointed to by old_event + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_event

pointer to a +pointer to a GstEvent to be replaced.

[inout][transfer full][nullable]

new_event

pointer to a GstEvent that will +replace the event pointed to by old_event +.

[allow-none][transfer none]
+
+
+

Returns

+

TRUE if new_event +was different from old_event +

+
+
+
+
+

gst_event_copy ()

+
GstEvent *
+gst_event_copy (const GstEvent *event);
+

Copy the event using the event specific copy function.

+
+

Parameters

+
+++++ + + + + + +

event

The event to copy

 
+
+
+

Returns

+

the new event.

+

[transfer full]

+
+
+
+
+

gst_event_steal ()

+
GstEvent *
+gst_event_steal (GstEvent **old_event);
+

Atomically replace the GstEvent pointed to by old_event + with NULL and +return the original event.

+
+

Parameters

+
+++++ + + + + + +

old_event

pointer to a +pointer to a GstEvent to be stolen.

[inout][transfer full][nullable]
+
+
+

Returns

+

the GstEvent that was in old_event +

+
+
+
+
+

gst_event_take ()

+
gboolean
+gst_event_take (GstEvent **old_event,
+                GstEvent *new_event);
+

Modifies a pointer to a GstEvent to point to a different GstEvent. This +function is similar to gst_event_replace() except that it takes ownership of +new_event +.

+

Either new_event + or the GstEvent pointed to by old_event + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_event

pointer to a +pointer to a GstEvent to be stolen.

[inout][transfer full][nullable]

new_event

pointer to a GstEvent that will +replace the event pointed to by old_event +.

[allow-none][transfer full]
+
+
+

Returns

+

TRUE if new_event +was different from old_event +

+
+
+
+
+

gst_event_is_writable()

+
#define         gst_event_is_writable(ev)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ev))
+
+

Tests if you can safely write data into a event's structure or validly +modify the seqnum and timestamp field.

+
+

Parameters

+
+++++ + + + + + +

ev

a GstEvent

 
+
+
+
+
+

gst_event_make_writable()

+
#define         gst_event_make_writable(ev)   GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ev)))
+
+

Makes a writable event from the given event. If the source event is +already writable, this will simply return the same event. A copy will +otherwise be made using gst_event_copy().

+
+

Parameters

+
+++++ + + + + + +

ev

a GstEvent.

[transfer full]
+
+
+

Returns

+

a writable event which may or may not be the +same as ev +.

+

[transfer full]

+
+
+
+
+

gst_event_writable_structure ()

+
GstStructure *
+gst_event_writable_structure (GstEvent *event);
+

Get a writable version of the structure.

+
+

Parameters

+
+++++ + + + + + +

event

The GstEvent.

 
+
+
+

Returns

+

The structure of the event. The structure +is still owned by the event, which means that you should not free +it and that the pointer becomes invalid when you free the event. +This function checks if event +is writable and will never return +NULL.

+

MT safe.

+

[transfer none]

+
+
+
+
+

gst_event_new_custom ()

+
GstEvent *
+gst_event_new_custom (GstEventType type,
+                      GstStructure *structure);
+

Create a new custom-typed event. This can be used for anything not +handled by other event-specific functions to pass an event to another +element.

+

Make sure to allocate an event type with the GST_EVENT_MAKE_TYPE macro, +assigning a free number and filling in the correct direction and +serialization flags.

+

New custom events can also be created by subclassing the event type if +needed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

The type of the new event

 

structure

the structure for the event. The event will +take ownership of the structure.

[transfer full]
+
+
+

Returns

+

the new custom event.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_get_structure ()

+
const GstStructure *
+gst_event_get_structure (GstEvent *event);
+

Access the structure of the event.

+
+

Parameters

+
+++++ + + + + + +

event

The GstEvent.

 
+
+
+

Returns

+

The structure of the event. The +structure is still owned by the event, which means that you should not free +it and that the pointer becomes invalid when you free the event.

+

MT safe.

+

[transfer none][nullable]

+
+
+
+
+

gst_event_has_name ()

+
gboolean
+gst_event_has_name (GstEvent *event,
+                    const gchar *name);
+

Checks if event + has the given name +. This function is usually used to +check the name of a custom event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The GstEvent.

 

name

name to check

 
+
+
+

Returns

+

TRUE if name +matches the name of the event structure.

+
+
+
+
+

gst_event_get_seqnum ()

+
guint32
+gst_event_get_seqnum (GstEvent *event);
+

Retrieve the sequence number of a event.

+

Events have ever-incrementing sequence numbers, which may also be set +explicitly via gst_event_set_seqnum(). Sequence numbers are typically used to +indicate that a event corresponds to some other set of events or messages, +for example an EOS event corresponding to a SEEK event. It is considered good +practice to make this correspondence when possible, though it is not +required.

+

Note that events and messages share the same sequence number incrementor; +two events or messages will never have the same sequence number unless +that correspondence was made explicitly.

+
+

Parameters

+
+++++ + + + + + +

event

A GstEvent.

 
+
+
+

Returns

+

The event's sequence number.

+

MT safe.

+
+
+
+
+

gst_event_set_seqnum ()

+
void
+gst_event_set_seqnum (GstEvent *event,
+                      guint32 seqnum);
+

Set the sequence number of a event.

+

This function might be called by the creator of a event to indicate that the +event relates to other events or messages. See gst_event_get_seqnum() for +more information.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

A GstEvent.

 

seqnum

A sequence number.

 
+
+
+
+
+

gst_event_get_running_time_offset ()

+
gint64
+gst_event_get_running_time_offset (GstEvent *event);
+

Retrieve the accumulated running time offset of the event.

+

Events passing through GstPads that have a running time +offset set via gst_pad_set_offset() will get their offset +adjusted according to the pad's offset.

+

If the event contains any information that related to the +running time, this information will need to be updated +before usage with this offset.

+
+

Parameters

+
+++++ + + + + + +

event

A GstEvent.

 
+
+
+

Returns

+

The event's running time offset

+

MT safe.

+
+

Since: 1.4

+
+
+
+

gst_event_set_running_time_offset ()

+
void
+gst_event_set_running_time_offset (GstEvent *event,
+                                   gint64 offset);
+

Set the running time offset of a event. See +gst_event_get_running_time_offset() for more information.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

A GstEvent.

 

offset

A the new running time offset

 
+
+

Since: 1.4

+
+
+
+

gst_event_new_flush_start ()

+
GstEvent *
+gst_event_new_flush_start (void);
+

Allocate a new flush start event. The flush start event can be sent +upstream and downstream and travels out-of-bounds with the dataflow.

+

It marks pads as being flushing and will make them return +GST_FLOW_FLUSHING when used for data flow with gst_pad_push(), +gst_pad_chain(), gst_pad_get_range() and gst_pad_pull_range(). +Any event (except a GST_EVENT_FLUSH_STOP) received +on a flushing pad will return FALSE immediately.

+

Elements should unlock any blocking functions and exit their streaming +functions as fast as possible when this event is received.

+

This event is typically generated after a seek to flush out all queued data +in the pipeline so that the new media is played as soon as possible.

+
+

Returns

+

a new flush start event.

+

[transfer full]

+
+
+
+
+

gst_event_new_flush_stop ()

+
GstEvent *
+gst_event_new_flush_stop (gboolean reset_time);
+

Allocate a new flush stop event. The flush stop event can be sent +upstream and downstream and travels serialized with the dataflow. +It is typically sent after sending a FLUSH_START event to make the +pads accept data again.

+

Elements can process this event synchronized with the dataflow since +the preceding FLUSH_START event stopped the dataflow.

+

This event is typically generated to complete a seek and to resume +dataflow.

+
+

Parameters

+
+++++ + + + + + +

reset_time

if time should be reset

 
+
+
+

Returns

+

a new flush stop event.

+

[transfer full]

+
+
+
+
+

gst_event_parse_flush_stop ()

+
void
+gst_event_parse_flush_stop (GstEvent *event,
+                            gboolean *reset_time);
+

Parse the FLUSH_STOP event and retrieve the reset_time + member.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to parse

 

reset_time

if time should be reset.

[out]
+
+
+
+
+

gst_event_new_eos ()

+
GstEvent *
+gst_event_new_eos (void);
+

Create a new EOS event. The eos event can only travel downstream +synchronized with the buffer flow. Elements that receive the EOS +event on a pad can return GST_FLOW_EOS as a GstFlowReturn +when data after the EOS event arrives.

+

The EOS event will travel down to the sink elements in the pipeline +which will then post the GST_MESSAGE_EOS on the bus after they have +finished playing any buffered data.

+

When all sinks have posted an EOS message, an EOS message is +forwarded to the application.

+

The EOS event itself will not cause any state transitions of the pipeline.

+
+

Returns

+

the new EOS event.

+

[transfer full]

+
+
+
+
+

gst_event_new_gap ()

+
GstEvent *
+gst_event_new_gap (GstClockTime timestamp,
+                   GstClockTime duration);
+

Create a new GAP event. A gap event can be thought of as conceptually +equivalent to a buffer to signal that there is no data for a certain +amount of time. This is useful to signal a gap to downstream elements +which may wait for data, such as muxers or mixers or overlays, especially +for sparse streams such as subtitle streams.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

timestamp

the start time (pts) of the gap

 

duration

the duration of the gap

 
+
+
+

Returns

+

the new GAP event.

+

[transfer full]

+
+
+
+
+

gst_event_parse_gap ()

+
void
+gst_event_parse_gap (GstEvent *event,
+                     GstClockTime *timestamp,
+                     GstClockTime *duration);
+

Extract timestamp and duration from a new GAP event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

event

a GstEvent of type GST_EVENT_GAP

 

timestamp

location where to store the +start time (pts) of the gap, or NULL.

[out][allow-none]

duration

location where to store the duration of +the gap, or NULL.

[out][allow-none]
+
+
+
+
+

gst_event_new_stream_start ()

+
GstEvent *
+gst_event_new_stream_start (const gchar *stream_id);
+

Create a new STREAM_START event. The stream start event can only +travel downstream synchronized with the buffer flow. It is expected +to be the first event that is sent for a new stream.

+

Source elements, demuxers and other elements that create new streams +are supposed to send this event as the first event of a new stream. It +should not be sent after a flushing seek or in similar situations +and is used to mark the beginning of a new logical stream. Elements +combining multiple streams must ensure that this event is only forwarded +downstream once and not for every single input stream.

+

The stream_id + should be a unique string that consists of the upstream +stream-id, / as separator and a unique stream-id for this specific +stream. A new stream-id should only be created for a stream if the upstream +stream is split into (potentially) multiple new streams, e.g. in a demuxer, +but not for every single element in the pipeline. +gst_pad_create_stream_id() or gst_pad_create_stream_id_printf() can be +used to create a stream-id. There are no particular semantics for the +stream-id, though it should be deterministic (to support stream matching) +and it might be used to order streams (besides any information conveyed by +stream flags).

+
+

Parameters

+
+++++ + + + + + +

stream_id

Identifier for this stream

 
+
+
+

Returns

+

the new STREAM_START event.

+

[transfer full]

+
+
+
+
+

gst_event_parse_stream_start ()

+
void
+gst_event_parse_stream_start (GstEvent *event,
+                              const gchar **stream_id);
+

Parse a stream-id event + and store the result in the given stream_id + +location. The string stored in stream_id + must not be modified and will +remain valid only until event + gets freed. Make a copy if you want to +modify it or store it for later use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event.

 

stream_id

pointer to store the stream-id.

[out][transfer none]
+
+
+
+
+

gst_event_set_stream_flags ()

+
void
+gst_event_set_stream_flags (GstEvent *event,
+                            GstStreamFlags flags);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

flags

the stream flags to set

 
+
+

Since: 1.2

+
+
+
+

gst_event_parse_stream_flags ()

+
void
+gst_event_parse_stream_flags (GstEvent *event,
+                              GstStreamFlags *flags);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

flags

address of variable where to store the stream flags.

[out]
+
+

Since: 1.2

+
+
+
+

gst_event_set_group_id ()

+
void
+gst_event_set_group_id (GstEvent *event,
+                        guint group_id);
+

All streams that have the same group id are supposed to be played +together, i.e. all streams inside a container file should have the +same group id but different stream ids. The group id should change +each time the stream is started, resulting in different group ids +each time a file is played for example.

+

Use gst_util_group_id_next() to get a new group id.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

group_id

the group id to set

 
+
+

Since: 1.2

+
+
+
+

gst_event_parse_group_id ()

+
gboolean
+gst_event_parse_group_id (GstEvent *event,
+                          guint *group_id);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

group_id

address of variable where to store the group id.

[out]
+
+
+

Returns

+

TRUE if a group id was set on the event and could be parsed, +FALSE otherwise.

+
+

Since: 1.2

+
+
+
+

gst_event_set_stream ()

+
void
+gst_event_set_stream (GstEvent *event,
+                      GstStream *stream);
+

Set the stream + on the stream-start event +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

stream

the stream object to set.

[transfer none]
+
+

Since: 1.10

+
+
+
+

gst_event_parse_stream ()

+
void
+gst_event_parse_stream (GstEvent *event,
+                        GstStream **stream);
+

Parse a stream-start event + and extract the GstStream from it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-start event

 

stream

adress of variable to store the stream.

[out][transfer full]
+
+

Since: 1.10

+
+
+
+

gst_event_new_segment ()

+
GstEvent *
+gst_event_new_segment (const GstSegment *segment);
+

Create a new SEGMENT event for segment +. The segment event can only travel +downstream synchronized with the buffer flow and contains timing information +and playback properties for the buffers that will follow.

+

The segment event marks the range of buffers to be processed. All +data not within the segment range is not to be processed. This can be +used intelligently by plugins to apply more efficient methods of skipping +unneeded data. The valid range is expressed with the start + and stop + +values.

+

The time value of the segment is used in conjunction with the start +value to convert the buffer timestamps into the stream time. This is +usually done in sinks to report the current stream_time. +time + represents the stream_time of a buffer carrying a timestamp of +start +. time + cannot be -1.

+

start + cannot be -1, stop + can be -1. If there +is a valid stop + given, it must be greater or equal the start +, including +when the indicated playback rate + is < 0.

+

The applied_rate + value provides information about any rate adjustment that +has already been made to the timestamps and content on the buffers of the +stream. (rate + * applied_rate +) should always equal the rate that has been +requested for playback. For example, if an element has an input segment +with intended playback rate + of 2.0 and applied_rate of 1.0, it can adjust +incoming timestamps and buffer content by half and output a segment event +with rate + of 1.0 and applied_rate + of 2.0

+

After a segment event, the buffer stream time is calculated with:

+

time + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)

+
+

Parameters

+
+++++ + + + + + +

segment

a GstSegment.

[transfer none]
+
+
+

Returns

+

the new SEGMENT event.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_parse_segment ()

+
void
+gst_event_parse_segment (GstEvent *event,
+                         const GstSegment **segment);
+

Parses a segment event + and stores the result in the given segment + location. +segment + remains valid only until the event + is freed. Don't modify the segment +and make a copy if you want to modify it or store it for later use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to parse

 

segment

a pointer to a GstSegment.

[out][transfer none]
+
+
+
+
+

gst_event_copy_segment ()

+
void
+gst_event_copy_segment (GstEvent *event,
+                        GstSegment *segment);
+

Parses a segment event + and copies the GstSegment into the location +given by segment +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to parse

 

segment

a pointer to a GstSegment

 
+
+
+
+
+

gst_event_new_tag ()

+
GstEvent *
+gst_event_new_tag (GstTagList *taglist);
+

Generates a metadata tag event from the given taglist +.

+

The scope of the taglist specifies if the taglist applies to the +complete medium or only to this specific stream. As the tag event +is a sticky event, elements should merge tags received from +upstream with a given scope with their own tags with the same +scope and create a new tag event from it.

+
+

Parameters

+
+++++ + + + + + +

taglist

metadata list. The event will take ownership +of the taglist.

[transfer full]
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_tag ()

+
void
+gst_event_parse_tag (GstEvent *event,
+                     GstTagList **taglist);
+

Parses a tag event + and stores the results in the given taglist + location. +No reference to the taglist will be returned, it remains valid only until +the event + is freed. Don't modify or free the taglist, make a copy if you +want to modify it or store it for later use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a tag event

 

taglist

pointer to metadata list.

[out][transfer none]
+
+
+
+
+

gst_event_new_buffer_size ()

+
GstEvent *
+gst_event_new_buffer_size (GstFormat format,
+                           gint64 minsize,
+                           gint64 maxsize,
+                           gboolean async);
+

Create a new buffersize event. The event is sent downstream and notifies +elements that they should provide a buffer of the specified dimensions.

+

When the async + flag is set, a thread boundary is preferred.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

format

buffer format

 

minsize

minimum buffer size

 

maxsize

maximum buffer size

 

async

thread behavior

 
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_buffer_size ()

+
void
+gst_event_parse_buffer_size (GstEvent *event,
+                             GstFormat *format,
+                             gint64 *minsize,
+                             gint64 *maxsize,
+                             gboolean *async);
+

Get the format, minsize, maxsize and async-flag in the buffersize event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

event

The event to query

 

format

A pointer to store the format in.

[out]

minsize

A pointer to store the minsize in.

[out]

maxsize

A pointer to store the maxsize in.

[out]

async

A pointer to store the async-flag in.

[out]
+
+
+
+
+

gst_event_new_qos ()

+
GstEvent *
+gst_event_new_qos (GstQOSType type,
+                   gdouble proportion,
+                   GstClockTimeDiff diff,
+                   GstClockTime timestamp);
+

Allocate a new qos event with the given values. +The QOS event is generated in an element that wants an upstream +element to either reduce or increase its rate because of +high/low CPU load or other resource usage such as network performance or +throttling. Typically sinks generate these events for each buffer +they receive.

+

type + indicates the reason for the QoS event. GST_QOS_TYPE_OVERFLOW is +used when a buffer arrived in time or when the sink cannot keep up with +the upstream datarate. GST_QOS_TYPE_UNDERFLOW is when the sink is not +receiving buffers fast enough and thus has to drop late buffers. +GST_QOS_TYPE_THROTTLE is used when the datarate is artificially limited +by the application, for example to reduce power consumption.

+

proportion + indicates the real-time performance of the streaming in the +element that generated the QoS event (usually the sink). The value is +generally computed based on more long term statistics about the streams +timestamps compared to the clock. +A value < 1.0 indicates that the upstream element is producing data faster +than real-time. A value > 1.0 indicates that the upstream element is not +producing data fast enough. 1.0 is the ideal proportion + value. The +proportion value can safely be used to lower or increase the quality of +the element.

+

diff + is the difference against the clock in running time of the last +buffer that caused the element to generate the QOS event. A negative value +means that the buffer with timestamp + arrived in time. A positive value +indicates how late the buffer with timestamp + was. When throttling is +enabled, diff + will be set to the requested throttling interval.

+

timestamp + is the timestamp of the last buffer that cause the element +to generate the QOS event. It is expressed in running time and thus an ever +increasing value.

+

The upstream element can use the diff + and timestamp + values to decide +whether to process more buffers. For positive diff +, all buffers with +timestamp <= timestamp + + diff + will certainly arrive late in the sink +as well. A (negative) diff + value so that timestamp + + diff + would yield a +result smaller than 0 is not allowed.

+

The application can use general event probes to intercept the QoS +event and implement custom application specific QoS handling.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

type

the QoS type

 

proportion

the proportion of the qos message

 

diff

The time difference of the last Clock sync

 

timestamp

The timestamp of the buffer

 
+
+
+

Returns

+

a new QOS event.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_parse_qos ()

+
void
+gst_event_parse_qos (GstEvent *event,
+                     GstQOSType *type,
+                     gdouble *proportion,
+                     GstClockTimeDiff *diff,
+                     GstClockTime *timestamp);
+

Get the type, proportion, diff and timestamp in the qos event. See +gst_event_new_qos() for more information about the different QoS values.

+

timestamp + will be adjusted for any pad offsets of pads it was passing through.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

event

The event to query

 

type

A pointer to store the QoS type in.

[out]

proportion

A pointer to store the proportion in.

[out]

diff

A pointer to store the diff in.

[out]

timestamp

A pointer to store the timestamp in.

[out]
+
+
+
+
+

gst_event_new_seek ()

+
GstEvent *
+gst_event_new_seek (gdouble rate,
+                    GstFormat format,
+                    GstSeekFlags flags,
+                    GstSeekType start_type,
+                    gint64 start,
+                    GstSeekType stop_type,
+                    gint64 stop);
+

Allocate a new seek event with the given parameters.

+

The seek event configures playback of the pipeline between start + to stop + +at the speed given in rate +, also called a playback segment. +The start + and stop + values are expressed in format +.

+

A rate + of 1.0 means normal playback rate, 2.0 means double speed. +Negatives values means backwards playback. A value of 0.0 for the +rate is not allowed and should be accomplished instead by PAUSING the +pipeline.

+

A pipeline has a default playback segment configured with a start +position of 0, a stop position of -1 and a rate of 1.0. The currently +configured playback segment can be queried with GST_QUERY_SEGMENT.

+

start_type + and stop_type + specify how to adjust the currently configured +start and stop fields in playback segment. Adjustments can be made relative +or absolute to the last configured values. A type of GST_SEEK_TYPE_NONE +means that the position should not be updated.

+

When the rate is positive and start + has been updated, playback will start +from the newly configured start position.

+

For negative rates, playback will start from the newly configured stop +position (if any). If the stop position is updated, it must be different from +-1 (GST_CLOCK_TIME_NONE) for negative rates.

+

It is not possible to seek relative to the current playback position, to do +this, PAUSE the pipeline, query the current playback position with +GST_QUERY_POSITION and update the playback segment current position with a +GST_SEEK_TYPE_SET to the desired position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

rate

The new playback rate

 

format

The format of the seek values

 

flags

The optional seek flags

 

start_type

The type and flags for the new start position

 

start

The value of the new start position

 

stop_type

The type and flags for the new stop position

 

stop

The value of the new stop position

 
+
+
+

Returns

+

a new seek event.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_parse_seek ()

+
void
+gst_event_parse_seek (GstEvent *event,
+                      gdouble *rate,
+                      GstFormat *format,
+                      GstSeekFlags *flags,
+                      GstSeekType *start_type,
+                      gint64 *start,
+                      GstSeekType *stop_type,
+                      gint64 *stop);
+

Parses a seek event + and stores the results in the given result locations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

event

a seek event

 

rate

result location for the rate.

[out]

format

result location for the stream format.

[out]

flags

result location for the GstSeekFlags.

[out]

start_type

result location for the GstSeekType of the start position.

[out]

start

result location for the start position expressed in format +.

[out]

stop_type

result location for the GstSeekType of the stop position.

[out]

stop

result location for the stop position expressed in format +.

[out]
+
+
+
+
+

gst_event_new_navigation ()

+
GstEvent *
+gst_event_new_navigation (GstStructure *structure);
+

Create a new navigation event from the given description.

+
+

Parameters

+
+++++ + + + + + +

structure

description of the event. The event will take +ownership of the structure.

[transfer full]
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_new_latency ()

+
GstEvent *
+gst_event_new_latency (GstClockTime latency);
+

Create a new latency event. The event is sent upstream from the sinks and +notifies elements that they should add an additional latency + to the +running time before synchronising against the clock.

+

The latency is mostly used in live sinks and is always expressed in +the time format.

+
+

Parameters

+
+++++ + + + + + +

latency

the new latency value

 
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_latency ()

+
void
+gst_event_parse_latency (GstEvent *event,
+                         GstClockTime *latency);
+

Get the latency in the latency event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to query

 

latency

A pointer to store the latency in.

[out]
+
+
+
+
+

gst_event_new_step ()

+
GstEvent *
+gst_event_new_step (GstFormat format,
+                    guint64 amount,
+                    gdouble rate,
+                    gboolean flush,
+                    gboolean intermediate);
+

Create a new step event. The purpose of the step event is to instruct a sink +to skip amount + (expressed in format +) of media. It can be used to implement +stepping through the video frame by frame or for doing fast trick modes.

+

A rate of <= 0.0 is not allowed. Pause the pipeline, for the effect of rate += 0.0 or first reverse the direction of playback using a seek event to get +the same effect as rate < 0.0.

+

The flush + flag will clear any pending data in the pipeline before starting +the step operation.

+

The intermediate + flag instructs the pipeline that this step operation is +part of a larger step operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

format

the format of amount +

 

amount

the amount of data to step

 

rate

the step rate

 

flush

flushing steps

 

intermediate

intermediate steps

 
+
+
+

Returns

+

a new GstEvent.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_parse_step ()

+
void
+gst_event_parse_step (GstEvent *event,
+                      GstFormat *format,
+                      guint64 *amount,
+                      gdouble *rate,
+                      gboolean *flush,
+                      gboolean *intermediate);
+

Parse the step event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

event

The event to query

 

format

a pointer to store the format in.

[out][allow-none]

amount

a pointer to store the amount in.

[out][allow-none]

rate

a pointer to store the rate in.

[out][allow-none]

flush

a pointer to store the flush boolean in.

[out][allow-none]

intermediate

a pointer to store the intermediate +boolean in.

[out][allow-none]
+
+
+
+
+

gst_event_new_sink_message ()

+
GstEvent *
+gst_event_new_sink_message (const gchar *name,
+                            GstMessage *msg);
+

Create a new sink-message event. The purpose of the sink-message event is +to instruct a sink to post the message contained in the event synchronized +with the stream.

+

name + is used to store multiple sticky events on one pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

a name for the event

 

msg

the GstMessage to be posted.

[transfer none]
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_sink_message ()

+
void
+gst_event_parse_sink_message (GstEvent *event,
+                              GstMessage **msg);
+

Parse the sink-message event. Unref msg + after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to query

 

msg

a pointer to store the GstMessage in.

[out][transfer full]
+
+
+
+
+

gst_event_new_reconfigure ()

+
GstEvent *
+gst_event_new_reconfigure (void);
+

Create a new reconfigure event. The purpose of the reconfigure event is +to travel upstream and make elements renegotiate their caps or reconfigure +their buffer pools. This is useful when changing properties on elements +or changing the topology of the pipeline.

+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_new_caps ()

+
GstEvent *
+gst_event_new_caps (GstCaps *caps);
+

Create a new CAPS event for caps +. The caps event can only travel downstream +synchronized with the buffer flow and contains the format of the buffers +that will follow after the event.

+
+

Parameters

+
+++++ + + + + + +

caps

a GstCaps.

[transfer none]
+
+
+

Returns

+

the new CAPS event.

+

[transfer full][nullable]

+
+
+
+
+

gst_event_parse_caps ()

+
void
+gst_event_parse_caps (GstEvent *event,
+                      GstCaps **caps);
+

Get the caps from event +. The caps remains valid as long as event + remains +valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to parse

 

caps

A pointer to the caps.

[out][transfer none]
+
+
+
+
+

gst_event_new_toc ()

+
GstEvent *
+gst_event_new_toc (GstToc *toc,
+                   gboolean updated);
+

Generate a TOC event from the given toc +. The purpose of the TOC event is to +inform elements that some kind of the TOC was found.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

toc

GstToc structure.

[transfer none]

updated

whether toc +was updated or not.

 
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_toc ()

+
void
+gst_event_parse_toc (GstEvent *event,
+                     GstToc **toc,
+                     gboolean *updated);
+

Parse a TOC event + and store the results in the given toc + and updated + locations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

event

a TOC event.

 

toc

pointer to GstToc structure.

[out][transfer full]

updated

pointer to store TOC updated flag.

[out]
+
+
+
+
+

gst_event_new_toc_select ()

+
GstEvent *
+gst_event_new_toc_select (const gchar *uid);
+

Generate a TOC select event with the given uid +. The purpose of the +TOC select event is to start playback based on the TOC's entry with the +given uid +.

+
+

Parameters

+
+++++ + + + + + +

uid

UID in the TOC to start playback from.

 
+
+
+

Returns

+

a new GstEvent.

+
+
+
+
+

gst_event_parse_toc_select ()

+
void
+gst_event_parse_toc_select (GstEvent *event,
+                            gchar **uid);
+

Parse a TOC select event + and store the results in the given uid + location.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a TOC select event.

 

uid

storage for the selection UID.

[out][transfer full][allow-none]
+
+
+
+
+

gst_event_new_segment_done ()

+
GstEvent *
+gst_event_new_segment_done (GstFormat format,
+                            gint64 position);
+

Create a new segment-done event. This event is sent by elements that +finish playback of a segment as a result of a segment seek.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

The format of the position being done

 

position

The position of the segment being done

 
+
+
+

Returns

+

a new GstEvent.

+

[transfer full]

+
+
+
+
+

gst_event_parse_segment_done ()

+
void
+gst_event_parse_segment_done (GstEvent *event,
+                              GstFormat *format,
+                              gint64 *position);
+

Extracts the position and format from the segment done message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

event

A valid GstEvent of type GST_EVENT_SEGMENT_DONE.

 

format

Result location for the format, or NULL.

[out][allow-none]

position

Result location for the position, or NULL.

[out][allow-none]
+
+
+
+
+

gst_event_new_protection ()

+
GstEvent *
+gst_event_new_protection (const gchar *system_id,
+                          GstBuffer *data,
+                          const gchar *origin);
+

Creates a new event containing information specific to a particular +protection system (uniquely identified by system_id +), by which that +protection system can acquire key(s) to decrypt a protected stream.

+

In order for a decryption element to decrypt media +protected using a specific system, it first needs all the +protection system specific information necessary to acquire the decryption +key(s) for that stream. The functions defined here enable this information +to be passed in events from elements that extract it +(e.g., ISOBMFF demuxers, MPEG DASH demuxers) to protection decrypter +elements that use it.

+

Events containing protection system specific information are created using +gst_event_new_protection, and they can be parsed by downstream elements +using gst_event_parse_protection.

+

In Common Encryption, protection system specific information may be located +within ISOBMFF files, both in movie (moov) boxes and movie fragment (moof) +boxes; it may also be contained in ContentProtection elements within MPEG +DASH MPDs. The events created by gst_event_new_protection contain data +identifying from which of these locations the encapsulated protection system +specific information originated. This origin information is required as +some protection systems use different encodings depending upon where the +information originates.

+

The events returned by gst_event_new_protection() are implemented +in such a way as to ensure that the most recently-pushed protection info +event of a particular origin + and system_id + will +be stuck to the output pad of the sending element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

system_id

a string holding a UUID that uniquely +identifies a protection system.

[transfer none]

data

a GstBuffer holding protection system specific +information. The reference count of the buffer will be incremented by one.

[transfer none]

origin

a string indicating where the protection +information carried in the event was extracted from. The allowed values +of this string will depend upon the protection scheme.

 
+
+
+

Returns

+

a GST_EVENT_PROTECTION event, if successful; NULL +if unsuccessful.

+
+

Since: 1.6

+
+
+
+

gst_event_parse_protection ()

+
void
+gst_event_parse_protection (GstEvent *event,
+                            const gchar **system_id,
+                            GstBuffer **data,
+                            const gchar **origin);
+

Parses an event containing protection system specific information and stores +the results in system_id +, data + and origin +. The data stored in system_id +, +origin + and data + are valid until event + is released.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

event

a GST_EVENT_PROTECTION event.

 

system_id

pointer to store the UUID +string uniquely identifying a content protection system.

[out][allow-none][transfer none]

data

pointer to store a GstBuffer +holding protection system specific information.

[out][allow-none][transfer none]

origin

pointer to store a value that +indicates where the protection information carried by event +was extracted +from.

[out][allow-none][transfer none]
+
+

Since: 1.6

+
+
+
+

gst_event_new_select_streams ()

+
GstEvent *
+gst_event_new_select_streams (GList *streams);
+

Allocate a new select-streams event.

+

The select-streams event requests the specified streams + to be activated.

+

The list of streams + corresponds to the "Stream ID" of each stream to be +activated. Those ID can be obtained via the GstStream objects present +in GST_EVENT_STREAM_START, GST_EVENT_STREAM_COLLECTION or +GST_MESSAGE_STREAM_COLLECTION.

+

Note: The list of streams + can not be empty.

+
+

Parameters

+
+++++ + + + + + +

streams

the list of streams to +activate.

[element-type utf8][transfer none]
+
+
+

Returns

+

a new select-streams event or NULL in case of +an error (like an empty streams list).

+

[transfer full]

+
+

Since: 1.10

+
+
+
+

gst_event_parse_select_streams ()

+
void
+gst_event_parse_select_streams (GstEvent *event,
+                                GList **streams);
+

Parse the SELECT_STREAMS event and retrieve the contained streams.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

The event to parse

 

streams

the streams.

[out][element-type utf8][transfer full]
+
+

Since: 1.10

+
+
+
+

gst_event_new_stream_collection ()

+
GstEvent *
+gst_event_new_stream_collection (GstStreamCollection *collection);
+

Create a new STREAM_COLLECTION event. The stream collection event can only +travel downstream synchronized with the buffer flow.

+

Source elements, demuxers and other elements that manage collections +of streams and post GstStreamCollection messages on the bus also send +this event downstream on each pad involved in the collection, so that +activation of a new collection can be tracked through the downstream +data flow.

+
+

Parameters

+
+++++ + + + + + +

collection

Active collection for this data flow

 
+
+
+

Returns

+

the new STREAM_COLLECTION event.

+

[transfer full]

+
+

Since: 1.10

+
+
+
+

gst_event_parse_stream_collection ()

+
void
+gst_event_parse_stream_collection (GstEvent *event,
+                                   GstStreamCollection **collection);
+

Retrieve new GstStreamCollection from STREAM_COLLECTION event event +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-collection event

 

collection

pointer to store the collection.

[out]
+
+

Since: 1.10

+
+
+
+

gst_event_new_stream_group_done ()

+
GstEvent *
+gst_event_new_stream_group_done (guint group_id);
+

Create a new Stream Group Done event. The stream-group-done event can +only travel downstream synchronized with the buffer flow. Elements +that receive the event on a pad should handle it mostly like EOS, +and emit any data or pending buffers that would depend on more data +arriving and unblock, since there won't be any more data.

+

This event is followed by EOS at some point in the future, and is +generally used when switching pads - to unblock downstream so that +new pads can be exposed before sending EOS on the existing pads.

+
+

Parameters

+
+++++ + + + + + +

group_id

the group id of the stream group which is ending

 
+
+
+

Returns

+

the new stream-group-done event.

+

[transfer full]

+
+

Since: 1.10

+
+
+
+

gst_event_parse_stream_group_done ()

+
void
+gst_event_parse_stream_group_done (GstEvent *event,
+                                   guint *group_id);
+

Parse a stream-group-done event + and store the result in the given +group_id + location.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

event

a stream-group-done event.

 

group_id

address of variable to store the group id into.

[out]
+
+

Since: 1.10

+
+
+
+

Types and Values

+
+

struct GstEvent

+
struct GstEvent {
+  GstMiniObject mini_object;
+
+  GstEventType  type;
+  guint64       timestamp;
+  guint32       seqnum;
+};
+
+

A GstEvent.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject mini_object;

the parent structure

 

GstEventType type;

the GstEventType of the event

 

guint64 timestamp;

the timestamp of the event

 

guint32 seqnum;

the sequence number of the event

 
+
+
+
+
+

enum GstEventTypeFlags

+

GstEventTypeFlags indicate the aspects of the different GstEventType +values. You can get the type flags of a GstEventType with the +gst_event_type_get_flags() function.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_EVENT_TYPE_UPSTREAM

+

Set if the event can travel upstream.

+
 

GST_EVENT_TYPE_DOWNSTREAM

+

Set if the event can travel downstream.

+
 

GST_EVENT_TYPE_SERIALIZED

+

Set if the event should be serialized with data + flow.

+
 

GST_EVENT_TYPE_STICKY

+

Set if the event is sticky on the pads.

+
 

GST_EVENT_TYPE_STICKY_MULTI

+

Multiple sticky events can be on a pad, each + identified by the event name.

+
 
+
+
+
+
+

GST_EVENT_TYPE_BOTH

+
#define             GST_EVENT_TYPE_BOTH
+

The same thing as GST_EVENT_TYPE_UPSTREAM | GST_EVENT_TYPE_DOWNSTREAM.

+
+
+
+

enum GstEventType

+

GstEventType lists the standard event types that can be sent in a pipeline.

+

The custom event types can be used for private messages between elements +that can't be expressed using normal +GStreamer buffer passing semantics. Custom events carry an arbitrary +GstStructure. +Specific custom events are distinguished by the name of the structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_EVENT_UNKNOWN

+

unknown event.

+
 

GST_EVENT_FLUSH_START

+

Start a flush operation. This event clears all data + from the pipeline and unblock all streaming threads.

+
 

GST_EVENT_FLUSH_STOP

+

Stop a flush operation. This event resets the + running-time of the pipeline.

+
 

GST_EVENT_STREAM_START

+

Event to mark the start of a new stream. Sent before any + other serialized event and only sent at the start of a new stream, + not after flushing seeks.

+
 

GST_EVENT_CAPS

+

GstCaps event. Notify the pad of a new media type.

+
 

GST_EVENT_SEGMENT

+

A new media segment follows in the dataflow. The + segment events contains information for clipping buffers and + converting buffer timestamps to running-time and + stream-time.

+
 

GST_EVENT_STREAM_COLLECTION

+

A new GstStreamCollection is available (Since 1.10)

+
 

GST_EVENT_TAG

+

A new set of metadata tags has been found in the stream.

+
 

GST_EVENT_BUFFERSIZE

+

Notification of buffering requirements. Currently not + used yet.

+
 

GST_EVENT_SINK_MESSAGE

+

An event that sinks turn into a message. Used to + send messages that should be emitted in sync with + rendering.

+
 

GST_EVENT_STREAM_GROUP_DONE

+

Indicates that there is no more data for + the stream group ID in the message. Sent before EOS + in some instances and should be handled mostly the same. (Since 1.10)

+
 

GST_EVENT_EOS

+

End-Of-Stream. No more data is to be expected to follow + without either a STREAM_START event, or a FLUSH_STOP and a SEGMENT + event.

+
 

GST_EVENT_TOC

+

An event which indicates that a new table of contents (TOC) + was found or updated.

+
 

GST_EVENT_PROTECTION

+

An event which indicates that new or updated + encryption information has been found in the stream.

+
 

GST_EVENT_SEGMENT_DONE

+

Marks the end of a segment playback.

+
 

GST_EVENT_GAP

+

Marks a gap in the datastream.

+
 

GST_EVENT_QOS

+

A quality message. Used to indicate to upstream elements + that the downstream elements should adjust their processing + rate.

+
 

GST_EVENT_SEEK

+

A request for a new playback position and rate.

+
 

GST_EVENT_NAVIGATION

+

Navigation events are usually used for communicating + user requests, such as mouse or keyboard movements, + to upstream elements.

+
 

GST_EVENT_LATENCY

+

Notification of new latency adjustment. Sinks will use + the latency information to adjust their synchronisation.

+
 

GST_EVENT_STEP

+

A request for stepping through the media. Sinks will usually + execute the step operation.

+
 

GST_EVENT_RECONFIGURE

+

A request for upstream renegotiating caps and reconfiguring.

+
 

GST_EVENT_TOC_SELECT

+

A request for a new playback position based on TOC + entry's UID.

+
 

GST_EVENT_SELECT_STREAMS

+

A request to select one or more streams (Since 1.10)

+
 

GST_EVENT_CUSTOM_UPSTREAM

+

Upstream custom event

+
 

GST_EVENT_CUSTOM_DOWNSTREAM

+

Downstream custom event that travels in the + data flow.

+
 

GST_EVENT_CUSTOM_DOWNSTREAM_OOB

+

Custom out-of-band downstream event.

+
 

GST_EVENT_CUSTOM_DOWNSTREAM_STICKY

+

Custom sticky downstream event.

+
 

GST_EVENT_CUSTOM_BOTH

+

Custom upstream or downstream event. + In-band when travelling downstream.

+
 

GST_EVENT_CUSTOM_BOTH_OOB

+

Custom upstream or downstream out-of-band event.

+
 
+
+
+
+
+

enum GstStreamFlags

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_STREAM_FLAG_NONE

+

This stream has no special attributes

+
 

GST_STREAM_FLAG_SPARSE

+

This stream is a sparse stream (e.g. a subtitle + stream), data may flow only in irregular intervals with large gaps in + between.

+
 

GST_STREAM_FLAG_SELECT

+

This stream should be selected by default. This + flag may be used by demuxers to signal that a stream should be selected + by default in a playback scenario.

+
 

GST_STREAM_FLAG_UNSELECT

+

This stream should not be selected by default. + This flag may be used by demuxers to signal that a stream should not + be selected by default in a playback scenario, but only if explicitly + selected by the user (e.g. an audio track for the hard of hearing or + a director's commentary track).

+
 
+
+

Since: 1.2

+
+
+
+

enum GstQOSType

+

The different types of QoS events that can be given to the +gst_event_new_qos() method.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_QOS_TYPE_OVERFLOW

+

The QoS event type that is produced when upstream + elements are producing data too quickly and the element can't keep up + processing the data. Upstream should reduce their production rate. This + type is also used when buffers arrive early or in time.

+
 

GST_QOS_TYPE_UNDERFLOW

+

The QoS event type that is produced when upstream + elements are producing data too slowly and need to speed up their + production rate.

+
 

GST_QOS_TYPE_THROTTLE

+

The QoS event type that is produced when the + application enabled throttling to limit the data rate.

+
 
+
+
+
+
+

enum GstSeekType

+

The different types of seek events. When constructing a seek event with +gst_event_new_seek() or when doing gst_segment_do_seek().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_SEEK_TYPE_NONE

+

no change in position is required

+
 

GST_SEEK_TYPE_SET

+

absolute position is requested

+
 

GST_SEEK_TYPE_END

+

relative position to duration is requested

+
 
+
+
+
+
+

enum GstSeekFlags

+

Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags +can be used together.

+

A non flushing seek might take some time to perform as the currently +playing data in the pipeline will not be cleared.

+

An accurate seek might be slower for formats that don't have any indexes +or timestamp markers in the stream. Specifying this flag might require a +complete scan of the file in those cases.

+

When performing a segment seek: after the playback of the segment completes, +no EOS will be emitted by the element that performed the seek, but a +GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. +When this message is posted, it is possible to send a new seek event to +continue playback. With this seek method it is possible to perform seamless +looping or simple linear editing.

+

When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode +playback, the GST_SEEK_FLAG_TRICKMODE flag can be used to instruct decoders +and demuxers to adjust the playback rate by skipping frames. This can improve +performance and decrease CPU usage because not all frames need to be decoded.

+

Beyond that, the GST_SEEK_FLAG_TRICKMODE_KEY_UNITS flag can be used to +request that decoders skip all frames except key units, and +GST_SEEK_FLAG_TRICKMODE_NO_AUDIO flags can be used to request that audio +decoders do no decoding at all, and simple output silence.

+

The GST_SEEK_FLAG_SNAP_BEFORE flag can be used to snap to the previous +relevant location, and the GST_SEEK_FLAG_SNAP_AFTER flag can be used to +select the next relevant location. If GST_SEEK_FLAG_KEY_UNIT is specified, +the relevant location is a keyframe. If both flags are specified, the nearest +of these locations will be selected. If none are specified, the implementation is +free to select whichever it wants.

+

The before and after here are in running time, so when playing backwards, +the next location refers to the one that will played in next, and not the +one that is located after in the actual source stream.

+

Also see part-seeking.txt in the GStreamer design documentation for more +details on the meaning of these flags and the behaviour expected of +elements that handle them.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_SEEK_FLAG_NONE

+

no flag

+
 

GST_SEEK_FLAG_FLUSH

+

flush pipeline

+
 

GST_SEEK_FLAG_ACCURATE

+

accurate position is requested, this might + be considerably slower for some formats.

+
 

GST_SEEK_FLAG_KEY_UNIT

+

seek to the nearest keyframe. This might be + faster but less accurate.

+
 

GST_SEEK_FLAG_SEGMENT

+

perform a segment seek.

+
 

GST_SEEK_FLAG_TRICKMODE

+

when doing fast forward or fast reverse playback, allow + elements to skip frames instead of generating all + frames. (Since 1.6)

+
 

GST_SEEK_FLAG_SKIP

+

Deprecated backward compatibility flag, replaced + by GST_SEEK_FLAG_TRICKMODE

+
 

GST_SEEK_FLAG_SNAP_BEFORE

+

go to a location before the requested position, + if GST_SEEK_FLAG_KEY_UNIT this means the keyframe at or before + the requested position the one at or before the seek target.

+
 

GST_SEEK_FLAG_SNAP_AFTER

+

go to a location after the requested position, + if GST_SEEK_FLAG_KEY_UNIT this means the keyframe at of after the + requested position.

+
 

GST_SEEK_FLAG_SNAP_NEAREST

+

go to a position near the requested position, + if GST_SEEK_FLAG_KEY_UNIT this means the keyframe closest + to the requested position, if both keyframes are at an equal + distance, behaves like GST_SEEK_FLAG_SNAP_BEFORE.

+
 

GST_SEEK_FLAG_TRICKMODE_KEY_UNITS

+

when doing fast forward or fast reverse + playback, request that elements only decode keyframes + and skip all other content, for formats that have + keyframes. (Since 1.6)

+
 

GST_SEEK_FLAG_TRICKMODE_NO_AUDIO

+

when doing fast forward or fast reverse + playback, request that audio decoder elements skip + decoding and output only gap events or silence. (Since 1.6)

+
 
+
+
+
+
+

See Also

+

GstPad, GstElement

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstGhostPad.html b/docs/gst/html/GstGhostPad.html new file mode 100644 index 0000000..f43dca3 --- /dev/null +++ b/docs/gst/html/GstGhostPad.html @@ -0,0 +1,797 @@ + + + + +GstGhostPad: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstGhostPad

+

GstGhostPad — Pseudo link pads

+
+ +
+

Types and Values

+
++++ + + + + + + + + + + +
structGstProxyPad
structGstGhostPad
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPad
+                ╰── GstProxyPad
+                    ╰── GstGhostPad
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GhostPads are useful when organizing pipelines with GstBin like elements. +The idea here is to create hierarchical element graphs. The bin element +contains a sub-graph. Now one would like to treat the bin-element like any +other GstElement. This is where GhostPads come into play. A GhostPad acts as +a proxy for another pad. Thus the bin can have sink and source ghost-pads +that are associated with sink and source pads of the child elements.

+

If the target pad is known at creation time, gst_ghost_pad_new() is the +function to use to get a ghost-pad. Otherwise one can use gst_ghost_pad_new_no_target() +to create the ghost-pad and use gst_ghost_pad_set_target() to establish the +association later on.

+

Note that GhostPads add overhead to the data processing of a pipeline.

+
+
+

Functions

+
+

gst_ghost_pad_new ()

+
GstPad *
+gst_ghost_pad_new (const gchar *name,
+                   GstPad *target);
+

Create a new ghostpad with target + as the target. The direction will be taken +from the target pad. target + must be unlinked.

+

Will ref the target.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

the name of the new pad, or NULL to assign a default name.

[allow-none]

target

the pad to ghost.

[transfer none]
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_ghost_pad_new_no_target ()

+
GstPad *
+gst_ghost_pad_new_no_target (const gchar *name,
+                             GstPadDirection dir);
+

Create a new ghostpad without a target with the given direction. +A target can be set on the ghostpad later with the +gst_ghost_pad_set_target() function.

+

The created ghostpad will not have a padtemplate.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

the name of the new pad, or NULL to assign a default name.

[allow-none]

dir

the direction of the ghostpad

 
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_ghost_pad_new_from_template ()

+
GstPad *
+gst_ghost_pad_new_from_template (const gchar *name,
+                                 GstPad *target,
+                                 GstPadTemplate *templ);
+

Create a new ghostpad with target + as the target. The direction will be taken +from the target pad. The template used on the ghostpad will be template +.

+

Will ref the target.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name

the name of the new pad, or NULL to assign a default name.

[allow-none]

target

the pad to ghost.

[transfer none]

templ

the GstPadTemplate to use on the ghostpad.

[transfer none]
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_ghost_pad_new_no_target_from_template ()

+
GstPad *
+gst_ghost_pad_new_no_target_from_template
+                               (const gchar *name,
+                                GstPadTemplate *templ);
+

Create a new ghostpad based on templ +, without setting a target. The +direction will be taken from the templ +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

the name of the new pad, or NULL to assign a default name.

[allow-none]

templ

the GstPadTemplate to create the ghostpad from.

[transfer none]
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_ghost_pad_set_target ()

+
gboolean
+gst_ghost_pad_set_target (GstGhostPad *gpad,
+                          GstPad *newtarget);
+

Set the new target of the ghostpad gpad +. Any existing target +is unlinked and links to the new target are established. if newtarget + is +NULL the target will be cleared.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

gpad

the GstGhostPad

 

newtarget

the new pad target.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if the new target could be set. This function +can return FALSE when the internal pads could not be linked.

+
+
+
+
+

gst_ghost_pad_get_target ()

+
GstPad *
+gst_ghost_pad_get_target (GstGhostPad *gpad);
+

Get the target pad of gpad +. Unref target pad after usage.

+
+

Parameters

+
+++++ + + + + + +

gpad

the GstGhostPad

 
+
+
+

Returns

+

the target GstPad, can be +NULL if the ghostpad has no target set. Unref target pad after +usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_ghost_pad_construct ()

+
gboolean
+gst_ghost_pad_construct (GstGhostPad *gpad);
+

Finish initialization of a newly allocated ghost pad.

+

This function is most useful in language bindings and when subclassing +GstGhostPad; plugin and application developers normally will not call this +function. Call this function directly after a call to g_object_new +(GST_TYPE_GHOST_PAD, "direction", dir +, ..., NULL).

+
+

Parameters

+
+++++ + + + + + +

gpad

the newly allocated ghost pad

 
+
+
+

Returns

+

TRUE if the construction succeeds, FALSE otherwise.

+
+
+
+
+

gst_ghost_pad_activate_mode_default ()

+
gboolean
+gst_ghost_pad_activate_mode_default (GstPad *pad,
+                                     GstObject *parent,
+                                     GstPadMode mode,
+                                     gboolean active);
+

Invoke the default activate mode function of a ghost pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

the GstPad to activate or deactivate.

 

parent

the parent of pad +or NULL.

[allow-none]

mode

the requested activation mode

 

active

whether the pad should be active or not.

 
+
+
+

Returns

+

TRUE if the operation was successful.

+
+
+
+
+

gst_ghost_pad_internal_activate_mode_default ()

+
gboolean
+gst_ghost_pad_internal_activate_mode_default
+                               (GstPad *pad,
+                                GstObject *parent,
+                                GstPadMode mode,
+                                gboolean active);
+

Invoke the default activate mode function of a proxy pad that is +owned by a ghost pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

the GstPad to activate or deactivate.

 

parent

the parent of pad +or NULL.

[allow-none]

mode

the requested activation mode

 

active

whether the pad should be active or not.

 
+
+
+

Returns

+

TRUE if the operation was successful.

+
+
+
+
+

gst_proxy_pad_get_internal ()

+
GstProxyPad *
+gst_proxy_pad_get_internal (GstProxyPad *pad);
+

Get the internal pad of pad +. Unref target pad after usage.

+

The internal pad of a GstGhostPad is the internally used +pad of opposite direction, which is used to link to the target.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstProxyPad

 
+
+
+

Returns

+

the target GstProxyPad, can +be NULL. Unref target pad after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_proxy_pad_iterate_internal_links_default ()

+
GstIterator *
+gst_proxy_pad_iterate_internal_links_default
+                               (GstPad *pad,
+                                GstObject *parent);
+

Invoke the default iterate internal links function of the proxy pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad to get the internal links of.

 

parent

the parent of pad +or NULL.

[allow-none]
+
+
+

Returns

+

a GstIterator of GstPad, or NULL if pad +has no parent. Unref each returned pad with gst_object_unref().

+

[nullable]

+
+
+
+
+

gst_proxy_pad_chain_default ()

+
GstFlowReturn
+gst_proxy_pad_chain_default (GstPad *pad,
+                             GstObject *parent,
+                             GstBuffer *buffer);
+

Invoke the default chain function of the proxy pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a sink GstPad, returns GST_FLOW_ERROR if not.

 

parent

the parent of pad +or NULL.

[allow-none]

buffer

the GstBuffer to send, return GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+
+
+
+
+

gst_proxy_pad_chain_list_default ()

+
GstFlowReturn
+gst_proxy_pad_chain_list_default (GstPad *pad,
+                                  GstObject *parent,
+                                  GstBufferList *list);
+

Invoke the default chain list function of the proxy pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a sink GstPad, returns GST_FLOW_ERROR if not.

 

parent

the parent of pad +or NULL.

[allow-none]

list

the GstBufferList to send, return GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+
+
+
+
+

gst_proxy_pad_getrange_default ()

+
GstFlowReturn
+gst_proxy_pad_getrange_default (GstPad *pad,
+                                GstObject *parent,
+                                guint64 offset,
+                                guint size,
+                                GstBuffer **buffer);
+

Invoke the default getrange function of the proxy pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pad

a src GstPad, returns GST_FLOW_ERROR if not.

 

parent

the parent of pad +

 

offset

The start offset of the buffer

 

size

The length of the buffer

 

buffer

a pointer to hold the GstBuffer, +returns GST_FLOW_ERROR if NULL.

[out callee-allocates]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+
+
+
+
+

Types and Values

+
+

struct GstProxyPad

+
struct GstProxyPad;
+
+
+
+

struct GstGhostPad

+
struct GstGhostPad;
+

Opaque GstGhostPad structure.

+
+
+
+

See Also

+

GstPad

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstMemory.html b/docs/gst/html/GstMemory.html new file mode 100644 index 0000000..22ef557 --- /dev/null +++ b/docs/gst/html/GstMemory.html @@ -0,0 +1,1671 @@ + + + + +GstMemory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstMemory

+

GstMemory — refcounted wrapper for memory blocks

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_MEMORY_FLAGS() +
#define +GST_MEMORY_FLAG_IS_SET() +
#define +GST_MEMORY_FLAG_UNSET() +
#define +GST_MEMORY_IS_READONLY() +
#define +GST_MEMORY_IS_NO_SHARE() +
#define +GST_MEMORY_IS_ZERO_PADDED() +
#define +GST_MEMORY_IS_ZERO_PREFIXED() +
#define +GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS() +
#define +GST_MEMORY_IS_NOT_MAPPABLE() +
+gpointer + +(*GstMemoryMapFunction) () +
+gpointer + +(*GstMemoryMapFullFunction) () +
+void + +(*GstMemoryUnmapFunction) () +
+void + +(*GstMemoryUnmapFullFunction) () +
+GstMemory * + +(*GstMemoryCopyFunction) () +
+GstMemory * + +(*GstMemoryShareFunction) () +
+gboolean + +(*GstMemoryIsSpanFunction) () +
+void + +gst_memory_init () +
+gboolean + +gst_memory_is_type () +
+GstMemory * + +gst_memory_ref () +
+void + +gst_memory_unref () +
+gsize + +gst_memory_get_sizes () +
+void + +gst_memory_resize () +
#define +gst_memory_lock() +
#define +gst_memory_unlock() +
#define +gst_memory_is_writable() +
#define +gst_memory_make_writable() +
+GstMemory * + +gst_memory_make_mapped () +
+gboolean + +gst_memory_map () +
+void + +gst_memory_unmap () +
+GstMemory * + +gst_memory_copy () +
+GstMemory * + +gst_memory_share () +
+gboolean + +gst_memory_is_span () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
enumGstMemoryFlags
structGstMemory
enumGstMapFlags
#defineGST_MAP_READWRITE
 GstMapInfo
#defineGST_MAP_INFO_INIT
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstMemory
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstMemory is a lightweight refcounted object that wraps a region of memory. +They are typically used to manage the data of a GstBuffer.

+

A GstMemory object has an allocated region of memory of maxsize. The maximum +size does not change during the lifetime of the memory object. The memory +also has an offset and size property that specifies the valid range of memory +in the allocated region.

+

Memory is usually created by allocators with a gst_allocator_alloc() +method call. When NULL is used as the allocator, the default allocator will +be used.

+

New allocators can be registered with gst_allocator_register(). +Allocators are identified by name and can be retrieved with +gst_allocator_find(). gst_allocator_set_default() can be used to change the +default allocator.

+

New memory can be created with gst_memory_new_wrapped() that wraps the memory +allocated elsewhere.

+

Refcounting of the memory block is performed with gst_memory_ref() and +gst_memory_unref().

+

The size of the memory can be retrieved and changed with +gst_memory_get_sizes() and gst_memory_resize() respectively.

+

Getting access to the data of the memory is performed with gst_memory_map(). +The call will return a pointer to offset bytes into the region of memory. +After the memory access is completed, gst_memory_unmap() should be called.

+

Memory can be copied with gst_memory_copy(), which will return a writable +copy. gst_memory_share() will create a new memory block that shares the +memory with an existing memory block at a custom offset and with a custom +size.

+

Memory can be efficiently merged when gst_memory_is_span() returns TRUE.

+
+
+

Functions

+
+

GST_MEMORY_FLAGS()

+
#define GST_MEMORY_FLAGS(mem)  GST_MINI_OBJECT_FLAGS (mem)
+
+

A flags word containing GstMemoryFlags flags set on mem +

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+
+
+
+

GST_MEMORY_FLAG_IS_SET()

+
#define GST_MEMORY_FLAG_IS_SET(mem,flag)   GST_MINI_OBJECT_FLAG_IS_SET (mem,flag)
+
+

Gives the status of a specific flag on a mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a GstMemory.

 

flag

the GstMemoryFlags to check.

 
+
+
+
+
+

GST_MEMORY_FLAG_UNSET()

+
#define GST_MEMORY_FLAG_UNSET(mem,flag)   GST_MINI_OBJECT_FLAG_UNSET (mem, flag)
+
+

Clear a specific flag on a mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a GstMemory.

 

flag

the GstMemoryFlags to clear.

 
+
+
+
+
+

GST_MEMORY_IS_READONLY()

+
#define GST_MEMORY_IS_READONLY(mem)        GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_READONLY)
+
+

Check if mem + is readonly.

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+
+
+
+

GST_MEMORY_IS_NO_SHARE()

+
#define GST_MEMORY_IS_NO_SHARE(mem)        GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_NO_SHARE)
+
+

Check if mem + cannot be shared between buffers

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+
+
+
+

GST_MEMORY_IS_ZERO_PADDED()

+
#define GST_MEMORY_IS_ZERO_PADDED(mem)     GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PADDED)
+
+

Check if the padding in mem + is 0 filled.

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+
+
+
+

GST_MEMORY_IS_ZERO_PREFIXED()

+
#define GST_MEMORY_IS_ZERO_PREFIXED(mem)   GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PREFIXED)
+
+

Check if the prefix in mem + is 0 filled.

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+
+
+
+

GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS()

+
#define GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS(mem)     GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS)
+
+

Check if mem + is physically contiguous.

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+

Since: 1.2

+
+
+
+

GST_MEMORY_IS_NOT_MAPPABLE()

+
#define GST_MEMORY_IS_NOT_MAPPABLE(mem)     GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_NOT_MAPPABLE)
+
+

Check if mem + can't be mapped via gst_memory_map() without any preconditions

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory.

 
+
+

Since: 1.2

+
+
+
+

GstMemoryMapFunction ()

+
gpointer
+(*GstMemoryMapFunction) (GstMemory *mem,
+                         gsize maxsize,
+                         GstMapFlags flags);
+

Get the memory of mem + that can be accessed according to the mode specified +in flags +. The function should return a pointer that contains at least +maxsize + bytes.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

maxsize

size to map

 

flags

access mode for the memory

 
+
+
+

Returns

+

a pointer to memory of which at least maxsize +bytes can be +accessed according to the access pattern in flags +.

+
+
+
+
+

GstMemoryMapFullFunction ()

+
gpointer
+(*GstMemoryMapFullFunction) (GstMemory *mem,
+                             GstMapInfo *info,
+                             gsize maxsize);
+

Get the memory of mem + that can be accessed according to the mode specified +in info +'s flags. The function should return a pointer that contains at least +maxsize + bytes.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

info

the GstMapInfo to map with

 

maxsize

size to map

 
+
+
+

Returns

+

a pointer to memory of which at least maxsize +bytes can be +accessed according to the access pattern in info +'s flags.

+
+
+
+
+

GstMemoryUnmapFunction ()

+
void
+(*GstMemoryUnmapFunction) (GstMemory *mem);
+

Return the pointer previously retrieved with gst_memory_map().

+
+

Parameters

+
+++++ + + + + + +

mem

a GstMemory

 
+
+
+
+
+

GstMemoryUnmapFullFunction ()

+
void
+(*GstMemoryUnmapFullFunction) (GstMemory *mem,
+                               GstMapInfo *info);
+

Return the pointer previously retrieved with gst_memory_map() with info +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a GstMemory

 

info

a GstMapInfo

 
+
+
+
+
+

GstMemoryCopyFunction ()

+
GstMemory *
+(*GstMemoryCopyFunction) (GstMemory *mem,
+                          gssize offset,
+                          gssize size);
+

Copy size + bytes from mem + starting at offset + and return them wrapped in a +new GstMemory object. +If size + is set to -1, all bytes starting at offset + are copied.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

an offset

 

size

a size or -1

 
+
+
+

Returns

+

a new GstMemory object wrapping a copy of the requested region in +mem +.

+
+
+
+
+

GstMemoryShareFunction ()

+
GstMemory *
+(*GstMemoryShareFunction) (GstMemory *mem,
+                           gssize offset,
+                           gssize size);
+

Share size + bytes from mem + starting at offset + and return them wrapped in a +new GstMemory object. If size + is set to -1, all bytes starting at offset + are +shared. This function does not make a copy of the bytes in mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

an offset

 

size

a size or -1

 
+
+
+

Returns

+

a new GstMemory object sharing the requested region in mem +.

+
+
+
+
+

GstMemoryIsSpanFunction ()

+
gboolean
+(*GstMemoryIsSpanFunction) (GstMemory *mem1,
+                            GstMemory *mem2,
+                            gsize *offset);
+

Check if mem1 + and mem2 + occupy contiguous memory and return the offset of +mem1 + in the parent buffer in offset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem1

a GstMemory

 

mem2

a GstMemory

 

offset

a result offset

 
+
+
+

Returns

+

TRUE if mem1 +and mem2 +are in contiguous memory.

+
+
+
+
+

gst_memory_init ()

+
void
+gst_memory_init (GstMemory *mem,
+                 GstMemoryFlags flags,
+                 GstAllocator *allocator,
+                 GstMemory *parent,
+                 gsize maxsize,
+                 gsize align,
+                 gsize offset,
+                 gsize size);
+

Initializes a newly allocated mem + with the given parameters. This function +will call gst_mini_object_init() with the default memory parameters.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

flags

GstMemoryFlags

 

allocator

the GstAllocator

 

parent

the parent of mem +

 

maxsize

the total size of the memory

 

align

the alignment of the memory

 

offset

The offset in the memory

 

size

the size of valid data in the memory

 
+
+
+
+
+

gst_memory_is_type ()

+
gboolean
+gst_memory_is_type (GstMemory *mem,
+                    const gchar *mem_type);
+

Check if mem + if allocated with an allocator for mem_type +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a GstMemory

 

mem_type

a memory type

 
+
+
+

Returns

+

TRUE if mem +was allocated from an allocator for mem_type +.

+
+

Since: 1.2

+
+
+
+

gst_memory_ref ()

+
GstMemory *
+gst_memory_ref (GstMemory *memory);
+

Increase the refcount of this memory.

+
+

Parameters

+
+++++ + + + + + +

memory

The memory to refcount

 
+
+
+

Returns

+

memory +(for convenience when doing assignments).

+

[transfer full]

+
+
+
+
+

gst_memory_unref ()

+
void
+gst_memory_unref (GstMemory *memory);
+

Decrease the refcount of an memory, freeing it if the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

memory

the memory to refcount.

[transfer full]
+
+
+
+
+

gst_memory_get_sizes ()

+
gsize
+gst_memory_get_sizes (GstMemory *mem,
+                      gsize *offset,
+                      gsize *maxsize);
+

Get the current size +, offset + and maxsize + of mem +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

pointer to offset.

[out][allow-none]

maxsize

pointer to maxsize.

[out][allow-none]
+
+
+

Returns

+

the current sizes of mem +

+
+
+
+
+

gst_memory_resize ()

+
void
+gst_memory_resize (GstMemory *mem,
+                   gssize offset,
+                   gsize size);
+

Resize the memory region. mem + should be writable and offset + size should be +less than the maxsize of mem +.

+

GST_MEMORY_FLAG_ZERO_PREFIXED and GST_MEMORY_FLAG_ZERO_PADDED will be +cleared when offset or padding is increased respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

a new offset

 

size

a new size

 
+
+
+
+
+

gst_memory_lock()

+
#define        gst_memory_lock(m,f)        gst_mini_object_lock (GST_MINI_OBJECT_CAST (m), (f))
+
+
+
+
+

gst_memory_unlock()

+
#define        gst_memory_unlock(m,f)      gst_mini_object_unlock (GST_MINI_OBJECT_CAST (m), (f))
+
+
+
+
+

gst_memory_is_writable()

+
#define        gst_memory_is_writable(m)   gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (m))
+
+
+
+
+

gst_memory_make_writable()

+
#define        gst_memory_make_writable(m) GST_MEMORY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (m)))
+
+
+
+
+

gst_memory_make_mapped ()

+
GstMemory *
+gst_memory_make_mapped (GstMemory *mem,
+                        GstMapInfo *info,
+                        GstMapFlags flags);
+

Create a GstMemory object that is mapped with flags +. If mem + is mappable +with flags +, this function returns the mapped mem + directly. Otherwise a +mapped copy of mem + is returned.

+

This function takes ownership of old mem + and returns a reference to a new +GstMemory.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory.

[transfer full]

info

pointer for info.

[out]

flags

mapping flags

 
+
+
+

Returns

+

a GstMemory object mapped +with flags +or NULL when a mapping is not possible.

+

[transfer full][nullable]

+
+
+
+
+

gst_memory_map ()

+
gboolean
+gst_memory_map (GstMemory *mem,
+                GstMapInfo *info,
+                GstMapFlags flags);
+

Fill info + with the pointer and sizes of the memory in mem + that can be +accessed according to flags +.

+

This function can return FALSE for various reasons:

+
    +
  • the memory backed by mem + is not accessible with the given flags +.

  • +
  • the memory was already mapped with a different mapping.

  • +
+

info + and its contents remain valid for as long as mem + is valid and +until gst_memory_unmap() is called.

+

For each gst_memory_map() call, a corresponding gst_memory_unmap() call +should be done.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

info

pointer for info.

[out]

flags

mapping flags

 
+
+
+

Returns

+

TRUE if the map operation was successful.

+
+
+
+
+

gst_memory_unmap ()

+
void
+gst_memory_unmap (GstMemory *mem,
+                  GstMapInfo *info);
+

Release the memory obtained with gst_memory_map()

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a GstMemory

 

info

a GstMapInfo

 
+
+
+
+
+

gst_memory_copy ()

+
GstMemory *
+gst_memory_copy (GstMemory *mem,
+                 gssize offset,
+                 gssize size);
+

Return a copy of size + bytes from mem + starting from offset +. This copy is +guaranteed to be writable. size + can be set to -1 to return a copy +from offset + to the end of the memory region.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

offset to copy from

 

size

size to copy, or -1 to copy to the end of the memory region

 
+
+
+

Returns

+

a new GstMemory.

+
+
+
+
+

gst_memory_share ()

+
GstMemory *
+gst_memory_share (GstMemory *mem,
+                  gssize offset,
+                  gssize size);
+

Return a shared copy of size + bytes from mem + starting from offset +. No +memory copy is performed and the memory region is simply shared. The result +is guaranteed to be non-writable. size + can be set to -1 to return a shared +copy from offset + to the end of the memory region.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem

a GstMemory

 

offset

offset to share from

 

size

size to share, or -1 to share to the end of the memory region

 
+
+
+

Returns

+

a new GstMemory.

+
+
+
+
+

gst_memory_is_span ()

+
gboolean
+gst_memory_is_span (GstMemory *mem1,
+                    GstMemory *mem2,
+                    gsize *offset);
+

Check if mem1 + and mem2 share the memory with a common parent memory object +and that the memory is contiguous.

+

If this is the case, the memory of mem1 + and mem2 + can be merged +efficiently by performing gst_memory_share() on the parent object from +the returned offset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

mem1

a GstMemory

 

mem2

a GstMemory

 

offset

a pointer to a result offset.

[out]
+
+
+

Returns

+

TRUE if the memory is contiguous and of a common parent.

+
+
+
+
+

Types and Values

+
+

enum GstMemoryFlags

+

Flags for wrapped memory.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_MEMORY_FLAG_READONLY

+

memory is readonly. It is not allowed to map the +memory with GST_MAP_WRITE.

+
 

GST_MEMORY_FLAG_NO_SHARE

+

memory must not be shared. Copies will have to be +made when this memory needs to be shared between buffers.

+
 

GST_MEMORY_FLAG_ZERO_PREFIXED

+

the memory prefix is filled with 0 bytes

+
 

GST_MEMORY_FLAG_ZERO_PADDED

+

the memory padding is filled with 0 bytes

+
 

GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS

+

the memory is physically contiguous. (Since 1.2)

+
 

GST_MEMORY_FLAG_NOT_MAPPABLE

+

the memory can't be mapped via gst_memory_map() without any preconditions. (Since 1.2)

+
 

GST_MEMORY_FLAG_LAST

+

first flag that can be used for custom purposes

+
 
+
+
+
+
+

struct GstMemory

+
struct GstMemory {
+  GstMiniObject   mini_object;
+
+  GstAllocator   *allocator;
+
+  GstMemory      *parent;
+  gsize           maxsize;
+  gsize           align;
+  gsize           offset;
+  gsize           size;
+};
+
+

Base structure for memory implementations. Custom memory will put this structure +as the first member of their structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject mini_object;

parent structure

 

GstAllocator *allocator;

pointer to the GstAllocator

 

GstMemory *parent;

parent memory block

 

gsize maxsize;

the maximum size allocated

 

gsize align;

the alignment of the memory

 

gsize offset;

the offset where valid data starts

 

gsize size;

the size of valid data

 
+
+
+
+
+

enum GstMapFlags

+

Flags used when mapping memory

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_MAP_READ

+

map for read access

+
 

GST_MAP_WRITE

+

map for write access

+
 

GST_MAP_FLAG_LAST

+

first flag that can be used for custom purposes

+
 
+
+
+
+
+

GST_MAP_READWRITE

+
#define GST_MAP_READWRITE      ((GstMapFlags) (GST_MAP_READ | GST_MAP_WRITE))
+
+

GstMapFlags value alias for GST_MAP_READ | GST_MAP_WRITE

+
+
+
+

GstMapInfo

+
typedef struct {
+  GstMemory *memory;
+  GstMapFlags flags;
+  guint8 *data;
+  gsize size;
+  gsize maxsize;
+} GstMapInfo;
+
+

A structure containing the result of a map operation such as +gst_memory_map(). It contains the data and size.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMemory *memory;

a pointer to the mapped memory

 

GstMapFlags flags;

flags used when mapping the memory

 

guint8 *data;

a pointer to the mapped data.

[array length=size]

gsize size;

the valid size in data +

 

gsize maxsize;

the maximum bytes in data +

 
+
+
+
+
+

GST_MAP_INFO_INIT

+
#define GST_MAP_INFO_INIT { NULL, (GstMapFlags) 0, NULL, 0, 0, { NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL}}
+
+

Initializer for GstMapInfo

+
+
+
+

See Also

+

GstBuffer

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstMessage.html b/docs/gst/html/GstMessage.html new file mode 100644 index 0000000..ba2d8d4 --- /dev/null +++ b/docs/gst/html/GstMessage.html @@ -0,0 +1,5889 @@ + + + + +GstMessage: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstMessage

+

GstMessage — Lightweight objects to signal the application of + pipeline events

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_MESSAGE_SRC() +
#define +GST_MESSAGE_SRC_NAME() +
#define +GST_MESSAGE_TIMESTAMP() +
#define +GST_MESSAGE_SEQNUM() +
#define +GST_MESSAGE_TYPE() +
#define +GST_MESSAGE_TYPE_IS_EXTENDED() +
#define +GST_MESSAGE_TYPE_NAME() +
+GQuark + +gst_message_type_to_quark () +
const gchar * + +gst_message_type_get_name () +
+GstMessage * + +gst_message_ref () +
+void + +gst_message_unref () +
+GstMessage * + +gst_message_copy () +
const GstStructure * + +gst_message_get_structure () +
+GstStructure * + +gst_message_writable_structure () +
#define +gst_message_make_writable() +
+guint32 + +gst_message_get_seqnum () +
+void + +gst_message_set_seqnum () +
+gboolean + +gst_message_has_name () +
#define +gst_message_is_writable() +
+gboolean + +gst_message_replace () +
+GstMessage * + +gst_message_new_eos () +
+GstMessage * + +gst_message_new_error () +
+GstMessage * + +gst_message_new_error_with_details () +
+void + +gst_message_parse_error () +
+void + +gst_message_parse_error_details () +
+GstMessage * + +gst_message_new_warning () +
+GstMessage * + +gst_message_new_warning_with_details () +
+void + +gst_message_parse_warning () +
+void + +gst_message_parse_warning_details () +
+GstMessage * + +gst_message_new_info () +
+GstMessage * + +gst_message_new_info_with_details () +
+void + +gst_message_parse_info () +
+void + +gst_message_parse_info_details () +
+GstMessage * + +gst_message_new_tag () +
+void + +gst_message_parse_tag () +
+GstMessage * + +gst_message_new_buffering () +
+void + +gst_message_parse_buffering () +
+void + +gst_message_set_buffering_stats () +
+void + +gst_message_parse_buffering_stats () +
+GstMessage * + +gst_message_new_state_changed () +
+void + +gst_message_parse_state_changed () +
+GstMessage * + +gst_message_new_state_dirty () +
+GstMessage * + +gst_message_new_step_done () +
+void + +gst_message_parse_step_done () +
+GstMessage * + +gst_message_new_clock_provide () +
+void + +gst_message_parse_clock_provide () +
+GstMessage * + +gst_message_new_clock_lost () +
+void + +gst_message_parse_clock_lost () +
+GstMessage * + +gst_message_new_new_clock () +
+void + +gst_message_parse_new_clock () +
+GstMessage * + +gst_message_new_application () +
+GstMessage * + +gst_message_new_element () +
+GstMessage * + +gst_message_new_custom () +
+GstMessage * + +gst_message_new_segment_start () +
+void + +gst_message_parse_segment_start () +
+GstMessage * + +gst_message_new_segment_done () +
+void + +gst_message_parse_segment_done () +
+GstMessage * + +gst_message_new_duration_changed () +
+GstMessage * + +gst_message_new_latency () +
+GstMessage * + +gst_message_new_async_start () +
+GstMessage * + +gst_message_new_async_done () +
+void + +gst_message_parse_async_done () +
+GstMessage * + +gst_message_new_step_start () +
+void + +gst_message_parse_step_start () +
+GstMessage * + +gst_message_new_qos () +
+void + +gst_message_set_qos_values () +
+void + +gst_message_set_qos_stats () +
+void + +gst_message_parse_qos () +
+void + +gst_message_parse_qos_values () +
+void + +gst_message_parse_qos_stats () +
+GstMessage * + +gst_message_new_toc () +
+void + +gst_message_parse_toc () +
+GstMessage * + +gst_message_new_reset_time () +
+void + +gst_message_parse_reset_time () +
+GstMessage * + +gst_message_new_stream_start () +
+void + +gst_message_set_group_id () +
+gboolean + +gst_message_parse_group_id () +
+GstMessage * + +gst_message_new_stream_collection () +
+void + +gst_message_parse_stream_collection () +
+GstMessage * + +gst_message_new_structure_change () +
+void + +gst_message_parse_structure_change () +
+GstMessage * + +gst_message_new_request_state () +
+void + +gst_message_parse_request_state () +
+GstMessage * + +gst_message_new_stream_status () +
+void + +gst_message_parse_stream_status () +
+void + +gst_message_set_stream_status_object () +
const GValue * + +gst_message_get_stream_status_object () +
+GstMessage * + +gst_message_new_progress () +
+void + +gst_message_parse_progress () +
+GstMessage * + +gst_message_new_need_context () +
+gboolean + +gst_message_parse_context_type () +
+GstMessage * + +gst_message_new_have_context () +
+void + +gst_message_parse_have_context () +
+GstMessage * + +gst_message_new_device_added () +
+GstMessage * + +gst_message_new_device_removed () +
+void + +gst_message_parse_device_added () +
+void + +gst_message_parse_device_removed () +
+GstMessage * + +gst_message_new_property_notify () +
+void + +gst_message_parse_property_notify () +
+GstMessage * + +gst_message_new_streams_selected () +
+void + +gst_message_parse_streams_selected () +
+void + +gst_message_streams_selected_add () +
+guint + +gst_message_streams_selected_get_size () +
+GstStream * + +gst_message_streams_selected_get_stream () +
+GstMessage * + +gst_message_new_redirect () +
+void + +gst_message_add_redirect_entry () +
+void + +gst_message_parse_redirect_entry () +
+gsize + +gst_message_get_num_redirect_entries () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
structGstMessage
enumGstMessageType
enumGstStructureChangeType
enumGstStreamStatusType
enumGstProgressType
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstMessage
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Messages are implemented as a subclass of GstMiniObject with a generic +GstStructure as the content. This allows for writing custom messages without +requiring an API change while allowing a wide range of different types +of messages.

+

Messages are posted by objects in the pipeline and are passed to the +application using the GstBus.

+

The basic use pattern of posting a message on a GstBus is as follows:

+
+ + + + + + + +
1
gst_bus_post (bus, gst_message_new_eos());
+
+ +

+

A GstElement usually posts messages on the bus provided by the parent +container using gst_element_post_message().

+
+
+

Functions

+
+

GST_MESSAGE_SRC()

+
#define GST_MESSAGE_SRC(message)        (GST_MESSAGE_CAST(message)->src)
+
+

Get the object that posted message +.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

GST_MESSAGE_SRC_NAME()

+
#define             GST_MESSAGE_SRC_NAME(message)
+

Get the name of the object that posted message +. Returns "(NULL)" if +the message has no source object set.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

GST_MESSAGE_TIMESTAMP()

+
#define GST_MESSAGE_TIMESTAMP(message)  (GST_MESSAGE_CAST(message)->timestamp)
+
+

Get the timestamp of message +. This is the timestamp when the message +was created.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

GST_MESSAGE_SEQNUM()

+
#define GST_MESSAGE_SEQNUM(message)     (GST_MESSAGE_CAST(message)->seqnum)
+
+

Get the sequence number of message +.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

GST_MESSAGE_TYPE()

+
#define GST_MESSAGE_TYPE(message)       (GST_MESSAGE_CAST(message)->type)
+
+

Get the GstMessageType of message +.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

GST_MESSAGE_TYPE_IS_EXTENDED()

+
#define GST_MESSAGE_TYPE_IS_EXTENDED(message)       (!!(GST_MESSAGE_CAST(message)->type & GST_MESSAGE_EXTENDED))
+
+

Check if the message is in the extended message group

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+

Since: 1.4

+
+
+
+

GST_MESSAGE_TYPE_NAME()

+
#define GST_MESSAGE_TYPE_NAME(message)  gst_message_type_get_name(GST_MESSAGE_TYPE(message))
+
+

Get a constant string representation of the GstMessageType of message +.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage

 
+
+
+
+
+

gst_message_type_to_quark ()

+
GQuark
+gst_message_type_to_quark (GstMessageType type);
+

Get the unique quark for the given message type.

+
+

Parameters

+
+++++ + + + + + +

type

the message type

 
+
+
+

Returns

+

the quark associated with the message type

+
+
+
+
+

gst_message_type_get_name ()

+
const gchar *
+gst_message_type_get_name (GstMessageType type);
+

Get a printable name for the given message type. Do not modify or free.

+
+

Parameters

+
+++++ + + + + + +

type

the message type

 
+
+
+

Returns

+

a reference to the static name of the message.

+
+
+
+
+

gst_message_ref ()

+
GstMessage *
+gst_message_ref (GstMessage *msg);
+

Convenience macro to increase the reference count of the message.

+
+

Parameters

+
+++++ + + + + + +

msg

the message to ref

 
+
+
+

Returns

+

msg +(for convenience when doing assignments)

+
+
+
+
+

gst_message_unref ()

+
void
+gst_message_unref (GstMessage *msg);
+

Convenience macro to decrease the reference count of the message, possibly +freeing it.

+
+

Parameters

+
+++++ + + + + + +

msg

the message to unref

 
+
+
+
+
+

gst_message_copy ()

+
GstMessage *
+gst_message_copy (const GstMessage *msg);
+

Creates a copy of the message. Returns a copy of the message.

+
+

Parameters

+
+++++ + + + + + +

msg

the message to copy

 
+
+
+

Returns

+

a new copy of msg +.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_get_structure ()

+
const GstStructure *
+gst_message_get_structure (GstMessage *message);
+

Access the structure of the message.

+
+

Parameters

+
+++++ + + + + + +

message

The GstMessage.

 
+
+
+

Returns

+

The structure of the message. The +structure is still owned by the message, which means that you should not +free it and that the pointer becomes invalid when you free the message.

+

MT safe.

+

[transfer none][nullable]

+
+
+
+
+

gst_message_writable_structure ()

+
GstStructure *
+gst_message_writable_structure (GstMessage *message);
+

Get a writable version of the structure.

+
+

Parameters

+
+++++ + + + + + +

message

The GstMessage.

 
+
+
+

Returns

+

The structure of the message. The structure +is still owned by the message, which means that you should not free +it and that the pointer becomes invalid when you free the message. +This function checks if message +is writable and will never return +NULL.

+

MT safe.

+

[transfer none]

+
+

Since: 1.14

+
+
+
+

gst_message_make_writable()

+
#define         gst_message_make_writable(msg)  GST_MESSAGE_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (msg)))
+
+

Checks if a message is writable. If not, a writable copy is made and +returned.

+
+

Parameters

+
+++++ + + + + + +

msg

the message to make writable.

[transfer full]
+
+
+

Returns

+

a message (possibly a duplicate) that is writable.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_get_seqnum ()

+
guint32
+gst_message_get_seqnum (GstMessage *message);
+

Retrieve the sequence number of a message.

+

Messages have ever-incrementing sequence numbers, which may also be set +explicitly via gst_message_set_seqnum(). Sequence numbers are typically used +to indicate that a message corresponds to some other set of messages or +events, for example a SEGMENT_DONE message corresponding to a SEEK event. It +is considered good practice to make this correspondence when possible, though +it is not required.

+

Note that events and messages share the same sequence number incrementor; +two events or messages will never have the same sequence number unless +that correspondence was made explicitly.

+
+

Parameters

+
+++++ + + + + + +

message

A GstMessage.

 
+
+
+

Returns

+

The message's sequence number.

+

MT safe.

+
+
+
+
+

gst_message_set_seqnum ()

+
void
+gst_message_set_seqnum (GstMessage *message,
+                        guint32 seqnum);
+

Set the sequence number of a message.

+

This function might be called by the creator of a message to indicate that +the message relates to other messages or events. See gst_message_get_seqnum() +for more information.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A GstMessage.

 

seqnum

A sequence number.

 
+
+
+
+
+

gst_message_has_name ()

+
gboolean
+gst_message_has_name (GstMessage *message,
+                      const gchar *name);
+

Checks if message + has the given name +. This function is usually used to +check the name of a custom message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

The GstMessage.

 

name

name to check

 
+
+
+

Returns

+

TRUE if name +matches the name of the message structure.

+
+
+
+
+

gst_message_is_writable()

+
#define         gst_message_is_writable(msg)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (msg))
+
+

Tests if you can safely write into a message's structure or validly +modify the seqnum and timestamp fields.

+
+

Parameters

+
+++++ + + + + + +

msg

a GstMessage

 
+
+
+
+
+

gst_message_replace ()

+
gboolean
+gst_message_replace (GstMessage **old_message,
+                     GstMessage *new_message);
+

Modifies a pointer to a GstMessage to point to a different GstMessage. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +message is unreffed, the new one is reffed).

+

Either new_message + or the GstMessage pointed to by old_message + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_message

pointer to a +pointer to a GstMessage to be replaced.

[inout][transfer full][nullable]

new_message

pointer to a GstMessage that will +replace the message pointed to by old_message +.

[allow-none][transfer none]
+
+
+

Returns

+

TRUE if new_message +was different from old_message +

+
+
+
+
+

gst_message_new_eos ()

+
GstMessage *
+gst_message_new_eos (GstObject *src);
+

Create a new eos message. This message is generated and posted in +the sink elements of a GstBin. The bin will only forward the EOS +message to the application if all sinks have posted an EOS message.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

The new eos message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_error ()

+
GstMessage *
+gst_message_new_error (GstObject *src,
+                       GError *error,
+                       const gchar *debug);
+

Create a new error message. The message will copy error + and +debug +. This message is posted by element when a fatal event +occurred. The pipeline will probably (partially) stop. The application +receiving this message should stop the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 
+
+
+

Returns

+

the new error message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_error_with_details ()

+
GstMessage *
+gst_message_new_error_with_details (GstObject *src,
+                                    GError *error,
+                                    const gchar *debug,
+                                    GstStructure *details);
+

Create a new error message. The message will copy error + and +debug +. This message is posted by element when a fatal event +occurred. The pipeline will probably (partially) stop. The application +receiving this message should stop the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 

details

(allow-none): A GstStructure with details.

[transfer full]
+
+
+

Returns

+

the new error message.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_message_parse_error ()

+
void
+gst_message_parse_error (GstMessage *message,
+                         GError **gerror,
+                         gchar **debug);
+

Extracts the GError and debug string from the GstMessage. The values returned +in the output arguments are copies; the caller must free them when done.

+

Typical usage of this function might be:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
...
+switch (GST_MESSAGE_TYPE (msg)) {
+  case GST_MESSAGE_ERROR: {
+    GError *err = NULL;
+    gchar *dbg_info = NULL;
+
+    gst_message_parse_error (msg, &err, &dbg_info);
+    g_printerr ("ERROR from element %s: %s\n",
+        GST_OBJECT_NAME (msg->src), err->message);
+    g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
+    g_error_free (err);
+    g_free (dbg_info);
+    break;
+  }
+  ...
+}
+...
+
+ +

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_ERROR.

 

gerror

location for the GError.

[out][allow-none][transfer full]

debug

location for the debug message, +or NULL.

[out][allow-none][transfer full]
+
+
+
+
+

gst_message_parse_error_details ()

+
void
+gst_message_parse_error_details (GstMessage *message,
+                                 const GstStructure **structure);
+

Returns the optional details structure, may be NULL if none. +The returned structure must not be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

The message object

 

structure

A pointer to the returned details.

[transfer none][out]
+
+

Since: 1.10

+
+
+
+

gst_message_new_warning ()

+
GstMessage *
+gst_message_new_warning (GstObject *src,
+                         GError *error,
+                         const gchar *debug);
+

Create a new warning message. The message will make copies of error + and +debug +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 
+
+
+

Returns

+

the new warning message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_warning_with_details ()

+
GstMessage *
+gst_message_new_warning_with_details (GstObject *src,
+                                      GError *error,
+                                      const gchar *debug,
+                                      GstStructure *details);
+

Create a new warning message. The message will make copies of error + and +debug +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 

details

(allow-none): A GstStructure with details.

[transfer full]
+
+
+

Returns

+

the new warning message.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_message_parse_warning ()

+
void
+gst_message_parse_warning (GstMessage *message,
+                           GError **gerror,
+                           gchar **debug);
+

Extracts the GError and debug string from the GstMessage. The values returned +in the output arguments are copies; the caller must free them when done.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_WARNING.

 

gerror

location for the GError.

[out][allow-none][transfer full]

debug

location for the debug message, +or NULL.

[out][allow-none][transfer full]
+
+
+
+
+

gst_message_parse_warning_details ()

+
void
+gst_message_parse_warning_details (GstMessage *message,
+                                   const GstStructure **structure);
+

Returns the optional details structure, may be NULL if none +The returned structure must not be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

The message object

 

structure

A pointer to the returned details structure.

[transfer none][out]
+
+

Since: 1.10

+
+
+
+

gst_message_new_info ()

+
GstMessage *
+gst_message_new_info (GstObject *src,
+                      GError *error,
+                      const gchar *debug);
+

Create a new info message. The message will make copies of error + and +debug +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 
+
+
+

Returns

+

the new info message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_info_with_details ()

+
GstMessage *
+gst_message_new_info_with_details (GstObject *src,
+                                   GError *error,
+                                   const gchar *debug,
+                                   GstStructure *details);
+

Create a new info message. The message will make copies of error + and +debug +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

error

The GError for this message.

[transfer none]

debug

A debugging string.

 

details

(allow-none): A GstStructure with details.

[transfer full]
+
+
+

Returns

+

the new warning message.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_message_parse_info ()

+
void
+gst_message_parse_info (GstMessage *message,
+                        GError **gerror,
+                        gchar **debug);
+

Extracts the GError and debug string from the GstMessage. The values returned +in the output arguments are copies; the caller must free them when done.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_INFO.

 

gerror

location for the GError.

[out][allow-none][transfer full]

debug

location for the debug message, +or NULL.

[out][allow-none][transfer full]
+
+
+
+
+

gst_message_parse_info_details ()

+
void
+gst_message_parse_info_details (GstMessage *message,
+                                const GstStructure **structure);
+

Returns the optional details structure, may be NULL if none +The returned structure must not be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

The message object

 

structure

A pointer to the returned details structure.

[transfer none][out]
+
+

Since: 1.10

+
+
+
+

gst_message_new_tag ()

+
GstMessage *
+gst_message_new_tag (GstObject *src,
+                     GstTagList *tag_list);
+

Create a new tag message. The message will take ownership of the tag list. +The message is posted by elements that discovered a new taglist.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

tag_list

the tag list for the message.

[transfer full]
+
+
+

Returns

+

the new tag message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_tag ()

+
void
+gst_message_parse_tag (GstMessage *message,
+                       GstTagList **tag_list);
+

Extracts the tag list from the GstMessage. The tag list returned in the +output argument is a copy; the caller must free it when done.

+

Typical usage of this function might be:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
...
+switch (GST_MESSAGE_TYPE (msg)) {
+  case GST_MESSAGE_TAG: {
+    GstTagList *tags = NULL;
+
+    gst_message_parse_tag (msg, &tags);
+    g_print ("Got tags from element %s\n", GST_OBJECT_NAME (msg->src));
+    handle_tags (tags);
+    gst_tag_list_unref (tags);
+    break;
+  }
+  ...
+}
+...
+
+ +

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_TAG.

 

tag_list

return location for the tag-list.

[out callee-allocates]
+
+
+
+
+

gst_message_new_buffering ()

+
GstMessage *
+gst_message_new_buffering (GstObject *src,
+                           gint percent);
+

Create a new buffering message. This message can be posted by an element that +needs to buffer data before it can continue processing. percent + should be a +value between 0 and 100. A value of 100 means that the buffering completed.

+

When percent + is < 100 the application should PAUSE a PLAYING pipeline. When +percent + is 100, the application can set the pipeline (back) to PLAYING. +The application must be prepared to receive BUFFERING messages in the +PREROLLING state and may only set the pipeline to PLAYING after receiving a +message with percent + set to 100, which can happen after the pipeline +completed prerolling.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

percent

The buffering percent

 
+
+
+

Returns

+

The new buffering message.

+

[transfer full][nullable]

+
+
+
+
+

gst_message_parse_buffering ()

+
void
+gst_message_parse_buffering (GstMessage *message,
+                             gint *percent);
+

Extracts the buffering percent from the GstMessage. see also +gst_message_new_buffering().

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_BUFFERING.

 

percent

Return location for the percent.

[out][allow-none]
+
+
+
+
+

gst_message_set_buffering_stats ()

+
void
+gst_message_set_buffering_stats (GstMessage *message,
+                                 GstBufferingMode mode,
+                                 gint avg_in,
+                                 gint avg_out,
+                                 gint64 buffering_left);
+

Configures the buffering stats values in message +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_BUFFERING.

 

mode

a buffering mode

 

avg_in

the average input rate

 

avg_out

the average output rate

 

buffering_left

amount of buffering time left in milliseconds

 
+
+
+
+
+

gst_message_parse_buffering_stats ()

+
void
+gst_message_parse_buffering_stats (GstMessage *message,
+                                   GstBufferingMode *mode,
+                                   gint *avg_in,
+                                   gint *avg_out,
+                                   gint64 *buffering_left);
+

Extracts the buffering stats values from message +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_BUFFERING.

 

mode

a buffering mode, or NULL.

[out][allow-none]

avg_in

the average input rate, or NULL.

[out][allow-none]

avg_out

the average output rate, or NULL.

[out][allow-none]

buffering_left

amount of buffering time left in +milliseconds, or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_state_changed ()

+
GstMessage *
+gst_message_new_state_changed (GstObject *src,
+                               GstState oldstate,
+                               GstState newstate,
+                               GstState pending);
+

Create a state change message. This message is posted whenever an element +changed its state.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

oldstate

the previous state

 

newstate

the new (current) state

 

pending

the pending (target) state

 
+
+
+

Returns

+

the new state change message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_state_changed ()

+
void
+gst_message_parse_state_changed (GstMessage *message,
+                                 GstState *oldstate,
+                                 GstState *newstate,
+                                 GstState *pending);
+

Extracts the old and new states from the GstMessage.

+

Typical usage of this function might be:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
...
+switch (GST_MESSAGE_TYPE (msg)) {
+  case GST_MESSAGE_STATE_CHANGED: {
+    GstState old_state, new_state;
+
+    gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
+    g_print ("Element %s changed state from %s to %s.\n",
+        GST_OBJECT_NAME (msg->src),
+        gst_element_state_get_name (old_state),
+        gst_element_state_get_name (new_state));
+    break;
+  }
+  ...
+}
+...
+
+ +

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

a valid GstMessage of type GST_MESSAGE_STATE_CHANGED

 

oldstate

the previous state, or NULL.

[out][allow-none]

newstate

the new (current) state, or NULL.

[out][allow-none]

pending

the pending (target) state, or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_state_dirty ()

+
GstMessage *
+gst_message_new_state_dirty (GstObject *src);
+

Create a state dirty message. This message is posted whenever an element +changed its state asynchronously and is used internally to update the +states of container objects.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

the new state dirty message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_step_done ()

+
GstMessage *
+gst_message_new_step_done (GstObject *src,
+                           GstFormat format,
+                           guint64 amount,
+                           gdouble rate,
+                           gboolean flush,
+                           gboolean intermediate,
+                           guint64 duration,
+                           gboolean eos);
+

This message is posted by elements when they complete a part, when intermediate + set +to TRUE, or a complete step operation.

+

duration + will contain the amount of time (in GST_FORMAT_TIME) of the stepped +amount + of media in format format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

 

format

the format of amount +

 

amount

the amount of stepped data

 

rate

the rate of the stepped amount

 

flush

is this an flushing step

 

intermediate

is this an intermediate step

 

duration

the duration of the data

 

eos

the step caused EOS

 
+
+
+

Returns

+

the new step_done message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_step_done ()

+
void
+gst_message_parse_step_done (GstMessage *message,
+                             GstFormat *format,
+                             guint64 *amount,
+                             gdouble *rate,
+                             gboolean *flush,
+                             gboolean *intermediate,
+                             guint64 *duration,
+                             gboolean *eos);
+

Extract the values the step_done message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STEP_DONE.

 

format

result location for the format.

[out][allow-none]

amount

result location for the amount.

[out][allow-none]

rate

result location for the rate.

[out][allow-none]

flush

result location for the flush flag.

[out][allow-none]

intermediate

result location for the intermediate flag.

[out][allow-none]

duration

result location for the duration.

[out][allow-none]

eos

result location for the EOS flag.

[out][allow-none]
+
+
+
+
+

gst_message_new_clock_provide ()

+
GstMessage *
+gst_message_new_clock_provide (GstObject *src,
+                               GstClock *clock,
+                               gboolean ready);
+

Create a clock provide message. This message is posted whenever an +element is ready to provide a clock or lost its ability to provide +a clock (maybe because it paused or became EOS).

+

This message is mainly used internally to manage the clock +selection.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

clock

the clock it provides.

[transfer none]

ready

TRUE if the sender can provide a clock

 
+
+
+

Returns

+

the new provide clock message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_clock_provide ()

+
void
+gst_message_parse_clock_provide (GstMessage *message,
+                                 GstClock **clock,
+                                 gboolean *ready);
+

Extracts the clock and ready flag from the GstMessage. +The clock object returned remains valid until the message is freed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_CLOCK_PROVIDE.

 

clock

a pointer to hold a clock +object, or NULL.

[out][allow-none][transfer none]

ready

a pointer to hold the ready flag, or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_clock_lost ()

+
GstMessage *
+gst_message_new_clock_lost (GstObject *src,
+                            GstClock *clock);
+

Create a clock lost message. This message is posted whenever the +clock is not valid anymore.

+

If this message is posted by the pipeline, the pipeline will +select a new clock again when it goes to PLAYING. It might therefore +be needed to set the pipeline to PAUSED and PLAYING again.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

clock

the clock that was lost.

[transfer none]
+
+
+

Returns

+

The new clock lost message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_clock_lost ()

+
void
+gst_message_parse_clock_lost (GstMessage *message,
+                              GstClock **clock);
+

Extracts the lost clock from the GstMessage. +The clock object returned remains valid until the message is freed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_CLOCK_LOST.

 

clock

a pointer to hold the lost clock.

[out][allow-none][transfer none]
+
+
+
+
+

gst_message_new_new_clock ()

+
GstMessage *
+gst_message_new_new_clock (GstObject *src,
+                           GstClock *clock);
+

Create a new clock message. This message is posted whenever the +pipeline selects a new clock for the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

clock

the new selected clock.

[transfer none]
+
+
+

Returns

+

The new new clock message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_new_clock ()

+
void
+gst_message_parse_new_clock (GstMessage *message,
+                             GstClock **clock);
+

Extracts the new clock from the GstMessage. +The clock object returned remains valid until the message is freed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_NEW_CLOCK.

 

clock

a pointer to hold the selected +new clock.

[out][allow-none][transfer none]
+
+
+
+
+

gst_message_new_application ()

+
GstMessage *
+gst_message_new_application (GstObject *src,
+                             GstStructure *structure);
+

Create a new application-typed message. GStreamer will never create these +messages; they are a gift from us to you. Enjoy.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

structure

the structure for the message. The message +will take ownership of the structure.

[transfer full]
+
+
+

Returns

+

The new application message.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_message_new_element ()

+
GstMessage *
+gst_message_new_element (GstObject *src,
+                         GstStructure *structure);
+

Create a new element-specific message. This is meant as a generic way of +allowing one-way communication from an element to an application, for example +"the firewire cable was unplugged". The format of the message should be +documented in the element's documentation. The structure field can be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

structure

The structure for the +message. The message will take ownership of the structure.

[transfer full]
+
+
+

Returns

+

The new element message.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_message_new_custom ()

+
GstMessage *
+gst_message_new_custom (GstMessageType type,
+                        GstObject *src,
+                        GstStructure *structure);
+

Create a new custom-typed message. This can be used for anything not +handled by other message-specific functions to pass a message to the +app. The structure field can be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

type

The GstMessageType to distinguish messages

 

src

The object originating the message.

[transfer none][allow-none]

structure

the structure for the +message. The message will take ownership of the structure.

[transfer full][allow-none]
+
+
+

Returns

+

The new message.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_message_new_segment_start ()

+
GstMessage *
+gst_message_new_segment_start (GstObject *src,
+                               GstFormat format,
+                               gint64 position);
+

Create a new segment message. This message is posted by elements that +start playback of a segment as a result of a segment seek. This message +is not received by the application but is used for maintenance reasons in +container elements.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

format

The format of the position being played

 

position

The position of the segment being played

 
+
+
+

Returns

+

the new segment start message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_segment_start ()

+
void
+gst_message_parse_segment_start (GstMessage *message,
+                                 GstFormat *format,
+                                 gint64 *position);
+

Extracts the position and format from the segment start message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_SEGMENT_START.

 

format

Result location for the format, or NULL.

[out][allow-none]

position

Result location for the position, or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_segment_done ()

+
GstMessage *
+gst_message_new_segment_done (GstObject *src,
+                              GstFormat format,
+                              gint64 position);
+

Create a new segment done message. This message is posted by elements that +finish playback of a segment as a result of a segment seek. This message +is received by the application after all elements that posted a segment_start +have posted the segment_done.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

format

The format of the position being done

 

position

The position of the segment being done

 
+
+
+

Returns

+

the new segment done message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_segment_done ()

+
void
+gst_message_parse_segment_done (GstMessage *message,
+                                GstFormat *format,
+                                gint64 *position);
+

Extracts the position and format from the segment done message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_SEGMENT_DONE.

 

format

Result location for the format, or NULL.

[out][allow-none]

position

Result location for the position, or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_duration_changed ()

+
GstMessage *
+gst_message_new_duration_changed (GstObject *src);
+

Create a new duration changed message. This message is posted by elements +that know the duration of a stream when the duration changes. This message +is received by bins and is used to calculate the total duration of a +pipeline.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

The new duration-changed message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_latency ()

+
GstMessage *
+gst_message_new_latency (GstObject *src);
+

This message can be posted by elements when their latency requirements have +changed.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

The new latency message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_async_start ()

+
GstMessage *
+gst_message_new_async_start (GstObject *src);
+

This message is posted by elements when they start an ASYNC state change.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

The new async_start message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_new_async_done ()

+
GstMessage *
+gst_message_new_async_done (GstObject *src,
+                            GstClockTime running_time);
+

The message is posted when elements completed an ASYNC state change. +running_time + contains the time of the desired running_time when this +elements goes to PLAYING. A value of GST_CLOCK_TIME_NONE for running_time + +means that the element has no clock interaction and thus doesn't care about +the running_time of the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

running_time

the desired running_time

 
+
+
+

Returns

+

The new async_done message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_async_done ()

+
void
+gst_message_parse_async_done (GstMessage *message,
+                              GstClockTime *running_time);
+

Extract the running_time from the async_done message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_ASYNC_DONE.

 

running_time

Result location for the running_time or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_step_start ()

+
GstMessage *
+gst_message_new_step_start (GstObject *src,
+                            gboolean active,
+                            GstFormat format,
+                            guint64 amount,
+                            gdouble rate,
+                            gboolean flush,
+                            gboolean intermediate);
+

This message is posted by elements when they accept or activate a new step +event for amount + in format +.

+

active + is set to FALSE when the element accepted the new step event and has +queued it for execution in the streaming threads.

+

active + is set to TRUE when the element has activated the step operation and +is now ready to start executing the step in the streaming thread. After this +message is emitted, the application can queue a new step operation in the +element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

 

active

if the step is active or queued

 

format

the format of amount +

 

amount

the amount of stepped data

 

rate

the rate of the stepped amount

 

flush

is this an flushing step

 

intermediate

is this an intermediate step

 
+
+
+

Returns

+

The new step_start message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_step_start ()

+
void
+gst_message_parse_step_start (GstMessage *message,
+                              gboolean *active,
+                              GstFormat *format,
+                              guint64 *amount,
+                              gdouble *rate,
+                              gboolean *flush,
+                              gboolean *intermediate);
+

Extract the values from step_start message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STEP_DONE.

 

active

result location for the active flag.

[out][allow-none]

format

result location for the format.

[out][allow-none]

amount

result location for the amount.

[out][allow-none]

rate

result location for the rate.

[out][allow-none]

flush

result location for the flush flag.

[out][allow-none]

intermediate

result location for the intermediate flag.

[out][allow-none]
+
+
+
+
+

gst_message_new_qos ()

+
GstMessage *
+gst_message_new_qos (GstObject *src,
+                     gboolean live,
+                     guint64 running_time,
+                     guint64 stream_time,
+                     guint64 timestamp,
+                     guint64 duration);
+

A QOS message is posted on the bus whenever an element decides to drop a +buffer because of QoS reasons or whenever it changes its processing strategy +because of QoS reasons (quality adjustments such as processing at lower +accuracy).

+

This message can be posted by an element that performs synchronisation against the +clock (live) or it could be dropped by an element that performs QoS because of QOS +events received from a downstream element (!live).

+

running_time +, stream_time +, timestamp +, duration + should be set to the +respective running-time, stream-time, timestamp and duration of the (dropped) +buffer that generated the QoS event. Values can be left to +GST_CLOCK_TIME_NONE when unknown.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

 

live

if the message was generated by a live element

 

running_time

the running time of the buffer that generated the message

 

stream_time

the stream time of the buffer that generated the message

 

timestamp

the timestamps of the buffer that generated the message

 

duration

the duration of the buffer that generated the message

 
+
+
+

Returns

+

The new qos message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_set_qos_values ()

+
void
+gst_message_set_qos_values (GstMessage *message,
+                            gint64 jitter,
+                            gdouble proportion,
+                            gint quality);
+

Set the QoS values that have been calculated/analysed from the QoS data

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_QOS.

 

jitter

The difference of the running-time against the deadline.

 

proportion

Long term prediction of the ideal rate relative to normal rate +to get optimal quality.

 

quality

An element dependent integer value that specifies the current +quality level of the element. The default maximum quality is 1000000.

 
+
+
+
+
+

gst_message_set_qos_stats ()

+
void
+gst_message_set_qos_stats (GstMessage *message,
+                           GstFormat format,
+                           guint64 processed,
+                           guint64 dropped);
+

Set the QoS stats representing the history of the current continuous pipeline +playback period.

+

When format + is GST_FORMAT_UNDEFINED + both dropped + and processed + are +invalid. Values of -1 for either processed + or dropped + mean unknown values.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_QOS.

 

format

Units of the 'processed' and 'dropped' fields. Video sinks and video +filters will use GST_FORMAT_BUFFERS (frames). Audio sinks and audio filters +will likely use GST_FORMAT_DEFAULT (samples).

 

processed

Total number of units correctly processed since the last state +change to READY or a flushing operation.

 

dropped

Total number of units dropped since the last state change to READY +or a flushing operation.

 
+
+
+
+
+

gst_message_parse_qos ()

+
void
+gst_message_parse_qos (GstMessage *message,
+                       gboolean *live,
+                       guint64 *running_time,
+                       guint64 *stream_time,
+                       guint64 *timestamp,
+                       guint64 *duration);
+

Extract the timestamps and live status from the QoS message.

+

The returned values give the running_time, stream_time, timestamp and +duration of the dropped buffer. Values of GST_CLOCK_TIME_NONE mean unknown +values.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_QOS.

 

live

if the message was generated by a live element.

[out][allow-none]

running_time

the running time of the buffer that +generated the message.

[out][allow-none]

stream_time

the stream time of the buffer that +generated the message.

[out][allow-none]

timestamp

the timestamps of the buffer that +generated the message.

[out][allow-none]

duration

the duration of the buffer that +generated the message.

[out][allow-none]
+
+
+
+
+

gst_message_parse_qos_values ()

+
void
+gst_message_parse_qos_values (GstMessage *message,
+                              gint64 *jitter,
+                              gdouble *proportion,
+                              gint *quality);
+

Extract the QoS values that have been calculated/analysed from the QoS data

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_QOS.

 

jitter

The difference of the running-time against +the deadline.

[out][allow-none]

proportion

Long term prediction of the ideal rate +relative to normal rate to get optimal quality.

[out][allow-none]

quality

An element dependent integer value that +specifies the current quality level of the element. The default +maximum quality is 1000000.

[out][allow-none]
+
+
+
+
+

gst_message_parse_qos_stats ()

+
void
+gst_message_parse_qos_stats (GstMessage *message,
+                             GstFormat *format,
+                             guint64 *processed,
+                             guint64 *dropped);
+

Extract the QoS stats representing the history of the current continuous +pipeline playback period.

+

When format + is GST_FORMAT_UNDEFINED + both dropped + and processed + are +invalid. Values of -1 for either processed + or dropped + mean unknown values.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_QOS.

 

format

Units of the 'processed' and 'dropped' fields. +Video sinks and video filters will use GST_FORMAT_BUFFERS (frames). +Audio sinks and audio filters will likely use GST_FORMAT_DEFAULT +(samples).

[out][allow-none]

processed

Total number of units correctly processed +since the last state change to READY or a flushing operation.

[out][allow-none]

dropped

Total number of units dropped since the last +state change to READY or a flushing operation.

[out][allow-none]
+
+
+
+
+

gst_message_new_toc ()

+
GstMessage *
+gst_message_new_toc (GstObject *src,
+                     GstToc *toc,
+                     gboolean updated);
+

Create a new TOC message. The message is posted by elements +that discovered or updated a TOC.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

the object originating the message.

 

toc

GstToc structure for the message.

[transfer none]

updated

whether TOC was updated or not.

 
+
+
+

Returns

+

a new TOC message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_toc ()

+
void
+gst_message_parse_toc (GstMessage *message,
+                       GstToc **toc,
+                       gboolean *updated);
+

Extract the TOC from the GstMessage. The TOC returned in the +output argument is a copy; the caller must free it with +gst_toc_unref() when done.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

a valid GstMessage of type GST_MESSAGE_TOC.

 

toc

return location for the TOC.

[out][transfer full]

updated

return location for the updated flag.

[out]
+
+
+
+
+

gst_message_new_reset_time ()

+
GstMessage *
+gst_message_new_reset_time (GstObject *src,
+                            GstClockTime running_time);
+

This message is posted when the pipeline running-time should be reset to +running_time +, like after a flushing seek.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

running_time

the requested running-time

 
+
+
+

Returns

+

The new reset_time message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_reset_time ()

+
void
+gst_message_parse_reset_time (GstMessage *message,
+                              GstClockTime *running_time);
+

Extract the running-time from the RESET_TIME message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_RESET_TIME.

 

running_time

Result location for the running_time or +NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_stream_start ()

+
GstMessage *
+gst_message_new_stream_start (GstObject *src);
+

Create a new stream_start message. This message is generated and posted in +the sink elements of a GstBin. The bin will only forward the STREAM_START +message to the application if all sinks have posted an STREAM_START message.

+
+

Parameters

+
+++++ + + + + + +

src

The object originating the message.

[transfer none][allow-none]
+
+
+

Returns

+

The new stream_start message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_set_group_id ()

+
void
+gst_message_set_group_id (GstMessage *message,
+                          guint group_id);
+

Sets the group id on the stream-start message.

+

All streams that have the same group id are supposed to be played +together, i.e. all streams inside a container file should have the +same group id but different stream ids. The group id should change +each time the stream is started, resulting in different group ids +each time a file is played for example.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

the message

 

group_id

the group id

 
+
+

Since: 1.2

+
+
+
+

gst_message_parse_group_id ()

+
gboolean
+gst_message_parse_group_id (GstMessage *message,
+                            guint *group_id);
+

Extract the group from the STREAM_START message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STREAM_START.

 

group_id

Result location for the group id or +NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the message had a group id set, FALSE otherwise

+

MT safe.

+
+

Since: 1.2

+
+
+
+

gst_message_new_stream_collection ()

+
GstMessage *
+gst_message_new_stream_collection (GstObject *src,
+                                   GstStreamCollection *collection);
+

Creates a new stream-collection message. The message is used to announce new +GstStreamCollection

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The GstObject that created the message

 

collection

The GstStreamCollection.

[transfer none]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.10

+
+
+
+

gst_message_parse_stream_collection ()

+
void
+gst_message_parse_stream_collection (GstMessage *message,
+                                     GstStreamCollection **collection);
+

Parses a stream-collection message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_STREAM_COLLECTION

 

collection

A location where to store a +pointer to the GstStreamCollection, or NULL.

[out][allow-none][transfer full]
+
+

Since: 1.10

+
+
+
+

gst_message_new_structure_change ()

+
GstMessage *
+gst_message_new_structure_change (GstObject *src,
+                                  GstStructureChangeType type,
+                                  GstElement *owner,
+                                  gboolean busy);
+

Create a new structure change message. This message is posted when the +structure of a pipeline is in the process of being changed, for example +when pads are linked or unlinked.

+

src + should be the sinkpad that unlinked or linked.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

type

The change type.

 

owner

The owner element of src +.

[transfer none]

busy

Whether the structure change is busy.

 
+
+
+

Returns

+

the new structure change message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_structure_change ()

+
void
+gst_message_parse_structure_change (GstMessage *message,
+                                    GstStructureChangeType *type,
+                                    GstElement **owner,
+                                    gboolean *busy);
+

Extracts the change type and completion status from the GstMessage.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STRUCTURE_CHANGE.

 

type

A pointer to hold the change type.

[out]

owner

The owner element of the +message source.

[out][allow-none][transfer none]

busy

a pointer to hold whether the change is in +progress or has been completed.

[out][allow-none]
+
+
+
+
+

gst_message_new_request_state ()

+
GstMessage *
+gst_message_new_request_state (GstObject *src,
+                               GstState state);
+

This message can be posted by elements when they want to have their state +changed. A typical use case would be an audio server that wants to pause the +pipeline because a higher priority stream is being played.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

state

The new requested state

 
+
+
+

Returns

+

the new request state message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_request_state ()

+
void
+gst_message_parse_request_state (GstMessage *message,
+                                 GstState *state);
+

Extract the requested state from the request_state message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_REQUEST_STATE.

 

state

Result location for the requested state or NULL.

[out][allow-none]
+
+
+
+
+

gst_message_new_stream_status ()

+
GstMessage *
+gst_message_new_stream_status (GstObject *src,
+                               GstStreamStatusType type,
+                               GstElement *owner);
+

Create a new stream status message. This message is posted when a streaming +thread is created/destroyed or when the state changed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The object originating the message.

 

type

The stream status type.

 

owner

the owner element of src +.

[transfer none]
+
+
+

Returns

+

the new stream status message.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_message_parse_stream_status ()

+
void
+gst_message_parse_stream_status (GstMessage *message,
+                                 GstStreamStatusType *type,
+                                 GstElement **owner);
+

Extracts the stream status type and owner the GstMessage. The returned +owner remains valid for as long as the reference to message + is valid and +should thus not be unreffed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STREAM_STATUS.

 

type

A pointer to hold the status type.

[out]

owner

The owner element of the message source.

[out][transfer none]
+
+
+
+
+

gst_message_set_stream_status_object ()

+
void
+gst_message_set_stream_status_object (GstMessage *message,
+                                      const GValue *object);
+

Configures the object handling the streaming thread. This is usually a +GstTask object but other objects might be added in the future.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STREAM_STATUS.

 

object

the object controlling the streaming

 
+
+
+
+
+

gst_message_get_stream_status_object ()

+
const GValue *
+gst_message_get_stream_status_object (GstMessage *message);
+

Extracts the object managing the streaming thread from message +.

+
+

Parameters

+
+++++ + + + + + +

message

A valid GstMessage of type GST_MESSAGE_STREAM_STATUS.

 
+
+
+

Returns

+

a GValue containing the object that manages the +streaming thread. This object is usually of type GstTask but other types can +be added in the future. The object remains valid as long as message +is +valid.

+

[nullable]

+
+
+
+
+

gst_message_new_progress ()

+
GstMessage *
+gst_message_new_progress (GstObject *src,
+                          GstProgressType type,
+                          const gchar *code,
+                          const gchar *text);
+

Progress messages are posted by elements when they use an asynchronous task +to perform actions triggered by a state change.

+

code + contains a well defined string describing the action. +text + should contain a user visible string detailing the current action.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The object originating the message.

 

type

a GstProgressType

 

code

a progress code

 

text

free, user visible text describing the progress

 
+
+
+

Returns

+

The new qos message.

+

[transfer full][nullable]

+
+
+
+
+

gst_message_parse_progress ()

+
void
+gst_message_parse_progress (GstMessage *message,
+                            GstProgressType *type,
+                            gchar **code,
+                            gchar **text);
+

Parses the progress type +, code + and text +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_PROGRESS.

 

type

location for the type.

[out][allow-none]

code

location for the code.

[out][allow-none][transfer full]

text

location for the text.

[out][allow-none][transfer full]
+
+
+
+
+

gst_message_new_need_context ()

+
GstMessage *
+gst_message_new_need_context (GstObject *src,
+                              const gchar *context_type);
+

This message is posted when an element needs a specific GstContext.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

context_type

The context type that is needed

 
+
+
+

Returns

+

The new need-context message.

+

MT safe.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_message_parse_context_type ()

+
gboolean
+gst_message_parse_context_type (GstMessage *message,
+                                const gchar **context_type);
+

Parse a context type from an existing GST_MESSAGE_NEED_CONTEXT message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GST_MESSAGE_NEED_CONTEXT type message

 

context_type

the context type, or NULL.

[out][transfer none][allow-none]
+
+
+

Returns

+

a gboolean indicating if the parsing succeeded.

+
+

Since: 1.2

+
+
+
+

gst_message_new_have_context ()

+
GstMessage *
+gst_message_new_have_context (GstObject *src,
+                              GstContext *context);
+

This message is posted when an element has a new local GstContext.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The object originating the message.

[transfer none][allow-none]

context

the context.

[transfer full]
+
+
+

Returns

+

The new have-context message.

+

MT safe.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_message_parse_have_context ()

+
void
+gst_message_parse_have_context (GstMessage *message,
+                                GstContext **context);
+

Extract the context from the HAVE_CONTEXT message.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

A valid GstMessage of type GST_MESSAGE_HAVE_CONTEXT.

 

context

Result location for the +context or NULL.

[out][transfer full][allow-none]
+
+

Since: 1.2

+
+
+
+

gst_message_new_device_added ()

+
GstMessage *
+gst_message_new_device_added (GstObject *src,
+                              GstDevice *device);
+

Creates a new device-added message. The device-added message is produced by +GstDeviceProvider or a GstDeviceMonitor. They announce the appearance +of monitored devices.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The GstObject that created the message

 

device

The new GstDevice.

[transfer none]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.4

+
+
+
+

gst_message_new_device_removed ()

+
GstMessage *
+gst_message_new_device_removed (GstObject *src,
+                                GstDevice *device);
+

Creates a new device-removed message. The device-removed message is produced +by GstDeviceProvider or a GstDeviceMonitor. They announce the +disappearance of monitored devices.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The GstObject that created the message

 

device

The removed GstDevice.

[transfer none]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.4

+
+
+
+

gst_message_parse_device_added ()

+
void
+gst_message_parse_device_added (GstMessage *message,
+                                GstDevice **device);
+

Parses a device-added message. The device-added message is produced by +GstDeviceProvider or a GstDeviceMonitor. It announces the appearance +of monitored devices.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_DEVICE_ADDED

 

device

A location where to store a +pointer to the new GstDevice, or NULL.

[out][allow-none][transfer full]
+
+

Since: 1.4

+
+
+
+

gst_message_parse_device_removed ()

+
void
+gst_message_parse_device_removed (GstMessage *message,
+                                  GstDevice **device);
+

Parses a device-removed message. The device-removed message is produced by +GstDeviceProvider or a GstDeviceMonitor. It announces the +disappearance of monitored devices.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_DEVICE_REMOVED

 

device

A location where to store a +pointer to the removed GstDevice, or NULL.

[out][allow-none][transfer full]
+
+

Since: 1.4

+
+
+
+

gst_message_new_property_notify ()

+
GstMessage *
+gst_message_new_property_notify (GstObject *src,
+                                 const gchar *property_name,
+                                 GValue *val);
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

The GstObject whose property changed (may or may not be a GstElement)

 

property_name

name of the property that changed

 

val

new property value, or NULL.

[allow-none][transfer full]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.10

+
+
+
+

gst_message_parse_property_notify ()

+
void
+gst_message_parse_property_notify (GstMessage *message,
+                                   GstObject **object,
+                                   const gchar **property_name,
+                                   const GValue **property_value);
+

Parses a property-notify message. These will be posted on the bus only +when set up with gst_element_add_property_notify_watch() or +gst_element_add_property_deep_notify_watch().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_PROPERTY_NOTIFY

 

object

location where to store a +pointer to the object whose property got changed, or NULL.

[out][allow-none][transfer none]

property_name

return location for +the name of the property that got changed, or NULL.

[out][transfer none][allow-none]

property_value

return location for +the new value of the property that got changed, or NULL. This will +only be set if the property notify watch was told to include the value +when it was set up.

[out][transfer none][allow-none]
+
+

Since: 1.10

+
+
+
+

gst_message_new_streams_selected ()

+
GstMessage *
+gst_message_new_streams_selected (GstObject *src,
+                                  GstStreamCollection *collection);
+

Creates a new steams-selected message. The message is used to announce +that an array of streams has been selected. This is generally in response +to a GST_EVENT_SELECT_STREAMS event, or when an element (such as decodebin3) +makes an initial selection of streams.

+

The message also contains the GstStreamCollection to which the various streams +belong to.

+

Users of gst_message_new_streams_selected() can add the selected streams with +gst_message_streams_selected_add().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

The GstObject that created the message

 

collection

The GstStreamCollection.

[transfer none]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.10

+
+
+
+

gst_message_parse_streams_selected ()

+
void
+gst_message_parse_streams_selected (GstMessage *message,
+                                    GstStreamCollection **collection);
+

Parses a streams-selected message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_STREAMS_SELECTED

 

collection

A location where to store a +pointer to the GstStreamCollection, or NULL.

[out][allow-none][transfer full]
+
+

Since: 1.10

+
+
+
+

gst_message_streams_selected_add ()

+
void
+gst_message_streams_selected_add (GstMessage *message,
+                                  GstStream *stream);
+

Adds the stream + to the message +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_STREAMS_SELECTED

 

stream

a GstStream to add to message +.

[transfer none]
+
+

Since: 1.10

+
+
+
+

gst_message_streams_selected_get_size ()

+
guint
+gst_message_streams_selected_get_size (GstMessage *message);
+

Returns the number of streams contained in the message +.

+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage of type GST_MESSAGE_STREAMS_SELECTED

 
+
+
+

Returns

+

The number of streams contained within.

+
+

Since: 1.10

+
+
+
+

gst_message_streams_selected_get_stream ()

+
GstStream *
+gst_message_streams_selected_get_stream
+                               (GstMessage *message,
+                                guint idx);
+

Retrieves the GstStream with index index + from the message +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_STREAMS_SELECTED

 

idx

Index of the stream to retrieve

 
+
+
+

Returns

+

A GstStream.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_message_new_redirect ()

+
GstMessage *
+gst_message_new_redirect (GstObject *src,
+                          const gchar *location,
+                          GstTagList *tag_list,
+                          const GstStructure *entry_struct);
+

Creates a new redirect message and adds a new entry to it. Redirect messages +are posted when an element detects that the actual data has to be retrieved +from a different location. This is useful if such a redirection cannot be +handled inside a source element, for example when HTTP 302/303 redirects +return a non-HTTP URL.

+

The redirect message can hold multiple entries. The first one is added +when the redirect message is created, with the given location, tag_list, +entry_struct arguments. Use gst_message_add_redirect_entry() to add more +entries.

+

Each entry has a location, a tag list, and a structure. All of these are +optional. The tag list and structure are useful for additional metadata, +such as bitrate statistics for the given location.

+

By default, message recipients should treat entries in the order they are +stored. The recipient should therefore try entry #0 first, and if this +entry is not acceptable or working, try entry #1 etc. Senders must make +sure that they add entries in this order. However, recipients are free to +ignore the order and pick an entry that is "best" for them. One example +would be a recipient that scans the entries for the one with the highest +bitrate tag.

+

The specified location string is copied. However, ownership over the tag +list and structure are transferred to the message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The GstObject whose property changed (may or may not be a GstElement)

 

location

location string for the new entry.

[transfer none]

tag_list

tag list for the new entry.

[transfer full][allow-none]

entry_struct

structure for the new entry.

[transfer full][allow-none]
+
+
+

Returns

+

a newly allocated GstMessage

+
+

Since: 1.10

+
+
+
+

gst_message_add_redirect_entry ()

+
void
+gst_message_add_redirect_entry (GstMessage *message,
+                                const gchar *location,
+                                GstTagList *tag_list,
+                                const GstStructure *entry_struct);
+

Creates and appends a new entry.

+

The specified location string is copied. However, ownership over the tag +list and structure are transferred to the message.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_REDIRECT

 

location

location string for the new entry.

[transfer none]

tag_list

tag list for the new entry.

[transfer full][allow-none]

entry_struct

structure for the new entry.

[transfer full][allow-none]
+
+

Since: 1.10

+
+
+
+

gst_message_parse_redirect_entry ()

+
void
+gst_message_parse_redirect_entry (GstMessage *message,
+                                  gsize entry_index,
+                                  const gchar **location,
+                                  GstTagList **tag_list,
+                                  const GstStructure **entry_struct);
+

Parses the location and/or structure from the entry with the given index. +The index must be between 0 and gst_message_get_num_redirect_entries() - 1. +Returned pointers are valid for as long as this message exists.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

message

a GstMessage of type GST_MESSAGE_REDIRECT

 

entry_index

index of the entry to parse

 

location

return location for +the pointer to the entry's location string, or NULL.

[out][transfer none][allow-none]

tag_list

return location for +the pointer to the entry's tag list, or NULL.

[out][transfer none][allow-none]

entry_struct

return location +for the pointer to the entry's structure, or NULL.

[out][transfer none][allow-none]
+
+

Since: 1.10

+
+
+
+

gst_message_get_num_redirect_entries ()

+
gsize
+gst_message_get_num_redirect_entries (GstMessage *message);
+
+

Parameters

+
+++++ + + + + + +

message

a GstMessage of type GST_MESSAGE_REDIRECT

 
+
+
+

Returns

+

the number of entries stored in the message

+
+

Since: 1.10

+
+
+
+

Types and Values

+
+

struct GstMessage

+
struct GstMessage {
+  GstMiniObject   mini_object;
+
+  GstMessageType  type;
+  guint64         timestamp;
+  GstObject      *src;
+  guint32         seqnum;
+};
+
+

A GstMessage.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject mini_object;

the parent structure

 

GstMessageType type;

the GstMessageType of the message

 

guint64 timestamp;

the timestamp of the message

 

GstObject *src;

the src of the message

 

guint32 seqnum;

the sequence number of the message

 
+
+
+
+
+

enum GstMessageType

+

The different message types that are available.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_MESSAGE_UNKNOWN

+

an undefined message

+
 

GST_MESSAGE_EOS

+

end-of-stream reached in a pipeline. The application will +only receive this message in the PLAYING state and every time it sets a +pipeline to PLAYING that is in the EOS state. The application can perform a +flushing seek in the pipeline, which will undo the EOS state again.

+
 

GST_MESSAGE_ERROR

+

an error occurred. When the application receives an error +message it should stop playback of the pipeline and not assume that more +data will be played.

+
 

GST_MESSAGE_WARNING

+

a warning occurred.

+
 

GST_MESSAGE_INFO

+

an info message occurred

+
 

GST_MESSAGE_TAG

+

a tag was found.

+
 

GST_MESSAGE_BUFFERING

+

the pipeline is buffering. When the application +receives a buffering message in the PLAYING state for a non-live pipeline it +must PAUSE the pipeline until the buffering completes, when the percentage +field in the message is 100%. For live pipelines, no action must be +performed and the buffering percentage can be used to inform the user about +the progress.

+
 

GST_MESSAGE_STATE_CHANGED

+

a state change happened

+
 

GST_MESSAGE_STATE_DIRTY

+

an element changed state in a streaming thread. +This message is deprecated.

+
 

GST_MESSAGE_STEP_DONE

+

a stepping operation finished.

+
 

GST_MESSAGE_CLOCK_PROVIDE

+

an element notifies its capability of providing + a clock. This message is used internally and + never forwarded to the application.

+
 

GST_MESSAGE_CLOCK_LOST

+

The current clock as selected by the pipeline became + unusable. The pipeline will select a new clock on + the next PLAYING state change. The application + should set the pipeline to PAUSED and back to + PLAYING when this message is received.

+
 

GST_MESSAGE_NEW_CLOCK

+

a new clock was selected in the pipeline.

+
 

GST_MESSAGE_STRUCTURE_CHANGE

+

the structure of the pipeline changed. This +message is used internally and never forwarded to the application.

+
 

GST_MESSAGE_STREAM_STATUS

+

status about a stream, emitted when it starts, + stops, errors, etc..

+
 

GST_MESSAGE_APPLICATION

+

message posted by the application, possibly + via an application-specific element.

+
 

GST_MESSAGE_ELEMENT

+

element-specific message, see the specific element's + documentation

+
 

GST_MESSAGE_SEGMENT_START

+

pipeline started playback of a segment. This +message is used internally and never forwarded to the application.

+
 

GST_MESSAGE_SEGMENT_DONE

+

pipeline completed playback of a segment. This +message is forwarded to the application after all elements that posted +GST_MESSAGE_SEGMENT_START + posted a GST_MESSAGE_SEGMENT_DONE message.

+
 

GST_MESSAGE_DURATION_CHANGED

+

The duration of a pipeline changed. The +application can get the new duration with a duration query.

+
 

GST_MESSAGE_LATENCY

+

Posted by elements when their latency changes. The +application should recalculate and distribute a new latency.

+
 

GST_MESSAGE_ASYNC_START

+

Posted by elements when they start an ASYNC +GstStateChange. This message is not forwarded to the application but is used +internally.

+
 

GST_MESSAGE_ASYNC_DONE

+

Posted by elements when they complete an ASYNC +GstStateChange. The application will only receive this message from the toplevel +pipeline.

+
 

GST_MESSAGE_REQUEST_STATE

+

Posted by elements when they want the pipeline to +change state. This message is a suggestion to the application which can +decide to perform the state change on (part of) the pipeline.

+
 

GST_MESSAGE_STEP_START

+

A stepping operation was started.

+
 

GST_MESSAGE_QOS

+

A buffer was dropped or an element changed its processing +strategy for Quality of Service reasons.

+
 

GST_MESSAGE_PROGRESS

+

A progress message.

+
 

GST_MESSAGE_TOC

+

A new table of contents (TOC) was found or previously found TOC +was updated.

+
 

GST_MESSAGE_RESET_TIME

+

Message to request resetting the pipeline's + running time from the pipeline. This is an internal message which + applications will likely never receive.

+
 

GST_MESSAGE_STREAM_START

+

Message indicating start of a new stream. Useful + e.g. when using playbin in gapless playback mode, to get notified when + the next title actually starts playing (which will be some time after + the URI for the next title has been set).

+
 

GST_MESSAGE_NEED_CONTEXT

+

Message indicating that an element wants a specific context (Since 1.2)

+
 

GST_MESSAGE_HAVE_CONTEXT

+

Message indicating that an element created a context (Since 1.2)

+
 

GST_MESSAGE_EXTENDED

+

Message is an extended message type (see below). + These extended message IDs can't be used directly with mask-based API + like gst_bus_poll() or gst_bus_timed_pop_filtered(), but you can still + filter for GST_MESSAGE_EXTENDED and then check the result for the + specific type. (Since 1.4)

+
 

GST_MESSAGE_DEVICE_ADDED

+

Message indicating a GstDevice was added to + a GstDeviceProvider (Since 1.4)

+
 

GST_MESSAGE_DEVICE_REMOVED

+

Message indicating a GstDevice was removed + from a GstDeviceProvider (Since 1.4)

+
 

GST_MESSAGE_PROPERTY_NOTIFY

+

Message indicating a GObject property has + changed (Since 1.10)

+
 

GST_MESSAGE_STREAM_COLLECTION

+

Message indicating a new GstStreamCollection + is available (Since 1.10)

+
 

GST_MESSAGE_STREAMS_SELECTED

+

Message indicating the active selection of + GstStreams has changed (Since 1.10)

+
 

GST_MESSAGE_REDIRECT

+

Message indicating to request the application to + try to play the given URL(s). Useful if for example a HTTP 302/303 + response is received with a non-HTTP URL inside. (Since 1.10)

+
 

GST_MESSAGE_ANY

+

mask for all of the above messages.

+
 
+
+
+
+
+

enum GstStructureChangeType

+

The type of a GST_MESSAGE_STRUCTURE_CHANGE.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_STRUCTURE_CHANGE_TYPE_PAD_LINK

+

Pad linking is starting or done.

+
 

GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK

+

Pad unlinking is starting or done.

+
 
+
+
+
+
+

enum GstStreamStatusType

+

The type of a GST_MESSAGE_STREAM_STATUS. The stream status messages inform the +application of new streaming threads and their status.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_STREAM_STATUS_TYPE_CREATE

+

A new thread need to be created.

+
 

GST_STREAM_STATUS_TYPE_ENTER

+

a thread entered its loop function

+
 

GST_STREAM_STATUS_TYPE_LEAVE

+

a thread left its loop function

+
 

GST_STREAM_STATUS_TYPE_DESTROY

+

a thread is destroyed

+
 

GST_STREAM_STATUS_TYPE_START

+

a thread is started

+
 

GST_STREAM_STATUS_TYPE_PAUSE

+

a thread is paused

+
 

GST_STREAM_STATUS_TYPE_STOP

+

a thread is stopped

+
 
+
+
+
+
+

enum GstProgressType

+

The type of a GST_MESSAGE_PROGRESS. The progress messages inform the +application of the status of asynchronous tasks.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PROGRESS_TYPE_START

+

A new task started.

+
 

GST_PROGRESS_TYPE_CONTINUE

+

A task completed and a new one continues.

+
 

GST_PROGRESS_TYPE_COMPLETE

+

A task completed.

+
 

GST_PROGRESS_TYPE_CANCELED

+

A task was canceled.

+
 

GST_PROGRESS_TYPE_ERROR

+

A task caused an error. An error message is also + posted on the bus.

+
 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstObject.html b/docs/gst/html/GstObject.html new file mode 100644 index 0000000..f70ffe6 --- /dev/null +++ b/docs/gst/html/GstObject.html @@ -0,0 +1,2118 @@ + + + + +GstObject: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstObject

+

GstObject — Base class for the GStreamer object hierarchy

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_OBJECT_FLAGS() +
#define +GST_OBJECT_FLAG_IS_SET() +
#define +GST_OBJECT_FLAG_SET() +
#define +GST_OBJECT_FLAG_UNSET() +
#define +GST_OBJECT_NAME() +
#define +GST_OBJECT_PARENT() +
#define +GST_OBJECT_REFCOUNT() +
#define +GST_OBJECT_REFCOUNT_VALUE() +
#define +GST_OBJECT_LOCK() +
#define +GST_OBJECT_TRYLOCK() +
#define +GST_OBJECT_UNLOCK() +
#define +GST_OBJECT_GET_LOCK() +
+gboolean + +gst_object_set_name () +
+gchar * + +gst_object_get_name () +
+gboolean + +gst_object_set_parent () +
+GstObject * + +gst_object_get_parent () +
+gboolean + +gst_object_has_as_parent () +
+void + +gst_object_unparent () +
+void + +gst_object_default_deep_notify () +
+void + +gst_object_default_error () +
+gboolean + +gst_object_check_uniqueness () +
+gboolean + +gst_object_has_as_ancestor () +
+gboolean + +gst_object_has_ancestor () +
+gpointer + +gst_object_ref () +
+void + +gst_object_unref () +
+gpointer + +gst_object_ref_sink () +
+gboolean + +gst_object_replace () +
+gchar * + +gst_object_get_path_string () +
+GstClockTime + +gst_object_suggest_next_sync () +
+gboolean + +gst_object_sync_values () +
+gboolean + +gst_object_has_active_control_bindings () +
+void + +gst_object_set_control_bindings_disabled () +
+void + +gst_object_set_control_binding_disabled () +
+gboolean + +gst_object_add_control_binding () +
+GstControlBinding * + +gst_object_get_control_binding () +
+gboolean + +gst_object_remove_control_binding () +
+GValue * + +gst_object_get_value () +
+gboolean + +gst_object_get_value_array () +
+gboolean + +gst_object_get_g_value_array () +
+GstClockTime + +gst_object_get_control_rate () +
+void + +gst_object_set_control_rate () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+gchar *nameRead / Write / Construct
+GstObject *parentRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voiddeep-notifyNo Hooks
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstObject
structGstObjectClass
enumGstObjectFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ├── GstAllocator
+            ├── GstPad
+            ├── GstPadTemplate
+            ├── GstPluginFeature
+            ├── GstElement
+            ├── GstBus
+            ├── GstTask
+            ├── GstTaskPool
+            ├── GstClock
+            ├── GstControlBinding
+            ├── GstControlSource
+            ├── GstPlugin
+            ├── GstRegistry
+            ├── GstBufferPool
+            ├── GstTracer
+            ╰── GstTracerRecord
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstObject provides a root for the object hierarchy tree filed in by the +GStreamer library. It is currently a thin wrapper on top of +GInitiallyUnowned. It is an abstract class that is not very usable on its own.

+

GstObject gives us basic refcounting, parenting functionality and locking. +Most of the functions are just extended for special GStreamer needs and can be +found under the same name in the base class of GstObject which is GObject +(e.g. g_object_ref() becomes gst_object_ref()).

+

Since GstObject derives from GInitiallyUnowned, it also inherits the +floating reference. Be aware that functions such as gst_bin_add() and +gst_element_add_pad() take ownership of the floating reference.

+

In contrast to GObject instances, GstObject adds a name property. The functions +gst_object_set_name() and gst_object_get_name() are used to set/get the name +of the object.

+
+

controlled properties

+

Controlled properties offers a lightweight way to adjust gobject properties +over stream-time. It works by using time-stamped value pairs that are queued +for element-properties. At run-time the elements continuously pull value +changes for the current stream-time.

+

What needs to be changed in a GstElement? +Very little - it is just two steps to make a plugin controllable!

+
    +
  • mark gobject-properties paramspecs that make sense to be controlled, +by GST_PARAM_CONTROLLABLE.

  • +
  • when processing data (get, chain, loop function) at the beginning call +gst_object_sync_values(element,timestamp). +This will make the controller update all GObject properties that are +under its control with the current values based on the timestamp.

  • +
+

What needs to be done in applications? Again it's not a lot to change.

+
    +
  • create a GstControlSource. +csource = gst_interpolation_control_source_new(); +g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);

  • +
  • Attach the GstControlSource on the controller to a property. +gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource));

  • +
  • Set the control values +gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1); +gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);

  • +
  • start your pipeline

  • +
+
+
+
+

Functions

+
+

GST_OBJECT_FLAGS()

+
#define GST_OBJECT_FLAGS(obj)                  (GST_OBJECT_CAST (obj)->flags)
+
+

This macro returns the entire set of flags for the object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

GST_OBJECT_FLAG_IS_SET()

+
#define GST_OBJECT_FLAG_IS_SET(obj,flag)       ((GST_OBJECT_FLAGS (obj) & (flag)) == (flag))
+
+

This macro checks to see if the given flag is set.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

a GstObject

 

flag

Flag to check for

 
+
+
+
+
+

GST_OBJECT_FLAG_SET()

+
#define GST_OBJECT_FLAG_SET(obj,flag)          (GST_OBJECT_FLAGS (obj) |= (flag))
+
+

This macro sets the given bits.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

a GstObject

 

flag

Flag to set

 
+
+
+
+
+

GST_OBJECT_FLAG_UNSET()

+
#define GST_OBJECT_FLAG_UNSET(obj,flag)        (GST_OBJECT_FLAGS (obj) &= ~(flag))
+
+

This macro unsets the given bits.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

a GstObject

 

flag

Flag to set

 
+
+
+
+
+

GST_OBJECT_NAME()

+
#define GST_OBJECT_NAME(obj)            (GST_OBJECT_CAST(obj)->name)
+
+

Get the name of this object. This is not thread-safe by default +(i.e. you will have to make sure the object lock is taken yourself). +If in doubt use gst_object_get_name() instead.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

GST_OBJECT_PARENT()

+
#define GST_OBJECT_PARENT(obj)          (GST_OBJECT_CAST(obj)->parent)
+
+

Get the parent of this object. This is not thread-safe by default +(i.e. you will have to make sure the object lock is taken yourself). +If in doubt use gst_object_get_parent() instead.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

GST_OBJECT_REFCOUNT()

+
#define GST_OBJECT_REFCOUNT(obj)                (((GObject*)(obj))->ref_count)
+
+

Get access to the reference count field of the object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

GST_OBJECT_REFCOUNT_VALUE()

+
#define GST_OBJECT_REFCOUNT_VALUE(obj)          g_atomic_int_get ((gint *) &GST_OBJECT_REFCOUNT(obj))
+
+

Get the reference count value of the object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

GST_OBJECT_LOCK()

+
#define GST_OBJECT_LOCK(obj)                   g_mutex_lock(GST_OBJECT_GET_LOCK(obj))
+
+

This macro will obtain a lock on the object, making serialization possible. +It blocks until the lock can be obtained.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject to lock

 
+
+
+
+
+

GST_OBJECT_TRYLOCK()

+
#define GST_OBJECT_TRYLOCK(obj)                g_mutex_trylock(GST_OBJECT_GET_LOCK(obj))
+
+

This macro will try to obtain a lock on the object, but will return with +FALSE if it can't get it immediately.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject.

 
+
+
+
+
+

GST_OBJECT_UNLOCK()

+
#define GST_OBJECT_UNLOCK(obj)                 g_mutex_unlock(GST_OBJECT_GET_LOCK(obj))
+
+

This macro releases a lock on the object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject to unlock.

 
+
+
+
+
+

GST_OBJECT_GET_LOCK()

+
#define GST_OBJECT_GET_LOCK(obj)               (&GST_OBJECT_CAST(obj)->lock)
+
+

Acquire a reference to the mutex of this object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstObject

 
+
+
+
+
+

gst_object_set_name ()

+
gboolean
+gst_object_set_name (GstObject *object,
+                     const gchar *name);
+

Sets the name of object +, or gives object + a guaranteed unique +name (if name + is NULL). +This function makes a copy of the provided name, so the caller +retains ownership of the name it sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

a GstObject

 

name

new name of object.

[allow-none]
+
+
+

Returns

+

TRUE if the name could be set. Since Objects that have +a parent cannot be renamed, this function returns FALSE in those +cases.

+

MT safe. This function grabs and releases object +'s LOCK.

+
+
+
+
+

gst_object_get_name ()

+
gchar *
+gst_object_get_name (GstObject *object);
+

Returns a copy of the name of object +. +Caller should g_free() the return value after usage. +For a nameless object, this returns NULL, which you can safely g_free() +as well.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject

 
+
+
+

Returns

+

the name of object +. g_free() +after usage.

+

MT safe. This function grabs and releases object +'s LOCK.

+

[transfer full][nullable]

+
+
+
+
+

gst_object_set_parent ()

+
gboolean
+gst_object_set_parent (GstObject *object,
+                       GstObject *parent);
+

Sets the parent of object + to parent +. The object's reference count will +be incremented, and any floating reference will be removed (see gst_object_ref_sink()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

a GstObject.

[transfer floating]

parent

new parent of object

 
+
+
+

Returns

+

TRUE if parent +could be set or FALSE when object +already had a parent or object +and parent +are the same.

+

MT safe. Grabs and releases object +'s LOCK.

+
+
+
+
+

gst_object_get_parent ()

+
GstObject *
+gst_object_get_parent (GstObject *object);
+

Returns the parent of object +. This function increases the refcount +of the parent object so you should gst_object_unref() it after usage.

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject

 
+
+
+

Returns

+

parent of object +, this can be +NULL if object +has no parent. unref after usage.

+

MT safe. Grabs and releases object +'s LOCK.

+

[transfer full][nullable]

+
+
+
+
+

gst_object_has_as_parent ()

+
gboolean
+gst_object_has_as_parent (GstObject *object,
+                          GstObject *parent);
+

Check if parent + is the parent of object +. +E.g. a GstElement can check if it owns a given GstPad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

a GstObject to check

 

parent

a GstObject to check as parent

 
+
+
+

Returns

+

FALSE if either object +or parent +is NULL. TRUE if parent +is +the parent of object +. Otherwise FALSE.

+

MT safe. Grabs and releases object +'s locks.

+
+

Since: 1.6

+
+
+
+

gst_object_unparent ()

+
void
+gst_object_unparent (GstObject *object);
+

Clear the parent of object +, removing the associated reference. +This function decreases the refcount of object +.

+

MT safe. Grabs and releases object +'s lock.

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject to unparent

 
+
+
+
+
+

gst_object_default_deep_notify ()

+
void
+gst_object_default_deep_notify (GObject *object,
+                                GstObject *orig,
+                                GParamSpec *pspec,
+                                gchar **excluded_props);
+

A default deep_notify signal callback for an object. The user data +should contain a pointer to an array of strings that should be excluded +from the notify. The default handler will print the new value of the property +using g_print.

+

MT safe. This function grabs and releases object +'s LOCK for getting its + path string.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

object

the GObject that signalled the notify.

 

orig

a GstObject that initiated the notify.

 

pspec

a GParamSpec of the property.

 

excluded_props

a set of user-specified properties to exclude or NULL to show +all changes.

[array zero-terminated=1][element-type gchar*][allow-none]
+
+
+
+
+

gst_object_default_error ()

+
void
+gst_object_default_error (GstObject *source,
+                          const GError *error,
+                          const gchar *debug);
+

A default error function that uses g_printerr() to display the error message +and the optional debug sting..

+

The default handler will simply print the error string using g_print.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

source

the GstObject that initiated the error.

 

error

the GError.

[in]

debug

an additional debug information string, or NULL.

[in][allow-none]
+
+
+
+
+

gst_object_check_uniqueness ()

+
gboolean
+gst_object_check_uniqueness (GList *list,
+                             const gchar *name);
+

Checks to see if there is any object named name + in list +. This function +does not do any locking of any kind. You might want to protect the +provided list with the lock of the owner of the list. This function +will lock each GstObject in the list to compare the name, so be +careful when passing a list with a locked object.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

a list of GstObject to +check through.

[transfer none][element-type Gst.Object]

name

the name to search for

 
+
+
+

Returns

+

TRUE if a GstObject named name +does not appear in list +, +FALSE if it does.

+

MT safe. Grabs and releases the LOCK of each object in the list.

+
+
+
+
+

gst_object_has_as_ancestor ()

+
gboolean
+gst_object_has_as_ancestor (GstObject *object,
+                            GstObject *ancestor);
+

Check if object + has an ancestor ancestor + somewhere up in +the hierarchy. One can e.g. check if a GstElement is inside a GstPipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

a GstObject to check

 

ancestor

a GstObject to check as ancestor

 
+
+
+

Returns

+

TRUE if ancestor +is an ancestor of object +.

+

MT safe. Grabs and releases object +'s locks.

+
+
+
+
+

gst_object_has_ancestor ()

+
gboolean
+gst_object_has_ancestor (GstObject *object,
+                         GstObject *ancestor);
+
+

gst_object_has_ancestor is deprecated and should not be used in newly-written code.

+

Use gst_object_has_as_ancestor() instead.

+

MT safe. Grabs and releases object +'s locks.

+
+

Check if object + has an ancestor ancestor + somewhere up in +the hierarchy. One can e.g. check if a GstElement is inside a GstPipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

a GstObject to check

 

ancestor

a GstObject to check as ancestor

 
+
+
+

Returns

+

TRUE if ancestor +is an ancestor of object +.

+
+
+
+
+

gst_object_ref ()

+
gpointer
+gst_object_ref (gpointer object);
+

Increments the reference count on object +. This function +does not take the lock on object + because it relies on +atomic refcounting.

+

This object returns the input parameter to ease writing +constructs like : + result = gst_object_ref (object->parent);

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject to reference.

[type Gst.Object]
+
+
+

Returns

+

A pointer to object +.

+

[transfer full][type Gst.Object]

+
+
+
+
+

gst_object_unref ()

+
void
+gst_object_unref (gpointer object);
+

Decrements the reference count on object +. If reference count hits +zero, destroy object +. This function does not take the lock +on object + as it relies on atomic refcounting.

+

The unref method should never be called with the LOCK held since +this might deadlock the dispose function.

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject to unreference.

[type Gst.Object]
+
+
+
+
+

gst_object_ref_sink ()

+
gpointer
+gst_object_ref_sink (gpointer object);
+

Increase the reference count of object +, and possibly remove the floating +reference, if object + has a floating reference.

+

In other words, if the object is floating, then this call "assumes ownership" +of the floating reference, converting it to a normal reference by clearing +the floating flag while leaving the reference count unchanged. If the object +is not floating, then this call adds a new normal reference increasing the +reference count by one.

+

For more background on "floating references" please see the GObject +documentation.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject to sink

 
+
+
+
+
+

gst_object_replace ()

+
gboolean
+gst_object_replace (GstObject **oldobj,
+                    GstObject *newobj);
+

Atomically modifies a pointer to point to a new object. +The reference count of oldobj + is decreased and the reference count of +newobj + is increased.

+

Either newobj + and the value pointed to by oldobj + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

oldobj

pointer to a place of +a GstObject to replace.

[inout][transfer full][nullable]

newobj

a new GstObject.

[transfer none][allow-none]
+
+
+

Returns

+

TRUE if newobj +was different from oldobj +

+
+
+
+
+

gst_object_get_path_string ()

+
gchar *
+gst_object_get_path_string (GstObject *object);
+

Generates a string describing the path of object + in +the object hierarchy. Only useful (or used) for debugging.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

object

a GstObject

 
+
+
+

Returns

+

a string describing the path of object +. You must +g_free() the string after usage.

+

MT safe. Grabs and releases the GstObject's LOCK for all objects +in the hierarchy.

+

[transfer full]

+
+
+
+
+

gst_object_suggest_next_sync ()

+
GstClockTime
+gst_object_suggest_next_sync (GstObject *object);
+

Returns a suggestion for timestamps where buffers should be split +to get best controller results.

+
+

Parameters

+
+++++ + + + + + +

object

the object that has controlled properties

 
+
+
+

Returns

+

Returns the suggested timestamp or GST_CLOCK_TIME_NONE +if no control-rate was set.

+
+
+
+
+

gst_object_sync_values ()

+
gboolean
+gst_object_sync_values (GstObject *object,
+                        GstClockTime timestamp);
+

Sets the properties of the object, according to the GstControlSources that +(maybe) handle them and for the given timestamp.

+

If this function fails, it is most likely the application developers fault. +Most probably the control sources are not setup correctly.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the object that has controlled properties

 

timestamp

the time that should be processed

 
+
+
+

Returns

+

TRUE if the controller values could be applied to the object +properties, FALSE otherwise

+
+
+
+
+

gst_object_has_active_control_bindings ()

+
gboolean
+gst_object_has_active_control_bindings
+                               (GstObject *object);
+

Check if the object + has active controlled properties.

+
+

Parameters

+
+++++ + + + + + +

object

the object that has controlled properties

 
+
+
+

Returns

+

TRUE if the object has active controlled properties

+
+
+
+
+

gst_object_set_control_bindings_disabled ()

+
void
+gst_object_set_control_bindings_disabled
+                               (GstObject *object,
+                                gboolean disabled);
+

This function is used to disable all controlled properties of the object + for +some time, i.e. gst_object_sync_values() will do nothing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the object that has controlled properties

 

disabled

boolean that specifies whether to disable the controller +or not.

 
+
+
+
+
+

gst_object_set_control_binding_disabled ()

+
void
+gst_object_set_control_binding_disabled
+                               (GstObject *object,
+                                const gchar *property_name,
+                                gboolean disabled);
+

This function is used to disable the control bindings on a property for +some time, i.e. gst_object_sync_values() will do nothing for the +property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object that has controlled properties

 

property_name

property to disable

 

disabled

boolean that specifies whether to disable the controller +or not.

 
+
+
+
+
+

gst_object_add_control_binding ()

+
gboolean
+gst_object_add_control_binding (GstObject *object,
+                                GstControlBinding *binding);
+

Attach the GstControlBinding to the object. If there already was a +GstControlBinding for this property it will be replaced.

+

The object's reference count will be incremented, and any floating +reference will be removed (see gst_object_ref_sink())

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the controller object

 

binding

the GstControlBinding that should be used.

[transfer floating]
+
+
+

Returns

+

FALSE if the given binding +has not been setup for this object or +has been setup for a non suitable property, TRUE otherwise.

+
+
+
+
+

gst_object_get_control_binding ()

+
GstControlBinding *
+gst_object_get_control_binding (GstObject *object,
+                                const gchar *property_name);
+

Gets the corresponding GstControlBinding for the property. This should be +unreferenced again after use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the object

 

property_name

name of the property

 
+
+
+

Returns

+

the GstControlBinding for +property_name +or NULL if the property is not controlled.

+

[transfer full][nullable]

+
+
+
+
+

gst_object_remove_control_binding ()

+
gboolean
+gst_object_remove_control_binding (GstObject *object,
+                                   GstControlBinding *binding);
+

Removes the corresponding GstControlBinding. If it was the +last ref of the binding, it will be disposed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the object

 

binding

the binding

 
+
+
+

Returns

+

TRUE if the binding could be removed.

+
+
+
+
+

gst_object_get_value ()

+
GValue *
+gst_object_get_value (GstObject *object,
+                      const gchar *property_name,
+                      GstClockTime timestamp);
+

Gets the value for the given controlled property at the requested time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object that has controlled properties

 

property_name

the name of the property to get

 

timestamp

the time the control-change should be read from

 
+
+
+

Returns

+

the GValue of the property at the given time, +or NULL if the property isn't controlled.

+

[nullable]

+
+
+
+
+

gst_object_get_value_array ()

+
gboolean
+gst_object_get_value_array (GstObject *object,
+                            const gchar *property_name,
+                            GstClockTime timestamp,
+                            GstClockTime interval,
+                            guint n_values,
+                            gpointer values);
+

Gets a number of values for the given controlled property starting at the +requested time. The array values + need to hold enough space for n_values + of +the same type as the objects property's type.

+

This function is useful if one wants to e.g. draw a graph of the control +curve or apply a control curve sample by sample.

+

The values are unboxed and ready to be used. The similar function +gst_object_get_g_value_array() returns the array as GValues and is +better suites for bindings.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

the object that has controlled properties

 

property_name

the name of the property to get

 

timestamp

the time that should be processed

 

interval

the time spacing between subsequent values

 

n_values

the number of values

 

values

array to put control-values in

 
+
+
+

Returns

+

TRUE if the given array could be filled, FALSE otherwise

+
+
+
+
+

gst_object_get_g_value_array ()

+
gboolean
+gst_object_get_g_value_array (GstObject *object,
+                              const gchar *property_name,
+                              GstClockTime timestamp,
+                              GstClockTime interval,
+                              guint n_values,
+                              GValue *values);
+

Gets a number of GValues for the given controlled property starting at the +requested time. The array values + need to hold enough space for n_values + of +GValue.

+

This function is useful if one wants to e.g. draw a graph of the control +curve or apply a control curve sample by sample.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

the object that has controlled properties

 

property_name

the name of the property to get

 

timestamp

the time that should be processed

 

interval

the time spacing between subsequent values

 

n_values

the number of values

 

values

array to put control-values in.

[array length=n_values]
+
+
+

Returns

+

TRUE if the given array could be filled, FALSE otherwise

+
+
+
+
+

gst_object_get_control_rate ()

+
GstClockTime
+gst_object_get_control_rate (GstObject *object);
+

Obtain the control-rate for this object +. Audio processing GstElement +objects will use this rate to sub-divide their processing loop and call +gst_object_sync_values() inbetween. The length of the processing segment +should be up to control +-rate nanoseconds.

+

If the object + is not under property control, this will return +GST_CLOCK_TIME_NONE. This allows the element to avoid the sub-dividing.

+

The control-rate is not expected to change if the element is in +GST_STATE_PAUSED or GST_STATE_PLAYING.

+
+

Parameters

+
+++++ + + + + + +

object

the object that has controlled properties

 
+
+
+

Returns

+

the control rate in nanoseconds

+
+
+
+
+

gst_object_set_control_rate ()

+
void
+gst_object_set_control_rate (GstObject *object,
+                             GstClockTime control_rate);
+

Change the control-rate for this object +. Audio processing GstElement +objects will use this rate to sub-divide their processing loop and call +gst_object_sync_values() inbetween. The length of the processing segment +should be up to control +-rate nanoseconds.

+

The control-rate should not change if the element is in GST_STATE_PAUSED or +GST_STATE_PLAYING.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the object that has controlled properties

 

control_rate

the new control-rate in nanoseconds.

 
+
+
+
+
+

Types and Values

+
+

struct GstObject

+
struct GstObject {
+  GMutex         lock;        /* object LOCK */
+  gchar         *name;        /* object name */
+  GstObject     *parent;      /* this object's parent, weak ref */
+  guint32        flags;
+};
+
+

GStreamer base object class.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GMutex lock;

object LOCK

 

gchar *name;

The name of the object

 

GstObject *parent;

this object's parent, weak ref

 

guint32 flags;

flags for this object

 
+
+
+
+
+

struct GstObjectClass

+
struct GstObjectClass {
+  GInitiallyUnownedClass parent_class;
+
+  const gchar *path_string_separator;
+
+  /* signals */
+  void          (*deep_notify)      (GstObject * object, GstObject * orig, GParamSpec * pspec);
+
+  /* virtual methods for subclasses */
+};
+
+

GStreamer base object class.

+
+

Members

+
+++++ + + + + + + + + + + + + +

const gchar *path_string_separator;

separator used by gst_object_get_path_string()

 

deep_notify ()

default signal handler

 
+
+
+
+
+

enum GstObjectFlags

+

The standard flags that an gstobject may have.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_OBJECT_FLAG_MAY_BE_LEAKED

+

the object is expected to stay alive even +after gst_deinit() has been called and so should be ignored by leak +detection tools. (Since 1.10)

+
 

GST_OBJECT_FLAG_LAST

+

subclasses can add additional flags starting from this flag

+
 
+
+
+
+
+

Property Details

+
+

The “name” property

+
  “name”                     gchar *
+

The name of the object.

+

Flags: Read / Write / Construct

+

Default value: NULL

+
+
+
+

The “parent” property

+
  “parent”                   GstObject *
+

The parent of the object. Please note, that when changing the 'parent' +property, we don't emit “notify” and “deep-notify” +signals due to locking issues. In some cases one can use +“element-added” or “element-removed” signals on the parent to +achieve a similar effect.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “deep-notify” signal

+
void
+user_function (GstObject  *gstobject,
+               GstObject  *prop_object,
+               GParamSpec *prop,
+               gpointer    user_data)
+

The deep notify signal is used to be notified of property changes. It is +typically attached to the toplevel bin to receive notifications from all +the elements contained in that bin.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

gstobject

a GstObject

 

prop_object

the object that originated the signal

 

prop

the property that changed

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: No Hooks

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPad.html b/docs/gst/html/GstPad.html new file mode 100644 index 0000000..de736a8 --- /dev/null +++ b/docs/gst/html/GstPad.html @@ -0,0 +1,8633 @@ + + + + +GstPad: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPad

+

GstPad — Object contained by elements that allows links to + other elements

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
const gchar * + +gst_pad_link_get_name () +
#define +GST_PAD_LINK_FAILED() +
#define +GST_PAD_LINK_SUCCESSFUL() +
const gchar * + +gst_flow_get_name () +
+GQuark + +gst_flow_to_quark () +
const gchar * + +gst_pad_mode_get_name () +
+GstFlowReturn + +gst_pad_store_sticky_event () +
#define +gst_pad_get_name() +
+GstPadDirection + +gst_pad_get_direction () +
#define +gst_pad_get_parent() +
+GstElement * + +gst_pad_get_parent_element () +
+GstPadTemplate * + +gst_pad_get_pad_template () +
+GstPadLinkReturn + +gst_pad_link () +
+GstPadLinkReturn + +gst_pad_link_full () +
+gboolean + +gst_pad_link_maybe_ghosting () +
+gboolean + +gst_pad_link_maybe_ghosting_full () +
+gboolean + +gst_pad_unlink () +
+gboolean + +gst_pad_is_linked () +
+gboolean + +gst_pad_can_link () +
+GstCaps * + +gst_pad_get_allowed_caps () +
+GstCaps * + +gst_pad_get_current_caps () +
+GstCaps * + +gst_pad_get_pad_template_caps () +
+GstPad * + +gst_pad_get_peer () +
+void + +gst_pad_use_fixed_caps () +
+gboolean + +gst_pad_has_current_caps () +
+GstEvent * + +gst_pad_get_sticky_event () +
+gboolean + +(*GstPadStickyEventsForeachFunction) () +
+void + +gst_pad_sticky_events_foreach () +
+gboolean + +gst_pad_is_active () +
+GstFlowReturn + +gst_pad_get_last_flow_return () +
#define +GST_PAD_PROBE_INFO_TYPE() +
#define +GST_PAD_PROBE_INFO_ID() +
#define +GST_PAD_PROBE_INFO_DATA() +
#define +GST_PAD_PROBE_INFO_BUFFER() +
#define +GST_PAD_PROBE_INFO_BUFFER_LIST() +
#define +GST_PAD_PROBE_INFO_EVENT() +
#define +GST_PAD_PROBE_INFO_QUERY() +
+GstBuffer * + +gst_pad_probe_info_get_buffer () +
+GstBufferList * + +gst_pad_probe_info_get_buffer_list () +
+GstEvent * + +gst_pad_probe_info_get_event () +
+GstQuery * + +gst_pad_probe_info_get_query () +
#define +GST_PAD_PROBE_INFO_OFFSET() +
#define +GST_PAD_PROBE_INFO_SIZE() +
#define +GST_PAD_PROBE_INFO_FLOW_RETURN() +
+GstPadProbeReturn + +(*GstPadProbeCallback) () +
+gulong + +gst_pad_add_probe () +
+void + +gst_pad_remove_probe () +
+gboolean + +gst_pad_is_blocked () +
+gboolean + +gst_pad_is_blocking () +
+gint64 + +gst_pad_get_offset () +
+void + +gst_pad_set_offset () +
+GstPad * + +gst_pad_new () +
+GstPad * + +gst_pad_new_from_template () +
+GstPad * + +gst_pad_new_from_static_template () +
#define +gst_pad_set_chain_function() +
+void + +gst_pad_set_chain_function_full () +
+GstFlowReturn + +(*GstPadChainFunction) () +
#define +gst_pad_set_chain_list_function() +
+void + +gst_pad_set_chain_list_function_full () +
+GstFlowReturn + +(*GstPadChainListFunction) () +
+GstFlowReturn + +gst_pad_get_range () +
#define +gst_pad_set_getrange_function() +
+void + +gst_pad_set_getrange_function_full () +
+GstFlowReturn + +(*GstPadGetRangeFunction) () +
#define +gst_pad_set_event_function() +
+void + +gst_pad_set_event_function_full () +
+gboolean + +(*GstPadEventFunction) () +
#define +gst_pad_set_event_full_function() +
+void + +gst_pad_set_event_full_function_full () +
+GstFlowReturn + +(*GstPadEventFullFunction) () +
#define +gst_pad_set_link_function() +
+void + +gst_pad_set_link_function_full () +
+GstPadLinkReturn + +(*GstPadLinkFunction) () +
#define +gst_pad_set_unlink_function() +
+void + +gst_pad_set_unlink_function_full () +
+void + +(*GstPadUnlinkFunction) () +
+gboolean + +gst_pad_proxy_query_caps () +
+gboolean + +gst_pad_proxy_query_accept_caps () +
#define +gst_pad_set_activate_function() +
+void + +gst_pad_set_activate_function_full () +
+gboolean + +(*GstPadActivateFunction) () +
#define +gst_pad_set_activatemode_function() +
+void + +gst_pad_set_activatemode_function_full () +
+gboolean + +(*GstPadActivateModeFunction) () +
+gboolean + +gst_pad_needs_reconfigure () +
+gboolean + +gst_pad_check_reconfigure () +
+void + +gst_pad_mark_reconfigure () +
+GstFlowReturn + +gst_pad_push () +
+gboolean + +gst_pad_push_event () +
+GstFlowReturn + +gst_pad_push_list () +
+GstFlowReturn + +gst_pad_pull_range () +
+gboolean + +gst_pad_activate_mode () +
+gboolean + +gst_pad_send_event () +
+gboolean + +gst_pad_event_default () +
+gboolean + +gst_pad_query () +
+gboolean + +gst_pad_peer_query () +
+gboolean + +gst_pad_query_default () +
+gboolean + +gst_pad_query_position () +
+gboolean + +gst_pad_query_duration () +
+gboolean + +gst_pad_query_convert () +
+gboolean + +gst_pad_query_accept_caps () +
+GstCaps * + +gst_pad_query_caps () +
+gboolean + +gst_pad_peer_query_position () +
+gboolean + +gst_pad_peer_query_duration () +
+gboolean + +gst_pad_peer_query_convert () +
+gboolean + +gst_pad_peer_query_accept_caps () +
+GstCaps * + +gst_pad_peer_query_caps () +
#define +gst_pad_set_query_function() +
+void + +gst_pad_set_query_function_full () +
+gboolean + +(*GstPadQueryFunction) () +
#define +gst_pad_set_iterate_internal_links_function() +
+void + +gst_pad_set_iterate_internal_links_function_full () +
+GstIterator * + +(*GstPadIterIntLinkFunction) () +
+GstIterator * + +gst_pad_iterate_internal_links () +
+GstIterator * + +gst_pad_iterate_internal_links_default () +
+void + +gst_pad_set_element_private () +
+gpointer + +gst_pad_get_element_private () +
+gchar * + +gst_pad_create_stream_id () +
+gchar * + +gst_pad_create_stream_id_printf () +
+gchar * + +gst_pad_create_stream_id_printf_valist () +
+gchar * + +gst_pad_get_stream_id () +
+GstStream * + +gst_pad_get_stream () +
+gboolean + +(*GstPadForwardFunction) () +
+gboolean + +gst_pad_forward () +
+GstFlowReturn + +gst_pad_chain () +
+GstFlowReturn + +gst_pad_chain_list () +
+gboolean + +gst_pad_start_task () +
+gboolean + +gst_pad_pause_task () +
+gboolean + +gst_pad_stop_task () +
+GstTaskState + +gst_pad_get_task_state () +
+gboolean + +gst_pad_set_active () +
#define +GST_PAD_GET_STREAM_LOCK() +
#define +GST_PAD_STREAM_LOCK() +
#define +GST_PAD_STREAM_TRYLOCK() +
#define +GST_PAD_STREAM_UNLOCK() +
#define +GST_PAD_NAME() +
#define +GST_PAD_PARENT() +
#define +GST_PAD_ELEMENT_PRIVATE() +
#define +GST_PAD_PAD_TEMPLATE() +
#define +GST_PAD_DIRECTION() +
#define +GST_PAD_LAST_FLOW_RETURN() +
#define +GST_PAD_TASK() +
#define +GST_PAD_MODE() +
#define +GST_PAD_ACTIVATEFUNC() +
#define +GST_PAD_ACTIVATEMODEFUNC() +
#define +GST_PAD_CHAINFUNC() +
#define +GST_PAD_CHAINLISTFUNC() +
#define +GST_PAD_EVENTFUNC() +
#define +GST_PAD_EVENTFULLFUNC() +
#define +GST_PAD_GETRANGEFUNC() +
#define +GST_PAD_QUERYFUNC() +
#define +GST_PAD_ITERINTLINKFUNC() +
#define +GST_PAD_PEER() +
#define +GST_PAD_LINKFUNC() +
#define +GST_PAD_UNLINKFUNC() +
#define +GST_PAD_IS_LINKED() +
#define +GST_PAD_IS_SRC() +
#define +GST_PAD_IS_SINK() +
#define +GST_PAD_IS_ACTIVE() +
#define +GST_PAD_IS_BLOCKED() +
#define +GST_PAD_IS_BLOCKING() +
#define +GST_PAD_IS_FLUSHING() +
#define +GST_PAD_SET_FLUSHING() +
#define +GST_PAD_UNSET_FLUSHING() +
#define +GST_PAD_IS_EOS() +
#define +GST_PAD_NEEDS_RECONFIGURE() +
#define +GST_PAD_HAS_PENDING_EVENTS() +
#define +GST_PAD_IS_FIXED_CAPS() +
#define +GST_PAD_NEEDS_PARENT() +
#define +GST_PAD_IS_PROXY_CAPS() +
#define +GST_PAD_SET_PROXY_CAPS() +
#define +GST_PAD_UNSET_PROXY_CAPS() +
#define +GST_PAD_IS_PROXY_ALLOCATION() +
#define +GST_PAD_SET_PROXY_ALLOCATION() +
#define +GST_PAD_UNSET_PROXY_ALLOCATION() +
#define +GST_PAD_SET_PROXY_SCHEDULING() +
#define +GST_PAD_UNSET_PROXY_SCHEDULING() +
#define +GST_PAD_IS_PROXY_SCHEDULING() +
#define +GST_PAD_IS_ACCEPT_INTERSECT() +
#define +GST_PAD_SET_ACCEPT_INTERSECT() +
#define +GST_PAD_UNSET_ACCEPT_INTERSECT() +
#define +GST_PAD_IS_ACCEPT_TEMPLATE() +
#define +GST_PAD_SET_ACCEPT_TEMPLATE() +
#define +GST_PAD_UNSET_ACCEPT_TEMPLATE() +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+GstCaps *capsRead
GstPadDirectiondirectionRead / Write / Construct Only
gint64offsetRead / Write
+GstPadTemplate *templateRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidlinkedRun Last
voidunlinkedRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstPad
enumGstPadDirection
enumGstPadFlags
enumGstPadLinkReturn
enumGstPadLinkCheck
enumGstFlowReturn
enumGstPadMode
enumGstPadProbeReturn
enumGstPadProbeType
structGstPadProbeInfo
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPad
+                ╰── GstProxyPad
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstElement is linked to other elements via "pads", which are extremely +light-weight generic link points.

+

Pads have a GstPadDirection, source pads produce data, sink pads consume +data.

+

Pads are typically created from a GstPadTemplate with +gst_pad_new_from_template() and are then added to a GstElement. This usually +happens when the element is created but it can also happen dynamically based +on the data that the element is processing or based on the pads that the +application requests.

+

Pads without pad templates can be created with gst_pad_new(), +which takes a direction and a name as an argument. If the name is NULL, +then a guaranteed unique name will be assigned to it.

+

A GstElement creating a pad will typically use the various +gst_pad_set_*_function() calls to register callbacks for events, queries or +dataflow on the pads.

+

gst_pad_get_parent() will retrieve the GstElement that owns the pad.

+

After two pads are retrieved from an element by gst_element_get_static_pad(), +the pads can be linked with gst_pad_link(). (For quick links, +you can also use gst_element_link(), which will make the obvious +link for you if it's straightforward.). Pads can be unlinked again with +gst_pad_unlink(). gst_pad_get_peer() can be used to check what the pad is +linked to.

+

Before dataflow is possible on the pads, they need to be activated with +gst_pad_set_active().

+

gst_pad_query() and gst_pad_peer_query() can be used to query various +properties of the pad and the stream.

+

To send a GstEvent on a pad, use gst_pad_send_event() and +gst_pad_push_event(). Some events will be sticky on the pad, meaning that +after they pass on the pad they can be queried later with +gst_pad_get_sticky_event() and gst_pad_sticky_events_foreach(). +gst_pad_get_current_caps() and gst_pad_has_current_caps() are convenience +functions to query the current sticky CAPS event on a pad.

+

GstElements will use gst_pad_push() and gst_pad_pull_range() to push out +or pull in a buffer.

+

The dataflow, events and queries that happen on a pad can be monitored with +probes that can be installed with gst_pad_add_probe(). gst_pad_is_blocked() +can be used to check if a block probe is installed on the pad. +gst_pad_is_blocking() checks if the blocking probe is currently blocking the +pad. gst_pad_remove_probe() is used to remove a previously installed probe +and unblock blocking probes if any.

+

Pad have an offset that can be retrieved with gst_pad_get_offset(). This +offset will be applied to the running_time of all data passing over the pad. +gst_pad_set_offset() can be used to change the offset.

+

Convenience functions exist to start, pause and stop the task on a pad with +gst_pad_start_task(), gst_pad_pause_task() and gst_pad_stop_task() +respectively.

+
+
+

Functions

+
+

gst_pad_link_get_name ()

+
const gchar *
+gst_pad_link_get_name (GstPadLinkReturn ret);
+

Gets a string representing the given pad-link return.

+
+

Parameters

+
+++++ + + + + + +

ret

a GstPadLinkReturn to get the name of.

 
+
+
+

Returns

+

a static string with the name of the pad-link return.

+
+

Since: 1.4

+
+
+
+

GST_PAD_LINK_FAILED()

+
#define GST_PAD_LINK_FAILED(ret) ((ret) < GST_PAD_LINK_OK)
+
+

Macro to test if the given GstPadLinkReturn value indicates a failed +link step.

+
+

Parameters

+
+++++ + + + + + +

ret

the GstPadLinkReturn value

 
+
+
+
+
+

GST_PAD_LINK_SUCCESSFUL()

+
#define GST_PAD_LINK_SUCCESSFUL(ret) ((ret) >= GST_PAD_LINK_OK)
+
+

Macro to test if the given GstPadLinkReturn value indicates a successful +link step.

+
+

Parameters

+
+++++ + + + + + +

ret

the GstPadLinkReturn value

 
+
+
+
+
+

gst_flow_get_name ()

+
const gchar *
+gst_flow_get_name (GstFlowReturn ret);
+

Gets a string representing the given flow return.

+
+

Parameters

+
+++++ + + + + + +

ret

a GstFlowReturn to get the name of.

 
+
+
+

Returns

+

a static string with the name of the flow return.

+
+
+
+
+

gst_flow_to_quark ()

+
GQuark
+gst_flow_to_quark (GstFlowReturn ret);
+

Get the unique quark for the given GstFlowReturn.

+
+

Parameters

+
+++++ + + + + + +

ret

a GstFlowReturn to get the quark of.

 
+
+
+

Returns

+

the quark associated with the flow return or 0 if an +invalid return was specified.

+
+
+
+
+

gst_pad_mode_get_name ()

+
const gchar *
+gst_pad_mode_get_name (GstPadMode mode);
+

Return the name of a pad mode, for use in debug messages mostly.

+
+

Parameters

+
+++++ + + + + + +

mode

the pad mode

 
+
+
+

Returns

+

short mnemonic for pad mode mode +

+
+
+
+
+

gst_pad_store_sticky_event ()

+
GstFlowReturn
+gst_pad_store_sticky_event (GstPad *pad,
+                            GstEvent *event);
+

Store the sticky event + on pad +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad

 

event

a GstEvent.

[transfer none]
+
+
+

Returns

+

GST_FLOW_OK on success, GST_FLOW_FLUSHING when the pad +was flushing or GST_FLOW_EOS when the pad was EOS.

+
+

Since: 1.2

+
+
+
+

gst_pad_get_name()

+
#define gst_pad_get_name(pad) gst_object_get_name (GST_OBJECT_CAST (pad))
+
+

Get a copy of the name of the pad. g_free() after usage.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pad

the pad to get the name from

 
+
+
+
+
+

gst_pad_get_direction ()

+
GstPadDirection
+gst_pad_get_direction (GstPad *pad);
+

Gets the direction of the pad. The direction of the pad is +decided at construction time so this function does not take +the LOCK.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad to get the direction of.

 
+
+
+

Returns

+

the GstPadDirection of the pad.

+

MT safe.

+
+
+
+
+

gst_pad_get_parent()

+
#define gst_pad_get_parent(pad) gst_object_get_parent (GST_OBJECT_CAST (pad))
+
+

Get the parent of pad +. This function increases the refcount +of the parent object so you should gst_object_unref() it after usage. +Can return NULL if the pad did not have a parent.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pad

the pad to get the parent of

 
+
+
+

Returns

+

the parent.

+

[nullable]

+
+
+
+
+

gst_pad_get_parent_element ()

+
GstElement *
+gst_pad_get_parent_element (GstPad *pad);
+

Gets the parent of pad +, cast to a GstElement. If a pad + has no parent or +its parent is not an element, return NULL.

+
+

Parameters

+
+++++ + + + + + +

pad

a pad

 
+
+
+

Returns

+

the parent of the pad. The +caller has a reference on the parent, so unref when you're finished +with it.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_get_pad_template ()

+
GstPadTemplate *
+gst_pad_get_pad_template (GstPad *pad);
+

Gets the template for pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad.

 
+
+
+

Returns

+

the GstPadTemplate from which +this pad was instantiated, or NULL if this pad has no +template. Unref after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_link ()

+
GstPadLinkReturn
+gst_pad_link (GstPad *srcpad,
+              GstPad *sinkpad);
+

Links the source pad and the sink pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

srcpad

the source GstPad to link.

 

sinkpad

the sink GstPad to link.

 
+
+
+

Returns

+

A result code indicating if the connection worked or +what went wrong.

+

MT Safe.

+
+
+
+
+

gst_pad_link_full ()

+
GstPadLinkReturn
+gst_pad_link_full (GstPad *srcpad,
+                   GstPad *sinkpad,
+                   GstPadLinkCheck flags);
+

Links the source pad and the sink pad.

+

This variant of gst_pad_link provides a more granular control on the +checks being done when linking. While providing some considerable speedups +the caller of this method must be aware that wrong usage of those flags +can cause severe issues. Refer to the documentation of GstPadLinkCheck +for more information.

+

MT Safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

srcpad

the source GstPad to link.

 

sinkpad

the sink GstPad to link.

 

flags

the checks to validate when linking

 
+
+
+

Returns

+

A result code indicating if the connection worked or +what went wrong.

+
+
+
+
+

gst_pad_link_maybe_ghosting ()

+
gboolean
+gst_pad_link_maybe_ghosting (GstPad *src,
+                             GstPad *sink);
+

Links src + to sink +, creating any GstGhostPad's in between as necessary.

+

This is a convenience function to save having to create and add intermediate +GstGhostPad's as required for linking across GstBin boundaries.

+

If src + or sink + pads don't have parent elements or do not share a common +ancestor, the link will fail.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

a GstPad

 

sink

a GstPad

 
+
+
+

Returns

+

whether the link succeeded.

+
+

Since: 1.10

+
+
+
+

gst_pad_link_maybe_ghosting_full ()

+
gboolean
+gst_pad_link_maybe_ghosting_full (GstPad *src,
+                                  GstPad *sink,
+                                  GstPadLinkCheck flags);
+

Links src + to sink +, creating any GstGhostPad's in between as necessary.

+

This is a convenience function to save having to create and add intermediate +GstGhostPad's as required for linking across GstBin boundaries.

+

If src + or sink + pads don't have parent elements or do not share a common +ancestor, the link will fail.

+

Calling gst_pad_link_maybe_ghosting_full() with +flags + == GST_PAD_LINK_CHECK_DEFAULT is the recommended way of linking +pads with safety checks applied.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

a GstPad

 

sink

a GstPad

 

flags

some GstPadLinkCheck flags

 
+
+
+

Returns

+

whether the link succeeded.

+
+

Since: 1.10

+
+
+
+

gst_pad_unlink ()

+
gboolean
+gst_pad_unlink (GstPad *srcpad,
+                GstPad *sinkpad);
+

Unlinks the source pad from the sink pad. Will emit the “unlinked” +signal on both pads.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

srcpad

the source GstPad to unlink.

 

sinkpad

the sink GstPad to unlink.

 
+
+
+

Returns

+

TRUE if the pads were unlinked. This function returns FALSE if +the pads were not linked together.

+

MT safe.

+
+
+
+
+

gst_pad_is_linked ()

+
gboolean
+gst_pad_is_linked (GstPad *pad);
+

Checks if a pad + is linked to another pad or not.

+
+

Parameters

+
+++++ + + + + + +

pad

pad to check

 
+
+
+

Returns

+

TRUE if the pad is linked, FALSE otherwise.

+

MT safe.

+
+
+
+
+

gst_pad_can_link ()

+
gboolean
+gst_pad_can_link (GstPad *srcpad,
+                  GstPad *sinkpad);
+

Checks if the source pad and the sink pad are compatible so they can be +linked.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

srcpad

the source GstPad.

 

sinkpad

the sink GstPad.

 
+
+
+

Returns

+

TRUE if the pads can be linked.

+
+
+
+
+

gst_pad_get_allowed_caps ()

+
GstCaps *
+gst_pad_get_allowed_caps (GstPad *pad);
+

Gets the capabilities of the allowed media types that can flow through +pad + and its peer.

+

The allowed capabilities is calculated as the intersection of the results of +calling gst_pad_query_caps() on pad + and its peer. The caller owns a reference +on the resulting caps.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad.

 
+
+
+

Returns

+

the allowed GstCaps of the +pad link. Unref the caps when you no longer need it. This +function returns NULL when pad +has no peer.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_get_current_caps ()

+
GstCaps *
+gst_pad_get_current_caps (GstPad *pad);
+

Gets the capabilities currently configured on pad + with the last +GST_EVENT_CAPS event.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad to get the current capabilities of.

 
+
+
+

Returns

+

the current caps of the pad with +incremented ref-count or NULL when pad has no caps. Unref after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_get_pad_template_caps ()

+
GstCaps *
+gst_pad_get_pad_template_caps (GstPad *pad);
+

Gets the capabilities for pad +'s template.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad to get the template capabilities from.

 
+
+
+

Returns

+

the GstCaps of this pad template. +Unref after usage.

+

[transfer full]

+
+
+
+
+

gst_pad_get_peer ()

+
GstPad *
+gst_pad_get_peer (GstPad *pad);
+

Gets the peer of pad +. This function refs the peer pad so +you need to unref it after use.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad to get the peer of.

 
+
+
+

Returns

+

the peer GstPad. Unref after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_use_fixed_caps ()

+
void
+gst_pad_use_fixed_caps (GstPad *pad);
+

A helper function you can use that sets the FIXED_CAPS flag +This way the default CAPS query will always return the negotiated caps +or in case the pad is not negotiated, the padtemplate caps.

+

The negotiated caps are the caps of the last CAPS event that passed on the +pad. Use this function on a pad that, once it negotiated to a CAPS, cannot +be renegotiated to something else.

+
+

Parameters

+
+++++ + + + + + +

pad

the pad to use

 
+
+
+
+
+

gst_pad_has_current_caps ()

+
gboolean
+gst_pad_has_current_caps (GstPad *pad);
+

Check if pad + has caps set on it with a GST_EVENT_CAPS event.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad to check

 
+
+
+

Returns

+

TRUE when pad +has caps associated with it.

+
+
+
+
+

gst_pad_get_sticky_event ()

+
GstEvent *
+gst_pad_get_sticky_event (GstPad *pad,
+                          GstEventType event_type,
+                          guint idx);
+

Returns a new reference of the sticky event of type event_type + +from the event.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad to get the event from.

 

event_type

the GstEventType that should be retrieved.

 

idx

the index of the event

 
+
+
+

Returns

+

a GstEvent of type +event_type +or NULL when no event of event_type +was on +pad +. Unref after usage.

+

[transfer full][nullable]

+
+
+
+
+

GstPadStickyEventsForeachFunction ()

+
gboolean
+(*GstPadStickyEventsForeachFunction) (GstPad *pad,
+                                      GstEvent **event,
+                                      gpointer user_data);
+

Callback used by gst_pad_sticky_events_foreach().

+

When this function returns TRUE, the next event will be +returned. When FALSE is returned, gst_pad_sticky_events_foreach() will return.

+

When event + is set to NULL, the item will be removed from the list of sticky events. +event + can be replaced by assigning a new reference to it. +This function is responsible for unreffing the old event when +removing or modifying.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad.

 

event

a sticky GstEvent.

[allow-none]

user_data

the gpointer to optional user data.

 
+
+
+

Returns

+

TRUE if the iteration should continue

+
+
+
+
+

gst_pad_sticky_events_foreach ()

+
void
+gst_pad_sticky_events_foreach (GstPad *pad,
+                               GstPadStickyEventsForeachFunction foreach_func,
+                               gpointer user_data);
+

Iterates all sticky events on pad + and calls foreach_func + for every +event. If foreach_func + returns FALSE the iteration is immediately stopped.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad that should be used for iteration.

 

foreach_func

the GstPadStickyEventsForeachFunction that +should be called for every event.

[scope call]

user_data

the optional user data.

[closure]
+
+
+
+
+

gst_pad_is_active ()

+
gboolean
+gst_pad_is_active (GstPad *pad);
+

Query if a pad is active

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to query

 
+
+
+

Returns

+

TRUE if the pad is active.

+

MT safe.

+
+
+
+
+

gst_pad_get_last_flow_return ()

+
GstFlowReturn
+gst_pad_get_last_flow_return (GstPad *pad);
+

Gets the GstFlowReturn return from the last data passed by this pad.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad

 
+
+

Since: 1.4

+
+
+
+

GST_PAD_PROBE_INFO_TYPE()

+
#define GST_PAD_PROBE_INFO_TYPE(d)         ((d)->type)
+
+
+
+
+

GST_PAD_PROBE_INFO_ID()

+
#define GST_PAD_PROBE_INFO_ID(d)           ((d)->id)
+
+
+
+
+

GST_PAD_PROBE_INFO_DATA()

+
#define GST_PAD_PROBE_INFO_DATA(d)         ((d)->data)
+
+
+
+
+

GST_PAD_PROBE_INFO_BUFFER()

+
#define GST_PAD_PROBE_INFO_BUFFER(d)       GST_BUFFER_CAST(GST_PAD_PROBE_INFO_DATA(d))
+
+
+
+
+

GST_PAD_PROBE_INFO_BUFFER_LIST()

+
#define GST_PAD_PROBE_INFO_BUFFER_LIST(d)  GST_BUFFER_LIST_CAST(GST_PAD_PROBE_INFO_DATA(d))
+
+
+
+
+

GST_PAD_PROBE_INFO_EVENT()

+
#define GST_PAD_PROBE_INFO_EVENT(d)        GST_EVENT_CAST(GST_PAD_PROBE_INFO_DATA(d))
+
+
+
+
+

GST_PAD_PROBE_INFO_QUERY()

+
#define GST_PAD_PROBE_INFO_QUERY(d)        GST_QUERY_CAST(GST_PAD_PROBE_INFO_DATA(d))
+
+
+
+
+

gst_pad_probe_info_get_buffer ()

+
GstBuffer *
+gst_pad_probe_info_get_buffer (GstPadProbeInfo *info);
+
+

Parameters

+
+++++ + + + + + +

info

a GstPadProbeInfo

 
+
+
+

Returns

+

The GstBuffer from the probe.

+

[transfer none][nullable]

+
+
+
+
+

gst_pad_probe_info_get_buffer_list ()

+
GstBufferList *
+gst_pad_probe_info_get_buffer_list (GstPadProbeInfo *info);
+
+

Parameters

+
+++++ + + + + + +

info

a GstPadProbeInfo

 
+
+
+

Returns

+

The GstBufferList from the probe.

+

[transfer none][nullable]

+
+
+
+
+

gst_pad_probe_info_get_event ()

+
GstEvent *
+gst_pad_probe_info_get_event (GstPadProbeInfo *info);
+
+

Parameters

+
+++++ + + + + + +

info

a GstPadProbeInfo

 
+
+
+

Returns

+

The GstEvent from the probe.

+

[transfer none][nullable]

+
+
+
+
+

gst_pad_probe_info_get_query ()

+
GstQuery *
+gst_pad_probe_info_get_query (GstPadProbeInfo *info);
+
+

Parameters

+
+++++ + + + + + +

info

a GstPadProbeInfo

 
+
+
+

Returns

+

The GstQuery from the probe.

+

[transfer none][nullable]

+
+
+
+
+

GST_PAD_PROBE_INFO_OFFSET()

+
#define GST_PAD_PROBE_INFO_OFFSET(d)       ((d)->offset)
+
+
+
+
+

GST_PAD_PROBE_INFO_SIZE()

+
#define GST_PAD_PROBE_INFO_SIZE(d)         ((d)->size)
+
+
+
+
+

GST_PAD_PROBE_INFO_FLOW_RETURN()

+
#define GST_PAD_PROBE_INFO_FLOW_RETURN(d)  ((d)->ABI.abi.flow_ret)
+
+
+
+
+

GstPadProbeCallback ()

+
GstPadProbeReturn
+(*GstPadProbeCallback) (GstPad *pad,
+                        GstPadProbeInfo *info,
+                        gpointer user_data);
+

Callback used by gst_pad_add_probe(). Gets called to notify about the current +blocking type.

+

The callback is allowed to modify the data pointer in info +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad that is blocked

 

info

GstPadProbeInfo

 

user_data

the gpointer to optional user data.

 
+
+
+

Returns

+

a GstPadProbeReturn

+
+
+
+
+

gst_pad_add_probe ()

+
gulong
+gst_pad_add_probe (GstPad *pad,
+                   GstPadProbeType mask,
+                   GstPadProbeCallback callback,
+                   gpointer user_data,
+                   GDestroyNotify destroy_data);
+

Be notified of different states of pads. The provided callback is called for +every state that matches mask +.

+

Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are +called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only +exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called +immediately if the pad is already idle while calling gst_pad_add_probe(). +In each of the groups, probes are called in the order in which they were +added.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pad

the GstPad to add the probe to

 

mask

the probe mask

 

callback

GstPadProbeCallback that will be called with notifications of +the pad state

 

user_data

user data passed to the callback.

[closure]

destroy_data

GDestroyNotify for user_data

 
+
+
+

Returns

+

an id or 0 if no probe is pending. The id can be used to remove the +probe with gst_pad_remove_probe(). When using GST_PAD_PROBE_TYPE_IDLE it can +happen that the probe can be run immediately and if the probe returns +GST_PAD_PROBE_REMOVE this functions returns 0.

+

MT safe.

+
+
+
+
+

gst_pad_remove_probe ()

+
void
+gst_pad_remove_probe (GstPad *pad,
+                      gulong id);
+

Remove the probe with id + from pad +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad with the probe

 

id

the probe id to remove

 
+
+
+
+
+

gst_pad_is_blocked ()

+
gboolean
+gst_pad_is_blocked (GstPad *pad);
+

Checks if the pad is blocked or not. This function returns the +last requested state of the pad. It is not certain that the pad +is actually blocking at this point (see gst_pad_is_blocking()).

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to query

 
+
+
+

Returns

+

TRUE if the pad is blocked.

+

MT safe.

+
+
+
+
+

gst_pad_is_blocking ()

+
gboolean
+gst_pad_is_blocking (GstPad *pad);
+

Checks if the pad is blocking or not. This is a guaranteed state +of whether the pad is actually blocking on a GstBuffer or a GstEvent.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to query

 
+
+
+

Returns

+

TRUE if the pad is blocking.

+

MT safe.

+
+
+
+
+

gst_pad_get_offset ()

+
gint64
+gst_pad_get_offset (GstPad *pad);
+

Get the offset applied to the running time of pad +. pad + has to be a source +pad.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+

Returns

+

the offset.

+
+
+
+
+

gst_pad_set_offset ()

+
void
+gst_pad_set_offset (GstPad *pad,
+                    gint64 offset);
+

Set the offset that will be applied to the running time of pad +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad

 

offset

the offset

 
+
+
+
+
+

gst_pad_new ()

+
GstPad *
+gst_pad_new (const gchar *name,
+             GstPadDirection direction);
+

Creates a new pad with the given name in the given direction. +If name is NULL, a guaranteed unique name (across all pads) +will be assigned. +This function makes a copy of the name so you can safely free the name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

the name of the new pad.

[allow-none]

direction

the GstPadDirection of the pad.

 
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

MT safe.

+

[transfer floating][nullable]

+
+
+
+
+

gst_pad_new_from_template ()

+
GstPad *
+gst_pad_new_from_template (GstPadTemplate *templ,
+                           const gchar *name);
+

Creates a new pad with the given name from the given template. +If name is NULL, a guaranteed unique name (across all pads) +will be assigned. +This function makes a copy of the name so you can safely free the name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

templ

the pad template to use

 

name

the name of the pad.

[allow-none]
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_pad_new_from_static_template ()

+
GstPad *
+gst_pad_new_from_static_template (GstStaticPadTemplate *templ,
+                                  const gchar *name);
+

Creates a new pad with the given name from the given static template. +If name is NULL, a guaranteed unique name (across all pads) +will be assigned. +This function makes a copy of the name so you can safely free the name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

templ

the GstStaticPadTemplate to use

 

name

the name of the pad

 
+
+
+

Returns

+

a new GstPad, or NULL in +case of an error.

+

[transfer floating][nullable]

+
+
+
+
+

gst_pad_set_chain_function()

+
#define gst_pad_set_chain_function(p,f)         gst_pad_set_chain_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_chain_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a sink GstPad.

 

f

the GstPadChainFunction to set.

 
+
+
+
+
+

gst_pad_set_chain_function_full ()

+
void
+gst_pad_set_chain_function_full (GstPad *pad,
+                                 GstPadChainFunction chain,
+                                 gpointer user_data,
+                                 GDestroyNotify notify);
+

Sets the given chain function for the pad. The chain function is called to +process a GstBuffer input buffer. see GstPadChainFunction for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a sink GstPad.

 

chain

the GstPadChainFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when chain +will not be used anymore.

 
+
+
+
+
+

GstPadChainFunction ()

+
GstFlowReturn
+(*GstPadChainFunction) (GstPad *pad,
+                        GstObject *parent,
+                        GstBuffer *buffer);
+

A function that will be called on sinkpads when chaining buffers. +The function typically processes the data contained in the buffer and +either consumes the data or passes it on to the internally linked pad(s).

+

The implementer of this function receives a refcount to buffer + and should +gst_buffer_unref() when the buffer is no longer needed.

+

When a chain function detects an error in the data stream, it must post an +error on the bus and return an appropriate GstFlowReturn value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the sink GstPad that performed the chain.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

buffer

the GstBuffer that is chained, not NULL.

[transfer full]
+
+
+

Returns

+

GST_FLOW_OK for success

+
+
+
+
+

gst_pad_set_chain_list_function()

+
#define gst_pad_set_chain_list_function(p,f)    gst_pad_set_chain_list_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_chain_list_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a sink GstPad.

 

f

the GstPadChainListFunction to set.

 
+
+
+
+
+

gst_pad_set_chain_list_function_full ()

+
void
+gst_pad_set_chain_list_function_full (GstPad *pad,
+                                      GstPadChainListFunction chainlist,
+                                      gpointer user_data,
+                                      GDestroyNotify notify);
+

Sets the given chain list function for the pad. The chainlist function is +called to process a GstBufferList input buffer list. See +GstPadChainListFunction for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a sink GstPad.

 

chainlist

the GstPadChainListFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when chainlist +will not be used anymore.

 
+
+
+
+
+

GstPadChainListFunction ()

+
GstFlowReturn
+(*GstPadChainListFunction) (GstPad *pad,
+                            GstObject *parent,
+                            GstBufferList *list);
+

A function that will be called on sinkpads when chaining buffer lists. +The function typically processes the data contained in the buffer list and +either consumes the data or passes it on to the internally linked pad(s).

+

The implementer of this function receives a refcount to list + and +should gst_buffer_list_unref() when the list is no longer needed.

+

When a chainlist function detects an error in the data stream, it must +post an error on the bus and return an appropriate GstFlowReturn value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the sink GstPad that performed the chain.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

list

the GstBufferList that is chained, not NULL.

[transfer full]
+
+
+

Returns

+

GST_FLOW_OK for success

+
+
+
+
+

gst_pad_get_range ()

+
GstFlowReturn
+gst_pad_get_range (GstPad *pad,
+                   guint64 offset,
+                   guint size,
+                   GstBuffer **buffer);
+

When pad + is flushing this function returns GST_FLOW_FLUSHING +immediately and buffer + is NULL.

+

Calls the getrange function of pad +, see GstPadGetRangeFunction for a +description of a getrange function. If pad + has no getrange function +installed (see gst_pad_set_getrange_function()) this function returns +GST_FLOW_NOT_SUPPORTED.

+

If buffer + points to a variable holding NULL, a valid new GstBuffer will be +placed in buffer + when this function returns GST_FLOW_OK. The new buffer +must be freed with gst_buffer_unref() after usage.

+

When buffer + points to a variable that points to a valid GstBuffer, the +buffer will be filled with the result data when this function returns +GST_FLOW_OK. If the provided buffer is larger than size +, only +size + bytes will be filled in the result buffer and its size will be updated +accordingly.

+

Note that less than size + bytes can be returned in buffer + when, for example, +an EOS condition is near or when buffer + is not large enough to hold size + +bytes. The caller should check the result buffer size to get the result size.

+

When this function returns any other result value than GST_FLOW_OK, buffer + +will be unchanged.

+

This is a lowlevel function. Usually gst_pad_pull_range() is used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a src GstPad, returns GST_FLOW_ERROR if not.

 

offset

The start offset of the buffer

 

size

The length of the buffer

 

buffer

a pointer to hold the GstBuffer, +returns GST_FLOW_ERROR if NULL.

[out callee-allocates]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+

MT safe.

+
+
+
+
+

gst_pad_set_getrange_function()

+
#define gst_pad_set_getrange_function(p,f)      gst_pad_set_getrange_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_getrange_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a source GstPad.

 

f

the GstPadGetRangeFunction to set.

 
+
+
+
+
+

gst_pad_set_getrange_function_full ()

+
void
+gst_pad_set_getrange_function_full (GstPad *pad,
+                                    GstPadGetRangeFunction get,
+                                    gpointer user_data,
+                                    GDestroyNotify notify);
+

Sets the given getrange function for the pad. The getrange function is +called to produce a new GstBuffer to start the processing pipeline. see +GstPadGetRangeFunction for a description of the getrange function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a source GstPad.

 

get

the GstPadGetRangeFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when get +will not be used anymore.

 
+
+
+
+
+

GstPadGetRangeFunction ()

+
GstFlowReturn
+(*GstPadGetRangeFunction) (GstPad *pad,
+                           GstObject *parent,
+                           guint64 offset,
+                           guint length,
+                           GstBuffer **buffer);
+

This function will be called on source pads when a peer element +request a buffer at the specified offset + and length +. If this function +returns GST_FLOW_OK, the result buffer will be stored in buffer +. The +contents of buffer + is invalid for any other return value.

+

This function is installed on a source pad with +gst_pad_set_getrange_function() and can only be called on source pads after +they are successfully activated with gst_pad_activate_mode() with the +GST_PAD_MODE_PULL.

+

offset + and length + are always given in byte units. offset + must normally be a value +between 0 and the length in bytes of the data available on pad +. The +length (duration in bytes) can be retrieved with a GST_QUERY_DURATION or with a +GST_QUERY_SEEKING.

+

Any offset + larger or equal than the length will make the function return +GST_FLOW_EOS, which corresponds to EOS. In this case buffer + does not +contain a valid buffer.

+

The buffer size of buffer + will only be smaller than length + when offset + is +near the end of the stream. In all other cases, the size of buffer + must be +exactly the requested size.

+

It is allowed to call this function with a 0 length + and valid offset +, in +which case buffer + will contain a 0-sized buffer and the function returns +GST_FLOW_OK.

+

When this function is called with a -1 offset +, the sequentially next buffer +of length length + in the stream is returned.

+

When this function is called with a -1 length +, a buffer with a default +optimal length is returned in buffer +. The length might depend on the value +of offset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pad

the src GstPad to perform the getrange on.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

offset

the offset of the range

 

length

the length of the range

 

buffer

a memory location to hold the result buffer, cannot be NULL.

 
+
+
+

Returns

+

GST_FLOW_OK for success and a valid buffer in buffer +. Any other +return value leaves buffer +undefined.

+
+
+
+
+

gst_pad_set_event_function()

+
#define gst_pad_set_event_function(p,f)         gst_pad_set_event_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_event_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad of either direction.

 

f

the GstPadEventFunction to set.

 
+
+
+
+
+

gst_pad_set_event_function_full ()

+
void
+gst_pad_set_event_function_full (GstPad *pad,
+                                 GstPadEventFunction event,
+                                 gpointer user_data,
+                                 GDestroyNotify notify);
+

Sets the given event handler for the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad of either direction.

 

event

the GstPadEventFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when event +will not be used anymore.

 
+
+
+
+
+

GstPadEventFunction ()

+
gboolean
+(*GstPadEventFunction) (GstPad *pad,
+                        GstObject *parent,
+                        GstEvent *event);
+

Function signature to handle an event for the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad to handle the event.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

event

the GstEvent to handle.

[transfer full]
+
+
+

Returns

+

TRUE if the pad could handle the event.

+
+
+
+
+

gst_pad_set_event_full_function()

+
#define gst_pad_set_event_full_function(p,f)    gst_pad_set_event_full_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_event_full_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad of either direction.

 

f

the GstPadEventFullFunction to set.

 
+
+
+
+
+

gst_pad_set_event_full_function_full ()

+
void
+gst_pad_set_event_full_function_full (GstPad *pad,
+                                      GstPadEventFullFunction event,
+                                      gpointer user_data,
+                                      GDestroyNotify notify);
+

Sets the given event handler for the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad of either direction.

 

event

the GstPadEventFullFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when event +will not be used anymore.

 
+
+

Since: 1.8

+
+
+
+

GstPadEventFullFunction ()

+
GstFlowReturn
+(*GstPadEventFullFunction) (GstPad *pad,
+                            GstObject *parent,
+                            GstEvent *event);
+

Function signature to handle an event for the pad.

+

This variant is for specific elements that will take into account the +last downstream flow return (from a pad push), in which case they can +return it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad to handle the event.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

event

the GstEvent to handle.

[transfer full]
+
+
+

Returns

+

GST_FLOW_OK if the event was handled properly, or any other +GstFlowReturn dependent on downstream state.

+
+

Since: 1.8

+
+
+
+

gst_pad_set_link_function()

+
#define gst_pad_set_link_function(p,f)          gst_pad_set_link_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_link_function_full() with NULL +for the user_data and notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad.

 

f

the GstPadLinkFunction to set.

 
+
+
+
+
+

gst_pad_set_link_function_full ()

+
void
+gst_pad_set_link_function_full (GstPad *pad,
+                                GstPadLinkFunction link,
+                                gpointer user_data,
+                                GDestroyNotify notify);
+

Sets the given link function for the pad. It will be called when +the pad is linked with another pad.

+

The return value GST_PAD_LINK_OK should be used when the connection can be +made.

+

The return value GST_PAD_LINK_REFUSED should be used when the connection +cannot be made for some reason.

+

If link + is installed on a source pad, it should call the GstPadLinkFunction +of the peer sink pad, if present.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad.

 

link

the GstPadLinkFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when link +will not be used anymore.

 
+
+
+
+
+

GstPadLinkFunction ()

+
GstPadLinkReturn
+(*GstPadLinkFunction) (GstPad *pad,
+                       GstObject *parent,
+                       GstPad *peer);
+

Function signature to handle a new link on the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad that is linked.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

peer

the peer GstPad of the link

 
+
+
+

Returns

+

the result of the link with the specified peer.

+
+
+
+
+

gst_pad_set_unlink_function()

+
#define gst_pad_set_unlink_function(p,f)        gst_pad_set_unlink_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_unlink_function_full() with NULL +for the user_data and notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad.

 

f

the GstPadUnlinkFunction to set.

 
+
+
+
+
+

gst_pad_set_unlink_function_full ()

+
void
+gst_pad_set_unlink_function_full (GstPad *pad,
+                                  GstPadUnlinkFunction unlink,
+                                  gpointer user_data,
+                                  GDestroyNotify notify);
+

Sets the given unlink function for the pad. It will be called +when the pad is unlinked.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad.

 

unlink

the GstPadUnlinkFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when unlink +will not be used anymore.

 
+
+
+
+
+

GstPadUnlinkFunction ()

+
void
+(*GstPadUnlinkFunction) (GstPad *pad,
+                         GstObject *parent);
+

Function signature to handle a unlinking the pad prom its peer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad that is linked.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]
+
+
+
+
+

gst_pad_proxy_query_caps ()

+
gboolean
+gst_pad_proxy_query_caps (GstPad *pad,
+                          GstQuery *query);
+

Calls gst_pad_query_caps() for all internally linked pads of pad + and returns +the intersection of the results.

+

This function is useful as a default caps query function for an element +that can handle any stream format, but requires all its pads to have +the same caps. Two such elements are tee and adder.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to proxy.

 

query

a CAPS GstQuery.

 
+
+
+

Returns

+

TRUE if query +could be executed

+
+
+
+
+

gst_pad_proxy_query_accept_caps ()

+
gboolean
+gst_pad_proxy_query_accept_caps (GstPad *pad,
+                                 GstQuery *query);
+

Checks if all internally linked pads of pad + accepts the caps in query + and +returns the intersection of the results.

+

This function is useful as a default accept caps query function for an element +that can handle any stream format, but requires caps that are acceptable for +all opposite pads.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to proxy.

 

query

an ACCEPT_CAPS GstQuery.

 
+
+
+

Returns

+

TRUE if query +could be executed

+
+
+
+
+

gst_pad_set_activate_function()

+
#define gst_pad_set_activate_function(p,f)      gst_pad_set_activate_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_activate_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad.

 

f

the GstPadActivateFunction to set.

 
+
+
+
+
+

gst_pad_set_activate_function_full ()

+
void
+gst_pad_set_activate_function_full (GstPad *pad,
+                                    GstPadActivateFunction activate,
+                                    gpointer user_data,
+                                    GDestroyNotify notify);
+

Sets the given activate function for pad +. The activate function will +dispatch to gst_pad_activate_mode() to perform the actual activation. +Only makes sense to set on sink pads.

+

Call this function if your sink pad can start a pull-based task.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad.

 

activate

the GstPadActivateFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when activate +will not be used anymore.

 
+
+
+
+
+

GstPadActivateFunction ()

+
gboolean
+(*GstPadActivateFunction) (GstPad *pad,
+                           GstObject *parent);
+

This function is called when the pad is activated during the element +READY to PAUSED state change. By default this function will call the +activate function that puts the pad in push mode but elements can +override this function to activate the pad in pull mode if they wish.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad

 

parent

the parent of pad +

 
+
+
+

Returns

+

TRUE if the pad could be activated.

+
+
+
+
+

gst_pad_set_activatemode_function()

+
#define gst_pad_set_activatemode_function(p,f)  gst_pad_set_activatemode_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_activatemode_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad.

 

f

the GstPadActivateModeFunction to set.

 
+
+
+
+
+

gst_pad_set_activatemode_function_full ()

+
void
+gst_pad_set_activatemode_function_full
+                               (GstPad *pad,
+                                GstPadActivateModeFunction activatemode,
+                                gpointer user_data,
+                                GDestroyNotify notify);
+

Sets the given activate_mode function for the pad. An activate_mode function +prepares the element for data passing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad.

 

activatemode

the GstPadActivateModeFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when activatemode +will not be used anymore.

 
+
+
+
+
+

GstPadActivateModeFunction ()

+
gboolean
+(*GstPadActivateModeFunction) (GstPad *pad,
+                               GstObject *parent,
+                               GstPadMode mode,
+                               gboolean active);
+

The prototype of the push and pull activate functions.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad

 

parent

the parent of pad +

 

mode

the requested activation mode of pad +

 

active

activate or deactivate the pad.

 
+
+
+

Returns

+

TRUE if the pad could be activated or deactivated.

+
+
+
+
+

gst_pad_needs_reconfigure ()

+
gboolean
+gst_pad_needs_reconfigure (GstPad *pad);
+

Check the GST_PAD_FLAG_NEED_RECONFIGURE flag on pad + and return TRUE +if the flag was set.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to check

 
+
+
+

Returns

+

TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag is set on pad +.

+
+
+
+
+

gst_pad_check_reconfigure ()

+
gboolean
+gst_pad_check_reconfigure (GstPad *pad);
+

Check and clear the GST_PAD_FLAG_NEED_RECONFIGURE flag on pad + and return TRUE +if the flag was set.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to check

 
+
+
+

Returns

+

TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag was set on pad +.

+
+
+
+
+

gst_pad_mark_reconfigure ()

+
void
+gst_pad_mark_reconfigure (GstPad *pad);
+

Mark a pad for needing reconfiguration. The next call to +gst_pad_check_reconfigure() will return TRUE after this call.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to mark

 
+
+
+
+
+

gst_pad_push ()

+
GstFlowReturn
+gst_pad_push (GstPad *pad,
+              GstBuffer *buffer);
+

Pushes a buffer to the peer of pad +.

+

This function will call installed block probes before triggering any +installed data probes.

+

The function proceeds calling gst_pad_chain() on the peer pad and returns +the value from that function. If pad + has no peer, GST_FLOW_NOT_LINKED will +be returned.

+

In all cases, success or failure, the caller loses its reference to buffer + +after calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a source GstPad, returns GST_FLOW_ERROR if not.

 

buffer

the GstBuffer to push returns GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the peer pad.

+

MT safe.

+
+
+
+
+

gst_pad_push_event ()

+
gboolean
+gst_pad_push_event (GstPad *pad,
+                    GstEvent *event);
+

Sends the event to the peer of the given pad. This function is +mainly used by elements to send events to their peer +elements.

+

This function takes ownership of the provided event so you should +gst_event_ref() it if you want to reuse the event after this call.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to push the event to.

 

event

the GstEvent to send to the pad.

[transfer full]
+
+
+

Returns

+

TRUE if the event was handled.

+

MT safe.

+
+
+
+
+

gst_pad_push_list ()

+
GstFlowReturn
+gst_pad_push_list (GstPad *pad,
+                   GstBufferList *list);
+

Pushes a buffer list to the peer of pad +.

+

This function will call installed block probes before triggering any +installed data probes.

+

The function proceeds calling the chain function on the peer pad and returns +the value from that function. If pad + has no peer, GST_FLOW_NOT_LINKED will +be returned. If the peer pad does not have any installed chainlist function +every group buffer of the list will be merged into a normal GstBuffer and +chained via gst_pad_chain().

+

In all cases, success or failure, the caller loses its reference to list + +after calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a source GstPad, returns GST_FLOW_ERROR if not.

 

list

the GstBufferList to push returns GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the peer pad.

+

MT safe.

+
+
+
+
+

gst_pad_pull_range ()

+
GstFlowReturn
+gst_pad_pull_range (GstPad *pad,
+                    guint64 offset,
+                    guint size,
+                    GstBuffer **buffer);
+

Pulls a buffer + from the peer pad or fills up a provided buffer.

+

This function will first trigger the pad block signal if it was +installed.

+

When pad + is not linked GST_FLOW_NOT_LINKED is returned else this +function returns the result of gst_pad_get_range() on the peer pad. +See gst_pad_get_range() for a list of return values and for the +semantics of the arguments of this function.

+

If buffer + points to a variable holding NULL, a valid new GstBuffer will be +placed in buffer + when this function returns GST_FLOW_OK. The new buffer +must be freed with gst_buffer_unref() after usage. When this function +returns any other result value, buffer + will still point to NULL.

+

When buffer + points to a variable that points to a valid GstBuffer, the +buffer will be filled with the result data when this function returns +GST_FLOW_OK. When this function returns any other result value, +buffer + will be unchanged. If the provided buffer is larger than size +, only +size + bytes will be filled in the result buffer and its size will be updated +accordingly.

+

Note that less than size + bytes can be returned in buffer + when, for example, +an EOS condition is near or when buffer + is not large enough to hold size + +bytes. The caller should check the result buffer size to get the result size.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a sink GstPad, returns GST_FLOW_ERROR if not.

 

offset

The start offset of the buffer

 

size

The length of the buffer

 

buffer

a pointer to hold the GstBuffer, returns +GST_FLOW_ERROR if NULL.

[out callee-allocates]
+
+
+

Returns

+

a GstFlowReturn from the peer pad.

+

MT safe.

+
+
+
+
+

gst_pad_activate_mode ()

+
gboolean
+gst_pad_activate_mode (GstPad *pad,
+                       GstPadMode mode,
+                       gboolean active);
+

Activates or deactivates the given pad in mode + via dispatching to the +pad's activatemodefunc. For use from within pad activation functions only.

+

If you don't know what this is, you probably don't want to call it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad to activate or deactivate.

 

mode

the requested activation mode

 

active

whether or not the pad should be active.

 
+
+
+

Returns

+

TRUE if the operation was successful.

+

MT safe.

+
+
+
+
+

gst_pad_send_event ()

+
gboolean
+gst_pad_send_event (GstPad *pad,
+                    GstEvent *event);
+

Sends the event to the pad. This function can be used +by applications to send events in the pipeline.

+

If pad + is a source pad, event + should be an upstream event. If pad + is a +sink pad, event + should be a downstream event. For example, you would not +send a GST_EVENT_EOS on a src pad; EOS events only propagate downstream. +Furthermore, some downstream events have to be serialized with data flow, +like EOS, while some can travel out-of-band, like GST_EVENT_FLUSH_START. If +the event needs to be serialized with data flow, this function will take the +pad's stream lock while calling its event function.

+

To find out whether an event type is upstream, downstream, or downstream and +serialized, see GstEventTypeFlags, gst_event_type_get_flags(), +GST_EVENT_IS_UPSTREAM, GST_EVENT_IS_DOWNSTREAM, and +GST_EVENT_IS_SERIALIZED. Note that in practice that an application or +plugin doesn't need to bother itself with this information; the core handles +all necessary locks and checks.

+

This function takes ownership of the provided event so you should +gst_event_ref() it if you want to reuse the event after this call.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to send the event to.

 

event

the GstEvent to send to the pad.

[transfer full]
+
+
+

Returns

+

TRUE if the event was handled.

+
+
+
+
+

gst_pad_event_default ()

+
gboolean
+gst_pad_event_default (GstPad *pad,
+                       GstObject *parent,
+                       GstEvent *event);
+

Invokes the default event handler for the given pad.

+

The EOS event will pause the task associated with pad + before it is forwarded +to all internally linked pads,

+

The event is sent to all pads internally linked to pad +. This function +takes ownership of event +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad to call the default event handler on.

 

parent

the parent of pad +or NULL.

[allow-none]

event

the GstEvent to handle.

[transfer full]
+
+
+

Returns

+

TRUE if the event was sent successfully.

+
+
+
+
+

gst_pad_query ()

+
gboolean
+gst_pad_query (GstPad *pad,
+               GstQuery *query);
+

Dispatches a query to a pad. The query should have been allocated by the +caller via one of the type-specific allocation functions. The element that +the pad belongs to is responsible for filling the query with an appropriate +response, which should then be parsed with a type-specific query parsing +function.

+

Again, the caller is responsible for both the allocation and deallocation of +the query structure.

+

Please also note that some queries might need a running pipeline to work.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to invoke the default query on.

 

query

the GstQuery to perform.

[transfer none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_peer_query ()

+
gboolean
+gst_pad_peer_query (GstPad *pad,
+                    GstQuery *query);
+

Performs gst_pad_query() on the peer of pad +.

+

The caller is responsible for both the allocation and deallocation of +the query structure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to invoke the peer query on.

 

query

the GstQuery to perform.

[transfer none]
+
+
+

Returns

+

TRUE if the query could be performed. This function returns FALSE +if pad +has no peer.

+
+
+
+
+

gst_pad_query_default ()

+
gboolean
+gst_pad_query_default (GstPad *pad,
+                       GstObject *parent,
+                       GstQuery *query);
+

Invokes the default query handler for the given pad. +The query is sent to all pads internally linked to pad +. Note that +if there are many possible sink pads that are internally linked to +pad +, only one will be sent the query. +Multi-sinkpad elements should implement custom query handlers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad to call the default query handler on.

 

parent

the parent of pad +or NULL.

[allow-none]

query

the GstQuery to handle.

[transfer none]
+
+
+

Returns

+

TRUE if the query was performed successfully.

+
+
+
+
+

gst_pad_query_position ()

+
gboolean
+gst_pad_query_position (GstPad *pad,
+                        GstFormat format,
+                        gint64 *cur);
+

Queries a pad for the stream position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad to invoke the position query on.

 

format

the GstFormat requested

 

cur

A location in which to store the current position, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_query_duration ()

+
gboolean
+gst_pad_query_duration (GstPad *pad,
+                        GstFormat format,
+                        gint64 *duration);
+

Queries a pad for the total stream duration.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad to invoke the duration query on.

 

format

the GstFormat requested

 

duration

a location in which to store the total +duration, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_query_convert ()

+
gboolean
+gst_pad_query_convert (GstPad *pad,
+                       GstFormat src_format,
+                       gint64 src_val,
+                       GstFormat dest_format,
+                       gint64 *dest_val);
+

Queries a pad to convert src_val + in src_format + to dest_format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad to invoke the convert query on.

 

src_format

a GstFormat to convert from.

 

src_val

a value to convert.

 

dest_format

the GstFormat to convert to.

 

dest_val

a pointer to the result.

[out]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_query_accept_caps ()

+
gboolean
+gst_pad_query_accept_caps (GstPad *pad,
+                           GstCaps *caps);
+

Check if the given pad accepts the caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to check

 

caps

a GstCaps to check on the pad

 
+
+
+

Returns

+

TRUE if the pad can accept the caps.

+
+
+
+
+

gst_pad_query_caps ()

+
GstCaps *
+gst_pad_query_caps (GstPad *pad,
+                    GstCaps *filter);
+

Gets the capabilities this pad can produce or consume. +Note that this method doesn't necessarily return the caps set by sending a +gst_event_new_caps() - use gst_pad_get_current_caps() for that instead. +gst_pad_query_caps returns all possible caps a pad can operate with, using +the pad's CAPS query function, If the query fails, this function will return +filter +, if not NULL, otherwise ANY.

+

When called on sinkpads filter + contains the caps that +upstream could produce in the order preferred by upstream. When +called on srcpads filter + contains the caps accepted by +downstream in the preferred order. filter + might be NULL but +if it is not NULL the returned caps will be a subset of filter +.

+

Note that this function does not return writable GstCaps, use +gst_caps_make_writable() before modifying the caps.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to get the capabilities of.

 

filter

suggested GstCaps, or NULL.

[allow-none]
+
+
+

Returns

+

the caps of the pad with incremented ref-count.

+

[transfer full]

+
+
+
+
+

gst_pad_peer_query_position ()

+
gboolean
+gst_pad_peer_query_position (GstPad *pad,
+                             GstFormat format,
+                             gint64 *cur);
+

Queries the peer of a given sink pad for the stream position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad on whose peer to invoke the position query on. +Must be a sink pad.

 

format

the GstFormat requested

 

cur

a location in which to store the current +position, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_peer_query_duration ()

+
gboolean
+gst_pad_peer_query_duration (GstPad *pad,
+                             GstFormat format,
+                             gint64 *duration);
+

Queries the peer pad of a given sink pad for the total stream duration.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad on whose peer pad to invoke the duration query on. +Must be a sink pad.

 

format

the GstFormat requested

 

duration

a location in which to store the total +duration, or NULL.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_peer_query_convert ()

+
gboolean
+gst_pad_peer_query_convert (GstPad *pad,
+                            GstFormat src_format,
+                            gint64 src_val,
+                            GstFormat dest_format,
+                            gint64 *dest_val);
+

Queries the peer pad of a given sink pad to convert src_val + in src_format + +to dest_format +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad, on whose peer pad to invoke the convert query on. +Must be a sink pad.

 

src_format

a GstFormat to convert from.

 

src_val

a value to convert.

 

dest_format

the GstFormat to convert to.

 

dest_val

a pointer to the result.

[out]
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_peer_query_accept_caps ()

+
gboolean
+gst_pad_peer_query_accept_caps (GstPad *pad,
+                                GstCaps *caps);
+

Check if the peer of pad + accepts caps +. If pad + has no peer, this function +returns TRUE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to check the peer of

 

caps

a GstCaps to check on the pad

 
+
+
+

Returns

+

TRUE if the peer of pad +can accept the caps or pad +has no peer.

+
+
+
+
+

gst_pad_peer_query_caps ()

+
GstCaps *
+gst_pad_peer_query_caps (GstPad *pad,
+                         GstCaps *filter);
+

Gets the capabilities of the peer connected to this pad. Similar to +gst_pad_query_caps().

+

When called on srcpads filter + contains the caps that +upstream could produce in the order preferred by upstream. When +called on sinkpads filter + contains the caps accepted by +downstream in the preferred order. filter + might be NULL but +if it is not NULL the returned caps will be a subset of filter +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a GstPad to get the capabilities of.

 

filter

a GstCaps filter, or NULL.

[allow-none]
+
+
+

Returns

+

the caps of the peer pad with incremented +ref-count. When there is no peer pad, this function returns filter +or, +when filter +is NULL, ANY caps.

+

[transfer full]

+
+
+
+
+

gst_pad_set_query_function()

+
#define gst_pad_set_query_function(p,f)   gst_pad_set_query_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_query_function_full() with NULL for the user_data and +notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad of either direction.

 

f

the GstPadQueryFunction to set.

 
+
+
+
+
+

gst_pad_set_query_function_full ()

+
void
+gst_pad_set_query_function_full (GstPad *pad,
+                                 GstPadQueryFunction query,
+                                 gpointer user_data,
+                                 GDestroyNotify notify);
+

Set the given query function for the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad of either direction.

 

query

the GstPadQueryFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when query +will not be used anymore.

 
+
+
+
+
+

GstPadQueryFunction ()

+
gboolean
+(*GstPadQueryFunction) (GstPad *pad,
+                        GstObject *parent,
+                        GstQuery *query);
+

The signature of the query function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the GstPad to query.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]

query

the GstQuery object to execute

 
+
+
+

Returns

+

TRUE if the query could be performed.

+
+
+
+
+

gst_pad_set_iterate_internal_links_function()

+
#define gst_pad_set_iterate_internal_links_function(p,f) gst_pad_set_iterate_internal_links_function_full((p),(f),NULL,NULL)
+
+

Calls gst_pad_set_iterate_internal_links_function_full() with NULL +for the user_data and notify.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p

a GstPad of either direction.

 

f

the GstPadIterIntLinkFunction to set.

 
+
+
+
+
+

gst_pad_set_iterate_internal_links_function_full ()

+
void
+gst_pad_set_iterate_internal_links_function_full
+                               (GstPad *pad,
+                                GstPadIterIntLinkFunction iterintlink,
+                                gpointer user_data,
+                                GDestroyNotify notify);
+

Sets the given internal link iterator function for the pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

a GstPad of either direction.

 

iterintlink

the GstPadIterIntLinkFunction to set.

 

user_data

user_data passed to notify +

 

notify

notify called when iterintlink +will not be used anymore.

 
+
+
+
+
+

GstPadIterIntLinkFunction ()

+
GstIterator *
+(*GstPadIterIntLinkFunction) (GstPad *pad,
+                              GstObject *parent);
+

The signature of the internal pad link iterator function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

The GstPad to query.

 

parent

the parent of pad +. If the GST_PAD_FLAG_NEED_PARENT +flag is set, parent +is guaranteed to be not-NULL and remain valid +during the execution of this function.

[allow-none]
+
+
+

Returns

+

a new GstIterator that will iterate over all pads that are +linked to the given pad on the inside of the parent element.

+

the caller must call gst_iterator_free() after usage.

+
+
+
+
+

gst_pad_iterate_internal_links ()

+
GstIterator *
+gst_pad_iterate_internal_links (GstPad *pad);
+

Gets an iterator for the pads to which the given pad is linked to inside +of the parent element.

+

Each GstPad element yielded by the iterator will have its refcount increased, +so unref after use.

+

Free-function: gst_iterator_free

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to get the internal links of.

 
+
+
+

Returns

+

a new GstIterator of GstPad +or NULL when the pad does not have an iterator function +configured. Use gst_iterator_free() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_pad_iterate_internal_links_default ()

+
GstIterator *
+gst_pad_iterate_internal_links_default
+                               (GstPad *pad,
+                                GstObject *parent);
+

Iterate the list of pads to which the given pad is linked to inside of +the parent element. +This is the default handler, and thus returns an iterator of all of the +pads inside the parent element with opposite direction.

+

The caller must free this iterator after use with gst_iterator_free().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad to get the internal links of.

 

parent

the parent of pad +or NULL.

[allow-none]
+
+
+

Returns

+

a GstIterator of GstPad, or NULL if pad +has no parent. Unref each returned pad with gst_object_unref().

+

[nullable]

+
+
+
+
+

gst_pad_set_element_private ()

+
void
+gst_pad_set_element_private (GstPad *pad,
+                             gpointer priv);
+

Set the given private data gpointer on the pad. +This function can only be used by the element that owns the pad. +No locking is performed in this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad to set the private data of.

 

priv

The private data to attach to the pad.

 
+
+
+
+
+

gst_pad_get_element_private ()

+
gpointer
+gst_pad_get_element_private (GstPad *pad);
+

Gets the private data of a pad. +No locking is performed in this function.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to get the private data of.

 
+
+
+

Returns

+

a gpointer to the private data.

+

[transfer none][nullable]

+
+
+
+
+

gst_pad_create_stream_id ()

+
gchar *
+gst_pad_create_stream_id (GstPad *pad,
+                          GstElement *parent,
+                          const gchar *stream_id);
+

Creates a stream-id for the source GstPad pad + by combining the +upstream information with the optional stream_id + of the stream +of pad +. pad + must have a parent GstElement and which must have zero +or one sinkpad. stream_id + can only be NULL if the parent element +of pad + has only a single source pad.

+

This function generates an unique stream-id by getting the upstream +stream-start event stream ID and appending stream_id + to it. If the +element has no sinkpad it will generate an upstream stream-id by +doing an URI query on the element and in the worst case just uses +a random number. Source elements that don't implement the URI +handler interface should ideally generate a unique, deterministic +stream-id manually instead.

+

Since stream IDs are sorted alphabetically, any numbers in the +stream ID should be printed with a fixed number of characters, +preceded by 0's, such as by using the format %03u instead of %u.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

A source GstPad

 

parent

Parent GstElement of pad +

 

stream_id

The stream-id.

[allow-none]
+
+
+

Returns

+

A stream-id for pad +. g_free() after usage.

+
+
+
+
+

gst_pad_create_stream_id_printf ()

+
gchar *
+gst_pad_create_stream_id_printf (GstPad *pad,
+                                 GstElement *parent,
+                                 const gchar *stream_id,
+                                 ...);
+

Creates a stream-id for the source GstPad pad + by combining the +upstream information with the optional stream_id + of the stream +of pad +. pad + must have a parent GstElement and which must have zero +or one sinkpad. stream_id + can only be NULL if the parent element +of pad + has only a single source pad.

+

This function generates an unique stream-id by getting the upstream +stream-start event stream ID and appending stream_id + to it. If the +element has no sinkpad it will generate an upstream stream-id by +doing an URI query on the element and in the worst case just uses +a random number. Source elements that don't implement the URI +handler interface should ideally generate a unique, deterministic +stream-id manually instead.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

A source GstPad

 

parent

Parent GstElement of pad +

 

stream_id

The stream-id.

[allow-none]

...

parameters for the stream_id +format string

 
+
+
+

Returns

+

A stream-id for pad +. g_free() after usage.

+
+
+
+
+

gst_pad_create_stream_id_printf_valist ()

+
gchar *
+gst_pad_create_stream_id_printf_valist
+                               (GstPad *pad,
+                                GstElement *parent,
+                                const gchar *stream_id,
+                                va_list var_args);
+

Creates a stream-id for the source GstPad pad + by combining the +upstream information with the optional stream_id + of the stream +of pad +. pad + must have a parent GstElement and which must have zero +or one sinkpad. stream_id + can only be NULL if the parent element +of pad + has only a single source pad.

+

This function generates an unique stream-id by getting the upstream +stream-start event stream ID and appending stream_id + to it. If the +element has no sinkpad it will generate an upstream stream-id by +doing an URI query on the element and in the worst case just uses +a random number. Source elements that don't implement the URI +handler interface should ideally generate a unique, deterministic +stream-id manually instead.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

A source GstPad

 

parent

Parent GstElement of pad +

 

stream_id

The stream-id.

[allow-none]

var_args

parameters for the stream_id +format string

 
+
+
+

Returns

+

A stream-id for pad +. g_free() after usage.

+
+
+
+
+

gst_pad_get_stream_id ()

+
gchar *
+gst_pad_get_stream_id (GstPad *pad);
+

Returns the current stream-id for the pad +, or NULL if none has been +set yet, i.e. the pad has not received a stream-start event yet.

+

This is a convenience wrapper around gst_pad_get_sticky_event() and +gst_event_parse_stream_start().

+

The returned stream-id string should be treated as an opaque string, its +contents should not be interpreted.

+
+

Parameters

+
+++++ + + + + + +

pad

A source GstPad

 
+
+
+

Returns

+

a newly-allocated copy of the stream-id for +pad +, or NULL. g_free() the returned string when no longer +needed.

+

[nullable]

+
+

Since: 1.2

+
+
+
+

gst_pad_get_stream ()

+
GstStream *
+gst_pad_get_stream (GstPad *pad);
+

Returns the current GstStream for the pad +, or NULL if none has been +set yet, i.e. the pad has not received a stream-start event yet.

+

This is a convenience wrapper around gst_pad_get_sticky_event() and +gst_event_parse_stream().

+
+

Parameters

+
+++++ + + + + + +

pad

A source GstPad

 
+
+
+

Returns

+

the current GstStream for pad +, or NULL. +unref the returned stream when no longer needed.

+

[nullable][transfer full]

+
+

Since: 1.10

+
+
+
+

GstPadForwardFunction ()

+
gboolean
+(*GstPadForwardFunction) (GstPad *pad,
+                          gpointer user_data);
+

A forward function is called for all internally linked pads, see +gst_pad_forward().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad that is forwarded.

 

user_data

the gpointer to optional user data.

 
+
+
+

Returns

+

TRUE if the dispatching procedure has to be stopped.

+
+
+
+
+

gst_pad_forward ()

+
gboolean
+gst_pad_forward (GstPad *pad,
+                 GstPadForwardFunction forward,
+                 gpointer user_data);
+

Calls forward + for all internally linked pads of pad +. This function deals with +dynamically changing internal pads and will make sure that the forward + +function is only called once for each pad.

+

When forward + returns TRUE, no further pads will be processed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

a GstPad

 

forward

a GstPadForwardFunction.

[scope call]

user_data

user data passed to forward +

 
+
+
+

Returns

+

TRUE if one of the dispatcher functions returned TRUE.

+
+
+
+
+

gst_pad_chain ()

+
GstFlowReturn
+gst_pad_chain (GstPad *pad,
+               GstBuffer *buffer);
+

Chain a buffer to pad +.

+

The function returns GST_FLOW_FLUSHING if the pad was flushing.

+

If the buffer type is not acceptable for pad + (as negotiated with a +preceding GST_EVENT_CAPS event), this function returns +GST_FLOW_NOT_NEGOTIATED.

+

The function proceeds calling the chain function installed on pad + (see +gst_pad_set_chain_function()) and the return value of that function is +returned to the caller. GST_FLOW_NOT_SUPPORTED is returned if pad + has no +chain function.

+

In all cases, success or failure, the caller loses its reference to buffer + +after calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a sink GstPad, returns GST_FLOW_ERROR if not.

 

buffer

the GstBuffer to send, return GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+

MT safe.

+
+
+
+
+

gst_pad_chain_list ()

+
GstFlowReturn
+gst_pad_chain_list (GstPad *pad,
+                    GstBufferList *list);
+

Chain a bufferlist to pad +.

+

The function returns GST_FLOW_FLUSHING if the pad was flushing.

+

If pad + was not negotiated properly with a CAPS event, this function +returns GST_FLOW_NOT_NEGOTIATED.

+

The function proceeds calling the chainlist function installed on pad + (see +gst_pad_set_chain_list_function()) and the return value of that function is +returned to the caller. GST_FLOW_NOT_SUPPORTED is returned if pad + has no +chainlist function.

+

In all cases, success or failure, the caller loses its reference to list + +after calling this function.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

a sink GstPad, returns GST_FLOW_ERROR if not.

 

list

the GstBufferList to send, return GST_FLOW_ERROR +if not.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn from the pad.

+
+
+
+
+

gst_pad_start_task ()

+
gboolean
+gst_pad_start_task (GstPad *pad,
+                    GstTaskFunction func,
+                    gpointer user_data,
+                    GDestroyNotify notify);
+

Starts a task that repeatedly calls func + with user_data +. This function +is mostly used in pad activation functions to start the dataflow. +The GST_PAD_STREAM_LOCK of pad + will automatically be acquired +before func + is called.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pad

the GstPad to start the task of

 

func

the task function to call

 

user_data

user data passed to the task function

 

notify

called when user_data +is no longer referenced

 
+
+
+

Returns

+

a TRUE if the task could be started.

+
+
+
+
+

gst_pad_pause_task ()

+
gboolean
+gst_pad_pause_task (GstPad *pad);
+

Pause the task of pad +. This function will also wait until the +function executed by the task is finished if this function is not +called from the task function.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to pause the task of

 
+
+
+

Returns

+

a TRUE if the task could be paused or FALSE when the pad +has no task.

+
+
+
+
+

gst_pad_stop_task ()

+
gboolean
+gst_pad_stop_task (GstPad *pad);
+

Stop the task of pad +. This function will also make sure that the +function executed by the task will effectively stop if not called +from the GstTaskFunction.

+

This function will deadlock if called from the GstTaskFunction of +the task. Use gst_task_pause() instead.

+

Regardless of whether the pad has a task, the stream lock is acquired and +released so as to ensure that streaming through this pad has finished.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to stop the task of

 
+
+
+

Returns

+

a TRUE if the task could be stopped or FALSE on error.

+
+
+
+
+

gst_pad_get_task_state ()

+
GstTaskState
+gst_pad_get_task_state (GstPad *pad);
+

Get pad + task state. If no task is currently +set, GST_TASK_STOPPED is returned.

+
+

Parameters

+
+++++ + + + + + +

pad

the GstPad to get task state from

 
+
+
+

Returns

+

The current state of pad +'s task.

+
+

Since: 1.12

+
+
+
+

gst_pad_set_active ()

+
gboolean
+gst_pad_set_active (GstPad *pad,
+                    gboolean active);
+

Activates or deactivates the given pad. +Normally called from within core state change functions.

+

If active +, makes sure the pad is active. If it is already active, either in +push or pull mode, just return. Otherwise dispatches to the pad's activate +function to perform the actual activation.

+

If not active +, calls gst_pad_activate_mode() with the pad's current mode +and a FALSE argument.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad

the GstPad to activate or deactivate.

 

active

whether or not the pad should be active.

 
+
+
+

Returns

+

TRUE if the operation was successful.

+

MT safe.

+
+
+
+
+

GST_PAD_GET_STREAM_LOCK()

+
#define GST_PAD_GET_STREAM_LOCK(pad)    (&(GST_PAD_CAST(pad)->stream_rec_lock))
+
+

Get the stream lock of pad +. The stream lock is protecting the +resources used in the data processing functions of pad +. Accessor +macro, use GST_PAD_STREAM_LOCK() and GST_PAD_STREAM_UNLOCK() instead +to take/release the pad's stream lock.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_STREAM_LOCK()

+
#define GST_PAD_STREAM_LOCK(pad)        g_rec_mutex_lock(GST_PAD_GET_STREAM_LOCK(pad))
+
+

Take the pad's stream lock. The stream lock is recursive and will be taken +when buffers or serialized downstream events are pushed on a pad.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_STREAM_TRYLOCK()

+
#define GST_PAD_STREAM_TRYLOCK(pad)     g_rec_mutex_trylock(GST_PAD_GET_STREAM_LOCK(pad))
+
+

Try to take the pad's stream lock, and return TRUE if the lock could be +taken, and otherwise FALSE.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_STREAM_UNLOCK()

+
#define GST_PAD_STREAM_UNLOCK(pad)      g_rec_mutex_unlock(GST_PAD_GET_STREAM_LOCK(pad))
+
+

Release the pad's stream lock.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_NAME()

+
#define GST_PAD_NAME(pad)		(GST_OBJECT_NAME(pad))
+
+

Get name of the given pad. +No locking is performed in this function, use gst_pad_get_name() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_PARENT()

+
#define GST_PAD_PARENT(pad)		(GST_ELEMENT_CAST(GST_OBJECT_PARENT(pad)))
+
+

Get the pad + parent. +No locking is performed in this function, use gst_pad_get_parent() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_ELEMENT_PRIVATE()

+
#define GST_PAD_ELEMENT_PRIVATE(pad)    (GST_PAD_CAST(pad)->element_private)
+
+

Get the private data of pad +, which is usually some pad- or stream-specific +structure created by the element and set on the pad when creating it. +No locking is performed in this function.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_PAD_TEMPLATE()

+
#define GST_PAD_PAD_TEMPLATE(pad) (GST_PAD_CAST(pad)->padtemplate)
+
+

Get the pad + GstPadTemplate. It describes the possible media types +a pad + or an element factory can handle.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_DIRECTION()

+
#define GST_PAD_DIRECTION(pad)		(GST_PAD_CAST(pad)->direction)
+
+

Get the GstPadDirection of the given pad +. Accessor macro, use +gst_pad_get_direction() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_LAST_FLOW_RETURN()

+
#define GST_PAD_LAST_FLOW_RETURN(pad)   (GST_PAD_CAST(pad)->ABI.abi.last_flowret)
+
+

Gets the last flow return on this pad

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+

Since: 1.4

+
+
+
+

GST_PAD_TASK()

+
#define GST_PAD_TASK(pad)		(GST_PAD_CAST(pad)->task)
+
+

Get the GstTask of pad +. Accessor macro used by GStreamer. Use the +gst_pad_start_task(), gst_pad_stop_task() and gst_pad_pause_task() +functions instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_MODE()

+
#define GST_PAD_MODE(pad)	        (GST_PAD_CAST(pad)->mode)
+
+

Get the GstPadMode of pad, which will be GST_PAD_MODE_NONE if the pad +has not been activated yet, and otherwise either GST_PAD_MODE_PUSH or +GST_PAD_MODE_PULL depending on which mode the pad was activated in.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_ACTIVATEFUNC()

+
#define GST_PAD_ACTIVATEFUNC(pad) (GST_PAD_CAST(pad)->activatefunc)
+
+

Get the GstPadActivateFunction from pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_ACTIVATEMODEFUNC()

+
#define GST_PAD_ACTIVATEMODEFUNC(pad) (GST_PAD_CAST(pad)->activatemodefunc)
+
+

Get the GstPadActivateModeFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_CHAINFUNC()

+
#define GST_PAD_CHAINFUNC(pad)		(GST_PAD_CAST(pad)->chainfunc)
+
+

Get the GstPadChainFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_CHAINLISTFUNC()

+
#define GST_PAD_CHAINLISTFUNC(pad)      (GST_PAD_CAST(pad)->chainlistfunc)
+
+

Get the GstPadChainListFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_EVENTFUNC()

+
#define GST_PAD_EVENTFUNC(pad)		(GST_PAD_CAST(pad)->eventfunc)
+
+

Get the GstPadEventFunction from the given pad +, which +is the function that handles events on the pad. You can +use this to set your own event handling function on a pad +after you create it. If your element derives from a base +class, use the base class's virtual functions instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_EVENTFULLFUNC()

+
#define GST_PAD_EVENTFULLFUNC(pad) (GST_PAD_CAST(pad)->ABI.abi.eventfullfunc)
+
+

Get the GstPadEventFullFunction from the given pad +, which +is the function that handles events on the pad. You can +use this to set your own event handling function on a pad +after you create it. If your element derives from a base +class, use the base class's virtual functions instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+

Since: 1.8

+
+
+
+

GST_PAD_GETRANGEFUNC()

+
#define GST_PAD_GETRANGEFUNC(pad) (GST_PAD_CAST(pad)->getrangefunc)
+
+

Get the GstPadGetRangeFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_QUERYFUNC()

+
#define GST_PAD_QUERYFUNC(pad)		(GST_PAD_CAST(pad)->queryfunc)
+
+

Get the GstPadQueryFunction from pad +, which is the function +that handles queries on the pad. You can use this to set your +own query handling function on a pad after you create it. If your +element derives from a base class, use the base class's virtual +functions instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_ITERINTLINKFUNC()

+
#define GST_PAD_ITERINTLINKFUNC(pad)    (GST_PAD_CAST(pad)->iterintlinkfunc)
+
+

Get the GstPadIterIntLinkFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_PEER()

+
#define GST_PAD_PEER(pad)		(GST_PAD_CAST(pad)->peer)
+
+

Return the pad's peer member. This member is a pointer to the linked pad +. +No locking is performed in this function, use gst_pad_get_peer() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_LINKFUNC()

+
#define GST_PAD_LINKFUNC(pad)		(GST_PAD_CAST(pad)->linkfunc)
+
+

Get the GstPadLinkFunction for the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNLINKFUNC()

+
#define GST_PAD_UNLINKFUNC(pad)		(GST_PAD_CAST(pad)->unlinkfunc)
+
+

Get the GstPadUnlinkFunction from the given pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_LINKED()

+
#define GST_PAD_IS_LINKED(pad)		(GST_PAD_PEER(pad) != NULL)
+
+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+

Returns

+

TRUE if the pad is linked to another pad. Use gst_pad_is_linked() +instead.

+
+
+
+
+

GST_PAD_IS_SRC()

+
#define GST_PAD_IS_SRC(pad)		(GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
+
+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+

Returns

+

TRUE if the pad is a source pad (i.e. produces data).

+
+
+
+
+

GST_PAD_IS_SINK()

+
#define GST_PAD_IS_SINK(pad)		(GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
+
+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+

Returns

+

TRUE if the pad is a sink pad (i.e. consumes data).

+
+
+
+
+

GST_PAD_IS_ACTIVE()

+
#define GST_PAD_IS_ACTIVE(pad)          (GST_PAD_MODE(pad) != GST_PAD_MODE_NONE)
+
+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+

Returns

+

TRUE if the pad has been activated.

+
+
+
+
+

GST_PAD_IS_BLOCKED()

+
#define GST_PAD_IS_BLOCKED(pad)		(GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED))
+
+

Check if the dataflow on a pad + is blocked. Use gst_pad_is_blocked() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_BLOCKING()

+
#define GST_PAD_IS_BLOCKING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING))
+
+

Check if the pad + is currently blocking on a buffer or event. Use +gst_pad_is_blocking() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_FLUSHING()

+
#define GST_PAD_IS_FLUSHING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING))
+
+

Check if the given pad + is flushing.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_SET_FLUSHING()

+
#define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING))
+
+

Set the given pad + to flushing state, which means it will not accept any +more events, queries or buffers, and return GST_FLOW_FLUSHING if any buffers +are pushed on it. This usually happens when the pad is shut down or when +a flushing seek happens. This is used inside GStreamer when flush start/stop +events pass through pads, or when an element state is changed and pads are +activated or deactivated.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNSET_FLUSHING()

+
#define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING))
+
+

Unset the flushing flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_EOS()

+
#define GST_PAD_IS_EOS(pad)	        (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS))
+
+

Check if the pad + is in EOS state.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_NEEDS_RECONFIGURE()

+
#define GST_PAD_NEEDS_RECONFIGURE(pad)  (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE))
+
+

Check if the pad + should be reconfigured/renegotiated. +The flag has to be unset manually after reconfiguration happened. +Use gst_pad_needs_reconfigure() or gst_pad_check_reconfigure() instead.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_HAS_PENDING_EVENTS()

+
#define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS))
+
+

Check if the given pad + has pending events. This is used internally by +GStreamer.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_FIXED_CAPS()

+
#define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS))
+
+

Check if the given pad + is using fixed caps, which means that +once the caps are set on the pad +, the caps query function will +only return those caps. See gst_pad_use_fixed_caps().

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_NEEDS_PARENT()

+
#define GST_PAD_NEEDS_PARENT(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_PARENT))
+
+

Check if there is a parent object before calling into the pad + callbacks. +This is used internally by GStreamer.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_PROXY_CAPS()

+
#define GST_PAD_IS_PROXY_CAPS(pad)      (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_CAPS))
+
+

Check if the given pad + is set to proxy caps. This means that the default +event and query handler will forward all events and queries to the +internally linked pads + instead of discarding them.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_SET_PROXY_CAPS()

+
#define GST_PAD_SET_PROXY_CAPS(pad)     (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_CAPS))
+
+

Set pad + to proxy caps, so that all caps-related events and queries are +proxied down- or upstream to the other side of the element automatically. +Set this if the element always outputs data in the exact same format as it +receives as input. This is just for convenience to avoid implementing some +standard event and query handling code in an element.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNSET_PROXY_CAPS()

+
#define GST_PAD_UNSET_PROXY_CAPS(pad)   (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_CAPS))
+
+

Unset proxy caps flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_PROXY_ALLOCATION()

+
#define GST_PAD_IS_PROXY_ALLOCATION(pad)    (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION))
+
+

Check if the given pad + is set as proxy allocation which means +that the default query handler will forward allocation queries to the +internally linked pads + instead of discarding them.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_SET_PROXY_ALLOCATION()

+
#define GST_PAD_SET_PROXY_ALLOCATION(pad)   (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION))
+
+

Set pad + to proxy allocation queries, which means that the default query +handler will forward allocation queries to the internally linked pads + +instead of discarding them. +Set this if the element always outputs data in the exact same format as it +receives as input. This is just for convenience to avoid implementing some +standard query handling code in an element.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNSET_PROXY_ALLOCATION()

+
#define GST_PAD_UNSET_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_ALLOCATION))
+
+

Unset proxy allocation flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_SET_PROXY_SCHEDULING()

+
#define GST_PAD_SET_PROXY_SCHEDULING(pad)   (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING))
+
+

Set pad + to proxy scheduling queries, which means that the default query +handler will forward scheduling queries to the internally linked pads + +instead of discarding them. You will usually want to handle scheduling +queries explicitly if your element supports multiple scheduling modes.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNSET_PROXY_SCHEDULING()

+
#define GST_PAD_UNSET_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_SCHEDULING))
+
+

Unset proxy scheduling flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_PROXY_SCHEDULING()

+
#define GST_PAD_IS_PROXY_SCHEDULING(pad)    (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING))
+
+

Check if the given pad + is set to proxy scheduling queries, which means that +the default query handler will forward scheduling queries to the internally +linked pads + instead of discarding them.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_ACCEPT_INTERSECT()

+
#define GST_PAD_IS_ACCEPT_INTERSECT(pad)    (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT))
+
+

Check if the pad's accept intersect flag is set. The default accept-caps +handler will check if the caps intersect the query-caps result instead of +checking for a subset. This is interesting for parser elements that can +accept incompletely specified caps.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_SET_ACCEPT_INTERSECT()

+
#define GST_PAD_SET_ACCEPT_INTERSECT(pad)   (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT))
+
+

Set pad + to by default accept caps by intersecting the result instead of +checking for a subset. This is interesting for parser elements that can +accept incompletely specified caps.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_UNSET_ACCEPT_INTERSECT()

+
#define GST_PAD_UNSET_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT))
+
+

Unset accept intersect flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+
+
+
+

GST_PAD_IS_ACCEPT_TEMPLATE()

+
#define GST_PAD_IS_ACCEPT_TEMPLATE(pad)    (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE))
+
+

Check if the pad's accept caps operation will use the pad template caps. +The default accept-caps will do a query caps to get the caps, which might +be querying downstream causing unnecessary overhead. It is recommended to +implement a proper accept-caps query handler or to use this flag to prevent +recursive accept-caps handling.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+

Since: 1.6

+
+
+
+

GST_PAD_SET_ACCEPT_TEMPLATE()

+
#define GST_PAD_SET_ACCEPT_TEMPLATE(pad)   (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE))
+
+

Set pad + to by default use the pad template caps to compare with +the accept caps instead of using a caps query result.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+

Since: 1.6

+
+
+
+

GST_PAD_UNSET_ACCEPT_TEMPLATE()

+
#define GST_PAD_UNSET_ACCEPT_TEMPLATE(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE))
+
+

Unset accept template flag.

+
+

Parameters

+
+++++ + + + + + +

pad

a GstPad

 
+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstPad

+
struct GstPad {
+  gpointer                       element_private;
+
+  GstPadTemplate                *padtemplate;
+
+  GstPadDirection                direction;
+};
+
+

The GstPad structure. Use the functions to update the variables.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

gpointer element_private;

private data owned by the parent element

 

GstPadTemplate *padtemplate;

padtemplate for this pad

 

GstPadDirection direction;

the direction of the pad, cannot change after creating +the pad.

 
+
+
+
+
+

enum GstPadDirection

+

The direction of a pad.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_PAD_UNKNOWN

+

direction is unknown.

+
 

GST_PAD_SRC

+

the pad is a source pad.

+
 

GST_PAD_SINK

+

the pad is a sink pad.

+
 
+
+
+
+
+

enum GstPadFlags

+

Pad state flags

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PAD_FLAG_BLOCKED

+

is dataflow on a pad blocked

+
 

GST_PAD_FLAG_FLUSHING

+

is pad flushing

+
 

GST_PAD_FLAG_EOS

+

is pad in EOS state

+
 

GST_PAD_FLAG_BLOCKING

+

is pad currently blocking on a buffer or event

+
 

GST_PAD_FLAG_NEED_PARENT

+

ensure that there is a parent object before calling + into the pad callbacks.

+
 

GST_PAD_FLAG_NEED_RECONFIGURE

+

the pad should be reconfigured/renegotiated. + The flag has to be unset manually after + reconfiguration happened.

+
 

GST_PAD_FLAG_PENDING_EVENTS

+

the pad has pending events

+
 

GST_PAD_FLAG_FIXED_CAPS

+

the pad is using fixed caps. This means that + once the caps are set on the pad, the default caps query function + will only return those caps.

+
 

GST_PAD_FLAG_PROXY_CAPS

+

the default event and query handler will forward + all events and queries to the internally linked pads + instead of discarding them.

+
 

GST_PAD_FLAG_PROXY_ALLOCATION

+

the default query handler will forward + allocation queries to the internally linked pads + instead of discarding them.

+
 

GST_PAD_FLAG_PROXY_SCHEDULING

+

the default query handler will forward + scheduling queries to the internally linked pads + instead of discarding them.

+
 

GST_PAD_FLAG_ACCEPT_INTERSECT

+

the default accept-caps handler will check + it the caps intersect the query-caps result instead + of checking for a subset. This is interesting for + parsers that can accept incompletely specified caps.

+
 

GST_PAD_FLAG_ACCEPT_TEMPLATE

+

the default accept-caps handler will use + the template pad caps instead of query caps to + compare with the accept caps. Use this in combination + with GST_PAD_FLAG_ACCEPT_INTERSECT. (Since 1.6)

+
 

GST_PAD_FLAG_LAST

+

offset to define more flags

+
 
+
+
+
+
+

enum GstPadLinkReturn

+

Result values from gst_pad_link and friends.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PAD_LINK_OK

+

link succeeded

+
 

GST_PAD_LINK_WRONG_HIERARCHY

+

pads have no common grandparent

+
 

GST_PAD_LINK_WAS_LINKED

+

pad was already linked

+
 

GST_PAD_LINK_WRONG_DIRECTION

+

pads have wrong direction

+
 

GST_PAD_LINK_NOFORMAT

+

pads do not have common format

+
 

GST_PAD_LINK_NOSCHED

+

pads cannot cooperate in scheduling

+
 

GST_PAD_LINK_REFUSED

+

refused for some reason

+
 
+
+
+
+
+

enum GstPadLinkCheck

+

The amount of checking to be done when linking pads. GST_PAD_LINK_CHECK_CAPS + +and GST_PAD_LINK_CHECK_TEMPLATE_CAPS + are mutually exclusive. If both are +specified, expensive but safe GST_PAD_LINK_CHECK_CAPS + are performed.

+

Only disable some of the checks if you are 100% certain you know the link +will not fail because of hierarchy/caps compatibility failures. If uncertain, +use the default checks (GST_PAD_LINK_CHECK_DEFAULT) or the regular methods +for linking the pads.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PAD_LINK_CHECK_NOTHING

+

Don't check hierarchy or caps compatibility.

+
 

GST_PAD_LINK_CHECK_HIERARCHY

+

Check the pads have same parents/grandparents. + Could be omitted if it is already known that the two elements that own the + pads are in the same bin.

+
 

GST_PAD_LINK_CHECK_TEMPLATE_CAPS

+

Check if the pads are compatible by using + their template caps. This is much faster than GST_PAD_LINK_CHECK_CAPS +, but + would be unsafe e.g. if one pad has GST_CAPS_ANY.

+
 

GST_PAD_LINK_CHECK_CAPS

+

Check if the pads are compatible by comparing the + caps returned by gst_pad_query_caps().

+
 

GST_PAD_LINK_CHECK_NO_RECONFIGURE

+

Disables pushing a reconfigure event when pads are + linked.

+
 

GST_PAD_LINK_CHECK_DEFAULT

+

The default checks done when linking + pads (i.e. the ones used by gst_pad_link()).

+
 
+
+
+
+
+

enum GstFlowReturn

+

The result of passing data to a pad.

+

Note that the custom return values should not be exposed outside of the +element scope.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_FLOW_CUSTOM_SUCCESS_2

+

Pre-defined custom success code.

+
 

GST_FLOW_CUSTOM_SUCCESS_1

+

Pre-defined custom success code (define your + custom success code to this to avoid compiler + warnings).

+
 

GST_FLOW_CUSTOM_SUCCESS

+

Elements can use values starting from + this (and higher) to define custom success + codes.

+
 

GST_FLOW_OK

+

Data passing was ok.

+
 

GST_FLOW_NOT_LINKED

+

Pad is not linked.

+
 

GST_FLOW_FLUSHING

+

Pad is flushing.

+
 

GST_FLOW_EOS

+

Pad is EOS.

+
 

GST_FLOW_NOT_NEGOTIATED

+

Pad is not negotiated.

+
 

GST_FLOW_ERROR

+

Some (fatal) error occurred. Element generating + this error should post an error message with more + details.

+
 

GST_FLOW_NOT_SUPPORTED

+

This operation is not supported.

+
 

GST_FLOW_CUSTOM_ERROR

+

Elements can use values starting from + this (and lower) to define custom error codes.

+
 

GST_FLOW_CUSTOM_ERROR_1

+

Pre-defined custom error code (define your + custom error code to this to avoid compiler + warnings).

+
 

GST_FLOW_CUSTOM_ERROR_2

+

Pre-defined custom error code.

+
 
+
+
+
+
+

enum GstPadMode

+

The status of a GstPad. After activating a pad, which usually happens when the +parent element goes from READY to PAUSED, the GstPadMode defines if the +pad operates in push or pull mode.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_PAD_MODE_NONE

+

Pad will not handle dataflow

+
 

GST_PAD_MODE_PUSH

+

Pad handles dataflow in downstream push mode

+
 

GST_PAD_MODE_PULL

+

Pad handles dataflow in upstream pull mode

+
 
+
+
+
+
+

enum GstPadProbeReturn

+

Different return values for the GstPadProbeCallback.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PAD_PROBE_DROP

+

drop data in data probes. For push mode this means that + the data item is not sent downstream. For pull mode, it means that + the data item is not passed upstream. In both cases, no other probes + are called for this item and GST_FLOW_OK or TRUE is returned to the + caller.

+
 

GST_PAD_PROBE_OK

+

normal probe return value. This leaves the probe in + place, and defers decisions about dropping or passing data to other + probes, if any. If there are no other probes, the default behaviour + for the probe type applies ('block' for blocking probes, + and 'pass' for non-blocking probes).

+
 

GST_PAD_PROBE_REMOVE

+

remove this probe.

+
 

GST_PAD_PROBE_PASS

+

pass the data item in the block probe and block on the + next item.

+
 

GST_PAD_PROBE_HANDLED

+

Data has been handled in the probe and will not be + forwarded further. For events and buffers this is the same behaviour as + GST_PAD_PROBE_DROP (except that in this case you need to unref the buffer + or event yourself). For queries it will also return TRUE to the caller. + The probe can also modify the GstFlowReturn value by using the + GST_PAD_PROBE_INFO_FLOW_RETURN() accessor. + Note that the resulting query must contain valid entries. + Since: 1.6

+
 
+
+
+
+
+

enum GstPadProbeType

+

The different probing types that can occur. When either one of +GST_PAD_PROBE_TYPE_IDLE + or GST_PAD_PROBE_TYPE_BLOCK + is used, the probe will be a +blocking probe.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PAD_PROBE_TYPE_INVALID

+

invalid probe type

+
 

GST_PAD_PROBE_TYPE_IDLE

+

probe idle pads and block while the callback is called

+
 

GST_PAD_PROBE_TYPE_BLOCK

+

probe and block pads

+
 

GST_PAD_PROBE_TYPE_BUFFER

+

probe buffers

+
 

GST_PAD_PROBE_TYPE_BUFFER_LIST

+

probe buffer lists

+
 

GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM

+

probe downstream events

+
 

GST_PAD_PROBE_TYPE_EVENT_UPSTREAM

+

probe upstream events

+
 

GST_PAD_PROBE_TYPE_EVENT_FLUSH

+

probe flush events. This probe has to be + explicitly enabled and is not included in the + @GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM + or + @GST_PAD_PROBE_TYPE_EVENT_UPSTREAM + probe types.

+
 

GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM

+

probe downstream queries

+
 

GST_PAD_PROBE_TYPE_QUERY_UPSTREAM

+

probe upstream queries

+
 

GST_PAD_PROBE_TYPE_PUSH

+

probe push

+
 

GST_PAD_PROBE_TYPE_PULL

+

probe pull

+
 

GST_PAD_PROBE_TYPE_BLOCKING

+

probe and block at the next opportunity, at data flow or when idle

+
 

GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM

+

probe downstream data (buffers, buffer lists, and events)

+
 

GST_PAD_PROBE_TYPE_DATA_UPSTREAM

+

probe upstream data (events)

+
 

GST_PAD_PROBE_TYPE_DATA_BOTH

+

probe upstream and downstream data (buffers, buffer lists, and events)

+
 

GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM

+

probe and block downstream data (buffers, buffer lists, and events)

+
 

GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM

+

probe and block upstream data (events)

+
 

GST_PAD_PROBE_TYPE_EVENT_BOTH

+

probe upstream and downstream events

+
 

GST_PAD_PROBE_TYPE_QUERY_BOTH

+

probe upstream and downstream queries

+
 

GST_PAD_PROBE_TYPE_ALL_BOTH

+

probe upstream events and queries and downstream buffers, buffer lists, events and queries

+
 

GST_PAD_PROBE_TYPE_SCHEDULING

+

probe push and pull

+
 
+
+
+
+
+

struct GstPadProbeInfo

+
struct GstPadProbeInfo {
+  GstPadProbeType type;
+  gulong id;
+  gpointer data;
+  guint64 offset;
+  guint size;
+};
+
+

Info passed in the GstPadProbeCallback.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstPadProbeType type;

the current probe type

 

gulong id;

the id of the probe

 

gpointer data;

type specific data, check the type +field to know the +datatype. This field can be NULL.

[allow-none]

guint64 offset;

offset of pull probe, this field is valid when type +contains +GST_PAD_PROBE_TYPE_PULL

 

guint size;

size of pull probe, this field is valid when type +contains +GST_PAD_PROBE_TYPE_PULL

 
+
+
+
+
+

Property Details

+
+

The “caps” property

+
  “caps”                     GstCaps *
+

The capabilities of the pad.

+

Flags: Read

+
+
+
+

The “direction” property

+
  “direction”                GstPadDirection
+

The direction of the pad.

+

Flags: Read / Write / Construct Only

+

Default value: GST_PAD_UNKNOWN

+
+
+
+

The “offset” property

+
  “offset”                   gint64
+

The offset that will be applied to the running time of the pad.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+

Since: 1.6

+
+
+
+

The “template” property

+
  “template”                 GstPadTemplate *
+

The GstPadTemplate of this pad.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “linked” signal

+
void
+user_function (GstPad  *pad,
+               GstPad  *peer,
+               gpointer user_data)
+

Signals that a pad has been linked to the peer pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the pad that emitted the signal

 

peer

the peer pad that has been connected

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “unlinked” signal

+
void
+user_function (GstPad  *pad,
+               GstPad  *peer,
+               gpointer user_data)
+

Signals that a pad has been unlinked from the peer pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad

the pad that emitted the signal

 

peer

the peer pad that has been disconnected

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPadTemplate.html b/docs/gst/html/GstPadTemplate.html new file mode 100644 index 0000000..e83a2aa --- /dev/null +++ b/docs/gst/html/GstPadTemplate.html @@ -0,0 +1,867 @@ + + + + +GstPadTemplate: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPadTemplate

+

GstPadTemplate — Describe the media type of a pad.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_STATIC_PAD_TEMPLATE() +
+GstPadTemplate * + +gst_static_pad_template_get () +
+GstCaps * + +gst_static_pad_template_get_caps () +
#define +GST_PAD_TEMPLATE_NAME_TEMPLATE() +
#define +GST_PAD_TEMPLATE_DIRECTION() +
#define +GST_PAD_TEMPLATE_PRESENCE() +
#define +GST_PAD_TEMPLATE_CAPS() +
#define +GST_PAD_TEMPLATE_IS_FIXED() +
#define +GST_PAD_TEMPLATE_GTYPE() +
+GstPadTemplate * + +gst_pad_template_new () +
+GstPadTemplate * + +gst_pad_template_new_from_static_pad_template_with_gtype () +
+GstCaps * + +gst_pad_template_get_caps () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstCaps *capsRead / Write / Construct Only
GstPadDirectiondirectionRead / Write / Construct Only
+GType *gtypeRead / Write / Construct Only
+gchar *name-templateRead / Write / Construct Only
GstPadPresencepresenceRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + +
voidpad-createdRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
structGstStaticPadTemplate
structGstPadTemplate
enumGstPadTemplateFlags
enumGstPadPresence
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPadTemplate
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

Padtemplates describe the possible media types a pad or an elementfactory can +handle. This allows for both inspection of handled types before loading the +element plugin as well as identifying pads on elements that are not yet +created (request or sometimes pads).

+

Pad and PadTemplates have GstCaps attached to it to describe the media type +they are capable of dealing with. gst_pad_template_get_caps() or +GST_PAD_TEMPLATE_CAPS() are used to get the caps of a padtemplate. It's not +possible to modify the caps of a padtemplate after creation.

+

PadTemplates have a GstPadPresence property which identifies the lifetime +of the pad and that can be retrieved with GST_PAD_TEMPLATE_PRESENCE(). Also +the direction of the pad can be retrieved from the GstPadTemplate with +GST_PAD_TEMPLATE_DIRECTION().

+

The GST_PAD_TEMPLATE_NAME_TEMPLATE() is important for GST_PAD_REQUEST pads +because it has to be used as the name in the gst_element_get_request_pad() +call to instantiate a pad from this template.

+

Padtemplates can be created with gst_pad_template_new() or with +gst_static_pad_template_get(), which creates a GstPadTemplate from a +GstStaticPadTemplate that can be filled with the +convenient GST_STATIC_PAD_TEMPLATE() macro.

+

A padtemplate can be used to create a pad (see gst_pad_new_from_template() +or gst_pad_new_from_static_template()) or to add to an element class +(see gst_element_class_add_static_pad_template()).

+

The following code example shows the code to create a pad from a padtemplate.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
GstStaticPadTemplate my_template =
+GST_STATIC_PAD_TEMPLATE (
+  "sink",          // the name of the pad
+  GST_PAD_SINK,    // the direction of the pad
+  GST_PAD_ALWAYS,  // when this pad will be present
+  GST_STATIC_CAPS (        // the capabilities of the padtemplate
+    "audio/x-raw, "
+      "channels = (int) [ 1, 6 ]"
+  )
+);
+void
+my_method (void)
+{
+  GstPad *pad;
+  pad = gst_pad_new_from_static_template (&my_template, "sink");
+  ...
+}
+
+ +

+

The following example shows you how to add the padtemplate to an +element class, this is usually done in the class_init of the class:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
static void
+my_element_class_init (GstMyElementClass *klass)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_static_pad_template (gstelement_class, &my_template);
+}
+
+ +

+
+
+

Functions

+
+

GST_STATIC_PAD_TEMPLATE()

+
#define             GST_STATIC_PAD_TEMPLATE(padname, dir, pres, caps)
+

Convenience macro to fill the values of a GstStaticPadTemplate +structure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

padname

the name template of the pad

 

dir

the GstPadDirection of the pad

 

pres

the GstPadPresence of the pad

 

caps

the GstStaticCaps of the pad

 
+
+
+
+
+

gst_static_pad_template_get ()

+
GstPadTemplate *
+gst_static_pad_template_get (GstStaticPadTemplate *pad_template);
+

Converts a GstStaticPadTemplate into a GstPadTemplate.

+
+

Parameters

+
+++++ + + + + + +

pad_template

the static pad template

 
+
+
+

Returns

+

a new GstPadTemplate.

+

[transfer floating][nullable]

+
+
+
+
+

gst_static_pad_template_get_caps ()

+
GstCaps *
+gst_static_pad_template_get_caps (GstStaticPadTemplate *templ);
+

Gets the capabilities of the static pad template.

+
+

Parameters

+
+++++ + + + + + +

templ

a GstStaticPadTemplate to get capabilities of.

 
+
+
+

Returns

+

the GstCaps of the static pad template. +Unref after usage. Since the core holds an additional +ref to the returned caps, use gst_caps_make_writable() +on the returned caps to modify it.

+

[transfer full]

+
+
+
+
+

GST_PAD_TEMPLATE_NAME_TEMPLATE()

+
#define GST_PAD_TEMPLATE_NAME_TEMPLATE(templ) (((GstPadTemplate *)(templ))->name_template)
+
+

Get the nametemplate of the padtemplate.

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+
+
+
+

GST_PAD_TEMPLATE_DIRECTION()

+
#define GST_PAD_TEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction)
+
+

Get the GstPadDirection of the padtemplate.

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+
+
+
+

GST_PAD_TEMPLATE_PRESENCE()

+
#define GST_PAD_TEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence)
+
+

Get the GstPadPresence of the padtemplate.

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+
+
+
+

GST_PAD_TEMPLATE_CAPS()

+
#define GST_PAD_TEMPLATE_CAPS(templ)		(((GstPadTemplate *)(templ))->caps)
+
+

Get a handle to the padtemplate GstCaps

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+
+
+
+

GST_PAD_TEMPLATE_IS_FIXED()

+
#define GST_PAD_TEMPLATE_IS_FIXED(templ) (GST_OBJECT_FLAG_IS_SET(templ, GST_PAD_TEMPLATE_FIXED))
+
+

Check if the properties of the padtemplate are fixed

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+
+
+
+

GST_PAD_TEMPLATE_GTYPE()

+
#define GST_PAD_TEMPLATE_GTYPE(templ)		(((GstPadTemplate *)(templ))->ABI.abi.gtype)
+
+

Get the GType of the padtemplate

+
+

Parameters

+
+++++ + + + + + +

templ

the template to query

 
+
+

Since: 1.14

+
+
+
+

gst_pad_template_new ()

+
GstPadTemplate *
+gst_pad_template_new (const gchar *name_template,
+                      GstPadDirection direction,
+                      GstPadPresence presence,
+                      GstCaps *caps);
+

Creates a new pad template with a name according to the given template +and with the given arguments.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

name_template

the name template.

 

direction

the GstPadDirection of the template.

 

presence

the GstPadPresence of the pad.

 

caps

a GstCaps set for the template.

[transfer none]
+
+
+

Returns

+

a new GstPadTemplate.

+

[transfer floating][nullable]

+
+
+
+
+

gst_pad_template_new_from_static_pad_template_with_gtype ()

+
GstPadTemplate *
+gst_pad_template_new_from_static_pad_template_with_gtype
+                               (GstStaticPadTemplate *pad_template,
+                                GType pad_type);
+

Converts a GstStaticPadTemplate into a GstPadTemplate with a type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pad_template

the static pad template

 

pad_type

The GType of the pad to create

 
+
+
+

Returns

+

a new GstPadTemplate.

+

[transfer floating]

+
+

Since: 1.14

+
+
+
+

gst_pad_template_get_caps ()

+
GstCaps *
+gst_pad_template_get_caps (GstPadTemplate *templ);
+

Gets the capabilities of the pad template.

+
+

Parameters

+
+++++ + + + + + +

templ

a GstPadTemplate to get capabilities of.

 
+
+
+

Returns

+

the GstCaps of the pad template. +Unref after usage.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstStaticPadTemplate

+
struct GstStaticPadTemplate {
+  const gchar     *name_template;
+  GstPadDirection  direction;
+  GstPadPresence   presence;
+  GstStaticCaps    static_caps;
+};
+
+

Structure describing the GstStaticPadTemplate.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

const gchar *name_template;

the name of the template

 

GstPadDirection direction;

the direction of the template

 

GstPadPresence presence;

the presence of the template

 

GstStaticCaps static_caps;

the caps of the template.

 
+
+
+
+
+

struct GstPadTemplate

+
struct GstPadTemplate;
+

The padtemplate object.

+
+
+
+

enum GstPadTemplateFlags

+

Flags for the padtemplate

+
+

Members

+
+++++ + + + + + +

GST_PAD_TEMPLATE_FLAG_LAST

+

first flag that can be used by subclasses.

+
 
+
+
+
+
+

enum GstPadPresence

+

Indicates when this pad will become available.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_PAD_ALWAYS

+

the pad is always available

+
 

GST_PAD_SOMETIMES

+

the pad will become available depending on the media stream

+
 

GST_PAD_REQUEST

+

the pad is only available on request with + gst_element_request_pad().

+
 
+
+
+
+
+

Property Details

+
+

The “caps” property

+
  “caps”                     GstCaps *
+

The capabilities of the pad described by the pad template.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “direction” property

+
  “direction”                GstPadDirection
+

The direction of the pad described by the pad template.

+

Flags: Read / Write / Construct Only

+

Default value: GST_PAD_UNKNOWN

+
+
+
+

The “gtype” property

+
  “gtype”                    GType *
+

The type of the pad described by the pad template.

+

Flags: Read / Write / Construct Only

+

Allowed values: void

+

Since: 1.14

+
+
+
+

The “name-template” property

+
  “name-template”            gchar *
+

The name template of the pad template.

+

Flags: Read / Write / Construct Only

+

Default value: NULL

+
+
+
+

The “presence” property

+
  “presence”                 GstPadPresence
+

When the pad described by the pad template will become available.

+

Flags: Read / Write / Construct Only

+

Default value: GST_PAD_ALWAYS

+
+
+
+

Signal Details

+
+

The “pad-created” signal

+
void
+user_function (GstPadTemplate *pad_template,
+               GstPad         *pad,
+               gpointer        user_data)
+

This signal is fired when an element creates a pad from this template.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pad_template

the object which received the signal.

 

pad

the pad that was created.

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

See Also

+

GstPad, GstElementFactory

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPipeline.html b/docs/gst/html/GstPipeline.html new file mode 100644 index 0000000..f9aaa59 --- /dev/null +++ b/docs/gst/html/GstPipeline.html @@ -0,0 +1,807 @@ + + + + +GstPipeline: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPipeline

+

GstPipeline — Top-level bin with clocking and bus management + functionality.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstElement * + +gst_pipeline_new () +
+GstBus * + +gst_pipeline_get_bus () +
+gboolean + +gst_pipeline_set_clock () +
+GstClock * + +gst_pipeline_get_pipeline_clock () +
+GstClock * + +gst_pipeline_get_clock () +
+void + +gst_pipeline_use_clock () +
+void + +gst_pipeline_auto_clock () +
+void + +gst_pipeline_set_auto_flush_bus () +
+gboolean + +gst_pipeline_get_auto_flush_bus () +
+void + +gst_pipeline_set_delay () +
+GstClockTime + +gst_pipeline_get_delay () +
+void + +gst_pipeline_set_latency () +
+GstClockTime + +gst_pipeline_get_latency () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
gbooleanauto-flush-busRead / Write
guint64delayRead / Write
guint64latencyRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstPipeline
enumGstPipelineFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBin
+                    ╰── GstPipeline
+
+
+
+

Implemented Interfaces

+

+GstPipeline implements + GstChildProxy.

+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstPipeline is a special GstBin used as the toplevel container for +the filter graph. The GstPipeline will manage the selection and +distribution of a global GstClock as well as provide a GstBus to the +application.

+

gst_pipeline_new() is used to create a pipeline. when you are done with +the pipeline, use gst_object_unref() to free its resources including all +added GstElement objects (if not otherwise referenced).

+

Elements are added and removed from the pipeline using the GstBin +methods like gst_bin_add() and gst_bin_remove() (see GstBin).

+

Before changing the state of the GstPipeline (see GstElement) a GstBus +can be retrieved with gst_pipeline_get_bus(). This bus can then be +used to receive GstMessage from the elements in the pipeline.

+

By default, a GstPipeline will automatically flush the pending GstBus +messages when going to the NULL state to ensure that no circular +references exist when no messages are read from the GstBus. This +behaviour can be changed with gst_pipeline_set_auto_flush_bus().

+

When the GstPipeline performs the PAUSED to PLAYING state change it will +select a clock for the elements. The clock selection algorithm will by +default select a clock provided by an element that is most upstream +(closest to the source). For live pipelines (ones that return +GST_STATE_CHANGE_NO_PREROLL from the gst_element_set_state() call) this +will select the clock provided by the live source. For normal pipelines +this will select a clock provided by the sinks (most likely the audio +sink). If no element provides a clock, a default GstSystemClock is used.

+

The clock selection can be controlled with the gst_pipeline_use_clock() +method, which will enforce a given clock on the pipeline. With +gst_pipeline_auto_clock() the default clock selection algorithm can be +restored.

+

A GstPipeline maintains a running time for the elements. The running +time is defined as the difference between the current clock time and +the base time. When the pipeline goes to READY or a flushing seek is +performed on it, the running time is reset to 0. When the pipeline is +set from PLAYING to PAUSED, the current clock time is sampled and used to +configure the base time for the elements when the pipeline is set +to PLAYING again. The effect is that the running time (as the difference +between the clock time and the base time) will count how much time was spent +in the PLAYING state. This default behaviour can be changed with the +gst_element_set_start_time() method.

+
+
+

Functions

+
+

gst_pipeline_new ()

+
GstElement *
+gst_pipeline_new (const gchar *name);
+

Create a new pipeline with the given name.

+
+

Parameters

+
+++++ + + + + + +

name

name of new pipeline.

[allow-none]
+
+
+

Returns

+

newly created GstPipeline

+

MT safe.

+

[transfer floating]

+
+
+
+
+

gst_pipeline_get_bus ()

+
GstBus *
+gst_pipeline_get_bus (GstPipeline *pipeline);
+

Gets the GstBus of pipeline +. The bus allows applications to receive +GstMessage packets.

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

a GstBus, unref after usage.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_pipeline_set_clock ()

+
gboolean
+gst_pipeline_set_clock (GstPipeline *pipeline,
+                        GstClock *clock);
+

Set the clock for pipeline +. The clock will be distributed +to all the elements managed by the pipeline.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline

a GstPipeline

 

clock

the clock to set.

[transfer none]
+
+
+

Returns

+

TRUE if the clock could be set on the pipeline. FALSE if +some element did not accept the clock.

+

MT safe.

+
+
+
+
+

gst_pipeline_get_pipeline_clock ()

+
GstClock *
+gst_pipeline_get_pipeline_clock (GstPipeline *pipeline);
+

Gets the current clock used by pipeline +.

+

Unlike gst_element_get_clock(), this function will always return a +clock, even if the pipeline is not in the PLAYING state.

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

a GstClock, unref after usage.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_pipeline_get_clock ()

+
GstClock *
+gst_pipeline_get_clock (GstPipeline *pipeline);
+

Gets the current clock used by pipeline +. Users of object +oriented languages should use gst_pipeline_get_pipeline_clock() +to avoid confusion with gst_element_get_clock() which has a different behavior.

+

Unlike gst_element_get_clock(), this function will always return a +clock, even if the pipeline is not in the PLAYING state.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

a GstClock, unref after usage.

+

[transfer full]

+
+
+
+
+

gst_pipeline_use_clock ()

+
void
+gst_pipeline_use_clock (GstPipeline *pipeline,
+                        GstClock *clock);
+

Force pipeline + to use the given clock +. The pipeline will +always use the given clock even if new clock providers are added +to this pipeline.

+

If clock + is NULL all clocking will be disabled which will make +the pipeline run as fast as possible.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline

a GstPipeline

 

clock

the clock to use.

[transfer none][allow-none]
+
+
+
+
+

gst_pipeline_auto_clock ()

+
void
+gst_pipeline_auto_clock (GstPipeline *pipeline);
+

Let pipeline + select a clock automatically. This is the default +behaviour.

+

Use this function if you previous forced a fixed clock with +gst_pipeline_use_clock() and want to restore the default +pipeline clock selection algorithm.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+
+
+

gst_pipeline_set_auto_flush_bus ()

+
void
+gst_pipeline_set_auto_flush_bus (GstPipeline *pipeline,
+                                 gboolean auto_flush);
+

Usually, when a pipeline goes from READY to NULL state, it automatically +flushes all pending messages on the bus, which is done for refcounting +purposes, to break circular references.

+

This means that applications that update state using (async) bus messages +(e.g. do certain things when a pipeline goes from PAUSED to READY) might +not get to see messages when the pipeline is shut down, because they might +be flushed before they can be dispatched in the main thread. This behaviour +can be disabled using this function.

+

It is important that all messages on the bus are handled when the +automatic flushing is disabled else memory leaks will be introduced.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline

a GstPipeline

 

auto_flush

whether or not to automatically flush the bus when +the pipeline goes from READY to NULL state

 
+
+
+
+
+

gst_pipeline_get_auto_flush_bus ()

+
gboolean
+gst_pipeline_get_auto_flush_bus (GstPipeline *pipeline);
+

Check if pipeline + will automatically flush messages when going to +the NULL state.

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

whether the pipeline will automatically flush its bus when +going from READY to NULL state or not.

+

MT safe.

+
+
+
+
+

gst_pipeline_set_delay ()

+
void
+gst_pipeline_set_delay (GstPipeline *pipeline,
+                        GstClockTime delay);
+

Set the expected delay needed for all elements to perform the +PAUSED to PLAYING state change. delay + will be added to the +base time of the elements so that they wait an additional delay + +amount of time before starting to process buffers and cannot be +GST_CLOCK_TIME_NONE.

+

This option is used for tuning purposes and should normally not be +used.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline

a GstPipeline

 

delay

the delay

 
+
+
+
+
+

gst_pipeline_get_delay ()

+
GstClockTime
+gst_pipeline_get_delay (GstPipeline *pipeline);
+

Get the configured delay (see gst_pipeline_set_delay()).

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

The configured delay.

+

MT safe.

+
+
+
+
+

gst_pipeline_set_latency ()

+
void
+gst_pipeline_set_latency (GstPipeline *pipeline,
+                          GstClockTime latency);
+

Sets the latency that should be configured on the pipeline. Setting +GST_CLOCK_TIME_NONE will restore the default behaviour of using the minimum +latency from the LATENCY query. Setting this is usually not required and +the pipeline will figure out an appropriate latency automatically.

+

Setting a too low latency, especially lower than the minimum latency from +the LATENCY query, will most likely cause the pipeline to fail.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline

a GstPipeline

 

latency

latency to configure

 
+
+

Since: 1.6

+
+
+
+

gst_pipeline_get_latency ()

+
GstClockTime
+gst_pipeline_get_latency (GstPipeline *pipeline);
+

Gets the latency that should be configured on the pipeline. See +gst_pipeline_set_latency().

+
+

Parameters

+
+++++ + + + + + +

pipeline

a GstPipeline

 
+
+
+

Returns

+

Latency to configure on the pipeline or GST_CLOCK_TIME_NONE

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstPipeline

+
struct GstPipeline {
+  GstClock      *fixed_clock;
+
+  GstClockTime   stream_time;
+  GstClockTime   delay;
+};
+
+

The GstPipeline structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GstClock *fixed_clock;

The fixed clock of the pipeline, used when +GST_PIPELINE_FLAG_FIXED_CLOCK is set.

 

GstClockTime stream_time;

The stream time of the pipeline. A better name for this +property would be the running_time, the total time spent in the +PLAYING state without being flushed. (deprecated, use the start_time +on GstElement).

 

GstClockTime delay;

Extra delay added to base_time to compensate for computing delays +when setting elements to PLAYING.

 
+
+
+
+
+

enum GstPipelineFlags

+

Pipeline flags

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_PIPELINE_FLAG_FIXED_CLOCK

+

this pipeline works with a fixed clock

+
 

GST_PIPELINE_FLAG_LAST

+

offset to define more flags

+
 
+
+
+
+
+

Property Details

+
+

The “auto-flush-bus” property

+
  “auto-flush-bus”           gboolean
+

Whether or not to automatically flush all messages on the +pipeline's bus when going from READY to NULL state. Please see +gst_pipeline_set_auto_flush_bus() for more information on this option.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “delay” property

+
  “delay”                    guint64
+

The expected delay needed for elements to spin up to the +PLAYING state expressed in nanoseconds. +see gst_pipeline_set_delay() for more information on this option.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “latency” property

+
  “latency”                  guint64
+

Latency to configure on the pipeline. See gst_pipeline_set_latency().

+

Flags: Read / Write

+

Default value: 18446744073709551615

+

Since: 1.6

+
+
+
+

See Also

+

GstElement, GstBin, GstClock, GstBus

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPlugin.html b/docs/gst/html/GstPlugin.html new file mode 100644 index 0000000..d5d2e29 --- /dev/null +++ b/docs/gst/html/GstPlugin.html @@ -0,0 +1,1605 @@ + + + + +GstPlugin: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPlugin

+

GstPlugin — Container for features loaded from a shared object module

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GQuark + +gst_plugin_error_quark () +
+gboolean + +(*GstPluginInitFunc) () +
+gboolean + +(*GstPluginInitFullFunc) () +
#define +GST_PLUGIN_DEFINE() +
#define +GST_PLUGIN_STATIC_DECLARE() +
#define +GST_PLUGIN_STATIC_REGISTER() +
+gboolean + +(*GstPluginFilter) () +
const gchar * + +gst_plugin_get_name () +
const gchar * + +gst_plugin_get_description () +
const gchar * + +gst_plugin_get_filename () +
const gchar * + +gst_plugin_get_license () +
const gchar * + +gst_plugin_get_package () +
const gchar * + +gst_plugin_get_origin () +
const gchar * + +gst_plugin_get_source () +
const gchar * + +gst_plugin_get_version () +
const gchar * + +gst_plugin_get_release_date_string () +
+gboolean + +gst_plugin_is_loaded () +
const GstStructure * + +gst_plugin_get_cache_data () +
+void + +gst_plugin_set_cache_data () +
+GstPlugin * + +gst_plugin_load_file () +
+GstPlugin * + +gst_plugin_load () +
+GstPlugin * + +gst_plugin_load_by_name () +
+void + +gst_plugin_list_free () +
+gboolean + +gst_plugin_register_static () +
+gboolean + +gst_plugin_register_static_full () +
+void + +gst_plugin_add_dependency () +
+void + +gst_plugin_add_dependency_simple () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineGST_PLUGIN_ERROR
enumGstPluginError
 GstPlugin
structGstPluginDesc
#defineGST_LICENSE_UNKNOWN
enumGstPluginFlags
enumGstPluginDependencyFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPlugin
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GStreamer is extensible, so GstElement instances can be loaded at runtime. +A plugin system can provide one or more of the basic

+GStreamerGstPluginFeature subclasses. +

A plugin should export a symbol gst_plugin_desc that is a +struct of type GstPluginDesc. +the plugin loader will check the version of the core library the plugin was +linked against and will create a new GstPlugin. It will then call the +GstPluginInitFunc function that was provided in the

+gst_plugin_desc. +

Once you have a handle to a GstPlugin (e.g. from the GstRegistry), you +can add any object that subclasses GstPluginFeature.

+

Usually plugins are always automatically loaded so you don't need to call +gst_plugin_load() explicitly to bring it into memory. There are options to +statically link plugins to an app or even use GStreamer without a plugin +repository in which case gst_plugin_load() can be needed to bring the plugin +into memory.

+
+
+

Functions

+
+

gst_plugin_error_quark ()

+
GQuark
+gst_plugin_error_quark (void);
+

Get the error quark.

+
+

Returns

+

The error quark used in GError messages

+
+
+
+
+

GstPluginInitFunc ()

+
gboolean
+(*GstPluginInitFunc) (GstPlugin *plugin);
+

A plugin should provide a pointer to a function of this type in the +plugin_desc struct. +This function will be called by the loader at startup. One would then +register each GstPluginFeature.

+
+

Parameters

+
+++++ + + + + + +

plugin

The plugin object

 
+
+
+

Returns

+

TRUE if plugin initialised successfully

+
+
+
+
+

GstPluginInitFullFunc ()

+
gboolean
+(*GstPluginInitFullFunc) (GstPlugin *plugin,
+                          gpointer user_data);
+

A plugin should provide a pointer to a function of either GstPluginInitFunc +or this type in the plugin_desc struct. +The function will be called by the loader at startup. One would then +register each GstPluginFeature. This version allows +user data to be passed to init function (useful for bindings).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

plugin

The plugin object

 

user_data

extra data

 
+
+
+

Returns

+

TRUE if plugin initialised successfully

+
+
+
+
+

GST_PLUGIN_DEFINE()

+
#define             GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin)
+

This macro needs to be used to define the entry point and meta data of a +plugin. One would use this macro to export a plugin, so that it can be used +by other applications.

+

The macro uses a define named PACKAGE for the GstPluginDesc,source field. +When using autoconf, this is usually set automatically via the AC_INIT +macro, and set in config.h. If you are not using autoconf, you will need to +define PACKAGE yourself and set it to a short mnemonic string identifying +your application/package, e.g. 'someapp' or 'my-plugins-foo.

+

If defined, the GST_PACKAGE_RELEASE_DATETIME will also be used for the +GstPluginDesc,release_datetime field.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

major

major version number of the gstreamer-core that plugin was compiled for

 

minor

minor version number of the gstreamer-core that plugin was compiled for

 

name

short, but unique name of the plugin

 

description

information about the purpose of the plugin

 

init

function pointer to the plugin_init method with the signature of static gboolean plugin_init (GstPlugin * plugin).

 

version

full version string (e.g. VERSION from config.h)

 

license

under which licence the package has been released, e.g. GPL, LGPL.

 

package

the package-name (e.g. PACKAGE_NAME from config.h)

 

origin

a description from where the package comes from (e.g. the homepage URL)

 
+
+
+
+
+

GST_PLUGIN_STATIC_DECLARE()

+
#define             GST_PLUGIN_STATIC_DECLARE(name)
+

This macro can be used to initialize statically linked plugins. It is +necessary to call this macro before the plugin can be used. +It has to be used in combination with GST_PLUGIN_STATIC_REGISTER +and must be placed outside any block to declare the plugin initialization +function.

+
+

Parameters

+
+++++ + + + + + +

name

short, but unique name of the plugin

 
+
+

Since: 1.2

+
+
+
+

GST_PLUGIN_STATIC_REGISTER()

+
#define GST_PLUGIN_STATIC_REGISTER(name) G_PASTE(gst_plugin_, G_PASTE(name, _register)) ()
+
+

This macro can be used to initialize statically linked plugins. It is +necessary to call this macro before the plugin can be used. +It has to be used in combination with GST_PLUGIN_STATIC_DECLARE and +calls the plugin initialization function.

+
+

Parameters

+
+++++ + + + + + +

name

short, but unique name of the plugin

 
+
+

Since: 1.2

+
+
+
+

GstPluginFilter ()

+
gboolean
+(*GstPluginFilter) (GstPlugin *plugin,
+                    gpointer user_data);
+

A function that can be used with e.g. gst_registry_plugin_filter() +to get a list of plugins that match certain criteria.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

plugin

the plugin to check

 

user_data

the user_data that has been passed on e.g. gst_registry_plugin_filter()

 
+
+
+

Returns

+

TRUE for a positive match, FALSE otherwise

+
+
+
+
+

gst_plugin_get_name ()

+
const gchar *
+gst_plugin_get_name (GstPlugin *plugin);
+

Get the short name of the plugin

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the name of

 
+
+
+

Returns

+

the name of the plugin

+
+
+
+
+

gst_plugin_get_description ()

+
const gchar *
+gst_plugin_get_description (GstPlugin *plugin);
+

Get the long descriptive name of the plugin

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get long name of

 
+
+
+

Returns

+

the long name of the plugin

+
+
+
+
+

gst_plugin_get_filename ()

+
const gchar *
+gst_plugin_get_filename (GstPlugin *plugin);
+

get the filename of the plugin

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the filename of

 
+
+
+

Returns

+

the filename of the plugin.

+

[type filename]

+
+
+
+
+

gst_plugin_get_license ()

+
const gchar *
+gst_plugin_get_license (GstPlugin *plugin);
+

get the license of the plugin

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the license of

 
+
+
+

Returns

+

the license of the plugin

+
+
+
+
+

gst_plugin_get_package ()

+
const gchar *
+gst_plugin_get_package (GstPlugin *plugin);
+

get the package the plugin belongs to.

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the package of

 
+
+
+

Returns

+

the package of the plugin

+
+
+
+
+

gst_plugin_get_origin ()

+
const gchar *
+gst_plugin_get_origin (GstPlugin *plugin);
+

get the URL where the plugin comes from

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the origin of

 
+
+
+

Returns

+

the origin of the plugin

+
+
+
+
+

gst_plugin_get_source ()

+
const gchar *
+gst_plugin_get_source (GstPlugin *plugin);
+

get the source module the plugin belongs to.

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the source of

 
+
+
+

Returns

+

the source of the plugin

+
+
+
+
+

gst_plugin_get_version ()

+
const gchar *
+gst_plugin_get_version (GstPlugin *plugin);
+

get the version of the plugin

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the version of

 
+
+
+

Returns

+

the version of the plugin

+
+
+
+
+

gst_plugin_get_release_date_string ()

+
const gchar *
+gst_plugin_get_release_date_string (GstPlugin *plugin);
+

Get the release date (and possibly time) in form of a string, if available.

+

For normal GStreamer plugin releases this will usually just be a date in +the form of "YYYY-MM-DD", while pre-releases and builds from git may contain +a time component after the date as well, in which case the string will be +formatted like "YYYY-MM-DDTHH:MMZ" (e.g. "2012-04-30T09:30Z").

+

There may be plugins that do not have a valid release date set on them.

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to get the release date of

 
+
+
+

Returns

+

the date string of the plugin, or NULL if not +available.

+

[nullable]

+
+
+
+
+

gst_plugin_is_loaded ()

+
gboolean
+gst_plugin_is_loaded (GstPlugin *plugin);
+

queries if the plugin is loaded into memory

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to query

 
+
+
+

Returns

+

TRUE is loaded, FALSE otherwise

+
+
+
+
+

gst_plugin_get_cache_data ()

+
const GstStructure *
+gst_plugin_get_cache_data (GstPlugin *plugin);
+

Gets the plugin specific data cache. If it is NULL there is no cached data +stored. This is the case when the registry is getting rebuilt.

+
+

Parameters

+
+++++ + + + + + +

plugin

a plugin

 
+
+
+

Returns

+

The cached data as a +GstStructure or NULL.

+

[transfer none][nullable]

+
+
+
+
+

gst_plugin_set_cache_data ()

+
void
+gst_plugin_set_cache_data (GstPlugin *plugin,
+                           GstStructure *cache_data);
+

Adds plugin specific data to cache. Passes the ownership of the structure to +the plugin +.

+

The cache is flushed every time the registry is rebuilt.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

plugin

a plugin

 

cache_data

a structure containing the data to cache.

[transfer full]
+
+
+
+
+

gst_plugin_load_file ()

+
GstPlugin *
+gst_plugin_load_file (const gchar *filename,
+                      GError **error);
+

Loads the given plugin and refs it. Caller needs to unref after use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

filename

the plugin filename to load.

[type filename]

error

pointer to a NULL-valued GError

 
+
+
+

Returns

+

a reference to the existing loaded GstPlugin, a +reference to the newly-loaded GstPlugin, or NULL if an error occurred.

+

[transfer full]

+
+
+
+
+

gst_plugin_load ()

+
GstPlugin *
+gst_plugin_load (GstPlugin *plugin);
+

Loads plugin +. Note that the *return value* is the loaded plugin; plugin + is +untouched. The normal use pattern of this function goes like this:

+
+ + + + + + + +
1
+2
+3
+4
+5
GstPlugin *loaded_plugin;
+loaded_plugin = gst_plugin_load (plugin);
+// presumably, we're no longer interested in the potentially-unloaded plugin
+gst_object_unref (plugin);
+plugin = loaded_plugin;
+
+ +

+
+

Parameters

+
+++++ + + + + + +

plugin

plugin to load.

[transfer none]
+
+
+

Returns

+

a reference to a loaded plugin, or +NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

gst_plugin_load_by_name ()

+
GstPlugin *
+gst_plugin_load_by_name (const gchar *name);
+

Load the named plugin. Refs the plugin.

+
+

Parameters

+
+++++ + + + + + +

name

name of plugin to load

 
+
+
+

Returns

+

a reference to a loaded plugin, or +NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

gst_plugin_list_free ()

+
void
+gst_plugin_list_free (GList *list);
+

Unrefs each member of list +, then frees the list.

+
+

Parameters

+
+++++ + + + + + +

list

list of GstPlugin.

[transfer full][element-type Gst.Plugin]
+
+
+
+
+

gst_plugin_register_static ()

+
gboolean
+gst_plugin_register_static (gint major_version,
+                            gint minor_version,
+                            const gchar *name,
+                            const gchar *description,
+                            GstPluginInitFunc init_func,
+                            const gchar *version,
+                            const gchar *license,
+                            const gchar *source,
+                            const gchar *package,
+                            const gchar *origin);
+

Registers a static plugin, ie. a plugin which is private to an application +or library and contained within the application or library (as opposed to +being shipped as a separate module file).

+

You must make sure that GStreamer has been initialised (with gst_init() or +via gst_init_get_option_group()) before calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

major_version

the major version number of the GStreamer core that the +plugin was compiled for, you can just use GST_VERSION_MAJOR here

 

minor_version

the minor version number of the GStreamer core that the +plugin was compiled for, you can just use GST_VERSION_MINOR here

 

name

a unique name of the plugin (ideally prefixed with an application- or +library-specific namespace prefix in order to avoid name conflicts in +case a similar plugin with the same name ever gets added to GStreamer)

 

description

description of the plugin

 

init_func

pointer to the init function of this plugin.

[scope call]

version

version string of the plugin

 

license

effective license of plugin. Must be one of the approved licenses +(see GstPluginDesc above) or the plugin will not be registered.

 

source

source module plugin belongs to

 

package

shipped package plugin belongs to

 

origin

URL to provider of plugin

 
+
+
+

Returns

+

TRUE if the plugin was registered correctly, otherwise FALSE.

+
+
+
+
+

gst_plugin_register_static_full ()

+
gboolean
+gst_plugin_register_static_full (gint major_version,
+                                 gint minor_version,
+                                 const gchar *name,
+                                 const gchar *description,
+                                 GstPluginInitFullFunc init_full_func,
+                                 const gchar *version,
+                                 const gchar *license,
+                                 const gchar *source,
+                                 const gchar *package,
+                                 const gchar *origin,
+                                 gpointer user_data);
+

Registers a static plugin, ie. a plugin which is private to an application +or library and contained within the application or library (as opposed to +being shipped as a separate module file) with a GstPluginInitFullFunc +which allows user data to be passed to the callback function (useful +for bindings).

+

You must make sure that GStreamer has been initialised (with gst_init() or +via gst_init_get_option_group()) before calling this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

major_version

the major version number of the GStreamer core that the +plugin was compiled for, you can just use GST_VERSION_MAJOR here

 

minor_version

the minor version number of the GStreamer core that the +plugin was compiled for, you can just use GST_VERSION_MINOR here

 

name

a unique name of the plugin (ideally prefixed with an application- or +library-specific namespace prefix in order to avoid name conflicts in +case a similar plugin with the same name ever gets added to GStreamer)

 

description

description of the plugin

 

init_full_func

pointer to the init function with user data +of this plugin.

[scope call]

version

version string of the plugin

 

license

effective license of plugin. Must be one of the approved licenses +(see GstPluginDesc above) or the plugin will not be registered.

 

source

source module plugin belongs to

 

package

shipped package plugin belongs to

 

origin

URL to provider of plugin

 

user_data

gpointer to user data

 
+
+
+

Returns

+

TRUE if the plugin was registered correctly, otherwise FALSE.

+
+
+
+
+

gst_plugin_add_dependency ()

+
void
+gst_plugin_add_dependency (GstPlugin *plugin,
+                           const gchar **env_vars,
+                           const gchar **paths,
+                           const gchar **names,
+                           GstPluginDependencyFlags flags);
+

Make GStreamer aware of external dependencies which affect the feature +set of this plugin (ie. the elements or typefinders associated with it).

+

GStreamer will re-inspect plugins with external dependencies whenever any +of the external dependencies change. This is useful for plugins which wrap +other plugin systems, e.g. a plugin which wraps a plugin-based visualisation +library and makes visualisations available as GStreamer elements, or a +codec loader which exposes elements and/or caps dependent on what external +codec libraries are currently installed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

plugin

a GstPlugin

 

env_vars

NULL-terminated array of environment variables affecting the +feature set of the plugin (e.g. an environment variable containing +paths where to look for additional modules/plugins of a library), +or NULL. Environment variable names may be followed by a path component +which will be added to the content of the environment variable, e.g. +"HOME/.mystuff/plugins".

[allow-none][array zero-terminated=1]

paths

NULL-terminated array of directories/paths where dependent files +may be, or NULL.

[allow-none][array zero-terminated=1]

names

NULL-terminated array of file names (or file name suffixes, +depending on flags +) to be used in combination with the paths from +paths +and/or the paths extracted from the environment variables in +env_vars +, or NULL.

[allow-none][array zero-terminated=1]

flags

optional flags, or GST_PLUGIN_DEPENDENCY_FLAG_NONE

 
+
+
+
+
+

gst_plugin_add_dependency_simple ()

+
void
+gst_plugin_add_dependency_simple (GstPlugin *plugin,
+                                  const gchar *env_vars,
+                                  const gchar *paths,
+                                  const gchar *names,
+                                  GstPluginDependencyFlags flags);
+

Make GStreamer aware of external dependencies which affect the feature +set of this plugin (ie. the elements or typefinders associated with it).

+

GStreamer will re-inspect plugins with external dependencies whenever any +of the external dependencies change. This is useful for plugins which wrap +other plugin systems, e.g. a plugin which wraps a plugin-based visualisation +library and makes visualisations available as GStreamer elements, or a +codec loader which exposes elements and/or caps dependent on what external +codec libraries are currently installed.

+

Convenience wrapper function for gst_plugin_add_dependency() which +takes simple strings as arguments instead of string arrays, with multiple +arguments separated by predefined delimiters (see above).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

plugin

the GstPlugin

 

env_vars

one or more environment variables (separated by ':', ';' or ','), +or NULL. Environment variable names may be followed by a path component +which will be added to the content of the environment variable, e.g. +"HOME/.mystuff/plugins:MYSTUFF_PLUGINS_PATH".

[allow-none]

paths

one ore more directory paths (separated by ':' or ';' or ','), +or NULL. Example: "/usr/lib/mystuff/plugins".

[allow-none]

names

one or more file names or file name suffixes (separated by commas), +or NULL.

[allow-none]

flags

optional flags, or GST_PLUGIN_DEPENDENCY_FLAG_NONE

 
+
+
+
+
+

Types and Values

+
+

GST_PLUGIN_ERROR

+
#define GST_PLUGIN_ERROR gst_plugin_error_quark ()
+
+

The error message category quark

+
+
+
+

enum GstPluginError

+

The plugin loading errors

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_PLUGIN_ERROR_MODULE

+

The plugin could not be loaded

+
 

GST_PLUGIN_ERROR_DEPENDENCIES

+

The plugin has unresolved dependencies

+
 

GST_PLUGIN_ERROR_NAME_MISMATCH

+

The plugin has already be loaded from a different file

+
 
+
+
+
+
+

GstPlugin

+
typedef struct _GstPlugin GstPlugin;
+

The opaque plugin object

+
+
+
+

struct GstPluginDesc

+
struct GstPluginDesc {
+  gint major_version;
+  gint minor_version;
+  const gchar *name;
+  const gchar *description;
+  GstPluginInitFunc plugin_init;
+  const gchar *version;
+  const gchar *license;
+  const gchar *source;
+  const gchar *package;
+  const gchar *origin;
+  const gchar *release_datetime;
+};
+
+

A plugin should export a variable of this type called plugin_desc. The plugin +loader will use the data provided there to initialize the plugin.

+

The licence + parameter must be one of: LGPL, GPL, QPL, GPL/QPL, MPL, +BSD, MIT/X11, Proprietary, unknown.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gint major_version;

the major version number of core that plugin was compiled for

 

gint minor_version;

the minor version number of core that plugin was compiled for

 

const gchar *name;

a unique name of the plugin

 

const gchar *description;

description of plugin

 

GstPluginInitFunc plugin_init;

pointer to the init function of this plugin.

 

const gchar *version;

version of the plugin

 

const gchar *license;

effective license of plugin

 

const gchar *source;

source module plugin belongs to

 

const gchar *package;

shipped package plugin belongs to

 

const gchar *origin;

URL to provider of plugin

 

const gchar *release_datetime;

date time string in ISO 8601 +format (or rather, a subset thereof), or NULL. Allowed are the +following formats: "YYYY-MM-DD" and "YYY-MM-DDTHH:MMZ" (with +'T' a separator and 'Z' indicating UTC/Zulu time). This field +should be set via the GST_PACKAGE_RELEASE_DATETIME +preprocessor macro.

[allow-none]
+
+
+
+
+

GST_LICENSE_UNKNOWN

+
#define GST_LICENSE_UNKNOWN "unknown"
+
+

To be used in GST_PLUGIN_DEFINE if unsure about the licence.

+
+
+
+

enum GstPluginFlags

+

The plugin loading state

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_PLUGIN_FLAG_CACHED

+

Temporarily loaded plugins

+
 

GST_PLUGIN_FLAG_BLACKLISTED

+

The plugin won't be scanned (again)

+
 
+
+
+
+
+

enum GstPluginDependencyFlags

+

Flags used in connection with gst_plugin_add_dependency().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PLUGIN_DEPENDENCY_FLAG_NONE

+

no special flags

+
 

GST_PLUGIN_DEPENDENCY_FLAG_RECURSE

+

recurse into subdirectories

+
 

GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY

+

use paths + argument only if none of the environment variables is set

+
 

GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX

+

interpret + filename argument as filter suffix and check all matching files in + the directory

+
 

GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX

+

interpret + filename argument as filter prefix and check all matching files in + the directory. Since 1.8.

+
 

GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE

+

interpret + non-absolute paths as relative to the main executable directory. Since + 1.14.

+
 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPluginFeature.html b/docs/gst/html/GstPluginFeature.html new file mode 100644 index 0000000..b19d90b --- /dev/null +++ b/docs/gst/html/GstPluginFeature.html @@ -0,0 +1,685 @@ + + + + +GstPluginfeature: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPluginfeature

+

GstPluginfeature — Base class for contents of a GstPlugin

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +(*GstPluginFeatureFilter) () +
+void + +gst_plugin_feature_set_rank () +
#define +gst_plugin_feature_set_name() +
+guint + +gst_plugin_feature_get_rank () +
#define +gst_plugin_feature_get_name() +
+GstPlugin * + +gst_plugin_feature_get_plugin () +
const gchar * + +gst_plugin_feature_get_plugin_name () +
+GstPluginFeature * + +gst_plugin_feature_load () +
+GList * + +gst_plugin_feature_list_copy () +
+void + +gst_plugin_feature_list_free () +
#define +GST_PLUGIN_FEATURE_LIST_DEBUG() +
+gboolean + +gst_plugin_feature_check_version () +
+gint + +gst_plugin_feature_rank_compare_func () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstPluginFeature
enumGstRank
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ├── GstElementFactory
+                ├── GstTracerFactory
+                ├── GstTypeFindFactory
+                ├── GstDeviceProviderFactory
+                ╰── GstDynamicTypeFactory
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

This is a base class for anything that can be added to a GstPlugin.

+
+
+

Functions

+
+

GstPluginFeatureFilter ()

+
gboolean
+(*GstPluginFeatureFilter) (GstPluginFeature *feature,
+                           gpointer user_data);
+

A function that can be used with e.g. gst_registry_feature_filter() +to get a list of pluginfeature that match certain criteria.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature

the pluginfeature to check

 

user_data

the user_data that has been passed on e.g. +gst_registry_feature_filter()

 
+
+
+

Returns

+

TRUE for a positive match, FALSE otherwise

+
+
+
+
+

gst_plugin_feature_set_rank ()

+
void
+gst_plugin_feature_set_rank (GstPluginFeature *feature,
+                             guint rank);
+

Specifies a rank for a plugin feature, so that autoplugging uses +the most appropriate feature.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature

feature to rank

 

rank

rank value - higher number means more priority rank

 
+
+
+
+
+

gst_plugin_feature_set_name()

+
#define                 gst_plugin_feature_set_name(feature,name) gst_object_set_name(GST_OBJECT_CAST(feature),name)
+
+

Sets the name of the plugin feature, getting rid of the old name if there was one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

feature

a GstPluginFeature to set the name of.

 

name

the new name

 
+
+
+
+
+

gst_plugin_feature_get_rank ()

+
guint
+gst_plugin_feature_get_rank (GstPluginFeature *feature);
+

Gets the rank of a plugin feature.

+
+

Parameters

+
+++++ + + + + + +

feature

a feature

 
+
+
+

Returns

+

The rank of the feature

+
+
+
+
+

gst_plugin_feature_get_name()

+
#define                 gst_plugin_feature_get_name(feature)      GST_OBJECT_NAME(feature)
+
+

Returns the name of feature +. +For a nameless plugin feature, this returns NULL.

+
+

Parameters

+
+++++ + + + + + +

feature

a GstPluginFeature to get the name of feature +.

 
+
+
+

Returns

+

the name of feature +. MT safe.

+

[transfer none][nullable]

+
+
+
+
+

gst_plugin_feature_get_plugin ()

+
GstPlugin *
+gst_plugin_feature_get_plugin (GstPluginFeature *feature);
+

Get the plugin that provides this feature.

+
+

Parameters

+
+++++ + + + + + +

feature

a feature

 
+
+
+

Returns

+

the plugin that provides this +feature, or NULL. Unref with gst_object_unref() when no +longer needed.

+

[transfer full][nullable]

+
+
+
+
+

gst_plugin_feature_get_plugin_name ()

+
const gchar *
+gst_plugin_feature_get_plugin_name (GstPluginFeature *feature);
+

Get the name of the plugin that provides this feature.

+
+

Parameters

+
+++++ + + + + + +

feature

a feature

 
+
+
+

Returns

+

the name of the plugin that provides this +feature, or NULL if the feature is not associated with a +plugin.

+

[nullable]

+
+

Since: 1.2

+
+
+
+

gst_plugin_feature_load ()

+
GstPluginFeature *
+gst_plugin_feature_load (GstPluginFeature *feature);
+

Loads the plugin containing feature + if it's not already loaded. feature + is +unaffected; use the return value instead.

+

Normally this function is used like this:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
GstPluginFeature *loaded_feature;
+
+loaded_feature = gst_plugin_feature_load (feature);
+// presumably, we're no longer interested in the potentially-unloaded feature
+gst_object_unref (feature);
+feature = loaded_feature;
+
+ +

+
+

Parameters

+
+++++ + + + + + +

feature

the plugin feature to check.

[transfer none]
+
+
+

Returns

+

a reference to the loaded +feature, or NULL on error.

+

[transfer full][nullable]

+
+
+
+
+

gst_plugin_feature_list_copy ()

+
GList *
+gst_plugin_feature_list_copy (GList *list);
+

Copies the list of features. Caller should call gst_plugin_feature_list_free + +when done with the list.

+
+

Parameters

+
+++++ + + + + + +

list

list +of GstPluginFeature.

[transfer none][element-type Gst.PluginFeature]
+
+
+

Returns

+

a copy of list +, +with each feature's reference count incremented.

+

[transfer full][element-type Gst.PluginFeature]

+
+
+
+
+

gst_plugin_feature_list_free ()

+
void
+gst_plugin_feature_list_free (GList *list);
+

Unrefs each member of list +, then frees the list.

+
+

Parameters

+
+++++ + + + + + +

list

list +of GstPluginFeature.

[transfer full][element-type Gst.PluginFeature]
+
+
+
+
+

GST_PLUGIN_FEATURE_LIST_DEBUG()

+
#define GST_PLUGIN_FEATURE_LIST_DEBUG(list) gst_plugin_feature_list_debug(list)
+
+

Debug the plugin feature names in list +.

+
+

Parameters

+
+++++ + + + + + +

list

a GList of +plugin features.

[transfer none][element-type Gst.PluginFeature]
+
+
+
+
+

gst_plugin_feature_check_version ()

+
gboolean
+gst_plugin_feature_check_version (GstPluginFeature *feature,
+                                  guint min_major,
+                                  guint min_minor,
+                                  guint min_micro);
+

Checks whether the given plugin feature is at least + the required version

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

feature

a feature

 

min_major

minimum required major version

 

min_minor

minimum required minor version

 

min_micro

minimum required micro version

 
+
+
+

Returns

+

TRUE if the plugin feature has at least +the required version, otherwise FALSE.

+
+
+
+
+

gst_plugin_feature_rank_compare_func ()

+
gint
+gst_plugin_feature_rank_compare_func (gconstpointer p1,
+                                      gconstpointer p2);
+

Compares the two given GstPluginFeature instances. This function can be +used as a GCompareFunc when sorting by rank and then by name.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

p1

a GstPluginFeature

 

p2

a GstPluginFeature

 
+
+
+

Returns

+

negative value if the rank of p1 > the rank of p2 or the ranks are +equal but the name of p1 comes before the name of p2; zero if the rank +and names are equal; positive value if the rank of p1 < the rank of p2 or the +ranks are equal but the name of p2 comes before the name of p1

+
+
+
+
+

Types and Values

+
+

GstPluginFeature

+
typedef struct _GstPluginFeature GstPluginFeature;
+

Opaque GstPluginFeature structure.

+
+
+
+

enum GstRank

+

Element priority ranks. Defines the order in which the autoplugger (or +similar rank-picking mechanisms, such as e.g. gst_element_make_from_uri()) +will choose this element over an alternative one with the same function.

+

These constants serve as a rough guidance for defining the rank of a +GstPluginFeature. Any value is valid, including values bigger than +GST_RANK_PRIMARY +.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_RANK_NONE

+

will be chosen last or not at all

+
 

GST_RANK_MARGINAL

+

unlikely to be chosen

+
 

GST_RANK_SECONDARY

+

likely to be chosen

+
 

GST_RANK_PRIMARY

+

will be chosen first

+
 
+
+
+
+
+

See Also

+

GstPlugin

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPreset.html b/docs/gst/html/GstPreset.html new file mode 100644 index 0000000..dcbeac4 --- /dev/null +++ b/docs/gst/html/GstPreset.html @@ -0,0 +1,660 @@ + + + + +GstPreset: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPreset

+

GstPreset — helper interface for element presets

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar ** + +gst_preset_get_preset_names () +
+gchar ** + +gst_preset_get_property_names () +
+gboolean + +gst_preset_load_preset () +
+gboolean + +gst_preset_save_preset () +
+gboolean + +gst_preset_rename_preset () +
+gboolean + +gst_preset_delete_preset () +
+gboolean + +gst_preset_set_meta () +
+gboolean + +gst_preset_get_meta () +
+gboolean + +gst_preset_set_app_dir () +
const gchar * + +gst_preset_get_app_dir () +
+gboolean + +gst_preset_is_editable () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstPreset
structGstPresetInterface
+
+
+

Object Hierarchy

+
    GInterface
+    ╰── GstPreset
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

This interface offers methods to query and manipulate parameter preset sets. +A preset is a bunch of property settings, together with meta data and a name. +The name of a preset serves as key for subsequent method calls to manipulate +single presets. +All instances of one type will share the list of presets. The list is created +on demand, if presets are not used, the list is not created.

+

The interface comes with a default implementation that serves most plugins. +Wrapper plugins will override most methods to implement support for the +native preset format of those wrapped plugins. +One method that is useful to be overridden is gst_preset_get_property_names(). +With that one can control which properties are saved and in which order. +When implementing support for read-only presets, one should set the vmethods +for gst_preset_save_preset() and gst_preset_delete_preset() to NULL. +Applications can use gst_preset_is_editable() to check for that.

+

The default implementation supports presets located in a system directory, +application specific directory and in the users home directory. When getting +a list of presets individual presets are read and overlaid in 1) system, +2) application and 3) user order. Whenever an earlier entry is newer, the +later entries will be updated. Since 1.8 you can also provide extra paths +where to find presets through the GST_PRESET_PATH environment variable. +Presets found in those paths will be concidered as "app presets".

+
+
+

Functions

+
+

gst_preset_get_preset_names ()

+
gchar **
+gst_preset_get_preset_names (GstPreset *preset);
+

Get a copy of preset names as a NULL terminated string array.

+
+

Parameters

+
+++++ + + + + + +

preset

a GObject that implements GstPreset

 
+
+
+

Returns

+

list with names, use g_strfreev() after usage.

+

[transfer full][array zero-terminated=1][element-type gchar*]

+
+
+
+
+

gst_preset_get_property_names ()

+
gchar **
+gst_preset_get_property_names (GstPreset *preset);
+

Get a the names of the GObject properties that can be used for presets.

+
+

Parameters

+
+++++ + + + + + +

preset

a GObject that implements GstPreset

 
+
+
+

Returns

+

an +array of property names which should be freed with g_strfreev() after use.

+

[transfer full][array zero-terminated=1][element-type gchar*]

+
+
+
+
+

gst_preset_load_preset ()

+
gboolean
+gst_preset_load_preset (GstPreset *preset,
+                        const gchar *name);
+

Load the given preset.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

name

preset name to load

 
+
+
+

Returns

+

TRUE for success, FALSE if e.g. there is no preset with that name +

+
+
+
+
+

gst_preset_save_preset ()

+
gboolean
+gst_preset_save_preset (GstPreset *preset,
+                        const gchar *name);
+

Save the current object settings as a preset under the given name. If there +is already a preset by this name + it will be overwritten.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

name

preset name to save

 
+
+
+

Returns

+

TRUE for success, FALSE

+
+
+
+
+

gst_preset_rename_preset ()

+
gboolean
+gst_preset_rename_preset (GstPreset *preset,
+                          const gchar *old_name,
+                          const gchar *new_name);
+

Renames a preset. If there is already a preset by the new_name + it will be +overwritten.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

old_name

current preset name

 

new_name

new preset name

 
+
+
+

Returns

+

TRUE for success, FALSE if e.g. there is no preset with old_name +

+
+
+
+
+

gst_preset_delete_preset ()

+
gboolean
+gst_preset_delete_preset (GstPreset *preset,
+                          const gchar *name);
+

Delete the given preset.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

name

preset name to remove

 
+
+
+

Returns

+

TRUE for success, FALSE if e.g. there is no preset with that name +

+
+
+
+
+

gst_preset_set_meta ()

+
gboolean
+gst_preset_set_meta (GstPreset *preset,
+                     const gchar *name,
+                     const gchar *tag,
+                     const gchar *value);
+

Sets a new value + for an existing meta data item or adds a new item. Meta +data tag + names can be something like e.g. "comment". Supplying NULL for the +value + will unset an existing value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

name

preset name

 

tag

meta data item name

 

value

new value.

[allow-none]
+
+
+

Returns

+

TRUE for success, FALSE if e.g. there is no preset with that name +

+
+
+
+
+

gst_preset_get_meta ()

+
gboolean
+gst_preset_get_meta (GstPreset *preset,
+                     const gchar *name,
+                     const gchar *tag,
+                     gchar **value);
+

Gets the value + for an existing meta data tag +. Meta data tag + names can be +something like e.g. "comment". Returned values need to be released when done.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

preset

a GObject that implements GstPreset

 

name

preset name

 

tag

meta data item name

 

value

value.

[out callee-allocates]
+
+
+

Returns

+

TRUE for success, FALSE if e.g. there is no preset with that name +or no value for the given tag +

+
+
+
+
+

gst_preset_set_app_dir ()

+
gboolean
+gst_preset_set_app_dir (const gchar *app_dir);
+

Sets an extra directory as an absolute path that should be considered when +looking for presets. Any presets in the application dir will shadow the +system presets.

+
+

Parameters

+
+++++ + + + + + +

app_dir

the application specific preset dir.

[type filename]
+
+
+

Returns

+

TRUE for success, FALSE if the dir already has been set

+
+
+
+
+

gst_preset_get_app_dir ()

+
const gchar *
+gst_preset_get_app_dir (void);
+

Gets the directory for application specific presets if set by the +application.

+
+

Returns

+

the directory or NULL, don't free or modify +the string.

+

[nullable][type filename]

+
+
+
+
+

gst_preset_is_editable ()

+
gboolean
+gst_preset_is_editable (GstPreset *preset);
+

Check if one can add new presets, change existing ones and remove presets.

+
+

Parameters

+
+++++ + + + + + +

preset

a GObject that implements GstPreset

 
+
+
+

Returns

+

TRUE if presets are editable or FALSE if they are static

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GstPreset

+
typedef struct _GstPreset GstPreset;
+

Opaque GstPreset data structure.

+
+
+
+

struct GstPresetInterface

+
struct GstPresetInterface {
+  GTypeInterface parent;
+
+  /* methods */
+  gchar**      (*get_preset_names)    (GstPreset *preset);
+
+  gchar**      (*get_property_names)  (GstPreset *preset);
+
+  gboolean     (*load_preset)         (GstPreset *preset, const gchar *name);
+  gboolean     (*save_preset)         (GstPreset *preset, const gchar *name);
+  gboolean     (*rename_preset)       (GstPreset *preset, const gchar *old_name,
+                                       const gchar *new_name);
+  gboolean     (*delete_preset)       (GstPreset *preset, const gchar *name);
+
+  gboolean     (*set_meta)            (GstPreset *preset, const gchar *name,
+                                       const gchar *tag, const gchar *value);
+  gboolean     (*get_meta)            (GstPreset *preset, const gchar *name,
+                                       const gchar *tag, gchar **value);
+};
+
+

GstPreset interface.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GTypeInterface parent;

parent interface type.

 

get_preset_names ()

virtual method to get list of presets

 

get_property_names ()

virtual methods to get properties that are persistent

 

load_preset ()

virtual methods to load a preset into properties

 

save_preset ()

virtual methods to save properties into a preset

 

rename_preset ()

virtual methods to rename a preset

 

delete_preset ()

virtual methods to remove a preset

 

set_meta ()

virtual methods to set textual meta data to a preset

 

get_meta ()

virtual methods to get textual meta data from a preset

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstPromise.html b/docs/gst/html/GstPromise.html new file mode 100644 index 0000000..d03a719 --- /dev/null +++ b/docs/gst/html/GstPromise.html @@ -0,0 +1,598 @@ + + + + +GstPromise: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPromise

+

GstPromise — a miniobject for future/promise-like functionality

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstPromiseChangeFunc) () +
+GstPromise * + +gst_promise_new () +
+GstPromise * + +gst_promise_new_with_change_func () +
+GstPromise * + +gst_promise_ref () +
+void + +gst_promise_unref () +
+GstPromiseResult + +gst_promise_wait () +
+void + +gst_promise_reply () +
+void + +gst_promise_interrupt () +
+void + +gst_promise_expire () +
const GstStructure * + +gst_promise_get_reply () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
enumGstPromiseResult
structGstPromise
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstPromise
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

The GstPromise object implements the container for values that may +be available later. i.e. a Future or a Promise in

+https://en.wikipedia.org/wiki/Futures_and_promises

As with all Future/Promise-like functionality, there is the concept of the +producer of the value and the consumer of the value.

+

A GstPromise is created with gst_promise_new() by the consumer and passed +to the producer to avoid thread safety issues with the change callback. +A GstPromise can be replied to with a value (or an error) by the producer +with gst_promise_reply(). gst_promise_interrupt() is for the consumer to +indicate to the producer that the value is not needed anymore and producing +that value can stop. The GST_PROMISE_RESULT_EXPIRED + state set by a call +to gst_promise_expire() indicates to the consumer that a value will never +be produced and is intended to be called by a third party that implements +some notion of message handling such as GstBus. +A callback can also be installed at GstPromise creation for +result changes with gst_promise_new_with_change_func(). +The change callback can be used to chain GstPromises's together as in the +following example.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
const GstStructure *reply;
+GstPromise *p;
+if (gst_promise_wait (promise) != GST_PROMISE_RESULT_REPLIED)
+  return; // interrupted or expired value
+reply = gst_promise_get_reply (promise);
+if (error in reply)
+  return; // propagate error
+p = gst_promise_new_with_change_func (another_promise_change_func, user_data, notify);
+pass p to promise-using API
+
+ +

+

Each GstPromise starts out with a GstPromiseResult of +GST_PROMISE_RESULT_PENDING and only ever transitions once +into one of the other GstPromiseResult's.

+

In order to support multi-threaded code, gst_promise_reply(), +gst_promise_interrupt() and gst_promise_expire() may all be from +different threads with some restrictions and the final result of the promise +is whichever call is made first. There are two restrictions on ordering:

+
    +
  1. That gst_promise_reply() and gst_promise_interrupt() cannot be called +after gst_promise_expire()

  2. +
  3. That gst_promise_reply() and gst_promise_interrupt() +cannot be called twice.

  4. +
+

The change function set with gst_promise_new_with_change_func() is +called directly from either the gst_promise_reply(), +gst_promise_interrupt() or gst_promise_expire() and can be called +from an arbitrary thread. GstPromise using APIs can restrict this to +a single thread or a subset of threads but that is entirely up to the API +that uses GstPromise.

+
+
+

Functions

+
+

GstPromiseChangeFunc ()

+
void
+(*GstPromiseChangeFunc) (GstPromise *promise,
+                         gpointer user_data);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

promise

a GstPromise

 

user_data

user data.

[closure]
+
+

Since: 1.14

+
+
+
+

gst_promise_new ()

+
GstPromise *
+gst_promise_new (void);
+
+

Returns

+

a new GstPromise

+
+

Since: 1.14

+
+
+
+

gst_promise_new_with_change_func ()

+
GstPromise *
+gst_promise_new_with_change_func (GstPromiseChangeFunc func,
+                                  gpointer user_data,
+                                  GDestroyNotify notify);
+

func + will be called exactly once when transitioning out of +GST_PROMISE_RESULT_PENDING into any of the other GstPromiseResult +states.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

func

a GstPromiseChangeFunc to call.

[scope notified]

user_data

argument to call func +with.

[closure]

notify

notification function that user_data +is no longer needed

 
+
+
+

Returns

+

a new GstPromise

+
+

Since: 1.14

+
+
+
+

gst_promise_ref ()

+
GstPromise *
+gst_promise_ref (GstPromise *promise);
+

Increases the refcount of the given promise + by one.

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise.

 
+
+
+

Returns

+

promise +.

+

[transfer full]

+
+

Since: 1.14

+
+
+
+

gst_promise_unref ()

+
void
+gst_promise_unref (GstPromise *promise);
+

Decreases the refcount of the promise. If the refcount reaches 0, the +promise will be freed.

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise.

[transfer full]
+
+

Since: 1.14

+
+
+
+

gst_promise_wait ()

+
GstPromiseResult
+gst_promise_wait (GstPromise *promise);
+

Wait for promise + to move out of the GST_PROMISE_RESULT_PENDING state. +If promise + is not in GST_PROMISE_RESULT_PENDING then it will return +immediately with the current result.

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise

 
+
+
+

Returns

+

the result of the promise

+
+

Since: 1.14

+
+
+
+

gst_promise_reply ()

+
void
+gst_promise_reply (GstPromise *promise,
+                   GstStructure *s);
+

Set a reply on promise +. This will wake up any waiters with +GST_PROMISE_RESULT_REPLIED. Called by the producer of the value to +indicate success (or failure).

+

If promise + has already been interrupted by the consumer, then this reply +is not visible to the consumer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

promise

a GstPromise.

[allow-none]

s

a GstStructure with the the reply contents.

[transfer full]
+
+

Since: 1.14

+
+
+
+

gst_promise_interrupt ()

+
void
+gst_promise_interrupt (GstPromise *promise);
+

Interrupt waiting for a promise +. This will wake up any waiters with +GST_PROMISE_RESULT_INTERRUPTED. Called when the consumer does not want +the value produced anymore.

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise

 
+
+

Since: 1.14

+
+
+
+

gst_promise_expire ()

+
void
+gst_promise_expire (GstPromise *promise);
+

Expire a promise +. This will wake up any waiters with +GST_PROMISE_RESULT_EXPIRED. Called by a message loop when the parent +message is handled and/or destroyed (possibly unanswered).

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise

 
+
+

Since: 1.14

+
+
+
+

gst_promise_get_reply ()

+
const GstStructure *
+gst_promise_get_reply (GstPromise *promise);
+

Retrieve the reply set on promise +. promise + must be in +GST_PROMISE_RESULT_REPLIED and the returned structure is owned by promise +

+
+

Parameters

+
+++++ + + + + + +

promise

a GstPromise

 
+
+
+

Returns

+

The reply set on promise +.

+

[transfer none]

+
+

Since: 1.14

+
+
+
+

Types and Values

+
+

enum GstPromiseResult

+

The result of a GstPromise

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_PROMISE_RESULT_PENDING

+

Initial state. Waiting for transition to any + other state.

+
 

GST_PROMISE_RESULT_INTERRUPTED

+

Interrupted by the consumer as it doesn't + want the value anymore.

+
 

GST_PROMISE_RESULT_REPLIED

+

A producer marked a reply

+
 

GST_PROMISE_RESULT_EXPIRED

+

The promise expired (the carrying object + lost all refs) and the promise will never be fulfilled.

+
 
+
+

Since: 1.14

+
+
+
+

struct GstPromise

+
struct GstPromise {
+  GstMiniObject         parent;
+};
+
+
+

Members

+
+++++ + + + + + +

GstMiniObject parent;

parent GstMiniObject

 
+
+

Since: 1.14

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstQuery.html b/docs/gst/html/GstQuery.html new file mode 100644 index 0000000..829d165 --- /dev/null +++ b/docs/gst/html/GstQuery.html @@ -0,0 +1,4636 @@ + + + + +GstQuery: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstQuery

+

GstQuery — Provide functions to create queries, and to set and parse + values in them.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_QUERY_MAKE_TYPE() +
#define +GST_QUERY_TYPE() +
#define +GST_QUERY_TYPE_NAME() +
#define +GST_QUERY_IS_UPSTREAM() +
#define +GST_QUERY_IS_DOWNSTREAM() +
#define +GST_QUERY_IS_SERIALIZED() +
+GstQueryTypeFlags + +gst_query_type_get_flags () +
const gchar * + +gst_query_type_get_name () +
+GQuark + +gst_query_type_to_quark () +
+GstQuery * + +gst_query_ref () +
+void + +gst_query_unref () +
+GstQuery * + +gst_query_copy () +
#define +gst_query_make_writable() +
#define +gst_query_is_writable() +
+gboolean + +gst_query_replace () +
+GstStructure * + +gst_query_writable_structure () +
+GstQuery * + +gst_query_new_custom () +
const GstStructure * + +gst_query_get_structure () +
+GstQuery * + +gst_query_new_convert () +
+void + +gst_query_set_convert () +
+void + +gst_query_parse_convert () +
+GstQuery * + +gst_query_new_position () +
+void + +gst_query_set_position () +
+void + +gst_query_parse_position () +
+GstQuery * + +gst_query_new_duration () +
+void + +gst_query_set_duration () +
+void + +gst_query_parse_duration () +
+GstQuery * + +gst_query_new_latency () +
+void + +gst_query_parse_latency () +
+void + +gst_query_set_latency () +
+GstQuery * + +gst_query_new_seeking () +
+void + +gst_query_set_seeking () +
+void + +gst_query_parse_seeking () +
+GstQuery * + +gst_query_new_formats () +
+void + +gst_query_set_formats () +
+void + +gst_query_set_formatsv () +
+void + +gst_query_parse_n_formats () +
+void + +gst_query_parse_nth_format () +
+GstQuery * + +gst_query_new_segment () +
+void + +gst_query_set_segment () +
+void + +gst_query_parse_segment () +
+GstQuery * + +gst_query_new_caps () +
+void + +gst_query_parse_caps () +
+void + +gst_query_set_caps_result () +
+void + +gst_query_parse_caps_result () +
+GstQuery * + +gst_query_new_accept_caps () +
+void + +gst_query_parse_accept_caps () +
+void + +gst_query_set_accept_caps_result () +
+void + +gst_query_parse_accept_caps_result () +
+GstQuery * + +gst_query_new_buffering () +
+void + +gst_query_set_buffering_percent () +
+void + +gst_query_parse_buffering_percent () +
+void + +gst_query_set_buffering_stats () +
+void + +gst_query_parse_buffering_stats () +
+void + +gst_query_set_buffering_range () +
+void + +gst_query_parse_buffering_range () +
+gboolean + +gst_query_add_buffering_range () +
+guint + +gst_query_get_n_buffering_ranges () +
+gboolean + +gst_query_parse_nth_buffering_range () +
+GstQuery * + +gst_query_new_uri () +
+void + +gst_query_parse_uri () +
+void + +gst_query_set_uri () +
+void + +gst_query_parse_uri_redirection () +
+void + +gst_query_set_uri_redirection () +
+void + +gst_query_parse_uri_redirection_permanent () +
+void + +gst_query_set_uri_redirection_permanent () +
+GstQuery * + +gst_query_new_allocation () +
+void + +gst_query_parse_allocation () +
+void + +gst_query_add_allocation_pool () +
+guint + +gst_query_get_n_allocation_pools () +
+void + +gst_query_parse_nth_allocation_pool () +
+void + +gst_query_set_nth_allocation_pool () +
+void + +gst_query_remove_nth_allocation_pool () +
+void + +gst_query_add_allocation_param () +
+guint + +gst_query_get_n_allocation_params () +
+void + +gst_query_parse_nth_allocation_param () +
+void + +gst_query_set_nth_allocation_param () +
+void + +gst_query_remove_nth_allocation_param () +
+void + +gst_query_add_allocation_meta () +
+guint + +gst_query_get_n_allocation_metas () +
+GType + +gst_query_parse_nth_allocation_meta () +
+void + +gst_query_remove_nth_allocation_meta () +
+gboolean + +gst_query_find_allocation_meta () +
+GstQuery * + +gst_query_new_scheduling () +
+void + +gst_query_parse_scheduling () +
+void + +gst_query_set_scheduling () +
+void + +gst_query_add_scheduling_mode () +
+guint + +gst_query_get_n_scheduling_modes () +
+GstPadMode + +gst_query_parse_nth_scheduling_mode () +
+gboolean + +gst_query_has_scheduling_mode () +
+gboolean + +gst_query_has_scheduling_mode_with_flags () +
+GstQuery * + +gst_query_new_drain () +
+GstQuery * + +gst_query_new_context () +
+void + +gst_query_set_context () +
+void + +gst_query_parse_context () +
+gboolean + +gst_query_parse_context_type () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstQuery
enumGstQueryTypeFlags
#defineGST_QUERY_TYPE_BOTH
enumGstQueryType
enumGstBufferingMode
enumGstSchedulingFlags
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstQuery
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Queries can be performed on pads (gst_pad_query()) and elements +(gst_element_query()). Please note that some queries might need a running +pipeline to work.

+

Queries can be created using the gst_query_new_*() functions. +Query values can be set using gst_query_set_*(), and parsed using +gst_query_parse_*() helpers.

+

The following example shows how to query the duration of a pipeline:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
GstQuery *query;
+gboolean res;
+query = gst_query_new_duration (GST_FORMAT_TIME);
+res = gst_element_query (pipeline, query);
+if (res) {
+  gint64 duration;
+  gst_query_parse_duration (query, NULL, &duration);
+  g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
+} else {
+  g_print ("duration query failed...");
+}
+gst_query_unref (query);
+
+ +

+
+
+

Functions

+
+

GST_QUERY_MAKE_TYPE()

+
#define             GST_QUERY_MAKE_TYPE(num,flags)
+

when making custom query types, use this macro with the num and +the given flags

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

num

the query number to create

 

flags

the query flags

 
+
+
+
+
+

GST_QUERY_TYPE()

+
#define GST_QUERY_TYPE(query)  (((GstQuery*)(query))->type)
+
+

Get the GstQueryType of the query.

+
+

Parameters

+
+++++ + + + + + +

query

the query to query

 
+
+
+
+
+

GST_QUERY_TYPE_NAME()

+
#define GST_QUERY_TYPE_NAME(query) (gst_query_type_get_name(GST_QUERY_TYPE(query)))
+
+

Get a constant string representation of the GstQueryType of the query.

+
+

Parameters

+
+++++ + + + + + +

query

the query to query

 
+
+
+
+
+

GST_QUERY_IS_UPSTREAM()

+
#define GST_QUERY_IS_UPSTREAM(ev)       !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_UPSTREAM)
+
+

Check if an query can travel upstream.

+
+

Parameters

+
+++++ + + + + + +

ev

the query to query

 
+
+
+
+
+

GST_QUERY_IS_DOWNSTREAM()

+
#define GST_QUERY_IS_DOWNSTREAM(ev)     !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_DOWNSTREAM)
+
+

Check if an query can travel downstream.

+
+

Parameters

+
+++++ + + + + + +

ev

the query to query

 
+
+
+
+
+

GST_QUERY_IS_SERIALIZED()

+
#define GST_QUERY_IS_SERIALIZED(ev)     !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_SERIALIZED)
+
+

Check if an query is serialized with the data stream.

+
+

Parameters

+
+++++ + + + + + +

ev

the query to query

 
+
+
+
+
+

gst_query_type_get_flags ()

+
GstQueryTypeFlags
+gst_query_type_get_flags (GstQueryType type);
+

Gets the GstQueryTypeFlags associated with type +.

+
+

Parameters

+
+++++ + + + + + +

type

a GstQueryType

 
+
+
+

Returns

+

a GstQueryTypeFlags.

+
+
+
+
+

gst_query_type_get_name ()

+
const gchar *
+gst_query_type_get_name (GstQueryType type);
+

Get a printable name for the given query type. Do not modify or free.

+
+

Parameters

+
+++++ + + + + + +

type

the query type

 
+
+
+

Returns

+

a reference to the static name of the query.

+
+
+
+
+

gst_query_type_to_quark ()

+
GQuark
+gst_query_type_to_quark (GstQueryType type);
+

Get the unique quark for the given query type.

+
+

Parameters

+
+++++ + + + + + +

type

the query type

 
+
+
+

Returns

+

the quark associated with the query type

+
+
+
+
+

gst_query_ref ()

+
GstQuery *
+gst_query_ref (GstQuery *q);
+

Increases the refcount of the given query by one.

+
+

Parameters

+
+++++ + + + + + +

q

a GstQuery to increase the refcount of.

 
+
+
+

Returns

+

q +

+
+
+
+
+

gst_query_unref ()

+
void
+gst_query_unref (GstQuery *q);
+

Decreases the refcount of the query. If the refcount reaches 0, the query +will be freed.

+
+

Parameters

+
+++++ + + + + + +

q

a GstQuery to decrease the refcount of.

 
+
+
+
+
+

gst_query_copy ()

+
GstQuery *
+gst_query_copy (const GstQuery *q);
+

Copies the given query using the copy function of the parent GstStructure.

+

Free-function: gst_query_unref

+
+

Parameters

+
+++++ + + + + + +

q

a GstQuery to copy.

 
+
+
+

Returns

+

a new copy of q +.

+

[transfer full]

+
+
+
+
+

gst_query_make_writable()

+
#define         gst_query_make_writable(q)      GST_QUERY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (q)))
+
+

Makes a writable query from the given query.

+
+

Parameters

+
+++++ + + + + + +

q

a GstQuery to make writable.

[transfer full]
+
+
+

Returns

+

a new writable query (possibly same as q +).

+

[transfer full]

+
+
+
+
+

gst_query_is_writable()

+
#define         gst_query_is_writable(q)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (q))
+
+

Tests if you can safely write data into a query's structure.

+
+

Parameters

+
+++++ + + + + + +

q

a GstQuery

 
+
+
+
+
+

gst_query_replace ()

+
gboolean
+gst_query_replace (GstQuery **old_query,
+                   GstQuery *new_query);
+

Modifies a pointer to a GstQuery to point to a different GstQuery. The +modification is done atomically (so this is useful for ensuring thread safety +in some cases), and the reference counts are updated appropriately (the old +query is unreffed, the new one is reffed).

+

Either new_query + or the GstQuery pointed to by old_query + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

old_query

pointer to a pointer to a +GstQuery to be replaced.

[inout][transfer full][nullable]

new_query

pointer to a GstQuery that will +replace the query pointed to by old_query +.

[allow-none][transfer none]
+
+
+

Returns

+

TRUE if new_query +was different from old_query +

+
+
+
+
+

gst_query_writable_structure ()

+
GstStructure *
+gst_query_writable_structure (GstQuery *query);
+

Get the structure of a query. This method should be called with a writable +query + so that the returned structure is guaranteed to be writable.

+
+

Parameters

+
+++++ + + + + + +

query

a GstQuery

 
+
+
+

Returns

+

the GstStructure of the query. The structure is +still owned by the query and will therefore be freed when the query +is unreffed.

+

[transfer none]

+
+
+
+
+

gst_query_new_custom ()

+
GstQuery *
+gst_query_new_custom (GstQueryType type,
+                      GstStructure *structure);
+

Constructs a new custom query object. Use gst_query_unref() +when done with it.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

the query type

 

structure

a structure for the query.

[allow-none][transfer full]
+
+
+

Returns

+

a new GstQuery.

+

[transfer full][nullable]

+
+
+
+
+

gst_query_get_structure ()

+
const GstStructure *
+gst_query_get_structure (GstQuery *query);
+

Get the structure of a query.

+
+

Parameters

+
+++++ + + + + + +

query

a GstQuery

 
+
+
+

Returns

+

the GstStructure of the query. The +structure is still owned by the query and will therefore be freed when the +query is unreffed.

+

[transfer none][nullable]

+
+
+
+
+

gst_query_new_convert ()

+
GstQuery *
+gst_query_new_convert (GstFormat src_format,
+                       gint64 value,
+                       GstFormat dest_format);
+

Constructs a new convert query object. Use gst_query_unref() +when done with it. A convert query is used to ask for a conversion between +one format and another.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src_format

the source GstFormat for the new query

 

value

the value to convert

 

dest_format

the target GstFormat

 
+
+
+

Returns

+

a GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_convert ()

+
void
+gst_query_set_convert (GstQuery *query,
+                       GstFormat src_format,
+                       gint64 src_value,
+                       GstFormat dest_format,
+                       gint64 dest_value);
+

Answer a convert query by setting the requested values.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

src_format

the source GstFormat

 

src_value

the source value

 

dest_format

the destination GstFormat

 

dest_value

the destination value

 
+
+
+
+
+

gst_query_parse_convert ()

+
void
+gst_query_parse_convert (GstQuery *query,
+                         GstFormat *src_format,
+                         gint64 *src_value,
+                         GstFormat *dest_format,
+                         gint64 *dest_value);
+

Parse a convert query answer. Any of src_format +, src_value +, dest_format +, +and dest_value + may be NULL, in which case that value is omitted.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

src_format

the storage for the GstFormat of the +source value, or NULL.

[out][allow-none]

src_value

the storage for the source value, or NULL.

[out][allow-none]

dest_format

the storage for the GstFormat of the +destination value, or NULL.

[out][allow-none]

dest_value

the storage for the destination value, +or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_new_position ()

+
GstQuery *
+gst_query_new_position (GstFormat format);
+

Constructs a new query stream position query object. Use gst_query_unref() +when done with it. A position query is used to query the current position +of playback in the streams, in some format.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

format

the default GstFormat for the new query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_position ()

+
void
+gst_query_set_position (GstQuery *query,
+                        GstFormat format,
+                        gint64 cur);
+

Answer a position query by setting the requested value in the given format.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery with query type GST_QUERY_POSITION

 

format

the requested GstFormat

 

cur

the position to set

 
+
+
+
+
+

gst_query_parse_position ()

+
void
+gst_query_parse_position (GstQuery *query,
+                          GstFormat *format,
+                          gint64 *cur);
+

Parse a position query, writing the format into format +, and the position +into cur +, if the respective parameters are non-NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

format

the storage for the GstFormat of the +position values (may be NULL).

[out][allow-none]

cur

the storage for the current position (may be NULL).

[out][allow-none]
+
+
+
+
+

gst_query_new_duration ()

+
GstQuery *
+gst_query_new_duration (GstFormat format);
+

Constructs a new stream duration query object to query in the given format. +Use gst_query_unref() when done with it. A duration query will give the +total length of the stream.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

format

the GstFormat for this duration query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_duration ()

+
void
+gst_query_set_duration (GstQuery *query,
+                        GstFormat format,
+                        gint64 duration);
+

Answer a duration query by setting the requested value in the given format.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

format

the GstFormat for the duration

 

duration

the duration of the stream

 
+
+
+
+
+

gst_query_parse_duration ()

+
void
+gst_query_parse_duration (GstQuery *query,
+                          GstFormat *format,
+                          gint64 *duration);
+

Parse a duration query answer. Write the format of the duration into format +, +and the value into duration +, if the respective variables are non-NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

format

the storage for the GstFormat of the duration +value, or NULL.

[out][allow-none]

duration

the storage for the total duration, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_new_latency ()

+
GstQuery *
+gst_query_new_latency (void);
+

Constructs a new latency query object. +Use gst_query_unref() when done with it. A latency query is usually performed +by sinks to compensate for additional latency introduced by elements in the +pipeline.

+

Free-function: gst_query_unref()

+
+

Returns

+

a GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_latency ()

+
void
+gst_query_parse_latency (GstQuery *query,
+                         gboolean *live,
+                         GstClockTime *min_latency,
+                         GstClockTime *max_latency);
+

Parse a latency query answer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

live

storage for live or NULL.

[out][allow-none]

min_latency

the storage for the min latency or NULL.

[out][allow-none]

max_latency

the storage for the max latency or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_set_latency ()

+
void
+gst_query_set_latency (GstQuery *query,
+                       gboolean live,
+                       GstClockTime min_latency,
+                       GstClockTime max_latency);
+

Answer a latency query by setting the requested values in the given format.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

live

if there is a live element upstream

 

min_latency

the minimal latency of the upstream elements

 

max_latency

the maximal latency of the upstream elements

 
+
+
+
+
+

gst_query_new_seeking ()

+
GstQuery *
+gst_query_new_seeking (GstFormat format);
+

Constructs a new query object for querying seeking properties of +the stream.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

format

the default GstFormat for the new query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_seeking ()

+
void
+gst_query_set_seeking (GstQuery *query,
+                       GstFormat format,
+                       gboolean seekable,
+                       gint64 segment_start,
+                       gint64 segment_end);
+

Set the seeking query result fields in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

format

the format to set for the segment_start +and segment_end +values

 

seekable

the seekable flag to set

 

segment_start

the segment_start to set

 

segment_end

the segment_end to set

 
+
+
+
+
+

gst_query_parse_seeking ()

+
void
+gst_query_parse_seeking (GstQuery *query,
+                         GstFormat *format,
+                         gboolean *seekable,
+                         gint64 *segment_start,
+                         gint64 *segment_end);
+

Parse a seeking query, writing the format into format +, and +other results into the passed parameters, if the respective parameters +are non-NULL

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_SEEKING type query GstQuery

 

format

the format to set for the segment_start +and segment_end +values, or NULL.

[out][allow-none]

seekable

the seekable flag to set, or NULL.

[out][allow-none]

segment_start

the segment_start to set, or NULL.

[out][allow-none]

segment_end

the segment_end to set, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_new_formats ()

+
GstQuery *
+gst_query_new_formats (void);
+

Constructs a new query object for querying formats of +the stream.

+

Free-function: gst_query_unref()

+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_formats ()

+
void
+gst_query_set_formats (GstQuery *query,
+                       gint n_formats,
+                       ...);
+

Set the formats query result fields in query +. The number of formats passed +must be equal to n_formats +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

n_formats

the number of formats to set.

 

...

A number of GstFormats +equal to n_formats +.

 
+
+
+
+
+

gst_query_set_formatsv ()

+
void
+gst_query_set_formatsv (GstQuery *query,
+                        gint n_formats,
+                        const GstFormat *formats);
+

Set the formats query result fields in query +. The number of formats passed +in the formats + array must be equal to n_formats +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

n_formats

the number of formats to set.

 

formats

an array containing n_formats +GstFormat +values.

[in][array length=n_formats]
+
+
+
+
+

gst_query_parse_n_formats ()

+
void
+gst_query_parse_n_formats (GstQuery *query,
+                           guint *n_formats);
+

Parse the number of formats in the formats query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery

 

n_formats

the number of formats in this query.

[out][allow-none]
+
+
+
+
+

gst_query_parse_nth_format ()

+
void
+gst_query_parse_nth_format (GstQuery *query,
+                            guint nth,
+                            GstFormat *format);
+

Parse the format query and retrieve the nth + format from it into +format +. If the list contains less elements than nth +, format + will be +set to GST_FORMAT_UNDEFINED.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

nth

the nth format to retrieve.

 

format

a pointer to store the nth format.

[out][allow-none]
+
+
+
+
+

gst_query_new_segment ()

+
GstQuery *
+gst_query_new_segment (GstFormat format);
+

Constructs a new segment query object. Use gst_query_unref() +when done with it. A segment query is used to discover information about the +currently configured segment for playback.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

format

the GstFormat for the new query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_segment ()

+
void
+gst_query_set_segment (GstQuery *query,
+                       gdouble rate,
+                       GstFormat format,
+                       gint64 start_value,
+                       gint64 stop_value);
+

Answer a segment query by setting the requested values. The normal +playback segment of a pipeline is 0 to duration at the default rate of +1.0. If a seek was performed on the pipeline to play a different +segment, this query will return the range specified in the last seek.

+

start_value + and stop_value + will respectively contain the configured +playback range start and stop values expressed in format +. +The values are always between 0 and the duration of the media and +start_value + <= stop_value +. rate + will contain the playback rate. For +negative rates, playback will actually happen from stop_value + to +start_value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

rate

the rate of the segment

 

format

the GstFormat of the segment values (start_value +and stop_value +)

 

start_value

the start value

 

stop_value

the stop value

 
+
+
+
+
+

gst_query_parse_segment ()

+
void
+gst_query_parse_segment (GstQuery *query,
+                         gdouble *rate,
+                         GstFormat *format,
+                         gint64 *start_value,
+                         gint64 *stop_value);
+

Parse a segment query answer. Any of rate +, format +, start_value +, and +stop_value + may be NULL, which will cause this value to be omitted.

+

See gst_query_set_segment() for an explanation of the function arguments.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

rate

the storage for the rate of the segment, or NULL.

[out][allow-none]

format

the storage for the GstFormat of the values, +or NULL.

[out][allow-none]

start_value

the storage for the start value, or NULL.

[out][allow-none]

stop_value

the storage for the stop value, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_new_caps ()

+
GstQuery *
+gst_query_new_caps (GstCaps *filter);
+

Constructs a new query object for querying the caps.

+

The CAPS query should return the allowable caps for a pad in the context +of the element's state, its link to other elements, and the devices or files +it has opened. These caps must be a subset of the pad template caps. In the +NULL state with no links, the CAPS query should ideally return the same caps +as the pad template. In rare circumstances, an object property can affect +the caps returned by the CAPS query, but this is discouraged.

+

For most filters, the caps returned by CAPS query is directly affected by the +allowed caps on other pads. For demuxers and decoders, the caps returned by +the srcpad's getcaps function is directly related to the stream data. Again, +the CAPS query should return the most specific caps it reasonably can, since this +helps with autoplugging.

+

The filter + is used to restrict the result caps, only the caps matching +filter + should be returned from the CAPS query. Specifying a filter might +greatly reduce the amount of processing an element needs to do.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

filter

a filter

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_caps ()

+
void
+gst_query_parse_caps (GstQuery *query,
+                      GstCaps **filter);
+

Get the filter from the caps query +. The caps remains valid as long as +query + remains valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

The query to parse

 

filter

A pointer to the caps filter.

[out][transfer none]
+
+
+
+
+

gst_query_set_caps_result ()

+
void
+gst_query_set_caps_result (GstQuery *query,
+                           GstCaps *caps);
+

Set the caps + result in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

The query to use

 

caps

A pointer to the caps.

[in]
+
+
+
+
+

gst_query_parse_caps_result ()

+
void
+gst_query_parse_caps_result (GstQuery *query,
+                             GstCaps **caps);
+

Get the caps result from query +. The caps remains valid as long as +query + remains valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

The query to parse

 

caps

A pointer to the caps.

[out][transfer none]
+
+
+
+
+

gst_query_new_accept_caps ()

+
GstQuery *
+gst_query_new_accept_caps (GstCaps *caps);
+

Constructs a new query object for querying if caps + are accepted.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

caps

a fixed GstCaps

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_accept_caps ()

+
void
+gst_query_parse_accept_caps (GstQuery *query,
+                             GstCaps **caps);
+

Get the caps from query +. The caps remains valid as long as query + remains +valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

The query to parse

 

caps

A pointer to the caps.

[out][transfer none]
+
+
+
+
+

gst_query_set_accept_caps_result ()

+
void
+gst_query_set_accept_caps_result (GstQuery *query,
+                                  gboolean result);
+

Set result + as the result for the query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_ACCEPT_CAPS type query GstQuery

 

result

the result to set

 
+
+
+
+
+

gst_query_parse_accept_caps_result ()

+
void
+gst_query_parse_accept_caps_result (GstQuery *query,
+                                    gboolean *result);
+

Parse the result from query + and store in result +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_ACCEPT_CAPS type query GstQuery

 

result

location for the result.

[out][allow-none]
+
+
+
+
+

gst_query_new_buffering ()

+
GstQuery *
+gst_query_new_buffering (GstFormat format);
+

Constructs a new query object for querying the buffering status of +a stream.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

format

the default GstFormat for the new query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_set_buffering_percent ()

+
void
+gst_query_set_buffering_percent (GstQuery *query,
+                                 gboolean busy,
+                                 gint percent);
+

Set the percentage of buffered data. This is a value between 0 and 100. +The busy + indicator is TRUE when the buffering is in progress.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_BUFFERING.

 

busy

if buffering is busy

 

percent

a buffering percent

 
+
+
+
+
+

gst_query_parse_buffering_percent ()

+
void
+gst_query_parse_buffering_percent (GstQuery *query,
+                                   gboolean *busy,
+                                   gint *percent);
+

Get the percentage of buffered data. This is a value between 0 and 100. +The busy + indicator is TRUE when the buffering is in progress.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_BUFFERING.

 

busy

if buffering is busy, or NULL.

[out][allow-none]

percent

a buffering percent, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_set_buffering_stats ()

+
void
+gst_query_set_buffering_stats (GstQuery *query,
+                               GstBufferingMode mode,
+                               gint avg_in,
+                               gint avg_out,
+                               gint64 buffering_left);
+

Configures the buffering stats values in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_BUFFERING.

 

mode

a buffering mode

 

avg_in

the average input rate

 

avg_out

the average output rate

 

buffering_left

amount of buffering time left in milliseconds

 
+
+
+
+
+

gst_query_parse_buffering_stats ()

+
void
+gst_query_parse_buffering_stats (GstQuery *query,
+                                 GstBufferingMode *mode,
+                                 gint *avg_in,
+                                 gint *avg_out,
+                                 gint64 *buffering_left);
+

Extracts the buffering stats values from query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_BUFFERING.

 

mode

a buffering mode, or NULL.

[out][allow-none]

avg_in

the average input rate, or NULL.

[out][allow-none]

avg_out

the average output rat, or NULL.

[out][allow-none]

buffering_left

amount of buffering time left in +milliseconds, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_set_buffering_range ()

+
void
+gst_query_set_buffering_range (GstQuery *query,
+                               GstFormat format,
+                               gint64 start,
+                               gint64 stop,
+                               gint64 estimated_total);
+

Set the available query result fields in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

format

the format to set for the start +and stop +values

 

start

the start to set

 

stop

the stop to set

 

estimated_total

estimated total amount of download time remaining in +milliseconds

 
+
+
+
+
+

gst_query_parse_buffering_range ()

+
void
+gst_query_parse_buffering_range (GstQuery *query,
+                                 GstFormat *format,
+                                 gint64 *start,
+                                 gint64 *stop,
+                                 gint64 *estimated_total);
+

Parse an available query, writing the format into format +, and +other results into the passed parameters, if the respective parameters +are non-NULL

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_BUFFERING type query GstQuery

 

format

the format to set for the segment_start +and segment_end +values, or NULL.

[out][allow-none]

start

the start to set, or NULL.

[out][allow-none]

stop

the stop to set, or NULL.

[out][allow-none]

estimated_total

estimated total amount of download +time remaining in milliseconds, or NULL.

[out][allow-none]
+
+
+
+
+

gst_query_add_buffering_range ()

+
gboolean
+gst_query_add_buffering_range (GstQuery *query,
+                               gint64 start,
+                               gint64 stop);
+

Set the buffering-ranges array field in query +. The current last +start position of the array should be inferior to start +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_BUFFERING type query GstQuery

 

start

start position of the range

 

stop

stop position of the range

 
+
+
+

Returns

+

a gboolean indicating if the range was added or not.

+
+
+
+
+

gst_query_get_n_buffering_ranges ()

+
guint
+gst_query_get_n_buffering_ranges (GstQuery *query);
+

Retrieve the number of values currently stored in the +buffered-ranges array of the query's structure.

+
+

Parameters

+
+++++ + + + + + +

query

a GST_QUERY_BUFFERING type query GstQuery

 
+
+
+

Returns

+

the range array size as a guint.

+
+
+
+
+

gst_query_parse_nth_buffering_range ()

+
gboolean
+gst_query_parse_nth_buffering_range (GstQuery *query,
+                                     guint index,
+                                     gint64 *start,
+                                     gint64 *stop);
+

Parse an available query and get the start and stop values stored +at the index + of the buffered ranges array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_BUFFERING type query GstQuery

 

index

position in the buffered-ranges array to read

 

start

the start position to set, or NULL.

[out][allow-none]

stop

the stop position to set, or NULL.

[out][allow-none]
+
+
+

Returns

+

a gboolean indicating if the parsing succeeded.

+
+
+
+
+

gst_query_new_uri ()

+
GstQuery *
+gst_query_new_uri (void);
+

Constructs a new query URI query object. Use gst_query_unref() +when done with it. An URI query is used to query the current URI +that is used by the source or sink.

+

Free-function: gst_query_unref()

+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_uri ()

+
void
+gst_query_parse_uri (GstQuery *query,
+                     gchar **uri);
+

Parse an URI query, writing the URI into uri + as a newly +allocated string, if the respective parameters are non-NULL. +Free the string with g_free() after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery

 

uri

the storage for the current URI +(may be NULL).

[out][transfer full][allow-none]
+
+
+
+
+

gst_query_set_uri ()

+
void
+gst_query_set_uri (GstQuery *query,
+                   const gchar *uri);
+

Answer a URI query by setting the requested URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery with query type GST_QUERY_URI

 

uri

the URI to set

 
+
+
+
+
+

gst_query_parse_uri_redirection ()

+
void
+gst_query_parse_uri_redirection (GstQuery *query,
+                                 gchar **uri);
+

Parse an URI query, writing the URI into uri + as a newly +allocated string, if the respective parameters are non-NULL. +Free the string with g_free() after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery

 

uri

the storage for the redirect URI +(may be NULL).

[out][transfer full][allow-none]
+
+

Since: 1.2

+
+
+
+

gst_query_set_uri_redirection ()

+
void
+gst_query_set_uri_redirection (GstQuery *query,
+                               const gchar *uri);
+

Answer a URI query by setting the requested URI redirection.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery with query type GST_QUERY_URI

 

uri

the URI to set

 
+
+

Since: 1.2

+
+
+
+

gst_query_parse_uri_redirection_permanent ()

+
void
+gst_query_parse_uri_redirection_permanent
+                               (GstQuery *query,
+                                gboolean *permanent);
+

Parse an URI query, and set permanent + to TRUE if there is a redirection +and it should be considered permanent. If a redirection is permanent, +applications should update their internal storage of the URI, otherwise +they should make all future requests to the original URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery

 

permanent

if the URI redirection is permanent +(may be NULL).

[out][allow-none]
+
+

Since: 1.4

+
+
+
+

gst_query_set_uri_redirection_permanent ()

+
void
+gst_query_set_uri_redirection_permanent
+                               (GstQuery *query,
+                                gboolean permanent);
+

Answer a URI query by setting the requested URI redirection +to permanent or not.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery with query type GST_QUERY_URI

 

permanent

whether the redirect is permanent or not

 
+
+

Since: 1.4

+
+
+
+

gst_query_new_allocation ()

+
GstQuery *
+gst_query_new_allocation (GstCaps *caps,
+                          gboolean need_pool);
+

Constructs a new query object for querying the allocation properties.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps

the negotiated caps

 

need_pool

return a pool

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_allocation ()

+
void
+gst_query_parse_allocation (GstQuery *query,
+                            GstCaps **caps,
+                            gboolean *need_pool);
+

Parse an allocation query, writing the requested caps in caps + and +whether a pool is needed in need_pool +, if the respective parameters +are non-NULL.

+

Pool details can be retrieved using gst_query_get_n_allocation_pools() and +gst_query_parse_nth_allocation_pool().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GstQuery

 

caps

The GstCaps.

[out][transfer none][allow-none]

need_pool

Whether a GstBufferPool is needed.

[out][allow-none]
+
+
+
+
+

gst_query_add_allocation_pool ()

+
void
+gst_query_add_allocation_pool (GstQuery *query,
+                               GstBufferPool *pool,
+                               guint size,
+                               guint min_buffers,
+                               guint max_buffers);
+

Set the pool parameters in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_ALLOCATION.

 

pool

the GstBufferPool.

[transfer none][allow-none]

size

the buffer size

 

min_buffers

the min buffers

 

max_buffers

the max buffers

 
+
+
+
+
+

gst_query_get_n_allocation_pools ()

+
guint
+gst_query_get_n_allocation_pools (GstQuery *query);
+

Retrieve the number of values currently stored in the +pool array of the query's structure.

+
+

Parameters

+
+++++ + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 
+
+
+

Returns

+

the pool array size as a guint.

+
+
+
+
+

gst_query_parse_nth_allocation_pool ()

+
void
+gst_query_parse_nth_allocation_pool (GstQuery *query,
+                                     guint index,
+                                     GstBufferPool **pool,
+                                     guint *size,
+                                     guint *min_buffers,
+                                     guint *max_buffers);
+

Get the pool parameters in query +.

+

Unref pool + with gst_object_unref() when it's not needed any more.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_ALLOCATION.

 

index

index to parse

 

pool

the GstBufferPool.

[out][allow-none][transfer full]

size

the buffer size.

[out][allow-none]

min_buffers

the min buffers.

[out][allow-none]

max_buffers

the max buffers.

[out][allow-none]
+
+
+
+
+

gst_query_set_nth_allocation_pool ()

+
void
+gst_query_set_nth_allocation_pool (GstQuery *query,
+                                   guint index,
+                                   GstBufferPool *pool,
+                                   guint size,
+                                   guint min_buffers,
+                                   guint max_buffers);
+

Set the pool parameters in query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

index

index to modify

 

query

A valid GstQuery of type GST_QUERY_ALLOCATION.

 

pool

the GstBufferPool.

[transfer none][allow-none]

size

the buffer size

 

min_buffers

the min buffers

 

max_buffers

the max buffers

 
+
+
+
+
+

gst_query_remove_nth_allocation_pool ()

+
void
+gst_query_remove_nth_allocation_pool (GstQuery *query,
+                                      guint index);
+

Remove the allocation pool at index + of the allocation pool array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the allocation pool array to remove

 
+
+

Since: 1.2

+
+
+
+

gst_query_add_allocation_param ()

+
void
+gst_query_add_allocation_param (GstQuery *query,
+                                GstAllocator *allocator,
+                                const GstAllocationParams *params);
+

Add allocator + and its params + as a supported memory allocator.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

allocator

the memory allocator.

[transfer none][allow-none]

params

a GstAllocationParams.

[transfer none][allow-none]
+
+
+
+
+

gst_query_get_n_allocation_params ()

+
guint
+gst_query_get_n_allocation_params (GstQuery *query);
+

Retrieve the number of values currently stored in the +allocator params array of the query's structure.

+

If no memory allocator is specified, the downstream element can handle +the default memory allocator. The first memory allocator in the query +should be generic and allow mapping to system memory, all following +allocators should be ordered by preference with the preferred one first.

+
+

Parameters

+
+++++ + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 
+
+
+

Returns

+

the allocator array size as a guint.

+
+
+
+
+

gst_query_parse_nth_allocation_param ()

+
void
+gst_query_parse_nth_allocation_param (GstQuery *query,
+                                      guint index,
+                                      GstAllocator **allocator,
+                                      GstAllocationParams *params);
+

Parse an available query and get the allocator and its params +at index + of the allocator array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the allocator array to read

 

allocator

variable to hold the result.

[out][transfer full][allow-none]

params

parameters for the allocator.

[out][allow-none]
+
+
+
+
+

gst_query_set_nth_allocation_param ()

+
void
+gst_query_set_nth_allocation_param (GstQuery *query,
+                                    guint index,
+                                    GstAllocator *allocator,
+                                    const GstAllocationParams *params);
+

Parse an available query and get the allocator and its params +at index + of the allocator array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the allocator array to set

 

allocator

new allocator to set.

[transfer none][allow-none]

params

parameters for the allocator.

[transfer none][allow-none]
+
+
+
+
+

gst_query_remove_nth_allocation_param ()

+
void
+gst_query_remove_nth_allocation_param (GstQuery *query,
+                                       guint index);
+

Remove the allocation param at index + of the allocation param array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the allocation param array to remove

 
+
+

Since: 1.2

+
+
+
+

gst_query_add_allocation_meta ()

+
void
+gst_query_add_allocation_meta (GstQuery *query,
+                               GType api,
+                               const GstStructure *params);
+

Add api + with params + as one of the supported metadata API to query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

api

the metadata API

 

params

API specific parameters.

[transfer none][allow-none]
+
+
+
+
+

gst_query_get_n_allocation_metas ()

+
guint
+gst_query_get_n_allocation_metas (GstQuery *query);
+

Retrieve the number of values currently stored in the +meta API array of the query's structure.

+
+

Parameters

+
+++++ + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 
+
+
+

Returns

+

the metadata API array size as a guint.

+
+
+
+
+

gst_query_parse_nth_allocation_meta ()

+
GType
+gst_query_parse_nth_allocation_meta (GstQuery *query,
+                                     guint index,
+                                     const GstStructure **params);
+

Parse an available query and get the metadata API +at index + of the metadata API array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the metadata API array to read

 

params

API specific parameters.

[out][transfer none][allow-none]
+
+
+

Returns

+

a GType of the metadata API at index +.

+
+
+
+
+

gst_query_remove_nth_allocation_meta ()

+
void
+gst_query_remove_nth_allocation_meta (GstQuery *query,
+                                      guint index);
+

Remove the metadata API at index + of the metadata API array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

index

position in the metadata API array to remove

 
+
+
+
+
+

gst_query_find_allocation_meta ()

+
gboolean
+gst_query_find_allocation_meta (GstQuery *query,
+                                GType api,
+                                guint *index);
+

Check if query + has metadata api + set. When this function returns TRUE, +index + will contain the index where the requested API and the parameters +can be found.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_ALLOCATION type query GstQuery

 

api

the metadata API

 

index

the index.

[out][transfer none][allow-none]
+
+
+

Returns

+

TRUE when api +is in the list of metadata.

+
+
+
+
+

gst_query_new_scheduling ()

+
GstQuery *
+gst_query_new_scheduling (void);
+

Constructs a new query object for querying the scheduling properties.

+

Free-function: gst_query_unref()

+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_parse_scheduling ()

+
void
+gst_query_parse_scheduling (GstQuery *query,
+                            GstSchedulingFlags *flags,
+                            gint *minsize,
+                            gint *maxsize,
+                            gint *align);
+

Set the scheduling properties.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_SCHEDULING.

 

flags

GstSchedulingFlags.

[out][allow-none]

minsize

the suggested minimum size of pull requests.

[out][allow-none]

maxsize

the suggested maximum size of pull requests:.

[out][allow-none]

align

the suggested alignment of pull requests.

[out][allow-none]
+
+
+
+
+

gst_query_set_scheduling ()

+
void
+gst_query_set_scheduling (GstQuery *query,
+                          GstSchedulingFlags flags,
+                          gint minsize,
+                          gint maxsize,
+                          gint align);
+

Set the scheduling properties.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

query

A valid GstQuery of type GST_QUERY_SCHEDULING.

 

flags

GstSchedulingFlags

 

minsize

the suggested minimum size of pull requests

 

maxsize

the suggested maximum size of pull requests

 

align

the suggested alignment of pull requests

 
+
+
+
+
+

gst_query_add_scheduling_mode ()

+
void
+gst_query_add_scheduling_mode (GstQuery *query,
+                               GstPadMode mode);
+

Add mode + as one of the supported scheduling modes to query +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_SCHEDULING type query GstQuery

 

mode

a GstPadMode

 
+
+
+
+
+

gst_query_get_n_scheduling_modes ()

+
guint
+gst_query_get_n_scheduling_modes (GstQuery *query);
+

Retrieve the number of values currently stored in the +scheduling mode array of the query's structure.

+
+

Parameters

+
+++++ + + + + + +

query

a GST_QUERY_SCHEDULING type query GstQuery

 
+
+
+

Returns

+

the scheduling mode array size as a guint.

+
+
+
+
+

gst_query_parse_nth_scheduling_mode ()

+
GstPadMode
+gst_query_parse_nth_scheduling_mode (GstQuery *query,
+                                     guint index);
+

Parse an available query and get the scheduling mode +at index + of the scheduling modes array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_SCHEDULING type query GstQuery

 

index

position in the scheduling modes array to read

 
+
+
+

Returns

+

a GstPadMode of the scheduling mode at index +.

+
+
+
+
+

gst_query_has_scheduling_mode ()

+
gboolean
+gst_query_has_scheduling_mode (GstQuery *query,
+                               GstPadMode mode);
+

Check if query + has scheduling mode set.

+

When checking if upstream supports pull mode, it is usually not +enough to just check for GST_PAD_MODE_PULL with this function, you +also want to check whether the scheduling flags returned by +gst_query_parse_scheduling() have the seeking flag set (meaning +random access is supported, not only sequential pulls).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_SCHEDULING type query GstQuery

 

mode

the scheduling mode

 
+
+
+

Returns

+

TRUE when mode +is in the list of scheduling modes.

+
+
+
+
+

gst_query_has_scheduling_mode_with_flags ()

+
gboolean
+gst_query_has_scheduling_mode_with_flags
+                               (GstQuery *query,
+                                GstPadMode mode,
+                                GstSchedulingFlags flags);
+

Check if query + has scheduling mode set and flags + is set in +query scheduling flags.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

query

a GST_QUERY_SCHEDULING type query GstQuery

 

mode

the scheduling mode

 

flags

GstSchedulingFlags

 
+
+
+

Returns

+

TRUE when mode +is in the list of scheduling modes +and flags +are compatible with query flags.

+
+
+
+
+

gst_query_new_drain ()

+
GstQuery *
+gst_query_new_drain (void);
+

Constructs a new query object for querying the drain state.

+

Free-function: gst_query_unref()

+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+
+
+
+

gst_query_new_context ()

+
GstQuery *
+gst_query_new_context (const gchar *context_type);
+

Constructs a new query object for querying the pipeline-local context.

+

Free-function: gst_query_unref()

+
+

Parameters

+
+++++ + + + + + +

context_type

Context type to query

 
+
+
+

Returns

+

a new GstQuery.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_query_set_context ()

+
void
+gst_query_set_context (GstQuery *query,
+                       GstContext *context);
+

Answer a context query by setting the requested context.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GstQuery with query type GST_QUERY_CONTEXT

 

context

the requested GstContext

 
+
+

Since: 1.2

+
+
+
+

gst_query_parse_context ()

+
void
+gst_query_parse_context (GstQuery *query,
+                         GstContext **context);
+

Get the context from the context query +. The context remains valid as long as +query + remains valid.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

The query to parse

 

context

A pointer to store the GstContext.

[out][transfer none]
+
+

Since: 1.2

+
+
+
+

gst_query_parse_context_type ()

+
gboolean
+gst_query_parse_context_type (GstQuery *query,
+                              const gchar **context_type);
+

Parse a context type from an existing GST_QUERY_CONTEXT query.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

query

a GST_QUERY_CONTEXT type query

 

context_type

the context type, or NULL.

[out][transfer none][allow-none]
+
+
+

Returns

+

a gboolean indicating if the parsing succeeded.

+
+

Since: 1.2

+
+
+
+

Types and Values

+
+

struct GstQuery

+
struct GstQuery {
+  GstMiniObject mini_object;
+
+  GstQueryType type;
+};
+
+

The GstQuery structure.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMiniObject mini_object;

The parent GstMiniObject type

 

GstQueryType type;

the GstQueryType

 
+
+
+
+
+

enum GstQueryTypeFlags

+

GstQueryTypeFlags indicate the aspects of the different GstQueryType +values. You can get the type flags of a GstQueryType with the +gst_query_type_get_flags() function.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_QUERY_TYPE_UPSTREAM

+

Set if the query can travel upstream.

+
 

GST_QUERY_TYPE_DOWNSTREAM

+

Set if the query can travel downstream.

+
 

GST_QUERY_TYPE_SERIALIZED

+

Set if the query should be serialized with data + flow.

+
 
+
+
+
+
+

GST_QUERY_TYPE_BOTH

+
#define             GST_QUERY_TYPE_BOTH
+

The same thing as GST_QUERY_TYPE_UPSTREAM | GST_QUERY_TYPE_DOWNSTREAM.

+
+
+
+

enum GstQueryType

+

Standard predefined Query types

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_QUERY_UNKNOWN

+

unknown query type

+
 

GST_QUERY_POSITION

+

current position in stream

+
 

GST_QUERY_DURATION

+

total duration of the stream

+
 

GST_QUERY_LATENCY

+

latency of stream

+
 

GST_QUERY_JITTER

+

current jitter of stream

+
 

GST_QUERY_RATE

+

current rate of the stream

+
 

GST_QUERY_SEEKING

+

seeking capabilities

+
 

GST_QUERY_SEGMENT

+

segment start/stop positions

+
 

GST_QUERY_CONVERT

+

convert values between formats

+
 

GST_QUERY_FORMATS

+

query supported formats for convert

+
 

GST_QUERY_BUFFERING

+

query available media for efficient seeking.

+
 

GST_QUERY_CUSTOM

+

a custom application or element defined query.

+
 

GST_QUERY_URI

+

query the URI of the source or sink.

+
 

GST_QUERY_ALLOCATION

+

the buffer allocation properties

+
 

GST_QUERY_SCHEDULING

+

the scheduling properties

+
 

GST_QUERY_ACCEPT_CAPS

+

the accept caps query

+
 

GST_QUERY_CAPS

+

the caps query

+
 

GST_QUERY_DRAIN

+

wait till all serialized data is consumed downstream

+
 

GST_QUERY_CONTEXT

+

query the pipeline-local context from + downstream or upstream (since 1.2)

+
 
+
+
+
+
+

enum GstBufferingMode

+

The different types of buffering methods.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_BUFFERING_STREAM

+

a small amount of data is buffered

+
 

GST_BUFFERING_DOWNLOAD

+

the stream is being downloaded

+
 

GST_BUFFERING_TIMESHIFT

+

the stream is being downloaded in a ringbuffer

+
 

GST_BUFFERING_LIVE

+

the stream is a live stream

+
 
+
+
+
+
+

enum GstSchedulingFlags

+

The different scheduling flags.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_SCHEDULING_FLAG_SEEKABLE

+

if seeking is possible

+
 

GST_SCHEDULING_FLAG_SEQUENTIAL

+

if sequential access is recommended

+
 

GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED

+

if bandwidth is limited and buffering possible (since 1.2)

+
 
+
+
+
+
+

See Also

+

GstPad, GstElement

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstRegistry.html b/docs/gst/html/GstRegistry.html new file mode 100644 index 0000000..7a2d5cf --- /dev/null +++ b/docs/gst/html/GstRegistry.html @@ -0,0 +1,1100 @@ + + + + +GstRegistry: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstRegistry

+

GstRegistry — Abstract base class for management of GstPlugin objects

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstRegistry * + +gst_registry_get () +
+GList * + +gst_registry_get_feature_list () +
+guint32 + +gst_registry_get_feature_list_cookie () +
+GList * + +gst_registry_get_feature_list_by_plugin () +
+GList * + +gst_registry_get_plugin_list () +
+gboolean + +gst_registry_add_plugin () +
+void + +gst_registry_remove_plugin () +
+GList * + +gst_registry_plugin_filter () +
+GList * + +gst_registry_feature_filter () +
+GstPlugin * + +gst_registry_find_plugin () +
+GstPluginFeature * + +gst_registry_find_feature () +
+GstPluginFeature * + +gst_registry_lookup_feature () +
+void + +gst_registry_add_path () +
+GList * + +gst_registry_get_path_list () +
+gboolean + +gst_registry_scan_path () +
+GstPlugin * + +gst_registry_lookup () +
+void + +gst_registry_remove_feature () +
+gboolean + +gst_registry_add_feature () +
+gboolean + +gst_registry_check_feature_version () +
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidfeature-addedRun Last
voidplugin-addedRun Last
+
+
+

Types and Values

+
++++ + + + + +
structGstRegistry
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstRegistry
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

One registry holds the metadata of a set of plugins.

+

Design:

+

The GstRegistry object is a list of plugins and some functions for dealing +with them. Each GstPlugin is matched 1-1 with a file on disk, and may or may +not be loaded at a given time.

+

The primary source, at all times, of plugin information is each plugin file +itself. Thus, if an application wants information about a particular plugin, +or wants to search for a feature that satisfies given criteria, the primary +means of doing so is to load every plugin and look at the resulting +information that is gathered in the default registry. Clearly, this is a time +consuming process, so we cache information in the registry file. The format +and location of the cache file is internal to gstreamer.

+

On startup, plugins are searched for in the plugin search path. The following +locations are checked in this order:

+
    +
  • location from --gst-plugin-path commandline option.

  • +
  • the GST_PLUGIN_PATH environment variable.

  • +
  • the GST_PLUGIN_SYSTEM_PATH environment variable.

  • +
  • default locations (if GST_PLUGIN_SYSTEM_PATH is not set). +Those default locations are: +$XDG_DATA_HOME/gstreamer-$GST_API_VERSION/plugins/ +and $prefix/libs/gstreamer-$GST_API_VERSION/. +$XDG_DATA_HOME defaults to +$HOME/.local/share.

  • +
+

The registry cache file is loaded from +$XDG_CACHE_HOME/gstreamer-$GST_API_VERSION/registry-$ARCH.bin +(where $XDG_CACHE_HOME defaults to $HOME/.cache) or the file listed in the GST_REGISTRY +env var. One reason to change the registry location is for testing.

+

For each plugin that is found in the plugin search path, there could be 3 +possibilities for cached information:

+
    +
  • the cache may not contain information about a given file.

  • +
  • the cache may have stale information.

  • +
  • the cache may have current information.

  • +
+

In the first two cases, the plugin is loaded and the cache updated. In +addition to these cases, the cache may have entries for plugins that are not +relevant to the current process. These are marked as not available to the +current process. If the cache is updated for whatever reason, it is marked +dirty.

+

A dirty cache is written out at the end of initialization. Each entry is +checked to make sure the information is minimally valid. If not, the entry is +simply dropped.

+
+

Implementation notes:

+

The "cache" and "registry" are different concepts and can represent +different sets of plugins. For various reasons, at init time, the cache is +stored in the default registry, and plugins not relevant to the current +process are marked with the GST_PLUGIN_FLAG_CACHED bit. These plugins are +removed at the end of initialization.

+
+
+
+

Functions

+
+

gst_registry_get ()

+
GstRegistry *
+gst_registry_get (void);
+

Retrieves the singleton plugin registry. The caller does not own a +reference on the registry, as it is alive as long as GStreamer is +initialized.

+
+

Returns

+

the GstRegistry.

+

[transfer none]

+
+
+
+
+

gst_registry_get_feature_list ()

+
GList *
+gst_registry_get_feature_list (GstRegistry *registry,
+                               GType type);
+

Retrieves a GList of GstPluginFeature of type +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

a GstRegistry

 

type

a GType.

 
+
+
+

Returns

+

a GList of +GstPluginFeature of type +. Use gst_plugin_feature_list_free() after use

+

MT safe.

+

[transfer full][element-type Gst.PluginFeature]

+
+
+
+
+

gst_registry_get_feature_list_cookie ()

+
guint32
+gst_registry_get_feature_list_cookie (GstRegistry *registry);
+

Returns the registry's feature list cookie. This changes +every time a feature is added or removed from the registry.

+
+

Parameters

+
+++++ + + + + + +

registry

the registry

 
+
+
+

Returns

+

the feature list cookie.

+
+
+
+
+

gst_registry_get_feature_list_by_plugin ()

+
GList *
+gst_registry_get_feature_list_by_plugin
+                               (GstRegistry *registry,
+                                const gchar *name);
+

Retrieves a GList of features of the plugin with name name +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

a GstRegistry.

 

name

a plugin name.

 
+
+
+

Returns

+

a GList of +GstPluginFeature. Use gst_plugin_feature_list_free() after usage.

+

[transfer full][element-type Gst.PluginFeature]

+
+
+
+
+

gst_registry_get_plugin_list ()

+
GList *
+gst_registry_get_plugin_list (GstRegistry *registry);
+

Get a copy of all plugins registered in the given registry. The refcount +of each element in the list in incremented.

+
+

Parameters

+
+++++ + + + + + +

registry

the registry to search

 
+
+
+

Returns

+

a GList of GstPlugin. +Use gst_plugin_list_free() after usage.

+

MT safe.

+

[transfer full][element-type Gst.Plugin]

+
+
+
+
+

gst_registry_add_plugin ()

+
gboolean
+gst_registry_add_plugin (GstRegistry *registry,
+                         GstPlugin *plugin);
+

Add the plugin to the registry. The plugin-added signal will be emitted.

+

plugin +'s reference count will be incremented, and any floating +reference will be removed (see gst_object_ref_sink())

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to add the plugin to

 

plugin

the plugin to add.

[transfer floating]
+
+
+

Returns

+

TRUE on success.

+

MT safe.

+
+
+
+
+

gst_registry_remove_plugin ()

+
void
+gst_registry_remove_plugin (GstRegistry *registry,
+                            GstPlugin *plugin);
+

Remove the plugin from the registry.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to remove the plugin from

 

plugin

the plugin to remove.

[transfer none]
+
+
+
+
+

gst_registry_plugin_filter ()

+
GList *
+gst_registry_plugin_filter (GstRegistry *registry,
+                            GstPluginFilter filter,
+                            gboolean first,
+                            gpointer user_data);
+

Runs a filter against all plugins in the registry and returns a GList with +the results. If the first flag is set, only the first match is +returned (as a list with a single object). +Every plugin is reffed; use gst_plugin_list_free() after use, which +will unref again.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

registry

registry to query

 

filter

the filter to use.

[scope call]

first

only return first match

 

user_data

user data passed to the filter function.

[closure]
+
+
+

Returns

+

a GList of GstPlugin. +Use gst_plugin_list_free() after usage.

+

MT safe.

+

[transfer full][element-type Gst.Plugin]

+
+
+
+
+

gst_registry_feature_filter ()

+
GList *
+gst_registry_feature_filter (GstRegistry *registry,
+                             GstPluginFeatureFilter filter,
+                             gboolean first,
+                             gpointer user_data);
+

Runs a filter against all features of the plugins in the registry +and returns a GList with the results. +If the first flag is set, only the first match is +returned (as a list with a single object).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

registry

registry to query

 

filter

the filter to use.

[scope call]

first

only return first match

 

user_data

user data passed to the filter function.

[closure]
+
+
+

Returns

+

a GList of +GstPluginFeature. Use gst_plugin_feature_list_free() after usage.

+

MT safe.

+

[transfer full][element-type Gst.PluginFeature]

+
+
+
+
+

gst_registry_find_plugin ()

+
GstPlugin *
+gst_registry_find_plugin (GstRegistry *registry,
+                          const gchar *name);
+

Find the plugin with the given name in the registry. +The plugin will be reffed; caller is responsible for unreffing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to search

 

name

the plugin name to find

 
+
+
+

Returns

+

the plugin with the given name +or NULL if the plugin was not found. gst_object_unref() after +usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_registry_find_feature ()

+
GstPluginFeature *
+gst_registry_find_feature (GstRegistry *registry,
+                           const gchar *name,
+                           GType type);
+

Find the pluginfeature with the given name and type in the registry.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

registry

the registry to search

 

name

the pluginfeature name to find

 

type

the pluginfeature type to find

 
+
+
+

Returns

+

the pluginfeature with the +given name and type or NULL if the plugin was not +found. gst_object_unref() after usage.

+

MT safe.

+

[transfer full][nullable]

+
+
+
+
+

gst_registry_lookup_feature ()

+
GstPluginFeature *
+gst_registry_lookup_feature (GstRegistry *registry,
+                             const char *name);
+

Find a GstPluginFeature with name + in registry +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

a GstRegistry

 

name

a GstPluginFeature name

 
+
+
+

Returns

+

a GstPluginFeature with its refcount incremented, +use gst_object_unref() after usage.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_registry_add_path ()

+
void
+gst_registry_add_path (GstRegistry *registry,
+                       const gchar *path);
+

Add the given path to the registry. The syntax of the +path is specific to the registry. If the path has already been +added, do nothing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to add the path to

 

path

the path to add to the registry

 
+
+
+
+
+

gst_registry_get_path_list ()

+
GList *
+gst_registry_get_path_list (GstRegistry *registry);
+

Get the list of paths for the given registry.

+
+

Parameters

+
+++++ + + + + + +

registry

the registry to get the pathlist of

 
+
+
+

Returns

+

A GList of paths as +strings. g_list_free after use.

+

MT safe.

+

[transfer container][element-type char*]

+
+
+
+
+

gst_registry_scan_path ()

+
gboolean
+gst_registry_scan_path (GstRegistry *registry,
+                        const gchar *path);
+

Scan the given path for plugins to add to the registry. The syntax of the +path is specific to the registry.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to add found plugins to

 

path

the path to scan.

[type filename]
+
+
+

Returns

+

TRUE if registry changed

+
+
+
+
+

gst_registry_lookup ()

+
GstPlugin *
+gst_registry_lookup (GstRegistry *registry,
+                     const char *filename);
+

Look up a plugin in the given registry with the given filename. +If found, plugin is reffed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to look up in

 

filename

the name of the file to look up

 
+
+
+

Returns

+

the GstPlugin if found, or +NULL if not. gst_object_unref() after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_registry_remove_feature ()

+
void
+gst_registry_remove_feature (GstRegistry *registry,
+                             GstPluginFeature *feature);
+

Remove the feature from the registry.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to remove the feature from

 

feature

the feature to remove.

[transfer none]
+
+
+
+
+

gst_registry_add_feature ()

+
gboolean
+gst_registry_add_feature (GstRegistry *registry,
+                          GstPluginFeature *feature);
+

Add the feature to the registry. The feature-added signal will be emitted.

+

feature +'s reference count will be incremented, and any floating +reference will be removed (see gst_object_ref_sink())

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

registry

the registry to add the plugin to

 

feature

the feature to add.

[transfer floating]
+
+
+

Returns

+

TRUE on success.

+

MT safe.

+
+
+
+
+

gst_registry_check_feature_version ()

+
gboolean
+gst_registry_check_feature_version (GstRegistry *registry,
+                                    const gchar *feature_name,
+                                    guint min_major,
+                                    guint min_minor,
+                                    guint min_micro);
+

Checks whether a plugin feature by the given name exists in +registry + and whether its version is at least the +version required.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

registry

a GstRegistry

 

feature_name

the name of the feature (e.g. "oggdemux")

 

min_major

the minimum major version number

 

min_minor

the minimum minor version number

 

min_micro

the minimum micro version number

 
+
+
+

Returns

+

TRUE if the feature could be found and the version is +the same as the required version or newer, and FALSE otherwise.

+
+
+
+
+

Types and Values

+
+

struct GstRegistry

+
struct GstRegistry;
+

Opaque GstRegistry structure.

+
+
+
+

Signal Details

+
+

The “feature-added” signal

+
void
+user_function (GstRegistry      *registry,
+               GstPluginFeature *feature,
+               gpointer          user_data)
+

Signals that a feature has been added to the registry (possibly +replacing a previously-added one by the same name)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

registry

the registry that emitted the signal

 

feature

the feature that has been added

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “plugin-added” signal

+
void
+user_function (GstRegistry *registry,
+               GstPlugin   *plugin,
+               gpointer     user_data)
+

Signals that a plugin has been added to the registry (possibly +replacing a previously-added one by the same name)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

registry

the registry that emitted the signal

 

plugin

the plugin that has been added

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstSample.html b/docs/gst/html/GstSample.html new file mode 100644 index 0000000..138d3d8 --- /dev/null +++ b/docs/gst/html/GstSample.html @@ -0,0 +1,498 @@ + + + + +GstSample: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstSample

+

GstSample — A media sample

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstBuffer * + +gst_sample_get_buffer () +
+GstBufferList * + +gst_sample_get_buffer_list () +
+GstCaps * + +gst_sample_get_caps () +
const GstStructure * + +gst_sample_get_info () +
+GstSegment * + +gst_sample_get_segment () +
+void + +gst_sample_set_buffer_list () +
+GstSample * + +gst_sample_new () +
+GstSample * + +gst_sample_ref () +
+void + +gst_sample_unref () +
+GstSample * + +gst_sample_copy () +
+
+
+

Types and Values

+
++++ + + + + +
 GstSample
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstSample
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstSample is a small object containing data, a type, timing and +extra arbitrary information.

+
+
+

Functions

+
+

gst_sample_get_buffer ()

+
GstBuffer *
+gst_sample_get_buffer (GstSample *sample);
+

Get the buffer associated with sample +

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

the buffer of sample +or NULL +when there is no buffer. The buffer remains valid as long as +sample +is valid. If you need to hold on to it for longer than +that, take a ref to the buffer with gst_buffer_ref().

+

[transfer none][nullable]

+
+
+
+
+

gst_sample_get_buffer_list ()

+
GstBufferList *
+gst_sample_get_buffer_list (GstSample *sample);
+

Get the buffer list associated with sample +

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

the buffer list of sample +or NULL +when there is no buffer list. The buffer list remains valid as long as +sample +is valid. If you need to hold on to it for longer than +that, take a ref to the buffer list with gst_mini_object_ref().

+

[transfer none][nullable]

+
+

Since: 1.6

+
+
+
+

gst_sample_get_caps ()

+
GstCaps *
+gst_sample_get_caps (GstSample *sample);
+

Get the caps associated with sample +

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

the caps of sample +or NULL +when there is no caps. The caps remain valid as long as sample +is +valid. If you need to hold on to the caps for longer than that, +take a ref to the caps with gst_caps_ref().

+

[transfer none][nullable]

+
+
+
+
+

gst_sample_get_info ()

+
const GstStructure *
+gst_sample_get_info (GstSample *sample);
+

Get extra information associated with sample +.

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

the extra info of sample +. +The info remains valid as long as sample +is valid.

+

[transfer none][nullable]

+
+
+
+
+

gst_sample_get_segment ()

+
GstSegment *
+gst_sample_get_segment (GstSample *sample);
+

Get the segment associated with sample +

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

the segment of sample +. +The segment remains valid as long as sample +is valid.

+

[transfer none]

+
+
+
+
+

gst_sample_set_buffer_list ()

+
void
+gst_sample_set_buffer_list (GstSample *sample,
+                            GstBufferList *buffer_list);
+

Set the buffer list associated with sample +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sample

a GstSample

 

buffer_list

a GstBufferList

 
+
+

Since: 1.6

+
+
+
+

gst_sample_new ()

+
GstSample *
+gst_sample_new (GstBuffer *buffer,
+                GstCaps *caps,
+                const GstSegment *segment,
+                GstStructure *info);
+

Create a new GstSample with the provided details.

+

Free-function: gst_sample_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer, or NULL.

[transfer none][allow-none]

caps

a GstCaps, or NULL.

[transfer none][allow-none]

segment

a GstSegment, or NULL.

[transfer none][allow-none]

info

a GstStructure, or NULL.

[transfer full][allow-none]
+
+
+

Returns

+

the new GstSample. gst_sample_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_sample_ref ()

+
GstSample *
+gst_sample_ref (GstSample *sample);
+

Increases the refcount of the given sample by one.

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample

 
+
+
+

Returns

+

sample +.

+

[transfer full]

+
+
+
+
+

gst_sample_unref ()

+
void
+gst_sample_unref (GstSample *sample);
+

Decreases the refcount of the sample. If the refcount reaches 0, the +sample will be freed.

+
+

Parameters

+
+++++ + + + + + +

sample

a GstSample.

[transfer full]
+
+
+
+
+

gst_sample_copy ()

+
GstSample *
+gst_sample_copy (const GstSample *buf);
+

Create a copy of the given sample. This will also make a newly allocated +copy of the data the source sample contains.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstSample.

 
+
+
+

Returns

+

a new copy of buf +.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

Types and Values

+
+

GstSample

+
typedef struct _GstSample GstSample;
+

The opaque structure of a GstSample. A sample contains a typed memory +block and the associated timing information. It is mainly used to +exchange buffers with an application.

+
+
+
+

See Also

+

GstBuffer, GstCaps, GstSegment

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstSegment.html b/docs/gst/html/GstSegment.html new file mode 100644 index 0000000..494e1e5 --- /dev/null +++ b/docs/gst/html/GstSegment.html @@ -0,0 +1,1414 @@ + + + + +GstSegment: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstSegment

+

GstSegment — Structure describing the configured region of interest + in a media file.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +gst_segment_clip () +
+void + +gst_segment_init () +
+GstSegment * + +gst_segment_new () +
+GstSegment * + +gst_segment_copy () +
+void + +gst_segment_free () +
+gboolean + +gst_segment_do_seek () +
+guint64 + +gst_segment_position_from_stream_time () +
+gint + +gst_segment_position_from_stream_time_full () +
+guint64 + +gst_segment_to_running_time () +
+gint + +gst_segment_to_running_time_full () +
+guint64 + +gst_segment_to_stream_time () +
+gint + +gst_segment_to_stream_time_full () +
+guint64 + +gst_segment_position_from_running_time () +
+gint + +gst_segment_position_from_running_time_full () +
+guint64 + +gst_segment_to_position () +
+gboolean + +gst_segment_set_running_time () +
+void + +gst_segment_copy_into () +
+gboolean + +gst_segment_offset_running_time () +
+gboolean + +gst_segment_is_equal () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstSegment
enumGstSegmentFlags
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstSegment
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

This helper structure holds the relevant values for tracking the region of +interest in a media file, called a segment.

+

The structure can be used for two purposes:

+
    +
  • performing seeks (handling seek events)

  • +
  • tracking playback regions (handling newsegment events)

  • +
+

The segment is usually configured by the application with a seek event which +is propagated upstream and eventually handled by an element that performs the seek.

+

The configured segment is then propagated back downstream with a newsegment event. +This information is then used to clip media to the segment boundaries.

+

A segment structure is initialized with gst_segment_init(), which takes a GstFormat +that will be used as the format of the segment values. The segment will be configured +with a start value of 0 and a stop/duration of -1, which is undefined. The default +rate and applied_rate is 1.0.

+

The public duration field contains the duration of the segment. When using +the segment for seeking, the start and time members should normally be left +to their default 0 value. The stop position is left to -1 unless explicitly +configured to a different value after a seek event.

+

The current position in the segment should be set by changing the position +member in the structure.

+

For elements that perform seeks, the current segment should be updated with the +gst_segment_do_seek() and the values from the seek event. This method will update +all the segment fields. The position field will contain the new playback position. +If the start_type was different from GST_SEEK_TYPE_NONE, playback continues from +the position position, possibly with updated flags or rate.

+

For elements that want to use GstSegment to track the playback region, +update the segment fields with the information from the newsegment event. +The gst_segment_clip() method can be used to check and clip +the media data to the segment boundaries.

+

For elements that want to synchronize to the pipeline clock, gst_segment_to_running_time() +can be used to convert a timestamp to a value that can be used to synchronize +to the clock. This function takes into account the base as well as +any rate or applied_rate conversions.

+

For elements that need to perform operations on media data in stream_time, +gst_segment_to_stream_time() can be used to convert a timestamp and the segment +info to stream time (which is always between 0 and the duration of the stream).

+
+
+

Functions

+
+

gst_segment_clip ()

+
gboolean
+gst_segment_clip (const GstSegment *segment,
+                  GstFormat format,
+                  guint64 start,
+                  guint64 stop,
+                  guint64 *clip_start,
+                  guint64 *clip_stop);
+

Clip the given start + and stop + values to the segment boundaries given +in segment +. start + and stop + are compared and clipped to segment + +start and stop values.

+

If the function returns FALSE, start + and stop + are known to fall +outside of segment + and clip_start + and clip_stop + are not updated.

+

When the function returns TRUE, clip_start + and clip_stop + will be +updated. If clip_start + or clip_stop + are different from start + or stop + +respectively, the region fell partially in the segment.

+

Note that when stop + is -1, clip_stop + will be set to the end of the +segment. Depending on the use case, this may or may not be what you want.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

start

the start position in the segment

 

stop

the stop position in the segment

 

clip_start

the clipped start position in the segment.

[out][allow-none]

clip_stop

the clipped stop position in the segment.

[out][allow-none]
+
+
+

Returns

+

TRUE if the given start +and stop +times fall partially or +completely in segment +, FALSE if the values are completely outside +of the segment.

+
+
+
+
+

gst_segment_init ()

+
void
+gst_segment_init (GstSegment *segment,
+                  GstFormat format);
+

The start/position fields are set to 0 and the stop/duration +fields are set to -1 (unknown). The default rate of 1.0 and no +flags are set.

+

Initialize segment + to its default values.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 
+
+
+
+
+

gst_segment_new ()

+
GstSegment *
+gst_segment_new (void);
+

Allocate a new GstSegment structure and initialize it using +gst_segment_init().

+

Free-function: gst_segment_free

+
+

Returns

+

a new GstSegment, free with gst_segment_free().

+

[transfer full]

+
+
+
+
+

gst_segment_copy ()

+
GstSegment *
+gst_segment_copy (const GstSegment *segment);
+

Create a copy of given segment +.

+

Free-function: gst_segment_free

+
+

Parameters

+
+++++ + + + + + +

segment

a GstSegment.

[transfer none]
+
+
+

Returns

+

a new GstSegment, free with gst_segment_free().

+

[transfer full]

+
+
+
+
+

gst_segment_free ()

+
void
+gst_segment_free (GstSegment *segment);
+

Free the allocated segment segment +.

+
+

Parameters

+
+++++ + + + + + +

segment

a GstSegment.

[in][transfer full]
+
+
+
+
+

gst_segment_do_seek ()

+
gboolean
+gst_segment_do_seek (GstSegment *segment,
+                     gdouble rate,
+                     GstFormat format,
+                     GstSeekFlags flags,
+                     GstSeekType start_type,
+                     guint64 start,
+                     GstSeekType stop_type,
+                     guint64 stop,
+                     gboolean *update);
+

Update the segment structure with the field values of a seek event (see +gst_event_new_seek()).

+

After calling this method, the segment field position and time will +contain the requested new position in the segment. The new requested +position in the segment depends on rate + and start_type + and stop_type +.

+

For positive rate +, the new position in the segment is the new segment + +start field when it was updated with a start_type + different from +GST_SEEK_TYPE_NONE. If no update was performed on segment + start position +(GST_SEEK_TYPE_NONE), start + is ignored and segment + position is +unmodified.

+

For negative rate +, the new position in the segment is the new segment + +stop field when it was updated with a stop_type + different from +GST_SEEK_TYPE_NONE. If no stop was previously configured in the segment, the +duration of the segment will be used to update the stop position. +If no update was performed on segment + stop position (GST_SEEK_TYPE_NONE), +stop + is ignored and segment + position is unmodified.

+

The applied rate of the segment will be set to 1.0 by default. +If the caller can apply a rate change, it should update segment + +rate and applied_rate after calling this function.

+

update + will be set to TRUE if a seek should be performed to the segment +position field. This field can be FALSE if, for example, only the rate + +has been changed but not the playback position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

rate

the rate of the segment.

 

format

the format of the segment.

 

flags

the segment flags for the segment

 

start_type

the seek method

 

start

the seek start value

 

stop_type

the seek method

 

stop

the seek stop value

 

update

boolean holding whether position was updated.

[out][allow-none]
+
+
+

Returns

+

TRUE if the seek could be performed.

+
+
+
+
+

gst_segment_position_from_stream_time ()

+
guint64
+gst_segment_position_from_stream_time (const GstSegment *segment,
+                                       GstFormat format,
+                                       guint64 stream_time);
+

Convert stream_time + into a position in the segment so that +gst_segment_to_stream_time() with that position returns stream_time +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

stream_time

the stream_time in the segment

 
+
+
+

Returns

+

the position in the segment for stream_time +. This function returns +-1 when stream_time +is -1 or when it is not inside segment +.

+
+

Since: 1.8

+
+
+
+

gst_segment_position_from_stream_time_full ()

+
gint
+gst_segment_position_from_stream_time_full
+                               (const GstSegment *segment,
+                                GstFormat format,
+                                guint64 stream_time,
+                                guint64 *position);
+

Translate stream_time + to the segment position using the currently configured +segment. Compared to gst_segment_position_from_stream_time() this function can +return negative segment position.

+

This function is typically used by elements that need to synchronize buffers +against the clock or each other.

+

stream_time + can be any value and the result of this function for values outside +of the segment is extrapolated.

+

When 1 is returned, stream_time + resulted in a positive position returned +in position +.

+

When this function returns -1, the returned position + should be negated +to get the real negative segment position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

stream_time

the stream-time

 

position

the resulting position in the segment.

[out]
+
+
+

Returns

+

a 1 or -1 on success, 0 on failure.

+
+

Since: 1.8

+
+
+
+

gst_segment_to_running_time ()

+
guint64
+gst_segment_to_running_time (const GstSegment *segment,
+                             GstFormat format,
+                             guint64 position);
+

Translate position + to the total running time using the currently configured +segment. Position is a value between segment + start and stop time.

+

This function is typically used by elements that need to synchronize to the +global clock in a pipeline. The running time is a constantly increasing value +starting from 0. When gst_segment_init() is called, this value will reset to +0.

+

This function returns -1 if the position is outside of segment + start and stop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

position

the position in the segment

 
+
+
+

Returns

+

the position as the total running time or -1 when an invalid position +was given.

+
+
+
+
+

gst_segment_to_running_time_full ()

+
gint
+gst_segment_to_running_time_full (const GstSegment *segment,
+                                  GstFormat format,
+                                  guint64 position,
+                                  guint64 *running_time);
+

Translate position + to the total running time using the currently configured +segment. Compared to gst_segment_to_running_time() this function can return +negative running-time.

+

This function is typically used by elements that need to synchronize buffers +against the clock or eachother.

+

position + can be any value and the result of this function for values outside +of the segment is extrapolated.

+

When 1 is returned, position + resulted in a positive running-time returned +in running_time +.

+

When this function returns -1, the returned running_time + should be negated +to get the real negative running time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

position

the position in the segment

 

running_time

result running-time.

[out][allow-none]
+
+
+

Returns

+

a 1 or -1 on success, 0 on failure.

+
+

Since: 1.6

+
+
+
+

gst_segment_to_stream_time ()

+
guint64
+gst_segment_to_stream_time (const GstSegment *segment,
+                            GstFormat format,
+                            guint64 position);
+

Translate position + to stream time using the currently configured +segment. The position + value must be between segment + start and +stop value.

+

This function is typically used by elements that need to operate on +the stream time of the buffers it receives, such as effect plugins. +In those use cases, position + is typically the buffer timestamp or +clock time that one wants to convert to the stream time. +The stream time is always between 0 and the total duration of the +media stream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

position

the position in the segment

 
+
+
+

Returns

+

the position in stream_time or -1 when an invalid position +was given.

+
+

Since: 1.8

+
+
+
+

gst_segment_to_stream_time_full ()

+
gint
+gst_segment_to_stream_time_full (const GstSegment *segment,
+                                 GstFormat format,
+                                 guint64 position,
+                                 guint64 *stream_time);
+

Translate position + to the total stream time using the currently configured +segment. Compared to gst_segment_to_stream_time() this function can return +negative stream-time.

+

This function is typically used by elements that need to synchronize buffers +against the clock or eachother.

+

position + can be any value and the result of this function for values outside +of the segment is extrapolated.

+

When 1 is returned, position + resulted in a positive stream-time returned +in stream_time +.

+

When this function returns -1, the returned stream_time + should be negated +to get the real negative stream time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

position

the position in the segment

 

stream_time

result stream-time.

[out]
+
+
+

Returns

+

a 1 or -1 on success, 0 on failure.

+
+

Since: 1.8

+
+
+
+

gst_segment_position_from_running_time ()

+
guint64
+gst_segment_position_from_running_time
+                               (const GstSegment *segment,
+                                GstFormat format,
+                                guint64 running_time);
+

Convert running_time + into a position in the segment so that +gst_segment_to_running_time() with that position returns running_time +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

running_time

the running_time in the segment

 
+
+
+

Returns

+

the position in the segment for running_time +. This function returns +-1 when running_time +is -1 or when it is not inside segment +.

+
+

Since: 1.8

+
+
+
+

gst_segment_position_from_running_time_full ()

+
gint
+gst_segment_position_from_running_time_full
+                               (const GstSegment *segment,
+                                GstFormat format,
+                                guint64 running_time,
+                                guint64 *position);
+

Translate running_time + to the segment position using the currently configured +segment. Compared to gst_segment_position_from_running_time() this function can +return negative segment position.

+

This function is typically used by elements that need to synchronize buffers +against the clock or each other.

+

running_time + can be any value and the result of this function for values +outside of the segment is extrapolated.

+

When 1 is returned, running_time + resulted in a positive position returned +in position +.

+

When this function returns -1, the returned position + should be negated +to get the real negative segment position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

running_time

the running-time

 

position

the resulting position in the segment.

[out]
+
+
+

Returns

+

a 1 or -1 on success, 0 on failure.

+
+

Since: 1.8

+
+
+
+

gst_segment_to_position ()

+
guint64
+gst_segment_to_position (const GstSegment *segment,
+                         GstFormat format,
+                         guint64 running_time);
+
+

gst_segment_to_position is deprecated and should not be used in newly-written code.

+

Use gst_segment_position_from_running_time() instead.

+
+

Convert running_time + into a position in the segment so that +gst_segment_to_running_time() with that position returns running_time +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

running_time

the running_time in the segment

 
+
+
+

Returns

+

the position in the segment for running_time +. This function returns +-1 when running_time +is -1 or when it is not inside segment +.

+
+
+
+
+

gst_segment_set_running_time ()

+
gboolean
+gst_segment_set_running_time (GstSegment *segment,
+                              GstFormat format,
+                              guint64 running_time);
+

Adjust the start/stop and base values of segment + such that the next valid +buffer will be one with running_time +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

running_time

the running_time in the segment

 
+
+
+

Returns

+

TRUE if the segment could be updated successfully. If FALSE is +returned, running_time +is -1 or not in segment +.

+
+
+
+
+

gst_segment_copy_into ()

+
void
+gst_segment_copy_into (const GstSegment *src,
+                       GstSegment *dest);
+

Copy the contents of src + into dest +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

a GstSegment.

[transfer none]

dest

a GstSegment.

[transfer none]
+
+
+
+
+

gst_segment_offset_running_time ()

+
gboolean
+gst_segment_offset_running_time (GstSegment *segment,
+                                 GstFormat format,
+                                 gint64 offset);
+

Adjust the values in segment + so that offset + is applied to all +future running-time calculations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

segment

a GstSegment structure.

 

format

the format of the segment.

 

offset

the offset to apply in the segment

 
+
+
+

Returns

+

TRUE if the segment could be updated successfully. If FALSE is +returned, offset +is not in segment +.

+
+

Since: 1.2.3

+
+
+
+

gst_segment_is_equal ()

+
gboolean
+gst_segment_is_equal (const GstSegment *s0,
+                      const GstSegment *s1);
+

Checks for two segments being equal. Equality here is defined +as perfect equality, including floating point values.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

s0

a GstSegment structure.

 

s1

a GstSegment structure.

 
+
+
+

Returns

+

TRUE if the segments are equal, FALSE otherwise.

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstSegment

+
struct GstSegment {
+  GstSegmentFlags flags;
+
+  gdouble         rate;
+  gdouble         applied_rate;
+
+  GstFormat       format;
+  guint64         base;
+  guint64         offset;
+  guint64         start;
+  guint64         stop;
+  guint64         time;
+
+  guint64         position;
+  guint64         duration;
+};
+
+

A helper structure that holds the configured region of +interest in a media file.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstSegmentFlags flags;

flags for this segment

 

gdouble rate;

the playback rate of the segment

 

gdouble applied_rate;

the already applied rate to the segment

 

GstFormat format;

the format of the segment values

 

guint64 base;

the running time (plus elapsed time, see offset) of the segment start

 

guint64 offset;

the amount (in buffer timestamps) that has already been elapsed in +the segment

 

guint64 start;

the start of the segment in buffer timestamp time (PTS)

 

guint64 stop;

the stop of the segment in buffer timestamp time (PTS)

 

guint64 time;

the stream time of the segment start

 

guint64 position;

the buffer timestamp position in the segment (used internally by +elements such as sources, demuxers or parsers to track progress)

 

guint64 duration;

the duration of the stream

 
+
+
+
+
+

enum GstSegmentFlags

+

Flags for the GstSegment structure. Currently mapped to the corresponding +values of the seek flags.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_SEGMENT_FLAG_NONE

+

no flags

+
 

GST_SEGMENT_FLAG_RESET

+

reset the pipeline running_time to the segment + running_time

+
 

GST_SEGMENT_FLAG_TRICKMODE

+

perform skip playback (Since 1.6)

+
 

GST_SEGMENT_FLAG_SKIP

+

Deprecated backward compatibility flag, replaced + by GST_SEGMENT_FLAG_TRICKMODE +

+
 

GST_SEGMENT_FLAG_SEGMENT

+

send SEGMENT_DONE instead of EOS

+
 

GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS

+

Decode only keyframes, where + possible (Since 1.6)

+
 

GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO

+

Do not decode any audio, where + possible (Since 1.6)

+
 
+
+
+
+
+

See Also

+

GstEvent

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstStructure.html b/docs/gst/html/GstStructure.html new file mode 100644 index 0000000..448c9f3 --- /dev/null +++ b/docs/gst/html/GstStructure.html @@ -0,0 +1,3648 @@ + + + + +GstStructure: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstStructure

+

GstStructure — Generic structure containing fields of names and values

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +(*GstStructureForeachFunc) () +
+gboolean + +(*GstStructureMapFunc) () +
+gboolean + +(*GstStructureFilterMapFunc) () +
+GstStructure * + +gst_structure_new_empty () +
+GstStructure * + +gst_structure_new_id_empty () +
+GstStructure * + +gst_structure_new () +
+GstStructure * + +gst_structure_new_valist () +
+GstStructure * + +gst_structure_new_id () +
+GstStructure * + +gst_structure_new_from_string () +
+GstStructure * + +gst_structure_copy () +
+void + +gst_structure_free () +
const gchar * + +gst_structure_get_name () +
+gboolean + +gst_structure_has_name () +
+void + +gst_structure_set_name () +
+GQuark + +gst_structure_get_name_id () +
+gboolean + +gst_structure_id_get () +
+gboolean + +gst_structure_id_get_valist () +
const GValue * + +gst_structure_id_get_value () +
+void + +gst_structure_id_set_value () +
+void + +gst_structure_id_take_value () +
+gboolean + +gst_structure_get () +
+gboolean + +gst_structure_get_valist () +
const GValue * + +gst_structure_get_value () +
+void + +gst_structure_set_value () +
+void + +gst_structure_set_array () +
+void + +gst_structure_set_list () +
+void + +gst_structure_take_value () +
+void + +gst_structure_set () +
+void + +gst_structure_set_valist () +
+void + +gst_structure_id_set () +
+void + +gst_structure_id_set_valist () +
+void + +gst_structure_remove_field () +
+void + +gst_structure_remove_fields () +
+void + +gst_structure_remove_fields_valist () +
+void + +gst_structure_remove_all_fields () +
+GType + +gst_structure_get_field_type () +
+gint + +gst_structure_n_fields () +
+gboolean + +gst_structure_has_field () +
+gboolean + +gst_structure_has_field_typed () +
+gboolean + +gst_structure_is_equal () +
+gboolean + +gst_structure_is_subset () +
+gboolean + +gst_structure_can_intersect () +
+GstStructure * + +gst_structure_intersect () +
+gboolean + +gst_structure_id_has_field () +
+gboolean + +gst_structure_id_has_field_typed () +
+gboolean + +gst_structure_get_boolean () +
+gboolean + +gst_structure_get_int () +
+gboolean + +gst_structure_get_uint () +
+gboolean + +gst_structure_get_int64 () +
+gboolean + +gst_structure_get_uint64 () +
+gboolean + +gst_structure_get_double () +
const gchar * + +gst_structure_get_string () +
+gboolean + +gst_structure_get_date () +
+gboolean + +gst_structure_get_date_time () +
+gboolean + +gst_structure_get_clock_time () +
+gboolean + +gst_structure_get_enum () +
+gboolean + +gst_structure_get_fraction () +
+gboolean + +gst_structure_get_array () +
+gboolean + +gst_structure_get_list () +
+gboolean + +gst_structure_foreach () +
+gboolean + +gst_structure_map_in_place () +
+void + +gst_structure_filter_and_map_in_place () +
const gchar * + +gst_structure_nth_field_name () +
+gboolean + +gst_structure_set_parent_refcount () +
+gchar * + +gst_structure_to_string () +
+GstStructure * + +gst_structure_from_string () +
+void + +gst_structure_fixate () +
+gboolean + +gst_structure_fixate_field () +
+gboolean + +gst_structure_fixate_field_nearest_int () +
+gboolean + +gst_structure_fixate_field_nearest_double () +
+gboolean + +gst_structure_fixate_field_nearest_fraction () +
+gboolean + +gst_structure_fixate_field_boolean () +
+gboolean + +gst_structure_fixate_field_string () +
+
+
+

Types and Values

+
++++ + + + + +
structGstStructure
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstStructure
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

A GstStructure is a collection of key/value pairs. The keys are expressed +as GQuarks and the values can be of any GType.

+

In addition to the key/value pairs, a GstStructure also has a name. The name +starts with a letter and can be filled by letters, numbers and any of "/-_.:".

+

GstStructure is used by various GStreamer subsystems to store information +in a flexible and extensible way. A GstStructure does not have a refcount +because it usually is part of a higher level object such as GstCaps, +GstMessage, GstEvent, GstQuery. It provides a means to enforce mutability +using the refcount of the parent with the gst_structure_set_parent_refcount() +method.

+

A GstStructure can be created with gst_structure_new_empty() or +gst_structure_new(), which both take a name and an optional set of +key/value pairs along with the types of the values.

+

Field values can be changed with gst_structure_set_value() or +gst_structure_set().

+

Field values can be retrieved with gst_structure_get_value() or the more +convenient gst_structure_get_*() functions.

+

Fields can be removed with gst_structure_remove_field() or +gst_structure_remove_fields().

+

Strings in structures must be ASCII or UTF-8 encoded. Other encodings are +not allowed. Strings may be NULL however.

+

Be aware that the current GstCaps / GstStructure serialization into string +has limited support for nested GstCaps / GstStructure fields. It can only +support one level of nesting. Using more levels will lead to unexpected +behavior when using serialization features, such as gst_caps_to_string() or +gst_value_serialize() and their counterparts.

+
+
+

Functions

+
+

GstStructureForeachFunc ()

+
gboolean
+(*GstStructureForeachFunc) (GQuark field_id,
+                            const GValue *value,
+                            gpointer user_data);
+

A function that will be called in gst_structure_foreach(). The function may +not modify value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

field_id

the GQuark of the field name

 

value

the GValue of the field

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the foreach operation should continue, FALSE if +the foreach operation should stop with FALSE.

+
+
+
+
+

GstStructureMapFunc ()

+
gboolean
+(*GstStructureMapFunc) (GQuark field_id,
+                        GValue *value,
+                        gpointer user_data);
+

A function that will be called in gst_structure_map_in_place(). The function +may modify value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

field_id

the GQuark of the field name

 

value

the GValue of the field

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the map operation should continue, FALSE if +the map operation should stop with FALSE.

+
+
+
+
+

GstStructureFilterMapFunc ()

+
gboolean
+(*GstStructureFilterMapFunc) (GQuark field_id,
+                              GValue *value,
+                              gpointer user_data);
+

A function that will be called in gst_structure_filter_and_map_in_place(). +The function may modify value +, and the value will be removed from +the structure if FALSE is returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

field_id

the GQuark of the field name

 

value

the GValue of the field

 

user_data

user data

 
+
+
+

Returns

+

TRUE if the field should be preserved, FALSE if it +should be removed.

+
+
+
+
+

gst_structure_new_empty ()

+
GstStructure *
+gst_structure_new_empty (const gchar *name);
+

Creates a new, empty GstStructure with the given name +.

+

See gst_structure_set_name() for constraints on the name + parameter.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + +

name

name of new structure

 
+
+
+

Returns

+

a new, empty GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_new_id_empty ()

+
GstStructure *
+gst_structure_new_id_empty (GQuark quark);
+

Creates a new, empty GstStructure with the given name as a GQuark.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + +

quark

name of new structure

 
+
+
+

Returns

+

a new, empty GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_new ()

+
GstStructure *
+gst_structure_new (const gchar *name,
+                   const gchar *firstfield,
+                   ...);
+

Creates a new GstStructure with the given name. Parses the +list of variable arguments and sets fields to the values listed. +Variable arguments should be passed as field name, field type, +and value. Last variable argument should be NULL.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name

name of new structure

 

firstfield

name of first field to set

 

...

additional arguments

 
+
+
+

Returns

+

a new GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_new_valist ()

+
GstStructure *
+gst_structure_new_valist (const gchar *name,
+                          const gchar *firstfield,
+                          va_list varargs);
+

Creates a new GstStructure with the given name +. Structure fields +are set according to the varargs in a manner similar to +gst_structure_new().

+

See gst_structure_set_name() for constraints on the name + parameter.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name

name of new structure

 

firstfield

name of first field to set

 

varargs

variable argument list

 
+
+
+

Returns

+

a new GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_new_id ()

+
GstStructure *
+gst_structure_new_id (GQuark name_quark,
+                      GQuark field_quark,
+                      ...);
+

Creates a new GstStructure with the given name as a GQuark, followed by +fieldname quark, GType, argument(s) "triplets" in the same format as +gst_structure_id_set(). Basically a convenience wrapper around +gst_structure_new_id_empty() and gst_structure_id_set().

+

The last variable argument must be NULL (or 0).

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name_quark

name of new structure

 

field_quark

the GQuark for the name of the field to set

 

...

variable arguments

 
+
+
+

Returns

+

a new GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_new_from_string ()

+
GstStructure *
+gst_structure_new_from_string (const gchar *string);
+

Creates a GstStructure from a string representation. +If end is not NULL, a pointer to the place inside the given string +where parsing ended will be returned.

+

The current implementation of serialization will lead to unexpected results +when there are nested GstCaps / GstStructure deeper than one level.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + +

string

a string representation of a GstStructure

 
+
+
+

Returns

+

a new GstStructure or NULL +when the string could not be parsed. Free with +gst_structure_free() after use.

+

[transfer full][nullable]

+
+

Since: 1.2

+
+
+
+

gst_structure_copy ()

+
GstStructure *
+gst_structure_copy (const GstStructure *structure);
+

Duplicates a GstStructure and all its fields and values.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure to duplicate

 
+
+
+

Returns

+

a new GstStructure.

+

[transfer full]

+
+
+
+
+

gst_structure_free ()

+
void
+gst_structure_free (GstStructure *structure);
+

Frees a GstStructure and all its fields and values. The structure must not +have a parent when this function is called.

+
+

Parameters

+
+++++ + + + + + +

structure

the GstStructure to free.

[in][transfer full]
+
+
+
+
+

gst_structure_get_name ()

+
const gchar *
+gst_structure_get_name (const GstStructure *structure);
+

Get the name of structure + as a string.

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+

Returns

+

the name of the structure.

+
+
+
+
+

gst_structure_has_name ()

+
gboolean
+gst_structure_has_name (const GstStructure *structure,
+                        const gchar *name);
+

Checks if the structure has the given name

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

name

structure name to check for

 
+
+
+

Returns

+

TRUE if name +matches the name of the structure.

+
+
+
+
+

gst_structure_set_name ()

+
void
+gst_structure_set_name (GstStructure *structure,
+                        const gchar *name);
+

Sets the name of the structure to the given name +. The string +provided is copied before being used. It must not be empty, start with a +letter and can be followed by letters, numbers and any of "/-_.:".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

name

the new name of the structure

 
+
+
+
+
+

gst_structure_get_name_id ()

+
GQuark
+gst_structure_get_name_id (const GstStructure *structure);
+

Get the name of structure + as a GQuark.

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+

Returns

+

the quark representing the name of the structure.

+
+
+
+
+

gst_structure_id_get ()

+
gboolean
+gst_structure_id_get (const GstStructure *structure,
+                      GQuark first_field_id,
+                      ...);
+

Parses the variable arguments and reads fields from structure + accordingly. +Variable arguments should be in the form field id quark, field type +(as a GType), pointer(s) to a variable(s) to hold the return value(s). +The last variable argument should be NULL (technically it should be a +0 quark, but we require NULL so compilers that support it can check for +the NULL terminator and warn if it's not there).

+

This function is just like gst_structure_get() only that it is slightly +more efficient since it saves the string-to-quark lookup in the global +quark hashtable.

+

For refcounted (mini)objects you will receive a new reference which +you must release with a suitable _unref() when no longer needed. For +strings and boxed types you will receive a copy which you will need to +release with either g_free() or the suitable function for the boxed type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

first_field_id

the quark of the first field to read

 

...

variable arguments

 
+
+
+

Returns

+

FALSE if there was a problem reading any of the fields (e.g. +because the field requested did not exist, or was of a type other +than the type specified), otherwise TRUE.

+
+
+
+
+

gst_structure_id_get_valist ()

+
gboolean
+gst_structure_id_get_valist (const GstStructure *structure,
+                             GQuark first_field_id,
+                             va_list args);
+

Parses the variable arguments and reads fields from structure + accordingly. +valist-variant of gst_structure_id_get(). Look at the documentation of +gst_structure_id_get() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

first_field_id

the quark of the first field to read

 

args

variable arguments

 
+
+
+

Returns

+

TRUE, or FALSE if there was a problem reading any of the fields

+
+
+
+
+

gst_structure_id_get_value ()

+
const GValue *
+gst_structure_id_get_value (const GstStructure *structure,
+                            GQuark field);
+

Get the value of the field with GQuark field +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

field

the GQuark of the field to get

 
+
+
+

Returns

+

the GValue corresponding to the field with the given +name identifier.

+

[nullable]

+
+
+
+
+

gst_structure_id_set_value ()

+
void
+gst_structure_id_set_value (GstStructure *structure,
+                            GQuark field,
+                            const GValue *value);
+

Sets the field with the given GQuark field + to value +. If the field +does not exist, it is created. If the field exists, the previous +value is replaced and freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field

a GQuark representing a field

 

value

the new value of the field

 
+
+
+
+
+

gst_structure_id_take_value ()

+
void
+gst_structure_id_take_value (GstStructure *structure,
+                             GQuark field,
+                             GValue *value);
+

Sets the field with the given GQuark field + to value +. If the field +does not exist, it is created. If the field exists, the previous +value is replaced and freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field

a GQuark representing a field

 

value

the new value of the field.

[transfer full]
+
+
+
+
+

gst_structure_get ()

+
gboolean
+gst_structure_get (const GstStructure *structure,
+                   const char *first_fieldname,
+                   ...);
+

Parses the variable arguments and reads fields from structure + accordingly. +Variable arguments should be in the form field name, field type +(as a GType), pointer(s) to a variable(s) to hold the return value(s). +The last variable argument should be NULL.

+

For refcounted (mini)objects you will receive a new reference which +you must release with a suitable _unref() when no longer needed. For +strings and boxed types you will receive a copy which you will need to +release with either g_free() or the suitable function for the boxed type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

first_fieldname

the name of the first field to read

 

...

variable arguments

 
+
+
+

Returns

+

FALSE if there was a problem reading any of the fields (e.g. +because the field requested did not exist, or was of a type other +than the type specified), otherwise TRUE.

+
+
+
+
+

gst_structure_get_valist ()

+
gboolean
+gst_structure_get_valist (const GstStructure *structure,
+                          const char *first_fieldname,
+                          va_list args);
+

Parses the variable arguments and reads fields from structure + accordingly. +valist-variant of gst_structure_get(). Look at the documentation of +gst_structure_get() for more details.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

first_fieldname

the name of the first field to read

 

args

variable arguments

 
+
+
+

Returns

+

TRUE, or FALSE if there was a problem reading any of the fields

+
+
+
+
+

gst_structure_get_value ()

+
const GValue *
+gst_structure_get_value (const GstStructure *structure,
+                         const gchar *fieldname);
+

Get the value of the field with name fieldname +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to get

 
+
+
+

Returns

+

the GValue corresponding to the field with the given +name.

+

[nullable]

+
+
+
+
+

gst_structure_set_value ()

+
void
+gst_structure_set_value (GstStructure *structure,
+                         const gchar *fieldname,
+                         const GValue *value);
+

Sets the field with the given name field + to value +. If the field +does not exist, it is created. If the field exists, the previous +value is replaced and freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to set

 

value

the new value of the field

 
+
+
+
+
+

gst_structure_set_array ()

+
void
+gst_structure_set_array (GstStructure *structure,
+                         const gchar *fieldname,
+                         const GValueArray *array);
+

This is useful in language bindings where unknown GValue types are not +supported. This function will convert a array + to GST_TYPE_ARRAY and set +the field specified by fieldname +. Be aware that this is slower then using +GST_TYPE_ARRAY in a GValue directly.

+

Since 1.12

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

array

a pointer to a GValueArray

 
+
+
+
+
+

gst_structure_set_list ()

+
void
+gst_structure_set_list (GstStructure *structure,
+                        const gchar *fieldname,
+                        const GValueArray *array);
+

This is useful in language bindings where unknown GValue types are not +supported. This function will convert a array + to GST_TYPE_ARRAY and set +the field specified by fieldname +. Be aware that this is slower then using +GST_TYPE_ARRAY in a GValue directly.

+

Since 1.12

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

array

a pointer to a GValueArray

 
+
+
+
+
+

gst_structure_take_value ()

+
void
+gst_structure_take_value (GstStructure *structure,
+                          const gchar *fieldname,
+                          GValue *value);
+

Sets the field with the given name field + to value +. If the field +does not exist, it is created. If the field exists, the previous +value is replaced and freed. The function will take ownership of value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to set

 

value

the new value of the field.

[transfer full]
+
+
+
+
+

gst_structure_set ()

+
void
+gst_structure_set (GstStructure *structure,
+                   const gchar *fieldname,
+                   ...);
+

Parses the variable arguments and sets fields accordingly. Fields that +weren't already part of the structure are added as needed. +Variable arguments should be in the form field name, field type +(as a GType), value(s). The last variable argument should be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to set

 

...

variable arguments

 
+
+
+
+
+

gst_structure_set_valist ()

+
void
+gst_structure_set_valist (GstStructure *structure,
+                          const gchar *fieldname,
+                          va_list varargs);
+

va_list form of gst_structure_set().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to set

 

varargs

variable arguments

 
+
+
+
+
+

gst_structure_id_set ()

+
void
+gst_structure_id_set (GstStructure *structure,
+                      GQuark fieldname,
+                      ...);
+

Identical to gst_structure_set, except that field names are +passed using the GQuark for the field name. This allows more efficient +setting of the structure if the caller already knows the associated +quark values. +The last variable argument must be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the GQuark for the name of the field to set

 

...

variable arguments

 
+
+
+
+
+

gst_structure_id_set_valist ()

+
void
+gst_structure_id_set_valist (GstStructure *structure,
+                             GQuark fieldname,
+                             va_list varargs);
+

va_list form of gst_structure_id_set().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to set

 

varargs

variable arguments

 
+
+
+
+
+

gst_structure_remove_field ()

+
void
+gst_structure_remove_field (GstStructure *structure,
+                            const gchar *fieldname);
+

Removes the field with the given name. If the field with the given +name does not exist, the structure is unchanged.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to remove

 
+
+
+
+
+

gst_structure_remove_fields ()

+
void
+gst_structure_remove_fields (GstStructure *structure,
+                             const gchar *fieldname,
+                             ...);
+

Removes the fields with the given names. If a field does not exist, the +argument is ignored.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to remove

 

...

NULL-terminated list of more fieldnames to remove

 
+
+
+
+
+

gst_structure_remove_fields_valist ()

+
void
+gst_structure_remove_fields_valist (GstStructure *structure,
+                                    const gchar *fieldname,
+                                    va_list varargs);
+

va_list form of gst_structure_remove_fields().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field to remove

 

varargs

NULL-terminated list of more fieldnames to remove

 
+
+
+
+
+

gst_structure_remove_all_fields ()

+
void
+gst_structure_remove_all_fields (GstStructure *structure);
+

Removes all fields in a GstStructure.

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+
+
+

gst_structure_get_field_type ()

+
GType
+gst_structure_get_field_type (const GstStructure *structure,
+                              const gchar *fieldname);
+

Finds the field with the given name, and returns the type of the +value it contains. If the field is not found, G_TYPE_INVALID is +returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of the field

 
+
+
+

Returns

+

the GValue of the field

+
+
+
+
+

gst_structure_n_fields ()

+
gint
+gst_structure_n_fields (const GstStructure *structure);
+

Get the number of fields in the structure.

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+

Returns

+

the number of fields in the structure

+
+
+
+
+

gst_structure_has_field ()

+
gboolean
+gst_structure_has_field (const GstStructure *structure,
+                         const gchar *fieldname);
+

Check if structure + contains a field named fieldname +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 
+
+
+

Returns

+

TRUE if the structure contains a field with the given name

+
+
+
+
+

gst_structure_has_field_typed ()

+
gboolean
+gst_structure_has_field_typed (const GstStructure *structure,
+                               const gchar *fieldname,
+                               GType type);
+

Check if structure + contains a field named fieldname + and with GType type +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

type

the type of a value

 
+
+
+

Returns

+

TRUE if the structure contains a field with the given name and type

+
+
+
+
+

gst_structure_is_equal ()

+
gboolean
+gst_structure_is_equal (const GstStructure *structure1,
+                        const GstStructure *structure2);
+

Tests if the two GstStructure are equal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure1

a GstStructure.

 

structure2

a GstStructure.

 
+
+
+

Returns

+

TRUE if the two structures have the same name and field.

+
+
+
+
+

gst_structure_is_subset ()

+
gboolean
+gst_structure_is_subset (const GstStructure *subset,
+                         const GstStructure *superset);
+

Checks if subset + is a subset of superset +, i.e. has the same +structure name and for all fields that are existing in superset +, +subset + has a value that is a subset of the value in superset +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

subset

a GstStructure

 

superset

a potentially greater GstStructure

 
+
+
+

Returns

+

TRUE if subset +is a subset of superset +

+
+
+
+
+

gst_structure_can_intersect ()

+
gboolean
+gst_structure_can_intersect (const GstStructure *struct1,
+                             const GstStructure *struct2);
+

Tries intersecting struct1 + and struct2 + and reports whether the result +would not be empty.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

struct1

a GstStructure

 

struct2

a GstStructure

 
+
+
+

Returns

+

TRUE if intersection would not be empty

+
+
+
+
+

gst_structure_intersect ()

+
GstStructure *
+gst_structure_intersect (const GstStructure *struct1,
+                         const GstStructure *struct2);
+

Intersects struct1 + and struct2 + and returns the intersection.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

struct1

a GstStructure

 

struct2

a GstStructure

 
+
+
+

Returns

+

Intersection of struct1 +and struct2 +.

+

[nullable]

+
+
+
+
+

gst_structure_id_has_field ()

+
gboolean
+gst_structure_id_has_field (const GstStructure *structure,
+                            GQuark field);
+

Check if structure + contains a field named field +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

field

GQuark of the field name

 
+
+
+

Returns

+

TRUE if the structure contains a field with the given name

+
+
+
+
+

gst_structure_id_has_field_typed ()

+
gboolean
+gst_structure_id_has_field_typed (const GstStructure *structure,
+                                  GQuark field,
+                                  GType type);
+

Check if structure + contains a field named field + and with GType type +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field

GQuark of the field name

 

type

the type of a value

 
+
+
+

Returns

+

TRUE if the structure contains a field with the given name and type

+
+
+
+
+

gst_structure_get_boolean ()

+
gboolean
+gst_structure_get_boolean (const GstStructure *structure,
+                           const gchar *fieldname,
+                           gboolean *value);
+

Sets the boolean pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a gboolean to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a boolean, this +function returns FALSE.

+
+
+
+
+

gst_structure_get_int ()

+
gboolean
+gst_structure_get_int (const GstStructure *structure,
+                       const gchar *fieldname,
+                       gint *value);
+

Sets the int pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to an int to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain an int, this function +returns FALSE.

+
+
+
+
+

gst_structure_get_uint ()

+
gboolean
+gst_structure_get_uint (const GstStructure *structure,
+                        const gchar *fieldname,
+                        guint *value);
+

Sets the uint pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a uint to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a uint, this function +returns FALSE.

+
+
+
+
+

gst_structure_get_int64 ()

+
gboolean
+gst_structure_get_int64 (const GstStructure *structure,
+                         const gchar *fieldname,
+                         gint64 *value);
+

Sets the gint64 pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a gint64 to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a gint64, this function +returns FALSE.

+
+

Since: 1.4

+
+
+
+

gst_structure_get_uint64 ()

+
gboolean
+gst_structure_get_uint64 (const GstStructure *structure,
+                          const gchar *fieldname,
+                          guint64 *value);
+

Sets the guint64 pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a guint64 to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a guint64, this function +returns FALSE.

+
+

Since: 1.4

+
+
+
+

gst_structure_get_double ()

+
gboolean
+gst_structure_get_double (const GstStructure *structure,
+                          const gchar *fieldname,
+                          gdouble *value);
+

Sets the double pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a gdouble to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a double, this +function returns FALSE.

+
+
+
+
+

gst_structure_get_string ()

+
const gchar *
+gst_structure_get_string (const GstStructure *structure,
+                          const gchar *fieldname);
+

Finds the field corresponding to fieldname +, and returns the string +contained in the field's value. Caller is responsible for making +sure the field exists and has the correct type.

+

The string should not be modified, and remains valid until the next +call to a gst_structure_*() function with the given structure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 
+
+
+

Returns

+

a pointer to the string or NULL when the +field did not exist or did not contain a string.

+

[nullable]

+
+
+
+
+

gst_structure_get_date ()

+
gboolean
+gst_structure_get_date (const GstStructure *structure,
+                        const gchar *fieldname,
+                        GDate **value);
+

Sets the date pointed to by value + corresponding to the date of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+

On success value + will point to a newly-allocated copy of the date which +should be freed with g_date_free() when no longer needed (note: this is +inconsistent with e.g. gst_structure_get_string() which doesn't return a +copy of the string).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a GDate to set.

[out callee-allocates]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a data, this function +returns FALSE.

+
+
+
+
+

gst_structure_get_date_time ()

+
gboolean
+gst_structure_get_date_time (const GstStructure *structure,
+                             const gchar *fieldname,
+                             GstDateTime **value);
+

Sets the datetime pointed to by value + corresponding to the datetime of the +given field. Caller is responsible for making sure the field exists +and has the correct type.

+

On success value + will point to a reference of the datetime which +should be unreffed with gst_date_time_unref() when no longer needed +(note: this is inconsistent with e.g. gst_structure_get_string() +which doesn't return a copy of the string).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a GstDateTime to set.

[out callee-allocates]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a data, this function +returns FALSE.

+
+
+
+
+

gst_structure_get_clock_time ()

+
gboolean
+gst_structure_get_clock_time (const GstStructure *structure,
+                              const gchar *fieldname,
+                              GstClockTime *value);
+

Sets the clock time pointed to by value + corresponding to the clock time +of the given field. Caller is responsible for making sure the field exists +and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value

a pointer to a GstClockTime to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain a GstClockTime, this +function returns FALSE.

+
+
+
+
+

gst_structure_get_enum ()

+
gboolean
+gst_structure_get_enum (const GstStructure *structure,
+                        const gchar *fieldname,
+                        GType enumtype,
+                        gint *value);
+

Sets the int pointed to by value + corresponding to the value of the +given field. Caller is responsible for making sure the field exists, +has the correct type and that the enumtype is correct.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

enumtype

the enum type of a field

 

value

a pointer to an int to set.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain an enum of the given +type, this function returns FALSE.

+
+
+
+
+

gst_structure_get_fraction ()

+
gboolean
+gst_structure_get_fraction (const GstStructure *structure,
+                            const gchar *fieldname,
+                            gint *value_numerator,
+                            gint *value_denominator);
+

Sets the integers pointed to by value_numerator + and value_denominator + +corresponding to the value of the given field. Caller is responsible +for making sure the field exists and has the correct type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value_numerator

a pointer to an int to set.

[out]

value_denominator

a pointer to an int to set.

[out]
+
+
+

Returns

+

TRUE if the values could be set correctly. If there was no field +with fieldname +or the existing field did not contain a GstFraction, this +function returns FALSE.

+
+
+
+
+

gst_structure_get_array ()

+
gboolean
+gst_structure_get_array (GstStructure *structure,
+                         const gchar *fieldname,
+                         GValueArray **array);
+

This is useful in language bindings where unknown GValue types are not +supported. This function will convert the GST_TYPE_ARRAY and +GST_TYPE_LIST into a newly allocated GValueArray and return it through +array +. Be aware that this is slower then getting the GValue directly.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

array

a pointer to a GValueArray.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain an int, this function +returns FALSE.

+
+
+
+
+

gst_structure_get_list ()

+
gboolean
+gst_structure_get_list (GstStructure *structure,
+                        const gchar *fieldname,
+                        GValueArray **array);
+

This is useful in language bindings where unknown GValue types are not +supported. This function will convert the GST_TYPE_ARRAY and +GST_TYPE_LIST into a newly allocated GValueArray and return it through +array +. Be aware that this is slower then getting the GValue directly.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

array

a pointer to a GValueArray.

[out]
+
+
+

Returns

+

TRUE if the value could be set correctly. If there was no field +with fieldname +or the existing field did not contain an int, this function +returns FALSE.

+

Since 1.12

+
+
+
+
+

gst_structure_foreach ()

+
gboolean
+gst_structure_foreach (const GstStructure *structure,
+                       GstStructureForeachFunc func,
+                       gpointer user_data);
+

Calls the provided function once for each field in the GstStructure. The +function must not modify the fields. Also see gst_structure_map_in_place() +and gst_structure_filter_and_map_in_place().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+
+

Returns

+

TRUE if the supplied function returns TRUE For each of the fields, +FALSE otherwise.

+
+
+
+
+

gst_structure_map_in_place ()

+
gboolean
+gst_structure_map_in_place (GstStructure *structure,
+                            GstStructureMapFunc func,
+                            gpointer user_data);
+

Calls the provided function once for each field in the GstStructure. In +contrast to gst_structure_foreach(), the function may modify but not delete the +fields. The structure must be mutable.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+
+

Returns

+

TRUE if the supplied function returns TRUE For each of the fields, +FALSE otherwise.

+
+
+
+
+

gst_structure_filter_and_map_in_place ()

+
void
+gst_structure_filter_and_map_in_place (GstStructure *structure,
+                                       GstStructureFilterMapFunc func,
+                                       gpointer user_data);
+

Calls the provided function once for each field in the GstStructure. In +contrast to gst_structure_foreach(), the function may modify the fields. +In contrast to gst_structure_map_in_place(), the field is removed from +the structure if FALSE is returned from the function. +The structure must be mutable.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

func

a function to call for each field.

[scope call]

user_data

private data.

[closure]
+
+

Since: 1.6

+
+
+
+

gst_structure_nth_field_name ()

+
const gchar *
+gst_structure_nth_field_name (const GstStructure *structure,
+                              guint index);
+

Get the name of the given field number, counting from 0 onwards.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

index

the index to get the name of

 
+
+
+

Returns

+

the name of the given field number

+
+
+
+
+

gst_structure_set_parent_refcount ()

+
gboolean
+gst_structure_set_parent_refcount (GstStructure *structure,
+                                   gint *refcount);
+

Sets the parent_refcount field of GstStructure. This field is used to +determine whether a structure is mutable or not. This function should only be +called by code implementing parent objects of GstStructure, as described in +the MT Refcounting section of the design documents.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

refcount

a pointer to the parent's refcount.

[in]
+
+
+

Returns

+

TRUE if the parent refcount could be set.

+
+
+
+
+

gst_structure_to_string ()

+
gchar *
+gst_structure_to_string (const GstStructure *structure);
+

Converts structure + to a human-readable string representation.

+

For debugging purposes its easier to do something like this:

+
+ + + + + + + +
1
GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
+
+ +

+This prints the structure in human readable form.

+

The current implementation of serialization will lead to unexpected results +when there are nested GstCaps / GstStructure deeper than one level.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+

Returns

+

a pointer to string allocated by g_malloc(). +g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_structure_from_string ()

+
GstStructure *
+gst_structure_from_string (const gchar *string,
+                           gchar **end);
+

Creates a GstStructure from a string representation. +If end is not NULL, a pointer to the place inside the given string +where parsing ended will be returned.

+

Free-function: gst_structure_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

string

a string representation of a GstStructure.

 

end

pointer to store the end of the string in.

[out][allow-none][transfer none][skip]
+
+
+

Returns

+

a new GstStructure or NULL +when the string could not be parsed. Free with +gst_structure_free() after use.

+

[transfer full][nullable]

+
+
+
+
+

gst_structure_fixate ()

+
void
+gst_structure_fixate (GstStructure *structure);
+

Fixate all values in structure + using gst_value_fixate(). +structure + will be modified in-place and should be writable.

+
+

Parameters

+
+++++ + + + + + +

structure

a GstStructure

 
+
+
+
+
+

gst_structure_fixate_field ()

+
gboolean
+gst_structure_fixate_field (GstStructure *structure,
+                            const char *field_name);
+

Fixates a GstStructure by changing the given field with its fixated value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 
+
+
+

Returns

+

TRUE if the structure field could be fixated

+
+
+
+
+

gst_structure_fixate_field_nearest_int ()

+
gboolean
+gst_structure_fixate_field_nearest_int
+                               (GstStructure *structure,
+                                const char *field_name,
+                                int target);
+

Fixates a GstStructure by changing the given field to the nearest +integer to target + that is a subset of the existing field.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 

target

the target value of the fixation

 
+
+
+

Returns

+

TRUE if the structure could be fixated

+
+
+
+
+

gst_structure_fixate_field_nearest_double ()

+
gboolean
+gst_structure_fixate_field_nearest_double
+                               (GstStructure *structure,
+                                const char *field_name,
+                                double target);
+

Fixates a GstStructure by changing the given field to the nearest +double to target + that is a subset of the existing field.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 

target

the target value of the fixation

 
+
+
+

Returns

+

TRUE if the structure could be fixated

+
+
+
+
+

gst_structure_fixate_field_nearest_fraction ()

+
gboolean
+gst_structure_fixate_field_nearest_fraction
+                               (GstStructure *structure,
+                                const char *field_name,
+                                const gint target_numerator,
+                                const gint target_denominator);
+

Fixates a GstStructure by changing the given field to the nearest +fraction to target_numerator +/target_denominator + that is a subset +of the existing field.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 

target_numerator

The numerator of the target value of the fixation

 

target_denominator

The denominator of the target value of the fixation

 
+
+
+

Returns

+

TRUE if the structure could be fixated

+
+
+
+
+

gst_structure_fixate_field_boolean ()

+
gboolean
+gst_structure_fixate_field_boolean (GstStructure *structure,
+                                    const char *field_name,
+                                    gboolean target);
+

Fixates a GstStructure by changing the given field_name + field to the given +target + boolean if that field is not fixed yet.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 

target

the target value of the fixation

 
+
+
+

Returns

+

TRUE if the structure could be fixated

+
+
+
+
+

gst_structure_fixate_field_string ()

+
gboolean
+gst_structure_fixate_field_string (GstStructure *structure,
+                                   const char *field_name,
+                                   const gchar *target);
+

Fixates a GstStructure by changing the given field_name + field to the given +target + string if that field is not fixed yet.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

field_name

a field in structure +

 

target

the target value of the fixation

 
+
+
+

Returns

+

TRUE if the structure could be fixated

+
+
+
+
+

Types and Values

+
+

struct GstStructure

+
struct GstStructure {
+  GType type;
+};
+
+

The GstStructure object. Most fields are private.

+
+

Members

+
+++++ + + + + + +

GType type;

the GType of a structure

 
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstSystemClock.html b/docs/gst/html/GstSystemClock.html new file mode 100644 index 0000000..5e3166d --- /dev/null +++ b/docs/gst/html/GstSystemClock.html @@ -0,0 +1,231 @@ + + + + +GstSystemClock: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstSystemClock

+

GstSystemClock — Default clock that uses the current system time

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GstClock * + +gst_system_clock_obtain () +
+void + +gst_system_clock_set_default () +
+
+
+

Properties

+
+++++ + + + + + +
GstClockTypeclock-typeRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
enumGstClockType
structGstSystemClock
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstClock
+                ╰── GstSystemClock
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

The GStreamer core provides a GstSystemClock based on the system time. +Asynchronous callbacks are scheduled from an internal thread.

+

Clock implementors are encouraged to subclass this systemclock as it +implements the async notification.

+

Subclasses can however override all of the important methods for sync and +async notifications to implement their own callback methods or blocking +wait operations.

+
+
+

Functions

+
+

gst_system_clock_obtain ()

+
GstClock *
+gst_system_clock_obtain (void);
+

Get a handle to the default system clock. The refcount of the +clock will be increased so you need to unref the clock after +usage.

+
+

Returns

+

the default clock.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_system_clock_set_default ()

+
void
+gst_system_clock_set_default (GstClock *new_clock);
+

Sets the default system clock that can be obtained with +gst_system_clock_obtain().

+

This is mostly used for testing and debugging purposes when you +want to have control over the time reported by the default system +clock.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

new_clock

a GstClock.

[allow-none]
+
+

Since: 1.4

+
+
+
+

Types and Values

+
+

enum GstClockType

+

The different kind of clocks.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_CLOCK_TYPE_REALTIME

+

time since Epoch

+
 

GST_CLOCK_TYPE_MONOTONIC

+

monotonic time since some unspecified starting + point

+
 

GST_CLOCK_TYPE_OTHER

+

some other time source is used (Since 1.0.5)

+
 
+
+
+
+
+

struct GstSystemClock

+
struct GstSystemClock;
+

The default implementation of a GstClock that uses the system time.

+
+
+
+

Property Details

+
+

The “clock-type” property

+
  “clock-type”               GstClockType
+

The type of underlying clock implementation used.

+

Flags: Read / Write

+

Default value: GST_CLOCK_TYPE_MONOTONIC

+
+
+
+

See Also

+

GstClock

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTagList.html b/docs/gst/html/GstTagList.html new file mode 100644 index 0000000..796ba5c --- /dev/null +++ b/docs/gst/html/GstTagList.html @@ -0,0 +1,4448 @@ + + + + +GstTagList: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTagList

+

GstTagList — List of tags and values used to describe media metadata

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstTagForeachFunc) () +
+void + +(*GstTagMergeFunc) () +
+void + +gst_tag_register () +
+void + +gst_tag_register_static () +
+void + +gst_tag_merge_use_first () +
+void + +gst_tag_merge_strings_with_comma () +
+gboolean + +gst_tag_exists () +
+GType + +gst_tag_get_type () +
const gchar * + +gst_tag_get_nick () +
const gchar * + +gst_tag_get_description () +
+GstTagFlag + +gst_tag_get_flag () +
+gboolean + +gst_tag_is_fixed () +
+GstTagList * + +gst_tag_list_new () +
+GstTagList * + +gst_tag_list_new_empty () +
+GstTagList * + +gst_tag_list_new_valist () +
+GstTagList * + +gst_tag_list_new_from_string () +
#define +gst_tag_list_free() +
+GstTagScope + +gst_tag_list_get_scope () +
+void + +gst_tag_list_set_scope () +
+gchar * + +gst_tag_list_to_string () +
+gboolean + +gst_tag_list_is_empty () +
+gboolean + +gst_tag_list_is_equal () +
+GstTagList * + +gst_tag_list_copy () +
+GstTagList * + +gst_tag_list_ref () +
+void + +gst_tag_list_unref () +
#define +gst_tag_list_is_writable() +
#define +gst_tag_list_make_writable() +
+void + +gst_tag_list_insert () +
+GstTagList * + +gst_tag_list_merge () +
+guint + +gst_tag_list_get_tag_size () +
+gint + +gst_tag_list_n_tags () +
const gchar * + +gst_tag_list_nth_tag_name () +
+void + +gst_tag_list_add () +
+void + +gst_tag_list_add_value () +
+void + +gst_tag_list_add_values () +
+void + +gst_tag_list_add_valist () +
+void + +gst_tag_list_add_valist_values () +
+void + +gst_tag_list_remove_tag () +
+void + +gst_tag_list_foreach () +
const GValue * + +gst_tag_list_get_value_index () +
+gboolean + +gst_tag_list_copy_value () +
+gboolean + +gst_tag_list_get_boolean () +
+gboolean + +gst_tag_list_get_boolean_index () +
+gboolean + +gst_tag_list_get_int () +
+gboolean + +gst_tag_list_get_int_index () +
+gboolean + +gst_tag_list_get_uint () +
+gboolean + +gst_tag_list_get_uint_index () +
+gboolean + +gst_tag_list_get_int64 () +
+gboolean + +gst_tag_list_get_int64_index () +
+gboolean + +gst_tag_list_get_uint64 () +
+gboolean + +gst_tag_list_get_uint64_index () +
+gboolean + +gst_tag_list_get_float () +
+gboolean + +gst_tag_list_get_float_index () +
+gboolean + +gst_tag_list_get_double () +
+gboolean + +gst_tag_list_get_double_index () +
+gboolean + +gst_tag_list_get_string () +
+gboolean + +gst_tag_list_get_string_index () +
+gboolean + +gst_tag_list_peek_string_index () +
+gboolean + +gst_tag_list_get_pointer () +
+gboolean + +gst_tag_list_get_pointer_index () +
+gboolean + +gst_tag_list_get_date () +
+gboolean + +gst_tag_list_get_date_index () +
+gboolean + +gst_tag_list_get_date_time () +
+gboolean + +gst_tag_list_get_date_time_index () +
+gboolean + +gst_tag_list_get_sample () +
+gboolean + +gst_tag_list_get_sample_index () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstTagList
enumGstTagMergeMode
enumGstTagFlag
enumGstTagScope
#defineGST_TAG_TITLE
#defineGST_TAG_TITLE_SORTNAME
#defineGST_TAG_ARTIST
#defineGST_TAG_ARTIST_SORTNAME
#defineGST_TAG_ALBUM
#defineGST_TAG_ALBUM_SORTNAME
#defineGST_TAG_ALBUM_ARTIST
#defineGST_TAG_ALBUM_ARTIST_SORTNAME
#defineGST_TAG_DATE
#defineGST_TAG_DATE_TIME
#defineGST_TAG_GENRE
#defineGST_TAG_COMMENT
#defineGST_TAG_EXTENDED_COMMENT
#defineGST_TAG_TRACK_NUMBER
#defineGST_TAG_TRACK_COUNT
#defineGST_TAG_ALBUM_VOLUME_NUMBER
#defineGST_TAG_ALBUM_VOLUME_COUNT
#defineGST_TAG_LOCATION
#defineGST_TAG_HOMEPAGE
#defineGST_TAG_DESCRIPTION
#defineGST_TAG_VERSION
#defineGST_TAG_ISRC
#defineGST_TAG_ORGANIZATION
#defineGST_TAG_COPYRIGHT
#defineGST_TAG_COPYRIGHT_URI
#defineGST_TAG_ENCODED_BY
#defineGST_TAG_COMPOSER
#defineGST_TAG_CONDUCTOR
#defineGST_TAG_CONTACT
#defineGST_TAG_LICENSE
#defineGST_TAG_LICENSE_URI
#defineGST_TAG_PERFORMER
#defineGST_TAG_DURATION
#defineGST_TAG_CODEC
#defineGST_TAG_VIDEO_CODEC
#defineGST_TAG_AUDIO_CODEC
#defineGST_TAG_SUBTITLE_CODEC
#defineGST_TAG_CONTAINER_FORMAT
#defineGST_TAG_BITRATE
#defineGST_TAG_NOMINAL_BITRATE
#defineGST_TAG_MINIMUM_BITRATE
#defineGST_TAG_MAXIMUM_BITRATE
#defineGST_TAG_SERIAL
#defineGST_TAG_ENCODER
#defineGST_TAG_ENCODER_VERSION
#defineGST_TAG_TRACK_GAIN
#defineGST_TAG_TRACK_PEAK
#defineGST_TAG_ALBUM_GAIN
#defineGST_TAG_ALBUM_PEAK
#defineGST_TAG_REFERENCE_LEVEL
#defineGST_TAG_LANGUAGE_CODE
#defineGST_TAG_LANGUAGE_NAME
#defineGST_TAG_IMAGE
#defineGST_TAG_PREVIEW_IMAGE
#defineGST_TAG_ATTACHMENT
#defineGST_TAG_BEATS_PER_MINUTE
#defineGST_TAG_KEYWORDS
#defineGST_TAG_GEO_LOCATION_NAME
#defineGST_TAG_GEO_LOCATION_LATITUDE
#defineGST_TAG_GEO_LOCATION_LONGITUDE
#defineGST_TAG_GEO_LOCATION_ELEVATION
#defineGST_TAG_GEO_LOCATION_CITY
#defineGST_TAG_GEO_LOCATION_COUNTRY
#defineGST_TAG_GEO_LOCATION_SUBLOCATION
#defineGST_TAG_GEO_LOCATION_HORIZONTAL_ERROR
#defineGST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION
#defineGST_TAG_GEO_LOCATION_MOVEMENT_SPEED
#defineGST_TAG_GEO_LOCATION_CAPTURE_DIRECTION
#defineGST_TAG_SHOW_NAME
#defineGST_TAG_SHOW_SORTNAME
#defineGST_TAG_SHOW_EPISODE_NUMBER
#defineGST_TAG_SHOW_SEASON_NUMBER
#defineGST_TAG_LYRICS
#defineGST_TAG_COMPOSER_SORTNAME
#defineGST_TAG_GROUPING
#defineGST_TAG_USER_RATING
#defineGST_TAG_DEVICE_MANUFACTURER
#defineGST_TAG_DEVICE_MODEL
#defineGST_TAG_APPLICATION_NAME
#defineGST_TAG_APPLICATION_DATA
#defineGST_TAG_IMAGE_ORIENTATION
#defineGST_TAG_PUBLISHER
#defineGST_TAG_INTERPRETED_BY
#defineGST_TAG_MIDI_BASE_NOTE
#defineGST_TAG_PRIVATE_DATA
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstTagList
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

List of tags and values used to describe media metadata.

+

Strings in structures must be ASCII or UTF-8 encoded. Other encodings are +not allowed. Strings must not be empty or NULL.

+
+
+

Functions

+
+

GstTagForeachFunc ()

+
void
+(*GstTagForeachFunc) (const GstTagList *list,
+                      const gchar *tag,
+                      gpointer user_data);
+

A function that will be called in gst_tag_list_foreach(). The function may +not modify the tag list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

the GstTagList

 

tag

a name of a tag in list +

 

user_data

user data

 
+
+
+
+
+

GstTagMergeFunc ()

+
void
+(*GstTagMergeFunc) (GValue *dest,
+                    const GValue *src);
+

A function for merging multiple values of a tag used when registering +tags.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

the destination GValue

 

src

the source GValue

 
+
+
+
+
+

gst_tag_register ()

+
void
+gst_tag_register (const gchar *name,
+                  GstTagFlag flag,
+                  GType type,
+                  const gchar *nick,
+                  const gchar *blurb,
+                  GstTagMergeFunc func);
+

Registers a new tag type for the use with GStreamer's type system. If a type +with that name is already registered, that one is used. +The old registration may have used a different type however. So don't rely +on your supplied values.

+

Important: if you do not supply a merge function the implication will be +that there can only be one single value for this tag in a tag list and +any additional values will silently be discarded when being added (unless +GST_TAG_MERGE_REPLACE, GST_TAG_MERGE_REPLACE_ALL, or +GST_TAG_MERGE_PREPEND is used as merge mode, in which case the new +value will replace the old one in the list).

+

The merge function will be called from gst_tag_list_copy_value() when +it is required that one or more values for a tag be condensed into +one single value. This may happen from gst_tag_list_get_string(), +gst_tag_list_get_int(), gst_tag_list_get_double() etc. What will happen +exactly in that case depends on how the tag was registered and if a +merge function was supplied and if so which one.

+

Two default merge functions are provided: gst_tag_merge_use_first() and +gst_tag_merge_strings_with_comma().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

the name or identifier string

 

flag

a flag describing the type of tag info

 

type

the type this data is in

 

nick

human-readable name

 

blurb

a human-readable description about this tag

 

func

function for merging multiple values of this tag, or NULL.

[allow-none][scope call]
+
+
+
+
+

gst_tag_register_static ()

+
void
+gst_tag_register_static (const gchar *name,
+                         GstTagFlag flag,
+                         GType type,
+                         const gchar *nick,
+                         const gchar *blurb,
+                         GstTagMergeFunc func);
+

Registers a new tag type for the use with GStreamer's type system.

+

Same as gst_tag_register(), but name +, nick +, and blurb + must be +static strings or inlined strings, as they will not be copied. (GStreamer +plugins will be made resident once loaded, so this function can be used +even from dynamically loaded plugins.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

the name or identifier string (string constant)

 

flag

a flag describing the type of tag info

 

type

the type this data is in

 

nick

human-readable name or short description (string constant)

 

blurb

a human-readable description for this tag (string constant)

 

func

function for merging multiple values of this tag, or NULL.

[allow-none][scope call]
+
+
+
+
+

gst_tag_merge_use_first ()

+
void
+gst_tag_merge_use_first (GValue *dest,
+                         const GValue *src);
+

This is a convenience function for the func argument of gst_tag_register(). +It creates a copy of the first value from the list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

uninitialized GValue to store result in.

[out caller-allocates]

src

GValue to copy from

 
+
+
+
+
+

gst_tag_merge_strings_with_comma ()

+
void
+gst_tag_merge_strings_with_comma (GValue *dest,
+                                  const GValue *src);
+

This is a convenience function for the func argument of gst_tag_register(). +It concatenates all given strings using a comma. The tag must be registered +as a G_TYPE_STRING or this function will fail.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

uninitialized GValue to store result in.

[out caller-allocates]

src

GValue to copy from

 
+
+
+
+
+

gst_tag_exists ()

+
gboolean
+gst_tag_exists (const gchar *tag);
+

Checks if the given type is already registered.

+
+

Parameters

+
+++++ + + + + + +

tag

name of the tag

 
+
+
+

Returns

+

TRUE if the type is already registered

+
+
+
+
+

gst_tag_get_type ()

+
GType
+gst_tag_get_type (const gchar *tag);
+

Gets the GType used for this tag.

+
+

Parameters

+
+++++ + + + + + +

tag

the tag

 
+
+
+

Returns

+

the GType of this tag

+
+
+
+
+

gst_tag_get_nick ()

+
const gchar *
+gst_tag_get_nick (const gchar *tag);
+

Returns the human-readable name of this tag, You must not change or free +this string.

+
+

Parameters

+
+++++ + + + + + +

tag

the tag

 
+
+
+

Returns

+

the human-readable name of this tag.

+

[nullable]

+
+
+
+
+

gst_tag_get_description ()

+
const gchar *
+gst_tag_get_description (const gchar *tag);
+

Returns the human-readable description of this tag, You must not change or +free this string.

+
+

Parameters

+
+++++ + + + + + +

tag

the tag

 
+
+
+

Returns

+

the human-readable description of this tag.

+

[nullable]

+
+
+
+
+

gst_tag_get_flag ()

+
GstTagFlag
+gst_tag_get_flag (const gchar *tag);
+

Gets the flag of tag +.

+
+

Parameters

+
+++++ + + + + + +

tag

the tag

 
+
+
+

Returns

+

the flag of this tag.

+
+
+
+
+

gst_tag_is_fixed ()

+
gboolean
+gst_tag_is_fixed (const gchar *tag);
+

Checks if the given tag is fixed. A fixed tag can only contain one value. +Unfixed tags can contain lists of values.

+
+

Parameters

+
+++++ + + + + + +

tag

tag to check

 
+
+
+

Returns

+

TRUE, if the given tag is fixed.

+
+
+
+
+

gst_tag_list_new ()

+
GstTagList *
+gst_tag_list_new (const gchar *tag,
+                  ...);
+

Creates a new taglist and appends the values for the given tags. It expects +tag-value pairs like gst_tag_list_add(), and a NULL terminator after the +last pair. The type of the values is implicit and is documented in the API +reference, but can also be queried at runtime with gst_tag_get_type(). It +is an error to pass a value of a type not matching the tag type into this +function. The tag list will make copies of any arguments passed +(e.g. strings, buffers).

+

After creation you might also want to set a GstTagScope on the returned +taglist to signal if the contained tags are global or stream tags. By +default stream scope is assumes. See gst_tag_list_set_scope().

+

Free-function: gst_tag_list_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

tag

tag

 

...

NULL-terminated list of values to set

 
+
+
+

Returns

+

a new GstTagList. Free with gst_tag_list_unref() +when no longer needed.

+

[transfer full]

+
+
+
+
+

gst_tag_list_new_empty ()

+
GstTagList *
+gst_tag_list_new_empty (void);
+

Creates a new empty GstTagList.

+

Free-function: gst_tag_list_unref

+
+

Returns

+

An empty tag list.

+

[transfer full]

+
+
+
+
+

gst_tag_list_new_valist ()

+
GstTagList *
+gst_tag_list_new_valist (va_list var_args);
+

Just like gst_tag_list_new(), only that it takes a va_list argument. +Useful mostly for language bindings.

+

Free-function: gst_tag_list_unref

+
+

Parameters

+
+++++ + + + + + +

var_args

tag / value pairs to set

 
+
+
+

Returns

+

a new GstTagList. Free with gst_tag_list_unref() +when no longer needed.

+

[transfer full]

+
+
+
+
+

gst_tag_list_new_from_string ()

+
GstTagList *
+gst_tag_list_new_from_string (const gchar *str);
+

Deserializes a tag list.

+
+

Parameters

+
+++++ + + + + + +

str

a string created with gst_tag_list_to_string()

 
+
+
+

Returns

+

a new GstTagList, or NULL in case of an +error.

+

[nullable]

+
+
+
+
+

gst_tag_list_free()

+
#define gst_tag_list_free(taglist)    gst_tag_list_unref(taglist)
+
+

gst_tag_list_free is deprecated and should not be used in newly-written code.

+
+
+
+

gst_tag_list_get_scope ()

+
GstTagScope
+gst_tag_list_get_scope (const GstTagList *list);
+

Gets the scope of list +.

+
+

Parameters

+
+++++ + + + + + +

list

a GstTagList

 
+
+
+

Returns

+

The scope of list +

+
+
+
+
+

gst_tag_list_set_scope ()

+
void
+gst_tag_list_set_scope (GstTagList *list,
+                        GstTagScope scope);
+

Sets the scope of list + to scope +. By default the scope +of a taglist is stream scope.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

a GstTagList

 

scope

new scope for list +

 
+
+
+
+
+

gst_tag_list_to_string ()

+
gchar *
+gst_tag_list_to_string (const GstTagList *list);
+

Serializes a tag list to a string.

+
+

Parameters

+
+++++ + + + + + +

list

a GstTagList

 
+
+
+

Returns

+

a newly-allocated string, or NULL in case of +an error. The string must be freed with g_free() when no longer +needed.

+

[nullable]

+
+
+
+
+

gst_tag_list_is_empty ()

+
gboolean
+gst_tag_list_is_empty (const GstTagList *list);
+

Checks if the given taglist is empty.

+
+

Parameters

+
+++++ + + + + + +

list

A GstTagList.

 
+
+
+

Returns

+

TRUE if the taglist is empty, otherwise FALSE.

+
+
+
+
+

gst_tag_list_is_equal ()

+
gboolean
+gst_tag_list_is_equal (const GstTagList *list1,
+                       const GstTagList *list2);
+

Checks if the two given taglists are equal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list1

a GstTagList.

 

list2

a GstTagList.

 
+
+
+

Returns

+

TRUE if the taglists are equal, otherwise FALSE

+
+
+
+
+

gst_tag_list_copy ()

+
GstTagList *
+gst_tag_list_copy (const GstTagList *taglist);
+

Creates a new GstTagList as a copy of the old taglist +. The new taglist +will have a refcount of 1, owned by the caller, and will be writable as +a result.

+

Note that this function is the semantic equivalent of a gst_tag_list_ref() +followed by a gst_tag_list_make_writable(). If you only want to hold on to a +reference to the data, you should use gst_tag_list_ref().

+

When you are finished with the taglist, call gst_tag_list_unref() on it.

+
+

Parameters

+
+++++ + + + + + +

taglist

a GstTagList.

 
+
+
+

Returns

+

the new GstTagList

+
+
+
+
+

gst_tag_list_ref ()

+
GstTagList *
+gst_tag_list_ref (GstTagList *taglist);
+

Add a reference to a GstTagList mini object.

+

From this point on, until the caller calls gst_tag_list_unref() or +gst_tag_list_make_writable(), it is guaranteed that the taglist object will +not change. To use a GstTagList object, you must always have a refcount on +it -- either the one made implicitly by e.g. gst_tag_list_new(), or via +taking one explicitly with this function.

+
+

Parameters

+
+++++ + + + + + +

taglist

the GstTagList to reference

 
+
+
+

Returns

+

the same GstTagList mini object.

+
+
+
+
+

gst_tag_list_unref ()

+
void
+gst_tag_list_unref (GstTagList *taglist);
+

Unref a GstTagList, and and free all its memory when the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

taglist

a GstTagList.

 
+
+
+
+
+

gst_tag_list_is_writable()

+
#define gst_tag_list_is_writable(taglist)    gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (taglist))
+
+

Tests if you can safely modify taglist +. It is only safe to modify taglist +when there is only one owner of the taglist - ie, the refcount is 1.

+
+

Parameters

+
+++++ + + + + + +

taglist

a GstTagList

 
+
+
+
+
+

gst_tag_list_make_writable()

+
#define gst_tag_list_make_writable(taglist)   GST_TAG_LIST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (taglist)))
+
+

Returns a writable copy of taglist +.

+

If there is only one reference count on taglist +, the caller must be the +owner, and so this function will return the taglist object unchanged. If on +the other hand there is more than one reference on the object, a new taglist +object will be returned (which will be a copy of taglist +). The caller's +reference on taglist + will be removed, and instead the caller will own a +reference to the returned object.

+

In short, this function unrefs the taglist in the argument and refs the +taglist that it returns. Don't access the argument after calling this +function. See also: gst_tag_list_ref().

+
+

Parameters

+
+++++ + + + + + +

taglist

a GstTagList.

[transfer full]
+
+
+

Returns

+

a writable taglist which may or may not be the +same as taglist +.

+

[transfer full]

+
+
+
+
+

gst_tag_list_insert ()

+
void
+gst_tag_list_insert (GstTagList *into,
+                     const GstTagList *from,
+                     GstTagMergeMode mode);
+

Inserts the tags of the from + list into the first list using the given mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

into

list to merge into

 

from

list to merge from

 

mode

the mode to use

 
+
+
+
+
+

gst_tag_list_merge ()

+
GstTagList *
+gst_tag_list_merge (const GstTagList *list1,
+                    const GstTagList *list2,
+                    GstTagMergeMode mode);
+

Merges the two given lists into a new list. If one of the lists is NULL, a +copy of the other is returned. If both lists are NULL, NULL is returned.

+

Free-function: gst_tag_list_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list1

first list to merge.

[allow-none]

list2

second list to merge.

[allow-none]

mode

the mode to use

 
+
+
+

Returns

+

the new list.

+

[transfer full][nullable]

+
+
+
+
+

gst_tag_list_get_tag_size ()

+
guint
+gst_tag_list_get_tag_size (const GstTagList *list,
+                           const gchar *tag);
+

Checks how many value are stored in this tag list for the given tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

a taglist

 

tag

the tag to query

 
+
+
+

Returns

+

The number of tags stored

+
+
+
+
+

gst_tag_list_n_tags ()

+
gint
+gst_tag_list_n_tags (const GstTagList *list);
+

Get the number of tags in list +.

+
+

Parameters

+
+++++ + + + + + +

list

A GstTagList.

 
+
+
+

Returns

+

The number of tags in list +.

+
+
+
+
+

gst_tag_list_nth_tag_name ()

+
const gchar *
+gst_tag_list_nth_tag_name (const GstTagList *list,
+                           guint index);
+

Get the name of the tag in list + at index +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

A GstTagList.

 

index

the index

 
+
+
+

Returns

+

The name of the tag at index +.

+
+
+
+
+

gst_tag_list_add ()

+
void
+gst_tag_list_add (GstTagList *list,
+                  GstTagMergeMode mode,
+                  const gchar *tag,
+                  ...);
+

Sets the values for the given tags using the specified mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

list to set tags in

 

mode

the mode to use

 

tag

tag

 

...

NULL-terminated list of values to set

 
+
+
+
+
+

gst_tag_list_add_value ()

+
void
+gst_tag_list_add_value (GstTagList *list,
+                        GstTagMergeMode mode,
+                        const gchar *tag,
+                        const GValue *value);
+

Sets the GValue for a given tag using the specified mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

list to set tags in

 

mode

the mode to use

 

tag

tag

 

value

GValue for this tag

 
+
+
+
+
+

gst_tag_list_add_values ()

+
void
+gst_tag_list_add_values (GstTagList *list,
+                         GstTagMergeMode mode,
+                         const gchar *tag,
+                         ...);
+

Sets the GValues for the given tags using the specified mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

list to set tags in

 

mode

the mode to use

 

tag

tag

 

...

GValues to set

 
+
+
+
+
+

gst_tag_list_add_valist ()

+
void
+gst_tag_list_add_valist (GstTagList *list,
+                         GstTagMergeMode mode,
+                         const gchar *tag,
+                         va_list var_args);
+

Sets the values for the given tags using the specified mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

list to set tags in

 

mode

the mode to use

 

tag

tag

 

var_args

tag / value pairs to set

 
+
+
+
+
+

gst_tag_list_add_valist_values ()

+
void
+gst_tag_list_add_valist_values (GstTagList *list,
+                                GstTagMergeMode mode,
+                                const gchar *tag,
+                                va_list var_args);
+

Sets the GValues for the given tags using the specified mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

list to set tags in

 

mode

the mode to use

 

tag

tag

 

var_args

tag / GValue pairs to set

 
+
+
+
+
+

gst_tag_list_remove_tag ()

+
void
+gst_tag_list_remove_tag (GstTagList *list,
+                         const gchar *tag);
+

Removes the given tag from the taglist.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

list to remove tag from

 

tag

tag to remove

 
+
+
+
+
+

gst_tag_list_foreach ()

+
void
+gst_tag_list_foreach (const GstTagList *list,
+                      GstTagForeachFunc func,
+                      gpointer user_data);
+

Calls the given function for each tag inside the tag list. Note that if there +is no tag, the function won't be called at all.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

list to iterate over

 

func

function to be called for each tag.

[scope call]

user_data

user specified data.

[closure]
+
+
+
+
+

gst_tag_list_get_value_index ()

+
const GValue *
+gst_tag_list_get_value_index (const GstTagList *list,
+                              const gchar *tag,
+                              guint index);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList

 

tag

tag to read out

 

index

number of entry to read out

 
+
+
+

Returns

+

The GValue for the specified +entry or NULL if the tag wasn't available or the tag +doesn't have as many entries.

+

[transfer none][nullable]

+
+
+
+
+

gst_tag_list_copy_value ()

+
gboolean
+gst_tag_list_copy_value (GValue *dest,
+                         const GstTagList *list,
+                         const gchar *tag);
+

Copies the contents for the given tag into the value, +merging multiple values into one if multiple values are associated +with the tag. +You must g_value_unset() the value after use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

uninitialized GValue to copy into.

[out caller-allocates]

list

list to get the tag from

 

tag

tag to read out

 
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_boolean ()

+
gboolean
+gst_tag_list_get_boolean (const GstTagList *list,
+                          const gchar *tag,
+                          gboolean *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_boolean_index ()

+
gboolean
+gst_tag_list_get_boolean_index (const GstTagList *list,
+                                const gchar *tag,
+                                guint index,
+                                gboolean *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_int ()

+
gboolean
+gst_tag_list_get_int (const GstTagList *list,
+                      const gchar *tag,
+                      gint *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_int_index ()

+
gboolean
+gst_tag_list_get_int_index (const GstTagList *list,
+                            const gchar *tag,
+                            guint index,
+                            gint *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_uint ()

+
gboolean
+gst_tag_list_get_uint (const GstTagList *list,
+                       const gchar *tag,
+                       guint *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_uint_index ()

+
gboolean
+gst_tag_list_get_uint_index (const GstTagList *list,
+                             const gchar *tag,
+                             guint index,
+                             guint *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_int64 ()

+
gboolean
+gst_tag_list_get_int64 (const GstTagList *list,
+                        const gchar *tag,
+                        gint64 *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_int64_index ()

+
gboolean
+gst_tag_list_get_int64_index (const GstTagList *list,
+                              const gchar *tag,
+                              guint index,
+                              gint64 *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_uint64 ()

+
gboolean
+gst_tag_list_get_uint64 (const GstTagList *list,
+                         const gchar *tag,
+                         guint64 *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_uint64_index ()

+
gboolean
+gst_tag_list_get_uint64_index (const GstTagList *list,
+                               const gchar *tag,
+                               guint index,
+                               guint64 *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_float ()

+
gboolean
+gst_tag_list_get_float (const GstTagList *list,
+                        const gchar *tag,
+                        gfloat *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_float_index ()

+
gboolean
+gst_tag_list_get_float_index (const GstTagList *list,
+                              const gchar *tag,
+                              guint index,
+                              gfloat *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_double ()

+
gboolean
+gst_tag_list_get_double (const GstTagList *list,
+                         const gchar *tag,
+                         gdouble *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_double_index ()

+
gboolean
+gst_tag_list_get_double_index (const GstTagList *list,
+                               const gchar *tag,
+                               guint index,
+                               gdouble *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_string ()

+
gboolean
+gst_tag_list_get_string (const GstTagList *list,
+                         const gchar *tag,
+                         gchar **value);
+

Copies the contents for the given tag into the value, possibly merging +multiple values into one if multiple values are associated with the tag.

+

Use gst_tag_list_get_string_index (list, tag, 0, value) if you want +to retrieve the first string associated with this tag unmodified.

+

The resulting string in value + will be in UTF-8 encoding and should be +freed by the caller using g_free when no longer needed. The +returned string is also guaranteed to be non-NULL and non-empty.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_string_index ()

+
gboolean
+gst_tag_list_get_string_index (const GstTagList *list,
+                               const gchar *tag,
+                               guint index,
+                               gchar **value);
+

Gets the value that is at the given index for the given tag in the given +list.

+

The resulting string in value + will be in UTF-8 encoding and should be +freed by the caller using g_free when no longer needed. The +returned string is also guaranteed to be non-NULL and non-empty.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_peek_string_index ()

+
gboolean
+gst_tag_list_peek_string_index (const GstTagList *list,
+                                const gchar *tag,
+                                guint index,
+                                const gchar **value);
+

Peeks at the value that is at the given index for the given tag in the given +list.

+

The resulting string in value + will be in UTF-8 encoding and doesn't need +to be freed by the caller. The returned string is also guaranteed to +be non-NULL and non-empty.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out][transfer none]
+
+
+

Returns

+

TRUE, if a value was set, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_pointer ()

+
gboolean
+gst_tag_list_get_pointer (const GstTagList *list,
+                          const gchar *tag,
+                          gpointer *value);
+

Copies the contents for the given tag into the value, merging multiple values +into one if multiple values are associated with the tag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

location for the result.

[out][transfer none]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_pointer_index ()

+
gboolean
+gst_tag_list_get_pointer_index (const GstTagList *list,
+                                const gchar *tag,
+                                guint index,
+                                gpointer *value);
+

Gets the value that is at the given index for the given tag in the given +list.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out][transfer none]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list.

+
+
+
+
+

gst_tag_list_get_date ()

+
gboolean
+gst_tag_list_get_date (const GstTagList *list,
+                       const gchar *tag,
+                       GDate **value);
+

Copies the first date for the given tag in the taglist into the variable +pointed to by value +. Free the date with g_date_free() when it is no longer +needed.

+

Free-function: g_date_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

address of a GDate pointer +variable to store the result into.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a date was copied, FALSE if the tag didn't exist in the +given list or if it was NULL.

+
+
+
+
+

gst_tag_list_get_date_index ()

+
gboolean
+gst_tag_list_get_date_index (const GstTagList *list,
+                             const gchar *tag,
+                             guint index,
+                             GDate **value);
+

Gets the date that is at the given index for the given tag in the given +list and copies it into the variable pointed to by value +. Free the date +with g_date_free() when it is no longer needed.

+

Free-function: g_date_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list or if it was NULL.

+
+
+
+
+

gst_tag_list_get_date_time ()

+
gboolean
+gst_tag_list_get_date_time (const GstTagList *list,
+                            const gchar *tag,
+                            GstDateTime **value);
+

Copies the first datetime for the given tag in the taglist into the variable +pointed to by value +. Unref the date with gst_date_time_unref() when +it is no longer needed.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

value

address of a GstDateTime +pointer variable to store the result into.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a datetime was copied, FALSE if the tag didn't exist in +the given list or if it was NULL.

+
+
+
+
+

gst_tag_list_get_date_time_index ()

+
gboolean
+gst_tag_list_get_date_time_index (const GstTagList *list,
+                                  const gchar *tag,
+                                  guint index,
+                                  GstDateTime **value);
+

Gets the datetime that is at the given index for the given tag in the given +list and copies it into the variable pointed to by value +. Unref the datetime +with gst_date_time_unref() when it is no longer needed.

+

Free-function: gst_date_time_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

value

location for the result.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a value was copied, FALSE if the tag didn't exist in the +given list or if it was NULL.

+
+
+
+
+

gst_tag_list_get_sample ()

+
gboolean
+gst_tag_list_get_sample (const GstTagList *list,
+                         const gchar *tag,
+                         GstSample **sample);
+

Copies the first sample for the given tag in the taglist into the variable +pointed to by sample +. Free the sample with gst_sample_unref() when it is +no longer needed. You can retrieve the buffer from the sample using +gst_sample_get_buffer() and the associated caps (if any) with +gst_sample_get_caps().

+

Free-function: gst_sample_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

sample

address of a GstSample +pointer variable to store the result into.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a sample was returned, FALSE if the tag didn't exist in +the given list or if it was NULL.

+
+
+
+
+

gst_tag_list_get_sample_index ()

+
gboolean
+gst_tag_list_get_sample_index (const GstTagList *list,
+                               const gchar *tag,
+                               guint index,
+                               GstSample **sample);
+

Gets the sample that is at the given index for the given tag in the given +list and copies it into the variable pointed to by sample +. Free the sample +with gst_sample_unref() when it is no longer needed. You can retrieve the +buffer from the sample using gst_sample_get_buffer() and the associated +caps (if any) with gst_sample_get_caps().

+

Free-function: gst_sample_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

list

a GstTagList to get the tag from

 

tag

tag to read out

 

index

number of entry to read out

 

sample

address of a GstSample +pointer variable to store the result into.

[out callee-allocates][transfer full]
+
+
+

Returns

+

TRUE, if a sample was copied, FALSE if the tag didn't exist in the +given list or if it was NULL.

+
+
+
+
+

Types and Values

+
+

struct GstTagList

+
struct GstTagList {
+  GstMiniObject mini_object;
+};
+
+

Object describing tags / metadata.

+
+

Members

+
+++++ + + + + + +

GstMiniObject mini_object;

the parent type

 
+
+
+
+
+

enum GstTagMergeMode

+

The different tag merging modes are basically replace, overwrite and append, +but they can be seen from two directions. Given two taglists: (A) the tags +already in the element and (B) the ones that are supplied to the element ( +e.g. via gst_tag_setter_merge_tags() / gst_tag_setter_add_tags() or a +GST_EVENT_TAG), how are these tags merged? +In the table below this is shown for the cases that a tag exists in the list +(A) or does not exists (!A) and combinations thereof.

+
+

Table 1. merge mode

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
merge modeA + BA + !B!A + B!A + !B
REPLACE_ALLB-B-
REPLACEBAB-
APPENDA, BAB-
PREPENDB, AAB-
KEEPAAB-
KEEP_ALLAA--
+
+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_TAG_MERGE_UNDEFINED

+

undefined merge mode

+
 

GST_TAG_MERGE_REPLACE_ALL

+

replace all tags (clear list and append)

+
 

GST_TAG_MERGE_REPLACE

+

replace tags

+
 

GST_TAG_MERGE_APPEND

+

append tags

+
 

GST_TAG_MERGE_PREPEND

+

prepend tags

+
 

GST_TAG_MERGE_KEEP

+

keep existing tags

+
 

GST_TAG_MERGE_KEEP_ALL

+

keep all existing tags

+
 

GST_TAG_MERGE_COUNT

+

the number of merge modes

+
 
+
+
+
+
+

enum GstTagFlag

+

Extra tag flags used when registering tags.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_TAG_FLAG_UNDEFINED

+

undefined flag

+
 

GST_TAG_FLAG_META

+

tag is meta data

+
 

GST_TAG_FLAG_ENCODED

+

tag is encoded

+
 

GST_TAG_FLAG_DECODED

+

tag is decoded

+
 

GST_TAG_FLAG_COUNT

+

number of tag flags

+
 
+
+
+
+
+

enum GstTagScope

+

GstTagScope specifies if a taglist applies to the complete +medium or only to one single stream.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_TAG_SCOPE_STREAM

+

tags specific to this single stream

+
 

GST_TAG_SCOPE_GLOBAL

+

global tags for the complete medium

+
 
+
+
+
+
+

GST_TAG_TITLE

+
#define GST_TAG_TITLE                  "title"
+
+

commonly used title (string)

+

The title as it should be displayed, e.g. 'The Doll House'

+
+
+
+

GST_TAG_TITLE_SORTNAME

+
#define GST_TAG_TITLE_SORTNAME         "title-sortname"
+
+

commonly used title, as used for sorting (string)

+

The title as it should be sorted, e.g. 'Doll House, The'

+
+
+
+

GST_TAG_ARTIST

+
#define GST_TAG_ARTIST                 "artist"
+
+

person(s) responsible for the recording (string)

+

The artist name as it should be displayed, e.g. 'Jimi Hendrix' or +'The Guitar Heroes'

+
+
+
+

GST_TAG_ARTIST_SORTNAME

+
#define GST_TAG_ARTIST_SORTNAME        "artist-sortname"
+
+

person(s) responsible for the recording, as used for sorting (string)

+

The artist name as it should be sorted, e.g. 'Hendrix, Jimi' or +'Guitar Heroes, The'

+
+
+
+

GST_TAG_ALBUM

+
#define GST_TAG_ALBUM                  "album"
+
+

album containing this data (string)

+

The album name as it should be displayed, e.g. 'The Jazz Guitar'

+
+
+
+

GST_TAG_ALBUM_SORTNAME

+
#define GST_TAG_ALBUM_SORTNAME         "album-sortname"
+
+

album containing this data, as used for sorting (string)

+

The album name as it should be sorted, e.g. 'Jazz Guitar, The'

+
+
+
+

GST_TAG_ALBUM_ARTIST

+
#define GST_TAG_ALBUM_ARTIST           "album-artist"
+
+

The artist of the entire album, as it should be displayed.

+
+
+
+

GST_TAG_ALBUM_ARTIST_SORTNAME

+
#define GST_TAG_ALBUM_ARTIST_SORTNAME  "album-artist-sortname"
+
+

The artist of the entire album, as it should be sorted.

+
+
+
+

GST_TAG_DATE

+
#define GST_TAG_DATE                   "date"
+
+

date the data was created (GDate structure)

+
+
+
+

GST_TAG_DATE_TIME

+
#define GST_TAG_DATE_TIME              "datetime"
+
+

date and time the data was created (GstDateTime structure)

+
+
+
+

GST_TAG_GENRE

+
#define GST_TAG_GENRE                  "genre"
+
+

genre this data belongs to (string)

+
+
+
+

GST_TAG_COMMENT

+
#define GST_TAG_COMMENT                "comment"
+
+

free text commenting the data (string)

+
+
+
+

GST_TAG_EXTENDED_COMMENT

+
#define GST_TAG_EXTENDED_COMMENT       "extended-comment"
+
+

key/value text commenting the data (string)

+

Must be in the form of 'key=comment' or +'key[lc]=comment' where 'lc' is an ISO-639 +language code.

+

This tag is used for unknown Vorbis comment tags, +unknown APE tags and certain ID3v2 comment fields.

+
+
+
+

GST_TAG_TRACK_NUMBER

+
#define GST_TAG_TRACK_NUMBER           "track-number"
+
+

track number inside a collection (unsigned integer)

+
+
+
+

GST_TAG_TRACK_COUNT

+
#define GST_TAG_TRACK_COUNT            "track-count"
+
+

count of tracks inside collection this track belongs to (unsigned integer)

+
+
+
+

GST_TAG_ALBUM_VOLUME_NUMBER

+
#define GST_TAG_ALBUM_VOLUME_NUMBER    "album-disc-number"
+
+

disc number inside a collection (unsigned integer)

+
+
+
+

GST_TAG_ALBUM_VOLUME_COUNT

+
#define GST_TAG_ALBUM_VOLUME_COUNT    "album-disc-count"
+
+

count of discs inside collection this disc belongs to (unsigned integer)

+
+
+
+

GST_TAG_LOCATION

+
#define GST_TAG_LOCATION               "location"
+
+

Origin of media as a URI (location, where the original of the file or stream +is hosted) (string)

+
+
+
+

GST_TAG_HOMEPAGE

+
#define GST_TAG_HOMEPAGE               "homepage"
+
+

Homepage for this media (i.e. artist or movie homepage) (string)

+
+
+
+

GST_TAG_DESCRIPTION

+
#define GST_TAG_DESCRIPTION            "description"
+
+

short text describing the content of the data (string)

+
+
+
+

GST_TAG_VERSION

+
#define GST_TAG_VERSION                "version"
+
+

version of this data (string)

+
+
+
+

GST_TAG_ISRC

+
#define GST_TAG_ISRC                   "isrc"
+
+

International Standard Recording Code - see http://www.ifpi.org/isrc/ (string)

+
+
+
+

GST_TAG_ORGANIZATION

+
#define GST_TAG_ORGANIZATION           "organization"
+
+

organization (string)

+
+
+
+

GST_TAG_COPYRIGHT

+
#define GST_TAG_COPYRIGHT              "copyright"
+
+

copyright notice of the data (string)

+
+
+
+

GST_TAG_COPYRIGHT_URI

+
#define GST_TAG_COPYRIGHT_URI          "copyright-uri"
+
+

URI to location where copyright details can be found (string)

+
+
+
+

GST_TAG_ENCODED_BY

+
#define GST_TAG_ENCODED_BY             "encoded-by"
+
+

name of the person or organisation that encoded the file. May contain a +copyright message if the person or organisation also holds the copyright +(string)

+

Note: do not use this field to describe the encoding application. Use +GST_TAG_APPLICATION_NAME or GST_TAG_COMMENT for that.

+
+
+
+

GST_TAG_COMPOSER

+
#define GST_TAG_COMPOSER               "composer"
+
+

person(s) who composed the recording (string)

+
+
+
+

GST_TAG_CONDUCTOR

+
#define GST_TAG_CONDUCTOR               "conductor"
+
+

conductor/performer refinement (string)

+

Since: 1.8

+
+
+
+

GST_TAG_CONTACT

+
#define GST_TAG_CONTACT                "contact"
+
+

contact information (string)

+
+
+
+

GST_TAG_LICENSE

+
#define GST_TAG_LICENSE                "license"
+
+

license of data (string)

+
+
+
+

GST_TAG_LICENSE_URI

+
#define GST_TAG_LICENSE_URI            "license-uri"
+
+

URI to location where license details can be found (string)

+
+
+
+

GST_TAG_PERFORMER

+
#define GST_TAG_PERFORMER              "performer"
+
+

person(s) performing (string)

+
+
+
+

GST_TAG_DURATION

+
#define GST_TAG_DURATION               "duration"
+
+

length in GStreamer time units (nanoseconds) (unsigned 64-bit integer)

+
+
+
+

GST_TAG_CODEC

+
#define GST_TAG_CODEC                  "codec"
+
+

codec the data is stored in (string)

+
+
+
+

GST_TAG_VIDEO_CODEC

+
#define GST_TAG_VIDEO_CODEC            "video-codec"
+
+

codec the video data is stored in (string)

+
+
+
+

GST_TAG_AUDIO_CODEC

+
#define GST_TAG_AUDIO_CODEC            "audio-codec"
+
+

codec the audio data is stored in (string)

+
+
+
+

GST_TAG_SUBTITLE_CODEC

+
#define GST_TAG_SUBTITLE_CODEC         "subtitle-codec"
+
+

codec/format the subtitle data is stored in (string)

+
+
+
+

GST_TAG_CONTAINER_FORMAT

+
#define GST_TAG_CONTAINER_FORMAT       "container-format"
+
+

container format the data is stored in (string)

+
+
+
+

GST_TAG_BITRATE

+
#define GST_TAG_BITRATE                "bitrate"
+
+

exact or average bitrate in bits/s (unsigned integer)

+
+
+
+

GST_TAG_NOMINAL_BITRATE

+
#define GST_TAG_NOMINAL_BITRATE        "nominal-bitrate"
+
+

nominal bitrate in bits/s (unsigned integer). The actual bitrate might be +different from this target bitrate.

+
+
+
+

GST_TAG_MINIMUM_BITRATE

+
#define GST_TAG_MINIMUM_BITRATE        "minimum-bitrate"
+
+

minimum bitrate in bits/s (unsigned integer)

+
+
+
+

GST_TAG_MAXIMUM_BITRATE

+
#define GST_TAG_MAXIMUM_BITRATE        "maximum-bitrate"
+
+

maximum bitrate in bits/s (unsigned integer)

+
+
+
+

GST_TAG_SERIAL

+
#define GST_TAG_SERIAL                 "serial"
+
+

serial number of track (unsigned integer)

+
+
+
+

GST_TAG_ENCODER

+
#define GST_TAG_ENCODER                "encoder"
+
+

encoder used to encode this stream (string)

+
+
+
+

GST_TAG_ENCODER_VERSION

+
#define GST_TAG_ENCODER_VERSION        "encoder-version"
+
+

version of the encoder used to encode this stream (unsigned integer)

+
+
+
+

GST_TAG_TRACK_GAIN

+
#define GST_TAG_TRACK_GAIN             "replaygain-track-gain"
+
+

track gain in db (double)

+
+
+
+

GST_TAG_TRACK_PEAK

+
#define GST_TAG_TRACK_PEAK             "replaygain-track-peak"
+
+

peak of the track (double)

+
+
+
+

GST_TAG_ALBUM_GAIN

+
#define GST_TAG_ALBUM_GAIN             "replaygain-album-gain"
+
+

album gain in db (double)

+
+
+
+

GST_TAG_ALBUM_PEAK

+
#define GST_TAG_ALBUM_PEAK             "replaygain-album-peak"
+
+

peak of the album (double)

+
+
+
+

GST_TAG_REFERENCE_LEVEL

+
#define GST_TAG_REFERENCE_LEVEL        "replaygain-reference-level"
+
+

reference level of track and album gain values (double)

+
+
+
+

GST_TAG_LANGUAGE_CODE

+
#define GST_TAG_LANGUAGE_CODE          "language-code"
+
+

ISO-639-2 or ISO-639-1 code for the language the content is in (string)

+

There is utility API in libgsttag in gst-plugins-base to obtain a translated +language name from the language code: gst_tag_get_language_name()

+
+
+
+

GST_TAG_LANGUAGE_NAME

+
#define GST_TAG_LANGUAGE_NAME          "language-name"
+
+

Name of the language the content is in (string)

+

Free-form name of the language the content is in, if a language code +is not available. This tag should not be set in addition to a language +code. It is undefined what language or locale the language name is in.

+
+
+
+

GST_TAG_IMAGE

+
#define GST_TAG_IMAGE                  "image"
+
+

image (sample) (sample taglist should specify the content type and preferably +also set "image-type" field as GstTagImageType)

+
+
+
+

GST_TAG_PREVIEW_IMAGE

+
#define GST_TAG_PREVIEW_IMAGE          "preview-image"
+
+

image that is meant for preview purposes, e.g. small icon-sized version +(sample) (sample taglist should specify the content type)

+
+
+
+

GST_TAG_ATTACHMENT

+
#define GST_TAG_ATTACHMENT             "attachment"
+
+

generic file attachment (sample) (sample taglist should specify the content +type and if possible set "filename" to the file name of the +attachment)

+
+
+
+

GST_TAG_BEATS_PER_MINUTE

+
#define GST_TAG_BEATS_PER_MINUTE       "beats-per-minute"
+
+

number of beats per minute in audio (double)

+
+
+
+

GST_TAG_KEYWORDS

+
#define GST_TAG_KEYWORDS               "keywords"
+
+

comma separated keywords describing the content (string).

+
+
+
+

GST_TAG_GEO_LOCATION_NAME

+
#define GST_TAG_GEO_LOCATION_NAME               "geo-location-name"
+
+

human readable descriptive location of where the media has been recorded or +produced. (string).

+
+
+
+

GST_TAG_GEO_LOCATION_LATITUDE

+
#define GST_TAG_GEO_LOCATION_LATITUDE               "geo-location-latitude"
+
+

geo latitude location of where the media has been recorded or produced in +degrees according to WGS84 (zero at the equator, negative values for southern +latitudes) (double).

+
+
+
+

GST_TAG_GEO_LOCATION_LONGITUDE

+
#define GST_TAG_GEO_LOCATION_LONGITUDE               "geo-location-longitude"
+
+

geo longitude location of where the media has been recorded or produced in +degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, +negative values for western longitudes). (double).

+
+
+
+

GST_TAG_GEO_LOCATION_ELEVATION

+
#define GST_TAG_GEO_LOCATION_ELEVATION               "geo-location-elevation"
+
+

geo elevation of where the media has been recorded or produced in meters +according to WGS84 (zero is average sea level) (double).

+
+
+
+

GST_TAG_GEO_LOCATION_CITY

+
#define GST_TAG_GEO_LOCATION_CITY                    "geo-location-city"
+
+

The city (english name) where the media has been produced (string).

+
+
+
+

GST_TAG_GEO_LOCATION_COUNTRY

+
#define GST_TAG_GEO_LOCATION_COUNTRY                 "geo-location-country"
+
+

The country (english name) where the media has been produced (string).

+
+
+
+

GST_TAG_GEO_LOCATION_SUBLOCATION

+
#define GST_TAG_GEO_LOCATION_SUBLOCATION             "geo-location-sublocation"
+
+

A location 'smaller' than GST_TAG_GEO_LOCATION_CITY that specifies better +where the media has been produced. (e.g. the neighborhood) (string).

+

This tag has been added as this is how it is handled/named in XMP's +Iptc4xmpcore schema.

+
+
+
+

GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR

+
#define GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR   "geo-location-horizontal-error"
+
+

Represents the expected error on the horizontal positioning in +meters (double).

+
+
+
+

GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION

+
#define GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION "geo-location-movement-direction"
+
+

Indicates the movement direction of the device performing the capture +of a media. It is represented as degrees in floating point representation, +0 means the geographic north, and increases clockwise (double from 0 to 360)

+

See also GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION

+
+
+
+

GST_TAG_GEO_LOCATION_MOVEMENT_SPEED

+
#define GST_TAG_GEO_LOCATION_MOVEMENT_SPEED       "geo-location-movement-speed"
+
+

Speed of the capturing device when performing the capture. +Represented in m/s. (double)

+

See also GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION

+
+
+
+

GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION

+
#define GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION  "geo-location-capture-direction"
+
+

Indicates the direction the device is pointing to when capturing +a media. It is represented as degrees in floating point representation, +0 means the geographic north, and increases clockwise (double from 0 to 360)

+

See also GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION

+
+
+
+

GST_TAG_SHOW_NAME

+
#define GST_TAG_SHOW_NAME                         "show-name"
+
+

Name of the show, used for displaying (string)

+
+
+
+

GST_TAG_SHOW_SORTNAME

+
#define GST_TAG_SHOW_SORTNAME                     "show-sortname"
+
+

Name of the show, used for sorting (string)

+
+
+
+

GST_TAG_SHOW_EPISODE_NUMBER

+
#define GST_TAG_SHOW_EPISODE_NUMBER               "show-episode-number"
+
+

Number of the episode within a season/show (unsigned integer)

+
+
+
+

GST_TAG_SHOW_SEASON_NUMBER

+
#define GST_TAG_SHOW_SEASON_NUMBER                "show-season-number"
+
+

Number of the season of a show/series (unsigned integer)

+
+
+
+

GST_TAG_LYRICS

+
#define GST_TAG_LYRICS                            "lyrics"
+
+

The lyrics of the media (string)

+
+
+
+

GST_TAG_COMPOSER_SORTNAME

+
#define GST_TAG_COMPOSER_SORTNAME                 "composer-sortname"
+
+

The composer's name, used for sorting (string)

+
+
+
+

GST_TAG_GROUPING

+
#define GST_TAG_GROUPING                          "grouping"
+
+

Groups together media that are related and spans multiple tracks. An +example are multiple pieces of a concerto. (string)

+
+
+
+

GST_TAG_USER_RATING

+
#define GST_TAG_USER_RATING                       "user-rating"
+
+

Rating attributed by a person (likely the application user). +The higher the value, the more the user likes this media +(unsigned int from 0 to 100)

+
+
+
+

GST_TAG_DEVICE_MANUFACTURER

+
#define GST_TAG_DEVICE_MANUFACTURER               "device-manufacturer"
+
+

Manufacturer of the device used to create the media (string)

+
+
+
+

GST_TAG_DEVICE_MODEL

+
#define GST_TAG_DEVICE_MODEL                      "device-model"
+
+

Model of the device used to create the media (string)

+
+
+
+

GST_TAG_APPLICATION_NAME

+
#define GST_TAG_APPLICATION_NAME                  "application-name"
+
+

Name of the application used to create the media (string)

+
+
+
+

GST_TAG_APPLICATION_DATA

+
#define GST_TAG_APPLICATION_DATA          "application-data"
+
+

Arbitrary application data (sample)

+

Some formats allow applications to add their own arbitrary data +into files. This data is application dependent.

+
+
+
+

GST_TAG_IMAGE_ORIENTATION

+
#define GST_TAG_IMAGE_ORIENTATION            "image-orientation"
+
+

Represents the 'Orientation' tag from EXIF. Defines how the image +should be rotated and mirrored for display. (string)

+

This tag has a predefined set of allowed values: + "rotate-0" + "rotate-90" + "rotate-180" + "rotate-270" + "flip-rotate-0" + "flip-rotate-90" + "flip-rotate-180" + "flip-rotate-270"

+

The naming is adopted according to a possible transformation to perform +on the image to fix its orientation, obviously equivalent operations will +yield the same result.

+

Rotations indicated by the values are in clockwise direction and +'flip' means an horizontal mirroring.

+
+
+
+

GST_TAG_PUBLISHER

+
#define GST_TAG_PUBLISHER                         "publisher"
+
+

Name of the label or publisher (string)

+

Since: 1.2

+
+
+
+

GST_TAG_INTERPRETED_BY

+
#define GST_TAG_INTERPRETED_BY                    "interpreted-by"
+
+

Information about the people behind a remix and similar +interpretations of another existing piece (string)

+

Since: 1.2

+
+
+
+

GST_TAG_MIDI_BASE_NOTE

+
#define GST_TAG_MIDI_BASE_NOTE                    "midi-base-note"
+
+Midi note number

of the audio track. This is useful for sample instruments and in particular +for multi-samples.

+

Since: 1.4

+
+
+
+

GST_TAG_PRIVATE_DATA

+
#define GST_TAG_PRIVATE_DATA                         "private-data"
+
+

Any private data that may be contained in tags (sample).

+

It is represented by GstSample in which GstBuffer contains the +binary data and the sample's info GstStructure may contain any +extra information that identifies the origin or meaning of the data.

+

Private frames in ID3v2 tags ('PRIV' frames) will be represented +using this tag, in which case the GstStructure will be named +"ID3PrivateFrame" and contain a field named "owner" of type string +which contains the owner-identification string from the tag.

+

Since: 1.8

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTagSetter.html b/docs/gst/html/GstTagSetter.html new file mode 100644 index 0000000..efb8861 --- /dev/null +++ b/docs/gst/html/GstTagSetter.html @@ -0,0 +1,629 @@ + + + + +GstTagsetter: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTagsetter

+

GstTagsetter — Element interface that allows setting and retrieval + of media metadata

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +gst_tag_setter_reset_tags () +
+void + +gst_tag_setter_merge_tags () +
+void + +gst_tag_setter_add_tags () +
+void + +gst_tag_setter_add_tag_value () +
+void + +gst_tag_setter_add_tag_values () +
+void + +gst_tag_setter_add_tag_valist () +
+void + +gst_tag_setter_add_tag_valist_values () +
const GstTagList * + +gst_tag_setter_get_tag_list () +
+void + +gst_tag_setter_set_tag_merge_mode () +
+GstTagMergeMode + +gst_tag_setter_get_tag_merge_mode () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstTagSetter
structGstTagSetterInterface
+
+
+

Object Hierarchy

+
    GInterface
+    ╰── GstTagSetter
+
+
+
+

Prerequisites

+

+GstTagSetter requires + GstElement.

+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Element interface that allows setting of media metadata.

+

Elements that support changing a stream's metadata will implement this +interface. Examples of such elements are 'vorbisenc', 'theoraenc' and +'id3v2mux'.

+

If you just want to retrieve metadata in your application then all you +need to do is watch for tag messages on your pipeline's bus. This +interface is only for setting metadata, not for extracting it. To set tags +from the application, find tagsetter elements and set tags using e.g. +gst_tag_setter_merge_tags() or gst_tag_setter_add_tags(). Also consider +setting the GstTagMergeMode that is used for tag events that arrive at the +tagsetter element (default mode is to keep existing tags). +The application should do that before the element goes to GST_STATE_PAUSED.

+

Elements implementing the GstTagSetter interface often have to merge +any tags received from upstream and the tags set by the application via +the interface. This can be done like this:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
GstTagMergeMode merge_mode;
+const GstTagList *application_tags;
+const GstTagList *event_tags;
+GstTagSetter *tagsetter;
+GstTagList *result;
+
+tagsetter = GST_TAG_SETTER (element);
+
+merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter);
+application_tags = gst_tag_setter_get_tag_list (tagsetter);
+event_tags = (const GstTagList *) element->event_tags;
+
+GST_LOG_OBJECT (tagsetter, "merging tags, merge mode = %d", merge_mode);
+GST_LOG_OBJECT (tagsetter, "event tags: %" GST_PTR_FORMAT, event_tags);
+GST_LOG_OBJECT (tagsetter, "set   tags: %" GST_PTR_FORMAT, application_tags);
+
+result = gst_tag_list_merge (application_tags, event_tags, merge_mode);
+
+GST_LOG_OBJECT (tagsetter, "final tags: %" GST_PTR_FORMAT, result);
+
+ +

+
+
+

Functions

+
+

gst_tag_setter_reset_tags ()

+
void
+gst_tag_setter_reset_tags (GstTagSetter *setter);
+

Reset the internal taglist. Elements should call this from within the +state-change handler.

+
+

Parameters

+
+++++ + + + + + +

setter

a GstTagSetter

 
+
+
+
+
+

gst_tag_setter_merge_tags ()

+
void
+gst_tag_setter_merge_tags (GstTagSetter *setter,
+                           const GstTagList *list,
+                           GstTagMergeMode mode);
+

Merges the given list into the setter's list using the given mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

list

a tag list to merge from

 

mode

the mode to merge with

 
+
+
+
+
+

gst_tag_setter_add_tags ()

+
void
+gst_tag_setter_add_tags (GstTagSetter *setter,
+                         GstTagMergeMode mode,
+                         const gchar *tag,
+                         ...);
+

Adds the given tag / value pairs on the setter using the given merge mode. +The list must be terminated with NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

the mode to use

 

tag

tag to set

 

...

more tag / value pairs to set

 
+
+
+
+
+

gst_tag_setter_add_tag_value ()

+
void
+gst_tag_setter_add_tag_value (GstTagSetter *setter,
+                              GstTagMergeMode mode,
+                              const gchar *tag,
+                              const GValue *value);
+

Adds the given tag / GValue pair on the setter using the given merge mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

the mode to use

 

tag

tag to set

 

value

GValue to set for the tag

 
+
+
+
+
+

gst_tag_setter_add_tag_values ()

+
void
+gst_tag_setter_add_tag_values (GstTagSetter *setter,
+                               GstTagMergeMode mode,
+                               const gchar *tag,
+                               ...);
+

Adds the given tag / GValue pairs on the setter using the given merge mode. +The list must be terminated with NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

the mode to use

 

tag

tag to set

 

...

more tag / GValue pairs to set

 
+
+
+
+
+

gst_tag_setter_add_tag_valist ()

+
void
+gst_tag_setter_add_tag_valist (GstTagSetter *setter,
+                               GstTagMergeMode mode,
+                               const gchar *tag,
+                               va_list var_args);
+

Adds the given tag / value pairs on the setter using the given merge mode. +The list must be terminated with NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

the mode to use

 

tag

tag to set

 

var_args

tag / value pairs to set

 
+
+
+
+
+

gst_tag_setter_add_tag_valist_values ()

+
void
+gst_tag_setter_add_tag_valist_values (GstTagSetter *setter,
+                                      GstTagMergeMode mode,
+                                      const gchar *tag,
+                                      va_list var_args);
+

Adds the given tag / GValue pairs on the setter using the given merge mode. +The list must be terminated with NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

the mode to use

 

tag

tag to set

 

var_args

tag / GValue pairs to set

 
+
+
+
+
+

gst_tag_setter_get_tag_list ()

+
const GstTagList *
+gst_tag_setter_get_tag_list (GstTagSetter *setter);
+

Returns the current list of tags the setter uses. The list should not be +modified or freed.

+

This function is not thread-safe.

+
+

Parameters

+
+++++ + + + + + +

setter

a GstTagSetter

 
+
+
+

Returns

+

a current snapshot of the +taglist used in the setter or NULL if none is used.

+

[transfer none][nullable]

+
+
+
+
+

gst_tag_setter_set_tag_merge_mode ()

+
void
+gst_tag_setter_set_tag_merge_mode (GstTagSetter *setter,
+                                   GstTagMergeMode mode);
+

Sets the given merge mode that is used for adding tags from events to tags +specified by this interface. The default is GST_TAG_MERGE_KEEP, which keeps +the tags set with this interface and discards tags from events.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

setter

a GstTagSetter

 

mode

The mode with which tags are added

 
+
+
+
+
+

gst_tag_setter_get_tag_merge_mode ()

+
GstTagMergeMode
+gst_tag_setter_get_tag_merge_mode (GstTagSetter *setter);
+

Queries the mode by which tags inside the setter are overwritten by tags +from events

+
+

Parameters

+
+++++ + + + + + +

setter

a GstTagSetter

 
+
+
+

Returns

+

the merge mode used inside the element.

+
+
+
+
+

Types and Values

+
+

GstTagSetter

+
typedef struct _GstTagSetter GstTagSetter;
+

Opaque GstTagSetter data structure.

+
+
+
+

struct GstTagSetterInterface

+
struct GstTagSetterInterface {
+  GTypeInterface g_iface;
+
+  /* signals */
+
+  /* virtual table */
+};
+
+

GstTagSetterInterface interface.

+
+

Members

+
+++++ + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTask.html b/docs/gst/html/GstTask.html new file mode 100644 index 0000000..670f499 --- /dev/null +++ b/docs/gst/html/GstTask.html @@ -0,0 +1,1036 @@ + + + + +GstTask: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTask

+

GstTask — Abstraction of GStreamer streaming threads.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstTaskFunction) () +
#define +GST_TASK_BROADCAST() +
#define +GST_TASK_GET_COND() +
#define +GST_TASK_GET_LOCK() +
#define +GST_TASK_SIGNAL() +
#define +GST_TASK_STATE() +
#define +GST_TASK_WAIT() +
+GstTask * + +gst_task_new () +
+void + +gst_task_set_lock () +
+void + +gst_task_set_pool () +
+GstTaskPool * + +gst_task_get_pool () +
+void + +(*GstTaskThreadFunc) () +
+void + +gst_task_set_enter_callback () +
+void + +gst_task_set_leave_callback () +
+GstTaskState + +gst_task_get_state () +
+gboolean + +gst_task_set_state () +
+gboolean + +gst_task_pause () +
+gboolean + +gst_task_start () +
+gboolean + +gst_task_stop () +
+gboolean + +gst_task_join () +
+void + +gst_task_cleanup_all () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTask
enumGstTaskState
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTask
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

GstTask is used by GstElement and GstPad to provide the data passing +threads in a GstPipeline.

+

A GstPad will typically start a GstTask to push or pull data to/from the +peer pads. Most source elements start a GstTask to push data. In some cases +a demuxer element can start a GstTask to pull data from a peer element. This +is typically done when the demuxer can perform random access on the upstream +peer element for improved performance.

+

Although convenience functions exist on GstPad to start/pause/stop tasks, it +might sometimes be needed to create a GstTask manually if it is not related to +a GstPad.

+

Before the GstTask can be run, it needs a GRecMutex that can be set with +gst_task_set_lock().

+

The task can be started, paused and stopped with gst_task_start(), gst_task_pause() +and gst_task_stop() respectively or with the gst_task_set_state() function.

+

A GstTask will repeatedly call the GstTaskFunction with the user data +that was provided when creating the task with gst_task_new(). While calling +the function it will acquire the provided lock. The provided lock is released +when the task pauses or stops.

+

Stopping a task with gst_task_stop() will not immediately make sure the task is +not running anymore. Use gst_task_join() to make sure the task is completely +stopped and the thread is stopped.

+

After creating a GstTask, use gst_object_unref() to free its resources. This can +only be done when the task is not running anymore.

+

Task functions can send a GstMessage to send out-of-band data to the +application. The application can receive messages from the GstBus in its +mainloop.

+

For debugging purposes, the task will configure its object name as the thread +name on Linux. Please note that the object name should be configured before the +task is started; changing the object name after the task has been started, has +no effect on the thread name.

+
+
+

Functions

+
+

GstTaskFunction ()

+
void
+(*GstTaskFunction) (gpointer user_data);
+

A function that will repeatedly be called in the thread created by +a GstTask.

+
+

Parameters

+
+++++ + + + + + +

user_data

user data passed to the function

 
+
+
+
+
+

GST_TASK_BROADCAST()

+
#define GST_TASK_BROADCAST(task)        g_cond_broadcast(GST_TASK_GET_COND (task))
+
+

Send a broadcast signal to all waiting task conds

+
+

Parameters

+
+++++ + + + + + +

task

Task to broadcast

 
+
+
+
+
+

GST_TASK_GET_COND()

+
#define GST_TASK_GET_COND(task)         (&GST_TASK_CAST(task)->cond)
+
+

Get access to the cond of the task.

+
+

Parameters

+
+++++ + + + + + +

task

Task to get the cond of

 
+
+
+
+
+

GST_TASK_GET_LOCK()

+
#define GST_TASK_GET_LOCK(task)         (GST_TASK_CAST(task)->lock)
+
+

Get access to the task lock.

+
+

Parameters

+
+++++ + + + + + +

task

Task to get the lock of

 
+
+
+
+
+

GST_TASK_SIGNAL()

+
#define GST_TASK_SIGNAL(task)           g_cond_signal(GST_TASK_GET_COND (task))
+
+

Signal the task cond

+
+

Parameters

+
+++++ + + + + + +

task

Task to signal

 
+
+
+
+
+

GST_TASK_STATE()

+
#define GST_TASK_STATE(task)            (GST_TASK_CAST(task)->state)
+
+

Get access to the state of the task.

+
+

Parameters

+
+++++ + + + + + +

task

Task to get the state of

 
+
+
+
+
+

GST_TASK_WAIT()

+
#define GST_TASK_WAIT(task)             g_cond_wait(GST_TASK_GET_COND (task), GST_OBJECT_GET_LOCK (task))
+
+

Wait for the task cond to be signalled

+
+

Parameters

+
+++++ + + + + + +

task

Task to wait for

 
+
+
+
+
+

gst_task_new ()

+
GstTask *
+gst_task_new (GstTaskFunction func,
+              gpointer user_data,
+              GDestroyNotify notify);
+

Create a new Task that will repeatedly call the provided func + +with user_data + as a parameter. Typically the task will run in +a new thread.

+

The function cannot be changed after the task has been created. You +must create a new GstTask to change the function.

+

This function will not yet create and start a thread. Use gst_task_start() or +gst_task_pause() to create and start the GThread.

+

Before the task can be used, a GRecMutex must be configured using the +gst_task_set_lock() function. This lock will always be acquired while +func + is called.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

func

The GstTaskFunction to use

 

user_data

User data to pass to func +

 

notify

the function to call when user_data +is no longer needed.

 
+
+
+

Returns

+

A new GstTask.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_task_set_lock ()

+
void
+gst_task_set_lock (GstTask *task,
+                   GRecMutex *mutex);
+

Set the mutex used by the task. The mutex will be acquired before +calling the GstTaskFunction.

+

This function has to be called before calling gst_task_pause() or +gst_task_start().

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

task

The GstTask to use

 

mutex

The GRecMutex to use

 
+
+
+
+
+

gst_task_set_pool ()

+
void
+gst_task_set_pool (GstTask *task,
+                   GstTaskPool *pool);
+

Set pool + as the new GstTaskPool for task +. Any new streaming threads that +will be created by task + will now use pool +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

task

a GstTask

 

pool

a GstTaskPool.

[transfer none]
+
+
+
+
+

gst_task_get_pool ()

+
GstTaskPool *
+gst_task_get_pool (GstTask *task);
+

Get the GstTaskPool that this task will use for its streaming +threads.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

task

a GstTask

 
+
+
+

Returns

+

the GstTaskPool used by task +. gst_object_unref() +after usage.

+

[transfer full]

+
+
+
+
+

GstTaskThreadFunc ()

+
void
+(*GstTaskThreadFunc) (GstTask *task,
+                      GThread *thread,
+                      gpointer user_data);
+

Custom GstTask thread callback functions that can be installed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

task

The GstTask

 

thread

The GThread

 

user_data

user data

 
+
+
+
+
+

gst_task_set_enter_callback ()

+
void
+gst_task_set_enter_callback (GstTask *task,
+                             GstTaskThreadFunc enter_func,
+                             gpointer user_data,
+                             GDestroyNotify notify);
+

Call enter_func + when the task function of task + is entered. user_data + will +be passed to enter_func + and notify + will be called when user_data + is no +longer referenced.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

task

The GstTask to use

 

enter_func

a GstTaskThreadFunc.

[in]

user_data

user data passed to enter_func +

 

notify

called when user_data +is no longer referenced

 
+
+
+
+
+

gst_task_set_leave_callback ()

+
void
+gst_task_set_leave_callback (GstTask *task,
+                             GstTaskThreadFunc leave_func,
+                             gpointer user_data,
+                             GDestroyNotify notify);
+

Call leave_func + when the task function of task + is left. user_data + will +be passed to leave_func + and notify + will be called when user_data + is no +longer referenced.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

task

The GstTask to use

 

leave_func

a GstTaskThreadFunc.

[in]

user_data

user data passed to leave_func +

 

notify

called when user_data +is no longer referenced

 
+
+
+
+
+

gst_task_get_state ()

+
GstTaskState
+gst_task_get_state (GstTask *task);
+

Get the current state of the task.

+
+

Parameters

+
+++++ + + + + + +

task

The GstTask to query

 
+
+
+

Returns

+

The GstTaskState of the task

+

MT safe.

+
+
+
+
+

gst_task_set_state ()

+
gboolean
+gst_task_set_state (GstTask *task,
+                    GstTaskState state);
+

Sets the state of task + to state +.

+

The task + must have a lock associated with it using +gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or +this function will return FALSE.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

task

a GstTask

 

state

the new task state

 
+
+
+

Returns

+

TRUE if the state could be changed.

+
+
+
+
+

gst_task_pause ()

+
gboolean
+gst_task_pause (GstTask *task);
+

Pauses task +. This method can also be called on a task in the +stopped state, in which case a thread will be started and will remain +in the paused state. This function does not wait for the task to complete +the paused state.

+
+

Parameters

+
+++++ + + + + + +

task

The GstTask to pause

 
+
+
+

Returns

+

TRUE if the task could be paused.

+

MT safe.

+
+
+
+
+

gst_task_start ()

+
gboolean
+gst_task_start (GstTask *task);
+

Starts task +. The task + must have a lock associated with it using +gst_task_set_lock() or this function will return FALSE.

+
+

Parameters

+
+++++ + + + + + +

task

The GstTask to start

 
+
+
+

Returns

+

TRUE if the task could be started.

+

MT safe.

+
+
+
+
+

gst_task_stop ()

+
gboolean
+gst_task_stop (GstTask *task);
+

Stops task +. This method merely schedules the task to stop and +will not wait for the task to have completely stopped. Use +gst_task_join() to stop and wait for completion.

+
+

Parameters

+
+++++ + + + + + +

task

The GstTask to stop

 
+
+
+

Returns

+

TRUE if the task could be stopped.

+

MT safe.

+
+
+
+
+

gst_task_join ()

+
gboolean
+gst_task_join (GstTask *task);
+

Joins task +. After this call, it is safe to unref the task +and clean up the lock set with gst_task_set_lock().

+

The task will automatically be stopped with this call.

+

This function cannot be called from within a task function as this +would cause a deadlock. The function will detect this and print a +g_warning.

+
+

Parameters

+
+++++ + + + + + +

task

The GstTask to join

 
+
+
+

Returns

+

TRUE if the task could be joined.

+

MT safe.

+
+
+
+
+

gst_task_cleanup_all ()

+
void
+gst_task_cleanup_all (void);
+

Wait for all tasks to be stopped. This is mainly used internally +to ensure proper cleanup of internal data structures in test suites.

+

MT safe.

+
+
+
+

Types and Values

+
+

struct GstTask

+
struct GstTask {
+  GstTaskState     state;
+  GCond            cond;
+
+  GRecMutex       *lock;
+
+  GstTaskFunction  func;
+  gpointer         user_data;
+  GDestroyNotify   notify;
+
+  gboolean         running;
+};
+
+

The GstTask object.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstTaskState state;

the state of the task

 

GCond cond;

used to pause/resume the task

 

GRecMutex *lock;

The lock taken when iterating the task function

 

GstTaskFunction func;

the function executed by this task

 

gpointer user_data;

user_data passed to the task function

 

GDestroyNotify notify;

GDestroyNotify for user_data +

 

gboolean running;

a flag indicating that the task is running

 
+
+
+
+
+

enum GstTaskState

+

The different states a task can be in

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_TASK_STARTED

+

the task is started and running

+
 

GST_TASK_STOPPED

+

the task is stopped

+
 

GST_TASK_PAUSED

+

the task is paused

+
 
+
+
+
+
+

See Also

+

GstElement, GstPad

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTaskPool.html b/docs/gst/html/GstTaskPool.html new file mode 100644 index 0000000..b3be47a --- /dev/null +++ b/docs/gst/html/GstTaskPool.html @@ -0,0 +1,372 @@ + + + + +GstTaskPool: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTaskPool

+

GstTaskPool — Pool of GStreamer streaming threads

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstTaskPoolFunction) () +
+GstTaskPool * + +gst_task_pool_new () +
+void + +gst_task_pool_prepare () +
+gpointer + +gst_task_pool_push () +
+void + +gst_task_pool_join () +
+void + +gst_task_pool_cleanup () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTaskPool
structGstTaskPoolClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTaskPool
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

This object provides an abstraction for creating threads. The default +implementation uses a regular GThreadPool to start tasks.

+

Subclasses can be made to create custom threads.

+
+
+

Functions

+
+

GstTaskPoolFunction ()

+
void
+(*GstTaskPoolFunction) (void *user_data);
+

Task function, see gst_task_pool_push().

+
+

Parameters

+
+++++ + + + + + +

user_data

user data for the task function

 
+
+
+
+
+

gst_task_pool_new ()

+
GstTaskPool *
+gst_task_pool_new (void);
+

Create a new default task pool. The default task pool will use a regular +GThreadPool for threads.

+
+

Returns

+

a new GstTaskPool. gst_object_unref() after usage.

+

[transfer full]

+
+
+
+
+

gst_task_pool_prepare ()

+
void
+gst_task_pool_prepare (GstTaskPool *pool,
+                       GError **error);
+

Prepare the taskpool for accepting gst_task_pool_push() operations.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstTaskPool

 

error

an error return location

 
+
+
+
+
+

gst_task_pool_push ()

+
gpointer
+gst_task_pool_push (GstTaskPool *pool,
+                    GstTaskPoolFunction func,
+                    gpointer user_data,
+                    GError **error);
+

Start the execution of a new thread from pool +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pool

a GstTaskPool

 

func

the function to call.

[scope async]

user_data

data to pass to func +.

[closure]

error

return location for an error

 
+
+
+

Returns

+

a pointer that should be used +for the gst_task_pool_join function. This pointer can be NULL, you +must check error +to detect errors.

+

[transfer none][nullable]

+
+
+
+
+

gst_task_pool_join ()

+
void
+gst_task_pool_join (GstTaskPool *pool,
+                    gpointer id);
+

Join a task and/or return it to the pool. id + is the id obtained from +gst_task_pool_push().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pool

a GstTaskPool

 

id

the id

 
+
+
+
+
+

gst_task_pool_cleanup ()

+
void
+gst_task_pool_cleanup (GstTaskPool *pool);
+

Wait for all tasks to be stopped. This is mainly used internally +to ensure proper cleanup of internal data structures in test suites.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pool

a GstTaskPool

 
+
+
+
+
+

Types and Values

+
+

struct GstTaskPool

+
struct GstTaskPool;
+

The GstTaskPool object.

+
+
+
+

struct GstTaskPoolClass

+
struct GstTaskPoolClass {
+  GstObjectClass parent_class;
+
+  void      (*prepare)  (GstTaskPool *pool, GError **error);
+  void      (*cleanup)  (GstTaskPool *pool);
+
+  gpointer  (*push)     (GstTaskPool *pool, GstTaskPoolFunction func,
+                         gpointer user_data, GError **error);
+  void      (*join)     (GstTaskPool *pool, gpointer id);
+};
+
+

The GstTaskPoolClass object.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

prepare ()

prepare the threadpool

 

cleanup ()

make sure all threads are stopped

 

push ()

start a new thread

 

join ()

join a thread

 
+
+
+
+
+

See Also

+

GstTask, GstPad

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstToc.html b/docs/gst/html/GstToc.html new file mode 100644 index 0000000..6944167 --- /dev/null +++ b/docs/gst/html/GstToc.html @@ -0,0 +1,1547 @@ + + + + +GstToc: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstToc

+

GstToc — Generic table of contents support

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstToc * + +gst_toc_new () +
#define +gst_toc_ref() +
#define +gst_toc_unref() +
#define +gst_toc_copy() +
#define +gst_toc_make_writable() +
+GstTocScope + +gst_toc_get_scope () +
+GList * + +gst_toc_get_entries () +
+void + +gst_toc_append_entry () +
+GstTagList * + +gst_toc_get_tags () +
+void + +gst_toc_merge_tags () +
+void + +gst_toc_set_tags () +
+void + +gst_toc_dump () +
+GstTocEntry * + +gst_toc_entry_new () +
#define +gst_toc_entry_ref() +
#define +gst_toc_entry_unref() +
#define +gst_toc_entry_copy() +
#define +gst_toc_entry_make_writable() +
+GstTocEntry * + +gst_toc_find_entry () +
+GstToc * + +gst_toc_entry_get_toc () +
const gchar * + +gst_toc_entry_get_uid () +
+GstTocEntry * + +gst_toc_entry_get_parent () +
+GList * + +gst_toc_entry_get_sub_entries () +
+void + +gst_toc_entry_append_sub_entry () +
+gboolean + +gst_toc_entry_get_loop () +
+void + +gst_toc_entry_set_loop () +
+gboolean + +gst_toc_entry_get_start_stop_times () +
+void + +gst_toc_entry_set_start_stop_times () +
+GstTagList * + +gst_toc_entry_get_tags () +
+void + +gst_toc_entry_merge_tags () +
+void + +gst_toc_entry_set_tags () +
const gchar * + +gst_toc_entry_type_get_nick () +
+GstTocEntryType + +gst_toc_entry_get_entry_type () +
+gboolean + +gst_toc_entry_is_alternative () +
+gboolean + +gst_toc_entry_is_sequence () +
#define +GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE() +
#define +GST_TOC_ENTRY_TYPE_IS_SEQUENCE() +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 GstToc
enumGstTocScope
 GstTocEntry
enumGstTocEntryType
enumGstTocLoopType
#defineGST_TOC_REPEAT_COUNT_INFINITE
+
+
+

Object Hierarchy

+
    GBoxed
+    ├── GstToc
+    ╰── GstTocEntry
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

GstToc functions are used to create/free GstToc and GstTocEntry structures. +Also they are used to convert GstToc into GstStructure and vice versa.

+

GstToc lets you to inform other elements in pipeline or application that playing +source has some kind of table of contents (TOC). These may be chapters, editions, +angles or other types. For example: DVD chapters, Matroska chapters or cue sheet +TOC. Such TOC will be useful for applications to display instead of just a +playlist.

+

Using TOC is very easy. Firstly, create GstToc structure which represents root +contents of the source. You can also attach TOC-specific tags to it. Then fill +it with GstTocEntry entries by appending them to the GstToc using +gst_toc_append_entry(), and appending subentries to a GstTocEntry using +gst_toc_entry_append_sub_entry().

+

Note that root level of the TOC can contain only either editions or chapters. You +should not mix them together at the same level. Otherwise you will get serialization +/deserialization errors. Make sure that no one of the entries has negative start and + stop values.

+

Use gst_event_new_toc() to create a new TOC GstEvent, and gst_event_parse_toc() to +parse received TOC event. Use gst_event_new_toc_select() to create a new TOC select GstEvent, +and gst_event_parse_toc_select() to parse received TOC select event. The same rule for +the GstMessage: gst_message_new_toc() to create new TOC GstMessage, and +gst_message_parse_toc() to parse received TOC message.

+

TOCs can have global scope or current scope. Global scope TOCs contain +all entries that can possibly be selected using a toc select event, and +are what an application is usually interested in. TOCs with current scope +only contain the parts of the TOC relevant to the currently selected/playing +stream; the current scope TOC is used by downstream elements such as muxers +to write correct TOC entries when transcoding files, for example. When +playing a DVD, the global TOC would contain a hierarchy of all titles, +chapters and angles, for example, while the current TOC would only contain +the chapters for the currently playing title if playback of a specific +title was requested.

+

Applications and plugins should not rely on TOCs having a certain kind of +structure, but should allow for different alternatives. For example, a +simple CUE sheet embedded in a file may be presented as a flat list of +track entries, or could have a top-level edition node (or some other +alternative type entry) with track entries underneath that node; or even +multiple top-level edition nodes (or some other alternative type entries) +each with track entries underneath, in case the source file has extracted +a track listing from different sources).

+
+
+

Functions

+
+

gst_toc_new ()

+
GstToc *
+gst_toc_new (GstTocScope scope);
+

Create a new GstToc structure.

+
+

Parameters

+
+++++ + + + + + +

scope

scope of this TOC

 
+
+
+

Returns

+

newly allocated GstToc structure, free it +with gst_toc_unref().

+

[transfer full]

+
+
+
+
+

gst_toc_ref()

+
#define gst_toc_ref(toc)            (GstToc*)gst_mini_object_ref(GST_MINI_OBJECT_CAST(toc))
+
+
+
+
+

gst_toc_unref()

+
#define gst_toc_unref(toc)          gst_mini_object_unref(GST_MINI_OBJECT_CAST(toc))
+
+
+
+
+

gst_toc_copy()

+
#define gst_toc_copy(toc)           (GstToc*)gst_mini_object_copy(GST_MINI_OBJECT_CAST(toc))
+
+

Copy GstToc with all subentries (deep copy).

+
+

Parameters

+
+++++ + + + + + +

toc

GstToc to copy.

 
+
+
+

Returns

+

newly allocated GstToc in case of success, +NULL otherwise; free it when done with gst_toc_unref().

+

[nullable]

+
+
+
+
+

gst_toc_make_writable()

+
#define gst_toc_make_writable(toc)  (GstToc*)gst_mini_object_make_writable(GST_MINI_OBJECT_CAST(toc))
+
+
+
+
+

gst_toc_get_scope ()

+
GstTocScope
+gst_toc_get_scope (const GstToc *toc);
+
+

Parameters

+
+++++ + + + + + +

toc

a GstToc instance

 
+
+
+

Returns

+

scope of toc +

+
+
+
+
+

gst_toc_get_entries ()

+
GList *
+gst_toc_get_entries (const GstToc *toc);
+

Gets the list of GstTocEntry of toc +.

+
+

Parameters

+
+++++ + + + + + +

toc

A GstToc instance

 
+
+
+

Returns

+

A GList of GstTocEntry for entry +.

+

[transfer none][element-type Gst.TocEntry]

+
+
+
+
+

gst_toc_append_entry ()

+
void
+gst_toc_append_entry (GstToc *toc,
+                      GstTocEntry *entry);
+

Appends the GstTocEntry entry + to toc +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

toc

A GstToc instance

 

entry

A GstTocEntry.

[transfer full]
+
+
+
+
+

gst_toc_get_tags ()

+
GstTagList *
+gst_toc_get_tags (const GstToc *toc);
+

Gets the tags for toc +.

+
+

Parameters

+
+++++ + + + + + +

toc

A GstToc instance

 
+
+
+

Returns

+

A GstTagList for entry +.

+

[transfer none]

+
+
+
+
+

gst_toc_merge_tags ()

+
void
+gst_toc_merge_tags (GstToc *toc,
+                    GstTagList *tags,
+                    GstTagMergeMode mode);
+

Merge tags + into the existing tags of toc + using mode +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

toc

A GstToc instance

 

tags

A GstTagList or NULL.

[allow-none]

mode

A GstTagMergeMode

 
+
+
+
+
+

gst_toc_set_tags ()

+
void
+gst_toc_set_tags (GstToc *toc,
+                  GstTagList *tags);
+

Set a GstTagList with tags for the complete toc +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

toc

A GstToc instance

 

tags

A GstTagList or NULL.

[allow-none][transfer full]
+
+
+
+
+

gst_toc_dump ()

+
void
+gst_toc_dump (GstToc *toc);
+
+
+
+

gst_toc_entry_new ()

+
GstTocEntry *
+gst_toc_entry_new (GstTocEntryType type,
+                   const gchar *uid);
+

Create new GstTocEntry structure.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

entry type.

 

uid

unique ID (UID) in the whole TOC.

 
+
+
+

Returns

+

newly allocated GstTocEntry structure, free it with gst_toc_entry_unref().

+
+
+
+
+

gst_toc_entry_ref()

+
#define gst_toc_entry_ref(entry)            (GstTocEntry*)gst_mini_object_ref(GST_MINI_OBJECT_CAST(entry))
+
+
+
+
+

gst_toc_entry_unref()

+
#define gst_toc_entry_unref(entry)          gst_mini_object_unref(GST_MINI_OBJECT_CAST(entry))
+
+
+
+
+

gst_toc_entry_copy()

+
#define gst_toc_entry_copy(entry)           (GstTocEntry*)gst_mini_object_copy(GST_MINI_OBJECT_CAST(entry))
+
+

Copy GstTocEntry with all subentries (deep copy).

+
+

Parameters

+
+++++ + + + + + +

entry

GstTocEntry to copy.

 
+
+
+

Returns

+

newly allocated GstTocEntry in case of +success, NULL otherwise; free it when done with +gst_toc_entry_unref().

+

[nullable]

+
+
+
+
+

gst_toc_entry_make_writable()

+
#define gst_toc_entry_make_writable(entry)  (GstTocEntry*)gst_mini_object_make_writable(GST_MINI_OBJECT_CAST(entry))
+
+
+
+
+

gst_toc_find_entry ()

+
GstTocEntry *
+gst_toc_find_entry (const GstToc *toc,
+                    const gchar *uid);
+

Find GstTocEntry with given uid + in the toc +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

toc

GstToc to search in.

 

uid

UID to find GstTocEntry with.

 
+
+
+

Returns

+

GstTocEntry with specified +uid +from the toc +, or NULL if not found.

+

[transfer none][nullable]

+
+
+
+
+

gst_toc_entry_get_toc ()

+
GstToc *
+gst_toc_entry_get_toc (GstTocEntry *entry);
+

Gets the parent GstToc of entry +.

+
+

Parameters

+
+++++ + + + + + +

entry

A GstTocEntry instance

 
+
+
+

Returns

+

The parent GstToc of entry +.

+

[transfer none]

+
+
+
+
+

gst_toc_entry_get_uid ()

+
const gchar *
+gst_toc_entry_get_uid (const GstTocEntry *entry);
+

Gets the UID of entry +.

+
+

Parameters

+
+++++ + + + + + +

entry

A GstTocEntry instance

 
+
+
+

Returns

+

The UID of entry +.

+

[transfer none]

+
+
+
+
+

gst_toc_entry_get_parent ()

+
GstTocEntry *
+gst_toc_entry_get_parent (GstTocEntry *entry);
+

Gets the parent GstTocEntry of entry +.

+
+

Parameters

+
+++++ + + + + + +

entry

A GstTocEntry instance

 
+
+
+

Returns

+

The parent GstTocEntry of entry +.

+

[transfer none][nullable]

+
+
+
+
+

gst_toc_entry_get_sub_entries ()

+
GList *
+gst_toc_entry_get_sub_entries (const GstTocEntry *entry);
+

Gets the sub-entries of entry +.

+
+

Parameters

+
+++++ + + + + + +

entry

A GstTocEntry instance

 
+
+
+

Returns

+

A GList of GstTocEntry of entry +.

+

[transfer none][element-type Gst.TocEntry]

+
+
+
+
+

gst_toc_entry_append_sub_entry ()

+
void
+gst_toc_entry_append_sub_entry (GstTocEntry *entry,
+                                GstTocEntry *subentry);
+

Appends the GstTocEntry subentry + to entry +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

entry

A GstTocEntry instance

 

subentry

A GstTocEntry.

[transfer full]
+
+
+
+
+

gst_toc_entry_get_loop ()

+
gboolean
+gst_toc_entry_get_loop (const GstTocEntry *entry,
+                        GstTocLoopType *loop_type,
+                        gint *repeat_count);
+

Get loop_type + and repeat_count + values from the entry + and write them into +appropriate storages. Loops are e.g. used by sampled instruments. GStreamer +is not automatically applying the loop. The application can process this +meta data and use it e.g. to send a seek-event to loop a section.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

entry

GstTocEntry to get values from.

 

loop_type

the storage for the loop_type +value, leave NULL if not need.

[out][allow-none]

repeat_count

the storage for the repeat_count +value, leave NULL if not need.

[out][allow-none]
+
+
+

Returns

+

TRUE if all non-NULL storage pointers were filled with appropriate +values, FALSE otherwise.

+
+

Since: 1.4

+
+
+
+

gst_toc_entry_set_loop ()

+
void
+gst_toc_entry_set_loop (GstTocEntry *entry,
+                        GstTocLoopType loop_type,
+                        gint repeat_count);
+

Set loop_type + and repeat_count + values for the entry +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

entry

GstTocEntry to set values.

 

loop_type

loop_type value to set.

 

repeat_count

repeat_count value to set.

 
+
+

Since: 1.4

+
+
+
+

gst_toc_entry_get_start_stop_times ()

+
gboolean
+gst_toc_entry_get_start_stop_times (const GstTocEntry *entry,
+                                    gint64 *start,
+                                    gint64 *stop);
+

Get start + and stop + values from the entry + and write them into appropriate +storages.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

entry

GstTocEntry to get values from.

 

start

the storage for the start value, leave +NULL if not need.

[out][allow-none]

stop

the storage for the stop value, leave +NULL if not need.

[out][allow-none]
+
+
+

Returns

+

TRUE if all non-NULL storage pointers were filled with appropriate +values, FALSE otherwise.

+
+
+
+
+

gst_toc_entry_set_start_stop_times ()

+
void
+gst_toc_entry_set_start_stop_times (GstTocEntry *entry,
+                                    gint64 start,
+                                    gint64 stop);
+

Set start + and stop + values for the entry +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

entry

GstTocEntry to set values.

 

start

start value to set.

 

stop

stop value to set.

 
+
+
+
+
+

gst_toc_entry_get_tags ()

+
GstTagList *
+gst_toc_entry_get_tags (const GstTocEntry *entry);
+

Gets the tags for entry +.

+
+

Parameters

+
+++++ + + + + + +

entry

A GstTocEntry instance

 
+
+
+

Returns

+

A GstTagList for entry +.

+

[transfer none]

+
+
+
+
+

gst_toc_entry_merge_tags ()

+
void
+gst_toc_entry_merge_tags (GstTocEntry *entry,
+                          GstTagList *tags,
+                          GstTagMergeMode mode);
+

Merge tags + into the existing tags of entry + using mode +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

entry

A GstTocEntry instance

 

tags

A GstTagList or NULL.

[allow-none]

mode

A GstTagMergeMode

 
+
+
+
+
+

gst_toc_entry_set_tags ()

+
void
+gst_toc_entry_set_tags (GstTocEntry *entry,
+                        GstTagList *tags);
+

Set a GstTagList with tags for the complete entry +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

entry

A GstTocEntry instance

 

tags

A GstTagList or NULL.

[allow-none][transfer full]
+
+
+
+
+

gst_toc_entry_type_get_nick ()

+
const gchar *
+gst_toc_entry_type_get_nick (GstTocEntryType type);
+

Converts type + to a string representation.

+
+

Parameters

+
+++++ + + + + + +

type

a GstTocEntryType.

 
+
+
+

Returns

+

Returns a human-readable string for type +. This string is +only for debugging purpose and should not be displayed in a user +interface.

+
+
+
+
+

gst_toc_entry_get_entry_type ()

+
GstTocEntryType
+gst_toc_entry_get_entry_type (const GstTocEntry *entry);
+
+

Parameters

+
+++++ + + + + + +

entry

a GstTocEntry

 
+
+
+

Returns

+

entry +'s entry type

+
+
+
+
+

gst_toc_entry_is_alternative ()

+
gboolean
+gst_toc_entry_is_alternative (const GstTocEntry *entry);
+
+

Parameters

+
+++++ + + + + + +

entry

a GstTocEntry

 
+
+
+

Returns

+

TRUE if entry +'s type is an alternative type, otherwise FALSE

+
+
+
+
+

gst_toc_entry_is_sequence ()

+
gboolean
+gst_toc_entry_is_sequence (const GstTocEntry *entry);
+
+

Parameters

+
+++++ + + + + + +

entry

a GstTocEntry

 
+
+
+

Returns

+

TRUE if entry +'s type is a sequence type, otherwise FALSE

+
+
+
+
+

GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE()

+
#define GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE(entry_type)  (entry_type < 0)
+
+

Checks if entry_type + indicates that its GstTocEntry is an alternative.

+
+

Parameters

+
+++++ + + + + + +

entry_type

The GstTocEntryType from a GstTocEntry

 
+
+
+
+
+

GST_TOC_ENTRY_TYPE_IS_SEQUENCE()

+
#define GST_TOC_ENTRY_TYPE_IS_SEQUENCE(entry_type)     (entry_type > 0)
+
+

Checks if entry_type + indicates that its GstTocEntry is a sequence.

+
+

Parameters

+
+++++ + + + + + +

entry_type

The GstTocEntryType from a GstTocEntry

 
+
+
+
+
+

Types and Values

+
+

GstToc

+
typedef struct _GstToc GstToc;
+
+
+
+

enum GstTocScope

+

The scope of a TOC.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_TOC_SCOPE_GLOBAL

+

global TOC representing all selectable options + (this is what applications are usually interested in)

+
 

GST_TOC_SCOPE_CURRENT

+

TOC for the currently active/selected stream + (this is a TOC representing the current stream from start to EOS, + and is what a TOC writer / muxer is usually interested in; it will + usually be a subset of the global TOC, e.g. just the chapters of + the current title, or the chapters selected for playback from the + current title)

+
 
+
+
+
+
+

GstTocEntry

+
typedef struct _GstTocEntry GstTocEntry;
+
+
+
+

enum GstTocEntryType

+

The different types of TOC entries (see GstTocEntry).

+

There are two types of TOC entries: alternatives or parts in a sequence.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_TOC_ENTRY_TYPE_ANGLE

+

entry is an angle (i.e. an alternative)

+
 

GST_TOC_ENTRY_TYPE_VERSION

+

entry is a version (i.e. alternative)

+
 

GST_TOC_ENTRY_TYPE_EDITION

+

entry is an edition (i.e. alternative)

+
 

GST_TOC_ENTRY_TYPE_INVALID

+

invalid entry type value

+
 

GST_TOC_ENTRY_TYPE_TITLE

+

entry is a title (i.e. a part of a sequence)

+
 

GST_TOC_ENTRY_TYPE_TRACK

+

entry is a track (i.e. a part of a sequence)

+
 

GST_TOC_ENTRY_TYPE_CHAPTER

+

entry is a chapter (i.e. a part of a sequence)

+
 
+
+
+
+
+

enum GstTocLoopType

+

How a GstTocEntry should be repeated. By default, entries are played a +single time.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_TOC_LOOP_NONE

+

single forward playback

+
 

GST_TOC_LOOP_FORWARD

+

repeat forward

+
 

GST_TOC_LOOP_REVERSE

+

repeat backward

+
 

GST_TOC_LOOP_PING_PONG

+

repeat forward and backward

+
 
+
+

Since: 1.4

+
+
+
+

GST_TOC_REPEAT_COUNT_INFINITE

+
#define GST_TOC_REPEAT_COUNT_INFINITE (-1)
+
+

Special value for the repeat_count set in gst_toc_entry_set_loop() or +returned by gst_toc_entry_set_loop() to indicate infinite looping.

+

Since: 1.4

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTracer.html b/docs/gst/html/GstTracer.html new file mode 100644 index 0000000..157cd0a --- /dev/null +++ b/docs/gst/html/GstTracer.html @@ -0,0 +1,1998 @@ + + + + +GstTracer: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTracer

+

GstTracer — Tracing base class

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +gst_tracer_register () +
+void + +gst_tracing_register_hook () +
+void + +(*GstTracerHookBinAddPost) () +
+void + +(*GstTracerHookBinAddPre) () +
+void + +(*GstTracerHookBinRemovePost) () +
+void + +(*GstTracerHookBinRemovePre) () +
+void + +(*GstTracerHookElementAddPad) () +
+void + +(*GstTracerHookElementChangeStatePost) () +
+void + +(*GstTracerHookElementChangeStatePre) () +
+void + +(*GstTracerHookElementNew) () +
+void + +(*GstTracerHookElementPostMessagePost) () +
+void + +(*GstTracerHookElementPostMessagePre) () +
+void + +(*GstTracerHookElementQueryPost) () +
+void + +(*GstTracerHookElementQueryPre) () +
+void + +(*GstTracerHookElementRemovePad) () +
+void + +(*GstTracerHookMiniObjectCreated) () +
+void + +(*GstTracerHookMiniObjectDestroyed) () +
+void + +(*GstTracerHookMiniObjectReffed) () +
+void + +(*GstTracerHookMiniObjectUnreffed) () +
+void + +(*GstTracerHookObjectCreated) () +
+void + +(*GstTracerHookObjectDestroyed) () +
+void + +(*GstTracerHookObjectReffed) () +
+void + +(*GstTracerHookObjectUnreffed) () +
+void + +(*GstTracerHookPadLinkPost) () +
+void + +(*GstTracerHookPadLinkPre) () +
+void + +(*GstTracerHookPadPullRangePost) () +
+void + +(*GstTracerHookPadPullRangePre) () +
+void + +(*GstTracerHookPadPushEventPost) () +
+void + +(*GstTracerHookPadPushEventPre) () +
+void + +(*GstTracerHookPadPushListPost) () +
+void + +(*GstTracerHookPadPushListPre) () +
+void + +(*GstTracerHookPadPushPost) () +
+void + +(*GstTracerHookPadPushPre) () +
+void + +(*GstTracerHookPadQueryPost) () +
+void + +(*GstTracerHookPadQueryPre) () +
+void + +(*GstTracerHookPadUnlinkPost) () +
+void + +(*GstTracerHookPadUnlinkPre) () +
+
+
+

Properties

+
+++++ + + + + + +
+gchar *paramsRead / Write / Construct
+
+
+

Types and Values

+
++++ + + + + +
structGstTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Tracing modules will subclass GstTracer and register through +gst_tracer_register(). Modules can attach to various hook-types - see +gst_tracing_register_hook(). When invoked they receive hook specific +contextual data, which they must not modify.

+
+
+

Functions

+
+

gst_tracer_register ()

+
gboolean
+gst_tracer_register (GstPlugin *plugin,
+                     const gchar *name,
+                     GType type);
+

Create a new tracer-factory capable of instantiating objects of the +type + and add the factory to plugin +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

plugin

A GstPlugin, or NULL for a static typefind function.

[allow-none]

name

The name for registering

 

type

GType of tracer to register

 
+
+
+

Returns

+

TRUE, if the registering succeeded, FALSE on error

+
+
+
+
+

gst_tracing_register_hook ()

+
void
+gst_tracing_register_hook (GstTracer *tracer,
+                           const gchar *detail,
+                           GCallback func);
+

Register func + to be called when the trace hook detail + is getting invoked. +Use NULL for detail + to register to all hooks.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

tracer

the tracer

 

detail

the detailed hook

 

func

the callback.

[scope async]
+
+
+
+
+

GstTracerHookBinAddPost ()

+
void
+(*GstTracerHookBinAddPost) (GObject *self,
+                            GstClockTime ts,
+                            GstBin *bin,
+                            GstElement *element,
+                            gboolean result);
+

Post-hook for gst_bin_add() named "bin-add-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

bin

the bin

 

element

the element

 

result

the result of gst_bin_add()

 
+
+
+
+
+

GstTracerHookBinAddPre ()

+
void
+(*GstTracerHookBinAddPre) (GObject *self,
+                           GstClockTime ts,
+                           GstBin *bin,
+                           GstElement *element);
+

Pre-hook for gst_bin_add() named "bin-add-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

bin

the bin

 

element

the element

 
+
+
+
+
+

GstTracerHookBinRemovePost ()

+
void
+(*GstTracerHookBinRemovePost) (GObject *self,
+                               GstClockTime ts,
+                               GstBin *bin,
+                               gboolean result);
+

Post-hook for gst_bin_remove() named "bin-remove-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

bin

the bin

 

result

the result of gst_bin_remove()

 
+
+
+
+
+

GstTracerHookBinRemovePre ()

+
void
+(*GstTracerHookBinRemovePre) (GObject *self,
+                              GstClockTime ts,
+                              GstBin *bin,
+                              GstElement *element);
+

Pre-hook for gst_bin_remove() named "bin-remove-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

bin

the bin

 

element

the element

 
+
+
+
+
+

GstTracerHookElementAddPad ()

+
void
+(*GstTracerHookElementAddPad) (GObject *self,
+                               GstClockTime ts,
+                               GstElement *element,
+                               GstPad *pad);
+

Hook for gst_element_add_pad() named "element-add-pad".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

pad

the pad

 
+
+
+
+
+

GstTracerHookElementChangeStatePost ()

+
void
+(*GstTracerHookElementChangeStatePost)
+                               (GObject *self,
+                                GstClockTime ts,
+                                GstElement *element,
+                                GstStateChange transition,
+                                GstStateChangeReturn result);
+

Post-hook for gst_element_change_state() named "element-change-state-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

transition

the transition

 

result

the result of gst_pad_push()

 
+
+
+
+
+

GstTracerHookElementChangeStatePre ()

+
void
+(*GstTracerHookElementChangeStatePre) (GObject *self,
+                                       GstClockTime ts,
+                                       GstElement *element,
+                                       GstStateChange transition);
+

Pre-hook for gst_element_change_state() named "element-change-state-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

transition

the transition

 
+
+
+
+
+

GstTracerHookElementNew ()

+
void
+(*GstTracerHookElementNew) (GObject *self,
+                            GstClockTime ts,
+                            GstElement *element);
+

Hook for whenever a new element is created, named "element-new".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 
+
+
+
+
+

GstTracerHookElementPostMessagePost ()

+
void
+(*GstTracerHookElementPostMessagePost)
+                               (GObject *self,
+                                GstClockTime ts,
+                                GstElement *element,
+                                gboolean res);
+

Pre-hook for gst_element_post_message() named "element-post-message-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

res

the result of gst_element_post_message()

 
+
+
+
+
+

GstTracerHookElementPostMessagePre ()

+
void
+(*GstTracerHookElementPostMessagePre) (GObject *self,
+                                       GstClockTime ts,
+                                       GstElement *element,
+                                       GstMessage *message);
+

Pre-hook for gst_element_post_message() named "element-post-message-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

message

the message

 
+
+
+
+
+

GstTracerHookElementQueryPost ()

+
void
+(*GstTracerHookElementQueryPost) (GObject *self,
+                                  GstClockTime ts,
+                                  GstElement *element,
+                                  GstQuery *query,
+                                  gboolean res);
+

Post-hook for gst_element_query() named "element-query-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

query

the query

 

res

the result of gst_element_query()

 
+
+
+
+
+

GstTracerHookElementQueryPre ()

+
void
+(*GstTracerHookElementQueryPre) (GObject *self,
+                                 GstClockTime ts,
+                                 GstElement *element,
+                                 GstQuery *query);
+

Pre-hook for gst_element_query() named "element-query-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

query

the query

 
+
+
+
+
+

GstTracerHookElementRemovePad ()

+
void
+(*GstTracerHookElementRemovePad) (GObject *self,
+                                  GstClockTime ts,
+                                  GstElement *element,
+                                  GstPad *pad);
+

Hook for gst_element_remove_pad() named "element-remove-pad".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

element

the element

 

pad

the pad

 
+
+
+
+
+

GstTracerHookMiniObjectCreated ()

+
void
+(*GstTracerHookMiniObjectCreated) (GObject *self,
+                                   GstClockTime ts,
+                                   GstMiniObject *object);
+

Hook called when a GstMiniObject is created named "mini-object-created".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the mini object being created

 
+
+
+
+
+

GstTracerHookMiniObjectDestroyed ()

+
void
+(*GstTracerHookMiniObjectDestroyed) (GObject *self,
+                                     GstClockTime ts,
+                                     GstMiniObject *object);
+

Hook called when a GstMiniObject is being destroyed named +"mini-object-destroyed".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the mini object being destroyed

 
+
+
+
+
+

GstTracerHookMiniObjectReffed ()

+
void
+(*GstTracerHookMiniObjectReffed) (GObject *self,
+                                  GstClockTime ts,
+                                  GstMiniObject *object,
+                                  gint new_refcount);
+

Hook called when a GstMiniObject is being reffed named +"mini-object-reffed".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the mini object being reffed

 

refcount

the new refcount after refing object +

 
+
+
+
+
+

GstTracerHookMiniObjectUnreffed ()

+
void
+(*GstTracerHookMiniObjectUnreffed) (GObject *self,
+                                    GstClockTime ts,
+                                    GstMiniObject *object,
+                                    gint new_refcount);
+

Hook called when a GstMiniObject is being unreffed named +"mini-object-unreffed".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the mini object being unreffed

 

refcount

the new refcount after unrefing object +

 
+
+
+
+
+

GstTracerHookObjectCreated ()

+
void
+(*GstTracerHookObjectCreated) (GObject *self,
+                               GstClockTime ts,
+                               GstObject *object);
+

Hook called when a GstObject is created named "object-created".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the object being created

 
+
+
+
+
+

GstTracerHookObjectDestroyed ()

+
void
+(*GstTracerHookObjectDestroyed) (GObject *self,
+                                 GstClockTime ts,
+                                 GstObject *object);
+

Hook called when a GstObject is being destroyed named +"object-destroyed".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the object being destroyed

 
+
+
+
+
+

GstTracerHookObjectReffed ()

+
void
+(*GstTracerHookObjectReffed) (GObject *self,
+                              GstClockTime ts,
+                              GstObject *object,
+                              gint new_refcount);
+

Hook called when a GstObject is being reffed named +"object-reffed".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the object being reffed

 

refcount

the new refcount after refing object +

 
+
+
+
+
+

GstTracerHookObjectUnreffed ()

+
void
+(*GstTracerHookObjectUnreffed) (GObject *self,
+                                GstClockTime ts,
+                                GstObject *object,
+                                gint new_refcount);
+

Hook called when a GstObject is being unreffed named +"object-unreffed"

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

object

the object being unreffed

 

refcount

the new refcount after unrefing object +

 
+
+
+
+
+

GstTracerHookPadLinkPost ()

+
void
+(*GstTracerHookPadLinkPost) (GObject *self,
+                             GstClockTime ts,
+                             GstPad *srcpad,
+                             GstPad *sinkpad,
+                             GstPadLinkReturn result);
+

Post-hook for gst_pad_link() named "pad-link-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

srcpad

the srcpad

 

sinkpad

the sinkpad

 

result

the result of gst_pad_link()

 
+
+
+
+
+

GstTracerHookPadLinkPre ()

+
void
+(*GstTracerHookPadLinkPre) (GObject *self,
+                            GstClockTime ts,
+                            GstPad *srcpad,
+                            GstPad *sinkpad);
+

Pre-hook for gst_pad_link() named "pad-link-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

srcpad

the srcpad

 

sinkpad

the sinkpad

 
+
+
+
+
+

GstTracerHookPadPullRangePost ()

+
void
+(*GstTracerHookPadPullRangePost) (GObject *self,
+                                  GstClockTime ts,
+                                  GstPad *pad,
+                                  GstBuffer *buffer,
+                                  GstFlowReturn res);
+

Post-hook for gst_pad_pull_range() named "pad-pull-range-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

buffer

the buffer

 

res

the result of gst_pad_pull_range()

 
+
+
+
+
+

GstTracerHookPadPullRangePre ()

+
void
+(*GstTracerHookPadPullRangePre) (GObject *self,
+                                 GstClockTime ts,
+                                 GstPad *pad,
+                                 guint64 offset,
+                                 guint size);
+

Pre-hook for gst_pad_pull_range() named "pad-pull-range-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

offset

the stream offset

 

size

the requested size

 
+
+
+
+
+

GstTracerHookPadPushEventPost ()

+
void
+(*GstTracerHookPadPushEventPost) (GObject *self,
+                                  GstClockTime ts,
+                                  GstPad *pad,
+                                  gboolean res);
+

Post-hook for gst_pad_push_event() named "pad-push-event-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

res

the result of gst_pad_push_event()

 
+
+
+
+
+

GstTracerHookPadPushEventPre ()

+
void
+(*GstTracerHookPadPushEventPre) (GObject *self,
+                                 GstClockTime ts,
+                                 GstPad *pad,
+                                 GstEvent *event);
+

Pre-hook for gst_pad_push_event() named "pad-push-event-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

event

the event

 
+
+
+
+
+

GstTracerHookPadPushListPost ()

+
void
+(*GstTracerHookPadPushListPost) (GObject *self,
+                                 GstClockTime ts,
+                                 GstPad *pad,
+                                 GstFlowReturn res);
+

Post-hook for gst_pad_push_list() named "pad-push-list-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

res

the result of gst_pad_push_list()

 
+
+
+
+
+

GstTracerHookPadPushListPre ()

+
void
+(*GstTracerHookPadPushListPre) (GObject *self,
+                                GstClockTime ts,
+                                GstPad *pad,
+                                GstBufferList *list);
+

Pre-hook for gst_pad_push_list() named "pad-push-list-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

list

the buffer-list

 
+
+
+
+
+

GstTracerHookPadPushPost ()

+
void
+(*GstTracerHookPadPushPost) (GObject *self,
+                             GstClockTime ts,
+                             GstPad *pad,
+                             GstFlowReturn res);
+

Post-hook for gst_pad_push() named "pad-push-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

res

the result of gst_pad_push()

 
+
+
+
+
+

GstTracerHookPadPushPre ()

+
void
+(*GstTracerHookPadPushPre) (GObject *self,
+                            GstClockTime ts,
+                            GstPad *pad,
+                            GstBuffer *buffer);
+

Pre-hook for gst_pad_push() named "pad-push-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

buffer

the buffer

 
+
+
+
+
+

GstTracerHookPadQueryPost ()

+
void
+(*GstTracerHookPadQueryPost) (GObject *self,
+                              GstClockTime ts,
+                              GstPad *pad,
+                              GstQuery *query,
+                              gboolean res);
+

Post-hook for gst_pad_query() named "pad-query-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

query

the query

 

res

the result of gst_pad_query()

 
+
+
+
+
+

GstTracerHookPadQueryPre ()

+
void
+(*GstTracerHookPadQueryPre) (GObject *self,
+                             GstClockTime ts,
+                             GstPad *pad,
+                             GstQuery *query);
+

Pre-hook for gst_pad_query() named "pad-query-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

pad

the pad

 

query

the query

 
+
+
+
+
+

GstTracerHookPadUnlinkPost ()

+
void
+(*GstTracerHookPadUnlinkPost) (GObject *self,
+                               GstClockTime ts,
+                               GstPad *srcpad,
+                               GstPad *sinkpad,
+                               gboolean result);
+

Post-hook for gst_pad_unlink() named "pad-unlink-post".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

srcpad

the srcpad

 

sinkpad

the sinkpad

 

result

the result of gst_pad_push()

 
+
+
+
+
+

GstTracerHookPadUnlinkPre ()

+
void
+(*GstTracerHookPadUnlinkPre) (GObject *self,
+                              GstClockTime ts,
+                              GstPad *srcpad,
+                              GstPad *sinkpad);
+

Pre-hook for gst_pad_unlink() named "pad-unlink-pre".

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

self

the tracer instance

 

ts

the current timestamp

 

srcpad

the srcpad

 

sinkpad

the sinkpad

 
+
+
+
+
+

Types and Values

+
+

struct GstTracer

+
struct GstTracer;
+
+
+
+

Property Details

+
+

The “params” property

+
  “params”                   gchar *
+

Extra configuration parameters.

+

Flags: Read / Write / Construct

+

Default value: NULL

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTracerFactory.html b/docs/gst/html/GstTracerFactory.html new file mode 100644 index 0000000..e996653 --- /dev/null +++ b/docs/gst/html/GstTracerFactory.html @@ -0,0 +1,155 @@ + + + + +GstTracerFactory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTracerFactory

+

GstTracerFactory — Information about registered tracer functions

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GList * + +gst_tracer_factory_get_list () +
+GType + +gst_tracer_factory_get_tracer_type () +
+
+
+

Types and Values

+
++++ + + + + +
 GstTracerFactory
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ╰── GstTracerFactory
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Use gst_tracer_factory_get_list() to get a list of tracer factories known to +GStreamer.

+
+
+

Functions

+
+

gst_tracer_factory_get_list ()

+
GList *
+gst_tracer_factory_get_list (void);
+

Gets the list of all registered tracer factories. You must free the +list using gst_plugin_feature_list_free().

+

The returned factories are sorted by factory name.

+

Free-function: gst_plugin_feature_list_free

+
+

Returns

+

the list of all +registered GstTracerFactory.

+

[transfer full][element-type Gst.TracerFactory]

+
+

Since: 1.8

+
+
+
+

gst_tracer_factory_get_tracer_type ()

+
GType
+gst_tracer_factory_get_tracer_type (GstTracerFactory *factory);
+

Get the GType for elements managed by this factory. The type can +only be retrieved if the element factory is loaded, which can be +assured with gst_plugin_feature_load().

+
+

Parameters

+
+++++ + + + + + +

factory

factory to get managed GType from

 
+
+
+

Returns

+

the GType for tracers managed by this factory or 0 if +the factory is not loaded.

+
+
+
+
+

Types and Values

+
+

GstTracerFactory

+
typedef struct _GstTracerFactory GstTracerFactory;
+

Opaque object that stores information about a tracer function.

+

Since: 1.8

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTracerRecord.html b/docs/gst/html/GstTracerRecord.html new file mode 100644 index 0000000..d5b5318 --- /dev/null +++ b/docs/gst/html/GstTracerRecord.html @@ -0,0 +1,297 @@ + + + + +GstTracerRecord: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTracerRecord

+

GstTracerRecord — Trace log entry class

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GstTracerRecord * + +gst_tracer_record_new () +
+void + +gst_tracer_record_log () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
 GstTracerRecord
enumGstTracerValueFlags
enumGstTracerValueScope
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracerRecord
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Tracing modules will create instances of this class to announce the data they +will log and create a log formatter.

+
+
+

Functions

+
+

gst_tracer_record_new ()

+
GstTracerRecord *
+gst_tracer_record_new (const gchar *name,
+                       const gchar *firstfield,
+                       ...);
+

Create a new tracer record. The record instance can be used to efficiently +log entries using gst_tracer_record_log().

+

The name + without the ".class" suffix will be used for the log records. +There must be fields for each value that gets logged where the field name is +the value name. The field must be a GstStructure describing the value. The +sub structure must contain a field called 'type' of G_TYPE_GTYPE that +contains the GType of the value. The resulting GstTracerRecord will take +ownership of the field structures.

+

The way to deal with optional values is to log an additional boolean before +the optional field, that if TRUE signals that the optional field is valid +and FALSE signals that the optional field should be ignored. One must still +log a placeholder value for the optional field though. Please also note, that +pointer type values must not be NULL - the underlying serialisation can not +handle that right now.

+

Please note that this is still under discussion and subject to change.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

name

name of new record, must end on ".class".

 

firstfield

name of first field to set

 

...

additional arguments

 
+
+
+

Returns

+

a new GstTracerRecord.

+

[transfer full]

+
+
+
+
+

gst_tracer_record_log ()

+
void
+gst_tracer_record_log (GstTracerRecord *self,
+                       ...);
+

Serialzes the trace event into the log.

+

Right now this is using the gstreamer debug log with the level TRACE (7) and +the category "GST_TRACER".

+

Please note that this is still under discussion and subject to change.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the tracer-record

 

...

the args as described in the spec-

 
+
+
+
+
+

Types and Values

+
+

GstTracerRecord

+
typedef struct _GstTracerRecord GstTracerRecord;
+
+
+
+

enum GstTracerValueFlags

+

Flag that describe the value. These flags help applications processing the +logs to understand the values.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_TRACER_VALUE_FLAGS_NONE

+

no flags

+
 

GST_TRACER_VALUE_FLAGS_OPTIONAL

+

the value is optional. When using this flag + one need to have an additional boolean arg before this value in the + var-args list passed to gst_tracer_record_log().

+
 

GST_TRACER_VALUE_FLAGS_AGGREGATED

+

the value is a combined figure, since the + start of tracing. Examples are averages or timestamps.

+
 
+
+
+
+
+

enum GstTracerValueScope

+

Tracing record will contain fields that contain a meassured value or extra +meta-data. One such meta data are values that tell where a measurement was +taken. This enumerating declares to which scope such a meta data field +relates to. If it is e.g. GST_TRACER_VALUE_SCOPE_PAD, then each of the log +events may contain values for different GstPads.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_TRACER_VALUE_SCOPE_PROCESS

+

the value is related to the process

+
 

GST_TRACER_VALUE_SCOPE_THREAD

+

the value is related to a thread

+
 

GST_TRACER_VALUE_SCOPE_ELEMENT

+

the value is related to an GstElement

+
 

GST_TRACER_VALUE_SCOPE_PAD

+

the value is related to a GstPad

+
 
+
+

Since: 1.8

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/GstTypeFindFactory.html b/docs/gst/html/GstTypeFindFactory.html new file mode 100644 index 0000000..d2ce61b --- /dev/null +++ b/docs/gst/html/GstTypeFindFactory.html @@ -0,0 +1,357 @@ + + + + +GstTypeFindFactory: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTypeFindFactory

+

GstTypeFindFactory — Information about registered typefind functions

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+GList * + +gst_type_find_factory_get_list () +
const gchar * const * + +gst_type_find_factory_get_extensions () +
+GstCaps * + +gst_type_find_factory_get_caps () +
+gboolean + +gst_type_find_factory_has_function () +
+void + +gst_type_find_factory_call_function () +
+
+
+

Types and Values

+
++++ + + + + +
 GstTypeFindFactory
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPluginFeature
+                ╰── GstTypeFindFactory
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

These functions allow querying informations about registered typefind +functions. How to create and register these functions is described in +the section +"Writing typefind functions".

+

The following example shows how to write a very simple typefinder that +identifies the given data. You can get quite a bit more complicated than +that though.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
typedef struct {
+  guint8 *data;
+  guint size;
+  guint probability;
+  GstCaps *data;
+} MyTypeFind;
+static void
+my_peek (gpointer data, gint64 offset, guint size)
+{
+  MyTypeFind *find = (MyTypeFind *) data;
+  if (offset >= 0 && offset + size <= find->size) {
+    return find->data + offset;
+  }
+  return NULL;
+}
+static void
+my_suggest (gpointer data, guint probability, GstCaps *caps)
+{
+  MyTypeFind *find = (MyTypeFind *) data;
+  if (probability > find->probability) {
+    find->probability = probability;
+    gst_caps_replace (&find->caps, caps);
+  }
+}
+static GstCaps *
+find_type (guint8 *data, guint size)
+{
+  GList *walk, *type_list;
+  MyTypeFind find = {data, size, 0, NULL};
+  GstTypeFind gst_find = {my_peek, my_suggest, &find, };
+  walk = type_list = gst_type_find_factory_get_list ();
+  while (walk) {
+    GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
+    walk = g_list_next (walk)
+    gst_type_find_factory_call_function (factory, &gst_find);
+  }
+  g_list_free (type_list);
+  return find.caps;
+};
+
+ +

+
+
+

Functions

+
+

gst_type_find_factory_get_list ()

+
GList *
+gst_type_find_factory_get_list (void);
+

Gets the list of all registered typefind factories. You must free the +list using gst_plugin_feature_list_free().

+

The returned factories are sorted by highest rank first, and then by +factory name.

+

Free-function: gst_plugin_feature_list_free

+
+

Returns

+

the list of all +registered GstTypeFindFactory.

+

[transfer full][element-type Gst.TypeFindFactory]

+
+
+
+
+

gst_type_find_factory_get_extensions ()

+
const gchar * const *
+gst_type_find_factory_get_extensions (GstTypeFindFactory *factory);
+

Gets the extensions associated with a GstTypeFindFactory. The returned +array should not be changed. If you need to change stuff in it, you should +copy it using g_strdupv(). This function may return NULL to indicate +a 0-length list.

+
+

Parameters

+
+++++ + + + + + +

factory

A GstTypeFindFactory

 
+
+
+

Returns

+

a NULL-terminated array of extensions associated with this factory.

+

[transfer none][array zero-terminated=1][element-type utf8][nullable]

+
+
+
+
+

gst_type_find_factory_get_caps ()

+
GstCaps *
+gst_type_find_factory_get_caps (GstTypeFindFactory *factory);
+

Gets the GstCaps associated with a typefind factory.

+
+

Parameters

+
+++++ + + + + + +

factory

A GstTypeFindFactory

 
+
+
+

Returns

+

the GstCaps associated with this factory.

+

[transfer none]

+
+
+
+
+

gst_type_find_factory_has_function ()

+
gboolean
+gst_type_find_factory_has_function (GstTypeFindFactory *factory);
+

Check whether the factory has a typefind function. Typefind factories +without typefind functions are a last-effort fallback mechanism to +e.g. assume a certain media type based on the file extension.

+
+

Parameters

+
+++++ + + + + + +

factory

A GstTypeFindFactory

 
+
+
+

Returns

+

TRUE if the factory has a typefind functions set, otherwise FALSE

+
+
+
+
+

gst_type_find_factory_call_function ()

+
void
+gst_type_find_factory_call_function (GstTypeFindFactory *factory,
+                                     GstTypeFind *find);
+

Calls the GstTypeFindFunction associated with this factory.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

factory

A GstTypeFindFactory

 

find

a properly setup GstTypeFind entry. The get_data +and suggest_type members must be set.

[transfer none]
+
+
+
+
+

Types and Values

+
+

GstTypeFindFactory

+
typedef struct _GstTypeFindFactory GstTypeFindFactory;
+

Opaque object that stores information about a typefind function.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/annotation-glossary.html b/docs/gst/html/annotation-glossary.html new file mode 100644 index 0000000..71d32a0 --- /dev/null +++ b/docs/gst/html/annotation-glossary.html @@ -0,0 +1,103 @@ + + + + +Annotation Glossary: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

A

+
allow-none
+

NULL is OK, both for passing and for returning.

+
array
+

Parameter points to an array of items.

+

C

+
closure
+

This parameter is a 'user_data', for callbacks; many bindings can pass NULL here.

+

E

+
element-type
+

Generics and defining elements of containers and arrays.

+

I

+
in
+

Parameter for input. Default is transfer none.

+
inout
+

Parameter for input and for returning results. Default is transfer full.

+

M

+
method
+

This is a method

+

N

+
nullable
+

NULL may be passed as the value in, out, in-out; or as a return value.

+

O

+
out
+

Parameter for returning results. Default is transfer full.

+
out callee-allocates
+

Out parameter, where caller must allocate storage.

+
out caller-allocates
+

Out parameter, where caller must allocate storage.

+

R

+
rename-to
+

Rename the original symbol's name to SYMBOL.

+

S

+
scope async
+

The callback is valid until first called.

+
scope call
+

The callback is valid only during the call to the method.

+
scope notified
+

The callback is valid until the GDestroyNotify argument is called.

+
skip
+

Exposed in C code, not necessarily available in other languages.

+

T

+
transfer container
+

Free data container after the code is done.

+
transfer floating
+

Alias for transfer none, used for objects with floating refs.

+
transfer full
+

Free data after the code is done.

+
transfer none
+

Don't free data after the code is done.

+
type
+

Override the parsed C type with given type.

+

V

+
virtual
+

This is the invoker for a virtual method.

+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gst-building.html b/docs/gst/html/gst-building.html new file mode 100644 index 0000000..55f43dd --- /dev/null +++ b/docs/gst/html/gst-building.html @@ -0,0 +1,108 @@ + + + + +Building GStreamer and GStreamer Applications: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Building GStreamer and GStreamer Applications

+

Building GStreamer and GStreamer Applications — +How to build the GStreamer framework and applications using it. +

+
+
+

Building GStreamer on UNIX

+

+ On UNIX, GStreamer uses the standard GNU build system, + using autoconf for package + configuration and resolving portability issues, + automake for building makefiles + that comply with the GNU Coding Standards, and + libtool for building shared + libraries on multiple platforms. The normal sequence for + compiling and installing the GStreamer library is thus: + +

+


+      ./configure
+      make
+      make install
+    

+

+

+

+ The standard options provided by GNU + autoconf may be passed to the + configure script. Please see the + autoconf documentation or run + ./configure --help for information about + the standard options. +

+

+ In addition there are several options to activate or deactivate features. + E.g. passing --disable-gst-debug to configure + will turn the debugging subsystem into a non-functional stub and remove all + macro based invocations from within the library (and anything compiled + against the library afterwards.) +

+

+ If library size matters and one builds in a controlled environment, it is + also possible to totally remove subsystem code. This is intentionally not + offered as a configure option as it causes an ABI break. Code built against + a version of GStreamer without these modifications needs to be recompiled. + +

+


+      make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED"
+    

+

+ +

+
    +
  • + GST_REMOVE_DEPRECATED - Omit deprecated functions + from the library. +

  • +
  • + GST_REMOVE_DISABLED - Omit stubs for disabled + subsystems from the library. +

  • +
+

+

+
+
+

Building GStreamer Applications

+

+Applications and libraries can use pkg-config to get all the +needed compiler and linker flags to build against GStreamer. Please note that +GStreamer is split into several libraries itself. +pkg-config --list-all | grep gstreamer will list the +available libraries. +

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gst-running.html b/docs/gst/html/gst-running.html new file mode 100644 index 0000000..39ec152 --- /dev/null +++ b/docs/gst/html/gst-running.html @@ -0,0 +1,414 @@ + + + + +Running GStreamer Applications: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Running GStreamer Applications

+

Running GStreamer Applications — +How to run and debug your GStreamer application +

+
+
+

Running and debugging GStreamer Applications

+
+

Environment variables

+

+GStreamer inspects a few of environment variables in addition to standard +variables like LANG, PATH or HOME. +

+

GST_PLUGIN_SYSTEM_PATH, + GST_PLUGIN_SYSTEM_PATH_1_0 + +This environment variable can be set to a colon-separated list of paths (or +semicolon-separated list on Windows). +If this variable is not set, GStreamer will fill in this list for you +with +

+
    +
  • +plug-ins in the user's home directory, or rather the user's "data home" +directory according to the xdg base dir specification. Usually this will be +a directory called +plugins inside the +.local/share/gstreamer-1.0 directory in +the user's home directory by default, though this search path may change if +the XDG_DATA_HOME environment variable is set. +

  • +
  • +plug-ins installed system-wide. On this system, they are stored in +/usr/local/lib/gstreamer-1.0. +

  • +
+

+ +GStreamer will scan these paths for GStreamer plug-ins. These plug-ins will +be loaded after the plug-ins in the GST_PLUGIN_PATH variable below. + +The paths are scanned in the given order. This allows a user to override +system-installed plug-ins with his own versions. + +The GST_PLUGIN_SYSTEM_PATH_1_0 variant is useful if both the old GStreamer 0.10 +version and the new GStreamer 1.0 version need to be pointed to new plugin +paths. The latter will use the _1_0 variant over the non-versioned one if +it is set. + +Setting this variable to an empty string will cause GStreamer not to scan any +system paths at all for plug-ins. This can be useful if you're running +uninstalled (for development purposes) or while running testsuites. +

+

GST_PLUGIN_PATH, GST_PLUGIN_PATH_1_0 +This environment variable can be set to a colon-separated list of paths (or a +semicolon-separated list on Windows). +GStreamer will scan these paths for GStreamer plug-ins. These plug-ins will +be loaded in addition to, and before, the plug-ins in the system paths. + +The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer 0.10 +version and the new GStreamer 1.0 version need to be pointed to new plugin +paths. The latter will use the _1_0 variant over the non-versioned one if +it is set. +

+

GST_DEBUG +If GStreamer has been configured with --enable-gst-debug=yes, +this variable can be set to a list of debug options, which cause GStreamer +to print out different types of debugging information to stderr. + +The variable takes a comma-separated list of "category_name:level" pairs +to set specific levels for the individual categories. +The level value ranges from 0 (nothing) to 9 (MEMDUMP). +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

1 - ERROR

+Logs all fatal errors. These are errors that do not allow the core or elements +to perform the requested action. The application can still recover if +programmed to handle the conditions that triggered the error. +

2 - WARNING

+Logs all warnings. Typically these are non-fatal, but user-visible problems +are expected to happen. +

3 - FIXME

+Logs all fixme messages. Fixme messages are messages that indicate that something +in the executed code path is not fully implemented or handled yet. The purpose +of this message is to make it easier to spot incomplete/unfinished pieces of +code when reading the debug log. +

4 - INFO

+Logs all informational messages. These are typically used for events in +the system that only happen once, or are important and rare enough to be +logged at this level. +

5 - DEBUG

+Logs all debug messages. These are general debug messages for events +that happen only a limited number of times during an object's lifetime; +these include setup, teardown, change of parameters, ... +

6 - LOG

+Logs all log messages. These are messages for events +that happen repeatedly during an object's lifetime; +these include streaming and steady-state conditions. +

7 - TRACE

+Logs all trace messages. These messages for events +that happen repeatedly during an object's lifetime such as the +ref/unref cycles. +

9 - MEMDUMP

+Log all memory dump messages. Memory dump messages are used to log +(small) chunks of data as memory dumps in the log. They will be displayed +as hexdump with ASCII characters. +

+

+ + The category_name can contain "*" as a wildcard. + +For example, setting GST_DEBUG to +GST_AUTOPLUG:6,GST_ELEMENT_*:4, will cause the +GST_AUTOPLUG category to be logged at full +LOG level, while all categories starting with +GST_ELEMENT_ will be logged at INFO level. + +To get all possible debug output, set +GST_DEBUG +to *:9. For debugging purposes a *:6 debug +log is usually the most useful, as it contains all important information, but +hides a lot of noise such as refs/unrefs. For bug reporting purposes, a +*:6 log is also what will be requested usually. It's often +also worth running with *:3 to see if there are any +non-fatal errors or warnings that might be related to the problem at hand. + +Since GStreamer 1.2 it is also possible to specify debug levels by name, +e.g. GST_DEBUG=*:WARNING,*audio*:LOG +

+

GST_DEBUG_NO_COLOR +Set this environment variable to any value ("1" typically) to switch off +colouring in GST_DEBUG output. This has the same effect as specifying the +--gst-debug-no-color or +--gst-debug-color-mode=off command line option to +well-behaved GStreamer applications (ie. those that pass command-line +options correctly to GStreamer). +This is particularly useful to reduce the size of debug output and also allows +for the output to be compressed much better than with colours turned on. + +Has the same effect as setting GST_DEBUG_COLOR_MODE environment variable to +"off". +

+

GST_DEBUG_COLOR_MODE +Set this environment variable to change log colouring in GST_DEBUG output. +Possible values: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + +

on

+Enables debug log output coloring. Uses default coloring method for current +platform. This is the default. +

off

+

+Disables debug log output coloring. This has the same effect as specifying the +--gst-debug-color-mode=off command line option to +well-behaved GStreamer applications (ie. those that pass command-line +options correctly to GStreamer). +This is particularly useful to reduce the size of debug output and also allows +for the output to be compressed much better than with colours turned on. +

+

+Has the same effect as setting GST_DEBUG_NO_COLOR environment variable to +any value. +

+

auto

+Same as on. +

disable

+Same as off. +

unix

+Enables debug log output coloring and forces the use of UNIX termial codes +for coloring, even if this method is not normally used on current platform. +This has the same effect as specifying the +--gst-debug-color-mode=unix command line option to +well-behaved GStreamer applications (ie. those that pass command-line options +correctly to GStreamer). +This is particularly useful to dump debug output into a file on non-UNIX +platforms to be sent to developers who have viewers that support UNIX terminal +codes. +

+

+

+

GST_DEBUG_OPTIONS +This environment variable can be used to tweak the behaviour of the debugging +system. Currently the only options supported are "pretty-tags" and "full-tags". +In "pretty-tags" mode (the default), taglists in the debug log will be +serialized so that only the first few and last few bytes of a buffer-type tag +will be serialized into the log, to avoid dumping hundreds of lines of useless +output into the log in case of large image tags and the like. +

+

GST_DEBUG_DUMP_DOT_DIR +Set this environment variable to a path to turn on all +#GST_DEBUG_BIN_TO_DOT_FILE or #GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS calls +and have the dot files in that location. + +This will only work if the application in question makes these calls in +strategic places (like when the pipeline state changes or an error occurs). +gst-launch-1.0 is one such application. + +When gst-launch-1.0 changes state through NULL to PLAYING +and back to NULL, a dot file is generated on each state change. To have +gst-launch-1.0 write a snapshot of the pipeline state, send +a SIGHUP to the gst-launch-1.0 process. + +These .dot files can then be turned into images using the 'dot' utility +from the graphviz set of tools, like this: + dot foo.dot -Tsvg -o foo.svg or + dot foo.dot -Tpng -o foo.png or + dot foo.dot -Tjpg -o foo.jpg. + +There is also a utility called xdot which allows you to +view the dot file directly without converting it first. +

+

GST_REGISTRY, GST_REGISTRY_1_0 +Set this environment variable to make GStreamer use a different file for the +plugin cache / registry than the default one. This is useful when operating +in a separate environment which should not affect the default cache in the +user's home directory. +

+

GST_REGISTRY_FORK +Set this environment variable to "no" to prevent GStreamer from forking on +startup in order to update the plugin registry. This is useful for debugging +purposes, but should not be used under normal circumstances, since it means +that plugins may be loaded into memory even if they are not needed by the +application. +

+

GST_REGISTRY_UPDATE +Set this environment variable to "no" to prevent GStreamer from updating the +plugin registry. This is useful for embedded device which is not updating the +plugins frequently, it will save time when doing gst_init(). +

+

GST_TRACE + Enable memory allocation tracing. Most GStreamer objects have support for + tracing the number of unfreed objects and their memory pointers. + +The variable takes a comma-separated list of tracing options to enable. +

+
++++ + + + + + + + + + + +

live

+ Counts all live objects and dumps an overview of the number of unfreed + objects at program exit. +

mem-live

+ Keep track of the unfreed memory pointers and dump an overview of all unfreed + memory at program exit. Together with a level 9 debug log this can be used to + follow the lifecycle of leaked objects in order to track down where they are + leaked. This can be useful for debugging memory leaks in situations where + tools such as valgrind are not available, or not an option. +

+

+ + Use all to enable all tracing flags. +

+

GST_DEBUG_FILE + Set this variable to a file path to redirect all GStreamer debug + messages to this file. If left unset, debug messages with be output + unto the standard error. +

+

ORC_CODE +Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers +such as gdb to create useful backtraces from Orc-generated code. Set +ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code +generator is producing incorrect code (Quite a few important +GStreamer plugins like videotestsrc, audioconvert or audioresample use Orc). +One can also combine flags like ORC_CODE=backup,debug. +

+

G_DEBUG +Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make +GStreamer programs abort when a critical warning such as an assertion failure +occurs. This is useful if you want to find out which part of the code caused +that warning to be triggered and under what circumstances. Simply set G_DEBUG +as mentioned above and run the program in gdb (or let it core dump). Then get +a stack trace in the usual way. +

+

G_SLICE +Useful GLib environment variable. Set G_SLICE=always-malloc when running +GStreamer programs in valgrind, or debugging memory leaks with other tools. +See the GLib API reference for more details. +

+

GST_TAG_ENCODING +Try this character encoding first for tag-related strings where the encoding +is not defined and which are not UTF-8 already. By default the current locale +will be tried (if not UTF-8). +

+

GST_TAG_ID3_ENCODING +Try this character encoding first for ID3 tag-related strings where the +encoding is not defined and which are not UTF-8 already. By default the current +locale will be tried (if not UTF-8). +

+

GST_TAG_ID3V1_ENCODING +Try this character encoding first for ID3v1 tag-related strings where the +encoding does not look like UTF-8. +

+

GST_GL_WINDOW +Influences the window system to use by the GStreamer OpenGL library. +Common values are 'x11', 'wayland', 'win32' or 'cocoa'. +

+

GST_GL_PLATFORM +Influences the OpenGL platform to use by the GStreamer OpenGL library. +Common values are 'egl', 'glx', 'wgl' or 'cgl'. +

+

GST_GL_API +Influences the OpenGL API requested by the OpenGL platform. +Common values are 'opengl' or 'gles2'. +

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-1.0.devhelp2 b/docs/gst/html/gstreamer-1.0.devhelp2 new file mode 100644 index 0000000..de7018b --- /dev/null +++ b/docs/gst/html/gstreamer-1.0.devhelp2 @@ -0,0 +1,3294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/gst/html/gstreamer-Gst.html b/docs/gst/html/gstreamer-Gst.html new file mode 100644 index 0000000..21c1870 --- /dev/null +++ b/docs/gst/html/gstreamer-Gst.html @@ -0,0 +1,578 @@ + + + + +GStreamer: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GStreamer

+

GStreamer — Media library supporting arbitrary formats and filter + graphs.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +gst_init () +
+gboolean + +gst_init_check () +
+GOptionGroup * + +gst_init_get_option_group () +
+gboolean + +gst_is_initialized () +
+void + +gst_deinit () +
+void + +gst_version () +
+gchar * + +gst_version_string () +
+gboolean + +gst_segtrap_is_enabled () +
+void + +gst_segtrap_set_enabled () +
+gboolean + +gst_registry_fork_is_enabled () +
+void + +gst_registry_fork_set_enabled () +
+gboolean + +gst_update_registry () +
const gchar * + +gst_get_main_executable_path () +
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GStreamer is a framework for constructing graphs of various filters +(termed elements here) that will handle streaming media. Any discrete +(packetizable) media type is supported, with provisions for automatically +determining source type. Formatting/framing information is provided with +a powerful negotiation framework. Plugins are heavily used to provide for +all elements, allowing one to construct plugins outside of the GST +library, even released binary-only if license require (please don't). +GStreamer covers a wide range of use cases including: playback, recording, +editing, serving streams, voice over ip and video calls.

+

The GStreamer library should be initialized with +gst_init() before it can be used. You should pass pointers to the main argc +and argv variables so that GStreamer can process its own command line +options, as shown in the following example.

+
+

Initializing the gstreamer library

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
int
+main (int argc, char *argv[])
+{
+  // initialize the GStreamer library
+  gst_init (&argc, &argv);
+  ...
+}
+
+ +

+

It's allowed to pass two NULL pointers to gst_init() in case you don't want +to pass the command line args to GStreamer.

+

You can also use GOption to initialize your own parameters as shown in +the next code fragment:

+
+
+

Initializing own parameters when initializing gstreamer

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
static gboolean stats = FALSE;
+...
+int
+main (int argc, char *argv[])
+{
+ GOptionEntry options[] = {
+  {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
+      N_("Output tags (also known as metadata)"), NULL},
+  {NULL}
+ };
+ ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
+ 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);
+...
+}
+
+ +

+

Use gst_version() to query the library version at runtime or use the +GST_VERSION_* macros to find the version at compile time. Optionally +gst_version_string() returns a printable string.

+

The gst_deinit() call is used to clean up all internal resources used +by GStreamer. It is mostly used in unit tests to check for leaks.

+
+
+
+

Functions

+
+

gst_init ()

+
void
+gst_init (int *argc,
+          char **argv[]);
+

Initializes the GStreamer library, setting up internal path lists, +registering built-in elements, and loading standard plugins.

+

Unless the plugin registry is disabled at compile time, the registry will be +loaded. By default this will also check if the registry cache needs to be +updated and rescan all plugins if needed. See gst_update_registry() for +details and section

+Running GStreamer Applications

for how to disable automatic registry updates.

+

This function will terminate your program if it was unable to initialize +GStreamer for some reason. If you want your program to fall back, +use gst_init_check() instead.

+

WARNING: This function does not work in the same way as corresponding +functions in other glib-style libraries, such as gtk_init(). In +particular, unknown command line options cause this function to +abort program execution.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

argc

pointer to application's argc.

[inout][allow-none]

argv

pointer to application's argv.

[inout][array length=argc][allow-none]
+
+
+
+
+

gst_init_check ()

+
gboolean
+gst_init_check (int *argc,
+                char **argv[],
+                GError **err);
+

Initializes the GStreamer library, setting up internal path lists, +registering built-in elements, and loading standard plugins.

+

This function will return FALSE if GStreamer could not be initialized +for some reason. If you want your program to fail fatally, +use gst_init() instead.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

argc

pointer to application's argc.

[inout][allow-none]

argv

pointer to application's argv.

[inout][array length=argc][allow-none]

err

pointer to a GError to which a message will be posted on error

 
+
+
+

Returns

+

TRUE if GStreamer could be initialized.

+
+
+
+
+

gst_init_get_option_group ()

+
GOptionGroup *
+gst_init_get_option_group (void);
+

Returns a GOptionGroup with GStreamer's argument specifications. The +group is set up to use standard GOption callbacks, so when using this +group in combination with GOption parsing methods, all argument parsing +and initialization is automated.

+

This function is useful if you want to integrate GStreamer with other +libraries that use GOption (see g_option_context_add_group() ).

+

If you use this function, you should make sure you initialise the GLib +threading system as one of the very first things in your program +(see the example at the beginning of this section).

+

[skip]

+
+

Returns

+

a pointer to GStreamer's option group.

+

[transfer full][nullable]

+
+
+
+
+

gst_is_initialized ()

+
gboolean
+gst_is_initialized (void);
+

Use this function to check if GStreamer has been initialized with gst_init() +or gst_init_check().

+
+

Returns

+

TRUE if initialization has been done, FALSE otherwise.

+
+
+
+
+

gst_deinit ()

+
void
+gst_deinit (void);
+

Clean up any resources created by GStreamer in gst_init().

+

It is normally not needed to call this function in a normal application +as the resources will automatically be freed when the program terminates. +This function is therefore mostly used by testsuites and other memory +profiling tools.

+

After this call GStreamer (including this method) should not be used anymore.

+
+
+
+

gst_version ()

+
void
+gst_version (guint *major,
+             guint *minor,
+             guint *micro,
+             guint *nano);
+

Gets the version number of the GStreamer library.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

major

pointer to a guint to store the major version number.

[out]

minor

pointer to a guint to store the minor version number.

[out]

micro

pointer to a guint to store the micro version number.

[out]

nano

pointer to a guint to store the nano version number.

[out]
+
+
+
+
+

gst_version_string ()

+
gchar *
+gst_version_string (void);
+

This function returns a string that is useful for describing this version +of GStreamer to the outside world: user agent strings, logging, ...

+
+

Returns

+

a newly allocated string describing this version +of GStreamer.

+

[transfer full]

+
+
+
+
+

gst_segtrap_is_enabled ()

+
gboolean
+gst_segtrap_is_enabled (void);
+

Some functions in the GStreamer core might install a custom SIGSEGV handler +to better catch and report errors to the application. Currently this feature +is enabled by default when loading plugins.

+

Applications might want to disable this behaviour with the +gst_segtrap_set_enabled() function. This is typically done if the application +wants to install its own handler without GStreamer interfering.

+
+

Returns

+

TRUE if GStreamer is allowed to install a custom SIGSEGV handler.

+
+
+
+
+

gst_segtrap_set_enabled ()

+
void
+gst_segtrap_set_enabled (gboolean enabled);
+

Applications might want to disable/enable the SIGSEGV handling of +the GStreamer core. See gst_segtrap_is_enabled() for more information.

+
+

Parameters

+
+++++ + + + + + +

enabled

whether a custom SIGSEGV handler should be installed.

 
+
+
+
+
+

gst_registry_fork_is_enabled ()

+
gboolean
+gst_registry_fork_is_enabled (void);
+

By default GStreamer will perform scanning and rebuilding of the +registry file using a helper child process.

+

Applications might want to disable this behaviour with the +gst_registry_fork_set_enabled() function, in which case new plugins +are scanned (and loaded) into the application process.

+
+

Returns

+

TRUE if GStreamer will use the child helper process when +rebuilding the registry.

+
+
+
+
+

gst_registry_fork_set_enabled ()

+
void
+gst_registry_fork_set_enabled (gboolean enabled);
+

Applications might want to disable/enable spawning of a child helper process +when rebuilding the registry. See gst_registry_fork_is_enabled() for more +information.

+
+

Parameters

+
+++++ + + + + + +

enabled

whether rebuilding the registry can use a temporary child helper process.

 
+
+
+
+
+

gst_update_registry ()

+
gboolean
+gst_update_registry (void);
+

Forces GStreamer to re-scan its plugin paths and update the default +plugin registry.

+

Applications will almost never need to call this function, it is only +useful if the application knows new plugins have been installed (or old +ones removed) since the start of the application (or, to be precise, the +first call to gst_init()) and the application wants to make use of any +newly-installed plugins without restarting the application.

+

Applications should assume that the registry update is neither atomic nor +thread-safe and should therefore not have any dynamic pipelines running +(including the playbin and decodebin elements) and should also not create +any elements or access the GStreamer registry while the update is in +progress.

+

Note that this function may block for a significant amount of time.

+
+

Returns

+

TRUE if the registry has been updated successfully (does not +imply that there were changes), otherwise FALSE.

+
+
+
+
+

gst_get_main_executable_path ()

+
const gchar *
+gst_get_main_executable_path (void);
+

This helper is mostly helpful for plugins that need to +inspect the folder of the main executable to determine +their set of features.

+

When a plugin is initialized from the gst-plugin-scanner +external process, the returned path will be the same as from the +parent process.

+
+

Returns

+

The path of the executable that +initialized GStreamer, or NULL if it could not be determined.

+

[transfer none][nullable]

+
+

Since: 1.14

+
+
+
+

Types and Values

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstAtomicQueue.html b/docs/gst/html/gstreamer-GstAtomicQueue.html new file mode 100644 index 0000000..44a5a64 --- /dev/null +++ b/docs/gst/html/gstreamer-GstAtomicQueue.html @@ -0,0 +1,328 @@ + + + + +GstAtomicQueue: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstAtomicQueue

+

GstAtomicQueue — An atomic queue implementation

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstAtomicQueue * + +gst_atomic_queue_new () +
+void + +gst_atomic_queue_ref () +
+void + +gst_atomic_queue_unref () +
+void + +gst_atomic_queue_push () +
+gpointer + +gst_atomic_queue_peek () +
+gpointer + +gst_atomic_queue_pop () +
+guint + +gst_atomic_queue_length () +
+
+
+

Types and Values

+
++++ + + + + +
 GstAtomicQueue
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

The GstAtomicQueue object implements a queue that can be used from multiple +threads without performing any blocking operations.

+
+
+

Functions

+
+

gst_atomic_queue_new ()

+
GstAtomicQueue *
+gst_atomic_queue_new (guint initial_size);
+

Create a new atomic queue instance. initial_size + will be rounded up to the +nearest power of 2 and used as the initial size of the queue.

+
+

Parameters

+
+++++ + + + + + +

initial_size

initial queue size

 
+
+
+

Returns

+

a new GstAtomicQueue

+
+
+
+
+

gst_atomic_queue_ref ()

+
void
+gst_atomic_queue_ref (GstAtomicQueue *queue);
+

Increase the refcount of queue +.

+
+

Parameters

+
+++++ + + + + + +

queue

a GstAtomicQueue

 
+
+
+
+
+

gst_atomic_queue_unref ()

+
void
+gst_atomic_queue_unref (GstAtomicQueue *queue);
+

Unref queue + and free the memory when the refcount reaches 0.

+
+

Parameters

+
+++++ + + + + + +

queue

a GstAtomicQueue

 
+
+
+
+
+

gst_atomic_queue_push ()

+
void
+gst_atomic_queue_push (GstAtomicQueue *queue,
+                       gpointer data);
+

Append data + to the tail of the queue.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstAtomicQueue

 

data

the data

 
+
+
+
+
+

gst_atomic_queue_peek ()

+
gpointer
+gst_atomic_queue_peek (GstAtomicQueue *queue);
+

Peek the head element of the queue without removing it from the queue.

+
+

Parameters

+
+++++ + + + + + +

queue

a GstAtomicQueue

 
+
+
+

Returns

+

the head element of queue +or +NULL when the queue is empty.

+

[transfer none][nullable]

+
+
+
+
+

gst_atomic_queue_pop ()

+
gpointer
+gst_atomic_queue_pop (GstAtomicQueue *queue);
+

Get the head element of the queue.

+
+

Parameters

+
+++++ + + + + + +

queue

a GstAtomicQueue

 
+
+
+

Returns

+

the head element of queue +or NULL when +the queue is empty.

+

[transfer full]

+
+
+
+
+

gst_atomic_queue_length ()

+
guint
+gst_atomic_queue_length (GstAtomicQueue *queue);
+

Get the amount of items in the queue.

+
+

Parameters

+
+++++ + + + + + +

queue

a GstAtomicQueue

 
+
+
+

Returns

+

the number of elements in the queue.

+
+
+
+
+

Types and Values

+
+

GstAtomicQueue

+
typedef struct _GstAtomicQueue GstAtomicQueue;
+

Opaque atomic data queue.

+

Use the accessor functions to get the stored values.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstConfig.html b/docs/gst/html/gstreamer-GstConfig.html new file mode 100644 index 0000000..568e70a --- /dev/null +++ b/docs/gst/html/gstreamer-GstConfig.html @@ -0,0 +1,138 @@ + + + + +GstConfig: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstConfig

+

GstConfig — Build configuration options

+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
#defineGST_DISABLE_GST_DEBUG
#defineGST_DISABLE_PARSE
#defineGST_DISABLE_REGISTRY
#defineGST_DISABLE_PLUGIN
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

This describes the configuration options for GStreamer. When building +GStreamer there are a lot of parts (known internally as "subsystems" ) that +can be disabled for various reasons. The most common reasons are speed and +size, which is important because GStreamer is designed to run on embedded +systems.

+

If a subsystem is disabled, most of this changes are done in an API +compatible way, so you don't need to adapt your code in most cases. It is +never done in an ABI compatible way though. So if you want to disable a +subsystem, you have to rebuild all programs depending on GStreamer, too.

+

If a subsystem is disabled in GStreamer, a value is defined in +<gst/gst.h>. You can check this if you do subsystem-specific stuff.

+
+

Example 1. Doing subsystem specific things

+
+ + + + + + + +
1
+2
+3
#ifndef GST_DISABLE_GST_DEBUG
+// do stuff specific to the debugging subsystem
+#endif // GST_DISABLE_GST_DEBUG
+
+ +
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

GST_DISABLE_GST_DEBUG

+
#define GST_DISABLE_GST_DEBUG 1
+
+

Configures the inclusion of the debugging subsystem

+
+
+
+

GST_DISABLE_PARSE

+
#define GST_DISABLE_PARSE 1
+
+

Configures the inclusion of the gst-launch parser

+
+
+
+

GST_DISABLE_REGISTRY

+
#define GST_DISABLE_REGISTRY 1
+
+

Configures the use of the plugin registry. +If one disables this, required plugins need to be loaded and registered +manually

+
+
+
+

GST_DISABLE_PLUGIN

+
#define GST_DISABLE_PLUGIN 1
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstDevice.html b/docs/gst/html/gstreamer-GstDevice.html new file mode 100644 index 0000000..6439c65 --- /dev/null +++ b/docs/gst/html/gstreamer-GstDevice.html @@ -0,0 +1,485 @@ + + + + +GstDevice: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDevice

+

GstDevice — Object representing a device

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstElement * + +gst_device_create_element () +
+GstCaps * + +gst_device_get_caps () +
+gchar * + +gst_device_get_device_class () +
+gchar * + +gst_device_get_display_name () +
+gboolean + +gst_device_has_classes () +
+gboolean + +gst_device_has_classesv () +
+gboolean + +gst_device_reconfigure_element () +
+GstStructure * + +gst_device_get_properties () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstDevice
structGstDeviceClass
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

GstDevice are objects representing a device, they contain +relevant metadata about the device, such as its class and the GstCaps +representing the media types it can produce or handle.

+

GstDevice are created by GstDeviceProvider objects which can be +aggregated by GstDeviceMonitor objects.

+
+
+

Functions

+
+

gst_device_create_element ()

+
GstElement *
+gst_device_create_element (GstDevice *device,
+                           const gchar *name);
+

Creates the element with all of the required parameters set to use +this device.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

device

a GstDevice

 

name

name of new element, or NULL to automatically +create a unique name.

[allow-none]
+
+
+

Returns

+

a new GstElement configured to use +this device.

+

[transfer full][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_get_caps ()

+
GstCaps *
+gst_device_get_caps (GstDevice *device);
+

Getter for the GstCaps that this device supports.

+
+

Parameters

+
+++++ + + + + + +

device

a GstDevice

 
+
+
+

Returns

+

The GstCaps supported by this device. Unref with +gst_caps_unref() when done.

+

[nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_get_device_class ()

+
gchar *
+gst_device_get_device_class (GstDevice *device);
+

Gets the "class" of a device. This is a "/" separated list of +classes that represent this device. They are a subset of the +classes of the GstDeviceProvider that produced this device.

+
+

Parameters

+
+++++ + + + + + +

device

a GstDevice

 
+
+
+

Returns

+

The device class. Free with g_free() after use.

+
+

Since: 1.4

+
+
+
+

gst_device_get_display_name ()

+
gchar *
+gst_device_get_display_name (GstDevice *device);
+

Gets the user-friendly name of the device.

+
+

Parameters

+
+++++ + + + + + +

device

a GstDevice

 
+
+
+

Returns

+

The device name. Free with g_free() after use.

+
+

Since: 1.4

+
+
+
+

gst_device_has_classes ()

+
gboolean
+gst_device_has_classes (GstDevice *device,
+                        const gchar *classes);
+

Check if device + matches all of the given classes

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

device

a GstDevice

 

classes

a "/"-separated list of device classes to match, only match if +all classes are matched

 
+
+
+

Returns

+

TRUE if device +matches.

+
+

Since: 1.4

+
+
+
+

gst_device_has_classesv ()

+
gboolean
+gst_device_has_classesv (GstDevice *device,
+                         gchar **classes);
+

Check if factory + matches all of the given classes

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

device

a GstDevice

 

classes

a NULL terminated array of classes +to match, only match if all classes are matched.

[array zero-terminated=1]
+
+
+

Returns

+

TRUE if device +matches.

+
+

Since: 1.4

+
+
+
+

gst_device_reconfigure_element ()

+
gboolean
+gst_device_reconfigure_element (GstDevice *device,
+                                GstElement *element);
+

Tries to reconfigure an existing element to use the device. If this +function fails, then one must destroy the element and create a new one +using gst_device_create_element().

+

Note: This should only be implemented for elements can change their +device in the PLAYING state.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

device

a GstDevice

 

element

a GstElement

 
+
+
+

Returns

+

TRUE if the element could be reconfigured to use this device, +FALSE otherwise.

+
+

Since: 1.4

+
+
+
+

gst_device_get_properties ()

+
GstStructure *
+gst_device_get_properties (GstDevice *device);
+

Gets the extra properties of a device.

+
+

Parameters

+
+++++ + + + + + +

device

a GstDevice

 
+
+
+

Returns

+

The extra properties or NULL when there are none. +Free with gst_structure_free() after use.

+

[nullable]

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstDevice

+
struct GstDevice {
+  GstObject         parent;
+};
+
+

A device object.

+
+

Members

+
+++++ + + + + + +

GstObject parent;

The parent GstObject strucuture.

 
+
+

Since: 1.4

+
+
+
+

struct GstDeviceClass

+
struct GstDeviceClass {
+  GstObjectClass    parent_class;
+
+  GstElement * (*create_element)      (GstDevice * device, const gchar * name);
+  gboolean     (*reconfigure_element) (GstDevice * device, GstElement * element);
+};
+
+

The class structure for a GstDevice object.

+
+

Members

+
+++++ + + + + + + + + + + + + +

create_element ()

Creates the fully configured element to access this device. +Subclasses need to override this and return a new element.

 

reconfigure_element ()

This only needs to be implemented by subclasses if the +element can be reconfigured to use a different device. See the documentation +for gst_device_reconfigure_element().

 
+
+

Since: 1.4

+
+
+
+

See Also

+

GstDeviceProvider

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstDeviceMonitor.html b/docs/gst/html/gstreamer-GstDeviceMonitor.html new file mode 100644 index 0000000..0568b96 --- /dev/null +++ b/docs/gst/html/gstreamer-GstDeviceMonitor.html @@ -0,0 +1,764 @@ + + + + +GstDeviceMonitor: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDeviceMonitor

+

GstDeviceMonitor — A device monitor and prober

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstDeviceMonitor
structGstDeviceMonitorClass
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Applications should create a GstDeviceMonitor when they want +to probe, list and monitor devices of a specific type. The +GstDeviceMonitor will create the appropriate +GstDeviceProvider objects and manage them. It will then post +messages on its GstBus for devices that have been added and +removed.

+

The device monitor will monitor all devices matching the filters that +the application has set.

+

The basic use pattern of a device monitor is as follows:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
static gboolean
+my_bus_func (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+   GstDevice *device;
+   gchar *name;
+
+   switch (GST_MESSAGE_TYPE (message)) {
+     case GST_MESSAGE_DEVICE_ADDED:
+       gst_message_parse_device_added (message, &device);
+       name = gst_device_get_display_name (device);
+       g_print("Device added: %s\n", name);
+       g_free (name);
+       gst_object_unref (device);
+       break;
+     case GST_MESSAGE_DEVICE_REMOVED:
+       gst_message_parse_device_removed (message, &device);
+       name = gst_device_get_display_name (device);
+       g_print("Device removed: %s\n", name);
+       g_free (name);
+       gst_object_unref (device);
+       break;
+     default:
+       break;
+   }
+
+   return G_SOURCE_CONTINUE;
+}
+
+GstDeviceMonitor *
+setup_raw_video_source_device_monitor (void) {
+   GstDeviceMonitor *monitor;
+   GstBus *bus;
+   GstCaps *caps;
+
+   monitor = gst_device_monitor_new ();
+
+   bus = gst_device_monitor_get_bus (monitor);
+   gst_bus_add_watch (bus, my_bus_func, NULL);
+   gst_object_unref (bus);
+
+   caps = gst_caps_new_empty_simple ("video/x-raw");
+   gst_device_monitor_add_filter (monitor, "Video/Source", caps);
+   gst_caps_unref (caps);
+
+   gst_device_monitor_start (monitor);
+
+   return monitor;
+}
+
+ +

+
+
+

Functions

+
+

gst_device_monitor_new ()

+
GstDeviceMonitor *
+gst_device_monitor_new (void);
+

Create a new GstDeviceMonitor

+
+

Returns

+

a new device monitor.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_get_bus ()

+
GstBus *
+gst_device_monitor_get_bus (GstDeviceMonitor *monitor);
+

Gets the GstBus of this GstDeviceMonitor

+
+

Parameters

+
+++++ + + + + + +

monitor

a GstDeviceProvider

 
+
+
+

Returns

+

a GstBus.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_add_filter ()

+
guint
+gst_device_monitor_add_filter (GstDeviceMonitor *monitor,
+                               const gchar *classes,
+                               GstCaps *caps);
+

Adds a filter for which GstDevice will be monitored, any device that matches +all these classes and the GstCaps will be returned.

+

If this function is called multiple times to add more filters, each will be +matched independently. That is, adding more filters will not further restrict +what devices are matched.

+

The GstCaps supported by the device as returned by gst_device_get_caps() are +not intersected with caps filters added using this function.

+

Filters must be added before the GstDeviceMonitor is started.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

monitor

a device monitor

 

classes

device classes to use as filter or NULL for any class.

[allow-none]

caps

the GstCaps to filter or NULL for ANY.

[allow-none]
+
+
+

Returns

+

The id of the new filter or 0 if no provider matched the filter's +classes.

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_remove_filter ()

+
gboolean
+gst_device_monitor_remove_filter (GstDeviceMonitor *monitor,
+                                  guint filter_id);
+

Removes a filter from the GstDeviceMonitor using the id that was returned +by gst_device_monitor_add_filter().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

monitor

a device monitor

 

filter_id

the id of the filter

 
+
+
+

Returns

+

TRUE of the filter id was valid, FALSE otherwise

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_start ()

+
gboolean
+gst_device_monitor_start (GstDeviceMonitor *monitor);
+

Starts monitoring the devices, one this has succeeded, the +GST_MESSAGE_DEVICE_ADDED and GST_MESSAGE_DEVICE_REMOVED messages +will be emitted on the bus when the list of devices changes.

+
+

Parameters

+
+++++ + + + + + +

monitor

A GstDeviceMonitor

 
+
+
+

Returns

+

TRUE if the device monitoring could be started

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_stop ()

+
void
+gst_device_monitor_stop (GstDeviceMonitor *monitor);
+

Stops monitoring the devices.

+
+

Parameters

+
+++++ + + + + + +

monitor

A GstDeviceProvider

 
+
+

Since: 1.4

+
+
+
+

gst_device_monitor_get_devices ()

+
GList *
+gst_device_monitor_get_devices (GstDeviceMonitor *monitor);
+

Gets a list of devices from all of the relevant monitors. This may actually +probe the hardware if the monitor is not currently started.

+
+

Parameters

+
+++++ + + + + + +

monitor

A GstDeviceProvider

 
+
+
+

Returns

+

a GList of +GstDevice.

+

[transfer full][element-type GstDevice][nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_monitor_get_providers ()

+
gchar **
+gst_device_monitor_get_providers (GstDeviceMonitor *monitor);
+

Get a list of the currently selected device provider factories.

+

This

+
+

Parameters

+
+++++ + + + + + +

monitor

a GstDeviceMonitor

 
+
+
+

Returns

+

A list of device provider factory names that are currently being +monitored by monitor +or NULL when nothing is being monitored.

+

[transfer full][array zero-terminated=1][element-type gchar*]

+
+

Since: 1.6

+
+
+
+

gst_device_monitor_get_show_all_devices ()

+
gboolean
+gst_device_monitor_get_show_all_devices
+                               (GstDeviceMonitor *monitor);
+

Get if monitor + is curretly showing all devices, even those from hidden +providers.

+
+

Parameters

+
+++++ + + + + + +

monitor

a GstDeviceMonitor

 
+
+
+

Returns

+

TRUE when all devices will be shown.

+
+

Since: 1.6

+
+
+
+

gst_device_monitor_set_show_all_devices ()

+
void
+gst_device_monitor_set_show_all_devices
+                               (GstDeviceMonitor *monitor,
+                                gboolean show_all);
+

Set if all devices should be visible, even those devices from hidden +providers. Setting show_all + to true might show some devices multiple times.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

monitor

a GstDeviceMonitor

 

show_all

show all devices

 
+
+

Since: 1.6

+
+
+
+

gst_device_provider_get_hidden_providers ()

+
gchar **
+gst_device_provider_get_hidden_providers
+                               (GstDeviceProvider *provider);
+

Get the provider factory names of the GstDeviceProvider instances that +are hidden by provider +.

+
+

Parameters

+
+++++ + + + + + +

provider

a GstDeviceProvider

 
+
+
+

Returns

+

a list of hidden providers factory names or NULL when +nothing is hidden by provider +. Free with g_strfreev.

+

[transfer full][array zero-terminated=1][element-type gchar*]

+
+

Since: 1.6

+
+
+
+

gst_device_provider_hide_provider ()

+
void
+gst_device_provider_hide_provider (GstDeviceProvider *provider,
+                                   const gchar *name);
+

Make provider + hide the devices from the factory with name +.

+

This function is used when provider + will also provide the devices reported +by provider factory name +. A monitor should stop monitoring the +device provider with name + to avoid duplicate devices.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

provider

a GstDeviceProvider

 

name

a provider factory name

 
+
+

Since: 1.6

+
+
+
+

gst_device_provider_unhide_provider ()

+
void
+gst_device_provider_unhide_provider (GstDeviceProvider *provider,
+                                     const gchar *name);
+

Make provider + unhide the devices from factory name +.

+

This function is used when provider + will no longer provide the devices +reported by provider factory name +. A monitor should start +monitoring the devices from provider factory name + in order to see +all devices again.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

provider

a GstDeviceProvider

 

name

a provider factory name

 
+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstDeviceMonitor

+
struct GstDeviceMonitor {
+  GstObject                parent;
+};
+
+

Opaque device monitor object structure.

+
+

Members

+
+++++ + + + + + +

GstObject parent;

the parent GstObject structure

 
+
+

Since: 1.4

+
+
+
+

struct GstDeviceMonitorClass

+
struct GstDeviceMonitorClass {
+  GstObjectClass           parent_class;
+};
+
+

Opaque device monitor class structure.

+
+

Members

+
+++++ + +
+
+

Since: 1.4

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstDeviceProvider.html b/docs/gst/html/gstreamer-GstDeviceProvider.html new file mode 100644 index 0000000..a1d3553 --- /dev/null +++ b/docs/gst/html/gstreamer-GstDeviceProvider.html @@ -0,0 +1,853 @@ + + + + +GstDeviceProvider: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDeviceProvider

+

GstDeviceProvider — A device provider

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstDeviceProvider
structGstDeviceProviderClass
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

A GstDeviceProvider subclass is provided by a plugin that handles devices +if there is a way to programatically list connected devices. It can also +optionally provide updates to the list of connected devices.

+

Each GstDeviceProvider subclass is a singleton, a plugin should +normally provide a single subclass for all devices.

+

Applications would normally use a GstDeviceMonitor to monitor devices +from all relevant providers.

+
+
+

Functions

+
+

gst_device_provider_can_monitor ()

+
gboolean
+gst_device_provider_can_monitor (GstDeviceProvider *provider);
+
+
+
+

gst_device_provider_class_add_metadata ()

+
void
+gst_device_provider_class_add_metadata
+                               (GstDeviceProviderClass *klass,
+                                const gchar *key,
+                                const gchar *value);
+

Set key + with value + as metadata in klass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

key

the key to set

 

value

the value to set

 
+
+

Since: 1.4

+
+
+
+

gst_device_provider_class_add_static_metadata ()

+
void
+gst_device_provider_class_add_static_metadata
+                               (GstDeviceProviderClass *klass,
+                                const gchar *key,
+                                const gchar *value);
+

Set key + with value + as metadata in klass +.

+

Same as gst_device_provider_class_add_metadata(), but value + must be a static string +or an inlined string, as it will not be copied. (GStreamer plugins will +be made resident once loaded, so this function can be used even from +dynamically loaded plugins.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

key

the key to set

 

value

the value to set.

[transfer full]
+
+

Since: 1.4

+
+
+
+

gst_device_provider_class_get_metadata ()

+
const gchar *
+gst_device_provider_class_get_metadata
+                               (GstDeviceProviderClass *klass,
+                                const gchar *key);
+

Get metadata with key + in klass +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

klass

class to get metadata for

 

key

the key to get

 
+
+
+

Returns

+

the metadata for key +.

+

[nullable]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_class_set_metadata ()

+
void
+gst_device_provider_class_set_metadata
+                               (GstDeviceProviderClass *klass,
+                                const gchar *longname,
+                                const gchar *classification,
+                                const gchar *description,
+                                const gchar *author);
+

Sets the detailed information for a GstDeviceProviderClass.

+

This function is for use in _class_init functions only.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

longname

The long English name of the device provider. E.g. "File Sink"

 

classification

String describing the type of device provider, as an +unordered list separated with slashes ('/'). See draft-klass.txt of the +design docs +for more details and common types. E.g: "Sink/File"

 

description

Sentence describing the purpose of the device provider. +E.g: "Write stream to a file"

 

author

Name and contact details of the author(s). Use \n to separate +multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"

 
+
+

Since: 1.4

+
+
+
+

gst_device_provider_class_set_static_metadata ()

+
void
+gst_device_provider_class_set_static_metadata
+                               (GstDeviceProviderClass *klass,
+                                const gchar *longname,
+                                const gchar *classification,
+                                const gchar *description,
+                                const gchar *author);
+

Sets the detailed information for a GstDeviceProviderClass.

+

This function is for use in _class_init functions only.

+

Same as gst_device_provider_class_set_metadata(), but longname +, classification +, +description +, and author + must be static strings or inlined strings, as +they will not be copied. (GStreamer plugins will be made resident once +loaded, so this function can be used even from dynamically loaded plugins.)

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

klass

class to set metadata for

 

longname

The long English name of the element. E.g. "File Sink".

[transfer full]

classification

String describing the type of element, as +an unordered list separated with slashes ('/'). See draft-klass.txt of the +design docs for more details and common types. E.g: "Sink/File".

[transfer full]

description

Sentence describing the purpose of the +element. E.g: "Write stream to a file".

[transfer full]

author

Name and contact details of the author(s). Use \n +to separate multiple author metadata. E.g: "Joe Bloggs <joe.blogs at +foo.com>".

[transfer full]
+
+

Since: 1.4

+
+
+
+

gst_device_provider_device_add ()

+
void
+gst_device_provider_device_add (GstDeviceProvider *provider,
+                                GstDevice *device);
+

Posts a message on the provider's GstBus to inform applications that +a new device has been added.

+

This is for use by subclasses.

+

device +'s reference count will be incremented, and any floating reference +will be removed (see gst_object_ref_sink()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

provider

a GstDeviceProvider

 

device

a GstDevice that has been added.

[transfer floating]
+
+

Since: 1.4

+
+
+
+

gst_device_provider_device_remove ()

+
void
+gst_device_provider_device_remove (GstDeviceProvider *provider,
+                                   GstDevice *device);
+

Posts a message on the provider's GstBus to inform applications that +a device has been removed.

+

This is for use by subclasses.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

provider

a GstDeviceProvider

 

device

a GstDevice that has been removed

 
+
+

Since: 1.4

+
+
+
+

gst_device_provider_get_bus ()

+
GstBus *
+gst_device_provider_get_bus (GstDeviceProvider *provider);
+

Gets the GstBus of this GstDeviceProvider

+
+

Parameters

+
+++++ + + + + + +

provider

a GstDeviceProvider

 
+
+
+

Returns

+

a GstBus.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_get_devices ()

+
GList *
+gst_device_provider_get_devices (GstDeviceProvider *provider);
+

Gets a list of devices that this provider understands. This may actually +probe the hardware if the provider is not currently started.

+
+

Parameters

+
+++++ + + + + + +

provider

A GstDeviceProvider

 
+
+
+

Returns

+

a GList of +GstDevice.

+

[transfer full][element-type GstDevice]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_get_factory ()

+
GstDeviceProviderFactory *
+gst_device_provider_get_factory (GstDeviceProvider *provider);
+

Retrieves the factory that was used to create this device provider.

+
+

Parameters

+
+++++ + + + + + +

provider

a GstDeviceProvider to request the device provider factory of.

 
+
+
+

Returns

+

the GstDeviceProviderFactory used for +creating this device provider. no refcounting is needed.

+

[transfer none]

+
+

Since: 1.4

+
+
+
+

gst_device_provider_get_metadata ()

+
const gchar *
+gst_device_provider_get_metadata (GstDeviceProvider *provider,
+                                  const gchar *key);
+

Get metadata with key + in provider +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

provider

provider to get metadata for

 

key

the key to get

 
+
+
+

Returns

+

the metadata for key +.

+
+

Since: 1.14

+
+
+
+

gst_device_provider_register ()

+
gboolean
+gst_device_provider_register (GstPlugin *plugin,
+                              const gchar *name,
+                              guint rank,
+                              GType type);
+

Create a new device providerfactory capable of instantiating objects of the +type + and add the factory to plugin +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

plugin

GstPlugin to register the device provider with, or NULL for +a static device provider.

[allow-none]

name

name of device providers of this type

 

rank

rank of device provider (higher rank means more importance when autoplugging)

 

type

GType of device provider to register

 
+
+
+

Returns

+

TRUE, if the registering succeeded, FALSE on error

+
+

Since: 1.4

+
+
+
+

gst_device_provider_start ()

+
gboolean
+gst_device_provider_start (GstDeviceProvider *provider);
+

Starts providering the devices. This will cause GST_MESSAGE_DEVICE_ADDED +and GST_MESSAGE_DEVICE_REMOVED messages to be posted on the provider's bus +when devices are added or removed from the system.

+

Since the GstDeviceProvider is a singleton, +gst_device_provider_start() may already have been called by another +user of the object, gst_device_provider_stop() needs to be called the same +number of times.

+
+

Parameters

+
+++++ + + + + + +

provider

A GstDeviceProvider

 
+
+
+

Returns

+

TRUE if the device providering could be started

+
+

Since: 1.4

+
+
+
+

gst_device_provider_stop ()

+
void
+gst_device_provider_stop (GstDeviceProvider *provider);
+

Decreases the use-count by one. If the use count reaches zero, this +GstDeviceProvider will stop providering the devices. This needs to be +called the same number of times that gst_device_provider_start() was called.

+
+

Parameters

+
+++++ + + + + + +

provider

A GstDeviceProvider

 
+
+

Since: 1.4

+
+
+
+

Types and Values

+
+

struct GstDeviceProvider

+
struct GstDeviceProvider {
+  GstObject         parent;
+
+  /* Protected by the Object lock */
+  GList *devices;
+};
+
+

The structure of the base GstDeviceProvider

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstObject parent;

The parent GstObject

 

GList *devices;

a GList of the GstDevice objects

 
+
+

Since: 1.4

+
+
+
+

struct GstDeviceProviderClass

+
struct GstDeviceProviderClass {
+  GstObjectClass    parent_class;
+
+  GstDeviceProviderFactory     *factory;
+
+  GList*      (*probe) (GstDeviceProvider * provider);
+
+  gboolean    (*start) (GstDeviceProvider * provider);
+  void        (*stop)  (GstDeviceProvider * provider);
+};
+
+

The structure of the base GstDeviceProviderClass

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstDeviceProviderFactory *factory;

a pointer to the GstDeviceProviderFactory that creates this +provider

 

probe ()

Returns a list of devices that are currently available. +This should never block.

 

start ()

Starts monitoring for new devices. Only subclasses that can know +that devices have been added or remove need to implement this method.

 

stop ()

Stops monitoring for new devices. Only subclasses that implement +the start() method need to implement this method.

 
+
+

Since: 1.4

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstFormat.html b/docs/gst/html/gstreamer-GstFormat.html new file mode 100644 index 0000000..3641458 --- /dev/null +++ b/docs/gst/html/gstreamer-GstFormat.html @@ -0,0 +1,470 @@ + + + + +GstFormat: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstFormat

+

GstFormat — Dynamically register new data formats

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
const gchar * + +gst_format_get_name () +
+GQuark + +gst_format_to_quark () +
+GstFormat + +gst_format_register () +
+GstFormat + +gst_format_get_by_nick () +
+gboolean + +gst_formats_contains () +
const GstFormatDefinition * + +gst_format_get_details () +
+GstIterator * + +gst_format_iterate_definitions () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
enumGstFormat
#defineGST_FORMAT_PERCENT_MAX
#defineGST_FORMAT_PERCENT_SCALE
structGstFormatDefinition
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstFormats functions are used to register a new format to the gstreamer +core. Formats can be used to perform seeking or conversions/query +operations.

+
+
+

Functions

+
+

gst_format_get_name ()

+
const gchar *
+gst_format_get_name (GstFormat format);
+

Get a printable name for the given format. Do not modify or free.

+
+

Parameters

+
+++++ + + + + + +

format

a GstFormat

 
+
+
+

Returns

+

a reference to the static name of the format +or NULL if the format is unknown.

+

[nullable]

+
+
+
+
+

gst_format_to_quark ()

+
GQuark
+gst_format_to_quark (GstFormat format);
+

Get the unique quark for the given format.

+
+

Parameters

+
+++++ + + + + + +

format

a GstFormat

 
+
+
+

Returns

+

the quark associated with the format or 0 if the format +is unknown.

+
+
+
+
+

gst_format_register ()

+
GstFormat
+gst_format_register (const gchar *nick,
+                     const gchar *description);
+

Create a new GstFormat based on the nick or return an +already registered format with that nick.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

nick

The nick of the new format

 

description

The description of the new format

 
+
+
+

Returns

+

A new GstFormat or an already registered format +with the same nick.

+

MT safe.

+
+
+
+
+

gst_format_get_by_nick ()

+
GstFormat
+gst_format_get_by_nick (const gchar *nick);
+

Return the format registered with the given nick.

+
+

Parameters

+
+++++ + + + + + +

nick

The nick of the format

 
+
+
+

Returns

+

The format with nick +or GST_FORMAT_UNDEFINED +if the format was not registered.

+
+
+
+
+

gst_formats_contains ()

+
gboolean
+gst_formats_contains (const GstFormat *formats,
+                      GstFormat format);
+

See if the given format is inside the format array.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

formats

The format array to search.

[array zero-terminated=1]

format

the format to find

 
+
+
+

Returns

+

TRUE if the format is found inside the array

+
+
+
+
+

gst_format_get_details ()

+
const GstFormatDefinition *
+gst_format_get_details (GstFormat format);
+

Get details about the given format.

+
+

Parameters

+
+++++ + + + + + +

format

The format to get details of

 
+
+
+

Returns

+

The GstFormatDefinition for format +or NULL +on failure.

+

MT safe.

+

[nullable]

+
+
+
+
+

gst_format_iterate_definitions ()

+
GstIterator *
+gst_format_iterate_definitions (void);
+

Iterate all the registered formats. The format definition is read +only.

+
+

Returns

+

a GstIterator of GstFormatDefinition.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

enum GstFormat

+

Standard predefined formats

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_FORMAT_UNDEFINED

+

undefined format

+
 

GST_FORMAT_DEFAULT

+

the default format of the pad/element. This can be + samples for raw audio, frames/fields for raw video (some, but not all, + elements support this; use GST_FORMAT_TIME + if you don't have a good + reason to query for samples/frames)

+
 

GST_FORMAT_BYTES

+

bytes

+
 

GST_FORMAT_TIME

+

time in nanoseconds

+
 

GST_FORMAT_BUFFERS

+

buffers (few, if any, elements implement this as of + May 2009)

+
 

GST_FORMAT_PERCENT

+

percentage of stream (few, if any, elements implement + this as of May 2009)

+
 
+
+
+
+
+

GST_FORMAT_PERCENT_MAX

+
#define GST_FORMAT_PERCENT_MAX          G_GINT64_CONSTANT (1000000)
+
+

The PERCENT format is between 0 and this value

+
+
+
+

GST_FORMAT_PERCENT_SCALE

+
#define GST_FORMAT_PERCENT_SCALE        G_GINT64_CONSTANT (10000)
+
+

The value used to scale down the reported PERCENT format value to +its real value.

+
+
+
+

struct GstFormatDefinition

+
struct GstFormatDefinition {
+  GstFormat    value;
+  const gchar *nick;
+  const gchar *description;
+  GQuark       quark;
+};
+
+

A format definition

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstFormat value;

The unique id of this format

 

const gchar *nick;

A short nick of the format

 

const gchar *description;

A longer description of the format

 

GQuark quark;

A quark for the nick

 
+
+
+
+
+

See Also

+

GstPad, GstElement

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstGError.html b/docs/gst/html/gstreamer-GstGError.html new file mode 100644 index 0000000..4b8b84c --- /dev/null +++ b/docs/gst/html/gstreamer-GstGError.html @@ -0,0 +1,728 @@ + + + + +GstError: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstError

+

GstError — Categorized error messages

+
+
+

Functions

+
++++ + + + + +
+gchar * + +gst_error_get_message () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
enumGstCoreError
enumGstLibraryError
enumGstResourceError
enumGstStreamError
#defineGST_CORE_ERROR
#defineGST_LIBRARY_ERROR
#defineGST_RESOURCE_ERROR
#defineGST_STREAM_ERROR
#defineGST_ERROR_SYSTEM
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GStreamer elements can throw non-fatal warnings and fatal errors. +Higher-level elements and applications can programmatically filter +the ones they are interested in or can recover from, +and have a default handler handle the rest of them.

+

The rest of this section will use the term error +to mean both (non-fatal) warnings and (fatal) errors; they are treated +similarly.

+

Errors from elements are the combination of a GError and a debug string. +The GError contains:

+
    +
  • a domain type: CORE, LIBRARY, RESOURCE or STREAM

  • +
  • a code: an enum value specific to the domain

  • +
  • a translated, human-readable message

  • +
  • a non-translated additional debug string, which also contains

  • +
  • file and line information

  • +
+

Elements do not have the context required to decide what to do with +errors. As such, they should only inform about errors, and stop their +processing. In short, an element doesn't know what it is being used for.

+

It is the application or compound element using the given element that +has more context about the use of the element. Errors can be received by +listening to the GstBus of the element/pipeline for GstMessage objects with +the type GST_MESSAGE_ERROR or GST_MESSAGE_WARNING. The thrown errors should +be inspected, and filtered if appropriate.

+

An application is expected to, by default, present the user with a +dialog box (or an equivalent) showing the error message. The dialog +should also allow a way to get at the additional debug information, +so the user can provide bug reporting information.

+

A compound element is expected to forward errors by default higher up +the hierarchy; this is done by default in the same way as for other types +of GstMessage.

+

When applications or compound elements trigger errors that they can +recover from, they can filter out these errors and take appropriate action. +For example, an application that gets an error from xvimagesink +that indicates all XVideo ports are taken, the application can attempt +to use another sink instead.

+

Elements throw errors using the GST_ELEMENT_ERROR convenience macro:

+
+

Throwing an error

+
+ + + + + + + +
1
+2
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
+  (_("No file name specified for reading.")), (NULL));
+
+ +

+

Things to keep in mind:

+
    +
  • Don't go off inventing new error codes. The ones +currently provided should be enough. If you find your type of error +does not fit the current codes, you should use FAILED.

  • +
  • Don't provide a message if the default one suffices. +this keeps messages more uniform. Use (NULL) - not forgetting the +parentheses.

  • +
  • If you do supply a custom message, it should be +marked for translation. The message should start with a capital +and end with a period. The message should describe the error in short, +in a human-readable form, and without any complex technical terms. +A user interface will present this message as the first thing a user +sees. Details, technical info, ... should go in the debug string.

  • +
  • The debug string can be as you like. Again, use (NULL) +if there's nothing to add - file and line number will still be +passed. GST_ERROR_SYSTEM can be used as a shortcut to give +debug information on a system call error.

  • +
+
+
+
+

Functions

+
+

gst_error_get_message ()

+
gchar *
+gst_error_get_message (GQuark domain,
+                       gint code);
+

Get a string describing the error message in the current locale.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

domain

the GStreamer error domain this error belongs to.

 

code

the error code belonging to the domain.

 
+
+
+

Returns

+

a newly allocated string describing +the error message (in UTF-8 encoding).

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

enum GstCoreError

+

Core errors are errors inside the core GStreamer library.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_CORE_ERROR_FAILED

+

a general error which doesn't fit in any other +category. Make sure you add a custom message to the error call.

+
 

GST_CORE_ERROR_TOO_LAZY

+

do not use this except as a placeholder for +deciding where to go while developing code.

+
 

GST_CORE_ERROR_NOT_IMPLEMENTED

+

use this when you do not want to implement +this functionality yet.

+
 

GST_CORE_ERROR_STATE_CHANGE

+

used for state change errors.

+
 

GST_CORE_ERROR_PAD

+

used for pad-related errors.

+
 

GST_CORE_ERROR_THREAD

+

used for thread-related errors.

+
 

GST_CORE_ERROR_NEGOTIATION

+

used for negotiation-related errors.

+
 

GST_CORE_ERROR_EVENT

+

used for event-related errors.

+
 

GST_CORE_ERROR_SEEK

+

used for seek-related errors.

+
 

GST_CORE_ERROR_CAPS

+

used for caps-related errors.

+
 

GST_CORE_ERROR_TAG

+

used for negotiation-related errors.

+
 

GST_CORE_ERROR_MISSING_PLUGIN

+

used if a plugin is missing.

+
 

GST_CORE_ERROR_CLOCK

+

used for clock related errors.

+
 

GST_CORE_ERROR_DISABLED

+

used if functionality has been disabled at + compile time.

+
 

GST_CORE_ERROR_NUM_ERRORS

+

the number of core error types.

+
 
+
+
+
+
+

enum GstLibraryError

+

Library errors are for errors from the library being used by elements +(initializing, finalizing, settings, ...)

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_LIBRARY_ERROR_FAILED

+

a general error which doesn't fit in any other +category. Make sure you add a custom message to the error call.

+
 

GST_LIBRARY_ERROR_TOO_LAZY

+

do not use this except as a placeholder for +deciding where to go while developing code.

+
 

GST_LIBRARY_ERROR_INIT

+

used when the library could not be opened.

+
 

GST_LIBRARY_ERROR_SHUTDOWN

+

used when the library could not be closed.

+
 

GST_LIBRARY_ERROR_SETTINGS

+

used when the library doesn't accept settings.

+
 

GST_LIBRARY_ERROR_ENCODE

+

used when the library generated an encoding error.

+
 

GST_LIBRARY_ERROR_NUM_ERRORS

+

the number of library error types.

+
 
+
+
+
+
+

enum GstResourceError

+

Resource errors are for any resource used by an element: +memory, files, network connections, process space, ... +They're typically used by source and sink elements.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_RESOURCE_ERROR_FAILED

+

a general error which doesn't fit in any other +category. Make sure you add a custom message to the error call.

+
 

GST_RESOURCE_ERROR_TOO_LAZY

+

do not use this except as a placeholder for +deciding where to go while developing code.

+
 

GST_RESOURCE_ERROR_NOT_FOUND

+

used when the resource could not be found.

+
 

GST_RESOURCE_ERROR_BUSY

+

used when resource is busy.

+
 

GST_RESOURCE_ERROR_OPEN_READ

+

used when resource fails to open for reading.

+
 

GST_RESOURCE_ERROR_OPEN_WRITE

+

used when resource fails to open for writing.

+
 

GST_RESOURCE_ERROR_OPEN_READ_WRITE

+

used when resource cannot be opened for +both reading and writing, or either (but unspecified which).

+
 

GST_RESOURCE_ERROR_CLOSE

+

used when the resource can't be closed.

+
 

GST_RESOURCE_ERROR_READ

+

used when the resource can't be read from.

+
 

GST_RESOURCE_ERROR_WRITE

+

used when the resource can't be written to.

+
 

GST_RESOURCE_ERROR_SEEK

+

used when a seek on the resource fails.

+
 

GST_RESOURCE_ERROR_SYNC

+

used when a synchronize on the resource fails.

+
 

GST_RESOURCE_ERROR_SETTINGS

+

used when settings can't be manipulated on.

+
 

GST_RESOURCE_ERROR_NO_SPACE_LEFT

+

used when the resource has no space left.

+
 

GST_RESOURCE_ERROR_NOT_AUTHORIZED

+

used when the resource can't be opened + due to missing authorization. + (Since 1.2.4)

+
 

GST_RESOURCE_ERROR_NUM_ERRORS

+

the number of resource error types.

+
 
+
+
+
+
+

enum GstStreamError

+

Stream errors are for anything related to the stream being processed: +format errors, media type errors, ... +They're typically used by decoders, demuxers, converters, ...

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_STREAM_ERROR_FAILED

+

a general error which doesn't fit in any other +category. Make sure you add a custom message to the error call.

+
 

GST_STREAM_ERROR_TOO_LAZY

+

do not use this except as a placeholder for +deciding where to go while developing code.

+
 

GST_STREAM_ERROR_NOT_IMPLEMENTED

+

use this when you do not want to implement +this functionality yet.

+
 

GST_STREAM_ERROR_TYPE_NOT_FOUND

+

used when the element doesn't know the +stream's type.

+
 

GST_STREAM_ERROR_WRONG_TYPE

+

used when the element doesn't handle this type +of stream.

+
 

GST_STREAM_ERROR_CODEC_NOT_FOUND

+

used when there's no codec to handle the +stream's type.

+
 

GST_STREAM_ERROR_DECODE

+

used when decoding fails.

+
 

GST_STREAM_ERROR_ENCODE

+

used when encoding fails.

+
 

GST_STREAM_ERROR_DEMUX

+

used when demuxing fails.

+
 

GST_STREAM_ERROR_MUX

+

used when muxing fails.

+
 

GST_STREAM_ERROR_FORMAT

+

used when the stream is of the wrong format +(for example, wrong caps).

+
 

GST_STREAM_ERROR_DECRYPT

+

used when the stream is encrypted and can't be +decrypted because this is not supported by the element.

+
 

GST_STREAM_ERROR_DECRYPT_NOKEY

+

used when the stream is encrypted and +can't be decrypted because no suitable key is available.

+
 

GST_STREAM_ERROR_NUM_ERRORS

+

the number of stream error types.

+
 
+
+
+
+
+

GST_CORE_ERROR

+
#define GST_CORE_ERROR      gst_core_error_quark ()
+
+

Error domain for core system. Errors in this domain will +be from the GstCoreError enumeration. +See GError for information on error domains.

+
+
+
+

GST_LIBRARY_ERROR

+
#define GST_LIBRARY_ERROR   gst_library_error_quark ()
+
+

Error domain for library loading. Errors in this domain will +be from the GstLibraryError enumeration. +See GError for information on error domains.

+
+
+
+

GST_RESOURCE_ERROR

+
#define GST_RESOURCE_ERROR  gst_resource_error_quark ()
+
+

Error domain for resource handling. Errors in this domain will +be from the GstResourceError enumeration. +See GError for information on error domains.

+
+
+
+

GST_STREAM_ERROR

+
#define GST_STREAM_ERROR    gst_stream_error_quark ()
+
+

Error domain for media stream processing. Errors in this domain will +be from the GstStreamError enumeration. +See GError for information on error domains.

+
+
+
+

GST_ERROR_SYSTEM

+
#define GST_ERROR_SYSTEM    ("system error: %s", g_strerror (errno))
+
+

Builds a string using errno describing the previously failed system +call. To be used as the debug argument in GST_ELEMENT_ERROR.

+
+
+
+

See Also

+

GstMessage

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstInfo.html b/docs/gst/html/gstreamer-GstInfo.html new file mode 100644 index 0000000..76881f5 --- /dev/null +++ b/docs/gst/html/gstreamer-GstInfo.html @@ -0,0 +1,4313 @@ + + + + +GstInfo: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstInfo

+

GstInfo — Debugging and logging facilities

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_STR_NULL() +
#define +GST_DEBUG_PAD_NAME() +
+void + +(*GstLogFunction) () +
+void + +gst_debug_log () +
+void + +gst_debug_log_valist () +
const gchar * + +gst_debug_message_get () +
+void + +gst_debug_log_default () +
const gchar * + +gst_debug_level_get_name () +
+void + +gst_debug_add_log_function () +
+guint + +gst_debug_remove_log_function () +
+guint + +gst_debug_remove_log_function_by_data () +
+void + +gst_debug_add_ring_buffer_logger () +
+void + +gst_debug_remove_ring_buffer_logger () +
+gchar ** + +gst_debug_ring_buffer_logger_get_logs () +
+void + +gst_debug_set_active () +
+gboolean + +gst_debug_is_active () +
+void + +gst_debug_set_colored () +
+void + +gst_debug_set_color_mode () +
+void + +gst_debug_set_color_mode_from_string () +
+gboolean + +gst_debug_is_colored () +
+GstDebugColorMode + +gst_debug_get_color_mode () +
+void + +gst_debug_set_default_threshold () +
+void + +gst_debug_set_threshold_from_string () +
+GstDebugLevel + +gst_debug_get_default_threshold () +
+void + +gst_debug_set_threshold_for_name () +
+void + +gst_debug_unset_threshold_for_name () +
#define +GST_DEBUG_CATEGORY() +
#define +GST_DEBUG_CATEGORY_EXTERN() +
#define +GST_DEBUG_CATEGORY_STATIC() +
#define +GST_DEBUG_CATEGORY_INIT() +
#define +GST_DEBUG_CATEGORY_GET() +
+void + +gst_debug_category_free () +
+void + +gst_debug_category_set_threshold () +
+void + +gst_debug_category_reset_threshold () +
+GstDebugLevel + +gst_debug_category_get_threshold () +
const gchar * + +gst_debug_category_get_name () +
+guint + +gst_debug_category_get_color () +
const gchar * + +gst_debug_category_get_description () +
+GSList * + +gst_debug_get_all_categories () +
+gchar * + +gst_debug_construct_term_color () +
+gint + +gst_debug_construct_win_color () +
#define +GST_CAT_LEVEL_LOG() +
#define +GST_CAT_ERROR_OBJECT() +
#define +GST_CAT_WARNING_OBJECT() +
#define +GST_CAT_INFO_OBJECT() +
#define +GST_CAT_DEBUG_OBJECT() +
#define +GST_CAT_LOG_OBJECT() +
#define +GST_CAT_FIXME_OBJECT() +
#define +GST_CAT_TRACE_OBJECT() +
#define +GST_CAT_MEMDUMP_OBJECT() +
#define +GST_CAT_ERROR() +
#define +GST_CAT_WARNING() +
#define +GST_CAT_INFO() +
#define +GST_CAT_DEBUG() +
#define +GST_CAT_LOG() +
#define +GST_CAT_FIXME() +
#define +GST_CAT_TRACE() +
#define +GST_CAT_MEMDUMP() +
#define +GST_ERROR_OBJECT() +
#define +GST_WARNING_OBJECT() +
#define +GST_INFO_OBJECT() +
#define +GST_DEBUG_OBJECT() +
#define +GST_LOG_OBJECT() +
#define +GST_FIXME_OBJECT() +
#define +GST_TRACE_OBJECT() +
#define +GST_MEMDUMP_OBJECT() +
#define +GST_ERROR() +
#define +GST_WARNING() +
#define +GST_INFO() +
#define +GST_DEBUG() +
#define +GST_LOG() +
#define +GST_FIXME() +
#define +GST_TRACE() +
#define +GST_MEMDUMP() +
#define +GST_DEBUG_REGISTER_FUNCPTR() +
#define +GST_DEBUG_FUNCPTR() +
#define +GST_DEBUG_FUNCPTR_NAME() +
#define +GST_DEBUG_BIN_TO_DOT_FILE() +
#define +GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS() +
+void + +gst_debug_print_stack_trace () +
+gchar * + +gst_debug_get_stack_trace () +
#define +GST_TIME_ARGS() +
#define +GST_STIME_ARGS() +
+gchar * + +gst_debug_bin_to_dot_data () +
+void + +gst_debug_bin_to_dot_file () +
+void + +gst_debug_bin_to_dot_file_with_ts () +
+gint + +gst_info_vasprintf () +
+gchar * + +gst_info_strdup_vprintf () +
+gchar * + +gst_info_strdup_printf () +
+void + +gst_print () +
+void + +gst_println () +
+void + +gst_printerr () +
+void + +gst_printerrln () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
enumGstDebugLevel
#defineGST_LEVEL_DEFAULT
#defineGST_LEVEL_MAX
enumGstDebugColorFlags
enumGstDebugColorMode
structGstDebugCategory
enumGstDebugGraphDetails
#defineGST_FUNCTION
enumGstStackTraceFlags
externGST_CAT_DEFAULT
#defineGST_TIME_FORMAT
#defineGST_STIME_FORMAT
#defineGST_PTR_FORMAT
#defineGST_SEGMENT_FORMAT
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GStreamer's debugging subsystem is an easy way to get information about what +the application is doing. It is not meant for programming errors. Use GLib +methods (g_warning and friends) for that.

+

The debugging subsystem works only after GStreamer has been initialized

+
+

The debugging subsystem is used to log informational messages while the +application runs. Each messages has some properties attached to it. Among +these properties are the debugging category, the severity (called "level" +here) and an optional GObject it belongs to. Each of these messages is sent +to all registered debugging handlers, which then handle the messages. +GStreamer attaches a default handler on startup, which outputs requested +messages to stderr.

+

Messages are output by using shortcut macros like GST_DEBUG, +GST_CAT_ERROR_OBJECT or similar. These all expand to calling gst_debug_log() +with the right parameters. +The only thing a developer will probably want to do is define his own +categories. This is easily done with 3 lines. At the top of your code, +declare +the variables and set the default category.

+
+ + + + + + + +
1
+2
GST_DEBUG_CATEGORY_STATIC (my_category);  // define category (statically)
+#define GST_CAT_DEFAULT my_category       // set as default
+
+ +

+After that you only need to initialize the category.

+
+ + + + + + + +
1
+2
GST_DEBUG_CATEGORY_INIT (my_category, "my category",
+                         0, "This is my very own");
+
+ +

+Initialization must be done before the category is used first. +Plugins do this +in their plugin_init function, libraries and applications should do that +during their initialization.

+

The whole debugging subsystem can be disabled at build time with passing the +--disable-gst-debug switch to configure. If this is done, every function, +macro and even structs described in this file evaluate to default values or +nothing at all. +So don't take addresses of these functions or use other tricks. +If you must do that for some reason, there is still an option. +If the debugging +subsystem was compiled out, GST_DISABLE_GST_DEBUG is defined in +<gst/gst.h>, +so you can check that before doing your trick. +Disabling the debugging subsystem will give you a slight (read: unnoticeable) +speed increase and will reduce the size of your compiled code. The GStreamer +library itself becomes around 10% smaller.

+

Please note that there are naming conventions for the names of debugging +categories. These are explained at GST_DEBUG_CATEGORY_INIT().

+
+
+

Functions

+
+

GST_STR_NULL()

+
#define GST_STR_NULL(str) ((str) ? (str) : "(NULL)")
+
+

Macro to use when a string must not be NULL, but may be NULL. If the string +is NULL, "(NULL)" is printed instead. +In GStreamer printf string arguments may not be NULL, because on some +platforms (ie Solaris) the libc crashes in that case. This includes debugging +strings.

+
+

Parameters

+
+++++ + + + + + +

str

The string to check.

[allow-none]
+
+
+
+
+

GST_DEBUG_PAD_NAME()

+
#define             GST_DEBUG_PAD_NAME(pad)
+

Evaluates to 2 strings, that describe the pad. Often used in debugging +statements.

+
+

Parameters

+
+++++ + + + + + +

pad

The pad to debug.

 
+
+
+
+
+

GstLogFunction ()

+
void
+(*GstLogFunction) (GstDebugCategory *category,
+                   GstDebugLevel level,
+                   const gchar *file,
+                   const gchar *function,
+                   gint line,
+                   GObject *object,
+                   GstDebugMessage *message,
+                   gpointer user_data);
+

Function prototype for a logging function that can be registered with +gst_debug_add_log_function(). +Use G_GNUC_NO_INSTRUMENT on that function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

category

a GstDebugCategory

 

level

a GstDebugLevel

 

file

file name

 

function

function name

 

line

line number

 

object

a GObject

 

message

the message

 

user_data

user data for the log function

 
+
+
+
+
+

gst_debug_log ()

+
void
+gst_debug_log (GstDebugCategory *category,
+               GstDebugLevel level,
+               const gchar *file,
+               const gchar *function,
+               gint line,
+               GObject *object,
+               const gchar *format,
+               ...);
+

Logs the given message using the currently registered debugging handlers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

category

category to log

 

level

level of the message is in

 

file

the file that emitted the message, usually the __FILE__ identifier

 

function

the function that emitted the message

 

line

the line from that the message was emitted, usually __LINE__

 

object

the object this message relates to, +or NULL if none.

[transfer none][allow-none]

format

a printf style format string

 

...

optional arguments for the format

 
+
+
+
+
+

gst_debug_log_valist ()

+
void
+gst_debug_log_valist (GstDebugCategory *category,
+                      GstDebugLevel level,
+                      const gchar *file,
+                      const gchar *function,
+                      gint line,
+                      GObject *object,
+                      const gchar *format,
+                      va_list args);
+

Logs the given message using the currently registered debugging handlers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

category

category to log

 

level

level of the message is in

 

file

the file that emitted the message, usually the __FILE__ identifier

 

function

the function that emitted the message

 

line

the line from that the message was emitted, usually __LINE__

 

object

the object this message relates to, +or NULL if none.

[transfer none][allow-none]

format

a printf style format string

 

args

optional arguments for the format

 
+
+
+
+
+

gst_debug_message_get ()

+
const gchar *
+gst_debug_message_get (GstDebugMessage *message);
+

Gets the string representation of a GstDebugMessage. This function is used +in debug handlers to extract the message.

+
+

Parameters

+
+++++ + + + + + +

message

a debug message

 
+
+
+

Returns

+

the string representation of a GstDebugMessage.

+

[nullable]

+
+
+
+
+

gst_debug_log_default ()

+
void
+gst_debug_log_default (GstDebugCategory *category,
+                       GstDebugLevel level,
+                       const gchar *file,
+                       const gchar *function,
+                       gint line,
+                       GObject *object,
+                       GstDebugMessage *message,
+                       gpointer user_data);
+

The default logging handler used by GStreamer. Logging functions get called +whenever a macro like GST_DEBUG or similar is used. By default this function +is setup to output the message and additional info to stderr (or the log file +specified via the GST_DEBUG_FILE environment variable) as received via +user_data +.

+

You can add other handlers by using gst_debug_add_log_function(). +And you can remove this handler by calling +gst_debug_remove_log_function(gst_debug_log_default);

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

category

category to log

 

level

level of the message

 

file

the file that emitted the message, usually the __FILE__ identifier

 

function

the function that emitted the message

 

line

the line from that the message was emitted, usually __LINE__

 

message

the actual message

 

object

the object this message relates to, +or NULL if none.

[transfer none][allow-none]

user_data

the FILE* to log to

 
+
+
+
+
+

gst_debug_level_get_name ()

+
const gchar *
+gst_debug_level_get_name (GstDebugLevel level);
+

Get the string representation of a debugging level

+
+

Parameters

+
+++++ + + + + + +

level

the level to get the name for

 
+
+
+

Returns

+

the name

+
+
+
+
+

gst_debug_add_log_function ()

+
void
+gst_debug_add_log_function (GstLogFunction func,
+                            gpointer user_data,
+                            GDestroyNotify notify);
+

Adds the logging function to the list of logging functions. +Be sure to use G_GNUC_NO_INSTRUMENT on that function, it is needed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

func

the function to use

 

user_data

user data

 

notify

called when user_data +is not used anymore

 
+
+
+
+
+

gst_debug_remove_log_function ()

+
guint
+gst_debug_remove_log_function (GstLogFunction func);
+

Removes all registered instances of the given logging functions.

+
+

Parameters

+
+++++ + + + + + +

func

the log function to remove, or NULL to +remove the default log function.

[scope call][allow-none]
+
+
+

Returns

+

How many instances of the function were removed

+
+
+
+
+

gst_debug_remove_log_function_by_data ()

+
guint
+gst_debug_remove_log_function_by_data (gpointer data);
+

Removes all registered instances of log functions with the given user data.

+
+

Parameters

+
+++++ + + + + + +

data

user data of the log function to remove

 
+
+
+

Returns

+

How many instances of the function were removed

+
+
+
+
+

gst_debug_add_ring_buffer_logger ()

+
void
+gst_debug_add_ring_buffer_logger (guint max_size_per_thread,
+                                  guint thread_timeout);
+

Adds a memory ringbuffer based debug logger that stores up to +max_size_per_thread + bytes of logs per thread and times out threads after +thread_timeout + seconds of inactivity.

+

Logs can be fetched with gst_debug_ring_buffer_logger_get_logs() and the +logger can be removed again with gst_debug_remove_ring_buffer_logger(). +Only one logger at a time is possible.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

max_size_per_thread

Maximum size of log per thread in bytes

 

thread_timeout

Timeout for threads in seconds

 
+
+

Since: 1.14

+
+
+
+

gst_debug_remove_ring_buffer_logger ()

+
void
+gst_debug_remove_ring_buffer_logger (void);
+

Removes any previously added ring buffer logger with +gst_debug_add_ring_buffer_logger().

+

Since: 1.14

+
+
+
+

gst_debug_ring_buffer_logger_get_logs ()

+
gchar **
+gst_debug_ring_buffer_logger_get_logs (void);
+

Fetches the current logs per thread from the ring buffer logger. See +gst_debug_add_ring_buffer_logger() for details.

+
+

Returns

+

NULL-terminated array of +strings with the debug output per thread.

+

[transfer full][array zero-terminated]

+
+

Since: 1.14

+
+
+
+

gst_debug_set_active ()

+
void
+gst_debug_set_active (gboolean active);
+

If activated, debugging messages are sent to the debugging +handlers. +It makes sense to deactivate it for speed issues.

+

This function is not threadsafe. It makes sense to only call it +during initialization.

+
+

Parameters

+
+++++ + + + + + +

active

Whether to use debugging output or not

 
+
+
+
+
+

gst_debug_is_active ()

+
gboolean
+gst_debug_is_active (void);
+

Checks if debugging output is activated.

+
+

Returns

+

TRUE, if debugging is activated

+
+
+
+
+

gst_debug_set_colored ()

+
void
+gst_debug_set_colored (gboolean colored);
+

Sets or unsets the use of coloured debugging output. +Same as gst_debug_set_color_mode() with the argument being +being GST_DEBUG_COLOR_MODE_ON or GST_DEBUG_COLOR_MODE_OFF.

+

This function may be called before gst_init().

+
+

Parameters

+
+++++ + + + + + +

colored

Whether to use colored output or not

 
+
+
+
+
+

gst_debug_set_color_mode ()

+
void
+gst_debug_set_color_mode (GstDebugColorMode mode);
+

Changes the coloring mode for debug output.

+

This function may be called before gst_init().

+
+

Parameters

+
+++++ + + + + + +

mode

The coloring mode for debug output. See GstDebugColorMode +.

 
+
+

Since: 1.2

+
+
+
+

gst_debug_set_color_mode_from_string ()

+
void
+gst_debug_set_color_mode_from_string (const gchar *mode);
+

Changes the coloring mode for debug output.

+

This function may be called before gst_init().

+
+

Parameters

+
+++++ + + + + + +

mode

The coloring mode for debug output. One of the following: +"on", "auto", "off", "disable", "unix".

 
+
+

Since: 1.2

+
+
+
+

gst_debug_is_colored ()

+
gboolean
+gst_debug_is_colored (void);
+

Checks if the debugging output should be colored.

+
+

Returns

+

TRUE, if the debug output should be colored.

+
+
+
+
+

gst_debug_get_color_mode ()

+
GstDebugColorMode
+gst_debug_get_color_mode (void);
+

Changes the coloring mode for debug output.

+
+

Returns

+

see GstDebugColorMode +for possible values.

+
+

Since: 1.2

+
+
+
+

gst_debug_set_default_threshold ()

+
void
+gst_debug_set_default_threshold (GstDebugLevel level);
+

Sets the default threshold to the given level and updates all categories to +use this threshold.

+

This function may be called before gst_init().

+
+

Parameters

+
+++++ + + + + + +

level

level to set

 
+
+
+
+
+

gst_debug_set_threshold_from_string ()

+
void
+gst_debug_set_threshold_from_string (const gchar *list,
+                                     gboolean reset);
+

Sets the debug logging wanted in the same form as with the GST_DEBUG +environment variable. You can use wildcards such as '*', but note that +the order matters when you use wild cards, e.g. "foosrc:6,*src:3,*:2" sets +everything to log level 2.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

list

comma-separated list of "category:level" pairs to be used +as debug logging levels

 

reset

TRUE to clear all previously-set debug levels before setting +new thresholds +FALSE if adding the threshold described by list +to the one already set.

 
+
+

Since: 1.2

+
+
+
+

gst_debug_get_default_threshold ()

+
GstDebugLevel
+gst_debug_get_default_threshold (void);
+

Returns the default threshold that is used for new categories.

+
+

Returns

+

the default threshold level

+
+
+
+
+

gst_debug_set_threshold_for_name ()

+
void
+gst_debug_set_threshold_for_name (const gchar *name,
+                                  GstDebugLevel level);
+

Sets all categories which match the given glob style pattern to the given +level.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

name of the categories to set

 

level

level to set them to

 
+
+
+
+
+

gst_debug_unset_threshold_for_name ()

+
void
+gst_debug_unset_threshold_for_name (const gchar *name);
+

Resets all categories with the given name back to the default level.

+
+

Parameters

+
+++++ + + + + + +

name

name of the categories to set

 
+
+
+
+
+

GST_DEBUG_CATEGORY()

+
#define GST_DEBUG_CATEGORY(cat) GstDebugCategory *cat = NULL
+
+

Defines a GstDebugCategory variable. +This macro expands to nothing if debugging is disabled.

+
+

Parameters

+
+++++ + + + + + +

cat

the category

 
+
+
+
+
+

GST_DEBUG_CATEGORY_EXTERN()

+
#define GST_DEBUG_CATEGORY_EXTERN(cat) extern GstDebugCategory *cat
+
+

Declares a GstDebugCategory variable as extern. Use in header files. +This macro expands to nothing if debugging is disabled.

+
+

Parameters

+
+++++ + + + + + +

cat

the category

 
+
+
+
+
+

GST_DEBUG_CATEGORY_STATIC()

+
#define GST_DEBUG_CATEGORY_STATIC(cat) static GstDebugCategory *cat = NULL
+
+

Defines a static GstDebugCategory variable. +This macro expands to nothing if debugging is disabled.

+
+

Parameters

+
+++++ + + + + + +

cat

the category

 
+
+
+
+
+

GST_DEBUG_CATEGORY_INIT()

+
#define             GST_DEBUG_CATEGORY_INIT(cat,name,color,description)
+

Initializes a new GstDebugCategory with the given properties and set to +the default threshold.

+
+

This macro expands to nothing if debugging is disabled.

+

When naming your category, please follow the following conventions to ensure +that the pattern matching for categories works as expected. It is not +earth-shattering if you don't follow these conventions, but it would be nice +for everyone.

+

If you define a category for a plugin or a feature of it, name the category +like the feature. So if you wanted to write a "filesrc" element, you would +name the category "filesrc". Use lowercase letters only. +If you define more than one category for the same element, append an +underscore and an identifier to your categories, like this: "filesrc_cache"

+

If you create a library or an application using debugging categories, use a +common prefix followed by an underscore for all your categories. GStreamer +uses the GST prefix so GStreamer categories look like "GST_STATES". Be sure +to include uppercase letters.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

cat

the category to initialize.

 

name

the name of the category.

 

color

the colors to use for a color representation or 0 for no color.

 

description

optional description of the category.

 
+
+
+
+
+

GST_DEBUG_CATEGORY_GET()

+
#define             GST_DEBUG_CATEGORY_GET(cat,name)
+

Looks up an existing GstDebugCategory by its name + and sets cat +. If the +category is not found, but GST_CAT_DEFAULT is defined, that is assigned to +cat +. Otherwise cat + will be NULL.

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
GST_DEBUG_CATEGORY_STATIC (gst_myplugin_debug);
+#define GST_CAT_DEFAULT gst_myplugin_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
+...
+GST_DEBUG_CATEGORY_INIT (gst_myplugin_debug, "myplugin", 0, "nice element");
+GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
+ +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

the category to initialize.

 

name

log category name

 
+
+
+
+
+

gst_debug_category_free ()

+
void
+gst_debug_category_free (GstDebugCategory *category);
+

Removes and frees the category and all associated resources.

+
+

Parameters

+
+++++ + + + + + +

category

GstDebugCategory to free.

 
+
+
+
+
+

gst_debug_category_set_threshold ()

+
void
+gst_debug_category_set_threshold (GstDebugCategory *category,
+                                  GstDebugLevel level);
+

Sets the threshold of the category to the given level. Debug information will +only be output if the threshold is lower or equal to the level of the +debugging message.

+

Do not use this function in production code, because other functions may +change the threshold of categories as side effect. It is however a nice +function to use when debugging (even from gdb).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

category

a GstDebugCategory to set threshold of.

 

level

the GstDebugLevel threshold to set.

 
+
+
+
+
+

gst_debug_category_reset_threshold ()

+
void
+gst_debug_category_reset_threshold (GstDebugCategory *category);
+

Resets the threshold of the category to the default level. Debug information +will only be output if the threshold is lower or equal to the level of the +debugging message. +Use this function to set the threshold back to where it was after using +gst_debug_category_set_threshold().

+
+

Parameters

+
+++++ + + + + + +

category

a GstDebugCategory to reset threshold of.

 
+
+
+
+
+

gst_debug_category_get_threshold ()

+
GstDebugLevel
+gst_debug_category_get_threshold (GstDebugCategory *category);
+

Returns the threshold of a GstDebugCategory.

+
+

Parameters

+
+++++ + + + + + +

category

a GstDebugCategory to get threshold of.

 
+
+
+

Returns

+

the GstDebugLevel that is used as threshold.

+
+
+
+
+

gst_debug_category_get_name ()

+
const gchar *
+gst_debug_category_get_name (GstDebugCategory *category);
+

Returns the name of a debug category.

+
+

Parameters

+
+++++ + + + + + +

category

a GstDebugCategory to get name of.

 
+
+
+

Returns

+

the name of the category.

+
+
+
+
+

gst_debug_category_get_color ()

+
guint
+gst_debug_category_get_color (GstDebugCategory *category);
+

Returns the color of a debug category used when printing output in this +category.

+
+

Parameters

+
+++++ + + + + + +

category

a GstDebugCategory to get the color of.

 
+
+
+

Returns

+

the color of the category.

+
+
+
+
+

gst_debug_category_get_description ()

+
const gchar *
+gst_debug_category_get_description (GstDebugCategory *category);
+

Returns the description of a debug category.

+
+

Parameters

+
+++++ + + + + + +

category

a GstDebugCategory to get the description of.

 
+
+
+

Returns

+

the description of the category.

+
+
+
+
+

gst_debug_get_all_categories ()

+
GSList *
+gst_debug_get_all_categories (void);
+

Returns a snapshot of a all categories that are currently in use . This list +may change anytime. +The caller has to free the list after use.

+
+

Returns

+

the list of +debug categories.

+

[transfer container][element-type Gst.DebugCategory]

+
+
+
+
+

gst_debug_construct_term_color ()

+
gchar *
+gst_debug_construct_term_color (guint colorinfo);
+

Constructs a string that can be used for getting the desired color in color +terminals. +You need to free the string after use.

+
+

Parameters

+
+++++ + + + + + +

colorinfo

the color info

 
+
+
+

Returns

+

a string containing the color +definition.

+

[transfer full][type gchar*]

+
+
+
+
+

gst_debug_construct_win_color ()

+
gint
+gst_debug_construct_win_color (guint colorinfo);
+

Constructs an integer that can be used for getting the desired color in +windows' terminals (cmd.exe). As there is no mean to underline, we simply +ignore this attribute.

+

This function returns 0 on non-windows machines.

+
+

Parameters

+
+++++ + + + + + +

colorinfo

the color info

 
+
+
+

Returns

+

an integer containing the color definition

+
+
+
+
+

GST_CAT_LEVEL_LOG()

+
#define             GST_CAT_LEVEL_LOG(cat,level,object,...)
+

Outputs a debugging message. This is the most general macro for outputting +debugging messages. You will probably want to use one of the ones described +below.

+

There is no need to finish the end of the debug message with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

cat

category to use

 

level

the severity of the message

 

object

the GObject the message belongs to or NULL if none.

[allow-none]

...

A printf-style message to output

 
+
+
+
+
+

GST_CAT_ERROR_OBJECT()

+
#define GST_CAT_ERROR_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR,   obj,  __VA_ARGS__)
+
+

Output an error message belonging to the given object in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_WARNING_OBJECT()

+
#define GST_CAT_WARNING_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, obj,  __VA_ARGS__)
+
+

Output a warning message belonging to the given object in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_INFO_OBJECT()

+
#define GST_CAT_INFO_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    obj,  __VA_ARGS__)
+
+

Output an informational message belonging to the given object in the given +category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_DEBUG_OBJECT()

+
#define GST_CAT_DEBUG_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   obj,  __VA_ARGS__)
+
+

Output an debugging message belonging to the given object in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_LOG_OBJECT()

+
#define GST_CAT_LOG_OBJECT(cat,obj,...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     obj,  __VA_ARGS__)
+
+

Output an logging message belonging to the given object in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_FIXME_OBJECT()

+
#define GST_CAT_FIXME_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   obj,  __VA_ARGS__)
+
+

Output a fixme message belonging to the given object in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_TRACE_OBJECT()

+
#define GST_CAT_TRACE_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE,   obj,  __VA_ARGS__)
+
+

Output a tracing message belonging to the given object in the given +category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_MEMDUMP_OBJECT()

+
#define             GST_CAT_MEMDUMP_OBJECT(cat,obj,msg,data,length)
+

Output a hexdump of data + relating to the given object in the given +category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cat

category to use

 

obj

the GObject the message belongs to

 

msg

message string to log with the data

 

data

pointer to the data to output

 

length

length of the data to output

 
+
+
+
+
+

GST_CAT_ERROR()

+
#define GST_CAT_ERROR(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR,   NULL, __VA_ARGS__)
+
+

Output an error message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_WARNING()

+
#define GST_CAT_WARNING(cat,...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, NULL, __VA_ARGS__)
+
+

Output an warning message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_INFO()

+
#define GST_CAT_INFO(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO,    NULL, __VA_ARGS__)
+
+

Output an informational message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_DEBUG()

+
#define GST_CAT_DEBUG(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG,   NULL, __VA_ARGS__)
+
+

Output an debugging message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_LOG()

+
#define GST_CAT_LOG(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG,     NULL, __VA_ARGS__)
+
+

Output an logging message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_FIXME()

+
#define GST_CAT_FIXME(cat,...)			GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME,   NULL, __VA_ARGS__)
+
+

Output an fixme message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_TRACE()

+
#define GST_CAT_TRACE(cat,...)		GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE,   NULL, __VA_ARGS__)
+
+

Output a tracing message in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cat

category to use

 

...

printf-style message to output

 
+
+
+
+
+

GST_CAT_MEMDUMP()

+
#define             GST_CAT_MEMDUMP(cat,msg,data,length)
+

Output a hexdump of data + in the given category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

cat

category to use

 

msg

message string to log with the data

 

data

pointer to the data to output

 

length

length of the data to output

 
+
+
+
+
+

GST_ERROR_OBJECT()

+
#define GST_ERROR_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   obj,  __VA_ARGS__)
+
+

Output an error message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_WARNING_OBJECT()

+
#define GST_WARNING_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj,  __VA_ARGS__)
+
+

Output a warning message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_INFO_OBJECT()

+
#define GST_INFO_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    obj,  __VA_ARGS__)
+
+

Output an informational message belonging to the given object in the default +category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_DEBUG_OBJECT()

+
#define GST_DEBUG_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   obj,  __VA_ARGS__)
+
+

Output a debugging message belonging to the given object in the default +category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_LOG_OBJECT()

+
#define GST_LOG_OBJECT(obj,...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     obj,  __VA_ARGS__)
+
+

Output a logging message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_FIXME_OBJECT()

+
#define GST_FIXME_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   obj,  __VA_ARGS__)
+
+

Output a fixme message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_TRACE_OBJECT()

+
#define GST_TRACE_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE,   obj,  __VA_ARGS__)
+
+

Output a tracing message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

...

printf-style message to output

 
+
+
+
+
+

GST_MEMDUMP_OBJECT()

+
#define             GST_MEMDUMP_OBJECT(obj,msg,data,length)
+

Output a logging message belonging to the given object in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

obj

the GObject the message belongs to

 

msg

message string to log with the data

 

data

pointer to the data to output

 

length

length of the data to output

 
+
+
+
+
+

GST_ERROR()

+
#define GST_ERROR(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR,   NULL, __VA_ARGS__)
+
+

Output an error message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_WARNING()

+
#define GST_WARNING(...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, __VA_ARGS__)
+
+

Output a warning message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_INFO()

+
#define GST_INFO(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO,    NULL, __VA_ARGS__)
+
+

Output an informational message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_DEBUG()

+
#define GST_DEBUG(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG,   NULL, __VA_ARGS__)
+
+

Output a debugging message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_LOG()

+
#define GST_LOG(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG,     NULL, __VA_ARGS__)
+
+

Output a logging message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_FIXME()

+
#define GST_FIXME(...)			GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME,   NULL, __VA_ARGS__)
+
+

Output a fixme message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_TRACE()

+
#define GST_TRACE(...)		GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE,   NULL, __VA_ARGS__)
+
+

Output a tracing message in the default category.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + +

...

printf-style message to output

 
+
+
+
+
+

GST_MEMDUMP()

+
#define             GST_MEMDUMP(msg,data,length)
+

Output a hexdump of data +.

+

There is no need to finish the end of the message string with a newline +character, a newline character will be added automatically.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

msg

message string to log with the data

 

data

pointer to the data to output

 

length

length of the data to output

 
+
+
+
+
+

GST_DEBUG_REGISTER_FUNCPTR()

+
#define             GST_DEBUG_REGISTER_FUNCPTR(ptr)
+

Register a pointer to a function with its name, so it can later be used by +GST_DEBUG_FUNCPTR_NAME().

+

Use this variant of GST_DEBUG_FUNCPTR if you do not need to use ptr +.

+
+

Parameters

+
+++++ + + + + + +

ptr

pointer to the function to register

 
+
+
+
+
+

GST_DEBUG_FUNCPTR()

+
#define             GST_DEBUG_FUNCPTR(ptr)
+

Register a pointer to a function with its name, so it can later be used by +GST_DEBUG_FUNCPTR_NAME().

+
+

Parameters

+
+++++ + + + + + +

ptr

pointer to the function to register

 
+
+
+

Returns

+

the value passed to ptr +.

+
+
+
+
+

GST_DEBUG_FUNCPTR_NAME()

+
#define             GST_DEBUG_FUNCPTR_NAME(ptr)
+

Retrieves the name of the function, if it was previously registered with +GST_DEBUG_FUNCPTR(). If not, it returns a description of the pointer.

+

This macro returns a constant string which must not be modified or +freed by the caller.

+
+

Parameters

+
+++++ + + + + + +

ptr

address of the function of which to look up the name

 
+
+
+
+
+

GST_DEBUG_BIN_TO_DOT_FILE()

+
#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) gst_debug_bin_to_dot_file (bin, details, file_name)
+
+

To aid debugging applications one can use this method to write out the whole +network of gstreamer elements that form the pipeline into an dot file. +This file can be processed with graphviz to get an image, like this:

+
+ + + + + + + +
1
dot -Tpng -oimage.png graph_lowlevel.dot
+
+ +

+There is also a utility called xdot which allows you to view the dot file +directly without converting it first.

+

The macro is only active if gstreamer is configured with +"--gst-enable-gst-debug" and the environment variable +GST_DEBUG_DUMP_DOT_DIR is set to a basepath (e.g. /tmp).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

the top-level pipeline that should be analyzed

 

details

details to show in the graph, e.g. GST_DEBUG_GRAPH_SHOW_ALL or +one or more other GstDebugGraphDetails flags.

 

file_name

output base filename (e.g. "myplayer")

 
+
+
+
+
+

GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS()

+
#define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) gst_debug_bin_to_dot_file_with_ts (bin, details, file_name)
+
+

This works like GST_DEBUG_BIN_TO_DOT_FILE(), but adds the current timestamp +to the filename, so that it can be used to take multiple snapshots.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin

the top-level pipeline that should be analyzed

 

details

details to show in the graph, e.g. GST_DEBUG_GRAPH_SHOW_ALL or +one or more other GstDebugGraphDetails flags.

 

file_name

output base filename (e.g. "myplayer")

 
+
+
+
+
+

gst_debug_print_stack_trace ()

+
void
+gst_debug_print_stack_trace (void);
+

If libunwind or glibc backtrace are present +a stack trace is printed.

+
+
+
+

gst_debug_get_stack_trace ()

+
gchar *
+gst_debug_get_stack_trace (GstStackTraceFlags flags);
+
+

Parameters

+
+++++ + + + + + +

flags

A set of GstStackTraceFlags to determine how the stack +trace should look like. Pass 0 to retrieve a minimal backtrace.

 
+
+
+

Returns

+

a stack trace, if libunwind or glibc backtrace are +present, else NULL.

+

[nullable]

+
+

Since: 1.12

+
+
+
+

GST_TIME_ARGS()

+
#define             GST_TIME_ARGS(t)
+

Format t + for the GST_TIME_FORMAT format string. Note: t + will be +evaluated more than once.

+
+

Parameters

+
+++++ + + + + + +

t

a GstClockTime

 
+
+
+
+
+

GST_STIME_ARGS()

+
#define             GST_STIME_ARGS(t)
+

Format t + for the GST_STIME_FORMAT format string. Note: t + will be +evaluated more than once.

+
+

Parameters

+
+++++ + + + + + +

t

a GstClockTimeDiff or gint64

 
+
+

Since: 1.6

+
+
+
+

gst_debug_bin_to_dot_data ()

+
gchar *
+gst_debug_bin_to_dot_data (GstBin *bin,
+                           GstDebugGraphDetails details);
+

To aid debugging applications one can use this method to obtain the whole +network of gstreamer elements that form the pipeline into an dot file. +This data can be processed with graphviz to get an image.

+
+

Parameters

+
+++++ + + + + + +

bin

the top-level pipeline that should be analyzed

 
+
+
+

Returns

+

a string containing the pipeline in graphviz +dot format.

+

[transfer full]

+
+
+
+
+

gst_debug_bin_to_dot_file ()

+
void
+gst_debug_bin_to_dot_file (GstBin *bin,
+                           GstDebugGraphDetails details,
+                           const gchar *file_name);
+

To aid debugging applications one can use this method to write out the whole +network of gstreamer elements that form the pipeline into an dot file. +This file can be processed with graphviz to get an image.

+
+ + + + + + + +
1
dot -Tpng -oimage.png graph_lowlevel.dot
+
+ +
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the top-level pipeline that should be analyzed

 

file_name

output base filename (e.g. "myplayer").

[type filename]
+
+
+
+
+

gst_debug_bin_to_dot_file_with_ts ()

+
void
+gst_debug_bin_to_dot_file_with_ts (GstBin *bin,
+                                   GstDebugGraphDetails details,
+                                   const gchar *file_name);
+

This works like gst_debug_bin_to_dot_file(), but adds the current timestamp +to the filename, so that it can be used to take multiple snapshots.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the top-level pipeline that should be analyzed

 

file_name

output base filename (e.g. "myplayer").

[type filename]
+
+
+
+
+

gst_info_vasprintf ()

+
gint
+gst_info_vasprintf (gchar **result,
+                    const gchar *format,
+                    va_list args);
+

Allocates and fills a string large enough (including the terminating null +byte) to hold the specified printf style format + and args +.

+

This function deals with the GStreamer specific printf specifiers +GST_PTR_FORMAT and GST_SEGMENT_FORMAT. If you do not have these specifiers +in your format + string, you do not need to use this function and can use +alternatives such as g_vasprintf().

+

Free result + with g_free().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

result

the resulting string.

[out]

format

a printf style format string

 

args

the va_list of printf arguments for format +

 
+
+
+

Returns

+

the length of the string allocated into result +or -1 on any error

+
+

Since: 1.8

+
+
+
+

gst_info_strdup_vprintf ()

+
gchar *
+gst_info_strdup_vprintf (const gchar *format,
+                         va_list args);
+

Allocates, fills and returns a null terminated string from the printf style +format + string and args +.

+

See gst_info_vasprintf() for when this function is required.

+

Free with g_free().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

args

the va_list of printf arguments for format +

 
+
+
+

Returns

+

a newly allocated null terminated string or NULL on any error.

+

[nullable]

+
+

Since: 1.8

+
+
+
+

gst_info_strdup_printf ()

+
gchar *
+gst_info_strdup_printf (const gchar *format,
+                        ...);
+

Allocates, fills and returns a 0-terminated string from the printf style +format + string and corresponding arguments.

+

See gst_info_vasprintf() for when this function is required.

+

Free with g_free().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

...

the printf arguments for format +

 
+
+
+

Returns

+

a newly allocated null terminated string or NULL on any error.

+

[nullable]

+
+

Since: 1.8

+
+
+
+

gst_print ()

+
void
+gst_print (const gchar *format,
+           ...);
+

Outputs a formatted message via the GLib print handler. The default print +handler simply outputs the message to stdout.

+

This function will not append a new-line character at the end, unlike +gst_println() which will.

+

All strings must be in ASCII or UTF-8 encoding.

+

This function differs from g_print() in that it supports all the additional +printf specifiers that are supported by GStreamer's debug logging system, +such as GST_PTR_FORMAT and GST_SEGMENT_FORMAT.

+

This function is primarily for printing debug output.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

...

the printf arguments for format +

 
+
+

Since: 1.12

+
+
+
+

gst_println ()

+
void
+gst_println (const gchar *format,
+             ...);
+

Outputs a formatted message via the GLib print handler. The default print +handler simply outputs the message to stdout.

+

This function will append a new-line character at the end, unlike +gst_print() which will not.

+

All strings must be in ASCII or UTF-8 encoding.

+

This function differs from g_print() in that it supports all the additional +printf specifiers that are supported by GStreamer's debug logging system, +such as GST_PTR_FORMAT and GST_SEGMENT_FORMAT.

+

This function is primarily for printing debug output.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

...

the printf arguments for format +

 
+
+

Since: 1.12

+
+
+
+

gst_printerr ()

+
void
+gst_printerr (const gchar *format,
+              ...);
+

Outputs a formatted message via the GLib error message handler. The default +handler simply outputs the message to stderr.

+

This function will not append a new-line character at the end, unlike +gst_printerrln() which will.

+

All strings must be in ASCII or UTF-8 encoding.

+

This function differs from g_printerr() in that it supports the additional +printf specifiers that are supported by GStreamer's debug logging system, +such as GST_PTR_FORMAT and GST_SEGMENT_FORMAT.

+

This function is primarily for printing debug output.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

...

the printf arguments for format +

 
+
+

Since: 1.12

+
+
+
+

gst_printerrln ()

+
void
+gst_printerrln (const gchar *format,
+                ...);
+

Outputs a formatted message via the GLib error message handler. The default +handler simply outputs the message to stderr.

+

This function will append a new-line character at the end, unlike +gst_printerr() which will not.

+

All strings must be in ASCII or UTF-8 encoding.

+

This function differs from g_printerr() in that it supports the additional +printf specifiers that are supported by GStreamer's debug logging system, +such as GST_PTR_FORMAT and GST_SEGMENT_FORMAT.

+

This function is primarily for printing debug output.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

format

a printf style format string

 

...

the printf arguments for format +

 
+
+

Since: 1.12

+
+
+
+

Types and Values

+
+

enum GstDebugLevel

+

The level defines the importance of a debugging message. The more important a +message is, the greater the probability that the debugging system outputs it.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_LEVEL_NONE

+

No debugging level specified or desired. Used to deactivate + debugging output.

+
 

GST_LEVEL_ERROR

+

Error messages are to be used only when an error occurred + that stops the application from keeping working correctly. + An examples is gst_element_error, which outputs a message with this priority. + It does not mean that the application is terminating as with g_error.

+
 

GST_LEVEL_WARNING

+

Warning messages are to inform about abnormal behaviour + that could lead to problems or weird behaviour later on. An example of this + would be clocking issues ("your computer is pretty slow") or broken input + data ("Can't synchronize to stream.")

+
 

GST_LEVEL_FIXME

+

Fixme messages are messages that indicate that something + in the executed code path is not fully implemented or handled yet. Note + that this does not replace proper error handling in any way, the purpose + of this message is to make it easier to spot incomplete/unfinished pieces + of code when reading the debug log.

+
 

GST_LEVEL_INFO

+

Informational messages should be used to keep the developer + updated about what is happening. + Examples where this should be used are when a typefind function has + successfully determined the type of the stream or when an mp3 plugin detects + the format to be used. ("This file has mono sound.")

+
 

GST_LEVEL_DEBUG

+

Debugging messages should be used when something common + happens that is not the expected default behavior, or something that's + useful to know but doesn't happen all the time (ie. per loop iteration or + buffer processed or event handled). + An example would be notifications about state changes or receiving/sending + of events.

+
 

GST_LEVEL_LOG

+

Log messages are messages that are very common but might be + useful to know. As a rule of thumb a pipeline that is running as expected + should never output anything else but LOG messages whilst processing data. + Use this log level to log recurring information in chain functions and + loop functions, for example.

+
 

GST_LEVEL_TRACE

+

Tracing-related messages. + Examples for this are referencing/dereferencing of objects.

+
 

GST_LEVEL_MEMDUMP

+

memory dump messages are used to log (small) chunks of + data as memory dumps in the log. They will be displayed as hexdump with + ASCII characters.

+
 

GST_LEVEL_COUNT

+

The number of defined debugging levels.

+
 
+
+
+
+
+

GST_LEVEL_DEFAULT

+
#define GST_LEVEL_DEFAULT GST_LEVEL_NONE
+
+

Defines the default debugging level to be used with GStreamer. It is normally +set to GST_LEVEL_NONE so nothing get printed. +As it can be configured at compile time, developer builds may chose to +override that though. +You can use this as an argument to gst_debug_set_default_threshold() to +reset the debugging output to default behaviour.

+
+
+
+

GST_LEVEL_MAX

+
#define GST_LEVEL_MAX GST_LEVEL_COUNT
+
+

Defines the maximum debugging level to be enabled at compilation time. By default +it is set such that all debugging statements will be enabled.

+

If you wish to compile GStreamer and plugins with only some debugging statements +(Such as just warnings and errors), you can define it at compile time to the +maximum debug level. Any debug statements above that level will be compiled out.

+

Since: 1.6

+
+
+
+

enum GstDebugColorFlags

+

These are some terminal style flags you can use when creating your +debugging categories to make them stand out in debugging output.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_DEBUG_FG_BLACK

+

Use black as foreground color.

+
 

GST_DEBUG_FG_RED

+

Use red as foreground color.

+
 

GST_DEBUG_FG_GREEN

+

Use green as foreground color.

+
 

GST_DEBUG_FG_YELLOW

+

Use yellow as foreground color.

+
 

GST_DEBUG_FG_BLUE

+

Use blue as foreground color.

+
 

GST_DEBUG_FG_MAGENTA

+

Use magenta as foreground color.

+
 

GST_DEBUG_FG_CYAN

+

Use cyan as foreground color.

+
 

GST_DEBUG_FG_WHITE

+

Use white as foreground color.

+
 

GST_DEBUG_BG_BLACK

+

Use black as background color.

+
 

GST_DEBUG_BG_RED

+

Use red as background color.

+
 

GST_DEBUG_BG_GREEN

+

Use green as background color.

+
 

GST_DEBUG_BG_YELLOW

+

Use yellow as background color.

+
 

GST_DEBUG_BG_BLUE

+

Use blue as background color.

+
 

GST_DEBUG_BG_MAGENTA

+

Use magenta as background color.

+
 

GST_DEBUG_BG_CYAN

+

Use cyan as background color.

+
 

GST_DEBUG_BG_WHITE

+

Use white as background color.

+
 

GST_DEBUG_BOLD

+

Make the output bold.

+
 

GST_DEBUG_UNDERLINE

+

Underline the output.

+
 
+
+
+
+
+

enum GstDebugColorMode

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_DEBUG_COLOR_MODE_OFF

+

Do not use colors in logs.

+
 

GST_DEBUG_COLOR_MODE_ON

+

Paint logs in a platform-specific way.

+
 

GST_DEBUG_COLOR_MODE_UNIX

+

Paint logs with UNIX terminal color codes + no matter what platform GStreamer is running on.

+
 
+
+
+
+
+

struct GstDebugCategory

+
struct GstDebugCategory {
+};
+
+

This is the struct that describes the categories. Once initialized with +GST_DEBUG_CATEGORY_INIT, its values can't be changed anymore.

+
+
+
+

enum GstDebugGraphDetails

+

Available details for pipeline graphs produced by GST_DEBUG_BIN_TO_DOT_FILE() +and GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE

+

show caps-name on edges

+
 

GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS

+

show caps-details on edges

+
 

GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS

+

show modified parameters on + elements

+
 

GST_DEBUG_GRAPH_SHOW_STATES

+

show element states

+
 

GST_DEBUG_GRAPH_SHOW_FULL_PARAMS

+

show full element parameter values even + if they are very long

+
 

GST_DEBUG_GRAPH_SHOW_ALL

+

show all the typical details that one might want

+
 

GST_DEBUG_GRAPH_SHOW_VERBOSE

+

show all details regardless of how large or + verbose they make the resulting output

+
 
+
+
+
+
+

GST_FUNCTION

+
#  define GST_FUNCTION     ((const char*) (__func__))
+
+

This macro should evaluate to the name of the current function and be should +be defined when configuring your project, as it is compiler dependant. If it +is not defined, some default value is used. It is used to provide debugging +output with the function name of the message.

+

Note that this is different from G_STRFUNC as we do not want the full +function signature in C++ code.

+
+
+
+

enum GstStackTraceFlags

+
+

Members

+
+++++ + + + + + +

GST_STACK_TRACE_SHOW_FULL

+

Try to retrieve as much information as + possible when getting the stack trace

+
 
+
+

Since: 1.12

+
+
+
+

GST_CAT_DEFAULT

+
GST_API GstDebugCategory * GST_CAT_DEFAULT;
+
+

Default gstreamer core debug log category. Please define your own.

+
+
+
+

GST_TIME_FORMAT

+
#define GST_TIME_FORMAT "u:%02u:%02u.%09u"
+
+

A string that can be used in printf-like format strings to display a +GstClockTime value in h:m:s format. Use GST_TIME_ARGS() to construct +the matching arguments.

+

Example:

+
+ + + + + + + +
1
printf("%" GST_TIME_FORMAT "\n", GST_TIME_ARGS(ts));
+
+ +

+
+
+
+

GST_STIME_FORMAT

+
#define GST_STIME_FORMAT "c%" GST_TIME_FORMAT
+
+

A string that can be used in printf-like format strings to display a signed +GstClockTimeDiff or gint64 value in h:m:s format. Use GST_TIME_ARGS() to +construct the matching arguments.

+

Example:

+
+ + + + + + + +
1
printf("%" GST_STIME_FORMAT "\n", GST_STIME_ARGS(ts));
+
+ +

+

Since: 1.6

+
+
+
+

GST_PTR_FORMAT

+
#define GST_PTR_FORMAT     "p\aA"
+
+

printf format type used to debug GStreamer types. You can use this in +combination with GStreamer's debug logging system as well as the functions +gst_info_vasprintf(), gst_info_strdup_vprintf() and gst_info_strdup_printf() +to pretty-print the following types: GstCaps, GstStructure, +GstCapsFeatures, GstTagList, GstDateTime, GstBuffer, GstBufferList, +GstMessage, GstEvent, GstQuery, GstContext, GstPad, GstObject. All +GObject types will be printed as typename plus pointer, and everything +else will simply be printed as pointer address.

+

This can only be used on types whose size is >= sizeof(gpointer).

+
+
+
+

GST_SEGMENT_FORMAT

+
#define GST_SEGMENT_FORMAT "p\aB"
+
+

printf format type used to debug GStreamer segments. You can use this in +combination with GStreamer's debug logging system as well as the functions +gst_info_vasprintf(), gst_info_strdup_vprintf() and gst_info_strdup_printf() +to pretty-print GstSegment structures. +This can only be used on pointers to GstSegment structures.

+
+
+
+

See Also

+

gst-running for command line parameters +and environment variables that affect the debugging output.

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstIterator.html b/docs/gst/html/gstreamer-GstIterator.html new file mode 100644 index 0000000..fc5a34f --- /dev/null +++ b/docs/gst/html/gstreamer-GstIterator.html @@ -0,0 +1,1362 @@ + + + + +GstIterator: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstIterator

+

GstIterator — Object to retrieve multiple elements in a threadsafe +way.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstIteratorCopyFunction) () +
+GstIteratorResult + +(*GstIteratorNextFunction) () +
+GstIteratorItem + +(*GstIteratorItemFunction) () +
+void + +(*GstIteratorResyncFunction) () +
+void + +(*GstIteratorFreeFunction) () +
+void + +(*GstIteratorForeachFunction) () +
+gboolean + +(*GstIteratorFoldFunction) () +
#define +GST_ITERATOR() +
#define +GST_ITERATOR_LOCK() +
#define +GST_ITERATOR_COOKIE() +
#define +GST_ITERATOR_ORIG_COOKIE() +
+GstIterator * + +gst_iterator_new () +
+GstIterator * + +gst_iterator_new_list () +
+GstIterator * + +gst_iterator_new_single () +
+GstIterator * + +gst_iterator_copy () +
+void + +gst_iterator_free () +
+GstIteratorResult + +gst_iterator_next () +
+void + +gst_iterator_resync () +
+void + +gst_iterator_push () +
+GstIterator * + +gst_iterator_filter () +
+GstIteratorResult + +gst_iterator_fold () +
+GstIteratorResult + +gst_iterator_foreach () +
+gboolean + +gst_iterator_find_custom () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstIterator
enumGstIteratorItem
enumGstIteratorResult
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstIterator is used to retrieve multiple objects from another object in +a threadsafe way.

+

Various GStreamer objects provide access to their internal structures using +an iterator.

+

Note that if calling a GstIterator function results in your code receiving +a refcounted object (with, say, g_value_get_object()), the refcount for that +object will not be increased. Your code is responsible for taking a reference +if it wants to continue using it later.

+

The basic use pattern of an iterator is as follows:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
GstIterator *it = _get_iterator(object);
+GValue item = G_VALUE_INIT;
+done = FALSE;
+while (!done) {
+  switch (gst_iterator_next (it, &item)) {
+    case GST_ITERATOR_OK:
+      ...get/use/change item here...
+      g_value_reset (&item);
+      break;
+    case GST_ITERATOR_RESYNC:
+      ...rollback changes to items...
+      gst_iterator_resync (it);
+      break;
+    case GST_ITERATOR_ERROR:
+      ...wrong parameters were given...
+      done = TRUE;
+      break;
+    case GST_ITERATOR_DONE:
+      done = TRUE;
+      break;
+  }
+}
+g_value_unset (&item);
+gst_iterator_free (it);
+
+ +

+
+
+

Functions

+
+

GstIteratorCopyFunction ()

+
void
+(*GstIteratorCopyFunction) (const GstIterator *it,
+                            GstIterator *copy);
+

This function will be called when creating a copy of it + and should +create a copy of all custom iterator fields or increase their +reference counts.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

it

The original iterator

 

copy

The copied iterator

 
+
+
+
+
+

GstIteratorNextFunction ()

+
GstIteratorResult
+(*GstIteratorNextFunction) (GstIterator *it,
+                            GValue *result);
+

The function that will be called when the next element of the iterator +should be retrieved.

+

Implementors of a GstIterator should implement this +function and pass it to the constructor of the custom iterator. +The function will be called with the iterator lock held.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

it

the iterator

 

result

a pointer to hold the next item

 
+
+
+

Returns

+

the result of the operation.

+
+
+
+
+

GstIteratorItemFunction ()

+
GstIteratorItem
+(*GstIteratorItemFunction) (GstIterator *it,
+                            const GValue *item);
+

The function that will be called after the next item of the iterator +has been retrieved. This function can be used to skip items or stop +the iterator.

+

The function will be called with the iterator lock held.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

it

the iterator

 

item

the item being retrieved.

 
+
+
+

Returns

+

the result of the operation.

+
+
+
+
+

GstIteratorResyncFunction ()

+
void
+(*GstIteratorResyncFunction) (GstIterator *it);
+

This function will be called whenever a concurrent update happened +to the iterated datastructure. The implementor of the iterator should +restart the iterator from the beginning and clean up any state it might +have.

+

Implementors of a GstIterator should implement this +function and pass it to the constructor of the custom iterator. +The function will be called with the iterator lock held.

+
+

Parameters

+
+++++ + + + + + +

it

the iterator

 
+
+
+
+
+

GstIteratorFreeFunction ()

+
void
+(*GstIteratorFreeFunction) (GstIterator *it);
+

This function will be called when the iterator is freed.

+

Implementors of a GstIterator should implement this +function and pass it to the constructor of the custom iterator. +The function will be called with the iterator lock held.

+
+

Parameters

+
+++++ + + + + + +

it

the iterator

 
+
+
+
+
+

GstIteratorForeachFunction ()

+
void
+(*GstIteratorForeachFunction) (const GValue *item,
+                               gpointer user_data);
+

A function that is called by gst_iterator_foreach() for every element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

item

The item

 

user_data

User data

 
+
+
+
+
+

GstIteratorFoldFunction ()

+
gboolean
+(*GstIteratorFoldFunction) (const GValue *item,
+                            GValue *ret,
+                            gpointer user_data);
+

A function to be passed to gst_iterator_fold().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

item

the item to fold

 

ret

a GValue collecting the result

 

user_data

data passed to gst_iterator_fold()

 
+
+
+

Returns

+

TRUE if the fold should continue, FALSE if it should stop.

+
+
+
+
+

GST_ITERATOR()

+
#define GST_ITERATOR(it)                ((GstIterator*)(it))
+
+

Macro to cast to a GstIterator

+
+

Parameters

+
+++++ + + + + + +

it

the GstIterator value

 
+
+
+
+
+

GST_ITERATOR_LOCK()

+
#define GST_ITERATOR_LOCK(it)           (GST_ITERATOR(it)->lock)
+
+

Macro to get the lock protecting the datastructure being iterated.

+
+

Parameters

+
+++++ + + + + + +

it

the GstIterator to get the lock of

 
+
+
+
+
+

GST_ITERATOR_COOKIE()

+
#define GST_ITERATOR_COOKIE(it)         (GST_ITERATOR(it)->cookie)
+
+

Macro to get the cookie of a GstIterator. The cookie of the +iterator is the value of the master cookie when the iterator +was created. +Whenever the iterator is iterated, the value is compared to the +value of the master cookie. If they are different, a concurrent +modification happened to the iterator and a resync is needed.

+
+

Parameters

+
+++++ + + + + + +

it

the GstIterator to get the cookie of

 
+
+
+
+
+

GST_ITERATOR_ORIG_COOKIE()

+
#define GST_ITERATOR_ORIG_COOKIE(it)    (GST_ITERATOR(it)->master_cookie)
+
+

Macro to get a pointer to where the master cookie is stored. The +master cookie protects the structure being iterated and gets updated +whenever the datastructure changes.

+
+

Parameters

+
+++++ + + + + + +

it

the GstIterator to get the master cookie of

 
+
+
+
+
+

gst_iterator_new ()

+
GstIterator *
+gst_iterator_new (guint size,
+                  GType type,
+                  GMutex *lock,
+                  guint32 *master_cookie,
+                  GstIteratorCopyFunction copy,
+                  GstIteratorNextFunction next,
+                  GstIteratorItemFunction item,
+                  GstIteratorResyncFunction resync,
+                  GstIteratorFreeFunction free);
+

Create a new iterator. This function is mainly used for objects +implementing the next/resync/free function to iterate a data structure.

+

For each item retrieved, the item + function is called with the lock +held. The free + function is called when the iterator is freed.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

size

the size of the iterator structure

 

type

GType of children

 

lock

pointer to a GMutex.

 

master_cookie

pointer to a guint32 that is changed when the items in the +iterator changed.

 

copy

copy function

 

next

function to get next item

 

item

function to call on each item retrieved

 

resync

function to resync the iterator

 

free

function to free the iterator

 
+
+
+

Returns

+

the new GstIterator.

+

MT safe.

+
+
+
+
+

gst_iterator_new_list ()

+
GstIterator *
+gst_iterator_new_list (GType type,
+                       GMutex *lock,
+                       guint32 *master_cookie,
+                       GList **list,
+                       GObject *owner,
+                       GstIteratorItemFunction item);
+

Create a new iterator designed for iterating list +.

+

The list you iterate is usually part of a data structure owner + and is +protected with lock +.

+

The iterator will use lock + to retrieve the next item of the list and it +will then call the item + function before releasing lock + again.

+

When a concurrent update to the list is performed, usually by owner + while +holding lock +, master_cookie + will be updated. The iterator implementation +will notice the update of the cookie and will return GST_ITERATOR_RESYNC to +the user of the iterator in the next call to gst_iterator_next().

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

type

GType of elements

 

lock

pointer to a GMutex protecting the list.

 

master_cookie

pointer to a guint32 that is incremented when the list +is changed.

 

list

pointer to the list

 

owner

object owning the list

 

item

function to call on each item retrieved

 
+
+
+

Returns

+

the new GstIterator for list +.

+

MT safe.

+
+
+
+
+

gst_iterator_new_single ()

+
GstIterator *
+gst_iterator_new_single (GType type,
+                         const GValue *object);
+

This GstIterator is a convenient iterator for the common +case where a GstIterator needs to be returned but only +a single object has to be considered. This happens often +for the GstPadIterIntLinkFunction.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

GType of the passed object

 

object

object that this iterator should return

 
+
+
+

Returns

+

the new GstIterator for object +.

+
+
+
+
+

gst_iterator_copy ()

+
GstIterator *
+gst_iterator_copy (const GstIterator *it);
+

Copy the iterator and its state.

+
+

Parameters

+
+++++ + + + + + +

it

a GstIterator

 
+
+
+

Returns

+

a new copy of it +.

+
+
+
+
+

gst_iterator_free ()

+
void
+gst_iterator_free (GstIterator *it);
+

Free the iterator.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

it

The GstIterator to free

 
+
+
+
+
+

gst_iterator_next ()

+
GstIteratorResult
+gst_iterator_next (GstIterator *it,
+                   GValue *elem);
+

Get the next item from the iterator in elem +.

+

Only when this function returns GST_ITERATOR_OK, elem + will contain a valid +value. elem + must have been initialized to the type of the iterator or +initialized to zeroes with g_value_unset(). The caller is responsible for +unsetting or resetting elem + with g_value_unset() or g_value_reset() +after usage.

+

When this function returns GST_ITERATOR_DONE, no more elements can be +retrieved from it +.

+

A return value of GST_ITERATOR_RESYNC indicates that the element list was +concurrently updated. The user of it + should call gst_iterator_resync() to +get the newly updated list.

+

A return value of GST_ITERATOR_ERROR indicates an unrecoverable fatal error.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

it

The GstIterator to iterate

 

elem

pointer to hold next element.

[out caller-allocates]
+
+
+

Returns

+

The result of the iteration. Unset elem +after usage.

+

MT safe.

+
+
+
+
+

gst_iterator_resync ()

+
void
+gst_iterator_resync (GstIterator *it);
+

Resync the iterator. this function is mostly called +after gst_iterator_next() returned GST_ITERATOR_RESYNC.

+

When an iterator was pushed on it +, it will automatically be popped again +with this function.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

it

The GstIterator to resync

 
+
+
+
+
+

gst_iterator_push ()

+
void
+gst_iterator_push (GstIterator *it,
+                   GstIterator *other);
+

Pushes other + iterator onto it +. All calls performed on it + are +forwarded to other +. If other + returns GST_ITERATOR_DONE, it is +popped again and calls are handled by it + again.

+

This function is mainly used by objects implementing the iterator +next function to recurse into substructures.

+

When gst_iterator_resync() is called on it +, other + will automatically be +popped.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

it

The GstIterator to use

 

other

The GstIterator to push

 
+
+
+
+
+

gst_iterator_filter ()

+
GstIterator *
+gst_iterator_filter (GstIterator *it,
+                     GCompareFunc func,
+                     const GValue *user_data);
+

Create a new iterator from an existing iterator. The new iterator +will only return those elements that match the given compare function func +. +The first parameter that is passed to func + is the GValue of the current +iterator element and the second parameter is user_data +. func + should +return 0 for elements that should be included in the filtered iterator.

+

When this iterator is freed, it + will also be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

it

The GstIterator to filter

 

func

the compare function to select elements.

[scope call]

user_data

user data passed to the compare function.

[closure]
+
+
+

Returns

+

a new GstIterator.

+

MT safe.

+

[transfer full]

+
+
+
+
+

gst_iterator_fold ()

+
GstIteratorResult
+gst_iterator_fold (GstIterator *it,
+                   GstIteratorFoldFunction func,
+                   GValue *ret,
+                   gpointer user_data);
+

Folds func + over the elements of iter +. That is to say, func + will be called +as func + (object, ret +, user_data +) for each object in it +. The normal use +of this procedure is to accumulate the results of operating on the objects in +ret +.

+

This procedure can be used (and is used internally) to implement the +gst_iterator_foreach() and gst_iterator_find_custom() operations.

+

The fold will proceed as long as func + returns TRUE. When the iterator has no +more arguments, GST_ITERATOR_DONE will be returned. If func + returns FALSE, +the fold will stop, and GST_ITERATOR_OK will be returned. Errors or resyncs +will cause fold to return GST_ITERATOR_ERROR or GST_ITERATOR_RESYNC as +appropriate.

+

The iterator will not be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

it

The GstIterator to fold over

 

func

the fold function.

[scope call]

ret

the seed value passed to the fold function

 

user_data

user data passed to the fold function.

[closure]
+
+
+

Returns

+

A GstIteratorResult, as described above.

+

MT safe.

+
+
+
+
+

gst_iterator_foreach ()

+
GstIteratorResult
+gst_iterator_foreach (GstIterator *it,
+                      GstIteratorForeachFunction func,
+                      gpointer user_data);
+

Iterate over all element of it + and call the given function func + for +each element.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

it

The GstIterator to iterate

 

func

the function to call for each element.

[scope call]

user_data

user data passed to the function.

[closure]
+
+
+

Returns

+

the result call to gst_iterator_fold(). The iterator will not be +freed.

+

MT safe.

+
+
+
+
+

gst_iterator_find_custom ()

+
gboolean
+gst_iterator_find_custom (GstIterator *it,
+                          GCompareFunc func,
+                          GValue *elem,
+                          gpointer user_data);
+

Find the first element in it + that matches the compare function func +. +func + should return 0 when the element is found. The first parameter +to func + will be the current element of the iterator and the +second parameter will be user_data +. +The result will be stored in elem + if a result is found.

+

The iterator will not be freed.

+

This function will return FALSE if an error happened to the iterator +or if the element wasn't found.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

it

The GstIterator to iterate

 

func

the compare function to use.

[scope call]

elem

pointer to a GValue where to store the result.

[out]

user_data

user data passed to the compare function.

[closure]
+
+
+

Returns

+

Returns TRUE if the element was found, else FALSE.

+

MT safe.

+
+
+
+
+

Types and Values

+
+

struct GstIterator

+
struct GstIterator {
+};
+
+

GstIterator base structure. The values of this structure are +protected for subclasses, use the methods to use the GstIterator.

+
+

Members

+
+++++ + +
+
+
+
+
+

enum GstIteratorItem

+

The result of a GstIteratorItemFunction.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_ITERATOR_ITEM_SKIP

+

Skip this item

+
 

GST_ITERATOR_ITEM_PASS

+

Return item

+
 

GST_ITERATOR_ITEM_END

+

Stop after this item.

+
 
+
+
+
+
+

enum GstIteratorResult

+

The result of gst_iterator_next().

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_ITERATOR_DONE

+

No more items in the iterator

+
 

GST_ITERATOR_OK

+

An item was retrieved

+
 

GST_ITERATOR_RESYNC

+

Datastructure changed while iterating

+
 

GST_ITERATOR_ERROR

+

An error happened

+
 
+
+
+
+
+

See Also

+

GstElement, GstBin

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstMeta.html b/docs/gst/html/gstreamer-GstMeta.html new file mode 100644 index 0000000..1591297 --- /dev/null +++ b/docs/gst/html/gstreamer-GstMeta.html @@ -0,0 +1,876 @@ + + + + +GstMeta: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstMeta

+

GstMeta — Buffer metadata

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_META_FLAGS() +
#define +GST_META_FLAG_IS_SET() +
#define +GST_META_FLAG_SET() +
#define +GST_META_FLAG_UNSET() +
+gboolean + +(*GstMetaInitFunction) () +
+void + +(*GstMetaFreeFunction) () +
+gboolean + +(*GstMetaTransformFunction) () +
#define +GST_META_TRANSFORM_IS_COPY() +
+GType + +gst_meta_api_type_register () +
+gboolean + +gst_meta_api_type_has_tag () +
const gchar * const* + +gst_meta_api_type_get_tags () +
const GstMetaInfo * + +gst_meta_register () +
const GstMetaInfo * + +gst_meta_get_info () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstMeta
enumGstMetaFlags
structGstMetaInfo
 GstMetaTransformCopy
#defineGST_META_TAG_MEMORY
#defineGST_META_TAG_MEMORY_STR
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

The GstMeta structure should be included as the first member of a GstBuffer +metadata structure. The structure defines the API of the metadata and should +be accessible to all elements using the metadata.

+

A metadata API is registered with gst_meta_api_type_register() which takes a +name for the metadata API and some tags associated with the metadata. +With gst_meta_api_type_has_tag() one can check if a certain metadata API +contains a given tag.

+

Multiple implementations of a metadata API can be registered. +To implement a metadata API, gst_meta_register() should be used. This +function takes all parameters needed to create, free and transform metadata +along with the size of the metadata. The function returns a GstMetaInfo +structure that contains the information for the implementation of the API.

+

A specific implementation can be retrieved by name with gst_meta_get_info().

+

See GstBuffer for how the metadata can be added, retrieved and removed from +buffers.

+
+
+

Functions

+
+

GST_META_FLAGS()

+
#define GST_META_FLAGS(meta)  (GST_META_CAST (meta)->flags)
+
+

A flags word containing GstMetaFlags flags set on meta +

+
+

Parameters

+
+++++ + + + + + +

meta

a GstMeta.

 
+
+
+
+
+

GST_META_FLAG_IS_SET()

+
#define GST_META_FLAG_IS_SET(meta,flag)        !!(GST_META_FLAGS (meta) & (flag))
+
+

Gives the status of a specific flag on a metadata.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

meta

a GstMeta.

 

flag

the GstMetaFlags to check.

 
+
+
+
+
+

GST_META_FLAG_SET()

+
#define GST_META_FLAG_SET(meta,flag)           (GST_META_FLAGS (meta) |= (flag))
+
+

Sets a metadata flag on a metadata.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

meta

a GstMeta.

 

flag

the GstMetaFlags to set.

 
+
+
+
+
+

GST_META_FLAG_UNSET()

+
#define GST_META_FLAG_UNSET(meta,flag)         (GST_META_FLAGS (meta) &= ~(flag))
+
+

Clears a metadata flag.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

meta

a GstMeta.

 

flag

the GstMetaFlags to clear.

 
+
+
+
+
+

GstMetaInitFunction ()

+
gboolean
+(*GstMetaInitFunction) (GstMeta *meta,
+                        gpointer params,
+                        GstBuffer *buffer);
+

Function called when meta + is initialized in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

meta

a GstMeta

 

params

parameters passed to the init function

 

buffer

a GstBuffer

 
+
+
+
+
+

GstMetaFreeFunction ()

+
void
+(*GstMetaFreeFunction) (GstMeta *meta,
+                        GstBuffer *buffer);
+

Function called when meta + is freed in buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

meta

a GstMeta

 

buffer

a GstBuffer

 
+
+
+
+
+

GstMetaTransformFunction ()

+
gboolean
+(*GstMetaTransformFunction) (GstBuffer *transbuf,
+                             GstMeta *meta,
+                             GstBuffer *buffer,
+                             GQuark type,
+                             gpointer data);
+

Function called for each meta + in buffer + as a result of performing a +transformation on transbuf +. Additional type + specific transform data +is passed to the function as data +.

+

Implementations should check the type + of the transform and parse +additional type specific fields in data + that should be used to update +the metadata on transbuf +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

transbuf

a GstBuffer

 

meta

a GstMeta

 

buffer

a GstBuffer

 

type

the transform type

 

data

transform specific data.

 
+
+
+

Returns

+

TRUE if the transform could be performed

+
+
+
+
+

GST_META_TRANSFORM_IS_COPY()

+
#define GST_META_TRANSFORM_IS_COPY(type) ((type) == _gst_meta_transform_copy)
+
+

Check if the transform type is a copy transform

+
+

Parameters

+
+++++ + + + + + +

type

a transform type

 
+
+
+
+
+

gst_meta_api_type_register ()

+
GType
+gst_meta_api_type_register (const gchar *api,
+                            const gchar **tags);
+

Register and return a GType for the api + and associate it with +tags +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

api

an API to register

 

tags

tags for api +

 
+
+
+

Returns

+

a unique GType for api +.

+
+
+
+
+

gst_meta_api_type_has_tag ()

+
gboolean
+gst_meta_api_type_has_tag (GType api,
+                           GQuark tag);
+

Check if api + was registered with tag +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

api

an API

 

tag

the tag to check

 
+
+
+

Returns

+

TRUE if api +was registered with tag +.

+
+
+
+
+

gst_meta_api_type_get_tags ()

+
const gchar * const*
+gst_meta_api_type_get_tags (GType api);
+
+

Parameters

+
+++++ + + + + + +

api

an API

 
+
+
+

Returns

+

an array of tags as strings.

+

[transfer none][array zero-terminated=1][element-type utf8]

+
+

Since: 1.2

+
+
+
+

gst_meta_register ()

+
const GstMetaInfo *
+gst_meta_register (GType api,
+                   const gchar *impl,
+                   gsize size,
+                   GstMetaInitFunction init_func,
+                   GstMetaFreeFunction free_func,
+                   GstMetaTransformFunction transform_func);
+

Register a new GstMeta implementation.

+

The same info + can be retrieved later with gst_meta_get_info() by using +impl + as the key.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

api

the type of the GstMeta API

 

impl

the name of the GstMeta implementation

 

size

the size of the GstMeta structure

 

init_func

a GstMetaInitFunction.

[scope async]

free_func

a GstMetaFreeFunction.

[scope async]

transform_func

a GstMetaTransformFunction.

[scope async]
+
+
+

Returns

+

a GstMetaInfo that can be used to +access metadata.

+

[transfer none][nullable]

+
+
+
+
+

gst_meta_get_info ()

+
const GstMetaInfo *
+gst_meta_get_info (const gchar *impl);
+

Lookup a previously registered meta info structure by its implementation name +impl +.

+
+

Parameters

+
+++++ + + + + + +

impl

the name

 
+
+
+

Returns

+

a GstMetaInfo with impl +, or +NULL when no such metainfo exists.

+

[transfer none][nullable]

+
+
+
+
+

Types and Values

+
+

struct GstMeta

+
struct GstMeta {
+  GstMetaFlags       flags;
+  const GstMetaInfo *info;
+};
+
+

Base structure for metadata. Custom metadata will put this structure +as the first member of their structure.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMetaFlags flags;

extra flags for the metadata

 

const GstMetaInfo *info;

pointer to the GstMetaInfo

 
+
+
+
+
+

enum GstMetaFlags

+

Extra metadata flags.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_META_FLAG_NONE

+

no flags

+
 

GST_META_FLAG_READONLY

+

metadata should not be modified

+
 

GST_META_FLAG_POOLED

+

metadata is managed by a bufferpool

+
 

GST_META_FLAG_LOCKED

+

metadata should not be removed

+
 

GST_META_FLAG_LAST

+

additional flags can be added starting from this flag.

+
 
+
+
+
+
+

struct GstMetaInfo

+
struct GstMetaInfo {
+  GType                      api;
+  GType                      type;
+  gsize                      size;
+
+  GstMetaInitFunction        init_func;
+  GstMetaFreeFunction        free_func;
+  GstMetaTransformFunction   transform_func;
+
+  /* No padding needed, GstMetaInfo is always allocated by GStreamer and is
+   * not subclassable or stack-allocatable, so we can extend it as we please
+   * just like interfaces */
+};
+
+

The GstMetaInfo provides information about a specific metadata +structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GType api;

tag identifying the metadata structure and api

 

GType type;

type identifying the implementor of the api

 

gsize size;

size of the metadata

 

GstMetaInitFunction init_func;

function for initializing the metadata

 

GstMetaFreeFunction free_func;

function for freeing the metadata

 

GstMetaTransformFunction transform_func;

function for transforming the metadata

 
+
+
+
+
+

GstMetaTransformCopy

+
typedef struct {
+  gboolean region;
+  gsize offset;
+  gsize size;
+} GstMetaTransformCopy;
+
+

Extra data passed to a "gst-copy" transform GstMetaTransformFunction.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

gboolean region;

TRUE if only region is copied

 

gsize offset;

the offset to copy, 0 if region +is FALSE, otherwise > 0

 

gsize size;

the size to copy, -1 or the buffer size when region +is FALSE

 
+
+
+
+
+

GST_META_TAG_MEMORY

+
#define GST_META_TAG_MEMORY (_gst_meta_tag_memory)
+
+
+

GST_META_TAG_MEMORY is deprecated and should not be used in newly-written code.

+

The GQuarks are not exported by any public API, use + GST_META_TAG_MEMORY_STR instead.

+
+

Metadata tagged with this tag depends on the particular memory +or buffer that it is on.

+
+
+
+

GST_META_TAG_MEMORY_STR

+
#define GST_META_TAG_MEMORY_STR "memory"
+
+

This metadata stays relevant as long as memory layout is unchanged.

+

Since: 1.2

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstMiniObject.html b/docs/gst/html/gstreamer-GstMiniObject.html new file mode 100644 index 0000000..374f425 --- /dev/null +++ b/docs/gst/html/gstreamer-GstMiniObject.html @@ -0,0 +1,1441 @@ + + + + +GstMiniObject: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstMiniObject

+

GstMiniObject — Lightweight base class for the GStreamer object hierarchy

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstMiniObject * + +(*GstMiniObjectCopyFunction) () +
+gboolean + +(*GstMiniObjectDisposeFunction) () +
+void + +(*GstMiniObjectFreeFunction) () +
+void + +(*GstMiniObjectNotify) () +
#define +GST_MINI_OBJECT_TYPE() +
#define +GST_MINI_OBJECT_FLAGS() +
#define +GST_MINI_OBJECT_FLAG_IS_SET() +
#define +GST_MINI_OBJECT_FLAG_SET() +
#define +GST_MINI_OBJECT_FLAG_UNSET() +
#define +GST_MINI_OBJECT_IS_LOCKABLE() +
#define +GST_MINI_OBJECT_REFCOUNT() +
#define +GST_MINI_OBJECT_REFCOUNT_VALUE() +
#define +GST_DEFINE_MINI_OBJECT_TYPE() +
+void + +gst_mini_object_init () +
+GstMiniObject * + +gst_mini_object_ref () +
+void + +gst_mini_object_unref () +
+void + +gst_mini_object_weak_ref () +
+void + +gst_mini_object_weak_unref () +
+gboolean + +gst_mini_object_lock () +
+void + +gst_mini_object_unlock () +
+gboolean + +gst_mini_object_is_writable () +
+GstMiniObject * + +gst_mini_object_make_writable () +
+GstMiniObject * + +gst_mini_object_copy () +
+void + +gst_mini_object_set_qdata () +
+gpointer + +gst_mini_object_get_qdata () +
+gpointer + +gst_mini_object_steal_qdata () +
+gboolean + +gst_mini_object_replace () +
+gboolean + +gst_mini_object_take () +
+GstMiniObject * + +gst_mini_object_steal () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
structGstMiniObject
enumGstMiniObjectFlags
enumGstLockFlags
#defineGST_LOCK_FLAG_READWRITE
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GstMiniObject is a simple structure that can be used to implement refcounted +types.

+

Subclasses will include GstMiniObject as the first member in their structure +and then call gst_mini_object_init() to initialize the GstMiniObject fields.

+

gst_mini_object_ref() and gst_mini_object_unref() increment and decrement the +refcount respectively. When the refcount of a mini-object reaches 0, the +dispose function is called first and when this returns TRUE, the free +function of the miniobject is called.

+

A copy can be made with gst_mini_object_copy().

+

gst_mini_object_is_writable() will return TRUE when the refcount of the +object is exactly 1, meaning the current caller has the only reference to the +object. gst_mini_object_make_writable() will return a writable version of the +object, which might be a new copy when the refcount was not 1.

+

Opaque data can be associated with a GstMiniObject with +gst_mini_object_set_qdata() and gst_mini_object_get_qdata(). The data is +meant to be specific to the particular object and is not automatically copied +with gst_mini_object_copy() or similar methods.

+

A weak reference can be added and remove with gst_mini_object_weak_ref() +and gst_mini_object_weak_unref() respectively.

+
+
+

Functions

+
+

GstMiniObjectCopyFunction ()

+
GstMiniObject *
+(*GstMiniObjectCopyFunction) (const GstMiniObject *obj);
+

Function prototype for methods to create copies of instances.

+
+

Parameters

+
+++++ + + + + + +

obj

MiniObject to copy

 
+
+
+

Returns

+

reference to cloned instance.

+
+
+
+
+

GstMiniObjectDisposeFunction ()

+
gboolean
+(*GstMiniObjectDisposeFunction) (GstMiniObject *obj);
+

Function prototype for when a miniobject has lost its last refcount. +Implementation of the mini object are allowed to revive the +passed object by doing a gst_mini_object_ref(). If the object is not +revived after the dispose function, the function should return TRUE +and the memory associated with the object is freed.

+
+

Parameters

+
+++++ + + + + + +

obj

MiniObject to dispose

 
+
+
+

Returns

+

TRUE if the object should be cleaned up.

+
+
+
+
+

GstMiniObjectFreeFunction ()

+
void
+(*GstMiniObjectFreeFunction) (GstMiniObject *obj);
+

Virtual function prototype for methods to free resources used by +mini-objects.

+
+

Parameters

+
+++++ + + + + + +

obj

MiniObject to free

 
+
+
+
+
+

GstMiniObjectNotify ()

+
void
+(*GstMiniObjectNotify) (gpointer user_data,
+                        GstMiniObject *obj);
+

A GstMiniObjectNotify function can be added to a mini object as a +callback that gets triggered when gst_mini_object_unref() drops the +last ref and obj + is about to be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

user_data

data that was provided when the notify was added

 

obj

the mini object

 
+
+
+
+
+

GST_MINI_OBJECT_TYPE()

+
#define GST_MINI_OBJECT_TYPE(obj)  (GST_MINI_OBJECT_CAST(obj)->type)
+
+

This macro returns the type of the mini-object.

+
+

Parameters

+
+++++ + + + + + +

obj

MiniObject to return type for.

 
+
+
+
+
+

GST_MINI_OBJECT_FLAGS()

+
#define GST_MINI_OBJECT_FLAGS(obj)  (GST_MINI_OBJECT_CAST(obj)->flags)
+
+

This macro returns the entire set of flags for the mini-object.

+
+

Parameters

+
+++++ + + + + + +

obj

MiniObject to return flags for.

 
+
+
+
+
+

GST_MINI_OBJECT_FLAG_IS_SET()

+
#define GST_MINI_OBJECT_FLAG_IS_SET(obj,flag)        !!(GST_MINI_OBJECT_FLAGS (obj) & (flag))
+
+

This macro checks to see if the given flag is set.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

MiniObject to check for flags.

 

flag

Flag to check for

 
+
+
+
+
+

GST_MINI_OBJECT_FLAG_SET()

+
#define GST_MINI_OBJECT_FLAG_SET(obj,flag)           (GST_MINI_OBJECT_FLAGS (obj) |= (flag))
+
+

This macro sets the given bits.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

MiniObject to set flag in.

 

flag

Flag to set, can by any number of bits in guint32.

 
+
+
+
+
+

GST_MINI_OBJECT_FLAG_UNSET()

+
#define GST_MINI_OBJECT_FLAG_UNSET(obj,flag)         (GST_MINI_OBJECT_FLAGS (obj) &= ~(flag))
+
+

This macro unsets the given bits.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

MiniObject to unset flag in.

 

flag

Flag to set, must be a single bit in guint32.

 
+
+
+
+
+

GST_MINI_OBJECT_IS_LOCKABLE()

+
#define GST_MINI_OBJECT_IS_LOCKABLE(obj)  GST_MINI_OBJECT_FLAG_IS_SET(obj, GST_MINI_OBJECT_FLAG_LOCKABLE)
+
+

Check if obj + is lockable. A lockable object can be locked and unlocked with +gst_mini_object_lock() and gst_mini_object_unlock().

+
+

Parameters

+
+++++ + + + + + +

obj

a GstMiniObject

 
+
+
+
+
+

GST_MINI_OBJECT_REFCOUNT()

+
#define GST_MINI_OBJECT_REFCOUNT(obj)           ((GST_MINI_OBJECT_CAST(obj))->refcount)
+
+

Get access to the reference count field of the mini-object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstMiniObject

 
+
+
+
+
+

GST_MINI_OBJECT_REFCOUNT_VALUE()

+
#define GST_MINI_OBJECT_REFCOUNT_VALUE(obj)     (g_atomic_int_get (&(GST_MINI_OBJECT_CAST(obj))->refcount))
+
+

Get the reference count value of the mini-object.

+
+

Parameters

+
+++++ + + + + + +

obj

a GstMiniObject

 
+
+
+
+
+

GST_DEFINE_MINI_OBJECT_TYPE()

+
#define             GST_DEFINE_MINI_OBJECT_TYPE(TypeName,type_name)
+

Define a new mini-object type with the given name

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

TypeName

name of the new type in CamelCase

 

type_name

name of the new type

 
+
+
+
+
+

gst_mini_object_init ()

+
void
+gst_mini_object_init (GstMiniObject *mini_object,
+                      guint flags,
+                      GType type,
+                      GstMiniObjectCopyFunction copy_func,
+                      GstMiniObjectDisposeFunction dispose_func,
+                      GstMiniObjectFreeFunction free_func);
+

Initializes a mini-object with the desired type and copy/dispose/free +functions.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

mini_object

a GstMiniObject

 

flags

initial GstMiniObjectFlags

 

type

the GType of the mini-object to create

 

copy_func

the copy function, or NULL.

[allow-none]

dispose_func

the dispose function, or NULL.

[allow-none]

free_func

the free function or NULL.

[allow-none]
+
+
+
+
+

gst_mini_object_ref ()

+
GstMiniObject *
+gst_mini_object_ref (GstMiniObject *mini_object);
+

Increase the reference count of the mini-object.

+

Note that the refcount affects the writability +of mini +-object, see gst_mini_object_is_writable(). It is +important to note that keeping additional references to +GstMiniObject instances can potentially increase the number +of memcpy operations in a pipeline, especially if the miniobject +is a GstBuffer.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

mini_object

the mini-object

 
+
+
+

Returns

+

the mini-object.

+

[transfer full]

+
+
+
+
+

gst_mini_object_unref ()

+
void
+gst_mini_object_unref (GstMiniObject *mini_object);
+

Decreases the reference count of the mini-object, possibly freeing +the mini-object.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

mini_object

the mini-object

 
+
+
+
+
+

gst_mini_object_weak_ref ()

+
void
+gst_mini_object_weak_ref (GstMiniObject *object,
+                          GstMiniObjectNotify notify,
+                          gpointer data);
+

Adds a weak reference callback to a mini object. Weak references are +used for notification when a mini object is finalized. They are called +"weak references" because they allow you to safely hold a pointer +to the mini object without calling gst_mini_object_ref() +(gst_mini_object_ref() adds a strong reference, that is, forces the object +to stay alive).

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

GstMiniObject to reference weakly

 

notify

callback to invoke before the mini object is freed

 

data

extra data to pass to notify

 
+
+
+
+
+

gst_mini_object_weak_unref ()

+
void
+gst_mini_object_weak_unref (GstMiniObject *object,
+                            GstMiniObjectNotify notify,
+                            gpointer data);
+

Removes a weak reference callback from a mini object.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

GstMiniObject to remove a weak reference from

 

notify

callback to search for

 

data

data to search for

 
+
+
+
+
+

gst_mini_object_lock ()

+
gboolean
+gst_mini_object_lock (GstMiniObject *object,
+                      GstLockFlags flags);
+

Lock the mini-object with the specified access mode in flags +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the mini-object to lock

 

flags

GstLockFlags

 
+
+
+

Returns

+

TRUE if object +could be locked.

+
+
+
+
+

gst_mini_object_unlock ()

+
void
+gst_mini_object_unlock (GstMiniObject *object,
+                        GstLockFlags flags);
+

Unlock the mini-object with the specified access mode in flags +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

the mini-object to unlock

 

flags

GstLockFlags

 
+
+
+
+
+

gst_mini_object_is_writable ()

+
gboolean
+gst_mini_object_is_writable (const GstMiniObject *mini_object);
+

If mini_object + has the LOCKABLE flag set, check if the current EXCLUSIVE +lock on object + is the only one, this means that changes to the object will +not be visible to any other object.

+

If the LOCKABLE flag is not set, check if the refcount of mini_object + is +exactly 1, meaning that no other reference exists to the object and that the +object is therefore writable.

+

Modification of a mini-object should only be done after verifying that it +is writable.

+
+

Parameters

+
+++++ + + + + + +

mini_object

the mini-object to check

 
+
+
+

Returns

+

TRUE if the object is writable.

+
+
+
+
+

gst_mini_object_make_writable ()

+
GstMiniObject *
+gst_mini_object_make_writable (GstMiniObject *mini_object);
+

Checks if a mini-object is writable. If not, a writable copy is made and +returned. This gives away the reference to the original mini object, +and returns a reference to the new object.

+

MT safe

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

mini_object

the mini-object to make writable.

[transfer full]
+
+
+

Returns

+

a mini-object (possibly the same pointer) that +is writable.

+

[transfer full]

+
+
+
+
+

gst_mini_object_copy ()

+
GstMiniObject *
+gst_mini_object_copy (const GstMiniObject *mini_object);
+

Creates a copy of the mini-object.

+

MT safe

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

mini_object

the mini-object to copy

 
+
+
+

Returns

+

the new mini-object if copying is +possible, NULL otherwise.

+

[transfer full][nullable]

+
+
+
+
+

gst_mini_object_set_qdata ()

+
void
+gst_mini_object_set_qdata (GstMiniObject *object,
+                           GQuark quark,
+                           gpointer data,
+                           GDestroyNotify destroy);
+

This sets an opaque, named pointer on a miniobject. +The name is specified through a GQuark (retrieved e.g. via +g_quark_from_static_string()), and the pointer +can be gotten back from the object + with gst_mini_object_get_qdata() +until the object + is disposed. +Setting a previously set user data pointer, overrides (frees) +the old pointer set, using NULL as pointer essentially +removes the data stored.

+

destroy + may be specified which is called with data + as argument +when the object + is disposed, or the data is being overwritten by +a call to gst_mini_object_set_qdata() with the same quark +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

object

a GstMiniObject

 

quark

A GQuark, naming the user data pointer

 

data

An opaque user data pointer

 

destroy

Function to invoke with data +as argument, when data +needs to be freed

 
+
+
+
+
+

gst_mini_object_get_qdata ()

+
gpointer
+gst_mini_object_get_qdata (GstMiniObject *object,
+                           GQuark quark);
+

This function gets back user data pointers stored via +gst_mini_object_set_qdata().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

The GstMiniObject to get a stored user data pointer from

 

quark

A GQuark, naming the user data pointer

 
+
+
+

Returns

+

The user data pointer set, or +NULL.

+

[transfer none][nullable]

+
+
+
+
+

gst_mini_object_steal_qdata ()

+
gpointer
+gst_mini_object_steal_qdata (GstMiniObject *object,
+                             GQuark quark);
+

This function gets back user data pointers stored via gst_mini_object_set_qdata() +and removes the data from object + without invoking its destroy() function (if +any was set).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

object

The GstMiniObject to get a stored user data pointer from

 

quark

A GQuark, naming the user data pointer

 
+
+
+

Returns

+

The user data pointer set, or +NULL.

+

[transfer full][nullable]

+
+
+
+
+

gst_mini_object_replace ()

+
gboolean
+gst_mini_object_replace (GstMiniObject **olddata,
+                         GstMiniObject *newdata);
+

Atomically modifies a pointer to point to a new mini-object. +The reference count of olddata + is decreased and the reference count of +newdata + is increased.

+

Either newdata + and the value pointed to by olddata + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

olddata

pointer to a pointer to a +mini-object to be replaced.

[inout][transfer full][nullable]

newdata

pointer to new mini-object.

[allow-none]
+
+
+

Returns

+

TRUE if newdata +was different from olddata +

+
+
+
+
+

gst_mini_object_take ()

+
gboolean
+gst_mini_object_take (GstMiniObject **olddata,
+                      GstMiniObject *newdata);
+

Modifies a pointer to point to a new mini-object. The modification +is done atomically. This version is similar to gst_mini_object_replace() +except that it does not increase the refcount of newdata + and thus +takes ownership of newdata +.

+

Either newdata + and the value pointed to by olddata + may be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

olddata

pointer to a pointer to a mini-object to +be replaced.

[inout][transfer full]

newdata

pointer to new mini-object

 
+
+
+

Returns

+

TRUE if newdata +was different from olddata +

+
+
+
+
+

gst_mini_object_steal ()

+
GstMiniObject *
+gst_mini_object_steal (GstMiniObject **olddata);
+

Replace the current GstMiniObject pointer to by olddata + with NULL and +return the old value.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

olddata

pointer to a pointer to a mini-object to +be stolen.

[inout][transfer full]
+
+
+

Returns

+

the GstMiniObject at oldata +.

+

[nullable]

+
+
+
+
+

Types and Values

+
+

struct GstMiniObject

+
struct GstMiniObject {
+  GType   type;
+
+  gint    refcount;
+  gint    lockstate;
+  guint   flags;
+
+  GstMiniObjectCopyFunction copy;
+  GstMiniObjectDisposeFunction dispose;
+  GstMiniObjectFreeFunction free;
+};
+
+

Base class for refcounted lightweight objects.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GType type;

the GType of the object

 

gint refcount;

atomic refcount

 

gint lockstate;

atomic state of the locks

 

guint flags;

extra flags.

 

GstMiniObjectCopyFunction copy;

a copy function

 

GstMiniObjectDisposeFunction dispose;

a dispose function

 

GstMiniObjectFreeFunction free;

the free function

 
+
+
+
+
+

enum GstMiniObjectFlags

+

Flags for the mini object

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_MINI_OBJECT_FLAG_LOCKABLE

+

the object can be locked and unlocked with +gst_mini_object_lock() and gst_mini_object_unlock().

+
 

GST_MINI_OBJECT_FLAG_LOCK_READONLY

+

the object is permanently locked in +READONLY mode. Only read locks can be performed on the object.

+
 

GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED

+

the object is expected to stay alive +even after gst_deinit() has been called and so should be ignored by leak +detection tools. (Since 1.10)

+
 

GST_MINI_OBJECT_FLAG_LAST

+

first flag that can be used by subclasses.

+
 
+
+
+
+
+

enum GstLockFlags

+

Flags used when locking miniobjects

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_LOCK_FLAG_READ

+

lock for read access

+
 

GST_LOCK_FLAG_WRITE

+

lock for write access

+
 

GST_LOCK_FLAG_EXCLUSIVE

+

lock for exclusive access

+
 

GST_LOCK_FLAG_LAST

+

first flag that can be used for custom purposes

+
 
+
+
+
+
+

GST_LOCK_FLAG_READWRITE

+
#define GST_LOCK_FLAG_READWRITE  ((GstLockFlags) (GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE))
+
+

GstLockFlags value alias for GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstParamSpec.html b/docs/gst/html/gstreamer-GstParamSpec.html new file mode 100644 index 0000000..55254f0 --- /dev/null +++ b/docs/gst/html/gstreamer-GstParamSpec.html @@ -0,0 +1,385 @@ + + + + +GstParamSpec: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstParamSpec

+

GstParamSpec — GParamSpec implementations specific +to GStreamer

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GParamSpec * + +gst_param_spec_fraction () +
+GParamSpec * + +gst_param_spec_array () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineGST_PARAM_CONTROLLABLE
#defineGST_PARAM_USER_SHIFT
#defineGST_PARAM_MUTABLE_PAUSED
#defineGST_PARAM_MUTABLE_PLAYING
#defineGST_PARAM_MUTABLE_READY
structGstParamSpecFraction
structGstParamSpecArray
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

GParamSpec implementations specific to GStreamer.

+
+
+

Functions

+
+

gst_param_spec_fraction ()

+
GParamSpec *
+gst_param_spec_fraction (const gchar *name,
+                         const gchar *nick,
+                         const gchar *blurb,
+                         gint min_num,
+                         gint min_denom,
+                         gint max_num,
+                         gint max_denom,
+                         gint default_num,
+                         gint default_denom,
+                         GParamFlags flags);
+

This function creates a fraction GParamSpec for use by objects/elements +that want to expose properties of fraction type. This function is typically +used in connection with g_object_class_install_property() in a GObjects's +instance_init function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

canonical name of the property specified

 

nick

nick name for the property specified

 

blurb

description of the property specified

 

min_num

minimum value (fraction numerator)

 

min_denom

minimum value (fraction denominator)

 

max_num

maximum value (fraction numerator)

 

max_denom

maximum value (fraction denominator)

 

default_num

default value (fraction numerator)

 

default_denom

default value (fraction denominator)

 

flags

flags for the property specified

 
+
+
+

Returns

+

a newly created parameter specification.

+

[transfer full][nullable]

+
+
+
+
+

gst_param_spec_array ()

+
GParamSpec *
+gst_param_spec_array (const gchar *name,
+                      const gchar *nick,
+                      const gchar *blurb,
+                      GParamSpec *element_spec,
+                      GParamFlags flags);
+

This function creates a GstArray GParamSpec for use by objects/elements +that want to expose properties of GstArray type. This function is +typically * used in connection with g_object_class_install_property() in a +GObjects's instance_init function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

canonical name of the property specified

 

nick

nick name for the property specified

 

blurb

description of the property specified

 

element_spec

GParamSpec of the array

 

flags

flags for the property specified

 
+
+
+

Returns

+

a newly created parameter specification.

+

[transfer full]

+
+

Since: 1.14

+
+
+
+

Types and Values

+
+

GST_PARAM_CONTROLLABLE

+
#define GST_PARAM_CONTROLLABLE (1 << (G_PARAM_USER_SHIFT + 1))
+
+

Use this flag on GObject properties to signal they can make sense to be. +controlled over time. This hint is used by the GstController.

+
+
+
+

GST_PARAM_USER_SHIFT

+
#define GST_PARAM_USER_SHIFT (1 << (G_PARAM_USER_SHIFT + 8))
+
+

Bits based on GST_PARAM_USER_SHIFT can be used by 3rd party applications.

+
+
+
+

GST_PARAM_MUTABLE_PAUSED

+
#define GST_PARAM_MUTABLE_PAUSED  (1 << (G_PARAM_USER_SHIFT + 3))
+
+

Use this flag on GObject properties of GstElements to indicate that +they can be changed when the element is in the PAUSED or lower state. +This flag implies GST_PARAM_MUTABLE_READY.

+
+
+
+

GST_PARAM_MUTABLE_PLAYING

+
#define GST_PARAM_MUTABLE_PLAYING  (1 << (G_PARAM_USER_SHIFT + 4))
+
+

Use this flag on GObject properties of GstElements to indicate that +they can be changed when the element is in the PLAYING or lower state. +This flag implies GST_PARAM_MUTABLE_PAUSED.

+
+
+
+

GST_PARAM_MUTABLE_READY

+
#define GST_PARAM_MUTABLE_READY  (1 << (G_PARAM_USER_SHIFT + 2))
+
+

Use this flag on GObject properties of GstElements to indicate that +they can be changed when the element is in the READY or lower state.

+
+
+
+

struct GstParamSpecFraction

+
struct GstParamSpecFraction {
+  GParamSpec    parent_instance;
+
+  gint          min_num, min_den;
+  gint          max_num, max_den;
+  gint          def_num, def_den;
+};
+
+

A GParamSpec derived structure that contains the meta data for fractional +properties.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gint min_num;

minimal numerator

 

gint min_den;

minimal denominator

 

gint max_num;

maximal numerator

 

gint max_den;

maximal denominator

 

gint def_num;

default numerator

 

gint def_den;

default denominator

 
+
+
+
+
+

struct GstParamSpecArray

+
struct GstParamSpecArray {
+  GParamSpec    parent_instance;
+
+  GParamSpec * element_spec;
+};
+
+

A GParamSpec derived structure that contains the meta data for fractional +properties.

+
+

Members

+
+++++ + + + + + +

GParamSpec *element_spec;

  
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstParse.html b/docs/gst/html/gstreamer-GstParse.html new file mode 100644 index 0000000..4db81e2 --- /dev/null +++ b/docs/gst/html/gstreamer-GstParse.html @@ -0,0 +1,745 @@ + + + + +GstParse: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstParse

+

GstParse — Get a pipeline from a text pipeline description

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GQuark + +gst_parse_error_quark () +
+GstElement * + +gst_parse_launch () +
+GstElement * + +gst_parse_launch_full () +
+GstElement * + +gst_parse_launchv () +
+GstElement * + +gst_parse_launchv_full () +
+GstElement * + +gst_parse_bin_from_description () +
+GstElement * + +gst_parse_bin_from_description_full () +
+GstParseContext * + +gst_parse_context_new () +
+GstParseContext * + +gst_parse_context_copy () +
+void + +gst_parse_context_free () +
+gchar ** + +gst_parse_context_get_missing_elements () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
#defineGST_PARSE_ERROR
enumGstParseError
 GstParseContext
enumGstParseFlags
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── GstParseContext
+
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

These function allow to create a pipeline based on the syntax used in the +gst-launch-1.0 utility (see man-page for syntax documentation).

+

Please note that these functions take several measures to create +somewhat dynamic pipelines. Due to that such pipelines are not always +reusable (set the state to NULL and back to PLAYING).

+
+
+

Functions

+
+

gst_parse_error_quark ()

+
GQuark
+gst_parse_error_quark (void);
+

Get the error quark used by the parsing subsystem.

+
+

Returns

+

the quark of the parse errors.

+
+
+
+
+

gst_parse_launch ()

+
GstElement *
+gst_parse_launch (const gchar *pipeline_description,
+                  GError **error);
+

Create a new pipeline based on command line syntax. +Please note that you might get a return value that is not NULL even though +the error + is set. In this case there was a recoverable parsing error and you +can try to play the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pipeline_description

the command line describing the pipeline

 

error

the error message in case of an erroneous pipeline.

 
+
+
+

Returns

+

a new element on success, NULL on +failure. If more than one toplevel element is specified by the +pipeline_description +, all elements are put into a GstPipeline, which +than is returned.

+

[transfer floating][nullable]

+
+
+
+
+

gst_parse_launch_full ()

+
GstElement *
+gst_parse_launch_full (const gchar *pipeline_description,
+                       GstParseContext *context,
+                       GstParseFlags flags,
+                       GError **error);
+

Create a new pipeline based on command line syntax. +Please note that you might get a return value that is not NULL even though +the error + is set. In this case there was a recoverable parsing error and you +can try to play the pipeline.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pipeline_description

the command line describing the pipeline

 

context

a parse context allocated with +gst_parse_context_new(), or NULL.

[allow-none]

flags

parsing options, or GST_PARSE_FLAG_NONE

 

error

the error message in case of an erroneous pipeline.

 
+
+
+

Returns

+

a new element on success, NULL on +failure. If more than one toplevel element is specified by the +pipeline_description +, all elements are put into a GstPipeline, which +then is returned (unless the GST_PARSE_FLAG_PLACE_IN_BIN flag is set, in +which case they are put in a GstBin instead).

+

[transfer floating][nullable]

+
+
+
+
+

gst_parse_launchv ()

+
GstElement *
+gst_parse_launchv (const gchar **argv,
+                   GError **error);
+

Create a new element based on command line syntax. +error + will contain an error message if an erroneous pipeline is specified. +An error does not mean that the pipeline could not be constructed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

argv

null-terminated array of arguments.

[in][array zero-terminated=1]

error

pointer to a GError

 
+
+
+

Returns

+

a new element on success and NULL +on failure.

+

[transfer floating][nullable]

+
+
+
+
+

gst_parse_launchv_full ()

+
GstElement *
+gst_parse_launchv_full (const gchar **argv,
+                        GstParseContext *context,
+                        GstParseFlags flags,
+                        GError **error);
+

Create a new element based on command line syntax. +error + will contain an error message if an erroneous pipeline is specified. +An error does not mean that the pipeline could not be constructed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

argv

null-terminated array of arguments.

[in][array zero-terminated=1]

context

a parse context allocated with +gst_parse_context_new(), or NULL.

[allow-none]

flags

parsing options, or GST_PARSE_FLAG_NONE

 

error

pointer to a GError (which must be initialised to NULL)

 
+
+
+

Returns

+

a new element on success; on +failure, either NULL or a partially-constructed bin or element will be +returned and error +will be set (unless you passed +GST_PARSE_FLAG_FATAL_ERRORS in flags +, then NULL will always be returned +on failure).

+

[transfer floating][nullable]

+
+
+
+
+

gst_parse_bin_from_description ()

+
GstElement *
+gst_parse_bin_from_description (const gchar *bin_description,
+                                gboolean ghost_unlinked_pads,
+                                GError **err);
+

This is a convenience wrapper around gst_parse_launch() to create a +GstBin from a gst-launch-style pipeline description. See +gst_parse_launch() and the gst-launch man page for details about the +syntax. Ghost pads on the bin for unlinked source or sink pads +within the bin can automatically be created (but only a maximum of +one ghost pad for each direction will be created; if you expect +multiple unlinked source pads or multiple unlinked sink pads +and want them all ghosted, you will have to create the ghost pads +yourself).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

bin_description

command line describing the bin

 

ghost_unlinked_pads

whether to automatically create ghost pads +for unlinked source or sink pads within the bin

 

err

where to store the error message in case of an error, or NULL

 
+
+
+

Returns

+

a +newly-created bin, or NULL if an error occurred.

+

[transfer floating][type Gst.Bin][nullable]

+
+
+
+
+

gst_parse_bin_from_description_full ()

+
GstElement *
+gst_parse_bin_from_description_full (const gchar *bin_description,
+                                     gboolean ghost_unlinked_pads,
+                                     GstParseContext *context,
+                                     GstParseFlags flags,
+                                     GError **err);
+

This is a convenience wrapper around gst_parse_launch() to create a +GstBin from a gst-launch-style pipeline description. See +gst_parse_launch() and the gst-launch man page for details about the +syntax. Ghost pads on the bin for unlinked source or sink pads +within the bin can automatically be created (but only a maximum of +one ghost pad for each direction will be created; if you expect +multiple unlinked source pads or multiple unlinked sink pads +and want them all ghosted, you will have to create the ghost pads +yourself).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

bin_description

command line describing the bin

 

ghost_unlinked_pads

whether to automatically create ghost pads +for unlinked source or sink pads within the bin

 

context

a parse context allocated with +gst_parse_context_new(), or NULL.

[transfer none][allow-none]

flags

parsing options, or GST_PARSE_FLAG_NONE

 

err

where to store the error message in case of an error, or NULL

 
+
+
+

Returns

+

a newly-created +element, which is guaranteed to be a bin unless +GST_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or NULL if an error +occurred.

+

[transfer floating][type Gst.Element][nullable]

+
+
+
+
+

gst_parse_context_new ()

+
GstParseContext *
+gst_parse_context_new (void);
+

Allocates a parse context for use with gst_parse_launch_full() or +gst_parse_launchv_full().

+

Free-function: gst_parse_context_free

+
+

Returns

+

a newly-allocated parse context. Free +with gst_parse_context_free() when no longer needed.

+

[transfer full][nullable]

+
+
+
+
+

gst_parse_context_copy ()

+
GstParseContext *
+gst_parse_context_copy (const GstParseContext *context);
+

Copies the context +.

+
+

Parameters

+
+++++ + + + + + +

context

a GstParseContext

 
+
+
+

Returns

+

A copied GstParseContext.

+

[transfer full][nullable]

+
+
+
+
+

gst_parse_context_free ()

+
void
+gst_parse_context_free (GstParseContext *context);
+

Frees a parse context previously allocated with gst_parse_context_new().

+
+

Parameters

+
+++++ + + + + + +

context

a GstParseContext.

[transfer full]
+
+
+
+
+

gst_parse_context_get_missing_elements ()

+
gchar **
+gst_parse_context_get_missing_elements
+                               (GstParseContext *context);
+

Retrieve missing elements from a previous run of gst_parse_launch_full() +or gst_parse_launchv_full(). Will only return results if an error code +of GST_PARSE_ERROR_NO_SUCH_ELEMENT was returned.

+
+

Parameters

+
+++++ + + + + + +

context

a GstParseContext

 
+
+
+

Returns

+

a +NULL-terminated array of element factory name strings of missing +elements. Free with g_strfreev() when no longer needed.

+

[transfer full][array zero-terminated=1][element-type gchar*][nullable]

+
+
+
+
+

Types and Values

+
+

GST_PARSE_ERROR

+
#define GST_PARSE_ERROR gst_parse_error_quark ()
+
+

Get access to the error quark of the parse subsystem.

+
+
+
+

enum GstParseError

+

The different parsing errors that can occur.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_PARSE_ERROR_SYNTAX

+

A syntax error occurred.

+
 

GST_PARSE_ERROR_NO_SUCH_ELEMENT

+

The description contained an unknown element

+
 

GST_PARSE_ERROR_NO_SUCH_PROPERTY

+

An element did not have a specified property

+
 

GST_PARSE_ERROR_LINK

+

There was an error linking two pads.

+
 

GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY

+

There was an error setting a property

+
 

GST_PARSE_ERROR_EMPTY_BIN

+

An empty bin was specified.

+
 

GST_PARSE_ERROR_EMPTY

+

An empty description was specified

+
 

GST_PARSE_ERROR_DELAYED_LINK

+

A delayed link did not get resolved.

+
 
+
+
+
+
+

GstParseContext

+
typedef struct _GstParseContext GstParseContext;
+

Opaque structure.

+
+
+
+

enum GstParseFlags

+

Parsing options.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_PARSE_FLAG_NONE

+

Do not use any special parsing options.

+
 

GST_PARSE_FLAG_FATAL_ERRORS

+

Always return NULL when an error occurs + (default behaviour is to return partially constructed bins or elements + in some cases)

+
 

GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS

+

If a bin only has a single element, + just return the element.

+
 

GST_PARSE_FLAG_PLACE_IN_BIN

+

If more than one toplevel element is described + by the pipeline description string, put them in a GstBin instead of a + GstPipeline. (Since 1.10)

+
 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstPoll.html b/docs/gst/html/gstreamer-GstPoll.html new file mode 100644 index 0000000..32e534d --- /dev/null +++ b/docs/gst/html/gstreamer-GstPoll.html @@ -0,0 +1,991 @@ + + + + +GstPoll: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPoll

+

GstPoll — Keep track of file descriptors and make it possible + to wait on them in a cancellable way

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +gst_poll_add_fd () +
+gboolean + +gst_poll_fd_can_read () +
+gboolean + +gst_poll_fd_can_write () +
+gboolean + +gst_poll_fd_ctl_read () +
+gboolean + +gst_poll_fd_ctl_write () +
+gboolean + +gst_poll_fd_has_closed () +
+gboolean + +gst_poll_fd_has_error () +
+void + +gst_poll_fd_ignored () +
+void + +gst_poll_fd_init () +
+void + +gst_poll_free () +
+GstPoll * + +gst_poll_new () +
+GstPoll * + +gst_poll_new_timer () +
+void + +gst_poll_get_read_gpollfd () +
+gboolean + +gst_poll_remove_fd () +
+void + +gst_poll_restart () +
+gboolean + +gst_poll_set_controllable () +
+void + +gst_poll_set_flushing () +
+gint + +gst_poll_wait () +
+gboolean + +gst_poll_read_control () +
+gboolean + +gst_poll_write_control () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
 GstPoll
 GstPollFD
#defineGST_POLL_FD_INIT
+
+
+

Includes

+
#include <gst/gst.h>
+
+
+
+

Description

+

A GstPoll keeps track of file descriptors much like fd_set (used with +select()) or a struct pollfd array (used with poll()). Once created with +gst_poll_new(), the set can be used to wait for file descriptors to be +readable and/or writable. It is possible to make this wait be controlled +by specifying TRUE for the controllable + flag when creating the set (or +later calling gst_poll_set_controllable()).

+

New file descriptors are added to the set using gst_poll_add_fd(), and +removed using gst_poll_remove_fd(). Controlling which file descriptors +should be waited for to become readable and/or writable are done using +gst_poll_fd_ctl_read() and gst_poll_fd_ctl_write().

+

Use gst_poll_wait() to wait for the file descriptors to actually become +readable and/or writable, or to timeout if no file descriptor is available +in time. The wait can be controlled by calling gst_poll_restart() and +gst_poll_set_flushing().

+

Once the file descriptor set has been waited for, one can use +gst_poll_fd_has_closed() to see if the file descriptor has been closed, +gst_poll_fd_has_error() to see if it has generated an error, +gst_poll_fd_can_read() to see if it is possible to read from the file +descriptor, and gst_poll_fd_can_write() to see if it is possible to +write to it.

+
+
+

Functions

+
+

gst_poll_add_fd ()

+
gboolean
+gst_poll_add_fd (GstPoll *set,
+                 GstPollFD *fd);
+

Add a file descriptor to the file descriptor set.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the file descriptor was successfully added to the set.

+
+
+
+
+

gst_poll_fd_can_read ()

+
gboolean
+gst_poll_fd_can_read (const GstPoll *set,
+                      GstPollFD *fd);
+

Check if fd + in set + has data to be read.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the descriptor has data to be read.

+
+
+
+
+

gst_poll_fd_can_write ()

+
gboolean
+gst_poll_fd_can_write (const GstPoll *set,
+                       GstPollFD *fd);
+

Check if fd + in set + can be used for writing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the descriptor can be used for writing.

+
+
+
+
+

gst_poll_fd_ctl_read ()

+
gboolean
+gst_poll_fd_ctl_read (GstPoll *set,
+                      GstPollFD *fd,
+                      gboolean active);
+

Control whether the descriptor fd + in set + will be monitored for +readability.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 

active

a new status.

 
+
+
+

Returns

+

TRUE if the descriptor was successfully updated.

+
+
+
+
+

gst_poll_fd_ctl_write ()

+
gboolean
+gst_poll_fd_ctl_write (GstPoll *set,
+                       GstPollFD *fd,
+                       gboolean active);
+

Control whether the descriptor fd + in set + will be monitored for +writability.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 

active

a new status.

 
+
+
+

Returns

+

TRUE if the descriptor was successfully updated.

+
+
+
+
+

gst_poll_fd_has_closed ()

+
gboolean
+gst_poll_fd_has_closed (const GstPoll *set,
+                        GstPollFD *fd);
+

Check if fd + in set + has closed the connection.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the connection was closed.

+
+
+
+
+

gst_poll_fd_has_error ()

+
gboolean
+gst_poll_fd_has_error (const GstPoll *set,
+                       GstPollFD *fd);
+

Check if fd + in set + has an error.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the descriptor has an error.

+
+
+
+
+

gst_poll_fd_ignored ()

+
void
+gst_poll_fd_ignored (GstPoll *set,
+                     GstPollFD *fd);
+

Mark fd + as ignored so that the next call to gst_poll_wait() will yield +the same result for fd + as last time. This function must be called if no +operation (read/write/recv/send/etc.) will be performed on fd + before +the next call to gst_poll_wait().

+

The reason why this is needed is because the underlying implementation +might not allow querying the fd more than once between calls to one of +the re-enabling operations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+
+
+

gst_poll_fd_init ()

+
void
+gst_poll_fd_init (GstPollFD *fd);
+

Initializes fd +. Alternatively you can initialize it with +GST_POLL_FD_INIT.

+
+

Parameters

+
+++++ + + + + + +

fd

a GstPollFD

 
+
+
+
+
+

gst_poll_free ()

+
void
+gst_poll_free (GstPoll *set);
+

Free a file descriptor set.

+
+

Parameters

+
+++++ + + + + + +

set

a file descriptor set.

[transfer full]
+
+
+
+
+

gst_poll_new ()

+
GstPoll *
+gst_poll_new (gboolean controllable);
+

Create a new file descriptor set. If controllable +, it +is possible to restart or flush a call to gst_poll_wait() with +gst_poll_restart() and gst_poll_set_flushing() respectively.

+

Free-function: gst_poll_free

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

controllable

whether it should be possible to control a wait.

 
+
+
+

Returns

+

a new GstPoll, or NULL in +case of an error. Free with gst_poll_free().

+

[transfer full][nullable]

+
+
+
+
+

gst_poll_new_timer ()

+
GstPoll *
+gst_poll_new_timer (void);
+

Create a new poll object that can be used for scheduling cancellable +timeouts.

+

A timeout is performed with gst_poll_wait(). Multiple timeouts can be +performed from different threads.

+

Free-function: gst_poll_free

+

[skip]

+
+

Returns

+

a new GstPoll, or NULL in +case of an error. Free with gst_poll_free().

+

[transfer full][nullable]

+
+
+
+
+

gst_poll_get_read_gpollfd ()

+
void
+gst_poll_get_read_gpollfd (GstPoll *set,
+                           GPollFD *fd);
+

Get a GPollFD for the reading part of the control socket. This is useful when +integrating with a GSource and GMainLoop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a GstPoll

 

fd

a GPollFD

 
+
+
+
+
+

gst_poll_remove_fd ()

+
gboolean
+gst_poll_remove_fd (GstPoll *set,
+                    GstPollFD *fd);
+

Remove a file descriptor from the file descriptor set.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a file descriptor set.

 

fd

a file descriptor.

 
+
+
+

Returns

+

TRUE if the file descriptor was successfully removed from the set.

+
+
+
+
+

gst_poll_restart ()

+
void
+gst_poll_restart (GstPoll *set);
+

Restart any gst_poll_wait() that is in progress. This function is typically +used after adding or removing descriptors to set +.

+

If set + is not controllable, then this call will have no effect.

+

This function only works for non-timer GstPoll objects created with +gst_poll_new().

+
+

Parameters

+
+++++ + + + + + +

set

a GstPoll.

 
+
+
+
+
+

gst_poll_set_controllable ()

+
gboolean
+gst_poll_set_controllable (GstPoll *set,
+                           gboolean controllable);
+

When controllable + is TRUE, this function ensures that future calls to +gst_poll_wait() will be affected by gst_poll_restart() and +gst_poll_set_flushing().

+

This function only works for non-timer GstPoll objects created with +gst_poll_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a GstPoll.

 

controllable

new controllable state.

 
+
+
+

Returns

+

TRUE if the controllability of set +could be updated.

+
+
+
+
+

gst_poll_set_flushing ()

+
void
+gst_poll_set_flushing (GstPoll *set,
+                       gboolean flushing);
+

When flushing + is TRUE, this function ensures that current and future calls +to gst_poll_wait() will return -1, with errno set to EBUSY.

+

Unsetting the flushing state will restore normal operation of set +.

+

This function only works for non-timer GstPoll objects created with +gst_poll_new().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a GstPoll.

 

flushing

new flushing state.

 
+
+
+
+
+

gst_poll_wait ()

+
gint
+gst_poll_wait (GstPoll *set,
+               GstClockTime timeout);
+

Wait for activity on the file descriptors in set +. This function waits up to +the specified timeout +. A timeout of GST_CLOCK_TIME_NONE waits forever.

+

For GstPoll objects created with gst_poll_new(), this function can only be +called from a single thread at a time. If called from multiple threads, +-1 will be returned with errno set to EPERM.

+

This is not true for timer GstPoll objects created with +gst_poll_new_timer(), where it is allowed to have multiple threads waiting +simultaneously.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

set

a GstPoll.

 

timeout

a timeout in nanoseconds.

 
+
+
+

Returns

+

The number of GstPollFD in set +that have activity or 0 when no +activity was detected after timeout +. If an error occurs, -1 is returned +and errno is set.

+
+
+
+
+

gst_poll_read_control ()

+
gboolean
+gst_poll_read_control (GstPoll *set);
+

Read a byte from the control socket of the controllable set +.

+

This function only works for timer GstPoll objects created with +gst_poll_new_timer().

+
+

Parameters

+
+++++ + + + + + +

set

a GstPoll.

 
+
+
+

Returns

+

TRUE on success. FALSE when when there was no byte to read or +reading the byte failed. If there was no byte to read, and only then, errno +will contain EWOULDBLOCK or EAGAIN. For all other values of errno this always signals a +critical error.

+
+
+
+
+

gst_poll_write_control ()

+
gboolean
+gst_poll_write_control (GstPoll *set);
+

Write a byte to the control socket of the controllable set +. +This function is mostly useful for timer GstPoll objects created with +gst_poll_new_timer().

+

It will make any current and future gst_poll_wait() function return with +1, meaning the control socket is set. After an equal amount of calls to +gst_poll_read_control() have been performed, calls to gst_poll_wait() will +block again until their timeout expired.

+

This function only works for timer GstPoll objects created with +gst_poll_new_timer().

+
+

Parameters

+
+++++ + + + + + +

set

a GstPoll.

 
+
+
+

Returns

+

TRUE on success. FALSE when when the byte could not be written. +errno contains the detailed error code but will never be EAGAIN, EINTR or +EWOULDBLOCK. FALSE always signals a critical error.

+
+
+
+
+

Types and Values

+
+

GstPoll

+
typedef struct _GstPoll GstPoll;
+

A set of file/network descriptors.

+
+
+
+

GstPollFD

+
typedef struct {
+  int fd;
+} GstPollFD;
+
+

A file descriptor object.

+
+

Members

+
+++++ + + + + + +

int fd;

a file descriptor

 
+
+
+
+
+

GST_POLL_FD_INIT

+
#define GST_POLL_FD_INIT  { -1, -1 }
+
+

A GstPollFD must be initialized with this macro, before it can be +used. This macro can used be to initialize a variable, but it cannot +be assigned to a variable. In that case you have to use +gst_poll_fd_init().

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstProtectionMeta.html b/docs/gst/html/gstreamer-GstProtectionMeta.html new file mode 100644 index 0000000..1e9e682 --- /dev/null +++ b/docs/gst/html/gstreamer-GstProtectionMeta.html @@ -0,0 +1,283 @@ + + + + +GstProtection: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstProtection

+

GstProtection — Functions and classes to support encrypted streams.

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstProtectionMeta
#defineGST_PROTECTION_SYSTEM_ID_CAPS_FIELD
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

The GstProtectionMeta class enables the information needed to decrypt a +GstBuffer to be attached to that buffer.

+

Typically, a demuxer element would attach GstProtectionMeta objects +to the buffers that it pushes downstream. The demuxer would parse the +protection information for a video/audio frame from its input data and use +this information to populate the GstStructure info + field, +which is then encapsulated in a GstProtectionMeta object and attached to +the corresponding output buffer using the gst_buffer_add_protection_meta() +function. The information in this attached GstProtectionMeta would be +used by a downstream decrypter element to recover the original unencrypted +frame.

+
+
+

Functions

+
+

gst_buffer_add_protection_meta ()

+
GstProtectionMeta *
+gst_buffer_add_protection_meta (GstBuffer *buffer,
+                                GstStructure *info);
+

Attaches protection metadata to a GstBuffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

GstBuffer holding an encrypted sample, to which protection +metadata should be added.

 

info

a GstStructure holding cryptographic +information relating to the sample contained in buffer +. This +function takes ownership of info +.

[transfer full]
+
+
+

Returns

+

a pointer to the added GstProtectionMeta if successful; NULL if +unsuccessful.

+

[transfer none]

+
+

Since: 1.6

+
+
+
+

gst_buffer_get_protection_meta()

+
#define             gst_buffer_get_protection_meta(b)
+
+
+
+

gst_protection_select_system ()

+
const gchar *
+gst_protection_select_system (const gchar **system_identifiers);
+

Iterates the supplied list of UUIDs and checks the GstRegistry for +an element that supports one of the supplied UUIDs. If more than one +element matches, the system ID of the highest ranked element is selected.

+
+

Parameters

+
+++++ + + + + + +

system_identifiers

A null terminated array of strings +that contains the UUID values of each protection system that is to be +checked.

[transfer none][array zero-terminated=1]
+
+
+

Returns

+

One of the strings from +system_identifiers +that indicates the highest ranked element that +implements the protection system indicated by that system ID, or NULL if no +element has been found.

+

[transfer none][nullable]

+
+

Since: 1.6

+
+
+
+

gst_protection_filter_systems_by_available_decryptors ()

+
gchar **
+gst_protection_filter_systems_by_available_decryptors
+                               (const gchar **system_identifiers);
+

Iterates the supplied list of UUIDs and checks the GstRegistry for +all the decryptors supporting one of the supplied UUIDs.

+
+

Parameters

+
+++++ + + + + + +

system_identifiers

A null terminated array of strings +that contains the UUID values of each protection system that is to be +checked.

[transfer none]
+
+
+

Returns

+

A null terminated array containing all +the system_identifiers +supported by the set of available decryptors, or +NULL if no matches were found.

+

[transfer full][nullable]

+
+

Since: 1.14

+
+
+
+

Types and Values

+
+

struct GstProtectionMeta

+
struct GstProtectionMeta {
+  GstMeta meta;
+
+  GstStructure *info;
+};
+
+

Metadata type that holds information about a sample from a protection-protected +track, including the information needed to decrypt it (if it is encrypted).

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMeta meta;

the parent GstMeta.

 

GstStructure *info;

the cryptographic information needed to decrypt the sample.

 
+
+

Since: 1.6

+
+
+
+

GST_PROTECTION_SYSTEM_ID_CAPS_FIELD

+
#define GST_PROTECTION_SYSTEM_ID_CAPS_FIELD "protection-system"
+
+

The field name in a GstCaps that is used to signal the UUID of the protection +system.

+

Since: 1.6

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstStream.html b/docs/gst/html/gstreamer-GstStream.html new file mode 100644 index 0000000..0d57c2f --- /dev/null +++ b/docs/gst/html/gstreamer-GstStream.html @@ -0,0 +1,651 @@ + + + + +GstStreams: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstStreams

+

GstStreams — Base class for stream objects

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstStream * + +gst_stream_new () +
+GstCaps * + +gst_stream_get_caps () +
+GstStreamFlags + +gst_stream_get_stream_flags () +
const gchar * + +gst_stream_get_stream_id () +
+GstStreamType + +gst_stream_get_stream_type () +
+GstTagList * + +gst_stream_get_tags () +
+void + +gst_stream_set_caps () +
+void + +gst_stream_set_stream_flags () +
+void + +gst_stream_set_stream_type () +
+void + +gst_stream_set_tags () +
const gchar * + +gst_stream_type_get_name () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstStream
structGstStreamClass
enumGstStreamType
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

A GstStream is a high-level object defining a stream of data which is, or +can be, present in a GstPipeline.

+

It is defined by a unique identifier, a "Stream ID". A GstStream does not +automatically imply the stream is present within a pipeline or element.

+

Any element that can introduce new streams in a pipeline should create the +appropriate GstStream object, and can convey that object via the +GST_EVENT_STREAM_START event and/or the GstStreamCollection.

+

Elements that do not modify the nature of the stream can add extra information +on it (such as enrich the GstCaps, or GstTagList). This is typically done +by parsing elements.

+
+
+

Functions

+
+

gst_stream_new ()

+
GstStream *
+gst_stream_new (const gchar *stream_id,
+                GstCaps *caps,
+                GstStreamType type,
+                GstStreamFlags flags);
+

Create a new GstStream for the given stream_id +, caps +, type + +and flags +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

stream_id

the id for the new stream. If NULL, +a new one will be automatically generated.

[allow-none]

caps

the GstCaps of the stream.

[allow-none][transfer none]

type

the GstStreamType of the stream

 

flags

the GstStreamFlags of the stream

 
+
+
+

Returns

+

The new GstStream.

+

[transfer full]

+
+

Since: 1.10

+
+
+
+

gst_stream_get_caps ()

+
GstCaps *
+gst_stream_get_caps (GstStream *stream);
+

Retrieve the caps for stream +, if any

+
+

Parameters

+
+++++ + + + + + +

stream

a GstStream

 
+
+
+

Returns

+

The GstCaps for stream +.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_stream_get_stream_flags ()

+
GstStreamFlags
+gst_stream_get_stream_flags (GstStream *stream);
+

Retrieve the current stream flags for stream +

+
+

Parameters

+
+++++ + + + + + +

stream

a GstStream

 
+
+
+

Returns

+

The GstStreamFlags for stream +

+
+

Since: 1.10

+
+
+
+

gst_stream_get_stream_id ()

+
const gchar *
+gst_stream_get_stream_id (GstStream *stream);
+

Returns the stream ID of stream +.

+
+

Parameters

+
+++++ + + + + + +

stream

a GstStream

 
+
+
+

Returns

+

the stream ID of stream +. Only valid +during the lifetime of stream +.

+

[transfer none][nullable]

+
+

Since: 1.10

+
+
+
+

gst_stream_get_stream_type ()

+
GstStreamType
+gst_stream_get_stream_type (GstStream *stream);
+

Retrieve the stream type for stream +

+
+

Parameters

+
+++++ + + + + + +

stream

a GstStream

 
+
+
+

Returns

+

The GstStreamType for stream +

+
+

Since: 1.10

+
+
+
+

gst_stream_get_tags ()

+
GstTagList *
+gst_stream_get_tags (GstStream *stream);
+

Retrieve the tags for stream +, if any

+
+

Parameters

+
+++++ + + + + + +

stream

a GstStream

 
+
+
+

Returns

+

The GstTagList for stream +.

+

[transfer full][nullable]

+
+

Since: 1.10

+
+
+
+

gst_stream_set_caps ()

+
void
+gst_stream_set_caps (GstStream *stream,
+                     GstCaps *caps);
+

Set the caps for the GstStream

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstStream

 

caps

a GstCaps.

[transfer none][allow-none]
+
+

Since: 1.10

+
+
+
+

gst_stream_set_stream_flags ()

+
void
+gst_stream_set_stream_flags (GstStream *stream,
+                             GstStreamFlags flags);
+

Set the flags + for the stream +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstStream

 

flags

the flags to set on stream +

 
+
+

Since: 1.10

+
+
+
+

gst_stream_set_stream_type ()

+
void
+gst_stream_set_stream_type (GstStream *stream,
+                            GstStreamType stream_type);
+

Set the stream type of stream +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstStream

 

stream_type

the type to set on stream +

 
+
+

Since: 1.10

+
+
+
+

gst_stream_set_tags ()

+
void
+gst_stream_set_tags (GstStream *stream,
+                     GstTagList *tags);
+

Set the tags for the GstStream

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

stream

a GstStream

 

tags

a GstTagList.

[transfer none][allow-none]
+
+

Since: 1.10

+
+
+
+

gst_stream_type_get_name ()

+
const gchar *
+gst_stream_type_get_name (GstStreamType stype);
+

Get a descriptive string for a given GstStreamType

+
+

Parameters

+
+++++ + + + + + +

stype

a GstStreamType

 
+
+
+

Returns

+

A string describing the stream type.

+

[nullable]

+
+

Since: 1.10

+
+
+
+

Types and Values

+
+

struct GstStream

+
struct GstStream {
+  const gchar *stream_id;
+};
+
+

A high-level object representing a single stream. It might be backed, or +not, by an actual flow of data in a pipeline (GstPad).

+

A GstStream does not care about data changes (such as decoding, encoding, +parsing,...) as long as the underlying data flow corresponds to the same +high-level flow (ex: a certain audio track).

+

A GstStream contains all the information pertinent to a stream, such as +stream-id, tags, caps, type, ...

+

Elements can subclass a GstStream for internal usage (to contain information +pertinent to streams of data).

+
+

Members

+
+++++ + + + + + +

const gchar *stream_id;

The Stream Identifier for this GstStream

 
+
+

Since: 1.10

+
+
+
+

struct GstStreamClass

+
struct GstStreamClass {
+  GstObjectClass parent_class;
+};
+
+

GstStream class structure

+
+

Members

+
+++++ + +
+
+
+
+
+

enum GstStreamType

+

GstStreamType describes a high level classification set for +flows of data in GstStream objects.

+

Note that this is a flag, and therefore users should not assume it +will be a single value. Do not use the equality operator for checking +whether a stream is of a certain type.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_STREAM_TYPE_UNKNOWN

+

The stream is of unknown (unclassified) type.

+
 

GST_STREAM_TYPE_AUDIO

+

The stream is of audio data

+
 

GST_STREAM_TYPE_VIDEO

+

The stream carries video data

+
 

GST_STREAM_TYPE_CONTAINER

+

The stream is a muxed container type

+
 

GST_STREAM_TYPE_TEXT

+

The stream contains subtitle / subpicture data.

+
 
+
+

Since: 1.10

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstStreamCollection.html b/docs/gst/html/gstreamer-GstStreamCollection.html new file mode 100644 index 0000000..d526d26 --- /dev/null +++ b/docs/gst/html/gstreamer-GstStreamCollection.html @@ -0,0 +1,327 @@ + + + + +GstStreamCollection: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstStreamCollection

+

GstStreamCollection — Base class for collection of streams

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstStreamCollection
structGstStreamCollectionClass
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+
+
+

Functions

+
+

gst_stream_collection_new ()

+
GstStreamCollection *
+gst_stream_collection_new (const gchar *upstream_id);
+

Create a new GstStreamCollection.

+
+

Parameters

+
+++++ + + + + + +

upstream_id

The stream id of the parent stream.

[allow-none]
+
+
+

Returns

+

The new GstStreamCollection.

+

[transfer full]

+
+

Since: 1.10

+
+
+
+

gst_stream_collection_add_stream ()

+
gboolean
+gst_stream_collection_add_stream (GstStreamCollection *collection,
+                                  GstStream *stream);
+

Add the given stream + to the collection +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

collection

a GstStreamCollection

 

stream

the GstStream to add.

[transfer full]
+
+
+

Returns

+

TRUE if the stream +was properly added, else FALSE

+
+

Since: 1.10

+
+
+
+

gst_stream_collection_get_upstream_id ()

+
const gchar *
+gst_stream_collection_get_upstream_id (GstStreamCollection *collection);
+

Returns the upstream id of the collection +.

+
+

Parameters

+
+++++ + + + + + +

collection

a GstStreamCollection

 
+
+
+

Returns

+

The upstream id.

+

[transfer none]

+
+

Since: 1.10

+
+
+
+

gst_stream_collection_get_size ()

+
guint
+gst_stream_collection_get_size (GstStreamCollection *collection);
+

Get the number of streams this collection contains

+
+

Parameters

+
+++++ + + + + + +

collection

a GstStreamCollection

 
+
+
+

Returns

+

The number of streams that collection +contains

+
+

Since: 1.10

+
+
+
+

gst_stream_collection_get_stream ()

+
GstStream *
+gst_stream_collection_get_stream (GstStreamCollection *collection,
+                                  guint index);
+

Retrieve the GstStream with index index + from the collection.

+

The caller should not modify the returned GstStream

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

collection

a GstStreamCollection

 

index

Index of the stream to retrieve

 
+
+
+

Returns

+

A GstStream.

+

[transfer none][nullable]

+
+

Since: 1.10

+
+
+
+

Types and Values

+
+

struct GstStreamCollection

+
struct GstStreamCollection {
+};
+
+

A collection of GstStream that are available.

+

A GstStreamCollection will be provided by elements that can make those +streams available. Applications can use the collection to show the user +what streams are available by using gst_stream_collection_get_stream()

+

Once posted, a GstStreamCollection is immutable. Updates are made by sending +a new GstStreamCollection message, which may or may not share some of +the GstStream objects from the collection it replaces. The receiver can check +the sender of a stream collection message to know which collection is +obsoleted.

+

Several elements in a pipeline can provide GstStreamCollection.

+

Applications can activate streams from a collection by using the +GST_EVENT_SELECT_STREAMS event on a pipeline, bin or element.

+

Since: 1.10

+
+
+
+

struct GstStreamCollectionClass

+
struct GstStreamCollectionClass {
+  GstObjectClass parent_class;
+
+  /* signals */
+  void  (*stream_notify)      (GstStreamCollection *collection, GstStream *stream, GParamSpec * pspec);
+};
+
+

GstStreamCollection class structure

+
+

Members

+
+++++ + + + + + +

stream_notify ()

default signal handler for the stream-notify signal

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstTocSetter.html b/docs/gst/html/gstreamer-GstTocSetter.html new file mode 100644 index 0000000..ffbde9e --- /dev/null +++ b/docs/gst/html/gstreamer-GstTocSetter.html @@ -0,0 +1,229 @@ + + + + +GstTocSetter: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTocSetter

+

GstTocSetter — Element interface that allows setting and retrieval + of the TOC

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+void + +gst_toc_setter_set_toc () +
+GstToc * + +gst_toc_setter_get_toc () +
+void + +gst_toc_setter_reset () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 GstTocSetter
structGstTocSetterInterface
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Element interface that allows setting of the TOC.

+

Elements that support some kind of chapters or editions (or tracks like in +the FLAC cue sheet) will implement this interface.

+

If you just want to retrieve the TOC in your application then all you +need to do is watch for TOC messages on your pipeline's bus (or you can +perform TOC query). This interface is only for setting TOC data, not for +extracting it. To set TOC from the application, find proper tocsetter element +and set TOC using gst_toc_setter_set_toc().

+

Elements implementing the GstTocSetter interface can extend existing TOC +by getting extend UID for that (you can use gst_toc_find_entry() to retrieve it) +with any TOC entries received from downstream.

+
+
+

Functions

+
+

gst_toc_setter_set_toc ()

+
void
+gst_toc_setter_set_toc (GstTocSetter *setter,
+                        GstToc *toc);
+

Set the given TOC on the setter. Previously set TOC will be +unreffed before setting a new one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

setter

a GstTocSetter.

 

toc

a GstToc to set.

[allow-none]
+
+
+
+
+

gst_toc_setter_get_toc ()

+
GstToc *
+gst_toc_setter_get_toc (GstTocSetter *setter);
+

Return current TOC the setter uses. The TOC should not be +modified without making it writable first.

+
+

Parameters

+
+++++ + + + + + +

setter

a GstTocSetter.

 
+
+
+

Returns

+

TOC set, or NULL. Unref with +gst_toc_unref() when no longer needed.

+

[transfer full][nullable]

+
+
+
+
+

gst_toc_setter_reset ()

+
void
+gst_toc_setter_reset (GstTocSetter *setter);
+

Reset the internal TOC. Elements should call this from within the +state-change handler.

+
+

Parameters

+
+++++ + + + + + +

setter

a GstTocSetter.

 
+
+
+
+
+

Types and Values

+
+

GstTocSetter

+
typedef struct _GstTocSetter GstTocSetter;
+

Opaque GstTocSetter data structure.

+
+
+
+

struct GstTocSetterInterface

+
struct GstTocSetterInterface {
+  GTypeInterface g_iface;
+
+  /* signals */
+
+  /* virtual table */
+};
+
+

GstTocSetterInterface interface.

+
+

Members

+
+++++ + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstTypeFind.html b/docs/gst/html/gstreamer-GstTypeFind.html new file mode 100644 index 0000000..94b1942 --- /dev/null +++ b/docs/gst/html/gstreamer-GstTypeFind.html @@ -0,0 +1,521 @@ + + + + +GstTypefind: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTypefind

+

GstTypefind — Stream type detection

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstTypeFindFunction) () +
const guint8 * + +gst_type_find_peek () +
+void + +gst_type_find_suggest () +
+void + +gst_type_find_suggest_simple () +
+guint64 + +gst_type_find_get_length () +
+gboolean + +gst_type_find_register () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTypeFind
enumGstTypeFindProbability
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

The following functions allow you to detect the media type of an unknown +stream.

+
+
+

Functions

+
+

GstTypeFindFunction ()

+
void
+(*GstTypeFindFunction) (GstTypeFind *find,
+                        gpointer user_data);
+

A function that will be called by typefinding.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

find

A GstTypeFind structure

 

user_data

optional data to pass to the function

 
+
+
+
+
+

gst_type_find_peek ()

+
const guint8 *
+gst_type_find_peek (GstTypeFind *find,
+                    gint64 offset,
+                    guint size);
+

Returns the size + bytes of the stream to identify beginning at offset. If +offset is a positive number, the offset is relative to the beginning of the +stream, if offset is a negative number the offset is relative to the end of +the stream. The returned memory is valid until the typefinding function +returns and must not be freed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

find

The GstTypeFind object the function was called with

 

offset

The offset

 

size

The number of bytes to return

 
+
+
+

Returns

+

the +requested data, or NULL if that data is not available.

+

[transfer none][array length=size][nullable]

+
+
+
+
+

gst_type_find_suggest ()

+
void
+gst_type_find_suggest (GstTypeFind *find,
+                       guint probability,
+                       GstCaps *caps);
+

If a GstTypeFindFunction calls this function it suggests the caps with the +given probability. A GstTypeFindFunction may supply different suggestions +in one call. +It is up to the caller of the GstTypeFindFunction to interpret these values.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

find

The GstTypeFind object the function was called with

 

probability

The probability in percent that the suggestion is right

 

caps

The fixed GstCaps to suggest

 
+
+
+
+
+

gst_type_find_suggest_simple ()

+
void
+gst_type_find_suggest_simple (GstTypeFind *find,
+                              guint probability,
+                              const char *media_type,
+                              const char *fieldname,
+                              ...);
+

If a GstTypeFindFunction calls this function it suggests the caps with the +given probability. A GstTypeFindFunction may supply different suggestions +in one call. It is up to the caller of the GstTypeFindFunction to interpret +these values.

+

This function is similar to gst_type_find_suggest(), only that instead of +passing a GstCaps argument you can create the caps on the fly in the same +way as you can with gst_caps_new_simple().

+

Make sure you terminate the list of arguments with a NULL argument and that +the values passed have the correct type (in terms of width in bytes when +passed to the vararg function - this applies particularly to gdouble and +guint64 arguments).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

find

The GstTypeFind object the function was called with

 

probability

The probability in percent that the suggestion is right

 

media_type

the media type of the suggested caps

 

fieldname

first field of the suggested caps, or NULL.

[allow-none]

...

additional arguments to the suggested caps in the same format as the +arguments passed to gst_structure_new() (ie. triplets of field name, +field GType and field value)

 
+
+
+
+
+

gst_type_find_get_length ()

+
guint64
+gst_type_find_get_length (GstTypeFind *find);
+

Get the length of the data stream.

+
+

Parameters

+
+++++ + + + + + +

find

The GstTypeFind the function was called with

 
+
+
+

Returns

+

The length of the data stream, or 0 if it is not available.

+
+
+
+
+

gst_type_find_register ()

+
gboolean
+gst_type_find_register (GstPlugin *plugin,
+                        const gchar *name,
+                        guint rank,
+                        GstTypeFindFunction func,
+                        const gchar *extensions,
+                        GstCaps *possible_caps,
+                        gpointer data,
+                        GDestroyNotify data_notify);
+

Registers a new typefind function to be used for typefinding. After +registering this function will be available for typefinding. +This function is typically called during an element's plugin initialization.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

plugin

A GstPlugin, or NULL for a static typefind function.

[allow-none]

name

The name for registering

 

rank

The rank (or importance) of this typefind function

 

func

The GstTypeFindFunction to use

 

extensions

Optional comma-separated list of extensions +that could belong to this type.

[allow-none]

possible_caps

Optionally the caps that could be returned when typefinding +succeeds

 

data

Optional user data. This user data must be available until the plugin +is unloaded.

 

data_notify

a GDestroyNotify that will be called on data +when the plugin +is unloaded.

 
+
+
+

Returns

+

TRUE on success, FALSE otherwise

+
+
+
+
+

Types and Values

+
+

struct GstTypeFind

+
struct GstTypeFind {
+  /* private to the caller of the typefind function */
+  const guint8 *  (* peek)       (gpointer         data,
+                                  gint64           offset,
+                                  guint            size);
+
+  void            (* suggest)    (gpointer         data,
+                                  guint            probability,
+                                  GstCaps         *caps);
+
+  gpointer         data;
+
+  /* optional */
+  guint64         (* get_length) (gpointer data);
+};
+
+

Object that stores typefind callbacks. To use with GstTypeFindFactory.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

peek ()

Method to peek data.

 

suggest ()

Method to suggest GstCaps with a given probability.

 

gpointer data;

The data used by the caller of the typefinding function.

 

get_length ()

Returns the length of current data.

 
+
+
+
+
+

enum GstTypeFindProbability

+

The probability of the typefind function. Higher values have more certainty +in doing a reliable typefind.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_TYPE_FIND_NONE

+

type undetected.

+
 

GST_TYPE_FIND_MINIMUM

+

unlikely typefind.

+
 

GST_TYPE_FIND_POSSIBLE

+

possible type detected.

+
 

GST_TYPE_FIND_LIKELY

+

likely a type was detected.

+
 

GST_TYPE_FIND_NEARLY_CERTAIN

+

nearly certain that a type was detected.

+
 

GST_TYPE_FIND_MAXIMUM

+

very certain a type was detected.

+
 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstUri.html b/docs/gst/html/gstreamer-GstUri.html new file mode 100644 index 0000000..6b8b709 --- /dev/null +++ b/docs/gst/html/gstreamer-GstUri.html @@ -0,0 +1,1969 @@ + + + + +GstUri: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstUri

+

GstUri — URI parsing and manipulation.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_URI_CAST() +
#define +GST_URI_CONST_CAST() +
+GstUri * + +gst_uri_new () +
+GstUri * + +gst_uri_new_with_base () +
+GstUri * + +gst_uri_from_string () +
+GstUri * + +gst_uri_from_string_with_base () +
+GstUri * + +gst_uri_copy () +
+gboolean + +gst_uri_equal () +
+GstUri * + +gst_uri_join () +
+gchar * + +gst_uri_join_strings () +
+gboolean + +gst_uri_is_writable () +
+GstUri * + +gst_uri_make_writable () +
+gchar * + +gst_uri_to_string () +
+GstUri * + +gst_uri_ref () +
+void + +gst_uri_unref () +
+gboolean + +gst_uri_is_normalized () +
+gboolean + +gst_uri_normalize () +
const gchar * + +gst_uri_get_scheme () +
+gboolean + +gst_uri_set_scheme () +
const gchar * + +gst_uri_get_userinfo () +
+gboolean + +gst_uri_set_userinfo () +
const gchar * + +gst_uri_get_host () +
+gboolean + +gst_uri_set_host () +
+guint + +gst_uri_get_port () +
+gboolean + +gst_uri_set_port () +
+gchar * + +gst_uri_get_path () +
+gboolean + +gst_uri_set_path () +
+gchar * + +gst_uri_get_path_string () +
+gboolean + +gst_uri_set_path_string () +
+GList * + +gst_uri_get_path_segments () +
+gboolean + +gst_uri_set_path_segments () +
+gboolean + +gst_uri_append_path () +
+gboolean + +gst_uri_append_path_segment () +
+gchar * + +gst_uri_get_query_string () +
+gboolean + +gst_uri_set_query_string () +
+GHashTable * + +gst_uri_get_query_table () +
+gboolean + +gst_uri_set_query_table () +
const gchar * + +gst_uri_get_query_value () +
+gboolean + +gst_uri_set_query_value () +
+gboolean + +gst_uri_remove_query_key () +
+gboolean + +gst_uri_query_has_key () +
+GList * + +gst_uri_get_query_keys () +
const gchar * + +gst_uri_get_fragment () +
+gboolean + +gst_uri_set_fragment () +
+GHashTable * + +gst_uri_get_media_fragment_table () +
+
+
+

Types and Values

+
++++ + + + + +
 GstUri
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

A GstUri object can be used to parse and split a URI string into its +constituant parts. Two GstUri objects can be joined to make a new GstUri +using the algorithm described in RFC3986.

+
+
+

Functions

+
+

GST_URI_CAST()

+
#define GST_URI_CAST(obj)   ((GstUri *)(obj))
+
+
+
+
+

GST_URI_CONST_CAST()

+
#define GST_URI_CONST_CAST(obj) ((const GstUri *)(obj))
+
+
+
+
+

gst_uri_new ()

+
GstUri *
+gst_uri_new (const gchar *scheme,
+             const gchar *userinfo,
+             const gchar *host,
+             guint port,
+             const gchar *path,
+             const gchar *query,
+             const gchar *fragment);
+

Creates a new GstUri object with the given URI parts. The path and query +strings will be broken down into their elements. All strings should not be +escaped except where indicated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

scheme

The scheme for the new URI.

[nullable]

userinfo

The user-info for the new URI.

[nullable]

host

The host name for the new URI.

[nullable]

port

The port number for the new URI or GST_URI_NO_PORT.

 

path

The path for the new URI with '/' separating path +elements.

[nullable]

query

The query string for the new URI with '&' separating +query elements. Elements containing '&' characters +should encode them as "%26".

[nullable]

fragment

The fragment name for the new URI.

[nullable]
+
+
+

Returns

+

A new GstUri object.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_new_with_base ()

+
GstUri *
+gst_uri_new_with_base (GstUri *base,
+                       const gchar *scheme,
+                       const gchar *userinfo,
+                       const gchar *host,
+                       guint port,
+                       const gchar *path,
+                       const gchar *query,
+                       const gchar *fragment);
+

Like gst_uri_new(), but joins the new URI onto a base URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

base

The base URI to join the new URI to.

[transfer none][nullable]

scheme

The scheme for the new URI.

[nullable]

userinfo

The user-info for the new URI.

[nullable]

host

The host name for the new URI.

[nullable]

port

The port number for the new URI or GST_URI_NO_PORT.

 

path

The path for the new URI with '/' separating path +elements.

[nullable]

query

The query string for the new URI with '&' separating +query elements. Elements containing '&' characters +should encode them as "%26".

[nullable]

fragment

The fragment name for the new URI.

[nullable]
+
+
+

Returns

+

The new URI joined onto base +.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_from_string ()

+
GstUri *
+gst_uri_from_string (const gchar *uri);
+

Parses a URI string into a new GstUri object. Will return NULL if the URI +cannot be parsed.

+
+

Parameters

+
+++++ + + + + + +

uri

The URI string to parse.

 
+
+
+

Returns

+

A new GstUri object, or NULL.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_from_string_with_base ()

+
GstUri *
+gst_uri_from_string_with_base (GstUri *base,
+                               const gchar *uri);
+

Like gst_uri_from_string() but also joins with a base URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

base

The base URI to join the new URI with.

[transfer none][nullable]

uri

The URI string to parse.

 
+
+
+

Returns

+

A new GstUri object.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_copy ()

+
GstUri *
+gst_uri_copy (const GstUri *uri);
+

Create a new GstUri object with the same data as this GstUri object. +If uri + is NULL then returns NULL.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

 
+
+
+

Returns

+

A new GstUri object which is a copy of this +GstUri or NULL.

+

[transfer full]

+
+
+
+
+

gst_uri_equal ()

+
gboolean
+gst_uri_equal (const GstUri *first,
+               const GstUri *second);
+

Compares two GstUri objects to see if they represent the same normalized +URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

first

First GstUri to compare.

 

second

Second GstUri to compare.

 
+
+
+

Returns

+

TRUE if the normalized versions of the two URI's would be equal.

+
+

Since: 1.6

+
+
+
+

gst_uri_join ()

+
GstUri *
+gst_uri_join (GstUri *base_uri,
+              GstUri *ref_uri);
+

Join a reference URI onto a base URI using the method from RFC 3986. +If either URI is NULL then the other URI will be returned with the ref count +increased.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

base_uri

The base URI to join another to.

[transfer none][nullable]

ref_uri

The reference URI to join onto the +base URI.

[transfer none][nullable]
+
+
+

Returns

+

A GstUri which represents the base +with the reference URI joined on.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_join_strings ()

+
gchar *
+gst_uri_join_strings (const gchar *base_uri,
+                      const gchar *ref_uri);
+

This is a convenience function to join two URI strings and return the result. +The returned string should be g_free()'d after use.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

base_uri

The percent-encoded base URI.

 

ref_uri

The percent-encoded reference URI to join to the base_uri +.

 
+
+
+

Returns

+

A string representing the percent-encoded join of +the two URIs.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_is_writable ()

+
gboolean
+gst_uri_is_writable (const GstUri *uri);
+

Check if it is safe to write to this GstUri.

+

Check if the refcount of uri + is exactly 1, meaning that no other +reference exists to the GstUri and that the GstUri is therefore writable.

+

Modification of a GstUri should only be done after verifying that it is +writable.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri object to test.

 
+
+
+

Returns

+

TRUE if it is safe to write to the object.

+
+

Since: 1.6

+
+
+
+

gst_uri_make_writable ()

+
GstUri *
+gst_uri_make_writable (GstUri *uri);
+

Make the GstUri writable.

+

Checks if uri + is writable, and if so the original object is returned. If +not, then a writable copy is made and returned. This gives away the +reference to uri + and returns a reference to the new GstUri. +If uri + is NULL then NULL is returned.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri object to make writable.

[transfer full]
+
+
+

Returns

+

A writable version of uri +.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_to_string ()

+
gchar *
+gst_uri_to_string (const GstUri *uri);
+

Convert the URI to a string.

+

Returns the URI as held in this object as a gchar* nul-terminated string. +The caller should g_free() the string once they are finished with it. +The string is put together as described in RFC 3986.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri to convert to a string.

 
+
+
+

Returns

+

The string version of the URI.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_ref ()

+
GstUri *
+gst_uri_ref (GstUri *uri);
+

Add a reference to this GstUri object. See gst_mini_object_ref() for further +info.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[transfer none]
+
+
+

Returns

+

This object with the reference count incremented.

+
+
+
+
+

gst_uri_unref ()

+
void
+gst_uri_unref (GstUri *uri);
+

Decrement the reference count to this GstUri object.

+

If the reference count drops to 0 then finalize this object.

+

See gst_mini_object_unref() for further info.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[transfer full]
+
+
+
+
+

gst_uri_is_normalized ()

+
gboolean
+gst_uri_is_normalized (const GstUri *uri);
+

Tests the uri + to see if it is normalized. A NULL uri + is considered to be +normalized.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to test to see if it is normalized.

 
+
+
+

Returns

+

TRUE if the URI is normalized or is NULL.

+
+

Since: 1.6

+
+
+
+

gst_uri_normalize ()

+
gboolean
+gst_uri_normalize (GstUri *uri);
+

Normalization will remove extra path segments ("." and "..") from the URI. It +will also convert the scheme and host name to lower case and any +percent-encoded values to uppercase.

+

The GstUri object must be writable. Check with gst_uri_is_writable() or use +gst_uri_make_writable() first.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to normalize.

[transfer none]
+
+
+

Returns

+

TRUE if the URI was modified.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_scheme ()

+
const gchar *
+gst_uri_get_scheme (const GstUri *uri);
+

Get the scheme name from the URI or NULL if it doesn't exist. +If uri + is NULL then returns NULL.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[nullable]
+
+
+

Returns

+

The scheme from the GstUri object or NULL.

+

[nullable]

+
+
+
+
+

gst_uri_set_scheme ()

+
gboolean
+gst_uri_set_scheme (GstUri *uri,
+                    const gchar *scheme);
+

Set or unset the scheme for the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

scheme

The new scheme to set or NULL to unset the scheme.

 
+
+
+

Returns

+

TRUE if the scheme was set/unset successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_userinfo ()

+
const gchar *
+gst_uri_get_userinfo (const GstUri *uri);
+

Get the userinfo (usually in the form "username:password") from the URI +or NULL if it doesn't exist. If uri + is NULL then returns NULL.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[nullable]
+
+
+

Returns

+

The userinfo from the GstUri object or NULL.

+

[nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_userinfo ()

+
gboolean
+gst_uri_set_userinfo (GstUri *uri,
+                      const gchar *userinfo);
+

Set or unset the user information for the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

userinfo

The new user-information string to set or NULL to unset.

 
+
+
+

Returns

+

TRUE if the user information was set/unset successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_host ()

+
const gchar *
+gst_uri_get_host (const GstUri *uri);
+

Get the host name from the URI or NULL if it doesn't exist. +If uri + is NULL then returns NULL.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[nullable]
+
+
+

Returns

+

The host name from the GstUri object or NULL.

+

[nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_host ()

+
gboolean
+gst_uri_set_host (GstUri *uri,
+                  const gchar *host);
+

Set or unset the host for the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

host

The new host string to set or NULL to unset.

 
+
+
+

Returns

+

TRUE if the host was set/unset successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_port ()

+
guint
+gst_uri_get_port (const GstUri *uri);
+

Get the port number from the URI or GST_URI_NO_PORT if it doesn't exist. +If uri + is NULL then returns GST_URI_NO_PORT.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[nullable]
+
+
+

Returns

+

The port number from the GstUri object or GST_URI_NO_PORT.

+
+

Since: 1.6

+
+
+
+

gst_uri_set_port ()

+
gboolean
+gst_uri_set_port (GstUri *uri,
+                  guint port);
+

Set or unset the port number for the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

port

The new port number to set or GST_URI_NO_PORT to unset.

 
+
+
+

Returns

+

TRUE if the port number was set/unset successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_path ()

+
gchar *
+gst_uri_get_path (const GstUri *uri);
+

Extract the path string from the URI object.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the path from.

 
+
+
+

Returns

+

(nullable): The path from the URI. Once finished +with the string should be g_free()'d.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_path ()

+
gboolean
+gst_uri_set_path (GstUri *uri,
+                  const gchar *path);
+

Sets or unsets the path in the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

path

The new path to set with path segments separated by '/', or use NULL +to unset the path.

 
+
+
+

Returns

+

TRUE if the path was set successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_path_string ()

+
gchar *
+gst_uri_get_path_string (const GstUri *uri);
+

Extract the path string from the URI object as a percent encoded URI path.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the path from.

 
+
+
+

Returns

+

The path from the URI. Once finished +with the string should be g_free()'d.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_path_string ()

+
gboolean
+gst_uri_set_path_string (GstUri *uri,
+                         const gchar *path);
+

Sets or unsets the path in the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

path

The new percent encoded path to set with path segments separated by +'/', or use NULL to unset the path.

 
+
+
+

Returns

+

TRUE if the path was set successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_path_segments ()

+
GList *
+gst_uri_get_path_segments (const GstUri *uri);
+

Get a list of path segments from the URI.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the path from.

[nullable]
+
+
+

Returns

+

A GList of path segment +strings or NULL if no path segments are available. Free the list +when no longer needed with g_list_free_full(list, g_free).

+

[transfer full][element-type gchar*]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_path_segments ()

+
gboolean
+gst_uri_set_path_segments (GstUri *uri,
+                           GList *path_segments);
+

Replace the path segments list in the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

path_segments

The new +path list to set.

[transfer full][nullable][element-type gchar*]
+
+
+

Returns

+

TRUE if the path segments were set successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_append_path ()

+
gboolean
+gst_uri_append_path (GstUri *uri,
+                     const gchar *relative_path);
+

Append a path onto the end of the path in the URI. The path is not +normalized, call gst_uri_normalize() to normalize the path.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

relative_path

Relative path to append to the end of the current path.

 
+
+
+

Returns

+

TRUE if the path was appended successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_append_path_segment ()

+
gboolean
+gst_uri_append_path_segment (GstUri *uri,
+                             const gchar *path_segment);
+

Append a single path segment onto the end of the URI path.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

path_segment

The path segment string to append to the URI path.

 
+
+
+

Returns

+

TRUE if the path was appended successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_query_string ()

+
gchar *
+gst_uri_get_query_string (const GstUri *uri);
+

Get a percent encoded URI query string from the uri +.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the query string from.

[nullable]
+
+
+

Returns

+

A percent encoded query string. Use +g_free() when no longer needed.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_query_string ()

+
gboolean
+gst_uri_set_query_string (GstUri *uri,
+                          const gchar *query);
+

Sets or unsets the query table in the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

query

The new percent encoded query string to use to populate the query +table, or use NULL to unset the query table.

 
+
+
+

Returns

+

TRUE if the query table was set successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_query_table ()

+
GHashTable *
+gst_uri_get_query_table (const GstUri *uri);
+

Get the query table from the URI. Keys and values in the table are freed +with g_free when they are deleted. A value may be NULL to indicate that +the key should appear in the query string in the URI, but does not have a +value. Free the returned GHashTable with g_hash_table_unref() when it is +no longer required. Modifying this hash table will modify the query in the +URI.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the query table from.

[nullable]
+
+
+

Returns

+

The query +hash table from the URI.

+

[transfer full][element-type gchar* gchar*][nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_query_table ()

+
gboolean
+gst_uri_set_query_table (GstUri *uri,
+                         GHashTable *query_table);
+

Set the query table to use in the URI. The old table is unreferenced and a +reference to the new one is used instead. A value if NULL for query_table + +will remove the query string from the URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

query_table

The new +query table to use.

[transfer none][nullable][element-type gchar* gchar*]
+
+
+

Returns

+

TRUE if the new table was sucessfully used for the query table.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_query_value ()

+
const gchar *
+gst_uri_get_query_value (const GstUri *uri,
+                         const gchar *query_key);
+

Get the value associated with the query_key + key. Will return NULL if the +key has no value or if the key does not exist in the URI query table. Because +NULL is returned for both missing keys and keys with no value, you should +use gst_uri_query_has_key() to determine if a key is present in the URI +query.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to examine.

[nullable]

query_key

The key to lookup.

 
+
+
+

Returns

+

The value for the given key, or NULL if not found.

+

[nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_query_value ()

+
gboolean
+gst_uri_set_query_value (GstUri *uri,
+                         const gchar *query_key,
+                         const gchar *query_value);
+

This inserts or replaces a key in the query table. A query_value + of NULL +indicates that the key has no associated value, but will still be present in +the query string.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

query_key

The key for the query entry.

[transfer none]

query_value

The value for the key.

[transfer none][nullable]
+
+
+

Returns

+

TRUE if the query table was sucessfully updated.

+
+

Since: 1.6

+
+
+
+

gst_uri_remove_query_key ()

+
gboolean
+gst_uri_remove_query_key (GstUri *uri,
+                          const gchar *query_key);
+

Remove an entry from the query table by key.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

query_key

The key to remove.

 
+
+
+

Returns

+

TRUE if the key existed in the table and was removed.

+
+

Since: 1.6

+
+
+
+

gst_uri_query_has_key ()

+
gboolean
+gst_uri_query_has_key (const GstUri *uri,
+                       const gchar *query_key);
+

Check if there is a query table entry for the query_key + key.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to examine.

[nullable]

query_key

The key to lookup.

 
+
+
+

Returns

+

TRUE if query_key +exists in the URI query table.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_query_keys ()

+
GList *
+gst_uri_get_query_keys (const GstUri *uri);
+

Get a list of the query keys from the URI.

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to examine.

[nullable]
+
+
+

Returns

+

A list of keys from +the URI query. Free the list with g_list_free().

+

[transfer container][element-type gchar*]

+
+

Since: 1.6

+
+
+
+

gst_uri_get_fragment ()

+
const gchar *
+gst_uri_get_fragment (const GstUri *uri);
+

Get the fragment name from the URI or NULL if it doesn't exist. +If uri + is NULL then returns NULL.

+
+

Parameters

+
+++++ + + + + + +

uri

This GstUri object.

[nullable]
+
+
+

Returns

+

The host name from the GstUri object or NULL.

+

[nullable]

+
+

Since: 1.6

+
+
+
+

gst_uri_set_fragment ()

+
gboolean
+gst_uri_set_fragment (GstUri *uri,
+                      const gchar *fragment);
+

Sets the fragment string in the URI. Use a value of NULL in fragment + to +unset the fragment string.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

The GstUri to modify.

[transfer none][nullable]

fragment

The fragment string to set.

[nullable]
+
+
+

Returns

+

TRUE if the fragment was set/unset successfully.

+
+

Since: 1.6

+
+
+
+

gst_uri_get_media_fragment_table ()

+
GHashTable *
+gst_uri_get_media_fragment_table (const GstUri *uri);
+

Get the media fragment table from the URI, as defined by "Media Fragments URI 1.0". +Hash table returned by this API is a list of "key-value" pairs, and the each +pair is generated by splitting "URI fragment" per "&" sub-delims, then "key" +and "value" are splitted by "=" sub-delims. The "key" returned by this API may +be undefined keyword by standard. +A value may be NULL to indicate that the key should appear in the fragment +string in the URI, but does not have a value. Free the returned GHashTable +with g_hash_table_unref() when it is no longer required. +Modifying this hash table does not affect the fragment in the URI.

+

See more about Media Fragments URI 1.0 (W3C) at https://www.w3.org/TR/media-frags/

+
+

Parameters

+
+++++ + + + + + +

uri

The GstUri to get the fragment table from.

[nullable]
+
+
+

Returns

+

The +fragment hash table from the URI.

+

[transfer full][element-type gchar* gchar*][nullable]

+
+

Since: 1.12

+
+
+
+

Types and Values

+
+

GstUri

+
typedef struct _GstUri GstUri;
+

This is a private structure that holds the various parts of a parsed URI.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstUriHandler.html b/docs/gst/html/gstreamer-GstUriHandler.html new file mode 100644 index 0000000..6f1030a --- /dev/null +++ b/docs/gst/html/gstreamer-GstUriHandler.html @@ -0,0 +1,855 @@ + + + + +GstUriHandler: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstUriHandler

+

GstUriHandler — Interface to ease URI handling in plugins.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GQuark + +gst_uri_error_quark () +
#define +GST_URI_TYPE_IS_VALID() +
+gboolean + +gst_uri_protocol_is_valid () +
+gboolean + +gst_uri_protocol_is_supported () +
+gboolean + +gst_uri_is_valid () +
+gboolean + +gst_uri_has_protocol () +
+gchar * + +gst_uri_get_protocol () +
+gchar * + +gst_uri_get_location () +
+gchar * + +gst_uri_construct () +
+gchar * + +gst_filename_to_uri () +
+GstElement * + +gst_element_make_from_uri () +
+GstURIType + +gst_uri_handler_get_uri_type () +
const gchar * const * + +gst_uri_handler_get_protocols () +
+gchar * + +gst_uri_handler_get_uri () +
+gboolean + +gst_uri_handler_set_uri () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
 GstURIHandler
structGstURIHandlerInterface
enumGstURIType
enumGstURIError
#defineGST_URI_NO_PORT
+
+
+

Object Hierarchy

+
    GInterface
+    ╰── GstURIHandler
+
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

The GstURIHandler is an interface that is implemented by Source and Sink +GstElement to unify handling of URI.

+

An application can use the following functions to quickly get an element +that handles the given URI for reading or writing +(gst_element_make_from_uri()).

+

Source and Sink plugins should implement this interface when possible.

+
+
+

Functions

+
+

gst_uri_error_quark ()

+
GQuark
+gst_uri_error_quark (void);
+
+
+
+

GST_URI_TYPE_IS_VALID()

+
#define GST_URI_TYPE_IS_VALID(type) ((type) == GST_URI_SRC || (type) == GST_URI_SINK)
+
+

Tests if the type direction is valid.

+
+

Parameters

+
+++++ + + + + + +

type

A GstURIType

 
+
+
+
+
+

gst_uri_protocol_is_valid ()

+
gboolean
+gst_uri_protocol_is_valid (const gchar *protocol);
+

Tests if the given string is a valid protocol identifier. Protocols +must consist of alphanumeric characters, '+', '-' and '.' and must +start with a alphabetic character. See RFC 3986 Section 3.1.

+
+

Parameters

+
+++++ + + + + + +

protocol

A string

 
+
+
+

Returns

+

TRUE if the string is a valid protocol identifier, FALSE otherwise.

+
+
+
+
+

gst_uri_protocol_is_supported ()

+
gboolean
+gst_uri_protocol_is_supported (const GstURIType type,
+                               const gchar *protocol);
+

Checks if an element exists that supports the given URI protocol. Note +that a positive return value does not imply that a subsequent call to +gst_element_make_from_uri() is guaranteed to work.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

type

Whether to check for a source or a sink

 

protocol

Protocol that should be checked for (e.g. "http" or "smb")

 
+
+
+

Returns

+

TRUE

+
+
+
+
+

gst_uri_is_valid ()

+
gboolean
+gst_uri_is_valid (const gchar *uri);
+

Tests if the given string is a valid URI identifier. URIs start with a valid +scheme followed by ":" and maybe a string identifying the location.

+
+

Parameters

+
+++++ + + + + + +

uri

A URI string

 
+
+
+

Returns

+

TRUE if the string is a valid URI

+
+
+
+
+

gst_uri_has_protocol ()

+
gboolean
+gst_uri_has_protocol (const gchar *uri,
+                      const gchar *protocol);
+

Checks if the protocol of a given valid URI matches protocol +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a URI string

 

protocol

a protocol string (e.g. "http")

 
+
+
+

Returns

+

TRUE if the protocol matches.

+
+
+
+
+

gst_uri_get_protocol ()

+
gchar *
+gst_uri_get_protocol (const gchar *uri);
+

Extracts the protocol out of a given valid URI. The returned string must be +freed using g_free().

+
+

Parameters

+
+++++ + + + + + +

uri

A URI string

 
+
+
+

Returns

+

The protocol for this URI.

+

[nullable]

+
+
+
+
+

gst_uri_get_location ()

+
gchar *
+gst_uri_get_location (const gchar *uri);
+

Extracts the location out of a given valid URI, ie. the protocol and "://" +are stripped from the URI, which means that the location returned includes +the hostname if one is specified. The returned string must be freed using +g_free().

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

uri

A URI string

 
+
+
+

Returns

+

the location for this URI. Returns +NULL if the URI isn't valid. If the URI does not contain a location, an +empty string is returned.

+

[transfer full][nullable]

+
+
+
+
+

gst_uri_construct ()

+
gchar *
+gst_uri_construct (const gchar *protocol,
+                   const gchar *location);
+
+

gst_uri_construct is deprecated and should not be used in newly-written code.

+

Use GstURI instead.

+
+

Constructs a URI for a given valid protocol and location.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

protocol

Protocol for URI

 

location

Location for URI.

[transfer none]
+
+
+

Returns

+

a new string for this URI. Returns NULL if the +given URI protocol is not valid, or the given location is NULL.

+

[transfer full]

+
+
+
+
+

gst_filename_to_uri ()

+
gchar *
+gst_filename_to_uri (const gchar *filename,
+                     GError **error);
+

Similar to g_filename_to_uri(), but attempts to handle relative file paths +as well. Before converting filename + into an URI, it will be prefixed by +the current working directory if it is a relative path, and then the path +will be canonicalised so that it doesn't contain any './' or '../' segments.

+

On Windows filename should be in UTF-8 encoding.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

filename

absolute or relative file name path.

[type filename]

error

pointer to error, or NULL

 
+
+
+

Returns

+

newly-allocated URI string, or NULL on error. The caller must +free the URI string with g_free() when no longer needed.

+
+
+
+
+

gst_element_make_from_uri ()

+
GstElement *
+gst_element_make_from_uri (const GstURIType type,
+                           const gchar *uri,
+                           const gchar *elementname,
+                           GError **error);
+

Creates an element for handling the given URI.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

type

Whether to create a source or a sink

 

uri

URI to create an element for

 

elementname

Name of created element, can be NULL.

[allow-none]

error

address where to store error information, or NULL.

[allow-none]
+
+
+

Returns

+

a new element or NULL if none +could be created.

+

[transfer floating][nullable]

+
+
+
+
+

gst_uri_handler_get_uri_type ()

+
GstURIType
+gst_uri_handler_get_uri_type (GstURIHandler *handler);
+

Gets the type of the given URI handler

+
+

Parameters

+
+++++ + + + + + +

handler

A GstURIHandler.

 
+
+
+

Returns

+

the GstURIType of the URI handler. +Returns GST_URI_UNKNOWN if the handler +isn't implemented correctly.

+
+
+
+
+

gst_uri_handler_get_protocols ()

+
const gchar * const *
+gst_uri_handler_get_protocols (GstURIHandler *handler);
+

Gets the list of protocols supported by handler +. This list may not be +modified.

+
+

Parameters

+
+++++ + + + + + +

handler

A GstURIHandler.

 
+
+
+

Returns

+

the +supported protocols. Returns NULL if the handler +isn't +implemented properly, or the handler +doesn't support any +protocols.

+

[transfer none][element-type utf8][nullable]

+
+
+
+
+

gst_uri_handler_get_uri ()

+
gchar *
+gst_uri_handler_get_uri (GstURIHandler *handler);
+

Gets the currently handled URI.

+
+

Parameters

+
+++++ + + + + + +

handler

A GstURIHandler

 
+
+
+

Returns

+

the URI currently handled by +the handler +. Returns NULL if there are no URI currently +handled. The returned string must be freed with g_free() when no +longer needed.

+

[transfer full][nullable]

+
+
+
+
+

gst_uri_handler_set_uri ()

+
gboolean
+gst_uri_handler_set_uri (GstURIHandler *handler,
+                         const gchar *uri,
+                         GError **error);
+

Tries to set the URI of the given handler.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

handler

A GstURIHandler

 

uri

URI to set

 

error

address where to store a GError in case of +an error, or NULL.

[allow-none]
+
+
+

Returns

+

TRUE if the URI was set successfully, else FALSE.

+
+
+
+
+

Types and Values

+
+

GstURIHandler

+
typedef struct _GstURIHandler GstURIHandler;
+

Opaque GstURIHandler structure.

+
+
+
+

struct GstURIHandlerInterface

+
struct GstURIHandlerInterface {
+  GTypeInterface parent;
+
+  /* vtable */
+  /* querying capabilities */
+  GstURIType             (* get_type)           (GType type);
+  const gchar * const *  (* get_protocols)      (GType type);
+
+  /* using the interface */
+  gchar *                (* get_uri)            (GstURIHandler * handler);
+  gboolean               (* set_uri)            (GstURIHandler * handler,
+                                                 const gchar   * uri,
+                                                 GError       ** error);
+};
+
+

Any GstElement using this interface should implement these methods.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GTypeInterface parent;

The parent interface type

 

get_type ()

Method to tell whether the element handles source or sink URI.

 

get_protocols ()

Method to return the list of protocols handled by the element.

 

get_uri ()

Method to return the URI currently handled by the element.

 

set_uri ()

Method to set a new URI.

 
+
+
+
+
+

enum GstURIType

+

The different types of URI direction.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_URI_UNKNOWN

+

The URI direction is unknown

+
 

GST_URI_SINK

+

The URI is a consumer.

+
 

GST_URI_SRC

+

The URI is a producer.

+
 
+
+
+
+
+

enum GstURIError

+

Different URI-related errors that can occur.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_URI_ERROR_UNSUPPORTED_PROTOCOL

+

The protocol is not supported

+
 

GST_URI_ERROR_BAD_URI

+

There was a problem with the URI

+
 

GST_URI_ERROR_BAD_STATE

+

Could not set or change the URI because the + URI handler was in a state where that is not possible or not permitted

+
 

GST_URI_ERROR_BAD_REFERENCE

+

There was a problem with the entity that + the URI references

+
 
+
+
+
+
+

GST_URI_NO_PORT

+
#define GST_URI_NO_PORT 0
+
+

Value for GstUri.port to indicate no port number.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstUtils.html b/docs/gst/html/gstreamer-GstUtils.html new file mode 100644 index 0000000..cd84939 --- /dev/null +++ b/docs/gst/html/gstreamer-GstUtils.html @@ -0,0 +1,3150 @@ + + + + +GstUtils: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstUtils

+

GstUtils — Various utility functions

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_CALL_PARENT() +
#define +GST_CALL_PARENT_WITH_DEFAULT() +
#define +GST_READ_UINT8() +
#define +GST_READ_UINT16_LE() +
#define +GST_READ_UINT16_BE() +
#define +GST_READ_UINT24_LE() +
#define +GST_READ_UINT24_BE() +
#define +GST_READ_UINT32_LE() +
#define +GST_READ_UINT32_BE() +
#define +GST_READ_UINT64_LE() +
#define +GST_READ_UINT64_BE() +
+gfloat + +GST_READ_FLOAT_LE () +
+gfloat + +GST_READ_FLOAT_BE () +
+gdouble + +GST_READ_DOUBLE_LE () +
+gdouble + +GST_READ_DOUBLE_BE () +
#define +GST_WRITE_UINT8() +
#define +GST_WRITE_UINT16_LE() +
#define +GST_WRITE_UINT16_BE() +
#define +GST_WRITE_UINT24_LE() +
#define +GST_WRITE_UINT24_BE() +
#define +GST_WRITE_UINT32_LE() +
#define +GST_WRITE_UINT32_BE() +
#define +GST_WRITE_UINT64_LE() +
#define +GST_WRITE_UINT64_BE() +
+void + +GST_WRITE_FLOAT_LE () +
+void + +GST_WRITE_FLOAT_BE () +
+void + +GST_WRITE_DOUBLE_LE () +
+void + +GST_WRITE_DOUBLE_BE () +
#define +GST_ROUND_UP_2() +
#define +GST_ROUND_UP_4() +
#define +GST_ROUND_UP_8() +
#define +GST_ROUND_UP_16() +
#define +GST_ROUND_UP_32() +
#define +GST_ROUND_UP_64() +
#define +GST_ROUND_UP_128() +
#define +GST_ROUND_UP_N() +
#define +GST_ROUND_DOWN_2() +
#define +GST_ROUND_DOWN_4() +
#define +GST_ROUND_DOWN_8() +
#define +GST_ROUND_DOWN_16() +
#define +GST_ROUND_DOWN_32() +
#define +GST_ROUND_DOWN_64() +
#define +GST_ROUND_DOWN_128() +
#define +GST_ROUND_DOWN_N() +
#define +GDOUBLE_FROM_BE() +
#define +GDOUBLE_FROM_LE() +
+gdouble + +GDOUBLE_SWAP_LE_BE () +
#define +GDOUBLE_TO_BE() +
#define +GDOUBLE_TO_LE() +
#define +GFLOAT_FROM_BE() +
#define +GFLOAT_FROM_LE() +
+gfloat + +GFLOAT_SWAP_LE_BE () +
#define +GFLOAT_TO_BE() +
#define +GFLOAT_TO_LE() +
#define +gst_guint64_to_gdouble() +
#define +gst_gdouble_to_guint64() +
+void + +gst_util_dump_buffer () +
+void + +gst_util_dump_mem () +
+guint64 + +gst_util_uint64_scale () +
+guint64 + +gst_util_uint64_scale_round () +
+guint64 + +gst_util_uint64_scale_ceil () +
+guint64 + +gst_util_uint64_scale_int () +
+guint64 + +gst_util_uint64_scale_int_round () +
+guint64 + +gst_util_uint64_scale_int_ceil () +
+gint + +gst_util_greatest_common_divisor () +
+gint64 + +gst_util_greatest_common_divisor_int64 () +
+void + +gst_util_fraction_to_double () +
+void + +gst_util_double_to_fraction () +
+gboolean + +gst_util_fraction_multiply () +
+gboolean + +gst_util_fraction_add () +
+gint + +gst_util_fraction_compare () +
+guint32 + +gst_util_seqnum_next () +
+gint32 + +gst_util_seqnum_compare () +
+guint + +gst_util_group_id_next () +
+void + +gst_util_set_object_arg () +
+void + +gst_util_set_value_from_string () +
+gboolean + +gst_util_set_object_array () +
+gboolean + +gst_util_get_object_array () +
+GstClockTime + +gst_util_get_timestamp () +
+gpointer + +gst_util_array_binary_search () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
#defineGST_SEQNUM_INVALID
#defineGST_GROUP_ID_INVALID
enumGstSearchMode
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+
+
+

Functions

+
+

GST_CALL_PARENT()

+
#define             GST_CALL_PARENT(parent_class_cast, name, args)
+

Just call the parent handler. This assumes that there is a variable +named parent_class that points to the (duh!) parent class. Note that +this macro is not to be used with things that return something, use +the _WITH_DEFAULT version for that

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parent_class_cast

the name of the class cast macro for the parent type

 

name

name of the function to call

 

args

arguments enclosed in '( )'

 
+
+
+
+
+

GST_CALL_PARENT_WITH_DEFAULT()

+
#define             GST_CALL_PARENT_WITH_DEFAULT(parent_class_cast, name, args, def_return)
+

Same as GST_CALL_PARENT(), but in case there is no implementation, it +evaluates to def_return +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

parent_class_cast

the name of the class cast macro for the parent type

 

name

name of the function to call

 

args

arguments enclosed in '( )'

 

def_return

default result

 
+
+
+
+
+

GST_READ_UINT8()

+
#define GST_READ_UINT8(data)            (_GST_GET (data, 0,  8,  0))
+
+

Read an 8 bit unsigned integer value from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT16_LE()

+
#  define GST_READ_UINT16_LE(data)      _GST_FAST_READ_SWAP (16, data)
+
+

Read a 16 bit unsigned integer value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT16_BE()

+
#  define GST_READ_UINT16_BE(data)      _GST_FAST_READ (16, data)
+
+

Read a 16 bit unsigned integer value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT24_LE()

+
#define GST_READ_UINT24_LE(data) __gst_slow_read24_le((const guint8 *)(data))
+
+

Read a 24 bit unsigned integer value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT24_BE()

+
#define GST_READ_UINT24_BE(data) __gst_slow_read24_be((const guint8 *)(data))
+
+

Read a 24 bit unsigned integer value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT32_LE()

+
#  define GST_READ_UINT32_LE(data)      _GST_FAST_READ_SWAP (32, data)
+
+

Read a 32 bit unsigned integer value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT32_BE()

+
#  define GST_READ_UINT32_BE(data)      _GST_FAST_READ (32, data)
+
+

Read a 32 bit unsigned integer value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT64_LE()

+
#  define GST_READ_UINT64_LE(data)      _GST_FAST_READ_SWAP (64, data)
+
+

Read a 64 bit unsigned integer value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_UINT64_BE()

+
#  define GST_READ_UINT64_BE(data)      _GST_FAST_READ (64, data)
+
+

Read a 64 bit unsigned integer value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+
+
+

GST_READ_FLOAT_LE ()

+
gfloat
+GST_READ_FLOAT_LE (const guint8 *data);
+

Read a 32 bit float value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+

Returns

+

The floating point value read from data +

+
+
+
+
+

GST_READ_FLOAT_BE ()

+
gfloat
+GST_READ_FLOAT_BE (const guint8 *data);
+

Read a 32 bit float value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+

Returns

+

The floating point value read from data +

+
+
+
+
+

GST_READ_DOUBLE_LE ()

+
gdouble
+GST_READ_DOUBLE_LE (const guint8 *data);
+

Read a 64 bit double value in little endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+

Returns

+

The double-precision floating point value read from data +

+
+
+
+
+

GST_READ_DOUBLE_BE ()

+
gdouble
+GST_READ_DOUBLE_BE (const guint8 *data);
+

Read a 64 bit double value in big endian format from the memory buffer.

+
+

Parameters

+
+++++ + + + + + +

data

memory location

 
+
+
+

Returns

+

The double-precision floating point value read from data +

+
+
+
+
+

GST_WRITE_UINT8()

+
#define             GST_WRITE_UINT8(data, num)
+

Store an 8 bit unsigned integer value into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_UINT16_LE()

+
#  define GST_WRITE_UINT16_LE(data,val) _GST_FAST_WRITE_SWAP(16,data,val)
+
+

Store a 16 bit unsigned integer value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_UINT16_BE()

+
#  define GST_WRITE_UINT16_BE(data,val) _GST_FAST_WRITE(16,data,val)
+
+

Store a 16 bit unsigned integer value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_UINT24_LE()

+
#define             GST_WRITE_UINT24_LE(data, num)
+

Store a 24 bit unsigned integer value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_UINT24_BE()

+
#define             GST_WRITE_UINT24_BE(data, num)
+

Store a 24 bit unsigned integer value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_UINT32_LE()

+
#  define GST_WRITE_UINT32_LE(data,val) _GST_FAST_WRITE_SWAP(32,data,val)
+
+

Store a 32 bit unsigned integer value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_UINT32_BE()

+
#  define GST_WRITE_UINT32_BE(data,val) _GST_FAST_WRITE(32,data,val)
+
+

Store a 32 bit unsigned integer value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_UINT64_LE()

+
#  define GST_WRITE_UINT64_LE(data,val) _GST_FAST_WRITE_SWAP(64,data,val)
+
+

Store a 64 bit unsigned integer value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_UINT64_BE()

+
#  define GST_WRITE_UINT64_BE(data,val) _GST_FAST_WRITE(64,data,val)
+
+

Store a 64 bit unsigned integer value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

val

value to store

 
+
+
+
+
+

GST_WRITE_FLOAT_LE ()

+
void
+GST_WRITE_FLOAT_LE (guint8 *data,
+                    gfloat num);
+

Store a 32 bit float value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_FLOAT_BE ()

+
void
+GST_WRITE_FLOAT_BE (guint8 *data,
+                    gfloat num);
+

Store a 32 bit float value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_DOUBLE_LE ()

+
void
+GST_WRITE_DOUBLE_LE (guint8 *data,
+                     gdouble num);
+

Store a 64 bit double value in little endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_WRITE_DOUBLE_BE ()

+
void
+GST_WRITE_DOUBLE_BE (guint8 *data,
+                     gdouble num);
+

Store a 64 bit double value in big endian format into the memory buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

memory location

 

num

value to store

 
+
+
+
+
+

GST_ROUND_UP_2()

+
#define GST_ROUND_UP_2(num)  (((num)+1)&~1)
+
+

Rounds an integer value up to the next multiple of 2.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_4()

+
#define GST_ROUND_UP_4(num)  (((num)+3)&~3)
+
+

Rounds an integer value up to the next multiple of 4.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_8()

+
#define GST_ROUND_UP_8(num)  (((num)+7)&~7)
+
+

Rounds an integer value up to the next multiple of 8.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_16()

+
#define GST_ROUND_UP_16(num) (((num)+15)&~15)
+
+

Rounds an integer value up to the next multiple of 16.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_32()

+
#define GST_ROUND_UP_32(num) (((num)+31)&~31)
+
+

Rounds an integer value up to the next multiple of 32.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_64()

+
#define GST_ROUND_UP_64(num) (((num)+63)&~63)
+
+

Rounds an integer value up to the next multiple of 64.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+
+
+
+

GST_ROUND_UP_128()

+
#define GST_ROUND_UP_128(num) (((num)+127)&~127)
+
+

Rounds an integer value up to the next multiple of 128.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round up

 
+
+

Since: 1.4

+
+
+
+

GST_ROUND_UP_N()

+
#define GST_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1)))
+
+

Rounds an integer value up to the next multiple of align +. align + MUST be a +power of two.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

num

integrer value to round up

 

align

a power of two to round up to

 
+
+
+
+
+

GST_ROUND_DOWN_2()

+
#define GST_ROUND_DOWN_2(num)  ((num)&(~1))
+
+

Rounds an integer value down to the next multiple of 2.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_4()

+
#define GST_ROUND_DOWN_4(num)  ((num)&(~3))
+
+

Rounds an integer value down to the next multiple of 4.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_8()

+
#define GST_ROUND_DOWN_8(num)  ((num)&(~7))
+
+

Rounds an integer value down to the next multiple of 8.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_16()

+
#define GST_ROUND_DOWN_16(num) ((num)&(~15))
+
+

Rounds an integer value down to the next multiple of 16.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_32()

+
#define GST_ROUND_DOWN_32(num) ((num)&(~31))
+
+

Rounds an integer value down to the next multiple of 32.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_64()

+
#define GST_ROUND_DOWN_64(num) ((num)&(~63))
+
+

Rounds an integer value down to the next multiple of 64.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+
+
+
+

GST_ROUND_DOWN_128()

+
#define GST_ROUND_DOWN_128(num) ((num)&(~127))
+
+

Rounds an integer value down to the next multiple of 128.

+
+

Parameters

+
+++++ + + + + + +

num

integer value to round down

 
+
+

Since: 1.4

+
+
+
+

GST_ROUND_DOWN_N()

+
#define GST_ROUND_DOWN_N(num,align) (((num) & ~((align) - 1)))
+
+

Rounds an integer value down to the next multiple of align +. align + MUST be a +power of two.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

num

integrer value to round down

 

align

a power of two to round down to

 
+
+
+
+
+

GDOUBLE_FROM_BE()

+
#define GDOUBLE_FROM_BE(val) (GDOUBLE_TO_BE (val))
+
+

Convert 64-bit floating point value (double) from big endian byte order +into native byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GDOUBLE_FROM_LE()

+
#define GDOUBLE_FROM_LE(val) (GDOUBLE_TO_LE (val))
+
+

Convert 64-bit floating point value (double) from little endian byte order +into native byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GDOUBLE_SWAP_LE_BE ()

+
gdouble
+GDOUBLE_SWAP_LE_BE (gdouble in);
+

Swap byte order of a 64-bit floating point value (double).

+
+

Parameters

+
+++++ + + + + + +

in

input value

 
+
+
+

Returns

+

in +byte-swapped.

+
+
+
+
+

GDOUBLE_TO_BE()

+
#define GDOUBLE_TO_BE(val)   (GDOUBLE_SWAP_LE_BE (val))
+
+

Convert 64-bit floating point value (double) from native byte order into +big endian byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GDOUBLE_TO_LE()

+
#define GDOUBLE_TO_LE(val)   ((gdouble) (val))
+
+

Convert 64-bit floating point value (double) from native byte order into +little endian byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GFLOAT_FROM_BE()

+
#define GFLOAT_FROM_BE(val)  (GFLOAT_TO_BE (val))
+
+

Convert 32-bit floating point value (float) from big endian byte order +into native byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GFLOAT_FROM_LE()

+
#define GFLOAT_FROM_LE(val)  (GFLOAT_TO_LE (val))
+
+

Convert 32-bit floating point value (float) from little endian byte order +into native byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GFLOAT_SWAP_LE_BE ()

+
gfloat
+GFLOAT_SWAP_LE_BE (gfloat in);
+

Swap byte order of a 32-bit floating point value (float).

+
+

Parameters

+
+++++ + + + + + +

in

input value

 
+
+
+

Returns

+

in +byte-swapped.

+
+
+
+
+

GFLOAT_TO_BE()

+
#define GFLOAT_TO_BE(val)    (GFLOAT_SWAP_LE_BE (val))
+
+

Convert 32-bit floating point value (float) from native byte order into +big endian byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

GFLOAT_TO_LE()

+
#define GFLOAT_TO_LE(val)    ((gfloat) (val))
+
+

Convert 32-bit floating point value (float) from native byte order into +little endian byte order.

+
+

Parameters

+
+++++ + + + + + +

val

value

 
+
+
+
+
+

gst_guint64_to_gdouble()

+
#define         gst_guint64_to_gdouble(value)   gst_util_guint64_to_gdouble(value)
+
+

Convert value + to a gdouble.

+
+

Parameters

+
+++++ + + + + + +

value

the guint64 value to convert

 
+
+
+

Returns

+

value +converted to a gdouble.

+
+
+
+
+

gst_gdouble_to_guint64()

+
#define         gst_gdouble_to_guint64(value)   gst_util_gdouble_to_guint64(value)
+
+

Convert value + to a guint64.

+
+

Parameters

+
+++++ + + + + + +

value

the gdouble value to convert

 
+
+
+

Returns

+

value +converted to a guint64.

+
+
+
+
+

gst_util_dump_buffer ()

+
void
+gst_util_dump_buffer (GstBuffer *buf);
+

Dumps the buffer memory into a hex representation. Useful for debugging.

+
+

Parameters

+
+++++ + + + + + +

buf

a GstBuffer whose memory to dump

 
+
+

Since: 1.14

+
+
+
+

gst_util_dump_mem ()

+
void
+gst_util_dump_mem (const guchar *mem,
+                   guint size);
+

Dumps the memory block into a hex representation. Useful for debugging.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

mem

a pointer to the memory to dump.

[array length=size]

size

the size of the memory block to dump

 
+
+
+
+
+

gst_util_uint64_scale ()

+
guint64
+gst_util_uint64_scale (guint64 val,
+                       guint64 num,
+                       guint64 denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision.

+

This function can potentially be very slow if val and num are both +greater than G_MAXUINT32.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

the number to scale

 

num

the numerator of the scale ratio

 

denom

the denominator of the scale ratio

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer it is truncated. See also +gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil(), +gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), +gst_util_uint64_scale_int_ceil().

+
+
+
+
+

gst_util_uint64_scale_round ()

+
guint64
+gst_util_uint64_scale_round (guint64 val,
+                             guint64 num,
+                             guint64 denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision.

+

This function can potentially be very slow if val and num are both +greater than G_MAXUINT32.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

the number to scale

 

num

the numerator of the scale ratio

 

denom

the denominator of the scale ratio

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer, it is rounded to the nearest integer +(half-way cases are rounded up). See also gst_util_uint64_scale(), +gst_util_uint64_scale_ceil(), gst_util_uint64_scale_int(), +gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil().

+
+
+
+
+

gst_util_uint64_scale_ceil ()

+
guint64
+gst_util_uint64_scale_ceil (guint64 val,
+                            guint64 num,
+                            guint64 denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision.

+

This function can potentially be very slow if val and num are both +greater than G_MAXUINT32.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

the number to scale

 

num

the numerator of the scale ratio

 

denom

the denominator of the scale ratio

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer, it is rounded up. See also +gst_util_uint64_scale(), gst_util_uint64_scale_round(), +gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), +gst_util_uint64_scale_int_ceil().

+
+
+
+
+

gst_util_uint64_scale_int ()

+
guint64
+gst_util_uint64_scale_int (guint64 val,
+                           gint num,
+                           gint denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision. num + must be non-negative and +denom + must be positive.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

guint64 (such as a GstClockTime) to scale.

 

num

numerator of the scale factor.

 

denom

denominator of the scale factor.

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer, it is truncated. See also +gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil(), +gst_util_uint64_scale(), gst_util_uint64_scale_round(), +gst_util_uint64_scale_ceil().

+
+
+
+
+

gst_util_uint64_scale_int_round ()

+
guint64
+gst_util_uint64_scale_int_round (guint64 val,
+                                 gint num,
+                                 gint denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision. num + must be non-negative and +denom + must be positive.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

guint64 (such as a GstClockTime) to scale.

 

num

numerator of the scale factor.

 

denom

denominator of the scale factor.

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer, it is rounded to the nearest integer +(half-way cases are rounded up). See also gst_util_uint64_scale_int(), +gst_util_uint64_scale_int_ceil(), gst_util_uint64_scale(), +gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil().

+
+
+
+
+

gst_util_uint64_scale_int_ceil ()

+
guint64
+gst_util_uint64_scale_int_ceil (guint64 val,
+                                gint num,
+                                gint denom);
+

Scale val + by the rational number num + / denom +, avoiding overflows and +underflows and without loss of precision. num + must be non-negative and +denom + must be positive.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

val

guint64 (such as a GstClockTime) to scale.

 

num

numerator of the scale factor.

 

denom

denominator of the scale factor.

 
+
+
+

Returns

+

val +* num +/ denom +. In the case of an overflow, this +function returns G_MAXUINT64. If the result is not exactly +representable as an integer, it is rounded up. See also +gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), +gst_util_uint64_scale(), gst_util_uint64_scale_round(), +gst_util_uint64_scale_ceil().

+
+
+
+
+

gst_util_greatest_common_divisor ()

+
gint
+gst_util_greatest_common_divisor (gint a,
+                                  gint b);
+

Calculates the greatest common divisor of a + +and b +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

First value as gint

 

b

Second value as gint

 
+
+
+

Returns

+

Greatest common divisor of a +and b +

+
+
+
+
+

gst_util_greatest_common_divisor_int64 ()

+
gint64
+gst_util_greatest_common_divisor_int64
+                               (gint64 a,
+                                gint64 b);
+

Calculates the greatest common divisor of a + +and b +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

First value as gint64

 

b

Second value as gint64

 
+
+
+

Returns

+

Greatest common divisor of a +and b +

+
+
+
+
+

gst_util_fraction_to_double ()

+
void
+gst_util_fraction_to_double (gint src_n,
+                             gint src_d,
+                             gdouble *dest);
+

Transforms a fraction to a gdouble.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src_n

Fraction numerator as gint

 

src_d

Fraction denominator gint

 

dest

pointer to a gdouble for the result.

[out]
+
+
+
+
+

gst_util_double_to_fraction ()

+
void
+gst_util_double_to_fraction (gdouble src,
+                             gint *dest_n,
+                             gint *dest_d);
+

Transforms a gdouble to a fraction and simplifies +the result.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

gdouble to transform

 

dest_n

pointer to a gint to hold the result numerator.

[out]

dest_d

pointer to a gint to hold the result denominator.

[out]
+
+
+
+
+

gst_util_fraction_multiply ()

+
gboolean
+gst_util_fraction_multiply (gint a_n,
+                            gint a_d,
+                            gint b_n,
+                            gint b_d,
+                            gint *res_n,
+                            gint *res_d);
+

Multiplies the fractions a_n +/a_d + and b_n +/b_d + and stores +the result in res_n + and res_d +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

a_n

Numerator of first value

 

a_d

Denominator of first value

 

b_n

Numerator of second value

 

b_d

Denominator of second value

 

res_n

Pointer to gint to hold the result numerator.

[out]

res_d

Pointer to gint to hold the result denominator.

[out]
+
+
+

Returns

+

FALSE on overflow, TRUE otherwise.

+
+
+
+
+

gst_util_fraction_add ()

+
gboolean
+gst_util_fraction_add (gint a_n,
+                       gint a_d,
+                       gint b_n,
+                       gint b_d,
+                       gint *res_n,
+                       gint *res_d);
+

Adds the fractions a_n +/a_d + and b_n +/b_d + and stores +the result in res_n + and res_d +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

a_n

Numerator of first value

 

a_d

Denominator of first value

 

b_n

Numerator of second value

 

b_d

Denominator of second value

 

res_n

Pointer to gint to hold the result numerator.

[out]

res_d

Pointer to gint to hold the result denominator.

[out]
+
+
+

Returns

+

FALSE on overflow, TRUE otherwise.

+
+
+
+
+

gst_util_fraction_compare ()

+
gint
+gst_util_fraction_compare (gint a_n,
+                           gint a_d,
+                           gint b_n,
+                           gint b_d);
+

Compares the fractions a_n +/a_d + and b_n +/b_d + and returns +-1 if a < b, 0 if a = b and 1 if a > b.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

a_n

Numerator of first value

 

a_d

Denominator of first value

 

b_n

Numerator of second value

 

b_d

Denominator of second value

 
+
+
+

Returns

+

-1 if a < b; 0 if a = b; 1 if a > b.

+
+
+
+
+

gst_util_seqnum_next ()

+
guint32
+gst_util_seqnum_next (void);
+

Return a constantly incrementing sequence number.

+

This function is used internally to GStreamer to be able to determine which +events and messages are "the same". For example, elements may set the seqnum +on a segment-done message to be the same as that of the last seek event, to +indicate that event and the message correspond to the same segment.

+

This function never returns GST_SEQNUM_INVALID (which is 0).

+
+

Returns

+

A constantly incrementing 32-bit unsigned integer, which might +overflow at some point. Use gst_util_seqnum_compare() to make sure +you handle wraparound correctly.

+
+
+
+
+

gst_util_seqnum_compare ()

+
gint32
+gst_util_seqnum_compare (guint32 s1,
+                         guint32 s2);
+

Compare two sequence numbers, handling wraparound.

+

The current implementation just returns (gint32)(s1 + - s2 +).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

s1

A sequence number.

 

s2

Another sequence number.

 
+
+
+

Returns

+

A negative number if s1 +is before s2 +, 0 if they are equal, or a +positive number if s1 +is after s2 +.

+
+
+
+
+

gst_util_group_id_next ()

+
guint
+gst_util_group_id_next (void);
+

Return a constantly incrementing group id.

+

This function is used to generate a new group-id for the +stream-start event.

+

This function never returns GST_GROUP_ID_INVALID (which is 0)

+
+

Returns

+

A constantly incrementing unsigned integer, which might +overflow back to 0 at some point.

+
+
+
+
+

gst_util_set_object_arg ()

+
void
+gst_util_set_object_arg (GObject *object,
+                         const gchar *name,
+                         const gchar *value);
+

Converts the string value to the type of the objects argument and +sets the argument with it.

+

Note that this function silently returns if object + has no property named +name + or when value + cannot be converted to the type of the property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object to set the argument of

 

name

the name of the argument to set

 

value

the string value to set

 
+
+
+
+
+

gst_util_set_value_from_string ()

+
void
+gst_util_set_value_from_string (GValue *value,
+                                const gchar *value_str);
+

Converts the string to the type of the value and +sets the value with it.

+

Note that this function is dangerous as it does not return any indication +if the conversion worked or not.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

the value to set.

[out caller-allocates]

value_str

the string to get the value from

 
+
+
+
+
+

gst_util_set_object_array ()

+
gboolean
+gst_util_set_object_array (GObject *object,
+                           const gchar *name,
+                           const GValueArray *array);
+

Transfer a GValueArray to GST_TYPE_ARRAY and set this value on the +specified property name. This allow language bindings to set GST_TYPE_ARRAY +properties which are otherwise not an accessible type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object to set the array to

 

name

the name of the property to set

 

array

a GValueArray containing the values

 
+
+

Since: 1.12

+
+
+
+

gst_util_get_object_array ()

+
gboolean
+gst_util_get_object_array (GObject *object,
+                           const gchar *name,
+                           GValueArray **array);
+

Get a property of type GST_TYPE_ARRAY and transform it into a +GValueArray. This allow language bindings to get GST_TYPE_ARRAY +properties which are otherwise not an accessible type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object to set the array to

 

name

the name of the property to set

 

array

a return GValueArray.

[out]
+
+

Since: 1.12

+
+
+
+

gst_util_get_timestamp ()

+
GstClockTime
+gst_util_get_timestamp (void);
+

Get a timestamp as GstClockTime to be used for interval measurements. +The timestamp should not be interpreted in any other way.

+
+

Returns

+

the timestamp

+
+
+
+
+

gst_util_array_binary_search ()

+
gpointer
+gst_util_array_binary_search (gpointer array,
+                              guint num_elements,
+                              gsize element_size,
+                              GCompareDataFunc search_func,
+                              GstSearchMode mode,
+                              gconstpointer search_data,
+                              gpointer user_data);
+

Searches inside array + for search_data + by using the comparison function +search_func +. array + must be sorted ascending.

+

As search_data + is always passed as second argument to search_func + it's +not required that search_data + has the same type as the array elements.

+

The complexity of this search function is O(log (num_elements)).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

array

the sorted input array

 

num_elements

number of elements in the array

 

element_size

size of every element in bytes

 

search_func

function to compare two elements, search_data +will always be passed as second argument.

[scope call]

mode

search mode that should be used

 

search_data

element that should be found

 

user_data

data to pass to search_func +.

[closure]
+
+
+

Returns

+

The address of the found +element or NULL if nothing was found.

+

[transfer none][nullable]

+
+
+
+
+

Types and Values

+
+

GST_SEQNUM_INVALID

+
#define GST_SEQNUM_INVALID (0)
+
+

A value which is guaranteed to never be returned by +gst_util_seqnum_next().

+

Can be used as a default value in variables used to store seqnum.

+

Since: 1.14

+
+
+
+

GST_GROUP_ID_INVALID

+
#define GST_GROUP_ID_INVALID (0)
+
+

A value which is guaranteed to never be returned by +gst_util_group_id_next().

+

Can be used as a default value in variables used to store group_id.

+

Since: 1.14

+
+
+
+

enum GstSearchMode

+

The different search modes.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_SEARCH_MODE_EXACT

+

Only search for exact matches.

+
 

GST_SEARCH_MODE_BEFORE

+

Search for an exact match or the element just before.

+
 

GST_SEARCH_MODE_AFTER

+

Search for an exact match or the element just after.

+
 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstValue.html b/docs/gst/html/gstreamer-GstValue.html new file mode 100644 index 0000000..dbf4dc6 --- /dev/null +++ b/docs/gst/html/gstreamer-GstValue.html @@ -0,0 +1,3888 @@ + + + + +GstValue: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstValue

+

GstValue — GValue implementations specific +to GStreamer

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_MAKE_FOURCC() +
#define +GST_STR_FOURCC() +
#define +GST_FOURCC_ARGS() +
#define +GST_VALUE_HOLDS_INT_RANGE() +
+void + +gst_value_set_int_range () +
+gint + +gst_value_get_int_range_min () +
+gint + +gst_value_get_int_range_max () +
+void + +gst_value_set_int_range_step () +
+gint + +gst_value_get_int_range_step () +
#define +GST_VALUE_HOLDS_BITMASK() +
+void + +gst_value_set_bitmask () +
+guint64 + +gst_value_get_bitmask () +
#define +GST_VALUE_HOLDS_FLAG_SET() +
+gboolean + +gst_structure_get_flagset () +
+guint + +gst_value_get_flagset_flags () +
+guint + +gst_value_get_flagset_mask () +
+void + +gst_value_set_flagset () +
#define +GST_VALUE_HOLDS_INT64_RANGE() +
+void + +gst_value_set_int64_range () +
+gint64 + +gst_value_get_int64_range_min () +
+gint64 + +gst_value_get_int64_range_max () +
+void + +gst_value_set_int64_range_step () +
+gint64 + +gst_value_get_int64_range_step () +
#define +GST_VALUE_HOLDS_DOUBLE_RANGE() +
+void + +gst_value_set_double_range () +
+gdouble + +gst_value_get_double_range_min () +
+gdouble + +gst_value_get_double_range_max () +
#define +GST_VALUE_HOLDS_LIST() +
#define +GST_VALUE_HOLDS_ARRAY() +
+void + +gst_value_list_append_value () +
+void + +gst_value_list_append_and_take_value () +
+void + +gst_value_list_prepend_value () +
+void + +gst_value_list_concat () +
+void + +gst_value_list_merge () +
+guint + +gst_value_list_get_size () +
const GValue * + +gst_value_list_get_value () +
#define +GST_VALUE_HOLDS_FRACTION() +
+void + +gst_value_set_fraction () +
+gint + +gst_value_get_fraction_numerator () +
+gint + +gst_value_get_fraction_denominator () +
+gboolean + +gst_value_fraction_multiply () +
+gboolean + +gst_value_fraction_subtract () +
#define +GST_VALUE_HOLDS_FRACTION_RANGE() +
+void + +gst_value_set_fraction_range () +
const GValue * + +gst_value_get_fraction_range_min () +
const GValue * + +gst_value_get_fraction_range_max () +
+void + +gst_value_set_fraction_range_full () +
#define +GST_VALUE_HOLDS_DATE_TIME() +
#define +GST_VALUE_HOLDS_CAPS() +
+void + +gst_value_set_caps () +
const GstCaps * + +gst_value_get_caps () +
#define +GST_VALUE_HOLDS_CAPS_FEATURES() +
+void + +gst_value_set_caps_features () +
const GstCapsFeatures * + +gst_value_get_caps_features () +
#define +GST_VALUE_HOLDS_STRUCTURE() +
+void + +gst_value_set_structure () +
const GstStructure * + +gst_value_get_structure () +
#define +GST_VALUE_HOLDS_BUFFER() +
#define +gst_value_get_buffer() +
#define +gst_value_set_buffer() +
#define +gst_value_take_buffer() +
#define +GST_VALUE_HOLDS_SAMPLE() +
#define +gst_value_get_sample() +
#define +gst_value_set_sample() +
#define +gst_value_take_sample() +
+gint + +(*GstValueCompareFunc) () +
+gchar * + +(*GstValueSerializeFunc) () +
+gboolean + +(*GstValueDeserializeFunc) () +
+gboolean + +gst_value_is_fixed () +
+void + +gst_value_register () +
+void + +gst_value_init_and_copy () +
+gchar * + +gst_value_serialize () +
+gboolean + +gst_value_deserialize () +
+gint + +gst_value_compare () +
+gboolean + +gst_value_can_compare () +
+gboolean + +gst_value_union () +
+gboolean + +gst_value_can_union () +
+gboolean + +gst_value_subtract () +
+gboolean + +gst_value_can_subtract () +
+gboolean + +gst_value_intersect () +
+gboolean + +gst_value_can_intersect () +
+gboolean + +gst_value_is_subset () +
+void + +gst_value_array_append_value () +
+void + +gst_value_array_append_and_take_value () +
+guint + +gst_value_array_get_size () +
const GValue * + +gst_value_array_get_value () +
+void + +gst_value_array_prepend_value () +
+gboolean + +gst_value_fixate () +
+GType + +gst_flagset_register () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#defineGST_FOURCC_FORMAT
#defineGST_TYPE_INT_RANGE
#defineGST_TYPE_BITMASK
#defineGST_TYPE_FLAG_SET
#defineGST_FLAG_SET_MASK_EXACT
#defineGST_TYPE_INT64_RANGE
#defineGST_TYPE_DOUBLE_RANGE
#defineGST_TYPE_LIST
#defineGST_TYPE_ARRAY
#defineGST_TYPE_FRACTION
#defineGST_TYPE_FRACTION_RANGE
#defineGST_VALUE_LESS_THAN
#defineGST_VALUE_EQUAL
#defineGST_VALUE_GREATER_THAN
#defineGST_VALUE_UNORDERED
structGstValueTable
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

GValue implementations specific to GStreamer.

+

Note that operations on the same GValue from multiple threads may lead to +undefined behaviour.

+
+
+

Functions

+
+

GST_MAKE_FOURCC()

+
#define             GST_MAKE_FOURCC(a,b,c,d)
+

Transform four characters into a guint32 fourcc value with host +endianness.

+
+ + + + + + + +
1
guint32 fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
+
+ +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

a

the first character

 

b

the second character

 

c

the third character

 

d

the fourth character

 
+
+
+
+
+

GST_STR_FOURCC()

+
#define GST_STR_FOURCC(f)               ((guint32)(((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24)))
+
+

Transform an input string into a guint32 fourcc value with host +endianness. +Caller is responsible for ensuring the input string consists of at least +four characters.

+
+ + + + + + + +
1
guint32 fourcc = GST_STR_FOURCC ("MJPG");
+
+ +

+
+

Parameters

+
+++++ + + + + + +

f

a string with at least four characters

 
+
+
+
+
+

GST_FOURCC_ARGS()

+
#define             GST_FOURCC_ARGS(fourcc)
+

Can be used together with GST_FOURCC_FORMAT to properly output a +guint32 fourcc value in a printf()-style text message.

+
+

Parameters

+
+++++ + + + + + +

fourcc

a guint32 fourcc value to output

 
+
+
+
+
+

GST_VALUE_HOLDS_INT_RANGE()

+
#define GST_VALUE_HOLDS_INT_RANGE(x)      ((x) != NULL && G_VALUE_TYPE(x) == _gst_int_range_type)
+
+

Checks if the given GValue contains a GST_TYPE_INT_RANGE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_int_range ()

+
void
+gst_value_set_int_range (GValue *value,
+                         gint start,
+                         gint end);
+

Sets value + to the range specified by start + and end +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_INT_RANGE

 

start

the start of the range

 

end

the end of the range

 
+
+
+
+
+

gst_value_get_int_range_min ()

+
gint
+gst_value_get_int_range_min (const GValue *value);
+

Gets the minimum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT_RANGE

 
+
+
+

Returns

+

the minimum of the range

+
+
+
+
+

gst_value_get_int_range_max ()

+
gint
+gst_value_get_int_range_max (const GValue *value);
+

Gets the maximum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT_RANGE

 
+
+
+

Returns

+

the maximum of the range

+
+
+
+
+

gst_value_set_int_range_step ()

+
void
+gst_value_set_int_range_step (GValue *value,
+                              gint start,
+                              gint end,
+                              gint step);
+

Sets value + to the range specified by start +, end + and step +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_INT_RANGE

 

start

the start of the range

 

end

the end of the range

 

step

the step of the range

 
+
+
+
+
+

gst_value_get_int_range_step ()

+
gint
+gst_value_get_int_range_step (const GValue *value);
+

Gets the step of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT_RANGE

 
+
+
+

Returns

+

the step of the range

+
+
+
+
+

GST_VALUE_HOLDS_BITMASK()

+
#define GST_VALUE_HOLDS_BITMASK(x)      ((x) != NULL && G_VALUE_TYPE(x) == _gst_bitmask_type)
+
+

Checks if the given GValue contains a GST_TYPE_BITMASK value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_bitmask ()

+
void
+gst_value_set_bitmask (GValue *value,
+                       guint64 bitmask);
+

Sets value + to the bitmask specified by bitmask +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_BITMASK

 

bitmask

the bitmask

 
+
+
+
+
+

gst_value_get_bitmask ()

+
guint64
+gst_value_get_bitmask (const GValue *value);
+

Gets the bitmask specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_BITMASK

 
+
+
+

Returns

+

the bitmask.

+
+
+
+
+

GST_VALUE_HOLDS_FLAG_SET()

+
#define GST_VALUE_HOLDS_FLAG_SET(x)     (G_TYPE_CHECK_VALUE_TYPE ((x), GST_TYPE_FLAG_SET))
+
+

Checks if the given GValue contains a GST_TYPE_FLAG_SET value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+

Since: 1.6

+
+
+
+

gst_structure_get_flagset ()

+
gboolean
+gst_structure_get_flagset (const GstStructure *structure,
+                           const gchar *fieldname,
+                           guint *value_flags,
+                           guint *value_mask);
+

Read the GstFlagSet flags and mask out of the structure into the +provided pointers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

structure

a GstStructure

 

fieldname

the name of a field

 

value_flags

a pointer to a guint for the flags field.

[out][allow-none]

value_mask

a pointer to a guint for the mask field.

[out][allow-none]
+
+
+

Returns

+

TRUE if the values could be set correctly. If there was no field +with fieldname +or the existing field did not contain a GstFlagSet, this +function returns FALSE.

+
+

Since: 1.6

+
+
+
+

gst_value_get_flagset_flags ()

+
guint
+gst_value_get_flagset_flags (const GValue *value);
+

Retrieve the flags field of a GstFlagSet value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FLAG_SET

 
+
+
+

Returns

+

the flags field of the flagset instance.

+
+

Since: 1.6

+
+
+
+

gst_value_get_flagset_mask ()

+
guint
+gst_value_get_flagset_mask (const GValue *value);
+

Retrieve the mask field of a GstFlagSet value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FLAG_SET

 
+
+
+

Returns

+

the mask field of the flagset instance.

+
+

Since: 1.6

+
+
+
+

gst_value_set_flagset ()

+
void
+gst_value_set_flagset (GValue *value,
+                       guint flags,
+                       guint mask);
+

Sets value + to the flags and mask values provided in flags + and mask +. +The flags + value indicates the values of flags, the mask + represents +which bits in the flag value have been set, and which are "don't care"

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_FLAG_SET

 

flags

The value of the flags set or unset

 

mask

The mask indicate which flags bits must match for comparisons

 
+
+

Since: 1.6

+
+
+
+

GST_VALUE_HOLDS_INT64_RANGE()

+
#define GST_VALUE_HOLDS_INT64_RANGE(x)    ((x) != NULL && G_VALUE_TYPE(x) == _gst_int64_range_type)
+
+

Checks if the given GValue contains a GST_TYPE_INT64_RANGE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_int64_range ()

+
void
+gst_value_set_int64_range (GValue *value,
+                           gint64 start,
+                           gint64 end);
+

Sets value + to the range specified by start + and end +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_INT64_RANGE

 

start

the start of the range

 

end

the end of the range

 
+
+
+
+
+

gst_value_get_int64_range_min ()

+
gint64
+gst_value_get_int64_range_min (const GValue *value);
+

Gets the minimum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT64_RANGE

 
+
+
+

Returns

+

the minimum of the range

+
+
+
+
+

gst_value_get_int64_range_max ()

+
gint64
+gst_value_get_int64_range_max (const GValue *value);
+

Gets the maximum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT64_RANGE

 
+
+
+

Returns

+

the maximum of the range

+
+
+
+
+

gst_value_set_int64_range_step ()

+
void
+gst_value_set_int64_range_step (GValue *value,
+                                gint64 start,
+                                gint64 end,
+                                gint64 step);
+

Sets value + to the range specified by start +, end + and step +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_INT64_RANGE

 

start

the start of the range

 

end

the end of the range

 

step

the step of the range

 
+
+
+
+
+

gst_value_get_int64_range_step ()

+
gint64
+gst_value_get_int64_range_step (const GValue *value);
+

Gets the step of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_INT64_RANGE

 
+
+
+

Returns

+

the step of the range

+
+
+
+
+

GST_VALUE_HOLDS_DOUBLE_RANGE()

+
#define GST_VALUE_HOLDS_DOUBLE_RANGE(x)   ((x) != NULL && G_VALUE_TYPE(x) == _gst_double_range_type)
+
+

Checks if the given GValue contains a GST_TYPE_DOUBLE_RANGE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_double_range ()

+
void
+gst_value_set_double_range (GValue *value,
+                            gdouble start,
+                            gdouble end);
+

Sets value + to the range specified by start + and end +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_DOUBLE_RANGE

 

start

the start of the range

 

end

the end of the range

 
+
+
+
+
+

gst_value_get_double_range_min ()

+
gdouble
+gst_value_get_double_range_min (const GValue *value);
+

Gets the minimum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_DOUBLE_RANGE

 
+
+
+

Returns

+

the minimum of the range

+
+
+
+
+

gst_value_get_double_range_max ()

+
gdouble
+gst_value_get_double_range_max (const GValue *value);
+

Gets the maximum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_DOUBLE_RANGE

 
+
+
+

Returns

+

the maximum of the range

+
+
+
+
+

GST_VALUE_HOLDS_LIST()

+
#define GST_VALUE_HOLDS_LIST(x)         ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_list_type)
+
+

Checks if the given GValue contains a GST_TYPE_LIST value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

GST_VALUE_HOLDS_ARRAY()

+
#define GST_VALUE_HOLDS_ARRAY(x)        ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_array_type)
+
+

Checks if the given GValue contains a GST_TYPE_ARRAY value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_list_append_value ()

+
void
+gst_value_list_append_value (GValue *value,
+                             const GValue *append_value);
+

Appends append_value + to the GstValueList in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_LIST

 

append_value

the value to append.

[transfer none]
+
+
+
+
+

gst_value_list_append_and_take_value ()

+
void
+gst_value_list_append_and_take_value (GValue *value,
+                                      GValue *append_value);
+

Appends append_value + to the GstValueList in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_LIST

 

append_value

the value to append.

[transfer full]
+
+

Since: 1.2

+
+
+
+

gst_value_list_prepend_value ()

+
void
+gst_value_list_prepend_value (GValue *value,
+                              const GValue *prepend_value);
+

Prepends prepend_value + to the GstValueList in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_LIST

 

prepend_value

the value to prepend

 
+
+
+
+
+

gst_value_list_concat ()

+
void
+gst_value_list_concat (GValue *dest,
+                       const GValue *value1,
+                       const GValue *value2);
+

Concatenates copies of value1 + and value2 + into a list. Values that are not +of type GST_TYPE_LIST are treated as if they were lists of length 1. +dest + will be initialized to the type GST_TYPE_LIST.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

an uninitialized GValue to take the result.

[out caller-allocates]

value1

a GValue

 

value2

a GValue

 
+
+
+
+
+

gst_value_list_merge ()

+
void
+gst_value_list_merge (GValue *dest,
+                      const GValue *value1,
+                      const GValue *value2);
+

Merges copies of value1 + and value2 +. Values that are not +of type GST_TYPE_LIST are treated as if they were lists of length 1.

+

The result will be put into dest + and will either be a list that will not +contain any duplicates, or a non-list type (if value1 + and value2 + +were equal).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

an uninitialized GValue to take the result.

[out caller-allocates]

value1

a GValue

 

value2

a GValue

 
+
+
+
+
+

gst_value_list_get_size ()

+
guint
+gst_value_list_get_size (const GValue *value);
+

Gets the number of values contained in value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue of type GST_TYPE_LIST

 
+
+
+

Returns

+

the number of values

+
+
+
+
+

gst_value_list_get_value ()

+
const GValue *
+gst_value_list_get_value (const GValue *value,
+                          guint index);
+

Gets the value that is a member of the list contained in value + and +has the index index +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_LIST

 

index

index of value to get from the list

 
+
+
+

Returns

+

the value at the given index.

+

[transfer none]

+
+
+
+
+

GST_VALUE_HOLDS_FRACTION()

+
#define GST_VALUE_HOLDS_FRACTION(x)     ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_type)
+
+

Checks if the given GValue contains a GST_TYPE_FRACTION value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_fraction ()

+
void
+gst_value_set_fraction (GValue *value,
+                        gint numerator,
+                        gint denominator);
+

Sets value + to the fraction specified by numerator + over denominator +. +The fraction gets reduced to the smallest numerator and denominator, +and if necessary the sign is moved to the numerator.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION

 

numerator

the numerator of the fraction

 

denominator

the denominator of the fraction

 
+
+
+
+
+

gst_value_get_fraction_numerator ()

+
gint
+gst_value_get_fraction_numerator (const GValue *value);
+

Gets the numerator of the fraction specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION

 
+
+
+

Returns

+

the numerator of the fraction.

+
+
+
+
+

gst_value_get_fraction_denominator ()

+
gint
+gst_value_get_fraction_denominator (const GValue *value);
+

Gets the denominator of the fraction specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION

 
+
+
+

Returns

+

the denominator of the fraction.

+
+
+
+
+

gst_value_fraction_multiply ()

+
gboolean
+gst_value_fraction_multiply (GValue *product,
+                             const GValue *factor1,
+                             const GValue *factor2);
+

Multiplies the two GValue items containing a GST_TYPE_FRACTION and sets +product + to the product of the two fractions.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

product

a GValue initialized to GST_TYPE_FRACTION

 

factor1

a GValue initialized to GST_TYPE_FRACTION

 

factor2

a GValue initialized to GST_TYPE_FRACTION

 
+
+
+

Returns

+

FALSE in case of an error (like integer overflow), TRUE otherwise.

+
+
+
+
+

gst_value_fraction_subtract ()

+
gboolean
+gst_value_fraction_subtract (GValue *dest,
+                             const GValue *minuend,
+                             const GValue *subtrahend);
+

Subtracts the subtrahend + from the minuend + and sets dest + to the result.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

a GValue initialized to GST_TYPE_FRACTION

 

minuend

a GValue initialized to GST_TYPE_FRACTION

 

subtrahend

a GValue initialized to GST_TYPE_FRACTION

 
+
+
+

Returns

+

FALSE in case of an error (like integer overflow), TRUE otherwise.

+
+
+
+
+

GST_VALUE_HOLDS_FRACTION_RANGE()

+
#define GST_VALUE_HOLDS_FRACTION_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_range_type)
+
+

Checks if the given GValue contains a GST_TYPE_FRACTION_RANGE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_fraction_range ()

+
void
+gst_value_set_fraction_range (GValue *value,
+                              const GValue *start,
+                              const GValue *end);
+

Sets value + to the range specified by start + and end +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION_RANGE

 

start

the start of the range (a GST_TYPE_FRACTION GValue)

 

end

the end of the range (a GST_TYPE_FRACTION GValue)

 
+
+
+
+
+

gst_value_get_fraction_range_min ()

+
const GValue *
+gst_value_get_fraction_range_min (const GValue *value);
+

Gets the minimum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION_RANGE

 
+
+
+

Returns

+

the minimum of the range.

+

[nullable]

+
+
+
+
+

gst_value_get_fraction_range_max ()

+
const GValue *
+gst_value_get_fraction_range_max (const GValue *value);
+

Gets the maximum of the range specified by value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION_RANGE

 
+
+
+

Returns

+

the maximum of the range.

+

[nullable]

+
+
+
+
+

gst_value_set_fraction_range_full ()

+
void
+gst_value_set_fraction_range_full (GValue *value,
+                                   gint numerator_start,
+                                   gint denominator_start,
+                                   gint numerator_end,
+                                   gint denominator_end);
+

Sets value + to the range specified by numerator_start +/denominator_start + +and numerator_end +/denominator_end +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_FRACTION_RANGE

 

numerator_start

the numerator start of the range

 

denominator_start

the denominator start of the range

 

numerator_end

the numerator end of the range

 

denominator_end

the denominator end of the range

 
+
+
+
+
+

GST_VALUE_HOLDS_DATE_TIME()

+
#define GST_VALUE_HOLDS_DATE_TIME(x)    ((x) != NULL && G_VALUE_TYPE(x) == _gst_date_time_type)
+
+

Checks if the given GValue contains a GST_TYPE_DATE_TIME value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

GST_VALUE_HOLDS_CAPS()

+
#define GST_VALUE_HOLDS_CAPS(x)         ((x) != NULL && G_VALUE_TYPE(x) == _gst_caps_type)
+
+

Checks if the given GValue contains a GST_TYPE_CAPS value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_caps ()

+
void
+gst_value_set_caps (GValue *value,
+                    const GstCaps *caps);
+

Sets the contents of value + to caps +. A reference to the +provided caps + will be taken by the value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_CAPS

 

caps

the caps to set the value to.

[transfer none]
+
+
+
+
+

gst_value_get_caps ()

+
const GstCaps *
+gst_value_get_caps (const GValue *value);
+

Gets the contents of value +. The reference count of the returned +GstCaps will not be modified, therefore the caller must take one +before getting rid of the value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_CAPS

 
+
+
+

Returns

+

the contents of value +.

+

[transfer none]

+
+
+
+
+

GST_VALUE_HOLDS_CAPS_FEATURES()

+
#define GST_VALUE_HOLDS_CAPS_FEATURES(x)        (G_VALUE_HOLDS((x), _gst_caps_features_type))
+
+

Checks if the given GValue contains a GST_TYPE_CAPS_FEATURES value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_caps_features ()

+
void
+gst_value_set_caps_features (GValue *value,
+                             const GstCapsFeatures *features);
+

Sets the contents of value + to features +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_CAPS_FEATURES

 

features

the features to set the value to

 
+
+
+
+
+

gst_value_get_caps_features ()

+
const GstCapsFeatures *
+gst_value_get_caps_features (const GValue *value);
+

Gets the contents of value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_CAPS_FEATURES

 
+
+
+

Returns

+

the contents of value +.

+

[transfer none]

+
+
+
+
+

GST_VALUE_HOLDS_STRUCTURE()

+
#define GST_VALUE_HOLDS_STRUCTURE(x)            (G_VALUE_HOLDS((x), _gst_structure_type))
+
+

Checks if the given GValue contains a GST_TYPE_STRUCTURE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_set_structure ()

+
void
+gst_value_set_structure (GValue *value,
+                         const GstStructure *structure);
+

Sets the contents of value + to structure +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue initialized to GST_TYPE_STRUCTURE

 

structure

the structure to set the value to

 
+
+
+
+
+

gst_value_get_structure ()

+
const GstStructure *
+gst_value_get_structure (const GValue *value);
+

Gets the contents of value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue initialized to GST_TYPE_STRUCTURE

 
+
+
+

Returns

+

the contents of value +.

+

[transfer none]

+
+
+
+
+

GST_VALUE_HOLDS_BUFFER()

+
#define GST_VALUE_HOLDS_BUFFER(x)       ((x) != NULL && G_VALUE_TYPE(x) == _gst_buffer_type)
+
+

Checks if the given GValue contains a GST_TYPE_BUFFER value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_get_buffer()

+
#define         gst_value_get_buffer(v)         GST_BUFFER_CAST (g_value_get_boxed(v))
+
+

Receives a GstBuffer as the value of v +. Does not return a reference to +the buffer, so the pointer is only valid for as long as the caller owns +a reference to v +.

+
+

Parameters

+
+++++ + + + + + +

v

a GValue to query

 
+
+
+

Returns

+

buffer.

+

[transfer none]

+
+
+
+
+

gst_value_set_buffer()

+
#define         gst_value_set_buffer(v,b)       g_value_set_boxed((v),(b))
+
+

Sets b + as the value of v +. Caller retains reference to buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v

a GValue to receive the data

 

b

a GstBuffer to assign to the GstValue.

[transfer none]
+
+
+
+
+

gst_value_take_buffer()

+
#define         gst_value_take_buffer(v,b)      g_value_take_boxed(v,(b))
+
+

Sets b + as the value of v +. Caller gives away reference to buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v

a GValue to receive the data

 

b

a GstBuffer to assign to the GstValue.

[transfer full]
+
+
+
+
+

GST_VALUE_HOLDS_SAMPLE()

+
#define GST_VALUE_HOLDS_SAMPLE(x)       ((x) != NULL && G_VALUE_TYPE(x) == _gst_sample_type)
+
+

Checks if the given GValue contains a GST_TYPE_SAMPLE value.

+
+

Parameters

+
+++++ + + + + + +

x

the GValue to check

 
+
+
+
+
+

gst_value_get_sample()

+
#define         gst_value_get_sample(v)         GST_SAMPLE_CAST (g_value_get_boxed(v))
+
+

Receives a GstSample as the value of v +. Does not return a reference to +the sample, so the pointer is only valid for as long as the caller owns +a reference to v +.

+
+

Parameters

+
+++++ + + + + + +

v

a GValue to query

 
+
+
+

Returns

+

sample.

+

[transfer none]

+
+
+
+
+

gst_value_set_sample()

+
#define         gst_value_set_sample(v,b)       g_value_set_boxed((v),(b))
+
+

Sets b + as the value of v +. Caller retains reference to sample.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v

a GValue to receive the data

 

b

a GstSample to assign to the GstValue.

[transfer none]
+
+
+
+
+

gst_value_take_sample()

+
#define         gst_value_take_sample(v,b)      g_value_take_boxed(v,(b))
+
+

Sets b + as the value of v +. Caller gives away reference to sample.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

v

a GValue to receive the data

 

b

a GstSample to assign to the GstValue.

[transfer full]
+
+
+
+
+

GstValueCompareFunc ()

+
gint
+(*GstValueCompareFunc) (const GValue *value1,
+                        const GValue *value2);
+

Used together with gst_value_compare() to compare GValue items.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

first value for comparison

 

value2

second value for comparison

 
+
+
+

Returns

+

one of GST_VALUE_LESS_THAN, GST_VALUE_EQUAL, GST_VALUE_GREATER_THAN +or GST_VALUE_UNORDERED

+
+
+
+
+

GstValueSerializeFunc ()

+
gchar *
+(*GstValueSerializeFunc) (const GValue *value1);
+

Used by gst_value_serialize() to obtain a non-binary form of the GValue.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

value1

a GValue

 
+
+
+

Returns

+

the string representation of the value.

+

[transfer full]

+
+
+
+
+

GstValueDeserializeFunc ()

+
gboolean
+(*GstValueDeserializeFunc) (GValue *dest,
+                            const gchar *s);
+

Used by gst_value_deserialize() to parse a non-binary form into the GValue.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

a GValue

 

s

a string

 
+
+
+

Returns

+

TRUE for success

+
+
+
+
+

gst_value_is_fixed ()

+
gboolean
+gst_value_is_fixed (const GValue *value);
+

Tests if the given GValue, if available in a GstStructure (or any other +container) contains a "fixed" (which means: one value) or an "unfixed" +(which means: multiple possible values, such as data lists or data +ranges) value.

+
+

Parameters

+
+++++ + + + + + +

value

the GValue to check

 
+
+
+

Returns

+

true if the value is "fixed".

+
+
+
+
+

gst_value_register ()

+
void
+gst_value_register (const GstValueTable *table);
+

Registers functions to perform calculations on GValue items of a given +type. Each type can only be added once.

+
+

Parameters

+
+++++ + + + + + +

table

structure containing functions to register

 
+
+
+
+
+

gst_value_init_and_copy ()

+
void
+gst_value_init_and_copy (GValue *dest,
+                         const GValue *src);
+

Initialises the target value to be of the same type as source and then copies +the contents from source to target.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

the target value.

[out caller-allocates]

src

the source value

 
+
+
+
+
+

gst_value_serialize ()

+
gchar *
+gst_value_serialize (const GValue *value);
+

tries to transform the given value + into a string representation that allows +getting back this string later on using gst_value_deserialize().

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

value

a GValue to serialize

 
+
+
+

Returns

+

the serialization for value +or NULL if none exists.

+

[transfer full][nullable]

+
+
+
+
+

gst_value_deserialize ()

+
gboolean
+gst_value_deserialize (GValue *dest,
+                       const gchar *src);
+

Tries to deserialize a string into the type specified by the given GValue. +If the operation succeeds, TRUE is returned, FALSE otherwise.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

GValue to fill with contents of +deserialization.

[out caller-allocates]

src

string to deserialize

 
+
+
+

Returns

+

TRUE on success

+
+
+
+
+

gst_value_compare ()

+
gint
+gst_value_compare (const GValue *value1,
+                   const GValue *value2);
+

Compares value1 + and value2 +. If value1 + and value2 + cannot be +compared, the function returns GST_VALUE_UNORDERED. Otherwise, +if value1 + is greater than value2 +, GST_VALUE_GREATER_THAN is returned. +If value1 + is less than value2 +, GST_VALUE_LESS_THAN is returned. +If the values are equal, GST_VALUE_EQUAL is returned.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

a value to compare

 

value2

another value to compare

 
+
+
+

Returns

+

comparison result

+
+
+
+
+

gst_value_can_compare ()

+
gboolean
+gst_value_can_compare (const GValue *value1,
+                       const GValue *value2);
+

Determines if value1 + and value2 + can be compared.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

a value to compare

 

value2

another value to compare

 
+
+
+

Returns

+

TRUE if the values can be compared

+
+
+
+
+

gst_value_union ()

+
gboolean
+gst_value_union (GValue *dest,
+                 const GValue *value1,
+                 const GValue *value2);
+

Creates a GValue corresponding to the union of value1 + and value2 +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

the destination value.

[out caller-allocates]

value1

a value to union

 

value2

another value to union

 
+
+
+

Returns

+

TRUE if the union succeeded.

+
+
+
+
+

gst_value_can_union ()

+
gboolean
+gst_value_can_union (const GValue *value1,
+                     const GValue *value2);
+

Determines if value1 + and value2 + can be non-trivially unioned. +Any two values can be trivially unioned by adding both of them +to a GstValueList. However, certain types have the possibility +to be unioned in a simpler way. For example, an integer range +and an integer can be unioned if the integer is a subset of the +integer range. If there is the possibility that two values can +be unioned, this function returns TRUE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

a value to union

 

value2

another value to union

 
+
+
+

Returns

+

TRUE if there is a function allowing the two values to +be unioned.

+
+
+
+
+

gst_value_subtract ()

+
gboolean
+gst_value_subtract (GValue *dest,
+                    const GValue *minuend,
+                    const GValue *subtrahend);
+

Subtracts subtrahend + from minuend + and stores the result in dest +. +Note that this means subtraction as in sets, not as in mathematics.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

the destination value +for the result if the subtraction is not empty. May be NULL, +in which case the resulting set will not be computed, which can +give a fair speedup.

[out caller-allocates][allow-none]

minuend

the value to subtract from

 

subtrahend

the value to subtract

 
+
+
+

Returns

+

TRUE if the subtraction is not empty

+
+
+
+
+

gst_value_can_subtract ()

+
gboolean
+gst_value_can_subtract (const GValue *minuend,
+                        const GValue *subtrahend);
+

Checks if it's possible to subtract subtrahend + from minuend +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

minuend

the value to subtract from

 

subtrahend

the value to subtract

 
+
+
+

Returns

+

TRUE if a subtraction is possible

+
+
+
+
+

gst_value_intersect ()

+
gboolean
+gst_value_intersect (GValue *dest,
+                     const GValue *value1,
+                     const GValue *value2);
+

Calculates the intersection of two values. If the values have +a non-empty intersection, the value representing the intersection +is placed in dest +, unless NULL. If the intersection is non-empty, +dest + is not modified.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

dest

a uninitialized GValue that will hold the calculated +intersection value. May be NULL if the resulting set if not +needed.

[out caller-allocates][transfer full][allow-none]

value1

a value to intersect

 

value2

another value to intersect

 
+
+
+

Returns

+

TRUE if the intersection is non-empty

+
+
+
+
+

gst_value_can_intersect ()

+
gboolean
+gst_value_can_intersect (const GValue *value1,
+                         const GValue *value2);
+

Determines if intersecting two values will produce a valid result. +Two values will produce a valid intersection if they have the same +type.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

a value to intersect

 

value2

another value to intersect

 
+
+
+

Returns

+

TRUE if the values can intersect

+
+
+
+
+

gst_value_is_subset ()

+
gboolean
+gst_value_is_subset (const GValue *value1,
+                     const GValue *value2);
+

Check that value1 + is a subset of value2 +.

+

Return: TRUE is value1 + is a subset of value2 +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value1

a GValue

 

value2

a GValue

 
+
+
+
+
+

gst_value_array_append_value ()

+
void
+gst_value_array_append_value (GValue *value,
+                              const GValue *append_value);
+

Appends append_value + to the GstValueArray in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_ARRAY

 

append_value

the value to append

 
+
+
+
+
+

gst_value_array_append_and_take_value ()

+
void
+gst_value_array_append_and_take_value (GValue *value,
+                                       GValue *append_value);
+

Appends append_value + to the GstValueArray in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_ARRAY

 

append_value

the value to append.

[transfer full]
+
+

Since: 1.2

+
+
+
+

gst_value_array_get_size ()

+
guint
+gst_value_array_get_size (const GValue *value);
+

Gets the number of values contained in value +.

+
+

Parameters

+
+++++ + + + + + +

value

a GValue of type GST_TYPE_ARRAY

 
+
+
+

Returns

+

the number of values

+
+
+
+
+

gst_value_array_get_value ()

+
const GValue *
+gst_value_array_get_value (const GValue *value,
+                           guint index);
+

Gets the value that is a member of the array contained in value + and +has the index index +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_ARRAY

 

index

index of value to get from the array

 
+
+
+

Returns

+

the value at the given index.

+

[transfer none]

+
+
+
+
+

gst_value_array_prepend_value ()

+
void
+gst_value_array_prepend_value (GValue *value,
+                               const GValue *prepend_value);
+

Prepends prepend_value + to the GstValueArray in value +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

value

a GValue of type GST_TYPE_ARRAY

 

prepend_value

the value to prepend

 
+
+
+
+
+

gst_value_fixate ()

+
gboolean
+gst_value_fixate (GValue *dest,
+                  const GValue *src);
+

Fixate src + into a new value dest +. +For ranges, the first element is taken. For lists and arrays, the +first item is fixated and returned. +If src + is already fixed, this function returns FALSE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

dest

the GValue destination

 

src

the GValue to fixate

 
+
+
+

Returns

+

TRUE if dest +contains a fixated version of src +.

+
+
+
+
+

gst_flagset_register ()

+
GType
+gst_flagset_register (GType flags_type);
+

Create a new sub-class of GST_TYPE_FLAG_SET +which will pretty-print the human-readable flags +when serializing, for easier debugging.

+
+

Parameters

+
+++++ + + + + + +

flags_type

a GType of a G_TYPE_FLAGS type.

 
+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GST_FOURCC_FORMAT

+
#define GST_FOURCC_FORMAT "c%c%c%c"
+
+

Can be used together with GST_FOURCC_ARGS to properly output a +guint32 fourcc value in a printf()-style text message.

+
+ + + + + + + +
1
printf ("fourcc: %" GST_FOURCC_FORMAT "\n", GST_FOURCC_ARGS (fcc));
+
+ +

+
+
+
+

GST_TYPE_INT_RANGE

+
#define GST_TYPE_INT_RANGE               (_gst_int_range_type)
+
+

a GValue type that represents an integer range

+
+

Returns

+

the GType of GstIntRange

+
+
+
+
+

GST_TYPE_BITMASK

+
#define GST_TYPE_BITMASK                 (_gst_bitmask_type)
+
+

a GValue type that represents a 64-bit bitmask.

+
+

Returns

+

the GType of GstBitmask (which is not explicitly typed)

+
+
+
+
+

GST_TYPE_FLAG_SET

+
#define GST_TYPE_FLAG_SET                   (_gst_flagset_type)
+
+

a GValue type that represents a 32-bit flag bitfield, with 32-bit +mask indicating which of the bits in the field are explicitly set. +Useful for negotiation.

+
+

Returns

+

the GType of GstFlags (which is not explicitly typed)

+
+

Since: 1.6

+
+
+
+

GST_FLAG_SET_MASK_EXACT

+
#define GST_FLAG_SET_MASK_EXACT ((guint)(-1))
+
+

A mask value with all bits set, for use as a +GstFlagSet mask where all flag bits must match +exactly

+

Since: 1.6

+
+
+
+

GST_TYPE_INT64_RANGE

+
#define GST_TYPE_INT64_RANGE             (_gst_int64_range_type)
+
+

a GValue type that represents an gint64 range

+
+

Returns

+

the GType of GstInt64Range

+
+
+
+
+

GST_TYPE_DOUBLE_RANGE

+
#define GST_TYPE_DOUBLE_RANGE            (_gst_double_range_type)
+
+

a GValue type that represents a floating point range with double precision

+
+

Returns

+

the GType of GstIntRange

+
+
+
+
+

GST_TYPE_LIST

+
#define GST_TYPE_LIST                    (_gst_value_list_type)
+
+

a GValue type that represents an unordered list of GValue values. This +is used for example to express a list of possible values for a field in +a caps structure, like a list of possible sample rates, of which only one +will be chosen in the end. This means that all values in the list are +meaningful on their own.

+
+

Returns

+

the GType of GstValueList (which is not explicitly typed)

+
+
+
+
+

GST_TYPE_ARRAY

+
#define GST_TYPE_ARRAY                   (_gst_value_array_type)
+
+

a GValue type that represents an ordered list of GValue values. This is +used to express a set of values that is meaningful only in their specific +combination and order of values. Each value on its own is not particularly +meaningful, only the ordered array in its entirety is meaningful. This is +used for example to express channel layouts for multichannel audio where +each channel needs to be mapped to a position in the room.

+
+

Returns

+

the GType of GstArrayList (which is not explicitly typed)

+
+
+
+
+

GST_TYPE_FRACTION

+
#define GST_TYPE_FRACTION                (_gst_fraction_type)
+
+

a GValue type that represents a fraction of an integer numerator over +an integer denominator

+
+

Returns

+

the GType of GstFraction (which is not explicitly typed)

+
+
+
+
+

GST_TYPE_FRACTION_RANGE

+
#define GST_TYPE_FRACTION_RANGE           (_gst_fraction_range_type)
+
+

a GValue type that represents a GstFraction range

+
+

Returns

+

the GType of GstFractionRange

+
+
+
+
+

GST_VALUE_LESS_THAN

+
#define GST_VALUE_LESS_THAN              (-1)
+
+

Indicates that the first value provided to a comparison function +(gst_value_compare()) is lesser than the second one.

+
+
+
+

GST_VALUE_EQUAL

+
#define GST_VALUE_EQUAL                   0
+
+

Indicates that the first value provided to a comparison function +(gst_value_compare()) is equal to the second one.

+
+
+
+

GST_VALUE_GREATER_THAN

+
#define GST_VALUE_GREATER_THAN            1
+
+

Indicates that the first value provided to a comparison function +(gst_value_compare()) is greater than the second one.

+
+
+
+

GST_VALUE_UNORDERED

+
#define GST_VALUE_UNORDERED               2
+
+

Indicates that the comparison function (gst_value_compare()) can not +determine a order for the two provided values.

+
+
+
+

struct GstValueTable

+
struct GstValueTable {
+  GType type;
+  GstValueCompareFunc compare;
+  GstValueSerializeFunc serialize;
+  GstValueDeserializeFunc deserialize;
+};
+
+

VTable for the GValue type +.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GType type;

a GType

 

GstValueCompareFunc compare;

a GstValueCompareFunc

 

GstValueSerializeFunc serialize;

a GstValueSerializeFunc

 

GstValueDeserializeFunc deserialize;

a GstValueDeserializeFunc

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-GstVersion.html b/docs/gst/html/gstreamer-GstVersion.html new file mode 100644 index 0000000..731c459 --- /dev/null +++ b/docs/gst/html/gstreamer-GstVersion.html @@ -0,0 +1,163 @@ + + + + +GstVersion: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstVersion

+

GstVersion — GStreamer version macros.

+
+
+

Functions

+
++++ + + + + +
#define +GST_CHECK_VERSION() +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + +
#defineGST_VERSION_MAJOR
#defineGST_VERSION_MINOR
#defineGST_VERSION_MICRO
#defineGST_VERSION_NANO
+
+
+

Includes

+
#include <gst/gstprotection.h>
+
+
+
+

Description

+

Use the GST_VERSION_* macros e.g. when defining own plugins. The GStreamer +runtime checks if these plugin and core version match and refuses to use a +plugin compiled against a different version of GStreamer. +You can also use the macros to keep the GStreamer version information in +your application.

+

Use the gst_version() function if you want to know which version of +GStreamer you are currently linked against.

+

The version macros get defined by including "gst/gst.h".

+
+
+

Functions

+
+

GST_CHECK_VERSION()

+
#define             GST_CHECK_VERSION(major,minor,micro)
+

Check whether a GStreamer version equal to or greater than +major.minor.micro is present.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

major

a number indicating the major version

 

minor

a number indicating the minor version

 

micro

a number indicating the micro version

 
+
+
+
+
+

Types and Values

+
+

GST_VERSION_MAJOR

+
#define GST_VERSION_MAJOR (1)
+
+

The major version of GStreamer at compile time:

+
+
+
+

GST_VERSION_MINOR

+
#define GST_VERSION_MINOR (14)
+
+

The minor version of GStreamer at compile time:

+
+
+
+

GST_VERSION_MICRO

+
#define GST_VERSION_MICRO (1)
+
+

The micro version of GStreamer at compile time:

+
+
+
+

GST_VERSION_NANO

+
#define GST_VERSION_NANO (0)
+
+

The nano version of GStreamer at compile time: +Actual releases have 0, GIT versions have 1, prerelease versions have 2-...

+
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-device-probing.html b/docs/gst/html/gstreamer-device-probing.html new file mode 100644 index 0000000..1866f2a --- /dev/null +++ b/docs/gst/html/gstreamer-device-probing.html @@ -0,0 +1,43 @@ + + + + +GStreamer Device Discovery and Device Probing: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Device Discovery and Device Probing

+
+
+GstDeviceMonitor — A device monitor and prober +
+
+GstDevice — Object representing a device +
+
+GstDeviceProvider — A device provider +
+
+GstDeviceProviderFactory — Create GstDeviceProviders from a factory +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-hierarchy.html b/docs/gst/html/gstreamer-hierarchy.html new file mode 100644 index 0000000..5ce0c72 --- /dev/null +++ b/docs/gst/html/gstreamer-hierarchy.html @@ -0,0 +1,85 @@ + + + + +Object Hierarchy: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Object Hierarchy

+
+    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ├── GstAllocator
+            ├── GstPad
+               ╰── GstProxyPad
+                   ╰── GstGhostPad
+            ├── GstPadTemplate
+            ├── GstPluginFeature
+               ├── GstElementFactory
+               ├── GstTracerFactory
+               ├── GstTypeFindFactory
+               ├── GstDeviceProviderFactory
+               ╰── GstDynamicTypeFactory
+            ├── GstElement
+               ╰── GstBin
+                   ╰── GstPipeline
+            ├── GstBus
+            ├── GstTask
+            ├── GstTaskPool
+            ├── GstClock
+               ╰── GstSystemClock
+            ├── GstControlBinding
+            ├── GstControlSource
+            ├── GstPlugin
+            ├── GstRegistry
+            ├── GstBufferPool
+            ├── GstTracer
+            ╰── GstTracerRecord
+    GInterface
+    ├── GstChildProxy
+    ├── GstURIHandler
+    ├── GstPreset
+    ╰── GstTagSetter
+    GBoxed
+    ├── GstMemory
+    ├── GstQuery
+    ├── GstStructure
+    ├── GstCaps
+    ├── GstCapsFeatures
+    ├── GstMessage
+    ├── GstEvent
+    ├── GstBuffer
+    ├── GstBufferList
+    ├── GstSample
+    ├── GstContext
+    ├── GstDateTime
+    ├── GstTagList
+    ├── GstSegment
+    ├── GstAllocationParams
+    ├── GstToc
+    ├── GstTocEntry
+    ├── GstParseContext
+    ╰── GstPromise
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer-support.html b/docs/gst/html/gstreamer-support.html new file mode 100644 index 0000000..bacbb71 --- /dev/null +++ b/docs/gst/html/gstreamer-support.html @@ -0,0 +1,47 @@ + + + + +GStreamer Core Support: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Core Support

+
+
+GstInfo — Debugging and logging facilities +
+
+GstTracer — Tracing base class +
+
+GstTracerFactory — Information about registered tracer functions +
+
+GstTracerRecord — Trace log entry class +
+
+

+ Theses modules support the gstreamer core and plugin development. + Application developers will rarely need to know about it. +

+
+ + + \ No newline at end of file diff --git a/docs/gst/html/gstreamer.html b/docs/gst/html/gstreamer.html new file mode 100644 index 0000000..47fb07f --- /dev/null +++ b/docs/gst/html/gstreamer.html @@ -0,0 +1,56 @@ + + + + +GStreamer Overview: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Overview

+
+
+Building GStreamer and GStreamer Applications — +How to build the GStreamer framework and applications using it. + +
+
+Running GStreamer Applications — +How to run and debug your GStreamer application + +
+
+

+GStreamer is a streaming media framework. +It uses graphs of elements which operate on data. +The functionality to process media is provided by plug-ins which provide +features like elements, typefinding, and so on. +This allows new functionality to be added simply by installing new plug-ins. +

+

+GStreamer is cross-platform and works on most UNIX-like platforms as well as +Windows. It is released under the GNU Library General Public License +(GNU LGPL). +

+
+

Relation between gstreamer core objects.

+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/home.png b/docs/gst/html/home.png new file mode 100644 index 0000000..effb5ea Binary files /dev/null and b/docs/gst/html/home.png differ diff --git a/docs/gst/html/index.html b/docs/gst/html/index.html new file mode 100644 index 0000000..de863df --- /dev/null +++ b/docs/gst/html/index.html @@ -0,0 +1,290 @@ + + + + +GStreamer 1.0 Core Reference Manual: GStreamer 1.0 Core Reference Manual + + + + + + + +
+
+
+
+

+ for GStreamer Core 1.0 (1.14.1) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/. +

+
+
+
+
+
GStreamer Overview
+
+
+Building GStreamer and GStreamer Applications — +How to build the GStreamer framework and applications using it. + +
+
+Running GStreamer Applications — +How to run and debug your GStreamer application + +
+
+
GStreamer Core Library
+
+
+GStreamer — Media library supporting arbitrary formats and filter + graphs. +
+
+GstAllocator — allocate memory blocks +
+
+GstAtomicQueue — An atomic queue implementation +
+
+GstBin — Base class and element that can contain other elements +
+
+GstBuffer — Data-passing buffer type +
+
+GstBufferList — Lists of buffers for data-passing +
+
+GstBufferPool — Pool for buffers +
+
+GstBus — Asynchronous message bus subsystem +
+
+GstCaps — Structure describing sets of media formats +
+
+GstCapsFeatures — A set of features in caps +
+
+GstSample — A media sample +
+
+GstChildProxy — Interface for multi child elements. +
+
+GstClock — Abstract class for global clocks +
+
+GstConfig — Build configuration options +
+
+GstContext — Lightweight objects to represent element contexts +
+
+GstControlBinding — attachment for control source sources +
+
+GstControlSource — base class for control source sources +
+
+GstDateTime — A date, time and timezone structure +
+
+GstDynamicTypeFactory — Represents a registered dynamically loadable GType +
+
+GstElement — Abstract base class for all pipeline elements +
+
+GstElementFactory — Create GstElements from a factory +
+
+GstError — Categorized error messages +
+
+GstEvent — Structure describing events that are passed up and down + a pipeline +
+
+GstFormat — Dynamically register new data formats +
+
+GstGhostPad — Pseudo link pads +
+
+GstIterator — Object to retrieve multiple elements in a threadsafe +way. +
+
+GstMemory — refcounted wrapper for memory blocks +
+
+GstMessage — Lightweight objects to signal the application of + pipeline events +
+
+GstMeta — Buffer metadata +
+
+GstMiniObject — Lightweight base class for the GStreamer object hierarchy +
+
+GstObject — Base class for the GStreamer object hierarchy +
+
+GstPad — Object contained by elements that allows links to + other elements +
+
+GstPadTemplate — Describe the media type of a pad. +
+
+GstParamSpec — GParamSpec implementations specific +to GStreamer +
+
+GstParse — Get a pipeline from a text pipeline description +
+
+GstPipeline — Top-level bin with clocking and bus management + functionality. +
+
+GstPlugin — Container for features loaded from a shared object module +
+
+GstPluginfeature — Base class for contents of a GstPlugin +
+
+GstPoll — Keep track of file descriptors and make it possible + to wait on them in a cancellable way +
+
+GstPreset — helper interface for element presets +
+
+GstPromise — a miniobject for future/promise-like functionality +
+
+GstProtection — Functions and classes to support encrypted streams. +
+
+GstQuery — Provide functions to create queries, and to set and parse + values in them. +
+
+GstRegistry — Abstract base class for management of GstPlugin objects +
+
+GstSegment — Structure describing the configured region of interest + in a media file. +
+
+GstStreams — Base class for stream objects +
+
+GstStreamCollection — Base class for collection of streams +
+
+GstStructure — Generic structure containing fields of names and values +
+
+GstSystemClock — Default clock that uses the current system time +
+
+GstTagList — List of tags and values used to describe media metadata +
+
+GstTagsetter — Element interface that allows setting and retrieval + of media metadata +
+
+GstTask — Abstraction of GStreamer streaming threads. +
+
+GstTaskPool — Pool of GStreamer streaming threads +
+
+GstToc — Generic table of contents support +
+
+GstTocSetter — Element interface that allows setting and retrieval + of the TOC +
+
+GstTypefind — Stream type detection +
+
+GstTypeFindFactory — Information about registered typefind functions +
+
+GstUri — URI parsing and manipulation. +
+
+GstUriHandler — Interface to ease URI handling in plugins. +
+
+GstUtils — Various utility functions +
+
+GstValue — GValue implementations specific +to GStreamer +
+
+GstVersion — GStreamer version macros. +
+
+
GStreamer Device Discovery and Device Probing
+
+
+GstDeviceMonitor — A device monitor and prober +
+
+GstDevice — Object representing a device +
+
+GstDeviceProvider — A device provider +
+
+GstDeviceProviderFactory — Create GstDeviceProviders from a factory +
+
+
GStreamer Core Support
+
+
+GstInfo — Debugging and logging facilities +
+
+GstTracer — Tracing base class +
+
+GstTracerFactory — Information about registered tracer functions +
+
+GstTracerRecord — Trace log entry class +
+
+
Object Hierarchy
+
API Index
+
Index of deprecated API
+
Index of new API in 1.14
+
Index of new API in 1.12
+
Index of new API in 1.10
+
Index of new API in 1.8
+
Index of new API in 1.6
+
Index of new API in 1.4
+
Index of new API in 1.2.3
+
Index of new API in 1.2
+
Index of new API in 1.0.10
+
Index of new API in 1.0.5
+
Annotation Glossary
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix01.html b/docs/gst/html/ix01.html new file mode 100644 index 0000000..88a9ee4 --- /dev/null +++ b/docs/gst/html/ix01.html @@ -0,0 +1,9671 @@ + + + + +API Index: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+API Index

+

A

+
+GstAllocationParams, struct in GstAllocator +
+
+
+gst_allocation_params_copy, function in GstAllocator +
+
+
+gst_allocation_params_free, function in GstAllocator +
+
+
+gst_allocation_params_init, function in GstAllocator +
+
+
+GstAllocator, struct in GstAllocator +
+
+
+GstAllocatorClass, struct in GstAllocator +
+
+
+GstAllocatorFlags, enum in GstAllocator +
+
+
+gst_allocator_alloc, function in GstAllocator +
+
+
+gst_allocator_find, function in GstAllocator +
+
+
+gst_allocator_free, function in GstAllocator +
+
+
+gst_allocator_register, function in GstAllocator +
+
+
+gst_allocator_set_default, function in GstAllocator +
+
+
+GST_ALLOCATOR_SYSMEM, macro in GstAllocator +
+
+
+GstAtomicQueue, struct in GstAtomicQueue +
+
+
+gst_atomic_queue_length, function in GstAtomicQueue +
+
+
+gst_atomic_queue_new, function in GstAtomicQueue +
+
+
+gst_atomic_queue_peek, function in GstAtomicQueue +
+
+
+gst_atomic_queue_pop, function in GstAtomicQueue +
+
+
+gst_atomic_queue_push, function in GstAtomicQueue +
+
+
+gst_atomic_queue_ref, function in GstAtomicQueue +
+
+
+gst_atomic_queue_unref, function in GstAtomicQueue +
+
+

B

+
+GstBin, struct in GstBin +
+
+
+GstBin::deep-element-added, object signal in GstBin +
+
+
+GstBin::deep-element-removed, object signal in GstBin +
+
+
+GstBin::do-latency, object signal in GstBin +
+
+
+GstBin::element-added, object signal in GstBin +
+
+
+GstBin::element-removed, object signal in GstBin +
+
+
+GstBin:async-handling, object property in GstBin +
+
+
+GstBin:message-forward, object property in GstBin +
+
+
+GstBinClass, struct in GstBin +
+
+
+GstBinFlags, enum in GstBin +
+
+
+gst_bin_add, function in GstBin +
+
+
+gst_bin_add_many, function in GstBin +
+
+
+GST_BIN_CHILDREN, macro in GstBin +
+
+
+GST_BIN_CHILDREN_COOKIE, macro in GstBin +
+
+
+gst_bin_find_unlinked_pad, function in GstBin +
+
+
+gst_bin_get_by_interface, function in GstBin +
+
+
+gst_bin_get_by_name, function in GstBin +
+
+
+gst_bin_get_by_name_recurse_up, function in GstBin +
+
+
+gst_bin_get_suppressed_flags, function in GstBin +
+
+
+GST_BIN_IS_NO_RESYNC, macro in GstBin +
+
+
+gst_bin_iterate_all_by_interface, function in GstBin +
+
+
+gst_bin_iterate_elements, function in GstBin +
+
+
+gst_bin_iterate_recurse, function in GstBin +
+
+
+gst_bin_iterate_sinks, function in GstBin +
+
+
+gst_bin_iterate_sorted, function in GstBin +
+
+
+gst_bin_iterate_sources, function in GstBin +
+
+
+gst_bin_new, function in GstBin +
+
+
+GST_BIN_NUMCHILDREN, macro in GstBin +
+
+
+gst_bin_recalculate_latency, function in GstBin +
+
+
+gst_bin_remove, function in GstBin +
+
+
+gst_bin_remove_many, function in GstBin +
+
+
+gst_bin_set_suppressed_flags, function in GstBin +
+
+
+gst_bin_sync_children_states, function in GstBin +
+
+
+GstBuffer, struct in GstBuffer +
+
+
+GstBufferCopyFlags, enum in GstBuffer +
+
+
+GstBufferFlags, enum in GstBuffer +
+
+
+GstBufferForeachMetaFunc, user_function in GstBuffer +
+
+
+GstBufferingMode, enum in GstQuery +
+
+
+GstBufferList, struct in GstBufferList +
+
+
+GstBufferListFunc, user_function in GstBufferList +
+
+
+GstBufferPool, struct in GstBufferPool +
+
+
+GstBufferPoolAcquireFlags, enum in GstBufferPool +
+
+
+GstBufferPoolAcquireParams, struct in GstBufferPool +
+
+
+GstBufferPoolClass, struct in GstBufferPool +
+
+
+gst_buffer_add_meta, function in GstBuffer +
+
+
+gst_buffer_add_parent_buffer_meta, function in GstBuffer +
+
+
+gst_buffer_add_protection_meta, function in GstProtectionMeta +
+
+
+gst_buffer_add_reference_timestamp_meta, function in GstBuffer +
+
+
+gst_buffer_append, function in GstBuffer +
+
+
+gst_buffer_append_memory, function in GstBuffer +
+
+
+gst_buffer_append_region, function in GstBuffer +
+
+
+gst_buffer_copy, function in GstBuffer +
+
+
+GST_BUFFER_COPY_ALL, macro in GstBuffer +
+
+
+gst_buffer_copy_deep, function in GstBuffer +
+
+
+gst_buffer_copy_into, function in GstBuffer +
+
+
+GST_BUFFER_COPY_METADATA, macro in GstBuffer +
+
+
+gst_buffer_copy_region, function in GstBuffer +
+
+
+GST_BUFFER_DTS, macro in GstBuffer +
+
+
+GST_BUFFER_DTS_IS_VALID, macro in GstBuffer +
+
+
+GST_BUFFER_DTS_OR_PTS, macro in GstBuffer +
+
+
+GST_BUFFER_DURATION, macro in GstBuffer +
+
+
+GST_BUFFER_DURATION_IS_VALID, macro in GstBuffer +
+
+
+gst_buffer_extract, function in GstBuffer +
+
+
+gst_buffer_extract_dup, function in GstBuffer +
+
+
+gst_buffer_fill, function in GstBuffer +
+
+
+gst_buffer_find_memory, function in GstBuffer +
+
+
+GST_BUFFER_FLAGS, macro in GstBuffer +
+
+
+GST_BUFFER_FLAG_IS_SET, macro in GstBuffer +
+
+
+GST_BUFFER_FLAG_SET, macro in GstBuffer +
+
+
+GST_BUFFER_FLAG_UNSET, macro in GstBuffer +
+
+
+gst_buffer_foreach_meta, function in GstBuffer +
+
+
+gst_buffer_get_all_memory, function in GstBuffer +
+
+
+gst_buffer_get_flags, function in GstBuffer +
+
+
+gst_buffer_get_max_memory, function in GstBuffer +
+
+
+gst_buffer_get_memory, function in GstBuffer +
+
+
+gst_buffer_get_memory_range, function in GstBuffer +
+
+
+gst_buffer_get_meta, function in GstBuffer +
+
+
+gst_buffer_get_n_meta, function in GstBuffer +
+
+
+gst_buffer_get_parent_buffer_meta, macro in GstBuffer +
+
+
+gst_buffer_get_protection_meta, macro in GstProtectionMeta +
+
+
+gst_buffer_get_reference_timestamp_meta, function in GstBuffer +
+
+
+gst_buffer_get_size, function in GstBuffer +
+
+
+gst_buffer_get_sizes, function in GstBuffer +
+
+
+gst_buffer_get_sizes_range, function in GstBuffer +
+
+
+gst_buffer_has_flags, function in GstBuffer +
+
+
+gst_buffer_insert_memory, function in GstBuffer +
+
+
+gst_buffer_is_all_memory_writable, function in GstBuffer +
+
+
+GST_BUFFER_IS_DISCONT, macro in GstBuffer +
+
+
+gst_buffer_is_memory_range_writable, function in GstBuffer +
+
+
+gst_buffer_is_writable, macro in GstBuffer +
+
+
+gst_buffer_iterate_meta, function in GstBuffer +
+
+
+gst_buffer_iterate_meta_filtered, function in GstBuffer +
+
+
+gst_buffer_list_add, macro in GstBufferList +
+
+
+gst_buffer_list_calculate_size, function in GstBufferList +
+
+
+gst_buffer_list_copy, function in GstBufferList +
+
+
+gst_buffer_list_copy_deep, function in GstBufferList +
+
+
+gst_buffer_list_foreach, function in GstBufferList +
+
+
+gst_buffer_list_get, function in GstBufferList +
+
+
+gst_buffer_list_get_writable, function in GstBufferList +
+
+
+gst_buffer_list_insert, function in GstBufferList +
+
+
+gst_buffer_list_is_writable, macro in GstBufferList +
+
+
+gst_buffer_list_length, function in GstBufferList +
+
+
+gst_buffer_list_make_writable, macro in GstBufferList +
+
+
+gst_buffer_list_new, function in GstBufferList +
+
+
+gst_buffer_list_new_sized, function in GstBufferList +
+
+
+gst_buffer_list_ref, function in GstBufferList +
+
+
+gst_buffer_list_remove, function in GstBufferList +
+
+
+gst_buffer_list_unref, function in GstBufferList +
+
+
+gst_buffer_make_writable, macro in GstBuffer +
+
+
+gst_buffer_map, function in GstBuffer +
+
+
+gst_buffer_map_range, function in GstBuffer +
+
+
+gst_buffer_memcmp, function in GstBuffer +
+
+
+gst_buffer_memset, function in GstBuffer +
+
+
+gst_buffer_new, function in GstBuffer +
+
+
+gst_buffer_new_allocate, function in GstBuffer +
+
+
+gst_buffer_new_wrapped, function in GstBuffer +
+
+
+gst_buffer_new_wrapped_full, function in GstBuffer +
+
+
+gst_buffer_n_memory, function in GstBuffer +
+
+
+GST_BUFFER_OFFSET, macro in GstBuffer +
+
+
+GST_BUFFER_OFFSET_END, macro in GstBuffer +
+
+
+GST_BUFFER_OFFSET_END_IS_VALID, macro in GstBuffer +
+
+
+GST_BUFFER_OFFSET_IS_VALID, macro in GstBuffer +
+
+
+GST_BUFFER_OFFSET_NONE, macro in GstBuffer +
+
+
+gst_buffer_peek_memory, function in GstBuffer +
+
+
+gst_buffer_pool_acquire_buffer, function in GstBufferPool +
+
+
+gst_buffer_pool_config_add_option, function in GstBufferPool +
+
+
+gst_buffer_pool_config_get_allocator, function in GstBufferPool +
+
+
+gst_buffer_pool_config_get_option, function in GstBufferPool +
+
+
+gst_buffer_pool_config_get_params, function in GstBufferPool +
+
+
+gst_buffer_pool_config_has_option, function in GstBufferPool +
+
+
+gst_buffer_pool_config_n_options, function in GstBufferPool +
+
+
+gst_buffer_pool_config_set_allocator, function in GstBufferPool +
+
+
+gst_buffer_pool_config_set_params, function in GstBufferPool +
+
+
+gst_buffer_pool_config_validate_params, function in GstBufferPool +
+
+
+gst_buffer_pool_get_config, function in GstBufferPool +
+
+
+gst_buffer_pool_get_options, function in GstBufferPool +
+
+
+gst_buffer_pool_has_option, function in GstBufferPool +
+
+
+gst_buffer_pool_is_active, function in GstBufferPool +
+
+
+GST_BUFFER_POOL_IS_FLUSHING, macro in GstBufferPool +
+
+
+gst_buffer_pool_new, function in GstBufferPool +
+
+
+gst_buffer_pool_release_buffer, function in GstBufferPool +
+
+
+gst_buffer_pool_set_active, function in GstBufferPool +
+
+
+gst_buffer_pool_set_config, function in GstBufferPool +
+
+
+gst_buffer_pool_set_flushing, function in GstBufferPool +
+
+
+gst_buffer_prepend_memory, function in GstBuffer +
+
+
+GST_BUFFER_PTS, macro in GstBuffer +
+
+
+GST_BUFFER_PTS_IS_VALID, macro in GstBuffer +
+
+
+gst_buffer_ref, function in GstBuffer +
+
+
+gst_buffer_remove_all_memory, function in GstBuffer +
+
+
+gst_buffer_remove_memory, function in GstBuffer +
+
+
+gst_buffer_remove_memory_range, function in GstBuffer +
+
+
+gst_buffer_remove_meta, function in GstBuffer +
+
+
+gst_buffer_replace, function in GstBuffer +
+
+
+gst_buffer_replace_all_memory, function in GstBuffer +
+
+
+gst_buffer_replace_memory, function in GstBuffer +
+
+
+gst_buffer_replace_memory_range, function in GstBuffer +
+
+
+gst_buffer_resize, function in GstBuffer +
+
+
+gst_buffer_resize_range, function in GstBuffer +
+
+
+gst_buffer_set_flags, function in GstBuffer +
+
+
+gst_buffer_set_size, function in GstBuffer +
+
+
+gst_buffer_unmap, function in GstBuffer +
+
+
+gst_buffer_unref, function in GstBuffer +
+
+
+gst_buffer_unset_flags, function in GstBuffer +
+
+
+GstBus, struct in GstBus +
+
+
+GstBus::message, object signal in GstBus +
+
+
+GstBus::sync-message, object signal in GstBus +
+
+
+GstBus:enable-async, object property in GstBus +
+
+
+GstBusFlags, enum in GstBus +
+
+
+GstBusFunc, user_function in GstBus +
+
+
+GstBusSyncHandler, user_function in GstBus +
+
+
+GstBusSyncReply, enum in GstBus +
+
+
+gst_bus_add_signal_watch, function in GstBus +
+
+
+gst_bus_add_signal_watch_full, function in GstBus +
+
+
+gst_bus_add_watch, function in GstBus +
+
+
+gst_bus_add_watch_full, function in GstBus +
+
+
+gst_bus_async_signal_func, function in GstBus +
+
+
+gst_bus_create_watch, function in GstBus +
+
+
+gst_bus_disable_sync_message_emission, function in GstBus +
+
+
+gst_bus_enable_sync_message_emission, function in GstBus +
+
+
+gst_bus_get_pollfd, function in GstBus +
+
+
+gst_bus_have_pending, function in GstBus +
+
+
+gst_bus_new, function in GstBus +
+
+
+gst_bus_peek, function in GstBus +
+
+
+gst_bus_poll, function in GstBus +
+
+
+gst_bus_pop, function in GstBus +
+
+
+gst_bus_pop_filtered, function in GstBus +
+
+
+gst_bus_post, function in GstBus +
+
+
+gst_bus_remove_signal_watch, function in GstBus +
+
+
+gst_bus_remove_watch, function in GstBus +
+
+
+gst_bus_set_flushing, function in GstBus +
+
+
+gst_bus_set_sync_handler, function in GstBus +
+
+
+gst_bus_sync_signal_handler, function in GstBus +
+
+
+gst_bus_timed_pop, function in GstBus +
+
+
+gst_bus_timed_pop_filtered, function in GstBus +
+
+

C

+
+GST_CALL_PARENT, macro in GstUtils +
+
+
+GST_CALL_PARENT_WITH_DEFAULT, macro in GstUtils +
+
+
+GstCaps, struct in GstCaps +
+
+
+GstCapsFeatures, struct in GstCapsFeatures +
+
+
+GstCapsFilterMapFunc, user_function in GstCaps +
+
+
+GstCapsFlags, enum in GstCaps +
+
+
+GstCapsForeachFunc, user_function in GstCaps +
+
+
+GstCapsIntersectMode, enum in GstCaps +
+
+
+GstCapsMapFunc, user_function in GstCaps +
+
+
+GST_CAPS_ANY, macro in GstCaps +
+
+
+gst_caps_append, function in GstCaps +
+
+
+gst_caps_append_structure, function in GstCaps +
+
+
+gst_caps_append_structure_full, function in GstCaps +
+
+
+gst_caps_can_intersect, function in GstCaps +
+
+
+gst_caps_copy, function in GstCaps +
+
+
+gst_caps_copy_nth, function in GstCaps +
+
+
+gst_caps_features_add, function in GstCapsFeatures +
+
+
+gst_caps_features_add_id, function in GstCapsFeatures +
+
+
+GST_CAPS_FEATURES_ANY, macro in GstCapsFeatures +
+
+
+gst_caps_features_contains, function in GstCapsFeatures +
+
+
+gst_caps_features_contains_id, function in GstCapsFeatures +
+
+
+gst_caps_features_copy, function in GstCapsFeatures +
+
+
+gst_caps_features_free, function in GstCapsFeatures +
+
+
+gst_caps_features_from_string, function in GstCapsFeatures +
+
+
+gst_caps_features_get_nth, function in GstCapsFeatures +
+
+
+gst_caps_features_get_nth_id, function in GstCapsFeatures +
+
+
+gst_caps_features_get_size, function in GstCapsFeatures +
+
+
+gst_caps_features_is_any, function in GstCapsFeatures +
+
+
+gst_caps_features_is_equal, function in GstCapsFeatures +
+
+
+GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, macro in GstCapsFeatures +
+
+
+gst_caps_features_new, function in GstCapsFeatures +
+
+
+gst_caps_features_new_any, function in GstCapsFeatures +
+
+
+gst_caps_features_new_empty, function in GstCapsFeatures +
+
+
+gst_caps_features_new_id, function in GstCapsFeatures +
+
+
+gst_caps_features_new_id_valist, function in GstCapsFeatures +
+
+
+gst_caps_features_new_valist, function in GstCapsFeatures +
+
+
+gst_caps_features_remove, function in GstCapsFeatures +
+
+
+gst_caps_features_remove_id, function in GstCapsFeatures +
+
+
+gst_caps_features_set_parent_refcount, function in GstCapsFeatures +
+
+
+gst_caps_features_to_string, function in GstCapsFeatures +
+
+
+GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY, macro in GstCapsFeatures +
+
+
+gst_caps_filter_and_map_in_place, function in GstCaps +
+
+
+gst_caps_fixate, function in GstCaps +
+
+
+GST_CAPS_FLAGS, macro in GstCaps +
+
+
+GST_CAPS_FLAG_IS_SET, macro in GstCaps +
+
+
+GST_CAPS_FLAG_SET, macro in GstCaps +
+
+
+GST_CAPS_FLAG_UNSET, macro in GstCaps +
+
+
+gst_caps_foreach, function in GstCaps +
+
+
+gst_caps_from_string, function in GstCaps +
+
+
+gst_caps_get_features, function in GstCaps +
+
+
+gst_caps_get_size, function in GstCaps +
+
+
+gst_caps_get_structure, function in GstCaps +
+
+
+gst_caps_intersect, function in GstCaps +
+
+
+gst_caps_intersect_full, function in GstCaps +
+
+
+gst_caps_is_always_compatible, function in GstCaps +
+
+
+gst_caps_is_any, function in GstCaps +
+
+
+gst_caps_is_empty, function in GstCaps +
+
+
+gst_caps_is_equal, function in GstCaps +
+
+
+gst_caps_is_equal_fixed, function in GstCaps +
+
+
+gst_caps_is_fixed, function in GstCaps +
+
+
+GST_CAPS_IS_SIMPLE, macro in GstCaps +
+
+
+gst_caps_is_strictly_equal, function in GstCaps +
+
+
+gst_caps_is_subset, function in GstCaps +
+
+
+gst_caps_is_subset_structure, function in GstCaps +
+
+
+gst_caps_is_subset_structure_full, function in GstCaps +
+
+
+gst_caps_is_writable, macro in GstCaps +
+
+
+gst_caps_make_writable, macro in GstCaps +
+
+
+gst_caps_map_in_place, function in GstCaps +
+
+
+gst_caps_merge, function in GstCaps +
+
+
+gst_caps_merge_structure, function in GstCaps +
+
+
+gst_caps_merge_structure_full, function in GstCaps +
+
+
+gst_caps_new_any, function in GstCaps +
+
+
+gst_caps_new_empty, function in GstCaps +
+
+
+gst_caps_new_empty_simple, function in GstCaps +
+
+
+gst_caps_new_full, function in GstCaps +
+
+
+gst_caps_new_full_valist, function in GstCaps +
+
+
+gst_caps_new_simple, function in GstCaps +
+
+
+GST_CAPS_NONE, macro in GstCaps +
+
+
+gst_caps_normalize, function in GstCaps +
+
+
+gst_caps_ref, function in GstCaps +
+
+
+GST_CAPS_REFCOUNT, macro in GstCaps +
+
+
+GST_CAPS_REFCOUNT_VALUE, macro in GstCaps +
+
+
+gst_caps_remove_structure, function in GstCaps +
+
+
+gst_caps_replace, function in GstCaps +
+
+
+gst_caps_set_features, function in GstCaps +
+
+
+gst_caps_set_simple, function in GstCaps +
+
+
+gst_caps_set_simple_valist, function in GstCaps +
+
+
+gst_caps_set_value, function in GstCaps +
+
+
+gst_caps_simplify, function in GstCaps +
+
+
+gst_caps_steal_structure, function in GstCaps +
+
+
+gst_caps_subtract, function in GstCaps +
+
+
+gst_caps_take, function in GstCaps +
+
+
+gst_caps_to_string, function in GstCaps +
+
+
+gst_caps_truncate, function in GstCaps +
+
+
+gst_caps_unref, function in GstCaps +
+
+
+GST_CAT_DEBUG, macro in GstInfo +
+
+
+GST_CAT_DEBUG_OBJECT, macro in GstInfo +
+
+
+GST_CAT_DEFAULT, variable in GstInfo +
+
+
+GST_CAT_ERROR, macro in GstInfo +
+
+
+GST_CAT_ERROR_OBJECT, macro in GstInfo +
+
+
+GST_CAT_FIXME, macro in GstInfo +
+
+
+GST_CAT_FIXME_OBJECT, macro in GstInfo +
+
+
+GST_CAT_INFO, macro in GstInfo +
+
+
+GST_CAT_INFO_OBJECT, macro in GstInfo +
+
+
+GST_CAT_LEVEL_LOG, macro in GstInfo +
+
+
+GST_CAT_LOG, macro in GstInfo +
+
+
+GST_CAT_LOG_OBJECT, macro in GstInfo +
+
+
+GST_CAT_MEMDUMP, macro in GstInfo +
+
+
+GST_CAT_MEMDUMP_OBJECT, macro in GstInfo +
+
+
+GST_CAT_TRACE, macro in GstInfo +
+
+
+GST_CAT_TRACE_OBJECT, macro in GstInfo +
+
+
+GST_CAT_WARNING, macro in GstInfo +
+
+
+GST_CAT_WARNING_OBJECT, macro in GstInfo +
+
+
+GST_CHECK_VERSION, macro in GstVersion +
+
+
+GstChildProxy, struct in GstChildProxy +
+
+
+GstChildProxy::child-added, object signal in GstChildProxy +
+
+
+GstChildProxy::child-removed, object signal in GstChildProxy +
+
+
+GstChildProxyInterface, struct in GstChildProxy +
+
+
+gst_child_proxy_child_added, function in GstChildProxy +
+
+
+gst_child_proxy_child_removed, function in GstChildProxy +
+
+
+gst_child_proxy_get, function in GstChildProxy +
+
+
+gst_child_proxy_get_children_count, function in GstChildProxy +
+
+
+gst_child_proxy_get_child_by_index, function in GstChildProxy +
+
+
+gst_child_proxy_get_child_by_name, function in GstChildProxy +
+
+
+gst_child_proxy_get_property, function in GstChildProxy +
+
+
+gst_child_proxy_get_valist, function in GstChildProxy +
+
+
+gst_child_proxy_lookup, function in GstChildProxy +
+
+
+gst_child_proxy_set, function in GstChildProxy +
+
+
+gst_child_proxy_set_property, function in GstChildProxy +
+
+
+gst_child_proxy_set_valist, function in GstChildProxy +
+
+
+GstClock, struct in GstClock +
+
+
+GstClock::synced, object signal in GstClock +
+
+
+GstClock:timeout, object property in GstClock +
+
+
+GstClock:window-size, object property in GstClock +
+
+
+GstClock:window-threshold, object property in GstClock +
+
+
+GstClockCallback, user_function in GstClock +
+
+
+GstClockClass, struct in GstClock +
+
+
+GstClockEntry, struct in GstClock +
+
+
+GstClockEntryType, enum in GstClock +
+
+
+GstClockFlags, enum in GstClock +
+
+
+GstClockID, typedef in GstClock +
+
+
+GstClockReturn, enum in GstClock +
+
+
+GstClockTime, typedef in GstClock +
+
+
+GstClockTimeDiff, typedef in GstClock +
+
+
+GstClockType, enum in GstSystemClock +
+
+
+gst_clock_add_observation, function in GstClock +
+
+
+gst_clock_add_observation_unapplied, function in GstClock +
+
+
+gst_clock_adjust_unlocked, function in GstClock +
+
+
+gst_clock_adjust_with_calibration, function in GstClock +
+
+
+GST_CLOCK_DIFF, macro in GstClock +
+
+
+GST_CLOCK_ENTRY, macro in GstClock +
+
+
+GST_CLOCK_ENTRY_CLOCK, macro in GstClock +
+
+
+GST_CLOCK_ENTRY_INTERVAL, macro in GstClock +
+
+
+GST_CLOCK_ENTRY_STATUS, macro in GstClock +
+
+
+GST_CLOCK_ENTRY_TIME, macro in GstClock +
+
+
+GST_CLOCK_ENTRY_TYPE, macro in GstClock +
+
+
+GST_CLOCK_FLAGS, macro in GstClock +
+
+
+gst_clock_get_calibration, function in GstClock +
+
+
+gst_clock_get_internal_time, function in GstClock +
+
+
+gst_clock_get_master, function in GstClock +
+
+
+gst_clock_get_resolution, function in GstClock +
+
+
+gst_clock_get_time, function in GstClock +
+
+
+gst_clock_get_timeout, function in GstClock +
+
+
+gst_clock_id_compare_func, function in GstClock +
+
+
+gst_clock_id_get_time, function in GstClock +
+
+
+gst_clock_id_ref, function in GstClock +
+
+
+gst_clock_id_unref, function in GstClock +
+
+
+gst_clock_id_unschedule, function in GstClock +
+
+
+gst_clock_id_wait, function in GstClock +
+
+
+gst_clock_id_wait_async, function in GstClock +
+
+
+gst_clock_is_synced, function in GstClock +
+
+
+gst_clock_new_periodic_id, function in GstClock +
+
+
+gst_clock_new_single_shot_id, function in GstClock +
+
+
+gst_clock_periodic_id_reinit, function in GstClock +
+
+
+gst_clock_set_calibration, function in GstClock +
+
+
+gst_clock_set_master, function in GstClock +
+
+
+gst_clock_set_resolution, function in GstClock +
+
+
+gst_clock_set_synced, function in GstClock +
+
+
+gst_clock_set_timeout, function in GstClock +
+
+
+gst_clock_single_shot_id_reinit, function in GstClock +
+
+
+GST_CLOCK_STIME_IS_VALID, macro in GstClock +
+
+
+GST_CLOCK_STIME_NONE, macro in GstClock +
+
+
+GST_CLOCK_TIME_IS_VALID, macro in GstClock +
+
+
+GST_CLOCK_TIME_NONE, macro in GstClock +
+
+
+gst_clock_unadjust_unlocked, function in GstClock +
+
+
+gst_clock_unadjust_with_calibration, function in GstClock +
+
+
+gst_clock_wait_for_sync, function in GstClock +
+
+
+GstContext, struct in GstContext +
+
+
+gst_context_copy, function in GstContext +
+
+
+gst_context_get_context_type, function in GstContext +
+
+
+gst_context_get_structure, function in GstContext +
+
+
+gst_context_has_context_type, function in GstContext +
+
+
+gst_context_is_persistent, function in GstContext +
+
+
+gst_context_is_writable, macro in GstContext +
+
+
+gst_context_make_writable, macro in GstContext +
+
+
+gst_context_new, function in GstContext +
+
+
+gst_context_ref, function in GstContext +
+
+
+gst_context_replace, function in GstContext +
+
+
+gst_context_unref, function in GstContext +
+
+
+gst_context_writable_structure, function in GstContext +
+
+
+GstControlBinding, struct in GstControlBinding +
+
+
+GstControlBinding:name, object property in GstControlBinding +
+
+
+GstControlBinding:object, object property in GstControlBinding +
+
+
+GstControlBindingClass, struct in GstControlBinding +
+
+
+GstControlSource, struct in GstControlSource +
+
+
+GstControlSourceClass, struct in GstControlSource +
+
+
+GstControlSourceGetValue, user_function in GstControlSource +
+
+
+GstControlSourceGetValueArray, user_function in GstControlSource +
+
+
+gst_control_binding_get_g_value_array, function in GstControlBinding +
+
+
+gst_control_binding_get_value, function in GstControlBinding +
+
+
+gst_control_binding_get_value_array, function in GstControlBinding +
+
+
+gst_control_binding_is_disabled, function in GstControlBinding +
+
+
+gst_control_binding_set_disabled, function in GstControlBinding +
+
+
+gst_control_binding_sync_values, function in GstControlBinding +
+
+
+gst_control_source_get_value, function in GstControlSource +
+
+
+gst_control_source_get_value_array, function in GstControlSource +
+
+
+GstCoreError, enum in GstGError +
+
+
+GST_CORE_ERROR, macro in GstGError +
+
+

D

+
+GstDateTime, struct in GstDateTime +
+
+
+gst_date_time_get_day, function in GstDateTime +
+
+
+gst_date_time_get_hour, function in GstDateTime +
+
+
+gst_date_time_get_microsecond, function in GstDateTime +
+
+
+gst_date_time_get_minute, function in GstDateTime +
+
+
+gst_date_time_get_month, function in GstDateTime +
+
+
+gst_date_time_get_second, function in GstDateTime +
+
+
+gst_date_time_get_time_zone_offset, function in GstDateTime +
+
+
+gst_date_time_get_year, function in GstDateTime +
+
+
+gst_date_time_has_day, function in GstDateTime +
+
+
+gst_date_time_has_month, function in GstDateTime +
+
+
+gst_date_time_has_second, function in GstDateTime +
+
+
+gst_date_time_has_time, function in GstDateTime +
+
+
+gst_date_time_has_year, function in GstDateTime +
+
+
+gst_date_time_new, function in GstDateTime +
+
+
+gst_date_time_new_from_g_date_time, function in GstDateTime +
+
+
+gst_date_time_new_from_iso8601_string, function in GstDateTime +
+
+
+gst_date_time_new_from_unix_epoch_local_time, function in GstDateTime +
+
+
+gst_date_time_new_from_unix_epoch_utc, function in GstDateTime +
+
+
+gst_date_time_new_local_time, function in GstDateTime +
+
+
+gst_date_time_new_now_local_time, function in GstDateTime +
+
+
+gst_date_time_new_now_utc, function in GstDateTime +
+
+
+gst_date_time_new_y, function in GstDateTime +
+
+
+gst_date_time_new_ym, function in GstDateTime +
+
+
+gst_date_time_new_ymd, function in GstDateTime +
+
+
+gst_date_time_ref, function in GstDateTime +
+
+
+gst_date_time_to_g_date_time, function in GstDateTime +
+
+
+gst_date_time_to_iso8601_string, function in GstDateTime +
+
+
+gst_date_time_unref, function in GstDateTime +
+
+
+GST_DEBUG, macro in GstInfo +
+
+
+GstDebugCategory, struct in GstInfo +
+
+
+GstDebugColorFlags, enum in GstInfo +
+
+
+GstDebugColorMode, enum in GstInfo +
+
+
+GstDebugGraphDetails, enum in GstInfo +
+
+
+GstDebugLevel, enum in GstInfo +
+
+
+gst_debug_add_log_function, function in GstInfo +
+
+
+gst_debug_add_ring_buffer_logger, function in GstInfo +
+
+
+gst_debug_bin_to_dot_data, function in GstInfo +
+
+
+GST_DEBUG_BIN_TO_DOT_FILE, macro in GstInfo +
+
+
+gst_debug_bin_to_dot_file, function in GstInfo +
+
+
+GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS, macro in GstInfo +
+
+
+gst_debug_bin_to_dot_file_with_ts, function in GstInfo +
+
+
+GST_DEBUG_CATEGORY, macro in GstInfo +
+
+
+GST_DEBUG_CATEGORY_EXTERN, macro in GstInfo +
+
+
+gst_debug_category_free, function in GstInfo +
+
+
+GST_DEBUG_CATEGORY_GET, macro in GstInfo +
+
+
+gst_debug_category_get_color, function in GstInfo +
+
+
+gst_debug_category_get_description, function in GstInfo +
+
+
+gst_debug_category_get_name, function in GstInfo +
+
+
+gst_debug_category_get_threshold, function in GstInfo +
+
+
+GST_DEBUG_CATEGORY_INIT, macro in GstInfo +
+
+
+gst_debug_category_reset_threshold, function in GstInfo +
+
+
+gst_debug_category_set_threshold, function in GstInfo +
+
+
+GST_DEBUG_CATEGORY_STATIC, macro in GstInfo +
+
+
+gst_debug_construct_term_color, function in GstInfo +
+
+
+gst_debug_construct_win_color, function in GstInfo +
+
+
+GST_DEBUG_FUNCPTR, macro in GstInfo +
+
+
+GST_DEBUG_FUNCPTR_NAME, macro in GstInfo +
+
+
+gst_debug_get_all_categories, function in GstInfo +
+
+
+gst_debug_get_color_mode, function in GstInfo +
+
+
+gst_debug_get_default_threshold, function in GstInfo +
+
+
+gst_debug_get_stack_trace, function in GstInfo +
+
+
+gst_debug_is_active, function in GstInfo +
+
+
+gst_debug_is_colored, function in GstInfo +
+
+
+gst_debug_level_get_name, function in GstInfo +
+
+
+gst_debug_log, function in GstInfo +
+
+
+gst_debug_log_default, function in GstInfo +
+
+
+gst_debug_log_valist, function in GstInfo +
+
+
+gst_debug_message_get, function in GstInfo +
+
+
+GST_DEBUG_OBJECT, macro in GstInfo +
+
+
+GST_DEBUG_PAD_NAME, macro in GstInfo +
+
+
+gst_debug_print_stack_trace, function in GstInfo +
+
+
+GST_DEBUG_REGISTER_FUNCPTR, macro in GstInfo +
+
+
+gst_debug_remove_log_function, function in GstInfo +
+
+
+gst_debug_remove_log_function_by_data, function in GstInfo +
+
+
+gst_debug_remove_ring_buffer_logger, function in GstInfo +
+
+
+gst_debug_ring_buffer_logger_get_logs, function in GstInfo +
+
+
+gst_debug_set_active, function in GstInfo +
+
+
+gst_debug_set_colored, function in GstInfo +
+
+
+gst_debug_set_color_mode, function in GstInfo +
+
+
+gst_debug_set_color_mode_from_string, function in GstInfo +
+
+
+gst_debug_set_default_threshold, function in GstInfo +
+
+
+gst_debug_set_threshold_for_name, function in GstInfo +
+
+
+gst_debug_set_threshold_from_string, function in GstInfo +
+
+
+gst_debug_unset_threshold_for_name, function in GstInfo +
+
+
+GST_DEFINE_MINI_OBJECT_TYPE, macro in GstMiniObject +
+
+
+gst_deinit, function in Gst +
+
+
+GstDevice, struct in GstDevice +
+
+
+GstDeviceClass, struct in GstDevice +
+
+
+GstDeviceMonitor, struct in GstDeviceMonitor +
+
+
+GstDeviceMonitorClass, struct in GstDeviceMonitor +
+
+
+GstDeviceProvider, struct in GstDeviceProvider +
+
+
+GstDeviceProviderClass, struct in GstDeviceProvider +
+
+
+GstDeviceProviderFactory, struct in GstDeviceProviderFactory +
+
+
+GstDeviceProviderFactoryClass, struct in GstDeviceProviderFactory +
+
+
+gst_device_create_element, function in GstDevice +
+
+
+gst_device_get_caps, function in GstDevice +
+
+
+gst_device_get_device_class, function in GstDevice +
+
+
+gst_device_get_display_name, function in GstDevice +
+
+
+gst_device_get_properties, function in GstDevice +
+
+
+gst_device_has_classes, function in GstDevice +
+
+
+gst_device_has_classesv, function in GstDevice +
+
+
+gst_device_monitor_add_filter, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_bus, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_devices, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_providers, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_show_all_devices, function in GstDeviceMonitor +
+
+
+gst_device_monitor_new, function in GstDeviceMonitor +
+
+
+gst_device_monitor_remove_filter, function in GstDeviceMonitor +
+
+
+gst_device_monitor_set_show_all_devices, function in GstDeviceMonitor +
+
+
+gst_device_monitor_start, function in GstDeviceMonitor +
+
+
+gst_device_monitor_stop, function in GstDeviceMonitor +
+
+
+gst_device_provider_can_monitor, function in GstDeviceProvider +
+
+
+gst_device_provider_class_add_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_add_static_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_get_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_set_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_set_static_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_device_add, function in GstDeviceProvider +
+
+
+gst_device_provider_device_remove, function in GstDeviceProvider +
+
+
+gst_device_provider_factory_find, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_by_name, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_device_provider_type, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_metadata, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_metadata_keys, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_has_classes, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_has_classesv, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_list_get_device_providers, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_get_bus, function in GstDeviceProvider +
+
+
+gst_device_provider_get_devices, function in GstDeviceProvider +
+
+
+gst_device_provider_get_factory, function in GstDeviceProvider +
+
+
+gst_device_provider_get_hidden_providers, function in GstDeviceMonitor +
+
+
+gst_device_provider_get_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_hide_provider, function in GstDeviceMonitor +
+
+
+gst_device_provider_register, function in GstDeviceProvider +
+
+
+gst_device_provider_start, function in GstDeviceProvider +
+
+
+gst_device_provider_stop, function in GstDeviceProvider +
+
+
+gst_device_provider_unhide_provider, function in GstDeviceMonitor +
+
+
+gst_device_reconfigure_element, function in GstDevice +
+
+
+GST_DISABLE_GST_DEBUG, macro in GstConfig +
+
+
+GST_DISABLE_PARSE, macro in GstConfig +
+
+
+GST_DISABLE_PLUGIN, macro in GstConfig +
+
+
+GST_DISABLE_REGISTRY, macro in GstConfig +
+
+
+GstDynamicTypeFactory, struct in GstDynamicTypeFactory +
+
+
+gst_dynamic_type_factory_load, function in GstDynamicTypeFactory +
+
+
+gst_dynamic_type_register, function in GstDynamicTypeFactory +
+
+

E

+
+GstElement, struct in GstElement +
+
+
+GstElement::no-more-pads, object signal in GstElement +
+
+
+GstElement::pad-added, object signal in GstElement +
+
+
+GstElement::pad-removed, object signal in GstElement +
+
+
+GstElementCallAsyncFunc, user_function in GstElement +
+
+
+GstElementClass, struct in GstElement +
+
+
+GstElementFactory, struct in GstElementFactory +
+
+
+GstElementFactoryListType, typedef in GstElementFactory +
+
+
+GstElementFlags, enum in GstElement +
+
+
+GstElementForeachPadFunc, user_function in GstElement +
+
+
+gst_element_abort_state, function in GstElement +
+
+
+gst_element_add_pad, function in GstElement +
+
+
+gst_element_add_property_deep_notify_watch, function in GstElement +
+
+
+gst_element_add_property_notify_watch, function in GstElement +
+
+
+GST_ELEMENT_BUS, macro in GstElement +
+
+
+gst_element_call_async, function in GstElement +
+
+
+gst_element_change_state, function in GstElement +
+
+
+gst_element_class_add_metadata, function in GstElement +
+
+
+gst_element_class_add_pad_template, function in GstElement +
+
+
+gst_element_class_add_static_metadata, function in GstElement +
+
+
+gst_element_class_add_static_pad_template, function in GstElement +
+
+
+gst_element_class_add_static_pad_template_with_gtype, function in GstElement +
+
+
+gst_element_class_get_metadata, function in GstElement +
+
+
+gst_element_class_get_pad_template, function in GstElement +
+
+
+gst_element_class_get_pad_template_list, function in GstElement +
+
+
+gst_element_class_set_metadata, function in GstElement +
+
+
+gst_element_class_set_static_metadata, function in GstElement +
+
+
+GST_ELEMENT_CLOCK, macro in GstElement +
+
+
+gst_element_continue_state, function in GstElement +
+
+
+gst_element_create_all_pads, function in GstElement +
+
+
+GST_ELEMENT_ERROR, macro in GstElement +
+
+
+GST_ELEMENT_ERROR_WITH_DETAILS, macro in GstElement +
+
+
+gst_element_factory_can_sink_all_caps, function in GstElementFactory +
+
+
+gst_element_factory_can_sink_any_caps, function in GstElementFactory +
+
+
+gst_element_factory_can_src_all_caps, function in GstElementFactory +
+
+
+gst_element_factory_can_src_any_caps, function in GstElementFactory +
+
+
+gst_element_factory_create, function in GstElementFactory +
+
+
+gst_element_factory_find, function in GstElementFactory +
+
+
+gst_element_factory_get_element_type, function in GstElementFactory +
+
+
+gst_element_factory_get_metadata, function in GstElementFactory +
+
+
+gst_element_factory_get_metadata_keys, function in GstElementFactory +
+
+
+gst_element_factory_get_num_pad_templates, function in GstElementFactory +
+
+
+gst_element_factory_get_static_pad_templates, function in GstElementFactory +
+
+
+gst_element_factory_get_uri_protocols, function in GstElementFactory +
+
+
+gst_element_factory_get_uri_type, function in GstElementFactory +
+
+
+gst_element_factory_has_interface, function in GstElementFactory +
+
+
+gst_element_factory_list_filter, function in GstElementFactory +
+
+
+gst_element_factory_list_get_elements, function in GstElementFactory +
+
+
+gst_element_factory_list_is_type, function in GstElementFactory +
+
+
+gst_element_factory_make, function in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_ANY, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_DECODABLE, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_DECODER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_DECRYPTOR, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_DEMUXER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_ENCODER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_FORMATTER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_MUXER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_PARSER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_PAYLOADER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_SINK, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_SRC, macro in GstElementFactory +
+
+
+GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER, macro in GstElementFactory +
+
+
+GST_ELEMENT_FLOW_ERROR, macro in GstElement +
+
+
+gst_element_foreach_pad, function in GstElement +
+
+
+gst_element_foreach_sink_pad, function in GstElement +
+
+
+gst_element_foreach_src_pad, function in GstElement +
+
+
+gst_element_get_base_time, function in GstElement +
+
+
+gst_element_get_bus, function in GstElement +
+
+
+gst_element_get_clock, function in GstElement +
+
+
+gst_element_get_compatible_pad, function in GstElement +
+
+
+gst_element_get_compatible_pad_template, function in GstElement +
+
+
+gst_element_get_context, function in GstElement +
+
+
+gst_element_get_contexts, function in GstElement +
+
+
+gst_element_get_context_unlocked, function in GstElement +
+
+
+gst_element_get_factory, function in GstElement +
+
+
+gst_element_get_metadata, function in GstElement +
+
+
+gst_element_get_name, macro in GstElement +
+
+
+gst_element_get_pad_template, function in GstElement +
+
+
+gst_element_get_pad_template_list, function in GstElement +
+
+
+gst_element_get_parent, macro in GstElement +
+
+
+gst_element_get_request_pad, function in GstElement +
+
+
+gst_element_get_start_time, function in GstElement +
+
+
+gst_element_get_state, function in GstElement +
+
+
+gst_element_get_static_pad, function in GstElement +
+
+
+GST_ELEMENT_INFO, macro in GstElement +
+
+
+GST_ELEMENT_INFO_WITH_DETAILS, macro in GstElement +
+
+
+GST_ELEMENT_IS_LOCKED_STATE, macro in GstElement +
+
+
+gst_element_is_locked_state, function in GstElement +
+
+
+gst_element_iterate_pads, function in GstElement +
+
+
+gst_element_iterate_sink_pads, function in GstElement +
+
+
+gst_element_iterate_src_pads, function in GstElement +
+
+
+gst_element_link, function in GstElement +
+
+
+gst_element_link_filtered, function in GstElement +
+
+
+gst_element_link_many, function in GstElement +
+
+
+gst_element_link_pads, function in GstElement +
+
+
+gst_element_link_pads_filtered, function in GstElement +
+
+
+gst_element_link_pads_full, function in GstElement +
+
+
+gst_element_lost_state, function in GstElement +
+
+
+gst_element_make_from_uri, function in GstUriHandler +
+
+
+gst_element_message_full, function in GstElement +
+
+
+gst_element_message_full_with_details, function in GstElement +
+
+
+GST_ELEMENT_METADATA_AUTHOR, macro in GstElement +
+
+
+GST_ELEMENT_METADATA_DESCRIPTION, macro in GstElement +
+
+
+GST_ELEMENT_METADATA_DOC_URI, macro in GstElement +
+
+
+GST_ELEMENT_METADATA_ICON_NAME, macro in GstElement +
+
+
+GST_ELEMENT_METADATA_KLASS, macro in GstElement +
+
+
+GST_ELEMENT_METADATA_LONGNAME, macro in GstElement +
+
+
+GST_ELEMENT_NAME, macro in GstElement +
+
+
+gst_element_no_more_pads, function in GstElement +
+
+
+GST_ELEMENT_PADS, macro in GstElement +
+
+
+GST_ELEMENT_PARENT, macro in GstElement +
+
+
+gst_element_post_message, function in GstElement +
+
+
+gst_element_provide_clock, function in GstElement +
+
+
+gst_element_query, function in GstElement +
+
+
+gst_element_query_convert, function in GstElement +
+
+
+gst_element_query_duration, function in GstElement +
+
+
+gst_element_query_position, function in GstElement +
+
+
+gst_element_register, function in GstElementFactory +
+
+
+gst_element_release_request_pad, function in GstElement +
+
+
+gst_element_remove_pad, function in GstElement +
+
+
+gst_element_remove_property_notify_watch, function in GstElement +
+
+
+gst_element_request_pad, function in GstElement +
+
+
+gst_element_seek, function in GstElement +
+
+
+gst_element_seek_simple, function in GstElement +
+
+
+gst_element_send_event, function in GstElement +
+
+
+gst_element_set_base_time, function in GstElement +
+
+
+gst_element_set_bus, function in GstElement +
+
+
+gst_element_set_clock, function in GstElement +
+
+
+gst_element_set_context, function in GstElement +
+
+
+gst_element_set_locked_state, function in GstElement +
+
+
+gst_element_set_name, macro in GstElement +
+
+
+gst_element_set_parent, macro in GstElement +
+
+
+gst_element_set_start_time, function in GstElement +
+
+
+gst_element_set_state, function in GstElement +
+
+
+GST_ELEMENT_START_TIME, macro in GstElement +
+
+
+gst_element_state_change_return_get_name, function in GstElement +
+
+
+gst_element_state_get_name, function in GstElement +
+
+
+gst_element_sync_state_with_parent, function in GstElement +
+
+
+gst_element_unlink, function in GstElement +
+
+
+gst_element_unlink_many, function in GstElement +
+
+
+gst_element_unlink_pads, function in GstElement +
+
+
+GST_ELEMENT_WARNING, macro in GstElement +
+
+
+GST_ELEMENT_WARNING_WITH_DETAILS, macro in GstElement +
+
+
+GST_ERROR, macro in GstInfo +
+
+
+gst_error_get_message, function in GstGError +
+
+
+GST_ERROR_OBJECT, macro in GstInfo +
+
+
+GST_ERROR_SYSTEM, macro in GstGError +
+
+
+GstEvent, struct in GstEvent +
+
+
+GstEventType, enum in GstEvent +
+
+
+GstEventTypeFlags, enum in GstEvent +
+
+
+gst_event_copy, function in GstEvent +
+
+
+gst_event_copy_segment, function in GstEvent +
+
+
+gst_event_get_running_time_offset, function in GstEvent +
+
+
+gst_event_get_seqnum, function in GstEvent +
+
+
+gst_event_get_structure, function in GstEvent +
+
+
+gst_event_has_name, function in GstEvent +
+
+
+GST_EVENT_IS_DOWNSTREAM, macro in GstEvent +
+
+
+GST_EVENT_IS_SERIALIZED, macro in GstEvent +
+
+
+GST_EVENT_IS_STICKY, macro in GstEvent +
+
+
+GST_EVENT_IS_UPSTREAM, macro in GstEvent +
+
+
+gst_event_is_writable, macro in GstEvent +
+
+
+GST_EVENT_MAKE_TYPE, macro in GstEvent +
+
+
+gst_event_make_writable, macro in GstEvent +
+
+
+gst_event_new_buffer_size, function in GstEvent +
+
+
+gst_event_new_caps, function in GstEvent +
+
+
+gst_event_new_custom, function in GstEvent +
+
+
+gst_event_new_eos, function in GstEvent +
+
+
+gst_event_new_flush_start, function in GstEvent +
+
+
+gst_event_new_flush_stop, function in GstEvent +
+
+
+gst_event_new_gap, function in GstEvent +
+
+
+gst_event_new_latency, function in GstEvent +
+
+
+gst_event_new_navigation, function in GstEvent +
+
+
+gst_event_new_protection, function in GstEvent +
+
+
+gst_event_new_qos, function in GstEvent +
+
+
+gst_event_new_reconfigure, function in GstEvent +
+
+
+gst_event_new_seek, function in GstEvent +
+
+
+gst_event_new_segment, function in GstEvent +
+
+
+gst_event_new_segment_done, function in GstEvent +
+
+
+gst_event_new_select_streams, function in GstEvent +
+
+
+gst_event_new_sink_message, function in GstEvent +
+
+
+gst_event_new_step, function in GstEvent +
+
+
+gst_event_new_stream_collection, function in GstEvent +
+
+
+gst_event_new_stream_group_done, function in GstEvent +
+
+
+gst_event_new_stream_start, function in GstEvent +
+
+
+gst_event_new_tag, function in GstEvent +
+
+
+gst_event_new_toc, function in GstEvent +
+
+
+gst_event_new_toc_select, function in GstEvent +
+
+
+gst_event_parse_buffer_size, function in GstEvent +
+
+
+gst_event_parse_caps, function in GstEvent +
+
+
+gst_event_parse_flush_stop, function in GstEvent +
+
+
+gst_event_parse_gap, function in GstEvent +
+
+
+gst_event_parse_group_id, function in GstEvent +
+
+
+gst_event_parse_latency, function in GstEvent +
+
+
+gst_event_parse_protection, function in GstEvent +
+
+
+gst_event_parse_qos, function in GstEvent +
+
+
+gst_event_parse_seek, function in GstEvent +
+
+
+gst_event_parse_segment, function in GstEvent +
+
+
+gst_event_parse_segment_done, function in GstEvent +
+
+
+gst_event_parse_select_streams, function in GstEvent +
+
+
+gst_event_parse_sink_message, function in GstEvent +
+
+
+gst_event_parse_step, function in GstEvent +
+
+
+gst_event_parse_stream, function in GstEvent +
+
+
+gst_event_parse_stream_collection, function in GstEvent +
+
+
+gst_event_parse_stream_flags, function in GstEvent +
+
+
+gst_event_parse_stream_group_done, function in GstEvent +
+
+
+gst_event_parse_stream_start, function in GstEvent +
+
+
+gst_event_parse_tag, function in GstEvent +
+
+
+gst_event_parse_toc, function in GstEvent +
+
+
+gst_event_parse_toc_select, function in GstEvent +
+
+
+gst_event_ref, function in GstEvent +
+
+
+gst_event_replace, function in GstEvent +
+
+
+GST_EVENT_SEQNUM, macro in GstEvent +
+
+
+gst_event_set_group_id, function in GstEvent +
+
+
+gst_event_set_running_time_offset, function in GstEvent +
+
+
+gst_event_set_seqnum, function in GstEvent +
+
+
+gst_event_set_stream, function in GstEvent +
+
+
+gst_event_set_stream_flags, function in GstEvent +
+
+
+gst_event_steal, function in GstEvent +
+
+
+gst_event_take, function in GstEvent +
+
+
+GST_EVENT_TIMESTAMP, macro in GstEvent +
+
+
+GST_EVENT_TYPE, macro in GstEvent +
+
+
+GST_EVENT_TYPE_BOTH, macro in GstEvent +
+
+
+gst_event_type_get_flags, function in GstEvent +
+
+
+gst_event_type_get_name, function in GstEvent +
+
+
+GST_EVENT_TYPE_NAME, macro in GstEvent +
+
+
+gst_event_type_to_quark, function in GstEvent +
+
+
+gst_event_unref, function in GstEvent +
+
+
+gst_event_writable_structure, function in GstEvent +
+
+

F

+
+gst_filename_to_uri, function in GstUriHandler +
+
+
+GST_FIXME, macro in GstInfo +
+
+
+GST_FIXME_OBJECT, macro in GstInfo +
+
+
+gst_flagset_register, function in GstValue +
+
+
+GST_FLAG_SET_MASK_EXACT, macro in GstValue +
+
+
+GstFlowReturn, enum in GstPad +
+
+
+gst_flow_get_name, function in GstPad +
+
+
+gst_flow_to_quark, function in GstPad +
+
+
+GstFormat, enum in GstFormat +
+
+
+GstFormatDefinition, struct in GstFormat +
+
+
+gst_formats_contains, function in GstFormat +
+
+
+gst_format_get_by_nick, function in GstFormat +
+
+
+gst_format_get_details, function in GstFormat +
+
+
+gst_format_get_name, function in GstFormat +
+
+
+gst_format_iterate_definitions, function in GstFormat +
+
+
+GST_FORMAT_PERCENT_MAX, macro in GstFormat +
+
+
+GST_FORMAT_PERCENT_SCALE, macro in GstFormat +
+
+
+gst_format_register, function in GstFormat +
+
+
+gst_format_to_quark, function in GstFormat +
+
+
+GST_FOURCC_ARGS, macro in GstValue +
+
+
+GST_FOURCC_FORMAT, macro in GstValue +
+
+
+GST_FUNCTION, macro in GstInfo +
+
+

G

+
+GDOUBLE_FROM_BE, macro in GstUtils +
+
+
+GDOUBLE_FROM_LE, macro in GstUtils +
+
+
+GDOUBLE_SWAP_LE_BE, function in GstUtils +
+
+
+GDOUBLE_TO_BE, macro in GstUtils +
+
+
+gst_gdouble_to_guint64, macro in GstUtils +
+
+
+GDOUBLE_TO_LE, macro in GstUtils +
+
+
+gst_get_main_executable_path, function in Gst +
+
+
+GFLOAT_FROM_BE, macro in GstUtils +
+
+
+GFLOAT_FROM_LE, macro in GstUtils +
+
+
+GFLOAT_SWAP_LE_BE, function in GstUtils +
+
+
+GFLOAT_TO_BE, macro in GstUtils +
+
+
+GFLOAT_TO_LE, macro in GstUtils +
+
+
+GstGhostPad, struct in GstGhostPad +
+
+
+gst_ghost_pad_activate_mode_default, function in GstGhostPad +
+
+
+gst_ghost_pad_construct, function in GstGhostPad +
+
+
+gst_ghost_pad_get_target, function in GstGhostPad +
+
+
+gst_ghost_pad_internal_activate_mode_default, function in GstGhostPad +
+
+
+gst_ghost_pad_new, function in GstGhostPad +
+
+
+gst_ghost_pad_new_from_template, function in GstGhostPad +
+
+
+gst_ghost_pad_new_no_target, function in GstGhostPad +
+
+
+gst_ghost_pad_new_no_target_from_template, function in GstGhostPad +
+
+
+gst_ghost_pad_set_target, function in GstGhostPad +
+
+
+GST_GROUP_ID_INVALID, macro in GstUtils +
+
+
+gst_guint64_to_gdouble, macro in GstUtils +
+
+

I

+
+GST_INFO, macro in GstInfo +
+
+
+GST_INFO_OBJECT, macro in GstInfo +
+
+
+gst_info_strdup_printf, function in GstInfo +
+
+
+gst_info_strdup_vprintf, function in GstInfo +
+
+
+gst_info_vasprintf, function in GstInfo +
+
+
+gst_init, function in Gst +
+
+
+gst_init_check, function in Gst +
+
+
+gst_init_get_option_group, function in Gst +
+
+
+gst_is_initialized, function in Gst +
+
+
+GST_ITERATOR, macro in GstIterator +
+
+
+GstIterator, struct in GstIterator +
+
+
+GstIteratorCopyFunction, user_function in GstIterator +
+
+
+GstIteratorFoldFunction, user_function in GstIterator +
+
+
+GstIteratorForeachFunction, user_function in GstIterator +
+
+
+GstIteratorFreeFunction, user_function in GstIterator +
+
+
+GstIteratorItem, enum in GstIterator +
+
+
+GstIteratorItemFunction, user_function in GstIterator +
+
+
+GstIteratorNextFunction, user_function in GstIterator +
+
+
+GstIteratorResult, enum in GstIterator +
+
+
+GstIteratorResyncFunction, user_function in GstIterator +
+
+
+GST_ITERATOR_COOKIE, macro in GstIterator +
+
+
+gst_iterator_copy, function in GstIterator +
+
+
+gst_iterator_filter, function in GstIterator +
+
+
+gst_iterator_find_custom, function in GstIterator +
+
+
+gst_iterator_fold, function in GstIterator +
+
+
+gst_iterator_foreach, function in GstIterator +
+
+
+gst_iterator_free, function in GstIterator +
+
+
+GST_ITERATOR_LOCK, macro in GstIterator +
+
+
+gst_iterator_new, function in GstIterator +
+
+
+gst_iterator_new_list, function in GstIterator +
+
+
+gst_iterator_new_single, function in GstIterator +
+
+
+gst_iterator_next, function in GstIterator +
+
+
+GST_ITERATOR_ORIG_COOKIE, macro in GstIterator +
+
+
+gst_iterator_push, function in GstIterator +
+
+
+gst_iterator_resync, function in GstIterator +
+
+

L

+
+GST_LEVEL_DEFAULT, macro in GstInfo +
+
+
+GST_LEVEL_MAX, macro in GstInfo +
+
+
+GstLibraryError, enum in GstGError +
+
+
+GST_LIBRARY_ERROR, macro in GstGError +
+
+
+GST_LICENSE_UNKNOWN, macro in GstPlugin +
+
+
+GstLockFlags, enum in GstMiniObject +
+
+
+GST_LOCK_FLAG_READWRITE, macro in GstMiniObject +
+
+
+GST_LOG, macro in GstInfo +
+
+
+GstLogFunction, user_function in GstInfo +
+
+
+GST_LOG_OBJECT, macro in GstInfo +
+
+

M

+
+gst_make_element_message_details, function in GstElement +
+
+
+GST_MAKE_FOURCC, macro in GstValue +
+
+
+GstMapFlags, enum in GstMemory +
+
+
+GstMapInfo, struct in GstMemory +
+
+
+GST_MAP_INFO_INIT, macro in GstMemory +
+
+
+GST_MAP_READWRITE, macro in GstMemory +
+
+
+GST_MEMDUMP, macro in GstInfo +
+
+
+GST_MEMDUMP_OBJECT, macro in GstInfo +
+
+
+GstMemory, struct in GstMemory +
+
+
+GstMemoryCopyFunction, user_function in GstMemory +
+
+
+GstMemoryFlags, enum in GstMemory +
+
+
+GstMemoryIsSpanFunction, user_function in GstMemory +
+
+
+GstMemoryMapFullFunction, user_function in GstMemory +
+
+
+GstMemoryMapFunction, user_function in GstMemory +
+
+
+GstMemoryShareFunction, user_function in GstMemory +
+
+
+GstMemoryUnmapFullFunction, user_function in GstMemory +
+
+
+GstMemoryUnmapFunction, user_function in GstMemory +
+
+
+gst_memory_alignment, variable in GstAllocator +
+
+
+gst_memory_copy, function in GstMemory +
+
+
+GST_MEMORY_FLAGS, macro in GstMemory +
+
+
+GST_MEMORY_FLAG_IS_SET, macro in GstMemory +
+
+
+GST_MEMORY_FLAG_UNSET, macro in GstMemory +
+
+
+gst_memory_get_sizes, function in GstMemory +
+
+
+gst_memory_init, function in GstMemory +
+
+
+GST_MEMORY_IS_NOT_MAPPABLE, macro in GstMemory +
+
+
+GST_MEMORY_IS_NO_SHARE, macro in GstMemory +
+
+
+GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS, macro in GstMemory +
+
+
+GST_MEMORY_IS_READONLY, macro in GstMemory +
+
+
+gst_memory_is_span, function in GstMemory +
+
+
+gst_memory_is_type, function in GstMemory +
+
+
+gst_memory_is_writable, macro in GstMemory +
+
+
+GST_MEMORY_IS_ZERO_PADDED, macro in GstMemory +
+
+
+GST_MEMORY_IS_ZERO_PREFIXED, macro in GstMemory +
+
+
+gst_memory_lock, macro in GstMemory +
+
+
+gst_memory_make_mapped, function in GstMemory +
+
+
+gst_memory_make_writable, macro in GstMemory +
+
+
+gst_memory_map, function in GstMemory +
+
+
+gst_memory_new_wrapped, function in GstAllocator +
+
+
+gst_memory_ref, function in GstMemory +
+
+
+gst_memory_resize, function in GstMemory +
+
+
+gst_memory_share, function in GstMemory +
+
+
+gst_memory_unlock, macro in GstMemory +
+
+
+gst_memory_unmap, function in GstMemory +
+
+
+gst_memory_unref, function in GstMemory +
+
+
+GstMessage, struct in GstMessage +
+
+
+GstMessageType, enum in GstMessage +
+
+
+gst_message_add_redirect_entry, function in GstMessage +
+
+
+gst_message_copy, function in GstMessage +
+
+
+gst_message_get_num_redirect_entries, function in GstMessage +
+
+
+gst_message_get_seqnum, function in GstMessage +
+
+
+gst_message_get_stream_status_object, function in GstMessage +
+
+
+gst_message_get_structure, function in GstMessage +
+
+
+gst_message_has_name, function in GstMessage +
+
+
+gst_message_is_writable, macro in GstMessage +
+
+
+gst_message_make_writable, macro in GstMessage +
+
+
+gst_message_new_application, function in GstMessage +
+
+
+gst_message_new_async_done, function in GstMessage +
+
+
+gst_message_new_async_start, function in GstMessage +
+
+
+gst_message_new_buffering, function in GstMessage +
+
+
+gst_message_new_clock_lost, function in GstMessage +
+
+
+gst_message_new_clock_provide, function in GstMessage +
+
+
+gst_message_new_custom, function in GstMessage +
+
+
+gst_message_new_device_added, function in GstMessage +
+
+
+gst_message_new_device_removed, function in GstMessage +
+
+
+gst_message_new_duration_changed, function in GstMessage +
+
+
+gst_message_new_element, function in GstMessage +
+
+
+gst_message_new_eos, function in GstMessage +
+
+
+gst_message_new_error, function in GstMessage +
+
+
+gst_message_new_error_with_details, function in GstMessage +
+
+
+gst_message_new_have_context, function in GstMessage +
+
+
+gst_message_new_info, function in GstMessage +
+
+
+gst_message_new_info_with_details, function in GstMessage +
+
+
+gst_message_new_latency, function in GstMessage +
+
+
+gst_message_new_need_context, function in GstMessage +
+
+
+gst_message_new_new_clock, function in GstMessage +
+
+
+gst_message_new_progress, function in GstMessage +
+
+
+gst_message_new_property_notify, function in GstMessage +
+
+
+gst_message_new_qos, function in GstMessage +
+
+
+gst_message_new_redirect, function in GstMessage +
+
+
+gst_message_new_request_state, function in GstMessage +
+
+
+gst_message_new_reset_time, function in GstMessage +
+
+
+gst_message_new_segment_done, function in GstMessage +
+
+
+gst_message_new_segment_start, function in GstMessage +
+
+
+gst_message_new_state_changed, function in GstMessage +
+
+
+gst_message_new_state_dirty, function in GstMessage +
+
+
+gst_message_new_step_done, function in GstMessage +
+
+
+gst_message_new_step_start, function in GstMessage +
+
+
+gst_message_new_streams_selected, function in GstMessage +
+
+
+gst_message_new_stream_collection, function in GstMessage +
+
+
+gst_message_new_stream_start, function in GstMessage +
+
+
+gst_message_new_stream_status, function in GstMessage +
+
+
+gst_message_new_structure_change, function in GstMessage +
+
+
+gst_message_new_tag, function in GstMessage +
+
+
+gst_message_new_toc, function in GstMessage +
+
+
+gst_message_new_warning, function in GstMessage +
+
+
+gst_message_new_warning_with_details, function in GstMessage +
+
+
+gst_message_parse_async_done, function in GstMessage +
+
+
+gst_message_parse_buffering, function in GstMessage +
+
+
+gst_message_parse_buffering_stats, function in GstMessage +
+
+
+gst_message_parse_clock_lost, function in GstMessage +
+
+
+gst_message_parse_clock_provide, function in GstMessage +
+
+
+gst_message_parse_context_type, function in GstMessage +
+
+
+gst_message_parse_device_added, function in GstMessage +
+
+
+gst_message_parse_device_removed, function in GstMessage +
+
+
+gst_message_parse_error, function in GstMessage +
+
+
+gst_message_parse_error_details, function in GstMessage +
+
+
+gst_message_parse_group_id, function in GstMessage +
+
+
+gst_message_parse_have_context, function in GstMessage +
+
+
+gst_message_parse_info, function in GstMessage +
+
+
+gst_message_parse_info_details, function in GstMessage +
+
+
+gst_message_parse_new_clock, function in GstMessage +
+
+
+gst_message_parse_progress, function in GstMessage +
+
+
+gst_message_parse_property_notify, function in GstMessage +
+
+
+gst_message_parse_qos, function in GstMessage +
+
+
+gst_message_parse_qos_stats, function in GstMessage +
+
+
+gst_message_parse_qos_values, function in GstMessage +
+
+
+gst_message_parse_redirect_entry, function in GstMessage +
+
+
+gst_message_parse_request_state, function in GstMessage +
+
+
+gst_message_parse_reset_time, function in GstMessage +
+
+
+gst_message_parse_segment_done, function in GstMessage +
+
+
+gst_message_parse_segment_start, function in GstMessage +
+
+
+gst_message_parse_state_changed, function in GstMessage +
+
+
+gst_message_parse_step_done, function in GstMessage +
+
+
+gst_message_parse_step_start, function in GstMessage +
+
+
+gst_message_parse_streams_selected, function in GstMessage +
+
+
+gst_message_parse_stream_collection, function in GstMessage +
+
+
+gst_message_parse_stream_status, function in GstMessage +
+
+
+gst_message_parse_structure_change, function in GstMessage +
+
+
+gst_message_parse_tag, function in GstMessage +
+
+
+gst_message_parse_toc, function in GstMessage +
+
+
+gst_message_parse_warning, function in GstMessage +
+
+
+gst_message_parse_warning_details, function in GstMessage +
+
+
+gst_message_ref, function in GstMessage +
+
+
+gst_message_replace, function in GstMessage +
+
+
+GST_MESSAGE_SEQNUM, macro in GstMessage +
+
+
+gst_message_set_buffering_stats, function in GstMessage +
+
+
+gst_message_set_group_id, function in GstMessage +
+
+
+gst_message_set_qos_stats, function in GstMessage +
+
+
+gst_message_set_qos_values, function in GstMessage +
+
+
+gst_message_set_seqnum, function in GstMessage +
+
+
+gst_message_set_stream_status_object, function in GstMessage +
+
+
+GST_MESSAGE_SRC, macro in GstMessage +
+
+
+GST_MESSAGE_SRC_NAME, macro in GstMessage +
+
+
+gst_message_streams_selected_add, function in GstMessage +
+
+
+gst_message_streams_selected_get_size, function in GstMessage +
+
+
+gst_message_streams_selected_get_stream, function in GstMessage +
+
+
+GST_MESSAGE_TIMESTAMP, macro in GstMessage +
+
+
+GST_MESSAGE_TYPE, macro in GstMessage +
+
+
+gst_message_type_get_name, function in GstMessage +
+
+
+GST_MESSAGE_TYPE_IS_EXTENDED, macro in GstMessage +
+
+
+GST_MESSAGE_TYPE_NAME, macro in GstMessage +
+
+
+gst_message_type_to_quark, function in GstMessage +
+
+
+gst_message_unref, function in GstMessage +
+
+
+gst_message_writable_structure, function in GstMessage +
+
+
+GstMeta, struct in GstMeta +
+
+
+GstMetaFlags, enum in GstMeta +
+
+
+GstMetaFreeFunction, user_function in GstMeta +
+
+
+GstMetaInfo, struct in GstMeta +
+
+
+GstMetaInitFunction, user_function in GstMeta +
+
+
+GstMetaTransformCopy, struct in GstMeta +
+
+
+GstMetaTransformFunction, user_function in GstMeta +
+
+
+gst_meta_api_type_get_tags, function in GstMeta +
+
+
+gst_meta_api_type_has_tag, function in GstMeta +
+
+
+gst_meta_api_type_register, function in GstMeta +
+
+
+GST_META_FLAGS, macro in GstMeta +
+
+
+GST_META_FLAG_IS_SET, macro in GstMeta +
+
+
+GST_META_FLAG_SET, macro in GstMeta +
+
+
+GST_META_FLAG_UNSET, macro in GstMeta +
+
+
+gst_meta_get_info, function in GstMeta +
+
+
+gst_meta_register, function in GstMeta +
+
+
+GST_META_TAG_MEMORY, macro in GstMeta +
+
+
+GST_META_TAG_MEMORY_STR, macro in GstMeta +
+
+
+GST_META_TRANSFORM_IS_COPY, macro in GstMeta +
+
+
+GstMiniObject, struct in GstMiniObject +
+
+
+GstMiniObjectCopyFunction, user_function in GstMiniObject +
+
+
+GstMiniObjectDisposeFunction, user_function in GstMiniObject +
+
+
+GstMiniObjectFlags, enum in GstMiniObject +
+
+
+GstMiniObjectFreeFunction, user_function in GstMiniObject +
+
+
+GstMiniObjectNotify, user_function in GstMiniObject +
+
+
+gst_mini_object_copy, function in GstMiniObject +
+
+
+GST_MINI_OBJECT_FLAGS, macro in GstMiniObject +
+
+
+GST_MINI_OBJECT_FLAG_IS_SET, macro in GstMiniObject +
+
+
+GST_MINI_OBJECT_FLAG_SET, macro in GstMiniObject +
+
+
+GST_MINI_OBJECT_FLAG_UNSET, macro in GstMiniObject +
+
+
+gst_mini_object_get_qdata, function in GstMiniObject +
+
+
+gst_mini_object_init, function in GstMiniObject +
+
+
+GST_MINI_OBJECT_IS_LOCKABLE, macro in GstMiniObject +
+
+
+gst_mini_object_is_writable, function in GstMiniObject +
+
+
+gst_mini_object_lock, function in GstMiniObject +
+
+
+gst_mini_object_make_writable, function in GstMiniObject +
+
+
+gst_mini_object_ref, function in GstMiniObject +
+
+
+GST_MINI_OBJECT_REFCOUNT, macro in GstMiniObject +
+
+
+GST_MINI_OBJECT_REFCOUNT_VALUE, macro in GstMiniObject +
+
+
+gst_mini_object_replace, function in GstMiniObject +
+
+
+gst_mini_object_set_qdata, function in GstMiniObject +
+
+
+gst_mini_object_steal, function in GstMiniObject +
+
+
+gst_mini_object_steal_qdata, function in GstMiniObject +
+
+
+gst_mini_object_take, function in GstMiniObject +
+
+
+GST_MINI_OBJECT_TYPE, macro in GstMiniObject +
+
+
+gst_mini_object_unlock, function in GstMiniObject +
+
+
+gst_mini_object_unref, function in GstMiniObject +
+
+
+gst_mini_object_weak_ref, function in GstMiniObject +
+
+
+gst_mini_object_weak_unref, function in GstMiniObject +
+
+
+GST_MSECOND, macro in GstClock +
+
+

N

+
+GST_NSECOND, macro in GstClock +
+
+

O

+
+GstObject, struct in GstObject +
+
+
+GstObject::deep-notify, object signal in GstObject +
+
+
+GstObject:name, object property in GstObject +
+
+
+GstObject:parent, object property in GstObject +
+
+
+GstObjectClass, struct in GstObject +
+
+
+GstObjectFlags, enum in GstObject +
+
+
+gst_object_add_control_binding, function in GstObject +
+
+
+gst_object_check_uniqueness, function in GstObject +
+
+
+gst_object_default_deep_notify, function in GstObject +
+
+
+gst_object_default_error, function in GstObject +
+
+
+GST_OBJECT_FLAGS, macro in GstObject +
+
+
+GST_OBJECT_FLAG_IS_SET, macro in GstObject +
+
+
+GST_OBJECT_FLAG_SET, macro in GstObject +
+
+
+GST_OBJECT_FLAG_UNSET, macro in GstObject +
+
+
+gst_object_get_control_binding, function in GstObject +
+
+
+gst_object_get_control_rate, function in GstObject +
+
+
+gst_object_get_g_value_array, function in GstObject +
+
+
+GST_OBJECT_GET_LOCK, macro in GstObject +
+
+
+gst_object_get_name, function in GstObject +
+
+
+gst_object_get_parent, function in GstObject +
+
+
+gst_object_get_path_string, function in GstObject +
+
+
+gst_object_get_value, function in GstObject +
+
+
+gst_object_get_value_array, function in GstObject +
+
+
+gst_object_has_active_control_bindings, function in GstObject +
+
+
+gst_object_has_ancestor, function in GstObject +
+
+
+gst_object_has_as_ancestor, function in GstObject +
+
+
+gst_object_has_as_parent, function in GstObject +
+
+
+GST_OBJECT_LOCK, macro in GstObject +
+
+
+GST_OBJECT_NAME, macro in GstObject +
+
+
+GST_OBJECT_PARENT, macro in GstObject +
+
+
+gst_object_ref, function in GstObject +
+
+
+GST_OBJECT_REFCOUNT, macro in GstObject +
+
+
+GST_OBJECT_REFCOUNT_VALUE, macro in GstObject +
+
+
+gst_object_ref_sink, function in GstObject +
+
+
+gst_object_remove_control_binding, function in GstObject +
+
+
+gst_object_replace, function in GstObject +
+
+
+gst_object_set_control_bindings_disabled, function in GstObject +
+
+
+gst_object_set_control_binding_disabled, function in GstObject +
+
+
+gst_object_set_control_rate, function in GstObject +
+
+
+gst_object_set_name, function in GstObject +
+
+
+gst_object_set_parent, function in GstObject +
+
+
+gst_object_suggest_next_sync, function in GstObject +
+
+
+gst_object_sync_values, function in GstObject +
+
+
+GST_OBJECT_TRYLOCK, macro in GstObject +
+
+
+GST_OBJECT_UNLOCK, macro in GstObject +
+
+
+gst_object_unparent, function in GstObject +
+
+
+gst_object_unref, function in GstObject +
+
+

P

+
+GstPad, struct in GstPad +
+
+
+GstPad::linked, object signal in GstPad +
+
+
+GstPad::unlinked, object signal in GstPad +
+
+
+GstPad:caps, object property in GstPad +
+
+
+GstPad:direction, object property in GstPad +
+
+
+GstPad:offset, object property in GstPad +
+
+
+GstPad:template, object property in GstPad +
+
+
+GstPadActivateFunction, user_function in GstPad +
+
+
+GstPadActivateModeFunction, user_function in GstPad +
+
+
+GstPadChainFunction, user_function in GstPad +
+
+
+GstPadChainListFunction, user_function in GstPad +
+
+
+GstPadDirection, enum in GstPad +
+
+
+GstPadEventFullFunction, user_function in GstPad +
+
+
+GstPadEventFunction, user_function in GstPad +
+
+
+GstPadFlags, enum in GstPad +
+
+
+GstPadForwardFunction, user_function in GstPad +
+
+
+GstPadGetRangeFunction, user_function in GstPad +
+
+
+GstPadIterIntLinkFunction, user_function in GstPad +
+
+
+GstPadLinkCheck, enum in GstPad +
+
+
+GstPadLinkFunction, user_function in GstPad +
+
+
+GstPadLinkReturn, enum in GstPad +
+
+
+GstPadMode, enum in GstPad +
+
+
+GstPadPresence, enum in GstPadTemplate +
+
+
+GstPadProbeCallback, user_function in GstPad +
+
+
+GstPadProbeInfo, struct in GstPad +
+
+
+GstPadProbeReturn, enum in GstPad +
+
+
+GstPadProbeType, enum in GstPad +
+
+
+GstPadQueryFunction, user_function in GstPad +
+
+
+GstPadStickyEventsForeachFunction, user_function in GstPad +
+
+
+GstPadTemplate, struct in GstPadTemplate +
+
+
+GstPadTemplate::pad-created, object signal in GstPadTemplate +
+
+
+GstPadTemplate:caps, object property in GstPadTemplate +
+
+
+GstPadTemplate:direction, object property in GstPadTemplate +
+
+
+GstPadTemplate:gtype, object property in GstPadTemplate +
+
+
+GstPadTemplate:name-template, object property in GstPadTemplate +
+
+
+GstPadTemplate:presence, object property in GstPadTemplate +
+
+
+GstPadTemplateFlags, enum in GstPadTemplate +
+
+
+GstPadUnlinkFunction, user_function in GstPad +
+
+
+GST_PAD_ACTIVATEFUNC, macro in GstPad +
+
+
+GST_PAD_ACTIVATEMODEFUNC, macro in GstPad +
+
+
+gst_pad_activate_mode, function in GstPad +
+
+
+gst_pad_add_probe, function in GstPad +
+
+
+gst_pad_can_link, function in GstPad +
+
+
+gst_pad_chain, function in GstPad +
+
+
+GST_PAD_CHAINFUNC, macro in GstPad +
+
+
+GST_PAD_CHAINLISTFUNC, macro in GstPad +
+
+
+gst_pad_chain_list, function in GstPad +
+
+
+gst_pad_check_reconfigure, function in GstPad +
+
+
+gst_pad_create_stream_id, function in GstPad +
+
+
+gst_pad_create_stream_id_printf, function in GstPad +
+
+
+gst_pad_create_stream_id_printf_valist, function in GstPad +
+
+
+GST_PAD_DIRECTION, macro in GstPad +
+
+
+GST_PAD_ELEMENT_PRIVATE, macro in GstPad +
+
+
+GST_PAD_EVENTFULLFUNC, macro in GstPad +
+
+
+GST_PAD_EVENTFUNC, macro in GstPad +
+
+
+gst_pad_event_default, function in GstPad +
+
+
+gst_pad_forward, function in GstPad +
+
+
+GST_PAD_GETRANGEFUNC, macro in GstPad +
+
+
+gst_pad_get_allowed_caps, function in GstPad +
+
+
+gst_pad_get_current_caps, function in GstPad +
+
+
+gst_pad_get_direction, function in GstPad +
+
+
+gst_pad_get_element_private, function in GstPad +
+
+
+gst_pad_get_last_flow_return, function in GstPad +
+
+
+gst_pad_get_name, macro in GstPad +
+
+
+gst_pad_get_offset, function in GstPad +
+
+
+gst_pad_get_pad_template, function in GstPad +
+
+
+gst_pad_get_pad_template_caps, function in GstPad +
+
+
+gst_pad_get_parent, macro in GstPad +
+
+
+gst_pad_get_parent_element, function in GstPad +
+
+
+gst_pad_get_peer, function in GstPad +
+
+
+gst_pad_get_range, function in GstPad +
+
+
+gst_pad_get_sticky_event, function in GstPad +
+
+
+gst_pad_get_stream, function in GstPad +
+
+
+gst_pad_get_stream_id, function in GstPad +
+
+
+GST_PAD_GET_STREAM_LOCK, macro in GstPad +
+
+
+gst_pad_get_task_state, function in GstPad +
+
+
+gst_pad_has_current_caps, function in GstPad +
+
+
+GST_PAD_HAS_PENDING_EVENTS, macro in GstPad +
+
+
+GST_PAD_IS_ACCEPT_INTERSECT, macro in GstPad +
+
+
+GST_PAD_IS_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+GST_PAD_IS_ACTIVE, macro in GstPad +
+
+
+gst_pad_is_active, function in GstPad +
+
+
+GST_PAD_IS_BLOCKED, macro in GstPad +
+
+
+gst_pad_is_blocked, function in GstPad +
+
+
+GST_PAD_IS_BLOCKING, macro in GstPad +
+
+
+gst_pad_is_blocking, function in GstPad +
+
+
+GST_PAD_IS_EOS, macro in GstPad +
+
+
+GST_PAD_IS_FIXED_CAPS, macro in GstPad +
+
+
+GST_PAD_IS_FLUSHING, macro in GstPad +
+
+
+GST_PAD_IS_LINKED, macro in GstPad +
+
+
+gst_pad_is_linked, function in GstPad +
+
+
+GST_PAD_IS_PROXY_ALLOCATION, macro in GstPad +
+
+
+GST_PAD_IS_PROXY_CAPS, macro in GstPad +
+
+
+GST_PAD_IS_PROXY_SCHEDULING, macro in GstPad +
+
+
+GST_PAD_IS_SINK, macro in GstPad +
+
+
+GST_PAD_IS_SRC, macro in GstPad +
+
+
+gst_pad_iterate_internal_links, function in GstPad +
+
+
+gst_pad_iterate_internal_links_default, function in GstPad +
+
+
+GST_PAD_ITERINTLINKFUNC, macro in GstPad +
+
+
+GST_PAD_LAST_FLOW_RETURN, macro in GstPad +
+
+
+gst_pad_link, function in GstPad +
+
+
+GST_PAD_LINKFUNC, macro in GstPad +
+
+
+GST_PAD_LINK_FAILED, macro in GstPad +
+
+
+gst_pad_link_full, function in GstPad +
+
+
+gst_pad_link_get_name, function in GstPad +
+
+
+gst_pad_link_maybe_ghosting, function in GstPad +
+
+
+gst_pad_link_maybe_ghosting_full, function in GstPad +
+
+
+GST_PAD_LINK_SUCCESSFUL, macro in GstPad +
+
+
+gst_pad_mark_reconfigure, function in GstPad +
+
+
+GST_PAD_MODE, macro in GstPad +
+
+
+gst_pad_mode_get_name, function in GstPad +
+
+
+GST_PAD_NAME, macro in GstPad +
+
+
+GST_PAD_NEEDS_PARENT, macro in GstPad +
+
+
+GST_PAD_NEEDS_RECONFIGURE, macro in GstPad +
+
+
+gst_pad_needs_reconfigure, function in GstPad +
+
+
+gst_pad_new, function in GstPad +
+
+
+gst_pad_new_from_static_template, function in GstPad +
+
+
+gst_pad_new_from_template, function in GstPad +
+
+
+GST_PAD_PAD_TEMPLATE, macro in GstPad +
+
+
+GST_PAD_PARENT, macro in GstPad +
+
+
+gst_pad_pause_task, function in GstPad +
+
+
+GST_PAD_PEER, macro in GstPad +
+
+
+gst_pad_peer_query, function in GstPad +
+
+
+gst_pad_peer_query_accept_caps, function in GstPad +
+
+
+gst_pad_peer_query_caps, function in GstPad +
+
+
+gst_pad_peer_query_convert, function in GstPad +
+
+
+gst_pad_peer_query_duration, function in GstPad +
+
+
+gst_pad_peer_query_position, function in GstPad +
+
+
+GST_PAD_PROBE_INFO_BUFFER, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_BUFFER_LIST, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_DATA, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_EVENT, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_FLOW_RETURN, macro in GstPad +
+
+
+gst_pad_probe_info_get_buffer, function in GstPad +
+
+
+gst_pad_probe_info_get_buffer_list, function in GstPad +
+
+
+gst_pad_probe_info_get_event, function in GstPad +
+
+
+gst_pad_probe_info_get_query, function in GstPad +
+
+
+GST_PAD_PROBE_INFO_ID, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_OFFSET, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_QUERY, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_SIZE, macro in GstPad +
+
+
+GST_PAD_PROBE_INFO_TYPE, macro in GstPad +
+
+
+gst_pad_proxy_query_accept_caps, function in GstPad +
+
+
+gst_pad_proxy_query_caps, function in GstPad +
+
+
+gst_pad_pull_range, function in GstPad +
+
+
+gst_pad_push, function in GstPad +
+
+
+gst_pad_push_event, function in GstPad +
+
+
+gst_pad_push_list, function in GstPad +
+
+
+gst_pad_query, function in GstPad +
+
+
+GST_PAD_QUERYFUNC, macro in GstPad +
+
+
+gst_pad_query_accept_caps, function in GstPad +
+
+
+gst_pad_query_caps, function in GstPad +
+
+
+gst_pad_query_convert, function in GstPad +
+
+
+gst_pad_query_default, function in GstPad +
+
+
+gst_pad_query_duration, function in GstPad +
+
+
+gst_pad_query_position, function in GstPad +
+
+
+gst_pad_remove_probe, function in GstPad +
+
+
+gst_pad_send_event, function in GstPad +
+
+
+GST_PAD_SET_ACCEPT_INTERSECT, macro in GstPad +
+
+
+GST_PAD_SET_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+gst_pad_set_activatemode_function, macro in GstPad +
+
+
+gst_pad_set_activatemode_function_full, function in GstPad +
+
+
+gst_pad_set_activate_function, macro in GstPad +
+
+
+gst_pad_set_activate_function_full, function in GstPad +
+
+
+gst_pad_set_active, function in GstPad +
+
+
+gst_pad_set_chain_function, macro in GstPad +
+
+
+gst_pad_set_chain_function_full, function in GstPad +
+
+
+gst_pad_set_chain_list_function, macro in GstPad +
+
+
+gst_pad_set_chain_list_function_full, function in GstPad +
+
+
+gst_pad_set_element_private, function in GstPad +
+
+
+gst_pad_set_event_full_function, macro in GstPad +
+
+
+gst_pad_set_event_full_function_full, function in GstPad +
+
+
+gst_pad_set_event_function, macro in GstPad +
+
+
+gst_pad_set_event_function_full, function in GstPad +
+
+
+GST_PAD_SET_FLUSHING, macro in GstPad +
+
+
+gst_pad_set_getrange_function, macro in GstPad +
+
+
+gst_pad_set_getrange_function_full, function in GstPad +
+
+
+gst_pad_set_iterate_internal_links_function, macro in GstPad +
+
+
+gst_pad_set_iterate_internal_links_function_full, function in GstPad +
+
+
+gst_pad_set_link_function, macro in GstPad +
+
+
+gst_pad_set_link_function_full, function in GstPad +
+
+
+gst_pad_set_offset, function in GstPad +
+
+
+GST_PAD_SET_PROXY_ALLOCATION, macro in GstPad +
+
+
+GST_PAD_SET_PROXY_CAPS, macro in GstPad +
+
+
+GST_PAD_SET_PROXY_SCHEDULING, macro in GstPad +
+
+
+gst_pad_set_query_function, macro in GstPad +
+
+
+gst_pad_set_query_function_full, function in GstPad +
+
+
+gst_pad_set_unlink_function, macro in GstPad +
+
+
+gst_pad_set_unlink_function_full, function in GstPad +
+
+
+gst_pad_start_task, function in GstPad +
+
+
+gst_pad_sticky_events_foreach, function in GstPad +
+
+
+gst_pad_stop_task, function in GstPad +
+
+
+gst_pad_store_sticky_event, function in GstPad +
+
+
+GST_PAD_STREAM_LOCK, macro in GstPad +
+
+
+GST_PAD_STREAM_TRYLOCK, macro in GstPad +
+
+
+GST_PAD_STREAM_UNLOCK, macro in GstPad +
+
+
+GST_PAD_TASK, macro in GstPad +
+
+
+GST_PAD_TEMPLATE_CAPS, macro in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_DIRECTION, macro in GstPadTemplate +
+
+
+gst_pad_template_get_caps, function in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_GTYPE, macro in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_IS_FIXED, macro in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_NAME_TEMPLATE, macro in GstPadTemplate +
+
+
+gst_pad_template_new, function in GstPadTemplate +
+
+
+gst_pad_template_new_from_static_pad_template_with_gtype, function in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_PRESENCE, macro in GstPadTemplate +
+
+
+gst_pad_unlink, function in GstPad +
+
+
+GST_PAD_UNLINKFUNC, macro in GstPad +
+
+
+GST_PAD_UNSET_ACCEPT_INTERSECT, macro in GstPad +
+
+
+GST_PAD_UNSET_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+GST_PAD_UNSET_FLUSHING, macro in GstPad +
+
+
+GST_PAD_UNSET_PROXY_ALLOCATION, macro in GstPad +
+
+
+GST_PAD_UNSET_PROXY_CAPS, macro in GstPad +
+
+
+GST_PAD_UNSET_PROXY_SCHEDULING, macro in GstPad +
+
+
+gst_pad_use_fixed_caps, function in GstPad +
+
+
+GstParamSpecArray, struct in GstParamSpec +
+
+
+GstParamSpecFraction, struct in GstParamSpec +
+
+
+GST_PARAM_CONTROLLABLE, macro in GstParamSpec +
+
+
+GST_PARAM_MUTABLE_PAUSED, macro in GstParamSpec +
+
+
+GST_PARAM_MUTABLE_PLAYING, macro in GstParamSpec +
+
+
+GST_PARAM_MUTABLE_READY, macro in GstParamSpec +
+
+
+gst_param_spec_array, function in GstParamSpec +
+
+
+gst_param_spec_fraction, function in GstParamSpec +
+
+
+GST_PARAM_USER_SHIFT, macro in GstParamSpec +
+
+
+GstParentBufferMeta, struct in GstBuffer +
+
+
+GstParseContext, struct in GstParse +
+
+
+GstParseError, enum in GstParse +
+
+
+GstParseFlags, enum in GstParse +
+
+
+gst_parse_bin_from_description, function in GstParse +
+
+
+gst_parse_bin_from_description_full, function in GstParse +
+
+
+gst_parse_context_copy, function in GstParse +
+
+
+gst_parse_context_free, function in GstParse +
+
+
+gst_parse_context_get_missing_elements, function in GstParse +
+
+
+gst_parse_context_new, function in GstParse +
+
+
+GST_PARSE_ERROR, macro in GstParse +
+
+
+gst_parse_error_quark, function in GstParse +
+
+
+gst_parse_launch, function in GstParse +
+
+
+gst_parse_launchv, function in GstParse +
+
+
+gst_parse_launchv_full, function in GstParse +
+
+
+gst_parse_launch_full, function in GstParse +
+
+
+GstPipeline, struct in GstPipeline +
+
+
+GstPipeline:auto-flush-bus, object property in GstPipeline +
+
+
+GstPipeline:delay, object property in GstPipeline +
+
+
+GstPipeline:latency, object property in GstPipeline +
+
+
+GstPipelineFlags, enum in GstPipeline +
+
+
+gst_pipeline_auto_clock, function in GstPipeline +
+
+
+gst_pipeline_get_auto_flush_bus, function in GstPipeline +
+
+
+gst_pipeline_get_bus, function in GstPipeline +
+
+
+gst_pipeline_get_clock, function in GstPipeline +
+
+
+gst_pipeline_get_delay, function in GstPipeline +
+
+
+gst_pipeline_get_latency, function in GstPipeline +
+
+
+gst_pipeline_get_pipeline_clock, function in GstPipeline +
+
+
+gst_pipeline_new, function in GstPipeline +
+
+
+gst_pipeline_set_auto_flush_bus, function in GstPipeline +
+
+
+gst_pipeline_set_clock, function in GstPipeline +
+
+
+gst_pipeline_set_delay, function in GstPipeline +
+
+
+gst_pipeline_set_latency, function in GstPipeline +
+
+
+gst_pipeline_use_clock, function in GstPipeline +
+
+
+GstPlugin, struct in GstPlugin +
+
+
+GstPluginDependencyFlags, enum in GstPlugin +
+
+
+GstPluginDesc, struct in GstPlugin +
+
+
+GstPluginError, enum in GstPlugin +
+
+
+GstPluginFeature, struct in GstPluginFeature +
+
+
+GstPluginFeatureFilter, user_function in GstPluginFeature +
+
+
+GstPluginFilter, user_function in GstPlugin +
+
+
+GstPluginFlags, enum in GstPlugin +
+
+
+GstPluginInitFullFunc, user_function in GstPlugin +
+
+
+GstPluginInitFunc, user_function in GstPlugin +
+
+
+gst_plugin_add_dependency, function in GstPlugin +
+
+
+gst_plugin_add_dependency_simple, function in GstPlugin +
+
+
+GST_PLUGIN_DEFINE, macro in GstPlugin +
+
+
+GST_PLUGIN_ERROR, macro in GstPlugin +
+
+
+gst_plugin_error_quark, function in GstPlugin +
+
+
+gst_plugin_feature_check_version, function in GstPluginFeature +
+
+
+gst_plugin_feature_get_name, macro in GstPluginFeature +
+
+
+gst_plugin_feature_get_plugin, function in GstPluginFeature +
+
+
+gst_plugin_feature_get_plugin_name, function in GstPluginFeature +
+
+
+gst_plugin_feature_get_rank, function in GstPluginFeature +
+
+
+gst_plugin_feature_list_copy, function in GstPluginFeature +
+
+
+GST_PLUGIN_FEATURE_LIST_DEBUG, macro in GstPluginFeature +
+
+
+gst_plugin_feature_list_free, function in GstPluginFeature +
+
+
+gst_plugin_feature_load, function in GstPluginFeature +
+
+
+gst_plugin_feature_rank_compare_func, function in GstPluginFeature +
+
+
+gst_plugin_feature_set_name, macro in GstPluginFeature +
+
+
+gst_plugin_feature_set_rank, function in GstPluginFeature +
+
+
+gst_plugin_get_cache_data, function in GstPlugin +
+
+
+gst_plugin_get_description, function in GstPlugin +
+
+
+gst_plugin_get_filename, function in GstPlugin +
+
+
+gst_plugin_get_license, function in GstPlugin +
+
+
+gst_plugin_get_name, function in GstPlugin +
+
+
+gst_plugin_get_origin, function in GstPlugin +
+
+
+gst_plugin_get_package, function in GstPlugin +
+
+
+gst_plugin_get_release_date_string, function in GstPlugin +
+
+
+gst_plugin_get_source, function in GstPlugin +
+
+
+gst_plugin_get_version, function in GstPlugin +
+
+
+gst_plugin_is_loaded, function in GstPlugin +
+
+
+gst_plugin_list_free, function in GstPlugin +
+
+
+gst_plugin_load, function in GstPlugin +
+
+
+gst_plugin_load_by_name, function in GstPlugin +
+
+
+gst_plugin_load_file, function in GstPlugin +
+
+
+gst_plugin_register_static, function in GstPlugin +
+
+
+gst_plugin_register_static_full, function in GstPlugin +
+
+
+gst_plugin_set_cache_data, function in GstPlugin +
+
+
+GST_PLUGIN_STATIC_DECLARE, macro in GstPlugin +
+
+
+GST_PLUGIN_STATIC_REGISTER, macro in GstPlugin +
+
+
+GstPoll, struct in GstPoll +
+
+
+GstPollFD, struct in GstPoll +
+
+
+gst_poll_add_fd, function in GstPoll +
+
+
+gst_poll_fd_can_read, function in GstPoll +
+
+
+gst_poll_fd_can_write, function in GstPoll +
+
+
+gst_poll_fd_ctl_read, function in GstPoll +
+
+
+gst_poll_fd_ctl_write, function in GstPoll +
+
+
+gst_poll_fd_has_closed, function in GstPoll +
+
+
+gst_poll_fd_has_error, function in GstPoll +
+
+
+gst_poll_fd_ignored, function in GstPoll +
+
+
+GST_POLL_FD_INIT, macro in GstPoll +
+
+
+gst_poll_fd_init, function in GstPoll +
+
+
+gst_poll_free, function in GstPoll +
+
+
+gst_poll_get_read_gpollfd, function in GstPoll +
+
+
+gst_poll_new, function in GstPoll +
+
+
+gst_poll_new_timer, function in GstPoll +
+
+
+gst_poll_read_control, function in GstPoll +
+
+
+gst_poll_remove_fd, function in GstPoll +
+
+
+gst_poll_restart, function in GstPoll +
+
+
+gst_poll_set_controllable, function in GstPoll +
+
+
+gst_poll_set_flushing, function in GstPoll +
+
+
+gst_poll_wait, function in GstPoll +
+
+
+gst_poll_write_control, function in GstPoll +
+
+
+GstPreset, struct in GstPreset +
+
+
+GstPresetInterface, struct in GstPreset +
+
+
+gst_preset_delete_preset, function in GstPreset +
+
+
+gst_preset_get_app_dir, function in GstPreset +
+
+
+gst_preset_get_meta, function in GstPreset +
+
+
+gst_preset_get_preset_names, function in GstPreset +
+
+
+gst_preset_get_property_names, function in GstPreset +
+
+
+gst_preset_is_editable, function in GstPreset +
+
+
+gst_preset_load_preset, function in GstPreset +
+
+
+gst_preset_rename_preset, function in GstPreset +
+
+
+gst_preset_save_preset, function in GstPreset +
+
+
+gst_preset_set_app_dir, function in GstPreset +
+
+
+gst_preset_set_meta, function in GstPreset +
+
+
+gst_print, function in GstInfo +
+
+
+gst_printerr, function in GstInfo +
+
+
+gst_printerrln, function in GstInfo +
+
+
+gst_println, function in GstInfo +
+
+
+GstProgressType, enum in GstMessage +
+
+
+GstPromise, struct in GstPromise +
+
+
+GstPromiseChangeFunc, user_function in GstPromise +
+
+
+GstPromiseResult, enum in GstPromise +
+
+
+gst_promise_expire, function in GstPromise +
+
+
+gst_promise_get_reply, function in GstPromise +
+
+
+gst_promise_interrupt, function in GstPromise +
+
+
+gst_promise_new, function in GstPromise +
+
+
+gst_promise_new_with_change_func, function in GstPromise +
+
+
+gst_promise_ref, function in GstPromise +
+
+
+gst_promise_reply, function in GstPromise +
+
+
+gst_promise_unref, function in GstPromise +
+
+
+gst_promise_wait, function in GstPromise +
+
+
+GstProtectionMeta, struct in GstProtectionMeta +
+
+
+gst_protection_filter_systems_by_available_decryptors, function in GstProtectionMeta +
+
+
+gst_protection_select_system, function in GstProtectionMeta +
+
+
+GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, macro in GstProtectionMeta +
+
+
+GstProxyPad, struct in GstGhostPad +
+
+
+gst_proxy_pad_chain_default, function in GstGhostPad +
+
+
+gst_proxy_pad_chain_list_default, function in GstGhostPad +
+
+
+gst_proxy_pad_getrange_default, function in GstGhostPad +
+
+
+gst_proxy_pad_get_internal, function in GstGhostPad +
+
+
+gst_proxy_pad_iterate_internal_links_default, function in GstGhostPad +
+
+
+GST_PTR_FORMAT, macro in GstInfo +
+
+

Q

+
+GstQOSType, enum in GstEvent +
+
+
+GstQuery, struct in GstQuery +
+
+
+GstQueryType, enum in GstQuery +
+
+
+GstQueryTypeFlags, enum in GstQuery +
+
+
+gst_query_add_allocation_meta, function in GstQuery +
+
+
+gst_query_add_allocation_param, function in GstQuery +
+
+
+gst_query_add_allocation_pool, function in GstQuery +
+
+
+gst_query_add_buffering_range, function in GstQuery +
+
+
+gst_query_add_scheduling_mode, function in GstQuery +
+
+
+gst_query_copy, function in GstQuery +
+
+
+gst_query_find_allocation_meta, function in GstQuery +
+
+
+gst_query_get_n_allocation_metas, function in GstQuery +
+
+
+gst_query_get_n_allocation_params, function in GstQuery +
+
+
+gst_query_get_n_allocation_pools, function in GstQuery +
+
+
+gst_query_get_n_buffering_ranges, function in GstQuery +
+
+
+gst_query_get_n_scheduling_modes, function in GstQuery +
+
+
+gst_query_get_structure, function in GstQuery +
+
+
+gst_query_has_scheduling_mode, function in GstQuery +
+
+
+gst_query_has_scheduling_mode_with_flags, function in GstQuery +
+
+
+GST_QUERY_IS_DOWNSTREAM, macro in GstQuery +
+
+
+GST_QUERY_IS_SERIALIZED, macro in GstQuery +
+
+
+GST_QUERY_IS_UPSTREAM, macro in GstQuery +
+
+
+gst_query_is_writable, macro in GstQuery +
+
+
+GST_QUERY_MAKE_TYPE, macro in GstQuery +
+
+
+gst_query_make_writable, macro in GstQuery +
+
+
+gst_query_new_accept_caps, function in GstQuery +
+
+
+gst_query_new_allocation, function in GstQuery +
+
+
+gst_query_new_buffering, function in GstQuery +
+
+
+gst_query_new_caps, function in GstQuery +
+
+
+gst_query_new_context, function in GstQuery +
+
+
+gst_query_new_convert, function in GstQuery +
+
+
+gst_query_new_custom, function in GstQuery +
+
+
+gst_query_new_drain, function in GstQuery +
+
+
+gst_query_new_duration, function in GstQuery +
+
+
+gst_query_new_formats, function in GstQuery +
+
+
+gst_query_new_latency, function in GstQuery +
+
+
+gst_query_new_position, function in GstQuery +
+
+
+gst_query_new_scheduling, function in GstQuery +
+
+
+gst_query_new_seeking, function in GstQuery +
+
+
+gst_query_new_segment, function in GstQuery +
+
+
+gst_query_new_uri, function in GstQuery +
+
+
+gst_query_parse_accept_caps, function in GstQuery +
+
+
+gst_query_parse_accept_caps_result, function in GstQuery +
+
+
+gst_query_parse_allocation, function in GstQuery +
+
+
+gst_query_parse_buffering_percent, function in GstQuery +
+
+
+gst_query_parse_buffering_range, function in GstQuery +
+
+
+gst_query_parse_buffering_stats, function in GstQuery +
+
+
+gst_query_parse_caps, function in GstQuery +
+
+
+gst_query_parse_caps_result, function in GstQuery +
+
+
+gst_query_parse_context, function in GstQuery +
+
+
+gst_query_parse_context_type, function in GstQuery +
+
+
+gst_query_parse_convert, function in GstQuery +
+
+
+gst_query_parse_duration, function in GstQuery +
+
+
+gst_query_parse_latency, function in GstQuery +
+
+
+gst_query_parse_nth_allocation_meta, function in GstQuery +
+
+
+gst_query_parse_nth_allocation_param, function in GstQuery +
+
+
+gst_query_parse_nth_allocation_pool, function in GstQuery +
+
+
+gst_query_parse_nth_buffering_range, function in GstQuery +
+
+
+gst_query_parse_nth_format, function in GstQuery +
+
+
+gst_query_parse_nth_scheduling_mode, function in GstQuery +
+
+
+gst_query_parse_n_formats, function in GstQuery +
+
+
+gst_query_parse_position, function in GstQuery +
+
+
+gst_query_parse_scheduling, function in GstQuery +
+
+
+gst_query_parse_seeking, function in GstQuery +
+
+
+gst_query_parse_segment, function in GstQuery +
+
+
+gst_query_parse_uri, function in GstQuery +
+
+
+gst_query_parse_uri_redirection, function in GstQuery +
+
+
+gst_query_parse_uri_redirection_permanent, function in GstQuery +
+
+
+gst_query_ref, function in GstQuery +
+
+
+gst_query_remove_nth_allocation_meta, function in GstQuery +
+
+
+gst_query_remove_nth_allocation_param, function in GstQuery +
+
+
+gst_query_remove_nth_allocation_pool, function in GstQuery +
+
+
+gst_query_replace, function in GstQuery +
+
+
+gst_query_set_accept_caps_result, function in GstQuery +
+
+
+gst_query_set_buffering_percent, function in GstQuery +
+
+
+gst_query_set_buffering_range, function in GstQuery +
+
+
+gst_query_set_buffering_stats, function in GstQuery +
+
+
+gst_query_set_caps_result, function in GstQuery +
+
+
+gst_query_set_context, function in GstQuery +
+
+
+gst_query_set_convert, function in GstQuery +
+
+
+gst_query_set_duration, function in GstQuery +
+
+
+gst_query_set_formats, function in GstQuery +
+
+
+gst_query_set_formatsv, function in GstQuery +
+
+
+gst_query_set_latency, function in GstQuery +
+
+
+gst_query_set_nth_allocation_param, function in GstQuery +
+
+
+gst_query_set_nth_allocation_pool, function in GstQuery +
+
+
+gst_query_set_position, function in GstQuery +
+
+
+gst_query_set_scheduling, function in GstQuery +
+
+
+gst_query_set_seeking, function in GstQuery +
+
+
+gst_query_set_segment, function in GstQuery +
+
+
+gst_query_set_uri, function in GstQuery +
+
+
+gst_query_set_uri_redirection, function in GstQuery +
+
+
+gst_query_set_uri_redirection_permanent, function in GstQuery +
+
+
+GST_QUERY_TYPE, macro in GstQuery +
+
+
+GST_QUERY_TYPE_BOTH, macro in GstQuery +
+
+
+gst_query_type_get_flags, function in GstQuery +
+
+
+gst_query_type_get_name, function in GstQuery +
+
+
+GST_QUERY_TYPE_NAME, macro in GstQuery +
+
+
+gst_query_type_to_quark, function in GstQuery +
+
+
+gst_query_unref, function in GstQuery +
+
+
+gst_query_writable_structure, function in GstQuery +
+
+

R

+
+GstRank, enum in GstPluginFeature +
+
+
+GST_READ_DOUBLE_BE, function in GstUtils +
+
+
+GST_READ_DOUBLE_LE, function in GstUtils +
+
+
+GST_READ_FLOAT_BE, function in GstUtils +
+
+
+GST_READ_FLOAT_LE, function in GstUtils +
+
+
+GST_READ_UINT16_BE, macro in GstUtils +
+
+
+GST_READ_UINT16_LE, macro in GstUtils +
+
+
+GST_READ_UINT24_BE, macro in GstUtils +
+
+
+GST_READ_UINT24_LE, macro in GstUtils +
+
+
+GST_READ_UINT32_BE, macro in GstUtils +
+
+
+GST_READ_UINT32_LE, macro in GstUtils +
+
+
+GST_READ_UINT64_BE, macro in GstUtils +
+
+
+GST_READ_UINT64_LE, macro in GstUtils +
+
+
+GST_READ_UINT8, macro in GstUtils +
+
+
+GstReferenceTimestampMeta, struct in GstBuffer +
+
+
+GstRegistry, struct in GstRegistry +
+
+
+GstRegistry::feature-added, object signal in GstRegistry +
+
+
+GstRegistry::plugin-added, object signal in GstRegistry +
+
+
+gst_registry_add_feature, function in GstRegistry +
+
+
+gst_registry_add_path, function in GstRegistry +
+
+
+gst_registry_add_plugin, function in GstRegistry +
+
+
+gst_registry_check_feature_version, function in GstRegistry +
+
+
+gst_registry_feature_filter, function in GstRegistry +
+
+
+gst_registry_find_feature, function in GstRegistry +
+
+
+gst_registry_find_plugin, function in GstRegistry +
+
+
+gst_registry_fork_is_enabled, function in Gst +
+
+
+gst_registry_fork_set_enabled, function in Gst +
+
+
+gst_registry_get, function in GstRegistry +
+
+
+gst_registry_get_feature_list, function in GstRegistry +
+
+
+gst_registry_get_feature_list_by_plugin, function in GstRegistry +
+
+
+gst_registry_get_feature_list_cookie, function in GstRegistry +
+
+
+gst_registry_get_path_list, function in GstRegistry +
+
+
+gst_registry_get_plugin_list, function in GstRegistry +
+
+
+gst_registry_lookup, function in GstRegistry +
+
+
+gst_registry_lookup_feature, function in GstRegistry +
+
+
+gst_registry_plugin_filter, function in GstRegistry +
+
+
+gst_registry_remove_feature, function in GstRegistry +
+
+
+gst_registry_remove_plugin, function in GstRegistry +
+
+
+gst_registry_scan_path, function in GstRegistry +
+
+
+GstResourceError, enum in GstGError +
+
+
+GST_RESOURCE_ERROR, macro in GstGError +
+
+
+GST_ROUND_DOWN_128, macro in GstUtils +
+
+
+GST_ROUND_DOWN_16, macro in GstUtils +
+
+
+GST_ROUND_DOWN_2, macro in GstUtils +
+
+
+GST_ROUND_DOWN_32, macro in GstUtils +
+
+
+GST_ROUND_DOWN_4, macro in GstUtils +
+
+
+GST_ROUND_DOWN_64, macro in GstUtils +
+
+
+GST_ROUND_DOWN_8, macro in GstUtils +
+
+
+GST_ROUND_DOWN_N, macro in GstUtils +
+
+
+GST_ROUND_UP_128, macro in GstUtils +
+
+
+GST_ROUND_UP_16, macro in GstUtils +
+
+
+GST_ROUND_UP_2, macro in GstUtils +
+
+
+GST_ROUND_UP_32, macro in GstUtils +
+
+
+GST_ROUND_UP_4, macro in GstUtils +
+
+
+GST_ROUND_UP_64, macro in GstUtils +
+
+
+GST_ROUND_UP_8, macro in GstUtils +
+
+
+GST_ROUND_UP_N, macro in GstUtils +
+
+

S

+
+GstSample, struct in GstSample +
+
+
+gst_sample_copy, function in GstSample +
+
+
+gst_sample_get_buffer, function in GstSample +
+
+
+gst_sample_get_buffer_list, function in GstSample +
+
+
+gst_sample_get_caps, function in GstSample +
+
+
+gst_sample_get_info, function in GstSample +
+
+
+gst_sample_get_segment, function in GstSample +
+
+
+gst_sample_new, function in GstSample +
+
+
+gst_sample_ref, function in GstSample +
+
+
+gst_sample_set_buffer_list, function in GstSample +
+
+
+gst_sample_unref, function in GstSample +
+
+
+GstSchedulingFlags, enum in GstQuery +
+
+
+GstSearchMode, enum in GstUtils +
+
+
+GST_SECOND, macro in GstClock +
+
+
+GstSeekFlags, enum in GstEvent +
+
+
+GstSeekType, enum in GstEvent +
+
+
+GstSegment, struct in GstSegment +
+
+
+GstSegmentFlags, enum in GstSegment +
+
+
+gst_segment_clip, function in GstSegment +
+
+
+gst_segment_copy, function in GstSegment +
+
+
+gst_segment_copy_into, function in GstSegment +
+
+
+gst_segment_do_seek, function in GstSegment +
+
+
+GST_SEGMENT_FORMAT, macro in GstInfo +
+
+
+gst_segment_free, function in GstSegment +
+
+
+gst_segment_init, function in GstSegment +
+
+
+gst_segment_is_equal, function in GstSegment +
+
+
+gst_segment_new, function in GstSegment +
+
+
+gst_segment_offset_running_time, function in GstSegment +
+
+
+gst_segment_position_from_running_time, function in GstSegment +
+
+
+gst_segment_position_from_running_time_full, function in GstSegment +
+
+
+gst_segment_position_from_stream_time, function in GstSegment +
+
+
+gst_segment_position_from_stream_time_full, function in GstSegment +
+
+
+gst_segment_set_running_time, function in GstSegment +
+
+
+gst_segment_to_position, function in GstSegment +
+
+
+gst_segment_to_running_time, function in GstSegment +
+
+
+gst_segment_to_running_time_full, function in GstSegment +
+
+
+gst_segment_to_stream_time, function in GstSegment +
+
+
+gst_segment_to_stream_time_full, function in GstSegment +
+
+
+gst_segtrap_is_enabled, function in Gst +
+
+
+gst_segtrap_set_enabled, function in Gst +
+
+
+GST_SEQNUM_INVALID, macro in GstUtils +
+
+
+GstStackTraceFlags, enum in GstInfo +
+
+
+GST_STATE, macro in GstElement +
+
+
+GstState, enum in GstElement +
+
+
+GstStateChange, enum in GstElement +
+
+
+GstStateChangeReturn, enum in GstElement +
+
+
+gst_state_change_get_name, function in GstElement +
+
+
+GST_STATE_GET_COND, macro in GstElement +
+
+
+GST_STATE_GET_LOCK, macro in GstElement +
+
+
+GST_STATE_GET_NEXT, macro in GstElement +
+
+
+GST_STATE_NEXT, macro in GstElement +
+
+
+GST_STATE_PENDING, macro in GstElement +
+
+
+GST_STATE_RETURN, macro in GstElement +
+
+
+GST_STATE_TARGET, macro in GstElement +
+
+
+GST_STATE_TRANSITION, macro in GstElement +
+
+
+GST_STATE_TRANSITION_CURRENT, macro in GstElement +
+
+
+GST_STATE_TRANSITION_NEXT, macro in GstElement +
+
+
+GstStaticCaps, struct in GstCaps +
+
+
+GstStaticPadTemplate, struct in GstPadTemplate +
+
+
+GST_STATIC_CAPS, macro in GstCaps +
+
+
+GST_STATIC_CAPS_ANY, macro in GstCaps +
+
+
+gst_static_caps_cleanup, function in GstCaps +
+
+
+gst_static_caps_get, function in GstCaps +
+
+
+GST_STATIC_CAPS_NONE, macro in GstCaps +
+
+
+GST_STATIC_PAD_TEMPLATE, macro in GstPadTemplate +
+
+
+gst_static_pad_template_get, function in GstPadTemplate +
+
+
+gst_static_pad_template_get_caps, function in GstPadTemplate +
+
+
+GST_STIME_ARGS, macro in GstInfo +
+
+
+GST_STIME_FORMAT, macro in GstInfo +
+
+
+GstStream, struct in GstStream +
+
+
+GstStreamClass, struct in GstStream +
+
+
+GstStreamCollection, struct in GstStreamCollection +
+
+
+GstStreamCollectionClass, struct in GstStreamCollection +
+
+
+GstStreamError, enum in GstGError +
+
+
+GstStreamFlags, enum in GstEvent +
+
+
+GstStreamStatusType, enum in GstMessage +
+
+
+GstStreamType, enum in GstStream +
+
+
+gst_stream_collection_add_stream, function in GstStreamCollection +
+
+
+gst_stream_collection_get_size, function in GstStreamCollection +
+
+
+gst_stream_collection_get_stream, function in GstStreamCollection +
+
+
+gst_stream_collection_get_upstream_id, function in GstStreamCollection +
+
+
+gst_stream_collection_new, function in GstStreamCollection +
+
+
+GST_STREAM_ERROR, macro in GstGError +
+
+
+gst_stream_get_caps, function in GstStream +
+
+
+gst_stream_get_stream_flags, function in GstStream +
+
+
+gst_stream_get_stream_id, function in GstStream +
+
+
+gst_stream_get_stream_type, function in GstStream +
+
+
+gst_stream_get_tags, function in GstStream +
+
+
+gst_stream_new, function in GstStream +
+
+
+gst_stream_set_caps, function in GstStream +
+
+
+gst_stream_set_stream_flags, function in GstStream +
+
+
+gst_stream_set_stream_type, function in GstStream +
+
+
+gst_stream_set_tags, function in GstStream +
+
+
+gst_stream_type_get_name, function in GstStream +
+
+
+GstStructure, struct in GstStructure +
+
+
+GstStructureChangeType, enum in GstMessage +
+
+
+GstStructureFilterMapFunc, user_function in GstStructure +
+
+
+GstStructureForeachFunc, user_function in GstStructure +
+
+
+GstStructureMapFunc, user_function in GstStructure +
+
+
+gst_structure_can_intersect, function in GstStructure +
+
+
+gst_structure_copy, function in GstStructure +
+
+
+gst_structure_filter_and_map_in_place, function in GstStructure +
+
+
+gst_structure_fixate, function in GstStructure +
+
+
+gst_structure_fixate_field, function in GstStructure +
+
+
+gst_structure_fixate_field_boolean, function in GstStructure +
+
+
+gst_structure_fixate_field_nearest_double, function in GstStructure +
+
+
+gst_structure_fixate_field_nearest_fraction, function in GstStructure +
+
+
+gst_structure_fixate_field_nearest_int, function in GstStructure +
+
+
+gst_structure_fixate_field_string, function in GstStructure +
+
+
+gst_structure_foreach, function in GstStructure +
+
+
+gst_structure_free, function in GstStructure +
+
+
+gst_structure_from_string, function in GstStructure +
+
+
+gst_structure_get, function in GstStructure +
+
+
+gst_structure_get_array, function in GstStructure +
+
+
+gst_structure_get_boolean, function in GstStructure +
+
+
+gst_structure_get_clock_time, function in GstStructure +
+
+
+gst_structure_get_date, function in GstStructure +
+
+
+gst_structure_get_date_time, function in GstStructure +
+
+
+gst_structure_get_double, function in GstStructure +
+
+
+gst_structure_get_enum, function in GstStructure +
+
+
+gst_structure_get_field_type, function in GstStructure +
+
+
+gst_structure_get_flagset, function in GstValue +
+
+
+gst_structure_get_fraction, function in GstStructure +
+
+
+gst_structure_get_int, function in GstStructure +
+
+
+gst_structure_get_int64, function in GstStructure +
+
+
+gst_structure_get_list, function in GstStructure +
+
+
+gst_structure_get_name, function in GstStructure +
+
+
+gst_structure_get_name_id, function in GstStructure +
+
+
+gst_structure_get_string, function in GstStructure +
+
+
+gst_structure_get_uint, function in GstStructure +
+
+
+gst_structure_get_uint64, function in GstStructure +
+
+
+gst_structure_get_valist, function in GstStructure +
+
+
+gst_structure_get_value, function in GstStructure +
+
+
+gst_structure_has_field, function in GstStructure +
+
+
+gst_structure_has_field_typed, function in GstStructure +
+
+
+gst_structure_has_name, function in GstStructure +
+
+
+gst_structure_id_get, function in GstStructure +
+
+
+gst_structure_id_get_valist, function in GstStructure +
+
+
+gst_structure_id_get_value, function in GstStructure +
+
+
+gst_structure_id_has_field, function in GstStructure +
+
+
+gst_structure_id_has_field_typed, function in GstStructure +
+
+
+gst_structure_id_set, function in GstStructure +
+
+
+gst_structure_id_set_valist, function in GstStructure +
+
+
+gst_structure_id_set_value, function in GstStructure +
+
+
+gst_structure_id_take_value, function in GstStructure +
+
+
+gst_structure_intersect, function in GstStructure +
+
+
+gst_structure_is_equal, function in GstStructure +
+
+
+gst_structure_is_subset, function in GstStructure +
+
+
+gst_structure_map_in_place, function in GstStructure +
+
+
+gst_structure_new, function in GstStructure +
+
+
+gst_structure_new_empty, function in GstStructure +
+
+
+gst_structure_new_from_string, function in GstStructure +
+
+
+gst_structure_new_id, function in GstStructure +
+
+
+gst_structure_new_id_empty, function in GstStructure +
+
+
+gst_structure_new_valist, function in GstStructure +
+
+
+gst_structure_nth_field_name, function in GstStructure +
+
+
+gst_structure_n_fields, function in GstStructure +
+
+
+gst_structure_remove_all_fields, function in GstStructure +
+
+
+gst_structure_remove_field, function in GstStructure +
+
+
+gst_structure_remove_fields, function in GstStructure +
+
+
+gst_structure_remove_fields_valist, function in GstStructure +
+
+
+gst_structure_set, function in GstStructure +
+
+
+gst_structure_set_array, function in GstStructure +
+
+
+gst_structure_set_list, function in GstStructure +
+
+
+gst_structure_set_name, function in GstStructure +
+
+
+gst_structure_set_parent_refcount, function in GstStructure +
+
+
+gst_structure_set_valist, function in GstStructure +
+
+
+gst_structure_set_value, function in GstStructure +
+
+
+gst_structure_take_value, function in GstStructure +
+
+
+gst_structure_to_string, function in GstStructure +
+
+
+GST_STR_FOURCC, macro in GstValue +
+
+
+GST_STR_NULL, macro in GstInfo +
+
+
+GstSystemClock, struct in GstSystemClock +
+
+
+GstSystemClock:clock-type, object property in GstSystemClock +
+
+
+gst_system_clock_obtain, function in GstSystemClock +
+
+
+gst_system_clock_set_default, function in GstSystemClock +
+
+

T

+
+GstTagFlag, enum in GstTagList +
+
+
+GstTagForeachFunc, user_function in GstTagList +
+
+
+GstTagList, struct in GstTagList +
+
+
+GstTagMergeFunc, user_function in GstTagList +
+
+
+GstTagMergeMode, enum in GstTagList +
+
+
+GstTagScope, enum in GstTagList +
+
+
+GstTagSetter, struct in GstTagSetter +
+
+
+GstTagSetterInterface, struct in GstTagSetter +
+
+
+GST_TAG_ALBUM, macro in GstTagList +
+
+
+GST_TAG_ALBUM_ARTIST, macro in GstTagList +
+
+
+GST_TAG_ALBUM_ARTIST_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_ALBUM_GAIN, macro in GstTagList +
+
+
+GST_TAG_ALBUM_PEAK, macro in GstTagList +
+
+
+GST_TAG_ALBUM_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_ALBUM_VOLUME_COUNT, macro in GstTagList +
+
+
+GST_TAG_ALBUM_VOLUME_NUMBER, macro in GstTagList +
+
+
+GST_TAG_APPLICATION_DATA, macro in GstTagList +
+
+
+GST_TAG_APPLICATION_NAME, macro in GstTagList +
+
+
+GST_TAG_ARTIST, macro in GstTagList +
+
+
+GST_TAG_ARTIST_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_ATTACHMENT, macro in GstTagList +
+
+
+GST_TAG_AUDIO_CODEC, macro in GstTagList +
+
+
+GST_TAG_BEATS_PER_MINUTE, macro in GstTagList +
+
+
+GST_TAG_BITRATE, macro in GstTagList +
+
+
+GST_TAG_CODEC, macro in GstTagList +
+
+
+GST_TAG_COMMENT, macro in GstTagList +
+
+
+GST_TAG_COMPOSER, macro in GstTagList +
+
+
+GST_TAG_COMPOSER_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_CONDUCTOR, macro in GstTagList +
+
+
+GST_TAG_CONTACT, macro in GstTagList +
+
+
+GST_TAG_CONTAINER_FORMAT, macro in GstTagList +
+
+
+GST_TAG_COPYRIGHT, macro in GstTagList +
+
+
+GST_TAG_COPYRIGHT_URI, macro in GstTagList +
+
+
+GST_TAG_DATE, macro in GstTagList +
+
+
+GST_TAG_DATE_TIME, macro in GstTagList +
+
+
+GST_TAG_DESCRIPTION, macro in GstTagList +
+
+
+GST_TAG_DEVICE_MANUFACTURER, macro in GstTagList +
+
+
+GST_TAG_DEVICE_MODEL, macro in GstTagList +
+
+
+GST_TAG_DURATION, macro in GstTagList +
+
+
+GST_TAG_ENCODED_BY, macro in GstTagList +
+
+
+GST_TAG_ENCODER, macro in GstTagList +
+
+
+GST_TAG_ENCODER_VERSION, macro in GstTagList +
+
+
+gst_tag_exists, function in GstTagList +
+
+
+GST_TAG_EXTENDED_COMMENT, macro in GstTagList +
+
+
+GST_TAG_GENRE, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_CITY, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_COUNTRY, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_ELEVATION, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_LATITUDE, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_LONGITUDE, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_NAME, macro in GstTagList +
+
+
+GST_TAG_GEO_LOCATION_SUBLOCATION, macro in GstTagList +
+
+
+gst_tag_get_description, function in GstTagList +
+
+
+gst_tag_get_flag, function in GstTagList +
+
+
+gst_tag_get_nick, function in GstTagList +
+
+
+gst_tag_get_type, function in GstTagList +
+
+
+GST_TAG_GROUPING, macro in GstTagList +
+
+
+GST_TAG_HOMEPAGE, macro in GstTagList +
+
+
+GST_TAG_IMAGE, macro in GstTagList +
+
+
+GST_TAG_IMAGE_ORIENTATION, macro in GstTagList +
+
+
+GST_TAG_INTERPRETED_BY, macro in GstTagList +
+
+
+GST_TAG_ISRC, macro in GstTagList +
+
+
+gst_tag_is_fixed, function in GstTagList +
+
+
+GST_TAG_KEYWORDS, macro in GstTagList +
+
+
+GST_TAG_LANGUAGE_CODE, macro in GstTagList +
+
+
+GST_TAG_LANGUAGE_NAME, macro in GstTagList +
+
+
+GST_TAG_LICENSE, macro in GstTagList +
+
+
+GST_TAG_LICENSE_URI, macro in GstTagList +
+
+
+gst_tag_list_add, function in GstTagList +
+
+
+gst_tag_list_add_valist, function in GstTagList +
+
+
+gst_tag_list_add_valist_values, function in GstTagList +
+
+
+gst_tag_list_add_value, function in GstTagList +
+
+
+gst_tag_list_add_values, function in GstTagList +
+
+
+gst_tag_list_copy, function in GstTagList +
+
+
+gst_tag_list_copy_value, function in GstTagList +
+
+
+gst_tag_list_foreach, function in GstTagList +
+
+
+gst_tag_list_free, macro in GstTagList +
+
+
+gst_tag_list_get_boolean, function in GstTagList +
+
+
+gst_tag_list_get_boolean_index, function in GstTagList +
+
+
+gst_tag_list_get_date, function in GstTagList +
+
+
+gst_tag_list_get_date_index, function in GstTagList +
+
+
+gst_tag_list_get_date_time, function in GstTagList +
+
+
+gst_tag_list_get_date_time_index, function in GstTagList +
+
+
+gst_tag_list_get_double, function in GstTagList +
+
+
+gst_tag_list_get_double_index, function in GstTagList +
+
+
+gst_tag_list_get_float, function in GstTagList +
+
+
+gst_tag_list_get_float_index, function in GstTagList +
+
+
+gst_tag_list_get_int, function in GstTagList +
+
+
+gst_tag_list_get_int64, function in GstTagList +
+
+
+gst_tag_list_get_int64_index, function in GstTagList +
+
+
+gst_tag_list_get_int_index, function in GstTagList +
+
+
+gst_tag_list_get_pointer, function in GstTagList +
+
+
+gst_tag_list_get_pointer_index, function in GstTagList +
+
+
+gst_tag_list_get_sample, function in GstTagList +
+
+
+gst_tag_list_get_sample_index, function in GstTagList +
+
+
+gst_tag_list_get_scope, function in GstTagList +
+
+
+gst_tag_list_get_string, function in GstTagList +
+
+
+gst_tag_list_get_string_index, function in GstTagList +
+
+
+gst_tag_list_get_tag_size, function in GstTagList +
+
+
+gst_tag_list_get_uint, function in GstTagList +
+
+
+gst_tag_list_get_uint64, function in GstTagList +
+
+
+gst_tag_list_get_uint64_index, function in GstTagList +
+
+
+gst_tag_list_get_uint_index, function in GstTagList +
+
+
+gst_tag_list_get_value_index, function in GstTagList +
+
+
+gst_tag_list_insert, function in GstTagList +
+
+
+gst_tag_list_is_empty, function in GstTagList +
+
+
+gst_tag_list_is_equal, function in GstTagList +
+
+
+gst_tag_list_is_writable, macro in GstTagList +
+
+
+gst_tag_list_make_writable, macro in GstTagList +
+
+
+gst_tag_list_merge, function in GstTagList +
+
+
+gst_tag_list_new, function in GstTagList +
+
+
+gst_tag_list_new_empty, function in GstTagList +
+
+
+gst_tag_list_new_from_string, function in GstTagList +
+
+
+gst_tag_list_new_valist, function in GstTagList +
+
+
+gst_tag_list_nth_tag_name, function in GstTagList +
+
+
+gst_tag_list_n_tags, function in GstTagList +
+
+
+gst_tag_list_peek_string_index, function in GstTagList +
+
+
+gst_tag_list_ref, function in GstTagList +
+
+
+gst_tag_list_remove_tag, function in GstTagList +
+
+
+gst_tag_list_set_scope, function in GstTagList +
+
+
+gst_tag_list_to_string, function in GstTagList +
+
+
+gst_tag_list_unref, function in GstTagList +
+
+
+GST_TAG_LOCATION, macro in GstTagList +
+
+
+GST_TAG_LYRICS, macro in GstTagList +
+
+
+GST_TAG_MAXIMUM_BITRATE, macro in GstTagList +
+
+
+gst_tag_merge_strings_with_comma, function in GstTagList +
+
+
+gst_tag_merge_use_first, function in GstTagList +
+
+
+GST_TAG_MIDI_BASE_NOTE, macro in GstTagList +
+
+
+GST_TAG_MINIMUM_BITRATE, macro in GstTagList +
+
+
+GST_TAG_NOMINAL_BITRATE, macro in GstTagList +
+
+
+GST_TAG_ORGANIZATION, macro in GstTagList +
+
+
+GST_TAG_PERFORMER, macro in GstTagList +
+
+
+GST_TAG_PREVIEW_IMAGE, macro in GstTagList +
+
+
+GST_TAG_PRIVATE_DATA, macro in GstTagList +
+
+
+GST_TAG_PUBLISHER, macro in GstTagList +
+
+
+GST_TAG_REFERENCE_LEVEL, macro in GstTagList +
+
+
+gst_tag_register, function in GstTagList +
+
+
+gst_tag_register_static, function in GstTagList +
+
+
+GST_TAG_SERIAL, macro in GstTagList +
+
+
+gst_tag_setter_add_tags, function in GstTagSetter +
+
+
+gst_tag_setter_add_tag_valist, function in GstTagSetter +
+
+
+gst_tag_setter_add_tag_valist_values, function in GstTagSetter +
+
+
+gst_tag_setter_add_tag_value, function in GstTagSetter +
+
+
+gst_tag_setter_add_tag_values, function in GstTagSetter +
+
+
+gst_tag_setter_get_tag_list, function in GstTagSetter +
+
+
+gst_tag_setter_get_tag_merge_mode, function in GstTagSetter +
+
+
+gst_tag_setter_merge_tags, function in GstTagSetter +
+
+
+gst_tag_setter_reset_tags, function in GstTagSetter +
+
+
+gst_tag_setter_set_tag_merge_mode, function in GstTagSetter +
+
+
+GST_TAG_SHOW_EPISODE_NUMBER, macro in GstTagList +
+
+
+GST_TAG_SHOW_NAME, macro in GstTagList +
+
+
+GST_TAG_SHOW_SEASON_NUMBER, macro in GstTagList +
+
+
+GST_TAG_SHOW_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_SUBTITLE_CODEC, macro in GstTagList +
+
+
+GST_TAG_TITLE, macro in GstTagList +
+
+
+GST_TAG_TITLE_SORTNAME, macro in GstTagList +
+
+
+GST_TAG_TRACK_COUNT, macro in GstTagList +
+
+
+GST_TAG_TRACK_GAIN, macro in GstTagList +
+
+
+GST_TAG_TRACK_NUMBER, macro in GstTagList +
+
+
+GST_TAG_TRACK_PEAK, macro in GstTagList +
+
+
+GST_TAG_USER_RATING, macro in GstTagList +
+
+
+GST_TAG_VERSION, macro in GstTagList +
+
+
+GST_TAG_VIDEO_CODEC, macro in GstTagList +
+
+
+GstTask, struct in GstTask +
+
+
+GstTaskFunction, user_function in GstTask +
+
+
+GstTaskPool, struct in GstTaskPool +
+
+
+GstTaskPoolClass, struct in GstTaskPool +
+
+
+GstTaskPoolFunction, user_function in GstTaskPool +
+
+
+GstTaskState, enum in GstTask +
+
+
+GstTaskThreadFunc, user_function in GstTask +
+
+
+GST_TASK_BROADCAST, macro in GstTask +
+
+
+gst_task_cleanup_all, function in GstTask +
+
+
+GST_TASK_GET_COND, macro in GstTask +
+
+
+GST_TASK_GET_LOCK, macro in GstTask +
+
+
+gst_task_get_pool, function in GstTask +
+
+
+gst_task_get_state, function in GstTask +
+
+
+gst_task_join, function in GstTask +
+
+
+gst_task_new, function in GstTask +
+
+
+gst_task_pause, function in GstTask +
+
+
+gst_task_pool_cleanup, function in GstTaskPool +
+
+
+gst_task_pool_join, function in GstTaskPool +
+
+
+gst_task_pool_new, function in GstTaskPool +
+
+
+gst_task_pool_prepare, function in GstTaskPool +
+
+
+gst_task_pool_push, function in GstTaskPool +
+
+
+gst_task_set_enter_callback, function in GstTask +
+
+
+gst_task_set_leave_callback, function in GstTask +
+
+
+gst_task_set_lock, function in GstTask +
+
+
+gst_task_set_pool, function in GstTask +
+
+
+gst_task_set_state, function in GstTask +
+
+
+GST_TASK_SIGNAL, macro in GstTask +
+
+
+gst_task_start, function in GstTask +
+
+
+GST_TASK_STATE, macro in GstTask +
+
+
+gst_task_stop, function in GstTask +
+
+
+GST_TASK_WAIT, macro in GstTask +
+
+
+GstTimedValue, struct in GstControlSource +
+
+
+GST_TIMESPEC_TO_TIME, macro in GstClock +
+
+
+GST_TIMEVAL_TO_TIME, macro in GstClock +
+
+
+GST_TIME_ARGS, macro in GstInfo +
+
+
+GST_TIME_AS_MSECONDS, macro in GstClock +
+
+
+GST_TIME_AS_NSECONDS, macro in GstClock +
+
+
+GST_TIME_AS_SECONDS, macro in GstClock +
+
+
+GST_TIME_AS_USECONDS, macro in GstClock +
+
+
+GST_TIME_FORMAT, macro in GstInfo +
+
+
+GST_TIME_TO_TIMESPEC, macro in GstClock +
+
+
+GST_TIME_TO_TIMEVAL, macro in GstClock +
+
+
+GstToc, struct in GstToc +
+
+
+GstTocEntry, struct in GstToc +
+
+
+GstTocEntryType, enum in GstToc +
+
+
+GstTocLoopType, enum in GstToc +
+
+
+GstTocScope, enum in GstToc +
+
+
+GstTocSetter, struct in GstTocSetter +
+
+
+GstTocSetterInterface, struct in GstTocSetter +
+
+
+gst_toc_append_entry, function in GstToc +
+
+
+gst_toc_copy, macro in GstToc +
+
+
+gst_toc_dump, function in GstToc +
+
+
+gst_toc_entry_append_sub_entry, function in GstToc +
+
+
+gst_toc_entry_copy, macro in GstToc +
+
+
+gst_toc_entry_get_entry_type, function in GstToc +
+
+
+gst_toc_entry_get_loop, function in GstToc +
+
+
+gst_toc_entry_get_parent, function in GstToc +
+
+
+gst_toc_entry_get_start_stop_times, function in GstToc +
+
+
+gst_toc_entry_get_sub_entries, function in GstToc +
+
+
+gst_toc_entry_get_tags, function in GstToc +
+
+
+gst_toc_entry_get_toc, function in GstToc +
+
+
+gst_toc_entry_get_uid, function in GstToc +
+
+
+gst_toc_entry_is_alternative, function in GstToc +
+
+
+gst_toc_entry_is_sequence, function in GstToc +
+
+
+gst_toc_entry_make_writable, macro in GstToc +
+
+
+gst_toc_entry_merge_tags, function in GstToc +
+
+
+gst_toc_entry_new, function in GstToc +
+
+
+gst_toc_entry_ref, macro in GstToc +
+
+
+gst_toc_entry_set_loop, function in GstToc +
+
+
+gst_toc_entry_set_start_stop_times, function in GstToc +
+
+
+gst_toc_entry_set_tags, function in GstToc +
+
+
+gst_toc_entry_type_get_nick, function in GstToc +
+
+
+GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE, macro in GstToc +
+
+
+GST_TOC_ENTRY_TYPE_IS_SEQUENCE, macro in GstToc +
+
+
+gst_toc_entry_unref, macro in GstToc +
+
+
+gst_toc_find_entry, function in GstToc +
+
+
+gst_toc_get_entries, function in GstToc +
+
+
+gst_toc_get_scope, function in GstToc +
+
+
+gst_toc_get_tags, function in GstToc +
+
+
+gst_toc_make_writable, macro in GstToc +
+
+
+gst_toc_merge_tags, function in GstToc +
+
+
+gst_toc_new, function in GstToc +
+
+
+gst_toc_ref, macro in GstToc +
+
+
+GST_TOC_REPEAT_COUNT_INFINITE, macro in GstToc +
+
+
+gst_toc_setter_get_toc, function in GstTocSetter +
+
+
+gst_toc_setter_reset, function in GstTocSetter +
+
+
+gst_toc_setter_set_toc, function in GstTocSetter +
+
+
+gst_toc_set_tags, function in GstToc +
+
+
+gst_toc_unref, macro in GstToc +
+
+
+GST_TRACE, macro in GstInfo +
+
+
+GstTracer, struct in GstTracer +
+
+
+GstTracer:params, object property in GstTracer +
+
+
+GstTracerFactory, struct in GstTracerFactory +
+
+
+GstTracerHookBinAddPost, user_function in GstTracer +
+
+
+GstTracerHookBinAddPre, user_function in GstTracer +
+
+
+GstTracerHookBinRemovePost, user_function in GstTracer +
+
+
+GstTracerHookBinRemovePre, user_function in GstTracer +
+
+
+GstTracerHookElementAddPad, user_function in GstTracer +
+
+
+GstTracerHookElementChangeStatePost, user_function in GstTracer +
+
+
+GstTracerHookElementChangeStatePre, user_function in GstTracer +
+
+
+GstTracerHookElementNew, user_function in GstTracer +
+
+
+GstTracerHookElementPostMessagePost, user_function in GstTracer +
+
+
+GstTracerHookElementPostMessagePre, user_function in GstTracer +
+
+
+GstTracerHookElementQueryPost, user_function in GstTracer +
+
+
+GstTracerHookElementQueryPre, user_function in GstTracer +
+
+
+GstTracerHookElementRemovePad, user_function in GstTracer +
+
+
+GstTracerHookMiniObjectCreated, user_function in GstTracer +
+
+
+GstTracerHookMiniObjectDestroyed, user_function in GstTracer +
+
+
+GstTracerHookMiniObjectReffed, user_function in GstTracer +
+
+
+GstTracerHookMiniObjectUnreffed, user_function in GstTracer +
+
+
+GstTracerHookObjectCreated, user_function in GstTracer +
+
+
+GstTracerHookObjectDestroyed, user_function in GstTracer +
+
+
+GstTracerHookObjectReffed, user_function in GstTracer +
+
+
+GstTracerHookObjectUnreffed, user_function in GstTracer +
+
+
+GstTracerHookPadLinkPost, user_function in GstTracer +
+
+
+GstTracerHookPadLinkPre, user_function in GstTracer +
+
+
+GstTracerHookPadPullRangePost, user_function in GstTracer +
+
+
+GstTracerHookPadPullRangePre, user_function in GstTracer +
+
+
+GstTracerHookPadPushEventPost, user_function in GstTracer +
+
+
+GstTracerHookPadPushEventPre, user_function in GstTracer +
+
+
+GstTracerHookPadPushListPost, user_function in GstTracer +
+
+
+GstTracerHookPadPushListPre, user_function in GstTracer +
+
+
+GstTracerHookPadPushPost, user_function in GstTracer +
+
+
+GstTracerHookPadPushPre, user_function in GstTracer +
+
+
+GstTracerHookPadQueryPost, user_function in GstTracer +
+
+
+GstTracerHookPadQueryPre, user_function in GstTracer +
+
+
+GstTracerHookPadUnlinkPost, user_function in GstTracer +
+
+
+GstTracerHookPadUnlinkPre, user_function in GstTracer +
+
+
+GstTracerRecord, struct in GstTracerRecord +
+
+
+GstTracerValueFlags, enum in GstTracerRecord +
+
+
+GstTracerValueScope, enum in GstTracerRecord +
+
+
+gst_tracer_factory_get_list, function in GstTracerFactory +
+
+
+gst_tracer_factory_get_tracer_type, function in GstTracerFactory +
+
+
+gst_tracer_record_log, function in GstTracerRecord +
+
+
+gst_tracer_record_new, function in GstTracerRecord +
+
+
+gst_tracer_register, function in GstTracer +
+
+
+GST_TRACE_OBJECT, macro in GstInfo +
+
+
+gst_tracing_register_hook, function in GstTracer +
+
+
+GstTypeFind, struct in GstTypeFind +
+
+
+GstTypeFindFactory, struct in GstTypeFindFactory +
+
+
+GstTypeFindFunction, user_function in GstTypeFind +
+
+
+GstTypeFindProbability, enum in GstTypeFind +
+
+
+GST_TYPE_ARRAY, macro in GstValue +
+
+
+GST_TYPE_BITMASK, macro in GstValue +
+
+
+GST_TYPE_DATE_TIME, macro in GstDateTime +
+
+
+GST_TYPE_DOUBLE_RANGE, macro in GstValue +
+
+
+gst_type_find_factory_call_function, function in GstTypeFindFactory +
+
+
+gst_type_find_factory_get_caps, function in GstTypeFindFactory +
+
+
+gst_type_find_factory_get_extensions, function in GstTypeFindFactory +
+
+
+gst_type_find_factory_get_list, function in GstTypeFindFactory +
+
+
+gst_type_find_factory_has_function, function in GstTypeFindFactory +
+
+
+gst_type_find_get_length, function in GstTypeFind +
+
+
+gst_type_find_peek, function in GstTypeFind +
+
+
+gst_type_find_register, function in GstTypeFind +
+
+
+gst_type_find_suggest, function in GstTypeFind +
+
+
+gst_type_find_suggest_simple, function in GstTypeFind +
+
+
+GST_TYPE_FLAG_SET, macro in GstValue +
+
+
+GST_TYPE_FRACTION, macro in GstValue +
+
+
+GST_TYPE_FRACTION_RANGE, macro in GstValue +
+
+
+GST_TYPE_INT64_RANGE, macro in GstValue +
+
+
+GST_TYPE_INT_RANGE, macro in GstValue +
+
+
+GST_TYPE_LIST, macro in GstValue +
+
+

U

+
+gst_update_registry, function in Gst +
+
+
+GstUri, struct in GstUri +
+
+
+GstURIError, enum in GstUriHandler +
+
+
+GstURIHandler, struct in GstUriHandler +
+
+
+GstURIHandlerInterface, struct in GstUriHandler +
+
+
+GstURIType, enum in GstUriHandler +
+
+
+gst_uri_append_path, function in GstUri +
+
+
+gst_uri_append_path_segment, function in GstUri +
+
+
+GST_URI_CAST, macro in GstUri +
+
+
+gst_uri_construct, function in GstUriHandler +
+
+
+GST_URI_CONST_CAST, macro in GstUri +
+
+
+gst_uri_copy, function in GstUri +
+
+
+gst_uri_equal, function in GstUri +
+
+
+gst_uri_error_quark, function in GstUriHandler +
+
+
+gst_uri_from_string, function in GstUri +
+
+
+gst_uri_from_string_with_base, function in GstUri +
+
+
+gst_uri_get_fragment, function in GstUri +
+
+
+gst_uri_get_host, function in GstUri +
+
+
+gst_uri_get_location, function in GstUriHandler +
+
+
+gst_uri_get_media_fragment_table, function in GstUri +
+
+
+gst_uri_get_path, function in GstUri +
+
+
+gst_uri_get_path_segments, function in GstUri +
+
+
+gst_uri_get_path_string, function in GstUri +
+
+
+gst_uri_get_port, function in GstUri +
+
+
+gst_uri_get_protocol, function in GstUriHandler +
+
+
+gst_uri_get_query_keys, function in GstUri +
+
+
+gst_uri_get_query_string, function in GstUri +
+
+
+gst_uri_get_query_table, function in GstUri +
+
+
+gst_uri_get_query_value, function in GstUri +
+
+
+gst_uri_get_scheme, function in GstUri +
+
+
+gst_uri_get_userinfo, function in GstUri +
+
+
+gst_uri_handler_get_protocols, function in GstUriHandler +
+
+
+gst_uri_handler_get_uri, function in GstUriHandler +
+
+
+gst_uri_handler_get_uri_type, function in GstUriHandler +
+
+
+gst_uri_handler_set_uri, function in GstUriHandler +
+
+
+gst_uri_has_protocol, function in GstUriHandler +
+
+
+gst_uri_is_normalized, function in GstUri +
+
+
+gst_uri_is_valid, function in GstUriHandler +
+
+
+gst_uri_is_writable, function in GstUri +
+
+
+gst_uri_join, function in GstUri +
+
+
+gst_uri_join_strings, function in GstUri +
+
+
+gst_uri_make_writable, function in GstUri +
+
+
+gst_uri_new, function in GstUri +
+
+
+gst_uri_new_with_base, function in GstUri +
+
+
+gst_uri_normalize, function in GstUri +
+
+
+GST_URI_NO_PORT, macro in GstUriHandler +
+
+
+gst_uri_protocol_is_supported, function in GstUriHandler +
+
+
+gst_uri_protocol_is_valid, function in GstUriHandler +
+
+
+gst_uri_query_has_key, function in GstUri +
+
+
+gst_uri_ref, function in GstUri +
+
+
+gst_uri_remove_query_key, function in GstUri +
+
+
+gst_uri_set_fragment, function in GstUri +
+
+
+gst_uri_set_host, function in GstUri +
+
+
+gst_uri_set_path, function in GstUri +
+
+
+gst_uri_set_path_segments, function in GstUri +
+
+
+gst_uri_set_path_string, function in GstUri +
+
+
+gst_uri_set_port, function in GstUri +
+
+
+gst_uri_set_query_string, function in GstUri +
+
+
+gst_uri_set_query_table, function in GstUri +
+
+
+gst_uri_set_query_value, function in GstUri +
+
+
+gst_uri_set_scheme, function in GstUri +
+
+
+gst_uri_set_userinfo, function in GstUri +
+
+
+gst_uri_to_string, function in GstUri +
+
+
+GST_URI_TYPE_IS_VALID, macro in GstUriHandler +
+
+
+gst_uri_unref, function in GstUri +
+
+
+GST_USECOND, macro in GstClock +
+
+
+gst_util_array_binary_search, function in GstUtils +
+
+
+gst_util_double_to_fraction, function in GstUtils +
+
+
+gst_util_dump_buffer, function in GstUtils +
+
+
+gst_util_dump_mem, function in GstUtils +
+
+
+gst_util_fraction_add, function in GstUtils +
+
+
+gst_util_fraction_compare, function in GstUtils +
+
+
+gst_util_fraction_multiply, function in GstUtils +
+
+
+gst_util_fraction_to_double, function in GstUtils +
+
+
+gst_util_get_object_array, function in GstUtils +
+
+
+gst_util_get_timestamp, function in GstUtils +
+
+
+gst_util_greatest_common_divisor, function in GstUtils +
+
+
+gst_util_greatest_common_divisor_int64, function in GstUtils +
+
+
+gst_util_group_id_next, function in GstUtils +
+
+
+gst_util_seqnum_compare, function in GstUtils +
+
+
+gst_util_seqnum_next, function in GstUtils +
+
+
+gst_util_set_object_arg, function in GstUtils +
+
+
+gst_util_set_object_array, function in GstUtils +
+
+
+gst_util_set_value_from_string, function in GstUtils +
+
+
+gst_util_uint64_scale, function in GstUtils +
+
+
+gst_util_uint64_scale_ceil, function in GstUtils +
+
+
+gst_util_uint64_scale_int, function in GstUtils +
+
+
+gst_util_uint64_scale_int_ceil, function in GstUtils +
+
+
+gst_util_uint64_scale_int_round, function in GstUtils +
+
+
+gst_util_uint64_scale_round, function in GstUtils +
+
+

V

+
+GstValueArray, struct in GstControlSource +
+
+
+GstValueCompareFunc, user_function in GstValue +
+
+
+GstValueDeserializeFunc, user_function in GstValue +
+
+
+GstValueSerializeFunc, user_function in GstValue +
+
+
+GstValueTable, struct in GstValue +
+
+
+gst_value_array_append_and_take_value, function in GstValue +
+
+
+gst_value_array_append_value, function in GstValue +
+
+
+gst_value_array_get_size, function in GstValue +
+
+
+gst_value_array_get_value, function in GstValue +
+
+
+gst_value_array_prepend_value, function in GstValue +
+
+
+gst_value_can_compare, function in GstValue +
+
+
+gst_value_can_intersect, function in GstValue +
+
+
+gst_value_can_subtract, function in GstValue +
+
+
+gst_value_can_union, function in GstValue +
+
+
+gst_value_compare, function in GstValue +
+
+
+gst_value_deserialize, function in GstValue +
+
+
+GST_VALUE_EQUAL, macro in GstValue +
+
+
+gst_value_fixate, function in GstValue +
+
+
+gst_value_fraction_multiply, function in GstValue +
+
+
+gst_value_fraction_subtract, function in GstValue +
+
+
+gst_value_get_bitmask, function in GstValue +
+
+
+gst_value_get_buffer, macro in GstValue +
+
+
+gst_value_get_caps, function in GstValue +
+
+
+gst_value_get_caps_features, function in GstValue +
+
+
+gst_value_get_double_range_max, function in GstValue +
+
+
+gst_value_get_double_range_min, function in GstValue +
+
+
+gst_value_get_flagset_flags, function in GstValue +
+
+
+gst_value_get_flagset_mask, function in GstValue +
+
+
+gst_value_get_fraction_denominator, function in GstValue +
+
+
+gst_value_get_fraction_numerator, function in GstValue +
+
+
+gst_value_get_fraction_range_max, function in GstValue +
+
+
+gst_value_get_fraction_range_min, function in GstValue +
+
+
+gst_value_get_int64_range_max, function in GstValue +
+
+
+gst_value_get_int64_range_min, function in GstValue +
+
+
+gst_value_get_int64_range_step, function in GstValue +
+
+
+gst_value_get_int_range_max, function in GstValue +
+
+
+gst_value_get_int_range_min, function in GstValue +
+
+
+gst_value_get_int_range_step, function in GstValue +
+
+
+gst_value_get_sample, macro in GstValue +
+
+
+gst_value_get_structure, function in GstValue +
+
+
+GST_VALUE_GREATER_THAN, macro in GstValue +
+
+
+GST_VALUE_HOLDS_ARRAY, macro in GstValue +
+
+
+GST_VALUE_HOLDS_BITMASK, macro in GstValue +
+
+
+GST_VALUE_HOLDS_BUFFER, macro in GstValue +
+
+
+GST_VALUE_HOLDS_CAPS, macro in GstValue +
+
+
+GST_VALUE_HOLDS_CAPS_FEATURES, macro in GstValue +
+
+
+GST_VALUE_HOLDS_DATE_TIME, macro in GstValue +
+
+
+GST_VALUE_HOLDS_DOUBLE_RANGE, macro in GstValue +
+
+
+GST_VALUE_HOLDS_FLAG_SET, macro in GstValue +
+
+
+GST_VALUE_HOLDS_FRACTION, macro in GstValue +
+
+
+GST_VALUE_HOLDS_FRACTION_RANGE, macro in GstValue +
+
+
+GST_VALUE_HOLDS_INT64_RANGE, macro in GstValue +
+
+
+GST_VALUE_HOLDS_INT_RANGE, macro in GstValue +
+
+
+GST_VALUE_HOLDS_LIST, macro in GstValue +
+
+
+GST_VALUE_HOLDS_SAMPLE, macro in GstValue +
+
+
+GST_VALUE_HOLDS_STRUCTURE, macro in GstValue +
+
+
+gst_value_init_and_copy, function in GstValue +
+
+
+gst_value_intersect, function in GstValue +
+
+
+gst_value_is_fixed, function in GstValue +
+
+
+gst_value_is_subset, function in GstValue +
+
+
+GST_VALUE_LESS_THAN, macro in GstValue +
+
+
+gst_value_list_append_and_take_value, function in GstValue +
+
+
+gst_value_list_append_value, function in GstValue +
+
+
+gst_value_list_concat, function in GstValue +
+
+
+gst_value_list_get_size, function in GstValue +
+
+
+gst_value_list_get_value, function in GstValue +
+
+
+gst_value_list_merge, function in GstValue +
+
+
+gst_value_list_prepend_value, function in GstValue +
+
+
+gst_value_register, function in GstValue +
+
+
+gst_value_serialize, function in GstValue +
+
+
+gst_value_set_bitmask, function in GstValue +
+
+
+gst_value_set_buffer, macro in GstValue +
+
+
+gst_value_set_caps, function in GstValue +
+
+
+gst_value_set_caps_features, function in GstValue +
+
+
+gst_value_set_double_range, function in GstValue +
+
+
+gst_value_set_flagset, function in GstValue +
+
+
+gst_value_set_fraction, function in GstValue +
+
+
+gst_value_set_fraction_range, function in GstValue +
+
+
+gst_value_set_fraction_range_full, function in GstValue +
+
+
+gst_value_set_int64_range, function in GstValue +
+
+
+gst_value_set_int64_range_step, function in GstValue +
+
+
+gst_value_set_int_range, function in GstValue +
+
+
+gst_value_set_int_range_step, function in GstValue +
+
+
+gst_value_set_sample, macro in GstValue +
+
+
+gst_value_set_structure, function in GstValue +
+
+
+gst_value_subtract, function in GstValue +
+
+
+gst_value_take_buffer, macro in GstValue +
+
+
+gst_value_take_sample, macro in GstValue +
+
+
+gst_value_union, function in GstValue +
+
+
+GST_VALUE_UNORDERED, macro in GstValue +
+
+
+gst_version, function in Gst +
+
+
+GST_VERSION_MAJOR, macro in GstVersion +
+
+
+GST_VERSION_MICRO, macro in GstVersion +
+
+
+GST_VERSION_MINOR, macro in GstVersion +
+
+
+GST_VERSION_NANO, macro in GstVersion +
+
+
+gst_version_string, function in Gst +
+
+

W

+
+GST_WARNING, macro in GstInfo +
+
+
+GST_WARNING_OBJECT, macro in GstInfo +
+
+
+GST_WRITE_DOUBLE_BE, function in GstUtils +
+
+
+GST_WRITE_DOUBLE_LE, function in GstUtils +
+
+
+GST_WRITE_FLOAT_BE, function in GstUtils +
+
+
+GST_WRITE_FLOAT_LE, function in GstUtils +
+
+
+GST_WRITE_UINT16_BE, macro in GstUtils +
+
+
+GST_WRITE_UINT16_LE, macro in GstUtils +
+
+
+GST_WRITE_UINT24_BE, macro in GstUtils +
+
+
+GST_WRITE_UINT24_LE, macro in GstUtils +
+
+
+GST_WRITE_UINT32_BE, macro in GstUtils +
+
+
+GST_WRITE_UINT32_LE, macro in GstUtils +
+
+
+GST_WRITE_UINT64_BE, macro in GstUtils +
+
+
+GST_WRITE_UINT64_LE, macro in GstUtils +
+
+
+GST_WRITE_UINT8, macro in GstUtils +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix02.html b/docs/gst/html/ix02.html new file mode 100644 index 0000000..b0596c5 --- /dev/null +++ b/docs/gst/html/ix02.html @@ -0,0 +1,62 @@ + + + + +Index of deprecated API: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of deprecated API

+

M

+
+GST_META_TAG_MEMORY, macro in GstMeta +
+
+

O

+
+gst_object_has_ancestor, function in GstObject +
+
+

S

+
+gst_segment_to_position, function in GstSegment +
+
+

T

+
+gst_tag_list_free, macro in GstTagList +
+
+

U

+
+gst_uri_construct, function in GstUriHandler +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix03.html b/docs/gst/html/ix03.html new file mode 100644 index 0000000..d09d311 --- /dev/null +++ b/docs/gst/html/ix03.html @@ -0,0 +1,222 @@ + + + + +Index of new API in 1.14: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.14

+

B

+
+gst_buffer_add_reference_timestamp_meta, function in GstBuffer +
+
+
+gst_buffer_get_n_meta, function in GstBuffer +
+
+
+gst_buffer_get_reference_timestamp_meta, function in GstBuffer +
+
+
+gst_buffer_list_calculate_size, function in GstBufferList +
+
+
+gst_buffer_list_get_writable, function in GstBufferList +
+
+
+gst_bus_get_pollfd, function in GstBus +
+
+

D

+
+gst_debug_add_ring_buffer_logger, function in GstInfo +
+
+
+gst_debug_remove_ring_buffer_logger, function in GstInfo +
+
+
+gst_debug_ring_buffer_logger_get_logs, function in GstInfo +
+
+
+gst_device_provider_get_metadata, function in GstDeviceProvider +
+
+

E

+
+GstElementForeachPadFunc, user_function in GstElement +
+
+
+gst_element_class_add_static_pad_template_with_gtype, function in GstElement +
+
+
+gst_element_foreach_pad, function in GstElement +
+
+
+gst_element_foreach_sink_pad, function in GstElement +
+
+
+gst_element_foreach_src_pad, function in GstElement +
+
+
+gst_element_get_metadata, function in GstElement +
+
+
+gst_element_get_pad_template, function in GstElement +
+
+
+gst_element_get_pad_template_list, function in GstElement +
+
+

G

+
+gst_get_main_executable_path, function in Gst +
+
+
+GST_GROUP_ID_INVALID, macro in GstUtils +
+
+

M

+
+gst_message_writable_structure, function in GstMessage +
+
+

P

+
+GstPadTemplate:gtype, object property in GstPadTemplate +
+
+
+GST_PAD_TEMPLATE_GTYPE, macro in GstPadTemplate +
+
+
+gst_pad_template_new_from_static_pad_template_with_gtype, function in GstPadTemplate +
+
+
+gst_param_spec_array, function in GstParamSpec +
+
+
+GstPromise, struct in GstPromise +
+
+
+GstPromiseChangeFunc, user_function in GstPromise +
+
+
+GstPromiseResult, enum in GstPromise +
+
+
+gst_promise_expire, function in GstPromise +
+
+
+gst_promise_get_reply, function in GstPromise +
+
+
+gst_promise_interrupt, function in GstPromise +
+
+
+gst_promise_new, function in GstPromise +
+
+
+gst_promise_new_with_change_func, function in GstPromise +
+
+
+gst_promise_ref, function in GstPromise +
+
+
+gst_promise_reply, function in GstPromise +
+
+
+gst_promise_unref, function in GstPromise +
+
+
+gst_promise_wait, function in GstPromise +
+
+
+gst_protection_filter_systems_by_available_decryptors, function in GstProtectionMeta +
+
+

R

+
+GstReferenceTimestampMeta, struct in GstBuffer +
+
+

S

+
+GST_SEQNUM_INVALID, macro in GstUtils +
+
+
+gst_state_change_get_name, function in GstElement +
+
+

U

+
+gst_util_dump_buffer, function in GstUtils +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix04.html b/docs/gst/html/ix04.html new file mode 100644 index 0000000..b07eec7 --- /dev/null +++ b/docs/gst/html/ix04.html @@ -0,0 +1,86 @@ + + + + +Index of new API in 1.12: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.12

+

B

+
+gst_buffer_iterate_meta_filtered, function in GstBuffer +
+
+

D

+
+gst_debug_get_stack_trace, function in GstInfo +
+
+

P

+
+gst_pad_get_task_state, function in GstPad +
+
+
+gst_print, function in GstInfo +
+
+
+gst_printerr, function in GstInfo +
+
+
+gst_printerrln, function in GstInfo +
+
+
+gst_println, function in GstInfo +
+
+

S

+
+GstStackTraceFlags, enum in GstInfo +
+
+

U

+
+gst_uri_get_media_fragment_table, function in GstUri +
+
+
+gst_util_get_object_array, function in GstUtils +
+
+
+gst_util_set_object_array, function in GstUtils +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix05.html b/docs/gst/html/ix05.html new file mode 100644 index 0000000..9bbc954 --- /dev/null +++ b/docs/gst/html/ix05.html @@ -0,0 +1,302 @@ + + + + +Index of new API in 1.10: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.10

+

B

+
+GstBin::deep-element-added, object signal in GstBin +
+
+
+GstBin::deep-element-removed, object signal in GstBin +
+
+
+gst_bin_get_suppressed_flags, function in GstBin +
+
+
+gst_bin_set_suppressed_flags, function in GstBin +
+
+
+gst_buffer_get_flags, function in GstBuffer +
+
+
+gst_buffer_set_flags, function in GstBuffer +
+
+
+gst_buffer_unset_flags, function in GstBuffer +
+
+

E

+
+gst_element_add_property_deep_notify_watch, function in GstElement +
+
+
+gst_element_add_property_notify_watch, function in GstElement +
+
+
+gst_element_call_async, function in GstElement +
+
+
+GST_ELEMENT_ERROR_WITH_DETAILS, macro in GstElement +
+
+
+GST_ELEMENT_FLOW_ERROR, macro in GstElement +
+
+
+GST_ELEMENT_INFO_WITH_DETAILS, macro in GstElement +
+
+
+gst_element_message_full_with_details, function in GstElement +
+
+
+gst_element_remove_property_notify_watch, function in GstElement +
+
+
+GST_ELEMENT_WARNING_WITH_DETAILS, macro in GstElement +
+
+
+gst_event_new_select_streams, function in GstEvent +
+
+
+gst_event_new_stream_collection, function in GstEvent +
+
+
+gst_event_new_stream_group_done, function in GstEvent +
+
+
+gst_event_parse_select_streams, function in GstEvent +
+
+
+gst_event_parse_stream, function in GstEvent +
+
+
+gst_event_parse_stream_collection, function in GstEvent +
+
+
+gst_event_parse_stream_group_done, function in GstEvent +
+
+
+gst_event_set_stream, function in GstEvent +
+
+

M

+
+gst_message_add_redirect_entry, function in GstMessage +
+
+
+gst_message_get_num_redirect_entries, function in GstMessage +
+
+
+gst_message_new_error_with_details, function in GstMessage +
+
+
+gst_message_new_info_with_details, function in GstMessage +
+
+
+gst_message_new_property_notify, function in GstMessage +
+
+
+gst_message_new_redirect, function in GstMessage +
+
+
+gst_message_new_streams_selected, function in GstMessage +
+
+
+gst_message_new_stream_collection, function in GstMessage +
+
+
+gst_message_new_warning_with_details, function in GstMessage +
+
+
+gst_message_parse_error_details, function in GstMessage +
+
+
+gst_message_parse_info_details, function in GstMessage +
+
+
+gst_message_parse_property_notify, function in GstMessage +
+
+
+gst_message_parse_redirect_entry, function in GstMessage +
+
+
+gst_message_parse_streams_selected, function in GstMessage +
+
+
+gst_message_parse_stream_collection, function in GstMessage +
+
+
+gst_message_parse_warning_details, function in GstMessage +
+
+
+gst_message_streams_selected_add, function in GstMessage +
+
+
+gst_message_streams_selected_get_size, function in GstMessage +
+
+
+gst_message_streams_selected_get_stream, function in GstMessage +
+
+

P

+
+gst_pad_get_stream, function in GstPad +
+
+
+gst_pad_link_maybe_ghosting, function in GstPad +
+
+
+gst_pad_link_maybe_ghosting_full, function in GstPad +
+
+

S

+
+GstStream, struct in GstStream +
+
+
+GstStreamCollection, struct in GstStreamCollection +
+
+
+GstStreamType, enum in GstStream +
+
+
+gst_stream_collection_add_stream, function in GstStreamCollection +
+
+
+gst_stream_collection_get_size, function in GstStreamCollection +
+
+
+gst_stream_collection_get_stream, function in GstStreamCollection +
+
+
+gst_stream_collection_get_upstream_id, function in GstStreamCollection +
+
+
+gst_stream_collection_new, function in GstStreamCollection +
+
+
+gst_stream_get_caps, function in GstStream +
+
+
+gst_stream_get_stream_flags, function in GstStream +
+
+
+gst_stream_get_stream_id, function in GstStream +
+
+
+gst_stream_get_stream_type, function in GstStream +
+
+
+gst_stream_get_tags, function in GstStream +
+
+
+gst_stream_new, function in GstStream +
+
+
+gst_stream_set_caps, function in GstStream +
+
+
+gst_stream_set_stream_flags, function in GstStream +
+
+
+gst_stream_set_stream_type, function in GstStream +
+
+
+gst_stream_set_tags, function in GstStream +
+
+
+gst_stream_type_get_name, function in GstStream +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix06.html b/docs/gst/html/ix06.html new file mode 100644 index 0000000..776b406 --- /dev/null +++ b/docs/gst/html/ix06.html @@ -0,0 +1,140 @@ + + + + +Index of new API in 1.8: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/gst/html/ix07.html b/docs/gst/html/ix07.html new file mode 100644 index 0000000..c3a81aa --- /dev/null +++ b/docs/gst/html/ix07.html @@ -0,0 +1,439 @@ + + + + +Index of new API in 1.6: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.6

+

B

+
+gst_bin_sync_children_states, function in GstBin +
+
+
+gst_buffer_add_parent_buffer_meta, function in GstBuffer +
+
+
+gst_buffer_add_protection_meta, function in GstProtectionMeta +
+
+
+gst_buffer_copy_deep, function in GstBuffer +
+
+
+gst_buffer_list_copy_deep, function in GstBufferList +
+
+
+gst_bus_remove_watch, function in GstBus +
+
+

C

+
+GstCapsForeachFunc, user_function in GstCaps +
+
+
+gst_caps_filter_and_map_in_place, function in GstCaps +
+
+
+gst_caps_foreach, function in GstCaps +
+
+
+gst_caps_map_in_place, function in GstCaps +
+
+
+GstClock::synced, object signal in GstClock +
+
+
+gst_clock_add_observation_unapplied, function in GstClock +
+
+
+gst_clock_adjust_with_calibration, function in GstClock +
+
+
+gst_clock_is_synced, function in GstClock +
+
+
+gst_clock_set_synced, function in GstClock +
+
+
+GST_CLOCK_STIME_IS_VALID, macro in GstClock +
+
+
+gst_clock_wait_for_sync, function in GstClock +
+
+

D

+
+gst_device_get_properties, function in GstDevice +
+
+
+gst_device_monitor_get_providers, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_show_all_devices, function in GstDeviceMonitor +
+
+
+gst_device_monitor_set_show_all_devices, function in GstDeviceMonitor +
+
+
+gst_device_provider_get_hidden_providers, function in GstDeviceMonitor +
+
+
+gst_device_provider_hide_provider, function in GstDeviceMonitor +
+
+
+gst_device_provider_unhide_provider, function in GstDeviceMonitor +
+
+

E

+
+gst_event_new_protection, function in GstEvent +
+
+
+gst_event_parse_protection, function in GstEvent +
+
+

F

+
+gst_flagset_register, function in GstValue +
+
+
+GST_FLAG_SET_MASK_EXACT, macro in GstValue +
+
+

L

+
+GST_LEVEL_MAX, macro in GstInfo +
+
+

O

+
+gst_object_has_as_parent, function in GstObject +
+
+

P

+
+GstPad:offset, object property in GstPad +
+
+
+GST_PAD_IS_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+GST_PAD_SET_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+GST_PAD_UNSET_ACCEPT_TEMPLATE, macro in GstPad +
+
+
+GstParentBufferMeta, struct in GstBuffer +
+
+
+GstPipeline:latency, object property in GstPipeline +
+
+
+gst_pipeline_get_latency, function in GstPipeline +
+
+
+gst_pipeline_get_pipeline_clock, function in GstPipeline +
+
+
+gst_pipeline_set_latency, function in GstPipeline +
+
+
+gst_preset_is_editable, function in GstPreset +
+
+
+GstProtectionMeta, struct in GstProtectionMeta +
+
+
+gst_protection_select_system, function in GstProtectionMeta +
+
+
+GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, macro in GstProtectionMeta +
+
+

S

+
+gst_sample_get_buffer_list, function in GstSample +
+
+
+gst_sample_set_buffer_list, function in GstSample +
+
+
+gst_segment_is_equal, function in GstSegment +
+
+
+gst_segment_to_running_time_full, function in GstSegment +
+
+
+GST_STIME_ARGS, macro in GstInfo +
+
+
+GST_STIME_FORMAT, macro in GstInfo +
+
+
+gst_structure_filter_and_map_in_place, function in GstStructure +
+
+
+gst_structure_get_flagset, function in GstValue +
+
+

T

+
+GST_TYPE_FLAG_SET, macro in GstValue +
+
+

U

+
+gst_uri_append_path, function in GstUri +
+
+
+gst_uri_append_path_segment, function in GstUri +
+
+
+gst_uri_equal, function in GstUri +
+
+
+gst_uri_from_string, function in GstUri +
+
+
+gst_uri_from_string_with_base, function in GstUri +
+
+
+gst_uri_get_fragment, function in GstUri +
+
+
+gst_uri_get_host, function in GstUri +
+
+
+gst_uri_get_path, function in GstUri +
+
+
+gst_uri_get_path_segments, function in GstUri +
+
+
+gst_uri_get_path_string, function in GstUri +
+
+
+gst_uri_get_port, function in GstUri +
+
+
+gst_uri_get_query_keys, function in GstUri +
+
+
+gst_uri_get_query_string, function in GstUri +
+
+
+gst_uri_get_query_table, function in GstUri +
+
+
+gst_uri_get_query_value, function in GstUri +
+
+
+gst_uri_get_userinfo, function in GstUri +
+
+
+gst_uri_is_normalized, function in GstUri +
+
+
+gst_uri_is_writable, function in GstUri +
+
+
+gst_uri_join, function in GstUri +
+
+
+gst_uri_join_strings, function in GstUri +
+
+
+gst_uri_make_writable, function in GstUri +
+
+
+gst_uri_new, function in GstUri +
+
+
+gst_uri_new_with_base, function in GstUri +
+
+
+gst_uri_normalize, function in GstUri +
+
+
+gst_uri_query_has_key, function in GstUri +
+
+
+gst_uri_remove_query_key, function in GstUri +
+
+
+gst_uri_set_fragment, function in GstUri +
+
+
+gst_uri_set_host, function in GstUri +
+
+
+gst_uri_set_path, function in GstUri +
+
+
+gst_uri_set_path_segments, function in GstUri +
+
+
+gst_uri_set_path_string, function in GstUri +
+
+
+gst_uri_set_port, function in GstUri +
+
+
+gst_uri_set_query_string, function in GstUri +
+
+
+gst_uri_set_query_table, function in GstUri +
+
+
+gst_uri_set_query_value, function in GstUri +
+
+
+gst_uri_set_scheme, function in GstUri +
+
+
+gst_uri_set_userinfo, function in GstUri +
+
+
+gst_uri_to_string, function in GstUri +
+
+

V

+
+gst_value_get_flagset_flags, function in GstValue +
+
+
+gst_value_get_flagset_mask, function in GstValue +
+
+
+GST_VALUE_HOLDS_FLAG_SET, macro in GstValue +
+
+
+gst_value_set_flagset, function in GstValue +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix08.html b/docs/gst/html/ix08.html new file mode 100644 index 0000000..a9d7e31 --- /dev/null +++ b/docs/gst/html/ix08.html @@ -0,0 +1,334 @@ + + + + +Index of new API in 1.4: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.4

+

B

+
+gst_buffer_is_all_memory_writable, function in GstBuffer +
+
+
+gst_buffer_is_memory_range_writable, function in GstBuffer +
+
+
+gst_buffer_pool_config_validate_params, function in GstBufferPool +
+
+
+gst_buffer_pool_set_flushing, function in GstBufferPool +
+
+

D

+
+GstDevice, struct in GstDevice +
+
+
+GstDeviceClass, struct in GstDevice +
+
+
+GstDeviceMonitor, struct in GstDeviceMonitor +
+
+
+GstDeviceMonitorClass, struct in GstDeviceMonitor +
+
+
+GstDeviceProvider, struct in GstDeviceProvider +
+
+
+GstDeviceProviderClass, struct in GstDeviceProvider +
+
+
+GstDeviceProviderFactory, struct in GstDeviceProviderFactory +
+
+
+GstDeviceProviderFactoryClass, struct in GstDeviceProviderFactory +
+
+
+gst_device_create_element, function in GstDevice +
+
+
+gst_device_get_caps, function in GstDevice +
+
+
+gst_device_get_device_class, function in GstDevice +
+
+
+gst_device_get_display_name, function in GstDevice +
+
+
+gst_device_has_classes, function in GstDevice +
+
+
+gst_device_has_classesv, function in GstDevice +
+
+
+gst_device_monitor_add_filter, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_bus, function in GstDeviceMonitor +
+
+
+gst_device_monitor_get_devices, function in GstDeviceMonitor +
+
+
+gst_device_monitor_new, function in GstDeviceMonitor +
+
+
+gst_device_monitor_remove_filter, function in GstDeviceMonitor +
+
+
+gst_device_monitor_start, function in GstDeviceMonitor +
+
+
+gst_device_monitor_stop, function in GstDeviceMonitor +
+
+
+gst_device_provider_class_add_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_add_static_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_get_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_set_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_class_set_static_metadata, function in GstDeviceProvider +
+
+
+gst_device_provider_device_add, function in GstDeviceProvider +
+
+
+gst_device_provider_device_remove, function in GstDeviceProvider +
+
+
+gst_device_provider_factory_find, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_by_name, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_device_provider_type, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_metadata, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_get_metadata_keys, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_has_classes, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_has_classesv, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_factory_list_get_device_providers, function in GstDeviceProviderFactory +
+
+
+gst_device_provider_get_bus, function in GstDeviceProvider +
+
+
+gst_device_provider_get_devices, function in GstDeviceProvider +
+
+
+gst_device_provider_get_factory, function in GstDeviceProvider +
+
+
+gst_device_provider_register, function in GstDeviceProvider +
+
+
+gst_device_provider_start, function in GstDeviceProvider +
+
+
+gst_device_provider_stop, function in GstDeviceProvider +
+
+
+gst_device_reconfigure_element, function in GstDevice +
+
+

E

+
+gst_event_get_running_time_offset, function in GstEvent +
+
+
+gst_event_set_running_time_offset, function in GstEvent +
+
+

M

+
+gst_message_new_device_added, function in GstMessage +
+
+
+gst_message_new_device_removed, function in GstMessage +
+
+
+gst_message_parse_device_added, function in GstMessage +
+
+
+gst_message_parse_device_removed, function in GstMessage +
+
+
+GST_MESSAGE_TYPE_IS_EXTENDED, macro in GstMessage +
+
+

P

+
+gst_pad_get_last_flow_return, function in GstPad +
+
+
+GST_PAD_LAST_FLOW_RETURN, macro in GstPad +
+
+
+gst_pad_link_get_name, function in GstPad +
+
+

Q

+
+gst_query_parse_uri_redirection_permanent, function in GstQuery +
+
+
+gst_query_set_uri_redirection_permanent, function in GstQuery +
+
+

R

+
+GST_ROUND_DOWN_128, macro in GstUtils +
+
+
+GST_ROUND_UP_128, macro in GstUtils +
+
+

S

+
+gst_structure_get_int64, function in GstStructure +
+
+
+gst_structure_get_uint64, function in GstStructure +
+
+
+gst_system_clock_set_default, function in GstSystemClock +
+
+

T

+
+GST_TAG_MIDI_BASE_NOTE, macro in GstTagList +
+
+
+GstTocLoopType, enum in GstToc +
+
+
+gst_toc_entry_get_loop, function in GstToc +
+
+
+gst_toc_entry_set_loop, function in GstToc +
+
+
+GST_TOC_REPEAT_COUNT_INFINITE, macro in GstToc +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix09.html b/docs/gst/html/ix09.html new file mode 100644 index 0000000..1b40793 --- /dev/null +++ b/docs/gst/html/ix09.html @@ -0,0 +1,34 @@ + + + + +Index of new API in 1.2.3: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.2.3

+

S

+
+gst_segment_offset_running_time, function in GstSegment +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix10.html b/docs/gst/html/ix10.html new file mode 100644 index 0000000..6860abd --- /dev/null +++ b/docs/gst/html/ix10.html @@ -0,0 +1,349 @@ + + + + +Index of new API in 1.2: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.2

+

B

+
+gst_buffer_get_max_memory, function in GstBuffer +
+
+

C

+
+gst_caps_append_structure_full, function in GstCaps +
+
+
+gst_caps_features_add, function in GstCapsFeatures +
+
+
+gst_caps_features_add_id, function in GstCapsFeatures +
+
+
+gst_caps_features_contains, function in GstCapsFeatures +
+
+
+gst_caps_features_contains_id, function in GstCapsFeatures +
+
+
+gst_caps_features_copy, function in GstCapsFeatures +
+
+
+gst_caps_features_free, function in GstCapsFeatures +
+
+
+gst_caps_features_from_string, function in GstCapsFeatures +
+
+
+gst_caps_features_get_nth, function in GstCapsFeatures +
+
+
+gst_caps_features_get_nth_id, function in GstCapsFeatures +
+
+
+gst_caps_features_get_size, function in GstCapsFeatures +
+
+
+gst_caps_features_is_any, function in GstCapsFeatures +
+
+
+gst_caps_features_is_equal, function in GstCapsFeatures +
+
+
+gst_caps_features_new, function in GstCapsFeatures +
+
+
+gst_caps_features_new_any, function in GstCapsFeatures +
+
+
+gst_caps_features_new_empty, function in GstCapsFeatures +
+
+
+gst_caps_features_new_id, function in GstCapsFeatures +
+
+
+gst_caps_features_new_id_valist, function in GstCapsFeatures +
+
+
+gst_caps_features_new_valist, function in GstCapsFeatures +
+
+
+gst_caps_features_remove, function in GstCapsFeatures +
+
+
+gst_caps_features_remove_id, function in GstCapsFeatures +
+
+
+gst_caps_features_set_parent_refcount, function in GstCapsFeatures +
+
+
+gst_caps_features_to_string, function in GstCapsFeatures +
+
+
+gst_caps_get_features, function in GstCaps +
+
+
+gst_caps_is_subset_structure_full, function in GstCaps +
+
+
+gst_caps_merge_structure_full, function in GstCaps +
+
+
+gst_caps_set_features, function in GstCaps +
+
+
+gst_context_get_context_type, function in GstContext +
+
+
+gst_context_get_structure, function in GstContext +
+
+
+gst_context_has_context_type, function in GstContext +
+
+
+gst_context_is_persistent, function in GstContext +
+
+
+gst_context_new, function in GstContext +
+
+
+gst_context_writable_structure, function in GstContext +
+
+

D

+
+gst_debug_get_color_mode, function in GstInfo +
+
+
+gst_debug_set_color_mode, function in GstInfo +
+
+
+gst_debug_set_color_mode_from_string, function in GstInfo +
+
+
+gst_debug_set_threshold_from_string, function in GstInfo +
+
+

E

+
+gst_event_parse_group_id, function in GstEvent +
+
+
+gst_event_parse_stream_flags, function in GstEvent +
+
+
+gst_event_set_group_id, function in GstEvent +
+
+
+gst_event_set_stream_flags, function in GstEvent +
+
+

M

+
+GST_MEMORY_IS_NOT_MAPPABLE, macro in GstMemory +
+
+
+GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS, macro in GstMemory +
+
+
+gst_memory_is_type, function in GstMemory +
+
+
+gst_message_new_have_context, function in GstMessage +
+
+
+gst_message_new_need_context, function in GstMessage +
+
+
+gst_message_parse_context_type, function in GstMessage +
+
+
+gst_message_parse_group_id, function in GstMessage +
+
+
+gst_message_parse_have_context, function in GstMessage +
+
+
+gst_message_set_group_id, function in GstMessage +
+
+
+gst_meta_api_type_get_tags, function in GstMeta +
+
+
+GST_META_TAG_MEMORY_STR, macro in GstMeta +
+
+

P

+
+gst_pad_get_stream_id, function in GstPad +
+
+
+gst_pad_store_sticky_event, function in GstPad +
+
+
+gst_plugin_feature_get_plugin_name, function in GstPluginFeature +
+
+
+GST_PLUGIN_STATIC_DECLARE, macro in GstPlugin +
+
+
+GST_PLUGIN_STATIC_REGISTER, macro in GstPlugin +
+
+

Q

+
+gst_query_new_context, function in GstQuery +
+
+
+gst_query_parse_context, function in GstQuery +
+
+
+gst_query_parse_context_type, function in GstQuery +
+
+
+gst_query_parse_uri_redirection, function in GstQuery +
+
+
+gst_query_remove_nth_allocation_param, function in GstQuery +
+
+
+gst_query_remove_nth_allocation_pool, function in GstQuery +
+
+
+gst_query_set_context, function in GstQuery +
+
+
+gst_query_set_uri_redirection, function in GstQuery +
+
+

S

+
+gst_sample_copy, function in GstSample +
+
+
+GstStreamFlags, enum in GstEvent +
+
+
+gst_structure_new_from_string, function in GstStructure +
+
+

T

+
+GST_TAG_INTERPRETED_BY, macro in GstTagList +
+
+
+GST_TAG_PUBLISHER, macro in GstTagList +
+
+

V

+
+gst_value_array_append_and_take_value, function in GstValue +
+
+
+gst_value_list_append_and_take_value, function in GstValue +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix11.html b/docs/gst/html/ix11.html new file mode 100644 index 0000000..acd8f75 --- /dev/null +++ b/docs/gst/html/ix11.html @@ -0,0 +1,34 @@ + + + + +Index of new API in 1.0.10: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.0.10

+

B

+
+gst_buffer_extract_dup, function in GstBuffer +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/ix12.html b/docs/gst/html/ix12.html new file mode 100644 index 0000000..ffda4e0 --- /dev/null +++ b/docs/gst/html/ix12.html @@ -0,0 +1,34 @@ + + + + +Index of new API in 1.0.5: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.0.5

+

B

+
+GST_BIN_IS_NO_RESYNC, macro in GstBin +
+
+
+ + + \ No newline at end of file diff --git a/docs/gst/html/left-insensitive.png b/docs/gst/html/left-insensitive.png new file mode 100644 index 0000000..6290738 Binary files /dev/null and b/docs/gst/html/left-insensitive.png differ diff --git a/docs/gst/html/left.png b/docs/gst/html/left.png new file mode 100644 index 0000000..d34a7bc Binary files /dev/null and b/docs/gst/html/left.png differ diff --git a/docs/gst/html/libgstreamer.html b/docs/gst/html/libgstreamer.html new file mode 100644 index 0000000..388682c --- /dev/null +++ b/docs/gst/html/libgstreamer.html @@ -0,0 +1,236 @@ + + + + +GStreamer Core Library: GStreamer 1.0 Core Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Core Library

+
+
+GStreamer — Media library supporting arbitrary formats and filter + graphs. +
+
+GstAllocator — allocate memory blocks +
+
+GstAtomicQueue — An atomic queue implementation +
+
+GstBin — Base class and element that can contain other elements +
+
+GstBuffer — Data-passing buffer type +
+
+GstBufferList — Lists of buffers for data-passing +
+
+GstBufferPool — Pool for buffers +
+
+GstBus — Asynchronous message bus subsystem +
+
+GstCaps — Structure describing sets of media formats +
+
+GstCapsFeatures — A set of features in caps +
+
+GstSample — A media sample +
+
+GstChildProxy — Interface for multi child elements. +
+
+GstClock — Abstract class for global clocks +
+
+GstConfig — Build configuration options +
+
+GstContext — Lightweight objects to represent element contexts +
+
+GstControlBinding — attachment for control source sources +
+
+GstControlSource — base class for control source sources +
+
+GstDateTime — A date, time and timezone structure +
+
+GstDynamicTypeFactory — Represents a registered dynamically loadable GType +
+
+GstElement — Abstract base class for all pipeline elements +
+
+GstElementFactory — Create GstElements from a factory +
+
+GstError — Categorized error messages +
+
+GstEvent — Structure describing events that are passed up and down + a pipeline +
+
+GstFormat — Dynamically register new data formats +
+
+GstGhostPad — Pseudo link pads +
+
+GstIterator — Object to retrieve multiple elements in a threadsafe +way. +
+
+GstMemory — refcounted wrapper for memory blocks +
+
+GstMessage — Lightweight objects to signal the application of + pipeline events +
+
+GstMeta — Buffer metadata +
+
+GstMiniObject — Lightweight base class for the GStreamer object hierarchy +
+
+GstObject — Base class for the GStreamer object hierarchy +
+
+GstPad — Object contained by elements that allows links to + other elements +
+
+GstPadTemplate — Describe the media type of a pad. +
+
+GstParamSpec — GParamSpec implementations specific +to GStreamer +
+
+GstParse — Get a pipeline from a text pipeline description +
+
+GstPipeline — Top-level bin with clocking and bus management + functionality. +
+
+GstPlugin — Container for features loaded from a shared object module +
+
+GstPluginfeature — Base class for contents of a GstPlugin +
+
+GstPoll — Keep track of file descriptors and make it possible + to wait on them in a cancellable way +
+
+GstPreset — helper interface for element presets +
+
+GstPromise — a miniobject for future/promise-like functionality +
+
+GstProtection — Functions and classes to support encrypted streams. +
+
+GstQuery — Provide functions to create queries, and to set and parse + values in them. +
+
+GstRegistry — Abstract base class for management of GstPlugin objects +
+
+GstSegment — Structure describing the configured region of interest + in a media file. +
+
+GstStreams — Base class for stream objects +
+
+GstStreamCollection — Base class for collection of streams +
+
+GstStructure — Generic structure containing fields of names and values +
+
+GstSystemClock — Default clock that uses the current system time +
+
+GstTagList — List of tags and values used to describe media metadata +
+
+GstTagsetter — Element interface that allows setting and retrieval + of media metadata +
+
+GstTask — Abstraction of GStreamer streaming threads. +
+
+GstTaskPool — Pool of GStreamer streaming threads +
+
+GstToc — Generic table of contents support +
+
+GstTocSetter — Element interface that allows setting and retrieval + of the TOC +
+
+GstTypefind — Stream type detection +
+
+GstTypeFindFactory — Information about registered typefind functions +
+
+GstUri — URI parsing and manipulation. +
+
+GstUriHandler — Interface to ease URI handling in plugins. +
+
+GstUtils — Various utility functions +
+
+GstValue — GValue implementations specific +to GStreamer +
+
+GstVersion — GStreamer version macros. +
+
+

+ libgstreamer-1.0.so provides all the core GStreamer services, + including initialization, plugin management and types, + as well as the object hierarchy that defines elements and bins, + along with some more specialized elements. +

+
+ + + \ No newline at end of file diff --git a/docs/gst/html/right-insensitive.png b/docs/gst/html/right-insensitive.png new file mode 100644 index 0000000..179725a Binary files /dev/null and b/docs/gst/html/right-insensitive.png differ diff --git a/docs/gst/html/right.png b/docs/gst/html/right.png new file mode 100644 index 0000000..bf5d8fa Binary files /dev/null and b/docs/gst/html/right.png differ diff --git a/docs/gst/html/style.css b/docs/gst/html/style.css new file mode 100644 index 0000000..3675420 --- /dev/null +++ b/docs/gst/html/style.css @@ -0,0 +1,479 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.3em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; + margin-top: 1em; + margin-bottom: 1em; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; + font-weight: bold; +} + +dl.toc > dl +{ + padding-bottom: 0.5em; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + /* these have a as a first child, but since there are no parent selectors + * we can't use that. */ + a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/docs/gst/html/up-insensitive.png b/docs/gst/html/up-insensitive.png new file mode 100644 index 0000000..5ee049e Binary files /dev/null and b/docs/gst/html/up-insensitive.png differ diff --git a/docs/gst/html/up.png b/docs/gst/html/up.png new file mode 100644 index 0000000..3a816d0 Binary files /dev/null and b/docs/gst/html/up.png differ diff --git a/docs/gst/meson.build b/docs/gst/meson.build new file mode 100644 index 0000000..b979823 --- /dev/null +++ b/docs/gst/meson.build @@ -0,0 +1,16 @@ +types = configure_file(input : 'gstreamer.types.in', + output : 'gstreamer.types', + configuration : configuration_data()) + +gnome.gtkdoc('gstreamer', + main_sgml : 'gstreamer-docs.sgml', + src_dir : '@0@/../../gst'.format(meson.current_source_dir()), + scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED', + '--ignore-decorators=GST_API', + '--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h' + ], + scanobjs_args : ['--type-init-func="gst_init(NULL,NULL)"'], + gobject_typesfile : types, + dependencies : [gst_dep], + content_files: ['building.xml', 'running.xml', version_entities], + install : true) diff --git a/docs/gst/running.xml b/docs/gst/running.xml new file mode 100644 index 0000000..9e4b3ef --- /dev/null +++ b/docs/gst/running.xml @@ -0,0 +1,559 @@ + + +%version-entities; + +]> + + +Running GStreamer Applications +3 +GStreamer Core + + + +Running GStreamer Applications + +How to run and debug your GStreamer application + + + + +Running and debugging GStreamer Applications + + +Environment variables + + +GStreamer inspects a few of environment variables in addition to standard +variables like LANG, PATH or HOME. + + + + <envar>GST_PLUGIN_SYSTEM_PATH</envar>, + <envar>GST_PLUGIN_SYSTEM_PATH_1_0</envar> + + + +This environment variable can be set to a colon-separated list of paths (or +semicolon-separated list on Windows). +If this variable is not set, GStreamer will fill in this list for you +with + + + +plug-ins in the user's home directory, or rather the user's "data home" +directory according to the xdg base dir specification. Usually this will be +a directory called +plugins inside the +.local/share/gstreamer-&GST_API_VERSION; directory in +the user's home directory by default, though this search path may change if +the XDG_DATA_HOME environment variable is set. + + + + +plug-ins installed system-wide. On this system, they are stored in +&GST_PLUGINS_DIR;. + + + + + + + +GStreamer will scan these paths for GStreamer plug-ins. These plug-ins will +be loaded after the plug-ins in the GST_PLUGIN_PATH variable below. + +The paths are scanned in the given order. This allows a user to override +system-installed plug-ins with his own versions. + + +The GST_PLUGIN_SYSTEM_PATH_1_0 variant is useful if both the old GStreamer 0.10 +version and the new GStreamer 1.0 version need to be pointed to new plugin +paths. The latter will use the _1_0 variant over the non-versioned one if +it is set. + + + +Setting this variable to an empty string will cause GStreamer not to scan any +system paths at all for plug-ins. This can be useful if you're running +uninstalled (for development purposes) or while running testsuites. + + + + + + <envar>GST_PLUGIN_PATH</envar>, <envar>GST_PLUGIN_PATH_1_0</envar> + + +This environment variable can be set to a colon-separated list of paths (or a +semicolon-separated list on Windows). +GStreamer will scan these paths for GStreamer plug-ins. These plug-ins will +be loaded in addition to, and before, the plug-ins in the system paths. + + +The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer 0.10 +version and the new GStreamer 1.0 version need to be pointed to new plugin +paths. The latter will use the _1_0 variant over the non-versioned one if +it is set. + + + + + <envar>GST_DEBUG</envar> + + +If GStreamer has been configured with , +this variable can be set to a list of debug options, which cause GStreamer +to print out different types of debugging information to stderr. + + +The variable takes a comma-separated list of "category_name:level" pairs +to set specific levels for the individual categories. +The level value ranges from 0 (nothing) to 9 (MEMDUMP). + + + + 1 - + + +Logs all fatal errors. These are errors that do not allow the core or elements +to perform the requested action. The application can still recover if +programmed to handle the conditions that triggered the error. + + + + + + 2 - + + +Logs all warnings. Typically these are non-fatal, but user-visible problems +are expected to happen. + + + + + + 3 - + + +Logs all fixme messages. Fixme messages are messages that indicate that something +in the executed code path is not fully implemented or handled yet. The purpose +of this message is to make it easier to spot incomplete/unfinished pieces of +code when reading the debug log. + + + + + + 4 - + + +Logs all informational messages. These are typically used for events in +the system that only happen once, or are important and rare enough to be +logged at this level. + + + + + + 5 - + + +Logs all debug messages. These are general debug messages for events +that happen only a limited number of times during an object's lifetime; +these include setup, teardown, change of parameters, ... + + + + + + 6 - + + +Logs all log messages. These are messages for events +that happen repeatedly during an object's lifetime; +these include streaming and steady-state conditions. + + + + + + 7 - + + +Logs all trace messages. These messages for events +that happen repeatedly during an object's lifetime such as the +ref/unref cycles. + + + + + + 9 - + + +Log all memory dump messages. Memory dump messages are used to log +(small) chunks of data as memory dumps in the log. They will be displayed +as hexdump with ASCII characters. + + + + + + The category_name can contain " as a wildcard. + + + +For example, setting GST_DEBUG to +, will cause the + category to be logged at full + level, while all categories starting with + will be logged at level. + + + +To get all possible debug output, set +GST_DEBUG +to . For debugging purposes a debug +log is usually the most useful, as it contains all important information, but +hides a lot of noise such as refs/unrefs. For bug reporting purposes, a + log is also what will be requested usually. It's often +also worth running with to see if there are any +non-fatal errors or warnings that might be related to the problem at hand. + + + +Since GStreamer 1.2 it is also possible to specify debug levels by name, +e.g. GST_DEBUG=*:WARNING,*audio*:LOG + + + + + + <envar>GST_DEBUG_NO_COLOR</envar> + + +Set this environment variable to any value ("1" typically) to switch off +colouring in GST_DEBUG output. This has the same effect as specifying the + or +=off command line option to +well-behaved GStreamer applications (ie. those that pass command-line +options correctly to GStreamer). +This is particularly useful to reduce the size of debug output and also allows +for the output to be compressed much better than with colours turned on. + + +Has the same effect as setting GST_DEBUG_COLOR_MODE environment variable to +"off". + + + + + + <envar>GST_DEBUG_COLOR_MODE</envar> + + +Set this environment variable to change log colouring in GST_DEBUG output. +Possible values: + + + + + + +Enables debug log output coloring. Uses default coloring method for current +platform. This is the default. + + + + + + + + +Disables debug log output coloring. This has the same effect as specifying the +=off command line option to +well-behaved GStreamer applications (ie. those that pass command-line +options correctly to GStreamer). +This is particularly useful to reduce the size of debug output and also allows +for the output to be compressed much better than with colours turned on. + + +Has the same effect as setting GST_DEBUG_NO_COLOR environment variable to +any value. + + + + + + + + +Same as . + + + + + + + + +Same as . + + + + + + + + +Enables debug log output coloring and forces the use of UNIX termial codes +for coloring, even if this method is not normally used on current platform. +This has the same effect as specifying the +=unix command line option to +well-behaved GStreamer applications (ie. those that pass command-line options +correctly to GStreamer). +This is particularly useful to dump debug output into a file on non-UNIX +platforms to be sent to developers who have viewers that support UNIX terminal +codes. + + + + + + + + + + + <envar>GST_DEBUG_OPTIONS</envar> + + +This environment variable can be used to tweak the behaviour of the debugging +system. Currently the only options supported are "pretty-tags" and "full-tags". +In "pretty-tags" mode (the default), taglists in the debug log will be +serialized so that only the first few and last few bytes of a buffer-type tag +will be serialized into the log, to avoid dumping hundreds of lines of useless +output into the log in case of large image tags and the like. + + + + + + <envar>GST_DEBUG_DUMP_DOT_DIR</envar> + + +Set this environment variable to a path to turn on all +#GST_DEBUG_BIN_TO_DOT_FILE or #GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS calls +and have the dot files in that location. + + +This will only work if the application in question makes these calls in +strategic places (like when the pipeline state changes or an error occurs). +gst-launch-&GST_API_VERSION; is one such application. + + +When gst-launch-&GST_API_VERSION; changes state through NULL to PLAYING +and back to NULL, a dot file is generated on each state change. To have +gst-launch-&GST_API_VERSION; write a snapshot of the pipeline state, send +a SIGHUP to the gst-launch-&GST_API_VERSION; process. + + +These .dot files can then be turned into images using the 'dot' utility +from the graphviz set of tools, like this: + dot foo.dot -Tsvg -o foo.svg or + dot foo.dot -Tpng -o foo.png or + dot foo.dot -Tjpg -o foo.jpg. + + +There is also a utility called xdot which allows you to +view the dot file directly without converting it first. + + + + + + + <envar>GST_REGISTRY</envar>, <envar>GST_REGISTRY_1_0</envar> + + +Set this environment variable to make GStreamer use a different file for the +plugin cache / registry than the default one. This is useful when operating +in a separate environment which should not affect the default cache in the +user's home directory. + + + + + + <envar>GST_REGISTRY_FORK</envar> + + +Set this environment variable to "no" to prevent GStreamer from forking on +startup in order to update the plugin registry. This is useful for debugging +purposes, but should not be used under normal circumstances, since it means +that plugins may be loaded into memory even if they are not needed by the +application. + + + + + + <envar>GST_REGISTRY_UPDATE</envar> + + +Set this environment variable to "no" to prevent GStreamer from updating the +plugin registry. This is useful for embedded device which is not updating the +plugins frequently, it will save time when doing gst_init(). + + + + + + <envar>GST_TRACE</envar> + + + Enable memory allocation tracing. Most GStreamer objects have support for + tracing the number of unfreed objects and their memory pointers. + + +The variable takes a comma-separated list of tracing options to enable. + + + + live + + + Counts all live objects and dumps an overview of the number of unfreed + objects at program exit. + + + + + + mem-live + + + Keep track of the unfreed memory pointers and dump an overview of all unfreed + memory at program exit. Together with a level 9 debug log this can be used to + follow the lifecycle of leaked objects in order to track down where they are + leaked. This can be useful for debugging memory leaks in situations where + tools such as valgrind are not available, or not an option. + + + + + + Use to enable all tracing flags. + + + + + <envar>GST_DEBUG_FILE</envar> + + + Set this variable to a file path to redirect all GStreamer debug + messages to this file. If left unset, debug messages with be output + unto the standard error. + + + + + + <envar>ORC_CODE</envar> + + +Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers +such as gdb to create useful backtraces from Orc-generated code. Set +ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code +generator is producing incorrect code (Quite a few important +GStreamer plugins like videotestsrc, audioconvert or audioresample use Orc). +One can also combine flags like ORC_CODE=backup,debug. + + + + + + <envar>G_DEBUG</envar> + + +Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make +GStreamer programs abort when a critical warning such as an assertion failure +occurs. This is useful if you want to find out which part of the code caused +that warning to be triggered and under what circumstances. Simply set G_DEBUG +as mentioned above and run the program in gdb (or let it core dump). Then get +a stack trace in the usual way. + + + + + + <envar>G_SLICE</envar> + + +Useful GLib environment variable. Set G_SLICE=always-malloc when running +GStreamer programs in valgrind, or debugging memory leaks with other tools. +See the GLib API reference for more details. + + + + + + <envar>GST_TAG_ENCODING</envar> + +Try this character encoding first for tag-related strings where the encoding +is not defined and which are not UTF-8 already. By default the current locale +will be tried (if not UTF-8). + + + + + <envar>GST_TAG_ID3_ENCODING</envar> + +Try this character encoding first for ID3 tag-related strings where the +encoding is not defined and which are not UTF-8 already. By default the current +locale will be tried (if not UTF-8). + + + + + <envar>GST_TAG_ID3V1_ENCODING</envar> + +Try this character encoding first for ID3v1 tag-related strings where the +encoding does not look like UTF-8. + + + + + <envar>GST_GL_WINDOW</envar> + +Influences the window system to use by the GStreamer OpenGL library. +Common values are 'x11', 'wayland', 'win32' or 'cocoa'. + + + + + <envar>GST_GL_PLATFORM</envar> + +Influences the OpenGL platform to use by the GStreamer OpenGL library. +Common values are 'egl', 'glx', 'wgl' or 'cgl'. + + + + + <envar>GST_GL_API</envar> + +Influences the OpenGL API requested by the OpenGL platform. +Common values are 'opengl' or 'gles2'. + + + + + + + + diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am new file mode 100644 index 0000000..f9c7c7d --- /dev/null +++ b/docs/libs/Makefile.am @@ -0,0 +1,79 @@ +## Process this file with automake to produce Makefile.in + +# The name of the module, e.g. 'glib'. +#DOC_MODULE=gstreamer-libs-@GST_API_VERSION@ +DOC_MODULE=gstreamer-libs + +# don't want $(DOC_MODULE)-scan.c to be built with -Werror +ERROR_CFLAGS= + +# for upload-doc.mak +DOC=gstreamer-libs +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR=$(top_srcdir)/libs/gst + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED" \ + --ignore-decorators="GST_API|GST_BASE_API|GST_CHECK_API|GST_CONTROLLER_API|GST_NET_API" + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode --output-format=xml --ignore-files="$(IGNORE_HFILES)" + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/gst/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(datadir)/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(top_srcdir)/libs/gst/*/*.h +CFILE_GLOB=$(top_srcdir)/libs/gst/*/*.c + +# Extra options to pass to gtkdoc-scanobj or gtkdoc-scangobj. +SCANOBJ_OPTIONS=--type-init-func="gst_init(&argc,&argv)" + +# Header files to ignore when scanning. +IGNORE_HFILES = \ + check/libcheck internal-check.h \ + gstinterpolationcontrolsourceprivate.h \ + gstlfocontrolsourceprivate.h \ + gstgetbits_inl.h \ + gstindex.h \ + dp-private.h \ + gstntppacket.h + +# Images to copy into HTML directory. +HTML_IMAGES = gdp-header.png + +# 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 = -I$(top_builddir) -I$(top_builddir)/libs $(GST_OBJ_CFLAGS) +GTKDOC_LIBS = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +GTKDOC_EXTRA_ENVIRONMENT= \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt + +include $(top_srcdir)/common/gtk-doc.mak diff --git a/docs/libs/Makefile.in b/docs/libs/Makefile.in new file mode 100644 index 0000000..206754d --- /dev/null +++ b/docs/libs/Makefile.in @@ -0,0 +1,1019 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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 + +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = docs/libs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/common/gtk-doc.mak \ + $(top_srcdir)/common/upload-doc.mak +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ + +# don't want $(DOC_MODULE)-scan.c to be built with -Werror +ERROR_CFLAGS = +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# The name of the module, e.g. 'glib'. +#DOC_MODULE=gstreamer-libs-@GST_API_VERSION@ +DOC_MODULE = gstreamer-libs + +# for upload-doc.mak +DOC = gstreamer-libs +FORMATS = html + +# 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) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml + +# The directory containing the source code. +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir)/libs/gst + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS = --deprecated-guards="GST_DISABLE_DEPRECATED" \ + --ignore-decorators="GST_API|GST_BASE_API|GST_CHECK_API|GST_CONTROLLER_API|GST_NET_API" + + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --sgml-mode --output-format=xml --ignore-files="$(IGNORE_HFILES)" + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS = --extra-dir=$(top_builddir)/docs/gst/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(datadir)/gtk-doc/html + + +# Used for dependencies. +HFILE_GLOB = $(top_srcdir)/libs/gst/*/*.h +CFILE_GLOB = $(top_srcdir)/libs/gst/*/*.c + +# Extra options to pass to gtkdoc-scanobj or gtkdoc-scangobj. +SCANOBJ_OPTIONS = --type-init-func="gst_init(&argc,&argv)" + +# Header files to ignore when scanning. +IGNORE_HFILES = \ + check/libcheck internal-check.h \ + gstinterpolationcontrolsourceprivate.h \ + gstlfocontrolsourceprivate.h \ + gstgetbits_inl.h \ + gstindex.h \ + dp-private.h \ + gstntppacket.h + + +# Images to copy into HTML directory. +HTML_IMAGES = gdp-header.png + +# 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 = -I$(top_builddir) -I$(top_builddir)/libs $(GST_OBJ_CFLAGS) +GTKDOC_LIBS = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +GTKDOC_EXTRA_ENVIRONMENT = \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute + +# 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_API_VERSION@ +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 \ + 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 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/libs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/libs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-local + +.PRECIOUS: Makefile + +html: html-build.stamp + +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 X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(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; \ + \ + 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 + +@ENABLE_GTK_DOC_TRUE@all-local: html-build.stamp + +#### setup #### + +@ENABLE_GTK_DOC_TRUE@setup-build.stamp: $(content_files) +@ENABLE_GTK_DOC_TRUE@ -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ +@ENABLE_GTK_DOC_TRUE@ echo ' DOC Preparing build'; \ +@ENABLE_GTK_DOC_TRUE@ files=`echo $(DOC_MAIN_SGML_FILE) $(DOC_OVERRIDES) $(DOC_MODULE)-sections.txt $(DOC_MODULE).types $(content_files)`; \ +@ENABLE_GTK_DOC_TRUE@ if test "x$$files" != "x" ; then \ +@ENABLE_GTK_DOC_TRUE@ for file in $$files ; do \ +@ENABLE_GTK_DOC_TRUE@ test -f $(abs_srcdir)/$$file && \ +@ENABLE_GTK_DOC_TRUE@ cp -pu $(abs_srcdir)/$$file $(abs_builddir)/ || true; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch setup-build.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 +@ENABLE_GTK_DOC_TRUE@scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Scanning header files' +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scan \ +@ENABLE_GTK_DOC_TRUE@ $(SCAN_OPTIONS) $(EXTRA_HFILES) \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $${_source_dir} \ +@ENABLE_GTK_DOC_TRUE@ --ignore-headers="$(IGNORE_HFILES)" +@ENABLE_GTK_DOC_TRUE@ @if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; then \ +@ENABLE_GTK_DOC_TRUE@ echo " DOC Introspecting gobjects"; \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$$?" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options="--verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0=`cd $(top_builddir) && pwd` \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_PATH_1_0= \ +@ENABLE_GTK_DOC_TRUE@ GST_REGISTRY_1_0=doc-registry.xml \ +@ENABLE_GTK_DOC_TRUE@ $(GTKDOC_EXTRA_ENVIRONMENT) \ +@ENABLE_GTK_DOC_TRUE@ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" \ +@ENABLE_GTK_DOC_TRUE@ CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ +@ENABLE_GTK_DOC_TRUE@ $$scanobj_options --module=$(DOC_MODULE) ; \ +@ENABLE_GTK_DOC_TRUE@ else \ +@ENABLE_GTK_DOC_TRUE@ for i in $(SCANOBJ_FILES) ; do \ +@ENABLE_GTK_DOC_TRUE@ $(MKDIR_P) $(dirname $$i) ; \ +@ENABLE_GTK_DOC_TRUE@ test -f $$i || touch $$i ; \ +@ENABLE_GTK_DOC_TRUE@ done \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @touch scan-build.stamp + +@ENABLE_GTK_DOC_TRUE@$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### xml #### + +@ENABLE_GTK_DOC_TRUE@sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building XML' +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkdb --module=$(DOC_MODULE) $${_source_dir} --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities xml +@ENABLE_GTK_DOC_TRUE@ @touch sgml-build.stamp + +@ENABLE_GTK_DOC_TRUE@sgml.stamp: sgml-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### html #### + +@ENABLE_GTK_DOC_TRUE@html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building HTML' +@ENABLE_GTK_DOC_TRUE@ @rm -rf html +@ENABLE_GTK_DOC_TRUE@ @mkdir html +@ENABLE_GTK_DOC_TRUE@ @cp -pr xml html +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities ./ +@ENABLE_GTK_DOC_TRUE@ @mkhtml_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options="$$mkhtml_options --verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options=--path="$(abs_srcdir)"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE)-@GST_API_VERSION@ ../$(DOC_MAIN_SGML_FILE) +@ENABLE_GTK_DOC_TRUE@ @rm -rf html/xml +@ENABLE_GTK_DOC_TRUE@ @rm -f version.entities +@ENABLE_GTK_DOC_TRUE@ @test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Fixing cross-references' +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @touch html-build.stamp + +@ENABLE_GTK_DOC_TRUE@clean-local-gtkdoc: +@ENABLE_GTK_DOC_TRUE@ @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ rm -rf $(DOC_MODULE).types; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_FALSE@all-local: +@ENABLE_GTK_DOC_FALSE@clean-local-gtkdoc: + +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_MAIN_SGML_FILE) ; \ + rm -f $(DOC_OVERRIDES) ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -f $(content_files) ; \ + 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)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(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 +# +@ENABLE_GTK_DOC_TRUE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@ @echo "*** gtk-doc must be installed and enabled in order to make dist" +@ENABLE_GTK_DOC_FALSE@ @false + +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: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/libs/gdp-header.png b/docs/libs/gdp-header.png new file mode 100644 index 0000000..d7d08f6 Binary files /dev/null and b/docs/libs/gdp-header.png differ diff --git a/docs/libs/gstreamer-libs-docs.sgml b/docs/libs/gstreamer-libs-docs.sgml new file mode 100644 index 0000000..07295b3 --- /dev/null +++ b/docs/libs/gstreamer-libs-docs.sgml @@ -0,0 +1,154 @@ + + +%version-entities; + + +]> + + + GStreamer &GST_API_VERSION; Library Reference Manual + + for GStreamer Library &GST_API_VERSION; (&GST_VERSION;) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/. + + + + GStreamer Libraries + + + To ease the creation of plugins, a library system was created. The most common + functions for a plugin can be found in a library. + + + GStreamer provides some standard libraries you can use to create plugins. + + + + GStreamer Base and Utillity Classes + + libgstbase-&GST_API_VERSION;.so provides some base classes to be extended + by elements and utillity classes that are most useful for plugin developers. + + + + + + + + + + + + + + + + + + + + + + + + GStreamer Dynamic Parameter Control + + libgstcontroller-&GST_API_VERSION;.so provides functionality to animate + element properties over time. + + + + + + + + + + + + + + GStreamer Network Classes + + libgstnet-&GST_API_VERSION;.so provides network elements and objects. + + + + + + + + + + + + GStreamer Check Unit Testing + + libgstcheck-&GST_API_VERSION;.so provides functionality for writing + unit tests that use the check framework. + + + + + + + + + + + + Object Hierarchy + + + + + API Index + + + + Index of deprecated API + + + + Index of new API in 1.14 + + + + Index of new API in 1.12.1 + + + + Index of new API in 1.12 + + + + Index of new API in 1.10 + + + + Index of new API in 1.8 + + + + Index of new API in 1.6 + + + + Index of new API in 1.4 + + + + Index of new API in 1.2 + + + + Index of new API in 1.0.1 + + + + + + diff --git a/docs/libs/gstreamer-libs-overrides.txt b/docs/libs/gstreamer-libs-overrides.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/libs/gstreamer-libs-overrides.txt diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt new file mode 100644 index 0000000..f5b22b3 --- /dev/null +++ b/docs/libs/gstreamer-libs-sections.txt @@ -0,0 +1,1441 @@ +# GStreamer Libraries API reference sections + +## please add sections in alphabetical order using the following template +# leave two empty lines between sections +#
+# gstxxx +# GstXxx +# typedefs +# macros +# constructor +# methods +# +# +#
+ +# control binding classes + +
+gstargbcontrolbinding +GstARGBControlBinding +libs/controller/controller.h +gst_argb_control_binding_new + +GstARGBControlBinding +GstARGBControlBindingClass +GST_ARGB_CONTROL_BINDING +GST_ARGB_CONTROL_BINDING_CLASS +GST_ARGB_CONTROL_BINDING_GET_CLASS +GST_IS_ARGB_CONTROL_BINDING +GST_IS_ARGB_CONTROL_BINDING_CLASS +GST_TYPE_ARGB_CONTROL_BINDING +gst_argb_control_binding_get_type +
+ +
+gstdirectcontrolbinding +GstDirectControlBinding +libs/controller/controller.h +gst_direct_control_binding_new +gst_direct_control_binding_new_absolute + +GstDirectControlBindingConvertValue +GstDirectControlBindingConvertGValue +GstDirectControlBinding +GstDirectControlBindingClass +GST_DIRECT_CONTROL_BINDING +GST_DIRECT_CONTROL_BINDING_CLASS +GST_DIRECT_CONTROL_BINDING_GET_CLASS +GST_IS_DIRECT_CONTROL_BINDING +GST_IS_DIRECT_CONTROL_BINDING_CLASS +GST_TYPE_DIRECT_CONTROL_BINDING +gst_direct_control_binding_get_type +
+ +
+gstproxycontrolbinding +GstProxyControlBinding +libs/controller/controller.h +gst_proxy_control_binding_new + +GstProxyControlBinding +GstProxyControlBindingClass +GST_PROXY_CONTROL_BINDING +GST_PROXY_CONTROL_BINDING_CLASS +GST_PROXY_CONTROL_BINDING_GET_CLASS +GST_IS_PROXY_CONTROL_BINDING +GST_IS_PROXY_CONTROL_BINDING_CLASS +GST_TYPE_PROXY_CONTROL_BINDING +gst_proxy_control_binding_get_type +
+ +# control source classes + +
+gsttimedvaluecontrolsource +GstTimedValueControlSource +libs/controller/controller.h +GstTimedValueControlSource +GstControlPoint +gst_timed_value_control_source_find_control_point_iter +gst_timed_value_control_source_set +gst_timed_value_control_source_set_from_list +gst_timed_value_control_source_get_all +gst_timed_value_control_source_unset +gst_timed_value_control_source_unset_all +gst_timed_value_control_source_get_count +gst_timed_value_control_invalidate_cache + +GstTimedValueControlSourceClass +GstTimedValueControlSourcePrivate +GST_TIMED_VALUE_CONTROL_SOURCE +GST_IS_TIMED_VALUE_CONTROL_SOURCE +GST_TIMED_VALUE_CONTROL_SOURCE_CLASS +GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS +GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS +GST_TYPE_TIMED_VALUE_CONTROL_SOURCE +GST_TIMED_VALUE_CONTROL_SOURCE_LOCK +GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK + +gst_timed_value_control_source_get_type +gst_control_point_get_type +
+ +
+gstinterpolationcontrolsource +GstInterpolationControlSource +libs/controller/controller.h +GstInterpolationControlSource +GstInterpolationMode +gst_interpolation_control_source_new + +GstInterpolationControlSourceClass +GstInterpolationControlSourcePrivate +GST_INTERPOLATION_CONTROL_SOURCE +GST_IS_INTERPOLATION_CONTROL_SOURCE +GST_INTERPOLATION_CONTROL_SOURCE_CLASS +GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS +GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS +GST_TYPE_INTERPOLATION_CONTROL_SOURCE +GST_TYPE_INTERPOLATION_MODE + +gst_interpolation_control_source_get_type +gst_interpolation_mode_get_type +
+ +
+gstlfocontrolsource +GstLFOControlSource +libs/controller/gstlfocontrolsource.h +GstLFOControlSource +GstLFOWaveform +gst_lfo_control_source_new + +GstLFOControlSourceClass +GstLFOControlSourcePrivate +GST_IS_LFO_CONTROL_SOURCE +GST_IS_LFO_CONTROL_SOURCE_CLASS +GST_LFO_CONTROL_SOURCE +GST_LFO_CONTROL_SOURCE_CLASS +GST_LFO_CONTROL_SOURCE_GET_CLASS +GST_TYPE_LFO_CONTROL_SOURCE +GST_TYPE_LFO_WAVEFORM + +gst_lfo_control_source_get_type +gst_lfo_waveform_get_type +
+ +
+gsttriggercontrolsource +GstTriggerControlSource +libs/controller/controller.h +GstTriggerControlSource +gst_trigger_control_source_new +GST_TYPE_TRIGGER_WAVEFORM + +GstTriggerControlSourceClass +GstTriggerControlSourcePrivate +GST_TRIGGER_CONTROL_SOURCE +GST_IS_TRIGGER_CONTROL_SOURCE +GST_TRIGGER_CONTROL_SOURCE_CLASS +GST_IS_TRIGGER_CONTROL_SOURCE_CLASS +GST_TRIGGER_CONTROL_SOURCE_GET_CLASS +GST_TYPE_TRIGGER_CONTROL_SOURCE + +gst_trigger_control_source_get_type +
+ +# base classes + +
+gstadapter +GstAdapter +gst/base/adapter.h +GstAdapter +gst_adapter_new +gst_adapter_clear +gst_adapter_push +gst_adapter_map +gst_adapter_unmap +gst_adapter_copy +gst_adapter_copy_bytes +gst_adapter_flush +gst_adapter_available +gst_adapter_available_fast +gst_adapter_take +gst_adapter_take_buffer +gst_adapter_get_buffer +gst_adapter_take_buffer_fast +gst_adapter_get_buffer_fast +gst_adapter_take_list +gst_adapter_get_list +gst_adapter_take_buffer_list +gst_adapter_get_buffer_list +gst_adapter_prev_pts +gst_adapter_prev_dts +gst_adapter_prev_pts_at_offset +gst_adapter_prev_dts_at_offset +gst_adapter_prev_offset +gst_adapter_pts_at_discont +gst_adapter_dts_at_discont +gst_adapter_offset_at_discont +gst_adapter_distance_from_discont +gst_adapter_masked_scan_uint32 +gst_adapter_masked_scan_uint32_peek + +GstAdapterClass +GstAdapterPrivate +GST_ADAPTER +GST_IS_ADAPTER +GST_TYPE_ADAPTER +GST_ADAPTER_CLASS +GST_IS_ADAPTER_CLASS +GST_ADAPTER_GET_CLASS + +gst_adapter_get_type +
+ +
+gstaggregator +GstAggregator +gst/base/base.h +GstAggregator +GstAggregatorClass +gst_aggregator_finish_buffer +gst_aggregator_set_src_caps +gst_aggregator_get_latency +gst_aggregator_get_buffer_pool +gst_aggregator_get_allocator + +GST_IS_AGGREGATOR +GST_IS_AGGREGATOR_CLASS +GST_TYPE_AGGREGATOR +GST_AGGREGATOR +GST_AGGREGATOR_CLASS +GST_AGGREGATOR_GET_CLASS +gst_aggregator_get_type +
+ +
+gstaggregatorpad +GstAggregatorPad +GstAggregatorPad +GstAggregatorPadClass +gst_aggregator_pad_pop_buffer +gst_aggregator_pad_peek_buffer +gst_aggregator_pad_drop_buffer +gst_aggregator_pad_is_eos +gst_aggregator_pad_has_buffer + +GST_IS_AGGREGATOR_PAD +GST_IS_AGGREGATOR_PAD_CLASS +GST_TYPE_AGGREGATOR_PAD +GST_AGGREGATOR_PAD +GST_AGGREGATOR_PAD_CLASS +GST_AGGREGATOR_PAD_GET_CLASS +gst_aggregator_pad_get_type +
+ +
+gstbaseparse +GstBaseParse +gst/base/gstbaseparse.h +GstBaseParse +GstBaseParseClass + +gst_base_parse_merge_tags +gst_base_parse_set_duration +gst_base_parse_set_average_bitrate +gst_base_parse_set_min_frame_size +gst_base_parse_set_passthrough +gst_base_parse_set_syncable +gst_base_parse_set_has_timing_info +gst_base_parse_drain +gst_base_parse_set_frame_rate +gst_base_parse_set_latency +gst_base_parse_set_infer_ts +gst_base_parse_set_pts_interpolation +gst_base_parse_set_ts_at_offset +gst_base_parse_convert_default +gst_base_parse_add_index_entry + +GstBaseParseFrame +GstBaseParseFrameFlags +gst_base_parse_frame_new +gst_base_parse_frame_init +gst_base_parse_frame_free + +gst_base_parse_push_frame +gst_base_parse_finish_frame + +GST_BASE_PARSE_DRAINING +GST_BASE_PARSE_FLAG_DRAINING +GST_BASE_PARSE_FLAG_LOST_SYNC +GST_BASE_PARSE_FLOW_DROPPED +GST_BASE_PARSE_LOST_SYNC +GST_BASE_PARSE_SINK_PAD +GST_BASE_PARSE_SRC_PAD + +GstBaseParsePrivate +GST_BASE_PARSE +GST_BASE_PARSE_CAST +GST_IS_BASE_PARSE +GST_TYPE_BASE_PARSE +GST_BASE_PARSE_CLASS +GST_IS_BASE_PARSE_CLASS +GST_BASE_PARSE_GET_CLASS + +gst_base_parse_get_type +gst_base_parse_frame_get_type +
+ +
+gstbasesrc +GstBaseSrc +gst/base/gstbasesrc.h +GstBaseSrc +GstBaseSrcClass +GstBaseSrcFlags + +gst_base_src_wait_playing +gst_base_src_start_wait +gst_base_src_start_complete +gst_base_src_is_live +gst_base_src_set_live +gst_base_src_set_format +gst_base_src_query_latency +gst_base_src_get_blocksize +gst_base_src_set_blocksize +gst_base_src_get_do_timestamp +gst_base_src_set_do_timestamp +gst_base_src_set_dynamic_size +gst_base_src_set_automatic_eos +gst_base_src_new_seamless_segment +gst_base_src_set_caps +gst_base_src_get_allocator +gst_base_src_get_buffer_pool +gst_base_src_is_async +gst_base_src_set_async +gst_base_src_submit_buffer_list + +GST_BASE_SRC_PAD +GST_BASE_SRC_IS_STARTED +GST_BASE_SRC_IS_STARTING + +GstBaseSrcPrivate +GST_BASE_SRC +GST_BASE_SRC_CAST +GST_IS_BASE_SRC +GST_TYPE_BASE_SRC +GST_BASE_SRC_CLASS +GST_IS_BASE_SRC_CLASS +GST_BASE_SRC_GET_CLASS + +gst_base_src_get_type +
+ +
+gstbasesink +GstBaseSink +gst/base/gstbasesink.h +GstBaseSink +GstBaseSinkClass + +gst_base_sink_query_latency +gst_base_sink_get_latency +gst_base_sink_do_preroll +gst_base_sink_wait +gst_base_sink_wait_preroll +gst_base_sink_wait_clock +gst_base_sink_set_sync +gst_base_sink_get_sync +gst_base_sink_set_max_lateness +gst_base_sink_get_max_lateness +gst_base_sink_set_qos_enabled +gst_base_sink_is_qos_enabled +gst_base_sink_set_async_enabled +gst_base_sink_is_async_enabled +gst_base_sink_set_ts_offset +gst_base_sink_get_ts_offset +gst_base_sink_set_render_delay +gst_base_sink_get_render_delay +gst_base_sink_get_last_sample +gst_base_sink_set_blocksize +gst_base_sink_get_blocksize +gst_base_sink_get_throttle_time +gst_base_sink_set_throttle_time +gst_base_sink_set_max_bitrate +gst_base_sink_get_max_bitrate +gst_base_sink_set_last_sample_enabled +gst_base_sink_is_last_sample_enabled + +GST_BASE_SINK_PAD +GST_BASE_SINK_GET_PREROLL_COND +GST_BASE_SINK_GET_PREROLL_LOCK +GST_BASE_SINK_PREROLL_BROADCAST +GST_BASE_SINK_PREROLL_LOCK +GST_BASE_SINK_PREROLL_SIGNAL +GST_BASE_SINK_PREROLL_TRYLOCK +GST_BASE_SINK_PREROLL_UNLOCK +GST_BASE_SINK_PREROLL_WAIT +GST_BASE_SINK_PREROLL_WAIT_UNTIL + + +GST_BASE_SINK +GST_BASE_SINK_CAST +GST_IS_BASE_SINK +GST_TYPE_BASE_SINK +GST_BASE_SINK_CLASS +GST_IS_BASE_SINK_CLASS +GST_BASE_SINK_GET_CLASS + +GstBaseSinkPrivate +gst_base_sink_get_type +
+ + +
+gstbasetransform +GstBaseTransform +gst/base/gstbasetransform.h +GstBaseTransform +GstBaseTransformClass + +gst_base_transform_is_passthrough +gst_base_transform_set_passthrough +gst_base_transform_set_prefer_passthrough +gst_base_transform_is_in_place +gst_base_transform_set_in_place +gst_base_transform_is_qos_enabled +gst_base_transform_set_qos_enabled +gst_base_transform_update_qos +gst_base_transform_set_gap_aware +gst_base_transform_get_allocator +gst_base_transform_get_buffer_pool +gst_base_transform_reconfigure_sink +gst_base_transform_reconfigure_src +gst_base_transform_update_src_caps + +GST_BASE_TRANSFORM_SINK_NAME +GST_BASE_TRANSFORM_SRC_NAME +GST_BASE_TRANSFORM_SINK_PAD +GST_BASE_TRANSFORM_SRC_PAD + +GST_BASE_TRANSFORM_FLOW_DROPPED + + +GST_BASE_TRANSFORM +GST_IS_BASE_TRANSFORM +GST_TYPE_BASE_TRANSFORM +GST_BASE_TRANSFORM_CLASS +GST_IS_BASE_TRANSFORM_CLASS +GST_BASE_TRANSFORM_GET_CLASS +GST_BASE_TRANSFORM_CAST + +GstBaseTransformPrivate +gst_base_transform_get_type +
+ + +
+gstbitreader +GstBitReader +gst/base/gstbitreader.h +GstBitReader + +GST_BIT_READER_INIT + +gst_bit_reader_new +gst_bit_reader_free + +gst_bit_reader_init + +gst_bit_reader_get_pos +gst_bit_reader_get_remaining +gst_bit_reader_set_pos +gst_bit_reader_get_size +gst_bit_reader_skip +gst_bit_reader_skip_to_byte + +gst_bit_reader_get_bits_uint16 +gst_bit_reader_get_bits_uint32 +gst_bit_reader_get_bits_uint64 +gst_bit_reader_get_bits_uint8 + +gst_bit_reader_peek_bits_uint16 +gst_bit_reader_peek_bits_uint32 +gst_bit_reader_peek_bits_uint64 +gst_bit_reader_peek_bits_uint8 + +gst_bit_reader_skip_unchecked +gst_bit_reader_skip_to_byte_unchecked + +gst_bit_reader_get_bits_uint16_unchecked +gst_bit_reader_get_bits_uint32_unchecked +gst_bit_reader_get_bits_uint64_unchecked +gst_bit_reader_get_bits_uint8_unchecked + +gst_bit_reader_peek_bits_uint16_unchecked +gst_bit_reader_peek_bits_uint32_unchecked +gst_bit_reader_peek_bits_uint64_unchecked +gst_bit_reader_peek_bits_uint8_unchecked + + +GST_BIT_READER +
+ +
+gstbytereader +GstByteReader +gst/base/gstbytereader.h +GstByteReader + +GST_BYTE_READER_INIT + +gst_byte_reader_new +gst_byte_reader_free + +gst_byte_reader_init + +gst_byte_reader_peek_sub_reader +gst_byte_reader_get_sub_reader + +gst_byte_reader_get_pos +gst_byte_reader_get_remaining +gst_byte_reader_set_pos +gst_byte_reader_get_size +gst_byte_reader_skip + +gst_byte_reader_get_int8 +gst_byte_reader_get_int16_be +gst_byte_reader_get_int16_le +gst_byte_reader_get_int24_be +gst_byte_reader_get_int24_le +gst_byte_reader_get_int32_be +gst_byte_reader_get_int32_le +gst_byte_reader_get_int64_be +gst_byte_reader_get_int64_le + +gst_byte_reader_get_uint8 +gst_byte_reader_get_uint16_be +gst_byte_reader_get_uint16_le +gst_byte_reader_get_uint24_be +gst_byte_reader_get_uint24_le +gst_byte_reader_get_uint32_be +gst_byte_reader_get_uint32_le +gst_byte_reader_get_uint64_be +gst_byte_reader_get_uint64_le + +gst_byte_reader_peek_int8 +gst_byte_reader_peek_int16_be +gst_byte_reader_peek_int16_le +gst_byte_reader_peek_int24_be +gst_byte_reader_peek_int24_le +gst_byte_reader_peek_int32_be +gst_byte_reader_peek_int32_le +gst_byte_reader_peek_int64_be +gst_byte_reader_peek_int64_le + +gst_byte_reader_peek_uint8 +gst_byte_reader_peek_uint16_be +gst_byte_reader_peek_uint16_le +gst_byte_reader_peek_uint24_be +gst_byte_reader_peek_uint24_le +gst_byte_reader_peek_uint32_be +gst_byte_reader_peek_uint32_le +gst_byte_reader_peek_uint64_be +gst_byte_reader_peek_uint64_le + + +gst_byte_reader_get_float32_le +gst_byte_reader_get_float32_be +gst_byte_reader_get_float64_le +gst_byte_reader_get_float64_be + +gst_byte_reader_peek_float32_le +gst_byte_reader_peek_float32_be +gst_byte_reader_peek_float64_le +gst_byte_reader_peek_float64_be + +gst_byte_reader_get_data +gst_byte_reader_dup_data +gst_byte_reader_peek_data + +gst_byte_reader_masked_scan_uint32 +gst_byte_reader_masked_scan_uint32_peek + +gst_byte_reader_get_string +gst_byte_reader_get_string_utf8 + +gst_byte_reader_peek_string +gst_byte_reader_peek_string_utf8 + +gst_byte_reader_dup_string +gst_byte_reader_dup_string_utf8 +gst_byte_reader_dup_string_utf16 +gst_byte_reader_dup_string_utf32 + +gst_byte_reader_skip_string +gst_byte_reader_skip_string_utf8 +gst_byte_reader_skip_string_utf16 +gst_byte_reader_skip_string_utf32 + +gst_byte_reader_skip_unchecked + +gst_byte_reader_get_int8_unchecked +gst_byte_reader_get_int16_be_unchecked +gst_byte_reader_get_int16_le_unchecked +gst_byte_reader_get_int24_be_unchecked +gst_byte_reader_get_int24_le_unchecked +gst_byte_reader_get_int32_be_unchecked +gst_byte_reader_get_int32_le_unchecked +gst_byte_reader_get_int64_be_unchecked +gst_byte_reader_get_int64_le_unchecked + +gst_byte_reader_get_uint8_unchecked +gst_byte_reader_get_uint16_be_unchecked +gst_byte_reader_get_uint16_le_unchecked +gst_byte_reader_get_uint24_be_unchecked +gst_byte_reader_get_uint24_le_unchecked +gst_byte_reader_get_uint32_be_unchecked +gst_byte_reader_get_uint32_le_unchecked +gst_byte_reader_get_uint64_be_unchecked +gst_byte_reader_get_uint64_le_unchecked + +gst_byte_reader_peek_int8_unchecked +gst_byte_reader_peek_int16_be_unchecked +gst_byte_reader_peek_int16_le_unchecked +gst_byte_reader_peek_int24_be_unchecked +gst_byte_reader_peek_int24_le_unchecked +gst_byte_reader_peek_int32_be_unchecked +gst_byte_reader_peek_int32_le_unchecked +gst_byte_reader_peek_int64_be_unchecked +gst_byte_reader_peek_int64_le_unchecked + +gst_byte_reader_peek_uint8_unchecked +gst_byte_reader_peek_uint16_be_unchecked +gst_byte_reader_peek_uint16_le_unchecked +gst_byte_reader_peek_uint24_be_unchecked +gst_byte_reader_peek_uint24_le_unchecked +gst_byte_reader_peek_uint32_be_unchecked +gst_byte_reader_peek_uint32_le_unchecked +gst_byte_reader_peek_uint64_be_unchecked +gst_byte_reader_peek_uint64_le_unchecked + +gst_byte_reader_get_float32_le_unchecked +gst_byte_reader_get_float32_be_unchecked +gst_byte_reader_get_float64_le_unchecked +gst_byte_reader_get_float64_be_unchecked + +gst_byte_reader_peek_float32_le_unchecked +gst_byte_reader_peek_float32_be_unchecked +gst_byte_reader_peek_float64_le_unchecked +gst_byte_reader_peek_float64_be_unchecked + +gst_byte_reader_dup_data_unchecked +gst_byte_reader_get_data_unchecked +gst_byte_reader_peek_data_unchecked + + +GST_BYTE_READER +# seems to be a header parsing bug +g_memdup +
+ +
+gstbytewriter +GstByteWriter +gst/base/gstbytewriter.h +GstByteWriter + +gst_byte_writer_new +gst_byte_writer_new_with_data +gst_byte_writer_new_with_size + +gst_byte_writer_init +gst_byte_writer_init_with_data +gst_byte_writer_init_with_size + +gst_byte_writer_free +gst_byte_writer_free_and_get_buffer +gst_byte_writer_free_and_get_data + +gst_byte_writer_reset +gst_byte_writer_reset_and_get_data +gst_byte_writer_reset_and_get_buffer + +gst_byte_writer_get_pos +gst_byte_writer_set_pos +gst_byte_writer_get_remaining +gst_byte_writer_get_size +gst_byte_writer_ensure_free_space + +gst_byte_writer_put_int8 +gst_byte_writer_put_int16_be +gst_byte_writer_put_int16_le +gst_byte_writer_put_int24_be +gst_byte_writer_put_int24_le +gst_byte_writer_put_int32_be +gst_byte_writer_put_int32_le +gst_byte_writer_put_int64_be +gst_byte_writer_put_int64_le + +gst_byte_writer_put_uint8 +gst_byte_writer_put_uint16_be +gst_byte_writer_put_uint16_le +gst_byte_writer_put_uint24_be +gst_byte_writer_put_uint24_le +gst_byte_writer_put_uint32_be +gst_byte_writer_put_uint32_le +gst_byte_writer_put_uint64_be +gst_byte_writer_put_uint64_le + +gst_byte_writer_put_float32_be +gst_byte_writer_put_float32_le +gst_byte_writer_put_float64_be +gst_byte_writer_put_float64_le + +gst_byte_writer_put_string +gst_byte_writer_put_string_utf16 +gst_byte_writer_put_string_utf32 +gst_byte_writer_put_string_utf8 + +gst_byte_writer_put_data +gst_byte_writer_fill + +gst_byte_writer_put_buffer +gst_byte_writer_put_buffer_unchecked + +gst_byte_writer_put_int8_unchecked +gst_byte_writer_put_int16_be_unchecked +gst_byte_writer_put_int16_le_unchecked +gst_byte_writer_put_int24_be_unchecked +gst_byte_writer_put_int24_le_unchecked +gst_byte_writer_put_int32_be_unchecked +gst_byte_writer_put_int32_le_unchecked +gst_byte_writer_put_int64_be_unchecked +gst_byte_writer_put_int64_le_unchecked + +gst_byte_writer_put_uint8_unchecked +gst_byte_writer_put_uint16_be_unchecked +gst_byte_writer_put_uint16_le_unchecked +gst_byte_writer_put_uint24_be_unchecked +gst_byte_writer_put_uint24_le_unchecked +gst_byte_writer_put_uint32_be_unchecked +gst_byte_writer_put_uint32_le_unchecked +gst_byte_writer_put_uint64_be_unchecked +gst_byte_writer_put_uint64_le_unchecked + +gst_byte_writer_put_float32_be_unchecked +gst_byte_writer_put_float32_le_unchecked +gst_byte_writer_put_float64_be_unchecked +gst_byte_writer_put_float64_le_unchecked + +gst_byte_writer_put_data_unchecked +gst_byte_writer_fill_unchecked + +GST_BYTE_WRITER +
+ +
+gstcollectpads +GstCollectPads +gst/base/gstcollectpads.h +GstCollectPads +GstCollectData + +GstCollectDataDestroyNotify +GstCollectPadsBufferFunction +GstCollectPadsClipFunction +GstCollectPadsCompareFunction +GstCollectPadsEventFunction +GstCollectPadsFlushFunction +GstCollectPadsQueryFunction +GstCollectPadsFunction +GstCollectPadsStateFlags + +GST_COLLECT_PADS_STATE +GST_COLLECT_PADS_STATE_IS_SET +GST_COLLECT_PADS_STATE_SET +GST_COLLECT_PADS_STATE_UNSET + +GST_COLLECT_PADS_GET_STREAM_LOCK +GST_COLLECT_PADS_STREAM_LOCK +GST_COLLECT_PADS_STREAM_UNLOCK + +GST_COLLECT_PADS_DTS +GST_COLLECT_PADS_DTS_IS_VALID + +gst_collect_pads_new + +gst_collect_pads_add_pad +gst_collect_pads_remove_pad + +gst_collect_pads_start +gst_collect_pads_stop + +gst_collect_pads_available + +gst_collect_pads_flush +gst_collect_pads_peek +gst_collect_pads_pop + +gst_collect_pads_read_buffer +gst_collect_pads_take_buffer + +gst_collect_pads_clip_running_time + +gst_collect_pads_query_default + +gst_collect_pads_event_default +gst_collect_pads_src_event_default + +gst_collect_pads_set_buffer_function +gst_collect_pads_set_clip_function +gst_collect_pads_set_compare_function +gst_collect_pads_set_event_function +gst_collect_pads_set_flush_function +gst_collect_pads_set_query_function +gst_collect_pads_set_flushing +gst_collect_pads_set_function +gst_collect_pads_set_waiting + +GstCollectPadsClass +GstCollectPadsPrivate +GstCollectDataPrivate +GST_COLLECT_PADS +GST_COLLECT_PADS_CLASS +GST_TYPE_COLLECT_PADS +GST_IS_COLLECT_PADS +GST_IS_COLLECT_PADS_CLASS +GST_COLLECT_PADS_GET_CLASS +gst_collect_pads_get_type + +
+ +
+gstflowcombiner +GstFlowCombiner +gst/base/gstflowcombiner.h +GstFlowCombiner +gst_flow_combiner_new +gst_flow_combiner_free +gst_flow_combiner_ref +gst_flow_combiner_unref +gst_flow_combiner_update_flow +gst_flow_combiner_add_pad +gst_flow_combiner_remove_pad +gst_flow_combiner_clear +gst_flow_combiner_reset +gst_flow_combiner_update_pad_flow + +GST_TYPE_FLOW_COMBINER + +gst_flow_combiner_get_type +
+ +
+gstpushsrc +GstPushSrc +gst/base/gstpushsrc.h +GstPushSrc +GstPushSrcClass + +GST_PUSH_SRC +GST_IS_PUSH_SRC +GST_TYPE_PUSH_SRC +GST_PUSH_SRC_CLASS +GST_IS_PUSH_SRC_CLASS +GST_PUSH_SRC_GET_CLASS + +gst_push_src_get_type +
+ +
+gsttypefindhelper +GstTypeFindHelper +gst/base/gsttypefindhelper.h +gst_type_find_helper +gst_type_find_helper_for_buffer +gst_type_find_helper_for_extension +gst_type_find_helper_for_data +GstTypeFindHelperGetRangeFunction +gst_type_find_helper_get_range + +
+ +
+gstdataqueue +GstDataQueue +gst/base/gstdataqueue.h +GstDataQueue +GstDataQueueSize +GstDataQueueCheckFullFunction +GstDataQueueItem +GstDataQueueEmptyCallback +GstDataQueueFullCallback +gst_data_queue_new +gst_data_queue_push +gst_data_queue_push_force +gst_data_queue_pop +gst_data_queue_peek +gst_data_queue_flush +gst_data_queue_set_flushing +gst_data_queue_drop_head +gst_data_queue_is_full +gst_data_queue_is_empty +gst_data_queue_get_level +gst_data_queue_limits_changed + +GstDataQueueClass +GstDataQueuePrivate +GST_DATA_QUEUE +GST_IS_DATA_QUEUE +GST_TYPE_DATA_QUEUE +GST_DATA_QUEUE_CLASS +GST_IS_DATA_QUEUE_CLASS + +gst_data_queue_get_type +
+ +
+gstqueuearray +GstQueueArray +gst/base/gstqueuearray.h +GstQueueArray +gst_queue_array_new +gst_queue_array_free +gst_queue_array_get_length +gst_queue_array_pop_head +gst_queue_array_peek_head +gst_queue_array_push_tail +gst_queue_array_pop_tail +gst_queue_array_peek_tail +gst_queue_array_is_empty +gst_queue_array_drop_element +gst_queue_array_find +gst_queue_array_new_for_struct +gst_queue_array_push_tail_struct +gst_queue_array_peek_head_struct +gst_queue_array_pop_head_struct +gst_queue_array_peek_tail_struct +gst_queue_array_pop_tail_struct +gst_queue_array_drop_struct +
+ +# net + +
+gstnetaddressmeta +GstNetAddressMeta +gst/net/gstnetaddressmeta.h +GstNetAddressMeta +gst_buffer_add_net_address_meta +gst_buffer_get_net_address_meta +gst_net_address_meta_get_info + +GST_NET_ADDRESS_META_API_TYPE +GST_NET_ADDRESS_META_INFO + +gst_net_address_meta_api_get_type +
+ +
+gstnetcontrolmessagemeta +GstNetControlMessageMeta +gst/net/gstnetcontrolmessagemeta.h +GstNetControlMessageMeta +gst_buffer_add_net_control_message_meta +gst_buffer_get_net_control_message_meta +gst_net_control_message_meta_get_info + +GST_NET_CONTROL_MESSAGE_META_API_TYPE +GST_NET_CONTROL_MESSAGE_META_INFO + +gst_net_control_message_meta_api_get_type +
+ +
+gstnetclientclock +GstNetClientClock +gst/net/gstnet.h +GstNetClientClock +GstNtpClock +gst_net_client_clock_new +gst_ntp_clock_new + +GstNetClientClockClass +GstNetClientClockPrivate +GST_NET_CLIENT_CLOCK +GST_IS_NET_CLIENT_CLOCK +GST_TYPE_NET_CLIENT_CLOCK +GST_NET_CLIENT_CLOCK_CLASS +GST_IS_NET_CLIENT_CLOCK_CLASS +GstNtpClockClass +GST_NTP_CLOCK +GST_IS_NTP_CLOCK +GST_TYPE_NTP_CLOCK +GST_NTP_CLOCK_CLASS +GST_IS_NTP_CLOCK_CLASS + +gst_net_client_clock_get_type +gst_ntp_clock_get_type +
+ + +
+gstnettimepacket +GstNetTimePacket +gst/net/gstnet.h +GstNetTimePacket +GST_NET_TIME_PACKET_SIZE +gst_net_time_packet_new +gst_net_time_packet_copy +gst_net_time_packet_free +gst_net_time_packet_receive +gst_net_time_packet_send +gst_net_time_packet_serialize + + +gst_net_time_packet_get_type +socklen_t +
+ + +
+gstnettimeprovider +GstNetTimeProvider +gst/net/gstnet.h +GstNetTimeProvider +gst_net_time_provider_new + +GstNetTimeProviderClass +GstNetTimeProviderPrivate +GST_NET_TIME_PROVIDER +GST_IS_NET_TIME_PROVIDER +GST_TYPE_NET_TIME_PROVIDER +GST_NET_TIME_PROVIDER_CLASS +GST_IS_NET_TIME_PROVIDER_CLASS + +gst_net_time_provider_get_type +
+ + +
+gstptpclock +GstPtpClock +gst/net/net.h +GST_PTP_CLOCK_ID_NONE + +gst_ptp_init +gst_ptp_deinit +gst_ptp_is_initialized +gst_ptp_is_supported + +GstPtpClock +gst_ptp_clock_new + +GstPtpStatisticsCallback +gst_ptp_statistics_callback_add +gst_ptp_statistics_callback_remove + +GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED +GST_PTP_STATISTICS_NEW_DOMAIN_FOUND +GST_PTP_STATISTICS_PATH_DELAY_MEASURED +GST_PTP_STATISTICS_TIME_UPDATED + +GstPtpClockClass +GstPtpClockPrivate +GST_PTP_CLOCK +GST_IS_PTP_CLOCK +GST_TYPE_PTP_CLOCK +GST_PTP_CLOCK_CLASS +GST_IS_PTP_CLOCK_CLASS + +gst_ptp_clock_get_type +
+ +
+gstcheck +GstCheck +gst/check/gstcheck.h +GST_START_TEST +GST_END_TEST + +ASSERT_BUFFER_REFCOUNT +ASSERT_CAPS_REFCOUNT +ASSERT_CRITICAL +ASSERT_WARNING +ASSERT_MINI_OBJECT_REFCOUNT +ASSERT_OBJECT_REFCOUNT +ASSERT_OBJECT_REFCOUNT_BETWEEN +ASSERT_SET_STATE + +fail_unless_equals_int +fail_unless_equals_float +fail_unless_equals_string +fail_unless_equals_uint64 +fail_unless_equals_int64 +fail_unless_equals_int_hex +fail_unless_equals_int64_hex +fail_unless_equals_uint64_hex +fail_unless_equals_pointer + +fail_unless_message_error + +assert_equals_int +assert_equals_float +assert_equals_string +assert_equals_uint64 +assert_equals_int64 +assert_equals_int_hex +assert_equals_int64_hex +assert_equals_uint64_hex +assert_equals_pointer +assert_message_error + +gst_check_init +gst_check_message_error +gst_check_setup_element +gst_check_setup_sink_pad +gst_check_setup_src_pad +gst_check_setup_sink_pad_by_name +gst_check_setup_src_pad_by_name +gst_check_teardown_pad_by_name +gst_check_teardown_element +gst_check_teardown_sink_pad +gst_check_teardown_src_pad +gst_check_drop_buffers +gst_check_buffer_data +gst_check_caps_equal +gst_check_element_push_buffer_list +gst_check_element_push_buffer +gst_check_run_suite +gst_check_setup_events +gst_check_setup_events_with_stream_id +gst_check_setup_sink_pad_by_name_from_template +gst_check_setup_sink_pad_from_template +gst_check_setup_src_pad_by_name_from_template +gst_check_setup_src_pad_from_template +gst_check_objects_destroyed_on_unref +gst_check_object_destroyed_on_unref + + +MAIN_INIT +MAIN_START_THREADS +MAIN_START_THREAD_FUNCTION +MAIN_START_THREAD_FUNCTIONS +MAIN_STOP_THREADS +MAIN_SYNCHRONIZE +THREAD_START +THREAD_STARTED +THREAD_SWITCH +THREAD_SYNCHRONIZE +THREAD_TEST_RUNNING + +sync_cond +mutex +GST_CAT_DEFAULT +thread_list +start_cond +GST_CHECK_MAIN + +gst_check_chain_func +gst_check_abi_list + +buffers +check_cond +check_mutex + +CHECK_MAJOR_VERSION +CHECK_MICRO_VERSION +CHECK_MINOR_VERSION +CK_ATTRIBUTE_UNUSED +CK_CPPEND +CK_CPPSTART +CK_EXPORT +END_TEST +GCC_VERSION_AT_LEAST +LFun +List +Log +NULL +SFun +SRunner +START_TEST +Suite +TCase +TF +TFun +TestResult +TestStats +check_list_create +ck_abort +ck_abort_msg +ck_assert +ck_assert_int_eq +ck_assert_int_ne +ck_assert_msg +ck_assert_str_eq +ck_assert_str_ne +ck_strdup_printf +cur_fork_status +emalloc +eprintf +erealloc +fail +fail_if +fail_unless +get_env_printmode +lfile_lfun +list_add_end +list_add_front +list_advance +list_apply +list_at_end +list_free +list_front +list_val +log_srunner_end +log_srunner_start +log_suite_end +log_suite_start +log_test_start +log_test_end +mark_point +pack +ppack +punpack +rcvmsg_free +receive_test_result +send_ctx_info +send_failure_info +send_loc_info +set_fork_status +setup_messaging +sr_stat_str +srunner_end_logging +srunner_fprint +srunner_init_logging +srunner_open_lfile +srunner_open_xmlfile +srunner_register_lfun +stdout_lfun +subunit_lfun +tcase_add_exit_test +tcase_add_loop_exit_test +tcase_add_loop_test +tcase_add_loop_test_raise_signal +tcase_add_test +tcase_add_test_raise_signal +tcase_skip_broken_test +teardown_messaging +tr_create +tr_fprint +tr_reset +tr_short_str +tr_str +tr_xmlprint +upack +xml_lfun +
+ +
+gstcheckbufferstraw +GstBufferStraw +gst/check/gstbufferstraw.h +gst_buffer_straw_start_pipeline +gst_buffer_straw_get_buffer +gst_buffer_straw_stop_pipeline +
+ +
+gstcheckconsistencychecker +GstStreamConsistency +gst/check/gstconsistencychecker.h +GstStreamConsistency +gst_consistency_checker_new +gst_consistency_checker_reset +gst_consistency_checker_free +gst_consistency_checker_add_pad +
+ +
+gstharness +GstHarness +gst/check/check.h +GstHarness + +gst_harness_new_empty +gst_harness_new_full +gst_harness_new_with_element +gst_harness_new_with_padnames +gst_harness_new_with_templates +gst_harness_new +gst_harness_new_parse +gst_harness_add_element_full +gst_harness_add_parse +gst_harness_teardown + +gst_harness_add_element_src_pad +gst_harness_add_element_sink_pad + +gst_harness_set_src_caps +gst_harness_set_sink_caps +gst_harness_set_caps +gst_harness_set_src_caps_str +gst_harness_set_sink_caps_str +gst_harness_set_caps_str + +gst_harness_use_systemclock +gst_harness_use_testclock +gst_harness_get_testclock +gst_harness_set_time +gst_harness_wait_for_clock_id_waits +gst_harness_crank_single_clock_wait +gst_harness_crank_multiple_clock_waits + +gst_harness_play +gst_harness_set_blocking_push_mode +gst_harness_set_forwarding + +gst_harness_create_buffer +gst_harness_push +gst_harness_pull +gst_harness_try_pull +gst_harness_push_and_pull +gst_harness_buffers_received +gst_harness_buffers_in_queue +gst_harness_set_drop_buffers +gst_harness_dump_to_file +gst_harness_take_all_data +gst_harness_take_all_data_as_buffer +gst_harness_take_all_data_as_bytes +gst_harness_get_last_pushed_timestamp + +gst_harness_push_event +gst_harness_pull_event +gst_harness_try_pull_event +gst_harness_events_received +gst_harness_events_in_queue + +gst_harness_push_upstream_event +gst_harness_pull_upstream_event +gst_harness_try_pull_upstream_event +gst_harness_upstream_events_received +gst_harness_upstream_events_in_queue + +gst_harness_query_latency +gst_harness_set_upstream_latency + +gst_harness_set_propose_allocator +gst_harness_get_allocator + +gst_harness_add_src +gst_harness_add_src_harness +gst_harness_add_src_parse +gst_harness_push_from_src +gst_harness_src_crank_and_push_many +gst_harness_src_push_event + +gst_harness_add_sink +gst_harness_add_sink_harness +gst_harness_add_sink_parse +gst_harness_push_to_sink +gst_harness_sink_push_many + +gst_harness_find_element +gst_harness_set +gst_harness_get +gst_harness_add_probe + +GstHarnessThread + +gst_harness_stress_thread_stop +gst_harness_stress_custom_start + +gst_harness_stress_statechange_start +gst_harness_stress_statechange_start_full + +gst_harness_stress_push_buffer_start +gst_harness_stress_push_buffer_start_full + +GstHarnessPrepareBufferFunc +gst_harness_stress_push_buffer_with_cb_start +gst_harness_stress_push_buffer_with_cb_start_full + +gst_harness_stress_push_event_start +gst_harness_stress_push_event_start_full + +GstHarnessPrepareEventFunc +gst_harness_stress_push_event_with_cb_start +gst_harness_stress_push_event_with_cb_start_full + +gst_harness_stress_send_upstream_event_start +gst_harness_stress_push_upstream_event_start_full + +gst_harness_stress_send_upstream_event_with_cb_start +gst_harness_stress_push_upstream_event_with_cb_start_full + +gst_harness_stress_property_start +gst_harness_stress_property_start_full + +gst_harness_stress_requestpad_start +gst_harness_stress_requestpad_start_full + +GstHarnessPrivate +
+ +
+gsttestclock +GstTestClock +gst/check/gsttestclock.h +GstTestClock +GstTestClockClass +gst_test_clock_new +gst_test_clock_new_with_start_time +gst_test_clock_set_time +gst_test_clock_advance_time +gst_test_clock_peek_id_count +gst_test_clock_has_id +gst_test_clock_peek_next_pending_id +gst_test_clock_wait_for_next_pending_id +gst_test_clock_wait_for_pending_id_count +gst_test_clock_process_next_clock_id +gst_test_clock_get_next_entry_time +gst_test_clock_wait_for_multiple_pending_ids +gst_test_clock_id_list_get_latest_time +gst_test_clock_process_id_list +gst_test_clock_crank + +GST_TEST_CLOCK +GST_IS_TEST_CLOCK +GST_TYPE_TEST_CLOCK +GST_TEST_CLOCK_CLASS +GST_IS_TEST_CLOCK_CLASS +GST_TEST_CLOCK_GET_CLASS +GST_TEST_CLOCK_CAST + +GstTestClockPrivate +gst_test_clock_get_type +
diff --git a/docs/libs/gstreamer-libs.types b/docs/libs/gstreamer-libs.types new file mode 100644 index 0000000..c68cf9e --- /dev/null +++ b/docs/libs/gstreamer-libs.types @@ -0,0 +1,53 @@ +#include + +% base classes + +#include +#include +#include +#include +#include +#include +#include +#include + +gst_adapter_get_type +gst_aggregator_get_type +gst_aggregator_pad_get_type +gst_base_parse_get_type +gst_base_src_get_type +gst_base_sink_get_type +gst_base_transform_get_type +gst_collect_pads_get_type +gst_push_src_get_type + +% controller + +#include +#include +#include +#include +#include +#include + +gst_argb_control_binding_get_type +gst_direct_control_binding_get_type +gst_timed_value_control_source_get_type +gst_interpolation_control_source_get_type +gst_lfo_control_source_get_type +gst_trigger_control_source_get_type + +% net + +#include + +gst_net_client_clock_get_type +gst_net_time_provider_get_type +gst_ntp_clock_get_type +gst_ptp_clock_get_type + +% check + +#include + +gst_test_clock_get_type diff --git a/docs/libs/html/GstARGBControlBinding.html b/docs/libs/html/GstARGBControlBinding.html new file mode 100644 index 0000000..c25d468 --- /dev/null +++ b/docs/libs/html/GstARGBControlBinding.html @@ -0,0 +1,208 @@ + + + + +GstARGBControlBinding: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstARGBControlBinding

+

GstARGBControlBinding — attachment for control sources to argb properties

+
+
+

Functions

+
++++ + + + + +
+GstControlBinding * + +gst_argb_control_binding_new () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+GstControlSource *control-source-aRead / Write / Construct
+GstControlSource *control-source-bRead / Write / Construct
+GstControlSource *control-source-gRead / Write / Construct
+GstControlSource *control-source-rRead / Write / Construct
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlBinding
+                ╰── GstARGBControlBinding
+
+
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

A value mapping object that attaches multiple control sources to a guint +gobject properties representing a color. A control value of 0.0 will turn the +color component off and a value of 1.0 will be the color level.

+
+
+

Functions

+
+

gst_argb_control_binding_new ()

+
GstControlBinding *
+gst_argb_control_binding_new (GstObject *object,
+                              const gchar *property_name,
+                              GstControlSource *cs_a,
+                              GstControlSource *cs_r,
+                              GstControlSource *cs_g,
+                              GstControlSource *cs_b);
+

Create a new control-binding that attaches the given GstControlSource to the +GObject property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

object

the object of the property

 

property_name

the property-name to attach the control source

 

cs_a

the control source for the alpha channel

 

cs_r

the control source for the red channel

 

cs_g

the control source for the green channel

 

cs_b

the control source for the blue channel

 
+
+
+

Returns

+

the new GstARGBControlBinding.

+

[transfer floating]

+
+
+
+
+

Types and Values

+
+
+

Property Details

+
+

The “control-source-a” property

+
  “control-source-a”         GstControlSource *
+

The control source for the alpha color component.

+

Flags: Read / Write / Construct

+
+
+
+

The “control-source-b” property

+
  “control-source-b”         GstControlSource *
+

The control source for the blue color component.

+

Flags: Read / Write / Construct

+
+
+
+

The “control-source-g” property

+
  “control-source-g”         GstControlSource *
+

The control source for the green color component.

+

Flags: Read / Write / Construct

+
+
+
+

The “control-source-r” property

+
  “control-source-r”         GstControlSource *
+

The control source for the red color component.

+

Flags: Read / Write / Construct

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstAdapter.html b/docs/libs/html/GstAdapter.html new file mode 100644 index 0000000..36b61d3 --- /dev/null +++ b/docs/libs/html/GstAdapter.html @@ -0,0 +1,1707 @@ + + + + +GstAdapter: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstAdapter

+

GstAdapter — adapts incoming data on a sink pad into chunks of N bytes

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstAdapter * + +gst_adapter_new () +
+void + +gst_adapter_clear () +
+void + +gst_adapter_push () +
+gconstpointer + +gst_adapter_map () +
+void + +gst_adapter_unmap () +
+void + +gst_adapter_copy () +
+GBytes * + +gst_adapter_copy_bytes () +
+void + +gst_adapter_flush () +
+gsize + +gst_adapter_available () +
+gsize + +gst_adapter_available_fast () +
+gpointer + +gst_adapter_take () +
+GstBuffer * + +gst_adapter_take_buffer () +
+GstBuffer * + +gst_adapter_get_buffer () +
+GstBuffer * + +gst_adapter_take_buffer_fast () +
+GstBuffer * + +gst_adapter_get_buffer_fast () +
+GList * + +gst_adapter_take_list () +
+GList * + +gst_adapter_get_list () +
+GstBufferList * + +gst_adapter_take_buffer_list () +
+GstBufferList * + +gst_adapter_get_buffer_list () +
+GstClockTime + +gst_adapter_prev_pts () +
+GstClockTime + +gst_adapter_prev_dts () +
+GstClockTime + +gst_adapter_prev_pts_at_offset () +
+GstClockTime + +gst_adapter_prev_dts_at_offset () +
+guint64 + +gst_adapter_prev_offset () +
+GstClockTime + +gst_adapter_pts_at_discont () +
+GstClockTime + +gst_adapter_dts_at_discont () +
+guint64 + +gst_adapter_offset_at_discont () +
+guint64 + +gst_adapter_distance_from_discont () +
+gssize + +gst_adapter_masked_scan_uint32 () +
+gssize + +gst_adapter_masked_scan_uint32_peek () +
+
+
+

Types and Values

+
++++ + + + + +
 GstAdapter
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GstAdapter
+
+
+
+

Includes

+
#include <gst/base/adapter.h>
+
+
+
+

Description

+

This class is for elements that receive buffers in an undesired size. +While for example raw video contains one image per buffer, the same is not +true for a lot of other formats, especially those that come directly from +a file. So if you have undefined buffer sizes and require a specific size, +this object is for you.

+

An adapter is created with gst_adapter_new(). It can be freed again with +g_object_unref().

+

The theory of operation is like this: All buffers received are put +into the adapter using gst_adapter_push() and the data is then read back +in chunks of the desired size using gst_adapter_map()/gst_adapter_unmap() +and/or gst_adapter_copy(). After the data has been processed, it is freed +using gst_adapter_unmap().

+

Other methods such as gst_adapter_take() and gst_adapter_take_buffer() +combine gst_adapter_map() and gst_adapter_unmap() in one method and are +potentially more convenient for some use cases.

+

For example, a sink pad's chain function that needs to pass data to a library +in 512-byte chunks could be implemented like this:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
static GstFlowReturn
+sink_pad_chain (GstPad *pad, GstObject *parent, GstBuffer *buffer)
+{
+  MyElement *this;
+  GstAdapter *adapter;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  this = MY_ELEMENT (parent);
+
+  adapter = this->adapter;
+
+  // put buffer into adapter
+  gst_adapter_push (adapter, buffer);
+
+  // while we can read out 512 bytes, process them
+  while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) {
+    const guint8 *data = gst_adapter_map (adapter, 512);
+    // use flowreturn as an error value
+    ret = my_library_foo (data);
+    gst_adapter_unmap (adapter);
+    gst_adapter_flush (adapter, 512);
+  }
+  return ret;
+}
+
+ +

+

For another example, a simple element inside GStreamer that uses GstAdapter +is the libvisual element.

+

An element using GstAdapter in its sink pad chain function should ensure that +when the FLUSH_STOP event is received, that any queued data is cleared using +gst_adapter_clear(). Data should also be cleared or processed on EOS and +when changing state from GST_STATE_PAUSED to GST_STATE_READY.

+

Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might +need to clear the adapter after a discontinuity.

+

The adapter will keep track of the timestamps of the buffers +that were pushed. The last seen timestamp before the current position +can be queried with gst_adapter_prev_pts(). This function can +optionally return the number of bytes between the start of the buffer that +carried the timestamp and the current adapter position. The distance is +useful when dealing with, for example, raw audio samples because it allows +you to calculate the timestamp of the current adapter position by using the +last seen timestamp and the amount of bytes since. Additionally, the +gst_adapter_prev_pts_at_offset() can be used to determine the last +seen timestamp at a particular offset in the adapter.

+

The adapter will also keep track of the offset of the buffers +(GST_BUFFER_OFFSET) that were pushed. The last seen offset before the +current position can be queried with gst_adapter_prev_offset(). This function +can optionally return the number of bytes between the start of the buffer +that carried the offset and the current adapter position.

+

Additionally the adapter also keeps track of the PTS, DTS and buffer offset +at the last discontinuity, which can be retrieved with +gst_adapter_pts_at_discont(), gst_adapter_dts_at_discont() and +gst_adapter_offset_at_discont(). The number of bytes that were consumed +since then can be queried with gst_adapter_distance_from_discont().

+

A last thing to note is that while GstAdapter is pretty optimized, +merging buffers still might be an operation that requires a malloc() and +memcpy() operation, and these operations are not the fastest. Because of +this, some functions like gst_adapter_available_fast() are provided to help +speed up such cases should you want to. To avoid repeated memory allocations, +gst_adapter_copy() can be used to copy data into a (statically allocated) +user provided buffer.

+

GstAdapter is not MT safe. All operations on an adapter must be serialized by +the caller. This is not normally a problem, however, as the normal use case +of GstAdapter is inside one pad's chain function, in which case access is +serialized via the pad's STREAM_LOCK.

+

Note that gst_adapter_push() takes ownership of the buffer passed. Use +gst_buffer_ref() before pushing it into the adapter if you still want to +access the buffer later. The adapter will never modify the data in the +buffer pushed in it.

+
+
+

Functions

+
+

gst_adapter_new ()

+
GstAdapter *
+gst_adapter_new (void);
+

Creates a new GstAdapter. Free with g_object_unref().

+
+

Returns

+

a new GstAdapter.

+

[transfer full]

+
+
+
+
+

gst_adapter_clear ()

+
void
+gst_adapter_clear (GstAdapter *adapter);
+

Removes all buffers from adapter +.

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+
+
+

gst_adapter_push ()

+
void
+gst_adapter_push (GstAdapter *adapter,
+                  GstBuffer *buf);
+

Adds the data from buf + to the data stored inside adapter + and takes +ownership of the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

buf

a GstBuffer to add to queue in the adapter.

[transfer full]
+
+
+
+
+

gst_adapter_map ()

+
gconstpointer
+gst_adapter_map (GstAdapter *adapter,
+                 gsize size);
+

Gets the first size + bytes stored in the adapter +. The returned pointer is +valid until the next function is called on the adapter.

+

Note that setting the returned pointer as the data of a GstBuffer is +incorrect for general-purpose plugins. The reason is that if a downstream +element stores the buffer so that it has access to it outside of the bounds +of its chain function, the buffer will have an invalid data pointer after +your element flushes the bytes. In that case you should use +gst_adapter_take(), which returns a freshly-allocated buffer that you can set +as GstBuffer memory or the potentially more performant +gst_adapter_take_buffer().

+

Returns NULL if size + bytes are not available.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

size

the number of bytes to map/peek

 
+
+
+

Returns

+

a pointer to the first size +bytes of data, or NULL.

+

[transfer none][array length=size][element-type guint8][nullable]

+
+
+
+
+

gst_adapter_unmap ()

+
void
+gst_adapter_unmap (GstAdapter *adapter);
+

Releases the memory obtained with the last gst_adapter_map().

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+
+
+

gst_adapter_copy ()

+
void
+gst_adapter_copy (GstAdapter *adapter,
+                  gpointer dest,
+                  gsize offset,
+                  gsize size);
+

Copies size + bytes of data starting at offset + out of the buffers +contained in GstAdapter into an array dest + provided by the caller.

+

The array dest + should be large enough to contain size + bytes. +The user should check that the adapter has (offset + + size +) bytes +available before calling this function.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

dest

the memory to copy into.

[out caller-allocates][array length=size][element-type guint8]

offset

the bytes offset in the adapter to start from

 

size

the number of bytes to copy

 
+
+
+
+
+

gst_adapter_copy_bytes ()

+
GBytes *
+gst_adapter_copy_bytes (GstAdapter *adapter,
+                        gsize offset,
+                        gsize size);
+

Similar to gst_adapter_copy, but more suitable for language bindings. size + +bytes of data starting at offset + will be copied out of the buffers contained +in adapter + and into a new GBytes structure which is returned. Depending on +the value of the size + argument an empty GBytes structure may be returned.

+

[rename-to gst_adapter_copy]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

offset

the bytes offset in the adapter to start from

 

size

the number of bytes to copy

 
+
+
+

Returns

+

A new GBytes structure containing the copied data.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_adapter_flush ()

+
void
+gst_adapter_flush (GstAdapter *adapter,
+                   gsize flush);
+

Flushes the first flush + bytes in the adapter +. The caller must ensure that +at least this many bytes are available.

+

See also: gst_adapter_map(), gst_adapter_unmap()

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

flush

the number of bytes to flush

 
+
+
+
+
+

gst_adapter_available ()

+
gsize
+gst_adapter_available (GstAdapter *adapter);
+

Gets the maximum amount of bytes available, that is it returns the maximum +value that can be supplied to gst_adapter_map() without that function +returning NULL.

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+

Returns

+

number of bytes available in adapter +

+
+
+
+
+

gst_adapter_available_fast ()

+
gsize
+gst_adapter_available_fast (GstAdapter *adapter);
+

Gets the maximum number of bytes that are immediately available without +requiring any expensive operations (like copying the data into a +temporary buffer).

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+

Returns

+

number of bytes that are available in adapter +without expensive +operations

+
+
+
+
+

gst_adapter_take ()

+
gpointer
+gst_adapter_take (GstAdapter *adapter,
+                  gsize nbytes);
+

Returns a freshly allocated buffer containing the first nbytes + bytes of the +adapter +. The returned bytes will be flushed from the adapter.

+

Caller owns returned value. g_free after usage.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to take

 
+
+
+

Returns

+

oven-fresh hot data, or NULL if nbytes +bytes are not available.

+

[transfer full][array length=nbytes][element-type guint8][nullable]

+
+
+
+
+

gst_adapter_take_buffer ()

+
GstBuffer *
+gst_adapter_take_buffer (GstAdapter *adapter,
+                         gsize nbytes);
+

Returns a GstBuffer containing the first nbytes + bytes of the +adapter +. The returned bytes will be flushed from the adapter. +This function is potentially more performant than +gst_adapter_take() since it can reuse the memory in pushed buffers +by subbuffering or merging. This function will always return a +buffer with a single memory region.

+

Note that no assumptions should be made as to whether certain buffer +flags such as the DISCONT flag are set on the returned buffer, or not. +The caller needs to explicitly set or unset flags that should be set or +unset.

+

Since 1.6 this will also copy over all GstMeta of the input buffers except +for meta with the GST_META_FLAG_POOLED flag or with the "memory" tag.

+

Caller owns a reference to the returned buffer. gst_buffer_unref() after +usage.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to take

 
+
+
+

Returns

+

a GstBuffer containing the first +nbytes +of the adapter, or NULL if nbytes +bytes are not available. +gst_buffer_unref() when no longer needed.

+

[transfer full][nullable]

+
+
+
+
+

gst_adapter_get_buffer ()

+
GstBuffer *
+gst_adapter_get_buffer (GstAdapter *adapter,
+                        gsize nbytes);
+

Returns a GstBuffer containing the first nbytes + of the adapter +, but +does not flush them from the adapter. See gst_adapter_take_buffer() +for details.

+

Caller owns a reference to the returned buffer. gst_buffer_unref() after +usage.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to get

 
+
+
+

Returns

+

a GstBuffer containing the first +nbytes +of the adapter, or NULL if nbytes +bytes are not available. +gst_buffer_unref() when no longer needed.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_adapter_take_buffer_fast ()

+
GstBuffer *
+gst_adapter_take_buffer_fast (GstAdapter *adapter,
+                              gsize nbytes);
+

Returns a GstBuffer containing the first nbytes + of the adapter +. +The returned bytes will be flushed from the adapter. This function +is potentially more performant than gst_adapter_take_buffer() since +it can reuse the memory in pushed buffers by subbuffering or +merging. Unlike gst_adapter_take_buffer(), the returned buffer may +be composed of multiple non-contiguous GstMemory objects, no +copies are made.

+

Note that no assumptions should be made as to whether certain buffer +flags such as the DISCONT flag are set on the returned buffer, or not. +The caller needs to explicitly set or unset flags that should be set or +unset.

+

This will also copy over all GstMeta of the input buffers except +for meta with the GST_META_FLAG_POOLED flag or with the "memory" tag.

+

This function can return buffer up to the return value of +gst_adapter_available() without making copies if possible.

+

Caller owns a reference to the returned buffer. gst_buffer_unref() after +usage.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to take

 
+
+
+

Returns

+

a GstBuffer containing the first +nbytes +of the adapter, or NULL if nbytes +bytes are not available. +gst_buffer_unref() when no longer needed.

+

[transfer full][nullable]

+
+

Since: 1.2

+
+
+
+

gst_adapter_get_buffer_fast ()

+
GstBuffer *
+gst_adapter_get_buffer_fast (GstAdapter *adapter,
+                             gsize nbytes);
+

Returns a GstBuffer containing the first nbytes + of the adapter +, but +does not flush them from the adapter. See gst_adapter_take_buffer_fast() +for details.

+

Caller owns a reference to the returned buffer. gst_buffer_unref() after +usage.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to get

 
+
+
+

Returns

+

a GstBuffer containing the first +nbytes +of the adapter, or NULL if nbytes +bytes are not available. +gst_buffer_unref() when no longer needed.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_adapter_take_list ()

+
GList *
+gst_adapter_take_list (GstAdapter *adapter,
+                       gsize nbytes);
+

Returns a GList of buffers containing the first nbytes + bytes of the +adapter +. The returned bytes will be flushed from the adapter. +When the caller can deal with individual buffers, this function is more +performant because no memory should be copied.

+

Caller owns returned list and contained buffers. gst_buffer_unref() each +buffer in the list before freeing the list after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to take

 
+
+
+

Returns

+

a GList of +buffers containing the first nbytes +of the adapter, or NULL if nbytes +bytes are not available.

+

[element-type Gst.Buffer][transfer full][nullable]

+
+
+
+
+

gst_adapter_get_list ()

+
GList *
+gst_adapter_get_list (GstAdapter *adapter,
+                      gsize nbytes);
+

Returns a GList of buffers containing the first nbytes + bytes of the +adapter +, but does not flush them from the adapter. See +gst_adapter_take_list() for details.

+

Caller owns returned list and contained buffers. gst_buffer_unref() each +buffer in the list before freeing the list after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to get

 
+
+
+

Returns

+

a GList of +buffers containing the first nbytes +of the adapter, or NULL if nbytes +bytes are not available.

+

[element-type Gst.Buffer][transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_adapter_take_buffer_list ()

+
GstBufferList *
+gst_adapter_take_buffer_list (GstAdapter *adapter,
+                              gsize nbytes);
+

Returns a GstBufferList of buffers containing the first nbytes + bytes of +the adapter +. The returned bytes will be flushed from the adapter. +When the caller can deal with individual buffers, this function is more +performant because no memory should be copied.

+

Caller owns the returned list. Call gst_buffer_list_unref() to free +the list after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to take

 
+
+
+

Returns

+

a GstBufferList of buffers containing +the first nbytes +of the adapter, or NULL if nbytes +bytes are not +available.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_adapter_get_buffer_list ()

+
GstBufferList *
+gst_adapter_get_buffer_list (GstAdapter *adapter,
+                             gsize nbytes);
+

Returns a GstBufferList of buffers containing the first nbytes + bytes of +the adapter + but does not flush them from the adapter. See +gst_adapter_take_buffer_list() for details.

+

Caller owns the returned list. Call gst_buffer_list_unref() to free +the list after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

nbytes

the number of bytes to get

 
+
+
+

Returns

+

a GstBufferList of buffers containing +the first nbytes +of the adapter, or NULL if nbytes +bytes are not +available.

+

[transfer full][nullable]

+
+

Since: 1.6

+
+
+
+

gst_adapter_prev_pts ()

+
GstClockTime
+gst_adapter_prev_pts (GstAdapter *adapter,
+                      guint64 *distance);
+

Get the pts that was before the current byte in the adapter. When +distance + is given, the amount of bytes between the pts and the current +position is returned.

+

The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when +the adapter is first created or when it is cleared. This also means that before +the first byte with a pts is removed from the adapter, the pts +and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

distance

pointer to location for distance, or NULL.

[out][allow-none]
+
+
+

Returns

+

The previously seen pts.

+
+
+
+
+

gst_adapter_prev_dts ()

+
GstClockTime
+gst_adapter_prev_dts (GstAdapter *adapter,
+                      guint64 *distance);
+

Get the dts that was before the current byte in the adapter. When +distance + is given, the amount of bytes between the dts and the current +position is returned.

+

The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when +the adapter is first created or when it is cleared. This also means that before +the first byte with a dts is removed from the adapter, the dts +and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

distance

pointer to location for distance, or NULL.

[out][allow-none]
+
+
+

Returns

+

The previously seen dts.

+
+
+
+
+

gst_adapter_prev_pts_at_offset ()

+
GstClockTime
+gst_adapter_prev_pts_at_offset (GstAdapter *adapter,
+                                gsize offset,
+                                guint64 *distance);
+

Get the pts that was before the byte at offset offset + in the adapter. When +distance + is given, the amount of bytes between the pts and the current +position is returned.

+

The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when +the adapter is first created or when it is cleared. This also means that before +the first byte with a pts is removed from the adapter, the pts +and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

offset

the offset in the adapter at which to get timestamp

 

distance

pointer to location for distance, or NULL.

[out][allow-none]
+
+
+

Returns

+

The previously seen pts at given offset.

+
+

Since: 1.2

+
+
+
+

gst_adapter_prev_dts_at_offset ()

+
GstClockTime
+gst_adapter_prev_dts_at_offset (GstAdapter *adapter,
+                                gsize offset,
+                                guint64 *distance);
+

Get the dts that was before the byte at offset offset + in the adapter. When +distance + is given, the amount of bytes between the dts and the current +position is returned.

+

The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when +the adapter is first created or when it is cleared. This also means that before +the first byte with a dts is removed from the adapter, the dts +and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

offset

the offset in the adapter at which to get timestamp

 

distance

pointer to location for distance, or NULL.

[out][allow-none]
+
+
+

Returns

+

The previously seen dts at given offset.

+
+

Since: 1.2

+
+
+
+

gst_adapter_prev_offset ()

+
guint64
+gst_adapter_prev_offset (GstAdapter *adapter,
+                         guint64 *distance);
+

Get the offset that was before the current byte in the adapter. When +distance + is given, the amount of bytes between the offset and the current +position is returned.

+

The offset is reset to GST_BUFFER_OFFSET_NONE and the distance is set to 0 +when the adapter is first created or when it is cleared. This also means that +before the first byte with an offset is removed from the adapter, the offset +and distance returned are GST_BUFFER_OFFSET_NONE and 0 respectively.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

adapter

a GstAdapter

 

distance

pointer to a location for distance, or NULL.

[out][allow-none]
+
+
+

Returns

+

The previous seen offset.

+
+

Since: 1.10

+
+
+
+

gst_adapter_pts_at_discont ()

+
GstClockTime
+gst_adapter_pts_at_discont (GstAdapter *adapter);
+

Get the PTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT +flag, or GST_CLOCK_TIME_NONE.

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+

Returns

+

The PTS at the last discont or GST_CLOCK_TIME_NONE.

+
+

Since: 1.10

+
+
+
+

gst_adapter_dts_at_discont ()

+
GstClockTime
+gst_adapter_dts_at_discont (GstAdapter *adapter);
+

Get the DTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT +flag, or GST_CLOCK_TIME_NONE.

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+

Returns

+

The DTS at the last discont or GST_CLOCK_TIME_NONE.

+
+

Since: 1.10

+
+
+
+

gst_adapter_offset_at_discont ()

+
guint64
+gst_adapter_offset_at_discont (GstAdapter *adapter);
+

Get the offset that was on the last buffer with the GST_BUFFER_FLAG_DISCONT +flag, or GST_BUFFER_OFFSET_NONE.

+
+

Parameters

+
+++++ + + + + + +

adapter

a GstAdapter

 
+
+
+

Returns

+

The offset at the last discont or GST_BUFFER_OFFSET_NONE.

+
+

Since: 1.10

+
+
+
+

gst_adapter_distance_from_discont ()

+
guint64
+gst_adapter_distance_from_discont (GstAdapter *adapter);
+
+
+
+

gst_adapter_masked_scan_uint32 ()

+
gssize
+gst_adapter_masked_scan_uint32 (GstAdapter *adapter,
+                                guint32 mask,
+                                guint32 pattern,
+                                gsize offset,
+                                gsize size);
+

Scan for pattern pattern + with applied mask mask + in the adapter data, +starting from offset offset +.

+

The bytes in pattern + and mask + are interpreted left-to-right, regardless +of endianness. All four bytes of the pattern must be present in the +adapter for it to match, even if the first or last bytes are masked out.

+

It is an error to call this function without making sure that there is +enough data (offset+size bytes) in the adapter.

+

This function calls gst_adapter_masked_scan_uint32_peek() passing NULL +for value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

mask

mask to apply to data before matching against pattern +

 

pattern

pattern to match (after mask is applied)

 

offset

offset into the adapter data from which to start scanning, returns +the last scanned position.

 

size

number of bytes to scan from offset

 
+
+
+

Returns

+

offset of the first match, or -1 if no match was found.

+

Example:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
// Assume the adapter contains 0x00 0x01 0x02 ... 0xfe 0xff
+gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 256);
+// -> returns 0
+gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 1, 255);
+// -> returns -1
+gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 255);
+// -> returns 1
+gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0001, 0, 256);
+// -> returns -1
+gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0203, 0, 256);
+// -> returns 0
+gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 256);
+// -> returns 2
+gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 4);
+// -> returns -1
+
+ +

+
+
+
+
+

gst_adapter_masked_scan_uint32_peek ()

+
gssize
+gst_adapter_masked_scan_uint32_peek (GstAdapter *adapter,
+                                     guint32 mask,
+                                     guint32 pattern,
+                                     gsize offset,
+                                     gsize size,
+                                     guint32 *value);
+

Scan for pattern pattern + with applied mask mask + in the adapter data, +starting from offset offset +. If a match is found, the value that matched +is returned through value +, otherwise value + is left untouched.

+

The bytes in pattern + and mask + are interpreted left-to-right, regardless +of endianness. All four bytes of the pattern must be present in the +adapter for it to match, even if the first or last bytes are masked out.

+

It is an error to call this function without making sure that there is +enough data (offset+size bytes) in the adapter.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

adapter

a GstAdapter

 

mask

mask to apply to data before matching against pattern +

 

pattern

pattern to match (after mask is applied)

 

offset

offset into the adapter data from which to start scanning, returns +the last scanned position.

 

size

number of bytes to scan from offset

 

value

pointer to uint32 to return matching data.

[out][allow-none]
+
+
+

Returns

+

offset of the first match, or -1 if no match was found.

+
+
+
+
+

Types and Values

+
+

GstAdapter

+
typedef struct _GstAdapter GstAdapter;
+

The opaque GstAdapter data structure.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstAggregator.html b/docs/libs/html/GstAggregator.html new file mode 100644 index 0000000..919f828 --- /dev/null +++ b/docs/libs/html/GstAggregator.html @@ -0,0 +1,636 @@ + + + + +GstAggregator: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstAggregator

+

GstAggregator — Base class for mixers and muxers, manages a set of input + pads and aggregates their streams

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+GstFlowReturn + +gst_aggregator_finish_buffer () +
+void + +gst_aggregator_set_src_caps () +
+GstClockTime + +gst_aggregator_get_latency () +
+GstBufferPool * + +gst_aggregator_get_buffer_pool () +
+void + +gst_aggregator_get_allocator () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
guint64latencyRead / Write
guint64start-timeRead / Write
GstAggregatorStartTimeSelectionstart-time-selectionRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstAggregator
structGstAggregatorClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstAggregator
+
+
+
+

Includes

+
#include <gst/base/base.h>
+
+
+
+

Description

+

Manages a set of pads with the purpose of aggregating their buffers. +Control is given to the subclass when all pads have data.

+
    +
  • Base class for mixers and muxers. Subclasses should at least implement +the GstAggregatorClass.aggregate() virtual method.

  • +
  • Installs a GstPadChainFunction, a GstPadEventFullFunction and a +GstPadQueryFunction to queue all serialized data packets per sink pad. +Subclasses should not overwrite those, but instead implement +GstAggregatorClass.sink_event() and GstAggregatorClass.sink_query() as +needed.

  • +
  • When data is queued on all pads, the aggregate vmethod is called.

  • +
  • One can peek at the data on any given GstAggregatorPad with the +gst_aggregator_pad_peek_buffer() method, and remove it from the pad +with the gst_aggregator_pad_pop_buffer() method. When a buffer +has been taken with pop_buffer(), a new buffer can be queued +on that pad.

  • +
  • If the subclass wishes to push a buffer downstream in its aggregate +implementation, it should do so through the +gst_aggregator_finish_buffer() method. This method will take care +of sending and ordering mandatory events such as stream start, caps +and segment.

  • +
  • Same goes for EOS events, which should not be pushed directly by the +subclass, it should instead return GST_FLOW_EOS in its aggregate +implementation.

  • +
  • Note that the aggregator logic regarding gap event handling is to turn +these into gap buffers with matching PTS and duration. It will also +flag these buffers with GST_BUFFER_FLAG_GAP and GST_BUFFER_FLAG_DROPPABLE +to ease their identification and subsequent processing.

  • +
  • Subclasses must use (a subclass of) GstAggregatorPad for both their +sink and source pads. +See gst_element_class_add_static_pad_template_with_gtype().

  • +
+

This class used to live in gst-plugins-bad and was moved to core.

+
+
+

Functions

+
+

gst_aggregator_finish_buffer ()

+
GstFlowReturn
+gst_aggregator_finish_buffer (GstAggregator *aggregator,
+                              GstBuffer *buffer);
+

This method will push the provided output buffer downstream. If needed, +mandatory events such as stream-start, caps, and segment events will be +sent before pushing the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

aggregator

The GstAggregator

 

buffer

the GstBuffer to push.

[transfer full]
+
+
+
+
+

gst_aggregator_set_src_caps ()

+
void
+gst_aggregator_set_src_caps (GstAggregator *self,
+                             GstCaps *caps);
+

Sets the caps to be used on the src pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

The GstAggregator

 

caps

The GstCaps to set on the src pad.

 
+
+
+
+
+

gst_aggregator_get_latency ()

+
GstClockTime
+gst_aggregator_get_latency (GstAggregator *self);
+

Retrieves the latency values reported by self + in response to the latency +query, or GST_CLOCK_TIME_NONE if there is not live source connected and the element +will not wait for the clock.

+

Typically only called by subclasses.

+
+

Parameters

+
+++++ + + + + + +

self

a GstAggregator

 
+
+
+

Returns

+

The latency or GST_CLOCK_TIME_NONE if the element does not sync

+
+
+
+
+

gst_aggregator_get_buffer_pool ()

+
GstBufferPool *
+gst_aggregator_get_buffer_pool (GstAggregator *self);
+
+

Parameters

+
+++++ + + + + + +

self

a GstAggregator

 
+
+
+

Returns

+

the instance of the GstBufferPool used +by trans +; free it after use it.

+

[transfer full]

+
+
+
+
+

gst_aggregator_get_allocator ()

+
void
+gst_aggregator_get_allocator (GstAggregator *self,
+                              GstAllocator **allocator,
+                              GstAllocationParams *params);
+

Lets GstAggregator sub-classes get the memory allocator + +acquired by the base class and its params +.

+

Unref the allocator + after use it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

a GstAggregator

 

allocator

the GstAllocator +used.

[out][allow-none][transfer full]

params

the +GstAllocationParams of allocator +.

[out][allow-none][transfer full]
+
+
+
+
+

Types and Values

+
+

struct GstAggregator

+
struct GstAggregator;
+

Aggregator base class object structure.

+
+

Members

+
+++++ + +
+
+
+
+
+

struct GstAggregatorClass

+
struct GstAggregatorClass {
+  GstElementClass   parent_class;
+
+  GstFlowReturn     (*flush)          (GstAggregator    *  aggregator);
+
+  GstBuffer *       (*clip)           (GstAggregator    *  aggregator,
+                                       GstAggregatorPad *  aggregator_pad,
+                                       GstBuffer        *  buf);
+
+  GstFlowReturn     (*finish_buffer)  (GstAggregator    * aggregator,
+                                       GstBuffer        * buffer);
+
+  /* sinkpads virtual methods */
+  gboolean          (*sink_event)     (GstAggregator    *  aggregator,
+                                       GstAggregatorPad *  aggregator_pad,
+                                       GstEvent         *  event);
+
+  gboolean          (*sink_query)     (GstAggregator    *  aggregator,
+                                       GstAggregatorPad *  aggregator_pad,
+                                       GstQuery         *  query);
+
+  /* srcpad virtual methods */
+  gboolean          (*src_event)      (GstAggregator    *  aggregator,
+                                       GstEvent         *  event);
+
+  gboolean          (*src_query)      (GstAggregator    *  aggregator,
+                                       GstQuery         *  query);
+
+  gboolean          (*src_activate)   (GstAggregator    *  aggregator,
+                                       GstPadMode          mode,
+                                       gboolean            active);
+
+  GstFlowReturn     (*aggregate)      (GstAggregator    *  aggregator,
+                                       gboolean            timeout);
+
+  gboolean          (*stop)           (GstAggregator    *  aggregator);
+
+  gboolean          (*start)          (GstAggregator    *  aggregator);
+
+  GstClockTime      (*get_next_time)  (GstAggregator    *  aggregator);
+
+  GstAggregatorPad * (*create_new_pad) (GstAggregator  * self,
+                                        GstPadTemplate * templ,
+                                        const gchar    * req_name,
+                                        const GstCaps  * caps);
+  GstFlowReturn     (*update_src_caps) (GstAggregator *  self,
+                                        GstCaps       *  caps,
+                                        GstCaps       ** ret);
+  GstCaps *         (*fixate_src_caps) (GstAggregator *  self,
+                                        GstCaps       *  caps);
+  gboolean          (*negotiated_src_caps) (GstAggregator *  self,
+                                            GstCaps      *  caps);
+  gboolean          (*decide_allocation) (GstAggregator * self,
+                                          GstQuery * query);
+  gboolean          (*propose_allocation) (GstAggregator * self,
+                                           GstAggregatorPad * pad,
+                                           GstQuery * decide_query,
+                                           GstQuery * query);
+};
+
+

The aggregator base class will handle in a thread-safe way all manners of +concurrent flushes, seeks, pad additions and removals, leaving to the +subclass the responsibility of clipping buffers, and aggregating buffers in +the way the implementor sees fit.

+

It will also take care of event ordering (stream-start, segment, eos).

+

Basically, a simple implementation will override aggregate +, and call +_finish_buffer from inside that function.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

flush ()

Optional. +Called after a successful flushing seek, once all the flush +stops have been received. Flush pad-specific data in +GstAggregatorPad->flush.

 

clip ()

Optional. +Called when a buffer is received on a sink pad, the task of +clipping it and translating it to the current segment falls +on the subclass. The function should use the segment of data +and the negotiated media type on the pad to perform +clipping of input buffer. This function takes ownership of +buf and should output a buffer or return NULL in +if the buffer should be dropped.

 

finish_buffer ()

Optional. +Called when a subclass calls gst_aggregator_finish_buffer() +from their aggregate function to push out a buffer. +Subclasses can override this to modify or decorate buffers +before they get pushed out. This function takes ownership +of the buffer passed. Subclasses that override this method +should always chain up to the parent class virtual method.

 

sink_event ()

Optional. +Called when an event is received on a sink pad, the subclass +should always chain up.

 

sink_query ()

Optional. +Called when a query is received on a sink pad, the subclass +should always chain up.

 

src_event ()

Optional. +Called when an event is received on the src pad, the subclass +should always chain up.

 

src_query ()

Optional. +Called when a query is received on the src pad, the subclass +should always chain up.

 

src_activate ()

Optional. +Called when the src pad is activated, it will start/stop its +pad task right after that call.

 

aggregate ()

Mandatory. +Called when buffers are queued on all sinkpads. Classes +should iterate the GstElement->sinkpads and peek or steal +buffers from the GstAggregatorPads. If the subclass returns +GST_FLOW_EOS, sending of the eos event will be taken care +of. Once / if a buffer has been constructed from the +aggregated buffers, the subclass should call _finish_buffer.

 

stop ()

Optional. +Called when the element goes from PAUSED to READY. +The subclass should free all resources and reset its state.

 

start ()

Optional. +Called when the element goes from READY to PAUSED. +The subclass should get ready to process +aggregated buffers.

 

get_next_time ()

Optional. +Called when the element needs to know the running time of the next +rendered buffer for live pipelines. This causes deadline +based aggregation to occur. Defaults to returning +GST_CLOCK_TIME_NONE causing the element to wait for buffers +on all sink pads before aggregating.

 

create_new_pad ()

  

update_src_caps ()

Lets subclasses update the GstCaps representing +the src pad caps before usage. The result should end up +in ret +. Return GST_AGGREGATOR_FLOW_NEED_DATA to indicate that the +element needs more information (caps, a buffer, etc) to +choose the correct caps. Should return ANY caps if the +stream has not caps at all.

 

fixate_src_caps ()

Optional. +Fixate and return the src pad caps provided. The function takes +ownership of caps +and returns a fixated version of +caps +. caps +is not guaranteed to be writable.

 

negotiated_src_caps ()

Optional. +Notifies subclasses what caps format has been negotiated

 

decide_allocation ()

Optional. +Allows the subclass to influence the allocation choices. +Setup the allocation parameters for allocating output +buffers. The passed in query contains the result of the +downstream allocation query.

 

propose_allocation ()

  
+
+
+
+
+

Property Details

+
+

The “latency” property

+
  “latency”                  guint64
+

Additional latency in live mode to allow upstream to take longer to produce buffers for the current position (in nanoseconds).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “start-time” property

+
  “start-time”               guint64
+

Start time to use if start-time-selection=set.

+

Flags: Read / Write

+

Default value: 18446744073709551615

+
+
+
+

The “start-time-selection” property

+
  “start-time-selection”     GstAggregatorStartTimeSelection
+

Decides which start time is output.

+

Flags: Read / Write

+

Default value: Start at 0 running time (default)

+
+
+
+

See Also

+

gstcollectpads for historical reasons.

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstAggregatorPad.html b/docs/libs/html/GstAggregatorPad.html new file mode 100644 index 0000000..2a038d2 --- /dev/null +++ b/docs/libs/html/GstAggregatorPad.html @@ -0,0 +1,329 @@ + + + + +GstAggregatorPad: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstAggregatorPad

+

GstAggregatorPad — GstPad subclass for pads managed by GstAggregator

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstAggregatorPad
structGstAggregatorPadClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstPad
+                ╰── GstAggregatorPad
+
+
+
+

Includes

+
#include <gst/base/base.h>
+
+
+
+

Description

+

Pads managed by a GstAggregor subclass.

+

This class used to live in gst-plugins-bad and was moved to core.

+
+
+

Functions

+
+

gst_aggregator_pad_pop_buffer ()

+
GstBuffer *
+gst_aggregator_pad_pop_buffer (GstAggregatorPad *pad);
+

Steal the ref to the buffer currently queued in pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

the pad to get buffer from

 
+
+
+

Returns

+

The buffer in pad +or NULL if no buffer was +queued. You should unref the buffer after usage.

+

[transfer full]

+
+
+
+
+

gst_aggregator_pad_peek_buffer ()

+
GstBuffer *
+gst_aggregator_pad_peek_buffer (GstAggregatorPad *pad);
+
+

Parameters

+
+++++ + + + + + +

pad

the pad to get buffer from

 
+
+
+

Returns

+

A reference to the buffer in pad +or +NULL if no buffer was queued. You should unref the buffer after +usage.

+

[transfer full]

+
+
+
+
+

gst_aggregator_pad_drop_buffer ()

+
gboolean
+gst_aggregator_pad_drop_buffer (GstAggregatorPad *pad);
+

Drop the buffer currently queued in pad +.

+
+

Parameters

+
+++++ + + + + + +

pad

the pad where to drop any pending buffer

 
+
+
+

Returns

+

TRUE if there was a buffer queued in pad +, or FALSE if not.

+
+
+
+
+

gst_aggregator_pad_is_eos ()

+
gboolean
+gst_aggregator_pad_is_eos (GstAggregatorPad *pad);
+
+

Parameters

+
+++++ + + + + + +

pad

an aggregator pad

 
+
+
+

Returns

+

TRUE if the pad is EOS, otherwise FALSE.

+
+
+
+
+

gst_aggregator_pad_has_buffer ()

+
gboolean
+gst_aggregator_pad_has_buffer (GstAggregatorPad *pad);
+
+

Parameters

+
+++++ + + + + + +

pad

the pad to check the buffer on

 
+
+
+

Returns

+

TRUE if the pad has a buffer available as the next thing.

+
+

Since: 1.14.1

+
+
+
+

Types and Values

+
+

struct GstAggregatorPad

+
struct GstAggregatorPad;
+

The implementation the GstPad to use with GstAggregator

+
+

Members

+
+++++ + +
+
+
+
+
+

struct GstAggregatorPadClass

+
struct GstAggregatorPadClass {
+  GstPadClass   parent_class;
+
+  GstFlowReturn (*flush)       (GstAggregatorPad * aggpad, GstAggregator * aggregator);
+  gboolean      (*skip_buffer) (GstAggregatorPad * aggpad, GstAggregator * aggregator, GstBuffer * buffer);
+};
+
+
+

Members

+
+++++ + + + + + + + + + + + + +

flush ()

Optional +Called when the pad has received a flush stop, this is the place +to flush any information specific to the pad, it allows for individual +pads to be flushed while others might not be.

 

skip_buffer ()

Optional +Called before input buffers are queued in the pad, return TRUE +if the buffer should be skipped.

 
+
+
+
+
+

See Also

+

gstcollectpads for historical reasons.

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstBaseParse.html b/docs/libs/html/GstBaseParse.html new file mode 100644 index 0000000..0284ded --- /dev/null +++ b/docs/libs/html/GstBaseParse.html @@ -0,0 +1,1649 @@ + + + + +GstBaseParse: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBaseParse

+

GstBaseParse — Base class for stream parsers

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +gst_base_parse_merge_tags () +
+void + +gst_base_parse_set_duration () +
+void + +gst_base_parse_set_average_bitrate () +
+void + +gst_base_parse_set_min_frame_size () +
+void + +gst_base_parse_set_passthrough () +
+void + +gst_base_parse_set_syncable () +
+void + +gst_base_parse_set_has_timing_info () +
+void + +gst_base_parse_drain () +
+void + +gst_base_parse_set_frame_rate () +
+void + +gst_base_parse_set_latency () +
+void + +gst_base_parse_set_infer_ts () +
+void + +gst_base_parse_set_pts_interpolation () +
+void + +gst_base_parse_set_ts_at_offset () +
+gboolean + +gst_base_parse_convert_default () +
+gboolean + +gst_base_parse_add_index_entry () +
+GstBaseParseFrame * + +gst_base_parse_frame_new () +
+void + +gst_base_parse_frame_init () +
+void + +gst_base_parse_frame_free () +
+GstFlowReturn + +gst_base_parse_push_frame () +
+GstFlowReturn + +gst_base_parse_finish_frame () +
#define +GST_BASE_PARSE_DRAINING() +
#define +GST_BASE_PARSE_LOST_SYNC() +
#define +GST_BASE_PARSE_SINK_PAD() +
#define +GST_BASE_PARSE_SRC_PAD() +
+
+
+

Properties

+
+++++ + + + + + +
gbooleandisable-passthroughRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structGstBaseParse
structGstBaseParseClass
 GstBaseParseFrame
enumGstBaseParseFrameFlags
#defineGST_BASE_PARSE_FLAG_DRAINING
#defineGST_BASE_PARSE_FLAG_LOST_SYNC
#defineGST_BASE_PARSE_FLOW_DROPPED
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseParse
+
+
+
+

Includes

+
#include <gst/base/gstbaseparse.h>
+
+
+
+

Description

+

This base class is for parser elements that process data and splits it +into separate audio/video/whatever frames.

+

It provides for:

+
    +
  • provides one sink pad and one source pad

  • +
  • handles state changes

  • +
  • can operate in pull mode or push mode

  • +
  • handles seeking in both modes

  • +
  • handles events (SEGMENT/EOS/FLUSH)

  • +
  • handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT)

  • +
  • handles flushing

  • +
+

The purpose of this base class is to provide the basic functionality of +a parser and share a lot of rather complex code.

+
+

Description of the parsing mechanism:

+
+

Set-up phase

+
    +
  • GstBaseParse calls start + to inform subclass that data processing is +about to start now.

  • +
  • GstBaseParse class calls set_sink_caps + to inform the subclass about +incoming sinkpad caps. Subclass could already set the srcpad caps +accordingly, but this might be delayed until calling +gst_base_parse_finish_frame() with a non-queued frame.

  • +
  • At least at this point subclass needs to tell the GstBaseParse class +how big data chunks it wants to receive (min_frame_size). It can do +this with gst_base_parse_set_min_frame_size().

  • +
  • GstBaseParse class sets up appropriate data passing mode (pull/push) +and starts to process the data.

  • +
+
+
+

Parsing phase

+
    +
  • GstBaseParse gathers at least min_frame_size bytes of data either +by pulling it from upstream or collecting buffers in an internal +GstAdapter.

  • +
  • +

    A buffer of (at least) min_frame_size bytes is passed to subclass with +handle_frame +. Subclass checks the contents and can optionally +return GST_FLOW_OK along with an amount of data to be skipped to find +a valid frame (which will result in a subsequent DISCONT). +If, otherwise, the buffer does not hold a complete frame, +handle_frame + can merely return and will be called again when additional +data is available. In push mode this amounts to an +additional input buffer (thus minimal additional latency), in pull mode +this amounts to some arbitrary reasonable buffer size increase. +Of course, gst_base_parse_set_min_frame_size() could also be used if a +very specific known amount of additional data is required. +If, however, the buffer holds a complete valid frame, it can pass +the size of this frame to gst_base_parse_finish_frame(). +If acting as a converter, it can also merely indicate consumed input data +while simultaneously providing custom output data. +Note that baseclass performs some processing (such as tracking +overall consumed data rate versus duration) for each finished frame, +but other state is only updated upon each call to handle_frame + +(such as tracking upstream input timestamp).

    +

    Subclass is also responsible for setting the buffer metadata +(e.g. buffer timestamp and duration, or keyframe if applicable). +(although the latter can also be done by GstBaseParse if it is +appropriately configured, see below). Frame is provided with +timestamp derived from upstream (as much as generally possible), +duration obtained from configuration (see below), and offset +if meaningful (in pull mode).

    +

    Note that check_valid_frame + might receive any small +amount of input data when leftover data is being drained (e.g. at EOS).

    +
  • +
  • As part of finish frame processing, +just prior to actually pushing the buffer in question, +it is passed to pre_push_frame + which gives subclass yet one +last chance to examine buffer metadata, or to send some custom (tag) +events, or to perform custom (segment) filtering.

  • +
  • During the parsing process GstBaseParseClass will handle both srcpad +and sinkpad events. They will be passed to subclass if event + or +src_event + callbacks have been provided.

  • +
+
+
+

Shutdown phase

+
  • GstBaseParse class calls stop + to inform the subclass that data +parsing will be stopped.

+

Subclass is responsible for providing pad template caps for +source and sink pads. The pads need to be named "sink" and "src". It also +needs to set the fixed caps on srcpad, when the format is ensured (e.g. +when base class calls subclass' set_sink_caps + function).

+

This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So, +subclass conversion routine needs to know that conversion from +GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the +frame number that can be found from the given byte position.

+

GstBaseParse uses subclasses conversion methods also for seeking (or +otherwise uses its own default one, see also below).

+

Subclass start + and stop + functions will be called to inform the beginning +and end of data processing.

+

Things that subclass need to take care of:

+
    +
  • Provide pad templates

  • +
  • Fixate the source pad caps when appropriate

  • +
  • Inform base class how big data chunks should be retrieved. This is +done with gst_base_parse_set_min_frame_size() function.

  • +
  • Examine data chunks passed to subclass with handle_frame + and pass +proper frame(s) to gst_base_parse_finish_frame(), and setting src pad +caps and timestamps on frame.

  • +
  • Provide conversion functions

  • +
  • Update the duration information with gst_base_parse_set_duration()

  • +
  • Optionally passthrough using gst_base_parse_set_passthrough()

  • +
  • Configure various baseparse parameters using +gst_base_parse_set_average_bitrate(), gst_base_parse_set_syncable() +and gst_base_parse_set_frame_rate().

  • +
  • In particular, if subclass is unable to determine a duration, but +parsing (or specs) yields a frames per seconds rate, then this can be +provided to GstBaseParse to enable it to cater for +buffer time metadata (which will be taken from upstream as much as +possible). Internally keeping track of frame durations and respective +sizes that have been pushed provides GstBaseParse with an estimated +bitrate. A default convert + (used if not overridden) will then use these +rates to perform obvious conversions. These rates are also used to +update (estimated) duration at regular frame intervals.

  • +
+
+
+
+
+

Functions

+
+

gst_base_parse_merge_tags ()

+
void
+gst_base_parse_merge_tags (GstBaseParse *parse,
+                           GstTagList *tags,
+                           GstTagMergeMode mode);
+

Sets the parser subclass's tags and how they should be merged with any +upstream stream tags. This will override any tags previously-set +with gst_base_parse_merge_tags().

+

Note that this is provided for convenience, and the subclass is +not required to use this and can still do tag handling on its own.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parse

a GstBaseParse

 

tags

a GstTagList to merge, or NULL to unset +previously-set tags.

[allow-none]

mode

the GstTagMergeMode to use, usually GST_TAG_MERGE_REPLACE

 
+
+

Since: 1.6

+
+
+
+

gst_base_parse_set_duration ()

+
void
+gst_base_parse_set_duration (GstBaseParse *parse,
+                             GstFormat fmt,
+                             gint64 duration,
+                             gint interval);
+

Sets the duration of the currently playing media. Subclass can use this +when it is able to determine duration and/or notices a change in the media +duration. Alternatively, if interval + is non-zero (default), then stream +duration is determined based on estimated bitrate, and updated every interval + +frames.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

parse

GstBaseParse.

 

fmt

GstFormat.

 

duration

duration value.

 

interval

how often to update the duration estimate based on bitrate, or 0.

 
+
+
+
+
+

gst_base_parse_set_average_bitrate ()

+
void
+gst_base_parse_set_average_bitrate (GstBaseParse *parse,
+                                    guint bitrate);
+

Optionally sets the average bitrate detected in media (if non-zero), +e.g. based on metadata, as it will be posted to the application.

+

By default, announced average bitrate is estimated. The average bitrate +is used to estimate the total duration of the stream and to estimate +a seek position, if there's no index and the format is syncable +(see gst_base_parse_set_syncable()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

GstBaseParse.

 

bitrate

average bitrate in bits/second

 
+
+
+
+
+

gst_base_parse_set_min_frame_size ()

+
void
+gst_base_parse_set_min_frame_size (GstBaseParse *parse,
+                                   guint min_size);
+

Subclass can use this function to tell the base class that it needs to +give at least min_size buffers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

GstBaseParse.

 

min_size

Minimum size of the data that this base class should give to +subclass.

 
+
+
+
+
+

gst_base_parse_set_passthrough ()

+
void
+gst_base_parse_set_passthrough (GstBaseParse *parse,
+                                gboolean passthrough);
+

Set if the nature of the format or configuration does not allow (much) +parsing, and the parser should operate in passthrough mode (which only +applies when operating in push mode). That is, incoming buffers are +pushed through unmodified, i.e. no check_valid_frame + or parse_frame + +callbacks will be invoked, but pre_push_frame + will still be invoked, +so subclass can perform as much or as little is appropriate for +passthrough semantics in pre_push_frame +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

passthrough

TRUE if parser should run in passthrough mode

 
+
+
+
+
+

gst_base_parse_set_syncable ()

+
void
+gst_base_parse_set_syncable (GstBaseParse *parse,
+                             gboolean syncable);
+

Set if frame starts can be identified. This is set by default and +determines whether seeking based on bitrate averages +is possible for a format/stream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

syncable

set if frame starts can be identified

 
+
+
+
+
+

gst_base_parse_set_has_timing_info ()

+
void
+gst_base_parse_set_has_timing_info (GstBaseParse *parse,
+                                    gboolean has_timing);
+

Set if frames carry timing information which the subclass can (generally) +parse and provide. In particular, intrinsic (rather than estimated) time +can be obtained following a seek.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

has_timing

whether frames carry timing information

 
+
+
+
+
+

gst_base_parse_drain ()

+
void
+gst_base_parse_drain (GstBaseParse *parse);
+

Drains the adapter until it is empty. It decreases the min_frame_size to +match the current adapter size and calls chain method until the adapter +is emptied or chain returns with error.

+
+

Parameters

+
+++++ + + + + + +

parse

a GstBaseParse

 
+
+

Since: 1.12

+
+
+
+

gst_base_parse_set_frame_rate ()

+
void
+gst_base_parse_set_frame_rate (GstBaseParse *parse,
+                               guint fps_num,
+                               guint fps_den,
+                               guint lead_in,
+                               guint lead_out);
+

If frames per second is configured, parser can take care of buffer duration +and timestamping. When performing segment clipping, or seeking to a specific +location, a corresponding decoder might need an initial lead_in + and a +following lead_out + number of frames to ensure the desired segment is +entirely filled upon decoding.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

parse

the GstBaseParse to set

 

fps_num

frames per second (numerator).

 

fps_den

frames per second (denominator).

 

lead_in

frames needed before a segment for subsequent decode

 

lead_out

frames needed after a segment

 
+
+
+
+
+

gst_base_parse_set_latency ()

+
void
+gst_base_parse_set_latency (GstBaseParse *parse,
+                            GstClockTime min_latency,
+                            GstClockTime max_latency);
+

Sets the minimum and maximum (which may likely be equal) latency introduced +by the parsing process. If there is such a latency, which depends on the +particular parsing of the format, it typically corresponds to 1 frame duration.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parse

a GstBaseParse

 

min_latency

minimum parse latency

 

max_latency

maximum parse latency

 
+
+
+
+
+

gst_base_parse_set_infer_ts ()

+
void
+gst_base_parse_set_infer_ts (GstBaseParse *parse,
+                             gboolean infer_ts);
+

By default, the base class might try to infer PTS from DTS and vice +versa. While this is generally correct for audio data, it may not +be otherwise. Sub-classes implementing such formats should disable +timestamp inferring.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

infer_ts

TRUE if parser should infer DTS/PTS from each other

 
+
+
+
+
+

gst_base_parse_set_pts_interpolation ()

+
void
+gst_base_parse_set_pts_interpolation (GstBaseParse *parse,
+                                      gboolean pts_interpolate);
+

By default, the base class will guess PTS timestamps using a simple +interpolation (previous timestamp + duration), which is incorrect for +data streams with reordering, where PTS can go backward. Sub-classes +implementing such formats should disable PTS interpolation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

pts_interpolate

TRUE if parser should interpolate PTS timestamps

 
+
+
+
+
+

gst_base_parse_set_ts_at_offset ()

+
void
+gst_base_parse_set_ts_at_offset (GstBaseParse *parse,
+                                 gsize offset);
+

This function should only be called from a handle_frame + implementation.

+

GstBaseParse creates initial timestamps for frames by using the last +timestamp seen in the stream before the frame starts. In certain +cases, the correct timestamps will occur in the stream after the +start of the frame, but before the start of the actual picture data. +This function can be used to set the timestamps based on the offset +into the frame data that the picture starts.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

a GstBaseParse

 

offset

offset into current buffer

 
+
+

Since: 1.2

+
+
+
+

gst_base_parse_convert_default ()

+
gboolean
+gst_base_parse_convert_default (GstBaseParse *parse,
+                                GstFormat src_format,
+                                gint64 src_value,
+                                GstFormat dest_format,
+                                gint64 *dest_value);
+

Default implementation of "convert" vmethod in GstBaseParse class.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

parse

GstBaseParse.

 

src_format

GstFormat describing the source format.

 

src_value

Source value to be converted.

 

dest_format

GstFormat defining the converted format.

 

dest_value

Pointer where the conversion result will be put.

[out]
+
+
+

Returns

+

TRUE if conversion was successful.

+
+
+
+
+

gst_base_parse_add_index_entry ()

+
gboolean
+gst_base_parse_add_index_entry (GstBaseParse *parse,
+                                guint64 offset,
+                                GstClockTime ts,
+                                gboolean key,
+                                gboolean force);
+

Adds an entry to the index associating offset + to ts +. It is recommended +to only add keyframe entries. force + allows to bypass checks, such as +whether the stream is (upstream) seekable, another entry is already "close" +to the new entry, etc.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

parse

GstBaseParse.

 

offset

offset of entry

 

ts

timestamp associated with offset

 

key

whether entry refers to keyframe

 

force

add entry disregarding sanity checks

 
+
+
+

Returns

+

gboolean indicating whether entry was added

+
+
+
+
+

gst_base_parse_frame_new ()

+
GstBaseParseFrame *
+gst_base_parse_frame_new (GstBuffer *buffer,
+                          GstBaseParseFrameFlags flags,
+                          gint overhead);
+

Allocates a new GstBaseParseFrame. This function is mainly for bindings, +elements written in C should usually allocate the frame on the stack and +then use gst_base_parse_frame_init() to initialise it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

a GstBuffer.

[transfer none]

flags

the flags

 

overhead

number of bytes in this frame which should be counted as +metadata overhead, ie. not used to calculate the average bitrate. +Set to -1 to mark the entire frame as metadata. If in doubt, set to 0.

 
+
+
+

Returns

+

a newly-allocated GstBaseParseFrame. Free with +gst_base_parse_frame_free() when no longer needed.

+
+
+
+
+

gst_base_parse_frame_init ()

+
void
+gst_base_parse_frame_init (GstBaseParseFrame *frame);
+

Sets a GstBaseParseFrame to initial state. Currently this means +all public fields are zero-ed and a private flag is set to make +sure gst_base_parse_frame_free() only frees the contents but not +the actual frame. Use this function to initialise a GstBaseParseFrame +allocated on the stack.

+
+

Parameters

+
+++++ + + + + + +

frame

GstBaseParseFrame.

 
+
+
+
+
+

gst_base_parse_frame_free ()

+
void
+gst_base_parse_frame_free (GstBaseParseFrame *frame);
+
+
+
+

gst_base_parse_push_frame ()

+
GstFlowReturn
+gst_base_parse_push_frame (GstBaseParse *parse,
+                           GstBaseParseFrame *frame);
+

Pushes the frame's buffer downstream, sends any pending events and +does some timestamp and segment handling. Takes ownership of +frame's buffer, though caller retains ownership of frame +.

+

This must be called with sinkpad STREAM_LOCK held.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

parse

GstBaseParse.

 

frame

a GstBaseParseFrame.

[transfer none]
+
+
+

Returns

+

GstFlowReturn

+
+
+
+
+

gst_base_parse_finish_frame ()

+
GstFlowReturn
+gst_base_parse_finish_frame (GstBaseParse *parse,
+                             GstBaseParseFrame *frame,
+                             gint size);
+

Collects parsed data and pushes this downstream. +Source pad caps must be set when this is called.

+

If frame +'s out_buffer is set, that will be used as subsequent frame data. +Otherwise, size + samples will be taken from the input and used for output, +and the output's metadata (timestamps etc) will be taken as (optionally) +set by the subclass on frame +'s (input) buffer (which is otherwise +ignored for any but the above purpose/information).

+

Note that the latter buffer is invalidated by this call, whereas the +caller retains ownership of frame +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

parse

a GstBaseParse

 

frame

a GstBaseParseFrame

 

size

consumed input data represented by frame

 
+
+
+

Returns

+

a GstFlowReturn that should be escalated to caller (of caller)

+
+
+
+
+

GST_BASE_PARSE_DRAINING()

+
#define GST_BASE_PARSE_DRAINING(parse)  (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_DRAINING))
+
+

Obtains current drain status (ie. whether EOS has been received and +the parser is now processing the frames at the end of the stream)

+
+

Parameters

+
+++++ + + + + + +

parse

base parse instance

 
+
+
+
+
+

GST_BASE_PARSE_LOST_SYNC()

+
#define GST_BASE_PARSE_LOST_SYNC(parse) (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_LOST_SYNC))
+
+

Obtains current sync status.

+
+

Parameters

+
+++++ + + + + + +

parse

base parse instance

 
+
+
+
+
+

GST_BASE_PARSE_SINK_PAD()

+
#define GST_BASE_PARSE_SINK_PAD(obj)    (GST_BASE_PARSE_CAST (obj)->sinkpad)
+
+

Gives the pointer to the sink GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base parse instance

 
+
+
+
+
+

GST_BASE_PARSE_SRC_PAD()

+
#define GST_BASE_PARSE_SRC_PAD(obj)    (GST_BASE_PARSE_CAST (obj)->srcpad)
+
+

Gives the pointer to the source GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base parse instance

 
+
+
+
+
+

Types and Values

+
+

struct GstBaseParse

+
struct GstBaseParse {
+  GstElement     element;
+};
+
+

The opaque GstBaseParse data structure.

+
+

Members

+
+++++ + + + + + +

GstElement element;

the parent element.

 
+
+
+
+
+

struct GstBaseParseClass

+
struct GstBaseParseClass {
+  GstElementClass parent_class;
+
+  /* virtual methods for subclasses */
+
+  gboolean      (*start)              (GstBaseParse * parse);
+
+  gboolean      (*stop)               (GstBaseParse * parse);
+
+  gboolean      (*set_sink_caps)      (GstBaseParse * parse,
+                                       GstCaps      * caps);
+
+  GstFlowReturn (*handle_frame)       (GstBaseParse      * parse,
+                                       GstBaseParseFrame * frame,
+                                       gint              * skipsize);
+
+  GstFlowReturn (*pre_push_frame)     (GstBaseParse      * parse,
+                                       GstBaseParseFrame * frame);
+
+  gboolean      (*convert)            (GstBaseParse * parse,
+                                       GstFormat      src_format,
+                                       gint64         src_value,
+                                       GstFormat      dest_format,
+                                       gint64       * dest_value);
+
+  gboolean      (*sink_event)         (GstBaseParse * parse,
+                                       GstEvent     * event);
+
+  gboolean      (*src_event)          (GstBaseParse * parse,
+                                       GstEvent     * event);
+
+  GstCaps *     (*get_sink_caps)      (GstBaseParse * parse,
+                                       GstCaps      * filter);
+
+  GstFlowReturn (*detect)             (GstBaseParse * parse,
+                                       GstBuffer    * buffer);
+
+  gboolean      (*sink_query)         (GstBaseParse * parse,
+                                       GstQuery     * query);
+
+  gboolean      (*src_query)          (GstBaseParse * parse,
+                                       GstQuery     * query);
+};
+
+

Subclasses can override any of the available virtual methods or not, as +needed. At minimum handle_frame + needs to be overridden.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

start ()

Optional. +Called when the element starts processing. +Allows opening external resources.

 

stop ()

Optional. +Called when the element stops processing. +Allows closing external resources.

 

set_sink_caps ()

Optional. +Allows the subclass to be notified of the actual caps set.

 

handle_frame ()

Parses the input data into valid frames as defined by subclass +which should be passed to gst_base_parse_finish_frame(). +The frame's input buffer is guaranteed writable, +whereas the input frame ownership is held by caller +(so subclass should make a copy if it needs to hang on). +Input buffer (data) is provided by baseclass with as much +metadata set as possible by baseclass according to upstream +information and/or subclass settings, +though subclass may still set buffer timestamp and duration +if desired.

 

pre_push_frame ()

Optional. +Called just prior to pushing a frame (after any pending +events have been sent) to give subclass a chance to perform +additional actions at this time (e.g. tag sending) or to +decide whether this buffer should be dropped or not +(e.g. custom segment clipping).

 

convert ()

Optional. +Convert between formats.

 

sink_event ()

Optional. +Event handler on the sink pad. This function should chain +up to the parent implementation to let the default handler +run.

 

src_event ()

Optional. +Event handler on the source pad. Should chain up to the +parent to let the default handler run.

 

get_sink_caps ()

Optional. +Allows the subclass to do its own sink get caps if needed.

 

detect ()

Optional. +Called until it doesn't return GST_FLOW_OK anymore for +the first buffers. Can be used by the subclass to detect +the stream format.

 

sink_query ()

Optional. +Query handler on the sink pad. This function should chain +up to the parent implementation to let the default handler +run (Since 1.2)

 

src_query ()

Optional. +Query handler on the source pad. Should chain up to the +parent to let the default handler run (Since 1.2)

 
+
+
+
+
+

GstBaseParseFrame

+
typedef struct {
+  GstBuffer * buffer;
+  GstBuffer * out_buffer;
+  guint       flags;
+  guint64     offset;
+  gint        overhead;
+} GstBaseParseFrame;
+
+

Frame (context) data passed to each frame parsing virtual methods. In +addition to providing the data to be checked for a valid frame or an already +identified frame, it conveys additional metadata or control information +from and to the subclass w.r.t. the particular frame in question (rather +than global parameters). Some of these may apply to each parsing stage, others +only to some a particular one. These parameters are effectively zeroed at start +of each frame's processing, i.e. parsing virtual method invocation sequence.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstBuffer *buffer;

input data to be parsed for frames.

 

GstBuffer *out_buffer;

output data.

 

guint flags;

a combination of input and output GstBaseParseFrameFlags that +convey additional context to subclass or allow subclass to tune +subsequent GstBaseParse actions.

 

guint64 offset;

media specific offset of input frame +Note that a converter may have a different one on the frame's buffer.

 

gint overhead;

subclass can set this to indicates the metadata overhead +for the given frame, which is then used to enable more accurate bitrate +computations. If this is -1, it is assumed that this frame should be +skipped in bitrate calculation.

 
+
+
+
+
+

enum GstBaseParseFrameFlags

+

Flags to be used in a GstBaseParseFrame.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_BASE_PARSE_FRAME_FLAG_NONE

+

no flag

+
 

GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME

+

set by baseclass if current frame + is passed for processing to the subclass for the first time + (and not set on subsequent calls with same data).

+
 

GST_BASE_PARSE_FRAME_FLAG_NO_FRAME

+

set to indicate this buffer should not be + counted as frame, e.g. if this frame is dependent on a previous one. + As it is not counted as a frame, bitrate increases but frame to time + conversions are maintained.

+
 

GST_BASE_PARSE_FRAME_FLAG_CLIP

+

pre_push_frame + can set this to indicate + that regular segment clipping can still be performed (as opposed to + any custom one having been done).

+
 

GST_BASE_PARSE_FRAME_FLAG_DROP

+

indicates to finish_frame + that the + the frame should be dropped (and might be handled internally by subclass)

+
 

GST_BASE_PARSE_FRAME_FLAG_QUEUE

+

indicates to finish_frame + that the + the frame should be queued for now and processed fully later + when the first non-queued frame is finished

+
 
+
+
+
+
+

GST_BASE_PARSE_FLAG_DRAINING

+
#define GST_BASE_PARSE_FLAG_DRAINING  (1 << 1)
+
+
+
+
+

GST_BASE_PARSE_FLAG_LOST_SYNC

+
#define GST_BASE_PARSE_FLAG_LOST_SYNC (1 << 0)
+
+
+
+
+

GST_BASE_PARSE_FLOW_DROPPED

+
#define GST_BASE_PARSE_FLOW_DROPPED     GST_FLOW_CUSTOM_SUCCESS
+
+

A GstFlowReturn that can be returned from parse_frame to +indicate that no output buffer was generated, or from pre_push_frame to +to forego pushing buffer.

+
+
+
+

Property Details

+
+

The “disable-passthrough” property

+
  “disable-passthrough”      gboolean
+

If set to TRUE, baseparse will unconditionally force parsing of the +incoming data. This can be required in the rare cases where the incoming +side-data (caps, pts, dts, ...) is not trusted by the user and wants to +force validation and parsing of the incoming data. +If set to FALSE, decision of whether to parse the data or not is up to +the implementation (standard behaviour).

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

See Also

+

GstBaseTransform

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstBaseSink.html b/docs/libs/html/GstBaseSink.html new file mode 100644 index 0000000..139c3ba --- /dev/null +++ b/docs/libs/html/GstBaseSink.html @@ -0,0 +1,1853 @@ + + + + +GstBaseSink: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBaseSink

+

GstBaseSink — Base class for sink elements

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +gst_base_sink_query_latency () +
+GstClockTime + +gst_base_sink_get_latency () +
+GstFlowReturn + +gst_base_sink_do_preroll () +
+GstFlowReturn + +gst_base_sink_wait () +
+GstFlowReturn + +gst_base_sink_wait_preroll () +
+GstClockReturn + +gst_base_sink_wait_clock () +
+void + +gst_base_sink_set_sync () +
+gboolean + +gst_base_sink_get_sync () +
+void + +gst_base_sink_set_max_lateness () +
+gint64 + +gst_base_sink_get_max_lateness () +
+void + +gst_base_sink_set_qos_enabled () +
+gboolean + +gst_base_sink_is_qos_enabled () +
+void + +gst_base_sink_set_async_enabled () +
+gboolean + +gst_base_sink_is_async_enabled () +
+void + +gst_base_sink_set_ts_offset () +
+GstClockTimeDiff + +gst_base_sink_get_ts_offset () +
+void + +gst_base_sink_set_render_delay () +
+GstClockTime + +gst_base_sink_get_render_delay () +
+GstSample * + +gst_base_sink_get_last_sample () +
+void + +gst_base_sink_set_blocksize () +
+guint + +gst_base_sink_get_blocksize () +
+guint64 + +gst_base_sink_get_throttle_time () +
+void + +gst_base_sink_set_throttle_time () +
+void + +gst_base_sink_set_max_bitrate () +
+guint64 + +gst_base_sink_get_max_bitrate () +
+void + +gst_base_sink_set_last_sample_enabled () +
+gboolean + +gst_base_sink_is_last_sample_enabled () +
#define +GST_BASE_SINK_PAD() +
#define +GST_BASE_SINK_GET_PREROLL_COND() +
#define +GST_BASE_SINK_GET_PREROLL_LOCK() +
#define +GST_BASE_SINK_PREROLL_BROADCAST() +
#define +GST_BASE_SINK_PREROLL_LOCK() +
#define +GST_BASE_SINK_PREROLL_SIGNAL() +
#define +GST_BASE_SINK_PREROLL_TRYLOCK() +
#define +GST_BASE_SINK_PREROLL_UNLOCK() +
#define +GST_BASE_SINK_PREROLL_WAIT() +
#define +GST_BASE_SINK_PREROLL_WAIT_UNTIL() +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleanasyncRead / Write
guintblocksizeRead / Write
gbooleanenable-last-sampleRead / Write
+GstSample *last-sampleRead
guint64max-bitrateRead / Write
gint64max-latenessRead / Write
gbooleanqosRead / Write
guint64render-delayRead / Write
gbooleansyncRead / Write
guint64throttle-timeRead / Write
gint64ts-offsetRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstBaseSink
structGstBaseSinkClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSink
+
+
+
+

Includes

+
#include <gst/base/gstbasesink.h>
+
+
+
+

Description

+

GstBaseSink is the base class for sink elements in GStreamer, such as +xvimagesink or filesink. It is a layer on top of GstElement that provides a +simplified interface to plugin writers. GstBaseSink handles many details +for you, for example: preroll, clock synchronization, state changes, +activation in push or pull mode, and queries.

+

In most cases, when writing sink elements, there is no need to implement +class methods from GstElement or to set functions on pads, because the +GstBaseSink infrastructure should be sufficient.

+

GstBaseSink provides support for exactly one sink pad, which should be +named "sink". A sink implementation (subclass of GstBaseSink) should +install a pad template in its class_init function, like so:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
static void
+my_element_class_init (GstMyElementClass *klass)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  // sinktemplate should be a #GstStaticPadTemplate with direction
+  // %GST_PAD_SINK and name "sink"
+  gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
+
+  gst_element_class_set_static_metadata (gstelement_class,
+      "Sink name",
+      "Sink",
+      "My Sink element",
+      "The author <my.sink@my.email>");
+}
+
+ +

+

GstBaseSink will handle the prerolling correctly. This means that it will +return GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first +buffer arrives in this element. The base class will call the +GstBaseSinkClass.preroll() vmethod with this preroll buffer and will then +commit the state change to the next asynchronously pending state.

+

When the element is set to PLAYING, GstBaseSink will synchronise on the +clock using the times returned from GstBaseSinkClass.get_times(). If this +function returns GST_CLOCK_TIME_NONE for the start time, no synchronisation +will be done. Synchronisation can be disabled entirely by setting the object +“sync” property to FALSE.

+

After synchronisation the virtual method GstBaseSinkClass.render() will be +called. Subclasses should minimally implement this method.

+

Subclasses that synchronise on the clock in the GstBaseSinkClass.render() +method are supported as well. These classes typically receive a buffer in +the render method and can then potentially block on the clock while +rendering. A typical example is an audiosink. +These subclasses can use gst_base_sink_wait_preroll() to perform the +blocking wait.

+

Upon receiving the EOS event in the PLAYING state, GstBaseSink will wait +for the clock to reach the time indicated by the stop time of the last +GstBaseSinkClass.get_times() call before posting an EOS message. When the +element receives EOS in PAUSED, preroll completes, the event is queued and an +EOS message is posted when going to PLAYING.

+

GstBaseSink will internally use the GST_EVENT_SEGMENT events to schedule +synchronisation and clipping of buffers. Buffers that fall completely outside +of the current segment are dropped. Buffers that fall partially in the +segment are rendered (and prerolled). Subclasses should do any subbuffer +clipping themselves when needed.

+

GstBaseSink will by default report the current playback position in +GST_FORMAT_TIME based on the current clock time and segment information. +If no clock has been set on the element, the query will be forwarded +upstream.

+

The GstBaseSinkClass.set_caps() function will be called when the subclass +should configure itself to process a specific media type.

+

The GstBaseSinkClass.start() and GstBaseSinkClass.stop() virtual methods +will be called when resources should be allocated. Any +GstBaseSinkClass.preroll(), GstBaseSinkClass.render() and +GstBaseSinkClass.set_caps() function will be called between the +GstBaseSinkClass.start() and GstBaseSinkClass.stop() calls.

+

The GstBaseSinkClass.event() virtual method will be called when an event is +received by GstBaseSink. Normally this method should only be overridden by +very specific elements (such as file sinks) which need to handle the +newsegment event specially.

+

The GstBaseSinkClass.unlock() method is called when the elements should +unblock any blocking operations they perform in the +GstBaseSinkClass.render() method. This is mostly useful when the +GstBaseSinkClass.render() method performs a blocking write on a file +descriptor, for example.

+

The “max-lateness” property affects how the sink deals with +buffers that arrive too late in the sink. A buffer arrives too late in the +sink when the presentation time (as a combination of the last segment, buffer +timestamp and element base_time) plus the duration is before the current +time of the clock. +If the frame is later than max-lateness, the sink will drop the buffer +without calling the render method. +This feature is disabled if sync is disabled, the +GstBaseSinkClass.get_times() method does not return a valid start time or +max-lateness is set to -1 (the default). +Subclasses can use gst_base_sink_set_max_lateness() to configure the +max-lateness value.

+

The “qos” property will enable the quality-of-service features of +the basesink which gather statistics about the real-time performance of the +clock synchronisation. For each buffer received in the sink, statistics are +gathered and a QOS event is sent upstream with these numbers. This +information can then be used by upstream elements to reduce their processing +rate, for example.

+

The “async” property can be used to instruct the sink to never +perform an ASYNC state change. This feature is mostly usable when dealing +with non-synchronized streams or sparse streams.

+
+
+

Functions

+
+

gst_base_sink_query_latency ()

+
gboolean
+gst_base_sink_query_latency (GstBaseSink *sink,
+                             gboolean *live,
+                             gboolean *upstream_live,
+                             GstClockTime *min_latency,
+                             GstClockTime *max_latency);
+

Query the sink for the latency parameters. The latency will be queried from +the upstream elements. live + will be TRUE if sink + is configured to +synchronize against the clock. upstream_live + will be TRUE if an upstream +element is live.

+

If both live + and upstream_live + are TRUE, the sink will want to compensate +for the latency introduced by the upstream elements by setting the +min_latency + to a strictly positive value.

+

This function is mostly used by subclasses.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

sink

the sink

 

live

if the sink is live.

[out][allow-none]

upstream_live

if an upstream element is live.

[out][allow-none]

min_latency

the min latency of the upstream elements.

[out][allow-none]

max_latency

the max latency of the upstream elements.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query succeeded.

+
+
+
+
+

gst_base_sink_get_latency ()

+
GstClockTime
+gst_base_sink_get_latency (GstBaseSink *sink);
+

Get the currently configured latency.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

The configured latency.

+
+
+
+
+

gst_base_sink_do_preroll ()

+
GstFlowReturn
+gst_base_sink_do_preroll (GstBaseSink *sink,
+                          GstMiniObject *obj);
+

If the sink + spawns its own thread for pulling buffers from upstream it +should call this method after it has pulled a buffer. If the element needed +to preroll, this function will perform the preroll and will then block +until the element state is changed.

+

This function should be called with the PREROLL_LOCK held.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

obj

the mini object that caused the preroll.

[transfer none]
+
+
+

Returns

+

GST_FLOW_OK if the preroll completed and processing can +continue. Any other return value should be returned from the render vmethod.

+
+
+
+
+

gst_base_sink_wait ()

+
GstFlowReturn
+gst_base_sink_wait (GstBaseSink *sink,
+                    GstClockTime time,
+                    GstClockTimeDiff *jitter);
+

This function will wait for preroll to complete and will then block until time + +is reached. It is usually called by subclasses that use their own internal +synchronisation but want to let some synchronization (like EOS) be handled +by the base class.

+

This function should only be called with the PREROLL_LOCK held (like when +receiving an EOS event in the ::event vmethod or when handling buffers in +::render).

+

The time + argument should be the running_time of when the timeout should happen +and will be adjusted with any latency and offset configured in the sink.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sink

the sink

 

time

the running_time to be reached

 

jitter

the jitter to be filled with time diff, or NULL.

[out][allow-none]
+
+
+

Returns

+

GstFlowReturn

+
+
+
+
+

gst_base_sink_wait_preroll ()

+
GstFlowReturn
+gst_base_sink_wait_preroll (GstBaseSink *sink);
+

If the GstBaseSinkClass.render() method performs its own synchronisation +against the clock it must unblock when going from PLAYING to the PAUSED state +and call this method before continuing to render the remaining data.

+

If the GstBaseSinkClass.render() method can block on something else than +the clock, it must also be ready to unblock immediately on +the GstBaseSinkClass.unlock() method and cause the +GstBaseSinkClass.render() method to immediately call this function. +In this case, the subclass must be prepared to continue rendering where it +left off if this function returns GST_FLOW_OK.

+

This function will block until a state change to PLAYING happens (in which +case this function returns GST_FLOW_OK) or the processing must be stopped due +to a state change to READY or a FLUSH event (in which case this function +returns GST_FLOW_FLUSHING).

+

This function should only be called with the PREROLL_LOCK held, like in the +render function.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

GST_FLOW_OK if the preroll completed and processing can +continue. Any other return value should be returned from the render vmethod.

+
+
+
+
+

gst_base_sink_wait_clock ()

+
GstClockReturn
+gst_base_sink_wait_clock (GstBaseSink *sink,
+                          GstClockTime time,
+                          GstClockTimeDiff *jitter);
+

This function will block until time + is reached. It is usually called by +subclasses that use their own internal synchronisation.

+

If time + is not valid, no synchronisation is done and GST_CLOCK_BADTIME is +returned. Likewise, if synchronisation is disabled in the element or there +is no clock, no synchronisation is done and GST_CLOCK_BADTIME is returned.

+

This function should only be called with the PREROLL_LOCK held, like when +receiving an EOS event in the GstBaseSinkClass.event() vmethod or when +receiving a buffer in +the GstBaseSinkClass.render() vmethod.

+

The time + argument should be the running_time of when this method should +return and is not adjusted with any latency or offset configured in the +sink.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

sink

the sink

 

time

the running_time to be reached

 

jitter

the jitter to be filled with time diff, or NULL.

[out][allow-none]
+
+
+

Returns

+

GstClockReturn

+
+
+
+
+

gst_base_sink_set_sync ()

+
void
+gst_base_sink_set_sync (GstBaseSink *sink,
+                        gboolean sync);
+

Configures sink + to synchronize on the clock or not. When +sync + is FALSE, incoming samples will be played as fast as +possible. If sync + is TRUE, the timestamps of the incoming +buffers will be used to schedule the exact render time of its +contents.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

sync

the new sync value.

 
+
+
+
+
+

gst_base_sink_get_sync ()

+
gboolean
+gst_base_sink_get_sync (GstBaseSink *sink);
+

Checks if sink + is currently configured to synchronize against the +clock.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

TRUE if the sink is configured to synchronize against the clock.

+
+
+
+
+

gst_base_sink_set_max_lateness ()

+
void
+gst_base_sink_set_max_lateness (GstBaseSink *sink,
+                                gint64 max_lateness);
+

Sets the new max lateness value to max_lateness +. This value is +used to decide if a buffer should be dropped or not based on the +buffer timestamp and the current clock time. A value of -1 means +an unlimited time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

max_lateness

the new max lateness value.

 
+
+
+
+
+

gst_base_sink_get_max_lateness ()

+
gint64
+gst_base_sink_get_max_lateness (GstBaseSink *sink);
+

Gets the max lateness value. See gst_base_sink_set_max_lateness() for +more details.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

The maximum time in nanoseconds that a buffer can be late +before it is dropped and not rendered. A value of -1 means an +unlimited time.

+
+
+
+
+

gst_base_sink_set_qos_enabled ()

+
void
+gst_base_sink_set_qos_enabled (GstBaseSink *sink,
+                               gboolean enabled);
+

Configures sink + to send Quality-of-Service events upstream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

enabled

the new qos value.

 
+
+
+
+
+

gst_base_sink_is_qos_enabled ()

+
gboolean
+gst_base_sink_is_qos_enabled (GstBaseSink *sink);
+

Checks if sink + is currently configured to send Quality-of-Service events +upstream.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

TRUE if the sink is configured to perform Quality-of-Service.

+
+
+
+
+

gst_base_sink_set_async_enabled ()

+
void
+gst_base_sink_set_async_enabled (GstBaseSink *sink,
+                                 gboolean enabled);
+

Configures sink + to perform all state changes asynchronously. When async is +disabled, the sink will immediately go to PAUSED instead of waiting for a +preroll buffer. This feature is useful if the sink does not synchronize +against the clock or when it is dealing with sparse streams.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

enabled

the new async value.

 
+
+
+
+
+

gst_base_sink_is_async_enabled ()

+
gboolean
+gst_base_sink_is_async_enabled (GstBaseSink *sink);
+

Checks if sink + is currently configured to perform asynchronous state +changes to PAUSED.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

TRUE if the sink is configured to perform asynchronous state +changes.

+
+
+
+
+

gst_base_sink_set_ts_offset ()

+
void
+gst_base_sink_set_ts_offset (GstBaseSink *sink,
+                             GstClockTimeDiff offset);
+

Adjust the synchronisation of sink + with offset +. A negative value will +render buffers earlier than their timestamp. A positive value will delay +rendering. This function can be used to fix playback of badly timestamped +buffers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

offset

the new offset

 
+
+
+
+
+

gst_base_sink_get_ts_offset ()

+
GstClockTimeDiff
+gst_base_sink_get_ts_offset (GstBaseSink *sink);
+

Get the synchronisation offset of sink +.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

The synchronisation offset.

+
+
+
+
+

gst_base_sink_set_render_delay ()

+
void
+gst_base_sink_set_render_delay (GstBaseSink *sink,
+                                GstClockTime delay);
+

Set the render delay in sink + to delay +. The render delay is the time +between actual rendering of a buffer and its synchronisation time. Some +devices might delay media rendering which can be compensated for with this +function.

+

After calling this function, this sink will report additional latency and +other sinks will adjust their latency to delay the rendering of their media.

+

This function is usually called by subclasses.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

a GstBaseSink

 

delay

the new delay

 
+
+
+
+
+

gst_base_sink_get_render_delay ()

+
GstClockTime
+gst_base_sink_get_render_delay (GstBaseSink *sink);
+

Get the render delay of sink +. see gst_base_sink_set_render_delay() for more +information about the render delay.

+
+

Parameters

+
+++++ + + + + + +

sink

a GstBaseSink

 
+
+
+

Returns

+

the render delay of sink +.

+
+
+
+
+

gst_base_sink_get_last_sample ()

+
GstSample *
+gst_base_sink_get_last_sample (GstBaseSink *sink);
+

Get the last sample that arrived in the sink and was used for preroll or for +rendering. This property can be used to generate thumbnails.

+

The GstCaps on the sample can be used to determine the type of the buffer.

+

Free-function: gst_sample_unref

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

a GstSample. gst_sample_unref() after +usage. This function returns NULL when no buffer has arrived in the +sink yet or when the sink is not in PAUSED or PLAYING.

+

[transfer full][nullable]

+
+
+
+
+

gst_base_sink_set_blocksize ()

+
void
+gst_base_sink_set_blocksize (GstBaseSink *sink,
+                             guint blocksize);
+

Set the number of bytes that the sink will pull when it is operating in pull +mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

a GstBaseSink

 

blocksize

the blocksize in bytes

 
+
+
+
+
+

gst_base_sink_get_blocksize ()

+
guint
+gst_base_sink_get_blocksize (GstBaseSink *sink);
+

Get the number of bytes that the sink will pull when it is operating in pull +mode.

+
+

Parameters

+
+++++ + + + + + +

sink

a GstBaseSink

 
+
+
+

Returns

+

the number of bytes sink +will pull in pull mode.

+
+
+
+
+

gst_base_sink_get_throttle_time ()

+
guint64
+gst_base_sink_get_throttle_time (GstBaseSink *sink);
+

Get the time that will be inserted between frames to control the +maximum buffers per second.

+
+

Parameters

+
+++++ + + + + + +

sink

a GstBaseSink

 
+
+
+

Returns

+

the number of nanoseconds sink +will put between frames.

+
+
+
+
+

gst_base_sink_set_throttle_time ()

+
void
+gst_base_sink_set_throttle_time (GstBaseSink *sink,
+                                 guint64 throttle);
+

Set the time that will be inserted between rendered buffers. This +can be used to control the maximum buffers per second that the sink +will render.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

a GstBaseSink

 

throttle

the throttle time in nanoseconds

 
+
+
+
+
+

gst_base_sink_set_max_bitrate ()

+
void
+gst_base_sink_set_max_bitrate (GstBaseSink *sink,
+                               guint64 max_bitrate);
+

Set the maximum amount of bits per second that the sink will render.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

a GstBaseSink

 

max_bitrate

the max_bitrate in bits per second

 
+
+

Since: 1.2

+
+
+
+

gst_base_sink_get_max_bitrate ()

+
guint64
+gst_base_sink_get_max_bitrate (GstBaseSink *sink);
+

Get the maximum amount of bits per second that the sink will render.

+
+

Parameters

+
+++++ + + + + + +

sink

a GstBaseSink

 
+
+
+

Returns

+

the maximum number of bits per second sink +will render.

+
+

Since: 1.2

+
+
+
+

gst_base_sink_set_last_sample_enabled ()

+
void
+gst_base_sink_set_last_sample_enabled (GstBaseSink *sink,
+                                       gboolean enabled);
+

Configures sink + to store the last received sample in the last-sample +property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

sink

the sink

 

enabled

the new enable-last-sample value.

 
+
+
+
+
+

gst_base_sink_is_last_sample_enabled ()

+
gboolean
+gst_base_sink_is_last_sample_enabled (GstBaseSink *sink);
+

Checks if sink + is currently configured to store the last received sample in +the last-sample property.

+
+

Parameters

+
+++++ + + + + + +

sink

the sink

 
+
+
+

Returns

+

TRUE if the sink is configured to store the last received sample.

+
+
+
+
+

GST_BASE_SINK_PAD()

+
#define GST_BASE_SINK_PAD(obj)          (GST_BASE_SINK_CAST (obj)->sinkpad)
+
+

Gives the pointer to the GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base sink instance

 
+
+
+
+
+

GST_BASE_SINK_GET_PREROLL_COND()

+
#define GST_BASE_SINK_GET_PREROLL_COND(obj)   (&GST_BASE_SINK_CAST(obj)->preroll_cond)
+
+
+
+
+

GST_BASE_SINK_GET_PREROLL_LOCK()

+
#define GST_BASE_SINK_GET_PREROLL_LOCK(obj)   (&GST_BASE_SINK_CAST(obj)->preroll_lock)
+
+
+
+
+

GST_BASE_SINK_PREROLL_BROADCAST()

+
#define GST_BASE_SINK_PREROLL_BROADCAST(obj)  g_cond_broadcast (GST_BASE_SINK_GET_PREROLL_COND (obj));
+
+
+
+
+

GST_BASE_SINK_PREROLL_LOCK()

+
#define GST_BASE_SINK_PREROLL_LOCK(obj)       (g_mutex_lock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
+
+
+
+
+

GST_BASE_SINK_PREROLL_SIGNAL()

+
#define GST_BASE_SINK_PREROLL_SIGNAL(obj)     g_cond_signal (GST_BASE_SINK_GET_PREROLL_COND (obj));
+
+
+
+
+

GST_BASE_SINK_PREROLL_TRYLOCK()

+
#define GST_BASE_SINK_PREROLL_TRYLOCK(obj)    (g_mutex_trylock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
+
+
+
+
+

GST_BASE_SINK_PREROLL_UNLOCK()

+
#define GST_BASE_SINK_PREROLL_UNLOCK(obj)     (g_mutex_unlock(GST_BASE_SINK_GET_PREROLL_LOCK(obj)))
+
+
+
+
+

GST_BASE_SINK_PREROLL_WAIT()

+
#define             GST_BASE_SINK_PREROLL_WAIT(obj)
+
+
+
+

GST_BASE_SINK_PREROLL_WAIT_UNTIL()

+
#define             GST_BASE_SINK_PREROLL_WAIT_UNTIL(obj, end_time)
+
+
+
+

Types and Values

+
+

struct GstBaseSink

+
struct GstBaseSink;
+

The opaque GstBaseSink data structure.

+
+
+
+

struct GstBaseSinkClass

+
struct GstBaseSinkClass {
+  GstElementClass parent_class;
+
+  /* get caps from subclass */
+  GstCaps*      (*get_caps)     (GstBaseSink *sink, GstCaps *filter);
+  /* notify subclass of new caps */
+  gboolean      (*set_caps)     (GstBaseSink *sink, GstCaps *caps);
+
+  /* fixate sink caps during pull-mode negotiation */
+  GstCaps *     (*fixate)       (GstBaseSink *sink, GstCaps *caps);
+  /* start or stop a pulling thread */
+  gboolean      (*activate_pull)(GstBaseSink *sink, gboolean active);
+
+  /* get the start and end times for syncing on this buffer */
+  void          (*get_times)    (GstBaseSink *sink, GstBuffer *buffer,
+                                 GstClockTime *start, GstClockTime *end);
+
+  /* propose allocation parameters for upstream */
+  gboolean      (*propose_allocation)   (GstBaseSink *sink, GstQuery *query);
+
+  /* start and stop processing, ideal for opening/closing the resource */
+  gboolean      (*start)        (GstBaseSink *sink);
+  gboolean      (*stop)         (GstBaseSink *sink);
+
+  /* unlock any pending access to the resource. subclasses should unlock
+   * any function ASAP. */
+  gboolean      (*unlock)       (GstBaseSink *sink);
+  /* Clear a previously indicated unlock request not that unlocking is
+   * complete. Sub-classes should clear any command queue or indicator they
+   * set during unlock */
+  gboolean      (*unlock_stop)  (GstBaseSink *sink);
+
+  /* notify subclass of query */
+  gboolean      (*query)        (GstBaseSink *sink, GstQuery *query);
+
+  /* notify subclass of event */
+  gboolean      (*event)        (GstBaseSink *sink, GstEvent *event);
+  /* wait for eos or gap, subclasses should chain up to parent first */
+  GstFlowReturn (*wait_event)   (GstBaseSink *sink, GstEvent *event);
+
+  /* notify subclass of buffer or list before doing sync */
+  GstFlowReturn (*prepare)      (GstBaseSink *sink, GstBuffer *buffer);
+  GstFlowReturn (*prepare_list) (GstBaseSink *sink, GstBufferList *buffer_list);
+
+  /* notify subclass of preroll buffer or real buffer */
+  GstFlowReturn (*preroll)      (GstBaseSink *sink, GstBuffer *buffer);
+  GstFlowReturn (*render)       (GstBaseSink *sink, GstBuffer *buffer);
+  /* Render a BufferList */
+  GstFlowReturn (*render_list)  (GstBaseSink *sink, GstBufferList *buffer_list);
+};
+
+

Subclasses can override any of the available virtual methods or not, as +needed. At the minimum, the render + method should be overridden to +output/present buffers.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_caps ()

Called to get sink pad caps from the subclass

 

set_caps ()

Notify subclass of changed caps

 

fixate ()

Only useful in pull mode. Implement if you have +ideas about what should be the default values for the caps you support.

 

activate_pull ()

Subclasses should override this when they can provide an +alternate method of spawning a thread to drive the pipeline in pull mode. +Should start or stop the pulling thread, depending on the value of the +"active" argument. Called after actually activating the sink pad in pull +mode. The default implementation starts a task on the sink pad.

 

get_times ()

Called to get the start and end times for synchronising +the passed buffer to the clock

 

propose_allocation ()

configure the allocation query

 

start ()

Start processing. Ideal for opening resources in the subclass

 

stop ()

Stop processing. Subclasses should use this to close resources.

 

unlock ()

Unlock any pending access to the resource. Subclasses should +unblock any blocked function ASAP and call gst_base_sink_wait_preroll()

 

unlock_stop ()

Clear the previous unlock request. Subclasses should clear +any state they set during GstBaseSinkClass.unlock(), and be ready to +continue where they left off after gst_base_sink_wait_preroll(), +gst_base_sink_wait() or gst_wait_sink_wait_clock() return or +GstBaseSinkClass.render() is called again.

 

query ()

perform a GstQuery on the element.

 

event ()

Override this to handle events arriving on the sink pad

 

wait_event ()

Override this to implement custom logic to wait for the event +time (for events like EOS and GAP). Subclasses should always first +chain up to the default implementation.

 

prepare ()

Called to prepare the buffer for render +and preroll +. This +function is called before synchronisation is performed.

 

prepare_list ()

Called to prepare the buffer list for render_list +. This +function is called before synchronisation is performed.

 

preroll ()

Called to present the preroll buffer if desired.

 

render ()

Called when a buffer should be presented or output, at the +correct moment if the GstBaseSink has been set to sync to the clock.

 

render_list ()

Same as render +but used with buffer lists instead of +buffers.

 
+
+
+
+
+

Property Details

+
+

The “async” property

+
  “async”                    gboolean
+

If set to TRUE, the basesink will perform asynchronous state changes. +When set to FALSE, the sink will not signal the parent when it prerolls. +Use this option when dealing with sparse streams or when synchronisation is +not required.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “blocksize” property

+
  “blocksize”                guint
+

The amount of bytes to pull when operating in pull mode.

+

Flags: Read / Write

+

Default value: 4096

+
+
+
+

The “enable-last-sample” property

+
  “enable-last-sample”       gboolean
+

Enable the last-sample property. If FALSE, basesink doesn't keep a +reference to the last buffer arrived and the last-sample property is always +set to NULL. This can be useful if you need buffers to be released as soon +as possible, eg. if you're using a buffer pool.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “last-sample” property

+
  “last-sample”              GstSample *
+

The last buffer that arrived in the sink and was used for preroll or for +rendering. This property can be used to generate thumbnails. This property +can be NULL when the sink has not yet received a buffer.

+

Flags: Read

+
+
+
+

The “max-bitrate” property

+
  “max-bitrate”              guint64
+

Control the maximum amount of bits that will be rendered per second. +Setting this property to a value bigger than 0 will make the sink delay +rendering of the buffers when it would exceed to max-bitrate.

+

Flags: Read / Write

+

Default value: 0

+

Since: 1.2

+
+
+
+

The “max-lateness” property

+
  “max-lateness”             gint64
+

Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited).

+

Flags: Read / Write

+

Allowed values: >= -1

+

Default value: -1

+
+
+
+

The “qos” property

+
  “qos”                      gboolean
+

Generate Quality-of-Service events upstream.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “render-delay” property

+
  “render-delay”             guint64
+

The additional delay between synchronisation and actual rendering of the +media. This property will add additional latency to the device in order to +make other sinks compensate for the delay.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “sync” property

+
  “sync”                     gboolean
+

Sync on the clock.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “throttle-time” property

+
  “throttle-time”            guint64
+

The time to insert between buffers. This property can be used to control +the maximum amount of buffers per second to render. Setting this property +to a value bigger than 0 will make the sink create THROTTLE QoS events.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “ts-offset” property

+
  “ts-offset”                gint64
+

Controls the final synchronisation, a negative value will render the buffer +earlier while a positive value delays playback. This property can be +used to fix synchronisation in bad files.

+

Flags: Read / Write

+

Default value: 0

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstBaseSrc.html b/docs/libs/html/GstBaseSrc.html new file mode 100644 index 0000000..dbb862b --- /dev/null +++ b/docs/libs/html/GstBaseSrc.html @@ -0,0 +1,1459 @@ + + + + +GstBaseSrc: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBaseSrc

+

GstBaseSrc — Base class for getrange based source elements

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstFlowReturn + +gst_base_src_wait_playing () +
+GstFlowReturn + +gst_base_src_start_wait () +
+void + +gst_base_src_start_complete () +
+gboolean + +gst_base_src_is_live () +
+void + +gst_base_src_set_live () +
+void + +gst_base_src_set_format () +
+gboolean + +gst_base_src_query_latency () +
+guint + +gst_base_src_get_blocksize () +
+void + +gst_base_src_set_blocksize () +
+gboolean + +gst_base_src_get_do_timestamp () +
+void + +gst_base_src_set_do_timestamp () +
+void + +gst_base_src_set_dynamic_size () +
+void + +gst_base_src_set_automatic_eos () +
+gboolean + +gst_base_src_new_seamless_segment () +
+gboolean + +gst_base_src_set_caps () +
+void + +gst_base_src_get_allocator () +
+GstBufferPool * + +gst_base_src_get_buffer_pool () +
+gboolean + +gst_base_src_is_async () +
+void + +gst_base_src_set_async () +
+void + +gst_base_src_submit_buffer_list () +
#define +GST_BASE_SRC_PAD() +
#define +GST_BASE_SRC_IS_STARTED() +
#define +GST_BASE_SRC_IS_STARTING() +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
guintblocksizeRead / Write
gbooleando-timestampRead / Write
gintnum-buffersRead / Write
gbooleantypefindRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstBaseSrc
structGstBaseSrcClass
enumGstBaseSrcFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstPushSrc
+
+
+
+

Includes

+
#include <gst/base/gstbasesrc.h>
+
+
+
+

Description

+

This is a generic base class for source elements. The following +types of sources are supported:

+
    +
  • random access sources like files

  • +
  • seekable sources

  • +
  • live sources

  • +
+

The source can be configured to operate in any GstFormat with the +gst_base_src_set_format() method. The currently set format determines +the format of the internal GstSegment and any GST_EVENT_SEGMENT +events. The default format for GstBaseSrc is GST_FORMAT_BYTES.

+

GstBaseSrc always supports push mode scheduling. If the following +conditions are met, it also supports pull mode scheduling:

+
+

If all the conditions are met for operating in pull mode, GstBaseSrc is +automatically seekable in push mode as well. The following conditions must +be met to make the element seekable in push mode when the format is not +GST_FORMAT_BYTES:

+
+

When the element does not meet the requirements to operate in pull mode, the +offset and length in the GstBaseSrcClass.create() method should be ignored. +It is recommended to subclass GstPushSrc instead, in this situation. If the +element can operate in pull mode but only with specific offsets and +lengths, it is allowed to generate an error when the wrong values are passed +to the GstBaseSrcClass.create() function.

+

GstBaseSrc has support for live sources. Live sources are sources that when +paused discard data, such as audio or video capture devices. A typical live +source also produces data at a fixed rate and thus provides a clock to publish +this rate. +Use gst_base_src_set_live() to activate the live source mode.

+

A live source does not produce data in the PAUSED state. This means that the +GstBaseSrcClass.create() method will not be called in PAUSED but only in +PLAYING. To signal the pipeline that the element will not produce data, the +return value from the READY to PAUSED state will be +GST_STATE_CHANGE_NO_PREROLL.

+

A typical live source will timestamp the buffers it creates with the +current running time of the pipeline. This is one reason why a live source +can only produce data in the PLAYING state, when the clock is actually +distributed and running.

+

Live sources that synchronize and block on the clock (an audio source, for +example) can use gst_base_src_wait_playing() when the +GstBaseSrcClass.create() function was interrupted by a state change to +PAUSED.

+

The GstBaseSrcClass.get_times() method can be used to implement pseudo-live +sources. It only makes sense to implement the GstBaseSrcClass.get_times() +function if the source is a live source. The GstBaseSrcClass.get_times() +function should return timestamps starting from 0, as if it were a non-live +source. The base class will make sure that the timestamps are transformed +into the current running_time. The base source will then wait for the +calculated running_time before pushing out the buffer.

+

For live sources, the base class will by default report a latency of 0. +For pseudo live sources, the base class will by default measure the difference +between the first buffer timestamp and the start time of get_times and will +report this value as the latency. +Subclasses should override the query function when this behaviour is not +acceptable.

+

There is only support in GstBaseSrc for exactly one source pad, which +should be named "src". A source implementation (subclass of GstBaseSrc) +should install a pad template in its class_init function, like so:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
static void
+my_element_class_init (GstMyElementClass *klass)
+{
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  // srctemplate should be a #GstStaticPadTemplate with direction
+  // %GST_PAD_SRC and name "src"
+  gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
+
+  gst_element_class_set_static_metadata (gstelement_class,
+     "Source name",
+     "Source",
+     "My Source element",
+     "The author <my.sink@my.email>");
+}
+
+ +

+
+

Controlled shutdown of live sources in applications

+

Applications that record from a live source may want to stop recording +in a controlled way, so that the recording is stopped, but the data +already in the pipeline is processed to the end (remember that many live +sources would go on recording forever otherwise). For that to happen the +application needs to make the source stop recording and send an EOS +event down the pipeline. The application would then wait for an +EOS message posted on the pipeline's bus to know when all data has +been processed and the pipeline can safely be stopped.

+

An application may send an EOS event to a source element to make it +perform the EOS logic (send EOS event downstream or post a +GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done +with the gst_element_send_event() function on the element or its parent bin.

+

After the EOS has been sent to the element, the application should wait for +an EOS message to be posted on the pipeline's bus. Once this EOS message is +received, it may safely shut down the entire pipeline.

+
+
+
+

Functions

+
+

gst_base_src_wait_playing ()

+
GstFlowReturn
+gst_base_src_wait_playing (GstBaseSrc *src);
+

If the GstBaseSrcClass.create() method performs its own synchronisation +against the clock it must unblock when going from PLAYING to the PAUSED state +and call this method before continuing to produce the remaining data.

+

This function will block until a state change to PLAYING happens (in which +case this function returns GST_FLOW_OK) or the processing must be stopped due +to a state change to READY or a FLUSH event (in which case this function +returns GST_FLOW_FLUSHING).

+
+

Parameters

+
+++++ + + + + + +

src

the src

 
+
+
+

Returns

+

GST_FLOW_OK if src +is PLAYING and processing can +continue. Any other return value should be returned from the create vmethod.

+
+
+
+
+

gst_base_src_start_wait ()

+
GstFlowReturn
+gst_base_src_start_wait (GstBaseSrc *basesrc);
+

Wait until the start operation completes.

+
+

Parameters

+
+++++ + + + + + +

basesrc

base source instance

 
+
+
+

Returns

+

a GstFlowReturn.

+
+
+
+
+

gst_base_src_start_complete ()

+
void
+gst_base_src_start_complete (GstBaseSrc *basesrc,
+                             GstFlowReturn ret);
+

Complete an asynchronous start operation. When the subclass overrides the +start method, it should call gst_base_src_start_complete() when the start +operation completes either from the same thread or from an asynchronous +helper thread.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

basesrc

base source instance

 

ret

a GstFlowReturn

 
+
+
+
+
+

gst_base_src_is_live ()

+
gboolean
+gst_base_src_is_live (GstBaseSrc *src);
+

Check if an element is in live mode.

+
+

Parameters

+
+++++ + + + + + +

src

base source instance

 
+
+
+

Returns

+

TRUE if element is in live mode.

+
+
+
+
+

gst_base_src_set_live ()

+
void
+gst_base_src_set_live (GstBaseSrc *src,
+                       gboolean live);
+

If the element listens to a live source, live + should +be set to TRUE.

+

A live source will not produce data in the PAUSED state and +will therefore not be able to participate in the PREROLL phase +of a pipeline. To signal this fact to the application and the +pipeline, the state change return value of the live source will +be GST_STATE_CHANGE_NO_PREROLL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

base source instance

 

live

new live-mode

 
+
+
+
+
+

gst_base_src_set_format ()

+
void
+gst_base_src_set_format (GstBaseSrc *src,
+                         GstFormat format);
+

Sets the default format of the source. This will be the format used +for sending SEGMENT events and for performing seeks.

+

If a format of GST_FORMAT_BYTES is set, the element will be able to +operate in pull mode if the GstBaseSrcClass.is_seekable() returns TRUE.

+

This function must only be called in states < GST_STATE_PAUSED.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

base source instance

 

format

the format to use

 
+
+
+
+
+

gst_base_src_query_latency ()

+
gboolean
+gst_base_src_query_latency (GstBaseSrc *src,
+                            gboolean *live,
+                            GstClockTime *min_latency,
+                            GstClockTime *max_latency);
+

Query the source for the latency parameters. live + will be TRUE when src + is +configured as a live source. min_latency + and max_latency + will be set +to the difference between the running time and the timestamp of the first +buffer.

+

This function is mostly used by subclasses.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

the source

 

live

if the source is live.

[out][allow-none]

min_latency

the min latency of the source.

[out][allow-none]

max_latency

the max latency of the source.

[out][allow-none]
+
+
+

Returns

+

TRUE if the query succeeded.

+
+
+
+
+

gst_base_src_get_blocksize ()

+
guint
+gst_base_src_get_blocksize (GstBaseSrc *src);
+

Get the number of bytes that src + will push out with each buffer.

+
+

Parameters

+
+++++ + + + + + +

src

the source

 
+
+
+

Returns

+

the number of bytes pushed with each buffer.

+
+
+
+
+

gst_base_src_set_blocksize ()

+
void
+gst_base_src_set_blocksize (GstBaseSrc *src,
+                            guint blocksize);
+

Set the number of bytes that src + will push out with each buffer. When +blocksize + is set to -1, a default length will be used.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

the source

 

blocksize

the new blocksize in bytes

 
+
+
+
+
+

gst_base_src_get_do_timestamp ()

+
gboolean
+gst_base_src_get_do_timestamp (GstBaseSrc *src);
+

Query if src + timestamps outgoing buffers based on the current running_time.

+
+

Parameters

+
+++++ + + + + + +

src

the source

 
+
+
+

Returns

+

TRUE if the base class will automatically timestamp outgoing buffers.

+
+
+
+
+

gst_base_src_set_do_timestamp ()

+
void
+gst_base_src_set_do_timestamp (GstBaseSrc *src,
+                               gboolean timestamp);
+

Configure src + to automatically timestamp outgoing buffers based on the +current running_time of the pipeline. This property is mostly useful for live +sources.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

the source

 

timestamp

enable or disable timestamping

 
+
+
+
+
+

gst_base_src_set_dynamic_size ()

+
void
+gst_base_src_set_dynamic_size (GstBaseSrc *src,
+                               gboolean dynamic);
+

If not dynamic +, size is only updated when needed, such as when trying to +read past current tracked size. Otherwise, size is checked for upon each +read.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

base source instance

 

dynamic

new dynamic size mode

 
+
+
+
+
+

gst_base_src_set_automatic_eos ()

+
void
+gst_base_src_set_automatic_eos (GstBaseSrc *src,
+                                gboolean automatic_eos);
+

If automatic_eos + is TRUE, src + will automatically go EOS if a buffer +after the total size is returned. By default this is TRUE but sources +that can't return an authoritative size and only know that they're EOS +when trying to read more should set this to FALSE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

base source instance

 

automatic_eos

automatic eos

 
+
+

Since: 1.4

+
+
+
+

gst_base_src_new_seamless_segment ()

+
gboolean
+gst_base_src_new_seamless_segment (GstBaseSrc *src,
+                                   gint64 start,
+                                   gint64 stop,
+                                   gint64 time);
+

Prepare a new seamless segment for emission downstream. This function must +only be called by derived sub-classes, and only from the create() function, +as the stream-lock needs to be held.

+

The format for the new segment will be the current format of the source, as +configured with gst_base_src_set_format()

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

src

The source

 

start

The new start value for the segment

 

stop

Stop value for the new segment

 

time

The new time value for the start of the new segment

 
+
+
+

Returns

+

TRUE if preparation of the seamless segment succeeded.

+
+
+
+
+

gst_base_src_set_caps ()

+
gboolean
+gst_base_src_set_caps (GstBaseSrc *src,
+                       GstCaps *caps);
+

Set new caps on the basesrc source pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

a GstBaseSrc

 

caps

a GstCaps.

[transfer none]
+
+
+

Returns

+

TRUE if the caps could be set

+
+
+
+
+

gst_base_src_get_allocator ()

+
void
+gst_base_src_get_allocator (GstBaseSrc *src,
+                            GstAllocator **allocator,
+                            GstAllocationParams *params);
+

Lets GstBaseSrc sub-classes to know the memory allocator + +used by the base class and its params +.

+

Unref the allocator + after usage.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

src

a GstBaseSrc

 

allocator

the GstAllocator +used.

[out][allow-none][transfer full]

params

the +GstAllocationParams of allocator +.

[out][allow-none][transfer full]
+
+
+
+
+

gst_base_src_get_buffer_pool ()

+
GstBufferPool *
+gst_base_src_get_buffer_pool (GstBaseSrc *src);
+
+

Parameters

+
+++++ + + + + + +

src

a GstBaseSrc

 
+
+
+

Returns

+

the instance of the GstBufferPool used +by the src; unref it after usage.

+

[transfer full]

+
+
+
+
+

gst_base_src_is_async ()

+
gboolean
+gst_base_src_is_async (GstBaseSrc *src);
+

Get the current async behaviour of src +. See also gst_base_src_set_async().

+
+

Parameters

+
+++++ + + + + + +

src

base source instance

 
+
+
+

Returns

+

TRUE if src +is operating in async mode.

+
+
+
+
+

gst_base_src_set_async ()

+
void
+gst_base_src_set_async (GstBaseSrc *src,
+                        gboolean async);
+

Configure async behaviour in src +, no state change will block. The open, +close, start, stop, play and pause virtual methods will be executed in a +different thread and are thus allowed to perform blocking operations. Any +blocking operation should be unblocked with the unlock vmethod.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

base source instance

 

async

new async mode

 
+
+
+
+
+

gst_base_src_submit_buffer_list ()

+
void
+gst_base_src_submit_buffer_list (GstBaseSrc *src,
+                                 GstBufferList *buffer_list);
+

Subclasses can call this from their create virtual method implementation +to submit a buffer list to be pushed out later. This is useful in +cases where the create function wants to produce multiple buffers to be +pushed out in one go in form of a GstBufferList, which can reduce overhead +drastically, especially for packetised inputs (for data streams where +the packetisation/chunking is not important it is usually more efficient +to return larger buffers instead).

+

Subclasses that use this function from their create function must return +GST_FLOW_OK and no buffer from their create virtual method implementation. +If a buffer is returned after a buffer list has also been submitted via this +function the behaviour is undefined.

+

Subclasses must only call this function once per create function call and +subclasses must only call this function when the source operates in push +mode.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

a GstBaseSrc

 

buffer_list

a GstBufferList.

[transfer full]
+
+

Since: 1.14

+
+
+
+

GST_BASE_SRC_PAD()

+
#define GST_BASE_SRC_PAD(obj)                 (GST_BASE_SRC_CAST (obj)->srcpad)
+
+

Gives the pointer to the GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base source instance

 
+
+
+
+
+

GST_BASE_SRC_IS_STARTED()

+
#define GST_BASE_SRC_IS_STARTED(obj)  GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTED)
+
+
+
+
+

GST_BASE_SRC_IS_STARTING()

+
#define GST_BASE_SRC_IS_STARTING(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTING)
+
+
+
+
+

Types and Values

+
+

struct GstBaseSrc

+
struct GstBaseSrc;
+

The opaque GstBaseSrc data structure.

+
+
+
+

struct GstBaseSrcClass

+
struct GstBaseSrcClass {
+  GstElementClass parent_class;
+
+  /* virtual methods for subclasses */
+
+  /* get caps from subclass */
+  GstCaps*      (*get_caps)     (GstBaseSrc *src, GstCaps *filter);
+  /* decide on caps */
+  gboolean      (*negotiate)    (GstBaseSrc *src);
+  /* called if, in negotiation, caps need fixating */
+  GstCaps *     (*fixate)       (GstBaseSrc *src, GstCaps *caps);
+  /* notify the subclass of new caps */
+  gboolean      (*set_caps)     (GstBaseSrc *src, GstCaps *caps);
+
+  /* setup allocation query */
+  gboolean      (*decide_allocation)   (GstBaseSrc *src, GstQuery *query);
+
+  /* start and stop processing, ideal for opening/closing the resource */
+  gboolean      (*start)        (GstBaseSrc *src);
+  gboolean      (*stop)         (GstBaseSrc *src);
+
+  /**
+   * GstBaseSrcClass::get_times:
+   * @start: (out):
+   * @end: (out):
+   *
+   * Given @buffer, return @start and @end time when it should be pushed
+   * out. The base class will sync on the clock using these times.
+   */
+  void          (*get_times)    (GstBaseSrc *src, GstBuffer *buffer,
+                                 GstClockTime *start, GstClockTime *end);
+
+  /* get the total size of the resource in the format set by
+   * gst_base_src_set_format() */
+  gboolean      (*get_size)     (GstBaseSrc *src, guint64 *size);
+
+  /* check if the resource is seekable */
+  gboolean      (*is_seekable)  (GstBaseSrc *src);
+
+  /* Prepare the segment on which to perform do_seek(), converting to the
+   * current basesrc format. */
+  gboolean      (*prepare_seek_segment) (GstBaseSrc *src, GstEvent *seek,
+                                         GstSegment *segment);
+  /* notify subclasses of a seek */
+  gboolean      (*do_seek)      (GstBaseSrc *src, GstSegment *segment);
+
+  /* unlock any pending access to the resource. subclasses should unlock
+   * any function ASAP. */
+  gboolean      (*unlock)       (GstBaseSrc *src);
+  /* Clear any pending unlock request, as we succeeded in unlocking */
+  gboolean      (*unlock_stop)  (GstBaseSrc *src);
+
+  /* notify subclasses of a query */
+  gboolean      (*query)        (GstBaseSrc *src, GstQuery *query);
+
+  /* notify subclasses of an event */
+  gboolean      (*event)        (GstBaseSrc *src, GstEvent *event);
+
+  /**
+   * GstBaseSrcClass::create:
+   * @buf: (out):
+   *
+   * Ask the subclass to create a buffer with @offset and @size, the default
+   * implementation will call alloc and fill.
+   */
+  GstFlowReturn (*create)       (GstBaseSrc *src, guint64 offset, guint size,
+                                 GstBuffer **buf);
+  /* ask the subclass to allocate an output buffer. The default implementation
+   * will use the negotiated allocator. */
+  GstFlowReturn (*alloc)        (GstBaseSrc *src, guint64 offset, guint size,
+                                 GstBuffer **buf);
+  /* ask the subclass to fill the buffer with data from offset and size */
+  GstFlowReturn (*fill)         (GstBaseSrc *src, guint64 offset, guint size,
+                                 GstBuffer *buf);
+};
+
+

Subclasses can override any of the available virtual methods or not, as +needed. At the minimum, the create + method should be overridden to produce +buffers.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

get_caps ()

Called to get the caps to report

 

negotiate ()

Negotiated the caps with the peer.

 

fixate ()

Called during negotiation if caps need fixating. Implement instead of +setting a fixate function on the source pad.

 

set_caps ()

Notify subclass of changed output caps

 

decide_allocation ()

configure the allocation query

 

start ()

Start processing. Subclasses should open resources and prepare +to produce data. Implementation should call gst_base_src_start_complete() +when the operation completes, either from the current thread or any other +thread that finishes the start operation asynchronously.

 

stop ()

Stop processing. Subclasses should use this to close resources.

 

get_times ()

Given a buffer, return the start and stop time when it +should be pushed out. The base class will sync on the clock using +these times.

 

get_size ()

Return the total size of the resource, in the format set by +gst_base_src_set_format().

 

is_seekable ()

Check if the source can seek

 

prepare_seek_segment ()

Prepare the GstSegment that will be passed to the +GstBaseSrcClass.do_seek() vmethod for executing a seek +request. Sub-classes should override this if they support seeking in +formats other than the configured native format. By default, it tries to +convert the seek arguments to the configured native format and prepare a +segment in that format.

 

do_seek ()

Perform seeking on the resource to the indicated segment.

 

unlock ()

Unlock any pending access to the resource. Subclasses should unblock +any blocked function ASAP. In particular, any create() function in +progress should be unblocked and should return GST_FLOW_FLUSHING. Any +future GstBaseSrcClass.create() function call should also return +GST_FLOW_FLUSHING until the GstBaseSrcClass.unlock_stop() function has +been called.

 

unlock_stop ()

Clear the previous unlock request. Subclasses should clear any +state they set during GstBaseSrcClass.unlock(), such as clearing command +queues.

 

query ()

Handle a requested query.

 

event ()

Override this to implement custom event handling.

 

create ()

Ask the subclass to create a buffer with offset and size. When the +subclass returns GST_FLOW_OK, it MUST return a buffer of the requested size +unless fewer bytes are available because an EOS condition is near. No +buffer should be returned when the return value is different from +GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the end of +stream is reached. The default implementation will call +GstBaseSrcClass.alloc() and then call GstBaseSrcClass.fill().

 

alloc ()

Ask the subclass to allocate a buffer with for offset and size. The +default implementation will create a new buffer from the negotiated allocator.

 

fill ()

Ask the subclass to fill the buffer with data for offset and size. The +passed buffer is guaranteed to hold the requested amount of bytes.

 
+
+
+
+
+

enum GstBaseSrcFlags

+

The GstElement flags that a basesrc element may have.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_BASE_SRC_FLAG_STARTING

+

has source is starting

+
 

GST_BASE_SRC_FLAG_STARTED

+

has source been started

+
 

GST_BASE_SRC_FLAG_LAST

+

offset to define more flags

+
 
+
+
+
+
+

Property Details

+
+

The “blocksize” property

+
  “blocksize”                guint
+

Size in bytes to read per buffer (-1 = default).

+

Flags: Read / Write

+

Default value: 4096

+
+
+
+

The “do-timestamp” property

+
  “do-timestamp”             gboolean
+

Apply current stream time to buffers.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “num-buffers” property

+
  “num-buffers”              gint
+

Number of buffers to output before sending EOS (-1 = unlimited).

+

Flags: Read / Write

+

Allowed values: >= -1

+

Default value: -1

+
+
+
+

The “typefind” property

+
  “typefind”                 gboolean
+

Run typefind before negotiating (deprecated, non-functional).

+

Flags: Read / Write

+

Default value: FALSE

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstBaseTransform.html b/docs/libs/html/GstBaseTransform.html new file mode 100644 index 0000000..7c6580d --- /dev/null +++ b/docs/libs/html/GstBaseTransform.html @@ -0,0 +1,1250 @@ + + + + +GstBaseTransform: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBaseTransform

+

GstBaseTransform — Base class for simple transform filters

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + +
gbooleanqosRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
structGstBaseTransform
structGstBaseTransformClass
#defineGST_BASE_TRANSFORM_SINK_NAME
#defineGST_BASE_TRANSFORM_SRC_NAME
#defineGST_BASE_TRANSFORM_FLOW_DROPPED
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseTransform
+
+
+
+

Includes

+
#include <gst/base/gstbasetransform.h>
+
+
+
+

Description

+

This base class is for filter elements that process data. Elements +that are suitable for implementation using GstBaseTransform are ones +where the size and caps of the output is known entirely from the input +caps and buffer sizes. These include elements that directly transform +one buffer into another, modify the contents of a buffer in-place, as +well as elements that collate multiple input buffers into one output buffer, +or that expand one input buffer into multiple output buffers. See below +for more concrete use cases.

+

It provides for:

+
    +
  • one sinkpad and one srcpad

  • +
  • Possible formats on sink and source pad implemented +with custom transform_caps function. By default uses +same format on sink and source.

  • +
  • Handles state changes

  • +
  • Does flushing

  • +
  • Push mode

  • +
  • Pull mode if the sub-class transform can operate on arbitrary data

  • +
+
+

Use Cases

+
+

Passthrough mode

+
    +
  • Element has no interest in modifying the buffer. It may want to inspect it, +in which case the element should have a transform_ip function. If there +is no transform_ip function in passthrough mode, the buffer is pushed +intact.

  • +
  • The GstBaseTransformClass.passthrough_on_same_caps variable +will automatically set/unset passthrough based on whether the +element negotiates the same caps on both pads.

  • +
  • GstBaseTransformClass.passthrough_on_same_caps on an element that +doesn't implement a transform_caps function is useful for elements that +only inspect data (such as level)

  • +
  • +

    Example elements

    +
      +
    • Level

    • +
    • Videoscale, audioconvert, videoconvert, audioresample in certain modes.

    • +
    +
  • +
+
+
+

Modifications in-place - input buffer and output buffer are the same thing.

+
    +
  • The element must implement a transform_ip function.

  • +
  • Output buffer size must <= input buffer size

  • +
  • If the always_in_place flag is set, non-writable buffers will be copied +and passed to the transform_ip function, otherwise a new buffer will be +created and the transform function called.

  • +
  • Incoming writable buffers will be passed to the transform_ip function +immediately.

  • +
  • +

    only implementing transform_ip and not transform implies always_in_place = TRUE

    +
    • +

      Example elements:

      +
        +
      • Volume

      • +
      • Audioconvert in certain modes (signed/unsigned conversion)

      • +
      • videoconvert in certain modes (endianness swapping)

      • +
      +
    +
  • +
+
+
+

Modifications only to the caps/metadata of a buffer

+
    +
  • The element does not require writable data, but non-writable buffers +should be subbuffered so that the meta-information can be replaced.

  • +
  • Elements wishing to operate in this mode should replace the +prepare_output_buffer method to create subbuffers of the input buffer +and set always_in_place to TRUE

  • +
  • +

    Example elements

    +
      +
    • Capsfilter when setting caps on outgoing buffers that have +none.

    • +
    • identity when it is going to re-timestamp buffers by +datarate.

    • +
    +
  • +
+
+
+

Normal mode

+
    +
  • always_in_place flag is not set, or there is no transform_ip function

  • +
  • Element will receive an input buffer and output buffer to operate on.

  • +
  • Output buffer is allocated by calling the prepare_output_buffer function.

  • +
  • +

    Example elements:

    +
    • Videoscale, videoconvert, audioconvert when doing +scaling/conversions

    +
  • +
+
+
+

Special output buffer allocations

+
    +
  • Elements which need to do special allocation of their output buffers +beyond allocating output buffers via the negotiated allocator or +buffer pool should implement the prepare_output_buffer method.

  • +
  • +

    Example elements:

    +
    • efence

    +
  • +
+
+
+
+
+

Sub-class settable flags on GstBaseTransform

+
    +
  • +

    passthrough

    +
      +
    • Implies that in the current configuration, the sub-class is not interested in modifying the buffers.

    • +
    • Elements which are always in passthrough mode whenever the same caps has been negotiated on both pads can set the class variable passthrough_on_same_caps to have this behaviour automatically.

    • +
    +
  • +
  • +

    always_in_place

    +
      +
    • Determines whether a non-writable buffer will be copied before passing +to the transform_ip function.

    • +
    • Implied TRUE if no transform function is implemented.

    • +
    • Implied FALSE if ONLY transform function is implemented.

    • +
    +
  • +
+
+
+
+

Functions

+
+

gst_base_transform_is_passthrough ()

+
gboolean
+gst_base_transform_is_passthrough (GstBaseTransform *trans);
+

See if trans + is configured as a passthrough transform.

+
+

Parameters

+
+++++ + + + + + +

trans

the GstBaseTransform to query

 
+
+
+

Returns

+

TRUE is the transform is configured in passthrough mode.

+

MT safe.

+
+
+
+
+

gst_base_transform_set_passthrough ()

+
void
+gst_base_transform_set_passthrough (GstBaseTransform *trans,
+                                    gboolean passthrough);
+

Set passthrough mode for this filter by default. This is mostly +useful for filters that do not care about negotiation.

+

Always TRUE for filters which don't implement either a transform +or transform_ip method.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

the GstBaseTransform to set

 

passthrough

boolean indicating passthrough mode.

 
+
+
+
+
+

gst_base_transform_set_prefer_passthrough ()

+
void
+gst_base_transform_set_prefer_passthrough
+                               (GstBaseTransform *trans,
+                                gboolean prefer_passthrough);
+

If prefer_passthrough + is TRUE (the default), trans + will check and +prefer passthrough caps from the list of caps returned by the +transform_caps vmethod.

+

If set to FALSE, the element must order the caps returned from the +transform_caps function in such a way that the preferred format is +first in the list. This can be interesting for transforms that can do +passthrough transforms but prefer to do something else, like a +capsfilter.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstBaseTransform

 

prefer_passthrough

New state

 
+
+

Since: 1.0.1

+
+
+
+

gst_base_transform_is_in_place ()

+
gboolean
+gst_base_transform_is_in_place (GstBaseTransform *trans);
+

See if trans + is configured as a in_place transform.

+
+

Parameters

+
+++++ + + + + + +

trans

the GstBaseTransform to query

 
+
+
+

Returns

+

TRUE is the transform is configured in in_place mode.

+

MT safe.

+
+
+
+
+

gst_base_transform_set_in_place ()

+
void
+gst_base_transform_set_in_place (GstBaseTransform *trans,
+                                 gboolean in_place);
+

Determines whether a non-writable buffer will be copied before passing +to the transform_ip function.

+
    +
  • Always TRUE if no transform function is implemented.

  • +
  • Always FALSE if ONLY transform function is implemented.

  • +
+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

the GstBaseTransform to modify

 

in_place

Boolean value indicating that we would like to operate +on in_place buffers.

 
+
+
+
+
+

gst_base_transform_is_qos_enabled ()

+
gboolean
+gst_base_transform_is_qos_enabled (GstBaseTransform *trans);
+

Queries if the transform will handle QoS.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstBaseTransform

 
+
+
+

Returns

+

TRUE if QoS is enabled.

+

MT safe.

+
+
+
+
+

gst_base_transform_set_qos_enabled ()

+
void
+gst_base_transform_set_qos_enabled (GstBaseTransform *trans,
+                                    gboolean enabled);
+

Enable or disable QoS handling in the transform.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstBaseTransform

 

enabled

new state

 
+
+
+
+
+

gst_base_transform_update_qos ()

+
void
+gst_base_transform_update_qos (GstBaseTransform *trans,
+                               gdouble proportion,
+                               GstClockTimeDiff diff,
+                               GstClockTime timestamp);
+

Set the QoS parameters in the transform. This function is called internally +when a QOS event is received but subclasses can provide custom information +when needed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

trans

a GstBaseTransform

 

proportion

the proportion

 

diff

the diff against the clock

 

timestamp

the timestamp of the buffer generating the QoS expressed in +running_time.

 
+
+
+
+
+

gst_base_transform_set_gap_aware ()

+
void
+gst_base_transform_set_gap_aware (GstBaseTransform *trans,
+                                  gboolean gap_aware);
+

If gap_aware + is FALSE (the default), output buffers will have the +GST_BUFFER_FLAG_GAP flag unset.

+

If set to TRUE, the element must handle output buffers with this flag set +correctly, i.e. it can assume that the buffer contains neutral data but must +unset the flag if the output is no neutral data.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstBaseTransform

 

gap_aware

New state

 
+
+
+
+
+

gst_base_transform_get_allocator ()

+
void
+gst_base_transform_get_allocator (GstBaseTransform *trans,
+                                  GstAllocator **allocator,
+                                  GstAllocationParams *params);
+

Lets GstBaseTransform sub-classes to know the memory allocator + +used by the base class and its params +.

+

Unref the allocator + after use it.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

trans

a GstBaseTransform

 

allocator

the GstAllocator +used.

[out][allow-none][transfer full]

params

the +GstAllocationParams of allocator +.

[out][allow-none][transfer full]
+
+
+
+
+

gst_base_transform_get_buffer_pool ()

+
GstBufferPool *
+gst_base_transform_get_buffer_pool (GstBaseTransform *trans);
+
+

Parameters

+
+++++ + + + + + +

trans

a GstBaseTransform

 
+
+
+

Returns

+

the instance of the GstBufferPool used +by trans +; free it after use it.

+

[transfer full]

+
+
+
+
+

gst_base_transform_reconfigure_sink ()

+
void
+gst_base_transform_reconfigure_sink (GstBaseTransform *trans);
+

Instructs trans + to request renegotiation upstream. This function is +typically called after properties on the transform were set that +influence the input format.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstBaseTransform

 
+
+
+
+
+

gst_base_transform_reconfigure_src ()

+
void
+gst_base_transform_reconfigure_src (GstBaseTransform *trans);
+

Instructs trans + to renegotiate a new downstream transform on the next +buffer. This function is typically called after properties on the transform +were set that influence the output format.

+
+

Parameters

+
+++++ + + + + + +

trans

a GstBaseTransform

 
+
+
+
+
+

gst_base_transform_update_src_caps ()

+
gboolean
+gst_base_transform_update_src_caps (GstBaseTransform *trans,
+                                    GstCaps *updated_caps);
+

Updates the srcpad caps and send the caps downstream. This function +can be used by subclasses when they have already negotiated their caps +but found a change in them (or computed new informations). This way, +they can notify downstream about that change without loosing any +buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

trans

a GstBaseTransform

 

updated_caps

An updated version of the srcpad caps to be pushed +downstream

 
+
+
+

Returns

+

TRUE if the caps could be send downstream FALSE otherwise

+
+

Since: 1.6

+
+
+
+

GST_BASE_TRANSFORM_SINK_PAD()

+
#define GST_BASE_TRANSFORM_SINK_PAD(obj) (GST_BASE_TRANSFORM_CAST (obj)->sinkpad)
+
+

Gives the pointer to the sink GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base transform instance

 
+
+
+
+
+

GST_BASE_TRANSFORM_SRC_PAD()

+
#define GST_BASE_TRANSFORM_SRC_PAD(obj)		(GST_BASE_TRANSFORM_CAST (obj)->srcpad)
+
+

Gives the pointer to the source GstPad object of the element.

+
+

Parameters

+
+++++ + + + + + +

obj

base transform instance

 
+
+
+
+
+

Types and Values

+
+

struct GstBaseTransform

+
struct GstBaseTransform;
+

The opaque GstBaseTransform data structure.

+
+
+
+

struct GstBaseTransformClass

+
struct GstBaseTransformClass {
+  GstElementClass parent_class;
+
+  gboolean       passthrough_on_same_caps;
+  gboolean       transform_ip_on_passthrough;
+
+  /* virtual methods for subclasses */
+  GstCaps* (*transform_caps) (GstBaseTransform *trans,
+                                   GstPadDirection direction,
+                                   GstCaps *caps, GstCaps *filter);
+  GstCaps* (*fixate_caps)	  (GstBaseTransform *trans,
+                                   GstPadDirection direction, GstCaps *caps,
+                                   GstCaps *othercaps);
+  gboolean      (*accept_caps)    (GstBaseTransform *trans, GstPadDirection direction,
+                                   GstCaps *caps);
+  gboolean      (*set_caps)       (GstBaseTransform *trans, GstCaps *incaps,
+                                   GstCaps *outcaps);
+  gboolean      (*query)          (GstBaseTransform *trans, GstPadDirection direction,
+                                   GstQuery *query);
+
+  /* decide allocation query for output buffers */
+  gboolean      (*decide_allocation)  (GstBaseTransform *trans, GstQuery *query);
+  gboolean      (*filter_meta)        (GstBaseTransform *trans, GstQuery *query,
+                                       GType api, const GstStructure *params);
+
+  /* propose allocation query parameters for input buffers */
+  gboolean      (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query,
+                                       GstQuery *query);
+
+  /**
+   * GstBaseTransformClass::transform_size:
+   * @othersize: (out):
+   */
+  gboolean      (*transform_size) (GstBaseTransform *trans,
+                                   GstPadDirection direction,
+                                   GstCaps *caps, gsize size,
+                                   GstCaps *othercaps, gsize *othersize);
+
+  /**
+   * GstBaseTransformClass::get_unit_size:
+   * @size: (out):
+   */
+  gboolean      (*get_unit_size)  (GstBaseTransform *trans, GstCaps *caps,
+                                   gsize *size);
+
+  /* states */
+  gboolean      (*start)        (GstBaseTransform *trans);
+  gboolean      (*stop)         (GstBaseTransform *trans);
+
+  /* sink and src pad event handlers */
+  gboolean      (*sink_event)   (GstBaseTransform *trans, GstEvent *event);
+  gboolean      (*src_event)    (GstBaseTransform *trans, GstEvent *event);
+
+  /**
+   * GstBaseTransformClass::prepare_output_buffer:
+   * @outbuf: (out):
+   */
+  GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
+                                          GstBuffer *input, GstBuffer **outbuf);
+
+  /* metadata */
+  gboolean      (*copy_metadata)     (GstBaseTransform *trans, GstBuffer *input,
+                                      GstBuffer *outbuf);
+  gboolean      (*transform_meta)    (GstBaseTransform *trans, GstBuffer *outbuf,
+                                      GstMeta *meta, GstBuffer *inbuf);
+
+  void          (*before_transform)  (GstBaseTransform *trans, GstBuffer *buffer);
+
+  /* transform */
+  GstFlowReturn (*transform)    (GstBaseTransform *trans, GstBuffer *inbuf,
+                                 GstBuffer *outbuf);
+  GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
+
+  GstFlowReturn (*submit_input_buffer) (GstBaseTransform *trans, gboolean is_discont, GstBuffer *input);
+
+  /**
+   * GstBaseTransformClass::generate_output:
+   * @outbuf: (out):
+   */
+  GstFlowReturn (*generate_output) (GstBaseTransform *trans, GstBuffer **outbuf);
+};
+
+

Subclasses can override any of the available virtual methods or not, as +needed. At minimum either transform + or transform_ip + need to be overridden. +If the element can overwrite the input data with the results (data is of the +same type and quantity) it should provide transform_ip +.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gboolean passthrough_on_same_caps;

If set to TRUE, passthrough mode will be +automatically enabled if the caps are the same. +Set to FALSE by default.

 

gboolean transform_ip_on_passthrough;

If set to TRUE, transform_ip +will be called in +passthrough mode. The passed buffer might not be +writable. When FALSE, neither transform +nor +transform_ip +will be called in passthrough mode. +Set to TRUE by default.

 

transform_caps ()

Optional. Given the pad in this direction and the given +caps, what caps are allowed on the other pad in this +element ?

 

fixate_caps ()

Optional. Given the pad in this direction and the given +caps, fixate the caps on the other pad. The function takes +ownership of othercaps +and returns a fixated version of +othercaps +. othercaps +is not guaranteed to be writable.

 

accept_caps ()

Optional. +Subclasses can override this method to check if caps +can be +handled by the element. The default implementation might not be +the most optimal way to check this in all cases.

 

set_caps ()

allows the subclass to be notified of the actual caps set.

 

query ()

Optional. +Handle a requested query. Subclasses that implement this +should must chain up to the parent if they didn't handle the +query

 

decide_allocation ()

Setup the allocation parameters for allocating output +buffers. The passed in query contains the result of the +downstream allocation query. This function is only called +when not operating in passthrough mode. The default +implementation will remove all memory dependent metadata. +If there is a filter_meta +method implementation, it will +be called for all metadata API in the downstream query, +otherwise the metadata API is removed.

 

filter_meta ()

Return TRUE if the metadata API should be proposed in the +upstream allocation query. The default implementation is NULL +and will cause all metadata to be removed.

 

propose_allocation ()

Propose buffer allocation parameters for upstream elements. +This function must be implemented if the element reads or +writes the buffer content. The query that was passed to +the decide_allocation is passed in this method (or NULL +when the element is in passthrough mode). The default +implementation will pass the query downstream when in +passthrough mode and will copy all the filtered metadata +API in non-passthrough mode.

 

transform_size ()

Optional. Given the size of a buffer in the given direction +with the given caps, calculate the size in bytes of a buffer +on the other pad with the given other caps. +The default implementation uses get_unit_size and keeps +the number of units the same.

 

get_unit_size ()

Required if the transform is not in-place. +get the size in bytes of one unit for the given caps.

 

start ()

Optional. +Called when the element starts processing. +Allows opening external resources.

 

stop ()

Optional. +Called when the element stops processing. +Allows closing external resources.

 

sink_event ()

Optional. +Event handler on the sink pad. The default implementation +handles the event and forwards it downstream.

 

src_event ()

Optional. +Event handler on the source pad. The default implementation +handles the event and forwards it upstream.

 

prepare_output_buffer ()

Optional. +Subclasses can override this to do their own +allocation of output buffers. Elements that only do +analysis can return a subbuffer or even just +return a reference to the input buffer (if in +passthrough mode). The default implementation will +use the negotiated allocator or bufferpool and +transform_size to allocate an output buffer or it +will return the input buffer in passthrough mode.

 

copy_metadata ()

Optional. +Copy the metadata from the input buffer to the output buffer. +The default implementation will copy the flags, timestamps and +offsets of the buffer.

 

transform_meta ()

Optional. Transform the metadata on the input buffer to the +output buffer. By default this method copies all meta without +tags. subclasses can implement this method and return TRUE if +the metadata is to be copied.

 

before_transform ()

Optional. +This method is called right before the base class will +start processing. Dynamic properties or other delayed +configuration could be performed in this method.

 

transform ()

Required if the element does not operate in-place. +Transforms one incoming buffer to one outgoing buffer. +The function is allowed to change size/timestamp/duration +of the outgoing buffer.

 

transform_ip ()

Required if the element operates in-place. +Transform the incoming buffer in-place.

 

submit_input_buffer ()

Function which accepts a new input buffer and pre-processes it. +The default implementation performs caps (re)negotiation, then +QoS if needed, and places the input buffer into the queued_buf +member variable. If the buffer is dropped due to QoS, it returns +GST_BASE_TRANSFORM_FLOW_DROPPED. If this input buffer is not +contiguous with any previous input buffer, then is_discont +is set to TRUE. (Since 1.6)

 

generate_output ()

Called after each new input buffer is submitted repeatedly +until it either generates an error or fails to generate an output +buffer. The default implementation takes the contents of the +queued_buf +variable, generates an output buffer if needed +by calling the class prepare_output_buffer +, and then +calls either transform +or transform_ip +. Elements that don't +do 1-to-1 transformations on input to output buffers can either +return GST_BASE_TRANSFORM_FLOW_DROPPED or simply not generate +an output buffer until they are ready to do so. (Since 1.6)

 
+
+
+
+
+

GST_BASE_TRANSFORM_SINK_NAME

+
#define GST_BASE_TRANSFORM_SINK_NAME "sink"
+
+

The name of the templates for the sink pad.

+
+
+
+

GST_BASE_TRANSFORM_SRC_NAME

+
#define GST_BASE_TRANSFORM_SRC_NAME "src"
+
+

The name of the templates for the source pad.

+
+
+
+

GST_BASE_TRANSFORM_FLOW_DROPPED

+
#define GST_BASE_TRANSFORM_FLOW_DROPPED   GST_FLOW_CUSTOM_SUCCESS
+
+

A GstFlowReturn that can be returned from transform and transform_ip to +indicate that no output buffer was generated.

+
+
+
+

Property Details

+
+

The “qos” property

+
  “qos”                      gboolean
+

Handle Quality-of-Service events.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

See Also

+

GstBaseSrc, GstBaseSink

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstCollectPads.html b/docs/libs/html/GstCollectPads.html new file mode 100644 index 0000000..d000c28 --- /dev/null +++ b/docs/libs/html/GstCollectPads.html @@ -0,0 +1,2155 @@ + + + + +GstCollectPads: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstCollectPads

+

GstCollectPads — manages a set of pads that operate in collect mode

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +(*GstCollectDataDestroyNotify) () +
+GstFlowReturn + +(*GstCollectPadsBufferFunction) () +
+GstFlowReturn + +(*GstCollectPadsClipFunction) () +
+gint + +(*GstCollectPadsCompareFunction) () +
+gboolean + +(*GstCollectPadsEventFunction) () +
+void + +(*GstCollectPadsFlushFunction) () +
+gboolean + +(*GstCollectPadsQueryFunction) () +
+GstFlowReturn + +(*GstCollectPadsFunction) () +
#define +GST_COLLECT_PADS_STATE() +
#define +GST_COLLECT_PADS_STATE_IS_SET() +
#define +GST_COLLECT_PADS_STATE_SET() +
#define +GST_COLLECT_PADS_STATE_UNSET() +
#define +GST_COLLECT_PADS_GET_STREAM_LOCK() +
#define +GST_COLLECT_PADS_STREAM_LOCK() +
#define +GST_COLLECT_PADS_STREAM_UNLOCK() +
#define +GST_COLLECT_PADS_DTS() +
#define +GST_COLLECT_PADS_DTS_IS_VALID() +
+GstCollectPads * + +gst_collect_pads_new () +
+GstCollectData * + +gst_collect_pads_add_pad () +
+gboolean + +gst_collect_pads_remove_pad () +
+void + +gst_collect_pads_start () +
+void + +gst_collect_pads_stop () +
+guint + +gst_collect_pads_available () +
+guint + +gst_collect_pads_flush () +
+GstBuffer * + +gst_collect_pads_peek () +
+GstBuffer * + +gst_collect_pads_pop () +
+GstBuffer * + +gst_collect_pads_read_buffer () +
+GstBuffer * + +gst_collect_pads_take_buffer () +
+GstFlowReturn + +gst_collect_pads_clip_running_time () +
+gboolean + +gst_collect_pads_query_default () +
+gboolean + +gst_collect_pads_event_default () +
+gboolean + +gst_collect_pads_src_event_default () +
+void + +gst_collect_pads_set_buffer_function () +
+void + +gst_collect_pads_set_clip_function () +
+void + +gst_collect_pads_set_compare_function () +
+void + +gst_collect_pads_set_event_function () +
+void + +gst_collect_pads_set_flush_function () +
+void + +gst_collect_pads_set_query_function () +
+void + +gst_collect_pads_set_flushing () +
+void + +gst_collect_pads_set_function () +
+void + +gst_collect_pads_set_waiting () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstCollectPads
structGstCollectData
enumGstCollectPadsStateFlags
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstCollectPads
+
+
+
+

Includes

+
#include <gst/base/gstcollectpads.h>
+
+
+
+

Description

+

Manages a set of pads that operate in collect mode. This means that control +is given to the manager of this object when all pads have data.

+
    +
  • Collectpads are created with gst_collect_pads_new(). A callback should then +be installed with gst_collect_pads_set_function().

  • +
  • Pads are added to the collection with gst_collect_pads_add_pad()/ +gst_collect_pads_remove_pad(). The pad has to be a sinkpad. When added, +the chain, event and query functions of the pad are overridden. The +element_private of the pad is used to store private information for the +collectpads.

  • +
  • For each pad, data is queued in the _chain function or by +performing a pull_range.

  • +
  • When data is queued on all pads in waiting mode, the callback function is called.

  • +
  • Data can be dequeued from the pad with the gst_collect_pads_pop() method. +One can peek at the data with the gst_collect_pads_peek() function. +These functions will return NULL if the pad received an EOS event. When all +pads return NULL from a gst_collect_pads_peek(), the element can emit an EOS +event itself.

  • +
  • Data can also be dequeued in byte units using the gst_collect_pads_available(), +gst_collect_pads_read_buffer() and gst_collect_pads_flush() calls.

  • +
  • Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in +their state change functions to start and stop the processing of the collectpads. +The gst_collect_pads_stop() call should be called before calling the parent +element state change function in the PAUSED_TO_READY state change to ensure +no pad is blocked and the element can finish streaming.

  • +
  • gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode. +CollectPads element is not waiting for data to be collected on non-waiting pads. +Thus these pads may but need not have data when the callback is called. +All pads are in waiting mode by default.

  • +
+
+
+

Functions

+
+

GstCollectDataDestroyNotify ()

+
void
+(*GstCollectDataDestroyNotify) (GstCollectData *data);
+

A function that will be called when the GstCollectData will be freed. +It is passed the pointer to the structure and should free any custom +memory and resources allocated for it.

+
+

Parameters

+
+++++ + + + + + +

data

the GstCollectData that will be freed

 
+
+
+
+
+

GstCollectPadsBufferFunction ()

+
GstFlowReturn
+(*GstCollectPadsBufferFunction) (GstCollectPads *pads,
+                                 GstCollectData *data,
+                                 GstBuffer *buffer,
+                                 gpointer user_data);
+

A function that will be called when a (considered oldest) buffer can be muxed. +If all pads have reached EOS, this function is called with NULL buffer + +and NULL data +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pads

the GstCollectPads that triggered the callback

 

data

the GstCollectData of pad that has received the buffer

 

buffer

the GstBuffer.

[transfer full]

user_data

user data passed to gst_collect_pads_set_buffer_function()

 
+
+
+

Returns

+

GST_FLOW_OK for success

+
+
+
+
+

GstCollectPadsClipFunction ()

+
GstFlowReturn
+(*GstCollectPadsClipFunction) (GstCollectPads *pads,
+                               GstCollectData *data,
+                               GstBuffer *inbuffer,
+                               GstBuffer **outbuffer,
+                               gpointer user_data);
+

A function that will be called when inbuffer + is received on the pad managed +by data + in the collectpad object pads +.

+

The function should use the segment of data + and the negotiated media type on +the pad to perform clipping of inbuffer +.

+

This function takes ownership of inbuffer + and should output a buffer in +outbuffer + or return NULL in outbuffer + if the buffer should be dropped.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pads

a GstCollectPads

 

data

a GstCollectData

 

inbuffer

the input GstBuffer.

[transfer full]

outbuffer

the output GstBuffer.

[out]

user_data

user data

 
+
+
+

Returns

+

a GstFlowReturn that corresponds to the result of clipping.

+
+
+
+
+

GstCollectPadsCompareFunction ()

+
gint
+(*GstCollectPadsCompareFunction) (GstCollectPads *pads,
+                                  GstCollectData *data1,
+                                  GstClockTime timestamp1,
+                                  GstCollectData *data2,
+                                  GstClockTime timestamp2,
+                                  gpointer user_data);
+

A function for comparing two timestamps of buffers or newsegments collected on one pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pads

the GstCollectPads that is comparing the timestamps

 

data1

the first GstCollectData

 

timestamp1

the first timestamp

 

data2

the second GstCollectData

 

timestamp2

the second timestamp

 

user_data

user data passed to gst_collect_pads_set_compare_function()

 
+
+
+

Returns

+

Integer less than zero when first timestamp is deemed older than the second one. +Zero if the timestamps are deemed equally old. +Integer greater than zero when second timestamp is deemed older than the first one.

+
+
+
+
+

GstCollectPadsEventFunction ()

+
gboolean
+(*GstCollectPadsEventFunction) (GstCollectPads *pads,
+                                GstCollectData *pad,
+                                GstEvent *event,
+                                gpointer user_data);
+

A function that will be called while processing an event. It takes +ownership of the event and is responsible for chaining up (to +gst_collect_pads_event_default()) or dropping events (such typical cases +being handled by the default handler).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pads

the GstCollectPads that triggered the callback

 

pad

the GstPad that received an event

 

event

the GstEvent received

 

user_data

user data passed to gst_collect_pads_set_event_function()

 
+
+
+

Returns

+

TRUE if the pad could handle the event

+
+
+
+
+

GstCollectPadsFlushFunction ()

+
void
+(*GstCollectPadsFlushFunction) (GstCollectPads *pads,
+                                gpointer user_data);
+

A function that will be called while processing a flushing seek event.

+

The function should flush any internal state of the element and the state of +all the pads. It should clear only the state not directly managed by the +pads + object. It is therefore not necessary to call +gst_collect_pads_set_flushing nor gst_collect_pads_clear from this function.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

a GstCollectPads

 

user_data

user data

 
+
+

Since: 1.4

+
+
+
+

GstCollectPadsQueryFunction ()

+
gboolean
+(*GstCollectPadsQueryFunction) (GstCollectPads *pads,
+                                GstCollectData *pad,
+                                GstQuery *query,
+                                gpointer user_data);
+

A function that will be called while processing a query. It takes +ownership of the query and is responsible for chaining up (to +events downstream (with gst_pad_event_default()).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pads

the GstCollectPads that triggered the callback

 

pad

the GstPad that received an event

 

query

the GstEvent received

 

user_data

user data passed to gst_collect_pads_set_query_function()

 
+
+
+

Returns

+

TRUE if the pad could handle the event

+
+
+
+
+

GstCollectPadsFunction ()

+
GstFlowReturn
+(*GstCollectPadsFunction) (GstCollectPads *pads,
+                           gpointer user_data);
+

A function that will be called when all pads have received data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

the GstCollectPads that triggered the callback

 

user_data

user data passed to gst_collect_pads_set_function()

 
+
+
+

Returns

+

GST_FLOW_OK for success

+
+
+
+
+

GST_COLLECT_PADS_STATE()

+
#define GST_COLLECT_PADS_STATE(data)                 (((GstCollectData *) data)->state)
+
+

A flags word containing GstCollectPadsStateFlags flags set +on this collected pad.

+
+

Parameters

+
+++++ + + + + + +

data

a GstCollectData.

 
+
+
+
+
+

GST_COLLECT_PADS_STATE_IS_SET()

+
#define GST_COLLECT_PADS_STATE_IS_SET(data,flag)     !!(GST_COLLECT_PADS_STATE (data) & flag)
+
+

Gives the status of a specific flag on a collected pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

a GstCollectData.

 

flag

the GstCollectPadsStateFlags to check.

 
+
+
+
+
+

GST_COLLECT_PADS_STATE_SET()

+
#define GST_COLLECT_PADS_STATE_SET(data,flag)        (GST_COLLECT_PADS_STATE (data) |= flag)
+
+

Sets a state flag on a collected pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

a GstCollectData.

 

flag

the GstCollectPadsStateFlags to set.

 
+
+
+
+
+

GST_COLLECT_PADS_STATE_UNSET()

+
#define GST_COLLECT_PADS_STATE_UNSET(data,flag)      (GST_COLLECT_PADS_STATE (data) &= ~(flag))
+
+

Clears a state flag on a collected pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

a GstCollectData.

 

flag

the GstCollectPadsStateFlags to clear.

 
+
+
+
+
+

GST_COLLECT_PADS_GET_STREAM_LOCK()

+
#define GST_COLLECT_PADS_GET_STREAM_LOCK(pads) (&((GstCollectPads *)pads)->stream_lock)
+
+

Get the stream lock of pads +. The stream lock is used to coordinate and +serialize execution among the various streams being collected, and in +protecting the resources used to accomplish this.

+
+

Parameters

+
+++++ + + + + + +

pads

a GstCollectPads

 
+
+
+
+
+

GST_COLLECT_PADS_STREAM_LOCK()

+
#define GST_COLLECT_PADS_STREAM_LOCK(pads)     g_rec_mutex_lock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads))
+
+

Lock the stream lock of pads +.

+
+

Parameters

+
+++++ + + + + + +

pads

a GstCollectPads

 
+
+
+
+
+

GST_COLLECT_PADS_STREAM_UNLOCK()

+
#define GST_COLLECT_PADS_STREAM_UNLOCK(pads)   g_rec_mutex_unlock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads))
+
+

Unlock the stream lock of pads +.

+
+

Parameters

+
+++++ + + + + + +

pads

a GstCollectPads

 
+
+
+
+
+

GST_COLLECT_PADS_DTS()

+
#define GST_COLLECT_PADS_DTS(data)                   (((GstCollectData *) data)->ABI.abi.dts)
+
+

Returns the DTS that has been converted to running time when using +gst_collect_pads_clip_running_time(). Unlike the value saved into +the buffer, this value is of type gint64 and may be negative. This allow +properly handling streams with frame reordering where the first DTS may +be negative. If the initial DTS was not set, this value will be +set to G_MININT64.

+
+

Parameters

+
+++++ + + + + + +

data

A GstCollectData.

 
+
+

Since: 1.6

+
+
+
+

GST_COLLECT_PADS_DTS_IS_VALID()

+
#define GST_COLLECT_PADS_DTS_IS_VALID(data)          (GST_CLOCK_STIME_IS_VALID (GST_COLLECT_PADS_DTS (data)))
+
+

Check if running DTS value store is valid.

+
+

Parameters

+
+++++ + + + + + +

data

A GstCollectData.

 
+
+

Since: 1.6

+
+
+
+

gst_collect_pads_new ()

+
GstCollectPads *
+gst_collect_pads_new (void);
+

Create a new instance of GstCollectPads.

+

MT safe.

+
+

Returns

+

a new GstCollectPads, or NULL in case of an error.

+

[transfer full]

+
+
+
+
+

gst_collect_pads_add_pad ()

+
GstCollectData *
+gst_collect_pads_add_pad (GstCollectPads *pads,
+                          GstPad *pad,
+                          guint size,
+                          GstCollectDataDestroyNotify destroy_notify,
+                          gboolean lock);
+

Add a pad to the collection of collect pads. The pad has to be +a sinkpad. The refcount of the pad is incremented. Use +gst_collect_pads_remove_pad() to remove the pad from the collection +again.

+

You specify a size for the returned GstCollectData structure +so that you can use it to store additional information.

+

You can also specify a GstCollectDataDestroyNotify that will be called +just before the GstCollectData structure is freed. It is passed the +pointer to the structure and should free any custom memory and resources +allocated for it.

+

Keeping a pad locked in waiting state is only relevant when using +the default collection algorithm (providing the oldest buffer). +It ensures a buffer must be available on this pad for a collection +to take place. This is of typical use to a muxer element where +non-subtitle streams should always be in waiting state, +e.g. to assure that caps information is available on all these streams +when initial headers have to be written.

+

The pad will be automatically activated in push mode when pads + is +started.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

pad

the pad to add.

[transfer none]

size

the size of the returned GstCollectData structure

 

destroy_notify

function to be called before the returned +GstCollectData structure is freed.

[scope async]

lock

whether to lock this pad in usual waiting state

 
+
+
+

Returns

+

a new GstCollectData to identify the +new pad. Or NULL if wrong parameters are supplied.

+

[nullable][transfer none]

+
+
+
+
+

gst_collect_pads_remove_pad ()

+
gboolean
+gst_collect_pads_remove_pad (GstCollectPads *pads,
+                             GstPad *pad);
+

Remove a pad from the collection of collect pads. This function will also +free the GstCollectData and all the resources that were allocated with +gst_collect_pads_add_pad().

+

The pad will be deactivated automatically when pads + is stopped.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

the collectpads to use

 

pad

the pad to remove.

[transfer none]
+
+
+

Returns

+

TRUE if the pad could be removed.

+
+
+
+
+

gst_collect_pads_start ()

+
void
+gst_collect_pads_start (GstCollectPads *pads);
+

Starts the processing of data in the collect_pads.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pads

the collectpads to use

 
+
+
+
+
+

gst_collect_pads_stop ()

+
void
+gst_collect_pads_stop (GstCollectPads *pads);
+

Stops the processing of data in the collect_pads. this function +will also unblock any blocking operations.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pads

the collectpads to use

 
+
+
+
+
+

gst_collect_pads_available ()

+
guint
+gst_collect_pads_available (GstCollectPads *pads);
+

Query how much bytes can be read from each queued buffer. This means +that the result of this call is the maximum number of bytes that can +be read from each of the pads.

+

This function should be called with pads + STREAM_LOCK held, such as +in the callback.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pads

the collectpads to query

 
+
+
+

Returns

+

The maximum number of bytes queued on all pads. This function +returns 0 if a pad has no queued buffer.

+
+
+
+
+

gst_collect_pads_flush ()

+
guint
+gst_collect_pads_flush (GstCollectPads *pads,
+                        GstCollectData *data,
+                        guint size);
+

Flush size + bytes from the pad data +.

+

This function should be called with pads + STREAM_LOCK held, such as +in the callback.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to query

 

data

the data to use

 

size

the number of bytes to flush

 
+
+
+

Returns

+

The number of bytes flushed This can be less than size +and +is 0 if the pad was end-of-stream.

+
+
+
+
+

gst_collect_pads_peek ()

+
GstBuffer *
+gst_collect_pads_peek (GstCollectPads *pads,
+                       GstCollectData *data);
+

Peek at the buffer currently queued in data +. This function +should be called with the pads + STREAM_LOCK held, such as in the callback +handler.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

the collectpads to peek

 

data

the data to use

 
+
+
+

Returns

+

The buffer in data +or NULL if no +buffer is queued. should unref the buffer after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_collect_pads_pop ()

+
GstBuffer *
+gst_collect_pads_pop (GstCollectPads *pads,
+                      GstCollectData *data);
+

Pop the buffer currently queued in data +. This function +should be called with the pads + STREAM_LOCK held, such as in the callback +handler.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

the collectpads to pop

 

data

the data to use

 
+
+
+

Returns

+

The buffer in data +or NULL if no +buffer was queued. You should unref the buffer after usage.

+

[transfer full][nullable]

+
+
+
+
+

gst_collect_pads_read_buffer ()

+
GstBuffer *
+gst_collect_pads_read_buffer (GstCollectPads *pads,
+                              GstCollectData *data,
+                              guint size);
+

Get a subbuffer of size + bytes from the given pad data +.

+

This function should be called with pads + STREAM_LOCK held, such as in the +callback.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to query

 

data

the data to use

 

size

the number of bytes to read

 
+
+
+

Returns

+

A sub buffer. The size of the buffer can +be less that requested. A return of NULL signals that the pad is +end-of-stream. Unref the buffer after use.

+

[transfer full][nullable]

+
+
+
+
+

gst_collect_pads_take_buffer ()

+
GstBuffer *
+gst_collect_pads_take_buffer (GstCollectPads *pads,
+                              GstCollectData *data,
+                              guint size);
+

Get a subbuffer of size + bytes from the given pad data +. Flushes the amount +of read bytes.

+

This function should be called with pads + STREAM_LOCK held, such as in the +callback.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to query

 

data

the data to use

 

size

the number of bytes to read

 
+
+
+

Returns

+

A sub buffer. The size of the buffer can +be less that requested. A return of NULL signals that the pad is +end-of-stream. Unref the buffer after use.

+

[transfer full][nullable]

+
+
+
+
+

gst_collect_pads_clip_running_time ()

+
GstFlowReturn
+gst_collect_pads_clip_running_time (GstCollectPads *pads,
+                                    GstCollectData *cdata,
+                                    GstBuffer *buf,
+                                    GstBuffer **outbuf,
+                                    gpointer user_data);
+

Convenience clipping function that converts incoming buffer's timestamp +to running time, or clips the buffer if outside configured segment.

+

Since 1.6, this clipping function also sets the DTS parameter of the +GstCollectData structure. This version of the running time DTS can be +negative. G_MININT64 is used to indicate invalid value.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

cdata

collect data of corresponding pad

 

buf

buffer being clipped

 

outbuf

output buffer with running time, or NULL if clipped.

[allow-none][out]

user_data

user data (unused)

 
+
+
+
+
+

gst_collect_pads_query_default ()

+
gboolean
+gst_collect_pads_query_default (GstCollectPads *pads,
+                                GstCollectData *data,
+                                GstQuery *query,
+                                gboolean discard);
+

Default GstCollectPads query handling that elements should always +chain up to to ensure proper operation. Element might however indicate +query should not be forwarded downstream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

data

collect data of corresponding pad

 

query

query being processed

 

discard

process but do not send event downstream

 
+
+
+
+
+

gst_collect_pads_event_default ()

+
gboolean
+gst_collect_pads_event_default (GstCollectPads *pads,
+                                GstCollectData *data,
+                                GstEvent *event,
+                                gboolean discard);
+

Default GstCollectPads event handling that elements should always +chain up to to ensure proper operation. Element might however indicate +event should not be forwarded downstream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

data

collect data of corresponding pad

 

event

event being processed

 

discard

process but do not send event downstream

 
+
+
+
+
+

gst_collect_pads_src_event_default ()

+
gboolean
+gst_collect_pads_src_event_default (GstCollectPads *pads,
+                                    GstPad *pad,
+                                    GstEvent *event);
+

Default GstCollectPads event handling for the src pad of elements. +Elements can chain up to this to let flushing seek event handling +be done by GstCollectPads.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the GstCollectPads to use

 

pad

src GstPad that received the event

 

event

event being processed

 
+
+

Since: 1.4

+
+
+
+

gst_collect_pads_set_buffer_function ()

+
void
+gst_collect_pads_set_buffer_function (GstCollectPads *pads,
+                                      GstCollectPadsBufferFunction func,
+                                      gpointer user_data);
+

Set the callback function and user data that will be called with +the oldest buffer when all pads have been collected, or NULL on EOS. +If a buffer is passed, the callback owns a reference and must unref +it.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

func

the function to set.

[scope call]

user_data

user data passed to the function.

[closure]
+
+
+
+
+

gst_collect_pads_set_clip_function ()

+
void
+gst_collect_pads_set_clip_function (GstCollectPads *pads,
+                                    GstCollectPadsClipFunction clipfunc,
+                                    gpointer user_data);
+

Install a clipping function that is called right after a buffer is received +on a pad managed by pads +. See GstCollectPadsClipFunction for more info.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

clipfunc

clip function to install.

[scope call]

user_data

user data to pass to clip_func +

 
+
+
+
+
+

gst_collect_pads_set_compare_function ()

+
void
+gst_collect_pads_set_compare_function (GstCollectPads *pads,
+                                       GstCollectPadsCompareFunction func,
+                                       gpointer user_data);
+

Set the timestamp comparison function.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the pads to use

 

func

the function to set.

[scope call]

user_data

user data passed to the function.

[closure]
+
+
+
+
+

gst_collect_pads_set_event_function ()

+
void
+gst_collect_pads_set_event_function (GstCollectPads *pads,
+                                     GstCollectPadsEventFunction func,
+                                     gpointer user_data);
+

Set the event callback function and user data that will be called when +collectpads has received an event originating from one of the collected +pads. If the event being processed is a serialized one, this callback is +called with pads + STREAM_LOCK held, otherwise not. As this lock should be +held when calling a number of CollectPads functions, it should be acquired +if so (unusually) needed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

func

the function to set.

[scope call]

user_data

user data passed to the function

 
+
+
+
+
+

gst_collect_pads_set_flush_function ()

+
void
+gst_collect_pads_set_flush_function (GstCollectPads *pads,
+                                     GstCollectPadsFlushFunction func,
+                                     gpointer user_data);
+

Install a flush function that is called when the internal +state of all pads should be flushed as part of flushing seek +handling. See GstCollectPadsFlushFunction for more info.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

func

flush function to install.

[scope call]

user_data

user data to pass to func +

 
+
+

Since: 1.4

+
+
+
+

gst_collect_pads_set_query_function ()

+
void
+gst_collect_pads_set_query_function (GstCollectPads *pads,
+                                     GstCollectPadsQueryFunction func,
+                                     gpointer user_data);
+

Set the query callback function and user data that will be called after +collectpads has received a query originating from one of the collected +pads. If the query being processed is a serialized one, this callback is +called with pads + STREAM_LOCK held, otherwise not. As this lock should be +held when calling a number of CollectPads functions, it should be acquired +if so (unusually) needed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

func

the function to set.

[scope call]

user_data

user data passed to the function

 
+
+
+
+
+

gst_collect_pads_set_flushing ()

+
void
+gst_collect_pads_set_flushing (GstCollectPads *pads,
+                               gboolean flushing);
+

Change the flushing state of all the pads in the collection. No pad +is able to accept anymore data when flushing + is TRUE. Calling this +function with flushing + FALSE makes pads + accept data again. +Caller must ensure that downstream streaming (thread) is not blocked, +e.g. by sending a FLUSH_START downstream.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

pads

the collectpads to use

 

flushing

desired state of the pads

 
+
+
+
+
+

gst_collect_pads_set_function ()

+
void
+gst_collect_pads_set_function (GstCollectPads *pads,
+                               GstCollectPadsFunction func,
+                               gpointer user_data);
+

CollectPads provides a default collection algorithm that will determine +the oldest buffer available on all of its pads, and then delegate +to a configured callback. +However, if circumstances are more complicated and/or more control +is desired, this sets a callback that will be invoked instead when +all the pads added to the collection have buffers queued. +Evidently, this callback is not compatible with +gst_collect_pads_set_buffer_function() callback. +If this callback is set, the former will be unset.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads to use

 

func

the function to set.

[scope call]

user_data

user data passed to the function

 
+
+
+
+
+

gst_collect_pads_set_waiting ()

+
void
+gst_collect_pads_set_waiting (GstCollectPads *pads,
+                              GstCollectData *data,
+                              gboolean waiting);
+

Sets a pad to waiting or non-waiting mode, if at least this pad +has not been created with locked waiting state, +in which case nothing happens.

+

This function should be called with pads + STREAM_LOCK held, such as +in the callback.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

pads

the collectpads

 

data

the data to use

 

waiting

boolean indicating whether this pad should operate +in waiting or non-waiting mode

 
+
+
+
+
+

Types and Values

+
+

struct GstCollectPads

+
struct GstCollectPads {
+  GSList        *data;                  /* list of CollectData items */
+};
+
+

Collectpads object.

+
+

Members

+
+++++ + + + + + +

GSList *data;

GList of GstCollectData managed +by this GstCollectPads.

[element-type GstBase.CollectData]
+
+
+
+
+

struct GstCollectData

+
struct GstCollectData {
+  /* with STREAM_LOCK of @collect */
+  GstCollectPads        *collect;
+  GstPad                *pad;
+  GstBuffer             *buffer;
+  guint                  pos;
+  GstSegment             segment;
+
+      gint64 dts;
+};
+
+

Structure used by the collect_pads.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstCollectPads *collect;

owner GstCollectPads

 

GstPad *pad;

GstPad managed by this data

 

GstBuffer *buffer;

currently queued buffer.

 

guint pos;

position in the buffer

 

GstSegment segment;

last segment received.

 

gint64 dts;

the signed version of the DTS converted to running time. To access +this memeber, use GST_COLLECT_PADS_DTS macro. (Since 1.6)

 
+
+
+
+
+

enum GstCollectPadsStateFlags

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_COLLECT_PADS_STATE_EOS

+

Set if collectdata's pad is EOS.

+
 

GST_COLLECT_PADS_STATE_FLUSHING

+

Set if collectdata's pad is flushing.

+
 

GST_COLLECT_PADS_STATE_NEW_SEGMENT

+

Set if collectdata's pad received a + new_segment event.

+
 

GST_COLLECT_PADS_STATE_WAITING

+

Set if collectdata's pad must be waited + for when collecting.

+
 

GST_COLLECT_PADS_STATE_LOCKED

+

Set collectdata's pad WAITING state must + not be changed. +GstCollectPadsStateFlags indicate private state of a collectdata('s pad).

+
 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstDirectControlBinding.html b/docs/libs/html/GstDirectControlBinding.html new file mode 100644 index 0000000..f0da3a9 --- /dev/null +++ b/docs/libs/html/GstDirectControlBinding.html @@ -0,0 +1,223 @@ + + + + +GstDirectControlBinding: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDirectControlBinding

+

GstDirectControlBinding — direct attachment for control sources

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + + + + + + + + +
gbooleanabsoluteRead / Write / Construct Only
+GstControlSource *control-sourceRead / Write / Construct
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlBinding
+                ╰── GstDirectControlBinding
+
+
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

A value mapping object that attaches control sources to gobject properties. It +will map the control values directly to the target property range. If a +non-absolute direct control binding is used, the value range [0.0 ... 1.0] +is mapped to full target property range, and all values outside the range +will be clipped. An absolute control binding will not do any value +transformations.

+
+
+

Functions

+
+

gst_direct_control_binding_new ()

+
GstControlBinding *
+gst_direct_control_binding_new (GstObject *object,
+                                const gchar *property_name,
+                                GstControlSource *cs);
+

Create a new control-binding that attaches the GstControlSource to the +GObject property. It will map the control source range [0.0 ... 1.0] to +the full target property range, and clip all values outside this range.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object of the property

 

property_name

the property-name to attach the control source

 

cs

the control source

 
+
+
+

Returns

+

the new GstDirectControlBinding.

+

[transfer floating]

+
+
+
+
+

gst_direct_control_binding_new_absolute ()

+
GstControlBinding *
+gst_direct_control_binding_new_absolute
+                               (GstObject *object,
+                                const gchar *property_name,
+                                GstControlSource *cs);
+

Create a new control-binding that attaches the GstControlSource to the +GObject property. It will directly map the control source values to the +target property range without any transformations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object

the object of the property

 

property_name

the property-name to attach the control source

 

cs

the control source

 
+
+
+

Returns

+

the new GstDirectControlBinding.

+

[transfer floating]

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+
+

Property Details

+
+

The “absolute” property

+
  “absolute”                 gboolean
+

Whether the control values are absolute.

+

Flags: Read / Write / Construct Only

+

Default value: FALSE

+
+
+
+

The “control-source” property

+
  “control-source”           GstControlSource *
+

The control source.

+

Flags: Read / Write / Construct

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstInterpolationControlSource.html b/docs/libs/html/GstInterpolationControlSource.html new file mode 100644 index 0000000..5751a64 --- /dev/null +++ b/docs/libs/html/GstInterpolationControlSource.html @@ -0,0 +1,195 @@ + + + + +GstInterpolationControlSource: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstInterpolationControlSource

+

GstInterpolationControlSource — interpolation control source

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + +
GstInterpolationModemodeRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstInterpolationControlSource
enumGstInterpolationMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlSource
+                ╰── GstTimedValueControlSource
+                    ╰── GstInterpolationControlSource
+
+
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

GstInterpolationControlSource is a GstControlSource, that interpolates values between user-given +control points. It supports several interpolation modes and property types.

+

To use GstInterpolationControlSource get a new instance by calling +gst_interpolation_control_source_new(), bind it to a GParamSpec and set some +control points by calling gst_timed_value_control_source_set().

+

All functions are MT-safe.

+
+
+

Functions

+
+

gst_interpolation_control_source_new ()

+
GstControlSource *
+gst_interpolation_control_source_new (void);
+

This returns a new, unbound GstInterpolationControlSource.

+
+

Returns

+

a new, unbound GstInterpolationControlSource.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstInterpolationControlSource

+
struct GstInterpolationControlSource;
+

The instance structure of GstControlSource.

+
+
+
+

enum GstInterpolationMode

+

The various interpolation modes available.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_INTERPOLATION_MODE_NONE

+

steps-like interpolation, default

+
 

GST_INTERPOLATION_MODE_LINEAR

+

linear interpolation

+
 

GST_INTERPOLATION_MODE_CUBIC

+

cubic interpolation (natural), may overshoot + the min or max values set by the control point, but is more 'curvy'

+
 

GST_INTERPOLATION_MODE_CUBIC_MONOTONIC

+

monotonic cubic interpolation, will not + produce any values outside of the min-max range set by the control points + (Since 1.8)

+
 
+
+
+
+
+

Property Details

+
+

The “mode” property

+
  “mode”                     GstInterpolationMode
+

Interpolation mode.

+

Flags: Read / Write

+

Default value: GST_INTERPOLATION_MODE_NONE

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstLFOControlSource.html b/docs/libs/html/GstLFOControlSource.html new file mode 100644 index 0000000..cafc9ef --- /dev/null +++ b/docs/libs/html/GstLFOControlSource.html @@ -0,0 +1,260 @@ + + + + +GstLFOControlSource: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstLFOControlSource

+

GstLFOControlSource — LFO control source

+
+
+

Functions

+
++++ + + + + +
+GstControlSource * + +gst_lfo_control_source_new () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gdoubleamplitudeRead / Write
gdoublefrequencyRead / Write
gdoubleoffsetRead / Write
guint64timeshiftRead / Write
GstLFOWaveformwaveformRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstLFOControlSource
enumGstLFOWaveform
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlSource
+                ╰── GstLFOControlSource
+
+
+
+

Includes

+
#include <libs/controller/gstlfocontrolsource.h>
+
+
+
+

Description

+

GstLFOControlSource is a GstControlSource, that provides several periodic +waveforms as control values.

+

To use GstLFOControlSource get a new instance by calling +gst_lfo_control_source_new(), bind it to a GParamSpec and set the relevant +properties.

+

All functions are MT-safe.

+
+
+

Functions

+
+

gst_lfo_control_source_new ()

+
GstControlSource *
+gst_lfo_control_source_new (void);
+

This returns a new, unbound GstLFOControlSource.

+
+

Returns

+

a new, unbound GstLFOControlSource.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstLFOControlSource

+
struct GstLFOControlSource;
+

The instance structure of GstControlSource.

+
+
+
+

enum GstLFOWaveform

+

The various waveform modes available.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GST_LFO_WAVEFORM_SINE

+

sine waveform

+
 

GST_LFO_WAVEFORM_SQUARE

+

square waveform

+
 

GST_LFO_WAVEFORM_SAW

+

saw waveform

+
 

GST_LFO_WAVEFORM_REVERSE_SAW

+

reverse saw waveform

+
 

GST_LFO_WAVEFORM_TRIANGLE

+

triangle waveform

+
 
+
+
+
+
+

Property Details

+
+

The “amplitude” property

+
  “amplitude”                gdouble
+

Specifies the amplitude for the waveform of this GstLFOControlSource.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 1

+
+
+
+

The “frequency” property

+
  “frequency”                gdouble
+

Specifies the frequency that should be used for the waveform +of this GstLFOControlSource. It should be large enough +so that the period is longer than one nanosecond.

+

Flags: Read / Write

+

Allowed values: >= G_MINDOUBLE

+

Default value: 1

+
+
+
+

The “offset” property

+
  “offset”                   gdouble
+

Specifies the value offset for the waveform of this GstLFOControlSource.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 1

+
+
+
+

The “timeshift” property

+
  “timeshift”                guint64
+

Specifies the timeshift to the right that should be used for the waveform +of this GstLFOControlSource in nanoseconds.

+

To get a n nanosecond shift to the left use +"(GST_SECOND / frequency) - n".

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “waveform” property

+
  “waveform”                 GstLFOWaveform
+

Specifies the waveform that should be used for this GstLFOControlSource.

+

Flags: Read / Write

+

Default value: GST_LFO_WAVEFORM_SINE

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstNetClientClock.html b/docs/libs/html/GstNetClientClock.html new file mode 100644 index 0000000..306f2af --- /dev/null +++ b/docs/libs/html/GstNetClientClock.html @@ -0,0 +1,368 @@ + + + + +GstNetClientClock: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstNetClientClock

+

GstNetClientClock — Special clock that synchronizes to a remote time + provider.

+
+
+

Functions

+
++++ + + + + + + + + + + +
+GstClock * + +gst_net_client_clock_new () +
+GstClock * + +gst_ntp_clock_new () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gchar *addressRead / Write / Construct
guint64base-timeRead / Write / Construct Only
+GstBus *busRead / Write
+GstClock *internal-clockRead
guint64minimum-update-intervalRead / Write
gintportRead / Write / Construct
gintqos-dscpRead / Write
guint64round-trip-limitRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstNetClientClock
typedefGstNtpClock
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstClock
+                ╰── GstSystemClock
+                    ╰── GstNetClientClock
+                        ╰── GstNtpClock
+
+
+
+

Includes

+
#include <gst/net/gstnet.h>
+
+
+
+

Description

+

GstNetClientClock implements a custom GstClock that synchronizes its time +to a remote time provider such as GstNetTimeProvider. GstNtpClock +implements a GstClock that synchronizes its time to a remote NTPv4 server.

+

A new clock is created with gst_net_client_clock_new() or +gst_ntp_clock_new(), which takes the address and port of the remote time +provider along with a name and an initial time.

+

This clock will poll the time provider and will update its calibration +parameters based on the local and remote observations.

+

The "round-trip" property limits the maximum round trip packets can take.

+

Various parameters of the clock can be configured with the parent GstClock +"timeout", "window-size" and "window-threshold" object properties.

+

A GstNetClientClock and GstNtpClock is typically set on a GstPipeline with +gst_pipeline_use_clock().

+

If you set a GstBus on the clock via the "bus" object property, it will +send GST_MESSAGE_ELEMENT + messages with an attached GstStructure containing +statistics about clock accuracy and network traffic.

+
+
+

Functions

+
+

gst_net_client_clock_new ()

+
GstClock *
+gst_net_client_clock_new (const gchar *name,
+                          const gchar *remote_address,
+                          gint remote_port,
+                          GstClockTime base_time);
+

Create a new GstNetClientInternalClock that will report the time +provided by the GstNetTimeProvider on remote_address + and +remote_port +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

name

a name for the clock

 

remote_address

the address or hostname of the remote clock provider

 

remote_port

the port of the remote clock provider

 

base_time

initial time of the clock

 
+
+
+

Returns

+

a new GstClock that receives a time from the remote +clock.

+

[transfer full]

+
+
+
+
+

gst_ntp_clock_new ()

+
GstClock *
+gst_ntp_clock_new (const gchar *name,
+                   const gchar *remote_address,
+                   gint remote_port,
+                   GstClockTime base_time);
+

Create a new GstNtpClock that will report the time provided by +the NTPv4 server on remote_address + and remote_port +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

name

a name for the clock

 

remote_address

the address or hostname of the remote clock provider

 

remote_port

the port of the remote clock provider

 

base_time

initial time of the clock

 
+
+
+

Returns

+

a new GstClock that receives a time from the remote +clock.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstNetClientClock

+
struct GstNetClientClock;
+

Opaque GstNetClientClock structure.

+
+
+
+

GstNtpClock

+
typedef struct _GstNetClientClock GstNtpClock;
+
+
+
+
+

Property Details

+
+

The “address” property

+
  “address”                  gchar *
+

The IP address of the machine providing a time server.

+

Flags: Read / Write / Construct

+

Default value: "127.0.0.1"

+
+
+
+

The “base-time” property

+
  “base-time”                guint64
+

Initial time that is reported before synchronization.

+

Flags: Read / Write / Construct Only

+

Default value: 0

+
+
+
+

The “bus” property

+
  “bus”                      GstBus *
+

A GstBus on which to send clock status information.

+

Flags: Read / Write

+
+
+
+

The “internal-clock” property

+
  “internal-clock”           GstClock *
+

Internal clock that directly slaved to the remote clock.

+

Flags: Read

+
+
+
+

The “minimum-update-interval” property

+
  “minimum-update-interval”  guint64
+

Minimum polling interval for packets, in nanoseconds(0 = no limit).

+

Flags: Read / Write

+

Default value: 50000000

+
+
+
+

The “port” property

+
  “port”                     gint
+

The port on which the remote server is listening.

+

Flags: Read / Write / Construct

+

Allowed values: [0,65535]

+

Default value: 5637

+
+
+
+

The “qos-dscp” property

+
  “qos-dscp”                 gint
+

Quality of Service, differentiated services code point (-1 default).

+

Flags: Read / Write

+

Allowed values: [-1,63]

+

Default value: -1

+
+
+
+

The “round-trip-limit” property

+
  “round-trip-limit”         guint64
+

Maximum tolerable round-trip interval for packets, in nanoseconds (0 = no limit).

+

Flags: Read / Write

+

Default value: 1000000000

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstNetTimeProvider.html b/docs/libs/html/GstNetTimeProvider.html new file mode 100644 index 0000000..a5cf1b9 --- /dev/null +++ b/docs/libs/html/GstNetTimeProvider.html @@ -0,0 +1,239 @@ + + + + +GstNetTimeProvider: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstNetTimeProvider

+

GstNetTimeProvider — Special object that exposed the time of a clock + on the network.

+
+
+

Functions

+
++++ + + + + +
+GstNetTimeProvider * + +gst_net_time_provider_new () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleanactiveRead / Write
+gchar *addressRead / Write / Construct Only
+GstClock *clockRead / Write / Construct Only
gintportRead / Write / Construct Only
gintqos-dscpRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstNetTimeProvider
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstNetTimeProvider
+
+
+
+

Implemented Interfaces

+

+GstNetTimeProvider implements + GInitable.

+
+
+

Includes

+
#include <gst/net/gstnet.h>
+
+
+
+

Description

+

This object exposes the time of a GstClock on the network.

+

A GstNetTimeProvider is created with gst_net_time_provider_new() which +takes a GstClock, an address and a port number as arguments.

+

After creating the object, a client clock such as GstNetClientClock can +query the exposed clock over the network for its values.

+

The GstNetTimeProvider typically wraps the clock used by a GstPipeline.

+
+
+

Functions

+
+

gst_net_time_provider_new ()

+
GstNetTimeProvider *
+gst_net_time_provider_new (GstClock *clock,
+                           const gchar *address,
+                           gint port);
+

Allows network clients to get the current time of clock +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

clock

a GstClock to export over the network

 

address

an address to bind on as a dotted quad +(xxx.xxx.xxx.xxx), IPv6 address, or NULL to bind to all addresses.

[allow-none]

port

a port to bind on, or 0 to let the kernel choose

 
+
+
+

Returns

+

the new GstNetTimeProvider, or NULL on error.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstNetTimeProvider

+
struct GstNetTimeProvider;
+

Opaque GstNetTimeProvider structure.

+
+
+
+

Property Details

+
+

The “active” property

+
  “active”                   gboolean
+

TRUE if the clock will respond to queries over the network.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “address” property

+
  “address”                  gchar *
+

The address to bind on, as a dotted quad (x.x.x.x).

+

Flags: Read / Write / Construct Only

+

Default value: "0.0.0.0"

+
+
+
+

The “clock” property

+
  “clock”                    GstClock *
+

The clock to export over the network.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “port” property

+
  “port”                     gint
+

The port to receive the packets from, 0=allocate.

+

Flags: Read / Write / Construct Only

+

Allowed values: [0,65535]

+

Default value: 5637

+
+
+
+

The “qos-dscp” property

+
  “qos-dscp”                 gint
+

Quality of Service, differentiated services code point (-1 default).

+

Flags: Read / Write

+

Allowed values: [-1,63]

+

Default value: -1

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstPtpClock.html b/docs/libs/html/GstPtpClock.html new file mode 100644 index 0000000..20e573a --- /dev/null +++ b/docs/libs/html/GstPtpClock.html @@ -0,0 +1,556 @@ + + + + +GstPtpClock: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPtpClock

+

GstPtpClock — Special clock that synchronizes to a remote time + provider via PTP (IEEE1588:2008).

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +gst_ptp_init () +
+void + +gst_ptp_deinit () +
+gboolean + +gst_ptp_is_initialized () +
+gboolean + +gst_ptp_is_supported () +
+GstClock * + +gst_ptp_clock_new () +
+gboolean + +(*GstPtpStatisticsCallback) () +
+gulong + +gst_ptp_statistics_callback_add () +
+void + +gst_ptp_statistics_callback_remove () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
guintdomainRead / Write / Construct Only
guint64grandmaster-clock-idRead
+GstClock *internal-clockRead
guint64master-clock-idRead
+
+
+

Types and Values

+ +
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstClock
+                ╰── GstSystemClock
+                    ╰── GstPtpClock
+
+
+
+

Includes

+
#include <gst/net/net.h>
+
+
+
+

Description

+

GstPtpClock implements a PTP (IEEE1588:2008) ordinary clock in slave-only +mode, that allows a GStreamer pipeline to synchronize to a PTP network +clock in some specific domain.

+

The PTP subsystem can be initialized with gst_ptp_init(), which then starts +a helper process to do the actual communication via the PTP ports. This is +required as PTP listens on ports < 1024 and thus requires special +privileges. Once this helper process is started, the main process will +synchronize to all PTP domains that are detected on the selected +interfaces.

+

gst_ptp_clock_new() then allows to create a GstClock that provides the PTP +time from a master clock inside a specific PTP domain. This clock will only +return valid timestamps once the timestamps in the PTP domain are known. To +check this, you can use gst_clock_wait_for_sync(), the GstClock::synced +signal and gst_clock_is_synced().

+

To gather statistics about the PTP clock synchronization, +gst_ptp_statistics_callback_add() can be used. This gives the application +the possibility to collect all kinds of statistics from the clock +synchronization.

+
+
+

Functions

+
+

gst_ptp_init ()

+
gboolean
+gst_ptp_init (guint64 clock_id,
+              gchar **interfaces);
+

Initialize the GStreamer PTP subsystem and create a PTP ordinary clock in +slave-only mode for all domains on the given interfaces + with the +given clock_id +.

+

If clock_id + is GST_PTP_CLOCK_ID_NONE, a clock id is automatically +generated from the MAC address of the first network interface.

+

This function is automatically called by gst_ptp_clock_new() with default +parameters if it wasn't called before.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

clock_id

PTP clock id of this process' clock or GST_PTP_CLOCK_ID_NONE

 

interfaces

network interfaces to run the clock on.

[transfer none][array zero-terminated=1][allow-none]
+
+
+

Returns

+

TRUE if the GStreamer PTP clock subsystem could be initialized.

+
+

Since: 1.6

+
+
+
+

gst_ptp_deinit ()

+
void
+gst_ptp_deinit (void);
+

Deinitialize the GStreamer PTP subsystem and stop the PTP clock. If there +are any remaining GstPtpClock instances, they won't be further synchronized +to the PTP network clock.

+

Since: 1.6

+
+
+
+

gst_ptp_is_initialized ()

+
gboolean
+gst_ptp_is_initialized (void);
+

Check if the GStreamer PTP clock subsystem is initialized.

+
+

Returns

+

TRUE if the GStreamer PTP clock subsystem is intialized.

+
+

Since: 1.6

+
+
+
+

gst_ptp_is_supported ()

+
gboolean
+gst_ptp_is_supported (void);
+

Check if PTP clocks are generally supported on this system, and if previous +initializations did not fail.

+
+

Returns

+

TRUE if PTP clocks are generally supported on this system, and +previous initializations did not fail.

+
+

Since: 1.6

+
+
+
+

gst_ptp_clock_new ()

+
GstClock *
+gst_ptp_clock_new (const gchar *name,
+                   guint domain);
+

Creates a new PTP clock instance that exports the PTP time of the master +clock in domain +. This clock can be slaved to other clocks as needed.

+

If gst_ptp_init() was not called before, this will call gst_ptp_init() with +default parameters.

+

This clock only returns valid timestamps after it received the first +times from the PTP master clock on the network. Once this happens the +GstPtpClock::internal-clock property will become non-NULL. You can +check this with gst_clock_wait_for_sync(), the GstClock::synced signal and +gst_clock_is_synced().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

name

Name of the clock

 

domain

PTP domain

 
+
+
+

Returns

+

A new GstClock.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

GstPtpStatisticsCallback ()

+
gboolean
+(*GstPtpStatisticsCallback) (guint8 domain,
+                             const GstStructure *stats,
+                             gpointer user_data);
+

The statistics can be the following structures:

+

GST_PTP_STATISTICS_NEW_DOMAIN_FOUND: +"domain" G_TYPE_UINT The domain identifier of the domain +"clock" GST_TYPE_CLOCK The internal clock that is slaved to the + PTP domain

+

GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED: +"domain" G_TYPE_UINT The domain identifier of the domain +"master-clock-id" G_TYPE_UINT64 PTP clock identifier of the selected master + clock +"master-clock-port" G_TYPE_UINT PTP port number of the selected master clock +"grandmaster-clock-id" G_TYPE_UINT64 PTP clock identifier of the grandmaster clock

+

GST_PTP_STATISTICS_PATH_DELAY_MEASURED: +"domain" G_TYPE_UINT The domain identifier of the domain +"mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay +"mean-path-delay" GST_TYPE_CLOCK_TIME Latest mean path delay +"delay-request-delay" GST_TYPE_CLOCK_TIME Delay of DELAY_REQ / DELAY_RESP messages

+

GST_PTP_STATISTICS_TIME_UPDATED: +"domain" G_TYPE_UINT The domain identifier of the domain +"mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay +"local-time" GST_TYPE_CLOCK_TIME Local time that corresponds to ptp-time +"ptp-time" GST_TYPE_CLOCK_TIME Newly measured PTP time at local-time +"estimated-ptp-time" GST_TYPE_CLOCK_TIME Estimated PTP time based on previous measurements +"discontinuity" G_TYPE_INT64 Difference between estimated and measured PTP time +"synced" G_TYPE_BOOLEAN Currently synced to the remote clock +"r-squared" G_TYPE_DOUBLE R² of clock estimation regression +"internal-time" GST_TYPE_CLOCK_TIME Internal time clock parameter +"external-time" GST_TYPE_CLOCK_TIME External time clock parameter +"rate-num" G_TYPE_UINT64 Internal/external rate numerator +"rate-den" G_TYPE_UINT64 Internal/external rate denominator +"rate" G_TYPE_DOUBLE Internal/external rate

+

If FALSE is returned, the callback is removed and never called again.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

domain

PTP domain identifier

 

stats

New statistics

 

user_data

Data passed to gst_ptp_statistics_callback_add()

 
+
+
+
+
+

gst_ptp_statistics_callback_add ()

+
gulong
+gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback,
+                                 gpointer user_data,
+                                 GDestroyNotify destroy_data);
+

Installs a new statistics callback for gathering PTP statistics. See +GstPtpStatisticsCallback for a list of statistics that are provided.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

callback

GstPtpStatisticsCallback to call

 

user_data

Data to pass to the callback

 

destroy_data

GDestroyNotify to destroy the data

 
+
+
+

Returns

+

Id for the callback that can be passed to +gst_ptp_statistics_callback_remove()

+
+

Since: 1.6

+
+
+
+

gst_ptp_statistics_callback_remove ()

+
void
+gst_ptp_statistics_callback_remove (gulong id);
+

Removes a PTP statistics callback that was previously added with +gst_ptp_statistics_callback_add().

+
+

Parameters

+
+++++ + + + + + +

id

Callback id to remove

 
+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GST_PTP_CLOCK_ID_NONE

+
#define GST_PTP_CLOCK_ID_NONE ((guint64) -1)
+
+
+
+
+

struct GstPtpClock

+
struct GstPtpClock;
+

Opaque GstPtpClock structure.

+
+
+
+

GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED

+
#define GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED "GstPtpStatisticsBestMasterClockSelected"
+
+
+
+
+

GST_PTP_STATISTICS_NEW_DOMAIN_FOUND

+
#define GST_PTP_STATISTICS_NEW_DOMAIN_FOUND           "GstPtpStatisticsNewDomainFound"
+
+
+
+
+

GST_PTP_STATISTICS_PATH_DELAY_MEASURED

+
#define GST_PTP_STATISTICS_PATH_DELAY_MEASURED        "GstPtpStatisticsPathDelayMeasured"
+
+
+
+
+

GST_PTP_STATISTICS_TIME_UPDATED

+
#define GST_PTP_STATISTICS_TIME_UPDATED               "GstPtpStatisticsTimeUpdated"
+
+
+
+
+

Property Details

+
+

The “domain” property

+
  “domain”                   guint
+

The PTP domain.

+

Flags: Read / Write / Construct Only

+

Allowed values: <= 255

+

Default value: 0

+
+
+
+

The “grandmaster-clock-id” property

+
  “grandmaster-clock-id”     guint64
+

Grand Master Clock ID.

+

Flags: Read

+

Default value: 0

+
+
+
+

The “internal-clock” property

+
  “internal-clock”           GstClock *
+

Internal clock.

+

Flags: Read

+
+
+
+

The “master-clock-id” property

+
  “master-clock-id”          guint64
+

Master Clock ID.

+

Flags: Read

+

Default value: 0

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstPushSrc.html b/docs/libs/html/GstPushSrc.html new file mode 100644 index 0000000..d63c1f0 --- /dev/null +++ b/docs/libs/html/GstPushSrc.html @@ -0,0 +1,161 @@ + + + + +GstPushSrc: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstPushSrc

+

GstPushSrc — Base class for push based source elements

+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstPushSrc
structGstPushSrcClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstPushSrc
+
+
+
+

Includes

+
#include <gst/base/gstpushsrc.h>
+
+
+
+

Description

+

This class is mostly useful for elements that cannot do +random access, or at least very slowly. The source usually +prefers to push out a fixed size buffer.

+

Subclasses usually operate in a format that is different from the +default GST_FORMAT_BYTES format of GstBaseSrc.

+

Classes extending this base class will usually be scheduled +in a push based mode. If the peer accepts to operate without +offsets and within the limits of the allowed block size, this +class can operate in getrange based mode automatically. To make +this possible, the subclass should implement and override the +SCHEDULING query.

+

The subclass should extend the methods from the baseclass in +addition to the ::create method.

+

Seeking, flushing, scheduling and sync is all handled by this +base class.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstPushSrc

+
struct GstPushSrc;
+

The opaque GstPushSrc data structure.

+
+
+
+

struct GstPushSrcClass

+
struct GstPushSrcClass {
+  GstBaseSrcClass parent_class;
+
+  /* ask the subclass to create a buffer, the default implementation
+   * uses alloc and fill */
+  GstFlowReturn (*create) (GstPushSrc *src, GstBuffer **buf);
+  /* allocate memory for a buffer */
+  GstFlowReturn (*alloc)  (GstPushSrc *src, GstBuffer **buf);
+  /* ask the subclass to fill a buffer */
+  GstFlowReturn (*fill)   (GstPushSrc *src, GstBuffer *buf);
+};
+
+

Subclasses can override any of the available virtual methods or not, as +needed. At the minimum, the fill + method should be overridden to produce +buffers.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

create ()

Ask the subclass to create a buffer. The subclass decides which +size this buffer should be. Other then that, refer to +GstBaseSrc.create() for more details. If this method is +not implemented, alloc +followed by fill +will be called.

 

alloc ()

Ask the subclass to allocate a buffer. The subclass decides which +size this buffer should be. The default implementation will create +a new buffer from the negotiated allocator.

 

fill ()

Ask the subclass to fill the buffer with data.

 
+
+
+
+
+

See Also

+

GstBaseSrc

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstTestClock.html b/docs/libs/html/GstTestClock.html new file mode 100644 index 0000000..dc7ce47 --- /dev/null +++ b/docs/libs/html/GstTestClock.html @@ -0,0 +1,1032 @@ + + + + +GstTestClock: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTestClock

+

GstTestClock — Controllable, deterministic clock for GStreamer unit tests

+
+ +
+

Properties

+
+++++ + + + + + + + + + + + + +
GstClockTypeclock-typeRead / Write
guint64start-timeRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTestClock
structGstTestClockClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstClock
+                ╰── GstTestClock
+
+
+
+

Includes

+
#include <gst/check/gsttestclock.h>
+
+
+
+

Description

+

GstTestClock is an implementation of GstClock which has different +behaviour compared to GstSystemClock. Time for GstSystemClock advances +according to the system time, while time for GstTestClock changes only +when gst_test_clock_set_time() or gst_test_clock_advance_time() are +called. GstTestClock provides unit tests with the possibility to +precisely advance the time in a deterministic manner, independent of the +system time or any other external factors.

+
+

Advancing the time of a GstTestClock +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
#include <gst/gst.h>
+#include <gst/check/gsttestclock.h>
+
+GstClock *clock;
+GstTestClock *test_clock;
+
+clock = gst_test_clock_new ();
+test_clock = GST_TEST_CLOCK (clock);
+GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
+gst_test_clock_advance_time ( test_clock, 1 * GST_SECOND);
+GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
+g_usleep (10 * G_USEC_PER_SEC);
+GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
+gst_test_clock_set_time (test_clock, 42 * GST_SECOND);
+GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
+...
+
+ +

+

GstClock allows for setting up single shot or periodic clock notifications +as well as waiting for these notifications synchronously (using +gst_clock_id_wait()) or asynchronously (using gst_clock_id_wait_async() or +gst_clock_id_wait_async()). This is used by many GStreamer elements, +among them GstBaseSrc and GstBaseSink.

+

GstTestClock keeps track of these clock notifications. By calling +gst_test_clock_wait_for_next_pending_id() or +gst_test_clock_wait_for_multiple_pending_ids() a unit tests may wait for the +next one or several clock notifications to be requested. Additionally unit +tests may release blocked waits in a controlled fashion by calling +gst_test_clock_process_next_clock_id(). This way a unit test can control the +inaccuracy (jitter) of clock notifications, since the test can decide to +release blocked waits when the clock time has advanced exactly to, or past, +the requested clock notification time.

+

There are also interfaces for determining if a notification belongs to a +GstTestClock or not, as well as getting the number of requested clock +notifications so far.

+

N.B.: When a unit test waits for a certain amount of clock notifications to +be requested in gst_test_clock_wait_for_next_pending_id() or +gst_test_clock_wait_for_multiple_pending_ids() then these functions may block +for a long time. If they block forever then the expected clock notifications +were never requested from GstTestClock, and so the assumptions in the code +of the unit test are wrong. The unit test case runner in gstcheck is +expected to catch these cases either by the default test case timeout or the +one set for the unit test by calling tcase_set_timeout().

+

The sample code below assumes that the element under test will delay a +buffer pushed on the source pad by some latency until it arrives on the sink +pad. Moreover it is assumed that the element will at some point call +gst_clock_id_wait() to synchronously wait for a specific time. The first +buffer sent will arrive exactly on time only delayed by the latency. The +second buffer will arrive a little late (7ms) due to simulated jitter in the +clock notification.

+
+
+

Demonstration of how to work with clock notifications and GstTestClock +

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+#include <gst/check/gsttestclock.h>
+
+GstClockTime latency;
+GstElement *element;
+GstPad *srcpad;
+GstClock *clock;
+GstTestClock *test_clock;
+GstBuffer buf;
+GstClockID pending_id;
+GstClockID processed_id;
+
+latency = 42 * GST_MSECOND;
+element = create_element (latency, ...);
+srcpad = get_source_pad (element);
+
+clock = gst_test_clock_new ();
+test_clock = GST_TEST_CLOCK (clock);
+gst_element_set_clock (element, clock);
+
+GST_INFO ("Set time, create and push the first buffer\n");
+gst_test_clock_set_time (test_clock, 0);
+buf = create_test_buffer (gst_clock_get_time (clock), ...);
+gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
+
+GST_INFO ("Block until element is waiting for a clock notification\n");
+gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
+GST_INFO ("Advance to the requested time of the clock notification\n");
+gst_test_clock_advance_time (test_clock, latency);
+GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
+processed_id = gst_test_clock_process_next_clock_id (test_clock);
+g_assert (processed_id == pending_id);
+g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
+gst_clock_id_unref (pending_id);
+gst_clock_id_unref (processed_id);
+
+GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
+g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
+buf = get_buffer_pushed_by_element (element, ...);
+g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency);
+gst_buffer_unref (buf);
+GST_INFO ("Check that element does not wait for any clock notification\n");
+g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
+
+GST_INFO ("Set time, create and push the second buffer\n");
+gst_test_clock_advance_time (test_clock, 10 * GST_SECOND);
+buf = create_test_buffer (gst_clock_get_time (clock), ...);
+gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
+
+GST_INFO ("Block until element is waiting for a new clock notification\n");
+(gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
+GST_INFO ("Advance past 7ms beyond the requested time of the clock notification\n");
+gst_test_clock_advance_time (test_clock, latency + 7 * GST_MSECOND);
+GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
+processed_id = gst_test_clock_process_next_clock_id (test_clock);
+g_assert (processed_id == pending_id);
+g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
+gst_clock_id_unref (pending_id);
+gst_clock_id_unref (processed_id);
+
+GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
+g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
+buf = get_buffer_pushed_by_element (element, ...);
+g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==,
+    10 * GST_SECOND + latency + 7 * GST_MSECOND);
+gst_buffer_unref (buf);
+GST_INFO ("Check that element does not wait for any clock notification\n");
+g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
+...
+
+ +

+

Since GstTestClock is only supposed to be used in unit tests it calls +g_assert(), g_assert_cmpint() or g_assert_cmpuint() to validate all function +arguments. This will highlight any issues with the unit test code itself.

+
+
+
+

Functions

+
+

gst_test_clock_new ()

+
GstClock *
+gst_test_clock_new (void);
+

Creates a new test clock with its time set to zero.

+

MT safe.

+
+

Returns

+

a GstTestClock cast to GstClock.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_test_clock_new_with_start_time ()

+
GstClock *
+gst_test_clock_new_with_start_time (GstClockTime start_time);
+

Creates a new test clock with its time set to the specified time.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

start_time

a GstClockTime set to the desired start time of the clock.

 
+
+
+

Returns

+

a GstTestClock cast to GstClock.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_test_clock_set_time ()

+
void
+gst_test_clock_set_time (GstTestClock *test_clock,
+                         GstClockTime new_time);
+

Sets the time of test_clock + to the time given by new_time +. The time of +test_clock + is monotonically increasing, therefore providing a new_time + +which is earlier or equal to the time of the clock as given by +gst_clock_get_time() is a programming error.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

a GstTestClock of which to set the time

 

new_time

a GstClockTime later than that returned by gst_clock_get_time()

 
+
+

Since: 1.2

+
+
+
+

gst_test_clock_advance_time ()

+
void
+gst_test_clock_advance_time (GstTestClock *test_clock,
+                             GstClockTimeDiff delta);
+

Advances the time of the test_clock + by the amount given by delta +. The +time of test_clock + is monotonically increasing, therefore providing a +delta + which is negative or zero is a programming error.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

a GstTestClock for which to increase the time

 

delta

a positive GstClockTimeDiff to be added to the time of the clock

 
+
+

Since: 1.2

+
+
+
+

gst_test_clock_peek_id_count ()

+
guint
+gst_test_clock_peek_id_count (GstTestClock *test_clock);
+

Determine the number of pending clock notifications that have been +requested from the test_clock +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

test_clock

a GstTestClock for which to count notifications

 
+
+
+

Returns

+

the number of pending clock notifications.

+
+

Since: 1.2

+
+
+
+

gst_test_clock_has_id ()

+
gboolean
+gst_test_clock_has_id (GstTestClock *test_clock,
+                       GstClockID id);
+

Checks whether test_clock + was requested to provide the clock notification +given by id +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

a GstTestClock to ask if it provided the notification

 

id

a GstClockID clock notification.

[transfer none]
+
+
+

Returns

+

TRUE if the clock has been asked to provide the given clock +notification, FALSE otherwise.

+
+

Since: 1.2

+
+
+
+

gst_test_clock_peek_next_pending_id ()

+
gboolean
+gst_test_clock_peek_next_pending_id (GstTestClock *test_clock,
+                                     GstClockID *pending_id);
+

Determines if the pending_id + is the next clock notification scheduled to +be triggered given the current time of the test_clock +.

+

MT safe.

+

Return: TRUE if pending_id + is the next clock notification to be +triggered, FALSE otherwise.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

a GstTestClock to check the clock notifications for

 

pending_id

a GstClockID clock +notification to look for.

[allow-none][out][transfer full]
+
+

Since: 1.2

+
+
+
+

gst_test_clock_wait_for_next_pending_id ()

+
void
+gst_test_clock_wait_for_next_pending_id
+                               (GstTestClock *test_clock,
+                                GstClockID *pending_id);
+

Waits until a clock notification is requested from test_clock +. There is no +timeout for this wait, see the main description of GstTestClock. A reference +to the pending clock notification is stored in pending_id +.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

GstTestClock for which to get the pending clock notification

 

pending_id

GstClockID +with information about the pending clock notification.

[allow-none][out][transfer full]
+
+

Since: 1.2

+
+
+
+

gst_test_clock_wait_for_pending_id_count ()

+
void
+gst_test_clock_wait_for_pending_id_count
+                               (GstTestClock *test_clock,
+                                guint count);
+
+

gst_test_clock_wait_for_pending_id_count is deprecated and should not be used in newly-written code.

+

use gst_test_clock_wait_for_multiple_pending_ids() instead.

+
+

Blocks until at least count + clock notifications have been requested from +test_clock +. There is no timeout for this wait, see the main description of +GstTestClock.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

GstTestClock for which to await having enough pending clock

 

count

the number of pending clock notifications to wait for

 
+
+

Since: 1.2

+
+
+
+

gst_test_clock_process_next_clock_id ()

+
GstClockID
+gst_test_clock_process_next_clock_id (GstTestClock *test_clock);
+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

test_clock

a GstTestClock for which to retrieve the next pending clock +notification

 
+
+
+

Returns

+

a GstClockID containing the next pending clock +notification.

+

[transfer full]

+
+

Since: 1.2

+
+
+
+

gst_test_clock_get_next_entry_time ()

+
GstClockTime
+gst_test_clock_get_next_entry_time (GstTestClock *test_clock);
+

Retrieve the requested time for the next pending clock notification.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

test_clock

a GstTestClock to fetch the next clock notification time for

 
+
+
+

Returns

+

a GstClockTime set to the time of the next pending clock +notification. If no clock notifications have been requested +GST_CLOCK_TIME_NONE will be returned.

+
+

Since: 1.2

+
+
+
+

gst_test_clock_wait_for_multiple_pending_ids ()

+
void
+gst_test_clock_wait_for_multiple_pending_ids
+                               (GstTestClock *test_clock,
+                                guint count,
+                                GList **pending_list);
+

Blocks until at least count + clock notifications have been requested from +test_clock +. There is no timeout for this wait, see the main description of +GstTestClock.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

test_clock

GstTestClock for which to await having enough pending clock

 

count

the number of pending clock notifications to wait for

 

pending_list

Address +of a GList pointer variable to store the list of pending GstClockIDs +that expired, or NULL.

[out][element-type Gst.ClockID][transfer full][allow-none]
+
+

Since: 1.4

+
+
+
+

gst_test_clock_id_list_get_latest_time ()

+
GstClockTime
+gst_test_clock_id_list_get_latest_time
+                               (const GList *pending_list);
+

Finds the latest time inside the list.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

pending_list

List +of of pending GstClockIDs.

[element-type Gst.ClockID][transfer none][allow-none]
+
+

Since: 1.4

+
+
+
+

gst_test_clock_process_id_list ()

+
guint
+gst_test_clock_process_id_list (GstTestClock *test_clock,
+                                const GList *pending_list);
+

Processes and releases the pending IDs in the list.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

test_clock

GstTestClock for which to process the pending IDs

 

pending_list

List +of pending GstClockIDs.

[element-type Gst.ClockID][transfer none][allow-none]
+
+

Since: 1.4

+
+
+
+

gst_test_clock_crank ()

+
gboolean
+gst_test_clock_crank (GstTestClock *test_clock);
+

A "crank" consists of three steps: +1: Wait for a GstClockID to be registered with the GstTestClock. +2: Advance the GstTestClock to the time the GstClockID is waiting for. +3: Release the GstClockID wait. +A "crank" can be though of as the notion of +manually driving the clock forward to its next logical step.

+

Return: TRUE if the crank was successful, FALSE otherwise.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

test_clock

GstTestClock to crank

 
+
+

Since: 1.8

+
+
+
+

Types and Values

+
+

struct GstTestClock

+
struct GstTestClock;
+

A GstTestClock structure which is based on a GstClock along with some +private data.

+

Since: 1.2

+
+
+
+

struct GstTestClockClass

+
struct GstTestClockClass {
+  GstClockClass parent_class;
+};
+
+

The class of a GstTestClock, which has no virtual methods to override.

+
+

Members

+
+++++ + +
+
+

Since: 1.2

+
+
+
+

Property Details

+
+

The “clock-type” property

+
  “clock-type”               GstClockType
+

The kind of clock implementation to be reported by this clock.

+

Flags: Read / Write

+

Default value: GST_CLOCK_TYPE_MONOTONIC

+
+
+
+

The “start-time” property

+
  “start-time”               guint64
+

When a GstTestClock is constructed it will have a certain start time set. +If the clock was created using gst_test_clock_new_with_start_time() then +this property contains the value of the start_time + argument. If +gst_test_clock_new() was called the clock started at time zero, and thus +this property contains the value 0.

+

Flags: Read / Write / Construct Only

+

Default value: 0

+
+
+
+

See Also

+

GstSystemClock, GstClock

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstTimedValueControlSource.html b/docs/libs/html/GstTimedValueControlSource.html new file mode 100644 index 0000000..e7946c8 --- /dev/null +++ b/docs/libs/html/GstTimedValueControlSource.html @@ -0,0 +1,604 @@ + + + + +GstTimedValueControlSource: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTimedValueControlSource

+

GstTimedValueControlSource — timed value control source base class

+
+ +
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + +
voidvalue-addedRun First
voidvalue-changedRun First
voidvalue-removedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTimedValueControlSource
structGstControlPoint
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlSource
+                ╰── GstTimedValueControlSource
+                    ├── GstInterpolationControlSource
+                    ╰── GstTriggerControlSource
+
+
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

Base class for GstControlSource that use time-stamped values.

+

When overriding bind, chain up first to give this bind implementation a +chance to setup things.

+

All functions are MT-safe.

+
+
+

Functions

+
+

gst_timed_value_control_source_find_control_point_iter ()

+
GSequenceIter *
+gst_timed_value_control_source_find_control_point_iter
+                               (GstTimedValueControlSource *self,
+                                GstClockTime timestamp);
+

Find last value before given timestamp in control point list. +If all values in the control point list come after the given +timestamp or no values exist, NULL is returned.

+

For use in control source implementations.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the control source to search in

 

timestamp

the search key

 
+
+
+

Returns

+

the found GSequenceIter or NULL.

+

[transfer none]

+
+
+
+
+

gst_timed_value_control_source_set ()

+
gboolean
+gst_timed_value_control_source_set (GstTimedValueControlSource *self,
+                                    GstClockTime timestamp,
+                                    const gdouble value);
+

Set the value of given controller-handled property at a certain time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the GstTimedValueControlSource object

 

timestamp

the time the control-change is scheduled for

 

value

the control-value

 
+
+
+

Returns

+

FALSE if the values couldn't be set, TRUE otherwise.

+
+
+
+
+

gst_timed_value_control_source_set_from_list ()

+
gboolean
+gst_timed_value_control_source_set_from_list
+                               (GstTimedValueControlSource *self,
+                                const GSList *timedvalues);
+

Sets multiple timed values at once.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the GstTimedValueControlSource object

 

timedvalues

a list +with GstTimedValue items.

[transfer none][element-type GstTimedValue]
+
+
+

Returns

+

FALSE if the values couldn't be set, TRUE otherwise.

+
+
+
+
+

gst_timed_value_control_source_get_all ()

+
GList *
+gst_timed_value_control_source_get_all
+                               (GstTimedValueControlSource *self);
+

Returns a read-only copy of the list of GstTimedValue for the given property. +Free the list after done with it.

+
+

Parameters

+
+++++ + + + + + +

self

the GstTimedValueControlSource to get the list from

 
+
+
+

Returns

+

a copy +of the list, or NULL if the property isn't handled by the controller.

+

[transfer container][element-type GstTimedValue]

+
+
+
+
+

gst_timed_value_control_source_unset ()

+
gboolean
+gst_timed_value_control_source_unset (GstTimedValueControlSource *self,
+                                      GstClockTime timestamp);
+

Used to remove the value of given controller-handled property at a certain +time.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

self

the GstTimedValueControlSource object

 

timestamp

the time the control-change should be removed from

 
+
+
+

Returns

+

FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.

+
+
+
+
+

gst_timed_value_control_source_unset_all ()

+
void
+gst_timed_value_control_source_unset_all
+                               (GstTimedValueControlSource *self);
+

Used to remove all time-stamped values of given controller-handled property

+
+

Parameters

+
+++++ + + + + + +

self

the GstTimedValueControlSource object

 
+
+
+
+
+

gst_timed_value_control_source_get_count ()

+
gint
+gst_timed_value_control_source_get_count
+                               (GstTimedValueControlSource *self);
+

Get the number of control points that are set.

+
+

Parameters

+
+++++ + + + + + +

self

the GstTimedValueControlSource to get the number of values from

 
+
+
+

Returns

+

the number of control points that are set.

+
+
+
+
+

gst_timed_value_control_invalidate_cache ()

+
void
+gst_timed_value_control_invalidate_cache
+                               (GstTimedValueControlSource *self);
+

Reset the controlled value cache.

+
+

Parameters

+
+++++ + + + + + +

self

the GstTimedValueControlSource

 
+
+
+
+
+

Types and Values

+
+

struct GstTimedValueControlSource

+
struct GstTimedValueControlSource;
+

The instance structure of GstControlSource.

+
+
+
+

struct GstControlPoint

+
struct GstControlPoint {
+  /* fields from GstTimedValue. DO NOT CHANGE! */
+  GstClockTime timestamp;
+  gdouble value;
+};
+
+

An internal structure for value+time and various temporary +values used for interpolation. This "inherits" from +GstTimedValue.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstClockTime timestamp;

timestamp of the value change

 

gdouble value;

the new value

 
+
+
+
+
+

Signal Details

+
+

The “value-added” signal

+
void
+user_function (GstTimedValueControlSource *self,
+               GstControlPoint            *timed_value,
+               gpointer                    user_data)
+

Emited right after the new value has been added to self +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

The GstTimedValueControlSource into which a GstTimedValue has been +added

 

timed_value

The newly added GstTimedValue

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 1.6

+
+
+
+

The “value-changed” signal

+
void
+user_function (GstTimedValueControlSource *self,
+               GstControlPoint            *timed_value,
+               gpointer                    user_data)
+

Emited right after the new value has been set on timed_signals +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

The GstTimedValueControlSource on which a GstTimedValue has changed

 

timed_value

The GstTimedValue where the value changed

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 1.6

+
+
+
+

The “value-removed” signal

+
void
+user_function (GstTimedValueControlSource *self,
+               GstControlPoint            *timed_value,
+               gpointer                    user_data)
+

Emited when timed_value + is removed from self +

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

The GstTimedValueControlSource from which a GstTimedValue has been +removed

 

timed_value

The removed GstTimedValue

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 1.6

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/GstTriggerControlSource.html b/docs/libs/html/GstTriggerControlSource.html new file mode 100644 index 0000000..a12c4cb --- /dev/null +++ b/docs/libs/html/GstTriggerControlSource.html @@ -0,0 +1,154 @@ + + + + +GstTriggerControlSource: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTriggerControlSource

+

GstTriggerControlSource — trigger control source

+
+
+

Functions

+ +
+
+

Properties

+
+++++ + + + + + +
gint64toleranceRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTriggerControlSource
#defineGST_TYPE_TRIGGER_WAVEFORM
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstControlSource
+                ╰── GstTimedValueControlSource
+                    ╰── GstTriggerControlSource
+
+
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

GstTriggerControlSource is a GstControlSource, that returns values from user-given +control points. It allows for a tolerance on the time-stamps.

+

To use GstTriggerControlSource get a new instance by calling +gst_trigger_control_source_new(), bind it to a GParamSpec and set some +control points by calling gst_timed_value_control_source_set().

+

All functions are MT-safe.

+
+
+

Functions

+
+

gst_trigger_control_source_new ()

+
GstControlSource *
+gst_trigger_control_source_new (void);
+

This returns a new, unbound GstTriggerControlSource.

+
+

Returns

+

a new, unbound GstTriggerControlSource.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

struct GstTriggerControlSource

+
struct GstTriggerControlSource;
+

The instance structure of GstControlSource.

+
+
+
+

GST_TYPE_TRIGGER_WAVEFORM

+
#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ())
+
+
+
+
+

Property Details

+
+

The “tolerance” property

+
  “tolerance”                gint64
+

Amount of ns a control time can be off to still trigger.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/annotation-glossary.html b/docs/libs/html/annotation-glossary.html new file mode 100644 index 0000000..2ee3e67 --- /dev/null +++ b/docs/libs/html/annotation-glossary.html @@ -0,0 +1,85 @@ + + + + +Annotation Glossary: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

A

+
allow-none
+

NULL is OK, both for passing and for returning.

+
array
+

Parameter points to an array of items.

+

C

+
closure
+

This parameter is a 'user_data', for callbacks; many bindings can pass NULL here.

+

E

+
element-type
+

Generics and defining elements of containers and arrays.

+

I

+
in
+

Parameter for input. Default is transfer none.

+

N

+
nullable
+

NULL may be passed as the value in, out, in-out; or as a return value.

+

O

+
out
+

Parameter for returning results. Default is transfer full.

+
out caller-allocates
+

Out parameter, where caller must allocate storage.

+

R

+
rename-to
+

Rename the original symbol's name to SYMBOL.

+

S

+
scope async
+

The callback is valid until first called.

+
scope call
+

The callback is valid only during the call to the method.

+
skip
+

Exposed in C code, not necessarily available in other languages.

+

T

+
transfer container
+

Free data container after the code is done.

+
transfer floating
+

Alias for transfer none, used for objects with floating refs.

+
transfer full
+

Free data after the code is done.

+
transfer none
+

Don't free data after the code is done.

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gdp-header.png b/docs/libs/html/gdp-header.png new file mode 100644 index 0000000..d7d08f6 Binary files /dev/null and b/docs/libs/html/gdp-header.png differ diff --git a/docs/libs/html/gstreamer-base.html b/docs/libs/html/gstreamer-base.html new file mode 100644 index 0000000..a62eb62 --- /dev/null +++ b/docs/libs/html/gstreamer-base.html @@ -0,0 +1,86 @@ + + + + +GStreamer Base and Utillity Classes: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Base and Utillity Classes

+
+
+GstAggregator — Base class for mixers and muxers, manages a set of input + pads and aggregates their streams +
+
+GstAggregatorPadGstPad subclass for pads managed by GstAggregator +
+
+GstBaseParse — Base class for stream parsers +
+
+GstBaseSrc — Base class for getrange based source elements +
+
+GstBaseSink — Base class for sink elements +
+
+GstBaseTransform — Base class for simple transform filters +
+
+GstPushSrc — Base class for push based source elements +
+
+GstAdapter — adapts incoming data on a sink pad into chunks of N bytes +
+
+GstBitReader — Reads any number of bits from a memory buffer +
+
+GstByteReader — Reads different integer, string and floating point + types from a memory buffer +
+
+GstByteWriter — Writes different integer, string and floating point + types to a memory buffer and allows reading +
+
+GstCollectPads — manages a set of pads that operate in collect mode +
+
+GstFlowCombiner — Utility to combine multiple flow returns into one +
+
+GstTypeFindHelper — Utility functions for typefinding +
+
+GstDataQueue — Threadsafe queueing object +
+
+GstQueueArray — Array based queue object +
+
+

+ libgstbase-1.0.so provides some base classes to be extended + by elements and utillity classes that are most useful for plugin developers. +

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-check.html b/docs/libs/html/gstreamer-check.html new file mode 100644 index 0000000..3520eec --- /dev/null +++ b/docs/libs/html/gstreamer-check.html @@ -0,0 +1,50 @@ + + + + +GStreamer Check Unit Testing: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Check Unit Testing

+
+
+GstCheck — Common code for GStreamer unit tests +
+
+GstBufferStraw — Buffer interception code for GStreamer unit tests +
+
+GstStreamConsistencyChecker — Data flow consistency checker for GStreamer unit tests. +
+
+GstHarness — A test-harness for writing GStreamer unit tests +
+
+GstTestClock — Controllable, deterministic clock for GStreamer unit tests +
+
+

+ libgstcheck-1.0.so provides functionality for writing + unit tests that use the check framework. +

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-control.html b/docs/libs/html/gstreamer-control.html new file mode 100644 index 0000000..415a453 --- /dev/null +++ b/docs/libs/html/gstreamer-control.html @@ -0,0 +1,56 @@ + + + + +GStreamer Dynamic Parameter Control: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Dynamic Parameter Control

+
+
+GstARGBControlBinding — attachment for control sources to argb properties +
+
+GstDirectControlBinding — direct attachment for control sources +
+
+GstProxyControlBinding — attachment for forwarding control sources +
+
+GstTimedValueControlSource — timed value control source base class +
+
+GstInterpolationControlSource — interpolation control source +
+
+GstLFOControlSource — LFO control source +
+
+GstTriggerControlSource — trigger control source +
+
+

+ libgstcontroller-1.0.so provides functionality to animate + element properties over time. +

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-hierarchy.html b/docs/libs/html/gstreamer-hierarchy.html new file mode 100644 index 0000000..0e7e48e --- /dev/null +++ b/docs/libs/html/gstreamer-hierarchy.html @@ -0,0 +1,60 @@ + + + + +Object Hierarchy: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Object Hierarchy

+
+    GObject
+    ├── GInitiallyUnowned
+       ╰── GstObject
+           ├── GstPad
+              ╰── GstAggregatorPad
+           ├── GstElement
+              ├── GstAggregator
+              ├── GstBaseParse
+              ├── GstBaseSrc
+                 ╰── GstPushSrc
+              ├── GstBaseSink
+              ╰── GstBaseTransform
+           ├── GstClock
+              ├── GstSystemClock
+                 ├── GstNetClientClock
+                    ╰── GstNtpClock
+                 ╰── GstPtpClock
+              ╰── GstTestClock
+           ├── GstControlBinding
+              ├── GstARGBControlBinding
+              ╰── GstDirectControlBinding
+           ├── GstControlSource
+              ├── GstTimedValueControlSource
+                 ├── GstInterpolationControlSource
+                 ╰── GstTriggerControlSource
+              ╰── GstLFOControlSource
+           ├── GstCollectPads
+           ╰── GstNetTimeProvider
+    ╰── GstAdapter
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-1.0.devhelp2 b/docs/libs/html/gstreamer-libs-1.0.devhelp2 new file mode 100644 index 0000000..70cc209 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-1.0.devhelp2 @@ -0,0 +1,1001 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/libs/html/gstreamer-libs-GstBitReader.html b/docs/libs/html/gstreamer-libs-GstBitReader.html new file mode 100644 index 0000000..b2d22fa --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstBitReader.html @@ -0,0 +1,1355 @@ + + + + +GstBitReader: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBitReader

+

GstBitReader — Reads any number of bits from a memory buffer

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_BIT_READER_INIT() +
+GstBitReader * + +gst_bit_reader_new () +
+void + +gst_bit_reader_free () +
+void + +gst_bit_reader_init () +
+guint + +gst_bit_reader_get_pos () +
+guint + +gst_bit_reader_get_remaining () +
+gboolean + +gst_bit_reader_set_pos () +
+guint + +gst_bit_reader_get_size () +
+gboolean + +gst_bit_reader_skip () +
+gboolean + +gst_bit_reader_skip_to_byte () +
+gboolean + +gst_bit_reader_get_bits_uint16 () +
+gboolean + +gst_bit_reader_get_bits_uint32 () +
+gboolean + +gst_bit_reader_get_bits_uint64 () +
+gboolean + +gst_bit_reader_get_bits_uint8 () +
+gboolean + +gst_bit_reader_peek_bits_uint16 () +
+gboolean + +gst_bit_reader_peek_bits_uint32 () +
+gboolean + +gst_bit_reader_peek_bits_uint64 () +
+gboolean + +gst_bit_reader_peek_bits_uint8 () +
+void + +gst_bit_reader_skip_unchecked () +
+void + +gst_bit_reader_skip_to_byte_unchecked () +
+guint16 + +gst_bit_reader_get_bits_uint16_unchecked () +
+guint32 + +gst_bit_reader_get_bits_uint32_unchecked () +
+guint64 + +gst_bit_reader_get_bits_uint64_unchecked () +
+guint8 + +gst_bit_reader_get_bits_uint8_unchecked () +
+guint16 + +gst_bit_reader_peek_bits_uint16_unchecked () +
+guint32 + +gst_bit_reader_peek_bits_uint32_unchecked () +
+guint64 + +gst_bit_reader_peek_bits_uint64_unchecked () +
+guint8 + +gst_bit_reader_peek_bits_uint8_unchecked () +
+
+
+

Types and Values

+
++++ + + + + +
 GstBitReader
+
+
+

Includes

+
#include <gst/base/gstbitreader.h>
+
+
+
+

Description

+

GstBitReader provides a bit reader that can read any number of bits +from a memory buffer. It provides functions for reading any number of bits +into 8, 16, 32 and 64 bit variables.

+
+
+

Functions

+
+

GST_BIT_READER_INIT()

+
#define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
+
+

A GstBitReader must be initialized with this macro, before it can be +used. This macro can used be to initialize a variable, but it cannot +be assigned to a variable. In that case you have to use +gst_bit_reader_init().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

Data from which the GstBitReader should read

 

size

Size of data +in bytes

 
+
+
+
+
+

gst_bit_reader_new ()

+
GstBitReader *
+gst_bit_reader_new (const guint8 *data,
+                    guint size);
+

Create a new GstBitReader instance, which will read from data +.

+

Free-function: gst_bit_reader_free

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

Data from which the GstBitReader +should read.

[array length=size]

size

Size of data +in bytes

 
+
+
+

Returns

+

a new GstBitReader instance.

+

[transfer full]

+
+
+
+
+

gst_bit_reader_free ()

+
void
+gst_bit_reader_free (GstBitReader *reader);
+

Frees a GstBitReader instance, which was previously allocated by +gst_bit_reader_new().

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance.

[in][transfer full]
+
+
+
+
+

gst_bit_reader_init ()

+
void
+gst_bit_reader_init (GstBitReader *reader,
+                     const guint8 *data,
+                     guint size);
+

Initializes a GstBitReader instance to read from data +. This function +can be called on already initialized instances.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

data

data from which the bit reader should read.

[in][array length=size]

size

Size of data +in bytes

 
+
+
+
+
+

gst_bit_reader_get_pos ()

+
guint
+gst_bit_reader_get_pos (const GstBitReader *reader);
+

Returns the current position of a GstBitReader instance in bits.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance

 
+
+
+

Returns

+

The current position of reader +in bits.

+
+
+
+
+

gst_bit_reader_get_remaining ()

+
guint
+gst_bit_reader_get_remaining (const GstBitReader *reader);
+

Returns the remaining number of bits of a GstBitReader instance.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance

 
+
+
+

Returns

+

The remaining number of bits of reader +instance.

+
+
+
+
+

gst_bit_reader_set_pos ()

+
gboolean
+gst_bit_reader_set_pos (GstBitReader *reader,
+                        guint pos);
+

Sets the new position of a GstBitReader instance to pos + in bits.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

pos

The new position in bits

 
+
+
+

Returns

+

TRUE if the position could be set successfully, FALSE +otherwise.

+
+
+
+
+

gst_bit_reader_get_size ()

+
guint
+gst_bit_reader_get_size (const GstBitReader *reader);
+

Returns the total number of bits of a GstBitReader instance.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance

 
+
+
+

Returns

+

The total number of bits of reader +instance.

+
+
+
+
+

gst_bit_reader_skip ()

+
gboolean
+gst_bit_reader_skip (GstBitReader *reader,
+                     guint nbits);
+

Skips nbits + bits of the GstBitReader instance.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

the number of bits to skip

 
+
+
+

Returns

+

TRUE if nbits +bits could be skipped, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_skip_to_byte ()

+
gboolean
+gst_bit_reader_skip_to_byte (GstBitReader *reader);
+

Skips until the next byte.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_get_bits_uint16 ()

+
gboolean
+gst_bit_reader_get_bits_uint16 (GstBitReader *reader,
+                                guint16 *val,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint16 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_get_bits_uint32 ()

+
gboolean
+gst_bit_reader_get_bits_uint32 (GstBitReader *reader,
+                                guint32 *val,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint32 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_get_bits_uint64 ()

+
gboolean
+gst_bit_reader_get_bits_uint64 (GstBitReader *reader,
+                                guint64 *val,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint64 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_get_bits_uint8 ()

+
gboolean
+gst_bit_reader_get_bits_uint8 (GstBitReader *reader,
+                               guint8 *val,
+                               guint nbits);
+

Read nbits + bits into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint8 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_peek_bits_uint16 ()

+
gboolean
+gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader,
+                                 guint16 *val,
+                                 guint nbits);
+

Read nbits + bits into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint16 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_peek_bits_uint32 ()

+
gboolean
+gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader,
+                                 guint32 *val,
+                                 guint nbits);
+

Read nbits + bits into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint32 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_peek_bits_uint64 ()

+
gboolean
+gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader,
+                                 guint64 *val,
+                                 guint nbits);
+

Read nbits + bits into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint64 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_peek_bits_uint8 ()

+
gboolean
+gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader,
+                                guint8 *val,
+                                guint nbits);
+

Read nbits + bits into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstBitReader instance

 

val

Pointer to a guint8 to store the result.

[out]

nbits

number of bits to read

 
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_bit_reader_skip_unchecked ()

+
void
+gst_bit_reader_skip_unchecked (GstBitReader *reader,
+                               guint nbits);
+

Skips nbits + bits of the GstBitReader instance without checking if there +are enough bits available in the bit reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

the number of bits to skip

 
+
+
+
+
+

gst_bit_reader_skip_to_byte_unchecked ()

+
void
+gst_bit_reader_skip_to_byte_unchecked (GstBitReader *reader);
+

Skips until the next byte without checking if there are enough bits +available in the bit reader.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstBitReader instance

 
+
+
+
+
+

gst_bit_reader_get_bits_uint16_unchecked ()

+
guint16
+gst_bit_reader_get_bits_uint16_unchecked
+                               (GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position without +checking if there are enough bits available in the bit reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 16 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_get_bits_uint32_unchecked ()

+
guint32
+gst_bit_reader_get_bits_uint32_unchecked
+                               (GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position without +checking if there are enough bits available in the bit reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 32 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_get_bits_uint64_unchecked ()

+
guint64
+gst_bit_reader_get_bits_uint64_unchecked
+                               (GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position without +checking if there are enough bits available in the bit reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 64 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_get_bits_uint8_unchecked ()

+
guint8
+gst_bit_reader_get_bits_uint8_unchecked
+                               (GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + and update the current position without +checking if there are enough bits available in the bit reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 8 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_peek_bits_uint16_unchecked ()

+
guint16
+gst_bit_reader_peek_bits_uint16_unchecked
+                               (const GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + but keep the current position without +checking if there are enough bits available in the bit reader

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 16 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_peek_bits_uint32_unchecked ()

+
guint32
+gst_bit_reader_peek_bits_uint32_unchecked
+                               (const GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + but keep the current position without +checking if there are enough bits available in the bit reader

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 32 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_peek_bits_uint64_unchecked ()

+
guint64
+gst_bit_reader_peek_bits_uint64_unchecked
+                               (const GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + but keep the current position without +checking if there are enough bits available in the bit reader

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 64 bit integer with the bits.

+
+
+
+
+

gst_bit_reader_peek_bits_uint8_unchecked ()

+
guint8
+gst_bit_reader_peek_bits_uint8_unchecked
+                               (const GstBitReader *reader,
+                                guint nbits);
+

Read nbits + bits into val + but keep the current position without +checking if there are enough bits available in the bit reader

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstBitReader instance

 

nbits

number of bits to read

 
+
+
+

Returns

+

unsigned 8 bit integer with the bits.

+
+
+
+
+

Types and Values

+
+

GstBitReader

+
typedef struct {
+  const guint8 *data;
+  guint size;
+
+  guint byte;  /* Byte position */
+  guint bit;   /* Bit position in the current byte */
+} GstBitReader;
+
+

A bit reader instance.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

const guint8 *data;

Data from which the bit reader will +read.

[array length=size]

guint size;

Size of data +in bytes

 

guint byte;

Current byte position

 

guint bit;

Bit position in the current byte

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstBufferStraw.html b/docs/libs/html/gstreamer-libs-GstBufferStraw.html new file mode 100644 index 0000000..ba2c215 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstBufferStraw.html @@ -0,0 +1,212 @@ + + + + +GstBufferStraw: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstBufferStraw

+

GstBufferStraw — Buffer interception code for GStreamer unit tests

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+void + +gst_buffer_straw_start_pipeline () +
+GstBuffer * + +gst_buffer_straw_get_buffer () +
+void + +gst_buffer_straw_stop_pipeline () +
+
+
+

Includes

+
#include <gst/check/gstbufferstraw.h>
+
+
+
+

Description

+

These macros and functions are for internal use of the unit tests found +inside the 'check' directories of various GStreamer packages.

+
+
+

Functions

+
+

gst_buffer_straw_start_pipeline ()

+
void
+gst_buffer_straw_start_pipeline (GstElement *bin,
+                                 GstPad *pad);
+

Sets up a pipeline for buffer sucking. This will allow you to call +gst_buffer_straw_get_buffer() to access buffers as they pass over pad +.

+

This function is normally used in unit tests that want to verify that a +particular element is outputting correct buffers. For example, you would make +a pipeline via gst_parse_launch(), pull out the pad you want to monitor, then +call gst_buffer_straw_get_buffer() to get the buffers that pass through pad +. +The pipeline will block until you have sucked off the buffers.

+

This function will set the state of bin + to PLAYING; to clean up, be sure to +call gst_buffer_straw_stop_pipeline().

+

Note that you may not start two buffer straws at the same time. This function +is intended for unit tests, not general API use. In fact it calls fail_if +from libcheck, so you cannot use it outside unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the pipeline to run

 

pad

a pad on an element in bin +

 
+
+
+
+
+

gst_buffer_straw_get_buffer ()

+
GstBuffer *
+gst_buffer_straw_get_buffer (GstElement *bin,
+                             GstPad *pad);
+

Get one buffer from pad +. Implemented via buffer probes. This function will +block until the pipeline passes a buffer over pad +, so for robust behavior +in unit tests, you need to use check's timeout to fail out in the case that a +buffer never arrives.

+

You must have previously called gst_buffer_straw_start_pipeline() on +pipeline + and pad +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the pipeline previously started via gst_buffer_straw_start_pipeline()

 

pad

the pad previously passed to gst_buffer_straw_start_pipeline()

 
+
+
+

Returns

+

the captured GstBuffer.

+
+
+
+
+

gst_buffer_straw_stop_pipeline ()

+
void
+gst_buffer_straw_stop_pipeline (GstElement *bin,
+                                GstPad *pad);
+

Set bin + to GST_STATE_NULL and release resource allocated in +gst_buffer_straw_start_pipeline().

+

You must have previously called gst_buffer_straw_start_pipeline() on +pipeline + and pad +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

bin

the pipeline previously started via gst_buffer_straw_start_pipeline()

 

pad

the pad previously passed to gst_buffer_straw_start_pipeline()

 
+
+
+
+
+

Types and Values

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstByteReader.html b/docs/libs/html/gstreamer-libs-GstByteReader.html new file mode 100644 index 0000000..ea604ae --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstByteReader.html @@ -0,0 +1,5142 @@ + + + + +GstByteReader: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstByteReader

+

GstByteReader — Reads different integer, string and floating point + types from a memory buffer

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_BYTE_READER_INIT() +
+GstByteReader * + +gst_byte_reader_new () +
+void + +gst_byte_reader_free () +
+void + +gst_byte_reader_init () +
+gboolean + +gst_byte_reader_peek_sub_reader () +
+gboolean + +gst_byte_reader_get_sub_reader () +
+guint + +gst_byte_reader_get_pos () +
+guint + +gst_byte_reader_get_remaining () +
+gboolean + +gst_byte_reader_set_pos () +
+guint + +gst_byte_reader_get_size () +
+gboolean + +gst_byte_reader_skip () +
+gboolean + +gst_byte_reader_get_int8 () +
+gboolean + +gst_byte_reader_get_int16_be () +
+gboolean + +gst_byte_reader_get_int16_le () +
+gboolean + +gst_byte_reader_get_int24_be () +
+gboolean + +gst_byte_reader_get_int24_le () +
+gboolean + +gst_byte_reader_get_int32_be () +
+gboolean + +gst_byte_reader_get_int32_le () +
+gboolean + +gst_byte_reader_get_int64_be () +
+gboolean + +gst_byte_reader_get_int64_le () +
+gboolean + +gst_byte_reader_get_uint8 () +
+gboolean + +gst_byte_reader_get_uint16_be () +
+gboolean + +gst_byte_reader_get_uint16_le () +
+gboolean + +gst_byte_reader_get_uint24_be () +
+gboolean + +gst_byte_reader_get_uint24_le () +
+gboolean + +gst_byte_reader_get_uint32_be () +
+gboolean + +gst_byte_reader_get_uint32_le () +
+gboolean + +gst_byte_reader_get_uint64_be () +
+gboolean + +gst_byte_reader_get_uint64_le () +
+gboolean + +gst_byte_reader_peek_int8 () +
+gboolean + +gst_byte_reader_peek_int16_be () +
+gboolean + +gst_byte_reader_peek_int16_le () +
+gboolean + +gst_byte_reader_peek_int24_be () +
+gboolean + +gst_byte_reader_peek_int24_le () +
+gboolean + +gst_byte_reader_peek_int32_be () +
+gboolean + +gst_byte_reader_peek_int32_le () +
+gboolean + +gst_byte_reader_peek_int64_be () +
+gboolean + +gst_byte_reader_peek_int64_le () +
+gboolean + +gst_byte_reader_peek_uint8 () +
+gboolean + +gst_byte_reader_peek_uint16_be () +
+gboolean + +gst_byte_reader_peek_uint16_le () +
+gboolean + +gst_byte_reader_peek_uint24_be () +
+gboolean + +gst_byte_reader_peek_uint24_le () +
+gboolean + +gst_byte_reader_peek_uint32_be () +
+gboolean + +gst_byte_reader_peek_uint32_le () +
+gboolean + +gst_byte_reader_peek_uint64_be () +
+gboolean + +gst_byte_reader_peek_uint64_le () +
+gboolean + +gst_byte_reader_get_float32_le () +
+gboolean + +gst_byte_reader_get_float32_be () +
+gboolean + +gst_byte_reader_get_float64_le () +
+gboolean + +gst_byte_reader_get_float64_be () +
+gboolean + +gst_byte_reader_peek_float32_le () +
+gboolean + +gst_byte_reader_peek_float32_be () +
+gboolean + +gst_byte_reader_peek_float64_le () +
+gboolean + +gst_byte_reader_peek_float64_be () +
+gboolean + +gst_byte_reader_get_data () +
+gboolean + +gst_byte_reader_dup_data () +
+gboolean + +gst_byte_reader_peek_data () +
+guint + +gst_byte_reader_masked_scan_uint32 () +
+guint + +gst_byte_reader_masked_scan_uint32_peek () +
#define +gst_byte_reader_get_string() +
+gboolean + +gst_byte_reader_get_string_utf8 () +
#define +gst_byte_reader_peek_string() +
+gboolean + +gst_byte_reader_peek_string_utf8 () +
#define +gst_byte_reader_dup_string() +
+gboolean + +gst_byte_reader_dup_string_utf8 () +
+gboolean + +gst_byte_reader_dup_string_utf16 () +
+gboolean + +gst_byte_reader_dup_string_utf32 () +
#define +gst_byte_reader_skip_string() +
+gboolean + +gst_byte_reader_skip_string_utf8 () +
+gboolean + +gst_byte_reader_skip_string_utf16 () +
+gboolean + +gst_byte_reader_skip_string_utf32 () +
+void + +gst_byte_reader_skip_unchecked () +
+gint8 + +gst_byte_reader_get_int8_unchecked () +
+gint16 + +gst_byte_reader_get_int16_be_unchecked () +
+gint16 + +gst_byte_reader_get_int16_le_unchecked () +
+gint32 + +gst_byte_reader_get_int24_be_unchecked () +
+gint32 + +gst_byte_reader_get_int24_le_unchecked () +
+gint32 + +gst_byte_reader_get_int32_be_unchecked () +
+gint32 + +gst_byte_reader_get_int32_le_unchecked () +
+gint64 + +gst_byte_reader_get_int64_be_unchecked () +
+gint64 + +gst_byte_reader_get_int64_le_unchecked () +
+guint8 + +gst_byte_reader_get_uint8_unchecked () +
+guint16 + +gst_byte_reader_get_uint16_be_unchecked () +
+guint16 + +gst_byte_reader_get_uint16_le_unchecked () +
+guint32 + +gst_byte_reader_get_uint24_be_unchecked () +
+guint32 + +gst_byte_reader_get_uint24_le_unchecked () +
+guint32 + +gst_byte_reader_get_uint32_be_unchecked () +
+guint32 + +gst_byte_reader_get_uint32_le_unchecked () +
+guint64 + +gst_byte_reader_get_uint64_be_unchecked () +
+guint64 + +gst_byte_reader_get_uint64_le_unchecked () +
+gint8 + +gst_byte_reader_peek_int8_unchecked () +
+gint16 + +gst_byte_reader_peek_int16_be_unchecked () +
+gint16 + +gst_byte_reader_peek_int16_le_unchecked () +
+gint32 + +gst_byte_reader_peek_int24_be_unchecked () +
+gint32 + +gst_byte_reader_peek_int24_le_unchecked () +
+gint32 + +gst_byte_reader_peek_int32_be_unchecked () +
+gint32 + +gst_byte_reader_peek_int32_le_unchecked () +
+gint64 + +gst_byte_reader_peek_int64_be_unchecked () +
+gint64 + +gst_byte_reader_peek_int64_le_unchecked () +
+guint8 + +gst_byte_reader_peek_uint8_unchecked () +
+guint16 + +gst_byte_reader_peek_uint16_be_unchecked () +
+guint16 + +gst_byte_reader_peek_uint16_le_unchecked () +
+guint32 + +gst_byte_reader_peek_uint24_be_unchecked () +
+guint32 + +gst_byte_reader_peek_uint24_le_unchecked () +
+guint32 + +gst_byte_reader_peek_uint32_be_unchecked () +
+guint32 + +gst_byte_reader_peek_uint32_le_unchecked () +
+guint64 + +gst_byte_reader_peek_uint64_be_unchecked () +
+guint64 + +gst_byte_reader_peek_uint64_le_unchecked () +
+gfloat + +gst_byte_reader_get_float32_le_unchecked () +
+gfloat + +gst_byte_reader_get_float32_be_unchecked () +
+gdouble + +gst_byte_reader_get_float64_le_unchecked () +
+gdouble + +gst_byte_reader_get_float64_be_unchecked () +
+gfloat + +gst_byte_reader_peek_float32_le_unchecked () +
+gfloat + +gst_byte_reader_peek_float32_be_unchecked () +
+gdouble + +gst_byte_reader_peek_float64_le_unchecked () +
+gdouble + +gst_byte_reader_peek_float64_be_unchecked () +
+guint8 * + +gst_byte_reader_dup_data_unchecked () +
const guint8 * + +gst_byte_reader_get_data_unchecked () +
const guint8 * + +gst_byte_reader_peek_data_unchecked () +
+
+
+

Types and Values

+
++++ + + + + +
 GstByteReader
+
+
+

Includes

+
#include <gst/base/gstbytereader.h>
+
+
+
+

Description

+

GstByteReader provides a byte reader that can read different integer and +floating point types from a memory buffer. It provides functions for reading +signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits +and functions for reading little/big endian floating points numbers of +32 and 64 bits. It also provides functions to read NUL-terminated strings +in various character encodings.

+
+
+

Functions

+
+

GST_BYTE_READER_INIT()

+
#define GST_BYTE_READER_INIT(data, size) {data, size, 0}
+
+

A GstByteReader must be initialized with this macro, before it can be +used. This macro can used be to initialize a variable, but it cannot +be assigned to a variable. In that case you have to use +gst_byte_reader_init().

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

Data from which the GstByteReader should read

 

size

Size of data +in bytes

 
+
+
+
+
+

gst_byte_reader_new ()

+
GstByteReader *
+gst_byte_reader_new (const guint8 *data,
+                     guint size);
+

Create a new GstByteReader instance, which will read from data +.

+

Free-function: gst_byte_reader_free

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

data

data from which the +GstByteReader should read.

[in][transfer none][array length=size]

size

Size of data +in bytes

 
+
+
+

Returns

+

a new GstByteReader instance.

+

[transfer full]

+
+
+
+
+

gst_byte_reader_free ()

+
void
+gst_byte_reader_free (GstByteReader *reader);
+

Frees a GstByteReader instance, which was previously allocated by +gst_byte_reader_new().

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance.

[in][transfer full]
+
+
+
+
+

gst_byte_reader_init ()

+
void
+gst_byte_reader_init (GstByteReader *reader,
+                      const guint8 *data,
+                      guint size);
+

Initializes a GstByteReader instance to read from data +. This function +can be called on already initialized instances.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstByteReader instance

 

data

data from which +the GstByteReader should read.

[in][transfer none][array length=size]

size

Size of data +in bytes

 
+
+
+
+
+

gst_byte_reader_peek_sub_reader ()

+
gboolean
+gst_byte_reader_peek_sub_reader (GstByteReader *reader,
+                                 GstByteReader *sub_reader,
+                                 guint size);
+

Initializes a GstByteReader sub-reader instance to contain size + bytes of +data from the current position of reader +. This is useful to read chunked +formats and make sure that one doesn't read beyond the size of the sub-chunk.

+

Unlike gst_byte_reader_get_sub_reader(), this function does not modify the +current position of reader +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

an existing and initialized GstByteReader instance

 

sub_reader

a GstByteReader instance to initialize as sub-reader

 

size

size of sub_reader +in bytes

 
+
+
+

Returns

+

FALSE on error or if reader +does not contain size +more bytes from +the current position, and otherwise TRUE

+
+

Since: 1.6

+
+
+
+

gst_byte_reader_get_sub_reader ()

+
gboolean
+gst_byte_reader_get_sub_reader (GstByteReader *reader,
+                                GstByteReader *sub_reader,
+                                guint size);
+

Initializes a GstByteReader sub-reader instance to contain size + bytes of +data from the current position of reader +. This is useful to read chunked +formats and make sure that one doesn't read beyond the size of the sub-chunk.

+

Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the +position of reader + and moves it forward by size + bytes.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

an existing and initialized GstByteReader instance

 

sub_reader

a GstByteReader instance to initialize as sub-reader

 

size

size of sub_reader +in bytes

 
+
+
+

Returns

+

FALSE on error or if reader +does not contain size +more bytes from +the current position, and otherwise TRUE

+
+

Since: 1.6

+
+
+
+

gst_byte_reader_get_pos ()

+
guint
+gst_byte_reader_get_pos (const GstByteReader *reader);
+

Returns the current position of a GstByteReader instance in bytes.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

The current position of reader +in bytes.

+
+
+
+
+

gst_byte_reader_get_remaining ()

+
guint
+gst_byte_reader_get_remaining (const GstByteReader *reader);
+

Returns the remaining number of bytes of a GstByteReader instance.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

The remaining number of bytes of reader +instance.

+
+
+
+
+

gst_byte_reader_set_pos ()

+
gboolean
+gst_byte_reader_set_pos (GstByteReader *reader,
+                         guint pos);
+

Sets the new position of a GstByteReader instance to pos + in bytes.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

pos

The new position in bytes

 
+
+
+

Returns

+

TRUE if the position could be set successfully, FALSE +otherwise.

+
+
+
+
+

gst_byte_reader_get_size ()

+
guint
+gst_byte_reader_get_size (const GstByteReader *reader);
+

Returns the total number of bytes of a GstByteReader instance.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

The total number of bytes of reader +instance.

+
+
+
+
+

gst_byte_reader_skip ()

+
gboolean
+gst_byte_reader_skip (GstByteReader *reader,
+                      guint nbytes);
+

Skips nbytes + bytes of the GstByteReader instance.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

nbytes

the number of bytes to skip

 
+
+
+

Returns

+

TRUE if nbytes +bytes could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int8 ()

+
gboolean
+gst_byte_reader_get_int8 (GstByteReader *reader,
+                          gint8 *val);
+

Read a signed 8 bit integer into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint8 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int16_be ()

+
gboolean
+gst_byte_reader_get_int16_be (GstByteReader *reader,
+                              gint16 *val);
+

Read a signed 16 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int16_le ()

+
gboolean
+gst_byte_reader_get_int16_le (GstByteReader *reader,
+                              gint16 *val);
+

Read a signed 16 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int24_be ()

+
gboolean
+gst_byte_reader_get_int24_be (GstByteReader *reader,
+                              gint32 *val);
+

Read a signed 24 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int24_le ()

+
gboolean
+gst_byte_reader_get_int24_le (GstByteReader *reader,
+                              gint32 *val);
+

Read a signed 24 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int32_be ()

+
gboolean
+gst_byte_reader_get_int32_be (GstByteReader *reader,
+                              gint32 *val);
+

Read a signed 32 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int32_le ()

+
gboolean
+gst_byte_reader_get_int32_le (GstByteReader *reader,
+                              gint32 *val);
+

Read a signed 32 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int64_be ()

+
gboolean
+gst_byte_reader_get_int64_be (GstByteReader *reader,
+                              gint64 *val);
+

Read a signed 64 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_int64_le ()

+
gboolean
+gst_byte_reader_get_int64_le (GstByteReader *reader,
+                              gint64 *val);
+

Read a signed 64 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint8 ()

+
gboolean
+gst_byte_reader_get_uint8 (GstByteReader *reader,
+                           guint8 *val);
+

Read an unsigned 8 bit integer into val + and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint8 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint16_be ()

+
gboolean
+gst_byte_reader_get_uint16_be (GstByteReader *reader,
+                               guint16 *val);
+

Read an unsigned 16 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint16_le ()

+
gboolean
+gst_byte_reader_get_uint16_le (GstByteReader *reader,
+                               guint16 *val);
+

Read an unsigned 16 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint24_be ()

+
gboolean
+gst_byte_reader_get_uint24_be (GstByteReader *reader,
+                               guint32 *val);
+

Read an unsigned 24 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint24_le ()

+
gboolean
+gst_byte_reader_get_uint24_le (GstByteReader *reader,
+                               guint32 *val);
+

Read an unsigned 24 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint32_be ()

+
gboolean
+gst_byte_reader_get_uint32_be (GstByteReader *reader,
+                               guint32 *val);
+

Read an unsigned 32 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint32_le ()

+
gboolean
+gst_byte_reader_get_uint32_le (GstByteReader *reader,
+                               guint32 *val);
+

Read an unsigned 32 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint64_be ()

+
gboolean
+gst_byte_reader_get_uint64_be (GstByteReader *reader,
+                               guint64 *val);
+

Read an unsigned 64 bit big endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_uint64_le ()

+
gboolean
+gst_byte_reader_get_uint64_le (GstByteReader *reader,
+                               guint64 *val);
+

Read an unsigned 64 bit little endian integer into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int8 ()

+
gboolean
+gst_byte_reader_peek_int8 (const GstByteReader *reader,
+                           gint8 *val);
+

Read a signed 8 bit integer into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint8 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int16_be ()

+
gboolean
+gst_byte_reader_peek_int16_be (const GstByteReader *reader,
+                               gint16 *val);
+

Read a signed 16 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int16_le ()

+
gboolean
+gst_byte_reader_peek_int16_le (const GstByteReader *reader,
+                               gint16 *val);
+

Read a signed 16 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int24_be ()

+
gboolean
+gst_byte_reader_peek_int24_be (const GstByteReader *reader,
+                               gint32 *val);
+

Read a signed 24 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int24_le ()

+
gboolean
+gst_byte_reader_peek_int24_le (const GstByteReader *reader,
+                               gint32 *val);
+

Read a signed 24 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int32_be ()

+
gboolean
+gst_byte_reader_peek_int32_be (const GstByteReader *reader,
+                               gint32 *val);
+

Read a signed 32 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int32_le ()

+
gboolean
+gst_byte_reader_peek_int32_le (const GstByteReader *reader,
+                               gint32 *val);
+

Read a signed 32 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int64_be ()

+
gboolean
+gst_byte_reader_peek_int64_be (const GstByteReader *reader,
+                               gint64 *val);
+

Read a signed 64 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_int64_le ()

+
gboolean
+gst_byte_reader_peek_int64_le (const GstByteReader *reader,
+                               gint64 *val);
+

Read a signed 64 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint8 ()

+
gboolean
+gst_byte_reader_peek_uint8 (const GstByteReader *reader,
+                            guint8 *val);
+

Read an unsigned 8 bit integer into val + but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint8 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint16_be ()

+
gboolean
+gst_byte_reader_peek_uint16_be (const GstByteReader *reader,
+                                guint16 *val);
+

Read an unsigned 16 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint16_le ()

+
gboolean
+gst_byte_reader_peek_uint16_le (const GstByteReader *reader,
+                                guint16 *val);
+

Read an unsigned 16 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint16 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint24_be ()

+
gboolean
+gst_byte_reader_peek_uint24_be (const GstByteReader *reader,
+                                guint32 *val);
+

Read an unsigned 24 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint24_le ()

+
gboolean
+gst_byte_reader_peek_uint24_le (const GstByteReader *reader,
+                                guint32 *val);
+

Read an unsigned 24 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint32_be ()

+
gboolean
+gst_byte_reader_peek_uint32_be (const GstByteReader *reader,
+                                guint32 *val);
+

Read an unsigned 32 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint32_le ()

+
gboolean
+gst_byte_reader_peek_uint32_le (const GstByteReader *reader,
+                                guint32 *val);
+

Read an unsigned 32 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint32 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint64_be ()

+
gboolean
+gst_byte_reader_peek_uint64_be (const GstByteReader *reader,
+                                guint64 *val);
+

Read an unsigned 64 bit big endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_uint64_le ()

+
gboolean
+gst_byte_reader_peek_uint64_le (const GstByteReader *reader,
+                                guint64 *val);
+

Read an unsigned 64 bit little endian integer into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a guint64 to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_float32_le ()

+
gboolean
+gst_byte_reader_get_float32_le (GstByteReader *reader,
+                                gfloat *val);
+

Read a 32 bit little endian floating point value into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gfloat to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_float32_be ()

+
gboolean
+gst_byte_reader_get_float32_be (GstByteReader *reader,
+                                gfloat *val);
+

Read a 32 bit big endian floating point value into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gfloat to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_float64_le ()

+
gboolean
+gst_byte_reader_get_float64_le (GstByteReader *reader,
+                                gdouble *val);
+

Read a 64 bit little endian floating point value into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gdouble to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_float64_be ()

+
gboolean
+gst_byte_reader_get_float64_be (GstByteReader *reader,
+                                gdouble *val);
+

Read a 64 bit big endian floating point value into val + +and update the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gdouble to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_float32_le ()

+
gboolean
+gst_byte_reader_peek_float32_le (const GstByteReader *reader,
+                                 gfloat *val);
+

Read a 32 bit little endian floating point value into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gfloat to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_float32_be ()

+
gboolean
+gst_byte_reader_peek_float32_be (const GstByteReader *reader,
+                                 gfloat *val);
+

Read a 32 bit big endian floating point value into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gfloat to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_float64_le ()

+
gboolean
+gst_byte_reader_peek_float64_le (const GstByteReader *reader,
+                                 gdouble *val);
+

Read a 64 bit little endian floating point value into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gdouble to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_float64_be ()

+
gboolean
+gst_byte_reader_peek_float64_be (const GstByteReader *reader,
+                                 gdouble *val);
+

Read a 64 bit big endian floating point value into val + +but keep the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

val

Pointer to a gdouble to store the result.

[out]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_get_data ()

+
gboolean
+gst_byte_reader_get_data (GstByteReader *reader,
+                          guint size,
+                          const guint8 **val);
+

Returns a constant pointer to the current data +position if at least size + bytes are left and +updates the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstByteReader instance

 

size

Size in bytes

 

val

address of a +guint8 pointer variable in which to store the result.

[out][transfer none][array length=size]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_dup_data ()

+
gboolean
+gst_byte_reader_dup_data (GstByteReader *reader,
+                          guint size,
+                          guint8 **val);
+

Free-function: g_free

+

Returns a newly-allocated copy of the current data +position if at least size + bytes are left and +updates the current position. Free with g_free() when no longer needed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstByteReader instance

 

size

Size in bytes

 

val

address of a +guint8 pointer variable in which to store the result.

[out][transfer full][array length=size]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_data ()

+
gboolean
+gst_byte_reader_peek_data (const GstByteReader *reader,
+                           guint size,
+                           const guint8 **val);
+

Returns a constant pointer to the current data +position if at least size + bytes are left and +keeps the current position.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

reader

a GstByteReader instance

 

size

Size in bytes

 

val

address of a +guint8 pointer variable in which to store the result.

[out][transfer none][array length=size]
+
+
+

Returns

+

TRUE if successful, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_masked_scan_uint32 ()

+
guint
+gst_byte_reader_masked_scan_uint32 (const GstByteReader *reader,
+                                    guint32 mask,
+                                    guint32 pattern,
+                                    guint offset,
+                                    guint size);
+

Scan for pattern pattern + with applied mask mask + in the byte reader data, +starting from offset offset + relative to the current position.

+

The bytes in pattern + and mask + are interpreted left-to-right, regardless +of endianness. All four bytes of the pattern must be present in the +byte reader data for it to match, even if the first or last bytes are masked +out.

+

It is an error to call this function without making sure that there is +enough data (offset+size bytes) in the byte reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

reader

a GstByteReader

 

mask

mask to apply to data before matching against pattern +

 

pattern

pattern to match (after mask is applied)

 

offset

offset from which to start scanning, relative to the current +position

 

size

number of bytes to scan from offset

 
+
+
+

Returns

+

offset of the first match, or -1 if no match was found.

+

Example:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
// Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
+gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
+// -> returns 0
+gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
+// -> returns -1
+gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
+// -> returns 1
+gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
+// -> returns -1
+gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
+// -> returns 0
+gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
+// -> returns 2
+gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
+// -> returns -1
+
+ +

+
+
+
+
+

gst_byte_reader_masked_scan_uint32_peek ()

+
guint
+gst_byte_reader_masked_scan_uint32_peek
+                               (const GstByteReader *reader,
+                                guint32 mask,
+                                guint32 pattern,
+                                guint offset,
+                                guint size,
+                                guint32 *value);
+

Scan for pattern pattern + with applied mask mask + in the byte reader data, +starting from offset offset + relative to the current position.

+

The bytes in pattern + and mask + are interpreted left-to-right, regardless +of endianness. All four bytes of the pattern must be present in the +byte reader data for it to match, even if the first or last bytes are masked +out.

+

It is an error to call this function without making sure that there is +enough data (offset+size bytes) in the byte reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

reader

a GstByteReader

 

mask

mask to apply to data before matching against pattern +

 

pattern

pattern to match (after mask is applied)

 

offset

offset from which to start scanning, relative to the current +position

 

size

number of bytes to scan from offset

 

value

pointer to uint32 to return matching data.

[out]
+
+
+

Returns

+

offset of the first match, or -1 if no match was found.

+
+

Since: 1.6

+
+
+
+

gst_byte_reader_get_string()

+
#define             gst_byte_reader_get_string(reader,str)
+
+
+
+

gst_byte_reader_get_string_utf8 ()

+
gboolean
+gst_byte_reader_get_string_utf8 (GstByteReader *reader,
+                                 const gchar **str);
+

Returns a constant pointer to the current data position if there is +a NUL-terminated string in the data (this could be just a NUL terminator), +advancing the current position to the byte after the string. This will work +for any NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc.

+

No input checking for valid UTF-8 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +gchar pointer variable in which to store the result.

[out][transfer none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be found, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_string()

+
#define             gst_byte_reader_peek_string(reader,str)
+

Returns a constant pointer to the current data position if there is +a NUL-terminated string in the data (this could be just a NUL terminator). +The current position will be maintained. This will work for any +NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +gchar pointer variable in which to store the result.

[out][transfer none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_peek_string_utf8 ()

+
gboolean
+gst_byte_reader_peek_string_utf8 (const GstByteReader *reader,
+                                  const gchar **str);
+

Returns a constant pointer to the current data position if there is +a NUL-terminated string in the data (this could be just a NUL terminator). +The current position will be maintained. This will work for any +NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc.

+

No input checking for valid UTF-8 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +gchar pointer variable in which to store the result.

[out][transfer none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_dup_string()

+
#define             gst_byte_reader_dup_string(reader,str)
+
+
+
+

gst_byte_reader_dup_string_utf8 ()

+
gboolean
+gst_byte_reader_dup_string_utf8 (GstByteReader *reader,
+                                 gchar **str);
+

Free-function: g_free

+

FIXME:Reads (copies) a NUL-terminated string in the GstByteReader instance, +advancing the current position to the byte after the string. This will work +for any NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +gchar pointer variable in which to store the result.

[out][transfer full][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be read into str +, FALSE otherwise. The +string put into str +must be freed with g_free() when no longer needed.

+
+
+
+
+

gst_byte_reader_dup_string_utf16 ()

+
gboolean
+gst_byte_reader_dup_string_utf16 (GstByteReader *reader,
+                                  guint16 **str);
+

Free-function: g_free

+

Returns a newly-allocated copy of the current data position if there is +a NUL-terminated UTF-16 string in the data (this could be an empty string +as well), and advances the current position.

+

No input checking for valid UTF-16 is done. This function is endianness +agnostic - you should not assume the UTF-16 characters are in host +endianness.

+

This function will fail if no NUL-terminator was found in in the data.

+

Note: there is no peek or get variant of this function to ensure correct +byte alignment of the UTF-16 string.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +guint16 pointer variable in which to store the result.

[out][transfer full][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be read, FALSE otherwise. The +string put into str +must be freed with g_free() when no longer needed.

+
+
+
+
+

gst_byte_reader_dup_string_utf32 ()

+
gboolean
+gst_byte_reader_dup_string_utf32 (GstByteReader *reader,
+                                  guint32 **str);
+

Free-function: g_free

+

Returns a newly-allocated copy of the current data position if there is +a NUL-terminated UTF-32 string in the data (this could be an empty string +as well), and advances the current position.

+

No input checking for valid UTF-32 is done. This function is endianness +agnostic - you should not assume the UTF-32 characters are in host +endianness.

+

This function will fail if no NUL-terminator was found in in the data.

+

Note: there is no peek or get variant of this function to ensure correct +byte alignment of the UTF-32 string.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

str

address of a +guint32 pointer variable in which to store the result.

[out][transfer full][array zero-terminated=1]
+
+
+

Returns

+

TRUE if a string could be read, FALSE otherwise. The +string put into str +must be freed with g_free() when no longer needed.

+
+
+
+
+

gst_byte_reader_skip_string()

+
#define             gst_byte_reader_skip_string(reader)
+

Skips a NUL-terminated string in the GstByteReader instance, advancing +the current position to the byte after the string. This will work for +any NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_skip_string_utf8 ()

+
gboolean
+gst_byte_reader_skip_string_utf8 (GstByteReader *reader);
+

Skips a NUL-terminated string in the GstByteReader instance, advancing +the current position to the byte after the string. This will work for +any NUL-terminated string with a character width of 8 bits, so ASCII, +UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_skip_string_utf16 ()

+
gboolean
+gst_byte_reader_skip_string_utf16 (GstByteReader *reader);
+

Skips a NUL-terminated UTF-16 string in the GstByteReader instance, +advancing the current position to the byte after the string.

+

No input checking for valid UTF-16 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_skip_string_utf32 ()

+
gboolean
+gst_byte_reader_skip_string_utf32 (GstByteReader *reader);
+

Skips a NUL-terminated UTF-32 string in the GstByteReader instance, +advancing the current position to the byte after the string.

+

No input checking for valid UTF-32 is done.

+

This function will fail if no NUL-terminator was found in in the data.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

TRUE if a string could be skipped, FALSE otherwise.

+
+
+
+
+

gst_byte_reader_skip_unchecked ()

+
void
+gst_byte_reader_skip_unchecked (GstByteReader *reader,
+                                guint nbytes);
+

Skips nbytes + bytes of the GstByteReader instance without checking if +there are enough bytes available in the byte reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

nbytes

the number of bytes to skip

 
+
+
+
+
+

gst_byte_reader_get_int8_unchecked ()

+
gint8
+gst_byte_reader_get_int8_unchecked (GstByteReader *reader);
+

Read an signed 8 bit integer without checking if there are enough bytes +available in the byte reader and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 8 bit integer.

+
+
+
+
+

gst_byte_reader_get_int16_be_unchecked ()

+
gint16
+gst_byte_reader_get_int16_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 16 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 16 bit integer.

+
+
+
+
+

gst_byte_reader_get_int16_le_unchecked ()

+
gint16
+gst_byte_reader_get_int16_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 16 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 16 bit integer.

+
+
+
+
+

gst_byte_reader_get_int24_be_unchecked ()

+
gint32
+gst_byte_reader_get_int24_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 24 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 24 bit integer (as gint32)

+
+
+
+
+

gst_byte_reader_get_int24_le_unchecked ()

+
gint32
+gst_byte_reader_get_int24_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 24 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 24 bit integer (as gint32)

+
+
+
+
+

gst_byte_reader_get_int32_be_unchecked ()

+
gint32
+gst_byte_reader_get_int32_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 32 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 32 bit integer.

+
+
+
+
+

gst_byte_reader_get_int32_le_unchecked ()

+
gint32
+gst_byte_reader_get_int32_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 32 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 32 bit integer.

+
+
+
+
+

gst_byte_reader_get_int64_be_unchecked ()

+
gint64
+gst_byte_reader_get_int64_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 64 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 64 bit integer.

+
+
+
+
+

gst_byte_reader_get_int64_le_unchecked ()

+
gint64
+gst_byte_reader_get_int64_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 64 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 64 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint8_unchecked ()

+
guint8
+gst_byte_reader_get_uint8_unchecked (GstByteReader *reader);
+

Read an unsigned 8 bit integer without checking if there are enough bytes +available in the byte reader and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 8 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint16_be_unchecked ()

+
guint16
+gst_byte_reader_get_uint16_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 16 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 16 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint16_le_unchecked ()

+
guint16
+gst_byte_reader_get_uint16_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 16 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 16 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint24_be_unchecked ()

+
guint32
+gst_byte_reader_get_uint24_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 24 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 24 bit integer (as guint32)

+
+
+
+
+

gst_byte_reader_get_uint24_le_unchecked ()

+
guint32
+gst_byte_reader_get_uint24_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 24 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 24 bit integer (as guint32)

+
+
+
+
+

gst_byte_reader_get_uint32_be_unchecked ()

+
guint32
+gst_byte_reader_get_uint32_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 32 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 32 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint32_le_unchecked ()

+
guint32
+gst_byte_reader_get_uint32_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 32 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 32 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint64_be_unchecked ()

+
guint64
+gst_byte_reader_get_uint64_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 64 bit integer in big endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 64 bit integer.

+
+
+
+
+

gst_byte_reader_get_uint64_le_unchecked ()

+
guint64
+gst_byte_reader_get_uint64_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 64 bit integer in little endian format without checking +if there are enough bytes available in the byte reader and update the +current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 64 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int8_unchecked ()

+
gint8
+gst_byte_reader_peek_int8_unchecked (GstByteReader *reader);
+

Read an signed 8 bit integer without checking if there are enough bytes +available in the byte reader, but do not advance the current read position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 8 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int16_be_unchecked ()

+
gint16
+gst_byte_reader_peek_int16_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 16 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 16 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int16_le_unchecked ()

+
gint16
+gst_byte_reader_peek_int16_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 16 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 16 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int24_be_unchecked ()

+
gint32
+gst_byte_reader_peek_int24_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 24 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 24 bit integer (as gint32)

+
+
+
+
+

gst_byte_reader_peek_int24_le_unchecked ()

+
gint32
+gst_byte_reader_peek_int24_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 24 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 24 bit integer (as gint32)

+
+
+
+
+

gst_byte_reader_peek_int32_be_unchecked ()

+
gint32
+gst_byte_reader_peek_int32_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 32 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 32 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int32_le_unchecked ()

+
gint32
+gst_byte_reader_peek_int32_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 32 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 32 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int64_be_unchecked ()

+
gint64
+gst_byte_reader_peek_int64_be_unchecked
+                               (GstByteReader *reader);
+

Read a signed 64 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 64 bit integer.

+
+
+
+
+

gst_byte_reader_peek_int64_le_unchecked ()

+
gint64
+gst_byte_reader_peek_int64_le_unchecked
+                               (GstByteReader *reader);
+

Read a signed 64 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

signed 64 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint8_unchecked ()

+
guint8
+gst_byte_reader_peek_uint8_unchecked (GstByteReader *reader);
+

Read an unsigned 8 bit integer without checking if there are enough bytes +available in the byte reader, but do not advance the current read position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 8 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint16_be_unchecked ()

+
guint16
+gst_byte_reader_peek_uint16_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 16 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 16 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint16_le_unchecked ()

+
guint16
+gst_byte_reader_peek_uint16_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 16 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 16 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint24_be_unchecked ()

+
guint32
+gst_byte_reader_peek_uint24_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 24 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 24 bit integer (as guint32)

+
+
+
+
+

gst_byte_reader_peek_uint24_le_unchecked ()

+
guint32
+gst_byte_reader_peek_uint24_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 24 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 24 bit integer (as guint32)

+
+
+
+
+

gst_byte_reader_peek_uint32_be_unchecked ()

+
guint32
+gst_byte_reader_peek_uint32_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 32 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 32 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint32_le_unchecked ()

+
guint32
+gst_byte_reader_peek_uint32_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 32 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 32 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint64_be_unchecked ()

+
guint64
+gst_byte_reader_peek_uint64_be_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 64 bit integer in big endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 64 bit integer.

+
+
+
+
+

gst_byte_reader_peek_uint64_le_unchecked ()

+
guint64
+gst_byte_reader_peek_uint64_le_unchecked
+                               (GstByteReader *reader);
+

Read an unsigned 64 bit integer in little endian format without checking +if there are enough bytes available in the byte reader, but do not advance +the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

unsigned 64 bit integer.

+
+
+
+
+

gst_byte_reader_get_float32_le_unchecked ()

+
gfloat
+gst_byte_reader_get_float32_le_unchecked
+                               (GstByteReader *reader);
+

Read a 32 bit little endian float without checking if there is enough +data available and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

floating point value read

+
+
+
+
+

gst_byte_reader_get_float32_be_unchecked ()

+
gfloat
+gst_byte_reader_get_float32_be_unchecked
+                               (GstByteReader *reader);
+

Read a 32 bit big endian float without checking if there is enough +data available and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

floating point value read

+
+
+
+
+

gst_byte_reader_get_float64_le_unchecked ()

+
gdouble
+gst_byte_reader_get_float64_le_unchecked
+                               (GstByteReader *reader);
+

Read a 64 bit little endian float without checking if there is enough +data available and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

double precision floating point value read

+
+
+
+
+

gst_byte_reader_get_float64_be_unchecked ()

+
gdouble
+gst_byte_reader_get_float64_be_unchecked
+                               (GstByteReader *reader);
+

Read a 64 bit big endian float without checking if there is enough +data available and update the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

double precision floating point value read

+
+
+
+
+

gst_byte_reader_peek_float32_le_unchecked ()

+
gfloat
+gst_byte_reader_peek_float32_le_unchecked
+                               (GstByteReader *reader);
+

Read a 32 bit little endian float without checking if there is enough +data available, but keep the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

floating point value read

+
+
+
+
+

gst_byte_reader_peek_float32_be_unchecked ()

+
gfloat
+gst_byte_reader_peek_float32_be_unchecked
+                               (GstByteReader *reader);
+

Read a 32 bit big endian float without checking if there is enough +data available, but keep the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

floating point value read

+
+
+
+
+

gst_byte_reader_peek_float64_le_unchecked ()

+
gdouble
+gst_byte_reader_peek_float64_le_unchecked
+                               (GstByteReader *reader);
+

Read a 64 bit little endian float without checking if there is enough +data available, but keep the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

double precision floating point value read

+
+
+
+
+

gst_byte_reader_peek_float64_be_unchecked ()

+
gdouble
+gst_byte_reader_peek_float64_be_unchecked
+                               (GstByteReader *reader);
+

Read a 64 bit big endian float without checking if there is enough +data available, but keep the current position.

+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

double precision floating point value read

+
+
+
+
+

gst_byte_reader_dup_data_unchecked ()

+
guint8 *
+gst_byte_reader_dup_data_unchecked (GstByteReader *reader,
+                                    guint size);
+

Returns a newly-allocated copy of the data at the current data position +without checking if at least size + bytes are left. Advances the current read +position by size + bytes.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

size

Size in bytes

 
+
+
+

Returns

+

a newly-allocated copy of the +data size +bytes in size. Free with g_free() when no longer needed.

+

[transfer full][array length=size]

+
+
+
+
+

gst_byte_reader_get_data_unchecked ()

+
const guint8 *
+gst_byte_reader_get_data_unchecked (GstByteReader *reader,
+                                    guint size);
+

Returns a constant pointer to the current data position without checking +if at least size + bytes are left. Advances the current read position by +size + bytes.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

reader

a GstByteReader instance

 

size

Size in bytes

 
+
+
+

Returns

+

a constant pointer to the +current data position.

+

[transfer none][array length=size]

+
+
+
+
+

gst_byte_reader_peek_data_unchecked ()

+
const guint8 *
+gst_byte_reader_peek_data_unchecked (const GstByteReader *reader);
+
+

Parameters

+
+++++ + + + + + +

reader

a GstByteReader instance

 
+
+
+

Returns

+

a constant pointer to the current data position.

+

[transfer none]

+
+
+
+
+

Types and Values

+
+

GstByteReader

+
typedef struct {
+  const guint8 *data;
+  guint size;
+
+  guint byte;  /* Byte position */
+} GstByteReader;
+
+

A byte reader instance.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

const guint8 *data;

Data from which the bit reader will +read.

[array length=size]

guint size;

Size of data +in bytes

 

guint byte;

Current byte position

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstByteWriter.html b/docs/libs/html/gstreamer-libs-GstByteWriter.html new file mode 100644 index 0000000..b5f7afb --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstByteWriter.html @@ -0,0 +1,3054 @@ + + + + +GstByteWriter: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstByteWriter

+

GstByteWriter — Writes different integer, string and floating point + types to a memory buffer and allows reading

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstByteWriter * + +gst_byte_writer_new () +
+GstByteWriter * + +gst_byte_writer_new_with_data () +
+GstByteWriter * + +gst_byte_writer_new_with_size () +
+void + +gst_byte_writer_init () +
+void + +gst_byte_writer_init_with_data () +
+void + +gst_byte_writer_init_with_size () +
+void + +gst_byte_writer_free () +
+GstBuffer * + +gst_byte_writer_free_and_get_buffer () +
+guint8 * + +gst_byte_writer_free_and_get_data () +
+void + +gst_byte_writer_reset () +
+guint8 * + +gst_byte_writer_reset_and_get_data () +
+GstBuffer * + +gst_byte_writer_reset_and_get_buffer () +
+guint + +gst_byte_writer_get_pos () +
+gboolean + +gst_byte_writer_set_pos () +
+guint + +gst_byte_writer_get_remaining () +
+guint + +gst_byte_writer_get_size () +
+gboolean + +gst_byte_writer_ensure_free_space () +
+gboolean + +gst_byte_writer_put_int8 () +
+gboolean + +gst_byte_writer_put_int16_be () +
+gboolean + +gst_byte_writer_put_int16_le () +
+gboolean + +gst_byte_writer_put_int24_be () +
+gboolean + +gst_byte_writer_put_int24_le () +
+gboolean + +gst_byte_writer_put_int32_be () +
+gboolean + +gst_byte_writer_put_int32_le () +
+gboolean + +gst_byte_writer_put_int64_be () +
+gboolean + +gst_byte_writer_put_int64_le () +
+gboolean + +gst_byte_writer_put_uint8 () +
+gboolean + +gst_byte_writer_put_uint16_be () +
+gboolean + +gst_byte_writer_put_uint16_le () +
+gboolean + +gst_byte_writer_put_uint24_be () +
+gboolean + +gst_byte_writer_put_uint24_le () +
+gboolean + +gst_byte_writer_put_uint32_be () +
+gboolean + +gst_byte_writer_put_uint32_le () +
+gboolean + +gst_byte_writer_put_uint64_be () +
+gboolean + +gst_byte_writer_put_uint64_le () +
+gboolean + +gst_byte_writer_put_float32_be () +
+gboolean + +gst_byte_writer_put_float32_le () +
+gboolean + +gst_byte_writer_put_float64_be () +
+gboolean + +gst_byte_writer_put_float64_le () +
#define +gst_byte_writer_put_string() +
+gboolean + +gst_byte_writer_put_string_utf16 () +
+gboolean + +gst_byte_writer_put_string_utf32 () +
+gboolean + +gst_byte_writer_put_string_utf8 () +
+gboolean + +gst_byte_writer_put_data () +
+gboolean + +gst_byte_writer_fill () +
+gboolean + +gst_byte_writer_put_buffer () +
+void + +gst_byte_writer_put_buffer_unchecked () +
+void + +gst_byte_writer_put_int8_unchecked () +
+void + +gst_byte_writer_put_int16_be_unchecked () +
+void + +gst_byte_writer_put_int16_le_unchecked () +
+void + +gst_byte_writer_put_int24_be_unchecked () +
+void + +gst_byte_writer_put_int24_le_unchecked () +
+void + +gst_byte_writer_put_int32_be_unchecked () +
+void + +gst_byte_writer_put_int32_le_unchecked () +
+void + +gst_byte_writer_put_int64_be_unchecked () +
+void + +gst_byte_writer_put_int64_le_unchecked () +
+void + +gst_byte_writer_put_uint8_unchecked () +
+void + +gst_byte_writer_put_uint16_be_unchecked () +
+void + +gst_byte_writer_put_uint16_le_unchecked () +
+void + +gst_byte_writer_put_uint24_be_unchecked () +
+void + +gst_byte_writer_put_uint24_le_unchecked () +
+void + +gst_byte_writer_put_uint32_be_unchecked () +
+void + +gst_byte_writer_put_uint32_le_unchecked () +
+void + +gst_byte_writer_put_uint64_be_unchecked () +
+void + +gst_byte_writer_put_uint64_le_unchecked () +
+void + +gst_byte_writer_put_float32_be_unchecked () +
+void + +gst_byte_writer_put_float32_le_unchecked () +
+void + +gst_byte_writer_put_float64_be_unchecked () +
+void + +gst_byte_writer_put_float64_le_unchecked () +
+void + +gst_byte_writer_put_data_unchecked () +
+void + +gst_byte_writer_fill_unchecked () +
+
+
+

Types and Values

+
++++ + + + + +
 GstByteWriter
+
+
+

Includes

+
#include <gst/base/gstbytewriter.h>
+
+
+
+

Description

+

GstByteWriter provides a byte writer and reader that can write/read different +integer and floating point types to/from a memory buffer. It provides functions +for writing/reading signed/unsigned, little/big endian integers of 8, 16, 24, +32 and 64 bits and functions for reading little/big endian floating points numbers of +32 and 64 bits. It also provides functions to write/read NUL-terminated strings +in various character encodings.

+
+
+

Functions

+
+

gst_byte_writer_new ()

+
GstByteWriter *
+gst_byte_writer_new (void);
+

Creates a new, empty GstByteWriter instance

+

Free-function: gst_byte_writer_free

+

[skip]

+
+

Returns

+

a new, empty GstByteWriter instance.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_new_with_data ()

+
GstByteWriter *
+gst_byte_writer_new_with_data (guint8 *data,
+                               guint size,
+                               gboolean initialized);
+

Creates a new GstByteWriter instance with the given +memory area. If initialized + is TRUE it is possible to +read size + bytes from the GstByteWriter from the beginning.

+

Free-function: gst_byte_writer_free

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

data

Memory area for writing

 

size

Size of data +in bytes

 

initialized

If TRUE the complete data can be read from the beginning

 
+
+
+

Returns

+

a new GstByteWriter instance.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_new_with_size ()

+
GstByteWriter *
+gst_byte_writer_new_with_size (guint size,
+                               gboolean fixed);
+

Creates a new GstByteWriter instance with the given +initial data size.

+

Free-function: gst_byte_writer_free

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

size

Initial size of data

 

fixed

If TRUE the data can't be reallocated

 
+
+
+

Returns

+

a new GstByteWriter instance.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_init ()

+
void
+gst_byte_writer_init (GstByteWriter *writer);
+

Initializes writer + to an empty instance

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+
+
+

gst_byte_writer_init_with_data ()

+
void
+gst_byte_writer_init_with_data (GstByteWriter *writer,
+                                guint8 *data,
+                                guint size,
+                                gboolean initialized);
+

Initializes writer + with the given +memory area. If initialized + is TRUE it is possible to +read size + bytes from the GstByteWriter from the beginning.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

Memory area for writing.

[array length=size][transfer none]

size

Size of data +in bytes

 

initialized

If TRUE the complete data can be read from the beginning

 
+
+
+
+
+

gst_byte_writer_init_with_size ()

+
void
+gst_byte_writer_init_with_size (GstByteWriter *writer,
+                                guint size,
+                                gboolean fixed);
+

Initializes writer + with the given initial data size.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

size

Initial size of data

 

fixed

If TRUE the data can't be reallocated

 
+
+
+
+
+

gst_byte_writer_free ()

+
void
+gst_byte_writer_free (GstByteWriter *writer);
+

Frees writer + and all memory allocated by it.

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance.

[in][transfer full]
+
+
+
+
+

gst_byte_writer_free_and_get_buffer ()

+
GstBuffer *
+gst_byte_writer_free_and_get_buffer (GstByteWriter *writer);
+

Frees writer + and all memory allocated by it except +the current data, which is returned as GstBuffer.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance.

[in][transfer full]
+
+
+

Returns

+

the current data as buffer. gst_buffer_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_free_and_get_data ()

+
guint8 *
+gst_byte_writer_free_and_get_data (GstByteWriter *writer);
+

Frees writer + and all memory allocated by it except +the current data, which is returned.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance.

[in][transfer full]
+
+
+

Returns

+

the current data. g_free() after usage.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_reset ()

+
void
+gst_byte_writer_reset (GstByteWriter *writer);
+

Resets writer + and frees the data if it's +owned by writer +.

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+
+
+

gst_byte_writer_reset_and_get_data ()

+
guint8 *
+gst_byte_writer_reset_and_get_data (GstByteWriter *writer);
+

Resets writer + and returns the current data.

+

Free-function: g_free

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+

Returns

+

the current data. g_free() after +usage.

+

[array][transfer full]

+
+
+
+
+

gst_byte_writer_reset_and_get_buffer ()

+
GstBuffer *
+gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer);
+

Resets writer + and returns the current data as buffer.

+

Free-function: gst_buffer_unref

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+

Returns

+

the current data as buffer. gst_buffer_unref() +after usage.

+

[transfer full]

+
+
+
+
+

gst_byte_writer_get_pos ()

+
guint
+gst_byte_writer_get_pos (const GstByteWriter *writer);
+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+

Returns

+

The current position of the read/write cursor

+
+
+
+
+

gst_byte_writer_set_pos ()

+
gboolean
+gst_byte_writer_set_pos (GstByteWriter *writer,
+                         guint pos);
+

Sets the current read/write cursor of writer +. The new position +can only be between 0 and the current size.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

pos

new position

 
+
+
+

Returns

+

TRUE if the new position could be set

+
+
+
+
+

gst_byte_writer_get_remaining ()

+
guint
+gst_byte_writer_get_remaining (const GstByteWriter *writer);
+

Returns the remaining size of data that can still be written. If +-1 is returned the remaining size is only limited by system resources.

+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+

Returns

+

the remaining size of data that can still be written

+
+
+
+
+

gst_byte_writer_get_size ()

+
guint
+gst_byte_writer_get_size (const GstByteWriter *writer);
+
+

Parameters

+
+++++ + + + + + +

writer

GstByteWriter instance

 
+
+
+

Returns

+

The current, initialized size of the data

+
+
+
+
+

gst_byte_writer_ensure_free_space ()

+
gboolean
+gst_byte_writer_ensure_free_space (GstByteWriter *writer,
+                                   guint size);
+

Checks if enough free space from the current write cursor is +available and reallocates if necessary.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

size

Number of bytes that should be available

 
+
+
+

Returns

+

TRUE if at least size +bytes are still available

+
+
+
+
+

gst_byte_writer_put_int8 ()

+
gboolean
+gst_byte_writer_put_int8 (GstByteWriter *writer,
+                          gint8 val);
+

Writes a signed 8 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int16_be ()

+
gboolean
+gst_byte_writer_put_int16_be (GstByteWriter *writer,
+                              gint16 val);
+

Writes a signed big endian 16 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int16_le ()

+
gboolean
+gst_byte_writer_put_int16_le (GstByteWriter *writer,
+                              gint16 val);
+

Writes a signed little endian 16 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int24_be ()

+
gboolean
+gst_byte_writer_put_int24_be (GstByteWriter *writer,
+                              gint32 val);
+

Writes a signed big endian 24 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int24_le ()

+
gboolean
+gst_byte_writer_put_int24_le (GstByteWriter *writer,
+                              gint32 val);
+

Writes a signed little endian 24 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int32_be ()

+
gboolean
+gst_byte_writer_put_int32_be (GstByteWriter *writer,
+                              gint32 val);
+

Writes a signed big endian 32 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int32_le ()

+
gboolean
+gst_byte_writer_put_int32_le (GstByteWriter *writer,
+                              gint32 val);
+

Writes a signed little endian 32 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int64_be ()

+
gboolean
+gst_byte_writer_put_int64_be (GstByteWriter *writer,
+                              gint64 val);
+

Writes a signed big endian 64 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_int64_le ()

+
gboolean
+gst_byte_writer_put_int64_le (GstByteWriter *writer,
+                              gint64 val);
+

Writes a signed little endian 64 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint8 ()

+
gboolean
+gst_byte_writer_put_uint8 (GstByteWriter *writer,
+                           guint8 val);
+

Writes a unsigned 8 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint16_be ()

+
gboolean
+gst_byte_writer_put_uint16_be (GstByteWriter *writer,
+                               guint16 val);
+

Writes a unsigned big endian 16 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint16_le ()

+
gboolean
+gst_byte_writer_put_uint16_le (GstByteWriter *writer,
+                               guint16 val);
+

Writes a unsigned little endian 16 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint24_be ()

+
gboolean
+gst_byte_writer_put_uint24_be (GstByteWriter *writer,
+                               guint32 val);
+

Writes a unsigned big endian 24 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint24_le ()

+
gboolean
+gst_byte_writer_put_uint24_le (GstByteWriter *writer,
+                               guint32 val);
+

Writes a unsigned little endian 24 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint32_be ()

+
gboolean
+gst_byte_writer_put_uint32_be (GstByteWriter *writer,
+                               guint32 val);
+

Writes a unsigned big endian 32 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint32_le ()

+
gboolean
+gst_byte_writer_put_uint32_le (GstByteWriter *writer,
+                               guint32 val);
+

Writes a unsigned little endian 32 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint64_be ()

+
gboolean
+gst_byte_writer_put_uint64_be (GstByteWriter *writer,
+                               guint64 val);
+

Writes a unsigned big endian 64 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_uint64_le ()

+
gboolean
+gst_byte_writer_put_uint64_le (GstByteWriter *writer,
+                               guint64 val);
+

Writes a unsigned little endian 64 bit integer to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_float32_be ()

+
gboolean
+gst_byte_writer_put_float32_be (GstByteWriter *writer,
+                                gfloat val);
+

Writes a big endian 32 bit float to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_float32_le ()

+
gboolean
+gst_byte_writer_put_float32_le (GstByteWriter *writer,
+                                gfloat val);
+

Writes a little endian 32 bit float to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_float64_be ()

+
gboolean
+gst_byte_writer_put_float64_be (GstByteWriter *writer,
+                                gdouble val);
+

Writes a big endian 64 bit float to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_float64_le ()

+
gboolean
+gst_byte_writer_put_float64_le (GstByteWriter *writer,
+                                gdouble val);
+

Writes a little endian 64 bit float to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_string()

+
#define             gst_byte_writer_put_string(writer, data)
+

Write a NUL-terminated string to writer + (including the terminator). The +string is assumed to be in an 8-bit encoding (e.g. ASCII,UTF-8 or +ISO-8859-1).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

Null terminated string.

[in][array zero-terminated=1]
+
+
+

Returns

+

TRUE if the string could be written

+
+
+
+
+

gst_byte_writer_put_string_utf16 ()

+
gboolean
+gst_byte_writer_put_string_utf16 (GstByteWriter *writer,
+                                  const guint16 *data);
+

Writes a NUL-terminated UTF16 string to writer + (including the terminator).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

UTF16 string to write.

[transfer none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_string_utf32 ()

+
gboolean
+gst_byte_writer_put_string_utf32 (GstByteWriter *writer,
+                                  const guint32 *data);
+

Writes a NUL-terminated UTF32 string to writer + (including the terminator).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

UTF32 string to write.

[transfer none][array zero-terminated=1]
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_string_utf8 ()

+
gboolean
+gst_byte_writer_put_string_utf8 (GstByteWriter *writer,
+                                 const gchar *data);
+

Writes a NUL-terminated UTF8 string to writer + (including the terminator).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

UTF8 string to write.

[transfer none]
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_data ()

+
gboolean
+gst_byte_writer_put_data (GstByteWriter *writer,
+                          const guint8 *data,
+                          guint size);
+

Writes size + bytes of data + to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

Data to write.

[transfer none][array length=size]

size

Size of data +in bytes

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_fill ()

+
gboolean
+gst_byte_writer_fill (GstByteWriter *writer,
+                      guint8 value,
+                      guint size);
+

Writes size + bytes containing value + to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

value

Value to be written

 

size

Number of bytes to be written

 
+
+
+

Returns

+

TRUE if the value could be written

+
+
+
+
+

gst_byte_writer_put_buffer ()

+
gboolean
+gst_byte_writer_put_buffer (GstByteWriter *writer,
+                            GstBuffer *buffer,
+                            gsize offset,
+                            gssize size);
+

Writes size + bytes of data + to writer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

buffer

source GstBuffer.

[transfer none]

offset

offset to copy from

 

size

total size to copy. If -1, all data is copied

 
+
+
+

Returns

+

TRUE if the data could be written

+
+
+
+
+

gst_byte_writer_put_buffer_unchecked ()

+
void
+gst_byte_writer_put_buffer_unchecked (GstByteWriter *writer,
+                                      GstBuffer *buffer,
+                                      gsize offset,
+                                      gssize size);
+
+
+
+

gst_byte_writer_put_int8_unchecked ()

+
void
+gst_byte_writer_put_int8_unchecked (GstByteWriter *writer,
+                                    gint8 val);
+
+
+
+

gst_byte_writer_put_int16_be_unchecked ()

+
void
+gst_byte_writer_put_int16_be_unchecked
+                               (GstByteWriter *writer,
+                                gint16 val);
+

Writes a signed big endian 16 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int16_le_unchecked ()

+
void
+gst_byte_writer_put_int16_le_unchecked
+                               (GstByteWriter *writer,
+                                gint16 val);
+

Writes a signed little endian 16 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int24_be_unchecked ()

+
void
+gst_byte_writer_put_int24_be_unchecked
+                               (GstByteWriter *writer,
+                                gint32 val);
+

Writes a signed big endian 24 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int24_le_unchecked ()

+
void
+gst_byte_writer_put_int24_le_unchecked
+                               (GstByteWriter *writer,
+                                gint32 val);
+

Writes a signed little endian 24 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int32_be_unchecked ()

+
void
+gst_byte_writer_put_int32_be_unchecked
+                               (GstByteWriter *writer,
+                                gint32 val);
+

Writes a signed big endian 32 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int32_le_unchecked ()

+
void
+gst_byte_writer_put_int32_le_unchecked
+                               (GstByteWriter *writer,
+                                gint32 val);
+

Writes a signed little endian 32 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int64_be_unchecked ()

+
void
+gst_byte_writer_put_int64_be_unchecked
+                               (GstByteWriter *writer,
+                                gint64 val);
+

Writes a signed big endian 64 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_int64_le_unchecked ()

+
void
+gst_byte_writer_put_int64_le_unchecked
+                               (GstByteWriter *writer,
+                                gint64 val);
+

Writes a signed little endian 64 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint8_unchecked ()

+
void
+gst_byte_writer_put_uint8_unchecked (GstByteWriter *writer,
+                                     guint8 val);
+

Writes a unsigned 8 bit integer to writer + without checking if there +is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint16_be_unchecked ()

+
void
+gst_byte_writer_put_uint16_be_unchecked
+                               (GstByteWriter *writer,
+                                guint16 val);
+

Writes a unsigned big endian 16 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint16_le_unchecked ()

+
void
+gst_byte_writer_put_uint16_le_unchecked
+                               (GstByteWriter *writer,
+                                guint16 val);
+

Writes a unsigned little endian 16 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint24_be_unchecked ()

+
void
+gst_byte_writer_put_uint24_be_unchecked
+                               (GstByteWriter *writer,
+                                guint32 val);
+

Writes a unsigned big endian 24 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint24_le_unchecked ()

+
void
+gst_byte_writer_put_uint24_le_unchecked
+                               (GstByteWriter *writer,
+                                guint32 val);
+

Writes a unsigned little endian 24 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint32_be_unchecked ()

+
void
+gst_byte_writer_put_uint32_be_unchecked
+                               (GstByteWriter *writer,
+                                guint32 val);
+

Writes a unsigned big endian 32 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint32_le_unchecked ()

+
void
+gst_byte_writer_put_uint32_le_unchecked
+                               (GstByteWriter *writer,
+                                guint32 val);
+

Writes a unsigned little endian 32 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint64_be_unchecked ()

+
void
+gst_byte_writer_put_uint64_be_unchecked
+                               (GstByteWriter *writer,
+                                guint64 val);
+

Writes a unsigned big endian 64 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_uint64_le_unchecked ()

+
void
+gst_byte_writer_put_uint64_le_unchecked
+                               (GstByteWriter *writer,
+                                guint64 val);
+

Writes a unsigned little endian 64 bit integer to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_float32_be_unchecked ()

+
void
+gst_byte_writer_put_float32_be_unchecked
+                               (GstByteWriter *writer,
+                                gfloat val);
+

Writes a big endian 32 bit float to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_float32_le_unchecked ()

+
void
+gst_byte_writer_put_float32_le_unchecked
+                               (GstByteWriter *writer,
+                                gfloat val);
+

Writes a little endian 32 bit float to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_float64_be_unchecked ()

+
void
+gst_byte_writer_put_float64_be_unchecked
+                               (GstByteWriter *writer,
+                                gdouble val);
+

Writes a big endian 64 bit float to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_float64_le_unchecked ()

+
void
+gst_byte_writer_put_float64_le_unchecked
+                               (GstByteWriter *writer,
+                                gdouble val);
+

Writes a little endian 64 bit float to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

writer

GstByteWriter instance

 

val

Value to write

 
+
+
+
+
+

gst_byte_writer_put_data_unchecked ()

+
void
+gst_byte_writer_put_data_unchecked (GstByteWriter *writer,
+                                    const guint8 *data,
+                                    guint size);
+

Writes size + bytes of data + to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

data

Data to write.

[in][transfer none][array length=size]

size

Size of data +in bytes

 
+
+
+
+
+

gst_byte_writer_fill_unchecked ()

+
void
+gst_byte_writer_fill_unchecked (GstByteWriter *writer,
+                                guint8 value,
+                                guint size);
+

Writes size + bytes containing value + to writer + without +checking if there is enough free space available in the byte writer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

writer

GstByteWriter instance

 

value

Value to be written

 

size

Number of bytes to be written

 
+
+
+
+
+

Types and Values

+
+

GstByteWriter

+
typedef struct {
+  GstByteReader parent;
+
+  guint alloc_size;
+
+  gboolean fixed;
+  gboolean owned;
+} GstByteWriter;
+
+

A byte writer instance.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GstByteReader parent;

GstByteReader parent

 

guint alloc_size;

Allocation size of the data

 

gboolean fixed;

If TRUE no reallocations are allowed

 

gboolean owned;

If FALSE no reallocations are allowed and copies of data are returned

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstCheck.html b/docs/libs/html/gstreamer-libs-GstCheck.html new file mode 100644 index 0000000..8dd25f8 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstCheck.html @@ -0,0 +1,1948 @@ + + + + +GstCheck: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstCheck

+

GstCheck — Common code for GStreamer unit tests

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#define +GST_START_TEST() +
#define +ASSERT_BUFFER_REFCOUNT() +
#define +ASSERT_CAPS_REFCOUNT() +
#define +ASSERT_CRITICAL() +
#define +ASSERT_WARNING() +
#define +ASSERT_MINI_OBJECT_REFCOUNT() +
#define +ASSERT_OBJECT_REFCOUNT() +
#define +ASSERT_OBJECT_REFCOUNT_BETWEEN() +
#define +ASSERT_SET_STATE() +
#define +fail_unless_equals_int() +
#define +fail_unless_equals_float() +
#define +fail_unless_equals_string() +
#define +fail_unless_equals_uint64() +
#define +fail_unless_equals_int64() +
#define +fail_unless_equals_int_hex() +
#define +fail_unless_equals_int64_hex() +
#define +fail_unless_equals_uint64_hex() +
#define +fail_unless_equals_pointer() +
#define +fail_unless_message_error() +
#define +assert_equals_int() +
#define +assert_equals_float() +
#define +assert_equals_string() +
#define +assert_equals_uint64() +
#define +assert_equals_int64() +
#define +assert_equals_int_hex() +
#define +assert_equals_int64_hex() +
#define +assert_equals_uint64_hex() +
#define +assert_equals_pointer() +
#define +assert_message_error() +
+void + +gst_check_init () +
+void + +gst_check_message_error () +
+GstElement * + +gst_check_setup_element () +
+GstPad * + +gst_check_setup_sink_pad () +
+GstPad * + +gst_check_setup_src_pad () +
+GstPad * + +gst_check_setup_sink_pad_by_name () +
+GstPad * + +gst_check_setup_src_pad_by_name () +
+void + +gst_check_teardown_pad_by_name () +
+void + +gst_check_teardown_element () +
+void + +gst_check_teardown_sink_pad () +
+void + +gst_check_teardown_src_pad () +
+void + +gst_check_drop_buffers () +
+void + +gst_check_buffer_data () +
+void + +gst_check_caps_equal () +
+void + +gst_check_element_push_buffer_list () +
+void + +gst_check_element_push_buffer () +
+gint + +gst_check_run_suite () +
+void + +gst_check_setup_events () +
+void + +gst_check_setup_events_with_stream_id () +
+GstPad * + +gst_check_setup_sink_pad_by_name_from_template () +
+GstPad * + +gst_check_setup_sink_pad_from_template () +
+GstPad * + +gst_check_setup_src_pad_by_name_from_template () +
+GstPad * + +gst_check_setup_src_pad_from_template () +
+void + +gst_check_objects_destroyed_on_unref () +
+void + +gst_check_object_destroyed_on_unref () +
+
+
+

Types and Values

+
++++ + + + + +
#defineGST_END_TEST
+
+
+

Includes

+
#include <gst/check/gstcheck.h>
+
+
+
+

Description

+

These macros and functions are for internal use of the unit tests found +inside the 'check' directories of various GStreamer packages.

+

One notable feature is that one can use the environment variables GST_CHECKS +and GST_CHECKS_IGNORE to select which tests to run or skip. Both variables +can contain a comma separated list of test name globs (e.g. test_*).

+
+
+

Functions

+
+

GST_START_TEST()

+
#define             GST_START_TEST(__testname)
+

wrapper for checks START_TEST

+
+

Parameters

+
+++++ + + + + + +

__testname

test function name

 
+
+
+
+
+

ASSERT_BUFFER_REFCOUNT()

+
#define             ASSERT_BUFFER_REFCOUNT(buffer, name, value)
+
+
+
+

ASSERT_CAPS_REFCOUNT()

+
#define             ASSERT_CAPS_REFCOUNT(caps, name, value)
+
+
+
+

ASSERT_CRITICAL()

+
#define             ASSERT_CRITICAL(code)
+
+
+
+

ASSERT_WARNING()

+
#define             ASSERT_WARNING(code)
+
+
+
+

ASSERT_MINI_OBJECT_REFCOUNT()

+
#define             ASSERT_MINI_OBJECT_REFCOUNT(miniobj, name, value)
+
+
+
+

ASSERT_OBJECT_REFCOUNT()

+
#define             ASSERT_OBJECT_REFCOUNT(object, name, value)
+
+
+
+

ASSERT_OBJECT_REFCOUNT_BETWEEN()

+
#define             ASSERT_OBJECT_REFCOUNT_BETWEEN(object, name, lower, upper)
+
+
+
+

ASSERT_SET_STATE()

+
#define             ASSERT_SET_STATE(element, state, ret)
+
+
+
+

fail_unless_equals_int()

+
#define             fail_unless_equals_int(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint value or expression

 

b

a gint value or expression

 
+
+
+
+
+

fail_unless_equals_float()

+
#define             fail_unless_equals_float(a, b)
+

This macro checks that a + and b + are (almost) equal and aborts if this +is not the case, printing both expressions and the values they evaluated +to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gdouble or gfloat value or expression

 

b

a gdouble or gfloat value or expression

 
+
+
+
+
+

fail_unless_equals_string()

+
#define             fail_unless_equals_string(a, b)
+

This macro checks that a + and b + are equal (as per strcmp) and aborts if +this is not the case, printing both expressions and the values they +evaluated to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a string literal or expression

 

b

a string literal or expression

 
+
+
+
+
+

fail_unless_equals_uint64()

+
#define             fail_unless_equals_uint64(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a guint64 value or expression

 

b

a guint64 value or expression

 
+
+
+
+
+

fail_unless_equals_int64()

+
#define             fail_unless_equals_int64(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint64 value or expression

 

b

a gint64 value or expression

 
+
+
+
+
+

fail_unless_equals_int_hex()

+
#define             fail_unless_equals_int_hex(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint value or expression

 

b

a gint value or expression

 
+
+

Since: 1.2

+
+
+
+

fail_unless_equals_int64_hex()

+
#define             fail_unless_equals_int64_hex(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint64 value or expression

 

b

a gint64 value or expression

 
+
+

Since: 1.2

+
+
+
+

fail_unless_equals_uint64_hex()

+
#define             fail_unless_equals_uint64_hex(a, b)
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint64 value or expression

 

b

a gint64 value or expression

 
+
+

Since: 1.2

+
+
+
+

fail_unless_equals_pointer()

+
#define             fail_unless_equals_pointer(a, b)
+

This macro checks that a + and b + are equal and aborts if this +is not the case, printing both expressions and the values they +evaluated to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a pointer value or expression

 

b

a pointer value or expression

 
+
+

Since: 1.2

+
+
+
+

fail_unless_message_error()

+
#define             fail_unless_message_error(msg, domain, code)
+
+
+
+

assert_equals_int()

+
#define assert_equals_int(a, b) fail_unless_equals_int(a, b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint value or expression

 

b

a gint value or expression

 
+
+
+
+
+

assert_equals_float()

+
#define assert_equals_float(a, b) fail_unless_equals_float(a, b)
+
+

This macro checks that a + and b + are (almost) equal and aborts if this +is not the case, printing both expressions and the values they evaluated +to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gdouble or gfloat value or expression

 

b

a gdouble or gfloat value or expression

 
+
+
+
+
+

assert_equals_string()

+
#define assert_equals_string(a, b) fail_unless_equals_string(a, b)
+
+

This macro checks that a + and b + are equal (as per strcmp) and aborts if +this is not the case, printing both expressions and the values they +evaluated to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a string literal or expression

 

b

a string literal or expression

 
+
+
+
+
+

assert_equals_uint64()

+
#define assert_equals_uint64(a, b) fail_unless_equals_uint64(a, b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a guint64 value or expression

 

b

a guint64 value or expression

 
+
+
+
+
+

assert_equals_int64()

+
#define assert_equals_int64(a, b) fail_unless_equals_int64(a, b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to. This +macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint64 value or expression

 

b

a gint64 value or expression

 
+
+
+
+
+

assert_equals_int_hex()

+
#define assert_equals_int_hex(a, b) fail_unless_equals_int_hex(a, b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint value or expression

 

b

a gint value or expression

 
+
+

Since: 1.2

+
+
+
+

assert_equals_int64_hex()

+
#define assert_equals_int64_hex(a,b) fail_unless_equals_int64_hex(a,b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a gint64 value or expression

 

b

a gint64 value or expression

 
+
+

Since: 1.2

+
+
+
+

assert_equals_uint64_hex()

+
#define assert_equals_uint64_hex(a,b) fail_unless_equals_uint64_hex(a,b)
+
+

This macro checks that a + and b + are equal and aborts if this is not the +case, printing both expressions and the values they evaluated to in +hexadecimal format. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a guint64 value or expression

 

b

a guint64 value or expression

 
+
+

Since: 1.2

+
+
+
+

assert_equals_pointer()

+
#define assert_equals_pointer(a, b) fail_unless_equals_pointer(a, b)
+
+

This macro checks that a + and b + are equal and aborts if this +is not the case, printing both expressions and the values they +evaluated to. This macro is for use in unit tests.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

a

a pointer value or expression

 

b

a pointer value or expression

 
+
+

Since: 1.2

+
+
+
+

assert_message_error()

+
#define assert_message_error(m, d, c) fail_unless_message_error(m, d, c)
+
+
+
+
+

gst_check_init ()

+
void
+gst_check_init (int *argc,
+                char **argv[]);
+
+
+
+

gst_check_message_error ()

+
void
+gst_check_message_error (GstMessage *message,
+                         GstMessageType type,
+                         GQuark domain,
+                         gint code);
+
+
+
+

gst_check_setup_element ()

+
GstElement *
+gst_check_setup_element (const gchar *factory);
+

setup an element for a filter test with mysrcpad and mysinkpad

+
+

Parameters

+
+++++ + + + + + +

factory

factory

 
+
+
+

Returns

+

a new element.

+

[transfer full]

+
+
+
+
+

gst_check_setup_sink_pad ()

+
GstPad *
+gst_check_setup_sink_pad (GstElement *element,
+                          GstStaticPadTemplate *tmpl);
+

Does the same as gst_check_setup_sink_pad_by_name with the name parameter equal to "src".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 
+
+
+

Returns

+

a new pad that can be used to check the output of element +.

+

[transfer full]

+
+
+
+
+

gst_check_setup_src_pad ()

+
GstPad *
+gst_check_setup_src_pad (GstElement *element,
+                         GstStaticPadTemplate *tmpl);
+

Does the same as gst_check_setup_src_pad_by_name with the name parameter equal to "sink".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 
+
+
+

Returns

+

A new pad that can be used to inject data on element +.

+

[transfer full]

+
+
+
+
+

gst_check_setup_sink_pad_by_name ()

+
GstPad *
+gst_check_setup_sink_pad_by_name (GstElement *element,
+                                  GstStaticPadTemplate *tmpl,
+                                  const gchar *name);
+

Creates a new sink pad (based on the given tmpl +) and links it to the given element + src pad +(the pad that matches the given name +). +You can set event/chain/query functions on this pad to check the output of the element +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 

name

Name of the element +src pad that will be linked to the sink pad that will be setup

 
+
+
+

Returns

+

a new pad that can be used to check the output of element +.

+

[transfer full]

+
+
+
+
+

gst_check_setup_src_pad_by_name ()

+
GstPad *
+gst_check_setup_src_pad_by_name (GstElement *element,
+                                 GstStaticPadTemplate *tmpl,
+                                 const gchar *name);
+

Creates a new src pad (based on the given tmpl +) and links it to the given element + sink pad (the pad that matches the given name +). +Before using the src pad to push data on element + you need to call gst_check_setup_events on the created src pad.

+

Example of how to push a buffer on element +:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+GST_PAD_SINK,
+GST_PAD_ALWAYS,
+GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING)
+);
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+GST_PAD_SRC,
+GST_PAD_ALWAYS,
+GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING)
+);
+
+GstElement * element = gst_check_setup_element ("element");
+GstPad * mysrcpad = gst_check_setup_src_pad (element, &srctemplate);
+GstPad * mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate);
+
+gst_pad_set_active (mysrcpad, TRUE);
+gst_pad_set_active (mysinkpad, TRUE);
+fail_unless (gst_element_set_state (element, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing");
+
+GstCaps * caps = gst_caps_from_string (YOUR_DESIRED_SINK_CAPS);
+gst_check_setup_events (mysrcpad, element, caps, GST_FORMAT_TIME);
+gst_caps_unref (caps);
+
+fail_unless (gst_pad_push (mysrcpad, gst_buffer_new_and_alloc(2)) == GST_FLOW_OK);
+
+ +

+

For very simple input/output test scenarios checkout gst_check_element_push_buffer_list and gst_check_element_push_buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

element to setup src pad on

 

tmpl

pad template

 

name

Name of the element +sink pad that will be linked to the src pad that will be setup

 
+
+
+

Returns

+

A new pad that can be used to inject data on element +.

+

[transfer full]

+
+
+
+
+

gst_check_teardown_pad_by_name ()

+
void
+gst_check_teardown_pad_by_name (GstElement *element,
+                                const gchar *name);
+
+
+
+

gst_check_teardown_element ()

+
void
+gst_check_teardown_element (GstElement *element);
+
+
+
+

gst_check_teardown_sink_pad ()

+
void
+gst_check_teardown_sink_pad (GstElement *element);
+
+
+
+

gst_check_teardown_src_pad ()

+
void
+gst_check_teardown_src_pad (GstElement *element);
+
+
+
+

gst_check_drop_buffers ()

+
void
+gst_check_drop_buffers (void);
+

Unref and remove all buffers that are in the global buffers + GList, +emptying the list.

+
+
+
+

gst_check_buffer_data ()

+
void
+gst_check_buffer_data (GstBuffer *buffer,
+                       gconstpointer data,
+                       gsize size);
+

Compare the buffer contents with data + and size +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

buffer

buffer to compare

 

data

data to compare to

 

size

size of data to compare

 
+
+
+
+
+

gst_check_caps_equal ()

+
void
+gst_check_caps_equal (GstCaps *caps1,
+                      GstCaps *caps2);
+

Compare two caps with gst_caps_is_equal and fail unless they are +equal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

caps1

first caps to compare

 

caps2

second caps to compare

 
+
+
+
+
+

gst_check_element_push_buffer_list ()

+
void
+gst_check_element_push_buffer_list (const gchar *element_name,
+                                    GList *buffer_in,
+                                    GstCaps *caps_in,
+                                    GList *buffer_out,
+                                    GstCaps *caps_out,
+                                    GstFlowReturn last_flow_return);
+

Create an element using the factory providing the element_name + and push the +buffers in buffer_in + to this element. The element should create the buffers +equal to the buffers in buffer_out +. We only check the size and the data of +the buffers. This function unrefs the buffers in the two lists. +The last_flow_return parameter indicates the expected flow return value from +pushing the final buffer in the list. +This can be used to set up a test which pushes some buffers and then an +invalid buffer, when the final buffer is expected to fail, for example.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element_name

name of the element that needs to be created

 

buffer_in

a list of buffers that needs to be +pushed to the element.

[element-type GstBuffer][transfer full]

caps_in

the GstCaps expected of the sinkpad of the element

 

buffer_out

a list of buffers that we expect from +the element.

[element-type GstBuffer][transfer full]

caps_out

the GstCaps expected of the srcpad of the element

 

last_flow_return

the last buffer push needs to give this GstFlowReturn

 
+
+
+
+
+

gst_check_element_push_buffer ()

+
void
+gst_check_element_push_buffer (const gchar *element_name,
+                               GstBuffer *buffer_in,
+                               GstCaps *caps_in,
+                               GstBuffer *buffer_out,
+                               GstCaps *caps_out);
+

Create an element using the factory providing the element_name + and +push the buffer_in + to this element. The element should create one buffer +and this will be compared with buffer_out +. We only check the caps +and the data of the buffers. This function unrefs the buffers.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element_name

name of the element that needs to be created

 

buffer_in

push this buffer to the element

 

caps_in

the GstCaps expected of the sinkpad of the element

 

buffer_out

compare the result with this buffer

 

caps_out

the GstCaps expected of the srcpad of the element

 
+
+
+
+
+

gst_check_run_suite ()

+
gint
+gst_check_run_suite (Suite *suite,
+                     const gchar *name,
+                     const gchar *fname);
+
+
+
+

gst_check_setup_events ()

+
void
+gst_check_setup_events (GstPad *srcpad,
+                        GstElement *element,
+                        GstCaps *caps,
+                        GstFormat format);
+

Push stream-start, caps and segment event, which consist of the minimum +required events to allow streaming. Caps is optional to allow raw src +testing. If element + has more than one src or sink pad, use +gst_check_setup_events_with_stream_id() instead.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

srcpad

The src GstPad to push on

 

element

The GstElement use to create the stream id

 

caps

GstCaps in case caps event must be sent.

[allow-none]

format

The GstFormat of the default segment to send

 
+
+
+
+
+

gst_check_setup_events_with_stream_id ()

+
void
+gst_check_setup_events_with_stream_id (GstPad *srcpad,
+                                       GstElement *element,
+                                       GstCaps *caps,
+                                       GstFormat format,
+                                       const gchar *stream_id);
+

Push stream-start, caps and segment event, which consist of the minimum +required events to allow streaming. Caps is optional to allow raw src +testing.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

srcpad

The src GstPad to push on

 

element

The GstElement use to create the stream id

 

caps

GstCaps in case caps event must be sent.

[allow-none]

format

The GstFormat of the default segment to send

 

stream_id

A unique identifier for the stream

 
+
+
+
+
+

gst_check_setup_sink_pad_by_name_from_template ()

+
GstPad *
+gst_check_setup_sink_pad_by_name_from_template
+                               (GstElement *element,
+                                GstPadTemplate *tmpl,
+                                const gchar *name);
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 

name

name

 
+
+
+

Returns

+

a new pad.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_check_setup_sink_pad_from_template ()

+
GstPad *
+gst_check_setup_sink_pad_from_template
+                               (GstElement *element,
+                                GstPadTemplate *tmpl);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 
+
+
+

Returns

+

a new pad.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_check_setup_src_pad_by_name_from_template ()

+
GstPad *
+gst_check_setup_src_pad_by_name_from_template
+                               (GstElement *element,
+                                GstPadTemplate *tmpl,
+                                const gchar *name);
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 

name

name

 
+
+
+

Returns

+

a new pad.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_check_setup_src_pad_from_template ()

+
GstPad *
+gst_check_setup_src_pad_from_template (GstElement *element,
+                                       GstPadTemplate *tmpl);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

element

element to setup pad on

 

tmpl

pad template

 
+
+
+

Returns

+

a new pad.

+

[transfer full]

+
+

Since: 1.4

+
+
+
+

gst_check_objects_destroyed_on_unref ()

+
void
+gst_check_objects_destroyed_on_unref (gpointer object_to_unref,
+                                      gpointer first_object,
+                                      ...);
+

Unrefs object_to_unref + and checks that is has properly been +destroyed, also checks that the other objects passed in +parametter have been destroyed as a concequence of +unrefing object_to_unref +. Last variable argument should be NULL.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

object_to_unref

The GObject to unref

 

first_object

The first object that should be destroyed as a +concequence of unrefing object_to_unref +.

[allow-none]

...

Additional object that should have been destroyed.

 
+
+

Since: 1.6

+
+
+
+

gst_check_object_destroyed_on_unref ()

+
void
+gst_check_object_destroyed_on_unref (gpointer object_to_unref);
+

Unrefs object_to_unref + and checks that is has properly been +destroyed.

+
+

Parameters

+
+++++ + + + + + +

object_to_unref

The GObject to unref

 
+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GST_END_TEST

+
#define             GST_END_TEST
+

wrapper for checks END_TEST

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstDataQueue.html b/docs/libs/html/gstreamer-libs-GstDataQueue.html new file mode 100644 index 0000000..7b87bcb --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstDataQueue.html @@ -0,0 +1,867 @@ + + + + +GstDataQueue: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstDataQueue

+

GstDataQueue — Threadsafe queueing object

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+gboolean + +(*GstDataQueueCheckFullFunction) () +
+void + +(*GstDataQueueEmptyCallback) () +
+void + +(*GstDataQueueFullCallback) () +
+GstDataQueue * + +gst_data_queue_new () +
+gboolean + +gst_data_queue_push () +
+gboolean + +gst_data_queue_push_force () +
+gboolean + +gst_data_queue_pop () +
+gboolean + +gst_data_queue_peek () +
+void + +gst_data_queue_flush () +
+void + +gst_data_queue_set_flushing () +
+gboolean + +gst_data_queue_drop_head () +
+gboolean + +gst_data_queue_is_full () +
+gboolean + +gst_data_queue_is_empty () +
+void + +gst_data_queue_get_level () +
+void + +gst_data_queue_limits_changed () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structGstDataQueue
structGstDataQueueSize
structGstDataQueueItem
+
+
+

Includes

+
#include <gst/base/gstdataqueue.h>
+
+
+
+

Description

+

GstDataQueue is an object that handles threadsafe queueing of objects. It +also provides size-related functionality. This object should be used for +any GstElement that wishes to provide some sort of queueing functionality.

+
+
+

Functions

+
+

GstDataQueueCheckFullFunction ()

+
gboolean
+(*GstDataQueueCheckFullFunction) (GstDataQueue *queue,
+                                  guint visible,
+                                  guint bytes,
+                                  guint64 time,
+                                  gpointer checkdata);
+

The prototype of the function used to inform the queue that it should be +considered as full.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

queue

a GstDataQueue.

 

visible

The number of visible items currently in the queue.

 

bytes

The amount of bytes currently in the queue.

 

time

The accumulated duration of the items currently in the queue.

 

checkdata

The gpointer registered when the GstDataQueue was created.

 
+
+
+

Returns

+

TRUE if the queue should be considered full.

+
+
+
+
+

GstDataQueueEmptyCallback ()

+
void
+(*GstDataQueueEmptyCallback) (GstDataQueue *queue,
+                              gpointer checkdata);
+
+
+
+

GstDataQueueFullCallback ()

+
void
+(*GstDataQueueFullCallback) (GstDataQueue *queue,
+                             gpointer checkdata);
+
+
+
+

gst_data_queue_new ()

+
GstDataQueue *
+gst_data_queue_new (GstDataQueueCheckFullFunction checkfull,
+                    GstDataQueueFullCallback fullcallback,
+                    GstDataQueueEmptyCallback emptycallback,
+                    gpointer checkdata);
+

Creates a new GstDataQueue. If fullcallback + or emptycallback + are supplied, then +the GstDataQueue will call the respective callback to signal full or empty condition. +If the callbacks are NULL the GstDataQueue will instead emit 'full' and 'empty' +signals.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

checkfull

the callback used to tell if the element considers the queue full +or not.

 

fullcallback

the callback which will be called when the queue is considered full.

 

emptycallback

the callback which will be called when the queue is considered empty.

 

checkdata

a gpointer that will be passed to the checkfull +, fullcallback +, +and emptycallback +callbacks.

 
+
+
+

Returns

+

a new GstDataQueue.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_push ()

+
gboolean
+gst_data_queue_push (GstDataQueue *queue,
+                     GstDataQueueItem *item);
+

Pushes a GstDataQueueItem (or a structure that begins with the same fields) +on the queue +. If the queue + is full, the call will block until space is +available, OR the queue + is set to flushing state. +MT safe.

+

Note that this function has slightly different semantics than gst_pad_push() +and gst_pad_push_event(): this function only takes ownership of item + and +the GstMiniObject contained in item + if the push was successful. If FALSE +is returned, the caller is responsible for freeing item + and its contents.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstDataQueue.

 

item

a GstDataQueueItem.

 
+
+
+

Returns

+

TRUE if the item +was successfully pushed on the queue +.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_push_force ()

+
gboolean
+gst_data_queue_push_force (GstDataQueue *queue,
+                           GstDataQueueItem *item);
+

Pushes a GstDataQueueItem (or a structure that begins with the same fields) +on the queue +. It ignores if the queue + is full or not and forces the item + +to be pushed anyway. +MT safe.

+

Note that this function has slightly different semantics than gst_pad_push() +and gst_pad_push_event(): this function only takes ownership of item + and +the GstMiniObject contained in item + if the push was successful. If FALSE +is returned, the caller is responsible for freeing item + and its contents.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstDataQueue.

 

item

a GstDataQueueItem.

 
+
+
+

Returns

+

TRUE if the item +was successfully pushed on the queue +.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_pop ()

+
gboolean
+gst_data_queue_pop (GstDataQueue *queue,
+                    GstDataQueueItem **item);
+

Retrieves the first item + available on the queue +. If the queue is currently +empty, the call will block until at least one item is available, OR the +queue + is set to the flushing state. +MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstDataQueue.

 

item

pointer to store the returned GstDataQueueItem.

 
+
+
+

Returns

+

TRUE if an item +was successfully retrieved from the queue +.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_peek ()

+
gboolean
+gst_data_queue_peek (GstDataQueue *queue,
+                     GstDataQueueItem **item);
+

Retrieves the first item + available on the queue + without removing it. +If the queue is currently empty, the call will block until at least +one item is available, OR the queue + is set to the flushing state. +MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstDataQueue.

 

item

pointer to store the returned GstDataQueueItem.

 
+
+
+

Returns

+

TRUE if an item +was successfully retrieved from the queue +.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_flush ()

+
void
+gst_data_queue_flush (GstDataQueue *queue);
+

Flushes all the contents of the queue +. Any call to gst_data_queue_push and +gst_data_queue_pop will be released. +MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

queue

a GstDataQueue.

 
+
+

Since: 1.2

+
+
+
+

gst_data_queue_set_flushing ()

+
void
+gst_data_queue_set_flushing (GstDataQueue *queue,
+                             gboolean flushing);
+

Sets the queue to flushing state if flushing + is TRUE. If set to flushing +state, any incoming data on the queue + will be discarded. Any call currently +blocking on gst_data_queue_push or gst_data_queue_pop will return straight +away with a return value of FALSE. While the queue + is in flushing state, +all calls to those two functions will return FALSE.

+

MT Safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

a GstDataQueue.

 

flushing

a gboolean stating if the queue will be flushing or not.

 
+
+

Since: 1.2

+
+
+
+

gst_data_queue_drop_head ()

+
gboolean
+gst_data_queue_drop_head (GstDataQueue *queue,
+                          GType type);
+

Pop and unref the head-most GstMiniObject with the given GType.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

The GstDataQueue to drop an item from.

 

type

The GType of the item to drop.

 
+
+
+

Returns

+

TRUE if an element was removed.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_is_full ()

+
gboolean
+gst_data_queue_is_full (GstDataQueue *queue);
+

Queries if queue + is full. This check will be done using the +GstDataQueueCheckFullFunction registered with queue +. +MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

queue

a GstDataQueue.

 
+
+
+

Returns

+

TRUE if queue +is full.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_is_empty ()

+
gboolean
+gst_data_queue_is_empty (GstDataQueue *queue);
+

Queries if there are any items in the queue +. +MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

queue

a GstDataQueue.

 
+
+
+

Returns

+

TRUE if queue +is empty.

+
+

Since: 1.2

+
+
+
+

gst_data_queue_get_level ()

+
void
+gst_data_queue_get_level (GstDataQueue *queue,
+                          GstDataQueueSize *level);
+

Get the current level of the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

The GstDataQueue

 

level

the location to store the result

 
+
+

Since: 1.2

+
+
+
+

gst_data_queue_limits_changed ()

+
void
+gst_data_queue_limits_changed (GstDataQueue *queue);
+

Inform the queue that the limits for the fullness check have changed and that +any blocking gst_data_queue_push() should be unblocked to recheck the limits.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

queue

The GstDataQueue

 
+
+

Since: 1.2

+
+
+
+

Types and Values

+
+

struct GstDataQueue

+
struct GstDataQueue {
+  GObject object;
+};
+
+

Opaque GstDataQueue structure.

+
+

Members

+
+++++ + + + + + +

GObject object;

the parent structure

 
+
+
+
+
+

struct GstDataQueueSize

+
struct GstDataQueueSize {
+  guint visible;
+  guint bytes;
+  guint64 time;
+};
+
+

Structure describing the size of a queue.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

guint visible;

number of buffers

 

guint bytes;

number of bytes

 

guint64 time;

amount of time

 
+
+
+
+
+

struct GstDataQueueItem

+
struct GstDataQueueItem {
+  GstMiniObject *object;
+  guint size;
+  guint64 duration;
+  gboolean visible;
+
+  /* user supplied destroy function */
+  GDestroyNotify destroy;
+};
+
+

Structure used by GstDataQueue. You can supply a different structure, as +long as the top of the structure is identical to this structure.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstMiniObject *object;

the GstMiniObject to queue.

 

guint size;

the size in bytes of the miniobject.

 

guint64 duration;

the duration in GstClockTime of the miniobject. Can not be +GST_CLOCK_TIME_NONE.

 

gboolean visible;

TRUE if object +should be considered as a visible object.

 

GDestroyNotify destroy;

The GDestroyNotify function to use to free the GstDataQueueItem. +This function should also drop the reference to object +the owner of the +GstDataQueueItem is assumed to hold.

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstFlowCombiner.html b/docs/libs/html/gstreamer-libs-GstFlowCombiner.html new file mode 100644 index 0000000..c48fb18 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstFlowCombiner.html @@ -0,0 +1,464 @@ + + + + +GstFlowCombiner: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstFlowCombiner

+

GstFlowCombiner — Utility to combine multiple flow returns into one

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstFlowCombiner * + +gst_flow_combiner_new () +
+void + +gst_flow_combiner_free () +
+GstFlowCombiner * + +gst_flow_combiner_ref () +
+void + +gst_flow_combiner_unref () +
+GstFlowReturn + +gst_flow_combiner_update_flow () +
+void + +gst_flow_combiner_add_pad () +
+void + +gst_flow_combiner_remove_pad () +
+void + +gst_flow_combiner_clear () +
+void + +gst_flow_combiner_reset () +
+GstFlowReturn + +gst_flow_combiner_update_pad_flow () +
+
+
+

Types and Values

+
++++ + + + + +
 GstFlowCombiner
+
+
+

Includes

+
#include <gst/base/gstflowcombiner.h>
+
+
+
+

Description

+

Utility struct to help handling GstFlowReturn combination. Useful for +GstElements that have multiple source pads and need to combine +the different GstFlowReturn for those pads.

+

GstFlowCombiner works by using the last GstFlowReturn for all GstPad +it has in its list and computes the combined return value and provides +it to the caller.

+

To add a new pad to the GstFlowCombiner use gst_flow_combiner_add_pad(). +The new GstPad is stored with a default value of GST_FLOW_OK.

+

In case you want a GstPad to be removed, use gst_flow_combiner_remove_pad().

+

Please be aware that this struct isn't thread safe as its designed to be + used by demuxers, those usually will have a single thread operating it.

+

These functions will take refs on the passed GstPads.

+

Aside from reducing the user's code size, the main advantage of using this +helper struct is to follow the standard rules for GstFlowReturn combination. +These rules are:

+
+

GST_FLOW_ERROR or below, GST_FLOW_NOT_NEGOTIATED and GST_FLOW_FLUSHING are +returned immediatelly from the gst_flow_combiner_update_flow() function.

+
+
+

Functions

+
+

gst_flow_combiner_new ()

+
GstFlowCombiner *
+gst_flow_combiner_new (void);
+

Creates a new GstFlowCombiner, use gst_flow_combiner_free() to free it.

+
+

Returns

+

A new GstFlowCombiner

+
+

Since: 1.4

+
+
+
+

gst_flow_combiner_free ()

+
void
+gst_flow_combiner_free (GstFlowCombiner *combiner);
+

Frees a GstFlowCombiner struct and all its internal data.

+
+

Parameters

+
+++++ + + + + + +

combiner

the GstFlowCombiner to free

 
+
+

Since: 1.4

+
+
+
+

gst_flow_combiner_ref ()

+
GstFlowCombiner *
+gst_flow_combiner_ref (GstFlowCombiner *combiner);
+

Increments the reference count on the GstFlowCombiner.

+
+

Parameters

+
+++++ + + + + + +

combiner

the GstFlowCombiner to add a reference to.

 
+
+
+

Returns

+

the GstFlowCombiner.

+
+

Since: 1.12.1

+
+
+
+

gst_flow_combiner_unref ()

+
void
+gst_flow_combiner_unref (GstFlowCombiner *combiner);
+

Decrements the reference count on the GstFlowCombiner.

+
+

Parameters

+
+++++ + + + + + +

combiner

the GstFlowCombiner to unreference.

 
+
+

Since: 1.12.1

+
+
+
+

gst_flow_combiner_update_flow ()

+
GstFlowReturn
+gst_flow_combiner_update_flow (GstFlowCombiner *combiner,
+                               GstFlowReturn fret);
+

Computes the combined flow return for the pads in it.

+

The GstFlowReturn parameter should be the last flow return update for a pad +in this GstFlowCombiner. It will use this value to be able to shortcut some +combinations and avoid looking over all pads again. e.g. The last combined +return is the same as the latest obtained GstFlowReturn.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

combiner

the GstFlowCombiner

 

fret

the latest GstFlowReturn received for a pad in this GstFlowCombiner

 
+
+
+

Returns

+

The combined GstFlowReturn

+
+

Since: 1.4

+
+
+
+

gst_flow_combiner_add_pad ()

+
void
+gst_flow_combiner_add_pad (GstFlowCombiner *combiner,
+                           GstPad *pad);
+

Adds a new GstPad to the GstFlowCombiner.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

combiner

the GstFlowCombiner

 

pad

the GstPad that is being added.

[transfer none]
+
+

Since: 1.4

+
+
+
+

gst_flow_combiner_remove_pad ()

+
void
+gst_flow_combiner_remove_pad (GstFlowCombiner *combiner,
+                              GstPad *pad);
+

Removes a GstPad from the GstFlowCombiner.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

combiner

the GstFlowCombiner

 

pad

the GstPad to remove.

[transfer none]
+
+

Since: 1.4

+
+
+
+

gst_flow_combiner_clear ()

+
void
+gst_flow_combiner_clear (GstFlowCombiner *combiner);
+

Removes all pads from a GstFlowCombiner and resets it to its initial state.

+
+

Parameters

+
+++++ + + + + + +

combiner

the GstFlowCombiner to clear

 
+
+

Since: 1.6

+
+
+
+

gst_flow_combiner_reset ()

+
void
+gst_flow_combiner_reset (GstFlowCombiner *combiner);
+

Reset flow combiner and all pads to their initial state without removing pads.

+
+

Parameters

+
+++++ + + + + + +

combiner

the GstFlowCombiner to clear

 
+
+

Since: 1.6

+
+
+
+

gst_flow_combiner_update_pad_flow ()

+
GstFlowReturn
+gst_flow_combiner_update_pad_flow (GstFlowCombiner *combiner,
+                                   GstPad *pad,
+                                   GstFlowReturn fret);
+

Sets the provided pad's last flow return to provided value and computes +the combined flow return for the pads in it.

+

The GstFlowReturn parameter should be the last flow return update for a pad +in this GstFlowCombiner. It will use this value to be able to shortcut some +combinations and avoid looking over all pads again. e.g. The last combined +return is the same as the latest obtained GstFlowReturn.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

combiner

the GstFlowCombiner

 

pad

the GstPad whose GstFlowReturn to update

 

fret

the latest GstFlowReturn received for a pad in this GstFlowCombiner

 
+
+
+

Returns

+

The combined GstFlowReturn

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GstFlowCombiner

+
typedef struct _GstFlowCombiner GstFlowCombiner;
+

Opaque helper structure to aggregate flow returns.

+

Since: 1.4

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstHarness.html b/docs/libs/html/gstreamer-libs-GstHarness.html new file mode 100644 index 0000000..95c9ad5 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstHarness.html @@ -0,0 +1,4247 @@ + + + + +GstHarness: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstHarness

+

GstHarness — A test-harness for writing GStreamer unit tests

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstHarness * + +gst_harness_new_empty () +
+GstHarness * + +gst_harness_new_full () +
+GstHarness * + +gst_harness_new_with_element () +
+GstHarness * + +gst_harness_new_with_padnames () +
+GstHarness * + +gst_harness_new_with_templates () +
+GstHarness * + +gst_harness_new () +
+GstHarness * + +gst_harness_new_parse () +
+void + +gst_harness_add_element_full () +
+void + +gst_harness_add_parse () +
+void + +gst_harness_teardown () +
+void + +gst_harness_add_element_src_pad () +
+void + +gst_harness_add_element_sink_pad () +
+void + +gst_harness_set_src_caps () +
+void + +gst_harness_set_sink_caps () +
+void + +gst_harness_set_caps () +
+void + +gst_harness_set_src_caps_str () +
+void + +gst_harness_set_sink_caps_str () +
+void + +gst_harness_set_caps_str () +
+void + +gst_harness_use_systemclock () +
+void + +gst_harness_use_testclock () +
+GstTestClock * + +gst_harness_get_testclock () +
+gboolean + +gst_harness_set_time () +
+gboolean + +gst_harness_wait_for_clock_id_waits () +
+gboolean + +gst_harness_crank_single_clock_wait () +
+gboolean + +gst_harness_crank_multiple_clock_waits () +
+void + +gst_harness_play () +
+void + +gst_harness_set_blocking_push_mode () +
+void + +gst_harness_set_forwarding () +
+GstBuffer * + +gst_harness_create_buffer () +
+GstFlowReturn + +gst_harness_push () +
+GstBuffer * + +gst_harness_pull () +
+GstBuffer * + +gst_harness_try_pull () +
+GstBuffer * + +gst_harness_push_and_pull () +
+guint + +gst_harness_buffers_received () +
+guint + +gst_harness_buffers_in_queue () +
+void + +gst_harness_set_drop_buffers () +
+void + +gst_harness_dump_to_file () +
+guint8 * + +gst_harness_take_all_data () +
+GstBuffer * + +gst_harness_take_all_data_as_buffer () +
+GBytes * + +gst_harness_take_all_data_as_bytes () +
+GstClockTime + +gst_harness_get_last_pushed_timestamp () +
+gboolean + +gst_harness_push_event () +
+GstEvent * + +gst_harness_pull_event () +
+GstEvent * + +gst_harness_try_pull_event () +
+guint + +gst_harness_events_received () +
+guint + +gst_harness_events_in_queue () +
+gboolean + +gst_harness_push_upstream_event () +
+GstEvent * + +gst_harness_pull_upstream_event () +
+GstEvent * + +gst_harness_try_pull_upstream_event () +
+guint + +gst_harness_upstream_events_received () +
+guint + +gst_harness_upstream_events_in_queue () +
+GstClockTime + +gst_harness_query_latency () +
+void + +gst_harness_set_upstream_latency () +
+void + +gst_harness_set_propose_allocator () +
+void + +gst_harness_get_allocator () +
+void + +gst_harness_add_src () +
+void + +gst_harness_add_src_harness () +
+void + +gst_harness_add_src_parse () +
+GstFlowReturn + +gst_harness_push_from_src () +
+GstFlowReturn + +gst_harness_src_crank_and_push_many () +
+gboolean + +gst_harness_src_push_event () +
+void + +gst_harness_add_sink () +
+void + +gst_harness_add_sink_harness () +
+void + +gst_harness_add_sink_parse () +
+GstFlowReturn + +gst_harness_push_to_sink () +
+GstFlowReturn + +gst_harness_sink_push_many () +
+GstElement * + +gst_harness_find_element () +
+void + +gst_harness_set () +
+void + +gst_harness_get () +
+void + +gst_harness_add_probe () +
+guint + +gst_harness_stress_thread_stop () +
+GstHarnessThread * + +gst_harness_stress_custom_start () +
#define +gst_harness_stress_statechange_start() +
+GstHarnessThread * + +gst_harness_stress_statechange_start_full () +
#define +gst_harness_stress_push_buffer_start() +
+GstHarnessThread * + +gst_harness_stress_push_buffer_start_full () +
+GstBuffer * + +(*GstHarnessPrepareBufferFunc) () +
#define +gst_harness_stress_push_buffer_with_cb_start() +
+GstHarnessThread * + +gst_harness_stress_push_buffer_with_cb_start_full () +
#define +gst_harness_stress_push_event_start() +
+GstHarnessThread * + +gst_harness_stress_push_event_start_full () +
+GstEvent * + +(*GstHarnessPrepareEventFunc) () +
#define +gst_harness_stress_push_event_with_cb_start() +
+GstHarnessThread * + +gst_harness_stress_push_event_with_cb_start_full () +
#define +gst_harness_stress_send_upstream_event_start() +
+GstHarnessThread * + +gst_harness_stress_push_upstream_event_start_full () +
#define +gst_harness_stress_send_upstream_event_with_cb_start() +
+GstHarnessThread * + +gst_harness_stress_push_upstream_event_with_cb_start_full () +
#define +gst_harness_stress_property_start() +
+GstHarnessThread * + +gst_harness_stress_property_start_full () +
#define +gst_harness_stress_requestpad_start() +
+GstHarnessThread * + +gst_harness_stress_requestpad_start_full () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstHarness
 GstHarnessThread
+
+
+

Includes

+
#include <gst/check/check.h>
+
+
+
+

Description

+

GstHarness is meant to make writing unit test for GStreamer much easier. +It can be thought of as a way of treating a GstElement as a black box, +deterministically feeding it data, and controlling what data it outputs.

+

The basic structure of GstHarness is two "floating" GstPads that connect +to the harnessed GstElement src and sink GstPads like so:

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
__________________________
+ _____   |  _____            _____  |   _____
+|     |  | |     |          |     | |  |     |
+| src |--+-| sink|  Element | src |-+--| sink|
+|_____|  | |_____|          |_____| |  |_____|
+         |__________________________|
+
+ +

+

With this, you can now simulate any environment the GstElement might find +itself in. By specifying the GstCaps of the harness GstPads, using +functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(), +you can test how the GstElement interacts with different caps sets.

+

Your harnessed GstElement can of course also be a bin, and using +gst_harness_new_parse() supporting standard gst-launch syntax, you can +easily test a whole pipeline instead of just one element.

+

You can then go on to push GstBuffers and GstEvents on to the srcpad, +using functions like gst_harness_push() and gst_harness_push_event(), and +then pull them out to examine them with gst_harness_pull() and +gst_harness_pull_event().

+
+

A simple buffer-in buffer-out example

+
+ + + + + + + +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
#include <gst/gst.h>
+#include <gst/check/gstharness.h>
+GstHarness *h;
+GstBuffer *in_buf;
+GstBuffer *out_buf;
+
+// attach the harness to the src and sink pad of GstQueue
+h = gst_harness_new ("queue");
+
+// we must specify a caps before pushing buffers
+gst_harness_set_src_caps_str (h, "mycaps");
+
+// create a buffer of size 42
+in_buf = gst_harness_create_buffer (h, 42);
+
+// push the buffer into the queue
+gst_harness_push (h, in_buf);
+
+// pull the buffer from the queue
+out_buf = gst_harness_pull (h);
+
+// validate the buffer in is the same as buffer out
+fail_unless (in_buf == out_buf);
+
+// cleanup
+gst_buffer_unref (out_buf);
+gst_harness_teardown (h);
+
+ +

+

Another main feature of the GstHarness is its integration with the +GstTestClock. Operating the GstTestClock can be very challenging, but +GstHarness simplifies some of the most desired actions a lot, like wanting +to manually advance the clock while at the same time releasing a GstClockID +that is waiting, with functions like gst_harness_crank_single_clock_wait().

+

GstHarness also supports sub-harnesses, as a way of generating and +validating data. A sub-harness is another GstHarness that is managed by +the "parent" harness, and can either be created by using the standard +gst_harness_new type functions directly on the (GstHarness *)->src_harness, +or using the much more convenient gst_harness_add_src() or +gst_harness_add_sink_parse(). If you have a decoder-element you want to test, +(like vp8dec) it can be very useful to add a src-harness with both a +src-element (videotestsrc) and an encoder (vp8enc) to feed the decoder data +with different configurations, by simply doing:

+
+ + + + + + + +
1
+2
GstHarness * h = gst_harness_new (h, "vp8dec");
+gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE);
+
+ +

+

and then feeding it data with:

+
+ + + + + + + +
1
gst_harness_push_from_src (h);
+
+ +

+
+
+
+

Functions

+
+

gst_harness_new_empty ()

+
GstHarness *
+gst_harness_new_empty (void);
+

Creates a new empty harness. Use gst_harness_add_element_full() to add +an GstElement to it.

+

MT safe.

+

[skip]

+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.8

+
+
+
+

gst_harness_new_full ()

+
GstHarness *
+gst_harness_new_full (GstElement *element,
+                      GstStaticPadTemplate *hsrc,
+                      const gchar *element_sinkpad_name,
+                      GstStaticPadTemplate *hsink,
+                      const gchar *element_srcpad_name);
+

Creates a new harness.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

element

a GstElement to attach the harness to (transfer none)

 

hsrc

a GstStaticPadTemplate describing the harness srcpad. +NULL will not create a harness srcpad.

[allow-none]

element_sinkpad_name

a gchar with the name of the element +sinkpad that is then linked to the harness srcpad. Can be a static or request +or a sometimes pad that has been added. NULL will not get/request a sinkpad +from the element. (Like if the element is a src.).

[allow-none]

hsink

a GstStaticPadTemplate describing the harness sinkpad. +NULL will not create a harness sinkpad.

[allow-none]

element_srcpad_name

a gchar with the name of the element +srcpad that is then linked to the harness sinkpad, similar to the +element_sinkpad_name +.

[allow-none]
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_new_with_element ()

+
GstHarness *
+gst_harness_new_with_element (GstElement *element,
+                              const gchar *element_sinkpad_name,
+                              const gchar *element_srcpad_name);
+

Creates a new harness. Works in the same way as gst_harness_new_full(), only +that generic padtemplates are used for the harness src and sinkpads, which +will be sufficient in most usecases.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element

a GstElement to attach the harness to (transfer none)

 

element_sinkpad_name

a gchar with the name of the element +sinkpad that is then linked to the harness srcpad. NULL does not attach a +sinkpad.

[allow-none]

element_srcpad_name

a gchar with the name of the element +srcpad that is then linked to the harness sinkpad. NULL does not attach a +srcpad.

[allow-none]
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_new_with_padnames ()

+
GstHarness *
+gst_harness_new_with_padnames (const gchar *element_name,
+                               const gchar *element_sinkpad_name,
+                               const gchar *element_srcpad_name);
+

Creates a new harness. Works like gst_harness_new_with_element(), +except you specify the factoryname of the GstElement

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element_name

a gchar describing the GstElement name

 

element_sinkpad_name

a gchar with the name of the element +sinkpad that is then linked to the harness srcpad. NULL does not attach a +sinkpad.

[allow-none]

element_srcpad_name

a gchar with the name of the element +srcpad that is then linked to the harness sinkpad. NULL does not attach a +srcpad.

[allow-none]
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_new_with_templates ()

+
GstHarness *
+gst_harness_new_with_templates (const gchar *element_name,
+                                GstStaticPadTemplate *hsrc,
+                                GstStaticPadTemplate *hsink);
+

Creates a new harness, like gst_harness_new_full(), except it +assumes the GstElement sinkpad is named "sink" and srcpad is named "src"

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

element_name

a gchar describing the GstElement name

 

hsrc

a GstStaticPadTemplate describing the harness srcpad. +NULL will not create a harness srcpad.

[allow-none]

hsink

a GstStaticPadTemplate describing the harness sinkpad. +NULL will not create a harness sinkpad.

[allow-none]
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_new ()

+
GstHarness *
+gst_harness_new (const gchar *element_name);
+

Creates a new harness. Works like gst_harness_new_with_padnames(), except it +assumes the GstElement sinkpad is named "sink" and srcpad is named "src"

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

element_name

a gchar describing the GstElement name

 
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_new_parse ()

+
GstHarness *
+gst_harness_new_parse (const gchar *launchline);
+

Creates a new harness, parsing the launchline + and putting that in a GstBin, +and then attches the harness to the bin.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

launchline

a gchar describing a gst-launch type line

 
+
+
+

Returns

+

a GstHarness, or NULL if the harness could +not be created.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_add_element_full ()

+
void
+gst_harness_add_element_full (GstHarness *h,
+                              GstElement *element,
+                              GstStaticPadTemplate *hsrc,
+                              const gchar *element_sinkpad_name,
+                              GstStaticPadTemplate *hsink,
+                              const gchar *element_srcpad_name);
+

Adds a GstElement to an empty GstHarness

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

element

a GstElement to add to the harness (transfer none)

 

hsrc

a GstStaticPadTemplate describing the harness srcpad. +NULL will not create a harness srcpad.

[allow-none]

element_sinkpad_name

a gchar with the name of the element +sinkpad that is then linked to the harness srcpad. Can be a static or request +or a sometimes pad that has been added. NULL will not get/request a sinkpad +from the element. (Like if the element is a src.).

[allow-none]

hsink

a GstStaticPadTemplate describing the harness sinkpad. +NULL will not create a harness sinkpad.

[allow-none]

element_srcpad_name

a gchar with the name of the element +srcpad that is then linked to the harness sinkpad, similar to the +element_sinkpad_name +.

[allow-none]
+
+

Since: 1.6

+
+
+
+

gst_harness_add_parse ()

+
void
+gst_harness_add_parse (GstHarness *h,
+                       const gchar *launchline);
+

Parses the launchline + and puts that in a GstBin, +and then attches the supplied GstHarness to the bin.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

launchline

a gchar describing a gst-launch type line

 
+
+

Since: 1.6

+
+
+
+

gst_harness_teardown ()

+
void
+gst_harness_teardown (GstHarness *h);
+

Tears down a GstHarness +, freeing all resources allocated using it.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_element_src_pad ()

+
void
+gst_harness_add_element_src_pad (GstHarness *h,
+                                 GstPad *srcpad);
+

Links the specifed GstPad the GstHarness + sinkpad. This can be useful if +perhaps the srcpad did not exist at the time of creating the harness, +like a demuxer that provides a sometimes-pad after receiving data.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

srcpad

a GstPad to link to the harness sinkpad

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_element_sink_pad ()

+
void
+gst_harness_add_element_sink_pad (GstHarness *h,
+                                  GstPad *sinkpad);
+

Links the specifed GstPad the GstHarness + srcpad.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

sinkpad

a GstPad to link to the harness srcpad

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_src_caps ()

+
void
+gst_harness_set_src_caps (GstHarness *h,
+                          GstCaps *caps);
+

Sets the GstHarness + srcpad caps. This must be done before any buffers +can legally be pushed from the harness to the element.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

caps

a GstCaps to set on the harness srcpad.

[transfer full]
+
+

Since: 1.6

+
+
+
+

gst_harness_set_sink_caps ()

+
void
+gst_harness_set_sink_caps (GstHarness *h,
+                           GstCaps *caps);
+

Sets the GstHarness + sinkpad caps.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

caps

a GstCaps to set on the harness sinkpad.

[transfer full]
+
+

Since: 1.6

+
+
+
+

gst_harness_set_caps ()

+
void
+gst_harness_set_caps (GstHarness *h,
+                      GstCaps *in,
+                      GstCaps *out);
+

Sets the GstHarness + srcpad and sinkpad caps.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

in

a GstCaps to set on the harness srcpad.

[transfer full]

out

a GstCaps to set on the harness sinkpad.

[transfer full]
+
+

Since: 1.6

+
+
+
+

gst_harness_set_src_caps_str ()

+
void
+gst_harness_set_src_caps_str (GstHarness *h,
+                              const gchar *str);
+

Sets the GstHarness + srcpad caps using a string. This must be done before +any buffers can legally be pushed from the harness to the element.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

str

a gchar +describing a GstCaps to set on the harness srcpad

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_sink_caps_str ()

+
void
+gst_harness_set_sink_caps_str (GstHarness *h,
+                               const gchar *str);
+

Sets the GstHarness + sinkpad caps using a string.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

str

a gchar +describing a GstCaps to set on the harness sinkpad

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_caps_str ()

+
void
+gst_harness_set_caps_str (GstHarness *h,
+                          const gchar *in,
+                          const gchar *out);
+

Sets the GstHarness + srcpad and sinkpad caps using strings.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

in

a gchar +describing a GstCaps to set on the harness srcpad

 

out

a gchar +describing a GstCaps to set on the harness sinkpad

 
+
+

Since: 1.6

+
+
+
+

gst_harness_use_systemclock ()

+
void
+gst_harness_use_systemclock (GstHarness *h);
+

Sets the system GstClock on the GstHarness + GstElement

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+

Since: 1.6

+
+
+
+

gst_harness_use_testclock ()

+
void
+gst_harness_use_testclock (GstHarness *h);
+

Sets the GstTestClock on the GstHarness GstElement

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+

Since: 1.6

+
+
+
+

gst_harness_get_testclock ()

+
GstTestClock *
+gst_harness_get_testclock (GstHarness *h);
+

Get the GstTestClock. Useful if specific operations on the testclock is +needed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstTestClock, or NULL if the testclock is not +present.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_set_time ()

+
gboolean
+gst_harness_set_time (GstHarness *h,
+                      GstClockTime time);
+

Advance the GstTestClock to a specific time.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

time

a GstClockTime to advance the clock to

 
+
+
+

Returns

+

a gboolean +TRUE if the time could be set. FALSE if not.

+
+

Since: 1.6

+
+
+
+

gst_harness_wait_for_clock_id_waits ()

+
gboolean
+gst_harness_wait_for_clock_id_waits (GstHarness *h,
+                                     guint waits,
+                                     guint timeout);
+

Waits for timeout + seconds until waits + number of GstClockID waits is +registered with the GstTestClock. Useful for writing deterministic tests, +where you want to make sure that an expected number of waits have been +reached.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

waits

a guint describing the numbers of GstClockID registered with +the GstTestClock

 

timeout

a guint describing how many seconds to wait for waits +to be true

 
+
+
+

Returns

+

a gboolean +TRUE if the waits have been registered, FALSE if not. +(Could be that it timed out waiting or that more waits then waits was found)

+
+

Since: 1.6

+
+
+
+

gst_harness_crank_single_clock_wait ()

+
gboolean
+gst_harness_crank_single_clock_wait (GstHarness *h);
+

A "crank" consists of three steps: +1: Wait for a GstClockID to be registered with the GstTestClock. +2: Advance the GstTestClock to the time the GstClockID is waiting for. +3: Release the GstClockID wait. +Together, this provides an easy way to not have to think about the details +around clocks and time, but still being able to write deterministic tests +that are dependant on this. A "crank" can be though of as the notion of +manually driving the clock forward to its next logical step.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a gboolean +TRUE if the "crank" was successful, FALSE if not.

+
+

Since: 1.6

+
+
+
+

gst_harness_crank_multiple_clock_waits ()

+
gboolean
+gst_harness_crank_multiple_clock_waits
+                               (GstHarness *h,
+                                guint waits);
+

Similar to gst_harness_crank_single_clock_wait(), this is the function to use +if your harnessed element(s) are using more then one gst_clock_id_wait. +Failing to do so can (and will) make it racy which GstClockID you actually +are releasing, where as this function will process all the waits at the +same time, ensuring that one thread can't register another wait before +both are released.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

waits

a guint describing the number of GstClockIDs to crank

 
+
+
+

Returns

+

a gboolean +TRUE if the "crank" was successful, FALSE if not.

+
+

Since: 1.6

+
+
+
+

gst_harness_play ()

+
void
+gst_harness_play (GstHarness *h);
+

This will set the harnessed GstElement to GST_STATE_PLAYING. +GstElements without a sink-GstPad and with the GST_ELEMENT_FLAG_SOURCE +flag set is concidered a src GstElement +Non-src GstElements (like sinks and filters) are automatically set to +playing by the GstHarness, but src GstElements are not to avoid them +starting to produce buffers. +Hence, for src GstElement you must call gst_harness_play() explicitly.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_blocking_push_mode ()

+
void
+gst_harness_set_blocking_push_mode (GstHarness *h);
+

Setting this will make the harness block in the chain-function, and +then release when gst_harness_pull() or gst_harness_try_pull() is called. +Can be useful when wanting to control a src-element that is not implementing +gst_clock_id_wait() so it can't be controlled by the GstTestClock, since +it otherwise would produce buffers as fast as possible.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_forwarding ()

+
void
+gst_harness_set_forwarding (GstHarness *h,
+                            gboolean forwarding);
+

As a convenience, a src-harness will forward GST_EVENT_STREAM_START, +GST_EVENT_CAPS and GST_EVENT_SEGMENT to the main-harness if forwarding +is enabled, and forward any sticky-events from the main-harness to +the sink-harness. It will also forward the GST_QUERY_ALLOCATION.

+

If forwarding is disabled, the user will have to either manually push +these events from the src-harness using gst_harness_src_push_event(), or +create and push them manually. While this will allow full control and +inspection of these events, for the most cases having forwarding enabled +will be sufficient when writing a test where the src-harness' main function +is providing data for the main-harness.

+

Forwarding is enabled by default.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

forwarding

a gboolean to enable/disable forwarding

 
+
+

Since: 1.6

+
+
+
+

gst_harness_create_buffer ()

+
GstBuffer *
+gst_harness_create_buffer (GstHarness *h,
+                           gsize size);
+

Allocates a buffer using a GstBufferPool if present, or else using the +configured GstAllocator and GstAllocationParams

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

size

a gsize specifying the size of the buffer

 
+
+
+

Returns

+

a GstBuffer of size size +

+
+

Since: 1.6

+
+
+
+

gst_harness_push ()

+
GstFlowReturn
+gst_harness_push (GstHarness *h,
+                  GstBuffer *buffer);
+

Pushes a GstBuffer on the GstHarness srcpad. The standard way of +interacting with an harnessed element.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

buffer

a GstBuffer to push.

[transfer full]
+
+
+

Returns

+

a GstFlowReturn with the result from the push

+
+

Since: 1.6

+
+
+
+

gst_harness_pull ()

+
GstBuffer *
+gst_harness_pull (GstHarness *h);
+

Pulls a GstBuffer from the GAsyncQueue on the GstHarness sinkpad. The pull +will timeout in 60 seconds. This is the standard way of getting a buffer +from a harnessed GstElement.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstBuffer or NULL if timed out.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_try_pull ()

+
GstBuffer *
+gst_harness_try_pull (GstHarness *h);
+

Pulls a GstBuffer from the GAsyncQueue on the GstHarness sinkpad. Unlike +gst_harness_pull this will not wait for any buffers if not any are present, +and return NULL straight away.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstBuffer or NULL if no buffers are present in the GAsyncQueue.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_push_and_pull ()

+
GstBuffer *
+gst_harness_push_and_pull (GstHarness *h,
+                           GstBuffer *buffer);
+

Basically a gst_harness_push and a gst_harness_pull in one line. Reflects +the fact that you often want to do exactly this in your test: Push one buffer +in, and inspect the outcome.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

buffer

a GstBuffer to push.

[transfer full]
+
+
+

Returns

+

a GstBuffer or NULL if timed out.

+

[transfer full]

+
+

Since: 1.6

+
+
+
+

gst_harness_buffers_received ()

+
guint
+gst_harness_buffers_received (GstHarness *h);
+

The total number of GstBuffers that has arrived on the GstHarness sinkpad. +This number includes buffers that have been dropped as well as buffers +that have already been pulled out.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of buffers received

+
+

Since: 1.6

+
+
+
+

gst_harness_buffers_in_queue ()

+
guint
+gst_harness_buffers_in_queue (GstHarness *h);
+

The number of GstBuffers currently in the GstHarness sinkpad GAsyncQueue

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of buffers in the queue

+
+

Since: 1.6

+
+
+
+

gst_harness_set_drop_buffers ()

+
void
+gst_harness_set_drop_buffers (GstHarness *h,
+                              gboolean drop_buffers);
+

When set to TRUE, instead of placing the buffers arriving from the harnessed +GstElement inside the sinkpads GAsyncQueue, they are instead unreffed.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

drop_buffers

a gboolean specifying to drop outgoing buffers or not

 
+
+

Since: 1.6

+
+
+
+

gst_harness_dump_to_file ()

+
void
+gst_harness_dump_to_file (GstHarness *h,
+                          const gchar *filename);
+

Allows you to dump the GstBuffers the GstHarness sinkpad GAsyncQueue +to a file.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

filename

a gchar with a the name of a file

 
+
+

Since: 1.6

+
+
+
+

gst_harness_take_all_data ()

+
guint8 *
+gst_harness_take_all_data (GstHarness *h,
+                           gsize *size);
+

Pulls all pending data from the harness and returns it as a single +data slice.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

size

the size of the data in bytes.

[out]
+
+
+

Returns

+

a pointer to the data, newly allocated. Free +with g_free() when no longer needed. Will return NULL if there is no +data.

+

[transfer full]

+
+

Since: 1.14

+
+
+
+

gst_harness_take_all_data_as_buffer ()

+
GstBuffer *
+gst_harness_take_all_data_as_buffer (GstHarness *h);
+

Pulls all pending data from the harness and returns it as a single buffer.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

the data as a buffer. Unref with gst_buffer_unref() +when no longer needed.

+

[transfer full]

+
+

Since: 1.14

+
+
+
+

gst_harness_take_all_data_as_bytes ()

+
GBytes *
+gst_harness_take_all_data_as_bytes (GstHarness *h);
+

Pulls all pending data from the harness and returns it as a single GBytes.

+

[rename-to gst_harness_take_all_data]

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a pointer to the data, newly allocated. Free +with g_free() when no longer needed.

+

[transfer full]

+
+

Since: 1.14

+
+
+
+

gst_harness_get_last_pushed_timestamp ()

+
GstClockTime
+gst_harness_get_last_pushed_timestamp (GstHarness *h);
+

Get the timestamp of the last GstBuffer pushed on the GstHarness srcpad, +typically with gst_harness_push or gst_harness_push_from_src.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstClockTime with the timestamp or GST_CLOCK_TIME_NONE if no +GstBuffer has been pushed on the GstHarness srcpad

+
+

Since: 1.6

+
+
+
+

gst_harness_push_event ()

+
gboolean
+gst_harness_push_event (GstHarness *h,
+                        GstEvent *event);
+

Pushes an GstEvent on the GstHarness srcpad.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

event

a GstEvent to push

 
+
+
+

Returns

+

a gboolean with the result from the push

+
+

Since: 1.6

+
+
+
+

gst_harness_pull_event ()

+
GstEvent *
+gst_harness_pull_event (GstHarness *h);
+

Pulls an GstEvent from the GAsyncQueue on the GstHarness sinkpad. +Timeouts after 60 seconds similar to gst_harness_pull.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstEvent or NULL if timed out.

+
+

Since: 1.6

+
+
+
+

gst_harness_try_pull_event ()

+
GstEvent *
+gst_harness_try_pull_event (GstHarness *h);
+

Pulls an GstEvent from the GAsyncQueue on the GstHarness sinkpad. +See gst_harness_try_pull for details.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstEvent or NULL if no buffers are present in the GAsyncQueue

+
+

Since: 1.6

+
+
+
+

gst_harness_events_received ()

+
guint
+gst_harness_events_received (GstHarness *h);
+

The total number of GstEvents that has arrived on the GstHarness sinkpad +This number includes events handled by the harness as well as events +that have already been pulled out.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of events received

+
+

Since: 1.6

+
+
+
+

gst_harness_events_in_queue ()

+
guint
+gst_harness_events_in_queue (GstHarness *h);
+

The number of GstEvents currently in the GstHarness sinkpad GAsyncQueue

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of events in the queue

+
+

Since: 1.6

+
+
+
+

gst_harness_push_upstream_event ()

+
gboolean
+gst_harness_push_upstream_event (GstHarness *h,
+                                 GstEvent *event);
+

Pushes an GstEvent on the GstHarness sinkpad.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

event

a GstEvent to push

 
+
+
+

Returns

+

a gboolean with the result from the push

+
+

Since: 1.6

+
+
+
+

gst_harness_pull_upstream_event ()

+
GstEvent *
+gst_harness_pull_upstream_event (GstHarness *h);
+

Pulls an GstEvent from the GAsyncQueue on the GstHarness srcpad. +Timeouts after 60 seconds similar to gst_harness_pull.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstEvent or NULL if timed out.

+
+

Since: 1.6

+
+
+
+

gst_harness_try_pull_upstream_event ()

+
GstEvent *
+gst_harness_try_pull_upstream_event (GstHarness *h);
+

Pulls an GstEvent from the GAsyncQueue on the GstHarness srcpad. +See gst_harness_try_pull for details.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstEvent or NULL if no buffers are present in the GAsyncQueue

+
+

Since: 1.6

+
+
+
+

gst_harness_upstream_events_received ()

+
guint
+gst_harness_upstream_events_received (GstHarness *h);
+

The total number of GstEvents that has arrived on the GstHarness srcpad +This number includes events handled by the harness as well as events +that have already been pulled out.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of events received

+
+

Since: 1.6

+
+
+
+

gst_harness_upstream_events_in_queue ()

+
guint
+gst_harness_upstream_events_in_queue (GstHarness *h);
+

The number of GstEvents currently in the GstHarness srcpad GAsyncQueue

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a guint number of events in the queue

+
+

Since: 1.6

+
+
+
+

gst_harness_query_latency ()

+
GstClockTime
+gst_harness_query_latency (GstHarness *h);
+

Get the min latency reported by any harnessed GstElement.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstClockTime with min latency

+
+

Since: 1.6

+
+
+
+

gst_harness_set_upstream_latency ()

+
void
+gst_harness_set_upstream_latency (GstHarness *h,
+                                  GstClockTime latency);
+

Sets the min latency reported by GstHarness when receiving a latency-query

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

latency

a GstClockTime specifying the latency

 
+
+

Since: 1.6

+
+
+
+

gst_harness_set_propose_allocator ()

+
void
+gst_harness_set_propose_allocator (GstHarness *h,
+                                   GstAllocator *allocator,
+                                   const GstAllocationParams *params);
+

Sets the allocator + and params + to propose when receiving an allocation +query.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

allocator

a GstAllocator.

[allow-none][transfer full]

params

a GstAllocationParams.

[allow-none][transfer none]
+
+

Since: 1.6

+
+
+
+

gst_harness_get_allocator ()

+
void
+gst_harness_get_allocator (GstHarness *h,
+                           GstAllocator **allocator,
+                           GstAllocationParams *params);
+

Gets the allocator + and its params + that has been decided to use after an +allocation query.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

allocator

the GstAllocator used.

[out][allow-none][transfer none]

params

the GstAllocationParams of +allocator +.

[out][allow-none][transfer full]
+
+

Since: 1.6

+
+
+
+

gst_harness_add_src ()

+
void
+gst_harness_add_src (GstHarness *h,
+                     const gchar *src_element_name,
+                     gboolean has_clock_wait);
+

Similar to gst_harness_add_src_harness, this is a convenience to +directly create a src-harness using the src_element_name + name specified.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

src_element_name

a gchar with the name of a GstElement

 

has_clock_wait

a gboolean specifying if the GstElement uses +gst_clock_wait_id internally.

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_src_harness ()

+
void
+gst_harness_add_src_harness (GstHarness *h,
+                             GstHarness *src_harness,
+                             gboolean has_clock_wait);
+

A src-harness is a great way of providing the GstHarness with data. +By adding a src-type GstElement, it is then easy to use functions like +gst_harness_push_from_src or gst_harness_src_crank_and_push_many +to provide your harnessed element with input. The has_clock_wait + variable +is a greate way to control you src-element with, in that you can have it +produce a buffer for you by simply cranking the clock, and not have it +spin out of control producing buffers as fast as possible.

+

If a src-harness already exists it will be replaced.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

src_harness

a GstHarness to be added as a src-harness.

[transfer full]

has_clock_wait

a gboolean specifying if the GstElement uses +gst_clock_wait_id internally.

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_src_parse ()

+
void
+gst_harness_add_src_parse (GstHarness *h,
+                           const gchar *launchline,
+                           gboolean has_clock_wait);
+

Similar to gst_harness_add_src, this allows you to specify a launch-line, +which can be useful for both having more then one GstElement acting as your +src (Like a src producing raw buffers, and then an encoder, providing encoded +data), but also by allowing you to set properties like "is-live" directly on +the elements.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

launchline

a gchar describing a gst-launch type line

 

has_clock_wait

a gboolean specifying if the GstElement uses +gst_clock_wait_id internally.

 
+
+

Since: 1.6

+
+
+
+

gst_harness_push_from_src ()

+
GstFlowReturn
+gst_harness_push_from_src (GstHarness *h);
+

Transfer data from the src-GstHarness to the main-GstHarness. It consists +of 4 steps: +1: Make sure the src is started. (see: gst_harness_play) +2: Crank the clock (see: gst_harness_crank_single_clock_wait) +3: Pull a GstBuffer from the src-GstHarness (see: gst_harness_pull) +4: Push the same GstBuffer into the main-GstHarness (see: gst_harness_push)

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstFlowReturn with the result of the push

+
+

Since: 1.6

+
+
+
+

gst_harness_src_crank_and_push_many ()

+
GstFlowReturn
+gst_harness_src_crank_and_push_many (GstHarness *h,
+                                     gint cranks,
+                                     gint pushes);
+

Transfer data from the src-GstHarness to the main-GstHarness. Similar to +gst_harness_push_from_src, this variant allows you to specify how many cranks +and how many pushes to perform. This can be useful for both moving a lot +of data at the same time, as well as cases when one crank does not equal one +buffer to push and v.v.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

cranks

a gint with the number of calls to gst_harness_crank_single_clock_wait

 

pushes

a gint with the number of calls to gst_harness_push

 
+
+
+

Returns

+

a GstFlowReturn with the result of the push

+
+

Since: 1.6

+
+
+
+

gst_harness_src_push_event ()

+
gboolean
+gst_harness_src_push_event (GstHarness *h);
+

Similar to what gst_harness_src_push does with GstBuffers, this transfers +a GstEvent from the src-GstHarness to the main-GstHarness. Note that +some GstEvents are being transferred automagically. Look at sink_forward_pad +for details.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a gboolean with the result of the push

+
+

Since: 1.6

+
+
+
+

gst_harness_add_sink ()

+
void
+gst_harness_add_sink (GstHarness *h,
+                      const gchar *sink_element_name);
+

Similar to gst_harness_add_sink_harness, this is a convenience to +directly create a sink-harness using the sink_element_name + name specified.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

sink_element_name

a gchar with the name of a GstElement

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_sink_harness ()

+
void
+gst_harness_add_sink_harness (GstHarness *h,
+                              GstHarness *sink_harness);
+

Similar to gst_harness_add_src, this allows you to send the data coming out +of your harnessed GstElement to a sink-element, allowing to test different +responses the element output might create in sink elements. An example might +be an existing sink providing some analytical data on the input it receives that +can be useful to your testing. If the goal is to test a sink-element itself, +this is better acheived using gst_harness_new directly on the sink.

+

If a sink-harness already exists it will be replaced.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

sink_harness

a GstHarness to be added as a sink-harness.

[transfer full]
+
+

Since: 1.6

+
+
+
+

gst_harness_add_sink_parse ()

+
void
+gst_harness_add_sink_parse (GstHarness *h,
+                            const gchar *launchline);
+

Similar to gst_harness_add_sink, this allows you to specify a launch-line +instead of just an element name. See gst_harness_add_src_parse for details.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

launchline

a gchar with the name of a GstElement

 
+
+

Since: 1.6

+
+
+
+

gst_harness_push_to_sink ()

+
GstFlowReturn
+gst_harness_push_to_sink (GstHarness *h);
+

Transfer one GstBuffer from the main-GstHarness to the sink-GstHarness. +See gst_harness_push_from_src for details.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

h

a GstHarness

 
+
+
+

Returns

+

a GstFlowReturn with the result of the push

+
+

Since: 1.6

+
+
+
+

gst_harness_sink_push_many ()

+
GstFlowReturn
+gst_harness_sink_push_many (GstHarness *h,
+                            gint pushes);
+

Convenience that calls gst_harness_push_to_sink pushes + number of times. +Will abort the pushing if any one push fails.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

pushes

a gint with the number of calls to gst_harness_push_to_sink

 
+
+
+

Returns

+

a GstFlowReturn with the result of the push

+
+

Since: 1.6

+
+
+
+

gst_harness_find_element ()

+
GstElement *
+gst_harness_find_element (GstHarness *h,
+                          const gchar *element_name);
+

Most useful in conjunction with gst_harness_new_parse, this will scan the +GstElements inside the GstHarness, and check if any of them matches +element_name +. Typical usecase being that you need to access one of the +harnessed elements for properties and/or signals.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

element_name

a gchar with a GstElementFactory name

 
+
+
+

Returns

+

a GstElement or NULL if not found.

+

[transfer full][allow-none]

+
+

Since: 1.6

+
+
+
+

gst_harness_set ()

+
void
+gst_harness_set (GstHarness *h,
+                 const gchar *element_name,
+                 const gchar *first_property_name,
+                 ...);
+

A convenience function to allows you to call g_object_set on a GstElement +that are residing inside the GstHarness, by using normal g_object_set +syntax.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

element_name

a gchar with a GstElementFactory name

 

first_property_name

a gchar with the first property name

 

...

value for the first property, followed optionally by more +name/value pairs, followed by NULL

 
+
+

Since: 1.6

+
+
+
+

gst_harness_get ()

+
void
+gst_harness_get (GstHarness *h,
+                 const gchar *element_name,
+                 const gchar *first_property_name,
+                 ...);
+

A convenience function to allows you to call g_object_get on a GstElement +that are residing inside the GstHarness, by using normal g_object_get +syntax.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

element_name

a gchar with a GstElementFactory name

 

first_property_name

a gchar with the first property name

 

...

return location for the first property, followed optionally by more +name/return location pairs, followed by NULL

 
+
+

Since: 1.6

+
+
+
+

gst_harness_add_probe ()

+
void
+gst_harness_add_probe (GstHarness *h,
+                       const gchar *element_name,
+                       const gchar *pad_name,
+                       GstPadProbeType mask,
+                       GstPadProbeCallback callback,
+                       gpointer user_data,
+                       GDestroyNotify destroy_data);
+

A convenience function to allows you to call gst_pad_add_probe on a +GstPad of a GstElement that are residing inside the GstHarness, +by using normal gst_pad_add_probe syntax

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

element_name

a gchar with a GstElementFactory name

 

pad_name

a gchar with the name of the pad to attach the probe to

 

mask

a GstPadProbeType (see gst_pad_add_probe)

 

callback

a GstPadProbeCallback (see gst_pad_add_probe)

 

user_data

a gpointer (see gst_pad_add_probe)

 

destroy_data

a GDestroyNotify (see gst_pad_add_probe)

 
+
+

Since: 1.6

+
+
+
+

gst_harness_stress_thread_stop ()

+
guint
+gst_harness_stress_thread_stop (GstHarnessThread *t);
+

Stop the running GstHarnessThread

+

MT safe.

+
+

Parameters

+
+++++ + + + + + +

t

a GstHarnessThread

 
+
+

Since: 1.6

+
+
+
+

gst_harness_stress_custom_start ()

+
GstHarnessThread *
+gst_harness_stress_custom_start (GstHarness *h,
+                                 GFunc init,
+                                 GFunc callback,
+                                 gpointer data,
+                                 gulong sleep);
+

Start a custom stress-thread that will call your callback + for every +iteration allowing you to do something nasty.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

init

a GFunc that is called initially and only once.

[allow-none]

callback

a GFunc that is called as often as possible

 

data

a gpointer with custom data to pass to the callback +function

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each call to the callback +

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

gst_harness_stress_statechange_start()

+
#define             gst_harness_stress_statechange_start(h)
+
+
+
+

gst_harness_stress_statechange_start_full ()

+
GstHarnessThread *
+gst_harness_stress_statechange_start_full
+                               (GstHarness *h,
+                                gulong sleep);
+

Change the state of your harnessed GstElement from NULL to PLAYING and +back again, only pausing for sleep + microseconds every time.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each state-change

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

gst_harness_stress_push_buffer_start()

+
#define             gst_harness_stress_push_buffer_start(h, c, s, b)
+
+
+
+

gst_harness_stress_push_buffer_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_buffer_start_full
+                               (GstHarness *h,
+                                GstCaps *caps,
+                                const GstSegment *segment,
+                                GstBuffer *buf,
+                                gulong sleep);
+

Push a GstBuffer in intervals of sleep + microseconds.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

caps

a GstCaps for the GstBuffer

 

segment

a GstSegment

 

buf

a GstBuffer to push

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

GstHarnessPrepareBufferFunc ()

+
GstBuffer *
+(*GstHarnessPrepareBufferFunc) (GstHarness *h,
+                                gpointer data);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

data

user data

 
+
+

Since: 1.6

+
+
+
+

gst_harness_stress_push_buffer_with_cb_start()

+
#define             gst_harness_stress_push_buffer_with_cb_start(h, c, s, f, d, n)
+
+
+
+

gst_harness_stress_push_buffer_with_cb_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_buffer_with_cb_start_full
+                               (GstHarness *h,
+                                GstCaps *caps,
+                                const GstSegment *segment,
+                                GstHarnessPrepareBufferFunc func,
+                                gpointer data,
+                                GDestroyNotify notify,
+                                gulong sleep);
+

Push a GstBuffer returned by func + in intervals of sleep + microseconds.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

caps

a GstCaps for the GstBuffer

 

segment

a GstSegment

 

func

a GstHarnessPrepareBufferFunc function called before every iteration +to prepare / create a GstBuffer for pushing

 

data

a gpointer with data to the GstHarnessPrepareBufferFunc function

 

notify

a GDestroyNotify that is called when thread is stopped

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

gst_harness_stress_push_event_start()

+
#define             gst_harness_stress_push_event_start(h, e)
+
+
+
+

gst_harness_stress_push_event_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_event_start_full
+                               (GstHarness *h,
+                                GstEvent *event,
+                                gulong sleep);
+

Push the event + onto the harnessed GstElement sinkpad in intervals of +sleep + microseconds

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

event

a GstEvent to push

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each gst_event_push with event +

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

GstHarnessPrepareEventFunc ()

+
GstEvent *
+(*GstHarnessPrepareEventFunc) (GstHarness *h,
+                               gpointer data);
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

h

a GstHarness

 

data

user data

 
+
+

Since: 1.8

+
+
+
+

gst_harness_stress_push_event_with_cb_start()

+
#define             gst_harness_stress_push_event_with_cb_start(h, f, d, n)
+
+
+
+

gst_harness_stress_push_event_with_cb_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_event_with_cb_start_full
+                               (GstHarness *h,
+                                GstHarnessPrepareEventFunc func,
+                                gpointer data,
+                                GDestroyNotify notify,
+                                gulong sleep);
+

Push a GstEvent returned by func + onto the harnessed GstElement sinkpad +in intervals of sleep + microseconds.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

func

a GstHarnessPrepareEventFunc function called before every iteration +to prepare / create a GstEvent for pushing

 

data

a gpointer with data to the GstHarnessPrepareEventFunc function

 

notify

a GDestroyNotify that is called when thread is stopped

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.8

+
+
+
+

gst_harness_stress_send_upstream_event_start()

+
#define             gst_harness_stress_send_upstream_event_start(h, e)
+
+
+
+

gst_harness_stress_push_upstream_event_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_upstream_event_start_full
+                               (GstHarness *h,
+                                GstEvent *event,
+                                gulong sleep);
+

Push the event + onto the harnessed GstElement srcpad in intervals of +sleep + microseconds.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

event

a GstEvent to push

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each gst_event_push with event +

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

gst_harness_stress_send_upstream_event_with_cb_start()

+
#define             gst_harness_stress_send_upstream_event_with_cb_start(h, f, d, n)
+
+
+
+

gst_harness_stress_push_upstream_event_with_cb_start_full ()

+
GstHarnessThread *
+gst_harness_stress_push_upstream_event_with_cb_start_full
+                               (GstHarness *h,
+                                GstHarnessPrepareEventFunc func,
+                                gpointer data,
+                                GDestroyNotify notify,
+                                gulong sleep);
+

Push a GstEvent returned by func + onto the harnessed GstElement srcpad +in intervals of sleep + microseconds.

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

func

a GstHarnessPrepareEventFunc function called before every iteration +to prepare / create a GstEvent for pushing

 

data

a gpointer with data to the GstHarnessPrepareEventFunc function

 

notify

a GDestroyNotify that is called when thread is stopped

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.8

+
+
+
+

gst_harness_stress_property_start()

+
#define             gst_harness_stress_property_start(h, n, v)
+
+
+
+

gst_harness_stress_property_start_full ()

+
GstHarnessThread *
+gst_harness_stress_property_start_full
+                               (GstHarness *h,
+                                const gchar *name,
+                                const GValue *value,
+                                gulong sleep);
+

Call g_object_set with name + and value + in intervals of sleep + microseconds

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

name

a gchar specifying a property name

 

value

a GValue to set the property to

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each g_object_set with name +and value +

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

gst_harness_stress_requestpad_start()

+
#define             gst_harness_stress_requestpad_start(h, t, n, c, r)
+
+
+
+

gst_harness_stress_requestpad_start_full ()

+
GstHarnessThread *
+gst_harness_stress_requestpad_start_full
+                               (GstHarness *h,
+                                GstPadTemplate *templ,
+                                const gchar *name,
+                                GstCaps *caps,
+                                gboolean release,
+                                gulong sleep);
+

Call gst_element_request_pad in intervals of sleep + microseconds

+

MT safe.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

h

a GstHarness

 

templ

a GstPadTemplate

 

name

a gchar

 

caps

a GstCaps

 

release

a gboolean

 

sleep

a gulong specifying how long to sleep in (microseconds) for +each gst_element_request_pad

 
+
+
+

Returns

+

a GstHarnessThread

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

struct GstHarness

+
struct GstHarness {
+  GstElement * element;
+
+  GstPad * srcpad;
+  GstPad * sinkpad;
+
+  GstHarness * src_harness;
+  GstHarness * sink_harness;
+};
+
+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

GstElement *element;

the element inside the harness

 

GstPad *srcpad;

the internal harness source pad

 

GstPad *sinkpad;

the internal harness sink pad

 

GstHarness *src_harness;

the source (input) harness (if any)

 

GstHarness *sink_harness;

the sink (output) harness (if any)

 
+
+

Since: 1.6

+
+
+
+

GstHarnessThread

+
typedef struct _GstHarnessThread GstHarnessThread;
+

Opaque handle representing a GstHarness stress testing thread.

+

Since: 1.6

+
+
+
+

See Also

+

GstTestClock

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstNetAddressMeta.html b/docs/libs/html/gstreamer-libs-GstNetAddressMeta.html new file mode 100644 index 0000000..4d63c5e --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstNetAddressMeta.html @@ -0,0 +1,209 @@ + + + + +GstNetAddressMeta: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstNetAddressMeta

+

GstNetAddressMeta — Network address metadata

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + +
structGstNetAddressMeta
+
+
+

Includes

+
#include <gst/net/gstnetaddressmeta.h>
+
+
+
+

Description

+

GstNetAddressMeta can be used to store a network address (a GSocketAddress) +in a GstBuffer so that it network elements can track the to and from address +of the buffer.

+
+
+

Functions

+
+

gst_buffer_add_net_address_meta ()

+
GstNetAddressMeta *
+gst_buffer_add_net_address_meta (GstBuffer *buffer,
+                                 GSocketAddress *addr);
+

Attaches addr + as metadata in a GstNetAddressMeta to buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

addr

a GSocketAddress +to connect to buffer +

 
+
+
+

Returns

+

a GstNetAddressMeta connected to buffer +.

+

[transfer none]

+
+
+
+
+

gst_buffer_get_net_address_meta ()

+
GstNetAddressMeta *
+gst_buffer_get_net_address_meta (GstBuffer *buffer);
+

Find the GstNetAddressMeta on buffer +.

+
+

Parameters

+
+++++ + + + + + +

buffer

a GstBuffer

 
+
+
+

Returns

+

the GstNetAddressMeta or NULL when there +is no such metadata on buffer +.

+

[transfer none]

+
+
+
+
+

gst_net_address_meta_get_info ()

+
const GstMetaInfo *
+gst_net_address_meta_get_info (void);
+
+
+
+

Types and Values

+
+

struct GstNetAddressMeta

+
struct GstNetAddressMeta {
+  GstMeta       meta;
+
+  GSocketAddress *addr;
+};
+
+

Buffer metadata for network addresses.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMeta meta;

the parent type

 

GSocketAddress *addr;

a GSocketAddress stored as metadata

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstNetControlMessageMeta.html b/docs/libs/html/gstreamer-libs-GstNetControlMessageMeta.html new file mode 100644 index 0000000..f6133df --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstNetControlMessageMeta.html @@ -0,0 +1,186 @@ + + + + +GstNetControlMessageMeta: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstNetControlMessageMeta

+

GstNetControlMessageMeta — Network Control Message Meta

+
+ +
+

Types and Values

+
++++ + + + + +
structGstNetControlMessageMeta
+
+
+

Includes

+
#include <gst/net/gstnetcontrolmessagemeta.h>
+
+
+
+

Description

+

GstNetControlMessageMeta can be used to store control messages (ancillary +data) which was received with or is to be sent alongside the buffer data. +When used with socket sinks and sources which understand this meta it allows +sending and receiving ancillary data such as unix credentials (See +GUnixCredentialsMessage) and Unix file descriptions (See GUnixFDMessage).

+
+
+

Functions

+
+

gst_buffer_add_net_control_message_meta ()

+
GstNetControlMessageMeta *
+gst_buffer_add_net_control_message_meta
+                               (GstBuffer *buffer,
+                                GSocketControlMessage *message);
+

Attaches message + as metadata in a GstNetControlMessageMeta to buffer +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

buffer

a GstBuffer

 

message

a GSocketControlMessage +to attach to buffer +

 
+
+
+

Returns

+

a GstNetControlMessageMeta connected to buffer +.

+

[transfer none]

+
+
+
+
+

gst_buffer_get_net_control_message_meta()

+
#define             gst_buffer_get_net_control_message_meta(b)
+
+
+
+

gst_net_control_message_meta_get_info ()

+
const GstMetaInfo *
+gst_net_control_message_meta_get_info (void);
+
+
+
+

Types and Values

+
+

struct GstNetControlMessageMeta

+
struct GstNetControlMessageMeta {
+  GstMeta       meta;
+
+  GSocketControlMessage *message;
+};
+
+

Buffer metadata for GSocket control messages, AKA ancillary data attached to +data sent across a socket.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstMeta meta;

the parent type

 

GSocketControlMessage *message;

a GSocketControlMessage stored as metadata

 
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstNetTimePacket.html b/docs/libs/html/gstreamer-libs-GstNetTimePacket.html new file mode 100644 index 0000000..a64af32 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstNetTimePacket.html @@ -0,0 +1,378 @@ + + + + +GstNetTimePacket: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstNetTimePacket

+

GstNetTimePacket — Helper structure to construct clock packets used + by network clocks.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstNetTimePacket * + +gst_net_time_packet_new () +
+GstNetTimePacket * + +gst_net_time_packet_copy () +
+void + +gst_net_time_packet_free () +
+GstNetTimePacket * + +gst_net_time_packet_receive () +
+gboolean + +gst_net_time_packet_send () +
+guint8 * + +gst_net_time_packet_serialize () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstNetTimePacket
#defineGST_NET_TIME_PACKET_SIZE
+
+
+

Includes

+
#include <gst/net/gstnet.h>
+
+
+
+

Description

+

Various functions for receiving, sending an serializing GstNetTimePacket +structures.

+
+
+

Functions

+
+

gst_net_time_packet_new ()

+
GstNetTimePacket *
+gst_net_time_packet_new (const guint8 *buffer);
+

Creates a new GstNetTimePacket from a buffer received over the network. The +caller is responsible for ensuring that buffer + is at least +GST_NET_TIME_PACKET_SIZE bytes long.

+

If buffer + is NULL, the local and remote times will be set to +GST_CLOCK_TIME_NONE.

+

MT safe. Caller owns return value (gst_net_time_packet_free to free).

+
+

Parameters

+
+++++ + + + + + +

buffer

a buffer from which to construct the packet, or NULL.

[array]
+
+
+

Returns

+

The new GstNetTimePacket.

+
+
+
+
+

gst_net_time_packet_copy ()

+
GstNetTimePacket *
+gst_net_time_packet_copy (const GstNetTimePacket *packet);
+

Make a copy of packet +.

+
+

Parameters

+
+++++ + + + + + +

packet

the GstNetTimePacket

 
+
+
+

Returns

+

a copy of packet +, free with gst_net_time_packet_free().

+
+
+
+
+

gst_net_time_packet_free ()

+
void
+gst_net_time_packet_free (GstNetTimePacket *packet);
+

Free packet +.

+
+

Parameters

+
+++++ + + + + + +

packet

the GstNetTimePacket

 
+
+
+
+
+

gst_net_time_packet_receive ()

+
GstNetTimePacket *
+gst_net_time_packet_receive (GSocket *socket,
+                             GSocketAddress **src_address,
+                             GError **error);
+

Receives a GstNetTimePacket over a socket. Handles interrupted system +calls, but otherwise returns NULL on error.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

socket

socket to receive the time packet on

 

src_address

address of variable to return sender address.

[out]

error

return address for a GError, or NULL

 
+
+
+

Returns

+

a new GstNetTimePacket, or NULL on error. Free +with gst_net_time_packet_free() when done.

+

[transfer full]

+
+
+
+
+

gst_net_time_packet_send ()

+
gboolean
+gst_net_time_packet_send (const GstNetTimePacket *packet,
+                          GSocket *socket,
+                          GSocketAddress *dest_address,
+                          GError **error);
+

Sends a GstNetTimePacket over a socket.

+

MT safe.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

packet

the GstNetTimePacket to send

 

socket

socket to send the time packet on

 

dest_address

address to send the time packet to

 

error

return address for a GError, or NULL

 
+
+
+

Returns

+

TRUE if successful, FALSE in case an error occurred.

+
+
+
+
+

gst_net_time_packet_serialize ()

+
guint8 *
+gst_net_time_packet_serialize (const GstNetTimePacket *packet);
+

Serialized a GstNetTimePacket into a newly-allocated sequence of +GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is +suitable for passing to write(2) or sendto(2) for communication over the +network.

+

MT safe. Caller owns return value (g_free to free).

+
+

Parameters

+
+++++ + + + + + +

packet

the GstNetTimePacket

 
+
+
+

Returns

+

A newly allocated sequence of GST_NET_TIME_PACKET_SIZE bytes.

+
+
+
+
+

Types and Values

+
+

struct GstNetTimePacket

+
struct GstNetTimePacket {
+  GstClockTime local_time;
+  GstClockTime remote_time;
+};
+
+

Content of a GstNetTimePacket.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GstClockTime local_time;

the local time when this packet was sent

 

GstClockTime remote_time;

the remote time observation

 
+
+
+
+
+

GST_NET_TIME_PACKET_SIZE

+
#define GST_NET_TIME_PACKET_SIZE 16
+
+

The size of the packets sent between network clocks.

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstProxyControlBinding.html b/docs/libs/html/gstreamer-libs-GstProxyControlBinding.html new file mode 100644 index 0000000..26cc2f1 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstProxyControlBinding.html @@ -0,0 +1,131 @@ + + + + +GstProxyControlBinding: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstProxyControlBinding

+

GstProxyControlBinding — attachment for forwarding control sources

+
+
+

Functions

+ +
+
+

Includes

+
#include <libs/controller/controller.h>
+
+
+
+

Description

+

A GstControlBinding that forwards requests to another GstControlBinding

+
+
+

Functions

+
+

gst_proxy_control_binding_new ()

+
GstControlBinding *
+gst_proxy_control_binding_new (GstObject *object,
+                               const gchar *property_name,
+                               GstObject *ref_object,
+                               const gchar *ref_property_name);
+

GstProxyControlBinding forwards all access to data or sync_values() +requests from property_name + on object + to the control binding at +ref_property_name + on ref_object +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

object

a GstObject.

[transfer none]

property_name

the property name in object +to control

 

ref_object

a GstObject to forward all +GstControlBinding requests to.

[transfer none]

ref_property_name

the property_name in ref_object +to control

 
+
+
+

Returns

+

a new GstControlBinding that proxies the control interface between +properties on different GstObject's.

+

[transfer floating]

+
+

Since: 1.12

+
+
+
+

Types and Values

+
+
+

See Also

+

GstControlBinding

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstQueueArray.html b/docs/libs/html/gstreamer-libs-GstQueueArray.html new file mode 100644 index 0000000..bcd72ae --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstQueueArray.html @@ -0,0 +1,802 @@ + + + + +GstQueueArray: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstQueueArray

+

GstQueueArray — Array based queue object

+
+
+

Functions

+ +
+
+

Types and Values

+
++++ + + + + +
 GstQueueArray
+
+
+

Includes

+
#include <gst/base/gstqueuearray.h>
+
+
+
+

Description

+

GstQueueArray is an object that provides standard queue functionality +based on an array instead of linked lists. This reduces the overhead +caused by memory management by a large factor.

+
+
+

Functions

+
+

gst_queue_array_new ()

+
GstQueueArray *
+gst_queue_array_new (guint initial_size);
+

Allocates a new GstQueueArray object with an initial +queue size of initial_size +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

initial_size

Initial size of the new queue

 
+
+
+

Returns

+

a new GstQueueArray object

+
+

Since: 1.2

+
+
+
+

gst_queue_array_free ()

+
void
+gst_queue_array_free (GstQueueArray *array);
+

Frees queue array + and all memory associated to it.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+

Since: 1.2

+
+
+
+

gst_queue_array_get_length ()

+
guint
+gst_queue_array_get_length (GstQueueArray *array);
+

Returns the length of the queue array +

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

the length of the queue array +.

+
+

Since: 1.2

+
+
+
+

gst_queue_array_pop_head ()

+
gpointer
+gst_queue_array_pop_head (GstQueueArray *array);
+

Returns and head of the queue array + and removes +it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The head of the queue

+
+

Since: 1.2

+
+
+
+

gst_queue_array_peek_head ()

+
gpointer
+gst_queue_array_peek_head (GstQueueArray *array);
+

Returns the head of the queue array + and does not +remove it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The head of the queue

+
+

Since: 1.2

+
+
+
+

gst_queue_array_push_tail ()

+
void
+gst_queue_array_push_tail (GstQueueArray *array,
+                           gpointer data);
+

Pushes data + to the tail of the queue array +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

array

a GstQueueArray object

 

data

object to push

 
+
+

Since: 1.2

+
+
+
+

gst_queue_array_pop_tail ()

+
gpointer
+gst_queue_array_pop_tail (GstQueueArray *array);
+

Returns the tail of the queue array + and removes +it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The tail of the queue

+
+

Since: 1.14

+
+
+
+

gst_queue_array_peek_tail ()

+
gpointer
+gst_queue_array_peek_tail (GstQueueArray *array);
+

Returns the tail of the queue array +, but does not remove it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The tail of the queue

+
+

Since: 1.14

+
+
+
+

gst_queue_array_is_empty ()

+
gboolean
+gst_queue_array_is_empty (GstQueueArray *array);
+

Checks if the queue array + is empty.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

TRUE if the queue array +is empty

+
+

Since: 1.2

+
+
+
+

gst_queue_array_drop_element ()

+
gpointer
+gst_queue_array_drop_element (GstQueueArray *array,
+                              guint idx);
+

Drops the queue element at position idx + from queue array +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

array

a GstQueueArray object

 

idx

index to drop

 
+
+
+

Returns

+

the dropped element

+
+

Since: 1.2

+
+
+
+

gst_queue_array_find ()

+
guint
+gst_queue_array_find (GstQueueArray *array,
+                      GCompareFunc func,
+                      gpointer data);
+

Finds an element in the queue array +, either by comparing every element +with func + or by looking up data + if no compare function func + is provided, +and returning the index of the found element.

+

Note that the index is not 0-based, but an internal index number with a +random offset. The index can be used in connection with +gst_queue_array_drop_element(). FIXME: return index 0-based and make +gst_queue_array_drop_element() take a 0-based index.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

array

a GstQueueArray object

 

func

comparison function, or NULL to find data +by value.

[allow-none]

data

data for comparison function

 
+
+
+

Returns

+

Index of the found element or -1 if nothing was found.

+
+

Since: 1.2

+
+
+
+

gst_queue_array_new_for_struct ()

+
GstQueueArray *
+gst_queue_array_new_for_struct (gsize struct_size,
+                                guint initial_size);
+

Allocates a new GstQueueArray object for elements (e.g. structures) +of size struct_size +, with an initial queue size of initial_size +.

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

struct_size

Size of each element (e.g. structure) in the array

 

initial_size

Initial size of the new queue

 
+
+
+

Returns

+

a new GstQueueArray object

+
+

Since: 1.6

+
+
+
+

gst_queue_array_push_tail_struct ()

+
void
+gst_queue_array_push_tail_struct (GstQueueArray *array,
+                                  gpointer p_struct);
+
+
+
+

gst_queue_array_peek_head_struct ()

+
gpointer
+gst_queue_array_peek_head_struct (GstQueueArray *array);
+

Returns the head of the queue array + without removing it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

pointer to element or struct, or NULL if array +was empty. The +data pointed to by the returned pointer stays valid only as long as +the queue array is not modified further!

+
+

Since: 1.6

+
+
+
+

gst_queue_array_pop_head_struct ()

+
gpointer
+gst_queue_array_pop_head_struct (GstQueueArray *array);
+

Returns the head of the queue array + and removes it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

pointer to element or struct, or NULL if array +was empty. The +data pointed to by the returned pointer stays valid only as long as +the queue array is not modified further!

+
+

Since: 1.6

+
+
+
+

gst_queue_array_peek_tail_struct ()

+
gpointer
+gst_queue_array_peek_tail_struct (GstQueueArray *array);
+

Returns the tail of the queue array +, but does not remove it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The tail of the queue

+
+

Since: 1.14

+
+
+
+

gst_queue_array_pop_tail_struct ()

+
gpointer
+gst_queue_array_pop_tail_struct (GstQueueArray *array);
+

Returns the tail of the queue array + and removes +it from the queue.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

array

a GstQueueArray object

 
+
+
+

Returns

+

The tail of the queue

+
+

Since: 1.14

+
+
+
+

gst_queue_array_drop_struct ()

+
gboolean
+gst_queue_array_drop_struct (GstQueueArray *array,
+                             guint idx,
+                             gpointer p_struct);
+

Drops the queue element at position idx + from queue array + and copies the +data of the element or structure that was removed into p_struct + if +p_struct + is set (not NULL).

+

[skip]

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

array

a GstQueueArray object

 

idx

index to drop

 

p_struct

address into which to store the data of the dropped structure, or NULL

 
+
+
+

Returns

+

TRUE on success, or FALSE on error

+
+

Since: 1.6

+
+
+
+

Types and Values

+
+

GstQueueArray

+
typedef struct _GstQueueArray GstQueueArray;
+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstStreamConsistency.html b/docs/libs/html/gstreamer-libs-GstStreamConsistency.html new file mode 100644 index 0000000..cc58c9d --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstStreamConsistency.html @@ -0,0 +1,222 @@ + + + + +GstStreamConsistencyChecker: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstStreamConsistencyChecker

+

GstStreamConsistencyChecker — Data flow consistency checker for GStreamer unit tests.

+
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + +
+GstStreamConsistency * + +gst_consistency_checker_new () +
+void + +gst_consistency_checker_reset () +
+void + +gst_consistency_checker_free () +
+gboolean + +gst_consistency_checker_add_pad () +
+
+
+

Types and Values

+
++++ + + + + +
 GstStreamConsistency
+
+
+

Includes

+
#include <gst/check/gstconsistencychecker.h>
+
+
+
+

Description

+

These macros and functions are for internal use of the unit tests found +inside the 'check' directories of various GStreamer packages.

+
+
+

Functions

+
+

gst_consistency_checker_new ()

+
GstStreamConsistency *
+gst_consistency_checker_new (GstPad *pad);
+

Sets up a data probe on the given pad which will raise assertions if the +data flow is inconsistent.

+

[skip]

+
+

Parameters

+
+++++ + + + + + +

pad

The GstPad on which the dataflow will be checked.

 
+
+
+

Returns

+

A GstStreamConsistency structure used to track data flow.

+
+
+
+
+

gst_consistency_checker_reset ()

+
void
+gst_consistency_checker_reset (GstStreamConsistency *consist);
+

Reset the stream checker's internal variables.

+
+

Parameters

+
+++++ + + + + + +

consist

The GstStreamConsistency to reset.

 
+
+
+
+
+

gst_consistency_checker_free ()

+
void
+gst_consistency_checker_free (GstStreamConsistency *consist);
+

Frees the allocated data and probes associated with consist +.

+
+

Parameters

+
+++++ + + + + + +

consist

The GstStreamConsistency to free.

 
+
+
+
+
+

gst_consistency_checker_add_pad ()

+
gboolean
+gst_consistency_checker_add_pad (GstStreamConsistency *consist,
+                                 GstPad *pad);
+

Sets up a data probe on the given pad which will raise assertions if the +data flow is inconsistent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

consist

The GstStreamConsistency handle

 

pad

The GstPad on which the dataflow will be checked.

 
+
+
+

Returns

+

TRUE if the pad was added

+
+
+
+
+

Types and Values

+
+

GstStreamConsistency

+
typedef struct _GstStreamConsistency GstStreamConsistency;
+

Opaque consistency checker handle.

+
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs-GstTypeFindHelper.html b/docs/libs/html/gstreamer-libs-GstTypeFindHelper.html new file mode 100644 index 0000000..b435a18 --- /dev/null +++ b/docs/libs/html/gstreamer-libs-GstTypeFindHelper.html @@ -0,0 +1,447 @@ + + + + +GstTypeFindHelper: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

GstTypeFindHelper

+

GstTypeFindHelper — Utility functions for typefinding

+
+
+

Functions

+ +
+
+

Includes

+
#include <gst/base/gsttypefindhelper.h>
+
+
+
+

Description

+

Utility functions for elements doing typefinding: +gst_type_find_helper() does typefinding in pull mode, while +gst_type_find_helper_for_buffer() is useful for elements needing to do +typefinding in push mode from a chain function.

+
+
+

Functions

+
+

gst_type_find_helper ()

+
GstCaps *
+gst_type_find_helper (GstPad *src,
+                      guint64 size);
+

Tries to find what type of data is flowing from the given source GstPad.

+

Free-function: gst_caps_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

src

A source GstPad

 

size

The length in bytes

 
+
+
+

Returns

+

the GstCaps corresponding to the data +stream. Returns NULL if no GstCaps matches the data stream.

+

[transfer full][nullable]

+
+
+
+
+

gst_type_find_helper_for_buffer ()

+
GstCaps *
+gst_type_find_helper_for_buffer (GstObject *obj,
+                                 GstBuffer *buf,
+                                 GstTypeFindProbability *prob);
+

Tries to find what type of data is contained in the given GstBuffer, the +assumption being that the buffer represents the beginning of the stream or +file.

+

All available typefinders will be called on the data in order of rank. If +a typefinding function returns a probability of GST_TYPE_FIND_MAXIMUM, +typefinding is stopped immediately and the found caps will be returned +right away. Otherwise, all available typefind functions will the tried, +and the caps with the highest probability will be returned, or NULL if +the content of the buffer could not be identified.

+

Free-function: gst_caps_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

obj

object doing the typefinding, or NULL (used for logging).

[allow-none]

buf

a GstBuffer with data to typefind.

[in][transfer none]

prob

location to store the probability of the found +caps, or NULL.

[out][allow-none]
+
+
+

Returns

+

the GstCaps corresponding to the data, +or NULL if no type could be found. The caller should free the caps +returned with gst_caps_unref().

+

[transfer full][nullable]

+
+
+
+
+

gst_type_find_helper_for_extension ()

+
GstCaps *
+gst_type_find_helper_for_extension (GstObject *obj,
+                                    const gchar *extension);
+

Tries to find the best GstCaps associated with extension +.

+

All available typefinders will be checked against the extension in order +of rank. The caps of the first typefinder that can handle extension + will be +returned.

+

Free-function: gst_caps_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

obj

object doing the typefinding, or NULL (used for logging).

[allow-none]

extension

an extension

 
+
+
+

Returns

+

the GstCaps corresponding to +extension +, or NULL if no type could be found. The caller should free +the caps returned with gst_caps_unref().

+

[transfer full][nullable]

+
+
+
+
+

gst_type_find_helper_for_data ()

+
GstCaps *
+gst_type_find_helper_for_data (GstObject *obj,
+                               const guint8 *data,
+                               gsize size,
+                               GstTypeFindProbability *prob);
+

Tries to find what type of data is contained in the given data +, the +assumption being that the data represents the beginning of the stream or +file.

+

All available typefinders will be called on the data in order of rank. If +a typefinding function returns a probability of GST_TYPE_FIND_MAXIMUM, +typefinding is stopped immediately and the found caps will be returned +right away. Otherwise, all available typefind functions will the tried, +and the caps with the highest probability will be returned, or NULL if +the content of data + could not be identified.

+

Free-function: gst_caps_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

obj

object doing the typefinding, or NULL (used for logging).

[allow-none]

data

  • a pointer with data to typefind.

[transfer none][array length=size]

size

the size of data +

 

prob

location to store the probability of the found +caps, or NULL.

[out][allow-none]
+
+
+

Returns

+

the GstCaps corresponding to the data, +or NULL if no type could be found. The caller should free the caps +returned with gst_caps_unref().

+

[transfer full][nullable]

+
+
+
+
+

GstTypeFindHelperGetRangeFunction ()

+
GstFlowReturn
+(*GstTypeFindHelperGetRangeFunction) (GstObject *obj,
+                                      GstObject *parent,
+                                      guint64 offset,
+                                      guint length,
+                                      GstBuffer **buffer);
+

This function will be called by gst_type_find_helper_get_range() when +typefinding functions request to peek at the data of a stream at certain +offsets. If this function returns GST_FLOW_OK, the result buffer will be +stored in buffer +. The contents of buffer + is invalid for any other +return value.

+

This function is supposed to behave exactly like a GstPadGetRangeFunction.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

obj

a GstObject that will handle the getrange request

 

parent

the parent of obj +or NULL.

[allow-none]

offset

the offset of the range

 

length

the length of the range

 

buffer

a memory location to hold the result buffer.

[out]
+
+
+

Returns

+

GST_FLOW_OK for success

+
+
+
+
+

gst_type_find_helper_get_range ()

+
GstCaps *
+gst_type_find_helper_get_range (GstObject *obj,
+                                GstObject *parent,
+                                GstTypeFindHelperGetRangeFunction func,
+                                guint64 size,
+                                const gchar *extension,
+                                GstTypeFindProbability *prob);
+

Utility function to do pull-based typefinding. Unlike gst_type_find_helper() +however, this function will use the specified function func + to obtain the +data needed by the typefind functions, rather than operating on a given +source pad. This is useful mostly for elements like tag demuxers which +strip off data at the beginning and/or end of a file and want to typefind +the stripped data stream before adding their own source pad (the specified +callback can then call the upstream peer pad with offsets adjusted for the +tag size, for example).

+

When extension + is not NULL, this function will first try the typefind +functions for the given extension, which might speed up the typefinding +in many cases.

+

Free-function: gst_caps_unref

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

obj

A GstObject that will be passed as first argument to func +

 

parent

the parent of obj +or NULL.

[allow-none]

func

A generic GstTypeFindHelperGetRangeFunction that will +be used to access data at random offsets when doing the typefinding.

[scope call]

size

The length in bytes

 

extension

extension of the media

 

prob

location to store the probability of the found +caps, or NULL.

[out][allow-none]
+
+
+

Returns

+

the GstCaps corresponding to the data +stream. Returns NULL if no GstCaps matches the data stream.

+

[transfer full][nullable]

+
+
+
+
+

Types and Values

+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-libs.html b/docs/libs/html/gstreamer-libs.html new file mode 100644 index 0000000..da90720 --- /dev/null +++ b/docs/libs/html/gstreamer-libs.html @@ -0,0 +1,162 @@ + + + + +Part I. GStreamer Libraries: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Part I. GStreamer Libraries

+
+

Table of Contents

+
+
GStreamer Base and Utillity Classes
+
+
+GstAggregator — Base class for mixers and muxers, manages a set of input + pads and aggregates their streams +
+
+GstAggregatorPadGstPad subclass for pads managed by GstAggregator +
+
+GstBaseParse — Base class for stream parsers +
+
+GstBaseSrc — Base class for getrange based source elements +
+
+GstBaseSink — Base class for sink elements +
+
+GstBaseTransform — Base class for simple transform filters +
+
+GstPushSrc — Base class for push based source elements +
+
+GstAdapter — adapts incoming data on a sink pad into chunks of N bytes +
+
+GstBitReader — Reads any number of bits from a memory buffer +
+
+GstByteReader — Reads different integer, string and floating point + types from a memory buffer +
+
+GstByteWriter — Writes different integer, string and floating point + types to a memory buffer and allows reading +
+
+GstCollectPads — manages a set of pads that operate in collect mode +
+
+GstFlowCombiner — Utility to combine multiple flow returns into one +
+
+GstTypeFindHelper — Utility functions for typefinding +
+
+GstDataQueue — Threadsafe queueing object +
+
+GstQueueArray — Array based queue object +
+
+
GStreamer Dynamic Parameter Control
+
+
+GstARGBControlBinding — attachment for control sources to argb properties +
+
+GstDirectControlBinding — direct attachment for control sources +
+
+GstProxyControlBinding — attachment for forwarding control sources +
+
+GstTimedValueControlSource — timed value control source base class +
+
+GstInterpolationControlSource — interpolation control source +
+
+GstLFOControlSource — LFO control source +
+
+GstTriggerControlSource — trigger control source +
+
+
GStreamer Network Classes
+
+
+GstNetAddressMeta — Network address metadata +
+
+GstNetClientClock — Special clock that synchronizes to a remote time + provider. +
+
+GstNetControlMessageMeta — Network Control Message Meta +
+
+GstNetTimePacket — Helper structure to construct clock packets used + by network clocks. +
+
+GstNetTimeProvider — Special object that exposed the time of a clock + on the network. +
+
+GstPtpClock — Special clock that synchronizes to a remote time + provider via PTP (IEEE1588:2008). +
+
+
GStreamer Check Unit Testing
+
+
+GstCheck — Common code for GStreamer unit tests +
+
+GstBufferStraw — Buffer interception code for GStreamer unit tests +
+
+GstStreamConsistencyChecker — Data flow consistency checker for GStreamer unit tests. +
+
+GstHarness — A test-harness for writing GStreamer unit tests +
+
+GstTestClock — Controllable, deterministic clock for GStreamer unit tests +
+
+
+
+

+ To ease the creation of plugins, a library system was created. The most common + functions for a plugin can be found in a library. +

+

+ GStreamer provides some standard libraries you can use to create plugins. +

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/gstreamer-net.html b/docs/libs/html/gstreamer-net.html new file mode 100644 index 0000000..f29f5ae --- /dev/null +++ b/docs/libs/html/gstreamer-net.html @@ -0,0 +1,56 @@ + + + + +GStreamer Network Classes: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+GStreamer Network Classes

+
+
+GstNetAddressMeta — Network address metadata +
+
+GstNetClientClock — Special clock that synchronizes to a remote time + provider. +
+
+GstNetControlMessageMeta — Network Control Message Meta +
+
+GstNetTimePacket — Helper structure to construct clock packets used + by network clocks. +
+
+GstNetTimeProvider — Special object that exposed the time of a clock + on the network. +
+
+GstPtpClock — Special clock that synchronizes to a remote time + provider via PTP (IEEE1588:2008). +
+
+

+ libgstnet-1.0.so provides network elements and objects. +

+
+ + + \ No newline at end of file diff --git a/docs/libs/html/home.png b/docs/libs/html/home.png new file mode 100644 index 0000000..effb5ea Binary files /dev/null and b/docs/libs/html/home.png differ diff --git a/docs/libs/html/index.html b/docs/libs/html/index.html new file mode 100644 index 0000000..6d005d3 --- /dev/null +++ b/docs/libs/html/index.html @@ -0,0 +1,168 @@ + + + + +GStreamer 1.0 Library Reference Manual: GStreamer 1.0 Library Reference Manual + + + + + + + +
+
+
+
+

+ for GStreamer Library 1.0 (1.14.1) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/. +

+
+
+
+
+
I. GStreamer Libraries
+
+
GStreamer Base and Utillity Classes
+
+
+GstAggregator — Base class for mixers and muxers, manages a set of input + pads and aggregates their streams +
+
+GstAggregatorPadGstPad subclass for pads managed by GstAggregator +
+
+GstBaseParse — Base class for stream parsers +
+
+GstBaseSrc — Base class for getrange based source elements +
+
+GstBaseSink — Base class for sink elements +
+
+GstBaseTransform — Base class for simple transform filters +
+
+GstPushSrc — Base class for push based source elements +
+
+GstAdapter — adapts incoming data on a sink pad into chunks of N bytes +
+
+GstBitReader — Reads any number of bits from a memory buffer +
+
+GstByteReader — Reads different integer, string and floating point + types from a memory buffer +
+
+GstByteWriter — Writes different integer, string and floating point + types to a memory buffer and allows reading +
+
+GstCollectPads — manages a set of pads that operate in collect mode +
+
+GstFlowCombiner — Utility to combine multiple flow returns into one +
+
+GstTypeFindHelper — Utility functions for typefinding +
+
+GstDataQueue — Threadsafe queueing object +
+
+GstQueueArray — Array based queue object +
+
+
GStreamer Dynamic Parameter Control
+
+
+GstARGBControlBinding — attachment for control sources to argb properties +
+
+GstDirectControlBinding — direct attachment for control sources +
+
+GstProxyControlBinding — attachment for forwarding control sources +
+
+GstTimedValueControlSource — timed value control source base class +
+
+GstInterpolationControlSource — interpolation control source +
+
+GstLFOControlSource — LFO control source +
+
+GstTriggerControlSource — trigger control source +
+
+
GStreamer Network Classes
+
+
+GstNetAddressMeta — Network address metadata +
+
+GstNetClientClock — Special clock that synchronizes to a remote time + provider. +
+
+GstNetControlMessageMeta — Network Control Message Meta +
+
+GstNetTimePacket — Helper structure to construct clock packets used + by network clocks. +
+
+GstNetTimeProvider — Special object that exposed the time of a clock + on the network. +
+
+GstPtpClock — Special clock that synchronizes to a remote time + provider via PTP (IEEE1588:2008). +
+
+
GStreamer Check Unit Testing
+
+
+GstCheck — Common code for GStreamer unit tests +
+
+GstBufferStraw — Buffer interception code for GStreamer unit tests +
+
+GstStreamConsistencyChecker — Data flow consistency checker for GStreamer unit tests. +
+
+GstHarness — A test-harness for writing GStreamer unit tests +
+
+GstTestClock — Controllable, deterministic clock for GStreamer unit tests +
+
+
+
Object Hierarchy
+
API Index
+
Index of deprecated API
+
Index of new API in 1.14
+
Index of new API in 1.12.1
+
Index of new API in 1.12
+
Index of new API in 1.10
+
Index of new API in 1.8
+
Index of new API in 1.6
+
Index of new API in 1.4
+
Index of new API in 1.2
+
Index of new API in 1.0.1
+
Annotation Glossary
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix01.html b/docs/libs/html/ix01.html new file mode 100644 index 0000000..23c7379 --- /dev/null +++ b/docs/libs/html/ix01.html @@ -0,0 +1,3157 @@ + + + + +API Index: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+API Index

+

A

+
+GstAdapter, struct in GstAdapter +
+
+
+gst_adapter_available, function in GstAdapter +
+
+
+gst_adapter_available_fast, function in GstAdapter +
+
+
+gst_adapter_clear, function in GstAdapter +
+
+
+gst_adapter_copy, function in GstAdapter +
+
+
+gst_adapter_copy_bytes, function in GstAdapter +
+
+
+gst_adapter_distance_from_discont, function in GstAdapter +
+
+
+gst_adapter_dts_at_discont, function in GstAdapter +
+
+
+gst_adapter_flush, function in GstAdapter +
+
+
+gst_adapter_get_buffer, function in GstAdapter +
+
+
+gst_adapter_get_buffer_fast, function in GstAdapter +
+
+
+gst_adapter_get_buffer_list, function in GstAdapter +
+
+
+gst_adapter_get_list, function in GstAdapter +
+
+
+gst_adapter_map, function in GstAdapter +
+
+
+gst_adapter_masked_scan_uint32, function in GstAdapter +
+
+
+gst_adapter_masked_scan_uint32_peek, function in GstAdapter +
+
+
+gst_adapter_new, function in GstAdapter +
+
+
+gst_adapter_offset_at_discont, function in GstAdapter +
+
+
+gst_adapter_prev_dts, function in GstAdapter +
+
+
+gst_adapter_prev_dts_at_offset, function in GstAdapter +
+
+
+gst_adapter_prev_offset, function in GstAdapter +
+
+
+gst_adapter_prev_pts, function in GstAdapter +
+
+
+gst_adapter_prev_pts_at_offset, function in GstAdapter +
+
+
+gst_adapter_pts_at_discont, function in GstAdapter +
+
+
+gst_adapter_push, function in GstAdapter +
+
+
+gst_adapter_take, function in GstAdapter +
+
+
+gst_adapter_take_buffer, function in GstAdapter +
+
+
+gst_adapter_take_buffer_fast, function in GstAdapter +
+
+
+gst_adapter_take_buffer_list, function in GstAdapter +
+
+
+gst_adapter_take_list, function in GstAdapter +
+
+
+gst_adapter_unmap, function in GstAdapter +
+
+
+GstAggregator, struct in GstAggregator +
+
+
+GstAggregator:latency, object property in GstAggregator +
+
+
+GstAggregator:start-time, object property in GstAggregator +
+
+
+GstAggregator:start-time-selection, object property in GstAggregator +
+
+
+GstAggregatorClass, struct in GstAggregator +
+
+
+GstAggregatorPad, struct in GstAggregatorPad +
+
+
+GstAggregatorPadClass, struct in GstAggregatorPad +
+
+
+gst_aggregator_finish_buffer, function in GstAggregator +
+
+
+gst_aggregator_get_allocator, function in GstAggregator +
+
+
+gst_aggregator_get_buffer_pool, function in GstAggregator +
+
+
+gst_aggregator_get_latency, function in GstAggregator +
+
+
+gst_aggregator_pad_drop_buffer, function in GstAggregatorPad +
+
+
+gst_aggregator_pad_has_buffer, function in GstAggregatorPad +
+
+
+gst_aggregator_pad_is_eos, function in GstAggregatorPad +
+
+
+gst_aggregator_pad_peek_buffer, function in GstAggregatorPad +
+
+
+gst_aggregator_pad_pop_buffer, function in GstAggregatorPad +
+
+
+gst_aggregator_set_src_caps, function in GstAggregator +
+
+
+GstARGBControlBinding:control-source-a, object property in GstARGBControlBinding +
+
+
+GstARGBControlBinding:control-source-b, object property in GstARGBControlBinding +
+
+
+GstARGBControlBinding:control-source-g, object property in GstARGBControlBinding +
+
+
+GstARGBControlBinding:control-source-r, object property in GstARGBControlBinding +
+
+
+gst_argb_control_binding_new, function in GstARGBControlBinding +
+
+
+ASSERT_BUFFER_REFCOUNT, macro in GstCheck +
+
+
+ASSERT_CAPS_REFCOUNT, macro in GstCheck +
+
+
+ASSERT_CRITICAL, macro in GstCheck +
+
+
+assert_equals_float, macro in GstCheck +
+
+
+assert_equals_int, macro in GstCheck +
+
+
+assert_equals_int64, macro in GstCheck +
+
+
+assert_equals_int64_hex, macro in GstCheck +
+
+
+assert_equals_int_hex, macro in GstCheck +
+
+
+assert_equals_pointer, macro in GstCheck +
+
+
+assert_equals_string, macro in GstCheck +
+
+
+assert_equals_uint64, macro in GstCheck +
+
+
+assert_equals_uint64_hex, macro in GstCheck +
+
+
+assert_message_error, macro in GstCheck +
+
+
+ASSERT_MINI_OBJECT_REFCOUNT, macro in GstCheck +
+
+
+ASSERT_OBJECT_REFCOUNT, macro in GstCheck +
+
+
+ASSERT_OBJECT_REFCOUNT_BETWEEN, macro in GstCheck +
+
+
+ASSERT_SET_STATE, macro in GstCheck +
+
+
+ASSERT_WARNING, macro in GstCheck +
+
+

B

+
+GstBaseParse, struct in GstBaseParse +
+
+
+GstBaseParse:disable-passthrough, object property in GstBaseParse +
+
+
+GstBaseParseClass, struct in GstBaseParse +
+
+
+GstBaseParseFrame, struct in GstBaseParse +
+
+
+GstBaseParseFrameFlags, enum in GstBaseParse +
+
+
+GstBaseSink, struct in GstBaseSink +
+
+
+GstBaseSink:async, object property in GstBaseSink +
+
+
+GstBaseSink:blocksize, object property in GstBaseSink +
+
+
+GstBaseSink:enable-last-sample, object property in GstBaseSink +
+
+
+GstBaseSink:last-sample, object property in GstBaseSink +
+
+
+GstBaseSink:max-bitrate, object property in GstBaseSink +
+
+
+GstBaseSink:max-lateness, object property in GstBaseSink +
+
+
+GstBaseSink:qos, object property in GstBaseSink +
+
+
+GstBaseSink:render-delay, object property in GstBaseSink +
+
+
+GstBaseSink:sync, object property in GstBaseSink +
+
+
+GstBaseSink:throttle-time, object property in GstBaseSink +
+
+
+GstBaseSink:ts-offset, object property in GstBaseSink +
+
+
+GstBaseSinkClass, struct in GstBaseSink +
+
+
+GstBaseSrc, struct in GstBaseSrc +
+
+
+GstBaseSrc:blocksize, object property in GstBaseSrc +
+
+
+GstBaseSrc:do-timestamp, object property in GstBaseSrc +
+
+
+GstBaseSrc:num-buffers, object property in GstBaseSrc +
+
+
+GstBaseSrc:typefind, object property in GstBaseSrc +
+
+
+GstBaseSrcClass, struct in GstBaseSrc +
+
+
+GstBaseSrcFlags, enum in GstBaseSrc +
+
+
+GstBaseTransform, struct in GstBaseTransform +
+
+
+GstBaseTransform:qos, object property in GstBaseTransform +
+
+
+GstBaseTransformClass, struct in GstBaseTransform +
+
+
+gst_base_parse_add_index_entry, function in GstBaseParse +
+
+
+gst_base_parse_convert_default, function in GstBaseParse +
+
+
+gst_base_parse_drain, function in GstBaseParse +
+
+
+GST_BASE_PARSE_DRAINING, macro in GstBaseParse +
+
+
+gst_base_parse_finish_frame, function in GstBaseParse +
+
+
+GST_BASE_PARSE_FLAG_DRAINING, macro in GstBaseParse +
+
+
+GST_BASE_PARSE_FLAG_LOST_SYNC, macro in GstBaseParse +
+
+
+GST_BASE_PARSE_FLOW_DROPPED, macro in GstBaseParse +
+
+
+gst_base_parse_frame_free, function in GstBaseParse +
+
+
+gst_base_parse_frame_init, function in GstBaseParse +
+
+
+gst_base_parse_frame_new, function in GstBaseParse +
+
+
+GST_BASE_PARSE_LOST_SYNC, macro in GstBaseParse +
+
+
+gst_base_parse_merge_tags, function in GstBaseParse +
+
+
+gst_base_parse_push_frame, function in GstBaseParse +
+
+
+gst_base_parse_set_average_bitrate, function in GstBaseParse +
+
+
+gst_base_parse_set_duration, function in GstBaseParse +
+
+
+gst_base_parse_set_frame_rate, function in GstBaseParse +
+
+
+gst_base_parse_set_has_timing_info, function in GstBaseParse +
+
+
+gst_base_parse_set_infer_ts, function in GstBaseParse +
+
+
+gst_base_parse_set_latency, function in GstBaseParse +
+
+
+gst_base_parse_set_min_frame_size, function in GstBaseParse +
+
+
+gst_base_parse_set_passthrough, function in GstBaseParse +
+
+
+gst_base_parse_set_pts_interpolation, function in GstBaseParse +
+
+
+gst_base_parse_set_syncable, function in GstBaseParse +
+
+
+gst_base_parse_set_ts_at_offset, function in GstBaseParse +
+
+
+GST_BASE_PARSE_SINK_PAD, macro in GstBaseParse +
+
+
+GST_BASE_PARSE_SRC_PAD, macro in GstBaseParse +
+
+
+gst_base_sink_do_preroll, function in GstBaseSink +
+
+
+gst_base_sink_get_blocksize, function in GstBaseSink +
+
+
+gst_base_sink_get_last_sample, function in GstBaseSink +
+
+
+gst_base_sink_get_latency, function in GstBaseSink +
+
+
+gst_base_sink_get_max_bitrate, function in GstBaseSink +
+
+
+gst_base_sink_get_max_lateness, function in GstBaseSink +
+
+
+GST_BASE_SINK_GET_PREROLL_COND, macro in GstBaseSink +
+
+
+GST_BASE_SINK_GET_PREROLL_LOCK, macro in GstBaseSink +
+
+
+gst_base_sink_get_render_delay, function in GstBaseSink +
+
+
+gst_base_sink_get_sync, function in GstBaseSink +
+
+
+gst_base_sink_get_throttle_time, function in GstBaseSink +
+
+
+gst_base_sink_get_ts_offset, function in GstBaseSink +
+
+
+gst_base_sink_is_async_enabled, function in GstBaseSink +
+
+
+gst_base_sink_is_last_sample_enabled, function in GstBaseSink +
+
+
+gst_base_sink_is_qos_enabled, function in GstBaseSink +
+
+
+GST_BASE_SINK_PAD, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_BROADCAST, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_LOCK, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_SIGNAL, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_TRYLOCK, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_UNLOCK, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_WAIT, macro in GstBaseSink +
+
+
+GST_BASE_SINK_PREROLL_WAIT_UNTIL, macro in GstBaseSink +
+
+
+gst_base_sink_query_latency, function in GstBaseSink +
+
+
+gst_base_sink_set_async_enabled, function in GstBaseSink +
+
+
+gst_base_sink_set_blocksize, function in GstBaseSink +
+
+
+gst_base_sink_set_last_sample_enabled, function in GstBaseSink +
+
+
+gst_base_sink_set_max_bitrate, function in GstBaseSink +
+
+
+gst_base_sink_set_max_lateness, function in GstBaseSink +
+
+
+gst_base_sink_set_qos_enabled, function in GstBaseSink +
+
+
+gst_base_sink_set_render_delay, function in GstBaseSink +
+
+
+gst_base_sink_set_sync, function in GstBaseSink +
+
+
+gst_base_sink_set_throttle_time, function in GstBaseSink +
+
+
+gst_base_sink_set_ts_offset, function in GstBaseSink +
+
+
+gst_base_sink_wait, function in GstBaseSink +
+
+
+gst_base_sink_wait_clock, function in GstBaseSink +
+
+
+gst_base_sink_wait_preroll, function in GstBaseSink +
+
+
+gst_base_src_get_allocator, function in GstBaseSrc +
+
+
+gst_base_src_get_blocksize, function in GstBaseSrc +
+
+
+gst_base_src_get_buffer_pool, function in GstBaseSrc +
+
+
+gst_base_src_get_do_timestamp, function in GstBaseSrc +
+
+
+gst_base_src_is_async, function in GstBaseSrc +
+
+
+gst_base_src_is_live, function in GstBaseSrc +
+
+
+GST_BASE_SRC_IS_STARTED, macro in GstBaseSrc +
+
+
+GST_BASE_SRC_IS_STARTING, macro in GstBaseSrc +
+
+
+gst_base_src_new_seamless_segment, function in GstBaseSrc +
+
+
+GST_BASE_SRC_PAD, macro in GstBaseSrc +
+
+
+gst_base_src_query_latency, function in GstBaseSrc +
+
+
+gst_base_src_set_async, function in GstBaseSrc +
+
+
+gst_base_src_set_automatic_eos, function in GstBaseSrc +
+
+
+gst_base_src_set_blocksize, function in GstBaseSrc +
+
+
+gst_base_src_set_caps, function in GstBaseSrc +
+
+
+gst_base_src_set_do_timestamp, function in GstBaseSrc +
+
+
+gst_base_src_set_dynamic_size, function in GstBaseSrc +
+
+
+gst_base_src_set_format, function in GstBaseSrc +
+
+
+gst_base_src_set_live, function in GstBaseSrc +
+
+
+gst_base_src_start_complete, function in GstBaseSrc +
+
+
+gst_base_src_start_wait, function in GstBaseSrc +
+
+
+gst_base_src_submit_buffer_list, function in GstBaseSrc +
+
+
+gst_base_src_wait_playing, function in GstBaseSrc +
+
+
+GST_BASE_TRANSFORM_FLOW_DROPPED, macro in GstBaseTransform +
+
+
+gst_base_transform_get_allocator, function in GstBaseTransform +
+
+
+gst_base_transform_get_buffer_pool, function in GstBaseTransform +
+
+
+gst_base_transform_is_in_place, function in GstBaseTransform +
+
+
+gst_base_transform_is_passthrough, function in GstBaseTransform +
+
+
+gst_base_transform_is_qos_enabled, function in GstBaseTransform +
+
+
+gst_base_transform_reconfigure_sink, function in GstBaseTransform +
+
+
+gst_base_transform_reconfigure_src, function in GstBaseTransform +
+
+
+gst_base_transform_set_gap_aware, function in GstBaseTransform +
+
+
+gst_base_transform_set_in_place, function in GstBaseTransform +
+
+
+gst_base_transform_set_passthrough, function in GstBaseTransform +
+
+
+gst_base_transform_set_prefer_passthrough, function in GstBaseTransform +
+
+
+gst_base_transform_set_qos_enabled, function in GstBaseTransform +
+
+
+GST_BASE_TRANSFORM_SINK_NAME, macro in GstBaseTransform +
+
+
+GST_BASE_TRANSFORM_SINK_PAD, macro in GstBaseTransform +
+
+
+GST_BASE_TRANSFORM_SRC_NAME, macro in GstBaseTransform +
+
+
+GST_BASE_TRANSFORM_SRC_PAD, macro in GstBaseTransform +
+
+
+gst_base_transform_update_qos, function in GstBaseTransform +
+
+
+gst_base_transform_update_src_caps, function in GstBaseTransform +
+
+
+GstBitReader, struct in GstBitReader +
+
+
+gst_bit_reader_free, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint16, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint16_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint32, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint32_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint64, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint64_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint8, function in GstBitReader +
+
+
+gst_bit_reader_get_bits_uint8_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_get_pos, function in GstBitReader +
+
+
+gst_bit_reader_get_remaining, function in GstBitReader +
+
+
+gst_bit_reader_get_size, function in GstBitReader +
+
+
+GST_BIT_READER_INIT, macro in GstBitReader +
+
+
+gst_bit_reader_init, function in GstBitReader +
+
+
+gst_bit_reader_new, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint16, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint16_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint32, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint32_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint64, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint64_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint8, function in GstBitReader +
+
+
+gst_bit_reader_peek_bits_uint8_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_set_pos, function in GstBitReader +
+
+
+gst_bit_reader_skip, function in GstBitReader +
+
+
+gst_bit_reader_skip_to_byte, function in GstBitReader +
+
+
+gst_bit_reader_skip_to_byte_unchecked, function in GstBitReader +
+
+
+gst_bit_reader_skip_unchecked, function in GstBitReader +
+
+
+gst_buffer_add_net_address_meta, function in GstNetAddressMeta +
+
+
+gst_buffer_add_net_control_message_meta, function in GstNetControlMessageMeta +
+
+
+gst_buffer_get_net_address_meta, function in GstNetAddressMeta +
+
+
+gst_buffer_get_net_control_message_meta, macro in GstNetControlMessageMeta +
+
+
+gst_buffer_straw_get_buffer, function in GstBufferStraw +
+
+
+gst_buffer_straw_start_pipeline, function in GstBufferStraw +
+
+
+gst_buffer_straw_stop_pipeline, function in GstBufferStraw +
+
+
+GstByteReader, struct in GstByteReader +
+
+
+GstByteWriter, struct in GstByteWriter +
+
+
+gst_byte_reader_dup_data, function in GstByteReader +
+
+
+gst_byte_reader_dup_data_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_dup_string, macro in GstByteReader +
+
+
+gst_byte_reader_dup_string_utf16, function in GstByteReader +
+
+
+gst_byte_reader_dup_string_utf32, function in GstByteReader +
+
+
+gst_byte_reader_dup_string_utf8, function in GstByteReader +
+
+
+gst_byte_reader_free, function in GstByteReader +
+
+
+gst_byte_reader_get_data, function in GstByteReader +
+
+
+gst_byte_reader_get_data_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_float32_be, function in GstByteReader +
+
+
+gst_byte_reader_get_float32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_float32_le, function in GstByteReader +
+
+
+gst_byte_reader_get_float32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_float64_be, function in GstByteReader +
+
+
+gst_byte_reader_get_float64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_float64_le, function in GstByteReader +
+
+
+gst_byte_reader_get_float64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int16_be, function in GstByteReader +
+
+
+gst_byte_reader_get_int16_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int16_le, function in GstByteReader +
+
+
+gst_byte_reader_get_int16_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int24_be, function in GstByteReader +
+
+
+gst_byte_reader_get_int24_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int24_le, function in GstByteReader +
+
+
+gst_byte_reader_get_int24_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int32_be, function in GstByteReader +
+
+
+gst_byte_reader_get_int32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int32_le, function in GstByteReader +
+
+
+gst_byte_reader_get_int32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int64_be, function in GstByteReader +
+
+
+gst_byte_reader_get_int64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int64_le, function in GstByteReader +
+
+
+gst_byte_reader_get_int64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_int8, function in GstByteReader +
+
+
+gst_byte_reader_get_int8_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_pos, function in GstByteReader +
+
+
+gst_byte_reader_get_remaining, function in GstByteReader +
+
+
+gst_byte_reader_get_size, function in GstByteReader +
+
+
+gst_byte_reader_get_string, macro in GstByteReader +
+
+
+gst_byte_reader_get_string_utf8, function in GstByteReader +
+
+
+gst_byte_reader_get_sub_reader, function in GstByteReader +
+
+
+gst_byte_reader_get_uint16_be, function in GstByteReader +
+
+
+gst_byte_reader_get_uint16_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint16_le, function in GstByteReader +
+
+
+gst_byte_reader_get_uint16_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint24_be, function in GstByteReader +
+
+
+gst_byte_reader_get_uint24_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint24_le, function in GstByteReader +
+
+
+gst_byte_reader_get_uint24_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint32_be, function in GstByteReader +
+
+
+gst_byte_reader_get_uint32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint32_le, function in GstByteReader +
+
+
+gst_byte_reader_get_uint32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint64_be, function in GstByteReader +
+
+
+gst_byte_reader_get_uint64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint64_le, function in GstByteReader +
+
+
+gst_byte_reader_get_uint64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_get_uint8, function in GstByteReader +
+
+
+gst_byte_reader_get_uint8_unchecked, function in GstByteReader +
+
+
+GST_BYTE_READER_INIT, macro in GstByteReader +
+
+
+gst_byte_reader_init, function in GstByteReader +
+
+
+gst_byte_reader_masked_scan_uint32, function in GstByteReader +
+
+
+gst_byte_reader_masked_scan_uint32_peek, function in GstByteReader +
+
+
+gst_byte_reader_new, function in GstByteReader +
+
+
+gst_byte_reader_peek_data, function in GstByteReader +
+
+
+gst_byte_reader_peek_data_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_float32_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_float32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_float32_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_float32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_float64_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_float64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_float64_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_float64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int16_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_int16_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int16_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_int16_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int24_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_int24_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int24_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_int24_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int32_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_int32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int32_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_int32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int64_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_int64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int64_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_int64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_int8, function in GstByteReader +
+
+
+gst_byte_reader_peek_int8_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_string, macro in GstByteReader +
+
+
+gst_byte_reader_peek_string_utf8, function in GstByteReader +
+
+
+gst_byte_reader_peek_sub_reader, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint16_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint16_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint16_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint16_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint24_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint24_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint24_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint24_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint32_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint32_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint32_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint32_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint64_be, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint64_be_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint64_le, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint64_le_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint8, function in GstByteReader +
+
+
+gst_byte_reader_peek_uint8_unchecked, function in GstByteReader +
+
+
+gst_byte_reader_set_pos, function in GstByteReader +
+
+
+gst_byte_reader_skip, function in GstByteReader +
+
+
+gst_byte_reader_skip_string, macro in GstByteReader +
+
+
+gst_byte_reader_skip_string_utf16, function in GstByteReader +
+
+
+gst_byte_reader_skip_string_utf32, function in GstByteReader +
+
+
+gst_byte_reader_skip_string_utf8, function in GstByteReader +
+
+
+gst_byte_reader_skip_unchecked, function in GstByteReader +
+
+
+gst_byte_writer_ensure_free_space, function in GstByteWriter +
+
+
+gst_byte_writer_fill, function in GstByteWriter +
+
+
+gst_byte_writer_fill_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_free, function in GstByteWriter +
+
+
+gst_byte_writer_free_and_get_buffer, function in GstByteWriter +
+
+
+gst_byte_writer_free_and_get_data, function in GstByteWriter +
+
+
+gst_byte_writer_get_pos, function in GstByteWriter +
+
+
+gst_byte_writer_get_remaining, function in GstByteWriter +
+
+
+gst_byte_writer_get_size, function in GstByteWriter +
+
+
+gst_byte_writer_init, function in GstByteWriter +
+
+
+gst_byte_writer_init_with_data, function in GstByteWriter +
+
+
+gst_byte_writer_init_with_size, function in GstByteWriter +
+
+
+gst_byte_writer_new, function in GstByteWriter +
+
+
+gst_byte_writer_new_with_data, function in GstByteWriter +
+
+
+gst_byte_writer_new_with_size, function in GstByteWriter +
+
+
+gst_byte_writer_put_buffer, function in GstByteWriter +
+
+
+gst_byte_writer_put_buffer_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_data, function in GstByteWriter +
+
+
+gst_byte_writer_put_data_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_float32_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_float32_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_float32_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_float32_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_float64_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_float64_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_float64_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_float64_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int16_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_int16_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int16_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_int16_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int24_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_int24_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int24_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_int24_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int32_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_int32_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int32_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_int32_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int64_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_int64_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int64_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_int64_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_int8, function in GstByteWriter +
+
+
+gst_byte_writer_put_int8_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_string, macro in GstByteWriter +
+
+
+gst_byte_writer_put_string_utf16, function in GstByteWriter +
+
+
+gst_byte_writer_put_string_utf32, function in GstByteWriter +
+
+
+gst_byte_writer_put_string_utf8, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint16_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint16_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint16_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint16_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint24_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint24_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint24_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint24_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint32_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint32_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint32_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint32_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint64_be, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint64_be_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint64_le, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint64_le_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint8, function in GstByteWriter +
+
+
+gst_byte_writer_put_uint8_unchecked, function in GstByteWriter +
+
+
+gst_byte_writer_reset, function in GstByteWriter +
+
+
+gst_byte_writer_reset_and_get_buffer, function in GstByteWriter +
+
+
+gst_byte_writer_reset_and_get_data, function in GstByteWriter +
+
+
+gst_byte_writer_set_pos, function in GstByteWriter +
+
+

C

+
+gst_check_buffer_data, function in GstCheck +
+
+
+gst_check_caps_equal, function in GstCheck +
+
+
+gst_check_drop_buffers, function in GstCheck +
+
+
+gst_check_element_push_buffer, function in GstCheck +
+
+
+gst_check_element_push_buffer_list, function in GstCheck +
+
+
+gst_check_init, function in GstCheck +
+
+
+gst_check_message_error, function in GstCheck +
+
+
+gst_check_objects_destroyed_on_unref, function in GstCheck +
+
+
+gst_check_object_destroyed_on_unref, function in GstCheck +
+
+
+gst_check_run_suite, function in GstCheck +
+
+
+gst_check_setup_element, function in GstCheck +
+
+
+gst_check_setup_events, function in GstCheck +
+
+
+gst_check_setup_events_with_stream_id, function in GstCheck +
+
+
+gst_check_setup_sink_pad, function in GstCheck +
+
+
+gst_check_setup_sink_pad_by_name, function in GstCheck +
+
+
+gst_check_setup_sink_pad_by_name_from_template, function in GstCheck +
+
+
+gst_check_setup_sink_pad_from_template, function in GstCheck +
+
+
+gst_check_setup_src_pad, function in GstCheck +
+
+
+gst_check_setup_src_pad_by_name, function in GstCheck +
+
+
+gst_check_setup_src_pad_by_name_from_template, function in GstCheck +
+
+
+gst_check_setup_src_pad_from_template, function in GstCheck +
+
+
+gst_check_teardown_element, function in GstCheck +
+
+
+gst_check_teardown_pad_by_name, function in GstCheck +
+
+
+gst_check_teardown_sink_pad, function in GstCheck +
+
+
+gst_check_teardown_src_pad, function in GstCheck +
+
+
+GstCollectData, struct in GstCollectPads +
+
+
+GstCollectDataDestroyNotify, user_function in GstCollectPads +
+
+
+GstCollectPads, struct in GstCollectPads +
+
+
+GstCollectPadsBufferFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsClipFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsCompareFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsEventFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsFlushFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsQueryFunction, user_function in GstCollectPads +
+
+
+GstCollectPadsStateFlags, enum in GstCollectPads +
+
+
+gst_collect_pads_add_pad, function in GstCollectPads +
+
+
+gst_collect_pads_available, function in GstCollectPads +
+
+
+gst_collect_pads_clip_running_time, function in GstCollectPads +
+
+
+GST_COLLECT_PADS_DTS, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_DTS_IS_VALID, macro in GstCollectPads +
+
+
+gst_collect_pads_event_default, function in GstCollectPads +
+
+
+gst_collect_pads_flush, function in GstCollectPads +
+
+
+GST_COLLECT_PADS_GET_STREAM_LOCK, macro in GstCollectPads +
+
+
+gst_collect_pads_new, function in GstCollectPads +
+
+
+gst_collect_pads_peek, function in GstCollectPads +
+
+
+gst_collect_pads_pop, function in GstCollectPads +
+
+
+gst_collect_pads_query_default, function in GstCollectPads +
+
+
+gst_collect_pads_read_buffer, function in GstCollectPads +
+
+
+gst_collect_pads_remove_pad, function in GstCollectPads +
+
+
+gst_collect_pads_set_buffer_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_clip_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_compare_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_event_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_flushing, function in GstCollectPads +
+
+
+gst_collect_pads_set_flush_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_query_function, function in GstCollectPads +
+
+
+gst_collect_pads_set_waiting, function in GstCollectPads +
+
+
+gst_collect_pads_src_event_default, function in GstCollectPads +
+
+
+gst_collect_pads_start, function in GstCollectPads +
+
+
+GST_COLLECT_PADS_STATE, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_STATE_IS_SET, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_STATE_SET, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_STATE_UNSET, macro in GstCollectPads +
+
+
+gst_collect_pads_stop, function in GstCollectPads +
+
+
+GST_COLLECT_PADS_STREAM_LOCK, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_STREAM_UNLOCK, macro in GstCollectPads +
+
+
+gst_collect_pads_take_buffer, function in GstCollectPads +
+
+
+gst_consistency_checker_add_pad, function in GstStreamConsistency +
+
+
+gst_consistency_checker_free, function in GstStreamConsistency +
+
+
+gst_consistency_checker_new, function in GstStreamConsistency +
+
+
+gst_consistency_checker_reset, function in GstStreamConsistency +
+
+
+GstControlPoint, struct in GstTimedValueControlSource +
+
+

D

+
+GstDataQueue, struct in GstDataQueue +
+
+
+GstDataQueueCheckFullFunction, user_function in GstDataQueue +
+
+
+GstDataQueueEmptyCallback, user_function in GstDataQueue +
+
+
+GstDataQueueFullCallback, user_function in GstDataQueue +
+
+
+GstDataQueueItem, struct in GstDataQueue +
+
+
+GstDataQueueSize, struct in GstDataQueue +
+
+
+gst_data_queue_drop_head, function in GstDataQueue +
+
+
+gst_data_queue_flush, function in GstDataQueue +
+
+
+gst_data_queue_get_level, function in GstDataQueue +
+
+
+gst_data_queue_is_empty, function in GstDataQueue +
+
+
+gst_data_queue_is_full, function in GstDataQueue +
+
+
+gst_data_queue_limits_changed, function in GstDataQueue +
+
+
+gst_data_queue_new, function in GstDataQueue +
+
+
+gst_data_queue_peek, function in GstDataQueue +
+
+
+gst_data_queue_pop, function in GstDataQueue +
+
+
+gst_data_queue_push, function in GstDataQueue +
+
+
+gst_data_queue_push_force, function in GstDataQueue +
+
+
+gst_data_queue_set_flushing, function in GstDataQueue +
+
+
+GstDirectControlBinding:absolute, object property in GstDirectControlBinding +
+
+
+GstDirectControlBinding:control-source, object property in GstDirectControlBinding +
+
+
+gst_direct_control_binding_new, function in GstDirectControlBinding +
+
+
+gst_direct_control_binding_new_absolute, function in GstDirectControlBinding +
+
+

E

+
+GST_END_TEST, macro in GstCheck +
+
+

F

+
+fail_unless_equals_float, macro in GstCheck +
+
+
+fail_unless_equals_int, macro in GstCheck +
+
+
+fail_unless_equals_int64, macro in GstCheck +
+
+
+fail_unless_equals_int64_hex, macro in GstCheck +
+
+
+fail_unless_equals_int_hex, macro in GstCheck +
+
+
+fail_unless_equals_pointer, macro in GstCheck +
+
+
+fail_unless_equals_string, macro in GstCheck +
+
+
+fail_unless_equals_uint64, macro in GstCheck +
+
+
+fail_unless_equals_uint64_hex, macro in GstCheck +
+
+
+fail_unless_message_error, macro in GstCheck +
+
+
+GstFlowCombiner, struct in GstFlowCombiner +
+
+
+gst_flow_combiner_add_pad, function in GstFlowCombiner +
+
+
+gst_flow_combiner_clear, function in GstFlowCombiner +
+
+
+gst_flow_combiner_free, function in GstFlowCombiner +
+
+
+gst_flow_combiner_new, function in GstFlowCombiner +
+
+
+gst_flow_combiner_ref, function in GstFlowCombiner +
+
+
+gst_flow_combiner_remove_pad, function in GstFlowCombiner +
+
+
+gst_flow_combiner_reset, function in GstFlowCombiner +
+
+
+gst_flow_combiner_unref, function in GstFlowCombiner +
+
+
+gst_flow_combiner_update_flow, function in GstFlowCombiner +
+
+
+gst_flow_combiner_update_pad_flow, function in GstFlowCombiner +
+
+

H

+
+GstHarness, struct in GstHarness +
+
+
+GstHarnessPrepareBufferFunc, user_function in GstHarness +
+
+
+GstHarnessPrepareEventFunc, user_function in GstHarness +
+
+
+GstHarnessThread, struct in GstHarness +
+
+
+gst_harness_add_element_full, function in GstHarness +
+
+
+gst_harness_add_element_sink_pad, function in GstHarness +
+
+
+gst_harness_add_element_src_pad, function in GstHarness +
+
+
+gst_harness_add_parse, function in GstHarness +
+
+
+gst_harness_add_probe, function in GstHarness +
+
+
+gst_harness_add_sink, function in GstHarness +
+
+
+gst_harness_add_sink_harness, function in GstHarness +
+
+
+gst_harness_add_sink_parse, function in GstHarness +
+
+
+gst_harness_add_src, function in GstHarness +
+
+
+gst_harness_add_src_harness, function in GstHarness +
+
+
+gst_harness_add_src_parse, function in GstHarness +
+
+
+gst_harness_buffers_in_queue, function in GstHarness +
+
+
+gst_harness_buffers_received, function in GstHarness +
+
+
+gst_harness_crank_multiple_clock_waits, function in GstHarness +
+
+
+gst_harness_crank_single_clock_wait, function in GstHarness +
+
+
+gst_harness_create_buffer, function in GstHarness +
+
+
+gst_harness_dump_to_file, function in GstHarness +
+
+
+gst_harness_events_in_queue, function in GstHarness +
+
+
+gst_harness_events_received, function in GstHarness +
+
+
+gst_harness_find_element, function in GstHarness +
+
+
+gst_harness_get, function in GstHarness +
+
+
+gst_harness_get_allocator, function in GstHarness +
+
+
+gst_harness_get_last_pushed_timestamp, function in GstHarness +
+
+
+gst_harness_get_testclock, function in GstHarness +
+
+
+gst_harness_new, function in GstHarness +
+
+
+gst_harness_new_empty, function in GstHarness +
+
+
+gst_harness_new_full, function in GstHarness +
+
+
+gst_harness_new_parse, function in GstHarness +
+
+
+gst_harness_new_with_element, function in GstHarness +
+
+
+gst_harness_new_with_padnames, function in GstHarness +
+
+
+gst_harness_new_with_templates, function in GstHarness +
+
+
+gst_harness_play, function in GstHarness +
+
+
+gst_harness_pull, function in GstHarness +
+
+
+gst_harness_pull_event, function in GstHarness +
+
+
+gst_harness_pull_upstream_event, function in GstHarness +
+
+
+gst_harness_push, function in GstHarness +
+
+
+gst_harness_push_and_pull, function in GstHarness +
+
+
+gst_harness_push_event, function in GstHarness +
+
+
+gst_harness_push_from_src, function in GstHarness +
+
+
+gst_harness_push_to_sink, function in GstHarness +
+
+
+gst_harness_push_upstream_event, function in GstHarness +
+
+
+gst_harness_query_latency, function in GstHarness +
+
+
+gst_harness_set, function in GstHarness +
+
+
+gst_harness_set_blocking_push_mode, function in GstHarness +
+
+
+gst_harness_set_caps, function in GstHarness +
+
+
+gst_harness_set_caps_str, function in GstHarness +
+
+
+gst_harness_set_drop_buffers, function in GstHarness +
+
+
+gst_harness_set_forwarding, function in GstHarness +
+
+
+gst_harness_set_propose_allocator, function in GstHarness +
+
+
+gst_harness_set_sink_caps, function in GstHarness +
+
+
+gst_harness_set_sink_caps_str, function in GstHarness +
+
+
+gst_harness_set_src_caps, function in GstHarness +
+
+
+gst_harness_set_src_caps_str, function in GstHarness +
+
+
+gst_harness_set_time, function in GstHarness +
+
+
+gst_harness_set_upstream_latency, function in GstHarness +
+
+
+gst_harness_sink_push_many, function in GstHarness +
+
+
+gst_harness_src_crank_and_push_many, function in GstHarness +
+
+
+gst_harness_src_push_event, function in GstHarness +
+
+
+gst_harness_stress_custom_start, function in GstHarness +
+
+
+gst_harness_stress_property_start, macro in GstHarness +
+
+
+gst_harness_stress_property_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_buffer_start, macro in GstHarness +
+
+
+gst_harness_stress_push_buffer_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_buffer_with_cb_start, macro in GstHarness +
+
+
+gst_harness_stress_push_buffer_with_cb_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_event_start, macro in GstHarness +
+
+
+gst_harness_stress_push_event_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_event_with_cb_start, macro in GstHarness +
+
+
+gst_harness_stress_push_event_with_cb_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_upstream_event_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_upstream_event_with_cb_start_full, function in GstHarness +
+
+
+gst_harness_stress_requestpad_start, macro in GstHarness +
+
+
+gst_harness_stress_requestpad_start_full, function in GstHarness +
+
+
+gst_harness_stress_send_upstream_event_start, macro in GstHarness +
+
+
+gst_harness_stress_send_upstream_event_with_cb_start, macro in GstHarness +
+
+
+gst_harness_stress_statechange_start, macro in GstHarness +
+
+
+gst_harness_stress_statechange_start_full, function in GstHarness +
+
+
+gst_harness_stress_thread_stop, function in GstHarness +
+
+
+gst_harness_take_all_data, function in GstHarness +
+
+
+gst_harness_take_all_data_as_buffer, function in GstHarness +
+
+
+gst_harness_take_all_data_as_bytes, function in GstHarness +
+
+
+gst_harness_teardown, function in GstHarness +
+
+
+gst_harness_try_pull, function in GstHarness +
+
+
+gst_harness_try_pull_event, function in GstHarness +
+
+
+gst_harness_try_pull_upstream_event, function in GstHarness +
+
+
+gst_harness_upstream_events_in_queue, function in GstHarness +
+
+
+gst_harness_upstream_events_received, function in GstHarness +
+
+
+gst_harness_use_systemclock, function in GstHarness +
+
+
+gst_harness_use_testclock, function in GstHarness +
+
+
+gst_harness_wait_for_clock_id_waits, function in GstHarness +
+
+

I

+
+GstInterpolationControlSource, struct in GstInterpolationControlSource +
+
+
+GstInterpolationControlSource:mode, object property in GstInterpolationControlSource +
+
+
+GstInterpolationMode, enum in GstInterpolationControlSource +
+
+
+gst_interpolation_control_source_new, function in GstInterpolationControlSource +
+
+

L

+
+GstLFOControlSource, struct in GstLFOControlSource +
+
+
+GstLFOControlSource:amplitude, object property in GstLFOControlSource +
+
+
+GstLFOControlSource:frequency, object property in GstLFOControlSource +
+
+
+GstLFOControlSource:offset, object property in GstLFOControlSource +
+
+
+GstLFOControlSource:timeshift, object property in GstLFOControlSource +
+
+
+GstLFOControlSource:waveform, object property in GstLFOControlSource +
+
+
+GstLFOWaveform, enum in GstLFOControlSource +
+
+
+gst_lfo_control_source_new, function in GstLFOControlSource +
+
+

N

+
+GstNetAddressMeta, struct in GstNetAddressMeta +
+
+
+GstNetClientClock, struct in GstNetClientClock +
+
+
+GstNetClientClock:address, object property in GstNetClientClock +
+
+
+GstNetClientClock:base-time, object property in GstNetClientClock +
+
+
+GstNetClientClock:bus, object property in GstNetClientClock +
+
+
+GstNetClientClock:internal-clock, object property in GstNetClientClock +
+
+
+GstNetClientClock:minimum-update-interval, object property in GstNetClientClock +
+
+
+GstNetClientClock:port, object property in GstNetClientClock +
+
+
+GstNetClientClock:qos-dscp, object property in GstNetClientClock +
+
+
+GstNetClientClock:round-trip-limit, object property in GstNetClientClock +
+
+
+GstNetControlMessageMeta, struct in GstNetControlMessageMeta +
+
+
+GstNetTimePacket, struct in GstNetTimePacket +
+
+
+GstNetTimeProvider, struct in GstNetTimeProvider +
+
+
+GstNetTimeProvider:active, object property in GstNetTimeProvider +
+
+
+GstNetTimeProvider:address, object property in GstNetTimeProvider +
+
+
+GstNetTimeProvider:clock, object property in GstNetTimeProvider +
+
+
+GstNetTimeProvider:port, object property in GstNetTimeProvider +
+
+
+GstNetTimeProvider:qos-dscp, object property in GstNetTimeProvider +
+
+
+gst_net_address_meta_get_info, function in GstNetAddressMeta +
+
+
+gst_net_client_clock_new, function in GstNetClientClock +
+
+
+gst_net_control_message_meta_get_info, function in GstNetControlMessageMeta +
+
+
+gst_net_time_packet_copy, function in GstNetTimePacket +
+
+
+gst_net_time_packet_free, function in GstNetTimePacket +
+
+
+gst_net_time_packet_new, function in GstNetTimePacket +
+
+
+gst_net_time_packet_receive, function in GstNetTimePacket +
+
+
+gst_net_time_packet_send, function in GstNetTimePacket +
+
+
+gst_net_time_packet_serialize, function in GstNetTimePacket +
+
+
+GST_NET_TIME_PACKET_SIZE, macro in GstNetTimePacket +
+
+
+gst_net_time_provider_new, function in GstNetTimeProvider +
+
+
+GstNtpClock, typedef in GstNetClientClock +
+
+
+gst_ntp_clock_new, function in GstNetClientClock +
+
+

P

+
+gst_proxy_control_binding_new, function in GstProxyControlBinding +
+
+
+GstPtpClock, struct in GstPtpClock +
+
+
+GstPtpClock:domain, object property in GstPtpClock +
+
+
+GstPtpClock:grandmaster-clock-id, object property in GstPtpClock +
+
+
+GstPtpClock:internal-clock, object property in GstPtpClock +
+
+
+GstPtpClock:master-clock-id, object property in GstPtpClock +
+
+
+GstPtpStatisticsCallback, user_function in GstPtpClock +
+
+
+GST_PTP_CLOCK_ID_NONE, macro in GstPtpClock +
+
+
+gst_ptp_clock_new, function in GstPtpClock +
+
+
+gst_ptp_deinit, function in GstPtpClock +
+
+
+gst_ptp_init, function in GstPtpClock +
+
+
+gst_ptp_is_initialized, function in GstPtpClock +
+
+
+gst_ptp_is_supported, function in GstPtpClock +
+
+
+GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED, macro in GstPtpClock +
+
+
+gst_ptp_statistics_callback_add, function in GstPtpClock +
+
+
+gst_ptp_statistics_callback_remove, function in GstPtpClock +
+
+
+GST_PTP_STATISTICS_NEW_DOMAIN_FOUND, macro in GstPtpClock +
+
+
+GST_PTP_STATISTICS_PATH_DELAY_MEASURED, macro in GstPtpClock +
+
+
+GST_PTP_STATISTICS_TIME_UPDATED, macro in GstPtpClock +
+
+
+GstPushSrc, struct in GstPushSrc +
+
+
+GstPushSrcClass, struct in GstPushSrc +
+
+

Q

+
+GstQueueArray, struct in GstQueueArray +
+
+
+gst_queue_array_drop_element, function in GstQueueArray +
+
+
+gst_queue_array_drop_struct, function in GstQueueArray +
+
+
+gst_queue_array_find, function in GstQueueArray +
+
+
+gst_queue_array_free, function in GstQueueArray +
+
+
+gst_queue_array_get_length, function in GstQueueArray +
+
+
+gst_queue_array_is_empty, function in GstQueueArray +
+
+
+gst_queue_array_new, function in GstQueueArray +
+
+
+gst_queue_array_new_for_struct, function in GstQueueArray +
+
+
+gst_queue_array_peek_head, function in GstQueueArray +
+
+
+gst_queue_array_peek_head_struct, function in GstQueueArray +
+
+
+gst_queue_array_peek_tail, function in GstQueueArray +
+
+
+gst_queue_array_peek_tail_struct, function in GstQueueArray +
+
+
+gst_queue_array_pop_head, function in GstQueueArray +
+
+
+gst_queue_array_pop_head_struct, function in GstQueueArray +
+
+
+gst_queue_array_pop_tail, function in GstQueueArray +
+
+
+gst_queue_array_pop_tail_struct, function in GstQueueArray +
+
+
+gst_queue_array_push_tail, function in GstQueueArray +
+
+
+gst_queue_array_push_tail_struct, function in GstQueueArray +
+
+

S

+
+GST_START_TEST, macro in GstCheck +
+
+
+GstStreamConsistency, struct in GstStreamConsistency +
+
+

T

+
+GstTestClock, struct in GstTestClock +
+
+
+GstTestClock:clock-type, object property in GstTestClock +
+
+
+GstTestClock:start-time, object property in GstTestClock +
+
+
+GstTestClockClass, struct in GstTestClock +
+
+
+gst_test_clock_advance_time, function in GstTestClock +
+
+
+gst_test_clock_crank, function in GstTestClock +
+
+
+gst_test_clock_get_next_entry_time, function in GstTestClock +
+
+
+gst_test_clock_has_id, function in GstTestClock +
+
+
+gst_test_clock_id_list_get_latest_time, function in GstTestClock +
+
+
+gst_test_clock_new, function in GstTestClock +
+
+
+gst_test_clock_new_with_start_time, function in GstTestClock +
+
+
+gst_test_clock_peek_id_count, function in GstTestClock +
+
+
+gst_test_clock_peek_next_pending_id, function in GstTestClock +
+
+
+gst_test_clock_process_id_list, function in GstTestClock +
+
+
+gst_test_clock_process_next_clock_id, function in GstTestClock +
+
+
+gst_test_clock_set_time, function in GstTestClock +
+
+
+gst_test_clock_wait_for_multiple_pending_ids, function in GstTestClock +
+
+
+gst_test_clock_wait_for_next_pending_id, function in GstTestClock +
+
+
+gst_test_clock_wait_for_pending_id_count, function in GstTestClock +
+
+
+GstTimedValueControlSource, struct in GstTimedValueControlSource +
+
+
+GstTimedValueControlSource::value-added, object signal in GstTimedValueControlSource +
+
+
+GstTimedValueControlSource::value-changed, object signal in GstTimedValueControlSource +
+
+
+GstTimedValueControlSource::value-removed, object signal in GstTimedValueControlSource +
+
+
+gst_timed_value_control_invalidate_cache, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_find_control_point_iter, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_get_all, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_get_count, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_set, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_set_from_list, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_unset, function in GstTimedValueControlSource +
+
+
+gst_timed_value_control_source_unset_all, function in GstTimedValueControlSource +
+
+
+GstTriggerControlSource, struct in GstTriggerControlSource +
+
+
+GstTriggerControlSource:tolerance, object property in GstTriggerControlSource +
+
+
+gst_trigger_control_source_new, function in GstTriggerControlSource +
+
+
+GstTypeFindHelperGetRangeFunction, user_function in GstTypeFindHelper +
+
+
+gst_type_find_helper, function in GstTypeFindHelper +
+
+
+gst_type_find_helper_for_buffer, function in GstTypeFindHelper +
+
+
+gst_type_find_helper_for_data, function in GstTypeFindHelper +
+
+
+gst_type_find_helper_for_extension, function in GstTypeFindHelper +
+
+
+gst_type_find_helper_get_range, function in GstTypeFindHelper +
+
+
+GST_TYPE_TRIGGER_WAVEFORM, macro in GstTriggerControlSource +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix02.html b/docs/libs/html/ix02.html new file mode 100644 index 0000000..535b389 --- /dev/null +++ b/docs/libs/html/ix02.html @@ -0,0 +1,34 @@ + + + + +Index of deprecated API: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of deprecated API

+

T

+
+gst_test_clock_wait_for_pending_id_count, function in GstTestClock +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix03.html b/docs/libs/html/ix03.html new file mode 100644 index 0000000..de47dea --- /dev/null +++ b/docs/libs/html/ix03.html @@ -0,0 +1,68 @@ + + + + +Index of new API in 1.14: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/libs/html/ix04.html b/docs/libs/html/ix04.html new file mode 100644 index 0000000..67bf93f --- /dev/null +++ b/docs/libs/html/ix04.html @@ -0,0 +1,38 @@ + + + + +Index of new API in 1.12.1: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.12.1

+

F

+
+gst_flow_combiner_ref, function in GstFlowCombiner +
+
+
+gst_flow_combiner_unref, function in GstFlowCombiner +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix05.html b/docs/libs/html/ix05.html new file mode 100644 index 0000000..067d69e --- /dev/null +++ b/docs/libs/html/ix05.html @@ -0,0 +1,41 @@ + + + + +Index of new API in 1.12: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.12

+

B

+
+gst_base_parse_drain, function in GstBaseParse +
+
+

P

+
+gst_proxy_control_binding_new, function in GstProxyControlBinding +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix06.html b/docs/libs/html/ix06.html new file mode 100644 index 0000000..3d8e1e5 --- /dev/null +++ b/docs/libs/html/ix06.html @@ -0,0 +1,46 @@ + + + + +Index of new API in 1.10: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.10

+

A

+
+gst_adapter_dts_at_discont, function in GstAdapter +
+
+
+gst_adapter_offset_at_discont, function in GstAdapter +
+
+
+gst_adapter_prev_offset, function in GstAdapter +
+
+
+gst_adapter_pts_at_discont, function in GstAdapter +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix07.html b/docs/libs/html/ix07.html new file mode 100644 index 0000000..29909c2 --- /dev/null +++ b/docs/libs/html/ix07.html @@ -0,0 +1,53 @@ + + + + +Index of new API in 1.8: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.8

+

H

+
+GstHarnessPrepareEventFunc, user_function in GstHarness +
+
+
+gst_harness_new_empty, function in GstHarness +
+
+
+gst_harness_stress_push_event_with_cb_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_upstream_event_with_cb_start_full, function in GstHarness +
+
+

T

+
+gst_test_clock_crank, function in GstTestClock +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix08.html b/docs/libs/html/ix08.html new file mode 100644 index 0000000..15decd2 --- /dev/null +++ b/docs/libs/html/ix08.html @@ -0,0 +1,501 @@ + + + + +Index of new API in 1.6: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.6

+

A

+
+gst_adapter_get_buffer, function in GstAdapter +
+
+
+gst_adapter_get_buffer_fast, function in GstAdapter +
+
+
+gst_adapter_get_buffer_list, function in GstAdapter +
+
+
+gst_adapter_get_list, function in GstAdapter +
+
+
+gst_adapter_take_buffer_list, function in GstAdapter +
+
+

B

+
+gst_base_parse_merge_tags, function in GstBaseParse +
+
+
+gst_base_transform_update_src_caps, function in GstBaseTransform +
+
+
+gst_byte_reader_get_sub_reader, function in GstByteReader +
+
+
+gst_byte_reader_masked_scan_uint32_peek, function in GstByteReader +
+
+
+gst_byte_reader_peek_sub_reader, function in GstByteReader +
+
+

C

+
+gst_check_objects_destroyed_on_unref, function in GstCheck +
+
+
+gst_check_object_destroyed_on_unref, function in GstCheck +
+
+
+GST_COLLECT_PADS_DTS, macro in GstCollectPads +
+
+
+GST_COLLECT_PADS_DTS_IS_VALID, macro in GstCollectPads +
+
+

D

+
+gst_direct_control_binding_new_absolute, function in GstDirectControlBinding +
+
+

F

+
+gst_flow_combiner_clear, function in GstFlowCombiner +
+
+
+gst_flow_combiner_reset, function in GstFlowCombiner +
+
+
+gst_flow_combiner_update_pad_flow, function in GstFlowCombiner +
+
+

H

+
+GstHarness, struct in GstHarness +
+
+
+GstHarnessPrepareBufferFunc, user_function in GstHarness +
+
+
+GstHarnessThread, struct in GstHarness +
+
+
+gst_harness_add_element_full, function in GstHarness +
+
+
+gst_harness_add_element_sink_pad, function in GstHarness +
+
+
+gst_harness_add_element_src_pad, function in GstHarness +
+
+
+gst_harness_add_parse, function in GstHarness +
+
+
+gst_harness_add_probe, function in GstHarness +
+
+
+gst_harness_add_sink, function in GstHarness +
+
+
+gst_harness_add_sink_harness, function in GstHarness +
+
+
+gst_harness_add_sink_parse, function in GstHarness +
+
+
+gst_harness_add_src, function in GstHarness +
+
+
+gst_harness_add_src_harness, function in GstHarness +
+
+
+gst_harness_add_src_parse, function in GstHarness +
+
+
+gst_harness_buffers_in_queue, function in GstHarness +
+
+
+gst_harness_buffers_received, function in GstHarness +
+
+
+gst_harness_crank_multiple_clock_waits, function in GstHarness +
+
+
+gst_harness_crank_single_clock_wait, function in GstHarness +
+
+
+gst_harness_create_buffer, function in GstHarness +
+
+
+gst_harness_dump_to_file, function in GstHarness +
+
+
+gst_harness_events_in_queue, function in GstHarness +
+
+
+gst_harness_events_received, function in GstHarness +
+
+
+gst_harness_find_element, function in GstHarness +
+
+
+gst_harness_get, function in GstHarness +
+
+
+gst_harness_get_allocator, function in GstHarness +
+
+
+gst_harness_get_last_pushed_timestamp, function in GstHarness +
+
+
+gst_harness_get_testclock, function in GstHarness +
+
+
+gst_harness_new, function in GstHarness +
+
+
+gst_harness_new_full, function in GstHarness +
+
+
+gst_harness_new_parse, function in GstHarness +
+
+
+gst_harness_new_with_element, function in GstHarness +
+
+
+gst_harness_new_with_padnames, function in GstHarness +
+
+
+gst_harness_new_with_templates, function in GstHarness +
+
+
+gst_harness_play, function in GstHarness +
+
+
+gst_harness_pull, function in GstHarness +
+
+
+gst_harness_pull_event, function in GstHarness +
+
+
+gst_harness_pull_upstream_event, function in GstHarness +
+
+
+gst_harness_push, function in GstHarness +
+
+
+gst_harness_push_and_pull, function in GstHarness +
+
+
+gst_harness_push_event, function in GstHarness +
+
+
+gst_harness_push_from_src, function in GstHarness +
+
+
+gst_harness_push_to_sink, function in GstHarness +
+
+
+gst_harness_push_upstream_event, function in GstHarness +
+
+
+gst_harness_query_latency, function in GstHarness +
+
+
+gst_harness_set, function in GstHarness +
+
+
+gst_harness_set_blocking_push_mode, function in GstHarness +
+
+
+gst_harness_set_caps, function in GstHarness +
+
+
+gst_harness_set_caps_str, function in GstHarness +
+
+
+gst_harness_set_drop_buffers, function in GstHarness +
+
+
+gst_harness_set_forwarding, function in GstHarness +
+
+
+gst_harness_set_propose_allocator, function in GstHarness +
+
+
+gst_harness_set_sink_caps, function in GstHarness +
+
+
+gst_harness_set_sink_caps_str, function in GstHarness +
+
+
+gst_harness_set_src_caps, function in GstHarness +
+
+
+gst_harness_set_src_caps_str, function in GstHarness +
+
+
+gst_harness_set_time, function in GstHarness +
+
+
+gst_harness_set_upstream_latency, function in GstHarness +
+
+
+gst_harness_sink_push_many, function in GstHarness +
+
+
+gst_harness_src_crank_and_push_many, function in GstHarness +
+
+
+gst_harness_src_push_event, function in GstHarness +
+
+
+gst_harness_stress_custom_start, function in GstHarness +
+
+
+gst_harness_stress_property_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_buffer_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_buffer_with_cb_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_event_start_full, function in GstHarness +
+
+
+gst_harness_stress_push_upstream_event_start_full, function in GstHarness +
+
+
+gst_harness_stress_requestpad_start_full, function in GstHarness +
+
+
+gst_harness_stress_statechange_start_full, function in GstHarness +
+
+
+gst_harness_stress_thread_stop, function in GstHarness +
+
+
+gst_harness_teardown, function in GstHarness +
+
+
+gst_harness_try_pull, function in GstHarness +
+
+
+gst_harness_try_pull_event, function in GstHarness +
+
+
+gst_harness_try_pull_upstream_event, function in GstHarness +
+
+
+gst_harness_upstream_events_in_queue, function in GstHarness +
+
+
+gst_harness_upstream_events_received, function in GstHarness +
+
+
+gst_harness_use_systemclock, function in GstHarness +
+
+
+gst_harness_use_testclock, function in GstHarness +
+
+
+gst_harness_wait_for_clock_id_waits, function in GstHarness +
+
+

N

+
+gst_ntp_clock_new, function in GstNetClientClock +
+
+

P

+
+gst_ptp_clock_new, function in GstPtpClock +
+
+
+gst_ptp_deinit, function in GstPtpClock +
+
+
+gst_ptp_init, function in GstPtpClock +
+
+
+gst_ptp_is_initialized, function in GstPtpClock +
+
+
+gst_ptp_is_supported, function in GstPtpClock +
+
+
+gst_ptp_statistics_callback_add, function in GstPtpClock +
+
+
+gst_ptp_statistics_callback_remove, function in GstPtpClock +
+
+

Q

+
+gst_queue_array_drop_struct, function in GstQueueArray +
+
+
+gst_queue_array_new_for_struct, function in GstQueueArray +
+
+
+gst_queue_array_peek_head_struct, function in GstQueueArray +
+
+
+gst_queue_array_pop_head_struct, function in GstQueueArray +
+
+

T

+
+GstTimedValueControlSource::value-added, object signal in GstTimedValueControlSource +
+
+
+GstTimedValueControlSource::value-changed, object signal in GstTimedValueControlSource +
+
+
+GstTimedValueControlSource::value-removed, object signal in GstTimedValueControlSource +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix09.html b/docs/libs/html/ix09.html new file mode 100644 index 0000000..5d2f59f --- /dev/null +++ b/docs/libs/html/ix09.html @@ -0,0 +1,114 @@ + + + + +Index of new API in 1.4: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/libs/html/ix10.html b/docs/libs/html/ix10.html new file mode 100644 index 0000000..0a9f6f1 --- /dev/null +++ b/docs/libs/html/ix10.html @@ -0,0 +1,241 @@ + + + + +Index of new API in 1.2: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.2

+

A

+
+gst_adapter_prev_dts_at_offset, function in GstAdapter +
+
+
+gst_adapter_prev_pts_at_offset, function in GstAdapter +
+
+
+gst_adapter_take_buffer_fast, function in GstAdapter +
+
+
+assert_equals_int64_hex, macro in GstCheck +
+
+
+assert_equals_int_hex, macro in GstCheck +
+
+
+assert_equals_pointer, macro in GstCheck +
+
+
+assert_equals_uint64_hex, macro in GstCheck +
+
+

B

+
+GstBaseSink:max-bitrate, object property in GstBaseSink +
+
+
+gst_base_parse_set_ts_at_offset, function in GstBaseParse +
+
+
+gst_base_sink_get_max_bitrate, function in GstBaseSink +
+
+
+gst_base_sink_set_max_bitrate, function in GstBaseSink +
+
+

D

+
+gst_data_queue_drop_head, function in GstDataQueue +
+
+
+gst_data_queue_flush, function in GstDataQueue +
+
+
+gst_data_queue_get_level, function in GstDataQueue +
+
+
+gst_data_queue_is_empty, function in GstDataQueue +
+
+
+gst_data_queue_is_full, function in GstDataQueue +
+
+
+gst_data_queue_limits_changed, function in GstDataQueue +
+
+
+gst_data_queue_new, function in GstDataQueue +
+
+
+gst_data_queue_peek, function in GstDataQueue +
+
+
+gst_data_queue_pop, function in GstDataQueue +
+
+
+gst_data_queue_push, function in GstDataQueue +
+
+
+gst_data_queue_push_force, function in GstDataQueue +
+
+
+gst_data_queue_set_flushing, function in GstDataQueue +
+
+

F

+
+fail_unless_equals_int64_hex, macro in GstCheck +
+
+
+fail_unless_equals_int_hex, macro in GstCheck +
+
+
+fail_unless_equals_pointer, macro in GstCheck +
+
+
+fail_unless_equals_uint64_hex, macro in GstCheck +
+
+

Q

+
+gst_queue_array_drop_element, function in GstQueueArray +
+
+
+gst_queue_array_find, function in GstQueueArray +
+
+
+gst_queue_array_free, function in GstQueueArray +
+
+
+gst_queue_array_get_length, function in GstQueueArray +
+
+
+gst_queue_array_is_empty, function in GstQueueArray +
+
+
+gst_queue_array_new, function in GstQueueArray +
+
+
+gst_queue_array_peek_head, function in GstQueueArray +
+
+
+gst_queue_array_pop_head, function in GstQueueArray +
+
+
+gst_queue_array_push_tail, function in GstQueueArray +
+
+

T

+
+GstTestClock, struct in GstTestClock +
+
+
+GstTestClockClass, struct in GstTestClock +
+
+
+gst_test_clock_advance_time, function in GstTestClock +
+
+
+gst_test_clock_get_next_entry_time, function in GstTestClock +
+
+
+gst_test_clock_has_id, function in GstTestClock +
+
+
+gst_test_clock_new, function in GstTestClock +
+
+
+gst_test_clock_new_with_start_time, function in GstTestClock +
+
+
+gst_test_clock_peek_id_count, function in GstTestClock +
+
+
+gst_test_clock_peek_next_pending_id, function in GstTestClock +
+
+
+gst_test_clock_process_next_clock_id, function in GstTestClock +
+
+
+gst_test_clock_set_time, function in GstTestClock +
+
+
+gst_test_clock_wait_for_next_pending_id, function in GstTestClock +
+
+
+gst_test_clock_wait_for_pending_id_count, function in GstTestClock +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/ix11.html b/docs/libs/html/ix11.html new file mode 100644 index 0000000..732a73d --- /dev/null +++ b/docs/libs/html/ix11.html @@ -0,0 +1,34 @@ + + + + +Index of new API in 1.0.1: GStreamer 1.0 Library Reference Manual + + + + + + + + + + + + + + + + +
+

+Index of new API in 1.0.1

+

B

+
+gst_base_transform_set_prefer_passthrough, function in GstBaseTransform +
+
+
+ + + \ No newline at end of file diff --git a/docs/libs/html/left-insensitive.png b/docs/libs/html/left-insensitive.png new file mode 100644 index 0000000..6290738 Binary files /dev/null and b/docs/libs/html/left-insensitive.png differ diff --git a/docs/libs/html/left.png b/docs/libs/html/left.png new file mode 100644 index 0000000..d34a7bc Binary files /dev/null and b/docs/libs/html/left.png differ diff --git a/docs/libs/html/right-insensitive.png b/docs/libs/html/right-insensitive.png new file mode 100644 index 0000000..179725a Binary files /dev/null and b/docs/libs/html/right-insensitive.png differ diff --git a/docs/libs/html/right.png b/docs/libs/html/right.png new file mode 100644 index 0000000..bf5d8fa Binary files /dev/null and b/docs/libs/html/right.png differ diff --git a/docs/libs/html/style.css b/docs/libs/html/style.css new file mode 100644 index 0000000..3675420 --- /dev/null +++ b/docs/libs/html/style.css @@ -0,0 +1,479 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.3em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; + margin-top: 1em; + margin-bottom: 1em; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; + font-weight: bold; +} + +dl.toc > dl +{ + padding-bottom: 0.5em; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + /* these have a as a first child, but since there are no parent selectors + * we can't use that. */ + a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/docs/libs/html/up-insensitive.png b/docs/libs/html/up-insensitive.png new file mode 100644 index 0000000..5ee049e Binary files /dev/null and b/docs/libs/html/up-insensitive.png differ diff --git a/docs/libs/html/up.png b/docs/libs/html/up.png new file mode 100644 index 0000000..3a816d0 Binary files /dev/null and b/docs/libs/html/up.png differ diff --git a/docs/libs/meson.build b/docs/libs/meson.build new file mode 100644 index 0000000..4748276 --- /dev/null +++ b/docs/libs/meson.build @@ -0,0 +1,16 @@ +types = configure_file(input : 'gstreamer-libs.types', + output : 'gstreamer-libs.types', + configuration : configuration_data()) + +gnome.gtkdoc('gstreamer-libs', + main_sgml : 'gstreamer-libs-docs.sgml', + src_dir : '@0@/../../libs/gst'.format(meson.current_source_dir()), + scan_args : ['--deprecated-guards=GST_DISABLE_DEPRECATED', + '--ignore-decorators=GST_API|GST_BASE_API|GST_CHECK_API|GST_CONTROLLER_API|GST_NET_API', + '--ignore-headers=gettext.h glib-compat-private.h glib-compat.h gst-i18n-app.h gst-i18n-lib.h gst_private.h gstelementdetails.h gstmacros.h grammar.tab.h grammar.tab.pre.h math-compat.h types.h' + ], + scanobjs_args : ['--type-init-func="gst_init(NULL,NULL)"'], + gobject_typesfile : types, + content_files : [version_entities], + dependencies : [gst_base_dep, gst_check_dep, gst_controller_dep, gst_net_dep], + install : true) diff --git a/docs/list-ulink.xsl b/docs/list-ulink.xsl new file mode 100644 index 0000000..969b5b7 --- /dev/null +++ b/docs/list-ulink.xsl @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 0000000..6b6a479 --- /dev/null +++ b/docs/meson.build @@ -0,0 +1,12 @@ +docconf = configuration_data() + +docconf.set('GST_API_VERSION', apiversion) +docconf.set('PACKAGE_VERSION', gst_version) +docconf.set('PLUGINDIR', '@0@/lib/gstreamer-1.0'.format(get_option('prefix'))) + +version_entities = configure_file(input : 'version.entities.in', + output : 'version.entities', + configuration : docconf) + +subdir('gst') +subdir('libs') diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am new file mode 100644 index 0000000..8f41089 --- /dev/null +++ b/docs/plugins/Makefile.am @@ -0,0 +1,95 @@ +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_API_VERSION@ +MODULE=gstreamer +DOC_MODULE=$(MODULE)-plugins + +# for upload-doc.mak +DOC=$(MODULE)-plugins +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# Extra environment needed for Core only... +INSPECT_EXTRA_ENVIRONMENT= \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir)/plugins/elements $(top_srcdir)/plugins/tracers + +# 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/gst/html \ + --extra-dir=$(top_builddir)/docs/libs/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(datadir)/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(top_srcdir)/plugins/elements/*.h $(top_srcdir)/plugins/tracers/*.h +CFILE_GLOB=$(top_srcdir)/plugins/elements/*.c $(top_srcdir)/plugins/tracers/*.c + +# Header files to ignore when scanning. +IGNORE_HFILES = +IGNORE_CFILES = + +# 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)/plugins/elements/gstcapsfilter.h \ + $(top_srcdir)/plugins/elements/gstdataurisrc.h \ + $(top_srcdir)/plugins/elements/gstdownloadbuffer.h \ + $(top_srcdir)/plugins/elements/gstfakesrc.h \ + $(top_srcdir)/plugins/elements/gstfakesink.h \ + $(top_srcdir)/plugins/elements/gstfdsink.h \ + $(top_srcdir)/plugins/elements/gstfdsrc.h \ + $(top_srcdir)/plugins/elements/gstfilesrc.h \ + $(top_srcdir)/plugins/elements/gstfilesink.h \ + $(top_srcdir)/plugins/elements/gstidentity.h \ + $(top_srcdir)/plugins/elements/gstinputselector.h \ + $(top_srcdir)/plugins/elements/gstmultiqueue.h \ + $(top_srcdir)/plugins/elements/gstoutputselector.h \ + $(top_srcdir)/plugins/elements/gstqueue.h \ + $(top_srcdir)/plugins/elements/gstqueue2.h \ + $(top_srcdir)/plugins/elements/gsttypefindelement.h \ + $(top_srcdir)/plugins/elements/gsttee.h \ + $(top_srcdir)/plugins/elements/gstvalve.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_OBJ_CFLAGS) -I$(top_builddir) -I$(top_builddir)/libs +GTKDOC_LIBS = $(GST_OBJ_LIBS) + +# 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/docs/plugins/Makefile.in b/docs/plugins/Makefile.in new file mode 100644 index 0000000..8b7575a --- /dev/null +++ b/docs/plugins/Makefile.in @@ -0,0 +1,1164 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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 + +# This is an include file specifically tuned for building documentation +# for GStreamer plug-ins +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = docs/plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/common/gtk-doc-plugins.mak \ + $(top_srcdir)/common/upload-doc.mak +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GST_DOC_SCANOBJ = $(top_srcdir)/common/gstdoc-scangobj + +# The name of the module, e.g. 'glib'. +#DOC_MODULE=gst-plugins-libs-@GST_API_VERSION@ +MODULE = gstreamer +DOC_MODULE = $(MODULE)-plugins + +# for upload-doc.mak +DOC = $(MODULE)-plugins +FORMATS = html + +# 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) + +# Extra environment needed for Core only... +INSPECT_EXTRA_ENVIRONMENT = \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner + + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml + +# The directory containing the source code. +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir)/plugins/elements $(top_srcdir)/plugins/tracers + +# 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/gst/html \ + --extra-dir=$(top_builddir)/docs/libs/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(datadir)/gtk-doc/html + + +# Used for dependencies. +HFILE_GLOB = $(top_srcdir)/plugins/elements/*.h $(top_srcdir)/plugins/tracers/*.h +CFILE_GLOB = $(top_srcdir)/plugins/elements/*.c $(top_srcdir)/plugins/tracers/*.c + +# Header files to ignore when scanning. +IGNORE_HFILES = +IGNORE_CFILES = + +# 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)/plugins/elements/gstcapsfilter.h \ + $(top_srcdir)/plugins/elements/gstdataurisrc.h \ + $(top_srcdir)/plugins/elements/gstdownloadbuffer.h \ + $(top_srcdir)/plugins/elements/gstfakesrc.h \ + $(top_srcdir)/plugins/elements/gstfakesink.h \ + $(top_srcdir)/plugins/elements/gstfdsink.h \ + $(top_srcdir)/plugins/elements/gstfdsrc.h \ + $(top_srcdir)/plugins/elements/gstfilesrc.h \ + $(top_srcdir)/plugins/elements/gstfilesink.h \ + $(top_srcdir)/plugins/elements/gstidentity.h \ + $(top_srcdir)/plugins/elements/gstinputselector.h \ + $(top_srcdir)/plugins/elements/gstmultiqueue.h \ + $(top_srcdir)/plugins/elements/gstoutputselector.h \ + $(top_srcdir)/plugins/elements/gstqueue.h \ + $(top_srcdir)/plugins/elements/gstqueue2.h \ + $(top_srcdir)/plugins/elements/gsttypefindelement.h \ + $(top_srcdir)/plugins/elements/gsttee.h \ + $(top_srcdir)/plugins/elements/gstvalve.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_OBJ_CFLAGS) -I$(top_builddir) -I$(top_builddir)/libs +GTKDOC_LIBS = $(GST_OBJ_LIBS) + +# 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 = +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute + +# 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_API_VERSION@ +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 \ + sgml-build.stamp \ + html-build.stamp \ + scan.stamp \ + sgml.stamp \ + html.stamp + + +# files generated/updated by gtkdoc-scangobj +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + $(DOC_MODULE).types + +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 + +CLEANFILES = \ + $(SCANOBJ_FILES_O) \ + $(REPORT_FILES) \ + $(DOC_STAMPS) \ + inspect-registry.xml + +INSPECT_DIR = inspect + +### inspect GStreamer plug-ins; done by documentation maintainer ### + +# only look at the plugins in this module when building inspect .xml stuff +@ENABLE_GTK_DOC_TRUE@INSPECT_REGISTRY = $(top_builddir)/docs/plugins/inspect-registry.xml +@ENABLE_GTK_DOC_TRUE@INSPECT_ENVIRONMENT = \ +@ENABLE_GTK_DOC_TRUE@ LC_ALL=C \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0= \ +@ENABLE_GTK_DOC_TRUE@ GST_PLUGIN_PATH_1_0=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(top_builddir)/plugins:$(top_builddir)/src:$(top_builddir)/gnl \ +@ENABLE_GTK_DOC_TRUE@ GST_REGISTRY_1_0=$(INSPECT_REGISTRY) \ +@ENABLE_GTK_DOC_TRUE@ PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ +@ENABLE_GTK_DOC_TRUE@ $(INSPECT_EXTRA_ENVIRONMENT) + +MAINTAINERCLEANFILES = $(MAINTAINER_DOC_STAMPS) + +# wildcard is apparently not portable to other makes, hence the use of find +inspect_files = $(shell find $(srcdir)/$(INSPECT_DIR) -name '*.xml') +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc-plugins.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu docs/plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/upload-doc.mak $(top_srcdir)/common/gtk-doc-plugins.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-local + +.PRECIOUS: Makefile + +html: html-build.stamp + +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 X.Y/ and head/ subdirectories \ + export DIR=$(DOC_BASE)/gstreamer/$(PACKAGE_VERSION_MAJOR).$(PACKAGE_VERSION_MINOR)/$(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; \ + \ + 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 + +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: scanobj-update + $(MAKE) check-outdated-docs + +@ENABLE_GTK_DOC_TRUE@all-local: html-build.stamp + +#### scan gobjects; done by documentation maintainer #### +@ENABLE_GTK_DOC_TRUE@scanobj-update: +@ENABLE_GTK_DOC_TRUE@ -rm scanobj-build.stamp +@ENABLE_GTK_DOC_TRUE@ $(MAKE) scanobj-build.stamp + +# gstdoc-scanobj produces 5 output files (.new) +# scangobj-merge.py merges them into the file which we commit later +# TODO: also merge the hierarchy +@ENABLE_GTK_DOC_TRUE@scanobj-build.stamp: $(SCANOBJ_DEPS) $(basefiles) +@ENABLE_GTK_DOC_TRUE@ @echo " DOC Introspecting gobjects" +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ +@ENABLE_GTK_DOC_TRUE@ do \ +@ENABLE_GTK_DOC_TRUE@ if test -e $(srcdir)/$$f; then \ +@ENABLE_GTK_DOC_TRUE@ cp -u $(srcdir)/$$f . || cp $(srcdir)/$$f . ; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ mkdir -p $(INSPECT_DIR); \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options=""; \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ scanobj_options="--verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ $(INSPECT_ENVIRONMENT) \ +@ENABLE_GTK_DOC_TRUE@ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" \ +@ENABLE_GTK_DOC_TRUE@ CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS) $(WARNING_CFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ +@ENABLE_GTK_DOC_TRUE@ $(GST_DOC_SCANOBJ) $$scanobj_options --type-init-func="gst_init(NULL,NULL)" \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) --source=$(PACKAGE) --inspect-dir=$(INSPECT_DIR) && \ +@ENABLE_GTK_DOC_TRUE@ echo " DOC Merging introspection data" && \ +@ENABLE_GTK_DOC_TRUE@ $(PYTHON) \ +@ENABLE_GTK_DOC_TRUE@ $(top_srcdir)/common/scangobj-merge.py $(DOC_MODULE) || exit 1; \ +@ENABLE_GTK_DOC_TRUE@ if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ for f in $(SCANOBJ_FILES); \ +@ENABLE_GTK_DOC_TRUE@ do \ +@ENABLE_GTK_DOC_TRUE@ cmp -s ./$$f $(srcdir)/$$f || cp ./$$f $(srcdir)/ ; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ touch scanobj-build.stamp + +@ENABLE_GTK_DOC_TRUE@$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(SCANOBJ_FILES_O): scan-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +### scan headers; done on every build ### +@ENABLE_GTK_DOC_TRUE@scan-build.stamp: $(HFILE_GLOB) $(EXTRA_HFILES) $(basefiles) scanobj-build.stamp +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Scanning header files' +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ +@ENABLE_GTK_DOC_TRUE@ do \ +@ENABLE_GTK_DOC_TRUE@ if test -e $(srcdir)/$$f; then \ +@ENABLE_GTK_DOC_TRUE@ cp -u $(srcdir)/$$f . || cp $(srcdir)/$$f .; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ done; \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-scan \ +@ENABLE_GTK_DOC_TRUE@ $(SCAN_OPTIONS) $(EXTRA_HFILES) \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $${_source_dir} \ +@ENABLE_GTK_DOC_TRUE@ --ignore-headers="$(IGNORE_HFILES)"; \ +@ENABLE_GTK_DOC_TRUE@ touch scan-build.stamp + +#### xml #### + +@ENABLE_GTK_DOC_TRUE@sgml-build.stamp: scan-build.stamp $(CFILE_GLOB) $(top_srcdir)/common/plugins.xsl $(expand_content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building XML' +@ENABLE_GTK_DOC_TRUE@ @-mkdir -p xml +@ENABLE_GTK_DOC_TRUE@ @for a in $(inspect_files); do \ +@ENABLE_GTK_DOC_TRUE@ xsltproc --stringparam module $(MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $(top_srcdir)/common/plugins.xsl $$a > xml/`basename $$a`; done +@ENABLE_GTK_DOC_TRUE@ @for f in $(EXAMPLE_CFILES); do \ +@ENABLE_GTK_DOC_TRUE@ $(PYTHON) $(top_srcdir)/common/c-to-xml.py $$f > xml/element-`basename $$f .c`.xml; done +@ENABLE_GTK_DOC_TRUE@ @_source_dir='' ; \ +@ENABLE_GTK_DOC_TRUE@ for i in $(DOC_SOURCE_DIR) ; do \ +@ENABLE_GTK_DOC_TRUE@ _source_dir="$${_source_dir} --source-dir=$$i" ; \ +@ENABLE_GTK_DOC_TRUE@ done ; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkdb \ +@ENABLE_GTK_DOC_TRUE@ --module=$(DOC_MODULE) \ +@ENABLE_GTK_DOC_TRUE@ $${_source_dir} \ +@ENABLE_GTK_DOC_TRUE@ --expand-content-files="$(expand_content_files)" \ +@ENABLE_GTK_DOC_TRUE@ --main-sgml-file=$(srcdir)/$(DOC_MAIN_SGML_FILE) \ +@ENABLE_GTK_DOC_TRUE@ --output-format=xml \ +@ENABLE_GTK_DOC_TRUE@ --ignore-files="$(IGNORE_HFILES) $(IGNORE_CFILES)" \ +@ENABLE_GTK_DOC_TRUE@ $(MKDB_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @$(PYTHON) $(top_srcdir)/common/mangle-db.py xml +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities xml +@ENABLE_GTK_DOC_TRUE@ @touch sgml-build.stamp + +@ENABLE_GTK_DOC_TRUE@sgml.stamp: sgml-build.stamp +@ENABLE_GTK_DOC_TRUE@ @true + +#### html #### + +@ENABLE_GTK_DOC_TRUE@html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Building HTML' +@ENABLE_GTK_DOC_TRUE@ @rm -rf html +@ENABLE_GTK_DOC_TRUE@ @mkdir html +@ENABLE_GTK_DOC_TRUE@ @cp $(srcdir)/$(DOC_MAIN_SGML_FILE) html +@ENABLE_GTK_DOC_TRUE@ @for f in $(content_files); do cp $(srcdir)/$$f html; done +@ENABLE_GTK_DOC_TRUE@ @cp -pr xml html +@ENABLE_GTK_DOC_TRUE@ @cp ../version.entities html +@ENABLE_GTK_DOC_TRUE@ @mkhtml_options=""; \ +@ENABLE_GTK_DOC_TRUE@ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ +@ENABLE_GTK_DOC_TRUE@ if test "$(?)" = "0"; then \ +@ENABLE_GTK_DOC_TRUE@ if test "x$(V)" = "x1"; then \ +@ENABLE_GTK_DOC_TRUE@ mkhtml_options="$$mkhtml_options --verbose"; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ fi; \ +@ENABLE_GTK_DOC_TRUE@ cd html && gtkdoc-mkhtml $$mkhtml_options $(DOC_MODULE)-@GST_API_VERSION@ $(DOC_MAIN_SGML_FILE) +@ENABLE_GTK_DOC_TRUE@ @rm -f html/$(DOC_MAIN_SGML_FILE) +@ENABLE_GTK_DOC_TRUE@ @rm -rf html/xml +@ENABLE_GTK_DOC_TRUE@ @rm -f html/version.entities +@ENABLE_GTK_DOC_TRUE@ @test "x$(HTML_IMAGES)" = "x" || for i in "" $(HTML_IMAGES) ; do \ +@ENABLE_GTK_DOC_TRUE@ if test "$$i" != ""; then cp $(srcdir)/$$i html ; fi; done +@ENABLE_GTK_DOC_TRUE@ @echo ' DOC Fixing cross-references' +@ENABLE_GTK_DOC_TRUE@ @gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) +@ENABLE_GTK_DOC_TRUE@ @touch html-build.stamp + +@ENABLE_GTK_DOC_TRUE@clean-local-gtkdoc: +@ENABLE_GTK_DOC_TRUE@ @rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build +@ENABLE_GTK_DOC_TRUE@ @if test x"$(srcdir)" != x. ; then \ +@ENABLE_GTK_DOC_TRUE@ rm -rf $(SCANOBJ_FILES) $(SCAN_FILES) $(REPORT_FILES) \ +@ENABLE_GTK_DOC_TRUE@ $(MAINTAINER_DOC_STAMPS); \ +@ENABLE_GTK_DOC_TRUE@ fi +@ENABLE_GTK_DOC_FALSE@all-local: +@ENABLE_GTK_DOC_FALSE@clean-local-gtkdoc: + +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 + +# 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)-@GST_API_VERSION@.devhelp2' ; \ + if test -e $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_API_VERSION@.devhelp2; \ + fi; \ + $(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 +# +@ENABLE_GTK_DOC_TRUE@check-hierarchy: $(DOC_MODULE).hierarchy +@ENABLE_GTK_DOC_TRUE@ @if grep ' ' $(DOC_MODULE).hierarchy; then \ +@ENABLE_GTK_DOC_TRUE@ echo "$(DOC_MODULE).hierarchy contains tabs, please fix"; \ +@ENABLE_GTK_DOC_TRUE@ /bin/false; \ +@ENABLE_GTK_DOC_TRUE@ fi + +@ENABLE_GTK_DOC_TRUE@check: check-hierarchy + +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 +# +@ENABLE_GTK_DOC_TRUE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@dist-check-gtkdoc: +@ENABLE_GTK_DOC_FALSE@ @echo "*** gtk-doc must be installed and enabled in order to make dist" +@ENABLE_GTK_DOC_FALSE@ @false + +# 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: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/docs/plugins/gstreamer-plugins-docs.sgml b/docs/plugins/gstreamer-plugins-docs.sgml new file mode 100644 index 0000000..6d823c9 --- /dev/null +++ b/docs/plugins/gstreamer-plugins-docs.sgml @@ -0,0 +1,58 @@ + + +%version-entities; +]> + + + + GStreamer Core Plugins &GST_API_VERSION; Plugins Reference Manual + + for GStreamer Core Plugins &GST_API_VERSION; (&GST_VERSION;) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/. + + + + + gstreamer Elements + + + + + + + + + + + + + + + + + + + + + + + + + gstreamer Tracers + + + + + + + + + gstreamer Plugins + + + + + diff --git a/docs/plugins/gstreamer-plugins-sections.txt b/docs/plugins/gstreamer-plugins-sections.txt new file mode 100644 index 0000000..89d4906 --- /dev/null +++ b/docs/plugins/gstreamer-plugins-sections.txt @@ -0,0 +1,430 @@ +
+element-capsfilter +capsfilter +GstCapsFilter +GstCapsFilterCapsChangeMode + +GstCapsFilterClass +GST_CAPS_FILTER +GST_CAPS_FILTER_CAST +GST_IS_CAPS_FILTER +GST_CAPS_FILTER_CLASS +GST_IS_CAPS_FILTER_CLASS +GST_TYPE_CAPS_FILTER + +gst_caps_filter_get_type +
+ +
+element-concat +concat +GstConcat + +GstConcatClass +GST_CONCAT +GST_CONCAT_CAST +GST_IS_CONCAT +GST_CONCAT_CLASS +GST_IS_CONCAT_CLASS +GST_TYPE_CONCAT + +gst_concat_get_type +
+ +
+element-dataurisrc +dataurisrc +GstDataURISrc + +GstDataURISrcClass +GST_DATA_URI_SRC +GST_DATA_URI_SRC_CAST +GST_IS_DATA_URI_SRC +GST_DATA_URI_SRC_CLASS +GST_IS_DATA_URI_SRC_CLASS +GST_TYPE_DATA_URI_SRC + +gst_data_uri_src_get_type +
+ +
+element-downloadbuffer +downloadbuffer +GstDownloadBuffer + +GstDownloadBufferSize +GstDownloadBufferClass +GST_DOWNLOAD_BUFFER +GST_DOWNLOAD_BUFFER_CAST +GST_IS_DOWNLOAD_BUFFER +GST_DOWNLOAD_BUFFER_CLASS +GST_IS_DOWNLOAD_BUFFER_CLASS +GST_TYPE_DOWNLOAD_BUFFER + +gst_download_buffer_get_type +
+ +
+element-fakesink +fakesink +GstFakeSink +GstFakeSinkStateError + +GstFakeSinkClass +GST_FAKE_SINK +GST_FAKE_SINK_CAST +GST_IS_FAKE_SINK +GST_FAKE_SINK_CLASS +GST_IS_FAKE_SINK_CLASS +GST_TYPE_FAKE_SINK + +gst_fake_sink_get_type +
+ +
+element-fakesrc +fakesrc +GstFakeSrc +GstFakeSrcDataType +GstFakeSrcFillType +GstFakeSrcOutputType +GstFakeSrcSizeType + +GstFakeSrcClass +GST_FAKE_SRC +GST_IS_FAKE_SRC +GST_FAKE_SRC_CLASS +GST_IS_FAKE_SRC_CLASS +GST_TYPE_FAKE_SRC + +gst_fake_src_get_type +
+ +
+element-fdsink +fdsink +GstFdSink + +GstFdSinkClass +GST_FD_SINK +GST_FD_SINK_CAST +GST_IS_FD_SINK +GST_FD_SINK_CLASS +GST_IS_FD_SINK_CLASS +GST_TYPE_FD_SINK + +gst_fd_sink_get_type +
+ +
+element-fdsrc +fdsrc +GstFdSrc + +GstFdSrcClass +GST_FD_SRC +GST_IS_FD_SRC +GST_FD_SRC_CLASS +GST_IS_FD_SRC_CLASS +GST_TYPE_FD_SRC + +gst_fd_src_get_type +
+ +
+element-filesink +filesink +GstFileSink +GstFileSinkBufferMode + +GstFileSinkClass +GST_FILE_SINK +GST_FILE_SINK_CAST +GST_IS_FILE_SINK +GST_FILE_SINK_CLASS +GST_IS_FILE_SINK_CLASS +GST_TYPE_FILE_SINK +GST_TYPE_FILE_SINK_BUFFER_MODE + +gst_file_sink_get_type +
+ +
+element-filesrc +filesrc +GstFileSrc + +GstFileSrcClass +GST_FILE_SRC +GST_FILE_SRC_CAST +GST_IS_FILE_SRC +GST_FILE_SRC_CLASS +GST_IS_FILE_SRC_CLASS +GST_TYPE_FILE_SRC + +gst_file_src_get_type +
+ +
+element-funnel +funnel +GstFunnel + +GstFunnelClass +GST_FUNNEL +GST_IS_FUNNEL +GST_FUNNEL_CLASS +GST_IS_FUNNEL_CLASS +GST_TYPE_FUNNEL + +gst_funnel_get_type +
+ +
+element-identity +identity +GstIdentity + +GstIdentityClass +GST_IDENTITY +GST_IS_IDENTITY +GST_IDENTITY_CLASS +GST_IS_IDENTITY_CLASS +GST_TYPE_IDENTITY + +gst_identity_get_type +
+ +
+element-input-selector +input-selector +GstInputSelector +GstInputSelectorSyncMode + +GstInputSelectorClass +GST_INPUT_SELECTOR +GST_IS_INPUT_SELECTOR +GST_INPUT_SELECTOR_CLASS +GST_IS_INPUT_SELECTOR_CLASS +GST_TYPE_INPUT_SELECTOR +GST_INPUT_SELECTOR_BROADCAST +GST_INPUT_SELECTOR_GET_COND +GST_INPUT_SELECTOR_GET_LOCK +GST_INPUT_SELECTOR_LOCK +GST_INPUT_SELECTOR_UNLOCK +GST_INPUT_SELECTOR_WAIT + +gst_input_selector_get_type +
+ +
+element-latencytracer +latencytracer +GstLatencyTracer + +GstLatencyTracerClass +GST_LATENCY_TRACER +GST_LATENCY_TRACER_CAST +GST_IS_LATENCY_TRACER +GST_LATENCY_TRACER_CLASS +GST_IS_LATENCY_TRACER_CLASS +GST_TYPE_LATENCY_TRACER + +gst_latency_tracer_get_type +
+ +
+element-leakstracer +leakstracer +GstLeaksTracer + +GstLeaksTracerClass +GST_LEAKS_TRACER +GST_LEAKS_TRACER_CAST +GST_IS_LEAKS_TRACER +GST_LEAKS_TRACER_CLASS +GST_IS_LEAKS_TRACER_CLASS +GST_TYPE_LEAKS_TRACER + +gst_leaks_tracer_get_type +
+ +
+element-logtracer +logtracer +GstLogTracer + +GstLogTracerClass +GST_LOG_TRACER +GST_LOG_TRACER_CAST +GST_IS_LOG_TRACER +GST_LOG_TRACER_CLASS +GST_IS_LOG_TRACER_CLASS +GST_TYPE_LOG_TRACER + +gst_log_tracer_get_type +
+ +
+element-multiqueue +multiqueue +GstMultiQueue + +GstMultiQueueClass +GST_MULTI_QUEUE +GST_IS_MULTI_QUEUE +GST_MULTI_QUEUE_CLASS +GST_IS_MULTI_QUEUE_CLASS +GST_TYPE_MULTI_QUEUE + +gst_multi_queue_get_type +
+ +
+element-output-selector +output-selector +GstOutputSelector +GstOutputSelectorPadNegotiationMode + +GstOutputSelectorClass +GST_OUTPUT_SELECTOR +GST_IS_OUTPUT_SELECTOR +GST_OUTPUT_SELECTOR_CLASS +GST_IS_OUTPUT_SELECTOR_CLASS +GST_TYPE_OUTPUT_SELECTOR + +gst_output_selector_get_type +
+ +
+element-queue +queue +GstQueue +GstQueueLeaky + +GstQueueClass +GST_QUEUE +GST_QUEUE_CAST +GST_IS_QUEUE +GST_QUEUE_CLASS +GST_IS_QUEUE_CLASS +GST_TYPE_QUEUE + +GstQueueSize +gst_queue_get_type +GST_QUEUE_CLEAR_LEVEL +
+ +
+element-queue2 +queue2 +GstQueue2 + +GstQueue2Class +GST_QUEUE2 +GST_QUEUE2_CAST +GST_IS_QUEUE2 +GST_QUEUE2_CLASS +GST_IS_QUEUE2_CLASS +GST_TYPE_QUEUE2 + +GstQueue2Size +GstQueue2Range +gst_queue2_get_type +
+ +
+element-rusagetracer +rusagetracer +GstRUsageTracer + +GstRUsageTracerClass +GST_RUSAGE_TRACER +GST_RUSAGE_TRACER_CAST +GST_IS_RUSAGE_TRACER +GST_RUSAGE_TRACER_CLASS +GST_IS_RUSAGE_TRACER_CLASS +GST_TYPE_RUSAGE_TRACER + +gst_rusage_tracer_get_type +
+ +
+element-statstracer +statstracer +GstStatsTracer + +GstStatsTracerClass +GST_STATS_TRACER +GST_STATS_TRACER_CAST +GST_IS_STATS_TRACER +GST_STATS_TRACER_CLASS +GST_IS_STATS_TRACER_CLASS +GST_TYPE_STATS_TRACER + +gst_stats_tracer_get_type +
+ +
+element-streamiddemux +streamiddemux +GstStreamidDemux + +GstStreamidDemuxClass +GST_STREAMID_DEMUX +GST_STREAMID_DEMUX_CAST +GST_IS_STREAMID_DEMUX +GST_STREAMID_DEMUX_CLASS +GST_IS_STREAMID_DEMUX_CLASS +GST_TYPE_STREAMID_DEMUX + +gst_streamid_demux_get_type +
+ +
+element-tee +tee +GstTee +GstTeePullMode + +GstTeeClass +GST_TEE +GST_TEE_CAST +GST_IS_TEE +GST_TEE_CLASS +GST_IS_TEE_CLASS +GST_TYPE_TEE + +gst_tee_get_type +
+ +
+element-typefind +typefind +GstTypeFindElement + +GstTypeFindElementClass +GST_TYPE_FIND_ELEMENT +GST_IS_TYPE_FIND_ELEMENT +GST_TYPE_FIND_ELEMENT_CLASS +GST_IS_TYPE_FIND_ELEMENT_CLASS +GST_TYPE_TYPE_FIND_ELEMENT + +gst_type_find_element_get_type +
+ +
+element-valve +valve +GstValve + +GstValveClass +GST_VALVE +GST_IS_VALVE +GST_VALVE_CLASS +GST_IS_VALVE_CLASS +GST_TYPE_VALVE + +gst_valve_get_type +
+ diff --git a/docs/plugins/gstreamer-plugins.args b/docs/plugins/gstreamer-plugins.args new file mode 100644 index 0000000..b19d197 --- /dev/null +++ b/docs/plugins/gstreamer-plugins.args @@ -0,0 +1,1270 @@ + +GstValve::drop +gboolean + +rw +Drop buffers and events +Whether to drop buffers and events or let them through. +FALSE + + + +GstTypeFindElement::caps +GstCaps* + +r +caps +detected capabilities in stream. + + + + +GstTypeFindElement::force-caps +GstCaps* + +rw +force caps +force caps without doing a typefind. + + + + +GstTypeFindElement::minimum +guint +[1,100] +rw +minimum +minimum probability required to accept caps. +1 + + + +GstTee::alloc-pad +GstPad* + +rw +Allocation Src Pad +The pad ALLOCATION queries will be proxied to (DEPRECATED, has no effect). + + + + +GstTee::has-chain +gboolean + +rwx +Has Chain +If the element can operate in push mode. +TRUE + + + +GstTee::last-message +gchar* + +r +Last Message +The message describing current status. +NULL + + + +GstTee::num-src-pads +gint +>= 0 +r +Num Src Pads +The number of source pads. +0 + + + +GstTee::pull-mode +GstTeePullMode + +rwx +Pull mode +Behavior of tee in pull mode. +Never activate in pull mode + + + +GstTee::silent +gboolean + +rwx +Silent +Don't produce last_message events. +TRUE + + + +GstTee::allow-not-linked +gboolean + +rwx +Allow not linked +Return GST_FLOW_OK even if there are no source pads or they are all unlinked. +FALSE + + + +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. Only used if use-buffering is True (Deprecated: use high-watermark instead). +99 + + + +GstQueue2::low-percent +gint +[0,100] +rw +Low percent +Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead). +1 + + + +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::ring-buffer-max-size +guint64 + +rw +Max. ring buffer size (bytes) +Max. amount of data in the ring buffer (bytes, 0 = disabled). +0 + + + +GstQueue2::temp-location +gchar* + +r +Temporary File Location +Location to store temporary files in (Only read this property, use temp-template to configure the name template). +NULL + + + +GstQueue2::temp-remove +gboolean + +rw +Remove the Temporary File +Remove the temp-location after use. +TRUE + + + +GstQueue2::temp-template +gchar* + +rw +Temporary File Template +File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled). +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::avg-in-rate +gint64 +>= 0 +r +Input data rate (bytes/s) +Average input data rate (bytes/s). +0 + + + +GstQueue2::use-tags-bitrate +gboolean + +rw +Use bitrate from tags +Use a bitrate from upstream tags to estimate buffer duration if not provided. +FALSE + + + +GstQueue2::high-watermark +gdouble +[0,1] +rw +High watermark +High threshold for buffering to finish. Only used if use-buffering is True. +0.99 + + + +GstQueue2::low-watermark +gdouble +[0,1] +rw +Low watermark +Low threshold for buffering to start. Only used if use-buffering is True. +0.01 + + + +GstQueue::current-level-buffers +guint + +r +Current level (buffers) +Current number of buffers in the queue. +0 + + + +GstQueue::current-level-bytes +guint + +r +Current level (kB) +Current amount of data in the queue (bytes). +0 + + + +GstQueue::current-level-time +guint64 + +r +Current level (ns) +Current amount of data in the queue (in ns). +0 + + + +GstQueue::flush-on-eos +gboolean + +rw +Flush on EOS +Discard all data in the queue when an EOS event is received. +FALSE + + + +GstQueue::leaky +GstQueueLeaky + +rw +Leaky +Where the queue leaks, if at all. +Not Leaky + + + +GstQueue::max-size-buffers +guint + +rw +Max. size (buffers) +Max. number of buffers in the queue (0=disable). +200 + + + +GstQueue::max-size-bytes +guint + +rw +Max. size (kB) +Max. amount of data in the queue (bytes, 0=disable). +10485760 + + + +GstQueue::max-size-time +guint64 + +rw +Max. size (ns) +Max. amount of data in the queue (in ns, 0=disable). +1000000000 + + + +GstQueue::min-threshold-buffers +guint + +rw +Min. threshold (buffers) +Min. number of buffers in the queue to allow reading (0=disable). +0 + + + +GstQueue::min-threshold-bytes +guint + +rw +Min. threshold (kB) +Min. amount of data in the queue to allow reading (bytes, 0=disable). +0 + + + +GstQueue::min-threshold-time +guint64 + +rw +Min. threshold (ns) +Min. amount of data in the queue to allow reading (in ns, 0=disable). +0 + + + +GstQueue::silent +gboolean + +rw +Silent +Don't emit queue signals. +FALSE + + + +GstOutputSelector::active-pad +GstPad* + +rw +Active pad +Currently active src pad. + + + + +GstOutputSelector::pad-negotiation-mode +GstOutputSelectorPadNegotiationMode + +rw +Pad negotiation mode +The mode to be used for pad negotiation. +All + + + +GstOutputSelector::resend-latest +gboolean + +rw +Resend latest buffer +Resend latest buffer after a switch to a new pad. +FALSE + + + +GstMultiQueue::extra-size-buffers +guint + +rw +Extra Size (buffers) +Amount of buffers the queues can grow if one of them is empty (0=disable) (NOT IMPLEMENTED). +5 + + + +GstMultiQueue::extra-size-bytes +guint + +rw +Extra Size (kB) +Amount of data the queues can grow if one of them is empty (bytes, 0=disable) (NOT IMPLEMENTED). +10485760 + + + +GstMultiQueue::extra-size-time +guint64 + +rw +Extra Size (ns) +Amount of time the queues can grow if one of them is empty (in ns, 0=disable) (NOT IMPLEMENTED). +3000000000 + + + +GstMultiQueue::high-percent +gint +[0,100] +rw +High percent +High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead). +99 + + + +GstMultiQueue::low-percent +gint +[0,100] +rw +Low percent +Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead). +1 + + + +GstMultiQueue::max-size-buffers +guint + +rw +Max. size (buffers) +Max. number of buffers in the queue (0=disable). +5 + + + +GstMultiQueue::max-size-bytes +guint + +rw +Max. size (kB) +Max. amount of data in the queue (bytes, 0=disable). +10485760 + + + +GstMultiQueue::max-size-time +guint64 + +rw +Max. size (ns) +Max. amount of data in the queue (in ns, 0=disable). +2000000000 + + + +GstMultiQueue::sync-by-running-time +gboolean + +rw +Sync By Running Time +Synchronize deactivated or not-linked streams by running time. +FALSE + + + +GstMultiQueue::use-buffering +gboolean + +rw +Use buffering +Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds. +FALSE + + + +GstMultiQueue::unlinked-cache-time +guint64 + +rw +Unlinked cache time (ns) +Extra buffering in time for unlinked streams (if 'sync-by-running-time'). +250000000 + + + +GstMultiQueue::use-interleave +gboolean + +rw +Use interleave +Adjust time limits based on input interleave. +FALSE + + + +GstMultiQueue::high-watermark +gdouble +[0,1] +rw +High watermark +High threshold for buffering to finish. Only used if use-buffering is True. +0.99 + + + +GstMultiQueue::low-watermark +gdouble +[0,1] +rw +Low watermark +Low threshold for buffering to start. Only used if use-buffering is True. +0.01 + + + +GstMultiQueue::min-interleave-time +guint64 + +rw +Minimum interleave time +Minimum extra buffering for deinterleaving (size of the queues) when use-interleave=true. +250000000 + + + +GstInputSelector::active-pad +GstPad* + +rw +Active pad +The currently active sink pad. + + + + +GstInputSelector::cache-buffers +gboolean + +rw +Cache Buffers +Cache buffers for active-pad. +FALSE + + + +GstInputSelector::n-pads +guint + +r +Number of Pads +The number of sink pads. +0 + + + +GstInputSelector::sync-mode +GstInputSelectorSyncMode + +rw +Sync mode +Behavior in sync-streams mode. +Sync using the current active segment + + + +GstInputSelector::sync-streams +gboolean + +rw +Sync Streams +Synchronize inactive streams to the running time of the active stream or to the current clock. +TRUE + + + +GstIdentity::check-imperfect-offset +gboolean + +rw +Check for discontiguous offset +Send element messages if offset and offset_end do not match up. +FALSE + + + +GstIdentity::check-imperfect-timestamp +gboolean + +rw +Check for discontiguous timestamps +Send element messages if timestamps and durations do not match up. +FALSE + + + +GstIdentity::datarate +gint +>= 0 +rw +Datarate +(Re)timestamps buffers with number of bytes per second (0 = inactive). +0 + + + +GstIdentity::drop-probability +gfloat +[0,1] +rw +Drop Probability +The Probability a buffer is dropped. +0 + + + +GstIdentity::dump +gboolean + +rw +Dump +Dump buffer contents to stdout. +FALSE + + + +GstIdentity::error-after +gint + +rw +Error After +Error after N buffers. +-1 + + + +GstIdentity::last-message +gchar* + +r +last-message +last-message. +NULL + + + +GstIdentity::signal-handoffs +gboolean + +rw +Signal handoffs +Send a signal before pushing the buffer. +TRUE + + + +GstIdentity::silent +gboolean + +rw +silent +silent. +TRUE + + + +GstIdentity::single-segment +gboolean + +rw +Single Segment +Timestamp buffers and eat segments so as to appear as one segment. +FALSE + + + +GstIdentity::sleep-time +guint + +rw +Sleep time +Microseconds to sleep between processing. +0 + + + +GstIdentity::sync +gboolean + +rw +Synchronize +Synchronize to pipeline clock. +FALSE + + + +GstIdentity::drop-buffer-flags +GstBufferFlags + +rw +Check flags to drop buffers +Drop buffers with the given flags. + + + + +GstIdentity::ts-offset +gint64 + +rw +Timestamp offset for synchronisation +Timestamp offset in nanoseconds for synchronisation, negative for earlier sync. +0 + + + +GstIdentity::drop-allocation +gboolean + +rw +Drop allocation query +Don't forward allocation queries. +FALSE + + + +GstFileSrc::location +gchar* + +rw +File Location +Location of the file to read. +NULL + + + +GstFileSink::append +gboolean + +rw +Append +Append to an already existing file. +FALSE + + + +GstFileSink::buffer-mode +GstFileSinkBufferMode + +rw +Buffering mode +The buffering mode to use. +Default buffering + + + +GstFileSink::buffer-size +guint + +rw +Buffering size +Size of buffer in number of bytes for line or full buffer-mode. +65536 + + + +GstFileSink::location +gchar* + +rw +File Location +Location of the file to write. +NULL + + + +GstFdSrc::fd +gint +>= 0 +rw +fd +An open file descriptor to read from. +0 + + + +GstFdSrc::timeout +guint64 + +rw +Timeout +Post a message after timeout microseconds (0 = disabled). +0 + + + +GstFdSink::fd +gint +>= 0 +rw +fd +An open file descriptor to write to. +1 + + + +GstFakeSrc::can-activate-pull +gboolean + +rwx +Can activate pull +Can activate in pull mode. +TRUE + + + +GstFakeSrc::can-activate-push +gboolean + +rwx +Can activate push +Can activate in push mode. +TRUE + + + +GstFakeSrc::data +GstFakeSrcDataType + +rw +data +Data allocation method. +Allocate data + + + +GstFakeSrc::datarate +gint +>= 0 +rw +Datarate +Timestamps buffers with number of bytes per second (0 = none). +0 + + + +GstFakeSrc::dump +gboolean + +rw +Dump +Dump buffer contents to stdout. +FALSE + + + +GstFakeSrc::filltype +GstFakeSrcFillType + +rw +filltype +How to fill the buffer, if at all. +Fill buffers with zeros + + + +GstFakeSrc::format +GstFormat + +rw +Format +The format of the segment events. +GST_FORMAT_BYTES + + + +GstFakeSrc::is-live +gboolean + +rwx +Is this a live source +True if the element cannot produce data in PAUSED. +FALSE + + + +GstFakeSrc::last-message +gchar* + +r +last-message +The last status message. +NULL + + + +GstFakeSrc::parentsize +gint +>= 0 +rw +parentsize +Size of parent buffer for sub-buffered allocation. +40960 + + + +GstFakeSrc::pattern +gchar* + +rw +pattern +Set the pattern (unused). +NULL + + + +GstFakeSrc::signal-handoffs +gboolean + +rw +Signal handoffs +Send a signal before pushing the buffer. +FALSE + + + +GstFakeSrc::silent +gboolean + +rw +Silent +Don't produce last_message events. +TRUE + + + +GstFakeSrc::sizemax +gint +>= 0 +rw +sizemax +Maximum buffer size. +4096 + + + +GstFakeSrc::sizemin +gint +>= 0 +rw +sizemin +Minimum buffer size. +0 + + + +GstFakeSrc::sizetype +GstFakeSrcSizeType + +rw +sizetype +How to determine buffer sizes. +Send empty buffers + + + +GstFakeSrc::sync +gboolean + +rw +Sync +Sync to the clock to the datarate. +FALSE + + + +GstFakeSink::can-activate-pull +gboolean + +rw +Can activate pull +Can activate in pull mode. +FALSE + + + +GstFakeSink::can-activate-push +gboolean + +rw +Can activate push +Can activate in push mode. +TRUE + + + +GstFakeSink::dump +gboolean + +rw +Dump +Dump buffer contents to stdout. +FALSE + + + +GstFakeSink::last-message +gchar* + +r +Last Message +The message describing current status. +NULL + + + +GstFakeSink::num-buffers +gint +>= G_MAXULONG +rw +num-buffers +Number of buffers to accept going EOS. +-1 + + + +GstFakeSink::signal-handoffs +gboolean + +rw +Signal handoffs +Send a signal before unreffing the buffer. +FALSE + + + +GstFakeSink::silent +gboolean + +rw +Silent +Don't produce last_message events. +TRUE + + + +GstFakeSink::state-error +GstFakeSinkStateError + +rw +State Error +Generate a state change error. +No state change errors + + + +GstFakeSink::drop-out-of-segment +gboolean + +rw +Drop out-of-segment buffers +Drop and don't render / hand off out-of-segment buffers. +TRUE + + + +GstCapsFilter::caps +GstCaps* + +rw +Filter caps +Restrict the possible allowed capabilities (NULL means ANY). Setting this property takes a reference to the supplied GstCaps object. + + + + +GstCapsFilter::caps-change-mode +GstCapsFilterCapsChangeMode + +rw +Caps Change Mode +Filter caps change behaviour. +Only accept the current filter caps + + + +GstDownloadBuffer::high-percent +gint +[0,100] +rw +High percent +High threshold for buffering to finish. Only used if use-buffering is True. +99 + + + +GstDownloadBuffer::low-percent +gint +[0,100] +rw +Low percent +Low threshold for buffering to start. Only used if use-buffering is True. +10 + + + +GstDownloadBuffer::max-size-bytes +guint + +rw +Max. size (kB) +Max. amount of data to buffer (bytes, 0=disable). +2097152 + + + +GstDownloadBuffer::max-size-time +guint64 + +rw +Max. size (ns) +Max. amount of data to buffer (in ns, 0=disable). +2000000000 + + + +GstDownloadBuffer::temp-location +gchar* + +r +Temporary File Location +Location to store temporary files in (Only read this property, use temp-template to configure the name template). +NULL + + + +GstDownloadBuffer::temp-remove +gboolean + +rw +Remove the Temporary File +Remove the temp-location after use. +TRUE + + + +GstDownloadBuffer::temp-template +gchar* + +rw +Temporary File Template +File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled). +NULL + + + +GstStreamidDemux::active-pad +GstPad* + +r +Active pad +The currently active src pad. + + + + +GstConcat::active-pad +GstPad* + +r +Active pad +Currently active src pad. + + + + +GstConcat::adjust-base +gboolean + +rw +Adjust segment base +Adjust the base value of segments to ensure they are adjacent. +TRUE + + + +GstFunnel::forward-sticky-events +gboolean + +rw +Forward sticky events +Forward sticky events on stream changes. +TRUE + + + +GstDataURISrc::uri +gchar* + +rw +URI +URI that should be used. +NULL + + diff --git a/docs/plugins/gstreamer-plugins.hierarchy b/docs/plugins/gstreamer-plugins.hierarchy new file mode 100644 index 0000000..4f5311d --- /dev/null +++ b/docs/plugins/gstreamer-plugins.hierarchy @@ -0,0 +1,62 @@ +GObject + GInitiallyUnowned + GstObject + GstAllocator + GstAllocatorSysmem + GstBus + GstClock + GstControlBinding + GstControlSource + GstElement + GstBaseSink + GstFakeSink + GstFdSink + GstFileSink + GstBaseSrc + GstDataURISrc + GstFakeSrc + GstFileSrc + GstPushSrc + GstFdSrc + GstBaseTransform + GstCapsFilter + GstIdentity + GstBin + GstPipeline + GstConcat + GstDownloadBuffer + GstFunnel + GstInputSelector + GstMultiQueue + GstOutputSelector + GstQueue + GstQueue2 + GstStreamidDemux + GstTee + GstTypeFindElement + GstValve + GstPad + GstMultiQueuePad + GstSelectorPad + GstPadTemplate + GstPlugin + GstPluginFeature + GstDeviceProviderFactory + GstDynamicTypeFactory + GstElementFactory + GstTracerFactory + GstTypeFindFactory + GstRegistry + GstTask + GstTaskPool + GstTracer + GstLatencyTracer + GstLeaksTracer + GstLogTracer + GstRUsageTracer + GstStatsTracer + GstTracerRecord +GInterface + GTypePlugin + GstChildProxy + GstURIHandler diff --git a/docs/plugins/gstreamer-plugins.interfaces b/docs/plugins/gstreamer-plugins.interfaces new file mode 100644 index 0000000..fde573e --- /dev/null +++ b/docs/plugins/gstreamer-plugins.interfaces @@ -0,0 +1,7 @@ +GstBin GstChildProxy +GstDataURISrc GstURIHandler +GstFdSink GstURIHandler +GstFdSrc GstURIHandler +GstFileSink GstURIHandler +GstFileSrc GstURIHandler +GstPipeline GstChildProxy diff --git a/docs/plugins/gstreamer-plugins.prerequisites b/docs/plugins/gstreamer-plugins.prerequisites new file mode 100644 index 0000000..a8d518a --- /dev/null +++ b/docs/plugins/gstreamer-plugins.prerequisites @@ -0,0 +1 @@ +GstChildProxy GObject diff --git a/docs/plugins/gstreamer-plugins.signals b/docs/plugins/gstreamer-plugins.signals new file mode 100644 index 0000000..a0cf066 --- /dev/null +++ b/docs/plugins/gstreamer-plugins.signals @@ -0,0 +1,93 @@ + +GstTypeFindElement::have-type +void +l +GstTypeFindElement *gsttypefindelement +guint arg1 +GstCaps *arg2 + + + +GstQueue::overrun +void +f +GstQueue *gstqueue + + + +GstQueue::pushing +void +f +GstQueue *gstqueue + + + +GstQueue::running +void +f +GstQueue *gstqueue + + + +GstQueue::underrun +void +f +GstQueue *gstqueue + + + +GstMultiQueue::overrun +void +f +GstMultiQueue *gstmultiqueue + + + +GstMultiQueue::underrun +void +f +GstMultiQueue *gstmultiqueue + + + +GstIdentity::handoff +void +l +GstIdentity *gstidentity +GstBuffer *arg1 + + + +GstFakeSrc::handoff +void +l +GstFakeSrc *gstfakesrc +GstBuffer *arg1 +GstPad *arg2 + + + +GstFakeSink::handoff +void +l +GstFakeSink *gstfakesink +GstBuffer *arg1 +GstPad *arg2 + + + +GstFakeSink::preroll-handoff +void +l +GstFakeSink *gstfakesink +GstBuffer *arg1 +GstPad *arg2 + + + +GstQueue2::overrun +void +f +GstQueue2 *gstqueue2 + + diff --git a/docs/plugins/gstreamer-plugins.types b/docs/plugins/gstreamer-plugins.types new file mode 100644 index 0000000..9f4950e --- /dev/null +++ b/docs/plugins/gstreamer-plugins.types @@ -0,0 +1 @@ +#include diff --git a/docs/plugins/html/ch01.html b/docs/plugins/html/ch01.html new file mode 100644 index 0000000..fc1caa9 --- /dev/null +++ b/docs/plugins/html/ch01.html @@ -0,0 +1,94 @@ + + + + +gstreamer Elements: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+

+gstreamer Elements

+
+
+capsfilter +
+
+concat +
+
+dataurisrc +
+
+downloadbuffer +
+
+fakesink +
+
+fakesrc +
+
+fdsink +
+
+fdsrc +
+
+filesink +
+
+filesrc +
+
+funnel +
+
+identity +
+
+input-selector +
+
+multiqueue +
+
+output-selector +
+
+queue2 +
+
+queue +
+
+streamiddemux +
+
+tee +
+
+typefind +
+
+valve +
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/ch02.html b/docs/plugins/html/ch02.html new file mode 100644 index 0000000..a02705b --- /dev/null +++ b/docs/plugins/html/ch02.html @@ -0,0 +1,46 @@ + + + + +gstreamer Tracers: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+

+gstreamer Tracers

+
+
+latencytracer — log processing latency stats +
+
+leakstracer — detect GstObject and GstMiniObject leaks +
+
+logtracer — log hook event +
+
+rusagetracer — log resource usage stats +
+
+statstracer — log event stats +
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/ch03.html b/docs/plugins/html/ch03.html new file mode 100644 index 0000000..26bf124 --- /dev/null +++ b/docs/plugins/html/ch03.html @@ -0,0 +1,37 @@ + + + + +gstreamer Plugins: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+

+gstreamer Plugins

+
+
+coreelements — GStreamer core elements +
+
+coretracers — GStreamer core tracers +
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-1.0.devhelp2 b/docs/plugins/html/gstreamer-plugins-1.0.devhelp2 new file mode 100644 index 0000000..dd296f0 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-1.0.devhelp2 @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/plugins/html/gstreamer-plugins-capsfilter.html b/docs/plugins/html/gstreamer-plugins-capsfilter.html new file mode 100644 index 0000000..0ee6527 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-capsfilter.html @@ -0,0 +1,264 @@ + + + + +capsfilter: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

capsfilter

+

capsfilter

+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+GstCaps *capsRead / Write
GstCapsFilterCapsChangeModecaps-change-modeRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstCapsFilter
enumGstCapsFilterCapsChangeMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseTransform
+                    ╰── GstCapsFilter
+
+
+
+

Description

+

The element does not modify data as such, but can enforce limitations on the +data format.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 videotestsrc ! capsfilter caps=video/x-raw,format=GRAY8 ! videoconvert ! autovideosink
+
+ +

Limits acceptable video from videotestsrc to be grayscale. Equivalent to

+
+ + + + + + + +
1
gst-launch-1.0 videotestsrc ! video/x-raw,format=GRAY8 ! videoconvert ! autovideosink
+
+ +

which is a short notation for the capsfilter element.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

David Schleef <ds@schleef.org>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstCapsFilter

+
struct GstCapsFilter;
+

The opaque GstCapsFilter data structure.

+
+
+
+

enum GstCapsFilterCapsChangeMode

+

Filter caps change behaviour

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_CAPS_FILTER_CAPS_CHANGE_MODE_IMMEDIATE

+

Only accept the current filter caps

+
 

GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED

+

Temporarily accept previous filter caps

+
 
+
+
+
+
+

Property Details

+
+

The “caps” property

+
  “caps”                     GstCaps *
+

Restrict the possible allowed capabilities (NULL means ANY). Setting this property takes a reference to the supplied GstCaps object.

+

Flags: Read / Write

+
+
+
+

The “caps-change-mode” property

+
  “caps-change-mode”         GstCapsFilterCapsChangeMode
+

Filter caps change behaviour.

+

Flags: Read / Write

+

Default value: Only accept the current filter caps

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-concat.html b/docs/plugins/html/gstreamer-plugins-concat.html new file mode 100644 index 0000000..febb3c5 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-concat.html @@ -0,0 +1,227 @@ + + + + +concat: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

concat

+

concat

+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+GstPad *active-padRead
gbooleanadjust-baseRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstConcat
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstConcat
+
+
+
+

Description

+

Concatenates streams together to one continous stream.

+

All streams but the current one are blocked until the current one +finished with GST_EVENT_EOS. Then the next stream is enabled, while +keeping the running time continous for GST_FORMAT_TIME segments or +keeping the segment continous for GST_FORMAT_BYTES segments.

+

Streams are switched in the order in which the sinkpads were requested.

+

By default, the stream segment's base values are adjusted to ensure +the segment transitions between streams are continuous. In some cases, +it may be desirable to turn off these adjustments (for example, because +another downstream element like a streamsynchronizer adjusts the base +values on its own). The adjust-base property can be used for this purpose.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 concat name=c ! xvimagesink  videotestsrc num-buffers=100 ! c.   videotestsrc num-buffers=100 pattern=ball ! c.
+
+ +

Plays two video streams one after another.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Sebastian Dröge <sebastian@centricular.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink_%u

direction

sink

presence

request

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstConcat

+
struct GstConcat;
+

The private concat structure

+
+
+
+

Property Details

+
+

The “active-pad” property

+
  “active-pad”               GstPad *
+

Currently active src pad.

+

Flags: Read

+
+
+
+

The “adjust-base” property

+
  “adjust-base”              gboolean
+

Adjust the base value of segments to ensure they are adjacent.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

See Also

+

GstFunnel

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-dataurisrc.html b/docs/plugins/html/gstreamer-plugins-dataurisrc.html new file mode 100644 index 0000000..909b927 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-dataurisrc.html @@ -0,0 +1,183 @@ + + + + +dataurisrc: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

dataurisrc

+

dataurisrc

+
+
+

Properties

+
+++++ + + + + + +
+gchar *uriRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstDataURISrc
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstDataURISrc
+
+
+
+

Implemented Interfaces

+

+GstDataURISrc implements + GstURIHandler.

+
+
+

Description

+

dataurisrc handles data: URIs, see RFC 2397 for more information.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 -v dataurisrc uri="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfElEQVQ4je2MwQnAIAxFgziA4EnczIsO4MEROo/gzZWc4xdTbe1R6LGRR74heYS7iKElzfcMiRnt4hf8gk8EayB6luefue/HzlJfCA50XsNjYRxprZmenXNIKSGEsC+QUqK1hhgj521BzhnWWiilUGvdF5RS4L2HMQZCCJy8sHMm2TYdJAAAAABJRU5ErkJggg==" ! pngdec ! videoconvert ! imagefreeze ! videoconvert ! autovideosink
+
+ +

+

This pipeline displays a small 16x16 PNG image from the data URI.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Philippe Normand <pnormand@igalia.com>, Sebastian Dröge <sebastian.droege@collabora.co.uk>

class

Source
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstDataURISrc

+
struct GstDataURISrc;
+
+
+
+

Property Details

+
+

The “uri” property

+
  “uri”                      gchar *
+

URI that should be used.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-downloadbuffer.html b/docs/plugins/html/gstreamer-plugins-downloadbuffer.html new file mode 100644 index 0000000..2666738 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-downloadbuffer.html @@ -0,0 +1,285 @@ + + + + +downloadbuffer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

downloadbuffer

+

downloadbuffer

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ginthigh-percentRead / Write
gintlow-percentRead / Write
guintmax-size-bytesRead / Write
guint64max-size-timeRead / Write
+gchar *temp-locationRead
gbooleantemp-removeRead / Write
+gchar *temp-templateRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstDownloadBuffer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstDownloadBuffer
+
+
+
+

Description

+

The downloadbuffer element provides on-disk buffering and caching of, typically, +a network file. temp-template should be set to a value such as +/tmp/gstreamer-XXXXXX and the element will allocate a random free filename and +buffer the data in the file.

+

With max-size-bytes and max-size-time you can configure the buffering limits. +The downloadbuffer element will try to read-ahead these amounts of data. When +the amount of read-ahead data drops below low-percent of the configured max, +the element will start emitting BUFFERING messages until high-percent of max is +reached again.

+

The downloadbuffer provides push and pull based scheduling on its source pad +and will efficiently seek in the upstream element when needed.

+

The temp-location property will be used to notify the application of the +allocated filename.

+

When the downloadbuffer has completely downloaded the media, it will +post an application message named "GstCacheDownloadComplete" +with the following information:

+

* + G_TYPE_STRING

+"location": +

the location of the completely downloaded file.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Wim Taymans <wim.taymans@gmail.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstDownloadBuffer

+
struct GstDownloadBuffer;
+
+
+
+

Property Details

+
+

The “high-percent” property

+
  “high-percent”             gint
+

High threshold for buffering to finish. Only used if use-buffering is True.

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 99

+
+
+
+

The “low-percent” property

+
  “low-percent”              gint
+

Low threshold for buffering to start. Only used if use-buffering is True.

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 10

+
+
+
+

The “max-size-bytes” property

+
  “max-size-bytes”           guint
+

Max. amount of data to buffer (bytes, 0=disable).

+

Flags: Read / Write

+

Default value: 2097152

+
+
+
+

The “max-size-time” property

+
  “max-size-time”            guint64
+

Max. amount of data to buffer (in ns, 0=disable).

+

Flags: Read / Write

+

Default value: 2000000000

+
+
+
+

The “temp-location” property

+
  “temp-location”            gchar *
+

Location to store temporary files in (Only read this property, use temp-template to configure the name template).

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “temp-remove” property

+
  “temp-remove”              gboolean
+

When temp-template is set, remove the temporary file when going to READY.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “temp-template” property

+
  “temp-template”            gchar *
+

File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled).

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-fakesink.html b/docs/plugins/html/gstreamer-plugins-fakesink.html new file mode 100644 index 0000000..247b1ba --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-fakesink.html @@ -0,0 +1,470 @@ + + + + +fakesink: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

fakesink

+

fakesink

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleancan-activate-pullRead / Write
gbooleancan-activate-pushRead / Write
gbooleandumpRead / Write
+gchar *last-messageRead
gintnum-buffersRead / Write
gbooleansignal-handoffsRead / Write
gbooleansilentRead / Write
GstFakeSinkStateErrorstate-errorRead / Write
gbooleandrop-out-of-segmentRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidhandoffRun Last
voidpreroll-handoffRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstFakeSink
enumGstFakeSinkStateError
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSink
+                    ╰── GstFakeSink
+
+
+
+

Description

+

Dummy sink that swallows everything.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 audiotestsrc num-buffers=1000 ! fakesink sync=false
+
+ +

Render 1000 audio buffers (of default size) as fast as possible.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>, Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com>

class

Sink
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFakeSink

+
struct GstFakeSink;
+

The opaque GstFakeSink data structure.

+
+
+
+

enum GstFakeSinkStateError

+

Possible state change errors for the state-error property.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

FAKE_SINK_STATE_ERROR_NONE

+

no error

+
 

FAKE_SINK_STATE_ERROR_NULL_READY

+

cause the NULL to READY state change to fail

+
 

FAKE_SINK_STATE_ERROR_READY_PAUSED

+

cause the READY to PAUSED state change to fail:

+
 

FAKE_SINK_STATE_ERROR_PAUSED_PLAYING

+

cause the PAUSED to PLAYING state change to fail:

+
 

FAKE_SINK_STATE_ERROR_PLAYING_PAUSED

+

cause the PLAYING to PAUSED state change to fail:

+
 

FAKE_SINK_STATE_ERROR_PAUSED_READY

+

cause the PAUSED to READY state change to fail:

+
 

FAKE_SINK_STATE_ERROR_READY_NULL

+

cause the READY to NULL state change to fail:

+
 
+
+
+
+
+

Property Details

+
+

The “can-activate-pull” property

+
  “can-activate-pull”        gboolean
+

Can activate in pull mode.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “can-activate-push” property

+
  “can-activate-push”        gboolean
+

Can activate in push mode.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “dump” property

+
  “dump”                     gboolean
+

Dump buffer contents to stdout.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “last-message” property

+
  “last-message”             gchar *
+

The message describing current status.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “num-buffers” property

+
  “num-buffers”              gint
+

Number of buffers to accept going EOS.

+

Flags: Read / Write

+

Allowed values: >= G_MAXULONG

+

Default value: -1

+
+
+
+

The “signal-handoffs” property

+
  “signal-handoffs”          gboolean
+

Send a signal before unreffing the buffer.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “silent” property

+
  “silent”                   gboolean
+

Don't produce last_message events.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “state-error” property

+
  “state-error”              GstFakeSinkStateError
+

Generate a state change error.

+

Flags: Read / Write

+

Default value: No state change errors

+
+
+
+

The “drop-out-of-segment” property

+
  “drop-out-of-segment”      gboolean
+

Drop and don't render / hand off out-of-segment buffers.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

Signal Details

+
+

The “handoff” signal

+
void
+user_function (GstFakeSink *fakesink,
+               GstBuffer   *buffer,
+               GstPad      *pad,
+               gpointer     user_data)
+

This signal gets emitted before unreffing the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

fakesink

the fakesink instance

 

buffer

the buffer that just has been received

 

pad

the pad that received it

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “preroll-handoff” signal

+
void
+user_function (GstFakeSink *fakesink,
+               GstBuffer   *buffer,
+               GstPad      *pad,
+               gpointer     user_data)
+

This signal gets emitted before unreffing the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

fakesink

the fakesink instance

 

buffer

the buffer that just has been received

 

pad

the pad that received it

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

See Also

+

GstFakeSrc

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-fakesrc.html b/docs/plugins/html/gstreamer-plugins-fakesrc.html new file mode 100644 index 0000000..0f823e9 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-fakesrc.html @@ -0,0 +1,672 @@ + + + + +fakesrc: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

fakesrc

+

fakesrc

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleancan-activate-pullRead / Write / Construct
gbooleancan-activate-pushRead / Write / Construct
GstFakeSrcDataTypedataRead / Write
gintdatarateRead / Write
gbooleandumpRead / Write
GstFakeSrcFillTypefilltypeRead / Write
GstFormatformatRead / Write
gbooleanis-liveRead / Write / Construct
+gchar *last-messageRead
gintparentsizeRead / Write
+gchar *patternRead / Write
gbooleansignal-handoffsRead / Write
gbooleansilentRead / Write
gintsizemaxRead / Write
gintsizeminRead / Write
GstFakeSrcSizeTypesizetypeRead / Write
gbooleansyncRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidhandoffRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
structGstFakeSrc
enumGstFakeSrcDataType
enumGstFakeSrcFillType
enumGstFakeSrcOutputType
enumGstFakeSrcSizeType
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstFakeSrc
+
+
+
+

Description

+

The fakesrc element is a multipurpose element that can generate +a wide range of buffers and can operate in various scheduling modes.

+

It is mostly used as a testing element, one trivial example for testing +basic GStreamer core functionality is:

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 -v fakesrc num-buffers=5 ! fakesink
+
+ +

This pipeline will push 5 empty buffers to the fakesink element and then +sends an EOS.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>

class

Source
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFakeSrc

+
struct GstFakeSrc;
+

Opaque GstFakeSrc data structure.

+
+
+
+

enum GstFakeSrcDataType

+

The different ways buffers are allocated.

+
+

Members

+
+++++ + + + + + + + + + + + + +

FAKE_SRC_DATA_ALLOCATE

+

allocate buffers

+
 

FAKE_SRC_DATA_SUBBUFFER

+

subbuffer each buffer

+
 
+
+
+
+
+

enum GstFakeSrcFillType

+

The different ways of filling the buffers.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

FAKE_SRC_FILLTYPE_NOTHING

+

do not fill buffers

+
 

FAKE_SRC_FILLTYPE_ZERO

+

fill buffers with 0

+
 

FAKE_SRC_FILLTYPE_RANDOM

+

fill buffers with random bytes

+
 

FAKE_SRC_FILLTYPE_PATTERN

+

fill buffers with a pattern

+
 

FAKE_SRC_FILLTYPE_PATTERN_CONT

+

fill buffers with a continuous pattern

+
 
+
+
+
+
+

enum GstFakeSrcOutputType

+

The different output types. Unused currently.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

FAKE_SRC_FIRST_LAST_LOOP

+

first pad then last pad

+
 

FAKE_SRC_LAST_FIRST_LOOP

+

last pad then first pad

+
 

FAKE_SRC_PING_PONG

+

ping pong between pads

+
 

FAKE_SRC_ORDERED_RANDOM

+

ordered random pad

+
 

FAKE_SRC_RANDOM

+

random pad

+
 

FAKE_SRC_PATTERN_LOOP

+

loop between pads in a particular pattern

+
 

FAKE_SRC_PING_PONG_PATTERN

+

ping pong based on a pattern

+
 

FAKE_SRC_GET_ALWAYS_SUCEEDS

+

a get always succeeds on a pad

+
 
+
+
+
+
+

enum GstFakeSrcSizeType

+

The different size of the allocated buffers.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

FAKE_SRC_SIZETYPE_EMPTY

+

create empty buffers

+
 

FAKE_SRC_SIZETYPE_FIXED

+

fixed buffer size (sizemax sized)

+
 

FAKE_SRC_SIZETYPE_RANDOM

+

random buffer size (sizemin <= size <= sizemax)

+
 
+
+
+
+
+

Property Details

+
+

The “can-activate-pull” property

+
  “can-activate-pull”        gboolean
+

Can activate in pull mode.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+
+
+
+

The “can-activate-push” property

+
  “can-activate-push”        gboolean
+

Can activate in push mode.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+
+
+
+

The “data” property

+
  “data”                     GstFakeSrcDataType
+

Data allocation method.

+

Flags: Read / Write

+

Default value: Allocate data

+
+
+
+

The “datarate” property

+
  “datarate”                 gint
+

Timestamps buffers with number of bytes per second (0 = none).

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “dump” property

+
  “dump”                     gboolean
+

Dump buffer contents to stdout.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “filltype” property

+
  “filltype”                 GstFakeSrcFillType
+

How to fill the buffer, if at all.

+

Flags: Read / Write

+

Default value: Fill buffers with zeros

+
+
+
+

The “format” property

+
  “format”                   GstFormat
+

Set the format of the newsegment events to produce.

+

Flags: Read / Write

+

Default value: GST_FORMAT_BYTES

+
+
+
+

The “is-live” property

+
  “is-live”                  gboolean
+

True if the element cannot produce data in PAUSED.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+
+
+
+

The “last-message” property

+
  “last-message”             gchar *
+

The last status message.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “parentsize” property

+
  “parentsize”               gint
+

Size of parent buffer for sub-buffered allocation.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 40960

+
+
+
+

The “pattern” property

+
  “pattern”                  gchar *
+

Set the pattern (unused).

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “signal-handoffs” property

+
  “signal-handoffs”          gboolean
+

Send a signal before pushing the buffer.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “silent” property

+
  “silent”                   gboolean
+

Don't produce last_message events.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “sizemax” property

+
  “sizemax”                  gint
+

Maximum buffer size.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 4096

+
+
+
+

The “sizemin” property

+
  “sizemin”                  gint
+

Minimum buffer size.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “sizetype” property

+
  “sizetype”                 GstFakeSrcSizeType
+

How to determine buffer sizes.

+

Flags: Read / Write

+

Default value: Send empty buffers

+
+
+
+

The “sync” property

+
  “sync”                     gboolean
+

Sync to the clock to the datarate.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “handoff” signal

+
void
+user_function (GstFakeSrc *fakesrc,
+               GstBuffer  *buffer,
+               GstPad     *pad,
+               gpointer    user_data)
+

This signal gets emitted before sending the buffer.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

fakesrc

the fakesrc instance

 

buffer

the buffer that will be pushed

 

pad

the pad that will sent it

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

See Also

+

GstFakeSink

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-fdsink.html b/docs/plugins/html/gstreamer-plugins-fdsink.html new file mode 100644 index 0000000..f775f57 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-fdsink.html @@ -0,0 +1,175 @@ + + + + +fdsink: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

fdsink

+

fdsink

+
+
+

Properties

+
+++++ + + + + + +
gintfdRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstFdSink
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSink
+                    ╰── GstFdSink
+
+
+
+

Implemented Interfaces

+

+GstFdSink implements + GstURIHandler.

+
+
+

Description

+

Write data to a unix file descriptor.

+

This element will synchronize on the clock before writing the data on the +socket. For file descriptors where this does not make sense (files, ...) the +“sync” property can be used to disable synchronisation.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>

class

Sink/File
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFdSink

+
struct GstFdSink;
+

The opaque GstFdSink data structure.

+
+
+
+

Property Details

+
+

The “fd” property

+
  “fd”                       gint
+

An open file descriptor to write to.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 1

+
+
+
+

See Also

+

GstFdSrc

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-fdsrc.html b/docs/plugins/html/gstreamer-plugins-fdsrc.html new file mode 100644 index 0000000..8cc39ae --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-fdsrc.html @@ -0,0 +1,212 @@ + + + + +fdsrc: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

fdsrc

+

fdsrc

+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
gintfdRead / Write
guint64timeoutRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstFdSrc
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstPushSrc
+                        ╰── GstFdSrc
+
+
+
+

Implemented Interfaces

+

+GstFdSrc implements + GstURIHandler.

+
+
+

Description

+

Read data from a unix file descriptor.

+

To generate data, enter some data on the console followed by enter. +The above mentioned pipeline should dump data packets to the console.

+

If the “timeout” property is set to a value bigger than 0, fdsrc will +generate an element message named "GstFdSrcTimeout" +if no data was received in the given timeout.

+

The message's structure contains one field:

+
  • guint64 timeout: the timeout in microseconds that +expired when waiting for data.

+
+

Example launch line

+
+ + + + + + + +
1
echo "Hello GStreamer" | gst-launch-1.0 -v fdsrc ! fakesink dump=true
+
+ +

A simple pipeline to read from the standard input and dump the data +with a fakesink as hex ascii block.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>

class

Source/File
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFdSrc

+
struct GstFdSrc;
+

Opaque GstFdSrc data structure.

+
+
+
+

Property Details

+
+

The “fd” property

+
  “fd”                       gint
+

An open file descriptor to read from.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “timeout” property

+
  “timeout”                  guint64
+

Post a message after timeout microseconds

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

See Also

+

GstFdSink

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-filesink.html b/docs/plugins/html/gstreamer-plugins-filesink.html new file mode 100644 index 0000000..f73ce51 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-filesink.html @@ -0,0 +1,279 @@ + + + + +filesink: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

filesink

+

filesink

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
gbooleanappendRead / Write
GstFileSinkBufferModebuffer-modeRead / Write
guintbuffer-sizeRead / Write
+gchar *locationRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstFileSink
enumGstFileSinkBufferMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSink
+                    ╰── GstFileSink
+
+
+
+

Implemented Interfaces

+

+GstFileSink implements + GstURIHandler.

+
+
+

Description

+

Write incoming data to a file in the local file system.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 v4l2src num-buffers=1 ! jpegenc ! filesink location=capture1.jpeg
+
+ +

Capture one frame from a v4l2 camera and save as jpeg image.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Thomas Vander Stichele <thomas at apestaart dot org>

class

Sink/File
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFileSink

+
struct GstFileSink;
+

Opaque GstFileSink structure.

+
+
+
+

enum GstFileSinkBufferMode

+

File read buffering mode.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

GST_FILE_SINK_BUFFER_MODE_DEFAULT

+

Default buffering

+
 

GST_FILE_SINK_BUFFER_MODE_FULL

+

Fully buffered

+
 

GST_FILE_SINK_BUFFER_MODE_LINE

+

Line buffered

+
 

GST_FILE_SINK_BUFFER_MODE_UNBUFFERED

+

Unbuffered

+
 
+
+
+
+
+

Property Details

+
+

The “append” property

+
  “append”                   gboolean
+

Append to an already existing file.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “buffer-mode” property

+
  “buffer-mode”              GstFileSinkBufferMode
+

The buffering mode to use.

+

Flags: Read / Write

+

Default value: Default buffering

+
+
+
+

The “buffer-size” property

+
  “buffer-size”              guint
+

Size of buffer in number of bytes for line or full buffer-mode.

+

Flags: Read / Write

+

Default value: 65536

+
+
+
+

The “location” property

+
  “location”                 gchar *
+

Location of the file to write.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

See Also

+

GstFileSrc

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-filesrc.html b/docs/plugins/html/gstreamer-plugins-filesrc.html new file mode 100644 index 0000000..0c271ab --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-filesrc.html @@ -0,0 +1,187 @@ + + + + +filesrc: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

filesrc

+

filesrc

+
+
+

Properties

+
+++++ + + + + + +
+gchar *locationRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstFileSrc
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseSrc
+                    ╰── GstFileSrc
+
+
+
+

Implemented Interfaces

+

+GstFileSrc implements + GstURIHandler.

+
+
+

Description

+

Read data from a file in the local file system.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 filesrc location=song.ogg ! decodebin ! audioconvert ! audioresample ! autoaudiosink
+
+ +

Play song.ogg audio file which must be in the current working directory.

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>

class

Source/File
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFileSrc

+
struct GstFileSrc;
+

Opaque GstFileSrc structure.

+
+
+
+

Property Details

+
+

The “location” property

+
  “location”                 gchar *
+

Location of the file to read.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

See Also

+

GstFileSrc

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-funnel.html b/docs/plugins/html/gstreamer-plugins-funnel.html new file mode 100644 index 0000000..2274668 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-funnel.html @@ -0,0 +1,189 @@ + + + + +funnel: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

funnel

+

funnel

+
+
+

Properties

+
+++++ + + + + + +
gbooleanforward-sticky-eventsRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstFunnel
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstFunnel
+
+
+
+

Description

+

Takes packets from various input sinks into one output source.

+

funnel always outputs a single, open ended segment from +0 with in GST_FORMAT_TIME and outputs the buffers of the +different sinkpads with timestamps that are set to the +running time for that stream. funnel does not synchronize +the different input streams but simply forwards all buffers +immediately when they arrive.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Olivier Crete <olivier.crete@collabora.co.uk>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink_%u

direction

sink

presence

request

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstFunnel

+
struct GstFunnel;
+

Opaque GstFunnel data structure.

+
+
+
+

Property Details

+
+

The “forward-sticky-events” property

+
  “forward-sticky-events”    gboolean
+

Forward sticky events on stream changes.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-identity.html b/docs/plugins/html/gstreamer-plugins-identity.html new file mode 100644 index 0000000..e130714 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-identity.html @@ -0,0 +1,433 @@ + + + + +identity: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

identity

+

identity

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleancheck-imperfect-offsetRead / Write
gbooleancheck-imperfect-timestampRead / Write
gintdatarateRead / Write
gfloatdrop-probabilityRead / Write
gbooleandumpRead / Write
ginterror-afterRead / Write
+gchar *last-messageRead
gbooleansignal-handoffsRead / Write
gbooleansilentRead / Write
gbooleansingle-segmentRead / Write
guintsleep-timeRead / Write
gbooleansyncRead / Write
GstBufferFlagsdrop-buffer-flagsRead / Write
gint64ts-offsetRead / Write
gbooleandrop-allocationRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidhandoffRun Last
+
+
+

Types and Values

+
++++ + + + + +
structGstIdentity
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstBaseTransform
+                    ╰── GstIdentity
+
+
+
+

Description

+

Dummy element that passes incoming data through unmodified. It has some +useful diagnostic functions, such as offset and timestamp checking.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstIdentity

+
struct GstIdentity;
+

Opaque GstIdentity data structure

+
+
+
+

Property Details

+
+

The “check-imperfect-offset” property

+
  “check-imperfect-offset”   gboolean
+

Send element messages if offset and offset_end do not match up.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “check-imperfect-timestamp” property

+
  “check-imperfect-timestamp” gboolean
+

Send element messages if timestamps and durations do not match up.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “datarate” property

+
  “datarate”                 gint
+

(Re)timestamps buffers with number of bytes per second (0 = inactive).

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “drop-probability” property

+
  “drop-probability”         gfloat
+

The Probability a buffer is dropped.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 0

+
+
+
+

The “dump” property

+
  “dump”                     gboolean
+

Dump buffer contents to stdout.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “error-after” property

+
  “error-after”              gint
+

Error after N buffers.

+

Flags: Read / Write

+

Default value: -1

+
+
+
+

The “last-message” property

+
  “last-message”             gchar *
+

last-message.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “signal-handoffs” property

+
  “signal-handoffs”          gboolean
+

If set to TRUE, the identity will emit a handoff signal when handling a buffer. +When set to FALSE, no signal will be emitted, which might improve performance.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “silent” property

+
  “silent”                   gboolean
+

silent.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “single-segment” property

+
  “single-segment”           gboolean
+

Timestamp buffers and eat segments so as to appear as one segment.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “sleep-time” property

+
  “sleep-time”               guint
+

Microseconds to sleep between processing.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “sync” property

+
  “sync”                     gboolean
+

Synchronize to pipeline clock.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “drop-buffer-flags” property

+
  “drop-buffer-flags”        GstBufferFlags
+

Drop buffers with the given flags.

+

Flags: Read / Write

+

Since: 1.8

+
+
+
+

The “ts-offset” property

+
  “ts-offset”                gint64
+

Timestamp offset in nanoseconds for synchronisation, negative for earlier sync.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “drop-allocation” property

+
  “drop-allocation”          gboolean
+

Don't forward allocation queries.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “handoff” signal

+
void
+user_function (GstIdentity *identity,
+               GstBuffer   *buffer,
+               gpointer     user_data)
+

This signal gets emitted before passing the buffer downstream.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

identity

the identity instance

 

buffer

the buffer that just has been received

 

pad

the pad that received it

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-input-selector.html b/docs/plugins/html/gstreamer-plugins-input-selector.html new file mode 100644 index 0000000..526f5b4 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-input-selector.html @@ -0,0 +1,300 @@ + + + + +input-selector: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

input-selector

+

input-selector

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstPad *active-padRead / Write
gbooleancache-buffersRead / Write
guintn-padsRead
GstInputSelectorSyncModesync-modeRead / Write
gbooleansync-streamsRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstInputSelector
enumGstInputSelectorSyncMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstInputSelector
+
+
+
+

Description

+

Direct one out of N input streams to the output pad.

+

The input pads are from a GstPad subclass and have additional +properties, which users may find useful, namely:

+
    +
  • "running-time": Running time of stream on pad (gint64)

  • +
  • "tags": The currently active tags on the pad (GstTagList, boxed type)

  • +
  • "active": If the pad is currently active (gboolean)

  • +
  • "always-ok" : Make an inactive pads return GST_FLOW_OK instead of +GST_FLOW_NOT_LINKED

  • +
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Julien Moutte <julien@moutte.net>, Jan Schmidt <thaytan@mad.scientist.com>, Wim Taymans <wim.taymans@gmail.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink_%u

direction

sink

presence

request

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstInputSelector

+
struct GstInputSelector;
+
+
+
+

enum GstInputSelectorSyncMode

+

The different ways that input-selector can behave when in sync-streams mode.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT

+

Sync using the current active segment.

+
 

GST_INPUT_SELECTOR_SYNC_MODE_CLOCK

+

Sync using the clock.

+
 
+
+
+
+
+

Property Details

+
+

The “active-pad” property

+
  “active-pad”               GstPad *
+

The currently active sink pad.

+

Flags: Read / Write

+
+
+
+

The “cache-buffers” property

+
  “cache-buffers”            gboolean
+

If set to TRUE and GstInputSelector:sync-streams is also set to TRUE, +the active pad will cache the buffers still considered valid (after current +running time, see sync-mode) to avoid missing frames if/when the pad is +reactivated.

+

The active pad may push more buffers than what is currently displayed/consumed +and when changing pads those buffers will be discarded and the only way to +reactivate that pad without loosing the already consumed buffers is to enable cache.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “n-pads” property

+
  “n-pads”                   guint
+

The number of sink pads.

+

Flags: Read

+

Default value: 0

+
+
+
+

The “sync-mode” property

+
  “sync-mode”                GstInputSelectorSyncMode
+

Select how input-selector will sync buffers when in sync-streams mode.

+

Note that when using the "active-segment" mode, the "active-segment" may +be ahead of current clock time when switching the active pad, as the current +active pad may have pushed more buffers than what was displayed/consumed, +which may cause delays and some missing buffers.

+

Flags: Read / Write

+

Default value: Sync using the current active segment

+
+
+
+

The “sync-streams” property

+
  “sync-streams”             gboolean
+

If set to TRUE all inactive streams will be synced to the +running time of the active stream or to the current clock.

+

To make sure no buffers are dropped by input-selector +that might be needed when switching the active pad, +sync-mode should be set to "clock" and cache-buffers to TRUE.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

See Also

+

GstOutputSelector

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-latencytracer.html b/docs/plugins/html/gstreamer-plugins-latencytracer.html new file mode 100644 index 0000000..00296e8 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-latencytracer.html @@ -0,0 +1,78 @@ + + + + +latencytracer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

latencytracer

+

latencytracer — log processing latency stats

+
+
+

Types and Values

+
++++ + + + + +
structGstLatencyTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+                ╰── GstLatencyTracer
+
+
+
+

Description

+

A tracing module that determines src-to-sink latencies by injecting custom +events at sources and process them at sinks.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstLatencyTracer

+
struct GstLatencyTracer;
+

Opaque GstLatencyTracer data structure

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-leakstracer.html b/docs/plugins/html/gstreamer-plugins-leakstracer.html new file mode 100644 index 0000000..f931eba --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-leakstracer.html @@ -0,0 +1,80 @@ + + + + +leakstracer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

leakstracer

+

leakstracer — detect GstObject and GstMiniObject leaks

+
+
+

Types and Values

+
++++ + + + + +
structGstLeaksTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+                ╰── GstLeaksTracer
+
+
+
+

Description

+

A tracing module tracking the lifetime of objects by logging those still +alive when program is exiting and raising a warning. +The type of objects tracked can be filtered using the parameters of the +tracer, for example: GST_TRACERS=leaks(filters="GstEvent,GstMessage",stack-traces-flags=full)

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstLeaksTracer

+
struct GstLeaksTracer;
+

Opaque GstLeaksTracer data structure

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-logtracer.html b/docs/plugins/html/gstreamer-plugins-logtracer.html new file mode 100644 index 0000000..a409c37 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-logtracer.html @@ -0,0 +1,77 @@ + + + + +logtracer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

logtracer

+

logtracer — log hook event

+
+
+

Types and Values

+
++++ + + + + +
structGstLogTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+                ╰── GstLogTracer
+
+
+
+

Description

+

A tracing module that logs all data from all hooks.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstLogTracer

+
struct GstLogTracer;
+

Opaque GstLogTracer data structure

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-multiqueue.html b/docs/plugins/html/gstreamer-plugins-multiqueue.html new file mode 100644 index 0000000..1684399 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-multiqueue.html @@ -0,0 +1,523 @@ + + + + +multiqueue: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

multiqueue

+

multiqueue

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
guintextra-size-buffersRead / Write
guintextra-size-bytesRead / Write
guint64extra-size-timeRead / Write
ginthigh-percentRead / Write
gintlow-percentRead / Write
guintmax-size-buffersRead / Write
guintmax-size-bytesRead / Write
guint64max-size-timeRead / Write
gbooleansync-by-running-timeRead / Write
gbooleanuse-bufferingRead / Write
guint64unlinked-cache-timeRead / Write
gbooleanuse-interleaveRead / Write
gdoublehigh-watermarkRead / Write
gdoublelow-watermarkRead / Write
guint64min-interleave-timeRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidoverrunRun First
voidunderrunRun First
+
+
+

Types and Values

+
++++ + + + + +
structGstMultiQueue
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstMultiQueue
+
+
+
+

Description

+

Multiqueue is similar to a normal GstQueue with the following additional +features:

+

1) Multiple streamhandling

+
  • The element handles queueing data on more than one stream at once. To +achieve such a feature it has request sink pads (sinku) and +'sometimes' src pads (srcu). When requesting a given sinkpad with gst_element_request_pad(), +the associated srcpad for that stream will be created. +Example: requesting sink1 will generate src1.

+

2) Non-starvation on multiple stream

+
  • 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 will be +considered as 'not-empty' in the queue-size-growing algorithm.

+

3) Non-linked srcpads graceful handling

+
  • 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.

+

Data is queued until one of the limits specified by the +“max-size-buffers”, “max-size-bytes” and/or +“max-size-time” properties has been reached. Any attempt to push +more buffers into the queue will block the pushing thread until more space +becomes available. “extra-size-buffers”,

+

“extra-size-bytes” and “extra-size-time” are +currently unused.

+

The default queue size limits are 5 buffers, 10MB of data, or +two second worth of data, whichever is reached first. Note that the number +of buffers will dynamically grow depending on the fill level of +other queues.

+

The “underrun” signal is emitted when all of the queues +are empty. The “overrun” signal is emitted when one of the +queues is filled. +Both signals are emitted from the context of the streaming thread.

+

When using “sync-by-running-time” the unlinked streams will +be throttled by the highest running-time of linked streams. This allows +further relinking of those unlinked streams without them being in the +future (i.e. to achieve gapless playback). +When dealing with streams which have got different consumption requirements +downstream (ex: video decoders which will consume more buffer (in time) than +audio decoders), it is recommended to group streams of the same type +by using the pad "group-id" property. This will further throttle streams +in time within that group.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Edward Hervey <edward@fluendo.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink_%u

direction

sink

presence

request

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src_%u

direction

source

presence

sometimes

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstMultiQueue

+
struct GstMultiQueue;
+

Opaque GstMultiQueue structure.

+
+
+
+

Property Details

+
+

The “extra-size-buffers” property

+
  “extra-size-buffers”       guint
+

Amount of buffers the queues can grow if one of them is empty (0=disable) (NOT IMPLEMENTED).

+

Flags: Read / Write

+

Default value: 5

+
+
+
+

The “extra-size-bytes” property

+
  “extra-size-bytes”         guint
+

Amount of data the queues can grow if one of them is empty (bytes, 0=disable) (NOT IMPLEMENTED).

+

Flags: Read / Write

+

Default value: 10485760

+
+
+
+

The “extra-size-time” property

+
  “extra-size-time”          guint64
+

Amount of time the queues can grow if one of them is empty (in ns, 0=disable) (NOT IMPLEMENTED).

+

Flags: Read / Write

+

Default value: 3000000000

+
+
+
+

The “high-percent” property

+
  “high-percent”             gint
+

High threshold percent for buffering to finish.

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 99

+
+
+
+

The “low-percent” property

+
  “low-percent”              gint
+

Low threshold percent for buffering to start.

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 1

+
+
+
+

The “max-size-buffers” property

+
  “max-size-buffers”         guint
+

Max. number of buffers in the queue (0=disable).

+

Flags: Read / Write

+

Default value: 5

+
+
+
+

The “max-size-bytes” property

+
  “max-size-bytes”           guint
+

Max. amount of data in the queue (bytes, 0=disable).

+

Flags: Read / Write

+

Default value: 10485760

+
+
+
+

The “max-size-time” property

+
  “max-size-time”            guint64
+

Max. amount of data in the queue (in ns, 0=disable).

+

Flags: Read / Write

+

Default value: 2000000000

+
+
+
+

The “sync-by-running-time” property

+
  “sync-by-running-time”     gboolean
+

If enabled multiqueue will synchronize deactivated or not-linked streams +to the activated and linked streams by taking the running time. +Otherwise multiqueue will synchronize the deactivated or not-linked +streams by keeping the order in which buffers and events arrived compared +to active and linked streams.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “use-buffering” property

+
  “use-buffering”            gboolean
+

Enable the buffering option in multiqueue so that BUFFERING messages are +emitted based on low-/high-percent thresholds.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “unlinked-cache-time” property

+
  “unlinked-cache-time”      guint64
+

Extra buffering in time for unlinked streams (if 'sync-by-running-time').

+

Flags: Read / Write

+

Default value: 250000000

+
+
+
+

The “use-interleave” property

+
  “use-interleave”           gboolean
+

Adjust time limits based on input interleave.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “high-watermark” property

+
  “high-watermark”           gdouble
+

High threshold watermark for buffering to finish.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 0.99

+

Since: 1.10

+
+
+
+

The “low-watermark” property

+
  “low-watermark”            gdouble
+

Low threshold watermark for buffering to start.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 0.01

+

Since: 1.10

+
+
+
+

The “min-interleave-time” property

+
  “min-interleave-time”      guint64
+

Minimum extra buffering for deinterleaving (size of the queues) when use-interleave=true.

+

Flags: Read / Write

+

Default value: 250000000

+
+
+
+

Signal Details

+
+

The “overrun” signal

+
void
+user_function (GstMultiQueue *multiqueue,
+               gpointer       user_data)
+

Reports that one of the queues in the multiqueue is full (overrun). +A queue is full if the total amount of data inside it (num-buffers, time, +size) is higher than the boundary values which can be set through the +GObject properties.

+

This can be used as an indicator of pre-roll.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

multiqueue

the multiqueue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “underrun” signal

+
void
+user_function (GstMultiQueue *multiqueue,
+               gpointer       user_data)
+

This signal is emitted from the streaming thread when there is +no data in any of the queues inside the multiqueue instance (underrun).

+

This indicates either starvation or EOS from the upstream data sources.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

multiqueue

the multiqueue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

GstQueue

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-output-selector.html b/docs/plugins/html/gstreamer-plugins-output-selector.html new file mode 100644 index 0000000..e0877ae --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-output-selector.html @@ -0,0 +1,262 @@ + + + + +output-selector: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

output-selector

+

output-selector

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
+GstPad *active-padRead / Write
GstOutputSelectorPadNegotiationModepad-negotiation-modeRead / Write
gbooleanresend-latestRead / Write
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstOutputSelector
enumGstOutputSelectorPadNegotiationMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstOutputSelector
+
+
+
+

Description

+

Direct input stream to one out of N output pads.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Stefan Kost <stefan.kost@nokia.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src_%u

direction

source

presence

request

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstOutputSelector

+
struct GstOutputSelector;
+
+
+
+

enum GstOutputSelectorPadNegotiationMode

+

To what output pad the input stream should be directed.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE

+

don't propagate the input +stream.

+
 

GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL

+

direct input stream to all +output pads.

+
 

GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ACTIVE

+

direct input stream to the +currently active output pad as described by the “active-pad” +property.

+
 
+
+
+
+
+

Property Details

+
+

The “active-pad” property

+
  “active-pad”               GstPad *
+

Currently active src pad.

+

Flags: Read / Write

+
+
+
+

The “pad-negotiation-mode” property

+
  “pad-negotiation-mode”     GstOutputSelectorPadNegotiationMode
+

The mode to be used for pad negotiation.

+

Flags: Read / Write

+

Default value: All

+
+
+
+

The “resend-latest” property

+
  “resend-latest”            gboolean
+

Resend latest buffer after a switch to a new pad.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+ +
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-plugin-coreelements.html b/docs/plugins/html/gstreamer-plugins-plugin-coreelements.html new file mode 100644 index 0000000..81e7da3 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-plugin-coreelements.html @@ -0,0 +1,161 @@ + + + + +coreelements: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

coreelements

+

coreelements — GStreamer core elements

+
+
+

Plugin Information

+
++++ + + + + + + + + + + + + + + + + + + + + + + +

filename

libgstcoreelements.so

version

1.14.1

run-time license

LGPL

package

GStreamer source release

origin

Unknown package origin
+
+
+

Elements

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

capsfilter

Pass data without modification, limiting formats

concat

Concatenate multiple streams

dataurisrc

Handles data: uris

downloadbuffer

Download Buffer element

fakesink

Black hole for data

fakesrc

Push empty (no data) buffers around

fdsink

Write data to a file descriptor

fdsrc

Read from a file descriptor

filesink

Write stream to a file

filesrc

Read from arbitrary point in a file

funnel

N-to-1 pipe fitting

identity

Pass data without modification

input-selector

N-to-1 input stream selector

multiqueue

Multiple data queue

output-selector

1-to-N output stream selector

queue

Simple data queue

queue2

Simple data queue

streamiddemux

1-to-N output stream by stream-id

tee

1-to-N pipe fitting

typefind

Finds the media type of a stream

valve

Drops buffers and events or lets them through
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-plugin-coretracers.html b/docs/plugins/html/gstreamer-plugins-plugin-coretracers.html new file mode 100644 index 0000000..fdac7d2 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-plugin-coretracers.html @@ -0,0 +1,96 @@ + + + + +coretracers: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + +
+
+
+ + +
+

coretracers

+

coretracers — GStreamer core tracers

+
+
+

Plugin Information

+
++++ + + + + + + + + + + + + + + + + + + + + + + +

filename

libgstcoretracers.so

version

1.14.1

run-time license

LGPL

package

GStreamer source release

origin

Unknown package origin
+
+
+

Elements

+
++++ + + + + + + + + + + + + + + + + + + + + + + +

latency

leaks

log

rusage

stats

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-queue.html b/docs/plugins/html/gstreamer-plugins-queue.html new file mode 100644 index 0000000..9a192e8 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-queue.html @@ -0,0 +1,571 @@ + + + + +queue: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

queue

+

queue

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
guintcurrent-level-buffersRead
guintcurrent-level-bytesRead
guint64current-level-timeRead
gbooleanflush-on-eosRead / Write
GstQueueLeakyleakyRead / Write
guintmax-size-buffersRead / Write
guintmax-size-bytesRead / Write
guint64max-size-timeRead / Write
guintmin-threshold-buffersRead / Write
guintmin-threshold-bytesRead / Write
guint64min-threshold-timeRead / Write
gbooleansilentRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidoverrunRun First
voidpushingRun First
voidrunningRun First
voidunderrunRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstQueue
enumGstQueueLeaky
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstQueue
+
+
+
+

Description

+

Data is queued until one of the limits specified by the +“max-size-buffers”, “max-size-bytes” and/or +“max-size-time” properties has been reached. Any attempt to push +more buffers into the queue will block the pushing thread until more space +becomes available.

+

The queue will create a new thread on the source pad to decouple the +processing on sink and source pad.

+

You can query how many buffers are queued by reading the +“current-level-buffers” property. You can track changes +by connecting to the notify::current-level-buffers signal (which +like all signals will be emitted from the streaming thread). The same +applies to the “current-level-time” and +“current-level-bytes” properties.

+

The default queue size limits are 200 buffers, 10MB of data, or +one second worth of data, whichever is reached first.

+

As said earlier, the queue blocks by default when one of the specified +maximums (bytes, time, buffers) has been reached. You can set the +“leaky” property to specify that instead of blocking it should +leak (drop) new or old buffers.

+

The “underrun” signal is emitted when the queue has less data than +the specified minimum thresholds require (by default: when the queue is +empty). The “overrun” signal is emitted when the queue is filled +up. Both signals are emitted from the context of the streaming thread.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstQueue

+
struct GstQueue;
+

Opaque GstQueue structure.

+
+
+
+

enum GstQueueLeaky

+

Buffer dropping scheme to avoid the queue to block when full.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

GST_QUEUE_NO_LEAK

+

Not Leaky

+
 

GST_QUEUE_LEAK_UPSTREAM

+

Leaky on upstream (new buffers)

+
 

GST_QUEUE_LEAK_DOWNSTREAM

+

Leaky on downstream (old buffers)

+
 
+
+
+
+
+

Property Details

+
+

The “current-level-buffers” property

+
  “current-level-buffers”    guint
+

Current number of buffers in the queue.

+

Flags: Read

+

Default value: 0

+
+
+
+

The “current-level-bytes” property

+
  “current-level-bytes”      guint
+

Current amount of data in the queue (bytes).

+

Flags: Read

+

Default value: 0

+
+
+
+

The “current-level-time” property

+
  “current-level-time”       guint64
+

Current amount of data in the queue (in ns).

+

Flags: Read

+

Default value: 0

+
+
+
+

The “flush-on-eos” property

+
  “flush-on-eos”             gboolean
+

Discard all data in the queue when an EOS event is received, and pass +on the EOS event as soon as possible (instead of waiting until all +buffers in the queue have been processed, which is the default behaviour).

+

Flushing the queue on EOS might be useful when capturing and encoding +from a live source, to finish up the recording quickly in cases when +the encoder is slow. Note that this might mean some data from the end of +the recording data might be lost though (never more than the configured +max. sizes though).

+

Flags: Read / Write

+

Default value: FALSE

+

Since: 1.2

+
+
+
+

The “leaky” property

+
  “leaky”                    GstQueueLeaky
+

Where the queue leaks, if at all.

+

Flags: Read / Write

+

Default value: Not Leaky

+
+
+
+

The “max-size-buffers” property

+
  “max-size-buffers”         guint
+

Max. number of buffers in the queue (0=disable).

+

Flags: Read / Write

+

Default value: 200

+
+
+
+

The “max-size-bytes” property

+
  “max-size-bytes”           guint
+

Max. amount of data in the queue (bytes, 0=disable).

+

Flags: Read / Write

+

Default value: 10485760

+
+
+
+

The “max-size-time” property

+
  “max-size-time”            guint64
+

Max. amount of data in the queue (in ns, 0=disable).

+

Flags: Read / Write

+

Default value: 1000000000

+
+
+
+

The “min-threshold-buffers” property

+
  “min-threshold-buffers”    guint
+

Min. number of buffers in the queue to allow reading (0=disable).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “min-threshold-bytes” property

+
  “min-threshold-bytes”      guint
+

Min. amount of data in the queue to allow reading (bytes, 0=disable).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “min-threshold-time” property

+
  “min-threshold-time”       guint64
+

Min. amount of data in the queue to allow reading (in ns, 0=disable).

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “silent” property

+
  “silent”                   gboolean
+

Don't emit queue signals. Makes queues more lightweight if no signals are +needed.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “overrun” signal

+
void
+user_function (GstQueue *queue,
+               gpointer  user_data)
+

Reports that the buffer became full (overrun). +A buffer is full if the total amount of data inside it (num-buffers, time, +size) is higher than the boundary values which can be set through the +GObject properties.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

the queue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “pushing” signal

+
void
+user_function (GstQueue *queue,
+               gpointer  user_data)
+

Reports when the queue has enough data to start pushing data again on the +source pad.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

the queue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “running” signal

+
void
+user_function (GstQueue *queue,
+               gpointer  user_data)
+

Reports that enough (min-threshold) data is in the queue. Use this signal +together with the underrun signal to pause the pipeline on underrun and +wait for the queue to fill-up before resume playback.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

the queue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “underrun” signal

+
void
+user_function (GstQueue *queue,
+               gpointer  user_data)
+

Reports that the buffer became empty (underrun). +A buffer is empty if the total amount of data inside it (num-buffers, time, +size) is lower than the boundary values which can be set through the +GObject properties.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

queue

the queue instance

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-queue2.html b/docs/plugins/html/gstreamer-plugins-queue2.html new file mode 100644 index 0000000..94e2134 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-queue2.html @@ -0,0 +1,455 @@ + + + + +queue2: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

queue2

+

queue2

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
guintcurrent-level-buffersRead
guintcurrent-level-bytesRead
guint64current-level-timeRead
ginthigh-percentRead / Write
gintlow-percentRead / Write
guintmax-size-buffersRead / Write
guintmax-size-bytesRead / Write
guint64max-size-timeRead / Write
guint64ring-buffer-max-sizeRead / Write
+gchar *temp-locationRead
gbooleantemp-removeRead / Write
+gchar *temp-templateRead / Write
gbooleanuse-bufferingRead / Write
gbooleanuse-rate-estimateRead / Write
gint64avg-in-rateRead
gbooleanuse-tags-bitrateRead / Write
gdoublehigh-watermarkRead / Write
gdoublelow-watermarkRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidoverrunRun First
+
+
+

Types and Values

+
++++ + + + + +
structGstQueue2
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstQueue2
+
+
+
+

Description

+

Data is queued until one of the limits specified by the +“max-size-buffers”, “max-size-bytes” and/or +“max-size-time” properties has been reached. Any attempt to push +more buffers into the queue will block the pushing thread until more space +becomes available.

+

The queue will create a new thread on the source pad to decouple the +processing on sink and source pad.

+

You can query how many buffers are queued by reading the +“current-level-buffers” property.

+

The default queue size limits are 100 buffers, 2MB of data, or +two seconds worth of data, whichever is reached first.

+

If you set temp-template to a value such as /tmp/gstreamer-XXXXXX, the element +will allocate a random free filename and buffer data in the file. +By using this, it will buffer the entire stream data on the file independently +of the queue size limits, they will only be used for buffering statistics.

+

The temp-location property will be used to notify the application of the +allocated filename.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim.taymans@gmail.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstQueue2

+
struct GstQueue2;
+
+
+
+

Property Details

+
+

The “current-level-buffers” property

+
  “current-level-buffers”    guint
+

Current number of buffers in the queue.

+

Flags: Read

+

Default value: 0

+
+
+
+

The “current-level-bytes” property

+
  “current-level-bytes”      guint
+

Current amount of data in the queue (bytes).

+

Flags: Read

+

Default value: 0

+
+
+
+

The “current-level-time” property

+
  “current-level-time”       guint64
+

Current amount of data in the queue (in ns).

+

Flags: Read

+

Default value: 0

+
+
+
+

The “high-percent” property

+
  “high-percent”             gint
+

High threshold for buffering to finish. Only used if use-buffering is True (Deprecated: use high-watermark instead).

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 99

+
+
+
+

The “low-percent” property

+
  “low-percent”              gint
+

Low threshold for buffering to start. Only used if use-buffering is True (Deprecated: use low-watermark instead).

+

Flags: Read / Write

+

Allowed values: [0,100]

+

Default value: 1

+
+
+
+

The “max-size-buffers” property

+
  “max-size-buffers”         guint
+

Max. number of buffers in the queue (0=disable).

+

Flags: Read / Write

+

Default value: 100

+
+
+
+

The “max-size-bytes” property

+
  “max-size-bytes”           guint
+

Max. amount of data in the queue (bytes, 0=disable).

+

Flags: Read / Write

+

Default value: 2097152

+
+
+
+

The “max-size-time” property

+
  “max-size-time”            guint64
+

Max. amount of data in the queue (in ns, 0=disable).

+

Flags: Read / Write

+

Default value: 2000000000

+
+
+
+

The “ring-buffer-max-size” property

+
  “ring-buffer-max-size”     guint64
+

The maximum size of the ring buffer in bytes. If set to 0, the ring +buffer is disabled. Default 0.

+

Flags: Read / Write

+

Default value: 0

+
+
+
+

The “temp-location” property

+
  “temp-location”            gchar *
+

Location to store temporary files in (Only read this property, use temp-template to configure the name template).

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “temp-remove” property

+
  “temp-remove”              gboolean
+

When temp-template is set, remove the temporary file when going to READY.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “temp-template” property

+
  “temp-template”            gchar *
+

File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled).

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “use-buffering” property

+
  “use-buffering”            gboolean
+

Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “use-rate-estimate” property

+
  “use-rate-estimate”        gboolean
+

Estimate the bitrate of the stream to calculate time level.

+

Flags: Read / Write

+

Default value: TRUE

+
+
+
+

The “avg-in-rate” property

+
  “avg-in-rate”              gint64
+

The average input data rate.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “use-tags-bitrate” property

+
  “use-tags-bitrate”         gboolean
+

Use a bitrate from upstream tags to estimate buffer duration if not provided.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “high-watermark” property

+
  “high-watermark”           gdouble
+

High threshold for buffering to finish. Only used if use-buffering is True.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 0.99

+
+
+
+

The “low-watermark” property

+
  “low-watermark”            gdouble
+

Low threshold for buffering to start. Only used if use-buffering is True.

+

Flags: Read / Write

+

Allowed values: [0,1]

+

Default value: 0.01

+
+
+
+

Signal Details

+
+

The “overrun” signal

+
void
+user_function (GstQueue2 *gstqueue2,
+               gpointer   user_data)
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-rusagetracer.html b/docs/plugins/html/gstreamer-plugins-rusagetracer.html new file mode 100644 index 0000000..9b93ed5 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-rusagetracer.html @@ -0,0 +1,77 @@ + + + + +rusagetracer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

rusagetracer

+

rusagetracer — log resource usage stats

+
+
+

Types and Values

+
++++ + + + + +
structGstRUsageTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+                ╰── GstRUsageTracer
+
+
+
+

Description

+

A tracing module that take rusage() snapshots and logs them.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstRUsageTracer

+
struct GstRUsageTracer;
+

Opaque GstRUsageTracer data structure

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-statstracer.html b/docs/plugins/html/gstreamer-plugins-statstracer.html new file mode 100644 index 0000000..21a5b36 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-statstracer.html @@ -0,0 +1,77 @@ + + + + +statstracer: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

statstracer

+

statstracer — log event stats

+
+
+

Types and Values

+
++++ + + + + +
structGstStatsTracer
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstTracer
+                ╰── GstStatsTracer
+
+
+
+

Description

+

A tracing module that builds usage statistic for elements and pads.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstStatsTracer

+
struct GstStatsTracer;
+

Opaque GstStatsTracer data structure

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-streamiddemux.html b/docs/plugins/html/gstreamer-plugins-streamiddemux.html new file mode 100644 index 0000000..0761944 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-streamiddemux.html @@ -0,0 +1,192 @@ + + + + +streamiddemux: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

streamiddemux

+

streamiddemux

+
+
+

Properties

+
+++++ + + + + + +
+GstPad *active-padRead
+
+
+

Types and Values

+
++++ + + + + +
structGstStreamidDemux
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstStreamidDemux
+
+
+
+

Description

+

The basic concept was started from de-funneling element which restores one +serialized stream via GstFunnel to its original state. GstStreamidDemux +classifies each stream base on stream ids.

+

The stream id demux always takes one input and checks how many streams +are contained in a stream by STREAM_START event. Likewise GstFunnel, +GstStreamidDemux does not synchronize the different output streams.

+

“active-pad” provides information about which output pad +is activated at the moment.

+

see_also +: GstFunnel, gst_event_new_stream_start

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

HoonHee Lee <hoonhee.lee@lge.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src_%u

direction

source

presence

sometimes

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstStreamidDemux

+
struct GstStreamidDemux;
+

The opaque GstStreamidDemux data structure.

+
+
+
+

Property Details

+
+

The “active-pad” property

+
  “active-pad”               GstPad *
+

The currently active src pad.

+

Flags: Read

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-tee.html b/docs/plugins/html/gstreamer-plugins-tee.html new file mode 100644 index 0000000..b0eba15 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-tee.html @@ -0,0 +1,336 @@ + + + + +tee: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

tee

+

tee

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GstPad *alloc-padRead / Write
gbooleanhas-chainRead / Write / Construct
+gchar *last-messageRead
gintnum-src-padsRead
GstTeePullModepull-modeRead / Write / Construct
gbooleansilentRead / Write / Construct
gbooleanallow-not-linkedRead / Write / Construct
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structGstTee
enumGstTeePullMode
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstTee
+
+
+
+

Description

+

Split data to multiple pads. Branching the data flow is useful when e.g. +capturing a video where the video is shown on the screen and also encoded and +written to a file. Another example is playing music and hooking up a +visualisation module.

+

One needs to use separate queue elements (or a multiqueue) in each branch to +provide separate threads for each branch. Otherwise a blocked dataflow in one +branch would stall the other branches.

+
+

Example launch line

+
+ + + + + + + +
1
gst-launch-1.0 filesrc location=song.ogg ! decodebin ! tee name=t ! queue ! audioconvert ! audioresample ! autoaudiosink t. ! queue ! audioconvert ! goom ! videoconvert ! autovideosink
+
+ +

+

Play song.ogg audio file which must be in the current working directory +and render visualisations using the goom element (this can be easier done +using the playbin element, this is just an example pipeline).

+
+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src_%u

direction

source

presence

request

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstTee

+
struct GstTee;
+

Opaque GstTee data structure.

+
+
+
+

enum GstTeePullMode

+

The different ways that tee can behave in pull mode. TEE_PULL_MODE_NEVER + +disables pull mode.

+
+

Members

+
+++++ + + + + + + + + + + + + +

GST_TEE_PULL_MODE_NEVER

+

Never activate in pull mode.

+
 

GST_TEE_PULL_MODE_SINGLE

+

Only one src pad can be active in pull mode.

+
 
+
+
+
+
+

Property Details

+
+

The “alloc-pad” property

+
  “alloc-pad”                GstPad *
+

The pad ALLOCATION queries will be proxied to (DEPRECATED, has no effect).

+

Flags: Read / Write

+
+
+
+

The “has-chain” property

+
  “has-chain”                gboolean
+

If the element can operate in push mode.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+
+
+
+

The “last-message” property

+
  “last-message”             gchar *
+

The message describing current status.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “num-src-pads” property

+
  “num-src-pads”             gint
+

The number of source pads.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “pull-mode” property

+
  “pull-mode”                GstTeePullMode
+

Behavior of tee in pull mode.

+

Flags: Read / Write / Construct

+

Default value: Never activate in pull mode

+
+
+
+

The “silent” property

+
  “silent”                   gboolean
+

Don't produce last_message events.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+
+
+
+

The “allow-not-linked” property

+
  “allow-not-linked”         gboolean
+

This property makes sink pad return GST_FLOW_OK even if there are no +source pads or any of them is linked.

+

This is useful to avoid errors when you have a dynamic pipeline and during +a reconnection you can have all the pads unlinked or removed.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+

Since: 1.6

+
+
+
+

See Also

+

GstIdentity

+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-typefind.html b/docs/plugins/html/gstreamer-plugins-typefind.html new file mode 100644 index 0000000..0983e0f --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-typefind.html @@ -0,0 +1,281 @@ + + + + +typefind: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

typefind

+

typefind

+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
+GstCaps *capsRead
+GstCaps *force-capsRead / Write
guintminimumRead / Write
+
+
+

Signals

+
+++++ + + + + + +
voidhave-typeRun Last
+
+
+

Types and Values

+
++++ + + + + +
structGstTypeFindElement
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstTypeFindElement
+
+
+
+

Description

+

Determines the media-type of a stream. It applies typefind functions in the +order of their rank. Once the type has been detected it sets its src pad caps +to the found media type.

+

Whenever a type is found the “have-type” signal is +emitted, either from the streaming thread or the application thread +(the latter may happen when typefinding is done pull-based from the +state change function).

+

Plugins can register custom typefinders by using GstTypeFindFactory.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Benjamin Otte <in7y118@public.uni-hamburg.de>

class

Generic
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstTypeFindElement

+
struct GstTypeFindElement;
+

Opaque GstTypeFindElement data structure

+
+
+
+

Property Details

+
+

The “caps” property

+
  “caps”                     GstCaps *
+

detected capabilities in stream.

+

Flags: Read

+
+
+
+

The “force-caps” property

+
  “force-caps”               GstCaps *
+

force caps without doing a typefind.

+

Flags: Read / Write

+
+
+
+

The “minimum” property

+
  “minimum”                  guint
+

minimum probability required to accept caps.

+

Flags: Read / Write

+

Allowed values: [1,100]

+

Default value: 1

+
+
+
+

Signal Details

+
+

The “have-type” signal

+
void
+user_function (GstTypeFindElement *typefind,
+               guint               probability,
+               GstCaps            *caps,
+               gpointer            user_data)
+

This signal gets emitted when the type and its probability has +been found.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

typefind

the typefind instance

 

probability

the probability of the type found

 

caps

the caps of the type found

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/gstreamer-plugins-valve.html b/docs/plugins/html/gstreamer-plugins-valve.html new file mode 100644 index 0000000..c7edf45 --- /dev/null +++ b/docs/plugins/html/gstreamer-plugins-valve.html @@ -0,0 +1,187 @@ + + + + +valve: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

valve

+

valve

+
+
+

Properties

+
+++++ + + + + + +
gbooleandropRead / Write
+
+
+

Types and Values

+
++++ + + + + +
structGstValve
+
+
+

Object Hierarchy

+
    GObject
+    ╰── GInitiallyUnowned
+        ╰── GstObject
+            ╰── GstElement
+                ╰── GstValve
+
+
+
+

Description

+

The valve is a simple element that drops buffers when the “drop” +property is set to TRUE and lets then through otherwise.

+

Any downstream error received while the “drop” property is TRUE +is ignored. So downstream element can be set to GST_STATE_NULL and removed, +without using pad blocking.

+
+

Synopsis

+
+

Element Information

+
++++ + + + + + + + + + + + + + + +

plugin

+ coreelements +

author

Olivier Crete <olivier.crete@collabora.co.uk>

class

Filter
+
+
+
+

Element Pads

+
++++ + + + + + + + + + + + + + + + + + + +

name

sink

direction

sink

presence

always

details

ANY
+
++++ + + + + + + + + + + + + + + + + + + +

name

src

direction

source

presence

always

details

ANY
+
+
+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct GstValve

+
struct GstValve;
+

The private valve structure

+
+
+
+

Property Details

+
+

The “drop” property

+
  “drop”                     gboolean
+

Whether to drop buffers and events or let them through.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/home.png b/docs/plugins/html/home.png new file mode 100644 index 0000000..effb5ea Binary files /dev/null and b/docs/plugins/html/home.png differ diff --git a/docs/plugins/html/index.html b/docs/plugins/html/index.html new file mode 100644 index 0000000..0f3c75c --- /dev/null +++ b/docs/plugins/html/index.html @@ -0,0 +1,124 @@ + + + + +GStreamer Core Plugins 1.0 Plugins Reference Manual: GStreamer Core Plugins 1.0 Plugins Reference Manual + + + + + + + +
+
+
+
+

+ for GStreamer Core Plugins 1.0 (1.14.1) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/. +

+
+
+
+
+
gstreamer Elements
+
+
+capsfilter +
+
+concat +
+
+dataurisrc +
+
+downloadbuffer +
+
+fakesink +
+
+fakesrc +
+
+fdsink +
+
+fdsrc +
+
+filesink +
+
+filesrc +
+
+funnel +
+
+identity +
+
+input-selector +
+
+multiqueue +
+
+output-selector +
+
+queue2 +
+
+queue +
+
+streamiddemux +
+
+tee +
+
+typefind +
+
+valve +
+
+
gstreamer Tracers
+
+
+latencytracer — log processing latency stats +
+
+leakstracer — detect GstObject and GstMiniObject leaks +
+
+logtracer — log hook event +
+
+rusagetracer — log resource usage stats +
+
+statstracer — log event stats +
+
+
gstreamer Plugins
+
+
+coreelements — GStreamer core elements +
+
+coretracers — GStreamer core tracers +
+
+
+
+ + + \ No newline at end of file diff --git a/docs/plugins/html/left-insensitive.png b/docs/plugins/html/left-insensitive.png new file mode 100644 index 0000000..6290738 Binary files /dev/null and b/docs/plugins/html/left-insensitive.png differ diff --git a/docs/plugins/html/left.png b/docs/plugins/html/left.png new file mode 100644 index 0000000..d34a7bc Binary files /dev/null and b/docs/plugins/html/left.png differ diff --git a/docs/plugins/html/right-insensitive.png b/docs/plugins/html/right-insensitive.png new file mode 100644 index 0000000..179725a Binary files /dev/null and b/docs/plugins/html/right-insensitive.png differ diff --git a/docs/plugins/html/right.png b/docs/plugins/html/right.png new file mode 100644 index 0000000..bf5d8fa Binary files /dev/null and b/docs/plugins/html/right.png differ diff --git a/docs/plugins/html/style.css b/docs/plugins/html/style.css new file mode 100644 index 0000000..3675420 --- /dev/null +++ b/docs/plugins/html/style.css @@ -0,0 +1,479 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.3em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; + margin-top: 1em; + margin-bottom: 1em; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; + font-weight: bold; +} + +dl.toc > dl +{ + padding-bottom: 0.5em; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + /* these have a as a first child, but since there are no parent selectors + * we can't use that. */ + a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/docs/plugins/html/up-insensitive.png b/docs/plugins/html/up-insensitive.png new file mode 100644 index 0000000..5ee049e Binary files /dev/null and b/docs/plugins/html/up-insensitive.png differ diff --git a/docs/plugins/html/up.png b/docs/plugins/html/up.png new file mode 100644 index 0000000..3a816d0 Binary files /dev/null and b/docs/plugins/html/up.png differ diff --git a/docs/plugins/inspect/plugin-coreelements.xml b/docs/plugins/inspect/plugin-coreelements.xml new file mode 100644 index 0000000..a1f9a37 --- /dev/null +++ b/docs/plugins/inspect/plugin-coreelements.xml @@ -0,0 +1,412 @@ + + coreelements + GStreamer core elements + ../../plugins/elements/.libs/libgstcoreelements.so + libgstcoreelements.so + 1.14.1 + LGPL + gstreamer + GStreamer source release + Unknown package origin + + + capsfilter + CapsFilter + Generic + Pass data without modification, limiting formats + David Schleef <ds@schleef.org> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + concat + Concat + Generic + Concatenate multiple streams + Sebastian Dröge <sebastian@centricular.com> + + + sink_%u + sink + request +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + dataurisrc + data: URI source element + Source + Handles data: uris + Philippe Normand <pnormand@igalia.com>, Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + src + source + always +
ANY
+
+
+
+ + downloadbuffer + DownloadBuffer + Generic + Download Buffer element + Wim Taymans <wim.taymans@gmail.com> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + fakesink + Fake Sink + Sink + Black hole for data + Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>, Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com> + + + sink + sink + always +
ANY
+
+
+
+ + fakesrc + Fake Source + Source + Push empty (no data) buffers around + Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com> + + + src + source + always +
ANY
+
+
+
+ + fdsink + Filedescriptor Sink + Sink/File + Write data to a file descriptor + Erik Walthinsen <omega@cse.ogi.edu> + + + sink + sink + always +
ANY
+
+
+
+ + fdsrc + Filedescriptor Source + Source/File + Read from a file descriptor + Erik Walthinsen <omega@cse.ogi.edu> + + + src + source + always +
ANY
+
+
+
+ + filesink + File Sink + Sink/File + Write stream to a file + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
ANY
+
+
+
+ + filesrc + File Source + Source/File + Read from arbitrary point in a file + Erik Walthinsen <omega@cse.ogi.edu> + + + src + source + always +
ANY
+
+
+
+ + funnel + Funnel pipe fitting + Generic + N-to-1 pipe fitting + Olivier Crete <olivier.crete@collabora.co.uk> + + + sink_%u + sink + request +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + identity + Identity + Generic + Pass data without modification + Erik Walthinsen <omega@cse.ogi.edu> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + input-selector + Input selector + Generic + N-to-1 input stream selector + Julien Moutte <julien@moutte.net>, Jan Schmidt <thaytan@mad.scientist.com>, Wim Taymans <wim.taymans@gmail.com> + + + sink_%u + sink + request +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + multiqueue + MultiQueue + Generic + Multiple data queue + Edward Hervey <edward@fluendo.com> + + + sink_%u + sink + request +
ANY
+
+ + src_%u + source + sometimes +
ANY
+
+
+
+ + output-selector + Output selector + Generic + 1-to-N output stream selector + Stefan Kost <stefan.kost@nokia.com> + + + sink + sink + always +
ANY
+
+ + src_%u + source + request +
ANY
+
+
+
+ + queue + Queue + Generic + Simple data queue + Erik Walthinsen <omega@cse.ogi.edu> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + queue2 + Queue 2 + Generic + Simple data queue + Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim.taymans@gmail.com> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + streamiddemux + Streamid Demux + Generic + 1-to-N output stream by stream-id + HoonHee Lee <hoonhee.lee@lge.com> + + + sink + sink + always +
ANY
+
+ + src_%u + source + sometimes +
ANY
+
+
+
+ + tee + Tee pipe fitting + Generic + 1-to-N pipe fitting + Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
ANY
+
+ + src_%u + source + request +
ANY
+
+
+
+ + typefind + TypeFind + Generic + Finds the media type of a stream + Benjamin Otte <in7y118@public.uni-hamburg.de> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+ + valve + Valve element + Filter + Drops buffers and events or lets them through + Olivier Crete <olivier.crete@collabora.co.uk> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-coretracers.xml b/docs/plugins/inspect/plugin-coretracers.xml new file mode 100644 index 0000000..d1d6dac --- /dev/null +++ b/docs/plugins/inspect/plugin-coretracers.xml @@ -0,0 +1,28 @@ + + coretracers + GStreamer core tracers + ../../plugins/tracers/.libs/libgstcoretracers.so + libgstcoretracers.so + 1.14.1 + LGPL + gstreamer + GStreamer source release + Unknown package origin + + + latency + + + leaks + + + log + + + rusage + + + stats + + + \ No newline at end of file diff --git a/docs/plugins/scanobj-build.stamp b/docs/plugins/scanobj-build.stamp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/plugins/scanobj-build.stamp diff --git a/docs/version.entities.in b/docs/version.entities.in new file mode 100644 index 0000000..be8ed4b --- /dev/null +++ b/docs/version.entities.in @@ -0,0 +1,3 @@ + + + diff --git a/gst-element-check-1.0.m4 b/gst-element-check-1.0.m4 new file mode 100644 index 0000000..9ad421f --- /dev/null +++ b/gst-element-check-1.0.m4 @@ -0,0 +1,33 @@ +dnl Perform a check for a GStreamer element using gst-inspect-x.y +dnl +dnl GST_ELEMENT_CHECK(ELEMENT-NAME, MIN-VERSION, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +dnl +dnl ELEMENT-NAME : element factory name (mandatory) +dnl MIN-VERSION : minimum version required, e.g. 1.0 or 1.0.5 (mandatory) +dnl ACTION-IF_FOUND : action if element exists and is of the desired version +dnl ACTION-IF-NOT-FOUND : action if element does not exist or is too old +dnl +dnl gstapiversion=`echo $2 | tr '.' '\n' | head -n 2 | tr '\n' '.' | sed 's/\.$//'` + +AC_DEFUN([GST_ELEMENT_CHECK], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + + gstapiversion=`echo "$2" | while IFS=. read a b; do echo "$a.0"; done` + gsttoolsdir=`$PKG_CONFIG --variable=toolsdir gstreamer-$gstapiversion` + if test "x$gsttoolsdir" != "x"; then + gstinspect="$gsttoolsdir/gst-inspect-$gstapiversion" + AC_MSG_CHECKING(GStreamer $gstapiversion element $1 >= $2) + if [ $gstinspect --exists --atleast-version=$2 $1 ]; then + AC_MSG_RESULT([found]) + $3 + else + if [ $gstinspect --exists $1 ]; then + AC_MSG_RESULT([found, but too old]) + else + AC_MSG_RESULT([not found]) + fi + $4 + fi + fi +]) diff --git a/gst/Makefile.am b/gst/Makefile.am new file mode 100644 index 0000000..78d10c2 --- /dev/null +++ b/gst/Makefile.am @@ -0,0 +1,336 @@ +lib_LTLIBRARIES = libgstreamer-@GST_API_VERSION@.la + +if GST_DISABLE_REGISTRY +GST_REGISTRY_SRC = +else +GST_REGISTRY_SRC = gstregistrybinary.c +endif + +if GST_DISABLE_PARSE +SUBDIRS_PARSE = +GST_PARSE_LA = +else +SUBDIRS_PARSE = parse +GST_PARSE_LA = parse/libgstparse.la +endif + +if GST_DISABLE_PLUGIN +GST_PLUGIN_SRC = +else +GST_PLUGIN_SRC = gstplugin.c +endif + +if !GST_DISABLE_GST_DEBUG +SUBDIRS_PRINTF = printf +GST_PRINTF_LA = printf/libgstprintf.la +else +SUBDIRS_PRINTF = +GST_PRINTF_LA = +endif + +SUBDIRS = $(SUBDIRS_PARSE) $(SUBDIRS_PRINTF) + +DIST_SUBDIRS = parse printf + +# make variables for all generated source and header files to make the +# distinction clear + +built_headers_configure = gstversion.h gstconfig.h +built_header_make = gstenumtypes.h +built_source_make = gstenumtypes.c + +EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES = \ + gstregistrybinary.c + + +# temporarily not used +# glib-compat.c + +libgstreamer_@GST_API_VERSION@_la_SOURCES = \ + gst.c \ + gstobject.c \ + gstallocator.c \ + gstbin.c \ + gstbuffer.c \ + gstbufferlist.c \ + gstbufferpool.c \ + gstbus.c \ + gstcaps.c \ + gstcapsfeatures.c \ + gstchildproxy.c \ + gstclock.c \ + gstcontext.c \ + gstcontrolbinding.c \ + gstcontrolsource.c \ + gstdatetime.c \ + gstdebugutils.c \ + gstdevice.c \ + gstdevicemonitor.c \ + gstdeviceprovider.c \ + gstdeviceproviderfactory.c \ + gstdynamictypefactory.c \ + gstelement.c \ + gstelementfactory.c \ + gsterror.c \ + gstevent.c \ + gstformat.c \ + gstghostpad.c \ + gstinfo.c \ + gstiterator.c \ + gstatomicqueue.c \ + gstmessage.c \ + gstmeta.c \ + gstmemory.c \ + gstminiobject.c \ + gstpad.c \ + gstpadtemplate.c \ + gstparamspecs.c \ + gstpipeline.c \ + gstplugin.c \ + gstpluginfeature.c \ + gstpluginloader.c \ + gstpoll.c \ + gstpreset.c \ + gstprotection.c \ + gstquark.c \ + gstquery.c \ + gstregistry.c \ + gstregistrychunks.c \ + gstpromise.c \ + gstsample.c \ + gstsegment.c \ + gststreamcollection.c \ + gststreams.c \ + gststructure.c \ + gstsystemclock.c \ + gsttaglist.c \ + gsttagsetter.c \ + gsttask.c \ + gsttaskpool.c \ + gsttoc.c \ + gsttocsetter.c \ + gsttracer.c \ + gsttracerfactory.c \ + gsttracerrecord.c \ + gsttracerutils.c \ + gsttypefind.c \ + gsttypefindfactory.c \ + gsturi.c \ + gstutils.c \ + gstvalue.c \ + gstparse.c \ + $(GST_REGISTRY_SRC) + +# do not put files in the distribution that are generated +nodist_libgstreamer_@GST_API_VERSION@_la_SOURCES = $(built_source_make) + +# BUILT_SOURCES are built on make all/check/install before all other targets +BUILT_SOURCES = \ + $(built_headers_configure) \ + $(built_header_make) \ + $(built_source_make) +# CLEANFILES is for files generated by make +CLEANFILES = $(built_header_make) $(built_source_make) $(as_dll_cleanfiles) *.gcno *.gcda *.gcov *.gcov.out +# DISTCLEANFILES is for files generated by configure +DISTCLEANFILES = $(built_headers_configure) + +libgstreamer_@GST_API_VERSION@_la_CFLAGS = \ + -D_GNU_SOURCE \ + -DGST_EXPORTS \ + -DG_LOG_DOMAIN=g_log_domain_gstreamer \ + -DGST_API_VERSION=\""$(GST_API_VERSION)"\" \ + -DGST_DISABLE_DEPRECATED \ + $(VALGRIND_CFLAGS) \ + $(UNWIND_CFLAGS) \ + $(DW_CFLAGS) \ + $(GST_ALL_CFLAGS) + +libgstreamer_@GST_API_VERSION@_la_LIBADD = \ + $(GST_PARSE_LA) \ + $(GST_PRINTF_LA) \ + $(GST_ALL_LIBS) \ + $(WIN32_LIBS) \ + $(SOCKET_LIBS) \ + $(UNWIND_LIBS) \ + $(DW_LIBS) \ + $(LIBM) + +libgstreamer_@GST_API_VERSION@_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +libgstreamer_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst + +gst_headers = \ + gst.h \ + glib-compat.h \ + gstobject.h \ + gstallocator.h \ + gstbin.h \ + gstbuffer.h \ + gstbufferlist.h \ + gstbufferpool.h \ + gstbus.h \ + gstcaps.h \ + gstcapsfeatures.h \ + gstchildproxy.h \ + gstclock.h \ + gstcompat.h \ + gstcontext.h \ + gstcontrolbinding.h \ + gstcontrolsource.h \ + gstdatetime.h \ + gstdebugutils.h \ + gstelement.h \ + gstelementmetadata.h \ + gstdevice.h \ + gstdeviceprovider.h \ + gstdeviceproviderfactory.h \ + gstdynamictypefactory.h \ + gstelementfactory.h \ + gsterror.h \ + gstevent.h \ + gstformat.h \ + gstghostpad.h \ + gstdevicemonitor.h \ + gstinfo.h \ + gstiterator.h \ + gstatomicqueue.h \ + gstmacros.h \ + gstmessage.h \ + gstmeta.h \ + gstmemory.h \ + gstminiobject.h \ + gstpad.h \ + gstpadtemplate.h \ + gstparamspecs.h \ + gstpipeline.h \ + gstplugin.h \ + gstpluginfeature.h \ + gstpoll.h \ + gstpreset.h \ + gstprotection.h \ + gstquery.h \ + gstpromise.h \ + gstsample.h \ + gstsegment.h \ + gststreamcollection.h \ + gststreams.h \ + gststructure.h \ + gstsystemclock.h \ + gsttaglist.h \ + gsttagsetter.h \ + gsttask.h \ + gsttaskpool.h \ + gsttoc.h \ + gsttocsetter.h \ + gsttracer.h \ + gsttracerfactory.h \ + gsttracerrecord.h \ + gsttypefind.h \ + gsttypefindfactory.h \ + gsturi.h \ + gstutils.h \ + gstvalue.h \ + gstregistry.h \ + gstparse.h + +libgstreamer_@GST_API_VERSION@include_HEADERS = $(gst_headers) math-compat.h + +nodist_libgstreamer_@GST_API_VERSION@include_HEADERS = \ + $(built_headers_configure) $(built_header_make) + +noinst_HEADERS = \ + gettext.h \ + glib-compat-private.h \ + gst-i18n-lib.h \ + gst-i18n-app.h \ + gstelementmetadata.h \ + gstpluginloader.h \ + gstquark.h \ + gstregistrybinary.h \ + gstregistrychunks.h \ + gsttracerutils.h \ + gst_private.h + +gstenumtypes.h: $(gst_headers) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --fhead "#ifndef __GST_ENUM_TYPES_H__\n#define __GST_ENUM_TYPES_H__\n\n#include \n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "GST_API GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __GST_ENUM_TYPES_H__ */" \ + $^ > gstenumtypes.h + +gstenumtypes.c: $(gst_headers) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --fhead "#include \"gst_private.h\"\n#include \n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n " \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static gsize id = 0;\n static const G@Type@Value values[] = {" \ + --vprod " { C_@TYPE@(@VALUENAME@), \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n\n if (g_once_init_enter (&id)) {\n GType tmp = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&id, tmp);\n }\n\n return (GType) id;\n}" \ + $^ > gstenumtypes.c + +%.c.gcov: .libs/libgstreamer_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstreamer_@GST_API_VERSION@_la_SOURCES:=.gcov) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = Gst-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@include_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(built_header_make)) +gir_headers+=$(patsubst %,$(builddir)/%, gstversion.h) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(built_source_make)) + +Gst-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstreamer-@GST_API_VERSION@.la + $(AM_V_GEN)GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes GI_SCANNER_DISABLE_CACHE=yes \ + CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ + $(INTROSPECTION_SCANNER) -v --namespace Gst \ + --nsversion=@GST_API_VERSION@ \ + --verbose \ + --warn-all \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -DIN_GOBJECT_INTROSPECTION=1 \ + --c-include='gst/gst.h' \ + --library=libgstreamer-@GST_API_VERSION@.la \ + --include=GLib-2.0 \ + --include=GObject-2.0 \ + --include=GModule-2.0 \ + --libtool="${LIBTOOL}" \ + --pkg glib-2.0 \ + --pkg gobject-2.0 \ + --pkg gmodule-no-export-2.0 \ + --pkg-export gstreamer-@GST_API_VERSION@ \ + --add-init-section="$(INTROSPECTION_INIT)" \ + --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)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +# try to prevent packaging errors +check-libexecdir-consistency: + @if test "${GST_PLUGIN_SCANNER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; then \ + echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \ + echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \ + echo "*** The same goes for prefix, libdir etc."; \ + echo "*** ${GST_PLUGIN_SCANNER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; \ + exit 1; \ + fi + +all-local: check-libexecdir-consistency diff --git a/gst/Makefile.in b/gst/Makefile.in new file mode 100644 index 0000000..0aa1868 --- /dev/null +++ b/gst/Makefile.in @@ -0,0 +1,2088 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = gst +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libgstreamer_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = gstconfig.h gstversion.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" \ + "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +@GST_DISABLE_PARSE_FALSE@am__DEPENDENCIES_1 = parse/libgstparse.la +@GST_DISABLE_GST_DEBUG_FALSE@am__DEPENDENCIES_2 = \ +@GST_DISABLE_GST_DEBUG_FALSE@ printf/libgstprintf.la +am__DEPENDENCIES_3 = +libgstreamer_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) +am__libgstreamer_@GST_API_VERSION@_la_SOURCES_DIST = gst.c gstobject.c \ + gstallocator.c gstbin.c gstbuffer.c gstbufferlist.c \ + gstbufferpool.c gstbus.c gstcaps.c gstcapsfeatures.c \ + gstchildproxy.c gstclock.c gstcontext.c gstcontrolbinding.c \ + gstcontrolsource.c gstdatetime.c gstdebugutils.c gstdevice.c \ + gstdevicemonitor.c gstdeviceprovider.c \ + gstdeviceproviderfactory.c gstdynamictypefactory.c \ + gstelement.c gstelementfactory.c gsterror.c gstevent.c \ + gstformat.c gstghostpad.c gstinfo.c gstiterator.c \ + gstatomicqueue.c gstmessage.c gstmeta.c gstmemory.c \ + gstminiobject.c gstpad.c gstpadtemplate.c gstparamspecs.c \ + gstpipeline.c gstplugin.c gstpluginfeature.c gstpluginloader.c \ + gstpoll.c gstpreset.c gstprotection.c gstquark.c gstquery.c \ + gstregistry.c gstregistrychunks.c gstpromise.c gstsample.c \ + gstsegment.c gststreamcollection.c gststreams.c gststructure.c \ + gstsystemclock.c gsttaglist.c gsttagsetter.c gsttask.c \ + gsttaskpool.c gsttoc.c gsttocsetter.c gsttracer.c \ + gsttracerfactory.c gsttracerrecord.c gsttracerutils.c \ + gsttypefind.c gsttypefindfactory.c gsturi.c gstutils.c \ + gstvalue.c gstparse.c gstregistrybinary.c +@GST_DISABLE_REGISTRY_FALSE@am__objects_1 = libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo +am_libgstreamer_@GST_API_VERSION@_la_OBJECTS = \ + libgstreamer_@GST_API_VERSION@_la-gst.lo \ + libgstreamer_@GST_API_VERSION@_la-gstobject.lo \ + libgstreamer_@GST_API_VERSION@_la-gstallocator.lo \ + libgstreamer_@GST_API_VERSION@_la-gstbin.lo \ + libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo \ + libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo \ + libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo \ + libgstreamer_@GST_API_VERSION@_la-gstbus.lo \ + libgstreamer_@GST_API_VERSION@_la-gstcaps.lo \ + libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo \ + libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo \ + libgstreamer_@GST_API_VERSION@_la-gstclock.lo \ + libgstreamer_@GST_API_VERSION@_la-gstcontext.lo \ + libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo \ + libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdevice.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo \ + libgstreamer_@GST_API_VERSION@_la-gstelement.lo \ + libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo \ + libgstreamer_@GST_API_VERSION@_la-gsterror.lo \ + libgstreamer_@GST_API_VERSION@_la-gstevent.lo \ + libgstreamer_@GST_API_VERSION@_la-gstformat.lo \ + libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo \ + libgstreamer_@GST_API_VERSION@_la-gstinfo.lo \ + libgstreamer_@GST_API_VERSION@_la-gstiterator.lo \ + libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo \ + libgstreamer_@GST_API_VERSION@_la-gstmessage.lo \ + libgstreamer_@GST_API_VERSION@_la-gstmeta.lo \ + libgstreamer_@GST_API_VERSION@_la-gstmemory.lo \ + libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpad.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo \ + libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo \ + libgstreamer_@GST_API_VERSION@_la-gstplugin.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpoll.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpreset.lo \ + libgstreamer_@GST_API_VERSION@_la-gstprotection.lo \ + libgstreamer_@GST_API_VERSION@_la-gstquark.lo \ + libgstreamer_@GST_API_VERSION@_la-gstquery.lo \ + libgstreamer_@GST_API_VERSION@_la-gstregistry.lo \ + libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo \ + libgstreamer_@GST_API_VERSION@_la-gstpromise.lo \ + libgstreamer_@GST_API_VERSION@_la-gstsample.lo \ + libgstreamer_@GST_API_VERSION@_la-gstsegment.lo \ + libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo \ + libgstreamer_@GST_API_VERSION@_la-gststreams.lo \ + libgstreamer_@GST_API_VERSION@_la-gststructure.lo \ + libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttask.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttoc.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttracer.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo \ + libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo \ + libgstreamer_@GST_API_VERSION@_la-gsturi.lo \ + libgstreamer_@GST_API_VERSION@_la-gstutils.lo \ + libgstreamer_@GST_API_VERSION@_la-gstvalue.lo \ + libgstreamer_@GST_API_VERSION@_la-gstparse.lo $(am__objects_1) +am__objects_2 = libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo +nodist_libgstreamer_@GST_API_VERSION@_la_OBJECTS = $(am__objects_2) +libgstreamer_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstreamer_@GST_API_VERSION@_la_OBJECTS) \ + $(nodist_libgstreamer_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstreamer_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) \ + $(libgstreamer_@GST_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstreamer_@GST_API_VERSION@_la_SOURCES) \ + $(EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES) \ + $(nodist_libgstreamer_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(am__libgstreamer_@GST_API_VERSION@_la_SOURCES_DIST) \ + $(EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstreamer_@GST_API_VERSION@include_HEADERS) \ + $(nodist_libgstreamer_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/gstconfig.h.in \ + $(srcdir)/gstversion.h.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libgstreamer-@GST_API_VERSION@.la +@GST_DISABLE_REGISTRY_FALSE@GST_REGISTRY_SRC = gstregistrybinary.c +@GST_DISABLE_REGISTRY_TRUE@GST_REGISTRY_SRC = +@GST_DISABLE_PARSE_FALSE@SUBDIRS_PARSE = parse +@GST_DISABLE_PARSE_TRUE@SUBDIRS_PARSE = +@GST_DISABLE_PARSE_FALSE@GST_PARSE_LA = parse/libgstparse.la +@GST_DISABLE_PARSE_TRUE@GST_PARSE_LA = +@GST_DISABLE_PLUGIN_FALSE@GST_PLUGIN_SRC = gstplugin.c +@GST_DISABLE_PLUGIN_TRUE@GST_PLUGIN_SRC = +@GST_DISABLE_GST_DEBUG_FALSE@SUBDIRS_PRINTF = printf +@GST_DISABLE_GST_DEBUG_TRUE@SUBDIRS_PRINTF = +@GST_DISABLE_GST_DEBUG_FALSE@GST_PRINTF_LA = printf/libgstprintf.la +@GST_DISABLE_GST_DEBUG_TRUE@GST_PRINTF_LA = +SUBDIRS = $(SUBDIRS_PARSE) $(SUBDIRS_PRINTF) +DIST_SUBDIRS = parse printf + +# make variables for all generated source and header files to make the +# distinction clear +built_headers_configure = gstversion.h gstconfig.h +built_header_make = gstenumtypes.h +built_source_make = gstenumtypes.c +EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES = \ + gstregistrybinary.c + + +# temporarily not used +# glib-compat.c +libgstreamer_@GST_API_VERSION@_la_SOURCES = \ + gst.c \ + gstobject.c \ + gstallocator.c \ + gstbin.c \ + gstbuffer.c \ + gstbufferlist.c \ + gstbufferpool.c \ + gstbus.c \ + gstcaps.c \ + gstcapsfeatures.c \ + gstchildproxy.c \ + gstclock.c \ + gstcontext.c \ + gstcontrolbinding.c \ + gstcontrolsource.c \ + gstdatetime.c \ + gstdebugutils.c \ + gstdevice.c \ + gstdevicemonitor.c \ + gstdeviceprovider.c \ + gstdeviceproviderfactory.c \ + gstdynamictypefactory.c \ + gstelement.c \ + gstelementfactory.c \ + gsterror.c \ + gstevent.c \ + gstformat.c \ + gstghostpad.c \ + gstinfo.c \ + gstiterator.c \ + gstatomicqueue.c \ + gstmessage.c \ + gstmeta.c \ + gstmemory.c \ + gstminiobject.c \ + gstpad.c \ + gstpadtemplate.c \ + gstparamspecs.c \ + gstpipeline.c \ + gstplugin.c \ + gstpluginfeature.c \ + gstpluginloader.c \ + gstpoll.c \ + gstpreset.c \ + gstprotection.c \ + gstquark.c \ + gstquery.c \ + gstregistry.c \ + gstregistrychunks.c \ + gstpromise.c \ + gstsample.c \ + gstsegment.c \ + gststreamcollection.c \ + gststreams.c \ + gststructure.c \ + gstsystemclock.c \ + gsttaglist.c \ + gsttagsetter.c \ + gsttask.c \ + gsttaskpool.c \ + gsttoc.c \ + gsttocsetter.c \ + gsttracer.c \ + gsttracerfactory.c \ + gsttracerrecord.c \ + gsttracerutils.c \ + gsttypefind.c \ + gsttypefindfactory.c \ + gsturi.c \ + gstutils.c \ + gstvalue.c \ + gstparse.c \ + $(GST_REGISTRY_SRC) + + +# do not put files in the distribution that are generated +nodist_libgstreamer_@GST_API_VERSION@_la_SOURCES = $(built_source_make) + +# BUILT_SOURCES are built on make all/check/install before all other targets +BUILT_SOURCES = \ + $(built_headers_configure) \ + $(built_header_make) \ + $(built_source_make) + +# CLEANFILES is for files generated by make +CLEANFILES = $(built_header_make) $(built_source_make) \ + $(as_dll_cleanfiles) *.gcno *.gcda *.gcov *.gcov.out \ + $(am__append_1) +# DISTCLEANFILES is for files generated by configure +DISTCLEANFILES = $(built_headers_configure) +libgstreamer_@GST_API_VERSION@_la_CFLAGS = \ + -D_GNU_SOURCE \ + -DGST_EXPORTS \ + -DG_LOG_DOMAIN=g_log_domain_gstreamer \ + -DGST_API_VERSION=\""$(GST_API_VERSION)"\" \ + -DGST_DISABLE_DEPRECATED \ + $(VALGRIND_CFLAGS) \ + $(UNWIND_CFLAGS) \ + $(DW_CFLAGS) \ + $(GST_ALL_CFLAGS) + +libgstreamer_@GST_API_VERSION@_la_LIBADD = \ + $(GST_PARSE_LA) \ + $(GST_PRINTF_LA) \ + $(GST_ALL_LIBS) \ + $(WIN32_LIBS) \ + $(SOCKET_LIBS) \ + $(UNWIND_LIBS) \ + $(DW_LIBS) \ + $(LIBM) + +libgstreamer_@GST_API_VERSION@_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +libgstreamer_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst +gst_headers = \ + gst.h \ + glib-compat.h \ + gstobject.h \ + gstallocator.h \ + gstbin.h \ + gstbuffer.h \ + gstbufferlist.h \ + gstbufferpool.h \ + gstbus.h \ + gstcaps.h \ + gstcapsfeatures.h \ + gstchildproxy.h \ + gstclock.h \ + gstcompat.h \ + gstcontext.h \ + gstcontrolbinding.h \ + gstcontrolsource.h \ + gstdatetime.h \ + gstdebugutils.h \ + gstelement.h \ + gstelementmetadata.h \ + gstdevice.h \ + gstdeviceprovider.h \ + gstdeviceproviderfactory.h \ + gstdynamictypefactory.h \ + gstelementfactory.h \ + gsterror.h \ + gstevent.h \ + gstformat.h \ + gstghostpad.h \ + gstdevicemonitor.h \ + gstinfo.h \ + gstiterator.h \ + gstatomicqueue.h \ + gstmacros.h \ + gstmessage.h \ + gstmeta.h \ + gstmemory.h \ + gstminiobject.h \ + gstpad.h \ + gstpadtemplate.h \ + gstparamspecs.h \ + gstpipeline.h \ + gstplugin.h \ + gstpluginfeature.h \ + gstpoll.h \ + gstpreset.h \ + gstprotection.h \ + gstquery.h \ + gstpromise.h \ + gstsample.h \ + gstsegment.h \ + gststreamcollection.h \ + gststreams.h \ + gststructure.h \ + gstsystemclock.h \ + gsttaglist.h \ + gsttagsetter.h \ + gsttask.h \ + gsttaskpool.h \ + gsttoc.h \ + gsttocsetter.h \ + gsttracer.h \ + gsttracerfactory.h \ + gsttracerrecord.h \ + gsttypefind.h \ + gsttypefindfactory.h \ + gsturi.h \ + gstutils.h \ + gstvalue.h \ + gstregistry.h \ + gstparse.h + +libgstreamer_@GST_API_VERSION@include_HEADERS = $(gst_headers) math-compat.h +nodist_libgstreamer_@GST_API_VERSION@include_HEADERS = \ + $(built_headers_configure) $(built_header_make) + +noinst_HEADERS = \ + gettext.h \ + glib-compat-private.h \ + gst-i18n-lib.h \ + gst-i18n-app.h \ + gstelementmetadata.h \ + gstpluginloader.h \ + gstquark.h \ + gstregistrybinary.h \ + gstregistrychunks.h \ + gsttracerutils.h \ + gst_private.h + +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = Gst-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(libgstreamer_@GST_API_VERSION@include_HEADERS)) \ +@HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(built_header_make)) $(patsubst \ +@HAVE_INTROSPECTION_TRUE@ %,$(builddir)/%, gstversion.h) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(libgstreamer_@GST_API_VERSION@_la_SOURCES)) \ +@HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(built_source_make)) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +gstconfig.h: $(top_builddir)/config.status $(srcdir)/gstconfig.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstversion.h: $(top_builddir)/config.status $(srcdir)/gstversion.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstreamer-@GST_API_VERSION@.la: $(libgstreamer_@GST_API_VERSION@_la_OBJECTS) $(libgstreamer_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstreamer_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstreamer_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstreamer_@GST_API_VERSION@_la_OBJECTS) $(libgstreamer_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstallocator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferlist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferpool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcaps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstchildproxy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstclock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdatetime.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdebugutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelementfactory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstenumtypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsterror.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstevent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstformat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstghostpad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstiterator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmemory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmessage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmeta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstminiobject.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstobject.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparamspecs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpipeline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstplugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginloader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpoll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpreset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpromise.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstprotection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquark.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquery.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsample.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsegment.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreamcollection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreams.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststructure.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsystemclock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaglist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttagsetter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttask.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaskpool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttoc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttocsetter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefind.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsturi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstvalue.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstreamer_@GST_API_VERSION@_la-gst.lo: gst.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gst.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gst.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gst.lo `test -f 'gst.c' || echo '$(srcdir)/'`gst.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gst.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gst.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst.c' object='libgstreamer_@GST_API_VERSION@_la-gst.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gst.lo `test -f 'gst.c' || echo '$(srcdir)/'`gst.c + +libgstreamer_@GST_API_VERSION@_la-gstobject.lo: gstobject.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstobject.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstobject.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstobject.lo `test -f 'gstobject.c' || echo '$(srcdir)/'`gstobject.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstobject.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstobject.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstobject.c' object='libgstreamer_@GST_API_VERSION@_la-gstobject.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstobject.lo `test -f 'gstobject.c' || echo '$(srcdir)/'`gstobject.c + +libgstreamer_@GST_API_VERSION@_la-gstallocator.lo: gstallocator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstallocator.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstallocator.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstallocator.lo `test -f 'gstallocator.c' || echo '$(srcdir)/'`gstallocator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstallocator.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstallocator.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstallocator.c' object='libgstreamer_@GST_API_VERSION@_la-gstallocator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstallocator.lo `test -f 'gstallocator.c' || echo '$(srcdir)/'`gstallocator.c + +libgstreamer_@GST_API_VERSION@_la-gstbin.lo: gstbin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstbin.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbin.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstbin.lo `test -f 'gstbin.c' || echo '$(srcdir)/'`gstbin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbin.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbin.c' object='libgstreamer_@GST_API_VERSION@_la-gstbin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstbin.lo `test -f 'gstbin.c' || echo '$(srcdir)/'`gstbin.c + +libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo: gstbuffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbuffer.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo `test -f 'gstbuffer.c' || echo '$(srcdir)/'`gstbuffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbuffer.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbuffer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbuffer.c' object='libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstbuffer.lo `test -f 'gstbuffer.c' || echo '$(srcdir)/'`gstbuffer.c + +libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo: gstbufferlist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferlist.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo `test -f 'gstbufferlist.c' || echo '$(srcdir)/'`gstbufferlist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferlist.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferlist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbufferlist.c' object='libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstbufferlist.lo `test -f 'gstbufferlist.c' || echo '$(srcdir)/'`gstbufferlist.c + +libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo: gstbufferpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferpool.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo `test -f 'gstbufferpool.c' || echo '$(srcdir)/'`gstbufferpool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferpool.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbufferpool.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbufferpool.c' object='libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstbufferpool.lo `test -f 'gstbufferpool.c' || echo '$(srcdir)/'`gstbufferpool.c + +libgstreamer_@GST_API_VERSION@_la-gstbus.lo: gstbus.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstbus.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbus.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstbus.lo `test -f 'gstbus.c' || echo '$(srcdir)/'`gstbus.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbus.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstbus.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbus.c' object='libgstreamer_@GST_API_VERSION@_la-gstbus.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstbus.lo `test -f 'gstbus.c' || echo '$(srcdir)/'`gstbus.c + +libgstreamer_@GST_API_VERSION@_la-gstcaps.lo: gstcaps.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstcaps.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcaps.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstcaps.lo `test -f 'gstcaps.c' || echo '$(srcdir)/'`gstcaps.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcaps.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcaps.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcaps.c' object='libgstreamer_@GST_API_VERSION@_la-gstcaps.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstcaps.lo `test -f 'gstcaps.c' || echo '$(srcdir)/'`gstcaps.c + +libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo: gstcapsfeatures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo `test -f 'gstcapsfeatures.c' || echo '$(srcdir)/'`gstcapsfeatures.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcapsfeatures.c' object='libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstcapsfeatures.lo `test -f 'gstcapsfeatures.c' || echo '$(srcdir)/'`gstcapsfeatures.c + +libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo: gstchildproxy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstchildproxy.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo `test -f 'gstchildproxy.c' || echo '$(srcdir)/'`gstchildproxy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstchildproxy.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstchildproxy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstchildproxy.c' object='libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstchildproxy.lo `test -f 'gstchildproxy.c' || echo '$(srcdir)/'`gstchildproxy.c + +libgstreamer_@GST_API_VERSION@_la-gstclock.lo: gstclock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstclock.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstclock.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstclock.lo `test -f 'gstclock.c' || echo '$(srcdir)/'`gstclock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstclock.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstclock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstclock.c' object='libgstreamer_@GST_API_VERSION@_la-gstclock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstclock.lo `test -f 'gstclock.c' || echo '$(srcdir)/'`gstclock.c + +libgstreamer_@GST_API_VERSION@_la-gstcontext.lo: gstcontext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstcontext.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontext.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstcontext.lo `test -f 'gstcontext.c' || echo '$(srcdir)/'`gstcontext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontext.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcontext.c' object='libgstreamer_@GST_API_VERSION@_la-gstcontext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstcontext.lo `test -f 'gstcontext.c' || echo '$(srcdir)/'`gstcontext.c + +libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo: gstcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo `test -f 'gstcontrolbinding.c' || echo '$(srcdir)/'`gstcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcontrolbinding.c' object='libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstcontrolbinding.lo `test -f 'gstcontrolbinding.c' || echo '$(srcdir)/'`gstcontrolbinding.c + +libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo: gstcontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo `test -f 'gstcontrolsource.c' || echo '$(srcdir)/'`gstcontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcontrolsource.c' object='libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo `test -f 'gstcontrolsource.c' || echo '$(srcdir)/'`gstcontrolsource.c + +libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo: gstdatetime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdatetime.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo `test -f 'gstdatetime.c' || echo '$(srcdir)/'`gstdatetime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdatetime.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdatetime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdatetime.c' object='libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo `test -f 'gstdatetime.c' || echo '$(srcdir)/'`gstdatetime.c + +libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo: gstdebugutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdebugutils.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo `test -f 'gstdebugutils.c' || echo '$(srcdir)/'`gstdebugutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdebugutils.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdebugutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdebugutils.c' object='libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo `test -f 'gstdebugutils.c' || echo '$(srcdir)/'`gstdebugutils.c + +libgstreamer_@GST_API_VERSION@_la-gstdevice.lo: gstdevice.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdevice.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdevice.lo `test -f 'gstdevice.c' || echo '$(srcdir)/'`gstdevice.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdevice.c' object='libgstreamer_@GST_API_VERSION@_la-gstdevice.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdevice.lo `test -f 'gstdevice.c' || echo '$(srcdir)/'`gstdevice.c + +libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo: gstdevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo `test -f 'gstdevicemonitor.c' || echo '$(srcdir)/'`gstdevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdevicemonitor.c' object='libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo `test -f 'gstdevicemonitor.c' || echo '$(srcdir)/'`gstdevicemonitor.c + +libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo: gstdeviceprovider.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo `test -f 'gstdeviceprovider.c' || echo '$(srcdir)/'`gstdeviceprovider.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdeviceprovider.c' object='libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdeviceprovider.lo `test -f 'gstdeviceprovider.c' || echo '$(srcdir)/'`gstdeviceprovider.c + +libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo: gstdeviceproviderfactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo `test -f 'gstdeviceproviderfactory.c' || echo '$(srcdir)/'`gstdeviceproviderfactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdeviceproviderfactory.c' object='libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdeviceproviderfactory.lo `test -f 'gstdeviceproviderfactory.c' || echo '$(srcdir)/'`gstdeviceproviderfactory.c + +libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo: gstdynamictypefactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo `test -f 'gstdynamictypefactory.c' || echo '$(srcdir)/'`gstdynamictypefactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdynamictypefactory.c' object='libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdynamictypefactory.lo `test -f 'gstdynamictypefactory.c' || echo '$(srcdir)/'`gstdynamictypefactory.c + +libgstreamer_@GST_API_VERSION@_la-gstelement.lo: gstelement.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstelement.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstelement.lo `test -f 'gstelement.c' || echo '$(srcdir)/'`gstelement.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstelement.c' object='libgstreamer_@GST_API_VERSION@_la-gstelement.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstelement.lo `test -f 'gstelement.c' || echo '$(srcdir)/'`gstelement.c + +libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo: gstelementfactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelementfactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo `test -f 'gstelementfactory.c' || echo '$(srcdir)/'`gstelementfactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelementfactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelementfactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstelementfactory.c' object='libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo `test -f 'gstelementfactory.c' || echo '$(srcdir)/'`gstelementfactory.c + +libgstreamer_@GST_API_VERSION@_la-gsterror.lo: gsterror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsterror.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsterror.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsterror.lo `test -f 'gsterror.c' || echo '$(srcdir)/'`gsterror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsterror.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsterror.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsterror.c' object='libgstreamer_@GST_API_VERSION@_la-gsterror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsterror.lo `test -f 'gsterror.c' || echo '$(srcdir)/'`gsterror.c + +libgstreamer_@GST_API_VERSION@_la-gstevent.lo: gstevent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstevent.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstevent.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstevent.lo `test -f 'gstevent.c' || echo '$(srcdir)/'`gstevent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstevent.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstevent.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstevent.c' object='libgstreamer_@GST_API_VERSION@_la-gstevent.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstevent.lo `test -f 'gstevent.c' || echo '$(srcdir)/'`gstevent.c + +libgstreamer_@GST_API_VERSION@_la-gstformat.lo: gstformat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstformat.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstformat.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstformat.lo `test -f 'gstformat.c' || echo '$(srcdir)/'`gstformat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstformat.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstformat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstformat.c' object='libgstreamer_@GST_API_VERSION@_la-gstformat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstformat.lo `test -f 'gstformat.c' || echo '$(srcdir)/'`gstformat.c + +libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo: gstghostpad.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstghostpad.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo `test -f 'gstghostpad.c' || echo '$(srcdir)/'`gstghostpad.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstghostpad.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstghostpad.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstghostpad.c' object='libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo `test -f 'gstghostpad.c' || echo '$(srcdir)/'`gstghostpad.c + +libgstreamer_@GST_API_VERSION@_la-gstinfo.lo: gstinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstinfo.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstinfo.lo `test -f 'gstinfo.c' || echo '$(srcdir)/'`gstinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstinfo.c' object='libgstreamer_@GST_API_VERSION@_la-gstinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstinfo.lo `test -f 'gstinfo.c' || echo '$(srcdir)/'`gstinfo.c + +libgstreamer_@GST_API_VERSION@_la-gstiterator.lo: gstiterator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstiterator.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstiterator.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstiterator.lo `test -f 'gstiterator.c' || echo '$(srcdir)/'`gstiterator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstiterator.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstiterator.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstiterator.c' object='libgstreamer_@GST_API_VERSION@_la-gstiterator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstiterator.lo `test -f 'gstiterator.c' || echo '$(srcdir)/'`gstiterator.c + +libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo: gstatomicqueue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo `test -f 'gstatomicqueue.c' || echo '$(srcdir)/'`gstatomicqueue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstatomicqueue.c' object='libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo `test -f 'gstatomicqueue.c' || echo '$(srcdir)/'`gstatomicqueue.c + +libgstreamer_@GST_API_VERSION@_la-gstmessage.lo: gstmessage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstmessage.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmessage.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstmessage.lo `test -f 'gstmessage.c' || echo '$(srcdir)/'`gstmessage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmessage.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmessage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstmessage.c' object='libgstreamer_@GST_API_VERSION@_la-gstmessage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstmessage.lo `test -f 'gstmessage.c' || echo '$(srcdir)/'`gstmessage.c + +libgstreamer_@GST_API_VERSION@_la-gstmeta.lo: gstmeta.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstmeta.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmeta.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstmeta.lo `test -f 'gstmeta.c' || echo '$(srcdir)/'`gstmeta.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmeta.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmeta.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstmeta.c' object='libgstreamer_@GST_API_VERSION@_la-gstmeta.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstmeta.lo `test -f 'gstmeta.c' || echo '$(srcdir)/'`gstmeta.c + +libgstreamer_@GST_API_VERSION@_la-gstmemory.lo: gstmemory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstmemory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmemory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstmemory.lo `test -f 'gstmemory.c' || echo '$(srcdir)/'`gstmemory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmemory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmemory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstmemory.c' object='libgstreamer_@GST_API_VERSION@_la-gstmemory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstmemory.lo `test -f 'gstmemory.c' || echo '$(srcdir)/'`gstmemory.c + +libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo: gstminiobject.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstminiobject.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo `test -f 'gstminiobject.c' || echo '$(srcdir)/'`gstminiobject.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstminiobject.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstminiobject.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstminiobject.c' object='libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstminiobject.lo `test -f 'gstminiobject.c' || echo '$(srcdir)/'`gstminiobject.c + +libgstreamer_@GST_API_VERSION@_la-gstpad.lo: gstpad.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpad.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpad.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpad.lo `test -f 'gstpad.c' || echo '$(srcdir)/'`gstpad.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpad.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpad.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpad.c' object='libgstreamer_@GST_API_VERSION@_la-gstpad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpad.lo `test -f 'gstpad.c' || echo '$(srcdir)/'`gstpad.c + +libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo: gstpadtemplate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo `test -f 'gstpadtemplate.c' || echo '$(srcdir)/'`gstpadtemplate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpadtemplate.c' object='libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpadtemplate.lo `test -f 'gstpadtemplate.c' || echo '$(srcdir)/'`gstpadtemplate.c + +libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo: gstparamspecs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparamspecs.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo `test -f 'gstparamspecs.c' || echo '$(srcdir)/'`gstparamspecs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparamspecs.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparamspecs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstparamspecs.c' object='libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstparamspecs.lo `test -f 'gstparamspecs.c' || echo '$(srcdir)/'`gstparamspecs.c + +libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo: gstpipeline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpipeline.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo `test -f 'gstpipeline.c' || echo '$(srcdir)/'`gstpipeline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpipeline.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpipeline.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpipeline.c' object='libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpipeline.lo `test -f 'gstpipeline.c' || echo '$(srcdir)/'`gstpipeline.c + +libgstreamer_@GST_API_VERSION@_la-gstplugin.lo: gstplugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstplugin.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstplugin.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstplugin.lo `test -f 'gstplugin.c' || echo '$(srcdir)/'`gstplugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstplugin.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstplugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstplugin.c' object='libgstreamer_@GST_API_VERSION@_la-gstplugin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstplugin.lo `test -f 'gstplugin.c' || echo '$(srcdir)/'`gstplugin.c + +libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo: gstpluginfeature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo `test -f 'gstpluginfeature.c' || echo '$(srcdir)/'`gstpluginfeature.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpluginfeature.c' object='libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpluginfeature.lo `test -f 'gstpluginfeature.c' || echo '$(srcdir)/'`gstpluginfeature.c + +libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo: gstpluginloader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginloader.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo `test -f 'gstpluginloader.c' || echo '$(srcdir)/'`gstpluginloader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginloader.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpluginloader.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpluginloader.c' object='libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpluginloader.lo `test -f 'gstpluginloader.c' || echo '$(srcdir)/'`gstpluginloader.c + +libgstreamer_@GST_API_VERSION@_la-gstpoll.lo: gstpoll.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpoll.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpoll.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpoll.lo `test -f 'gstpoll.c' || echo '$(srcdir)/'`gstpoll.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpoll.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpoll.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpoll.c' object='libgstreamer_@GST_API_VERSION@_la-gstpoll.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpoll.lo `test -f 'gstpoll.c' || echo '$(srcdir)/'`gstpoll.c + +libgstreamer_@GST_API_VERSION@_la-gstpreset.lo: gstpreset.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpreset.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpreset.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpreset.lo `test -f 'gstpreset.c' || echo '$(srcdir)/'`gstpreset.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpreset.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpreset.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpreset.c' object='libgstreamer_@GST_API_VERSION@_la-gstpreset.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpreset.lo `test -f 'gstpreset.c' || echo '$(srcdir)/'`gstpreset.c + +libgstreamer_@GST_API_VERSION@_la-gstprotection.lo: gstprotection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstprotection.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstprotection.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstprotection.lo `test -f 'gstprotection.c' || echo '$(srcdir)/'`gstprotection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstprotection.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstprotection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstprotection.c' object='libgstreamer_@GST_API_VERSION@_la-gstprotection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstprotection.lo `test -f 'gstprotection.c' || echo '$(srcdir)/'`gstprotection.c + +libgstreamer_@GST_API_VERSION@_la-gstquark.lo: gstquark.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstquark.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquark.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstquark.lo `test -f 'gstquark.c' || echo '$(srcdir)/'`gstquark.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquark.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquark.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstquark.c' object='libgstreamer_@GST_API_VERSION@_la-gstquark.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstquark.lo `test -f 'gstquark.c' || echo '$(srcdir)/'`gstquark.c + +libgstreamer_@GST_API_VERSION@_la-gstquery.lo: gstquery.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstquery.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquery.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstquery.lo `test -f 'gstquery.c' || echo '$(srcdir)/'`gstquery.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquery.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstquery.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstquery.c' object='libgstreamer_@GST_API_VERSION@_la-gstquery.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstquery.lo `test -f 'gstquery.c' || echo '$(srcdir)/'`gstquery.c + +libgstreamer_@GST_API_VERSION@_la-gstregistry.lo: gstregistry.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstregistry.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistry.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstregistry.lo `test -f 'gstregistry.c' || echo '$(srcdir)/'`gstregistry.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistry.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistry.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstregistry.c' object='libgstreamer_@GST_API_VERSION@_la-gstregistry.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstregistry.lo `test -f 'gstregistry.c' || echo '$(srcdir)/'`gstregistry.c + +libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo: gstregistrychunks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo `test -f 'gstregistrychunks.c' || echo '$(srcdir)/'`gstregistrychunks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstregistrychunks.c' object='libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstregistrychunks.lo `test -f 'gstregistrychunks.c' || echo '$(srcdir)/'`gstregistrychunks.c + +libgstreamer_@GST_API_VERSION@_la-gstpromise.lo: gstpromise.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstpromise.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpromise.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstpromise.lo `test -f 'gstpromise.c' || echo '$(srcdir)/'`gstpromise.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpromise.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstpromise.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpromise.c' object='libgstreamer_@GST_API_VERSION@_la-gstpromise.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstpromise.lo `test -f 'gstpromise.c' || echo '$(srcdir)/'`gstpromise.c + +libgstreamer_@GST_API_VERSION@_la-gstsample.lo: gstsample.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstsample.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsample.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstsample.lo `test -f 'gstsample.c' || echo '$(srcdir)/'`gstsample.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsample.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsample.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsample.c' object='libgstreamer_@GST_API_VERSION@_la-gstsample.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstsample.lo `test -f 'gstsample.c' || echo '$(srcdir)/'`gstsample.c + +libgstreamer_@GST_API_VERSION@_la-gstsegment.lo: gstsegment.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstsegment.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsegment.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstsegment.lo `test -f 'gstsegment.c' || echo '$(srcdir)/'`gstsegment.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsegment.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsegment.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsegment.c' object='libgstreamer_@GST_API_VERSION@_la-gstsegment.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstsegment.lo `test -f 'gstsegment.c' || echo '$(srcdir)/'`gstsegment.c + +libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo: gststreamcollection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreamcollection.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo `test -f 'gststreamcollection.c' || echo '$(srcdir)/'`gststreamcollection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreamcollection.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreamcollection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gststreamcollection.c' object='libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gststreamcollection.lo `test -f 'gststreamcollection.c' || echo '$(srcdir)/'`gststreamcollection.c + +libgstreamer_@GST_API_VERSION@_la-gststreams.lo: gststreams.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gststreams.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreams.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gststreams.lo `test -f 'gststreams.c' || echo '$(srcdir)/'`gststreams.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreams.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststreams.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gststreams.c' object='libgstreamer_@GST_API_VERSION@_la-gststreams.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gststreams.lo `test -f 'gststreams.c' || echo '$(srcdir)/'`gststreams.c + +libgstreamer_@GST_API_VERSION@_la-gststructure.lo: gststructure.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gststructure.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststructure.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gststructure.lo `test -f 'gststructure.c' || echo '$(srcdir)/'`gststructure.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststructure.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gststructure.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gststructure.c' object='libgstreamer_@GST_API_VERSION@_la-gststructure.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gststructure.lo `test -f 'gststructure.c' || echo '$(srcdir)/'`gststructure.c + +libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo: gstsystemclock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsystemclock.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo `test -f 'gstsystemclock.c' || echo '$(srcdir)/'`gstsystemclock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsystemclock.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstsystemclock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsystemclock.c' object='libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstsystemclock.lo `test -f 'gstsystemclock.c' || echo '$(srcdir)/'`gstsystemclock.c + +libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo: gsttaglist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaglist.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo `test -f 'gsttaglist.c' || echo '$(srcdir)/'`gsttaglist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaglist.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaglist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttaglist.c' object='libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttaglist.lo `test -f 'gsttaglist.c' || echo '$(srcdir)/'`gsttaglist.c + +libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo: gsttagsetter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttagsetter.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo `test -f 'gsttagsetter.c' || echo '$(srcdir)/'`gsttagsetter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttagsetter.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttagsetter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttagsetter.c' object='libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttagsetter.lo `test -f 'gsttagsetter.c' || echo '$(srcdir)/'`gsttagsetter.c + +libgstreamer_@GST_API_VERSION@_la-gsttask.lo: gsttask.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttask.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttask.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttask.lo `test -f 'gsttask.c' || echo '$(srcdir)/'`gsttask.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttask.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttask.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttask.c' object='libgstreamer_@GST_API_VERSION@_la-gsttask.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttask.lo `test -f 'gsttask.c' || echo '$(srcdir)/'`gsttask.c + +libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo: gsttaskpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaskpool.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo `test -f 'gsttaskpool.c' || echo '$(srcdir)/'`gsttaskpool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaskpool.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttaskpool.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttaskpool.c' object='libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttaskpool.lo `test -f 'gsttaskpool.c' || echo '$(srcdir)/'`gsttaskpool.c + +libgstreamer_@GST_API_VERSION@_la-gsttoc.lo: gsttoc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttoc.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttoc.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttoc.lo `test -f 'gsttoc.c' || echo '$(srcdir)/'`gsttoc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttoc.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttoc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttoc.c' object='libgstreamer_@GST_API_VERSION@_la-gsttoc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttoc.lo `test -f 'gsttoc.c' || echo '$(srcdir)/'`gsttoc.c + +libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo: gsttocsetter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttocsetter.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo `test -f 'gsttocsetter.c' || echo '$(srcdir)/'`gsttocsetter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttocsetter.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttocsetter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttocsetter.c' object='libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttocsetter.lo `test -f 'gsttocsetter.c' || echo '$(srcdir)/'`gsttocsetter.c + +libgstreamer_@GST_API_VERSION@_la-gsttracer.lo: gsttracer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttracer.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracer.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttracer.lo `test -f 'gsttracer.c' || echo '$(srcdir)/'`gsttracer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracer.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttracer.c' object='libgstreamer_@GST_API_VERSION@_la-gsttracer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttracer.lo `test -f 'gsttracer.c' || echo '$(srcdir)/'`gsttracer.c + +libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo: gsttracerfactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo `test -f 'gsttracerfactory.c' || echo '$(srcdir)/'`gsttracerfactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttracerfactory.c' object='libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerfactory.lo `test -f 'gsttracerfactory.c' || echo '$(srcdir)/'`gsttracerfactory.c + +libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo: gsttracerrecord.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo `test -f 'gsttracerrecord.c' || echo '$(srcdir)/'`gsttracerrecord.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttracerrecord.c' object='libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerrecord.lo `test -f 'gsttracerrecord.c' || echo '$(srcdir)/'`gsttracerrecord.c + +libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo: gsttracerutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerutils.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo `test -f 'gsttracerutils.c' || echo '$(srcdir)/'`gsttracerutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerutils.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttracerutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttracerutils.c' object='libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttracerutils.lo `test -f 'gsttracerutils.c' || echo '$(srcdir)/'`gsttracerutils.c + +libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo: gsttypefind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefind.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo `test -f 'gsttypefind.c' || echo '$(srcdir)/'`gsttypefind.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefind.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefind.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttypefind.c' object='libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttypefind.lo `test -f 'gsttypefind.c' || echo '$(srcdir)/'`gsttypefind.c + +libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo: gsttypefindfactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo `test -f 'gsttypefindfactory.c' || echo '$(srcdir)/'`gsttypefindfactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttypefindfactory.c' object='libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsttypefindfactory.lo `test -f 'gsttypefindfactory.c' || echo '$(srcdir)/'`gsttypefindfactory.c + +libgstreamer_@GST_API_VERSION@_la-gsturi.lo: gsturi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gsturi.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsturi.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gsturi.lo `test -f 'gsturi.c' || echo '$(srcdir)/'`gsturi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsturi.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gsturi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsturi.c' object='libgstreamer_@GST_API_VERSION@_la-gsturi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gsturi.lo `test -f 'gsturi.c' || echo '$(srcdir)/'`gsturi.c + +libgstreamer_@GST_API_VERSION@_la-gstutils.lo: gstutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstutils.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstutils.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstutils.lo `test -f 'gstutils.c' || echo '$(srcdir)/'`gstutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstutils.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstutils.c' object='libgstreamer_@GST_API_VERSION@_la-gstutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstutils.lo `test -f 'gstutils.c' || echo '$(srcdir)/'`gstutils.c + +libgstreamer_@GST_API_VERSION@_la-gstvalue.lo: gstvalue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstvalue.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstvalue.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstvalue.lo `test -f 'gstvalue.c' || echo '$(srcdir)/'`gstvalue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstvalue.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstvalue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstvalue.c' object='libgstreamer_@GST_API_VERSION@_la-gstvalue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstvalue.lo `test -f 'gstvalue.c' || echo '$(srcdir)/'`gstvalue.c + +libgstreamer_@GST_API_VERSION@_la-gstparse.lo: gstparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstparse.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparse.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstparse.lo `test -f 'gstparse.c' || echo '$(srcdir)/'`gstparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparse.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstparse.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstparse.c' object='libgstreamer_@GST_API_VERSION@_la-gstparse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstparse.lo `test -f 'gstparse.c' || echo '$(srcdir)/'`gstparse.c + +libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo: gstregistrybinary.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo `test -f 'gstregistrybinary.c' || echo '$(srcdir)/'`gstregistrybinary.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstregistrybinary.c' object='libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo `test -f 'gstregistrybinary.c' || echo '$(srcdir)/'`gstregistrybinary.c + +libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo: gstenumtypes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstenumtypes.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo `test -f 'gstenumtypes.c' || echo '$(srcdir)/'`gstenumtypes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstenumtypes.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstenumtypes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstenumtypes.c' object='libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstenumtypes.lo `test -f 'gstenumtypes.c' || echo '$(srcdir)/'`gstenumtypes.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstreamer_@GST_API_VERSION@includeHEADERS: $(libgstreamer_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstreamer_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstreamer_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-libgstreamer_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstreamer_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstreamer_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) +install-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS: $(nodist_libgstreamer_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libgstreamer_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstreamer_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libgstreamer_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstreamer_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)" "$(DESTDIR)$(libgstreamer_@GST_API_VERSION@includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-girDATA \ + install-libgstreamer_@GST_API_VERSION@includeHEADERS \ + install-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstreamer_@GST_API_VERSION@includeHEADERS \ + uninstall-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ + check check-am clean clean-generic clean-libLTLIBRARIES \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-girDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES \ + install-libgstreamer_@GST_API_VERSION@includeHEADERS \ + install-man \ + install-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstreamer_@GST_API_VERSION@includeHEADERS \ + uninstall-nodist_libgstreamer_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +gstenumtypes.h: $(gst_headers) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --fhead "#ifndef __GST_ENUM_TYPES_H__\n#define __GST_ENUM_TYPES_H__\n\n#include \n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "GST_API GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __GST_ENUM_TYPES_H__ */" \ + $^ > gstenumtypes.h + +gstenumtypes.c: $(gst_headers) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --fhead "#include \"gst_private.h\"\n#include \n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n " \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static gsize id = 0;\n static const G@Type@Value values[] = {" \ + --vprod " { C_@TYPE@(@VALUENAME@), \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n\n if (g_once_init_enter (&id)) {\n GType tmp = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&id, tmp);\n }\n\n return (GType) id;\n}" \ + $^ > gstenumtypes.c + +%.c.gcov: .libs/libgstreamer_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstreamer_@GST_API_VERSION@_la_SOURCES:=.gcov) + +@HAVE_INTROSPECTION_TRUE@Gst-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstreamer-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes GI_SCANNER_DISABLE_CACHE=yes \ +@HAVE_INTROSPECTION_TRUE@ CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace Gst \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --verbose \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -DIN_GOBJECT_INTROSPECTION=1 \ +@HAVE_INTROSPECTION_TRUE@ --c-include='gst/gst.h' \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstreamer-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=GLib-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --include=GObject-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --include=GModule-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ +@HAVE_INTROSPECTION_TRUE@ --pkg glib-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --pkg gobject-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --pkg gmodule-no-export-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --add-init-section="$(INTROSPECTION_INIT)" \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# try to prevent packaging errors +check-libexecdir-consistency: + @if test "${GST_PLUGIN_SCANNER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; then \ + echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \ + echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \ + echo "*** The same goes for prefix, libdir etc."; \ + echo "*** ${GST_PLUGIN_SCANNER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-plugin-scanner"; \ + exit 1; \ + fi + +all-local: check-libexecdir-consistency + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/gettext.h b/gst/gettext.h new file mode 100644 index 0000000..fc70ab7 --- /dev/null +++ b/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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#ifdef 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/glib-compat-private.h b/gst/glib-compat-private.h new file mode 100644 index 0000000..8f37de2 --- /dev/null +++ b/gst/glib-compat-private.h @@ -0,0 +1,36 @@ +/* + * glib-compat.c + * Functions copied from glib 2.10 + * + * Copyright 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GLIB_COMPAT_PRIVATE_H__ +#define __GLIB_COMPAT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +/* copies */ + +/* adaptations */ + +G_END_DECLS + +#endif diff --git a/gst/glib-compat.h b/gst/glib-compat.h new file mode 100644 index 0000000..5fb267b --- /dev/null +++ b/gst/glib-compat.h @@ -0,0 +1,39 @@ +/* GStreamer + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * glib-compat.h: Public GLib compatibility shims + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS file from + * glib-2.8.0 for a list of people on the GLib Team. See the ChangeLog files + * from glib-2.8.0 for a list of changes. These files are distributed with GLib + * at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GST_GLIB_COMPAT_H__ +#define __GST_GLIB_COMPAT_H__ + +#include + +G_BEGIN_DECLS + +G_END_DECLS + +#endif /* __GST_GLIB_COMPAT_H__ */ diff --git a/gst/gst-i18n-app.h b/gst/gst-i18n-app.h new file mode 100644 index 0000000..56140e5 --- /dev/null +++ b/gst/gst-i18n-app.h @@ -0,0 +1,44 @@ +/* GStreamer + * Copyright (C) 2004 Thomas Vander Stichele + * + * gst-i18n-app.h: internationalization macros for the GStreamer tools + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_I18N_APP_H__ +#define __GST_I18N_APP_H__ + +#ifdef ENABLE_NLS + +#include /* some people need it and some people don't */ +#include "gettext.h" /* included with gettext distribution and copied */ + +/* we want to use shorthand _() for translating and N_() for marking */ +#define _(String) gettext (String) +#define N_(String) gettext_noop (String) +/* FIXME: if we need it, we can add Q_ as well, like in glib */ + +#else + +#define _(String) String +#define N_(String) String +#define ngettext(Singular,Plural,Count) ((Count>1)?Plural:Singular) + +#endif + +#endif /* __GST_I18N_APP_H__ */ diff --git a/gst/gst-i18n-lib.h b/gst/gst-i18n-lib.h new file mode 100644 index 0000000..cf5c285 --- /dev/null +++ b/gst/gst-i18n-lib.h @@ -0,0 +1,47 @@ +/* GStreamer + * Copyright (C) 2004 Thomas Vander Stichele + * + * gst-i18n-lib.h: internationalization macros for the GStreamer libraries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_I18N_LIB_H__ +#define __GST_I18N_LIB_H__ + +#ifndef PACKAGE_NAME +#error You must include config.h before including this header. +#endif + +#ifdef ENABLE_NLS + +#include /* some people need it and some people don't */ +#include "gettext.h" /* included with gettext distribution and copied */ + +/* 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 */ + +#else +#define _(String) String +#define N_(String) String +#define ngettext(Singular,Plural,Count) ((Count>1)?Plural:Singular) + +#endif + +#endif /* __GST_I18N_LIB_H__ */ diff --git a/gst/gst.c b/gst/gst.c new file mode 100644 index 0000000..42adb9d --- /dev/null +++ b/gst/gst.c @@ -0,0 +1,1313 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gst.c: Initialization and non-pipeline operations + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gst + * @title: GStreamer + * @short_description: Media library supporting arbitrary formats and filter + * graphs. + * + * GStreamer is a framework for constructing graphs of various filters + * (termed elements here) that will handle streaming media. Any discrete + * (packetizable) media type is supported, with provisions for automatically + * determining source type. Formatting/framing information is provided with + * a powerful negotiation framework. Plugins are heavily used to provide for + * all elements, allowing one to construct plugins outside of the GST + * library, even released binary-only if license require (please don't). + * GStreamer covers a wide range of use cases including: playback, recording, + * editing, serving streams, voice over ip and video calls. + * + * The GStreamer library should be initialized with + * gst_init() before it can be used. You should pass pointers to the main argc + * and argv variables so that GStreamer can process its own command line + * options, as shown in the following example. + * + * ## Initializing the gstreamer library + * + * |[ + * int + * main (int argc, char *argv[]) + * { + * // initialize the GStreamer library + * gst_init (&argc, &argv); + * ... + * } + * ]| + * + * It's allowed to pass two %NULL pointers to gst_init() in case you don't want + * to pass the command line args to GStreamer. + * + * You can also use GOption to initialize your own parameters as shown in + * the next code fragment: + * + * ## Initializing own parameters when initializing gstreamer + * |[ + * static gboolean stats = FALSE; + * ... + * int + * main (int argc, char *argv[]) + * { + * GOptionEntry options[] = { + * {"tags", 't', 0, G_OPTION_ARG_NONE, &tags, + * N_("Output tags (also known as metadata)"), NULL}, + * {NULL} + * }; + * ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]"); + * 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); + * ... + * } + * ]| + * + * Use gst_version() to query the library version at runtime or use the + * GST_VERSION_* macros to find the version at compile time. Optionally + * gst_version_string() returns a printable string. + * + * The gst_deinit() call is used to clean up all internal resources used + * by GStreamer. It is mostly used in unit tests to check for leaks. + */ + +#include "gst_private.h" +#include "gstconfig.h" +#include +#include +#include +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ +#include /* GetStdHandle, windows console */ +#endif +#if defined (__APPLE__) +#include "TargetConditionals.h" +#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED +#include /* proc_pidpath, PROC_PIDPATHINFO_MAXSIZE */ +#endif +#endif + +#include "gst-i18n-lib.h" +#include /* for LC_ALL */ + +#include "gst.h" + +#define GST_CAT_DEFAULT GST_CAT_GST_INIT + +#define MAX_PATH_SPLIT 16 +#define GST_PLUGIN_SEPARATOR "," + +static gboolean gst_initialized = FALSE; +static gboolean gst_deinitialized = FALSE; + +GstClockTime _priv_gst_start_time; + +#ifdef G_OS_WIN32 +HMODULE _priv_gst_dll_handle = NULL; +#endif + +#ifndef GST_DISABLE_REGISTRY +GList *_priv_gst_plugin_paths = NULL; /* for delayed processing in init_post */ + +extern gboolean _priv_gst_disable_registry; +extern gboolean _priv_gst_disable_registry_update; +#endif + +gchar *_gst_executable_path = NULL; + +#ifndef GST_DISABLE_GST_DEBUG +const gchar *priv_gst_dump_dot_dir; +#endif + +/* defaults */ + +/* set to TRUE when segfaults need to be left as is */ +static gboolean _gst_disable_segtrap = FALSE; + +static gboolean init_pre (GOptionContext * context, GOptionGroup * group, + gpointer data, GError ** error); +static gboolean init_post (GOptionContext * context, GOptionGroup * group, + gpointer data, GError ** error); +#ifndef GST_DISABLE_OPTION_PARSING +static gboolean parse_goption_arg (const gchar * s_opt, + const gchar * arg, gpointer data, GError ** err); +#endif + +GSList *_priv_gst_preload_plugins = NULL; + +const gchar g_log_domain_gstreamer[] = "GStreamer"; + +static void +debug_log_handler (const gchar * log_domain, + GLogLevelFlags log_level, const gchar * message, gpointer user_data) +{ + g_log_default_handler (log_domain, log_level, message, user_data); + /* FIXME: do we still need this ? fatal errors these days are all + * other than core errors */ + /* g_on_error_query (NULL); */ +} + +enum +{ + ARG_VERSION = 1, + ARG_FATAL_WARNINGS, +#ifndef GST_DISABLE_GST_DEBUG + ARG_DEBUG_LEVEL, + ARG_DEBUG, + ARG_DEBUG_DISABLE, + ARG_DEBUG_NO_COLOR, + ARG_DEBUG_COLOR_MODE, + ARG_DEBUG_HELP, +#endif + ARG_PLUGIN_SPEW, + ARG_PLUGIN_PATH, + ARG_PLUGIN_LOAD, + ARG_SEGTRAP_DISABLE, + ARG_REGISTRY_UPDATE_DISABLE, + ARG_REGISTRY_FORK_DISABLE +}; + +/* debug-spec ::= category-spec [, category-spec]* + * category-spec ::= category:val | val + * category ::= [^:]+ + * val ::= [0-5] + */ + +#ifdef G_OS_WIN32 +/* Note: DllMain is only called when DLLs are loaded or unloaded, so this will + * never be called if libgstreamer-1.0 is linked statically. Do not add any code + * here to, say, initialize variables or set things up since that will only + * happen for dynamically-built GStreamer. + * + * Also, ideally this should not be defined when GStreamer is built statically. + * i.e., it should be conditional on #ifdef DLL_EXPORT. It will be ignored, but + * if other libraries make the same mistake of defining it when building + * statically, there will be a symbol collision during linking. Fixing this + * requires one to build two object files: one for static linking and another + * for dynamic linking. */ +BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + _priv_gst_dll_handle = (HMODULE) hinstDLL; + return TRUE; +} + +#endif + +/** + * gst_init_get_option_group: (skip) + * + * Returns a #GOptionGroup with GStreamer's argument specifications. The + * group is set up to use standard GOption callbacks, so when using this + * group in combination with GOption parsing methods, all argument parsing + * and initialization is automated. + * + * This function is useful if you want to integrate GStreamer with other + * libraries that use GOption (see g_option_context_add_group() ). + * + * If you use this function, you should make sure you initialise the GLib + * threading system as one of the very first things in your program + * (see the example at the beginning of this section). + * + * Returns: (transfer full) (nullable): a pointer to GStreamer's option group. + */ + +GOptionGroup * +gst_init_get_option_group (void) +{ +#ifndef GST_DISABLE_OPTION_PARSING + GOptionGroup *group; + static const GOptionEntry gst_args[] = { + {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, N_("Print the GStreamer version"), NULL}, + {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, N_("Make all warnings fatal"), NULL}, +#ifndef GST_DISABLE_GST_DEBUG + {"gst-debug-help", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Print available debug categories and exit"), + NULL}, + {"gst-debug-level", 0, 0, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Default debug level from 1 (only error) to 9 (anything) or " + "0 for no output"), + N_("LEVEL")}, + {"gst-debug", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) parse_goption_arg, + N_("Comma-separated list of category_name:level pairs to set " + "specific levels for the individual categories. Example: " + "GST_AUTOPLUG:5,GST_ELEMENT_*:3"), + N_("LIST")}, + {"gst-debug-no-color", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, N_("Disable colored debugging output"), + NULL}, + {"gst-debug-color-mode", 0, 0, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Changes coloring mode of the debug log. " + "Possible modes: off, on, disable, auto, unix"), + NULL}, + {"gst-debug-disable", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, N_("Disable debugging"), NULL}, +#endif + {"gst-plugin-spew", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Enable verbose plugin loading diagnostics"), + NULL}, + {"gst-plugin-path", 0, 0, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Colon-separated paths containing plugins"), N_("PATHS")}, + {"gst-plugin-load", 0, 0, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Comma-separated list of plugins to preload in addition to the " + "list stored in environment variable GST_PLUGIN_PATH"), + N_("PLUGINS")}, + {"gst-disable-segtrap", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Disable trapping of segmentation faults during plugin loading"), + NULL}, + {"gst-disable-registry-update", 0, G_OPTION_FLAG_NO_ARG, + G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Disable updating the registry"), + NULL}, + {"gst-disable-registry-fork", 0, G_OPTION_FLAG_NO_ARG, + G_OPTION_ARG_CALLBACK, + (gpointer) parse_goption_arg, + N_("Disable spawning a helper process while scanning the registry"), + NULL}, + {NULL} + }; + + group = g_option_group_new ("gst", _("GStreamer Options"), + _("Show GStreamer Options"), NULL, NULL); + g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre, + (GOptionParseFunc) init_post); + + g_option_group_add_entries (group, gst_args); + g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); + + return group; +#else + return NULL; +#endif +} + +#if defined(__linux__) +static void +find_executable_path (void) +{ + GError *error = NULL; + + if (_gst_executable_path) + return; + + _gst_executable_path = g_file_read_link ("/proc/self/exe", &error); + if (error) + g_error_free (error); +} +#elif defined(G_OS_WIN32) +static void +find_executable_path (void) +{ + char buffer[MAX_PATH]; + + if (!GetModuleFileName (NULL, buffer, MAX_PATH)) + return; + + _gst_executable_path = g_strdup (buffer); +} +#elif defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED +static void +find_executable_path (void) +{ + int ret; + pid_t pid; + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + + pid = getpid (); + ret = proc_pidpath (pid, pathbuf, sizeof (pathbuf)); + if (ret > 0) + _gst_executable_path = g_strdup (pathbuf); +} +#else +static void +find_executable_path (void) +{ + GST_FIXME ("Couldn't look up executable path, add support for this platform"); +} +#endif + +/** + * gst_get_main_executable_path: + * + * This helper is mostly helpful for plugins that need to + * inspect the folder of the main executable to determine + * their set of features. + * + * When a plugin is initialized from the gst-plugin-scanner + * external process, the returned path will be the same as from the + * parent process. + * + * Returns: (transfer none) (nullable): The path of the executable that + * initialized GStreamer, or %NULL if it could not be determined. + * + * Since: 1.14 + */ +const gchar * +gst_get_main_executable_path (void) +{ + return _gst_executable_path; +} + +/** + * gst_init_check: + * @argc: (inout) (allow-none): pointer to application's argc + * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv + * @err: pointer to a #GError to which a message will be posted on error + * + * Initializes the GStreamer library, setting up internal path lists, + * registering built-in elements, and loading standard plugins. + * + * This function will return %FALSE if GStreamer could not be initialized + * for some reason. If you want your program to fail fatally, + * use gst_init() instead. + * + * Returns: %TRUE if GStreamer could be initialized. + */ +gboolean +gst_init_check (int *argc, char **argv[], GError ** err) +{ + static GMutex init_lock; +#ifndef GST_DISABLE_OPTION_PARSING + GOptionGroup *group; + GOptionContext *ctx; +#endif + gboolean res; + + g_mutex_lock (&init_lock); + + if (gst_initialized) { + GST_DEBUG ("already initialized gst"); + g_mutex_unlock (&init_lock); + return TRUE; + } +#ifndef GST_DISABLE_OPTION_PARSING + ctx = g_option_context_new ("- GStreamer initialization"); + g_option_context_set_ignore_unknown_options (ctx, TRUE); + g_option_context_set_help_enabled (ctx, FALSE); + group = gst_init_get_option_group (); + g_option_context_add_group (ctx, group); + res = g_option_context_parse (ctx, argc, argv, err); + g_option_context_free (ctx); +#else + init_pre (NULL, NULL, NULL, NULL); + init_post (NULL, NULL, NULL, NULL); + res = TRUE; +#endif + + gst_initialized = res; + + g_mutex_unlock (&init_lock); + + return res; +} + +/** + * gst_init: + * @argc: (inout) (allow-none): pointer to application's argc + * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv + * + * Initializes the GStreamer library, setting up internal path lists, + * registering built-in elements, and loading standard plugins. + * + * Unless the plugin registry is disabled at compile time, the registry will be + * loaded. By default this will also check if the registry cache needs to be + * updated and rescan all plugins if needed. See gst_update_registry() for + * details and section + * Running GStreamer Applications + * for how to disable automatic registry updates. + * + * > This function will terminate your program if it was unable to initialize + * > GStreamer for some reason. If you want your program to fall back, + * > use gst_init_check() instead. + * + * WARNING: This function does not work in the same way as corresponding + * functions in other glib-style libraries, such as gtk_init\(\). In + * particular, unknown command line options cause this function to + * abort program execution. + */ +void +gst_init (int *argc, char **argv[]) +{ + GError *err = NULL; + + if (!gst_init_check (argc, argv, &err)) { + g_print ("Could not initialize GStreamer: %s\n", + err ? err->message : "unknown error occurred"); + if (err) { + g_error_free (err); + } + exit (1); + } +} + +/** + * gst_is_initialized: + * + * Use this function to check if GStreamer has been initialized with gst_init() + * or gst_init_check(). + * + * Returns: %TRUE if initialization has been done, %FALSE otherwise. + */ +gboolean +gst_is_initialized (void) +{ + return gst_initialized; +} + +#ifndef GST_DISABLE_OPTION_PARSING +# ifndef GST_DISABLE_REGISTRY +static void +add_path_func (gpointer data, gpointer user_data) +{ + GST_INFO ("Adding plugin path: \"%s\", will scan later", (gchar *) data); + _priv_gst_plugin_paths = + g_list_append (_priv_gst_plugin_paths, g_strdup (data)); +} +# endif +#endif + +#ifndef GST_DISABLE_OPTION_PARSING +static void +prepare_for_load_plugin_func (gpointer data, gpointer user_data) +{ + _priv_gst_preload_plugins = + g_slist_prepend (_priv_gst_preload_plugins, g_strdup (data)); +} +#endif + +#ifndef GST_DISABLE_OPTION_PARSING +static void +split_and_iterate (const gchar * stringlist, const gchar * separator, + GFunc iterator, gpointer user_data) +{ + gchar **strings; + gint j = 0; + gchar *lastlist = g_strdup (stringlist); + + while (lastlist) { + strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT); + g_free (lastlist); + lastlist = NULL; + + while (strings[j]) { + iterator (strings[j], user_data); + if (++j == MAX_PATH_SPLIT) { + lastlist = g_strdup (strings[j]); + j = 0; + break; + } + } + g_strfreev (strings); + } +} +#endif + +/* we have no fail cases yet, but maybe in the future */ +static gboolean +init_pre (GOptionContext * context, GOptionGroup * group, gpointer data, + GError ** error) +{ + gchar *libdir; + if (gst_initialized) { + GST_DEBUG ("already initialized"); + return TRUE; + } + + find_executable_path (); + + _priv_gst_start_time = gst_util_get_timestamp (); + +#ifndef GST_DISABLE_GST_DEBUG + _priv_gst_debug_init (); + priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR"); +#endif + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + /* This is the earliest we can make stuff show up in the logs. + * So give some useful info about GStreamer here */ +#ifdef G_OS_WIN32 + { + gchar *basedir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + + libdir = g_build_filename (basedir, +#ifdef _DEBUG + "debug" +#endif + "lib", NULL); + g_free (basedir); + } +#else + libdir = g_strdup (LIBDIR); +#endif + GST_INFO ("Initializing GStreamer Core Library version %s", VERSION); + GST_INFO ("Using library installed in %s", libdir); + g_free (libdir); + +#ifndef GST_DISABLE_REGISTRY + { + const gchar *disable_registry; + if ((disable_registry = g_getenv ("GST_REGISTRY_DISABLE"))) { + _priv_gst_disable_registry = (strcmp (disable_registry, "yes") == 0); + } + } +#endif + + /* Print some basic system details if possible (OS/architecture) */ +#ifdef HAVE_SYS_UTSNAME_H + { + struct utsname sys_details; + + if (uname (&sys_details) == 0) { + GST_INFO ("%s %s %s %s %s", sys_details.sysname, + sys_details.nodename, sys_details.release, sys_details.version, + sys_details.machine); + } + } +#endif + +#ifndef G_ATOMIC_LOCK_FREE + GST_CAT_WARNING (GST_CAT_PERFORMANCE, "GLib atomic operations are NOT " + "implemented using real hardware atomic operations!"); +#endif + + return TRUE; +} + +static gboolean +gst_register_core_elements (GstPlugin * plugin) +{ + /* register some standard builtin types */ + if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY, + GST_TYPE_BIN) || + !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY, + GST_TYPE_PIPELINE) + ) + g_assert_not_reached (); + + return TRUE; +} + +/* + * this bit handles: + * - initalization of threads if we use them + * - log handler + * - initial output + * - initializes gst_format + * - registers a bunch of types for gst_objects + * + * - we don't have cases yet where this fails, but in the future + * we might and then it's nice to be able to return that + */ +static gboolean +init_post (GOptionContext * context, GOptionGroup * group, gpointer data, + GError ** error) +{ + GLogLevelFlags llf; + + if (gst_initialized) { + GST_DEBUG ("already initialized"); + return TRUE; + } + + llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL; + g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL); + + _priv_gst_mini_object_initialize (); + _priv_gst_quarks_initialize (); + _priv_gst_allocator_initialize (); + _priv_gst_memory_initialize (); + _priv_gst_format_initialize (); + _priv_gst_query_initialize (); + _priv_gst_structure_initialize (); + _priv_gst_caps_initialize (); + _priv_gst_caps_features_initialize (); + _priv_gst_meta_initialize (); + _priv_gst_message_initialize (); + + g_type_class_ref (gst_object_get_type ()); + g_type_class_ref (gst_pad_get_type ()); + g_type_class_ref (gst_element_factory_get_type ()); + g_type_class_ref (gst_element_get_type ()); + g_type_class_ref (gst_tracer_factory_get_type ()); + g_type_class_ref (gst_type_find_factory_get_type ()); + g_type_class_ref (gst_bin_get_type ()); + g_type_class_ref (gst_bus_get_type ()); + g_type_class_ref (gst_task_get_type ()); + g_type_class_ref (gst_clock_get_type ()); + g_type_class_ref (gst_debug_color_mode_get_type ()); + + gst_uri_handler_get_type (); + + g_type_class_ref (gst_object_flags_get_type ()); + g_type_class_ref (gst_bin_flags_get_type ()); + g_type_class_ref (gst_buffer_flags_get_type ()); + g_type_class_ref (gst_buffer_copy_flags_get_type ()); + g_type_class_ref (gst_bus_flags_get_type ()); + g_type_class_ref (gst_bus_sync_reply_get_type ()); + g_type_class_ref (gst_caps_flags_get_type ()); + g_type_class_ref (gst_clock_return_get_type ()); + g_type_class_ref (gst_clock_entry_type_get_type ()); + g_type_class_ref (gst_clock_flags_get_type ()); + g_type_class_ref (gst_clock_type_get_type ()); + g_type_class_ref (gst_debug_graph_details_get_type ()); + g_type_class_ref (gst_state_get_type ()); + g_type_class_ref (gst_state_change_return_get_type ()); + g_type_class_ref (gst_state_change_get_type ()); + g_type_class_ref (gst_element_flags_get_type ()); + g_type_class_ref (gst_tracer_value_scope_get_type ()); + g_type_class_ref (gst_tracer_value_flags_get_type ()); + g_type_class_ref (gst_core_error_get_type ()); + g_type_class_ref (gst_library_error_get_type ()); + g_type_class_ref (gst_resource_error_get_type ()); + g_type_class_ref (gst_stream_error_get_type ()); + g_type_class_ref (gst_event_type_flags_get_type ()); + g_type_class_ref (gst_event_type_get_type ()); + g_type_class_ref (gst_seek_type_get_type ()); + g_type_class_ref (gst_seek_flags_get_type ()); + g_type_class_ref (gst_qos_type_get_type ()); + g_type_class_ref (gst_format_get_type ()); + g_type_class_ref (gst_debug_level_get_type ()); + g_type_class_ref (gst_debug_color_flags_get_type ()); + g_type_class_ref (gst_iterator_result_get_type ()); + g_type_class_ref (gst_iterator_item_get_type ()); + g_type_class_ref (gst_message_type_get_type ()); + g_type_class_ref (gst_mini_object_flags_get_type ()); + g_type_class_ref (gst_pad_link_return_get_type ()); + g_type_class_ref (gst_pad_link_check_get_type ()); + g_type_class_ref (gst_flow_return_get_type ()); + g_type_class_ref (gst_pad_mode_get_type ()); + g_type_class_ref (gst_pad_direction_get_type ()); + g_type_class_ref (gst_pad_flags_get_type ()); + g_type_class_ref (gst_pad_presence_get_type ()); + g_type_class_ref (gst_pad_template_flags_get_type ()); + g_type_class_ref (gst_pipeline_flags_get_type ()); + g_type_class_ref (gst_plugin_error_get_type ()); + g_type_class_ref (gst_plugin_flags_get_type ()); + g_type_class_ref (gst_plugin_dependency_flags_get_type ()); + g_type_class_ref (gst_rank_get_type ()); + g_type_class_ref (gst_query_type_flags_get_type ()); + g_type_class_ref (gst_query_type_get_type ()); + g_type_class_ref (gst_buffering_mode_get_type ()); + g_type_class_ref (gst_stream_status_type_get_type ()); + g_type_class_ref (gst_structure_change_type_get_type ()); + g_type_class_ref (gst_tag_merge_mode_get_type ()); + g_type_class_ref (gst_tag_flag_get_type ()); + g_type_class_ref (gst_tag_scope_get_type ()); + g_type_class_ref (gst_task_pool_get_type ()); + g_type_class_ref (gst_task_state_get_type ()); + g_type_class_ref (gst_toc_entry_type_get_type ()); + g_type_class_ref (gst_type_find_probability_get_type ()); + g_type_class_ref (gst_uri_error_get_type ()); + g_type_class_ref (gst_uri_type_get_type ()); + g_type_class_ref (gst_parse_error_get_type ()); + g_type_class_ref (gst_parse_flags_get_type ()); + g_type_class_ref (gst_search_mode_get_type ()); + g_type_class_ref (gst_progress_type_get_type ()); + g_type_class_ref (gst_buffer_pool_acquire_flags_get_type ()); + g_type_class_ref (gst_memory_flags_get_type ()); + g_type_class_ref (gst_map_flags_get_type ()); + g_type_class_ref (gst_caps_intersect_mode_get_type ()); + g_type_class_ref (gst_pad_probe_type_get_type ()); + g_type_class_ref (gst_pad_probe_return_get_type ()); + g_type_class_ref (gst_segment_flags_get_type ()); + g_type_class_ref (gst_scheduling_flags_get_type ()); + g_type_class_ref (gst_meta_flags_get_type ()); + g_type_class_ref (gst_toc_entry_type_get_type ()); + g_type_class_ref (gst_toc_scope_get_type ()); + g_type_class_ref (gst_toc_loop_type_get_type ()); + g_type_class_ref (gst_control_binding_get_type ()); + g_type_class_ref (gst_control_source_get_type ()); + g_type_class_ref (gst_lock_flags_get_type ()); + g_type_class_ref (gst_allocator_flags_get_type ()); + g_type_class_ref (gst_stream_flags_get_type ()); + g_type_class_ref (gst_stream_type_get_type ()); + g_type_class_ref (gst_stack_trace_flags_get_type ()); + g_type_class_ref (gst_promise_result_get_type ()); + + _priv_gst_event_initialize (); + _priv_gst_buffer_initialize (); + _priv_gst_buffer_list_initialize (); + _priv_gst_sample_initialize (); + _priv_gst_context_initialize (); + _priv_gst_date_time_initialize (); + _priv_gst_value_initialize (); + _priv_gst_tag_initialize (); + _priv_gst_toc_initialize (); + + g_type_class_ref (gst_param_spec_fraction_get_type ()); + gst_parse_context_get_type (); + + _priv_gst_plugin_initialize (); + + /* register core plugins */ + gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR, + "staticelements", "core elements linked into the GStreamer library", + gst_register_core_elements, VERSION, GST_LICENSE, PACKAGE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); + + /* + * Any errors happening below this point are non-fatal, we therefore mark + * gstreamer as being initialized, since it is the case from a plugin point of + * view. + * + * If anything fails, it will be put back to %FALSE in gst_init_check(). + * This allows some special plugins that would call gst_init() to not cause a + * looping effect (i.e. initializing GStreamer twice). + */ + gst_initialized = TRUE; + + if (!gst_update_registry ()) + return FALSE; + + GST_INFO ("GLib runtime version: %d.%d.%d", glib_major_version, + glib_minor_version, glib_micro_version); + GST_INFO ("GLib headers version: %d.%d.%d", GLIB_MAJOR_VERSION, + GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + GST_INFO ("initialized GStreamer successfully"); + +#ifndef GST_DISABLE_GST_DEBUG + _priv_gst_tracing_init (); +#endif + + return TRUE; +} + +#ifndef GST_DISABLE_OPTION_PARSING +# ifndef GST_DISABLE_GST_DEBUG +static gboolean +select_all (GstPlugin * plugin, gpointer user_data) +{ + return TRUE; +} + +static gint +sort_by_category_name (gconstpointer a, gconstpointer b) +{ + return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a), + gst_debug_category_get_name ((GstDebugCategory *) b)); +} + +static void +gst_debug_help (void) +{ + GSList *list, *walk; + GList *list2, *g; + + /* Need to ensure the registry is loaded to get debug categories */ + if (!init_post (NULL, NULL, NULL, NULL)) + exit (1); + + list2 = gst_registry_plugin_filter (gst_registry_get (), + select_all, FALSE, NULL); + + /* FIXME this is gross. why don't debug have categories PluginFeatures? */ + for (g = list2; g; g = g_list_next (g)) { + GstPlugin *plugin = GST_PLUGIN_CAST (g->data); + GList *features, *orig_features; + + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) + continue; + + gst_plugin_load (plugin); + /* Now create one of each feature so the class_init functions + * are called, as that's where most debug categories are + * registered. FIXME: If debug categories were a plugin feature, + * this would be unneeded */ + orig_features = features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + while (features) { + GstPluginFeature *feature; + + if (G_UNLIKELY (features->data == NULL)) + goto next; + + feature = GST_PLUGIN_FEATURE (features->data); + if (GST_IS_ELEMENT_FACTORY (feature)) { + GstElementFactory *factory; + GstElement *e; + + factory = GST_ELEMENT_FACTORY (feature); + e = gst_element_factory_create (factory, NULL); + if (e) + gst_object_unref (e); + } + + next: + features = g_list_next (features); + } + + gst_plugin_feature_list_free (orig_features); + } + g_list_free (list2); + + list = gst_debug_get_all_categories (); + walk = list = g_slist_sort (list, sort_by_category_name); + + g_print ("\n"); + g_print ("name level description\n"); + g_print ("---------------------+--------+--------------------------------\n"); + + while (walk) { + gboolean on_unix; + GstDebugCategory *cat = (GstDebugCategory *) walk->data; + GstDebugColorMode coloring = gst_debug_get_color_mode (); +#ifdef G_OS_UNIX + on_unix = TRUE; +#else + on_unix = FALSE; +#endif + + if (GST_DEBUG_COLOR_MODE_UNIX == coloring + || (on_unix && GST_DEBUG_COLOR_MODE_ON == coloring)) { + gchar *color = gst_debug_construct_term_color (cat->color); + + g_print ("%s%-20s\033[00m %1d %s %s%s\033[00m\n", + color, + gst_debug_category_get_name (cat), + gst_debug_category_get_threshold (cat), + gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), + color, gst_debug_category_get_description (cat)); + g_free (color); + } else if (GST_DEBUG_COLOR_MODE_ON == coloring && !on_unix) { +#ifdef G_OS_WIN32 + gint color = gst_debug_construct_win_color (cat->color); + const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + + SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color); + g_print ("%-20s", gst_debug_category_get_name (cat)); + SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear); + g_print (" %1d %s ", gst_debug_category_get_threshold (cat), + gst_debug_level_get_name (gst_debug_category_get_threshold (cat))); + SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color); + g_print ("%s", gst_debug_category_get_description (cat)); + SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear); + g_print ("\n"); +#endif /* G_OS_WIN32 */ + } else { + g_print ("%-20s %1d %s %s\n", gst_debug_category_get_name (cat), + gst_debug_category_get_threshold (cat), + gst_debug_level_get_name (gst_debug_category_get_threshold (cat)), + gst_debug_category_get_description (cat)); + } + walk = g_slist_next (walk); + } + g_slist_free (list); + g_print ("\n"); +} +# endif /* GST_DISABLE_OPTION_PARSING */ +#endif /* GST_DISABLE_GST_DEBUG */ + +#ifndef GST_DISABLE_OPTION_PARSING +static gboolean +parse_one_option (gint opt, const gchar * arg, GError ** err) +{ + switch (opt) { + case ARG_VERSION: + g_print ("GStreamer Core Library version %s\n", PACKAGE_VERSION); + exit (0); + case ARG_FATAL_WARNINGS:{ + GLogLevelFlags fatal_mask; + + fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); + fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; + g_log_set_always_fatal (fatal_mask); + break; + } +#ifndef GST_DISABLE_GST_DEBUG + case ARG_DEBUG_LEVEL:{ + GstDebugLevel tmp = GST_LEVEL_NONE; + + tmp = (GstDebugLevel) strtol (arg, NULL, 0); + if (((guint) tmp) < GST_LEVEL_COUNT) { + gst_debug_set_default_threshold (tmp); + } + break; + } + case ARG_DEBUG: + gst_debug_set_threshold_from_string (arg, FALSE); + break; + case ARG_DEBUG_NO_COLOR: + gst_debug_set_colored (FALSE); + break; + case ARG_DEBUG_COLOR_MODE: + gst_debug_set_color_mode_from_string (arg); + break; + case ARG_DEBUG_DISABLE: + gst_debug_set_active (FALSE); + break; + case ARG_DEBUG_HELP: + gst_debug_help (); + exit (0); +#endif + case ARG_PLUGIN_SPEW: + break; + case ARG_PLUGIN_PATH: +#ifndef GST_DISABLE_REGISTRY + if (!_priv_gst_disable_registry) + split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, NULL); +#endif /* GST_DISABLE_REGISTRY */ + break; + case ARG_PLUGIN_LOAD: + split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL); + break; + case ARG_SEGTRAP_DISABLE: + _gst_disable_segtrap = TRUE; + break; + case ARG_REGISTRY_UPDATE_DISABLE: +#ifndef GST_DISABLE_REGISTRY + if (!_priv_gst_disable_registry) + _priv_gst_disable_registry_update = TRUE; +#endif + break; + case ARG_REGISTRY_FORK_DISABLE: + gst_registry_fork_set_enabled (FALSE); + break; + default: + g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION, + _("Unknown option")); + return FALSE; + } + + return TRUE; +} + +static gboolean +parse_goption_arg (const gchar * opt, + const gchar * arg, gpointer data, GError ** err) +{ + static const struct + { + const gchar *opt; + int val; + } options[] = { + { + "--gst-version", ARG_VERSION}, { + "--gst-fatal-warnings", ARG_FATAL_WARNINGS}, +#ifndef GST_DISABLE_GST_DEBUG + { + "--gst-debug-level", ARG_DEBUG_LEVEL}, { + "--gst-debug", ARG_DEBUG}, { + "--gst-debug-disable", ARG_DEBUG_DISABLE}, { + "--gst-debug-no-color", ARG_DEBUG_NO_COLOR}, { + "--gst-debug-color-mode", ARG_DEBUG_COLOR_MODE}, { + "--gst-debug-help", ARG_DEBUG_HELP}, +#endif + { + "--gst-plugin-spew", ARG_PLUGIN_SPEW}, { + "--gst-plugin-path", ARG_PLUGIN_PATH}, { + "--gst-plugin-load", ARG_PLUGIN_LOAD}, { + "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, { + "--gst-disable-registry-update", ARG_REGISTRY_UPDATE_DISABLE}, { + "--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, { + NULL} + }; + gint val = 0, n; + + for (n = 0; options[n].opt; n++) { + if (!strcmp (opt, options[n].opt)) { + val = options[n].val; + break; + } + } + + return parse_one_option (val, arg, err); +} +#endif + +/** + * gst_deinit: + * + * Clean up any resources created by GStreamer in gst_init(). + * + * It is normally not needed to call this function in a normal application + * as the resources will automatically be freed when the program terminates. + * This function is therefore mostly used by testsuites and other memory + * profiling tools. + * + * After this call GStreamer (including this method) should not be used anymore. + */ +void +gst_deinit (void) +{ + GstBinClass *bin_class; + GstClock *clock; + + if (!gst_initialized) + return; + + GST_INFO ("deinitializing GStreamer"); + + if (gst_deinitialized) { + GST_DEBUG ("already deinitialized"); + return; + } + g_thread_pool_set_max_unused_threads (0); + bin_class = (GstBinClass *) g_type_class_peek (gst_bin_get_type ()); + if (bin_class && bin_class->pool != NULL) { + g_thread_pool_free (bin_class->pool, FALSE, TRUE); + bin_class->pool = NULL; + } + gst_task_cleanup_all (); + + g_slist_foreach (_priv_gst_preload_plugins, (GFunc) g_free, NULL); + g_slist_free (_priv_gst_preload_plugins); + _priv_gst_preload_plugins = NULL; + +#ifndef GST_DISABLE_REGISTRY + g_list_foreach (_priv_gst_plugin_paths, (GFunc) g_free, NULL); + g_list_free (_priv_gst_plugin_paths); + _priv_gst_plugin_paths = NULL; +#endif + + if (_gst_executable_path) { + g_free (_gst_executable_path); + _gst_executable_path = NULL; + } + + clock = gst_system_clock_obtain (); + gst_object_unref (clock); + gst_object_unref (clock); + + _priv_gst_registry_cleanup (); + _priv_gst_allocator_cleanup (); + + /* We want to destroy tracers as late as possible for the leaks tracer + * but still need to keep the caps system alive as it may have to use + * gst_caps_to_string() to display leaked caps. */ +#ifndef GST_DISABLE_GST_DEBUG + _priv_gst_tracing_deinit (); +#endif + + _priv_gst_caps_features_cleanup (); + _priv_gst_caps_cleanup (); + + g_type_class_unref (g_type_class_peek (gst_object_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_get_type ())); + g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ())); + g_type_class_unref (g_type_class_peek (gst_element_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tracer_factory_get_type ())); + g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ())); + g_type_class_unref (g_type_class_peek (gst_bin_get_type ())); + g_type_class_unref (g_type_class_peek (gst_bus_get_type ())); + g_type_class_unref (g_type_class_peek (gst_task_get_type ())); + g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_buffer_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ())); + g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_clock_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_clock_return_get_type ())); + g_type_class_unref (g_type_class_peek (gst_clock_entry_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_clock_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_debug_graph_details_get_type ())); + g_type_class_unref (g_type_class_peek (gst_state_get_type ())); + g_type_class_unref (g_type_class_peek (gst_state_change_return_get_type ())); + g_type_class_unref (g_type_class_peek (gst_state_change_get_type ())); + g_type_class_unref (g_type_class_peek (gst_element_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tracer_value_scope_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tracer_value_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_core_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_library_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_plugin_dependency_flags_get_type + ())); + g_type_class_unref (g_type_class_peek (gst_parse_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_resource_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_search_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_stream_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_stream_status_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_structure_change_type_get_type + ())); + g_type_class_unref (g_type_class_peek (gst_event_type_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_event_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_seek_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_qos_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_format_get_type ())); + g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ())); + g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ())); + g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ())); + g_type_class_unref (g_type_class_peek (gst_message_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_meta_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_link_check_get_type ())); + g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_template_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pipeline_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_rank_get_type ())); + g_type_class_unref (g_type_class_peek (gst_query_type_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_query_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tag_flag_get_type ())); + g_type_class_unref (g_type_class_peek (gst_tag_scope_get_type ())); + g_type_class_unref (g_type_class_peek (gst_task_state_get_type ())); + g_type_class_unref (g_type_class_peek (gst_toc_entry_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_toc_scope_get_type ())); + g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type + ())); + g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_uri_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ())); + g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ())); + g_type_class_unref (g_type_class_peek (gst_progress_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_buffer_pool_acquire_flags_get_type + ())); + g_type_class_unref (g_type_class_peek (gst_memory_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_map_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_probe_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_pad_probe_return_get_type ())); + g_type_class_unref (g_type_class_peek (gst_segment_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_scheduling_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_stream_type_get_type ())); + + g_type_class_unref (g_type_class_peek (gst_control_binding_get_type ())); + g_type_class_unref (g_type_class_peek (gst_control_source_get_type ())); + g_type_class_unref (g_type_class_peek (gst_toc_entry_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_toc_loop_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_lock_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_allocator_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_stream_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_debug_color_mode_get_type ())); + g_type_class_unref (g_type_class_peek (gst_stack_trace_flags_get_type ())); + g_type_class_unref (g_type_class_peek (gst_promise_result_get_type ())); + + gst_deinitialized = TRUE; + GST_INFO ("deinitialized GStreamer"); +} + +/** + * gst_version: + * @major: (out): pointer to a guint to store the major version number + * @minor: (out): pointer to a guint to store the minor version number + * @micro: (out): pointer to a guint to store the micro version number + * @nano: (out): pointer to a guint to store the nano version number + * + * Gets the version number of the GStreamer library. + */ +void +gst_version (guint * major, guint * minor, guint * micro, guint * nano) +{ + g_return_if_fail (major); + g_return_if_fail (minor); + g_return_if_fail (micro); + g_return_if_fail (nano); + + *major = GST_VERSION_MAJOR; + *minor = GST_VERSION_MINOR; + *micro = GST_VERSION_MICRO; + *nano = GST_VERSION_NANO; +} + +/** + * gst_version_string: + * + * This function returns a string that is useful for describing this version + * of GStreamer to the outside world: user agent strings, logging, ... + * + * Returns: (transfer full): a newly allocated string describing this version + * of GStreamer. + */ + +gchar * +gst_version_string (void) +{ + guint major, minor, micro, nano; + + gst_version (&major, &minor, µ, &nano); + if (nano == 0) + return g_strdup_printf ("GStreamer %d.%d.%d", major, minor, micro); + else if (nano == 1) + return g_strdup_printf ("GStreamer %d.%d.%d (GIT)", major, minor, micro); + else + return g_strdup_printf ("GStreamer %d.%d.%d (prerelease)", major, minor, + micro); +} + +/** + * gst_segtrap_is_enabled: + * + * Some functions in the GStreamer core might install a custom SIGSEGV handler + * to better catch and report errors to the application. Currently this feature + * is enabled by default when loading plugins. + * + * Applications might want to disable this behaviour with the + * gst_segtrap_set_enabled() function. This is typically done if the application + * wants to install its own handler without GStreamer interfering. + * + * Returns: %TRUE if GStreamer is allowed to install a custom SIGSEGV handler. + */ +gboolean +gst_segtrap_is_enabled (void) +{ + /* yeps, it's enabled when it's not disabled */ + return !_gst_disable_segtrap; +} + +/** + * gst_segtrap_set_enabled: + * @enabled: whether a custom SIGSEGV handler should be installed. + * + * Applications might want to disable/enable the SIGSEGV handling of + * the GStreamer core. See gst_segtrap_is_enabled() for more information. + */ +void +gst_segtrap_set_enabled (gboolean enabled) +{ + _gst_disable_segtrap = !enabled; +} diff --git a/gst/gst.h b/gst/gst.h new file mode 100644 index 0000000..a1f2297 --- /dev/null +++ b/gst/gst.h @@ -0,0 +1,141 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gst.h: Main header for GStreamer, apps should include this + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_H__ +#define __GST_H__ + +#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 + +/* API compatibility stuff */ +#include + +G_BEGIN_DECLS + +GST_API +void gst_init (int *argc, char **argv[]); + +GST_API +gboolean gst_init_check (int *argc, char **argv[], + GError ** err); +GST_API +gboolean gst_is_initialized (void); + +GST_API +GOptionGroup * gst_init_get_option_group (void); + +GST_API +void gst_deinit (void); + +GST_API +void gst_version (guint *major, guint *minor, + guint *micro, guint *nano); +GST_API +gchar * gst_version_string (void); + +GST_API +gboolean gst_segtrap_is_enabled (void); + +GST_API +void gst_segtrap_set_enabled (gboolean enabled); + +GST_API +gboolean gst_registry_fork_is_enabled (void); + +GST_API +void gst_registry_fork_set_enabled (gboolean enabled); + +GST_API +gboolean gst_update_registry (void); + +GST_API +const gchar * gst_get_main_executable_path (void); + +G_END_DECLS + +#endif /* __GST_H__ */ diff --git a/gst/gst_private.h b/gst/gst_private.h new file mode 100644 index 0000000..2a2e8fa --- /dev/null +++ b/gst/gst_private.h @@ -0,0 +1,508 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gst_private.h: Private header for within libgst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PRIVATE_H__ +#define __GST_PRIVATE_H__ + +#ifdef HAVE_CONFIG_H +# ifndef GST_LICENSE /* don't include config.h twice, it has no guards */ +# include "config.h" +# endif +#endif + +/* This needs to be before glib.h, since it might be used in inline + * functions */ +extern const char g_log_domain_gstreamer[]; + +#include + +#include +#include + +/* Needed for GST_API */ +#include "gst/gstconfig.h" + +/* Needed for GstRegistry * */ +#include "gstregistry.h" +#include "gststructure.h" + +/* we need this in pretty much all files */ +#include "gstinfo.h" + +/* for the flags in the GstPluginDep structure below */ +#include "gstplugin.h" + +/* for the pad cache */ +#include "gstpad.h" + +/* for GstElement */ +#include "gstelement.h" + +/* for GstDeviceProvider */ +#include "gstdeviceprovider.h" + +/* for GstToc */ +#include "gsttoc.h" + +#include "gstdatetime.h" + +#include "gsttracerutils.h" + +G_BEGIN_DECLS + +/* used by gstparse.c and grammar.y */ +struct _GstParseContext { + GList * missing_elements; +}; + +/* used by gstplugin.c and gstregistrybinary.c */ +typedef struct { + /* details registered via gst_plugin_add_dependency() */ + GstPluginDependencyFlags flags; + gchar **env_vars; + gchar **paths; + gchar **names; + + /* information saved from the last time the plugin was loaded (-1 = unset) */ + guint env_hash; /* hash of content of environment variables in env_vars */ + guint stat_hash; /* hash of stat() on all relevant files and directories */ +} GstPluginDep; + +struct _GstPluginPrivate { + GList *deps; /* list of GstPluginDep structures */ + GstStructure *cache_data; +}; + +/* FIXME: could rename all priv_gst_* functions to __gst_* now */ +G_GNUC_INTERNAL gboolean priv_gst_plugin_loading_have_whitelist (void); + +G_GNUC_INTERNAL guint32 priv_gst_plugin_loading_get_whitelist_hash (void); + +G_GNUC_INTERNAL gboolean priv_gst_plugin_desc_is_whitelisted (const GstPluginDesc * desc, + const gchar * filename); + +G_GNUC_INTERNAL gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin); + +G_GNUC_INTERNAL gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin); + +G_GNUC_INTERNAL gboolean _priv_gst_in_valgrind (void); + +/* init functions called from gst_init(). */ +G_GNUC_INTERNAL void _priv_gst_quarks_initialize (void); +G_GNUC_INTERNAL void _priv_gst_mini_object_initialize (void); +G_GNUC_INTERNAL void _priv_gst_memory_initialize (void); +G_GNUC_INTERNAL void _priv_gst_allocator_initialize (void); +G_GNUC_INTERNAL void _priv_gst_buffer_initialize (void); +G_GNUC_INTERNAL void _priv_gst_buffer_list_initialize (void); +G_GNUC_INTERNAL void _priv_gst_structure_initialize (void); +G_GNUC_INTERNAL void _priv_gst_caps_initialize (void); +G_GNUC_INTERNAL void _priv_gst_caps_features_initialize (void); +G_GNUC_INTERNAL void _priv_gst_event_initialize (void); +G_GNUC_INTERNAL void _priv_gst_format_initialize (void); +G_GNUC_INTERNAL void _priv_gst_message_initialize (void); +G_GNUC_INTERNAL void _priv_gst_meta_initialize (void); +G_GNUC_INTERNAL void _priv_gst_plugin_initialize (void); +G_GNUC_INTERNAL void _priv_gst_query_initialize (void); +G_GNUC_INTERNAL void _priv_gst_sample_initialize (void); +G_GNUC_INTERNAL void _priv_gst_tag_initialize (void); +G_GNUC_INTERNAL void _priv_gst_value_initialize (void); +G_GNUC_INTERNAL void _priv_gst_debug_init (void); +G_GNUC_INTERNAL void _priv_gst_context_initialize (void); +G_GNUC_INTERNAL void _priv_gst_toc_initialize (void); +G_GNUC_INTERNAL void _priv_gst_date_time_initialize (void); + +/* cleanup functions called from gst_deinit(). */ +G_GNUC_INTERNAL void _priv_gst_allocator_cleanup (void); +G_GNUC_INTERNAL void _priv_gst_caps_features_cleanup (void); +G_GNUC_INTERNAL void _priv_gst_caps_cleanup (void); + +/* called from gst_task_cleanup_all(). */ +G_GNUC_INTERNAL void _priv_gst_element_cleanup (void); + +/* Private registry functions */ +G_GNUC_INTERNAL +gboolean _priv_gst_registry_remove_cache_plugins (GstRegistry *registry); + +G_GNUC_INTERNAL void _priv_gst_registry_cleanup (void); + +GST_API +gboolean _gst_plugin_loader_client_run (void); + +G_GNUC_INTERNAL GstPlugin * _priv_gst_plugin_load_file_for_registry (const gchar *filename, + GstRegistry * registry, + GError** error); + +/* GValue serialization/deserialization */ + +G_GNUC_INTERNAL const char * _priv_gst_value_gtype_to_abbr (GType type); + +G_GNUC_INTERNAL gboolean _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next, gboolean unescape); +G_GNUC_INTERNAL gboolean _priv_gst_value_parse_simple_string (gchar * str, gchar ** end); +G_GNUC_INTERNAL gboolean _priv_gst_value_parse_value (gchar * str, gchar ** after, GValue * value, GType default_type); +G_GNUC_INTERNAL gchar * _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin, const gchar * end, gboolean print_type); + +/* Used in GstBin for manual state handling */ +G_GNUC_INTERNAL void _priv_gst_element_state_changed (GstElement *element, + GstState oldstate, GstState newstate, GstState pending); + +/* used in both gststructure.c and gstcaps.c; numbers are completely made up */ +#define STRUCTURE_ESTIMATED_STRING_LEN(s) (16 + gst_structure_n_fields(s) * 22) +#define FEATURES_ESTIMATED_STRING_LEN(s) (16 + gst_caps_features_get_size(s) * 14) + +G_GNUC_INTERNAL +gboolean priv_gst_structure_append_to_gstring (const GstStructure * structure, + GString * s); +G_GNUC_INTERNAL +gboolean priv__gst_structure_append_template_to_gstring (GQuark field_id, + const GValue *value, + gpointer user_data); + +G_GNUC_INTERNAL +void priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features, GString *s); + +G_GNUC_INTERNAL +gboolean priv_gst_structure_parse_name (gchar * str, gchar **start, gchar ** end, gchar ** next); +G_GNUC_INTERNAL +gboolean priv_gst_structure_parse_fields (gchar *str, gchar ** end, GstStructure *structure); + +/* used in gstvalue.c and gststructure.c */ + +#define GST_WRAPPED_PTR_FORMAT "p\aa" + +G_GNUC_INTERNAL +gchar *priv_gst_string_take_and_wrap (gchar * s); + +/* registry cache backends */ +G_GNUC_INTERNAL +gboolean priv_gst_registry_binary_read_cache (GstRegistry * registry, const char *location); + +G_GNUC_INTERNAL +gboolean priv_gst_registry_binary_write_cache (GstRegistry * registry, GList * plugins, const char *location); + + +G_GNUC_INTERNAL +void __gst_element_factory_add_static_pad_template (GstElementFactory * elementfactory, + GstStaticPadTemplate * templ); + +G_GNUC_INTERNAL +void __gst_element_factory_add_interface (GstElementFactory * elementfactory, + const gchar * interfacename); + +/* used in gstvalue.c and gststructure.c */ +#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \ + ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \ + ((c) == '.')) + +/* This is only meant for internal uses */ +G_GNUC_INTERNAL +gint __gst_date_time_compare (const GstDateTime * dt1, const GstDateTime * dt2); + +G_GNUC_INTERNAL +gchar * __gst_date_time_serialize (GstDateTime * datetime, gboolean with_usecs); + +/* For use in gstdebugutils */ +G_GNUC_INTERNAL +GstCapsFeatures * __gst_caps_get_features_unchecked (const GstCaps * caps, guint idx); + +#ifndef GST_DISABLE_REGISTRY +/* Secret variable to initialise gst without registry cache */ + +GST_API gboolean _gst_disable_registry_cache; +#endif + +/* Secret variable to let the plugin scanner use the same base path + * as the main application in order to determine dependencies */ +GST_API gchar *_gst_executable_path; + +/* provide inline gst_g_value_get_foo_unchecked(), used in gststructure.c */ +#define DEFINE_INLINE_G_VALUE_GET_UNCHECKED(ret_type,name_type,v_field) \ +static inline ret_type \ +gst_g_value_get_##name_type##_unchecked (const GValue *value) \ +{ \ + return value->data[0].v_field; \ +} + +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(gboolean,boolean,v_int) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(gint,int,v_int) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(guint,uint,v_uint) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(gint64,int64,v_int64) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(guint64,uint64,v_uint64) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(gfloat,float,v_float) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(gdouble,double,v_double) +DEFINE_INLINE_G_VALUE_GET_UNCHECKED(const gchar *,string,v_pointer) + + +/*** debugging categories *****************************************************/ + +#ifndef GST_REMOVE_GST_DEBUG + +GST_API GstDebugCategory *GST_CAT_GST_INIT; +GST_API GstDebugCategory *GST_CAT_MEMORY; +GST_API GstDebugCategory *GST_CAT_PARENTAGE; +GST_API GstDebugCategory *GST_CAT_STATES; +GST_API GstDebugCategory *GST_CAT_SCHEDULING; +GST_API GstDebugCategory *GST_CAT_BUFFER; +GST_API GstDebugCategory *GST_CAT_BUFFER_LIST; +GST_API GstDebugCategory *GST_CAT_BUS; +GST_API GstDebugCategory *GST_CAT_CAPS; +GST_API GstDebugCategory *GST_CAT_CLOCK; +GST_API GstDebugCategory *GST_CAT_ELEMENT_PADS; +GST_API GstDebugCategory *GST_CAT_PADS; +GST_API GstDebugCategory *GST_CAT_PERFORMANCE; +GST_API GstDebugCategory *GST_CAT_PIPELINE; +GST_API GstDebugCategory *GST_CAT_PLUGIN_LOADING; +GST_API GstDebugCategory *GST_CAT_PLUGIN_INFO; +GST_API GstDebugCategory *GST_CAT_PROPERTIES; +GST_API GstDebugCategory *GST_CAT_NEGOTIATION; +GST_API GstDebugCategory *GST_CAT_REFCOUNTING; +GST_API GstDebugCategory *GST_CAT_ERROR_SYSTEM; +GST_API GstDebugCategory *GST_CAT_EVENT; +GST_API GstDebugCategory *GST_CAT_MESSAGE; +GST_API GstDebugCategory *GST_CAT_PARAMS; +GST_API GstDebugCategory *GST_CAT_CALL_TRACE; +GST_API GstDebugCategory *GST_CAT_SIGNAL; +GST_API GstDebugCategory *GST_CAT_PROBE; +GST_API GstDebugCategory *GST_CAT_REGISTRY; +GST_API GstDebugCategory *GST_CAT_QOS; +GST_API GstDebugCategory *GST_CAT_META; +GST_API GstDebugCategory *GST_CAT_LOCKING; +GST_API GstDebugCategory *GST_CAT_CONTEXT; + +/* Categories that should be completely private to + * libgstreamer should be done like this: */ +#define GST_CAT_POLL _priv_GST_CAT_POLL +extern GstDebugCategory *_priv_GST_CAT_POLL; + +#define GST_CAT_PROTECTION _priv_GST_CAT_PROTECTION +extern GstDebugCategory *_priv_GST_CAT_PROTECTION; + +extern GstClockTime _priv_gst_start_time; + +#else + +#define GST_CAT_GST_INIT NULL +#define GST_CAT_AUTOPLUG NULL +#define GST_CAT_AUTOPLUG_ATTEMPT NULL +#define GST_CAT_PARENTAGE NULL +#define GST_CAT_STATES NULL +#define GST_CAT_SCHEDULING NULL +#define GST_CAT_DATAFLOW NULL +#define GST_CAT_BUFFER NULL +#define GST_CAT_BUFFER_LIST NULL +#define GST_CAT_BUS NULL +#define GST_CAT_CAPS NULL +#define GST_CAT_CLOCK NULL +#define GST_CAT_ELEMENT_PADS NULL +#define GST_CAT_PADS NULL +#define GST_CAT_PERFORMANCE NULL +#define GST_CAT_PIPELINE NULL +#define GST_CAT_PLUGIN_LOADING NULL +#define GST_CAT_PLUGIN_INFO NULL +#define GST_CAT_PROPERTIES NULL +#define GST_CAT_NEGOTIATION NULL +#define GST_CAT_REFCOUNTING NULL +#define GST_CAT_ERROR_SYSTEM NULL +#define GST_CAT_EVENT NULL +#define GST_CAT_MESSAGE NULL +#define GST_CAT_PARAMS NULL +#define GST_CAT_CALL_TRACE NULL +#define GST_CAT_SIGNAL NULL +#define GST_CAT_PROBE NULL +#define GST_CAT_REGISTRY NULL +#define GST_CAT_QOS NULL +#define GST_CAT_TYPES NULL +#define GST_CAT_POLL NULL +#define GST_CAT_META NULL +#define GST_CAT_LOCKING NULL +#define GST_CAT_CONTEXT NULL +#define GST_CAT_PROTECTION NULL + +#endif + +#ifdef GST_DISABLE_GST_DEBUG +/* for _gst_element_error_printf */ +#define __gst_vasprintf __gst_info_fallback_vasprintf +int __gst_vasprintf (char **result, char const *format, va_list args); +#endif + +/**** objects made opaque until the private bits have been made private ****/ + +#include +#include /* time_t */ +#include /* off_t */ +#include /* off_t */ + +typedef struct _GstPluginPrivate GstPluginPrivate; + +struct _GstPlugin { + GstObject object; + + /*< private >*/ + GstPluginDesc desc; + + gchar * filename; + gchar * basename; /* base name (non-dir part) of plugin path */ + + GModule * module; /* contains the module if plugin is loaded */ + + off_t file_size; + time_t file_mtime; + gboolean registered; /* TRUE when the registry has seen a filename + * that matches the plugin's basename */ + + GstPluginPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstPluginClass { + GstObjectClass object_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstPluginFeature { + GstObject object; + + /*< private >*/ + gboolean loaded; + guint rank; + + const gchar *plugin_name; + GstPlugin *plugin; /* weak ref */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstPluginFeatureClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +#include "gsttypefind.h" + +struct _GstTypeFindFactory { + GstPluginFeature feature; + /* */ + + GstTypeFindFunction function; + gchar ** extensions; + GstCaps * caps; + + gpointer user_data; + GDestroyNotify user_data_notify; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTypeFindFactoryClass { + GstPluginFeatureClass parent; + /* */ + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTracerFactory { + GstPluginFeature feature; + /* */ + + GType type; + + /* + gpointer user_data; + GDestroyNotify user_data_notify; + */ + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTracerFactoryClass { + GstPluginFeatureClass parent; + /* */ + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstElementFactory { + GstPluginFeature parent; + + GType type; /* unique GType of element or 0 if not loaded */ + + gpointer metadata; + + GList * staticpadtemplates; /* GstStaticPadTemplate list */ + guint numpadtemplates; + + /* URI interface stuff */ + GstURIType uri_type; + gchar ** uri_protocols; + + GList * interfaces; /* interface type names this element implements */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstElementFactoryClass { + GstPluginFeatureClass parent_class; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstDeviceProviderFactory { + GstPluginFeature feature; + /* */ + + GType type; /* unique GType the device factory or 0 if not loaded */ + + volatile GstDeviceProvider *provider; + gpointer metadata; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstDeviceProviderFactoryClass { + GstPluginFeatureClass parent; + /* */ + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstDynamicTypeFactory { + GstPluginFeature feature; + + GType type; /* GType of the type, when loaded. 0 if not */ +}; + +struct _GstDynamicTypeFactoryClass { + GstPluginFeatureClass parent; +}; + +/* privat flag used by GstBus / GstMessage */ +#define GST_MESSAGE_FLAG_ASYNC_DELIVERY (GST_MINI_OBJECT_FLAG_LAST << 0) + +G_END_DECLS +#endif /* __GST_PRIVATE_H__ */ diff --git a/gst/gstallocator.c b/gst/gstallocator.c new file mode 100644 index 0000000..4b78a33 --- /dev/null +++ b/gst/gstallocator.c @@ -0,0 +1,651 @@ +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstallocator.c: memory block allocator + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstallocator + * @title: GstAllocator + * @short_description: allocate memory blocks + * @see_also: #GstMemory + * + * Memory is usually created by allocators with a gst_allocator_alloc() + * method call. When %NULL is used as the allocator, the default allocator will + * be used. + * + * New allocators can be registered with gst_allocator_register(). + * Allocators are identified by name and can be retrieved with + * gst_allocator_find(). gst_allocator_set_default() can be used to change the + * default allocator. + * + * New memory can be created with gst_memory_new_wrapped() that wraps the memory + * allocated elsewhere. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "gstmemory.h" + +GST_DEBUG_CATEGORY_STATIC (gst_allocator_debug); +#define GST_CAT_DEFAULT gst_allocator_debug + +#define GST_ALLOCATOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_ALLOCATOR, GstAllocatorPrivate)) + +struct _GstAllocatorPrivate +{ + gpointer dummy; +}; + +#if defined(MEMORY_ALIGNMENT_MALLOC) +gsize gst_memory_alignment = 7; +#elif defined(MEMORY_ALIGNMENT_PAGESIZE) +/* we fill this in in the _init method */ +gsize gst_memory_alignment = 0; +#elif defined(MEMORY_ALIGNMENT) +gsize gst_memory_alignment = MEMORY_ALIGNMENT - 1; +#else +#error "No memory alignment configured" +gsize gst_memory_alignment = 0; +#endif + +/* the default allocator */ +static GstAllocator *_default_allocator; + +static GstAllocator *_sysmem_allocator; + +/* registered allocators */ +static GRWLock lock; +static GHashTable *allocators; + +G_DEFINE_ABSTRACT_TYPE (GstAllocator, gst_allocator, GST_TYPE_OBJECT); + +static void +gst_allocator_class_init (GstAllocatorClass * klass) +{ + g_type_class_add_private (klass, sizeof (GstAllocatorPrivate)); + + GST_DEBUG_CATEGORY_INIT (gst_allocator_debug, "allocator", 0, + "allocator debug"); +} + +static GstMemory * +_fallback_mem_copy (GstMemory * mem, gssize offset, gssize size) +{ + GstMemory *copy; + GstMapInfo sinfo, dinfo; + GstAllocationParams params = { 0, mem->align, 0, 0, }; + GstAllocator *allocator; + + if (!gst_memory_map (mem, &sinfo, GST_MAP_READ)) + return NULL; + + if (size == -1) + size = sinfo.size > offset ? sinfo.size - offset : 0; + + /* use the same allocator as the memory we copy */ + allocator = mem->allocator; + if (GST_OBJECT_FLAG_IS_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC)) + allocator = NULL; + copy = gst_allocator_alloc (allocator, size, ¶ms); + + if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) { + GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy); + gst_allocator_free (mem->allocator, copy); + gst_memory_unmap (mem, &sinfo); + return NULL; + } + + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, + "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy); + memcpy (dinfo.data, sinfo.data + offset, size); + gst_memory_unmap (copy, &dinfo); + gst_memory_unmap (mem, &sinfo); + + return copy; +} + +static gboolean +_fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) +{ + return FALSE; +} + +static void +gst_allocator_init (GstAllocator * allocator) +{ + allocator->priv = GST_ALLOCATOR_GET_PRIVATE (allocator); + + allocator->mem_copy = _fallback_mem_copy; + allocator->mem_is_span = _fallback_mem_is_span; +} + +G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params, + (GBoxedCopyFunc) gst_allocation_params_copy, + (GBoxedFreeFunc) gst_allocation_params_free); + +/** + * gst_allocation_params_init: + * @params: a #GstAllocationParams + * + * Initialize @params to its default values + */ +void +gst_allocation_params_init (GstAllocationParams * params) +{ + g_return_if_fail (params != NULL); + + memset (params, 0, sizeof (GstAllocationParams)); +} + +/** + * gst_allocation_params_copy: + * @params: (transfer none) (nullable): a #GstAllocationParams + * + * Create a copy of @params. + * + * Free-function: gst_allocation_params_free + * + * Returns: (transfer full) (nullable): a new ##GstAllocationParams, free with + * gst_allocation_params_free(). + */ +GstAllocationParams * +gst_allocation_params_copy (const GstAllocationParams * params) +{ + GstAllocationParams *result = NULL; + + if (params) { + result = + (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams), + params); + } + return result; +} + +/** + * gst_allocation_params_free: + * @params: (in) (transfer full): a #GstAllocationParams + * + * Free @params + */ +void +gst_allocation_params_free (GstAllocationParams * params) +{ + g_slice_free (GstAllocationParams, params); +} + +/** + * gst_allocator_register: + * @name: the name of the allocator + * @allocator: (transfer full): #GstAllocator + * + * Registers the memory @allocator with @name. This function takes ownership of + * @allocator. + */ +void +gst_allocator_register (const gchar * name, GstAllocator * allocator) +{ + g_return_if_fail (name != NULL); + g_return_if_fail (allocator != NULL); + + GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"", + allocator, name); + + g_rw_lock_writer_lock (&lock); + /* The ref will never be released */ + GST_OBJECT_FLAG_SET (allocator, GST_OBJECT_FLAG_MAY_BE_LEAKED); + g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator); + g_rw_lock_writer_unlock (&lock); +} + +/** + * gst_allocator_find: + * @name: (allow-none): the name of the allocator + * + * Find a previously registered allocator with @name. When @name is %NULL, the + * default allocator will be returned. + * + * Returns: (transfer full) (nullable): a #GstAllocator or %NULL when + * the allocator with @name was not registered. Use gst_object_unref() + * to release the allocator after usage. + */ +GstAllocator * +gst_allocator_find (const gchar * name) +{ + GstAllocator *allocator; + + g_rw_lock_reader_lock (&lock); + if (name) { + allocator = g_hash_table_lookup (allocators, (gconstpointer) name); + } else { + allocator = _default_allocator; + } + if (allocator) + gst_object_ref (allocator); + g_rw_lock_reader_unlock (&lock); + + return allocator; +} + +/** + * gst_allocator_set_default: + * @allocator: (transfer full): a #GstAllocator + * + * Set the default allocator. This function takes ownership of @allocator. + */ +void +gst_allocator_set_default (GstAllocator * allocator) +{ + GstAllocator *old; + + g_return_if_fail (GST_IS_ALLOCATOR (allocator)); + + g_rw_lock_writer_lock (&lock); + old = _default_allocator; + _default_allocator = allocator; + g_rw_lock_writer_unlock (&lock); + + if (old) + gst_object_unref (old); +} + +/** + * gst_allocator_alloc: + * @allocator: (transfer none) (allow-none): a #GstAllocator to use + * @size: size of the visible memory area + * @params: (transfer none) (allow-none): optional parameters + * + * Use @allocator to allocate a new memory block with memory that is at least + * @size big. + * + * The optional @params can specify the prefix and padding for the memory. If + * %NULL is passed, no flags, no extra prefix/padding and a default alignment is + * used. + * + * The prefix/padding will be filled with 0 if flags contains + * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively. + * + * When @allocator is %NULL, the default allocator will be used. + * + * The alignment in @params is given as a bitmask so that @align + 1 equals + * the amount of bytes to align to. For example, to align to 8 bytes, + * use an alignment of 7. + * + * Returns: (transfer full) (nullable): a new #GstMemory. + */ +GstMemory * +gst_allocator_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + GstMemory *mem; + static GstAllocationParams defparams = { 0, 0, 0, 0, }; + GstAllocatorClass *aclass; + + if (params) { + g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL); + } else { + params = &defparams; + } + + if (allocator == NULL) + allocator = _default_allocator; + + aclass = GST_ALLOCATOR_GET_CLASS (allocator); + if (aclass->alloc) + mem = aclass->alloc (allocator, size, params); + else + mem = NULL; + + return mem; +} + +/** + * gst_allocator_free: + * @allocator: (transfer none): a #GstAllocator to use + * @memory: (transfer full): the memory to free + * + * Free @memory that was previously allocated with gst_allocator_alloc(). + */ +void +gst_allocator_free (GstAllocator * allocator, GstMemory * memory) +{ + GstAllocatorClass *aclass; + + g_return_if_fail (GST_IS_ALLOCATOR (allocator)); + g_return_if_fail (memory != NULL); + g_return_if_fail (memory->allocator == allocator); + + aclass = GST_ALLOCATOR_GET_CLASS (allocator); + if (aclass->free) + aclass->free (allocator, memory); +} + +/* default memory implementation */ +typedef struct +{ + GstMemory mem; + + gsize slice_size; + guint8 *data; + + gpointer user_data; + GDestroyNotify notify; +} GstMemorySystem; + +typedef struct +{ + GstAllocator parent; +} GstAllocatorSysmem; + +typedef struct +{ + GstAllocatorClass parent_class; +} GstAllocatorSysmemClass; + +static GType gst_allocator_sysmem_get_type (void); +G_DEFINE_TYPE (GstAllocatorSysmem, gst_allocator_sysmem, GST_TYPE_ALLOCATOR); + +/* initialize the fields */ +static inline void +_sysmem_init (GstMemorySystem * mem, GstMemoryFlags flags, + GstMemory * parent, gsize slice_size, + gpointer data, gsize maxsize, gsize align, gsize offset, gsize size, + gpointer user_data, GDestroyNotify notify) +{ + gst_memory_init (GST_MEMORY_CAST (mem), + flags, _sysmem_allocator, parent, maxsize, align, offset, size); + + mem->slice_size = slice_size; + mem->data = data; + mem->user_data = user_data; + mem->notify = notify; +} + +/* create a new memory block that manages the given memory */ +static inline GstMemorySystem * +_sysmem_new (GstMemoryFlags flags, + GstMemory * parent, gpointer data, gsize maxsize, gsize align, gsize offset, + gsize size, gpointer user_data, GDestroyNotify notify) +{ + GstMemorySystem *mem; + gsize slice_size; + + slice_size = sizeof (GstMemorySystem); + + mem = g_slice_alloc (slice_size); + _sysmem_init (mem, flags, parent, slice_size, + data, maxsize, align, offset, size, user_data, notify); + + return mem; +} + +/* allocate the memory and structure in one block */ +static GstMemorySystem * +_sysmem_new_block (GstMemoryFlags flags, + gsize maxsize, gsize align, gsize offset, gsize size) +{ + GstMemorySystem *mem; + gsize aoffset, slice_size, padding; + guint8 *data; + + /* ensure configured alignment */ + align |= gst_memory_alignment; + /* allocate more to compensate for alignment */ + maxsize += align; + /* alloc header and data in one block */ + slice_size = sizeof (GstMemorySystem) + maxsize; + + mem = g_slice_alloc (slice_size); + if (mem == NULL) + return NULL; + + data = (guint8 *) mem + sizeof (GstMemorySystem); + + /* do alignment */ + if ((aoffset = ((guintptr) data & align))) { + aoffset = (align + 1) - aoffset; + data += aoffset; + maxsize -= aoffset; + } + + if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED)) + memset (data, 0, offset); + + padding = maxsize - (offset + size); + if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED)) + memset (data + offset + size, 0, padding); + + _sysmem_init (mem, flags, NULL, slice_size, data, maxsize, + align, offset, size, NULL, NULL); + + return mem; +} + +static gpointer +_sysmem_map (GstMemorySystem * mem, gsize maxsize, GstMapFlags flags) +{ + return mem->data; +} + +static gboolean +_sysmem_unmap (GstMemorySystem * mem) +{ + return TRUE; +} + +static GstMemorySystem * +_sysmem_copy (GstMemorySystem * mem, gssize offset, gsize size) +{ + GstMemorySystem *copy; + + if (size == -1) + size = mem->mem.size > offset ? mem->mem.size - offset : 0; + + copy = _sysmem_new_block (0, size, mem->mem.align, 0, size); + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, + "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", size, mem, copy); + memcpy (copy->data, mem->data + mem->mem.offset + offset, size); + + return copy; +} + +static GstMemorySystem * +_sysmem_share (GstMemorySystem * mem, gssize offset, gsize size) +{ + GstMemorySystem *sub; + GstMemory *parent; + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + if (size == -1) + size = mem->mem.size - offset; + + /* the shared memory is always readonly */ + sub = + _sysmem_new (GST_MINI_OBJECT_FLAGS (parent) | + GST_MINI_OBJECT_FLAG_LOCK_READONLY, parent, mem->data, mem->mem.maxsize, + mem->mem.align, mem->mem.offset + offset, size, NULL, NULL); + + return sub; +} + +static gboolean +_sysmem_is_span (GstMemorySystem * mem1, GstMemorySystem * mem2, gsize * offset) +{ + + if (offset) { + GstMemorySystem *parent; + + parent = (GstMemorySystem *) mem1->mem.parent; + + *offset = mem1->mem.offset - parent->mem.offset; + } + + /* and memory is contiguous */ + return mem1->data + mem1->mem.offset + mem1->mem.size == + mem2->data + mem2->mem.offset; +} + +static GstMemory * +default_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + gsize maxsize = size + params->prefix + params->padding; + + return (GstMemory *) _sysmem_new_block (params->flags, + maxsize, params->align, params->prefix, size); +} + +static void +default_free (GstAllocator * allocator, GstMemory * mem) +{ + GstMemorySystem *dmem = (GstMemorySystem *) mem; + gsize slice_size; + + if (dmem->notify) + dmem->notify (dmem->user_data); + + slice_size = dmem->slice_size; + +#ifdef USE_POISONING + /* just poison the structs, not all the data */ + memset (mem, 0xff, sizeof (GstMemorySystem)); +#endif + + g_slice_free1 (slice_size, mem); +} + +static void +gst_allocator_sysmem_finalize (GObject * obj) +{ + /* Don't raise warnings if we are shutting down */ + if (_default_allocator) + g_warning ("The default memory allocator was freed!"); + + ((GObjectClass *) gst_allocator_sysmem_parent_class)->finalize (obj); +} + +static void +gst_allocator_sysmem_class_init (GstAllocatorSysmemClass * klass) +{ + GObjectClass *gobject_class; + GstAllocatorClass *allocator_class; + + gobject_class = (GObjectClass *) klass; + allocator_class = (GstAllocatorClass *) klass; + + gobject_class->finalize = gst_allocator_sysmem_finalize; + + allocator_class->alloc = default_alloc; + allocator_class->free = default_free; +} + +static void +gst_allocator_sysmem_init (GstAllocatorSysmem * allocator) +{ + GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + + GST_CAT_DEBUG (GST_CAT_MEMORY, "init allocator %p", allocator); + + alloc->mem_type = GST_ALLOCATOR_SYSMEM; + alloc->mem_map = (GstMemoryMapFunction) _sysmem_map; + alloc->mem_unmap = (GstMemoryUnmapFunction) _sysmem_unmap; + alloc->mem_copy = (GstMemoryCopyFunction) _sysmem_copy; + alloc->mem_share = (GstMemoryShareFunction) _sysmem_share; + alloc->mem_is_span = (GstMemoryIsSpanFunction) _sysmem_is_span; +} + +void +_priv_gst_allocator_initialize (void) +{ + g_rw_lock_init (&lock); + allocators = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + gst_object_unref); + +#ifdef HAVE_GETPAGESIZE +#ifdef MEMORY_ALIGNMENT_PAGESIZE + gst_memory_alignment = getpagesize () - 1; +#endif +#endif + + GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT, + gst_memory_alignment); + + _sysmem_allocator = g_object_new (gst_allocator_sysmem_get_type (), NULL); + + /* Clear floating flag */ + gst_object_ref_sink (_sysmem_allocator); + + gst_allocator_register (GST_ALLOCATOR_SYSMEM, + gst_object_ref (_sysmem_allocator)); + + _default_allocator = gst_object_ref (_sysmem_allocator); +} + +void +_priv_gst_allocator_cleanup (void) +{ + gst_object_unref (_sysmem_allocator); + _sysmem_allocator = NULL; + + gst_object_unref (_default_allocator); + _default_allocator = NULL; + + g_clear_pointer (&allocators, g_hash_table_unref); +} + +/** + * gst_memory_new_wrapped: + * @flags: #GstMemoryFlags + * @data: (array length=size) (element-type guint8) (transfer none): data to + * wrap + * @maxsize: allocated size of @data + * @offset: offset in @data + * @size: size of valid data + * @user_data: (allow-none): user_data + * @notify: (allow-none) (scope async) (closure user_data): called with @user_data when the memory is freed + * + * Allocate a new memory block that wraps the given @data. + * + * The prefix/padding must be filled with 0 if @flags contains + * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively. + * + * Returns: (transfer full) (nullable): a new #GstMemory. + */ +GstMemory * +gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, + gsize maxsize, gsize offset, gsize size, gpointer user_data, + GDestroyNotify notify) +{ + GstMemorySystem *mem; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (offset + size <= maxsize, NULL); + + mem = + _sysmem_new (flags, NULL, data, maxsize, 0, offset, size, user_data, + notify); + + return (GstMemory *) mem; +} diff --git a/gst/gstallocator.h b/gst/gstallocator.h new file mode 100644 index 0000000..29c1a0f --- /dev/null +++ b/gst/gstallocator.h @@ -0,0 +1,200 @@ +/* GStreamer + * Copyright (C) 2009 Wim Taymans + * + * gstallocator.h: Header for memory allocation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_ALLOCATOR_H__ +#define __GST_ALLOCATOR_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstAllocatorPrivate GstAllocatorPrivate; +typedef struct _GstAllocatorClass GstAllocatorClass; + +#define GST_TYPE_ALLOCATOR (gst_allocator_get_type()) +#define GST_IS_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_ALLOCATOR)) +#define GST_IS_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_ALLOCATOR)) +#define GST_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ALLOCATOR, GstAllocatorClass)) +#define GST_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ALLOCATOR, GstAllocator)) +#define GST_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_ALLOCATOR, GstAllocatorClass)) +#define GST_ALLOCATOR_CAST(obj) ((GstAllocator *)(obj)) + +#define GST_TYPE_ALLOCATION_PARAMS (gst_allocation_params_get_type()) + +GST_API +GType gst_allocation_params_get_type(void); + +typedef struct _GstAllocationParams GstAllocationParams; + +/** + * gst_memory_alignment: + * + * The default memory alignment in bytes - 1 + * an alignment of 7 would be the same as what malloc() guarantees. + */ + +GST_API gsize gst_memory_alignment; + +/** + * GST_ALLOCATOR_SYSMEM: + * + * The allocator name for the default system memory allocator + */ +#define GST_ALLOCATOR_SYSMEM "SystemMemory" + +/** + * GstAllocationParams: + * @flags: flags to control allocation + * @align: the desired alignment of the memory + * @prefix: the desired prefix + * @padding: the desired padding + * + * Parameters to control the allocation of memory + */ +struct _GstAllocationParams { + GstMemoryFlags flags; + gsize align; + gsize prefix; + gsize padding; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstAllocatorFlags: + * @GST_ALLOCATOR_FLAG_CUSTOM_ALLOC: The allocator has a custom alloc function. + * @GST_ALLOCATOR_FLAG_LAST: first flag that can be used for custom purposes + * + * Flags for allocators. + */ +typedef enum { + GST_ALLOCATOR_FLAG_CUSTOM_ALLOC = (GST_OBJECT_FLAG_LAST << 0), + + GST_ALLOCATOR_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) +} GstAllocatorFlags; + +/** + * GstAllocator: + * @mem_map: the implementation of the GstMemoryMapFunction + * @mem_unmap: the implementation of the GstMemoryUnmapFunction + * @mem_copy: the implementation of the GstMemoryCopyFunction + * @mem_share: the implementation of the GstMemoryShareFunction + * @mem_is_span: the implementation of the GstMemoryIsSpanFunction + * @mem_map_full: the implementation of the GstMemoryMapFullFunction. + * Will be used instead of @mem_map if present. (Since 1.6) + * @mem_unmap_full: the implementation of the GstMemoryUnmapFullFunction. + * Will be used instead of @mem_unmap if present. (Since 1.6) + * + * The #GstAllocator is used to create new memory. + */ +struct _GstAllocator +{ + GstObject object; + + const gchar *mem_type; + + /*< public >*/ + GstMemoryMapFunction mem_map; + GstMemoryUnmapFunction mem_unmap; + + GstMemoryCopyFunction mem_copy; + GstMemoryShareFunction mem_share; + GstMemoryIsSpanFunction mem_is_span; + + GstMemoryMapFullFunction mem_map_full; + GstMemoryUnmapFullFunction mem_unmap_full; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 2]; + + GstAllocatorPrivate *priv; +}; + +/** + * GstAllocatorClass: + * @object_class: Object parent class + * @alloc: implementation that acquires memory + * @free: implementation that releases memory + * + * The #GstAllocator is used to create new memory. + */ +struct _GstAllocatorClass { + GstObjectClass object_class; + + /*< public >*/ + GstMemory * (*alloc) (GstAllocator *allocator, gsize size, + GstAllocationParams *params); + void (*free) (GstAllocator *allocator, GstMemory *memory); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_allocator_get_type (void); + +/* allocators */ + +GST_API +void gst_allocator_register (const gchar *name, GstAllocator *allocator); + +GST_API +GstAllocator * gst_allocator_find (const gchar *name); + +GST_API +void gst_allocator_set_default (GstAllocator * allocator); + +/* allocation parameters */ + +GST_API +void gst_allocation_params_init (GstAllocationParams *params); + +GST_API +GstAllocationParams * + gst_allocation_params_copy (const GstAllocationParams *params) G_GNUC_MALLOC; + +GST_API +void gst_allocation_params_free (GstAllocationParams *params); + +/* allocating memory blocks */ + +GST_API +GstMemory * gst_allocator_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams *params); + +GST_API +void gst_allocator_free (GstAllocator * allocator, GstMemory *memory); + +GST_API +GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, gsize maxsize, + gsize offset, gsize size, gpointer user_data, + GDestroyNotify notify); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAllocationParams, gst_allocation_params_free) +#endif + +G_END_DECLS + +#endif /* __GST_ALLOCATOR_H__ */ diff --git a/gst/gstatomicqueue.c b/gst/gstatomicqueue.c new file mode 100644 index 0000000..a80089c --- /dev/null +++ b/gst/gstatomicqueue.c @@ -0,0 +1,423 @@ +/* GStreamer + * Copyright (C) 2009 Edward Hervey + * 2011 Wim Taymans + * + * gstatomicqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "gst_private.h" + +#include + +#include +#include "gstatomicqueue.h" +#include "glib-compat-private.h" + +/** + * SECTION:gstatomicqueue + * @title: GstAtomicQueue + * @short_description: An atomic queue implementation + * + * The #GstAtomicQueue object implements a queue that can be used from multiple + * threads without performing any blocking operations. + */ + +G_DEFINE_BOXED_TYPE (GstAtomicQueue, gst_atomic_queue, + (GBoxedCopyFunc) gst_atomic_queue_ref, + (GBoxedFreeFunc) gst_atomic_queue_unref); + +/* By default the queue uses 2 * sizeof(gpointer) * clp2 (max_items) of + * memory. clp2(x) is the next power of two >= than x. + * + * The queue can operate in low memory mode, in which it consumes almost + * half the memory at the expense of extra overhead in the readers. This + * is disabled by default because even without LOW_MEM mode, the memory + * consumption is still lower than a plain GList. + */ +#undef LOW_MEM + +typedef struct _GstAQueueMem GstAQueueMem; + +struct _GstAQueueMem +{ + gint size; + gpointer *array; + volatile gint head; + volatile gint tail_write; + volatile gint tail_read; + GstAQueueMem *next; + GstAQueueMem *free; +}; + +static guint +clp2 (guint n) +{ + guint res = 1; + + while (res < n) + res <<= 1; + + return res; +} + +static GstAQueueMem * +new_queue_mem (guint size, gint pos) +{ + GstAQueueMem *mem; + + mem = g_new (GstAQueueMem, 1); + + /* we keep the size as a mask for performance */ + mem->size = clp2 (MAX (size, 16)) - 1; + mem->array = g_new0 (gpointer, mem->size + 1); + mem->head = pos; + mem->tail_write = pos; + mem->tail_read = pos; + mem->next = NULL; + mem->free = NULL; + + return mem; +} + +static void +free_queue_mem (GstAQueueMem * mem) +{ + g_free (mem->array); + g_free (mem); +} + +struct _GstAtomicQueue +{ + volatile gint refcount; +#ifdef LOW_MEM + gint num_readers; +#endif + GstAQueueMem *head_mem; + GstAQueueMem *tail_mem; + GstAQueueMem *free_list; +}; + +static void +add_to_free_list (GstAtomicQueue * queue, GstAQueueMem * mem) +{ + do { + mem->free = g_atomic_pointer_get (&queue->free_list); + } while (!g_atomic_pointer_compare_and_exchange (&queue->free_list, + mem->free, mem)); +} + +static void +clear_free_list (GstAtomicQueue * queue) +{ + GstAQueueMem *free_list; + + /* take the free list and replace with NULL */ + do { + free_list = g_atomic_pointer_get (&queue->free_list); + if (free_list == NULL) + return; + } while (!g_atomic_pointer_compare_and_exchange (&queue->free_list, free_list, + NULL)); + + while (free_list) { + GstAQueueMem *next = free_list->free; + + free_queue_mem (free_list); + + free_list = next; + } +} + +/** + * gst_atomic_queue_new: + * @initial_size: initial queue size + * + * Create a new atomic queue instance. @initial_size will be rounded up to the + * nearest power of 2 and used as the initial size of the queue. + * + * Returns: a new #GstAtomicQueue + */ +GstAtomicQueue * +gst_atomic_queue_new (guint initial_size) +{ + GstAtomicQueue *queue; + + queue = g_new (GstAtomicQueue, 1); + + queue->refcount = 1; +#ifdef LOW_MEM + queue->num_readers = 0; +#endif + queue->head_mem = queue->tail_mem = new_queue_mem (initial_size, 0); + queue->free_list = NULL; + + return queue; +} + +/** + * gst_atomic_queue_ref: + * @queue: a #GstAtomicQueue + * + * Increase the refcount of @queue. + */ +void +gst_atomic_queue_ref (GstAtomicQueue * queue) +{ + g_return_if_fail (queue != NULL); + + g_atomic_int_inc (&queue->refcount); +} + +static void +gst_atomic_queue_free (GstAtomicQueue * queue) +{ + free_queue_mem (queue->head_mem); + if (queue->head_mem != queue->tail_mem) + free_queue_mem (queue->tail_mem); + clear_free_list (queue); + g_free (queue); +} + +/** + * gst_atomic_queue_unref: + * @queue: a #GstAtomicQueue + * + * Unref @queue and free the memory when the refcount reaches 0. + */ +void +gst_atomic_queue_unref (GstAtomicQueue * queue) +{ + g_return_if_fail (queue != NULL); + + if (g_atomic_int_dec_and_test (&queue->refcount)) + gst_atomic_queue_free (queue); +} + +/** + * gst_atomic_queue_peek: + * @queue: a #GstAtomicQueue + * + * Peek the head element of the queue without removing it from the queue. + * + * Returns: (transfer none) (nullable): the head element of @queue or + * %NULL when the queue is empty. + */ +gpointer +gst_atomic_queue_peek (GstAtomicQueue * queue) +{ + GstAQueueMem *head_mem; + gint head, tail, size; + + g_return_val_if_fail (queue != NULL, NULL); + + while (TRUE) { + GstAQueueMem *next; + + head_mem = g_atomic_pointer_get (&queue->head_mem); + + head = g_atomic_int_get (&head_mem->head); + tail = g_atomic_int_get (&head_mem->tail_read); + size = head_mem->size; + + /* when we are not empty, we can continue */ + if (G_LIKELY (head != tail)) + break; + + /* else array empty, try to take next */ + next = g_atomic_pointer_get (&head_mem->next); + if (next == NULL) + return NULL; + + /* now we try to move the next array as the head memory. If we fail to do that, + * some other reader managed to do it first and we retry */ + if (!g_atomic_pointer_compare_and_exchange (&queue->head_mem, head_mem, + next)) + continue; + + /* when we managed to swing the head pointer the old head is now + * useless and we add it to the freelist. We can't free the memory yet + * because we first need to make sure no reader is accessing it anymore. */ + add_to_free_list (queue, head_mem); + } + + return head_mem->array[head & size]; +} + +/** + * gst_atomic_queue_pop: + * @queue: a #GstAtomicQueue + * + * Get the head element of the queue. + * + * Returns: (transfer full): the head element of @queue or %NULL when + * the queue is empty. + */ +gpointer +gst_atomic_queue_pop (GstAtomicQueue * queue) +{ + gpointer ret; + GstAQueueMem *head_mem; + gint head, tail, size; + + g_return_val_if_fail (queue != NULL, NULL); + +#ifdef LOW_MEM + g_atomic_int_inc (&queue->num_readers); +#endif + + do { + while (TRUE) { + GstAQueueMem *next; + + head_mem = g_atomic_pointer_get (&queue->head_mem); + + head = g_atomic_int_get (&head_mem->head); + tail = g_atomic_int_get (&head_mem->tail_read); + size = head_mem->size; + + /* when we are not empty, we can continue */ + if G_LIKELY + (head != tail) + break; + + /* else array empty, try to take next */ + next = g_atomic_pointer_get (&head_mem->next); + if (next == NULL) + return NULL; + + /* now we try to move the next array as the head memory. If we fail to do that, + * some other reader managed to do it first and we retry */ + if G_UNLIKELY + (!g_atomic_pointer_compare_and_exchange (&queue->head_mem, head_mem, + next)) + continue; + + /* when we managed to swing the head pointer the old head is now + * useless and we add it to the freelist. We can't free the memory yet + * because we first need to make sure no reader is accessing it anymore. */ + add_to_free_list (queue, head_mem); + } + + ret = head_mem->array[head & size]; + } while G_UNLIKELY + (!g_atomic_int_compare_and_exchange (&head_mem->head, head, head + 1)); + +#ifdef LOW_MEM + /* decrement number of readers, when we reach 0 readers we can be sure that + * none is accessing the memory in the free list and we can try to clean up */ + if (g_atomic_int_dec_and_test (&queue->num_readers)) + clear_free_list (queue); +#endif + + return ret; +} + +/** + * gst_atomic_queue_push: + * @queue: a #GstAtomicQueue + * @data: the data + * + * Append @data to the tail of the queue. + */ +void +gst_atomic_queue_push (GstAtomicQueue * queue, gpointer data) +{ + GstAQueueMem *tail_mem; + gint head, tail, size; + + g_return_if_fail (queue != NULL); + + do { + while (TRUE) { + GstAQueueMem *mem; + + tail_mem = g_atomic_pointer_get (&queue->tail_mem); + head = g_atomic_int_get (&tail_mem->head); + tail = g_atomic_int_get (&tail_mem->tail_write); + size = tail_mem->size; + + /* we're not full, continue */ + if G_LIKELY + (tail - head <= size) + break; + + /* else we need to grow the array, we store a mask so we have to add 1 */ + mem = new_queue_mem ((size << 1) + 1, tail); + + /* try to make our new array visible to other writers */ + if G_UNLIKELY + (!g_atomic_pointer_compare_and_exchange (&queue->tail_mem, tail_mem, + mem)) { + /* we tried to swap the new writer array but something changed. This is + * because some other writer beat us to it, we free our memory and try + * again */ + free_queue_mem (mem); + continue; + } + /* make sure that readers can find our new array as well. The one who + * manages to swap the pointer is the only one who can set the next + * pointer to the new array */ + g_atomic_pointer_set (&tail_mem->next, mem); + } + } while G_UNLIKELY + (!g_atomic_int_compare_and_exchange (&tail_mem->tail_write, tail, tail + 1)); + + tail_mem->array[tail & size] = data; + + /* now wait until all writers have completed their write before we move the + * tail_read to this new item. It is possible that other writers are still + * updating the previous array slots and we don't want to reveal their changes + * before they are done. FIXME, it would be nice if we didn't have to busy + * wait here. */ + while G_UNLIKELY + (!g_atomic_int_compare_and_exchange (&tail_mem->tail_read, tail, tail + 1)); +} + +/** + * gst_atomic_queue_length: + * @queue: a #GstAtomicQueue + * + * Get the amount of items in the queue. + * + * Returns: the number of elements in the queue. + */ +guint +gst_atomic_queue_length (GstAtomicQueue * queue) +{ + GstAQueueMem *head_mem, *tail_mem; + gint head, tail; + + g_return_val_if_fail (queue != NULL, 0); + +#ifdef LOW_MEM + g_atomic_int_inc (&queue->num_readers); +#endif + + head_mem = g_atomic_pointer_get (&queue->head_mem); + head = g_atomic_int_get (&head_mem->head); + + tail_mem = g_atomic_pointer_get (&queue->tail_mem); + tail = g_atomic_int_get (&tail_mem->tail_read); + +#ifdef LOW_MEM + if (g_atomic_int_dec_and_test (&queue->num_readers)) + clear_free_list (queue); +#endif + + return tail - head; +} diff --git a/gst/gstatomicqueue.h b/gst/gstatomicqueue.h new file mode 100644 index 0000000..8a131ab --- /dev/null +++ b/gst/gstatomicqueue.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 2009-2010 Edward Hervey + * (C) 2011 Wim Taymans + * + * gstatomicqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#ifndef __GST_ATOMIC_QUEUE_H__ +#define __GST_ATOMIC_QUEUE_H__ + +G_BEGIN_DECLS + +#define GST_TYPE_ATOMIC_QUEUE (gst_atomic_queue_get_type()) + +/** + * GstAtomicQueue: + * + * Opaque atomic data queue. + * + * Use the accessor functions to get the stored values. + */ +typedef struct _GstAtomicQueue GstAtomicQueue; + + +GST_API +GType gst_atomic_queue_get_type (void); + +GST_API +GstAtomicQueue * gst_atomic_queue_new (guint initial_size) G_GNUC_MALLOC; + +GST_API +void gst_atomic_queue_ref (GstAtomicQueue * queue); + +GST_API +void gst_atomic_queue_unref (GstAtomicQueue * queue); + +GST_API +void gst_atomic_queue_push (GstAtomicQueue* queue, gpointer data); + +GST_API +gpointer gst_atomic_queue_pop (GstAtomicQueue* queue); + +GST_API +gpointer gst_atomic_queue_peek (GstAtomicQueue* queue); + +GST_API +guint gst_atomic_queue_length (GstAtomicQueue * queue); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAtomicQueue, gst_atomic_queue_unref) +#endif + +G_END_DECLS + +#endif /* __GST_ATOMIC_QUEUE_H__ */ diff --git a/gst/gstbin.c b/gst/gstbin.c new file mode 100644 index 0000000..e575aee --- /dev/null +++ b/gst/gstbin.c @@ -0,0 +1,4622 @@ +/* GStreamer + * + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004 Wim Taymans + * + * gstbin.c: GstBin container object and support code + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * MT safe. + */ + +/** + * SECTION:gstbin + * @title: GstBin + * @short_description: Base class and element that can contain other elements + * + * #GstBin is an element that can contain other #GstElement, allowing them to be + * managed as a group. + * Pads from the child elements can be ghosted to the bin, see #GstGhostPad. + * This makes the bin look like any other elements and enables creation of + * higher-level abstraction elements. + * + * A new #GstBin is created with gst_bin_new(). Use a #GstPipeline instead if you + * want to create a toplevel bin because a normal bin doesn't have a bus or + * handle clock distribution of its own. + * + * After the bin has been created you will typically add elements to it with + * gst_bin_add(). You can remove elements with gst_bin_remove(). + * + * An element can be retrieved from a bin with gst_bin_get_by_name(), using the + * elements name. gst_bin_get_by_name_recurse_up() is mainly used for internal + * purposes and will query the parent bins when the element is not found in the + * current bin. + * + * An iterator of elements in a bin can be retrieved with + * gst_bin_iterate_elements(). Various other iterators exist to retrieve the + * elements in a bin. + * + * gst_object_unref() is used to drop your reference to the bin. + * + * The #GstBin::element-added signal is fired whenever a new element is added to + * the bin. Likewise the #GstBin::element-removed signal is fired whenever an + * element is removed from the bin. + * + * ## Notes + * + * A #GstBin internally intercepts every #GstMessage posted by its children and + * implements the following default behaviour for each of them: + * + * * GST_MESSAGE_EOS: This message is only posted by sinks in the PLAYING + * state. If all sinks posted the EOS message, this bin will post and EOS + * message upwards. + * + * * GST_MESSAGE_SEGMENT_START: Just collected and never forwarded upwards. + * The messages are used to decide when all elements have completed playback + * of their segment. + * + * * GST_MESSAGE_SEGMENT_DONE: Is posted by #GstBin when all elements that posted + * a SEGMENT_START have posted a SEGMENT_DONE. + * + * * GST_MESSAGE_DURATION_CHANGED: Is posted by an element that detected a change + * in the stream duration. The default bin behaviour is to clear any + * cached duration values so that the next duration query will perform + * a full duration recalculation. The duration change is posted to the + * application so that it can refetch the new duration with a duration + * query. Note that these messages can be posted before the bin is + * prerolled, in which case the duration query might fail. + * + * * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it + * can no longer provide a clock. The default bin behaviour is to + * check if the lost clock was the one provided by the bin. If so and + * the bin is currently in the PLAYING state, the message is forwarded to + * the bin parent. + * This message is also generated when a clock provider is removed from + * the bin. If this message is received by the application, it should + * PAUSE the pipeline and set it back to PLAYING to force a new clock + * distribution. + * + * * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element + * can provide a clock. This mostly happens when a new clock + * provider is added to the bin. The default behaviour of the bin is to + * mark the currently selected clock as dirty, which will perform a clock + * recalculation the next time the bin is asked to provide a clock. + * This message is never sent tot the application but is forwarded to + * the parent of the bin. + * + * * OTHERS: posted upwards. + * + * A #GstBin implements the following default behaviour for answering to a + * #GstQuery: + * + * * GST_QUERY_DURATION:If the query has been asked before with the same format + * and the bin is a toplevel bin (ie. has no parent), + * use the cached previous value. If no previous value was cached, the + * query is sent to all sink elements in the bin and the MAXIMUM of all + * values is returned. If the bin is a toplevel bin the value is cached. + * If no sinks are available in the bin, the query fails. + * + * * GST_QUERY_POSITION:The query is sent to all sink elements in the bin and the + * MAXIMUM of all values is returned. If no sinks are available in the bin, + * the query fails. + * + * * OTHERS:the query is forwarded to all sink elements, the result + * of the first sink that answers the query successfully is returned. If no + * sink is in the bin, the query fails. + * + * A #GstBin will by default forward any event sent to it to all sink + * (#GST_EVENT_TYPE_DOWNSTREAM) or source (#GST_EVENT_TYPE_UPSTREAM) elements + * depending on the event type. + * If all the elements return %TRUE, the bin will also return %TRUE, else %FALSE + * is returned. If no elements of the required type are in the bin, the event + * handler will return %TRUE. + * + */ + +#include "gst_private.h" + +#include "gstevent.h" +#include "gstbin.h" +#include "gstinfo.h" +#include "gsterror.h" + +#include "gstutils.h" +#include "gstchildproxy.h" + +GST_DEBUG_CATEGORY_STATIC (bin_debug); +#define GST_CAT_DEFAULT bin_debug + +/* a bin is toplevel if it has no parent or when it is configured to behave like + * a toplevel bin */ +#define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling) + +#define GST_BIN_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate)) + +struct _GstBinPrivate +{ + gboolean asynchandling; + /* if we get an ASYNC_DONE message from ourselves, this means that the + * subclass will simulate ASYNC behaviour without having ASYNC children. When + * such an ASYNC_DONE message is posted while we are doing a state change, we + * have to process the message after finishing the state change even when no + * child returned GST_STATE_CHANGE_ASYNC. */ + gboolean pending_async_done; + + guint32 structure_cookie; + +#if 0 + /* cached index */ + GstIndex *index; +#endif + + /* forward messages from our children */ + gboolean message_forward; + + gboolean posted_eos; + gboolean posted_playing; + GstElementFlags suppressed_flags; +}; + +typedef struct +{ + guint32 cookie; + GstState pending; +} BinContinueData; + +static void gst_bin_dispose (GObject * object); + +static void gst_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_bin_change_state_func (GstElement * element, + GstStateChange transition); +static gboolean gst_bin_post_message (GstElement * element, GstMessage * msg); +static GstStateChangeReturn gst_bin_get_state_func (GstElement * element, + GstState * state, GstState * pending, GstClockTime timeout); +static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, + gboolean flag_pending, GstClockTime running_time); +static void bin_handle_async_start (GstBin * bin); +static void bin_push_state_continue (GstBin * bin, BinContinueData * data); +static void bin_do_eos (GstBin * bin); + +static gboolean gst_bin_add_func (GstBin * bin, GstElement * element); +static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element); +static void gst_bin_deep_element_added_func (GstBin * bin, GstBin * sub_bin, + GstElement * element); +static void gst_bin_deep_element_removed_func (GstBin * bin, GstBin * sub_bin, + GstElement * element); +static void gst_bin_update_context (GstBin * bin, GstContext * context); +static void gst_bin_update_context_unlocked (GstBin * bin, + GstContext * context); + +#if 0 +static void gst_bin_set_index_func (GstElement * element, GstIndex * index); +static GstIndex *gst_bin_get_index_func (GstElement * element); +#endif + +static GstClock *gst_bin_provide_clock_func (GstElement * element); +static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock); + +static void gst_bin_handle_message_func (GstBin * bin, GstMessage * message); +static gboolean gst_bin_send_event (GstElement * element, GstEvent * event); +static GstBusSyncReply bin_bus_handler (GstBus * bus, + GstMessage * message, GstBin * bin); +static gboolean gst_bin_query (GstElement * element, GstQuery * query); +static void gst_bin_set_context (GstElement * element, GstContext * context); + +static gboolean gst_bin_do_latency_func (GstBin * bin); + +static void bin_remove_messages (GstBin * bin, GstObject * src, + GstMessageType types); +static void gst_bin_continue_func (GstBin * bin, BinContinueData * data); +static gint bin_element_is_sink (GstElement * child, GstBin * bin); +static gint bin_element_is_src (GstElement * child, GstBin * bin); + +static GstIterator *gst_bin_sort_iterator_new (GstBin * bin); + +/* Bin signals and properties */ +enum +{ + ELEMENT_ADDED, + ELEMENT_REMOVED, + DO_LATENCY, + DEEP_ELEMENT_ADDED, + DEEP_ELEMENT_REMOVED, + LAST_SIGNAL +}; + +#define DEFAULT_ASYNC_HANDLING FALSE +#define DEFAULT_MESSAGE_FORWARD FALSE + +enum +{ + PROP_0, + PROP_ASYNC_HANDLING, + PROP_MESSAGE_FORWARD, + PROP_LAST +}; + +static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data); + +static guint gst_bin_signals[LAST_SIGNAL] = { 0 }; + +#define _do_init \ +{ \ + static const GInterfaceInfo iface_info = { \ + gst_bin_child_proxy_init, \ + NULL, \ + NULL}; \ + \ + g_type_add_interface_static (g_define_type_id, GST_TYPE_CHILD_PROXY, &iface_info); \ + \ + GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \ + "debugging info for the 'bin' container element"); \ + \ +} + +#define gst_bin_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstBin, gst_bin, GST_TYPE_ELEMENT, _do_init); + +static GObject * +gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy, + guint index) +{ + GstObject *res; + GstBin *bin; + + bin = GST_BIN_CAST (child_proxy); + + GST_OBJECT_LOCK (bin); + if ((res = g_list_nth_data (bin->children, index))) + gst_object_ref (res); + GST_OBJECT_UNLOCK (bin); + + return (GObject *) res; +} + +static guint +gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy) +{ + guint num; + GstBin *bin; + + bin = GST_BIN_CAST (child_proxy); + + GST_OBJECT_LOCK (bin); + num = bin->numchildren; + GST_OBJECT_UNLOCK (bin); + + return num; +} + +static void +gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data) +{ + GstChildProxyInterface *iface = g_iface; + + iface->get_children_count = gst_bin_child_proxy_get_children_count; + iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index; +} + +static gboolean +_gst_boolean_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gboolean myboolean; + + myboolean = g_value_get_boolean (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boolean (return_accu, myboolean); + + GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean); + + /* stop emission */ + return FALSE; +} + +static void +gst_bin_class_init (GstBinClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + g_type_class_add_private (klass, sizeof (GstBinPrivate)); + + gobject_class->set_property = gst_bin_set_property; + gobject_class->get_property = gst_bin_get_property; + + /** + * GstBin:async-handling: + * + * If set to %TRUE, the bin will handle asynchronous state changes. + * This should be used only if the bin subclass is modifying the state + * of its children on its own. + */ + g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING, + g_param_spec_boolean ("async-handling", "Async Handling", + "The bin will handle Asynchronous state changes", + DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBin::element-added: + * @bin: the #GstBin + * @element: the #GstElement that was added to the bin + * + * Will be emitted after the element was added to the bin. + */ + gst_bin_signals[ELEMENT_ADDED] = + g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + /** + * GstBin::element-removed: + * @bin: the #GstBin + * @element: the #GstElement that was removed from the bin + * + * Will be emitted after the element was removed from the bin. + */ + gst_bin_signals[ELEMENT_REMOVED] = + g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + /** + * GstBin::deep-element-added: + * @bin: the #GstBin + * @sub_bin: the #GstBin the element was added to + * @element: the #GstElement that was added to @sub_bin + * + * Will be emitted after the element was added to sub_bin. + * + * Since: 1.10 + */ + gst_bin_signals[DEEP_ELEMENT_ADDED] = + g_signal_new ("deep-element-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, deep_element_added), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_BIN, + GST_TYPE_ELEMENT); + /** + * GstBin::deep-element-removed: + * @bin: the #GstBin + * @sub_bin: the #GstBin the element was removed from + * @element: the #GstElement that was removed from @sub_bin + * + * Will be emitted after the element was removed from sub_bin. + * + * Since: 1.10 + */ + gst_bin_signals[DEEP_ELEMENT_REMOVED] = + g_signal_new ("deep-element-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, deep_element_removed), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_BIN, + GST_TYPE_ELEMENT); + /** + * GstBin::do-latency: + * @bin: the #GstBin + * + * Will be emitted when the bin needs to perform latency calculations. This + * signal is only emitted for toplevel bins or when async-handling is + * enabled. + * + * Only one signal handler is invoked. If no signals are connected, the + * default handler is invoked, which will query and distribute the lowest + * possible latency to all sinks. + * + * Connect to this signal if the default latency calculations are not + * sufficient, like when you need different latencies for different sinks in + * the same pipeline. + */ + gst_bin_signals[DO_LATENCY] = + g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency), + _gst_boolean_accumulator, NULL, g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, 0, G_TYPE_NONE); + + /** + * GstBin:message-forward: + * + * Forward all children messages, even those that would normally be filtered by + * the bin. This can be interesting when one wants to be notified of the EOS + * state of individual elements, for example. + * + * The messages are converted to an ELEMENT message with the bin as the + * source. The structure of the message is named 'GstBinForwarded' and contains + * a field named 'message' of type GST_TYPE_MESSAGE that contains the original + * forwarded message. + */ + g_object_class_install_property (gobject_class, PROP_MESSAGE_FORWARD, + g_param_spec_boolean ("message-forward", "Message Forward", + "Forwards all children messages", + DEFAULT_MESSAGE_FORWARD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gobject_class->dispose = gst_bin_dispose; + + gst_element_class_set_static_metadata (gstelement_class, "Generic bin", + "Generic/Bin", + "Simple container object", + "Erik Walthinsen ," + "Wim Taymans "); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_bin_change_state_func); + gstelement_class->post_message = GST_DEBUG_FUNCPTR (gst_bin_post_message); + gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func); +#if 0 + gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_bin_get_index_func); + gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func); +#endif + gstelement_class->provide_clock = + GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func); + gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func); + + gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event); + gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query); + gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_bin_set_context); + + klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func); + klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func); + klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func); + + klass->deep_element_added = gst_bin_deep_element_added_func; + klass->deep_element_removed = gst_bin_deep_element_removed_func; + + klass->do_latency = GST_DEBUG_FUNCPTR (gst_bin_do_latency_func); +} + +static void +gst_bin_init (GstBin * bin) +{ + GstBus *bus; + + bin->numchildren = 0; + bin->children = NULL; + bin->children_cookie = 0; + bin->messages = NULL; + bin->provided_clock = NULL; + bin->clock_dirty = FALSE; + + /* Set up a bus for listening to child elements */ + bus = g_object_new (GST_TYPE_BUS, "enable-async", FALSE, NULL); + gst_object_ref_sink (bus); + bin->child_bus = bus; + GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children", + bus); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin, + NULL); + + bin->priv = GST_BIN_GET_PRIVATE (bin); + bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING; + bin->priv->structure_cookie = 0; + bin->priv->message_forward = DEFAULT_MESSAGE_FORWARD; +} + +static void +gst_bin_dispose (GObject * object) +{ + GstBin *bin = GST_BIN_CAST (object); + GstBus **child_bus_p = &bin->child_bus; + GstClock **provided_clock_p = &bin->provided_clock; + GstElement **clock_provider_p = &bin->clock_provider; + + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "%p dispose", object); + + GST_OBJECT_LOCK (object); + gst_object_replace ((GstObject **) child_bus_p, NULL); + gst_object_replace ((GstObject **) provided_clock_p, NULL); + gst_object_replace ((GstObject **) clock_provider_p, NULL); + bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); + GST_OBJECT_UNLOCK (object); + + while (bin->children) { + gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data)); + } + if (G_UNLIKELY (bin->children != NULL)) { + g_critical ("could not remove elements from bin '%s'", + GST_STR_NULL (GST_OBJECT_NAME (object))); + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/** + * gst_bin_new: + * @name: (allow-none): the name of the new bin + * + * Creates a new bin with the given name. + * + * Returns: (transfer floating): a new #GstBin + */ +GstElement * +gst_bin_new (const gchar * name) +{ + return gst_element_factory_make ("bin", name); +} + +static void +gst_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBin *gstbin; + + gstbin = GST_BIN_CAST (object); + + switch (prop_id) { + case PROP_ASYNC_HANDLING: + GST_OBJECT_LOCK (gstbin); + gstbin->priv->asynchandling = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (gstbin); + break; + case PROP_MESSAGE_FORWARD: + GST_OBJECT_LOCK (gstbin); + gstbin->priv->message_forward = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (gstbin); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBin *gstbin; + + gstbin = GST_BIN_CAST (object); + + switch (prop_id) { + case PROP_ASYNC_HANDLING: + GST_OBJECT_LOCK (gstbin); + g_value_set_boolean (value, gstbin->priv->asynchandling); + GST_OBJECT_UNLOCK (gstbin); + break; + case PROP_MESSAGE_FORWARD: + GST_OBJECT_LOCK (gstbin); + g_value_set_boolean (value, gstbin->priv->message_forward); + GST_OBJECT_UNLOCK (gstbin); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +#if 0 +/* return the cached index */ +static GstIndex * +gst_bin_get_index_func (GstElement * element) +{ + GstBin *bin; + GstIndex *result; + + bin = GST_BIN_CAST (element); + + GST_OBJECT_LOCK (bin); + if ((result = bin->priv->index)) + gst_object_ref (result); + GST_OBJECT_UNLOCK (bin); + + return result; +} + +/* set the index on all elements in this bin + * + * MT safe + */ +static void +gst_bin_set_index_func (GstElement * element, GstIndex * index) +{ + GstBin *bin; + gboolean done; + GstIterator *it; + GstIndex *old; + GValue data = { 0, }; + + bin = GST_BIN_CAST (element); + + GST_OBJECT_LOCK (bin); + old = bin->priv->index; + if (G_UNLIKELY (old == index)) + goto was_set; + if (index) + gst_object_ref (index); + bin->priv->index = index; + GST_OBJECT_UNLOCK (bin); + + if (old) + gst_object_unref (old); + + it = gst_bin_iterate_elements (bin); + + /* set the index on all elements in the bin */ + done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &data)) { + case GST_ITERATOR_OK: + { + GstElement *child = g_value_get_object (&data); + + GST_DEBUG_OBJECT (bin, "setting index on '%s'", + GST_ELEMENT_NAME (child)); + gst_element_set_index (child, index); + + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + GST_DEBUG_OBJECT (bin, "iterator doing resync"); + gst_iterator_resync (it); + break; + default: + case GST_ITERATOR_DONE: + GST_DEBUG_OBJECT (bin, "iterator done"); + done = TRUE; + break; + } + } + g_value_unset (&data); + gst_iterator_free (it); + return; + +was_set: + { + GST_DEBUG_OBJECT (bin, "index was already set"); + GST_OBJECT_UNLOCK (bin); + return; + } +} +#endif + +/* set the clock on all elements in this bin + * + * MT safe + */ +static gboolean +gst_bin_set_clock_func (GstElement * element, GstClock * clock) +{ + GstBin *bin; + gboolean done; + GstIterator *it; + gboolean res = TRUE; + GValue data = { 0, }; + + bin = GST_BIN_CAST (element); + + it = gst_bin_iterate_elements (bin); + + done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &data)) { + case GST_ITERATOR_OK: + { + GstElement *child = g_value_get_object (&data); + + res &= gst_element_set_clock (child, clock); + + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + GST_DEBUG_OBJECT (bin, "iterator doing resync"); + gst_iterator_resync (it); + res = TRUE; + break; + default: + case GST_ITERATOR_DONE: + GST_DEBUG_OBJECT (bin, "iterator done"); + done = TRUE; + break; + } + } + g_value_unset (&data); + gst_iterator_free (it); + + if (res) + res = GST_ELEMENT_CLASS (parent_class)->set_clock (element, clock); + + return res; +} + +/* get the clock for this bin by asking all of the children in this bin + * + * The ref of the returned clock in increased so unref after usage. + * + * We loop the elements in state order and pick the last clock we can + * get. This makes sure we get a clock from the source. + * + * MT safe + */ +static GstClock * +gst_bin_provide_clock_func (GstElement * element) +{ + GstClock *result = NULL; + GstElement *provider = NULL; + GstBin *bin; + GstIterator *it; + gboolean done; + GValue val = { 0, }; + GstClock **provided_clock_p; + GstElement **clock_provider_p; + + bin = GST_BIN_CAST (element); + + GST_OBJECT_LOCK (bin); + if (!bin->clock_dirty) + goto not_dirty; + + GST_DEBUG_OBJECT (bin, "finding new clock"); + + it = gst_bin_sort_iterator_new (bin); + GST_OBJECT_UNLOCK (bin); + + done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &val)) { + case GST_ITERATOR_OK: + { + GstElement *child = g_value_get_object (&val); + GstClock *clock; + + clock = gst_element_provide_clock (child); + if (clock) { + GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s", + clock, GST_ELEMENT_NAME (child)); + if (result) { + gst_object_unref (result); + gst_object_unref (provider); + } + result = clock; + provider = gst_object_ref (child); + } + + g_value_reset (&val); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + default: + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + g_value_unset (&val); + gst_iterator_free (it); + + GST_OBJECT_LOCK (bin); + if (!bin->clock_dirty) { + if (provider) + gst_object_unref (provider); + if (result) + gst_object_unref (result); + result = NULL; + + goto not_dirty; + } + + provided_clock_p = &bin->provided_clock; + clock_provider_p = &bin->clock_provider; + gst_object_replace ((GstObject **) provided_clock_p, (GstObject *) result); + gst_object_replace ((GstObject **) clock_provider_p, (GstObject *) provider); + bin->clock_dirty = FALSE; + GST_DEBUG_OBJECT (bin, + "provided new clock %" GST_PTR_FORMAT " by provider %" GST_PTR_FORMAT, + result, provider); + /* Provider is not being returned to caller, just the result */ + if (provider) + gst_object_unref (provider); + GST_OBJECT_UNLOCK (bin); + + return result; + +not_dirty: + { + if ((result = bin->provided_clock)) + gst_object_ref (result); + GST_DEBUG_OBJECT (bin, "returning old clock %p", result); + GST_OBJECT_UNLOCK (bin); + + return result; + } +} + +/* + * functions for manipulating cached messages + */ +typedef struct +{ + GstObject *src; + GstMessageType types; +} MessageFind; + +/* check if a message is of given src and type */ +static gint +message_check (GstMessage * message, MessageFind * target) +{ + gboolean eq = TRUE; + + if (target->src) + eq &= GST_MESSAGE_SRC (message) == target->src; + if (target->types) + eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0; + GST_LOG ("looking at message %p: %d", message, eq); + + return (eq ? 0 : 1); +} + +static GList * +find_message (GstBin * bin, GstObject * src, GstMessageType types) +{ + GList *result; + MessageFind find; + + find.src = src; + find.types = types; + + result = g_list_find_custom (bin->messages, &find, + (GCompareFunc) message_check); + + if (result) { + GST_DEBUG_OBJECT (bin, "we found a message %p from %s matching types %08x", + result->data, GST_OBJECT_NAME (GST_MESSAGE_CAST (result->data)->src), + types); + } else { + GST_DEBUG_OBJECT (bin, "no message found matching types %08x", types); +#ifndef GST_DISABLE_GST_DEBUG + { + guint i; + + for (i = 0; i < 32; i++) + if (types & (1U << i)) + GST_DEBUG_OBJECT (bin, " %s", gst_message_type_get_name (1U << i)); + } +#endif + } + + return result; +} + +/* with LOCK, returns TRUE if message had a valid SRC, takes ownership of + * the message. + * + * A message that is cached and has the same SRC and type is replaced + * by the given message. + */ +static gboolean +bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types) +{ + GList *previous; + GstObject *src; + gboolean res = TRUE; + + if ((src = GST_MESSAGE_SRC (message))) { + /* first find the previous message posted by this element */ + if ((previous = find_message (bin, src, types))) { + GstMessage *previous_msg; + + /* if we found a previous message, replace it */ + previous_msg = previous->data; + previous->data = message; + + GST_DEBUG_OBJECT (bin, "replace old message %s from %s with %s message", + GST_MESSAGE_TYPE_NAME (previous_msg), GST_ELEMENT_NAME (src), + GST_MESSAGE_TYPE_NAME (message)); + + gst_message_unref (previous_msg); + } else { + /* keep new message */ + bin->messages = g_list_prepend (bin->messages, message); + + GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s", + message, GST_MESSAGE_TYPE_NAME (message), GST_ELEMENT_NAME (src)); + } + } else { + GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing", + GST_MESSAGE_TYPE_NAME (message)); + res = FALSE; + gst_message_unref (message); + } + return res; +} + +/* with LOCK. Remove all messages of given types */ +static void +bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types) +{ + MessageFind find; + GList *walk, *next; + + find.src = src; + find.types = types; + + for (walk = bin->messages; walk; walk = next) { + GstMessage *message = (GstMessage *) walk->data; + + next = g_list_next (walk); + + if (message_check (message, &find) == 0) { + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), + "deleting message %p of type %s (types 0x%08x)", message, + GST_MESSAGE_TYPE_NAME (message), types); + bin->messages = g_list_delete_link (bin->messages, walk); + gst_message_unref (message); + } else { + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), + "not deleting message %p of type 0x%08x", message, + GST_MESSAGE_TYPE (message)); + } + } +} + + +/* Check if the bin is EOS. We do this by scanning all sinks and + * checking if they posted an EOS message. + * + * call with bin LOCK */ +static gboolean +is_eos (GstBin * bin, guint32 * seqnum) +{ + gboolean result; + gint n_eos = 0; + GList *walk, *msgs; + + result = TRUE; + for (walk = bin->children; walk; walk = g_list_next (walk)) { + GstElement *element; + + element = GST_ELEMENT_CAST (walk->data); + if (bin_element_is_sink (element, bin) == 0) { + /* check if element posted EOS */ + if ((msgs = + find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS))) { + GST_DEBUG ("sink '%s' posted EOS", GST_ELEMENT_NAME (element)); + *seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data)); + n_eos++; + } else { + GST_DEBUG ("sink '%s' did not post EOS yet", + GST_ELEMENT_NAME (element)); + result = FALSE; + break; + } + } + } + /* FIXME: Some tests (e.g. elements/capsfilter) use + * pipelines with a dangling sinkpad but no sink element. + * These tests assume that no EOS message is ever + * posted on the bus so let's keep that behaviour. + * In valid pipelines this doesn't make a difference. + */ + return result && n_eos > 0; +} + + +/* Check if the bin is STREAM_START. We do this by scanning all sinks and + * checking if they posted an STREAM_START message. + * + * call with bin LOCK */ +static gboolean +is_stream_start (GstBin * bin, guint32 * seqnum, gboolean * have_group_id, + guint * group_id) +{ + gboolean result; + GList *walk, *msgs; + guint tmp_group_id; + gboolean first = TRUE, same_group_id = TRUE; + + *have_group_id = TRUE; + *group_id = 0; + result = TRUE; + for (walk = bin->children; walk; walk = g_list_next (walk)) { + GstElement *element; + + element = GST_ELEMENT_CAST (walk->data); + if (bin_element_is_sink (element, bin) == 0) { + /* check if element posted STREAM_START */ + if ((msgs = + find_message (bin, GST_OBJECT_CAST (element), + GST_MESSAGE_STREAM_START))) { + GST_DEBUG ("sink '%s' posted STREAM_START", GST_ELEMENT_NAME (element)); + *seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data)); + if (gst_message_parse_group_id (GST_MESSAGE_CAST (msgs->data), + &tmp_group_id)) { + if (first) { + first = FALSE; + *group_id = tmp_group_id; + } else { + if (tmp_group_id != *group_id) + same_group_id = FALSE; + } + } else { + *have_group_id = FALSE; + } + } else { + GST_DEBUG ("sink '%s' did not post STREAM_START yet", + GST_ELEMENT_NAME (element)); + result = FALSE; + break; + } + } + } + + /* If all have a group_id we only consider this stream started + * if all group ids were the same and all sinks posted a stream-start + * message */ + if (*have_group_id) + return same_group_id && result; + /* otherwise consider this stream started after all sinks + * have reported stream-start for backward compatibility. + * FIXME 2.0: This should go away! */ + return result; +} + +static void +unlink_pads (const GValue * item, gpointer user_data) +{ + GstPad *pad; + GstPad *peer; + + pad = g_value_get_object (item); + + if ((peer = gst_pad_get_peer (pad))) { + if (gst_pad_get_direction (pad) == GST_PAD_SRC) + gst_pad_unlink (pad, peer); + else + gst_pad_unlink (peer, pad); + gst_object_unref (peer); + } +} + +static void +bin_deep_iterator_foreach (const GValue * item, gpointer user_data) +{ + GQueue *queue = user_data; + + g_queue_push_tail (queue, g_value_dup_object (item)); +} + +static void +gst_bin_do_deep_add_remove (GstBin * bin, gint sig_id, const gchar * sig_name, + GstElement * element) +{ + g_signal_emit (bin, sig_id, 0, bin, element); + + /* When removing a bin, emit deep-element-* for everything in the bin too */ + if (GST_IS_BIN (element)) { + GstIterator *it; + GstIteratorResult ires; + GQueue elements = G_QUEUE_INIT; + + GST_LOG_OBJECT (bin, "Recursing into bin %" GST_PTR_FORMAT " for %s", + element, sig_name); + it = gst_bin_iterate_recurse (GST_BIN_CAST (element)); + do { + ires = gst_iterator_foreach (it, bin_deep_iterator_foreach, &elements); + if (ires != GST_ITERATOR_DONE) { + g_queue_foreach (&elements, (GFunc) g_object_unref, NULL); + g_queue_clear (&elements); + } + if (ires == GST_ITERATOR_RESYNC) + gst_iterator_resync (it); + } while (ires == GST_ITERATOR_RESYNC); + if (ires != GST_ITERATOR_ERROR) { + GstElement *e; + + while ((e = g_queue_pop_head (&elements))) { + GstObject *parent = gst_object_get_parent (GST_OBJECT_CAST (e)); + + GST_LOG_OBJECT (bin, "calling %s for element %" GST_PTR_FORMAT + " in bin %" GST_PTR_FORMAT, sig_name, e, parent); + g_signal_emit (bin, sig_id, 0, parent, e); + gst_object_unref (parent); + g_object_unref (e); + } + } + gst_iterator_free (it); + } +} + +/* vmethod that adds an element to a bin + * + * MT safe + */ +static gboolean +gst_bin_add_func (GstBin * bin, GstElement * element) +{ + gchar *elem_name; + GstIterator *it; + gboolean is_sink, is_source, provides_clock, requires_clock; + GstMessage *clock_message = NULL, *async_message = NULL; + GstStateChangeReturn ret; + GList *l, *elem_contexts, *need_context_messages; + + GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element)); + + /* we obviously can't add ourself to ourself */ + if (G_UNLIKELY (element == GST_ELEMENT_CAST (bin))) + goto adding_itself; + + /* get the element name to make sure it is unique in this bin. */ + GST_OBJECT_LOCK (element); + elem_name = g_strdup (GST_ELEMENT_NAME (element)); + is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK); + is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE); + provides_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + requires_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + GST_OBJECT_UNLOCK (element); + + GST_OBJECT_LOCK (bin); + + /* then check to see if the element's name is already taken in the bin, + * we can safely take the lock here. This check is probably bogus because + * you can safely change the element name after this check and before setting + * the object parent. The window is very small though... */ + if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name))) + goto duplicate_name; + + /* set the element's parent and add the element to the bin's list of children */ + if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element), + GST_OBJECT_CAST (bin)))) + goto had_parent; + + /* if we add a sink we become a sink */ + if (is_sink && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_SINK)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink", + elem_name); + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SINK); + } + if (is_source && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_SOURCE)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was source", + elem_name); + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SOURCE); + } + if (provides_clock + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_PROVIDE_CLOCK)) { + GST_DEBUG_OBJECT (bin, "element \"%s\" can provide a clock", elem_name); + clock_message = + gst_message_new_clock_provide (GST_OBJECT_CAST (element), NULL, TRUE); + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + } + if (requires_clock + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_REQUIRE_CLOCK)) { + GST_DEBUG_OBJECT (bin, "element \"%s\" requires a clock", elem_name); + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + } + + bin->children = g_list_prepend (bin->children, element); + bin->numchildren++; + bin->children_cookie++; + if (!GST_BIN_IS_NO_RESYNC (bin)) + bin->priv->structure_cookie++; + + /* distribute the bus */ + gst_element_set_bus (element, bin->child_bus); + + /* propagate the current base_time, start_time and clock */ + gst_element_set_base_time (element, GST_ELEMENT_CAST (bin)->base_time); + gst_element_set_start_time (element, GST_ELEMENT_START_TIME (bin)); + /* it's possible that the element did not accept the clock but + * that is not important right now. When the pipeline goes to PLAYING, + * a new clock will be selected */ + gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin)); + + /* get the element's list of contexts before propagating our own */ + elem_contexts = gst_element_get_contexts (element); + for (l = GST_ELEMENT_CAST (bin)->contexts; l; l = l->next) + gst_element_set_context (element, l->data); + + need_context_messages = NULL; + for (l = elem_contexts; l; l = l->next) { + GstContext *replacement, *context = l->data; + const gchar *context_type; + + context_type = gst_context_get_context_type (context); + + /* we already set this context above? */ + replacement = + gst_element_get_context_unlocked (GST_ELEMENT (bin), context_type); + if (replacement) { + gst_context_unref (replacement); + } else { + GstMessage *msg; + GstStructure *s; + + /* ask our parent for the context */ + msg = gst_message_new_need_context (GST_OBJECT_CAST (bin), context_type); + s = (GstStructure *) gst_message_get_structure (msg); + gst_structure_set (s, "bin.old.context", GST_TYPE_CONTEXT, context, NULL); + + need_context_messages = g_list_prepend (need_context_messages, msg); + } + } + +#if 0 + /* set the cached index on the children */ + if (bin->priv->index) + gst_element_set_index (element, bin->priv->index); +#endif + + ret = GST_STATE_RETURN (bin); + /* no need to update the state if we are in error */ + if (ret == GST_STATE_CHANGE_FAILURE) + goto no_state_recalc; + + /* update the bin state, the new element could have been an ASYNC or + * NO_PREROLL element */ + ret = GST_STATE_RETURN (element); + GST_DEBUG_OBJECT (bin, "added %s element", + gst_element_state_change_return_get_name (ret)); + + switch (ret) { + case GST_STATE_CHANGE_ASYNC: + { + /* create message to track this aync element when it posts an async-done + * message */ + async_message = gst_message_new_async_start (GST_OBJECT_CAST (element)); + break; + } + case GST_STATE_CHANGE_NO_PREROLL: + /* ignore all async elements we might have and commit our state */ + bin_handle_async_done (bin, ret, FALSE, GST_CLOCK_TIME_NONE); + break; + case GST_STATE_CHANGE_FAILURE: + break; + default: + break; + } + +no_state_recalc: + GST_OBJECT_UNLOCK (bin); + + for (l = need_context_messages; l; l = l->next) { + GstMessage *msg = l->data; + GstStructure *s; + const gchar *context_type; + GstContext *replacement, *context; + + gst_message_parse_context_type (msg, &context_type); + + GST_LOG_OBJECT (bin, "asking parent for context type: %s " + "from %" GST_PTR_FORMAT, context_type, element); + + s = (GstStructure *) gst_message_get_structure (msg); + gst_structure_get (s, "bin.old.context", GST_TYPE_CONTEXT, &context, NULL); + gst_structure_remove_field (s, "bin.old.context"); + gst_element_post_message (GST_ELEMENT_CAST (bin), msg); + + /* lock to avoid losing a potential write */ + GST_OBJECT_LOCK (bin); + replacement = + gst_element_get_context_unlocked (GST_ELEMENT_CAST (bin), context_type); + + if (replacement) { + /* we got the context set from GstElement::set_context */ + gst_context_unref (replacement); + GST_OBJECT_UNLOCK (bin); + } else { + /* Propagate the element's context upwards */ + GST_LOG_OBJECT (bin, "propagating existing context type: %s %p " + "from %" GST_PTR_FORMAT, context_type, context, element); + + gst_bin_update_context_unlocked (bin, context); + + msg = + gst_message_new_have_context (GST_OBJECT_CAST (bin), + gst_context_ref (context)); + GST_OBJECT_UNLOCK (bin); + gst_element_post_message (GST_ELEMENT_CAST (bin), msg); + } + gst_context_unref (context); + } + g_list_free_full (elem_contexts, (GDestroyNotify) gst_context_unref); + g_list_free (need_context_messages); + + /* post the messages on the bus of the element so that the bin can handle + * them */ + if (clock_message) + gst_element_post_message (element, clock_message); + + if (async_message) + gst_element_post_message (element, async_message); + + /* unlink all linked pads */ + it = gst_element_iterate_pads (element); + while (gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, + NULL) == GST_ITERATOR_RESYNC) + gst_iterator_resync (it); + gst_iterator_free (it); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"", + elem_name); + + g_signal_emit (bin, gst_bin_signals[ELEMENT_ADDED], 0, element); + gst_child_proxy_child_added ((GstChildProxy *) bin, (GObject *) element, + elem_name); + + gst_bin_do_deep_add_remove (bin, gst_bin_signals[DEEP_ELEMENT_ADDED], + "deep-element-added", element); + + g_free (elem_name); + + return TRUE; + + /* ERROR handling here */ +adding_itself: + { + GST_OBJECT_LOCK (bin); + g_warning ("Cannot add bin '%s' to itself", GST_ELEMENT_NAME (bin)); + GST_OBJECT_UNLOCK (bin); + gst_object_ref_sink (element); + gst_object_unref (element); + return FALSE; + } +duplicate_name: + { + g_warning ("Name '%s' is not unique in bin '%s', not adding", + elem_name, GST_ELEMENT_NAME (bin)); + GST_OBJECT_UNLOCK (bin); + g_free (elem_name); + gst_object_ref_sink (element); + gst_object_unref (element); + return FALSE; + } +had_parent: + { + g_warning ("Element '%s' already has parent", elem_name); + GST_OBJECT_UNLOCK (bin); + g_free (elem_name); + return FALSE; + } +} + +/** + * gst_bin_set_suppressed_flags: + * @bin: a #GstBin + * @flags: the #GstElementFlags to suppress + * + * Suppress the given flags on the bin. #GstElementFlags of a + * child element are propagated when it is added to the bin. + * When suppressed flags are set, those specified flags will + * not be propagated to the bin. + * + * MT safe. + * + * Since: 1.10 + */ +void +gst_bin_set_suppressed_flags (GstBin * bin, GstElementFlags flags) +{ + g_return_if_fail (GST_IS_BIN (bin)); + + GST_OBJECT_LOCK (bin); + bin->priv->suppressed_flags = bin->priv->suppressed_flags | flags; + GST_OBJECT_UNLOCK (bin); + + GST_DEBUG_OBJECT (bin, "Set suppressed flags(0x%x) to bin '%s'", flags, + GST_ELEMENT_NAME (bin)); +} + +/** + * gst_bin_get_suppressed_flags: + * @bin: a #GstBin + * + * Return the suppressed flags of the bin. + * + * MT safe. + * + * Returns: the bin's suppressed #GstElementFlags. + * + * Since: 1.10 + */ +GstElementFlags +gst_bin_get_suppressed_flags (GstBin * bin) +{ + GstElementFlags res; + + g_return_val_if_fail (GST_IS_BIN (bin), 0); + + GST_OBJECT_LOCK (bin); + res = bin->priv->suppressed_flags; + GST_OBJECT_UNLOCK (bin); + + return res; +} + +/* signal vfunc, will be called when a new element was added */ +static void +gst_bin_deep_element_added_func (GstBin * bin, GstBin * sub_bin, + GstElement * child) +{ + GstBin *parent_bin; + + parent_bin = (GstBin *) gst_object_get_parent (GST_OBJECT_CAST (bin)); + if (parent_bin == NULL) { + GST_LOG_OBJECT (bin, "no parent, reached top-level"); + return; + } + + GST_LOG_OBJECT (parent_bin, "emitting deep-element-added for element " + "%" GST_PTR_FORMAT " which has just been added to %" GST_PTR_FORMAT, + child, sub_bin); + + g_signal_emit (parent_bin, gst_bin_signals[DEEP_ELEMENT_ADDED], 0, sub_bin, + child); + + gst_object_unref (parent_bin); +} + +/* signal vfunc, will be called when an element was removed */ +static void +gst_bin_deep_element_removed_func (GstBin * bin, GstBin * sub_bin, + GstElement * child) +{ + GstBin *parent_bin; + + parent_bin = (GstBin *) gst_object_get_parent (GST_OBJECT_CAST (bin)); + if (parent_bin == NULL) { + GST_LOG_OBJECT (bin, "no parent, reached top-level"); + return; + } + + GST_LOG_OBJECT (parent_bin, "emitting deep-element-removed for element " + "%" GST_PTR_FORMAT " which has just been removed from %" GST_PTR_FORMAT, + sub_bin, child); + + g_signal_emit (parent_bin, gst_bin_signals[DEEP_ELEMENT_REMOVED], 0, sub_bin, + child); + + gst_object_unref (parent_bin); +} + +/** + * gst_bin_add: + * @bin: a #GstBin + * @element: (transfer floating): the #GstElement to add + * + * Adds the given element to the bin. Sets the element's parent, and thus + * takes ownership of the element. An element can only be added to one bin. + * + * If the element's pads are linked to other pads, the pads will be unlinked + * before the element is added to the bin. + * + * > When you add an element to an already-running pipeline, you will have to + * > take care to set the state of the newly-added element to the desired + * > state (usually PLAYING or PAUSED, same you set the pipeline to originally) + * > with gst_element_set_state(), or use gst_element_sync_state_with_parent(). + * > The bin or pipeline will not take care of this for you. + * + * MT safe. + * + * Returns: %TRUE if the element could be added, %FALSE if + * the bin does not want to accept the element. + */ +gboolean +gst_bin_add (GstBin * bin, GstElement * element) +{ + GstBinClass *bclass; + gboolean result; + + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (GST_ELEMENT_CAST (bin) != element, FALSE); + + bclass = GST_BIN_GET_CLASS (bin); + + if (G_UNLIKELY (bclass->add_element == NULL)) + goto no_function; + + GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s", + GST_STR_NULL (GST_ELEMENT_NAME (element)), + GST_STR_NULL (GST_ELEMENT_NAME (bin))); + + GST_TRACER_BIN_ADD_PRE (bin, element); + result = bclass->add_element (bin, element); + GST_TRACER_BIN_ADD_POST (bin, element, result); + + return result; + + /* ERROR handling */ +no_function: + { + g_warning ("adding elements to bin '%s' is not supported", + GST_ELEMENT_NAME (bin)); + gst_object_ref_sink (element); + gst_object_unref (element); + return FALSE; + } +} + +/* remove an element from the bin + * + * MT safe + */ +static gboolean +gst_bin_remove_func (GstBin * bin, GstElement * element) +{ + gchar *elem_name; + GstIterator *it; + gboolean is_sink, is_source, provides_clock, requires_clock; + gboolean othersink, othersource, otherprovider, otherrequirer, found; + GstMessage *clock_message = NULL; + GstClock **provided_clock_p; + GstElement **clock_provider_p; + GList *walk, *next; + gboolean other_async, this_async, have_no_preroll; + GstStateChangeReturn ret; + + GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element)); + + /* we obviously can't remove ourself from ourself */ + if (G_UNLIKELY (element == GST_ELEMENT_CAST (bin))) + goto removing_itself; + + GST_OBJECT_LOCK (bin); + + GST_OBJECT_LOCK (element); + elem_name = g_strdup (GST_ELEMENT_NAME (element)); + + if (GST_OBJECT_PARENT (element) != GST_OBJECT_CAST (bin)) + goto not_in_bin; + + /* remove the parent ref */ + GST_OBJECT_PARENT (element) = NULL; + + /* grab element name so we can print it */ + is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK); + is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE); + provides_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + requires_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + GST_OBJECT_UNLOCK (element); + + found = FALSE; + othersink = FALSE; + othersource = FALSE; + otherprovider = FALSE; + otherrequirer = FALSE; + have_no_preroll = FALSE; + /* iterate the elements, we collect which ones are async and no_preroll. We + * also remove the element when we find it. */ + for (walk = bin->children; walk; walk = next) { + GstElement *child = GST_ELEMENT_CAST (walk->data); + + next = g_list_next (walk); + + if (child == element) { + found = TRUE; + /* remove the element */ + bin->children = g_list_delete_link (bin->children, walk); + } else { + gboolean child_sink, child_source, child_provider, child_requirer; + + GST_OBJECT_LOCK (child); + child_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK); + child_source = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE); + child_provider = + GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + child_requirer = + GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + /* when we remove a sink, check if there are other sinks. */ + if (is_sink && !othersink && child_sink) + othersink = TRUE; + if (is_source && !othersource && child_source) + othersource = TRUE; + if (provides_clock && !otherprovider && child_provider) + otherprovider = TRUE; + if (requires_clock && !otherrequirer && child_requirer) + otherrequirer = TRUE; + /* check if we have NO_PREROLL children */ + if (GST_STATE_RETURN (child) == GST_STATE_CHANGE_NO_PREROLL) + have_no_preroll = TRUE; + GST_OBJECT_UNLOCK (child); + } + } + + /* the element must have been in the bin's list of children */ + if (G_UNLIKELY (!found)) + goto not_in_bin; + + /* we now removed the element from the list of elements, increment the cookie + * so that others can detect a change in the children list. */ + bin->numchildren--; + bin->children_cookie++; + if (!GST_BIN_IS_NO_RESYNC (bin)) + bin->priv->structure_cookie++; + + if (is_sink && !othersink + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_SINK)) { + /* we're not a sink anymore */ + GST_DEBUG_OBJECT (bin, "we removed the last sink"); + GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SINK); + } + if (is_source && !othersource + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_SOURCE)) { + /* we're not a source anymore */ + GST_DEBUG_OBJECT (bin, "we removed the last source"); + GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SOURCE); + } + if (provides_clock && !otherprovider + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_PROVIDE_CLOCK)) { + /* we're not a clock provider anymore */ + GST_DEBUG_OBJECT (bin, "we removed the last clock provider"); + GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + } + if (requires_clock && !otherrequirer + && !(bin->priv->suppressed_flags & GST_ELEMENT_FLAG_REQUIRE_CLOCK)) { + /* we're not a clock requirer anymore */ + GST_DEBUG_OBJECT (bin, "we removed the last clock requirer"); + GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + } + + /* if the clock provider for this element is removed, we lost + * the clock as well, we need to inform the parent of this + * so that it can select a new clock */ + if (bin->clock_provider == element) { + GST_DEBUG_OBJECT (bin, "element \"%s\" provided the clock", elem_name); + bin->clock_dirty = TRUE; + clock_message = + gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock); + provided_clock_p = &bin->provided_clock; + clock_provider_p = &bin->clock_provider; + gst_object_replace ((GstObject **) provided_clock_p, NULL); + gst_object_replace ((GstObject **) clock_provider_p, NULL); + } + + /* remove messages for the element, if there was a pending ASYNC_START + * message we must see if removing the element caused the bin to lose its + * async state. */ + this_async = FALSE; + other_async = FALSE; + for (walk = bin->messages; walk; walk = next) { + GstMessage *message = (GstMessage *) walk->data; + GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message)); + gboolean remove; + + next = g_list_next (walk); + remove = FALSE; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ASYNC_START: + if (src == element) + this_async = TRUE; + else + other_async = TRUE; + + GST_DEBUG_OBJECT (src, "looking at message %p", message); + break; + case GST_MESSAGE_STRUCTURE_CHANGE: + { + GstElement *owner; + + GST_DEBUG_OBJECT (src, "looking at structure change message %p", + message); + /* it's unlikely that this message is still in the list of messages + * because this would mean that a link/unlink is busy in another thread + * while we remove the element. We still have to remove the message + * because we might not receive the done message anymore when the element + * is removed from the bin. */ + gst_message_parse_structure_change (message, NULL, &owner, NULL); + if (owner == element) + remove = TRUE; + break; + } + default: + break; + } + if (src == element) + remove = TRUE; + + if (remove) { + /* delete all message types */ + GST_DEBUG_OBJECT (src, "deleting message %p of element \"%s\"", + message, elem_name); + bin->messages = g_list_delete_link (bin->messages, walk); + gst_message_unref (message); + } + } + + /* get last return */ + ret = GST_STATE_RETURN (bin); + + /* no need to update the state if we are in error */ + if (ret == GST_STATE_CHANGE_FAILURE) + goto no_state_recalc; + + if (!other_async && this_async) { + /* all other elements were not async and we removed the async one, + * handle the async-done case because we are not async anymore now. */ + GST_DEBUG_OBJECT (bin, + "we removed the last async element, have no_preroll %d", + have_no_preroll); + + /* the current state return of the bin depends on if there are no_preroll + * elements in the pipeline or not */ + if (have_no_preroll) + ret = GST_STATE_CHANGE_NO_PREROLL; + else + ret = GST_STATE_CHANGE_SUCCESS; + + bin_handle_async_done (bin, ret, FALSE, GST_CLOCK_TIME_NONE); + } else { + GST_DEBUG_OBJECT (bin, + "recalc state preroll: %d, other async: %d, this async %d", + have_no_preroll, other_async, this_async); + + if (have_no_preroll) { + ret = GST_STATE_CHANGE_NO_PREROLL; + } else if (other_async) { + /* there are other async elements and we were not doing an async state + * change, change our pending state and go async */ + if (GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING) { + GST_STATE_NEXT (bin) = GST_STATE (bin); + GST_STATE_PENDING (bin) = GST_STATE (bin); + } + ret = GST_STATE_CHANGE_ASYNC; + } + GST_STATE_RETURN (bin) = ret; + } +no_state_recalc: + /* clear bus */ + gst_element_set_bus (element, NULL); + /* Clear the clock we provided to the element */ + gst_element_set_clock (element, NULL); + GST_OBJECT_UNLOCK (bin); + + if (clock_message) + gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message); + + /* unlink all linked pads */ + it = gst_element_iterate_pads (element); + while (gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, + NULL) == GST_ITERATOR_RESYNC) + gst_iterator_resync (it); + gst_iterator_free (it); + + GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"", + elem_name); + + g_signal_emit (bin, gst_bin_signals[ELEMENT_REMOVED], 0, element); + gst_child_proxy_child_removed ((GstChildProxy *) bin, (GObject *) element, + elem_name); + + gst_bin_do_deep_add_remove (bin, gst_bin_signals[DEEP_ELEMENT_REMOVED], + "deep-element-removed", element); + + g_free (elem_name); + /* element is really out of our control now */ + gst_object_unref (element); + + return TRUE; + + /* ERROR handling */ +removing_itself: + { + GST_OBJECT_LOCK (bin); + g_warning ("Cannot remove bin '%s' from itself", GST_ELEMENT_NAME (bin)); + GST_OBJECT_UNLOCK (bin); + return FALSE; + } +not_in_bin: + { + g_warning ("Element '%s' is not in bin '%s'", elem_name, + GST_ELEMENT_NAME (bin)); + GST_OBJECT_UNLOCK (element); + GST_OBJECT_UNLOCK (bin); + g_free (elem_name); + return FALSE; + } +} + +/** + * gst_bin_remove: + * @bin: a #GstBin + * @element: (transfer none): the #GstElement to remove + * + * Removes the element from the bin, unparenting it as well. + * Unparenting the element means that the element will be dereferenced, + * so if the bin holds the only reference to the element, the element + * will be freed in the process of removing it from the bin. If you + * want the element to still exist after removing, you need to call + * gst_object_ref() before removing it from the bin. + * + * If the element's pads are linked to other pads, the pads will be unlinked + * before the element is removed from the bin. + * + * MT safe. + * + * Returns: %TRUE if the element could be removed, %FALSE if + * the bin does not want to remove the element. + */ +gboolean +gst_bin_remove (GstBin * bin, GstElement * element) +{ + GstBinClass *bclass; + gboolean result; + + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (GST_ELEMENT_CAST (bin) != element, FALSE); + + bclass = GST_BIN_GET_CLASS (bin); + + if (G_UNLIKELY (bclass->remove_element == NULL)) + goto no_function; + + GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s", + GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)); + + GST_TRACER_BIN_REMOVE_PRE (bin, element); + result = bclass->remove_element (bin, element); + GST_TRACER_BIN_REMOVE_POST (bin, result); + + return result; + + /* ERROR handling */ +no_function: + { + g_warning ("removing elements from bin '%s' is not supported", + GST_ELEMENT_NAME (bin)); + return FALSE; + } +} + +/** + * gst_bin_iterate_elements: + * @bin: a #GstBin + * + * Gets an iterator for the elements in this bin. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement, + * or %NULL + */ +GstIterator * +gst_bin_iterate_elements (GstBin * bin) +{ + GstIterator *result; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + GST_OBJECT_LOCK (bin); + result = gst_iterator_new_list (GST_TYPE_ELEMENT, + GST_OBJECT_GET_LOCK (bin), + &bin->children_cookie, &bin->children, (GObject *) bin, NULL); + GST_OBJECT_UNLOCK (bin); + + return result; +} + +static GstIteratorItem +iterate_child_recurse (GstIterator * it, const GValue * item) +{ + GstElement *child = g_value_get_object (item); + + if (GST_IS_BIN (child)) { + GstIterator *other = gst_bin_iterate_recurse (GST_BIN_CAST (child)); + + gst_iterator_push (it, other); + } + return GST_ITERATOR_ITEM_PASS; +} + +/** + * gst_bin_iterate_recurse: + * @bin: a #GstBin + * + * Gets an iterator for the elements in this bin. + * This iterator recurses into GstBin children. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement, + * or %NULL + */ +GstIterator * +gst_bin_iterate_recurse (GstBin * bin) +{ + GstIterator *result; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + GST_OBJECT_LOCK (bin); + result = gst_iterator_new_list (GST_TYPE_ELEMENT, + GST_OBJECT_GET_LOCK (bin), + &bin->children_cookie, + &bin->children, + (GObject *) bin, (GstIteratorItemFunction) iterate_child_recurse); + GST_OBJECT_UNLOCK (bin); + + return result; +} + +/* returns 0 when TRUE because this is a GCompareFunc */ +/* MT safe */ +static gint +bin_element_is_sink (GstElement * child, GstBin * bin) +{ + gboolean is_sink; + + /* we lock the child here for the remainder of the function to + * get its name and flag safely. */ + GST_OBJECT_LOCK (child); + is_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not"); + + GST_OBJECT_UNLOCK (child); + return is_sink ? 0 : 1; +} + +static gint +sink_iterator_filter (const GValue * vchild, GValue * vbin) +{ + GstBin *bin = g_value_get_object (vbin); + GstElement *child = g_value_get_object (vchild); + + return (bin_element_is_sink (child, bin)); +} + +/** + * gst_bin_iterate_sinks: + * @bin: a #GstBin + * + * Gets an iterator for all elements in the bin that have the + * #GST_ELEMENT_FLAG_SINK flag set. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement, + * or %NULL + */ +GstIterator * +gst_bin_iterate_sinks (GstBin * bin) +{ + GstIterator *children; + GstIterator *result; + GValue vbin = { 0, }; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + g_value_init (&vbin, GST_TYPE_BIN); + g_value_set_object (&vbin, bin); + + children = gst_bin_iterate_elements (bin); + result = gst_iterator_filter (children, + (GCompareFunc) sink_iterator_filter, &vbin); + + g_value_unset (&vbin); + + return result; +} + +/* returns 0 when TRUE because this is a GCompareFunc */ +/* MT safe */ +static gint +bin_element_is_src (GstElement * child, GstBin * bin) +{ + gboolean is_src; + + /* we lock the child here for the remainder of the function to + * get its name and other info safely. */ + GST_OBJECT_LOCK (child); + is_src = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not"); + + GST_OBJECT_UNLOCK (child); + return is_src ? 0 : 1; +} + +static gint +src_iterator_filter (const GValue * vchild, GValue * vbin) +{ + GstBin *bin = g_value_get_object (vbin); + GstElement *child = g_value_get_object (vchild); + + return (bin_element_is_src (child, bin)); +} + +/** + * gst_bin_iterate_sources: + * @bin: a #GstBin + * + * Gets an iterator for all elements in the bin that have the + * #GST_ELEMENT_FLAG_SOURCE flag set. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement, + * or %NULL + */ +GstIterator * +gst_bin_iterate_sources (GstBin * bin) +{ + GstIterator *children; + GstIterator *result; + GValue vbin = { 0, }; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + g_value_init (&vbin, GST_TYPE_BIN); + g_value_set_object (&vbin, bin); + + children = gst_bin_iterate_elements (bin); + result = gst_iterator_filter (children, + (GCompareFunc) src_iterator_filter, &vbin); + + g_value_unset (&vbin); + + return result; +} + +/* + * MT safe + */ +static GstStateChangeReturn +gst_bin_get_state_func (GstElement * element, GstState * state, + GstState * pending, GstClockTime timeout) +{ + GstStateChangeReturn ret; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state"); + + ret = + GST_ELEMENT_CLASS (parent_class)->get_state (element, state, pending, + timeout); + + return ret; +} + +/*********************************************** + * Topologically sorted iterator + * see http://en.wikipedia.org/wiki/Topological_sorting + * + * For each element in the graph, an entry is kept in a HashTable + * with its number of srcpad connections (degree). + * We then change state of all elements without dependencies + * (degree 0) and decrement the degree of all elements connected + * on the sinkpads. When an element reaches degree 0, its state is + * changed next. + * When all elements are handled the algorithm stops. + */ +typedef struct _GstBinSortIterator +{ + GstIterator it; + GQueue queue; /* elements queued for state change */ + GstBin *bin; /* bin we iterate */ + gint mode; /* adding or removing dependency */ + GstElement *best; /* next element with least dependencies */ + gint best_deg; /* best degree */ + GHashTable *hash; /* hashtable with element dependencies */ + gboolean dirty; /* we detected structure change */ +} GstBinSortIterator; + +static void +copy_to_queue (gpointer data, gpointer user_data) +{ + GstElement *element = data; + GQueue *queue = user_data; + + gst_object_ref (element); + g_queue_push_tail (queue, element); +} + +static void +gst_bin_sort_iterator_copy (const GstBinSortIterator * it, + GstBinSortIterator * copy) +{ + GHashTableIter iter; + gpointer key, value; + + g_queue_init (©->queue); + g_queue_foreach ((GQueue *) & it->queue, copy_to_queue, ©->queue); + + copy->bin = gst_object_ref (it->bin); + if (it->best) + copy->best = gst_object_ref (it->best); + + copy->hash = g_hash_table_new (NULL, NULL); + g_hash_table_iter_init (&iter, it->hash); + while (g_hash_table_iter_next (&iter, &key, &value)) + g_hash_table_insert (copy->hash, key, value); +} + +/* we add and subtract 1 to make sure we don't confuse NULL and 0 */ +#define HASH_SET_DEGREE(bit, elem, deg) \ + g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1)) +#define HASH_GET_DEGREE(bit, elem) \ + (GPOINTER_TO_INT(g_hash_table_lookup (bit->hash, elem))-1) + +/* add element to queue of next elements in the iterator. + * We push at the tail to give higher priority elements a + * chance first */ +static void +add_to_queue (GstBinSortIterator * bit, GstElement * element) +{ + GST_DEBUG_OBJECT (bit->bin, "adding '%s' to queue", + GST_ELEMENT_NAME (element)); + gst_object_ref (element); + g_queue_push_tail (&bit->queue, element); + HASH_SET_DEGREE (bit, element, -1); +} + +static void +remove_from_queue (GstBinSortIterator * bit, GstElement * element) +{ + GList *find; + + if ((find = g_queue_find (&bit->queue, element))) { + GST_DEBUG_OBJECT (bit->bin, "removing '%s' from queue", + GST_ELEMENT_NAME (element)); + + g_queue_delete_link (&bit->queue, find); + gst_object_unref (element); + } else { + GST_DEBUG_OBJECT (bit->bin, "unable to remove '%s' from queue", + GST_ELEMENT_NAME (element)); + } +} + +/* clear the queue, unref all objects as we took a ref when + * we added them to the queue */ +static void +clear_queue (GQueue * queue) +{ + gpointer p; + + while ((p = g_queue_pop_head (queue))) + gst_object_unref (p); +} + +/* set all degrees to 0. Elements marked as a sink are + * added to the queue immediately. Since we only look at the SINK flag of the + * element, it is possible that we add non-sinks to the queue. These will be + * removed from the queue again when we can prove that it provides data for some + * other element. */ +static void +reset_degree (GstElement * element, GstBinSortIterator * bit) +{ + gboolean is_sink; + + /* sinks are added right away */ + GST_OBJECT_LOCK (element); + is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK); + GST_OBJECT_UNLOCK (element); + + if (is_sink) { + add_to_queue (bit, element); + } else { + /* others are marked with 0 and handled when sinks are done */ + HASH_SET_DEGREE (bit, element, 0); + } +} + +/* adjust the degree of all elements connected to the given + * element. If a degree of an element drops to 0, it is + * added to the queue of elements to schedule next. + * + * We have to make sure not to cross the bin boundary this element + * belongs to. + */ +static void +update_degree (GstElement * element, GstBinSortIterator * bit) +{ + gboolean linked = FALSE; + + GST_OBJECT_LOCK (element); + /* don't touch degree if element has no sinkpads */ + if (element->numsinkpads != 0) { + /* loop over all sinkpads, decrement degree for all connected + * elements in this bin */ + GList *pads; + + for (pads = element->sinkpads; pads; pads = g_list_next (pads)) { + GstPad *pad, *peer; + + pad = GST_PAD_CAST (pads->data); + + /* we're iterating over the sinkpads, check if it's busy in a link/unlink */ + if (G_UNLIKELY (find_message (bit->bin, GST_OBJECT_CAST (pad), + GST_MESSAGE_STRUCTURE_CHANGE))) { + /* mark the iterator as dirty because we won't be updating the degree + * of the peer parent now. This would result in the 'loop detected' + * later on because the peer parent element could become the best next + * element with a degree > 0. We will simply continue our state + * changes and we'll eventually resync when the unlink completed and + * the iterator cookie is updated. */ + bit->dirty = TRUE; + continue; + } + + if ((peer = gst_pad_get_peer (pad))) { + GstElement *peer_element; + + if ((peer_element = gst_pad_get_parent_element (peer))) { + GST_OBJECT_LOCK (peer_element); + /* check that we don't go outside of this bin */ + if (GST_OBJECT_CAST (peer_element)->parent == + GST_OBJECT_CAST (bit->bin)) { + gint old_deg, new_deg; + + old_deg = HASH_GET_DEGREE (bit, peer_element); + + /* check to see if we added an element as sink that was not really a + * sink because it was connected to some other element. */ + if (old_deg == -1) { + remove_from_queue (bit, peer_element); + old_deg = 0; + } + new_deg = old_deg + bit->mode; + + GST_DEBUG_OBJECT (bit->bin, + "change element %s, degree %d->%d, linked to %s", + GST_ELEMENT_NAME (peer_element), old_deg, new_deg, + GST_ELEMENT_NAME (element)); + + /* update degree, it is possible that an element was in 0 and + * reaches -1 here. This would mean that the element had no sinkpads + * but became linked while the state change was happening. We will + * resync on this with the structure change message. */ + if (new_deg == 0) { + /* degree hit 0, add to queue */ + add_to_queue (bit, peer_element); + } else { + HASH_SET_DEGREE (bit, peer_element, new_deg); + } + linked = TRUE; + } + GST_OBJECT_UNLOCK (peer_element); + gst_object_unref (peer_element); + } + gst_object_unref (peer); + } + } + } + if (!linked) { + GST_DEBUG_OBJECT (bit->bin, "element %s not linked on any sinkpads", + GST_ELEMENT_NAME (element)); + } + GST_OBJECT_UNLOCK (element); +} + +/* find the next best element not handled yet. This is the one + * with the lowest non-negative degree */ +static void +find_element (GstElement * element, GstBinSortIterator * bit) +{ + gint degree; + + /* element is already handled */ + if ((degree = HASH_GET_DEGREE (bit, element)) < 0) + return; + + /* first element or element with smaller degree */ + if (bit->best == NULL || bit->best_deg > degree) { + bit->best = element; + bit->best_deg = degree; + } else if (bit->best_deg == degree + && GST_OBJECT_FLAG_IS_SET (bit->best, GST_ELEMENT_FLAG_SOURCE) + && !GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE)) { + /* If two elements have the same degree, we want to ensure we + * return non-source elements first. */ + bit->best = element; + } +} + +/* get next element in iterator. */ +static GstIteratorResult +gst_bin_sort_iterator_next (GstBinSortIterator * bit, GValue * result) +{ + GstElement *best; + GstBin *bin = bit->bin; + + /* empty queue, we have to find a next best element */ + if (g_queue_is_empty (&bit->queue)) { + bit->best = NULL; + bit->best_deg = G_MAXINT; + g_list_foreach (bin->children, (GFunc) find_element, bit); + if ((best = bit->best)) { + /* when we detected an unlink, don't warn because our degrees might be + * screwed up. We will resync later */ + if (bit->best_deg != 0 && !bit->dirty) { + /* we don't fail on this one yet */ + GST_WARNING_OBJECT (bin, "loop dected in graph"); + g_warning ("loop detected in the graph of bin '%s'!!", + GST_ELEMENT_NAME (bin)); + } + /* best unhandled element, schedule as next element */ + GST_DEBUG_OBJECT (bin, "queue empty, next best: %s", + GST_ELEMENT_NAME (best)); + HASH_SET_DEGREE (bit, best, -1); + g_value_set_object (result, best); + } else { + GST_DEBUG_OBJECT (bin, "queue empty, elements exhausted"); + /* no more unhandled elements, we are done */ + return GST_ITERATOR_DONE; + } + } else { + /* everything added to the queue got reffed */ + best = g_queue_pop_head (&bit->queue); + g_value_set_object (result, best); + gst_object_unref (best); + } + + GST_DEBUG_OBJECT (bin, "queue head gives %s", GST_ELEMENT_NAME (best)); + /* update degrees of linked elements */ + update_degree (best, bit); + + return GST_ITERATOR_OK; +} + +/* clear queues, recalculate the degrees and restart. */ +static void +gst_bin_sort_iterator_resync (GstBinSortIterator * bit) +{ + GstBin *bin = bit->bin; + + GST_DEBUG_OBJECT (bin, "resync"); + bit->dirty = FALSE; + clear_queue (&bit->queue); + /* reset degrees */ + g_list_foreach (bin->children, (GFunc) reset_degree, bit); + /* calc degrees, incrementing */ + bit->mode = 1; + g_list_foreach (bin->children, (GFunc) update_degree, bit); + /* for the rest of the function we decrement the degrees */ + bit->mode = -1; +} + +/* clear queues, unref bin and free iterator. */ +static void +gst_bin_sort_iterator_free (GstBinSortIterator * bit) +{ + GstBin *bin = bit->bin; + + GST_DEBUG_OBJECT (bin, "free"); + clear_queue (&bit->queue); + g_hash_table_destroy (bit->hash); + gst_object_unref (bin); +} + +/* should be called with the bin LOCK held */ +static GstIterator * +gst_bin_sort_iterator_new (GstBin * bin) +{ + GstBinSortIterator *result; + + /* we don't need an ItemFunction because we ref the items in the _next + * method already */ + result = (GstBinSortIterator *) + gst_iterator_new (sizeof (GstBinSortIterator), + GST_TYPE_ELEMENT, + GST_OBJECT_GET_LOCK (bin), + &bin->priv->structure_cookie, + (GstIteratorCopyFunction) gst_bin_sort_iterator_copy, + (GstIteratorNextFunction) gst_bin_sort_iterator_next, + (GstIteratorItemFunction) NULL, + (GstIteratorResyncFunction) gst_bin_sort_iterator_resync, + (GstIteratorFreeFunction) gst_bin_sort_iterator_free); + g_queue_init (&result->queue); + result->hash = g_hash_table_new (NULL, NULL); + gst_object_ref (bin); + result->bin = bin; + gst_bin_sort_iterator_resync (result); + + return (GstIterator *) result; +} + +/** + * gst_bin_iterate_sorted: + * @bin: a #GstBin + * + * Gets an iterator for the elements in this bin in topologically + * sorted order. This means that the elements are returned from + * the most downstream elements (sinks) to the sources. + * + * This function is used internally to perform the state changes + * of the bin elements and for clock selection. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement, + * or %NULL + */ +GstIterator * +gst_bin_iterate_sorted (GstBin * bin) +{ + GstIterator *result; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + GST_OBJECT_LOCK (bin); + result = gst_bin_sort_iterator_new (bin); + GST_OBJECT_UNLOCK (bin); + + return result; +} + +static GstStateChangeReturn +gst_bin_element_set_state (GstBin * bin, GstElement * element, + GstClockTime base_time, GstClockTime start_time, GstState current, + GstState next) +{ + GstStateChangeReturn ret; + GstState child_current, child_pending; + gboolean locked; + GList *found; + + GST_STATE_LOCK (element); + + GST_OBJECT_LOCK (element); + /* set base_time and start time on child */ + GST_ELEMENT_START_TIME (element) = start_time; + element->base_time = base_time; + /* peel off the locked flag */ + locked = GST_ELEMENT_IS_LOCKED_STATE (element); + /* Get the previous set_state result to preserve NO_PREROLL and ASYNC */ + ret = GST_STATE_RETURN (element); + child_current = GST_STATE (element); + child_pending = GST_STATE_PENDING (element); + GST_OBJECT_UNLOCK (element); + + /* skip locked elements */ + if (G_UNLIKELY (locked)) + goto locked; + + /* if the element was no preroll, just start changing the state regardless + * if it had async elements (in the case of a bin) because they won't preroll + * anyway. */ + if (G_UNLIKELY (ret == GST_STATE_CHANGE_NO_PREROLL)) { + GST_DEBUG_OBJECT (element, "element is NO_PREROLL, ignore async elements"); + goto no_preroll; + } + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "current %s pending %s, desired next %s", + gst_element_state_get_name (child_current), + gst_element_state_get_name (child_pending), + gst_element_state_get_name (next)); + + /* always recurse into bins so that we can set the base time */ + if (GST_IS_BIN (element)) + goto do_state; + + /* Try not to change the state of elements that are already in the state we're + * going to */ + if (child_current == next && child_pending == GST_STATE_VOID_PENDING) { + /* child is already at the requested state, return previous return. Note that + * if the child has a pending state to next, we will still call the + * set_state function */ + goto unneeded; + } else if (next > current) { + /* upward state change */ + if (child_pending == GST_STATE_VOID_PENDING) { + /* .. and the child is not busy doing anything */ + if (child_current > next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else if (child_pending > child_current) { + /* .. and the child is busy going upwards */ + if (child_current >= next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else { + /* .. and the child is busy going downwards */ + if (child_current > next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } + } else if (next < current) { + /* downward state change */ + if (child_pending == GST_STATE_VOID_PENDING) { + /* .. and the child is not busy doing anything */ + if (child_current < next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else if (child_pending < child_current) { + /* .. and the child is busy going downwards */ + if (child_current <= next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else { + /* .. and the child is busy going upwards */ + if (child_current < next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } + } + +do_state: + GST_OBJECT_LOCK (bin); + /* the element was busy with an upwards async state change, we must wait for + * an ASYNC_DONE message before we attemp to change the state. */ + if ((found = + find_message (bin, GST_OBJECT_CAST (element), + GST_MESSAGE_ASYNC_START))) { +#ifndef GST_DISABLE_GST_DEBUG + GstMessage *message = GST_MESSAGE_CAST (found->data); + + GST_DEBUG_OBJECT (element, "element message %p, %s async busy", + message, GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))); +#endif + /* only wait for upward state changes */ + if (next > current) { + /* We found an async element check if we can force its state to change or + * if we have to wait for it to preroll. */ + goto was_busy; + } + } + GST_OBJECT_UNLOCK (bin); + +no_preroll: + GST_DEBUG_OBJECT (bin, + "setting element %s to %s, base_time %" GST_TIME_FORMAT, + GST_ELEMENT_NAME (element), gst_element_state_get_name (next), + GST_TIME_ARGS (base_time)); + + /* change state */ + ret = gst_element_set_state (element, next); + + GST_STATE_UNLOCK (element); + + return ret; + +locked: + { + GST_DEBUG_OBJECT (element, + "element is locked, return previous return %s", + gst_element_state_change_return_get_name (ret)); + GST_STATE_UNLOCK (element); + return ret; + } +unneeded: + { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "skipping transition from %s to %s", + gst_element_state_get_name (child_current), + gst_element_state_get_name (next)); + GST_STATE_UNLOCK (element); + return ret; + } +was_busy: + { + GST_DEBUG_OBJECT (element, "element was busy, delaying state change"); + GST_OBJECT_UNLOCK (bin); + GST_STATE_UNLOCK (element); + return GST_STATE_CHANGE_ASYNC; + } +} + +/* gst_iterator_fold functions for pads_activate + * Stop the iterator if activating one pad failed, but only if that pad + * has not been removed from the element. */ +static gboolean +activate_pads (const GValue * vpad, GValue * ret, gboolean * active) +{ + GstPad *pad = g_value_get_object (vpad); + gboolean cont = TRUE; + + if (!gst_pad_set_active (pad, *active)) { + if (GST_PAD_PARENT (pad) != NULL) { + cont = FALSE; + g_value_set_boolean (ret, FALSE); + } + } + + return cont; +} + +/* returns false on error or early cutout of the fold, true if all + * pads in @iter were (de)activated successfully. */ +static gboolean +iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data) +{ + GstIteratorResult ires; + GValue ret = { 0 }; + + /* no need to unset this later, it's just a boolean */ + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, TRUE); + + while (1) { + ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) activate_pads, + &ret, user_data); + switch (ires) { + case GST_ITERATOR_RESYNC: + /* need to reset the result again */ + g_value_set_boolean (&ret, TRUE); + gst_iterator_resync (iter); + break; + case GST_ITERATOR_DONE: + /* all pads iterated, return collected value */ + goto done; + default: + /* iterator returned _ERROR or premature end with _OK, + * mark an error and exit */ + g_value_set_boolean (&ret, FALSE); + goto done; + } + } +done: + /* return collected value */ + return g_value_get_boolean (&ret); +} + +/* is called with STATE_LOCK + */ +static gboolean +gst_bin_src_pads_activate (GstBin * bin, gboolean active) +{ + GstIterator *iter; + gboolean fold_ok; + + GST_DEBUG_OBJECT (bin, "%s pads", active ? "activate" : "deactivate"); + + iter = gst_element_iterate_src_pads ((GstElement *) bin); + fold_ok = iterator_activate_fold_with_resync (iter, &active); + gst_iterator_free (iter); + if (G_UNLIKELY (!fold_ok)) + goto failed; + + GST_DEBUG_OBJECT (bin, "pad %sactivation successful", active ? "" : "de"); + + return TRUE; + + /* ERRORS */ +failed: + { + GST_DEBUG_OBJECT (bin, "pad %sactivation failed", active ? "" : "de"); + return FALSE; + } +} + +/** + * gst_bin_recalculate_latency: + * @bin: a #GstBin + * + * Query @bin for the current latency using and reconfigures this latency to all the + * elements with a LATENCY event. + * + * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY + * is posted on the bus. + * + * This function simply emits the 'do-latency' signal so any custom latency + * calculations will be performed. + * + * Returns: %TRUE if the latency could be queried and reconfigured. + */ +gboolean +gst_bin_recalculate_latency (GstBin * bin) +{ + gboolean res; + + g_signal_emit (bin, gst_bin_signals[DO_LATENCY], 0, &res); + GST_DEBUG_OBJECT (bin, "latency returned %d", res); + + return res; +} + +static gboolean +gst_bin_do_latency_func (GstBin * bin) +{ + GstQuery *query; + GstElement *element; + GstClockTime min_latency, max_latency; + gboolean res; + + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + + element = GST_ELEMENT_CAST (bin); + + GST_DEBUG_OBJECT (element, "querying latency"); + + query = gst_query_new_latency (); + if ((res = gst_element_query (element, query))) { + gboolean live; + + gst_query_parse_latency (query, &live, &min_latency, &max_latency); + + GST_DEBUG_OBJECT (element, + "got min latency %" GST_TIME_FORMAT ", max latency %" + GST_TIME_FORMAT ", live %d", GST_TIME_ARGS (min_latency), + GST_TIME_ARGS (max_latency), live); + + if (max_latency < min_latency) { + /* this is an impossible situation, some parts of the pipeline might not + * work correctly. We post a warning for now. */ + GST_ELEMENT_WARNING (element, CORE, CLOCK, (NULL), + ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %" + GST_TIME_FORMAT ". Add queues or other buffering elements.", + GST_TIME_ARGS (max_latency), GST_TIME_ARGS (min_latency))); + } + + /* configure latency on elements */ + res = gst_element_send_event (element, gst_event_new_latency (min_latency)); + if (res) { + GST_INFO_OBJECT (element, "configured latency of %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency)); + } else { + GST_WARNING_OBJECT (element, + "did not really configure latency of %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency)); + } + } else { + /* this is not a real problem, we just don't configure any latency. */ + GST_WARNING_OBJECT (element, "failed to query latency"); + } + gst_query_unref (query); + + return res; +} + +static gboolean +gst_bin_post_message (GstElement * element, GstMessage * msg) +{ + GstElementClass *pklass = (GstElementClass *) parent_class; + gboolean ret; + + ret = pklass->post_message (element, gst_message_ref (msg)); + + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_SRC (msg) == GST_OBJECT_CAST (element)) { + GstState newstate, pending; + + gst_message_parse_state_changed (msg, NULL, &newstate, &pending); + if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING) { + GST_BIN_CAST (element)->priv->posted_playing = TRUE; + bin_do_eos (GST_BIN_CAST (element)); + } else { + GST_BIN_CAST (element)->priv->posted_playing = FALSE; + } + } + + gst_message_unref (msg); + + return ret; +} + +static void +reset_state (const GValue * data, gpointer user_data) +{ + GstElement *e = g_value_get_object (data); + GstState state = GPOINTER_TO_INT (user_data); + + if (gst_element_set_state (e, state) == GST_STATE_CHANGE_FAILURE) + GST_WARNING_OBJECT (e, "Failed to switch back down to %s", + gst_element_state_get_name (state)); +} + +static GstStateChangeReturn +gst_bin_change_state_func (GstElement * element, GstStateChange transition) +{ + GstBin *bin; + GstStateChangeReturn ret; + GstState current, next; + gboolean have_async; + gboolean have_no_preroll; + GstClockTime base_time, start_time; + GstIterator *it; + gboolean done; + GValue data = { 0, }; + + /* we don't need to take the STATE_LOCK, it is already taken */ + current = (GstState) GST_STATE_TRANSITION_CURRENT (transition); + next = (GstState) GST_STATE_TRANSITION_NEXT (transition); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "changing state of children from %s to %s", + gst_element_state_get_name (current), gst_element_state_get_name (next)); + + bin = GST_BIN_CAST (element); + + switch (next) { + case GST_STATE_PLAYING: + { + gboolean toplevel, asynchandling; + + GST_OBJECT_LOCK (bin); + toplevel = BIN_IS_TOPLEVEL (bin); + asynchandling = bin->priv->asynchandling; + GST_OBJECT_UNLOCK (bin); + + if (toplevel) + gst_bin_recalculate_latency (bin); + if (asynchandling) + gst_element_post_message (element, + gst_message_new_latency (GST_OBJECT_CAST (element))); + break; + } + case GST_STATE_PAUSED: + /* Clear EOS list on next PAUSED */ + GST_OBJECT_LOCK (bin); + GST_DEBUG_OBJECT (element, "clearing EOS elements"); + bin_remove_messages (bin, NULL, GST_MESSAGE_EOS); + bin->priv->posted_eos = FALSE; + if (current == GST_STATE_READY) + bin_remove_messages (bin, NULL, GST_MESSAGE_STREAM_START); + GST_OBJECT_UNLOCK (bin); + if (current == GST_STATE_READY) + if (!(gst_bin_src_pads_activate (bin, TRUE))) + goto activate_failure; + break; + case GST_STATE_READY: + /* Clear message list on next READY */ + GST_OBJECT_LOCK (bin); + GST_DEBUG_OBJECT (element, "clearing all cached messages"); + bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); + GST_OBJECT_UNLOCK (bin); + /* We might not have reached PAUSED yet due to async errors, + * make sure to always deactivate the pads nonetheless */ + if (!(gst_bin_src_pads_activate (bin, FALSE))) + goto activate_failure; + break; + case GST_STATE_NULL: + /* Clear message list on next NULL */ + GST_OBJECT_LOCK (bin); + GST_DEBUG_OBJECT (element, "clearing all cached messages"); + bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); + GST_OBJECT_UNLOCK (bin); + if (current == GST_STATE_READY) { + if (!(gst_bin_src_pads_activate (bin, FALSE))) + goto activate_failure; + } + break; + default: + break; + } + + /* this flag is used to make the async state changes return immediately. We + * don't want them to interfere with this state change */ + GST_OBJECT_LOCK (bin); + bin->polling = TRUE; + GST_OBJECT_UNLOCK (bin); + + /* iterate in state change order */ + it = gst_bin_iterate_sorted (bin); + + /* mark if we've seen an ASYNC element in the bin when we did a state change. + * Note how we don't reset this value when a resync happens, the reason being + * that the async element posted ASYNC_START and we want to post ASYNC_DONE + * even after a resync when the async element is gone */ + have_async = FALSE; + +restart: + /* take base_time */ + base_time = gst_element_get_base_time (element); + start_time = gst_element_get_start_time (element); + + have_no_preroll = FALSE; + + done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &data)) { + case GST_ITERATOR_OK: + { + GstElement *child; + + child = g_value_get_object (&data); + + /* set state and base_time now */ + ret = gst_bin_element_set_state (bin, child, base_time, start_time, + current, next); + + switch (ret) { + case GST_STATE_CHANGE_SUCCESS: + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "child '%s' changed state to %d(%s) successfully", + GST_ELEMENT_NAME (child), next, + gst_element_state_get_name (next)); + break; + case GST_STATE_CHANGE_ASYNC: + { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "child '%s' is changing state asynchronously to %s", + GST_ELEMENT_NAME (child), gst_element_state_get_name (next)); + have_async = TRUE; + break; + } + case GST_STATE_CHANGE_FAILURE:{ + GstObject *parent; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "child '%s' failed to go to state %d(%s)", + GST_ELEMENT_NAME (child), + next, gst_element_state_get_name (next)); + + /* Only fail if the child is still inside + * this bin. It might've been removed already + * because of the error by the bin subclass + * to ignore the error. */ + parent = gst_object_get_parent (GST_OBJECT_CAST (child)); + if (parent == GST_OBJECT_CAST (element)) { + /* element is still in bin, really error now */ + gst_object_unref (parent); + goto undo; + } + /* child removed from bin, let the resync code redo the state + * change */ + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "child '%s' was removed from the bin", + GST_ELEMENT_NAME (child)); + + if (parent) + gst_object_unref (parent); + + break; + } + case GST_STATE_CHANGE_NO_PREROLL: + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "child '%s' changed state to %d(%s) successfully without preroll", + GST_ELEMENT_NAME (child), next, + gst_element_state_get_name (next)); + have_no_preroll = TRUE; + break; + default: + g_assert_not_reached (); + break; + } + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "iterator doing resync"); + gst_iterator_resync (it); + goto restart; + default: + case GST_ITERATOR_DONE: + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "iterator done"); + done = TRUE; + break; + } + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE)) + goto done; + + if (have_no_preroll) { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "we have NO_PREROLL elements %s -> NO_PREROLL", + gst_element_state_change_return_get_name (ret)); + ret = GST_STATE_CHANGE_NO_PREROLL; + } else if (have_async) { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "we have ASYNC elements %s -> ASYNC", + gst_element_state_change_return_get_name (ret)); + ret = GST_STATE_CHANGE_ASYNC; + } + +done: + g_value_unset (&data); + gst_iterator_free (it); + + GST_OBJECT_LOCK (bin); + bin->polling = FALSE; + /* it's possible that we did not get ASYNC from the children while the bin is + * simulating ASYNC behaviour by posting an ASYNC_DONE message on the bus with + * itself as the source. In that case we still want to check if the state + * change completed. */ + if (ret != GST_STATE_CHANGE_ASYNC && !bin->priv->pending_async_done) { + /* no element returned ASYNC and there are no pending async_done messages, + * we can just complete. */ + GST_DEBUG_OBJECT (bin, "no async elements"); + goto state_end; + } + /* when we get here an ASYNC element was found */ + if (GST_STATE_TARGET (bin) <= GST_STATE_READY) { + /* we ignore ASYNC state changes when we go to READY or NULL */ + GST_DEBUG_OBJECT (bin, "target state %s <= READY", + gst_element_state_get_name (GST_STATE_TARGET (bin))); + goto state_end; + } + + GST_DEBUG_OBJECT (bin, "check async elements"); + /* check if all elements managed to commit their state already */ + if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) { + /* nothing found, remove all old ASYNC_DONE messages. This can happen when + * all the elements commited their state while we were doing the state + * change. We will still return ASYNC for consistency but we commit the + * state already so that a _get_state() will return immediately. */ + bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE); + + GST_DEBUG_OBJECT (bin, "async elements commited"); + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE, + GST_CLOCK_TIME_NONE); + } + +state_end: + bin->priv->pending_async_done = FALSE; + GST_OBJECT_UNLOCK (bin); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "done changing bin's state from %s to %s, now in %s, ret %s", + gst_element_state_get_name (current), + gst_element_state_get_name (next), + gst_element_state_get_name (GST_STATE (element)), + gst_element_state_change_return_get_name (ret)); + + return ret; + + /* ERRORS */ +activate_failure: + { + GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element, + "failure (de)activating src pads"); + return GST_STATE_CHANGE_FAILURE; + } + +undo: + { + if (current < next) { + GstIterator *it = gst_bin_iterate_sorted (GST_BIN (element)); + GstIteratorResult ret; + + GST_DEBUG_OBJECT (element, + "Bin failed to change state, switching children back to %s", + gst_element_state_get_name (current)); + while (TRUE) { + ret = + gst_iterator_foreach (it, &reset_state, GINT_TO_POINTER (current)); + if (ret != GST_ITERATOR_RESYNC) + break; + gst_iterator_resync (it); + } + gst_iterator_free (it); + } + goto done; + } +} + +/* + * This function is a utility event handler. It will send the event to all sinks + * or sources and appropriate ghost pads depending on the event-direction. + * + * Applications are free to override this behaviour and implement their own + * handler, but this will work for pretty much all cases in practice. + */ +static gboolean +gst_bin_send_event (GstElement * element, GstEvent * event) +{ + GstBin *bin = GST_BIN_CAST (element); + GstIterator *iter; + gboolean res = TRUE; + gboolean done = FALSE; + GValue data = { 0, }; + + if (GST_EVENT_IS_DOWNSTREAM (event)) { + iter = gst_bin_iterate_sources (bin); + GST_DEBUG_OBJECT (bin, "Sending %s event to src children", + GST_EVENT_TYPE_NAME (event)); + } else { + iter = gst_bin_iterate_sinks (bin); + GST_DEBUG_OBJECT (bin, "Sending %s event to sink children", + GST_EVENT_TYPE_NAME (event)); + } + + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK: + { + GstElement *child = g_value_get_object (&data); + + gst_event_ref (event); + res &= gst_element_send_event (child, event); + + GST_LOG_OBJECT (child, "After handling %s event: %d", + GST_EVENT_TYPE_NAME (event), res); + + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + res = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_ERROR: + g_assert_not_reached (); + break; + } + } + g_value_unset (&data); + gst_iterator_free (iter); + + if (GST_EVENT_IS_DOWNSTREAM (event)) { + iter = gst_element_iterate_sink_pads (GST_ELEMENT (bin)); + GST_DEBUG_OBJECT (bin, "Sending %s event to sink pads", + GST_EVENT_TYPE_NAME (event)); + } else { + iter = gst_element_iterate_src_pads (GST_ELEMENT (bin)); + GST_DEBUG_OBJECT (bin, "Sending %s event to src pads", + GST_EVENT_TYPE_NAME (event)); + } + + done = FALSE; + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK: + { + GstPad *pad = g_value_get_object (&data); + + gst_event_ref (event); + res &= gst_pad_send_event (pad, event); + GST_LOG_OBJECT (pad, "After handling %s event: %d", + GST_EVENT_TYPE_NAME (event), res); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + res = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_ERROR: + g_assert_not_reached (); + break; + } + } + + g_value_unset (&data); + gst_iterator_free (iter); + gst_event_unref (event); + + return res; +} + +/* this is the function called by the threadpool. When async elements commit + * their state, this function will attempt to bring the bin to the next state. + */ +static void +gst_bin_continue_func (GstBin * bin, BinContinueData * data) +{ + GstState current, next, pending; + GstStateChange transition; + + pending = data->pending; + + GST_DEBUG_OBJECT (bin, "waiting for state lock"); + GST_STATE_LOCK (bin); + + GST_DEBUG_OBJECT (bin, "doing state continue"); + GST_OBJECT_LOCK (bin); + + /* if a new state change happened after this thread was scheduled, we return + * immediately. */ + if (data->cookie != GST_ELEMENT_CAST (bin)->state_cookie) + goto interrupted; + + current = GST_STATE (bin); + next = GST_STATE_GET_NEXT (current, pending); + transition = (GstStateChange) GST_STATE_TRANSITION (current, next); + + GST_STATE_NEXT (bin) = next; + GST_STATE_PENDING (bin) = pending; + /* mark busy */ + GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC; + GST_OBJECT_UNLOCK (bin); + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, + "continue state change %s to %s, final %s", + gst_element_state_get_name (current), + gst_element_state_get_name (next), gst_element_state_get_name (pending)); + + gst_element_change_state (GST_ELEMENT_CAST (bin), transition); + + GST_STATE_UNLOCK (bin); + GST_DEBUG_OBJECT (bin, "state continue done"); + + return; + +interrupted: + { + GST_OBJECT_UNLOCK (bin); + GST_STATE_UNLOCK (bin); + GST_DEBUG_OBJECT (bin, "state continue aborted due to intervening change"); + return; + } +} + +static GstBusSyncReply +bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin) +{ + GstBinClass *bclass; + + bclass = GST_BIN_GET_CLASS (bin); + if (bclass->handle_message) + bclass->handle_message (bin, message); + else + gst_message_unref (message); + + return GST_BUS_DROP; +} + +static void +free_bin_continue_data (BinContinueData * data) +{ + g_slice_free (BinContinueData, data); +} + +static void +bin_push_state_continue (GstBin * bin, BinContinueData * data) +{ + GST_DEBUG_OBJECT (bin, "pushing continue on thread pool"); + gst_element_call_async (GST_ELEMENT_CAST (bin), + (GstElementCallAsyncFunc) gst_bin_continue_func, data, + (GDestroyNotify) free_bin_continue_data); +} + +/* an element started an async state change, if we were not busy with a state + * change, we perform a lost state. + * This function is called with the OBJECT lock. + */ +static void +bin_handle_async_start (GstBin * bin) +{ + GstState old_state, new_state; + gboolean toplevel; + GstMessage *amessage = NULL; + + if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE) + goto had_error; + + /* get our toplevel state */ + toplevel = BIN_IS_TOPLEVEL (bin); + + /* prepare an ASYNC_START message, we always post the start message even if we + * are busy with a state change or when we are NO_PREROLL. */ + if (!toplevel) + /* non toplevel bin, prepare async-start for the parent */ + amessage = gst_message_new_async_start (GST_OBJECT_CAST (bin)); + + if (bin->polling || GST_STATE_PENDING (bin) != GST_STATE_VOID_PENDING) + goto was_busy; + + /* async starts are ignored when we are NO_PREROLL */ + if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL) + goto was_no_preroll; + + old_state = GST_STATE (bin); + + /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to + * PLAYING after optionally redistributing the base_time. */ + if (old_state > GST_STATE_PAUSED) + new_state = GST_STATE_PAUSED; + else + new_state = old_state; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "lost state of %s, new %s", gst_element_state_get_name (old_state), + gst_element_state_get_name (new_state)); + + GST_STATE (bin) = new_state; + GST_STATE_NEXT (bin) = new_state; + GST_STATE_PENDING (bin) = new_state; + GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC; + GST_OBJECT_UNLOCK (bin); + + /* post message */ + _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), new_state, new_state, + new_state); + +post_start: + if (amessage) { + /* post our ASYNC_START. */ + GST_DEBUG_OBJECT (bin, "posting ASYNC_START to parent"); + gst_element_post_message (GST_ELEMENT_CAST (bin), amessage); + } + GST_OBJECT_LOCK (bin); + + return; + +had_error: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "we had an error"); + return; + } +was_busy: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy"); + GST_OBJECT_UNLOCK (bin); + goto post_start; + } +was_no_preroll: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "ignoring, we are NO_PREROLL"); + GST_OBJECT_UNLOCK (bin); + goto post_start; + } +} + +/* this function is called when there are no more async elements in the bin. We + * post a state changed message and an ASYNC_DONE message. + * This function is called with the OBJECT lock. + */ +static void +bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, + gboolean flag_pending, GstClockTime running_time) +{ + GstState current, pending, target; + GstStateChangeReturn old_ret; + GstState old_state, old_next; + gboolean toplevel, state_changed = FALSE; + GstMessage *amessage = NULL; + BinContinueData *cont = NULL; + + if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE) + goto had_error; + + pending = GST_STATE_PENDING (bin); + + if (bin->polling) + goto was_busy; + + /* check if there is something to commit */ + if (pending == GST_STATE_VOID_PENDING) + goto nothing_pending; + + old_ret = GST_STATE_RETURN (bin); + GST_STATE_RETURN (bin) = ret; + + /* move to the next target state */ + target = GST_STATE_TARGET (bin); + pending = GST_STATE_PENDING (bin) = target; + + amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin), running_time); + + old_state = GST_STATE (bin); + /* this is the state we should go to next */ + old_next = GST_STATE_NEXT (bin); + + if (old_next != GST_STATE_PLAYING) { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, + "committing state from %s to %s, old pending %s", + gst_element_state_get_name (old_state), + gst_element_state_get_name (old_next), + gst_element_state_get_name (pending)); + + /* update current state */ + current = GST_STATE (bin) = old_next; + } else { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, + "setting state from %s to %s, pending %s", + gst_element_state_get_name (old_state), + gst_element_state_get_name (old_state), + gst_element_state_get_name (pending)); + current = old_state; + } + + /* get our toplevel state */ + toplevel = BIN_IS_TOPLEVEL (bin); + + /* see if we reached the final state. If we are not toplevel, we also have to + * stop here, the parent will continue our state. */ + if ((pending == current) || !toplevel) { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, + "completed state change, pending VOID"); + + /* mark VOID pending */ + pending = GST_STATE_VOID_PENDING; + GST_STATE_PENDING (bin) = pending; + GST_STATE_NEXT (bin) = GST_STATE_VOID_PENDING; + } else { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, + "continue state change, pending %s", + gst_element_state_get_name (pending)); + + cont = g_slice_new (BinContinueData); + + /* cookie to detect concurrent state change */ + cont->cookie = GST_ELEMENT_CAST (bin)->state_cookie; + /* pending target state */ + cont->pending = pending; + /* mark busy */ + GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC; + GST_STATE_NEXT (bin) = GST_STATE_GET_NEXT (old_state, pending); + } + + if (old_next != GST_STATE_PLAYING) { + if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) { + state_changed = TRUE; + } + } + GST_OBJECT_UNLOCK (bin); + + if (state_changed) { + _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), old_state, + old_next, pending); + } + if (amessage) { + /* post our combined ASYNC_DONE when all is ASYNC_DONE. */ + GST_DEBUG_OBJECT (bin, "posting ASYNC_DONE to parent"); + gst_element_post_message (GST_ELEMENT_CAST (bin), amessage); + } + + GST_OBJECT_LOCK (bin); + if (cont) { + /* toplevel, start continue state */ + GST_DEBUG_OBJECT (bin, "all async-done, starting state continue"); + bin_push_state_continue (bin, cont); + } else { + GST_DEBUG_OBJECT (bin, "state change complete"); + GST_STATE_BROADCAST (bin); + } + return; + +had_error: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "we had an error"); + return; + } +was_busy: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy"); + /* if we were busy with a state change and we are requested to flag a + * pending async done, we do so here */ + if (flag_pending) + bin->priv->pending_async_done = TRUE; + return; + } +nothing_pending: + { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "nothing pending"); + return; + } +} + +static void +bin_do_eos (GstBin * bin) +{ + guint32 seqnum = 0; + gboolean eos; + + GST_OBJECT_LOCK (bin); + /* If all sinks are EOS, we're in PLAYING and no state change is pending + * (or we're doing playing to playing and noone else will trigger posting + * EOS for us) we forward the EOS message to the parent bin or application + */ + eos = GST_STATE (bin) == GST_STATE_PLAYING + && (GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING || + GST_STATE_PENDING (bin) == GST_STATE_PLAYING) + && bin->priv->posted_playing && is_eos (bin, &seqnum); + GST_OBJECT_UNLOCK (bin); + + if (eos + && g_atomic_int_compare_and_exchange (&bin->priv->posted_eos, FALSE, + TRUE)) { + GstMessage *tmessage; + + /* Clear out any further messages, and reset posted_eos so we can + detect any new EOS that happens (eg, after a seek). Since all + sinks have now posted an EOS, there will be no further EOS events + seen unless there is a new logical EOS */ + GST_OBJECT_LOCK (bin); + bin_remove_messages (bin, NULL, GST_MESSAGE_EOS); + bin->priv->posted_eos = FALSE; + GST_OBJECT_UNLOCK (bin); + + tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin)); + gst_message_set_seqnum (tmessage, seqnum); + GST_DEBUG_OBJECT (bin, + "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum); + gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + } else { + GST_LOG_OBJECT (bin, "Not forwarding EOS due to in progress state change, " + " or already posted, or waiting for more EOS"); + } +} + +static void +bin_do_stream_start (GstBin * bin) +{ + guint32 seqnum = 0; + gboolean stream_start; + gboolean have_group_id = FALSE; + guint group_id = 0; + + GST_OBJECT_LOCK (bin); + /* If all sinks are STREAM_START we forward the STREAM_START message + * to the parent bin or application + */ + stream_start = is_stream_start (bin, &seqnum, &have_group_id, &group_id); + GST_OBJECT_UNLOCK (bin); + + if (stream_start) { + GstMessage *tmessage; + + GST_OBJECT_LOCK (bin); + bin_remove_messages (bin, NULL, GST_MESSAGE_STREAM_START); + GST_OBJECT_UNLOCK (bin); + + tmessage = gst_message_new_stream_start (GST_OBJECT_CAST (bin)); + gst_message_set_seqnum (tmessage, seqnum); + if (have_group_id) + gst_message_set_group_id (tmessage, group_id); + + GST_DEBUG_OBJECT (bin, + "all sinks posted STREAM_START, posting seqnum #%" G_GUINT32_FORMAT, + seqnum); + gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + } +} + +/* must be called without the object lock as it posts messages */ +static void +bin_do_message_forward (GstBin * bin, GstMessage * message) +{ + if (bin->priv->message_forward) { + GstMessage *forwarded; + + GST_DEBUG_OBJECT (bin, "pass %s message upward", + GST_MESSAGE_TYPE_NAME (message)); + + /* we need to convert these messages to element messages so that our parent + * bin can easily ignore them and so that the application can easily + * distinguish between the internally forwarded and the real messages. */ + forwarded = gst_message_new_element (GST_OBJECT_CAST (bin), + gst_structure_new ("GstBinForwarded", + "message", GST_TYPE_MESSAGE, message, NULL)); + + gst_element_post_message (GST_ELEMENT_CAST (bin), forwarded); + } +} + +static void +gst_bin_update_context (GstBin * bin, GstContext * context) +{ + GST_OBJECT_LOCK (bin); + gst_bin_update_context_unlocked (bin, context); + GST_OBJECT_UNLOCK (bin); +} + +static void +gst_bin_update_context_unlocked (GstBin * bin, GstContext * context) +{ + const gchar *context_type; + GList *l, **contexts; + + contexts = &GST_ELEMENT_CAST (bin)->contexts; + context_type = gst_context_get_context_type (context); + + GST_DEBUG_OBJECT (bin, "set context %p %" GST_PTR_FORMAT, context, + gst_context_get_structure (context)); + for (l = *contexts; l; l = l->next) { + GstContext *tmp = l->data; + const gchar *tmp_type = gst_context_get_context_type (tmp); + + /* Always store newest context but never replace + * a persistent one by a non-persistent one */ + if (strcmp (context_type, tmp_type) == 0 && + (gst_context_is_persistent (context) || + !gst_context_is_persistent (tmp))) { + gst_context_replace ((GstContext **) & l->data, context); + break; + } + } + /* Not found? Add */ + if (l == NULL) { + *contexts = g_list_prepend (*contexts, gst_context_ref (context)); + } +} + +/* handle child messages: + * + * This method is called synchronously when a child posts a message on + * the internal bus. + * + * GST_MESSAGE_EOS: This message is only posted by sinks + * in the PLAYING state. If all sinks posted the EOS message, post + * one upwards. + * + * GST_MESSAGE_STATE_DIRTY: Deprecated + * + * GST_MESSAGE_SEGMENT_START: just collect, never forward upwards. If an + * element posts segment_start twice, only the last message is kept. + * + * GST_MESSAGE_SEGMENT_DONE: replace SEGMENT_START message from same poster + * with the segment_done message. If there are no more segment_start + * messages, post segment_done message upwards. + * + * GST_MESSAGE_DURATION_CHANGED: clear any cached durations. + * Whenever someone performs a duration query on the bin, we store the + * result so we can answer it quicker the next time. Any element that + * changes its duration marks our cached values invalid. + * This message is also posted upwards. This is currently disabled + * because too many elements don't post DURATION_CHANGED messages when + * the duration changes. + * + * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it + * can no longer provide a clock. The default bin behaviour is to + * check if the lost clock was the one provided by the bin. If so and + * we are currently in the PLAYING state, we forward the message to + * our parent. + * This message is also generated when we remove a clock provider from + * a bin. If this message is received by the application, it should + * PAUSE the pipeline and set it back to PLAYING to force a new clock + * and a new base_time distribution. + * + * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element + * can provide a clock. This mostly happens when we add a new clock + * provider to the bin. The default behaviour of the bin is to mark the + * currently selected clock as dirty, which will perform a clock + * recalculation the next time we are asked to provide a clock. + * This message is never sent to the application but is forwarded to + * the parent. + * + * GST_MESSAGE_ASYNC_START: Create an internal ELEMENT message that stores + * the state of the element and the fact that the element will need a + * new base_time. This message is not forwarded to the application. + * + * GST_MESSAGE_ASYNC_DONE: Find the internal ELEMENT message we kept for the + * element when it posted ASYNC_START. If all elements are done, post a + * ASYNC_DONE message to the parent. + * + * OTHER: post upwards. + */ +static void +gst_bin_handle_message_func (GstBin * bin, GstMessage * message) +{ + GstObject *src; + GstMessageType type; + GstMessage *tmessage; + guint32 seqnum; + + src = GST_MESSAGE_SRC (message); + type = GST_MESSAGE_TYPE (message); + + GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s", + message, src ? GST_ELEMENT_NAME (src) : "(NULL)", + GST_MESSAGE_TYPE_NAME (message)); + + switch (type) { + case GST_MESSAGE_ERROR: + { + GST_OBJECT_LOCK (bin); + /* flag error */ + GST_DEBUG_OBJECT (bin, "got ERROR message, unlocking state change"); + GST_STATE_RETURN (bin) = GST_STATE_CHANGE_FAILURE; + GST_STATE_BROADCAST (bin); + GST_OBJECT_UNLOCK (bin); + + goto forward; + } + case GST_MESSAGE_EOS: + { + + /* collect all eos messages from the children */ + bin_do_message_forward (bin, message); + GST_OBJECT_LOCK (bin); + /* ref message for future use */ + bin_replace_message (bin, message, GST_MESSAGE_EOS); + GST_OBJECT_UNLOCK (bin); + + bin_do_eos (bin); + break; + } + case GST_MESSAGE_STREAM_START: + { + + /* collect all stream_start messages from the children */ + GST_OBJECT_LOCK (bin); + /* ref message for future use */ + bin_replace_message (bin, message, GST_MESSAGE_STREAM_START); + GST_OBJECT_UNLOCK (bin); + + bin_do_stream_start (bin); + break; + } + case GST_MESSAGE_STATE_DIRTY: + { + GST_WARNING_OBJECT (bin, "received deprecated STATE_DIRTY message"); + + /* free message */ + gst_message_unref (message); + break; + } + case GST_MESSAGE_SEGMENT_START:{ + gboolean post = FALSE; + GstFormat format; + gint64 position; + + gst_message_parse_segment_start (message, &format, &position); + seqnum = gst_message_get_seqnum (message); + + bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); + /* if this is the first segment-start, post to parent but not to the + * application */ + if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) && + (GST_OBJECT_PARENT (bin) != NULL)) { + post = TRUE; + } + /* replace any previous segment_start message from this source + * with the new segment start message */ + bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START); + GST_OBJECT_UNLOCK (bin); + if (post) { + tmessage = gst_message_new_segment_start (GST_OBJECT_CAST (bin), + format, position); + gst_message_set_seqnum (tmessage, seqnum); + + /* post segment start with initial format and position. */ + GST_DEBUG_OBJECT (bin, "posting SEGMENT_START (%u) bus message: %p", + seqnum, message); + gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + } + break; + } + case GST_MESSAGE_SEGMENT_DONE: + { + gboolean post = FALSE; + GstFormat format; + gint64 position; + + gst_message_parse_segment_done (message, &format, &position); + seqnum = gst_message_get_seqnum (message); + + bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); + bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START); + /* if there are no more segment_start messages, everybody posted + * a segment_done and we can post one on the bus. */ + + /* we don't care who still has a pending segment start */ + if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START)) { + /* nothing found */ + post = TRUE; + /* remove all old segment_done messages */ + bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE); + } + GST_OBJECT_UNLOCK (bin); + if (post) { + tmessage = gst_message_new_segment_done (GST_OBJECT_CAST (bin), + format, position); + gst_message_set_seqnum (tmessage, seqnum); + + /* post segment done with latest format and position. */ + GST_DEBUG_OBJECT (bin, "posting SEGMENT_DONE (%u) bus message: %p", + seqnum, message); + gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage); + } + break; + } + case GST_MESSAGE_DURATION_CHANGED: + { + /* FIXME: remove all cached durations, next time somebody asks + * for duration, we will recalculate. */ +#if 0 + GST_OBJECT_LOCK (bin); + bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION_CHANGED); + GST_OBJECT_UNLOCK (bin); +#endif + goto forward; + } + case GST_MESSAGE_CLOCK_LOST: + { + GstClock **provided_clock_p; + GstElement **clock_provider_p; + gboolean playing, toplevel, provided, forward; + GstClock *clock; + + gst_message_parse_clock_lost (message, &clock); + + GST_OBJECT_LOCK (bin); + bin->clock_dirty = TRUE; + /* if we lost the clock that we provided, post to parent but + * only if we are not a top-level bin or PLAYING. + * The reason for this is that applications should be able + * to PAUSE/PLAY if they receive this message without worrying + * about the state of the pipeline. */ + provided = (clock == bin->provided_clock); + playing = (GST_STATE (bin) == GST_STATE_PLAYING); + toplevel = GST_OBJECT_PARENT (bin) == NULL; + forward = provided && (playing || !toplevel); + if (provided) { + GST_DEBUG_OBJECT (bin, + "Lost clock %" GST_PTR_FORMAT " provided by %" GST_PTR_FORMAT, + bin->provided_clock, bin->clock_provider); + provided_clock_p = &bin->provided_clock; + clock_provider_p = &bin->clock_provider; + gst_object_replace ((GstObject **) provided_clock_p, NULL); + gst_object_replace ((GstObject **) clock_provider_p, NULL); + } + GST_DEBUG_OBJECT (bin, "provided %d, playing %d, forward %d", + provided, playing, forward); + GST_OBJECT_UNLOCK (bin); + + if (forward) + goto forward; + + /* free message */ + gst_message_unref (message); + break; + } + case GST_MESSAGE_CLOCK_PROVIDE: + { + gboolean forward; + + GST_OBJECT_LOCK (bin); + bin->clock_dirty = TRUE; + /* a new clock is available, post to parent but not + * to the application */ + forward = GST_OBJECT_PARENT (bin) != NULL; + GST_OBJECT_UNLOCK (bin); + + if (forward) + goto forward; + + /* free message */ + gst_message_unref (message); + break; + } + case GST_MESSAGE_ASYNC_START: + { + GstState target; + + GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message, + src ? GST_OBJECT_NAME (src) : "(NULL)"); + + bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); + /* we ignore the message if we are going to <= READY */ + if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY) + goto ignore_start_message; + + /* takes ownership of the message */ + bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START); + + bin_handle_async_start (bin); + GST_OBJECT_UNLOCK (bin); + break; + + ignore_start_message: + { + GST_DEBUG_OBJECT (bin, "ignoring message, target %s", + gst_element_state_get_name (target)); + GST_OBJECT_UNLOCK (bin); + gst_message_unref (message); + break; + } + } + case GST_MESSAGE_ASYNC_DONE: + { + GstClockTime running_time; + GstState target; + + GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message, + src ? GST_OBJECT_NAME (src) : "(NULL)"); + + gst_message_parse_async_done (message, &running_time); + + bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); + /* ignore messages if we are shutting down */ + if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY) + goto ignore_done_message; + + bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START); + /* if there are no more ASYNC_START messages, everybody posted + * a ASYNC_DONE and we can post one on the bus. When checking, we + * don't care who still has a pending ASYNC_START */ + if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) { + /* nothing found, remove all old ASYNC_DONE messages */ + bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE); + + GST_DEBUG_OBJECT (bin, "async elements commited"); + /* when we get an async done message when a state change was busy, we + * need to set the pending_done flag so that at the end of the state + * change we can see if we need to verify pending async elements, hence + * the TRUE argument here. */ + bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE, + running_time); + } else { + GST_DEBUG_OBJECT (bin, "there are more async elements pending"); + } + GST_OBJECT_UNLOCK (bin); + break; + + ignore_done_message: + { + GST_DEBUG_OBJECT (bin, "ignoring message, target %s", + gst_element_state_get_name (target)); + GST_OBJECT_UNLOCK (bin); + gst_message_unref (message); + break; + } + } + case GST_MESSAGE_STRUCTURE_CHANGE: + { + gboolean busy; + + gst_message_parse_structure_change (message, NULL, NULL, &busy); + + GST_OBJECT_LOCK (bin); + if (busy) { + /* while the pad is busy, avoid following it when doing state changes. + * Don't update the cookie yet, we will do that after the structure + * change finished and we are ready to inspect the new updated + * structure. */ + bin_replace_message (bin, message, GST_MESSAGE_STRUCTURE_CHANGE); + message = NULL; + } else { + /* a pad link/unlink ended, signal the state change iterator that we + * need to resync by updating the structure_cookie. */ + bin_remove_messages (bin, GST_MESSAGE_SRC (message), + GST_MESSAGE_STRUCTURE_CHANGE); + if (!GST_BIN_IS_NO_RESYNC (bin)) + bin->priv->structure_cookie++; + } + GST_OBJECT_UNLOCK (bin); + + if (message) + gst_message_unref (message); + + break; + } + case GST_MESSAGE_NEED_CONTEXT:{ + const gchar *context_type; + GList *l, *contexts; + + gst_message_parse_context_type (message, &context_type); + GST_OBJECT_LOCK (bin); + contexts = GST_ELEMENT_CAST (bin)->contexts; + GST_LOG_OBJECT (bin, "got need-context message type: %s", context_type); + for (l = contexts; l; l = l->next) { + GstContext *tmp = l->data; + const gchar *tmp_type = gst_context_get_context_type (tmp); + + if (strcmp (context_type, tmp_type) == 0) { + gst_element_set_context (GST_ELEMENT (src), l->data); + break; + } + } + GST_OBJECT_UNLOCK (bin); + + /* Forward if we couldn't answer the message */ + if (l == NULL) { + goto forward; + } else { + gst_message_unref (message); + } + + break; + } + case GST_MESSAGE_HAVE_CONTEXT:{ + GstContext *context; + + gst_message_parse_have_context (message, &context); + gst_bin_update_context (bin, context); + gst_context_unref (context); + + goto forward; + break; + } + default: + goto forward; + } + return; + +forward: + { + /* Send all other messages upward */ + GST_DEBUG_OBJECT (bin, "posting message upward"); + gst_element_post_message (GST_ELEMENT_CAST (bin), message); + return; + } +} + +/* generic struct passed to all query fold methods */ +typedef struct +{ + GstQuery *query; + gint64 min; + gint64 max; + gboolean live; +} QueryFold; + +typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold); +typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold); + +/* for duration/position we collect all durations/positions and take + * the MAX of all valid results */ +static void +bin_query_min_max_init (GstBin * bin, QueryFold * fold) +{ + fold->min = 0; + fold->max = -1; + fold->live = FALSE; +} + +static gboolean +bin_query_duration_fold (const GValue * vitem, GValue * ret, QueryFold * fold) +{ + gboolean res = FALSE; + GstObject *item = g_value_get_object (vitem); + if (GST_IS_PAD (item)) + res = gst_pad_query (GST_PAD (item), fold->query); + else + res = gst_element_query (GST_ELEMENT (item), fold->query); + + if (res) { + 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 == -1) { + /* duration query succeeded, but duration is unknown */ + fold->max = -1; + return FALSE; + } + + if (duration > fold->max) + fold->max = duration; + } + + return TRUE; +} + +static void +bin_query_duration_done (GstBin * bin, 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_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max); + + /* FIXME: re-implement duration caching */ +#if 0 + /* and cache now */ + GST_OBJECT_LOCK (bin); + bin->messages = g_list_prepend (bin->messages, + gst_message_new_duration (GST_OBJECT_CAST (bin), format, fold->max)); + GST_OBJECT_UNLOCK (bin); +#endif +} + +static gboolean +bin_query_position_fold (const GValue * vitem, GValue * ret, QueryFold * fold) +{ + gboolean res = FALSE; + GstObject *item = g_value_get_object (vitem); + if (GST_IS_PAD (item)) + res = gst_pad_query (GST_PAD (item), fold->query); + else + res = gst_element_query (GST_ELEMENT (item), fold->query); + + if (res) { + 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; + } + + return TRUE; +} + +static void +bin_query_position_done (GstBin * bin, 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 (bin, "max position %" G_GINT64_FORMAT, fold->max); +} + +static gboolean +bin_query_latency_fold (const GValue * vitem, GValue * ret, QueryFold * fold) +{ + gboolean res = FALSE; + GstObject *item = g_value_get_object (vitem); + if (GST_IS_PAD (item)) + res = gst_pad_query (GST_PAD (item), fold->query); + else + res = gst_element_query (GST_ELEMENT (item), fold->query); + if (res) { + GstClockTime min, max; + gboolean live; + + 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 (live) { + if (min > fold->min) + fold->min = min; + if (fold->max == -1) + fold->max = max; + else if (max < fold->max) + fold->max = max; + if (!fold->live) + fold->live = live; + } + } else { + g_value_set_boolean (ret, FALSE); + GST_DEBUG_OBJECT (item, "failed query"); + } + + return TRUE; +} + +static void +bin_query_latency_done (GstBin * bin, QueryFold * fold) +{ + /* store max in query result */ + gst_query_set_latency (fold->query, fold->live, fold->min, fold->max); + + GST_DEBUG_OBJECT (bin, + "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT + ", live %d", GST_TIME_ARGS (fold->min), GST_TIME_ARGS (fold->max), + fold->live); +} + +/* generic fold, return first valid result */ +static gboolean +bin_query_generic_fold (const GValue * vitem, GValue * ret, QueryFold * fold) +{ + gboolean res = FALSE; + GstObject *item = g_value_get_object (vitem); + if (GST_IS_PAD (item)) + res = gst_pad_query (GST_PAD (item), fold->query); + else + res = gst_element_query (GST_ELEMENT (item), fold->query); + if (res) { + g_value_set_boolean (ret, TRUE); + GST_DEBUG_OBJECT (item, "answered query %p", fold->query); + } + + /* and stop as soon as we have a valid result */ + return !res; +} + +/* Perform a query iteration for the given bin. The query is stored in + * QueryFold and iter should be either a GstPad iterator or a + * GstElement iterator. */ +static gboolean +bin_iterate_fold (GstBin * bin, GstIterator * iter, QueryInitFunction fold_init, + QueryDoneFunction fold_done, GstIteratorFoldFunction fold_func, + QueryFold * fold_data, gboolean default_return) +{ + gboolean res = default_return; + GValue ret = { 0 }; + /* set the result of the query to FALSE initially */ + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, res); + + 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 (bin, fold_data); + g_value_set_boolean (&ret, res); + break; + case GST_ITERATOR_OK: + case GST_ITERATOR_DONE: + res = g_value_get_boolean (&ret); + if (fold_done != NULL && res) + fold_done (bin, fold_data); + goto done; + default: + res = FALSE; + goto done; + } + } +done: + return res; +} + +static gboolean +gst_bin_query (GstElement * element, GstQuery * query) +{ + GstBin *bin = GST_BIN_CAST (element); + GstIterator *iter; + gboolean default_return = FALSE; + gboolean res = FALSE; + gboolean src_pads_query_result = FALSE; + GstIteratorFoldFunction fold_func; + QueryInitFunction fold_init = NULL; + QueryDoneFunction fold_done = NULL; + QueryFold fold_data; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION: + { + /* FIXME: implement duration caching in GstBin again */ +#if 0 + GList *cached; + GstFormat qformat; + + gst_query_parse_duration (query, &qformat, NULL); + + /* find cached duration query */ + GST_OBJECT_LOCK (bin); + for (cached = bin->messages; cached; cached = g_list_next (cached)) { + GstMessage *message = (GstMessage *) cached->data; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION_CHANGED && + GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) { + GstFormat format; + gint64 duration; + + gst_message_parse_duration (message, &format, &duration); + + /* if cached same format, copy duration in query result */ + if (format == qformat) { + GST_DEBUG_OBJECT (bin, "return cached duration %" G_GINT64_FORMAT, + duration); + GST_OBJECT_UNLOCK (bin); + + gst_query_set_duration (query, qformat, duration); + res = TRUE; + goto exit; + } + } + } + GST_OBJECT_UNLOCK (bin); +#else +#ifndef GST_DISABLE_GST_DEBUG + G_STMT_START { + /* Quieten this particularly annoying FIXME a bit: */ + static gboolean printed_fixme = FALSE; + if (!printed_fixme) { + GST_FIXME ("implement duration caching in GstBin again"); + printed_fixme = TRUE; + } + } + G_STMT_END; +#endif +#endif + /* no cached value found, iterate and collect durations */ + fold_func = (GstIteratorFoldFunction) bin_query_duration_fold; + fold_init = bin_query_min_max_init; + fold_done = bin_query_duration_done; + break; + } + case GST_QUERY_POSITION: + { + fold_func = (GstIteratorFoldFunction) bin_query_position_fold; + fold_init = bin_query_min_max_init; + fold_done = bin_query_position_done; + break; + } + case GST_QUERY_LATENCY: + { + fold_func = (GstIteratorFoldFunction) bin_query_latency_fold; + fold_init = bin_query_min_max_init; + fold_done = bin_query_latency_done; + default_return = TRUE; + break; + } + default: + fold_func = (GstIteratorFoldFunction) bin_query_generic_fold; + break; + } + + fold_data.query = query; + + iter = gst_bin_iterate_sinks (bin); + GST_DEBUG_OBJECT (bin, "Sending query %p (type %s) to sink children", + query, GST_QUERY_TYPE_NAME (query)); + + if (fold_init) + fold_init (bin, &fold_data); + + res = + bin_iterate_fold (bin, iter, fold_init, fold_done, fold_func, &fold_data, + default_return); + gst_iterator_free (iter); + + if (!res) { + /* Query the source pads of the element */ + iter = gst_element_iterate_src_pads (element); + src_pads_query_result = + bin_iterate_fold (bin, iter, fold_init, fold_done, fold_func, + &fold_data, default_return); + gst_iterator_free (iter); + + if (src_pads_query_result) + res = TRUE; + } + + GST_DEBUG_OBJECT (bin, "query %p result %d", query, res); + + return res; +} + +static void +set_context (const GValue * item, gpointer user_data) +{ + GstElement *element = g_value_get_object (item); + + gst_element_set_context (element, user_data); +} + +static void +gst_bin_set_context (GstElement * element, GstContext * context) +{ + GstBin *bin; + GstIterator *children; + + g_return_if_fail (GST_IS_BIN (element)); + + bin = GST_BIN (element); + + GST_ELEMENT_CLASS (parent_class)->set_context (element, context); + + children = gst_bin_iterate_elements (bin); + while (gst_iterator_foreach (children, set_context, + context) == GST_ITERATOR_RESYNC) + gst_iterator_resync (children); + gst_iterator_free (children); +} + +static gint +compare_name (const GValue * velement, const gchar * name) +{ + gint eq; + GstElement *element = g_value_get_object (velement); + + GST_OBJECT_LOCK (element); + eq = strcmp (GST_ELEMENT_NAME (element), name); + GST_OBJECT_UNLOCK (element); + + return eq; +} + +/** + * gst_bin_get_by_name: + * @bin: a #GstBin + * @name: the element name to search for + * + * Gets the element with the given name from a bin. This + * function recurses into child bins. + * + * Returns %NULL if no element with the given name is found in the bin. + * + * MT safe. Caller owns returned reference. + * + * Returns: (transfer full) (nullable): the #GstElement with the given + * name, or %NULL + */ +GstElement * +gst_bin_get_by_name (GstBin * bin, const gchar * name) +{ + GstIterator *children; + GValue result = { 0, }; + GstElement *element; + gboolean found; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s", + GST_ELEMENT_NAME (bin), name); + + children = gst_bin_iterate_recurse (bin); + found = gst_iterator_find_custom (children, + (GCompareFunc) compare_name, &result, (gpointer) name); + gst_iterator_free (children); + + if (found) { + element = g_value_dup_object (&result); + g_value_unset (&result); + } else { + element = NULL; + } + + return element; +} + +/** + * gst_bin_get_by_name_recurse_up: + * @bin: a #GstBin + * @name: the element name to search for + * + * Gets the element with the given name from this bin. If the + * element is not found, a recursion is performed on the parent bin. + * + * Returns %NULL if: + * - no element with the given name is found in the bin + * + * MT safe. Caller owns returned reference. + * + * Returns: (transfer full) (nullable): the #GstElement with the given + * name, or %NULL + */ +GstElement * +gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name) +{ + GstElement *result; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (name != NULL, NULL); + + result = gst_bin_get_by_name (bin, name); + + if (!result) { + GstObject *parent; + + parent = gst_object_get_parent (GST_OBJECT_CAST (bin)); + if (parent) { + if (GST_IS_BIN (parent)) { + result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name); + } + gst_object_unref (parent); + } + } + + return result; +} + +static gint +compare_interface (const GValue * velement, GValue * interface) +{ + GstElement *element = g_value_get_object (velement); + GType interface_type = (GType) g_value_get_pointer (interface); + gint ret; + + if (G_TYPE_CHECK_INSTANCE_TYPE (element, interface_type)) { + ret = 0; + } else { + ret = 1; + } + return ret; +} + +/** + * gst_bin_get_by_interface: + * @bin: a #GstBin + * @iface: the #GType of an interface + * + * Looks for an element inside the bin that implements the given + * interface. If such an element is found, it returns the element. + * You can cast this element to the given interface afterwards. If you want + * all elements that implement the interface, use + * gst_bin_iterate_all_by_interface(). This function recurses into child bins. + * + * MT safe. Caller owns returned reference. + * + * Returns: (transfer full) (nullable): A #GstElement inside the bin + * implementing the interface + */ +GstElement * +gst_bin_get_by_interface (GstBin * bin, GType iface) +{ + GstIterator *children; + GValue result = { 0, }; + GstElement *element; + gboolean found; + GValue viface = { 0, }; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL); + + g_value_init (&viface, G_TYPE_POINTER); + g_value_set_pointer (&viface, (gpointer) iface); + + children = gst_bin_iterate_recurse (bin); + found = gst_iterator_find_custom (children, (GCompareFunc) compare_interface, + &result, &viface); + gst_iterator_free (children); + + if (found) { + element = g_value_dup_object (&result); + g_value_unset (&result); + } else { + element = NULL; + } + g_value_unset (&viface); + + return element; +} + +/** + * gst_bin_iterate_all_by_interface: + * @bin: a #GstBin + * @iface: the #GType of an interface + * + * Looks for all elements inside the bin that implements the given + * interface. You can safely cast all returned elements to the given interface. + * The function recurses inside child bins. The iterator will yield a series + * of #GstElement that should be unreffed after use. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement + * for all elements in the bin implementing the given interface, + * or %NULL + */ +GstIterator * +gst_bin_iterate_all_by_interface (GstBin * bin, GType iface) +{ + GstIterator *children; + GstIterator *result; + GValue viface = { 0, }; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL); + + g_value_init (&viface, G_TYPE_POINTER); + g_value_set_pointer (&viface, (gpointer) iface); + + children = gst_bin_iterate_recurse (bin); + result = gst_iterator_filter (children, (GCompareFunc) compare_interface, + &viface); + + g_value_unset (&viface); + + return result; +} diff --git a/gst/gstbin.h b/gst/gstbin.h new file mode 100644 index 0000000..5e9c38d --- /dev/null +++ b/gst/gstbin.h @@ -0,0 +1,260 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstbin.h: Header for GstBin container 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_BIN_H__ +#define __GST_BIN_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BIN (gst_bin_get_type ()) +#define GST_IS_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BIN)) +#define GST_IS_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BIN)) +#define GST_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BIN, GstBinClass)) +#define GST_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BIN, GstBin)) +#define GST_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BIN, GstBinClass)) +#define GST_BIN_CAST(obj) ((GstBin*)(obj)) + +/** + * GstBinFlags: + * @GST_BIN_FLAG_NO_RESYNC: don't resync a state change when elements are + * added or linked in the bin (Since 1.0.5) + * @GST_BIN_FLAG_STREAMS_AWARE: Indicates whether the bin can handle elements + * that add/remove source pads at any point in time without + * first posting a no-more-pads signal (Since 1.10) + * @GST_BIN_FLAG_LAST: the last enum in the series of flags for bins. + * Derived classes can use this as first value in a list of flags. + * + * GstBinFlags are a set of flags specific to bins. Most are set/used + * internally. They can be checked using the GST_OBJECT_FLAG_IS_SET () macro, + * and (un)set using GST_OBJECT_FLAG_SET () and GST_OBJECT_FLAG_UNSET (). + */ +typedef enum { + GST_BIN_FLAG_NO_RESYNC = (GST_ELEMENT_FLAG_LAST << 0), + GST_BIN_FLAG_STREAMS_AWARE = (GST_ELEMENT_FLAG_LAST << 1), + /* padding */ + GST_BIN_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 5) +} GstBinFlags; + +/** + * GST_BIN_IS_NO_RESYNC: + * @bin: A #GstBin + * + * Check if @bin will resync its state change when elements are added and + * removed. + * + * Since: 1.0.5 + */ +#define GST_BIN_IS_NO_RESYNC(bin) (GST_OBJECT_FLAG_IS_SET(bin,GST_BIN_FLAG_NO_RESYNC)) + +typedef struct _GstBin GstBin; +typedef struct _GstBinClass GstBinClass; +typedef struct _GstBinPrivate GstBinPrivate; + +/** + * GST_BIN_NUMCHILDREN: + * @bin: a #GstBin + * + * Gets the number of children in a bin. + */ +#define GST_BIN_NUMCHILDREN(bin) (GST_BIN_CAST(bin)->numchildren) +/** + * GST_BIN_CHILDREN: + * @bin: a #GstBin + * + * Gets the list with children in a bin. + */ +#define GST_BIN_CHILDREN(bin) (GST_BIN_CAST(bin)->children) +/** + * GST_BIN_CHILDREN_COOKIE: + * @bin: a #GstBin + * + * Gets the children cookie that watches the children list. + */ +#define GST_BIN_CHILDREN_COOKIE(bin) (GST_BIN_CAST(bin)->children_cookie) + +/** + * GstBin: + * @numchildren: the number of children in this bin + * @children: (element-type Gst.Element): the list of children in this bin + * @children_cookie: updated whenever @children changes + * @child_bus: internal bus for handling child messages + * @messages: (element-type Gst.Message): queued and cached messages + * @polling: the bin is currently calculating its state + * @state_dirty: the bin needs to recalculate its state (deprecated) + * @clock_dirty: the bin needs to select a new clock + * @provided_clock: the last clock selected + * @clock_provider: the element that provided @provided_clock + * + * The GstBin base class. Subclasses can access these fields provided + * the LOCK is taken. + */ +struct _GstBin { + GstElement element; + + /*< public >*/ /* with LOCK */ + /* our children, subclass are supposed to update these + * fields to reflect their state with _iterate_*() */ + gint numchildren; + GList *children; + guint32 children_cookie; + + GstBus *child_bus; + GList *messages; + + gboolean polling; + gboolean state_dirty; + + gboolean clock_dirty; + GstClock *provided_clock; + GstElement *clock_provider; + + /*< private >*/ + GstBinPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstBinClass: + * @parent_class: bin parent class + * @add_element: method to add an element to a bin + * @remove_element: method to remove an element from a bin + * @handle_message: method to handle a message from the children + * @deep_element_added: method called when an element was added somewhere + * in the bin hierarchy + * @deep_element_removed: method called when an element was removed somewhere + * in the bin hierarchy + * + * Subclasses can override the @add_element and @remove_element to + * update the list of children in the bin. + * + * The @handle_message method can be overridden to implement custom + * message handling. @handle_message takes ownership of the message, just like + * #gst_element_post_message. + * + * The @deep_element_added vfunc will be called when a new element has been + * added to any bin inside this bin, so it will also be called if a new child + * was added to a sub-bin of this bin. #GstBin implementations that override + * this message should chain up to the parent class implementation so the + * element-added-deep signal is emitted on all parents. + */ +struct _GstBinClass { + GstElementClass parent_class; + + /*< private >*/ + GThreadPool *pool; /* deprecated */ + + /* signals */ + void (*element_added) (GstBin *bin, GstElement *child); + void (*element_removed) (GstBin *bin, GstElement *child); + + /*< public >*/ + /* virtual methods for subclasses */ + gboolean (*add_element) (GstBin *bin, GstElement *element); + gboolean (*remove_element) (GstBin *bin, GstElement *element); + + void (*handle_message) (GstBin *bin, GstMessage *message); + + /*< private >*/ + /* signal */ + gboolean (*do_latency) (GstBin *bin); + + /*< public >*/ + /* signal */ + void (*deep_element_added) (GstBin *bin, GstBin *sub_bin, GstElement *child); + void (*deep_element_removed) (GstBin *bin, GstBin *sub_bin, GstElement *child); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING-2]; +}; + +GST_API +GType gst_bin_get_type (void); + +GST_API +GstElement* gst_bin_new (const gchar *name); + +/* add and remove elements from the bin */ + +GST_API +gboolean gst_bin_add (GstBin *bin, GstElement *element); + +GST_API +gboolean gst_bin_remove (GstBin *bin, GstElement *element); + +/* retrieve a single child */ + +GST_API +GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name); + +GST_API +GstElement* gst_bin_get_by_name_recurse_up (GstBin *bin, const gchar *name); + +GST_API +GstElement* gst_bin_get_by_interface (GstBin *bin, GType iface); + +/* retrieve multiple children */ + +GST_API +GstIterator* gst_bin_iterate_elements (GstBin *bin); + +GST_API +GstIterator* gst_bin_iterate_sorted (GstBin *bin); + +GST_API +GstIterator* gst_bin_iterate_recurse (GstBin *bin); + +GST_API +GstIterator* gst_bin_iterate_sinks (GstBin *bin); + +GST_API +GstIterator* gst_bin_iterate_sources (GstBin *bin); + +GST_API +GstIterator* gst_bin_iterate_all_by_interface (GstBin *bin, GType iface); + +/* latency */ + +GST_API +gboolean gst_bin_recalculate_latency (GstBin * bin); + +/* set and get suppressed flags */ + +GST_API +void gst_bin_set_suppressed_flags (GstBin * bin, GstElementFlags flags); + +GST_API +GstElementFlags gst_bin_get_suppressed_flags (GstBin * bin); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBin, gst_object_unref) +#endif + +G_END_DECLS + + +#endif /* __GST_BIN_H__ */ diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c new file mode 100644 index 0000000..5e61cbc --- /dev/null +++ b/gst/gstbuffer.c @@ -0,0 +1,2741 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstbuffer.c: Buffer operations + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbuffer + * @title: GstBuffer + * @short_description: Data-passing buffer type + * @see_also: #GstPad, #GstMiniObject, #GstMemory, #GstMeta, #GstBufferPool + * + * Buffers are the basic unit of data transfer in GStreamer. They contain the + * timing and offset along with other arbitrary metadata that is associated + * with the #GstMemory blocks that the buffer contains. + * + * Buffers are usually created with gst_buffer_new(). After a buffer has been + * created one will typically allocate memory for it and add it to the buffer. + * The following example creates a buffer that can hold a given video frame + * with a given width, height and bits per plane. + * |[ + * GstBuffer *buffer; + * GstMemory *memory; + * gint size, width, height, bpp; + * ... + * size = width * height * bpp; + * buffer = gst_buffer_new (); + * memory = gst_allocator_alloc (NULL, size, NULL); + * gst_buffer_insert_memory (buffer, -1, memory); + * ... + * ]| + * + * Alternatively, use gst_buffer_new_allocate() to create a buffer with + * preallocated data of a given size. + * + * Buffers can contain a list of #GstMemory objects. You can retrieve how many + * memory objects with gst_buffer_n_memory() and you can get a pointer + * to memory with gst_buffer_peek_memory() + * + * A buffer will usually have timestamps, and a duration, but neither of these + * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a + * meaningful value can be given for these, they should be set. The timestamps + * and duration are measured in nanoseconds (they are #GstClockTime values). + * + * The buffer DTS refers to the timestamp when the buffer should be decoded and + * is usually monotonically increasing. The buffer PTS refers to the timestamp when + * the buffer content should be presented to the user and is not always + * monotonically increasing. + * + * A buffer can also have one or both of a start and an end offset. These are + * media-type specific. For video buffers, the start offset will generally be + * the frame number. For audio buffers, it will be the number of samples + * produced so far. For compressed data, it could be the byte offset in a + * source or destination file. Likewise, the end offset will be the offset of + * the end of the buffer. These can only be meaningfully interpreted if you + * know the media type of the buffer (the preceding CAPS event). Either or both + * can be set to #GST_BUFFER_OFFSET_NONE. + * + * gst_buffer_ref() is used to increase the refcount of a buffer. This must be + * done when you want to keep a handle to the buffer after pushing it to the + * next element. The buffer refcount determines the writability of the buffer, a + * buffer is only writable when the refcount is exactly 1, i.e. when the caller + * has the only reference to the buffer. + * + * To efficiently create a smaller buffer out of an existing one, you can + * use gst_buffer_copy_region(). This method tries to share the memory objects + * between the two buffers. + * + * If a plug-in wants to modify the buffer data or metadata in-place, it should + * first obtain a buffer that is safe to modify by using + * gst_buffer_make_writable(). This function is optimized so that a copy will + * only be made when it is necessary. + * + * Several flags of the buffer can be set and unset with the + * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use + * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlags flag is set. + * + * Buffers can be efficiently merged into a larger buffer with + * gst_buffer_append(). Copying of memory will only be done when absolutely + * needed. + * + * Arbitrary extra metadata can be set on a buffer with gst_buffer_add_meta(). + * Metadata can be retrieved with gst_buffer_get_meta(). See also #GstMeta + * + * An element should either unref the buffer or push it out on a src pad + * using gst_pad_push() (see #GstPad). + * + * Buffers are usually freed by unreffing them with gst_buffer_unref(). When + * the refcount drops to 0, any memory and metadata pointed to by the buffer is + * unreffed as well. Buffers allocated from a #GstBufferPool will be returned to + * the pool when the refcount drops to 0. + * + * The #GstParentBufferMeta is a meta which can be attached to a #GstBuffer + * to hold a reference to another buffer that is only released when the child + * #GstBuffer is released. + * + * Typically, #GstParentBufferMeta is used when the child buffer is directly + * using the #GstMemory of the parent buffer, and wants to prevent the parent + * buffer from being returned to a buffer pool until the #GstMemory is available + * for re-use. (Since 1.6) + * + */ +#include "gst_private.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "gstbuffer.h" +#include "gstbufferpool.h" +#include "gstinfo.h" +#include "gstutils.h" +#include "gstversion.h" + +GType _gst_buffer_type = 0; + +typedef struct _GstMetaItem GstMetaItem; + +struct _GstMetaItem +{ + GstMetaItem *next; + GstMeta meta; +}; +#define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem)) + +#define GST_BUFFER_MEM_MAX 16 + +#define GST_BUFFER_SLICE_SIZE(b) (((GstBufferImpl *)(b))->slice_size) +#define GST_BUFFER_MEM_LEN(b) (((GstBufferImpl *)(b))->len) +#define GST_BUFFER_MEM_ARRAY(b) (((GstBufferImpl *)(b))->mem) +#define GST_BUFFER_MEM_PTR(b,i) (((GstBufferImpl *)(b))->mem[i]) +#define GST_BUFFER_BUFMEM(b) (((GstBufferImpl *)(b))->bufmem) +#define GST_BUFFER_META(b) (((GstBufferImpl *)(b))->item) + +typedef struct +{ + GstBuffer buffer; + + gsize slice_size; + + /* the memory blocks */ + guint len; + GstMemory *mem[GST_BUFFER_MEM_MAX]; + + /* memory of the buffer when allocated from 1 chunk */ + GstMemory *bufmem; + + /* FIXME, make metadata allocation more efficient by using part of the + * GstBufferImpl */ + GstMetaItem *item; +} GstBufferImpl; + + +static gboolean +_is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent) +{ + GstMemory *mcur, *mprv; + gboolean have_offset = FALSE; + gsize i; + + mcur = mprv = NULL; + + for (i = 0; i < len; i++) { + if (mcur) + mprv = mcur; + mcur = mem[i]; + + if (mprv && mcur) { + gsize poffs; + + /* check if memory is contiguous */ + if (!gst_memory_is_span (mprv, mcur, &poffs)) + return FALSE; + + if (!have_offset) { + if (poffset) + *poffset = poffs; + if (parent) + *parent = mprv->parent; + + have_offset = TRUE; + } + } + } + return have_offset; +} + +static GstMemory * +_get_merged_memory (GstBuffer * buffer, guint idx, guint length) +{ + GstMemory **mem, *result = NULL; + + GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx, + length); + + mem = GST_BUFFER_MEM_ARRAY (buffer); + + if (G_UNLIKELY (length == 0)) { + result = NULL; + } else if (G_LIKELY (length == 1)) { + result = gst_memory_ref (mem[idx]); + } else { + GstMemory *parent = NULL; + gsize size, poffset = 0; + + size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL); + + if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) { + if (!GST_MEMORY_IS_NO_SHARE (parent)) + result = gst_memory_share (parent, poffset, size); + if (!result) { + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent); + result = gst_memory_copy (parent, poffset, size); + } + } else { + gsize i, tocopy, left; + GstMapInfo sinfo, dinfo; + guint8 *ptr; + + result = gst_allocator_alloc (NULL, size, NULL); + if (result == NULL || !gst_memory_map (result, &dinfo, GST_MAP_WRITE)) { + GST_CAT_ERROR (GST_CAT_BUFFER, "Failed to map memory writable"); + if (result) + gst_memory_unref (result); + return NULL; + } + + ptr = dinfo.data; + left = size; + + for (i = idx; i < (idx + length) && left > 0; i++) { + if (!gst_memory_map (mem[i], &sinfo, GST_MAP_READ)) { + GST_CAT_ERROR (GST_CAT_BUFFER, + "buffer %p, idx %u, length %u failed to map readable", buffer, + idx, length); + gst_memory_unmap (result, &dinfo); + gst_memory_unref (result); + return NULL; + } + tocopy = MIN (sinfo.size, left); + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, + "memcpy %" G_GSIZE_FORMAT " bytes for merge %p from memory %p", + tocopy, result, mem[i]); + memcpy (ptr, (guint8 *) sinfo.data, tocopy); + left -= tocopy; + ptr += tocopy; + gst_memory_unmap (mem[i], &sinfo); + } + gst_memory_unmap (result, &dinfo); + } + } + return result; +} + +static void +_replace_memory (GstBuffer * buffer, guint len, guint idx, guint length, + GstMemory * mem) +{ + gsize end, i; + + end = idx + length; + + GST_CAT_LOG (GST_CAT_BUFFER, + "buffer %p replace %u-%" G_GSIZE_FORMAT " with memory %p", buffer, idx, + end, mem); + + /* unref old memory */ + for (i = idx; i < end; i++) { + GstMemory *old = GST_BUFFER_MEM_PTR (buffer, i); + + gst_memory_unlock (old, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unref (old); + } + + if (mem != NULL) { + /* replace with single memory */ + gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE); + GST_BUFFER_MEM_PTR (buffer, idx) = mem; + idx++; + length--; + } + + if (end < len) { + memmove (&GST_BUFFER_MEM_PTR (buffer, idx), + &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer)); + } + GST_BUFFER_MEM_LEN (buffer) = len - length; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); +} + +/** + * gst_buffer_get_flags: + * @buffer: a #GstBuffer + * + * Get the #GstBufferFlags flags set on this buffer. + * + * Returns: the flags set on this buffer. + * + * Since: 1.10 + */ +GstBufferFlags +gst_buffer_get_flags (GstBuffer * buffer) +{ + return (GstBufferFlags) GST_BUFFER_FLAGS (buffer); +} + +/** + * gst_buffer_flag_is_set: + * @buffer: a #GstBuffer + * @flags: the #GstBufferFlags flag to check. + * + * Gives the status of a specific flag on a buffer. + * + * Returns: %TRUE if all flags in @flags are found on @buffer. + * + * Since: 1.10 + */ +gboolean +gst_buffer_has_flags (GstBuffer * buffer, GstBufferFlags flags) +{ + return GST_BUFFER_FLAG_IS_SET (buffer, flags); +} + +/** + * gst_buffer_set_flags: + * @buffer: a #GstBuffer + * @flags: the #GstBufferFlags to set. + * + * Sets one or more buffer flags on a buffer. + * + * Returns: %TRUE if @flags were successfully set on buffer. + * + * Since: 1.10 + */ +gboolean +gst_buffer_set_flags (GstBuffer * buffer, GstBufferFlags flags) +{ + GST_BUFFER_FLAG_SET (buffer, flags); + return TRUE; +} + +/** + * gst_buffer_unset_flags: + * @buffer: a #GstBuffer + * @flags: the #GstBufferFlags to clear + * + * Clears one or more buffer flags. + * + * Returns: true if @flags is successfully cleared from buffer. + * + * Since: 1.10 + */ +gboolean +gst_buffer_unset_flags (GstBuffer * buffer, GstBufferFlags flags) +{ + GST_BUFFER_FLAG_UNSET (buffer, flags); + return TRUE; +} + + + +/* transfer full for return and transfer none for @mem */ +static inline GstMemory * +_memory_get_exclusive_reference (GstMemory * mem) +{ + GstMemory *ret = NULL; + + if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) { + ret = gst_memory_ref (mem); + } else { + /* we cannot take another exclusive lock as the memory is already + * locked WRITE + EXCLUSIVE according to part-miniobject.txt */ + ret = gst_memory_copy (mem, 0, -1); + + if (ret) { + if (!gst_memory_lock (ret, GST_LOCK_FLAG_EXCLUSIVE)) { + gst_memory_unref (ret); + ret = NULL; + } + } + } + + if (!ret) + GST_CAT_WARNING (GST_CAT_BUFFER, "Failed to acquire an exclusive lock for " + "memory %p", mem); + + return ret; +} + +static inline void +_memory_add (GstBuffer * buffer, gint idx, GstMemory * mem) +{ + guint i, len = GST_BUFFER_MEM_LEN (buffer); + + GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %d, mem %p", buffer, idx, mem); + + if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) { + /* too many buffer, span them. */ + /* FIXME, there is room for improvement here: We could only try to merge + * 2 buffers to make some room. If we can't efficiently merge 2 buffers we + * could try to only merge the two smallest buffers to avoid memcpy, etc. */ + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p", + buffer); + _replace_memory (buffer, len, 0, len, _get_merged_memory (buffer, 0, len)); + /* we now have 1 single spanned buffer */ + len = 1; + } + + if (idx == -1) + idx = len; + + for (i = len; i > idx; i--) { + /* move buffers to insert, FIXME, we need to insert first and then merge */ + GST_BUFFER_MEM_PTR (buffer, i) = GST_BUFFER_MEM_PTR (buffer, i - 1); + } + /* and insert the new buffer */ + GST_BUFFER_MEM_PTR (buffer, idx) = mem; + GST_BUFFER_MEM_LEN (buffer) = len + 1; + + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); +} + +GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer); + +void +_priv_gst_buffer_initialize (void) +{ + _gst_buffer_type = gst_buffer_get_type (); +} + +/** + * gst_buffer_get_max_memory: + * + * Get the maximum amount of memory blocks that a buffer can hold. This is a + * compile time constant that can be queried with the function. + * + * When more memory blocks are added, existing memory blocks will be merged + * together to make room for the new block. + * + * Returns: the maximum amount of memory blocks that a buffer can hold. + * + * Since: 1.2 + */ +guint +gst_buffer_get_max_memory (void) +{ + return GST_BUFFER_MEM_MAX; +} + +/** + * gst_buffer_copy_into: + * @dest: a destination #GstBuffer + * @src: a source #GstBuffer + * @flags: flags indicating what metadata fields should be copied. + * @offset: offset to copy from + * @size: total size to copy. If -1, all data is copied. + * + * Copies the information from @src into @dest. + * + * If @dest already contains memory and @flags contains GST_BUFFER_COPY_MEMORY, + * the memory from @src will be appended to @dest. + * + * @flags indicate which fields will be copied. + * + * Returns: %TRUE if the copying succeeded, %FALSE otherwise. + */ +gboolean +gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, + GstBufferCopyFlags flags, gsize offset, gsize size) +{ + GstMetaItem *walk; + gsize bufsize; + gboolean region = FALSE; + + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (src != NULL, FALSE); + + /* nothing to copy if the buffers are the same */ + if (G_UNLIKELY (dest == src)) + return TRUE; + + g_return_val_if_fail (gst_buffer_is_writable (dest), FALSE); + + bufsize = gst_buffer_get_size (src); + g_return_val_if_fail (bufsize >= offset, FALSE); + if (offset > 0) + region = TRUE; + if (size == -1) + size = bufsize - offset; + if (size < bufsize) + region = TRUE; + g_return_val_if_fail (bufsize >= offset + size, FALSE); + + GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT + "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size, + bufsize); + + if (flags & GST_BUFFER_COPY_FLAGS) { + /* copy flags */ + guint flags_mask = ~GST_BUFFER_FLAG_TAG_MEMORY; + + GST_MINI_OBJECT_FLAGS (dest) = + (GST_MINI_OBJECT_FLAGS (src) & flags_mask) | + (GST_MINI_OBJECT_FLAGS (dest) & ~flags_mask); + } + + if (flags & GST_BUFFER_COPY_TIMESTAMPS) { + if (offset == 0) { + GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src); + GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src); + GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src); + if (size == bufsize) { + GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src); + GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src); + } + } else { + GST_BUFFER_PTS (dest) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DTS (dest) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE; + } + } + + if (flags & GST_BUFFER_COPY_MEMORY) { + gsize skip, left, len, dest_len, i, bsize; + gboolean deep; + + deep = flags & GST_BUFFER_COPY_DEEP; + + len = GST_BUFFER_MEM_LEN (src); + dest_len = GST_BUFFER_MEM_LEN (dest); + left = size; + skip = offset; + + /* copy and make regions of the memory */ + for (i = 0; i < len && left > 0; i++) { + GstMemory *mem = GST_BUFFER_MEM_PTR (src, i); + + bsize = gst_memory_get_sizes (mem, NULL, NULL); + + if (bsize <= skip) { + /* don't copy buffer */ + skip -= bsize; + } else { + GstMemory *newmem = NULL; + gsize tocopy; + + tocopy = MIN (bsize - skip, left); + + if (tocopy < bsize && !deep && !GST_MEMORY_IS_NO_SHARE (mem)) { + /* we need to clip something */ + newmem = gst_memory_share (mem, skip, tocopy); + if (newmem) { + gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE); + skip = 0; + } + } + + if (deep || GST_MEMORY_IS_NO_SHARE (mem) || (!newmem && tocopy < bsize)) { + /* deep copy or we're not allowed to share this memory + * between buffers, always copy then */ + newmem = gst_memory_copy (mem, skip, tocopy); + if (newmem) { + gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE); + skip = 0; + } + } else if (!newmem) { + newmem = _memory_get_exclusive_reference (mem); + } + + if (!newmem) { + gst_buffer_remove_memory_range (dest, dest_len, -1); + return FALSE; + } + + _memory_add (dest, -1, newmem); + left -= tocopy; + } + } + if (flags & GST_BUFFER_COPY_MERGE) { + GstMemory *mem; + + len = GST_BUFFER_MEM_LEN (dest); + mem = _get_merged_memory (dest, 0, len); + if (!mem) { + gst_buffer_remove_memory_range (dest, dest_len, -1); + return FALSE; + } + _replace_memory (dest, len, 0, len, mem); + } + } + + if (flags & GST_BUFFER_COPY_META) { + /* NOTE: GstGLSyncMeta copying relies on the meta + * being copied now, after the buffer data, + * so this has to happen last */ + for (walk = GST_BUFFER_META (src); walk; walk = walk->next) { + GstMeta *meta = &walk->meta; + const GstMetaInfo *info = meta->info; + + /* Don't copy memory metas if we only copied part of the buffer, didn't + * copy memories or merged memories. In all these cases the memory + * structure has changed and the memory meta becomes meaningless. + */ + if ((region || !(flags & GST_BUFFER_COPY_MEMORY) + || (flags & GST_BUFFER_COPY_MERGE)) + && gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) { + GST_CAT_DEBUG (GST_CAT_BUFFER, + "don't copy memory meta %p of API type %s", meta, + g_type_name (info->api)); + } else if (info->transform_func) { + GstMetaTransformCopy copy_data; + + copy_data.region = region; + copy_data.offset = offset; + copy_data.size = size; + + if (!info->transform_func (dest, meta, src, + _gst_meta_transform_copy, ©_data)) { + GST_CAT_ERROR (GST_CAT_BUFFER, + "failed to copy meta %p of API type %s", meta, + g_type_name (info->api)); + } + } + } + } + + return TRUE; +} + +static GstBuffer * +gst_buffer_copy_with_flags (const GstBuffer * buffer, GstBufferCopyFlags flags) +{ + GstBuffer *copy; + + g_return_val_if_fail (buffer != NULL, NULL); + + /* create a fresh new buffer */ + copy = gst_buffer_new (); + + /* copy what the 'flags' want from our parent */ + /* FIXME why we can't pass const to gst_buffer_copy_into() ? */ + if (!gst_buffer_copy_into (copy, (GstBuffer *) buffer, flags, 0, -1)) + gst_buffer_replace (©, NULL); + + if (copy) + GST_BUFFER_FLAG_UNSET (copy, GST_BUFFER_FLAG_TAG_MEMORY); + + return copy; +} + +static GstBuffer * +_gst_buffer_copy (const GstBuffer * buffer) +{ + return gst_buffer_copy_with_flags (buffer, GST_BUFFER_COPY_ALL); +} + +/** + * gst_buffer_copy_deep: + * @buf: a #GstBuffer. + * + * Create a copy of the given buffer. This will make a newly allocated + * copy of the data the source buffer contains. + * + * Returns: (transfer full): a new copy of @buf. + * + * Since: 1.6 + */ +GstBuffer * +gst_buffer_copy_deep (const GstBuffer * buffer) +{ + return gst_buffer_copy_with_flags (buffer, + GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP); +} + +/* the default dispose function revives the buffer and returns it to the + * pool when there is a pool */ +static gboolean +_gst_buffer_dispose (GstBuffer * buffer) +{ + GstBufferPool *pool; + + /* no pool, do free */ + if ((pool = buffer->pool) == NULL) + return TRUE; + + /* keep the buffer alive */ + gst_buffer_ref (buffer); + /* return the buffer to the pool */ + GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool); + gst_buffer_pool_release_buffer (pool, buffer); + + return FALSE; +} + +static void +_gst_buffer_free (GstBuffer * buffer) +{ + GstMetaItem *walk, *next; + guint i, len; + gsize msize; + + g_return_if_fail (buffer != NULL); + + GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer); + + /* free metadata */ + for (walk = GST_BUFFER_META (buffer); walk; walk = next) { + GstMeta *meta = &walk->meta; + const GstMetaInfo *info = meta->info; + + /* call free_func if any */ + if (info->free_func) + info->free_func (meta, buffer); + + next = walk->next; + /* and free the slice */ + g_slice_free1 (ITEM_SIZE (info), walk); + } + + /* get the size, when unreffing the memory, we could also unref the buffer + * itself */ + msize = GST_BUFFER_SLICE_SIZE (buffer); + + /* free our memory */ + len = GST_BUFFER_MEM_LEN (buffer); + for (i = 0; i < len; i++) { + gst_memory_unlock (GST_BUFFER_MEM_PTR (buffer, i), GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i)); + } + + /* we set msize to 0 when the buffer is part of the memory block */ + if (msize) { +#ifdef USE_POISONING + memset (buffer, 0xff, msize); +#endif + g_slice_free1 (msize, buffer); + } else { + gst_memory_unref (GST_BUFFER_BUFMEM (buffer)); + } +} + +static void +gst_buffer_init (GstBufferImpl * buffer, gsize size) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), 0, _gst_buffer_type, + (GstMiniObjectCopyFunction) _gst_buffer_copy, + (GstMiniObjectDisposeFunction) _gst_buffer_dispose, + (GstMiniObjectFreeFunction) _gst_buffer_free); + + GST_BUFFER_SLICE_SIZE (buffer) = size; + + GST_BUFFER (buffer)->pool = NULL; + GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE; + + GST_BUFFER_MEM_LEN (buffer) = 0; + GST_BUFFER_META (buffer) = NULL; +} + +/** + * gst_buffer_new: + * + * Creates a newly allocated buffer without any data. + * + * MT safe. + * + * Returns: (transfer full): the new #GstBuffer. + */ +GstBuffer * +gst_buffer_new (void) +{ + GstBufferImpl *newbuf; + + newbuf = g_slice_new (GstBufferImpl); + GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf); + + gst_buffer_init (newbuf, sizeof (GstBufferImpl)); + + return GST_BUFFER_CAST (newbuf); +} + +/** + * gst_buffer_new_allocate: + * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or %NULL to use the + * default allocator + * @size: the size in bytes of the new buffer's data. + * @params: (transfer none) (allow-none): optional parameters + * + * Tries to create a newly allocated buffer with data of the given size and + * extra parameters from @allocator. If the requested amount of memory can't be + * allocated, %NULL will be returned. The allocated buffer memory is not cleared. + * + * When @allocator is %NULL, the default memory allocator will be used. + * + * Note that when @size == 0, the buffer will not have memory associated with it. + * + * MT safe. + * + * Returns: (transfer full) (nullable): a new #GstBuffer, or %NULL if + * the memory couldn't be allocated. + */ +GstBuffer * +gst_buffer_new_allocate (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + GstBuffer *newbuf; + GstMemory *mem; +#if 0 + guint8 *data; + gsize asize; +#endif + +#if 1 + if (size > 0) { + mem = gst_allocator_alloc (allocator, size, params); + if (G_UNLIKELY (mem == NULL)) + goto no_memory; + } else { + mem = NULL; + } + + newbuf = gst_buffer_new (); + + if (mem != NULL) { + gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE); + _memory_add (newbuf, -1, mem); + } + + GST_CAT_LOG (GST_CAT_BUFFER, + "new buffer %p of size %" G_GSIZE_FORMAT " from allocator %p", newbuf, + size, allocator); +#endif + +#if 0 + asize = sizeof (GstBufferImpl) + size; + data = g_slice_alloc (asize); + if (G_UNLIKELY (data == NULL)) + goto no_memory; + + newbuf = GST_BUFFER_CAST (data); + + gst_buffer_init ((GstBufferImpl *) data, asize); + if (size > 0) { + mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL, + size, 0, size); + _memory_add (newbuf, -1, mem, TRUE); + } +#endif + +#if 0 + /* allocate memory and buffer, it might be interesting to do this but there + * are many complications. We need to keep the memory mapped to access the + * buffer fields and the memory for the buffer might be just very slow. We + * also need to do some more magic to get the alignment right. */ + asize = sizeof (GstBufferImpl) + size; + mem = gst_allocator_alloc (allocator, asize, align); + if (G_UNLIKELY (mem == NULL)) + goto no_memory; + + /* map the data part and init the buffer in it, set the buffer size to 0 so + * that a finalize won't free the buffer */ + data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE); + gst_buffer_init ((GstBufferImpl *) data, 0); + gst_memory_unmap (mem); + + /* strip off the buffer */ + gst_memory_resize (mem, sizeof (GstBufferImpl), size); + + newbuf = GST_BUFFER_CAST (data); + GST_BUFFER_BUFMEM (newbuf) = mem; + + if (size > 0) + _memory_add (newbuf, -1, gst_memory_ref (mem), TRUE); +#endif + GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY); + + return newbuf; + + /* ERRORS */ +no_memory: + { + GST_CAT_WARNING (GST_CAT_BUFFER, + "failed to allocate %" G_GSIZE_FORMAT " bytes", size); + return NULL; + } +} + +/** + * gst_buffer_new_wrapped_full: + * @flags: #GstMemoryFlags + * @data: (array length=size) (element-type guint8) (transfer none): data to wrap + * @maxsize: allocated size of @data + * @offset: offset in @data + * @size: size of valid data + * @user_data: (allow-none): user_data + * @notify: (allow-none) (scope async) (closure user_data): called with @user_data when the memory is freed + * + * Allocate a new buffer that wraps the given memory. @data must point to + * @maxsize of memory, the wrapped buffer will have the region from @offset and + * @size visible. + * + * When the buffer is destroyed, @notify will be called with @user_data. + * + * The prefix/padding must be filled with 0 if @flags contains + * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively. + * + * Returns: (transfer full): a new #GstBuffer + */ +GstBuffer * +gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data, + gsize maxsize, gsize offset, gsize size, gpointer user_data, + GDestroyNotify notify) +{ + GstMemory *mem; + GstBuffer *newbuf; + + newbuf = gst_buffer_new (); + mem = + gst_memory_new_wrapped (flags, data, maxsize, offset, size, user_data, + notify); + gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE); + _memory_add (newbuf, -1, mem); + GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY); + + return newbuf; +} + +/** + * gst_buffer_new_wrapped: + * @data: (array length=size) (element-type guint8) (transfer full): data to wrap + * @size: allocated size of @data + * + * Creates a new buffer that wraps the given @data. The memory will be freed + * with g_free and will be marked writable. + * + * MT safe. + * + * Returns: (transfer full): a new #GstBuffer + */ +GstBuffer * +gst_buffer_new_wrapped (gpointer data, gsize size) +{ + return gst_buffer_new_wrapped_full (0, data, size, 0, size, data, g_free); +} + +/** + * gst_buffer_n_memory: + * @buffer: a #GstBuffer. + * + * Get the amount of memory blocks that this buffer has. This amount is never + * larger than what gst_buffer_get_max_memory() returns. + * + * Returns: the number of memory blocks this buffer is made of. + */ +guint +gst_buffer_n_memory (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + + return GST_BUFFER_MEM_LEN (buffer); +} + +/** + * gst_buffer_prepend_memory: + * @buffer: a #GstBuffer. + * @mem: (transfer full): a #GstMemory. + * + * Prepend the memory block @mem to @buffer. This function takes + * ownership of @mem and thus doesn't increase its refcount. + * + * This function is identical to gst_buffer_insert_memory() with an index of 0. + * See gst_buffer_insert_memory() for more details. + */ +void +gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem) +{ + gst_buffer_insert_memory (buffer, 0, mem); +} + +/** + * gst_buffer_append_memory: + * @buffer: a #GstBuffer. + * @mem: (transfer full): a #GstMemory. + * + * Append the memory block @mem to @buffer. This function takes + * ownership of @mem and thus doesn't increase its refcount. + * + * This function is identical to gst_buffer_insert_memory() with an index of -1. + * See gst_buffer_insert_memory() for more details. + */ +void +gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem) +{ + gst_buffer_insert_memory (buffer, -1, mem); +} + +/** + * gst_buffer_insert_memory: + * @buffer: a #GstBuffer. + * @idx: the index to add the memory at, or -1 to append it to the end + * @mem: (transfer full): a #GstMemory. + * + * Insert the memory block @mem to @buffer at @idx. This function takes ownership + * of @mem and thus doesn't increase its refcount. + * + * Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is + * added, existing memory blocks will automatically be merged to make room for + * the new memory. + */ +void +gst_buffer_insert_memory (GstBuffer * buffer, gint idx, GstMemory * mem) +{ + GstMemory *tmp; + + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (gst_buffer_is_writable (buffer)); + g_return_if_fail (mem != NULL); + g_return_if_fail (idx == -1 || + (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer))); + + tmp = _memory_get_exclusive_reference (mem); + g_return_if_fail (tmp != NULL); + gst_memory_unref (mem); + _memory_add (buffer, idx, tmp); +} + +static GstMemory * +_get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info, + GstMapFlags flags) +{ + GstMemory *mem, *mapped; + + mem = gst_memory_ref (GST_BUFFER_MEM_PTR (buffer, idx)); + + mapped = gst_memory_make_mapped (mem, info, flags); + + if (mapped != mem) { + /* memory changed, lock new memory */ + gst_memory_lock (mapped, GST_LOCK_FLAG_EXCLUSIVE); + GST_BUFFER_MEM_PTR (buffer, idx) = mapped; + /* unlock old memory */ + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); + } + gst_memory_unref (mem); + + return mapped; +} + +/** + * gst_buffer_peek_memory: + * @buffer: a #GstBuffer. + * @idx: an index + * + * Get the memory block at @idx in @buffer. The memory block stays valid until + * the memory block in @buffer is removed, replaced or merged, typically with + * any call that modifies the memory in @buffer. + * + * Returns: (transfer none) (nullable): the #GstMemory at @idx. + */ +GstMemory * +gst_buffer_peek_memory (GstBuffer * buffer, guint idx) +{ + guint len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail (idx < len, NULL); + + return GST_BUFFER_MEM_PTR (buffer, idx); +} + +/** + * gst_buffer_get_memory: + * @buffer: a #GstBuffer. + * @idx: an index + * + * Get the memory block at index @idx in @buffer. + * + * Returns: (transfer full) (nullable): a #GstMemory that contains the data of the + * memory block at @idx. Use gst_memory_unref () after usage. + */ +GstMemory * +gst_buffer_get_memory (GstBuffer * buffer, guint idx) +{ + return gst_buffer_get_memory_range (buffer, idx, 1); +} + +/** + * gst_buffer_get_all_memory: + * @buffer: a #GstBuffer. + * + * Get all the memory block in @buffer. The memory blocks will be merged + * into one large #GstMemory. + * + * Returns: (transfer full) (nullable): a #GstMemory that contains the merged memory. + * Use gst_memory_unref () after usage. + */ +GstMemory * +gst_buffer_get_all_memory (GstBuffer * buffer) +{ + return gst_buffer_get_memory_range (buffer, 0, -1); +} + +/** + * gst_buffer_get_memory_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length + * + * Get @length memory blocks in @buffer starting at @idx. The memory blocks will + * be merged into one large #GstMemory. + * + * If @length is -1, all memory starting from @idx is merged. + * + * Returns: (transfer full) (nullable): a #GstMemory that contains the merged data of @length + * blocks starting at @idx. Use gst_memory_unref () after usage. + */ +GstMemory * +gst_buffer_get_memory_range (GstBuffer * buffer, guint idx, gint length) +{ + guint len; + + GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length); + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length > 0 && length + idx <= len), NULL); + + if (length == -1) + length = len - idx; + + return _get_merged_memory (buffer, idx, length); +} + +/** + * gst_buffer_replace_memory: + * @buffer: a #GstBuffer. + * @idx: an index + * @mem: (transfer full): a #GstMemory + * + * Replaces the memory block at index @idx in @buffer with @mem. + */ +void +gst_buffer_replace_memory (GstBuffer * buffer, guint idx, GstMemory * mem) +{ + gst_buffer_replace_memory_range (buffer, idx, 1, mem); +} + +/** + * gst_buffer_replace_all_memory: + * @buffer: a #GstBuffer. + * @mem: (transfer full): a #GstMemory + * + * Replaces all memory in @buffer with @mem. + */ +void +gst_buffer_replace_all_memory (GstBuffer * buffer, GstMemory * mem) +{ + gst_buffer_replace_memory_range (buffer, 0, -1, mem); +} + +/** + * gst_buffer_replace_memory_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length should not be 0 + * @mem: (transfer full): a #GstMemory + * + * Replaces @length memory blocks in @buffer starting at @idx with @mem. + * + * If @length is -1, all memory starting from @idx will be removed and + * replaced with @mem. + * + * @buffer should be writable. + */ +void +gst_buffer_replace_memory_range (GstBuffer * buffer, guint idx, gint length, + GstMemory * mem) +{ + guint len; + + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (gst_buffer_is_writable (buffer)); + + GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d, %p", idx, length, mem); + + len = GST_BUFFER_MEM_LEN (buffer); + g_return_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length > 0 && length + idx <= len)); + + if (length == -1) + length = len - idx; + + _replace_memory (buffer, len, idx, length, mem); +} + +/** + * gst_buffer_remove_memory: + * @buffer: a #GstBuffer. + * @idx: an index + * + * Remove the memory block in @b at index @i. + */ +void +gst_buffer_remove_memory (GstBuffer * buffer, guint idx) +{ + gst_buffer_remove_memory_range (buffer, idx, 1); +} + +/** + * gst_buffer_remove_all_memory: + * @buffer: a #GstBuffer. + * + * Remove all the memory blocks in @buffer. + */ +void +gst_buffer_remove_all_memory (GstBuffer * buffer) +{ + gst_buffer_remove_memory_range (buffer, 0, -1); +} + +/** + * gst_buffer_remove_memory_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length + * + * Remove @length memory blocks in @buffer starting from @idx. + * + * @length can be -1, in which case all memory starting from @idx is removed. + */ +void +gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length) +{ + guint len; + + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (gst_buffer_is_writable (buffer)); + + GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length); + + len = GST_BUFFER_MEM_LEN (buffer); + g_return_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || length + idx <= len); + + if (length == -1) + length = len - idx; + + _replace_memory (buffer, len, idx, length, NULL); +} + +/** + * gst_buffer_find_memory: + * @buffer: a #GstBuffer. + * @offset: an offset + * @size: a size + * @idx: (out): pointer to index + * @length: (out): pointer to length + * @skip: (out): pointer to skip + * + * Find the memory blocks that span @size bytes starting from @offset + * in @buffer. + * + * When this function returns %TRUE, @idx will contain the index of the first + * memory block where the byte for @offset can be found and @length contains the + * number of memory blocks containing the @size remaining bytes. @skip contains + * the number of bytes to skip in the memory block at @idx to get to the byte + * for @offset. + * + * @size can be -1 to get all the memory blocks after @idx. + * + * Returns: %TRUE when @size bytes starting from @offset could be found in + * @buffer and @idx, @length and @skip will be filled. + */ +gboolean +gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size, + guint * idx, guint * length, gsize * skip) +{ + guint i, len, found; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (idx != NULL, FALSE); + g_return_val_if_fail (length != NULL, FALSE); + g_return_val_if_fail (skip != NULL, FALSE); + + len = GST_BUFFER_MEM_LEN (buffer); + + found = 0; + for (i = 0; i < len; i++) { + GstMemory *mem; + gsize s; + + mem = GST_BUFFER_MEM_PTR (buffer, i); + s = gst_memory_get_sizes (mem, NULL, NULL); + + if (s <= offset) { + /* block before offset, or empty block, skip */ + offset -= s; + } else { + /* block after offset */ + if (found == 0) { + /* first block, remember index and offset */ + *idx = i; + *skip = offset; + if (size == -1) { + /* return remaining blocks */ + *length = len - i; + return TRUE; + } + s -= offset; + offset = 0; + } + /* count the amount of found bytes */ + found += s; + if (found >= size) { + /* we have enough bytes */ + *length = i - *idx + 1; + return TRUE; + } + } + } + return FALSE; +} + +/** + * gst_buffer_is_memory_range_writable: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length should not be 0 + * + * Check if @length memory blocks in @buffer starting from @idx are writable. + * + * @length can be -1 to check all the memory blocks after @idx. + * + * Note that this function does not check if @buffer is writable, use + * gst_buffer_is_writable() to check that if needed. + * + * Returns: %TRUE if the memory range is writable + * + * Since: 1.4 + */ +gboolean +gst_buffer_is_memory_range_writable (GstBuffer * buffer, guint idx, gint length) +{ + guint i, len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length); + + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length > 0 && length + idx <= len), + FALSE); + + if (length == -1) + len -= idx; + else + len = length; + + for (i = 0; i < len; i++) { + if (!gst_memory_is_writable (GST_BUFFER_MEM_PTR (buffer, i + idx))) + return FALSE; + } + return TRUE; +} + +/** + * gst_buffer_is_all_memory_writable: + * @buffer: a #GstBuffer. + * + * Check if all memory blocks in @buffer are writable. + * + * Note that this function does not check if @buffer is writable, use + * gst_buffer_is_writable() to check that if needed. + * + * Returns: %TRUE if all memory blocks in @buffer are writable + * + * Since: 1.4 + */ +gboolean +gst_buffer_is_all_memory_writable (GstBuffer * buffer) +{ + return gst_buffer_is_memory_range_writable (buffer, 0, -1); +} + +/** + * gst_buffer_get_sizes: + * @buffer: a #GstBuffer. + * @offset: (out) (allow-none): a pointer to the offset + * @maxsize: (out) (allow-none): a pointer to the maxsize + * + * Get the total size of the memory blocks in @b. + * + * When not %NULL, @offset will contain the offset of the data in the + * first memory block in @buffer and @maxsize will contain the sum of + * the size and @offset and the amount of extra padding on the last + * memory block. @offset and @maxsize can be used to resize the + * buffer memory blocks with gst_buffer_resize(). + * + * Returns: total size of the memory blocks in @buffer. + */ +gsize +gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize) +{ + return gst_buffer_get_sizes_range (buffer, 0, -1, offset, maxsize); +} + +/** + * gst_buffer_get_size: + * @buffer: a #GstBuffer. + * + * Get the total size of the memory blocks in @buffer. + * + * Returns: total size of the memory blocks in @buffer. + */ +gsize +gst_buffer_get_size (GstBuffer * buffer) +{ + return gst_buffer_get_sizes_range (buffer, 0, -1, NULL, NULL); +} + +/** + * gst_buffer_get_sizes_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length + * @offset: (out) (allow-none): a pointer to the offset + * @maxsize: (out) (allow-none): a pointer to the maxsize + * + * Get the total size of @length memory blocks stating from @idx in @buffer. + * + * When not %NULL, @offset will contain the offset of the data in the + * memory block in @buffer at @idx and @maxsize will contain the sum of the size + * and @offset and the amount of extra padding on the memory block at @idx + + * @length -1. + * @offset and @maxsize can be used to resize the buffer memory blocks with + * gst_buffer_resize_range(). + * + * Returns: total size of @length memory blocks starting at @idx in @buffer. + */ +gsize +gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length, + gsize * offset, gsize * maxsize) +{ + guint len; + gsize size; + GstMemory *mem; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length + idx <= len), 0); + + if (length == -1) + length = len - idx; + + if (G_LIKELY (length == 1)) { + /* common case */ + mem = GST_BUFFER_MEM_PTR (buffer, idx); + size = gst_memory_get_sizes (mem, offset, maxsize); + } else { + guint i, end; + gsize extra, offs; + + end = idx + length; + size = offs = extra = 0; + for (i = idx; i < end; i++) { + gsize s, o, ms; + + mem = GST_BUFFER_MEM_PTR (buffer, i); + s = gst_memory_get_sizes (mem, &o, &ms); + + if (s) { + if (size == 0) + /* first size, take accumulated data before as the offset */ + offs = extra + o; + /* add sizes */ + size += s; + /* save the amount of data after this block */ + extra = ms - (o + s); + } else { + /* empty block, add as extra */ + extra += ms; + } + } + if (offset) + *offset = offs; + if (maxsize) + *maxsize = offs + size + extra; + } + return size; +} + +/** + * gst_buffer_resize: + * @buffer: a #GstBuffer. + * @offset: the offset adjustment + * @size: the new size or -1 to just adjust the offset + * + * Set the offset and total size of the memory blocks in @buffer. + */ +void +gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size) +{ + gst_buffer_resize_range (buffer, 0, -1, offset, size); +} + +/** + * gst_buffer_set_size: + * @buffer: a #GstBuffer. + * @size: the new size + * + * Set the total size of the memory blocks in @buffer. + */ +void +gst_buffer_set_size (GstBuffer * buffer, gssize size) +{ + gst_buffer_resize_range (buffer, 0, -1, 0, size); +} + +/** + * gst_buffer_resize_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length + * @offset: the offset adjustment + * @size: the new size or -1 to just adjust the offset + * + * Set the total size of the @length memory blocks starting at @idx in + * @buffer + * + * Returns: %TRUE if resizing succeeded, %FALSE otherwise. + */ +gboolean +gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, + gssize offset, gssize size) +{ + guint i, len, end; + gsize bsize, bufsize, bufoffs, bufmax; + + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + g_return_val_if_fail (size >= -1, FALSE); + + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length + idx <= len), FALSE); + + if (length == -1) + length = len - idx; + + bufsize = gst_buffer_get_sizes_range (buffer, idx, length, &bufoffs, &bufmax); + + GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT + " size:%" G_GSIZE_FORMAT " offs:%" G_GSIZE_FORMAT " max:%" + G_GSIZE_FORMAT, buffer, offset, size, bufsize, bufoffs, bufmax); + + /* we can't go back further than the current offset or past the end of the + * buffer */ + g_return_val_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0 + && bufoffs + offset <= bufmax), FALSE); + if (size == -1) { + g_return_val_if_fail (bufsize >= offset, FALSE); + size = bufsize - offset; + } + g_return_val_if_fail (bufmax >= bufoffs + offset + size, FALSE); + + /* no change */ + if (offset == 0 && size == bufsize) + return TRUE; + + end = idx + length; + /* copy and trim */ + for (i = idx; i < end; i++) { + GstMemory *mem; + gsize left, noffs; + + mem = GST_BUFFER_MEM_PTR (buffer, i); + bsize = gst_memory_get_sizes (mem, NULL, NULL); + + noffs = 0; + /* last buffer always gets resized to the remaining size */ + if (i + 1 == end) + left = size; + /* shrink buffers before the offset */ + else if ((gssize) bsize <= offset) { + left = 0; + noffs = offset - bsize; + offset = 0; + } + /* clip other buffers */ + else + left = MIN (bsize - offset, size); + + if (offset != 0 || left != bsize) { + if (gst_memory_is_writable (mem)) { + gst_memory_resize (mem, offset, left); + } else { + GstMemory *newmem = NULL; + + if (!GST_MEMORY_IS_NO_SHARE (mem)) + newmem = gst_memory_share (mem, offset, left); + + if (!newmem) + newmem = gst_memory_copy (mem, offset, left); + + if (newmem == NULL) + return FALSE; + + gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE); + GST_BUFFER_MEM_PTR (buffer, i) = newmem; + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unref (mem); + + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); + } + } + + offset = noffs; + size -= left; + } + + return TRUE; +} + +/** + * gst_buffer_map: + * @buffer: a #GstBuffer. + * @info: (out): info about the mapping + * @flags: flags for the mapping + * + * This function fills @info with the #GstMapInfo of all merged memory + * blocks in @buffer. + * + * @flags describe the desired access of the memory. When @flags is + * #GST_MAP_WRITE, @buffer should be writable (as returned from + * gst_buffer_is_writable()). + * + * When @buffer is writable but the memory isn't, a writable copy will + * automatically be created and returned. The readonly copy of the + * buffer memory will then also be replaced with this writable copy. + * + * The memory in @info should be unmapped with gst_buffer_unmap() after + * usage. + * + * Returns: %TRUE if the map succeeded and @info contains valid data. + */ +gboolean +gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags) +{ + return gst_buffer_map_range (buffer, 0, -1, info, flags); +} + +/** + * gst_buffer_map_range: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length + * @info: (out): info about the mapping + * @flags: flags for the mapping + * + * This function fills @info with the #GstMapInfo of @length merged memory blocks + * starting at @idx in @buffer. When @length is -1, all memory blocks starting + * from @idx are merged and mapped. + * + * @flags describe the desired access of the memory. When @flags is + * #GST_MAP_WRITE, @buffer should be writable (as returned from + * gst_buffer_is_writable()). + * + * When @buffer is writable but the memory isn't, a writable copy will + * automatically be created and returned. The readonly copy of the buffer memory + * will then also be replaced with this writable copy. + * + * The memory in @info should be unmapped with gst_buffer_unmap() after usage. + * + * Returns: %TRUE if the map succeeded and @info contains valid + * data. + */ +gboolean +gst_buffer_map_range (GstBuffer * buffer, guint idx, gint length, + GstMapInfo * info, GstMapFlags flags) +{ + GstMemory *mem, *nmem; + gboolean write, writable; + gsize len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (info != NULL, FALSE); + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length > 0 + && length + idx <= len), FALSE); + + GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %d, flags %04x", + buffer, idx, length, flags); + + write = (flags & GST_MAP_WRITE) != 0; + writable = gst_buffer_is_writable (buffer); + + /* check if we can write when asked for write access */ + if (G_UNLIKELY (write && !writable)) + goto not_writable; + + if (length == -1) + length = len - idx; + + mem = _get_merged_memory (buffer, idx, length); + if (G_UNLIKELY (mem == NULL)) + goto no_memory; + + /* now try to map */ + nmem = gst_memory_make_mapped (mem, info, flags); + if (G_UNLIKELY (nmem == NULL)) + goto cannot_map; + + /* if we merged or when the map returned a different memory, we try to replace + * the memory in the buffer */ + if (G_UNLIKELY (length > 1 || nmem != mem)) { + /* if the buffer is writable, replace the memory */ + if (writable) { + _replace_memory (buffer, len, idx, length, gst_memory_ref (nmem)); + } else { + if (len > 1) { + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, + "temporary mapping for memory %p in buffer %p", nmem, buffer); + } + } + } + return TRUE; + + /* ERROR */ +not_writable: + { + GST_WARNING_OBJECT (buffer, "write map requested on non-writable buffer"); + g_critical ("write map requested on non-writable buffer"); + memset (info, 0, sizeof (GstMapInfo)); + return FALSE; + } +no_memory: + { + /* empty buffer, we need to return NULL */ + GST_DEBUG_OBJECT (buffer, "can't get buffer memory"); + memset (info, 0, sizeof (GstMapInfo)); + return TRUE; + } +cannot_map: + { + GST_DEBUG_OBJECT (buffer, "cannot map memory"); + memset (info, 0, sizeof (GstMapInfo)); + return FALSE; + } +} + +/** + * gst_buffer_unmap: + * @buffer: a #GstBuffer. + * @info: a #GstMapInfo + * + * Release the memory previously mapped with gst_buffer_map(). + */ +void +gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (info != NULL); + + /* we need to check for NULL, it is possible that we tried to map a buffer + * without memory and we should be able to unmap that fine */ + if (G_LIKELY (info->memory)) { + gst_memory_unmap (info->memory, info); + gst_memory_unref (info->memory); + } +} + +/** + * gst_buffer_fill: + * @buffer: a #GstBuffer. + * @offset: the offset to fill + * @src: (array length=size) (element-type guint8): the source address + * @size: the size to fill + * + * Copy @size bytes from @src to @buffer at @offset. + * + * Returns: The amount of bytes copied. This value can be lower than @size + * when @buffer did not contain enough data. + */ +gsize +gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src, + gsize size) +{ + gsize i, len, left; + const guint8 *ptr = src; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (gst_buffer_is_writable (buffer), 0); + g_return_val_if_fail (src != NULL || size == 0, 0); + + GST_CAT_LOG (GST_CAT_BUFFER, + "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer, + offset, size); + + len = GST_BUFFER_MEM_LEN (buffer); + left = size; + + for (i = 0; i < len && left > 0; i++) { + GstMapInfo info; + gsize tocopy; + GstMemory *mem; + + mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE); + if (info.size > offset) { + /* we have enough */ + tocopy = MIN (info.size - offset, left); + memcpy ((guint8 *) info.data + offset, ptr, tocopy); + left -= tocopy; + ptr += tocopy; + offset = 0; + } else { + /* offset past buffer, skip */ + offset -= info.size; + } + gst_memory_unmap (mem, &info); + } + return size - left; +} + +/** + * gst_buffer_extract: + * @buffer: a #GstBuffer. + * @offset: the offset to extract + * @dest: (out caller-allocates) (array length=size) (element-type guint8): + * the destination address + * @size: the size to extract + * + * Copy @size bytes starting from @offset in @buffer to @dest. + * + * Returns: The amount of bytes extracted. This value can be lower than @size + * when @buffer did not contain enough data. + */ +gsize +gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size) +{ + gsize i, len, left; + guint8 *ptr = dest; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (dest != NULL, 0); + + GST_CAT_LOG (GST_CAT_BUFFER, + "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer, + offset, size); + + len = GST_BUFFER_MEM_LEN (buffer); + left = size; + + for (i = 0; i < len && left > 0; i++) { + GstMapInfo info; + gsize tocopy; + GstMemory *mem; + + mem = _get_mapped (buffer, i, &info, GST_MAP_READ); + if (info.size > offset) { + /* we have enough */ + tocopy = MIN (info.size - offset, left); + memcpy (ptr, (guint8 *) info.data + offset, tocopy); + left -= tocopy; + ptr += tocopy; + offset = 0; + } else { + /* offset past buffer, skip */ + offset -= info.size; + } + gst_memory_unmap (mem, &info); + } + return size - left; +} + +/** + * gst_buffer_memcmp: + * @buffer: a #GstBuffer. + * @offset: the offset in @buffer + * @mem: (array length=size) (element-type guint8): the memory to compare + * @size: the size to compare + * + * Compare @size bytes starting from @offset in @buffer with the memory in @mem. + * + * Returns: 0 if the memory is equal. + */ +gint +gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem, + gsize size) +{ + gsize i, len; + const guint8 *ptr = mem; + gint res = 0; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (mem != NULL, 0); + + GST_CAT_LOG (GST_CAT_BUFFER, + "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer, + offset, size); + + if (G_UNLIKELY (gst_buffer_get_size (buffer) < offset + size)) + return -1; + + len = GST_BUFFER_MEM_LEN (buffer); + + for (i = 0; i < len && size > 0 && res == 0; i++) { + GstMapInfo info; + gsize tocmp; + GstMemory *mem; + + mem = _get_mapped (buffer, i, &info, GST_MAP_READ); + if (info.size > offset) { + /* we have enough */ + tocmp = MIN (info.size - offset, size); + res = memcmp (ptr, (guint8 *) info.data + offset, tocmp); + size -= tocmp; + ptr += tocmp; + offset = 0; + } else { + /* offset past buffer, skip */ + offset -= info.size; + } + gst_memory_unmap (mem, &info); + } + return res; +} + +/** + * gst_buffer_memset: + * @buffer: a #GstBuffer. + * @offset: the offset in @buffer + * @val: the value to set + * @size: the size to set + * + * Fill @buf with @size bytes with @val starting from @offset. + * + * Returns: The amount of bytes filled. This value can be lower than @size + * when @buffer did not contain enough data. + */ +gsize +gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size) +{ + gsize i, len, left; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (gst_buffer_is_writable (buffer), 0); + + GST_CAT_LOG (GST_CAT_BUFFER, + "buffer %p, offset %" G_GSIZE_FORMAT ", val %02x, size %" G_GSIZE_FORMAT, + buffer, offset, val, size); + + len = GST_BUFFER_MEM_LEN (buffer); + left = size; + + for (i = 0; i < len && left > 0; i++) { + GstMapInfo info; + gsize toset; + GstMemory *mem; + + mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE); + if (info.size > offset) { + /* we have enough */ + toset = MIN (info.size - offset, left); + memset ((guint8 *) info.data + offset, val, toset); + left -= toset; + offset = 0; + } else { + /* offset past buffer, skip */ + offset -= info.size; + } + gst_memory_unmap (mem, &info); + } + return size - left; +} + +/** + * gst_buffer_copy_region: + * @parent: a #GstBuffer. + * @flags: the #GstBufferCopyFlags + * @offset: the offset into parent #GstBuffer at which the new sub-buffer + * begins. + * @size: the size of the new #GstBuffer sub-buffer, in bytes. If -1, all + * data is copied. + * + * Creates a sub-buffer from @parent at @offset and @size. + * This sub-buffer uses the actual memory space of the parent buffer. + * This function will copy the offset and timestamp fields when the + * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and + * #GST_BUFFER_OFFSET_NONE. + * If @offset equals 0 and @size equals the total size of @buffer, the + * duration and offset end fields are also copied. If not they will be set + * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE. + * + * MT safe. + * + * Returns: (transfer full): the new #GstBuffer or %NULL if the arguments were + * invalid. + */ +GstBuffer * +gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags, + gsize offset, gsize size) +{ + GstBuffer *copy; + + g_return_val_if_fail (buffer != NULL, NULL); + + /* create the new buffer */ + copy = gst_buffer_new (); + + GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT + "-%" G_GSIZE_FORMAT, copy, buffer, offset, size); + + if (!gst_buffer_copy_into (copy, buffer, flags, offset, size)) + gst_buffer_replace (©, NULL); + + return copy; +} + +/** + * gst_buffer_append: + * @buf1: (transfer full): the first source #GstBuffer to append. + * @buf2: (transfer full): the second source #GstBuffer to append. + * + * Append all the memory from @buf2 to @buf1. The result buffer will contain a + * concatenation of the memory of @buf1 and @buf2. + * + * Returns: (transfer full): the new #GstBuffer that contains the memory + * of the two source buffers. + */ +GstBuffer * +gst_buffer_append (GstBuffer * buf1, GstBuffer * buf2) +{ + return gst_buffer_append_region (buf1, buf2, 0, -1); +} + +/** + * gst_buffer_append_region: + * @buf1: (transfer full): the first source #GstBuffer to append. + * @buf2: (transfer full): the second source #GstBuffer to append. + * @offset: the offset in @buf2 + * @size: the size or -1 of @buf2 + * + * Append @size bytes at @offset from @buf2 to @buf1. The result buffer will + * contain a concatenation of the memory of @buf1 and the requested region of + * @buf2. + * + * Returns: (transfer full): the new #GstBuffer that contains the memory + * of the two source buffers. + */ +GstBuffer * +gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset, + gssize size) +{ + gsize i, len; + + g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL); + g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL); + + buf1 = gst_buffer_make_writable (buf1); + buf2 = gst_buffer_make_writable (buf2); + + gst_buffer_resize (buf2, offset, size); + + len = GST_BUFFER_MEM_LEN (buf2); + for (i = 0; i < len; i++) { + GstMemory *mem; + + mem = GST_BUFFER_MEM_PTR (buf2, i); + GST_BUFFER_MEM_PTR (buf2, i) = NULL; + _memory_add (buf1, -1, mem); + } + + GST_BUFFER_MEM_LEN (buf2) = 0; + GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_TAG_MEMORY); + gst_buffer_unref (buf2); + + return buf1; +} + +/** + * gst_buffer_get_meta: + * @buffer: a #GstBuffer + * @api: the #GType of an API + * + * Get the metadata for @api on buffer. When there is no such metadata, %NULL is + * returned. If multiple metadata with the given @api are attached to this + * buffer only the first one is returned. To handle multiple metadata with a + * given API use gst_buffer_iterate_meta() or gst_buffer_foreach_meta() instead + * and check the meta->info.api member for the API type. + * + * Returns: (transfer none) (nullable): the metadata for @api on + * @buffer. + */ +GstMeta * +gst_buffer_get_meta (GstBuffer * buffer, GType api) +{ + GstMetaItem *item; + GstMeta *result = NULL; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (api != 0, NULL); + + /* find GstMeta of the requested API */ + for (item = GST_BUFFER_META (buffer); item; item = item->next) { + GstMeta *meta = &item->meta; + if (meta->info->api == api) { + result = meta; + break; + } + } + return result; +} + +/** + * gst_buffer_get_n_meta: + * @buffer: a #GstBuffer + * @api_type: the #GType of an API + * + * Returns: number of metas of type @api_type on @buffer. + * + * Since: 1.14 + */ +guint +gst_buffer_get_n_meta (GstBuffer * buffer, GType api_type) +{ + gpointer state = NULL; + GstMeta *meta; + guint n = 0; + + while ((meta = gst_buffer_iterate_meta_filtered (buffer, &state, api_type))) + ++n; + + return n; +} + +/** + * gst_buffer_add_meta: + * @buffer: a #GstBuffer + * @info: a #GstMetaInfo + * @params: params for @info + * + * Add metadata for @info to @buffer using the parameters in @params. + * + * Returns: (transfer none) (nullable): the metadata for the api in @info on @buffer. + */ +GstMeta * +gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info, + gpointer params) +{ + GstMetaItem *item; + GstMeta *result = NULL; + gsize size; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL); + + /* create a new slice */ + size = ITEM_SIZE (info); + /* We warn in gst_meta_register() about metas without + * init function but let's play safe here and prevent + * uninitialized memory + */ + if (!info->init_func) + item = g_slice_alloc0 (size); + else + item = g_slice_alloc (size); + result = &item->meta; + result->info = info; + result->flags = GST_META_FLAG_NONE; + GST_CAT_DEBUG (GST_CAT_BUFFER, + "alloc metadata %p (%s) of size %" G_GSIZE_FORMAT, result, + g_type_name (info->type), info->size); + + /* call the init_func when needed */ + if (info->init_func) + if (!info->init_func (result, params, buffer)) + goto init_failed; + + /* and add to the list of metadata */ + item->next = GST_BUFFER_META (buffer); + GST_BUFFER_META (buffer) = item; + + return result; + +init_failed: + { + g_slice_free1 (size, item); + return NULL; + } +} + +/** + * gst_buffer_remove_meta: + * @buffer: a #GstBuffer + * @meta: a #GstMeta + * + * Remove the metadata for @meta on @buffer. + * + * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such + * metadata was on @buffer. + */ +gboolean +gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta) +{ + GstMetaItem *walk, *prev; + + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (meta != NULL, FALSE); + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + g_return_val_if_fail (!GST_META_FLAG_IS_SET (meta, GST_META_FLAG_LOCKED), + FALSE); + + /* find the metadata and delete */ + prev = GST_BUFFER_META (buffer); + for (walk = prev; walk; walk = walk->next) { + GstMeta *m = &walk->meta; + if (m == meta) { + const GstMetaInfo *info = meta->info; + + /* remove from list */ + if (GST_BUFFER_META (buffer) == walk) + GST_BUFFER_META (buffer) = walk->next; + else + prev->next = walk->next; + /* call free_func if any */ + if (info->free_func) + info->free_func (m, buffer); + + /* and free the slice */ + g_slice_free1 (ITEM_SIZE (info), walk); + break; + } + prev = walk; + } + return walk != NULL; +} + +/** + * gst_buffer_iterate_meta: (skip) + * @buffer: a #GstBuffer + * @state: (out caller-allocates): an opaque state pointer + * + * Retrieve the next #GstMeta after @current. If @state points + * to %NULL, the first metadata is returned. + * + * @state will be updated with an opaque state pointer + * + * Returns: (transfer none) (nullable): The next #GstMeta or %NULL + * when there are no more items. + */ +GstMeta * +gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state) +{ + GstMetaItem **meta; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (state != NULL, NULL); + + meta = (GstMetaItem **) state; + if (*meta == NULL) + /* state NULL, move to first item */ + *meta = GST_BUFFER_META (buffer); + else + /* state !NULL, move to next item in list */ + *meta = (*meta)->next; + + if (*meta) + return &(*meta)->meta; + else + return NULL; +} + +/** + * gst_buffer_iterate_meta_filtered: (skip) + * @buffer: a #GstBuffer + * @state: (out caller-allocates): an opaque state pointer + * @meta_api_type: only return #GstMeta of this type + * + * Retrieve the next #GstMeta of type @meta_api_type after the current one + * according to @state. If @state points to %NULL, the first metadata of + * type @meta_api_type is returned. + * + * @state will be updated with an opaque state pointer + * + * Returns: (transfer none) (nullable): The next #GstMeta of type + * @meta_api_type or %NULL when there are no more items. + * + * Since: 1.12 + */ +GstMeta * +gst_buffer_iterate_meta_filtered (GstBuffer * buffer, gpointer * state, + GType meta_api_type) +{ + GstMetaItem **meta; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (state != NULL, NULL); + + meta = (GstMetaItem **) state; + if (*meta == NULL) + /* state NULL, move to first item */ + *meta = GST_BUFFER_META (buffer); + else + /* state !NULL, move to next item in list */ + *meta = (*meta)->next; + + while (*meta != NULL && (*meta)->meta.info->api != meta_api_type) + *meta = (*meta)->next; + + if (*meta) + return &(*meta)->meta; + else + return NULL; +} + +/** + * gst_buffer_foreach_meta: + * @buffer: a #GstBuffer + * @func: (scope call): a #GstBufferForeachMetaFunc to call + * @user_data: (closure): user data passed to @func + * + * Call @func with @user_data for each meta in @buffer. + * + * @func can modify the passed meta pointer or its contents. The return value + * of @func define if this function returns or if the remaining metadata items + * in the buffer should be skipped. + * + * Returns: %FALSE when @func returned %FALSE for one of the metadata. + */ +gboolean +gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func, + gpointer user_data) +{ + GstMetaItem *walk, *prev, *next; + gboolean res = TRUE; + + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + /* find the metadata and delete */ + prev = GST_BUFFER_META (buffer); + for (walk = prev; walk; walk = next) { + GstMeta *m, *new; + + m = new = &walk->meta; + next = walk->next; + + res = func (buffer, &new, user_data); + + if (new == NULL) { + const GstMetaInfo *info = m->info; + + GST_CAT_DEBUG (GST_CAT_BUFFER, "remove metadata %p (%s)", m, + g_type_name (info->type)); + + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + g_return_val_if_fail (!GST_META_FLAG_IS_SET (m, GST_META_FLAG_LOCKED), + FALSE); + + /* remove from list */ + if (GST_BUFFER_META (buffer) == walk) + GST_BUFFER_META (buffer) = next; + else + prev->next = next; + + prev = next; + + /* call free_func if any */ + if (info->free_func) + info->free_func (m, buffer); + + /* and free the slice */ + g_slice_free1 (ITEM_SIZE (info), walk); + } else { + prev = walk; + } + if (!res) + break; + } + return res; +} + +/** + * gst_buffer_extract_dup: + * @buffer: a #GstBuffer + * @offset: the offset to extract + * @size: the size to extract + * @dest: (array length=dest_size) (element-type guint8) (out): A pointer where + * the destination array will be written. Might be %NULL if the size is 0. + * @dest_size: (out): A location where the size of @dest can be written + * + * Extracts a copy of at most @size bytes the data at @offset into + * newly-allocated memory. @dest must be freed using g_free() when done. + * + * Since: 1.0.10 + */ + +void +gst_buffer_extract_dup (GstBuffer * buffer, gsize offset, gsize size, + gpointer * dest, gsize * dest_size) +{ + gsize real_size, alloc_size; + + real_size = gst_buffer_get_size (buffer); + + alloc_size = MIN (real_size - offset, size); + if (alloc_size == 0) { + *dest = NULL; + *dest_size = 0; + } else { + *dest = g_malloc (alloc_size); + *dest_size = gst_buffer_extract (buffer, offset, *dest, size); + } +} + +GST_DEBUG_CATEGORY_STATIC (gst_parent_buffer_meta_debug); + +/** + * gst_buffer_add_parent_buffer_meta: + * @buffer: (transfer none): a #GstBuffer + * @ref: (transfer none): a #GstBuffer to ref + * + * Add a #GstParentBufferMeta to @buffer that holds a reference on + * @ref until the buffer is freed. + * + * Returns: (transfer none) (nullable): The #GstParentBufferMeta that was added to the buffer + * + * Since: 1.6 + */ +GstParentBufferMeta * +gst_buffer_add_parent_buffer_meta (GstBuffer * buffer, GstBuffer * ref) +{ + GstParentBufferMeta *meta; + + g_return_val_if_fail (GST_IS_BUFFER (ref), NULL); + + meta = + (GstParentBufferMeta *) gst_buffer_add_meta (buffer, + GST_PARENT_BUFFER_META_INFO, NULL); + + if (!meta) + return NULL; + + meta->buffer = gst_buffer_ref (ref); + + return meta; +} + +static gboolean +_gst_parent_buffer_meta_transform (GstBuffer * dest, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstParentBufferMeta *dmeta, *smeta; + + smeta = (GstParentBufferMeta *) meta; + + if (GST_META_TRANSFORM_IS_COPY (type)) { + /* copy over the reference to the parent buffer. + * Usually, this meta means we need to keep the parent buffer + * alive because one of the child memories is in use, which + * might not be the case if memory is deep copied or sub-regioned, + * but we can't tell, so keep the meta */ + dmeta = gst_buffer_add_parent_buffer_meta (dest, smeta->buffer); + if (!dmeta) + return FALSE; + + GST_CAT_DEBUG (gst_parent_buffer_meta_debug, + "copy buffer reference metadata"); + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + +static void +_gst_parent_buffer_meta_free (GstParentBufferMeta * parent_meta, + GstBuffer * buffer) +{ + GST_CAT_DEBUG (gst_parent_buffer_meta_debug, + "Dropping reference on buffer %p", parent_meta->buffer); + gst_buffer_unref (parent_meta->buffer); +} + +static gboolean +_gst_parent_buffer_meta_init (GstParentBufferMeta * parent_meta, + gpointer params, GstBuffer * buffer) +{ + static volatile gsize _init; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (gst_parent_buffer_meta_debug, "parentbuffermeta", + 0, "parentbuffermeta"); + g_once_init_leave (&_init, 1); + } + + parent_meta->buffer = NULL; + + return TRUE; +} + +GType +gst_parent_buffer_meta_api_get_type (void) +{ + static volatile GType type = 0; + static const gchar *tags[] = { NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstParentBufferMetaAPI", tags); + g_once_init_leave (&type, _type); + } + + return type; +} + +/** + * gst_parent_buffer_meta_get_info: + * + * Get the global #GstMetaInfo describing the #GstParentBufferMeta meta. + * + * Returns: (transfer none): The #GstMetaInfo + * + * Since: 1.6 + */ +const GstMetaInfo * +gst_parent_buffer_meta_get_info (void) +{ + static const GstMetaInfo *meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & meta_info)) { + const GstMetaInfo *meta = + gst_meta_register (gst_parent_buffer_meta_api_get_type (), + "GstParentBufferMeta", + sizeof (GstParentBufferMeta), + (GstMetaInitFunction) _gst_parent_buffer_meta_init, + (GstMetaFreeFunction) _gst_parent_buffer_meta_free, + _gst_parent_buffer_meta_transform); + g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) meta); + } + + return meta_info; +} + +GST_DEBUG_CATEGORY_STATIC (gst_reference_timestamp_meta_debug); + +/** + * gst_buffer_add_reference_timestamp_meta: + * @buffer: (transfer none): a #GstBuffer + * @reference: (transfer none): identifier for the timestamp reference. + * @timestamp: timestamp + * @duration: duration, or %GST_CLOCK_TIME_NONE + * + * Add a #GstReferenceTimestampMeta to @buffer that holds a @timestamp and + * optionally @duration based on a specific timestamp @reference. See the + * documentation of #GstReferenceTimestampMeta for details. + * + * Returns: (transfer none) (nullable): The #GstReferenceTimestampMeta that was added to the buffer + * + * Since: 1.14 + */ +GstReferenceTimestampMeta * +gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer, + GstCaps * reference, GstClockTime timestamp, GstClockTime duration) +{ + GstReferenceTimestampMeta *meta; + + g_return_val_if_fail (GST_IS_CAPS (reference), NULL); + g_return_val_if_fail (timestamp != GST_CLOCK_TIME_NONE, NULL); + + meta = + (GstReferenceTimestampMeta *) gst_buffer_add_meta (buffer, + GST_REFERENCE_TIMESTAMP_META_INFO, NULL); + + if (!meta) + return NULL; + + meta->reference = gst_caps_ref (reference); + meta->timestamp = timestamp; + meta->duration = duration; + + return meta; +} + +/** + * gst_buffer_get_reference_timestamp_meta: + * @buffer: a #GstBuffer + * @reference: (allow-none): a reference #GstCaps + * + * Find the first #GstReferenceTimestampMeta on @buffer that conforms to + * @reference. Conformance is tested by checking if the meta's reference is a + * subset of @reference. + * + * Buffers can contain multiple #GstReferenceTimestampMeta metadata items. + * + * Returns: (transfer none) (nullable): the #GstReferenceTimestampMeta or %NULL when there + * is no such metadata on @buffer. + * + * Since: 1.14 + */ +GstReferenceTimestampMeta * +gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer, + GstCaps * reference) +{ + gpointer state = NULL; + GstMeta *meta; + const GstMetaInfo *info = GST_REFERENCE_TIMESTAMP_META_INFO; + + while ((meta = gst_buffer_iterate_meta (buffer, &state))) { + if (meta->info->api == info->api) { + GstReferenceTimestampMeta *rmeta = (GstReferenceTimestampMeta *) meta; + + if (!reference) + return rmeta; + if (gst_caps_is_subset (rmeta->reference, reference)) + return rmeta; + } + } + return NULL; +} + +static gboolean +_gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstReferenceTimestampMeta *dmeta, *smeta; + + /* we copy over the reference timestamp meta, independent of transformation + * that happens. If it applied to the original buffer, it still applies to + * the new buffer as it refers to the time when the media was captured */ + smeta = (GstReferenceTimestampMeta *) meta; + dmeta = + gst_buffer_add_reference_timestamp_meta (dest, smeta->reference, + smeta->timestamp, smeta->duration); + if (!dmeta) + return FALSE; + + GST_CAT_DEBUG (gst_reference_timestamp_meta_debug, + "copy reference timestamp metadata from buffer %p to %p", buffer, dest); + + return TRUE; +} + +static void +_gst_reference_timestamp_meta_free (GstReferenceTimestampMeta * meta, + GstBuffer * buffer) +{ + if (meta->reference) + gst_caps_unref (meta->reference); +} + +static gboolean +_gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta, + gpointer params, GstBuffer * buffer) +{ + static volatile gsize _init; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (gst_reference_timestamp_meta_debug, + "referencetimestampmeta", 0, "referencetimestampmeta"); + g_once_init_leave (&_init, 1); + } + + meta->reference = NULL; + meta->timestamp = GST_CLOCK_TIME_NONE; + meta->duration = GST_CLOCK_TIME_NONE; + + return TRUE; +} + +GType +gst_reference_timestamp_meta_api_get_type (void) +{ + static volatile GType type = 0; + static const gchar *tags[] = { NULL }; + + if (g_once_init_enter (&type)) { + GType _type = + gst_meta_api_type_register ("GstReferenceTimestampMetaAPI", tags); + g_once_init_leave (&type, _type); + } + + return type; +} + +/** + * gst_reference_timestamp_meta_get_info: + * + * Get the global #GstMetaInfo describing the #GstReferenceTimestampMeta meta. + * + * Returns: (transfer none): The #GstMetaInfo + * + * Since: 1.14 + */ +const GstMetaInfo * +gst_reference_timestamp_meta_get_info (void) +{ + static const GstMetaInfo *meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & meta_info)) { + const GstMetaInfo *meta = + gst_meta_register (gst_reference_timestamp_meta_api_get_type (), + "GstReferenceTimestampMeta", + sizeof (GstReferenceTimestampMeta), + (GstMetaInitFunction) _gst_reference_timestamp_meta_init, + (GstMetaFreeFunction) _gst_reference_timestamp_meta_free, + _gst_reference_timestamp_meta_transform); + g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) meta); + } + + return meta_info; +} diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h new file mode 100644 index 0000000..2804b52 --- /dev/null +++ b/gst/gstbuffer.h @@ -0,0 +1,784 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstbuffer.h: Header for GstBuffer object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_BUFFER_H__ +#define __GST_BUFFER_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_buffer_type; + +typedef struct _GstBuffer GstBuffer; +typedef struct _GstBufferPool GstBufferPool; + +#include + +#define GST_TYPE_BUFFER (_gst_buffer_type) +#define GST_IS_BUFFER(obj) (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_BUFFER)) +#define GST_BUFFER_CAST(obj) ((GstBuffer *)(obj)) +#define GST_BUFFER(obj) (GST_BUFFER_CAST(obj)) + +/** + * GST_BUFFER_FLAGS: + * @buf: a #GstBuffer. + * + * A flags word containing #GstBufferFlags flags set on this buffer. + */ +#define GST_BUFFER_FLAGS(buf) GST_MINI_OBJECT_FLAGS(buf) +/** + * GST_BUFFER_FLAG_IS_SET: + * @buf: a #GstBuffer. + * @flag: the #GstBufferFlags flag to check. + * + * Gives the status of a specific flag on a buffer. + */ +#define GST_BUFFER_FLAG_IS_SET(buf,flag) GST_MINI_OBJECT_FLAG_IS_SET (buf, flag) +/** + * GST_BUFFER_FLAG_SET: + * @buf: a #GstBuffer. + * @flag: the #GstBufferFlags flag to set. + * + * Sets a buffer flag on a buffer. + */ +#define GST_BUFFER_FLAG_SET(buf,flag) GST_MINI_OBJECT_FLAG_SET (buf, flag) +/** + * GST_BUFFER_FLAG_UNSET: + * @buf: a #GstBuffer. + * @flag: the #GstBufferFlags flag to clear. + * + * Clears a buffer flag. + */ +#define GST_BUFFER_FLAG_UNSET(buf,flag) GST_MINI_OBJECT_FLAG_UNSET (buf, flag) + + +/** + * GST_BUFFER_PTS: + * @buf: a #GstBuffer.: + * + * The presentation timestamp (pts) in nanoseconds (as a #GstClockTime) + * of the data in the buffer. This is the timestamp when the media should be + * presented to the user. + * Value will be %GST_CLOCK_TIME_NONE if the pts is unknown. + */ +#define GST_BUFFER_PTS(buf) (GST_BUFFER_CAST(buf)->pts) +/** + * GST_BUFFER_DTS: + * @buf: a #GstBuffer.: + * + * The decoding timestamp (dts) in nanoseconds (as a #GstClockTime) + * of the data in the buffer. This is the timestamp when the media should be + * decoded or processed otherwise. + * Value will be %GST_CLOCK_TIME_NONE if the dts is unknown. + */ +#define GST_BUFFER_DTS(buf) (GST_BUFFER_CAST(buf)->dts) +/** + * GST_BUFFER_DTS_OR_PTS: + * @buf: a #GstBuffer.: + * + * Returns the buffer decoding timestamp (dts) if valid, else the buffer + * presentation time (pts) + * + * Since: 1.8 + */ +#define GST_BUFFER_DTS_OR_PTS(buf) (GST_BUFFER_DTS_IS_VALID(buf) ? GST_BUFFER_DTS(buf) : GST_BUFFER_PTS (buf)) +/** + * GST_BUFFER_DURATION: + * @buf: a #GstBuffer. + * + * The duration in nanoseconds (as a #GstClockTime) of the data in the buffer. + * Value will be %GST_CLOCK_TIME_NONE if the duration is unknown. + */ +#define GST_BUFFER_DURATION(buf) (GST_BUFFER_CAST(buf)->duration) +/** + * GST_BUFFER_OFFSET: + * @buf: a #GstBuffer. + * + * The offset in the source file of the beginning of this buffer. + */ +#define GST_BUFFER_OFFSET(buf) (GST_BUFFER_CAST(buf)->offset) +/** + * GST_BUFFER_OFFSET_END: + * @buf: a #GstBuffer. + * + * The offset in the source file of the end of this buffer. + */ +#define GST_BUFFER_OFFSET_END(buf) (GST_BUFFER_CAST(buf)->offset_end) + +/** + * GST_BUFFER_OFFSET_NONE: + * + * Constant for no-offset return results. + */ +#define GST_BUFFER_OFFSET_NONE ((guint64)-1) + +/** + * GST_BUFFER_DURATION_IS_VALID: + * @buffer: a #GstBuffer + * + * Tests if the duration is known. + */ +#define GST_BUFFER_DURATION_IS_VALID(buffer) (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) +/** + * GST_BUFFER_PTS_IS_VALID: + * @buffer: a #GstBuffer + * + * Tests if the pts is known. + */ +#define GST_BUFFER_PTS_IS_VALID(buffer) (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer))) +/** + * GST_BUFFER_DTS_IS_VALID: + * @buffer: a #GstBuffer + * + * Tests if the dts is known. + */ +#define GST_BUFFER_DTS_IS_VALID(buffer) (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer))) +/** + * GST_BUFFER_OFFSET_IS_VALID: + * @buffer: a #GstBuffer + * + * Tests if the start offset is known. + */ +#define GST_BUFFER_OFFSET_IS_VALID(buffer) (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE) +/** + * GST_BUFFER_OFFSET_END_IS_VALID: + * @buffer: a #GstBuffer + * + * Tests if the end offset is known. + */ +#define GST_BUFFER_OFFSET_END_IS_VALID(buffer) (GST_BUFFER_OFFSET_END (buffer) != GST_BUFFER_OFFSET_NONE) +/** + * GST_BUFFER_IS_DISCONT: + * @buffer: a #GstBuffer + * + * Tests if the buffer marks a discontinuity in the stream. + */ +#define GST_BUFFER_IS_DISCONT(buffer) (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) + +/** + * GstBufferFlags: + * @GST_BUFFER_FLAG_LIVE: the buffer is live data and should be discarded in + * the PAUSED state. + * @GST_BUFFER_FLAG_DECODE_ONLY: the buffer contains data that should be dropped + * because it will be clipped against the segment + * boundaries or because it does not contain data + * that should be shown to the user. + * @GST_BUFFER_FLAG_DISCONT: the buffer marks a data discontinuity in the stream. + * This typically occurs after a seek or a dropped buffer + * from a live or network source. + * @GST_BUFFER_FLAG_RESYNC: the buffer timestamps might have a discontinuity + * and this buffer is a good point to resynchronize. + * @GST_BUFFER_FLAG_CORRUPTED: the buffer data is corrupted. + * @GST_BUFFER_FLAG_MARKER: the buffer contains a media specific marker. for + * video this is typically the end of a frame boundary, for audio + * this is usually the start of a talkspurt. + * @GST_BUFFER_FLAG_HEADER: the buffer contains header information that is + * needed to decode the following data. + * @GST_BUFFER_FLAG_GAP: the buffer has been created to fill a gap in the + * stream and contains media neutral data (elements can + * switch to optimized code path that ignores the buffer + * content). + * @GST_BUFFER_FLAG_DROPPABLE: the buffer can be dropped without breaking the + * stream, for example to reduce bandwidth. + * @GST_BUFFER_FLAG_DELTA_UNIT: this unit cannot be decoded independently. + * @GST_BUFFER_FLAG_TAG_MEMORY: this flag is set when memory of the buffer + * is added/removed + * @GST_BUFFER_FLAG_SYNC_AFTER: Elements which write to disk or permanent + * storage should ensure the data is synced after + * writing the contents of this buffer. (Since 1.6) + * @GST_BUFFER_FLAG_NON_DROPPABLE: This buffer is important and should not be dropped. + * This can be used to mark important buffers, e.g. to flag + * RTP packets carrying keyframes or codec setup data for RTP + * Forward Error Correction purposes, or to prevent still video + * frames from being dropped by elements due to QoS. (Since 1.14) + * @GST_BUFFER_FLAG_LAST: additional media specific flags can be added starting from + * this flag. + * + * A set of buffer flags used to describe properties of a #GstBuffer. + */ +typedef enum { + GST_BUFFER_FLAG_LIVE = (GST_MINI_OBJECT_FLAG_LAST << 0), + GST_BUFFER_FLAG_DECODE_ONLY = (GST_MINI_OBJECT_FLAG_LAST << 1), + GST_BUFFER_FLAG_DISCONT = (GST_MINI_OBJECT_FLAG_LAST << 2), + GST_BUFFER_FLAG_RESYNC = (GST_MINI_OBJECT_FLAG_LAST << 3), + GST_BUFFER_FLAG_CORRUPTED = (GST_MINI_OBJECT_FLAG_LAST << 4), + GST_BUFFER_FLAG_MARKER = (GST_MINI_OBJECT_FLAG_LAST << 5), + GST_BUFFER_FLAG_HEADER = (GST_MINI_OBJECT_FLAG_LAST << 6), + GST_BUFFER_FLAG_GAP = (GST_MINI_OBJECT_FLAG_LAST << 7), + GST_BUFFER_FLAG_DROPPABLE = (GST_MINI_OBJECT_FLAG_LAST << 8), + GST_BUFFER_FLAG_DELTA_UNIT = (GST_MINI_OBJECT_FLAG_LAST << 9), + GST_BUFFER_FLAG_TAG_MEMORY = (GST_MINI_OBJECT_FLAG_LAST << 10), + GST_BUFFER_FLAG_SYNC_AFTER = (GST_MINI_OBJECT_FLAG_LAST << 11), + GST_BUFFER_FLAG_NON_DROPPABLE = (GST_MINI_OBJECT_FLAG_LAST << 12), + + GST_BUFFER_FLAG_LAST = (GST_MINI_OBJECT_FLAG_LAST << 16) +} GstBufferFlags; + +/** + * GstBuffer: + * @mini_object: the parent structure + * @pool: pointer to the pool owner of the buffer + * @pts: presentation timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the + * pts is not known or relevant. The pts contains the timestamp when the + * media should be presented to the user. + * @dts: decoding timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the + * dts is not known or relevant. The dts contains the timestamp when the + * media should be processed. + * @duration: duration in time of the buffer data, can be #GST_CLOCK_TIME_NONE + * when the duration is not known or relevant. + * @offset: a media specific offset for the buffer data. + * For video frames, this is the frame number of this buffer. + * For audio samples, this is the offset of the first sample in this buffer. + * For file data or compressed data this is the byte offset of the first + * byte in this buffer. + * @offset_end: the last offset contained in this buffer. It has the same + * format as @offset. + * + * The structure of a #GstBuffer. Use the associated macros to access the public + * variables. + */ +struct _GstBuffer { + GstMiniObject mini_object; + + /*< public >*/ /* with COW */ + GstBufferPool *pool; + + /* timestamp */ + GstClockTime pts; + GstClockTime dts; + GstClockTime duration; + + /* media specific offset */ + guint64 offset; + guint64 offset_end; +}; + +GST_API +GType gst_buffer_get_type (void); + +GST_API +guint gst_buffer_get_max_memory (void); + +/* allocation */ + +GST_API +GstBuffer * gst_buffer_new (void); + +GST_API +GstBuffer * gst_buffer_new_allocate (GstAllocator * allocator, gsize size, + GstAllocationParams * params); +GST_API +GstBuffer * gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data, gsize maxsize, + gsize offset, gsize size, gpointer user_data, + GDestroyNotify notify); +GST_API +GstBuffer * gst_buffer_new_wrapped (gpointer data, gsize size); + +/* memory blocks */ + +GST_API +guint gst_buffer_n_memory (GstBuffer *buffer); + +GST_API +void gst_buffer_insert_memory (GstBuffer *buffer, gint idx, GstMemory *mem); + +GST_API +void gst_buffer_replace_memory_range (GstBuffer *buffer, guint idx, gint length, GstMemory *mem); + +GST_API +GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx); + +GST_API +GstMemory * gst_buffer_get_memory_range (GstBuffer *buffer, guint idx, gint length); + +GST_API +void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, gint length); + +GST_API +void gst_buffer_prepend_memory (GstBuffer *buffer, GstMemory *mem); + +GST_API +void gst_buffer_append_memory (GstBuffer *buffer, GstMemory *mem); + +GST_API +void gst_buffer_replace_memory (GstBuffer *buffer, guint idx, GstMemory *mem); + +GST_API +void gst_buffer_replace_all_memory (GstBuffer *buffer, GstMemory *mem); + +GST_API +GstMemory * gst_buffer_get_memory (GstBuffer *buffer, guint idx); + +GST_API +GstMemory * gst_buffer_get_all_memory (GstBuffer *buffer); + +GST_API +void gst_buffer_remove_memory (GstBuffer *buffer, guint idx); + +GST_API +void gst_buffer_remove_all_memory (GstBuffer *buffer); + +GST_API +gboolean gst_buffer_find_memory (GstBuffer *buffer, gsize offset, gsize size, + guint *idx, guint *length, gsize *skip); +GST_API +gboolean gst_buffer_is_memory_range_writable (GstBuffer *buffer, guint idx, gint length); + +GST_API +gboolean gst_buffer_is_all_memory_writable (GstBuffer *buffer); + +GST_API +gsize gst_buffer_fill (GstBuffer *buffer, gsize offset, + gconstpointer src, gsize size); +GST_API +gsize gst_buffer_extract (GstBuffer *buffer, gsize offset, + gpointer dest, gsize size); +GST_API +gint gst_buffer_memcmp (GstBuffer *buffer, gsize offset, + gconstpointer mem, gsize size); +GST_API +gsize gst_buffer_memset (GstBuffer *buffer, gsize offset, + guint8 val, gsize size); +GST_API +gsize gst_buffer_get_sizes_range (GstBuffer *buffer, guint idx, gint length, + gsize *offset, gsize *maxsize); +GST_API +gboolean gst_buffer_resize_range (GstBuffer *buffer, guint idx, gint length, + gssize offset, gssize size); +GST_API +gsize gst_buffer_get_sizes (GstBuffer *buffer, gsize *offset, gsize *maxsize); + +GST_API +gsize gst_buffer_get_size (GstBuffer *buffer); + +GST_API +void gst_buffer_resize (GstBuffer *buffer, gssize offset, gssize size); + +GST_API +void gst_buffer_set_size (GstBuffer *buffer, gssize size); + +GST_API +gboolean gst_buffer_map_range (GstBuffer *buffer, guint idx, gint length, + GstMapInfo *info, GstMapFlags flags); +GST_API +gboolean gst_buffer_map (GstBuffer *buffer, GstMapInfo *info, GstMapFlags flags); + +GST_API +void gst_buffer_unmap (GstBuffer *buffer, GstMapInfo *info); + +GST_API +void gst_buffer_extract_dup (GstBuffer *buffer, gsize offset, + gsize size, gpointer *dest, + gsize *dest_size); +GST_API +GstBufferFlags gst_buffer_get_flags (GstBuffer * buffer); + +GST_API +gboolean gst_buffer_has_flags (GstBuffer * buffer, GstBufferFlags flags); + +GST_API +gboolean gst_buffer_set_flags (GstBuffer * buffer, GstBufferFlags flags); + +GST_API +gboolean gst_buffer_unset_flags (GstBuffer * buffer, GstBufferFlags flags); + + + +/* refcounting */ +/** + * gst_buffer_ref: + * @buf: a #GstBuffer. + * + * Increases the refcount of the given buffer by one. + * + * Note that the refcount affects the writability + * of @buf and its metadata, see gst_buffer_is_writable(). + * It is important to note that keeping additional references to + * GstBuffer instances can potentially increase the number + * of memcpy operations in a pipeline. + * + * Returns: (transfer full): @buf + */ +static inline GstBuffer * +gst_buffer_ref (GstBuffer * buf) +{ + return (GstBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (buf)); +} + +/** + * gst_buffer_unref: + * @buf: (transfer full): a #GstBuffer. + * + * Decreases the refcount of the buffer. If the refcount reaches 0, the buffer + * with the associated metadata and memory will be freed. + */ +static inline void +gst_buffer_unref (GstBuffer * buf) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf)); +} + +/* copy buffer */ +/** + * gst_buffer_copy: + * @buf: a #GstBuffer. + * + * Create a copy of the given buffer. This will only copy the buffer's + * data to a newly allocated memory if needed (if the type of memory + * requires it), otherwise the underlying data is just referenced. + * Check gst_buffer_copy_deep() if you want to force the data + * to be copied to newly allocated memory. + * + * Returns: (transfer full): a new copy of @buf. + */ +static inline GstBuffer * +gst_buffer_copy (const GstBuffer * buf) +{ + return GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf))); +} + +GST_API +GstBuffer * gst_buffer_copy_deep (const GstBuffer * buf); + +/** + * GstBufferCopyFlags: + * @GST_BUFFER_COPY_NONE: copy nothing + * @GST_BUFFER_COPY_FLAGS: flag indicating that buffer flags should be copied + * @GST_BUFFER_COPY_TIMESTAMPS: flag indicating that buffer pts, dts, + * duration, offset and offset_end should be copied + * @GST_BUFFER_COPY_MEMORY: flag indicating that buffer memory should be reffed + * and appended to already existing memory. Unless the memory is marked as + * NO_SHARE, no actual copy of the memory is made but it is simply reffed. + * Add @GST_BUFFER_COPY_DEEP to force a real copy. + * @GST_BUFFER_COPY_MERGE: flag indicating that buffer memory should be + * merged + * @GST_BUFFER_COPY_META: flag indicating that buffer meta should be + * copied + * @GST_BUFFER_COPY_DEEP: flag indicating that memory should always be + * copied instead of reffed (Since 1.2) + * + * A set of flags that can be provided to the gst_buffer_copy_into() + * function to specify which items should be copied. + */ +typedef enum { + GST_BUFFER_COPY_NONE = 0, + GST_BUFFER_COPY_FLAGS = (1 << 0), + GST_BUFFER_COPY_TIMESTAMPS = (1 << 1), + GST_BUFFER_COPY_META = (1 << 2), + GST_BUFFER_COPY_MEMORY = (1 << 3), + GST_BUFFER_COPY_MERGE = (1 << 4), + GST_BUFFER_COPY_DEEP = (1 << 5) +} GstBufferCopyFlags; + +/** + * GST_BUFFER_COPY_METADATA: (value 7) (type GstBufferCopyFlags) + * + * Combination of all possible metadata fields that can be copied with + * gst_buffer_copy_into(). + */ +#define GST_BUFFER_COPY_METADATA ((GstBufferCopyFlags) (GST_BUFFER_COPY_FLAGS |\ + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_META)) + +/** + * GST_BUFFER_COPY_ALL: (value 15) (type GstBufferCopyFlags) + * + * Combination of all possible fields that can be copied with + * gst_buffer_copy_into(). + */ +#define GST_BUFFER_COPY_ALL ((GstBufferCopyFlags)(GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY)) + +/* copies memory or metadata into newly allocated buffer */ + +GST_API +gboolean gst_buffer_copy_into (GstBuffer *dest, GstBuffer *src, + GstBufferCopyFlags flags, + gsize offset, gsize size); + +/** + * gst_buffer_is_writable: + * @buf: a #GstBuffer + * + * Tests if you can safely write to a buffer's metadata or its memory array. + * It is only safe to change buffer metadata when the current reference is + * writable, i.e. nobody can see the modifications you will make. + */ +#define gst_buffer_is_writable(buf) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (buf)) +/** + * gst_buffer_make_writable: + * @buf: (transfer full): a #GstBuffer + * + * Returns a writable copy of @buf. If the source buffer is + * already writable, this will simply return the same buffer. + * + * Use this function to ensure that a buffer can be safely modified before + * making changes to it, including changing the metadata such as PTS/DTS. + * + * If the reference count of the source buffer @buf is exactly one, the caller + * is the sole owner and this function will return the buffer object unchanged. + * + * If there is more than one reference on the object, a copy will be made using + * gst_buffer_copy(). The passed-in @buf will be unreffed in that case, and the + * caller will now own a reference to the new returned buffer object. Note + * that this just copies the buffer structure itself, the underlying memory is + * not copied if it can be shared amongst multiple buffers. + * + * In short, this function unrefs the buf in the argument and refs the buffer + * that it returns. Don't access the argument after calling this function unless + * you have an additional reference to it. + * + * Returns: (transfer full): a writable buffer which may or may not be the + * same as @buf + */ +#define gst_buffer_make_writable(buf) GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (buf))) + +/** + * gst_buffer_replace: + * @obuf: (inout) (transfer full) (nullable): pointer to a pointer to + * a #GstBuffer to be replaced. + * @nbuf: (transfer none) (allow-none): pointer to a #GstBuffer that will + * replace the buffer pointed to by @obuf. + * + * Modifies a pointer to a #GstBuffer to point to a different #GstBuffer. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * buffer is unreffed, the new is reffed). + * + * Either @nbuf or the #GstBuffer pointed to by @obuf may be %NULL. + * + * Returns: %TRUE when @obuf was different from @nbuf. + */ +static inline gboolean +gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf) +{ + return gst_mini_object_replace ((GstMiniObject **) obuf, (GstMiniObject *) nbuf); +} + +/* creating a region */ + +GST_API +GstBuffer* gst_buffer_copy_region (GstBuffer *parent, GstBufferCopyFlags flags, + gsize offset, gsize size); + +/* append two buffers */ + +GST_API +GstBuffer* gst_buffer_append_region (GstBuffer *buf1, GstBuffer *buf2, + gssize offset, gssize size); +GST_API +GstBuffer* gst_buffer_append (GstBuffer *buf1, GstBuffer *buf2); + +/* metadata */ +#include + +/** + * GstBufferForeachMetaFunc: + * @buffer: a #GstBuffer + * @meta: (out) (nullable): a pointer to a #GstMeta + * @user_data: user data passed to gst_buffer_foreach_meta() + * + * A function that will be called from gst_buffer_foreach_meta(). The @meta + * field will point to a the reference of the meta. + * + * @buffer should not be modified from this callback. + * + * When this function returns %TRUE, the next meta will be + * returned. When %FALSE is returned, gst_buffer_foreach_meta() will return. + * + * When @meta is set to %NULL, the item will be removed from the buffer. + * + * Returns: %FALSE when gst_buffer_foreach_meta() should stop + */ +typedef gboolean (*GstBufferForeachMetaFunc) (GstBuffer *buffer, GstMeta **meta, + gpointer user_data); + +GST_API +GstMeta * gst_buffer_get_meta (GstBuffer *buffer, GType api); + +GST_API +guint gst_buffer_get_n_meta (GstBuffer *buffer, GType api_type); + +GST_API +GstMeta * gst_buffer_add_meta (GstBuffer *buffer, const GstMetaInfo *info, + gpointer params); +GST_API +gboolean gst_buffer_remove_meta (GstBuffer *buffer, GstMeta *meta); + +GST_API +GstMeta * gst_buffer_iterate_meta (GstBuffer *buffer, gpointer *state); + +GST_API +GstMeta * gst_buffer_iterate_meta_filtered (GstBuffer * buffer, + gpointer * state, + GType meta_api_type); +GST_API +gboolean gst_buffer_foreach_meta (GstBuffer *buffer, + GstBufferForeachMetaFunc func, + gpointer user_data); + +/** + * gst_value_set_buffer: + * @v: a #GValue to receive the data + * @b: (transfer none): a #GstBuffer to assign to the GstValue + * + * Sets @b as the value of @v. Caller retains reference to buffer. + */ +#define gst_value_set_buffer(v,b) g_value_set_boxed((v),(b)) +/** + * gst_value_take_buffer: + * @v: a #GValue to receive the data + * @b: (transfer full): a #GstBuffer to assign to the GstValue + * + * Sets @b as the value of @v. Caller gives away reference to buffer. + */ +#define gst_value_take_buffer(v,b) g_value_take_boxed(v,(b)) +/** + * gst_value_get_buffer: + * @v: a #GValue to query + * + * Receives a #GstBuffer as the value of @v. Does not return a reference to + * the buffer, so the pointer is only valid for as long as the caller owns + * a reference to @v. + * + * Returns: (transfer none): buffer + */ +#define gst_value_get_buffer(v) GST_BUFFER_CAST (g_value_get_boxed(v)) + +typedef struct _GstParentBufferMeta GstParentBufferMeta; + +/** + * GstParentBufferMeta: + * @parent: the parent #GstMeta structure + * @buffer: the #GstBuffer on which a reference is being held. + * + * The #GstParentBufferMeta is a #GstMeta which can be attached to a #GstBuffer + * to hold a reference to another buffer that is only released when the child + * #GstBuffer is released. + * + * Typically, #GstParentBufferMeta is used when the child buffer is directly + * using the #GstMemory of the parent buffer, and wants to prevent the parent + * buffer from being returned to a buffer pool until the #GstMemory is available + * for re-use. + * + * Since: 1.6 + */ +struct _GstParentBufferMeta +{ + GstMeta parent; + + /*< public >*/ + GstBuffer *buffer; +}; + +GST_API +GType gst_parent_buffer_meta_api_get_type (void); +#ifndef GST_DISABLE_DEPRECATED +#define GST_TYPE_PARENT_BUFFER_META_API_TYPE GST_PARENT_BUFFER_META_API_TYPE +#endif +#define GST_PARENT_BUFFER_META_API_TYPE (gst_parent_buffer_meta_api_get_type()) + +/** + * gst_buffer_get_parent_buffer_meta: + * @b: a #GstBuffer + * + * Find and return a #GstParentBufferMeta if one exists on the + * buffer + */ +#define gst_buffer_get_parent_buffer_meta(b) \ + ((GstParentBufferMeta*)gst_buffer_get_meta((b),GST_PARENT_BUFFER_META_API_TYPE)) + +GST_API +const GstMetaInfo *gst_parent_buffer_meta_get_info (void); +#define GST_PARENT_BUFFER_META_INFO (gst_parent_buffer_meta_get_info()) + +/* implementation */ + +GST_API +GstParentBufferMeta *gst_buffer_add_parent_buffer_meta (GstBuffer *buffer, + GstBuffer *ref); + +typedef struct _GstReferenceTimestampMeta GstReferenceTimestampMeta; + +/** + * GstReferenceTimestampMeta: + * @parent: the parent #GstMeta structure + * @reference: identifier for the timestamp reference. + * @timestamp: timestamp + * @duration: duration, or %GST_CLOCK_TIME_NONE + * + * #GstReferenceTimestampMeta can be used to attach alternative timestamps and + * possibly durations to a #GstBuffer. These are generally not according to + * the pipeline clock and could be e.g. the NTP timestamp when the media was + * captured. + * + * The reference is stored as a #GstCaps in @reference. Examples of valid + * references would be "timestamp/x-drivername-stream" for timestamps that are locally + * generated by some driver named "drivername" when generating the stream, + * e.g. based on a frame counter, or "timestamp/x-ntp, host=pool.ntp.org, + * port=123" for timestamps based on a specific NTP server. + * + * Since: 1.14 + */ +struct _GstReferenceTimestampMeta +{ + GstMeta parent; + + /*< public >*/ + GstCaps *reference; + GstClockTime timestamp, duration; +}; + +GST_API +GType gst_reference_timestamp_meta_api_get_type (void); +#define GST_REFERENCE_TIMESTAMP_META_API_TYPE (gst_reference_timestamp_meta_api_get_type()) + +GST_API +const GstMetaInfo *gst_reference_timestamp_meta_get_info (void); +#define GST_REFERENCE_TIMESTAMP_META_INFO (gst_reference_timestamp_meta_get_info()) + +/* implementation */ + +GST_API +GstReferenceTimestampMeta * gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer, + GstCaps * reference, + GstClockTime timestamp, + GstClockTime duration); + +GST_API +GstReferenceTimestampMeta * gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer, + GstCaps * reference); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBuffer, gst_buffer_unref) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBufferPool, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BUFFER_H__ */ diff --git a/gst/gstbufferlist.c b/gst/gstbufferlist.c new file mode 100644 index 0000000..16de4ce --- /dev/null +++ b/gst/gstbufferlist.c @@ -0,0 +1,470 @@ +/* GStreamer + * Copyright (C) 2009 Axis Communications + * @author Jonas Holmberg + * Copyright (C) 2014 Tim-Philipp Müller + * + * gstbufferlist.c: Buffer list + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbufferlist + * @title: GstBufferList + * @short_description: Lists of buffers for data-passing + * @see_also: #GstPad, #GstMiniObject + * + * Buffer lists are an object containing a list of buffers. + * + * Buffer lists are created with gst_buffer_list_new() and filled with data + * using a gst_buffer_list_insert(). + * + * Buffer lists can be pushed on a srcpad with gst_pad_push_list(). This is + * interesting when multiple buffers need to be pushed in one go because it + * can reduce the amount of overhead for pushing each buffer individually. + */ +#include "gst_private.h" + +#include "gstbuffer.h" +#include "gstbufferlist.h" +#include "gstutils.h" + +#define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST + +#define GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY(list) \ + ((list)->buffers != &(list)->arr[0]) + +/** + * GstBufferList: + * + * Opaque list of grouped buffers. + */ +struct _GstBufferList +{ + GstMiniObject mini_object; + + GstBuffer **buffers; + guint n_buffers; + guint n_allocated; + + gsize slice_size; + + /* one-item array, in reality more items are pre-allocated + * as part of the GstBufferList structure, and that + * pre-allocated array extends beyond the declared struct */ + GstBuffer *arr[1]; +}; + +GType _gst_buffer_list_type = 0; + +GST_DEFINE_MINI_OBJECT_TYPE (GstBufferList, gst_buffer_list); + +void +_priv_gst_buffer_list_initialize (void) +{ + _gst_buffer_list_type = gst_buffer_list_get_type (); +} + +static GstBufferList * +_gst_buffer_list_copy (GstBufferList * list) +{ + GstBufferList *copy; + guint i, len; + + len = list->n_buffers; + copy = gst_buffer_list_new_sized (list->n_allocated); + + /* add and ref all buffers in the array */ + for (i = 0; i < len; i++) + copy->buffers[i] = gst_buffer_ref (list->buffers[i]); + + copy->n_buffers = len; + + return copy; +} + +static void +_gst_buffer_list_free (GstBufferList * list) +{ + guint i, len; + + GST_LOG ("free %p", list); + + /* unrefs all buffers too */ + len = list->n_buffers; + for (i = 0; i < len; i++) + gst_buffer_unref (list->buffers[i]); + + if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) + g_free (list->buffers); + + g_slice_free1 (list->slice_size, list); +} + +static void +gst_buffer_list_init (GstBufferList * list, guint n_allocated, gsize slice_size) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (list), 0, _gst_buffer_list_type, + (GstMiniObjectCopyFunction) _gst_buffer_list_copy, NULL, + (GstMiniObjectFreeFunction) _gst_buffer_list_free); + + list->buffers = &list->arr[0]; + list->n_buffers = 0; + list->n_allocated = n_allocated; + list->slice_size = slice_size; + + GST_LOG ("init %p", list); +} + +/** + * gst_buffer_list_new_sized: + * @size: an initial reserved size + * + * Creates a new, empty #GstBufferList. The caller is responsible for unreffing + * the returned #GstBufferList. The list will have @size space preallocated so + * that memory reallocations can be avoided. + * + * Free-function: gst_buffer_list_unref + * + * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref() + * after usage. + */ +GstBufferList * +gst_buffer_list_new_sized (guint size) +{ + GstBufferList *list; + gsize slice_size; + guint n_allocated; + + if (size == 0) + size = 1; + + n_allocated = GST_ROUND_UP_16 (size); + + slice_size = sizeof (GstBufferList) + (n_allocated - 1) * sizeof (gpointer); + + list = g_slice_alloc0 (slice_size); + + GST_LOG ("new %p", list); + + gst_buffer_list_init (list, n_allocated, slice_size); + + return list; +} + +/** + * gst_buffer_list_new: + * + * Creates a new, empty #GstBufferList. The caller is responsible for unreffing + * the returned #GstBufferList. + * + * Free-function: gst_buffer_list_unref + * + * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref() + * after usage. + */ +GstBufferList * +gst_buffer_list_new (void) +{ + return gst_buffer_list_new_sized (8); +} + +/** + * gst_buffer_list_length: + * @list: a #GstBufferList + * + * Returns the number of buffers in @list. + * + * Returns: the number of buffers in the buffer list + */ +guint +gst_buffer_list_length (GstBufferList * list) +{ + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0); + + return list->n_buffers; +} + +static inline void +gst_buffer_list_remove_range_internal (GstBufferList * list, guint idx, + guint length, gboolean unref_old) +{ + guint i; + + if (unref_old) { + for (i = idx; i < idx + length; ++i) + gst_buffer_unref (list->buffers[i]); + } + + if (idx + length != list->n_buffers) { + memmove (&list->buffers[idx], &list->buffers[idx + length], + (list->n_buffers - (idx + length)) * sizeof (void *)); + } + + list->n_buffers -= length; +} + +/** + * gst_buffer_list_foreach: + * @list: a #GstBufferList + * @func: (scope call): a #GstBufferListFunc to call + * @user_data: (closure): user data passed to @func + * + * Call @func with @data for each buffer in @list. + * + * @func can modify the passed buffer pointer or its contents. The return value + * of @func define if this function returns or if the remaining buffers in + * the list should be skipped. + * + * Returns: %TRUE when @func returned %TRUE for each buffer in @list or when + * @list is empty. + */ +gboolean +gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func, + gpointer user_data) +{ + guint i, len; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + len = list->n_buffers; + for (i = 0; i < len;) { + GstBuffer *buf, *buf_ret; + + buf = buf_ret = list->buffers[i]; + ret = func (&buf_ret, i, user_data); + + /* Check if the function changed the buffer */ + if (buf != buf_ret) { + if (buf_ret == NULL) { + gst_buffer_list_remove_range_internal (list, i, 1, FALSE); + --len; + } else { + list->buffers[i] = buf_ret; + } + } + + if (!ret) + break; + + /* If the buffer was not removed by func go to the next buffer */ + if (buf_ret != NULL) + i++; + } + return ret; +} + +/** + * gst_buffer_list_get: + * @list: a #GstBufferList + * @idx: the index + * + * Get the buffer at @idx. + * + * You must make sure that @idx does not exceed the number of + * buffers available. + * + * Returns: (transfer none) (nullable): the buffer at @idx in @group + * or %NULL when there is no buffer. The buffer remains valid as + * long as @list is valid and buffer is not removed from the list. + */ +GstBuffer * +gst_buffer_list_get (GstBufferList * list, guint idx) +{ + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); + g_return_val_if_fail (idx < list->n_buffers, NULL); + + return list->buffers[idx]; +} + +/** + * gst_buffer_list_get_writable: + * @list: a (writable) #GstBufferList + * @idx: the index + * + * Gets the buffer at @idx, ensuring it is a writable buffer. + * + * You must make sure that @idx does not exceed the number of + * buffers available. + * + * Returns: (transfer none) (nullable): the buffer at @idx in @group. + * The returned buffer remains valid as long as @list is valid and + * the buffer is not removed from the list. + * + * Since: 1.14 + */ +GstBuffer * +gst_buffer_list_get_writable (GstBufferList * list, guint idx) +{ + GstBuffer **p_buf; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); + g_return_val_if_fail (gst_buffer_list_is_writable (list), NULL); + g_return_val_if_fail (idx < list->n_buffers, NULL); + + p_buf = &list->buffers[idx]; + return (*p_buf = gst_buffer_make_writable (*p_buf)); +} + +/** + * gst_buffer_list_add: + * @l: a #GstBufferList + * @b: a #GstBuffer + * + * Append @b at the end of @l. + */ +/** + * gst_buffer_list_insert: + * @list: a #GstBufferList + * @idx: the index + * @buffer: (transfer full): a #GstBuffer + * + * Insert @buffer at @idx in @list. Other buffers are moved to make room for + * this new buffer. + * + * A -1 value for @idx will append the buffer at the end. + */ +void +gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer) +{ + guint want_alloc; + + g_return_if_fail (GST_IS_BUFFER_LIST (list)); + g_return_if_fail (buffer != NULL); + g_return_if_fail (gst_buffer_list_is_writable (list)); + + if (idx == -1 && list->n_buffers < list->n_allocated) { + list->buffers[list->n_buffers++] = buffer; + return; + } + + if (idx == -1 || idx > list->n_buffers) + idx = list->n_buffers; + + want_alloc = list->n_buffers + 1; + + if (want_alloc > list->n_allocated) { + want_alloc = MAX (GST_ROUND_UP_16 (want_alloc), list->n_allocated * 2); + + if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) { + list->buffers = g_renew (GstBuffer *, list->buffers, want_alloc); + } else { + list->buffers = g_new0 (GstBuffer *, want_alloc); + memcpy (list->buffers, &list->arr[0], list->n_buffers * sizeof (void *)); + GST_CAT_LOG (GST_CAT_PERFORMANCE, "exceeding pre-alloced array"); + } + + list->n_allocated = want_alloc; + } + + if (idx < list->n_buffers) { + memmove (&list->buffers[idx + 1], &list->buffers[idx], + (list->n_buffers - idx) * sizeof (void *)); + } + + ++list->n_buffers; + list->buffers[idx] = buffer; +} + +/** + * gst_buffer_list_remove: + * @list: a #GstBufferList + * @idx: the index + * @length: the amount to remove + * + * Remove @length buffers starting from @idx in @list. The following buffers + * are moved to close the gap. + */ +void +gst_buffer_list_remove (GstBufferList * list, guint idx, guint length) +{ + g_return_if_fail (GST_IS_BUFFER_LIST (list)); + g_return_if_fail (idx < list->n_buffers); + g_return_if_fail (idx + length <= list->n_buffers); + g_return_if_fail (gst_buffer_list_is_writable (list)); + + gst_buffer_list_remove_range_internal (list, idx, length, TRUE); +} + +/** + * gst_buffer_list_copy_deep: + * @list: a #GstBufferList + * + * Create a copy of the given buffer list. This will make a newly allocated + * copy of the buffer that the source buffer list contains. + * + * Returns: (transfer full): a new copy of @list. + * + * Since: 1.6 + */ +GstBufferList * +gst_buffer_list_copy_deep (const GstBufferList * list) +{ + guint i, len; + GstBufferList *result = NULL; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); + + result = gst_buffer_list_new (); + + len = list->n_buffers; + for (i = 0; i < len; i++) { + GstBuffer *old = list->buffers[i]; + GstBuffer *new = gst_buffer_copy_deep (old); + + if (G_LIKELY (new)) { + gst_buffer_list_insert (result, i, new); + } else { + g_warning + ("Failed to deep copy buffer %p while deep " + "copying buffer list %p. Buffer list copy " + "will be incomplete", old, list); + } + } + + return result; +} + +/** + * gst_buffer_list_calculate_size: + * @list: a #GstBufferList + * + * Calculates the size of the data contained in buffer list by adding the + * size of all buffers. + * + * Returns: the size of the data contained in buffer list in bytes. + * + * Since: 1.14 + */ +gsize +gst_buffer_list_calculate_size (GstBufferList * list) +{ + GstBuffer **buffers; + gsize size = 0; + guint i, n; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0); + + n = list->n_buffers; + buffers = list->buffers; + + for (i = 0; i < n; ++i) + size += gst_buffer_get_size (buffers[i]); + + return size; +} diff --git a/gst/gstbufferlist.h b/gst/gstbufferlist.h new file mode 100644 index 0000000..ce9fe11 --- /dev/null +++ b/gst/gstbufferlist.h @@ -0,0 +1,178 @@ +/* GStreamer + * Copyright (C) 2009 Axis Communications + * @author Jonas Holmberg + * + * gstbufferlist.h: Header for GstBufferList object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BUFFER_LIST_H__ +#define __GST_BUFFER_LIST_H__ + +#include + +G_BEGIN_DECLS + +GST_API GType _gst_buffer_list_type; + +#define GST_TYPE_BUFFER_LIST (_gst_buffer_list_type) +#define GST_IS_BUFFER_LIST(obj) (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_BUFFER_LIST)) +#define GST_BUFFER_LIST_CAST(obj) ((GstBufferList *)obj) +#define GST_BUFFER_LIST(obj) (GST_BUFFER_LIST_CAST(obj)) + +typedef struct _GstBufferList GstBufferList; + +/** + * GstBufferListFunc: + * @buffer: (out) (nullable): pointer the buffer + * @idx: the index of @buffer + * @user_data: user data passed to gst_buffer_list_foreach() + * + * A function that will be called from gst_buffer_list_foreach(). The @buffer + * field will point to a the reference of the buffer at @idx. + * + * When this function returns %TRUE, the next buffer will be + * returned. When %FALSE is returned, gst_buffer_list_foreach() will return. + * + * When @buffer is set to %NULL, the item will be removed from the bufferlist. + * When @buffer has been made writable, the new buffer reference can be assigned + * to @buffer. This function is responsible for unreffing the old buffer when + * removing or modifying. + * + * Returns: %FALSE when gst_buffer_list_foreach() should stop + */ +typedef gboolean (*GstBufferListFunc) (GstBuffer **buffer, guint idx, + gpointer user_data); + + +/* refcounting */ +/** + * gst_buffer_list_ref: + * @list: a #GstBufferList + * + * Increases the refcount of the given buffer list by one. + * + * Note that the refcount affects the writability of @list and its data, see + * gst_buffer_list_make_writable(). It is important to note that keeping + * additional references to GstBufferList instances can potentially increase + * the number of memcpy operations in a pipeline. + * + * Returns: (transfer full): @list + */ +static inline GstBufferList * +gst_buffer_list_ref (GstBufferList * list) +{ + return GST_BUFFER_LIST_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST ( + list))); +} + +/** + * gst_buffer_list_unref: + * @list: (transfer full): a #GstBufferList + * + * Decreases the refcount of the buffer list. If the refcount reaches 0, the + * buffer list will be freed. + */ +static inline void +gst_buffer_list_unref (GstBufferList * list) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (list)); +} + +/* copy */ +/** + * gst_buffer_list_copy: + * @list: a #GstBufferList + * + * Create a shallow copy of the given buffer list. This will make a newly + * allocated copy of the source list with copies of buffer pointers. The + * refcount of buffers pointed to will be increased by one. + * + * Returns: (transfer full): a new copy of @list. + */ +static inline GstBufferList * +gst_buffer_list_copy (const GstBufferList * list) +{ + return GST_BUFFER_LIST_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (list))); +} + +/** + * gst_buffer_list_is_writable: + * @list: a #GstBufferList + * + * Tests if you can safely add buffers and groups into a buffer list. + */ +#define gst_buffer_list_is_writable(list) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (list)) + +/** + * gst_buffer_list_make_writable: + * @list: (transfer full): a #GstBufferList + * + * Makes a writable buffer list from the given buffer list. If the source buffer + * list is already writable, this will simply return the same buffer list. A + * copy will otherwise be made using gst_buffer_list_copy(). + * + * Returns: (transfer full): a writable list, which may or may not be the + * same as @list + */ +#define gst_buffer_list_make_writable(list) GST_BUFFER_LIST_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (list))) + +GST_API +GType gst_buffer_list_get_type (void); + +/* allocation */ + +GST_API +GstBufferList * gst_buffer_list_new (void) G_GNUC_MALLOC; + +GST_API +GstBufferList * gst_buffer_list_new_sized (guint size) G_GNUC_MALLOC; + +GST_API +guint gst_buffer_list_length (GstBufferList *list); + +GST_API +GstBuffer * gst_buffer_list_get (GstBufferList *list, guint idx); + +GST_API +GstBuffer * gst_buffer_list_get_writable (GstBufferList *list, guint idx); + +GST_API +void gst_buffer_list_insert (GstBufferList *list, gint idx, GstBuffer *buffer); + +GST_API +void gst_buffer_list_remove (GstBufferList *list, guint idx, guint length); + +GST_API +gboolean gst_buffer_list_foreach (GstBufferList *list, + GstBufferListFunc func, + gpointer user_data); +GST_API +GstBufferList * gst_buffer_list_copy_deep (const GstBufferList * list); + +GST_API +gsize gst_buffer_list_calculate_size (GstBufferList * list); + +#define gst_buffer_list_add(l,b) gst_buffer_list_insert((l),-1,(b)); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBufferList, gst_buffer_list_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BUFFER_LIST_H__ */ diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c new file mode 100644 index 0000000..3d91236 --- /dev/null +++ b/gst/gstbufferpool.c @@ -0,0 +1,1402 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * gstbufferpool.c: GstBufferPool baseclass + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbufferpool + * @title: GstBufferPool + * @short_description: Pool for buffers + * @see_also: #GstBuffer + * + * A #GstBufferPool is an object that can be used to pre-allocate and recycle + * buffers of the same size and with the same properties. + * + * A #GstBufferPool is created with gst_buffer_pool_new(). + * + * Once a pool is created, it needs to be configured. A call to + * gst_buffer_pool_get_config() returns the current configuration structure from + * the pool. With gst_buffer_pool_config_set_params() and + * gst_buffer_pool_config_set_allocator() the bufferpool parameters and + * allocator can be configured. Other properties can be configured in the pool + * depending on the pool implementation. + * + * A bufferpool can have extra options that can be enabled with + * gst_buffer_pool_config_add_option(). The available options can be retrieved + * with gst_buffer_pool_get_options(). Some options allow for additional + * configuration properties to be set. + * + * After the configuration structure has been configured, + * gst_buffer_pool_set_config() updates the configuration in the pool. This can + * fail when the configuration structure is not accepted. + * + * After the a pool has been configured, it can be activated with + * gst_buffer_pool_set_active(). This will preallocate the configured resources + * in the pool. + * + * When the pool is active, gst_buffer_pool_acquire_buffer() can be used to + * retrieve a buffer from the pool. + * + * Buffers allocated from a bufferpool will automatically be returned to the + * pool with gst_buffer_pool_release_buffer() when their refcount drops to 0. + * + * The bufferpool can be deactivated again with gst_buffer_pool_set_active(). + * All further gst_buffer_pool_acquire_buffer() calls will return an error. When + * all buffers are returned to the pool they will be freed. + * + * Use gst_object_unref() to release the reference to a bufferpool. If the + * refcount of the pool reaches 0, the pool will be freed. + */ + +#include "gst_private.h" +#include "glib-compat-private.h" + +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "gstatomicqueue.h" +#include "gstpoll.h" +#include "gstinfo.h" +#include "gstquark.h" +#include "gstvalue.h" + +#include "gstbufferpool.h" + +#ifdef G_OS_WIN32 +# ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN /* This is just to placate gcc */ +# endif +#endif /* G_OS_WIN32 */ + +GST_DEBUG_CATEGORY_STATIC (gst_buffer_pool_debug); +#define GST_CAT_DEFAULT gst_buffer_pool_debug + +#define GST_BUFFER_POOL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BUFFER_POOL, GstBufferPoolPrivate)) + +#define GST_BUFFER_POOL_LOCK(pool) (g_rec_mutex_lock(&pool->priv->rec_lock)) +#define GST_BUFFER_POOL_UNLOCK(pool) (g_rec_mutex_unlock(&pool->priv->rec_lock)) + +struct _GstBufferPoolPrivate +{ + GstAtomicQueue *queue; + GstPoll *poll; + + GRecMutex rec_lock; + + gboolean started; + gboolean active; + gint outstanding; /* number of buffers that are in use */ + + gboolean configured; + GstStructure *config; + + guint size; + guint min_buffers; + guint max_buffers; + guint cur_buffers; + GstAllocator *allocator; + GstAllocationParams params; +}; + +static void gst_buffer_pool_finalize (GObject * object); + +G_DEFINE_TYPE (GstBufferPool, gst_buffer_pool, GST_TYPE_OBJECT); + +static gboolean default_start (GstBufferPool * pool); +static gboolean default_stop (GstBufferPool * pool); +static gboolean default_set_config (GstBufferPool * pool, + GstStructure * config); +static GstFlowReturn default_alloc_buffer (GstBufferPool * pool, + GstBuffer ** buffer, GstBufferPoolAcquireParams * params); +static GstFlowReturn default_acquire_buffer (GstBufferPool * pool, + GstBuffer ** buffer, GstBufferPoolAcquireParams * params); +static void default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer); +static void default_free_buffer (GstBufferPool * pool, GstBuffer * buffer); +static void default_release_buffer (GstBufferPool * pool, GstBuffer * buffer); + +static void +gst_buffer_pool_class_init (GstBufferPoolClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstBufferPoolPrivate)); + + gobject_class->finalize = gst_buffer_pool_finalize; + + klass->start = default_start; + klass->stop = default_stop; + klass->set_config = default_set_config; + klass->acquire_buffer = default_acquire_buffer; + klass->reset_buffer = default_reset_buffer; + klass->alloc_buffer = default_alloc_buffer; + klass->release_buffer = default_release_buffer; + klass->free_buffer = default_free_buffer; + + GST_DEBUG_CATEGORY_INIT (gst_buffer_pool_debug, "bufferpool", 0, + "bufferpool debug"); +} + +static void +gst_buffer_pool_init (GstBufferPool * pool) +{ + GstBufferPoolPrivate *priv; + + priv = pool->priv = GST_BUFFER_POOL_GET_PRIVATE (pool); + + g_rec_mutex_init (&priv->rec_lock); + + priv->poll = gst_poll_new_timer (); + priv->queue = gst_atomic_queue_new (16); + pool->flushing = 1; + priv->active = FALSE; + priv->configured = FALSE; + priv->started = FALSE; + priv->config = gst_structure_new_id_empty (GST_QUARK (BUFFER_POOL_CONFIG)); + gst_buffer_pool_config_set_params (priv->config, NULL, 0, 0, 0); + priv->allocator = NULL; + gst_allocation_params_init (&priv->params); + gst_buffer_pool_config_set_allocator (priv->config, priv->allocator, + &priv->params); + /* 1 control write for flushing - the flush token */ + gst_poll_write_control (priv->poll); + /* 1 control write for marking that we are not waiting for poll - the wait token */ + gst_poll_write_control (priv->poll); + + GST_DEBUG_OBJECT (pool, "created"); +} + +static void +gst_buffer_pool_finalize (GObject * object) +{ + GstBufferPool *pool; + GstBufferPoolPrivate *priv; + + pool = GST_BUFFER_POOL_CAST (object); + priv = pool->priv; + + GST_DEBUG_OBJECT (pool, "%p finalize", pool); + + gst_buffer_pool_set_active (pool, FALSE); + gst_atomic_queue_unref (priv->queue); + gst_poll_free (priv->poll); + gst_structure_free (priv->config); + g_rec_mutex_clear (&priv->rec_lock); + if (priv->allocator) + gst_object_unref (priv->allocator); + + G_OBJECT_CLASS (gst_buffer_pool_parent_class)->finalize (object); +} + +/** + * gst_buffer_pool_new: + * + * Creates a new #GstBufferPool instance. + * + * Returns: (transfer full): a new #GstBufferPool instance + */ +GstBufferPool * +gst_buffer_pool_new (void) +{ + GstBufferPool *result; + + result = g_object_new (GST_TYPE_BUFFER_POOL, NULL); + GST_DEBUG_OBJECT (result, "created new buffer pool"); + + /* Clear floating flag */ + gst_object_ref_sink (result); + + return result; +} + +static GstFlowReturn +default_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer, + GstBufferPoolAcquireParams * params) +{ + GstBufferPoolPrivate *priv = pool->priv; + + *buffer = + gst_buffer_new_allocate (priv->allocator, priv->size, &priv->params); + + if (!*buffer) + return GST_FLOW_ERROR; + + return GST_FLOW_OK; +} + +static gboolean +mark_meta_pooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) +{ + GST_DEBUG_OBJECT (GST_BUFFER_POOL (user_data), + "marking meta %p as POOLED in buffer %p", *meta, buffer); + GST_META_FLAG_SET (*meta, GST_META_FLAG_POOLED); + GST_META_FLAG_SET (*meta, GST_META_FLAG_LOCKED); + + return TRUE; +} + +static GstFlowReturn +do_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer, + GstBufferPoolAcquireParams * params) +{ + GstBufferPoolPrivate *priv = pool->priv; + GstFlowReturn result; + gint cur_buffers, max_buffers; + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + if (G_UNLIKELY (!pclass->alloc_buffer)) + goto no_function; + + max_buffers = priv->max_buffers; + + /* increment the allocation counter */ + cur_buffers = g_atomic_int_add (&priv->cur_buffers, 1); + if (max_buffers && cur_buffers >= max_buffers) + goto max_reached; + + result = pclass->alloc_buffer (pool, buffer, params); + if (G_UNLIKELY (result != GST_FLOW_OK)) + goto alloc_failed; + + /* lock all metadata and mark as pooled, we want this to remain on + * the buffer and we want to remove any other metadata that gets added + * later */ + gst_buffer_foreach_meta (*buffer, mark_meta_pooled, pool); + + /* un-tag memory, this is how we expect the buffer when it is + * released again */ + GST_BUFFER_FLAG_UNSET (*buffer, GST_BUFFER_FLAG_TAG_MEMORY); + + GST_LOG_OBJECT (pool, "allocated buffer %d/%d, %p", cur_buffers, + max_buffers, *buffer); + + return result; + + /* ERRORS */ +no_function: + { + GST_ERROR_OBJECT (pool, "no alloc function"); + return GST_FLOW_NOT_SUPPORTED; + } +max_reached: + { + GST_DEBUG_OBJECT (pool, "max buffers reached"); + g_atomic_int_add (&priv->cur_buffers, -1); + return GST_FLOW_EOS; + } +alloc_failed: + { + GST_WARNING_OBJECT (pool, "alloc function failed"); + g_atomic_int_add (&priv->cur_buffers, -1); + return result; + } +} + +/* the default implementation for preallocating the buffers in the pool */ +static gboolean +default_start (GstBufferPool * pool) +{ + guint i; + GstBufferPoolPrivate *priv = pool->priv; + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + /* we need to prealloc buffers */ + for (i = 0; i < priv->min_buffers; i++) { + GstBuffer *buffer; + + if (do_alloc_buffer (pool, &buffer, NULL) != GST_FLOW_OK) + goto alloc_failed; + + /* release to the queue, we call the vmethod directly, we don't need to do + * the other refcount handling right now. */ + if (G_LIKELY (pclass->release_buffer)) + pclass->release_buffer (pool, buffer); + } + return TRUE; + + /* ERRORS */ +alloc_failed: + { + GST_WARNING_OBJECT (pool, "failed to allocate buffer"); + return FALSE; + } +} + +/* must be called with the lock */ +static gboolean +do_start (GstBufferPool * pool) +{ + GstBufferPoolPrivate *priv = pool->priv; + + if (!priv->started) { + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + GST_LOG_OBJECT (pool, "starting"); + /* start the pool, subclasses should allocate buffers and put them + * in the queue */ + if (G_LIKELY (pclass->start)) { + if (!pclass->start (pool)) + return FALSE; + } + priv->started = TRUE; + } + return TRUE; +} + +static void +default_free_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); +} + +static void +do_free_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + GstBufferPoolPrivate *priv; + GstBufferPoolClass *pclass; + + priv = pool->priv; + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + g_atomic_int_add (&priv->cur_buffers, -1); + GST_LOG_OBJECT (pool, "freeing buffer %p (%u left)", buffer, + priv->cur_buffers); + + if (G_LIKELY (pclass->free_buffer)) + pclass->free_buffer (pool, buffer); +} + +/* must be called with the lock */ +static gboolean +default_stop (GstBufferPool * pool) +{ + GstBufferPoolPrivate *priv = pool->priv; + GstBuffer *buffer; + + /* clear the pool */ + while ((buffer = gst_atomic_queue_pop (priv->queue))) { + while (!gst_poll_read_control (priv->poll)) { + if (errno == EWOULDBLOCK) { + /* We put the buffer into the queue but did not finish writing control + * yet, let's wait a bit and retry */ + g_thread_yield (); + continue; + } else { + /* Critical error but GstPoll already complained */ + break; + } + } + do_free_buffer (pool, buffer); + } + return priv->cur_buffers == 0; +} + +/* must be called with the lock */ +static gboolean +do_stop (GstBufferPool * pool) +{ + GstBufferPoolPrivate *priv = pool->priv; + + if (priv->started) { + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + GST_LOG_OBJECT (pool, "stopping"); + if (G_LIKELY (pclass->stop)) { + if (!pclass->stop (pool)) + return FALSE; + } + priv->started = FALSE; + } + return TRUE; +} + +/* must be called with the lock */ +static void +do_set_flushing (GstBufferPool * pool, gboolean flushing) +{ + GstBufferPoolPrivate *priv = pool->priv; + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + if (GST_BUFFER_POOL_IS_FLUSHING (pool) == flushing) + return; + + if (flushing) { + g_atomic_int_set (&pool->flushing, 1); + /* Write the flush token to wake up any waiters */ + gst_poll_write_control (priv->poll); + + if (pclass->flush_start) + pclass->flush_start (pool); + } else { + if (pclass->flush_stop) + pclass->flush_stop (pool); + + while (!gst_poll_read_control (priv->poll)) { + if (errno == EWOULDBLOCK) { + /* This should not really happen unless flushing and unflushing + * happens on different threads. Let's wait a bit to get back flush + * token from the thread that was setting it to flushing */ + g_thread_yield (); + continue; + } else { + /* Critical error but GstPoll already complained */ + break; + } + } + + g_atomic_int_set (&pool->flushing, 0); + } +} + +/** + * gst_buffer_pool_set_active: + * @pool: a #GstBufferPool + * @active: the new active state + * + * Control the active state of @pool. When the pool is inactive, new calls to + * gst_buffer_pool_acquire_buffer() will return with %GST_FLOW_FLUSHING. + * + * Activating the bufferpool will preallocate all resources in the pool based on + * the configuration of the pool. + * + * Deactivating will free the resources again when there are no outstanding + * buffers. When there are outstanding buffers, they will be freed as soon as + * they are all returned to the pool. + * + * Returns: %FALSE when the pool was not configured or when preallocation of the + * buffers failed. + */ +gboolean +gst_buffer_pool_set_active (GstBufferPool * pool, gboolean active) +{ + gboolean res = TRUE; + GstBufferPoolPrivate *priv; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE); + + GST_LOG_OBJECT (pool, "active %d", active); + + priv = pool->priv; + + GST_BUFFER_POOL_LOCK (pool); + /* just return if we are already in the right state */ + if (priv->active == active) + goto was_ok; + + /* we need to be configured */ + if (!priv->configured) + goto not_configured; + + if (active) { + if (!do_start (pool)) + goto start_failed; + + /* flush_stop my release buffers, setting to active to avoid running + * do_stop while activating the pool */ + priv->active = TRUE; + + /* unset the flushing state now */ + do_set_flushing (pool, FALSE); + } else { + gint outstanding; + + /* set to flushing first */ + do_set_flushing (pool, TRUE); + + /* when all buffers are in the pool, free them. Else they will be + * freed when they are released */ + outstanding = g_atomic_int_get (&priv->outstanding); + GST_LOG_OBJECT (pool, "outstanding buffers %d", outstanding); + if (outstanding == 0) { + if (!do_stop (pool)) + goto stop_failed; + } + + priv->active = FALSE; + } + GST_BUFFER_POOL_UNLOCK (pool); + + return res; + +was_ok: + { + GST_DEBUG_OBJECT (pool, "pool was in the right state"); + GST_BUFFER_POOL_UNLOCK (pool); + return TRUE; + } +not_configured: + { + GST_ERROR_OBJECT (pool, "pool was not configured"); + GST_BUFFER_POOL_UNLOCK (pool); + return FALSE; + } +start_failed: + { + GST_ERROR_OBJECT (pool, "start failed"); + GST_BUFFER_POOL_UNLOCK (pool); + return FALSE; + } +stop_failed: + { + GST_WARNING_OBJECT (pool, "stop failed"); + GST_BUFFER_POOL_UNLOCK (pool); + return FALSE; + } +} + +/** + * gst_buffer_pool_is_active: + * @pool: a #GstBufferPool + * + * Check if @pool is active. A pool can be activated with the + * gst_buffer_pool_set_active() call. + * + * Returns: %TRUE when the pool is active. + */ +gboolean +gst_buffer_pool_is_active (GstBufferPool * pool) +{ + gboolean res; + + GST_BUFFER_POOL_LOCK (pool); + res = pool->priv->active; + GST_BUFFER_POOL_UNLOCK (pool); + + return res; +} + +static gboolean +default_set_config (GstBufferPool * pool, GstStructure * config) +{ + GstBufferPoolPrivate *priv = pool->priv; + GstCaps *caps; + guint size, min_buffers, max_buffers; + GstAllocator *allocator; + GstAllocationParams params; + + /* parse the config and keep around */ + if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, + &max_buffers)) + goto wrong_config; + + if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) + goto wrong_config; + + GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config); + + priv->size = size; + priv->min_buffers = min_buffers; + priv->max_buffers = max_buffers; + priv->cur_buffers = 0; + + if (priv->allocator) + gst_object_unref (priv->allocator); + if ((priv->allocator = allocator)) + gst_object_ref (allocator); + priv->params = params; + + return TRUE; + +wrong_config: + { + GST_WARNING_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config); + return FALSE; + } +} + +/** + * gst_buffer_pool_set_config: + * @pool: a #GstBufferPool + * @config: (transfer full): a #GstStructure + * + * Set the configuration of the pool. If the pool is already configured, and + * the configuration haven't change, this function will return %TRUE. If the + * pool is active, this method will return %FALSE and active configuration + * will remain. Buffers allocated form this pool must be returned or else this + * function will do nothing and return %FALSE. + * + * @config is a #GstStructure that contains the configuration parameters for + * the pool. A default and mandatory set of parameters can be configured with + * gst_buffer_pool_config_set_params(), gst_buffer_pool_config_set_allocator() + * and gst_buffer_pool_config_add_option(). + * + * If the parameters in @config can not be set exactly, this function returns + * %FALSE and will try to update as much state as possible. The new state can + * then be retrieved and refined with gst_buffer_pool_get_config(). + * + * This function takes ownership of @config. + * + * Returns: %TRUE when the configuration could be set. + */ +gboolean +gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) +{ + gboolean result; + GstBufferPoolClass *pclass; + GstBufferPoolPrivate *priv; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE); + g_return_val_if_fail (config != NULL, FALSE); + + priv = pool->priv; + + GST_BUFFER_POOL_LOCK (pool); + + /* nothing to do if config is unchanged */ + if (priv->configured && gst_structure_is_equal (config, priv->config)) + goto config_unchanged; + + /* can't change the settings when active */ + if (priv->active) + goto was_active; + + /* we can't change when outstanding buffers */ + if (g_atomic_int_get (&priv->outstanding) != 0) + goto have_outstanding; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + /* set the new config */ + if (G_LIKELY (pclass->set_config)) + result = pclass->set_config (pool, config); + else + result = FALSE; + + /* save the config regardless of the result so user can read back the + * modified config and evaluate if the changes are acceptable */ + if (priv->config) + gst_structure_free (priv->config); + priv->config = config; + + if (result) { + /* now we are configured */ + priv->configured = TRUE; + } + GST_BUFFER_POOL_UNLOCK (pool); + + return result; + +config_unchanged: + { + gst_structure_free (config); + GST_BUFFER_POOL_UNLOCK (pool); + return TRUE; + } + /* ERRORS */ +was_active: + { + gst_structure_free (config); + GST_INFO_OBJECT (pool, "can't change config, we are active"); + GST_BUFFER_POOL_UNLOCK (pool); + return FALSE; + } +have_outstanding: + { + gst_structure_free (config); + GST_WARNING_OBJECT (pool, "can't change config, have outstanding buffers"); + GST_BUFFER_POOL_UNLOCK (pool); + return FALSE; + } +} + +/** + * gst_buffer_pool_get_config: + * @pool: a #GstBufferPool + * + * Get a copy of the current configuration of the pool. This configuration + * can either be modified and used for the gst_buffer_pool_set_config() call + * or it must be freed after usage. + * + * Returns: (transfer full): a copy of the current configuration of @pool. use + * gst_structure_free() after usage or gst_buffer_pool_set_config(). + */ +GstStructure * +gst_buffer_pool_get_config (GstBufferPool * pool) +{ + GstStructure *result; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), NULL); + + GST_BUFFER_POOL_LOCK (pool); + result = gst_structure_copy (pool->priv->config); + GST_BUFFER_POOL_UNLOCK (pool); + + return result; +} + +static const gchar *empty_option[] = { NULL }; + +/** + * gst_buffer_pool_get_options: + * @pool: a #GstBufferPool + * + * Get a %NULL terminated array of string with supported bufferpool options for + * @pool. An option would typically be enabled with + * gst_buffer_pool_config_add_option(). + * + * Returns: (array zero-terminated=1) (transfer none): a %NULL terminated array + * of strings. + */ +const gchar ** +gst_buffer_pool_get_options (GstBufferPool * pool) +{ + GstBufferPoolClass *pclass; + const gchar **result; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), NULL); + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + if (G_LIKELY (pclass->get_options)) { + if ((result = pclass->get_options (pool)) == NULL) + goto invalid_result; + } else + result = empty_option; + + return result; + + /* ERROR */ +invalid_result: + { + g_warning ("bufferpool subclass returned NULL options"); + return empty_option; + } +} + +/** + * gst_buffer_pool_has_option: + * @pool: a #GstBufferPool + * @option: an option + * + * Check if the bufferpool supports @option. + * + * Returns: %TRUE if the buffer pool contains @option. + */ +gboolean +gst_buffer_pool_has_option (GstBufferPool * pool, const gchar * option) +{ + guint i; + const gchar **options; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE); + g_return_val_if_fail (option != NULL, FALSE); + + options = gst_buffer_pool_get_options (pool); + + for (i = 0; options[i]; i++) { + if (g_str_equal (options[i], option)) + return TRUE; + } + return FALSE; +} + +/** + * gst_buffer_pool_config_set_params: + * @config: a #GstBufferPool configuration + * @caps: caps for the buffers + * @size: the size of each buffer, not including prefix and padding + * @min_buffers: the minimum amount of buffers to allocate. + * @max_buffers: the maximum amount of buffers to allocate or 0 for unlimited. + * + * Configure @config with the given parameters. + */ +void +gst_buffer_pool_config_set_params (GstStructure * config, GstCaps * caps, + guint size, guint min_buffers, guint max_buffers) +{ + g_return_if_fail (config != NULL); + g_return_if_fail (max_buffers == 0 || min_buffers <= max_buffers); + g_return_if_fail (caps == NULL || gst_caps_is_fixed (caps)); + + gst_structure_id_set (config, + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, + GST_QUARK (SIZE), G_TYPE_UINT, size, + GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers, + GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers, NULL); +} + +/** + * gst_buffer_pool_config_set_allocator: + * @config: a #GstBufferPool configuration + * @allocator: (allow-none): a #GstAllocator + * @params: (allow-none): #GstAllocationParams + * + * Set the @allocator and @params on @config. + * + * One of @allocator and @params can be %NULL, but not both. When @allocator + * is %NULL, the default allocator of the pool will use the values in @param + * to perform its allocation. When @param is %NULL, the pool will use the + * provided @allocator with its default #GstAllocationParams. + * + * A call to gst_buffer_pool_set_config() can update the allocator and params + * with the values that it is able to do. Some pools are, for example, not able + * to operate with different allocators or cannot allocate with the values + * specified in @params. Use gst_buffer_pool_get_config() to get the currently + * used values. + */ +void +gst_buffer_pool_config_set_allocator (GstStructure * config, + GstAllocator * allocator, const GstAllocationParams * params) +{ + g_return_if_fail (config != NULL); + g_return_if_fail (allocator != NULL || params != NULL); + + gst_structure_id_set (config, + GST_QUARK (ALLOCATOR), GST_TYPE_ALLOCATOR, allocator, + GST_QUARK (PARAMS), GST_TYPE_ALLOCATION_PARAMS, params, NULL); +} + +/** + * gst_buffer_pool_config_add_option: + * @config: a #GstBufferPool configuration + * @option: an option to add + * + * Enabled the option in @config. This will instruct the @bufferpool to enable + * the specified option on the buffers that it allocates. + * + * The supported options by @pool can be retrieved with gst_buffer_pool_get_options(). + */ +void +gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option) +{ + const GValue *value; + GValue option_value = { 0, }; + guint i, len; + + g_return_if_fail (config != NULL); + + value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS)); + if (value) { + len = gst_value_array_get_size (value); + for (i = 0; i < len; ++i) { + const GValue *nth_val = gst_value_array_get_value (value, i); + + if (g_str_equal (option, g_value_get_string (nth_val))) + return; + } + } else { + GValue new_array_val = { 0, }; + + g_value_init (&new_array_val, GST_TYPE_ARRAY); + gst_structure_id_take_value (config, GST_QUARK (OPTIONS), &new_array_val); + value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS)); + } + g_value_init (&option_value, G_TYPE_STRING); + g_value_set_string (&option_value, option); + gst_value_array_append_and_take_value ((GValue *) value, &option_value); +} + +/** + * gst_buffer_pool_config_n_options: + * @config: a #GstBufferPool configuration + * + * Retrieve the number of values currently stored in the options array of the + * @config structure. + * + * Returns: the options array size as a #guint. + */ +guint +gst_buffer_pool_config_n_options (GstStructure * config) +{ + const GValue *value; + guint size = 0; + + g_return_val_if_fail (config != NULL, 0); + + value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS)); + if (value) { + size = gst_value_array_get_size (value); + } + return size; +} + +/** + * gst_buffer_pool_config_get_option: + * @config: a #GstBufferPool configuration + * @index: position in the option array to read + * + * Parse an available @config and get the option at @index of the options API + * array. + * + * Returns: a #gchar of the option at @index. + */ +const gchar * +gst_buffer_pool_config_get_option (GstStructure * config, guint index) +{ + const GValue *value; + const gchar *ret = NULL; + + g_return_val_if_fail (config != NULL, 0); + + value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS)); + if (value) { + const GValue *option_value; + + option_value = gst_value_array_get_value (value, index); + if (option_value) + ret = g_value_get_string (option_value); + } + return ret; +} + +/** + * gst_buffer_pool_config_has_option: + * @config: a #GstBufferPool configuration + * @option: an option + * + * Check if @config contains @option. + * + * Returns: %TRUE if the options array contains @option. + */ +gboolean +gst_buffer_pool_config_has_option (GstStructure * config, const gchar * option) +{ + const GValue *value; + guint i, len; + + g_return_val_if_fail (config != NULL, 0); + + value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS)); + if (value) { + len = gst_value_array_get_size (value); + for (i = 0; i < len; ++i) { + const GValue *nth_val = gst_value_array_get_value (value, i); + + if (g_str_equal (option, g_value_get_string (nth_val))) + return TRUE; + } + } + return FALSE; +} + +/** + * gst_buffer_pool_config_get_params: + * @config: (transfer none): a #GstBufferPool configuration + * @caps: (out) (transfer none) (allow-none): the caps of buffers + * @size: (out) (allow-none): the size of each buffer, not including prefix and padding + * @min_buffers: (out) (allow-none): the minimum amount of buffers to allocate. + * @max_buffers: (out) (allow-none): the maximum amount of buffers to allocate or 0 for unlimited. + * + * Get the configuration values from @config. + * + * Returns: %TRUE if all parameters could be fetched. + */ +gboolean +gst_buffer_pool_config_get_params (GstStructure * config, GstCaps ** caps, + guint * size, guint * min_buffers, guint * max_buffers) +{ + g_return_val_if_fail (config != NULL, FALSE); + + if (caps) { + *caps = g_value_get_boxed (gst_structure_id_get_value (config, + GST_QUARK (CAPS))); + } + return gst_structure_id_get (config, + GST_QUARK (SIZE), G_TYPE_UINT, size, + GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers, + GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers, NULL); +} + +/** + * gst_buffer_pool_config_get_allocator: + * @config: (transfer none): a #GstBufferPool configuration + * @allocator: (out) (allow-none) (transfer none): a #GstAllocator, or %NULL + * @params: (out) (allow-none): #GstAllocationParams, or %NULL + * + * Get the @allocator and @params from @config. + * + * Returns: %TRUE, if the values are set. + */ +gboolean +gst_buffer_pool_config_get_allocator (GstStructure * config, + GstAllocator ** allocator, GstAllocationParams * params) +{ + g_return_val_if_fail (config != NULL, FALSE); + + if (allocator) + *allocator = g_value_get_object (gst_structure_id_get_value (config, + GST_QUARK (ALLOCATOR))); + if (params) { + GstAllocationParams *p; + + p = g_value_get_boxed (gst_structure_id_get_value (config, + GST_QUARK (PARAMS))); + if (p) { + *params = *p; + } else { + gst_allocation_params_init (params); + } + } + return TRUE; +} + +/** + * gst_buffer_pool_config_validate_params: + * @config: (transfer none): a #GstBufferPool configuration + * @caps: (transfer none): the excepted caps of buffers + * @size: the expected size of each buffer, not including prefix and padding + * @min_buffers: the expected minimum amount of buffers to allocate. + * @max_buffers: the expect maximum amount of buffers to allocate or 0 for unlimited. + * + * Validate that changes made to @config are still valid in the context of the + * expected parameters. This function is a helper that can be used to validate + * changes made by a pool to a config when gst_buffer_pool_set_config() + * returns %FALSE. This expects that @caps haven't changed and that + * @min_buffers aren't lower then what we initially expected. + * This does not check if options or allocator parameters are still valid, + * won't check if size have changed, since changing the size is valid to adapt + * padding. + * + * Since: 1.4 + * + * Returns: %TRUE, if the parameters are valid in this context. + */ +gboolean +gst_buffer_pool_config_validate_params (GstStructure * config, GstCaps * caps, + guint size, guint min_buffers, G_GNUC_UNUSED guint max_buffers) +{ + GstCaps *newcaps; + guint newsize, newmin; + gboolean ret = FALSE; + + g_return_val_if_fail (config != NULL, FALSE); + + gst_buffer_pool_config_get_params (config, &newcaps, &newsize, &newmin, NULL); + + if (gst_caps_is_equal (caps, newcaps) && (newsize >= size) + && (newmin >= min_buffers)) + ret = TRUE; + + return ret; +} + +static GstFlowReturn +default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer, + GstBufferPoolAcquireParams * params) +{ + GstFlowReturn result; + GstBufferPoolPrivate *priv = pool->priv; + + while (TRUE) { + if (G_UNLIKELY (GST_BUFFER_POOL_IS_FLUSHING (pool))) + goto flushing; + + /* try to get a buffer from the queue */ + *buffer = gst_atomic_queue_pop (priv->queue); + if (G_LIKELY (*buffer)) { + while (!gst_poll_read_control (priv->poll)) { + if (errno == EWOULDBLOCK) { + /* We put the buffer into the queue but did not finish writing control + * yet, let's wait a bit and retry */ + g_thread_yield (); + continue; + } else { + /* Critical error but GstPoll already complained */ + break; + } + } + result = GST_FLOW_OK; + GST_LOG_OBJECT (pool, "acquired buffer %p", *buffer); + break; + } + + /* no buffer, try to allocate some more */ + GST_LOG_OBJECT (pool, "no buffer, trying to allocate"); + result = do_alloc_buffer (pool, buffer, params); + if (G_LIKELY (result == GST_FLOW_OK)) + /* we have a buffer, return it */ + break; + + if (G_UNLIKELY (result != GST_FLOW_EOS)) + /* something went wrong, return error */ + break; + + /* check if we need to wait */ + if (params && (params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT)) { + GST_LOG_OBJECT (pool, "no more buffers"); + break; + } + + /* now we release the control socket, we wait for a buffer release or + * flushing */ + if (!gst_poll_read_control (pool->priv->poll)) { + if (errno == EWOULDBLOCK) { + /* This means that we have two threads trying to allocate buffers + * already, and the other one already got the wait token. This + * means that we only have to wait for the poll now and not write the + * token afterwards: we will be woken up once the other thread is + * woken up and that one will write the wait token it removed */ + GST_LOG_OBJECT (pool, "waiting for free buffers or flushing"); + gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE); + } else { + /* This is a critical error, GstPoll already gave a warning */ + result = GST_FLOW_ERROR; + break; + } + } else { + /* We're the first thread waiting, we got the wait token and have to + * write it again later + * OR + * We're a second thread and just consumed the flush token and block all + * other threads, in which case we must not wait and give it back + * immediately */ + if (!GST_BUFFER_POOL_IS_FLUSHING (pool)) { + GST_LOG_OBJECT (pool, "waiting for free buffers or flushing"); + gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE); + } + gst_poll_write_control (pool->priv->poll); + } + } + + return result; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (pool, "we are flushing"); + return GST_FLOW_FLUSHING; + } +} + +static inline void +dec_outstanding (GstBufferPool * pool) +{ + if (g_atomic_int_dec_and_test (&pool->priv->outstanding)) { + /* all buffers are returned to the pool, see if we need to free them */ + if (GST_BUFFER_POOL_IS_FLUSHING (pool)) { + /* take the lock so that set_active is not run concurrently */ + GST_BUFFER_POOL_LOCK (pool); + /* now that we have the lock, check if we have been de-activated with + * outstanding buffers */ + if (!pool->priv->active) + do_stop (pool); + + GST_BUFFER_POOL_UNLOCK (pool); + } + } +} + +static gboolean +remove_meta_unpooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) +{ + if (!GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) { + GST_META_FLAG_UNSET (*meta, GST_META_FLAG_LOCKED); + *meta = NULL; + } + return TRUE; +} + +static void +default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + GST_BUFFER_FLAGS (buffer) &= GST_BUFFER_FLAG_TAG_MEMORY; + + GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE; + + /* remove all metadata without the POOLED flag */ + gst_buffer_foreach_meta (buffer, remove_meta_unpooled, pool); +} + +/** + * gst_buffer_pool_acquire_buffer: + * @pool: a #GstBufferPool + * @buffer: (out): a location for a #GstBuffer + * @params: (transfer none) (allow-none): parameters. + * + * Acquire a buffer from @pool. @buffer should point to a memory location that + * can hold a pointer to the new buffer. + * + * @params can be %NULL or contain optional parameters to influence the + * allocation. + * + * Returns: a #GstFlowReturn such as %GST_FLOW_FLUSHING when the pool is + * inactive. + */ +GstFlowReturn +gst_buffer_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer, + GstBufferPoolAcquireParams * params) +{ + GstBufferPoolClass *pclass; + GstFlowReturn result; + + g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + /* assume we'll have one more outstanding buffer we need to do that so + * that concurrent set_active doesn't clear the buffers */ + g_atomic_int_inc (&pool->priv->outstanding); + + if (G_LIKELY (pclass->acquire_buffer)) + result = pclass->acquire_buffer (pool, buffer, params); + else + result = GST_FLOW_NOT_SUPPORTED; + + if (G_LIKELY (result == GST_FLOW_OK)) { + /* all buffers from the pool point to the pool and have the refcount of the + * pool incremented */ + (*buffer)->pool = gst_object_ref (pool); + } else { + dec_outstanding (pool); + } + + return result; +} + +static void +default_release_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + GST_LOG_OBJECT (pool, "released buffer %p %d", buffer, + GST_MINI_OBJECT_FLAGS (buffer)); + + /* memory should be untouched */ + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))) + goto memory_tagged; + + /* size should have been reset. This is not a catch all, pool with + * size requirement per memory should do their own check. */ + if (G_UNLIKELY (gst_buffer_get_size (buffer) != pool->priv->size)) + goto size_changed; + + /* all memory should be exclusive to this buffer (and thus be writable) */ + if (G_UNLIKELY (!gst_buffer_is_all_memory_writable (buffer))) + goto not_writable; + + /* keep it around in our queue */ + gst_atomic_queue_push (pool->priv->queue, buffer); + gst_poll_write_control (pool->priv->poll); + + return; + +memory_tagged: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, + "discarding buffer %p: memory tag set", buffer); + goto discard; + } +size_changed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, + "discarding buffer %p: size %" G_GSIZE_FORMAT " != %u", + buffer, gst_buffer_get_size (buffer), pool->priv->size); + goto discard; + } +not_writable: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pool, + "discarding buffer %p: memory not writable", buffer); + goto discard; + } +discard: + { + do_free_buffer (pool, buffer); + return; + } +} + +/** + * gst_buffer_pool_release_buffer: + * @pool: a #GstBufferPool + * @buffer: (transfer full): a #GstBuffer + * + * Release @buffer to @pool. @buffer should have previously been allocated from + * @pool with gst_buffer_pool_acquire_buffer(). + * + * This function is usually called automatically when the last ref on @buffer + * disappears. + */ +void +gst_buffer_pool_release_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + GstBufferPoolClass *pclass; + + g_return_if_fail (GST_IS_BUFFER_POOL (pool)); + g_return_if_fail (buffer != NULL); + + /* check that the buffer is ours, all buffers returned to the pool have the + * pool member set to NULL and the pool refcount decreased */ + if (!g_atomic_pointer_compare_and_exchange (&buffer->pool, pool, NULL)) + return; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + /* reset the buffer when needed */ + if (G_LIKELY (pclass->reset_buffer)) + pclass->reset_buffer (pool, buffer); + + if (G_LIKELY (pclass->release_buffer)) + pclass->release_buffer (pool, buffer); + + dec_outstanding (pool); + + /* decrease the refcount that the buffer had to us */ + gst_object_unref (pool); +} + +/** + * gst_buffer_pool_set_flushing: + * @pool: a #GstBufferPool + * @flushing: whether to start or stop flushing + * + * Enable or disable the flushing state of a @pool without freeing or + * allocating buffers. + * + * Since: 1.4 + */ +void +gst_buffer_pool_set_flushing (GstBufferPool * pool, gboolean flushing) +{ + GstBufferPoolPrivate *priv; + + g_return_if_fail (GST_IS_BUFFER_POOL (pool)); + + GST_LOG_OBJECT (pool, "flushing %d", flushing); + + priv = pool->priv; + + GST_BUFFER_POOL_LOCK (pool); + + if (!priv->active) { + GST_WARNING_OBJECT (pool, "can't change flushing state of inactive pool"); + goto done; + } + + do_set_flushing (pool, flushing); + +done: + GST_BUFFER_POOL_UNLOCK (pool); +} diff --git a/gst/gstbufferpool.h b/gst/gstbufferpool.h new file mode 100644 index 0000000..d36d066 --- /dev/null +++ b/gst/gstbufferpool.h @@ -0,0 +1,256 @@ +/* GStreamer + * Copyright (C) 2010 Wim Taymans + * + * gstbufferpool.h: Header for GstBufferPool 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_BUFFER_POOL_H__ +#define __GST_BUFFER_POOL_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstBufferPoolPrivate GstBufferPoolPrivate; +typedef struct _GstBufferPoolClass GstBufferPoolClass; + +#define GST_TYPE_BUFFER_POOL (gst_buffer_pool_get_type()) +#define GST_IS_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_POOL)) +#define GST_IS_BUFFER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_POOL)) +#define GST_BUFFER_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_POOL, GstBufferPoolClass)) +#define GST_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_POOL, GstBufferPool)) +#define GST_BUFFER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_POOL, GstBufferPoolClass)) +#define GST_BUFFER_POOL_CAST(obj) ((GstBufferPool *)(obj)) + +/** + * GstBufferPoolAcquireFlags: + * @GST_BUFFER_POOL_ACQUIRE_FLAG_NONE: no flags + * @GST_BUFFER_POOL_ACQUIRE_FLAG_KEY_UNIT: buffer is keyframe + * @GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT: when the bufferpool is empty, acquire_buffer + * will by default block until a buffer is released into the pool again. Setting + * this flag makes acquire_buffer return #GST_FLOW_EOS instead of blocking. + * @GST_BUFFER_POOL_ACQUIRE_FLAG_DISCONT: buffer is discont + * @GST_BUFFER_POOL_ACQUIRE_FLAG_LAST: last flag, subclasses can use private flags + * starting from this value. + * + * Additional flags to control the allocation of a buffer + */ +typedef enum { + GST_BUFFER_POOL_ACQUIRE_FLAG_NONE = 0, + GST_BUFFER_POOL_ACQUIRE_FLAG_KEY_UNIT = (1 << 0), + GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT = (1 << 1), + GST_BUFFER_POOL_ACQUIRE_FLAG_DISCONT = (1 << 2), + GST_BUFFER_POOL_ACQUIRE_FLAG_LAST = (1 << 16), +} GstBufferPoolAcquireFlags; + +typedef struct _GstBufferPoolAcquireParams GstBufferPoolAcquireParams; + +/** + * GstBufferPoolAcquireParams: + * @format: the format of @start and @stop + * @start: the start position + * @stop: the stop position + * @flags: additional flags + * + * Parameters passed to the gst_buffer_pool_acquire_buffer() function to control the + * allocation of the buffer. + * + * The default implementation ignores the @start and @stop members but other + * implementations can use this extra information to decide what buffer to + * return. + */ +struct _GstBufferPoolAcquireParams { + GstFormat format; + gint64 start; + gint64 stop; + GstBufferPoolAcquireFlags flags; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GST_BUFFER_POOL_IS_FLUSHING: + * @pool: a GstBufferPool + * + * Check if the bufferpool is flushing. Subclasses might want to check the + * state of the pool in the acquire function. + */ +#define GST_BUFFER_POOL_IS_FLUSHING(pool) (g_atomic_int_get (&pool->flushing)) + +/** + * GstBufferPool: + * + * The structure of a #GstBufferPool. Use the associated macros to access the public + * variables. + */ +struct _GstBufferPool { + GstObject object; + + /*< protected >*/ + gint flushing; + + /*< private >*/ + GstBufferPoolPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstBufferPoolClass: + * @object_class: Object parent class + * @get_options: get a list of options supported by this pool + * @set_config: apply the bufferpool configuration. The default configuration + * will parse the default config parameters + * @start: start the bufferpool. The default implementation will preallocate + * min-buffers buffers and put them in the queue + * @stop: stop the bufferpool. the default implementation will free the + * preallocated buffers. This function is called when all the buffers are + * returned to the pool. + * @acquire_buffer: get a new buffer from the pool. The default implementation + * will take a buffer from the queue and optionally wait for a buffer to + * be released when there are no buffers available. + * @alloc_buffer: allocate a buffer. the default implementation allocates + * buffers from the configured memory allocator and with the configured + * parameters. All metadata that is present on the allocated buffer will + * be marked as #GST_META_FLAG_POOLED and #GST_META_FLAG_LOCKED and will + * not be removed from the buffer in @reset_buffer. The buffer should + * have the GST_BUFFER_FLAG_TAG_MEMORY cleared. + * @reset_buffer: reset the buffer to its state when it was freshly allocated. + * The default implementation will clear the flags, timestamps and + * will remove the metadata without the #GST_META_FLAG_POOLED flag (even + * the metadata with #GST_META_FLAG_LOCKED). If the + * #GST_BUFFER_FLAG_TAG_MEMORY was set, this function can also try to + * restore the memory and clear the #GST_BUFFER_FLAG_TAG_MEMORY again. + * @release_buffer: release a buffer back in the pool. The default + * implementation will put the buffer back in the queue and notify any + * blocking acquire_buffer calls when the #GST_BUFFER_FLAG_TAG_MEMORY + * is not set on the buffer. If #GST_BUFFER_FLAG_TAG_MEMORY is set, the + * buffer will be freed with @free_buffer. + * @free_buffer: free a buffer. The default implementation unrefs the buffer. + * @flush_start: enter the flushing state. (Since 1.4) + * @flush_stop: leave the flushign state. (Since 1.4) + * + * The GstBufferPool class. + */ +struct _GstBufferPoolClass { + GstObjectClass object_class; + + /*< public >*/ + const gchar ** (*get_options) (GstBufferPool *pool); + gboolean (*set_config) (GstBufferPool *pool, GstStructure *config); + + gboolean (*start) (GstBufferPool *pool); + gboolean (*stop) (GstBufferPool *pool); + + GstFlowReturn (*acquire_buffer) (GstBufferPool *pool, GstBuffer **buffer, + GstBufferPoolAcquireParams *params); + GstFlowReturn (*alloc_buffer) (GstBufferPool *pool, GstBuffer **buffer, + GstBufferPoolAcquireParams *params); + void (*reset_buffer) (GstBufferPool *pool, GstBuffer *buffer); + void (*release_buffer) (GstBufferPool *pool, GstBuffer *buffer); + void (*free_buffer) (GstBufferPool *pool, GstBuffer *buffer); + void (*flush_start) (GstBufferPool *pool); + void (*flush_stop) (GstBufferPool *pool); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 2]; +}; + +GST_API +GType gst_buffer_pool_get_type (void); + +/* allocation */ + +GST_API +GstBufferPool * gst_buffer_pool_new (void); + +/* state management */ + +GST_API +gboolean gst_buffer_pool_set_active (GstBufferPool *pool, gboolean active); + +GST_API +gboolean gst_buffer_pool_is_active (GstBufferPool *pool); + +GST_API +gboolean gst_buffer_pool_set_config (GstBufferPool *pool, GstStructure *config); + +GST_API +GstStructure * gst_buffer_pool_get_config (GstBufferPool *pool); + +GST_API +const gchar ** gst_buffer_pool_get_options (GstBufferPool *pool); + +GST_API +gboolean gst_buffer_pool_has_option (GstBufferPool *pool, const gchar *option); + +GST_API +void gst_buffer_pool_set_flushing (GstBufferPool *pool, gboolean flushing); + +/* helpers for configuring the config structure */ + +GST_API +void gst_buffer_pool_config_set_params (GstStructure *config, GstCaps *caps, + guint size, guint min_buffers, guint max_buffers); + +GST_API +gboolean gst_buffer_pool_config_get_params (GstStructure *config, GstCaps **caps, + guint *size, guint *min_buffers, guint *max_buffers); + +GST_API +void gst_buffer_pool_config_set_allocator (GstStructure *config, GstAllocator *allocator, + const GstAllocationParams *params); + +GST_API +gboolean gst_buffer_pool_config_get_allocator (GstStructure *config, GstAllocator **allocator, + GstAllocationParams *params); + +/* options */ + +GST_API +guint gst_buffer_pool_config_n_options (GstStructure *config); + +GST_API +void gst_buffer_pool_config_add_option (GstStructure *config, const gchar *option); + +GST_API +const gchar * gst_buffer_pool_config_get_option (GstStructure *config, guint index); + +GST_API +gboolean gst_buffer_pool_config_has_option (GstStructure *config, const gchar *option); + +GST_API +gboolean gst_buffer_pool_config_validate_params (GstStructure *config, GstCaps *caps, + guint size, guint min_buffers, guint max_buffers); + +/* buffer management */ + +GST_API +GstFlowReturn gst_buffer_pool_acquire_buffer (GstBufferPool *pool, GstBuffer **buffer, + GstBufferPoolAcquireParams *params); + +GST_API +void gst_buffer_pool_release_buffer (GstBufferPool *pool, GstBuffer *buffer); + +G_END_DECLS + +#endif /* __GST_BUFFER_POOL_H__ */ diff --git a/gst/gstbus.c b/gst/gstbus.c new file mode 100644 index 0000000..81f2fb9 --- /dev/null +++ b/gst/gstbus.c @@ -0,0 +1,1475 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstbus.c: GstBus subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbus + * @title: GstBus + * @short_description: Asynchronous message bus subsystem + * @see_also: #GstMessage, #GstElement + * + * The #GstBus is an object responsible for delivering #GstMessage packets in + * a first-in first-out way from the streaming threads (see #GstTask) to the + * application. + * + * Since the application typically only wants to deal with delivery of these + * messages from one thread, the GstBus will marshall the messages between + * different threads. This is important since the actual streaming of media + * is done in another thread than the application. + * + * The GstBus provides support for #GSource based notifications. This makes it + * possible to handle the delivery in the glib mainloop. + * + * The #GSource callback function gst_bus_async_signal_func() can be used to + * convert all bus messages into signal emissions. + * + * A message is posted on the bus with the gst_bus_post() method. With the + * gst_bus_peek() and gst_bus_pop() methods one can look at or retrieve a + * previously posted message. + * + * The bus can be polled with the gst_bus_poll() method. This methods blocks + * up to the specified timeout value until one of the specified messages types + * is posted on the bus. The application can then gst_bus_pop() the messages + * from the bus to handle them. + * Alternatively the application can register an asynchronous bus function + * using gst_bus_add_watch_full() or gst_bus_add_watch(). This function will + * install a #GSource in the default glib main loop and will deliver messages + * a short while after they have been posted. Note that the main loop should + * be running for the asynchronous callbacks. + * + * It is also possible to get messages from the bus without any thread + * marshalling with the gst_bus_set_sync_handler() method. This makes it + * possible to react to a message in the same thread that posted the + * message on the bus. This should only be used if the application is able + * to deal with messages from different threads. + * + * Every #GstPipeline has one bus. + * + * Note that a #GstPipeline will set its bus into flushing state when changing + * from READY to NULL state. + */ + +#include "gst_private.h" +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "gstatomicqueue.h" +#include "gstinfo.h" +#include "gstpoll.h" + +#include "gstbus.h" +#include "glib-compat-private.h" + +#ifdef G_OS_WIN32 +# ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN /* This is just to placate gcc */ +# endif +#endif /* G_OS_WIN32 */ + +#define GST_CAT_DEFAULT GST_CAT_BUS +/* bus signals */ +enum +{ + SYNC_MESSAGE, + ASYNC_MESSAGE, + /* add more above */ + LAST_SIGNAL +}; + +#define DEFAULT_ENABLE_ASYNC (TRUE) + +enum +{ + PROP_0, + PROP_ENABLE_ASYNC +}; + +static void gst_bus_dispose (GObject * object); +static void gst_bus_finalize (GObject * object); + +static guint gst_bus_signals[LAST_SIGNAL] = { 0 }; + +struct _GstBusPrivate +{ + GstAtomicQueue *queue; + GMutex queue_lock; + + GstBusSyncHandler sync_handler; + gpointer sync_handler_data; + GDestroyNotify sync_handler_notify; + + guint num_signal_watchers; + + guint num_sync_message_emitters; + GSource *signal_watch; + + gboolean enable_async; + GstPoll *poll; + GPollFD pollfd; +}; + +#define gst_bus_parent_class parent_class +G_DEFINE_TYPE (GstBus, gst_bus, GST_TYPE_OBJECT); + +static void +gst_bus_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstBus *bus = GST_BUS_CAST (object); + + switch (prop_id) { + case PROP_ENABLE_ASYNC: + bus->priv->enable_async = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_bus_constructed (GObject * object) +{ + GstBus *bus = GST_BUS_CAST (object); + + if (bus->priv->enable_async) { + bus->priv->poll = gst_poll_new_timer (); + gst_poll_get_read_gpollfd (bus->priv->poll, &bus->priv->pollfd); + } + + G_OBJECT_CLASS (gst_bus_parent_class)->constructed (object); +} + +static void +gst_bus_class_init (GstBusClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gst_bus_dispose; + gobject_class->finalize = gst_bus_finalize; + gobject_class->set_property = gst_bus_set_property; + gobject_class->constructed = gst_bus_constructed; + + /** + * GstBus::enable-async: + * + * Enable async message delivery support for bus watches, + * gst_bus_pop() and similar API. Without this only the + * synchronous message handlers are called. + * + * This property is used to create the child element buses + * in #GstBin. + */ + g_object_class_install_property (gobject_class, PROP_ENABLE_ASYNC, + g_param_spec_boolean ("enable-async", "Enable Async", + "Enable async message delivery for bus watches and gst_bus_pop()", + DEFAULT_ENABLE_ASYNC, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBus::sync-message: + * @bus: the object which received the signal + * @message: the message that has been posted synchronously + * + * A message has been posted on the bus. This signal is emitted from the + * thread that posted the message so one has to be careful with locking. + * + * This signal will not be emitted by default, you have to call + * gst_bus_enable_sync_message_emission() before. + */ + gst_bus_signals[SYNC_MESSAGE] = + g_signal_new ("sync-message", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GstBusClass, sync_message), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_MESSAGE); + + /** + * GstBus::message: + * @bus: the object which received the signal + * @message: the message that has been posted asynchronously + * + * A message has been posted on the bus. This signal is emitted from a + * GSource added to the mainloop. this signal will only be emitted when + * there is a mainloop running. + */ + gst_bus_signals[ASYNC_MESSAGE] = + g_signal_new ("message", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_MESSAGE); + + g_type_class_add_private (klass, sizeof (GstBusPrivate)); +} + +static void +gst_bus_init (GstBus * bus) +{ + bus->priv = G_TYPE_INSTANCE_GET_PRIVATE (bus, GST_TYPE_BUS, GstBusPrivate); + bus->priv->enable_async = DEFAULT_ENABLE_ASYNC; + g_mutex_init (&bus->priv->queue_lock); + bus->priv->queue = gst_atomic_queue_new (32); + + GST_DEBUG_OBJECT (bus, "created"); +} + +static void +gst_bus_dispose (GObject * object) +{ + GstBus *bus = GST_BUS (object); + + if (bus->priv->queue) { + GstMessage *message; + + g_mutex_lock (&bus->priv->queue_lock); + do { + message = gst_atomic_queue_pop (bus->priv->queue); + if (message) + gst_message_unref (message); + } while (message != NULL); + gst_atomic_queue_unref (bus->priv->queue); + bus->priv->queue = NULL; + g_mutex_unlock (&bus->priv->queue_lock); + g_mutex_clear (&bus->priv->queue_lock); + + if (bus->priv->poll) + gst_poll_free (bus->priv->poll); + bus->priv->poll = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_bus_finalize (GObject * object) +{ + GstBus *bus = GST_BUS (object); + + if (bus->priv->sync_handler_notify) + bus->priv->sync_handler_notify (bus->priv->sync_handler_data); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_bus_new: + * + * Creates a new #GstBus instance. + * + * Returns: (transfer full): a new #GstBus instance + */ +GstBus * +gst_bus_new (void) +{ + GstBus *result; + + result = g_object_new (gst_bus_get_type (), NULL); + GST_DEBUG_OBJECT (result, "created new bus"); + + /* clear floating flag */ + gst_object_ref_sink (result); + + return result; +} + +/** + * gst_bus_post: + * @bus: a #GstBus to post on + * @message: (transfer full): the #GstMessage to post + * + * Post a message on the given bus. Ownership of the message + * is taken by the bus. + * + * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing. + * + * MT safe. + */ +gboolean +gst_bus_post (GstBus * bus, GstMessage * message) +{ + GstBusSyncReply reply = GST_BUS_PASS; + GstBusSyncHandler handler; + gboolean emit_sync_message; + gpointer handler_data; + + g_return_val_if_fail (GST_IS_BUS (bus), FALSE); + g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE); + + GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus %" GST_PTR_FORMAT, message, + message); + + /* check we didn't accidentally add a public flag that maps to same value */ + g_assert (!GST_MINI_OBJECT_FLAG_IS_SET (message, + GST_MESSAGE_FLAG_ASYNC_DELIVERY)); + + GST_OBJECT_LOCK (bus); + /* check if the bus is flushing */ + if (GST_OBJECT_FLAG_IS_SET (bus, GST_BUS_FLUSHING)) + goto is_flushing; + + handler = bus->priv->sync_handler; + handler_data = bus->priv->sync_handler_data; + emit_sync_message = bus->priv->num_sync_message_emitters > 0; + GST_OBJECT_UNLOCK (bus); + + /* first call the sync handler if it is installed */ + if (handler) + reply = handler (bus, message, handler_data); + + /* emit sync-message if requested to do so via + gst_bus_enable_sync_message_emission. terrible but effective */ + if (emit_sync_message && reply != GST_BUS_DROP + && handler != gst_bus_sync_signal_handler) + gst_bus_sync_signal_handler (bus, message, NULL); + + /* If this is a bus without async message delivery + * always drop the message */ + if (!bus->priv->poll) + reply = GST_BUS_DROP; + + /* now see what we should do with the message */ + switch (reply) { + case GST_BUS_DROP: + /* drop the message */ + GST_DEBUG_OBJECT (bus, "[msg %p] dropped", message); + break; + case GST_BUS_PASS: + /* pass the message to the async queue, refcount passed in the queue */ + GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message); + gst_atomic_queue_push (bus->priv->queue, message); + gst_poll_write_control (bus->priv->poll); + GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message); + + break; + case GST_BUS_ASYNC: + { + /* async delivery, we need a mutex and a cond to block + * on */ + GCond *cond = GST_MESSAGE_GET_COND (message); + GMutex *lock = GST_MESSAGE_GET_LOCK (message); + + g_cond_init (cond); + g_mutex_init (lock); + + GST_MINI_OBJECT_FLAG_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY); + + GST_DEBUG_OBJECT (bus, "[msg %p] waiting for async delivery", message); + + /* now we lock the message mutex, send the message to the async + * queue. When the message is handled by the app and destroyed, + * the cond will be signalled and we can continue */ + g_mutex_lock (lock); + + gst_atomic_queue_push (bus->priv->queue, message); + gst_poll_write_control (bus->priv->poll); + + /* now block till the message is freed */ + g_cond_wait (cond, lock); + + /* we acquired a new ref from gst_message_dispose() so we can clean up */ + g_mutex_unlock (lock); + + GST_DEBUG_OBJECT (bus, "[msg %p] delivered asynchronously", message); + + GST_MINI_OBJECT_FLAG_UNSET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY); + + g_mutex_clear (lock); + g_cond_clear (cond); + + gst_message_unref (message); + break; + } + default: + g_warning ("invalid return from bus sync handler"); + break; + } + return TRUE; + + /* ERRORS */ +is_flushing: + { + GST_DEBUG_OBJECT (bus, "bus is flushing"); + GST_OBJECT_UNLOCK (bus); + gst_message_unref (message); + + return FALSE; + } +} + +/** + * gst_bus_have_pending: + * @bus: a #GstBus to check + * + * Check if there are pending messages on the bus that + * should be handled. + * + * Returns: %TRUE if there are messages on the bus to be handled, %FALSE + * otherwise. + * + * MT safe. + */ +gboolean +gst_bus_have_pending (GstBus * bus) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BUS (bus), FALSE); + + /* see if there is a message on the bus */ + result = gst_atomic_queue_length (bus->priv->queue) != 0; + + return result; +} + +/** + * gst_bus_set_flushing: + * @bus: a #GstBus + * @flushing: whether or not to flush the bus + * + * If @flushing, flush out and unref any messages queued in the bus. Releases + * references to the message origin objects. Will flush future messages until + * gst_bus_set_flushing() sets @flushing to %FALSE. + * + * MT safe. + */ +void +gst_bus_set_flushing (GstBus * bus, gboolean flushing) +{ + GstMessage *message; + GList *message_list = NULL; + + g_return_if_fail (GST_IS_BUS (bus)); + + GST_OBJECT_LOCK (bus); + + if (flushing) { + GST_OBJECT_FLAG_SET (bus, GST_BUS_FLUSHING); + + GST_DEBUG_OBJECT (bus, "set bus flushing"); + + while ((message = gst_bus_pop (bus))) + message_list = g_list_prepend (message_list, message); + } else { + GST_DEBUG_OBJECT (bus, "unset bus flushing"); + GST_OBJECT_FLAG_UNSET (bus, GST_BUS_FLUSHING); + } + + GST_OBJECT_UNLOCK (bus); + + g_list_free_full (message_list, (GDestroyNotify) gst_message_unref); +} + +/** + * gst_bus_timed_pop_filtered: + * @bus: a #GstBus to pop from + * @timeout: a timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever + * @types: message types to take into account, GST_MESSAGE_ANY for any type + * + * Get a message from the bus whose type matches the message type mask @types, + * waiting up to the specified timeout (and discarding any messages that do not + * match the mask provided). + * + * If @timeout is 0, this function behaves like gst_bus_pop_filtered(). If + * @timeout is #GST_CLOCK_TIME_NONE, this function will block forever until a + * matching message was posted on the bus. + * + * Returns: (transfer full) (nullable): a #GstMessage matching the + * filter in @types, or %NULL if no matching message was found on + * the bus until the timeout expired. The message is taken from + * the bus and needs to be unreffed with gst_message_unref() after + * usage. + * + * MT safe. + */ +GstMessage * +gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, + GstMessageType types) +{ + GstMessage *message; + GTimeVal now, then; + gboolean first_round = TRUE; + GstClockTime elapsed = 0; + + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + g_return_val_if_fail (types != 0, NULL); + g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL); + + g_mutex_lock (&bus->priv->queue_lock); + + while (TRUE) { + gint ret; + + GST_LOG_OBJECT (bus, "have %d messages", + gst_atomic_queue_length (bus->priv->queue)); + + while ((message = gst_atomic_queue_pop (bus->priv->queue))) { + if (bus->priv->poll) { + while (!gst_poll_read_control (bus->priv->poll)) { + if (errno == EWOULDBLOCK) { + /* Retry, this can happen if pushing to the queue has finished, + * popping here succeeded but writing control did not finish + * before we got to this line. */ + /* Give other threads the chance to do something */ + g_thread_yield (); + continue; + } else { + /* This is a real error and means that either the bus is in an + * inconsistent state, or the GstPoll is invalid. GstPoll already + * prints a critical warning about this, no need to do that again + * ourselves */ + break; + } + } + } + + GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u", + message, GST_MESSAGE_TYPE_NAME (message), + GST_MESSAGE_SRC_NAME (message), (guint) types); + if ((GST_MESSAGE_TYPE (message) & types) != 0) { + /* Extra check to ensure extended types don't get matched unless + * asked for */ + if ((!GST_MESSAGE_TYPE_IS_EXTENDED (message)) + || (types & GST_MESSAGE_EXTENDED)) { + /* exit the loop, we have a message */ + goto beach; + } + } + + GST_DEBUG_OBJECT (bus, "discarding message, does not match mask"); + gst_message_unref (message); + message = NULL; + } + + /* no need to wait, exit loop */ + if (timeout == 0) + break; + + else if (timeout != GST_CLOCK_TIME_NONE) { + if (first_round) { + g_get_current_time (&then); + first_round = FALSE; + } else { + g_get_current_time (&now); + + elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then); + + if (elapsed > timeout) + break; + } + } + + /* only here in timeout case */ + g_assert (bus->priv->poll); + g_mutex_unlock (&bus->priv->queue_lock); + ret = gst_poll_wait (bus->priv->poll, timeout - elapsed); + g_mutex_lock (&bus->priv->queue_lock); + + if (ret == 0) { + GST_INFO_OBJECT (bus, "timed out, breaking loop"); + break; + } else { + GST_INFO_OBJECT (bus, "we got woken up, recheck for message"); + } + } + +beach: + + g_mutex_unlock (&bus->priv->queue_lock); + + return message; +} + + +/** + * gst_bus_timed_pop: + * @bus: a #GstBus to pop + * @timeout: a timeout + * + * Get a message from the bus, waiting up to the specified timeout. + * + * If @timeout is 0, this function behaves like gst_bus_pop(). If @timeout is + * #GST_CLOCK_TIME_NONE, this function will block forever until a message was + * posted on the bus. + * + * Returns: (transfer full) (nullable): the #GstMessage that is on the + * bus after the specified timeout or %NULL if the bus is empty + * after the timeout expired. The message is taken from the bus + * and needs to be unreffed with gst_message_unref() after usage. + * + * MT safe. + */ +GstMessage * +gst_bus_timed_pop (GstBus * bus, GstClockTime timeout) +{ + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + + return gst_bus_timed_pop_filtered (bus, timeout, GST_MESSAGE_ANY); +} + +/** + * gst_bus_pop_filtered: + * @bus: a #GstBus to pop + * @types: message types to take into account + * + * Get a message matching @type from the bus. Will discard all messages on + * the bus that do not match @type and that have been posted before the first + * message that does match @type. If there is no message matching @type on + * the bus, all messages will be discarded. It is not possible to use message + * enums beyond #GST_MESSAGE_EXTENDED in the @events mask. + * + * Returns: (transfer full) (nullable): the next #GstMessage matching + * @type that is on the bus, or %NULL if the bus is empty or there + * is no message matching @type. The message is taken from the bus + * and needs to be unreffed with gst_message_unref() after usage. + * + * MT safe. + */ +GstMessage * +gst_bus_pop_filtered (GstBus * bus, GstMessageType types) +{ + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + g_return_val_if_fail (types != 0, NULL); + + return gst_bus_timed_pop_filtered (bus, 0, types); +} + +/** + * gst_bus_pop: + * @bus: a #GstBus to pop + * + * Get a message from the bus. + * + * Returns: (transfer full) (nullable): the #GstMessage that is on the + * bus, or %NULL if the bus is empty. The message is taken from + * the bus and needs to be unreffed with gst_message_unref() after + * usage. + * + * MT safe. + */ +GstMessage * +gst_bus_pop (GstBus * bus) +{ + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + + return gst_bus_timed_pop_filtered (bus, 0, GST_MESSAGE_ANY); +} + +/** + * gst_bus_peek: + * @bus: a #GstBus + * + * Peek the message on the top of the bus' queue. The message will remain + * on the bus' message queue. A reference is returned, and needs to be unreffed + * by the caller. + * + * Returns: (transfer full) (nullable): the #GstMessage that is on the + * bus, or %NULL if the bus is empty. + * + * MT safe. + */ +GstMessage * +gst_bus_peek (GstBus * bus) +{ + GstMessage *message; + + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + + g_mutex_lock (&bus->priv->queue_lock); + message = gst_atomic_queue_peek (bus->priv->queue); + if (message) + gst_message_ref (message); + g_mutex_unlock (&bus->priv->queue_lock); + + GST_DEBUG_OBJECT (bus, "peek on bus, got message %p", message); + + return message; +} + +/** + * gst_bus_set_sync_handler: + * @bus: a #GstBus to install the handler on + * @func: (allow-none): The handler function to install + * @user_data: User data that will be sent to the handler function. + * @notify: called when @user_data becomes unused + * + * Sets the synchronous handler on the bus. The function will be called + * every time a new message is posted on the bus. Note that the function + * will be called in the same thread context as the posting object. This + * function is usually only called by the creator of the bus. Applications + * should handle messages asynchronously using the gst_bus watch and poll + * functions. + * + * You cannot replace an existing sync_handler. You can pass %NULL to this + * function, which will clear the existing handler. + */ +void +gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func, + gpointer user_data, GDestroyNotify notify) +{ + GDestroyNotify old_notify; + + g_return_if_fail (GST_IS_BUS (bus)); + + GST_OBJECT_LOCK (bus); + /* Assert if the user attempts to replace an existing sync_handler, + * other than to clear it */ + if (func != NULL && bus->priv->sync_handler != NULL) + goto no_replace; + + if ((old_notify = bus->priv->sync_handler_notify)) { + gpointer old_data = bus->priv->sync_handler_data; + + bus->priv->sync_handler_data = NULL; + bus->priv->sync_handler_notify = NULL; + GST_OBJECT_UNLOCK (bus); + + old_notify (old_data); + + GST_OBJECT_LOCK (bus); + } + bus->priv->sync_handler = func; + bus->priv->sync_handler_data = user_data; + bus->priv->sync_handler_notify = notify; + GST_OBJECT_UNLOCK (bus); + + return; + +no_replace: + { + GST_OBJECT_UNLOCK (bus); + g_warning ("cannot replace existing sync handler"); + return; + } +} + +/** + * gst_bus_get_pollfd: + * @bus: A #GstBus + * @fd: A GPollFD to fill + * + * Gets the file descriptor from the bus which can be used to get notified about + * messages being available with functions like g_poll(), and allows integration + * into other event loops based on file descriptors. + * Whenever a message is available, the POLLIN / %G_IO_IN event is set. + * + * Warning: NEVER read or write anything to the returned fd but only use it + * for getting notifications via g_poll() or similar and then use the normal + * GstBus API, e.g. gst_bus_pop(). + * + * Since: 1.14 + */ +void +gst_bus_get_pollfd (GstBus * bus, GPollFD * fd) +{ + g_return_if_fail (GST_IS_BUS (bus)); + g_return_if_fail (bus->priv->poll != NULL); + + *fd = bus->priv->pollfd; +} + +/* GSource for the bus + */ +typedef struct +{ + GSource source; + GstBus *bus; +} GstBusSource; + +static gboolean +gst_bus_source_prepare (GSource * source, gint * timeout) +{ + *timeout = -1; + return FALSE; +} + +static gboolean +gst_bus_source_check (GSource * source) +{ + GstBusSource *bsrc = (GstBusSource *) source; + + return bsrc->bus->priv->pollfd.revents & (G_IO_IN | G_IO_HUP | G_IO_ERR); +} + +static gboolean +gst_bus_source_dispatch (GSource * source, GSourceFunc callback, + gpointer user_data) +{ + GstBusFunc handler = (GstBusFunc) callback; + GstBusSource *bsource = (GstBusSource *) source; + GstMessage *message; + gboolean keep; + GstBus *bus; + + g_return_val_if_fail (bsource != NULL, FALSE); + + bus = bsource->bus; + + g_return_val_if_fail (GST_IS_BUS (bus), FALSE); + + message = gst_bus_pop (bus); + + /* The message queue might be empty if some other thread or callback set + * the bus to flushing between check/prepare and dispatch */ + if (G_UNLIKELY (message == NULL)) + return TRUE; + + if (!handler) + goto no_handler; + + GST_DEBUG_OBJECT (bus, "source %p calling dispatch with %" GST_PTR_FORMAT, + source, message); + + keep = handler (bus, message, user_data); + gst_message_unref (message); + + GST_DEBUG_OBJECT (bus, "source %p handler returns %d", source, keep); + + return keep; + +no_handler: + { + g_warning ("GstBus watch dispatched without callback\n" + "You must call g_source_set_callback()."); + gst_message_unref (message); + return FALSE; + } +} + +static void +gst_bus_source_finalize (GSource * source) +{ + GstBusSource *bsource = (GstBusSource *) source; + GstBus *bus; + + bus = bsource->bus; + + GST_DEBUG_OBJECT (bus, "finalize source %p", source); + + GST_OBJECT_LOCK (bus); + if (bus->priv->signal_watch == source) + bus->priv->signal_watch = NULL; + GST_OBJECT_UNLOCK (bus); + + gst_object_unref (bsource->bus); + bsource->bus = NULL; +} + +static GSourceFuncs gst_bus_source_funcs = { + gst_bus_source_prepare, + gst_bus_source_check, + gst_bus_source_dispatch, + gst_bus_source_finalize +}; + +/** + * gst_bus_create_watch: + * @bus: a #GstBus to create the watch for + * + * Create watch for this bus. The GSource will be dispatched whenever + * a message is on the bus. After the GSource is dispatched, the + * message is popped off the bus and unreffed. + * + * Returns: (transfer full) (nullable): a #GSource that can be added to a mainloop. + */ +GSource * +gst_bus_create_watch (GstBus * bus) +{ + GstBusSource *source; + + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + g_return_val_if_fail (bus->priv->poll != NULL, NULL); + + source = (GstBusSource *) g_source_new (&gst_bus_source_funcs, + sizeof (GstBusSource)); + + g_source_set_name ((GSource *) source, "GStreamer message bus watch"); + + source->bus = gst_object_ref (bus); + g_source_add_poll ((GSource *) source, &bus->priv->pollfd); + + return (GSource *) source; +} + +/* must be called with the bus OBJECT LOCK */ +static guint +gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority, + GstBusFunc func, gpointer user_data, GDestroyNotify notify) +{ + GMainContext *ctx; + guint id; + GSource *source; + + if (bus->priv->signal_watch) { + GST_ERROR_OBJECT (bus, + "Tried to add new watch while one was already there"); + return 0; + } + + source = gst_bus_create_watch (bus); + if (!source) { + g_critical ("Creating bus watch failed"); + return 0; + } + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + + g_source_set_callback (source, (GSourceFunc) func, user_data, notify); + + ctx = g_main_context_get_thread_default (); + id = g_source_attach (source, ctx); + g_source_unref (source); + + if (id) { + bus->priv->signal_watch = source; + } + + GST_DEBUG_OBJECT (bus, "New source %p with id %u", source, id); + return id; +} + +/** + * gst_bus_add_watch_full: (rename-to gst_bus_add_watch) + * @bus: a #GstBus to create the watch for. + * @priority: The priority of the watch. + * @func: A function to call when a message is received. + * @user_data: user data passed to @func. + * @notify: the function to call when the source is removed. + * + * Adds a bus watch to the default main context with the given @priority (e.g. + * %G_PRIORITY_DEFAULT). It is also possible to use a non-default main + * context set up using g_main_context_push_thread_default() (before + * one had to create a bus watch source and attach it to the desired main + * context 'manually'). + * + * This function is used to receive asynchronous messages in the main loop. + * There can only be a single bus watch per bus, you must remove it before you + * can set a new one. + * + * The bus watch will only work if a GLib main loop is being run. + * + * When @func is called, the message belongs to the caller; if you want to + * keep a copy of it, call gst_message_ref() before leaving @func. + * + * The watch can be removed using gst_bus_remove_watch() or by returning %FALSE + * from @func. If the watch was added to the default main context it is also + * possible to remove the watch using g_source_remove(). + * + * The bus watch will take its own reference to the @bus, so it is safe to unref + * @bus using gst_object_unref() after setting the bus watch. + * + * MT safe. + * + * Returns: The event source id or 0 if @bus already got an event source. + */ +guint +gst_bus_add_watch_full (GstBus * bus, gint priority, + GstBusFunc func, gpointer user_data, GDestroyNotify notify) +{ + guint id; + + g_return_val_if_fail (GST_IS_BUS (bus), 0); + + GST_OBJECT_LOCK (bus); + id = gst_bus_add_watch_full_unlocked (bus, priority, func, user_data, notify); + GST_OBJECT_UNLOCK (bus); + + return id; +} + +/** + * gst_bus_add_watch: (skip) + * @bus: a #GstBus to create the watch for + * @func: A function to call when a message is received. + * @user_data: user data passed to @func. + * + * Adds a bus watch to the default main context with the default priority + * (%G_PRIORITY_DEFAULT). It is also possible to use a non-default main + * context set up using g_main_context_push_thread_default() (before + * one had to create a bus watch source and attach it to the desired main + * context 'manually'). + * + * This function is used to receive asynchronous messages in the main loop. + * There can only be a single bus watch per bus, you must remove it before you + * can set a new one. + * + * The bus watch will only work if a GLib main loop is being run. + * + * The watch can be removed using gst_bus_remove_watch() or by returning %FALSE + * from @func. If the watch was added to the default main context it is also + * possible to remove the watch using g_source_remove(). + * + * The bus watch will take its own reference to the @bus, so it is safe to unref + * @bus using gst_object_unref() after setting the bus watch. + * + * MT safe. + * + * Returns: The event source id or 0 if @bus already got an event source. + */ +guint +gst_bus_add_watch (GstBus * bus, GstBusFunc func, gpointer user_data) +{ + return gst_bus_add_watch_full (bus, G_PRIORITY_DEFAULT, func, + user_data, NULL); +} + +/** + * gst_bus_remove_watch: + * @bus: a #GstBus to remove the watch from. + * + * Removes an installed bus watch from @bus. + * + * Returns: %TRUE on success or %FALSE if @bus has no event source. + * + * Since: 1.6 + * + */ +gboolean +gst_bus_remove_watch (GstBus * bus) +{ + GSource *watch_id; + + g_return_val_if_fail (GST_IS_BUS (bus), FALSE); + + GST_OBJECT_LOCK (bus); + + if (bus->priv->signal_watch == NULL) { + GST_ERROR_OBJECT (bus, "no bus watch was present"); + goto no_watch; + } + + watch_id = bus->priv->signal_watch; + + GST_OBJECT_UNLOCK (bus); + + g_source_destroy (watch_id); + + return TRUE; + +no_watch: + GST_OBJECT_UNLOCK (bus); + + return FALSE; +} + +typedef struct +{ + GMainLoop *loop; + guint timeout_id; + gboolean source_running; + GstMessageType events; + GstMessage *message; +} GstBusPollData; + +static void +poll_func (GstBus * bus, GstMessage * message, GstBusPollData * poll_data) +{ + GstMessageType type; + + if (!g_main_loop_is_running (poll_data->loop)) { + GST_DEBUG ("mainloop %p not running", poll_data->loop); + return; + } + + type = GST_MESSAGE_TYPE (message); + + if (type & poll_data->events) { + g_assert (poll_data->message == NULL); + /* keep ref to message */ + poll_data->message = gst_message_ref (message); + GST_DEBUG ("mainloop %p quit", poll_data->loop); + g_main_loop_quit (poll_data->loop); + } else { + GST_DEBUG ("type %08x does not match %08x", type, poll_data->events); + } +} + +static gboolean +poll_timeout (GstBusPollData * poll_data) +{ + GST_DEBUG ("mainloop %p quit", poll_data->loop); + g_main_loop_quit (poll_data->loop); + + /* we don't remove the GSource as this would free our poll_data, + * which we still need */ + return TRUE; +} + +static void +poll_destroy (GstBusPollData * poll_data, gpointer unused) +{ + poll_data->source_running = FALSE; + if (!poll_data->timeout_id) { + g_main_loop_unref (poll_data->loop); + g_slice_free (GstBusPollData, poll_data); + } +} + +static void +poll_destroy_timeout (GstBusPollData * poll_data) +{ + poll_data->timeout_id = 0; + if (!poll_data->source_running) { + g_main_loop_unref (poll_data->loop); + g_slice_free (GstBusPollData, poll_data); + } +} + +/** + * gst_bus_poll: + * @bus: a #GstBus + * @events: a mask of #GstMessageType, representing the set of message types to + * poll for (note special handling of extended message types below) + * @timeout: the poll timeout, as a #GstClockTime, or #GST_CLOCK_TIME_NONE to poll + * indefinitely. + * + * Poll the bus for messages. Will block while waiting for messages to come. + * You can specify a maximum time to poll with the @timeout parameter. If + * @timeout is negative, this function will block indefinitely. + * + * All messages not in @events will be popped off the bus and will be ignored. + * It is not possible to use message enums beyond #GST_MESSAGE_EXTENDED in the + * @events mask + * + * Because poll is implemented using the "message" signal enabled by + * gst_bus_add_signal_watch(), calling gst_bus_poll() will cause the "message" + * signal to be emitted for every message that poll sees. Thus a "message" + * signal handler will see the same messages that this function sees -- neither + * will steal messages from the other. + * + * This function will run a main loop from the default main context when + * polling. + * + * You should never use this function, since it is pure evil. This is + * especially true for GUI applications based on Gtk+ or Qt, but also for any + * other non-trivial application that uses the GLib main loop. As this function + * runs a GLib main loop, any callback attached to the default GLib main + * context may be invoked. This could be timeouts, GUI events, I/O events etc.; + * even if gst_bus_poll() is called with a 0 timeout. Any of these callbacks + * may do things you do not expect, e.g. destroy the main application window or + * some other resource; change other application state; display a dialog and + * run another main loop until the user clicks it away. In short, using this + * function may add a lot of complexity to your code through unexpected + * re-entrancy and unexpected changes to your application's state. + * + * For 0 timeouts use gst_bus_pop_filtered() instead of this function; for + * other short timeouts use gst_bus_timed_pop_filtered(); everything else is + * better handled by setting up an asynchronous bus watch and doing things + * from there. + * + * Returns: (transfer full) (nullable): the message that was received, + * or %NULL if the poll timed out. The message is taken from the + * bus and needs to be unreffed with gst_message_unref() after + * usage. + */ +GstMessage * +gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTime timeout) +{ + GstBusPollData *poll_data; + GstMessage *ret; + gulong id; + + g_return_val_if_fail (GST_IS_BUS (bus), NULL); + + poll_data = g_slice_new (GstBusPollData); + poll_data->source_running = TRUE; + poll_data->loop = g_main_loop_new (NULL, FALSE); + poll_data->events = events; + poll_data->message = NULL; + + if (timeout != GST_CLOCK_TIME_NONE) + poll_data->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, + timeout / GST_MSECOND, (GSourceFunc) poll_timeout, poll_data, + (GDestroyNotify) poll_destroy_timeout); + else + poll_data->timeout_id = 0; + + id = g_signal_connect_data (bus, "message", G_CALLBACK (poll_func), poll_data, + (GClosureNotify) poll_destroy, 0); + + /* these can be nested, so it's ok */ + gst_bus_add_signal_watch (bus); + + GST_DEBUG ("running mainloop %p", poll_data->loop); + g_main_loop_run (poll_data->loop); + GST_DEBUG ("mainloop stopped %p", poll_data->loop); + + gst_bus_remove_signal_watch (bus); + + /* holds a ref */ + ret = poll_data->message; + + if (poll_data->timeout_id) + g_source_remove (poll_data->timeout_id); + + /* poll_data will be freed now */ + g_signal_handler_disconnect (bus, id); + + GST_DEBUG_OBJECT (bus, "finished poll with message %p", ret); + + return ret; +} + +/** + * gst_bus_async_signal_func: + * @bus: a #GstBus + * @message: the #GstMessage received + * @data: user data + * + * A helper #GstBusFunc that can be used to convert all asynchronous messages + * into signals. + * + * Returns: %TRUE + */ +gboolean +gst_bus_async_signal_func (GstBus * bus, GstMessage * message, gpointer data) +{ + GQuark detail = 0; + + g_return_val_if_fail (GST_IS_BUS (bus), TRUE); + g_return_val_if_fail (message != NULL, TRUE); + + detail = gst_message_type_to_quark (GST_MESSAGE_TYPE (message)); + + g_signal_emit (bus, gst_bus_signals[ASYNC_MESSAGE], detail, message); + + /* we never remove this source based on signal emission return values */ + return TRUE; +} + +/** + * gst_bus_sync_signal_handler: + * @bus: a #GstBus + * @message: the #GstMessage received + * @data: user data + * + * A helper GstBusSyncHandler that can be used to convert all synchronous + * messages into signals. + * + * Returns: GST_BUS_PASS + */ +GstBusSyncReply +gst_bus_sync_signal_handler (GstBus * bus, GstMessage * message, gpointer data) +{ + GQuark detail = 0; + + g_return_val_if_fail (GST_IS_BUS (bus), GST_BUS_DROP); + g_return_val_if_fail (message != NULL, GST_BUS_DROP); + + detail = gst_message_type_to_quark (GST_MESSAGE_TYPE (message)); + + g_signal_emit (bus, gst_bus_signals[SYNC_MESSAGE], detail, message); + + return GST_BUS_PASS; +} + +/** + * gst_bus_enable_sync_message_emission: + * @bus: a #GstBus on which you want to receive the "sync-message" signal + * + * Instructs GStreamer to emit the "sync-message" signal after running the bus's + * sync handler. This function is here so that code can ensure that they can + * synchronously receive messages without having to affect what the bin's sync + * handler is. + * + * This function may be called multiple times. To clean up, the caller is + * responsible for calling gst_bus_disable_sync_message_emission() as many times + * as this function is called. + * + * While this function looks similar to gst_bus_add_signal_watch(), it is not + * exactly the same -- this function enables synchronous emission of + * signals when messages arrive; gst_bus_add_signal_watch() adds an idle callback + * to pop messages off the bus asynchronously. The sync-message signal + * comes from the thread of whatever object posted the message; the "message" + * signal is marshalled to the main thread via the main loop. + * + * MT safe. + */ +void +gst_bus_enable_sync_message_emission (GstBus * bus) +{ + g_return_if_fail (GST_IS_BUS (bus)); + + GST_OBJECT_LOCK (bus); + bus->priv->num_sync_message_emitters++; + GST_OBJECT_UNLOCK (bus); +} + +/** + * gst_bus_disable_sync_message_emission: + * @bus: a #GstBus on which you previously called + * gst_bus_enable_sync_message_emission() + * + * Instructs GStreamer to stop emitting the "sync-message" signal for this bus. + * See gst_bus_enable_sync_message_emission() for more information. + * + * In the event that multiple pieces of code have called + * gst_bus_enable_sync_message_emission(), the sync-message emissions will only + * be stopped after all calls to gst_bus_enable_sync_message_emission() were + * "cancelled" by calling this function. In this way the semantics are exactly + * the same as gst_object_ref() that which calls enable should also call + * disable. + * + * MT safe. + */ +void +gst_bus_disable_sync_message_emission (GstBus * bus) +{ + g_return_if_fail (GST_IS_BUS (bus)); + g_return_if_fail (bus->priv->num_sync_message_emitters > 0); + + GST_OBJECT_LOCK (bus); + bus->priv->num_sync_message_emitters--; + GST_OBJECT_UNLOCK (bus); +} + +/** + * gst_bus_add_signal_watch_full: + * @bus: a #GstBus on which you want to receive the "message" signal + * @priority: The priority of the watch. + * + * Adds a bus signal watch to the default main context with the given @priority + * (e.g. %G_PRIORITY_DEFAULT). It is also possible to use a non-default main + * context set up using g_main_context_push_thread_default() + * (before one had to create a bus watch source and attach it to the desired + * main context 'manually'). + * + * After calling this statement, the bus will emit the "message" signal for each + * message posted on the bus when the main loop is running. + * + * This function may be called multiple times. To clean up, the caller is + * responsible for calling gst_bus_remove_signal_watch() as many times as this + * function is called. + * + * There can only be a single bus watch per bus, you must remove any signal + * watch before you can set another type of watch. + * + * MT safe. + */ +void +gst_bus_add_signal_watch_full (GstBus * bus, gint priority) +{ + g_return_if_fail (GST_IS_BUS (bus)); + + /* I know the callees don't take this lock, so go ahead and abuse it */ + GST_OBJECT_LOCK (bus); + + if (bus->priv->num_signal_watchers > 0) + goto done; + + /* this should not fail because the counter above takes care of it */ + g_assert (!bus->priv->signal_watch); + + gst_bus_add_watch_full_unlocked (bus, priority, gst_bus_async_signal_func, + NULL, NULL); + + if (G_UNLIKELY (!bus->priv->signal_watch)) + goto add_failed; + +done: + + bus->priv->num_signal_watchers++; + + GST_OBJECT_UNLOCK (bus); + return; + + /* ERRORS */ +add_failed: + { + g_critical ("Could not add signal watch to bus %s", GST_OBJECT_NAME (bus)); + GST_OBJECT_UNLOCK (bus); + return; + } +} + +/** + * gst_bus_add_signal_watch: + * @bus: a #GstBus on which you want to receive the "message" signal + * + * Adds a bus signal watch to the default main context with the default priority + * (%G_PRIORITY_DEFAULT). It is also possible to use a non-default + * main context set up using g_main_context_push_thread_default() (before + * one had to create a bus watch source and attach it to the desired main + * context 'manually'). + * + * After calling this statement, the bus will emit the "message" signal for each + * message posted on the bus. + * + * This function may be called multiple times. To clean up, the caller is + * responsible for calling gst_bus_remove_signal_watch() as many times as this + * function is called. + * + * MT safe. + */ +void +gst_bus_add_signal_watch (GstBus * bus) +{ + gst_bus_add_signal_watch_full (bus, G_PRIORITY_DEFAULT); +} + +/** + * gst_bus_remove_signal_watch: + * @bus: a #GstBus you previously added a signal watch to + * + * Removes a signal watch previously added with gst_bus_add_signal_watch(). + * + * MT safe. + */ +void +gst_bus_remove_signal_watch (GstBus * bus) +{ + GSource *source = NULL; + + g_return_if_fail (GST_IS_BUS (bus)); + + /* I know the callees don't take this lock, so go ahead and abuse it */ + GST_OBJECT_LOCK (bus); + + if (bus->priv->num_signal_watchers == 0) + goto error; + + bus->priv->num_signal_watchers--; + + if (bus->priv->num_signal_watchers > 0) + goto done; + + GST_DEBUG_OBJECT (bus, "removing signal watch %u", + g_source_get_id (bus->priv->signal_watch)); + + source = bus->priv->signal_watch; + +done: + GST_OBJECT_UNLOCK (bus); + + if (source) + g_source_destroy (source); + + return; + + /* ERRORS */ +error: + { + g_critical ("Bus %s has no signal watches attached", GST_OBJECT_NAME (bus)); + GST_OBJECT_UNLOCK (bus); + return; + } +} diff --git a/gst/gstbus.h b/gst/gstbus.h new file mode 100644 index 0000000..1f14246 --- /dev/null +++ b/gst/gstbus.h @@ -0,0 +1,232 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstbus.h: Header for GstBus subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BUS_H__ +#define __GST_BUS_H__ + +typedef struct _GstBus GstBus; +typedef struct _GstBusPrivate GstBusPrivate; +typedef struct _GstBusClass GstBusClass; + +#include +#include + +G_BEGIN_DECLS + +/* --- standard type macros --- */ +#define GST_TYPE_BUS (gst_bus_get_type ()) +#define GST_BUS(bus) (G_TYPE_CHECK_INSTANCE_CAST ((bus), GST_TYPE_BUS, GstBus)) +#define GST_IS_BUS(bus) (G_TYPE_CHECK_INSTANCE_TYPE ((bus), GST_TYPE_BUS)) +#define GST_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_CAST ((bclass), GST_TYPE_BUS, GstBusClass)) +#define GST_IS_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_TYPE ((bclass), GST_TYPE_BUS)) +#define GST_BUS_GET_CLASS(bus) (G_TYPE_INSTANCE_GET_CLASS ((bus), GST_TYPE_BUS, GstBusClass)) +#define GST_BUS_CAST(bus) ((GstBus*)(bus)) + +/** + * GstBusFlags: + * @GST_BUS_FLUSHING: The bus is currently dropping all messages + * @GST_BUS_FLAG_LAST: offset to define more flags + * + * The standard flags that a bus may have. + */ +typedef enum { + GST_BUS_FLUSHING = (GST_OBJECT_FLAG_LAST << 0), + /* padding */ + GST_BUS_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 1) +} GstBusFlags; + +/** + * GstBusSyncReply: + * @GST_BUS_DROP: drop the message + * @GST_BUS_PASS: pass the message to the async queue + * @GST_BUS_ASYNC: pass message to async queue, continue if message is handled + * + * The result values for a GstBusSyncHandler. + */ +typedef enum +{ + GST_BUS_DROP = 0, + GST_BUS_PASS = 1, + GST_BUS_ASYNC = 2 +} GstBusSyncReply; + +/** + * GstBusSyncHandler: + * @bus: the #GstBus that sent the message + * @message: the #GstMessage + * @user_data: user data that has been given, when registering the handler + * + * Handler will be invoked synchronously, when a new message has been injected + * into the bus. This function is mostly used internally. Only one sync handler + * can be attached to a given bus. + * + * If the handler returns GST_BUS_DROP, it should unref the message, else the + * message should not be unreffed by the sync handler. + * + * Returns: #GstBusSyncReply stating what to do with the message + */ +typedef GstBusSyncReply (*GstBusSyncHandler) (GstBus * bus, GstMessage * message, gpointer user_data); + +/** + * GstBusFunc: + * @bus: the #GstBus that sent the message + * @message: the #GstMessage + * @user_data: user data that has been given, when registering the handler + * + * Specifies the type of function passed to gst_bus_add_watch() or + * gst_bus_add_watch_full(), which is called from the mainloop when a message + * is available on the bus. + * + * The message passed to the function will be unreffed after execution of this + * function so it should not be freed in the function. + * + * Note that this function is used as a GSourceFunc which means that returning + * %FALSE will remove the GSource from the mainloop. + * + * Returns: %FALSE if the event source should be removed. + */ +typedef gboolean (*GstBusFunc) (GstBus * bus, GstMessage * message, gpointer user_data); + +/** + * GstBus: + * + * The opaque #GstBus data structure. + */ +struct _GstBus +{ + GstObject object; + + /*< private >*/ + GstBusPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstBusClass +{ + GstObjectClass parent_class; + + /* signals */ + void (*message) (GstBus *bus, GstMessage *message); + void (*sync_message) (GstBus *bus, GstMessage *message); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_bus_get_type (void); + +GST_API +GstBus* gst_bus_new (void); + +GST_API +gboolean gst_bus_post (GstBus * bus, GstMessage * message); + +GST_API +gboolean gst_bus_have_pending (GstBus * bus); + +GST_API +GstMessage * gst_bus_peek (GstBus * bus); + +GST_API +GstMessage * gst_bus_pop (GstBus * bus); + +GST_API +GstMessage * gst_bus_pop_filtered (GstBus * bus, GstMessageType types); + +GST_API +GstMessage * gst_bus_timed_pop (GstBus * bus, GstClockTime timeout); + +GST_API +GstMessage * gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, GstMessageType types); + +GST_API +void gst_bus_set_flushing (GstBus * bus, gboolean flushing); + +/* synchronous dispatching */ + +GST_API +void gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func, + gpointer user_data, GDestroyNotify notify); + +/* asynchronous message notifications */ + +GST_API +void gst_bus_get_pollfd (GstBus * bus, GPollFD *fd); + +/* GSource based dispatching */ + +GST_API +GSource * gst_bus_create_watch (GstBus * bus); + +GST_API +guint gst_bus_add_watch_full (GstBus * bus, + gint priority, + GstBusFunc func, + gpointer user_data, + GDestroyNotify notify); +GST_API +guint gst_bus_add_watch (GstBus * bus, + GstBusFunc func, + gpointer user_data); +GST_API +gboolean gst_bus_remove_watch (GstBus * bus); + +/* polling the bus */ + +GST_API +GstMessage* gst_bus_poll (GstBus *bus, GstMessageType events, + GstClockTime timeout); + +/* signal based dispatching helper functions. */ + +GST_API +gboolean gst_bus_async_signal_func (GstBus *bus, GstMessage *message, + gpointer data); +GST_API +GstBusSyncReply gst_bus_sync_signal_handler (GstBus *bus, GstMessage *message, + gpointer data); + +/* convenience api to add/remove a gsource that emits the async signals */ + +GST_API +void gst_bus_add_signal_watch (GstBus * bus); + +GST_API +void gst_bus_add_signal_watch_full (GstBus * bus, gint priority); + +GST_API +void gst_bus_remove_signal_watch (GstBus * bus); + +GST_API +void gst_bus_enable_sync_message_emission (GstBus * bus); + +GST_API +void gst_bus_disable_sync_message_emission (GstBus * bus); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBus, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BUS_H__ */ diff --git a/gst/gstcaps.c b/gst/gstcaps.c new file mode 100644 index 0000000..d660e52 --- /dev/null +++ b/gst/gstcaps.c @@ -0,0 +1,2542 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcaps + * @title: GstCaps + * @short_description: Structure describing sets of media formats + * @see_also: #GstStructure, #GstMiniObject + * + * Caps (capabilities) are lightweight refcounted objects describing media types. + * They are composed of an array of #GstStructure. + * + * Caps are exposed on #GstPadTemplate to describe all possible types a + * given pad can handle. They are also stored in the #GstRegistry along with + * a description of the #GstElement. + * + * Caps are exposed on the element pads using the gst_pad_query_caps() pad + * function. This function describes the possible types that the pad can + * handle or produce at runtime. + * + * A #GstCaps can be constructed with the following code fragment: + * |[ + * GstCaps *caps = gst_caps_new_simple ("video/x-raw", + * "format", G_TYPE_STRING, "I420", + * "framerate", GST_TYPE_FRACTION, 25, 1, + * "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + * "width", G_TYPE_INT, 320, + * "height", G_TYPE_INT, 240, + * NULL); + * ]| + * + * A #GstCaps is fixed when it has no properties with ranges or lists. Use + * gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a + * caps event to notify downstream elements of the current media type. + * + * Various methods exist to work with the media types such as subtracting + * or intersecting. + * + * Be aware that the current #GstCaps / #GstStructure serialization into string + * has limited support for nested #GstCaps / #GstStructure fields. It can only + * support one level of nesting. Using more levels will lead to unexpected + * behavior when using serialization features, such as gst_caps_to_string() or + * gst_value_serialize() and their counterparts. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "gst_private.h" +#include +#include + +#define DEBUG_REFCOUNT + +typedef struct _GstCapsArrayElement +{ + GstStructure *structure; + GstCapsFeatures *features; +} GstCapsArrayElement; + +typedef struct _GstCapsImpl +{ + GstCaps caps; + + GArray *array; +} GstCapsImpl; + +#define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array) + +#define GST_CAPS_LEN(c) (GST_CAPS_ARRAY(c)->len) + +#define IS_WRITABLE(caps) \ + (GST_CAPS_REFCOUNT_VALUE (caps) == 1) + +/* same as gst_caps_is_any () */ +#define CAPS_IS_ANY(caps) \ + (!!(GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY)) + +/* same as gst_caps_is_empty () */ +#define CAPS_IS_EMPTY(caps) \ + (!CAPS_IS_ANY(caps) && CAPS_IS_EMPTY_SIMPLE(caps)) + +#define CAPS_IS_EMPTY_SIMPLE(caps) \ + ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0)) + +#define gst_caps_features_copy_conditional(f) ((f && (gst_caps_features_is_any (f) || !gst_caps_features_is_equal (f, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) ? gst_caps_features_copy (f) : NULL) + +/* quick way to get a caps structure at an index without doing a type or array + * length check */ +#define gst_caps_get_structure_unchecked(caps, index) \ + (g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).structure) +#define gst_caps_get_features_storage_unchecked(caps, index) \ + (&g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).features) +#define gst_caps_get_features_unchecked(caps, index) \ + (g_atomic_pointer_get (gst_caps_get_features_storage_unchecked (caps, index))) +/* quick way to append a structure without checking the args */ +#define gst_caps_append_structure_unchecked(caps, s, f) G_STMT_START{\ + GstCapsArrayElement __e={s, f}; \ + if (gst_structure_set_parent_refcount (__e.structure, &GST_MINI_OBJECT_REFCOUNT(caps)) && \ + (!__e.features || gst_caps_features_set_parent_refcount (__e.features, &GST_MINI_OBJECT_REFCOUNT(caps)))) \ + g_array_append_val (GST_CAPS_ARRAY (caps), __e); \ +}G_STMT_END + +/* lock to protect multiple invocations of static caps to caps conversion */ +G_LOCK_DEFINE_STATIC (static_caps_lock); + +static void gst_caps_transform_to_string (const GValue * src_value, + GValue * dest_value); +static gboolean gst_caps_from_string_inplace (GstCaps * caps, + const gchar * string); + +GType _gst_caps_type = 0; +GstCaps *_gst_caps_any; +GstCaps *_gst_caps_none; + +GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps); + +void +_priv_gst_caps_initialize (void) +{ + _gst_caps_type = gst_caps_get_type (); + + _gst_caps_any = gst_caps_new_any (); + _gst_caps_none = gst_caps_new_empty (); + + g_value_register_transform_func (_gst_caps_type, + G_TYPE_STRING, gst_caps_transform_to_string); +} + +void +_priv_gst_caps_cleanup (void) +{ + gst_caps_unref (_gst_caps_any); + _gst_caps_any = NULL; + gst_caps_unref (_gst_caps_none); + _gst_caps_none = NULL; +} + +GstCapsFeatures * +__gst_caps_get_features_unchecked (const GstCaps * caps, guint idx) +{ + return gst_caps_get_features_unchecked (caps, idx); +} + +static GstCaps * +_gst_caps_copy (const GstCaps * caps) +{ + GstCaps *newcaps; + GstStructure *structure; + GstCapsFeatures *features; + guint i, n; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + newcaps = gst_caps_new_empty (); + GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps); + n = GST_CAPS_LEN (caps); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, caps, "doing copy %p -> %p", + caps, newcaps); + + for (i = 0; i < n; i++) { + structure = gst_caps_get_structure_unchecked (caps, i); + features = gst_caps_get_features_unchecked (caps, i); + gst_caps_append_structure_full (newcaps, gst_structure_copy (structure), + gst_caps_features_copy_conditional (features)); + } + + return newcaps; +} + +/* creation/deletion */ +static void +_gst_caps_free (GstCaps * caps) +{ + GstStructure *structure; + GstCapsFeatures *features; + guint i, len; + + /* The refcount must be 0, but since we're only called by gst_caps_unref, + * don't bother testing. */ + len = GST_CAPS_LEN (caps); + /* This can be used to get statistics about caps sizes */ + /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */ + for (i = 0; i < len; i++) { + structure = gst_caps_get_structure_unchecked (caps, i); + gst_structure_set_parent_refcount (structure, NULL); + gst_structure_free (structure); + features = gst_caps_get_features_unchecked (caps, i); + if (features) { + gst_caps_features_set_parent_refcount (features, NULL); + gst_caps_features_free (features); + } + } + g_array_free (GST_CAPS_ARRAY (caps), TRUE); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps); +#endif + g_slice_free1 (sizeof (GstCapsImpl), caps); +} + +static void +gst_caps_init (GstCaps * caps) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), 0, _gst_caps_type, + (GstMiniObjectCopyFunction) _gst_caps_copy, NULL, + (GstMiniObjectFreeFunction) _gst_caps_free); + + /* the 32 has been determined by logging caps sizes in _gst_caps_free + * but g_ptr_array uses 16 anyway if it expands once, so this does not help + * in practice + * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32); + */ + GST_CAPS_ARRAY (caps) = + g_array_new (FALSE, TRUE, sizeof (GstCapsArrayElement)); +} + +/** + * gst_caps_new_empty: + * + * Creates a new #GstCaps that is empty. That is, the returned + * #GstCaps contains no media formats. + * The #GstCaps is guaranteed to be writable. + * Caller is responsible for unreffing the returned caps. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_empty (void) +{ + GstCaps *caps; + + caps = (GstCaps *) g_slice_new (GstCapsImpl); + + gst_caps_init (caps); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps); +#endif + + return caps; +} + +/** + * gst_caps_new_any: + * + * Creates a new #GstCaps that indicates that it is compatible with + * any media format. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_any (void) +{ + GstCaps *caps = gst_caps_new_empty (); + + GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY); + + return caps; +} + +/** + * gst_caps_new_empty_simple: + * @media_type: the media type of the structure + * + * Creates a new #GstCaps that contains one #GstStructure with name + * @media_type. + * Caller is responsible for unreffing the returned caps. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_empty_simple (const char *media_type) +{ + GstCaps *caps; + GstStructure *structure; + + caps = gst_caps_new_empty (); + structure = gst_structure_new_empty (media_type); + if (structure) + gst_caps_append_structure_unchecked (caps, structure, NULL); + + return caps; +} + +/** + * gst_caps_new_simple: + * @media_type: the media type of the structure + * @fieldname: first field to set + * @...: additional arguments + * + * Creates a new #GstCaps that contains one #GstStructure. The + * structure is defined by the arguments, which have the same format + * as gst_structure_new(). + * Caller is responsible for unreffing the returned caps. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_simple (const char *media_type, const char *fieldname, ...) +{ + GstCaps *caps; + GstStructure *structure; + va_list var_args; + + caps = gst_caps_new_empty (); + + va_start (var_args, fieldname); + structure = gst_structure_new_valist (media_type, fieldname, var_args); + va_end (var_args); + + if (structure) + gst_caps_append_structure_unchecked (caps, structure, NULL); + else + gst_caps_replace (&caps, NULL); + + return caps; +} + +/** + * gst_caps_new_full: + * @struct1: the first structure to add + * @...: additional structures to add + * + * Creates a new #GstCaps and adds all the structures listed as + * arguments. The list must be %NULL-terminated. The structures + * are not copied; the returned #GstCaps owns the structures. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_full (GstStructure * struct1, ...) +{ + GstCaps *caps; + va_list var_args; + + va_start (var_args, struct1); + caps = gst_caps_new_full_valist (struct1, var_args); + va_end (var_args); + + return caps; +} + +/** + * gst_caps_new_full_valist: + * @structure: the first structure to add + * @var_args: additional structures to add + * + * Creates a new #GstCaps and adds all the structures listed as + * arguments. The list must be %NULL-terminated. The structures + * are not copied; the returned #GstCaps owns the structures. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_new_full_valist (GstStructure * structure, va_list var_args) +{ + GstCaps *caps; + + caps = gst_caps_new_empty (); + + while (structure) { + gst_caps_append_structure_unchecked (caps, structure, NULL); + structure = va_arg (var_args, GstStructure *); + } + + return caps; +} + +G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps); + +/** + * gst_static_caps_get: + * @static_caps: the #GstStaticCaps to convert + * + * Converts a #GstStaticCaps to a #GstCaps. + * + * Returns: (transfer full) (nullable): a pointer to the #GstCaps. Unref + * after usage. Since the core holds an additional ref to the + * returned caps, use gst_caps_make_writable() on the returned caps + * to modify it. + */ +GstCaps * +gst_static_caps_get (GstStaticCaps * static_caps) +{ + GstCaps **caps; + + g_return_val_if_fail (static_caps != NULL, NULL); + + caps = &static_caps->caps; + + /* refcount is 0 when we need to convert */ + if (G_UNLIKELY (*caps == NULL)) { + const char *string; + + G_LOCK (static_caps_lock); + /* check if other thread already updated */ + if (G_UNLIKELY (*caps != NULL)) + goto done; + + string = static_caps->string; + + if (G_UNLIKELY (string == NULL)) + goto no_string; + + *caps = gst_caps_from_string (string); + + /* convert to string */ + if (G_UNLIKELY (*caps == NULL)) { + g_critical ("Could not convert static caps \"%s\"", string); + goto done; + } + + /* Caps generated from static caps are usually leaked */ + GST_MINI_OBJECT_FLAG_SET (*caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); + + GST_CAT_TRACE (GST_CAT_CAPS, "created %p from string %s", static_caps, + string); + done: + G_UNLOCK (static_caps_lock); + } + /* ref the caps, makes it not writable */ + if (G_LIKELY (*caps != NULL)) + gst_caps_ref (*caps); + + return *caps; + + /* ERRORS */ +no_string: + { + G_UNLOCK (static_caps_lock); + g_warning ("static caps %p string is NULL", static_caps); + return NULL; + } +} + +/** + * gst_static_caps_cleanup: + * @static_caps: the #GstStaticCaps to clean + * + * Clean up the cached caps contained in @static_caps. + */ +void +gst_static_caps_cleanup (GstStaticCaps * static_caps) +{ + G_LOCK (static_caps_lock); + gst_caps_replace (&static_caps->caps, NULL); + G_UNLOCK (static_caps_lock); +} + +/* manipulation */ + +static void +gst_caps_remove_and_get_structure_and_features (GstCaps * caps, guint idx, + GstStructure ** s, GstCapsFeatures ** f) +{ + GstStructure *s_; + GstCapsFeatures *f_; + + s_ = gst_caps_get_structure_unchecked (caps, idx); + f_ = gst_caps_get_features_unchecked (caps, idx); + + /* don't use index_fast, gst_caps_simplify relies on the order */ + g_array_remove_index (GST_CAPS_ARRAY (caps), idx); + + gst_structure_set_parent_refcount (s_, NULL); + if (f_) { + gst_caps_features_set_parent_refcount (f_, NULL); + } + + *s = s_; + *f = f_; +} + +static GstStructure * +gst_caps_remove_and_get_structure (GstCaps * caps, guint idx) +{ + GstStructure *s; + GstCapsFeatures *f; + + gst_caps_remove_and_get_structure_and_features (caps, idx, &s, &f); + + if (f) + gst_caps_features_free (f); + + return s; +} + +/** + * gst_caps_steal_structure: + * @caps: the #GstCaps to retrieve from + * @index: Index of the structure to retrieve + * + * Retrieves the structure with the given index from the list of structures + * contained in @caps. The caller becomes the owner of the returned structure. + * + * Returns: (transfer full) (nullable): a pointer to the #GstStructure + * corresponding to @index. + */ +GstStructure * +gst_caps_steal_structure (GstCaps * caps, guint index) +{ + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (IS_WRITABLE (caps), NULL); + + if (G_UNLIKELY (index >= GST_CAPS_LEN (caps))) + return NULL; + + return gst_caps_remove_and_get_structure (caps, index); +} + +/** + * gst_caps_append: + * @caps1: the #GstCaps that will be appended to + * @caps2: (transfer full): the #GstCaps to append + * + * Appends the structures contained in @caps2 to @caps1. The structures in + * @caps2 are not copied -- they are transferred to @caps1, and then @caps2 is + * freed. If either caps is ANY, the resulting caps will be ANY. + */ +void +gst_caps_append (GstCaps * caps1, GstCaps * caps2) +{ + GstStructure *structure; + GstCapsFeatures *features; + int i; + + g_return_if_fail (GST_IS_CAPS (caps1)); + g_return_if_fail (GST_IS_CAPS (caps2)); + g_return_if_fail (IS_WRITABLE (caps1)); + + if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) { + GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY; + gst_caps_unref (caps2); + } else { + caps2 = gst_caps_make_writable (caps2); + + for (i = GST_CAPS_LEN (caps2); i; i--) { + gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure, + &features); + gst_caps_append_structure_unchecked (caps1, structure, features); + } + gst_caps_unref (caps2); /* guaranteed to free it */ + } +} + +/** + * gst_caps_merge: + * @caps1: (transfer full): the #GstCaps that will take the new entries + * @caps2: (transfer full): the #GstCaps to merge in + * + * Appends the structures contained in @caps2 to @caps1 if they are not yet + * expressed by @caps1. The structures in @caps2 are not copied -- they are + * transferred to a writable copy of @caps1, and then @caps2 is freed. + * If either caps is ANY, the resulting caps will be ANY. + * + * Returns: (transfer full): the merged caps. + */ +GstCaps * +gst_caps_merge (GstCaps * caps1, GstCaps * caps2) +{ + GstStructure *structure; + GstCapsFeatures *features; + int i; + GstCaps *result; + + g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); + g_return_val_if_fail (GST_IS_CAPS (caps2), NULL); + + if (G_UNLIKELY (CAPS_IS_ANY (caps1))) { + gst_caps_unref (caps2); + result = caps1; + } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) { + gst_caps_unref (caps1); + result = caps2; + } else { + caps2 = gst_caps_make_writable (caps2); + + for (i = GST_CAPS_LEN (caps2); i; i--) { + gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure, + &features); + caps1 = gst_caps_merge_structure_full (caps1, structure, features); + } + gst_caps_unref (caps2); + result = caps1; + + /* this is too naive + GstCaps *com = gst_caps_intersect (caps1, caps2); + GstCaps *add = gst_caps_subtract (caps2, com); + + GST_DEBUG ("common : %d", gst_caps_get_size (com)); + GST_DEBUG ("adding : %d", gst_caps_get_size (add)); + gst_caps_append (caps1, add); + gst_caps_unref (com); + */ + } + + return result; +} + +/** + * gst_caps_append_structure: + * @caps: the #GstCaps that will be appended to + * @structure: (transfer full): the #GstStructure to append + * + * Appends @structure to @caps. The structure is not copied; @caps + * becomes the owner of @structure. + */ +void +gst_caps_append_structure (GstCaps * caps, GstStructure * structure) +{ + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + if (G_LIKELY (structure)) { + gst_caps_append_structure_unchecked (caps, structure, NULL); + } +} + +/** + * gst_caps_append_structure_full: + * @caps: the #GstCaps that will be appended to + * @structure: (transfer full): the #GstStructure to append + * @features: (transfer full) (allow-none): the #GstCapsFeatures to append + * + * Appends @structure with @features to @caps. The structure is not copied; @caps + * becomes the owner of @structure. + * + * Since: 1.2 + */ +void +gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure, + GstCapsFeatures * features) +{ + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + if (G_LIKELY (structure)) { + gst_caps_append_structure_unchecked (caps, structure, features); + } +} + +/** + * gst_caps_remove_structure: + * @caps: the #GstCaps to remove from + * @idx: Index of the structure to remove + * + * removes the structure with the given index from the list of structures + * contained in @caps. + */ +void +gst_caps_remove_structure (GstCaps * caps, guint idx) +{ + GstStructure *structure; + + g_return_if_fail (caps != NULL); + g_return_if_fail (idx <= gst_caps_get_size (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + structure = gst_caps_remove_and_get_structure (caps, idx); + gst_structure_free (structure); +} + +/** + * gst_caps_merge_structure: + * @caps: (transfer full): the #GstCaps to merge into + * @structure: (transfer full): the #GstStructure to merge + * + * Appends @structure to @caps if its not already expressed by @caps. + * + * Returns: (transfer full): the merged caps. + */ +GstCaps * +gst_caps_merge_structure (GstCaps * caps, GstStructure * structure) +{ + GstStructure *structure1; + GstCapsFeatures *features1; + int i; + gboolean unique = TRUE; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + if (G_UNLIKELY (structure == NULL)) + return caps; + + /* check each structure */ + for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) { + structure1 = gst_caps_get_structure_unchecked (caps, i); + features1 = gst_caps_get_features_unchecked (caps, i); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + /* if structure is a subset of structure1 and the + * there are no existing features, then skip it */ + if (gst_caps_features_is_equal (features1, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY) + && gst_structure_is_subset (structure, structure1)) { + unique = FALSE; + break; + } + } + if (unique) { + caps = gst_caps_make_writable (caps); + gst_caps_append_structure_unchecked (caps, structure, NULL); + } else { + gst_structure_free (structure); + } + return caps; +} + +/** + * gst_caps_merge_structure_full: + * @caps: (transfer full): the #GstCaps to merge into + * @structure: (transfer full): the #GstStructure to merge + * @features: (transfer full) (allow-none): the #GstCapsFeatures to merge + * + * Appends @structure with @features to @caps if its not already expressed by @caps. + * + * Returns: (transfer full): the merged caps. + * + * Since: 1.2 + */ +GstCaps * +gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure, + GstCapsFeatures * features) +{ + GstStructure *structure1; + GstCapsFeatures *features1, *features_tmp; + int i; + gboolean unique = TRUE; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + if (G_UNLIKELY (structure == NULL)) + return caps; + + /* To make comparisons easier below */ + features_tmp = features ? features : GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + /* check each structure */ + for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) { + structure1 = gst_caps_get_structure_unchecked (caps, i); + features1 = gst_caps_get_features_unchecked (caps, i); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + /* if structure is a subset of structure1 and the + * the features are a subset, then skip it */ + /* FIXME: We only skip if none of the features are + * ANY and are still equal. That way all ANY structures + * show up in the caps and no non-ANY structures are + * swallowed by ANY structures + */ + if (((!gst_caps_features_is_any (features_tmp) + || gst_caps_features_is_any (features1)) + && gst_caps_features_is_equal (features_tmp, features1)) + && gst_structure_is_subset (structure, structure1)) { + unique = FALSE; + break; + } + } + if (unique) { + caps = gst_caps_make_writable (caps); + gst_caps_append_structure_unchecked (caps, structure, features); + } else { + gst_structure_free (structure); + if (features) + gst_caps_features_free (features); + } + return caps; +} + +/** + * gst_caps_get_size: + * @caps: a #GstCaps + * + * Gets the number of structures contained in @caps. + * + * Returns: the number of structures that @caps contains + */ +guint +gst_caps_get_size (const GstCaps * caps) +{ + g_return_val_if_fail (GST_IS_CAPS (caps), 0); + + return GST_CAPS_LEN (caps); +} + +/** + * gst_caps_get_structure: + * @caps: a #GstCaps + * @index: the index of the structure + * + * Finds the structure in @caps that has the index @index, and + * returns it. + * + * WARNING: This function takes a const GstCaps *, but returns a + * non-const GstStructure *. This is for programming convenience -- + * the caller should be aware that structures inside a constant + * #GstCaps should not be modified. However, if you know the caps + * are writable, either because you have just copied them or made + * them writable with gst_caps_make_writable(), you may modify the + * structure returned in the usual way, e.g. with functions like + * gst_structure_set(). + * + * You do not need to free or unref the structure returned, it + * belongs to the #GstCaps. + * + * Returns: (transfer none): a pointer to the #GstStructure corresponding + * to @index + */ +GstStructure * +gst_caps_get_structure (const GstCaps * caps, guint index) +{ + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL); + + return gst_caps_get_structure_unchecked (caps, index); +} + +/** + * gst_caps_get_features: + * @caps: a #GstCaps + * @index: the index of the structure + * + * Finds the features in @caps that has the index @index, and + * returns it. + * + * WARNING: This function takes a const GstCaps *, but returns a + * non-const GstCapsFeatures *. This is for programming convenience -- + * the caller should be aware that structures inside a constant + * #GstCaps should not be modified. However, if you know the caps + * are writable, either because you have just copied them or made + * them writable with gst_caps_make_writable(), you may modify the + * features returned in the usual way, e.g. with functions like + * gst_caps_features_add(). + * + * You do not need to free or unref the structure returned, it + * belongs to the #GstCaps. + * + * Returns: (transfer none) (nullable): a pointer to the #GstCapsFeatures + * corresponding to @index + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_get_features (const GstCaps * caps, guint index) +{ + GstCapsFeatures *features; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL); + + features = gst_caps_get_features_unchecked (caps, index); + if (!features) { + GstCapsFeatures **storage; + + /* We have to do some atomic pointer magic here as the caps + * might not be writable and someone else calls this function + * at the very same time */ + features = gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY); + gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps)); + + storage = gst_caps_get_features_storage_unchecked (caps, index); + if (!g_atomic_pointer_compare_and_exchange (storage, NULL, features)) { + /* Someone did the same we just tried in the meantime */ + gst_caps_features_set_parent_refcount (features, NULL); + gst_caps_features_free (features); + + features = gst_caps_get_features_unchecked (caps, index); + g_assert (features != NULL); + } + } + + return features; +} + +/** + * gst_caps_set_features: + * @caps: a #GstCaps + * @index: the index of the structure + * @features: (allow-none) (transfer full): the #GstCapsFeatures to set + * + * Sets the #GstCapsFeatures @features for the structure at @index. + * + * Since: 1.2 + */ +void +gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features) +{ + GstCapsFeatures **storage, *old; + + g_return_if_fail (caps != NULL); + g_return_if_fail (index <= gst_caps_get_size (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + storage = gst_caps_get_features_storage_unchecked (caps, index); + /* Not much problem here as caps are writable */ + old = g_atomic_pointer_get (storage); + g_atomic_pointer_set (storage, features); + + if (features) + gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps)); + + if (old) { + gst_caps_features_set_parent_refcount (old, NULL); + gst_caps_features_free (old); + } +} + +/** + * gst_caps_copy_nth: + * @caps: the #GstCaps to copy + * @nth: the nth structure to copy + * + * Creates a new #GstCaps and appends a copy of the nth structure + * contained in @caps. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_copy_nth (const GstCaps * caps, guint nth) +{ + GstCaps *newcaps; + GstStructure *structure; + GstCapsFeatures *features; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + newcaps = gst_caps_new_empty (); + GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps); + + if (G_LIKELY (GST_CAPS_LEN (caps) > nth)) { + structure = gst_caps_get_structure_unchecked (caps, nth); + features = gst_caps_get_features_unchecked (caps, nth); + gst_caps_append_structure_unchecked (newcaps, + gst_structure_copy (structure), + gst_caps_features_copy_conditional (features)); + } + + return newcaps; +} + +/** + * gst_caps_truncate: + * @caps: (transfer full): the #GstCaps to truncate + * + * Discard all but the first structure from @caps. Useful when + * fixating. + * + * This function takes ownership of @caps and will call gst_caps_make_writable() + * on it if necessary, so you must not use @caps afterwards unless you keep an + * additional reference to it with gst_caps_ref(). + * + * Returns: (transfer full): truncated caps + */ +GstCaps * +gst_caps_truncate (GstCaps * caps) +{ + gint i; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + i = GST_CAPS_LEN (caps) - 1; + if (i == 0) + return caps; + + caps = gst_caps_make_writable (caps); + while (i > 0) + gst_caps_remove_structure (caps, i--); + + return caps; +} + +/** + * gst_caps_set_value: + * @caps: a writable caps + * @field: name of the field to set + * @value: value to set the field to + * + * Sets the given @field on all structures of @caps to the given @value. + * This is a convenience function for calling gst_structure_set_value() on + * all structures of @caps. + **/ +void +gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value) +{ + guint i, len; + + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + g_return_if_fail (field != NULL); + g_return_if_fail (G_IS_VALUE (value)); + + len = GST_CAPS_LEN (caps); + for (i = 0; i < len; i++) { + GstStructure *structure = gst_caps_get_structure_unchecked (caps, i); + gst_structure_set_value (structure, field, value); + } +} + +/** + * gst_caps_set_simple_valist: + * @caps: the #GstCaps to set + * @field: first field to set + * @varargs: additional parameters + * + * Sets fields in a #GstCaps. The arguments must be passed in the same + * manner as gst_structure_set(), and be %NULL-terminated. + */ +void +gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs) +{ + GValue value = { 0, }; + + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + while (field) { + GType type; + char *err; + + type = va_arg (varargs, GType); + + G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err); + if (G_UNLIKELY (err)) { + g_critical ("%s", err); + return; + } + + gst_caps_set_value (caps, field, &value); + + g_value_unset (&value); + + field = va_arg (varargs, const gchar *); + } +} + +/** + * gst_caps_set_simple: + * @caps: the #GstCaps to set + * @field: first field to set + * @...: additional parameters + * + * Sets fields in a #GstCaps. The arguments must be passed in the same + * manner as gst_structure_set(), and be %NULL-terminated. + */ +void +gst_caps_set_simple (GstCaps * caps, const char *field, ...) +{ + va_list var_args; + + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (IS_WRITABLE (caps)); + + va_start (var_args, field); + gst_caps_set_simple_valist (caps, field, var_args); + va_end (var_args); +} + +/* tests */ + +/** + * gst_caps_is_any: + * @caps: the #GstCaps to test + * + * Determines if @caps represents any media format. + * + * Returns: %TRUE if @caps represents any format. + */ +gboolean +gst_caps_is_any (const GstCaps * caps) +{ + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + return (CAPS_IS_ANY (caps)); +} + +/** + * gst_caps_is_empty: + * @caps: the #GstCaps to test + * + * Determines if @caps represents no media formats. + * + * Returns: %TRUE if @caps represents no formats. + */ +gboolean +gst_caps_is_empty (const GstCaps * caps) +{ + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + if (CAPS_IS_ANY (caps)) + return FALSE; + + return CAPS_IS_EMPTY_SIMPLE (caps); +} + +static gboolean +gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value, + gpointer unused) +{ + return gst_value_is_fixed (value); +} + +/** + * gst_caps_is_fixed: + * @caps: the #GstCaps to test + * + * Fixed #GstCaps describe exactly one format, that is, they have exactly + * one structure, and each field in the structure describes a fixed type. + * Examples of non-fixed types are GST_TYPE_INT_RANGE and GST_TYPE_LIST. + * + * Returns: %TRUE if @caps is fixed + */ +gboolean +gst_caps_is_fixed (const GstCaps * caps) +{ + GstStructure *structure; + GstCapsFeatures *features; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + if (GST_CAPS_LEN (caps) != 1) + return FALSE; + + features = gst_caps_get_features_unchecked (caps, 0); + if (features && gst_caps_features_is_any (features)) + return FALSE; + + structure = gst_caps_get_structure_unchecked (caps, 0); + + return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL); +} + +/** + * gst_caps_is_equal_fixed: + * @caps1: the #GstCaps to test + * @caps2: the #GstCaps to test + * + * Tests if two #GstCaps are equal. This function only works on fixed + * #GstCaps. + * + * Returns: %TRUE if the arguments represent the same format + */ +gboolean +gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2) +{ + GstStructure *struct1, *struct2; + GstCapsFeatures *features1, *features2; + + g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE); + + struct1 = gst_caps_get_structure_unchecked (caps1, 0); + features1 = gst_caps_get_features_unchecked (caps1, 0); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + struct2 = gst_caps_get_structure_unchecked (caps2, 0); + features2 = gst_caps_get_features_unchecked (caps2, 0); + if (!features2) + features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + return gst_structure_is_equal (struct1, struct2) && + gst_caps_features_is_equal (features1, features2); +} + +/** + * gst_caps_is_always_compatible: + * @caps1: the #GstCaps to test + * @caps2: the #GstCaps to test + * + * A given #GstCaps structure is always compatible with another if + * every media format that is in the first is also contained in the + * second. That is, @caps1 is a subset of @caps2. + * + * Returns: %TRUE if @caps1 is a subset of @caps2. + */ +gboolean +gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2) +{ + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); + + return gst_caps_is_subset (caps1, caps2); +} + +/** + * gst_caps_is_subset: + * @subset: a #GstCaps + * @superset: a potentially greater #GstCaps + * + * Checks if all caps represented by @subset are also represented by @superset. + * + * Returns: %TRUE if @subset is a subset of @superset + */ +gboolean +gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset) +{ + GstStructure *s1, *s2; + GstCapsFeatures *f1, *f2; + gboolean ret = TRUE; + gint i, j; + + g_return_val_if_fail (subset != NULL, FALSE); + g_return_val_if_fail (superset != NULL, FALSE); + + if (CAPS_IS_EMPTY (subset) || CAPS_IS_ANY (superset)) + return TRUE; + if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset)) + return FALSE; + + for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) { + for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) { + s1 = gst_caps_get_structure_unchecked (subset, i); + f1 = gst_caps_get_features_unchecked (subset, i); + if (!f1) + f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + s2 = gst_caps_get_structure_unchecked (superset, j); + f2 = gst_caps_get_features_unchecked (superset, j); + if (!f2) + f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if ((!gst_caps_features_is_any (f1) || gst_caps_features_is_any (f2)) && + gst_caps_features_is_equal (f1, f2) + && gst_structure_is_subset (s1, s2)) { + /* If we found a superset, continue with the next + * subset structure */ + break; + } + } + /* If we found no superset for this subset structure + * we return FALSE immediately */ + if (j == -1) { + ret = FALSE; + break; + } + } + + return ret; +} + +/** + * gst_caps_is_subset_structure: + * @caps: a #GstCaps + * @structure: a potential #GstStructure subset of @caps + * + * Checks if @structure is a subset of @caps. See gst_caps_is_subset() + * for more information. + * + * Returns: %TRUE if @structure is a subset of @caps + */ +gboolean +gst_caps_is_subset_structure (const GstCaps * caps, + const GstStructure * structure) +{ + GstStructure *s; + gint i; + + g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (structure != NULL, FALSE); + + if (CAPS_IS_ANY (caps)) + return TRUE; + if (CAPS_IS_EMPTY (caps)) + return FALSE; + + for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) { + s = gst_caps_get_structure_unchecked (caps, i); + if (gst_structure_is_subset (structure, s)) { + /* If we found a superset return TRUE */ + return TRUE; + } + } + + return FALSE; +} + +/** + * gst_caps_is_subset_structure_full: + * @caps: a #GstCaps + * @structure: a potential #GstStructure subset of @caps + * @features: (allow-none): a #GstCapsFeatures for @structure + * + * Checks if @structure is a subset of @caps. See gst_caps_is_subset() + * for more information. + * + * Returns: %TRUE if @structure is a subset of @caps + * + * Since: 1.2 + */ +gboolean +gst_caps_is_subset_structure_full (const GstCaps * caps, + const GstStructure * structure, const GstCapsFeatures * features) +{ + GstStructure *s; + GstCapsFeatures *f; + gint i; + + g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (structure != NULL, FALSE); + + if (CAPS_IS_ANY (caps)) + return TRUE; + if (CAPS_IS_EMPTY (caps)) + return FALSE; + + if (!features) + features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) { + s = gst_caps_get_structure_unchecked (caps, i); + f = gst_caps_get_features_unchecked (caps, i); + if (!f) + f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if ((!gst_caps_features_is_any (features) || gst_caps_features_is_any (f)) + && gst_caps_features_is_equal (features, f) + && gst_structure_is_subset (structure, s)) { + /* If we found a superset return TRUE */ + return TRUE; + } + } + + return FALSE; +} + +/** + * gst_caps_is_equal: + * @caps1: a #GstCaps + * @caps2: another #GstCaps + * + * Checks if the given caps represent the same set of caps. + * + * Returns: %TRUE if both caps are equal. + */ +gboolean +gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) +{ + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); + + if (G_UNLIKELY (caps1 == caps2)) + return TRUE; + + if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2))) + return gst_caps_is_equal_fixed (caps1, caps2); + + return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1); +} + +/** + * gst_caps_is_strictly_equal: + * @caps1: a #GstCaps + * @caps2: another #GstCaps + * + * Checks if the given caps are exactly the same set of caps. + * + * Returns: %TRUE if both caps are strictly equal. + */ +gboolean +gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2) +{ + int i; + GstStructure *s1, *s2; + GstCapsFeatures *f1, *f2; + + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); + + if (G_UNLIKELY (caps1 == caps2)) + return TRUE; + + if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2)) + return FALSE; + + for (i = 0; i < GST_CAPS_LEN (caps1); i++) { + s1 = gst_caps_get_structure_unchecked (caps1, i); + f1 = gst_caps_get_features_unchecked (caps1, i); + if (!f1) + f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + s2 = gst_caps_get_structure_unchecked (caps2, i); + f2 = gst_caps_get_features_unchecked (caps2, i); + if (!f2) + f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + if (gst_caps_features_is_any (f1) != gst_caps_features_is_any (f2) || + !gst_caps_features_is_equal (f1, f2) || + !gst_structure_is_equal (s1, s2)) + return FALSE; + } + + return TRUE; +} + +/* intersect operation */ + +/** + * gst_caps_can_intersect: + * @caps1: a #GstCaps to intersect + * @caps2: a #GstCaps to intersect + * + * Tries intersecting @caps1 and @caps2 and reports whether the result would not + * be empty + * + * Returns: %TRUE if intersection would be not empty + */ +gboolean +gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2) +{ + guint64 i; /* index can be up to 2 * G_MAX_UINT */ + guint j, k, len1, len2; + GstStructure *struct1; + GstStructure *struct2; + GstCapsFeatures *features1; + GstCapsFeatures *features2; + + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); + + /* caps are exactly the same pointers */ + if (G_UNLIKELY (caps1 == caps2)) + return TRUE; + + /* empty caps on either side, return empty */ + if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2))) + return FALSE; + + /* one of the caps is any */ + if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) + return TRUE; + + /* run zigzag on top line then right line, this preserves the caps order + * much better than a simple loop. + * + * This algorithm zigzags over the caps structures as demonstrated in + * the following matrix: + * + * caps1 0 1 2 3 + * +------------- total distance: +------------- + * | 1 2 4 7 0 | 0 1 2 3 + * caps2 | 3 5 8 10 1 | 1 2 3 4 + * | 6 9 11 12 2 | 2 3 4 5 + * + * First we iterate over the caps1 structures (top line) intersecting + * the structures diagonally down, then we iterate over the caps2 + * structures. The result is that the intersections are ordered based on the + * sum of the indexes in the list. + */ + len1 = GST_CAPS_LEN (caps1); + len2 = GST_CAPS_LEN (caps2); + for (i = 0; i < len1 + len2 - 1; i++) { + /* superset index goes from 0 to superset->structs->len-1 */ + j = MIN (i, len1 - 1); + /* subset index stays 0 until i reaches superset->structs->len, then it + * counts up from 1 to subset->structs->len - 1 */ + k = (i > j) ? (i - j) : 0; /* MAX (0, i - j) */ + /* now run the diagonal line, end condition is the left or bottom + * border */ + while (k < len2) { + struct1 = gst_caps_get_structure_unchecked (caps1, j); + features1 = gst_caps_get_features_unchecked (caps1, j); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + struct2 = gst_caps_get_structure_unchecked (caps2, k); + features2 = gst_caps_get_features_unchecked (caps2, k); + if (!features2) + features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (gst_caps_features_is_equal (features1, features2) && + gst_structure_can_intersect (struct1, struct2)) { + return TRUE; + } + /* move down left */ + k++; + if (G_UNLIKELY (j == 0)) + break; /* so we don't roll back to G_MAXUINT */ + j--; + } + } + + return FALSE; +} + +static GstCaps * +gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2) +{ + guint64 i; /* index can be up to 2 * G_MAX_UINT */ + guint j, k, len1, len2; + GstStructure *struct1; + GstStructure *struct2; + GstCapsFeatures *features1; + GstCapsFeatures *features2; + GstCaps *dest; + GstStructure *istruct; + + /* caps are exactly the same pointers, just copy one caps */ + if (G_UNLIKELY (caps1 == caps2)) + return gst_caps_ref (caps1); + + /* empty caps on either side, return empty */ + if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2))) + return gst_caps_ref (GST_CAPS_NONE); + + /* one of the caps is any, just copy the other caps */ + if (G_UNLIKELY (CAPS_IS_ANY (caps1))) + return gst_caps_ref (caps2); + + if (G_UNLIKELY (CAPS_IS_ANY (caps2))) + return gst_caps_ref (caps1); + + dest = gst_caps_new_empty (); + /* run zigzag on top line then right line, this preserves the caps order + * much better than a simple loop. + * + * This algorithm zigzags over the caps structures as demonstrated in + * the following matrix: + * + * caps1 + * +------------- + * | 1 2 4 7 + * caps2 | 3 5 8 10 + * | 6 9 11 12 + * + * First we iterate over the caps1 structures (top line) intersecting + * the structures diagonally down, then we iterate over the caps2 + * structures. + */ + len1 = GST_CAPS_LEN (caps1); + len2 = GST_CAPS_LEN (caps2); + for (i = 0; i < len1 + len2 - 1; i++) { + /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */ + j = MIN (i, len1 - 1); + /* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts + * up from 1 to GST_CAPS_LEN (caps2) - 1 */ + k = (i > j) ? (i - j) : 0; /* MAX (0, i - j) */ + /* now run the diagonal line, end condition is the left or bottom + * border */ + while (k < len2) { + struct1 = gst_caps_get_structure_unchecked (caps1, j); + features1 = gst_caps_get_features_unchecked (caps1, j); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + struct2 = gst_caps_get_structure_unchecked (caps2, k); + features2 = gst_caps_get_features_unchecked (caps2, k); + if (!features2) + features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (gst_caps_features_is_equal (features1, features2)) { + istruct = gst_structure_intersect (struct1, struct2); + if (istruct) { + if (gst_caps_features_is_any (features1)) + dest = + gst_caps_merge_structure_full (dest, istruct, + gst_caps_features_copy_conditional (features2)); + else + dest = + gst_caps_merge_structure_full (dest, istruct, + gst_caps_features_copy_conditional (features1)); + } + } + /* move down left */ + k++; + if (G_UNLIKELY (j == 0)) + break; /* so we don't roll back to G_MAXUINT */ + j--; + } + } + return dest; +} + +/** + * gst_caps_intersect_first: + * @caps1: a #GstCaps to intersect + * @caps2: a #GstCaps to intersect + * + * Creates a new #GstCaps that contains all the formats that are common + * to both @caps1 and @caps2. + * + * Unlike @gst_caps_intersect, the returned caps will be ordered in a similar + * fashion as @caps1. + * + * Returns: (transfer full): the new #GstCaps + */ +static GstCaps * +gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2) +{ + guint i; + guint j, len1, len2; + GstStructure *struct1; + GstStructure *struct2; + GstCapsFeatures *features1; + GstCapsFeatures *features2; + GstCaps *dest; + GstStructure *istruct; + + /* caps are exactly the same pointers, just copy one caps */ + if (G_UNLIKELY (caps1 == caps2)) + return gst_caps_ref (caps1); + + /* empty caps on either side, return empty */ + if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2))) + return gst_caps_ref (GST_CAPS_NONE); + + /* one of the caps is any, just copy the other caps */ + if (G_UNLIKELY (CAPS_IS_ANY (caps1))) + return gst_caps_ref (caps2); + + if (G_UNLIKELY (CAPS_IS_ANY (caps2))) + return gst_caps_ref (caps1); + + dest = gst_caps_new_empty (); + len1 = GST_CAPS_LEN (caps1); + len2 = GST_CAPS_LEN (caps2); + for (i = 0; i < len1; i++) { + struct1 = gst_caps_get_structure_unchecked (caps1, i); + features1 = gst_caps_get_features_unchecked (caps1, i); + if (!features1) + features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + for (j = 0; j < len2; j++) { + struct2 = gst_caps_get_structure_unchecked (caps2, j); + features2 = gst_caps_get_features_unchecked (caps2, j); + if (!features2) + features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (gst_caps_features_is_equal (features1, features2)) { + istruct = gst_structure_intersect (struct1, struct2); + if (istruct) { + if (gst_caps_features_is_any (features1)) + dest = + gst_caps_merge_structure_full (dest, istruct, + gst_caps_features_copy_conditional (features2)); + else + dest = + gst_caps_merge_structure_full (dest, istruct, + gst_caps_features_copy_conditional (features1)); + } + } + } + } + + return dest; +} + +/** + * gst_caps_intersect_full: + * @caps1: a #GstCaps to intersect + * @caps2: a #GstCaps to intersect + * @mode: The intersection algorithm/mode to use + * + * Creates a new #GstCaps that contains all the formats that are common + * to both @caps1 and @caps2, the order is defined by the #GstCapsIntersectMode + * used. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_intersect_full (GstCaps * caps1, GstCaps * caps2, + GstCapsIntersectMode mode) +{ + g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); + g_return_val_if_fail (GST_IS_CAPS (caps2), NULL); + + switch (mode) { + case GST_CAPS_INTERSECT_FIRST: + return gst_caps_intersect_first (caps1, caps2); + default: + g_warning ("Unknown caps intersect mode: %d", mode); + /* fallthrough */ + case GST_CAPS_INTERSECT_ZIG_ZAG: + return gst_caps_intersect_zig_zag (caps1, caps2); + } +} + +/** + * gst_caps_intersect: + * @caps1: a #GstCaps to intersect + * @caps2: a #GstCaps to intersect + * + * Creates a new #GstCaps that contains all the formats that are common + * to both @caps1 and @caps2. Defaults to %GST_CAPS_INTERSECT_ZIG_ZAG mode. + * + * Returns: (transfer full): the new #GstCaps + */ +GstCaps * +gst_caps_intersect (GstCaps * caps1, GstCaps * caps2) +{ + return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG); +} + +/* subtract operation */ + +typedef struct +{ + const GstStructure *subtract_from; + GSList *put_into; +} SubtractionEntry; + +static gboolean +gst_caps_structure_subtract_field (GQuark field_id, const GValue * value, + gpointer user_data) +{ + SubtractionEntry *e = user_data; + GValue subtraction = { 0, }; + const GValue *other; + GstStructure *structure; + + other = gst_structure_id_get_value (e->subtract_from, field_id); + + if (!other) { + return FALSE; + } + + if (!gst_value_subtract (&subtraction, other, value)) + return TRUE; + + if (gst_value_compare (&subtraction, other) == GST_VALUE_EQUAL) { + g_value_unset (&subtraction); + return FALSE; + } else { + structure = gst_structure_copy (e->subtract_from); + gst_structure_id_take_value (structure, field_id, &subtraction); + e->put_into = g_slist_prepend (e->put_into, structure); + return TRUE; + } +} + +static gboolean +gst_caps_structure_subtract (GSList ** into, const GstStructure * minuend, + const GstStructure * subtrahend) +{ + SubtractionEntry e; + gboolean ret; + + e.subtract_from = minuend; + e.put_into = NULL; + ret = gst_structure_foreach ((GstStructure *) subtrahend, + gst_caps_structure_subtract_field, &e); + + if (ret) { + *into = e.put_into; + } else { + GSList *walk; + + for (walk = e.put_into; walk; walk = g_slist_next (walk)) { + gst_structure_free (walk->data); + } + g_slist_free (e.put_into); + } + + return ret; +} + +/** + * gst_caps_subtract: + * @minuend: #GstCaps to subtract from + * @subtrahend: #GstCaps to subtract + * + * Subtracts the @subtrahend from the @minuend. + * > This function does not work reliably if optional properties for caps + * > are included on one caps and omitted on the other. + * + * Returns: (transfer full): the resulting caps + */ +GstCaps * +gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend) +{ + guint i, j, sublen; + GstStructure *min; + GstStructure *sub; + GstCapsFeatures *min_f, *sub_f; + GstCaps *dest = NULL, *src; + + g_return_val_if_fail (minuend != NULL, NULL); + g_return_val_if_fail (subtrahend != NULL, NULL); + + if (CAPS_IS_EMPTY (minuend) || CAPS_IS_ANY (subtrahend)) { + return gst_caps_new_empty (); + } + + if (CAPS_IS_EMPTY_SIMPLE (subtrahend)) + return gst_caps_ref (minuend); + + /* FIXME: Do we want this here or above? + The reason we need this is that there is no definition about what + ANY means for specific types, so it's not possible to reduce ANY partially + You can only remove everything or nothing and that is done above. + Note: there's a test that checks this behaviour. */ + + g_return_val_if_fail (!CAPS_IS_ANY (minuend), NULL); + sublen = GST_CAPS_LEN (subtrahend); + g_assert (sublen > 0); + + src = _gst_caps_copy (minuend); + for (i = 0; i < sublen; i++) { + guint srclen; + + sub = gst_caps_get_structure_unchecked (subtrahend, i); + sub_f = gst_caps_get_features_unchecked (subtrahend, i); + if (!sub_f) + sub_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (dest) { + gst_caps_unref (src); + src = dest; + } + dest = gst_caps_new_empty (); + srclen = GST_CAPS_LEN (src); + for (j = 0; j < srclen; j++) { + min = gst_caps_get_structure_unchecked (src, j); + min_f = gst_caps_get_features_unchecked (src, j); + if (!min_f) + min_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + + /* Same reason as above for ANY caps */ + g_return_val_if_fail (!gst_caps_features_is_any (min_f), NULL); + + if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub) && + gst_caps_features_is_equal (min_f, sub_f)) { + GSList *list; + + if (gst_caps_structure_subtract (&list, min, sub)) { + GSList *walk; + + for (walk = list; walk; walk = g_slist_next (walk)) { + gst_caps_append_structure_unchecked (dest, + (GstStructure *) walk->data, + gst_caps_features_copy_conditional (min_f)); + } + g_slist_free (list); + } else { + gst_caps_append_structure_unchecked (dest, gst_structure_copy (min), + gst_caps_features_copy_conditional (min_f)); + } + } else { + gst_caps_append_structure_unchecked (dest, gst_structure_copy (min), + gst_caps_features_copy_conditional (min_f)); + } + } + + if (CAPS_IS_EMPTY_SIMPLE (dest)) { + gst_caps_unref (src); + return dest; + } + } + + gst_caps_unref (src); + dest = gst_caps_simplify (dest); + + return dest; +} + +/* normalize/simplify operations */ + +typedef struct _NormalizeForeach +{ + GstCaps *caps; + GstStructure *structure; + GstCapsFeatures *features; +} NormalizeForeach; + +static gboolean +gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr) +{ + NormalizeForeach *nf = (NormalizeForeach *) ptr; + GValue val = { 0 }; + guint i; + + if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + guint len = gst_value_list_get_size (value); + + for (i = 1; i < len; i++) { + const GValue *v = gst_value_list_get_value (value, i); + GstStructure *structure = gst_structure_copy (nf->structure); + + gst_structure_id_set_value (structure, field_id, v); + gst_caps_append_structure_unchecked (nf->caps, structure, + gst_caps_features_copy_conditional (nf->features)); + } + + gst_value_init_and_copy (&val, gst_value_list_get_value (value, 0)); + gst_structure_id_take_value (nf->structure, field_id, &val); + return FALSE; + } + + return TRUE; +} + +/** + * gst_caps_normalize: + * @caps: (transfer full): a #GstCaps to normalize + * + * Returns a #GstCaps that represents the same set of formats as + * @caps, but contains no lists. Each list is expanded into separate + * @GstStructures. + * + * This function takes ownership of @caps and will call gst_caps_make_writable() + * on it so you must not use @caps afterwards unless you keep an additional + * reference to it with gst_caps_ref(). + * + * Returns: (transfer full): the normalized #GstCaps + */ +GstCaps * +gst_caps_normalize (GstCaps * caps) +{ + NormalizeForeach nf; + guint i; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + caps = gst_caps_make_writable (caps); + nf.caps = caps; + + for (i = 0; i < gst_caps_get_size (nf.caps); i++) { + nf.structure = gst_caps_get_structure_unchecked (nf.caps, i); + nf.features = gst_caps_get_features_unchecked (nf.caps, i); + while (!gst_structure_foreach (nf.structure, + gst_caps_normalize_foreach, &nf)); + } + + return nf.caps; +} + +static gint +gst_caps_compare_structures (gconstpointer one, gconstpointer two) +{ + gint ret; + const GstStructure *struct1 = ((const GstCapsArrayElement *) one)->structure; + const GstStructure *struct2 = ((const GstCapsArrayElement *) two)->structure; + + /* FIXME: this orders alphabetically, but ordering the quarks might be faster + So what's the best way? */ + ret = strcmp (gst_structure_get_name (struct1), + gst_structure_get_name (struct2)); + + if (ret) + return ret; + + return gst_structure_n_fields (struct2) - gst_structure_n_fields (struct1); +} + +typedef struct +{ + GQuark name; + GValue value; + GstStructure *compare; +} UnionField; + +static gboolean +gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value, + gpointer user_data) +{ + UnionField *u = user_data; + const GValue *val = gst_structure_id_get_value (u->compare, field_id); + + if (!val) { + if (u->name) + g_value_unset (&u->value); + return FALSE; + } + + if (gst_value_compare (val, value) == GST_VALUE_EQUAL) + return TRUE; + + if (u->name) { + g_value_unset (&u->value); + return FALSE; + } + + u->name = field_id; + gst_value_union (&u->value, val, value); + + return TRUE; +} + +static gboolean +gst_caps_structure_simplify (GstStructure ** result, + GstStructure * simplify, GstStructure * compare) +{ + GSList *list; + UnionField field = { 0, {0,}, NULL }; + + /* try to subtract to get a real subset */ + if (gst_caps_structure_subtract (&list, simplify, compare)) { + if (list == NULL) { /* no result */ + *result = NULL; + return TRUE; + } else if (list->next == NULL) { /* one result */ + *result = list->data; + g_slist_free (list); + return TRUE; + } else { /* multiple results */ + g_slist_foreach (list, (GFunc) gst_structure_free, NULL); + g_slist_free (list); + list = NULL; + } + } + + /* try to union both structs */ + field.compare = compare; + if (gst_structure_foreach (simplify, + gst_caps_structure_figure_out_union, &field)) { + gboolean ret = FALSE; + + /* now we know all of simplify's fields are the same in compare + * but at most one field: field.name */ + if (G_IS_VALUE (&field.value)) { + if (gst_structure_n_fields (simplify) == gst_structure_n_fields (compare)) { + gst_structure_id_take_value (compare, field.name, &field.value); + *result = NULL; + ret = TRUE; + } else { + g_value_unset (&field.value); + } + } else + if (gst_structure_n_fields (simplify) <= + gst_structure_n_fields (compare)) { + /* compare is just more specific, will be optimized away later */ + /* FIXME: do this here? */ + GST_LOG ("found a case that will be optimized later."); + } else { + gchar *one = gst_structure_to_string (simplify); + gchar *two = gst_structure_to_string (compare); + + GST_ERROR + ("caps mismatch: structures %s and %s claim to be possible to unify, but aren't", + one, two); + g_free (one); + g_free (two); + } + return ret; + } + + return FALSE; +} + +static void +gst_caps_switch_structures (GstCaps * caps, GstStructure * old, + GstStructure * new, gint i) +{ + gst_structure_set_parent_refcount (old, NULL); + gst_structure_free (old); + gst_structure_set_parent_refcount (new, &GST_CAPS_REFCOUNT (caps)); + g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, i).structure = new; +} + +/** + * gst_caps_simplify: + * @caps: (transfer full): a #GstCaps to simplify + * + * Converts the given @caps into a representation that represents the + * same set of formats, but in a simpler form. Component structures that are + * identical are merged. Component structures that have values that can be + * merged are also merged. + * + * This function takes ownership of @caps and will call gst_caps_make_writable() + * on it if necessary, so you must not use @caps afterwards unless you keep an + * additional reference to it with gst_caps_ref(). + * + * This method does not preserve the original order of @caps. + * + * Returns: (transfer full): The simplified caps. + */ +GstCaps * +gst_caps_simplify (GstCaps * caps) +{ + GstStructure *simplify, *compare, *result = NULL; + GstCapsFeatures *simplify_f, *compare_f; + gint i, j, start; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + start = GST_CAPS_LEN (caps) - 1; + /* one caps, already as simple as can be */ + if (start == 0) + return caps; + + caps = gst_caps_make_writable (caps); + + g_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures); + + for (i = start; i >= 0; i--) { + simplify = gst_caps_get_structure_unchecked (caps, i); + simplify_f = gst_caps_get_features_unchecked (caps, i); + if (!simplify_f) + simplify_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + compare = gst_caps_get_structure_unchecked (caps, start); + compare_f = gst_caps_get_features_unchecked (caps, start); + if (!compare_f) + compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (gst_structure_get_name_id (simplify) != + gst_structure_get_name_id (compare) || + !gst_caps_features_is_equal (simplify_f, compare_f)) + start = i; + for (j = start; j >= 0; j--) { + if (j == i) + continue; + compare = gst_caps_get_structure_unchecked (caps, j); + compare_f = gst_caps_get_features_unchecked (caps, j); + if (!compare_f) + compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (gst_structure_get_name_id (simplify) != + gst_structure_get_name_id (compare) || + !gst_caps_features_is_equal (simplify_f, compare_f)) { + break; + } + if (gst_caps_structure_simplify (&result, simplify, compare)) { + if (result) { + gst_caps_switch_structures (caps, simplify, result, i); + simplify = result; + } else { + gst_caps_remove_structure (caps, i); + start--; + break; + } + } + } + } + return caps; +} + +/** + * gst_caps_fixate: + * @caps: (transfer full): a #GstCaps to fixate + * + * Modifies the given @caps into a representation with only fixed + * values. First the caps will be truncated and then the first structure will be + * fixated with gst_structure_fixate(). + * + * This function takes ownership of @caps and will call gst_caps_make_writable() + * on it so you must not use @caps afterwards unless you keep an additional + * reference to it with gst_caps_ref(). + * + * Returns: (transfer full): the fixated caps + */ +GstCaps * +gst_caps_fixate (GstCaps * caps) +{ + GstStructure *s; + GstCapsFeatures *f; + + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + /* default fixation */ + caps = gst_caps_truncate (caps); + caps = gst_caps_make_writable (caps); + s = gst_caps_get_structure (caps, 0); + gst_structure_fixate (s); + + /* Set features to sysmem if they're still ANY */ + f = gst_caps_get_features_unchecked (caps, 0); + if (f && gst_caps_features_is_any (f)) { + f = gst_caps_features_new_empty (); + gst_caps_set_features (caps, 0, f); + } + + return caps; +} + +/* utility */ + +/** + * gst_caps_to_string: + * @caps: a #GstCaps + * + * Converts @caps to a string representation. This string representation + * can be converted back to a #GstCaps by gst_caps_from_string(). + * + * For debugging purposes its easier to do something like this: + * |[ + * GST_LOG ("caps are %" GST_PTR_FORMAT, caps); + * ]| + * This prints the caps in human readable form. + * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * + * Returns: (transfer full): a newly allocated string representing @caps. + */ +gchar * +gst_caps_to_string (const GstCaps * caps) +{ + guint i, slen, clen; + GString *s; + + /* NOTE: This function is potentially called by the debug system, + * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.) + * should be careful to avoid recursion. This includes any functions + * called by gst_caps_to_string. In particular, calls should + * not use the GST_PTR_FORMAT extension. */ + + if (caps == NULL) { + return g_strdup ("NULL"); + } + if (CAPS_IS_ANY (caps)) { + return g_strdup ("ANY"); + } + if (CAPS_IS_EMPTY_SIMPLE (caps)) { + return g_strdup ("EMPTY"); + } + + /* estimate a rough string length to avoid unnecessary reallocs in GString */ + slen = 0; + clen = GST_CAPS_LEN (caps); + for (i = 0; i < clen; i++) { + GstCapsFeatures *f; + + slen += + STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked + (caps, i)); + f = gst_caps_get_features_unchecked (caps, i); + if (f) + slen += FEATURES_ESTIMATED_STRING_LEN (f); + } + + s = g_string_sized_new (slen); + for (i = 0; i < clen; i++) { + GstStructure *structure; + GstCapsFeatures *features; + + if (i > 0) { + /* ';' is now added by gst_structure_to_string */ + g_string_append_c (s, ' '); + } + + structure = gst_caps_get_structure_unchecked (caps, i); + features = gst_caps_get_features_unchecked (caps, i); + + g_string_append (s, gst_structure_get_name (structure)); + if (features && (gst_caps_features_is_any (features) + || !gst_caps_features_is_equal (features, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) { + g_string_append_c (s, '('); + priv_gst_caps_features_append_to_gstring (features, s); + g_string_append_c (s, ')'); + } + priv_gst_structure_append_to_gstring (structure, s); + } + if (s->len && s->str[s->len - 1] == ';') { + /* remove latest ';' */ + s->str[--s->len] = '\0'; + } + return g_string_free (s, FALSE); +} + +static gboolean +gst_caps_from_string_inplace (GstCaps * caps, const gchar * string) +{ + GstStructure *structure; + gchar *s, *copy, *end, *next, save; + + if (strcmp ("ANY", string) == 0) { + GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY; + return TRUE; + } + + if (strcmp ("EMPTY", string) == 0 || strcmp ("NONE", string) == 0) { + return TRUE; + } + + copy = s = g_strdup (string); + do { + GstCapsFeatures *features = NULL; + + while (g_ascii_isspace (*s)) + s++; + if (*s == '\0') { + break; + } + + if (!priv_gst_structure_parse_name (s, &s, &end, &next)) { + g_free (copy); + return FALSE; + } + + save = *end; + *end = '\0'; + structure = gst_structure_new_empty (s); + *end = save; + + if (structure == NULL) { + g_free (copy); + return FALSE; + } + + s = next; + + if (*s == '\0') { + goto append; + } + + if (*s == '(') { + s++; + end = s; + + while (TRUE) { + if (*end == '\0') { + break; + } else if (*end == ')') { + break; + } else { + end++; + } + } + + save = *end; + *end = '\0'; + features = gst_caps_features_from_string (s); + if (!features) { + gst_structure_free (structure); + g_free (copy); + return FALSE; + } + *end = save; + s = end; + if (save == ')') + s++; + } + + if (*s == '\0') { + goto append; + } + + if (!priv_gst_structure_parse_fields (s, &s, structure)) { + gst_structure_free (structure); + if (features) + gst_caps_features_free (features); + g_free (copy); + return FALSE; + } + + append: + gst_caps_append_structure_unchecked (caps, structure, features); + features = NULL; + if (*s == '\0') + break; + } while (TRUE); + + g_free (copy); + + return TRUE; +} + +/** + * gst_caps_from_string: + * @string: a string to convert to #GstCaps + * + * Converts @caps from a string representation. + * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * + * Returns: (transfer full) (nullable): a newly allocated #GstCaps + */ +GstCaps * +gst_caps_from_string (const gchar * string) +{ + GstCaps *caps; + + g_return_val_if_fail (string, FALSE); + + caps = gst_caps_new_empty (); + if (gst_caps_from_string_inplace (caps, string)) { + return caps; + } else { + gst_caps_unref (caps); + return NULL; + } +} + +static void +gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value) +{ + g_return_if_fail (G_IS_VALUE (src_value)); + g_return_if_fail (G_IS_VALUE (dest_value)); + g_return_if_fail (G_VALUE_HOLDS (src_value, GST_TYPE_CAPS)); + g_return_if_fail (G_VALUE_HOLDS (dest_value, G_TYPE_STRING) + || G_VALUE_HOLDS (dest_value, G_TYPE_POINTER)); + + g_value_take_string (dest_value, + gst_caps_to_string (gst_value_get_caps (src_value))); +} + +/** + * gst_caps_foreach: + * @caps: a #GstCaps + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each structure and caps feature in the + * #GstCaps. The function must not modify the fields. + * Also see gst_caps_map_in_place() and gst_caps_filter_and_map_in_place(). + * + * Returns: %TRUE if the supplied function returns %TRUE for each call, + * %FALSE otherwise. + * + * Since: 1.6 + */ +gboolean +gst_caps_foreach (const GstCaps * caps, GstCapsForeachFunc func, + gpointer user_data) +{ + guint i, n; + GstCapsFeatures *features; + GstStructure *structure; + gboolean ret; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + n = GST_CAPS_LEN (caps); + + for (i = 0; i < n; i++) { + features = gst_caps_get_features_unchecked (caps, i); + structure = gst_caps_get_structure_unchecked (caps, i); + + ret = func (features, structure, user_data); + if (G_UNLIKELY (!ret)) + return FALSE; + } + + return TRUE; +} + +/** + * gst_caps_map_in_place: + * @caps: a #GstCaps + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each structure and caps feature in the + * #GstCaps. In contrast to gst_caps_foreach(), the function may modify but not + * delete the structures and features. The caps must be mutable. + * + * Returns: %TRUE if the supplied function returns %TRUE for each call, + * %FALSE otherwise. + * + * Since: 1.6 + */ +gboolean +gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data) +{ + guint i, n; + GstCapsFeatures *features; + GstStructure *structure; + gboolean ret; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + g_return_val_if_fail (gst_caps_is_writable (caps), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + n = GST_CAPS_LEN (caps); + + for (i = 0; i < n; i++) { + features = gst_caps_get_features_unchecked (caps, i); + structure = gst_caps_get_structure_unchecked (caps, i); + + /* Provide sysmem features if there are none yet */ + if (!features) { + features = + gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY); + gst_caps_set_features (caps, i, features); + } + + ret = func (features, structure, user_data); + if (G_UNLIKELY (!ret)) + return FALSE; + } + + return TRUE; +} + +/** + * gst_caps_filter_and_map_in_place: + * @caps: a #GstCaps + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each structure and caps feature in the + * #GstCaps. In contrast to gst_caps_foreach(), the function may modify the + * structure and features. In contrast to gst_caps_filter_and_map_in_place(), + * the structure and features are removed from the caps if %FALSE is returned + * from the function. + * The caps must be mutable. + * + * Since: 1.6 + */ +void +gst_caps_filter_and_map_in_place (GstCaps * caps, GstCapsFilterMapFunc func, + gpointer user_data) +{ + guint i, n; + GstCapsFeatures *features; + GstStructure *structure; + gboolean ret; + + g_return_if_fail (GST_IS_CAPS (caps)); + g_return_if_fail (gst_caps_is_writable (caps)); + g_return_if_fail (func != NULL); + + n = GST_CAPS_LEN (caps); + + for (i = 0; i < n;) { + features = gst_caps_get_features_unchecked (caps, i); + structure = gst_caps_get_structure_unchecked (caps, i); + + /* Provide sysmem features if there are none yet */ + if (!features) { + features = + gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY); + gst_caps_set_features (caps, i, features); + } + + ret = func (features, structure, user_data); + if (!ret) { + GST_CAPS_ARRAY (caps) = g_array_remove_index (GST_CAPS_ARRAY (caps), i); + + gst_structure_set_parent_refcount (structure, NULL); + gst_structure_free (structure); + if (features) { + gst_caps_features_set_parent_refcount (features, NULL); + gst_caps_features_free (features); + } + + n = GST_CAPS_LEN (caps); + } else { + i++; + } + } +} diff --git a/gst/gstcaps.h b/gst/gstcaps.h new file mode 100644 index 0000000..4730fd0 --- /dev/null +++ b/gst/gstcaps.h @@ -0,0 +1,575 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CAPS_H__ +#define __GST_CAPS_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_caps_type; + +#define GST_TYPE_CAPS (_gst_caps_type) +#define GST_IS_CAPS(obj) (GST_IS_MINI_OBJECT_TYPE((obj), GST_TYPE_CAPS)) +#define GST_CAPS_CAST(obj) ((GstCaps*)(obj)) +#define GST_CAPS(obj) (GST_CAPS_CAST(obj)) + +#define GST_TYPE_STATIC_CAPS (gst_static_caps_get_type()) + +/** + * GstCapsFlags: + * @GST_CAPS_FLAG_ANY: Caps has no specific content, but can contain + * anything. + * + * Extra flags for a caps. + */ +typedef enum { + GST_CAPS_FLAG_ANY = (GST_MINI_OBJECT_FLAG_LAST << 0) +} GstCapsFlags; + +/** + * GstCapsIntersectMode: + * @GST_CAPS_INTERSECT_ZIG_ZAG : Zig-zags over both caps. + * @GST_CAPS_INTERSECT_FIRST : Keeps the first caps order. + * + * Modes of caps intersection + * + * @GST_CAPS_INTERSECT_ZIG_ZAG tries to preserve overall order of both caps + * by iterating on the caps' structures as the following matrix shows: + * |[ + * caps1 + * +------------- + * | 1 2 4 7 + * caps2 | 3 5 8 10 + * | 6 9 11 12 + * ]| + * Used when there is no explicit precedence of one caps over the other. e.g. + * tee's sink pad getcaps function, it will probe its src pad peers' for their + * caps and intersect them with this mode. + * + * @GST_CAPS_INTERSECT_FIRST is useful when an element wants to preserve + * another element's caps priority order when intersecting with its own caps. + * Example: If caps1 is [A, B, C] and caps2 is [E, B, D, A], the result + * would be [A, B], maintaining the first caps priority on the intersection. + */ +typedef enum { + GST_CAPS_INTERSECT_ZIG_ZAG = 0, + GST_CAPS_INTERSECT_FIRST = 1 +} GstCapsIntersectMode; + +/** + * GST_CAPS_ANY: + * + * Means that the element/pad can output 'anything'. Useful for elements + * that output unknown media, such as filesrc. This macro returns a singleton and + * should not be unreffed. + */ +#define GST_CAPS_ANY _gst_caps_any +/** + * GST_CAPS_NONE: + * + * The opposite of %GST_CAPS_ANY: it means that the pad/element outputs an + * undefined media type that can not be detected. This macro returns a singleton + * and should not be unreffed. + */ +#define GST_CAPS_NONE _gst_caps_none + +/** + * GST_STATIC_CAPS_ANY: + * + * Creates a new #GstCaps static caps that matches anything. + * This can be used in pad templates. + */ +#define GST_STATIC_CAPS_ANY GST_STATIC_CAPS("ANY") +/** + * GST_STATIC_CAPS_NONE: + * + * Creates a new #GstCaps static caps that matches nothing. + * This can be used in pad templates. + */ +#define GST_STATIC_CAPS_NONE GST_STATIC_CAPS("NONE") + +/** + * GST_CAPS_IS_SIMPLE: + * @caps: the #GstCaps instance to check + * + * Convenience macro that checks if the number of structures in the given caps + * is exactly one. + */ +#define GST_CAPS_IS_SIMPLE(caps) (gst_caps_get_size(caps) == 1) + +/** + * GST_STATIC_CAPS: + * @string: the string describing the caps + * + * Creates a new #GstCaps static caps from an input string. + * This can be used in pad templates. + */ +#define GST_STATIC_CAPS(string) \ +{ \ + /* caps */ NULL, \ + /* string */ string, \ + GST_PADDING_INIT \ +} + +typedef struct _GstCaps GstCaps; +typedef struct _GstStaticCaps GstStaticCaps; + +GST_API GstCaps * _gst_caps_any; + +GST_API GstCaps * _gst_caps_none; +/** + * GST_CAPS_FLAGS: + * @caps: a #GstCaps. + * + * A flags word containing #GstCapsFlags flags set on this caps. + */ +#define GST_CAPS_FLAGS(caps) GST_MINI_OBJECT_FLAGS(caps) + +/* refcount */ +/** + * GST_CAPS_REFCOUNT: + * @caps: a #GstCaps + * + * Get access to the reference count field of the caps + */ +#define GST_CAPS_REFCOUNT(caps) GST_MINI_OBJECT_REFCOUNT(caps) +/** + * GST_CAPS_REFCOUNT_VALUE: + * @caps: a #GstCaps + * + * Get the reference count value of the caps. + */ +#define GST_CAPS_REFCOUNT_VALUE(caps) GST_MINI_OBJECT_REFCOUNT_VALUE(caps) + +/** + * GST_CAPS_FLAG_IS_SET: + * @caps: a #GstCaps. + * @flag: the #GstCapsFlags to check. + * + * Gives the status of a specific flag on a caps. + */ +#define GST_CAPS_FLAG_IS_SET(caps,flag) GST_MINI_OBJECT_FLAG_IS_SET (caps, flag) +/** + * GST_CAPS_FLAG_SET: + * @caps: a #GstCaps. + * @flag: the #GstCapsFlags to set. + * + * Sets a caps flag on a caps. + */ +#define GST_CAPS_FLAG_SET(caps,flag) GST_MINI_OBJECT_FLAG_SET (caps, flag) +/** + * GST_CAPS_FLAG_UNSET: + * @caps: a #GstCaps. + * @flag: the #GstCapsFlags to clear. + * + * Clears a caps flag. + */ +#define GST_CAPS_FLAG_UNSET(caps,flag) GST_MINI_OBJECT_FLAG_UNSET (caps, flag) + +/* refcounting */ +/** + * gst_caps_ref: + * @caps: the #GstCaps to reference + * + * Add a reference to a #GstCaps object. + * + * From this point on, until the caller calls gst_caps_unref() or + * gst_caps_make_writable(), it is guaranteed that the caps object will not + * change. This means its structures won't change, etc. To use a #GstCaps + * object, you must always have a refcount on it -- either the one made + * implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with + * this function. + * + * Returns: the same #GstCaps object. + */ +static inline GstCaps * +gst_caps_ref (GstCaps * caps) +{ + return (GstCaps *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps)); +} + +/** + * gst_caps_unref: + * @caps: a #GstCaps. + * + * Unref a #GstCaps and and free all its structures and the + * structures' values when the refcount reaches 0. + */ +static inline void +gst_caps_unref (GstCaps * caps) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps)); +} + +/* copy caps */ +/** + * gst_caps_copy: + * @caps: a #GstCaps. + * + * Creates a new #GstCaps as a copy of the old @caps. The new caps will have a + * refcount of 1, owned by the caller. The structures are copied as well. + * + * Note that this function is the semantic equivalent of a gst_caps_ref() + * followed by a gst_caps_make_writable(). If you only want to hold on to a + * reference to the data, you should use gst_caps_ref(). + * + * When you are finished with the caps, call gst_caps_unref() on it. + * + * Returns: the new #GstCaps + */ +static inline GstCaps * +gst_caps_copy (const GstCaps * caps) +{ + return GST_CAPS (gst_mini_object_copy (GST_MINI_OBJECT_CAST (caps))); +} + +/** + * gst_caps_is_writable: + * @caps: a #GstCaps + * + * Tests if you can safely modify @caps. It is only safe to modify caps when + * there is only one owner of the caps - ie, the object is writable. + */ +#define gst_caps_is_writable(caps) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (caps)) + +/** + * gst_caps_make_writable: + * @caps: (transfer full): a #GstCaps + * + * Returns a writable copy of @caps. + * + * If there is only one reference count on @caps, the caller must be the owner, + * and so this function will return the caps object unchanged. If on the other + * hand there is more than one reference on the object, a new caps object will + * be returned. The caller's reference on @caps will be removed, and instead the + * caller will own a reference to the returned object. + * + * In short, this function unrefs the caps in the argument and refs the caps + * that it returns. Don't access the argument after calling this function. See + * also: gst_caps_ref(). + * + * Returns: (transfer full): a writable caps which may or may not be the + * same as @caps + */ +#define gst_caps_make_writable(caps) GST_CAPS_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (caps))) + +/** + * gst_caps_replace: + * @old_caps: (inout) (transfer full) (nullable): pointer to a pointer + * to a #GstCaps to be replaced. + * @new_caps: (transfer none) (allow-none): pointer to a #GstCaps that will + * replace the caps pointed to by @old_caps. + * + * Modifies a pointer to a #GstCaps to point to a different #GstCaps. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * caps is unreffed, the new is reffed). + * + * Either @new_caps or the #GstCaps pointed to by @old_caps may be %NULL. + * + * Returns: %TRUE if @new_caps was different from @old_caps + */ +static inline gboolean +gst_caps_replace (GstCaps **old_caps, GstCaps *new_caps) +{ + return gst_mini_object_replace ((GstMiniObject **) old_caps, (GstMiniObject *) new_caps); +} + +/** + * gst_caps_take: + * @old_caps: (inout) (transfer full): pointer to a pointer to a #GstCaps to be + * replaced. + * @new_caps: (transfer full) (allow-none): pointer to a #GstCaps that will + * replace the caps pointed to by @old_caps. + * + * Modifies a pointer to a #GstCaps to point to a different #GstCaps. This + * function is similar to gst_caps_replace() except that it takes ownership + * of @new_caps. + * + * Returns: %TRUE if @new_caps was different from @old_caps + */ +static inline gboolean +gst_caps_take (GstCaps **old_caps, GstCaps *new_caps) +{ + return gst_mini_object_take ((GstMiniObject **) old_caps, (GstMiniObject *) new_caps); +} + +/** + * GstCaps: + * @mini_object: the parent type + * + * Object describing media types. + */ +struct _GstCaps { + GstMiniObject mini_object; +}; + +/** + * GstStaticCaps: + * @caps: the cached #GstCaps + * @string: a string describing a caps + * + * Datastructure to initialize #GstCaps from a string description usually + * used in conjunction with GST_STATIC_CAPS() and gst_static_caps_get() to + * instantiate a #GstCaps. + */ +struct _GstStaticCaps { + /*< public >*/ + GstCaps *caps; + const char *string; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstCapsForeachFunc: + * @features: the #GstCapsFeatures + * @structure: the #GstStructure + * @user_data: user data + * + * A function that will be called in gst_caps_foreach(). The function may + * not modify @features or @structure. + * + * Returns: %TRUE if the foreach operation should continue, %FALSE if + * the foreach operation should stop with %FALSE. + * + * Since: 1.6 + */ +typedef gboolean (*GstCapsForeachFunc) (GstCapsFeatures *features, + GstStructure *structure, + gpointer user_data); + +/** + * GstCapsMapFunc: + * @features: the #GstCapsFeatures + * @structure: the #GstStructure + * @user_data: user data + * + * A function that will be called in gst_caps_map_in_place(). The function + * may modify @features and @structure. + * + * Returns: %TRUE if the map operation should continue, %FALSE if + * the map operation should stop with %FALSE. + */ +typedef gboolean (*GstCapsMapFunc) (GstCapsFeatures *features, + GstStructure *structure, + gpointer user_data); + +/** + * GstCapsFilterMapFunc: + * @features: the #GstCapsFeatures + * @structure: the #GstStructure + * @user_data: user data + * + * A function that will be called in gst_caps_filter_and_map_in_place(). + * The function may modify @features and @structure, and both will be + * removed from the caps if %FALSE is returned. + * + * Returns: %TRUE if the features and structure should be preserved, + * %FALSE if it should be removed. + */ +typedef gboolean (*GstCapsFilterMapFunc) (GstCapsFeatures *features, + GstStructure *structure, + gpointer user_data); + + +GST_API +GType gst_caps_get_type (void); + +GST_API +GstCaps * gst_caps_new_empty (void); + +GST_API +GstCaps * gst_caps_new_any (void); + +GST_API +GstCaps * gst_caps_new_empty_simple (const char *media_type) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +GstCaps * gst_caps_new_simple (const char *media_type, + const char *fieldname, + ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_new_full (GstStructure *struct1, + ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_new_full_valist (GstStructure *structure, + va_list var_args) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GType gst_static_caps_get_type (void); + +GST_API +GstCaps * gst_static_caps_get (GstStaticCaps *static_caps); + +GST_API +void gst_static_caps_cleanup (GstStaticCaps *static_caps); + +/* manipulation */ + +GST_API +void gst_caps_append (GstCaps *caps1, + GstCaps *caps2); +GST_API +void gst_caps_append_structure (GstCaps *caps, + GstStructure *structure); +GST_API +void gst_caps_append_structure_full (GstCaps *caps, + GstStructure *structure, + GstCapsFeatures *features); +GST_API +void gst_caps_remove_structure (GstCaps *caps, guint idx); + +GST_API +GstCaps * gst_caps_merge (GstCaps *caps1, + GstCaps *caps2) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_merge_structure (GstCaps *caps, + GstStructure *structure) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_merge_structure_full (GstCaps *caps, + GstStructure *structure, + GstCapsFeatures *features) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +guint gst_caps_get_size (const GstCaps *caps); + +GST_API +GstStructure * gst_caps_get_structure (const GstCaps *caps, + guint index); +GST_API +GstStructure * gst_caps_steal_structure (GstCaps *caps, + guint index) G_GNUC_WARN_UNUSED_RESULT; +GST_API +void gst_caps_set_features (GstCaps *caps, + guint index, + GstCapsFeatures * features); +GST_API +GstCapsFeatures * gst_caps_get_features (const GstCaps *caps, + guint index); +GST_API +GstCaps * gst_caps_copy_nth (const GstCaps *caps, guint nth) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +GstCaps * gst_caps_truncate (GstCaps *caps) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +void gst_caps_set_value (GstCaps *caps, + const char *field, + const GValue *value); +GST_API +void gst_caps_set_simple (GstCaps *caps, + const char *field, ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_caps_set_simple_valist (GstCaps *caps, + const char *field, + va_list varargs); +GST_API +gboolean gst_caps_foreach (const GstCaps *caps, + GstCapsForeachFunc func, + gpointer user_data); +GST_API +gboolean gst_caps_map_in_place (GstCaps *caps, + GstCapsMapFunc func, + gpointer user_data); +GST_API +void gst_caps_filter_and_map_in_place (GstCaps *caps, + GstCapsFilterMapFunc func, + gpointer user_data); + +/* tests */ + +GST_API +gboolean gst_caps_is_any (const GstCaps *caps); + +GST_API +gboolean gst_caps_is_empty (const GstCaps *caps); + +GST_API +gboolean gst_caps_is_fixed (const GstCaps *caps); + +GST_API +gboolean gst_caps_is_always_compatible (const GstCaps *caps1, + const GstCaps *caps2); +GST_API +gboolean gst_caps_is_subset (const GstCaps *subset, + const GstCaps *superset); +GST_API +gboolean gst_caps_is_subset_structure (const GstCaps *caps, + const GstStructure *structure); +GST_API +gboolean gst_caps_is_subset_structure_full (const GstCaps *caps, + const GstStructure *structure, + const GstCapsFeatures *features); +GST_API +gboolean gst_caps_is_equal (const GstCaps *caps1, + const GstCaps *caps2); +GST_API +gboolean gst_caps_is_equal_fixed (const GstCaps *caps1, + const GstCaps *caps2); +GST_API +gboolean gst_caps_can_intersect (const GstCaps * caps1, + const GstCaps * caps2); +GST_API +gboolean gst_caps_is_strictly_equal (const GstCaps *caps1, + const GstCaps *caps2); + + +/* operations */ + +GST_API +GstCaps * gst_caps_intersect (GstCaps *caps1, + GstCaps *caps2) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_intersect_full (GstCaps *caps1, + GstCaps *caps2, + GstCapsIntersectMode mode) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_subtract (GstCaps *minuend, + GstCaps *subtrahend) G_GNUC_WARN_UNUSED_RESULT; +GST_API +GstCaps * gst_caps_normalize (GstCaps *caps) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +GstCaps * gst_caps_simplify (GstCaps *caps) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +GstCaps * gst_caps_fixate (GstCaps *caps) G_GNUC_WARN_UNUSED_RESULT; + +/* utility */ + +GST_API +gchar * gst_caps_to_string (const GstCaps *caps) G_GNUC_MALLOC; + +GST_API +GstCaps * gst_caps_from_string (const gchar *string) G_GNUC_WARN_UNUSED_RESULT; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCaps, gst_caps_unref) +#endif + +G_END_DECLS + +#endif /* __GST_CAPS_H__ */ diff --git a/gst/gstcapsfeatures.c b/gst/gstcapsfeatures.c new file mode 100644 index 0000000..9215de8 --- /dev/null +++ b/gst/gstcapsfeatures.c @@ -0,0 +1,871 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcapsfeatures + * @title: GstCapsFeatures + * @short_description: A set of features in caps + * @see_also: #GstCaps + * + * #GstCapsFeatures can optionally be set on a #GstCaps to add requirements + * for additional features for a specific #GstStructure. Caps structures with + * the same name but with a non-equal set of caps features are not compatible. + * If a pad supports multiple sets of features it has to add multiple equal + * structures with different feature sets to the caps. + * + * Empty #GstCapsFeatures are equivalent with the #GstCapsFeatures that only + * contain #GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY. ANY #GstCapsFeatures as + * created by gst_caps_features_new_any() are equal to any other #GstCapsFeatures + * and can be used to specify that any #GstCapsFeatures would be supported, e.g. + * for elements that don't touch buffer memory. #GstCaps with ANY #GstCapsFeatures + * are considered non-fixed and during negotiation some #GstCapsFeatures have + * to be selected. + * + * Examples for caps features would be the requirement of a specific #GstMemory + * types or the requirement of having a specific #GstMeta on the buffer. Features + * are given as a string of the format "memory:GstMemoryTypeName" or + * "meta:GstMetaAPIName". + * + * Since: 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gst_private.h" +#include "gstcapsfeatures.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_caps_features_debug); +#define GST_CAT_DEFAULT gst_caps_features_debug + +struct _GstCapsFeatures +{ + GType type; + gint *parent_refcount; + GArray *array; + gboolean is_any; +}; + +GType _gst_caps_features_type = 0; +static gint static_caps_features_parent_refcount = G_MAXINT; +GstCapsFeatures *_gst_caps_features_any = NULL; +GstCapsFeatures *_gst_caps_features_memory_system_memory = NULL; +static GQuark _gst_caps_feature_memory_system_memory = 0; + +G_DEFINE_BOXED_TYPE (GstCapsFeatures, gst_caps_features, + gst_caps_features_copy, gst_caps_features_free); + +#define IS_MUTABLE(features) \ + (!features->parent_refcount || \ + g_atomic_int_get (features->parent_refcount) == 1) + +static void +gst_caps_features_transform_to_string (const GValue * src_value, + GValue * dest_value); + +void +_priv_gst_caps_features_initialize (void) +{ + GST_DEBUG_CATEGORY_INIT (gst_caps_features_debug, "caps-features", 0, + "GstCapsFeatures debug"); + + _gst_caps_features_type = gst_caps_features_get_type (); + _gst_caps_feature_memory_system_memory = + g_quark_from_static_string (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); + + g_value_register_transform_func (_gst_caps_features_type, G_TYPE_STRING, + gst_caps_features_transform_to_string); + + _gst_caps_features_any = gst_caps_features_new_any (); + gst_caps_features_set_parent_refcount (_gst_caps_features_any, + &static_caps_features_parent_refcount); + _gst_caps_features_memory_system_memory = + gst_caps_features_new_id (_gst_caps_feature_memory_system_memory, 0); + gst_caps_features_set_parent_refcount + (_gst_caps_features_memory_system_memory, + &static_caps_features_parent_refcount); +} + +void +_priv_gst_caps_features_cleanup (void) +{ + gst_caps_features_set_parent_refcount (_gst_caps_features_any, NULL); + gst_caps_features_free (_gst_caps_features_any); + _gst_caps_features_any = NULL; + gst_caps_features_set_parent_refcount + (_gst_caps_features_memory_system_memory, NULL); + gst_caps_features_free (_gst_caps_features_memory_system_memory); + _gst_caps_features_memory_system_memory = NULL; +} + +gboolean +gst_is_caps_features (gconstpointer obj) +{ + const GstCapsFeatures *features = obj; + + return (obj != NULL && features->type == _gst_caps_features_type); +} + +static gboolean +gst_caps_feature_name_is_valid (const gchar * feature) +{ +#ifndef G_DISABLE_CHECKS + while (TRUE) { + if (g_ascii_isalpha (*feature)) + feature++; + else if (*feature == ':') + break; + else + return FALSE; + } + + if (*feature != ':') + return FALSE; + + feature++; + if (*feature == '\0' || !g_ascii_isalpha (*feature)) + return FALSE; + + while (TRUE) { + if (g_ascii_isalnum (*feature)) + feature++; + else if (*feature == '\0') + break; + else + return FALSE; + } +#endif + + return TRUE; +} + +/** + * gst_caps_features_new_empty: + * + * Creates a new, empty #GstCapsFeatures. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, empty #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new_empty (void) +{ + GstCapsFeatures *features; + + features = g_slice_new (GstCapsFeatures); + features->type = _gst_caps_features_type; + features->parent_refcount = NULL; + features->array = g_array_new (FALSE, FALSE, sizeof (GQuark)); + features->is_any = FALSE; + + GST_TRACE ("created caps features %p", features); + + return features; +} + +/** + * gst_caps_features_new_any: + * + * Creates a new, ANY #GstCapsFeatures. This will be equal + * to any other #GstCapsFeatures but caps with these are + * unfixed. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, ANY #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new_any (void) +{ + GstCapsFeatures *features; + + features = gst_caps_features_new_empty (); + features->is_any = TRUE; + + return features; +} + +/** + * gst_caps_features_new: + * @feature1: name of first feature to set + * @...: additional features + * + * Creates a new #GstCapsFeatures with the given features. + * The last argument must be %NULL. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, empty #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new (const gchar * feature1, ...) +{ + GstCapsFeatures *features; + va_list varargs; + + g_return_val_if_fail (feature1 != NULL, NULL); + + va_start (varargs, feature1); + features = gst_caps_features_new_valist (feature1, varargs); + va_end (varargs); + + return features; +} + +/** + * gst_caps_features_new_valist: + * @feature1: name of first feature to set + * @varargs: variable argument list + * + * Creates a new #GstCapsFeatures with the given features. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, empty #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new_valist (const gchar * feature1, va_list varargs) +{ + GstCapsFeatures *features; + + g_return_val_if_fail (feature1 != NULL, NULL); + + features = gst_caps_features_new_empty (); + + while (feature1) { + gst_caps_features_add (features, feature1); + feature1 = va_arg (varargs, const gchar *); + } + + return features; +} + +/** + * gst_caps_features_new_id: + * @feature1: name of first feature to set + * @...: additional features + * + * Creates a new #GstCapsFeatures with the given features. + * The last argument must be 0. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, empty #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new_id (GQuark feature1, ...) +{ + GstCapsFeatures *features; + va_list varargs; + + g_return_val_if_fail (feature1 != 0, NULL); + + va_start (varargs, feature1); + features = gst_caps_features_new_id_valist (feature1, varargs); + va_end (varargs); + + return features; +} + +/** + * gst_caps_features_new_id_valist: + * @feature1: name of first feature to set + * @varargs: variable argument list + * + * Creates a new #GstCapsFeatures with the given features. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new, empty #GstCapsFeatures + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_new_id_valist (GQuark feature1, va_list varargs) +{ + GstCapsFeatures *features; + + g_return_val_if_fail (feature1 != 0, NULL); + + features = gst_caps_features_new_empty (); + + while (feature1) { + gst_caps_features_add_id (features, feature1); + feature1 = va_arg (varargs, GQuark); + } + + return features; +} + +/** + * gst_caps_features_set_parent_refcount: + * @features: a #GstCapsFeatures + * @refcount: (in): a pointer to the parent's refcount + * + * Sets the parent_refcount field of #GstCapsFeatures. This field is used to + * determine whether a caps features is mutable or not. This function should only be + * called by code implementing parent objects of #GstCapsFeatures, as described in + * the MT Refcounting section of the design documents. + * + * Returns: %TRUE if the parent refcount could be set. + * + * Since: 1.2 + */ +gboolean +gst_caps_features_set_parent_refcount (GstCapsFeatures * features, + gint * refcount) +{ + g_return_val_if_fail (features != NULL, FALSE); + + /* if we have a parent_refcount already, we can only clear + * if with a NULL refcount */ + if (features->parent_refcount) { + if (refcount != NULL) { + g_return_val_if_fail (refcount == NULL, FALSE); + return FALSE; + } + } else { + if (refcount == NULL) { + g_return_val_if_fail (refcount != NULL, FALSE); + return FALSE; + } + } + + features->parent_refcount = refcount; + + return TRUE; +} + +/** + * gst_caps_features_copy: + * @features: a #GstCapsFeatures to duplicate + * + * Duplicates a #GstCapsFeatures and all its values. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full): a new #GstCapsFeatures. + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_copy (const GstCapsFeatures * features) +{ + GstCapsFeatures *copy; + guint i, n; + + g_return_val_if_fail (features != NULL, NULL); + + copy = gst_caps_features_new_empty (); + n = gst_caps_features_get_size (features); + for (i = 0; i < n; i++) + gst_caps_features_add_id (copy, gst_caps_features_get_nth_id (features, i)); + copy->is_any = features->is_any; + + return copy; +} + +/** + * gst_caps_features_free: + * @features: (in) (transfer full): the #GstCapsFeatures to free + * + * Frees a #GstCapsFeatures and all its values. The caps features must not + * have a parent when this function is called. + * + * Since: 1.2 + */ +void +gst_caps_features_free (GstCapsFeatures * features) +{ + g_return_if_fail (features != NULL); + g_return_if_fail (features->parent_refcount == NULL); + + g_array_free (features->array, TRUE); +#ifdef USE_POISONING + memset (features, 0xff, sizeof (GstCapsFeatures)); +#endif + GST_TRACE ("free caps features %p", features); + + g_slice_free (GstCapsFeatures, features); +} + +/** + * gst_caps_features_to_string: + * @features: a #GstCapsFeatures + * + * Converts @features to a human-readable string representation. + * + * For debugging purposes its easier to do something like this: + * |[ + * GST_LOG ("features is %" GST_PTR_FORMAT, features); + * ]| + * This prints the features in human readable form. + * + * Free-function: g_free + * + * Returns: (transfer full): a pointer to string allocated by g_malloc(). + * g_free() after usage. + * + * Since: 1.2 + */ +gchar * +gst_caps_features_to_string (const GstCapsFeatures * features) +{ + GString *s; + + g_return_val_if_fail (features != NULL, NULL); + + s = g_string_sized_new (FEATURES_ESTIMATED_STRING_LEN (features)); + + priv_gst_caps_features_append_to_gstring (features, s); + + return g_string_free (s, FALSE); +} + +void +priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features, + GString * s) +{ + guint i, n; + + g_return_if_fail (features != NULL); + + if (features->array->len == 0 && features->is_any) { + g_string_append (s, "ANY"); + return; + } + + n = features->array->len; + for (i = 0; i < n; i++) { + GQuark *quark = &g_array_index (features->array, GQuark, i); + + g_string_append (s, g_quark_to_string (*quark)); + if (i + 1 < n) + g_string_append (s, ", "); + } +} + +/** + * gst_caps_features_from_string: + * @features: a string representation of a #GstCapsFeatures. + * + * Creates a #GstCapsFeatures from a string representation. + * + * Free-function: gst_caps_features_free + * + * Returns: (transfer full) (nullable): a new #GstCapsFeatures or + * %NULL when the string could not be parsed. Free with + * gst_caps_features_free() after use. + * + * Since: 1.2 + */ +GstCapsFeatures * +gst_caps_features_from_string (const gchar * features) +{ + GstCapsFeatures *ret; + gboolean escape = FALSE; + const gchar *features_orig = features; + const gchar *feature; + + ret = gst_caps_features_new_empty (); + + if (!features || *features == '\0') + return ret; + + if (strcmp (features, "ANY") == 0) { + ret->is_any = TRUE; + return ret; + } + + /* Skip trailing spaces */ + while (*features == ' ') + features++; + + feature = features; + while (TRUE) { + gchar c = *features; + + if (c == '\\') { + escape = TRUE; + features++; + continue; + } else if ((!escape && c == ',') || c == '\0') { + guint len = features - feature + 1; + gchar *tmp; + gchar *p; + + if (len == 1) { + g_warning ("Failed deserialize caps features '%s'", features_orig); + gst_caps_features_free (ret); + return NULL; + } + + tmp = g_malloc (len); + memcpy (tmp, feature, len - 1); + tmp[len - 1] = '\0'; + + p = tmp + len - 1; + while (*p == ' ') { + *p = '\0'; + p--; + } + + if (strstr (tmp, " ") != NULL || *tmp == '\0') { + g_free (tmp); + g_warning ("Failed deserialize caps features '%s'", features_orig); + gst_caps_features_free (ret); + return NULL; + } + + gst_caps_features_add (ret, tmp); + g_free (tmp); + + if (c == '\0') + break; + + /* Skip to the next value */ + features++; + while (*features == ' ') + features++; + feature = features; + } else { + escape = FALSE; + features++; + } + } + + return ret; +} + +/** + * gst_caps_features_get_size: + * @features: a #GstCapsFeatures. + * + * Returns the number of features in @features. + * + * Returns: The number of features in @features. + * + * Since: 1.2 + */ +guint +gst_caps_features_get_size (const GstCapsFeatures * features) +{ + g_return_val_if_fail (features != NULL, 0); + + return features->array->len; +} + +/** + * gst_caps_features_get_nth: + * @features: a #GstCapsFeatures. + * @i: index of the feature + * + * Returns the @i-th feature of @features. + * + * Returns: (nullable): The @i-th feature of @features. + * + * Since: 1.2 + */ +const gchar * +gst_caps_features_get_nth (const GstCapsFeatures * features, guint i) +{ + const gchar *feature; + GQuark quark; + + g_return_val_if_fail (features != NULL, NULL); + + quark = gst_caps_features_get_nth_id (features, i); + if (!quark) + return NULL; + + feature = g_quark_to_string (quark); + return feature; +} + +/** + * gst_caps_features_get_nth_id: + * @features: a #GstCapsFeatures. + * @i: index of the feature + * + * Returns the @i-th feature of @features. + * + * Returns: The @i-th feature of @features. + * + * Since: 1.2 + */ +GQuark +gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i) +{ + GQuark *quark; + + g_return_val_if_fail (features != NULL, 0); + g_return_val_if_fail (i < features->array->len, 0); + + quark = &g_array_index (features->array, GQuark, i); + + return *quark; +} + +/** + * gst_caps_features_contains: + * @features: a #GstCapsFeatures. + * @feature: a feature + * + * Check if @features contains @feature. + * + * Returns: %TRUE if @features contains @feature. + * + * Since: 1.2 + */ +gboolean +gst_caps_features_contains (const GstCapsFeatures * features, + const gchar * feature) +{ + g_return_val_if_fail (features != NULL, FALSE); + g_return_val_if_fail (feature != NULL, FALSE); + + return gst_caps_features_contains_id (features, + g_quark_from_string (feature)); +} + +/** + * gst_caps_features_contains_id: + * @features: a #GstCapsFeatures. + * @feature: a feature + * + * Check if @features contains @feature. + * + * Returns: %TRUE if @features contains @feature. + * + * Since: 1.2 + */ +gboolean +gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature) +{ + guint i, n; + + g_return_val_if_fail (features != NULL, FALSE); + g_return_val_if_fail (feature != 0, FALSE); + + if (features->is_any) + return TRUE; + + n = features->array->len; + if (n == 0) + return feature == _gst_caps_feature_memory_system_memory; + + for (i = 0; i < n; i++) { + if (gst_caps_features_get_nth_id (features, i) == feature) + return TRUE; + } + + return FALSE; +} + +/** + * gst_caps_features_is_equal: + * @features1: a #GstCapsFeatures. + * @features2: a #GstCapsFeatures. + * + * Check if @features1 and @features2 are equal. + * + * Returns: %TRUE if @features1 and @features2 are equal. + * + * Since: 1.2 + */ +gboolean +gst_caps_features_is_equal (const GstCapsFeatures * features1, + const GstCapsFeatures * features2) +{ + guint i, n; + + g_return_val_if_fail (features1 != NULL, FALSE); + g_return_val_if_fail (features2 != NULL, FALSE); + + if (features1->is_any || features2->is_any) + return TRUE; + + /* Check for the sysmem==empty case */ + if (features1->array->len == 0 && features2->array->len == 0) + return TRUE; + if (features1->array->len == 0 && features2->array->len == 1 + && gst_caps_features_contains_id (features2, + _gst_caps_feature_memory_system_memory)) + return TRUE; + if (features2->array->len == 0 && features1->array->len == 1 + && gst_caps_features_contains_id (features1, + _gst_caps_feature_memory_system_memory)) + return TRUE; + + if (features1->array->len != features2->array->len) + return FALSE; + + n = features1->array->len; + for (i = 0; i < n; i++) + if (!gst_caps_features_contains_id (features2, + gst_caps_features_get_nth_id (features1, i))) + return FALSE; + + return TRUE; +} + +/** + * gst_caps_features_is_any: + * @features: a #GstCapsFeatures. + * + * Check if @features is %GST_CAPS_FEATURES_ANY. + * + * Returns: %TRUE if @features is %GST_CAPS_FEATURES_ANY. + * + * Since: 1.2 + */ +gboolean +gst_caps_features_is_any (const GstCapsFeatures * features) +{ + g_return_val_if_fail (features != NULL, FALSE); + + return features->is_any; +} + +/** + * gst_caps_features_add: + * @features: a #GstCapsFeatures. + * @feature: a feature. + * + * Adds @feature to @features. + * + * Since: 1.2 + */ +void +gst_caps_features_add (GstCapsFeatures * features, const gchar * feature) +{ + g_return_if_fail (features != NULL); + g_return_if_fail (IS_MUTABLE (features)); + g_return_if_fail (feature != NULL); + g_return_if_fail (!features->is_any); + + gst_caps_features_add_id (features, g_quark_from_string (feature)); +} + +/** + * gst_caps_features_add_id: + * @features: a #GstCapsFeatures. + * @feature: a feature. + * + * Adds @feature to @features. + * + * Since: 1.2 + */ +void +gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature) +{ + g_return_if_fail (features != NULL); + g_return_if_fail (IS_MUTABLE (features)); + g_return_if_fail (feature != 0); + g_return_if_fail (!features->is_any); + + if (!gst_caps_feature_name_is_valid (g_quark_to_string (feature))) { + g_warning ("Invalid caps feature name: %s", g_quark_to_string (feature)); + return; + } + + /* If features is empty it will contain sysmem, however + * we want to add it explicitely if it is tried to be + * added as first features + */ + if (features->array->len > 0 + && gst_caps_features_contains_id (features, feature)) + return; + + g_array_append_val (features->array, feature); +} + +/** + * gst_caps_features_remove: + * @features: a #GstCapsFeatures. + * @feature: a feature. + * + * Removes @feature from @features. + * + * Since: 1.2 + */ +void +gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature) +{ + g_return_if_fail (features != NULL); + g_return_if_fail (IS_MUTABLE (features)); + g_return_if_fail (feature != NULL); + + gst_caps_features_remove_id (features, g_quark_from_string (feature)); +} + +/** + * gst_caps_features_remove_id: + * @features: a #GstCapsFeatures. + * @feature: a feature. + * + * Removes @feature from @features. + * + * Since: 1.2 + */ +void +gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature) +{ + guint i, n; + + g_return_if_fail (features != NULL); + g_return_if_fail (IS_MUTABLE (features)); + g_return_if_fail (feature != 0); + + n = features->array->len; + for (i = 0; i < n; i++) { + GQuark quark = gst_caps_features_get_nth_id (features, i); + + if (quark == feature) { + g_array_remove_index_fast (features->array, i); + return; + } + } +} + +static void +gst_caps_features_transform_to_string (const GValue * src_value, + GValue * dest_value) +{ + g_return_if_fail (src_value != NULL); + g_return_if_fail (dest_value != NULL); + + dest_value->data[0].v_pointer = + gst_caps_features_to_string (src_value->data[0].v_pointer); +} diff --git a/gst/gstcapsfeatures.h b/gst/gstcapsfeatures.h new file mode 100644 index 0000000..4477b28 --- /dev/null +++ b/gst/gstcapsfeatures.h @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CAPS_FEATURES_H__ +#define __GST_CAPS_FEATURES_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstCapsFeatures GstCapsFeatures; + +GST_API GType _gst_caps_features_type; + +#define GST_TYPE_CAPS_FEATURES (_gst_caps_features_type) +#define GST_IS_CAPS_FEATURES(object) (gst_is_caps_features(object)) +#define GST_CAPS_FEATURES_CAST(object) ((GstCapsFeatures *)(object)) +#define GST_CAPS_FEATURES(object) (GST_CAPS_FEATURES_CAST(object)) + +#define GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY "memory:SystemMemory" + +GST_API GstCapsFeatures *_gst_caps_features_any; +#define GST_CAPS_FEATURES_ANY (_gst_caps_features_any) + +GST_API GstCapsFeatures *_gst_caps_features_memory_system_memory; +#define GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY (_gst_caps_features_memory_system_memory) + +GST_API +GType gst_caps_features_get_type (void); + +GST_API +gboolean gst_is_caps_features (gconstpointer obj); + +GST_API +GstCapsFeatures * gst_caps_features_new_empty (void); + +GST_API +GstCapsFeatures * gst_caps_features_new_any (void); + +GST_API +GstCapsFeatures * gst_caps_features_new (const gchar *feature1, ...); + +GST_API +GstCapsFeatures * gst_caps_features_new_valist (const gchar *feature1, va_list varargs); + +GST_API +GstCapsFeatures * gst_caps_features_new_id (GQuark feature1, ...); + +GST_API +GstCapsFeatures * gst_caps_features_new_id_valist (GQuark feature1, va_list varargs); + +GST_API +gboolean gst_caps_features_set_parent_refcount (GstCapsFeatures *features, gint * refcount); + +GST_API +GstCapsFeatures * gst_caps_features_copy (const GstCapsFeatures * features); + +GST_API +void gst_caps_features_free (GstCapsFeatures * features); + +GST_API +gchar * gst_caps_features_to_string (const GstCapsFeatures * features); + +GST_API +GstCapsFeatures * gst_caps_features_from_string (const gchar * features); + +GST_API +guint gst_caps_features_get_size (const GstCapsFeatures * features); + +GST_API +const gchar * gst_caps_features_get_nth (const GstCapsFeatures * features, guint i); + +GST_API +GQuark gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i); + +GST_API +gboolean gst_caps_features_contains (const GstCapsFeatures * features, const gchar * feature); + +GST_API +gboolean gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature); + +GST_API +gboolean gst_caps_features_is_equal (const GstCapsFeatures * features1, const GstCapsFeatures * features2); + +GST_API +gboolean gst_caps_features_is_any (const GstCapsFeatures * features); + +GST_API +void gst_caps_features_add (GstCapsFeatures * features, const gchar * feature); + +GST_API +void gst_caps_features_add_id ( GstCapsFeatures * features, GQuark feature); + +GST_API +void gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature); + +GST_API +void gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCapsFeatures, gst_caps_features_free) +#endif + +G_END_DECLS + +#endif /* __GST_CAPS_FEATURES_H__ */ diff --git a/gst/gstchildproxy.c b/gst/gstchildproxy.c new file mode 100644 index 0000000..1bf983a --- /dev/null +++ b/gst/gstchildproxy.c @@ -0,0 +1,585 @@ +/* GStreamer + * Copyright (C) 2005 Stefan Kost + * + * gstchildproxy.c: interface for multi child 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstchildproxy + * @title: GstChildProxy + * @short_description: Interface for multi child elements. + * @see_also: #GstBin + * + * This interface abstracts handling of property sets for elements with + * children. Imagine elements such as mixers or polyphonic generators. They all + * have multiple #GstPad or some kind of voice objects. Another use case are + * container elements like #GstBin. + * The element implementing the interface acts as a parent for those child + * objects. + * + * By implementing this interface the child properties can be accessed from the + * parent element by using gst_child_proxy_get() and gst_child_proxy_set(). + * + * Property names are written as "child-name::property-name". The whole naming + * scheme is recursive. Thus "child1::child2::property" is valid too, if + * "child1" and "child2" implement the #GstChildProxy interface. + */ + +#include "gst_private.h" + +#include "gstchildproxy.h" +#include + +/* signals */ +enum +{ + CHILD_ADDED, + CHILD_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static GObject * +gst_child_proxy_default_get_child_by_name (GstChildProxy * parent, + const gchar * name) +{ + guint count, i; + GObject *object, *result; + gchar *object_name; + + g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL); + g_return_val_if_fail (name != NULL, NULL); + + result = NULL; + + count = gst_child_proxy_get_children_count (parent); + for (i = 0; i < count; i++) { + gboolean eq; + + if (!(object = gst_child_proxy_get_child_by_index (parent, i))) + continue; + + if (!GST_IS_OBJECT (object)) { + goto next; + } + object_name = gst_object_get_name (GST_OBJECT_CAST (object)); + if (object_name == NULL) { + g_warning ("child %u of parent %s has no name", i, + GST_OBJECT_NAME (parent)); + goto next; + } + eq = g_str_equal (object_name, name); + g_free (object_name); + + if (eq) { + result = object; + break; + } + next: + g_object_unref (object); + } + return result; +} + + +/** + * gst_child_proxy_get_child_by_name: + * @parent: the parent object to get the child from + * @name: the child's name + * + * Looks up a child element by the given name. + * + * This virtual method has a default implementation that uses #GstObject + * together with gst_object_get_name(). If the interface is to be used with + * #GObjects, this methods needs to be overridden. + * + * Returns: (transfer full) (nullable): the child object or %NULL if + * not found. Unref after usage. + * + * MT safe. + */ +GObject * +gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name) +{ + GstChildProxyInterface *iface; + + g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0); + + iface = GST_CHILD_PROXY_GET_INTERFACE (parent); + + if (iface->get_child_by_name != NULL) + return iface->get_child_by_name (parent, name); + + return NULL; +} + +/** + * gst_child_proxy_get_child_by_index: + * @parent: the parent object to get the child from + * @index: the child's position in the child list + * + * Fetches a child by its number. + * + * Returns: (transfer full) (nullable): the child object or %NULL if + * not found (index too high). Unref after usage. + * + * MT safe. + */ +GObject * +gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index) +{ + GstChildProxyInterface *iface; + + g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL); + + iface = GST_CHILD_PROXY_GET_INTERFACE (parent); + + if (iface->get_child_by_index != NULL) + return iface->get_child_by_index (parent, index); + + return NULL; +} + +/** + * gst_child_proxy_get_children_count: + * @parent: the parent object + * + * Gets the number of child objects this parent contains. + * + * Returns: the number of child objects + * + * MT safe. + */ +guint +gst_child_proxy_get_children_count (GstChildProxy * parent) +{ + GstChildProxyInterface *iface; + + g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0); + + iface = GST_CHILD_PROXY_GET_INTERFACE (parent); + + if (iface->get_children_count != NULL) + return iface->get_children_count (parent); + + return 0; +} + +/** + * gst_child_proxy_lookup: + * @object: child proxy object to lookup the property in + * @name: name of the property to look up + * @target: (out) (allow-none) (transfer full): pointer to a #GObject that + * takes the real object to set property on + * @pspec: (out) (allow-none) (transfer none): pointer to take the #GParamSpec + * describing the property + * + * Looks up which object and #GParamSpec would be effected by the given @name. + * + * MT safe. + * + * Returns: %TRUE if @target and @pspec could be found. %FALSE otherwise. In that + * case the values for @pspec and @target are not modified. Unref @target after + * usage. For plain GObjects @target is the same as @object. + */ +gboolean +gst_child_proxy_lookup (GstChildProxy * object, const gchar * name, + GObject ** target, GParamSpec ** pspec) +{ + GObject *obj; + gboolean res = FALSE; + gchar **names, **current; + + g_return_val_if_fail (GST_IS_CHILD_PROXY (object), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + obj = G_OBJECT (g_object_ref (object)); + + current = names = g_strsplit (name, "::", -1); + /* find the owner of the property */ + while (current[1]) { + GObject *next; + + if (!GST_IS_CHILD_PROXY (obj)) { + GST_INFO + ("object %s is not a parent, so you cannot request a child by name %s", + (GST_IS_OBJECT (obj) ? GST_OBJECT_NAME (obj) : ""), current[0]); + break; + } + next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (obj), + current[0]); + if (!next) { + GST_INFO ("no such object %s", current[0]); + break; + } + g_object_unref (obj); + obj = next; + current++; + } + + /* look for psec */ + if (current[1] == NULL) { + GParamSpec *spec = + g_object_class_find_property (G_OBJECT_GET_CLASS (obj), current[0]); + if (spec == NULL) { + GST_INFO ("no param spec named %s", current[0]); + } else { + if (pspec) + *pspec = spec; + if (target) { + g_object_ref (obj); + *target = obj; + } + res = TRUE; + } + } + g_object_unref (obj); + g_strfreev (names); + return res; +} + +/** + * gst_child_proxy_get_property: + * @object: object to query + * @name: name of the property + * @value: (out caller-allocates): a #GValue that should take the result. + * + * Gets a single property using the GstChildProxy mechanism. + * You are responsible for freeing it by calling g_value_unset() + */ +void +gst_child_proxy_get_property (GstChildProxy * object, const gchar * name, + GValue * value) +{ + GParamSpec *pspec; + GObject *target; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + g_return_if_fail (name != NULL); + g_return_if_fail (G_IS_VALUE (value)); + + if (!gst_child_proxy_lookup (object, name, &target, &pspec)) + goto not_found; + + g_object_get_property (target, pspec->name, value); + g_object_unref (target); + + return; + +not_found: + { + g_warning ("no property %s in object %s", name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); + return; + } +} + +/** + * gst_child_proxy_get_valist: + * @object: the object to query + * @first_property_name: name of the first property to get + * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by %NULL + * + * Gets properties of the parent object and its children. + */ +void +gst_child_proxy_get_valist (GstChildProxy * object, + const gchar * first_property_name, va_list var_args) +{ + const gchar *name; + gchar *error = NULL; + GValue value = { 0, }; + GParamSpec *pspec; + GObject *target; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + + name = first_property_name; + + /* iterate over pairs */ + while (name) { + if (!gst_child_proxy_lookup (object, name, &target, &pspec)) + goto not_found; + + g_value_init (&value, pspec->value_type); + g_object_get_property (target, pspec->name, &value); + g_object_unref (target); + + G_VALUE_LCOPY (&value, var_args, 0, &error); + if (error) + goto cant_copy; + g_value_unset (&value); + name = va_arg (var_args, gchar *); + } + return; + +not_found: + { + g_warning ("no property %s in object %s", name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); + return; + } +cant_copy: + { + g_warning ("error copying value %s in object %s: %s", pspec->name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error); + g_value_unset (&value); + return; + } +} + +/** + * gst_child_proxy_get: + * @object: the parent object + * @first_property_name: name of the first property to get + * @...: return location for the first property, followed optionally by more name/return location pairs, followed by %NULL + * + * Gets properties of the parent object and its children. + */ +void +gst_child_proxy_get (GstChildProxy * object, const gchar * first_property_name, + ...) +{ + va_list var_args; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + + va_start (var_args, first_property_name); + gst_child_proxy_get_valist (object, first_property_name, var_args); + va_end (var_args); +} + +/** + * gst_child_proxy_set_property: + * @object: the parent object + * @name: name of the property to set + * @value: new #GValue for the property + * + * Sets a single property using the GstChildProxy mechanism. + */ +void +gst_child_proxy_set_property (GstChildProxy * object, const gchar * name, + const GValue * value) +{ + GParamSpec *pspec; + GObject *target; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + g_return_if_fail (name != NULL); + g_return_if_fail (G_IS_VALUE (value)); + + if (!gst_child_proxy_lookup (object, name, &target, &pspec)) + goto not_found; + + g_object_set_property (target, pspec->name, value); + g_object_unref (target); + return; + +not_found: + { + g_warning ("cannot set property %s on object %s", name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); + return; + } +} + +/** + * gst_child_proxy_set_valist: + * @object: the parent object + * @first_property_name: name of the first property to set + * @var_args: value for the first property, followed optionally by more name/value pairs, followed by %NULL + * + * Sets properties of the parent object and its children. + */ +void +gst_child_proxy_set_valist (GstChildProxy * object, + const gchar * first_property_name, va_list var_args) +{ + const gchar *name; + gchar *error = NULL; + GValue value = { 0, }; + GParamSpec *pspec; + GObject *target; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + + name = first_property_name; + + /* iterate over pairs */ + while (name) { + if (!gst_child_proxy_lookup (object, name, &target, &pspec)) + goto not_found; + + G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args, + G_VALUE_NOCOPY_CONTENTS, &error); + + if (error) + goto cant_copy; + + g_object_set_property (target, pspec->name, &value); + g_object_unref (target); + + g_value_unset (&value); + name = va_arg (var_args, gchar *); + } + return; + +not_found: + { + g_warning ("no property %s in object %s", name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); + return; + } +cant_copy: + { + g_warning ("error copying value %s in object %s: %s", pspec->name, + (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error); + g_value_unset (&value); + g_object_unref (target); + return; + } +} + +/** + * gst_child_proxy_set: + * @object: the parent object + * @first_property_name: name of the first property to set + * @...: value for the first property, followed optionally by more name/value pairs, followed by %NULL + * + * Sets properties of the parent object and its children. + */ +void +gst_child_proxy_set (GstChildProxy * object, const gchar * first_property_name, + ...) +{ + va_list var_args; + + g_return_if_fail (GST_IS_CHILD_PROXY (object)); + + va_start (var_args, first_property_name); + gst_child_proxy_set_valist (object, first_property_name, var_args); + va_end (var_args); +} + +/** + * gst_child_proxy_child_added: + * @parent: the parent object + * @child: the newly added child + * @name: the name of the new child + * + * Emits the "child-added" signal. + */ +void +gst_child_proxy_child_added (GstChildProxy * parent, GObject * child, + const gchar * name) +{ + g_signal_emit (parent, signals[CHILD_ADDED], 0, child, name); +} + +/** + * gst_child_proxy_child_removed: + * @parent: the parent object + * @child: the removed child + * @name: the name of the old child + * + * Emits the "child-removed" signal. + */ +void +gst_child_proxy_child_removed (GstChildProxy * parent, GObject * child, + const gchar * name) +{ + g_signal_emit (parent, signals[CHILD_REMOVED], 0, child, name); +} + +/* gobject methods */ + +static void +gst_child_proxy_class_init (gpointer g_class, gpointer class_data) +{ + GstChildProxyInterface *iface = (GstChildProxyInterface *) g_class; + + iface->get_child_by_name = gst_child_proxy_default_get_child_by_name; +} + +static void +gst_child_proxy_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /* create interface signals and properties here. */ + /** + * GstChildProxy::child-added: + * @child_proxy: the #GstChildProxy + * @object: the #GObject that was added + * @name: the name of the new child + * + * Will be emitted after the @object was added to the @child_proxy. + */ + signals[CHILD_ADDED] = + g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface, + child_added), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, + 2, G_TYPE_OBJECT, G_TYPE_STRING); + + /** + * GstChildProxy::child-removed: + * @child_proxy: the #GstChildProxy + * @object: the #GObject that was removed + * @name: the name of the old child + * + * Will be emitted after the @object was removed from the @child_proxy. + */ + signals[CHILD_REMOVED] = + g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface, + child_removed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, + 2, G_TYPE_OBJECT, G_TYPE_STRING); + + initialized = TRUE; + } +} + +GType +gst_child_proxy_get_type (void) +{ + static volatile gsize type = 0; + + if (g_once_init_enter (&type)) { + GType _type; + static const GTypeInfo info = { + sizeof (GstChildProxyInterface), + gst_child_proxy_base_init, /* base_init */ + NULL, /* base_finalize */ + gst_child_proxy_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + + _type = + g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0); + + g_type_interface_add_prerequisite (_type, G_TYPE_OBJECT); + g_once_init_leave (&type, (gsize) _type); + } + return type; +} diff --git a/gst/gstchildproxy.h b/gst/gstchildproxy.h new file mode 100644 index 0000000..57e3012 --- /dev/null +++ b/gst/gstchildproxy.h @@ -0,0 +1,117 @@ +/* GStreamer + * Copyright (C) 2005 Stefan Kost + * + * gstchildproxy.h: interface header for multi child 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CHILD_PROXY_H__ +#define __GST_CHILD_PROXY_H__ + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_CHILD_PROXY (gst_child_proxy_get_type ()) +#define GST_CHILD_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CHILD_PROXY, GstChildProxy)) +#define GST_IS_CHILD_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CHILD_PROXY)) +#define GST_CHILD_PROXY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_CHILD_PROXY, GstChildProxyInterface)) + +/** + * GstChildProxy: + * + * Opaque #GstChildProxy data structure. + */ +typedef struct _GstChildProxy GstChildProxy; /* dummy object */ +typedef struct _GstChildProxyInterface GstChildProxyInterface; + +/** + * GstChildProxyInterface: + * @parent: parent interface type. + * @get_child_by_name: virtual method to fetch the child by name + * @get_child_by_index: virtual method to fetch the child by index + * @get_children_count: virtual method to get the children count + * + * #GstChildProxy interface. + */ +struct _GstChildProxyInterface +{ + GTypeInterface parent; + + /* methods */ + GObject * (*get_child_by_name) (GstChildProxy * parent, const gchar * name); + GObject * (*get_child_by_index) (GstChildProxy * parent, guint index); + guint (*get_children_count) (GstChildProxy * parent); + /*< private >*/ + /* signals */ + void (*child_added) (GstChildProxy * parent, GObject * child, const gchar * name); + void (*child_removed) (GstChildProxy * parent, GObject * child, const gchar * name); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_child_proxy_get_type (void); + +GST_API +GObject * gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name); + +GST_API +guint gst_child_proxy_get_children_count (GstChildProxy * parent); + +GST_API +GObject * gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index); + +GST_API +gboolean gst_child_proxy_lookup (GstChildProxy *object, const gchar *name, + GObject **target, GParamSpec **pspec); +GST_API +void gst_child_proxy_get_property (GstChildProxy * object, const gchar *name, + GValue *value); +GST_API +void gst_child_proxy_get_valist (GstChildProxy * object, + const gchar * first_property_name, + va_list var_args); +GST_API +void gst_child_proxy_get (GstChildProxy * object, + const gchar * first_property_name, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_child_proxy_set_property (GstChildProxy * object, const gchar *name, + const GValue *value); + +GST_API +void gst_child_proxy_set_valist (GstChildProxy* object, + const gchar * first_property_name, + va_list var_args); +GST_API +void gst_child_proxy_set (GstChildProxy * object, + const gchar * first_property_name, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_child_proxy_child_added (GstChildProxy * parent, GObject * child, + const gchar *name); +GST_API +void gst_child_proxy_child_removed (GstChildProxy * parent, GObject * child, + const gchar *name); + +G_END_DECLS + +#endif /* __GST_CHILD_PROXY_H__ */ diff --git a/gst/gstclock.c b/gst/gstclock.c new file mode 100644 index 0000000..35d5186 --- /dev/null +++ b/gst/gstclock.c @@ -0,0 +1,1680 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2004 Wim Taymans + * + * gstclock.c: Clock subsystem for maintaining time sync + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstclock + * @title: GstClock + * @short_description: Abstract class for global clocks + * @see_also: #GstSystemClock, #GstPipeline + * + * GStreamer uses a global clock to synchronize the plugins in a pipeline. + * Different clock implementations are possible by implementing this abstract + * base class or, more conveniently, by subclassing #GstSystemClock. + * + * The #GstClock returns a monotonically increasing time with the method + * gst_clock_get_time(). Its accuracy and base time depend on the specific + * clock implementation but time is always expressed in nanoseconds. Since the + * baseline of the clock is undefined, the clock time returned is not + * meaningful in itself, what matters are the deltas between two clock times. + * The time returned by a clock is called the absolute time. + * + * The pipeline uses the clock to calculate the running time. Usually all + * renderers synchronize to the global clock using the buffer timestamps, the + * newsegment events and the element's base time, see #GstPipeline. + * + * A clock implementation can support periodic and single shot clock + * notifications both synchronous and asynchronous. + * + * One first needs to create a #GstClockID for the periodic or single shot + * notification using gst_clock_new_single_shot_id() or + * gst_clock_new_periodic_id(). + * + * To perform a blocking wait for the specific time of the #GstClockID use the + * gst_clock_id_wait(). To receive a callback when the specific time is reached + * in the clock use gst_clock_id_wait_async(). Both these calls can be + * interrupted with the gst_clock_id_unschedule() call. If the blocking wait is + * unscheduled a return value of #GST_CLOCK_UNSCHEDULED is returned. + * + * Periodic callbacks scheduled async will be repeatedly called automatically + * until it is unscheduled. To schedule a sync periodic callback, + * gst_clock_id_wait() should be called repeatedly. + * + * The async callbacks can happen from any thread, either provided by the core + * or from a streaming thread. The application should be prepared for this. + * + * A #GstClockID that has been unscheduled cannot be used again for any wait + * operation, a new #GstClockID should be created and the old unscheduled one + * should be destroyed with gst_clock_id_unref(). + * + * It is possible to perform a blocking wait on the same #GstClockID from + * multiple threads. However, registering the same #GstClockID for multiple + * async notifications is not possible, the callback will only be called for + * the thread registering the entry last. + * + * None of the wait operations unref the #GstClockID, the owner is responsible + * for unreffing the ids itself. This holds for both periodic and single shot + * notifications. The reason being that the owner of the #GstClockID has to + * keep a handle to the #GstClockID to unblock the wait on FLUSHING events or + * state changes and if the entry would be unreffed automatically, the handle + * might become invalid without any notification. + * + * These clock operations do not operate on the running time, so the callbacks + * will also occur when not in PLAYING state as if the clock just keeps on + * running. Some clocks however do not progress when the element that provided + * the clock is not PLAYING. + * + * When a clock has the #GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be + * slaved to another #GstClock with the gst_clock_set_master(). The clock will + * then automatically be synchronized to this master clock by repeatedly + * sampling the master clock and the slave clock and recalibrating the slave + * clock with gst_clock_set_calibration(). This feature is mostly useful for + * plugins that have an internal clock but must operate with another clock + * selected by the #GstPipeline. They can track the offset and rate difference + * of their internal clock relative to the master clock by using the + * gst_clock_get_calibration() function. + * + * The master/slave synchronisation can be tuned with the #GstClock:timeout, + * #GstClock:window-size and #GstClock:window-threshold properties. + * The #GstClock:timeout property defines the interval to sample the master + * clock and run the calibration functions. #GstClock:window-size defines the + * number of samples to use when calibrating and #GstClock:window-threshold + * defines the minimum number of samples before the calibration is performed. + */ + +#include "gst_private.h" +#include + +#include "gstclock.h" +#include "gstinfo.h" +#include "gstutils.h" +#include "glib-compat-private.h" + +/* #define DEBUGGING_ENABLED */ + +#define DEFAULT_WINDOW_SIZE 32 +#define DEFAULT_WINDOW_THRESHOLD 4 +#define DEFAULT_TIMEOUT GST_SECOND / 10 + +enum +{ + PROP_0, + PROP_WINDOW_SIZE, + PROP_WINDOW_THRESHOLD, + PROP_TIMEOUT +}; + +enum +{ + SIGNAL_SYNCED, + SIGNAL_LAST +}; + +#define GST_CLOCK_SLAVE_LOCK(clock) g_mutex_lock (&GST_CLOCK_CAST (clock)->priv->slave_lock) +#define GST_CLOCK_SLAVE_UNLOCK(clock) g_mutex_unlock (&GST_CLOCK_CAST (clock)->priv->slave_lock) + +struct _GstClockPrivate +{ + GMutex slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */ + + GCond sync_cond; + + /* with LOCK */ + GstClockTime internal_calibration; + GstClockTime external_calibration; + GstClockTime rate_numerator; + GstClockTime rate_denominator; + GstClockTime last_time; + + /* with LOCK */ + GstClockTime resolution; + + /* for master/slave clocks */ + GstClock *master; + + /* with SLAVE_LOCK */ + gboolean filling; + gint window_size; + gint window_threshold; + gint time_index; + GstClockTime timeout; + GstClockTime *times; + GstClockTime *times_temp; + GstClockID clockid; + + gint pre_count; + gint post_count; + + gboolean synced; +}; + +/* seqlocks */ +#define read_seqbegin(clock) \ + g_atomic_int_get (&clock->priv->post_count); + +static inline gboolean +read_seqretry (GstClock * clock, gint seq) +{ + /* no retry if the seqnum did not change */ + if (G_LIKELY (seq == g_atomic_int_get (&clock->priv->pre_count))) + return FALSE; + + /* wait for the writer to finish and retry */ + GST_OBJECT_LOCK (clock); + GST_OBJECT_UNLOCK (clock); + return TRUE; +} + +#define write_seqlock(clock) \ +G_STMT_START { \ + GST_OBJECT_LOCK (clock); \ + g_atomic_int_inc (&clock->priv->pre_count); \ +} G_STMT_END; + +#define write_sequnlock(clock) \ +G_STMT_START { \ + g_atomic_int_inc (&clock->priv->post_count); \ + GST_OBJECT_UNLOCK (clock); \ +} G_STMT_END; + +#ifndef GST_DISABLE_GST_DEBUG +static const gchar * +gst_clock_return_get_name (GstClockReturn ret) +{ + switch (ret) { + case GST_CLOCK_OK: + return "ok"; + case GST_CLOCK_EARLY: + return "early"; + case GST_CLOCK_UNSCHEDULED: + return "unscheduled"; + case GST_CLOCK_BUSY: + return "busy"; + case GST_CLOCK_BADTIME: + return "bad-time"; + case GST_CLOCK_ERROR: + return "error"; + case GST_CLOCK_UNSUPPORTED: + return "unsupported"; + case GST_CLOCK_DONE: + return "done"; + default: + break; + } + + return "unknown"; +} +#endif /* GST_DISABLE_GST_DEBUG */ + +static void gst_clock_dispose (GObject * object); +static void gst_clock_finalize (GObject * object); + +static void gst_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static guint gst_clock_signals[SIGNAL_LAST] = { 0 }; + +static GstClockID +gst_clock_entry_new (GstClock * clock, GstClockTime time, + GstClockTime interval, GstClockEntryType type) +{ + GstClockEntry *entry; + + entry = g_slice_new (GstClockEntry); + + /* FIXME: add tracer hook for struct allocations such as clock entries */ + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time)); + + entry->refcount = 1; + entry->clock = clock; + entry->type = type; + entry->time = time; + entry->interval = interval; + entry->status = GST_CLOCK_OK; + entry->func = NULL; + entry->user_data = NULL; + entry->destroy_data = NULL; + entry->unscheduled = FALSE; + entry->woken_up = FALSE; + + return (GstClockID) entry; +} + +/* WARNING : Does not modify the refcount + * WARNING : Do not use if a pending clock operation is happening on that entry */ +static gboolean +gst_clock_entry_reinit (GstClock * clock, GstClockEntry * entry, + GstClockTime time, GstClockTime interval, GstClockEntryType type) +{ + g_return_val_if_fail (entry->status != GST_CLOCK_BUSY, FALSE); + g_return_val_if_fail (entry->clock == clock, FALSE); + + entry->type = type; + entry->time = time; + entry->interval = interval; + entry->status = GST_CLOCK_OK; + entry->unscheduled = FALSE; + entry->woken_up = FALSE; + + return TRUE; +} + +/** + * gst_clock_single_shot_id_reinit: + * @clock: a #GstClock + * @id: a #GstClockID + * @time: The requested time. + * + * Reinitializes the provided single shot @id to the provided time. Does not + * modify the reference count. + * + * Returns: %TRUE if the GstClockID could be reinitialized to the provided + * @time, else %FALSE. + */ +gboolean +gst_clock_single_shot_id_reinit (GstClock * clock, GstClockID id, + GstClockTime time) +{ + return gst_clock_entry_reinit (clock, (GstClockEntry *) id, time, + GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE); +} + +/** + * gst_clock_periodic_id_reinit: + * @clock: a #GstClock + * @id: a #GstClockID + * @start_time: the requested start time + * @interval: the requested interval + * + * Reinitializes the provided periodic @id to the provided start time and + * interval. Does not modify the reference count. + * + * Returns: %TRUE if the GstClockID could be reinitialized to the provided + * @time, else %FALSE. + */ +gboolean +gst_clock_periodic_id_reinit (GstClock * clock, GstClockID id, + GstClockTime start_time, GstClockTime interval) +{ + return gst_clock_entry_reinit (clock, (GstClockEntry *) id, start_time, + interval, GST_CLOCK_ENTRY_PERIODIC); +} + +/** + * gst_clock_id_ref: + * @id: The #GstClockID to ref + * + * Increase the refcount of given @id. + * + * Returns: (transfer full): The same #GstClockID with increased refcount. + * + * MT safe. + */ +GstClockID +gst_clock_id_ref (GstClockID id) +{ + g_return_val_if_fail (id != NULL, NULL); + + g_atomic_int_inc (&((GstClockEntry *) id)->refcount); + + return id; +} + +static void +_gst_clock_id_free (GstClockID id) +{ + GstClockEntry *entry; + g_return_if_fail (id != NULL); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "freed entry %p", id); + entry = (GstClockEntry *) id; + if (entry->destroy_data) + entry->destroy_data (entry->user_data); + + /* FIXME: add tracer hook for struct allocations such as clock entries */ + + g_slice_free (GstClockEntry, id); +} + +/** + * gst_clock_id_unref: + * @id: (transfer full): The #GstClockID to unref + * + * Unref given @id. When the refcount reaches 0 the + * #GstClockID will be freed. + * + * MT safe. + */ +void +gst_clock_id_unref (GstClockID id) +{ + gint zero; + + g_return_if_fail (id != NULL); + + zero = g_atomic_int_dec_and_test (&((GstClockEntry *) id)->refcount); + /* if we ended up with the refcount at zero, free the id */ + if (zero) { + _gst_clock_id_free (id); + } +} + +/** + * gst_clock_new_single_shot_id: + * @clock: The #GstClockID to get a single shot notification from + * @time: the requested time + * + * Get a #GstClockID from @clock to trigger a single shot + * notification at the requested time. The single shot id should be + * unreffed after usage. + * + * Free-function: gst_clock_id_unref + * + * Returns: (transfer full): a #GstClockID that can be used to request the + * time notification. + * + * MT safe. + */ +GstClockID +gst_clock_new_single_shot_id (GstClock * clock, GstClockTime time) +{ + g_return_val_if_fail (GST_IS_CLOCK (clock), NULL); + + return gst_clock_entry_new (clock, + time, GST_CLOCK_TIME_NONE, GST_CLOCK_ENTRY_SINGLE); +} + +/** + * gst_clock_new_periodic_id: + * @clock: The #GstClockID to get a periodic notification id from + * @start_time: the requested start time + * @interval: the requested interval + * + * Get an ID from @clock to trigger a periodic notification. + * The periodic notifications will start at time @start_time and + * will then be fired with the given @interval. @id should be unreffed + * after usage. + * + * Free-function: gst_clock_id_unref + * + * Returns: (transfer full): a #GstClockID that can be used to request the + * time notification. + * + * MT safe. + */ +GstClockID +gst_clock_new_periodic_id (GstClock * clock, GstClockTime start_time, + GstClockTime interval) +{ + g_return_val_if_fail (GST_IS_CLOCK (clock), NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), NULL); + g_return_val_if_fail (interval != 0, NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), NULL); + + return gst_clock_entry_new (clock, + start_time, interval, GST_CLOCK_ENTRY_PERIODIC); +} + +/** + * gst_clock_id_compare_func: + * @id1: A #GstClockID + * @id2: A #GstClockID to compare with + * + * Compares the two #GstClockID instances. This function can be used + * as a GCompareFunc when sorting ids. + * + * Returns: negative value if a < b; zero if a = b; positive value if a > b + * + * MT safe. + */ +gint +gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2) +{ + GstClockEntry *entry1, *entry2; + + entry1 = (GstClockEntry *) id1; + entry2 = (GstClockEntry *) id2; + + if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) { + return 1; + } + if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) { + return -1; + } + return 0; +} + +/** + * gst_clock_id_get_time: + * @id: The #GstClockID to query + * + * Get the time of the clock ID + * + * Returns: the time of the given clock id. + * + * MT safe. + */ +GstClockTime +gst_clock_id_get_time (GstClockID id) +{ + g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE); + + return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id); +} + +/** + * gst_clock_id_wait: + * @id: The #GstClockID to wait on + * @jitter: (out) (allow-none): a pointer that will contain the jitter, + * can be %NULL. + * + * Perform a blocking wait on @id. + * @id should have been created with gst_clock_new_single_shot_id() + * or gst_clock_new_periodic_id() and should not have been unscheduled + * with a call to gst_clock_id_unschedule(). + * + * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK + * or #GST_CLOCK_EARLY, it will contain the difference + * against the clock and the time of @id when this method was + * called. + * Positive values indicate how late @id was relative to the clock + * (in which case this function will return #GST_CLOCK_EARLY). + * Negative values indicate how much time was spent waiting on the clock + * before this function returned. + * + * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned + * if the current clock time is past the time of @id, #GST_CLOCK_OK if + * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was + * unscheduled with gst_clock_id_unschedule(). + * + * MT safe. + */ +GstClockReturn +gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter) +{ + GstClockEntry *entry; + GstClock *clock; + GstClockReturn res; + GstClockTime requested; + GstClockClass *cclass; + + g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR); + + entry = (GstClockEntry *) id; + requested = GST_CLOCK_ENTRY_TIME (entry); + + clock = GST_CLOCK_ENTRY_CLOCK (entry); + + /* can't sync on invalid times */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) + goto invalid_time; + + cclass = GST_CLOCK_GET_CLASS (clock); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id); + + /* if we have a wait_jitter function, use that */ + if (G_UNLIKELY (cclass->wait == NULL)) + goto not_supported; + + res = cclass->wait (clock, entry, jitter); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "done waiting entry %p, res: %d (%s)", id, res, + gst_clock_return_get_name (res)); + + if (entry->type == GST_CLOCK_ENTRY_PERIODIC) + entry->time = requested + entry->interval; + + return res; + + /* ERRORS */ +invalid_time: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "invalid time requested, returning _BADTIME"); + return GST_CLOCK_BADTIME; + } +not_supported: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported"); + return GST_CLOCK_UNSUPPORTED; + } +} + +/** + * gst_clock_id_wait_async: + * @id: a #GstClockID to wait on + * @func: The callback function + * @user_data: User data passed in the callback + * @destroy_data: #GDestroyNotify for user_data + * + * Register a callback on the given #GstClockID @id with the given + * function and user_data. When passing a #GstClockID with an invalid + * time to this function, the callback will be called immediately + * with a time set to GST_CLOCK_TIME_NONE. The callback will + * be called when the time of @id has been reached. + * + * The callback @func can be invoked from any thread, either provided by the + * core or from a streaming thread. The application should be prepared for this. + * + * Returns: the result of the non blocking wait. + * + * MT safe. + */ +GstClockReturn +gst_clock_id_wait_async (GstClockID id, + GstClockCallback func, gpointer user_data, GDestroyNotify destroy_data) +{ + GstClockEntry *entry; + GstClock *clock; + GstClockReturn res; + GstClockClass *cclass; + GstClockTime requested; + + g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR); + g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR); + + entry = (GstClockEntry *) id; + requested = GST_CLOCK_ENTRY_TIME (entry); + clock = GST_CLOCK_ENTRY_CLOCK (entry); + + /* can't sync on invalid times */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested))) + goto invalid_time; + + cclass = GST_CLOCK_GET_CLASS (clock); + + if (G_UNLIKELY (cclass->wait_async == NULL)) + goto not_supported; + + entry->func = func; + entry->user_data = user_data; + entry->destroy_data = destroy_data; + + res = cclass->wait_async (clock, entry); + + return res; + + /* ERRORS */ +invalid_time: + { + (func) (clock, GST_CLOCK_TIME_NONE, id, user_data); + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "invalid time requested, returning _BADTIME"); + return GST_CLOCK_BADTIME; + } +not_supported: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported"); + return GST_CLOCK_UNSUPPORTED; + } +} + +/** + * gst_clock_id_unschedule: + * @id: The id to unschedule + * + * Cancel an outstanding request with @id. This can either + * be an outstanding async notification or a pending sync notification. + * After this call, @id cannot be used anymore to receive sync or + * async notifications, you need to create a new #GstClockID. + * + * MT safe. + */ +void +gst_clock_id_unschedule (GstClockID id) +{ + GstClockEntry *entry; + GstClock *clock; + GstClockClass *cclass; + + g_return_if_fail (id != NULL); + + entry = (GstClockEntry *) id; + clock = entry->clock; + + cclass = GST_CLOCK_GET_CLASS (clock); + + if (G_LIKELY (cclass->unschedule)) + cclass->unschedule (clock, entry); +} + + +/* + * GstClock abstract base class implementation + */ +#define gst_clock_parent_class parent_class +G_DEFINE_ABSTRACT_TYPE (GstClock, gst_clock, GST_TYPE_OBJECT); + +static void +gst_clock_class_init (GstClockClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gst_clock_dispose; + gobject_class->finalize = gst_clock_finalize; + gobject_class->set_property = gst_clock_set_property; + gobject_class->get_property = gst_clock_get_property; + + g_object_class_install_property (gobject_class, PROP_WINDOW_SIZE, + g_param_spec_int ("window-size", "Window size", + "The size of the window used to calculate rate and offset", 2, 1024, + DEFAULT_WINDOW_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_WINDOW_THRESHOLD, + g_param_spec_int ("window-threshold", "Window threshold", + "The threshold to start calculating rate and offset", 2, 1024, + DEFAULT_WINDOW_THRESHOLD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TIMEOUT, + g_param_spec_uint64 ("timeout", "Timeout", + "The amount of time, in nanoseconds, to sample master and slave clocks", + 0, G_MAXUINT64, DEFAULT_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstClock::synced: + * @clock: the clock + * @synced: if the clock is synced now + * + * Signaled on clocks with GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC set once + * the clock is synchronized, or when it completely lost synchronization. + * This signal will not be emitted on clocks without the flag. + * + * This signal will be emitted from an arbitrary thread, most likely not + * the application's main thread. + * + * Since: 1.6 + */ + gst_clock_signals[SIGNAL_SYNCED] = + g_signal_new ("synced", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + g_type_class_add_private (klass, sizeof (GstClockPrivate)); +} + +static void +gst_clock_init (GstClock * clock) +{ + GstClockPrivate *priv; + + clock->priv = priv = + G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate); + + priv->last_time = 0; + + priv->internal_calibration = 0; + priv->external_calibration = 0; + priv->rate_numerator = 1; + priv->rate_denominator = 1; + + g_mutex_init (&priv->slave_lock); + g_cond_init (&priv->sync_cond); + priv->window_size = DEFAULT_WINDOW_SIZE; + priv->window_threshold = DEFAULT_WINDOW_THRESHOLD; + priv->filling = TRUE; + priv->time_index = 0; + priv->timeout = DEFAULT_TIMEOUT; + priv->times = g_new0 (GstClockTime, 4 * priv->window_size); + priv->times_temp = priv->times + 2 * priv->window_size; +} + +static void +gst_clock_dispose (GObject * object) +{ + GstClock *clock = GST_CLOCK (object); + GstClock **master_p; + + GST_OBJECT_LOCK (clock); + master_p = &clock->priv->master; + gst_object_replace ((GstObject **) master_p, NULL); + GST_OBJECT_UNLOCK (clock); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_clock_finalize (GObject * object) +{ + GstClock *clock = GST_CLOCK (object); + + GST_CLOCK_SLAVE_LOCK (clock); + if (clock->priv->clockid) { + gst_clock_id_unschedule (clock->priv->clockid); + gst_clock_id_unref (clock->priv->clockid); + clock->priv->clockid = NULL; + } + g_free (clock->priv->times); + clock->priv->times = NULL; + clock->priv->times_temp = NULL; + GST_CLOCK_SLAVE_UNLOCK (clock); + + g_mutex_clear (&clock->priv->slave_lock); + g_cond_clear (&clock->priv->sync_cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_clock_set_resolution: + * @clock: a #GstClock + * @resolution: The resolution to set + * + * Set the accuracy of the clock. Some clocks have the possibility to operate + * with different accuracy at the expense of more resource usage. There is + * normally no need to change the default resolution of a clock. The resolution + * of a clock can only be changed if the clock has the + * #GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set. + * + * Returns: the new resolution of the clock. + */ +GstClockTime +gst_clock_set_resolution (GstClock * clock, GstClockTime resolution) +{ + GstClockPrivate *priv; + GstClockClass *cclass; + + g_return_val_if_fail (GST_IS_CLOCK (clock), 0); + g_return_val_if_fail (resolution != 0, 0); + + cclass = GST_CLOCK_GET_CLASS (clock); + priv = clock->priv; + + if (cclass->change_resolution) + priv->resolution = + cclass->change_resolution (clock, priv->resolution, resolution); + + return priv->resolution; +} + +/** + * gst_clock_get_resolution: + * @clock: a #GstClock + * + * Get the accuracy of the clock. The accuracy of the clock is the granularity + * of the values returned by gst_clock_get_time(). + * + * Returns: the resolution of the clock in units of #GstClockTime. + * + * MT safe. + */ +GstClockTime +gst_clock_get_resolution (GstClock * clock) +{ + GstClockClass *cclass; + + g_return_val_if_fail (GST_IS_CLOCK (clock), 0); + + cclass = GST_CLOCK_GET_CLASS (clock); + + if (cclass->get_resolution) + return cclass->get_resolution (clock); + + return 1; +} + +/* FIXME 2.0: Remove clock parameter below */ +/** + * gst_clock_adjust_with_calibration: + * @clock: (allow-none): a #GstClock to use + * @internal_target: a clock time + * @cinternal: a reference internal time + * @cexternal: a reference external time + * @cnum: the numerator of the rate of the clock relative to its + * internal time + * @cdenom: the denominator of the rate of the clock + * + * Converts the given @internal_target clock time to the external time, + * using the passed calibration parameters. This function performs the + * same calculation as gst_clock_adjust_unlocked() when called using the + * current calibration parameters, but doesn't ensure a monotonically + * increasing result as gst_clock_adjust_unlocked() does. + * + * Note: The @clock parameter is unused and can be NULL + * + * Returns: the converted time of the clock. + * + * Since: 1.6 + */ +GstClockTime +gst_clock_adjust_with_calibration (GstClock * clock, + GstClockTime internal_target, GstClockTime cinternal, + GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom) +{ + GstClockTime ret; + + /* avoid divide by 0 */ + if (G_UNLIKELY (cdenom == 0)) + cnum = cdenom = 1; + + /* The formula is (internal - cinternal) * cnum / cdenom + cexternal + * + * Since we do math on unsigned 64-bit ints we have to special case for + * internal < cinternal to get the sign right. this case is not very common, + * though. + */ + if (G_LIKELY (internal_target >= cinternal)) { + ret = internal_target - cinternal; + ret = gst_util_uint64_scale (ret, cnum, cdenom); + ret += cexternal; + } else { + ret = cinternal - internal_target; + ret = gst_util_uint64_scale (ret, cnum, cdenom); + /* clamp to 0 */ + if (G_LIKELY (cexternal > ret)) + ret = cexternal - ret; + else + ret = 0; + } + + return ret; +} + +/** + * gst_clock_adjust_unlocked: + * @clock: a #GstClock to use + * @internal: a clock time + * + * Converts the given @internal clock time to the external time, adjusting for the + * rate and reference time set with gst_clock_set_calibration() and making sure + * that the returned time is increasing. This function should be called with the + * clock's OBJECT_LOCK held and is mainly used by clock subclasses. + * + * This function is the reverse of gst_clock_unadjust_unlocked(). + * + * Returns: the converted time of the clock. + */ +GstClockTime +gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal) +{ + GstClockTime ret, cinternal, cexternal, cnum, cdenom; + GstClockPrivate *priv = clock->priv; + + /* get calibration values for readability */ + cinternal = priv->internal_calibration; + cexternal = priv->external_calibration; + cnum = priv->rate_numerator; + cdenom = priv->rate_denominator; + + ret = + gst_clock_adjust_with_calibration (clock, internal, cinternal, cexternal, + cnum, cdenom); + + /* make sure the time is increasing */ + priv->last_time = MAX (ret, priv->last_time); + + return priv->last_time; +} + +/* FIXME 2.0: Remove clock parameter below */ +/** + * gst_clock_unadjust_with_calibration: + * @clock: (allow-none): a #GstClock to use + * @external_target: a clock time + * @cinternal: a reference internal time + * @cexternal: a reference external time + * @cnum: the numerator of the rate of the clock relative to its + * internal time + * @cdenom: the denominator of the rate of the clock + * + * Converts the given @external_target clock time to the internal time, + * using the passed calibration parameters. This function performs the + * same calculation as gst_clock_unadjust_unlocked() when called using the + * current calibration parameters. + * + * Note: The @clock parameter is unused and can be NULL + * + * Returns: the converted time of the clock. + * + * Since: 1.8 + */ +GstClockTime +gst_clock_unadjust_with_calibration (GstClock * clock, + GstClockTime external_target, GstClockTime cinternal, + GstClockTime cexternal, GstClockTime cnum, GstClockTime cdenom) +{ + GstClockTime ret; + + /* avoid divide by 0 */ + if (G_UNLIKELY (cnum == 0)) + cnum = cdenom = 1; + + /* The formula is (external - cexternal) * cdenom / cnum + cinternal */ + if (G_LIKELY (external_target >= cexternal)) { + ret = external_target - cexternal; + ret = gst_util_uint64_scale (ret, cdenom, cnum); + ret += cinternal; + } else { + ret = cexternal - external_target; + ret = gst_util_uint64_scale (ret, cdenom, cnum); + if (G_LIKELY (cinternal > ret)) + ret = cinternal - ret; + else + ret = 0; + } + + return ret; +} + +/** + * gst_clock_unadjust_unlocked: + * @clock: a #GstClock to use + * @external: an external clock time + * + * Converts the given @external clock time to the internal time of @clock, + * using the rate and reference time set with gst_clock_set_calibration(). + * This function should be called with the clock's OBJECT_LOCK held and + * is mainly used by clock subclasses. + * + * This function is the reverse of gst_clock_adjust_unlocked(). + * + * Returns: the internal time of the clock corresponding to @external. + */ +GstClockTime +gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external) +{ + GstClockTime cinternal, cexternal, cnum, cdenom; + GstClockPrivate *priv = clock->priv; + + /* get calibration values for readability */ + cinternal = priv->internal_calibration; + cexternal = priv->external_calibration; + cnum = priv->rate_numerator; + cdenom = priv->rate_denominator; + + return gst_clock_unadjust_with_calibration (clock, external, cinternal, + cexternal, cnum, cdenom); +} + +/** + * gst_clock_get_internal_time: + * @clock: a #GstClock to query + * + * Gets the current internal time of the given clock. The time is returned + * unadjusted for the offset and the rate. + * + * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when + * given invalid input. + * + * MT safe. + */ +GstClockTime +gst_clock_get_internal_time (GstClock * clock) +{ + GstClockTime ret; + GstClockClass *cclass; + + g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); + + if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (clock, + GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) && !clock->priv->synced)) + GST_CAT_WARNING_OBJECT (GST_CAT_CLOCK, clock, + "clock is not synchronized yet"); + + cclass = GST_CLOCK_GET_CLASS (clock); + + if (G_UNLIKELY (cclass->get_internal_time == NULL)) + goto not_supported; + + ret = cclass->get_internal_time (clock); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal time %" GST_TIME_FORMAT, + GST_TIME_ARGS (ret)); + + return ret; + + /* ERRORS */ +not_supported: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "internal time not supported, return 0"); + return G_GINT64_CONSTANT (0); + } +} + +/** + * gst_clock_get_time: + * @clock: a #GstClock to query + * + * Gets the current time of the given clock. The time is always + * monotonically increasing and adjusted according to the current + * offset and rate. + * + * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when + * given invalid input. + * + * MT safe. + */ +GstClockTime +gst_clock_get_time (GstClock * clock) +{ + GstClockTime ret; + gint seq; + + g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); + + do { + /* reget the internal time when we retry to get the most current + * timevalue */ + ret = gst_clock_get_internal_time (clock); + + seq = read_seqbegin (clock); + /* this will scale for rate and offset */ + ret = gst_clock_adjust_unlocked (clock, ret); + } while (read_seqretry (clock, seq)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT, + GST_TIME_ARGS (ret)); + + return ret; +} + +/** + * gst_clock_set_calibration: + * @clock: a #GstClock to calibrate + * @internal: a reference internal time + * @external: a reference external time + * @rate_num: the numerator of the rate of the clock relative to its + * internal time + * @rate_denom: the denominator of the rate of the clock + * + * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of + * the clock. Values bigger than 1/1 make the clock go faster. + * + * @internal and @external are calibration parameters that arrange that + * gst_clock_get_time() should have been @external at internal time @internal. + * This internal time should not be in the future; that is, it should be less + * than the value of gst_clock_get_internal_time() when this function is called. + * + * Subsequent calls to gst_clock_get_time() will return clock times computed as + * follows: + * + * |[ + * time = (internal_time - internal) * rate_num / rate_denom + external + * ]| + * + * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it + * tries to do the integer arithmetic as precisely as possible. + * + * Note that gst_clock_get_time() always returns increasing values so when you + * move the clock backwards, gst_clock_get_time() will report the previous value + * until the clock catches up. + * + * MT safe. + */ +void +gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime + external, GstClockTime rate_num, GstClockTime rate_denom) +{ + GstClockPrivate *priv; + + g_return_if_fail (GST_IS_CLOCK (clock)); + g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE); + g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE); + + priv = clock->priv; + + write_seqlock (clock); + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %" + G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal), + GST_TIME_ARGS (external), rate_num, rate_denom, + gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom)); + + priv->internal_calibration = internal; + priv->external_calibration = external; + priv->rate_numerator = rate_num; + priv->rate_denominator = rate_denom; + write_sequnlock (clock); +} + +/** + * gst_clock_get_calibration: + * @clock: a #GstClock + * @internal: (out) (allow-none): a location to store the internal time + * @external: (out) (allow-none): a location to store the external time + * @rate_num: (out) (allow-none): a location to store the rate numerator + * @rate_denom: (out) (allow-none): a location to store the rate denominator + * + * Gets the internal rate and reference time of @clock. See + * gst_clock_set_calibration() for more information. + * + * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the + * caller is not interested in the values. + * + * MT safe. + */ +void +gst_clock_get_calibration (GstClock * clock, GstClockTime * internal, + GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom) +{ + gint seq; + GstClockPrivate *priv; + + g_return_if_fail (GST_IS_CLOCK (clock)); + + priv = clock->priv; + + do { + seq = read_seqbegin (clock); + if (rate_num) + *rate_num = priv->rate_numerator; + if (rate_denom) + *rate_denom = priv->rate_denominator; + if (external) + *external = priv->external_calibration; + if (internal) + *internal = priv->internal_calibration; + } while (read_seqretry (clock, seq)); +} + +/* will be called repeatedly to sample the master and slave clock + * to recalibrate the clock */ +static gboolean +gst_clock_slave_callback (GstClock * master, GstClockTime time, + GstClockID id, GstClock * clock) +{ + GstClockTime stime, mtime; + gdouble r_squared; + + if (!gst_clock_is_synced (clock)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "Slave clock is not synced yet"); + return TRUE; + } + + stime = gst_clock_get_internal_time (clock); + mtime = gst_clock_get_time (master); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "master %" GST_TIME_FORMAT ", slave %" GST_TIME_FORMAT, + GST_TIME_ARGS (mtime), GST_TIME_ARGS (stime)); + + gst_clock_add_observation (clock, stime, mtime, &r_squared); + + /* FIXME, we can use the r_squared value to adjust the timeout + * value of the clockid */ + + return TRUE; +} + +/** + * gst_clock_set_master: + * @clock: a #GstClock + * @master: (allow-none): a master #GstClock + * + * Set @master as the master clock for @clock. @clock will be automatically + * calibrated so that gst_clock_get_time() reports the same time as the + * master clock. + * + * A clock provider that slaves its clock to a master can get the current + * calibration values with gst_clock_get_calibration(). + * + * @master can be %NULL in which case @clock will not be slaved anymore. It will + * however keep reporting its time adjusted with the last configured rate + * and time offsets. + * + * Returns: %TRUE if the clock is capable of being slaved to a master clock. + * Trying to set a master on a clock without the + * #GST_CLOCK_FLAG_CAN_SET_MASTER flag will make this function return %FALSE. + * + * MT safe. + */ +gboolean +gst_clock_set_master (GstClock * clock, GstClock * master) +{ + GstClock **master_p; + GstClockPrivate *priv; + + g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); + g_return_val_if_fail (master != clock, FALSE); + + GST_OBJECT_LOCK (clock); + /* we always allow setting the master to NULL */ + if (master && !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER)) + goto not_supported; + if (master && !gst_clock_is_synced (master)) + goto master_not_synced; + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "slaving %p to master clock %p", clock, master); + GST_OBJECT_UNLOCK (clock); + + priv = clock->priv; + + GST_CLOCK_SLAVE_LOCK (clock); + if (priv->clockid) { + gst_clock_id_unschedule (priv->clockid); + gst_clock_id_unref (priv->clockid); + priv->clockid = NULL; + } + if (master) { + priv->filling = TRUE; + priv->time_index = 0; + /* use the master periodic id to schedule sampling and + * clock calibration. */ + priv->clockid = gst_clock_new_periodic_id (master, + gst_clock_get_time (master), priv->timeout); + gst_clock_id_wait_async (priv->clockid, + (GstClockCallback) gst_clock_slave_callback, + gst_object_ref (clock), (GDestroyNotify) gst_object_unref); + } + GST_CLOCK_SLAVE_UNLOCK (clock); + + GST_OBJECT_LOCK (clock); + master_p = &priv->master; + gst_object_replace ((GstObject **) master_p, (GstObject *) master); + GST_OBJECT_UNLOCK (clock); + + return TRUE; + + /* ERRORS */ +not_supported: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, + "cannot be slaved to a master clock"); + GST_OBJECT_UNLOCK (clock); + return FALSE; + } + +master_not_synced: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, master, + "master clock is not synced yet"); + GST_OBJECT_UNLOCK (clock); + return FALSE; + } +} + +/** + * gst_clock_get_master: + * @clock: a #GstClock + * + * Get the master clock that @clock is slaved to or %NULL when the clock is + * not slaved to any master clock. + * + * Returns: (transfer full) (nullable): a master #GstClock or %NULL + * when this clock is not slaved to a master clock. Unref after + * usage. + * + * MT safe. + */ +GstClock * +gst_clock_get_master (GstClock * clock) +{ + GstClock *result = NULL; + GstClockPrivate *priv; + + g_return_val_if_fail (GST_IS_CLOCK (clock), NULL); + + priv = clock->priv; + + GST_OBJECT_LOCK (clock); + if (priv->master) + result = gst_object_ref (priv->master); + GST_OBJECT_UNLOCK (clock); + + return result; +} + +/** + * gst_clock_add_observation: + * @clock: a #GstClock + * @slave: a time on the slave + * @master: a time on the master + * @r_squared: (out): a pointer to hold the result + * + * The time @master of the master clock and the time @slave of the slave + * clock are added to the list of observations. If enough observations + * are available, a linear regression algorithm is run on the + * observations and @clock is recalibrated. + * + * If this functions returns %TRUE, @r_squared will contain the + * correlation coefficient of the interpolation. A value of 1.0 + * means a perfect regression was performed. This value can + * be used to control the sampling frequency of the master and slave + * clocks. + * + * Returns: %TRUE if enough observations were added to run the + * regression algorithm. + * + * MT safe. + */ +gboolean +gst_clock_add_observation (GstClock * clock, GstClockTime slave, + GstClockTime master, gdouble * r_squared) +{ + GstClockTime m_num, m_denom, b, xbase; + + if (!gst_clock_add_observation_unapplied (clock, slave, master, r_squared, + &xbase, &b, &m_num, &m_denom)) + return FALSE; + + /* if we have a valid regression, adjust the clock */ + gst_clock_set_calibration (clock, xbase, b, m_num, m_denom); + + return TRUE; +} + +/** + * gst_clock_add_observation_unapplied: + * @clock: a #GstClock + * @slave: a time on the slave + * @master: a time on the master + * @r_squared: (out): a pointer to hold the result + * @internal: (out) (allow-none): a location to store the internal time + * @external: (out) (allow-none): a location to store the external time + * @rate_num: (out) (allow-none): a location to store the rate numerator + * @rate_denom: (out) (allow-none): a location to store the rate denominator + * + * Add a clock observation to the internal slaving algorithm the same as + * gst_clock_add_observation(), and return the result of the master clock + * estimation, without updating the internal calibration. + * + * The caller can then take the results and call gst_clock_set_calibration() + * with the values, or some modified version of them. + * + * Since: 1.6 + */ +gboolean +gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave, + GstClockTime master, gdouble * r_squared, + GstClockTime * internal, GstClockTime * external, + GstClockTime * rate_num, GstClockTime * rate_denom) +{ + GstClockTime m_num, m_denom, b, xbase; + GstClockPrivate *priv; + guint n; + + g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); + g_return_val_if_fail (r_squared != NULL, FALSE); + + priv = clock->priv; + + GST_CLOCK_SLAVE_LOCK (clock); + + GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock, + "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT, + GST_TIME_ARGS (slave), GST_TIME_ARGS (master)); + + priv->times[(2 * priv->time_index)] = slave; + priv->times[(2 * priv->time_index) + 1] = master; + + priv->time_index++; + if (G_UNLIKELY (priv->time_index == priv->window_size)) { + priv->filling = FALSE; + priv->time_index = 0; + } + + if (G_UNLIKELY (priv->filling && priv->time_index < priv->window_threshold)) + goto filling; + + n = priv->filling ? priv->time_index : priv->window_size; + if (!gst_calculate_linear_regression (priv->times, priv->times_temp, n, + &m_num, &m_denom, &b, &xbase, r_squared)) + goto invalid; + + GST_CLOCK_SLAVE_UNLOCK (clock); + + GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock, + "adjusting clock to m=%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT ", b=%" + G_GUINT64_FORMAT " (rsquared=%g)", m_num, m_denom, b, *r_squared); + + if (internal) + *internal = xbase; + if (external) + *external = b; + if (rate_num) + *rate_num = m_num; + if (rate_denom) + *rate_denom = m_denom; + + return TRUE; + +filling: + { + GST_CLOCK_SLAVE_UNLOCK (clock); + return FALSE; + } +invalid: + { + /* no valid regression has been done, ignore the result then */ + GST_CLOCK_SLAVE_UNLOCK (clock); + return FALSE; + } +} + +/** + * gst_clock_set_timeout: + * @clock: a #GstClock + * @timeout: a timeout + * + * Set the amount of time, in nanoseconds, to sample master and slave + * clocks + */ +void +gst_clock_set_timeout (GstClock * clock, GstClockTime timeout) +{ + g_return_if_fail (GST_IS_CLOCK (clock)); + + GST_CLOCK_SLAVE_LOCK (clock); + clock->priv->timeout = timeout; + GST_CLOCK_SLAVE_UNLOCK (clock); +} + +/** + * gst_clock_get_timeout: + * @clock: a #GstClock + * + * Get the amount of time that master and slave clocks are sampled. + * + * Returns: the interval between samples. + */ +GstClockTime +gst_clock_get_timeout (GstClock * clock) +{ + GstClockTime result; + + g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); + + GST_CLOCK_SLAVE_LOCK (clock); + result = clock->priv->timeout; + GST_CLOCK_SLAVE_UNLOCK (clock); + + return result; +} + +static void +gst_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstClock *clock; + GstClockPrivate *priv; + + clock = GST_CLOCK (object); + priv = clock->priv; + + switch (prop_id) { + case PROP_WINDOW_SIZE: + GST_CLOCK_SLAVE_LOCK (clock); + priv->window_size = g_value_get_int (value); + priv->window_threshold = MIN (priv->window_threshold, priv->window_size); + priv->times = g_renew (GstClockTime, priv->times, 4 * priv->window_size); + priv->times_temp = priv->times + 2 * priv->window_size; + /* restart calibration */ + priv->filling = TRUE; + priv->time_index = 0; + GST_CLOCK_SLAVE_UNLOCK (clock); + break; + case PROP_WINDOW_THRESHOLD: + GST_CLOCK_SLAVE_LOCK (clock); + priv->window_threshold = MIN (g_value_get_int (value), priv->window_size); + GST_CLOCK_SLAVE_UNLOCK (clock); + break; + case PROP_TIMEOUT: + gst_clock_set_timeout (clock, g_value_get_uint64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstClock *clock; + GstClockPrivate *priv; + + clock = GST_CLOCK (object); + priv = clock->priv; + + switch (prop_id) { + case PROP_WINDOW_SIZE: + GST_CLOCK_SLAVE_LOCK (clock); + g_value_set_int (value, priv->window_size); + GST_CLOCK_SLAVE_UNLOCK (clock); + break; + case PROP_WINDOW_THRESHOLD: + GST_CLOCK_SLAVE_LOCK (clock); + g_value_set_int (value, priv->window_threshold); + GST_CLOCK_SLAVE_UNLOCK (clock); + break; + case PROP_TIMEOUT: + g_value_set_uint64 (value, gst_clock_get_timeout (clock)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/** + * gst_clock_wait_for_sync: + * @clock: a GstClock + * @timeout: timeout for waiting or %GST_CLOCK_TIME_NONE + * + * Waits until @clock is synced for reporting the current time. If @timeout + * is %GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out + * after @timeout nanoseconds. + * + * For asynchronous waiting, the GstClock::synced signal can be used. + * + * This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC + * is not set on the clock, or if the clock is already synced. + * + * Returns: %TRUE if waiting was successful, or %FALSE on timeout + * + * Since: 1.6 + */ +gboolean +gst_clock_wait_for_sync (GstClock * clock, GstClockTime timeout) +{ + gboolean timed_out = FALSE; + + g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); + + GST_OBJECT_LOCK (clock); + if (!GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) + || clock->priv->synced) { + GST_OBJECT_UNLOCK (clock); + return TRUE; + } + + if (timeout != GST_CLOCK_TIME_NONE) { + gint64 end_time = g_get_monotonic_time () + gst_util_uint64_scale (timeout, + G_TIME_SPAN_SECOND, GST_SECOND); + + while (!clock->priv->synced && !timed_out) { + timed_out = + !g_cond_wait_until (&clock->priv->sync_cond, + GST_OBJECT_GET_LOCK (clock), end_time); + } + } else { + timed_out = FALSE; + while (!clock->priv->synced) { + g_cond_wait (&clock->priv->sync_cond, GST_OBJECT_GET_LOCK (clock)); + } + } + GST_OBJECT_UNLOCK (clock); + + return !timed_out; +} + +/** + * gst_clock_is_synced: + * @clock: a GstClock + * + * Checks if the clock is currently synced. + * + * This returns if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC is not set on the clock. + * + * Returns: %TRUE if the clock is currently synced + * + * Since: 1.6 + */ +gboolean +gst_clock_is_synced (GstClock * clock) +{ + g_return_val_if_fail (GST_IS_CLOCK (clock), TRUE); + + return !GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) + || clock->priv->synced; +} + +/** + * gst_clock_set_synced: + * @clock: a GstClock + * @synced: if the clock is synced + * + * Sets @clock to synced and emits the GstClock::synced signal, and wakes up any + * thread waiting in gst_clock_wait_for_sync(). + * + * This function must only be called if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC + * is set on the clock, and is intended to be called by subclasses only. + * + * Since: 1.6 + */ +void +gst_clock_set_synced (GstClock * clock, gboolean synced) +{ + g_return_if_fail (GST_IS_CLOCK (clock)); + g_return_if_fail (GST_OBJECT_FLAG_IS_SET (clock, + GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC)); + + GST_OBJECT_LOCK (clock); + if (clock->priv->synced != ! !synced) { + clock->priv->synced = ! !synced; + g_cond_signal (&clock->priv->sync_cond); + GST_OBJECT_UNLOCK (clock); + g_signal_emit (clock, gst_clock_signals[SIGNAL_SYNCED], 0, ! !synced); + } else { + GST_OBJECT_UNLOCK (clock); + } +} diff --git a/gst/gstclock.h b/gst/gstclock.h new file mode 100644 index 0000000..4d2df75 --- /dev/null +++ b/gst/gstclock.h @@ -0,0 +1,633 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstclock.h: Header for clock subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CLOCK_H__ +#define __GST_CLOCK_H__ + +#include +#include + +G_BEGIN_DECLS + +/* --- standard type macros --- */ +#define GST_TYPE_CLOCK (gst_clock_get_type ()) +#define GST_CLOCK(clock) (G_TYPE_CHECK_INSTANCE_CAST ((clock), GST_TYPE_CLOCK, GstClock)) +#define GST_IS_CLOCK(clock) (G_TYPE_CHECK_INSTANCE_TYPE ((clock), GST_TYPE_CLOCK)) +#define GST_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_CAST ((cclass), GST_TYPE_CLOCK, GstClockClass)) +#define GST_IS_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_TYPE ((cclass), GST_TYPE_CLOCK)) +#define GST_CLOCK_GET_CLASS(clock) (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass)) +#define GST_CLOCK_CAST(clock) ((GstClock*)(clock)) + +/** + * GstClockTime: + * + * A datatype to hold a time, measured in nanoseconds. + */ +typedef guint64 GstClockTime; + +/** + * GST_TYPE_CLOCK_TIME: + * + * The #GType of a #GstClockTime. + */ +#define GST_TYPE_CLOCK_TIME G_TYPE_UINT64 + +/** + * GstClockTimeDiff: + * + * A datatype to hold a time difference, measured in nanoseconds. + */ +typedef gint64 GstClockTimeDiff; +/** + * GstClockID: + * + * A datatype to hold the handle to an outstanding sync or async clock callback. + */ +typedef gpointer GstClockID; + +/** + * GST_CLOCK_TIME_NONE: (value 18446744073709551615) (type GstClockTime) + * + * Constant to define an undefined clock time. + */ +#define GST_CLOCK_TIME_NONE ((GstClockTime) -1) +/** + * GST_CLOCK_TIME_IS_VALID: + * @time: clock time to validate + * + * Tests if a given #GstClockTime represents a valid defined time. + */ +#define GST_CLOCK_TIME_IS_VALID(time) (((GstClockTime)(time)) != GST_CLOCK_TIME_NONE) + +/** + * GST_CLOCK_STIME_NONE: (value -9223372036854775808) (type GstClockTimeDiff) + * + * Constant to define an undefined clock time. + */ +#define GST_CLOCK_STIME_NONE ((GstClockTimeDiff)G_MININT64) +/** + * GST_CLOCK_STIME_IS_VALID: + * @time: signed clock time to validate + * + * Tests if a given #GstClockTimeDiff of #gint64 represents a valid defined time. + * + * Since: 1.6 + */ +#define GST_CLOCK_STIME_IS_VALID(time) (((GstClockTimeDiff)(time)) != GST_CLOCK_STIME_NONE) + +/** + * GST_SECOND: (value 1000000000) (type GstClockTimeDiff) + * + * Constant that defines one GStreamer second. + */ +#define GST_SECOND ((GstClockTimeDiff)(G_USEC_PER_SEC * G_GINT64_CONSTANT (1000))) +/** + * GST_MSECOND: (value 1000000) (type GstClockTimeDiff) + * + * Constant that defines one GStreamer millisecond. + */ +#define GST_MSECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000))) +/** + * GST_USECOND: (value 1000) (type GstClockTimeDiff) + * + * Constant that defines one GStreamer microsecond. + */ +#define GST_USECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000000))) +/** + * GST_NSECOND: (value 1) (type GstClockTimeDiff) + * + * Constant that defines one GStreamer nanosecond + */ +#define GST_NSECOND ((GstClockTimeDiff)(GST_SECOND / G_GINT64_CONSTANT (1000000000))) + + +/** + * GST_TIME_AS_SECONDS: + * @time: the time + * + * Convert a #GstClockTime to seconds. + */ +#define GST_TIME_AS_SECONDS(time) ((time) / GST_SECOND) +/** + * GST_TIME_AS_MSECONDS: + * @time: the time + * + * Convert a #GstClockTime to milliseconds (1/1000 of a second). + */ +#define GST_TIME_AS_MSECONDS(time) ((time) / G_GINT64_CONSTANT (1000000)) +/** + * GST_TIME_AS_USECONDS: + * @time: the time + * + * Convert a #GstClockTime to microseconds (1/1000000 of a second). + */ +#define GST_TIME_AS_USECONDS(time) ((time) / G_GINT64_CONSTANT (1000)) +/** + * GST_TIME_AS_NSECONDS: + * @time: the time + * + * Convert a #GstClockTime to nanoseconds (1/1000000000 of a second). + */ +#define GST_TIME_AS_NSECONDS(time) (time) + +/** + * GST_CLOCK_DIFF: + * @s: the first time + * @e: the second time + * + * Calculate a difference between two clock times as a #GstClockTimeDiff. + * The difference is calculated as @e - @s. + */ +#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((e) - (s)) + +/** + * GST_TIMEVAL_TO_TIME: + * @tv: the timeval to convert + * + * Convert a #GTimeVal to a #GstClockTime. + */ +#define GST_TIMEVAL_TO_TIME(tv) (GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND) + +/** + * GST_TIME_TO_TIMEVAL: + * @t: The #GstClockTime to convert + * @tv: The target timeval + * + * Convert a #GstClockTime to a #GTimeVal + * + * > on 32-bit systems, a timeval has a range of only 2^32 - 1 seconds, + * > which is about 68 years. Expect trouble if you want to schedule stuff + * > in your pipeline for 2038. + */ +#define GST_TIME_TO_TIMEVAL(t,tv) \ +G_STMT_START { \ + g_assert ("Value of time " #t " is out of timeval's range" && \ + ((t) / GST_SECOND) < G_MAXLONG); \ + (tv).tv_sec = (glong) (((GstClockTime) (t)) / GST_SECOND); \ + (tv).tv_usec = (glong) ((((GstClockTime) (t)) - \ + ((GstClockTime) (tv).tv_sec) * GST_SECOND) \ + / GST_USECOND); \ +} G_STMT_END + +/** + * GST_TIMESPEC_TO_TIME: + * @ts: the timespec to convert + * + * Convert a struct timespec (see man pselect) to a #GstClockTime. + */ +#define GST_TIMESPEC_TO_TIME(ts) (GstClockTime)((ts).tv_sec * GST_SECOND + (ts).tv_nsec * GST_NSECOND) +/** + * GST_TIME_TO_TIMESPEC: + * @t: The #GstClockTime to convert + * @ts: The target timespec + * + * Convert a #GstClockTime to a struct timespec (see man pselect) + */ +#define GST_TIME_TO_TIMESPEC(t,ts) \ +G_STMT_START { \ + g_assert ("Value of time " #t " is out of timespec's range" && \ + ((t) / GST_SECOND) < G_MAXLONG); \ + (ts).tv_sec = (glong) ((t) / GST_SECOND); \ + (ts).tv_nsec = (glong) (((t) - (ts).tv_sec * GST_SECOND) / GST_NSECOND); \ +} G_STMT_END + +/* timestamp debugging macros */ +/** + * GST_TIME_FORMAT: + * + * A string that can be used in printf-like format strings to display a + * #GstClockTime value in h:m:s format. Use GST_TIME_ARGS() to construct + * the matching arguments. + * + * Example: + * |[ + * printf("%" GST_TIME_FORMAT "\n", GST_TIME_ARGS(ts)); + * ]| + */ +#define GST_TIME_FORMAT "u:%02u:%02u.%09u" +/** + * GST_TIME_ARGS: + * @t: a #GstClockTime + * + * Format @t for the #GST_TIME_FORMAT format string. Note: @t will be + * evaluated more than once. + */ +#define GST_TIME_ARGS(t) \ + GST_CLOCK_TIME_IS_VALID (t) ? \ + (guint) (((GstClockTime)(t)) / (GST_SECOND * 60 * 60)) : 99, \ + GST_CLOCK_TIME_IS_VALID (t) ? \ + (guint) ((((GstClockTime)(t)) / (GST_SECOND * 60)) % 60) : 99, \ + GST_CLOCK_TIME_IS_VALID (t) ? \ + (guint) ((((GstClockTime)(t)) / GST_SECOND) % 60) : 99, \ + GST_CLOCK_TIME_IS_VALID (t) ? \ + (guint) (((GstClockTime)(t)) % GST_SECOND) : 999999999 +/** + * GST_STIME_FORMAT: + * + * A string that can be used in printf-like format strings to display a signed + * #GstClockTimeDiff or #gint64 value in h:m:s format. Use GST_TIME_ARGS() to + * construct the matching arguments. + * + * Example: + * |[ + * printf("%" GST_STIME_FORMAT "\n", GST_STIME_ARGS(ts)); + * ]| + * + * Since: 1.6 + */ +#define GST_STIME_FORMAT "c%" GST_TIME_FORMAT +/** + * GST_STIME_ARGS: + * @t: a #GstClockTimeDiff or #gint64 + * + * Format @t for the #GST_STIME_FORMAT format string. Note: @t will be + * evaluated more than once. + * + * Since: 1.6 + */ +#define GST_STIME_ARGS(t) \ + ((t) == GST_CLOCK_STIME_NONE || (t) >= 0) ? '+' : '-', \ + GST_CLOCK_STIME_IS_VALID (t) ? \ + (guint) (((GstClockTime)(ABS(t))) / (GST_SECOND * 60 * 60)) : 99, \ + GST_CLOCK_STIME_IS_VALID (t) ? \ + (guint) ((((GstClockTime)(ABS(t))) / (GST_SECOND * 60)) % 60) : 99, \ + GST_CLOCK_STIME_IS_VALID (t) ? \ + (guint) ((((GstClockTime)(ABS(t))) / GST_SECOND) % 60) : 99, \ + GST_CLOCK_STIME_IS_VALID (t) ? \ + (guint) (((GstClockTime)(ABS(t))) % GST_SECOND) : 999999999 + +typedef struct _GstClockEntry GstClockEntry; +typedef struct _GstClock GstClock; +typedef struct _GstClockClass GstClockClass; +typedef struct _GstClockPrivate GstClockPrivate; + +/* --- prototype for async callbacks --- */ +/** + * GstClockCallback: + * @clock: The clock that triggered the callback + * @time: The time it was triggered + * @id: The #GstClockID that expired + * @user_data: user data passed in the gst_clock_id_wait_async() function + * + * The function prototype of the callback. + * + * Returns: %TRUE or %FALSE (currently unused) + */ +typedef gboolean (*GstClockCallback) (GstClock *clock, GstClockTime time, + GstClockID id, gpointer user_data); +/** + * GstClockReturn: + * @GST_CLOCK_OK: The operation succeeded. + * @GST_CLOCK_EARLY: The operation was scheduled too late. + * @GST_CLOCK_UNSCHEDULED: The clockID was unscheduled + * @GST_CLOCK_BUSY: The ClockID is busy + * @GST_CLOCK_BADTIME: A bad time was provided to a function. + * @GST_CLOCK_ERROR: An error occurred + * @GST_CLOCK_UNSUPPORTED: Operation is not supported + * @GST_CLOCK_DONE: The ClockID is done waiting + * + * The return value of a clock operation. + */ +typedef enum +{ + GST_CLOCK_OK = 0, + GST_CLOCK_EARLY = 1, + GST_CLOCK_UNSCHEDULED = 2, + GST_CLOCK_BUSY = 3, + GST_CLOCK_BADTIME = 4, + GST_CLOCK_ERROR = 5, + GST_CLOCK_UNSUPPORTED = 6, + GST_CLOCK_DONE = 7 +} GstClockReturn; + +/** + * GstClockEntryType: + * @GST_CLOCK_ENTRY_SINGLE: a single shot timeout + * @GST_CLOCK_ENTRY_PERIODIC: a periodic timeout request + * + * The type of the clock entry + */ +typedef enum { + GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_ENTRY_PERIODIC +} GstClockEntryType; + +/** + * GST_CLOCK_ENTRY: + * @entry: the entry to cast + * + * Cast to a clock entry + */ +#define GST_CLOCK_ENTRY(entry) ((GstClockEntry *)(entry)) +/** + * GST_CLOCK_ENTRY_CLOCK: + * @entry: the entry to query + * + * Get the owner clock of the entry + */ +#define GST_CLOCK_ENTRY_CLOCK(entry) ((entry)->clock) +/** + * GST_CLOCK_ENTRY_TYPE: + * @entry: the entry to query + * + * Get the type of the clock entry + */ +#define GST_CLOCK_ENTRY_TYPE(entry) ((entry)->type) +/** + * GST_CLOCK_ENTRY_TIME: + * @entry: the entry to query + * + * Get the requested time of this entry + */ +#define GST_CLOCK_ENTRY_TIME(entry) ((entry)->time) +/** + * GST_CLOCK_ENTRY_INTERVAL: + * @entry: the entry to query + * + * Get the interval of this periodic entry + */ +#define GST_CLOCK_ENTRY_INTERVAL(entry) ((entry)->interval) +/** + * GST_CLOCK_ENTRY_STATUS: + * @entry: the entry to query + * + * The status of the entry + */ +#define GST_CLOCK_ENTRY_STATUS(entry) ((entry)->status) + +/** + * GstClockEntry: + * @refcount: reference counter (read-only) + * + * All pending timeouts or periodic notifies are converted into + * an entry. + * Note that GstClockEntry should be treated as an opaque structure. It must + * not be extended or allocated using a custom allocator. + */ +struct _GstClockEntry { + gint refcount; + /*< protected >*/ + GstClock *clock; + GstClockEntryType type; + GstClockTime time; + GstClockTime interval; + GstClockReturn status; + GstClockCallback func; + gpointer user_data; + GDestroyNotify destroy_data; + gboolean unscheduled; + gboolean woken_up; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +#include + +/** + * GstClockFlags: + * @GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC: clock can do a single sync timeout request + * @GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC: clock can do a single async timeout request + * @GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC: clock can do sync periodic timeout requests + * @GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC: clock can do async periodic timeout callbacks + * @GST_CLOCK_FLAG_CAN_SET_RESOLUTION: clock's resolution can be changed + * @GST_CLOCK_FLAG_CAN_SET_MASTER: clock can be slaved to a master clock + * @GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC: clock needs to be synced before it can be used + * (Since 1.6) + * @GST_CLOCK_FLAG_LAST: subclasses can add additional flags starting from this flag + * + * The capabilities of this clock + */ +typedef enum { + GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC = (GST_OBJECT_FLAG_LAST << 0), + GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC = (GST_OBJECT_FLAG_LAST << 1), + GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC = (GST_OBJECT_FLAG_LAST << 2), + GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC = (GST_OBJECT_FLAG_LAST << 3), + GST_CLOCK_FLAG_CAN_SET_RESOLUTION = (GST_OBJECT_FLAG_LAST << 4), + GST_CLOCK_FLAG_CAN_SET_MASTER = (GST_OBJECT_FLAG_LAST << 5), + GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC = (GST_OBJECT_FLAG_LAST << 6), + /* padding */ + GST_CLOCK_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8) +} GstClockFlags; + +/** + * GST_CLOCK_FLAGS: + * @clock: the clock to query + * + * Gets the #GstClockFlags clock flags. + */ +#define GST_CLOCK_FLAGS(clock) GST_OBJECT_FLAGS(clock) + +/** + * GstClock: + * + * #GstClock base structure. The values of this structure are + * protected for subclasses, use the methods to use the #GstClock. + */ +struct _GstClock { + GstObject object; + + /*< private >*/ + GstClockPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstClockClass: + * @parent_class: the parent class structure + * @change_resolution: change the resolution of the clock. Not all values might + * be acceptable. The new resolution should be returned. + * @get_resolution: get the resolution of the clock. + * @get_internal_time: get the internal unadjusted time of the clock. + * implement @wait_jitter instead. + * @wait: perform a blocking wait on the given #GstClockEntry and return + * the jitter. + * @wait_async: perform an asynchronous wait for the given #GstClockEntry. + * @unschedule: unblock a blocking or async wait operation. + * + * GStreamer clock class. Override the vmethods to implement the clock + * functionality. + */ +struct _GstClockClass { + GstObjectClass parent_class; + + /*< public >*/ + /* vtable */ + GstClockTime (*change_resolution) (GstClock *clock, + GstClockTime old_resolution, + GstClockTime new_resolution); + GstClockTime (*get_resolution) (GstClock *clock); + + GstClockTime (*get_internal_time) (GstClock *clock); + + /* waiting on an ID */ + GstClockReturn (*wait) (GstClock *clock, GstClockEntry *entry, + GstClockTimeDiff *jitter); + GstClockReturn (*wait_async) (GstClock *clock, GstClockEntry *entry); + void (*unschedule) (GstClock *clock, GstClockEntry *entry); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_clock_get_type (void); + +GST_API +GstClockTime gst_clock_set_resolution (GstClock *clock, + GstClockTime resolution); +GST_API +GstClockTime gst_clock_get_resolution (GstClock *clock); + +GST_API +GstClockTime gst_clock_get_time (GstClock *clock); + +GST_API +void gst_clock_set_calibration (GstClock *clock, GstClockTime internal, + GstClockTime external, + GstClockTime rate_num, + GstClockTime rate_denom); +GST_API +void gst_clock_get_calibration (GstClock *clock, GstClockTime *internal, + GstClockTime *external, + GstClockTime *rate_num, + GstClockTime *rate_denom); + +/* master/slave clocks */ + +GST_API +gboolean gst_clock_set_master (GstClock *clock, GstClock *master); + +GST_API +GstClock* gst_clock_get_master (GstClock *clock); + +GST_API +void gst_clock_set_timeout (GstClock *clock, + GstClockTime timeout); +GST_API +GstClockTime gst_clock_get_timeout (GstClock *clock); + +GST_API +gboolean gst_clock_add_observation (GstClock *clock, GstClockTime slave, + GstClockTime master, gdouble *r_squared); +GST_API +gboolean gst_clock_add_observation_unapplied (GstClock *clock, GstClockTime slave, + GstClockTime master, gdouble *r_squared, + GstClockTime *internal, + GstClockTime *external, + GstClockTime *rate_num, + GstClockTime *rate_denom); + +/* getting and adjusting internal/external time */ + +GST_API +GstClockTime gst_clock_get_internal_time (GstClock *clock); + +GST_API +GstClockTime gst_clock_adjust_unlocked (GstClock *clock, GstClockTime internal); + +GST_API +GstClockTime gst_clock_adjust_with_calibration (GstClock *clock, + GstClockTime internal_target, + GstClockTime cinternal, + GstClockTime cexternal, + GstClockTime cnum, + GstClockTime cdenom); +GST_API +GstClockTime gst_clock_unadjust_with_calibration (GstClock *clock, + GstClockTime external_target, + GstClockTime cinternal, + GstClockTime cexternal, + GstClockTime cnum, + GstClockTime cdenom); +GST_API +GstClockTime gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external); + +/* waiting for, signalling and checking for synchronization */ + +GST_API +gboolean gst_clock_wait_for_sync (GstClock * clock, GstClockTime timeout); + +GST_API +gboolean gst_clock_is_synced (GstClock * clock); + +/* to be used by subclasses only */ + +GST_API +void gst_clock_set_synced (GstClock * clock, gboolean synced); + +/* creating IDs that can be used to get notifications */ + +GST_API +GstClockID gst_clock_new_single_shot_id (GstClock *clock, + GstClockTime time); +GST_API +GstClockID gst_clock_new_periodic_id (GstClock *clock, + GstClockTime start_time, + GstClockTime interval); + +/* reference counting */ + +GST_API +GstClockID gst_clock_id_ref (GstClockID id); + +GST_API +void gst_clock_id_unref (GstClockID id); + +/* operations on IDs */ + +GST_API +gint gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2); + +GST_API +GstClockTime gst_clock_id_get_time (GstClockID id); + +GST_API +GstClockReturn gst_clock_id_wait (GstClockID id, + GstClockTimeDiff *jitter); +GST_API +GstClockReturn gst_clock_id_wait_async (GstClockID id, + GstClockCallback func, + gpointer user_data, + GDestroyNotify destroy_data); +GST_API +void gst_clock_id_unschedule (GstClockID id); + +GST_API +gboolean gst_clock_single_shot_id_reinit (GstClock * clock, + GstClockID id, + GstClockTime time); +GST_API +gboolean gst_clock_periodic_id_reinit (GstClock * clock, + GstClockID id, + GstClockTime start_time, + GstClockTime interval); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClock, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_CLOCK_H__ */ diff --git a/gst/gstcompat.h b/gst/gstcompat.h new file mode 100644 index 0000000..1349ab4 --- /dev/null +++ b/gst/gstcompat.h @@ -0,0 +1,103 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004 Wim Taymans + * + * gstcompat.h: backwards compatibility stuff + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* API compatibility stuff */ +#ifndef __GSTCOMPAT_H__ +#define __GSTCOMPAT_H__ +/** + * SECTION:gstcompat + * @title: GstCompat + * @short_description: Deprecated API entries + * + * Please do not use these in new code. + * These symbols are only available by defining GST_DISABLE_DEPRECATED. + * This can be done in CFLAGS for compiling old code. + */ + +#include +#include + + +G_BEGIN_DECLS + +#define gst_buffer_new_and_alloc(s) gst_buffer_new_allocate(NULL, s, NULL) + +#define GST_BUFFER_TIMESTAMP GST_BUFFER_PTS +#define GST_BUFFER_TIMESTAMP_IS_VALID GST_BUFFER_PTS_IS_VALID + +static inline gboolean +gst_pad_set_caps (GstPad * pad, GstCaps * caps) +{ + GstEvent *event; + gboolean res = TRUE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (caps != NULL && gst_caps_is_fixed (caps), FALSE); + + event = gst_event_new_caps (caps); + + if (GST_PAD_IS_SRC (pad)) + res = gst_pad_push_event (pad, event); + else + res = gst_pad_send_event (pad, event); + + return res; +} + + +#ifndef GST_DISABLE_DEPRECATED + +/* added to ease the transition to 0.11 */ +#define gst_element_class_set_details_simple gst_element_class_set_metadata + +#define gst_element_factory_get_longname(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_LONGNAME) +#define gst_element_factory_get_klass(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_KLASS) +#define gst_element_factory_get_description(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_DESCRIPTION) +#define gst_element_factory_get_author(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_AUTHOR) +#define gst_element_factory_get_documentation_uri(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_DOC_URI) +#define gst_element_factory_get_icon_name(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_ICON_NAME) + +#define gst_pad_get_caps_reffed(p) gst_pad_get_caps(p) +#define gst_pad_peer_get_caps_reffed(p) gst_pad_peer_get_caps(p) + +#define gst_adapter_prev_timestamp gst_adapter_prev_pts + +#define gst_tag_list_free(taglist) gst_tag_list_unref(taglist) + +#define GST_MESSAGE_DURATION GST_MESSAGE_DURATION_CHANGED +#define gst_message_new_duration(src,fmt,dur) \ + gst_message_new_duration_changed(src) +#define gst_message_parse_duration(msg,fmt,dur) \ +G_STMT_START { \ + GstFormat *p_fmt = fmt; \ + gint64 *p_dur = dur; \ + if (p_fmt) \ + *p_fmt = GST_FORMAT_TIME; \ + if (p_dur) \ + *p_dur = GST_CLOCK_TIME_NONE; \ +} G_STMT_END + +#endif /* not GST_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __GSTCOMPAT_H__ */ diff --git a/gst/gstconfig.h.in b/gst/gstconfig.h.in new file mode 100644 index 0000000..6351c04 --- /dev/null +++ b/gst/gstconfig.h.in @@ -0,0 +1,174 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004,2005 Wim Taymans + * + * gstconfig.h: GST_DISABLE_* macros for build configuration + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstconfig + * @short_description: Build configuration options + * + * This describes the configuration options for GStreamer. When building + * GStreamer there are a lot of parts (known internally as "subsystems" ) that + * can be disabled for various reasons. The most common reasons are speed and + * size, which is important because GStreamer is designed to run on embedded + * systems. + * + * If a subsystem is disabled, most of this changes are done in an API + * compatible way, so you don't need to adapt your code in most cases. It is + * never done in an ABI compatible way though. So if you want to disable a + * subsystem, you have to rebuild all programs depending on GStreamer, too. + * + * If a subsystem is disabled in GStreamer, a value is defined in + * <gst/gst.h>. You can check this if you do subsystem-specific stuff. + * + * Doing subsystem specific things + * + * &hash;ifndef GST_DISABLE_GST_DEBUG + * // do stuff specific to the debugging subsystem + * &hash;endif // GST_DISABLE_GST_DEBUG + * + * + */ + +#ifndef __GST_CONFIG_H__ +#define __GST_CONFIG_H__ + +/* trick gtk-doc into believing these symbols are defined (yes, it's ugly) */ + +#if 0 +#define GST_DISABLE_GST_DEBUG 1 +#define GST_DISABLE_PARSE 1 +#define GST_DISABLE_REGISTRY 1 +#define GST_DISABLE_PLUGIN 1 +#endif + +/***** default padding of structures *****/ +#define GST_PADDING 4 +#define GST_PADDING_INIT { NULL } + +/***** padding for very extensible base classes *****/ +#define GST_PADDING_LARGE 20 + +/***** disabling of subsystems *****/ + +/** + * GST_DISABLE_GST_DEBUG: + * + * Configures the inclusion of the debugging subsystem + */ +@GST_DISABLE_GST_DEBUG_DEFINE@ + +/** + * GST_DISABLE_PARSE: + * + * Configures the inclusion of the gst-launch parser + */ +@GST_DISABLE_PARSE_DEFINE@ + +/** + * GST_DISABLE_REGISTRY: + * + * Configures the use of the plugin registry. + * If one disables this, required plugins need to be loaded and registered + * manually + */ +@GST_DISABLE_REGISTRY_DEFINE@ + +/* FIXME: test and document these! */ +/* Configures the use of external plugins */ +@GST_DISABLE_PLUGIN_DEFINE@ + +/* Whether or not the CPU supports unaligned access + * The macros used are defined consistently by GCC, Clang, MSVC, Sun, and ICC + * + * References: + * https://sourceforge.net/p/predef/wiki/Architectures/ + * https://msdn.microsoft.com/en-us/library/b0084kay.aspx + * http://docs.oracle.com/cd/E19205-01/820-4155/c++_faq.html#Vers6 + * https://software.intel.com/en-us/node/583402 + */ +#if defined(__alpha__) || defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__bfin) || defined(__hppa__) || defined(__nios2__) || defined(__MICROBLAZE__) || defined(__mips__) || defined(__or1k__) || defined(__sh__) || defined(__SH4__) || defined(__sparc__) || defined(__sparc) || defined(__ia64__) || defined(_M_ALPHA) || defined(_M_ARM) || defined(_M_IA64) || defined(__xtensa__) || defined(__e2k__) +# define GST_HAVE_UNALIGNED_ACCESS 0 +#elif defined(__i386__) || defined(__i386) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__m68k__) || defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(__s390__) || defined(__s390x__) || defined(__zarch__) +# define GST_HAVE_UNALIGNED_ACCESS 1 +#else +# error "Could not detect architecture; don't know whether it supports unaligned access! Please file a bug." +#endif + +/** + * GST_EXPORT: + * + * Export the given variable from the built shared object. + * + * On Windows, this exports the variable from the DLL. + * On other platforms, this gets defined to "extern". + */ +/** + * GST_PLUGIN_EXPORT: + * + * Export the plugin's definition. + * + * On Windows, this exports the plugin definition from the DLL. + * On other platforms, this gets defined as a no-op. + */ +/* Only use __declspec(dllexport/import) when we have been built with MSVC or + * the user is linking to us with MSVC. The only remaining case is when we were + * built with MinGW and are linking with MinGW in which case we rely on the + * linker to auto-export/import symbols. Of course all this is only used when + * not linking statically. + * + * NOTE: To link to GStreamer statically on Windows, you must define + * GST_STATIC_COMPILATION or the prototypes will cause the compiler to search + * for the symbol inside a DLL. + */ +#if (@GSTCONFIG_BUILT_WITH_MSVC@ || defined(_MSC_VER)) && !defined(GST_STATIC_COMPILATION) +# define GST_PLUGIN_EXPORT __declspec(dllexport) +# ifdef GST_EXPORTS +# define GST_EXPORT __declspec(dllexport) +# else +# define GST_EXPORT __declspec(dllimport) extern +# endif +#else +# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +# define GST_PLUGIN_EXPORT __attribute__ ((visibility ("default"))) +# define GST_EXPORT extern __attribute__ ((visibility ("default"))) +# else +# define GST_PLUGIN_EXPORT +# define GST_EXPORT extern +# endif +#endif + +#ifndef GST_API +#define GST_API GST_EXPORT +#endif + +/* These macros are used to mark deprecated functions in GStreamer headers, + * and thus have to be exposed in installed headers. But please + * do *not* use them in other projects. Instead, use G_DEPRECATED + * or define your own wrappers around it. */ +#ifndef GST_DISABLE_DEPRECATED +#define GST_DEPRECATED GST_API +#define GST_DEPRECATED_FOR(f) GST_API +#else +#define GST_DEPRECATED G_DEPRECATED GST_API +#define GST_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) GST_API +#endif + +#endif /* __GST_CONFIG_H__ */ diff --git a/gst/gstcontext.c b/gst/gstcontext.c new file mode 100644 index 0000000..73cace4 --- /dev/null +++ b/gst/gstcontext.c @@ -0,0 +1,280 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: Sebastian Dröge + * Copyright (C) 2013 Sebastian Dröge + * + * gstcontext.h: Header for GstContext subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcontext + * @title: GstContext + * @short_description: Lightweight objects to represent element contexts + * @see_also: #GstMiniObject, #GstElement + * + * #GstContext is a container object used to store contexts like a device + * context, a display server connection and similar concepts that should + * be shared between multiple elements. + * + * Applications can set a context on a complete pipeline by using + * gst_element_set_context(), which will then be propagated to all + * child elements. Elements can handle these in #GstElementClass.set_context() + * and merge them with the context information they already have. + * + * When an element needs a context it will do the following actions in this + * order until one step succeeds: + * 1. Check if the element already has a context + * 2. Query downstream with GST_QUERY_CONTEXT for the context + * 3. Query upstream with GST_QUERY_CONTEXT for the context + * 4. Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required + * context types and afterwards check if a usable context was set now + * 5. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message + * on the bus. + * + * Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously + * known context on the element that asks for it if possible. Otherwise the + * application should provide one if it can. + * + * #GstContexts can be persistent. + * A persistent #GstContext is kept in elements when they reach + * %GST_STATE_NULL, non-persistent ones will be removed. + * Also, a non-persistent context won't override a previous persistent + * context set to an element. + * + * Since: 1.2 + */ + +#include "gst_private.h" +#include +#include "gstcontext.h" +#include "gstquark.h" + +struct _GstContext +{ + GstMiniObject mini_object; + + gchar *context_type; + GstStructure *structure; + gboolean persistent; +}; + +#define GST_CONTEXT_STRUCTURE(c) (((GstContext *)(c))->structure) + +GType _gst_context_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context); + +void +_priv_gst_context_initialize (void) +{ + GST_CAT_INFO (GST_CAT_GST_INIT, "init contexts"); + + /* the GstMiniObject types need to be class_ref'd once before it can be + * done from multiple threads; + * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */ + gst_context_get_type (); + + _gst_context_type = gst_context_get_type (); +} + +static void +_gst_context_free (GstContext * context) +{ + GstStructure *structure; + + g_return_if_fail (context != NULL); + + GST_CAT_LOG (GST_CAT_CONTEXT, "finalize context %p: %" GST_PTR_FORMAT, + context, GST_CONTEXT_STRUCTURE (context)); + + structure = GST_CONTEXT_STRUCTURE (context); + if (structure) { + gst_structure_set_parent_refcount (structure, NULL); + gst_structure_free (structure); + } + g_free (context->context_type); + + g_slice_free1 (sizeof (GstContext), context); +} + +static void gst_context_init (GstContext * context); + +static GstContext * +_gst_context_copy (GstContext * context) +{ + GstContext *copy; + GstStructure *structure; + + GST_CAT_LOG (GST_CAT_CONTEXT, "copy context %p: %" GST_PTR_FORMAT, context, + GST_CONTEXT_STRUCTURE (context)); + + copy = g_slice_new0 (GstContext); + + gst_context_init (copy); + + copy->context_type = g_strdup (context->context_type); + + structure = GST_CONTEXT_STRUCTURE (context); + GST_CONTEXT_STRUCTURE (copy) = gst_structure_copy (structure); + gst_structure_set_parent_refcount (GST_CONTEXT_STRUCTURE (copy), + ©->mini_object.refcount); + + copy->persistent = context->persistent; + + return GST_CONTEXT_CAST (copy); +} + +static void +gst_context_init (GstContext * context) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (context), 0, _gst_context_type, + (GstMiniObjectCopyFunction) _gst_context_copy, NULL, + (GstMiniObjectFreeFunction) _gst_context_free); +} + +/** + * gst_context_new: + * @context_type: Context type + * @persistent: Persistent context + * + * Create a new context. + * + * Returns: (transfer full): The new context. + * + * Since: 1.2 + */ +GstContext * +gst_context_new (const gchar * context_type, gboolean persistent) +{ + GstContext *context; + GstStructure *structure; + + g_return_val_if_fail (context_type != NULL, NULL); + + context = g_slice_new0 (GstContext); + + GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context); + + structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT)); + gst_structure_set_parent_refcount (structure, &context->mini_object.refcount); + gst_context_init (context); + + context->context_type = g_strdup (context_type); + GST_CONTEXT_STRUCTURE (context) = structure; + context->persistent = persistent; + + return context; +} + +/** + * gst_context_get_context_type: + * @context: The #GstContext. + * + * Get the type of @context. + * + * Returns: The type of the context. + * + * Since: 1.2 + */ +const gchar * +gst_context_get_context_type (const GstContext * context) +{ + g_return_val_if_fail (GST_IS_CONTEXT (context), NULL); + + return context->context_type; +} + +/** + * gst_context_has_context_type: + * @context: The #GstContext. + * @context_type: Context type to check. + * + * Checks if @context has @context_type. + * + * Returns: %TRUE if @context has @context_type. + * + * Since: 1.2 + */ +gboolean +gst_context_has_context_type (const GstContext * context, + const gchar * context_type) +{ + g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE); + g_return_val_if_fail (context_type != NULL, FALSE); + + return strcmp (context->context_type, context_type) == 0; +} + +/** + * gst_context_get_structure: + * @context: The #GstContext. + * + * Access the structure of the context. + * + * Returns: (transfer none): The structure of the context. The structure is + * still owned by the context, which means that you should not modify it, + * free it and that the pointer becomes invalid when you free the context. + * + * Since: 1.2 + */ +const GstStructure * +gst_context_get_structure (const GstContext * context) +{ + g_return_val_if_fail (GST_IS_CONTEXT (context), NULL); + + return GST_CONTEXT_STRUCTURE (context); +} + +/** + * gst_context_writable_structure: + * @context: The #GstContext. + * + * Get a writable version of the structure. + * + * Returns: The structure of the context. The structure is still + * owned by the context, which means that you should not free it and + * that the pointer becomes invalid when you free the context. + * This function checks if @context is writable. + * + * Since: 1.2 + */ +GstStructure * +gst_context_writable_structure (GstContext * context) +{ + g_return_val_if_fail (GST_IS_CONTEXT (context), NULL); + g_return_val_if_fail (gst_context_is_writable (context), NULL); + + return GST_CONTEXT_STRUCTURE (context); +} + +/** + * gst_context_is_persistent: + * @context: The #GstContext. + * + * Check if @context is persistent. + * + * Returns: %TRUE if the context is persistent. + * + * Since: 1.2 + */ +gboolean +gst_context_is_persistent (const GstContext * context) +{ + g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE); + + return context->persistent; +} diff --git a/gst/gstcontext.h b/gst/gstcontext.h new file mode 100644 index 0000000..f55e84c --- /dev/null +++ b/gst/gstcontext.h @@ -0,0 +1,160 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: Sebastian Dröge + * Copyright (C) 2013 Sebastian Dröge + * + * gstcontext.h: Header for GstContext subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONTEXT_H__ +#define __GST_CONTEXT_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstContext GstContext; + +#include +#include + +GST_API GType _gst_context_type; + +#define GST_TYPE_CONTEXT (_gst_context_type) +#define GST_IS_CONTEXT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_CONTEXT)) +#define GST_CONTEXT_CAST(obj) ((GstContext*)(obj)) +#define GST_CONTEXT(obj) (GST_CONTEXT_CAST(obj)) + + + +GST_API +GType gst_context_get_type (void); + + +/* refcounting */ +/** + * gst_context_ref: + * @context: the context to ref + * + * Convenience macro to increase the reference count of the context. + * + * Returns: @context (for convenience when doing assignments) + */ +static inline GstContext * +gst_context_ref (GstContext * context) +{ + return (GstContext *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (context)); +} + +/** + * gst_context_unref: + * @context: the context to unref + * + * Convenience macro to decrease the reference count of the context, possibly + * freeing it. + */ +static inline void +gst_context_unref (GstContext * context) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (context)); +} + +/* copy context */ +/** + * gst_context_copy: + * @context: the context to copy + * + * Creates a copy of the context. Returns a copy of the context. + * + * Returns: (transfer full): a new copy of @context. + * + * MT safe + */ +static inline GstContext * +gst_context_copy (const GstContext * context) +{ + return GST_CONTEXT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (context))); +} + +/** + * gst_context_is_writable: + * @context: a #GstContext + * + * Tests if you can safely write into a context's structure or validly + * modify the seqnum and timestamp fields. + */ +#define gst_context_is_writable(context) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (context)) +/** + * gst_context_make_writable: + * @context: (transfer full): the context to make writable + * + * Checks if a context is writable. If not, a writable copy is made and + * returned. + * + * Returns: (transfer full): a context (possibly a duplicate) that is writable. + * + * MT safe + */ +#define gst_context_make_writable(context) GST_CONTEXT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (context))) +/** + * gst_context_replace: + * @old_context: (inout) (transfer full): pointer to a pointer to a #GstContext + * to be replaced. + * @new_context: (allow-none) (transfer none): pointer to a #GstContext that will + * replace the context pointed to by @old_context. + * + * Modifies a pointer to a #GstContext to point to a different #GstContext. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * context is unreffed, the new one is reffed). + * + * Either @new_context or the #GstContext pointed to by @old_context may be %NULL. + * + * Returns: %TRUE if @new_context was different from @old_context + */ +static inline gboolean +gst_context_replace (GstContext **old_context, GstContext *new_context) +{ + return gst_mini_object_replace ((GstMiniObject **) old_context, (GstMiniObject *) new_context); +} + +GST_API +GstContext * gst_context_new (const gchar * context_type, + gboolean persistent) G_GNUC_MALLOC; +GST_API +const gchar * gst_context_get_context_type (const GstContext * context); + +GST_API +gboolean gst_context_has_context_type (const GstContext * context, const gchar * context_type); + +GST_API +const GstStructure * gst_context_get_structure (const GstContext * context); + +GST_API +GstStructure * gst_context_writable_structure (GstContext * context); + +GST_API +gboolean gst_context_is_persistent (const GstContext * context); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstContext, gst_context_unref) +#endif + +G_END_DECLS + +#endif /* __GST_CONTEXT_H__ */ diff --git a/gst/gstcontrolbinding.c b/gst/gstcontrolbinding.c new file mode 100644 index 0000000..0d73948 --- /dev/null +++ b/gst/gstcontrolbinding.c @@ -0,0 +1,497 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstcontrolbinding.c: Attachment for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstcontrolbinding + * @title: GstControlBinding + * @short_description: attachment for control source sources + * + * A base class for value mapping objects that attaches control sources to gobject + * properties. Such an object is taking one or more #GstControlSource instances, + * combines them and maps the resulting value to the type and value range of the + * bound property. + */ +/* FIXME(ensonic): should we make gst_object_add_control_binding() internal + * - we create the control_binding for a certain object anyway + * - we could call gst_object_add_control_binding() at the end of + * gst_control_binding_constructor() + * - the weak-ref on object is not nice, as is the same as gst_object_parent() + * once the object is added to the parent + * + * - another option would be to defer what is done in _constructor to when + * the parent is set (need to listen to the signal then) + * then basically I could + * a) remove the obj arg and wait the binding to be added or + * b) add the binding from constructor, unref object there and make obj + * writeonly + */ + +#include "gst_private.h" + +#include +#include + +#include "gstcontrolbinding.h" + +#include + +#define GST_CAT_DEFAULT control_binding_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolbinding", 0, \ + "dynamic parameter control source attachment"); + +static GObject *gst_control_binding_constructor (GType type, + guint n_construct_params, GObjectConstructParam * construct_params); +static void gst_control_binding_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_control_binding_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_control_binding_dispose (GObject * object); +static void gst_control_binding_finalize (GObject * object); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstControlBinding, gst_control_binding, + GST_TYPE_OBJECT, _do_init); + +struct _GstControlBindingPrivate +{ + GWeakRef object; +}; + +enum +{ + PROP_0, + PROP_OBJECT, + PROP_NAME, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +static void +gst_control_binding_class_init (GstControlBindingClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstControlBindingPrivate)); + + gobject_class->constructor = gst_control_binding_constructor; + gobject_class->set_property = gst_control_binding_set_property; + gobject_class->get_property = gst_control_binding_get_property; + gobject_class->dispose = gst_control_binding_dispose; + gobject_class->finalize = gst_control_binding_finalize; + + properties[PROP_OBJECT] = + g_param_spec_object ("object", "Object", + "The object of the property", GST_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + properties[PROP_NAME] = + g_param_spec_string ("name", "Name", "The name of the property", NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + + g_object_class_install_properties (gobject_class, PROP_LAST, properties); +} + +static void +gst_control_binding_init (GstControlBinding * binding) +{ + binding->ABI.abi.priv = + G_TYPE_INSTANCE_GET_PRIVATE (binding, GST_TYPE_CONTROL_BINDING, + GstControlBindingPrivate); + g_weak_ref_init (&binding->ABI.abi.priv->object, NULL); +} + +static GObject * +gst_control_binding_constructor (GType type, guint n_construct_params, + GObjectConstructParam * construct_params) +{ + GstControlBinding *binding; + GParamSpec *pspec; + GstObject *object; + + binding = + GST_CONTROL_BINDING (G_OBJECT_CLASS (gst_control_binding_parent_class) + ->constructor (type, n_construct_params, construct_params)); + + object = g_weak_ref_get (&binding->ABI.abi.priv->object); + if (!object) { + GST_WARNING_OBJECT (object, "no object set"); + return (GObject *) binding; + } + + GST_INFO_OBJECT (object, "trying to put property '%s' under control", + binding->name); + + /* check if the object has a property of that name */ + if ((pspec = + g_object_class_find_property (G_OBJECT_GET_CLASS (object), + binding->name))) { + GST_DEBUG_OBJECT (object, " psec->flags : 0x%08x", pspec->flags); + + /* check if this param is witable && controlable && !construct-only */ + if ((pspec->flags & (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE | + G_PARAM_CONSTRUCT_ONLY)) == + (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE)) { + binding->pspec = pspec; + } else { + GST_WARNING_OBJECT (object, + "property '%s' on class '%s' needs to " + "be writeable, controlable and not construct_only", binding->name, + G_OBJECT_TYPE_NAME (object)); + } + } else { + GST_WARNING_OBJECT (object, "class '%s' has no property '%s'", + G_OBJECT_TYPE_NAME (object), binding->name); + } + + gst_object_unref (object); + + return (GObject *) binding; +} + +static void +gst_control_binding_dispose (GObject * object) +{ + GstControlBinding *self = GST_CONTROL_BINDING (object); + + /* we did not took a reference */ + g_object_remove_weak_pointer ((GObject *) self->__object, + (gpointer *) & self->__object); + self->__object = NULL; + g_weak_ref_clear (&self->ABI.abi.priv->object); + + ((GObjectClass *) gst_control_binding_parent_class)->dispose (object); +} + +static void +gst_control_binding_finalize (GObject * object) +{ + GstControlBinding *self = GST_CONTROL_BINDING (object); + + g_free (self->name); + + ((GObjectClass *) gst_control_binding_parent_class)->finalize (object); +} + +static void +gst_control_binding_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstControlBinding *self = GST_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_OBJECT: + /* do not ref to avoid a ref cycle */ + self->__object = g_value_get_object (value); + g_object_add_weak_pointer ((GObject *) self->__object, + (gpointer *) & self->__object); + + g_weak_ref_set (&self->ABI.abi.priv->object, self->__object); + break; + case PROP_NAME: + self->name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_control_binding_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstControlBinding *self = GST_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_OBJECT: + g_value_take_object (value, g_weak_ref_get (&self->ABI.abi.priv->object)); + break; + case PROP_NAME: + g_value_set_string (value, self->name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* functions */ + +/** + * gst_control_binding_sync_values: + * @binding: the control binding + * @object: the object that has controlled properties + * @timestamp: the time that should be processed + * @last_sync: the last time this was called + * + * Sets the property of the @object, according to the #GstControlSources that + * handle them and for the given timestamp. + * + * If this function fails, it is most likely the application developers fault. + * Most probably the control sources are not setup correctly. + * + * Returns: %TRUE if the controller value could be applied to the object + * property, %FALSE otherwise + */ +gboolean +gst_control_binding_sync_values (GstControlBinding * binding, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync) +{ + GstControlBindingClass *klass; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE); + + if (binding->disabled) + return TRUE; + + klass = GST_CONTROL_BINDING_GET_CLASS (binding); + + if (G_LIKELY (klass->sync_values != NULL)) { + ret = klass->sync_values (binding, object, timestamp, last_sync); + } else { + GST_WARNING_OBJECT (binding, "missing sync_values implementation"); + } + return ret; +} + +/** + * gst_control_binding_get_value: + * @binding: the control binding + * @timestamp: the time the control-change should be read from + * + * Gets the value for the given controlled property at the requested time. + * + * Returns: (nullable): the GValue of the property at the given time, + * or %NULL if the property isn't controlled. + */ +GValue * +gst_control_binding_get_value (GstControlBinding * binding, + GstClockTime timestamp) +{ + GstControlBindingClass *klass; + GValue *ret = NULL; + + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); + + klass = GST_CONTROL_BINDING_GET_CLASS (binding); + + if (G_LIKELY (klass->get_value != NULL)) { + ret = klass->get_value (binding, timestamp); + } else { + GST_WARNING_OBJECT (binding, "missing get_value implementation"); + } + return ret; +} + +/** + * gst_control_binding_get_value_array: (skip) + * @binding: the control binding + * @timestamp: the time that should be processed + * @interval: the time spacing between subsequent values + * @n_values: the number of values + * @values: (array length=n_values): array to put control-values in + * + * Gets a number of values for the given controlled property starting at the + * requested time. The array @values need to hold enough space for @n_values of + * the same type as the objects property's type. + * + * This function is useful if one wants to e.g. draw a graph of the control + * curve or apply a control curve sample by sample. + * + * The values are unboxed and ready to be used. The similar function + * gst_control_binding_get_g_value_array() returns the array as #GValues and is + * more suitable for bindings. + * + * Returns: %TRUE if the given array could be filled, %FALSE otherwise + */ +gboolean +gst_control_binding_get_value_array (GstControlBinding * binding, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values) +{ + GstControlBindingClass *klass; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + + klass = GST_CONTROL_BINDING_GET_CLASS (binding); + + if (G_LIKELY (klass->get_value_array != NULL)) { + ret = + klass->get_value_array (binding, timestamp, interval, n_values, values); + } else { + GST_WARNING_OBJECT (binding, "missing get_value_array implementation"); + } + return ret; +} + +#define CONVERT_ARRAY(type,TYPE) \ +{ \ + g##type *v = g_new (g##type,n_values); \ + ret = gst_control_binding_get_value_array (binding, timestamp, interval, \ + n_values, v); \ + if (ret) { \ + for (i = 0; i < n_values; i++) { \ + g_value_init (&values[i], G_TYPE_##TYPE); \ + g_value_set_##type (&values[i], v[i]); \ + } \ + } \ + g_free (v); \ +} + +/** + * gst_control_binding_get_g_value_array: + * @binding: the control binding + * @timestamp: the time that should be processed + * @interval: the time spacing between subsequent values + * @n_values: the number of values + * @values: (array length=n_values): array to put control-values in + * + * Gets a number of #GValues for the given controlled property starting at the + * requested time. The array @values need to hold enough space for @n_values of + * #GValue. + * + * This function is useful if one wants to e.g. draw a graph of the control + * curve or apply a control curve sample by sample. + * + * Returns: %TRUE if the given array could be filled, %FALSE otherwise + */ +gboolean +gst_control_binding_get_g_value_array (GstControlBinding * binding, + GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + GstControlBindingClass *klass; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + + klass = GST_CONTROL_BINDING_GET_CLASS (binding); + + if (G_LIKELY (klass->get_g_value_array != NULL)) { + ret = + klass->get_g_value_array (binding, timestamp, interval, n_values, + values); + } else { + guint i; + GType type, base; + + base = type = G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (binding)); + while ((type = g_type_parent (type))) + base = type; + + GST_INFO_OBJECT (binding, "missing get_g_value_array implementation, we're " + "emulating it"); + switch (base) { + case G_TYPE_INT: + CONVERT_ARRAY (int, INT); + break; + case G_TYPE_UINT: + CONVERT_ARRAY (uint, UINT); + break; + case G_TYPE_LONG: + CONVERT_ARRAY (long, LONG); + break; + case G_TYPE_ULONG: + CONVERT_ARRAY (ulong, ULONG); + break; + case G_TYPE_INT64: + CONVERT_ARRAY (int64, INT64); + break; + case G_TYPE_UINT64: + CONVERT_ARRAY (uint64, UINT64); + break; + case G_TYPE_FLOAT: + CONVERT_ARRAY (float, FLOAT); + break; + case G_TYPE_DOUBLE: + CONVERT_ARRAY (double, DOUBLE); + break; + case G_TYPE_BOOLEAN: + CONVERT_ARRAY (boolean, BOOLEAN); + break; + case G_TYPE_ENUM: + { + gint *v = g_new (gint, n_values); + ret = gst_control_binding_get_value_array (binding, timestamp, interval, + n_values, v); + if (ret) { + for (i = 0; i < n_values; i++) { + g_value_init (&values[i], type); + g_value_set_enum (&values[i], v[i]); + } + } + g_free (v); + } + break; + default: + GST_WARNING ("incomplete implementation for paramspec type '%s'", + G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (binding))); + GST_CONTROL_BINDING_PSPEC (binding) = NULL; + break; + } + } + return ret; +} + +/** + * gst_control_binding_set_disabled: + * @binding: the control binding + * @disabled: boolean that specifies whether to disable the controller + * or not. + * + * This function is used to disable a control binding for some time, i.e. + * gst_object_sync_values() will do nothing. + */ +void +gst_control_binding_set_disabled (GstControlBinding * binding, + gboolean disabled) +{ + g_return_if_fail (GST_IS_CONTROL_BINDING (binding)); + binding->disabled = disabled; +} + +/** + * gst_control_binding_is_disabled: + * @binding: the control binding + * + * Check if the control binding is disabled. + * + * Returns: %TRUE if the binding is inactive + */ +gboolean +gst_control_binding_is_disabled (GstControlBinding * binding) +{ + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), TRUE); + return ! !binding->disabled; +} diff --git a/gst/gstcontrolbinding.h b/gst/gstcontrolbinding.h new file mode 100644 index 0000000..ba67547 --- /dev/null +++ b/gst/gstcontrolbinding.h @@ -0,0 +1,142 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstcontrolbinding.h: Attachment for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONTROL_BINDING_H__ +#define __GST_CONTROL_BINDING_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CONTROL_BINDING \ + (gst_control_binding_get_type()) +#define GST_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_BINDING,GstControlBinding)) +#define GST_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_BINDING,GstControlBindingClass)) +#define GST_IS_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_BINDING)) +#define GST_IS_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_BINDING)) +#define GST_CONTROL_BINDING_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlBindingClass)) + +typedef struct _GstControlBinding GstControlBinding; +typedef struct _GstControlBindingClass GstControlBindingClass; +typedef struct _GstControlBindingPrivate GstControlBindingPrivate; + +#include + +/* FIXME(2.0): remove, this is unused */ +typedef void (* GstControlBindingConvert) (GstControlBinding *binding, gdouble src_value, GValue *dest_value); + +/** + * GstControlBinding: + * @name: name of the property of this binding + * @pspec: #GParamSpec for this property + * + * The instance structure of #GstControlBinding. + */ +struct _GstControlBinding { + GstObject parent; + + /*< public >*/ + gchar *name; + GParamSpec *pspec; + + /*< private >*/ +#ifndef GST_DISABLE_DEPRECATED + GstObject *object; /* GstObject owning the property + * (== parent when bound) */ +#else + gpointer __object; +#endif + gboolean disabled; + + union { + struct { + GstControlBindingPrivate *priv; + } abi; + gpointer _gst_reserved[GST_PADDING]; + } ABI; +}; + +/** + * GstControlBindingClass: + * @parent_class: Parent class + * @sync_values: implementation for updating the target values + * @get_value: implementation to fetch a single control-value + * @get_value_array: implementation to fetch a series of control-values + * @get_g_value_array: implementation to fetch a series of control-values + * as g_values + * + * The class structure of #GstControlBinding. + */ + +struct _GstControlBindingClass +{ + GstObjectClass parent_class; + + /*< public >*/ + gboolean (* sync_values) (GstControlBinding *binding, GstObject *object, GstClockTime timestamp, GstClockTime last_sync); + GValue * (* get_value) (GstControlBinding *binding, GstClockTime timestamp); + gboolean (* get_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, gpointer values); + gboolean (* get_g_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +#define GST_CONTROL_BINDING_PSPEC(cb) (((GstControlBinding *) cb)->pspec) + +GST_API +GType gst_control_binding_get_type (void); + +/* Functions */ + +GST_API +gboolean gst_control_binding_sync_values (GstControlBinding * binding, GstObject *object, + GstClockTime timestamp, GstClockTime last_sync); +GST_API +GValue * gst_control_binding_get_value (GstControlBinding *binding, + GstClockTime timestamp); +GST_API +gboolean gst_control_binding_get_value_array (GstControlBinding *binding, GstClockTime timestamp, + GstClockTime interval, guint n_values, gpointer values); +GST_API +gboolean gst_control_binding_get_g_value_array (GstControlBinding *binding, GstClockTime timestamp, + GstClockTime interval, guint n_values, GValue *values); +GST_API +void gst_control_binding_set_disabled (GstControlBinding * binding, gboolean disabled); + +GST_API +gboolean gst_control_binding_is_disabled (GstControlBinding * binding); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstControlBinding, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_CONTROL_BINDING_H__ */ diff --git a/gst/gstcontrolsource.c b/gst/gstcontrolsource.c new file mode 100644 index 0000000..1817edc --- /dev/null +++ b/gst/gstcontrolsource.c @@ -0,0 +1,122 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * + * gstcontrolsource.c: Interface declaration for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcontrolsource + * @title: GstControlSource + * @short_description: base class for control source sources + * + * The #GstControlSource is a base class for control value sources that could + * be used to get timestamp-value pairs. A control source essentially is a + * function over time. + * + * A #GstControlSource is used by first getting an instance of a specific + * control-source, creating a binding for the control-source to the target property + * of the element and then adding the binding to the element. The binding will + * convert the data types and value range to fit to the bound property. + * + * For implementing a new #GstControlSource one has to implement + * #GstControlSourceGetValue and #GstControlSourceGetValueArray functions. + * These are then used by gst_control_source_get_value() and + * gst_control_source_get_value_array() to get values for specific timestamps. + */ + +#include "gst_private.h" + +#include +#include + +#include "gstcontrolsource.h" + +#define GST_CAT_DEFAULT control_source_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolsource", 0, \ + "dynamic parameter control sources"); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstControlSource, gst_control_source, + GST_TYPE_OBJECT, _do_init); + +static void +gst_control_source_class_init (GstControlSourceClass * klass) +{ +} + +static void +gst_control_source_init (GstControlSource * self) +{ + self->get_value = NULL; + self->get_value_array = NULL; +} + +/** + * gst_control_source_get_value: (method) + * @self: the #GstControlSource object + * @timestamp: the time for which the value should be returned + * @value: (out): the value + * + * Gets the value for this #GstControlSource at a given timestamp. + * + * Returns: %FALSE if the value couldn't be returned, %TRUE otherwise. + */ +gboolean +gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE); + + if (G_LIKELY (self->get_value)) { + return self->get_value (self, timestamp, value); + } else { + GST_ERROR ("Not bound to a specific property yet!"); + return FALSE; + } +} + +/** + * gst_control_source_get_value_array: (method) + * @self: the #GstControlSource object + * @timestamp: the first timestamp + * @interval: the time steps + * @n_values: the number of values to fetch + * @values: (array length=n_values): array to put control-values in + * + * Gets an array of values for for this #GstControlSource. Values that are + * undefined contain NANs. + * + * Returns: %TRUE if the given array could be filled, %FALSE otherwise + */ +gboolean +gst_control_source_get_value_array (GstControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE); + + if (G_LIKELY (self->get_value_array)) { + return self->get_value_array (self, timestamp, interval, n_values, values); + } else { + GST_ERROR ("Not bound to a specific property yet!"); + return FALSE; + } +} diff --git a/gst/gstcontrolsource.h b/gst/gstcontrolsource.h new file mode 100644 index 0000000..295d46f --- /dev/null +++ b/gst/gstcontrolsource.h @@ -0,0 +1,150 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * + * gstcontrolsource.h: Interface declaration for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONTROL_SOURCE_H__ +#define __GST_CONTROL_SOURCE_H__ + +#include + +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CONTROL_SOURCE \ + (gst_control_source_get_type()) +#define GST_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_SOURCE,GstControlSource)) +#define GST_CONTROL_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_SOURCE,GstControlSourceClass)) +#define GST_IS_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_SOURCE)) +#define GST_IS_CONTROL_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_SOURCE)) +#define GST_CONTROL_SOURCE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlSourceClass)) + +typedef struct _GstControlSource GstControlSource; +typedef struct _GstControlSourceClass GstControlSourceClass; +typedef struct _GstTimedValue GstTimedValue; +typedef struct _GstValueArray GstValueArray; + +/** + * GstTimedValue: + * @timestamp: timestamp of the value change + * @value: the corresponding value + * + * Structure for saving a timestamp and a value. + */ +struct _GstTimedValue +{ + GstClockTime timestamp; + gdouble value; +}; + +/** + * GstControlSourceGetValue: + * @self: the #GstControlSource instance + * @timestamp: timestamp for which a value should be calculated + * @value: a value which will be set to the result. + * + * Function for returning a value for a given timestamp. + * + * Returns: %TRUE if the value was successfully calculated. + * + */ +typedef gboolean (* GstControlSourceGetValue) (GstControlSource *self, + GstClockTime timestamp, gdouble *value); + +/** + * GstControlSourceGetValueArray: + * @self: the #GstControlSource instance + * @timestamp: timestamp for which a value should be calculated + * @interval: the time spacing between subsequent values + * @n_values: the number of values + * @values: array to put control-values in + * + * Function for returning an array of values for starting at a given timestamp. + * + * Returns: %TRUE if the values were successfully calculated. + * + */ +typedef gboolean (* GstControlSourceGetValueArray) (GstControlSource *self, + GstClockTime timestamp, GstClockTime interval, guint n_values, gdouble *values); + +/** + * GstControlSource: + * @get_value: Function for returning a value for a given timestamp + * @get_value_array: Function for returning a values array for a given timestamp + * + * The instance structure of #GstControlSource. + */ +struct _GstControlSource { + GstObject parent; + + /*< public >*/ + GstControlSourceGetValue get_value; /* Returns the value for a property at a given timestamp */ + GstControlSourceGetValueArray get_value_array; /* Returns values for a property in a given timespan */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstControlSourceClass: + * @parent_class: Parent class + * + * The class structure of #GstControlSource. + */ + +struct _GstControlSourceClass +{ + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_control_source_get_type (void); + +/* Functions */ + +GST_API +gboolean gst_control_source_get_value (GstControlSource *self, GstClockTime timestamp, + gdouble *value); +GST_API +gboolean gst_control_source_get_value_array (GstControlSource *self, GstClockTime timestamp, + GstClockTime interval, guint n_values, + gdouble *values); +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstControlSource, gst_object_unref) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstValueArray, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_CONTROL_SOURCE_H__ */ diff --git a/gst/gstdatetime.c b/gst/gstdatetime.c new file mode 100644 index 0000000..93205f1 --- /dev/null +++ b/gst/gstdatetime.c @@ -0,0 +1,959 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "glib-compat-private.h" +#include "gstdatetime.h" +#include "gstvalue.h" +#include +#include +#include + +/** + * SECTION:gstdatetime + * @title: GstDateTime + * @short_description: A date, time and timezone structure + * + * Struct to store date, time and timezone information altogether. + * #GstDateTime is refcounted and immutable. + * + * Date information is handled using the proleptic Gregorian calendar. + * + * Provides basic creation functions and accessor functions to its fields. + */ + +typedef enum +{ + GST_DATE_TIME_FIELDS_INVALID = 0, + GST_DATE_TIME_FIELDS_Y, /* have year */ + GST_DATE_TIME_FIELDS_YM, /* have year and month */ + GST_DATE_TIME_FIELDS_YMD, /* have year, month and day */ + GST_DATE_TIME_FIELDS_YMD_HM, + GST_DATE_TIME_FIELDS_YMD_HMS + /* Note: if we ever add more granularity here, e.g. for microsecs, + * the compare function will need updating */ +} GstDateTimeFields; + +struct _GstDateTime +{ + GstMiniObject mini_object; + + GDateTime *datetime; + + GstDateTimeFields fields; +}; + +GType _gst_date_time_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstDateTime, gst_date_time); + +static void gst_date_time_free (GstDateTime * datetime); + +/** + * gst_date_time_new_from_g_date_time: + * @dt: (transfer full): the #GDateTime. The new #GstDateTime takes ownership. + * + * Creates a new #GstDateTime from a #GDateTime object. + * + * Free-function: gst_date_time_unref + * + * Returns: (transfer full) (nullable): a newly created #GstDateTime, + * or %NULL on error + */ +GstDateTime * +gst_date_time_new_from_g_date_time (GDateTime * dt) +{ + GstDateTime *gst_dt; + + if (!dt) + return NULL; + + gst_dt = g_slice_new (GstDateTime); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (gst_dt), 0, GST_TYPE_DATE_TIME, + NULL, NULL, (GstMiniObjectFreeFunction) gst_date_time_free); + + gst_dt->datetime = dt; + gst_dt->fields = GST_DATE_TIME_FIELDS_YMD_HMS; + return gst_dt; +} + +/** + * gst_date_time_to_g_date_time: + * @datetime: GstDateTime. + * + * Creates a new #GDateTime from a fully defined #GstDateTime object. + * + * Free-function: g_date_time_unref + * + * Returns: (transfer full) (nullable): a newly created #GDateTime, or + * %NULL on error + */ +GDateTime * +gst_date_time_to_g_date_time (GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, NULL); + + if (datetime->fields != GST_DATE_TIME_FIELDS_YMD_HMS) + return NULL; + + return g_date_time_add (datetime->datetime, 0); +} + +/** + * gst_date_time_has_year: + * @datetime: a #GstDateTime + * + * Returns: %TRUE if @datetime's year field is set (which should always + * be the case), otherwise %FALSE + */ +gboolean +gst_date_time_has_year (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, FALSE); + + return (datetime->fields >= GST_DATE_TIME_FIELDS_Y); +} + +/** + * gst_date_time_has_month: + * @datetime: a #GstDateTime + * + * Returns: %TRUE if @datetime's month field is set, otherwise %FALSE + */ +gboolean +gst_date_time_has_month (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, FALSE); + + return (datetime->fields >= GST_DATE_TIME_FIELDS_YM); +} + +/** + * gst_date_time_has_day: + * @datetime: a #GstDateTime + * + * Returns: %TRUE if @datetime's day field is set, otherwise %FALSE + */ +gboolean +gst_date_time_has_day (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, FALSE); + + return (datetime->fields >= GST_DATE_TIME_FIELDS_YMD); +} + +/** + * gst_date_time_has_time: + * @datetime: a #GstDateTime + * + * Returns: %TRUE if @datetime's hour and minute fields are set, + * otherwise %FALSE + */ +gboolean +gst_date_time_has_time (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, FALSE); + + return (datetime->fields >= GST_DATE_TIME_FIELDS_YMD_HM); +} + +/** + * gst_date_time_has_second: + * @datetime: a #GstDateTime + * + * Returns: %TRUE if @datetime's second field is set, otherwise %FALSE + */ +gboolean +gst_date_time_has_second (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, FALSE); + + return (datetime->fields >= GST_DATE_TIME_FIELDS_YMD_HMS); +} + +/** + * gst_date_time_get_year: + * @datetime: a #GstDateTime + * + * Returns the year of this #GstDateTime + * Call gst_date_time_has_year before, to avoid warnings. + * + * Return value: The year of this #GstDateTime + */ +gint +gst_date_time_get_year (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + + return g_date_time_get_year (datetime->datetime); +} + +/** + * gst_date_time_get_month: + * @datetime: a #GstDateTime + * + * Returns the month of this #GstDateTime. January is 1, February is 2, etc.. + * Call gst_date_time_has_month before, to avoid warnings. + * + * Return value: The month of this #GstDateTime + */ +gint +gst_date_time_get_month (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_month (datetime), 0); + + return g_date_time_get_month (datetime->datetime); +} + +/** + * gst_date_time_get_day: + * @datetime: a #GstDateTime + * + * Returns the day of the month of this #GstDateTime. + * Call gst_date_time_has_day before, to avoid warnings. + * + * Return value: The day of this #GstDateTime + */ +gint +gst_date_time_get_day (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_day (datetime), 0); + + return g_date_time_get_day_of_month (datetime->datetime); +} + +/** + * gst_date_time_get_hour: + * @datetime: a #GstDateTime + * + * Retrieves the hour of the day represented by @datetime in the gregorian + * calendar. The return is in the range of 0 to 23. + * Call gst_date_time_has_haur before, to avoid warnings. + * + * Return value: the hour of the day + */ +gint +gst_date_time_get_hour (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_time (datetime), 0); + + return g_date_time_get_hour (datetime->datetime); +} + +/** + * gst_date_time_get_minute: + * @datetime: a #GstDateTime + * + * Retrieves the minute of the hour represented by @datetime in the gregorian + * calendar. + * Call gst_date_time_has_minute before, to avoid warnings. + * + * Return value: the minute of the hour + */ +gint +gst_date_time_get_minute (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_time (datetime), 0); + + return g_date_time_get_minute (datetime->datetime); +} + +/** + * gst_date_time_get_second: + * @datetime: a #GstDateTime + * + * Retrieves the second of the minute represented by @datetime in the gregorian + * calendar. + * Call gst_date_time_has_second before, to avoid warnings. + * + * Return value: the second represented by @datetime + */ +gint +gst_date_time_get_second (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_second (datetime), 0); + + return g_date_time_get_second (datetime->datetime); +} + +/** + * gst_date_time_get_microsecond: + * @datetime: a #GstDateTime + * + * Retrieves the fractional part of the seconds in microseconds represented by + * @datetime in the gregorian calendar. + * + * Return value: the microsecond of the second + */ +gint +gst_date_time_get_microsecond (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0); + g_return_val_if_fail (gst_date_time_has_second (datetime), 0); + + return g_date_time_get_microsecond (datetime->datetime); +} + +/** + * gst_date_time_get_time_zone_offset: + * @datetime: a #GstDateTime + * + * Retrieves the offset from UTC in hours that the timezone specified + * by @datetime represents. Timezones ahead (to the east) of UTC have positive + * values, timezones before (to the west) of UTC have negative values. + * If @datetime represents UTC time, then the offset is zero. + * + * Return value: the offset from UTC in hours + */ +gfloat +gst_date_time_get_time_zone_offset (const GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, 0.0); + g_return_val_if_fail (gst_date_time_has_time (datetime), 0.0); + + return (g_date_time_get_utc_offset (datetime->datetime) / + G_USEC_PER_SEC) / 3600.0; +} + +/** + * gst_date_time_new_y: + * @year: the gregorian year + * + * Creates a new #GstDateTime using the date and times in the gregorian calendar + * in the local timezone. + * + * @year should be from 1 to 9999. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_y (gint year) +{ + return gst_date_time_new (0.0, year, -1, -1, -1, -1, -1); +} + +/** + * gst_date_time_new_ym: + * @year: the gregorian year + * @month: the gregorian month + * + * Creates a new #GstDateTime using the date and times in the gregorian calendar + * in the local timezone. + * + * @year should be from 1 to 9999, @month should be from 1 to 12. + * + * If value is -1 then all over value will be ignored. For example + * if @month == -1, then #GstDateTime will created only for @year. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_ym (gint year, gint month) +{ + return gst_date_time_new (0.0, year, month, -1, -1, -1, -1); +} + +/** + * gst_date_time_new_ymd: + * @year: the gregorian year + * @month: the gregorian month + * @day: the day of the gregorian month + * + * Creates a new #GstDateTime using the date and times in the gregorian calendar + * in the local timezone. + * + * @year should be from 1 to 9999, @month should be from 1 to 12, @day from + * 1 to 31. + * + * If value is -1 then all over value will be ignored. For example + * if @month == -1, then #GstDateTime will created only for @year. If + * @day == -1, then #GstDateTime will created for @year and @month and + * so on. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_ymd (gint year, gint month, gint day) +{ + return gst_date_time_new (0.0, year, month, day, -1, -1, -1); +} + +/** + * gst_date_time_new_from_unix_epoch_local_time: + * @secs: seconds from the Unix epoch + * + * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by + * @secs. The #GstDateTime is in the local timezone. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_from_unix_epoch_local_time (gint64 secs) +{ + GDateTime *datetime; + + datetime = g_date_time_new_from_unix_local (secs); + return gst_date_time_new_from_g_date_time (datetime); +} + +/** + * gst_date_time_new_from_unix_epoch_utc: + * @secs: seconds from the Unix epoch + * + * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by + * @secs. The #GstDateTime is in the UTC timezone. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_from_unix_epoch_utc (gint64 secs) +{ + GstDateTime *datetime; + datetime = + gst_date_time_new_from_g_date_time (g_date_time_new_from_unix_utc (secs)); + return datetime; +} + +static GstDateTimeFields +gst_date_time_check_fields (gint * year, gint * month, gint * day, + gint * hour, gint * minute, gdouble * seconds) +{ + if (*month == -1) { + *month = *day = 1; + *hour = *minute = *seconds = 0; + return GST_DATE_TIME_FIELDS_Y; + } else if (*day == -1) { + *day = 1; + *hour = *minute = *seconds = 0; + return GST_DATE_TIME_FIELDS_YM; + } else if (*hour == -1) { + *hour = *minute = *seconds = 0; + return GST_DATE_TIME_FIELDS_YMD; + } else if (*seconds == -1) { + *seconds = 0; + return GST_DATE_TIME_FIELDS_YMD_HM; + } else + return GST_DATE_TIME_FIELDS_YMD_HMS; +} + +/** + * gst_date_time_new_local_time: + * @year: the gregorian year + * @month: the gregorian month, or -1 + * @day: the day of the gregorian month, or -1 + * @hour: the hour of the day, or -1 + * @minute: the minute of the hour, or -1 + * @seconds: the second of the minute, or -1 + * + * Creates a new #GstDateTime using the date and times in the gregorian calendar + * in the local timezone. + * + * @year should be from 1 to 9999, @month should be from 1 to 12, @day from + * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59. + * + * If @month is -1, then the #GstDateTime created will only contain @year, + * and all other fields will be considered not set. + * + * If @day is -1, then the #GstDateTime created will only contain @year and + * @month and all other fields will be considered not set. + * + * If @hour is -1, then the #GstDateTime created will only contain @year and + * @month and @day, and the time fields will be considered not set. In this + * case @minute and @seconds should also be -1. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full) (nullable): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new_local_time (gint year, gint month, gint day, gint hour, + gint minute, gdouble seconds) +{ + GstDateTimeFields fields; + GstDateTime *datetime; + + g_return_val_if_fail (year > 0 && year <= 9999, NULL); + g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL); + g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL); + g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL); + g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL); + g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL); + + fields = gst_date_time_check_fields (&year, &month, &day, + &hour, &minute, &seconds); + + datetime = gst_date_time_new_from_g_date_time (g_date_time_new_local (year, + month, day, hour, minute, seconds)); + + datetime->fields = fields; + return datetime; +} + +/** + * gst_date_time_new_now_local_time: + * + * Creates a new #GstDateTime representing the current date and time. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime which should + * be freed with gst_date_time_unref(). + */ +GstDateTime * +gst_date_time_new_now_local_time (void) +{ + return gst_date_time_new_from_g_date_time (g_date_time_new_now_local ()); +} + +/** + * gst_date_time_new_now_utc: + * + * Creates a new #GstDateTime that represents the current instant at Universal + * coordinated time. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full): the newly created #GstDateTime which should + * be freed with gst_date_time_unref(). + */ +GstDateTime * +gst_date_time_new_now_utc (void) +{ + return gst_date_time_new_from_g_date_time (g_date_time_new_now_utc ()); +} + +gint +__gst_date_time_compare (const GstDateTime * dt1, const GstDateTime * dt2) +{ + gint64 diff; + + /* we assume here that GST_DATE_TIME_FIELDS_YMD_HMS is the highest + * resolution, and ignore microsecond differences on purpose for now */ + if (dt1->fields != dt2->fields) + return GST_VALUE_UNORDERED; + + /* This will round down to nearest second, which is what we want. We're + * not comparing microseconds on purpose here, since we're not + * serialising them when doing new_utc_now() + to_string() */ + diff = + g_date_time_to_unix (dt1->datetime) - g_date_time_to_unix (dt2->datetime); + if (diff < 0) + return GST_VALUE_LESS_THAN; + else if (diff > 0) + return GST_VALUE_GREATER_THAN; + else + return GST_VALUE_EQUAL; +} + +/** + * gst_date_time_new: + * @tzoffset: Offset from UTC in hours. + * @year: the gregorian year + * @month: the gregorian month + * @day: the day of the gregorian month + * @hour: the hour of the day + * @minute: the minute of the hour + * @seconds: the second of the minute + * + * Creates a new #GstDateTime using the date and times in the gregorian calendar + * in the supplied timezone. + * + * @year should be from 1 to 9999, @month should be from 1 to 12, @day from + * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59. + * + * Note that @tzoffset is a float and was chosen so for being able to handle + * some fractional timezones, while it still keeps the readability of + * representing it in hours for most timezones. + * + * If value is -1 then all over value will be ignored. For example + * if @month == -1, then #GstDateTime will created only for @year. If + * @day == -1, then #GstDateTime will created for @year and @month and + * so on. + * + * Free-function: gst_date_time_unref + * + * Return value: (transfer full) (nullable): the newly created #GstDateTime + */ +GstDateTime * +gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour, + gint minute, gdouble seconds) +{ + GstDateTimeFields fields; + gchar buf[6]; + GTimeZone *tz; + GDateTime *dt; + GstDateTime *datetime; + gint tzhour, tzminute; + + g_return_val_if_fail (year > 0 && year <= 9999, NULL); + g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL); + g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL); + g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL); + g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL); + g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL); + g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL); + g_return_val_if_fail ((hour >= 0 && minute >= 0) || + (hour == -1 && minute == -1 && seconds == -1 && tzoffset == 0.0), NULL); + + tzhour = (gint) ABS (tzoffset); + tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60); + + g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour, + tzminute); + + tz = g_time_zone_new (buf); + + fields = gst_date_time_check_fields (&year, &month, &day, + &hour, &minute, &seconds); + + dt = g_date_time_new (tz, year, month, day, hour, minute, seconds); + g_time_zone_unref (tz); + + datetime = gst_date_time_new_from_g_date_time (dt); + datetime->fields = fields; + + return datetime; +} + +gchar * +__gst_date_time_serialize (GstDateTime * datetime, gboolean serialize_usecs) +{ + GString *s; + gfloat gmt_offset; + guint msecs; + + /* we always have at least the year */ + s = g_string_new (NULL); + g_string_append_printf (s, "%04u", gst_date_time_get_year (datetime)); + + if (datetime->fields == GST_DATE_TIME_FIELDS_Y) + goto done; + + /* add month */ + g_string_append_printf (s, "-%02u", gst_date_time_get_month (datetime)); + + if (datetime->fields == GST_DATE_TIME_FIELDS_YM) + goto done; + + /* add day of month */ + g_string_append_printf (s, "-%02u", gst_date_time_get_day (datetime)); + + if (datetime->fields == GST_DATE_TIME_FIELDS_YMD) + goto done; + + /* add time */ + g_string_append_printf (s, "T%02u:%02u", gst_date_time_get_hour (datetime), + gst_date_time_get_minute (datetime)); + + if (datetime->fields == GST_DATE_TIME_FIELDS_YMD_HM) + goto add_timezone; + + /* add seconds */ + g_string_append_printf (s, ":%02u", gst_date_time_get_second (datetime)); + + /* add microseconds */ + if (serialize_usecs) { + msecs = gst_date_time_get_microsecond (datetime); + if (msecs != 0) { + g_string_append_printf (s, ".%06u", msecs); + /* trim trailing 0s */ + while (s->str[s->len - 1] == '0') + g_string_truncate (s, s->len - 1); + } + } + + /* add timezone */ + +add_timezone: + + gmt_offset = gst_date_time_get_time_zone_offset (datetime); + if (gmt_offset == 0) { + g_string_append_c (s, 'Z'); + } else { + guint tzhour, tzminute; + + tzhour = (guint) ABS (gmt_offset); + tzminute = (guint) ((ABS (gmt_offset) - tzhour) * 60); + + g_string_append_c (s, (gmt_offset >= 0) ? '+' : '-'); + g_string_append_printf (s, "%02u%02u", tzhour, tzminute); + } + +done: + + return g_string_free (s, FALSE); +} + +/** + * gst_date_time_to_iso8601_string: + * @datetime: GstDateTime. + * + * Create a minimal string compatible with ISO-8601. Possible output formats + * are (for example): 2012, 2012-06, 2012-06-23, 2012-06-23T23:30Z, + * 2012-06-23T23:30+0100, 2012-06-23T23:30:59Z, 2012-06-23T23:30:59+0100 + * + * Returns: (nullable): a newly allocated string formatted according + * to ISO 8601 and only including the datetime fields that are + * valid, or %NULL in case there was an error. The string should + * be freed with g_free(). + */ +gchar * +gst_date_time_to_iso8601_string (GstDateTime * datetime) +{ + g_return_val_if_fail (datetime != NULL, NULL); + + if (datetime->fields == GST_DATE_TIME_FIELDS_INVALID) + return NULL; + + return __gst_date_time_serialize (datetime, FALSE); +} + +/** + * gst_date_time_new_from_iso8601_string: + * @string: ISO 8601-formatted datetime string. + * + * Tries to parse common variants of ISO-8601 datetime strings into a + * #GstDateTime. Possible input formats are (for example): + * 2012-06-30T22:46:43Z, 2012, 2012-06, 2012-06-30, 2012-06-30T22:46:43-0430, + * 2012-06-30T22:46Z, 2012-06-30T22:46-0430, 2012-06-30 22:46, + * 2012-06-30 22:46:43, 2012-06-00, 2012-00-00, 2012-00-30, 22:46:43Z, 22:46Z, + * 22:46:43-0430, 22:46-0430, 22:46:30, 22:46 + * If no date is provided, it is assumed to be "today" in the timezone + * provided (if any), otherwise UTC. + * + * Free-function: gst_date_time_unref + * + * Returns: (transfer full) (nullable): a newly created #GstDateTime, + * or %NULL on error + */ +GstDateTime * +gst_date_time_new_from_iso8601_string (const gchar * string) +{ + gint year = -1, month = -1, day = -1, hour = -1, minute = -1; + gint gmt_offset_hour = -99, gmt_offset_min = -99; + gdouble second = -1.0; + gfloat tzoffset = 0.0; + guint64 usecs; + gint len, ret; + + g_return_val_if_fail (string != NULL, NULL); + + GST_DEBUG ("Parsing '%s' into a datetime", string); + + len = strlen (string); + + /* The input string is expected to start either with a year (4 digits) or + * with an hour (2 digits). Hour must be followed by minute. In any case, + * the string must be at least 4 characters long and start with 2 digits */ + if (len < 4 || !g_ascii_isdigit (string[0]) || !g_ascii_isdigit (string[1])) + return NULL; + + if (g_ascii_isdigit (string[2]) && g_ascii_isdigit (string[3])) { + ret = sscanf (string, "%04d-%02d-%02d", &year, &month, &day); + + if (ret == 0) + return NULL; + + if (ret == 3 && day <= 0) { + ret = 2; + day = -1; + } + + if (ret >= 2 && month <= 0) { + ret = 1; + month = day = -1; + } + + if (ret >= 1 && (year <= 0 || year > 9999 || month > 12 || day > 31)) + return NULL; + + else if (ret >= 1 && len < 16) + /* YMD is 10 chars. XMD + HM will be 16 chars. if it is less, + * it make no sense to continue. We will stay with YMD. */ + goto ymd; + + string += 10; + /* Exit if there is no expeceted value on this stage */ + if (!(*string == 'T' || *string == '-' || *string == ' ')) + goto ymd; + + string += 1; + } + /* if hour or minute fails, then we will use only ymd. */ + hour = g_ascii_strtoull (string, (gchar **) & string, 10); + if (hour > 24 || *string != ':') + goto ymd; + + /* minute */ + minute = g_ascii_strtoull (string + 1, (gchar **) & string, 10); + if (minute > 59) + goto ymd; + + /* second */ + if (*string == ':') { + second = g_ascii_strtoull (string + 1, (gchar **) & string, 10); + /* if we fail here, we still can reuse hour and minute. We + * will still attempt to parse any timezone information */ + if (second > 59) { + second = -1.0; + } else { + /* microseconds */ + if (*string == '.' || *string == ',') { + const gchar *usec_start = string + 1; + guint digits; + + usecs = g_ascii_strtoull (string + 1, (gchar **) & string, 10); + if (usecs != G_MAXUINT64 && string > usec_start) { + digits = (guint) (string - usec_start); + second += (gdouble) usecs / pow (10.0, digits); + } + } + } + } + + if (*string == 'Z') + goto ymd_hms; + else { + /* reuse some code from gst-plugins-base/gst-libs/gst/tag/gstxmptag.c */ + gint gmt_offset = -1; + 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 (string, '+'); + neg_pos = strrchr (string, '-'); + if (plus_pos) + pos = plus_pos + 1; + else if (neg_pos) + pos = neg_pos + 1; + + if (pos && strlen (pos) >= 3) { + gint ret_tz; + if (pos[2] == ':') + ret_tz = sscanf (pos, "%d:%d", &gmt_offset_hour, &gmt_offset_min); + else + ret_tz = sscanf (pos, "%02d%02d", &gmt_offset_hour, &gmt_offset_min); + + GST_DEBUG ("Parsing timezone: %s", pos); + + if (ret_tz == 2) { + if (neg_pos != NULL && neg_pos + 1 == pos) { + gmt_offset_hour *= -1; + gmt_offset_min *= -1; + } + gmt_offset = gmt_offset_hour * 60 + gmt_offset_min; + + tzoffset = gmt_offset / 60.0; + + GST_LOG ("Timezone offset: %f (%d minutes)", tzoffset, gmt_offset); + } else + GST_WARNING ("Failed to parse timezone information"); + } + } + +ymd_hms: + if (year == -1 || month == -1 || day == -1) { + GDateTime *now_utc, *now_in_given_tz; + + /* No date was supplied: make it today */ + now_utc = g_date_time_new_now_utc (); + if (tzoffset != 0.0) { + /* If a timezone offset was supplied, get the date of that timezone */ + g_assert (gmt_offset_min != -99); + g_assert (gmt_offset_hour != -99); + now_in_given_tz = + g_date_time_add_minutes (now_utc, + (60 * gmt_offset_hour) + gmt_offset_min); + g_date_time_unref (now_utc); + } else { + now_in_given_tz = now_utc; + } + g_date_time_get_ymd (now_in_given_tz, &year, &month, &day); + g_date_time_unref (now_in_given_tz); + } + return gst_date_time_new (tzoffset, year, month, day, hour, minute, second); +ymd: + if (year == -1) { + /* No date was supplied and time failed to parse */ + return NULL; + } + return gst_date_time_new_ymd (year, month, day); +} + +static void +gst_date_time_free (GstDateTime * datetime) +{ + g_date_time_unref (datetime->datetime); + g_slice_free (GstDateTime, datetime); +} + +/** + * gst_date_time_ref: + * @datetime: a #GstDateTime + * + * Atomically increments the reference count of @datetime by one. + * + * Return value: (transfer full): the reference @datetime + */ +GstDateTime * +gst_date_time_ref (GstDateTime * datetime) +{ + return (GstDateTime *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (datetime)); +} + +/** + * gst_date_time_unref: + * @datetime: (transfer full): a #GstDateTime + * + * Atomically decrements the reference count of @datetime by one. When the + * reference count reaches zero, the structure is freed. + */ +void +gst_date_time_unref (GstDateTime * datetime) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (datetime)); +} + +void +_priv_gst_date_time_initialize (void) +{ + _gst_date_time_type = gst_date_time_get_type (); +} diff --git a/gst/gstdatetime.h b/gst/gstdatetime.h new file mode 100644 index 0000000..61a32ec --- /dev/null +++ b/gst/gstdatetime.h @@ -0,0 +1,163 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_DATE_TIME_H__ +#define __GST_DATE_TIME_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstDateTime: + * + * Opaque, immutable, refcounted struct that stores date, time and timezone + * information. It currently supports ranges from 0001-01-01 to + * 9999-12-31 in the Gregorian proleptic calendar. + * + * Use the accessor functions to get the stored values. + */ +typedef struct _GstDateTime GstDateTime; + +GST_API GType _gst_date_time_type; + +/** + * GST_TYPE_DATE_TIME: + * + * a boxed #GValue type for #GstDateTime that represents a date and time. + * + * Returns: the #GType of GstDateTime + */ + +#define GST_TYPE_DATE_TIME (_gst_date_time_type) + +GST_API +GType gst_date_time_get_type (void); + +/* query which fields are set */ + +GST_API +gboolean gst_date_time_has_year (const GstDateTime * datetime); + +GST_API +gboolean gst_date_time_has_month (const GstDateTime * datetime); + +GST_API +gboolean gst_date_time_has_day (const GstDateTime * datetime); + +GST_API +gboolean gst_date_time_has_time (const GstDateTime * datetime); + +GST_API +gboolean gst_date_time_has_second (const GstDateTime * datetime); + +/* field getters */ + +GST_API +gint gst_date_time_get_year (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_month (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_day (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_hour (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_minute (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_second (const GstDateTime * datetime); + +GST_API +gint gst_date_time_get_microsecond (const GstDateTime * datetime); + +GST_API +gfloat gst_date_time_get_time_zone_offset (const GstDateTime * datetime); + +/* constructors */ + +GST_API +GstDateTime * gst_date_time_new_from_unix_epoch_local_time (gint64 secs) G_GNUC_MALLOC; + +GST_API +GstDateTime * gst_date_time_new_from_unix_epoch_utc (gint64 secs) G_GNUC_MALLOC; + +GST_API +GstDateTime * gst_date_time_new_local_time (gint year, + gint month, + gint day, + gint hour, + gint minute, + gdouble seconds) G_GNUC_MALLOC; +GST_API +GstDateTime * gst_date_time_new_y (gint year) G_GNUC_MALLOC; + +GST_API +GstDateTime * gst_date_time_new_ym (gint year, + gint month) G_GNUC_MALLOC; +GST_API +GstDateTime * gst_date_time_new_ymd (gint year, + gint month, + gint day) G_GNUC_MALLOC; +GST_API +GstDateTime * gst_date_time_new (gfloat tzoffset, + gint year, gint month, + gint day, gint hour, + gint minute, + gdouble seconds) G_GNUC_MALLOC; +GST_API +GstDateTime * gst_date_time_new_now_local_time (void) G_GNUC_MALLOC; + +GST_API +GstDateTime * gst_date_time_new_now_utc (void) G_GNUC_MALLOC; + +GST_API +gchar * gst_date_time_to_iso8601_string (GstDateTime * datetime) G_GNUC_MALLOC; + +GST_API +GstDateTime * gst_date_time_new_from_iso8601_string (const gchar * string) G_GNUC_MALLOC; + +GST_API +GDateTime * gst_date_time_to_g_date_time (GstDateTime * datetime); + +GST_API +GstDateTime * gst_date_time_new_from_g_date_time (GDateTime * dt); + +/* refcounting */ + +GST_API +GstDateTime * gst_date_time_ref (GstDateTime * datetime); + +GST_API +void gst_date_time_unref (GstDateTime * datetime); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDateTime, gst_date_time_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DATE_TIME_H__ */ diff --git a/gst/gstdebugutils.c b/gst/gstdebugutils.c new file mode 100644 index 0000000..4584af3 --- /dev/null +++ b/gst/gstdebugutils.c @@ -0,0 +1,921 @@ +/* GStreamer + * Copyright (C) 2007 Stefan Kost + * + * gstdebugutils.c: debugging and analysis utillities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* TODO: + * edge [ constraint=false ]; + * this creates strange graphs ("minlen=0" is better) + * try puting src/sink ghostpads for each bin into invisible clusters + * + * for more compact nodes, try + * - changing node-shape from box into record + * - use labels like : element [ label="{element | src | sink}"] + * - point to record-connectors : element1:src -> element2:sink + * - we use head/tail labels for pad-caps right now + * - this does not work well, as dot seems to not look at their size when + * doing the layout + * - we could add the caps to the pad itself, then we should use one line per + * caps (simple caps = one line) + */ + +#include "gst_private.h" +#include "gstdebugutils.h" + +#ifndef GST_DISABLE_GST_DEBUG + +#include +#include +#include +#include + +#include "gstinfo.h" +#include "gstbin.h" +#include "gstobject.h" +#include "gstghostpad.h" +#include "gstpad.h" +#include "gstutils.h" +#include "gstvalue.h" + +/*** PIPELINE GRAPHS **********************************************************/ + +extern const gchar *priv_gst_dump_dot_dir; /* NULL *//* set from gst.c */ + +#define PARAM_MAX_LENGTH 80 + +static const gchar spaces[] = { + " " /* 32 */ + " " /* 64 */ + " " /* 96 */ + " " /* 128 */ +}; + +#define MAKE_INDENT(indent) \ + &spaces[MAX (sizeof (spaces) - (1 + (indent) * 2), 0)] + +static gchar * +debug_dump_make_object_name (GstObject * obj) +{ + return g_strcanon (g_strdup_printf ("%s_%p", GST_OBJECT_NAME (obj), obj), + G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_", '_'); +} + +static gchar * +debug_dump_get_element_state (GstElement * element) +{ + gchar *state_name = NULL; + const gchar *state_icons = "~0-=>"; + GstState state = GST_STATE_VOID_PENDING, pending = GST_STATE_VOID_PENDING; + + gst_element_get_state (element, &state, &pending, 0); + if (pending == GST_STATE_VOID_PENDING) { + gboolean is_locked = gst_element_is_locked_state (element); + state_name = g_strdup_printf ("\\n[%c]%s", state_icons[state], + (is_locked ? "(locked)" : "")); + } else { + state_name = g_strdup_printf ("\\n[%c] -> [%c]", state_icons[state], + state_icons[pending]); + } + return state_name; +} + +static gchar * +debug_dump_get_object_params (GObject * object, + GstDebugGraphDetails details, const char *const *ignored_propnames) +{ + gchar *param_name = NULL; + GParamSpec **properties, *property; + GValue value = { 0, }; + guint i, number_of_properties; + gchar *tmp, *value_str; + const gchar *ellipses; + + /* get paramspecs and show non-default properties */ + properties = + g_object_class_list_properties (G_OBJECT_GET_CLASS (object), + &number_of_properties); + if (properties) { + for (i = 0; i < number_of_properties; i++) { + gint j; + gboolean ignore = FALSE; + property = properties[i]; + + /* skip some properties */ + if (!(property->flags & G_PARAM_READABLE)) + continue; + if (!strcmp (property->name, "name")) + continue; + + if (ignored_propnames) + for (j = 0; ignored_propnames[j]; j++) + if (!g_strcmp0 (ignored_propnames[j], property->name)) + ignore = TRUE; + + if (ignore) + continue; + + g_value_init (&value, property->value_type); + g_object_get_property (G_OBJECT (object), property->name, &value); + if (!(g_param_value_defaults (property, &value))) { + /* we need to serialise enums and flags ourselves to make sure the + * enum/flag nick is used and not the enum/flag name, which would be the + * C header enum/flag for public enums/flags, but for element-specific + * enums/flags we abuse the name field for the property description, + * and we don't want to print that in the dot file. The nick will + * always work, and it's also shorter. */ + if (G_VALUE_HOLDS_ENUM (&value)) { + GEnumClass *e_class = g_type_class_ref (G_VALUE_TYPE (&value)); + gint idx, e_val; + + tmp = NULL; + e_val = g_value_get_enum (&value); + for (idx = 0; idx < e_class->n_values; ++idx) { + if (e_class->values[idx].value == e_val) { + tmp = g_strdup (e_class->values[idx].value_nick); + break; + } + } + if (tmp == NULL) { + g_value_unset (&value); + continue; + } + } else if (G_VALUE_HOLDS_FLAGS (&value)) { + GFlagsClass *f_class = g_type_class_ref (G_VALUE_TYPE (&value)); + GFlagsValue *vals = f_class->values; + GString *s = NULL; + guint idx, flags_left; + + s = g_string_new (NULL); + + /* we assume the values are sorted from lowest to highest value */ + flags_left = g_value_get_flags (&value); + idx = f_class->n_values; + while (idx > 0) { + --idx; + if (vals[idx].value != 0 + && (flags_left & vals[idx].value) == vals[idx].value) { + if (s->len > 0) + g_string_prepend_c (s, '+'); + g_string_prepend (s, vals[idx].value_nick); + flags_left -= vals[idx].value; + if (flags_left == 0) + break; + } + } + + if (s->len == 0) + g_string_assign (s, "(none)"); + + tmp = g_string_free (s, FALSE); + } else { + tmp = g_strdup_value_contents (&value); + } + value_str = g_strescape (tmp, NULL); + g_free (tmp); + + /* too long, ellipsize */ + if (!(details & GST_DEBUG_GRAPH_SHOW_FULL_PARAMS) && + strlen (value_str) > PARAM_MAX_LENGTH) + ellipses = "…"; + else + ellipses = ""; + + if (param_name) + tmp = param_name; + else + tmp = (char *) ""; + + if (details & GST_DEBUG_GRAPH_SHOW_FULL_PARAMS) { + param_name = g_strdup_printf ("%s\\n%s=%s", tmp, property->name, + value_str); + } else { + param_name = g_strdup_printf ("%s\\n%s=%." + G_STRINGIFY (PARAM_MAX_LENGTH) "s%s", tmp, property->name, + value_str, ellipses); + } + + if (tmp[0] != '\0') + g_free (tmp); + + g_free (value_str); + } + g_value_unset (&value); + } + g_free (properties); + } + return param_name; +} + +static void +debug_dump_pad (GstPad * pad, const gchar * color_name, + const gchar * element_name, GstDebugGraphDetails details, GString * str, + const gint indent) +{ + GstPadTemplate *pad_templ; + GstPadPresence presence; + gchar *pad_name, *param_name = NULL; + const gchar *style_name; + static const char *const ignore_propnames[] = + { "parent", "direction", "template", + "caps", NULL + }; + const gchar *spc = MAKE_INDENT (indent); + + pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); + + /* pad availability */ + style_name = "filled,solid"; + if ((pad_templ = gst_pad_get_pad_template (pad))) { + presence = GST_PAD_TEMPLATE_PRESENCE (pad_templ); + gst_object_unref (pad_templ); + if (presence == GST_PAD_SOMETIMES) { + style_name = "filled,dotted"; + } else if (presence == GST_PAD_REQUEST) { + style_name = "filled,dashed"; + } + } + + param_name = + debug_dump_get_object_params (G_OBJECT (pad), details, ignore_propnames); + if (details & GST_DEBUG_GRAPH_SHOW_STATES) { + gchar pad_flags[5]; + const gchar *activation_mode = "-><"; + const gchar *task_mode = ""; + GstTask *task; + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task) { + switch (gst_task_get_state (task)) { + case GST_TASK_STARTED: + task_mode = "[T]"; + break; + case GST_TASK_PAUSED: + task_mode = "[t]"; + break; + default: + /* Invalid task state, ignoring */ + break; + } + } + GST_OBJECT_UNLOCK (pad); + + /* check if pad flags */ + pad_flags[0] = + GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED) ? 'B' : 'b'; + pad_flags[1] = + GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING) ? 'F' : 'f'; + pad_flags[2] = + GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING) ? 'B' : 'b'; + pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS) ? 'E' : '\0'; + pad_flags[4] = '\0'; + + g_string_append_printf (str, + "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s%s\\n[%c][%s]%s\", height=\"0.2\", style=\"%s\"];\n", + spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), + (param_name ? param_name : ""), + activation_mode[pad->mode], pad_flags, task_mode, style_name); + } else { + g_string_append_printf (str, + "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s%s\", height=\"0.2\", style=\"%s\"];\n", + spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), + (param_name ? param_name : ""), style_name); + } + + g_free (param_name); + g_free (pad_name); +} + +static void +debug_dump_element_pad (GstPad * pad, GstElement * element, + GstDebugGraphDetails details, GString * str, const gint indent) +{ + GstElement *target_element; + GstPad *target_pad, *tmp_pad; + GstPadDirection dir; + gchar *element_name; + gchar *target_element_name; + const gchar *color_name; + + dir = gst_pad_get_direction (pad); + element_name = debug_dump_make_object_name (GST_OBJECT (element)); + if (GST_IS_GHOST_PAD (pad)) { + color_name = + (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir == + GST_PAD_SINK) ? "#ddddff" : "#ffffff"); + /* output target-pad so that it belongs to this element */ + if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) { + if ((target_pad = gst_pad_get_peer (tmp_pad))) { + gchar *pad_name, *target_pad_name; + const gchar *spc = MAKE_INDENT (indent); + + if ((target_element = gst_pad_get_parent_element (target_pad))) { + target_element_name = + debug_dump_make_object_name (GST_OBJECT (target_element)); + } else { + target_element_name = g_strdup (""); + } + debug_dump_pad (target_pad, color_name, target_element_name, details, + str, indent); + /* src ghostpad relationship */ + pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); + target_pad_name = debug_dump_make_object_name (GST_OBJECT (target_pad)); + if (dir == GST_PAD_SRC) { + g_string_append_printf (str, + "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, + target_element_name, target_pad_name, element_name, pad_name); + } else { + g_string_append_printf (str, + "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc, + element_name, pad_name, target_element_name, target_pad_name); + } + g_free (target_pad_name); + g_free (target_element_name); + if (target_element) + gst_object_unref (target_element); + gst_object_unref (target_pad); + g_free (pad_name); + } + gst_object_unref (tmp_pad); + } + } else { + color_name = + (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir == + GST_PAD_SINK) ? "#aaaaff" : "#cccccc"); + } + /* pads */ + debug_dump_pad (pad, color_name, element_name, details, str, indent); + g_free (element_name); +} + +static gboolean +string_append_field (GQuark field, const GValue * value, gpointer ptr) +{ + GString *str = (GString *) ptr; + gchar *value_str = gst_value_serialize (value); + gchar *esc_value_str; + + if (value_str == NULL) { + g_string_append_printf (str, " %18s: NULL\\l", g_quark_to_string (field)); + return TRUE; + } + + /* some enums can become really long */ + if (strlen (value_str) > 25) { + gint pos = 24; + + /* truncate */ + value_str[25] = '\0'; + + /* mirror any brackets and quotes */ + if (value_str[0] == '<') + value_str[pos--] = '>'; + if (value_str[0] == '[') + value_str[pos--] = ']'; + if (value_str[0] == '(') + value_str[pos--] = ')'; + if (value_str[0] == '{') + value_str[pos--] = '}'; + if (value_str[0] == '"') + value_str[pos--] = '"'; + if (pos != 24) + value_str[pos--] = ' '; + /* elippsize */ + value_str[pos--] = '.'; + value_str[pos--] = '.'; + value_str[pos--] = '.'; + } + esc_value_str = g_strescape (value_str, NULL); + + g_string_append_printf (str, " %18s: %s\\l", g_quark_to_string (field), + esc_value_str); + + g_free (value_str); + g_free (esc_value_str); + return TRUE; +} + +static gchar * +debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details) +{ + gchar *media = NULL; + + if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) { + + if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) { + media = gst_caps_to_string (caps); + + } else { + GString *str = NULL; + guint i; + guint slen = 0; + + for (i = 0; i < gst_caps_get_size (caps); i++) { + slen += 25 + + STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i)); + } + + str = g_string_sized_new (slen); + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstCapsFeatures *features = __gst_caps_get_features_unchecked (caps, i); + GstStructure *structure = gst_caps_get_structure (caps, i); + + g_string_append (str, gst_structure_get_name (structure)); + + if (features && (gst_caps_features_is_any (features) + || !gst_caps_features_is_equal (features, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) { + g_string_append_c (str, '('); + priv_gst_caps_features_append_to_gstring (features, str); + g_string_append_c (str, ')'); + } + g_string_append (str, "\\l"); + + gst_structure_foreach (structure, string_append_field, (gpointer) str); + } + + media = g_string_free (str, FALSE); + } + + } else { + if (GST_CAPS_IS_SIMPLE (caps)) + media = + g_strdup (gst_structure_get_name (gst_caps_get_structure (caps, 0))); + else + media = g_strdup ("*"); + } + return media; +} + +static void +debug_dump_element_pad_link (GstPad * pad, GstElement * element, + GstDebugGraphDetails details, GString * str, const gint indent) +{ + GstElement *peer_element; + GstPad *peer_pad; + GstCaps *caps, *peer_caps; + gchar *media = NULL; + gchar *media_src = NULL, *media_sink = NULL; + gchar *pad_name, *element_name; + gchar *peer_pad_name, *peer_element_name; + const gchar *spc = MAKE_INDENT (indent); + + if ((peer_pad = gst_pad_get_peer (pad))) { + if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) || + (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) + ) { + caps = gst_pad_get_current_caps (pad); + if (!caps) + caps = gst_pad_get_pad_template_caps (pad); + peer_caps = gst_pad_get_current_caps (peer_pad); + if (!peer_caps) + peer_caps = gst_pad_get_pad_template_caps (peer_pad); + + media = debug_dump_describe_caps (caps, details); + /* check if peer caps are different */ + if (peer_caps && !gst_caps_is_equal (caps, peer_caps)) { + gchar *tmp; + + tmp = debug_dump_describe_caps (peer_caps, details); + if (gst_pad_get_direction (pad) == GST_PAD_SRC) { + media_src = media; + media_sink = tmp; + } else { + media_src = tmp; + media_sink = media; + } + media = NULL; + } + gst_caps_unref (peer_caps); + gst_caps_unref (caps); + } + + pad_name = debug_dump_make_object_name (GST_OBJECT (pad)); + if (element) { + element_name = debug_dump_make_object_name (GST_OBJECT (element)); + } else { + element_name = g_strdup (""); + } + peer_pad_name = debug_dump_make_object_name (GST_OBJECT (peer_pad)); + if ((peer_element = gst_pad_get_parent_element (peer_pad))) { + peer_element_name = + debug_dump_make_object_name (GST_OBJECT (peer_element)); + } else { + peer_element_name = g_strdup (""); + } + + /* pad link */ + if (media) { + g_string_append_printf (str, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc, + element_name, pad_name, peer_element_name, peer_pad_name, media); + g_free (media); + } else if (media_src && media_sink) { + /* dot has some issues with placement of head and taillabels, + * we need an empty label to make space */ + g_string_append_printf (str, + "%s%s_%s -> %s_%s [labeldistance=\"10\", labelangle=\"0\", " + "label=\" \", " + "taillabel=\"%s\", headlabel=\"%s\"]\n", + spc, element_name, pad_name, peer_element_name, peer_pad_name, + media_src, media_sink); + g_free (media_src); + g_free (media_sink); + } else { + g_string_append_printf (str, "%s%s_%s -> %s_%s\n", spc, + element_name, pad_name, peer_element_name, peer_pad_name); + } + + g_free (pad_name); + g_free (element_name); + g_free (peer_pad_name); + g_free (peer_element_name); + if (peer_element) + gst_object_unref (peer_element); + gst_object_unref (peer_pad); + } +} + +static void +debug_dump_element_pads (GstIterator * pad_iter, GstPad * pad, + GstElement * element, GstDebugGraphDetails details, GString * str, + const gint indent, guint * num_pads, gchar * cluster_name, + gchar ** first_pad_name) +{ + GValue item = { 0, }; + gboolean pads_done; + const gchar *spc = MAKE_INDENT (indent); + + pads_done = FALSE; + while (!pads_done) { + switch (gst_iterator_next (pad_iter, &item)) { + case GST_ITERATOR_OK: + pad = g_value_get_object (&item); + if (!*num_pads) { + g_string_append_printf (str, "%ssubgraph cluster_%s {\n", spc, + cluster_name); + g_string_append_printf (str, "%s label=\"\";\n", spc); + g_string_append_printf (str, "%s style=\"invis\";\n", spc); + (*first_pad_name) = debug_dump_make_object_name (GST_OBJECT (pad)); + } + debug_dump_element_pad (pad, element, details, str, indent); + (*num_pads)++; + g_value_reset (&item); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pad_iter); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + pads_done = TRUE; + break; + } + } + if (*num_pads) { + g_string_append_printf (str, "%s}\n\n", spc); + } +} + +/* + * debug_dump_element: + * @bin: the bin that should be analyzed + * @out: file to write to + * @indent: level of graph indentation + * + * Helper for gst_debug_bin_to_dot_file() to recursively dump a pipeline. + */ +static void +debug_dump_element (GstBin * bin, GstDebugGraphDetails details, + GString * str, const gint indent) +{ + GstIterator *element_iter, *pad_iter; + gboolean elements_done, pads_done; + GValue item = { 0, }; + GValue item2 = { 0, }; + GstElement *element; + GstPad *pad = NULL; + guint src_pads, sink_pads; + gchar *src_pad_name = NULL, *sink_pad_name = NULL; + gchar *element_name; + gchar *state_name = NULL; + gchar *param_name = NULL; + const gchar *spc = MAKE_INDENT (indent); + + element_iter = gst_bin_iterate_elements (bin); + elements_done = FALSE; + while (!elements_done) { + switch (gst_iterator_next (element_iter, &item)) { + case GST_ITERATOR_OK: + element = g_value_get_object (&item); + element_name = debug_dump_make_object_name (GST_OBJECT (element)); + + if (details & GST_DEBUG_GRAPH_SHOW_STATES) { + state_name = debug_dump_get_element_state (GST_ELEMENT (element)); + } + if (details & GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS) { + param_name = debug_dump_get_object_params (G_OBJECT (element), + details, NULL); + } + /* elements */ + g_string_append_printf (str, "%ssubgraph cluster_%s {\n", spc, + element_name); + g_string_append_printf (str, "%s fontname=\"Bitstream Vera Sans\";\n", + spc); + g_string_append_printf (str, "%s fontsize=\"8\";\n", spc); + g_string_append_printf (str, "%s style=\"filled,rounded\";\n", spc); + g_string_append_printf (str, "%s color=black;\n", spc); + g_string_append_printf (str, "%s label=\"%s\\n%s%s%s\";\n", spc, + G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element), + (state_name ? state_name : ""), (param_name ? param_name : "") + ); + if (state_name) { + g_free (state_name); + state_name = NULL; + } + if (param_name) { + g_free (param_name); + param_name = NULL; + } + + src_pads = sink_pads = 0; + if ((pad_iter = gst_element_iterate_sink_pads (element))) { + gchar *cluster_name = g_strdup_printf ("%s_sink", element_name); + debug_dump_element_pads (pad_iter, pad, element, details, str, + indent + 1, &sink_pads, cluster_name, &sink_pad_name); + g_free (cluster_name); + gst_iterator_free (pad_iter); + } + if ((pad_iter = gst_element_iterate_src_pads (element))) { + gchar *cluster_name = g_strdup_printf ("%s_src", element_name); + debug_dump_element_pads (pad_iter, pad, element, details, str, + indent + 1, &src_pads, cluster_name, &src_pad_name); + g_free (cluster_name); + gst_iterator_free (pad_iter); + } + if (sink_pads && src_pads) { + /* add invisible link from first sink to first src pad */ + g_string_append_printf (str, + "%s %s_%s -> %s_%s [style=\"invis\"];\n", + spc, element_name, sink_pad_name, element_name, src_pad_name); + } + g_free (sink_pad_name); + g_free (src_pad_name); + g_free (element_name); + sink_pad_name = src_pad_name = NULL; + if (GST_IS_BIN (element)) { + g_string_append_printf (str, "%s fillcolor=\"#ffffff\";\n", spc); + /* recurse */ + debug_dump_element (GST_BIN (element), details, str, indent + 1); + } else { + if (src_pads && !sink_pads) + g_string_append_printf (str, "%s fillcolor=\"#ffaaaa\";\n", spc); + else if (!src_pads && sink_pads) + g_string_append_printf (str, "%s fillcolor=\"#aaaaff\";\n", spc); + else if (src_pads && sink_pads) + g_string_append_printf (str, "%s fillcolor=\"#aaffaa\";\n", spc); + else + g_string_append_printf (str, "%s fillcolor=\"#ffffff\";\n", spc); + } + g_string_append_printf (str, "%s}\n\n", spc); + if ((pad_iter = gst_element_iterate_pads (element))) { + pads_done = FALSE; + while (!pads_done) { + switch (gst_iterator_next (pad_iter, &item2)) { + case GST_ITERATOR_OK: + pad = g_value_get_object (&item2); + if (gst_pad_is_linked (pad)) { + if (gst_pad_get_direction (pad) == GST_PAD_SRC) { + debug_dump_element_pad_link (pad, element, details, str, + indent); + } else { + GstPad *peer_pad = gst_pad_get_peer (pad); + + if (peer_pad) { + if (!GST_IS_GHOST_PAD (peer_pad) + && GST_IS_PROXY_PAD (peer_pad)) { + debug_dump_element_pad_link (peer_pad, NULL, details, + str, indent); + } + gst_object_unref (peer_pad); + } + } + } + g_value_reset (&item2); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pad_iter); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + pads_done = TRUE; + break; + } + } + g_value_unset (&item2); + gst_iterator_free (pad_iter); + } + g_value_reset (&item); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (element_iter); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + elements_done = TRUE; + break; + } + } + + g_value_unset (&item); + gst_iterator_free (element_iter); +} + +static void +debug_dump_header (GstBin * bin, GstDebugGraphDetails details, GString * str) +{ + gchar *state_name = NULL; + gchar *param_name = NULL; + + if (details & GST_DEBUG_GRAPH_SHOW_STATES) { + state_name = debug_dump_get_element_state (GST_ELEMENT (bin)); + } + if (details & GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS) { + param_name = debug_dump_get_object_params (G_OBJECT (bin), details, NULL); + } + + /* write header */ + g_string_append_printf (str, + "digraph pipeline {\n" + " rankdir=LR;\n" + " fontname=\"sans\";\n" + " fontsize=\"10\";\n" + " labelloc=t;\n" + " nodesep=.1;\n" + " ranksep=.2;\n" + " label=\"<%s>\\n%s%s%s\";\n" + " node [style=\"filled,rounded\", shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n" + " edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n" + " \n" + " legend [\n" + " pos=\"0,0!\",\n" + " margin=\"0.05,0.05\",\n" + " style=\"filled\",\n" + " label=\"Legend\\lElement-States: [~] void-pending, [0] null, [-] ready, [=] paused, [>] playing\\lPad-Activation: [-] none, [>] push, [<] pull\\lPad-Flags: [b]locked, [f]lushing, [b]locking, [E]OS; upper-case is set\\lPad-Task: [T] has started task, [t] has paused task\\l\",\n" + " ];" + "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin), + (state_name ? state_name : ""), (param_name ? param_name : "") + ); + + if (state_name) + g_free (state_name); + if (param_name) + g_free (param_name); +} + +static void +debug_dump_footer (GString * str) +{ + g_string_append_printf (str, "}\n"); +} + +/** + * gst_debug_bin_to_dot_data: + * @bin: the top-level pipeline that should be analyzed + * + * To aid debugging applications one can use this method to obtain the whole + * network of gstreamer elements that form the pipeline into an dot file. + * This data can be processed with graphviz to get an image. + * + * Returns: (transfer full): a string containing the pipeline in graphviz + * dot format. + */ +gchar * +gst_debug_bin_to_dot_data (GstBin * bin, GstDebugGraphDetails details) +{ + GString *str; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + + str = g_string_new (NULL); + + debug_dump_header (bin, details, str); + debug_dump_element (bin, details, str, 1); + debug_dump_footer (str); + + return g_string_free (str, FALSE); +} + +/** + * gst_debug_bin_to_dot_file: + * @bin: the top-level pipeline that should be analyzed + * @file_name: (type filename): output base filename (e.g. "myplayer") + * + * To aid debugging applications one can use this method to write out the whole + * network of gstreamer elements that form the pipeline into an dot file. + * This file can be processed with graphviz to get an image. + * + * dot -Tpng -oimage.png graph_lowlevel.dot + * + */ +void +gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details, + const gchar * file_name) +{ + gchar *full_file_name = NULL; + FILE *out; + + g_return_if_fail (GST_IS_BIN (bin)); + + if (G_LIKELY (priv_gst_dump_dot_dir == NULL)) + return; + + if (!file_name) { + file_name = g_get_application_name (); + if (!file_name) + file_name = "unnamed"; + } + + full_file_name = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.dot", + priv_gst_dump_dot_dir, file_name); + + if ((out = fopen (full_file_name, "wb"))) { + gchar *buf; + + buf = gst_debug_bin_to_dot_data (bin, details); + fputs (buf, out); + + g_free (buf); + fclose (out); + + GST_INFO ("wrote bin graph to : '%s'", full_file_name); + } else { + GST_WARNING ("Failed to open file '%s' for writing: %s", full_file_name, + g_strerror (errno)); + } + g_free (full_file_name); +} + +/** + * gst_debug_bin_to_dot_file_with_ts: + * @bin: the top-level pipeline that should be analyzed + * @file_name: (type filename): output base filename (e.g. "myplayer") + * + * This works like gst_debug_bin_to_dot_file(), but adds the current timestamp + * to the filename, so that it can be used to take multiple snapshots. + */ +void +gst_debug_bin_to_dot_file_with_ts (GstBin * bin, + GstDebugGraphDetails details, const gchar * file_name) +{ + gchar *ts_file_name = NULL; + GstClockTime elapsed; + + g_return_if_fail (GST_IS_BIN (bin)); + + if (!file_name) { + file_name = g_get_application_name (); + if (!file_name) + file_name = "unnamed"; + } + + /* add timestamp */ + elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ()); + + /* we don't use GST_TIME_FORMAT as such filenames would fail on some + * filesystems like fat */ + ts_file_name = + g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed), + file_name); + + gst_debug_bin_to_dot_file (bin, details, ts_file_name); + g_free (ts_file_name); +} +#else /* !GST_DISABLE_GST_DEBUG */ +#ifndef GST_REMOVE_DISABLED +void +gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details, + const gchar * file_name) +{ +} + +void +gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details, + const gchar * file_name) +{ +} +#endif /* GST_REMOVE_DISABLED */ +#endif /* GST_DISABLE_GST_DEBUG */ diff --git a/gst/gstdebugutils.h b/gst/gstdebugutils.h new file mode 100644 index 0000000..8e36cfc --- /dev/null +++ b/gst/gstdebugutils.h @@ -0,0 +1,118 @@ +/* GStreamer + * Copyright (C) 2007 Stefan Kost + * + * gstdebugutils.h: debugging and analysis utillities + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GSTDEBUGUTILS_H__ +#define __GSTDEBUGUTILS_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstDebugGraphDetails: + * @GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE: show caps-name on edges + * @GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS: show caps-details on edges + * @GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS: show modified parameters on + * elements + * @GST_DEBUG_GRAPH_SHOW_STATES: show element states + * @GST_DEBUG_GRAPH_SHOW_FULL_PARAMS: show full element parameter values even + * if they are very long + * @GST_DEBUG_GRAPH_SHOW_ALL: show all the typical details that one might want + * @GST_DEBUG_GRAPH_SHOW_VERBOSE: show all details regardless of how large or + * verbose they make the resulting output + * + * Available details for pipeline graphs produced by GST_DEBUG_BIN_TO_DOT_FILE() + * and GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(). + */ +typedef enum { + GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE = (1<<0), + GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS = (1<<1), + GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS = (1<<2), + GST_DEBUG_GRAPH_SHOW_STATES = (1<<3), + GST_DEBUG_GRAPH_SHOW_FULL_PARAMS = (1<<4), + GST_DEBUG_GRAPH_SHOW_ALL = ((1<<4)-1), + GST_DEBUG_GRAPH_SHOW_VERBOSE = (-1) +} GstDebugGraphDetails; + + +/********** pipeline graphs **********/ + +GST_API +gchar * gst_debug_bin_to_dot_data (GstBin *bin, GstDebugGraphDetails details); + +GST_API +void gst_debug_bin_to_dot_file (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name); + +GST_API +void gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name); + +#ifndef GST_DISABLE_GST_DEBUG + +/** + * GST_DEBUG_BIN_TO_DOT_FILE: + * @bin: the top-level pipeline that should be analyzed + * @details: details to show in the graph, e.g. #GST_DEBUG_GRAPH_SHOW_ALL or + * one or more other #GstDebugGraphDetails flags. + * @file_name: output base filename (e.g. "myplayer") + * + * To aid debugging applications one can use this method to write out the whole + * network of gstreamer elements that form the pipeline into an dot file. + * This file can be processed with graphviz to get an image, like this: + * |[ + * dot -Tpng -oimage.png graph_lowlevel.dot + * ]| + * There is also a utility called xdot which allows you to view the dot file + * directly without converting it first. + * + * The macro is only active if gstreamer is configured with + * "--gst-enable-gst-debug" and the environment variable + * GST_DEBUG_DUMP_DOT_DIR is set to a basepath (e.g. /tmp). + */ +#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) gst_debug_bin_to_dot_file (bin, details, file_name) + +/** + * GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS: + * @bin: the top-level pipeline that should be analyzed + * @details: details to show in the graph, e.g. #GST_DEBUG_GRAPH_SHOW_ALL or + * one or more other #GstDebugGraphDetails flags. + * @file_name: output base filename (e.g. "myplayer") + * + * This works like GST_DEBUG_BIN_TO_DOT_FILE(), but adds the current timestamp + * to the filename, so that it can be used to take multiple snapshots. + */ +#define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) gst_debug_bin_to_dot_file_with_ts (bin, details, file_name) + + +#else /* GST_DISABLE_GST_DEBUG */ + + +#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) +#define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) + +#endif /* GST_DISABLE_GST_DEBUG */ + +G_END_DECLS + +#endif /* __GSTDEBUGUTILS_H__ */ + diff --git a/gst/gstdevice.c b/gst/gstdevice.c new file mode 100644 index 0000000..8a46752 --- /dev/null +++ b/gst/gstdevice.c @@ -0,0 +1,409 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete + * + * gstdevice.c: Device discovery + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstdevice + * @title: GstDevice + * @short_description: Object representing a device + * @see_also: #GstDeviceProvider + * + * #GstDevice are objects representing a device, they contain + * relevant metadata about the device, such as its class and the #GstCaps + * representing the media types it can produce or handle. + * + * #GstDevice are created by #GstDeviceProvider objects which can be + * aggregated by #GstDeviceMonitor objects. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdevice.h" + +enum +{ + PROP_DISPLAY_NAME = 1, + PROP_CAPS, + PROP_DEVICE_CLASS, + PROP_PROPERTIES +}; + +enum +{ + REMOVED, + LAST_SIGNAL +}; + +struct _GstDevicePrivate +{ + GstCaps *caps; + gchar *device_class; + gchar *display_name; + GstStructure *properties; +}; + + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_ABSTRACT_TYPE (GstDevice, gst_device, GST_TYPE_OBJECT); + +static void gst_device_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void gst_device_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void gst_device_finalize (GObject * object); + + +static void +gst_device_class_init (GstDeviceClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstDevicePrivate)); + + object_class->get_property = gst_device_get_property; + object_class->set_property = gst_device_set_property; + object_class->finalize = gst_device_finalize; + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME, + g_param_spec_string ("display-name", "Display Name", + "The user-friendly name of the device", "", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Device Caps", + "The possible caps of a device", GST_TYPE_CAPS, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_DEVICE_CLASS, + g_param_spec_string ("device-class", "Device Class", + "The Class of the device", "", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_PROPERTIES, + g_param_spec_boxed ("properties", "Properties", + "The extra properties of the device", GST_TYPE_STRUCTURE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + signals[REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); +} + +static void +gst_device_init (GstDevice * device) +{ + device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, GST_TYPE_DEVICE, + GstDevicePrivate); +} + +static void +gst_device_finalize (GObject * object) +{ + GstDevice *device = GST_DEVICE (object); + + gst_caps_replace (&device->priv->caps, NULL); + + if (device->priv->properties) + gst_structure_free (device->priv->properties); + g_free (device->priv->display_name); + g_free (device->priv->device_class); + + G_OBJECT_CLASS (gst_device_parent_class)->finalize (object); +} + +static void +gst_device_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDevice *gstdevice; + + gstdevice = GST_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + g_value_take_string (value, gst_device_get_display_name (gstdevice)); + break; + case PROP_CAPS: + if (gstdevice->priv->caps) + g_value_take_boxed (value, gst_device_get_caps (gstdevice)); + break; + case PROP_DEVICE_CLASS: + g_value_take_string (value, gst_device_get_device_class (gstdevice)); + break; + case PROP_PROPERTIES: + if (gstdevice->priv->properties) + g_value_take_boxed (value, gst_device_get_properties (gstdevice)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDevice *gstdevice; + + gstdevice = GST_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + gstdevice->priv->display_name = g_value_dup_string (value); + break; + case PROP_CAPS: + gst_caps_replace (&gstdevice->priv->caps, g_value_get_boxed (value)); + break; + case PROP_DEVICE_CLASS: + gstdevice->priv->device_class = g_value_dup_string (value); + break; + case PROP_PROPERTIES: + if (gstdevice->priv->properties) + gst_structure_free (gstdevice->priv->properties); + gstdevice->priv->properties = g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_device_create_element: + * @device: a #GstDevice + * @name: (allow-none): name of new element, or %NULL to automatically + * create a unique name. + * + * Creates the element with all of the required parameters set to use + * this device. + * + * Returns: (transfer full) (nullable): a new #GstElement configured to use + * this device + * + * Since: 1.4 + */ +GstElement * +gst_device_create_element (GstDevice * device, const gchar * name) +{ + GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + if (klass->create_element) + return klass->create_element (device, name); + else + return NULL; +} + +/** + * gst_device_get_caps: + * @device: a #GstDevice + * + * Getter for the #GstCaps that this device supports. + * + * Returns: (nullable): The #GstCaps supported by this device. Unref with + * gst_caps_unref() when done. + * + * Since: 1.4 + */ +GstCaps * +gst_device_get_caps (GstDevice * device) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + if (device->priv->caps) + return gst_caps_ref (device->priv->caps); + else + return NULL; +} + +/** + * gst_device_get_display_name: + * @device: a #GstDevice + * + * Gets the user-friendly name of the device. + * + * Returns: The device name. Free with g_free() after use. + * + * Since: 1.4 + */ +gchar * +gst_device_get_display_name (GstDevice * device) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + return + g_strdup (device->priv->display_name ? device->priv->display_name : ""); +} + +/** + * gst_device_get_device_class: + * @device: a #GstDevice + * + * Gets the "class" of a device. This is a "/" separated list of + * classes that represent this device. They are a subset of the + * classes of the #GstDeviceProvider that produced this device. + * + * Returns: The device class. Free with g_free() after use. + * + * Since: 1.4 + */ +gchar * +gst_device_get_device_class (GstDevice * device) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + if (device->priv->device_class != NULL) + return g_strdup (device->priv->device_class); + else + return g_strdup (""); +} + +/** + * gst_device_get_properties: + * @device: a #GstDevice + * + * Gets the extra properties of a device. + * + * Returns: (nullable): The extra properties or %NULL when there are none. + * Free with gst_structure_free() after use. + * + * Since: 1.6 + */ +GstStructure * +gst_device_get_properties (GstDevice * device) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + if (device->priv->properties != NULL) + return gst_structure_copy (device->priv->properties); + else + return NULL; +} + +/** + * gst_device_reconfigure_element: + * @device: a #GstDevice + * @element: a #GstElement + * + * Tries to reconfigure an existing element to use the device. If this + * function fails, then one must destroy the element and create a new one + * using gst_device_create_element(). + * + * Note: This should only be implemented for elements can change their + * device in the PLAYING state. + * + * Returns: %TRUE if the element could be reconfigured to use this device, + * %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gst_device_reconfigure_element (GstDevice * device, GstElement * element) +{ + GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (GST_IS_DEVICE (device), FALSE); + + if (klass->reconfigure_element) + return klass->reconfigure_element (device, element); + else + return FALSE; +} + +/** + * gst_device_has_classesv: + * @device: a #GstDevice + * @classes: (array zero-terminated=1): a %NULL terminated array of classes + * to match, only match if all classes are matched + * + * Check if @factory matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classesv (GstDevice * device, gchar ** classes) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), FALSE); + + if (!classes) + return TRUE; + + for (; classes[0]; classes++) { + const gchar *klass = classes[0]; + const gchar *found; + guint len; + + if (*klass == '\0') + continue; + + found = strstr (device->priv->device_class, klass); + + if (!found) + return FALSE; + if (found != device->priv->device_class && *(found - 1) != '/') + return FALSE; + + len = strlen (klass); + if (found[len] != 0 && found[len] != '/') + return FALSE; + } + + return TRUE; +} + +/** + * gst_device_has_classes: + * @device: a #GstDevice + * @classes: a "/"-separated list of device classes to match, only match if + * all classes are matched + * + * Check if @device matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classes (GstDevice * device, const gchar * classes) +{ + gchar **classesv; + gboolean res; + + g_return_val_if_fail (GST_IS_DEVICE (device), FALSE); + + if (!classes) + return TRUE; + + classesv = g_strsplit (classes, "/", 0); + + res = gst_device_has_classesv (device, classesv); + + g_strfreev (classesv); + + return res; +} diff --git a/gst/gstdevice.h b/gst/gstdevice.h new file mode 100644 index 0000000..1919d26 --- /dev/null +++ b/gst/gstdevice.h @@ -0,0 +1,122 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete + * + * gstdevice.c: Device discovery + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_DEVICE_H__ +#define __GST_DEVICE_H__ + +typedef struct _GstDevice GstDevice; +typedef struct _GstDeviceClass GstDeviceClass; + +#include +#include + + +G_BEGIN_DECLS + +typedef struct _GstDevicePrivate GstDevicePrivate; + +#define GST_TYPE_DEVICE (gst_device_get_type()) +#define GST_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE)) +#define GST_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE)) +#define GST_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE, GstDeviceClass)) +#define GST_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE, GstDevice)) +#define GST_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE, GstDeviceClass)) +#define GST_DEVICE_CAST(obj) ((GstDevice *)(obj)) + +/** + * GstDevice: + * @parent: The parent #GstObject strucuture. + * + * A device object. + * + * Since: 1.4 + */ + +struct _GstDevice { + GstObject parent; + + /*< private >*/ + GstDevicePrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDeviceClass: + * @parent_class: The parent #GstObjectClass strucuture. + * @create_element: Creates the fully configured element to access this device. + * Subclasses need to override this and return a new element. + * @reconfigure_element: This only needs to be implemented by subclasses if the + * element can be reconfigured to use a different device. See the documentation + * for gst_device_reconfigure_element(). + * + * The class structure for a #GstDevice object. + * + * Since: 1.4 + */ + +struct _GstDeviceClass { + GstObjectClass parent_class; + + GstElement * (*create_element) (GstDevice * device, const gchar * name); + gboolean (*reconfigure_element) (GstDevice * device, GstElement * element); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_device_get_type (void); + +GST_API +GstElement * gst_device_create_element (GstDevice * device, const gchar * name); + +GST_API +GstCaps * gst_device_get_caps (GstDevice * device); + +GST_API +gchar * gst_device_get_display_name (GstDevice * device); + +GST_API +gchar * gst_device_get_device_class (GstDevice * device); + +GST_API +GstStructure * gst_device_get_properties (GstDevice * device); + +GST_API +gboolean gst_device_reconfigure_element (GstDevice * device, + GstElement * element); +GST_API +gboolean gst_device_has_classesv (GstDevice * device, + gchar ** classes); +GST_API +gboolean gst_device_has_classes (GstDevice * device, + const gchar * classes); + + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDevice, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DEVICE_H__ */ diff --git a/gst/gstdevicemonitor.c b/gst/gstdevicemonitor.c new file mode 100644 index 0000000..e0b59ec --- /dev/null +++ b/gst/gstdevicemonitor.c @@ -0,0 +1,910 @@ +/* GStreamer + * Copyright (C) 2013 Olivier Crete + * + * gstdevicemonitor.c: device monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstdevicemonitor + * @title: GstDeviceMonitor + * @short_description: A device monitor and prober + * @see_also: #GstDevice, #GstDeviceProvider + * + * Applications should create a #GstDeviceMonitor when they want + * to probe, list and monitor devices of a specific type. The + * #GstDeviceMonitor will create the appropriate + * #GstDeviceProvider objects and manage them. It will then post + * messages on its #GstBus for devices that have been added and + * removed. + * + * The device monitor will monitor all devices matching the filters that + * the application has set. + * + * The basic use pattern of a device monitor is as follows: + * |[ + * static gboolean + * my_bus_func (GstBus * bus, GstMessage * message, gpointer user_data) + * { + * GstDevice *device; + * gchar *name; + * + * switch (GST_MESSAGE_TYPE (message)) { + * case GST_MESSAGE_DEVICE_ADDED: + * gst_message_parse_device_added (message, &device); + * name = gst_device_get_display_name (device); + * g_print("Device added: %s\n", name); + * g_free (name); + * gst_object_unref (device); + * break; + * case GST_MESSAGE_DEVICE_REMOVED: + * gst_message_parse_device_removed (message, &device); + * name = gst_device_get_display_name (device); + * g_print("Device removed: %s\n", name); + * g_free (name); + * gst_object_unref (device); + * break; + * default: + * break; + * } + * + * return G_SOURCE_CONTINUE; + * } + * + * GstDeviceMonitor * + * setup_raw_video_source_device_monitor (void) { + * GstDeviceMonitor *monitor; + * GstBus *bus; + * GstCaps *caps; + * + * monitor = gst_device_monitor_new (); + * + * bus = gst_device_monitor_get_bus (monitor); + * gst_bus_add_watch (bus, my_bus_func, NULL); + * gst_object_unref (bus); + * + * caps = gst_caps_new_empty_simple ("video/x-raw"); + * gst_device_monitor_add_filter (monitor, "Video/Source", caps); + * gst_caps_unref (caps); + * + * gst_device_monitor_start (monitor); + * + * return monitor; + * } + * ]| + * + * Since: 1.4 + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "gstdevicemonitor.h" + +struct _GstDeviceMonitorPrivate +{ + gboolean started; + + GstBus *bus; + + GPtrArray *providers; + guint cookie; + + GPtrArray *filters; + + guint last_id; + GList *hidden; + gboolean show_all; +}; + +#define DEFAULT_SHOW_ALL FALSE + +enum +{ + PROP_SHOW_ALL = 1, +}; + +G_DEFINE_TYPE (GstDeviceMonitor, gst_device_monitor, GST_TYPE_OBJECT); + +static void gst_device_monitor_dispose (GObject * object); + +struct DeviceFilter +{ + guint id; + + gchar **classesv; + GstCaps *caps; +}; + +static void +device_filter_free (struct DeviceFilter *filter) +{ + g_strfreev (filter->classesv); + gst_caps_unref (filter->caps); + + g_slice_free (struct DeviceFilter, filter); +} + +static void +gst_device_monitor_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object); + + switch (prop_id) { + case PROP_SHOW_ALL: + g_value_set_boolean (value, + gst_device_monitor_get_show_all_devices (monitor)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_device_monitor_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object); + + switch (prop_id) { + case PROP_SHOW_ALL: + gst_device_monitor_set_show_all_devices (monitor, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_device_monitor_class_init (GstDeviceMonitorClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstDeviceMonitorPrivate)); + + object_class->get_property = gst_device_monitor_get_property; + object_class->set_property = gst_device_monitor_set_property; + object_class->dispose = gst_device_monitor_dispose; + + g_object_class_install_property (object_class, PROP_SHOW_ALL, + g_param_spec_boolean ("show-all", "Show All", + "Show all devices, even those from hidden providers", + DEFAULT_SHOW_ALL, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); +} + +/* must be called with monitor lock */ +static gboolean +is_provider_hidden (GstDeviceMonitor * monitor, GList * hidden, + GstDeviceProvider * provider) +{ + GstDeviceProviderFactory *factory; + + if (monitor->priv->show_all) + return FALSE; + + factory = gst_device_provider_get_factory (provider); + if (g_list_find_custom (hidden, GST_OBJECT_NAME (factory), + (GCompareFunc) g_strcmp0)) + return TRUE; + + return FALSE; +} + +/* must be called with monitor lock */ +static void +update_hidden_providers_list (GList ** hidden, GstDeviceProvider * provider) +{ + gchar **obs; + + obs = gst_device_provider_get_hidden_providers (provider); + if (obs) { + gint i; + + for (i = 0; obs[i]; i++) + *hidden = g_list_prepend (*hidden, obs[i]); + + g_free (obs); + } +} + +static void +bus_sync_message (GstBus * bus, GstMessage * message, + GstDeviceMonitor * monitor) +{ + GstMessageType type = GST_MESSAGE_TYPE (message); + + if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) { + gboolean matches = TRUE; + GstDevice *device; + GstDeviceProvider *provider; + + if (type == GST_MESSAGE_DEVICE_ADDED) + gst_message_parse_device_added (message, &device); + else + gst_message_parse_device_removed (message, &device); + + GST_OBJECT_LOCK (monitor); + provider = + GST_DEVICE_PROVIDER (gst_object_get_parent (GST_OBJECT (device))); + if (is_provider_hidden (monitor, monitor->priv->hidden, provider)) { + matches = FALSE; + } else { + guint i; + + for (i = 0; i < monitor->priv->filters->len; i++) { + struct DeviceFilter *filter = + g_ptr_array_index (monitor->priv->filters, i); + GstCaps *caps; + + caps = gst_device_get_caps (device); + matches = gst_caps_can_intersect (filter->caps, caps) && + gst_device_has_classesv (device, filter->classesv); + gst_caps_unref (caps); + if (matches) + break; + } + } + GST_OBJECT_UNLOCK (monitor); + + gst_object_unref (provider); + gst_object_unref (device); + + if (matches) + gst_bus_post (monitor->priv->bus, gst_message_ref (message)); + } +} + + +static void +gst_device_monitor_init (GstDeviceMonitor * self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorPrivate); + + self->priv->show_all = DEFAULT_SHOW_ALL; + + self->priv->bus = gst_bus_new (); + gst_bus_set_flushing (self->priv->bus, TRUE); + + self->priv->providers = g_ptr_array_new (); + self->priv->filters = g_ptr_array_new_with_free_func ( + (GDestroyNotify) device_filter_free); + + self->priv->last_id = 1; +} + + +static void +gst_device_monitor_remove (GstDeviceMonitor * self, guint i) +{ + GstDeviceProvider *provider = g_ptr_array_index (self->priv->providers, i); + GstBus *bus; + + g_ptr_array_remove_index (self->priv->providers, i); + + bus = gst_device_provider_get_bus (provider); + g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self); + gst_object_unref (bus); + + gst_object_unref (provider); +} + +static void +gst_device_monitor_dispose (GObject * object) +{ + GstDeviceMonitor *self = GST_DEVICE_MONITOR (object); + + g_return_if_fail (!self->priv->started); + + if (self->priv->providers) { + while (self->priv->providers->len) + gst_device_monitor_remove (self, self->priv->providers->len - 1); + g_ptr_array_unref (self->priv->providers); + self->priv->providers = NULL; + } + + if (self->priv->filters) { + g_ptr_array_unref (self->priv->filters); + self->priv->filters = NULL; + } + + gst_object_replace ((GstObject **) & self->priv->bus, NULL); + + G_OBJECT_CLASS (gst_device_monitor_parent_class)->dispose (object); +} + +/** + * gst_device_monitor_get_devices: + * @monitor: A #GstDeviceProvider + * + * Gets a list of devices from all of the relevant monitors. This may actually + * probe the hardware if the monitor is not currently started. + * + * Returns: (transfer full) (element-type GstDevice) (nullable): a #GList of + * #GstDevice + * + * Since: 1.4 + */ + +GList * +gst_device_monitor_get_devices (GstDeviceMonitor * monitor) +{ + GList *devices = NULL, *hidden = NULL; + guint i; + guint cookie; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + + GST_OBJECT_LOCK (monitor); + + if (monitor->priv->filters->len == 0) { + GST_OBJECT_UNLOCK (monitor); + GST_WARNING_OBJECT (monitor, "No filters have been set"); + return NULL; + } + + if (monitor->priv->providers->len == 0) { + GST_OBJECT_UNLOCK (monitor); + GST_WARNING_OBJECT (monitor, "No providers match the current filters"); + return NULL; + } + +again: + + g_list_free_full (devices, gst_object_unref); + g_list_free_full (hidden, g_free); + devices = NULL; + hidden = NULL; + + cookie = monitor->priv->cookie; + + for (i = 0; i < monitor->priv->providers->len; i++) { + GList *tmpdev; + GstDeviceProvider *provider = + gst_object_ref (g_ptr_array_index (monitor->priv->providers, i)); + GList *item; + + if (!is_provider_hidden (monitor, hidden, provider)) { + GST_OBJECT_UNLOCK (monitor); + + tmpdev = gst_device_provider_get_devices (provider); + + GST_OBJECT_LOCK (monitor); + update_hidden_providers_list (&hidden, provider); + } else { + tmpdev = NULL; + } + + + for (item = tmpdev; item; item = item->next) { + GstDevice *dev = GST_DEVICE (item->data); + GstCaps *caps = gst_device_get_caps (dev); + guint j; + + for (j = 0; j < monitor->priv->filters->len; j++) { + struct DeviceFilter *filter = + g_ptr_array_index (monitor->priv->filters, j); + + if (gst_caps_can_intersect (filter->caps, caps) && + gst_device_has_classesv (dev, filter->classesv)) { + devices = g_list_prepend (devices, gst_object_ref (dev)); + break; + } + } + gst_caps_unref (caps); + } + + g_list_free_full (tmpdev, gst_object_unref); + gst_object_unref (provider); + + if (monitor->priv->cookie != cookie) + goto again; + } + g_list_free_full (hidden, g_free); + + GST_OBJECT_UNLOCK (monitor); + + return g_list_reverse (devices); +} + +/** + * gst_device_monitor_start: + * @monitor: A #GstDeviceMonitor + * + * Starts monitoring the devices, one this has succeeded, the + * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages + * will be emitted on the bus when the list of devices changes. + * + * Returns: %TRUE if the device monitoring could be started + * + * Since: 1.4 + */ + +gboolean +gst_device_monitor_start (GstDeviceMonitor * monitor) +{ + guint cookie, i; + GList *pending = NULL, *started = NULL, *removed = NULL; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE); + + GST_OBJECT_LOCK (monitor); + + if (monitor->priv->filters->len == 0) { + GST_OBJECT_UNLOCK (monitor); + GST_WARNING_OBJECT (monitor, "No filters have been set, will expose all " + "devices found"); + gst_device_monitor_add_filter (monitor, NULL, NULL); + GST_OBJECT_LOCK (monitor); + } + + if (monitor->priv->providers->len == 0) { + GST_OBJECT_UNLOCK (monitor); + GST_WARNING_OBJECT (monitor, "No providers match the current filters"); + return FALSE; + } + + gst_bus_set_flushing (monitor->priv->bus, FALSE); + +again: + cookie = monitor->priv->cookie; + + g_list_free_full (pending, gst_object_unref); + pending = NULL; + removed = started; + started = NULL; + + for (i = 0; i < monitor->priv->providers->len; i++) { + GstDeviceProvider *provider; + GList *find; + + provider = g_ptr_array_index (monitor->priv->providers, i); + + find = g_list_find (removed, provider); + if (find) { + /* this was already started, move to started list */ + removed = g_list_remove_link (removed, find); + started = g_list_concat (started, find); + } else { + /* not started, add to pending list */ + pending = g_list_append (pending, gst_object_ref (provider)); + } + } + g_list_free_full (removed, gst_object_unref); + removed = NULL; + + while (pending) { + GstDeviceProvider *provider = pending->data; + + if (gst_device_provider_can_monitor (provider)) { + GST_OBJECT_UNLOCK (monitor); + + if (!gst_device_provider_start (provider)) + goto start_failed; + + GST_OBJECT_LOCK (monitor); + } + started = g_list_prepend (started, provider); + pending = g_list_delete_link (pending, pending); + + if (monitor->priv->cookie != cookie) + goto again; + } + monitor->priv->started = TRUE; + GST_OBJECT_UNLOCK (monitor); + + g_list_free_full (started, gst_object_unref); + + return TRUE; + +start_failed: + { + GST_OBJECT_LOCK (monitor); + gst_bus_set_flushing (monitor->priv->bus, TRUE); + GST_OBJECT_UNLOCK (monitor); + + while (started) { + GstDeviceProvider *provider = started->data; + + gst_device_provider_stop (provider); + gst_object_unref (provider); + + started = g_list_delete_link (started, started); + } + return FALSE; + } +} + +/** + * gst_device_monitor_stop: + * @monitor: A #GstDeviceProvider + * + * Stops monitoring the devices. + * + * Since: 1.4 + */ +void +gst_device_monitor_stop (GstDeviceMonitor * monitor) +{ + guint i; + GList *started = NULL; + + g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor)); + + gst_bus_set_flushing (monitor->priv->bus, TRUE); + + GST_OBJECT_LOCK (monitor); + for (i = 0; i < monitor->priv->providers->len; i++) { + GstDeviceProvider *provider = + g_ptr_array_index (monitor->priv->providers, i); + + started = g_list_prepend (started, gst_object_ref (provider)); + } + GST_OBJECT_UNLOCK (monitor); + + while (started) { + GstDeviceProvider *provider = started->data; + + if (gst_device_provider_can_monitor (provider)) + gst_device_provider_stop (provider); + + started = g_list_delete_link (started, started); + gst_object_unref (provider); + } + + GST_OBJECT_LOCK (monitor); + monitor->priv->started = FALSE; + GST_OBJECT_UNLOCK (monitor); + +} + +static void +provider_hidden (GstDeviceProvider * provider, const gchar * hidden, + GstDeviceMonitor * monitor) +{ + GST_OBJECT_LOCK (monitor); + monitor->priv->hidden = + g_list_prepend (monitor->priv->hidden, g_strdup (hidden)); + GST_OBJECT_UNLOCK (monitor); +} + +static void +provider_unhidden (GstDeviceProvider * provider, const gchar * hidden, + GstDeviceMonitor * monitor) +{ + GList *find; + + GST_OBJECT_LOCK (monitor); + find = + g_list_find_custom (monitor->priv->hidden, hidden, + (GCompareFunc) g_strcmp0); + if (find) { + g_free (find->data); + monitor->priv->hidden = g_list_delete_link (monitor->priv->hidden, find); + } + GST_OBJECT_UNLOCK (monitor); +} + +/** + * gst_device_monitor_add_filter: + * @monitor: a device monitor + * @classes: (allow-none): device classes to use as filter or %NULL for any class + * @caps: (allow-none): the #GstCaps to filter or %NULL for ANY + * + * Adds a filter for which #GstDevice will be monitored, any device that matches + * all these classes and the #GstCaps will be returned. + * + * If this function is called multiple times to add more filters, each will be + * matched independently. That is, adding more filters will not further restrict + * what devices are matched. + * + * The #GstCaps supported by the device as returned by gst_device_get_caps() are + * not intersected with caps filters added using this function. + * + * Filters must be added before the #GstDeviceMonitor is started. + * + * Returns: The id of the new filter or 0 if no provider matched the filter's + * classes. + * + * Since: 1.4 + */ +guint +gst_device_monitor_add_filter (GstDeviceMonitor * monitor, + const gchar * classes, GstCaps * caps) +{ + GList *factories = NULL; + struct DeviceFilter *filter; + guint id = 0; + gboolean matched = FALSE; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), 0); + g_return_val_if_fail (!monitor->priv->started, 0); + + GST_OBJECT_LOCK (monitor); + + filter = g_slice_new0 (struct DeviceFilter); + filter->id = monitor->priv->last_id++; + if (caps) + filter->caps = gst_caps_ref (caps); + else + filter->caps = gst_caps_new_any (); + if (classes) + filter->classesv = g_strsplit (classes, "/", 0); + + factories = gst_device_provider_factory_list_get_device_providers (1); + + while (factories) { + GstDeviceProviderFactory *factory = factories->data; + + if (gst_device_provider_factory_has_classesv (factory, filter->classesv)) { + GstDeviceProvider *provider; + + provider = gst_device_provider_factory_get (factory); + + if (provider) { + guint i; + + for (i = 0; i < monitor->priv->providers->len; i++) { + if (g_ptr_array_index (monitor->priv->providers, i) == provider) { + gst_object_unref (provider); + provider = NULL; + matched = TRUE; + break; + } + } + } + + if (provider) { + GstBus *bus = gst_device_provider_get_bus (provider); + + update_hidden_providers_list (&monitor->priv->hidden, provider); + g_signal_connect (provider, "provider-hidden", + (GCallback) provider_hidden, monitor); + g_signal_connect (provider, "provider-unhidden", + (GCallback) provider_unhidden, monitor); + + matched = TRUE; + gst_bus_enable_sync_message_emission (bus); + g_signal_connect (bus, "sync-message", + G_CALLBACK (bus_sync_message), monitor); + gst_object_unref (bus); + g_ptr_array_add (monitor->priv->providers, provider); + monitor->priv->cookie++; + } + } + + factories = g_list_remove (factories, factory); + gst_object_unref (factory); + } + + /* Ensure there is no leak here */ + g_assert (factories == NULL); + + if (matched) + id = filter->id; + g_ptr_array_add (monitor->priv->filters, filter); + + GST_OBJECT_UNLOCK (monitor); + + return id; +} + +/** + * gst_device_monitor_remove_filter: + * @monitor: a device monitor + * @filter_id: the id of the filter + * + * Removes a filter from the #GstDeviceMonitor using the id that was returned + * by gst_device_monitor_add_filter(). + * + * Returns: %TRUE of the filter id was valid, %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +gst_device_monitor_remove_filter (GstDeviceMonitor * monitor, guint filter_id) +{ + guint i, j; + gboolean removed = FALSE; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE); + g_return_val_if_fail (!monitor->priv->started, FALSE); + g_return_val_if_fail (filter_id > 0, FALSE); + + GST_OBJECT_LOCK (monitor); + for (i = 0; i < monitor->priv->filters->len; i++) { + struct DeviceFilter *filter = g_ptr_array_index (monitor->priv->filters, i); + + if (filter->id == filter_id) { + g_ptr_array_remove_index (monitor->priv->filters, i); + removed = TRUE; + break; + } + } + + if (removed) { + for (i = 0; i < monitor->priv->providers->len; i++) { + GstDeviceProvider *provider = + g_ptr_array_index (monitor->priv->providers, i); + GstDeviceProviderFactory *factory = + gst_device_provider_get_factory (provider); + gboolean valid = FALSE; + + for (j = 0; j < monitor->priv->filters->len; j++) { + struct DeviceFilter *filter = + g_ptr_array_index (monitor->priv->filters, j); + + if (gst_device_provider_factory_has_classesv (factory, + filter->classesv)) { + valid = TRUE; + break; + } + } + + if (!valid) { + monitor->priv->cookie++; + gst_device_monitor_remove (monitor, i); + i--; + } + } + } + + GST_OBJECT_UNLOCK (monitor); + + return removed; +} + + + +/** + * gst_device_monitor_new: + * + * Create a new #GstDeviceMonitor + * + * Returns: (transfer full): a new device monitor. + * + * Since: 1.4 + */ +GstDeviceMonitor * +gst_device_monitor_new (void) +{ + GstDeviceMonitor *monitor; + + monitor = g_object_new (GST_TYPE_DEVICE_MONITOR, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (monitor); + + return monitor; +} + +/** + * gst_device_monitor_get_bus: + * @monitor: a #GstDeviceProvider + * + * Gets the #GstBus of this #GstDeviceMonitor + * + * Returns: (transfer full): a #GstBus + * + * Since: 1.4 + */ +GstBus * +gst_device_monitor_get_bus (GstDeviceMonitor * monitor) +{ + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + + return gst_object_ref (monitor->priv->bus); +} + +/** + * gst_device_monitor_get_providers: + * @monitor: a #GstDeviceMonitor + * + * Get a list of the currently selected device provider factories. + * + * This + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): + * A list of device provider factory names that are currently being + * monitored by @monitor or %NULL when nothing is being monitored. + * + * Since: 1.6 + */ +gchar ** +gst_device_monitor_get_providers (GstDeviceMonitor * monitor) +{ + guint i, len; + gchar **res = NULL; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + + GST_OBJECT_LOCK (monitor); + len = monitor->priv->providers->len; + if (len == 0) + goto done; + + res = g_new (gchar *, len + 1); + + for (i = 0; i < len; i++) { + GstDeviceProvider *provider = + g_ptr_array_index (monitor->priv->providers, i); + GstDeviceProviderFactory *factory = + gst_device_provider_get_factory (provider); + + res[i] = g_strdup (GST_OBJECT_NAME (factory)); + } + res[i] = NULL; + +done: + GST_OBJECT_UNLOCK (monitor); + + return res; +} + +/** + * gst_device_monitor_set_show_all_devices: + * @monitor: a #GstDeviceMonitor + * @show_all: show all devices + * + * Set if all devices should be visible, even those devices from hidden + * providers. Setting @show_all to true might show some devices multiple times. + * + * Since: 1.6 + */ +void +gst_device_monitor_set_show_all_devices (GstDeviceMonitor * monitor, + gboolean show_all) +{ + g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor)); + + GST_OBJECT_LOCK (monitor); + monitor->priv->show_all = show_all; + GST_OBJECT_UNLOCK (monitor); +} + +/** + * gst_device_monitor_get_show_all_devices: + * @monitor: a #GstDeviceMonitor + * + * Get if @monitor is curretly showing all devices, even those from hidden + * providers. + * + * Returns: %TRUE when all devices will be shown. + * + * Since: 1.6 + */ +gboolean +gst_device_monitor_get_show_all_devices (GstDeviceMonitor * monitor) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE); + + GST_OBJECT_LOCK (monitor); + res = monitor->priv->show_all; + GST_OBJECT_UNLOCK (monitor); + + return res; +} diff --git a/gst/gstdevicemonitor.h b/gst/gstdevicemonitor.h new file mode 100644 index 0000000..39e8cca --- /dev/null +++ b/gst/gstdevicemonitor.h @@ -0,0 +1,120 @@ +/* GStreamer + * Copyright (C) 2013 Olivier Crete + * + * gstdevicemonitor.c: Device monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_DEVICE_MONITOR_H__ +#define __GST_DEVICE_MONITOR_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstDeviceMonitor GstDeviceMonitor; +typedef struct _GstDeviceMonitorPrivate GstDeviceMonitorPrivate; +typedef struct _GstDeviceMonitorClass GstDeviceMonitorClass; + +#define GST_TYPE_DEVICE_MONITOR (gst_device_monitor_get_type()) +#define GST_IS_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE_MONITOR)) +#define GST_IS_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE_MONITOR)) +#define GST_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass)) +#define GST_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitor)) +#define GST_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass)) +#define GST_DEVICE_MONITOR_CAST(obj) ((GstDeviceMonitor *)(obj)) + +/** + * GstDeviceMonitor: + * @parent: the parent #GstObject structure + * + * Opaque device monitor object structure. + * + * Since: 1.4 + */ +struct _GstDeviceMonitor { + GstObject parent; + + /*< private >*/ + + GstDeviceMonitorPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDeviceMonitorClass: + * @parent_class: the parent #GstObjectClass structure + * + * Opaque device monitor class structure. + * + * Since: 1.4 + */ +struct _GstDeviceMonitorClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_device_monitor_get_type (void); + +GST_API +GstDeviceMonitor * gst_device_monitor_new (void); + +GST_API +GstBus * gst_device_monitor_get_bus (GstDeviceMonitor * monitor); + +GST_API +GList * gst_device_monitor_get_devices (GstDeviceMonitor * monitor); + + +GST_API +gboolean gst_device_monitor_start (GstDeviceMonitor * monitor); + +GST_API +void gst_device_monitor_stop (GstDeviceMonitor * monitor); + + +GST_API +guint gst_device_monitor_add_filter (GstDeviceMonitor * monitor, + const gchar * classes, + GstCaps * caps); +GST_API +gboolean gst_device_monitor_remove_filter (GstDeviceMonitor * monitor, + guint filter_id); +GST_API +gchar ** gst_device_monitor_get_providers (GstDeviceMonitor * monitor); + +GST_API +void gst_device_monitor_set_show_all_devices (GstDeviceMonitor * monitor, gboolean show_all); + +GST_API +gboolean gst_device_monitor_get_show_all_devices (GstDeviceMonitor * monitor); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceMonitor, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DEVICE_MONITOR_H__ */ diff --git a/gst/gstdeviceprovider.c b/gst/gstdeviceprovider.c new file mode 100644 index 0000000..83bb54b --- /dev/null +++ b/gst/gstdeviceprovider.c @@ -0,0 +1,763 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete + * + * gstdeviceprovider.c: Device probing and monitoring + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstdeviceprovider + * @title: GstDeviceProvider + * @short_description: A device provider + * @see_also: #GstDevice, #GstDeviceMonitor + * + * A #GstDeviceProvider subclass is provided by a plugin that handles devices + * if there is a way to programatically list connected devices. It can also + * optionally provide updates to the list of connected devices. + * + * Each #GstDeviceProvider subclass is a singleton, a plugin should + * normally provide a single subclass for all devices. + * + * Applications would normally use a #GstDeviceMonitor to monitor devices + * from all relevant providers. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdeviceprovider.h" + +#include "gstelementmetadata.h" +#include "gstquark.h" + +struct _GstDeviceProviderPrivate +{ + GstBus *bus; + + GMutex start_lock; + + gboolean started_count; + + GList *hidden_providers; +}; + +enum +{ + PROVIDER_HIDDEN, + PROVIDER_UNHIDDEN, + LAST_SIGNAL +}; + +static guint gst_device_provider_signals[LAST_SIGNAL] = { 0 }; + +/* this is used in gstelementfactory.c:gst_element_register() */ +GQuark __gst_deviceproviderclass_factory = 0; + +static void gst_device_provider_class_init (GstDeviceProviderClass * klass); +static void gst_device_provider_init (GstDeviceProvider * element); +static void gst_device_provider_base_class_init (gpointer g_class); +static void gst_device_provider_dispose (GObject * object); +static void gst_device_provider_finalize (GObject * object); + +static gpointer gst_device_provider_parent_class = NULL; + +GType +gst_device_provider_get_type (void) +{ + static volatile gsize gst_device_provider_type = 0; + + if (g_once_init_enter (&gst_device_provider_type)) { + GType _type; + static const GTypeInfo element_info = { + sizeof (GstDeviceProviderClass), + gst_device_provider_base_class_init, + NULL, /* base_class_finalize */ + (GClassInitFunc) gst_device_provider_class_init, + NULL, + NULL, + sizeof (GstDeviceProvider), + 0, + (GInstanceInitFunc) gst_device_provider_init, + NULL + }; + + _type = g_type_register_static (GST_TYPE_OBJECT, "GstDeviceProvider", + &element_info, G_TYPE_FLAG_ABSTRACT); + + __gst_deviceproviderclass_factory = + g_quark_from_static_string ("GST_DEVICEPROVIDERCLASS_FACTORY"); + g_once_init_leave (&gst_device_provider_type, _type); + } + return gst_device_provider_type; +} + +static void +gst_device_provider_base_class_init (gpointer g_class) +{ + GstDeviceProviderClass *klass = GST_DEVICE_PROVIDER_CLASS (g_class); + + /* Copy the element details here so elements can inherit the + * details from their base class and classes only need to set + * the details in class_init instead of base_init */ + klass->metadata = + klass->metadata ? gst_structure_copy (klass->metadata) : + gst_structure_new_empty ("metadata"); + + klass->factory = g_type_get_qdata (G_TYPE_FROM_CLASS (klass), + __gst_deviceproviderclass_factory); +} + +static void +gst_device_provider_class_init (GstDeviceProviderClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gst_device_provider_parent_class = g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (GstDeviceProviderPrivate)); + + gobject_class->dispose = gst_device_provider_dispose; + gobject_class->finalize = gst_device_provider_finalize; + + gst_device_provider_signals[PROVIDER_HIDDEN] = + g_signal_new ("provider-hidden", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING); + + gst_device_provider_signals[PROVIDER_UNHIDDEN] = + g_signal_new ("provider-unhidden", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +gst_device_provider_init (GstDeviceProvider * provider) +{ + provider->priv = G_TYPE_INSTANCE_GET_PRIVATE (provider, + GST_TYPE_DEVICE_PROVIDER, GstDeviceProviderPrivate); + + g_mutex_init (&provider->priv->start_lock); + + provider->priv->bus = gst_bus_new (); + gst_bus_set_flushing (provider->priv->bus, TRUE); +} + + +static void +gst_device_provider_dispose (GObject * object) +{ + GstDeviceProvider *provider = GST_DEVICE_PROVIDER (object); + + gst_object_replace ((GstObject **) & provider->priv->bus, NULL); + + GST_OBJECT_LOCK (provider); + g_list_free_full (provider->devices, (GDestroyNotify) gst_object_unparent); + provider->devices = NULL; + GST_OBJECT_UNLOCK (provider); + + G_OBJECT_CLASS (gst_device_provider_parent_class)->dispose (object); +} + +static void +gst_device_provider_finalize (GObject * object) +{ + GstDeviceProvider *provider = GST_DEVICE_PROVIDER (object); + + g_mutex_clear (&provider->priv->start_lock); + + G_OBJECT_CLASS (gst_device_provider_parent_class)->finalize (object); +} + +/** + * gst_device_provider_class_add_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + * + * Since: 1.4 + */ +void +gst_device_provider_class_add_metadata (GstDeviceProviderClass * klass, + const gchar * key, const gchar * value) +{ + g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + gst_structure_set ((GstStructure *) klass->metadata, + key, G_TYPE_STRING, value, NULL); +} + +/** + * gst_device_provider_class_add_static_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: (transfer full): the value to set + * + * Set @key with @value as metadata in @klass. + * + * Same as gst_device_provider_class_add_metadata(), but @value must be a static string + * or an inlined string, as it will not be copied. (GStreamer plugins will + * be made resident once loaded, so this function can be used even from + * dynamically loaded plugins.) + * + * Since: 1.4 + */ +void +gst_device_provider_class_add_static_metadata (GstDeviceProviderClass * klass, + const gchar * key, const gchar * value) +{ + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_value_init (&val, G_TYPE_STRING); + g_value_set_static_string (&val, value); + gst_structure_take_value ((GstStructure *) klass->metadata, key, &val); +} + +/** + * gst_device_provider_class_set_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the device provider. E.g. "File Sink" + * @classification: String describing the type of device provider, as an + * unordered list separated with slashes ('/'). See draft-klass.txt of the + * design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the device provider. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstDeviceProviderClass. + * + * > This function is for use in _class_init functions only. + * + * Since: 1.4 + */ +void +gst_device_provider_class_set_metadata (GstDeviceProviderClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + gst_structure_id_set ((GstStructure *) klass->metadata, + GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname, + GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification, + GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description, + GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL); +} + +/** + * gst_device_provider_class_set_static_metadata: + * @klass: class to set metadata for + * @longname: (transfer full): The long English name of the element. E.g. "File Sink" + * @classification: (transfer full): String describing the type of element, as + * an unordered list separated with slashes ('/'). See draft-klass.txt of the + * design docs for more details and common types. E.g: "Sink/File" + * @description: (transfer full): Sentence describing the purpose of the + * element. E.g: "Write stream to a file" + * @author: (transfer full): Name and contact details of the author(s). Use \n + * to separate multiple author metadata. E.g: "Joe Bloggs <joe.blogs at + * foo.com>" + * + * Sets the detailed information for a #GstDeviceProviderClass. + * + * > This function is for use in _class_init functions only. + * + * Same as gst_device_provider_class_set_metadata(), but @longname, @classification, + * @description, and @author must be static strings or inlined strings, as + * they will not be copied. (GStreamer plugins will be made resident once + * loaded, so this function can be used even from dynamically loaded plugins.) + * + * Since: 1.4 + */ +void +gst_device_provider_class_set_static_metadata (GstDeviceProviderClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + GstStructure *s = (GstStructure *) klass->metadata; + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + g_value_init (&val, G_TYPE_STRING); + + g_value_set_static_string (&val, longname); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val); + + g_value_set_static_string (&val, classification); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val); + + g_value_set_static_string (&val, description); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION), + &val); + + g_value_set_static_string (&val, author); + gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val); +} + +/** + * gst_device_provider_class_get_metadata: + * @klass: class to get metadata for + * @key: the key to get + * + * Get metadata with @key in @klass. + * + * Returns: (nullable): the metadata for @key. + * + * Since: 1.4 + */ +const gchar * +gst_device_provider_class_get_metadata (GstDeviceProviderClass * klass, + const gchar * key) +{ + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass), NULL); + g_return_val_if_fail (key != NULL, NULL); + + return gst_structure_get_string ((GstStructure *) klass->metadata, key); +} + +/** + * gst_device_provider_get_metadata: + * @provider: provider to get metadata for + * @key: the key to get + * + * Get metadata with @key in @provider. + * + * Returns: the metadata for @key. + * + * Since: 1.14 + */ +const gchar * +gst_device_provider_get_metadata (GstDeviceProvider * provider, + const gchar * key) +{ + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + g_return_val_if_fail (key != NULL, NULL); + + return + gst_device_provider_class_get_metadata (GST_DEVICE_PROVIDER_GET_CLASS + (provider), key); +} + +/** + * gst_device_provider_get_devices: + * @provider: A #GstDeviceProvider + * + * Gets a list of devices that this provider understands. This may actually + * probe the hardware if the provider is not currently started. + * + * Returns: (transfer full) (element-type GstDevice): a #GList of + * #GstDevice + * + * Since: 1.4 + */ + +GList * +gst_device_provider_get_devices (GstDeviceProvider * provider) +{ + GstDeviceProviderClass *klass; + GList *devices = NULL; + gboolean started; + GList *item; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + klass = GST_DEVICE_PROVIDER_GET_CLASS (provider); + + g_mutex_lock (&provider->priv->start_lock); + started = (provider->priv->started_count > 0); + + if (started) { + GST_OBJECT_LOCK (provider); + for (item = provider->devices; item; item = item->next) + devices = g_list_prepend (devices, gst_object_ref (item->data)); + GST_OBJECT_UNLOCK (provider); + } else if (klass->probe) + devices = klass->probe (provider); + + g_mutex_unlock (&provider->priv->start_lock); + + return devices; +} + +/** + * gst_device_provider_start: + * @provider: A #GstDeviceProvider + * + * Starts providering the devices. This will cause #GST_MESSAGE_DEVICE_ADDED + * and #GST_MESSAGE_DEVICE_REMOVED messages to be posted on the provider's bus + * when devices are added or removed from the system. + * + * Since the #GstDeviceProvider is a singleton, + * gst_device_provider_start() may already have been called by another + * user of the object, gst_device_provider_stop() needs to be called the same + * number of times. + * + * Returns: %TRUE if the device providering could be started + * + * Since: 1.4 + */ + +gboolean +gst_device_provider_start (GstDeviceProvider * provider) +{ + GstDeviceProviderClass *klass; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), FALSE); + klass = GST_DEVICE_PROVIDER_GET_CLASS (provider); + + g_mutex_lock (&provider->priv->start_lock); + + if (provider->priv->started_count > 0) { + ret = TRUE; + goto started; + } + + if (klass->start) + ret = klass->start (provider); + + if (ret) { + provider->priv->started_count++; + gst_bus_set_flushing (provider->priv->bus, FALSE); + } + +started: + + g_mutex_unlock (&provider->priv->start_lock); + + return ret; +} + +/** + * gst_device_provider_stop: + * @provider: A #GstDeviceProvider + * + * Decreases the use-count by one. If the use count reaches zero, this + * #GstDeviceProvider will stop providering the devices. This needs to be + * called the same number of times that gst_device_provider_start() was called. + * + * Since: 1.4 + */ + +void +gst_device_provider_stop (GstDeviceProvider * provider) +{ + GstDeviceProviderClass *klass; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + klass = GST_DEVICE_PROVIDER_GET_CLASS (provider); + + g_mutex_lock (&provider->priv->start_lock); + + if (provider->priv->started_count == 1) { + gst_bus_set_flushing (provider->priv->bus, TRUE); + if (klass->stop) + klass->stop (provider); + GST_OBJECT_LOCK (provider); + g_list_free_full (provider->devices, (GDestroyNotify) gst_object_unparent); + provider->devices = NULL; + GST_OBJECT_UNLOCK (provider); + } else if (provider->priv->started_count < 1) { + g_critical + ("Trying to stop a GstDeviceProvider %s which is already stopped", + GST_OBJECT_NAME (provider)); + } + + provider->priv->started_count--; + g_mutex_unlock (&provider->priv->start_lock); +} + + +/** + * gst_device_provider_get_factory: + * @provider: a #GstDeviceProvider to request the device provider factory of. + * + * Retrieves the factory that was used to create this device provider. + * + * Returns: (transfer none): the #GstDeviceProviderFactory used for + * creating this device provider. no refcounting is needed. + * + * Since: 1.4 + */ +GstDeviceProviderFactory * +gst_device_provider_get_factory (GstDeviceProvider * provider) +{ + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + + return GST_DEVICE_PROVIDER_GET_CLASS (provider)->factory; +} + +/** + * gst_device_provider_can_provider: + * @provider: a #GstDeviceProvider + * + * If this function returns %TRUE, then the device provider can provider if + * devices are added or removed. Otherwise, it can only do static probing. + * + * Returns: %TRUE if the #GstDeviceProvider support providering, %FALSE otherwise + */ +gboolean +gst_device_provider_can_monitor (GstDeviceProvider * provider) +{ + GstDeviceProviderClass *klass; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), FALSE); + klass = GST_DEVICE_PROVIDER_GET_CLASS (provider); + + if (klass->start) + return TRUE; + else + return FALSE; +} + +/** + * gst_device_provider_get_bus: + * @provider: a #GstDeviceProvider + * + * Gets the #GstBus of this #GstDeviceProvider + * + * Returns: (transfer full): a #GstBus + * + * Since: 1.4 + */ +GstBus * +gst_device_provider_get_bus (GstDeviceProvider * provider) +{ + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + + return gst_object_ref (provider->priv->bus); +} + +/** + * gst_device_provider_device_add: + * @provider: a #GstDeviceProvider + * @device: (transfer floating): a #GstDevice that has been added + * + * Posts a message on the provider's #GstBus to inform applications that + * a new device has been added. + * + * This is for use by subclasses. + * + * @device's reference count will be incremented, and any floating reference + * will be removed (see gst_object_ref_sink()). + * + * Since: 1.4 + */ +void +gst_device_provider_device_add (GstDeviceProvider * provider, + GstDevice * device) +{ + GstMessage *message; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (GST_IS_DEVICE (device)); + + if (!gst_object_set_parent (GST_OBJECT (device), GST_OBJECT (provider))) { + GST_WARNING_OBJECT (provider, "Could not parent device %p to provider," + " it already has a parent", device); + return; + } + + GST_OBJECT_LOCK (provider); + /* Take an additional reference so we can be sure nobody removed it from the + * provider in the meantime and we can safely emit the message */ + gst_object_ref (device); + provider->devices = g_list_prepend (provider->devices, device); + GST_OBJECT_UNLOCK (provider); + + message = gst_message_new_device_added (GST_OBJECT (provider), device); + gst_bus_post (provider->priv->bus, message); + gst_object_unref (device); +} + + +/** + * gst_device_provider_device_remove: + * @provider: a #GstDeviceProvider + * @device: a #GstDevice that has been removed + * + * Posts a message on the provider's #GstBus to inform applications that + * a device has been removed. + * + * This is for use by subclasses. + * + * Since: 1.4 + */ +void +gst_device_provider_device_remove (GstDeviceProvider * provider, + GstDevice * device) +{ + GstMessage *message; + GList *item; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (GST_IS_DEVICE (device)); + + GST_OBJECT_LOCK (provider); + item = g_list_find (provider->devices, device); + if (item) { + provider->devices = g_list_delete_link (provider->devices, item); + } + GST_OBJECT_UNLOCK (provider); + + message = gst_message_new_device_removed (GST_OBJECT (provider), device); + g_signal_emit_by_name (device, "removed"); + gst_bus_post (provider->priv->bus, message); + if (item) + gst_object_unparent (GST_OBJECT (device)); +} + +/** + * gst_device_provider_get_hidden_providers: + * @provider: a #GstDeviceProvider + * + * Get the provider factory names of the #GstDeviceProvider instances that + * are hidden by @provider. + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): + * a list of hidden providers factory names or %NULL when + * nothing is hidden by @provider. Free with g_strfreev. + * + * Since: 1.6 + */ +gchar ** +gst_device_provider_get_hidden_providers (GstDeviceProvider * provider) +{ + GList *walk; + guint i, len; + gchar **res = NULL; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + + GST_OBJECT_LOCK (provider); + len = g_list_length (provider->priv->hidden_providers); + if (len == 0) + goto done; + + res = g_new (gchar *, len + 1); + for (i = 0, walk = provider->priv->hidden_providers; walk; + walk = g_list_next (walk), i++) + res[i] = g_strdup (walk->data); + res[i] = NULL; + +done: + GST_OBJECT_UNLOCK (provider); + + return res; +} + +/** + * gst_device_provider_hide_provider: + * @provider: a #GstDeviceProvider + * @name: a provider factory name + * + * Make @provider hide the devices from the factory with @name. + * + * This function is used when @provider will also provide the devices reported + * by provider factory @name. A monitor should stop monitoring the + * device provider with @name to avoid duplicate devices. + * + * Since: 1.6 + */ +void +gst_device_provider_hide_provider (GstDeviceProvider * provider, + const gchar * name) +{ + GList *find; + const gchar *hidden_name = NULL; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (name != NULL); + + GST_OBJECT_LOCK (provider); + find = + g_list_find_custom (provider->priv->hidden_providers, name, + (GCompareFunc) g_strcmp0); + if (find == NULL) { + hidden_name = name; + provider->priv->hidden_providers = + g_list_prepend (provider->priv->hidden_providers, g_strdup (name)); + } + GST_OBJECT_UNLOCK (provider); + + if (hidden_name) + g_signal_emit (provider, gst_device_provider_signals[PROVIDER_HIDDEN], + 0, hidden_name); +} + +/** + * gst_device_provider_unhide_provider: + * @provider: a #GstDeviceProvider + * @name: a provider factory name + * + * Make @provider unhide the devices from factory @name. + * + * This function is used when @provider will no longer provide the devices + * reported by provider factory @name. A monitor should start + * monitoring the devices from provider factory @name in order to see + * all devices again. + * + * Since: 1.6 + */ +void +gst_device_provider_unhide_provider (GstDeviceProvider * provider, + const gchar * name) +{ + GList *find; + gchar *unhidden_name = NULL; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (name != NULL); + + GST_OBJECT_LOCK (provider); + find = + g_list_find_custom (provider->priv->hidden_providers, name, + (GCompareFunc) g_strcmp0); + if (find) { + unhidden_name = find->data; + provider->priv->hidden_providers = + g_list_delete_link (provider->priv->hidden_providers, find); + } + GST_OBJECT_UNLOCK (provider); + + if (unhidden_name) { + g_signal_emit (provider, + gst_device_provider_signals[PROVIDER_UNHIDDEN], 0, unhidden_name); + g_free (unhidden_name); + } +} diff --git a/gst/gstdeviceprovider.h b/gst/gstdeviceprovider.h new file mode 100644 index 0000000..a8f4474 --- /dev/null +++ b/gst/gstdeviceprovider.h @@ -0,0 +1,176 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete + * + * gstdeviceprovider.h: Device probing and monitoring + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifndef __GST_DEVICE_PROVIDER_H__ +#define __GST_DEVICE_PROVIDER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstDeviceProvider GstDeviceProvider; +typedef struct _GstDeviceProviderClass GstDeviceProviderClass; +typedef struct _GstDeviceProviderPrivate GstDeviceProviderPrivate; + +#include + +#define GST_TYPE_DEVICE_PROVIDER (gst_device_provider_get_type()) +#define GST_IS_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE_PROVIDER)) +#define GST_IS_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE_PROVIDER)) +#define GST_DEVICE_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE_PROVIDER, GstDeviceProviderClass)) +#define GST_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE_PROVIDER, GstDeviceProvider)) +#define GST_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_PROVIDER, GstDeviceProviderClass)) +#define GST_DEVICE_PROVIDER_CAST(obj) ((GstDeviceProvider *)(obj)) + + +/** + * GstDeviceProvider: + * @parent: The parent #GstObject + * @devices: a #GList of the #GstDevice objects + * + * The structure of the base #GstDeviceProvider + * + * Since: 1.4 + */ +struct _GstDeviceProvider { + GstObject parent; + + /* Protected by the Object lock */ + GList *devices; + + /*< private >*/ + + GstDeviceProviderPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDeviceProviderClass: + * @parent_class: the parent #GstObjectClass structure + * @factory: a pointer to the #GstDeviceProviderFactory that creates this + * provider + * @probe: Returns a list of devices that are currently available. + * This should never block. + * @start: Starts monitoring for new devices. Only subclasses that can know + * that devices have been added or remove need to implement this method. + * @stop: Stops monitoring for new devices. Only subclasses that implement + * the start() method need to implement this method. + * + * The structure of the base #GstDeviceProviderClass + * + * Since: 1.4 + */ + +struct _GstDeviceProviderClass { + GstObjectClass parent_class; + + GstDeviceProviderFactory *factory; + + GList* (*probe) (GstDeviceProvider * provider); + + gboolean (*start) (GstDeviceProvider * provider); + void (*stop) (GstDeviceProvider * provider); + + /*< private >*/ + gpointer metadata; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_device_provider_get_type (void); + + +GST_API +GList * gst_device_provider_get_devices (GstDeviceProvider * provider); + +GST_API +gboolean gst_device_provider_start (GstDeviceProvider * provider); + +GST_API +void gst_device_provider_stop (GstDeviceProvider * provider); + +GST_API +gboolean gst_device_provider_can_monitor (GstDeviceProvider * provider); + +GST_API +GstBus * gst_device_provider_get_bus (GstDeviceProvider * provider); + +GST_API +void gst_device_provider_device_add (GstDeviceProvider * provider, + GstDevice * device); +GST_API +void gst_device_provider_device_remove (GstDeviceProvider * provider, + GstDevice * device); +GST_API +gchar ** gst_device_provider_get_hidden_providers (GstDeviceProvider * provider); + +GST_API +void gst_device_provider_hide_provider (GstDeviceProvider * provider, + const gchar * name); +GST_API +void gst_device_provider_unhide_provider (GstDeviceProvider * provider, + const gchar * name); + +GST_API +const gchar * gst_device_provider_get_metadata (GstDeviceProvider * provider, + const gchar * key); + +/* device provider class meta data */ + +GST_API +void gst_device_provider_class_set_metadata (GstDeviceProviderClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +GST_API +void gst_device_provider_class_set_static_metadata (GstDeviceProviderClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +GST_API +void gst_device_provider_class_add_metadata (GstDeviceProviderClass * klass, + const gchar * key, const gchar * value); +GST_API +void gst_device_provider_class_add_static_metadata (GstDeviceProviderClass * klass, + const gchar * key, const gchar * value); +GST_API +const gchar * gst_device_provider_class_get_metadata (GstDeviceProviderClass * klass, + const gchar * key); + +/* factory management */ + +GST_API +GstDeviceProviderFactory * gst_device_provider_get_factory (GstDeviceProvider * provider); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceProvider, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DEVICE_PROVIDER_H__ */ diff --git a/gst/gstdeviceproviderfactory.c b/gst/gstdeviceproviderfactory.c new file mode 100644 index 0000000..3fbaa3b --- /dev/null +++ b/gst/gstdeviceproviderfactory.c @@ -0,0 +1,584 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2003 Benjamin Otte + * + * gstdeviceproviderfactory.c: GstDeviceProviderFactory object, support 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. + */ + +/** + * SECTION:gstdeviceproviderfactory + * @title: GstDeviceProviderFactory + * @short_description: Create GstDeviceProviders from a factory + * @see_also: #GstDeviceProvider, #GstPlugin, #GstPluginFeature, #GstPadTemplate. + * + * #GstDeviceProviderFactory is used to create instances of device providers. A + * GstDeviceProviderfactory can be added to a #GstPlugin as it is also a + * #GstPluginFeature. + * + * Use the gst_device_provider_factory_find() and + * gst_device_provider_factory_get() functions to create device + * provider instances or use gst_device_provider_factory_get_by_name() as a + * convenient shortcut. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdeviceproviderfactory.h" +#include "gst.h" + +#include "glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (device_provider_factory_debug); +#define GST_CAT_DEFAULT device_provider_factory_debug + +static void gst_device_provider_factory_finalize (GObject * object); +static void gst_device_provider_factory_cleanup (GstDeviceProviderFactory * + factory); + +/* static guint gst_device_provider_factory_signals[LAST_SIGNAL] = { 0 }; */ + +/* this is defined in gstelement.c */ +extern GQuark __gst_deviceproviderclass_factory; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (device_provider_factory_debug, "GST_DEVICE_PROVIDER_FACTORY", \ + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \ + "device provider factories keep information about installed device providers"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstDeviceProviderFactory, gst_device_provider_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_device_provider_factory_class_init (GstDeviceProviderFactoryClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = gst_device_provider_factory_finalize; +} + +static void +gst_device_provider_factory_init (GstDeviceProviderFactory * factory) +{ +} + +static void +gst_device_provider_factory_finalize (GObject * object) +{ + GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (object); + GstDeviceProvider *provider; + + gst_device_provider_factory_cleanup (factory); + + provider = g_atomic_pointer_get (&factory->provider); + if (provider) + gst_object_unref (provider); + + G_OBJECT_CLASS (gst_device_provider_factory_parent_class)->finalize (object); +} + +/** + * gst_device_provider_factory_find: + * @name: name of factory to find + * + * Search for an device provider factory of the given name. Refs the returned + * device provider factory; caller is responsible for unreffing. + * + * Returns: (transfer full) (nullable): #GstDeviceProviderFactory if + * found, %NULL otherwise + * + * Since: 1.4 + */ +GstDeviceProviderFactory * +gst_device_provider_factory_find (const gchar * name) +{ + GstPluginFeature *feature; + + g_return_val_if_fail (name != NULL, NULL); + + feature = gst_registry_find_feature (gst_registry_get (), name, + GST_TYPE_DEVICE_PROVIDER_FACTORY); + if (feature) + return GST_DEVICE_PROVIDER_FACTORY (feature); + + /* this isn't an error, for instance when you query if an device provider factory is + * present */ + GST_LOG ("no such device provider factory \"%s\"", name); + + return NULL; +} + +static void +gst_device_provider_factory_cleanup (GstDeviceProviderFactory * factory) +{ + if (factory->metadata) { + gst_structure_free ((GstStructure *) factory->metadata); + factory->metadata = NULL; + } + if (factory->type) { + factory->type = G_TYPE_INVALID; + } +} + +#define CHECK_METADATA_FIELD(klass, name, key) \ + G_STMT_START { \ + const gchar *metafield = gst_device_provider_class_get_metadata (klass, key); \ + if (G_UNLIKELY (metafield == NULL || *metafield == '\0')) { \ + g_warning ("Device provider factory metadata for '%s' has no valid %s field", name, key); \ + goto detailserror; \ + } \ + } G_STMT_END; + +/** + * gst_device_provider_register: + * @plugin: (allow-none): #GstPlugin to register the device provider with, or %NULL for + * a static device provider. + * @name: name of device providers of this type + * @rank: rank of device provider (higher rank means more importance when autoplugging) + * @type: GType of device provider to register + * + * Create a new device providerfactory capable of instantiating objects of the + * @type and add the factory to @plugin. + * + * Returns: %TRUE, if the registering succeeded, %FALSE on error + * + * Since: 1.4 + */ +gboolean +gst_device_provider_register (GstPlugin * plugin, const gchar * name, + guint rank, GType type) +{ + GstPluginFeature *existing_feature; + GstRegistry *registry; + GstDeviceProviderFactory *factory; + GstDeviceProviderClass *klass; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_DEVICE_PROVIDER), FALSE); + + registry = gst_registry_get (); + + /* check if feature already exists, if it exists there is no need to update it + * when the registry is getting updated, outdated plugins and all their + * features are removed and readded. + */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + factory = GST_DEVICE_PROVIDER_FACTORY_CAST (existing_feature); + factory->type = type; + existing_feature->loaded = TRUE; + g_type_set_qdata (type, __gst_deviceproviderclass_factory, factory); + gst_object_unref (existing_feature); + return TRUE; + } + + factory = g_object_new (GST_TYPE_DEVICE_PROVIDER_FACTORY, NULL); + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + GST_LOG_OBJECT (factory, "Created new device providerfactory for type %s", + g_type_name (type)); + + /* provide info needed during class structure setup */ + g_type_set_qdata (type, __gst_deviceproviderclass_factory, factory); + klass = GST_DEVICE_PROVIDER_CLASS (g_type_class_ref (type)); + + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_LONGNAME); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_KLASS); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_DESCRIPTION); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_AUTHOR); + + factory->type = type; + factory->metadata = gst_structure_copy ((GstStructure *) klass->metadata); + + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; + + /* ERRORS */ +detailserror: + { + gst_device_provider_factory_cleanup (factory); + return FALSE; + } +} + +/** + * gst_device_provider_factory_get: + * @factory: factory to instantiate + * + * Returns the device provider of the type defined by the given device + * providerfactory. + * + * Returns: (transfer full) (nullable): the #GstDeviceProvider or %NULL + * if the device provider couldn't be created + * + * Since: 1.4 + */ +GstDeviceProvider * +gst_device_provider_factory_get (GstDeviceProviderFactory * factory) +{ + GstDeviceProvider *device_provider; + GstDeviceProviderClass *oclass; + GstDeviceProviderFactory *newfactory; + + g_return_val_if_fail (factory != NULL, NULL); + + newfactory = + GST_DEVICE_PROVIDER_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + + if (newfactory == NULL) + goto load_failed; + + factory = newfactory; + + GST_INFO ("getting device provider \"%s\"", GST_OBJECT_NAME (factory)); + + if (factory->type == 0) + goto no_type; + + device_provider = g_atomic_pointer_get (&newfactory->provider); + if (device_provider) { + gst_object_unref (factory); + return gst_object_ref (device_provider); + } + + /* create an instance of the device provider, cast so we don't assert on NULL + * also set name as early as we can + */ + device_provider = g_object_new (factory->type, NULL); + if (G_UNLIKELY (device_provider == NULL)) + goto no_device_provider; + + /* fill in the pointer to the factory in the device provider class. The + * class will not be unreffed currently. + * Be thread safe as there might be 2 threads creating the first instance of + * an device provider at the same moment + */ + oclass = GST_DEVICE_PROVIDER_GET_CLASS (device_provider); + if (!g_atomic_pointer_compare_and_exchange (&oclass->factory, NULL, factory)) { + gst_object_unref (factory); + } else { + /* This ref will never be dropped as the class is never destroyed */ + GST_OBJECT_FLAG_SET (factory, GST_OBJECT_FLAG_MAY_BE_LEAKED); + } + + gst_object_ref_sink (device_provider); + + /* We use an atomic to make sure we don't create two in parallel */ + if (!g_atomic_pointer_compare_and_exchange (&newfactory->provider, NULL, + device_provider)) { + gst_object_unref (device_provider); + + device_provider = g_atomic_pointer_get (&newfactory->provider); + } + + GST_DEBUG ("created device provider \"%s\"", GST_OBJECT_NAME (factory)); + + return gst_object_ref (device_provider); + + /* ERRORS */ +load_failed: + { + GST_WARNING_OBJECT (factory, + "loading plugin containing feature %s returned NULL!", + GST_OBJECT_NAME (factory)); + return NULL; + } +no_type: + { + GST_WARNING_OBJECT (factory, "factory has no type"); + gst_object_unref (factory); + return NULL; + } +no_device_provider: + { + GST_WARNING_OBJECT (factory, "could not create device provider"); + gst_object_unref (factory); + return NULL; + } +} + +/** + * gst_device_provider_factory_get_by_name: + * @factoryname: a named factory to instantiate + * + * Returns the device provider of the type defined by the given device + * provider factory. + * + * Returns: (transfer full) (nullable): a #GstDeviceProvider or %NULL + * if unable to create device provider + * + * Since: 1.4 + */ +GstDeviceProvider * +gst_device_provider_factory_get_by_name (const gchar * factoryname) +{ + GstDeviceProviderFactory *factory; + GstDeviceProvider *device_provider; + + g_return_val_if_fail (factoryname != NULL, NULL); + g_return_val_if_fail (gst_is_initialized (), NULL); + + GST_LOG ("gstdeviceproviderfactory: get_by_name \"%s\"", factoryname); + + factory = gst_device_provider_factory_find (factoryname); + if (factory == NULL) + goto no_factory; + + GST_LOG_OBJECT (factory, "found factory %p", factory); + device_provider = gst_device_provider_factory_get (factory); + if (device_provider == NULL) + goto create_failed; + + gst_object_unref (factory); + return device_provider; + + /* ERRORS */ +no_factory: + { + GST_INFO ("no such device provider factory \"%s\"!", factoryname); + return NULL; + } +create_failed: + { + GST_INFO_OBJECT (factory, "couldn't create instance!"); + gst_object_unref (factory); + return NULL; + } +} + +/** + * gst_device_provider_factory_get_device_provider_type: + * @factory: factory to get managed #GType from + * + * Get the #GType for device providers managed by this factory. The type can + * only be retrieved if the device provider factory is loaded, which can be + * assured with gst_plugin_feature_load(). + * + * Returns: the #GType for device providers managed by this factory. + * + * Since: 1.4 + */ +GType +gst_device_provider_factory_get_device_provider_type (GstDeviceProviderFactory * + factory) +{ + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER_FACTORY (factory), + G_TYPE_INVALID); + + return factory->type; +} + +/** + * gst_device_provider_factory_get_metadata: + * @factory: a #GstDeviceProviderFactory + * @key: a key + * + * Get the metadata on @factory with @key. + * + * Returns: (nullable): the metadata with @key on @factory or %NULL + * when there was no metadata with the given @key. + * + * Since: 1.4 + */ +const gchar * +gst_device_provider_factory_get_metadata (GstDeviceProviderFactory * factory, + const gchar * key) +{ + return gst_structure_get_string ((GstStructure *) factory->metadata, key); +} + +/** + * gst_device_provider_factory_get_metadata_keys: + * @factory: a #GstDeviceProviderFactory + * + * Get the available keys for the metadata on @factory. + * + * Returns: (transfer full) (element-type utf8) (array zero-terminated=1) (nullable): + * a %NULL-terminated array of key strings, or %NULL when there is no + * metadata. Free with g_strfreev() when no longer needed. + * + * Since: 1.4 + */ +gchar ** +gst_device_provider_factory_get_metadata_keys (GstDeviceProviderFactory * + factory) +{ + GstStructure *metadata; + gchar **arr; + gint i, num; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER_FACTORY (factory), NULL); + + metadata = (GstStructure *) factory->metadata; + if (metadata == NULL) + return NULL; + + num = gst_structure_n_fields (metadata); + if (num == 0) + return NULL; + + arr = g_new (gchar *, num + 1); + for (i = 0; i < num; ++i) { + arr[i] = g_strdup (gst_structure_nth_field_name (metadata, i)); + } + arr[i] = NULL; + return arr; +} + +/** + * gst_device_provider_factory_has_classesv: + * @factory: a #GstDeviceProviderFactory + * @classes: (array zero-terminated=1) (allow-none): a %NULL terminated array + * of classes to match, only match if all classes are matched + * + * Check if @factory matches all of the given classes + * + * Returns: %TRUE if @factory matches. + * + * Since: 1.4 + */ +gboolean +gst_device_provider_factory_has_classesv (GstDeviceProviderFactory * factory, + gchar ** classes) +{ + const gchar *klass; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER_FACTORY (factory), FALSE); + + klass = gst_device_provider_factory_get_metadata (factory, + GST_ELEMENT_METADATA_KLASS); + + if (klass == NULL) { + GST_ERROR_OBJECT (factory, + "device provider factory is missing klass identifiers"); + return FALSE; + } + + for (; classes != NULL && classes[0] != NULL; classes++) { + const gchar *found; + guint len; + + if (classes[0][0] == '\0') + continue; + + found = strstr (klass, classes[0]); + + if (!found) + return FALSE; + if (found != klass && *(found - 1) != '/') + return FALSE; + + len = strlen (classes[0]); + if (found[len] != 0 && found[len] != '/') + return FALSE; + } + + return TRUE; +} + +/** + * gst_device_provider_factory_has_classes: + * @factory: a #GstDeviceProviderFactory + * @classes: (allow-none): a "/" separate list of classes to match, only match + * if all classes are matched + * + * Check if @factory matches all of the given @classes + * + * Returns: %TRUE if @factory matches or if @classes is %NULL. + * + * Since: 1.4 + */ +gboolean +gst_device_provider_factory_has_classes (GstDeviceProviderFactory * factory, + const gchar * classes) +{ + gchar **classesv; + gboolean res; + + if (classes == NULL) + return TRUE; + + classesv = g_strsplit (classes, "/", 0); + + res = gst_device_provider_factory_has_classesv (factory, classesv); + + g_strfreev (classesv); + + return res; +} + +static gboolean +device_provider_filter (GstPluginFeature * feature, GstRank * minrank) +{ + /* we only care about device provider factories */ + if (G_UNLIKELY (!GST_IS_DEVICE_PROVIDER_FACTORY (feature))) + return FALSE; + + return (gst_plugin_feature_get_rank (feature) >= *minrank); +} + +/** + * gst_device_provider_factory_list_get_device_providers: + * @minrank: Minimum rank + * + * Get a list of factories with a rank greater or equal to @minrank. + * The list of factories is returned by decreasing rank. + * + * Returns: (transfer full) (element-type Gst.DeviceProviderFactory): + * a #GList of #GstDeviceProviderFactory device providers. Use + * gst_plugin_feature_list_free() after usage. + * + * Since: 1.4 + */ +GList * +gst_device_provider_factory_list_get_device_providers (GstRank minrank) +{ + GList *result; + + /* get the feature list using the filter */ + result = gst_registry_feature_filter (gst_registry_get (), + (GstPluginFeatureFilter) device_provider_filter, FALSE, &minrank); + + /* sort on rank and name */ + result = g_list_sort (result, gst_plugin_feature_rank_compare_func); + + return result; +} diff --git a/gst/gstdeviceproviderfactory.h b/gst/gstdeviceproviderfactory.h new file mode 100644 index 0000000..41840b8 --- /dev/null +++ b/gst/gstdeviceproviderfactory.h @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2004 Wim Taymans + * 2012 Olivier Crete + * + * gstdeviceproviderfactory.h: Header for GstDeviceProviderFactory + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifndef __GST_DEVICE_PROVIDER_FACTORY_H__ +#define __GST_DEVICE_PROVIDER_FACTORY_H__ + +/** + * GstDeviceProviderFactory: + * + * The opaque #GstDeviceProviderFactory data structure. + * + * Since: 1.4 + */ + +/** + * GstDeviceProviderFactoryClass: + * + * The opaque #GstDeviceProviderFactoryClass data structure. + * + * Since: 1.4 + */ +typedef struct _GstDeviceProviderFactory GstDeviceProviderFactory; +typedef struct _GstDeviceProviderFactoryClass GstDeviceProviderFactoryClass; + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DEVICE_PROVIDER_FACTORY (gst_device_provider_factory_get_type()) +#define GST_DEVICE_PROVIDER_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEVICE_PROVIDER_FACTORY,\ + GstDeviceProviderFactory)) +#define GST_DEVICE_PROVIDER_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEVICE_PROVIDER_FACTORY,\ + GstDeviceProviderFactoryClass)) +#define GST_IS_DEVICE_PROVIDER_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEVICE_PROVIDER_FACTORY)) +#define GST_IS_DEVICE_PROVIDER_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEVICE_PROVIDER_FACTORY)) +#define GST_DEVICE_PROVIDER_FACTORY_CAST(obj) ((GstDeviceProviderFactory *)(obj)) + +GST_API +GType gst_device_provider_factory_get_type (void); + +GST_API +GstDeviceProviderFactory * gst_device_provider_factory_find (const gchar *name); + +GST_API +GType gst_device_provider_factory_get_device_provider_type (GstDeviceProviderFactory *factory); + +GST_API +const gchar * gst_device_provider_factory_get_metadata (GstDeviceProviderFactory *factory, const gchar *key); + +GST_API +gchar ** gst_device_provider_factory_get_metadata_keys (GstDeviceProviderFactory *factory); + +GST_API +GstDeviceProvider* gst_device_provider_factory_get (GstDeviceProviderFactory *factory) G_GNUC_MALLOC; + +GST_API +GstDeviceProvider* gst_device_provider_factory_get_by_name (const gchar *factoryname) G_GNUC_MALLOC; + +GST_API +gboolean gst_device_provider_register (GstPlugin *plugin, const gchar *name, + guint rank, + GType type); +GST_API +gboolean gst_device_provider_factory_has_classesv (GstDeviceProviderFactory * factory, + gchar ** classes); +GST_API +gboolean gst_device_provider_factory_has_classes (GstDeviceProviderFactory *factory, + const gchar * classes); +GST_API +GList * gst_device_provider_factory_list_get_device_providers ( + GstRank minrank) G_GNUC_MALLOC; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDeviceProviderFactory, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DEVICE_PROVIDER_FACTORY_H__ */ diff --git a/gst/gstdynamictypefactory.c b/gst/gstdynamictypefactory.c new file mode 100644 index 0000000..cb388a5 --- /dev/null +++ b/gst/gstdynamictypefactory.c @@ -0,0 +1,175 @@ +/* GStreamer + * Copyright (C) 2015 Jan Schmidt + * + * gstdynamictypefactory.c: Implementation of GstDynamicTypeFactory + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstdynamictypefactory + * @title: GstDynamicTypeFactory + * @short_description: Represents a registered dynamically loadable GType + * @see_also: #GstPlugin, #GstPluginFeature. + * + * #GstDynamicTypeFactory is used to represent a type that can be + * automatically loaded the first time it is used. For example, + * a non-standard type for use in caps fields. + * + * In general, applications and plugins don't need to use the factory + * beyond registering the type in a plugin init function. Once that is + * done, the type is stored in the registry, and ready as soon as the + * registry is loaded. + * + * ## Registering a type for dynamic loading + * + * |[ + * + * static gboolean + * plugin_init (GstPlugin * plugin) + * { + * return gst_dynamic_type_register (plugin, GST_TYPE_CUSTOM_CAPS_FIELD); + * } + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include + +#include "gst.h" + +#include "glib-compat-private.h" + + +GST_DEBUG_CATEGORY_STATIC (dynamic_type_factory_debug); +#define GST_CAT_DEFAULT dynamic_type_factory_debug + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (dynamic_type_factory_debug, \ + "GST_DYNAMIC_TYPE_FACTORY", GST_DEBUG_BOLD, \ + "dynamic type factories allow automatically loading a type from a plugin"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstDynamicTypeFactory, gst_dynamic_type_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_dynamic_type_factory_class_init (GstDynamicTypeFactoryClass * klass) +{ +} + +static void +gst_dynamic_type_factory_init (GstDynamicTypeFactory * factory) +{ +} + +static GstDynamicTypeFactory * +gst_dynamic_type_factory_find (const gchar * name) +{ + GstPluginFeature *feature; + + g_return_val_if_fail (name != NULL, NULL); + + feature = gst_registry_find_feature (gst_registry_get (), name, + GST_TYPE_DYNAMIC_TYPE_FACTORY); + if (feature) + return GST_DYNAMIC_TYPE_FACTORY (feature); + + return NULL; +} + +GType +gst_dynamic_type_factory_load (const gchar * factoryname) +{ + GstDynamicTypeFactory *factory = gst_dynamic_type_factory_find (factoryname); + + /* Called with a non-dynamic or unregistered type? */ + if (factory == NULL) + return FALSE; + + factory = + GST_DYNAMIC_TYPE_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + if (factory == NULL) + return 0; + + GST_DEBUG_OBJECT (factory, "Loaded type %s", factoryname); + + return factory->type; +} + +static GstDynamicTypeFactory * +gst_dynamic_type_factory_create (GstRegistry * registry, + GstPlugin * plugin, const gchar * name) +{ + GstDynamicTypeFactory *factory; + + factory = g_object_new (GST_TYPE_DYNAMIC_TYPE_FACTORY, NULL); + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + GST_LOG_OBJECT (factory, "Created new dynamictypefactory for type %s", name); + + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + return factory; +} + +gboolean +gst_dynamic_type_register (GstPlugin * plugin, GType dyn_type) +{ + GstDynamicTypeFactory *factory; + const gchar *name; + GstPluginFeature *existing_feature; + GstRegistry *registry; + + name = g_type_name (dyn_type); + g_return_val_if_fail (name != NULL, FALSE); + + registry = gst_registry_get (); + + /* check if feature already exists, if it exists there is no need to + * update it for this method of dynamic type */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + existing_feature->loaded = TRUE; + GST_DYNAMIC_TYPE_FACTORY (existing_feature)->type = dyn_type; + gst_object_unref (existing_feature); + return TRUE; + } + + factory = gst_dynamic_type_factory_create (registry, plugin, name); + factory->type = dyn_type; + + gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; +} diff --git a/gst/gstdynamictypefactory.h b/gst/gstdynamictypefactory.h new file mode 100644 index 0000000..2778408 --- /dev/null +++ b/gst/gstdynamictypefactory.h @@ -0,0 +1,59 @@ +/* GStreamer + * Copyright (C) 2015 Jan Schmidt + * + * gstdynamictypefactory.h: Header for GstDynamicTypeFactory + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_DYNAMIC_TYPE_FACTORY_H__ +#define __GST_DYNAMIC_TYPE_FACTORY_H__ + +/** + * GstDynamicTypeFactory: + * + * The opaque #GstDynamicTypeFactory data structure. + */ +typedef struct _GstDynamicTypeFactory GstDynamicTypeFactory; +typedef struct _GstDynamicTypeFactoryClass GstDynamicTypeFactoryClass; + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DYNAMIC_TYPE_FACTORY (gst_dynamic_type_factory_get_type()) +#define GST_DYNAMIC_TYPE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY,\ + GstDynamicTypeFactory)) +#define GST_DYNAMIC_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY,\ + GstDynamicTypeFactoryClass)) +#define GST_IS_DYNAMIC_TYPE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY)) +#define GST_IS_DYNAMIC_TYPE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY)) +#define GST_DYNAMIC_TYPE_FACTORY_CAST(obj) ((GstDynamicTypeFactory *)(obj)) + +GST_API +GType gst_dynamic_type_factory_get_type (void); + +GST_API +GType gst_dynamic_type_factory_load (const gchar *factoryname); + +GST_API +gboolean gst_dynamic_type_register (GstPlugin *plugin, GType type); + +G_END_DECLS + +#endif diff --git a/gst/gstelement.c b/gst/gstelement.c new file mode 100644 index 0000000..8a908a1 --- /dev/null +++ b/gst/gstelement.c @@ -0,0 +1,3757 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004 Wim Taymans + * + * gstelement.c: The base element, all elements derive from this + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstelement + * @title: GstElement + * @short_description: Abstract base class for all pipeline elements + * @see_also: #GstElementFactory, #GstPad + * + * GstElement is the abstract base class needed to construct an element that + * can be used in a GStreamer pipeline. Please refer to the plugin writers + * guide for more information on creating #GstElement subclasses. + * + * The name of a #GstElement can be get with gst_element_get_name() and set with + * gst_element_set_name(). For speed, GST_ELEMENT_NAME() can be used in the + * core when using the appropriate locking. Do not use this in plug-ins or + * applications in order to retain ABI compatibility. + * + * Elements can have pads (of the type #GstPad). These pads link to pads on + * other elements. #GstBuffer flow between these linked pads. + * A #GstElement has a #GList of #GstPad structures for all their input (or sink) + * and output (or source) pads. + * Core and plug-in writers can add and remove pads with gst_element_add_pad() + * and gst_element_remove_pad(). + * + * An existing pad of an element can be retrieved by name with + * gst_element_get_static_pad(). A new dynamic pad can be created using + * gst_element_request_pad() with a #GstPadTemplate. + * An iterator of all pads can be retrieved with gst_element_iterate_pads(). + * + * Elements can be linked through their pads. + * If the link is straightforward, use the gst_element_link() + * convenience function to link two elements, or gst_element_link_many() + * for more elements in a row. + * Use gst_element_link_filtered() to link two elements constrained by + * a specified set of #GstCaps. + * For finer control, use gst_element_link_pads() and + * gst_element_link_pads_filtered() to specify the pads to link on + * each element by name. + * + * Each element has a state (see #GstState). You can get and set the state + * of an element with gst_element_get_state() and gst_element_set_state(). + * Setting a state triggers a #GstStateChange. To get a string representation + * of a #GstState, use gst_element_state_get_name(). + * + * You can get and set a #GstClock on an element using gst_element_get_clock() + * and gst_element_set_clock(). + * Some elements can provide a clock for the pipeline if + * the #GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the + * gst_element_provide_clock() method one can retrieve the clock provided by + * such an element. + * Not all elements require a clock to operate correctly. If the + * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the + * element with gst_element_set_clock(). + * + * Note that clock selection and distribution is normally handled by the + * toplevel #GstPipeline so the clock functions are only to be used in very + * specific situations. + */ + +#include "gst_private.h" +#include +#include +#include + +#include "gstelement.h" +#include "gstelementmetadata.h" +#include "gstenumtypes.h" +#include "gstbus.h" +#include "gsterror.h" +#include "gstevent.h" +#include "gstutils.h" +#include "gstinfo.h" +#include "gstquark.h" +#include "gsttracerutils.h" +#include "gstvalue.h" +#include "gst-i18n-lib.h" +#include "glib-compat-private.h" + +#ifndef GST_DISABLE_GST_DEBUG +#include "printf/printf.h" +#endif + +/* Element signals and args */ +enum +{ + PAD_ADDED, + PAD_REMOVED, + NO_MORE_PADS, + /* add more above */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 + /* FILL ME */ +}; + +static void gst_element_class_init (GstElementClass * klass); +static void gst_element_init (GstElement * element); +static void gst_element_base_class_init (gpointer g_class); + +static void gst_element_constructed (GObject * object); +static void gst_element_dispose (GObject * object); +static void gst_element_finalize (GObject * object); + +static GstStateChangeReturn gst_element_change_state_func (GstElement * element, + GstStateChange transition); +static GstStateChangeReturn gst_element_get_state_func (GstElement * element, + GstState * state, GstState * pending, GstClockTime timeout); +static GstStateChangeReturn gst_element_set_state_func (GstElement * element, + GstState state); +static gboolean gst_element_set_clock_func (GstElement * element, + GstClock * clock); +static void gst_element_set_bus_func (GstElement * element, GstBus * bus); +static gboolean gst_element_post_message_default (GstElement * element, + GstMessage * message); +static void gst_element_set_context_default (GstElement * element, + GstContext * context); + +static gboolean gst_element_default_send_event (GstElement * element, + GstEvent * event); +static gboolean gst_element_default_query (GstElement * element, + GstQuery * query); + +static GstPadTemplate + * gst_element_class_get_request_pad_template (GstElementClass * + element_class, const gchar * name); + +static void gst_element_call_async_func (gpointer data, gpointer user_data); + +static GstObjectClass *parent_class = NULL; +static guint gst_element_signals[LAST_SIGNAL] = { 0 }; + +static GThreadPool *gst_element_pool = NULL; + +/* this is used in gstelementfactory.c:gst_element_register() */ +GQuark __gst_elementclass_factory = 0; + +GType +gst_element_get_type (void) +{ + static volatile gsize gst_element_type = 0; + + if (g_once_init_enter (&gst_element_type)) { + GType _type; + static const GTypeInfo element_info = { + sizeof (GstElementClass), + gst_element_base_class_init, + NULL, /* base_class_finalize */ + (GClassInitFunc) gst_element_class_init, + NULL, + NULL, + sizeof (GstElement), + 0, + (GInstanceInitFunc) gst_element_init, + NULL + }; + + _type = g_type_register_static (GST_TYPE_OBJECT, "GstElement", + &element_info, G_TYPE_FLAG_ABSTRACT); + + __gst_elementclass_factory = + g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY"); + g_once_init_leave (&gst_element_type, _type); + } + return gst_element_type; +} + +static void +gst_element_setup_thread_pool (void) +{ + GError *err = NULL; + + GST_DEBUG ("creating element thread pool"); + gst_element_pool = + g_thread_pool_new ((GFunc) gst_element_call_async_func, NULL, -1, FALSE, + &err); + if (err != NULL) { + g_critical ("could not alloc threadpool %s", err->message); + g_clear_error (&err); + } +} + +static void +gst_element_class_init (GstElementClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + /** + * GstElement::pad-added: + * @gstelement: the object which received the signal + * @new_pad: the pad that has been added + * + * a new #GstPad has been added to the element. Note that this signal will + * usually be emitted from the context of the streaming thread. Also keep in + * mind that if you add new elements to the pipeline in the signal handler + * you will need to set them to the desired target state with + * gst_element_set_state() or gst_element_sync_state_with_parent(). + */ + gst_element_signals[PAD_ADDED] = + g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD); + /** + * GstElement::pad-removed: + * @gstelement: the object which received the signal + * @old_pad: the pad that has been removed + * + * a #GstPad has been removed from the element + */ + gst_element_signals[PAD_REMOVED] = + g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD); + /** + * GstElement::no-more-pads: + * @gstelement: the object which received the signal + * + * This signals that the element will not generate more dynamic pads. + * Note that this signal will usually be emitted from the context of + * the streaming thread. + */ + gst_element_signals[NO_MORE_PADS] = + g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0); + + gobject_class->dispose = gst_element_dispose; + gobject_class->finalize = gst_element_finalize; + gobject_class->constructed = gst_element_constructed; + + klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func); + klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func); + klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func); + klass->set_clock = GST_DEBUG_FUNCPTR (gst_element_set_clock_func); + klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func); + klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query); + klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event); + klass->numpadtemplates = 0; + klass->post_message = GST_DEBUG_FUNCPTR (gst_element_post_message_default); + klass->set_context = GST_DEBUG_FUNCPTR (gst_element_set_context_default); + + klass->elementfactory = NULL; + + gst_element_setup_thread_pool (); +} + +static void +gst_element_base_class_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GList *node, *padtemplates; + + /* Copy the element details here so elements can inherit the + * details from their base class and classes only need to set + * the details in class_init instead of base_init */ + element_class->metadata = + element_class->metadata ? gst_structure_copy (element_class->metadata) : + gst_structure_new_empty ("metadata"); + + /* Copy the pad templates so elements inherit them + * from their base class but elements can add pad templates in class_init + * instead of base_init. + */ + padtemplates = g_list_copy (element_class->padtemplates); + for (node = padtemplates; node != NULL; node = node->next) { + GstPadTemplate *tmpl = (GstPadTemplate *) node->data; + gst_object_ref (tmpl); + } + element_class->padtemplates = padtemplates; + + /* set the factory, see gst_element_register() */ + element_class->elementfactory = + g_type_get_qdata (G_TYPE_FROM_CLASS (element_class), + __gst_elementclass_factory); + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "type %s : factory %p", + G_OBJECT_CLASS_NAME (element_class), element_class->elementfactory); +} + +static void +gst_element_init (GstElement * element) +{ + GST_STATE (element) = GST_STATE_NULL; + GST_STATE_TARGET (element) = GST_STATE_NULL; + GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING; + GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; + GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS; + + g_rec_mutex_init (&element->state_lock); + g_cond_init (&element->state_cond); +} + +static void +gst_element_constructed (GObject * object) +{ + GST_TRACER_ELEMENT_NEW (GST_ELEMENT_CAST (object)); + G_OBJECT_CLASS (parent_class)->constructed (object); +} + +/** + * gst_element_release_request_pad: + * @element: a #GstElement to release the request pad of. + * @pad: the #GstPad to release. + * + * Makes the element free the previously requested pad as obtained + * with gst_element_request_pad(). + * + * This does not unref the pad. If the pad was created by using + * gst_element_request_pad(), gst_element_release_request_pad() needs to be + * followed by gst_object_unref() to free the @pad. + * + * MT safe. + */ +void +gst_element_release_request_pad (GstElement * element, GstPad * pad) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (GST_PAD_PAD_TEMPLATE (pad) == NULL || + GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) == + GST_PAD_REQUEST); + g_return_if_fail (GST_PAD_PARENT (pad) == element); + + oclass = GST_ELEMENT_GET_CLASS (element); + + /* if the element implements a custom release function we call that, else we + * simply remove the pad from the element */ + if (oclass->release_pad) + oclass->release_pad (element, pad); + else + gst_element_remove_pad (element, pad); +} + +/** + * gst_element_provide_clock: + * @element: a #GstElement to query + * + * Get the clock provided by the given element. + * > An element is only required to provide a clock in the PAUSED + * > state. Some elements can provide a clock in other states. + * + * Returns: (transfer full) (nullable): the GstClock provided by the + * element or %NULL if no clock could be provided. Unref after usage. + * + * MT safe. + */ +GstClock * +gst_element_provide_clock (GstElement * element) +{ + GstClock *result = NULL; + GstElementClass *oclass; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->provide_clock) + result = oclass->provide_clock (element); + + return result; +} + +static gboolean +gst_element_set_clock_func (GstElement * element, GstClock * clock) +{ + GstClock **clock_p; + + GST_OBJECT_LOCK (element); + clock_p = &element->clock; + gst_object_replace ((GstObject **) clock_p, (GstObject *) clock); + GST_OBJECT_UNLOCK (element); + + return TRUE; +} + +/** + * gst_element_set_clock: + * @element: a #GstElement to set the clock for. + * @clock: (transfer none) (allow-none): the #GstClock to set for the element. + * + * Sets the clock for the element. This function increases the + * refcount on the clock. Any previously set clock on the object + * is unreffed. + * + * Returns: %TRUE if the element accepted the clock. An element can refuse a + * clock when it, for example, is not able to slave its internal clock to the + * @clock or when it requires a specific clock to operate. + * + * MT safe. + */ +gboolean +gst_element_set_clock (GstElement * element, GstClock * clock) +{ + GstElementClass *oclass; + gboolean res = FALSE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (clock == NULL || GST_IS_CLOCK (clock), FALSE); + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, "setting clock %p", clock); + + if (oclass->set_clock) + res = oclass->set_clock (element, clock); + + return res; +} + +/** + * gst_element_get_clock: + * @element: a #GstElement to get the clock of. + * + * Gets the currently configured clock of the element. This is the clock as was + * last set with gst_element_set_clock(). + * + * Elements in a pipeline will only have their clock set when the + * pipeline is in the PLAYING state. + * + * Returns: (transfer full) (nullable): the #GstClock of the element. unref after usage. + * + * MT safe. + */ +GstClock * +gst_element_get_clock (GstElement * element) +{ + GstClock *result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + GST_OBJECT_LOCK (element); + if ((result = element->clock)) + gst_object_ref (result); + GST_OBJECT_UNLOCK (element); + + return result; +} + +/** + * gst_element_set_base_time: + * @element: a #GstElement. + * @time: the base time to set. + * + * Set the base time of an element. See gst_element_get_base_time(). + * + * MT safe. + */ +void +gst_element_set_base_time (GstElement * element, GstClockTime time) +{ + GstClockTime old; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_OBJECT_LOCK (element); + old = element->base_time; + element->base_time = time; + GST_OBJECT_UNLOCK (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, + "set base_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT, + GST_TIME_ARGS (time), GST_TIME_ARGS (old)); +} + +/** + * gst_element_get_base_time: + * @element: a #GstElement. + * + * Returns the base time of the element. The base time is the + * absolute time of the clock when this element was last put to + * PLAYING. Subtracting the base time from the clock time gives + * the running time of the element. + * + * Returns: the base time of the element. + * + * MT safe. + */ +GstClockTime +gst_element_get_base_time (GstElement * element) +{ + GstClockTime result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (element); + result = element->base_time; + GST_OBJECT_UNLOCK (element); + + return result; +} + +/** + * gst_element_set_start_time: + * @element: a #GstElement. + * @time: the base time to set. + * + * Set the start time of an element. The start time of the element is the + * running time of the element when it last went to the PAUSED state. In READY + * or after a flushing seek, it is set to 0. + * + * Toplevel elements like #GstPipeline will manage the start_time and + * base_time on its children. Setting the start_time to #GST_CLOCK_TIME_NONE + * on such a toplevel element will disable the distribution of the base_time to + * the children and can be useful if the application manages the base_time + * itself, for example if you want to synchronize capture from multiple + * pipelines, and you can also ensure that the pipelines have the same clock. + * + * MT safe. + */ +void +gst_element_set_start_time (GstElement * element, GstClockTime time) +{ + GstClockTime old; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_OBJECT_LOCK (element); + old = GST_ELEMENT_START_TIME (element); + GST_ELEMENT_START_TIME (element) = time; + GST_OBJECT_UNLOCK (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, + "set start_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT, + GST_TIME_ARGS (time), GST_TIME_ARGS (old)); +} + +/** + * gst_element_get_start_time: + * @element: a #GstElement. + * + * Returns the start time of the element. The start time is the + * running time of the clock when this element was last put to PAUSED. + * + * Usually the start_time is managed by a toplevel element such as + * #GstPipeline. + * + * MT safe. + * + * Returns: the start time of the element. + */ +GstClockTime +gst_element_get_start_time (GstElement * element) +{ + GstClockTime result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (element); + result = GST_ELEMENT_START_TIME (element); + GST_OBJECT_UNLOCK (element); + + return result; +} + +#if 0 +/** + * gst_element_set_index: + * @element: a #GstElement. + * @index: (transfer none): a #GstIndex. + * + * Set @index on the element. The refcount of the index + * will be increased, any previously set index is unreffed. + * + * MT safe. + */ +void +gst_element_set_index (GstElement * element, GstIndex * index) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + g_return_if_fail (index == NULL || GST_IS_INDEX (index)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->set_index) + oclass->set_index (element, index); +} + +/** + * gst_element_get_index: + * @element: a #GstElement. + * + * Gets the index from the element. + * + * Returns: (transfer full) (nullable): a #GstIndex or %NULL when no + * index was set on the element. unref after usage. + * + * MT safe. + */ +GstIndex * +gst_element_get_index (GstElement * element) +{ + GstElementClass *oclass; + GstIndex *result = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->get_index) + result = oclass->get_index (element); + + return result; +} +#endif + +/** + * gst_element_add_pad: + * @element: a #GstElement to add the pad to. + * @pad: (transfer floating): the #GstPad to add to the element. + * + * Adds a pad (link point) to @element. @pad's parent will be set to @element; + * see gst_object_set_parent() for refcounting information. + * + * Pads are not automatically activated so elements should perform the needed + * steps to activate the pad in case this pad is added in the PAUSED or PLAYING + * state. See gst_pad_set_active() for more information about activating pads. + * + * The pad and the element should be unlocked when calling this function. + * + * This function will emit the #GstElement::pad-added signal on the element. + * + * Returns: %TRUE if the pad could be added. This function can fail when + * a pad with the same name already existed or the pad already had another + * parent. + * + * MT safe. + */ +gboolean +gst_element_add_pad (GstElement * element, GstPad * pad) +{ + gchar *pad_name; + gboolean active; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + /* locking pad to look at the name */ + GST_OBJECT_LOCK (pad); + pad_name = g_strdup (GST_PAD_NAME (pad)); + GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'", + GST_STR_NULL (pad_name)); + active = GST_PAD_IS_ACTIVE (pad); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT); + GST_OBJECT_UNLOCK (pad); + + /* then check to see if there's already a pad by that name here */ + GST_OBJECT_LOCK (element); + if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name))) + goto name_exists; + + /* try to set the pad's parent */ + if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad), + GST_OBJECT_CAST (element)))) + goto had_parent; + + /* check for active pads */ + if (!active && (GST_STATE (element) > GST_STATE_READY || + GST_STATE_NEXT (element) == GST_STATE_PAUSED)) { + g_warning ("adding inactive pad '%s' to running element '%s', you need to " + "use gst_pad_set_active(pad,TRUE) before adding it.", + GST_STR_NULL (pad_name), GST_ELEMENT_NAME (element)); + gst_pad_set_active (pad, TRUE); + } + + g_free (pad_name); + + /* add it to the list */ + switch (gst_pad_get_direction (pad)) { + case GST_PAD_SRC: + element->srcpads = g_list_append (element->srcpads, pad); + element->numsrcpads++; + break; + case GST_PAD_SINK: + element->sinkpads = g_list_append (element->sinkpads, pad); + element->numsinkpads++; + break; + default: + goto no_direction; + } + element->pads = g_list_append (element->pads, pad); + element->numpads++; + element->pads_cookie++; + GST_OBJECT_UNLOCK (element); + + /* emit the PAD_ADDED signal */ + g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad); + GST_TRACER_ELEMENT_ADD_PAD (element, pad); + return TRUE; + + /* ERROR cases */ +name_exists: + { + g_critical ("Padname %s is not unique in element %s, not adding", + pad_name, GST_ELEMENT_NAME (element)); + GST_OBJECT_UNLOCK (element); + g_free (pad_name); + gst_object_ref_sink (pad); + gst_object_unref (pad); + return FALSE; + } +had_parent: + { + g_critical + ("Pad %s already has parent when trying to add to element %s", + pad_name, GST_ELEMENT_NAME (element)); + GST_OBJECT_UNLOCK (element); + g_free (pad_name); + return FALSE; + } +no_direction: + { + GST_OBJECT_LOCK (pad); + g_critical + ("Trying to add pad %s to element %s, but it has no direction", + GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element)); + GST_OBJECT_UNLOCK (pad); + GST_OBJECT_UNLOCK (element); + return FALSE; + } +} + +/** + * gst_element_remove_pad: + * @element: a #GstElement to remove pad from. + * @pad: (transfer none): the #GstPad to remove from the element. + * + * Removes @pad from @element. @pad will be destroyed if it has not been + * referenced elsewhere using gst_object_unparent(). + * + * This function is used by plugin developers and should not be used + * by applications. Pads that were dynamically requested from elements + * with gst_element_request_pad() should be released with the + * gst_element_release_request_pad() function instead. + * + * Pads are not automatically deactivated so elements should perform the needed + * steps to deactivate the pad in case this pad is removed in the PAUSED or + * PLAYING state. See gst_pad_set_active() for more information about + * deactivating pads. + * + * The pad and the element should be unlocked when calling this function. + * + * This function will emit the #GstElement::pad-removed signal on the element. + * + * Returns: %TRUE if the pad could be removed. Can return %FALSE if the + * pad does not belong to the provided element. + * + * MT safe. + */ +gboolean +gst_element_remove_pad (GstElement * element, GstPad * pad) +{ + GstPad *peer; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + /* locking pad to look at the name and parent */ + GST_OBJECT_LOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'", + GST_STR_NULL (GST_PAD_NAME (pad))); + + if (G_UNLIKELY (GST_PAD_PARENT (pad) != element)) + goto not_our_pad; + GST_OBJECT_UNLOCK (pad); + + /* unlink */ + if ((peer = gst_pad_get_peer (pad))) { + /* window for MT unsafeness, someone else could unlink here + * and then we call unlink with wrong pads. The unlink + * function would catch this and safely return failed. */ + if (GST_PAD_IS_SRC (pad)) + gst_pad_unlink (pad, peer); + else + gst_pad_unlink (peer, pad); + + gst_object_unref (peer); + } + + GST_OBJECT_LOCK (element); + /* remove it from the list */ + switch (gst_pad_get_direction (pad)) { + case GST_PAD_SRC: + element->srcpads = g_list_remove (element->srcpads, pad); + element->numsrcpads--; + break; + case GST_PAD_SINK: + element->sinkpads = g_list_remove (element->sinkpads, pad); + element->numsinkpads--; + break; + default: + g_critical ("Removing pad without direction???"); + break; + } + element->pads = g_list_remove (element->pads, pad); + element->numpads--; + element->pads_cookie++; + GST_OBJECT_UNLOCK (element); + + /* emit the PAD_REMOVED signal before unparenting and losing the last ref. */ + g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad); + GST_TRACER_ELEMENT_REMOVE_PAD (element, pad); + gst_object_unparent (GST_OBJECT_CAST (pad)); + + return TRUE; + + /* ERRORS */ +not_our_pad: + { + /* locking order is element > pad */ + GST_OBJECT_UNLOCK (pad); + + GST_OBJECT_LOCK (element); + GST_OBJECT_LOCK (pad); + g_critical ("Padname %s:%s does not belong to element %s when removing", + GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element)); + GST_OBJECT_UNLOCK (pad); + GST_OBJECT_UNLOCK (element); + return FALSE; + } +} + +/** + * gst_element_no_more_pads: + * @element: a #GstElement + * + * Use this function to signal that the element does not expect any more pads + * to show up in the current pipeline. This function should be called whenever + * pads have been added by the element itself. Elements with #GST_PAD_SOMETIMES + * pad templates use this in combination with autopluggers to figure out that + * the element is done initializing its pads. + * + * This function emits the #GstElement::no-more-pads signal. + * + * MT safe. + */ +void +gst_element_no_more_pads (GstElement * element) +{ + g_return_if_fail (GST_IS_ELEMENT (element)); + + g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0); +} + +static gint +pad_compare_name (GstPad * pad1, const gchar * name) +{ + gint result; + + GST_OBJECT_LOCK (pad1); + result = strcmp (GST_PAD_NAME (pad1), name); + GST_OBJECT_UNLOCK (pad1); + + return result; +} + +/** + * gst_element_get_static_pad: + * @element: a #GstElement to find a static pad of. + * @name: the name of the static #GstPad to retrieve. + * + * Retrieves a pad from @element by name. This version only retrieves + * already-existing (i.e. 'static') pads. + * + * Returns: (transfer full) (nullable): the requested #GstPad if + * found, otherwise %NULL. unref after usage. + * + * MT safe. + */ +GstPad * +gst_element_get_static_pad (GstElement * element, const gchar * name) +{ + GList *find; + GstPad *result = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (name != NULL, NULL); + + GST_OBJECT_LOCK (element); + find = + g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name); + if (find) { + result = GST_PAD_CAST (find->data); + gst_object_ref (result); + } + + if (result == NULL) { + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", + name, GST_ELEMENT_NAME (element)); + } else { + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", + GST_ELEMENT_NAME (element), name); + } + GST_OBJECT_UNLOCK (element); + + return result; +} + +static gboolean +gst_element_is_valid_request_template_name (const gchar * templ_name, + const gchar * name) +{ + gchar *endptr; + const gchar *templ_name_ptr, *name_ptr; + gboolean next_specifier; + guint templ_postfix_len = 0, name_postfix_len = 0; + + g_return_val_if_fail (templ_name != NULL, FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + /* Is this the template name? */ + if (strcmp (templ_name, name) == 0) + return TRUE; + + /* otherwise check all the specifiers */ + do { + /* Because of sanity checks in gst_pad_template_new(), we know that %s + * and %d and %u, occurring at the template_name */ + templ_name_ptr = strchr (templ_name, '%'); + + /* check characters ahead of the specifier */ + if (!templ_name_ptr || strlen (name) <= templ_name_ptr - templ_name + || strncmp (templ_name, name, templ_name_ptr - templ_name) != 0) { + return FALSE; + } + + /* %s is not allowed for multiple specifiers, just a single specifier can be + * accepted in gst_pad_template_new() and can not be mixed with other + * specifier '%u' and '%d' */ + if (*(templ_name_ptr + 1) == 's' && g_strcmp0 (templ_name, name) == 0) { + return TRUE; + } + + name_ptr = name + (templ_name_ptr - templ_name); + + /* search next specifier, each of specifier should be separated by '_' */ + templ_name = strchr (templ_name_ptr, '_'); + name = strchr (name_ptr, '_'); + + /* don't match the number of specifiers */ + if ((templ_name && !name) || (!templ_name && name)) + return FALSE; + + if (templ_name && name) + next_specifier = TRUE; + else + next_specifier = FALSE; + + /* check characters followed by the specifier */ + if (*(templ_name_ptr + 2) != '\0' && *(templ_name_ptr + 2) != '_') { + if (next_specifier) { + templ_postfix_len = templ_name - (templ_name_ptr + 2); + name_postfix_len = name - name_ptr; + } else { + templ_postfix_len = strlen (templ_name_ptr + 2); + name_postfix_len = strlen (name_ptr); + } + + if (strncmp (templ_name_ptr + 2, + name_ptr + name_postfix_len - templ_postfix_len, + templ_postfix_len) != 0) { + return FALSE; + } + } + + /* verify the specifier */ + if (*(name_ptr) == '%') { + guint len; + + len = (next_specifier) ? name - name_ptr : strlen (name_ptr); + + if (strncmp (name_ptr, templ_name_ptr, len) != 0) + return FALSE; + + } else { + const gchar *specifier; + gchar *target = NULL; + + /* extract specifier when it has postfix characters */ + if (name_postfix_len > templ_postfix_len) { + target = g_strndup (name_ptr, name_postfix_len - templ_postfix_len); + } + specifier = target ? target : name_ptr; + + if (*(templ_name_ptr + 1) == 'd') { + gint64 tmp; + + /* it's an int */ + tmp = g_ascii_strtoll (specifier, &endptr, 10); + if (tmp < G_MININT || tmp > G_MAXINT || (*endptr != '\0' + && *endptr != '_')) + return FALSE; + } else if (*(templ_name_ptr + 1) == 'u') { + guint64 tmp; + + /* it's an int */ + tmp = g_ascii_strtoull (specifier, &endptr, 10); + if (tmp > G_MAXUINT || (*endptr != '\0' && *endptr != '_')) + return FALSE; + } + + g_free (target); + } + + /* otherwise we increment these from NULL to 1 */ + if (next_specifier) { + templ_name++; + name++; + } + } while (next_specifier); + + return TRUE; +} + +static GstPad * +_gst_element_request_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstPad *newpad = NULL; + GstElementClass *oclass; + + oclass = GST_ELEMENT_GET_CLASS (element); + +#ifndef G_DISABLE_CHECKS + /* Some sanity checking here */ + if (name) { + GstPad *pad; + + g_return_val_if_fail (gst_element_is_valid_request_template_name + (templ->name_template, name), NULL); + + pad = gst_element_get_static_pad (element, name); + if (pad) { + gst_object_unref (pad); + /* FIXME 2.0: Change this to g_return_val_if_fail() */ + g_critical ("Element %s already has a pad named %s, the behaviour of " + " gst_element_get_request_pad() for existing pads is undefined!", + GST_ELEMENT_NAME (element), name); + } + } +#endif + + if (oclass->request_new_pad) + newpad = (oclass->request_new_pad) (element, templ, name, caps); + + if (newpad) + gst_object_ref (newpad); + + return newpad; +} + +/** + * gst_element_get_request_pad: + * @element: a #GstElement to find a request pad of. + * @name: the name of the request #GstPad to retrieve. + * + * Retrieves a pad from the element by name (e.g. "src_\%d"). This version only + * retrieves request pads. The pad should be released with + * gst_element_release_request_pad(). + * + * This method is slower than manually getting the pad template and calling + * gst_element_request_pad() if the pads should have a specific name (e.g. + * @name is "src_1" instead of "src_\%u"). + * + * Returns: (transfer full) (nullable): requested #GstPad if found, + * otherwise %NULL. Release after usage. + */ +GstPad * +gst_element_get_request_pad (GstElement * element, const gchar * name) +{ + GstPadTemplate *templ = NULL; + GstPad *pad; + const gchar *req_name = NULL; + gboolean templ_found = FALSE; + GList *list; + GstElementClass *class; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (name != NULL, NULL); + + class = GST_ELEMENT_GET_CLASS (element); + + templ = gst_element_class_get_request_pad_template (class, name); + if (templ) { + req_name = strstr (name, "%") ? NULL : name; + templ_found = TRUE; + } else { + /* there is no % in the name, try to find a matching template */ + list = class->padtemplates; + while (!templ_found && list) { + templ = (GstPadTemplate *) list->data; + if (templ->presence == GST_PAD_REQUEST) { + GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, + templ->name_template); + if (gst_element_is_valid_request_template_name (templ->name_template, + name)) { + templ_found = TRUE; + req_name = name; + break; + } + } + list = list->next; + } + } + + if (!templ_found) + return NULL; + + pad = _gst_element_request_pad (element, templ, req_name, NULL); + + return pad; +} + +/** + * gst_element_request_pad: (virtual request_new_pad) + * @element: a #GstElement to find a request pad of. + * @templ: a #GstPadTemplate of which we want a pad of. + * @name: (transfer none) (allow-none): the name of the request #GstPad + * to retrieve. Can be %NULL. + * @caps: (transfer none) (allow-none): the caps of the pad we want to + * request. Can be %NULL. + * + * Retrieves a request pad from the element according to the provided template. + * Pad templates can be looked up using + * gst_element_factory_get_static_pad_templates(). + * + * The pad should be released with gst_element_release_request_pad(). + * + * Returns: (transfer full) (nullable): requested #GstPad if found, + * otherwise %NULL. Release after usage. + */ +GstPad * +gst_element_request_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (templ != NULL, NULL); + g_return_val_if_fail (templ->presence == GST_PAD_REQUEST, NULL); + + return _gst_element_request_pad (element, templ, name, caps); +} + +static GstIterator * +gst_element_iterate_pad_list (GstElement * element, GList ** padlist) +{ + GstIterator *result; + + GST_OBJECT_LOCK (element); + result = gst_iterator_new_list (GST_TYPE_PAD, + GST_OBJECT_GET_LOCK (element), + &element->pads_cookie, padlist, (GObject *) element, NULL); + GST_OBJECT_UNLOCK (element); + + return result; +} + +/** + * gst_element_iterate_pads: + * @element: a #GstElement to iterate pads of. + * + * Retrieves an iterator of @element's pads. The iterator should + * be freed after usage. Also more specialized iterators exists such as + * gst_element_iterate_src_pads() or gst_element_iterate_sink_pads(). + * + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. + * + * MT safe. + */ +GstIterator * +gst_element_iterate_pads (GstElement * element) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + return gst_element_iterate_pad_list (element, &element->pads); +} + +/** + * gst_element_iterate_src_pads: + * @element: a #GstElement. + * + * Retrieves an iterator of @element's source pads. + * + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. + * + * MT safe. + */ +GstIterator * +gst_element_iterate_src_pads (GstElement * element) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + return gst_element_iterate_pad_list (element, &element->srcpads); +} + +/** + * gst_element_iterate_sink_pads: + * @element: a #GstElement. + * + * Retrieves an iterator of @element's sink pads. + * + * The order of pads returned by the iterator will be the order in which + * the pads were added to the element. + * + * Returns: (transfer full): the #GstIterator of #GstPad. + * + * MT safe. + */ +GstIterator * +gst_element_iterate_sink_pads (GstElement * element) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + return gst_element_iterate_pad_list (element, &element->sinkpads); +} + +static gboolean +gst_element_do_foreach_pad (GstElement * element, + GstElementForeachPadFunc func, gpointer user_data, + GList ** p_pads, guint16 * p_npads) +{ + gboolean ret = TRUE; + GstPad **pads; + guint n_pads, i; + GList *l; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + GST_OBJECT_LOCK (element); + n_pads = *p_npads; + pads = g_newa (GstPad *, n_pads + 1); + for (l = *p_pads, i = 0; l != NULL; l = l->next) { + g_assert (i < n_pads); + pads[i++] = gst_object_ref (l->data); + } + GST_OBJECT_UNLOCK (element); + + if (n_pads == 0) + return FALSE; + + for (i = 0; i < n_pads; ++i) { + ret = func (element, pads[i], user_data); + if (!ret) + break; + } + + for (i = 0; i < n_pads; ++i) + gst_object_unref (pads[i]); + + return ret; +} + +/** + * gst_element_foreach_sink_pad: + * @element: a #GstElement to iterate sink pads of + * @func: (scope call): function to call for each sink pad + * @user_data: (closure): user data passed to @func + * + * Call @func with @user_data for each of @element's sink pads. @func will be + * called exactly once for each sink pad that exists at the time of this call, + * unless one of the calls to @func returns %FALSE in which case we will stop + * iterating pads and return early. If new sink pads are added or sink pads + * are removed while the sink pads are being iterated, this will not be taken + * into account until next time this function is used. + * + * Returns: %FALSE if @element had no sink pads or if one of the calls to @func + * returned %FALSE. + * + * Since: 1.14 + */ +gboolean +gst_element_foreach_sink_pad (GstElement * element, + GstElementForeachPadFunc func, gpointer user_data) +{ + return gst_element_do_foreach_pad (element, func, user_data, + &element->sinkpads, &element->numsinkpads); +} + +/** + * gst_element_foreach_src_pad: + * @element: a #GstElement to iterate source pads of + * @func: (scope call): function to call for each source pad + * @user_data: (closure): user data passed to @func + * + * Call @func with @user_data for each of @element's source pads. @func will be + * called exactly once for each source pad that exists at the time of this call, + * unless one of the calls to @func returns %FALSE in which case we will stop + * iterating pads and return early. If new source pads are added or source pads + * are removed while the source pads are being iterated, this will not be taken + * into account until next time this function is used. + * + * Returns: %FALSE if @element had no source pads or if one of the calls + * to @func returned %FALSE. + * + * Since: 1.14 + */ +gboolean +gst_element_foreach_src_pad (GstElement * element, + GstElementForeachPadFunc func, gpointer user_data) +{ + return gst_element_do_foreach_pad (element, func, user_data, + &element->srcpads, &element->numsrcpads); +} + +/** + * gst_element_foreach_pad: + * @element: a #GstElement to iterate pads of + * @func: (scope call): function to call for each pad + * @user_data: (closure): user data passed to @func + * + * Call @func with @user_data for each of @element's pads. @func will be called + * exactly once for each pad that exists at the time of this call, unless + * one of the calls to @func returns %FALSE in which case we will stop + * iterating pads and return early. If new pads are added or pads are removed + * while pads are being iterated, this will not be taken into account until + * next time this function is used. + * + * Returns: %FALSE if @element had no pads or if one of the calls to @func + * returned %FALSE. + * + * Since: 1.14 + */ +gboolean +gst_element_foreach_pad (GstElement * element, GstElementForeachPadFunc func, + gpointer user_data) +{ + return gst_element_do_foreach_pad (element, func, user_data, + &element->pads, &element->numpads); +} + +/** + * gst_element_class_add_pad_template: + * @klass: the #GstElementClass to add the pad template to. + * @templ: (transfer floating): a #GstPadTemplate to add to the element class. + * + * Adds a padtemplate to an element class. This is mainly used in the _class_init + * functions of classes. If a pad template with the same name as an already + * existing one is added the old one is replaced by the new one. + * + * @templ's reference count will be incremented, and any floating + * reference will be removed (see gst_object_ref_sink()) + * + */ +void +gst_element_class_add_pad_template (GstElementClass * klass, + GstPadTemplate * templ) +{ + GList *template_list = klass->padtemplates; + + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (GST_IS_PAD_TEMPLATE (templ)); + + /* If we already have a pad template with the same name replace the + * old one. */ + while (template_list) { + GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data; + + /* Found pad with the same name, replace and return */ + if (strcmp (templ->name_template, padtempl->name_template) == 0) { + gst_object_ref_sink (padtempl); + gst_object_unref (padtempl); + template_list->data = templ; + return; + } + template_list = g_list_next (template_list); + } + + /* Take ownership of the floating ref */ + gst_object_ref_sink (templ); + + klass->padtemplates = g_list_append (klass->padtemplates, templ); + klass->numpadtemplates++; +} + +/** + * gst_element_class_add_static_pad_template: + * @klass: the #GstElementClass to add the pad template to. + * @static_templ: #GstStaticPadTemplate to add as pad template to the element class. + * + * Adds a pad template to an element class based on the static pad template + * @templ. This is mainly used in the _class_init functions of element + * implementations. If a pad template with the same name already exists, + * the old one is replaced by the new one. + * + * Since: 1.8 + */ +void +gst_element_class_add_static_pad_template (GstElementClass * klass, + GstStaticPadTemplate * static_templ) +{ + gst_element_class_add_pad_template (klass, + gst_static_pad_template_get (static_templ)); +} + +/** + * gst_element_class_add_static_pad_template_with_gtype: + * @klass: the #GstElementClass to add the pad template to. + * @static_templ: #GstStaticPadTemplate to add as pad template to the element class. + * @pad_type: The #GType of the pad to create + * + * Adds a pad template to an element class based on the static pad template + * @templ. This is mainly used in the _class_init functions of element + * implementations. If a pad template with the same name already exists, + * the old one is replaced by the new one. + * + * Since: 1.14 + */ +void +gst_element_class_add_static_pad_template_with_gtype (GstElementClass * klass, + GstStaticPadTemplate * static_templ, GType pad_type) +{ + gst_element_class_add_pad_template (klass, + gst_pad_template_new_from_static_pad_template_with_gtype (static_templ, + pad_type)); +} + +/** + * gst_element_class_add_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + */ +void +gst_element_class_add_metadata (GstElementClass * klass, + const gchar * key, const gchar * value) +{ + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + gst_structure_set ((GstStructure *) klass->metadata, + key, G_TYPE_STRING, value, NULL); +} + +/** + * gst_element_class_add_static_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + * + * Same as gst_element_class_add_metadata(), but @value must be a static string + * or an inlined string, as it will not be copied. (GStreamer plugins will + * be made resident once loaded, so this function can be used even from + * dynamically loaded plugins.) + */ +void +gst_element_class_add_static_metadata (GstElementClass * klass, + const gchar * key, const gchar * value) +{ + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_value_init (&val, G_TYPE_STRING); + g_value_set_static_string (&val, value); + gst_structure_take_value ((GstStructure *) klass->metadata, key, &val); +} + +/** + * gst_element_class_set_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the element. E.g. "File Sink" + * @classification: String describing the type of element, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the element. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstElementClass. + * > This function is for use in _class_init functions only. + */ +void +gst_element_class_set_metadata (GstElementClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + gst_structure_id_set ((GstStructure *) klass->metadata, + GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname, + GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification, + GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description, + GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL); +} + +/** + * gst_element_class_set_static_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the element. E.g. "File Sink" + * @classification: String describing the type of element, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the element. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstElementClass. + * + * > This function is for use in _class_init functions only. + * + * Same as gst_element_class_set_metadata(), but @longname, @classification, + * @description, and @author must be static strings or inlined strings, as + * they will not be copied. (GStreamer plugins will be made resident once + * loaded, so this function can be used even from dynamically loaded plugins.) + */ +void +gst_element_class_set_static_metadata (GstElementClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + GstStructure *s = (GstStructure *) klass->metadata; + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + g_value_init (&val, G_TYPE_STRING); + + g_value_set_static_string (&val, longname); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val); + + g_value_set_static_string (&val, classification); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val); + + g_value_set_static_string (&val, description); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION), + &val); + + g_value_set_static_string (&val, author); + gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val); +} + +/** + * gst_element_class_get_metadata: + * @klass: class to get metadata for + * @key: the key to get + * + * Get metadata with @key in @klass. + * + * Returns: the metadata for @key. + */ +const gchar * +gst_element_class_get_metadata (GstElementClass * klass, const gchar * key) +{ + g_return_val_if_fail (GST_IS_ELEMENT_CLASS (klass), NULL); + g_return_val_if_fail (key != NULL, NULL); + + return gst_structure_get_string ((GstStructure *) klass->metadata, key); +} + +/** + * gst_element_get_metadata: + * @element: class to get metadata for + * @key: the key to get + * + * Get metadata with @key in @klass. + * + * Returns: the metadata for @key. + * + * Since: 1.14 + */ +const gchar * +gst_element_get_metadata (GstElement * element, const gchar * key) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (key != NULL, NULL); + + return gst_element_class_get_metadata (GST_ELEMENT_GET_CLASS (element), key); +} + +/** + * gst_element_class_get_pad_template_list: + * @element_class: a #GstElementClass to get pad templates of. + * + * Retrieves a list of the pad templates associated with @element_class. The + * list must not be modified by the calling code. + * > If you use this function in the #GInstanceInitFunc of an object class + * > that has subclasses, make sure to pass the g_class parameter of the + * > #GInstanceInitFunc here. + * + * Returns: (transfer none) (element-type Gst.PadTemplate): the #GList of + * pad templates. + */ +GList * +gst_element_class_get_pad_template_list (GstElementClass * element_class) +{ + g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL); + + return element_class->padtemplates; +} + +/** + * gst_element_get_pad_template_list: + * @element: a #GstElement to get pad templates of. + * + * Retrieves a list of the pad templates associated with @element. The + * list must not be modified by the calling code. + * + * Returns: (transfer none) (element-type Gst.PadTemplate): the #GList of + * pad templates. + * + * Since: 1.14 + */ +GList * +gst_element_get_pad_template_list (GstElement * element) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + return + gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS (element)); +} + +/** + * gst_element_class_get_pad_template: + * @element_class: a #GstElementClass to get the pad template of. + * @name: the name of the #GstPadTemplate to get. + * + * Retrieves a padtemplate from @element_class with the given name. + * > If you use this function in the #GInstanceInitFunc of an object class + * > that has subclasses, make sure to pass the g_class parameter of the + * > #GInstanceInitFunc here. + * + * Returns: (transfer none) (nullable): the #GstPadTemplate with the + * given name, or %NULL if none was found. No unreferencing is + * necessary. + */ +GstPadTemplate * +gst_element_class_get_pad_template (GstElementClass * + element_class, const gchar * name) +{ + GList *padlist; + + g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL); + g_return_val_if_fail (name != NULL, NULL); + + padlist = element_class->padtemplates; + + while (padlist) { + GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data; + + if (strcmp (padtempl->name_template, name) == 0) + return padtempl; + + padlist = g_list_next (padlist); + } + + return NULL; +} + +/** + * gst_element_get_pad_template: + * @element: a #GstElement to get the pad template of. + * @name: the name of the #GstPadTemplate to get. + * + * Retrieves a padtemplate from @element with the given name. + * + * Returns: (transfer none) (nullable): the #GstPadTemplate with the + * given name, or %NULL if none was found. No unreferencing is + * necessary. + * + * Since: 1.14 + */ +GstPadTemplate * +gst_element_get_pad_template (GstElement * element, const gchar * name) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (name != NULL, NULL); + + return gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element), + name); +} + +static GstPadTemplate * +gst_element_class_get_request_pad_template (GstElementClass * + element_class, const gchar * name) +{ + GstPadTemplate *tmpl; + + tmpl = gst_element_class_get_pad_template (element_class, name); + if (tmpl != NULL && tmpl->presence == GST_PAD_REQUEST) + return tmpl; + + return NULL; +} + +/* get a random pad on element of the given direction. + * The pad is random in a sense that it is the first pad that is (optionaly) linked. + */ +static GstPad * +gst_element_get_random_pad (GstElement * element, + gboolean need_linked, GstPadDirection dir) +{ + GstPad *result = NULL; + GList *pads; + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad"); + + switch (dir) { + case GST_PAD_SRC: + GST_OBJECT_LOCK (element); + pads = element->srcpads; + break; + case GST_PAD_SINK: + GST_OBJECT_LOCK (element); + pads = element->sinkpads; + break; + default: + goto wrong_direction; + } + for (; pads; pads = g_list_next (pads)) { + GstPad *pad = GST_PAD_CAST (pads->data); + + GST_OBJECT_LOCK (pad); + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + if (need_linked && !GST_PAD_IS_LINKED (pad)) { + /* if we require a linked pad, and it is not linked, continue the + * search */ + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + continue; + } else { + /* found a pad, stop search */ + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "found pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + result = pad; + break; + } + } + if (result) + gst_object_ref (result); + + GST_OBJECT_UNLOCK (element); + + return result; + + /* ERROR handling */ +wrong_direction: + { + g_warning ("unknown pad direction %d", dir); + return NULL; + } +} + +static gboolean +gst_element_default_send_event (GstElement * element, GstEvent * event) +{ + gboolean result = FALSE; + GstPad *pad; + + pad = GST_EVENT_IS_DOWNSTREAM (event) ? + gst_element_get_random_pad (element, TRUE, GST_PAD_SINK) : + gst_element_get_random_pad (element, TRUE, GST_PAD_SRC); + + if (pad) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "pushing %s event to random %s pad %s:%s", + GST_EVENT_TYPE_NAME (event), + (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"), + GST_DEBUG_PAD_NAME (pad)); + + result = gst_pad_send_event (pad, event); + gst_object_unref (pad); + } else { + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s", + GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element)); + gst_event_unref (event); + } + return result; +} + +/** + * gst_element_send_event: + * @element: a #GstElement to send the event to. + * @event: (transfer full): the #GstEvent to send to the element. + * + * Sends an event to an element. If the element doesn't implement an + * event handler, the event will be pushed on a random linked sink pad for + * downstream events or a random linked source pad for upstream events. + * + * This function takes ownership of the provided event so you should + * gst_event_ref() it if you want to reuse the event after this call. + * + * MT safe. + * + * Returns: %TRUE if the event was handled. Events that trigger a preroll (such + * as flushing seeks and steps) will emit %GST_MESSAGE_ASYNC_DONE. + */ +gboolean +gst_element_send_event (GstElement * element, GstEvent * event) +{ + GstElementClass *oclass; + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_STATE_LOCK (element); + if (oclass->send_event) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s", + GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element)); + result = oclass->send_event (element, event); + } else { + gst_event_unref (event); + } + GST_STATE_UNLOCK (element); + + return result; +} + +/** + * gst_element_seek: + * @element: a #GstElement to send the event to. + * @rate: The new playback rate + * @format: The format of the seek values + * @flags: The optional seek flags. + * @start_type: The type and flags for the new start position + * @start: The value of the new start position + * @stop_type: The type and flags for the new stop position + * @stop: The value of the new stop position + * + * Sends a seek event to an element. See gst_event_new_seek() for the details of + * the parameters. The seek event is sent to the element using + * gst_element_send_event(). + * + * MT safe. + * + * Returns: %TRUE if the event was handled. Flushing seeks will trigger a + * preroll, which will emit %GST_MESSAGE_ASYNC_DONE. + */ +gboolean +gst_element_seek (GstElement * element, gdouble rate, GstFormat format, + GstSeekFlags flags, GstSeekType start_type, gint64 start, + GstSeekType stop_type, gint64 stop) +{ + GstEvent *event; + gboolean result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + event = + gst_event_new_seek (rate, format, flags, start_type, start, stop_type, + stop); + result = gst_element_send_event (element, event); + + return result; +} + +static gboolean +gst_element_default_query (GstElement * element, GstQuery * query) +{ + gboolean result = FALSE; + GstPad *pad; + + pad = gst_element_get_random_pad (element, FALSE, GST_PAD_SRC); + if (pad) { + result = gst_pad_query (pad, query); + + gst_object_unref (pad); + } else { + pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK); + if (pad) { + GstPad *peer = gst_pad_get_peer (pad); + + if (peer) { + result = gst_pad_query (peer, query); + + gst_object_unref (peer); + } + gst_object_unref (pad); + } + } + return result; +} + +/** + * gst_element_query: + * @element: a #GstElement to perform the query on. + * @query: (transfer none): the #GstQuery. + * + * Performs a query on the given element. + * + * For elements that don't implement a query handler, this function + * forwards the query to a random srcpad or to the peer of a + * random linked sinkpad of this element. + * + * Please note that some queries might need a running pipeline to work. + * + * Returns: %TRUE if the query could be performed. + * + * MT safe. + */ +gboolean +gst_element_query (GstElement * element, GstQuery * query) +{ + GstElementClass *klass; + gboolean res = FALSE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (query != NULL, FALSE); + + GST_TRACER_ELEMENT_QUERY_PRE (element, query); + + klass = GST_ELEMENT_GET_CLASS (element); + if (klass->query) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s", + GST_ELEMENT_NAME (element)); + res = klass->query (element, query); + } + + GST_TRACER_ELEMENT_QUERY_POST (element, query, res); + return res; +} + +static gboolean +gst_element_post_message_default (GstElement * element, GstMessage * message) +{ + GstBus *bus; + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (message != NULL, FALSE); + + GST_OBJECT_LOCK (element); + bus = element->bus; + + if (G_UNLIKELY (bus == NULL)) + goto no_bus; + + gst_object_ref (bus); + GST_OBJECT_UNLOCK (element); + + /* we release the element lock when posting the message so that any + * (synchronous) message handlers can operate on the element */ + result = gst_bus_post (bus, message); + gst_object_unref (bus); + + return result; + + /* ERRORS */ +no_bus: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, + "not posting message %p: no bus", message); + GST_OBJECT_UNLOCK (element); + gst_message_unref (message); + return FALSE; + } +} + +/** + * gst_element_post_message: + * @element: a #GstElement posting the message + * @message: (transfer full): a #GstMessage to post + * + * Post a message on the element's #GstBus. This function takes ownership of the + * message; if you want to access the message after this call, you should add an + * additional reference before calling. + * + * Returns: %TRUE if the message was successfully posted. The function returns + * %FALSE if the element did not have a bus. + * + * MT safe. + */ +gboolean +gst_element_post_message (GstElement * element, GstMessage * message) +{ + GstElementClass *klass; + gboolean res = FALSE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (message != NULL, FALSE); + + GST_TRACER_ELEMENT_POST_MESSAGE_PRE (element, message); + + klass = GST_ELEMENT_GET_CLASS (element); + if (klass->post_message) + res = klass->post_message (element, message); + else + gst_message_unref (message); + + GST_TRACER_ELEMENT_POST_MESSAGE_POST (element, res); + return res; +} + +/** + * _gst_element_error_printf: + * @format: (allow-none): the printf-like format to use, or %NULL + * + * This function is only used internally by the gst_element_error() macro. + * + * Returns: (transfer full) (nullable): a newly allocated string, or + * %NULL if the format was %NULL or "" + * + * MT safe. + */ +gchar * +_gst_element_error_printf (const gchar * format, ...) +{ + va_list args; + gchar *buffer; + int len; + + if (format == NULL) + return NULL; + if (format[0] == 0) + return NULL; + + va_start (args, format); + + len = __gst_vasprintf (&buffer, format, args); + + va_end (args); + + if (len < 0) + buffer = NULL; + + return buffer; +} + +/** + * gst_element_message_full_with_details: + * @element: a #GstElement to send message from + * @type: the #GstMessageType + * @domain: the GStreamer GError domain this message belongs to + * @code: the GError code belonging to the domain + * @text: (allow-none) (transfer full): an allocated text string to be used + * as a replacement for the default message connected to code, + * or %NULL + * @debug: (allow-none) (transfer full): an allocated debug message to be + * used as a replacement for the default debugging information, + * or %NULL + * @file: the source code file where the error was generated + * @function: the source code function where the error was generated + * @line: the source code line where the error was generated + * @structure:(transfer full): optional details structure + * + * Post an error, warning or info message on the bus from inside an element. + * + * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or + * #GST_MESSAGE_INFO. + * + * Since: 1.10 + */ +void gst_element_message_full_with_details + (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, + gchar * debug, const gchar * file, const gchar * function, gint line, + GstStructure * structure) +{ + GError *gerror = NULL; + gchar *name; + gchar *sent_text; + gchar *sent_debug; + gboolean has_debug = TRUE; + GstMessage *message = NULL; + + /* checks */ + GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, "start"); + g_return_if_fail (GST_IS_ELEMENT (element)); + g_return_if_fail ((type == GST_MESSAGE_ERROR) || + (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO)); + + /* check if we send the given text or the default error text */ + if ((text == NULL) || (text[0] == 0)) { + /* text could have come from g_strdup_printf (""); */ + g_free (text); + sent_text = gst_error_get_message (domain, code); + } else + sent_text = text; + + /* construct a sent_debug with extra information from source */ + if ((debug == NULL) || (debug[0] == 0)) { + /* debug could have come from g_strdup_printf (""); */ + has_debug = FALSE; + } + + name = gst_object_get_path_string (GST_OBJECT_CAST (element)); + if (has_debug) + sent_debug = g_strdup_printf ("%s(%d): %s (): %s:\n%s", + file, line, function, name, debug); + else + sent_debug = g_strdup_printf ("%s(%d): %s (): %s", + file, line, function, name); + g_free (name); + g_free (debug); + + /* create gerror and post message */ + GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s", + sent_text); + gerror = g_error_new_literal (domain, code, sent_text); + + switch (type) { + case GST_MESSAGE_ERROR: + message = + gst_message_new_error_with_details (GST_OBJECT_CAST (element), gerror, + sent_debug, structure); + break; + case GST_MESSAGE_WARNING: + message = + gst_message_new_warning_with_details (GST_OBJECT_CAST (element), + gerror, sent_debug, structure); + break; + case GST_MESSAGE_INFO: + message = + gst_message_new_info_with_details (GST_OBJECT_CAST (element), gerror, + sent_debug, structure); + break; + default: + g_assert_not_reached (); + break; + } + + gst_element_post_message (element, message); + + GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s", + (type == GST_MESSAGE_ERROR ? "error" : "warning"), sent_text); + + /* cleanup */ + g_error_free (gerror); + g_free (sent_debug); + g_free (sent_text); +} + +/** + * gst_element_message_full: + * @element: a #GstElement to send message from + * @type: the #GstMessageType + * @domain: the GStreamer GError domain this message belongs to + * @code: the GError code belonging to the domain + * @text: (allow-none) (transfer full): an allocated text string to be used + * as a replacement for the default message connected to code, + * or %NULL + * @debug: (allow-none) (transfer full): an allocated debug message to be + * used as a replacement for the default debugging information, + * or %NULL + * @file: the source code file where the error was generated + * @function: the source code function where the error was generated + * @line: the source code line where the error was generated + * + * Post an error, warning or info message on the bus from inside an element. + * + * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or + * #GST_MESSAGE_INFO. + * + * MT safe. + */ +void gst_element_message_full + (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, + gchar * debug, const gchar * file, const gchar * function, gint line) +{ + gst_element_message_full_with_details (element, type, domain, code, text, + debug, file, function, line, NULL); +} + +/** + * gst_element_is_locked_state: + * @element: a #GstElement. + * + * Checks if the state of an element is locked. + * If the state of an element is locked, state changes of the parent don't + * affect the element. + * This way you can leave currently unused elements inside bins. Just lock their + * state before changing the state from #GST_STATE_NULL. + * + * MT safe. + * + * Returns: %TRUE, if the element's state is locked. + */ +gboolean +gst_element_is_locked_state (GstElement * element) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + GST_OBJECT_LOCK (element); + result = GST_ELEMENT_IS_LOCKED_STATE (element); + GST_OBJECT_UNLOCK (element); + + return result; +} + +/** + * gst_element_set_locked_state: + * @element: a #GstElement + * @locked_state: %TRUE to lock the element's state + * + * Locks the state of an element, so state changes of the parent don't affect + * this element anymore. + * + * MT safe. + * + * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given + * or the elements state-locking needed no change. + */ +gboolean +gst_element_set_locked_state (GstElement * element, gboolean locked_state) +{ + gboolean old; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + GST_OBJECT_LOCK (element); + old = GST_ELEMENT_IS_LOCKED_STATE (element); + + if (G_UNLIKELY (old == locked_state)) + goto was_ok; + + if (locked_state) { + GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s", + GST_ELEMENT_NAME (element)); + GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE); + } else { + GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s", + GST_ELEMENT_NAME (element)); + GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE); + } + GST_OBJECT_UNLOCK (element); + + return TRUE; + +was_ok: + { + GST_CAT_DEBUG (GST_CAT_STATES, + "elements %s was already in locked state %d", + GST_ELEMENT_NAME (element), old); + GST_OBJECT_UNLOCK (element); + + return FALSE; + } +} + +/** + * gst_element_sync_state_with_parent: + * @element: a #GstElement. + * + * Tries to change the state of the element to the same as its parent. + * If this function returns %FALSE, the state of element is undefined. + * + * Returns: %TRUE, if the element's state could be synced to the parent's state. + * + * MT safe. + */ +gboolean +gst_element_sync_state_with_parent (GstElement * element) +{ + GstElement *parent; + GstState target; + GstStateChangeReturn ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + if ((parent = GST_ELEMENT_CAST (gst_element_get_parent (element)))) { + GstState parent_current, parent_pending; + + GST_OBJECT_LOCK (parent); + parent_current = GST_STATE (parent); + parent_pending = GST_STATE_PENDING (parent); + GST_OBJECT_UNLOCK (parent); + + /* set to pending if there is one, else we set it to the current state of + * the parent */ + if (parent_pending != GST_STATE_VOID_PENDING) + target = parent_pending; + else + target = parent_current; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "syncing state (%s) to parent %s %s (%s, %s)", + gst_element_state_get_name (GST_STATE (element)), + GST_ELEMENT_NAME (parent), gst_element_state_get_name (target), + gst_element_state_get_name (parent_current), + gst_element_state_get_name (parent_pending)); + + ret = gst_element_set_state (element, target); + if (ret == GST_STATE_CHANGE_FAILURE) + goto failed; + + gst_object_unref (parent); + + return TRUE; + } else { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "element has no parent"); + } + return FALSE; + + /* ERROR */ +failed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "syncing state failed (%s)", + gst_element_state_change_return_get_name (ret)); + gst_object_unref (parent); + return FALSE; + } +} + +/* MT safe */ +static GstStateChangeReturn +gst_element_get_state_func (GstElement * element, + GstState * state, GstState * pending, GstClockTime timeout) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE; + GstState old_pending; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "getting state, timeout %" + GST_TIME_FORMAT, GST_TIME_ARGS (timeout)); + + GST_OBJECT_LOCK (element); + ret = GST_STATE_RETURN (element); + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "RETURN is %s", + gst_element_state_change_return_get_name (ret)); + + /* we got an error, report immediately */ + if (ret == GST_STATE_CHANGE_FAILURE) + goto done; + + /* we got no_preroll, report immediately */ + if (ret == GST_STATE_CHANGE_NO_PREROLL) + goto done; + + /* no need to wait async if we are not async */ + if (ret != GST_STATE_CHANGE_ASYNC) + goto done; + + old_pending = GST_STATE_PENDING (element); + if (old_pending != GST_STATE_VOID_PENDING) { + gboolean signaled; + guint32 cookie; + + /* get cookie to detect state changes during waiting */ + cookie = element->state_cookie; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "waiting for element to commit state"); + + /* we have a pending state change, wait for it to complete */ + if (timeout != GST_CLOCK_TIME_NONE) { + gint64 end_time; + /* make timeout absolute */ + end_time = g_get_monotonic_time () + (timeout / 1000); + signaled = GST_STATE_WAIT_UNTIL (element, end_time); + } else { + GST_STATE_WAIT (element); + signaled = TRUE; + } + + if (!signaled) { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out"); + /* timeout triggered */ + ret = GST_STATE_CHANGE_ASYNC; + } else { + if (cookie != element->state_cookie) + goto interrupted; + + /* could be success or failure */ + if (old_pending == GST_STATE (element)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got success"); + ret = GST_STATE_CHANGE_SUCCESS; + } else { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got failure"); + ret = GST_STATE_CHANGE_FAILURE; + } + } + /* if nothing is pending anymore we can return SUCCESS */ + if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) { + GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "nothing pending"); + ret = GST_STATE_CHANGE_SUCCESS; + } + } + +done: + if (state) + *state = GST_STATE (element); + if (pending) + *pending = GST_STATE_PENDING (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "state current: %s, pending: %s, result: %s", + gst_element_state_get_name (GST_STATE (element)), + gst_element_state_get_name (GST_STATE_PENDING (element)), + gst_element_state_change_return_get_name (ret)); + GST_OBJECT_UNLOCK (element); + + return ret; + +interrupted: + { + if (state) + *state = GST_STATE_VOID_PENDING; + if (pending) + *pending = GST_STATE_VOID_PENDING; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "interruped"); + + GST_OBJECT_UNLOCK (element); + + return GST_STATE_CHANGE_FAILURE; + } +} + +/** + * gst_element_get_state: + * @element: a #GstElement to get the state of. + * @state: (out) (allow-none): a pointer to #GstState to hold the state. + * Can be %NULL. + * @pending: (out) (allow-none): a pointer to #GstState to hold the pending + * state. Can be %NULL. + * @timeout: a #GstClockTime to specify the timeout for an async + * state change or %GST_CLOCK_TIME_NONE for infinite timeout. + * + * Gets the state of the element. + * + * For elements that performed an ASYNC state change, as reported by + * gst_element_set_state(), this function will block up to the + * specified timeout value for the state change to complete. + * If the element completes the state change or goes into + * an error, this function returns immediately with a return value of + * %GST_STATE_CHANGE_SUCCESS or %GST_STATE_CHANGE_FAILURE respectively. + * + * For elements that did not return %GST_STATE_CHANGE_ASYNC, this function + * returns the current and pending state immediately. + * + * This function returns %GST_STATE_CHANGE_NO_PREROLL if the element + * successfully changed its state but is not able to provide data yet. + * This mostly happens for live sources that only produce data in + * %GST_STATE_PLAYING. While the state change return is equivalent to + * %GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that + * some sink elements might not be able to complete their state change because + * an element is not producing data to complete the preroll. When setting the + * element to playing, the preroll will complete and playback will start. + * + * Returns: %GST_STATE_CHANGE_SUCCESS if the element has no more pending state + * and the last state change succeeded, %GST_STATE_CHANGE_ASYNC if the + * element is still performing a state change or + * %GST_STATE_CHANGE_FAILURE if the last state change failed. + * + * MT safe. + */ +GstStateChangeReturn +gst_element_get_state (GstElement * element, + GstState * state, GstState * pending, GstClockTime timeout) +{ + GstElementClass *oclass; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->get_state) + result = (oclass->get_state) (element, state, pending, timeout); + + return result; +} + +/** + * gst_element_abort_state: + * @element: a #GstElement to abort the state of. + * + * Abort the state change of the element. This function is used + * by elements that do asynchronous state changes and find out + * something is wrong. + * + * This function should be called with the STATE_LOCK held. + * + * MT safe. + */ +void +gst_element_abort_state (GstElement * element) +{ + GstState pending; + +#ifndef GST_DISABLE_GST_DEBUG + GstState old_state; +#endif + + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_OBJECT_LOCK (element); + pending = GST_STATE_PENDING (element); + + if (pending == GST_STATE_VOID_PENDING || + GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE) + goto nothing_aborted; + +#ifndef GST_DISABLE_GST_DEBUG + old_state = GST_STATE (element); + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "aborting state from %s to %s", gst_element_state_get_name (old_state), + gst_element_state_get_name (pending)); +#endif + + /* flag error */ + GST_STATE_RETURN (element) = GST_STATE_CHANGE_FAILURE; + + GST_STATE_BROADCAST (element); + GST_OBJECT_UNLOCK (element); + + return; + +nothing_aborted: + { + GST_OBJECT_UNLOCK (element); + return; + } +} + +/* Not static because GstBin has manual state handling too */ +void +_priv_gst_element_state_changed (GstElement * element, GstState oldstate, + GstState newstate, GstState pending) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); + GstMessage *message; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "notifying about state-changed %s to %s (%s pending)", + gst_element_state_get_name (oldstate), + gst_element_state_get_name (newstate), + gst_element_state_get_name (pending)); + + if (klass->state_changed) + klass->state_changed (element, oldstate, newstate, pending); + + message = gst_message_new_state_changed (GST_OBJECT_CAST (element), + oldstate, newstate, pending); + gst_element_post_message (element, message); +} + +/** + * gst_element_continue_state: + * @element: a #GstElement to continue the state change of. + * @ret: The previous state return value + * + * Commit the state change of the element and proceed to the next + * pending state if any. This function is used + * by elements that do asynchronous state changes. + * The core will normally call this method automatically when an + * element returned %GST_STATE_CHANGE_SUCCESS from the state change function. + * + * If after calling this method the element still has not reached + * the pending state, the next state change is performed. + * + * This method is used internally and should normally not be called by plugins + * or applications. + * + * This function must be called with STATE_LOCK held. + * + * Returns: The result of the commit state change. + * + * MT safe. + */ +GstStateChangeReturn +gst_element_continue_state (GstElement * element, GstStateChangeReturn ret) +{ + GstStateChangeReturn old_ret; + GstState old_state, old_next; + GstState current, next, pending; + GstStateChange transition; + + GST_OBJECT_LOCK (element); + old_ret = GST_STATE_RETURN (element); + GST_STATE_RETURN (element) = ret; + pending = GST_STATE_PENDING (element); + + /* check if there is something to commit */ + if (pending == GST_STATE_VOID_PENDING) + goto nothing_pending; + + old_state = GST_STATE (element); + /* this is the state we should go to next */ + old_next = GST_STATE_NEXT (element); + /* update current state */ + current = GST_STATE (element) = old_next; + + /* see if we reached the final state */ + if (pending == current) + goto complete; + + next = GST_STATE_GET_NEXT (current, pending); + transition = (GstStateChange) GST_STATE_TRANSITION (current, next); + + GST_STATE_NEXT (element) = next; + /* mark busy */ + GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; + GST_OBJECT_UNLOCK (element); + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "committing state from %s to %s, pending %s, next %s", + gst_element_state_get_name (old_state), + gst_element_state_get_name (old_next), + gst_element_state_get_name (pending), gst_element_state_get_name (next)); + + _priv_gst_element_state_changed (element, old_state, old_next, pending); + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "continue state change %s to %s, final %s", + gst_element_state_get_name (current), + gst_element_state_get_name (next), gst_element_state_get_name (pending)); + + ret = gst_element_change_state (element, transition); + + return ret; + +nothing_pending: + { + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending"); + GST_OBJECT_UNLOCK (element); + return ret; + } +complete: + { + GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; + GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING; + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "completed state change to %s", gst_element_state_get_name (pending)); + GST_OBJECT_UNLOCK (element); + + /* don't post silly messages with the same state. This can happen + * when an element state is changed to what it already was. For bins + * this can be the result of a lost state, which we check with the + * previous return value. + * We do signal the cond though as a _get_state() might be blocking + * on it. */ + if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) + _priv_gst_element_state_changed (element, old_state, old_next, + GST_STATE_VOID_PENDING); + + GST_STATE_BROADCAST (element); + + return ret; + } +} + +/** + * gst_element_lost_state: + * @element: a #GstElement the state is lost of + * + * Brings the element to the lost state. The current state of the + * element is copied to the pending state so that any call to + * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC. + * + * An ASYNC_START message is posted. If the element was PLAYING, it will + * go to PAUSED. The element will be restored to its PLAYING state by + * the parent pipeline when it prerolls again. + * + * This is mostly used for elements that lost their preroll buffer + * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush, + * they will go to their pending state again when a new preroll buffer is + * queued. This function can only be called when the element is currently + * not in error or an async state change. + * + * This function is used internally and should normally not be called from + * plugins or applications. + */ +void +gst_element_lost_state (GstElement * element) +{ + GstState old_state, new_state; + GstMessage *message; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_OBJECT_LOCK (element); + if (GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE) + goto nothing_lost; + + if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING) + goto only_async_start; + + old_state = GST_STATE (element); + + /* when we were PLAYING, the new state is PAUSED. We will also not + * automatically go to PLAYING but let the parent bin(s) set us to PLAYING + * when we preroll. */ + if (old_state > GST_STATE_PAUSED) + new_state = GST_STATE_PAUSED; + else + new_state = old_state; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "lost state of %s to %s", gst_element_state_get_name (old_state), + gst_element_state_get_name (new_state)); + + GST_STATE (element) = new_state; + GST_STATE_NEXT (element) = new_state; + GST_STATE_PENDING (element) = new_state; + GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; + GST_OBJECT_UNLOCK (element); + + _priv_gst_element_state_changed (element, new_state, new_state, new_state); + + message = gst_message_new_async_start (GST_OBJECT_CAST (element)); + gst_element_post_message (element, message); + + return; + +nothing_lost: + { + GST_OBJECT_UNLOCK (element); + return; + } +only_async_start: + { + GST_OBJECT_UNLOCK (element); + + message = gst_message_new_async_start (GST_OBJECT_CAST (element)); + gst_element_post_message (element, message); + return; + } +} + +/** + * gst_element_set_state: + * @element: a #GstElement to change state of. + * @state: the element's new #GstState. + * + * Sets the state of the element. This function will try to set the + * requested state by going through all the intermediary states and calling + * the class's state change function for each. + * + * This function can return #GST_STATE_CHANGE_ASYNC, in which case the + * element will perform the remainder of the state change asynchronously in + * another thread. + * An application can use gst_element_get_state() to wait for the completion + * of the state change or it can wait for a %GST_MESSAGE_ASYNC_DONE or + * %GST_MESSAGE_STATE_CHANGED on the bus. + * + * State changes to %GST_STATE_READY or %GST_STATE_NULL never return + * #GST_STATE_CHANGE_ASYNC. + * + * Returns: Result of the state change using #GstStateChangeReturn. + * + * MT safe. + */ +GstStateChangeReturn +gst_element_set_state (GstElement * element, GstState state) +{ + GstElementClass *oclass; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->set_state) + result = (oclass->set_state) (element, state); + + return result; +} + +/* + * default set state function, calculates the next state based + * on current state and calls the change_state function + */ +static GstStateChangeReturn +gst_element_set_state_func (GstElement * element, GstState state) +{ + GstState current, next, old_pending; + GstStateChangeReturn ret; + GstStateChange transition; + GstStateChangeReturn old_ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "set_state to %s", + gst_element_state_get_name (state)); + + /* state lock is taken to protect the set_state() and get_state() + * procedures, it does not lock any variables. */ + GST_STATE_LOCK (element); + + /* now calculate how to get to the new state */ + GST_OBJECT_LOCK (element); + old_ret = GST_STATE_RETURN (element); + /* previous state change returned an error, remove all pending + * and next states */ + if (old_ret == GST_STATE_CHANGE_FAILURE) { + GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING; + GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; + GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS; + } + + current = GST_STATE (element); + next = GST_STATE_NEXT (element); + old_pending = GST_STATE_PENDING (element); + + /* this is the (new) state we should go to. TARGET is the last state we set on + * the element. */ + if (state != GST_STATE_TARGET (element)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "setting target state to %s", gst_element_state_get_name (state)); + GST_STATE_TARGET (element) = state; + /* increment state cookie so that we can track each state change. We only do + * this if this is actually a new state change. */ + element->state_cookie++; + } + GST_STATE_PENDING (element) = state; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "current %s, old_pending %s, next %s, old return %s", + gst_element_state_get_name (current), + gst_element_state_get_name (old_pending), + gst_element_state_get_name (next), + gst_element_state_change_return_get_name (old_ret)); + + /* if the element was busy doing a state change, we just update the + * target state, it'll get to it async then. */ + if (old_pending != GST_STATE_VOID_PENDING) { + /* upwards state change will happen ASYNC */ + if (old_pending <= state) + goto was_busy; + /* element is going to this state already */ + else if (next == state) + goto was_busy; + /* element was performing an ASYNC upward state change and + * we request to go downward again. Start from the next pending + * state then. */ + else if (next > state + && GST_STATE_RETURN (element) == GST_STATE_CHANGE_ASYNC) { + current = next; + } + } + next = GST_STATE_GET_NEXT (current, state); + /* now we store the next state */ + GST_STATE_NEXT (element) = next; + /* mark busy, we need to check that there is actually a state change + * to be done else we could accidentally override SUCCESS/NO_PREROLL and + * the default element change_state function has no way to know what the + * old value was... could consider this a FIXME...*/ + if (current != next) + GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; + + transition = (GstStateChange) GST_STATE_TRANSITION (current, next); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "%s: setting state from %s to %s", + (next != state ? "intermediate" : "final"), + gst_element_state_get_name (current), gst_element_state_get_name (next)); + + /* now signal any waiters, they will error since the cookie was incremented */ + GST_STATE_BROADCAST (element); + + GST_OBJECT_UNLOCK (element); + + ret = gst_element_change_state (element, transition); + + GST_STATE_UNLOCK (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "returned %s", + gst_element_state_change_return_get_name (ret)); + + return ret; + +was_busy: + { + GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "element was busy with async state change"); + GST_OBJECT_UNLOCK (element); + + GST_STATE_UNLOCK (element); + + return GST_STATE_CHANGE_ASYNC; + } +} + +/** + * gst_element_change_state: + * @element: a #GstElement + * @transition: the requested transition + * + * Perform @transition on @element. + * + * This function must be called with STATE_LOCK held and is mainly used + * internally. + * + * Returns: the #GstStateChangeReturn of the state transition. + */ +GstStateChangeReturn +gst_element_change_state (GstElement * element, GstStateChange transition) +{ + GstElementClass *oclass; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_TRACER_ELEMENT_CHANGE_STATE_PRE (element, transition); + + /* call the state change function so it can set the state */ + if (oclass->change_state) + ret = (oclass->change_state) (element, transition); + else + ret = GST_STATE_CHANGE_FAILURE; + + GST_TRACER_ELEMENT_CHANGE_STATE_POST (element, transition, ret); + + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "have FAILURE change_state return"); + /* state change failure */ + gst_element_abort_state (element); + break; + case GST_STATE_CHANGE_ASYNC: + { + GstState target; + + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "element will change state ASYNC"); + + target = GST_STATE_TARGET (element); + + if (target > GST_STATE_READY) + goto async; + + /* else we just continue the state change downwards */ + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "forcing commit state %s <= %s", + gst_element_state_get_name (target), + gst_element_state_get_name (GST_STATE_READY)); + + ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS); + break; + } + case GST_STATE_CHANGE_SUCCESS: + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "element changed state SUCCESS"); + /* we can commit the state now which will proceeed to + * the next state */ + ret = gst_element_continue_state (element, ret); + break; + case GST_STATE_CHANGE_NO_PREROLL: + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "element changed state NO_PREROLL"); + /* we can commit the state now which will proceeed to + * the next state */ + ret = gst_element_continue_state (element, ret); + break; + default: + goto invalid_return; + } + + GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit state change %d", ret); + + return ret; + +async: + GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit async state change %d", + ret); + + return ret; + + /* ERROR */ +invalid_return: + { + GST_OBJECT_LOCK (element); + /* somebody added a GST_STATE_ and forgot to do stuff here ! */ + g_critical ("%s: unknown return value %d from a state change function", + GST_ELEMENT_NAME (element), ret); + + /* we are in error now */ + ret = GST_STATE_CHANGE_FAILURE; + GST_STATE_RETURN (element) = ret; + GST_OBJECT_UNLOCK (element); + + return ret; + } +} + +/* gst_iterator_fold functions for pads_activate + * Stop the iterator if activating one pad failed, but only if that pad + * has not been removed from the element. */ +static gboolean +activate_pads (const GValue * vpad, GValue * ret, gboolean * active) +{ + GstPad *pad = g_value_get_object (vpad); + gboolean cont = TRUE; + + if (!gst_pad_set_active (pad, *active)) { + if (GST_PAD_PARENT (pad) != NULL) { + cont = FALSE; + g_value_set_boolean (ret, FALSE); + } + } + + return cont; +} + +/* returns false on error or early cutout of the fold, true if all + * pads in @iter were (de)activated successfully. */ +static gboolean +iterator_activate_fold_with_resync (GstIterator * iter, + GstIteratorFoldFunction func, gpointer user_data) +{ + GstIteratorResult ires; + GValue ret = { 0 }; + + /* no need to unset this later, it's just a boolean */ + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, TRUE); + + while (1) { + ires = gst_iterator_fold (iter, func, &ret, user_data); + switch (ires) { + case GST_ITERATOR_RESYNC: + /* need to reset the result again */ + g_value_set_boolean (&ret, TRUE); + gst_iterator_resync (iter); + break; + case GST_ITERATOR_DONE: + /* all pads iterated, return collected value */ + goto done; + default: + /* iterator returned _ERROR or premature end with _OK, + * mark an error and exit */ + g_value_set_boolean (&ret, FALSE); + goto done; + } + } +done: + /* return collected value */ + return g_value_get_boolean (&ret); +} + +/* is called with STATE_LOCK + * + * Pads are activated from source pads to sinkpads. + */ +static gboolean +gst_element_pads_activate (GstElement * element, gboolean active) +{ + GstIterator *iter; + gboolean res; + + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "%s pads", active ? "activate" : "deactivate"); + + iter = gst_element_iterate_src_pads (element); + res = + iterator_activate_fold_with_resync (iter, + (GstIteratorFoldFunction) activate_pads, &active); + gst_iterator_free (iter); + if (G_UNLIKELY (!res)) + goto src_failed; + + iter = gst_element_iterate_sink_pads (element); + res = + iterator_activate_fold_with_resync (iter, + (GstIteratorFoldFunction) activate_pads, &active); + gst_iterator_free (iter); + if (G_UNLIKELY (!res)) + goto sink_failed; + + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "pad %sactivation successful", active ? "" : "de"); + + return TRUE; + + /* ERRORS */ +src_failed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "pad %sactivation failed", active ? "" : "de"); + return FALSE; + } +sink_failed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "sink pads_activate failed"); + return FALSE; + } +} + +/* is called with STATE_LOCK */ +static GstStateChangeReturn +gst_element_change_state_func (GstElement * element, GstStateChange transition) +{ + GstState state, next; + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); + + state = (GstState) GST_STATE_TRANSITION_CURRENT (transition); + next = GST_STATE_TRANSITION_NEXT (transition); + + /* if the element already is in the given state, we just return success */ + if (next == GST_STATE_VOID_PENDING || state == next) + goto was_ok; + + GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, + "default handler tries setting state from %s to %s (%04x)", + gst_element_state_get_name (state), + gst_element_state_get_name (next), transition); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!gst_element_pads_activate (element, TRUE)) { + result = GST_STATE_CHANGE_FAILURE; + } + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL:{ + GList *l; + + /* deactivate pads in both cases, since they are activated on + ready->paused but the element might not have made it to paused */ + if (!gst_element_pads_activate (element, FALSE)) { + result = GST_STATE_CHANGE_FAILURE; + } + + /* Remove all non-persistent contexts */ + GST_OBJECT_LOCK (element); + for (l = element->contexts; l;) { + GstContext *context = l->data; + + if (!gst_context_is_persistent (context)) { + GList *next; + + gst_context_unref (context); + next = l->next; + element->contexts = g_list_delete_link (element->contexts, l); + l = next; + } else { + l = l->next; + } + } + GST_OBJECT_UNLOCK (element); + break; + } + default: + /* this will catch real but unhandled state changes; + * can only be caused by: + * - a new state was added + * - somehow the element was asked to jump across an intermediate state + */ + g_warning ("Unhandled state change from %s to %s", + gst_element_state_get_name (state), + gst_element_state_get_name (next)); + break; + } + return result; + +was_ok: + { + GST_OBJECT_LOCK (element); + result = GST_STATE_RETURN (element); + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, + "element is already in the %s state", + gst_element_state_get_name (state)); + GST_OBJECT_UNLOCK (element); + + return result; + } +} + +/** + * gst_element_get_factory: + * @element: a #GstElement to request the element factory of. + * + * Retrieves the factory that was used to create this element. + * + * Returns: (transfer none): the #GstElementFactory used for creating this + * element. no refcounting is needed. + */ +GstElementFactory * +gst_element_get_factory (GstElement * element) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + return GST_ELEMENT_GET_CLASS (element)->elementfactory; +} + +static void +gst_element_dispose (GObject * object) +{ + GstElement *element = GST_ELEMENT_CAST (object); + GstClock **clock_p; + GstBus **bus_p; + GstElementClass *oclass; + GList *walk; + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p dispose", element); + + if (GST_STATE (element) != GST_STATE_NULL) + goto not_null; + + /* start by releasing all request pads, this might also remove some dynamic + * pads */ + walk = element->pads; + while (walk) { + GstPad *pad = GST_PAD_CAST (walk->data); + + walk = walk->next; + + if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) && + GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) + == GST_PAD_REQUEST) { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing request pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + oclass->release_pad (element, pad); + + /* in case the release_pad function removed the next pad too */ + if (walk && g_list_position (element->pads, walk) == -1) + walk = element->pads; + } + } + /* remove the remaining pads */ + while (element->pads) { + GstPad *pad = GST_PAD_CAST (element->pads->data); + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + if (!gst_element_remove_pad (element, pad)) { + /* only happens when someone unparented our pad.. */ + g_critical ("failed to remove pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + break; + } + } + + GST_OBJECT_LOCK (element); + clock_p = &element->clock; + bus_p = &element->bus; + gst_object_replace ((GstObject **) clock_p, NULL); + gst_object_replace ((GstObject **) bus_p, NULL); + g_list_free_full (element->contexts, (GDestroyNotify) gst_context_unref); + GST_OBJECT_UNLOCK (element); + + GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p parent class dispose", + element); + + G_OBJECT_CLASS (parent_class)->dispose (object); + + return; + + /* ERRORS */ +not_null: + { + gboolean is_locked; + + is_locked = GST_ELEMENT_IS_LOCKED_STATE (element); + g_critical + ("\nTrying to dispose element %s, but it is in %s%s instead of the NULL" + " state.\n" + "You need to explicitly set elements to the NULL state before\n" + "dropping the final reference, to allow them to clean up.\n" + "This problem may also be caused by a refcounting bug in the\n" + "application or some element.\n", + GST_OBJECT_NAME (element), + gst_element_state_get_name (GST_STATE (element)), + is_locked ? " (locked)" : ""); + return; + } +} + +static void +gst_element_finalize (GObject * object) +{ + GstElement *element = GST_ELEMENT_CAST (object); + + GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p finalize", element); + + g_cond_clear (&element->state_cond); + g_rec_mutex_clear (&element->state_lock); + + GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p finalize parent", + element); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_element_set_bus_func (GstElement * element, GstBus * bus) +{ + GstBus **bus_p; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus); + + GST_OBJECT_LOCK (element); + bus_p = &GST_ELEMENT_BUS (element); + gst_object_replace ((GstObject **) bus_p, GST_OBJECT_CAST (bus)); + GST_OBJECT_UNLOCK (element); +} + +/** + * gst_element_set_bus: + * @element: a #GstElement to set the bus of. + * @bus: (transfer none) (allow-none): the #GstBus to set. + * + * Sets the bus of the element. Increases the refcount on the bus. + * For internal use only, unless you're testing elements. + * + * MT safe. + */ +void +gst_element_set_bus (GstElement * element, GstBus * bus) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->set_bus) + oclass->set_bus (element, bus); +} + +/** + * gst_element_get_bus: + * @element: a #GstElement to get the bus of. + * + * Returns the bus of the element. Note that only a #GstPipeline will provide a + * bus for the application. + * + * Returns: (transfer full) (nullable): the element's #GstBus. unref after + * usage. + * + * MT safe. + */ +GstBus * +gst_element_get_bus (GstElement * element) +{ + GstBus *result = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), result); + + GST_OBJECT_LOCK (element); + if ((result = GST_ELEMENT_BUS (element))) + gst_object_ref (result); + GST_OBJECT_UNLOCK (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_BUS, element, "got bus %" GST_PTR_FORMAT, + result); + + return result; +} + +static void +gst_element_set_context_default (GstElement * element, GstContext * context) +{ + const gchar *context_type; + GList *l; + + g_return_if_fail (GST_IS_CONTEXT (context)); + context_type = gst_context_get_context_type (context); + g_return_if_fail (context_type != NULL); + + GST_OBJECT_LOCK (element); + for (l = element->contexts; l; l = l->next) { + GstContext *tmp = l->data; + const gchar *tmp_type = gst_context_get_context_type (tmp); + + /* Always store newest context but never replace + * a persistent one by a non-persistent one */ + if (g_strcmp0 (context_type, tmp_type) == 0 && + (gst_context_is_persistent (context) || + !gst_context_is_persistent (tmp))) { + gst_context_replace ((GstContext **) & l->data, context); + break; + } + } + /* Not found? Add */ + if (l == NULL) { + element->contexts = + g_list_prepend (element->contexts, gst_context_ref (context)); + } + GST_OBJECT_UNLOCK (element); +} + +/** + * gst_element_set_context: + * @element: a #GstElement to set the context of. + * @context: (transfer none): the #GstContext to set. + * + * Sets the context of the element. Increases the refcount of the context. + * + * MT safe. + */ +void +gst_element_set_context (GstElement * element, GstContext * context) +{ + GstElementClass *oclass; + + g_return_if_fail (GST_IS_ELEMENT (element)); + g_return_if_fail (GST_IS_CONTEXT (context)); + + oclass = GST_ELEMENT_GET_CLASS (element); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT, element, + "set context %p %" GST_PTR_FORMAT, context, + gst_context_get_structure (context)); + + if (oclass->set_context) + oclass->set_context (element, context); +} + +/** + * gst_element_get_contexts: + * @element: a #GstElement to set the context of. + * + * Gets the contexts set on the element. + * + * MT safe. + * + * Returns: (element-type Gst.Context) (transfer full): List of #GstContext + * + * Since: 1.8 + */ +GList * +gst_element_get_contexts (GstElement * element) +{ + GList *ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + GST_OBJECT_LOCK (element); + ret = g_list_copy_deep (element->contexts, (GCopyFunc) gst_context_ref, NULL); + GST_OBJECT_UNLOCK (element); + + return ret; +} + +static gint +_match_context_type (GstContext * c1, const gchar * context_type) +{ + const gchar *c1_type; + + c1_type = gst_context_get_context_type (c1); + + return g_strcmp0 (c1_type, context_type); +} + +/** + * gst_element_get_context_unlocked: + * @element: a #GstElement to get the context of. + * @context_type: a name of a context to retrieve + * + * Gets the context with @context_type set on the element or NULL. + * + * Returns: (transfer full) (nullable): A #GstContext or NULL + * + * Since: 1.8 + */ +GstContext * +gst_element_get_context_unlocked (GstElement * element, + const gchar * context_type) +{ + GstContext *ret = NULL; + GList *node; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + node = + g_list_find_custom (element->contexts, context_type, + (GCompareFunc) _match_context_type); + if (node && node->data) + ret = gst_context_ref (node->data); + + return ret; +} + +/** + * gst_element_get_context: + * @element: a #GstElement to get the context of. + * @context_type: a name of a context to retrieve + * + * Gets the context with @context_type set on the element or NULL. + * + * MT safe. + * + * Returns: (transfer full): A #GstContext or NULL + * + * Since: 1.8 + */ +GstContext * +gst_element_get_context (GstElement * element, const gchar * context_type) +{ + GstContext *ret = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + GST_OBJECT_LOCK (element); + ret = gst_element_get_context_unlocked (element, context_type); + GST_OBJECT_UNLOCK (element); + + return ret; +} + +static void +gst_element_property_post_notify_msg (GstElement * element, GObject * obj, + GParamSpec * pspec, gboolean include_value) +{ + GValue val = G_VALUE_INIT; + GValue *v; + + GST_LOG_OBJECT (element, "property '%s' of object %" GST_PTR_FORMAT " has " + "changed, posting message with%s value", pspec->name, obj, + include_value ? "" : "out"); + + if (include_value && (pspec->flags & G_PARAM_READABLE) != 0) { + g_value_init (&val, pspec->value_type); + g_object_get_property (obj, pspec->name, &val); + v = &val; + } else { + v = NULL; + } + gst_element_post_message (element, + gst_message_new_property_notify (GST_OBJECT_CAST (obj), pspec->name, v)); +} + +static void +gst_element_property_deep_notify_cb (GstElement * element, GObject * prop_obj, + GParamSpec * pspec, gpointer user_data) +{ + gboolean include_value = GPOINTER_TO_INT (user_data); + + gst_element_property_post_notify_msg (element, prop_obj, pspec, + include_value); +} + +static void +gst_element_property_notify_cb (GObject * obj, GParamSpec * pspec, + gpointer user_data) +{ + gboolean include_value = GPOINTER_TO_INT (user_data); + + gst_element_property_post_notify_msg (GST_ELEMENT_CAST (obj), obj, pspec, + include_value); +} + +/** + * gst_element_add_property_notify_watch: + * @element: a #GstElement to watch for property changes + * @property_name: (allow-none): name of property to watch for changes, or + * NULL to watch all properties + * @include_value: whether to include the new property value in the message + * + * Returns: a watch id, which can be used in connection with + * gst_element_remove_property_notify_watch() to remove the watch again. + * + * Since: 1.10 + */ +gulong +gst_element_add_property_notify_watch (GstElement * element, + const gchar * property_name, gboolean include_value) +{ + const gchar *sep; + gchar *signal_name; + gulong id; + + g_return_val_if_fail (GST_IS_ELEMENT (element), 0); + + sep = (property_name != NULL) ? "::" : NULL; + signal_name = g_strconcat ("notify", sep, property_name, NULL); + id = g_signal_connect (element, signal_name, + G_CALLBACK (gst_element_property_notify_cb), + GINT_TO_POINTER (include_value)); + g_free (signal_name); + + return id; +} + +/** + * gst_element_add_property_deep_notify_watch: + * @element: a #GstElement to watch (recursively) for property changes + * @property_name: (allow-none): name of property to watch for changes, or + * NULL to watch all properties + * @include_value: whether to include the new property value in the message + * + * Returns: a watch id, which can be used in connection with + * gst_element_remove_property_notify_watch() to remove the watch again. + * + * Since: 1.10 + */ +gulong +gst_element_add_property_deep_notify_watch (GstElement * element, + const gchar * property_name, gboolean include_value) +{ + const gchar *sep; + gchar *signal_name; + gulong id; + + g_return_val_if_fail (GST_IS_ELEMENT (element), 0); + + sep = (property_name != NULL) ? "::" : NULL; + signal_name = g_strconcat ("deep-notify", sep, property_name, NULL); + id = g_signal_connect (element, signal_name, + G_CALLBACK (gst_element_property_deep_notify_cb), + GINT_TO_POINTER (include_value)); + g_free (signal_name); + + return id; +} + +/** + * gst_element_remove_property_notify_watch: + * @element: a #GstElement being watched for property changes + * @watch_id: watch id to remove + * + * Since: 1.10 + */ +void +gst_element_remove_property_notify_watch (GstElement * element, gulong watch_id) +{ + g_signal_handler_disconnect (element, watch_id); +} + +typedef struct +{ + GstElement *element; + GstElementCallAsyncFunc func; + gpointer user_data; + GDestroyNotify destroy_notify; +} GstElementCallAsyncData; + +static void +gst_element_call_async_func (gpointer data, gpointer user_data) +{ + GstElementCallAsyncData *async_data = data; + + async_data->func (async_data->element, async_data->user_data); + if (async_data->destroy_notify) + async_data->destroy_notify (async_data->user_data); + gst_object_unref (async_data->element); + g_free (async_data); +} + +/** + * gst_element_call_async: + * @element: a #GstElement + * @func: Function to call asynchronously from another thread + * @user_data: Data to pass to @func + * @destroy_notify: GDestroyNotify for @user_data + * + * Calls @func from another thread and passes @user_data to it. This is to be + * used for cases when a state change has to be performed from a streaming + * thread, directly via gst_element_set_state() or indirectly e.g. via SEEK + * events. + * + * Calling those functions directly from the streaming thread will cause + * deadlocks in many situations, as they might involve waiting for the + * streaming thread to shut down from this very streaming thread. + * + * MT safe. + * + * Since: 1.10 + */ +void +gst_element_call_async (GstElement * element, GstElementCallAsyncFunc func, + gpointer user_data, GDestroyNotify destroy_notify) +{ + GstElementCallAsyncData *async_data; + + g_return_if_fail (GST_IS_ELEMENT (element)); + + async_data = g_new0 (GstElementCallAsyncData, 1); + async_data->element = gst_object_ref (element); + async_data->func = func; + async_data->user_data = user_data; + async_data->destroy_notify = destroy_notify; + + g_thread_pool_push (gst_element_pool, async_data, NULL); +} + +void +_priv_gst_element_cleanup (void) +{ + if (gst_element_pool) { + g_thread_pool_free (gst_element_pool, FALSE, TRUE); + gst_element_setup_thread_pool (); + } +} + +GstStructure * +gst_make_element_message_details (const char *name, ...) +{ + GstStructure *structure; + va_list varargs; + + if (name == NULL) + return NULL; + + va_start (varargs, name); + structure = gst_structure_new_valist ("details", name, varargs); + va_end (varargs); + + return structure; +} diff --git a/gst/gstelement.h b/gst/gstelement.h new file mode 100644 index 0000000..e806883 --- /dev/null +++ b/gst/gstelement.h @@ -0,0 +1,1059 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2004 Wim Taymans + * + * gstelement.h: Header for GstElement + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_ELEMENT_H__ +#define __GST_ELEMENT_H__ + +#include + +G_BEGIN_DECLS + +/* gstelement.h and gstelementfactory.h include eachother */ +typedef struct _GstElement GstElement; +typedef struct _GstElementClass GstElementClass; + +/* gstmessage.h needs State */ +/** + * GstState: + * @GST_STATE_VOID_PENDING: no pending state. + * @GST_STATE_NULL : the NULL state or initial state of an element. + * @GST_STATE_READY : the element is ready to go to PAUSED. + * @GST_STATE_PAUSED : the element is PAUSED, it is ready to accept and + * process data. Sink elements however only accept one + * buffer and then block. + * @GST_STATE_PLAYING : the element is PLAYING, the #GstClock is running and + * the data is flowing. + * + * The possible states an element can be in. States can be changed using + * gst_element_set_state() and checked using gst_element_get_state(). + */ +typedef enum { + GST_STATE_VOID_PENDING = 0, + GST_STATE_NULL = 1, + GST_STATE_READY = 2, + GST_STATE_PAUSED = 3, + GST_STATE_PLAYING = 4 +} GstState; + +#define GST_TYPE_ELEMENT (gst_element_get_type ()) +#define GST_IS_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_ELEMENT)) +#define GST_IS_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_ELEMENT)) +#define GST_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ELEMENT, GstElementClass)) +#define GST_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ELEMENT, GstElement)) +#define GST_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_ELEMENT, GstElementClass)) +#define GST_ELEMENT_CAST(obj) ((GstElement*)(obj)) + +/** + * GstStateChangeReturn: + * @GST_STATE_CHANGE_FAILURE : the state change failed + * @GST_STATE_CHANGE_SUCCESS : the state change succeeded + * @GST_STATE_CHANGE_ASYNC : the state change will happen asynchronously + * @GST_STATE_CHANGE_NO_PREROLL: the state change succeeded but the element + * cannot produce data in %GST_STATE_PAUSED. + * This typically happens with live sources. + * + * The possible return values from a state change function such as + * gst_element_set_state(). Only @GST_STATE_CHANGE_FAILURE is a real failure. + */ +typedef enum { + GST_STATE_CHANGE_FAILURE = 0, + GST_STATE_CHANGE_SUCCESS = 1, + GST_STATE_CHANGE_ASYNC = 2, + GST_STATE_CHANGE_NO_PREROLL = 3 +} GstStateChangeReturn; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* NOTE: this probably should be done with an #ifdef to decide + * whether to safe-cast or to just do the non-checking cast. + */ + +/** + * GST_STATE: + * @elem: a #GstElement to return state for. + * + * This macro returns the current #GstState of the element. + */ +#define GST_STATE(elem) (GST_ELEMENT_CAST(elem)->current_state) + +/** + * GST_STATE_NEXT: + * @elem: a #GstElement to return the next state for. + * + * This macro returns the next #GstState of the element. + */ +#define GST_STATE_NEXT(elem) (GST_ELEMENT_CAST(elem)->next_state) + +/** + * GST_STATE_PENDING: + * @elem: a #GstElement to return the pending state for. + * + * This macro returns the currently pending #GstState of the element. + */ +#define GST_STATE_PENDING(elem) (GST_ELEMENT_CAST(elem)->pending_state) + +/** + * GST_STATE_TARGET: + * @elem: a #GstElement to return the target state for. + * + * This macro returns the target #GstState of the element. + */ +#define GST_STATE_TARGET(elem) (GST_ELEMENT_CAST(elem)->target_state) + +/** + * GST_STATE_RETURN: + * @elem: a #GstElement to return the last state result for. + * + * This macro returns the last #GstStateChangeReturn value. + */ +#define GST_STATE_RETURN(elem) (GST_ELEMENT_CAST(elem)->last_return) + +#define __GST_SIGN(val) ((val) < 0 ? -1 : ((val) > 0 ? 1 : 0)) +/** + * GST_STATE_GET_NEXT: + * @cur: A starting #GstState + * @pending: A target #GstState + * + * Given a current state @cur and a target state @pending, calculate the next (intermediate) + * #GstState. + */ +#define GST_STATE_GET_NEXT(cur,pending) ((GstState)((cur) + __GST_SIGN ((gint)(pending) - (gint)(cur)))) +/** + * GST_STATE_TRANSITION: + * @cur: A current state + * @next: A next state + * + * Given a current state @cur and a next state @next, calculate the associated + * #GstStateChange transition. + */ +#define GST_STATE_TRANSITION(cur,next) ((GstStateChange)(((cur)<<3)|(next))) +/** + * GST_STATE_TRANSITION_CURRENT: + * @trans: A #GstStateChange + * + * Given a state transition @trans, extract the current #GstState. + */ +#define GST_STATE_TRANSITION_CURRENT(trans) ((GstState)((trans)>>3)) +/** + * GST_STATE_TRANSITION_NEXT: + * @trans: A #GstStateChange + * + * Given a state transition @trans, extract the next #GstState. + */ +#define GST_STATE_TRANSITION_NEXT(trans) ((GstState)((trans)&0x7)) + +/** + * GstStateChange: + * @GST_STATE_CHANGE_NULL_TO_READY : state change from NULL to READY. + * * The element must check if the resources it needs are available. Device + * sinks and -sources typically try to probe the device to constrain their + * caps. + * * The element opens the device (in case feature need to be probed). + * @GST_STATE_CHANGE_READY_TO_PAUSED : state change from READY to PAUSED. + * * The element pads are activated in order to receive data in PAUSED. + * Streaming threads are started. + * * Some elements might need to return %GST_STATE_CHANGE_ASYNC and complete + * the state change when they have enough information. It is a requirement + * for sinks to return %GST_STATE_CHANGE_ASYNC and complete the state change + * when they receive the first buffer or %GST_EVENT_EOS (preroll). + * Sinks also block the dataflow when in PAUSED. + * * A pipeline resets the running_time to 0. + * * Live sources return %GST_STATE_CHANGE_NO_PREROLL and don't generate data. + * @GST_STATE_CHANGE_PAUSED_TO_PLAYING: state change from PAUSED to PLAYING. + * * Most elements ignore this state change. + * * The pipeline selects a #GstClock and distributes this to all the children + * before setting them to PLAYING. This means that it is only allowed to + * synchronize on the #GstClock in the PLAYING state. + * * The pipeline uses the #GstClock and the running_time to calculate the + * base_time. The base_time is distributed to all children when performing + * the state change. + * * Sink elements stop blocking on the preroll buffer or event and start + * rendering the data. + * * Sinks can post %GST_MESSAGE_EOS in the PLAYING state. It is not allowed + * to post %GST_MESSAGE_EOS when not in the PLAYING state. + * * While streaming in PAUSED or PLAYING elements can create and remove + * sometimes pads. + * * Live sources start generating data and return %GST_STATE_CHANGE_SUCCESS. + * @GST_STATE_CHANGE_PLAYING_TO_PAUSED: state change from PLAYING to PAUSED. + * * Most elements ignore this state change. + * * The pipeline calculates the running_time based on the last selected + * #GstClock and the base_time. It stores this information to continue + * playback when going back to the PLAYING state. + * * Sinks unblock any #GstClock wait calls. + * * When a sink does not have a pending buffer to play, it returns + * #GST_STATE_CHANGE_ASYNC from this state change and completes the state + * change when it receives a new buffer or an %GST_EVENT_EOS. + * * Any queued %GST_MESSAGE_EOS items are removed since they will be reposted + * when going back to the PLAYING state. The EOS messages are queued in + * #GstBin containers. + * * Live sources stop generating data and return %GST_STATE_CHANGE_NO_PREROLL. + * @GST_STATE_CHANGE_PAUSED_TO_READY : state change from PAUSED to READY. + * * Sinks unblock any waits in the preroll. + * * Elements unblock any waits on devices + * * Chain or get_range functions return %GST_FLOW_FLUSHING. + * * The element pads are deactivated so that streaming becomes impossible and + * all streaming threads are stopped. + * * The sink forgets all negotiated formats + * * Elements remove all sometimes pads + * @GST_STATE_CHANGE_READY_TO_NULL : state change from READY to NULL. + * * Elements close devices + * * Elements reset any internal state. + * @GST_STATE_CHANGE_NULL_TO_NULL : state change from NULL to NULL. (Since 1.14) + * @GST_STATE_CHANGE_READY_TO_READY : state change from READY to READY, + * This might happen when going to PAUSED asynchronously failed, in that case + * elements should make sure they are in a proper, coherent READY state. (Since 1.14) + * @GST_STATE_CHANGE_PAUSED_TO_PAUSED : state change from PAUSED to PAUSED. + * This might happen when elements were in PLAYING state and 'lost state', + * they should make sure to go back to real 'PAUSED' state (prerolling for example). (Since 1.14) + * @GST_STATE_CHANGE_PLAYING_TO_PLAYING : state change from PLAYING to PLAYING. (Since 1.14) + * + * These are the different state changes an element goes through. + * %GST_STATE_NULL ⇒ %GST_STATE_PLAYING is called an upwards state change + * and %GST_STATE_PLAYING ⇒ %GST_STATE_NULL a downwards state change. + */ +typedef enum /*< flags=0 >*/ +{ + GST_STATE_CHANGE_NULL_TO_READY = (GST_STATE_NULL<<3) | GST_STATE_READY, + GST_STATE_CHANGE_READY_TO_PAUSED = (GST_STATE_READY<<3) | GST_STATE_PAUSED, + GST_STATE_CHANGE_PAUSED_TO_PLAYING = (GST_STATE_PAUSED<<3) | GST_STATE_PLAYING, + GST_STATE_CHANGE_PLAYING_TO_PAUSED = (GST_STATE_PLAYING<<3) | GST_STATE_PAUSED, + GST_STATE_CHANGE_PAUSED_TO_READY = (GST_STATE_PAUSED<<3) | GST_STATE_READY, + GST_STATE_CHANGE_READY_TO_NULL = (GST_STATE_READY<<3) | GST_STATE_NULL, + GST_STATE_CHANGE_NULL_TO_NULL = (GST_STATE_NULL<<3) | GST_STATE_NULL, + GST_STATE_CHANGE_READY_TO_READY = (GST_STATE_READY<<3) | GST_STATE_READY, + GST_STATE_CHANGE_PAUSED_TO_PAUSED = (GST_STATE_PAUSED<<3) | GST_STATE_PAUSED, + GST_STATE_CHANGE_PLAYING_TO_PLAYING = (GST_STATE_PLAYING<<3) | GST_STATE_PLAYING +} GstStateChange; + +/** + * GstElementFlags: + * @GST_ELEMENT_FLAG_LOCKED_STATE: ignore state changes from parent + * @GST_ELEMENT_FLAG_SINK: the element is a sink + * @GST_ELEMENT_FLAG_SOURCE: the element is a source. + * @GST_ELEMENT_FLAG_PROVIDE_CLOCK: the element can provide a clock + * @GST_ELEMENT_FLAG_REQUIRE_CLOCK: the element requires a clock + * @GST_ELEMENT_FLAG_INDEXABLE: the element can use an index + * @GST_ELEMENT_FLAG_LAST: offset to define more flags + * + * The standard flags that an element may have. + */ +typedef enum +{ + GST_ELEMENT_FLAG_LOCKED_STATE = (GST_OBJECT_FLAG_LAST << 0), + GST_ELEMENT_FLAG_SINK = (GST_OBJECT_FLAG_LAST << 1), + GST_ELEMENT_FLAG_SOURCE = (GST_OBJECT_FLAG_LAST << 2), + GST_ELEMENT_FLAG_PROVIDE_CLOCK = (GST_OBJECT_FLAG_LAST << 3), + GST_ELEMENT_FLAG_REQUIRE_CLOCK = (GST_OBJECT_FLAG_LAST << 4), + GST_ELEMENT_FLAG_INDEXABLE = (GST_OBJECT_FLAG_LAST << 5), + /* padding */ + GST_ELEMENT_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 10) +} GstElementFlags; + +/** + * GST_ELEMENT_IS_LOCKED_STATE: + * @elem: A #GstElement to query + * + * Check if the element is in the locked state and therefore will ignore state + * changes from its parent object. + */ +#define GST_ELEMENT_IS_LOCKED_STATE(elem) (GST_OBJECT_FLAG_IS_SET(elem,GST_ELEMENT_FLAG_LOCKED_STATE)) + +/** + * GST_ELEMENT_NAME: + * @elem: A #GstElement to query + * + * Gets the name of this element. This is not thread-safe by default + * (i.e. you will have to make sure the object lock is taken yourself). + * If in doubt use gst_element_get_name() instead. + */ +#define GST_ELEMENT_NAME(elem) (GST_OBJECT_NAME(elem)) + +/** + * GST_ELEMENT_PARENT: + * @elem: A #GstElement to query + * + * Get the parent object of this element. This is not thread-safe by default + * (i.e. you will have to make sure the object lock is taken yourself). + * If in doubt use gst_object_get_parent() instead. + */ +#define GST_ELEMENT_PARENT(elem) (GST_ELEMENT_CAST(GST_OBJECT_PARENT(elem))) + +/** + * GST_ELEMENT_BUS: + * @elem: A #GstElement to query + * + * Get the message bus of this element. This is not thread-safe by default + * (i.e. you will have to make sure the object lock is taken yourself). + * If in doubt use gst_element_get_bus() instead. + */ +#define GST_ELEMENT_BUS(elem) (GST_ELEMENT_CAST(elem)->bus) + +/** + * GST_ELEMENT_CLOCK: + * @elem: A #GstElement to query + * + * Get the clock of this element.This is not thread-safe by default + * (i.e. you will have to make sure it is safe yourself). + * If in doubt use gst_element_get_clock() instead. + */ +#define GST_ELEMENT_CLOCK(elem) (GST_ELEMENT_CAST(elem)->clock) + +/** + * GST_ELEMENT_PADS: + * @elem: A #GstElement to query + * + * Get the pads of this elements. + */ +#define GST_ELEMENT_PADS(elem) (GST_ELEMENT_CAST(elem)->pads) + +/** + * GST_ELEMENT_START_TIME: + * @elem: a #GstElement to return the start time for. + * + * This macro returns the start_time of the @elem. The start_time is the + * running_time of the pipeline when the element went to PAUSED. + */ +#define GST_ELEMENT_START_TIME(elem) (GST_ELEMENT_CAST(elem)->start_time) + +GST_API +GstStructure *gst_make_element_message_details (const char *name, ...); + +#define GST_ELEMENT_MESSAGE_MAKE_DETAILS(args) gst_make_element_message_details args + +/** + * GST_ELEMENT_FLOW_ERROR: + * @el: the element that generates the error + * @flow_return: the GstFlowReturn leading to that ERROR message + * + * Utility function that elements can use in case they encountered a fatal + * data processing error due to wrong flow processing. + * + * Since: 1.10 + */ +#define GST_ELEMENT_FLOW_ERROR(el,flow_return) \ +G_STMT_START { \ + GST_ELEMENT_ERROR_WITH_DETAILS (el, STREAM, FAILED, \ + ("Internal data stream error."), \ + ("streaming stopped, reason %s (%d)", gst_flow_get_name (flow_return), flow_return), \ + ("flow-return", G_TYPE_INT, flow_return, NULL));\ +} G_STMT_END + +/** + * GST_ELEMENT_ERROR_WITH_DETAILS: + * @el: the element that generates the error + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * @args: optional name, type, value triplets, which will be stored + * in the associated GstStructure. NULL terminator required. + * Must be enclosed within parentheses. + * + * Utility function that elements can use in case they encountered a fatal + * data processing error. The pipeline will post an error message and the + * application will be requested to stop further media processing. + * + * Since: 1.10 + */ +#define GST_ELEMENT_ERROR_WITH_DETAILS(el,domain,code,text,debug,args) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_WARNING_OBJECT (el, "error: %s", __txt); \ + if (__dbg) \ + GST_WARNING_OBJECT (el, "error: %s", __dbg); \ + gst_element_message_full_with_details (GST_ELEMENT(el), \ + GST_MESSAGE_ERROR, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__, GST_ELEMENT_MESSAGE_MAKE_DETAILS(args)); \ +} G_STMT_END + +/** + * GST_ELEMENT_ERROR: + * @el: the element that generates the error + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * + * Utility function that elements can use in case they encountered a fatal + * data processing error. The pipeline will post an error message and the + * application will be requested to stop further media processing. + */ +#define GST_ELEMENT_ERROR(el,domain,code,text,debug) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_WARNING_OBJECT (el, "error: %s", __txt); \ + if (__dbg) \ + GST_WARNING_OBJECT (el, "error: %s", __dbg); \ + gst_element_message_full (GST_ELEMENT(el), \ + GST_MESSAGE_ERROR, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__); \ +} G_STMT_END + +/** + * GST_ELEMENT_WARNING_WITH_DETAILS: + * @el: the element that generates the warning + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * @args: optional name, type, value triplets, which will be stored + * in the associated GstStructure. NULL terminator required. + * Must be enclosed within parentheses. + * + * Utility function that elements can use in case they encountered a non-fatal + * data processing problem. The pipeline will post a warning message and the + * application will be informed. + * + * Since: 1.10 + */ +#define GST_ELEMENT_WARNING_WITH_DETAILS(el, domain, code, text, debug, args)\ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_WARNING_OBJECT (el, "warning: %s", __txt); \ + if (__dbg) \ + GST_WARNING_OBJECT (el, "warning: %s", __dbg); \ + gst_element_message_full_with_details (GST_ELEMENT(el), \ + GST_MESSAGE_WARNING, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__, GST_ELEMENT_MESSAGE_MAKE_DETAILS(args)); \ +} G_STMT_END + +/** + * GST_ELEMENT_WARNING: + * @el: the element that generates the warning + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * + * Utility function that elements can use in case they encountered a non-fatal + * data processing problem. The pipeline will post a warning message and the + * application will be informed. + */ +#define GST_ELEMENT_WARNING(el, domain, code, text, debug) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_WARNING_OBJECT (el, "warning: %s", __txt); \ + if (__dbg) \ + GST_WARNING_OBJECT (el, "warning: %s", __dbg); \ + gst_element_message_full (GST_ELEMENT(el), \ + GST_MESSAGE_WARNING, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__); \ +} G_STMT_END + +/** + * GST_ELEMENT_INFO_WITH_DETAILS: + * @el: the element that generates the information + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * @args: optional name, type, value triplets, which will be stored + * in the associated GstStructure. NULL terminator required. + * Must be enclosed within parentheses. + * + * Utility function that elements can use in case they want to inform + * the application of something noteworthy that is not an error. + * The pipeline will post a info message and the + * application will be informed. + * Optional name, type, value triplets may be supplied, and will be stored + * in the associated GstStructure. NULL terminator required. + * + * Since: 1.10 + */ +#define GST_ELEMENT_INFO_WITH_DETAILS(el, domain, code, text, debug, args) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_INFO_OBJECT (el, "info: %s", __txt); \ + if (__dbg) \ + GST_INFO_OBJECT (el, "info: %s", __dbg); \ + gst_element_message_full_with_details (GST_ELEMENT(el), \ + GST_MESSAGE_INFO, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__, GST_ELEMENT_MESSAGE_MAKE_DETAILS(args)); \ +} G_STMT_END + +/** + * GST_ELEMENT_INFO: + * @el: the element that generates the information + * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError) + * @code: error code defined for that domain (see #gstreamer-GstGError) + * @text: the message to display (format string and args enclosed in + parentheses) + * @debug: debugging information for the message (format string and args + enclosed in parentheses) + * + * Utility function that elements can use in case they want to inform + * the application of something noteworthy that is not an error. + * The pipeline will post a info message and the + * application will be informed. + */ +#define GST_ELEMENT_INFO(el, domain, code, text, debug) \ +G_STMT_START { \ + gchar *__txt = _gst_element_error_printf text; \ + gchar *__dbg = _gst_element_error_printf debug; \ + if (__txt) \ + GST_INFO_OBJECT (el, "info: %s", __txt); \ + if (__dbg) \ + GST_INFO_OBJECT (el, "info: %s", __dbg); \ + gst_element_message_full (GST_ELEMENT(el), \ + GST_MESSAGE_INFO, GST_ ## domain ## _ERROR, \ + GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \ + GST_FUNCTION, __LINE__); \ +} G_STMT_END + +/* the state change mutexes and conds */ +/** + * GST_STATE_GET_LOCK: + * @elem: a #GstElement + * + * Get a reference to the state lock of @elem. + * This lock is used by the core. It is taken while getting or setting + * the state, during state changes, and while finalizing. + */ +#define GST_STATE_GET_LOCK(elem) (&(GST_ELEMENT_CAST(elem)->state_lock)) +/** + * GST_STATE_GET_COND: + * @elem: a #GstElement + * + * Get the conditional used to signal the completion of a state change. + */ +#define GST_STATE_GET_COND(elem) (&GST_ELEMENT_CAST(elem)->state_cond) + +#define GST_STATE_LOCK(elem) g_rec_mutex_lock(GST_STATE_GET_LOCK(elem)) +#define GST_STATE_TRYLOCK(elem) g_rec_mutex_trylock(GST_STATE_GET_LOCK(elem)) +#define GST_STATE_UNLOCK(elem) g_rec_mutex_unlock(GST_STATE_GET_LOCK(elem)) +#define GST_STATE_WAIT(elem) g_cond_wait (GST_STATE_GET_COND (elem), \ + GST_OBJECT_GET_LOCK (elem)) +#define GST_STATE_WAIT_UNTIL(elem, end_time) g_cond_wait_until (GST_STATE_GET_COND (elem), \ + GST_OBJECT_GET_LOCK (elem), end_time) +#define GST_STATE_SIGNAL(elem) g_cond_signal (GST_STATE_GET_COND (elem)); +#define GST_STATE_BROADCAST(elem) g_cond_broadcast (GST_STATE_GET_COND (elem)); + +/** + * GstElement: + * @state_lock: Used to serialize execution of gst_element_set_state() + * @state_cond: Used to signal completion of a state change + * @state_cookie: Used to detect concurrent execution of + * gst_element_set_state() and gst_element_get_state() + * @target_state: the target state of an element as set by the application + * @current_state: the current state of an element + * @next_state: the next state of an element, can be #GST_STATE_VOID_PENDING if + * the element is in the correct state. + * @pending_state: the final state the element should go to, can be + * #GST_STATE_VOID_PENDING if the element is in the correct state + * @last_return: the last return value of an element state change + * @bus: the bus of the element. This bus is provided to the element by the + * parent element or the application. A #GstPipeline has a bus of its own. + * @clock: the clock of the element. This clock is usually provided to the + * element by the toplevel #GstPipeline. + * @base_time: the time of the clock right before the element is set to + * PLAYING. Subtracting @base_time from the current clock time in the PLAYING + * state will yield the running_time against the clock. + * @start_time: the running_time of the last PAUSED state + * @numpads: number of pads of the element, includes both source and sink pads. + * @pads: (element-type Gst.Pad): list of pads + * @numsrcpads: number of source pads of the element. + * @srcpads: (element-type Gst.Pad): list of source pads + * @numsinkpads: number of sink pads of the element. + * @sinkpads: (element-type Gst.Pad): list of sink pads + * @pads_cookie: updated whenever the a pad is added or removed + * @contexts: (element-type Gst.Context): list of contexts + * + * GStreamer element abstract base class. + */ +struct _GstElement +{ + GstObject object; + + /*< public >*/ /* with LOCK */ + GRecMutex state_lock; + + /* element state */ + GCond state_cond; + guint32 state_cookie; + GstState target_state; + GstState current_state; + GstState next_state; + GstState pending_state; + GstStateChangeReturn last_return; + + GstBus *bus; + + /* allocated clock */ + GstClock *clock; + GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */ + GstClockTime start_time; + + /* element pads, these lists can only be iterated while holding + * the LOCK or checking the cookie after each LOCK. */ + guint16 numpads; + GList *pads; + guint16 numsrcpads; + GList *srcpads; + guint16 numsinkpads; + GList *sinkpads; + guint32 pads_cookie; + + /* with object LOCK */ + GList *contexts; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING-1]; +}; + +/** + * GstElementClass: + * @parent_class: the parent class structure + * @metadata: metadata for elements of this class + * @elementfactory: the #GstElementFactory that creates these elements + * @padtemplates: a #GList of #GstPadTemplate + * @numpadtemplates: the number of padtemplates + * @pad_templ_cookie: changed whenever the padtemplates change + * @request_new_pad: called when a new pad is requested + * @release_pad: called when a request pad is to be released + * @get_state: get the state of the element + * @set_state: set a new state on the element + * @change_state: called by @set_state to perform an incremental state change + * @set_bus: set a #GstBus on the element + * @provide_clock: gets the #GstClock provided by the element + * @set_clock: set the #GstClock on the element + * @send_event: send a #GstEvent to the element + * @query: perform a #GstQuery on the element + * @state_changed: called immediately after a new state was set. + * @post_message: called when a message is posted on the element. Chain up to + * the parent class' handler to have it posted on the bus. + * @set_context: set a #GstContext on the element + * + * GStreamer element class. Override the vmethods to implement the element + * functionality. + */ +struct _GstElementClass +{ + GstObjectClass parent_class; + + /*< public >*/ + /* the element metadata */ + gpointer metadata; + + /* factory that the element was created from */ + GstElementFactory *elementfactory; + + /* templates for our pads */ + GList *padtemplates; + gint numpadtemplates; + guint32 pad_templ_cookie; + + /*< private >*/ + /* signal callbacks */ + void (*pad_added) (GstElement *element, GstPad *pad); + void (*pad_removed) (GstElement *element, GstPad *pad); + void (*no_more_pads) (GstElement *element); + + /*< public >*/ + /* virtual methods for subclasses */ + + /* request/release pads */ + /* FIXME 2.0 harmonize naming with gst_element_request_pad */ + GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, + const gchar* name, const GstCaps *caps); + + void (*release_pad) (GstElement *element, GstPad *pad); + + /* state changes */ + GstStateChangeReturn (*get_state) (GstElement * element, GstState * state, + GstState * pending, GstClockTime timeout); + GstStateChangeReturn (*set_state) (GstElement *element, GstState state); + GstStateChangeReturn (*change_state) (GstElement *element, GstStateChange transition); + void (*state_changed) (GstElement *element, GstState oldstate, + GstState newstate, GstState pending); + + /* bus */ + void (*set_bus) (GstElement * element, GstBus * bus); + + /* set/get clocks */ + GstClock* (*provide_clock) (GstElement *element); + gboolean (*set_clock) (GstElement *element, GstClock *clock); + + /* query functions */ + gboolean (*send_event) (GstElement *element, GstEvent *event); + + gboolean (*query) (GstElement *element, GstQuery *query); + + gboolean (*post_message) (GstElement *element, GstMessage *message); + + void (*set_context) (GstElement *element, GstContext *context); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE-2]; +}; + +/* element class pad templates */ + +GST_API +void gst_element_class_add_pad_template (GstElementClass *klass, GstPadTemplate *templ); + +GST_API +void gst_element_class_add_static_pad_template (GstElementClass *klass, GstStaticPadTemplate *static_templ); + +GST_API +void gst_element_class_add_static_pad_template_with_gtype (GstElementClass *klass, + GstStaticPadTemplate *static_templ, + GType pad_type); + +GST_API +GstPadTemplate* gst_element_class_get_pad_template (GstElementClass *element_class, const gchar *name); + +GST_API +GList* gst_element_class_get_pad_template_list (GstElementClass *element_class); + +/* element class meta data */ + +GST_API +void gst_element_class_set_metadata (GstElementClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +GST_API +void gst_element_class_set_static_metadata (GstElementClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +GST_API +void gst_element_class_add_metadata (GstElementClass * klass, + const gchar * key, const gchar * value); +GST_API +void gst_element_class_add_static_metadata (GstElementClass * klass, + const gchar * key, const gchar * value); +GST_API +const gchar * gst_element_class_get_metadata (GstElementClass * klass, + const gchar * key); + + +/* element instance */ + +GST_API +GType gst_element_get_type (void); + +/* basic name and parentage stuff from GstObject */ + +/** + * gst_element_get_name: + * @elem: a #GstElement to get the name of @elem. + * + * Returns a copy of the name of @elem. + * Caller should g_free() the return value after usage. + * For a nameless element, this returns %NULL, which you can safely g_free() + * as well. + * + * Returns: (transfer full) (nullable): the name of @elem. g_free() + * after usage. MT safe. + * + */ +#define gst_element_get_name(elem) gst_object_get_name(GST_OBJECT_CAST(elem)) + +/** + * gst_element_set_name: + * @elem: a #GstElement to set the name of. + * @name: the new name + * + * Sets the name of the element, getting rid of the old name if there was one. + */ +#define gst_element_set_name(elem,name) gst_object_set_name(GST_OBJECT_CAST(elem),name) + +/** + * gst_element_get_parent: + * @elem: a #GstElement to get the parent of. + * + * Get the parent of an element. + * + * Returns: (transfer full): the parent of an element. + */ +#define gst_element_get_parent(elem) gst_object_get_parent(GST_OBJECT_CAST(elem)) + +/** + * gst_element_set_parent: + * @elem: a #GstElement to set the parent of. + * @parent: the new parent #GstObject of the element. + * + * Sets the parent of an element. + */ +#define gst_element_set_parent(elem,parent) gst_object_set_parent(GST_OBJECT_CAST(elem),parent) + +/* clocking */ + +GST_API +GstClock* gst_element_provide_clock (GstElement *element); + +GST_API +GstClock* gst_element_get_clock (GstElement *element); + +GST_API +gboolean gst_element_set_clock (GstElement *element, GstClock *clock); + +GST_API +void gst_element_set_base_time (GstElement *element, GstClockTime time); + +GST_API +GstClockTime gst_element_get_base_time (GstElement *element); + +GST_API +void gst_element_set_start_time (GstElement *element, GstClockTime time); + +GST_API +GstClockTime gst_element_get_start_time (GstElement *element); + +/* bus */ + +GST_API +void gst_element_set_bus (GstElement * element, GstBus * bus); + +GST_API +GstBus * gst_element_get_bus (GstElement * element); + +/* context */ + +GST_API +void gst_element_set_context (GstElement * element, GstContext * context); + +GST_API +GList * gst_element_get_contexts (GstElement * element); + +GST_API +GstContext * gst_element_get_context (GstElement * element, const gchar * context_type); + +GST_API +GstContext * gst_element_get_context_unlocked (GstElement * element, const gchar * context_type); + +/* pad management */ + +GST_API +gboolean gst_element_add_pad (GstElement *element, GstPad *pad); + +GST_API +gboolean gst_element_remove_pad (GstElement *element, GstPad *pad); + +GST_API +void gst_element_no_more_pads (GstElement *element); + +GST_API +GstPad* gst_element_get_static_pad (GstElement *element, const gchar *name); + +GST_API +GstPad* gst_element_get_request_pad (GstElement *element, const gchar *name); + +GST_API +GstPad* gst_element_request_pad (GstElement *element, GstPadTemplate *templ, + const gchar * name, const GstCaps *caps); +GST_API +void gst_element_release_request_pad (GstElement *element, GstPad *pad); + +GST_API +GstIterator * gst_element_iterate_pads (GstElement * element); + +GST_API +GstIterator * gst_element_iterate_src_pads (GstElement * element); + +GST_API +GstIterator * gst_element_iterate_sink_pads (GstElement * element); + +/** + * GstElementForeachPadFunc: + * @element: the #GstElement + * @pad: a #GstPad + * @user_data: user data passed to the foreach function + * + * Function called for each pad when using gst_element_foreach_sink_pad(), + * gst_element_foreach_src_pad(), or gst_element_foreach_pad(). + * + * Returns: %FALSE to stop iterating pads, %TRUE to continue + * + * Since: 1.14 + */ +typedef gboolean (*GstElementForeachPadFunc) (GstElement * element, + GstPad * pad, + gpointer user_data); + +GST_API +gboolean gst_element_foreach_sink_pad (GstElement * element, + GstElementForeachPadFunc func, + gpointer user_data); +GST_API +gboolean gst_element_foreach_src_pad (GstElement * element, + GstElementForeachPadFunc func, + gpointer user_data); +GST_API +gboolean gst_element_foreach_pad (GstElement * element, + GstElementForeachPadFunc func, + gpointer user_data); +/* event/query/format stuff */ + +GST_API +gboolean gst_element_send_event (GstElement *element, GstEvent *event); + +GST_API +gboolean gst_element_seek (GstElement *element, gdouble rate, + GstFormat format, GstSeekFlags flags, + GstSeekType start_type, gint64 start, + GstSeekType stop_type, gint64 stop); +GST_API +gboolean gst_element_query (GstElement *element, GstQuery *query); + +/* messages */ + +GST_API +gboolean gst_element_post_message (GstElement * element, GstMessage * message); + +/* error handling */ +/* gcc versions < 3.3 warn about NULL being passed as format to printf */ +#if (!defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)) +GST_API +gchar * _gst_element_error_printf (const gchar *format, ...); +#else +GST_API +gchar * _gst_element_error_printf (const gchar *format, ...) G_GNUC_PRINTF (1, 2); +#endif + +GST_API +void gst_element_message_full (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, + gchar * debug, const gchar * file, + const gchar * function, gint line); +GST_API +void gst_element_message_full_with_details (GstElement * element, GstMessageType type, + GQuark domain, gint code, gchar * text, + gchar * debug, const gchar * file, + const gchar * function, gint line, + GstStructure * structure); + +/* state management */ + +GST_API +gboolean gst_element_is_locked_state (GstElement *element); + +GST_API +gboolean gst_element_set_locked_state (GstElement *element, gboolean locked_state); + +GST_API +gboolean gst_element_sync_state_with_parent (GstElement *element); + +GST_API +GstStateChangeReturn gst_element_get_state (GstElement * element, + GstState * state, + GstState * pending, + GstClockTime timeout); +GST_API +GstStateChangeReturn gst_element_set_state (GstElement *element, GstState state); + +GST_API +void gst_element_abort_state (GstElement * element); + +GST_API +GstStateChangeReturn gst_element_change_state (GstElement * element, + GstStateChange transition); + +GST_API +GstStateChangeReturn gst_element_continue_state (GstElement * element, + GstStateChangeReturn ret); +GST_API +void gst_element_lost_state (GstElement * element); + + +typedef void (*GstElementCallAsyncFunc) (GstElement * element, + gpointer user_data); +GST_API +void gst_element_call_async (GstElement * element, + GstElementCallAsyncFunc func, gpointer user_data, + GDestroyNotify destroy_notify); + +/* factory management */ + +GST_API +GstElementFactory* gst_element_get_factory (GstElement *element); + +/* utility functions */ + +GST_API +gulong gst_element_add_property_notify_watch (GstElement * element, + const gchar * property_name, + gboolean include_value); +GST_API +gulong gst_element_add_property_deep_notify_watch (GstElement * element, + const gchar * property_name, + gboolean include_value); +GST_API +void gst_element_remove_property_notify_watch (GstElement * element, + gulong watch_id); + +GST_API +GstPadTemplate* gst_element_get_pad_template (GstElement *element, const gchar *name); + +GST_API +GList* gst_element_get_pad_template_list (GstElement *element); +GST_API +const gchar * gst_element_get_metadata (GstElement * element, const gchar * key); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstElement, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_ELEMENT_H__ */ diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c new file mode 100644 index 0000000..da64380 --- /dev/null +++ b/gst/gstelementfactory.c @@ -0,0 +1,877 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2003 Benjamin Otte + * + * gstelementfactory.c: GstElementFactory object, support 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstelementfactory + * @title: GstElementFactory + * @short_description: Create GstElements from a factory + * @see_also: #GstElement, #GstPlugin, #GstPluginFeature, #GstPadTemplate. + * + * #GstElementFactory is used to create instances of elements. A + * GstElementFactory can be added to a #GstPlugin as it is also a + * #GstPluginFeature. + * + * Use the gst_element_factory_find() and gst_element_factory_create() + * functions to create element instances or use gst_element_factory_make() as a + * convenient shortcut. + * + * The following code example shows you how to create a GstFileSrc element. + * + * ## Using an element factory + * |[ + * #include <gst/gst.h> + * + * GstElement *src; + * GstElementFactory *srcfactory; + * + * gst_init (&argc, &argv); + * + * srcfactory = gst_element_factory_find ("filesrc"); + * g_return_if_fail (srcfactory != NULL); + * src = gst_element_factory_create (srcfactory, "src"); + * g_return_if_fail (src != NULL); + * ... + * ]| + */ + +#include "gst_private.h" + +#include "gstelement.h" +#include "gstelementmetadata.h" +#include "gstinfo.h" +#include "gsturi.h" +#include "gstregistry.h" +#include "gst.h" + +#include "glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (element_factory_debug); +#define GST_CAT_DEFAULT element_factory_debug + +static void gst_element_factory_finalize (GObject * object); +static void gst_element_factory_cleanup (GstElementFactory * factory); + +/* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */ + +/* this is defined in gstelement.c */ +extern GQuark __gst_elementclass_factory; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", \ + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \ + "element factories keep information about installed elements"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstElementFactory, gst_element_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_element_factory_class_init (GstElementFactoryClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = gst_element_factory_finalize; +} + +static void +gst_element_factory_init (GstElementFactory * factory) +{ + factory->staticpadtemplates = NULL; + factory->numpadtemplates = 0; + + factory->uri_type = GST_URI_UNKNOWN; + factory->uri_protocols = NULL; + + factory->interfaces = NULL; +} + +static void +gst_element_factory_finalize (GObject * object) +{ + GstElementFactory *factory = GST_ELEMENT_FACTORY (object); + + gst_element_factory_cleanup (factory); + G_OBJECT_CLASS (gst_element_factory_parent_class)->finalize (object); +} + +/** + * gst_element_factory_find: + * @name: name of factory to find + * + * Search for an element factory of the given name. Refs the returned + * element factory; caller is responsible for unreffing. + * + * Returns: (transfer full) (nullable): #GstElementFactory if found, + * %NULL otherwise + */ +GstElementFactory * +gst_element_factory_find (const gchar * name) +{ + GstPluginFeature *feature; + + g_return_val_if_fail (name != NULL, NULL); + + feature = gst_registry_find_feature (gst_registry_get (), name, + GST_TYPE_ELEMENT_FACTORY); + if (feature) + return GST_ELEMENT_FACTORY (feature); + + /* this isn't an error, for instance when you query if an element factory is + * present */ + GST_LOG ("no such element factory \"%s\"", name); + return NULL; +} + +static void +gst_element_factory_cleanup (GstElementFactory * factory) +{ + GList *item; + + if (factory->metadata) { + gst_structure_free ((GstStructure *) factory->metadata); + factory->metadata = NULL; + } + if (factory->type) { + factory->type = G_TYPE_INVALID; + } + + for (item = factory->staticpadtemplates; item; item = item->next) { + GstStaticPadTemplate *templ = item->data; + + gst_static_caps_cleanup (&templ->static_caps); + g_slice_free (GstStaticPadTemplate, templ); + } + g_list_free (factory->staticpadtemplates); + factory->staticpadtemplates = NULL; + factory->numpadtemplates = 0; + factory->uri_type = GST_URI_UNKNOWN; + if (factory->uri_protocols) { + g_strfreev (factory->uri_protocols); + factory->uri_protocols = NULL; + } + + g_list_free (factory->interfaces); + factory->interfaces = NULL; +} + +#define CHECK_METADATA_FIELD(klass, name, key) \ + G_STMT_START { \ + const gchar *metafield = gst_element_class_get_metadata (klass, key); \ + if (G_UNLIKELY (metafield == NULL || *metafield == '\0')) { \ + g_warning ("Element factory metadata for '%s' has no valid %s field", name, key); \ + goto detailserror; \ + } \ + } G_STMT_END; + +/** + * gst_element_register: + * @plugin: (allow-none): #GstPlugin to register the element with, or %NULL for + * a static element. + * @name: name of elements of this type + * @rank: rank of element (higher rank means more importance when autoplugging) + * @type: GType of element to register + * + * Create a new elementfactory capable of instantiating objects of the + * @type and add the factory to @plugin. + * + * Returns: %TRUE, if the registering succeeded, %FALSE on error + */ +gboolean +gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, + GType type) +{ + GstPluginFeature *existing_feature; + GstRegistry *registry; + GstElementFactory *factory; + GType *interfaces; + guint n_interfaces, i; + GstElementClass *klass; + GList *item; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE); + + registry = gst_registry_get (); + + /* check if feature already exists, if it exists there is no need to update it + * when the registry is getting updated, outdated plugins and all their + * features are removed and readded. + */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + factory = GST_ELEMENT_FACTORY_CAST (existing_feature); + factory->type = type; + existing_feature->loaded = TRUE; + g_type_set_qdata (type, __gst_elementclass_factory, factory); + gst_object_unref (existing_feature); + return TRUE; + } + + factory = g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL); + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + GST_LOG_OBJECT (factory, "Created new elementfactory for type %s", + g_type_name (type)); + + /* provide info needed during class structure setup */ + g_type_set_qdata (type, __gst_elementclass_factory, factory); + klass = GST_ELEMENT_CLASS (g_type_class_ref (type)); + + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_LONGNAME); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_KLASS); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_DESCRIPTION); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_AUTHOR); + + factory->type = type; + factory->metadata = gst_structure_copy ((GstStructure *) klass->metadata); + + for (item = klass->padtemplates; item; item = item->next) { + GstPadTemplate *templ = item->data; + GstStaticPadTemplate *newt; + gchar *caps_string = gst_caps_to_string (templ->caps); + + newt = g_slice_new (GstStaticPadTemplate); + newt->name_template = g_intern_string (templ->name_template); + newt->direction = templ->direction; + newt->presence = templ->presence; + newt->static_caps.caps = NULL; + newt->static_caps.string = g_intern_string (caps_string); + factory->staticpadtemplates = + g_list_append (factory->staticpadtemplates, newt); + + g_free (caps_string); + } + factory->numpadtemplates = klass->numpadtemplates; + + /* special stuff for URI handling */ + if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) { + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) + g_type_interface_peek (klass, GST_TYPE_URI_HANDLER); + + if (!iface || !iface->get_type || !iface->get_protocols) + goto urierror; + if (iface->get_type) + factory->uri_type = iface->get_type (factory->type); + if (!GST_URI_TYPE_IS_VALID (factory->uri_type)) + goto urierror; + if (iface->get_protocols) { + const gchar *const *protocols; + + protocols = iface->get_protocols (factory->type); + factory->uri_protocols = g_strdupv ((gchar **) protocols); + } + if (!factory->uri_protocols) + goto urierror; + } + + interfaces = g_type_interfaces (type, &n_interfaces); + for (i = 0; i < n_interfaces; i++) { + __gst_element_factory_add_interface (factory, g_type_name (interfaces[i])); + } + g_free (interfaces); + + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; + + /* ERRORS */ +urierror: + { + GST_WARNING_OBJECT (factory, "error with uri handler!"); + gst_element_factory_cleanup (factory); + return FALSE; + } + +detailserror: + { + gst_element_factory_cleanup (factory); + return FALSE; + } +} + +/** + * gst_element_factory_create: + * @factory: factory to instantiate + * @name: (allow-none): name of new element, or %NULL to automatically create + * a unique name + * + * Create a new element of the type defined by the given elementfactory. + * It will be given the name supplied, since all elements require a name as + * their first argument. + * + * Returns: (transfer floating) (nullable): new #GstElement or %NULL + * if the element couldn't be created + */ +GstElement * +gst_element_factory_create (GstElementFactory * factory, const gchar * name) +{ + GstElement *element; + GstElementClass *oclass; + GstElementFactory *newfactory; + + g_return_val_if_fail (factory != NULL, NULL); + + newfactory = + GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + + if (newfactory == NULL) + goto load_failed; + + factory = newfactory; + + if (name) + GST_INFO ("creating element \"%s\" named \"%s\"", + GST_OBJECT_NAME (factory), GST_STR_NULL (name)); + else + GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory)); + + if (factory->type == 0) + goto no_type; + + /* create an instance of the element, cast so we don't assert on NULL + * also set name as early as we can + */ + if (name) + element = g_object_new (factory->type, "name", name, NULL); + else + element = g_object_new (factory->type, NULL); + if (G_UNLIKELY (element == NULL)) + goto no_element; + + /* fill in the pointer to the factory in the element class. The + * class will not be unreffed currently. + * Be thread safe as there might be 2 threads creating the first instance of + * an element at the same moment + */ + oclass = GST_ELEMENT_GET_CLASS (element); + if (!g_atomic_pointer_compare_and_exchange (&oclass->elementfactory, NULL, + factory)) + gst_object_unref (factory); + else + /* This ref will never be dropped as the class is never destroyed */ + GST_OBJECT_FLAG_SET (factory, GST_OBJECT_FLAG_MAY_BE_LEAKED); + + GST_DEBUG ("created element \"%s\"", GST_OBJECT_NAME (factory)); + + return element; + + /* ERRORS */ +load_failed: + { + GST_WARNING_OBJECT (factory, + "loading plugin containing feature %s returned NULL!", name); + return NULL; + } +no_type: + { + GST_WARNING_OBJECT (factory, "factory has no type"); + gst_object_unref (factory); + return NULL; + } +no_element: + { + GST_WARNING_OBJECT (factory, "could not create element"); + gst_object_unref (factory); + return NULL; + } +} + +/** + * gst_element_factory_make: + * @factoryname: a named factory to instantiate + * @name: (allow-none): name of new element, or %NULL to automatically create + * a unique name + * + * Create a new element of the type defined by the given element factory. + * If name is %NULL, then the element will receive a guaranteed unique name, + * consisting of the element factory name and a number. + * If name is given, it will be given the name supplied. + * + * Returns: (transfer floating) (nullable): new #GstElement or %NULL + * if unable to create element + */ +GstElement * +gst_element_factory_make (const gchar * factoryname, const gchar * name) +{ + GstElementFactory *factory; + GstElement *element; + + g_return_val_if_fail (factoryname != NULL, NULL); + g_return_val_if_fail (gst_is_initialized (), NULL); + + GST_LOG ("gstelementfactory: make \"%s\" \"%s\"", + factoryname, GST_STR_NULL (name)); + + factory = gst_element_factory_find (factoryname); + if (factory == NULL) + goto no_factory; + + GST_LOG_OBJECT (factory, "found factory %p", factory); + element = gst_element_factory_create (factory, name); + if (element == NULL) + goto create_failed; + + gst_object_unref (factory); + + return element; + + /* ERRORS */ +no_factory: + { + GST_WARNING ("no such element factory \"%s\"!", factoryname); + return NULL; + } +create_failed: + { + GST_INFO_OBJECT (factory, "couldn't create instance!"); + gst_object_unref (factory); + return NULL; + } +} + +void +__gst_element_factory_add_static_pad_template (GstElementFactory * factory, + GstStaticPadTemplate * templ) +{ + g_return_if_fail (factory != NULL); + g_return_if_fail (templ != NULL); + + factory->staticpadtemplates = + g_list_append (factory->staticpadtemplates, templ); + factory->numpadtemplates++; +} + +/** + * gst_element_factory_get_element_type: + * @factory: factory to get managed #GType from + * + * Get the #GType for elements managed by this factory. The type can + * only be retrieved if the element factory is loaded, which can be + * assured with gst_plugin_feature_load(). + * + * Returns: the #GType for elements managed by this factory or 0 if + * the factory is not loaded. + */ +GType +gst_element_factory_get_element_type (GstElementFactory * factory) +{ + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), 0); + + return factory->type; +} + +/** + * gst_element_factory_get_metadata: + * @factory: a #GstElementFactory + * @key: a key + * + * Get the metadata on @factory with @key. + * + * Returns: (nullable): the metadata with @key on @factory or %NULL + * when there was no metadata with the given @key. + */ +const gchar * +gst_element_factory_get_metadata (GstElementFactory * factory, + const gchar * key) +{ + return gst_structure_get_string ((GstStructure *) factory->metadata, key); +} + +/** + * gst_element_factory_get_metadata_keys: + * @factory: a #GstElementFactory + * + * Get the available keys for the metadata on @factory. + * + * Returns: (transfer full) (element-type utf8) (array zero-terminated=1) (nullable): + * a %NULL-terminated array of key strings, or %NULL when there is no + * metadata. Free with g_strfreev() when no longer needed. + */ +gchar ** +gst_element_factory_get_metadata_keys (GstElementFactory * factory) +{ + GstStructure *metadata; + gchar **arr; + gint i, num; + + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL); + + metadata = (GstStructure *) factory->metadata; + if (metadata == NULL) + return NULL; + + num = gst_structure_n_fields (metadata); + if (num == 0) + return NULL; + + arr = g_new (gchar *, num + 1); + for (i = 0; i < num; ++i) { + arr[i] = g_strdup (gst_structure_nth_field_name (metadata, i)); + } + arr[i] = NULL; + return arr; +} + +/** + * gst_element_factory_get_num_pad_templates: + * @factory: a #GstElementFactory + * + * Gets the number of pad_templates in this factory. + * + * Returns: the number of pad_templates + */ +guint +gst_element_factory_get_num_pad_templates (GstElementFactory * factory) +{ + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), 0); + + return factory->numpadtemplates; +} + +/** + * __gst_element_factory_add_interface: + * @elementfactory: The elementfactory to add the interface to + * @interfacename: Name of the interface + * + * Adds the given interfacename to the list of implemented interfaces of the + * element. + */ +void +__gst_element_factory_add_interface (GstElementFactory * elementfactory, + const gchar * interfacename) +{ + g_return_if_fail (GST_IS_ELEMENT_FACTORY (elementfactory)); + g_return_if_fail (interfacename != NULL); + g_return_if_fail (interfacename[0] != '\0'); /* no empty string */ + + elementfactory->interfaces = + g_list_prepend (elementfactory->interfaces, + (gpointer) g_intern_string (interfacename)); +} + +/** + * gst_element_factory_get_static_pad_templates: + * @factory: a #GstElementFactory + * + * Gets the #GList of #GstStaticPadTemplate for this factory. + * + * Returns: (transfer none) (element-type Gst.StaticPadTemplate): the + * static pad templates + */ +const GList * +gst_element_factory_get_static_pad_templates (GstElementFactory * factory) +{ + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL); + + return factory->staticpadtemplates; +} + +/** + * gst_element_factory_get_uri_type: + * @factory: a #GstElementFactory + * + * Gets the type of URIs the element supports or #GST_URI_UNKNOWN if none. + * + * Returns: type of URIs this element supports + */ +GstURIType +gst_element_factory_get_uri_type (GstElementFactory * factory) +{ + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), GST_URI_UNKNOWN); + + return factory->uri_type; +} + +/** + * gst_element_factory_get_uri_protocols: + * @factory: a #GstElementFactory + * + * Gets a %NULL-terminated array of protocols this element supports or %NULL if + * no protocols are supported. You may not change the contents of the returned + * array, as it is still owned by the element factory. Use g_strdupv() to + * make a copy of the protocol string array if you need to. + * + * Returns: (transfer none) (array zero-terminated=1): the supported protocols + * or %NULL + */ +const gchar *const * +gst_element_factory_get_uri_protocols (GstElementFactory * factory) +{ + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL); + + return (const gchar * const *) factory->uri_protocols; +} + +/** + * gst_element_factory_has_interface: + * @factory: a #GstElementFactory + * @interfacename: an interface name + * + * Check if @factory implements the interface with name @interfacename. + * + * Returns: %TRUE when @factory implement the interface. + */ +gboolean +gst_element_factory_has_interface (GstElementFactory * factory, + const gchar * interfacename) +{ + GList *walk; + + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), FALSE); + + for (walk = factory->interfaces; walk; walk = g_list_next (walk)) { + gchar *iname = (gchar *) walk->data; + + if (!strcmp (iname, interfacename)) + return TRUE; + } + return FALSE; +} + + +typedef struct +{ + GstElementFactoryListType type; + GstRank minrank; +} FilterData; + + +/** + * gst_element_factory_list_is_type: + * @factory: a #GstElementFactory + * @type: a #GstElementFactoryListType + * + * Check if @factory is of the given types. + * + * Returns: %TRUE if @factory is of @type. + */ +gboolean +gst_element_factory_list_is_type (GstElementFactory * factory, + GstElementFactoryListType type) +{ + gboolean res = FALSE; + const gchar *klass; + + klass = + gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS); + + if (klass == NULL) { + GST_ERROR_OBJECT (factory, "element factory is missing klass identifiers"); + return res; + } + + /* Filter by element type first, as soon as it matches + * one type, we skip all other tests */ + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SINK)) + res = (strstr (klass, "Sink") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SRC)) + res = (strstr (klass, "Source") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECODER)) + res = (strstr (klass, "Decoder") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCODER)) + res = (strstr (klass, "Encoder") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_MUXER)) + res = (strstr (klass, "Muxer") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEMUXER)) + res = (strstr (klass, "Demux") != NULL); + + /* FIXME : We're actually parsing two Classes here... */ + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PARSER)) + res = ((strstr (klass, "Parser") != NULL) + && (strstr (klass, "Codec") != NULL)); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER)) + res = (strstr (klass, "Depayloader") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PAYLOADER)) + res = (strstr (klass, "Payloader") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_FORMATTER)) + res = (strstr (klass, "Formatter") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECRYPTOR)) + res = (strstr (klass, "Decryptor") != NULL); + + if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR)) + res = (strstr (klass, "Encryptor") != NULL); + + /* Filter by media type now, we only test if it + * matched any of the types above or only checking the media + * type was requested. */ + if ((res || !(type & (GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS - 1))) + && (type & (GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO | + GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | + GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE | + GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE | + GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA))) + res = ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO) + && (strstr (klass, "Audio") != NULL)) + || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO) + && (strstr (klass, "Video") != NULL)) + || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE) + && (strstr (klass, "Image") != NULL)) || + ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE) + && (strstr (klass, "Subtitle") != NULL)) || + ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA) + && (strstr (klass, "Metadata") != NULL)); + + return res; +} + +static gboolean +element_filter (GstPluginFeature * feature, FilterData * data) +{ + gboolean res; + + /* we only care about element factories */ + if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature))) + return FALSE; + + res = (gst_plugin_feature_get_rank (feature) >= data->minrank) && + gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (feature), + data->type); + + return res; +} + +/** + * gst_element_factory_list_get_elements: + * @type: a #GstElementFactoryListType + * @minrank: Minimum rank + * + * Get a list of factories that match the given @type. Only elements + * with a rank greater or equal to @minrank will be returned. + * The list of factories is returned by decreasing rank. + * + * Returns: (transfer full) (element-type Gst.ElementFactory): a #GList of + * #GstElementFactory elements. Use gst_plugin_feature_list_free() after + * usage. + */ +GList * +gst_element_factory_list_get_elements (GstElementFactoryListType type, + GstRank minrank) +{ + GList *result; + FilterData data; + + /* prepare type */ + data.type = type; + data.minrank = minrank; + + /* get the feature list using the filter */ + result = gst_registry_feature_filter (gst_registry_get (), + (GstPluginFeatureFilter) element_filter, FALSE, &data); + + /* sort on rank and name */ + result = g_list_sort (result, gst_plugin_feature_rank_compare_func); + + return result; +} + +/** + * gst_element_factory_list_filter: + * @list: (transfer none) (element-type Gst.ElementFactory): a #GList of + * #GstElementFactory to filter + * @caps: a #GstCaps + * @direction: a #GstPadDirection to filter on + * @subsetonly: whether to filter on caps subsets or not. + * + * Filter out all the elementfactories in @list that can handle @caps in + * the given direction. + * + * If @subsetonly is %TRUE, then only the elements whose pads templates + * are a complete superset of @caps will be returned. Else any element + * whose pad templates caps can intersect with @caps will be returned. + * + * Returns: (transfer full) (element-type Gst.ElementFactory): a #GList of + * #GstElementFactory elements that match the given requisites. + * Use #gst_plugin_feature_list_free after usage. + */ +GList * +gst_element_factory_list_filter (GList * list, + const GstCaps * caps, GstPadDirection direction, gboolean subsetonly) +{ + GQueue results = G_QUEUE_INIT; + + GST_DEBUG ("finding factories"); + + /* loop over all the factories */ + for (; list; list = list->next) { + GstElementFactory *factory; + const GList *templates; + GList *walk; + + factory = (GstElementFactory *) list->data; + + GST_DEBUG ("Trying %s", + gst_plugin_feature_get_name ((GstPluginFeature *) factory)); + + /* 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 == direction) { + 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 */ + + /* check if the intersection is empty */ + if ((subsetonly && gst_caps_is_subset (caps, tmpl_caps)) || + (!subsetonly && gst_caps_can_intersect (caps, tmpl_caps))) { + /* non empty intersection, we can use this element */ + g_queue_push_tail (&results, gst_object_ref (factory)); + gst_caps_unref (tmpl_caps); + break; + } + gst_caps_unref (tmpl_caps); + } + } + } + return results.head; +} diff --git a/gst/gstelementfactory.h b/gst/gstelementfactory.h new file mode 100644 index 0000000..c66dd30 --- /dev/null +++ b/gst/gstelementfactory.h @@ -0,0 +1,232 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2004 Wim Taymans + * + * gstelementfactory.h: Header for GstElementFactory + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_ELEMENT_FACTORY_H__ +#define __GST_ELEMENT_FACTORY_H__ + +/** + * GstElementFactory: + * + * The opaque #GstElementFactory data structure. + */ +typedef struct _GstElementFactory GstElementFactory; +typedef struct _GstElementFactoryClass GstElementFactoryClass; + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_ELEMENT_FACTORY (gst_element_factory_get_type()) +#define GST_ELEMENT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENT_FACTORY,\ + GstElementFactory)) +#define GST_ELEMENT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENT_FACTORY,\ + GstElementFactoryClass)) +#define GST_IS_ELEMENT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENT_FACTORY)) +#define GST_IS_ELEMENT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT_FACTORY)) +#define GST_ELEMENT_FACTORY_CAST(obj) ((GstElementFactory *)(obj)) + +GST_API +GType gst_element_factory_get_type (void); + +GST_API +GstElementFactory * gst_element_factory_find (const gchar *name); + +GST_API +GType gst_element_factory_get_element_type (GstElementFactory *factory); + +GST_API +const gchar * gst_element_factory_get_metadata (GstElementFactory *factory, const gchar *key); + +GST_API +gchar ** gst_element_factory_get_metadata_keys (GstElementFactory *factory); + +GST_API +guint gst_element_factory_get_num_pad_templates (GstElementFactory *factory); + +GST_API +const GList * gst_element_factory_get_static_pad_templates (GstElementFactory *factory); + +GST_API +GstURIType gst_element_factory_get_uri_type (GstElementFactory *factory); + +GST_API +const gchar * const * gst_element_factory_get_uri_protocols (GstElementFactory *factory); + +GST_API +gboolean gst_element_factory_has_interface (GstElementFactory *factory, + const gchar *interfacename); +GST_API +GstElement* gst_element_factory_create (GstElementFactory *factory, + const gchar *name) G_GNUC_MALLOC; +GST_API +GstElement* gst_element_factory_make (const gchar *factoryname, const gchar *name) G_GNUC_MALLOC; + +GST_API +gboolean gst_element_register (GstPlugin *plugin, const gchar *name, + guint rank, GType type); + +/* Factory list functions */ + +/** + * GstFactoryListType: + * @GST_ELEMENT_FACTORY_TYPE_DECODER: Decoder elements + * @GST_ELEMENT_FACTORY_TYPE_ENCODER: Encoder elements + * @GST_ELEMENT_FACTORY_TYPE_SINK: Sink elements + * @GST_ELEMENT_FACTORY_TYPE_SRC: Source elements + * @GST_ELEMENT_FACTORY_TYPE_MUXER: Muxer elements + * @GST_ELEMENT_FACTORY_TYPE_DEMUXER: Demuxer elements + * @GST_ELEMENT_FACTORY_TYPE_PARSER: Parser elements + * @GST_ELEMENT_FACTORY_TYPE_PAYLOADER: Payloader elements + * @GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER: Depayloader elements + * @GST_ELEMENT_FACTORY_TYPE_DECRYPTOR: Elements handling decryption (Since 1.6) + * @GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR: Elements handling encryption (Since 1.6) + * @GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS: Private, do not use + * @GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO: Elements handling video media types + * @GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO: Elements handling audio media types + * @GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE: Elements handling image media types + * @GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE: Elements handling subtitle media types + * @GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA: Elements handling metadata media types + * + * The type of #GstElementFactory to filter. + * + * All @GstFactoryListType up to @GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS are exclusive. + * + * If one or more of the MEDIA types are specified, then only elements + * matching the specified media types will be selected. + */ + +typedef guint64 GstElementFactoryListType; + +#define GST_ELEMENT_FACTORY_TYPE_DECODER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 0)) +#define GST_ELEMENT_FACTORY_TYPE_ENCODER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 1)) +#define GST_ELEMENT_FACTORY_TYPE_SINK ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 2)) +#define GST_ELEMENT_FACTORY_TYPE_SRC ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 3)) +#define GST_ELEMENT_FACTORY_TYPE_MUXER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 4)) +#define GST_ELEMENT_FACTORY_TYPE_DEMUXER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 5)) +#define GST_ELEMENT_FACTORY_TYPE_PARSER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 6)) +#define GST_ELEMENT_FACTORY_TYPE_PAYLOADER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 7)) +#define GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 8)) +#define GST_ELEMENT_FACTORY_TYPE_FORMATTER ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 9)) +#define GST_ELEMENT_FACTORY_TYPE_DECRYPTOR ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 10)) +#define GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 11)) + +#define GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 48)) + +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 49)) +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 50)) +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 51)) +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 52)) +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA ((GstElementFactoryListType)(G_GUINT64_CONSTANT (1) << 53)) + +/** + * GST_ELEMENT_FACTORY_TYPE_ANY: (value 562949953421311) (type GstElementFactoryListType) + * + * Elements of any of the defined GST_ELEMENT_FACTORY_LIST types + */ +#define GST_ELEMENT_FACTORY_TYPE_ANY ((GstElementFactoryListType)((G_GUINT64_CONSTANT (1) << 49) - 1)) + +/** + * GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY: (value 18446462598732840960) (type GstElementFactoryListType) + * + * Elements matching any of the defined GST_ELEMENT_FACTORY_TYPE_MEDIA types + * + * Note: Do not use this if you wish to not filter against any of the defined + * media types. If you wish to do this, simply don't specify any + * GST_ELEMENT_FACTORY_TYPE_MEDIA flag. + */ +#define GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY ((GstElementFactoryListType)(~G_GUINT64_CONSTANT (0) << 48)) + +/** + * GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER: (value 2814749767106562) (type GstElementFactoryListType) + * + * All encoders handling video or image media types + */ +#define GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) + +/** + * GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER: (value 1125899906842626) (type GstElementFactoryListType) + * + * All encoders handling audio media types + */ +#define GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)) + +/** + * GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS: (value 3940649673949188) (type GstElementFactoryListType) + * + * All sinks handling audio, video or image media types + */ +#define GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) + +/** + * GST_ELEMENT_FACTORY_TYPE_DECODABLE: (value 1377) (type GstElementFactoryListType) + * + * All elements used to 'decode' streams (decoders, demuxers, parsers, depayloaders) + */ +#define GST_ELEMENT_FACTORY_TYPE_DECODABLE \ + ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER | GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_DECRYPTOR)) + +/* Element klass defines */ +#define GST_ELEMENT_FACTORY_KLASS_DECODER "Decoder" +#define GST_ELEMENT_FACTORY_KLASS_ENCODER "Encoder" +#define GST_ELEMENT_FACTORY_KLASS_SINK "Sink" +#define GST_ELEMENT_FACTORY_KLASS_SRC "Source" +#define GST_ELEMENT_FACTORY_KLASS_MUXER "Muxer" +#define GST_ELEMENT_FACTORY_KLASS_DEMUXER "Demuxer" +#define GST_ELEMENT_FACTORY_KLASS_PARSER "Parser" +#define GST_ELEMENT_FACTORY_KLASS_PAYLOADER "Payloader" +#define GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER "Depayloader" +#define GST_ELEMENT_FACTORY_KLASS_FORMATTER "Formatter" +#define GST_ELEMENT_FACTORY_KLASS_DECRYPTOR "Decryptor" +#define GST_ELEMENT_FACTORY_KLASS_ENCRYPTOR "Encryptor" + +#define GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO "Video" +#define GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO "Audio" +#define GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE "Image" +#define GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE "Subtitle" +#define GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA "Metadata" + +GST_API +gboolean gst_element_factory_list_is_type (GstElementFactory *factory, + GstElementFactoryListType type); + +GST_API +GList * gst_element_factory_list_get_elements (GstElementFactoryListType type, + GstRank minrank) G_GNUC_MALLOC; + + +GST_API +GList * gst_element_factory_list_filter (GList *list, const GstCaps *caps, + GstPadDirection direction, + gboolean subsetonly) G_GNUC_MALLOC; +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstElementFactory, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_ELEMENT_FACTORY_H__ */ diff --git a/gst/gstelementmetadata.h b/gst/gstelementmetadata.h new file mode 100644 index 0000000..76a0c04 --- /dev/null +++ b/gst/gstelementmetadata.h @@ -0,0 +1,79 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2004 Wim Taymans + * + * gstelementmetadata.h: Metadata for GstElement classes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_ELEMENT_METADATA_H__ +#define __GST_ELEMENT_METADATA_H__ + +#include + +G_BEGIN_DECLS + +/** + * GST_ELEMENT_METADATA_LONGNAME: + * + * The long English name of the element. E.g. "File Sink" + */ +#define GST_ELEMENT_METADATA_LONGNAME "long-name" +/** + * GST_ELEMENT_METADATA_KLASS: + * + * String describing the type of element, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + */ +#define GST_ELEMENT_METADATA_KLASS "klass" + +/** + * GST_ELEMENT_METADATA_DESCRIPTION: + * + * Sentence describing the purpose of the element. + * E.g: "Write stream to a file" + */ +#define GST_ELEMENT_METADATA_DESCRIPTION "description" +/** + * GST_ELEMENT_METADATA_AUTHOR: + * + * Name and contact details of the author(s). Use \n to separate + * multiple author details. + * E.g: "Joe Bloggs <joe.blogs at foo.com>" + */ +#define GST_ELEMENT_METADATA_AUTHOR "author" + +/** + * GST_ELEMENT_METADATA_DOC_URI: + * + * Set uri pointing to user documentation. Applications can use this to show + * help for e.g. effects to users. + */ +#define GST_ELEMENT_METADATA_DOC_URI "doc-uri" +/** + * GST_ELEMENT_METADATA_ICON_NAME: + * + * Elements that bridge to certain other products can include an icon of that + * used product. Application can show the icon in menus/selectors to help + * identifying specific elements. + */ +#define GST_ELEMENT_METADATA_ICON_NAME "icon-name" + +G_END_DECLS + +#endif /* __GST_ELEMENT_METADATA_H__ */ diff --git a/gst/gstenumtypes.c.template b/gst/gstenumtypes.c.template new file mode 100644 index 0000000..1bb7506 --- /dev/null +++ b/gst/gstenumtypes.c.template @@ -0,0 +1,41 @@ +/*** BEGIN file-header ***/ +#include "gst/gst_private.h" +#include +#define C_ENUM(v) ((gint) v) +#define C_FLAGS(v) ((guint) v) + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static gsize id = 0; + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + if (g_once_init_enter (&id)) { + GType tmp = g_@type@_register_static ("@EnumName@", values); + g_once_init_leave (&id, tmp); + } + + return (GType) id; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ + +/*** END file-tail ***/ diff --git a/gst/gstenumtypes.h.template b/gst/gstenumtypes.h.template new file mode 100644 index 0000000..14a8783 --- /dev/null +++ b/gst/gstenumtypes.h.template @@ -0,0 +1,25 @@ +/*** BEGIN file-header ***/ +#ifndef __GST_ENUM_TYPES_H__ +#define __GST_ENUM_TYPES_H__ + +#include +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GST_API GType @enum_name@_get_type (void); +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __GST_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/gst/gsterror.c b/gst/gsterror.c new file mode 100644 index 0000000..820b51e --- /dev/null +++ b/gst/gsterror.c @@ -0,0 +1,315 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsterror + * @title: GstError + * @short_description: Categorized error messages + * @see_also: #GstMessage + * + * GStreamer elements can throw non-fatal warnings and fatal errors. + * Higher-level elements and applications can programmatically filter + * the ones they are interested in or can recover from, + * and have a default handler handle the rest of them. + * + * The rest of this section will use the term error + * to mean both (non-fatal) warnings and (fatal) errors; they are treated + * similarly. + * + * Errors from elements are the combination of a #GError and a debug string. + * The #GError contains: + * - a domain type: CORE, LIBRARY, RESOURCE or STREAM + * - a code: an enum value specific to the domain + * - a translated, human-readable message + * - a non-translated additional debug string, which also contains + * - file and line information + * + * Elements do not have the context required to decide what to do with + * errors. As such, they should only inform about errors, and stop their + * processing. In short, an element doesn't know what it is being used for. + * + * It is the application or compound element using the given element that + * has more context about the use of the element. Errors can be received by + * listening to the #GstBus of the element/pipeline for #GstMessage objects with + * the type %GST_MESSAGE_ERROR or %GST_MESSAGE_WARNING. The thrown errors should + * be inspected, and filtered if appropriate. + * + * An application is expected to, by default, present the user with a + * dialog box (or an equivalent) showing the error message. The dialog + * should also allow a way to get at the additional debug information, + * so the user can provide bug reporting information. + * + * A compound element is expected to forward errors by default higher up + * the hierarchy; this is done by default in the same way as for other types + * of #GstMessage. + * + * When applications or compound elements trigger errors that they can + * recover from, they can filter out these errors and take appropriate action. + * For example, an application that gets an error from xvimagesink + * that indicates all XVideo ports are taken, the application can attempt + * to use another sink instead. + * + * Elements throw errors using the #GST_ELEMENT_ERROR convenience macro: + * + * ## Throwing an error + * + * |[ + * GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, + * (_("No file name specified for reading.")), (NULL)); + * ]| + * + * Things to keep in mind: + * + * * Don't go off inventing new error codes. The ones + * currently provided should be enough. If you find your type of error + * does not fit the current codes, you should use FAILED. + * * Don't provide a message if the default one suffices. + * this keeps messages more uniform. Use (%NULL) - not forgetting the + * parentheses. + * * If you do supply a custom message, it should be + * marked for translation. The message should start with a capital + * and end with a period. The message should describe the error in short, + * in a human-readable form, and without any complex technical terms. + * A user interface will present this message as the first thing a user + * sees. Details, technical info, ... should go in the debug string. + * + * * The debug string can be as you like. Again, use (%NULL) + * if there's nothing to add - file and line number will still be + * passed. #GST_ERROR_SYSTEM can be used as a shortcut to give + * debug information on a system call error. + * + */ + +/* FIXME 2.0: the entire error system needs an overhaul - it's not very + * useful the way it is. Also, we need to be able to specify additional + * 'details' for errors (e.g. disk/file/resource error -> out-of-space; or + * put the url/filename/device name that caused the error somewhere) + * without having to add enums for every little thing. + * + * FIXME 2.0: get rid of GST_{CORE,LIBRARY,RESOURCE,STREAM}_ERROR_NUM_ERRORS. + * Maybe also replace _quark() functions with g_quark_from_static_string()? + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include +#include "gst-i18n-lib.h" + +#define QUARK_FUNC(string) \ +GQuark gst_ ## string ## _error_quark (void) { \ + static GQuark quark; \ + if (!quark) \ + quark = g_quark_from_static_string ("gst-" # string "-error-quark"); \ + return quark; } + +#define FILE_A_BUG " Please file a bug at " PACKAGE_BUGREPORT "." + +static const gchar * +gst_error_get_core_error (GstCoreError code) +{ + switch (code) { + case GST_CORE_ERROR_FAILED: + return _("GStreamer encountered a general core library error."); + case GST_CORE_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_CORE_ERROR_NOT_IMPLEMENTED: + return _("Internal GStreamer error: code not implemented." FILE_A_BUG); + case GST_CORE_ERROR_STATE_CHANGE: + return _("GStreamer error: state change failed and some element failed " + "to post a proper error message with the reason for the failure."); + case GST_CORE_ERROR_PAD: + return _("Internal GStreamer error: pad problem." FILE_A_BUG); + case GST_CORE_ERROR_THREAD: + return _("Internal GStreamer error: thread problem." FILE_A_BUG); + case GST_CORE_ERROR_NEGOTIATION: + return _("GStreamer error: negotiation problem."); + case GST_CORE_ERROR_EVENT: + return _("Internal GStreamer error: event problem." FILE_A_BUG); + case GST_CORE_ERROR_SEEK: + return _("Internal GStreamer error: seek problem." FILE_A_BUG); + case GST_CORE_ERROR_CAPS: + return _("Internal GStreamer error: caps problem." FILE_A_BUG); + case GST_CORE_ERROR_TAG: + return _("Internal GStreamer error: tag problem." FILE_A_BUG); + case GST_CORE_ERROR_MISSING_PLUGIN: + return _("Your GStreamer installation is missing a plug-in."); + case GST_CORE_ERROR_CLOCK: + return _("GStreamer error: clock problem."); + case GST_CORE_ERROR_DISABLED: + return _("This application is trying to use GStreamer functionality " + "that has been disabled."); + case GST_CORE_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; +} + +static const gchar * +gst_error_get_library_error (GstLibraryError code) +{ + switch (code) { + case GST_LIBRARY_ERROR_FAILED: + return _("GStreamer encountered a general supporting library error."); + case GST_LIBRARY_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_LIBRARY_ERROR_INIT: + return _("Could not initialize supporting library."); + case GST_LIBRARY_ERROR_SHUTDOWN: + return _("Could not close supporting library."); + case GST_LIBRARY_ERROR_SETTINGS: + return _("Could not configure supporting library."); + case GST_LIBRARY_ERROR_ENCODE: + return _("Encoding error."); + case GST_LIBRARY_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; +} + +static const gchar * +gst_error_get_resource_error (GstResourceError code) +{ + switch (code) { + case GST_RESOURCE_ERROR_FAILED: + return _("GStreamer encountered a general resource error."); + case GST_RESOURCE_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_RESOURCE_ERROR_NOT_FOUND: + return _("Resource not found."); + case GST_RESOURCE_ERROR_BUSY: + return _("Resource busy or not available."); + case GST_RESOURCE_ERROR_OPEN_READ: + return _("Could not open resource for reading."); + case GST_RESOURCE_ERROR_OPEN_WRITE: + return _("Could not open resource for writing."); + case GST_RESOURCE_ERROR_OPEN_READ_WRITE: + return _("Could not open resource for reading and writing."); + case GST_RESOURCE_ERROR_CLOSE: + return _("Could not close resource."); + case GST_RESOURCE_ERROR_READ: + return _("Could not read from resource."); + case GST_RESOURCE_ERROR_WRITE: + return _("Could not write to resource."); + case GST_RESOURCE_ERROR_SEEK: + return _("Could not perform seek on resource."); + case GST_RESOURCE_ERROR_SYNC: + return _("Could not synchronize on resource."); + case GST_RESOURCE_ERROR_SETTINGS: + return _("Could not get/set settings from/on resource."); + case GST_RESOURCE_ERROR_NO_SPACE_LEFT: + return _("No space left on the resource."); + case GST_RESOURCE_ERROR_NOT_AUTHORIZED: + return _("Not authorized to access resource."); + case GST_RESOURCE_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; +} + +static const gchar * +gst_error_get_stream_error (GstStreamError code) +{ + switch (code) { + case GST_STREAM_ERROR_FAILED: + return _("GStreamer encountered a general stream error."); + case GST_STREAM_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_STREAM_ERROR_NOT_IMPLEMENTED: + return _("Element doesn't implement handling of this stream. " + "Please file a bug."); + case GST_STREAM_ERROR_TYPE_NOT_FOUND: + return _("Could not determine type of stream."); + case GST_STREAM_ERROR_WRONG_TYPE: + return _("The stream is of a different type than handled by this " + "element."); + case GST_STREAM_ERROR_CODEC_NOT_FOUND: + return _("There is no codec present that can handle the stream's type."); + case GST_STREAM_ERROR_DECODE: + return _("Could not decode stream."); + case GST_STREAM_ERROR_ENCODE: + return _("Could not encode stream."); + case GST_STREAM_ERROR_DEMUX: + return _("Could not demultiplex stream."); + case GST_STREAM_ERROR_MUX: + return _("Could not multiplex stream."); + case GST_STREAM_ERROR_FORMAT: + return _("The stream is in the wrong format."); + case GST_STREAM_ERROR_DECRYPT: + return _("The stream is encrypted and decryption is not supported."); + case GST_STREAM_ERROR_DECRYPT_NOKEY: + return _("The stream is encrypted and can't be decrypted because no " + "suitable key has been supplied."); + case GST_STREAM_ERROR_NUM_ERRORS: + default: + break; + } + + return NULL; +} + +QUARK_FUNC (core); +QUARK_FUNC (library); +QUARK_FUNC (resource); +QUARK_FUNC (stream); + +/** + * gst_error_get_message: + * @domain: the GStreamer error domain this error belongs to. + * @code: the error code belonging to the domain. + * + * Get a string describing the error message in the current locale. + * + * Returns: (transfer full): a newly allocated string describing + * the error message (in UTF-8 encoding) + */ +gchar * +gst_error_get_message (GQuark domain, gint code) +{ + const gchar *message = NULL; + + if (domain == GST_CORE_ERROR) + message = gst_error_get_core_error ((GstCoreError) code); + else if (domain == GST_LIBRARY_ERROR) + message = gst_error_get_library_error ((GstLibraryError) code); + else if (domain == GST_RESOURCE_ERROR) + message = gst_error_get_resource_error ((GstResourceError) code); + else if (domain == GST_STREAM_ERROR) + message = gst_error_get_stream_error ((GstStreamError) code); + else { + g_warning ("No error messages for domain %s", g_quark_to_string (domain)); + return g_strdup_printf (_("No error message for domain %s."), + g_quark_to_string (domain)); + } + if (message) + return g_strdup (message); + else + return + g_strdup_printf (_ + ("No standard error message for domain %s and code %d."), + g_quark_to_string (domain), code); +} diff --git a/gst/gsterror.h b/gst/gsterror.h new file mode 100644 index 0000000..59921cb --- /dev/null +++ b/gst/gsterror.h @@ -0,0 +1,261 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_ERROR_H__ +#define __GST_ERROR_H__ + +#include +#include +#include + +G_BEGIN_DECLS +/* + * we define FIXME error domains: + * GST_CORE_ERROR + * GST_LIBRARY_ERROR + * GST_RESOURCE_ERROR + * GST_STREAM_ERROR + * + * Check GError API docs for rationale for naming. + */ +/** + * GstCoreError: + * @GST_CORE_ERROR_FAILED: a general error which doesn't fit in any other + * category. Make sure you add a custom message to the error call. + * @GST_CORE_ERROR_TOO_LAZY: do not use this except as a placeholder for + * deciding where to go while developing code. + * @GST_CORE_ERROR_NOT_IMPLEMENTED: use this when you do not want to implement + * this functionality yet. + * @GST_CORE_ERROR_STATE_CHANGE: used for state change errors. + * @GST_CORE_ERROR_PAD: used for pad-related errors. + * @GST_CORE_ERROR_THREAD: used for thread-related errors. + * @GST_CORE_ERROR_NEGOTIATION: used for negotiation-related errors. + * @GST_CORE_ERROR_EVENT: used for event-related errors. + * @GST_CORE_ERROR_SEEK: used for seek-related errors. + * @GST_CORE_ERROR_CAPS: used for caps-related errors. + * @GST_CORE_ERROR_TAG: used for negotiation-related errors. + * @GST_CORE_ERROR_MISSING_PLUGIN: used if a plugin is missing. + * @GST_CORE_ERROR_CLOCK: used for clock related errors. + * @GST_CORE_ERROR_DISABLED: used if functionality has been disabled at + * compile time. + * @GST_CORE_ERROR_NUM_ERRORS: the number of core error types. + * + * Core errors are errors inside the core GStreamer library. + */ +/* FIXME: should we divide in numerical blocks so we can easily add + for example PAD errors later ? */ +typedef enum +{ + GST_CORE_ERROR_FAILED = 1, + GST_CORE_ERROR_TOO_LAZY, + GST_CORE_ERROR_NOT_IMPLEMENTED, + GST_CORE_ERROR_STATE_CHANGE, + GST_CORE_ERROR_PAD, + GST_CORE_ERROR_THREAD, + GST_CORE_ERROR_NEGOTIATION, + GST_CORE_ERROR_EVENT, + GST_CORE_ERROR_SEEK, + GST_CORE_ERROR_CAPS, + GST_CORE_ERROR_TAG, + GST_CORE_ERROR_MISSING_PLUGIN, + GST_CORE_ERROR_CLOCK, + GST_CORE_ERROR_DISABLED, + GST_CORE_ERROR_NUM_ERRORS +} GstCoreError; + +/** + * GstLibraryError: + * @GST_LIBRARY_ERROR_FAILED: a general error which doesn't fit in any other + * category. Make sure you add a custom message to the error call. + * @GST_LIBRARY_ERROR_TOO_LAZY: do not use this except as a placeholder for + * deciding where to go while developing code. + * @GST_LIBRARY_ERROR_INIT: used when the library could not be opened. + * @GST_LIBRARY_ERROR_SHUTDOWN: used when the library could not be closed. + * @GST_LIBRARY_ERROR_SETTINGS: used when the library doesn't accept settings. + * @GST_LIBRARY_ERROR_ENCODE: used when the library generated an encoding error. + * @GST_LIBRARY_ERROR_NUM_ERRORS: the number of library error types. + * + * Library errors are for errors from the library being used by elements + * (initializing, finalizing, settings, ...) + */ +typedef enum +{ + GST_LIBRARY_ERROR_FAILED = 1, + GST_LIBRARY_ERROR_TOO_LAZY, + GST_LIBRARY_ERROR_INIT, + GST_LIBRARY_ERROR_SHUTDOWN, + GST_LIBRARY_ERROR_SETTINGS, + GST_LIBRARY_ERROR_ENCODE, + GST_LIBRARY_ERROR_NUM_ERRORS +} GstLibraryError; + +/** + * GstResourceError: + * @GST_RESOURCE_ERROR_FAILED: a general error which doesn't fit in any other + * category. Make sure you add a custom message to the error call. + * @GST_RESOURCE_ERROR_TOO_LAZY: do not use this except as a placeholder for + * deciding where to go while developing code. + * @GST_RESOURCE_ERROR_NOT_FOUND: used when the resource could not be found. + * @GST_RESOURCE_ERROR_BUSY: used when resource is busy. + * @GST_RESOURCE_ERROR_OPEN_READ: used when resource fails to open for reading. + * @GST_RESOURCE_ERROR_OPEN_WRITE: used when resource fails to open for writing. + * @GST_RESOURCE_ERROR_OPEN_READ_WRITE: used when resource cannot be opened for + * both reading and writing, or either (but unspecified which). + * @GST_RESOURCE_ERROR_CLOSE: used when the resource can't be closed. + * @GST_RESOURCE_ERROR_READ: used when the resource can't be read from. + * @GST_RESOURCE_ERROR_WRITE: used when the resource can't be written to. + * @GST_RESOURCE_ERROR_SEEK: used when a seek on the resource fails. + * @GST_RESOURCE_ERROR_SYNC: used when a synchronize on the resource fails. + * @GST_RESOURCE_ERROR_SETTINGS: used when settings can't be manipulated on. + * @GST_RESOURCE_ERROR_NO_SPACE_LEFT: used when the resource has no space left. + * @GST_RESOURCE_ERROR_NOT_AUTHORIZED: used when the resource can't be opened + * due to missing authorization. + * (Since 1.2.4) + * @GST_RESOURCE_ERROR_NUM_ERRORS: the number of resource error types. + * + * Resource errors are for any resource used by an element: + * memory, files, network connections, process space, ... + * They're typically used by source and sink elements. + */ +typedef enum +{ + GST_RESOURCE_ERROR_FAILED = 1, + GST_RESOURCE_ERROR_TOO_LAZY, + GST_RESOURCE_ERROR_NOT_FOUND, + GST_RESOURCE_ERROR_BUSY, + GST_RESOURCE_ERROR_OPEN_READ, + GST_RESOURCE_ERROR_OPEN_WRITE, + GST_RESOURCE_ERROR_OPEN_READ_WRITE, + GST_RESOURCE_ERROR_CLOSE, + GST_RESOURCE_ERROR_READ, + GST_RESOURCE_ERROR_WRITE, + GST_RESOURCE_ERROR_SEEK, + GST_RESOURCE_ERROR_SYNC, + GST_RESOURCE_ERROR_SETTINGS, + GST_RESOURCE_ERROR_NO_SPACE_LEFT, + GST_RESOURCE_ERROR_NOT_AUTHORIZED, + GST_RESOURCE_ERROR_NUM_ERRORS +} GstResourceError; + +/** + * GstStreamError: + * @GST_STREAM_ERROR_FAILED: a general error which doesn't fit in any other + * category. Make sure you add a custom message to the error call. + * @GST_STREAM_ERROR_TOO_LAZY: do not use this except as a placeholder for + * deciding where to go while developing code. + * @GST_STREAM_ERROR_NOT_IMPLEMENTED: use this when you do not want to implement + * this functionality yet. + * @GST_STREAM_ERROR_TYPE_NOT_FOUND: used when the element doesn't know the + * stream's type. + * @GST_STREAM_ERROR_WRONG_TYPE: used when the element doesn't handle this type + * of stream. + * @GST_STREAM_ERROR_CODEC_NOT_FOUND: used when there's no codec to handle the + * stream's type. + * @GST_STREAM_ERROR_DECODE: used when decoding fails. + * @GST_STREAM_ERROR_ENCODE: used when encoding fails. + * @GST_STREAM_ERROR_DEMUX: used when demuxing fails. + * @GST_STREAM_ERROR_MUX: used when muxing fails. + * @GST_STREAM_ERROR_FORMAT: used when the stream is of the wrong format + * (for example, wrong caps). + * @GST_STREAM_ERROR_DECRYPT: used when the stream is encrypted and can't be + * decrypted because this is not supported by the element. + * @GST_STREAM_ERROR_DECRYPT_NOKEY: used when the stream is encrypted and + * can't be decrypted because no suitable key is available. + * @GST_STREAM_ERROR_NUM_ERRORS: the number of stream error types. + * + * Stream errors are for anything related to the stream being processed: + * format errors, media type errors, ... + * They're typically used by decoders, demuxers, converters, ... + */ +typedef enum +{ + GST_STREAM_ERROR_FAILED = 1, + GST_STREAM_ERROR_TOO_LAZY, + GST_STREAM_ERROR_NOT_IMPLEMENTED, + GST_STREAM_ERROR_TYPE_NOT_FOUND, + GST_STREAM_ERROR_WRONG_TYPE, + GST_STREAM_ERROR_CODEC_NOT_FOUND, + GST_STREAM_ERROR_DECODE, + GST_STREAM_ERROR_ENCODE, + GST_STREAM_ERROR_DEMUX, + GST_STREAM_ERROR_MUX, + GST_STREAM_ERROR_FORMAT, + GST_STREAM_ERROR_DECRYPT, + GST_STREAM_ERROR_DECRYPT_NOKEY, + GST_STREAM_ERROR_NUM_ERRORS +} GstStreamError; + +/** + * GST_LIBRARY_ERROR: + * + * Error domain for library loading. Errors in this domain will + * be from the #GstLibraryError enumeration. + * See #GError for information on error domains. + */ +#define GST_LIBRARY_ERROR gst_library_error_quark () +/** + * GST_RESOURCE_ERROR: + * + * Error domain for resource handling. Errors in this domain will + * be from the #GstResourceError enumeration. + * See #GError for information on error domains. + */ +#define GST_RESOURCE_ERROR gst_resource_error_quark () +/** + * GST_CORE_ERROR: + * + * Error domain for core system. Errors in this domain will + * be from the #GstCoreError enumeration. + * See #GError for information on error domains. + */ +#define GST_CORE_ERROR gst_core_error_quark () +/** + * GST_STREAM_ERROR: + * + * Error domain for media stream processing. Errors in this domain will + * be from the #GstStreamError enumeration. + * See #GError for information on error domains. + */ +#define GST_STREAM_ERROR gst_stream_error_quark () + +/** + * GST_ERROR_SYSTEM: + * + * Builds a string using errno describing the previously failed system + * call. To be used as the debug argument in #GST_ELEMENT_ERROR. + */ +#define GST_ERROR_SYSTEM ("system error: %s", g_strerror (errno)) + +GST_API +gchar *gst_error_get_message (GQuark domain, gint code); + +GST_API +GQuark gst_stream_error_quark (void); + +GST_API +GQuark gst_core_error_quark (void); + +GST_API +GQuark gst_resource_error_quark (void); + +GST_API +GQuark gst_library_error_quark (void); + +G_END_DECLS +#endif /* __GST_ERROR_H__ */ diff --git a/gst/gstevent.c b/gst/gstevent.c new file mode 100644 index 0000000..cb26088 --- /dev/null +++ b/gst/gstevent.c @@ -0,0 +1,2107 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstevent.c: GstEvent subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstevent + * @title: GstEvent + * @short_description: Structure describing events that are passed up and down + * a pipeline + * @see_also: #GstPad, #GstElement + * + * The event class provides factory methods to construct events for sending + * and functions to query (parse) received events. + * + * Events are usually created with gst_event_new_*() which takes event-type + * specific parameters as arguments. + * To send an event application will usually use gst_element_send_event() and + * elements will use gst_pad_send_event() or gst_pad_push_event(). + * The event should be unreffed with gst_event_unref() if it has not been sent. + * + * Events that have been received can be parsed with their respective + * gst_event_parse_*() functions. It is valid to pass %NULL for unwanted details. + * + * Events are passed between elements in parallel to the data stream. Some events + * are serialized with buffers, others are not. Some events only travel downstream, + * others only upstream. Some events can travel both upstream and downstream. + * + * The events are used to signal special conditions in the datastream such as + * EOS (end of stream) or the start of a new stream-segment. + * Events are also used to flush the pipeline of any pending data. + * + * Most of the event API is used inside plugins. Applications usually only + * construct and use seek events. + * To do that gst_event_new_seek() is used to create a seek event. It takes + * the needed parameters to specify seeking time and mode. + * |[ + * GstEvent *event; + * gboolean result; + * ... + * // construct a seek event to play the media from second 2 to 5, flush + * // the pipeline to decrease latency. + * event = gst_event_new_seek (1.0, + * GST_FORMAT_TIME, + * GST_SEEK_FLAG_FLUSH, + * GST_SEEK_TYPE_SET, 2 * GST_SECOND, + * GST_SEEK_TYPE_SET, 5 * GST_SECOND); + * ... + * result = gst_element_send_event (pipeline, event); + * if (!result) + * g_warning ("seek failed"); + * ... + * ]| + */ + + +#include "gst_private.h" +#include /* memcpy */ + +#include "gstinfo.h" +#include "gstevent.h" +#include "gstenumtypes.h" +#include "gstutils.h" +#include "gstquark.h" +#include "gstvalue.h" + +GType _gst_event_type = 0; + +typedef struct +{ + GstEvent event; + + GstStructure *structure; + gint64 running_time_offset; +} GstEventImpl; + +#define GST_EVENT_STRUCTURE(e) (((GstEventImpl *)(e))->structure) + +typedef struct +{ + const gint type; + const gchar *name; + GQuark quark; +} GstEventQuarks; + +static GstEventQuarks event_quarks[] = { + {GST_EVENT_UNKNOWN, "unknown", 0}, + {GST_EVENT_FLUSH_START, "flush-start", 0}, + {GST_EVENT_FLUSH_STOP, "flush-stop", 0}, + {GST_EVENT_SELECT_STREAMS, "select-streams", 0}, + {GST_EVENT_STREAM_START, "stream-start", 0}, + {GST_EVENT_STREAM_COLLECTION, "stream-collection", 0}, + {GST_EVENT_CAPS, "caps", 0}, + {GST_EVENT_SEGMENT, "segment", 0}, + {GST_EVENT_TAG, "tag", 0}, + {GST_EVENT_TOC, "toc", 0}, + {GST_EVENT_PROTECTION, "protection", 0}, + {GST_EVENT_BUFFERSIZE, "buffersize", 0}, + {GST_EVENT_SINK_MESSAGE, "sink-message", 0}, + {GST_EVENT_EOS, "eos", 0}, + {GST_EVENT_SEGMENT_DONE, "segment-done", 0}, + {GST_EVENT_GAP, "gap", 0}, + {GST_EVENT_QOS, "qos", 0}, + {GST_EVENT_SEEK, "seek", 0}, + {GST_EVENT_NAVIGATION, "navigation", 0}, + {GST_EVENT_LATENCY, "latency", 0}, + {GST_EVENT_STEP, "step", 0}, + {GST_EVENT_RECONFIGURE, "reconfigure", 0}, + {GST_EVENT_TOC_SELECT, "toc-select", 0}, + {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0}, + {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0}, + {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0}, + {GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, "custom-downstream-sticky", 0}, + {GST_EVENT_CUSTOM_BOTH, "custom-both", 0}, + {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0}, + {GST_EVENT_STREAM_GROUP_DONE, "stream-group-done", 0}, + + {0, NULL, 0} +}; + +GST_DEFINE_MINI_OBJECT_TYPE (GstEvent, gst_event); + +void +_priv_gst_event_initialize (void) +{ + gint i; + + _gst_event_type = gst_event_get_type (); + + g_type_class_ref (gst_seek_flags_get_type ()); + g_type_class_ref (gst_seek_type_get_type ()); + + for (i = 0; event_quarks[i].name; i++) { + event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name); + } +} + +/** + * gst_event_type_get_name: + * @type: the event type + * + * Get a printable name for the given event type. Do not modify or free. + * + * Returns: a reference to the static name of the event. + */ +const gchar * +gst_event_type_get_name (GstEventType type) +{ + gint i; + + for (i = 0; event_quarks[i].name; i++) { + if (type == event_quarks[i].type) + return event_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_event_type_to_quark: + * @type: the event type + * + * Get the unique quark for the given event type. + * + * Returns: the quark associated with the event type + */ +GQuark +gst_event_type_to_quark (GstEventType type) +{ + gint i; + + for (i = 0; event_quarks[i].name; i++) { + if (type == event_quarks[i].type) + return event_quarks[i].quark; + } + return 0; +} + +/** + * gst_event_type_get_flags: + * @type: a #GstEventType + * + * Gets the #GstEventTypeFlags associated with @type. + * + * Returns: a #GstEventTypeFlags. + */ +GstEventTypeFlags +gst_event_type_get_flags (GstEventType type) +{ + GstEventTypeFlags ret; + + ret = type & ((1 << GST_EVENT_NUM_SHIFT) - 1); + + return ret; +} + +static void +_gst_event_free (GstEvent * event) +{ + GstStructure *s; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_IS_EVENT (event)); + + GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event, + GST_EVENT_TYPE_NAME (event)); + + s = GST_EVENT_STRUCTURE (event); + + if (s) { + gst_structure_set_parent_refcount (s, NULL); + gst_structure_free (s); + } + + g_slice_free1 (sizeof (GstEventImpl), event); +} + +static void gst_event_init (GstEventImpl * event, GstEventType type); + +static GstEvent * +_gst_event_copy (GstEvent * event) +{ + GstEventImpl *copy; + GstStructure *s; + + copy = g_slice_new0 (GstEventImpl); + + gst_event_init (copy, GST_EVENT_TYPE (event)); + + GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event); + GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event); + + s = GST_EVENT_STRUCTURE (event); + if (s) { + GST_EVENT_STRUCTURE (copy) = gst_structure_copy (s); + gst_structure_set_parent_refcount (GST_EVENT_STRUCTURE (copy), + ©->event.mini_object.refcount); + } else { + GST_EVENT_STRUCTURE (copy) = NULL; + } + + ((GstEventImpl *) copy)->running_time_offset = + ((GstEventImpl *) event)->running_time_offset; + + return GST_EVENT_CAST (copy); +} + +static void +gst_event_init (GstEventImpl * event, GstEventType type) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (event), 0, _gst_event_type, + (GstMiniObjectCopyFunction) _gst_event_copy, NULL, + (GstMiniObjectFreeFunction) _gst_event_free); + + GST_EVENT_TYPE (event) = type; + GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE; + GST_EVENT_SEQNUM (event) = gst_util_seqnum_next (); + event->running_time_offset = 0; +} + + +/** + * gst_event_new_custom: + * @type: The type of the new event + * @structure: (transfer full): the structure for the event. The event will + * take ownership of the structure. + * + * Create a new custom-typed event. This can be used for anything not + * handled by other event-specific functions to pass an event to another + * element. + * + * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro, + * assigning a free number and filling in the correct direction and + * serialization flags. + * + * New custom events can also be created by subclassing the event type if + * needed. + * + * Returns: (transfer full) (nullable): the new custom event. + */ +GstEvent * +gst_event_new_custom (GstEventType type, GstStructure * structure) +{ + GstEventImpl *event; + + event = g_slice_new0 (GstEventImpl); + + GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event, + gst_event_type_get_name (type), type); + + if (structure) { + /* structure must not have a parent */ + if (!gst_structure_set_parent_refcount (structure, + &event->event.mini_object.refcount)) + goto had_parent; + + } + gst_event_init (event, type); + + GST_EVENT_STRUCTURE (event) = structure; + + return GST_EVENT_CAST (event); + + /* ERRORS */ +had_parent: + { + g_slice_free1 (sizeof (GstEventImpl), event); + g_warning ("structure is already owned by another object"); + return NULL; + } +} + +/** + * gst_event_get_structure: + * @event: The #GstEvent. + * + * Access the structure of the event. + * + * Returns: (transfer none) (nullable): The structure of the event. The + * structure is still owned by the event, which means that you should not free + * it and that the pointer becomes invalid when you free the event. + * + * MT safe. + */ +const GstStructure * +gst_event_get_structure (GstEvent * event) +{ + g_return_val_if_fail (GST_IS_EVENT (event), NULL); + + return GST_EVENT_STRUCTURE (event); +} + +/** + * gst_event_writable_structure: + * @event: The #GstEvent. + * + * Get a writable version of the structure. + * + * Returns: (transfer none): The structure of the event. The structure + * is still owned by the event, which means that you should not free + * it and that the pointer becomes invalid when you free the event. + * This function checks if @event is writable and will never return + * %NULL. + * + * MT safe. + */ +GstStructure * +gst_event_writable_structure (GstEvent * event) +{ + GstStructure *structure; + + g_return_val_if_fail (GST_IS_EVENT (event), NULL); + g_return_val_if_fail (gst_event_is_writable (event), NULL); + + structure = GST_EVENT_STRUCTURE (event); + + if (structure == NULL) { + structure = + gst_structure_new_id_empty (gst_event_type_to_quark (GST_EVENT_TYPE + (event))); + gst_structure_set_parent_refcount (structure, &event->mini_object.refcount); + GST_EVENT_STRUCTURE (event) = structure; + } + return structure; +} + +/** + * gst_event_has_name: + * @event: The #GstEvent. + * @name: name to check + * + * Checks if @event has the given @name. This function is usually used to + * check the name of a custom event. + * + * Returns: %TRUE if @name matches the name of the event structure. + */ +gboolean +gst_event_has_name (GstEvent * event, const gchar * name) +{ + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + + if (GST_EVENT_STRUCTURE (event) == NULL) + return FALSE; + + return gst_structure_has_name (GST_EVENT_STRUCTURE (event), name); +} + +/** + * gst_event_get_seqnum: + * @event: A #GstEvent. + * + * Retrieve the sequence number of a event. + * + * Events have ever-incrementing sequence numbers, which may also be set + * explicitly via gst_event_set_seqnum(). Sequence numbers are typically used to + * indicate that a event corresponds to some other set of events or messages, + * for example an EOS event corresponding to a SEEK event. It is considered good + * practice to make this correspondence when possible, though it is not + * required. + * + * Note that events and messages share the same sequence number incrementor; + * two events or messages will never have the same sequence number unless + * that correspondence was made explicitly. + * + * Returns: The event's sequence number. + * + * MT safe. + */ +guint32 +gst_event_get_seqnum (GstEvent * event) +{ + g_return_val_if_fail (GST_IS_EVENT (event), -1); + + return GST_EVENT_SEQNUM (event); +} + +/** + * gst_event_set_seqnum: + * @event: A #GstEvent. + * @seqnum: A sequence number. + * + * Set the sequence number of a event. + * + * This function might be called by the creator of a event to indicate that the + * event relates to other events or messages. See gst_event_get_seqnum() for + * more information. + * + * MT safe. + */ +void +gst_event_set_seqnum (GstEvent * event, guint32 seqnum) +{ + g_return_if_fail (GST_IS_EVENT (event)); + + GST_EVENT_SEQNUM (event) = seqnum; +} + +/** + * gst_event_get_running_time_offset: + * @event: A #GstEvent. + * + * Retrieve the accumulated running time offset of the event. + * + * Events passing through #GstPads that have a running time + * offset set via gst_pad_set_offset() will get their offset + * adjusted according to the pad's offset. + * + * If the event contains any information that related to the + * running time, this information will need to be updated + * before usage with this offset. + * + * Returns: The event's running time offset + * + * MT safe. + * + * Since: 1.4 + */ +gint64 +gst_event_get_running_time_offset (GstEvent * event) +{ + g_return_val_if_fail (GST_IS_EVENT (event), 0); + + return ((GstEventImpl *) event)->running_time_offset; +} + +/** + * gst_event_set_running_time_offset: + * @event: A #GstEvent. + * @offset: A the new running time offset + * + * Set the running time offset of a event. See + * gst_event_get_running_time_offset() for more information. + * + * MT safe. + * + * Since: 1.4 + */ +void +gst_event_set_running_time_offset (GstEvent * event, gint64 offset) +{ + g_return_if_fail (GST_IS_EVENT (event)); + + ((GstEventImpl *) event)->running_time_offset = offset; +} + +/** + * gst_event_new_flush_start: + * + * Allocate a new flush start event. The flush start event can be sent + * upstream and downstream and travels out-of-bounds with the dataflow. + * + * It marks pads as being flushing and will make them return + * #GST_FLOW_FLUSHING when used for data flow with gst_pad_push(), + * gst_pad_chain(), gst_pad_get_range() and gst_pad_pull_range(). + * Any event (except a #GST_EVENT_FLUSH_STOP) received + * on a flushing pad will return %FALSE immediately. + * + * Elements should unlock any blocking functions and exit their streaming + * functions as fast as possible when this event is received. + * + * This event is typically generated after a seek to flush out all queued data + * in the pipeline so that the new media is played as soon as possible. + * + * Returns: (transfer full): a new flush start event. + */ +GstEvent * +gst_event_new_flush_start (void) +{ + return gst_event_new_custom (GST_EVENT_FLUSH_START, NULL); +} + +/** + * gst_event_new_flush_stop: + * @reset_time: if time should be reset + * + * Allocate a new flush stop event. The flush stop event can be sent + * upstream and downstream and travels serialized with the dataflow. + * It is typically sent after sending a FLUSH_START event to make the + * pads accept data again. + * + * Elements can process this event synchronized with the dataflow since + * the preceding FLUSH_START event stopped the dataflow. + * + * This event is typically generated to complete a seek and to resume + * dataflow. + * + * Returns: (transfer full): a new flush stop event. + */ +GstEvent * +gst_event_new_flush_stop (gboolean reset_time) +{ + GstEvent *event; + + GST_CAT_INFO (GST_CAT_EVENT, "creating flush stop %d", reset_time); + + event = gst_event_new_custom (GST_EVENT_FLUSH_STOP, + gst_structure_new_id (GST_QUARK (EVENT_FLUSH_STOP), + GST_QUARK (RESET_TIME), G_TYPE_BOOLEAN, reset_time, NULL)); + + return event; +} + +/** + * gst_event_parse_flush_stop: + * @event: The event to parse + * @reset_time: (out): if time should be reset + * + * Parse the FLUSH_STOP event and retrieve the @reset_time member. + */ +void +gst_event_parse_flush_stop (GstEvent * event, gboolean * reset_time) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP); + + structure = GST_EVENT_STRUCTURE (event); + if (G_LIKELY (reset_time)) + *reset_time = + g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (RESET_TIME))); +} + +/** + * gst_event_new_select_streams: + * @streams: (element-type utf8) (transfer none): the list of streams to + * activate + * + * Allocate a new select-streams event. + * + * The select-streams event requests the specified @streams to be activated. + * + * The list of @streams corresponds to the "Stream ID" of each stream to be + * activated. Those ID can be obtained via the #GstStream objects present + * in #GST_EVENT_STREAM_START, #GST_EVENT_STREAM_COLLECTION or + * #GST_MESSAGE_STREAM_COLLECTION. + * + * Note: The list of @streams can not be empty. + * + * Returns: (transfer full): a new select-streams event or %NULL in case of + * an error (like an empty streams list). + * + * Since: 1.10 + */ +GstEvent * +gst_event_new_select_streams (GList * streams) +{ + GstEvent *event; + GValue val = G_VALUE_INIT; + GstStructure *struc; + GList *tmpl; + + g_return_val_if_fail (streams != NULL, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "Creating new select-streams event"); + struc = gst_structure_new_id_empty (GST_QUARK (EVENT_SELECT_STREAMS)); + g_value_init (&val, GST_TYPE_LIST); + /* Fill struc with streams */ + for (tmpl = streams; tmpl; tmpl = tmpl->next) { + GValue strval = G_VALUE_INIT; + const gchar *str = (const gchar *) tmpl->data; + g_value_init (&strval, G_TYPE_STRING); + g_value_set_string (&strval, str); + gst_value_list_append_and_take_value (&val, &strval); + } + gst_structure_id_take_value (struc, GST_QUARK (STREAMS), &val); + event = gst_event_new_custom (GST_EVENT_SELECT_STREAMS, struc); + + return event; +} + +/** + * gst_event_parse_select_streams: + * @event: The event to parse + * @streams: (out) (element-type utf8) (transfer full): the streams + * + * Parse the SELECT_STREAMS event and retrieve the contained streams. + * + * Since: 1.10 + */ +void +gst_event_parse_select_streams (GstEvent * event, GList ** streams) +{ + GstStructure *structure; + GList *res = NULL; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SELECT_STREAMS); + + structure = GST_EVENT_STRUCTURE (event); + if (G_LIKELY (streams)) { + const GValue *vlist = + gst_structure_id_get_value (structure, GST_QUARK (STREAMS)); + guint i, sz = gst_value_list_get_size (vlist); + for (i = 0; i < sz; i++) { + const GValue *strv = gst_value_list_get_value (vlist, i); + res = g_list_append (res, g_value_dup_string (strv)); + } + *streams = res; + } +} + + +/** + * gst_event_new_stream_group_done: + * @group_id: the group id of the stream group which is ending + * + * Create a new Stream Group Done event. The stream-group-done event can + * only travel downstream synchronized with the buffer flow. Elements + * that receive the event on a pad should handle it mostly like EOS, + * and emit any data or pending buffers that would depend on more data + * arriving and unblock, since there won't be any more data. + * + * This event is followed by EOS at some point in the future, and is + * generally used when switching pads - to unblock downstream so that + * new pads can be exposed before sending EOS on the existing pads. + * + * Returns: (transfer full): the new stream-group-done event. + * + * Since: 1.10 + */ +GstEvent * +gst_event_new_stream_group_done (guint group_id) +{ + GstStructure *s; + + s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_GROUP_DONE), + GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL); + + return gst_event_new_custom (GST_EVENT_STREAM_GROUP_DONE, s); +} + +/** + * gst_event_parse_stream_group_done: + * @event: a stream-group-done event. + * @group_id: (out): address of variable to store the group id into + * + * Parse a stream-group-done @event and store the result in the given + * @group_id location. + * + * Since: 1.10 + */ +void +gst_event_parse_stream_group_done (GstEvent * event, guint * group_id) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE); + + if (group_id) { + gst_structure_id_get (GST_EVENT_STRUCTURE (event), + GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL); + } +} + +/** + * gst_event_new_eos: + * + * Create a new EOS event. The eos event can only travel downstream + * synchronized with the buffer flow. Elements that receive the EOS + * event on a pad can return #GST_FLOW_EOS as a #GstFlowReturn + * when data after the EOS event arrives. + * + * The EOS event will travel down to the sink elements in the pipeline + * which will then post the #GST_MESSAGE_EOS on the bus after they have + * finished playing any buffered data. + * + * When all sinks have posted an EOS message, an EOS message is + * forwarded to the application. + * + * The EOS event itself will not cause any state transitions of the pipeline. + * + * Returns: (transfer full): the new EOS event. + */ +GstEvent * +gst_event_new_eos (void) +{ + return gst_event_new_custom (GST_EVENT_EOS, NULL); +} + +/** + * gst_event_new_gap: + * @timestamp: the start time (pts) of the gap + * @duration: the duration of the gap + * + * Create a new GAP event. A gap event can be thought of as conceptually + * equivalent to a buffer to signal that there is no data for a certain + * amount of time. This is useful to signal a gap to downstream elements + * which may wait for data, such as muxers or mixers or overlays, especially + * for sparse streams such as subtitle streams. + * + * Returns: (transfer full): the new GAP event. + */ +GstEvent * +gst_event_new_gap (GstClockTime timestamp, GstClockTime duration) +{ + GstEvent *event; + + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); + + GST_CAT_TRACE (GST_CAT_EVENT, "creating gap %" GST_TIME_FORMAT " - " + "%" GST_TIME_FORMAT " (duration: %" GST_TIME_FORMAT ")", + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (timestamp + duration), + GST_TIME_ARGS (duration)); + + event = gst_event_new_custom (GST_EVENT_GAP, + gst_structure_new_id (GST_QUARK (EVENT_GAP), + GST_QUARK (TIMESTAMP), GST_TYPE_CLOCK_TIME, timestamp, + GST_QUARK (DURATION), GST_TYPE_CLOCK_TIME, duration, NULL)); + + return event; +} + +/** + * gst_event_parse_gap: + * @event: a #GstEvent of type #GST_EVENT_GAP + * @timestamp: (out) (allow-none): location where to store the + * start time (pts) of the gap, or %NULL + * @duration: (out) (allow-none): location where to store the duration of + * the gap, or %NULL + * + * Extract timestamp and duration from a new GAP event. + */ +void +gst_event_parse_gap (GstEvent * event, GstClockTime * timestamp, + GstClockTime * duration) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_GAP); + + structure = GST_EVENT_STRUCTURE (event); + gst_structure_id_get (structure, + GST_QUARK (TIMESTAMP), GST_TYPE_CLOCK_TIME, timestamp, + GST_QUARK (DURATION), GST_TYPE_CLOCK_TIME, duration, NULL); +} + +/** + * gst_event_new_caps: + * @caps: (transfer none): a #GstCaps + * + * Create a new CAPS event for @caps. The caps event can only travel downstream + * synchronized with the buffer flow and contains the format of the buffers + * that will follow after the event. + * + * Returns: (transfer full) (nullable): the new CAPS event. + */ +GstEvent * +gst_event_new_caps (GstCaps * caps) +{ + GstEvent *event; + + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating caps event %" GST_PTR_FORMAT, caps); + + event = gst_event_new_custom (GST_EVENT_CAPS, + gst_structure_new_id (GST_QUARK (EVENT_CAPS), + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL)); + + return event; +} + +/** + * gst_event_parse_caps: + * @event: The event to parse + * @caps: (out) (transfer none): A pointer to the caps + * + * Get the caps from @event. The caps remains valid as long as @event remains + * valid. + */ +void +gst_event_parse_caps (GstEvent * event, GstCaps ** caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + + structure = GST_EVENT_STRUCTURE (event); + if (G_LIKELY (caps)) + *caps = + g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); +} + +/** + * gst_event_new_segment: + * @segment: (transfer none): a #GstSegment + * + * Create a new SEGMENT event for @segment. The segment event can only travel + * downstream synchronized with the buffer flow and contains timing information + * and playback properties for the buffers that will follow. + * + * The segment event marks the range of buffers to be processed. All + * data not within the segment range is not to be processed. This can be + * used intelligently by plugins to apply more efficient methods of skipping + * unneeded data. The valid range is expressed with the @start and @stop + * values. + * + * The time value of the segment is used in conjunction with the start + * value to convert the buffer timestamps into the stream time. This is + * usually done in sinks to report the current stream_time. + * @time represents the stream_time of a buffer carrying a timestamp of + * @start. @time cannot be -1. + * + * @start cannot be -1, @stop can be -1. If there + * is a valid @stop given, it must be greater or equal the @start, including + * when the indicated playback @rate is < 0. + * + * The @applied_rate value provides information about any rate adjustment that + * has already been made to the timestamps and content on the buffers of the + * stream. (@rate * @applied_rate) should always equal the rate that has been + * requested for playback. For example, if an element has an input segment + * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust + * incoming timestamps and buffer content by half and output a segment event + * with @rate of 1.0 and @applied_rate of 2.0 + * + * After a segment event, the buffer stream time is calculated with: + * + * time + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate) + * + * Returns: (transfer full) (nullable): the new SEGMENT event. + */ +GstEvent * +gst_event_new_segment (const GstSegment * segment) +{ + GstEvent *event; + + g_return_val_if_fail (segment != NULL, NULL); + g_return_val_if_fail (segment->rate != 0.0, NULL); + g_return_val_if_fail (segment->applied_rate != 0.0, NULL); + g_return_val_if_fail (segment->format != GST_FORMAT_UNDEFINED, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating segment event %" GST_SEGMENT_FORMAT, + segment); + + event = gst_event_new_custom (GST_EVENT_SEGMENT, + gst_structure_new_id (GST_QUARK (EVENT_SEGMENT), + GST_QUARK (SEGMENT), GST_TYPE_SEGMENT, segment, NULL)); + + return event; +} + +/** + * gst_event_parse_segment: + * @event: The event to parse + * @segment: (out) (transfer none): a pointer to a #GstSegment + * + * Parses a segment @event and stores the result in the given @segment location. + * @segment remains valid only until the @event is freed. Don't modify the segment + * and make a copy if you want to modify it or store it for later use. + */ +void +gst_event_parse_segment (GstEvent * event, const GstSegment ** segment) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + + if (segment) { + structure = GST_EVENT_STRUCTURE (event); + *segment = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (SEGMENT))); + } +} + +/** + * gst_event_copy_segment: + * @event: The event to parse + * @segment: a pointer to a #GstSegment + * + * Parses a segment @event and copies the #GstSegment into the location + * given by @segment. + */ +void +gst_event_copy_segment (GstEvent * event, GstSegment * segment) +{ + const GstSegment *src; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + + if (segment) { + gst_event_parse_segment (event, &src); + gst_segment_copy_into (src, segment); + } +} + +/** + * gst_event_new_tag: + * @taglist: (transfer full): metadata list. The event will take ownership + * of the taglist. + * + * Generates a metadata tag event from the given @taglist. + * + * The scope of the taglist specifies if the taglist applies to the + * complete medium or only to this specific stream. As the tag event + * is a sticky event, elements should merge tags received from + * upstream with a given scope with their own tags with the same + * scope and create a new tag event from it. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_tag (GstTagList * taglist) +{ + GstStructure *s; + GValue val = G_VALUE_INIT; + const gchar *names[] = { "GstTagList-stream", "GstTagList-global" }; + + g_return_val_if_fail (taglist != NULL, NULL); + + s = gst_structure_new_empty (names[gst_tag_list_get_scope (taglist)]); + g_value_init (&val, GST_TYPE_TAG_LIST); + g_value_take_boxed (&val, taglist); + gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val); + return gst_event_new_custom (GST_EVENT_TAG, s); +} + +/** + * gst_event_parse_tag: + * @event: a tag event + * @taglist: (out) (transfer none): pointer to metadata list + * + * Parses a tag @event and stores the results in the given @taglist location. + * No reference to the taglist will be returned, it remains valid only until + * the @event is freed. Don't modify or free the taglist, make a copy if you + * want to modify it or store it for later use. + */ +void +gst_event_parse_tag (GstEvent * event, GstTagList ** taglist) +{ + const GValue *val; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG); + + val = gst_structure_id_get_value (GST_EVENT_STRUCTURE (event), + GST_QUARK (TAGLIST)); + + if (taglist) + *taglist = (GstTagList *) g_value_get_boxed (val); +} + +/* buffersize event */ +/** + * gst_event_new_buffer_size: + * @format: buffer format + * @minsize: minimum buffer size + * @maxsize: maximum buffer size + * @async: thread behavior + * + * Create a new buffersize event. The event is sent downstream and notifies + * elements that they should provide a buffer of the specified dimensions. + * + * When the @async flag is set, a thread boundary is preferred. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_buffer_size (GstFormat format, gint64 minsize, + gint64 maxsize, gboolean async) +{ + GstEvent *event; + GstStructure *structure; + + GST_CAT_INFO (GST_CAT_EVENT, + "creating buffersize format %s, minsize %" G_GINT64_FORMAT + ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format), + minsize, maxsize, async); + + structure = gst_structure_new_id (GST_QUARK (EVENT_BUFFER_SIZE), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (MINSIZE), G_TYPE_INT64, minsize, + GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize, + GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL); + event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure); + + return event; +} + +/** + * gst_event_parse_buffer_size: + * @event: The event to query + * @format: (out): A pointer to store the format in + * @minsize: (out): A pointer to store the minsize in + * @maxsize: (out): A pointer to store the maxsize in + * @async: (out): A pointer to store the async-flag in + * + * Get the format, minsize, maxsize and async-flag in the buffersize event. + */ +void +gst_event_parse_buffer_size (GstEvent * event, GstFormat * format, + gint64 * minsize, gint64 * maxsize, gboolean * async) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE); + + structure = GST_EVENT_STRUCTURE (event); + if (format) + *format = (GstFormat) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (minsize) + *minsize = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (MINSIZE))); + if (maxsize) + *maxsize = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (MAXSIZE))); + if (async) + *async = + g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (ASYNC))); +} + +/** + * gst_event_new_qos: + * @type: the QoS type + * @proportion: the proportion of the qos message + * @diff: The time difference of the last Clock sync + * @timestamp: The timestamp of the buffer + * + * Allocate a new qos event with the given values. + * The QOS event is generated in an element that wants an upstream + * element to either reduce or increase its rate because of + * high/low CPU load or other resource usage such as network performance or + * throttling. Typically sinks generate these events for each buffer + * they receive. + * + * @type indicates the reason for the QoS event. #GST_QOS_TYPE_OVERFLOW is + * used when a buffer arrived in time or when the sink cannot keep up with + * the upstream datarate. #GST_QOS_TYPE_UNDERFLOW is when the sink is not + * receiving buffers fast enough and thus has to drop late buffers. + * #GST_QOS_TYPE_THROTTLE is used when the datarate is artificially limited + * by the application, for example to reduce power consumption. + * + * @proportion indicates the real-time performance of the streaming in the + * element that generated the QoS event (usually the sink). The value is + * generally computed based on more long term statistics about the streams + * timestamps compared to the clock. + * A value < 1.0 indicates that the upstream element is producing data faster + * than real-time. A value > 1.0 indicates that the upstream element is not + * producing data fast enough. 1.0 is the ideal @proportion value. The + * proportion value can safely be used to lower or increase the quality of + * the element. + * + * @diff is the difference against the clock in running time of the last + * buffer that caused the element to generate the QOS event. A negative value + * means that the buffer with @timestamp arrived in time. A positive value + * indicates how late the buffer with @timestamp was. When throttling is + * enabled, @diff will be set to the requested throttling interval. + * + * @timestamp is the timestamp of the last buffer that cause the element + * to generate the QOS event. It is expressed in running time and thus an ever + * increasing value. + * + * The upstream element can use the @diff and @timestamp values to decide + * whether to process more buffers. For positive @diff, all buffers with + * timestamp <= @timestamp + @diff will certainly arrive late in the sink + * as well. A (negative) @diff value so that @timestamp + @diff would yield a + * result smaller than 0 is not allowed. + * + * The application can use general event probes to intercept the QoS + * event and implement custom application specific QoS handling. + * + * Returns: (transfer full) (nullable): a new QOS event. + */ +GstEvent * +gst_event_new_qos (GstQOSType type, gdouble proportion, + GstClockTimeDiff diff, GstClockTime timestamp) +{ + GstEvent *event; + GstStructure *structure; + + /* diff must be positive or timestamp + diff must be positive */ + g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL); + + GST_CAT_LOG (GST_CAT_EVENT, + "creating qos type %d, proportion %lf, diff %" G_GINT64_FORMAT + ", timestamp %" GST_TIME_FORMAT, type, proportion, + diff, GST_TIME_ARGS (timestamp)); + + structure = gst_structure_new_id (GST_QUARK (EVENT_QOS), + GST_QUARK (TYPE), GST_TYPE_QOS_TYPE, type, + GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion, + GST_QUARK (DIFF), G_TYPE_INT64, diff, + GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL); + event = gst_event_new_custom (GST_EVENT_QOS, structure); + + return event; +} + +/** + * gst_event_parse_qos: + * @event: The event to query + * @type: (out): A pointer to store the QoS type in + * @proportion: (out): A pointer to store the proportion in + * @diff: (out): A pointer to store the diff in + * @timestamp: (out): A pointer to store the timestamp in + * + * Get the type, proportion, diff and timestamp in the qos event. See + * gst_event_new_qos() for more information about the different QoS values. + * + * @timestamp will be adjusted for any pad offsets of pads it was passing through. + */ +void +gst_event_parse_qos (GstEvent * event, GstQOSType * type, + gdouble * proportion, GstClockTimeDiff * diff, GstClockTime * timestamp) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS); + + structure = GST_EVENT_STRUCTURE (event); + if (type) + *type = (GstQOSType) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (TYPE))); + if (proportion) + *proportion = + g_value_get_double (gst_structure_id_get_value (structure, + GST_QUARK (PROPORTION))); + if (diff) + *diff = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (DIFF))); + if (timestamp) { + gint64 offset = gst_event_get_running_time_offset (event); + GstClockTimeDiff diff_ = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (DIFF))); + + *timestamp = + g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (TIMESTAMP))); + /* Catch underflows */ + if (*timestamp > -offset) + *timestamp += offset; + else + *timestamp = 0; + + /* Make sure that timestamp + diff is always >= 0. Because + * of the running time offset this might not be true */ + if (diff_ < 0 && *timestamp < -diff_) + *timestamp = (GstClockTime) - diff_; + } +} + +/** + * gst_event_new_seek: + * @rate: The new playback rate + * @format: The format of the seek values + * @flags: The optional seek flags + * @start_type: The type and flags for the new start position + * @start: The value of the new start position + * @stop_type: The type and flags for the new stop position + * @stop: The value of the new stop position + * + * Allocate a new seek event with the given parameters. + * + * The seek event configures playback of the pipeline between @start to @stop + * at the speed given in @rate, also called a playback segment. + * The @start and @stop values are expressed in @format. + * + * A @rate of 1.0 means normal playback rate, 2.0 means double speed. + * Negatives values means backwards playback. A value of 0.0 for the + * rate is not allowed and should be accomplished instead by PAUSING the + * pipeline. + * + * A pipeline has a default playback segment configured with a start + * position of 0, a stop position of -1 and a rate of 1.0. The currently + * configured playback segment can be queried with #GST_QUERY_SEGMENT. + * + * @start_type and @stop_type specify how to adjust the currently configured + * start and stop fields in playback segment. Adjustments can be made relative + * or absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE + * means that the position should not be updated. + * + * When the rate is positive and @start has been updated, playback will start + * from the newly configured start position. + * + * For negative rates, playback will start from the newly configured stop + * position (if any). If the stop position is updated, it must be different from + * -1 (#GST_CLOCK_TIME_NONE) for negative rates. + * + * It is not possible to seek relative to the current playback position, to do + * this, PAUSE the pipeline, query the current playback position with + * #GST_QUERY_POSITION and update the playback segment current position with a + * #GST_SEEK_TYPE_SET to the desired position. + * + * Returns: (transfer full) (nullable): a new seek event. + */ +GstEvent * +gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags, + GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop) +{ + GstEvent *event; + GstStructure *structure; + + g_return_val_if_fail (rate != 0.0, NULL); + + if (format == GST_FORMAT_TIME) { + GST_CAT_INFO (GST_CAT_EVENT, + "creating seek rate %lf, format TIME, flags %d, " + "start_type %d, start %" GST_TIME_FORMAT ", " + "stop_type %d, stop %" GST_TIME_FORMAT, + rate, flags, start_type, GST_TIME_ARGS (start), + stop_type, GST_TIME_ARGS (stop)); + } else { + GST_CAT_INFO (GST_CAT_EVENT, + "creating seek rate %lf, format %s, flags %d, " + "start_type %d, start %" G_GINT64_FORMAT ", " + "stop_type %d, stop %" G_GINT64_FORMAT, + rate, gst_format_get_name (format), flags, start_type, start, stop_type, + stop); + } + + structure = gst_structure_new_id (GST_QUARK (EVENT_SEEK), + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags, + GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type, + GST_QUARK (CUR), G_TYPE_INT64, start, + GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type, + GST_QUARK (STOP), G_TYPE_INT64, stop, NULL); + event = gst_event_new_custom (GST_EVENT_SEEK, structure); + + return event; +} + +/** + * gst_event_parse_seek: + * @event: a seek event + * @rate: (out): result location for the rate + * @format: (out): result location for the stream format + * @flags: (out): result location for the #GstSeekFlags + * @start_type: (out): result location for the #GstSeekType of the start position + * @start: (out): result location for the start position expressed in @format + * @stop_type: (out): result location for the #GstSeekType of the stop position + * @stop: (out): result location for the stop position expressed in @format + * + * Parses a seek @event and stores the results in the given result locations. + */ +void +gst_event_parse_seek (GstEvent * event, gdouble * rate, + GstFormat * format, GstSeekFlags * flags, GstSeekType * start_type, + gint64 * start, GstSeekType * stop_type, gint64 * stop) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK); + + structure = GST_EVENT_STRUCTURE (event); + if (rate) + *rate = + g_value_get_double (gst_structure_id_get_value (structure, + GST_QUARK (RATE))); + if (format) + *format = (GstFormat) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (flags) + *flags = (GstSeekFlags) + g_value_get_flags (gst_structure_id_get_value (structure, + GST_QUARK (FLAGS))); + if (start_type) + *start_type = (GstSeekType) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (CUR_TYPE))); + if (start) + *start = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (CUR))); + if (stop_type) + *stop_type = (GstSeekType) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (STOP_TYPE))); + if (stop) + *stop = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (STOP))); +} + +/** + * gst_event_new_navigation: + * @structure: (transfer full): description of the event. The event will take + * ownership of the structure. + * + * Create a new navigation event from the given description. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_navigation (GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, NULL); + + return gst_event_new_custom (GST_EVENT_NAVIGATION, structure); +} + +/** + * gst_event_new_latency: + * @latency: the new latency value + * + * Create a new latency event. The event is sent upstream from the sinks and + * notifies elements that they should add an additional @latency to the + * running time before synchronising against the clock. + * + * The latency is mostly used in live sinks and is always expressed in + * the time format. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_latency (GstClockTime latency) +{ + GstEvent *event; + GstStructure *structure; + + GST_CAT_INFO (GST_CAT_EVENT, + "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); + + structure = gst_structure_new_id (GST_QUARK (EVENT_LATENCY), + GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL); + event = gst_event_new_custom (GST_EVENT_LATENCY, structure); + + return event; +} + +/** + * gst_event_parse_latency: + * @event: The event to query + * @latency: (out): A pointer to store the latency in. + * + * Get the latency in the latency event. + */ +void +gst_event_parse_latency (GstEvent * event, GstClockTime * latency) +{ + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_LATENCY); + + if (latency) + *latency = + g_value_get_uint64 (gst_structure_id_get_value (GST_EVENT_STRUCTURE + (event), GST_QUARK (LATENCY))); +} + +/** + * gst_event_new_step: + * @format: the format of @amount + * @amount: the amount of data to step + * @rate: the step rate + * @flush: flushing steps + * @intermediate: intermediate steps + * + * Create a new step event. The purpose of the step event is to instruct a sink + * to skip @amount (expressed in @format) of media. It can be used to implement + * stepping through the video frame by frame or for doing fast trick modes. + * + * A rate of <= 0.0 is not allowed. Pause the pipeline, for the effect of rate + * = 0.0 or first reverse the direction of playback using a seek event to get + * the same effect as rate < 0.0. + * + * The @flush flag will clear any pending data in the pipeline before starting + * the step operation. + * + * The @intermediate flag instructs the pipeline that this step operation is + * part of a larger step operation. + * + * Returns: (transfer full) (nullable): a new #GstEvent + */ +GstEvent * +gst_event_new_step (GstFormat format, guint64 amount, gdouble rate, + gboolean flush, gboolean intermediate) +{ + GstEvent *event; + GstStructure *structure; + + g_return_val_if_fail (rate > 0.0, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating step event"); + + structure = gst_structure_new_id (GST_QUARK (EVENT_STEP), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (AMOUNT), G_TYPE_UINT64, amount, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush, + GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL); + event = gst_event_new_custom (GST_EVENT_STEP, structure); + + return event; +} + +/** + * gst_event_parse_step: + * @event: The event to query + * @format: (out) (allow-none): a pointer to store the format in + * @amount: (out) (allow-none): a pointer to store the amount in + * @rate: (out) (allow-none): a pointer to store the rate in + * @flush: (out) (allow-none): a pointer to store the flush boolean in + * @intermediate: (out) (allow-none): a pointer to store the intermediate + * boolean in + * + * Parse the step event. + */ +void +gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount, + gdouble * rate, gboolean * flush, gboolean * intermediate) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP); + + structure = GST_EVENT_STRUCTURE (event); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (amount) + *amount = g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (AMOUNT))); + if (rate) + *rate = g_value_get_double (gst_structure_id_get_value (structure, + GST_QUARK (RATE))); + if (flush) + *flush = g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (FLUSH))); + if (intermediate) + *intermediate = g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (INTERMEDIATE))); +} + +/** + * gst_event_new_reconfigure: + + * Create a new reconfigure event. The purpose of the reconfigure event is + * to travel upstream and make elements renegotiate their caps or reconfigure + * their buffer pools. This is useful when changing properties on elements + * or changing the topology of the pipeline. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_reconfigure (void) +{ + GstEvent *event; + + GST_CAT_INFO (GST_CAT_EVENT, "creating reconfigure event"); + + event = gst_event_new_custom (GST_EVENT_RECONFIGURE, NULL); + + return event; +} + +/** + * gst_event_new_sink_message: + * @name: a name for the event + * @msg: (transfer none): the #GstMessage to be posted + * + * Create a new sink-message event. The purpose of the sink-message event is + * to instruct a sink to post the message contained in the event synchronized + * with the stream. + * + * @name is used to store multiple sticky events on one pad. + * + * Returns: (transfer full): a new #GstEvent + */ +/* FIXME 2.0: take ownership of msg for consistency? */ +GstEvent * +gst_event_new_sink_message (const gchar * name, GstMessage * msg) +{ + GstEvent *event; + GstStructure *structure; + + g_return_val_if_fail (msg != NULL, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating sink-message event"); + + structure = gst_structure_new_id (g_quark_from_string (name), + GST_QUARK (MESSAGE), GST_TYPE_MESSAGE, msg, NULL); + event = gst_event_new_custom (GST_EVENT_SINK_MESSAGE, structure); + + return event; +} + +/** + * gst_event_parse_sink_message: + * @event: The event to query + * @msg: (out) (transfer full): a pointer to store the #GstMessage in. + * + * Parse the sink-message event. Unref @msg after usage. + */ +void +gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg) +{ + const GstStructure *structure; + + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE); + + structure = GST_EVENT_STRUCTURE (event); + if (msg) + *msg = + GST_MESSAGE (g_value_dup_boxed (gst_structure_id_get_value + (structure, GST_QUARK (MESSAGE)))); +} + +/** + * gst_event_new_stream_start: + * @stream_id: Identifier for this stream + * + * Create a new STREAM_START event. The stream start event can only + * travel downstream synchronized with the buffer flow. It is expected + * to be the first event that is sent for a new stream. + * + * Source elements, demuxers and other elements that create new streams + * are supposed to send this event as the first event of a new stream. It + * should not be sent after a flushing seek or in similar situations + * and is used to mark the beginning of a new logical stream. Elements + * combining multiple streams must ensure that this event is only forwarded + * downstream once and not for every single input stream. + * + * The @stream_id should be a unique string that consists of the upstream + * stream-id, / as separator and a unique stream-id for this specific + * stream. A new stream-id should only be created for a stream if the upstream + * stream is split into (potentially) multiple new streams, e.g. in a demuxer, + * but not for every single element in the pipeline. + * gst_pad_create_stream_id() or gst_pad_create_stream_id_printf() can be + * used to create a stream-id. There are no particular semantics for the + * stream-id, though it should be deterministic (to support stream matching) + * and it might be used to order streams (besides any information conveyed by + * stream flags). + * + * Returns: (transfer full): the new STREAM_START event. + */ +GstEvent * +gst_event_new_stream_start (const gchar * stream_id) +{ + GstStructure *s; + + g_return_val_if_fail (stream_id != NULL, NULL); + + s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_START), + GST_QUARK (STREAM_ID), G_TYPE_STRING, stream_id, + GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE, NULL); + + return gst_event_new_custom (GST_EVENT_STREAM_START, s); +} + +/** + * gst_event_parse_stream_start: + * @event: a stream-start event. + * @stream_id: (out) (transfer none): pointer to store the stream-id + * + * Parse a stream-id @event and store the result in the given @stream_id + * location. The string stored in @stream_id must not be modified and will + * remain valid only until @event gets freed. Make a copy if you want to + * modify it or store it for later use. + */ +void +gst_event_parse_stream_start (GstEvent * event, const gchar ** stream_id) +{ + const GstStructure *structure; + const GValue *val; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + + structure = gst_event_get_structure (event); + val = gst_structure_id_get_value (structure, GST_QUARK (STREAM_ID)); + + if (stream_id) + *stream_id = g_value_get_string (val); +} + +/** + * gst_event_set_stream: + * @event: a stream-start event + * @stream: (transfer none): the stream object to set + * + * Set the @stream on the stream-start @event + * + * Since: 1.10 + */ +void +gst_event_set_stream (GstEvent * event, GstStream * stream) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + g_return_if_fail (gst_event_is_writable (event)); + + gst_structure_id_set (GST_EVENT_STRUCTURE (event), + GST_QUARK (STREAM), GST_TYPE_STREAM, stream, NULL); +} + +/** + * gst_event_parse_stream: + * @event: a stream-start event + * @stream: (out) (transfer full): adress of variable to store the stream + * + * Parse a stream-start @event and extract the #GstStream from it. + * + * Since: 1.10 + */ +void +gst_event_parse_stream (GstEvent * event, GstStream ** stream) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + + if (stream) { + gst_structure_id_get (GST_EVENT_STRUCTURE (event), + GST_QUARK (STREAM), GST_TYPE_STREAM, stream, NULL); + } + +} + +/** + * gst_event_set_stream_flags: + * @event: a stream-start event + * @flags: the stream flags to set + * + * Since: 1.2 + */ +void +gst_event_set_stream_flags (GstEvent * event, GstStreamFlags flags) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + g_return_if_fail (gst_event_is_writable (event)); + + gst_structure_id_set (GST_EVENT_STRUCTURE (event), + GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, flags, NULL); +} + +/** + * gst_event_parse_stream_flags: + * @event: a stream-start event + * @flags: (out): address of variable where to store the stream flags + * + * Since: 1.2 + */ +void +gst_event_parse_stream_flags (GstEvent * event, GstStreamFlags * flags) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + + if (flags) { + gst_structure_id_get (GST_EVENT_STRUCTURE (event), + GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, flags, NULL); + } +} + +/** + * gst_event_set_group_id: + * @event: a stream-start event + * @group_id: the group id to set + * + * All streams that have the same group id are supposed to be played + * together, i.e. all streams inside a container file should have the + * same group id but different stream ids. The group id should change + * each time the stream is started, resulting in different group ids + * each time a file is played for example. + * + * Use gst_util_group_id_next() to get a new group id. + * + * Since: 1.2 + */ +void +gst_event_set_group_id (GstEvent * event, guint group_id) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + g_return_if_fail (gst_event_is_writable (event)); + + gst_structure_id_set (GST_EVENT_STRUCTURE (event), + GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL); +} + +/** + * gst_event_parse_group_id: + * @event: a stream-start event + * @group_id: (out): address of variable where to store the group id + * + * Returns: %TRUE if a group id was set on the event and could be parsed, + * %FALSE otherwise. + * + * Since: 1.2 + */ +gboolean +gst_event_parse_group_id (GstEvent * event, guint * group_id) +{ + g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START, + FALSE); + + if (group_id) { + return gst_structure_id_get (GST_EVENT_STRUCTURE (event), + GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL); + } + + return TRUE; +} + +/** + * gst_event_new_stream_collection: + * @collection: Active collection for this data flow + * + * Create a new STREAM_COLLECTION event. The stream collection event can only + * travel downstream synchronized with the buffer flow. + * + * Source elements, demuxers and other elements that manage collections + * of streams and post #GstStreamCollection messages on the bus also send + * this event downstream on each pad involved in the collection, so that + * activation of a new collection can be tracked through the downstream + * data flow. + * + * Returns: (transfer full): the new STREAM_COLLECTION event. + * + * Since: 1.10 + */ +GstEvent * +gst_event_new_stream_collection (GstStreamCollection * collection) +{ + GstStructure *s; + + g_return_val_if_fail (collection != NULL, NULL); + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL); + + s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_COLLECTION), + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); + + return gst_event_new_custom (GST_EVENT_STREAM_COLLECTION, s); +} + +/** + * gst_event_parse_stream_collection: + * @event: a stream-collection event + * @collection: (out): pointer to store the collection + * + * Retrieve new #GstStreamCollection from STREAM_COLLECTION event @event. + * + * Since: 1.10 + */ +void +gst_event_parse_stream_collection (GstEvent * event, + GstStreamCollection ** collection) +{ + const GstStructure *structure; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_COLLECTION); + + structure = gst_event_get_structure (event); + + if (collection) { + gst_structure_id_get (structure, + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); + } +} + +/** + * gst_event_new_toc: + * @toc: (transfer none): #GstToc structure. + * @updated: whether @toc was updated or not. + * + * Generate a TOC event from the given @toc. The purpose of the TOC event is to + * inform elements that some kind of the TOC was found. + * + * Returns: (transfer full): a new #GstEvent. + */ +GstEvent * +gst_event_new_toc (GstToc * toc, gboolean updated) +{ + GstStructure *toc_struct; + GQuark id; + + g_return_val_if_fail (toc != NULL, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating toc event"); + + /* need different structure names so sticky_multi event stuff on pads + * works, i.e. both TOC events are kept around */ + if (gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL) + id = GST_QUARK (EVENT_TOC_GLOBAL); + else + id = GST_QUARK (EVENT_TOC_CURRENT); + + toc_struct = gst_structure_new_id (id, + GST_QUARK (TOC), GST_TYPE_TOC, toc, + GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL); + + return gst_event_new_custom (GST_EVENT_TOC, toc_struct); +} + +/** + * gst_event_parse_toc: + * @event: a TOC event. + * @toc: (out) (transfer full): pointer to #GstToc structure. + * @updated: (out): pointer to store TOC updated flag. + * + * Parse a TOC @event and store the results in the given @toc and @updated locations. + */ +void +gst_event_parse_toc (GstEvent * event, GstToc ** toc, gboolean * updated) +{ + const GstStructure *structure; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TOC); + g_return_if_fail (toc != NULL); + + structure = gst_event_get_structure (event); + + gst_structure_id_get (structure, + GST_QUARK (TOC), GST_TYPE_TOC, toc, + GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL); +} + +/** + * gst_event_new_toc_select: + * @uid: UID in the TOC to start playback from. + * + * Generate a TOC select event with the given @uid. The purpose of the + * TOC select event is to start playback based on the TOC's entry with the + * given @uid. + * + * Returns: a new #GstEvent. + */ +GstEvent * +gst_event_new_toc_select (const gchar * uid) +{ + GstStructure *structure; + + g_return_val_if_fail (uid != NULL, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating toc select event for UID: %s", uid); + + structure = gst_structure_new_id (GST_QUARK (EVENT_TOC_SELECT), + GST_QUARK (UID), G_TYPE_STRING, uid, NULL); + + return gst_event_new_custom (GST_EVENT_TOC_SELECT, structure); +} + +/** + * gst_event_parse_toc_select: + * @event: a TOC select event. + * @uid: (out) (transfer full) (allow-none): storage for the selection UID. + * + * Parse a TOC select @event and store the results in the given @uid location. + */ +void +gst_event_parse_toc_select (GstEvent * event, gchar ** uid) +{ + const GstStructure *structure; + const GValue *val; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TOC_SELECT); + + structure = gst_event_get_structure (event); + val = gst_structure_id_get_value (structure, GST_QUARK (UID)); + + if (uid != NULL) + *uid = g_strdup (g_value_get_string (val)); + +} + +/** + * gst_event_new_protection: + * @system_id: (transfer none): a string holding a UUID that uniquely + * identifies a protection system. + * @data: (transfer none): a #GstBuffer holding protection system specific + * information. The reference count of the buffer will be incremented by one. + * @origin: a string indicating where the protection + * information carried in the event was extracted from. The allowed values + * of this string will depend upon the protection scheme. + * + * Creates a new event containing information specific to a particular + * protection system (uniquely identified by @system_id), by which that + * protection system can acquire key(s) to decrypt a protected stream. + * + * In order for a decryption element to decrypt media + * protected using a specific system, it first needs all the + * protection system specific information necessary to acquire the decryption + * key(s) for that stream. The functions defined here enable this information + * to be passed in events from elements that extract it + * (e.g., ISOBMFF demuxers, MPEG DASH demuxers) to protection decrypter + * elements that use it. + * + * Events containing protection system specific information are created using + * #gst_event_new_protection, and they can be parsed by downstream elements + * using #gst_event_parse_protection. + * + * In Common Encryption, protection system specific information may be located + * within ISOBMFF files, both in movie (moov) boxes and movie fragment (moof) + * boxes; it may also be contained in ContentProtection elements within MPEG + * DASH MPDs. The events created by #gst_event_new_protection contain data + * identifying from which of these locations the encapsulated protection system + * specific information originated. This origin information is required as + * some protection systems use different encodings depending upon where the + * information originates. + * + * The events returned by gst_event_new_protection() are implemented + * in such a way as to ensure that the most recently-pushed protection info + * event of a particular @origin and @system_id will + * be stuck to the output pad of the sending element. + * + * Returns: a #GST_EVENT_PROTECTION event, if successful; %NULL + * if unsuccessful. + * + * Since: 1.6 + */ +GstEvent * +gst_event_new_protection (const gchar * system_id, + GstBuffer * data, const gchar * origin) +{ + gchar *event_name; + GstEvent *event; + GstStructure *s; + + g_return_val_if_fail (system_id != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + + event_name = + g_strconcat ("GstProtectionEvent", origin ? "-" : "", + origin ? origin : "", "-", system_id, NULL); + + GST_CAT_INFO (GST_CAT_EVENT, "creating protection event %s", event_name); + + s = gst_structure_new (event_name, "data", GST_TYPE_BUFFER, data, + "system_id", G_TYPE_STRING, system_id, NULL); + if (origin) + gst_structure_set (s, "origin", G_TYPE_STRING, origin, NULL); + event = gst_event_new_custom (GST_EVENT_PROTECTION, s); + + g_free (event_name); + return event; +} + +/** + * gst_event_parse_protection: + * @event: a #GST_EVENT_PROTECTION event. + * @system_id: (out) (allow-none) (transfer none): pointer to store the UUID + * string uniquely identifying a content protection system. + * @data: (out) (allow-none) (transfer none): pointer to store a #GstBuffer + * holding protection system specific information. + * @origin: (out) (allow-none) (transfer none): pointer to store a value that + * indicates where the protection information carried by @event was extracted + * from. + * + * Parses an event containing protection system specific information and stores + * the results in @system_id, @data and @origin. The data stored in @system_id, + * @origin and @data are valid until @event is released. + * + * Since: 1.6 + */ +void +gst_event_parse_protection (GstEvent * event, const gchar ** system_id, + GstBuffer ** data, const gchar ** origin) +{ + const GstStructure *s; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_IS_EVENT (event)); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_PROTECTION); + + s = gst_event_get_structure (event); + + if (origin) + *origin = gst_structure_get_string (s, "origin"); + + if (system_id) + *system_id = gst_structure_get_string (s, "system_id"); + + if (data) { + const GValue *value = gst_structure_get_value (s, "data"); + *data = gst_value_get_buffer (value); + } +} + +/** + * gst_event_new_segment_done: + * @format: The format of the position being done + * @position: The position of the segment being done + * + * Create a new segment-done event. This event is sent by elements that + * finish playback of a segment as a result of a segment seek. + * + * Returns: (transfer full): a new #GstEvent + */ +GstEvent * +gst_event_new_segment_done (GstFormat format, gint64 position) +{ + GstEvent *event; + GstStructure *structure; + + GST_CAT_INFO (GST_CAT_EVENT, "creating segment-done event"); + + structure = gst_structure_new_id (GST_QUARK (EVENT_SEGMENT_DONE), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (POSITION), G_TYPE_INT64, position, NULL); + + event = gst_event_new_custom (GST_EVENT_SEGMENT_DONE, structure); + + return event; +} + +/** + * gst_event_parse_segment_done: + * @event: A valid #GstEvent of type GST_EVENT_SEGMENT_DONE. + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL + * + * Extracts the position and format from the segment done message. + * + */ +void +gst_event_parse_segment_done (GstEvent * event, GstFormat * format, + gint64 * position) +{ + const GstStructure *structure; + const GValue *val; + + g_return_if_fail (event != NULL); + g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT_DONE); + + structure = gst_event_get_structure (event); + + val = gst_structure_id_get_value (structure, GST_QUARK (FORMAT)); + if (format != NULL) + *format = g_value_get_enum (val); + + val = gst_structure_id_get_value (structure, GST_QUARK (POSITION)); + if (position != NULL) + *position = g_value_get_int64 (val); +} diff --git a/gst/gstevent.h b/gst/gstevent.h new file mode 100644 index 0000000..7a36f9a --- /dev/null +++ b/gst/gstevent.h @@ -0,0 +1,707 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstevent.h: Header for GstEvent subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_EVENT_H__ +#define __GST_EVENT_H__ + +typedef struct _GstEvent GstEvent; + +/** + * GstEventTypeFlags: + * @GST_EVENT_TYPE_UPSTREAM: Set if the event can travel upstream. + * @GST_EVENT_TYPE_DOWNSTREAM: Set if the event can travel downstream. + * @GST_EVENT_TYPE_SERIALIZED: Set if the event should be serialized with data + * flow. + * @GST_EVENT_TYPE_STICKY: Set if the event is sticky on the pads. + * @GST_EVENT_TYPE_STICKY_MULTI: Multiple sticky events can be on a pad, each + * identified by the event name. + * + * #GstEventTypeFlags indicate the aspects of the different #GstEventType + * values. You can get the type flags of a #GstEventType with the + * gst_event_type_get_flags() function. + */ +typedef enum { + GST_EVENT_TYPE_UPSTREAM = 1 << 0, + GST_EVENT_TYPE_DOWNSTREAM = 1 << 1, + GST_EVENT_TYPE_SERIALIZED = 1 << 2, + GST_EVENT_TYPE_STICKY = 1 << 3, + GST_EVENT_TYPE_STICKY_MULTI = 1 << 4 +} GstEventTypeFlags; + +/** + * GST_EVENT_TYPE_BOTH: (value 3) (type GstEventTypeFlags) + * + * The same thing as #GST_EVENT_TYPE_UPSTREAM | #GST_EVENT_TYPE_DOWNSTREAM. + */ +#define GST_EVENT_TYPE_BOTH \ + ((GstEventTypeFlags)(GST_EVENT_TYPE_UPSTREAM | GST_EVENT_TYPE_DOWNSTREAM)) + +#define GST_EVENT_NUM_SHIFT (8) + +/** + * GST_EVENT_MAKE_TYPE: + * @num: the event number to create + * @flags: the event flags + * + * when making custom event types, use this macro with the num and + * the given flags + */ +#define GST_EVENT_MAKE_TYPE(num,flags) \ + (((num) << GST_EVENT_NUM_SHIFT) | (flags)) + +#define FLAG(name) GST_EVENT_TYPE_##name + +/** + * GstEventType: + * @GST_EVENT_UNKNOWN: unknown event. + * @GST_EVENT_FLUSH_START: Start a flush operation. This event clears all data + * from the pipeline and unblock all streaming threads. + * @GST_EVENT_FLUSH_STOP: Stop a flush operation. This event resets the + * running-time of the pipeline. + * @GST_EVENT_SELECT_STREAMS: A request to select one or more streams (Since 1.10) + * @GST_EVENT_STREAM_START: Event to mark the start of a new stream. Sent before any + * other serialized event and only sent at the start of a new stream, + * not after flushing seeks. + * @GST_EVENT_CAPS: #GstCaps event. Notify the pad of a new media type. + * @GST_EVENT_SEGMENT: A new media segment follows in the dataflow. The + * segment events contains information for clipping buffers and + * converting buffer timestamps to running-time and + * stream-time. + * @GST_EVENT_STREAM_COLLECTION: A new #GstStreamCollection is available (Since 1.10) + * @GST_EVENT_TAG: A new set of metadata tags has been found in the stream. + * @GST_EVENT_BUFFERSIZE: Notification of buffering requirements. Currently not + * used yet. + * @GST_EVENT_SINK_MESSAGE: An event that sinks turn into a message. Used to + * send messages that should be emitted in sync with + * rendering. + * @GST_EVENT_STREAM_GROUP_DONE: Indicates that there is no more data for + * the stream group ID in the message. Sent before EOS + * in some instances and should be handled mostly the same. (Since 1.10) + * @GST_EVENT_EOS: End-Of-Stream. No more data is to be expected to follow + * without either a STREAM_START event, or a FLUSH_STOP and a SEGMENT + * event. + * @GST_EVENT_SEGMENT_DONE: Marks the end of a segment playback. + * @GST_EVENT_GAP: Marks a gap in the datastream. + * @GST_EVENT_TOC: An event which indicates that a new table of contents (TOC) + * was found or updated. + * @GST_EVENT_PROTECTION: An event which indicates that new or updated + * encryption information has been found in the stream. + * @GST_EVENT_QOS: A quality message. Used to indicate to upstream elements + * that the downstream elements should adjust their processing + * rate. + * @GST_EVENT_SEEK: A request for a new playback position and rate. + * @GST_EVENT_NAVIGATION: Navigation events are usually used for communicating + * user requests, such as mouse or keyboard movements, + * to upstream elements. + * @GST_EVENT_LATENCY: Notification of new latency adjustment. Sinks will use + * the latency information to adjust their synchronisation. + * @GST_EVENT_STEP: A request for stepping through the media. Sinks will usually + * execute the step operation. + * @GST_EVENT_RECONFIGURE: A request for upstream renegotiating caps and reconfiguring. + * @GST_EVENT_TOC_SELECT: A request for a new playback position based on TOC + * entry's UID. + * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event + * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the + * data flow. + * @GST_EVENT_CUSTOM_DOWNSTREAM_OOB: Custom out-of-band downstream event. + * @GST_EVENT_CUSTOM_DOWNSTREAM_STICKY: Custom sticky downstream event. + * @GST_EVENT_CUSTOM_BOTH: Custom upstream or downstream event. + * In-band when travelling downstream. + * @GST_EVENT_CUSTOM_BOTH_OOB: Custom upstream or downstream out-of-band event. + * + * #GstEventType lists the standard event types that can be sent in a pipeline. + * + * The custom event types can be used for private messages between elements + * that can't be expressed using normal + * GStreamer buffer passing semantics. Custom events carry an arbitrary + * #GstStructure. + * Specific custom events are distinguished by the name of the structure. + */ +/* NOTE: keep in sync with quark registration in gstevent.c */ +typedef enum { + GST_EVENT_UNKNOWN = GST_EVENT_MAKE_TYPE (0, 0), + + /* bidirectional events */ + GST_EVENT_FLUSH_START = GST_EVENT_MAKE_TYPE (10, FLAG(BOTH)), + GST_EVENT_FLUSH_STOP = GST_EVENT_MAKE_TYPE (20, FLAG(BOTH) | FLAG(SERIALIZED)), + + /* downstream serialized events */ + GST_EVENT_STREAM_START = GST_EVENT_MAKE_TYPE (40, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_CAPS = GST_EVENT_MAKE_TYPE (50, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_SEGMENT = GST_EVENT_MAKE_TYPE (70, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_STREAM_COLLECTION = GST_EVENT_MAKE_TYPE (75, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_TAG = GST_EVENT_MAKE_TYPE (80, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_BUFFERSIZE = GST_EVENT_MAKE_TYPE (90, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_SINK_MESSAGE = GST_EVENT_MAKE_TYPE (100, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_STREAM_GROUP_DONE = GST_EVENT_MAKE_TYPE (105, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_EOS = GST_EVENT_MAKE_TYPE (110, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), + GST_EVENT_TOC = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_PROTECTION = GST_EVENT_MAKE_TYPE (130, FLAG (DOWNSTREAM) | FLAG (SERIALIZED) | FLAG (STICKY) | FLAG (STICKY_MULTI)), + + /* non-sticky downstream serialized */ + GST_EVENT_SEGMENT_DONE = GST_EVENT_MAKE_TYPE (150, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), + GST_EVENT_GAP = GST_EVENT_MAKE_TYPE (160, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), + + /* upstream events */ + GST_EVENT_QOS = GST_EVENT_MAKE_TYPE (190, FLAG(UPSTREAM)), + GST_EVENT_SEEK = GST_EVENT_MAKE_TYPE (200, FLAG(UPSTREAM)), + GST_EVENT_NAVIGATION = GST_EVENT_MAKE_TYPE (210, FLAG(UPSTREAM)), + GST_EVENT_LATENCY = GST_EVENT_MAKE_TYPE (220, FLAG(UPSTREAM)), + GST_EVENT_STEP = GST_EVENT_MAKE_TYPE (230, FLAG(UPSTREAM)), + GST_EVENT_RECONFIGURE = GST_EVENT_MAKE_TYPE (240, FLAG(UPSTREAM)), + GST_EVENT_TOC_SELECT = GST_EVENT_MAKE_TYPE (250, FLAG(UPSTREAM)), + GST_EVENT_SELECT_STREAMS = GST_EVENT_MAKE_TYPE (260, FLAG(UPSTREAM)), + + /* custom events start here */ + GST_EVENT_CUSTOM_UPSTREAM = GST_EVENT_MAKE_TYPE (270, FLAG(UPSTREAM)), + GST_EVENT_CUSTOM_DOWNSTREAM = GST_EVENT_MAKE_TYPE (280, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), + GST_EVENT_CUSTOM_DOWNSTREAM_OOB = GST_EVENT_MAKE_TYPE (290, FLAG(DOWNSTREAM)), + GST_EVENT_CUSTOM_DOWNSTREAM_STICKY = GST_EVENT_MAKE_TYPE (300, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_CUSTOM_BOTH = GST_EVENT_MAKE_TYPE (310, FLAG(BOTH) | FLAG(SERIALIZED)), + GST_EVENT_CUSTOM_BOTH_OOB = GST_EVENT_MAKE_TYPE (320, FLAG(BOTH)) +} GstEventType; +#undef FLAG + +/** + * GstStreamFlags: + * @GST_STREAM_FLAG_NONE: This stream has no special attributes + * @GST_STREAM_FLAG_SPARSE: This stream is a sparse stream (e.g. a subtitle + * stream), data may flow only in irregular intervals with large gaps in + * between. + * @GST_STREAM_FLAG_SELECT: This stream should be selected by default. This + * flag may be used by demuxers to signal that a stream should be selected + * by default in a playback scenario. + * @GST_STREAM_FLAG_UNSELECT: This stream should not be selected by default. + * This flag may be used by demuxers to signal that a stream should not + * be selected by default in a playback scenario, but only if explicitly + * selected by the user (e.g. an audio track for the hard of hearing or + * a director's commentary track). + * + * Since: 1.2 + */ +typedef enum { + GST_STREAM_FLAG_NONE, + GST_STREAM_FLAG_SPARSE = (1 << 0), + GST_STREAM_FLAG_SELECT = (1 << 1), + GST_STREAM_FLAG_UNSELECT = (1 << 2) +} GstStreamFlags; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_event_type; + +#define GST_TYPE_EVENT (_gst_event_type) +#define GST_IS_EVENT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_EVENT)) +#define GST_EVENT_CAST(obj) ((GstEvent *)(obj)) +#define GST_EVENT(obj) (GST_EVENT_CAST(obj)) + +/** + * GST_EVENT_TYPE: + * @event: the event to query + * + * Get the #GstEventType of the event. + */ +#define GST_EVENT_TYPE(event) (GST_EVENT_CAST(event)->type) + +/** + * GST_EVENT_TYPE_NAME: + * @event: the event to query + * + * Get a constant string representation of the #GstEventType of the event. + */ +#define GST_EVENT_TYPE_NAME(event) (gst_event_type_get_name(GST_EVENT_TYPE(event))) + +/** + * GST_EVENT_TIMESTAMP: + * @event: the event to query + * + * Get the #GstClockTime timestamp of the event. This is the time when the event + * was created. + */ +#define GST_EVENT_TIMESTAMP(event) (GST_EVENT_CAST(event)->timestamp) + +/** + * GST_EVENT_SEQNUM: + * @event: the event to query + * + * The sequence number of @event. + */ +#define GST_EVENT_SEQNUM(event) (GST_EVENT_CAST(event)->seqnum) + +/** + * GST_EVENT_IS_UPSTREAM: + * @ev: the event to query + * + * Check if an event can travel upstream. + */ +#define GST_EVENT_IS_UPSTREAM(ev) !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_UPSTREAM) +/** + * GST_EVENT_IS_DOWNSTREAM: + * @ev: the event to query + * + * Check if an event can travel downstream. + */ +#define GST_EVENT_IS_DOWNSTREAM(ev) !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_DOWNSTREAM) +/** + * GST_EVENT_IS_SERIALIZED: + * @ev: the event to query + * + * Check if an event is serialized with the data stream. + */ +#define GST_EVENT_IS_SERIALIZED(ev) !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_SERIALIZED) +/** + * GST_EVENT_IS_STICKY: + * @ev: the event to query + * + * Check if an event is sticky on the pads. + */ +#define GST_EVENT_IS_STICKY(ev) !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_STICKY) + +/** + * gst_event_is_writable: + * @ev: a #GstEvent + * + * Tests if you can safely write data into a event's structure or validly + * modify the seqnum and timestamp field. + */ +#define gst_event_is_writable(ev) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ev)) +/** + * gst_event_make_writable: + * @ev: (transfer full): a #GstEvent + * + * Makes a writable event from the given event. If the source event is + * already writable, this will simply return the same event. A copy will + * otherwise be made using gst_event_copy(). + * + * Returns: (transfer full): a writable event which may or may not be the + * same as @ev + */ +#define gst_event_make_writable(ev) GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ev))) +/** + * gst_event_replace: + * @old_event: (inout) (transfer full) (nullable): pointer to a + * pointer to a #GstEvent to be replaced. + * @new_event: (allow-none) (transfer none): pointer to a #GstEvent that will + * replace the event pointed to by @old_event. + * + * Modifies a pointer to a #GstEvent to point to a different #GstEvent. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * event is unreffed, the new one is reffed). + * + * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL. + * + * Returns: %TRUE if @new_event was different from @old_event + */ +static inline gboolean +gst_event_replace (GstEvent **old_event, GstEvent *new_event) +{ + return gst_mini_object_replace ((GstMiniObject **) old_event, (GstMiniObject *) new_event); +} + +/** + * gst_event_steal: + * @old_event: (inout) (transfer full) (nullable): pointer to a + * pointer to a #GstEvent to be stolen. + * + * Atomically replace the #GstEvent pointed to by @old_event with %NULL and + * return the original event. + * + * Returns: the #GstEvent that was in @old_event + */ +static inline GstEvent * +gst_event_steal (GstEvent **old_event) +{ + return GST_EVENT_CAST (gst_mini_object_steal ((GstMiniObject **) old_event)); +} + +/** + * gst_event_take: + * @old_event: (inout) (transfer full) (nullable): pointer to a + * pointer to a #GstEvent to be stolen. + * @new_event: (allow-none) (transfer full): pointer to a #GstEvent that will + * replace the event pointed to by @old_event. + * + * Modifies a pointer to a #GstEvent to point to a different #GstEvent. This + * function is similar to gst_event_replace() except that it takes ownership of + * @new_event. + * + * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL. + * + * Returns: %TRUE if @new_event was different from @old_event + */ +static inline gboolean +gst_event_take (GstEvent **old_event, GstEvent *new_event) +{ + return gst_mini_object_take ((GstMiniObject **) old_event, (GstMiniObject *) new_event); +} + +/** + * GstQOSType: + * @GST_QOS_TYPE_OVERFLOW: The QoS event type that is produced when upstream + * elements are producing data too quickly and the element can't keep up + * processing the data. Upstream should reduce their production rate. This + * type is also used when buffers arrive early or in time. + * @GST_QOS_TYPE_UNDERFLOW: The QoS event type that is produced when upstream + * elements are producing data too slowly and need to speed up their + * production rate. + * @GST_QOS_TYPE_THROTTLE: The QoS event type that is produced when the + * application enabled throttling to limit the data rate. + * + * The different types of QoS events that can be given to the + * gst_event_new_qos() method. + */ +typedef enum { + GST_QOS_TYPE_OVERFLOW = 0, + GST_QOS_TYPE_UNDERFLOW = 1, + GST_QOS_TYPE_THROTTLE = 2 +} GstQOSType; + + +/** + * GstEvent: + * @mini_object: the parent structure + * @type: the #GstEventType of the event + * @timestamp: the timestamp of the event + * @seqnum: the sequence number of the event + * + * A #GstEvent. + */ +struct _GstEvent { + GstMiniObject mini_object; + + /*< public >*/ /* with COW */ + GstEventType type; + guint64 timestamp; + guint32 seqnum; +}; + +GST_API +const gchar* gst_event_type_get_name (GstEventType type); + +GST_API +GQuark gst_event_type_to_quark (GstEventType type); + +GST_API +GstEventTypeFlags + gst_event_type_get_flags (GstEventType type); + + +/* refcounting */ +/** + * gst_event_ref: + * @event: The event to refcount + * + * Increase the refcount of this event. + * + * Returns: (transfer full): @event (for convenience when doing assignments) + */ +static inline GstEvent * +gst_event_ref (GstEvent * event) +{ + return (GstEvent *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (event)); +} + +/** + * gst_event_unref: + * @event: (transfer full): the event to refcount + * + * Decrease the refcount of an event, freeing it if the refcount reaches 0. + */ +static inline void +gst_event_unref (GstEvent * event) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (event)); +} + +/* copy event */ +/** + * gst_event_copy: + * @event: The event to copy + * + * Copy the event using the event specific copy function. + * + * Returns: (transfer full): the new event + */ +static inline GstEvent * +gst_event_copy (const GstEvent * event) +{ + return GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (event))); +} + +GST_API +GType gst_event_get_type (void); + +/* custom event */ + +GST_API +GstEvent* gst_event_new_custom (GstEventType type, GstStructure *structure) G_GNUC_MALLOC; + +GST_API +const GstStructure * + gst_event_get_structure (GstEvent *event); + +GST_API +GstStructure * gst_event_writable_structure (GstEvent *event); + +GST_API +gboolean gst_event_has_name (GstEvent *event, const gchar *name); + +/* identifiers for events and messages */ + +GST_API +guint32 gst_event_get_seqnum (GstEvent *event); + +GST_API +void gst_event_set_seqnum (GstEvent *event, guint32 seqnum); + +/* accumulated pad offsets for the event */ + +GST_API +gint64 gst_event_get_running_time_offset (GstEvent *event); + +GST_API +void gst_event_set_running_time_offset (GstEvent *event, gint64 offset); + +/* Stream start event */ + +GST_API +GstEvent * gst_event_new_stream_start (const gchar *stream_id) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_stream_start (GstEvent *event, const gchar **stream_id); + +GST_API +void gst_event_set_stream (GstEvent *event, GstStream *stream); + +GST_API +void gst_event_parse_stream (GstEvent *event, GstStream **stream); + +GST_API +void gst_event_set_stream_flags (GstEvent *event, GstStreamFlags flags); + +GST_API +void gst_event_parse_stream_flags (GstEvent *event, GstStreamFlags *flags); + +GST_API +void gst_event_set_group_id (GstEvent *event, guint group_id); + +GST_API +gboolean gst_event_parse_group_id (GstEvent *event, guint *group_id); + +/* flush events */ + +GST_API +GstEvent * gst_event_new_flush_start (void) G_GNUC_MALLOC; + +GST_API +GstEvent * gst_event_new_flush_stop (gboolean reset_time) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_flush_stop (GstEvent *event, gboolean *reset_time); + +/* Stream collection event */ + +GST_API +GstEvent * gst_event_new_stream_collection (GstStreamCollection *collection) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_stream_collection (GstEvent *event, GstStreamCollection **collection); + +/* select streams event */ + +GST_API +GstEvent * gst_event_new_select_streams (GList *streams); + +GST_API +void gst_event_parse_select_streams (GstEvent *event, GList **streams); + +/* stream-group-done event */ + +GST_API +GstEvent * gst_event_new_stream_group_done (guint group_id) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_stream_group_done (GstEvent *event, guint *group_id); + +/* EOS event */ + +GST_API +GstEvent * gst_event_new_eos (void) G_GNUC_MALLOC; + +/* GAP event */ + +GST_API +GstEvent * gst_event_new_gap (GstClockTime timestamp, + GstClockTime duration) G_GNUC_MALLOC; +GST_API +void gst_event_parse_gap (GstEvent * event, + GstClockTime * timestamp, + GstClockTime * duration); + +/* Caps events */ + +GST_API +GstEvent * gst_event_new_caps (GstCaps *caps) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_caps (GstEvent *event, GstCaps **caps); + +/* segment event */ + +GST_API +GstEvent* gst_event_new_segment (const GstSegment *segment) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_segment (GstEvent *event, const GstSegment **segment); + +GST_API +void gst_event_copy_segment (GstEvent *event, GstSegment *segment); + +/* tag event */ + +GST_API +GstEvent* gst_event_new_tag (GstTagList *taglist) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_tag (GstEvent *event, GstTagList **taglist); + +/* TOC event */ + +GST_API +GstEvent* gst_event_new_toc (GstToc *toc, gboolean updated); + +GST_API +void gst_event_parse_toc (GstEvent *event, GstToc **toc, gboolean *updated); + +/* Protection event */ + +GST_API +GstEvent * gst_event_new_protection (const gchar * system_id, GstBuffer * data, const gchar * origin); + +GST_API +void gst_event_parse_protection (GstEvent * event, const gchar ** system_id, + GstBuffer ** data, const gchar ** origin); + +/* buffer */ + +GST_API +GstEvent * gst_event_new_buffer_size (GstFormat format, gint64 minsize, gint64 maxsize, + gboolean async) G_GNUC_MALLOC; +GST_API +void gst_event_parse_buffer_size (GstEvent *event, GstFormat *format, gint64 *minsize, + gint64 *maxsize, gboolean *async); + +/* sink message */ + +GST_API +GstEvent* gst_event_new_sink_message (const gchar *name, GstMessage *msg) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_sink_message (GstEvent *event, GstMessage **msg); + +/* QOS events */ + +GST_API +GstEvent* gst_event_new_qos (GstQOSType type, gdouble proportion, + GstClockTimeDiff diff, GstClockTime timestamp) G_GNUC_MALLOC; +GST_API +void gst_event_parse_qos (GstEvent *event, GstQOSType *type, + gdouble *proportion, GstClockTimeDiff *diff, + GstClockTime *timestamp); +/* seek event */ + +GST_API +GstEvent* gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags, + GstSeekType start_type, gint64 start, + GstSeekType stop_type, gint64 stop) G_GNUC_MALLOC; +GST_API +void gst_event_parse_seek (GstEvent *event, gdouble *rate, GstFormat *format, + GstSeekFlags *flags, + GstSeekType *start_type, gint64 *start, + GstSeekType *stop_type, gint64 *stop); + +/* navigation event */ + +GST_API +GstEvent* gst_event_new_navigation (GstStructure *structure) G_GNUC_MALLOC; + +/* latency event */ + +GST_API +GstEvent* gst_event_new_latency (GstClockTime latency) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_latency (GstEvent *event, GstClockTime *latency); + +/* step event */ + +GST_API +GstEvent* gst_event_new_step (GstFormat format, guint64 amount, gdouble rate, + gboolean flush, gboolean intermediate) G_GNUC_MALLOC; +GST_API +void gst_event_parse_step (GstEvent *event, GstFormat *format, guint64 *amount, + gdouble *rate, gboolean *flush, gboolean *intermediate); + +/* renegotiate event */ + +GST_API +GstEvent* gst_event_new_reconfigure (void) G_GNUC_MALLOC; + +/* TOC select event */ + +GST_API +GstEvent* gst_event_new_toc_select (const gchar *uid) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_toc_select (GstEvent *event, gchar **uid); + +/* segment-done event */ + +GST_API +GstEvent* gst_event_new_segment_done (GstFormat format, gint64 position) G_GNUC_MALLOC; + +GST_API +void gst_event_parse_segment_done (GstEvent *event, GstFormat *format, gint64 *position); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEvent, gst_event_unref) +#endif + +G_END_DECLS + +#endif /* __GST_EVENT_H__ */ diff --git a/gst/gstformat.c b/gst/gstformat.c new file mode 100644 index 0000000..130fc77 --- /dev/null +++ b/gst/gstformat.c @@ -0,0 +1,266 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstformat.c: GstFormat registration + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstformat + * @title: GstFormat + * @short_description: Dynamically register new data formats + * @see_also: #GstPad, #GstElement + * + * GstFormats functions are used to register a new format to the gstreamer + * core. Formats can be used to perform seeking or conversions/query + * operations. + */ + + +#include "gst_private.h" +#include +#include "gstformat.h" +#include "gstenumtypes.h" + +static GMutex mutex; +static GList *_gst_formats = NULL; +static GHashTable *_nick_to_format = NULL; +static GHashTable *_format_to_nick = NULL; +static guint32 _n_values = 1; /* we start from 1 because 0 reserved for UNDEFINED */ + +static GstFormatDefinition standard_definitions[] = { + {GST_FORMAT_DEFAULT, "default", "Default format for the media type", 0}, + {GST_FORMAT_BYTES, "bytes", "Bytes", 0}, + {GST_FORMAT_TIME, "time", "Time", 0}, + {GST_FORMAT_BUFFERS, "buffers", "Buffers", 0}, + {GST_FORMAT_PERCENT, "percent", "Percent", 0}, + {GST_FORMAT_UNDEFINED, NULL, NULL, 0} +}; + +void +_priv_gst_format_initialize (void) +{ + GstFormatDefinition *standards = standard_definitions; + + g_mutex_lock (&mutex); + if (_nick_to_format == NULL) { + _nick_to_format = g_hash_table_new (g_str_hash, g_str_equal); + _format_to_nick = g_hash_table_new (NULL, NULL); + } + + while (standards->nick) { + standards->quark = g_quark_from_static_string (standards->nick); + g_hash_table_insert (_nick_to_format, (gpointer) standards->nick, + standards); + g_hash_table_insert (_format_to_nick, GINT_TO_POINTER (standards->value), + standards); + + _gst_formats = g_list_append (_gst_formats, standards); + standards++; + _n_values++; + } + /* getting the type registers the enum */ + g_type_class_ref (gst_format_get_type ()); + g_mutex_unlock (&mutex); +} + +/** + * gst_format_get_name: + * @format: a #GstFormat + * + * Get a printable name for the given format. Do not modify or free. + * + * Returns: (nullable): a reference to the static name of the format + * or %NULL if the format is unknown. + */ +const gchar * +gst_format_get_name (GstFormat format) +{ + const GstFormatDefinition *def; + const gchar *result; + + if ((def = gst_format_get_details (format)) != NULL) + result = def->nick; + else + result = NULL; + + return result; +} + +/** + * gst_format_to_quark: + * @format: a #GstFormat + * + * Get the unique quark for the given format. + * + * Returns: the quark associated with the format or 0 if the format + * is unknown. + */ +GQuark +gst_format_to_quark (GstFormat format) +{ + const GstFormatDefinition *def; + GQuark result; + + if ((def = gst_format_get_details (format)) != NULL) + result = def->quark; + else + result = 0; + + return result; +} + +/** + * gst_format_register: + * @nick: The nick of the new format + * @description: The description of the new format + * + * Create a new GstFormat based on the nick or return an + * already registered format with that nick. + * + * Returns: A new GstFormat or an already registered format + * with the same nick. + * + * MT safe. + */ +GstFormat +gst_format_register (const gchar * nick, const gchar * description) +{ + GstFormatDefinition *format; + GstFormat query; + + g_return_val_if_fail (nick != NULL, GST_FORMAT_UNDEFINED); + g_return_val_if_fail (description != NULL, GST_FORMAT_UNDEFINED); + + query = gst_format_get_by_nick (nick); + if (query != GST_FORMAT_UNDEFINED) + return query; + + g_mutex_lock (&mutex); + format = g_slice_new (GstFormatDefinition); + format->value = (GstFormat) _n_values; + format->nick = g_strdup (nick); + format->description = g_strdup (description); + format->quark = g_quark_from_static_string (format->nick); + + g_hash_table_insert (_nick_to_format, (gpointer) format->nick, format); + g_hash_table_insert (_format_to_nick, GINT_TO_POINTER (format->value), + format); + _gst_formats = g_list_append (_gst_formats, format); + _n_values++; + g_mutex_unlock (&mutex); + + return format->value; +} + +/** + * gst_format_get_by_nick: + * @nick: The nick of the format + * + * Return the format registered with the given nick. + * + * Returns: The format with @nick or GST_FORMAT_UNDEFINED + * if the format was not registered. + */ +GstFormat +gst_format_get_by_nick (const gchar * nick) +{ + GstFormatDefinition *format; + + g_return_val_if_fail (nick != NULL, GST_FORMAT_UNDEFINED); + + g_mutex_lock (&mutex); + format = g_hash_table_lookup (_nick_to_format, nick); + g_mutex_unlock (&mutex); + + if (format != NULL) + return format->value; + else + return GST_FORMAT_UNDEFINED; +} + +/** + * gst_formats_contains: + * @formats: (array zero-terminated=1): The format array to search + * @format: the format to find + * + * See if the given format is inside the format array. + * + * Returns: %TRUE if the format is found inside the array + */ +gboolean +gst_formats_contains (const GstFormat * formats, GstFormat format) +{ + if (!formats) + return FALSE; + + while (*formats) { + if (*formats == format) + return TRUE; + + formats++; + } + return FALSE; +} + + +/** + * gst_format_get_details: + * @format: The format to get details of + * + * Get details about the given format. + * + * Returns: (nullable): The #GstFormatDefinition for @format or %NULL + * on failure. + * + * MT safe. + */ +const GstFormatDefinition * +gst_format_get_details (GstFormat format) +{ + const GstFormatDefinition *result; + + g_mutex_lock (&mutex); + result = g_hash_table_lookup (_format_to_nick, GINT_TO_POINTER (format)); + g_mutex_unlock (&mutex); + + return result; +} + +/** + * gst_format_iterate_definitions: + * + * Iterate all the registered formats. The format definition is read + * only. + * + * Returns: (transfer full): a GstIterator of #GstFormatDefinition. + */ +GstIterator * +gst_format_iterate_definitions (void) +{ + GstIterator *result; + + g_mutex_lock (&mutex); + /* FIXME: register a boxed type for GstFormatDefinition */ + result = gst_iterator_new_list (G_TYPE_POINTER, + &mutex, &_n_values, &_gst_formats, NULL, NULL); + g_mutex_unlock (&mutex); + + return result; +} diff --git a/gst/gstformat.h b/gst/gstformat.h new file mode 100644 index 0000000..111ca9b --- /dev/null +++ b/gst/gstformat.h @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstformat.h: Header for GstFormat types used in queries and + * seeking. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FORMAT_H__ +#define __GST_FORMAT_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * GstFormat: + * @GST_FORMAT_UNDEFINED: undefined format + * @GST_FORMAT_DEFAULT: the default format of the pad/element. This can be + * samples for raw audio, frames/fields for raw video (some, but not all, + * elements support this; use @GST_FORMAT_TIME if you don't have a good + * reason to query for samples/frames) + * @GST_FORMAT_BYTES: bytes + * @GST_FORMAT_TIME: time in nanoseconds + * @GST_FORMAT_BUFFERS: buffers (few, if any, elements implement this as of + * May 2009) + * @GST_FORMAT_PERCENT: percentage of stream (few, if any, elements implement + * this as of May 2009) + * + * Standard predefined formats + */ +/* NOTE: don't forget to update the table in gstformat.c when changing + * this enum */ +typedef enum { + GST_FORMAT_UNDEFINED = 0, /* must be first in list */ + GST_FORMAT_DEFAULT = 1, + GST_FORMAT_BYTES = 2, + GST_FORMAT_TIME = 3, + GST_FORMAT_BUFFERS = 4, + GST_FORMAT_PERCENT = 5 +} GstFormat; + +/* a percentage is always relative to 1000000 */ +/** + * GST_FORMAT_PERCENT_MAX: + * + * The PERCENT format is between 0 and this value + */ +#define GST_FORMAT_PERCENT_MAX G_GINT64_CONSTANT (1000000) +/** + * GST_FORMAT_PERCENT_SCALE: + * + * The value used to scale down the reported PERCENT format value to + * its real value. + */ +#define GST_FORMAT_PERCENT_SCALE G_GINT64_CONSTANT (10000) + +typedef struct _GstFormatDefinition GstFormatDefinition; + +/** + * GstFormatDefinition: + * @value: The unique id of this format + * @nick: A short nick of the format + * @description: A longer description of the format + * @quark: A quark for the nick + * + * A format definition + */ +struct _GstFormatDefinition +{ + GstFormat value; + const gchar *nick; + const gchar *description; + GQuark quark; +}; + +GST_API +const gchar* gst_format_get_name (GstFormat format); + +GST_API +GQuark gst_format_to_quark (GstFormat format); + +/* register a new format */ + +GST_API +GstFormat gst_format_register (const gchar *nick, + const gchar *description); + +GST_API +GstFormat gst_format_get_by_nick (const gchar *nick); + +/* check if a format is in an array of formats */ + +GST_API +gboolean gst_formats_contains (const GstFormat *formats, GstFormat format); + +/* query for format details */ + +GST_API +const GstFormatDefinition* + gst_format_get_details (GstFormat format); + +GST_API +GstIterator* gst_format_iterate_definitions (void); + +G_END_DECLS + +#endif /* __GST_FORMAT_H__ */ diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c new file mode 100644 index 0000000..90cae38 --- /dev/null +++ b/gst/gstghostpad.c @@ -0,0 +1,898 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Andy Wingo + * 2006 Edward Hervey + * + * gstghostpad.c: Proxy pads + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstghostpad + * @title: GstGhostPad + * @short_description: Pseudo link pads + * @see_also: #GstPad + * + * GhostPads are useful when organizing pipelines with #GstBin like elements. + * The idea here is to create hierarchical element graphs. The bin element + * contains a sub-graph. Now one would like to treat the bin-element like any + * other #GstElement. This is where GhostPads come into play. A GhostPad acts as + * a proxy for another pad. Thus the bin can have sink and source ghost-pads + * that are associated with sink and source pads of the child elements. + * + * If the target pad is known at creation time, gst_ghost_pad_new() is the + * function to use to get a ghost-pad. Otherwise one can use gst_ghost_pad_new_no_target() + * to create the ghost-pad and use gst_ghost_pad_set_target() to establish the + * association later on. + * + * Note that GhostPads add overhead to the data processing of a pipeline. + */ + +#include "gst_private.h" +#include "gstinfo.h" + +#include "gstghostpad.h" +#include "gst.h" + +#define GST_CAT_DEFAULT GST_CAT_PADS + +#define GST_PROXY_PAD_CAST(obj) ((GstProxyPad *)obj) +#define GST_PROXY_PAD_PRIVATE(obj) (GST_PROXY_PAD_CAST (obj)->priv) +#define GST_PROXY_PAD_TARGET(pad) (GST_PAD_PEER (GST_PROXY_PAD_INTERNAL (pad))) +#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_PRIVATE (pad)->internal) + +#define GST_PROXY_PAD_ACQUIRE_INTERNAL(pad, internal, retval) \ + internal = \ + GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad))); \ + if (internal == NULL) \ + return retval; + +#define GST_PROXY_PAD_RELEASE_INTERNAL(internal) gst_object_unref (internal); + +struct _GstProxyPadPrivate +{ + GstPad *internal; +}; + +G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD); + +static GstPad *gst_proxy_pad_get_target (GstPad * pad); + +/** + * gst_proxy_pad_iterate_internal_links_default: + * @pad: the #GstPad to get the internal links of. + * @parent: (allow-none): the parent of @pad or %NULL + * + * Invoke the default iterate internal links function of the proxy pad. + * + * Returns: (nullable): a #GstIterator of #GstPad, or %NULL if @pad + * has no parent. Unref each returned pad with gst_object_unref(). + */ +GstIterator * +gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent) +{ + GstIterator *res = NULL; + GstPad *internal; + GValue v = { 0, }; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL); + + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, NULL); + + g_value_init (&v, GST_TYPE_PAD); + g_value_take_object (&v, internal); + res = gst_iterator_new_single (GST_TYPE_PAD, &v); + g_value_unset (&v); + + return res; +} + +/** + * gst_proxy_pad_chain_default: + * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. + * @parent: (allow-none): the parent of @pad or %NULL + * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR + * if not. + * + * Invoke the default chain function of the proxy pad. + * + * Returns: a #GstFlowReturn from the pad. + */ +GstFlowReturn +gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent, + GstBuffer * buffer) +{ + GstFlowReturn res; + GstPad *internal; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED); + res = gst_pad_push (internal, buffer); + GST_PROXY_PAD_RELEASE_INTERNAL (internal); + + return res; +} + +/** + * gst_proxy_pad_chain_list_default: + * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. + * @parent: (allow-none): the parent of @pad or %NULL + * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR + * if not. + * + * Invoke the default chain list function of the proxy pad. + * + * Returns: a #GstFlowReturn from the pad. + */ +GstFlowReturn +gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent, + GstBufferList * list) +{ + GstFlowReturn res; + GstPad *internal; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); + + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED); + res = gst_pad_push_list (internal, list); + GST_PROXY_PAD_RELEASE_INTERNAL (internal); + + return res; +} + +/** + * gst_proxy_pad_getrange_default: + * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not. + * @parent: the parent of @pad + * @offset: The start offset of the buffer + * @size: The length of the buffer + * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, + * returns #GST_FLOW_ERROR if %NULL. + * + * Invoke the default getrange function of the proxy pad. + * + * Returns: a #GstFlowReturn from the pad. + */ +GstFlowReturn +gst_proxy_pad_getrange_default (GstPad * pad, GstObject * parent, + guint64 offset, guint size, GstBuffer ** buffer) +{ + GstFlowReturn res; + GstPad *internal; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, internal, GST_FLOW_NOT_LINKED); + res = gst_pad_pull_range (internal, offset, size, buffer); + GST_PROXY_PAD_RELEASE_INTERNAL (internal); + + return res; +} + +static GstPad * +gst_proxy_pad_get_target (GstPad * pad) +{ + GstPad *target; + + GST_OBJECT_LOCK (pad); + target = gst_pad_get_peer (GST_PROXY_PAD_INTERNAL (pad)); + GST_OBJECT_UNLOCK (pad); + + return target; +} + +/** + * gst_proxy_pad_get_internal: + * @pad: the #GstProxyPad + * + * Get the internal pad of @pad. Unref target pad after usage. + * + * The internal pad of a #GstGhostPad is the internally used + * pad of opposite direction, which is used to link to the target. + * + * Returns: (transfer full) (nullable): the target #GstProxyPad, can + * be %NULL. Unref target pad after usage. + */ +GstProxyPad * +gst_proxy_pad_get_internal (GstProxyPad * pad) +{ + GstPad *internal; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL); + + GST_OBJECT_LOCK (pad); + internal = GST_PROXY_PAD_INTERNAL (pad); + if (internal) + gst_object_ref (internal); + GST_OBJECT_UNLOCK (pad); + + return GST_PROXY_PAD_CAST (internal); +} + +static void +gst_proxy_pad_class_init (GstProxyPadClass * klass) +{ + g_type_class_add_private (klass, sizeof (GstProxyPadPrivate)); + + /* Register common function pointer descriptions */ + GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default); +} + +static void +gst_proxy_pad_init (GstProxyPad * ppad) +{ + GstPad *pad = (GstPad *) ppad; + + GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad, + GST_TYPE_PROXY_PAD, GstProxyPadPrivate); + + gst_pad_set_iterate_internal_links_function (pad, + gst_proxy_pad_iterate_internal_links_default); + + GST_PAD_SET_PROXY_CAPS (pad); + GST_PAD_SET_PROXY_SCHEDULING (pad); + GST_PAD_SET_PROXY_ALLOCATION (pad); +} + + +/*********************************************************************** + * Ghost pads, implemented as a pair of proxy pads (sort of) + */ + + +#define GST_GHOST_PAD_PRIVATE(obj) (GST_GHOST_PAD_CAST (obj)->priv) + +struct _GstGhostPadPrivate +{ + /* with PROXY_LOCK */ + gboolean constructed; +}; + +G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD); + +static void gst_ghost_pad_dispose (GObject * object); + +static gboolean +gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean ret; + GstPad *other; + + GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok", + (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); + + /* in both cases (SRC and SINK) we activate just the internal pad. The targets + * will be activated later (or already in case of a ghost sinkpad). */ + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active); + GST_PROXY_PAD_RELEASE_INTERNAL (other); + + return ret; +} + +static gboolean +gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean ret; + GstPad *other; + + GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"), + GST_DEBUG_PAD_NAME (pad)); + + if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { + /* we are activated in pull mode by our peer element, which is a sinkpad + * that wants to operate in pull mode. This activation has to propagate + * upstream through the pipeline. We call the internal activation function, + * which will trigger gst_ghost_pad_activate_pull_default, which propagates even + * further upstream */ + GST_LOG_OBJECT (pad, "pad is src, activate internal"); + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); + GST_PROXY_PAD_RELEASE_INTERNAL (other); + } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { + /* We are SINK, the ghostpad is SRC, we propagate the activation upstream + * since we hold a pointer to the upstream peer. */ + GST_LOG_OBJECT (pad, "activating peer"); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); + gst_object_unref (other); + } else if (active) { + /* this is failure, we can't activate pull if there is no peer */ + GST_LOG_OBJECT (pad, "not src and no peer, failing"); + ret = FALSE; + } else { + GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing"); + ret = TRUE; + } + + return ret; +} + +/** + * gst_ghost_pad_internal_activate_mode_default: + * @pad: the #GstPad to activate or deactivate. + * @parent: (allow-none): the parent of @pad or %NULL + * @mode: the requested activation mode + * @active: whether the pad should be active or not. + * + * Invoke the default activate mode function of a proxy pad that is + * owned by a ghost pad. + * + * Returns: %TRUE if the operation was successful. + */ +gboolean +gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE); + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_ghost_pad_internal_activate_pull_default (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_ghost_pad_internal_activate_push_default (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + +static gboolean +gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean ret; + GstPad *other; + + g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE); + + GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal", + (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); + + /* just activate the internal pad */ + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active); + GST_PROXY_PAD_RELEASE_INTERNAL (other); + + return ret; +} + +static gboolean +gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean ret; + GstPad *other; + + GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"), + GST_DEBUG_PAD_NAME (pad)); + + if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { + /* the ghostpad is SRC and activated in pull mode by its peer, call the + * activation function of the internal pad to propagate the activation + * upstream */ + GST_LOG_OBJECT (pad, "pad is src, activate internal"); + GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); + GST_PROXY_PAD_RELEASE_INTERNAL (other); + } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { + /* We are SINK and activated by the internal pad, propagate activation + * upstream because we hold a ref to the upstream peer */ + GST_LOG_OBJECT (pad, "activating peer"); + ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); + gst_object_unref (other); + } else if (active) { + /* this is failure, we can't activate pull if there is no peer */ + GST_LOG_OBJECT (pad, "not src and no peer, failing"); + ret = FALSE; + } else { + GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing"); + ret = TRUE; + } + + return ret; +} + +/** + * gst_ghost_pad_activate_mode_default: + * @pad: the #GstPad to activate or deactivate. + * @parent: (allow-none): the parent of @pad or %NULL + * @mode: the requested activation mode + * @active: whether the pad should be active or not. + * + * Invoke the default activate mode function of a ghost pad. + * + * Returns: %TRUE if the operation was successful. + */ +gboolean +gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE); + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_ghost_pad_activate_pull_default (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_ghost_pad_activate_push_default (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + +static void +gst_ghost_pad_class_init (GstGhostPadClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstGhostPadPrivate)); + + gobject_class->dispose = gst_ghost_pad_dispose; + + GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default); +} + +static void +gst_ghost_pad_init (GstGhostPad * pad) +{ + GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad, + GST_TYPE_GHOST_PAD, GstGhostPadPrivate); + + gst_pad_set_activatemode_function (GST_PAD_CAST (pad), + gst_ghost_pad_activate_mode_default); +} + +static void +gst_ghost_pad_dispose (GObject * object) +{ + GstPad *pad; + GstPad *internal; + GstPad *peer; + + pad = GST_PAD (object); + + GST_DEBUG_OBJECT (pad, "dispose"); + + gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL); + + /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to + * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */ + peer = gst_pad_get_peer (pad); + if (peer) { + if (GST_PAD_IS_SRC (pad)) + gst_pad_unlink (pad, peer); + else + gst_pad_unlink (peer, pad); + + gst_object_unref (peer); + } + + GST_OBJECT_LOCK (pad); + internal = GST_PROXY_PAD_INTERNAL (pad); + if (internal) { + gst_pad_set_activatemode_function (internal, NULL); + + GST_PROXY_PAD_INTERNAL (pad) = NULL; + GST_PROXY_PAD_INTERNAL (internal) = NULL; + + /* disposes of the internal pad, since the ghostpad is the only possible object + * that has a refcount on the internal pad. */ + gst_object_unparent (GST_OBJECT_CAST (internal)); + } + + GST_OBJECT_UNLOCK (pad); + + G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); +} + +/** + * gst_ghost_pad_construct: + * @gpad: the newly allocated ghost pad + * + * Finish initialization of a newly allocated ghost pad. + * + * This function is most useful in language bindings and when subclassing + * #GstGhostPad; plugin and application developers normally will not call this + * function. Call this function directly after a call to g_object_new + * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL). + * + * Returns: %TRUE if the construction succeeds, %FALSE otherwise. + */ +gboolean +gst_ghost_pad_construct (GstGhostPad * gpad) +{ + GstPadDirection dir, otherdir; + GstPadTemplate *templ; + GstPad *pad, *internal; + + g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); + g_return_val_if_fail (!GST_GHOST_PAD_PRIVATE (gpad)->constructed, FALSE); + + g_object_get (gpad, "direction", &dir, "template", &templ, NULL); + + g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE); + + pad = GST_PAD (gpad); + + /* Set directional padfunctions for ghostpad */ + if (dir == GST_PAD_SINK) { + gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default); + gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default); + } else { + gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default); + } + + /* INTERNAL PAD, it always exists and is child of the ghostpad */ + otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; + if (templ) { + internal = + g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, + "direction", otherdir, "template", templ, NULL); + /* release ref obtained via g_object_get */ + gst_object_unref (templ); + } else { + internal = + g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, + "direction", otherdir, NULL); + } + GST_PAD_UNSET_FLUSHING (internal); + + /* Set directional padfunctions for internal pad */ + if (dir == GST_PAD_SRC) { + gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default); + gst_pad_set_chain_list_function (internal, + gst_proxy_pad_chain_list_default); + } else { + gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default); + } + + GST_OBJECT_LOCK (pad); + + /* now make the ghostpad a parent of the internal pad */ + if (!gst_object_set_parent (GST_OBJECT_CAST (internal), + GST_OBJECT_CAST (pad))) + goto parent_failed; + + /* The ghostpad is the parent of the internal pad and is the only object that + * can have a refcount on the internal pad. + * At this point, the GstGhostPad has a refcount of 1, and the internal pad has + * a refcount of 1. + * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose + * its refcount on the internal pad in the dispose method by un-parenting it. + * This is why we don't take extra refcounts in the assignments below + */ + GST_PROXY_PAD_INTERNAL (pad) = internal; + GST_PROXY_PAD_INTERNAL (internal) = pad; + + /* special activation functions for the internal pad */ + gst_pad_set_activatemode_function (internal, + gst_ghost_pad_internal_activate_mode_default); + + GST_OBJECT_UNLOCK (pad); + + GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE; + return TRUE; + + /* ERRORS */ +parent_failed: + { + GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s", + GST_DEBUG_PAD_NAME (internal)); + g_critical ("Could not set internal pad %s:%s", + GST_DEBUG_PAD_NAME (internal)); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +static GstPad * +gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, + GstPadTemplate * templ) +{ + GstGhostPad *ret; + g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); + + /* OBJECT CREATION */ + if (templ) { + GType pad_type = + GST_PAD_TEMPLATE_GTYPE (templ) == + G_TYPE_NONE ? GST_TYPE_GHOST_PAD : GST_PAD_TEMPLATE_GTYPE (templ); + + g_return_val_if_fail (g_type_is_a (pad_type, GST_TYPE_GHOST_PAD), NULL); + + ret = g_object_new (pad_type, "name", name, + "direction", dir, "template", templ, NULL); + } else { + ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, + "direction", dir, NULL); + } + + if (!gst_ghost_pad_construct (ret)) + goto construct_failed; + + return GST_PAD_CAST (ret); + +construct_failed: + /* already logged */ + gst_object_unref (ret); + return NULL; +} + +/** + * gst_ghost_pad_new_no_target: + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name. + * @dir: the direction of the ghostpad + * + * Create a new ghostpad without a target with the given direction. + * A target can be set on the ghostpad later with the + * gst_ghost_pad_set_target() function. + * + * The created ghostpad will not have a padtemplate. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ +GstPad * +gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir) +{ + GstPad *ret; + + g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); + + GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir); + + ret = gst_ghost_pad_new_full (name, dir, NULL); + + return ret; +} + +/** + * gst_ghost_pad_new: + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name + * @target: (transfer none): the pad to ghost. + * + * Create a new ghostpad with @target as the target. The direction will be taken + * from the target pad. @target must be unlinked. + * + * Will ref the target. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ +GstPad * +gst_ghost_pad_new (const gchar * name, GstPad * target) +{ + GstPad *ret; + + g_return_val_if_fail (GST_IS_PAD (target), NULL); + g_return_val_if_fail (!gst_pad_is_linked (target), NULL); + + GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name), + GST_DEBUG_PAD_NAME (target)); + + if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target)))) + if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target)) + goto set_target_failed; + + return ret; + + /* ERRORS */ +set_target_failed: + { + GST_WARNING_OBJECT (ret, "failed to set target %s:%s", + GST_DEBUG_PAD_NAME (target)); + gst_object_unref (ret); + return NULL; + } +} + +/** + * gst_ghost_pad_new_from_template: + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name. + * @target: (transfer none): the pad to ghost. + * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad. + * + * Create a new ghostpad with @target as the target. The direction will be taken + * from the target pad. The template used on the ghostpad will be @template. + * + * Will ref the target. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ + +GstPad * +gst_ghost_pad_new_from_template (const gchar * name, GstPad * target, + GstPadTemplate * templ) +{ + GstPad *ret; + + g_return_val_if_fail (GST_IS_PAD (target), NULL); + g_return_val_if_fail (!gst_pad_is_linked (target), NULL); + g_return_val_if_fail (templ != NULL, NULL); + g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == + GST_PAD_DIRECTION (target), NULL); + + GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name), + GST_DEBUG_PAD_NAME (target), templ); + + if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ))) + if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target)) + goto set_target_failed; + + return ret; + + /* ERRORS */ +set_target_failed: + { + GST_WARNING_OBJECT (ret, "failed to set target %s:%s", + GST_DEBUG_PAD_NAME (target)); + gst_object_unref (ret); + return NULL; + } +} + +/** + * gst_ghost_pad_new_no_target_from_template: + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name + * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from. + * + * Create a new ghostpad based on @templ, without setting a target. The + * direction will be taken from the @templ. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ +GstPad * +gst_ghost_pad_new_no_target_from_template (const gchar * name, + GstPadTemplate * templ) +{ + GstPad *ret; + + g_return_val_if_fail (templ != NULL, NULL); + + ret = + gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ); + + return ret; +} + +/** + * gst_ghost_pad_get_target: + * @gpad: the #GstGhostPad + * + * Get the target pad of @gpad. Unref target pad after usage. + * + * Returns: (transfer full) (nullable): the target #GstPad, can be + * %NULL if the ghostpad has no target set. Unref target pad after + * usage. + */ +GstPad * +gst_ghost_pad_get_target (GstGhostPad * gpad) +{ + GstPad *ret; + + g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL); + + ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad)); + + GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret)); + + return ret; +} + +/** + * gst_ghost_pad_set_target: + * @gpad: the #GstGhostPad + * @newtarget: (transfer none) (allow-none): the new pad target + * + * Set the new target of the ghostpad @gpad. Any existing target + * is unlinked and links to the new target are established. if @newtarget is + * %NULL the target will be cleared. + * + * Returns: %TRUE if the new target could be set. This function + * can return %FALSE when the internal pads could not be linked. + */ +gboolean +gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) +{ + GstPad *internal; + GstPad *oldtarget; + GstPadLinkReturn lret; + + g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); + g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE); + + GST_OBJECT_LOCK (gpad); + internal = GST_PROXY_PAD_INTERNAL (gpad); + + if (newtarget == internal) { + GST_OBJECT_UNLOCK (gpad); + GST_WARNING_OBJECT (gpad, "Target has already been set to %s:%s", + GST_DEBUG_PAD_NAME (newtarget)); + return TRUE; + } + + if (newtarget) + GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); + else + GST_DEBUG_OBJECT (gpad, "clearing target"); + + /* clear old target */ + if ((oldtarget = gst_pad_get_peer (internal))) { + GST_OBJECT_UNLOCK (gpad); + + /* unlink internal pad */ + if (GST_PAD_IS_SRC (internal)) + gst_pad_unlink (internal, oldtarget); + else + gst_pad_unlink (oldtarget, internal); + + gst_object_unref (oldtarget); + } else { + GST_OBJECT_UNLOCK (gpad); + } + + if (newtarget) { + /* and link to internal pad without any checks */ + GST_DEBUG_OBJECT (gpad, "connecting internal pad to target %" + GST_PTR_FORMAT, newtarget); + + if (GST_PAD_IS_SRC (internal)) + lret = + gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING); + else + lret = + gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING); + + if (lret != GST_PAD_LINK_OK) + goto link_failed; + } + + return TRUE; + + /* ERRORS */ +link_failed: + { + GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%s", + gst_pad_link_get_name (lret)); + return FALSE; + } +} diff --git a/gst/gstghostpad.h b/gst/gstghostpad.h new file mode 100644 index 0000000..98a364d --- /dev/null +++ b/gst/gstghostpad.h @@ -0,0 +1,155 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Andy Wingo + * + * gstghostpad.h: Proxy pads + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_GHOST_PAD_H__ +#define __GST_GHOST_PAD_H__ + + +#include + + +G_BEGIN_DECLS + +#define GST_TYPE_PROXY_PAD (gst_proxy_pad_get_type ()) +#define GST_IS_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD)) +#define GST_IS_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD)) +#define GST_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad)) +#define GST_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass)) + +typedef struct _GstProxyPad GstProxyPad; +typedef struct _GstProxyPadPrivate GstProxyPadPrivate; +typedef struct _GstProxyPadClass GstProxyPadClass; + +struct _GstProxyPad +{ + GstPad pad; + + /*< private >*/ + GstProxyPadPrivate *priv; +}; + +struct _GstProxyPadClass +{ + GstPadClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[1]; +}; + +GST_API +GType gst_proxy_pad_get_type (void); + +GST_API +GstProxyPad * gst_proxy_pad_get_internal (GstProxyPad *pad); + + +GST_API +GstIterator* gst_proxy_pad_iterate_internal_links_default (GstPad *pad, GstObject *parent) G_GNUC_MALLOC; + +GST_API +GstFlowReturn gst_proxy_pad_chain_default (GstPad *pad, GstObject *parent, + GstBuffer *buffer); +GST_API +GstFlowReturn gst_proxy_pad_chain_list_default (GstPad *pad, GstObject *parent, + GstBufferList *list); +GST_API +GstFlowReturn gst_proxy_pad_getrange_default (GstPad *pad, GstObject *parent, + guint64 offset, guint size, + GstBuffer **buffer); + +#define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ()) +#define GST_IS_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD)) +#define GST_IS_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD)) +#define GST_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad)) +#define GST_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass)) +#define GST_GHOST_PAD_CAST(obj) ((GstGhostPad*)(obj)) + +/** + * GstGhostPad: + * + * Opaque #GstGhostPad structure. + */ +typedef struct _GstGhostPad GstGhostPad; +typedef struct _GstGhostPadPrivate GstGhostPadPrivate; +typedef struct _GstGhostPadClass GstGhostPadClass; + +struct _GstGhostPad +{ + GstProxyPad pad; + + /*< private >*/ + GstGhostPadPrivate *priv; +}; + +struct _GstGhostPadClass +{ + GstProxyPadClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + + +GST_API +GType gst_ghost_pad_get_type (void); + +GST_API +GstPad* gst_ghost_pad_new (const gchar *name, GstPad *target) G_GNUC_MALLOC; + +GST_API +GstPad* gst_ghost_pad_new_no_target (const gchar *name, GstPadDirection dir) G_GNUC_MALLOC; + +GST_API +GstPad* gst_ghost_pad_new_from_template (const gchar *name, GstPad * target, GstPadTemplate * templ) G_GNUC_MALLOC; + +GST_API +GstPad* gst_ghost_pad_new_no_target_from_template (const gchar *name, GstPadTemplate * templ) G_GNUC_MALLOC; + +GST_API +GstPad* gst_ghost_pad_get_target (GstGhostPad *gpad); + +GST_API +gboolean gst_ghost_pad_set_target (GstGhostPad *gpad, GstPad *newtarget); + +GST_API +gboolean gst_ghost_pad_construct (GstGhostPad *gpad); + +GST_API +gboolean gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +GST_API +gboolean gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstGhostPad, gst_object_unref) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstProxyPad, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_GHOST_PAD_H__ */ diff --git a/gst/gstinfo.c b/gst/gstinfo.c new file mode 100644 index 0000000..2485eee --- /dev/null +++ b/gst/gstinfo.c @@ -0,0 +1,3101 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2003 Benjamin Otte + * Copyright (C) 2008-2009 Tim-Philipp Müller + * + * gstinfo.c: debugging 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstinfo + * @title: GstInfo + * @short_description: Debugging and logging facilities + * @see_also: #gst-running for command line parameters + * and environment variables that affect the debugging output. + * + * GStreamer's debugging subsystem is an easy way to get information about what + * the application is doing. It is not meant for programming errors. Use GLib + * methods (g_warning and friends) for that. + * + * The debugging subsystem works only after GStreamer has been initialized + * - for example by calling gst_init(). + * + * The debugging subsystem is used to log informational messages while the + * application runs. Each messages has some properties attached to it. Among + * these properties are the debugging category, the severity (called "level" + * here) and an optional #GObject it belongs to. Each of these messages is sent + * to all registered debugging handlers, which then handle the messages. + * GStreamer attaches a default handler on startup, which outputs requested + * messages to stderr. + * + * Messages are output by using shortcut macros like #GST_DEBUG, + * #GST_CAT_ERROR_OBJECT or similar. These all expand to calling gst_debug_log() + * with the right parameters. + * The only thing a developer will probably want to do is define his own + * categories. This is easily done with 3 lines. At the top of your code, + * declare + * the variables and set the default category. + * |[ + * GST_DEBUG_CATEGORY_STATIC (my_category); // define category (statically) + * #define GST_CAT_DEFAULT my_category // set as default + * ]| + * After that you only need to initialize the category. + * |[ + * GST_DEBUG_CATEGORY_INIT (my_category, "my category", + * 0, "This is my very own"); + * ]| + * Initialization must be done before the category is used first. + * Plugins do this + * in their plugin_init function, libraries and applications should do that + * during their initialization. + * + * The whole debugging subsystem can be disabled at build time with passing the + * --disable-gst-debug switch to configure. If this is done, every function, + * macro and even structs described in this file evaluate to default values or + * nothing at all. + * So don't take addresses of these functions or use other tricks. + * If you must do that for some reason, there is still an option. + * If the debugging + * subsystem was compiled out, #GST_DISABLE_GST_DEBUG is defined in + * <gst/gst.h>, + * so you can check that before doing your trick. + * Disabling the debugging subsystem will give you a slight (read: unnoticeable) + * speed increase and will reduce the size of your compiled code. The GStreamer + * library itself becomes around 10% smaller. + * + * Please note that there are naming conventions for the names of debugging + * categories. These are explained at GST_DEBUG_CATEGORY_INIT(). + */ + +#define GST_INFO_C +#include "gst_private.h" +#include "gstinfo.h" + +#undef gst_debug_remove_log_function +#undef gst_debug_add_log_function + +#ifndef GST_DISABLE_GST_DEBUG +#ifdef HAVE_DLFCN_H +# include +#endif +#include /* fprintf */ +#include +#include +#ifdef HAVE_UNISTD_H +# include /* getpid on UNIX */ +#endif +#ifdef HAVE_PROCESS_H +# include /* getpid on win32 */ +#endif +#include /* G_VA_COPY */ +#ifdef G_OS_WIN32 +# define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ +# include /* GetStdHandle, windows console */ +#endif + +#include "gst_private.h" +#include "gstutils.h" +#include "gstquark.h" +#include "gstsegment.h" +#include "gstvalue.h" +#include "gstcapsfeatures.h" + +#ifdef HAVE_VALGRIND_VALGRIND_H +# include +#endif +#include /* g_sprintf */ + +/* our own printf implementation with custom extensions to %p for caps etc. */ +#include "printf/printf.h" +#include "printf/printf-extension.h" + +static char *gst_info_printf_pointer_extension_func (const char *format, + void *ptr); +#else /* GST_DISABLE_GST_DEBUG */ + +#include +#endif /* !GST_DISABLE_GST_DEBUG */ + +#ifdef HAVE_UNWIND +/* No need for remote debugging so turn on the 'local only' optimizations in + * libunwind */ +#define UNW_LOCAL_ONLY + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DW +#include +#endif /* HAVE_DW */ +#endif /* HAVE_UNWIND */ + +#ifdef HAVE_BACKTRACE +#include +#define BT_BUF_SIZE 100 +#endif /* HAVE_BACKTRACE */ + +extern gboolean gst_is_initialized (void); + +/* we want these symbols exported even if debug is disabled, to maintain + * ABI compatibility. Unless GST_REMOVE_DISABLED is defined. */ +#if !defined(GST_DISABLE_GST_DEBUG) || !defined(GST_REMOVE_DISABLED) + +/* disabled by default, as soon as some threshold is set > NONE, + * it becomes enabled. */ +gboolean _gst_debug_enabled = FALSE; +GstDebugLevel _gst_debug_min = GST_LEVEL_NONE; + +GstDebugCategory *GST_CAT_DEFAULT = NULL; + +GstDebugCategory *GST_CAT_GST_INIT = NULL; +GstDebugCategory *GST_CAT_MEMORY = NULL; +GstDebugCategory *GST_CAT_PARENTAGE = NULL; +GstDebugCategory *GST_CAT_STATES = NULL; +GstDebugCategory *GST_CAT_SCHEDULING = NULL; + +GstDebugCategory *GST_CAT_BUFFER = NULL; +GstDebugCategory *GST_CAT_BUFFER_LIST = NULL; +GstDebugCategory *GST_CAT_BUS = NULL; +GstDebugCategory *GST_CAT_CAPS = NULL; +GstDebugCategory *GST_CAT_CLOCK = NULL; +GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL; +GstDebugCategory *GST_CAT_PADS = NULL; +GstDebugCategory *GST_CAT_PERFORMANCE = NULL; +GstDebugCategory *GST_CAT_PIPELINE = NULL; +GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL; +GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL; +GstDebugCategory *GST_CAT_PROPERTIES = NULL; +GstDebugCategory *GST_CAT_NEGOTIATION = NULL; +GstDebugCategory *GST_CAT_REFCOUNTING = NULL; +GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL; +GstDebugCategory *GST_CAT_EVENT = NULL; +GstDebugCategory *GST_CAT_MESSAGE = NULL; +GstDebugCategory *GST_CAT_PARAMS = NULL; +GstDebugCategory *GST_CAT_CALL_TRACE = NULL; +GstDebugCategory *GST_CAT_SIGNAL = NULL; +GstDebugCategory *GST_CAT_PROBE = NULL; +GstDebugCategory *GST_CAT_REGISTRY = NULL; +GstDebugCategory *GST_CAT_QOS = NULL; +GstDebugCategory *_priv_GST_CAT_POLL = NULL; +GstDebugCategory *GST_CAT_META = NULL; +GstDebugCategory *GST_CAT_LOCKING = NULL; +GstDebugCategory *GST_CAT_CONTEXT = NULL; +GstDebugCategory *_priv_GST_CAT_PROTECTION = NULL; + + +#endif /* !defined(GST_DISABLE_GST_DEBUG) || !defined(GST_REMOVE_DISABLED) */ + +#ifndef GST_DISABLE_GST_DEBUG + +/* underscore is to prevent conflict with GST_CAT_DEBUG define */ +GST_DEBUG_CATEGORY_STATIC (_GST_CAT_DEBUG); + +#if 0 +#if defined __sgi__ +#include +typedef struct DL_INFO +{ + const char *dli_fname; + void *dli_fbase; + const char *dli_sname; + void *dli_saddr; + int dli_version; + int dli_reserved1; + long dli_reserved[4]; +} +Dl_info; + +#define _RLD_DLADDR 14 +int dladdr (void *address, Dl_info * dl); + +int +dladdr (void *address, Dl_info * dl) +{ + void *v; + + v = _rld_new_interface (_RLD_DLADDR, address, dl); + return (int) v; +} +#endif /* __sgi__ */ +#endif + +static void gst_debug_reset_threshold (gpointer category, gpointer unused); +static void gst_debug_reset_all_thresholds (void); + +struct _GstDebugMessage +{ + gchar *message; + const gchar *format; + va_list arguments; +}; + +/* list of all name/level pairs from --gst-debug and GST_DEBUG */ +static GMutex __level_name_mutex; +static GSList *__level_name = NULL; +typedef struct +{ + GPatternSpec *pat; + GstDebugLevel level; +} +LevelNameEntry; + +/* list of all categories */ +static GMutex __cat_mutex; +static GSList *__categories = NULL; + +static GstDebugCategory *_gst_debug_get_category_locked (const gchar * name); + + +/* all registered debug handlers */ +typedef struct +{ + GstLogFunction func; + gpointer user_data; + GDestroyNotify notify; +} +LogFuncEntry; +static GMutex __log_func_mutex; +static GSList *__log_functions = NULL; + +/* whether to add the default log function in gst_init() */ +static gboolean add_default_log_func = TRUE; + +#define PRETTY_TAGS_DEFAULT TRUE +static gboolean pretty_tags = PRETTY_TAGS_DEFAULT; + +static volatile gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT; +static volatile gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON; + +/* FIXME: export this? */ +gboolean +_priv_gst_in_valgrind (void) +{ + static enum + { + GST_VG_UNCHECKED, + GST_VG_NO_VALGRIND, + GST_VG_INSIDE + } + in_valgrind = GST_VG_UNCHECKED; + + if (in_valgrind == GST_VG_UNCHECKED) { +#ifdef HAVE_VALGRIND_VALGRIND_H + if (RUNNING_ON_VALGRIND) { + GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind"); + in_valgrind = GST_VG_INSIDE; + } else { + GST_CAT_LOG (GST_CAT_GST_INIT, "not doing extra valgrind stuff"); + in_valgrind = GST_VG_NO_VALGRIND; + } +#else + in_valgrind = GST_VG_NO_VALGRIND; +#endif + g_assert (in_valgrind == GST_VG_NO_VALGRIND || + in_valgrind == GST_VG_INSIDE); + } + return (in_valgrind == GST_VG_INSIDE); +} + +static gchar * +_replace_pattern_in_gst_debug_file_name (gchar * name, const char *token, + guint val) +{ + gchar *token_start; + if ((token_start = strstr (name, token))) { + gsize token_len = strlen (token); + gchar *name_prefix = name; + gchar *name_suffix = token_start + token_len; + token_start[0] = '\0'; + name = g_strdup_printf ("%s%u%s", name_prefix, val, name_suffix); + g_free (name_prefix); + } + return name; +} + +static gchar * +_priv_gst_debug_file_name (const gchar * env) +{ + gchar *name; + + name = g_strdup (env); + name = _replace_pattern_in_gst_debug_file_name (name, "%p", getpid ()); + name = _replace_pattern_in_gst_debug_file_name (name, "%r", g_random_int ()); + + return name; +} + +/* Initialize the debugging system */ +void +_priv_gst_debug_init (void) +{ + const gchar *env; + FILE *log_file; + + if (add_default_log_func) { + env = g_getenv ("GST_DEBUG_FILE"); + if (env != NULL && *env != '\0') { + if (strcmp (env, "-") == 0) { + log_file = stdout; + } else { + gchar *name = _priv_gst_debug_file_name (env); + log_file = g_fopen (name, "w"); + g_free (name); + if (log_file == NULL) { + g_printerr ("Could not open log file '%s' for writing: %s\n", env, + g_strerror (errno)); + log_file = stderr; + } + } + } else { + log_file = stderr; + } + + gst_debug_add_log_function (gst_debug_log_default, log_file, NULL); + } + + __gst_printf_pointer_extension_set_func + (gst_info_printf_pointer_extension_func); + + /* do NOT use a single debug function before this line has been run */ + GST_CAT_DEFAULT = _gst_debug_category_new ("default", + GST_DEBUG_UNDERLINE, NULL); + _GST_CAT_DEBUG = _gst_debug_category_new ("GST_DEBUG", + GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, "debugging subsystem"); + + /* FIXME: add descriptions here */ + GST_CAT_GST_INIT = _gst_debug_category_new ("GST_INIT", + GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL); + GST_CAT_MEMORY = _gst_debug_category_new ("GST_MEMORY", + GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, "memory"); + GST_CAT_PARENTAGE = _gst_debug_category_new ("GST_PARENTAGE", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_STATES = _gst_debug_category_new ("GST_STATES", + GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL); + GST_CAT_SCHEDULING = _gst_debug_category_new ("GST_SCHEDULING", + GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL); + GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER", + GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL); + GST_CAT_BUFFER_LIST = _gst_debug_category_new ("GST_BUFFER_LIST", + GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL); + GST_CAT_BUS = _gst_debug_category_new ("GST_BUS", GST_DEBUG_BG_YELLOW, NULL); + GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS", + GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL); + GST_CAT_CLOCK = _gst_debug_category_new ("GST_CLOCK", + GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, NULL); + GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_PADS = _gst_debug_category_new ("GST_PADS", + GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_RED, NULL); + GST_CAT_PERFORMANCE = _gst_debug_category_new ("GST_PERFORMANCE", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_PLUGIN_LOADING = _gst_debug_category_new ("GST_PLUGIN_LOADING", + GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL); + GST_CAT_PLUGIN_INFO = _gst_debug_category_new ("GST_PLUGIN_INFO", + GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL); + GST_CAT_PROPERTIES = _gst_debug_category_new ("GST_PROPERTIES", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL); + GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION", + GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL); + GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING", + GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_BLUE, NULL); + GST_CAT_ERROR_SYSTEM = _gst_debug_category_new ("GST_ERROR_SYSTEM", + GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_WHITE, NULL); + + GST_CAT_EVENT = _gst_debug_category_new ("GST_EVENT", + GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL); + GST_CAT_MESSAGE = _gst_debug_category_new ("GST_MESSAGE", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_PARAMS = _gst_debug_category_new ("GST_PARAMS", + GST_DEBUG_BOLD | GST_DEBUG_FG_BLACK | GST_DEBUG_BG_YELLOW, NULL); + GST_CAT_CALL_TRACE = _gst_debug_category_new ("GST_CALL_TRACE", + GST_DEBUG_BOLD, NULL); + GST_CAT_SIGNAL = _gst_debug_category_new ("GST_SIGNAL", + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL); + GST_CAT_PROBE = _gst_debug_category_new ("GST_PROBE", + GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "pad probes"); + GST_CAT_REGISTRY = _gst_debug_category_new ("GST_REGISTRY", 0, "registry"); + GST_CAT_QOS = _gst_debug_category_new ("GST_QOS", 0, "QoS"); + _priv_GST_CAT_POLL = _gst_debug_category_new ("GST_POLL", 0, "poll"); + GST_CAT_META = _gst_debug_category_new ("GST_META", 0, "meta"); + GST_CAT_LOCKING = _gst_debug_category_new ("GST_LOCKING", 0, "locking"); + GST_CAT_CONTEXT = _gst_debug_category_new ("GST_CONTEXT", 0, NULL); + _priv_GST_CAT_PROTECTION = + _gst_debug_category_new ("GST_PROTECTION", 0, "protection"); + + /* print out the valgrind message if we're in valgrind */ + _priv_gst_in_valgrind (); + + env = g_getenv ("GST_DEBUG_OPTIONS"); + if (env != NULL) { + if (strstr (env, "full_tags") || strstr (env, "full-tags")) + pretty_tags = FALSE; + else if (strstr (env, "pretty_tags") || strstr (env, "pretty-tags")) + pretty_tags = TRUE; + } + + if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL) + gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_OFF); + env = g_getenv ("GST_DEBUG_COLOR_MODE"); + if (env) + gst_debug_set_color_mode_from_string (env); + + env = g_getenv ("GST_DEBUG"); + if (env) + gst_debug_set_threshold_from_string (env, FALSE); +} + +/* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */ +#define GST_CAT_DEFAULT _GST_CAT_DEBUG + +/** + * gst_debug_log: + * @category: category to log + * @level: level of the message is in + * @file: the file that emitted the message, usually the __FILE__ identifier + * @function: the function that emitted the message + * @line: the line from that the message was emitted, usually __LINE__ + * @object: (transfer none) (allow-none): the object this message relates to, + * or %NULL if none + * @format: a printf style format string + * @...: optional arguments for the format + * + * Logs the given message using the currently registered debugging handlers. + */ +void +gst_debug_log (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, const gchar * format, ...) +{ + va_list var_args; + + va_start (var_args, format); + gst_debug_log_valist (category, level, file, function, line, object, format, + var_args); + va_end (var_args); +} + +/* based on g_basename(), which we can't use because it was deprecated */ +static inline const gchar * +gst_path_basename (const gchar * file_name) +{ + register const gchar *base; + + base = strrchr (file_name, G_DIR_SEPARATOR); + + { + const gchar *q = strrchr (file_name, '/'); + if (base == NULL || (q != NULL && q > base)) + base = q; + } + + if (base) + return base + 1; + + if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':') + return file_name + 2; + + return file_name; +} + +/** + * gst_debug_log_valist: + * @category: category to log + * @level: level of the message is in + * @file: the file that emitted the message, usually the __FILE__ identifier + * @function: the function that emitted the message + * @line: the line from that the message was emitted, usually __LINE__ + * @object: (transfer none) (allow-none): the object this message relates to, + * or %NULL if none + * @format: a printf style format string + * @args: optional arguments for the format + * + * Logs the given message using the currently registered debugging handlers. + */ +void +gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, const gchar * format, va_list args) +{ + GstDebugMessage message; + LogFuncEntry *entry; + GSList *handler; + + g_return_if_fail (category != NULL); + + if (level > gst_debug_category_get_threshold (category)) + return; + + g_return_if_fail (file != NULL); + g_return_if_fail (function != NULL); + g_return_if_fail (format != NULL); + + message.message = NULL; + message.format = format; + G_VA_COPY (message.arguments, args); + + handler = __log_functions; + while (handler) { + entry = handler->data; + handler = g_slist_next (handler); + entry->func (category, level, file, function, line, object, &message, + entry->user_data); + } + g_free (message.message); + va_end (message.arguments); +} + +/** + * gst_debug_message_get: + * @message: a debug message + * + * Gets the string representation of a #GstDebugMessage. This function is used + * in debug handlers to extract the message. + * + * Returns: (nullable): the string representation of a #GstDebugMessage. + */ +const gchar * +gst_debug_message_get (GstDebugMessage * message) +{ + if (message->message == NULL) { + int len; + + len = __gst_vasprintf (&message->message, message->format, + message->arguments); + + if (len < 0) + message->message = NULL; + } + return message->message; +} + +#define MAX_BUFFER_DUMP_STRING_LEN 100 + +/* structure_to_pretty_string: + * @str: a serialized #GstStructure + * + * If the serialized structure contains large buffers such as images the hex + * representation of those buffers will be shortened so that the string remains + * readable. + * + * Returns: the filtered string + */ +static gchar * +prettify_structure_string (gchar * str) +{ + gchar *pos = str, *end; + + while ((pos = strstr (pos, "(buffer)"))) { + guint count = 0; + + pos += strlen ("(buffer)"); + for (end = pos; *end != '\0' && *end != ';' && *end != ' '; ++end) + ++count; + if (count > MAX_BUFFER_DUMP_STRING_LEN) { + memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 6, "..", 2); + memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 4, pos + count - 4, 4); + memmove (pos + MAX_BUFFER_DUMP_STRING_LEN, pos + count, + strlen (pos + count) + 1); + pos += MAX_BUFFER_DUMP_STRING_LEN; + } + } + + return str; +} + +static inline gchar * +gst_info_structure_to_string (const GstStructure * s) +{ + if (G_LIKELY (s)) { + gchar *str = gst_structure_to_string (s); + if (G_UNLIKELY (pretty_tags && s->name == GST_QUARK (TAGLIST))) + return prettify_structure_string (str); + else + return str; + } + return NULL; +} + +static inline gchar * +gst_info_describe_buffer (GstBuffer * buffer) +{ + const gchar *offset_str = "none"; + const gchar *offset_end_str = "none"; + gchar offset_buf[32], offset_end_buf[32]; + + if (GST_BUFFER_OFFSET_IS_VALID (buffer)) { + g_snprintf (offset_buf, sizeof (offset_buf), "%" G_GUINT64_FORMAT, + GST_BUFFER_OFFSET (buffer)); + offset_str = offset_buf; + } + if (GST_BUFFER_OFFSET_END_IS_VALID (buffer)) { + g_snprintf (offset_end_buf, sizeof (offset_end_buf), "%" G_GUINT64_FORMAT, + GST_BUFFER_OFFSET_END (buffer)); + offset_end_str = offset_end_buf; + } + + return g_strdup_printf ("buffer: %p, pts %" GST_TIME_FORMAT ", dts %" + GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT + ", offset %s, offset_end %s, flags 0x%x", buffer, + GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), + gst_buffer_get_size (buffer), offset_str, offset_end_str, + GST_BUFFER_FLAGS (buffer)); +} + +static inline gchar * +gst_info_describe_buffer_list (GstBufferList * list) +{ + GstClockTime pts = GST_CLOCK_TIME_NONE; + GstClockTime dts = GST_CLOCK_TIME_NONE; + gsize total_size = 0; + guint n, i; + + n = gst_buffer_list_length (list); + for (i = 0; i < n; ++i) { + GstBuffer *buf = gst_buffer_list_get (list, i); + + if (i == 0) { + pts = GST_BUFFER_PTS (buf); + dts = GST_BUFFER_DTS (buf); + } + + total_size += gst_buffer_get_size (buf); + } + + return g_strdup_printf ("bufferlist: %p, %u buffers, pts %" GST_TIME_FORMAT + ", dts %" GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT, list, n, + GST_TIME_ARGS (pts), GST_TIME_ARGS (dts), total_size); +} + +static inline gchar * +gst_info_describe_event (GstEvent * event) +{ + gchar *s, *ret; + + s = gst_info_structure_to_string (gst_event_get_structure (event)); + ret = g_strdup_printf ("%s event: %p, time %" GST_TIME_FORMAT + ", seq-num %d, %s", GST_EVENT_TYPE_NAME (event), event, + GST_TIME_ARGS (GST_EVENT_TIMESTAMP (event)), GST_EVENT_SEQNUM (event), + (s ? s : "(NULL)")); + g_free (s); + return ret; +} + +static inline gchar * +gst_info_describe_message (GstMessage * message) +{ + gchar *s, *ret; + + s = gst_info_structure_to_string (gst_message_get_structure (message)); + ret = g_strdup_printf ("%s message: %p, time %" GST_TIME_FORMAT + ", seq-num %d, element '%s', %s", GST_MESSAGE_TYPE_NAME (message), + message, GST_TIME_ARGS (GST_MESSAGE_TIMESTAMP (message)), + GST_MESSAGE_SEQNUM (message), + ((message->src) ? GST_ELEMENT_NAME (message->src) : "(NULL)"), + (s ? s : "(NULL)")); + g_free (s); + return ret; +} + +static inline gchar * +gst_info_describe_query (GstQuery * query) +{ + gchar *s, *ret; + + s = gst_info_structure_to_string (gst_query_get_structure (query)); + ret = g_strdup_printf ("%s query: %p, %s", GST_QUERY_TYPE_NAME (query), + query, (s ? s : "(NULL)")); + g_free (s); + return ret; +} + +static inline gchar * +gst_info_describe_stream (GstStream * stream) +{ + gchar *ret, *caps_str = NULL, *tags_str = NULL; + GstCaps *caps; + GstTagList *tags; + + caps = gst_stream_get_caps (stream); + if (caps) { + caps_str = gst_caps_to_string (caps); + gst_caps_unref (caps); + } + + tags = gst_stream_get_tags (stream); + if (tags) { + tags_str = gst_tag_list_to_string (tags); + gst_tag_list_unref (tags); + } + + ret = + g_strdup_printf ("stream %s %p, ID %s, flags 0x%x, caps [%s], tags [%s]", + gst_stream_type_get_name (gst_stream_get_stream_type (stream)), stream, + gst_stream_get_stream_id (stream), gst_stream_get_stream_flags (stream), + caps_str ? caps_str : "", tags_str ? tags_str : ""); + + g_free (caps_str); + g_free (tags_str); + + return ret; +} + +static inline gchar * +gst_info_describe_stream_collection (GstStreamCollection * collection) +{ + gchar *ret; + GString *streams_str; + guint i; + + streams_str = g_string_new ("<"); + for (i = 0; i < gst_stream_collection_get_size (collection); i++) { + GstStream *stream = gst_stream_collection_get_stream (collection, i); + gchar *s; + + s = gst_info_describe_stream (stream); + g_string_append_printf (streams_str, " %s,", s); + g_free (s); + } + g_string_append (streams_str, " >"); + + ret = g_strdup_printf ("collection %p (%d streams) %s", collection, + gst_stream_collection_get_size (collection), streams_str->str); + + g_string_free (streams_str, TRUE); + return ret; +} + +static gchar * +gst_debug_print_object (gpointer ptr) +{ + GObject *object = (GObject *) ptr; + +#ifdef unused + /* This is a cute trick to detect unmapped memory, but is unportable, + * slow, screws around with madvise, and not actually that useful. */ + { + int ret; + + ret = madvise ((void *) ((unsigned long) ptr & (~0xfff)), 4096, 0); + if (ret == -1 && errno == ENOMEM) { + buffer = g_strdup_printf ("%p (unmapped memory)", ptr); + } + } +#endif + + /* nicely printed object */ + if (object == NULL) { + return g_strdup ("(NULL)"); + } + if (GST_IS_CAPS (ptr)) { + return gst_caps_to_string ((const GstCaps *) ptr); + } + if (GST_IS_STRUCTURE (ptr)) { + return gst_info_structure_to_string ((const GstStructure *) ptr); + } + if (*(GType *) ptr == GST_TYPE_CAPS_FEATURES) { + return gst_caps_features_to_string ((const GstCapsFeatures *) ptr); + } + if (GST_IS_TAG_LIST (ptr)) { + gchar *str = gst_tag_list_to_string ((GstTagList *) ptr); + if (G_UNLIKELY (pretty_tags)) + return prettify_structure_string (str); + else + return str; + } + if (*(GType *) ptr == GST_TYPE_DATE_TIME) { + return __gst_date_time_serialize ((GstDateTime *) ptr, TRUE); + } + if (GST_IS_BUFFER (ptr)) { + return gst_info_describe_buffer (GST_BUFFER_CAST (ptr)); + } + if (GST_IS_BUFFER_LIST (ptr)) { + return gst_info_describe_buffer_list (GST_BUFFER_LIST_CAST (ptr)); + } +#ifdef USE_POISONING + if (*(guint32 *) ptr == 0xffffffff) { + return g_strdup_printf ("", ptr); + } +#endif + if (GST_IS_MESSAGE (object)) { + return gst_info_describe_message (GST_MESSAGE_CAST (object)); + } + if (GST_IS_QUERY (object)) { + return gst_info_describe_query (GST_QUERY_CAST (object)); + } + if (GST_IS_EVENT (object)) { + return gst_info_describe_event (GST_EVENT_CAST (object)); + } + if (GST_IS_CONTEXT (object)) { + GstContext *context = GST_CONTEXT_CAST (object); + gchar *s, *ret; + const gchar *type; + const GstStructure *structure; + + type = gst_context_get_context_type (context); + structure = gst_context_get_structure (context); + + s = gst_info_structure_to_string (structure); + + ret = g_strdup_printf ("context '%s'='%s'", type, s); + g_free (s); + return ret; + } + if (GST_IS_STREAM (object)) { + return gst_info_describe_stream (GST_STREAM_CAST (object)); + } + if (GST_IS_STREAM_COLLECTION (object)) { + return + gst_info_describe_stream_collection (GST_STREAM_COLLECTION_CAST + (object)); + } + if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) { + return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object)); + } + if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) { + return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object)); + } + if (G_IS_OBJECT (object)) { + return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object); + } + + return g_strdup_printf ("%p", ptr); +} + +static gchar * +gst_debug_print_segment (gpointer ptr) +{ + GstSegment *segment = (GstSegment *) ptr; + + /* nicely printed segment */ + if (segment == NULL) { + return g_strdup ("(NULL)"); + } + + switch (segment->format) { + case GST_FORMAT_UNDEFINED:{ + return g_strdup_printf ("UNDEFINED segment"); + } + case GST_FORMAT_TIME:{ + return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT + ", offset=%" GST_TIME_FORMAT ", stop=%" GST_TIME_FORMAT + ", rate=%f, applied_rate=%f" ", flags=0x%02x, time=%" GST_TIME_FORMAT + ", base=%" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT + ", duration %" GST_TIME_FORMAT, GST_TIME_ARGS (segment->start), + GST_TIME_ARGS (segment->offset), GST_TIME_ARGS (segment->stop), + segment->rate, segment->applied_rate, (guint) segment->flags, + GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->base), + GST_TIME_ARGS (segment->position), GST_TIME_ARGS (segment->duration)); + } + default:{ + const gchar *format_name; + + format_name = gst_format_get_name (segment->format); + if (G_UNLIKELY (format_name == NULL)) + format_name = "(UNKNOWN FORMAT)"; + return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT + ", offset=%" G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT + ", rate=%f, applied_rate=%f" ", flags=0x%02x, time=%" G_GINT64_FORMAT + ", base=%" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT + ", duration %" G_GINT64_FORMAT, format_name, segment->start, + segment->offset, segment->stop, segment->rate, segment->applied_rate, + (guint) segment->flags, segment->time, segment->base, + segment->position, segment->duration); + } + } +} + +static char * +gst_info_printf_pointer_extension_func (const char *format, void *ptr) +{ + char *s = NULL; + + if (format[0] == 'p' && format[1] == '\a') { + switch (format[2]) { + case 'A': /* GST_PTR_FORMAT */ + s = gst_debug_print_object (ptr); + break; + case 'B': /* GST_SEGMENT_FORMAT */ + s = gst_debug_print_segment (ptr); + break; + case 'a': /* GST_WRAPPED_PTR_FORMAT */ + s = priv_gst_string_take_and_wrap (gst_debug_print_object (ptr)); + break; + default: + /* must have been compiled against a newer version with an extension + * we don't known about yet - just ignore and fallback to %p below */ + break; + } + } + if (s == NULL) + s = g_strdup_printf ("%p", ptr); + + return s; +} + +/** + * gst_debug_construct_term_color: + * @colorinfo: the color info + * + * Constructs a string that can be used for getting the desired color in color + * terminals. + * You need to free the string after use. + * + * Returns: (transfer full) (type gchar*): a string containing the color + * definition + */ +gchar * +gst_debug_construct_term_color (guint colorinfo) +{ + GString *color; + + color = g_string_new ("\033[00"); + + if (colorinfo & GST_DEBUG_BOLD) { + g_string_append_len (color, ";01", 3); + } + if (colorinfo & GST_DEBUG_UNDERLINE) { + g_string_append_len (color, ";04", 3); + } + if (colorinfo & GST_DEBUG_FG_MASK) { + g_string_append_printf (color, ";3%1d", colorinfo & GST_DEBUG_FG_MASK); + } + if (colorinfo & GST_DEBUG_BG_MASK) { + g_string_append_printf (color, ";4%1d", + (colorinfo & GST_DEBUG_BG_MASK) >> 4); + } + g_string_append_c (color, 'm'); + + return g_string_free (color, FALSE); +} + +/** + * gst_debug_construct_win_color: + * @colorinfo: the color info + * + * Constructs an integer that can be used for getting the desired color in + * windows' terminals (cmd.exe). As there is no mean to underline, we simply + * ignore this attribute. + * + * This function returns 0 on non-windows machines. + * + * Returns: an integer containing the color definition + */ +gint +gst_debug_construct_win_color (guint colorinfo) +{ + gint color = 0; +#ifdef G_OS_WIN32 + static const guchar ansi_to_win_fg[8] = { + 0, /* black */ + FOREGROUND_RED, /* red */ + FOREGROUND_GREEN, /* green */ + FOREGROUND_RED | FOREGROUND_GREEN, /* yellow */ + FOREGROUND_BLUE, /* blue */ + FOREGROUND_RED | FOREGROUND_BLUE, /* magenta */ + FOREGROUND_GREEN | FOREGROUND_BLUE, /* cyan */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* white */ + }; + static const guchar ansi_to_win_bg[8] = { + 0, + BACKGROUND_RED, + BACKGROUND_GREEN, + BACKGROUND_RED | BACKGROUND_GREEN, + BACKGROUND_BLUE, + BACKGROUND_RED | BACKGROUND_BLUE, + BACKGROUND_GREEN | FOREGROUND_BLUE, + BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE + }; + + /* we draw black as white, as cmd.exe can only have black bg */ + if ((colorinfo & (GST_DEBUG_FG_MASK | GST_DEBUG_BG_MASK)) == 0) { + color = ansi_to_win_fg[7]; + } + if (colorinfo & GST_DEBUG_UNDERLINE) { + color |= BACKGROUND_INTENSITY; + } + if (colorinfo & GST_DEBUG_BOLD) { + color |= FOREGROUND_INTENSITY; + } + if (colorinfo & GST_DEBUG_FG_MASK) { + color |= ansi_to_win_fg[colorinfo & GST_DEBUG_FG_MASK]; + } + if (colorinfo & GST_DEBUG_BG_MASK) { + color |= ansi_to_win_bg[(colorinfo & GST_DEBUG_BG_MASK) >> 4]; + } +#endif + return color; +} + +/* width of %p varies depending on actual value of pointer, which can make + * output unevenly aligned if multiple threads are involved, hence the %14p + * (should really be %18p, but %14p seems a good compromise between too many + * white spaces and likely unalignment on my system) */ +#if defined (GLIB_SIZEOF_VOID_P) && GLIB_SIZEOF_VOID_P == 8 +#define PTR_FMT "%14p" +#else +#define PTR_FMT "%10p" +#endif +#define PID_FMT "%5d" +#define CAT_FMT "%20s %s:%d:%s:%s" + +#ifdef G_OS_WIN32 +static const guchar levelcolormap_w32[GST_LEVEL_COUNT] = { + /* GST_LEVEL_NONE */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + /* GST_LEVEL_ERROR */ + FOREGROUND_RED | FOREGROUND_INTENSITY, + /* GST_LEVEL_WARNING */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + /* GST_LEVEL_INFO */ + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + /* GST_LEVEL_DEBUG */ + FOREGROUND_GREEN | FOREGROUND_BLUE, + /* GST_LEVEL_LOG */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + /* GST_LEVEL_FIXME */ + FOREGROUND_RED | FOREGROUND_GREEN, + /* GST_LEVEL_TRACE */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + /* placeholder for log level 8 */ + 0, + /* GST_LEVEL_MEMDUMP */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +}; + +static const guchar available_colors[] = { + FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_BLUE, FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_GREEN | FOREGROUND_BLUE, +}; +#endif /* G_OS_WIN32 */ +static const gchar *levelcolormap[GST_LEVEL_COUNT] = { + "\033[37m", /* GST_LEVEL_NONE */ + "\033[31;01m", /* GST_LEVEL_ERROR */ + "\033[33;01m", /* GST_LEVEL_WARNING */ + "\033[32;01m", /* GST_LEVEL_INFO */ + "\033[36m", /* GST_LEVEL_DEBUG */ + "\033[37m", /* GST_LEVEL_LOG */ + "\033[33;01m", /* GST_LEVEL_FIXME */ + "\033[37m", /* GST_LEVEL_TRACE */ + "\033[37m", /* placeholder for log level 8 */ + "\033[37m" /* GST_LEVEL_MEMDUMP */ +}; + +/** + * gst_debug_log_default: + * @category: category to log + * @level: level of the message + * @file: the file that emitted the message, usually the __FILE__ identifier + * @function: the function that emitted the message + * @line: the line from that the message was emitted, usually __LINE__ + * @message: the actual message + * @object: (transfer none) (allow-none): the object this message relates to, + * or %NULL if none + * @user_data: the FILE* to log to + * + * The default logging handler used by GStreamer. Logging functions get called + * whenever a macro like GST_DEBUG or similar is used. By default this function + * is setup to output the message and additional info to stderr (or the log file + * specified via the GST_DEBUG_FILE environment variable) as received via + * @user_data. + * + * You can add other handlers by using gst_debug_add_log_function(). + * And you can remove this handler by calling + * gst_debug_remove_log_function(gst_debug_log_default); + */ +void +gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, GstDebugMessage * message, gpointer user_data) +{ + gint pid; + GstClockTime elapsed; + gchar *obj = NULL; + GstDebugColorMode color_mode; + const gchar *message_str; + FILE *log_file = user_data ? user_data : stderr; + gchar c; + + /* Get message string first because printing it might call into our custom + * printf format extension mechanism which in turn might log something, e.g. + * from inside gst_structure_to_string() when something can't be serialised. + * This means we either need to do this outside of any critical section or + * use a recursive lock instead. As we always need the message string in all + * code paths, we might just as well get it here first thing and outside of + * the win_print_mutex critical section. */ + message_str = gst_debug_message_get (message); + + /* __FILE__ might be a file name or an absolute path or a + * relative path, irrespective of the exact compiler used, + * in which case we want to shorten it to the filename for + * readability. */ + c = file[0]; + if (c == '.' || c == '/' || c == '\\' || (c != '\0' && file[1] == ':')) { + file = gst_path_basename (file); + } + + pid = getpid (); + color_mode = gst_debug_get_color_mode (); + + if (object) { + obj = gst_debug_print_object (object); + } else { + obj = (gchar *) ""; + } + + elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ()); + + if (color_mode != GST_DEBUG_COLOR_MODE_OFF) { +#ifdef G_OS_WIN32 + /* We take a lock to keep colors and content together. + * Maybe there is a better way but for now this will do the right + * thing. */ + static GMutex win_print_mutex; + g_mutex_lock (&win_print_mutex); + if (color_mode == GST_DEBUG_COLOR_MODE_UNIX) { +#endif + /* colors, non-windows */ + gchar *color = NULL; + const gchar *clear; + gchar pidcolor[10]; + const gchar *levelcolor; + + color = gst_debug_construct_term_color (gst_debug_category_get_color + (category)); + clear = "\033[00m"; + g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31); + levelcolor = levelcolormap[level]; + +#define PRINT_FMT " %s"PID_FMT"%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n" + fprintf (log_file, "%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), + pidcolor, pid, clear, g_thread_self (), levelcolor, + gst_debug_level_get_name (level), clear, color, + gst_debug_category_get_name (category), file, line, function, obj, + clear, message_str); + fflush (log_file); +#undef PRINT_FMT + g_free (color); +#ifdef G_OS_WIN32 + } else { + /* colors, windows. */ + const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; +#define SET_COLOR(c) G_STMT_START { \ + if (log_file == stderr) \ + SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c)); \ + } G_STMT_END + /* timestamp */ + fprintf (log_file, "%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed)); + fflush (log_file); + /* pid */ + SET_COLOR (available_colors[pid % G_N_ELEMENTS (available_colors)]); + fprintf (log_file, PID_FMT, pid); + fflush (log_file); + /* thread */ + SET_COLOR (clear); + fprintf (log_file, " " PTR_FMT " ", g_thread_self ()); + fflush (log_file); + /* level */ + SET_COLOR (levelcolormap_w32[level]); + fprintf (log_file, "%s ", gst_debug_level_get_name (level)); + fflush (log_file); + /* category */ + SET_COLOR (gst_debug_construct_win_color (gst_debug_category_get_color + (category))); + fprintf (log_file, CAT_FMT, gst_debug_category_get_name (category), + file, line, function, obj); + fflush (log_file); + /* message */ + SET_COLOR (clear); + fprintf (log_file, " %s\n", message_str); + fflush (log_file); + } + g_mutex_unlock (&win_print_mutex); +#endif + } else { + /* no color, all platforms */ +#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n" + fprintf (log_file, "%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), + pid, g_thread_self (), gst_debug_level_get_name (level), + gst_debug_category_get_name (category), file, line, function, obj, + message_str); + fflush (log_file); +#undef PRINT_FMT + } + + if (object != NULL) + g_free (obj); +} + +/** + * gst_debug_level_get_name: + * @level: the level to get the name for + * + * Get the string representation of a debugging level + * + * Returns: the name + */ +const gchar * +gst_debug_level_get_name (GstDebugLevel level) +{ + switch (level) { + case GST_LEVEL_NONE: + return ""; + case GST_LEVEL_ERROR: + return "ERROR "; + case GST_LEVEL_WARNING: + return "WARN "; + case GST_LEVEL_INFO: + return "INFO "; + case GST_LEVEL_DEBUG: + return "DEBUG "; + case GST_LEVEL_LOG: + return "LOG "; + case GST_LEVEL_FIXME: + return "FIXME "; + case GST_LEVEL_TRACE: + return "TRACE "; + case GST_LEVEL_MEMDUMP: + return "MEMDUMP"; + default: + g_warning ("invalid level specified for gst_debug_level_get_name"); + return ""; + } +} + +/** + * gst_debug_add_log_function: + * @func: the function to use + * @user_data: user data + * @notify: called when @user_data is not used anymore + * + * Adds the logging function to the list of logging functions. + * Be sure to use #G_GNUC_NO_INSTRUMENT on that function, it is needed. + */ +void +gst_debug_add_log_function (GstLogFunction func, gpointer user_data, + GDestroyNotify notify) +{ + LogFuncEntry *entry; + GSList *list; + + if (func == NULL) + func = gst_debug_log_default; + + entry = g_slice_new (LogFuncEntry); + entry->func = func; + entry->user_data = user_data; + entry->notify = notify; + /* FIXME: we leak the old list here - other threads might access it right now + * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv, + * but that is waaay costly. + * It'd probably be clever to use some kind of RCU here, but I don't know + * anything about that. + */ + g_mutex_lock (&__log_func_mutex); + list = g_slist_copy (__log_functions); + __log_functions = g_slist_prepend (list, entry); + g_mutex_unlock (&__log_func_mutex); + + if (gst_is_initialized ()) + GST_DEBUG ("prepended log function %p (user data %p) to log functions", + func, user_data); +} + +static gint +gst_debug_compare_log_function_by_func (gconstpointer entry, gconstpointer func) +{ + gpointer entryfunc = (gpointer) (((LogFuncEntry *) entry)->func); + + return (entryfunc < func) ? -1 : (entryfunc > func) ? 1 : 0; +} + +static gint +gst_debug_compare_log_function_by_data (gconstpointer entry, gconstpointer data) +{ + gpointer entrydata = ((LogFuncEntry *) entry)->user_data; + + return (entrydata < data) ? -1 : (entrydata > data) ? 1 : 0; +} + +static guint +gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data) +{ + GSList *found; + GSList *new, *cleanup = NULL; + guint removals = 0; + + g_mutex_lock (&__log_func_mutex); + new = __log_functions; + cleanup = NULL; + while ((found = g_slist_find_custom (new, data, func))) { + if (new == __log_functions) { + /* make a copy when we have the first hit, so that we modify the copy and + * make that the new list later */ + new = g_slist_copy (new); + continue; + } + cleanup = g_slist_prepend (cleanup, found->data); + new = g_slist_delete_link (new, found); + removals++; + } + /* FIXME: We leak the old list here. See _add_log_function for why. */ + __log_functions = new; + g_mutex_unlock (&__log_func_mutex); + + while (cleanup) { + LogFuncEntry *entry = cleanup->data; + + if (entry->notify) + entry->notify (entry->user_data); + + g_slice_free (LogFuncEntry, entry); + cleanup = g_slist_delete_link (cleanup, cleanup); + } + return removals; +} + +/** + * gst_debug_remove_log_function: + * @func: (scope call) (allow-none): the log function to remove, or %NULL to + * remove the default log function + * + * Removes all registered instances of the given logging functions. + * + * Returns: How many instances of the function were removed + */ +guint +gst_debug_remove_log_function (GstLogFunction func) +{ + guint removals; + + if (func == NULL) + func = gst_debug_log_default; + + removals = + gst_debug_remove_with_compare_func + (gst_debug_compare_log_function_by_func, (gpointer) func); + + if (gst_is_initialized ()) { + GST_DEBUG ("removed log function %p %d times from log function list", func, + removals); + } else { + /* If the default log function is removed before gst_init() was called, + * set a flag so we don't add it in gst_init() later */ + if (func == gst_debug_log_default) { + add_default_log_func = FALSE; + ++removals; + } + } + + return removals; +} + +/** + * gst_debug_remove_log_function_by_data: + * @data: user data of the log function to remove + * + * Removes all registered instances of log functions with the given user data. + * + * Returns: How many instances of the function were removed + */ +guint +gst_debug_remove_log_function_by_data (gpointer data) +{ + guint removals; + + removals = + gst_debug_remove_with_compare_func + (gst_debug_compare_log_function_by_data, data); + + if (gst_is_initialized ()) + GST_DEBUG + ("removed %d log functions with user data %p from log function list", + removals, data); + + return removals; +} + +/** + * gst_debug_set_colored: + * @colored: Whether to use colored output or not + * + * Sets or unsets the use of coloured debugging output. + * Same as gst_debug_set_color_mode () with the argument being + * being GST_DEBUG_COLOR_MODE_ON or GST_DEBUG_COLOR_MODE_OFF. + * + * This function may be called before gst_init(). + */ +void +gst_debug_set_colored (gboolean colored) +{ + GstDebugColorMode new_mode; + new_mode = colored ? GST_DEBUG_COLOR_MODE_ON : GST_DEBUG_COLOR_MODE_OFF; + g_atomic_int_set (&__use_color, (gint) new_mode); +} + +/** + * gst_debug_set_color_mode: + * @mode: The coloring mode for debug output. See @GstDebugColorMode. + * + * Changes the coloring mode for debug output. + * + * This function may be called before gst_init(). + * + * Since: 1.2 + */ +void +gst_debug_set_color_mode (GstDebugColorMode mode) +{ + g_atomic_int_set (&__use_color, mode); +} + +/** + * gst_debug_set_color_mode_from_string: + * @mode: The coloring mode for debug output. One of the following: + * "on", "auto", "off", "disable", "unix". + * + * Changes the coloring mode for debug output. + * + * This function may be called before gst_init(). + * + * Since: 1.2 + */ +void +gst_debug_set_color_mode_from_string (const gchar * mode) +{ + if ((strcmp (mode, "on") == 0) || (strcmp (mode, "auto") == 0)) + gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_ON); + else if ((strcmp (mode, "off") == 0) || (strcmp (mode, "disable") == 0)) + gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_OFF); + else if (strcmp (mode, "unix") == 0) + gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_UNIX); +} + +/** + * gst_debug_is_colored: + * + * Checks if the debugging output should be colored. + * + * Returns: %TRUE, if the debug output should be colored. + */ +gboolean +gst_debug_is_colored (void) +{ + GstDebugColorMode mode = g_atomic_int_get (&__use_color); + return (mode == GST_DEBUG_COLOR_MODE_UNIX || mode == GST_DEBUG_COLOR_MODE_ON); +} + +/** + * gst_debug_get_color_mode: + * + * Changes the coloring mode for debug output. + * + * Returns: see @GstDebugColorMode for possible values. + * + * Since: 1.2 + */ +GstDebugColorMode +gst_debug_get_color_mode (void) +{ + return g_atomic_int_get (&__use_color); +} + +/** + * gst_debug_set_active: + * @active: Whether to use debugging output or not + * + * If activated, debugging messages are sent to the debugging + * handlers. + * It makes sense to deactivate it for speed issues. + * > This function is not threadsafe. It makes sense to only call it + * during initialization. + */ +void +gst_debug_set_active (gboolean active) +{ + _gst_debug_enabled = active; + if (active) + _gst_debug_min = GST_LEVEL_COUNT; + else + _gst_debug_min = GST_LEVEL_NONE; +} + +/** + * gst_debug_is_active: + * + * Checks if debugging output is activated. + * + * Returns: %TRUE, if debugging is activated + */ +gboolean +gst_debug_is_active (void) +{ + return _gst_debug_enabled; +} + +/** + * gst_debug_set_default_threshold: + * @level: level to set + * + * Sets the default threshold to the given level and updates all categories to + * use this threshold. + * + * This function may be called before gst_init(). + */ +void +gst_debug_set_default_threshold (GstDebugLevel level) +{ + g_atomic_int_set (&__default_level, level); + gst_debug_reset_all_thresholds (); +} + +/** + * gst_debug_get_default_threshold: + * + * Returns the default threshold that is used for new categories. + * + * Returns: the default threshold level + */ +GstDebugLevel +gst_debug_get_default_threshold (void) +{ + return (GstDebugLevel) g_atomic_int_get (&__default_level); +} + +static void +gst_debug_reset_threshold (gpointer category, gpointer unused) +{ + GstDebugCategory *cat = (GstDebugCategory *) category; + GSList *walk; + + g_mutex_lock (&__level_name_mutex); + walk = __level_name; + while (walk) { + LevelNameEntry *entry = walk->data; + + walk = g_slist_next (walk); + if (g_pattern_match_string (entry->pat, cat->name)) { + if (gst_is_initialized ()) + GST_LOG ("category %s matches pattern %p - gets set to level %d", + cat->name, entry->pat, entry->level); + gst_debug_category_set_threshold (cat, entry->level); + goto exit; + } + } + gst_debug_category_set_threshold (cat, gst_debug_get_default_threshold ()); + +exit: + g_mutex_unlock (&__level_name_mutex); +} + +static void +gst_debug_reset_all_thresholds (void) +{ + g_mutex_lock (&__cat_mutex); + g_slist_foreach (__categories, gst_debug_reset_threshold, NULL); + g_mutex_unlock (&__cat_mutex); +} + +static void +for_each_threshold_by_entry (gpointer data, gpointer user_data) +{ + GstDebugCategory *cat = (GstDebugCategory *) data; + LevelNameEntry *entry = (LevelNameEntry *) user_data; + + if (g_pattern_match_string (entry->pat, cat->name)) { + if (gst_is_initialized ()) + GST_TRACE ("category %s matches pattern %p - gets set to level %d", + cat->name, entry->pat, entry->level); + gst_debug_category_set_threshold (cat, entry->level); + } +} + +/** + * gst_debug_set_threshold_for_name: + * @name: name of the categories to set + * @level: level to set them to + * + * Sets all categories which match the given glob style pattern to the given + * level. + */ +void +gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level) +{ + GPatternSpec *pat; + LevelNameEntry *entry; + + g_return_if_fail (name != NULL); + + pat = g_pattern_spec_new (name); + entry = g_slice_new (LevelNameEntry); + entry->pat = pat; + entry->level = level; + g_mutex_lock (&__level_name_mutex); + __level_name = g_slist_prepend (__level_name, entry); + g_mutex_unlock (&__level_name_mutex); + g_mutex_lock (&__cat_mutex); + g_slist_foreach (__categories, for_each_threshold_by_entry, entry); + g_mutex_unlock (&__cat_mutex); +} + +/** + * gst_debug_unset_threshold_for_name: + * @name: name of the categories to set + * + * Resets all categories with the given name back to the default level. + */ +void +gst_debug_unset_threshold_for_name (const gchar * name) +{ + GSList *walk; + GPatternSpec *pat; + + g_return_if_fail (name != NULL); + + pat = g_pattern_spec_new (name); + g_mutex_lock (&__level_name_mutex); + walk = __level_name; + /* improve this if you want, it's mighty slow */ + while (walk) { + LevelNameEntry *entry = walk->data; + + if (g_pattern_spec_equal (entry->pat, pat)) { + __level_name = g_slist_remove_link (__level_name, walk); + g_pattern_spec_free (entry->pat); + g_slice_free (LevelNameEntry, entry); + g_slist_free_1 (walk); + walk = __level_name; + } else { + walk = g_slist_next (walk); + } + } + g_mutex_unlock (&__level_name_mutex); + g_pattern_spec_free (pat); + gst_debug_reset_all_thresholds (); +} + +GstDebugCategory * +_gst_debug_category_new (const gchar * name, guint color, + const gchar * description) +{ + GstDebugCategory *cat, *catfound; + + g_return_val_if_fail (name != NULL, NULL); + + cat = g_slice_new (GstDebugCategory); + cat->name = g_strdup (name); + cat->color = color; + if (description != NULL) { + cat->description = g_strdup (description); + } else { + cat->description = g_strdup ("no description"); + } + g_atomic_int_set (&cat->threshold, 0); + gst_debug_reset_threshold (cat, NULL); + + /* add to category list */ + g_mutex_lock (&__cat_mutex); + catfound = _gst_debug_get_category_locked (name); + if (catfound) { + g_free ((gpointer) cat->name); + g_free ((gpointer) cat->description); + g_slice_free (GstDebugCategory, cat); + cat = catfound; + } else { + __categories = g_slist_prepend (__categories, cat); + } + g_mutex_unlock (&__cat_mutex); + + return cat; +} + +/** + * gst_debug_category_free: + * @category: #GstDebugCategory to free. + * + * Removes and frees the category and all associated resources. + */ +void +gst_debug_category_free (GstDebugCategory * category) +{ + if (category == NULL) + return; + + /* remove from category list */ + g_mutex_lock (&__cat_mutex); + __categories = g_slist_remove (__categories, category); + g_mutex_unlock (&__cat_mutex); + + g_free ((gpointer) category->name); + g_free ((gpointer) category->description); + g_slice_free (GstDebugCategory, category); +} + +/** + * gst_debug_category_set_threshold: + * @category: a #GstDebugCategory to set threshold of. + * @level: the #GstDebugLevel threshold to set. + * + * Sets the threshold of the category to the given level. Debug information will + * only be output if the threshold is lower or equal to the level of the + * debugging message. + * > Do not use this function in production code, because other functions may + * > change the threshold of categories as side effect. It is however a nice + * > function to use when debugging (even from gdb). + */ +void +gst_debug_category_set_threshold (GstDebugCategory * category, + GstDebugLevel level) +{ + g_return_if_fail (category != NULL); + + if (level > _gst_debug_min) { + _gst_debug_enabled = TRUE; + _gst_debug_min = level; + } + + g_atomic_int_set (&category->threshold, level); +} + +/** + * gst_debug_category_reset_threshold: + * @category: a #GstDebugCategory to reset threshold of. + * + * Resets the threshold of the category to the default level. Debug information + * will only be output if the threshold is lower or equal to the level of the + * debugging message. + * Use this function to set the threshold back to where it was after using + * gst_debug_category_set_threshold(). + */ +void +gst_debug_category_reset_threshold (GstDebugCategory * category) +{ + gst_debug_reset_threshold (category, NULL); +} + +/** + * gst_debug_category_get_threshold: + * @category: a #GstDebugCategory to get threshold of. + * + * Returns the threshold of a #GstDebugCategory. + * + * Returns: the #GstDebugLevel that is used as threshold. + */ +GstDebugLevel +gst_debug_category_get_threshold (GstDebugCategory * category) +{ + return (GstDebugLevel) g_atomic_int_get (&category->threshold); +} + +/** + * gst_debug_category_get_name: + * @category: a #GstDebugCategory to get name of. + * + * Returns the name of a debug category. + * + * Returns: the name of the category. + */ +const gchar * +gst_debug_category_get_name (GstDebugCategory * category) +{ + return category->name; +} + +/** + * gst_debug_category_get_color: + * @category: a #GstDebugCategory to get the color of. + * + * Returns the color of a debug category used when printing output in this + * category. + * + * Returns: the color of the category. + */ +guint +gst_debug_category_get_color (GstDebugCategory * category) +{ + return category->color; +} + +/** + * gst_debug_category_get_description: + * @category: a #GstDebugCategory to get the description of. + * + * Returns the description of a debug category. + * + * Returns: the description of the category. + */ +const gchar * +gst_debug_category_get_description (GstDebugCategory * category) +{ + return category->description; +} + +/** + * gst_debug_get_all_categories: + * + * Returns a snapshot of a all categories that are currently in use . This list + * may change anytime. + * The caller has to free the list after use. + * + * Returns: (transfer container) (element-type Gst.DebugCategory): the list of + * debug categories + */ +GSList * +gst_debug_get_all_categories (void) +{ + GSList *ret; + + g_mutex_lock (&__cat_mutex); + ret = g_slist_copy (__categories); + g_mutex_unlock (&__cat_mutex); + + return ret; +} + +static GstDebugCategory * +_gst_debug_get_category_locked (const gchar * name) +{ + GstDebugCategory *ret = NULL; + GSList *node; + + for (node = __categories; node; node = g_slist_next (node)) { + ret = (GstDebugCategory *) node->data; + if (!strcmp (name, ret->name)) { + return ret; + } + } + return NULL; +} + +GstDebugCategory * +_gst_debug_get_category (const gchar * name) +{ + GstDebugCategory *ret; + + g_mutex_lock (&__cat_mutex); + ret = _gst_debug_get_category_locked (name); + g_mutex_unlock (&__cat_mutex); + + return ret; +} + +static gboolean +parse_debug_category (gchar * str, const gchar ** category) +{ + if (!str) + return FALSE; + + /* works in place */ + g_strstrip (str); + + if (str[0] != '\0') { + *category = str; + return TRUE; + } + + return FALSE; +} + +static gboolean +parse_debug_level (gchar * str, GstDebugLevel * level) +{ + if (!str) + return FALSE; + + /* works in place */ + g_strstrip (str); + + if (g_ascii_isdigit (str[0])) { + unsigned long l; + char *endptr; + l = strtoul (str, &endptr, 10); + if (endptr > str && endptr[0] == 0) { + *level = (GstDebugLevel) l; + } else { + return FALSE; + } + } else if (strcmp (str, "ERROR") == 0) { + *level = GST_LEVEL_ERROR; + } else if (strncmp (str, "WARN", 4) == 0) { + *level = GST_LEVEL_WARNING; + } else if (strcmp (str, "FIXME") == 0) { + *level = GST_LEVEL_FIXME; + } else if (strcmp (str, "INFO") == 0) { + *level = GST_LEVEL_INFO; + } else if (strcmp (str, "DEBUG") == 0) { + *level = GST_LEVEL_DEBUG; + } else if (strcmp (str, "LOG") == 0) { + *level = GST_LEVEL_LOG; + } else if (strcmp (str, "TRACE") == 0) { + *level = GST_LEVEL_TRACE; + } else if (strcmp (str, "MEMDUMP") == 0) { + *level = GST_LEVEL_MEMDUMP; + } else + return FALSE; + + return TRUE; +} + +/** + * gst_debug_set_threshold_from_string: + * @list: comma-separated list of "category:level" pairs to be used + * as debug logging levels + * @reset: %TRUE to clear all previously-set debug levels before setting + * new thresholds + * %FALSE if adding the threshold described by @list to the one already set. + * + * Sets the debug logging wanted in the same form as with the GST_DEBUG + * environment variable. You can use wildcards such as '*', but note that + * the order matters when you use wild cards, e.g. "foosrc:6,*src:3,*:2" sets + * everything to log level 2. + * + * Since: 1.2 + */ +void +gst_debug_set_threshold_from_string (const gchar * list, gboolean reset) +{ + gchar **split; + gchar **walk; + + g_assert (list); + + if (reset) + gst_debug_set_default_threshold (GST_LEVEL_DEFAULT); + + split = g_strsplit (list, ",", 0); + + for (walk = split; *walk; walk++) { + if (strchr (*walk, ':')) { + gchar **values = g_strsplit (*walk, ":", 2); + + if (values[0] && values[1]) { + GstDebugLevel level; + const gchar *category; + + if (parse_debug_category (values[0], &category) + && parse_debug_level (values[1], &level)) { + gst_debug_set_threshold_for_name (category, level); + + /* bump min-level anyway to allow the category to be registered in the + * future still */ + if (level > _gst_debug_min) { + _gst_debug_min = level; + } + } + } + + g_strfreev (values); + } else { + GstDebugLevel level; + + if (parse_debug_level (*walk, &level)) + gst_debug_set_default_threshold (level); + } + } + + g_strfreev (split); +} + +/*** FUNCTION POINTERS ********************************************************/ + +static GHashTable *__gst_function_pointers; /* NULL */ +static GMutex __dbg_functions_mutex; + +/* This function MUST NOT return NULL */ +const gchar * +_gst_debug_nameof_funcptr (GstDebugFuncPtr func) +{ + gchar *ptrname; + +#ifdef HAVE_DLADDR + Dl_info dl_info; +#endif + + if (G_UNLIKELY (func == NULL)) + return "(NULL)"; + + g_mutex_lock (&__dbg_functions_mutex); + if (G_LIKELY (__gst_function_pointers)) { + ptrname = g_hash_table_lookup (__gst_function_pointers, (gpointer) func); + g_mutex_unlock (&__dbg_functions_mutex); + if (G_LIKELY (ptrname)) + return ptrname; + } else { + g_mutex_unlock (&__dbg_functions_mutex); + } + /* we need to create an entry in the hash table for this one so we don't leak + * the name */ +#ifdef HAVE_DLADDR + if (dladdr ((gpointer) func, &dl_info) && dl_info.dli_sname) { + gchar *name = g_strdup (dl_info.dli_sname); + + _gst_debug_register_funcptr (func, name); + return name; + } else +#endif + { + gchar *name = g_strdup_printf ("%p", (gpointer) func); + + _gst_debug_register_funcptr (func, name); + return name; + } +} + +void +_gst_debug_register_funcptr (GstDebugFuncPtr func, const gchar * ptrname) +{ + gpointer ptr = (gpointer) func; + + g_mutex_lock (&__dbg_functions_mutex); + + if (!__gst_function_pointers) + __gst_function_pointers = g_hash_table_new (g_direct_hash, g_direct_equal); + if (!g_hash_table_lookup (__gst_function_pointers, ptr)) + g_hash_table_insert (__gst_function_pointers, ptr, (gpointer) ptrname); + + g_mutex_unlock (&__dbg_functions_mutex); +} + +static void +gst_info_dump_mem_line (gchar * linebuf, gsize linebuf_size, + const guint8 * mem, gsize mem_offset, gsize mem_size) +{ + gchar hexstr[50], ascstr[18], digitstr[4]; + + if (mem_size > 16) + mem_size = 16; + + hexstr[0] = '\0'; + ascstr[0] = '\0'; + + if (mem != NULL) { + guint i = 0; + + mem += mem_offset; + while (i < mem_size) { + ascstr[i] = (g_ascii_isprint (mem[i])) ? mem[i] : '.'; + g_snprintf (digitstr, sizeof (digitstr), "%02x ", mem[i]); + g_strlcat (hexstr, digitstr, sizeof (hexstr)); + ++i; + } + ascstr[i] = '\0'; + } + + g_snprintf (linebuf, linebuf_size, "%08x: %-48.48s %-16.16s", + (guint) mem_offset, hexstr, ascstr); +} + +void +_gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file, + const gchar * func, gint line, GObject * obj, const gchar * msg, + const guint8 * data, guint length) +{ + guint off = 0; + + gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------" + "-------------------------------------------------------------------"); + + if (msg != NULL && *msg != '\0') { + gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "%s", msg); + } + + while (off < length) { + gchar buf[128]; + + /* gst_info_dump_mem_line will process 16 bytes at most */ + gst_info_dump_mem_line (buf, sizeof (buf), data, off, length - off); + gst_debug_log (cat, GST_LEVEL_MEMDUMP, file, func, line, obj, "%s", buf); + off += 16; + } + + gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------" + "-------------------------------------------------------------------"); +} + +#else /* !GST_DISABLE_GST_DEBUG */ +#ifndef GST_REMOVE_DISABLED + +GstDebugCategory * +_gst_debug_category_new (const gchar * name, guint color, + const gchar * description) +{ + return NULL; +} + +void +_gst_debug_register_funcptr (GstDebugFuncPtr func, const gchar * ptrname) +{ +} + +/* This function MUST NOT return NULL */ +const gchar * +_gst_debug_nameof_funcptr (GstDebugFuncPtr func) +{ + return "(NULL)"; +} + +void +gst_debug_log (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, const gchar * format, ...) +{ +} + +void +gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, const gchar * format, va_list args) +{ +} + +const gchar * +gst_debug_message_get (GstDebugMessage * message) +{ + return ""; +} + +void +gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level, + const gchar * file, const gchar * function, gint line, + GObject * object, GstDebugMessage * message, gpointer unused) +{ +} + +const gchar * +gst_debug_level_get_name (GstDebugLevel level) +{ + return "NONE"; +} + +void +gst_debug_add_log_function (GstLogFunction func, gpointer user_data, + GDestroyNotify notify) +{ +} + +guint +gst_debug_remove_log_function (GstLogFunction func) +{ + return 0; +} + +guint +gst_debug_remove_log_function_by_data (gpointer data) +{ + return 0; +} + +void +gst_debug_set_active (gboolean active) +{ +} + +gboolean +gst_debug_is_active (void) +{ + return FALSE; +} + +void +gst_debug_set_colored (gboolean colored) +{ +} + +void +gst_debug_set_color_mode (GstDebugColorMode mode) +{ +} + +void +gst_debug_set_color_mode_from_string (const gchar * str) +{ +} + +gboolean +gst_debug_is_colored (void) +{ + return FALSE; +} + +GstDebugColorMode +gst_debug_get_color_mode (void) +{ + return GST_DEBUG_COLOR_MODE_OFF; +} + +void +gst_debug_set_threshold_from_string (const gchar * list, gboolean reset) +{ +} + +void +gst_debug_set_default_threshold (GstDebugLevel level) +{ +} + +GstDebugLevel +gst_debug_get_default_threshold (void) +{ + return GST_LEVEL_NONE; +} + +void +gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level) +{ +} + +void +gst_debug_unset_threshold_for_name (const gchar * name) +{ +} + +void +gst_debug_category_free (GstDebugCategory * category) +{ +} + +void +gst_debug_category_set_threshold (GstDebugCategory * category, + GstDebugLevel level) +{ +} + +void +gst_debug_category_reset_threshold (GstDebugCategory * category) +{ +} + +GstDebugLevel +gst_debug_category_get_threshold (GstDebugCategory * category) +{ + return GST_LEVEL_NONE; +} + +const gchar * +gst_debug_category_get_name (GstDebugCategory * category) +{ + return ""; +} + +guint +gst_debug_category_get_color (GstDebugCategory * category) +{ + return 0; +} + +const gchar * +gst_debug_category_get_description (GstDebugCategory * category) +{ + return ""; +} + +GSList * +gst_debug_get_all_categories (void) +{ + return NULL; +} + +GstDebugCategory * +_gst_debug_get_category (const gchar * name) +{ + return NULL; +} + +gchar * +gst_debug_construct_term_color (guint colorinfo) +{ + return g_strdup ("00"); +} + +gint +gst_debug_construct_win_color (guint colorinfo) +{ + return 0; +} + +gboolean +_priv_gst_in_valgrind (void) +{ + return FALSE; +} + +void +_gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file, + const gchar * func, gint line, GObject * obj, const gchar * msg, + const guint8 * data, guint length) +{ +} +#endif /* GST_REMOVE_DISABLED */ +#endif /* GST_DISABLE_GST_DEBUG */ + +/* Need this for _gst_element_error_printf even if GST_REMOVE_DISABLED is set: + * fallback function that cleans up the format string and replaces all pointer + * extension formats with plain %p. */ +#ifdef GST_DISABLE_GST_DEBUG +int +__gst_info_fallback_vasprintf (char **result, char const *format, va_list args) +{ + gchar *clean_format, *c; + gsize len; + + if (format == NULL) + return -1; + + clean_format = g_strdup (format); + c = clean_format; + while ((c = strstr (c, "%p\a"))) { + if (c[3] < 'A' || c[3] > 'Z') { + c += 3; + continue; + } + len = strlen (c + 4); + memmove (c + 2, c + 4, len + 1); + c += 2; + } + while ((c = strstr (clean_format, "%P"))) /* old GST_PTR_FORMAT */ + c[1] = 'p'; + while ((c = strstr (clean_format, "%Q"))) /* old GST_SEGMENT_FORMAT */ + c[1] = 'p'; + + len = g_vasprintf (result, clean_format, args); + + g_free (clean_format); + + if (*result == NULL) + return -1; + + return len; +} +#endif + +/** + * gst_info_vasprintf: + * @result: (out): the resulting string + * @format: a printf style format string + * @args: the va_list of printf arguments for @format + * + * Allocates and fills a string large enough (including the terminating null + * byte) to hold the specified printf style @format and @args. + * + * This function deals with the GStreamer specific printf specifiers + * #GST_PTR_FORMAT and #GST_SEGMENT_FORMAT. If you do not have these specifiers + * in your @format string, you do not need to use this function and can use + * alternatives such as g_vasprintf(). + * + * Free @result with g_free(). + * + * Returns: the length of the string allocated into @result or -1 on any error + * + * Since: 1.8 + */ +gint +gst_info_vasprintf (gchar ** result, const gchar * format, va_list args) +{ + /* This will fallback to __gst_info_fallback_vasprintf() via a #define in + * gst_private.h if the debug system is disabled which will remove the gst + * specific printf format specifiers */ + return __gst_vasprintf (result, format, args); +} + +/** + * gst_info_strdup_vprintf: + * @format: a printf style format string + * @args: the va_list of printf arguments for @format + * + * Allocates, fills and returns a null terminated string from the printf style + * @format string and @args. + * + * See gst_info_vasprintf() for when this function is required. + * + * Free with g_free(). + * + * Returns: (nullable): a newly allocated null terminated string or %NULL on any error + * + * Since: 1.8 + */ +gchar * +gst_info_strdup_vprintf (const gchar * format, va_list args) +{ + gchar *ret; + + if (gst_info_vasprintf (&ret, format, args) < 0) + ret = NULL; + + return ret; +} + +/** + * gst_info_strdup_printf: + * @format: a printf style format string + * @...: the printf arguments for @format + * + * Allocates, fills and returns a 0-terminated string from the printf style + * @format string and corresponding arguments. + * + * See gst_info_vasprintf() for when this function is required. + * + * Free with g_free(). + * + * Returns: (nullable): a newly allocated null terminated string or %NULL on any error + * + * Since: 1.8 + */ +gchar * +gst_info_strdup_printf (const gchar * format, ...) +{ + gchar *ret; + va_list args; + + va_start (args, format); + ret = gst_info_strdup_vprintf (format, args); + va_end (args); + + return ret; +} + +/** + * gst_print: + * @format: a printf style format string + * @...: the printf arguments for @format + * + * Outputs a formatted message via the GLib print handler. The default print + * handler simply outputs the message to stdout. + * + * This function will not append a new-line character at the end, unlike + * gst_println() which will. + * + * All strings must be in ASCII or UTF-8 encoding. + * + * This function differs from g_print() in that it supports all the additional + * printf specifiers that are supported by GStreamer's debug logging system, + * such as #GST_PTR_FORMAT and #GST_SEGMENT_FORMAT. + * + * This function is primarily for printing debug output. + * + * Since: 1.12 + */ +void +gst_print (const gchar * format, ...) +{ + va_list args; + gchar *str; + + va_start (args, format); + str = gst_info_strdup_vprintf (format, args); + va_end (args); + + g_print ("%s", str); + g_free (str); +} + +/** + * gst_println: + * @format: a printf style format string + * @...: the printf arguments for @format + * + * Outputs a formatted message via the GLib print handler. The default print + * handler simply outputs the message to stdout. + * + * This function will append a new-line character at the end, unlike + * gst_print() which will not. + * + * All strings must be in ASCII or UTF-8 encoding. + * + * This function differs from g_print() in that it supports all the additional + * printf specifiers that are supported by GStreamer's debug logging system, + * such as #GST_PTR_FORMAT and #GST_SEGMENT_FORMAT. + * + * This function is primarily for printing debug output. + * + * Since: 1.12 + */ +void +gst_println (const gchar * format, ...) +{ + va_list args; + gchar *str; + + va_start (args, format); + str = gst_info_strdup_vprintf (format, args); + va_end (args); + + g_print ("%s\n", str); + g_free (str); +} + +/** + * gst_printerr: + * @format: a printf style format string + * @...: the printf arguments for @format + * + * Outputs a formatted message via the GLib error message handler. The default + * handler simply outputs the message to stderr. + * + * This function will not append a new-line character at the end, unlike + * gst_printerrln() which will. + * + * All strings must be in ASCII or UTF-8 encoding. + * + * This function differs from g_printerr() in that it supports the additional + * printf specifiers that are supported by GStreamer's debug logging system, + * such as #GST_PTR_FORMAT and #GST_SEGMENT_FORMAT. + * + * This function is primarily for printing debug output. + * + * Since: 1.12 + */ +void +gst_printerr (const gchar * format, ...) +{ + va_list args; + gchar *str; + + va_start (args, format); + str = gst_info_strdup_vprintf (format, args); + va_end (args); + + g_printerr ("%s", str); + g_free (str); +} + +/** + * gst_printerrln: + * @format: a printf style format string + * @...: the printf arguments for @format + * + * Outputs a formatted message via the GLib error message handler. The default + * handler simply outputs the message to stderr. + * + * This function will append a new-line character at the end, unlike + * gst_printerr() which will not. + * + * All strings must be in ASCII or UTF-8 encoding. + * + * This function differs from g_printerr() in that it supports the additional + * printf specifiers that are supported by GStreamer's debug logging system, + * such as #GST_PTR_FORMAT and #GST_SEGMENT_FORMAT. + * + * This function is primarily for printing debug output. + * + * Since: 1.12 + */ +void +gst_printerrln (const gchar * format, ...) +{ + va_list args; + gchar *str; + + va_start (args, format); + str = gst_info_strdup_vprintf (format, args); + va_end (args); + + g_printerr ("%s\n", str); + g_free (str); +} + +#ifdef HAVE_UNWIND +#ifdef HAVE_DW +static gboolean +append_debug_info (GString * trace, Dwfl * dwfl, const void *ip) +{ + Dwfl_Line *line; + Dwarf_Addr addr; + Dwfl_Module *module; + const gchar *function_name; + + if (dwfl_linux_proc_report (dwfl, getpid ()) != 0) + return FALSE; + + if (dwfl_report_end (dwfl, NULL, NULL)) + return FALSE; + + addr = (uintptr_t) ip; + module = dwfl_addrmodule (dwfl, addr); + function_name = dwfl_module_addrname (module, addr); + + g_string_append_printf (trace, "%s (", function_name ? function_name : "??"); + + line = dwfl_getsrc (dwfl, addr); + if (line != NULL) { + gint nline; + Dwarf_Addr addr; + const gchar *filename = dwfl_lineinfo (line, &addr, + &nline, NULL, NULL, NULL); + + g_string_append_printf (trace, "%s:%d", strrchr (filename, + G_DIR_SEPARATOR) + 1, nline); + } else { + const gchar *eflfile = NULL; + + dwfl_module_info (module, NULL, NULL, NULL, NULL, NULL, &eflfile, NULL); + g_string_append_printf (trace, "%s:%p", eflfile ? eflfile : "??", ip); + } + + return TRUE; +} +#endif /* HAVE_DW */ + +static gchar * +generate_unwind_trace (GstStackTraceFlags flags) +{ + gint unret; + unw_context_t uc; + unw_cursor_t cursor; + gboolean use_libunwind = TRUE; + GString *trace = g_string_new (NULL); + +#ifdef HAVE_DW + Dwfl *dwfl = NULL; + Dwfl_Callbacks callbacks = { + .find_elf = dwfl_linux_proc_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + }; + + if ((flags & GST_STACK_TRACE_SHOW_FULL)) + dwfl = dwfl_begin (&callbacks); +#endif /* HAVE_DW */ + + unret = unw_getcontext (&uc); + if (unret) { + GST_DEBUG ("Could not get libunwind context (%d)", unret); + + goto done; + } + unret = unw_init_local (&cursor, &uc); + if (unret) { + GST_DEBUG ("Could not init libunwind context (%d)", unret); + + goto done; + } + + while (unw_step (&cursor) > 0) { +#ifdef HAVE_DW + if (dwfl) { + unw_word_t ip; + + unret = unw_get_reg (&cursor, UNW_REG_IP, &ip); + if (unret) { + GST_DEBUG ("libunwind could read frame info (%d)", unret); + + goto done; + } + + if (append_debug_info (trace, dwfl, (void *) (ip - 4))) { + use_libunwind = FALSE; + g_string_append (trace, ")\n"); + } + } +#endif /* HAVE_DW */ + + if (use_libunwind) { + char name[32]; + + unw_word_t offset = 0; + unw_get_proc_name (&cursor, name, sizeof (name), &offset); + g_string_append_printf (trace, "%s (0x%" G_GSIZE_FORMAT ")\n", name, + (gsize) offset); + } + } + +done: +#ifdef HAVE_DW + if (dwfl) + dwfl_end (dwfl); +#endif + + return g_string_free (trace, FALSE); +} + +#endif /* HAVE_UNWIND */ + +#ifdef HAVE_BACKTRACE +static gchar * +generate_backtrace_trace (void) +{ + int j, nptrs; + void *buffer[BT_BUF_SIZE]; + char **strings; + GString *trace; + + trace = g_string_new (NULL); + nptrs = backtrace (buffer, BT_BUF_SIZE); + + strings = backtrace_symbols (buffer, nptrs); + + if (!strings) + return NULL; + + for (j = 0; j < nptrs; j++) + g_string_append_printf (trace, "%s\n", strings[j]); + + free (strings); + + return g_string_free (trace, FALSE); +} +#else +#define generate_backtrace_trace() NULL +#endif /* HAVE_BACKTRACE */ + +/** + * gst_debug_get_stack_trace: + * @flags: A set of #GstStackTraceFlags to determine how the stack + * trace should look like. Pass 0 to retrieve a minimal backtrace. + * + * Returns: (nullable): a stack trace, if libunwind or glibc backtrace are + * present, else %NULL. + * + * Since: 1.12 + */ +gchar * +gst_debug_get_stack_trace (GstStackTraceFlags flags) +{ + gchar *trace = NULL; +#ifdef HAVE_BACKTRACE + gboolean have_backtrace = TRUE; +#else + gboolean have_backtrace = FALSE; +#endif + +#ifdef HAVE_UNWIND + if ((flags & GST_STACK_TRACE_SHOW_FULL) || !have_backtrace) + trace = generate_unwind_trace (flags); +#endif /* HAVE_UNWIND */ + + if (trace) + return trace; + else if (have_backtrace) + return generate_backtrace_trace (); + + return NULL; +} + +/** + * gst_debug_print_stack_trace: + * + * If libunwind or glibc backtrace are present + * a stack trace is printed. + */ +void +gst_debug_print_stack_trace (void) +{ + gchar *trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL); + + if (trace) + g_print ("%s\n", trace); + + g_free (trace); +} + +#ifndef GST_DISABLE_GST_DEBUG +typedef struct +{ + guint max_size_per_thread; + guint thread_timeout; + GQueue threads; + GHashTable *thread_index; +} GstRingBufferLogger; + +typedef struct +{ + GList *link; + gint64 last_use; + GThread *thread; + + GQueue log; + gsize log_size; +} GstRingBufferLog; + +G_LOCK_DEFINE_STATIC (ring_buffer_logger); +static GstRingBufferLogger *ring_buffer_logger = NULL; + +static void +gst_ring_buffer_logger_log (GstDebugCategory * category, + GstDebugLevel level, + const gchar * file, + const gchar * function, + gint line, GObject * object, GstDebugMessage * message, gpointer user_data) +{ + GstRingBufferLogger *logger = user_data; + gint pid; + GThread *thread; + GstClockTime elapsed; + gchar *obj = NULL; + gchar c; + gchar *output; + gsize output_len; + GstRingBufferLog *log; + gint64 now = g_get_monotonic_time (); + const gchar *message_str = gst_debug_message_get (message); + + G_LOCK (ring_buffer_logger); + + if (logger->thread_timeout > 0) { + /* Remove all threads that saw no output since thread_timeout seconds. + * By construction these are all at the tail of the queue, and the queue + * is ordered by last use, so we just need to look at the tail. + */ + while (logger->threads.tail) { + log = logger->threads.tail->data; + if (log->last_use + logger->thread_timeout * G_USEC_PER_SEC >= now) + break; + + g_hash_table_remove (logger->thread_index, log->thread); + while ((output = g_queue_pop_head (&log->log))) + g_free (output); + g_free (log); + g_queue_pop_tail (&logger->threads); + } + } + + /* Get logger for this thread, and put it back at the + * head of the threads queue */ + thread = g_thread_self (); + log = g_hash_table_lookup (logger->thread_index, thread); + if (!log) { + log = g_new0 (GstRingBufferLog, 1); + g_queue_init (&log->log); + log->log_size = 0; + g_queue_push_head (&logger->threads, log); + log->link = logger->threads.head; + log->thread = thread; + g_hash_table_insert (logger->thread_index, thread, log); + } else { + g_queue_unlink (&logger->threads, log->link); + g_queue_push_head_link (&logger->threads, log->link); + } + log->last_use = now; + + /* __FILE__ might be a file name or an absolute path or a + * relative path, irrespective of the exact compiler used, + * in which case we want to shorten it to the filename for + * readability. */ + c = file[0]; + if (c == '.' || c == '/' || c == '\\' || (c != '\0' && file[1] == ':')) { + file = gst_path_basename (file); + } + + pid = getpid (); + + if (object) { + obj = gst_debug_print_object (object); + } else { + obj = (gchar *) ""; + } + + elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ()); + + /* no color, all platforms */ +#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n" + output = + g_strdup_printf ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), + pid, thread, gst_debug_level_get_name (level), + gst_debug_category_get_name (category), file, line, function, obj, + message_str); +#undef PRINT_FMT + + output_len = strlen (output); + + if (output_len < logger->max_size_per_thread) { + gchar *buf; + + /* While using a GQueue here is not the most efficient thing to do, we + * have to allocate a string for every output anyway and could just store + * that instead of copying it to an actual ringbuffer. + * Better than GQueue would be GstQueueArray, but that one is in + * libgstbase and we can't use it here. That one allocation will not make + * much of a difference anymore, considering the number of allocations + * needed to get to this point... + */ + while (log->log_size + output_len > logger->max_size_per_thread) { + buf = g_queue_pop_head (&log->log); + log->log_size -= strlen (buf); + g_free (buf); + } + g_queue_push_tail (&log->log, output); + log->log_size += output_len; + } else { + gchar *buf; + + /* Can't really write anything as the line is bigger than the maximum + * allowed log size already, so just remove everything */ + + while ((buf = g_queue_pop_head (&log->log))) + g_free (buf); + g_free (output); + log->log_size = 0; + } + + if (object != NULL) + g_free (obj); + + G_UNLOCK (ring_buffer_logger); +} + +/** + * gst_debug_ring_buffer_logger_get_logs: + * + * Fetches the current logs per thread from the ring buffer logger. See + * gst_debug_add_ring_buffer_logger() for details. + * + * Returns: (transfer full) (array zero-terminated): NULL-terminated array of + * strings with the debug output per thread + * + * Since: 1.14 + */ +gchar ** +gst_debug_ring_buffer_logger_get_logs (void) +{ + gchar **logs, **tmp; + GList *l; + + g_return_val_if_fail (ring_buffer_logger != NULL, NULL); + + G_LOCK (ring_buffer_logger); + + tmp = logs = g_new0 (gchar *, ring_buffer_logger->threads.length + 1); + for (l = ring_buffer_logger->threads.head; l; l = l->next) { + GstRingBufferLog *log = l->data; + GList *l; + gchar *p; + gsize len; + + *tmp = p = g_new0 (gchar, log->log_size + 1); + + for (l = log->log.head; l; l = l->next) { + len = strlen (l->data); + memcpy (p, l->data, len); + p += len; + } + + tmp++; + } + + G_UNLOCK (ring_buffer_logger); + + return logs; +} + +static void +gst_ring_buffer_logger_free (GstRingBufferLogger * logger) +{ + G_LOCK (ring_buffer_logger); + if (ring_buffer_logger == logger) { + GstRingBufferLog *log; + + while ((log = g_queue_pop_head (&logger->threads))) { + gchar *buf; + while ((buf = g_queue_pop_head (&log->log))) + g_free (buf); + g_free (log); + } + + g_hash_table_unref (logger->thread_index); + + g_free (logger); + ring_buffer_logger = NULL; + } + G_UNLOCK (ring_buffer_logger); +} + +/** + * gst_debug_add_ring_buffer_logger: + * @max_size_per_thread: Maximum size of log per thread in bytes + * @thread_timeout: Timeout for threads in seconds + * + * Adds a memory ringbuffer based debug logger that stores up to + * @max_size_per_thread bytes of logs per thread and times out threads after + * @thread_timeout seconds of inactivity. + * + * Logs can be fetched with gst_debug_ring_buffer_logger_get_logs() and the + * logger can be removed again with gst_debug_remove_ring_buffer_logger(). + * Only one logger at a time is possible. + * + * Since: 1.14 + */ +void +gst_debug_add_ring_buffer_logger (guint max_size_per_thread, + guint thread_timeout) +{ + GstRingBufferLogger *logger; + + G_LOCK (ring_buffer_logger); + + if (ring_buffer_logger) { + g_warn_if_reached (); + G_UNLOCK (ring_buffer_logger); + return; + } + + logger = ring_buffer_logger = g_new0 (GstRingBufferLogger, 1); + + logger->max_size_per_thread = max_size_per_thread; + logger->thread_timeout = thread_timeout; + logger->thread_index = g_hash_table_new (g_direct_hash, g_direct_equal); + g_queue_init (&logger->threads); + + gst_debug_add_log_function (gst_ring_buffer_logger_log, logger, + (GDestroyNotify) gst_ring_buffer_logger_free); + G_UNLOCK (ring_buffer_logger); +} + +/** + * gst_debug_remove_ring_buffer_logger: + * + * Removes any previously added ring buffer logger with + * gst_debug_add_ring_buffer_logger(). + * + * Since: 1.14 + */ +void +gst_debug_remove_ring_buffer_logger (void) +{ + gst_debug_remove_log_function (gst_ring_buffer_logger_log); +} + +#else /* GST_DISABLE_GST_DEBUG */ +#ifndef GST_REMOVE_DISABLED + +gchar ** +gst_debug_ring_buffer_logger_get_logs (void) +{ + return NULL; +} + +void +gst_debug_add_ring_buffer_logger (guint max_size_per_thread, + guint thread_timeout) +{ +} + +void +gst_debug_remove_ring_buffer_logger (void) +{ +} + +#endif /* GST_REMOVE_DISABLED */ +#endif /* GST_DISABLE_GST_DEBUG */ diff --git a/gst/gstinfo.h b/gst/gstinfo.h new file mode 100644 index 0000000..82e4f9b --- /dev/null +++ b/gst/gstinfo.h @@ -0,0 +1,1758 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2003 Benjamin Otte + * + * gstinfo.h: debugging 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GSTINFO_H__ +#define __GSTINFO_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstDebugLevel: + * @GST_LEVEL_NONE: No debugging level specified or desired. Used to deactivate + * debugging output. + * @GST_LEVEL_ERROR: Error messages are to be used only when an error occurred + * that stops the application from keeping working correctly. + * An examples is gst_element_error, which outputs a message with this priority. + * It does not mean that the application is terminating as with g_error. + * @GST_LEVEL_WARNING: Warning messages are to inform about abnormal behaviour + * that could lead to problems or weird behaviour later on. An example of this + * would be clocking issues ("your computer is pretty slow") or broken input + * data ("Can't synchronize to stream.") + * @GST_LEVEL_FIXME: Fixme messages are messages that indicate that something + * in the executed code path is not fully implemented or handled yet. Note + * that this does not replace proper error handling in any way, the purpose + * of this message is to make it easier to spot incomplete/unfinished pieces + * of code when reading the debug log. + * @GST_LEVEL_INFO: Informational messages should be used to keep the developer + * updated about what is happening. + * Examples where this should be used are when a typefind function has + * successfully determined the type of the stream or when an mp3 plugin detects + * the format to be used. ("This file has mono sound.") + * @GST_LEVEL_DEBUG: Debugging messages should be used when something common + * happens that is not the expected default behavior, or something that's + * useful to know but doesn't happen all the time (ie. per loop iteration or + * buffer processed or event handled). + * An example would be notifications about state changes or receiving/sending + * of events. + * @GST_LEVEL_LOG: Log messages are messages that are very common but might be + * useful to know. As a rule of thumb a pipeline that is running as expected + * should never output anything else but LOG messages whilst processing data. + * Use this log level to log recurring information in chain functions and + * loop functions, for example. + * @GST_LEVEL_TRACE: Tracing-related messages. + * Examples for this are referencing/dereferencing of objects. + * @GST_LEVEL_MEMDUMP: memory dump messages are used to log (small) chunks of + * data as memory dumps in the log. They will be displayed as hexdump with + * ASCII characters. + * @GST_LEVEL_COUNT: The number of defined debugging levels. + * + * The level defines the importance of a debugging message. The more important a + * message is, the greater the probability that the debugging system outputs it. + */ +typedef enum { + GST_LEVEL_NONE = 0, + GST_LEVEL_ERROR = 1, + GST_LEVEL_WARNING = 2, + GST_LEVEL_FIXME = 3, + GST_LEVEL_INFO = 4, + GST_LEVEL_DEBUG = 5, + GST_LEVEL_LOG = 6, + GST_LEVEL_TRACE = 7, + /* add more */ + GST_LEVEL_MEMDUMP = 9, + /* add more */ + GST_LEVEL_COUNT +} GstDebugLevel; + +/** + * GST_LEVEL_DEFAULT: + * + * Defines the default debugging level to be used with GStreamer. It is normally + * set to #GST_LEVEL_NONE so nothing get printed. + * As it can be configured at compile time, developer builds may chose to + * override that though. + * You can use this as an argument to gst_debug_set_default_threshold() to + * reset the debugging output to default behaviour. + */ +#ifndef GST_LEVEL_DEFAULT +#define GST_LEVEL_DEFAULT GST_LEVEL_NONE +#endif + +/** + * GST_LEVEL_MAX: + * + * Defines the maximum debugging level to be enabled at compilation time. By default + * it is set such that all debugging statements will be enabled. + * + * If you wish to compile GStreamer and plugins with only some debugging statements + * (Such as just warnings and errors), you can define it at compile time to the + * maximum debug level. Any debug statements above that level will be compiled out. + * + * Since: 1.6 + */ +#ifndef GST_LEVEL_MAX +#define GST_LEVEL_MAX GST_LEVEL_COUNT +#endif + +/* defines for format (colors etc) + * don't change them around, it uses terminal layout + * Terminal color strings: + * 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed + * Text color codes: + * 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white + * Background color codes: + * 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white + */ +/** + * GstDebugColorFlags: + * @GST_DEBUG_FG_BLACK: Use black as foreground color. + * @GST_DEBUG_FG_RED: Use red as foreground color. + * @GST_DEBUG_FG_GREEN: Use green as foreground color. + * @GST_DEBUG_FG_YELLOW: Use yellow as foreground color. + * @GST_DEBUG_FG_BLUE: Use blue as foreground color. + * @GST_DEBUG_FG_MAGENTA: Use magenta as foreground color. + * @GST_DEBUG_FG_CYAN: Use cyan as foreground color. + * @GST_DEBUG_FG_WHITE: Use white as foreground color. + * @GST_DEBUG_BG_BLACK: Use black as background color. + * @GST_DEBUG_BG_RED: Use red as background color. + * @GST_DEBUG_BG_GREEN: Use green as background color. + * @GST_DEBUG_BG_YELLOW: Use yellow as background color. + * @GST_DEBUG_BG_BLUE: Use blue as background color. + * @GST_DEBUG_BG_MAGENTA: Use magenta as background color. + * @GST_DEBUG_BG_CYAN: Use cyan as background color. + * @GST_DEBUG_BG_WHITE: Use white as background color. + * @GST_DEBUG_BOLD: Make the output bold. + * @GST_DEBUG_UNDERLINE: Underline the output. + * + * These are some terminal style flags you can use when creating your + * debugging categories to make them stand out in debugging output. + */ +typedef enum { /*< flags >*/ + /* colors */ + GST_DEBUG_FG_BLACK = 0x0000, + GST_DEBUG_FG_RED = 0x0001, + GST_DEBUG_FG_GREEN = 0x0002, + GST_DEBUG_FG_YELLOW = 0x0003, + GST_DEBUG_FG_BLUE = 0x0004, + GST_DEBUG_FG_MAGENTA = 0x0005, + GST_DEBUG_FG_CYAN = 0x0006, + GST_DEBUG_FG_WHITE = 0x0007, + /* background colors */ + GST_DEBUG_BG_BLACK = 0x0000, + GST_DEBUG_BG_RED = 0x0010, + GST_DEBUG_BG_GREEN = 0x0020, + GST_DEBUG_BG_YELLOW = 0x0030, + GST_DEBUG_BG_BLUE = 0x0040, + GST_DEBUG_BG_MAGENTA = 0x0050, + GST_DEBUG_BG_CYAN = 0x0060, + GST_DEBUG_BG_WHITE = 0x0070, + /* other formats */ + GST_DEBUG_BOLD = 0x0100, + GST_DEBUG_UNDERLINE = 0x0200 +} GstDebugColorFlags; + +/** + * GstStackTraceFlags: + * @GST_STACK_TRACE_SHOW_FULL: Try to retrieve as much information as + * possible when getting the stack trace + * + * Since: 1.12 + */ +typedef enum { + GST_STACK_TRACE_SHOW_FULL = 1 << 0 +} GstStackTraceFlags; + +/** + * GstDebugColorMode: + * @GST_DEBUG_COLOR_MODE_OFF: Do not use colors in logs. + * @GST_DEBUG_COLOR_MODE_ON: Paint logs in a platform-specific way. + * @GST_DEBUG_COLOR_MODE_UNIX: Paint logs with UNIX terminal color codes + * no matter what platform GStreamer is running on. + */ +typedef enum { + GST_DEBUG_COLOR_MODE_OFF = 0, + GST_DEBUG_COLOR_MODE_ON = 1, + GST_DEBUG_COLOR_MODE_UNIX = 2 +} GstDebugColorMode; + + +#define GST_DEBUG_FG_MASK (0x000F) +#define GST_DEBUG_BG_MASK (0x00F0) +#define GST_DEBUG_FORMAT_MASK (0xFF00) + +typedef struct _GstDebugCategory GstDebugCategory; +/** + * GstDebugCategory: + * + * This is the struct that describes the categories. Once initialized with + * #GST_DEBUG_CATEGORY_INIT, its values can't be changed anymore. + */ +struct _GstDebugCategory { + /*< private >*/ + gint threshold; + guint color; /* see defines above */ + + const gchar * name; + const gchar * description; +}; + +/********** some convenience macros for debugging **********/ + +/** + * GST_STR_NULL: + * @str: (allow-none): The string to check. + * + * Macro to use when a string must not be %NULL, but may be %NULL. If the string + * is %NULL, "(NULL)" is printed instead. + * In GStreamer printf string arguments may not be %NULL, because on some + * platforms (ie Solaris) the libc crashes in that case. This includes debugging + * strings. + */ +#define GST_STR_NULL(str) ((str) ? (str) : "(NULL)") + +/* FIXME, not MT safe */ +/** + * GST_DEBUG_PAD_NAME: + * @pad: The pad to debug. + * + * Evaluates to 2 strings, that describe the pad. Often used in debugging + * statements. + */ +#define GST_DEBUG_PAD_NAME(pad) \ + (pad != NULL) ? \ + ((GST_OBJECT_PARENT(pad) != NULL) ? \ + GST_STR_NULL (GST_OBJECT_NAME (GST_OBJECT_PARENT(pad))) : \ + "''" ) : "''", \ + (pad != NULL) ? GST_STR_NULL (GST_OBJECT_NAME (pad)) : "''" + +/** + * GST_FUNCTION: + * + * This macro should evaluate to the name of the current function and be should + * be defined when configuring your project, as it is compiler dependant. If it + * is not defined, some default value is used. It is used to provide debugging + * output with the function name of the message. + * + * Note that this is different from G_STRFUNC as we do not want the full + * function signature in C++ code. + */ +#ifndef GST_FUNCTION +#if defined (__STDC__) && defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define GST_FUNCTION ((const char*) (__func__)) +#elif defined (__GNUC__) || (defined (_MSC_VER) && _MSC_VER >= 1300) +# define GST_FUNCTION ((const char*) (__FUNCTION__)) +#else +# define GST_FUNCTION ((const char*) ("???")) +#endif +#endif /* ifndef GST_FUNCTION */ + +/** + * GST_PTR_FORMAT: + * + * printf format type used to debug GStreamer types. You can use this in + * combination with GStreamer's debug logging system as well as the functions + * gst_info_vasprintf(), gst_info_strdup_vprintf() and gst_info_strdup_printf() + * to pretty-print the following types: #GstCaps, #GstStructure, + * #GstCapsFeatures, #GstTagList, #GstDateTime, #GstBuffer, #GstBufferList, + * #GstMessage, #GstEvent, #GstQuery, #GstContext, #GstPad, #GstObject. All + * #GObject types will be printed as typename plus pointer, and everything + * else will simply be printed as pointer address. + * + * This can only be used on types whose size is >= sizeof(gpointer). + */ +#define GST_PTR_FORMAT "p\aA" + +/** + * GST_SEGMENT_FORMAT: + * + * printf format type used to debug GStreamer segments. You can use this in + * combination with GStreamer's debug logging system as well as the functions + * gst_info_vasprintf(), gst_info_strdup_vprintf() and gst_info_strdup_printf() + * to pretty-print #GstSegment structures. + * This can only be used on pointers to GstSegment structures. + */ +#define GST_SEGMENT_FORMAT "p\aB" + +typedef struct _GstDebugMessage GstDebugMessage; + +/** + * GstLogFunction: + * @category: a #GstDebugCategory + * @level: a #GstDebugLevel + * @file: file name + * @function: function name + * @line: line number + * @object: a #GObject + * @message: the message + * @user_data: user data for the log function + * + * Function prototype for a logging function that can be registered with + * gst_debug_add_log_function(). + * Use G_GNUC_NO_INSTRUMENT on that function. + */ +typedef void (*GstLogFunction) (GstDebugCategory * category, + GstDebugLevel level, + const gchar * file, + const gchar * function, + gint line, + GObject * object, + GstDebugMessage * message, + gpointer user_data); + +GST_API +void gst_debug_log (GstDebugCategory * category, + GstDebugLevel level, + const gchar * file, + const gchar * function, + gint line, + GObject * object, + const gchar * format, + ...) G_GNUC_PRINTF (7, 8) G_GNUC_NO_INSTRUMENT; +GST_API +void gst_debug_log_valist (GstDebugCategory * category, + GstDebugLevel level, + const gchar * file, + const gchar * function, + gint line, + GObject * object, + const gchar * format, + va_list args) G_GNUC_NO_INSTRUMENT; + +/* do not use this function, use the GST_DEBUG_CATEGORY_INIT macro */ + +GST_API +GstDebugCategory *_gst_debug_category_new (const gchar * name, + guint color, + const gchar * description); + +/* do not use this function, use the GST_DEBUG_CATEGORY_GET macro */ + +GST_API +GstDebugCategory *_gst_debug_get_category (const gchar *name); + + +/* do not use this function, use the GST_CAT_MEMDUMP_* macros */ + +GST_API +void _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file, + const gchar * func, gint line, GObject * obj, const gchar * msg, + const guint8 * data, guint length); + +/* we define this to avoid a compiler warning regarding a cast from a function + * pointer to a void pointer + * (see https://bugzilla.gnome.org/show_bug.cgi?id=309253) + */ +typedef void (* GstDebugFuncPtr) (void); + +/* do no use these functions, use the GST_DEBUG*_FUNCPTR macros */ + +GST_API +void _gst_debug_register_funcptr (GstDebugFuncPtr func, + const gchar * ptrname); +GST_API +const gchar * + _gst_debug_nameof_funcptr (GstDebugFuncPtr func) G_GNUC_NO_INSTRUMENT; + + +GST_API +const gchar * gst_debug_message_get (GstDebugMessage * message); + +GST_API +void gst_debug_log_default (GstDebugCategory * category, + GstDebugLevel level, + const gchar * file, + const gchar * function, + gint line, + GObject * object, + GstDebugMessage * message, + gpointer user_data) G_GNUC_NO_INSTRUMENT; +GST_API +const gchar * gst_debug_level_get_name (GstDebugLevel level); + +GST_API +void gst_debug_add_log_function (GstLogFunction func, + gpointer user_data, + GDestroyNotify notify); +GST_API +guint gst_debug_remove_log_function (GstLogFunction func); + +GST_API +guint gst_debug_remove_log_function_by_data (gpointer data); + +GST_API +void gst_debug_set_active (gboolean active); + +GST_API +gboolean gst_debug_is_active (void); + +GST_API +void gst_debug_set_colored (gboolean colored); + +GST_API +void gst_debug_set_color_mode (GstDebugColorMode mode); + +GST_API +void gst_debug_set_color_mode_from_string (const gchar * mode); + +GST_API +gboolean gst_debug_is_colored (void); + +GST_API +GstDebugColorMode gst_debug_get_color_mode (void); + +GST_API +void gst_debug_set_default_threshold (GstDebugLevel level); + +GST_API +GstDebugLevel gst_debug_get_default_threshold (void); + +GST_API +void gst_debug_set_threshold_for_name (const gchar * name, + GstDebugLevel level); +GST_API +void gst_debug_set_threshold_from_string (const gchar * list, gboolean reset); + +GST_API +void gst_debug_unset_threshold_for_name (const gchar * name); + + +GST_API +void gst_debug_category_free (GstDebugCategory * category); + +GST_API +void gst_debug_category_set_threshold (GstDebugCategory * category, + GstDebugLevel level); + +GST_API +void gst_debug_category_reset_threshold (GstDebugCategory * category); + +GST_API +GstDebugLevel gst_debug_category_get_threshold (GstDebugCategory * category); + +GST_API +const gchar * gst_debug_category_get_name (GstDebugCategory * category); + +GST_API +guint gst_debug_category_get_color (GstDebugCategory * category); + +GST_API +const gchar * gst_debug_category_get_description (GstDebugCategory * category); + +GST_API +GSList * gst_debug_get_all_categories (void); + + +GST_API +gchar * gst_debug_construct_term_color (guint colorinfo); + +GST_API +gint gst_debug_construct_win_color (guint colorinfo); + +GST_API +gint gst_info_vasprintf (gchar ** result, + const gchar * format, + va_list args) G_GNUC_PRINTF (2, 0); +GST_API +gchar * gst_info_strdup_vprintf (const gchar *format, va_list args) G_GNUC_PRINTF (1, 0); + +GST_API +gchar * gst_info_strdup_printf (const gchar *format, ...) G_GNUC_PRINTF (1, 2); + +GST_API +void gst_print (const gchar * format, ...) G_GNUC_PRINTF (1, 2); + +GST_API +void gst_println (const gchar * format, ...) G_GNUC_PRINTF (1, 2); + +GST_API +void gst_printerr (const gchar * format, ...) G_GNUC_PRINTF (1, 2); + +GST_API +void gst_printerrln (const gchar * format, ...) G_GNUC_PRINTF (1, 2); + +#ifndef GST_DISABLE_GST_DEBUG + +/* cast to void * avoids a warning with gcc 6 + * see https://bugzilla.gnome.org/show_bug.cgi?id=764526 */ +#define gst_debug_add_log_function(func,data,notify) \ +G_STMT_START{ \ + if ((func) == (void *) gst_debug_log_default) { \ + gst_debug_add_log_function(NULL,data,notify); \ + } else { \ + gst_debug_add_log_function(func,data,notify); \ + } \ +}G_STMT_END + +#define gst_debug_remove_log_function(func) \ + ((func) == (void *) gst_debug_log_default) ? \ + gst_debug_remove_log_function(NULL) : \ + gst_debug_remove_log_function(func) + +/** + * GST_DEBUG_CATEGORY: + * @cat: the category + * + * Defines a GstDebugCategory variable. + * This macro expands to nothing if debugging is disabled. + */ +#define GST_DEBUG_CATEGORY(cat) GstDebugCategory *cat = NULL +/** + * GST_DEBUG_CATEGORY_EXTERN: + * @cat: the category + * + * Declares a GstDebugCategory variable as extern. Use in header files. + * This macro expands to nothing if debugging is disabled. + */ +#define GST_DEBUG_CATEGORY_EXTERN(cat) extern GstDebugCategory *cat + +/** + * GST_DEBUG_CATEGORY_STATIC: + * @cat: the category + * + * Defines a static GstDebugCategory variable. + * This macro expands to nothing if debugging is disabled. + */ +#define GST_DEBUG_CATEGORY_STATIC(cat) static GstDebugCategory *cat = NULL + +/** + * GST_DEBUG_CATEGORY_INIT: + * @cat: the category to initialize. + * @name: the name of the category. + * @color: the colors to use for a color representation or 0 for no color. + * @description: optional description of the category. + * + * Initializes a new #GstDebugCategory with the given properties and set to + * the default threshold. + * + * > This macro expands to nothing if debugging is disabled. + * > + * > When naming your category, please follow the following conventions to ensure + * > that the pattern matching for categories works as expected. It is not + * > earth-shattering if you don't follow these conventions, but it would be nice + * > for everyone. + * > + * > If you define a category for a plugin or a feature of it, name the category + * > like the feature. So if you wanted to write a "filesrc" element, you would + * > name the category "filesrc". Use lowercase letters only. + * > If you define more than one category for the same element, append an + * > underscore and an identifier to your categories, like this: "filesrc_cache" + * > + * > If you create a library or an application using debugging categories, use a + * > common prefix followed by an underscore for all your categories. GStreamer + * > uses the GST prefix so GStreamer categories look like "GST_STATES". Be sure + * > to include uppercase letters. + * + */ +#define GST_DEBUG_CATEGORY_INIT(cat,name,color,description) G_STMT_START{\ + if (cat == NULL) \ + cat = _gst_debug_category_new (name,color,description); \ +}G_STMT_END + +/** + * GST_DEBUG_CATEGORY_GET: + * @cat: the category to initialize. + * @name: log category name + * + * Looks up an existing #GstDebugCategory by its @name and sets @cat. If the + * category is not found, but GST_CAT_DEFAULT is defined, that is assigned to + * @cat. Otherwise @cat will be %NULL. + * + * |[ + * GST_DEBUG_CATEGORY_STATIC (gst_myplugin_debug); + * #define GST_CAT_DEFAULT gst_myplugin_debug + * GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); + * ... + * GST_DEBUG_CATEGORY_INIT (gst_myplugin_debug, "myplugin", 0, "nice element"); + * GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); + * ]| + */ +#ifdef GST_CAT_DEFAULT +#define GST_DEBUG_CATEGORY_GET(cat,name) G_STMT_START{\ + cat = _gst_debug_get_category (name); \ + if (!cat) { \ + cat = GST_CAT_DEFAULT; \ + } \ +}G_STMT_END +#else +#define GST_DEBUG_CATEGORY_GET(cat,name) G_STMT_START{\ + cat = _gst_debug_get_category (name); \ +}G_STMT_END +#endif + +/** + * GST_CAT_DEFAULT: + * + * Default gstreamer core debug log category. Please define your own. + */ + +GST_API GstDebugCategory * GST_CAT_DEFAULT; +/* this symbol may not be used */ + +GST_API gboolean _gst_debug_enabled; + +/* the min debug level, used for quickly discarding debug + * messages that fall under the threshold. */ + +GST_API GstDebugLevel _gst_debug_min; + +/** + * GST_CAT_LEVEL_LOG: + * @cat: category to use + * @level: the severity of the message + * @object: (allow-none): the #GObject the message belongs to or %NULL if none + * @...: A printf-style message to output + * + * Outputs a debugging message. This is the most general macro for outputting + * debugging messages. You will probably want to use one of the ones described + * below. + * + * There is no need to finish the end of the debug message with a newline + * character, a newline character will be added automatically. + */ +#ifdef G_HAVE_ISO_VARARGS +#define GST_CAT_LEVEL_LOG(cat,level,object,...) G_STMT_START{ \ + if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \ + gst_debug_log ((cat), (level), __FILE__, GST_FUNCTION, __LINE__, \ + (GObject *) (object), __VA_ARGS__); \ + } \ +}G_STMT_END +#else /* G_HAVE_GNUC_VARARGS */ +#ifdef G_HAVE_GNUC_VARARGS +#define GST_CAT_LEVEL_LOG(cat,level,object,args...) G_STMT_START{ \ + if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \ + gst_debug_log ((cat), (level), __FILE__, GST_FUNCTION, __LINE__, \ + (GObject *) (object), ##args ); \ + } \ +}G_STMT_END +#else /* no variadic macros, use inline */ +static inline void +GST_CAT_LEVEL_LOG_valist (GstDebugCategory * cat, + GstDebugLevel level, gpointer object, const char *format, va_list varargs) +{ + if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { + gst_debug_log_valist (cat, level, "", "", 0, (GObject *) object, format, + varargs); + } +} + +static inline void +GST_CAT_LEVEL_LOG (GstDebugCategory * cat, GstDebugLevel level, + gpointer object, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, level, object, format, varargs); + va_end (varargs); +} +#endif +#endif /* G_HAVE_ISO_VARARGS */ + +/* This one doesn't have varargs in the macro, so it's different than all the + * other macros and hence in a separate block right here. Docs chunks are + * with the other doc chunks below though. */ +#define __GST_CAT_MEMDUMP_LOG(cat,object,msg,data,length) G_STMT_START{ \ + if (G_UNLIKELY (GST_LEVEL_MEMDUMP <= GST_LEVEL_MAX && \ + GST_LEVEL_MEMDUMP <= _gst_debug_min)) { \ + _gst_debug_dump_mem ((cat), __FILE__, GST_FUNCTION, __LINE__, \ + (GObject *) (object), (msg), (data), (length)); \ + } \ +}G_STMT_END + +#define GST_CAT_MEMDUMP_OBJECT(cat,obj,msg,data,length) \ + __GST_CAT_MEMDUMP_LOG(cat,obj,msg,data,length) +#define GST_CAT_MEMDUMP(cat,msg,data,length) \ + __GST_CAT_MEMDUMP_LOG(cat,NULL,msg,data,length) +#define GST_MEMDUMP_OBJECT(obj,msg,data,length) \ + __GST_CAT_MEMDUMP_LOG(GST_CAT_DEFAULT,obj,msg,data,length) +#define GST_MEMDUMP(msg,data,length) \ + __GST_CAT_MEMDUMP_LOG(GST_CAT_DEFAULT,NULL,msg,data,length) + +/** + * GST_CAT_ERROR_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an error message belonging to the given object in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_WARNING_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a warning message belonging to the given object in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_INFO_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an informational message belonging to the given object in the given + * category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_DEBUG_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an debugging message belonging to the given object in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_LOG_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an logging message belonging to the given object in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_FIXME_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a fixme message belonging to the given object in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_TRACE_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a tracing message belonging to the given object in the given + * category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_MEMDUMP_OBJECT: + * @cat: category to use + * @obj: the #GObject the message belongs to + * @msg: message string to log with the data + * @data: pointer to the data to output + * @length: length of the data to output + * + * Output a hexdump of @data relating to the given object in the given + * category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ + + +/** + * GST_CAT_ERROR: + * @cat: category to use + * @...: printf-style message to output + * + * Output an error message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_WARNING: + * @cat: category to use + * @...: printf-style message to output + * + * Output an warning message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_INFO: + * @cat: category to use + * @...: printf-style message to output + * + * Output an informational message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_DEBUG: + * @cat: category to use + * @...: printf-style message to output + * + * Output an debugging message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_LOG: + * @cat: category to use + * @...: printf-style message to output + * + * Output an logging message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_FIXME: + * @cat: category to use + * @...: printf-style message to output + * + * Output an fixme message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_TRACE: + * @cat: category to use + * @...: printf-style message to output + * + * Output a tracing message in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_CAT_MEMDUMP: + * @cat: category to use + * @msg: message string to log with the data + * @data: pointer to the data to output + * @length: length of the data to output + * + * Output a hexdump of @data in the given category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ + + +/** + * GST_ERROR_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an error message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_WARNING_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a warning message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_INFO_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output an informational message belonging to the given object in the default + * category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_DEBUG_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a debugging message belonging to the given object in the default + * category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_LOG_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a logging message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_FIXME_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a fixme message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_TRACE_OBJECT: + * @obj: the #GObject the message belongs to + * @...: printf-style message to output + * + * Output a tracing message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_MEMDUMP_OBJECT: + * @obj: the #GObject the message belongs to + * @msg: message string to log with the data + * @data: pointer to the data to output + * @length: length of the data to output + * + * Output a logging message belonging to the given object in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ + + +/** + * GST_ERROR: + * @...: printf-style message to output + * + * Output an error message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_WARNING: + * @...: printf-style message to output + * + * Output a warning message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_INFO: + * @...: printf-style message to output + * + * Output an informational message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_DEBUG: + * @...: printf-style message to output + * + * Output a debugging message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_LOG: + * @...: printf-style message to output + * + * Output a logging message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_FIXME: + * @...: printf-style message to output + * + * Output a fixme message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_TRACE: + * @...: printf-style message to output + * + * Output a tracing message in the default category. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ +/** + * GST_MEMDUMP: + * @msg: message string to log with the data + * @data: pointer to the data to output + * @length: length of the data to output + * + * Output a hexdump of @data. + * + * There is no need to finish the end of the message string with a newline + * character, a newline character will be added automatically. + */ + +#ifdef G_HAVE_ISO_VARARGS + +#define GST_CAT_ERROR_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR, obj, __VA_ARGS__) +#define GST_CAT_WARNING_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, obj, __VA_ARGS__) +#define GST_CAT_INFO_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO, obj, __VA_ARGS__) +#define GST_CAT_DEBUG_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG, obj, __VA_ARGS__) +#define GST_CAT_LOG_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG, obj, __VA_ARGS__) +#define GST_CAT_FIXME_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME, obj, __VA_ARGS__) +#define GST_CAT_TRACE_OBJECT(cat,obj,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE, obj, __VA_ARGS__) + +#define GST_CAT_ERROR(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR, NULL, __VA_ARGS__) +#define GST_CAT_WARNING(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, NULL, __VA_ARGS__) +#define GST_CAT_INFO(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO, NULL, __VA_ARGS__) +#define GST_CAT_DEBUG(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG, NULL, __VA_ARGS__) +#define GST_CAT_LOG(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG, NULL, __VA_ARGS__) +#define GST_CAT_FIXME(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME, NULL, __VA_ARGS__) +#define GST_CAT_TRACE(cat,...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE, NULL, __VA_ARGS__) + +#define GST_ERROR_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR, obj, __VA_ARGS__) +#define GST_WARNING_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj, __VA_ARGS__) +#define GST_INFO_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO, obj, __VA_ARGS__) +#define GST_DEBUG_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, obj, __VA_ARGS__) +#define GST_LOG_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG, obj, __VA_ARGS__) +#define GST_FIXME_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME, obj, __VA_ARGS__) +#define GST_TRACE_OBJECT(obj,...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE, obj, __VA_ARGS__) + +#define GST_ERROR(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR, NULL, __VA_ARGS__) +#define GST_WARNING(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, __VA_ARGS__) +#define GST_INFO(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO, NULL, __VA_ARGS__) +#define GST_DEBUG(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, NULL, __VA_ARGS__) +#define GST_LOG(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG, NULL, __VA_ARGS__) +#define GST_FIXME(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME, NULL, __VA_ARGS__) +#define GST_TRACE(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE, NULL, __VA_ARGS__) + +#else +#ifdef G_HAVE_GNUC_VARARGS + +#define GST_CAT_ERROR_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR, obj, ##args ) +#define GST_CAT_WARNING_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, obj, ##args ) +#define GST_CAT_INFO_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO, obj, ##args ) +#define GST_CAT_DEBUG_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG, obj, ##args ) +#define GST_CAT_LOG_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG, obj, ##args ) +#define GST_CAT_FIXME_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME, obj, ##args ) +#define GST_CAT_TRACE_OBJECT(cat,obj,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE, obj, ##args ) + +#define GST_CAT_ERROR(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_ERROR, NULL, ##args ) +#define GST_CAT_WARNING(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_WARNING, NULL, ##args ) +#define GST_CAT_INFO(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_INFO, NULL, ##args ) +#define GST_CAT_DEBUG(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_DEBUG, NULL, ##args ) +#define GST_CAT_LOG(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_LOG, NULL, ##args ) +#define GST_CAT_FIXME(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_FIXME, NULL, ##args ) +#define GST_CAT_TRACE(cat,args...) GST_CAT_LEVEL_LOG (cat, GST_LEVEL_TRACE, NULL, ##args ) + +#define GST_ERROR_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR, obj, ##args ) +#define GST_WARNING_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj, ##args ) +#define GST_INFO_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO, obj, ##args ) +#define GST_DEBUG_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, obj, ##args ) +#define GST_LOG_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG, obj, ##args ) +#define GST_FIXME_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME, obj, ##args ) +#define GST_TRACE_OBJECT(obj,args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE, obj, ##args ) + +#define GST_ERROR(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR, NULL, ##args ) +#define GST_WARNING(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, ##args ) +#define GST_INFO(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO, NULL, ##args ) +#define GST_DEBUG(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, NULL, ##args ) +#define GST_LOG(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG, NULL, ##args ) +#define GST_FIXME(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME, NULL, ##args ) +#define GST_TRACE(args...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE, NULL, ##args ) + +#else +/* no variadic macros, use inline */ +static inline void +GST_CAT_ERROR_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_ERROR, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_WARNING_OBJECT (GstDebugCategory * cat, gpointer obj, + const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_WARNING, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_INFO_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_INFO, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_DEBUG_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_DEBUG, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_LOG_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_LOG, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_FIXME_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_FIXME, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_TRACE_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_TRACE, obj, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_ERROR (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_ERROR, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_WARNING (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_WARNING, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_INFO (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_INFO, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_DEBUG (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_DEBUG, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_LOG (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_LOG, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_FIXME (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_FIXME, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_CAT_TRACE (GstDebugCategory * cat, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (cat, GST_LEVEL_TRACE, NULL, format, varargs); + va_end (varargs); +} + +static inline void +GST_ERROR_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_ERROR, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_WARNING_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_INFO_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_INFO, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_DEBUG_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_LOG_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_LOG, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_FIXME_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_FIXME, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_TRACE_OBJECT (gpointer obj, const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_TRACE, obj, format, + varargs); + va_end (varargs); +} + +static inline void +GST_ERROR (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_ERROR, NULL, format, + varargs); + va_end (varargs); +} + +static inline void +GST_WARNING (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, format, + varargs); + va_end (varargs); +} + +static inline void +GST_INFO (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_INFO, NULL, format, + varargs); + va_end (varargs); +} + +static inline void +GST_DEBUG (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, NULL, format, + varargs); + va_end (varargs); +} + +static inline void +GST_LOG (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_LOG, NULL, + format, varargs); + va_end (varargs); +} + +static inline void +GST_FIXME (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_FIXME, NULL, format, + varargs); + va_end (varargs); +} + +static inline void +GST_TRACE (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_DEFAULT, GST_LEVEL_TRACE, NULL, format, + varargs); + va_end (varargs); +} +#endif +#endif + + +/********** function pointer stuff **********/ + +/** + * GST_DEBUG_REGISTER_FUNCPTR: + * @ptr: pointer to the function to register + * + * Register a pointer to a function with its name, so it can later be used by + * GST_DEBUG_FUNCPTR_NAME(). + * + * Use this variant of #GST_DEBUG_FUNCPTR if you do not need to use @ptr. + */ +#define GST_DEBUG_REGISTER_FUNCPTR(ptr) \ + _gst_debug_register_funcptr((GstDebugFuncPtr)(ptr), #ptr) +/** + * GST_DEBUG_FUNCPTR: + * @ptr: pointer to the function to register + * + * Register a pointer to a function with its name, so it can later be used by + * GST_DEBUG_FUNCPTR_NAME(). + * + * Returns: the value passed to @ptr. + */ +#define GST_DEBUG_FUNCPTR(ptr) \ + (_gst_debug_register_funcptr((GstDebugFuncPtr)(ptr), #ptr) , ptr) + +/** + * GST_DEBUG_FUNCPTR_NAME: + * @ptr: address of the function of which to look up the name + * + * Retrieves the name of the function, if it was previously registered with + * GST_DEBUG_FUNCPTR(). If not, it returns a description of the pointer. + * + * This macro returns a constant string which must not be modified or + * freed by the caller. + */ +#define GST_DEBUG_FUNCPTR_NAME(ptr) \ + _gst_debug_nameof_funcptr((GstDebugFuncPtr)ptr) + + +#else /* GST_DISABLE_GST_DEBUG */ + + +#ifndef GST_INFO_C + +#if defined(__GNUC__) && __GNUC__ >= 3 +# pragma GCC poison gst_debug_log +# pragma GCC poison gst_debug_log_valist +# pragma GCC poison _gst_debug_category_new +#endif + +#define _gst_debug_min GST_LEVEL_NONE + +#define gst_debug_set_default_threshold(level) G_STMT_START{ }G_STMT_END +#define gst_debug_get_default_threshold() (GST_LEVEL_NONE) + +#define gst_debug_level_get_name(level) ("NONE") +#define gst_debug_message_get(message) ("") +#define gst_debug_add_log_function(func,data,notify) G_STMT_START{ }G_STMT_END +#define gst_debug_set_active(active) G_STMT_START{ }G_STMT_END +#define gst_debug_is_active() (FALSE) +#define gst_debug_set_colored(colored) G_STMT_START{ }G_STMT_END +#define gst_debug_set_color_mode(mode) G_STMT_START{ }G_STMT_END +#define gst_debug_set_color_mode_from_string(mode) G_STMT_START{ }G_STMT_END +#define gst_debug_is_colored() (FALSE) +#define gst_debug_get_color_mode() (GST_DEBUG_COLOR_MODE_OFF) +#define gst_debug_set_default_threshold(level) G_STMT_START{ }G_STMT_END +#define gst_debug_get_default_threshold() (GST_LEVEL_NONE) +#define gst_debug_set_threshold_for_name(name,level) G_STMT_START{ }G_STMT_END +#define gst_debug_unset_threshold_for_name(name) G_STMT_START{ }G_STMT_END + +/* we are using dummy function prototypes here to eat ';' as these macros are + * used outside of functions */ +#define GST_DEBUG_CATEGORY(var) void _gst_debug_dummy_##var (void) +#define GST_DEBUG_CATEGORY_EXTERN(var) void _gst_debug_dummy_extern_##var (void) +#define GST_DEBUG_CATEGORY_STATIC(var) void _gst_debug_dummy_static_##var (void) + +#define GST_DEBUG_CATEGORY_INIT(var,name,color,desc) G_STMT_START{ }G_STMT_END +#define GST_DEBUG_CATEGORY_GET(var,name) G_STMT_START{ }G_STMT_END +#define gst_debug_category_free(category) G_STMT_START{ }G_STMT_END +#define gst_debug_category_set_threshold(category,level) G_STMT_START{ }G_STMT_END +#define gst_debug_category_reset_threshold(category) G_STMT_START{ }G_STMT_END +#define gst_debug_category_get_threshold(category) (GST_LEVEL_NONE) +#define gst_debug_category_get_name(cat) ("") +#define gst_debug_category_get_color(cat) (0) +#define gst_debug_category_get_description(cat) ("") +#define gst_debug_get_all_categories() (NULL) +#define gst_debug_construct_term_color(colorinfo) (g_strdup ("00")) +#define gst_debug_construct_win_color(colorinfo) (0) + +#endif /* !GST_INFO_C */ + +#ifdef G_HAVE_ISO_VARARGS + +#define GST_CAT_LEVEL_LOG(cat,level,...) G_STMT_START{ }G_STMT_END + +#define GST_CAT_ERROR_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_WARNING_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_INFO_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_DEBUG_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_LOG_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_FIXME_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_TRACE_OBJECT(...) G_STMT_START{ }G_STMT_END + +#define GST_CAT_ERROR(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_WARNING(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_INFO(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_DEBUG(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_LOG(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_FIXME(...) G_STMT_START{ }G_STMT_END +#define GST_CAT_TRACE(...) G_STMT_START{ }G_STMT_END + +#define GST_ERROR_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_WARNING_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_INFO_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_DEBUG_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_LOG_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_FIXME_OBJECT(...) G_STMT_START{ }G_STMT_END +#define GST_TRACE_OBJECT(...) G_STMT_START{ }G_STMT_END + +#define GST_ERROR(...) G_STMT_START{ }G_STMT_END +#define GST_WARNING(...) G_STMT_START{ }G_STMT_END +#define GST_INFO(...) G_STMT_START{ }G_STMT_END +#define GST_DEBUG(...) G_STMT_START{ }G_STMT_END +#define GST_LOG(...) G_STMT_START{ }G_STMT_END +#define GST_FIXME(...) G_STMT_START{ }G_STMT_END +#define GST_TRACE(...) G_STMT_START{ }G_STMT_END + +#else /* !G_HAVE_ISO_VARARGS */ +#ifdef G_HAVE_GNUC_VARARGS + +#define GST_CAT_LEVEL_LOG(cat,level,args...) G_STMT_START{ }G_STMT_END + +#define GST_CAT_ERROR_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_WARNING_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_INFO_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_DEBUG_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_LOG_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_FIXME_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_TRACE_OBJECT(args...) G_STMT_START{ }G_STMT_END + +#define GST_CAT_ERROR(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_WARNING(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_INFO(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_DEBUG(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_LOG(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_FIXME(args...) G_STMT_START{ }G_STMT_END +#define GST_CAT_TRACE(args...) G_STMT_START{ }G_STMT_END + +#define GST_ERROR_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_WARNING_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_INFO_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_DEBUG_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_LOG_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_FIXME_OBJECT(args...) G_STMT_START{ }G_STMT_END +#define GST_TRACE_OBJECT(args...) G_STMT_START{ }G_STMT_END + +#define GST_ERROR(args...) G_STMT_START{ }G_STMT_END +#define GST_WARNING(args...) G_STMT_START{ }G_STMT_END +#define GST_INFO(args...) G_STMT_START{ }G_STMT_END +#define GST_DEBUG(args...) G_STMT_START{ }G_STMT_END +#define GST_LOG(args...) G_STMT_START{ }G_STMT_END +#define GST_FIXME(args...) G_STMT_START{ }G_STMT_END +#define GST_TRACE(args...) G_STMT_START{ }G_STMT_END + +#else /* !G_HAVE_GNUC_VARARGS */ +static inline void +GST_CAT_LEVEL_LOG_valist (GstDebugCategory * cat, + GstDebugLevel level, gpointer object, const char *format, va_list varargs) +{ +} + +static inline void +GST_CAT_ERROR_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_WARNING_OBJECT (GstDebugCategory * cat, gpointer obj, + const char *format, ...) +{ +} + +static inline void +GST_CAT_INFO_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_DEBUG_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_LOG_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_FIXME_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_TRACE_OBJECT (GstDebugCategory * cat, gpointer obj, const char *format, + ...) +{ +} + +static inline void +GST_CAT_ERROR (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_WARNING (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_INFO (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_DEBUG (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_LOG (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_FIXME (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_CAT_TRACE (GstDebugCategory * cat, const char *format, ...) +{ +} + +static inline void +GST_ERROR_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_WARNING_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_INFO_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_DEBUG_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_LOG_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_FIXME_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_TRACE_OBJECT (gpointer obj, const char *format, ...) +{ +} + +static inline void +GST_ERROR (const char *format, ...) +{ +} + +static inline void +GST_WARNING (const char *format, ...) +{ +} + +static inline void +GST_INFO (const char *format, ...) +{ +} + +static inline void +GST_DEBUG (const char *format, ...) +{ +} + +static inline void +GST_LOG (const char *format, ...) +{ +} + +static inline void +GST_FIXME (const char *format, ...) +{ +} + +static inline void +GST_TRACE (const char *format, ...) +{ +} + +#endif /* G_HAVE_GNUC_VARARGS */ +#endif /* G_HAVE_ISO_VARARGS */ + +#define GST_DEBUG_REGISTER_FUNCPTR(ptr) G_STMT_START{ }G_STMT_END +#define GST_DEBUG_FUNCPTR(ptr) (ptr) +#define GST_DEBUG_FUNCPTR_NAME(ptr) (g_strdup_printf ("%p", ptr)) + +#define GST_CAT_MEMDUMP_OBJECT(cat,obj,msg,data,length) G_STMT_START{ }G_STMT_END +#define GST_CAT_MEMDUMP(cat,msg,data,length) G_STMT_START{ }G_STMT_END +#define GST_MEMDUMP_OBJECT(obj,msg,data,length) G_STMT_START{ }G_STMT_END +#define GST_MEMDUMP(msg,data,length) G_STMT_START{ }G_STMT_END + +#endif /* GST_DISABLE_GST_DEBUG */ + + +GST_API +void gst_debug_print_stack_trace (void); + +GST_API +gchar * gst_debug_get_stack_trace (GstStackTraceFlags flags); + +GST_API +void gst_debug_add_ring_buffer_logger (guint max_size_per_thread, guint thread_timeout); +GST_API +void gst_debug_remove_ring_buffer_logger (void); +GST_API +gchar ** gst_debug_ring_buffer_logger_get_logs (void); + +G_END_DECLS + +#endif /* __GSTINFO_H__ */ diff --git a/gst/gstiterator.c b/gst/gstiterator.c new file mode 100644 index 0000000..e7e5875 --- /dev/null +++ b/gst/gstiterator.c @@ -0,0 +1,837 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge + * + * gstiterator.h: Base class for iterating datastructures. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstiterator + * @title: GstIterator + * @short_description: Object to retrieve multiple elements in a threadsafe + * way. + * @see_also: #GstElement, #GstBin + * + * A GstIterator is used to retrieve multiple objects from another object in + * a threadsafe way. + * + * Various GStreamer objects provide access to their internal structures using + * an iterator. + * + * Note that if calling a GstIterator function results in your code receiving + * a refcounted object (with, say, g_value_get_object()), the refcount for that + * object will not be increased. Your code is responsible for taking a reference + * if it wants to continue using it later. + * + * The basic use pattern of an iterator is as follows: + * |[ + * GstIterator *it = _get_iterator(object); + * GValue item = G_VALUE_INIT; + * done = FALSE; + * while (!done) { + * switch (gst_iterator_next (it, &item)) { + * case GST_ITERATOR_OK: + * ...get/use/change item here... + * g_value_reset (&item); + * break; + * case GST_ITERATOR_RESYNC: + * ...rollback changes to items... + * gst_iterator_resync (it); + * break; + * case GST_ITERATOR_ERROR: + * ...wrong parameters were given... + * done = TRUE; + * break; + * case GST_ITERATOR_DONE: + * done = TRUE; + * break; + * } + * } + * g_value_unset (&item); + * gst_iterator_free (it); + * ]| + */ + +#include "gst_private.h" +#include + +/** + * gst_iterator_copy: + * @it: a #GstIterator + * + * Copy the iterator and its state. + * + * Returns: a new copy of @it. + */ +GstIterator * +gst_iterator_copy (const GstIterator * it) +{ + GstIterator *copy; + + copy = g_slice_copy (it->size, it); + if (it->copy) + it->copy (it, copy); + + return copy; +} + +G_DEFINE_BOXED_TYPE (GstIterator, gst_iterator, + (GBoxedCopyFunc) gst_iterator_copy, (GBoxedFreeFunc) gst_iterator_free); + +static void +gst_iterator_init (GstIterator * it, + guint size, + GType type, + GMutex * lock, + guint32 * master_cookie, + GstIteratorCopyFunction copy, + GstIteratorNextFunction next, + GstIteratorItemFunction item, + GstIteratorResyncFunction resync, GstIteratorFreeFunction free) +{ + it->size = size; + it->type = type; + it->lock = lock; + it->master_cookie = master_cookie; + it->cookie = *master_cookie; + it->copy = copy; + it->next = next; + it->item = item; + it->resync = resync; + it->free = free; + it->pushed = NULL; +} + +/** + * gst_iterator_new: (skip) + * @size: the size of the iterator structure + * @type: #GType of children + * @lock: pointer to a #GMutex. + * @master_cookie: pointer to a guint32 that is changed when the items in the + * iterator changed. + * @copy: copy function + * @next: function to get next item + * @item: function to call on each item retrieved + * @resync: function to resync the iterator + * @free: function to free the iterator + * + * Create a new iterator. This function is mainly used for objects + * implementing the next/resync/free function to iterate a data structure. + * + * For each item retrieved, the @item function is called with the lock + * held. The @free function is called when the iterator is freed. + * + * Returns: the new #GstIterator. + * + * MT safe. + */ +GstIterator * +gst_iterator_new (guint size, + GType type, + GMutex * lock, + guint32 * master_cookie, + GstIteratorCopyFunction copy, + GstIteratorNextFunction next, + GstIteratorItemFunction item, + GstIteratorResyncFunction resync, GstIteratorFreeFunction free) +{ + GstIterator *result; + + g_return_val_if_fail (size >= sizeof (GstIterator), NULL); + g_return_val_if_fail (g_type_qname (type) != 0, NULL); + g_return_val_if_fail (master_cookie != NULL, NULL); + g_return_val_if_fail (next != NULL, NULL); + g_return_val_if_fail (resync != NULL, NULL); + g_return_val_if_fail (free != NULL, NULL); + + result = g_slice_alloc0 (size); + gst_iterator_init (result, size, type, lock, master_cookie, copy, next, item, + resync, free); + + return result; +} + +/* + * list iterator + */ +typedef struct _GstListIterator +{ + GstIterator iterator; + GObject *owner; + GList **orig; + GList *list; /* pointer in list */ + + void (*set_value) (GValue * value, gpointer item); +} GstListIterator; + +static void +gst_list_iterator_copy (const GstListIterator * it, GstListIterator * copy) +{ + if (copy->owner) + g_object_ref (copy->owner); +} + +static GstIteratorResult +gst_list_iterator_next (GstListIterator * it, GValue * elem) +{ + gpointer data; + + if (it->list == NULL) + return GST_ITERATOR_DONE; + + data = it->list->data; + it->list = g_list_next (it->list); + + it->set_value (elem, data); + + return GST_ITERATOR_OK; +} + +static void +gst_list_iterator_resync (GstListIterator * it) +{ + it->list = *it->orig; +} + +static void +gst_list_iterator_free (GstListIterator * it) +{ + if (it->owner) + g_object_unref (it->owner); +} + +/** + * gst_iterator_new_list: (skip) + * @type: #GType of elements + * @lock: pointer to a #GMutex protecting the list. + * @master_cookie: pointer to a guint32 that is incremented when the list + * is changed. + * @list: pointer to the list + * @owner: object owning the list + * @item: function to call on each item retrieved + * + * Create a new iterator designed for iterating @list. + * + * The list you iterate is usually part of a data structure @owner and is + * protected with @lock. + * + * The iterator will use @lock to retrieve the next item of the list and it + * will then call the @item function before releasing @lock again. + * + * When a concurrent update to the list is performed, usually by @owner while + * holding @lock, @master_cookie will be updated. The iterator implementation + * will notice the update of the cookie and will return %GST_ITERATOR_RESYNC to + * the user of the iterator in the next call to gst_iterator_next(). + * + * Returns: the new #GstIterator for @list. + * + * MT safe. + */ +GstIterator * +gst_iterator_new_list (GType type, + GMutex * lock, guint32 * master_cookie, GList ** list, GObject * owner, + GstIteratorItemFunction item) +{ + GstListIterator *result; + gpointer set_value; + + if (g_type_is_a (type, G_TYPE_OBJECT)) { + set_value = g_value_set_object; + } else if (g_type_is_a (type, G_TYPE_BOXED)) { + set_value = g_value_set_boxed; + } else if (g_type_is_a (type, G_TYPE_POINTER)) { + set_value = g_value_set_pointer; + } else if (g_type_is_a (type, G_TYPE_STRING)) { + set_value = g_value_set_string; + } else { + g_critical ("List iterators can only be created for lists containing " + "instances of GObject, boxed types, pointer types and strings"); + return NULL; + } + + /* no need to lock, nothing can change here */ + result = (GstListIterator *) gst_iterator_new (sizeof (GstListIterator), + type, + lock, + master_cookie, + (GstIteratorCopyFunction) gst_list_iterator_copy, + (GstIteratorNextFunction) gst_list_iterator_next, + (GstIteratorItemFunction) item, + (GstIteratorResyncFunction) gst_list_iterator_resync, + (GstIteratorFreeFunction) gst_list_iterator_free); + + result->owner = owner ? g_object_ref (owner) : NULL; + result->orig = list; + result->list = *list; + result->set_value = set_value; + + return GST_ITERATOR (result); +} + +static void +gst_iterator_pop (GstIterator * it) +{ + if (it->pushed) { + gst_iterator_free (it->pushed); + it->pushed = NULL; + } +} + +/** + * gst_iterator_next: + * @it: The #GstIterator to iterate + * @elem: (out caller-allocates): pointer to hold next element + * + * Get the next item from the iterator in @elem. + * + * Only when this function returns %GST_ITERATOR_OK, @elem will contain a valid + * value. @elem must have been initialized to the type of the iterator or + * initialized to zeroes with g_value_unset(). The caller is responsible for + * unsetting or resetting @elem with g_value_unset() or g_value_reset() + * after usage. + * + * When this function returns %GST_ITERATOR_DONE, no more elements can be + * retrieved from @it. + * + * A return value of %GST_ITERATOR_RESYNC indicates that the element list was + * concurrently updated. The user of @it should call gst_iterator_resync() to + * get the newly updated list. + * + * A return value of %GST_ITERATOR_ERROR indicates an unrecoverable fatal error. + * + * Returns: The result of the iteration. Unset @elem after usage. + * + * MT safe. + */ +GstIteratorResult +gst_iterator_next (GstIterator * it, GValue * elem) +{ + GstIteratorResult result; + + g_return_val_if_fail (it != NULL, GST_ITERATOR_ERROR); + g_return_val_if_fail (elem != NULL, GST_ITERATOR_ERROR); + g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID + || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR); + + if (G_VALUE_TYPE (elem) == G_TYPE_INVALID) + g_value_init (elem, it->type); + +restart: + if (it->pushed) { + result = gst_iterator_next (it->pushed, elem); + if (result == GST_ITERATOR_DONE) { + /* we are done with this iterator, pop it and + * fallthrough iterating the main iterator again. */ + gst_iterator_pop (it); + } else { + return result; + } + } + + if (G_LIKELY (it->lock)) + g_mutex_lock (it->lock); + + if (G_UNLIKELY (*it->master_cookie != it->cookie)) { + result = GST_ITERATOR_RESYNC; + goto done; + } + + result = it->next (it, elem); + if (result == GST_ITERATOR_OK && it->item) { + GstIteratorItem itemres; + + itemres = it->item (it, elem); + switch (itemres) { + case GST_ITERATOR_ITEM_SKIP: + if (G_LIKELY (it->lock)) + g_mutex_unlock (it->lock); + g_value_reset (elem); + goto restart; + case GST_ITERATOR_ITEM_END: + result = GST_ITERATOR_DONE; + g_value_reset (elem); + break; + case GST_ITERATOR_ITEM_PASS: + break; + } + } + +done: + if (G_LIKELY (it->lock)) + g_mutex_unlock (it->lock); + + return result; +} + +/** + * gst_iterator_resync: + * @it: The #GstIterator to resync + * + * Resync the iterator. this function is mostly called + * after gst_iterator_next() returned %GST_ITERATOR_RESYNC. + * + * When an iterator was pushed on @it, it will automatically be popped again + * with this function. + * + * MT safe. + */ +void +gst_iterator_resync (GstIterator * it) +{ + g_return_if_fail (it != NULL); + + gst_iterator_pop (it); + + if (G_LIKELY (it->lock)) + g_mutex_lock (it->lock); + it->resync (it); + it->cookie = *it->master_cookie; + if (G_LIKELY (it->lock)) + g_mutex_unlock (it->lock); +} + +/** + * gst_iterator_free: + * @it: The #GstIterator to free + * + * Free the iterator. + * + * MT safe. + */ +void +gst_iterator_free (GstIterator * it) +{ + g_return_if_fail (it != NULL); + + gst_iterator_pop (it); + + it->free (it); + + g_slice_free1 (it->size, it); +} + +/** + * gst_iterator_push: + * @it: The #GstIterator to use + * @other: The #GstIterator to push + * + * Pushes @other iterator onto @it. All calls performed on @it are + * forwarded to @other. If @other returns %GST_ITERATOR_DONE, it is + * popped again and calls are handled by @it again. + * + * This function is mainly used by objects implementing the iterator + * next function to recurse into substructures. + * + * When gst_iterator_resync() is called on @it, @other will automatically be + * popped. + * + * MT safe. + */ +void +gst_iterator_push (GstIterator * it, GstIterator * other) +{ + g_return_if_fail (it != NULL); + g_return_if_fail (other != NULL); + + it->pushed = other; +} + +typedef struct _GstIteratorFilter +{ + GstIterator iterator; + GstIterator *slave; + + GMutex *master_lock; + GCompareFunc func; + GValue user_data; + gboolean have_user_data; +} GstIteratorFilter; + +static GstIteratorResult +filter_next (GstIteratorFilter * it, GValue * elem) +{ + GstIteratorResult result = GST_ITERATOR_ERROR; + gboolean done = FALSE; + GValue item = { 0, }; + + while (G_LIKELY (!done)) { + result = gst_iterator_next (it->slave, &item); + switch (result) { + case GST_ITERATOR_OK: + if (G_LIKELY (it->master_lock)) + g_mutex_unlock (it->master_lock); + if (it->func (&item, &it->user_data) == 0) { + g_value_copy (&item, elem); + done = TRUE; + } + g_value_reset (&item); + if (G_LIKELY (it->master_lock)) + g_mutex_lock (it->master_lock); + break; + case GST_ITERATOR_RESYNC: + case GST_ITERATOR_DONE: + done = TRUE; + break; + default: + g_assert_not_reached (); + break; + } + } + g_value_unset (&item); + return result; +} + +static void +filter_copy (const GstIteratorFilter * it, GstIteratorFilter * copy) +{ + copy->slave = gst_iterator_copy (it->slave); + copy->master_lock = copy->slave->lock ? copy->slave->lock : it->master_lock; + copy->slave->lock = NULL; + + if (it->have_user_data) { + memset (©->user_data, 0, sizeof (copy->user_data)); + g_value_init (©->user_data, G_VALUE_TYPE (&it->user_data)); + g_value_copy (&it->user_data, ©->user_data); + } +} + +static void +filter_resync (GstIteratorFilter * it) +{ + gst_iterator_resync (it->slave); +} + +static void +filter_free (GstIteratorFilter * it) +{ + if (it->have_user_data) + g_value_unset (&it->user_data); + gst_iterator_free (it->slave); +} + +/** + * gst_iterator_filter: + * @it: The #GstIterator to filter + * @func: (scope call): the compare function to select elements + * @user_data: (closure): user data passed to the compare function + * + * Create a new iterator from an existing iterator. The new iterator + * will only return those elements that match the given compare function @func. + * The first parameter that is passed to @func is the #GValue of the current + * iterator element and the second parameter is @user_data. @func should + * return 0 for elements that should be included in the filtered iterator. + * + * When this iterator is freed, @it will also be freed. + * + * Returns: (transfer full): a new #GstIterator. + * + * MT safe. + */ +GstIterator * +gst_iterator_filter (GstIterator * it, GCompareFunc func, + const GValue * user_data) +{ + GstIteratorFilter *result; + + g_return_val_if_fail (it != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + result = (GstIteratorFilter *) gst_iterator_new (sizeof (GstIteratorFilter), + it->type, it->lock, it->master_cookie, + (GstIteratorCopyFunction) filter_copy, + (GstIteratorNextFunction) filter_next, + (GstIteratorItemFunction) NULL, + (GstIteratorResyncFunction) filter_resync, + (GstIteratorFreeFunction) filter_free); + + result->master_lock = it->lock; + it->lock = NULL; + result->func = func; + if (user_data) { + g_value_init (&result->user_data, G_VALUE_TYPE (user_data)); + g_value_copy (user_data, &result->user_data); + result->have_user_data = TRUE; + } else { + result->have_user_data = FALSE; + } + result->slave = it; + + return GST_ITERATOR (result); +} + +/** + * gst_iterator_fold: + * @it: The #GstIterator to fold over + * @func: (scope call): the fold function + * @ret: the seed value passed to the fold function + * @user_data: (closure): user data passed to the fold function + * + * Folds @func over the elements of @iter. That is to say, @func will be called + * as @func (object, @ret, @user_data) for each object in @it. The normal use + * of this procedure is to accumulate the results of operating on the objects in + * @ret. + * + * This procedure can be used (and is used internally) to implement the + * gst_iterator_foreach() and gst_iterator_find_custom() operations. + * + * The fold will proceed as long as @func returns %TRUE. When the iterator has no + * more arguments, %GST_ITERATOR_DONE will be returned. If @func returns %FALSE, + * the fold will stop, and %GST_ITERATOR_OK will be returned. Errors or resyncs + * will cause fold to return %GST_ITERATOR_ERROR or %GST_ITERATOR_RESYNC as + * appropriate. + * + * The iterator will not be freed. + * + * Returns: A #GstIteratorResult, as described above. + * + * MT safe. + */ +GstIteratorResult +gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func, + GValue * ret, gpointer user_data) +{ + GValue item = { 0, }; + GstIteratorResult result; + + g_return_val_if_fail (it != NULL, GST_ITERATOR_ERROR); + + while (1) { + result = gst_iterator_next (it, &item); + switch (result) { + case GST_ITERATOR_OK: + if (!func (&item, ret, user_data)) + goto fold_done; + + g_value_reset (&item); + break; + case GST_ITERATOR_RESYNC: + case GST_ITERATOR_ERROR: + goto fold_done; + case GST_ITERATOR_DONE: + goto fold_done; + } + } + +fold_done: + +#if GLIB_CHECK_VERSION (2, 48, 0) + g_value_unset (&item); +#else + if (item.g_type != 0) + g_value_unset (&item); +#endif + + return result; +} + +typedef struct +{ + GstIteratorForeachFunction func; + gpointer user_data; +} ForeachFoldData; + +static gboolean +foreach_fold_func (const GValue * item, GValue * unused, ForeachFoldData * data) +{ + data->func (item, data->user_data); + return TRUE; +} + +/** + * gst_iterator_foreach: + * @it: The #GstIterator to iterate + * @func: (scope call): the function to call for each element. + * @user_data: (closure): user data passed to the function + * + * Iterate over all element of @it and call the given function @func for + * each element. + * + * Returns: the result call to gst_iterator_fold(). The iterator will not be + * freed. + * + * MT safe. + */ +GstIteratorResult +gst_iterator_foreach (GstIterator * it, GstIteratorForeachFunction func, + gpointer user_data) +{ + ForeachFoldData data; + + data.func = func; + data.user_data = user_data; + + return gst_iterator_fold (it, (GstIteratorFoldFunction) foreach_fold_func, + NULL, &data); +} + +typedef struct +{ + GCompareFunc func; + gpointer user_data; + gboolean found; +} FindCustomFoldData; + +static gboolean +find_custom_fold_func (const GValue * item, GValue * ret, + FindCustomFoldData * data) +{ + if (data->func (item, data->user_data) == 0) { + data->found = TRUE; + g_value_copy (item, ret); + return FALSE; + } else { + return TRUE; + } +} + +/** + * gst_iterator_find_custom: + * @it: The #GstIterator to iterate + * @func: (scope call): the compare function to use + * @elem: (out): pointer to a #GValue where to store the result + * @user_data: (closure): user data passed to the compare function + * + * Find the first element in @it that matches the compare function @func. + * @func should return 0 when the element is found. The first parameter + * to @func will be the current element of the iterator and the + * second parameter will be @user_data. + * The result will be stored in @elem if a result is found. + * + * The iterator will not be freed. + * + * This function will return %FALSE if an error happened to the iterator + * or if the element wasn't found. + * + * Returns: Returns %TRUE if the element was found, else %FALSE. + * + * MT safe. + */ +gboolean +gst_iterator_find_custom (GstIterator * it, GCompareFunc func, + GValue * elem, gpointer user_data) +{ + GstIteratorResult res; + FindCustomFoldData data; + + g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID + || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR); + + if (G_VALUE_TYPE (elem) == G_TYPE_INVALID) + g_value_init (elem, it->type); + + data.func = func; + data.user_data = user_data; + data.found = FALSE; + + do { + res = + gst_iterator_fold (it, (GstIteratorFoldFunction) find_custom_fold_func, + elem, &data); + if (res == GST_ITERATOR_RESYNC) + gst_iterator_resync (it); + } while (res == GST_ITERATOR_RESYNC); + + if (!data.found) + g_value_unset (elem); + + return data.found; +} + +typedef struct +{ + GstIterator parent; + GValue object; + gboolean visited; + gboolean empty; +} GstSingleObjectIterator; + +static guint32 _single_object_dummy_cookie = 0; + +static void +gst_single_object_iterator_copy (const GstSingleObjectIterator * it, + GstSingleObjectIterator * copy) +{ + if (!it->empty) { + memset (©->object, 0, sizeof (copy->object)); + g_value_init (©->object, it->parent.type); + g_value_copy (&it->object, ©->object); + } +} + +static GstIteratorResult +gst_single_object_iterator_next (GstSingleObjectIterator * it, GValue * result) +{ + if (it->visited || it->empty) + return GST_ITERATOR_DONE; + + g_value_copy (&it->object, result); + it->visited = TRUE; + + return GST_ITERATOR_OK; +} + +static void +gst_single_object_iterator_resync (GstSingleObjectIterator * it) +{ + it->visited = FALSE; +} + +static void +gst_single_object_iterator_free (GstSingleObjectIterator * it) +{ + if (!it->empty) + g_value_unset (&it->object); +} + +/** + * gst_iterator_new_single: + * @type: #GType of the passed object + * @object: object that this iterator should return + * + * This #GstIterator is a convenient iterator for the common + * case where a #GstIterator needs to be returned but only + * a single object has to be considered. This happens often + * for the #GstPadIterIntLinkFunction. + * + * Returns: the new #GstIterator for @object. + */ +GstIterator * +gst_iterator_new_single (GType type, const GValue * object) +{ + GstSingleObjectIterator *result; + + result = (GstSingleObjectIterator *) + gst_iterator_new (sizeof (GstSingleObjectIterator), + type, NULL, &_single_object_dummy_cookie, + (GstIteratorCopyFunction) gst_single_object_iterator_copy, + (GstIteratorNextFunction) gst_single_object_iterator_next, + (GstIteratorItemFunction) NULL, + (GstIteratorResyncFunction) gst_single_object_iterator_resync, + (GstIteratorFreeFunction) gst_single_object_iterator_free); + + if (object) { + g_value_init (&result->object, type); + g_value_copy (object, &result->object); + result->empty = FALSE; + } else { + result->empty = TRUE; + } + result->visited = FALSE; + + return GST_ITERATOR (result); +} diff --git a/gst/gstiterator.h b/gst/gstiterator.h new file mode 100644 index 0000000..2f53507 --- /dev/null +++ b/gst/gstiterator.h @@ -0,0 +1,292 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge + * + * gstiterator.h: Header for GstIterator + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_ITERATOR_H__ +#define __GST_ITERATOR_H__ + +#include /* for GValue in the fold */ +#include + +G_BEGIN_DECLS + +#define GST_TYPE_ITERATOR (gst_iterator_get_type ()) + +/** + * GstIteratorResult: + * @GST_ITERATOR_DONE: No more items in the iterator + * @GST_ITERATOR_OK: An item was retrieved + * @GST_ITERATOR_RESYNC: Datastructure changed while iterating + * @GST_ITERATOR_ERROR: An error happened + * + * The result of gst_iterator_next(). + */ +typedef enum { + GST_ITERATOR_DONE = 0, + GST_ITERATOR_OK = 1, + GST_ITERATOR_RESYNC = 2, + GST_ITERATOR_ERROR = 3 +} GstIteratorResult; + +typedef struct _GstIterator GstIterator; + +/** + * GstIteratorItem: + * @GST_ITERATOR_ITEM_SKIP: Skip this item + * @GST_ITERATOR_ITEM_PASS: Return item + * @GST_ITERATOR_ITEM_END: Stop after this item. + * + * The result of a #GstIteratorItemFunction. + */ +typedef enum { + GST_ITERATOR_ITEM_SKIP = 0, + GST_ITERATOR_ITEM_PASS = 1, + GST_ITERATOR_ITEM_END = 2 +} GstIteratorItem; + +/** + * GstIteratorCopyFunction: + * @it: The original iterator + * @copy: The copied iterator + * + * This function will be called when creating a copy of @it and should + * create a copy of all custom iterator fields or increase their + * reference counts. + */ +typedef void (*GstIteratorCopyFunction) (const GstIterator *it, GstIterator *copy); + +/** + * GstIteratorItemFunction: + * @it: the iterator + * @item: the item being retrieved. + * + * The function that will be called after the next item of the iterator + * has been retrieved. This function can be used to skip items or stop + * the iterator. + * + * The function will be called with the iterator lock held. + * + * Returns: the result of the operation. + */ +typedef GstIteratorItem (*GstIteratorItemFunction) (GstIterator *it, const GValue * item); + +/** + * GstIteratorNextFunction: + * @it: the iterator + * @result: a pointer to hold the next item + * + * The function that will be called when the next element of the iterator + * should be retrieved. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + * + * Returns: the result of the operation. + */ +typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, GValue *result); +/** + * GstIteratorResyncFunction: + * @it: the iterator + * + * This function will be called whenever a concurrent update happened + * to the iterated datastructure. The implementor of the iterator should + * restart the iterator from the beginning and clean up any state it might + * have. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + */ +typedef void (*GstIteratorResyncFunction) (GstIterator *it); +/** + * GstIteratorFreeFunction: + * @it: the iterator + * + * This function will be called when the iterator is freed. + * + * Implementors of a #GstIterator should implement this + * function and pass it to the constructor of the custom iterator. + * The function will be called with the iterator lock held. + */ +typedef void (*GstIteratorFreeFunction) (GstIterator *it); + +/** + * GstIteratorForeachFunction: + * @item: The item + * @user_data: User data + * + * A function that is called by gst_iterator_foreach() for every element. + */ +typedef void (*GstIteratorForeachFunction) (const GValue * item, gpointer user_data); + +/** + * GstIteratorFoldFunction: + * @item: the item to fold + * @ret: a #GValue collecting the result + * @user_data: data passed to gst_iterator_fold() + * + * A function to be passed to gst_iterator_fold(). + * + * Returns: %TRUE if the fold should continue, %FALSE if it should stop. + */ +typedef gboolean (*GstIteratorFoldFunction) (const GValue * item, GValue * ret, gpointer user_data); + +/** + * GST_ITERATOR: + * @it: the #GstIterator value + * + * Macro to cast to a #GstIterator + */ +#define GST_ITERATOR(it) ((GstIterator*)(it)) +/** + * GST_ITERATOR_LOCK: + * @it: the #GstIterator to get the lock of + * + * Macro to get the lock protecting the datastructure being iterated. + */ +#define GST_ITERATOR_LOCK(it) (GST_ITERATOR(it)->lock) +/** + * GST_ITERATOR_COOKIE: + * @it: the #GstIterator to get the cookie of + * + * Macro to get the cookie of a #GstIterator. The cookie of the + * iterator is the value of the master cookie when the iterator + * was created. + * Whenever the iterator is iterated, the value is compared to the + * value of the master cookie. If they are different, a concurrent + * modification happened to the iterator and a resync is needed. + */ +#define GST_ITERATOR_COOKIE(it) (GST_ITERATOR(it)->cookie) +/** + * GST_ITERATOR_ORIG_COOKIE: + * @it: the #GstIterator to get the master cookie of + * + * Macro to get a pointer to where the master cookie is stored. The + * master cookie protects the structure being iterated and gets updated + * whenever the datastructure changes. + */ +#define GST_ITERATOR_ORIG_COOKIE(it) (GST_ITERATOR(it)->master_cookie) + +/** + * GstIterator: + * @copy: The function to copy the iterator + * @next: The function to get the next item in the iterator + * @item: The function to be called for each item retrieved + * @resync: The function to call when a resync is needed. + * @free: The function to call when the iterator is freed + * @pushed: The iterator that is currently pushed with gst_iterator_push() + * @type: The type of the object that this iterator will return + * @lock: The lock protecting the data structure and the cookie. + * @cookie: The cookie; the value of the master_cookie when this iterator was + * created. + * @master_cookie: A pointer to the master cookie. + * @size: the size of the iterator + * + * #GstIterator base structure. The values of this structure are + * protected for subclasses, use the methods to use the #GstIterator. + */ +struct _GstIterator { + /*< protected >*/ + GstIteratorCopyFunction copy; + GstIteratorNextFunction next; + GstIteratorItemFunction item; + GstIteratorResyncFunction resync; + GstIteratorFreeFunction free; + + GstIterator *pushed; /* pushed iterator */ + + GType type; + GMutex *lock; + guint32 cookie; /* cookie of the iterator */ + guint32 *master_cookie; /* pointer to guint32 holding the cookie when this + iterator was created */ + guint size; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_iterator_get_type (void); + +/* creating iterators */ + +GST_API +GstIterator* gst_iterator_new (guint size, + GType type, + GMutex *lock, + guint32 *master_cookie, + GstIteratorCopyFunction copy, + GstIteratorNextFunction next, + GstIteratorItemFunction item, + GstIteratorResyncFunction resync, + GstIteratorFreeFunction free) G_GNUC_MALLOC; +GST_API +GstIterator* gst_iterator_new_list (GType type, + GMutex *lock, + guint32 *master_cookie, + GList **list, + GObject * owner, + GstIteratorItemFunction item) G_GNUC_MALLOC; +GST_API +GstIterator* gst_iterator_new_single (GType type, + const GValue * object) G_GNUC_MALLOC; +GST_API +GstIterator* gst_iterator_copy (const GstIterator *it) G_GNUC_MALLOC; + +/* using iterators */ + +GST_API +GstIteratorResult gst_iterator_next (GstIterator *it, GValue * elem); + +GST_API +void gst_iterator_resync (GstIterator *it); + +GST_API +void gst_iterator_free (GstIterator *it); + +GST_API +void gst_iterator_push (GstIterator *it, GstIterator *other); + +/* higher-order functions that operate on iterators */ + +GST_API +GstIterator* gst_iterator_filter (GstIterator *it, GCompareFunc func, + const GValue * user_data) G_GNUC_MALLOC; +GST_API +GstIteratorResult gst_iterator_fold (GstIterator *it, + GstIteratorFoldFunction func, + GValue *ret, gpointer user_data); +GST_API +GstIteratorResult gst_iterator_foreach (GstIterator *it, + GstIteratorForeachFunction func, gpointer user_data); +GST_API +gboolean gst_iterator_find_custom (GstIterator *it, GCompareFunc func, + GValue *elem, gpointer user_data); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstIterator, gst_iterator_free) +#endif + +G_END_DECLS + +#endif /* __GST_ITERATOR_H__ */ diff --git a/gst/gstmacros.h b/gst/gstmacros.h new file mode 100644 index 0000000..53cf6cf --- /dev/null +++ b/gst/gstmacros.h @@ -0,0 +1,56 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __GST_MACROS_H__ +#define __GST_MACROS_H__ + +#include + +G_BEGIN_DECLS + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +# define GST_GNUC_CONSTRUCTOR \ + __attribute__ ((constructor)) +#else /* !__GNUC__ */ +# define GST_GNUC_CONSTRUCTOR +#endif /* !__GNUC__ */ + +#if defined (__GNUC__) && !defined (GST_IMPLEMENT_INLINES) +# define GST_INLINE_FUNC extern __inline__ +# define GST_CAN_INLINE 1 +#elif defined(_MSC_VER) +# define GST_INLINE_FUNC extern __inline +# define GST_CAN_INLINE 1 +#else +# define GST_INLINE_FUNC extern +# undef GST_CAN_INLINE +#endif + +#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(restrict) +# if defined(__GNUC__) && __GNUC__ >= 4 +# define restrict __restrict__ +# else +# define restrict +# endif +#endif + +G_END_DECLS + +#endif /* __GST_MACROS_H__ */ + + diff --git a/gst/gstmemory.c b/gst/gstmemory.c new file mode 100644 index 0000000..ebdd45e --- /dev/null +++ b/gst/gstmemory.c @@ -0,0 +1,465 @@ +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstmemory.c: memory block 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstmemory + * @title: GstMemory + * @short_description: refcounted wrapper for memory blocks + * @see_also: #GstBuffer + * + * GstMemory is a lightweight refcounted object that wraps a region of memory. + * They are typically used to manage the data of a #GstBuffer. + * + * A GstMemory object has an allocated region of memory of maxsize. The maximum + * size does not change during the lifetime of the memory object. The memory + * also has an offset and size property that specifies the valid range of memory + * in the allocated region. + * + * Memory is usually created by allocators with a gst_allocator_alloc() + * method call. When %NULL is used as the allocator, the default allocator will + * be used. + * + * New allocators can be registered with gst_allocator_register(). + * Allocators are identified by name and can be retrieved with + * gst_allocator_find(). gst_allocator_set_default() can be used to change the + * default allocator. + * + * New memory can be created with gst_memory_new_wrapped() that wraps the memory + * allocated elsewhere. + * + * Refcounting of the memory block is performed with gst_memory_ref() and + * gst_memory_unref(). + * + * The size of the memory can be retrieved and changed with + * gst_memory_get_sizes() and gst_memory_resize() respectively. + * + * Getting access to the data of the memory is performed with gst_memory_map(). + * The call will return a pointer to offset bytes into the region of memory. + * After the memory access is completed, gst_memory_unmap() should be called. + * + * Memory can be copied with gst_memory_copy(), which will return a writable + * copy. gst_memory_share() will create a new memory block that shares the + * memory with an existing memory block at a custom offset and with a custom + * size. + * + * Memory can be efficiently merged when gst_memory_is_span() returns %TRUE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "gstmemory.h" + +GType _gst_memory_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstMemory, gst_memory); + +static GstMemory * +_gst_memory_copy (GstMemory * mem) +{ + GST_CAT_DEBUG (GST_CAT_MEMORY, "copy memory %p", mem); + return gst_memory_copy (mem, 0, -1); +} + +static void +_gst_memory_free (GstMemory * mem) +{ + GstAllocator *allocator; + + GST_CAT_DEBUG (GST_CAT_MEMORY, "free memory %p", mem); + + if (mem->parent) { + gst_memory_unlock (mem->parent, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unref (mem->parent); + } + + allocator = mem->allocator; + + gst_allocator_free (allocator, mem); + gst_object_unref (allocator); +} + +/** + * gst_memory_init: (skip) + * @mem: a #GstMemory + * @flags: #GstMemoryFlags + * @allocator: the #GstAllocator + * @parent: the parent of @mem + * @maxsize: the total size of the memory + * @align: the alignment of the memory + * @offset: The offset in the memory + * @size: the size of valid data in the memory + + * Initializes a newly allocated @mem with the given parameters. This function + * will call gst_mini_object_init() with the default memory parameters. + */ +void +gst_memory_init (GstMemory * mem, GstMemoryFlags flags, + GstAllocator * allocator, GstMemory * parent, gsize maxsize, gsize align, + gsize offset, gsize size) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (mem), + flags | GST_MINI_OBJECT_FLAG_LOCKABLE, GST_TYPE_MEMORY, + (GstMiniObjectCopyFunction) _gst_memory_copy, NULL, + (GstMiniObjectFreeFunction) _gst_memory_free); + + mem->allocator = gst_object_ref (allocator); + if (parent) { + /* FIXME 2.0: this can fail if the memory is already write locked */ + gst_memory_lock (parent, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_ref (parent); + } + mem->parent = parent; + mem->maxsize = maxsize; + mem->align = align; + mem->offset = offset; + mem->size = size; + + GST_CAT_DEBUG (GST_CAT_MEMORY, "new memory %p, maxsize:%" G_GSIZE_FORMAT + " offset:%" G_GSIZE_FORMAT " size:%" G_GSIZE_FORMAT, mem, maxsize, + offset, size); +} + +/** + * gst_memory_is_type: + * @mem: a #GstMemory + * @mem_type: a memory type + * + * Check if @mem if allocated with an allocator for @mem_type. + * + * Returns: %TRUE if @mem was allocated from an allocator for @mem_type. + * + * Since: 1.2 + */ +gboolean +gst_memory_is_type (GstMemory * mem, const gchar * mem_type) +{ + g_return_val_if_fail (mem != NULL, FALSE); + g_return_val_if_fail (mem->allocator != NULL, FALSE); + g_return_val_if_fail (mem_type != NULL, FALSE); + + return (g_strcmp0 (mem->allocator->mem_type, mem_type) == 0); +} + +/** + * gst_memory_get_sizes: + * @mem: a #GstMemory + * @offset: (out) (allow-none): pointer to offset + * @maxsize: (out) (allow-none): pointer to maxsize + * + * Get the current @size, @offset and @maxsize of @mem. + * + * Returns: the current sizes of @mem + */ +gsize +gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize) +{ + g_return_val_if_fail (mem != NULL, 0); + + if (offset) + *offset = mem->offset; + if (maxsize) + *maxsize = mem->maxsize; + + return mem->size; +} + +/** + * gst_memory_resize: + * @mem: a #GstMemory + * @offset: a new offset + * @size: a new size + * + * Resize the memory region. @mem should be writable and offset + size should be + * less than the maxsize of @mem. + * + * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED will be + * cleared when offset or padding is increased respectively. + */ +void +gst_memory_resize (GstMemory * mem, gssize offset, gsize size) +{ + g_return_if_fail (mem != NULL); + g_return_if_fail (gst_memory_is_writable (mem)); + g_return_if_fail (offset >= 0 || mem->offset >= -offset); + g_return_if_fail (size + mem->offset + offset <= mem->maxsize); + + /* if we increase the prefix, we can't guarantee it is still 0 filled */ + if ((offset > 0) && GST_MEMORY_IS_ZERO_PREFIXED (mem)) + GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PREFIXED); + + /* if we increase the padding, we can't guarantee it is still 0 filled */ + if ((offset + size < mem->size) && GST_MEMORY_IS_ZERO_PADDED (mem)) + GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PADDED); + + mem->offset += offset; + mem->size = size; +} + +/** + * gst_memory_make_mapped: + * @mem: (transfer full): a #GstMemory + * @info: (out): pointer for info + * @flags: mapping flags + * + * Create a #GstMemory object that is mapped with @flags. If @mem is mappable + * with @flags, this function returns the mapped @mem directly. Otherwise a + * mapped copy of @mem is returned. + * + * This function takes ownership of old @mem and returns a reference to a new + * #GstMemory. + * + * Returns: (transfer full) (nullable): a #GstMemory object mapped + * with @flags or %NULL when a mapping is not possible. + */ +GstMemory * +gst_memory_make_mapped (GstMemory * mem, GstMapInfo * info, GstMapFlags flags) +{ + GstMemory *result; + + if (gst_memory_map (mem, info, flags)) { + result = mem; + } else { + result = gst_memory_copy (mem, 0, -1); + gst_memory_unref (mem); + + if (result == NULL) + goto cannot_copy; + + if (!gst_memory_map (result, info, flags)) + goto cannot_map; + } + return result; + + /* ERRORS */ +cannot_copy: + { + GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot copy memory %p", mem); + return NULL; + } +cannot_map: + { + GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot map memory %p with flags %d", mem, + flags); + gst_memory_unref (result); + return NULL; + } +} + +/** + * gst_memory_map: + * @mem: a #GstMemory + * @info: (out): pointer for info + * @flags: mapping flags + * + * Fill @info with the pointer and sizes of the memory in @mem that can be + * accessed according to @flags. + * + * This function can return %FALSE for various reasons: + * - the memory backed by @mem is not accessible with the given @flags. + * - the memory was already mapped with a different mapping. + * + * @info and its contents remain valid for as long as @mem is valid and + * until gst_memory_unmap() is called. + * + * For each gst_memory_map() call, a corresponding gst_memory_unmap() call + * should be done. + * + * Returns: %TRUE if the map operation was successful. + */ +gboolean +gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags) +{ + g_return_val_if_fail (mem != NULL, FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + if (!gst_memory_lock (mem, (GstLockFlags) flags)) + goto lock_failed; + + info->flags = flags; + info->memory = mem; + info->size = mem->size; + info->maxsize = mem->maxsize - mem->offset; + + if (mem->allocator->mem_map_full) + info->data = mem->allocator->mem_map_full (mem, info, mem->maxsize); + else + info->data = mem->allocator->mem_map (mem, mem->maxsize, flags); + + if (G_UNLIKELY (info->data == NULL)) + goto error; + + info->data = info->data + mem->offset; + + return TRUE; + + /* ERRORS */ +lock_failed: + { + GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags); + memset (info, 0, sizeof (GstMapInfo)); + return FALSE; + } +error: + { + /* something went wrong, restore the orginal state again + * it is up to the subclass to log an error if needed. */ + GST_CAT_INFO (GST_CAT_MEMORY, "mem %p: subclass map failed", mem); + gst_memory_unlock (mem, (GstLockFlags) flags); + memset (info, 0, sizeof (GstMapInfo)); + return FALSE; + } +} + +/** + * gst_memory_unmap: + * @mem: a #GstMemory + * @info: a #GstMapInfo + * + * Release the memory obtained with gst_memory_map() + */ +void +gst_memory_unmap (GstMemory * mem, GstMapInfo * info) +{ + g_return_if_fail (mem != NULL); + g_return_if_fail (info != NULL); + g_return_if_fail (info->memory == mem); + + if (mem->allocator->mem_unmap_full) + mem->allocator->mem_unmap_full (mem, info); + else + mem->allocator->mem_unmap (mem); + gst_memory_unlock (mem, (GstLockFlags) info->flags); +} + +/** + * gst_memory_copy: + * @mem: a #GstMemory + * @offset: offset to copy from + * @size: size to copy, or -1 to copy to the end of the memory region + * + * Return a copy of @size bytes from @mem starting from @offset. This copy is + * guaranteed to be writable. @size can be set to -1 to return a copy + * from @offset to the end of the memory region. + * + * Returns: a new #GstMemory. + */ +GstMemory * +gst_memory_copy (GstMemory * mem, gssize offset, gssize size) +{ + GstMemory *copy; + + g_return_val_if_fail (mem != NULL, NULL); + + copy = mem->allocator->mem_copy (mem, offset, size); + + return copy; +} + +/** + * gst_memory_share: + * @mem: a #GstMemory + * @offset: offset to share from + * @size: size to share, or -1 to share to the end of the memory region + * + * Return a shared copy of @size bytes from @mem starting from @offset. No + * memory copy is performed and the memory region is simply shared. The result + * is guaranteed to be non-writable. @size can be set to -1 to return a shared + * copy from @offset to the end of the memory region. + * + * Returns: a new #GstMemory. + */ +GstMemory * +gst_memory_share (GstMemory * mem, gssize offset, gssize size) +{ + GstMemory *shared; + + g_return_val_if_fail (mem != NULL, NULL); + g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE), + NULL); + + /* whether we can lock the memory exclusively */ + /* in order to maintain backwards compatibility by not requiring subclasses + * to lock the memory themselves and propagate the possible failure in their + * mem_share implementation */ + /* FIXME 2.0: remove and fix gst_memory_init() and/or all memory subclasses + * to propagate this failure case */ + if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) + return NULL; + + /* double lock to ensure we are not mapped writable without an + * exclusive lock. */ + if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) { + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + return NULL; + } + + shared = mem->allocator->mem_share (mem, offset, size); + + /* unlocking before calling the subclass would be racy */ + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + + return shared; +} + +/** + * gst_memory_is_span: + * @mem1: a #GstMemory + * @mem2: a #GstMemory + * @offset: (out): a pointer to a result offset + * + * Check if @mem1 and mem2 share the memory with a common parent memory object + * and that the memory is contiguous. + * + * If this is the case, the memory of @mem1 and @mem2 can be merged + * efficiently by performing gst_memory_share() on the parent object from + * the returned @offset. + * + * Returns: %TRUE if the memory is contiguous and of a common parent. + */ +gboolean +gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) +{ + g_return_val_if_fail (mem1 != NULL, FALSE); + g_return_val_if_fail (mem2 != NULL, FALSE); + + /* need to have the same allocators */ + if (mem1->allocator != mem2->allocator) + return FALSE; + + /* need to have the same parent */ + if (mem1->parent == NULL || mem1->parent != mem2->parent) + return FALSE; + + /* and memory is contiguous */ + if (!mem1->allocator->mem_is_span (mem1, mem2, offset)) + return FALSE; + + return TRUE; +} + +void +_priv_gst_memory_initialize (void) +{ + _gst_memory_type = gst_memory_get_type (); +} diff --git a/gst/gstmemory.h b/gst/gstmemory.h new file mode 100644 index 0000000..8244da9 --- /dev/null +++ b/gst/gstmemory.h @@ -0,0 +1,395 @@ +/* GStreamer + * Copyright (C) 2009 Wim Taymans + * + * gstmemory.h: Header for memory blocks + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_MEMORY_H__ +#define __GST_MEMORY_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_memory_type; +#define GST_TYPE_MEMORY (_gst_memory_type) + +GST_API +GType gst_memory_get_type(void); + +typedef struct _GstMemory GstMemory; +typedef struct _GstAllocator GstAllocator; + +#define GST_MEMORY_CAST(mem) ((GstMemory *)(mem)) + +/** + * GstMemoryFlags: + * @GST_MEMORY_FLAG_READONLY: memory is readonly. It is not allowed to map the + * memory with #GST_MAP_WRITE. + * @GST_MEMORY_FLAG_NO_SHARE: memory must not be shared. Copies will have to be + * made when this memory needs to be shared between buffers. + * @GST_MEMORY_FLAG_ZERO_PREFIXED: the memory prefix is filled with 0 bytes + * @GST_MEMORY_FLAG_ZERO_PADDED: the memory padding is filled with 0 bytes + * @GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS: the memory is physically contiguous. (Since 1.2) + * @GST_MEMORY_FLAG_NOT_MAPPABLE: the memory can't be mapped via gst_memory_map() without any preconditions. (Since 1.2) + * @GST_MEMORY_FLAG_LAST: first flag that can be used for custom purposes + * + * Flags for wrapped memory. + */ +typedef enum { + GST_MEMORY_FLAG_READONLY = GST_MINI_OBJECT_FLAG_LOCK_READONLY, + GST_MEMORY_FLAG_NO_SHARE = (GST_MINI_OBJECT_FLAG_LAST << 0), + GST_MEMORY_FLAG_ZERO_PREFIXED = (GST_MINI_OBJECT_FLAG_LAST << 1), + GST_MEMORY_FLAG_ZERO_PADDED = (GST_MINI_OBJECT_FLAG_LAST << 2), + GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS = (GST_MINI_OBJECT_FLAG_LAST << 3), + GST_MEMORY_FLAG_NOT_MAPPABLE = (GST_MINI_OBJECT_FLAG_LAST << 4), + + GST_MEMORY_FLAG_LAST = (GST_MINI_OBJECT_FLAG_LAST << 16) +} GstMemoryFlags; + +/** + * GST_MEMORY_FLAGS: + * @mem: a #GstMemory. + * + * A flags word containing #GstMemoryFlags flags set on @mem + */ +#define GST_MEMORY_FLAGS(mem) GST_MINI_OBJECT_FLAGS (mem) +/** + * GST_MEMORY_FLAG_IS_SET: + * @mem: a #GstMemory. + * @flag: the #GstMemoryFlags to check. + * + * Gives the status of a specific flag on a @mem. + */ +#define GST_MEMORY_FLAG_IS_SET(mem,flag) GST_MINI_OBJECT_FLAG_IS_SET (mem,flag) +/** + * GST_MEMORY_FLAG_UNSET: + * @mem: a #GstMemory. + * @flag: the #GstMemoryFlags to clear. + * + * Clear a specific flag on a @mem. + */ +#define GST_MEMORY_FLAG_UNSET(mem,flag) GST_MINI_OBJECT_FLAG_UNSET (mem, flag) + +/** + * GST_MEMORY_IS_READONLY: + * @mem: a #GstMemory. + * + * Check if @mem is readonly. + */ +#define GST_MEMORY_IS_READONLY(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_READONLY) +/** + * GST_MEMORY_IS_NO_SHARE: + * @mem: a #GstMemory. + * + * Check if @mem cannot be shared between buffers + */ +#define GST_MEMORY_IS_NO_SHARE(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_NO_SHARE) +/** + * GST_MEMORY_IS_ZERO_PREFIXED: + * @mem: a #GstMemory. + * + * Check if the prefix in @mem is 0 filled. + */ +#define GST_MEMORY_IS_ZERO_PREFIXED(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PREFIXED) +/** + * GST_MEMORY_IS_ZERO_PADDED: + * @mem: a #GstMemory. + * + * Check if the padding in @mem is 0 filled. + */ +#define GST_MEMORY_IS_ZERO_PADDED(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PADDED) + +/** + * GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS: + * @mem: a #GstMemory. + * + * Check if @mem is physically contiguous. + * + * Since: 1.2 + */ +#define GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS) + +/** + * GST_MEMORY_IS_NOT_MAPPABLE: + * @mem: a #GstMemory. + * + * Check if @mem can't be mapped via gst_memory_map() without any preconditions + * + * Since: 1.2 + */ +#define GST_MEMORY_IS_NOT_MAPPABLE(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_NOT_MAPPABLE) + +/** + * GstMemory: + * @mini_object: parent structure + * @allocator: pointer to the #GstAllocator + * @parent: parent memory block + * @maxsize: the maximum size allocated + * @align: the alignment of the memory + * @offset: the offset where valid data starts + * @size: the size of valid data + * + * Base structure for memory implementations. Custom memory will put this structure + * as the first member of their structure. + */ +struct _GstMemory { + GstMiniObject mini_object; + + GstAllocator *allocator; + + GstMemory *parent; + gsize maxsize; + gsize align; + gsize offset; + gsize size; +}; + +/** + * GstMapFlags: + * @GST_MAP_READ: map for read access + * @GST_MAP_WRITE: map for write access + * @GST_MAP_FLAG_LAST: first flag that can be used for custom purposes + * + * Flags used when mapping memory + */ +typedef enum { + GST_MAP_READ = GST_LOCK_FLAG_READ, + GST_MAP_WRITE = GST_LOCK_FLAG_WRITE, + + GST_MAP_FLAG_LAST = (1 << 16) +} GstMapFlags; + +/** + * GST_MAP_READWRITE: (value 3) (type GstMapFlags) + * + * GstMapFlags value alias for GST_MAP_READ | GST_MAP_WRITE + */ +#define GST_MAP_READWRITE ((GstMapFlags) (GST_MAP_READ | GST_MAP_WRITE)) + + +/** + * GstMapInfo: + * @memory: a pointer to the mapped memory + * @flags: flags used when mapping the memory + * @data: (array length=size): a pointer to the mapped data + * @size: the valid size in @data + * @maxsize: the maximum bytes in @data + * @user_data: extra private user_data that the implementation of the memory + * can use to store extra info. + * + * A structure containing the result of a map operation such as + * gst_memory_map(). It contains the data and size. + */ +typedef struct { + GstMemory *memory; + GstMapFlags flags; + guint8 *data; + gsize size; + gsize maxsize; + /*< protected >*/ + gpointer user_data[4]; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +} GstMapInfo; + +/** + * GST_MAP_INFO_INIT: + * + * Initializer for #GstMapInfo + */ +#define GST_MAP_INFO_INIT { NULL, (GstMapFlags) 0, NULL, 0, 0, { NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL}} + +/** + * GstMemoryMapFunction: + * @mem: a #GstMemory + * @maxsize: size to map + * @flags: access mode for the memory + * + * Get the memory of @mem that can be accessed according to the mode specified + * in @flags. The function should return a pointer that contains at least + * @maxsize bytes. + * + * Returns: a pointer to memory of which at least @maxsize bytes can be + * accessed according to the access pattern in @flags. + */ +typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize maxsize, GstMapFlags flags); + +/** + * GstMemoryMapFullFunction: + * @mem: a #GstMemory + * @info: the #GstMapInfo to map with + * @maxsize: size to map + * + * Get the memory of @mem that can be accessed according to the mode specified + * in @info's flags. The function should return a pointer that contains at least + * @maxsize bytes. + * + * Returns: a pointer to memory of which at least @maxsize bytes can be + * accessed according to the access pattern in @info's flags. + */ +typedef gpointer (*GstMemoryMapFullFunction) (GstMemory *mem, GstMapInfo * info, gsize maxsize); + +/** + * GstMemoryUnmapFunction: + * @mem: a #GstMemory + * + * Return the pointer previously retrieved with gst_memory_map(). + */ +typedef void (*GstMemoryUnmapFunction) (GstMemory *mem); + +/** + * GstMemoryUnmapFullFunction: + * @mem: a #GstMemory + * @info: a #GstMapInfo + * + * Return the pointer previously retrieved with gst_memory_map() with @info. + */ +typedef void (*GstMemoryUnmapFullFunction) (GstMemory *mem, GstMapInfo * info); + +/** + * GstMemoryCopyFunction: + * @mem: a #GstMemory + * @offset: an offset + * @size: a size or -1 + * + * Copy @size bytes from @mem starting at @offset and return them wrapped in a + * new GstMemory object. + * If @size is set to -1, all bytes starting at @offset are copied. + * + * Returns: a new #GstMemory object wrapping a copy of the requested region in + * @mem. + */ +typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gssize offset, gssize size); + +/** + * GstMemoryShareFunction: + * @mem: a #GstMemory + * @offset: an offset + * @size: a size or -1 + * + * Share @size bytes from @mem starting at @offset and return them wrapped in a + * new GstMemory object. If @size is set to -1, all bytes starting at @offset are + * shared. This function does not make a copy of the bytes in @mem. + * + * Returns: a new #GstMemory object sharing the requested region in @mem. + */ +typedef GstMemory * (*GstMemoryShareFunction) (GstMemory *mem, gssize offset, gssize size); + +/** + * GstMemoryIsSpanFunction: + * @mem1: a #GstMemory + * @mem2: a #GstMemory + * @offset: a result offset + * + * Check if @mem1 and @mem2 occupy contiguous memory and return the offset of + * @mem1 in the parent buffer in @offset. + * + * Returns: %TRUE if @mem1 and @mem2 are in contiguous memory. + */ +typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, gsize *offset); + +GST_API +void gst_memory_init (GstMemory *mem, GstMemoryFlags flags, + GstAllocator *allocator, GstMemory *parent, + gsize maxsize, gsize align, + gsize offset, gsize size); +GST_API +gboolean gst_memory_is_type (GstMemory *mem, const gchar *mem_type); + +/* refcounting */ +/** + * gst_memory_ref: + * @memory: The memory to refcount + * + * Increase the refcount of this memory. + * + * Returns: (transfer full): @memory (for convenience when doing assignments) + */ +static inline GstMemory * +gst_memory_ref (GstMemory * memory) +{ + return (GstMemory *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (memory)); +} + +/** + * gst_memory_unref: + * @memory: (transfer full): the memory to refcount + * + * Decrease the refcount of an memory, freeing it if the refcount reaches 0. + */ +static inline void +gst_memory_unref (GstMemory * memory) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (memory)); +} + +/* getting/setting memory properties */ + +GST_API +gsize gst_memory_get_sizes (GstMemory *mem, gsize *offset, gsize *maxsize); + +GST_API +void gst_memory_resize (GstMemory *mem, gssize offset, gsize size); + +#define gst_memory_lock(m,f) gst_mini_object_lock (GST_MINI_OBJECT_CAST (m), (f)) +#define gst_memory_unlock(m,f) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (m), (f)) +#define gst_memory_is_writable(m) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (m)) +#define gst_memory_make_writable(m) GST_MEMORY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (m))) + +/* retrieving data */ + +GST_API +GstMemory * gst_memory_make_mapped (GstMemory *mem, GstMapInfo *info, GstMapFlags flags) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +gboolean gst_memory_map (GstMemory *mem, GstMapInfo *info, GstMapFlags flags); + +GST_API +void gst_memory_unmap (GstMemory *mem, GstMapInfo *info); + +/* copy and subregions */ + +GST_API +GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gssize size) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +GstMemory * gst_memory_share (GstMemory *mem, gssize offset, gssize size) G_GNUC_WARN_UNUSED_RESULT; + +/* span memory */ + +GST_API +gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMemory, gst_memory_unref) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAllocator, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_MEMORY_H__ */ diff --git a/gst/gstmessage.c b/gst/gstmessage.c new file mode 100644 index 0000000..31ad649 --- /dev/null +++ b/gst/gstmessage.c @@ -0,0 +1,3200 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstmessage.c: GstMessage subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstmessage + * @title: GstMessage + * @short_description: Lightweight objects to signal the application of + * pipeline events + * @see_also: #GstBus, #GstMiniObject, #GstElement + * + * Messages are implemented as a subclass of #GstMiniObject with a generic + * #GstStructure as the content. This allows for writing custom messages without + * requiring an API change while allowing a wide range of different types + * of messages. + * + * Messages are posted by objects in the pipeline and are passed to the + * application using the #GstBus. + * + * The basic use pattern of posting a message on a #GstBus is as follows: + * |[ + * gst_bus_post (bus, gst_message_new_eos()); + * ]| + * + * A #GstElement usually posts messages on the bus provided by the parent + * container using gst_element_post_message(). + */ + + +#include "gst_private.h" +#include /* memcpy */ +#include "gsterror.h" +#include "gstenumtypes.h" +#include "gstinfo.h" +#include "gstmessage.h" +#include "gsttaglist.h" +#include "gstutils.h" +#include "gstquark.h" +#include "gstvalue.h" + + +typedef struct +{ + GstMessage message; + + GstStructure *structure; +} GstMessageImpl; + +#define GST_MESSAGE_STRUCTURE(m) (((GstMessageImpl *)(m))->structure) + +typedef struct +{ + const gint type; + const gchar *name; + GQuark quark; +} GstMessageQuarks; + +static GstMessageQuarks message_quarks[] = { + {GST_MESSAGE_UNKNOWN, "unknown", 0}, + {GST_MESSAGE_EOS, "eos", 0}, + {GST_MESSAGE_ERROR, "error", 0}, + {GST_MESSAGE_WARNING, "warning", 0}, + {GST_MESSAGE_INFO, "info", 0}, + {GST_MESSAGE_TAG, "tag", 0}, + {GST_MESSAGE_BUFFERING, "buffering", 0}, + {GST_MESSAGE_STATE_CHANGED, "state-changed", 0}, + {GST_MESSAGE_STATE_DIRTY, "state-dirty", 0}, + {GST_MESSAGE_STEP_DONE, "step-done", 0}, + {GST_MESSAGE_CLOCK_PROVIDE, "clock-provide", 0}, + {GST_MESSAGE_CLOCK_LOST, "clock-lost", 0}, + {GST_MESSAGE_NEW_CLOCK, "new-clock", 0}, + {GST_MESSAGE_STRUCTURE_CHANGE, "structure-change", 0}, + {GST_MESSAGE_STREAM_STATUS, "stream-status", 0}, + {GST_MESSAGE_APPLICATION, "application", 0}, + {GST_MESSAGE_ELEMENT, "element", 0}, + {GST_MESSAGE_SEGMENT_START, "segment-start", 0}, + {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0}, + {GST_MESSAGE_DURATION_CHANGED, "duration-changed", 0}, + {GST_MESSAGE_LATENCY, "latency", 0}, + {GST_MESSAGE_ASYNC_START, "async-start", 0}, + {GST_MESSAGE_ASYNC_DONE, "async-done", 0}, + {GST_MESSAGE_REQUEST_STATE, "request-state", 0}, + {GST_MESSAGE_STEP_START, "step-start", 0}, + {GST_MESSAGE_QOS, "qos", 0}, + {GST_MESSAGE_PROGRESS, "progress", 0}, + {GST_MESSAGE_TOC, "toc", 0}, + {GST_MESSAGE_RESET_TIME, "reset-time", 0}, + {GST_MESSAGE_STREAM_START, "stream-start", 0}, + {GST_MESSAGE_NEED_CONTEXT, "need-context", 0}, + {GST_MESSAGE_HAVE_CONTEXT, "have-context", 0}, + {GST_MESSAGE_DEVICE_ADDED, "device-added", 0}, + {GST_MESSAGE_DEVICE_REMOVED, "device-removed", 0}, + {GST_MESSAGE_PROPERTY_NOTIFY, "property-notify", 0}, + {GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0}, + {GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0}, + {GST_MESSAGE_REDIRECT, "redirect", 0}, + {0, NULL, 0} +}; + +static GQuark details_quark = 0; + +GType _gst_message_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstMessage, gst_message); + +void +_priv_gst_message_initialize (void) +{ + gint i; + + GST_CAT_INFO (GST_CAT_GST_INIT, "init messages"); + + for (i = 0; message_quarks[i].name; i++) { + message_quarks[i].quark = + g_quark_from_static_string (message_quarks[i].name); + } + details_quark = g_quark_from_static_string ("details"); + + _gst_message_type = gst_message_get_type (); +} + +/** + * gst_message_type_get_name: + * @type: the message type + * + * Get a printable name for the given message type. Do not modify or free. + * + * Returns: a reference to the static name of the message. + */ +const gchar * +gst_message_type_get_name (GstMessageType type) +{ + gint i; + + for (i = 0; message_quarks[i].name; i++) { + if (type == message_quarks[i].type) + return message_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_message_type_to_quark: + * @type: the message type + * + * Get the unique quark for the given message type. + * + * Returns: the quark associated with the message type + */ +GQuark +gst_message_type_to_quark (GstMessageType type) +{ + gint i; + + for (i = 0; message_quarks[i].name; i++) { + if (type == message_quarks[i].type) + return message_quarks[i].quark; + } + return 0; +} + +static gboolean +_gst_message_dispose (GstMessage * message) +{ + gboolean do_free = TRUE; + + if (GST_MINI_OBJECT_FLAG_IS_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY)) { + /* revive message, so bus can finish with it and clean it up */ + gst_message_ref (message); + + GST_INFO ("[msg %p] signalling async free", message); + + GST_MESSAGE_LOCK (message); + GST_MESSAGE_SIGNAL (message); + GST_MESSAGE_UNLOCK (message); + + /* don't free it yet, let bus finish with it first */ + do_free = FALSE; + } + + return do_free; +} + +static void +_gst_message_free (GstMessage * message) +{ + GstStructure *structure; + + g_return_if_fail (message != NULL); + + GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p, %s from %s", message, + GST_MESSAGE_TYPE_NAME (message), GST_MESSAGE_SRC_NAME (message)); + + if (GST_MESSAGE_SRC (message)) { + gst_object_unref (GST_MESSAGE_SRC (message)); + GST_MESSAGE_SRC (message) = NULL; + } + + structure = GST_MESSAGE_STRUCTURE (message); + if (structure) { + gst_structure_set_parent_refcount (structure, NULL); + gst_structure_free (structure); + } + + g_slice_free1 (sizeof (GstMessageImpl), message); +} + +static void +gst_message_init (GstMessageImpl * message, GstMessageType type, + GstObject * src); + +static GstMessage * +_gst_message_copy (GstMessage * message) +{ + GstMessageImpl *copy; + GstStructure *structure; + + GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p, %s from %s", message, + GST_MESSAGE_TYPE_NAME (message), + GST_OBJECT_NAME (GST_MESSAGE_SRC (message))); + + copy = g_slice_new0 (GstMessageImpl); + + gst_message_init (copy, GST_MESSAGE_TYPE (message), + GST_MESSAGE_SRC (message)); + + GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message); + GST_MESSAGE_SEQNUM (copy) = GST_MESSAGE_SEQNUM (message); + + structure = GST_MESSAGE_STRUCTURE (message); + if (structure) { + GST_MESSAGE_STRUCTURE (copy) = gst_structure_copy (structure); + gst_structure_set_parent_refcount (GST_MESSAGE_STRUCTURE (copy), + ©->message.mini_object.refcount); + } else { + GST_MESSAGE_STRUCTURE (copy) = NULL; + } + + return GST_MESSAGE_CAST (copy); +} + +static void +gst_message_init (GstMessageImpl * message, GstMessageType type, + GstObject * src) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (message), 0, _gst_message_type, + (GstMiniObjectCopyFunction) _gst_message_copy, + (GstMiniObjectDisposeFunction) _gst_message_dispose, + (GstMiniObjectFreeFunction) _gst_message_free); + + GST_MESSAGE_TYPE (message) = type; + if (src) + gst_object_ref (src); + GST_MESSAGE_SRC (message) = src; + GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE; + GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next (); +} + + +/** + * gst_message_new_custom: + * @type: The #GstMessageType to distinguish messages + * @src: (transfer none) (allow-none): The object originating the message. + * @structure: (transfer full) (allow-none): the structure for the + * message. The message will take ownership of the structure. + * + * Create a new custom-typed message. This can be used for anything not + * handled by other message-specific functions to pass a message to the + * app. The structure field can be %NULL. + * + * Returns: (transfer full) (nullable): The new message. + * + * MT safe. + */ +GstMessage * +gst_message_new_custom (GstMessageType type, GstObject * src, + GstStructure * structure) +{ + GstMessageImpl *message; + + message = g_slice_new0 (GstMessageImpl); + + GST_CAT_LOG (GST_CAT_MESSAGE, "source %s: creating new message %p %s", + (src ? GST_OBJECT_NAME (src) : "NULL"), message, + gst_message_type_get_name (type)); + + if (structure) { + /* structure must not have a parent */ + if (!gst_structure_set_parent_refcount (structure, + &message->message.mini_object.refcount)) + goto had_parent; + } + gst_message_init (message, type, src); + + GST_MESSAGE_STRUCTURE (message) = structure; + + return GST_MESSAGE_CAST (message); + + /* ERRORS */ +had_parent: + { + g_slice_free1 (sizeof (GstMessageImpl), message); + g_warning ("structure is already owned by another object"); + return NULL; + } +} + +/** + * gst_message_get_seqnum: + * @message: A #GstMessage. + * + * Retrieve the sequence number of a message. + * + * Messages have ever-incrementing sequence numbers, which may also be set + * explicitly via gst_message_set_seqnum(). Sequence numbers are typically used + * to indicate that a message corresponds to some other set of messages or + * events, for example a SEGMENT_DONE message corresponding to a SEEK event. It + * is considered good practice to make this correspondence when possible, though + * it is not required. + * + * Note that events and messages share the same sequence number incrementor; + * two events or messages will never have the same sequence number unless + * that correspondence was made explicitly. + * + * Returns: The message's sequence number. + * + * MT safe. + */ +guint32 +gst_message_get_seqnum (GstMessage * message) +{ + g_return_val_if_fail (GST_IS_MESSAGE (message), -1); + + return GST_MESSAGE_SEQNUM (message); +} + +/** + * gst_message_set_seqnum: + * @message: A #GstMessage. + * @seqnum: A sequence number. + * + * Set the sequence number of a message. + * + * This function might be called by the creator of a message to indicate that + * the message relates to other messages or events. See gst_message_get_seqnum() + * for more information. + * + * MT safe. + */ +void +gst_message_set_seqnum (GstMessage * message, guint32 seqnum) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + + GST_MESSAGE_SEQNUM (message) = seqnum; +} + +/** + * gst_message_new_eos: + * @src: (transfer none) (allow-none): The object originating the message. + * + * Create a new eos message. This message is generated and posted in + * the sink elements of a GstBin. The bin will only forward the EOS + * message to the application if all sinks have posted an EOS message. + * + * Returns: (transfer full): The new eos message. + * + * MT safe. + */ +GstMessage * +gst_message_new_eos (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_EOS, src, NULL); + + return message; +} + +/** + * gst_message_new_error_with_details: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * @details: (transfer full): (allow-none): A GstStructure with details + * + * Create a new error message. The message will copy @error and + * @debug. This message is posted by element when a fatal event + * occurred. The pipeline will probably (partially) stop. The application + * receiving this message should stop the pipeline. + * + * Returns: (transfer full) (nullable): the new error message. + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_error_with_details (GstObject * src, GError * error, + const gchar * debug, GstStructure * details) +{ + GstMessage *message; + GstStructure *structure; + + if (debug && !g_utf8_validate (debug, -1, NULL)) { + debug = NULL; + g_warning ("Trying to set debug field of error message, but " + "string is not valid UTF-8. Please file a bug."); + } + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_ERROR), + GST_QUARK (GERROR), G_TYPE_ERROR, error, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); + message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure); + if (details) { + GValue v = G_VALUE_INIT; + + g_value_init (&v, GST_TYPE_STRUCTURE); + g_value_take_boxed (&v, details); + gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark, + &v); + } + + return message; +} + +/** + * gst_message_new_error: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * + * Create a new error message. The message will copy @error and + * @debug. This message is posted by element when a fatal event + * occurred. The pipeline will probably (partially) stop. The application + * receiving this message should stop the pipeline. + * + * Returns: (transfer full): the new error message. + * + * MT safe. + */ +GstMessage * +gst_message_new_error (GstObject * src, GError * error, const gchar * debug) +{ + return gst_message_new_error_with_details (src, error, debug, NULL); +} + +/** + * gst_message_parse_error_details: + * @message: The message object + * @structure: (transfer none) (out): A pointer to the returned details + * + * Returns the optional details structure, may be NULL if none. + * The returned structure must not be freed. + * + * Since: 1.10 + */ +void +gst_message_parse_error_details (GstMessage * message, + const GstStructure ** structure) +{ + const GValue *v; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR); + g_return_if_fail (structure != NULL); + + *structure = NULL; + v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message), + details_quark); + if (v) { + *structure = g_value_get_boxed (v); + } +} + +/** + * gst_message_new_warning_with_details: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * @details: (transfer full): (allow-none): A GstStructure with details + * + * Create a new warning message. The message will make copies of @error and + * @debug. + * + * Returns: (transfer full) (nullable): the new warning message. + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_warning_with_details (GstObject * src, GError * error, + const gchar * debug, GstStructure * details) +{ + GstMessage *message; + GstStructure *structure; + + if (debug && !g_utf8_validate (debug, -1, NULL)) { + debug = NULL; + g_warning ("Trying to set debug field of warning message, but " + "string is not valid UTF-8. Please file a bug."); + } + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_WARNING), + GST_QUARK (GERROR), G_TYPE_ERROR, error, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); + message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure); + if (details) { + GValue v = G_VALUE_INIT; + + g_value_init (&v, GST_TYPE_STRUCTURE); + g_value_take_boxed (&v, details); + gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark, + &v); + } + + return message; +} + +/** + * gst_message_new_warning: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * + * Create a new warning message. The message will make copies of @error and + * @debug. + * + * Returns: (transfer full): the new warning message. + * + * MT safe. + */ +GstMessage * +gst_message_new_warning (GstObject * src, GError * error, const gchar * debug) +{ + return gst_message_new_warning_with_details (src, error, debug, NULL); +} + +/** + * gst_message_parse_warning_details: + * @message: The message object + * @structure: (transfer none) (out): A pointer to the returned details structure + * + * Returns the optional details structure, may be NULL if none + * The returned structure must not be freed. + * + * Since: 1.10 + */ +void +gst_message_parse_warning_details (GstMessage * message, + const GstStructure ** structure) +{ + const GValue *v; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING); + g_return_if_fail (structure != NULL); + + *structure = NULL; + v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message), + details_quark); + if (v) { + *structure = g_value_get_boxed (v); + } +} + +/** + * gst_message_new_info_with_details: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * @details: (transfer full): (allow-none): A GstStructure with details + * + * Create a new info message. The message will make copies of @error and + * @debug. + * + * Returns: (transfer full) (nullable): the new warning message. + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_info_with_details (GstObject * src, GError * error, + const gchar * debug, GstStructure * details) +{ + GstMessage *message; + GstStructure *structure; + + if (debug && !g_utf8_validate (debug, -1, NULL)) { + debug = NULL; + g_warning ("Trying to set debug field of info message, but " + "string is not valid UTF-8. Please file a bug."); + } + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_INFO), + GST_QUARK (GERROR), G_TYPE_ERROR, error, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); + message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure); + if (details) { + GValue v = G_VALUE_INIT; + + g_value_init (&v, GST_TYPE_STRUCTURE); + g_value_take_boxed (&v, details); + gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark, + &v); + } + + return message; +} + +/** + * gst_message_new_info: + * @src: (transfer none) (allow-none): The object originating the message. + * @error: (transfer none): The GError for this message. + * @debug: A debugging string. + * + * Create a new info message. The message will make copies of @error and + * @debug. + * + * Returns: (transfer full): the new info message. + * + * MT safe. + */ +GstMessage * +gst_message_new_info (GstObject * src, GError * error, const gchar * debug) +{ + return gst_message_new_info_with_details (src, error, debug, NULL); +} + +/** + * gst_message_parse_info_details: + * @message: The message object + * @structure: (transfer none) (out): A pointer to the returned details structure + * + * Returns the optional details structure, may be NULL if none + * The returned structure must not be freed. + * + * Since: 1.10 + */ +void +gst_message_parse_info_details (GstMessage * message, + const GstStructure ** structure) +{ + const GValue *v; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO); + g_return_if_fail (structure != NULL); + + *structure = NULL; + v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message), + details_quark); + if (v) { + *structure = g_value_get_boxed (v); + } +} + +/** + * gst_message_new_tag: + * @src: (transfer none) (allow-none): The object originating the message. + * @tag_list: (transfer full): the tag list for the message. + * + * Create a new tag message. The message will take ownership of the tag list. + * The message is posted by elements that discovered a new taglist. + * + * Returns: (transfer full): the new tag message. + * + * MT safe. + */ +GstMessage * +gst_message_new_tag (GstObject * src, GstTagList * tag_list) +{ + GstStructure *s; + GstMessage *message; + GValue val = G_VALUE_INIT; + + g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), NULL); + + s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_TAG)); + g_value_init (&val, GST_TYPE_TAG_LIST); + g_value_take_boxed (&val, tag_list); + gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val); + message = gst_message_new_custom (GST_MESSAGE_TAG, src, s); + return message; +} + +/** + * gst_message_new_buffering: + * @src: (transfer none) (allow-none): The object originating the message. + * @percent: The buffering percent + * + * Create a new buffering message. This message can be posted by an element that + * needs to buffer data before it can continue processing. @percent should be a + * value between 0 and 100. A value of 100 means that the buffering completed. + * + * When @percent is < 100 the application should PAUSE a PLAYING pipeline. When + * @percent is 100, the application can set the pipeline (back) to PLAYING. + * The application must be prepared to receive BUFFERING messages in the + * PREROLLING state and may only set the pipeline to PLAYING after receiving a + * message with @percent set to 100, which can happen after the pipeline + * completed prerolling. + * + * MT safe. + * + * Returns: (transfer full) (nullable): The new buffering message. + */ +GstMessage * +gst_message_new_buffering (GstObject * src, gint percent) +{ + GstMessage *message; + GstStructure *structure; + gint64 buffering_left; + + g_return_val_if_fail (percent >= 0 && percent <= 100, NULL); + + buffering_left = (percent == 100 ? 0 : -1); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_BUFFERING), + GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, + GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM, + GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1, + GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1, + GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL); + message = gst_message_new_custom (GST_MESSAGE_BUFFERING, src, structure); + + return message; +} + +/** + * gst_message_new_state_changed: + * @src: (transfer none) (allow-none): The object originating the message. + * @oldstate: the previous state + * @newstate: the new (current) state + * @pending: the pending (target) state + * + * Create a state change message. This message is posted whenever an element + * changed its state. + * + * Returns: (transfer full): the new state change message. + * + * MT safe. + */ +GstMessage * +gst_message_new_state_changed (GstObject * src, + GstState oldstate, GstState newstate, GstState pending) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE_CHANGED), + GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate, + GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate, + GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL); + message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src, structure); + + return message; +} + +/** + * gst_message_new_state_dirty: + * @src: (transfer none) (allow-none): The object originating the message + * + * Create a state dirty message. This message is posted whenever an element + * changed its state asynchronously and is used internally to update the + * states of container objects. + * + * Returns: (transfer full): the new state dirty message. + * + * MT safe. + */ +GstMessage * +gst_message_new_state_dirty (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_STATE_DIRTY, src, NULL); + + return message; +} + +/** + * gst_message_new_clock_provide: + * @src: (transfer none) (allow-none): The object originating the message. + * @clock: (transfer none): the clock it provides + * @ready: %TRUE if the sender can provide a clock + * + * Create a clock provide message. This message is posted whenever an + * element is ready to provide a clock or lost its ability to provide + * a clock (maybe because it paused or became EOS). + * + * This message is mainly used internally to manage the clock + * selection. + * + * Returns: (transfer full): the new provide clock message. + * + * MT safe. + */ +GstMessage * +gst_message_new_clock_provide (GstObject * src, GstClock * clock, + gboolean ready) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_PROVIDE), + GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, + GST_QUARK (READY), G_TYPE_BOOLEAN, ready, NULL); + message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src, structure); + + return message; +} + +/** + * gst_message_new_clock_lost: + * @src: (transfer none) (allow-none): The object originating the message. + * @clock: (transfer none): the clock that was lost + * + * Create a clock lost message. This message is posted whenever the + * clock is not valid anymore. + * + * If this message is posted by the pipeline, the pipeline will + * select a new clock again when it goes to PLAYING. It might therefore + * be needed to set the pipeline to PAUSED and PLAYING again. + * + * Returns: (transfer full): The new clock lost message. + * + * MT safe. + */ +GstMessage * +gst_message_new_clock_lost (GstObject * src, GstClock * clock) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_LOST), + GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL); + message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src, structure); + + return message; +} + +/** + * gst_message_new_new_clock: + * @src: (transfer none) (allow-none): The object originating the message. + * @clock: (transfer none): the new selected clock + * + * Create a new clock message. This message is posted whenever the + * pipeline selects a new clock for the pipeline. + * + * Returns: (transfer full): The new new clock message. + * + * MT safe. + */ +GstMessage * +gst_message_new_new_clock (GstObject * src, GstClock * clock) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEW_CLOCK), + GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL); + message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src, structure); + + return message; +} + +/** + * gst_message_new_structure_change: + * @src: (transfer none) (allow-none): The object originating the message. + * @type: The change type. + * @owner: (transfer none): The owner element of @src. + * @busy: Whether the structure change is busy. + * + * Create a new structure change message. This message is posted when the + * structure of a pipeline is in the process of being changed, for example + * when pads are linked or unlinked. + * + * @src should be the sinkpad that unlinked or linked. + * + * Returns: (transfer full): the new structure change message. + * + * MT safe. + */ +GstMessage * +gst_message_new_structure_change (GstObject * src, GstStructureChangeType type, + GstElement * owner, gboolean busy) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (GST_IS_PAD (src), NULL); + /* g_return_val_if_fail (GST_PAD_DIRECTION (src) == GST_PAD_SINK, NULL); */ + g_return_val_if_fail (GST_IS_ELEMENT (owner), NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_STRUCTURE_CHANGE), + GST_QUARK (TYPE), GST_TYPE_STRUCTURE_CHANGE_TYPE, type, + GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, + GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, NULL); + + message = gst_message_new_custom (GST_MESSAGE_STRUCTURE_CHANGE, src, + structure); + + return message; +} + +/** + * gst_message_new_segment_start: + * @src: (transfer none) (allow-none): The object originating the message. + * @format: The format of the position being played + * @position: The position of the segment being played + * + * Create a new segment message. This message is posted by elements that + * start playback of a segment as a result of a segment seek. This message + * is not received by the application but is used for maintenance reasons in + * container elements. + * + * Returns: (transfer full): the new segment start message. + * + * MT safe. + */ +GstMessage * +gst_message_new_segment_start (GstObject * src, GstFormat format, + gint64 position) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_START), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (POSITION), G_TYPE_INT64, position, NULL); + message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src, structure); + + return message; +} + +/** + * gst_message_new_segment_done: + * @src: (transfer none) (allow-none): The object originating the message. + * @format: The format of the position being done + * @position: The position of the segment being done + * + * Create a new segment done message. This message is posted by elements that + * finish playback of a segment as a result of a segment seek. This message + * is received by the application after all elements that posted a segment_start + * have posted the segment_done. + * + * Returns: (transfer full): the new segment done message. + * + * MT safe. + */ +GstMessage * +gst_message_new_segment_done (GstObject * src, GstFormat format, + gint64 position) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_DONE), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (POSITION), G_TYPE_INT64, position, NULL); + message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src, structure); + + return message; +} + +/** + * gst_message_new_application: + * @src: (transfer none) (allow-none): The object originating the message. + * @structure: (transfer full): the structure for the message. The message + * will take ownership of the structure. + * + * Create a new application-typed message. GStreamer will never create these + * messages; they are a gift from us to you. Enjoy. + * + * Returns: (transfer full) (nullable): The new application message. + * + * MT safe. + */ +GstMessage * +gst_message_new_application (GstObject * src, GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, NULL); + + return gst_message_new_custom (GST_MESSAGE_APPLICATION, src, structure); +} + +/** + * gst_message_new_element: + * @src: (transfer none) (allow-none): The object originating the message. + * @structure: (transfer full): The structure for the + * message. The message will take ownership of the structure. + * + * Create a new element-specific message. This is meant as a generic way of + * allowing one-way communication from an element to an application, for example + * "the firewire cable was unplugged". The format of the message should be + * documented in the element's documentation. The structure field can be %NULL. + * + * Returns: (transfer full) (nullable): The new element message. + * + * MT safe. + */ +GstMessage * +gst_message_new_element (GstObject * src, GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, NULL); + + return gst_message_new_custom (GST_MESSAGE_ELEMENT, src, structure); +} + +/** + * gst_message_new_duration_changed: + * @src: (transfer none) (allow-none): The object originating the message. + * + * Create a new duration changed message. This message is posted by elements + * that know the duration of a stream when the duration changes. This message + * is received by bins and is used to calculate the total duration of a + * pipeline. + * + * Returns: (transfer full): The new duration-changed message. + * + * MT safe. + */ +GstMessage * +gst_message_new_duration_changed (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_DURATION_CHANGED, src, + gst_structure_new_id_empty (GST_QUARK (MESSAGE_DURATION_CHANGED))); + + return message; +} + +/** + * gst_message_new_async_start: + * @src: (transfer none) (allow-none): The object originating the message. + * + * This message is posted by elements when they start an ASYNC state change. + * + * Returns: (transfer full): The new async_start message. + * + * MT safe. + */ +GstMessage * +gst_message_new_async_start (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, NULL); + + return message; +} + +/** + * gst_message_new_async_done: + * @src: (transfer none) (allow-none): The object originating the message. + * @running_time: the desired running_time + * + * The message is posted when elements completed an ASYNC state change. + * @running_time contains the time of the desired running_time when this + * elements goes to PLAYING. A value of #GST_CLOCK_TIME_NONE for @running_time + * means that the element has no clock interaction and thus doesn't care about + * the running_time of the pipeline. + * + * Returns: (transfer full): The new async_done message. + * + * MT safe. + */ +GstMessage * +gst_message_new_async_done (GstObject * src, GstClockTime running_time) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_ASYNC_DONE), + GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL); + message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure); + + return message; +} + +/** + * gst_message_new_latency: + * @src: (transfer none) (allow-none): The object originating the message. + * + * This message can be posted by elements when their latency requirements have + * changed. + * + * Returns: (transfer full): The new latency message. + * + * MT safe. + */ +GstMessage * +gst_message_new_latency (GstObject * src) +{ + GstMessage *message; + + message = gst_message_new_custom (GST_MESSAGE_LATENCY, src, NULL); + + return message; +} + +/** + * gst_message_new_request_state: + * @src: (transfer none) (allow-none): The object originating the message. + * @state: The new requested state + * + * This message can be posted by elements when they want to have their state + * changed. A typical use case would be an audio server that wants to pause the + * pipeline because a higher priority stream is being played. + * + * Returns: (transfer full): the new request state message. + * + * MT safe. + */ +GstMessage * +gst_message_new_request_state (GstObject * src, GstState state) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_REQUEST_STATE), + GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) state, NULL); + message = gst_message_new_custom (GST_MESSAGE_REQUEST_STATE, src, structure); + + return message; +} + +/** + * gst_message_get_structure: + * @message: The #GstMessage. + * + * Access the structure of the message. + * + * Returns: (transfer none) (nullable): The structure of the message. The + * structure is still owned by the message, which means that you should not + * free it and that the pointer becomes invalid when you free the message. + * + * MT safe. + */ +const GstStructure * +gst_message_get_structure (GstMessage * message) +{ + g_return_val_if_fail (GST_IS_MESSAGE (message), NULL); + + return GST_MESSAGE_STRUCTURE (message); +} + +/** + * gst_message_writable_structure: + * @message: The #GstMessage. + * + * Get a writable version of the structure. + * + * Returns: (transfer none): The structure of the message. The structure + * is still owned by the message, which means that you should not free + * it and that the pointer becomes invalid when you free the message. + * This function checks if @message is writable and will never return + * %NULL. + * + * MT safe. + * + * Since: 1.14 + */ +GstStructure * +gst_message_writable_structure (GstMessage * message) +{ + GstStructure *structure; + + g_return_val_if_fail (GST_IS_MESSAGE (message), NULL); + g_return_val_if_fail (gst_message_is_writable (message), NULL); + + structure = GST_MESSAGE_STRUCTURE (message); + + if (structure == NULL) { + structure = + gst_structure_new_id_empty (gst_message_type_to_quark (GST_MESSAGE_TYPE + (message))); + gst_structure_set_parent_refcount (structure, + &message->mini_object.refcount); + GST_MESSAGE_STRUCTURE (message) = structure; + } + return structure; +} + +/** + * gst_message_has_name: + * @message: The #GstMessage. + * @name: name to check + * + * Checks if @message has the given @name. This function is usually used to + * check the name of a custom message. + * + * Returns: %TRUE if @name matches the name of the message structure. + */ +gboolean +gst_message_has_name (GstMessage * message, const gchar * name) +{ + GstStructure *structure; + + g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE); + + structure = GST_MESSAGE_STRUCTURE (message); + if (structure == NULL) + return FALSE; + + return gst_structure_has_name (structure, name); +} + +/** + * gst_message_parse_tag: + * @message: A valid #GstMessage of type GST_MESSAGE_TAG. + * @tag_list: (out callee-allocates): return location for the tag-list. + * + * Extracts the tag list from the GstMessage. The tag list returned in the + * output argument is a copy; the caller must free it when done. + * + * Typical usage of this function might be: + * |[ + * ... + * switch (GST_MESSAGE_TYPE (msg)) { + * case GST_MESSAGE_TAG: { + * GstTagList *tags = NULL; + * + * gst_message_parse_tag (msg, &tags); + * g_print ("Got tags from element %s\n", GST_OBJECT_NAME (msg->src)); + * handle_tags (tags); + * gst_tag_list_unref (tags); + * break; + * } + * ... + * } + * ... + * ]| + * + * MT safe. + */ +void +gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG); + g_return_if_fail (tag_list != NULL); + + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (TAGLIST), GST_TYPE_TAG_LIST, tag_list, NULL); +} + +/** + * gst_message_parse_buffering: + * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING. + * @percent: (out) (allow-none): Return location for the percent. + * + * Extracts the buffering percent from the GstMessage. see also + * gst_message_new_buffering(). + * + * MT safe. + */ +void +gst_message_parse_buffering (GstMessage * message, gint * percent) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING); + + if (percent) + *percent = + g_value_get_int (gst_structure_id_get_value (GST_MESSAGE_STRUCTURE + (message), GST_QUARK (BUFFER_PERCENT))); +} + +/** + * gst_message_set_buffering_stats: + * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING. + * @mode: a buffering mode + * @avg_in: the average input rate + * @avg_out: the average output rate + * @buffering_left: amount of buffering time left in milliseconds + * + * Configures the buffering stats values in @message. + */ +void +gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode, + gint avg_in, gint avg_out, gint64 buffering_left) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING); + + gst_structure_id_set (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode, + GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in, + GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out, + GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL); +} + +/** + * gst_message_parse_buffering_stats: + * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING. + * @mode: (out) (allow-none): a buffering mode, or %NULL + * @avg_in: (out) (allow-none): the average input rate, or %NULL + * @avg_out: (out) (allow-none): the average output rate, or %NULL + * @buffering_left: (out) (allow-none): amount of buffering time left in + * milliseconds, or %NULL + * + * Extracts the buffering stats values from @message. + */ +void +gst_message_parse_buffering_stats (GstMessage * message, + GstBufferingMode * mode, gint * avg_in, gint * avg_out, + gint64 * buffering_left) +{ + GstStructure *structure; + + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING); + + structure = GST_MESSAGE_STRUCTURE (message); + if (mode) + *mode = (GstBufferingMode) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (BUFFERING_MODE))); + if (avg_in) + *avg_in = g_value_get_int (gst_structure_id_get_value (structure, + GST_QUARK (AVG_IN_RATE))); + if (avg_out) + *avg_out = g_value_get_int (gst_structure_id_get_value (structure, + GST_QUARK (AVG_OUT_RATE))); + if (buffering_left) + *buffering_left = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (BUFFERING_LEFT))); +} + +/** + * gst_message_parse_state_changed: + * @message: a valid #GstMessage of type GST_MESSAGE_STATE_CHANGED + * @oldstate: (out) (allow-none): the previous state, or %NULL + * @newstate: (out) (allow-none): the new (current) state, or %NULL + * @pending: (out) (allow-none): the pending (target) state, or %NULL + * + * Extracts the old and new states from the GstMessage. + * + * Typical usage of this function might be: + * |[ + * ... + * switch (GST_MESSAGE_TYPE (msg)) { + * case GST_MESSAGE_STATE_CHANGED: { + * GstState old_state, new_state; + * + * gst_message_parse_state_changed (msg, &old_state, &new_state, NULL); + * g_print ("Element %s changed state from %s to %s.\n", + * GST_OBJECT_NAME (msg->src), + * gst_element_state_get_name (old_state), + * gst_element_state_get_name (new_state)); + * break; + * } + * ... + * } + * ... + * ]| + * + * MT safe. + */ +void +gst_message_parse_state_changed (GstMessage * message, + GstState * oldstate, GstState * newstate, GstState * pending) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED); + + structure = GST_MESSAGE_STRUCTURE (message); + if (oldstate) + *oldstate = (GstState) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (OLD_STATE))); + if (newstate) + *newstate = (GstState) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (NEW_STATE))); + if (pending) + *pending = (GstState) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (PENDING_STATE))); +} + +/** + * gst_message_parse_clock_provide: + * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_PROVIDE. + * @clock: (out) (allow-none) (transfer none): a pointer to hold a clock + * object, or %NULL + * @ready: (out) (allow-none): a pointer to hold the ready flag, or %NULL + * + * Extracts the clock and ready flag from the GstMessage. + * The clock object returned remains valid until the message is freed. + * + * MT safe. + */ +void +gst_message_parse_clock_provide (GstMessage * message, GstClock ** clock, + gboolean * ready) +{ + const GValue *clock_gvalue; + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE); + + structure = GST_MESSAGE_STRUCTURE (message); + clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK)); + g_return_if_fail (clock_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK); + + if (ready) + *ready = + g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (READY))); + if (clock) + *clock = (GstClock *) g_value_get_object (clock_gvalue); +} + +/** + * gst_message_parse_clock_lost: + * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_LOST. + * @clock: (out) (allow-none) (transfer none): a pointer to hold the lost clock + * + * Extracts the lost clock from the GstMessage. + * The clock object returned remains valid until the message is freed. + * + * MT safe. + */ +void +gst_message_parse_clock_lost (GstMessage * message, GstClock ** clock) +{ + const GValue *clock_gvalue; + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_LOST); + + structure = GST_MESSAGE_STRUCTURE (message); + clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK)); + g_return_if_fail (clock_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK); + + if (clock) + *clock = (GstClock *) g_value_get_object (clock_gvalue); +} + +/** + * gst_message_parse_new_clock: + * @message: A valid #GstMessage of type GST_MESSAGE_NEW_CLOCK. + * @clock: (out) (allow-none) (transfer none): a pointer to hold the selected + * new clock + * + * Extracts the new clock from the GstMessage. + * The clock object returned remains valid until the message is freed. + * + * MT safe. + */ +void +gst_message_parse_new_clock (GstMessage * message, GstClock ** clock) +{ + const GValue *clock_gvalue; + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK); + + structure = GST_MESSAGE_STRUCTURE (message); + clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK)); + g_return_if_fail (clock_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK); + + if (clock) + *clock = (GstClock *) g_value_get_object (clock_gvalue); +} + +/** + * gst_message_parse_structure_change: + * @message: A valid #GstMessage of type GST_MESSAGE_STRUCTURE_CHANGE. + * @type: (out): A pointer to hold the change type + * @owner: (out) (allow-none) (transfer none): The owner element of the + * message source + * @busy: (out) (allow-none): a pointer to hold whether the change is in + * progress or has been completed + * + * Extracts the change type and completion status from the GstMessage. + * + * MT safe. + */ +void +gst_message_parse_structure_change (GstMessage * message, + GstStructureChangeType * type, GstElement ** owner, gboolean * busy) +{ + const GValue *owner_gvalue; + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STRUCTURE_CHANGE); + + structure = GST_MESSAGE_STRUCTURE (message); + owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER)); + g_return_if_fail (owner_gvalue != NULL); + g_return_if_fail (G_VALUE_TYPE (owner_gvalue) == GST_TYPE_ELEMENT); + + if (type) + *type = (GstStructureChangeType) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (TYPE))); + if (owner) + *owner = (GstElement *) g_value_get_object (owner_gvalue); + if (busy) + *busy = + g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (BUSY))); +} + +/** + * gst_message_parse_error: + * @message: A valid #GstMessage of type GST_MESSAGE_ERROR. + * @gerror: (out) (allow-none) (transfer full): location for the GError + * @debug: (out) (allow-none) (transfer full): location for the debug message, + * or %NULL + * + * Extracts the GError and debug string from the GstMessage. The values returned + * in the output arguments are copies; the caller must free them when done. + * + * Typical usage of this function might be: + * |[ + * ... + * switch (GST_MESSAGE_TYPE (msg)) { + * case GST_MESSAGE_ERROR: { + * GError *err = NULL; + * gchar *dbg_info = NULL; + * + * gst_message_parse_error (msg, &err, &dbg_info); + * g_printerr ("ERROR from element %s: %s\n", + * GST_OBJECT_NAME (msg->src), err->message); + * g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none"); + * g_error_free (err); + * g_free (dbg_info); + * break; + * } + * ... + * } + * ... + * ]| + * + * MT safe. + */ +void +gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR); + + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (GERROR), G_TYPE_ERROR, gerror, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); +} + +/** + * gst_message_parse_warning: + * @message: A valid #GstMessage of type GST_MESSAGE_WARNING. + * @gerror: (out) (allow-none) (transfer full): location for the GError + * @debug: (out) (allow-none) (transfer full): location for the debug message, + * or %NULL + * + * Extracts the GError and debug string from the GstMessage. The values returned + * in the output arguments are copies; the caller must free them when done. + * + * MT safe. + */ +void +gst_message_parse_warning (GstMessage * message, GError ** gerror, + gchar ** debug) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING); + + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (GERROR), G_TYPE_ERROR, gerror, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); +} + +/** + * gst_message_parse_info: + * @message: A valid #GstMessage of type GST_MESSAGE_INFO. + * @gerror: (out) (allow-none) (transfer full): location for the GError + * @debug: (out) (allow-none) (transfer full): location for the debug message, + * or %NULL + * + * Extracts the GError and debug string from the GstMessage. The values returned + * in the output arguments are copies; the caller must free them when done. + * + * MT safe. + */ +void +gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO); + + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (GERROR), G_TYPE_ERROR, gerror, + GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL); +} + +/** + * gst_message_parse_segment_start: + * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_START. + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL + * + * Extracts the position and format from the segment start message. + * + * MT safe. + */ +void +gst_message_parse_segment_start (GstMessage * message, GstFormat * format, + gint64 * position) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START); + + structure = GST_MESSAGE_STRUCTURE (message); + if (format) + *format = (GstFormat) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (position) + *position = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (POSITION))); +} + +/** + * gst_message_parse_segment_done: + * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_DONE. + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL + * + * Extracts the position and format from the segment done message. + * + * MT safe. + */ +void +gst_message_parse_segment_done (GstMessage * message, GstFormat * format, + gint64 * position) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE); + + structure = GST_MESSAGE_STRUCTURE (message); + if (format) + *format = (GstFormat) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (position) + *position = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (POSITION))); +} + +/** + * gst_message_parse_async_done: + * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE. + * @running_time: (out) (allow-none): Result location for the running_time or %NULL + * + * Extract the running_time from the async_done message. + * + * MT safe. + */ +void +gst_message_parse_async_done (GstMessage * message, GstClockTime * running_time) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_DONE); + + structure = GST_MESSAGE_STRUCTURE (message); + if (running_time) + *running_time = + g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (RUNNING_TIME))); +} + +/** + * gst_message_parse_request_state: + * @message: A valid #GstMessage of type GST_MESSAGE_REQUEST_STATE. + * @state: (out) (allow-none): Result location for the requested state or %NULL + * + * Extract the requested state from the request_state message. + * + * MT safe. + */ +void +gst_message_parse_request_state (GstMessage * message, GstState * state) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REQUEST_STATE); + + structure = GST_MESSAGE_STRUCTURE (message); + if (state) + *state = (GstState) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (NEW_STATE))); +} + +/** + * gst_message_new_stream_status: + * @src: The object originating the message. + * @type: The stream status type. + * @owner: (transfer none): the owner element of @src. + * + * Create a new stream status message. This message is posted when a streaming + * thread is created/destroyed or when the state changed. + * + * Returns: (transfer full): the new stream status message. + * + * MT safe. + */ +GstMessage * +gst_message_new_stream_status (GstObject * src, GstStreamStatusType type, + GstElement * owner) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_STATUS), + GST_QUARK (TYPE), GST_TYPE_STREAM_STATUS_TYPE, (gint) type, + GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, NULL); + message = gst_message_new_custom (GST_MESSAGE_STREAM_STATUS, src, structure); + + return message; +} + +/** + * gst_message_parse_stream_status: + * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS. + * @type: (out): A pointer to hold the status type + * @owner: (out) (transfer none): The owner element of the message source + * + * Extracts the stream status type and owner the GstMessage. The returned + * owner remains valid for as long as the reference to @message is valid and + * should thus not be unreffed. + * + * MT safe. + */ +void +gst_message_parse_stream_status (GstMessage * message, + GstStreamStatusType * type, GstElement ** owner) +{ + const GValue *owner_gvalue; + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS); + + structure = GST_MESSAGE_STRUCTURE (message); + owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER)); + g_return_if_fail (owner_gvalue != NULL); + + if (type) + *type = (GstStreamStatusType) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (TYPE))); + if (owner) + *owner = (GstElement *) g_value_get_object (owner_gvalue); +} + +/** + * gst_message_set_stream_status_object: + * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS. + * @object: the object controlling the streaming + * + * Configures the object handling the streaming thread. This is usually a + * GstTask object but other objects might be added in the future. + */ +void +gst_message_set_stream_status_object (GstMessage * message, + const GValue * object) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_set_value (structure, GST_QUARK (OBJECT), object); +} + +/** + * gst_message_get_stream_status_object: + * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS. + * + * Extracts the object managing the streaming thread from @message. + * + * Returns: (nullable): a GValue containing the object that manages the + * streaming thread. This object is usually of type GstTask but other types can + * be added in the future. The object remains valid as long as @message is + * valid. + */ +const GValue * +gst_message_get_stream_status_object (GstMessage * message) +{ + const GValue *result; + GstStructure *structure; + + g_return_val_if_fail (GST_IS_MESSAGE (message), NULL); + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS, + NULL); + + structure = GST_MESSAGE_STRUCTURE (message); + result = gst_structure_id_get_value (structure, GST_QUARK (OBJECT)); + + return result; +} + +/** + * gst_message_new_step_done: + * @src: The object originating the message. + * @format: the format of @amount + * @amount: the amount of stepped data + * @rate: the rate of the stepped amount + * @flush: is this an flushing step + * @intermediate: is this an intermediate step + * @duration: the duration of the data + * @eos: the step caused EOS + * + * This message is posted by elements when they complete a part, when @intermediate set + * to %TRUE, or a complete step operation. + * + * @duration will contain the amount of time (in GST_FORMAT_TIME) of the stepped + * @amount of media in format @format. + * + * Returns: (transfer full): the new step_done message. + * + * MT safe. + */ +GstMessage * +gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount, + gdouble rate, gboolean flush, gboolean intermediate, guint64 duration, + gboolean eos) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_DONE), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (AMOUNT), G_TYPE_UINT64, amount, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush, + GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, + GST_QUARK (DURATION), G_TYPE_UINT64, duration, + GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL); + message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure); + + return message; +} + +/** + * gst_message_parse_step_done: + * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE. + * @format: (out) (allow-none): result location for the format + * @amount: (out) (allow-none): result location for the amount + * @rate: (out) (allow-none): result location for the rate + * @flush: (out) (allow-none): result location for the flush flag + * @intermediate: (out) (allow-none): result location for the intermediate flag + * @duration: (out) (allow-none): result location for the duration + * @eos: (out) (allow-none): result location for the EOS flag + * + * Extract the values the step_done message. + * + * MT safe. + */ +void +gst_message_parse_step_done (GstMessage * message, GstFormat * format, + guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate, + guint64 * duration, gboolean * eos) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (AMOUNT), G_TYPE_UINT64, amount, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush, + GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, + GST_QUARK (DURATION), G_TYPE_UINT64, duration, + GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL); +} + +/** + * gst_message_new_step_start: + * @src: The object originating the message. + * @active: if the step is active or queued + * @format: the format of @amount + * @amount: the amount of stepped data + * @rate: the rate of the stepped amount + * @flush: is this an flushing step + * @intermediate: is this an intermediate step + * + * This message is posted by elements when they accept or activate a new step + * event for @amount in @format. + * + * @active is set to %FALSE when the element accepted the new step event and has + * queued it for execution in the streaming threads. + * + * @active is set to %TRUE when the element has activated the step operation and + * is now ready to start executing the step in the streaming thread. After this + * message is emitted, the application can queue a new step operation in the + * element. + * + * Returns: (transfer full): The new step_start message. + * + * MT safe. + */ +GstMessage * +gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format, + guint64 amount, gdouble rate, gboolean flush, gboolean intermediate) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_START), + GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (AMOUNT), G_TYPE_UINT64, amount, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush, + GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL); + message = gst_message_new_custom (GST_MESSAGE_STEP_START, src, structure); + + return message; +} + +/** + * gst_message_parse_step_start: + * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE. + * @active: (out) (allow-none): result location for the active flag + * @format: (out) (allow-none): result location for the format + * @amount: (out) (allow-none): result location for the amount + * @rate: (out) (allow-none): result location for the rate + * @flush: (out) (allow-none): result location for the flush flag + * @intermediate: (out) (allow-none): result location for the intermediate flag + * + * Extract the values from step_start message. + * + * MT safe. + */ +void +gst_message_parse_step_start (GstMessage * message, gboolean * active, + GstFormat * format, guint64 * amount, gdouble * rate, gboolean * flush, + gboolean * intermediate) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (AMOUNT), G_TYPE_UINT64, amount, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush, + GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL); +} + +/** + * gst_message_new_qos: + * @src: The object originating the message. + * @live: if the message was generated by a live element + * @running_time: the running time of the buffer that generated the message + * @stream_time: the stream time of the buffer that generated the message + * @timestamp: the timestamps of the buffer that generated the message + * @duration: the duration of the buffer that generated the message + * + * A QOS message is posted on the bus whenever an element decides to drop a + * buffer because of QoS reasons or whenever it changes its processing strategy + * because of QoS reasons (quality adjustments such as processing at lower + * accuracy). + * + * This message can be posted by an element that performs synchronisation against the + * clock (live) or it could be dropped by an element that performs QoS because of QOS + * events received from a downstream element (!live). + * + * @running_time, @stream_time, @timestamp, @duration should be set to the + * respective running-time, stream-time, timestamp and duration of the (dropped) + * buffer that generated the QoS event. Values can be left to + * GST_CLOCK_TIME_NONE when unknown. + * + * Returns: (transfer full): The new qos message. + * + * MT safe. + */ +GstMessage * +gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time, + guint64 stream_time, guint64 timestamp, guint64 duration) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_QOS), + GST_QUARK (LIVE), G_TYPE_BOOLEAN, live, + GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, + GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time, + GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, + GST_QUARK (DURATION), G_TYPE_UINT64, duration, + GST_QUARK (JITTER), G_TYPE_INT64, (gint64) 0, + GST_QUARK (PROPORTION), G_TYPE_DOUBLE, (gdouble) 1.0, + GST_QUARK (QUALITY), G_TYPE_INT, (gint) 1000000, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, GST_FORMAT_UNDEFINED, + GST_QUARK (PROCESSED), G_TYPE_UINT64, (guint64) - 1, + GST_QUARK (DROPPED), G_TYPE_UINT64, (guint64) - 1, NULL); + message = gst_message_new_custom (GST_MESSAGE_QOS, src, structure); + + return message; +} + +/** + * gst_message_set_qos_values: + * @message: A valid #GstMessage of type GST_MESSAGE_QOS. + * @jitter: The difference of the running-time against the deadline. + * @proportion: Long term prediction of the ideal rate relative to normal rate + * to get optimal quality. + * @quality: An element dependent integer value that specifies the current + * quality level of the element. The default maximum quality is 1000000. + * + * Set the QoS values that have been calculated/analysed from the QoS data + * + * MT safe. + */ +void +gst_message_set_qos_values (GstMessage * message, gint64 jitter, + gdouble proportion, gint quality) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_set (structure, + GST_QUARK (JITTER), G_TYPE_INT64, jitter, + GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion, + GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL); +} + +/** + * gst_message_set_qos_stats: + * @message: A valid #GstMessage of type GST_MESSAGE_QOS. + * @format: Units of the 'processed' and 'dropped' fields. Video sinks and video + * filters will use GST_FORMAT_BUFFERS (frames). Audio sinks and audio filters + * will likely use GST_FORMAT_DEFAULT (samples). + * @processed: Total number of units correctly processed since the last state + * change to READY or a flushing operation. + * @dropped: Total number of units dropped since the last state change to READY + * or a flushing operation. + * + * Set the QoS stats representing the history of the current continuous pipeline + * playback period. + * + * When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are + * invalid. Values of -1 for either @processed or @dropped mean unknown values. + * + * MT safe. + */ +void +gst_message_set_qos_stats (GstMessage * message, GstFormat format, + guint64 processed, guint64 dropped) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_set (structure, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (PROCESSED), G_TYPE_UINT64, processed, + GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL); +} + +/** + * gst_message_parse_qos: + * @message: A valid #GstMessage of type GST_MESSAGE_QOS. + * @live: (out) (allow-none): if the message was generated by a live element + * @running_time: (out) (allow-none): the running time of the buffer that + * generated the message + * @stream_time: (out) (allow-none): the stream time of the buffer that + * generated the message + * @timestamp: (out) (allow-none): the timestamps of the buffer that + * generated the message + * @duration: (out) (allow-none): the duration of the buffer that + * generated the message + * + * Extract the timestamps and live status from the QoS message. + * + * The returned values give the running_time, stream_time, timestamp and + * duration of the dropped buffer. Values of GST_CLOCK_TIME_NONE mean unknown + * values. + * + * MT safe. + */ +void +gst_message_parse_qos (GstMessage * message, gboolean * live, + guint64 * running_time, guint64 * stream_time, guint64 * timestamp, + guint64 * duration) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (LIVE), G_TYPE_BOOLEAN, live, + GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, + GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time, + GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, + GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL); +} + +/** + * gst_message_parse_qos_values: + * @message: A valid #GstMessage of type GST_MESSAGE_QOS. + * @jitter: (out) (allow-none): The difference of the running-time against + * the deadline. + * @proportion: (out) (allow-none): Long term prediction of the ideal rate + * relative to normal rate to get optimal quality. + * @quality: (out) (allow-none): An element dependent integer value that + * specifies the current quality level of the element. The default + * maximum quality is 1000000. + * + * Extract the QoS values that have been calculated/analysed from the QoS data + * + * MT safe. + */ +void +gst_message_parse_qos_values (GstMessage * message, gint64 * jitter, + gdouble * proportion, gint * quality) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (JITTER), G_TYPE_INT64, jitter, + GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion, + GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL); +} + +/** + * gst_message_parse_qos_stats: + * @message: A valid #GstMessage of type GST_MESSAGE_QOS. + * @format: (out) (allow-none): Units of the 'processed' and 'dropped' fields. + * Video sinks and video filters will use GST_FORMAT_BUFFERS (frames). + * Audio sinks and audio filters will likely use GST_FORMAT_DEFAULT + * (samples). + * @processed: (out) (allow-none): Total number of units correctly processed + * since the last state change to READY or a flushing operation. + * @dropped: (out) (allow-none): Total number of units dropped since the last + * state change to READY or a flushing operation. + * + * Extract the QoS stats representing the history of the current continuous + * pipeline playback period. + * + * When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are + * invalid. Values of -1 for either @processed or @dropped mean unknown values. + * + * MT safe. + */ +void +gst_message_parse_qos_stats (GstMessage * message, GstFormat * format, + guint64 * processed, guint64 * dropped) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (PROCESSED), G_TYPE_UINT64, processed, + GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL); +} + +/** + * gst_message_new_progress: + * @src: The object originating the message. + * @type: a #GstProgressType + * @code: a progress code + * @text: free, user visible text describing the progress + * + * Progress messages are posted by elements when they use an asynchronous task + * to perform actions triggered by a state change. + * + * @code contains a well defined string describing the action. + * @text should contain a user visible string detailing the current action. + * + * Returns: (transfer full) (nullable): The new qos message. + */ +GstMessage * +gst_message_new_progress (GstObject * src, GstProgressType type, + const gchar * code, const gchar * text) +{ + GstMessage *message; + GstStructure *structure; + gint percent = 100, timeout = -1; + + g_return_val_if_fail (code != NULL, NULL); + g_return_val_if_fail (text != NULL, NULL); + + if (type == GST_PROGRESS_TYPE_START || type == GST_PROGRESS_TYPE_CONTINUE) + percent = 0; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_PROGRESS), + GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type, + GST_QUARK (CODE), G_TYPE_STRING, code, + GST_QUARK (TEXT), G_TYPE_STRING, text, + GST_QUARK (PERCENT), G_TYPE_INT, percent, + GST_QUARK (TIMEOUT), G_TYPE_INT, timeout, NULL); + message = gst_message_new_custom (GST_MESSAGE_PROGRESS, src, structure); + + return message; +} + +/** + * gst_message_parse_progress: + * @message: A valid #GstMessage of type GST_MESSAGE_PROGRESS. + * @type: (out) (allow-none): location for the type + * @code: (out) (allow-none) (transfer full): location for the code + * @text: (out) (allow-none) (transfer full): location for the text + * + * Parses the progress @type, @code and @text. + */ +void +gst_message_parse_progress (GstMessage * message, GstProgressType * type, + gchar ** code, gchar ** text) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROGRESS); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_get (structure, + GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type, + GST_QUARK (CODE), G_TYPE_STRING, code, + GST_QUARK (TEXT), G_TYPE_STRING, text, NULL); +} + +/** + * gst_message_new_toc: + * @src: the object originating the message. + * @toc: (transfer none): #GstToc structure for the message. + * @updated: whether TOC was updated or not. + * + * Create a new TOC message. The message is posted by elements + * that discovered or updated a TOC. + * + * Returns: (transfer full): a new TOC message. + * + * MT safe. + */ +GstMessage * +gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated) +{ + GstStructure *toc_struct; + + g_return_val_if_fail (toc != NULL, NULL); + + toc_struct = gst_structure_new_id (GST_QUARK (MESSAGE_TOC), + GST_QUARK (TOC), GST_TYPE_TOC, toc, + GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL); + + return gst_message_new_custom (GST_MESSAGE_TOC, src, toc_struct); +} + +/** + * gst_message_parse_toc: + * @message: a valid #GstMessage of type GST_MESSAGE_TOC. + * @toc: (out) (transfer full): return location for the TOC. + * @updated: (out): return location for the updated flag. + * + * Extract the TOC from the #GstMessage. The TOC returned in the + * output argument is a copy; the caller must free it with + * gst_toc_unref() when done. + * + * MT safe. + */ +void +gst_message_parse_toc (GstMessage * message, GstToc ** toc, gboolean * updated) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TOC); + g_return_if_fail (toc != NULL); + + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (TOC), GST_TYPE_TOC, toc, + GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL); +} + +/** + * gst_message_new_reset_time: + * @src: (transfer none) (allow-none): The object originating the message. + * @running_time: the requested running-time + * + * This message is posted when the pipeline running-time should be reset to + * @running_time, like after a flushing seek. + * + * Returns: (transfer full): The new reset_time message. + * + * MT safe. + */ +GstMessage * +gst_message_new_reset_time (GstObject * src, GstClockTime running_time) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_RESET_TIME), + GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL); + message = gst_message_new_custom (GST_MESSAGE_RESET_TIME, src, structure); + + return message; +} + +/** + * gst_message_parse_reset_time: + * @message: A valid #GstMessage of type GST_MESSAGE_RESET_TIME. + * @running_time: (out) (allow-none): Result location for the running_time or + * %NULL + * + * Extract the running-time from the RESET_TIME message. + * + * MT safe. + */ +void +gst_message_parse_reset_time (GstMessage * message, GstClockTime * running_time) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_RESET_TIME); + + structure = GST_MESSAGE_STRUCTURE (message); + if (running_time) + *running_time = + g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (RUNNING_TIME))); +} + +/** + * gst_message_new_stream_start: + * @src: (transfer none) (allow-none): The object originating the message. + * + * Create a new stream_start message. This message is generated and posted in + * the sink elements of a GstBin. The bin will only forward the STREAM_START + * message to the application if all sinks have posted an STREAM_START message. + * + * Returns: (transfer full): The new stream_start message. + * + * MT safe. + */ +GstMessage * +gst_message_new_stream_start (GstObject * src) +{ + GstMessage *message; + GstStructure *s; + + s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_STREAM_START)); + message = gst_message_new_custom (GST_MESSAGE_STREAM_START, src, s); + + return message; +} + + +/** + * gst_message_set_group_id: + * @message: the message + * @group_id: the group id + * + * Sets the group id on the stream-start message. + * + * All streams that have the same group id are supposed to be played + * together, i.e. all streams inside a container file should have the + * same group id but different stream ids. The group id should change + * each time the stream is started, resulting in different group ids + * each time a file is played for example. + * + * MT safe. + * + * Since: 1.2 + */ +void +gst_message_set_group_id (GstMessage * message, guint group_id) +{ + GstStructure *structure; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START); + g_return_if_fail (gst_message_is_writable (message)); + + structure = GST_MESSAGE_STRUCTURE (message); + gst_structure_id_set (structure, GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, + NULL); +} + +/** + * gst_message_parse_group_id: + * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_START. + * @group_id: (out) (allow-none): Result location for the group id or + * %NULL + * + * Extract the group from the STREAM_START message. + * + * Returns: %TRUE if the message had a group id set, %FALSE otherwise + * + * MT safe. + * + * Since: 1.2 + */ +gboolean +gst_message_parse_group_id (GstMessage * message, guint * group_id) +{ + GstStructure *structure; + const GValue *v; + + g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE); + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START, + FALSE); + + if (!group_id) + return TRUE; + + structure = GST_MESSAGE_STRUCTURE (message); + + v = gst_structure_id_get_value (structure, GST_QUARK (GROUP_ID)); + if (!v) + return FALSE; + + *group_id = g_value_get_uint (v); + return TRUE; +} + +/** + * gst_message_new_need_context: + * @src: (transfer none) (allow-none): The object originating the message. + * @context_type: The context type that is needed + * + * This message is posted when an element needs a specific #GstContext. + * + * Returns: (transfer full): The new need-context message. + * + * MT safe. + * + * Since: 1.2 + */ +GstMessage * +gst_message_new_need_context (GstObject * src, const gchar * context_type) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (context_type != NULL, NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEED_CONTEXT), + GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL); + message = gst_message_new_custom (GST_MESSAGE_NEED_CONTEXT, src, structure); + + return message; +} + +/** + * gst_message_parse_context_type: + * @message: a GST_MESSAGE_NEED_CONTEXT type message + * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL + * + * Parse a context type from an existing GST_MESSAGE_NEED_CONTEXT message. + * + * Returns: a #gboolean indicating if the parsing succeeded. + * + * Since: 1.2 + */ +gboolean +gst_message_parse_context_type (GstMessage * message, + const gchar ** context_type) +{ + GstStructure *structure; + const GValue *value; + + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT, + FALSE); + + structure = GST_MESSAGE_STRUCTURE (message); + + if (context_type) { + value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE)); + *context_type = g_value_get_string (value); + } + + return TRUE; +} + +/** + * gst_message_new_have_context: + * @src: (transfer none) (allow-none): The object originating the message. + * @context: (transfer full): the context + * + * This message is posted when an element has a new local #GstContext. + * + * Returns: (transfer full): The new have-context message. + * + * MT safe. + * + * Since: 1.2 + */ +GstMessage * +gst_message_new_have_context (GstObject * src, GstContext * context) +{ + GstMessage *message; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_HAVE_CONTEXT), + GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL); + message = gst_message_new_custom (GST_MESSAGE_HAVE_CONTEXT, src, structure); + gst_context_unref (context); + + return message; +} + +/** + * gst_message_parse_have_context: + * @message: A valid #GstMessage of type GST_MESSAGE_HAVE_CONTEXT. + * @context: (out) (transfer full) (allow-none): Result location for the + * context or %NULL + * + * Extract the context from the HAVE_CONTEXT message. + * + * MT safe. + * + * Since: 1.2 + */ +void +gst_message_parse_have_context (GstMessage * message, GstContext ** context) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_HAVE_CONTEXT); + + if (context) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL); +} + +/** + * gst_message_new_device_added: + * @src: The #GstObject that created the message + * @device: (transfer none): The new #GstDevice + * + * Creates a new device-added message. The device-added message is produced by + * #GstDeviceProvider or a #GstDeviceMonitor. They announce the appearance + * of monitored devices. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.4 + */ +GstMessage * +gst_message_new_device_added (GstObject * src, GstDevice * device) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_ADDED), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); + message = gst_message_new_custom (GST_MESSAGE_DEVICE_ADDED, src, structure); + + return message; +} + +/** + * gst_message_parse_device_added: + * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_ADDED + * @device: (out) (allow-none) (transfer full): A location where to store a + * pointer to the new #GstDevice, or %NULL + * + * Parses a device-added message. The device-added message is produced by + * #GstDeviceProvider or a #GstDeviceMonitor. It announces the appearance + * of monitored devices. + * + * Since: 1.4 + */ +void +gst_message_parse_device_added (GstMessage * message, GstDevice ** device) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_ADDED); + + if (device) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); +} + +/** + * gst_message_new_device_removed: + * @src: The #GstObject that created the message + * @device: (transfer none): The removed #GstDevice + * + * Creates a new device-removed message. The device-removed message is produced + * by #GstDeviceProvider or a #GstDeviceMonitor. They announce the + * disappearance of monitored devices. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.4 + */ +GstMessage * +gst_message_new_device_removed (GstObject * src, GstDevice * device) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_REMOVED), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); + message = gst_message_new_custom (GST_MESSAGE_DEVICE_REMOVED, src, structure); + + return message; +} + +/** + * gst_message_parse_device_removed: + * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_REMOVED + * @device: (out) (allow-none) (transfer full): A location where to store a + * pointer to the removed #GstDevice, or %NULL + * + * Parses a device-removed message. The device-removed message is produced by + * #GstDeviceProvider or a #GstDeviceMonitor. It announces the + * disappearance of monitored devices. + * + * Since: 1.4 + */ +void +gst_message_parse_device_removed (GstMessage * message, GstDevice ** device) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_REMOVED); + + if (device) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); +} + +/** + * gst_message_new_property_notify: + * @src: The #GstObject whose property changed (may or may not be a #GstElement) + * @property_name: name of the property that changed + * @val: (allow-none) (transfer full): new property value, or %NULL + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_property_notify (GstObject * src, const gchar * property_name, + GValue * val) +{ + GstStructure *structure; + GValue name_val = G_VALUE_INIT; + + g_return_val_if_fail (property_name != NULL, NULL); + + structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_PROPERTY_NOTIFY)); + g_value_init (&name_val, G_TYPE_STRING); + /* should already be interned, but let's make sure */ + g_value_set_static_string (&name_val, g_intern_string (property_name)); + gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_NAME), &name_val); + if (val != NULL) + gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_VALUE), val); + + return gst_message_new_custom (GST_MESSAGE_PROPERTY_NOTIFY, src, structure); +} + +/** + * gst_message_parse_property_notify: + * @message: a #GstMessage of type %GST_MESSAGE_PROPERTY_NOTIFY + * @object: (out) (allow-none) (transfer none): location where to store a + * pointer to the object whose property got changed, or %NULL + * @property_name: (out) (transfer none) (allow-none): return location for + * the name of the property that got changed, or %NULL + * @property_value: (out) (transfer none) (allow-none): return location for + * the new value of the property that got changed, or %NULL. This will + * only be set if the property notify watch was told to include the value + * when it was set up + * + * Parses a property-notify message. These will be posted on the bus only + * when set up with gst_element_add_property_notify_watch() or + * gst_element_add_property_deep_notify_watch(). + * + * Since: 1.10 + */ +void +gst_message_parse_property_notify (GstMessage * message, GstObject ** object, + const gchar ** property_name, const GValue ** property_value) +{ + const GstStructure *s = GST_MESSAGE_STRUCTURE (message); + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROPERTY_NOTIFY); + + if (object) + *object = GST_MESSAGE_SRC (message); + + if (property_name) { + const GValue *name_value; + + name_value = gst_structure_id_get_value (s, GST_QUARK (PROPERTY_NAME)); + *property_name = g_value_get_string (name_value); + } + + if (property_value) + *property_value = + gst_structure_id_get_value (s, GST_QUARK (PROPERTY_VALUE)); +} + +/** + * gst_message_new_stream_collection: + * @src: The #GstObject that created the message + * @collection: (transfer none): The #GstStreamCollection + * + * Creates a new stream-collection message. The message is used to announce new + * #GstStreamCollection + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_stream_collection (GstObject * src, + GstStreamCollection * collection) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (collection != NULL, NULL); + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL); + + structure = + gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_COLLECTION), + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); + message = + gst_message_new_custom (GST_MESSAGE_STREAM_COLLECTION, src, structure); + + return message; +} + +/** + * gst_message_parse_stream_collection: + * @message: a #GstMessage of type %GST_MESSAGE_STREAM_COLLECTION + * @collection: (out) (allow-none) (transfer full): A location where to store a + * pointer to the #GstStreamCollection, or %NULL + * + * Parses a stream-collection message. + * + * Since: 1.10 + */ +void +gst_message_parse_stream_collection (GstMessage * message, + GstStreamCollection ** collection) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == + GST_MESSAGE_STREAM_COLLECTION); + + if (collection) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); +} + +/** + * gst_message_new_streams_selected: + * @src: The #GstObject that created the message + * @collection: (transfer none): The #GstStreamCollection + * + * Creates a new steams-selected message. The message is used to announce + * that an array of streams has been selected. This is generally in response + * to a #GST_EVENT_SELECT_STREAMS event, or when an element (such as decodebin3) + * makes an initial selection of streams. + * + * The message also contains the #GstStreamCollection to which the various streams + * belong to. + * + * Users of gst_message_new_streams_selected() can add the selected streams with + * gst_message_streams_selected_add(). + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_streams_selected (GstObject * src, + GstStreamCollection * collection) +{ + GstMessage *message; + GstStructure *structure; + GValue val = G_VALUE_INIT; + + g_return_val_if_fail (collection != NULL, NULL); + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL); + + structure = + gst_structure_new_id (GST_QUARK (MESSAGE_STREAMS_SELECTED), + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); + g_value_init (&val, GST_TYPE_ARRAY); + gst_structure_id_take_value (structure, GST_QUARK (STREAMS), &val); + message = + gst_message_new_custom (GST_MESSAGE_STREAMS_SELECTED, src, structure); + + return message; +} + +/** + * gst_message_streams_selected_get_size: + * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED + * + * Returns the number of streams contained in the @message. + * + * Returns: The number of streams contained within. + * + * Since: 1.10 + */ +guint +gst_message_streams_selected_get_size (GstMessage * msg) +{ + const GValue *val; + + g_return_val_if_fail (GST_IS_MESSAGE (msg), 0); + g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED, + 0); + + val = + gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg), + GST_QUARK (STREAMS)); + return gst_value_array_get_size (val); +} + +/** + * gst_message_streams_selected_add: + * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED + * @stream: (transfer none): a #GstStream to add to @message + * + * Adds the @stream to the @message. + * + * Since: 1.10 + */ +void +gst_message_streams_selected_add (GstMessage * msg, GstStream * stream) +{ + GValue *val; + GValue to_add = G_VALUE_INIT; + + g_return_if_fail (GST_IS_MESSAGE (msg)); + g_return_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED); + g_return_if_fail (GST_IS_STREAM (stream)); + + val = + (GValue *) gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg), + GST_QUARK (STREAMS)); + g_value_init (&to_add, GST_TYPE_STREAM); + g_value_set_object (&to_add, stream); + gst_value_array_append_and_take_value (val, &to_add); +} + +/** + * gst_message_streams_selected_get_stream: + * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED + * @idx: Index of the stream to retrieve + * + * Retrieves the #GstStream with index @index from the @message. + * + * Returns: (transfer full) (nullable): A #GstStream + * + * Since: 1.10 + */ +GstStream * +gst_message_streams_selected_get_stream (GstMessage * msg, guint idx) +{ + const GValue *streams, *val; + + g_return_val_if_fail (GST_IS_MESSAGE (msg), NULL); + g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED, + NULL); + + streams = + gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg), + GST_QUARK (STREAMS)); + val = gst_value_array_get_value (streams, idx); + if (val) { + return (GstStream *) g_value_dup_object (val); + } + + return NULL; +} + +/** + * gst_message_parse_streams_selected: + * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED + * @collection: (out) (allow-none) (transfer full): A location where to store a + * pointer to the #GstStreamCollection, or %NULL + * + * Parses a streams-selected message. + * + * Since: 1.10 + */ +void +gst_message_parse_streams_selected (GstMessage * message, + GstStreamCollection ** collection) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAMS_SELECTED); + + if (collection) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL); +} + +/** + * gst_message_new_redirect: + * @src: The #GstObject whose property changed (may or may not be a #GstElement) + * @location: (transfer none): location string for the new entry + * @tag_list: (transfer full) (allow-none): tag list for the new entry + * @entry_struct: (transfer full) (allow-none): structure for the new entry + * + * Creates a new redirect message and adds a new entry to it. Redirect messages + * are posted when an element detects that the actual data has to be retrieved + * from a different location. This is useful if such a redirection cannot be + * handled inside a source element, for example when HTTP 302/303 redirects + * return a non-HTTP URL. + * + * The redirect message can hold multiple entries. The first one is added + * when the redirect message is created, with the given location, tag_list, + * entry_struct arguments. Use gst_message_add_redirect_entry() to add more + * entries. + * + * Each entry has a location, a tag list, and a structure. All of these are + * optional. The tag list and structure are useful for additional metadata, + * such as bitrate statistics for the given location. + * + * By default, message recipients should treat entries in the order they are + * stored. The recipient should therefore try entry #0 first, and if this + * entry is not acceptable or working, try entry #1 etc. Senders must make + * sure that they add entries in this order. However, recipients are free to + * ignore the order and pick an entry that is "best" for them. One example + * would be a recipient that scans the entries for the one with the highest + * bitrate tag. + * + * The specified location string is copied. However, ownership over the tag + * list and structure are transferred to the message. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.10 + */ +GstMessage * +gst_message_new_redirect (GstObject * src, const gchar * location, + GstTagList * tag_list, const GstStructure * entry_struct) +{ + GstStructure *structure; + GstMessage *message; + GValue entry_locations_gvalue = G_VALUE_INIT; + GValue entry_taglists_gvalue = G_VALUE_INIT; + GValue entry_structures_gvalue = G_VALUE_INIT; + + g_return_val_if_fail (location != NULL, NULL); + + g_value_init (&entry_locations_gvalue, GST_TYPE_LIST); + g_value_init (&entry_taglists_gvalue, GST_TYPE_LIST); + g_value_init (&entry_structures_gvalue, GST_TYPE_LIST); + + structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_REDIRECT)); + gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_LOCATIONS), + &entry_locations_gvalue); + gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_TAGLISTS), + &entry_taglists_gvalue); + gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_STRUCTURES), + &entry_structures_gvalue); + + message = gst_message_new_custom (GST_MESSAGE_REDIRECT, src, structure); + g_assert (message != NULL); + + gst_message_add_redirect_entry (message, location, tag_list, entry_struct); + + return message; +} + +/** + * gst_message_add_redirect_entry: + * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT + * @location: (transfer none): location string for the new entry + * @tag_list: (transfer full) (allow-none): tag list for the new entry + * @entry_struct: (transfer full) (allow-none): structure for the new entry + * + * Creates and appends a new entry. + * + * The specified location string is copied. However, ownership over the tag + * list and structure are transferred to the message. + * + * Since: 1.10 + */ +void +gst_message_add_redirect_entry (GstMessage * message, const gchar * location, + GstTagList * tag_list, const GstStructure * entry_struct) +{ + GValue val = G_VALUE_INIT; + GstStructure *structure; + GValue *entry_locations_gvalue; + GValue *entry_taglists_gvalue; + GValue *entry_structures_gvalue; + + g_return_if_fail (location != NULL); + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT); + + structure = GST_MESSAGE_STRUCTURE (message); + + entry_locations_gvalue = + (GValue *) gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_LOCATIONS)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue)); + entry_taglists_gvalue = + (GValue *) gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_TAGLISTS)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue)); + entry_structures_gvalue = + (GValue *) gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_STRUCTURES)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue)); + + g_value_init (&val, G_TYPE_STRING); + if (location) + g_value_set_string (&val, location); + gst_value_list_append_and_take_value (entry_locations_gvalue, &val); + + g_value_init (&val, GST_TYPE_TAG_LIST); + if (tag_list) + g_value_take_boxed (&val, tag_list); + gst_value_list_append_and_take_value (entry_taglists_gvalue, &val); + + g_value_init (&val, GST_TYPE_STRUCTURE); + if (entry_struct) + g_value_take_boxed (&val, entry_struct); + gst_value_list_append_and_take_value (entry_structures_gvalue, &val); +} + +/** + * gst_message_parse_redirect_entry: + * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT + * @entry_index: index of the entry to parse + * @location: (out) (transfer none) (allow-none): return location for + * the pointer to the entry's location string, or %NULL + * @tag_list: (out) (transfer none) (allow-none): return location for + * the pointer to the entry's tag list, or %NULL + * @entry_struct: (out) (transfer none) (allow-none): return location + * for the pointer to the entry's structure, or %NULL + * + * Parses the location and/or structure from the entry with the given index. + * The index must be between 0 and gst_message_get_num_redirect_entries() - 1. + * Returned pointers are valid for as long as this message exists. + * + * Since: 1.10 + */ +void +gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index, + const gchar ** location, GstTagList ** tag_list, + const GstStructure ** entry_struct) +{ + const GValue *val; + GstStructure *structure; + const GValue *entry_locations_gvalue; + const GValue *entry_taglists_gvalue; + const GValue *entry_structures_gvalue; + + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT); + + if (G_UNLIKELY (!location && !tag_list && !entry_struct)) + return; + + structure = GST_MESSAGE_STRUCTURE (message); + + entry_locations_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_LOCATIONS)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue)); + entry_taglists_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_TAGLISTS)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue)); + entry_structures_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_STRUCTURES)); + g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue)); + + if (location) { + val = gst_value_list_get_value (entry_locations_gvalue, entry_index); + g_return_if_fail (val != NULL); + *location = g_value_get_string (val); + } + + if (tag_list) { + val = gst_value_list_get_value (entry_taglists_gvalue, entry_index); + g_return_if_fail (val != NULL); + *tag_list = (GstTagList *) g_value_get_boxed (val); + } + + if (entry_struct) { + val = gst_value_list_get_value (entry_structures_gvalue, entry_index); + g_return_if_fail (val != NULL); + *entry_struct = (const GstStructure *) g_value_get_boxed (val); + } +} + +/** + * gst_message_get_num_redirect_entries: + * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT + * + * Returns: the number of entries stored in the message + * + * Since: 1.10 + */ +gsize +gst_message_get_num_redirect_entries (GstMessage * message) +{ + GstStructure *structure; + const GValue *entry_locations_gvalue; + const GValue *entry_taglists_gvalue; + const GValue *entry_structures_gvalue; + gsize size; + + g_return_val_if_fail (GST_IS_MESSAGE (message), 0); + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT, 0); + + structure = GST_MESSAGE_STRUCTURE (message); + + entry_locations_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_LOCATIONS)); + g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue), 0); + entry_taglists_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_TAGLISTS)); + g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue), 0); + entry_structures_gvalue = + gst_structure_id_get_value (structure, + GST_QUARK (REDIRECT_ENTRY_STRUCTURES)); + g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue), 0); + + size = gst_value_list_get_size (entry_locations_gvalue); + + g_return_val_if_fail ((size == + gst_value_list_get_size (entry_structures_gvalue)) + && (size == gst_value_list_get_size (entry_taglists_gvalue)), 0); + + return size; +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h new file mode 100644 index 0000000..c9f6ee8 --- /dev/null +++ b/gst/gstmessage.h @@ -0,0 +1,821 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstmessage.h: Header for GstMessage subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_MESSAGE_H__ +#define __GST_MESSAGE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstMessage GstMessage; + +/** + * GstMessageType: + * @GST_MESSAGE_UNKNOWN: an undefined message + * @GST_MESSAGE_EOS: end-of-stream reached in a pipeline. The application will + * only receive this message in the PLAYING state and every time it sets a + * pipeline to PLAYING that is in the EOS state. The application can perform a + * flushing seek in the pipeline, which will undo the EOS state again. + * @GST_MESSAGE_ERROR: an error occurred. When the application receives an error + * message it should stop playback of the pipeline and not assume that more + * data will be played. + * @GST_MESSAGE_WARNING: a warning occurred. + * @GST_MESSAGE_INFO: an info message occurred + * @GST_MESSAGE_TAG: a tag was found. + * @GST_MESSAGE_BUFFERING: the pipeline is buffering. When the application + * receives a buffering message in the PLAYING state for a non-live pipeline it + * must PAUSE the pipeline until the buffering completes, when the percentage + * field in the message is 100%. For live pipelines, no action must be + * performed and the buffering percentage can be used to inform the user about + * the progress. + * @GST_MESSAGE_STATE_CHANGED: a state change happened + * @GST_MESSAGE_STATE_DIRTY: an element changed state in a streaming thread. + * This message is deprecated. + * @GST_MESSAGE_STEP_DONE: a stepping operation finished. + * @GST_MESSAGE_CLOCK_PROVIDE: an element notifies its capability of providing + * a clock. This message is used internally and + * never forwarded to the application. + * @GST_MESSAGE_CLOCK_LOST: The current clock as selected by the pipeline became + * unusable. The pipeline will select a new clock on + * the next PLAYING state change. The application + * should set the pipeline to PAUSED and back to + * PLAYING when this message is received. + * @GST_MESSAGE_NEW_CLOCK: a new clock was selected in the pipeline. + * @GST_MESSAGE_STRUCTURE_CHANGE: the structure of the pipeline changed. This + * message is used internally and never forwarded to the application. + * @GST_MESSAGE_STREAM_STATUS: status about a stream, emitted when it starts, + * stops, errors, etc.. + * @GST_MESSAGE_APPLICATION: message posted by the application, possibly + * via an application-specific element. + * @GST_MESSAGE_ELEMENT: element-specific message, see the specific element's + * documentation + * @GST_MESSAGE_SEGMENT_START: pipeline started playback of a segment. This + * message is used internally and never forwarded to the application. + * @GST_MESSAGE_SEGMENT_DONE: pipeline completed playback of a segment. This + * message is forwarded to the application after all elements that posted + * @GST_MESSAGE_SEGMENT_START posted a GST_MESSAGE_SEGMENT_DONE message. + * @GST_MESSAGE_DURATION_CHANGED: The duration of a pipeline changed. The + * application can get the new duration with a duration query. + * @GST_MESSAGE_ASYNC_START: Posted by elements when they start an ASYNC + * #GstStateChange. This message is not forwarded to the application but is used + * internally. + * @GST_MESSAGE_ASYNC_DONE: Posted by elements when they complete an ASYNC + * #GstStateChange. The application will only receive this message from the toplevel + * pipeline. + * @GST_MESSAGE_LATENCY: Posted by elements when their latency changes. The + * application should recalculate and distribute a new latency. + * @GST_MESSAGE_REQUEST_STATE: Posted by elements when they want the pipeline to + * change state. This message is a suggestion to the application which can + * decide to perform the state change on (part of) the pipeline. + * @GST_MESSAGE_STEP_START: A stepping operation was started. + * @GST_MESSAGE_QOS: A buffer was dropped or an element changed its processing + * strategy for Quality of Service reasons. + * @GST_MESSAGE_PROGRESS: A progress message. + * @GST_MESSAGE_TOC: A new table of contents (TOC) was found or previously found TOC + * was updated. + * @GST_MESSAGE_RESET_TIME: Message to request resetting the pipeline's + * running time from the pipeline. This is an internal message which + * applications will likely never receive. + * @GST_MESSAGE_STREAM_START: Message indicating start of a new stream. Useful + * e.g. when using playbin in gapless playback mode, to get notified when + * the next title actually starts playing (which will be some time after + * the URI for the next title has been set). + * @GST_MESSAGE_NEED_CONTEXT: Message indicating that an element wants a specific context (Since 1.2) + * @GST_MESSAGE_HAVE_CONTEXT: Message indicating that an element created a context (Since 1.2) + * @GST_MESSAGE_EXTENDED: Message is an extended message type (see below). + * These extended message IDs can't be used directly with mask-based API + * like gst_bus_poll() or gst_bus_timed_pop_filtered(), but you can still + * filter for GST_MESSAGE_EXTENDED and then check the result for the + * specific type. (Since 1.4) + * @GST_MESSAGE_DEVICE_ADDED: Message indicating a #GstDevice was added to + * a #GstDeviceProvider (Since 1.4) + * @GST_MESSAGE_DEVICE_REMOVED: Message indicating a #GstDevice was removed + * from a #GstDeviceProvider (Since 1.4) + * @GST_MESSAGE_PROPERTY_NOTIFY: Message indicating a #GObject property has + * changed (Since 1.10) + * @GST_MESSAGE_STREAM_COLLECTION: Message indicating a new #GstStreamCollection + * is available (Since 1.10) + * @GST_MESSAGE_STREAMS_SELECTED: Message indicating the active selection of + * #GstStreams has changed (Since 1.10) + * @GST_MESSAGE_REDIRECT: Message indicating to request the application to + * try to play the given URL(s). Useful if for example a HTTP 302/303 + * response is received with a non-HTTP URL inside. (Since 1.10) + * @GST_MESSAGE_ANY: mask for all of the above messages. + * + * The different message types that are available. + */ +/* NOTE: keep in sync with quark registration in gstmessage.c + * NOTE: keep GST_MESSAGE_ANY a valid gint to avoid compiler warnings. + */ +/* FIXME: 2.0: Make it NOT flags, just a regular 1,2,3,4.. enumeration */ +/* FIXME: For GST_MESSAGE_ANY ~0 -> 0xffffffff see + * https://bugzilla.gnome.org/show_bug.cgi?id=732633 + */ +typedef enum +{ + GST_MESSAGE_UNKNOWN = 0, + GST_MESSAGE_EOS = (1 << 0), + GST_MESSAGE_ERROR = (1 << 1), + GST_MESSAGE_WARNING = (1 << 2), + GST_MESSAGE_INFO = (1 << 3), + GST_MESSAGE_TAG = (1 << 4), + GST_MESSAGE_BUFFERING = (1 << 5), + GST_MESSAGE_STATE_CHANGED = (1 << 6), + GST_MESSAGE_STATE_DIRTY = (1 << 7), + GST_MESSAGE_STEP_DONE = (1 << 8), + GST_MESSAGE_CLOCK_PROVIDE = (1 << 9), + GST_MESSAGE_CLOCK_LOST = (1 << 10), + GST_MESSAGE_NEW_CLOCK = (1 << 11), + GST_MESSAGE_STRUCTURE_CHANGE = (1 << 12), + GST_MESSAGE_STREAM_STATUS = (1 << 13), + GST_MESSAGE_APPLICATION = (1 << 14), + GST_MESSAGE_ELEMENT = (1 << 15), + GST_MESSAGE_SEGMENT_START = (1 << 16), + GST_MESSAGE_SEGMENT_DONE = (1 << 17), + GST_MESSAGE_DURATION_CHANGED = (1 << 18), + GST_MESSAGE_LATENCY = (1 << 19), + GST_MESSAGE_ASYNC_START = (1 << 20), + GST_MESSAGE_ASYNC_DONE = (1 << 21), + GST_MESSAGE_REQUEST_STATE = (1 << 22), + GST_MESSAGE_STEP_START = (1 << 23), + GST_MESSAGE_QOS = (1 << 24), + GST_MESSAGE_PROGRESS = (1 << 25), + GST_MESSAGE_TOC = (1 << 26), + GST_MESSAGE_RESET_TIME = (1 << 27), + GST_MESSAGE_STREAM_START = (1 << 28), + GST_MESSAGE_NEED_CONTEXT = (1 << 29), + GST_MESSAGE_HAVE_CONTEXT = (1 << 30), + GST_MESSAGE_EXTENDED = (gint) (1u << 31), + GST_MESSAGE_DEVICE_ADDED = GST_MESSAGE_EXTENDED + 1, + GST_MESSAGE_DEVICE_REMOVED = GST_MESSAGE_EXTENDED + 2, + GST_MESSAGE_PROPERTY_NOTIFY = GST_MESSAGE_EXTENDED + 3, + GST_MESSAGE_STREAM_COLLECTION = GST_MESSAGE_EXTENDED + 4, + GST_MESSAGE_STREAMS_SELECTED = GST_MESSAGE_EXTENDED + 5, + GST_MESSAGE_REDIRECT = GST_MESSAGE_EXTENDED + 6, + GST_MESSAGE_ANY = (gint) (0xffffffff) +} GstMessageType; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GST_API GType _gst_message_type; + +#define GST_TYPE_MESSAGE (_gst_message_type) +#define GST_IS_MESSAGE(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_MESSAGE)) +#define GST_MESSAGE_CAST(obj) ((GstMessage*)(obj)) +#define GST_MESSAGE(obj) (GST_MESSAGE_CAST(obj)) + +/* the lock is used to handle the synchronous handling of messages, + * the emiting thread is block until the handling thread processed + * the message using this mutex/cond pair */ +#define GST_MESSAGE_GET_LOCK(message) (&GST_MESSAGE_CAST(message)->lock) +#define GST_MESSAGE_LOCK(message) g_mutex_lock(GST_MESSAGE_GET_LOCK(message)) +#define GST_MESSAGE_UNLOCK(message) g_mutex_unlock(GST_MESSAGE_GET_LOCK(message)) +#define GST_MESSAGE_GET_COND(message) (&GST_MESSAGE_CAST(message)->cond) +#define GST_MESSAGE_WAIT(message) g_cond_wait(GST_MESSAGE_GET_COND(message),GST_MESSAGE_GET_LOCK(message)) +#define GST_MESSAGE_SIGNAL(message) g_cond_signal(GST_MESSAGE_GET_COND(message)) + +/** + * GST_MESSAGE_TYPE: + * @message: a #GstMessage + * + * Get the #GstMessageType of @message. + */ +#define GST_MESSAGE_TYPE(message) (GST_MESSAGE_CAST(message)->type) +/** + * GST_MESSAGE_TYPE_IS_EXTENDED: + * @message: a #GstMessage + * + * Check if the message is in the extended message group + * Since: 1.4 + */ +#define GST_MESSAGE_TYPE_IS_EXTENDED(message) (!!(GST_MESSAGE_CAST(message)->type & GST_MESSAGE_EXTENDED)) + +/** + * GST_MESSAGE_TYPE_NAME: + * @message: a #GstMessage + * + * Get a constant string representation of the #GstMessageType of @message. + */ +#define GST_MESSAGE_TYPE_NAME(message) gst_message_type_get_name(GST_MESSAGE_TYPE(message)) +/** + * GST_MESSAGE_TIMESTAMP: + * @message: a #GstMessage + * + * Get the timestamp of @message. This is the timestamp when the message + * was created. + */ +#define GST_MESSAGE_TIMESTAMP(message) (GST_MESSAGE_CAST(message)->timestamp) +/** + * GST_MESSAGE_SRC: + * @message: a #GstMessage + * + * Get the object that posted @message. + */ +#define GST_MESSAGE_SRC(message) (GST_MESSAGE_CAST(message)->src) + +/** + * GST_MESSAGE_SEQNUM: + * @message: a #GstMessage + * + * Get the sequence number of @message. + */ +#define GST_MESSAGE_SEQNUM(message) (GST_MESSAGE_CAST(message)->seqnum) + +/** + * GST_MESSAGE_SRC_NAME: + * @message: a #GstMessage + * + * Get the name of the object that posted @message. Returns "(NULL)" if + * the message has no source object set. + */ +#define GST_MESSAGE_SRC_NAME(message) (GST_MESSAGE_SRC(message) ? \ + GST_OBJECT_NAME (GST_MESSAGE_SRC(message)) : "(NULL)") + +/** + * GstStructureChangeType: + * @GST_STRUCTURE_CHANGE_TYPE_PAD_LINK: Pad linking is starting or done. + * @GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK: Pad unlinking is starting or done. + * + * The type of a %GST_MESSAGE_STRUCTURE_CHANGE. + */ +typedef enum { + GST_STRUCTURE_CHANGE_TYPE_PAD_LINK = 0, + GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK = 1 +} GstStructureChangeType; + +/** + * GstStreamStatusType: + * @GST_STREAM_STATUS_TYPE_CREATE: A new thread need to be created. + * @GST_STREAM_STATUS_TYPE_ENTER: a thread entered its loop function + * @GST_STREAM_STATUS_TYPE_LEAVE: a thread left its loop function + * @GST_STREAM_STATUS_TYPE_DESTROY: a thread is destroyed + * @GST_STREAM_STATUS_TYPE_START: a thread is started + * @GST_STREAM_STATUS_TYPE_PAUSE: a thread is paused + * @GST_STREAM_STATUS_TYPE_STOP: a thread is stopped + * + * The type of a %GST_MESSAGE_STREAM_STATUS. The stream status messages inform the + * application of new streaming threads and their status. + */ +typedef enum { + GST_STREAM_STATUS_TYPE_CREATE = 0, + GST_STREAM_STATUS_TYPE_ENTER = 1, + GST_STREAM_STATUS_TYPE_LEAVE = 2, + GST_STREAM_STATUS_TYPE_DESTROY = 3, + + GST_STREAM_STATUS_TYPE_START = 8, + GST_STREAM_STATUS_TYPE_PAUSE = 9, + GST_STREAM_STATUS_TYPE_STOP = 10 +} GstStreamStatusType; + +/** + * GstProgressType: + * @GST_PROGRESS_TYPE_START: A new task started. + * @GST_PROGRESS_TYPE_CONTINUE: A task completed and a new one continues. + * @GST_PROGRESS_TYPE_COMPLETE: A task completed. + * @GST_PROGRESS_TYPE_CANCELED: A task was canceled. + * @GST_PROGRESS_TYPE_ERROR: A task caused an error. An error message is also + * posted on the bus. + * + * The type of a %GST_MESSAGE_PROGRESS. The progress messages inform the + * application of the status of asynchronous tasks. + */ +typedef enum { + GST_PROGRESS_TYPE_START = 0, + GST_PROGRESS_TYPE_CONTINUE = 1, + GST_PROGRESS_TYPE_COMPLETE = 2, + GST_PROGRESS_TYPE_CANCELED = 3, + GST_PROGRESS_TYPE_ERROR = 4 +} GstProgressType; + +/** + * GstMessage: + * @mini_object: the parent structure + * @type: the #GstMessageType of the message + * @timestamp: the timestamp of the message + * @src: the src of the message + * @seqnum: the sequence number of the message + * + * A #GstMessage. + */ +struct _GstMessage +{ + GstMiniObject mini_object; + + /*< public > *//* with COW */ + GstMessageType type; + guint64 timestamp; + GstObject *src; + guint32 seqnum; + + /*< private >*//* with MESSAGE_LOCK */ + GMutex lock; /* lock and cond for async delivery */ + GCond cond; +}; + +#include + +GST_API +GType gst_message_get_type (void); + +GST_API +const gchar* gst_message_type_get_name (GstMessageType type); + +GST_API +GQuark gst_message_type_to_quark (GstMessageType type); + +/* refcounting */ +/** + * gst_message_ref: + * @msg: the message to ref + * + * Convenience macro to increase the reference count of the message. + * + * Returns: @msg (for convenience when doing assignments) + */ +static inline GstMessage * +gst_message_ref (GstMessage * msg) +{ + return (GstMessage *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (msg)); +} + +/** + * gst_message_unref: + * @msg: the message to unref + * + * Convenience macro to decrease the reference count of the message, possibly + * freeing it. + */ +static inline void +gst_message_unref (GstMessage * msg) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (msg)); +} + +/* copy message */ +/** + * gst_message_copy: + * @msg: the message to copy + * + * Creates a copy of the message. Returns a copy of the message. + * + * Returns: (transfer full): a new copy of @msg. + * + * MT safe + */ +static inline GstMessage * +gst_message_copy (const GstMessage * msg) +{ + return GST_MESSAGE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (msg))); +} + +/** + * gst_message_is_writable: + * @msg: a #GstMessage + * + * Tests if you can safely write into a message's structure or validly + * modify the seqnum and timestamp fields. + */ +#define gst_message_is_writable(msg) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (msg)) +/** + * gst_message_make_writable: + * @msg: (transfer full): the message to make writable + * + * Checks if a message is writable. If not, a writable copy is made and + * returned. + * + * Returns: (transfer full): a message (possibly a duplicate) that is writable. + * + * MT safe + */ +#define gst_message_make_writable(msg) GST_MESSAGE_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (msg))) +/** + * gst_message_replace: + * @old_message: (inout) (transfer full) (nullable): pointer to a + * pointer to a #GstMessage to be replaced. + * @new_message: (allow-none) (transfer none): pointer to a #GstMessage that will + * replace the message pointed to by @old_message. + * + * Modifies a pointer to a #GstMessage to point to a different #GstMessage. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * message is unreffed, the new one is reffed). + * + * Either @new_message or the #GstMessage pointed to by @old_message may be %NULL. + * + * Returns: %TRUE if @new_message was different from @old_message + */ +static inline gboolean +gst_message_replace (GstMessage **old_message, GstMessage *new_message) +{ + return gst_mini_object_replace ((GstMiniObject **) old_message, (GstMiniObject *) new_message); +} + + +/* custom messages */ + +GST_API +GstMessage * gst_message_new_custom (GstMessageType type, + GstObject * src, + GstStructure * structure) G_GNUC_MALLOC; +GST_API +const GstStructure * + gst_message_get_structure (GstMessage *message); + +GST_API +GstStructure * gst_message_writable_structure (GstMessage *message); + +GST_API +gboolean gst_message_has_name (GstMessage *message, const gchar *name); + +/* identifiers for events and messages */ + +GST_API +guint32 gst_message_get_seqnum (GstMessage *message); + +GST_API +void gst_message_set_seqnum (GstMessage *message, guint32 seqnum); + +/* EOS */ + +GST_API +GstMessage * gst_message_new_eos (GstObject * src) G_GNUC_MALLOC; + +/* ERROR */ + +GST_API +GstMessage * gst_message_new_error (GstObject * src, GError * error, const gchar * debug) G_GNUC_MALLOC; + +GST_API +GstMessage * gst_message_new_error_with_details (GstObject * src, GError * error, const gchar * debug, GstStructure * details) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_error (GstMessage *message, GError **gerror, gchar **debug); + +GST_API +void gst_message_parse_error_details (GstMessage *message, const GstStructure **structure); + +/* WARNING */ + +GST_API +GstMessage * gst_message_new_warning (GstObject * src, GError * error, const gchar * debug) G_GNUC_MALLOC; + +GST_API +GstMessage * gst_message_new_warning_with_details (GstObject * src, GError * error, const gchar * debug, GstStructure * details) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_warning (GstMessage *message, GError **gerror, gchar **debug); + +GST_API +void gst_message_parse_warning_details (GstMessage *message, const GstStructure **structure); + +/* INFO */ + +GST_API +GstMessage * gst_message_new_info (GstObject * src, GError * error, const gchar * debug) G_GNUC_MALLOC; + +GST_API +GstMessage * gst_message_new_info_with_details (GstObject * src, GError * error, const gchar * debug, GstStructure * details) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_info (GstMessage *message, GError **gerror, gchar **debug); + +GST_API +void gst_message_parse_info_details (GstMessage *message, const GstStructure **structure); + +/* TAG */ + +GST_API +GstMessage * gst_message_new_tag (GstObject * src, GstTagList * tag_list) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_tag (GstMessage *message, GstTagList **tag_list); + +/* BUFFERING */ + +GST_API +GstMessage * gst_message_new_buffering (GstObject * src, gint percent) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_buffering (GstMessage *message, gint *percent); + +GST_API +void gst_message_set_buffering_stats (GstMessage *message, GstBufferingMode mode, + gint avg_in, gint avg_out, + gint64 buffering_left); +GST_API +void gst_message_parse_buffering_stats (GstMessage *message, GstBufferingMode *mode, + gint *avg_in, gint *avg_out, + gint64 *buffering_left); + +/* STATE_CHANGED */ + +GST_API +GstMessage * gst_message_new_state_changed (GstObject * src, GstState oldstate, + GstState newstate, GstState pending) G_GNUC_MALLOC; +GST_API +void gst_message_parse_state_changed (GstMessage *message, GstState *oldstate, + GstState *newstate, GstState *pending); + +/* STATE_DIRTY */ + +GST_API +GstMessage * gst_message_new_state_dirty (GstObject * src) G_GNUC_MALLOC; + +/* STEP_DONE */ + +GST_API +GstMessage * gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount, + gdouble rate, gboolean flush, gboolean intermediate, + guint64 duration, gboolean eos) G_GNUC_MALLOC; +GST_API +void gst_message_parse_step_done (GstMessage * message, GstFormat *format, guint64 *amount, + gdouble *rate, gboolean *flush, gboolean *intermediate, + guint64 *duration, gboolean *eos); +/* CLOCK_PROVIDE */ + +GST_API +GstMessage * gst_message_new_clock_provide (GstObject * src, GstClock *clock, gboolean ready) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_clock_provide (GstMessage *message, GstClock **clock, + gboolean *ready); + +/* CLOCK_LOST */ + +GST_API +GstMessage * gst_message_new_clock_lost (GstObject * src, GstClock *clock) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_clock_lost (GstMessage *message, GstClock **clock); + +/* NEW_CLOCK */ + +GST_API +GstMessage * gst_message_new_new_clock (GstObject * src, GstClock *clock) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_new_clock (GstMessage *message, GstClock **clock); + +/* APPLICATION */ + +GST_API +GstMessage * gst_message_new_application (GstObject * src, GstStructure * structure) G_GNUC_MALLOC; + +/* ELEMENT */ + +GST_API +GstMessage * gst_message_new_element (GstObject * src, GstStructure * structure) G_GNUC_MALLOC; + +/* SEGMENT_START */ + +GST_API +GstMessage * gst_message_new_segment_start (GstObject * src, GstFormat format, gint64 position) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_segment_start (GstMessage *message, GstFormat *format, + gint64 *position); + +/* SEGMENT_DONE */ + +GST_API +GstMessage * gst_message_new_segment_done (GstObject * src, GstFormat format, gint64 position) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_segment_done (GstMessage *message, GstFormat *format, + gint64 *position); + +/* DURATION_CHANGED */ + +GST_API +GstMessage * gst_message_new_duration_changed (GstObject * src) G_GNUC_MALLOC; + +/* LATENCY */ + +GST_API +GstMessage * gst_message_new_latency (GstObject * src) G_GNUC_MALLOC; + +/* ASYNC_START */ + +GST_API +GstMessage * gst_message_new_async_start (GstObject * src) G_GNUC_MALLOC; + +/* ASYNC_DONE */ + +GST_API +GstMessage * gst_message_new_async_done (GstObject * src, GstClockTime running_time) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_async_done (GstMessage *message, GstClockTime *running_time); + +/* STRUCTURE CHANGE */ + +GST_API +GstMessage * gst_message_new_structure_change (GstObject * src, GstStructureChangeType type, + GstElement *owner, gboolean busy) G_GNUC_MALLOC; +GST_API +void gst_message_parse_structure_change (GstMessage *message, GstStructureChangeType *type, + GstElement **owner, gboolean *busy); + +/* STREAM STATUS */ + +GST_API +GstMessage * gst_message_new_stream_status (GstObject * src, GstStreamStatusType type, + GstElement *owner) G_GNUC_MALLOC; +GST_API +void gst_message_parse_stream_status (GstMessage *message, GstStreamStatusType *type, + GstElement **owner); +GST_API +void gst_message_set_stream_status_object (GstMessage *message, const GValue *object); + +GST_API +const GValue * gst_message_get_stream_status_object (GstMessage *message); + +/* REQUEST_STATE */ + +GST_API +GstMessage * gst_message_new_request_state (GstObject * src, GstState state) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_request_state (GstMessage * message, GstState *state); + +/* STEP_START */ + +GST_API +GstMessage * gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format, + guint64 amount, gdouble rate, gboolean flush, + gboolean intermediate) G_GNUC_MALLOC; +GST_API +void gst_message_parse_step_start (GstMessage * message, gboolean *active, GstFormat *format, + guint64 *amount, gdouble *rate, gboolean *flush, + gboolean *intermediate); + +/* QOS */ + +GST_API +GstMessage * gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time, + guint64 stream_time, guint64 timestamp, guint64 duration) G_GNUC_MALLOC; +GST_API +void gst_message_set_qos_values (GstMessage * message, gint64 jitter, gdouble proportion, + gint quality); +GST_API +void gst_message_set_qos_stats (GstMessage * message, GstFormat format, guint64 processed, + guint64 dropped); +GST_API +void gst_message_parse_qos (GstMessage * message, gboolean * live, guint64 * running_time, + guint64 * stream_time, guint64 * timestamp, guint64 * duration); +GST_API +void gst_message_parse_qos_values (GstMessage * message, gint64 * jitter, gdouble * proportion, + gint * quality); +GST_API +void gst_message_parse_qos_stats (GstMessage * message, GstFormat * format, guint64 * processed, + guint64 * dropped); +/* PROGRESS */ + +GST_API +GstMessage * gst_message_new_progress (GstObject * src, GstProgressType type, const gchar *code, + const gchar *text) G_GNUC_MALLOC; +GST_API +void gst_message_parse_progress (GstMessage * message, GstProgressType * type, gchar ** code, + gchar ** text); + +/* TOC */ + +GST_API +GstMessage * gst_message_new_toc (GstObject *src, GstToc *toc, gboolean updated); + +GST_API +void gst_message_parse_toc (GstMessage *message, GstToc **toc, gboolean *updated); + +/* RESET_TIME */ + +GST_API +GstMessage * gst_message_new_reset_time (GstObject * src, GstClockTime running_time) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_reset_time (GstMessage *message, GstClockTime *running_time); + +/* STREAM_START */ + +GST_API +GstMessage * gst_message_new_stream_start (GstObject * src) G_GNUC_MALLOC; + +GST_API +void gst_message_set_group_id (GstMessage *message, guint group_id); + +GST_API +gboolean gst_message_parse_group_id (GstMessage *message, guint *group_id); + +/* NEED_CONTEXT */ + +GST_API +GstMessage * gst_message_new_need_context (GstObject * src, const gchar * context_type) G_GNUC_MALLOC; + +GST_API +gboolean gst_message_parse_context_type (GstMessage * message, const gchar ** context_type); + +/* HAVE_CONTEXT */ + +GST_API +GstMessage * gst_message_new_have_context (GstObject * src, GstContext *context) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_have_context (GstMessage *message, GstContext **context); + +/* DEVICE_ADDED */ + +GST_API +GstMessage * gst_message_new_device_added (GstObject * src, GstDevice * device) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_device_added (GstMessage * message, GstDevice ** device); + +/* DEVICE_REMOVED */ + +GST_API +GstMessage * gst_message_new_device_removed (GstObject * src, GstDevice * device) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_device_removed (GstMessage * message, GstDevice ** device); + +/* PROPERTY_NOTIFY */ + +GST_API +GstMessage * gst_message_new_property_notify (GstObject * src, const gchar * property_name, GValue * val) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_property_notify (GstMessage * message, GstObject ** object, const gchar ** property_name, const GValue ** property_value); + +/* STREAM_COLLECTION */ + +GST_API +GstMessage * gst_message_new_stream_collection (GstObject * src, GstStreamCollection * collection) G_GNUC_MALLOC; + +GST_API +void gst_message_parse_stream_collection (GstMessage *message, GstStreamCollection **collection); + +/* STREAMS_SELECTED */ + +GST_API +GstMessage * gst_message_new_streams_selected (GstObject *src, GstStreamCollection *collection); + +GST_API +void gst_message_streams_selected_add (GstMessage *message, GstStream *stream); + +GST_API +void gst_message_parse_streams_selected (GstMessage * message, GstStreamCollection **collection); + +GST_API +guint gst_message_streams_selected_get_size (GstMessage * message); + +GST_API +GstStream *gst_message_streams_selected_get_stream (GstMessage *message, guint idx); + +/* REDIRECT */ + +GST_API +GstMessage * gst_message_new_redirect (GstObject * src, const gchar * location, GstTagList * tag_list, const GstStructure * entry_struct) G_GNUC_MALLOC; + +GST_API +void gst_message_add_redirect_entry (GstMessage * message, const gchar * location, GstTagList * tag_list, const GstStructure * entry_struct); + +GST_API +void gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index, const gchar ** location, GstTagList ** tag_list, const GstStructure ** entry_struct); + +GST_API +gsize gst_message_get_num_redirect_entries (GstMessage * message); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMessage, gst_message_unref) +#endif + +G_END_DECLS + +#endif /* __GST_MESSAGE_H__ */ diff --git a/gst/gstmeta.c b/gst/gstmeta.c new file mode 100644 index 0000000..84d9838 --- /dev/null +++ b/gst/gstmeta.c @@ -0,0 +1,229 @@ +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstmeta.c: metadata operations + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstmeta + * @title: GstMeta + * @short_description: Buffer metadata + * + * The #GstMeta structure should be included as the first member of a #GstBuffer + * metadata structure. The structure defines the API of the metadata and should + * be accessible to all elements using the metadata. + * + * A metadata API is registered with gst_meta_api_type_register() which takes a + * name for the metadata API and some tags associated with the metadata. + * With gst_meta_api_type_has_tag() one can check if a certain metadata API + * contains a given tag. + * + * Multiple implementations of a metadata API can be registered. + * To implement a metadata API, gst_meta_register() should be used. This + * function takes all parameters needed to create, free and transform metadata + * along with the size of the metadata. The function returns a #GstMetaInfo + * structure that contains the information for the implementation of the API. + * + * A specific implementation can be retrieved by name with gst_meta_get_info(). + * + * See #GstBuffer for how the metadata can be added, retrieved and removed from + * buffers. + */ +#include "gst_private.h" + +#include "gstbuffer.h" +#include "gstmeta.h" +#include "gstinfo.h" +#include "gstutils.h" + +static GHashTable *metainfo = NULL; +static GRWLock lock; + +GQuark _gst_meta_transform_copy; +GQuark _gst_meta_tag_memory; + +void +_priv_gst_meta_initialize (void) +{ + g_rw_lock_init (&lock); + metainfo = g_hash_table_new (g_str_hash, g_str_equal); + + _gst_meta_transform_copy = g_quark_from_static_string ("gst-copy"); + _gst_meta_tag_memory = g_quark_from_static_string ("memory"); +} + +/** + * gst_meta_api_type_register: + * @api: an API to register + * @tags: tags for @api + * + * Register and return a GType for the @api and associate it with + * @tags. + * + * Returns: a unique GType for @api. + */ +GType +gst_meta_api_type_register (const gchar * api, const gchar ** tags) +{ + GType type; + + g_return_val_if_fail (api != NULL, 0); + g_return_val_if_fail (tags != NULL, 0); + + GST_CAT_DEBUG (GST_CAT_META, "register API \"%s\"", api); + type = g_pointer_type_register_static (api); + + if (type != 0) { + gint i; + + for (i = 0; tags[i]; i++) { + GST_CAT_DEBUG (GST_CAT_META, " adding tag \"%s\"", tags[i]); + g_type_set_qdata (type, g_quark_from_string (tags[i]), + GINT_TO_POINTER (TRUE)); + } + } + + g_type_set_qdata (type, g_quark_from_string ("tags"), + g_strdupv ((gchar **) tags)); + + return type; +} + +/** + * gst_meta_api_type_has_tag: + * @api: an API + * @tag: the tag to check + * + * Check if @api was registered with @tag. + * + * Returns: %TRUE if @api was registered with @tag. + */ +gboolean +gst_meta_api_type_has_tag (GType api, GQuark tag) +{ + g_return_val_if_fail (api != 0, FALSE); + g_return_val_if_fail (tag != 0, FALSE); + + return g_type_get_qdata (api, tag) != NULL; +} + +/** + * gst_meta_api_type_get_tags: + * @api: an API + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): an array of tags as strings. + * + * Since: 1.2 + */ +const gchar *const * +gst_meta_api_type_get_tags (GType api) +{ + const gchar **tags; + g_return_val_if_fail (api != 0, FALSE); + + tags = g_type_get_qdata (api, g_quark_from_string ("tags")); + + if (!tags[0]) + return NULL; + + return (const gchar * const *) tags; +} + +/** + * gst_meta_register: + * @api: the type of the #GstMeta API + * @impl: the name of the #GstMeta implementation + * @size: the size of the #GstMeta structure + * @init_func: (scope async): a #GstMetaInitFunction + * @free_func: (scope async): a #GstMetaFreeFunction + * @transform_func: (scope async): a #GstMetaTransformFunction + * + * Register a new #GstMeta implementation. + * + * The same @info can be retrieved later with gst_meta_get_info() by using + * @impl as the key. + * + * Returns: (transfer none) (nullable): a #GstMetaInfo that can be used to + * access metadata. + */ + +const GstMetaInfo * +gst_meta_register (GType api, const gchar * impl, gsize size, + GstMetaInitFunction init_func, GstMetaFreeFunction free_func, + GstMetaTransformFunction transform_func) +{ + GstMetaInfo *info; + GType type; + + g_return_val_if_fail (api != 0, NULL); + g_return_val_if_fail (impl != NULL, NULL); + g_return_val_if_fail (size != 0, NULL); + + if (init_func == NULL) + g_critical ("Registering meta implementation '%s' without init function", + impl); + + /* first try to register the implementation name. It's possible + * that this fails because it was already registered. Don't warn, + * glib did this for us already. */ + type = g_pointer_type_register_static (impl); + if (type == 0) + return NULL; + + info = g_slice_new (GstMetaInfo); + info->api = api; + info->type = type; + info->size = size; + info->init_func = init_func; + info->free_func = free_func; + info->transform_func = transform_func; + + GST_CAT_DEBUG (GST_CAT_META, + "register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, impl, + g_type_name (api), size); + + g_rw_lock_writer_lock (&lock); + g_hash_table_insert (metainfo, (gpointer) impl, (gpointer) info); + g_rw_lock_writer_unlock (&lock); + + return info; +} + +/** + * gst_meta_get_info: + * @impl: the name + * + * Lookup a previously registered meta info structure by its implementation name + * @impl. + * + * Returns: (transfer none) (nullable): a #GstMetaInfo with @impl, or + * %NULL when no such metainfo exists. + */ +const GstMetaInfo * +gst_meta_get_info (const gchar * impl) +{ + GstMetaInfo *info; + + g_return_val_if_fail (impl != NULL, NULL); + + g_rw_lock_reader_lock (&lock); + info = g_hash_table_lookup (metainfo, impl); + g_rw_lock_reader_unlock (&lock); + + return info; +} diff --git a/gst/gstmeta.h b/gst/gstmeta.h new file mode 100644 index 0000000..60268f8 --- /dev/null +++ b/gst/gstmeta.h @@ -0,0 +1,244 @@ +/* GStreamer + * Copyright (C) 2009 Wim Taymans + * + * gstmeta.h: Header for Metadata structures + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_META_H__ +#define __GST_META_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstMeta GstMeta; +typedef struct _GstMetaInfo GstMetaInfo; + +#define GST_META_CAST(meta) ((GstMeta *)(meta)) + +/** + * GstMetaFlags: + * @GST_META_FLAG_NONE: no flags + * @GST_META_FLAG_READONLY: metadata should not be modified + * @GST_META_FLAG_POOLED: metadata is managed by a bufferpool + * @GST_META_FLAG_LOCKED: metadata should not be removed + * @GST_META_FLAG_LAST: additional flags can be added starting from this flag. + * + * Extra metadata flags. + */ +typedef enum { + GST_META_FLAG_NONE = 0, + GST_META_FLAG_READONLY = (1 << 0), + GST_META_FLAG_POOLED = (1 << 1), + GST_META_FLAG_LOCKED = (1 << 2), + + GST_META_FLAG_LAST = (1 << 16) +} GstMetaFlags; + +/** + * GST_META_FLAGS: + * @meta: a #GstMeta. + * + * A flags word containing #GstMetaFlags flags set on @meta + */ +#define GST_META_FLAGS(meta) (GST_META_CAST (meta)->flags) +/** + * GST_META_FLAG_IS_SET: + * @meta: a #GstMeta. + * @flag: the #GstMetaFlags to check. + * + * Gives the status of a specific flag on a metadata. + */ +#define GST_META_FLAG_IS_SET(meta,flag) !!(GST_META_FLAGS (meta) & (flag)) +/** + * GST_META_FLAG_SET: + * @meta: a #GstMeta. + * @flag: the #GstMetaFlags to set. + * + * Sets a metadata flag on a metadata. + */ +#define GST_META_FLAG_SET(meta,flag) (GST_META_FLAGS (meta) |= (flag)) +/** + * GST_META_FLAG_UNSET: + * @meta: a #GstMeta. + * @flag: the #GstMetaFlags to clear. + * + * Clears a metadata flag. + */ +#define GST_META_FLAG_UNSET(meta,flag) (GST_META_FLAGS (meta) &= ~(flag)) + +/** + * GST_META_TAG_MEMORY_STR: + * + * This metadata stays relevant as long as memory layout is unchanged. + * + * Since: 1.2 + */ +#define GST_META_TAG_MEMORY_STR "memory" + +/** + * GstMeta: + * @flags: extra flags for the metadata + * @info: pointer to the #GstMetaInfo + * + * Base structure for metadata. Custom metadata will put this structure + * as the first member of their structure. + */ +struct _GstMeta { + GstMetaFlags flags; + const GstMetaInfo *info; +}; + +#include + +/** + * GstMetaInitFunction: + * @meta: a #GstMeta + * @params: parameters passed to the init function + * @buffer: a #GstBuffer + * + * Function called when @meta is initialized in @buffer. + */ +typedef gboolean (*GstMetaInitFunction) (GstMeta *meta, gpointer params, GstBuffer *buffer); + +/** + * GstMetaFreeFunction: + * @meta: a #GstMeta + * @buffer: a #GstBuffer + * + * Function called when @meta is freed in @buffer. + */ +typedef void (*GstMetaFreeFunction) (GstMeta *meta, GstBuffer *buffer); + +/** + * gst_meta_transform_copy: + * + * GQuark for the "gst-copy" transform. + */ + +GST_API GQuark _gst_meta_transform_copy; + +/** + * GST_META_TRANSFORM_IS_COPY: + * @type: a transform type + * + * Check if the transform type is a copy transform + */ +#define GST_META_TRANSFORM_IS_COPY(type) ((type) == _gst_meta_transform_copy) + +/** + * GstMetaTransformCopy: + * @region: %TRUE if only region is copied + * @offset: the offset to copy, 0 if @region is %FALSE, otherwise > 0 + * @size: the size to copy, -1 or the buffer size when @region is %FALSE + * + * Extra data passed to a "gst-copy" transform #GstMetaTransformFunction. + */ +typedef struct { + gboolean region; + gsize offset; + gsize size; +} GstMetaTransformCopy; + +/** + * GstMetaTransformFunction: + * @transbuf: a #GstBuffer + * @meta: a #GstMeta + * @buffer: a #GstBuffer + * @type: the transform type + * @data: transform specific data. + * + * Function called for each @meta in @buffer as a result of performing a + * transformation on @transbuf. Additional @type specific transform data + * is passed to the function as @data. + * + * Implementations should check the @type of the transform and parse + * additional type specific fields in @data that should be used to update + * the metadata on @transbuf. + * + * Returns: %TRUE if the transform could be performed + */ +typedef gboolean (*GstMetaTransformFunction) (GstBuffer *transbuf, + GstMeta *meta, GstBuffer *buffer, + GQuark type, gpointer data); + +/** + * GstMetaInfo: + * @api: tag identifying the metadata structure and api + * @type: type identifying the implementor of the api + * @size: size of the metadata + * @init_func: function for initializing the metadata + * @free_func: function for freeing the metadata + * @transform_func: function for transforming the metadata + * + * The #GstMetaInfo provides information about a specific metadata + * structure. + */ +struct _GstMetaInfo { + GType api; + GType type; + gsize size; + + GstMetaInitFunction init_func; + GstMetaFreeFunction free_func; + GstMetaTransformFunction transform_func; + + /* No padding needed, GstMetaInfo is always allocated by GStreamer and is + * not subclassable or stack-allocatable, so we can extend it as we please + * just like interfaces */ +}; + +GST_API +GType gst_meta_api_type_register (const gchar *api, + const gchar **tags); +GST_API +gboolean gst_meta_api_type_has_tag (GType api, GQuark tag); + +GST_API +const GstMetaInfo * gst_meta_register (GType api, const gchar *impl, + gsize size, + GstMetaInitFunction init_func, + GstMetaFreeFunction free_func, + GstMetaTransformFunction transform_func); +GST_API +const GstMetaInfo * gst_meta_get_info (const gchar * impl); + +GST_API +const gchar* const* gst_meta_api_type_get_tags (GType api); + +/* some default tags */ + +GST_API GQuark _gst_meta_tag_memory; + +/** + * GST_META_TAG_MEMORY: + * + * Metadata tagged with this tag depends on the particular memory + * or buffer that it is on. + * + * Deprecated: The GQuarks are not exported by any public API, use + * GST_META_TAG_MEMORY_STR instead. + */ +#ifndef GST_DISABLE_DEPRECATED +#define GST_META_TAG_MEMORY (_gst_meta_tag_memory) +#endif + +G_END_DECLS + +#endif /* __GST_META_H__ */ diff --git a/gst/gstminiobject.c b/gst/gstminiobject.c new file mode 100644 index 0000000..b047f98 --- /dev/null +++ b/gst/gstminiobject.c @@ -0,0 +1,749 @@ +/* GStreamer + * Copyright (C) 2005 David Schleef + * + * gstminiobject.h: Header for GstMiniObject + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstminiobject + * @title: GstMiniObject + * @short_description: Lightweight base class for the GStreamer object hierarchy + * + * #GstMiniObject is a simple structure that can be used to implement refcounted + * types. + * + * Subclasses will include #GstMiniObject as the first member in their structure + * and then call gst_mini_object_init() to initialize the #GstMiniObject fields. + * + * gst_mini_object_ref() and gst_mini_object_unref() increment and decrement the + * refcount respectively. When the refcount of a mini-object reaches 0, the + * dispose function is called first and when this returns %TRUE, the free + * function of the miniobject is called. + * + * A copy can be made with gst_mini_object_copy(). + * + * gst_mini_object_is_writable() will return %TRUE when the refcount of the + * object is exactly 1, meaning the current caller has the only reference to the + * object. gst_mini_object_make_writable() will return a writable version of the + * object, which might be a new copy when the refcount was not 1. + * + * Opaque data can be associated with a #GstMiniObject with + * gst_mini_object_set_qdata() and gst_mini_object_get_qdata(). The data is + * meant to be specific to the particular object and is not automatically copied + * with gst_mini_object_copy() or similar methods. + * + * A weak reference can be added and remove with gst_mini_object_weak_ref() + * and gst_mini_object_weak_unref() respectively. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst/gst_private.h" +#include "gst/gstminiobject.h" +#include "gst/gstinfo.h" +#include + +/* Mutex used for weak referencing */ +G_LOCK_DEFINE_STATIC (qdata_mutex); +static GQuark weak_ref_quark; + +#define SHARE_ONE (1 << 16) +#define SHARE_TWO (2 << 16) +#define SHARE_MASK (~(SHARE_ONE - 1)) +#define IS_SHARED(state) (state >= SHARE_TWO) +#define LOCK_ONE (GST_LOCK_FLAG_LAST) +#define FLAG_MASK (GST_LOCK_FLAG_LAST - 1) +#define LOCK_MASK ((SHARE_ONE - 1) - FLAG_MASK) +#define LOCK_FLAG_MASK (SHARE_ONE - 1) + +typedef struct +{ + GQuark quark; + GstMiniObjectNotify notify; + gpointer data; + GDestroyNotify destroy; +} GstQData; + +#define QDATA(o,i) ((GstQData *)(o)->qdata)[(i)] +#define QDATA_QUARK(o,i) (QDATA(o,i).quark) +#define QDATA_NOTIFY(o,i) (QDATA(o,i).notify) +#define QDATA_DATA(o,i) (QDATA(o,i).data) +#define QDATA_DESTROY(o,i) (QDATA(o,i).destroy) + +void +_priv_gst_mini_object_initialize (void) +{ + weak_ref_quark = g_quark_from_static_string ("GstMiniObjectWeakRefQuark"); +} + +/** + * gst_mini_object_init: (skip) + * @mini_object: a #GstMiniObject + * @flags: initial #GstMiniObjectFlags + * @type: the #GType of the mini-object to create + * @copy_func: (allow-none): the copy function, or %NULL + * @dispose_func: (allow-none): the dispose function, or %NULL + * @free_func: (allow-none): the free function or %NULL + * + * Initializes a mini-object with the desired type and copy/dispose/free + * functions. + */ +void +gst_mini_object_init (GstMiniObject * mini_object, guint flags, GType type, + GstMiniObjectCopyFunction copy_func, + GstMiniObjectDisposeFunction dispose_func, + GstMiniObjectFreeFunction free_func) +{ + mini_object->type = type; + mini_object->refcount = 1; + mini_object->lockstate = 0; + mini_object->flags = flags; + + mini_object->copy = copy_func; + mini_object->dispose = dispose_func; + mini_object->free = free_func; + + mini_object->n_qdata = 0; + mini_object->qdata = NULL; + + GST_TRACER_MINI_OBJECT_CREATED (mini_object); +} + +/** + * gst_mini_object_copy: (skip) + * @mini_object: the mini-object to copy + * + * Creates a copy of the mini-object. + * + * MT safe + * + * Returns: (transfer full) (nullable): the new mini-object if copying is + * possible, %NULL otherwise. + */ +GstMiniObject * +gst_mini_object_copy (const GstMiniObject * mini_object) +{ + GstMiniObject *copy; + + g_return_val_if_fail (mini_object != NULL, NULL); + + if (mini_object->copy) + copy = mini_object->copy (mini_object); + else + copy = NULL; + + return copy; +} + +/** + * gst_mini_object_lock: + * @object: the mini-object to lock + * @flags: #GstLockFlags + * + * Lock the mini-object with the specified access mode in @flags. + * + * Returns: %TRUE if @object could be locked. + */ +gboolean +gst_mini_object_lock (GstMiniObject * object, GstLockFlags flags) +{ + gint access_mode, state, newstate; + + g_return_val_if_fail (object != NULL, FALSE); + g_return_val_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object), FALSE); + + if (G_UNLIKELY (object->flags & GST_MINI_OBJECT_FLAG_LOCK_READONLY && + flags & GST_LOCK_FLAG_WRITE)) + return FALSE; + + do { + access_mode = flags & FLAG_MASK; + newstate = state = g_atomic_int_get (&object->lockstate); + + GST_CAT_TRACE (GST_CAT_LOCKING, "lock %p: state %08x, access_mode %d", + object, state, access_mode); + + if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) { + /* shared ref */ + newstate += SHARE_ONE; + access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE; + } + + /* shared counter > 1 and write access is not allowed */ + if (((state & GST_LOCK_FLAG_WRITE) != 0 + || (access_mode & GST_LOCK_FLAG_WRITE) != 0) + && IS_SHARED (newstate)) + goto lock_failed; + + if (access_mode) { + if ((state & LOCK_FLAG_MASK) == 0) { + /* nothing mapped, set access_mode */ + newstate |= access_mode; + } else { + /* access_mode must match */ + if ((state & access_mode) != access_mode) + goto lock_failed; + } + /* increase refcount */ + newstate += LOCK_ONE; + } + } while (!g_atomic_int_compare_and_exchange (&object->lockstate, state, + newstate)); + + return TRUE; + +lock_failed: + { + GST_CAT_DEBUG (GST_CAT_LOCKING, + "lock failed %p: state %08x, access_mode %d", object, state, + access_mode); + return FALSE; + } +} + +/** + * gst_mini_object_unlock: + * @object: the mini-object to unlock + * @flags: #GstLockFlags + * + * Unlock the mini-object with the specified access mode in @flags. + */ +void +gst_mini_object_unlock (GstMiniObject * object, GstLockFlags flags) +{ + gint access_mode, state, newstate; + + g_return_if_fail (object != NULL); + g_return_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object)); + + do { + access_mode = flags & FLAG_MASK; + newstate = state = g_atomic_int_get (&object->lockstate); + + GST_CAT_TRACE (GST_CAT_LOCKING, "unlock %p: state %08x, access_mode %d", + object, state, access_mode); + + if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) { + /* shared counter */ + g_return_if_fail (state >= SHARE_ONE); + newstate -= SHARE_ONE; + access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE; + } + + if (access_mode) { + g_return_if_fail ((state & access_mode) == access_mode); + /* decrease the refcount */ + newstate -= LOCK_ONE; + /* last refcount, unset access_mode */ + if ((newstate & LOCK_FLAG_MASK) == access_mode) + newstate &= ~LOCK_FLAG_MASK; + } + } while (!g_atomic_int_compare_and_exchange (&object->lockstate, state, + newstate)); +} + +/** + * gst_mini_object_is_writable: + * @mini_object: the mini-object to check + * + * If @mini_object has the LOCKABLE flag set, check if the current EXCLUSIVE + * lock on @object is the only one, this means that changes to the object will + * not be visible to any other object. + * + * If the LOCKABLE flag is not set, check if the refcount of @mini_object is + * exactly 1, meaning that no other reference exists to the object and that the + * object is therefore writable. + * + * Modification of a mini-object should only be done after verifying that it + * is writable. + * + * Returns: %TRUE if the object is writable. + */ +gboolean +gst_mini_object_is_writable (const GstMiniObject * mini_object) +{ + gboolean result; + + g_return_val_if_fail (mini_object != NULL, FALSE); + + if (GST_MINI_OBJECT_IS_LOCKABLE (mini_object)) { + result = !IS_SHARED (g_atomic_int_get (&mini_object->lockstate)); + } else { + result = (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1); + } + return result; +} + +/** + * gst_mini_object_make_writable: (skip) + * @mini_object: (transfer full): the mini-object to make writable + * + * Checks if a mini-object is writable. If not, a writable copy is made and + * returned. This gives away the reference to the original mini object, + * and returns a reference to the new object. + * + * MT safe + * + * Returns: (transfer full): a mini-object (possibly the same pointer) that + * is writable. + */ +GstMiniObject * +gst_mini_object_make_writable (GstMiniObject * mini_object) +{ + GstMiniObject *ret; + + g_return_val_if_fail (mini_object != NULL, NULL); + + if (gst_mini_object_is_writable (mini_object)) { + ret = mini_object; + } else { + ret = gst_mini_object_copy (mini_object); + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy %s miniobject %p -> %p", + g_type_name (GST_MINI_OBJECT_TYPE (mini_object)), mini_object, ret); + gst_mini_object_unref (mini_object); + } + + return ret; +} + +/** + * gst_mini_object_ref: (skip) + * @mini_object: the mini-object + * + * Increase the reference count of the mini-object. + * + * Note that the refcount affects the writability + * of @mini-object, see gst_mini_object_is_writable(). It is + * important to note that keeping additional references to + * GstMiniObject instances can potentially increase the number + * of memcpy operations in a pipeline, especially if the miniobject + * is a #GstBuffer. + * + * Returns: (transfer full): the mini-object. + */ +GstMiniObject * +gst_mini_object_ref (GstMiniObject * mini_object) +{ + gint old_refcount, new_refcount; + + g_return_val_if_fail (mini_object != NULL, NULL); + /* we can't assert that the refcount > 0 since the _free functions + * increments the refcount from 0 to 1 again to allow resurecting + * the object + g_return_val_if_fail (mini_object->refcount > 0, NULL); + */ + + old_refcount = g_atomic_int_add (&mini_object->refcount, 1); + new_refcount = old_refcount + 1; + + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object, + old_refcount, new_refcount); + + GST_TRACER_MINI_OBJECT_REFFED (mini_object, new_refcount); + + return mini_object; +} + +static gint +find_notify (GstMiniObject * object, GQuark quark, gboolean match_notify, + GstMiniObjectNotify notify, gpointer data) +{ + guint i; + + for (i = 0; i < object->n_qdata; i++) { + if (QDATA_QUARK (object, i) == quark) { + /* check if we need to match the callback too */ + if (!match_notify || (QDATA_NOTIFY (object, i) == notify && + QDATA_DATA (object, i) == data)) + return i; + } + } + return -1; +} + +static void +remove_notify (GstMiniObject * object, gint index) +{ + /* remove item */ + if (--object->n_qdata == 0) { + /* we don't shrink but free when everything is gone */ + g_free (object->qdata); + object->qdata = NULL; + } else if (index != object->n_qdata) + QDATA (object, index) = QDATA (object, object->n_qdata); +} + +static void +set_notify (GstMiniObject * object, gint index, GQuark quark, + GstMiniObjectNotify notify, gpointer data, GDestroyNotify destroy) +{ + if (index == -1) { + /* add item */ + index = object->n_qdata++; + object->qdata = + g_realloc (object->qdata, sizeof (GstQData) * object->n_qdata); + } + QDATA_QUARK (object, index) = quark; + QDATA_NOTIFY (object, index) = notify; + QDATA_DATA (object, index) = data; + QDATA_DESTROY (object, index) = destroy; +} + +static void +call_finalize_notify (GstMiniObject * obj) +{ + guint i; + + for (i = 0; i < obj->n_qdata; i++) { + if (QDATA_QUARK (obj, i) == weak_ref_quark) + QDATA_NOTIFY (obj, i) (QDATA_DATA (obj, i), obj); + if (QDATA_DESTROY (obj, i)) + QDATA_DESTROY (obj, i) (QDATA_DATA (obj, i)); + } +} + +/** + * gst_mini_object_unref: (skip) + * @mini_object: the mini-object + * + * Decreases the reference count of the mini-object, possibly freeing + * the mini-object. + */ +void +gst_mini_object_unref (GstMiniObject * mini_object) +{ + gint old_refcount, new_refcount; + + g_return_if_fail (mini_object != NULL); + g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) > 0); + + old_refcount = g_atomic_int_add (&mini_object->refcount, -1); + new_refcount = old_refcount - 1; + + g_return_if_fail (old_refcount > 0); + + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p unref %d->%d", + mini_object, old_refcount, new_refcount); + + GST_TRACER_MINI_OBJECT_UNREFFED (mini_object, new_refcount); + + if (new_refcount == 0) { + gboolean do_free; + + if (mini_object->dispose) + do_free = mini_object->dispose (mini_object); + else + do_free = TRUE; + + /* if the subclass recycled the object (and returned FALSE) we don't + * want to free the instance anymore */ + if (G_LIKELY (do_free)) { + /* there should be no outstanding locks */ + g_return_if_fail ((g_atomic_int_get (&mini_object->lockstate) & LOCK_MASK) + < 4); + + if (mini_object->n_qdata) { + call_finalize_notify (mini_object); + g_free (mini_object->qdata); + } + GST_TRACER_MINI_OBJECT_DESTROYED (mini_object); + if (mini_object->free) + mini_object->free (mini_object); + } + } +} + +/** + * gst_mini_object_replace: + * @olddata: (inout) (transfer full) (nullable): pointer to a pointer to a + * mini-object to be replaced + * @newdata: (allow-none): pointer to new mini-object + * + * Atomically modifies a pointer to point to a new mini-object. + * The reference count of @olddata is decreased and the reference count of + * @newdata is increased. + * + * Either @newdata and the value pointed to by @olddata may be %NULL. + * + * Returns: %TRUE if @newdata was different from @olddata + */ +gboolean +gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata) +{ + GstMiniObject *olddata_val; + + g_return_val_if_fail (olddata != NULL, FALSE); + + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p (%d) with %p (%d)", + *olddata, *olddata ? (*olddata)->refcount : 0, + newdata, newdata ? newdata->refcount : 0); + + olddata_val = g_atomic_pointer_get ((gpointer *) olddata); + + if (G_UNLIKELY (olddata_val == newdata)) + return FALSE; + + if (newdata) + gst_mini_object_ref (newdata); + + while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *) + olddata, olddata_val, newdata))) { + olddata_val = g_atomic_pointer_get ((gpointer *) olddata); + if (G_UNLIKELY (olddata_val == newdata)) + break; + } + + if (olddata_val) + gst_mini_object_unref (olddata_val); + + return olddata_val != newdata; +} + +/** + * gst_mini_object_steal: (skip) + * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to + * be stolen + * + * Replace the current #GstMiniObject pointer to by @olddata with %NULL and + * return the old value. + * + * Returns: (nullable): the #GstMiniObject at @oldata + */ +GstMiniObject * +gst_mini_object_steal (GstMiniObject ** olddata) +{ + GstMiniObject *olddata_val; + + g_return_val_if_fail (olddata != NULL, NULL); + + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "steal %p (%d)", + *olddata, *olddata ? (*olddata)->refcount : 0); + + do { + olddata_val = g_atomic_pointer_get ((gpointer *) olddata); + if (olddata_val == NULL) + break; + } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *) + olddata, olddata_val, NULL))); + + return olddata_val; +} + +/** + * gst_mini_object_take: + * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to + * be replaced + * @newdata: pointer to new mini-object + * + * Modifies a pointer to point to a new mini-object. The modification + * is done atomically. This version is similar to gst_mini_object_replace() + * except that it does not increase the refcount of @newdata and thus + * takes ownership of @newdata. + * + * Either @newdata and the value pointed to by @olddata may be %NULL. + * + * Returns: %TRUE if @newdata was different from @olddata + */ +gboolean +gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata) +{ + GstMiniObject *olddata_val; + + g_return_val_if_fail (olddata != NULL, FALSE); + + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "take %p (%d) with %p (%d)", + *olddata, *olddata ? (*olddata)->refcount : 0, + newdata, newdata ? newdata->refcount : 0); + + do { + olddata_val = g_atomic_pointer_get ((gpointer *) olddata); + if (G_UNLIKELY (olddata_val == newdata)) + break; + } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *) + olddata, olddata_val, newdata))); + + if (olddata_val) + gst_mini_object_unref (olddata_val); + + return olddata_val != newdata; +} + +/** + * gst_mini_object_weak_ref: (skip) + * @object: #GstMiniObject to reference weakly + * @notify: callback to invoke before the mini object is freed + * @data: extra data to pass to notify + * + * Adds a weak reference callback to a mini object. Weak references are + * used for notification when a mini object is finalized. They are called + * "weak references" because they allow you to safely hold a pointer + * to the mini object without calling gst_mini_object_ref() + * (gst_mini_object_ref() adds a strong reference, that is, forces the object + * to stay alive). + */ +void +gst_mini_object_weak_ref (GstMiniObject * object, + GstMiniObjectNotify notify, gpointer data) +{ + g_return_if_fail (object != NULL); + g_return_if_fail (notify != NULL); + g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1); + + G_LOCK (qdata_mutex); + set_notify (object, -1, weak_ref_quark, notify, data, NULL); + G_UNLOCK (qdata_mutex); +} + +/** + * gst_mini_object_weak_unref: (skip) + * @object: #GstMiniObject to remove a weak reference from + * @notify: callback to search for + * @data: data to search for + * + * Removes a weak reference callback from a mini object. + */ +void +gst_mini_object_weak_unref (GstMiniObject * object, + GstMiniObjectNotify notify, gpointer data) +{ + gint i; + + g_return_if_fail (object != NULL); + g_return_if_fail (notify != NULL); + + G_LOCK (qdata_mutex); + if ((i = find_notify (object, weak_ref_quark, TRUE, notify, data)) != -1) { + remove_notify (object, i); + } else { + g_warning ("%s: couldn't find weak ref %p (object:%p data:%p)", G_STRFUNC, + notify, object, data); + } + G_UNLOCK (qdata_mutex); +} + +/** + * gst_mini_object_set_qdata: + * @object: a #GstMiniObject + * @quark: A #GQuark, naming the user data pointer + * @data: An opaque user data pointer + * @destroy: Function to invoke with @data as argument, when @data + * needs to be freed + * + * This sets an opaque, named pointer on a miniobject. + * The name is specified through a #GQuark (retrieved e.g. via + * g_quark_from_static_string()), and the pointer + * can be gotten back from the @object with gst_mini_object_get_qdata() + * until the @object is disposed. + * Setting a previously set user data pointer, overrides (frees) + * the old pointer set, using %NULL as pointer essentially + * removes the data stored. + * + * @destroy may be specified which is called with @data as argument + * when the @object is disposed, or the data is being overwritten by + * a call to gst_mini_object_set_qdata() with the same @quark. + */ +void +gst_mini_object_set_qdata (GstMiniObject * object, GQuark quark, + gpointer data, GDestroyNotify destroy) +{ + gint i; + gpointer old_data = NULL; + GDestroyNotify old_notify = NULL; + + g_return_if_fail (object != NULL); + g_return_if_fail (quark > 0); + + G_LOCK (qdata_mutex); + if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) { + + old_data = QDATA_DATA (object, i); + old_notify = QDATA_DESTROY (object, i); + + if (data == NULL) + remove_notify (object, i); + } + if (data != NULL) + set_notify (object, i, quark, NULL, data, destroy); + G_UNLOCK (qdata_mutex); + + if (old_notify) + old_notify (old_data); +} + +/** + * gst_mini_object_get_qdata: + * @object: The GstMiniObject to get a stored user data pointer from + * @quark: A #GQuark, naming the user data pointer + * + * This function gets back user data pointers stored via + * gst_mini_object_set_qdata(). + * + * Returns: (transfer none) (nullable): The user data pointer set, or + * %NULL + */ +gpointer +gst_mini_object_get_qdata (GstMiniObject * object, GQuark quark) +{ + guint i; + gpointer result; + + g_return_val_if_fail (object != NULL, NULL); + g_return_val_if_fail (quark > 0, NULL); + + G_LOCK (qdata_mutex); + if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) + result = QDATA_DATA (object, i); + else + result = NULL; + G_UNLOCK (qdata_mutex); + + return result; +} + +/** + * gst_mini_object_steal_qdata: + * @object: The GstMiniObject to get a stored user data pointer from + * @quark: A #GQuark, naming the user data pointer + * + * This function gets back user data pointers stored via gst_mini_object_set_qdata() + * and removes the data from @object without invoking its destroy() function (if + * any was set). + * + * Returns: (transfer full) (nullable): The user data pointer set, or + * %NULL + */ +gpointer +gst_mini_object_steal_qdata (GstMiniObject * object, GQuark quark) +{ + guint i; + gpointer result; + + g_return_val_if_fail (object != NULL, NULL); + g_return_val_if_fail (quark > 0, NULL); + + G_LOCK (qdata_mutex); + if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) { + result = QDATA_DATA (object, i); + remove_notify (object, i); + } else { + result = NULL; + } + G_UNLOCK (qdata_mutex); + + return result; +} diff --git a/gst/gstminiobject.h b/gst/gstminiobject.h new file mode 100644 index 0000000..f7aa87a --- /dev/null +++ b/gst/gstminiobject.h @@ -0,0 +1,299 @@ +/* GStreamer + * Copyright (C) 2005 David Schleef + * + * gstminiobject.h: Header for GstMiniObject + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_MINI_OBJECT_H__ +#define __GST_MINI_OBJECT_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GST_IS_MINI_OBJECT_TYPE(obj,type) ((obj) && GST_MINI_OBJECT_TYPE(obj) == (type)) +#define GST_MINI_OBJECT_CAST(obj) ((GstMiniObject*)(obj)) +#define GST_MINI_OBJECT_CONST_CAST(obj) ((const GstMiniObject*)(obj)) +#define GST_MINI_OBJECT(obj) (GST_MINI_OBJECT_CAST(obj)) + +typedef struct _GstMiniObject GstMiniObject; + +/** + * GstMiniObjectCopyFunction: + * @obj: MiniObject to copy + * + * Function prototype for methods to create copies of instances. + * + * Returns: reference to cloned instance. + */ +typedef GstMiniObject * (*GstMiniObjectCopyFunction) (const GstMiniObject *obj); +/** + * GstMiniObjectDisposeFunction: + * @obj: MiniObject to dispose + * + * Function prototype for when a miniobject has lost its last refcount. + * Implementation of the mini object are allowed to revive the + * passed object by doing a gst_mini_object_ref(). If the object is not + * revived after the dispose function, the function should return %TRUE + * and the memory associated with the object is freed. + * + * Returns: %TRUE if the object should be cleaned up. + */ +typedef gboolean (*GstMiniObjectDisposeFunction) (GstMiniObject *obj); +/** + * GstMiniObjectFreeFunction: + * @obj: MiniObject to free + * + * Virtual function prototype for methods to free resources used by + * mini-objects. + */ +typedef void (*GstMiniObjectFreeFunction) (GstMiniObject *obj); + + /** + * GstMiniObjectNotify: + * @user_data: data that was provided when the notify was added + * @obj: the mini object + * + * A #GstMiniObjectNotify function can be added to a mini object as a + * callback that gets triggered when gst_mini_object_unref() drops the + * last ref and @obj is about to be freed. + */ +typedef void (*GstMiniObjectNotify) (gpointer user_data, GstMiniObject * obj); + +/** + * GST_MINI_OBJECT_TYPE: + * @obj: MiniObject to return type for. + * + * This macro returns the type of the mini-object. + */ +#define GST_MINI_OBJECT_TYPE(obj) (GST_MINI_OBJECT_CAST(obj)->type) + +/** + * GST_MINI_OBJECT_FLAGS: + * @obj: MiniObject to return flags for. + * + * This macro returns the entire set of flags for the mini-object. + */ +#define GST_MINI_OBJECT_FLAGS(obj) (GST_MINI_OBJECT_CAST(obj)->flags) +/** + * GST_MINI_OBJECT_FLAG_IS_SET: + * @obj: MiniObject to check for flags. + * @flag: Flag to check for + * + * This macro checks to see if the given flag is set. + */ +#define GST_MINI_OBJECT_FLAG_IS_SET(obj,flag) !!(GST_MINI_OBJECT_FLAGS (obj) & (flag)) +/** + * GST_MINI_OBJECT_FLAG_SET: + * @obj: MiniObject to set flag in. + * @flag: Flag to set, can by any number of bits in guint32. + * + * This macro sets the given bits. + */ +#define GST_MINI_OBJECT_FLAG_SET(obj,flag) (GST_MINI_OBJECT_FLAGS (obj) |= (flag)) +/** + * GST_MINI_OBJECT_FLAG_UNSET: + * @obj: MiniObject to unset flag in. + * @flag: Flag to set, must be a single bit in guint32. + * + * This macro unsets the given bits. + */ +#define GST_MINI_OBJECT_FLAG_UNSET(obj,flag) (GST_MINI_OBJECT_FLAGS (obj) &= ~(flag)) + +/** + * GstMiniObjectFlags: + * @GST_MINI_OBJECT_FLAG_LOCKABLE: the object can be locked and unlocked with + * gst_mini_object_lock() and gst_mini_object_unlock(). + * @GST_MINI_OBJECT_FLAG_LOCK_READONLY: the object is permanently locked in + * READONLY mode. Only read locks can be performed on the object. + * @GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED: the object is expected to stay alive + * even after gst_deinit() has been called and so should be ignored by leak + * detection tools. (Since 1.10) + * @GST_MINI_OBJECT_FLAG_LAST: first flag that can be used by subclasses. + * + * Flags for the mini object + */ +typedef enum +{ + GST_MINI_OBJECT_FLAG_LOCKABLE = (1 << 0), + GST_MINI_OBJECT_FLAG_LOCK_READONLY = (1 << 1), + GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED = (1 << 2), + /* padding */ + GST_MINI_OBJECT_FLAG_LAST = (1 << 4) +} GstMiniObjectFlags; + +/** + * GST_MINI_OBJECT_IS_LOCKABLE: + * @obj: a #GstMiniObject + * + * Check if @obj is lockable. A lockable object can be locked and unlocked with + * gst_mini_object_lock() and gst_mini_object_unlock(). + */ +#define GST_MINI_OBJECT_IS_LOCKABLE(obj) GST_MINI_OBJECT_FLAG_IS_SET(obj, GST_MINI_OBJECT_FLAG_LOCKABLE) + +/** + * GstLockFlags: + * @GST_LOCK_FLAG_READ: lock for read access + * @GST_LOCK_FLAG_WRITE: lock for write access + * @GST_LOCK_FLAG_EXCLUSIVE: lock for exclusive access + * @GST_LOCK_FLAG_LAST: first flag that can be used for custom purposes + * + * Flags used when locking miniobjects + */ +typedef enum { + GST_LOCK_FLAG_READ = (1 << 0), + GST_LOCK_FLAG_WRITE = (1 << 1), + GST_LOCK_FLAG_EXCLUSIVE = (1 << 2), + + GST_LOCK_FLAG_LAST = (1 << 8) +} GstLockFlags; + +/** + * GST_LOCK_FLAG_READWRITE: (value 3) (type GstLockFlags) + * + * GstLockFlags value alias for GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE + */ +#define GST_LOCK_FLAG_READWRITE ((GstLockFlags) (GST_LOCK_FLAG_READ | GST_LOCK_FLAG_WRITE)) + +/** + * GST_MINI_OBJECT_REFCOUNT: + * @obj: a #GstMiniObject + * + * Get access to the reference count field of the mini-object. + */ +#define GST_MINI_OBJECT_REFCOUNT(obj) ((GST_MINI_OBJECT_CAST(obj))->refcount) +/** + * GST_MINI_OBJECT_REFCOUNT_VALUE: + * @obj: a #GstMiniObject + * + * Get the reference count value of the mini-object. + */ +#define GST_MINI_OBJECT_REFCOUNT_VALUE(obj) (g_atomic_int_get (&(GST_MINI_OBJECT_CAST(obj))->refcount)) + +/** + * GstMiniObject: (ref-func gst_mini_object_ref) (unref-func gst_mini_object_unref) (set-value-func g_value_set_boxed) (get-value-func g_value_get_boxed) + * @type: the GType of the object + * @refcount: atomic refcount + * @lockstate: atomic state of the locks + * @flags: extra flags. + * @copy: a copy function + * @dispose: a dispose function + * @free: the free function + * + * Base class for refcounted lightweight objects. + */ +struct _GstMiniObject { + GType type; + + /*< public >*/ /* with COW */ + gint refcount; + gint lockstate; + guint flags; + + GstMiniObjectCopyFunction copy; + GstMiniObjectDisposeFunction dispose; + GstMiniObjectFreeFunction free; + + /* < private > */ + /* Used to keep track of weak ref notifies and qdata */ + guint n_qdata; + gpointer qdata; +}; + +GST_API +void gst_mini_object_init (GstMiniObject *mini_object, + guint flags, GType type, + GstMiniObjectCopyFunction copy_func, + GstMiniObjectDisposeFunction dispose_func, + GstMiniObjectFreeFunction free_func); + + +/* refcounting */ + +GST_API +GstMiniObject * gst_mini_object_ref (GstMiniObject *mini_object); + +GST_API +void gst_mini_object_unref (GstMiniObject *mini_object); + +GST_API +void gst_mini_object_weak_ref (GstMiniObject *object, + GstMiniObjectNotify notify, + gpointer data); +GST_API +void gst_mini_object_weak_unref (GstMiniObject *object, + GstMiniObjectNotify notify, + gpointer data); + +/* locking */ + +GST_API +gboolean gst_mini_object_lock (GstMiniObject *object, GstLockFlags flags); + +GST_API +void gst_mini_object_unlock (GstMiniObject *object, GstLockFlags flags); + +GST_API +gboolean gst_mini_object_is_writable (const GstMiniObject *mini_object); + +GST_API +GstMiniObject * gst_mini_object_make_writable (GstMiniObject *mini_object) G_GNUC_WARN_UNUSED_RESULT; + +/* copy */ + +GST_API +GstMiniObject * gst_mini_object_copy (const GstMiniObject *mini_object) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +GST_API +void gst_mini_object_set_qdata (GstMiniObject *object, GQuark quark, + gpointer data, GDestroyNotify destroy); +GST_API +gpointer gst_mini_object_get_qdata (GstMiniObject *object, GQuark quark); + +GST_API +gpointer gst_mini_object_steal_qdata (GstMiniObject *object, GQuark quark); + +GST_API +gboolean gst_mini_object_replace (GstMiniObject **olddata, GstMiniObject *newdata); + +GST_API +gboolean gst_mini_object_take (GstMiniObject **olddata, GstMiniObject *newdata); + +GST_API +GstMiniObject * gst_mini_object_steal (GstMiniObject **olddata) G_GNUC_WARN_UNUSED_RESULT; + +/** + * GST_DEFINE_MINI_OBJECT_TYPE: + * @TypeName: name of the new type in CamelCase + * @type_name: name of the new type + * + * Define a new mini-object type with the given name + */ +#define GST_DEFINE_MINI_OBJECT_TYPE(TypeName,type_name) \ + G_DEFINE_BOXED_TYPE(TypeName,type_name, \ + (GBoxedCopyFunc) gst_mini_object_ref, \ + (GBoxedFreeFunc) gst_mini_object_unref) + +G_END_DECLS + +#endif + diff --git a/gst/gstobject.c b/gst/gstobject.c new file mode 100644 index 0000000..011598e --- /dev/null +++ b/gst/gstobject.c @@ -0,0 +1,1465 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstobject.c: Fundamental class used for all of GStreamer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstobject + * @title: GstObject + * @short_description: Base class for the GStreamer object hierarchy + * + * #GstObject provides a root for the object hierarchy tree filed in by the + * GStreamer library. It is currently a thin wrapper on top of + * #GInitiallyUnowned. It is an abstract class that is not very usable on its own. + * + * #GstObject gives us basic refcounting, parenting functionality and locking. + * Most of the functions are just extended for special GStreamer needs and can be + * found under the same name in the base class of #GstObject which is #GObject + * (e.g. g_object_ref() becomes gst_object_ref()). + * + * Since #GstObject derives from #GInitiallyUnowned, it also inherits the + * floating reference. Be aware that functions such as gst_bin_add() and + * gst_element_add_pad() take ownership of the floating reference. + * + * In contrast to #GObject instances, #GstObject adds a name property. The functions + * gst_object_set_name() and gst_object_get_name() are used to set/get the name + * of the object. + * + * ## controlled properties + * + * Controlled properties offers a lightweight way to adjust gobject properties + * over stream-time. It works by using time-stamped value pairs that are queued + * for element-properties. At run-time the elements continuously pull value + * changes for the current stream-time. + * + * What needs to be changed in a #GstElement? + * Very little - it is just two steps to make a plugin controllable! + * + * * mark gobject-properties paramspecs that make sense to be controlled, + * by GST_PARAM_CONTROLLABLE. + * + * * when processing data (get, chain, loop function) at the beginning call + * gst_object_sync_values(element,timestamp). + * This will make the controller update all GObject properties that are + * under its control with the current values based on the timestamp. + * + * What needs to be done in applications? Again it's not a lot to change. + * + * * create a #GstControlSource. + * csource = gst_interpolation_control_source_new (); + * g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + * + * * Attach the #GstControlSource on the controller to a property. + * gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource)); + * + * * Set the control values + * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1); + * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2); + * + * * start your pipeline + */ + +#include "gst_private.h" +#include "glib-compat-private.h" + +#include "gstobject.h" +#include "gstclock.h" +#include "gstcontrolbinding.h" +#include "gstcontrolsource.h" +#include "gstinfo.h" +#include "gstparamspecs.h" +#include "gstutils.h" + +#define DEBUG_REFCOUNT + +/* Object signals and args */ +enum +{ + DEEP_NOTIFY, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_NAME, + PROP_PARENT, + PROP_LAST +}; + +enum +{ + SO_OBJECT_LOADED, + SO_LAST_SIGNAL +}; + +/* maps type name quark => count */ +static GData *object_name_counts = NULL; + +G_LOCK_DEFINE_STATIC (object_name_mutex); + +static void gst_object_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_object_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_object_dispatch_properties_changed (GObject * object, + guint n_pspecs, GParamSpec ** pspecs); + +static void gst_object_dispose (GObject * object); +static void gst_object_finalize (GObject * object); + +static gboolean gst_object_set_name_default (GstObject * object); + +static guint gst_object_signals[LAST_SIGNAL] = { 0 }; + +static GParamSpec *properties[PROP_LAST]; + +G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_INITIALLY_UNOWNED); + +static void +gst_object_constructed (GObject * object) +{ + GST_TRACER_OBJECT_CREATED (GST_OBJECT_CAST (object)); + + ((GObjectClass *) gst_object_parent_class)->constructed (object); +} + +static void +gst_object_class_init (GstObjectClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_object_set_property; + gobject_class->get_property = gst_object_get_property; + + properties[PROP_NAME] = + g_param_spec_string ("name", "Name", "The name of the object", NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + /** + * GstObject:parent: + * + * The parent of the object. Please note, that when changing the 'parent' + * property, we don't emit #GObject::notify and #GstObject::deep-notify + * signals due to locking issues. In some cases one can use + * #GstBin::element-added or #GstBin::element-removed signals on the parent to + * achieve a similar effect. + */ + properties[PROP_PARENT] = + g_param_spec_object ("parent", "Parent", "The parent of the object", + GST_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, properties); + + /** + * GstObject::deep-notify: + * @gstobject: a #GstObject + * @prop_object: the object that originated the signal + * @prop: the property that changed + * + * The deep notify signal is used to be notified of property changes. It is + * typically attached to the toplevel bin to receive notifications from all + * the elements contained in that bin. + */ + gst_object_signals[DEEP_NOTIFY] = + g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | + G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_OBJECT, + G_TYPE_PARAM); + + klass->path_string_separator = "/"; + + /* see the comments at gst_object_dispatch_properties_changed */ + gobject_class->dispatch_properties_changed + = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed); + + gobject_class->constructed = gst_object_constructed; + gobject_class->dispose = gst_object_dispose; + gobject_class->finalize = gst_object_finalize; +} + +static void +gst_object_init (GstObject * object) +{ + g_mutex_init (&object->lock); + object->parent = NULL; + object->name = NULL; + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object); + + object->flags = 0; + + object->control_rate = 100 * GST_MSECOND; + object->last_sync = GST_CLOCK_TIME_NONE; +} + +/** + * gst_object_ref: + * @object: (type Gst.Object): a #GstObject to reference + * + * Increments the reference count on @object. This function + * does not take the lock on @object because it relies on + * atomic refcounting. + * + * This object returns the input parameter to ease writing + * constructs like : + * result = gst_object_ref (object->parent); + * + * Returns: (transfer full) (type Gst.Object): A pointer to @object + */ +gpointer +gst_object_ref (gpointer object) +{ + g_return_val_if_fail (object != NULL, NULL); + + GST_TRACER_OBJECT_REFFED (object, ((GObject *) object)->ref_count + 1); +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref %d->%d", object, + ((GObject *) object)->ref_count, ((GObject *) object)->ref_count + 1); +#endif + g_object_ref (object); + + return object; +} + +/** + * gst_object_unref: + * @object: (type Gst.Object): a #GstObject to unreference + * + * Decrements the reference count on @object. If reference count hits + * zero, destroy @object. This function does not take the lock + * on @object as it relies on atomic refcounting. + * + * The unref method should never be called with the LOCK held since + * this might deadlock the dispose function. + */ +void +gst_object_unref (gpointer object) +{ + g_return_if_fail (object != NULL); + g_return_if_fail (((GObject *) object)->ref_count > 0); + + GST_TRACER_OBJECT_UNREFFED (object, ((GObject *) object)->ref_count - 1); +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p unref %d->%d", object, + ((GObject *) object)->ref_count, ((GObject *) object)->ref_count - 1); +#endif + g_object_unref (object); +} + +/** + * gst_object_ref_sink: (skip) + * @object: a #GstObject to sink + * + * Increase the reference count of @object, and possibly remove the floating + * reference, if @object has a floating reference. + * + * In other words, if the object is floating, then this call "assumes ownership" + * of the floating reference, converting it to a normal reference by clearing + * the floating flag while leaving the reference count unchanged. If the object + * is not floating, then this call adds a new normal reference increasing the + * reference count by one. + * + * For more background on "floating references" please see the #GObject + * documentation. + */ +gpointer +gst_object_ref_sink (gpointer object) +{ + g_return_val_if_fail (object != NULL, NULL); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref_sink %d->%d", + object, ((GObject *) object)->ref_count, + ((GObject *) object)->ref_count + 1); +#endif + return g_object_ref_sink (object); +} + +/** + * gst_object_replace: + * @oldobj: (inout) (transfer full) (nullable): pointer to a place of + * a #GstObject to replace + * @newobj: (transfer none) (allow-none): a new #GstObject + * + * Atomically modifies a pointer to point to a new object. + * The reference count of @oldobj is decreased and the reference count of + * @newobj is increased. + * + * Either @newobj and the value pointed to by @oldobj may be %NULL. + * + * Returns: %TRUE if @newobj was different from @oldobj + */ +gboolean +gst_object_replace (GstObject ** oldobj, GstObject * newobj) +{ + GstObject *oldptr; + + g_return_val_if_fail (oldobj != NULL, FALSE); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)", + *oldobj, *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)", + *oldobj ? G_OBJECT (*oldobj)->ref_count : 0, + newobj, newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)", + newobj ? G_OBJECT (newobj)->ref_count : 0); +#endif + + oldptr = g_atomic_pointer_get ((gpointer *) oldobj); + + if (G_UNLIKELY (oldptr == newobj)) + return FALSE; + + if (newobj) + gst_object_ref (newobj); + + while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *) + oldobj, oldptr, newobj))) { + oldptr = g_atomic_pointer_get ((gpointer *) oldobj); + if (G_UNLIKELY (oldptr == newobj)) + break; + } + + if (oldptr) + gst_object_unref (oldptr); + + return oldptr != newobj; +} + +/* dispose is called when the object has to release all links + * to other objects */ +static void +gst_object_dispose (GObject * object) +{ + GstObject *self = (GstObject *) object; + GstObject *parent; + + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p dispose", object); + + GST_OBJECT_LOCK (object); + if ((parent = GST_OBJECT_PARENT (object))) + goto have_parent; + GST_OBJECT_PARENT (object) = NULL; + GST_OBJECT_UNLOCK (object); + + if (self->control_bindings) { + GList *node; + + for (node = self->control_bindings; node; node = g_list_next (node)) { + gst_object_unparent (node->data); + } + g_list_free (self->control_bindings); + self->control_bindings = NULL; + } + + ((GObjectClass *) gst_object_parent_class)->dispose (object); + + return; + + /* ERRORS */ +have_parent: + { + g_critical ("\nTrying to dispose object \"%s\", but it still has a " + "parent \"%s\".\nYou need to let the parent manage the " + "object instead of unreffing the object directly.\n", + GST_OBJECT_NAME (object), GST_OBJECT_NAME (parent)); + GST_OBJECT_UNLOCK (object); + /* ref the object again to revive it in this error case */ + gst_object_ref (object); + return; + } +} + +/* finalize is called when the object has to free its resources */ +static void +gst_object_finalize (GObject * object) +{ + GstObject *gstobject = GST_OBJECT_CAST (object); + + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p finalize", object); + + g_signal_handlers_destroy (object); + + g_free (gstobject->name); + g_mutex_clear (&gstobject->lock); + + GST_TRACER_OBJECT_DESTROYED (gstobject); + + ((GObjectClass *) gst_object_parent_class)->finalize (object); +} + +/* Changing a GObject property of a GstObject will result in "deep-notify" + * signals being emitted by the object itself, as well as in each parent + * object. This is so that an application can connect a listener to the + * top-level bin to catch property-change notifications for all contained + * elements. + * + * MT safe. + */ +static void +gst_object_dispatch_properties_changed (GObject * object, + guint n_pspecs, GParamSpec ** pspecs) +{ + GstObject *gst_object, *parent, *old_parent; + guint i; +#ifndef GST_DISABLE_GST_DEBUG + gchar *name = NULL; + const gchar *debug_name; +#endif + + /* do the standard dispatching */ + ((GObjectClass *) + gst_object_parent_class)->dispatch_properties_changed (object, n_pspecs, + pspecs); + + gst_object = GST_OBJECT_CAST (object); +#ifndef GST_DISABLE_GST_DEBUG + if (G_UNLIKELY (_gst_debug_min >= GST_LEVEL_LOG)) { + name = gst_object_get_name (gst_object); + debug_name = GST_STR_NULL (name); + } else + debug_name = ""; +#endif + + /* now let the parent dispatch those, too */ + parent = gst_object_get_parent (gst_object); + while (parent) { + for (i = 0; i < n_pspecs; i++) { + GST_CAT_LOG_OBJECT (GST_CAT_PROPERTIES, parent, + "deep notification from %s (%s)", debug_name, pspecs[i]->name); + + g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY], + g_quark_from_string (pspecs[i]->name), gst_object, pspecs[i]); + } + + old_parent = parent; + parent = gst_object_get_parent (old_parent); + gst_object_unref (old_parent); + } +#ifndef GST_DISABLE_GST_DEBUG + g_free (name); +#endif +} + +/** + * gst_object_default_deep_notify: + * @object: the #GObject that signalled the notify. + * @orig: a #GstObject that initiated the notify. + * @pspec: a #GParamSpec of the property. + * @excluded_props: (array zero-terminated=1) (element-type gchar*) (allow-none): + * a set of user-specified properties to exclude or %NULL to show + * all changes. + * + * A default deep_notify signal callback for an object. The user data + * should contain a pointer to an array of strings that should be excluded + * from the notify. The default handler will print the new value of the property + * using g_print. + * + * MT safe. This function grabs and releases @object's LOCK for getting its + * path string. + */ +void +gst_object_default_deep_notify (GObject * object, GstObject * orig, + GParamSpec * pspec, gchar ** excluded_props) +{ + GValue value = { 0, }; /* the important thing is that value.type = 0 */ + gchar *str = NULL; + gchar *name = NULL; + + if (pspec->flags & G_PARAM_READABLE) { + /* let's not print these out for excluded properties... */ + while (excluded_props != NULL && *excluded_props != NULL) { + if (strcmp (pspec->name, *excluded_props) == 0) + return; + excluded_props++; + } + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (orig), pspec->name, &value); + + if (G_VALUE_HOLDS_STRING (&value)) + str = g_value_dup_string (&value); + else + str = gst_value_serialize (&value); + name = gst_object_get_path_string (orig); + g_print ("%s: %s = %s\n", name, pspec->name, str); + g_free (name); + g_free (str); + g_value_unset (&value); + } else { + name = gst_object_get_path_string (orig); + g_warning ("Parameter %s not readable in %s.", pspec->name, name); + g_free (name); + } +} + +static gboolean +gst_object_set_name_default (GstObject * object) +{ + const gchar *type_name; + gint count; + gchar *name; + GQuark q; + guint i, l; + + /* to ensure guaranteed uniqueness across threads, only one thread + * may ever assign a name */ + G_LOCK (object_name_mutex); + + if (!object_name_counts) { + g_datalist_init (&object_name_counts); + } + + q = g_type_qname (G_OBJECT_TYPE (object)); + count = GPOINTER_TO_INT (g_datalist_id_get_data (&object_name_counts, q)); + g_datalist_id_set_data (&object_name_counts, q, GINT_TO_POINTER (count + 1)); + + G_UNLOCK (object_name_mutex); + + /* GstFooSink -> foosink */ + type_name = g_quark_to_string (q); + if (strncmp (type_name, "Gst", 3) == 0) + type_name += 3; + /* give the 20th "queue" element and the first "queue2" different names */ + l = strlen (type_name); + if (l > 0 && g_ascii_isdigit (type_name[l - 1])) { + name = g_strdup_printf ("%s-%d", type_name, count); + } else { + name = g_strdup_printf ("%s%d", type_name, count); + } + + l = strlen (name); + for (i = 0; i < l; i++) + name[i] = g_ascii_tolower (name[i]); + + GST_OBJECT_LOCK (object); + if (G_UNLIKELY (object->parent != NULL)) + goto had_parent; + + g_free (object->name); + object->name = name; + + GST_OBJECT_UNLOCK (object); + + return TRUE; + +had_parent: + { + g_free (name); + GST_WARNING ("parented objects can't be renamed"); + GST_OBJECT_UNLOCK (object); + return FALSE; + } +} + +/** + * gst_object_set_name: + * @object: a #GstObject + * @name: (allow-none): new name of object + * + * Sets the name of @object, or gives @object a guaranteed unique + * name (if @name is %NULL). + * This function makes a copy of the provided name, so the caller + * retains ownership of the name it sent. + * + * Returns: %TRUE if the name could be set. Since Objects that have + * a parent cannot be renamed, this function returns %FALSE in those + * cases. + * + * MT safe. This function grabs and releases @object's LOCK. + */ +gboolean +gst_object_set_name (GstObject * object, const gchar * name) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + + GST_OBJECT_LOCK (object); + + /* parented objects cannot be renamed */ + if (G_UNLIKELY (object->parent != NULL)) + goto had_parent; + + if (name != NULL) { + g_free (object->name); + object->name = g_strdup (name); + GST_OBJECT_UNLOCK (object); + result = TRUE; + } else { + GST_OBJECT_UNLOCK (object); + result = gst_object_set_name_default (object); + } + + g_object_notify (G_OBJECT (object), "name"); + return result; + + /* error */ +had_parent: + { + GST_WARNING ("parented objects can't be renamed"); + GST_OBJECT_UNLOCK (object); + return FALSE; + } +} + +/** + * gst_object_get_name: + * @object: a #GstObject + * + * Returns a copy of the name of @object. + * Caller should g_free() the return value after usage. + * For a nameless object, this returns %NULL, which you can safely g_free() + * as well. + * + * Free-function: g_free + * + * Returns: (transfer full) (nullable): the name of @object. g_free() + * after usage. + * + * MT safe. This function grabs and releases @object's LOCK. + */ +gchar * +gst_object_get_name (GstObject * object) +{ + gchar *result = NULL; + + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + + GST_OBJECT_LOCK (object); + result = g_strdup (object->name); + GST_OBJECT_UNLOCK (object); + + return result; +} + +/** + * gst_object_set_parent: + * @object: (transfer floating): a #GstObject + * @parent: new parent of object + * + * Sets the parent of @object to @parent. The object's reference count will + * be incremented, and any floating reference will be removed (see gst_object_ref_sink()). + * + * Returns: %TRUE if @parent could be set or %FALSE when @object + * already had a parent or @object and @parent are the same. + * + * MT safe. Grabs and releases @object's LOCK. + */ +gboolean +gst_object_set_parent (GstObject * object, GstObject * parent) +{ + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE); + g_return_val_if_fail (object != parent, FALSE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, + "set parent (ref and sink)"); + + GST_OBJECT_LOCK (object); + if (G_UNLIKELY (object->parent != NULL)) + goto had_parent; + + object->parent = parent; + gst_object_ref_sink (object); + GST_OBJECT_UNLOCK (object); + + /* FIXME-2.0: this does not work, the deep notify takes the lock from the + * parent object and deadlocks when the parent holds its lock when calling + * this function (like _element_add_pad()), we need to use a GRecMutex + * for locking the parent instead. + */ + /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */ + + return TRUE; + + /* ERROR handling */ +had_parent: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, + "set parent failed, object already had a parent"); + gst_object_ref_sink (object); + gst_object_unref (object); + GST_OBJECT_UNLOCK (object); + return FALSE; + } +} + +/** + * gst_object_get_parent: + * @object: a #GstObject + * + * Returns the parent of @object. This function increases the refcount + * of the parent object so you should gst_object_unref() it after usage. + * + * Returns: (transfer full) (nullable): parent of @object, this can be + * %NULL if @object has no parent. unref after usage. + * + * MT safe. Grabs and releases @object's LOCK. + */ +GstObject * +gst_object_get_parent (GstObject * object) +{ + GstObject *result = NULL; + + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + + GST_OBJECT_LOCK (object); + result = object->parent; + if (G_LIKELY (result)) + gst_object_ref (result); + GST_OBJECT_UNLOCK (object); + + return result; +} + +/** + * gst_object_unparent: + * @object: a #GstObject to unparent + * + * Clear the parent of @object, removing the associated reference. + * This function decreases the refcount of @object. + * + * MT safe. Grabs and releases @object's lock. + */ +void +gst_object_unparent (GstObject * object) +{ + GstObject *parent; + + g_return_if_fail (GST_IS_OBJECT (object)); + + GST_OBJECT_LOCK (object); + parent = object->parent; + + if (G_LIKELY (parent != NULL)) { + GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "unparent"); + object->parent = NULL; + GST_OBJECT_UNLOCK (object); + + /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */ + + gst_object_unref (object); + } else { + GST_OBJECT_UNLOCK (object); + } +} + +/** + * gst_object_has_as_parent: + * @object: a #GstObject to check + * @parent: a #GstObject to check as parent + * + * Check if @parent is the parent of @object. + * E.g. a #GstElement can check if it owns a given #GstPad. + * + * Returns: %FALSE if either @object or @parent is %NULL. %TRUE if @parent is + * the parent of @object. Otherwise %FALSE. + * + * MT safe. Grabs and releases @object's locks. + * Since: 1.6 + */ +gboolean +gst_object_has_as_parent (GstObject * object, GstObject * parent) +{ + gboolean result = FALSE; + + if (G_LIKELY (GST_IS_OBJECT (object) && GST_IS_OBJECT (parent))) { + GST_OBJECT_LOCK (object); + result = GST_OBJECT_PARENT (object) == parent; + GST_OBJECT_UNLOCK (object); + } + + return result; +} + +/** + * gst_object_has_as_ancestor: + * @object: a #GstObject to check + * @ancestor: a #GstObject to check as ancestor + * + * Check if @object has an ancestor @ancestor somewhere up in + * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline. + * + * Returns: %TRUE if @ancestor is an ancestor of @object. + * + * MT safe. Grabs and releases @object's locks. + */ +gboolean +gst_object_has_as_ancestor (GstObject * object, GstObject * ancestor) +{ + GstObject *parent, *tmp; + + if (!ancestor || !object) + return FALSE; + + parent = gst_object_ref (object); + do { + if (parent == ancestor) { + gst_object_unref (parent); + return TRUE; + } + + tmp = gst_object_get_parent (parent); + gst_object_unref (parent); + parent = tmp; + } while (parent); + + return FALSE; +} + +/** + * gst_object_has_ancestor: + * @object: a #GstObject to check + * @ancestor: a #GstObject to check as ancestor + * + * Check if @object has an ancestor @ancestor somewhere up in + * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline. + * + * Returns: %TRUE if @ancestor is an ancestor of @object. + * + * Deprecated: Use gst_object_has_as_ancestor() instead. + * + * MT safe. Grabs and releases @object's locks. + */ +#ifndef GST_REMOVE_DEPRECATED +gboolean +gst_object_has_ancestor (GstObject * object, GstObject * ancestor) +{ + return gst_object_has_as_ancestor (object, ancestor); +} +#endif + +/** + * gst_object_check_uniqueness: + * @list: (transfer none) (element-type Gst.Object): a list of #GstObject to + * check through + * @name: the name to search for + * + * Checks to see if there is any object named @name in @list. This function + * does not do any locking of any kind. You might want to protect the + * provided list with the lock of the owner of the list. This function + * will lock each #GstObject in the list to compare the name, so be + * careful when passing a list with a locked object. + * + * Returns: %TRUE if a #GstObject named @name does not appear in @list, + * %FALSE if it does. + * + * MT safe. Grabs and releases the LOCK of each object in the list. + */ +gboolean +gst_object_check_uniqueness (GList * list, const gchar * name) +{ + gboolean result = TRUE; + + g_return_val_if_fail (name != NULL, FALSE); + + for (; list; list = g_list_next (list)) { + GstObject *child; + gboolean eq; + + child = GST_OBJECT_CAST (list->data); + + GST_OBJECT_LOCK (child); + eq = strcmp (GST_OBJECT_NAME (child), name) == 0; + GST_OBJECT_UNLOCK (child); + + if (G_UNLIKELY (eq)) { + result = FALSE; + break; + } + } + return result; +} + + +static void +gst_object_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstObject *gstobject; + + gstobject = GST_OBJECT_CAST (object); + + switch (prop_id) { + case PROP_NAME: + gst_object_set_name (gstobject, g_value_get_string (value)); + break; + case PROP_PARENT: + gst_object_set_parent (gstobject, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_object_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstObject *gstobject; + + gstobject = GST_OBJECT_CAST (object); + + switch (prop_id) { + case PROP_NAME: + g_value_take_string (value, gst_object_get_name (gstobject)); + break; + case PROP_PARENT: + g_value_take_object (value, gst_object_get_parent (gstobject)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_object_get_path_string: + * @object: a #GstObject + * + * Generates a string describing the path of @object in + * the object hierarchy. Only useful (or used) for debugging. + * + * Free-function: g_free + * + * Returns: (transfer full): a string describing the path of @object. You must + * g_free() the string after usage. + * + * MT safe. Grabs and releases the #GstObject's LOCK for all objects + * in the hierarchy. + */ +gchar * +gst_object_get_path_string (GstObject * object) +{ + GSList *parentage; + GSList *parents; + void *parent; + gchar *prevpath, *path; + const gchar *typename; + gchar *component; + const gchar *separator; + + /* ref object before adding to list */ + gst_object_ref (object); + parentage = g_slist_prepend (NULL, object); + + path = g_strdup (""); + + /* first walk the object hierarchy to build a list of the parents, + * be careful here with refcounting. */ + do { + if (GST_IS_OBJECT (object)) { + parent = gst_object_get_parent (object); + /* add parents to list, refcount remains increased while + * we handle the object */ + if (parent) + parentage = g_slist_prepend (parentage, parent); + } else { + break; + } + object = parent; + } while (object != NULL); + + /* then walk the parent list and print them out. we need to + * decrease the refcounting on each element after we handled + * it. */ + for (parents = parentage; parents; parents = g_slist_next (parents)) { + if (G_IS_OBJECT (parents->data)) { + typename = G_OBJECT_TYPE_NAME (parents->data); + } else { + typename = NULL; + } + if (GST_IS_OBJECT (parents->data)) { + GstObject *item = GST_OBJECT_CAST (parents->data); + GstObjectClass *oclass = GST_OBJECT_GET_CLASS (item); + gchar *objname = gst_object_get_name (item); + + component = g_strdup_printf ("%s:%s", typename, objname); + separator = oclass->path_string_separator; + /* and unref now */ + gst_object_unref (item); + g_free (objname); + } else { + if (typename) { + component = g_strdup_printf ("%s:%p", typename, parents->data); + } else { + component = g_strdup_printf ("%p", parents->data); + } + separator = "/"; + } + + prevpath = path; + path = g_strjoin (separator, prevpath, component, NULL); + g_free (prevpath); + g_free (component); + } + + g_slist_free (parentage); + + return path; +} + +/* controller helper functions */ + +/* + * gst_object_find_control_binding: + * @self: the gobject to search for a property in + * @name: the gobject property name to look for + * + * Searches the list of properties under control. + * + * Returns: (nullable): a #GstControlBinding or %NULL if the property + * is not being controlled. + */ +static GstControlBinding * +gst_object_find_control_binding (GstObject * self, const gchar * name) +{ + GstControlBinding *binding; + GList *node; + + for (node = self->control_bindings; node; node = g_list_next (node)) { + binding = node->data; + /* FIXME: eventually use GQuark to speed it up */ + if (!strcmp (binding->name, name)) { + GST_DEBUG_OBJECT (self, "found control binding for property '%s'", name); + return binding; + } + } + GST_DEBUG_OBJECT (self, "controller does not manage property '%s'", name); + + return NULL; +} + +/* controller functions */ + +/** + * gst_object_suggest_next_sync: + * @object: the object that has controlled properties + * + * Returns a suggestion for timestamps where buffers should be split + * to get best controller results. + * + * Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE + * if no control-rate was set. + */ +GstClockTime +gst_object_suggest_next_sync (GstObject * object) +{ + GstClockTime ret; + + g_return_val_if_fail (GST_IS_OBJECT (object), GST_CLOCK_TIME_NONE); + g_return_val_if_fail (object->control_rate != GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (object); + + /* TODO: Implement more logic, depending on interpolation mode and control + * points + * FIXME: we need playback direction + */ + ret = object->last_sync + object->control_rate; + + GST_OBJECT_UNLOCK (object); + + return ret; +} + +/** + * gst_object_sync_values: + * @object: the object that has controlled properties + * @timestamp: the time that should be processed + * + * Sets the properties of the object, according to the #GstControlSources that + * (maybe) handle them and for the given timestamp. + * + * If this function fails, it is most likely the application developers fault. + * Most probably the control sources are not setup correctly. + * + * Returns: %TRUE if the controller values could be applied to the object + * properties, %FALSE otherwise + */ +gboolean +gst_object_sync_values (GstObject * object, GstClockTime timestamp) +{ + GList *node; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + + GST_LOG_OBJECT (object, "sync_values"); + if (!object->control_bindings) + return TRUE; + + /* FIXME: this deadlocks */ + /* GST_OBJECT_LOCK (object); */ + g_object_freeze_notify ((GObject *) object); + for (node = object->control_bindings; node; node = g_list_next (node)) { + ret &= gst_control_binding_sync_values ((GstControlBinding *) node->data, + object, timestamp, object->last_sync); + } + object->last_sync = timestamp; + g_object_thaw_notify ((GObject *) object); + /* GST_OBJECT_UNLOCK (object); */ + + return ret; +} + + +/** + * gst_object_has_active_control_bindings: + * @object: the object that has controlled properties + * + * Check if the @object has active controlled properties. + * + * Returns: %TRUE if the object has active controlled properties + */ +gboolean +gst_object_has_active_control_bindings (GstObject * object) +{ + gboolean res = FALSE; + GList *node; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + + GST_OBJECT_LOCK (object); + for (node = object->control_bindings; node; node = g_list_next (node)) { + res |= !gst_control_binding_is_disabled ((GstControlBinding *) node->data); + } + GST_OBJECT_UNLOCK (object); + return res; +} + +/** + * gst_object_set_control_bindings_disabled: + * @object: the object that has controlled properties + * @disabled: boolean that specifies whether to disable the controller + * or not. + * + * This function is used to disable all controlled properties of the @object for + * some time, i.e. gst_object_sync_values() will do nothing. + */ +void +gst_object_set_control_bindings_disabled (GstObject * object, gboolean disabled) +{ + GList *node; + + g_return_if_fail (GST_IS_OBJECT (object)); + + GST_OBJECT_LOCK (object); + for (node = object->control_bindings; node; node = g_list_next (node)) { + gst_control_binding_set_disabled ((GstControlBinding *) node->data, + disabled); + } + GST_OBJECT_UNLOCK (object); +} + +/** + * gst_object_set_control_binding_disabled: + * @object: the object that has controlled properties + * @property_name: property to disable + * @disabled: boolean that specifies whether to disable the controller + * or not. + * + * This function is used to disable the control bindings on a property for + * some time, i.e. gst_object_sync_values() will do nothing for the + * property. + */ +void +gst_object_set_control_binding_disabled (GstObject * object, + const gchar * property_name, gboolean disabled) +{ + GstControlBinding *binding; + + g_return_if_fail (GST_IS_OBJECT (object)); + g_return_if_fail (property_name); + + GST_OBJECT_LOCK (object); + if ((binding = gst_object_find_control_binding (object, property_name))) { + gst_control_binding_set_disabled (binding, disabled); + } + GST_OBJECT_UNLOCK (object); +} + + +/** + * gst_object_add_control_binding: + * @object: the controller object + * @binding: (transfer floating): the #GstControlBinding that should be used + * + * Attach the #GstControlBinding to the object. If there already was a + * #GstControlBinding for this property it will be replaced. + * + * The object's reference count will be incremented, and any floating + * reference will be removed (see gst_object_ref_sink()) + * + * Returns: %FALSE if the given @binding has not been setup for this object or + * has been setup for a non suitable property, %TRUE otherwise. + */ +gboolean +gst_object_add_control_binding (GstObject * object, GstControlBinding * binding) +{ + GstControlBinding *old; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE); + g_return_val_if_fail (binding->pspec, FALSE); + + GST_OBJECT_LOCK (object); + if ((old = gst_object_find_control_binding (object, binding->name))) { + GST_DEBUG_OBJECT (object, "controlled property %s removed", old->name); + object->control_bindings = g_list_remove (object->control_bindings, old); + gst_object_unparent (GST_OBJECT_CAST (old)); + } + object->control_bindings = g_list_prepend (object->control_bindings, binding); + gst_object_set_parent (GST_OBJECT_CAST (binding), object); + GST_DEBUG_OBJECT (object, "controlled property %s added", binding->name); + GST_OBJECT_UNLOCK (object); + + return TRUE; +} + +/** + * gst_object_get_control_binding: + * @object: the object + * @property_name: name of the property + * + * Gets the corresponding #GstControlBinding for the property. This should be + * unreferenced again after use. + * + * Returns: (transfer full) (nullable): the #GstControlBinding for + * @property_name or %NULL if the property is not controlled. + */ +GstControlBinding * +gst_object_get_control_binding (GstObject * object, const gchar * property_name) +{ + GstControlBinding *binding; + + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + g_return_val_if_fail (property_name, NULL); + + GST_OBJECT_LOCK (object); + if ((binding = gst_object_find_control_binding (object, property_name))) { + gst_object_ref (binding); + } + GST_OBJECT_UNLOCK (object); + + return binding; +} + +/** + * gst_object_remove_control_binding: + * @object: the object + * @binding: the binding + * + * Removes the corresponding #GstControlBinding. If it was the + * last ref of the binding, it will be disposed. + * + * Returns: %TRUE if the binding could be removed. + */ +gboolean +gst_object_remove_control_binding (GstObject * object, + GstControlBinding * binding) +{ + GList *node; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE); + + GST_OBJECT_LOCK (object); + if ((node = g_list_find (object->control_bindings, binding))) { + GST_DEBUG_OBJECT (object, "controlled property %s removed", binding->name); + object->control_bindings = + g_list_delete_link (object->control_bindings, node); + gst_object_unparent (GST_OBJECT_CAST (binding)); + ret = TRUE; + } + GST_OBJECT_UNLOCK (object); + + return ret; +} + +/** + * gst_object_get_value: + * @object: the object that has controlled properties + * @property_name: the name of the property to get + * @timestamp: the time the control-change should be read from + * + * Gets the value for the given controlled property at the requested time. + * + * Returns: (nullable): the GValue of the property at the given time, + * or %NULL if the property isn't controlled. + */ +GValue * +gst_object_get_value (GstObject * object, const gchar * property_name, + GstClockTime timestamp) +{ + GstControlBinding *binding; + GValue *val = NULL; + + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + g_return_val_if_fail (property_name, NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); + + GST_OBJECT_LOCK (object); + if ((binding = gst_object_find_control_binding (object, property_name))) { + val = gst_control_binding_get_value (binding, timestamp); + } + GST_OBJECT_UNLOCK (object); + + return val; +} + +/** + * gst_object_get_value_array: (skip) + * @object: the object that has controlled properties + * @property_name: the name of the property to get + * @timestamp: the time that should be processed + * @interval: the time spacing between subsequent values + * @n_values: the number of values + * @values: array to put control-values in + * + * Gets a number of values for the given controlled property starting at the + * requested time. The array @values need to hold enough space for @n_values of + * the same type as the objects property's type. + * + * This function is useful if one wants to e.g. draw a graph of the control + * curve or apply a control curve sample by sample. + * + * The values are unboxed and ready to be used. The similar function + * gst_object_get_g_value_array() returns the array as #GValues and is + * better suites for bindings. + * + * Returns: %TRUE if the given array could be filled, %FALSE otherwise + */ +gboolean +gst_object_get_value_array (GstObject * object, const gchar * property_name, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values) +{ + gboolean res = FALSE; + GstControlBinding *binding; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + + GST_OBJECT_LOCK (object); + if ((binding = gst_object_find_control_binding (object, property_name))) { + res = gst_control_binding_get_value_array (binding, timestamp, interval, + n_values, values); + } + GST_OBJECT_UNLOCK (object); + return res; +} + +/** + * gst_object_get_g_value_array: + * @object: the object that has controlled properties + * @property_name: the name of the property to get + * @timestamp: the time that should be processed + * @interval: the time spacing between subsequent values + * @n_values: the number of values + * @values: (array length=n_values): array to put control-values in + * + * Gets a number of #GValues for the given controlled property starting at the + * requested time. The array @values need to hold enough space for @n_values of + * #GValue. + * + * This function is useful if one wants to e.g. draw a graph of the control + * curve or apply a control curve sample by sample. + * + * Returns: %TRUE if the given array could be filled, %FALSE otherwise + */ +gboolean +gst_object_get_g_value_array (GstObject * object, const gchar * property_name, + GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + gboolean res = FALSE; + GstControlBinding *binding; + + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + + GST_OBJECT_LOCK (object); + if ((binding = gst_object_find_control_binding (object, property_name))) { + res = gst_control_binding_get_g_value_array (binding, timestamp, interval, + n_values, values); + } + GST_OBJECT_UNLOCK (object); + return res; +} + + +/** + * gst_object_get_control_rate: + * @object: the object that has controlled properties + * + * Obtain the control-rate for this @object. Audio processing #GstElement + * objects will use this rate to sub-divide their processing loop and call + * gst_object_sync_values() inbetween. The length of the processing segment + * should be up to @control-rate nanoseconds. + * + * If the @object is not under property control, this will return + * %GST_CLOCK_TIME_NONE. This allows the element to avoid the sub-dividing. + * + * The control-rate is not expected to change if the element is in + * %GST_STATE_PAUSED or %GST_STATE_PLAYING. + * + * Returns: the control rate in nanoseconds + */ +GstClockTime +gst_object_get_control_rate (GstObject * object) +{ + g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); + + return object->control_rate; +} + +/** + * gst_object_set_control_rate: + * @object: the object that has controlled properties + * @control_rate: the new control-rate in nanoseconds. + * + * Change the control-rate for this @object. Audio processing #GstElement + * objects will use this rate to sub-divide their processing loop and call + * gst_object_sync_values() inbetween. The length of the processing segment + * should be up to @control-rate nanoseconds. + * + * The control-rate should not change if the element is in %GST_STATE_PAUSED or + * %GST_STATE_PLAYING. + */ +void +gst_object_set_control_rate (GstObject * object, GstClockTime control_rate) +{ + g_return_if_fail (GST_IS_OBJECT (object)); + + object->control_rate = control_rate; +} diff --git a/gst/gstobject.h b/gst/gstobject.h new file mode 100644 index 0000000..fe5d95d --- /dev/null +++ b/gst/gstobject.h @@ -0,0 +1,330 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstobject.h: Header for base GstObject + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_OBJECT_H__ +#define __GST_OBJECT_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_OBJECT (gst_object_get_type ()) +#define GST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OBJECT)) +#define GST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OBJECT)) +#define GST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_OBJECT, GstObjectClass)) +#define GST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OBJECT, GstObject)) +#define GST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OBJECT, GstObjectClass)) +#define GST_OBJECT_CAST(obj) ((GstObject*)(obj)) +#define GST_OBJECT_CLASS_CAST(klass) ((GstObjectClass*)(klass)) + +/** + * GstObjectFlags: + * @GST_OBJECT_FLAG_MAY_BE_LEAKED: the object is expected to stay alive even + * after gst_deinit() has been called and so should be ignored by leak + * detection tools. (Since 1.10) + * @GST_OBJECT_FLAG_LAST: subclasses can add additional flags starting from this flag + * + * The standard flags that an gstobject may have. + */ +typedef enum +{ + GST_OBJECT_FLAG_MAY_BE_LEAKED = (1 << 0), + /* padding */ + GST_OBJECT_FLAG_LAST = (1<<4) +} GstObjectFlags; + +/** + * GST_OBJECT_REFCOUNT: + * @obj: a #GstObject + * + * Get access to the reference count field of the object. + */ +#define GST_OBJECT_REFCOUNT(obj) (((GObject*)(obj))->ref_count) +/** + * GST_OBJECT_REFCOUNT_VALUE: + * @obj: a #GstObject + * + * Get the reference count value of the object. + */ +#define GST_OBJECT_REFCOUNT_VALUE(obj) g_atomic_int_get ((gint *) &GST_OBJECT_REFCOUNT(obj)) + +/* we do a GST_OBJECT_CAST to avoid type checking, better call these + * function with a valid object! */ + +/** + * GST_OBJECT_GET_LOCK: + * @obj: a #GstObject + * + * Acquire a reference to the mutex of this object. + */ +#define GST_OBJECT_GET_LOCK(obj) (&GST_OBJECT_CAST(obj)->lock) +/** + * GST_OBJECT_LOCK: + * @obj: a #GstObject to lock + * + * This macro will obtain a lock on the object, making serialization possible. + * It blocks until the lock can be obtained. + */ +#define GST_OBJECT_LOCK(obj) g_mutex_lock(GST_OBJECT_GET_LOCK(obj)) +/** + * GST_OBJECT_TRYLOCK: + * @obj: a #GstObject. + * + * This macro will try to obtain a lock on the object, but will return with + * %FALSE if it can't get it immediately. + */ +#define GST_OBJECT_TRYLOCK(obj) g_mutex_trylock(GST_OBJECT_GET_LOCK(obj)) +/** + * GST_OBJECT_UNLOCK: + * @obj: a #GstObject to unlock. + * + * This macro releases a lock on the object. + */ +#define GST_OBJECT_UNLOCK(obj) g_mutex_unlock(GST_OBJECT_GET_LOCK(obj)) + + +/** + * GST_OBJECT_NAME: + * @obj: a #GstObject + * + * Get the name of this object. This is not thread-safe by default + * (i.e. you will have to make sure the object lock is taken yourself). + * If in doubt use gst_object_get_name() instead. + */ +#define GST_OBJECT_NAME(obj) (GST_OBJECT_CAST(obj)->name) +/** + * GST_OBJECT_PARENT: + * @obj: a #GstObject + * + * Get the parent of this object. This is not thread-safe by default + * (i.e. you will have to make sure the object lock is taken yourself). + * If in doubt use gst_object_get_parent() instead. + */ +#define GST_OBJECT_PARENT(obj) (GST_OBJECT_CAST(obj)->parent) + + +/** + * GST_OBJECT_FLAGS: + * @obj: a #GstObject + * + * This macro returns the entire set of flags for the object. + */ +#define GST_OBJECT_FLAGS(obj) (GST_OBJECT_CAST (obj)->flags) +/** + * GST_OBJECT_FLAG_IS_SET: + * @obj: a #GstObject + * @flag: Flag to check for + * + * This macro checks to see if the given flag is set. + */ +#define GST_OBJECT_FLAG_IS_SET(obj,flag) ((GST_OBJECT_FLAGS (obj) & (flag)) == (flag)) +/** + * GST_OBJECT_FLAG_SET: + * @obj: a #GstObject + * @flag: Flag to set + * + * This macro sets the given bits. + */ +#define GST_OBJECT_FLAG_SET(obj,flag) (GST_OBJECT_FLAGS (obj) |= (flag)) +/** + * GST_OBJECT_FLAG_UNSET: + * @obj: a #GstObject + * @flag: Flag to set + * + * This macro unsets the given bits. + */ +#define GST_OBJECT_FLAG_UNSET(obj,flag) (GST_OBJECT_FLAGS (obj) &= ~(flag)) + +typedef struct _GstObject GstObject; +typedef struct _GstObjectClass GstObjectClass; + +/** + * GstObject: + * @lock: object LOCK + * @name: The name of the object + * @parent: this object's parent, weak ref + * @flags: flags for this object + * + * GStreamer base object class. + */ +struct _GstObject { + GInitiallyUnowned object; + + /*< public >*/ /* with LOCK */ + GMutex lock; /* object LOCK */ + gchar *name; /* object name */ + GstObject *parent; /* this object's parent, weak ref */ + guint32 flags; + + /*< private >*/ + GList *control_bindings; /* List of GstControlBinding */ + guint64 control_rate; + guint64 last_sync; + + gpointer _gst_reserved; +}; + +/** + * GstObjectClass: + * @parent_class: parent + * @path_string_separator: separator used by gst_object_get_path_string() + * @deep_notify: default signal handler + * + * GStreamer base object class. + */ +struct _GstObjectClass { + GInitiallyUnownedClass parent_class; + + const gchar *path_string_separator; + + /* signals */ + void (*deep_notify) (GstObject * object, GstObject * orig, GParamSpec * pspec); + + /*< public >*/ + /* virtual methods for subclasses */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/* normal GObject stuff */ + +GST_API +GType gst_object_get_type (void); + +/* name routines */ + +GST_API +gboolean gst_object_set_name (GstObject *object, const gchar *name); + +GST_API +gchar* gst_object_get_name (GstObject *object); + +/* parentage routines */ + +GST_API +gboolean gst_object_set_parent (GstObject *object, GstObject *parent); + +GST_API +GstObject* gst_object_get_parent (GstObject *object); + +GST_API +void gst_object_unparent (GstObject *object); + +GST_API +gboolean gst_object_has_as_parent (GstObject *object, GstObject *parent); + +GST_API +gboolean gst_object_has_as_ancestor (GstObject *object, GstObject *ancestor); + +GST_DEPRECATED_FOR(gst_object_has_as_ancestor) +gboolean gst_object_has_ancestor (GstObject *object, GstObject *ancestor); + +GST_API +void gst_object_default_deep_notify (GObject *object, GstObject *orig, + GParamSpec *pspec, gchar **excluded_props); + +/* refcounting + life cycle */ + +GST_API +gpointer gst_object_ref (gpointer object); + +GST_API +void gst_object_unref (gpointer object); + +GST_API +gpointer gst_object_ref_sink (gpointer object); + +/* replace object pointer */ + +GST_API +gboolean gst_object_replace (GstObject **oldobj, GstObject *newobj); + +/* printing out the 'path' of the object */ + +GST_API +gchar * gst_object_get_path_string (GstObject *object); + +/* misc utils */ + +GST_API +gboolean gst_object_check_uniqueness (GList *list, const gchar *name); + +/* controller functions */ +#include +#include + +GST_API +GstClockTime gst_object_suggest_next_sync (GstObject * object); + +GST_API +gboolean gst_object_sync_values (GstObject * object, GstClockTime timestamp); + +GST_API +gboolean gst_object_has_active_control_bindings (GstObject *object); + +GST_API +void gst_object_set_control_bindings_disabled (GstObject *object, gboolean disabled); + +GST_API +void gst_object_set_control_binding_disabled (GstObject *object, + const gchar * property_name, + gboolean disabled); + +GST_API +gboolean gst_object_add_control_binding (GstObject * object, GstControlBinding * binding); + +GST_API +GstControlBinding * + gst_object_get_control_binding (GstObject *object, const gchar * property_name); + +GST_API +gboolean gst_object_remove_control_binding (GstObject * object, GstControlBinding * binding); + +GST_API +GValue * gst_object_get_value (GstObject * object, const gchar * property_name, + GstClockTime timestamp); +GST_API +gboolean gst_object_get_value_array (GstObject * object, const gchar * property_name, + GstClockTime timestamp, GstClockTime interval, + guint n_values, gpointer values); +GST_API +gboolean gst_object_get_g_value_array (GstObject * object, const gchar * property_name, + GstClockTime timestamp, GstClockTime interval, + guint n_values, GValue *values); +GST_API +GstClockTime gst_object_get_control_rate (GstObject * object); + +GST_API +void gst_object_set_control_rate (GstObject * object, GstClockTime control_rate); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstObject, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_OBJECT_H__ */ + diff --git a/gst/gstpad.c b/gst/gstpad.c new file mode 100644 index 0000000..84ac7a8 --- /dev/null +++ b/gst/gstpad.c @@ -0,0 +1,6396 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpad.c: Pads for linking elements together + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstpad + * @title: GstPad + * @short_description: Object contained by elements that allows links to + * other elements + * @see_also: #GstPadTemplate, #GstElement, #GstEvent, #GstQuery, #GstBuffer + * + * A #GstElement is linked to other elements via "pads", which are extremely + * light-weight generic link points. + * + * Pads have a #GstPadDirection, source pads produce data, sink pads consume + * data. + * + * Pads are typically created from a #GstPadTemplate with + * gst_pad_new_from_template() and are then added to a #GstElement. This usually + * happens when the element is created but it can also happen dynamically based + * on the data that the element is processing or based on the pads that the + * application requests. + * + * Pads without pad templates can be created with gst_pad_new(), + * which takes a direction and a name as an argument. If the name is %NULL, + * then a guaranteed unique name will be assigned to it. + * + * A #GstElement creating a pad will typically use the various + * gst_pad_set_*_function() calls to register callbacks for events, queries or + * dataflow on the pads. + * + * gst_pad_get_parent() will retrieve the #GstElement that owns the pad. + * + * After two pads are retrieved from an element by gst_element_get_static_pad(), + * the pads can be linked with gst_pad_link(). (For quick links, + * you can also use gst_element_link(), which will make the obvious + * link for you if it's straightforward.). Pads can be unlinked again with + * gst_pad_unlink(). gst_pad_get_peer() can be used to check what the pad is + * linked to. + * + * Before dataflow is possible on the pads, they need to be activated with + * gst_pad_set_active(). + * + * gst_pad_query() and gst_pad_peer_query() can be used to query various + * properties of the pad and the stream. + * + * To send a #GstEvent on a pad, use gst_pad_send_event() and + * gst_pad_push_event(). Some events will be sticky on the pad, meaning that + * after they pass on the pad they can be queried later with + * gst_pad_get_sticky_event() and gst_pad_sticky_events_foreach(). + * gst_pad_get_current_caps() and gst_pad_has_current_caps() are convenience + * functions to query the current sticky CAPS event on a pad. + * + * GstElements will use gst_pad_push() and gst_pad_pull_range() to push out + * or pull in a buffer. + * + * The dataflow, events and queries that happen on a pad can be monitored with + * probes that can be installed with gst_pad_add_probe(). gst_pad_is_blocked() + * can be used to check if a block probe is installed on the pad. + * gst_pad_is_blocking() checks if the blocking probe is currently blocking the + * pad. gst_pad_remove_probe() is used to remove a previously installed probe + * and unblock blocking probes if any. + * + * Pad have an offset that can be retrieved with gst_pad_get_offset(). This + * offset will be applied to the running_time of all data passing over the pad. + * gst_pad_set_offset() can be used to change the offset. + * + * Convenience functions exist to start, pause and stop the task on a pad with + * gst_pad_start_task(), gst_pad_pause_task() and gst_pad_stop_task() + * respectively. + */ + +#include "gst_private.h" + +#include "gstpad.h" +#include "gstpadtemplate.h" +#include "gstenumtypes.h" +#include "gstutils.h" +#include "gstinfo.h" +#include "gsterror.h" +#include "gsttracerutils.h" +#include "gstvalue.h" +#include "glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (debug_dataflow); +#define GST_CAT_DEFAULT GST_CAT_PADS + +/* Pad signals and args */ +enum +{ + PAD_LINKED, + PAD_UNLINKED, + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PAD_PROP_0, + PAD_PROP_CAPS, + PAD_PROP_DIRECTION, + PAD_PROP_TEMPLATE, + PAD_PROP_OFFSET + /* FILL ME */ +}; + +#define GST_PAD_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate)) + +#define _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH (GST_PAD_PROBE_TYPE_ALL_BOTH | GST_PAD_PROBE_TYPE_EVENT_FLUSH) + +/* we have a pending and an active event on the pad. On source pads only the + * active event is used. On sinkpads, events are copied to the pending entry and + * moved to the active event when the eventfunc returned %TRUE. */ +typedef struct +{ + gboolean received; + GstEvent *event; +} PadEvent; + +struct _GstPadPrivate +{ + guint events_cookie; + GArray *events; + guint last_cookie; + + gint using; + guint probe_list_cookie; + + /* counter of how many idle probes are running directly from the add_probe + * call. Used to block any data flowing in the pad while the idle callback + * Doesn't finish its work */ + gint idle_running; + + /* conditional and variable used to ensure pads only get (de)activated + * by a single thread at a time. Protected by the object lock */ + GCond activation_cond; + gboolean in_activation; +}; + +typedef struct +{ + GHook hook; +} GstProbe; + +#define GST_PAD_IS_RUNNING_IDLE_PROBE(p) \ + (((GstPad *)(p))->priv->idle_running > 0) + +typedef struct +{ + GstPad *pad; + GstPadProbeInfo *info; + gboolean dropped; + gboolean pass; + gboolean handled; + gboolean marshalled; + + GHook **called_probes; + guint n_called_probes; + guint called_probes_size; + gboolean retry; +} ProbeMarshall; + +static void gst_pad_dispose (GObject * object); +static void gst_pad_finalize (GObject * object); +static void gst_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ); +static gboolean gst_pad_activate_default (GstPad * pad, GstObject * parent); +static GstFlowReturn gst_pad_chain_list_default (GstPad * pad, + GstObject * parent, GstBufferList * list); + +static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad, + GstEvent * event, GstPadProbeType type); +static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad, + GstEvent * event, GstPadProbeType type); + +static gboolean activate_mode_internal (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); + +static guint gst_pad_signals[LAST_SIGNAL] = { 0 }; + +static GParamSpec *pspec_caps = NULL; + +/* quarks for probe signals */ +static GQuark buffer_quark; +static GQuark buffer_list_quark; +static GQuark event_quark; + +typedef struct +{ + const gint ret; + const gchar *name; + GQuark quark; +} GstFlowQuarks; + +static GstFlowQuarks flow_quarks[] = { + {GST_FLOW_CUSTOM_SUCCESS, "custom-success", 0}, + {GST_FLOW_OK, "ok", 0}, + {GST_FLOW_NOT_LINKED, "not-linked", 0}, + {GST_FLOW_FLUSHING, "flushing", 0}, + {GST_FLOW_EOS, "eos", 0}, + {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0}, + {GST_FLOW_ERROR, "error", 0}, + {GST_FLOW_NOT_SUPPORTED, "not-supported", 0}, + {GST_FLOW_CUSTOM_ERROR, "custom-error", 0} +}; + +/** + * gst_flow_get_name: + * @ret: a #GstFlowReturn to get the name of. + * + * Gets a string representing the given flow return. + * + * Returns: a static string with the name of the flow return. + */ +const gchar * +gst_flow_get_name (GstFlowReturn ret) +{ + gint i; + + ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); + + for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { + if (ret == flow_quarks[i].ret) + return flow_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_flow_to_quark: + * @ret: a #GstFlowReturn to get the quark of. + * + * Get the unique quark for the given GstFlowReturn. + * + * Returns: the quark associated with the flow return or 0 if an + * invalid return was specified. + */ +GQuark +gst_flow_to_quark (GstFlowReturn ret) +{ + gint i; + + ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); + + for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { + if (ret == flow_quarks[i].ret) + return flow_quarks[i].quark; + } + return 0; +} + +/** + * gst_pad_link_get_name: + * @ret: a #GstPadLinkReturn to get the name of. + * + * Gets a string representing the given pad-link return. + * + * Returns: a static string with the name of the pad-link return. + * + * Since: 1.4 + */ +const gchar * +gst_pad_link_get_name (GstPadLinkReturn ret) +{ + switch (ret) { + case GST_PAD_LINK_OK: + return "ok"; + case GST_PAD_LINK_WRONG_HIERARCHY: + return "wrong hierarchy"; + case GST_PAD_LINK_WAS_LINKED: + return "was linked"; + case GST_PAD_LINK_WRONG_DIRECTION: + return "wrong direction"; + case GST_PAD_LINK_NOFORMAT: + return "no common format"; + case GST_PAD_LINK_NOSCHED: + return "incompatible scheduling"; + case GST_PAD_LINK_REFUSED: + return "refused"; + } + g_return_val_if_reached ("unknown"); +} + +#define _do_init \ +{ \ + gint i; \ + \ + buffer_quark = g_quark_from_static_string ("buffer"); \ + buffer_list_quark = g_quark_from_static_string ("bufferlist"); \ + event_quark = g_quark_from_static_string ("event"); \ + \ + for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { \ + flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); \ + } \ + \ + GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", \ + GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \ +} + +#define gst_pad_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT, _do_init); + +static void +gst_pad_class_init (GstPadClass * klass) +{ + GObjectClass *gobject_class; + GstObjectClass *gstobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstobject_class = GST_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstPadPrivate)); + + gobject_class->dispose = gst_pad_dispose; + gobject_class->finalize = gst_pad_finalize; + gobject_class->set_property = gst_pad_set_property; + gobject_class->get_property = gst_pad_get_property; + + /** + * GstPad::linked: + * @pad: the pad that emitted the signal + * @peer: the peer pad that has been connected + * + * Signals that a pad has been linked to the peer pad. + */ + gst_pad_signals[PAD_LINKED] = + g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPadClass, linked), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD); + /** + * GstPad::unlinked: + * @pad: the pad that emitted the signal + * @peer: the peer pad that has been disconnected + * + * Signals that a pad has been unlinked from the peer pad. + */ + gst_pad_signals[PAD_UNLINKED] = + g_signal_new ("unlinked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPadClass, unlinked), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD); + + pspec_caps = g_param_spec_boxed ("caps", "Caps", + "The capabilities of the pad", GST_TYPE_CAPS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PAD_PROP_CAPS, pspec_caps); + + g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION, + g_param_spec_enum ("direction", "Direction", "The direction of the pad", + GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */ + g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE, + g_param_spec_object ("template", "Template", + "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPad:offset: + * + * The offset that will be applied to the running time of the pad. + * + * Since: 1.6 + */ + g_object_class_install_property (gobject_class, PAD_PROP_OFFSET, + g_param_spec_int64 ("offset", "Offset", + "The running time offset of the pad", 0, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstobject_class->path_string_separator = "."; + + /* Register common function pointer descriptions */ + GST_DEBUG_REGISTER_FUNCPTR (gst_pad_activate_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_pad_event_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_pad_query_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_pad_iterate_internal_links_default); + GST_DEBUG_REGISTER_FUNCPTR (gst_pad_chain_list_default); +} + +static void +gst_pad_init (GstPad * pad) +{ + pad->priv = GST_PAD_GET_PRIVATE (pad); + + GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN; + + GST_PAD_ACTIVATEFUNC (pad) = gst_pad_activate_default; + GST_PAD_EVENTFUNC (pad) = gst_pad_event_default; + GST_PAD_QUERYFUNC (pad) = gst_pad_query_default; + GST_PAD_ITERINTLINKFUNC (pad) = gst_pad_iterate_internal_links_default; + GST_PAD_CHAINLISTFUNC (pad) = gst_pad_chain_list_default; + + GST_PAD_SET_FLUSHING (pad); + + g_rec_mutex_init (&pad->stream_rec_lock); + + g_cond_init (&pad->block_cond); + + g_hook_list_init (&pad->probes, sizeof (GstProbe)); + + pad->priv->events = g_array_sized_new (FALSE, TRUE, sizeof (PadEvent), 16); + pad->priv->events_cookie = 0; + pad->priv->last_cookie = -1; + g_cond_init (&pad->priv->activation_cond); + + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; +} + +/* called when setting the pad inactive. It removes all sticky events from + * the pad. must be called with object lock */ +static void +remove_events (GstPad * pad) +{ + guint i, len; + GArray *events; + gboolean notify = FALSE; + + events = pad->priv->events; + + len = events->len; + for (i = 0; i < len; i++) { + PadEvent *ev = &g_array_index (events, PadEvent, i); + GstEvent *event = ev->event; + + ev->event = NULL; + + if (event && GST_EVENT_TYPE (event) == GST_EVENT_CAPS) + notify = TRUE; + + gst_event_unref (event); + } + + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS); + g_array_set_size (events, 0); + pad->priv->events_cookie++; + + if (notify) { + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pad, "notify caps"); + g_object_notify_by_pspec ((GObject *) pad, pspec_caps); + + GST_OBJECT_LOCK (pad); + } +} + +/* should be called with object lock */ +static PadEvent * +find_event_by_type (GstPad * pad, GstEventType type, guint idx) +{ + guint i, len; + GArray *events; + PadEvent *ev; + + events = pad->priv->events; + len = events->len; + + for (i = 0; i < len; i++) { + ev = &g_array_index (events, PadEvent, i); + if (ev->event == NULL) + continue; + + if (GST_EVENT_TYPE (ev->event) == type) { + if (idx == 0) + goto found; + idx--; + } else if (GST_EVENT_TYPE (ev->event) > type) { + break; + } + } + ev = NULL; +found: + return ev; +} + +/* should be called with OBJECT lock */ +static PadEvent * +find_event (GstPad * pad, GstEvent * event) +{ + guint i, len; + GArray *events; + PadEvent *ev; + + events = pad->priv->events; + len = events->len; + + for (i = 0; i < len; i++) { + ev = &g_array_index (events, PadEvent, i); + if (event == ev->event) + goto found; + else if (GST_EVENT_TYPE (ev->event) > GST_EVENT_TYPE (event)) + break; + } + ev = NULL; +found: + return ev; +} + +/* should be called with OBJECT lock */ +static void +remove_event_by_type (GstPad * pad, GstEventType type) +{ + guint i, len; + GArray *events; + PadEvent *ev; + + events = pad->priv->events; + len = events->len; + + i = 0; + while (i < len) { + ev = &g_array_index (events, PadEvent, i); + if (ev->event == NULL) + goto next; + + if (GST_EVENT_TYPE (ev->event) > type) + break; + else if (GST_EVENT_TYPE (ev->event) != type) + goto next; + + gst_event_unref (ev->event); + g_array_remove_index (events, i); + len--; + pad->priv->events_cookie++; + continue; + + next: + i++; + } +} + +/* check all events on srcpad against those on sinkpad. All events that are not + * on sinkpad are marked as received=%FALSE and the PENDING_EVENTS is set on the + * srcpad so that the events will be sent next time */ +/* should be called with srcpad and sinkpad LOCKS */ +static void +schedule_events (GstPad * srcpad, GstPad * sinkpad) +{ + gint i, len; + GArray *events; + PadEvent *ev; + gboolean pending = FALSE; + + events = srcpad->priv->events; + len = events->len; + + for (i = 0; i < len; i++) { + ev = &g_array_index (events, PadEvent, i); + if (ev->event == NULL) + continue; + + if (sinkpad == NULL || !find_event (sinkpad, ev->event)) { + ev->received = FALSE; + pending = TRUE; + } + } + if (pending) + GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PENDING_EVENTS); +} + +typedef gboolean (*PadEventFunction) (GstPad * pad, PadEvent * ev, + gpointer user_data); + +/* should be called with pad LOCK */ +static void +events_foreach (GstPad * pad, PadEventFunction func, gpointer user_data) +{ + guint i, len; + GArray *events; + gboolean ret; + guint cookie; + + events = pad->priv->events; + +restart: + cookie = pad->priv->events_cookie; + i = 0; + len = events->len; + while (i < len) { + PadEvent *ev, ev_ret; + + ev = &g_array_index (events, PadEvent, i); + if (G_UNLIKELY (ev->event == NULL)) + goto next; + + /* take aditional ref, func might release the lock */ + ev_ret.event = gst_event_ref (ev->event); + ev_ret.received = ev->received; + + ret = func (pad, &ev_ret, user_data); + + /* recheck the cookie, lock might have been released and the list could have + * changed */ + if (G_UNLIKELY (cookie != pad->priv->events_cookie)) { + if (G_LIKELY (ev_ret.event)) + gst_event_unref (ev_ret.event); + goto restart; + } + + /* store the received state */ + ev->received = ev_ret.received; + + /* if the event changed, we need to do something */ + if (G_UNLIKELY (ev->event != ev_ret.event)) { + if (G_UNLIKELY (ev_ret.event == NULL)) { + /* function unreffed and set the event to NULL, remove it */ + gst_event_unref (ev->event); + g_array_remove_index (events, i); + len--; + cookie = ++pad->priv->events_cookie; + continue; + } else { + /* function gave a new event for us */ + gst_event_take (&ev->event, ev_ret.event); + } + } else { + /* just unref, nothing changed */ + gst_event_unref (ev_ret.event); + } + if (!ret) + break; + next: + i++; + } +} + +/* should be called with LOCK */ +static GstEvent * +_apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream) +{ + gint64 offset; + + GST_DEBUG_OBJECT (pad, "apply pad offset %" GST_STIME_FORMAT, + GST_STIME_ARGS (pad->offset)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + GstSegment segment; + + g_assert (!upstream); + + /* copy segment values */ + gst_event_copy_segment (event, &segment); + gst_event_unref (event); + + gst_segment_offset_running_time (&segment, segment.format, pad->offset); + event = gst_event_new_segment (&segment); + } + + event = gst_event_make_writable (event); + offset = gst_event_get_running_time_offset (event); + if (upstream) + offset -= pad->offset; + else + offset += pad->offset; + gst_event_set_running_time_offset (event, offset); + + return event; +} + +static inline GstEvent * +apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream) +{ + if (G_UNLIKELY (pad->offset != 0)) + return _apply_pad_offset (pad, event, upstream); + return event; +} + + +/* should be called with the OBJECT_LOCK */ +static GstCaps * +get_pad_caps (GstPad * pad) +{ + GstCaps *caps = NULL; + PadEvent *ev; + + ev = find_event_by_type (pad, GST_EVENT_CAPS, 0); + if (ev && ev->event) + gst_event_parse_caps (ev->event, &caps); + + return caps; +} + +static void +gst_pad_dispose (GObject * object) +{ + GstPad *pad = GST_PAD_CAST (object); + GstPad *peer; + + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pad, "%p dispose", pad); + + /* unlink the peer pad */ + if ((peer = gst_pad_get_peer (pad))) { + /* window for MT unsafeness, someone else could unlink here + * and then we call unlink with wrong pads. The unlink + * function would catch this and safely return failed. */ + if (GST_PAD_IS_SRC (pad)) + gst_pad_unlink (pad, peer); + else + gst_pad_unlink (peer, pad); + + gst_object_unref (peer); + } + + gst_pad_set_pad_template (pad, NULL); + + GST_OBJECT_LOCK (pad); + remove_events (pad); + GST_OBJECT_UNLOCK (pad); + + g_hook_list_clear (&pad->probes); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_pad_finalize (GObject * object) +{ + GstPad *pad = GST_PAD_CAST (object); + GstTask *task; + + /* in case the task is still around, clean it up */ + if ((task = GST_PAD_TASK (pad))) { + gst_task_join (task); + GST_PAD_TASK (pad) = NULL; + gst_object_unref (task); + } + + if (pad->activatenotify) + pad->activatenotify (pad->activatedata); + if (pad->activatemodenotify) + pad->activatemodenotify (pad->activatemodedata); + if (pad->linknotify) + pad->linknotify (pad->linkdata); + if (pad->unlinknotify) + pad->unlinknotify (pad->unlinkdata); + if (pad->chainnotify) + pad->chainnotify (pad->chaindata); + if (pad->chainlistnotify) + pad->chainlistnotify (pad->chainlistdata); + if (pad->getrangenotify) + pad->getrangenotify (pad->getrangedata); + if (pad->eventnotify) + pad->eventnotify (pad->eventdata); + if (pad->querynotify) + pad->querynotify (pad->querydata); + if (pad->iterintlinknotify) + pad->iterintlinknotify (pad->iterintlinkdata); + + g_rec_mutex_clear (&pad->stream_rec_lock); + g_cond_clear (&pad->block_cond); + g_cond_clear (&pad->priv->activation_cond); + g_array_free (pad->priv->events, TRUE); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + g_return_if_fail (GST_IS_PAD (object)); + + switch (prop_id) { + case PAD_PROP_DIRECTION: + GST_PAD_DIRECTION (object) = (GstPadDirection) g_value_get_enum (value); + break; + case PAD_PROP_TEMPLATE: + gst_pad_set_pad_template (GST_PAD_CAST (object), + (GstPadTemplate *) g_value_get_object (value)); + break; + case PAD_PROP_OFFSET: + gst_pad_set_offset (GST_PAD_CAST (object), g_value_get_int64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + g_return_if_fail (GST_IS_PAD (object)); + + switch (prop_id) { + case PAD_PROP_CAPS: + GST_OBJECT_LOCK (object); + g_value_set_boxed (value, get_pad_caps (GST_PAD_CAST (object))); + GST_OBJECT_UNLOCK (object); + break; + case PAD_PROP_DIRECTION: + g_value_set_enum (value, GST_PAD_DIRECTION (object)); + break; + case PAD_PROP_TEMPLATE: + g_value_set_object (value, GST_PAD_PAD_TEMPLATE (object)); + break; + case PAD_PROP_OFFSET: + g_value_set_int64 (value, gst_pad_get_offset (GST_PAD_CAST (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_pad_new: + * @name: (allow-none): the name of the new pad. + * @direction: the #GstPadDirection of the pad. + * + * Creates a new pad with the given name in the given direction. + * If name is %NULL, a guaranteed unique name (across all pads) + * will be assigned. + * This function makes a copy of the name so you can safely free the name. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + * + * MT safe. + */ +GstPad * +gst_pad_new (const gchar * name, GstPadDirection direction) +{ + return g_object_new (GST_TYPE_PAD, + "name", name, "direction", direction, NULL); +} + +/** + * gst_pad_new_from_template: + * @templ: the pad template to use + * @name: (allow-none): the name of the pad + * + * Creates a new pad with the given name from the given template. + * If name is %NULL, a guaranteed unique name (across all pads) + * will be assigned. + * This function makes a copy of the name so you can safely free the name. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ +GstPad * +gst_pad_new_from_template (GstPadTemplate * templ, const gchar * name) +{ + GType pad_type = + GST_PAD_TEMPLATE_GTYPE (templ) == + G_TYPE_NONE ? GST_TYPE_PAD : GST_PAD_TEMPLATE_GTYPE (templ); + + g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); + + return g_object_new (pad_type, + "name", name, "direction", templ->direction, "template", templ, NULL); +} + +/** + * gst_pad_new_from_static_template: + * @templ: the #GstStaticPadTemplate to use + * @name: the name of the pad + * + * Creates a new pad with the given name from the given static template. + * If name is %NULL, a guaranteed unique name (across all pads) + * will be assigned. + * This function makes a copy of the name so you can safely free the name. + * + * Returns: (transfer floating) (nullable): a new #GstPad, or %NULL in + * case of an error. + */ +GstPad * +gst_pad_new_from_static_template (GstStaticPadTemplate * templ, + const gchar * name) +{ + GstPad *pad; + GstPadTemplate *template; + + template = gst_static_pad_template_get (templ); + pad = gst_pad_new_from_template (template, name); + gst_object_unref (template); + return pad; +} + +#define ACQUIRE_PARENT(pad, parent, label) \ + G_STMT_START { \ + if (G_LIKELY ((parent = GST_OBJECT_PARENT (pad)))) \ + gst_object_ref (parent); \ + else if (G_LIKELY (GST_PAD_NEEDS_PARENT (pad))) \ + goto label; \ + } G_STMT_END + +#define RELEASE_PARENT(parent) \ + G_STMT_START { \ + if (G_LIKELY (parent)) \ + gst_object_unref (parent); \ + } G_STMT_END + +/** + * gst_pad_get_direction: + * @pad: a #GstPad to get the direction of. + * + * Gets the direction of the pad. The direction of the pad is + * decided at construction time so this function does not take + * the LOCK. + * + * Returns: the #GstPadDirection of the pad. + * + * MT safe. + */ +GstPadDirection +gst_pad_get_direction (GstPad * pad) +{ + GstPadDirection result; + + /* PAD_UNKNOWN is a little silly but we need some sort of + * error return value */ + g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN); + + result = GST_PAD_DIRECTION (pad); + + return result; +} + +static gboolean +gst_pad_activate_default (GstPad * pad, GstObject * parent) +{ + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + return activate_mode_internal (pad, parent, GST_PAD_MODE_PUSH, TRUE); +} + +/** + * gst_pad_mode_get_name: + * @mode: the pad mode + * + * Return the name of a pad mode, for use in debug messages mostly. + * + * Returns: short mnemonic for pad mode @mode + */ +const gchar * +gst_pad_mode_get_name (GstPadMode mode) +{ + switch (mode) { + case GST_PAD_MODE_NONE: + return "none"; + case GST_PAD_MODE_PUSH: + return "push"; + case GST_PAD_MODE_PULL: + return "pull"; + default: + break; + } + return "unknown"; +} + +/* Returns TRUE if pad wasn't already in the new_mode */ +static gboolean +pre_activate (GstPad * pad, GstPadMode new_mode) +{ + switch (new_mode) { + case GST_PAD_MODE_NONE: + GST_OBJECT_LOCK (pad); + while (G_UNLIKELY (pad->priv->in_activation)) + g_cond_wait (&pad->priv->activation_cond, GST_OBJECT_GET_LOCK (pad)); + if (new_mode == GST_PAD_MODE (pad)) { + GST_WARNING_OBJECT (pad, + "Pad is already in the process of being deactivated"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } + pad->priv->in_activation = TRUE; + GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing"); + GST_PAD_SET_FLUSHING (pad); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + GST_PAD_MODE (pad) = new_mode; + /* unlock blocked pads so element can resume and stop */ + GST_PAD_BLOCK_BROADCAST (pad); + GST_OBJECT_UNLOCK (pad); + break; + case GST_PAD_MODE_PUSH: + case GST_PAD_MODE_PULL: + GST_OBJECT_LOCK (pad); + while (G_UNLIKELY (pad->priv->in_activation)) + g_cond_wait (&pad->priv->activation_cond, GST_OBJECT_GET_LOCK (pad)); + if (new_mode == GST_PAD_MODE (pad)) { + GST_WARNING_OBJECT (pad, + "Pad is already in the process of being activated"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } + pad->priv->in_activation = TRUE; + GST_DEBUG_OBJECT (pad, "setting pad into %s mode, unset flushing", + gst_pad_mode_get_name (new_mode)); + GST_PAD_UNSET_FLUSHING (pad); + pad->ABI.abi.last_flowret = GST_FLOW_OK; + GST_PAD_MODE (pad) = new_mode; + if (GST_PAD_IS_SINK (pad)) { + GstPad *peer; + /* make sure the peer src pad sends us all events */ + if ((peer = GST_PAD_PEER (pad))) { + gst_object_ref (peer); + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pad, "reschedule events on peer %s:%s", + GST_DEBUG_PAD_NAME (peer)); + + GST_OBJECT_LOCK (peer); + schedule_events (peer, NULL); + GST_OBJECT_UNLOCK (peer); + + gst_object_unref (peer); + } else { + GST_OBJECT_UNLOCK (pad); + } + } else { + GST_OBJECT_UNLOCK (pad); + } + break; + } + return TRUE; +} + +static void +post_activate (GstPad * pad, GstPadMode new_mode) +{ + switch (new_mode) { + case GST_PAD_MODE_NONE: + GST_OBJECT_LOCK (pad); + pad->priv->in_activation = FALSE; + g_cond_broadcast (&pad->priv->activation_cond); + GST_OBJECT_UNLOCK (pad); + + /* ensures that streaming stops */ + GST_PAD_STREAM_LOCK (pad); + GST_DEBUG_OBJECT (pad, "stopped streaming"); + GST_OBJECT_LOCK (pad); + remove_events (pad); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + break; + case GST_PAD_MODE_PUSH: + case GST_PAD_MODE_PULL: + GST_OBJECT_LOCK (pad); + pad->priv->in_activation = FALSE; + g_cond_broadcast (&pad->priv->activation_cond); + GST_OBJECT_UNLOCK (pad); + /* NOP */ + break; + } +} + +/** + * gst_pad_set_active: + * @pad: the #GstPad to activate or deactivate. + * @active: whether or not the pad should be active. + * + * Activates or deactivates the given pad. + * Normally called from within core state change functions. + * + * If @active, makes sure the pad is active. If it is already active, either in + * push or pull mode, just return. Otherwise dispatches to the pad's activate + * function to perform the actual activation. + * + * If not @active, calls gst_pad_activate_mode() with the pad's current mode + * and a %FALSE argument. + * + * Returns: %TRUE if the operation was successful. + * + * MT safe. + */ +gboolean +gst_pad_set_active (GstPad * pad, gboolean active) +{ + GstObject *parent; + GstPadMode old; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + old = GST_PAD_MODE (pad); + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + if (active) { + if (old == GST_PAD_MODE_NONE) { + GST_DEBUG_OBJECT (pad, "activating pad from none"); + ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent); + if (ret) + pad->ABI.abi.last_flowret = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (pad, "pad was active in %s mode", + gst_pad_mode_get_name (old)); + ret = TRUE; + } + } else { + if (old == GST_PAD_MODE_NONE) { + GST_DEBUG_OBJECT (pad, "pad was inactive"); + ret = TRUE; + } else { + GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode", + gst_pad_mode_get_name (old)); + ret = activate_mode_internal (pad, parent, old, FALSE); + if (ret) + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + } + } + + RELEASE_PARENT (parent); + + if (G_UNLIKELY (!ret)) + goto failed; + + return ret; + + /* ERRORS */ +no_parent: + { + GST_DEBUG_OBJECT (pad, "no parent"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +failed: + { + GST_OBJECT_LOCK (pad); + if (!active) { + g_critical ("Failed to deactivate pad %s:%s, very bad", + GST_DEBUG_PAD_NAME (pad)); + } else { + GST_WARNING_OBJECT (pad, "Failed to activate pad"); + } + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +static gboolean +activate_mode_internal (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean res = FALSE; + GstPadMode old, new; + GstPadDirection dir; + GstPad *peer; + + GST_OBJECT_LOCK (pad); + old = GST_PAD_MODE (pad); + dir = GST_PAD_DIRECTION (pad); + GST_OBJECT_UNLOCK (pad); + + new = active ? mode : GST_PAD_MODE_NONE; + + if (old == new) + goto was_ok; + + if (active && old != mode && old != GST_PAD_MODE_NONE) { + /* pad was activate in the wrong direction, deactivate it + * and reactivate it in the requested mode */ + GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode", + gst_pad_mode_get_name (old)); + + if (G_UNLIKELY (!activate_mode_internal (pad, parent, old, FALSE))) + goto deactivate_failed; + old = GST_PAD_MODE_NONE; + } + + switch (mode) { + case GST_PAD_MODE_PULL: + { + if (dir == GST_PAD_SINK) { + if ((peer = gst_pad_get_peer (pad))) { + GST_DEBUG_OBJECT (pad, "calling peer"); + if (G_UNLIKELY (!gst_pad_activate_mode (peer, mode, active))) + goto peer_failed; + gst_object_unref (peer); + } else { + /* there is no peer, this is only fatal when we activate. When we + * deactivate, we must assume the application has unlinked the peer and + * will deactivate it eventually. */ + if (active) + goto not_linked; + else + GST_DEBUG_OBJECT (pad, "deactivating unlinked pad"); + } + } else { + if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL)) + goto failure; /* Can't activate pull on a src without a + getrange function */ + } + break; + } + default: + break; + } + + /* Mark pad as needing reconfiguration */ + if (active) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + + /* pre_activate returns TRUE if we weren't already in the process of + * switching to the 'new' mode */ + if (pre_activate (pad, new)) { + + if (GST_PAD_ACTIVATEMODEFUNC (pad)) { + if (G_UNLIKELY (!GST_PAD_ACTIVATEMODEFUNC (pad) (pad, parent, mode, + active))) + goto failure; + } else { + /* can happen for sinks of passthrough elements */ + } + + post_activate (pad, new); + } + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in %s mode", + active ? "activated" : "deactivated", gst_pad_mode_get_name (mode)); + +exit_success: + res = TRUE; + + /* Clear sticky flags on deactivation */ + if (!active) { + GST_OBJECT_LOCK (pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + GST_OBJECT_UNLOCK (pad); + } + +exit: + return res; + +was_ok: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in %s mode", + active ? "activated" : "deactivated", gst_pad_mode_get_name (mode)); + goto exit_success; + } +deactivate_failed: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, + "failed to %s in switch to %s mode from %s mode", + (active ? "activate" : "deactivate"), gst_pad_mode_get_name (mode), + gst_pad_mode_get_name (old)); + goto exit; + } +peer_failed: + { + GST_OBJECT_LOCK (peer); + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, + "activate_mode on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer)); + GST_OBJECT_UNLOCK (peer); + gst_object_unref (peer); + goto exit; + } +not_linked: + { + GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "can't activate unlinked sink " + "pad in pull mode"); + goto exit; + } +failure: + { + GST_OBJECT_LOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in %s mode", + active ? "activate" : "deactivate", gst_pad_mode_get_name (mode)); + GST_PAD_SET_FLUSHING (pad); + GST_PAD_MODE (pad) = old; + pad->priv->in_activation = FALSE; + g_cond_broadcast (&pad->priv->activation_cond); + GST_OBJECT_UNLOCK (pad); + goto exit; + } +} + +/** + * gst_pad_activate_mode: + * @pad: the #GstPad to activate or deactivate. + * @mode: the requested activation mode + * @active: whether or not the pad should be active. + * + * Activates or deactivates the given pad in @mode via dispatching to the + * pad's activatemodefunc. For use from within pad activation functions only. + * + * If you don't know what this is, you probably don't want to call it. + * + * Returns: %TRUE if the operation was successful. + * + * MT safe. + */ +gboolean +gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active) +{ + GstObject *parent; + gboolean res; + GstPadMode old, new; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + + old = GST_PAD_MODE (pad); + new = active ? mode : GST_PAD_MODE_NONE; + if (old == new) + goto was_ok; + + ACQUIRE_PARENT (pad, parent, no_parent); + + GST_OBJECT_UNLOCK (pad); + + res = activate_mode_internal (pad, parent, mode, active); + + RELEASE_PARENT (parent); + + return res; + +was_ok: + { + GST_OBJECT_UNLOCK (pad); + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in %s mode", + active ? "activated" : "deactivated", gst_pad_mode_get_name (mode)); + return TRUE; + } +no_parent: + { + GST_WARNING_OBJECT (pad, "no parent"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +/** + * gst_pad_is_active: + * @pad: the #GstPad to query + * + * Query if a pad is active + * + * Returns: %TRUE if the pad is active. + * + * MT safe. + */ +gboolean +gst_pad_is_active (GstPad * pad) +{ + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + result = GST_PAD_IS_ACTIVE (pad); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +static void +cleanup_hook (GstPad * pad, GHook * hook) +{ + GstPadProbeType type; + + if (!G_HOOK_IS_VALID (hook)) + return; + + type = (hook->flags) >> G_HOOK_FLAG_USER_SHIFT; + + if (type & GST_PAD_PROBE_TYPE_BLOCKING) { + /* unblock when we remove the last blocking probe */ + pad->num_blocked--; + GST_DEBUG_OBJECT (pad, "remove blocking probe, now %d left", + pad->num_blocked); + + /* Might have new probes now that want to be called */ + GST_PAD_BLOCK_BROADCAST (pad); + + if (pad->num_blocked == 0) { + GST_DEBUG_OBJECT (pad, "last blocking probe removed, unblocking"); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKED); + } + } + g_hook_destroy_link (&pad->probes, hook); + pad->num_probes--; +} + +/** + * gst_pad_add_probe: + * @pad: the #GstPad to add the probe to + * @mask: the probe mask + * @callback: #GstPadProbeCallback that will be called with notifications of + * the pad state + * @user_data: (closure): user data passed to the callback + * @destroy_data: #GDestroyNotify for user_data + * + * Be notified of different states of pads. The provided callback is called for + * every state that matches @mask. + * + * Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are + * called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only + * exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called + * immediately if the pad is already idle while calling gst_pad_add_probe(). + * In each of the groups, probes are called in the order in which they were + * added. + * + * Returns: an id or 0 if no probe is pending. The id can be used to remove the + * probe with gst_pad_remove_probe(). When using GST_PAD_PROBE_TYPE_IDLE it can + * happen that the probe can be run immediately and if the probe returns + * GST_PAD_PROBE_REMOVE this functions returns 0. + * + * MT safe. + */ +gulong +gst_pad_add_probe (GstPad * pad, GstPadProbeType mask, + GstPadProbeCallback callback, gpointer user_data, + GDestroyNotify destroy_data) +{ + GHook *hook; + gulong res; + + g_return_val_if_fail (GST_IS_PAD (pad), 0); + g_return_val_if_fail (mask != 0, 0); + + GST_OBJECT_LOCK (pad); + + /* make a new probe */ + hook = g_hook_alloc (&pad->probes); + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "adding probe for mask 0x%08x", + mask); + + /* when no contraints are given for the types, assume all types are + * acceptable */ + if ((mask & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH) == 0) + mask |= GST_PAD_PROBE_TYPE_ALL_BOTH; + if ((mask & GST_PAD_PROBE_TYPE_SCHEDULING) == 0) + mask |= GST_PAD_PROBE_TYPE_SCHEDULING; + + /* store our flags and other fields */ + hook->flags |= (mask << G_HOOK_FLAG_USER_SHIFT); + hook->func = callback; + hook->data = user_data; + hook->destroy = destroy_data; + + /* add the probe */ + g_hook_append (&pad->probes, hook); + pad->num_probes++; + /* incremenent cookie so that the new hook get's called */ + pad->priv->probe_list_cookie++; + + /* get the id of the hook, we return this and it can be used to remove the + * probe later */ + res = hook->hook_id; + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got probe id %lu", res); + + if (mask & GST_PAD_PROBE_TYPE_BLOCKING) { + /* we have a block probe */ + pad->num_blocked++; + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKED); + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "added blocking probe, " + "now %d blocking probes", pad->num_blocked); + + /* Might have new probes now that want to be called */ + GST_PAD_BLOCK_BROADCAST (pad); + } + + /* call the callback if we need to be called for idle callbacks */ + if ((mask & GST_PAD_PROBE_TYPE_IDLE) && (callback != NULL)) { + if (pad->priv->using > 0) { + /* the pad is in use, we can't signal the idle callback yet. Since we set the + * flag above, the last thread to leave the push will do the callback. New + * threads going into the push will block. */ + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pad is in use, delay idle callback"); + GST_OBJECT_UNLOCK (pad); + } else { + GstPadProbeInfo info = { GST_PAD_PROBE_TYPE_IDLE, res, }; + GstPadProbeReturn ret; + + /* Keep another ref, the callback could destroy the pad */ + gst_object_ref (pad); + pad->priv->idle_running++; + + /* the pad is idle now, we can signal the idle callback now */ + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pad is idle, trigger idle callback"); + GST_OBJECT_UNLOCK (pad); + + ret = callback (pad, &info, user_data); + + GST_OBJECT_LOCK (pad); + switch (ret) { + case GST_PAD_PROBE_REMOVE: + /* remove the probe */ + GST_DEBUG_OBJECT (pad, "asked to remove hook"); + cleanup_hook (pad, hook); + res = 0; + break; + case GST_PAD_PROBE_DROP: + GST_DEBUG_OBJECT (pad, "asked to drop item"); + break; + case GST_PAD_PROBE_PASS: + GST_DEBUG_OBJECT (pad, "asked to pass item"); + break; + case GST_PAD_PROBE_OK: + GST_DEBUG_OBJECT (pad, "probe returned OK"); + break; + case GST_PAD_PROBE_HANDLED: + GST_DEBUG_OBJECT (pad, "probe handled the data"); + break; + default: + GST_DEBUG_OBJECT (pad, "probe returned %d", ret); + break; + } + pad->priv->idle_running--; + if (pad->priv->idle_running == 0) { + GST_PAD_BLOCK_BROADCAST (pad); + } + GST_OBJECT_UNLOCK (pad); + + gst_object_unref (pad); + } + } else { + GST_OBJECT_UNLOCK (pad); + } + return res; +} + +/** + * gst_pad_remove_probe: + * @pad: the #GstPad with the probe + * @id: the probe id to remove + * + * Remove the probe with @id from @pad. + * + * MT safe. + */ +void +gst_pad_remove_probe (GstPad * pad, gulong id) +{ + GHook *hook; + + g_return_if_fail (GST_IS_PAD (pad)); + + GST_OBJECT_LOCK (pad); + + hook = g_hook_get (&pad->probes, id); + if (hook == NULL) + goto not_found; + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "removing hook %ld", + hook->hook_id); + cleanup_hook (pad, hook); + GST_OBJECT_UNLOCK (pad); + + return; + +not_found: + { + GST_OBJECT_UNLOCK (pad); + g_warning ("%s: pad `%p' has no probe with id `%lu'", G_STRLOC, pad, id); + return; + } +} + +/** + * gst_pad_is_blocked: + * @pad: the #GstPad to query + * + * Checks if the pad is blocked or not. This function returns the + * last requested state of the pad. It is not certain that the pad + * is actually blocking at this point (see gst_pad_is_blocking()). + * + * Returns: %TRUE if the pad is blocked. + * + * MT safe. + */ +gboolean +gst_pad_is_blocked (GstPad * pad) +{ + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), result); + + GST_OBJECT_LOCK (pad); + result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_is_blocking: + * @pad: the #GstPad to query + * + * Checks if the pad is blocking or not. This is a guaranteed state + * of whether the pad is actually blocking on a #GstBuffer or a #GstEvent. + * + * Returns: %TRUE if the pad is blocking. + * + * MT safe. + */ +gboolean +gst_pad_is_blocking (GstPad * pad) +{ + gboolean result = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), result); + + GST_OBJECT_LOCK (pad); + /* the blocking flag is only valid if the pad is not flushing */ + result = GST_PAD_IS_BLOCKING (pad) && !GST_PAD_IS_FLUSHING (pad); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_needs_reconfigure: + * @pad: the #GstPad to check + * + * Check the #GST_PAD_FLAG_NEED_RECONFIGURE flag on @pad and return %TRUE + * if the flag was set. + * + * Returns: %TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag is set on @pad. + */ +gboolean +gst_pad_needs_reconfigure (GstPad * pad) +{ + gboolean reconfigure; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + reconfigure = GST_PAD_NEEDS_RECONFIGURE (pad); + GST_DEBUG_OBJECT (pad, "peeking RECONFIGURE flag %d", reconfigure); + GST_OBJECT_UNLOCK (pad); + + return reconfigure; +} + +/** + * gst_pad_check_reconfigure: + * @pad: the #GstPad to check + * + * Check and clear the #GST_PAD_FLAG_NEED_RECONFIGURE flag on @pad and return %TRUE + * if the flag was set. + * + * Returns: %TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag was set on @pad. + */ +gboolean +gst_pad_check_reconfigure (GstPad * pad) +{ + gboolean reconfigure; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + reconfigure = GST_PAD_NEEDS_RECONFIGURE (pad); + if (reconfigure) { + GST_DEBUG_OBJECT (pad, "remove RECONFIGURE flag"); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + } + GST_OBJECT_UNLOCK (pad); + + return reconfigure; +} + +/** + * gst_pad_mark_reconfigure: + * @pad: the #GstPad to mark + * + * Mark a pad for needing reconfiguration. The next call to + * gst_pad_check_reconfigure() will return %TRUE after this call. + */ +void +gst_pad_mark_reconfigure (GstPad * pad) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + GST_OBJECT_LOCK (pad); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + GST_OBJECT_UNLOCK (pad); +} + +/** + * gst_pad_set_activate_function: + * @p: a #GstPad. + * @f: the #GstPadActivateFunction to set. + * + * Calls gst_pad_set_activate_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_activate_function_full: + * @pad: a #GstPad. + * @activate: the #GstPadActivateFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @activate will not be used anymore. + * + * Sets the given activate function for @pad. The activate function will + * dispatch to gst_pad_activate_mode() to perform the actual activation. + * Only makes sense to set on sink pads. + * + * Call this function if your sink pad can start a pull-based task. + */ +void +gst_pad_set_activate_function_full (GstPad * pad, + GstPadActivateFunction activate, gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->activatenotify) + pad->activatenotify (pad->activatedata); + GST_PAD_ACTIVATEFUNC (pad) = activate; + pad->activatedata = user_data; + pad->activatenotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s", + GST_DEBUG_FUNCPTR_NAME (activate)); +} + +/** + * gst_pad_set_activatemode_function: + * @p: a #GstPad. + * @f: the #GstPadActivateModeFunction to set. + * + * Calls gst_pad_set_activatemode_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_activatemode_function_full: + * @pad: a #GstPad. + * @activatemode: the #GstPadActivateModeFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @activatemode will not be used anymore. + * + * Sets the given activate_mode function for the pad. An activate_mode function + * prepares the element for data passing. + */ +void +gst_pad_set_activatemode_function_full (GstPad * pad, + GstPadActivateModeFunction activatemode, gpointer user_data, + GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->activatemodenotify) + pad->activatemodenotify (pad->activatemodedata); + GST_PAD_ACTIVATEMODEFUNC (pad) = activatemode; + pad->activatemodedata = user_data; + pad->activatemodenotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatemodefunc set to %s", + GST_DEBUG_FUNCPTR_NAME (activatemode)); +} + +/** + * gst_pad_set_chain_function: + * @p: a sink #GstPad. + * @f: the #GstPadChainFunction to set. + * + * Calls gst_pad_set_chain_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_chain_function_full: + * @pad: a sink #GstPad. + * @chain: the #GstPadChainFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @chain will not be used anymore. + * + * Sets the given chain function for the pad. The chain function is called to + * process a #GstBuffer input buffer. see #GstPadChainFunction for more details. + */ +void +gst_pad_set_chain_function_full (GstPad * pad, GstPadChainFunction chain, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (GST_PAD_IS_SINK (pad)); + + if (pad->chainnotify) + pad->chainnotify (pad->chaindata); + GST_PAD_CHAINFUNC (pad) = chain; + pad->chaindata = user_data; + pad->chainnotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s", + GST_DEBUG_FUNCPTR_NAME (chain)); +} + +/** + * gst_pad_set_chain_list_function: + * @p: a sink #GstPad. + * @f: the #GstPadChainListFunction to set. + * + * Calls gst_pad_set_chain_list_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_chain_list_function_full: + * @pad: a sink #GstPad. + * @chainlist: the #GstPadChainListFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @chainlist will not be used anymore. + * + * Sets the given chain list function for the pad. The chainlist function is + * called to process a #GstBufferList input buffer list. See + * #GstPadChainListFunction for more details. + */ +void +gst_pad_set_chain_list_function_full (GstPad * pad, + GstPadChainListFunction chainlist, gpointer user_data, + GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (GST_PAD_IS_SINK (pad)); + + if (pad->chainlistnotify) + pad->chainlistnotify (pad->chainlistdata); + GST_PAD_CHAINLISTFUNC (pad) = chainlist; + pad->chainlistdata = user_data; + pad->chainlistnotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s", + GST_DEBUG_FUNCPTR_NAME (chainlist)); +} + +/** + * gst_pad_set_getrange_function: + * @p: a source #GstPad. + * @f: the #GstPadGetRangeFunction to set. + * + * Calls gst_pad_set_getrange_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_getrange_function_full: + * @pad: a source #GstPad. + * @get: the #GstPadGetRangeFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @get will not be used anymore. + * + * Sets the given getrange function for the pad. The getrange function is + * called to produce a new #GstBuffer to start the processing pipeline. see + * #GstPadGetRangeFunction for a description of the getrange function. + */ +void +gst_pad_set_getrange_function_full (GstPad * pad, GstPadGetRangeFunction get, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (GST_PAD_IS_SRC (pad)); + + if (pad->getrangenotify) + pad->getrangenotify (pad->getrangedata); + GST_PAD_GETRANGEFUNC (pad) = get; + pad->getrangedata = user_data; + pad->getrangenotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s", + GST_DEBUG_FUNCPTR_NAME (get)); +} + +/** + * gst_pad_set_event_function: + * @p: a #GstPad of either direction. + * @f: the #GstPadEventFunction to set. + * + * Calls gst_pad_set_event_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_event_function_full: + * @pad: a #GstPad of either direction. + * @event: the #GstPadEventFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @event will not be used anymore. + * + * Sets the given event handler for the pad. + */ +void +gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->eventnotify) + pad->eventnotify (pad->eventdata); + GST_PAD_EVENTFUNC (pad) = event; + pad->eventdata = user_data; + pad->eventnotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfunc for set to %s", + GST_DEBUG_FUNCPTR_NAME (event)); +} + +static gboolean +event_wrap (GstPad * pad, GstObject * object, GstEvent * event) +{ + GstFlowReturn ret; + + ret = GST_PAD_EVENTFULLFUNC (pad) (pad, object, event); + if (ret == GST_FLOW_OK) + return TRUE; + return FALSE; +} + +/** + * gst_pad_set_event_full_function: + * @p: a #GstPad of either direction. + * @f: the #GstPadEventFullFunction to set. + * + * Calls gst_pad_set_event_full_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_event_full_function_full: + * @pad: a #GstPad of either direction. + * @event: the #GstPadEventFullFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @event will not be used anymore. + * + * Sets the given event handler for the pad. + * + * Since: 1.8 + */ +void +gst_pad_set_event_full_function_full (GstPad * pad, + GstPadEventFullFunction event, gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->eventnotify) + pad->eventnotify (pad->eventdata); + GST_PAD_EVENTFULLFUNC (pad) = event; + GST_PAD_EVENTFUNC (pad) = event_wrap; + pad->eventdata = user_data; + pad->eventnotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfullfunc for set to %s", + GST_DEBUG_FUNCPTR_NAME (event)); +} + +/** + * gst_pad_set_query_function: + * @p: a #GstPad of either direction. + * @f: the #GstPadQueryFunction to set. + * + * Calls gst_pad_set_query_function_full() with %NULL for the user_data and + * notify. + */ +/** + * gst_pad_set_query_function_full: + * @pad: a #GstPad of either direction. + * @query: the #GstPadQueryFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @query will not be used anymore. + * + * Set the given query function for the pad. + */ +void +gst_pad_set_query_function_full (GstPad * pad, GstPadQueryFunction query, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->querynotify) + pad->querynotify (pad->querydata); + GST_PAD_QUERYFUNC (pad) = query; + pad->querydata = user_data; + pad->querynotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "queryfunc set to %s", + GST_DEBUG_FUNCPTR_NAME (query)); +} + +/** + * gst_pad_set_iterate_internal_links_function: + * @p: a #GstPad of either direction. + * @f: the #GstPadIterIntLinkFunction to set. + * + * Calls gst_pad_set_iterate_internal_links_function_full() with %NULL + * for the user_data and notify. + */ +/** + * gst_pad_set_iterate_internal_links_function_full: + * @pad: a #GstPad of either direction. + * @iterintlink: the #GstPadIterIntLinkFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @iterintlink will not be used anymore. + * + * Sets the given internal link iterator function for the pad. + */ +void +gst_pad_set_iterate_internal_links_function_full (GstPad * pad, + GstPadIterIntLinkFunction iterintlink, gpointer user_data, + GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->iterintlinknotify) + pad->iterintlinknotify (pad->iterintlinkdata); + GST_PAD_ITERINTLINKFUNC (pad) = iterintlink; + pad->iterintlinkdata = user_data; + pad->iterintlinknotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s", + GST_DEBUG_FUNCPTR_NAME (iterintlink)); +} + +/** + * gst_pad_set_link_function: + * @p: a #GstPad. + * @f: the #GstPadLinkFunction to set. + * + * Calls gst_pad_set_link_function_full() with %NULL + * for the user_data and notify. + */ +/** + * gst_pad_set_link_function_full: + * @pad: a #GstPad. + * @link: the #GstPadLinkFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @link will not be used anymore. + * + * Sets the given link function for the pad. It will be called when + * the pad is linked with another pad. + * + * The return value #GST_PAD_LINK_OK should be used when the connection can be + * made. + * + * The return value #GST_PAD_LINK_REFUSED should be used when the connection + * cannot be made for some reason. + * + * If @link is installed on a source pad, it should call the #GstPadLinkFunction + * of the peer sink pad, if present. + */ +void +gst_pad_set_link_function_full (GstPad * pad, GstPadLinkFunction link, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->linknotify) + pad->linknotify (pad->linkdata); + GST_PAD_LINKFUNC (pad) = link; + pad->linkdata = user_data; + pad->linknotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "linkfunc set to %s", + GST_DEBUG_FUNCPTR_NAME (link)); +} + +/** + * gst_pad_set_unlink_function: + * @p: a #GstPad. + * @f: the #GstPadUnlinkFunction to set. + * + * Calls gst_pad_set_unlink_function_full() with %NULL + * for the user_data and notify. + */ +/** + * gst_pad_set_unlink_function_full: + * @pad: a #GstPad. + * @unlink: the #GstPadUnlinkFunction to set. + * @user_data: user_data passed to @notify + * @notify: notify called when @unlink will not be used anymore. + * + * Sets the given unlink function for the pad. It will be called + * when the pad is unlinked. + */ +void +gst_pad_set_unlink_function_full (GstPad * pad, GstPadUnlinkFunction unlink, + gpointer user_data, GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + if (pad->unlinknotify) + pad->unlinknotify (pad->unlinkdata); + GST_PAD_UNLINKFUNC (pad) = unlink; + pad->unlinkdata = user_data; + pad->unlinknotify = notify; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "unlinkfunc set to %s", + GST_DEBUG_FUNCPTR_NAME (unlink)); +} + +/** + * gst_pad_unlink: + * @srcpad: the source #GstPad to unlink. + * @sinkpad: the sink #GstPad to unlink. + * + * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked + * signal on both pads. + * + * Returns: %TRUE if the pads were unlinked. This function returns %FALSE if + * the pads were not linked together. + * + * MT safe. + */ +gboolean +gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) +{ + gboolean result = FALSE; + GstElement *parent = NULL; + + g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); + g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE); + g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); + g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE); + + GST_TRACER_PAD_UNLINK_PRE (srcpad, sinkpad); + + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)", + GST_DEBUG_PAD_NAME (srcpad), srcpad, + GST_DEBUG_PAD_NAME (sinkpad), sinkpad); + + /* We need to notify the parent before taking any pad locks as the bin in + * question might be waiting for a lock on the pad while holding its lock + * that our message will try to take. */ + if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) { + if (GST_IS_ELEMENT (parent)) { + gst_element_post_message (parent, + gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad), + GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, TRUE)); + } else { + gst_object_unref (parent); + parent = NULL; + } + } + + GST_OBJECT_LOCK (srcpad); + GST_OBJECT_LOCK (sinkpad); + + if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad)) + goto not_linked_together; + + if (GST_PAD_UNLINKFUNC (srcpad)) { + GstObject *tmpparent; + + ACQUIRE_PARENT (srcpad, tmpparent, no_src_parent); + + GST_PAD_UNLINKFUNC (srcpad) (srcpad, tmpparent); + RELEASE_PARENT (tmpparent); + } +no_src_parent: + if (GST_PAD_UNLINKFUNC (sinkpad)) { + GstObject *tmpparent; + + ACQUIRE_PARENT (sinkpad, tmpparent, no_sink_parent); + + GST_PAD_UNLINKFUNC (sinkpad) (sinkpad, tmpparent); + RELEASE_PARENT (tmpparent); + } +no_sink_parent: + + /* first clear peers */ + GST_PAD_PEER (srcpad) = NULL; + GST_PAD_PEER (sinkpad) = NULL; + + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + + /* fire off a signal to each of the pads telling them + * that they've been unlinked */ + g_signal_emit (srcpad, gst_pad_signals[PAD_UNLINKED], 0, sinkpad); + g_signal_emit (sinkpad, gst_pad_signals[PAD_UNLINKED], 0, srcpad); + + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + result = TRUE; + +done: + if (parent != NULL) { + gst_element_post_message (parent, + gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad), + GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE)); + gst_object_unref (parent); + } + GST_TRACER_PAD_UNLINK_POST (srcpad, sinkpad, result); + return result; + + /* ERRORS */ +not_linked_together: + { + /* we do not emit a warning in this case because unlinking cannot + * be made MT safe.*/ + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + goto done; + } +} + +/** + * gst_pad_is_linked: + * @pad: pad to check + * + * Checks if a @pad is linked to another pad or not. + * + * Returns: %TRUE if the pad is linked, %FALSE otherwise. + * + * MT safe. + */ +gboolean +gst_pad_is_linked (GstPad * pad) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + result = (GST_PAD_PEER (pad) != NULL); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/* get the caps from both pads and see if the intersection + * is not empty. + * + * This function should be called with the pad LOCK on both + * pads + */ +static gboolean +gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink, + GstPadLinkCheck flags) +{ + GstCaps *srccaps = NULL; + GstCaps *sinkcaps = NULL; + gboolean compatible = FALSE; + + if (!(flags & (GST_PAD_LINK_CHECK_CAPS | GST_PAD_LINK_CHECK_TEMPLATE_CAPS))) + return TRUE; + + /* Doing the expensive caps checking takes priority over only checking the template caps */ + if (flags & GST_PAD_LINK_CHECK_CAPS) { + GST_OBJECT_UNLOCK (sink); + GST_OBJECT_UNLOCK (src); + + srccaps = gst_pad_query_caps (src, NULL); + sinkcaps = gst_pad_query_caps (sink, NULL); + + GST_OBJECT_LOCK (src); + GST_OBJECT_LOCK (sink); + } else { + /* If one of the two pads doesn't have a template, consider the intersection + * as valid.*/ + if (G_UNLIKELY ((GST_PAD_PAD_TEMPLATE (src) == NULL) + || (GST_PAD_PAD_TEMPLATE (sink) == NULL))) { + compatible = TRUE; + goto done; + } + srccaps = gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (src))); + sinkcaps = + gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (sink))); + } + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, src, "src caps %" GST_PTR_FORMAT, + srccaps); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, sink, "sink caps %" GST_PTR_FORMAT, + sinkcaps); + + /* if we have caps on both pads we can check the intersection. If one + * of the caps is %NULL, we return %TRUE. */ + if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) { + if (srccaps) + gst_caps_unref (srccaps); + if (sinkcaps) + gst_caps_unref (sinkcaps); + goto done; + } + + compatible = gst_caps_can_intersect (srccaps, sinkcaps); + gst_caps_unref (srccaps); + gst_caps_unref (sinkcaps); + +done: + GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible", + (compatible ? "" : "not ")); + + return compatible; +} + +/* check if the grandparents of both pads are the same. + * This check is required so that we don't try to link + * pads from elements in different bins without ghostpads. + * + * The LOCK should be held on both pads + */ +static gboolean +gst_pad_link_check_hierarchy (GstPad * src, GstPad * sink) +{ + GstObject *psrc, *psink; + + psrc = GST_OBJECT_PARENT (src); + psink = GST_OBJECT_PARENT (sink); + + /* if one of the pads has no parent, we allow the link */ + if (G_UNLIKELY (psrc == NULL || psink == NULL)) + goto no_parent; + + /* only care about parents that are elements */ + if (G_UNLIKELY (!GST_IS_ELEMENT (psrc) || !GST_IS_ELEMENT (psink))) + goto no_element_parent; + + /* if the parents are the same, we have a loop */ + if (G_UNLIKELY (psrc == psink)) + goto same_parents; + + /* if they both have a parent, we check the grandparents. We can not lock + * the parent because we hold on the child (pad) and the locking order is + * parent >> child. */ + psrc = GST_OBJECT_PARENT (psrc); + psink = GST_OBJECT_PARENT (psink); + + /* if they have grandparents but they are not the same */ + if (G_UNLIKELY (psrc != psink)) + goto wrong_grandparents; + + return TRUE; + + /* ERRORS */ +no_parent: + { + GST_CAT_DEBUG (GST_CAT_CAPS, + "one of the pads has no parent %" GST_PTR_FORMAT " and %" + GST_PTR_FORMAT, psrc, psink); + return TRUE; + } +no_element_parent: + { + GST_CAT_DEBUG (GST_CAT_CAPS, + "one of the pads has no element parent %" GST_PTR_FORMAT " and %" + GST_PTR_FORMAT, psrc, psink); + return TRUE; + } +same_parents: + { + GST_CAT_DEBUG (GST_CAT_CAPS, "pads have same parent %" GST_PTR_FORMAT, + psrc); + return FALSE; + } +wrong_grandparents: + { + GST_CAT_DEBUG (GST_CAT_CAPS, + "pads have different grandparents %" GST_PTR_FORMAT " and %" + GST_PTR_FORMAT, psrc, psink); + return FALSE; + } +} + +/* FIXME leftover from an attempt at refactoring... */ +/* call with the two pads unlocked, when this function returns GST_PAD_LINK_OK, + * the two pads will be locked in the srcpad, sinkpad order. */ +static GstPadLinkReturn +gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) +{ + GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + GST_OBJECT_LOCK (srcpad); + + if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL)) + goto src_was_linked; + + GST_OBJECT_LOCK (sinkpad); + + if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL)) + goto sink_was_linked; + + /* check hierarchy, pads can only be linked if the grandparents + * are the same. */ + if ((flags & GST_PAD_LINK_CHECK_HIERARCHY) + && !gst_pad_link_check_hierarchy (srcpad, sinkpad)) + goto wrong_hierarchy; + + /* check pad caps for non-empty intersection */ + if (!gst_pad_link_check_compatible_unlocked (srcpad, sinkpad, flags)) + goto no_format; + + /* FIXME check pad scheduling for non-empty intersection */ + + return GST_PAD_LINK_OK; + +src_was_linked: + { + GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s", + GST_DEBUG_PAD_NAME (srcpad), + GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad))); + /* we do not emit a warning in this case because unlinking cannot + * be made MT safe.*/ + GST_OBJECT_UNLOCK (srcpad); + return GST_PAD_LINK_WAS_LINKED; + } +sink_was_linked: + { + GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s", + GST_DEBUG_PAD_NAME (sinkpad), + GST_DEBUG_PAD_NAME (GST_PAD_PEER (sinkpad))); + /* we do not emit a warning in this case because unlinking cannot + * be made MT safe.*/ + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + return GST_PAD_LINK_WAS_LINKED; + } +wrong_hierarchy: + { + GST_CAT_INFO (GST_CAT_PADS, "pads have wrong hierarchy"); + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + return GST_PAD_LINK_WRONG_HIERARCHY; + } +no_format: + { + GST_CAT_INFO (GST_CAT_PADS, "caps are incompatible"); + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + return GST_PAD_LINK_NOFORMAT; + } +} + +/** + * gst_pad_can_link: + * @srcpad: the source #GstPad. + * @sinkpad: the sink #GstPad. + * + * Checks if the source pad and the sink pad are compatible so they can be + * linked. + * + * Returns: %TRUE if the pads can be linked. + */ +gboolean +gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad) +{ + GstPadLinkReturn result; + + /* generic checks */ + g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); + g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); + + GST_CAT_INFO (GST_CAT_PADS, "check if %s:%s can link with %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + /* gst_pad_link_prepare does everything for us, we only release the locks + * on the pads that it gets us. If this function returns !OK the locks are not + * taken anymore. */ + result = gst_pad_link_prepare (srcpad, sinkpad, GST_PAD_LINK_CHECK_DEFAULT); + if (result != GST_PAD_LINK_OK) + goto done; + + GST_OBJECT_UNLOCK (srcpad); + GST_OBJECT_UNLOCK (sinkpad); + +done: + return result == GST_PAD_LINK_OK; +} + +/** + * gst_pad_link_full: + * @srcpad: the source #GstPad to link. + * @sinkpad: the sink #GstPad to link. + * @flags: the checks to validate when linking + * + * Links the source pad and the sink pad. + * + * This variant of #gst_pad_link provides a more granular control on the + * checks being done when linking. While providing some considerable speedups + * the caller of this method must be aware that wrong usage of those flags + * can cause severe issues. Refer to the documentation of #GstPadLinkCheck + * for more information. + * + * MT Safe. + * + * Returns: A result code indicating if the connection worked or + * what went wrong. + */ +GstPadLinkReturn +gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags) +{ + GstPadLinkReturn result; + GstElement *parent; + GstPadLinkFunction srcfunc, sinkfunc; + + g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED); + g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION); + g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED); + g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), + GST_PAD_LINK_WRONG_DIRECTION); + + GST_TRACER_PAD_LINK_PRE (srcpad, sinkpad); + + /* Notify the parent early. See gst_pad_unlink for details. */ + if (G_LIKELY ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad))))) { + if (G_LIKELY (GST_IS_ELEMENT (parent))) { + gst_element_post_message (parent, + gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad), + GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE)); + } else { + gst_object_unref (parent); + parent = NULL; + } + } + + /* prepare will also lock the two pads */ + result = gst_pad_link_prepare (srcpad, sinkpad, flags); + + if (G_UNLIKELY (result != GST_PAD_LINK_OK)) { + GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), + gst_pad_link_get_name (result)); + goto done; + } + + /* must set peers before calling the link function */ + GST_PAD_PEER (srcpad) = sinkpad; + GST_PAD_PEER (sinkpad) = srcpad; + + /* check events, when something is different, mark pending */ + schedule_events (srcpad, sinkpad); + + /* get the link functions */ + srcfunc = GST_PAD_LINKFUNC (srcpad); + sinkfunc = GST_PAD_LINKFUNC (sinkpad); + + if (G_UNLIKELY (srcfunc || sinkfunc)) { + /* custom link functions, execute them */ + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + + if (srcfunc) { + GstObject *tmpparent; + + ACQUIRE_PARENT (srcpad, tmpparent, no_parent); + /* this one will call the peer link function */ + result = srcfunc (srcpad, tmpparent, sinkpad); + RELEASE_PARENT (tmpparent); + } else if (sinkfunc) { + GstObject *tmpparent; + + ACQUIRE_PARENT (sinkpad, tmpparent, no_parent); + /* if no source link function, we need to call the sink link + * function ourselves. */ + result = sinkfunc (sinkpad, tmpparent, srcpad); + RELEASE_PARENT (tmpparent); + } + no_parent: + + GST_OBJECT_LOCK (srcpad); + GST_OBJECT_LOCK (sinkpad); + + /* we released the lock, check if the same pads are linked still */ + if (GST_PAD_PEER (srcpad) != sinkpad || GST_PAD_PEER (sinkpad) != srcpad) + goto concurrent_link; + + if (G_UNLIKELY (result != GST_PAD_LINK_OK)) + goto link_failed; + } + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + + /* fire off a signal to each of the pads telling them + * that they've been linked */ + g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad); + g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad); + + GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + if (!(flags & GST_PAD_LINK_CHECK_NO_RECONFIGURE)) + gst_pad_send_event (srcpad, gst_event_new_reconfigure ()); + +done: + if (G_LIKELY (parent)) { + gst_element_post_message (parent, + gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad), + GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE)); + gst_object_unref (parent); + } + + GST_TRACER_PAD_LINK_POST (srcpad, sinkpad, result); + return result; + + /* ERRORS */ +concurrent_link: + { + GST_CAT_INFO (GST_CAT_PADS, "concurrent link between %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + + /* The other link operation succeeded first */ + result = GST_PAD_LINK_WAS_LINKED; + goto done; + } +link_failed: + { + GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), + gst_pad_link_get_name (result)); + + GST_PAD_PEER (srcpad) = NULL; + GST_PAD_PEER (sinkpad) = NULL; + + GST_OBJECT_UNLOCK (sinkpad); + GST_OBJECT_UNLOCK (srcpad); + + goto done; + } +} + +/** + * gst_pad_link: + * @srcpad: the source #GstPad to link. + * @sinkpad: the sink #GstPad to link. + * + * Links the source pad and the sink pad. + * + * Returns: A result code indicating if the connection worked or + * what went wrong. + * + * MT Safe. + */ +GstPadLinkReturn +gst_pad_link (GstPad * srcpad, GstPad * sinkpad) +{ + return gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_DEFAULT); +} + +static void +gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ) +{ + GstPadTemplate **template_p; + + /* this function would need checks if it weren't static */ + + GST_OBJECT_LOCK (pad); + template_p = &pad->padtemplate; + gst_object_replace ((GstObject **) template_p, (GstObject *) templ); + GST_OBJECT_UNLOCK (pad); + + if (templ) + gst_pad_template_pad_created (templ, pad); +} + +/** + * gst_pad_get_pad_template: + * @pad: a #GstPad. + * + * Gets the template for @pad. + * + * Returns: (transfer full) (nullable): the #GstPadTemplate from which + * this pad was instantiated, or %NULL if this pad has no + * template. Unref after usage. + */ +GstPadTemplate * +gst_pad_get_pad_template (GstPad * pad) +{ + GstPadTemplate *templ; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + templ = GST_PAD_PAD_TEMPLATE (pad); + + return (templ ? gst_object_ref (templ) : NULL); +} + +/** + * gst_pad_has_current_caps: + * @pad: a #GstPad to check + * + * Check if @pad has caps set on it with a #GST_EVENT_CAPS event. + * + * Returns: %TRUE when @pad has caps associated with it. + */ +gboolean +gst_pad_has_current_caps (GstPad * pad) +{ + gboolean result; + GstCaps *caps; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_OBJECT_LOCK (pad); + caps = get_pad_caps (pad); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "check current pad caps %" GST_PTR_FORMAT, caps); + result = (caps != NULL); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_get_current_caps: + * @pad: a #GstPad to get the current capabilities of. + * + * Gets the capabilities currently configured on @pad with the last + * #GST_EVENT_CAPS event. + * + * Returns: (transfer full) (nullable): the current caps of the pad with + * incremented ref-count or %NULL when pad has no caps. Unref after usage. + */ +GstCaps * +gst_pad_get_current_caps (GstPad * pad) +{ + GstCaps *result; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + GST_OBJECT_LOCK (pad); + if ((result = get_pad_caps (pad))) + gst_caps_ref (result); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "get current pad caps %" GST_PTR_FORMAT, result); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_get_pad_template_caps: + * @pad: a #GstPad to get the template capabilities from. + * + * Gets the capabilities for @pad's template. + * + * Returns: (transfer full): the #GstCaps of this pad template. + * Unref after usage. + */ +GstCaps * +gst_pad_get_pad_template_caps (GstPad * pad) +{ + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + if (GST_PAD_PAD_TEMPLATE (pad)) + return gst_pad_template_get_caps (GST_PAD_PAD_TEMPLATE (pad)); + + return gst_caps_ref (GST_CAPS_ANY); +} + +/** + * gst_pad_get_peer: + * @pad: a #GstPad to get the peer of. + * + * Gets the peer of @pad. This function refs the peer pad so + * you need to unref it after use. + * + * Returns: (transfer full) (nullable): the peer #GstPad. Unref after usage. + * + * MT safe. + */ +GstPad * +gst_pad_get_peer (GstPad * pad) +{ + GstPad *result; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + GST_OBJECT_LOCK (pad); + result = GST_PAD_PEER (pad); + if (result) + gst_object_ref (result); + GST_OBJECT_UNLOCK (pad); + + return result; +} + +/** + * gst_pad_get_allowed_caps: + * @pad: a #GstPad. + * + * Gets the capabilities of the allowed media types that can flow through + * @pad and its peer. + * + * The allowed capabilities is calculated as the intersection of the results of + * calling gst_pad_query_caps() on @pad and its peer. The caller owns a reference + * on the resulting caps. + * + * Returns: (transfer full) (nullable): the allowed #GstCaps of the + * pad link. Unref the caps when you no longer need it. This + * function returns %NULL when @pad has no peer. + * + * MT safe. + */ +GstCaps * +gst_pad_get_allowed_caps (GstPad * pad) +{ + GstCaps *mycaps; + GstCaps *caps = NULL; + GstQuery *query; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_PEER (pad) == NULL)) + goto no_peer; + GST_OBJECT_UNLOCK (pad); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting allowed caps"); + + mycaps = gst_pad_query_caps (pad, NULL); + + /* Query peer caps */ + query = gst_query_new_caps (mycaps); + if (!gst_pad_peer_query (pad, query)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "Caps query failed"); + goto end; + } + + gst_query_parse_caps_result (query, &caps); + if (caps == NULL) { + g_warn_if_fail (caps != NULL); + goto end; + } + gst_caps_ref (caps); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT, + caps); + +end: + gst_query_unref (query); + gst_caps_unref (mycaps); + + return caps; + +no_peer: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer"); + GST_OBJECT_UNLOCK (pad); + + return NULL; + } +} + +/** + * gst_pad_iterate_internal_links_default: + * @pad: the #GstPad to get the internal links of. + * @parent: (allow-none): the parent of @pad or %NULL + * + * Iterate the list of pads to which the given pad is linked to inside of + * the parent element. + * This is the default handler, and thus returns an iterator of all of the + * pads inside the parent element with opposite direction. + * + * The caller must free this iterator after use with gst_iterator_free(). + * + * Returns: (nullable): a #GstIterator of #GstPad, or %NULL if @pad + * has no parent. Unref each returned pad with gst_object_unref(). + */ +GstIterator * +gst_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent) +{ + GstIterator *res; + GList **padlist; + guint32 *cookie; + GMutex *lock; + gpointer owner; + GstElement *eparent; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + if (parent != NULL && GST_IS_ELEMENT (parent)) { + eparent = GST_ELEMENT_CAST (gst_object_ref (parent)); + } else { + GST_OBJECT_LOCK (pad); + eparent = GST_PAD_PARENT (pad); + if (!eparent || !GST_IS_ELEMENT (eparent)) + goto no_parent; + + gst_object_ref (eparent); + GST_OBJECT_UNLOCK (pad); + } + + if (pad->direction == GST_PAD_SRC) + padlist = &eparent->sinkpads; + else + padlist = &eparent->srcpads; + + GST_DEBUG_OBJECT (pad, "Making iterator"); + + cookie = &eparent->pads_cookie; + owner = eparent; + lock = GST_OBJECT_GET_LOCK (eparent); + + res = gst_iterator_new_list (GST_TYPE_PAD, + lock, cookie, padlist, (GObject *) owner, NULL); + + gst_object_unref (owner); + + return res; + + /* ERRORS */ +no_parent: + { + GST_OBJECT_UNLOCK (pad); + GST_DEBUG_OBJECT (pad, "no parent element"); + return NULL; + } +} + +/** + * gst_pad_iterate_internal_links: + * @pad: the GstPad to get the internal links of. + * + * Gets an iterator for the pads to which the given pad is linked to inside + * of the parent element. + * + * Each #GstPad element yielded by the iterator will have its refcount increased, + * so unref after use. + * + * Free-function: gst_iterator_free + * + * Returns: (transfer full) (nullable): a new #GstIterator of #GstPad + * or %NULL when the pad does not have an iterator function + * configured. Use gst_iterator_free() after usage. + */ +GstIterator * +gst_pad_iterate_internal_links (GstPad * pad) +{ + GstIterator *res = NULL; + GstObject *parent; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + GST_OBJECT_LOCK (pad); + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + if (GST_PAD_ITERINTLINKFUNC (pad)) + res = GST_PAD_ITERINTLINKFUNC (pad) (pad, parent); + + RELEASE_PARENT (parent); + + return res; + + /* ERRORS */ +no_parent: + { + GST_DEBUG_OBJECT (pad, "no parent"); + GST_OBJECT_UNLOCK (pad); + return NULL; + } +} + +/** + * gst_pad_forward: + * @pad: a #GstPad + * @forward: (scope call): a #GstPadForwardFunction + * @user_data: user data passed to @forward + * + * Calls @forward for all internally linked pads of @pad. This function deals with + * dynamically changing internal pads and will make sure that the @forward + * function is only called once for each pad. + * + * When @forward returns %TRUE, no further pads will be processed. + * + * Returns: %TRUE if one of the dispatcher functions returned %TRUE. + */ +gboolean +gst_pad_forward (GstPad * pad, GstPadForwardFunction forward, + gpointer user_data) +{ + gboolean result = FALSE; + GstIterator *iter; + gboolean done = FALSE; + GValue item = { 0, }; + GList *pushed_pads = NULL; + + iter = gst_pad_iterate_internal_links (pad); + + if (!iter) + goto no_iter; + + while (!done) { + switch (gst_iterator_next (iter, &item)) { + case GST_ITERATOR_OK: + { + GstPad *intpad; + + intpad = g_value_get_object (&item); + + /* if already pushed, skip. FIXME, find something faster to tag pads */ + if (intpad == NULL || g_list_find (pushed_pads, intpad)) { + g_value_reset (&item); + break; + } + + GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s", + GST_DEBUG_PAD_NAME (intpad)); + done = result = forward (intpad, user_data); + + pushed_pads = g_list_prepend (pushed_pads, intpad); + + g_value_reset (&item); + break; + } + case GST_ITERATOR_RESYNC: + /* We don't reset the result here because we don't push the event + * again on pads that got the event already and because we need + * to consider the result of the previous pushes */ + 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; + } + } + g_value_unset (&item); + gst_iterator_free (iter); + + g_list_free (pushed_pads); + +no_iter: + return result; +} + +typedef struct +{ + GstEvent *event; + gboolean result; + gboolean dispatched; +} EventData; + +static gboolean +event_forward_func (GstPad * pad, EventData * data) +{ + /* for each pad we send to, we should ref the event; it's up + * to downstream to unref again when handled. */ + GST_LOG_OBJECT (pad, "Reffing and pushing event %p (%s) to %s:%s", + data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad)); + + data->result |= gst_pad_push_event (pad, gst_event_ref (data->event)); + + data->dispatched = TRUE; + + /* don't stop */ + return FALSE; +} + +/** + * gst_pad_event_default: + * @pad: a #GstPad to call the default event handler on. + * @parent: (allow-none): the parent of @pad or %NULL + * @event: (transfer full): the #GstEvent to handle. + * + * Invokes the default event handler for the given pad. + * + * The EOS event will pause the task associated with @pad before it is forwarded + * to all internally linked pads, + * + * The event is sent to all pads internally linked to @pad. This function + * takes ownership of @event. + * + * Returns: %TRUE if the event was sent successfully. + */ +gboolean +gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean result, forward = TRUE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + GST_LOG_OBJECT (pad, "default event handler for event %" GST_PTR_FORMAT, + event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + forward = GST_PAD_IS_PROXY_CAPS (pad); + result = TRUE; + break; + default: + break; + } + + if (forward) { + EventData data; + + data.event = event; + data.dispatched = FALSE; + data.result = FALSE; + + gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data); + + /* for sinkpads without a parent element or without internal links, nothing + * will be dispatched but we still want to return TRUE. */ + if (data.dispatched) + result = data.result; + else + result = TRUE; + } + + gst_event_unref (event); + + return result; +} + +/* Default accept caps implementation just checks against + * the allowed caps for the pad */ +static gboolean +gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query) +{ + /* get the caps and see if it intersects to something not empty */ + GstCaps *caps, *allowed = NULL; + gboolean result; + + GST_DEBUG_OBJECT (pad, "query accept-caps %" GST_PTR_FORMAT, query); + + /* first forward the query to internally linked pads when we are dealing with + * a PROXY CAPS */ + if (GST_PAD_IS_PROXY_CAPS (pad)) { + result = gst_pad_proxy_query_accept_caps (pad, query); + if (result) + allowed = gst_pad_get_pad_template_caps (pad); + else + goto done; + } + + gst_query_parse_accept_caps (query, &caps); + if (!allowed) { + if (GST_PAD_IS_ACCEPT_TEMPLATE (pad)) { + allowed = gst_pad_get_pad_template_caps (pad); + } else { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pad, + "fallback ACCEPT_CAPS query, consider implementing a specialized version"); + allowed = gst_pad_query_caps (pad, caps); + } + } + + if (allowed) { + if (GST_PAD_IS_ACCEPT_INTERSECT (pad)) { + GST_DEBUG_OBJECT (pad, + "allowed caps intersect %" GST_PTR_FORMAT ", caps %" GST_PTR_FORMAT, + allowed, caps); + result = gst_caps_can_intersect (caps, allowed); + } else { + GST_DEBUG_OBJECT (pad, "allowed caps subset %" GST_PTR_FORMAT ", caps %" + GST_PTR_FORMAT, allowed, caps); + result = gst_caps_is_subset (caps, allowed); + } + gst_caps_unref (allowed); + } else { + GST_DEBUG_OBJECT (pad, "no compatible caps allowed on the pad"); + result = FALSE; + } + gst_query_set_accept_caps_result (query, result); + +done: + return TRUE; +} + +/* Default caps implementation */ +static gboolean +gst_pad_query_caps_default (GstPad * pad, GstQuery * query) +{ + GstCaps *result = NULL, *filter; + GstPadTemplate *templ; + gboolean fixed_caps; + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "query caps %" GST_PTR_FORMAT, + query); + + /* first try to proxy if we must */ + if (GST_PAD_IS_PROXY_CAPS (pad)) { + if ((gst_pad_proxy_query_caps (pad, query))) { + goto done; + } + } + + gst_query_parse_caps (query, &filter); + + /* no proxy or it failed, do default handling */ + fixed_caps = GST_PAD_IS_FIXED_CAPS (pad); + + GST_OBJECT_LOCK (pad); + if (fixed_caps) { + /* fixed caps, try the negotiated caps first */ + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "fixed pad caps: trying pad caps"); + if ((result = get_pad_caps (pad))) + goto filter_done_unlock; + } + + if ((templ = GST_PAD_PAD_TEMPLATE (pad))) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps"); + if ((result = GST_PAD_TEMPLATE_CAPS (templ))) + goto filter_done_unlock; + } + + if (!fixed_caps) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "non-fixed pad caps: trying pad caps"); + /* non fixed caps, try the negotiated caps */ + if ((result = get_pad_caps (pad))) + goto filter_done_unlock; + } + + /* this almost never happens */ + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps"); + result = GST_CAPS_ANY; + +filter_done_unlock: + GST_OBJECT_UNLOCK (pad); + + /* run the filter on the result */ + if (filter) { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "using caps %p %" GST_PTR_FORMAT " with filter %p %" + GST_PTR_FORMAT, result, result, filter, filter); + result = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT, + result, result); + } else { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "using caps %p %" GST_PTR_FORMAT, result, result); + result = gst_caps_ref (result); + } + gst_query_set_caps_result (query, result); + gst_caps_unref (result); + +done: + return TRUE; +} + +/* Default latency implementation */ +typedef struct +{ + guint count; + gboolean live; + GstClockTime min, max; +} LatencyFoldData; + +static gboolean +query_latency_default_fold (const GValue * item, GValue * ret, + gpointer user_data) +{ + GstPad *pad = g_value_get_object (item), *peer; + LatencyFoldData *fold_data = user_data; + GstQuery *query; + gboolean res = FALSE; + + query = gst_query_new_latency (); + + peer = gst_pad_get_peer (pad); + if (peer) { + res = gst_pad_peer_query (pad, query); + } else { + GST_LOG_OBJECT (pad, "No peer pad found, ignoring this pad"); + } + + if (res) { + gboolean live; + GstClockTime min, max; + + gst_query_parse_latency (query, &live, &min, &max); + + GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT + " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max); + + /* FIXME : Why do we only take values into account if it's live ? */ + if (live || fold_data->count == 0) { + if (min > fold_data->min) + fold_data->min = min; + + if (fold_data->max == GST_CLOCK_TIME_NONE) + fold_data->max = max; + else if (max < fold_data->max) + fold_data->max = max; + + fold_data->live = live; + } + fold_data->count += 1; + } else if (peer) { + GST_DEBUG_OBJECT (pad, "latency query failed"); + g_value_set_boolean (ret, FALSE); + } + + gst_query_unref (query); + if (peer) + gst_object_unref (peer); + + return TRUE; +} + +static gboolean +gst_pad_query_latency_default (GstPad * pad, GstQuery * query) +{ + GstIterator *it; + GstIteratorResult res; + GValue ret = G_VALUE_INIT; + gboolean query_ret; + LatencyFoldData fold_data; + + it = gst_pad_iterate_internal_links (pad); + if (!it) { + GST_DEBUG_OBJECT (pad, "Can't iterate internal links"); + return FALSE; + } + + g_value_init (&ret, G_TYPE_BOOLEAN); + +retry: + fold_data.count = 0; + fold_data.live = FALSE; + fold_data.min = 0; + fold_data.max = GST_CLOCK_TIME_NONE; + + g_value_set_boolean (&ret, TRUE); + res = gst_iterator_fold (it, query_latency_default_fold, &ret, &fold_data); + switch (res) { + case GST_ITERATOR_OK: + g_assert_not_reached (); + break; + case GST_ITERATOR_DONE: + break; + case GST_ITERATOR_ERROR: + g_value_set_boolean (&ret, FALSE); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + goto retry; + default: + g_assert_not_reached (); + break; + } + gst_iterator_free (it); + + query_ret = g_value_get_boolean (&ret); + if (query_ret) { + GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT + " max:%" G_GINT64_FORMAT, fold_data.live ? "true" : "false", + fold_data.min, fold_data.max); + + if (fold_data.min > fold_data.max) { + GST_ERROR_OBJECT (pad, "minimum latency bigger than maximum latency"); + } + + gst_query_set_latency (query, fold_data.live, fold_data.min, fold_data.max); + } else { + GST_LOG_OBJECT (pad, "latency query failed"); + } + + return query_ret; +} + +typedef struct +{ + GstQuery *query; + gboolean result; + gboolean dispatched; +} QueryData; + +static gboolean +query_forward_func (GstPad * pad, QueryData * data) +{ + GST_LOG_OBJECT (pad, "query peer %p (%s) of %s:%s", + data->query, GST_QUERY_TYPE_NAME (data->query), GST_DEBUG_PAD_NAME (pad)); + + data->result |= gst_pad_peer_query (pad, data->query); + + data->dispatched = TRUE; + + /* stop on first successful reply */ + return data->result; +} + +/** + * gst_pad_query_default: + * @pad: a #GstPad to call the default query handler on. + * @parent: (allow-none): the parent of @pad or %NULL + * @query: (transfer none): the #GstQuery to handle. + * + * Invokes the default query handler for the given pad. + * The query is sent to all pads internally linked to @pad. Note that + * if there are many possible sink pads that are internally linked to + * @pad, only one will be sent the query. + * Multi-sinkpad elements should implement custom query handlers. + * + * Returns: %TRUE if the query was performed successfully. + */ +gboolean +gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean forward, ret = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + forward = GST_PAD_IS_PROXY_SCHEDULING (pad); + break; + case GST_QUERY_ALLOCATION: + forward = GST_PAD_IS_PROXY_ALLOCATION (pad); + break; + case GST_QUERY_ACCEPT_CAPS: + ret = gst_pad_query_accept_caps_default (pad, query); + forward = FALSE; + break; + case GST_QUERY_CAPS: + ret = gst_pad_query_caps_default (pad, query); + forward = FALSE; + break; + case GST_QUERY_LATENCY: + ret = gst_pad_query_latency_default (pad, query); + forward = FALSE; + break; + case GST_QUERY_POSITION: + case GST_QUERY_SEEKING: + case GST_QUERY_FORMATS: + case GST_QUERY_JITTER: + case GST_QUERY_RATE: + case GST_QUERY_CONVERT: + default: + forward = TRUE; + break; + } + + GST_DEBUG_OBJECT (pad, "%sforwarding %p (%s) query", (forward ? "" : "not "), + query, GST_QUERY_TYPE_NAME (query)); + + if (forward) { + QueryData data; + + data.query = query; + data.dispatched = FALSE; + data.result = FALSE; + + gst_pad_forward (pad, (GstPadForwardFunction) query_forward_func, &data); + + if (data.dispatched) { + ret = data.result; + } else { + /* nothing dispatched, assume drained */ + if (GST_QUERY_TYPE (query) == GST_QUERY_DRAIN) + ret = TRUE; + else + ret = FALSE; + } + } + return ret; +} + +#define N_STACK_ALLOCATE_PROBES (16) + +static void +probe_hook_marshal (GHook * hook, ProbeMarshall * data) +{ + GstPad *pad = data->pad; + GstPadProbeInfo *info = data->info; + GstPadProbeType type, flags; + GstPadProbeCallback callback; + GstPadProbeReturn ret; + gpointer original_data; + guint i; + + /* if we have called this callback, do nothing. But only check + * if we're actually calling probes a second time */ + if (data->retry) { + for (i = 0; i < data->n_called_probes; i++) { + if (data->called_probes[i] == hook) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "hook %lu already called", hook->hook_id); + return; + } + } + } + + /* reallocate on the heap if we had more than 16 probes */ + if (data->n_called_probes == data->called_probes_size) { + if (data->called_probes_size > N_STACK_ALLOCATE_PROBES) { + data->called_probes_size *= 2; + data->called_probes = + g_renew (GHook *, data->called_probes, data->called_probes_size); + } else { + GHook **tmp = data->called_probes; + + data->called_probes_size *= 2; + data->called_probes = g_new (GHook *, data->called_probes_size); + memcpy (data->called_probes, tmp, + N_STACK_ALLOCATE_PROBES * sizeof (GHook *)); + } + } + data->called_probes[data->n_called_probes++] = hook; + + flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT; + type = info->type; + original_data = info->data; + + /* one of the scheduling types */ + if ((flags & GST_PAD_PROBE_TYPE_SCHEDULING & type) == 0) + goto no_match; + + if (G_UNLIKELY (data->handled)) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe previously returned HANDLED, not calling again"); + goto no_match; + } else if (G_UNLIKELY (data->dropped)) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe previously returned DROPPED, not calling again"); + goto no_match; + } + + if (type & GST_PAD_PROBE_TYPE_PUSH) { + /* one of the data types for non-idle probes */ + if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0 + && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0) + goto no_match; + } else if (type & GST_PAD_PROBE_TYPE_PULL) { + /* one of the data types for non-idle probes */ + if ((type & GST_PAD_PROBE_TYPE_BLOCKING) == 0 + && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0) + goto no_match; + } else { + /* Type must have PULL or PUSH probe types */ + g_assert_not_reached (); + } + + /* one of the blocking types must match */ + if ((type & GST_PAD_PROBE_TYPE_BLOCKING) && + (flags & GST_PAD_PROBE_TYPE_BLOCKING & type) == 0) + goto no_match; + if ((type & GST_PAD_PROBE_TYPE_BLOCKING) == 0 && + (flags & GST_PAD_PROBE_TYPE_BLOCKING)) + goto no_match; + /* only probes that have GST_PAD_PROBE_TYPE_EVENT_FLUSH set */ + if ((type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) && + (flags & GST_PAD_PROBE_TYPE_EVENT_FLUSH & type) == 0) + goto no_match; + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "hook %lu with flags 0x%08x matches", hook->hook_id, flags); + + data->marshalled = TRUE; + + callback = (GstPadProbeCallback) hook->func; + if (callback == NULL) + return; + + info->id = hook->hook_id; + + GST_OBJECT_UNLOCK (pad); + + ret = callback (pad, info, hook->data); + + GST_OBJECT_LOCK (pad); + + if (original_data != NULL && info->data == NULL) { + GST_DEBUG_OBJECT (pad, "data item in pad probe info was dropped"); + info->type = GST_PAD_PROBE_TYPE_INVALID; + data->dropped = TRUE; + } + + switch (ret) { + case GST_PAD_PROBE_REMOVE: + /* remove the probe */ + GST_DEBUG_OBJECT (pad, "asked to remove hook"); + cleanup_hook (pad, hook); + break; + case GST_PAD_PROBE_DROP: + /* need to drop the data, make sure other probes don't get called + * anymore */ + GST_DEBUG_OBJECT (pad, "asked to drop item"); + info->type = GST_PAD_PROBE_TYPE_INVALID; + data->dropped = TRUE; + break; + case GST_PAD_PROBE_HANDLED: + GST_DEBUG_OBJECT (pad, "probe handled data"); + data->handled = TRUE; + break; + case GST_PAD_PROBE_PASS: + /* inform the pad block to let things pass */ + GST_DEBUG_OBJECT (pad, "asked to pass item"); + data->pass = TRUE; + break; + case GST_PAD_PROBE_OK: + GST_DEBUG_OBJECT (pad, "probe returned OK"); + break; + default: + GST_DEBUG_OBJECT (pad, "probe returned %d", ret); + break; + } + return; + +no_match: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "hook %lu with flags 0x%08x does not match %08x", + hook->hook_id, flags, info->type); + return; + } +} + +/* a probe that does not take or return any data */ +#define PROBE_NO_DATA(pad,mask,label,defaultval) \ + G_STMT_START { \ + if (G_UNLIKELY (pad->num_probes)) { \ + GstFlowReturn pval = defaultval; \ + /* pass NULL as the data item */ \ + GstPadProbeInfo info = { mask, 0, NULL, 0, 0 }; \ + info.ABI.abi.flow_ret = defaultval; \ + ret = do_probe_callbacks (pad, &info, defaultval); \ + if (G_UNLIKELY (ret != pval && ret != GST_FLOW_OK)) \ + goto label; \ + } \ + } G_STMT_END + +#define PROBE_FULL(pad,mask,data,offs,size,label,handleable,handle_label) \ + G_STMT_START { \ + if (G_UNLIKELY (pad->num_probes)) { \ + /* pass the data item */ \ + GstPadProbeInfo info = { mask, 0, data, offs, size }; \ + info.ABI.abi.flow_ret = GST_FLOW_OK; \ + ret = do_probe_callbacks (pad, &info, GST_FLOW_OK); \ + /* store the possibly updated data item */ \ + data = GST_PAD_PROBE_INFO_DATA (&info); \ + /* if something went wrong, exit */ \ + if (G_UNLIKELY (ret != GST_FLOW_OK)) { \ + if (handleable && ret == GST_FLOW_CUSTOM_SUCCESS_1) { \ + ret = info.ABI.abi.flow_ret; \ + goto handle_label; \ + } \ + goto label; \ + } \ + } \ + } G_STMT_END + +#define PROBE_PUSH(pad,mask,data,label) \ + PROBE_FULL(pad, mask, data, -1, -1, label, FALSE, label); +#define PROBE_HANDLE(pad,mask,data,label,handle_label) \ + PROBE_FULL(pad, mask, data, -1, -1, label, TRUE, handle_label); +#define PROBE_PULL(pad,mask,data,offs,size,label) \ + PROBE_FULL(pad, mask, data, offs, size, label, FALSE, label); + +static GstFlowReturn +do_pad_idle_probe_wait (GstPad * pad) +{ + while (GST_PAD_IS_RUNNING_IDLE_PROBE (pad)) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "waiting idle probe to be removed"); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING); + GST_PAD_BLOCK_WAIT (pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING); + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked"); + + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + return GST_FLOW_FLUSHING; + } + return GST_FLOW_OK; +} + +#define PROBE_TYPE_IS_SERIALIZED(i) \ + ( \ + ( \ + (((i)->type & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | \ + GST_PAD_PROBE_TYPE_EVENT_FLUSH)) && \ + GST_EVENT_IS_SERIALIZED ((i)->data)) \ + ) || ( \ + (((i)->type & GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) && \ + GST_QUERY_IS_SERIALIZED ((i)->data)) \ + ) || ( \ + ((i)->type & (GST_PAD_PROBE_TYPE_BUFFER | \ + GST_PAD_PROBE_TYPE_BUFFER_LIST)) \ + ) \ + ) + +static GstFlowReturn +do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info, + GstFlowReturn defaultval) +{ + ProbeMarshall data; + guint cookie; + gboolean is_block; + GHook *called_probes[N_STACK_ALLOCATE_PROBES]; + + data.pad = pad; + data.info = info; + data.pass = FALSE; + data.handled = FALSE; + data.marshalled = FALSE; + data.dropped = FALSE; + + /* We stack-allocate for N_STACK_ALLOCATE_PROBES hooks as a first step. If more are needed, + * we will re-allocate with g_malloc(). This should usually never be needed + */ + data.called_probes = called_probes; + data.n_called_probes = 0; + data.called_probes_size = N_STACK_ALLOCATE_PROBES; + data.retry = FALSE; + + is_block = + (info->type & GST_PAD_PROBE_TYPE_BLOCK) == GST_PAD_PROBE_TYPE_BLOCK; + + if (is_block && PROBE_TYPE_IS_SERIALIZED (info)) { + if (do_pad_idle_probe_wait (pad) == GST_FLOW_FLUSHING) + goto flushing; + } + +again: + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "do probes"); + cookie = pad->priv->probe_list_cookie; + + g_hook_list_marshal (&pad->probes, TRUE, + (GHookMarshaller) probe_hook_marshal, &data); + + /* if the list changed, call the new callbacks (they will not be in + * called_probes yet) */ + if (cookie != pad->priv->probe_list_cookie) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe list changed, restarting"); + data.retry = TRUE; + goto again; + } + + /* the first item that dropped will stop the hooks and then we drop here */ + if (data.dropped) + goto dropped; + + /* If one handler took care of it, let the the item pass */ + if (data.handled) { + goto handled; + } + + /* if no handler matched and we are blocking, let the item pass */ + if (!data.marshalled && is_block) + goto passed; + + /* At this point, all handlers returned either OK or PASS. If one handler + * returned PASS, let the item pass */ + if (data.pass) + goto passed; + + if (is_block) { + while (GST_PAD_IS_BLOCKED (pad)) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "we are blocked %d times", pad->num_blocked); + + /* we might have released the lock */ + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + /* now we block the streaming thread. It can be unlocked when we + * deactivate the pad (which will also set the FLUSHING flag) or + * when the pad is unblocked. A flushing event will also unblock + * the pad after setting the FLUSHING flag. */ + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "Waiting to be unblocked or set flushing"); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING); + GST_PAD_BLOCK_WAIT (pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING); + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked"); + + /* if the list changed, call the new callbacks (they will not be in + * called_probes yet) */ + if (cookie != pad->priv->probe_list_cookie) { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe list changed, restarting"); + data.retry = TRUE; + goto again; + } + + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + } + } + + if (data.called_probes_size > N_STACK_ALLOCATE_PROBES) + g_free (data.called_probes); + + return defaultval; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (pad, "pad is flushing"); + if (data.called_probes_size > N_STACK_ALLOCATE_PROBES) + g_free (data.called_probes); + return GST_FLOW_FLUSHING; + } +dropped: + { + GST_DEBUG_OBJECT (pad, "data is dropped"); + if (data.called_probes_size > N_STACK_ALLOCATE_PROBES) + g_free (data.called_probes); + return GST_FLOW_CUSTOM_SUCCESS; + } +passed: + { + /* FIXME : Should we return FLOW_OK or the defaultval ?? */ + GST_DEBUG_OBJECT (pad, "data is passed"); + if (data.called_probes_size > N_STACK_ALLOCATE_PROBES) + g_free (data.called_probes); + return GST_FLOW_OK; + } +handled: + { + GST_DEBUG_OBJECT (pad, "data was handled"); + if (data.called_probes_size > N_STACK_ALLOCATE_PROBES) + g_free (data.called_probes); + return GST_FLOW_CUSTOM_SUCCESS_1; + } +} + +/* pad offsets */ + +/** + * gst_pad_get_offset: + * @pad: a #GstPad + * + * Get the offset applied to the running time of @pad. @pad has to be a source + * pad. + * + * Returns: the offset. + */ +gint64 +gst_pad_get_offset (GstPad * pad) +{ + gint64 result; + + g_return_val_if_fail (GST_IS_PAD (pad), 0); + + GST_OBJECT_LOCK (pad); + result = pad->offset; + GST_OBJECT_UNLOCK (pad); + + return result; +} + +static gboolean +mark_event_not_received (GstPad * pad, PadEvent * ev, gpointer user_data) +{ + ev->received = FALSE; + return TRUE; +} + +/** + * gst_pad_set_offset: + * @pad: a #GstPad + * @offset: the offset + * + * Set the offset that will be applied to the running time of @pad. + */ +void +gst_pad_set_offset (GstPad * pad, gint64 offset) +{ + g_return_if_fail (GST_IS_PAD (pad)); + + GST_OBJECT_LOCK (pad); + /* if nothing changed, do nothing */ + if (pad->offset == offset) + goto done; + + pad->offset = offset; + GST_DEBUG_OBJECT (pad, "changed offset to %" GST_STIME_FORMAT, + GST_STIME_ARGS (offset)); + + /* resend all sticky events with updated offset on next buffer push */ + events_foreach (pad, mark_event_not_received, NULL); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + +done: + GST_OBJECT_UNLOCK (pad); +} + +typedef struct +{ + GstFlowReturn ret; + + /* If TRUE and ret is not OK this means + * that pushing the EOS event failed + */ + gboolean was_eos; + + /* If called for an event this is + * the event that would be pushed + * next. Don't forward sticky events + * that would come after that */ + GstEvent *event; +} PushStickyData; + +/* should be called with pad LOCK */ +static gboolean +push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) +{ + PushStickyData *data = user_data; + GstEvent *event = ev->event; + + if (ev->received) { + GST_DEBUG_OBJECT (pad, "event %s was already received", + GST_EVENT_TYPE_NAME (event)); + return TRUE; + } + + /* If we're called because of an sticky event, only forward + * events that would come before this new event and the + * event itself */ + if (data->event && GST_EVENT_IS_STICKY (data->event) && + GST_EVENT_TYPE (data->event) <= GST_EVENT_SEGMENT && + GST_EVENT_TYPE (data->event) < GST_EVENT_TYPE (event)) { + data->ret = GST_FLOW_CUSTOM_SUCCESS_1; + } else { + data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM); + if (data->ret == GST_FLOW_CUSTOM_SUCCESS_1) + data->ret = GST_FLOW_OK; + } + + switch (data->ret) { + case GST_FLOW_OK: + ev->received = TRUE; + GST_DEBUG_OBJECT (pad, "event %s marked received", + GST_EVENT_TYPE_NAME (event)); + break; + case GST_FLOW_CUSTOM_SUCCESS: + /* we can't assume the event is received when it was dropped */ + GST_DEBUG_OBJECT (pad, "event %s was dropped, mark pending", + GST_EVENT_TYPE_NAME (event)); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + data->ret = GST_FLOW_OK; + break; + case GST_FLOW_CUSTOM_SUCCESS_1: + /* event was ignored and should be sent later */ + GST_DEBUG_OBJECT (pad, "event %s was ignored, mark pending", + GST_EVENT_TYPE_NAME (event)); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + data->ret = GST_FLOW_OK; + break; + case GST_FLOW_NOT_LINKED: + /* not linked is not a problem, we are sticky so the event will be + * rescheduled to be sent later on re-link, but only for non-EOS events */ + GST_DEBUG_OBJECT (pad, "pad was not linked, mark pending"); + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) { + data->ret = GST_FLOW_OK; + ev->received = TRUE; + } + break; + default: + GST_DEBUG_OBJECT (pad, "result %s, mark pending events", + gst_flow_get_name (data->ret)); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + break; + } + + if (data->ret != GST_FLOW_OK && GST_EVENT_TYPE (event) == GST_EVENT_EOS) + data->was_eos = TRUE; + + return data->ret == GST_FLOW_OK; +} + +/* check sticky events and push them when needed. should be called + * with pad LOCK */ +static inline GstFlowReturn +check_sticky (GstPad * pad, GstEvent * event) +{ + PushStickyData data = { GST_FLOW_OK, FALSE, event }; + + if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) { + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS); + + GST_DEBUG_OBJECT (pad, "pushing all sticky events"); + events_foreach (pad, push_sticky, &data); + + /* If there's an EOS event we must push it downstream + * even if sending a previous sticky event failed. + * Otherwise the pipeline might wait forever for EOS. + * + * Only do this if pushing another event than the EOS + * event failed. + */ + if (data.ret != GST_FLOW_OK && !data.was_eos) { + PadEvent *ev = find_event_by_type (pad, GST_EVENT_EOS, 0); + + if (ev && !ev->received) { + data.ret = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM); + /* the event could have been dropped. Because this can only + * happen if the user asked for it, it's not an error */ + if (data.ret == GST_FLOW_CUSTOM_SUCCESS) + data.ret = GST_FLOW_OK; + } + } + } + return data.ret; +} + + +/** + * gst_pad_query: + * @pad: a #GstPad to invoke the default query on. + * @query: (transfer none): the #GstQuery to perform. + * + * Dispatches a query to a pad. The query should have been allocated by the + * caller via one of the type-specific allocation functions. The element that + * the pad belongs to is responsible for filling the query with an appropriate + * response, which should then be parsed with a type-specific query parsing + * function. + * + * Again, the caller is responsible for both the allocation and deallocation of + * the query structure. + * + * Please also note that some queries might need a running pipeline to work. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_query (GstPad * pad, GstQuery * query) +{ + GstObject *parent; + gboolean res, serialized; + GstPadQueryFunction func; + GstPadProbeType type; + GstFlowReturn ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_QUERY (query), FALSE); + + if (GST_PAD_IS_SRC (pad)) { + if (G_UNLIKELY (!GST_QUERY_IS_UPSTREAM (query))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM; + } else if (GST_PAD_IS_SINK (pad)) { + if (G_UNLIKELY (!GST_QUERY_IS_DOWNSTREAM (query))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM; + } else + goto unknown_direction; + + GST_DEBUG_OBJECT (pad, "doing query %p (%s)", query, + GST_QUERY_TYPE_NAME (query)); + GST_TRACER_PAD_QUERY_PRE (pad, query); + + serialized = GST_QUERY_IS_SERIALIZED (query); + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_LOCK (pad); + + GST_OBJECT_LOCK (pad); + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH | + GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped); + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped); + + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + if ((func = GST_PAD_QUERYFUNC (pad)) == NULL) + goto no_func; + + res = func (pad, parent, query); + + RELEASE_PARENT (parent); + + GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query, + GST_QUERY_TYPE_NAME (query), res); + GST_TRACER_PAD_QUERY_POST (pad, query, res); + + if (res != TRUE) + goto query_failed; + + GST_OBJECT_LOCK (pad); + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped); + GST_OBJECT_UNLOCK (pad); + + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_UNLOCK (pad); + + return res; + + /* ERRORS */ +wrong_direction: + { + g_warning ("pad %s:%s query %s in wrong direction", + GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query)); + return FALSE; + } +unknown_direction: + { + g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); + return FALSE; + } +no_parent: + { + GST_DEBUG_OBJECT (pad, "had no parent"); + GST_OBJECT_UNLOCK (pad); + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_UNLOCK (pad); + return FALSE; + } +no_func: + { + GST_DEBUG_OBJECT (pad, "had no query function"); + RELEASE_PARENT (parent); + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_UNLOCK (pad); + return FALSE; + } +query_failed: + { + GST_DEBUG_OBJECT (pad, "query failed"); + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_UNLOCK (pad); + return FALSE; + } +probe_stopped: + { + GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret)); + GST_OBJECT_UNLOCK (pad); + if (G_UNLIKELY (serialized)) + GST_PAD_STREAM_UNLOCK (pad); + + /* if a probe dropped without handling, we don't sent it further but assume + * that the probe did not answer the query and return FALSE */ + if (ret != GST_FLOW_CUSTOM_SUCCESS_1) + res = FALSE; + else + res = TRUE; + + return res; + } +} + +/** + * gst_pad_peer_query: + * @pad: a #GstPad to invoke the peer query on. + * @query: (transfer none): the #GstQuery to perform. + * + * Performs gst_pad_query() on the peer of @pad. + * + * The caller is responsible for both the allocation and deallocation of + * the query structure. + * + * Returns: %TRUE if the query could be performed. This function returns %FALSE + * if @pad has no peer. + */ +gboolean +gst_pad_peer_query (GstPad * pad, GstQuery * query) +{ + GstPad *peerpad; + GstPadProbeType type; + gboolean res, serialized; + GstFlowReturn ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_QUERY (query), FALSE); + + if (GST_PAD_IS_SRC (pad)) { + if (G_UNLIKELY (!GST_QUERY_IS_DOWNSTREAM (query))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM; + } else if (GST_PAD_IS_SINK (pad)) { + if (G_UNLIKELY (!GST_QUERY_IS_UPSTREAM (query))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM; + } else + goto unknown_direction; + + GST_DEBUG_OBJECT (pad, "peer query %p (%s)", query, + GST_QUERY_TYPE_NAME (query)); + + serialized = GST_QUERY_IS_SERIALIZED (query); + + GST_OBJECT_LOCK (pad); + if (GST_PAD_IS_SRC (pad) && serialized) { + /* all serialized queries on the srcpad trigger push of + * sticky events */ + if (check_sticky (pad, NULL) != GST_FLOW_OK) + goto sticky_failed; + } + + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH | + GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped); + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped); + + peerpad = GST_PAD_PEER (pad); + if (G_UNLIKELY (peerpad == NULL)) + goto no_peer; + + gst_object_ref (peerpad); + GST_OBJECT_UNLOCK (pad); + + res = gst_pad_query (peerpad, query); + + gst_object_unref (peerpad); + + if (res != TRUE) + goto query_failed; + + GST_OBJECT_LOCK (pad); + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped); + GST_OBJECT_UNLOCK (pad); + + return res; + + /* ERRORS */ +wrong_direction: + { + g_warning ("pad %s:%s query %s in wrong direction", + GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query)); + return FALSE; + } +unknown_direction: + { + g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); + return FALSE; + } +sticky_failed: + { + GST_WARNING_OBJECT (pad, "could not send sticky events"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +no_peer: + { + GST_INFO_OBJECT (pad, "pad has no peer"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +query_failed: + { + GST_DEBUG_OBJECT (pad, "query failed"); + return FALSE; + } +probe_stopped: + { + GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret)); + GST_OBJECT_UNLOCK (pad); + + /* if a probe dropped without handling, we don't sent it further but + * assume that the probe did not answer the query and return FALSE */ + if (ret != GST_FLOW_CUSTOM_SUCCESS_1) + res = FALSE; + else + res = TRUE; + + return res; + } +} + +/********************************************************************** + * Data passing functions + */ + +/* this is the chain function that does not perform the additional argument + * checking for that little extra speed. + */ +static inline GstFlowReturn +gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) +{ + GstFlowReturn ret; + GstObject *parent; + gboolean handled = FALSE; + + GST_PAD_STREAM_LOCK (pad); + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) + goto wrong_mode; + +#ifdef GST_ENABLE_EXTRA_CHECKS + if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { + if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before stream-start event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before segment event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + pad->priv->last_cookie = pad->priv->events_cookie; + } +#endif + + PROBE_HANDLE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped, + probe_handled); + + PROBE_HANDLE (pad, type, data, probe_stopped, probe_handled); + + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + /* NOTE: we read the chainfunc unlocked. + * we cannot hold the lock for the pad so we might send + * the data to the wrong function. This is not really a + * problem since functions are assigned at creation time + * and don't change that often... */ + if (G_LIKELY (type & GST_PAD_PROBE_TYPE_BUFFER)) { + GstPadChainFunction chainfunc; + + if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL)) + goto no_function; + + GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling chainfunction &%s with buffer %" GST_PTR_FORMAT, + GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_BUFFER (data)); + + ret = chainfunc (pad, parent, GST_BUFFER_CAST (data)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, + "called chainfunction &%s with buffer %p, returned %s", + GST_DEBUG_FUNCPTR_NAME (chainfunc), data, gst_flow_get_name (ret)); + } else { + GstPadChainListFunction chainlistfunc; + + if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL)) + goto no_function; + + GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling chainlistfunction &%s", + GST_DEBUG_FUNCPTR_NAME (chainlistfunc)); + + ret = chainlistfunc (pad, parent, GST_BUFFER_LIST_CAST (data)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, + "called chainlistfunction &%s, returned %s", + GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret)); + } + + RELEASE_PARENT (parent); + + GST_PAD_STREAM_UNLOCK (pad); + + return ret; + + /* ERRORS */ +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "chaining, but pad was flushing"); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_FLUSHING; + } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "chaining, but pad was EOS"); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } +wrong_mode: + { + g_critical ("chain on pad %s:%s but it was not in push mode", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_ERROR; + } +probe_handled: + handled = TRUE; + /* PASSTHROUGH */ +probe_stopped: + { + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + /* We unref the buffer, except if the probe handled it (CUSTOM_SUCCESS_1) */ + if (!handled) + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + + switch (ret) { + case GST_FLOW_CUSTOM_SUCCESS: + case GST_FLOW_CUSTOM_SUCCESS_1: + GST_DEBUG_OBJECT (pad, "dropped or handled buffer"); + ret = GST_FLOW_OK; + break; + default: + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); + break; + } + return ret; + } +no_parent: + { + GST_DEBUG_OBJECT (pad, "No parent when chaining %" GST_PTR_FORMAT, data); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_FLUSHING; + } +no_function: + { + RELEASE_PARENT (parent); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + g_critical ("chain on pad %s:%s but it has no chainfunction", + GST_DEBUG_PAD_NAME (pad)); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_NOT_SUPPORTED; + } +} + +/** + * gst_pad_chain: + * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. + * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR + * if not. + * + * Chain a buffer to @pad. + * + * The function returns #GST_FLOW_FLUSHING if the pad was flushing. + * + * If the buffer type is not acceptable for @pad (as negotiated with a + * preceding GST_EVENT_CAPS event), this function returns + * #GST_FLOW_NOT_NEGOTIATED. + * + * The function proceeds calling the chain function installed on @pad (see + * gst_pad_set_chain_function()) and the return value of that function is + * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no + * chain function. + * + * In all cases, success or failure, the caller loses its reference to @buffer + * after calling this function. + * + * Returns: a #GstFlowReturn from the pad. + * + * MT safe. + */ +GstFlowReturn +gst_pad_chain (GstPad * pad, GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + + return gst_pad_chain_data_unchecked (pad, + GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer); +} + +static GstFlowReturn +gst_pad_chain_list_default (GstPad * pad, GstObject * parent, + GstBufferList * list) +{ + guint i, len; + GstBuffer *buffer; + GstFlowReturn ret; + + GST_INFO_OBJECT (pad, "chaining each buffer in list individually"); + + len = gst_buffer_list_length (list); + + ret = GST_FLOW_OK; + for (i = 0; i < len; i++) { + buffer = gst_buffer_list_get (list, i); + ret = + gst_pad_chain_data_unchecked (pad, + GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, + gst_buffer_ref (buffer)); + if (ret != GST_FLOW_OK) + break; + } + gst_buffer_list_unref (list); + + return ret; +} + +/** + * gst_pad_chain_list: + * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. + * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR + * if not. + * + * Chain a bufferlist to @pad. + * + * The function returns #GST_FLOW_FLUSHING if the pad was flushing. + * + * If @pad was not negotiated properly with a CAPS event, this function + * returns #GST_FLOW_NOT_NEGOTIATED. + * + * The function proceeds calling the chainlist function installed on @pad (see + * gst_pad_set_chain_list_function()) and the return value of that function is + * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no + * chainlist function. + * + * In all cases, success or failure, the caller loses its reference to @list + * after calling this function. + * + * MT safe. + * + * Returns: a #GstFlowReturn from the pad. + */ +GstFlowReturn +gst_pad_chain_list (GstPad * pad, GstBufferList * list) +{ + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); + + return gst_pad_chain_data_unchecked (pad, + GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list); +} + +static GstFlowReturn +gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) +{ + GstPad *peer; + GstFlowReturn ret; + gboolean handled = FALSE; + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) + goto wrong_mode; + +#ifdef GST_ENABLE_EXTRA_CHECKS + if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { + if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before stream-start event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before segment event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + pad->priv->last_cookie = pad->priv->events_cookie; + } +#endif + + if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK) + goto events_error; + + /* do block probes */ + PROBE_HANDLE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped, + probe_handled); + + /* recheck sticky events because the probe might have cause a relink */ + if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK) + goto events_error; + + /* do post-blocking probes */ + PROBE_HANDLE (pad, type, data, probe_stopped, probe_handled); + + /* recheck sticky events because the probe might have cause a relink */ + if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK) + goto events_error; + + if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) + goto not_linked; + + /* take ref to peer pad before releasing the lock */ + gst_object_ref (peer); + pad->priv->using++; + GST_OBJECT_UNLOCK (pad); + + ret = gst_pad_chain_data_unchecked (peer, type, data); + data = NULL; + + gst_object_unref (peer); + + GST_OBJECT_LOCK (pad); + pad->ABI.abi.last_flowret = ret; + pad->priv->using--; + if (pad->priv->using == 0) { + /* pad is not active anymore, trigger idle callbacks */ + PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE, + probe_stopped, ret); + } + GST_OBJECT_UNLOCK (pad); + + return ret; + + /* ERROR recovery here */ + /* ERRORS */ +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_FLUSHING; + } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS"); + pad->ABI.abi.last_flowret = GST_FLOW_EOS; + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } +wrong_mode: + { + g_critical ("pushing on pad %s:%s but it was not activated in push mode", + GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_ERROR; + } +events_error: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "error pushing events, return %s", gst_flow_get_name (ret)); + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return ret; + } +probe_handled: + handled = TRUE; + /* PASSTHROUGH */ +probe_stopped: + { + GST_OBJECT_UNLOCK (pad); + if (data != NULL && !handled) + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + + switch (ret) { + case GST_FLOW_CUSTOM_SUCCESS: + case GST_FLOW_CUSTOM_SUCCESS_1: + GST_DEBUG_OBJECT (pad, "dropped or handled buffer"); + ret = GST_FLOW_OK; + break; + default: + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); + break; + } + pad->ABI.abi.last_flowret = ret; + return ret; + } +not_linked: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pushing, but it was not linked"); + pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED; + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_NOT_LINKED; + } +} + +/** + * gst_pad_push: + * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. + * @buffer: (transfer full): the #GstBuffer to push returns GST_FLOW_ERROR + * if not. + * + * Pushes a buffer to the peer of @pad. + * + * This function will call installed block probes before triggering any + * installed data probes. + * + * The function proceeds calling gst_pad_chain() on the peer pad and returns + * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will + * be returned. + * + * In all cases, success or failure, the caller loses its reference to @buffer + * after calling this function. + * + * Returns: a #GstFlowReturn from the peer pad. + * + * MT safe. + */ +GstFlowReturn +gst_pad_push (GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn res; + + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + + GST_TRACER_PAD_PUSH_PRE (pad, buffer); + res = gst_pad_push_data (pad, + GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer); + GST_TRACER_PAD_PUSH_POST (pad, res); + return res; +} + +/** + * gst_pad_push_list: + * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. + * @list: (transfer full): the #GstBufferList to push returns GST_FLOW_ERROR + * if not. + * + * Pushes a buffer list to the peer of @pad. + * + * This function will call installed block probes before triggering any + * installed data probes. + * + * The function proceeds calling the chain function on the peer pad and returns + * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will + * be returned. If the peer pad does not have any installed chainlist function + * every group buffer of the list will be merged into a normal #GstBuffer and + * chained via gst_pad_chain(). + * + * In all cases, success or failure, the caller loses its reference to @list + * after calling this function. + * + * Returns: a #GstFlowReturn from the peer pad. + * + * MT safe. + */ +GstFlowReturn +gst_pad_push_list (GstPad * pad, GstBufferList * list) +{ + GstFlowReturn res; + + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); + + GST_TRACER_PAD_PUSH_LIST_PRE (pad, list); + res = gst_pad_push_data (pad, + GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list); + GST_TRACER_PAD_PUSH_LIST_POST (pad, res); + return res; +} + +static GstFlowReturn +gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size, + GstBuffer ** buffer) +{ + GstFlowReturn ret; + GstPadGetRangeFunction getrangefunc; + GstObject *parent; + GstBuffer *res_buf; + + GST_PAD_STREAM_LOCK (pad); + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL)) + goto wrong_mode; + + if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK) + goto events_error; + + res_buf = *buffer; + + /* when one of the probes returns DROPPED, probe_stopped will be called + * and we skip calling the getrange function, res_buf should then contain a + * valid result buffer */ + PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK, + res_buf, offset, size, probe_stopped); + + /* recheck sticky events because the probe might have cause a relink */ + if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK) + goto events_error; + + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL)) + goto no_function; + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling getrangefunc %s, offset %" + G_GUINT64_FORMAT ", size %u", + GST_DEBUG_FUNCPTR_NAME (getrangefunc), offset, size); + + ret = getrangefunc (pad, parent, offset, size, &res_buf); + + RELEASE_PARENT (parent); + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto get_range_failed; + + /* can only fire the signal if we have a valid buffer */ +probed_data: + PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER, + res_buf, offset, size, probe_stopped_unref); + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + + GST_PAD_STREAM_UNLOCK (pad); + + *buffer = res_buf; + + return ret; + + /* ERRORS */ +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "getrange, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_FLUSHING; + } +wrong_mode: + { + g_critical ("getrange on pad %s:%s but it was not activated in pull mode", + GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_ERROR; + } +events_error: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events"); + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + return ret; + } +no_parent: + { + GST_DEBUG_OBJECT (pad, "no parent"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_FLUSHING; + } +no_function: + { + g_critical ("getrange on pad %s:%s but it has no getrangefunction", + GST_DEBUG_PAD_NAME (pad)); + RELEASE_PARENT (parent); + GST_PAD_STREAM_UNLOCK (pad); + return GST_FLOW_NOT_SUPPORTED; + } +probe_stopped: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe returned %s", gst_flow_get_name (ret)); + if (ret == GST_FLOW_CUSTOM_SUCCESS) { + if (res_buf) { + /* the probe filled the buffer and asks us to not call the getrange + * anymore, we continue with the post probes then. */ + GST_DEBUG_OBJECT (pad, "handled buffer"); + ret = GST_FLOW_OK; + goto probed_data; + } else { + /* no buffer, we are EOS */ + GST_DEBUG_OBJECT (pad, "no buffer, return EOS"); + ret = GST_FLOW_EOS; + } + } + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + + return ret; + } +probe_stopped_unref: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "probe returned %s", gst_flow_get_name (ret)); + /* if we drop here, it signals EOS */ + if (ret == GST_FLOW_CUSTOM_SUCCESS) + ret = GST_FLOW_EOS; + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + if (*buffer == NULL) + gst_buffer_unref (res_buf); + return ret; + } +get_range_failed: + { + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, + (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, + pad, "getrange failed, flow: %s", gst_flow_get_name (ret)); + return ret; + } +} + +/** + * gst_pad_get_range: + * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not. + * @offset: The start offset of the buffer + * @size: The length of the buffer + * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, + * returns #GST_FLOW_ERROR if %NULL. + * + * When @pad is flushing this function returns #GST_FLOW_FLUSHING + * immediately and @buffer is %NULL. + * + * Calls the getrange function of @pad, see #GstPadGetRangeFunction for a + * description of a getrange function. If @pad has no getrange function + * installed (see gst_pad_set_getrange_function()) this function returns + * #GST_FLOW_NOT_SUPPORTED. + * + * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be + * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer + * must be freed with gst_buffer_unref() after usage. + * + * When @buffer points to a variable that points to a valid #GstBuffer, the + * buffer will be filled with the result data when this function returns + * #GST_FLOW_OK. If the provided buffer is larger than @size, only + * @size bytes will be filled in the result buffer and its size will be updated + * accordingly. + * + * Note that less than @size bytes can be returned in @buffer when, for example, + * an EOS condition is near or when @buffer is not large enough to hold @size + * bytes. The caller should check the result buffer size to get the result size. + * + * When this function returns any other result value than #GST_FLOW_OK, @buffer + * will be unchanged. + * + * This is a lowlevel function. Usually gst_pad_pull_range() is used. + * + * Returns: a #GstFlowReturn from the pad. + * + * MT safe. + */ +GstFlowReturn +gst_pad_get_range (GstPad * pad, guint64 offset, guint size, + GstBuffer ** buffer) +{ + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer) + && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR); + + return gst_pad_get_range_unchecked (pad, offset, size, buffer); +} + +/** + * gst_pad_pull_range: + * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. + * @offset: The start offset of the buffer + * @size: The length of the buffer + * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, returns + * GST_FLOW_ERROR if %NULL. + * + * Pulls a @buffer from the peer pad or fills up a provided buffer. + * + * This function will first trigger the pad block signal if it was + * installed. + * + * When @pad is not linked #GST_FLOW_NOT_LINKED is returned else this + * function returns the result of gst_pad_get_range() on the peer pad. + * See gst_pad_get_range() for a list of return values and for the + * semantics of the arguments of this function. + * + * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be + * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer + * must be freed with gst_buffer_unref() after usage. When this function + * returns any other result value, @buffer will still point to %NULL. + * + * When @buffer points to a variable that points to a valid #GstBuffer, the + * buffer will be filled with the result data when this function returns + * #GST_FLOW_OK. When this function returns any other result value, + * @buffer will be unchanged. If the provided buffer is larger than @size, only + * @size bytes will be filled in the result buffer and its size will be updated + * accordingly. + * + * Note that less than @size bytes can be returned in @buffer when, for example, + * an EOS condition is near or when @buffer is not large enough to hold @size + * bytes. The caller should check the result buffer size to get the result size. + * + * Returns: a #GstFlowReturn from the peer pad. + * + * MT safe. + */ +GstFlowReturn +gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, + GstBuffer ** buffer) +{ + GstPad *peer; + GstFlowReturn ret; + GstBuffer *res_buf; + + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer) + && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR); + + GST_TRACER_PAD_PULL_RANGE_PRE (pad, offset, size); + + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL)) + goto wrong_mode; + + res_buf = *buffer; + + /* when one of the probes returns DROPPED, probe_stopped will be + * called and we skip calling the peer getrange function. *buffer should then + * contain a valid buffer */ + PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK, + res_buf, offset, size, probe_stopped); + + if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) + goto not_linked; + + gst_object_ref (peer); + pad->priv->using++; + GST_OBJECT_UNLOCK (pad); + + ret = gst_pad_get_range_unchecked (peer, offset, size, &res_buf); + + gst_object_unref (peer); + + GST_OBJECT_LOCK (pad); + pad->priv->using--; + pad->ABI.abi.last_flowret = ret; + if (pad->priv->using == 0) { + /* pad is not active anymore, trigger idle callbacks */ + PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE, + probe_stopped_unref, ret); + } + + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto pull_range_failed; + +probed_data: + PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER, + res_buf, offset, size, probe_stopped_unref); + + GST_OBJECT_UNLOCK (pad); + + *buffer = res_buf; + + GST_TRACER_PAD_PULL_RANGE_POST (pad, *buffer, ret); + return ret; + + /* ERROR recovery here */ +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pullrange, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; + GST_OBJECT_UNLOCK (pad); + ret = GST_FLOW_FLUSHING; + goto done; + } +wrong_mode: + { + g_critical ("pullrange on pad %s:%s but it was not activated in pull mode", + GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; + GST_OBJECT_UNLOCK (pad); + ret = GST_FLOW_ERROR; + goto done; + } +probe_stopped: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pre probe returned %s", + gst_flow_get_name (ret)); + if (ret == GST_FLOW_CUSTOM_SUCCESS) { + if (res_buf) { + /* the probe filled the buffer and asks us to not forward to the peer + * anymore, we continue with the post probes then */ + GST_DEBUG_OBJECT (pad, "handled buffer"); + ret = GST_FLOW_OK; + goto probed_data; + } else { + /* no buffer, we are EOS then */ + GST_DEBUG_OBJECT (pad, "no buffer, return EOS"); + ret = GST_FLOW_EOS; + } + } + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + goto done; + } +not_linked: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but it was not linked"); + pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED; + GST_OBJECT_UNLOCK (pad); + ret = GST_FLOW_NOT_LINKED; + goto done; + } +pull_range_failed: + { + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, + (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, + pad, "pullrange failed, flow: %s", gst_flow_get_name (ret)); + goto done; + } +probe_stopped_unref: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "post probe returned %s", gst_flow_get_name (ret)); + + /* if we drop here, it signals EOS */ + if (ret == GST_FLOW_CUSTOM_SUCCESS) + ret = GST_FLOW_EOS; + + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + + if (*buffer == NULL) + gst_buffer_unref (res_buf); + goto done; + } +done: + GST_TRACER_PAD_PULL_RANGE_POST (pad, NULL, ret); + return ret; +} + +/* must be called with pad object lock */ +static GstFlowReturn +store_sticky_event (GstPad * pad, GstEvent * event) +{ + guint i, len; + GstEventType type; + GArray *events; + gboolean res = FALSE; + const gchar *name = NULL; + gboolean insert = TRUE; + + type = GST_EVENT_TYPE (event); + + /* Store all sticky events except SEGMENT/EOS when we're flushing, + * otherwise they can be dropped and nothing would ever resend them. + * Only do that for activated pads though, everything else is a bug! + */ + if (G_UNLIKELY (GST_PAD_MODE (pad) == GST_PAD_MODE_NONE + || (GST_PAD_IS_FLUSHING (pad) && (type == GST_EVENT_SEGMENT + || type == GST_EVENT_EOS)))) + goto flushed; + + /* Unset the EOS flag when received STREAM_START event, so pad can + * store sticky event and then push it later */ + if (type == GST_EVENT_STREAM_START) { + GST_LOG_OBJECT (pad, "Removing pending EOS and StreamGroupDone events"); + remove_event_by_type (pad, GST_EVENT_EOS); + remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + } + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + + if (type & GST_EVENT_TYPE_STICKY_MULTI) + name = gst_structure_get_name (gst_event_get_structure (event)); + + events = pad->priv->events; + len = events->len; + + for (i = 0; i < len; i++) { + PadEvent *ev = &g_array_index (events, PadEvent, i); + + if (ev->event == NULL) + continue; + + if (type == GST_EVENT_TYPE (ev->event)) { + /* matching types, check matching name if needed */ + if (name && !gst_event_has_name (ev->event, name)) + continue; + + /* overwrite */ + if ((res = gst_event_replace (&ev->event, event))) + ev->received = FALSE; + + insert = FALSE; + break; + } + + if (type < GST_EVENT_TYPE (ev->event) || (type != GST_EVENT_TYPE (ev->event) + && GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS)) { + /* STREAM_START, CAPS and SEGMENT must be delivered in this order. By + * storing the sticky ordered we can check that this is respected. */ + if (G_UNLIKELY (GST_EVENT_TYPE (ev->event) <= GST_EVENT_SEGMENT + || GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS)) + g_warning (G_STRLOC + ":%s:<%s:%s> Sticky event misordering, got '%s' before '%s'", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad), + gst_event_type_get_name (GST_EVENT_TYPE (ev->event)), + gst_event_type_get_name (type)); + break; + } + } + if (insert) { + PadEvent ev; + ev.event = gst_event_ref (event); + ev.received = FALSE; + g_array_insert_val (events, i, ev); + res = TRUE; + } + + if (res) { + pad->priv->events_cookie++; + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + + GST_LOG_OBJECT (pad, "stored sticky event %s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pad, "notify caps"); + g_object_notify_by_pspec ((GObject *) pad, pspec_caps); + + GST_OBJECT_LOCK (pad); + break; + default: + break; + } + } + if (type == GST_EVENT_EOS) { + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_EOS; + } + + return GST_PAD_IS_FLUSHING (pad) ? GST_FLOW_FLUSHING : GST_FLOW_OK; + + /* ERRORS */ +flushed: + { + GST_DEBUG_OBJECT (pad, "pad is flushing"); + return GST_FLOW_FLUSHING; + } +eos: + { + GST_DEBUG_OBJECT (pad, "pad is EOS"); + return GST_FLOW_EOS; + } +} + +/** + * gst_pad_store_sticky_event: + * @pad: a #GstPad + * @event: (transfer none): a #GstEvent + * + * Store the sticky @event on @pad + * + * Returns: #GST_FLOW_OK on success, #GST_FLOW_FLUSHING when the pad + * was flushing or #GST_FLOW_EOS when the pad was EOS. + * + * Since: 1.2 + */ +GstFlowReturn +gst_pad_store_sticky_event (GstPad * pad, GstEvent * event) +{ + GstFlowReturn ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + + GST_OBJECT_LOCK (pad); + ret = store_sticky_event (pad, event); + GST_OBJECT_UNLOCK (pad); + + return ret; +} + +static gboolean +sticky_changed (GstPad * pad, PadEvent * ev, gpointer user_data) +{ + PushStickyData *data = user_data; + + /* Forward all sticky events before our current one that are pending */ + if (ev->event != data->event + && GST_EVENT_TYPE (ev->event) < GST_EVENT_TYPE (data->event)) + return push_sticky (pad, ev, data); + + return TRUE; +} + +/* should be called with pad LOCK */ +static GstFlowReturn +gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, + GstPadProbeType type) +{ + GstFlowReturn ret; + GstPad *peerpad; + GstEventType event_type; + + /* pass the adjusted event on. We need to do this even if + * there is no peer pad because of the probes. */ + event = apply_pad_offset (pad, event, GST_PAD_IS_SINK (pad)); + + /* Two checks to be made: + * . (un)set the FLUSHING flag for flushing events, + * . handle pad blocking */ + event_type = GST_EVENT_TYPE (event); + switch (event_type) { + case GST_EVENT_FLUSH_START: + GST_PAD_SET_FLUSHING (pad); + + GST_PAD_BLOCK_BROADCAST (pad); + type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; + break; + case GST_EVENT_FLUSH_STOP: + if (G_UNLIKELY (!GST_PAD_IS_ACTIVE (pad))) + goto inactive; + + GST_PAD_UNSET_FLUSHING (pad); + + /* Remove sticky EOS events */ + GST_LOG_OBJECT (pad, "Removing pending EOS events"); + remove_event_by_type (pad, GST_EVENT_EOS); + remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE); + remove_event_by_type (pad, GST_EVENT_SEGMENT); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_OK; + + type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; + break; + default: + { + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushed; + + /* No need to check for EOS here as either the caller (gst_pad_push_event()) + * checked already or this is called as part of pushing sticky events, + * in which case we still want to forward the EOS event downstream. + */ + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_RECONFIGURE: + if (GST_PAD_IS_SINK (pad)) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + break; + default: + break; + } + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH | + GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped); + /* recheck sticky events because the probe might have cause a relink */ + if (GST_PAD_HAS_PENDING_EVENTS (pad) && GST_PAD_IS_SRC (pad) + && (GST_EVENT_IS_SERIALIZED (event) + || GST_EVENT_IS_STICKY (event))) { + PushStickyData data = { GST_FLOW_OK, FALSE, event }; + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS); + + /* Push all sticky events before our current one + * that have changed */ + events_foreach (pad, sticky_changed, &data); + } + break; + } + } + + /* send probes after modifying the events above */ + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped); + + /* recheck sticky events because the probe might have cause a relink */ + if (GST_PAD_HAS_PENDING_EVENTS (pad) && GST_PAD_IS_SRC (pad) + && (GST_EVENT_IS_SERIALIZED (event) + || GST_EVENT_IS_STICKY (event))) { + PushStickyData data = { GST_FLOW_OK, FALSE, event }; + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS); + + /* Push all sticky events before our current one + * that have changed */ + events_foreach (pad, sticky_changed, &data); + } + + /* now check the peer pad */ + peerpad = GST_PAD_PEER (pad); + if (peerpad == NULL) + goto not_linked; + + gst_object_ref (peerpad); + pad->priv->using++; + GST_OBJECT_UNLOCK (pad); + + GST_LOG_OBJECT (pad, "sending event %p (%s) to peerpad %" GST_PTR_FORMAT, + event, gst_event_type_get_name (event_type), peerpad); + + ret = gst_pad_send_event_unchecked (peerpad, event, type); + + /* Note: we gave away ownership of the event at this point but we can still + * print the old pointer */ + GST_LOG_OBJECT (pad, + "sent event %p (%s) to peerpad %" GST_PTR_FORMAT ", ret %s", event, + gst_event_type_get_name (event_type), peerpad, gst_flow_get_name (ret)); + + gst_object_unref (peerpad); + + GST_OBJECT_LOCK (pad); + pad->priv->using--; + if (pad->priv->using == 0) { + /* pad is not active anymore, trigger idle callbacks */ + PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE, + idle_probe_stopped, ret); + } + return ret; + + /* ERROR handling */ +flushed: + { + GST_DEBUG_OBJECT (pad, "We're flushing"); + gst_event_unref (event); + return GST_FLOW_FLUSHING; + } +inactive: + { + GST_DEBUG_OBJECT (pad, "flush-stop on inactive pad"); + gst_event_unref (event); + return GST_FLOW_FLUSHING; + } +probe_stopped: + { + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + if (ret != GST_FLOW_CUSTOM_SUCCESS_1) + gst_event_unref (event); + + switch (ret) { + case GST_FLOW_CUSTOM_SUCCESS_1: + GST_DEBUG_OBJECT (pad, "handled event"); + break; + case GST_FLOW_CUSTOM_SUCCESS: + GST_DEBUG_OBJECT (pad, "dropped event"); + break; + default: + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); + break; + } + return ret; + } +not_linked: + { + GST_DEBUG_OBJECT (pad, "Dropping event %s because pad is not linked", + gst_event_type_get_name (GST_EVENT_TYPE (event))); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); + gst_event_unref (event); + + /* unlinked pads should not influence latency configuration */ + if (event_type == GST_EVENT_LATENCY) + return GST_FLOW_OK; + + return GST_FLOW_NOT_LINKED; + } +idle_probe_stopped: + { + GST_DEBUG_OBJECT (pad, "Idle probe returned %s", gst_flow_get_name (ret)); + return ret; + } +} + +/** + * gst_pad_push_event: + * @pad: a #GstPad to push the event to. + * @event: (transfer full): the #GstEvent to send to the pad. + * + * Sends the event to the peer of the given pad. This function is + * mainly used by elements to send events to their peer + * elements. + * + * This function takes ownership of the provided event so you should + * gst_event_ref() it if you want to reuse the event after this call. + * + * Returns: %TRUE if the event was handled. + * + * MT safe. + */ +gboolean +gst_pad_push_event (GstPad * pad, GstEvent * event) +{ + gboolean res = FALSE; + GstPadProbeType type; + gboolean sticky, serialized; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + + GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event); + + if (GST_PAD_IS_SRC (pad)) { + if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM; + } else if (GST_PAD_IS_SINK (pad)) { + if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event))) + goto wrong_direction; + /* events pushed on sinkpad never are sticky */ + type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM; + } else + goto unknown_direction; + + GST_OBJECT_LOCK (pad); + sticky = GST_EVENT_IS_STICKY (event); + serialized = GST_EVENT_IS_SERIALIZED (event); + + if (sticky) { + /* srcpad sticky events are stored immediately, the received flag is set + * to FALSE and will be set to TRUE when we can successfully push the + * event to the peer pad */ + switch (store_sticky_event (pad, event)) { + case GST_FLOW_FLUSHING: + goto flushed; + case GST_FLOW_EOS: + goto eos; + default: + break; + } + } + if (GST_PAD_IS_SRC (pad) && (serialized || sticky)) { + /* all serialized or sticky events on the srcpad trigger push of + * sticky events */ + res = (check_sticky (pad, event) == GST_FLOW_OK); + } + if (!sticky) { + GstFlowReturn ret; + + /* other events are pushed right away */ + ret = gst_pad_push_event_unchecked (pad, event, type); + /* dropped events by a probe are not an error */ + res = (ret == GST_FLOW_OK || ret == GST_FLOW_CUSTOM_SUCCESS + || ret == GST_FLOW_CUSTOM_SUCCESS_1); + } else { + /* Errors in sticky event pushing are no problem and ignored here + * as they will cause more meaningful errors during data flow. + * For EOS events, that are not followed by data flow, we still + * return FALSE here though. + */ + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) + res = TRUE; + gst_event_unref (event); + } + GST_OBJECT_UNLOCK (pad); + + GST_TRACER_PAD_PUSH_EVENT_POST (pad, res); + return res; + + /* ERROR handling */ +wrong_direction: + { + g_warning ("pad %s:%s pushing %s event in wrong direction", + GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event)); + gst_event_unref (event); + goto done; + } +unknown_direction: + { + g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); + gst_event_unref (event); + goto done; + } +flushed: + { + GST_DEBUG_OBJECT (pad, "We're flushing"); + GST_OBJECT_UNLOCK (pad); + gst_event_unref (event); + goto done; + } +eos: + { + GST_DEBUG_OBJECT (pad, "We're EOS"); + GST_OBJECT_UNLOCK (pad); + gst_event_unref (event); + goto done; + } +done: + GST_TRACER_PAD_PUSH_EVENT_POST (pad, FALSE); + return FALSE; +} + +/* Check if we can call the event function with the given event */ +static GstFlowReturn +pre_eventfunc_check (GstPad * pad, GstEvent * event) +{ + GstCaps *caps; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + /* backwards compatibility mode for caps */ + gst_event_parse_caps (event, &caps); + + if (!gst_pad_query_accept_caps (pad, caps)) + goto not_accepted; + break; + } + default: + break; + } + return GST_FLOW_OK; + + /* ERRORS */ +not_accepted: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "caps %" GST_PTR_FORMAT " not accepted", caps); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static GstFlowReturn +gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, + GstPadProbeType type) +{ + GstFlowReturn ret; + GstEventType event_type; + gboolean serialized, need_unlock = FALSE, sticky; + GstPadEventFunction eventfunc; + GstPadEventFullFunction eventfullfunc = NULL; + GstObject *parent; + + GST_OBJECT_LOCK (pad); + + event = apply_pad_offset (pad, event, GST_PAD_IS_SRC (pad)); + + if (GST_PAD_IS_SINK (pad)) + serialized = GST_EVENT_IS_SERIALIZED (event); + else + serialized = FALSE; + sticky = GST_EVENT_IS_STICKY (event); + event_type = GST_EVENT_TYPE (event); + switch (event_type) { + case GST_EVENT_FLUSH_START: + GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, + "have event type %d (FLUSH_START)", GST_EVENT_TYPE (event)); + + /* can't even accept a flush begin event when flushing */ + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + GST_PAD_SET_FLUSHING (pad); + GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "set flush flag"); + GST_PAD_BLOCK_BROADCAST (pad); + type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; + break; + case GST_EVENT_FLUSH_STOP: + /* we can't accept flush-stop on inactive pads else the flushing flag + * would be cleared and it would look like the pad can accept data. + * Also, some elements restart a streaming thread in flush-stop which we + * can't allow on inactive pads */ + if (G_UNLIKELY (!GST_PAD_IS_ACTIVE (pad))) + goto inactive; + + GST_PAD_UNSET_FLUSHING (pad); + GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "cleared flush flag"); + /* Remove pending EOS events */ + GST_LOG_OBJECT (pad, "Removing pending EOS and SEGMENT events"); + remove_event_by_type (pad, GST_EVENT_EOS); + remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE); + remove_event_by_type (pad, GST_EVENT_SEGMENT); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_OK; + + GST_OBJECT_UNLOCK (pad); + /* grab stream lock */ + GST_PAD_STREAM_LOCK (pad); + need_unlock = TRUE; + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + break; + case GST_EVENT_RECONFIGURE: + if (GST_PAD_IS_SRC (pad)) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); + default: + GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, + "have event type %" GST_PTR_FORMAT, event); + + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + switch (event_type) { + case GST_EVENT_STREAM_START: + /* Remove sticky EOS events */ + GST_LOG_OBJECT (pad, "Removing pending EOS events"); + remove_event_by_type (pad, GST_EVENT_EOS); + remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + break; + default: + break; + } + + if (serialized) { + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + + /* lock order: STREAM_LOCK, LOCK, recheck flushing. */ + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_LOCK (pad); + need_unlock = TRUE; + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + } + break; + } + + /* now do the probe */ + PROBE_PUSH (pad, + type | GST_PAD_PROBE_TYPE_PUSH | + GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped); + + PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped); + + eventfullfunc = GST_PAD_EVENTFULLFUNC (pad); + eventfunc = GST_PAD_EVENTFUNC (pad); + if (G_UNLIKELY (eventfunc == NULL && eventfullfunc == NULL)) + goto no_function; + + ACQUIRE_PARENT (pad, parent, no_parent); + GST_OBJECT_UNLOCK (pad); + + ret = pre_eventfunc_check (pad, event); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto precheck_failed; + + if (sticky) + gst_event_ref (event); + + if (eventfullfunc) { + ret = eventfullfunc (pad, parent, event); + } else if (eventfunc (pad, parent, event)) { + ret = GST_FLOW_OK; + } else { + /* something went wrong */ + switch (event_type) { + case GST_EVENT_CAPS: + ret = GST_FLOW_NOT_NEGOTIATED; + break; + default: + ret = GST_FLOW_ERROR; + break; + } + } + RELEASE_PARENT (parent); + + GST_DEBUG_OBJECT (pad, "sent event, ret %s", gst_flow_get_name (ret)); + + if (sticky) { + if (ret == GST_FLOW_OK) { + GST_OBJECT_LOCK (pad); + /* after the event function accepted the event, we can store the sticky + * event on the pad */ + switch (store_sticky_event (pad, event)) { + case GST_FLOW_FLUSHING: + goto flushing; + case GST_FLOW_EOS: + goto eos; + default: + break; + } + GST_OBJECT_UNLOCK (pad); + } + gst_event_unref (event); + } + + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + + return ret; + + /* ERROR handling */ +flushing: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, + "Received event on flushing pad. Discarding"); + gst_event_unref (event); + return GST_FLOW_FLUSHING; + } +inactive: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, + "Received flush-stop on inactive pad. Discarding"); + gst_event_unref (event); + return GST_FLOW_FLUSHING; + } +eos: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, + "Received event on EOS pad. Discarding"); + gst_event_unref (event); + return GST_FLOW_EOS; + } +probe_stopped: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + /* Only unref if unhandled */ + if (ret != GST_FLOW_CUSTOM_SUCCESS_1) + gst_event_unref (event); + + switch (ret) { + case GST_FLOW_CUSTOM_SUCCESS_1: + case GST_FLOW_CUSTOM_SUCCESS: + GST_DEBUG_OBJECT (pad, "dropped or handled event"); + ret = GST_FLOW_OK; + break; + default: + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); + break; + } + return ret; + } +no_function: + { + g_warning ("pad %s:%s has no event handler, file a bug.", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + gst_event_unref (event); + return GST_FLOW_NOT_SUPPORTED; + } +no_parent: + { + GST_DEBUG_OBJECT (pad, "no parent"); + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + gst_event_unref (event); + return GST_FLOW_FLUSHING; + } +precheck_failed: + { + GST_DEBUG_OBJECT (pad, "pre event check failed"); + RELEASE_PARENT (parent); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + gst_event_unref (event); + return ret; + } +} + +/** + * gst_pad_send_event: + * @pad: a #GstPad to send the event to. + * @event: (transfer full): the #GstEvent to send to the pad. + * + * Sends the event to the pad. This function can be used + * by applications to send events in the pipeline. + * + * If @pad is a source pad, @event should be an upstream event. If @pad is a + * sink pad, @event should be a downstream event. For example, you would not + * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream. + * Furthermore, some downstream events have to be serialized with data flow, + * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If + * the event needs to be serialized with data flow, this function will take the + * pad's stream lock while calling its event function. + * + * To find out whether an event type is upstream, downstream, or downstream and + * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(), + * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and + * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or + * plugin doesn't need to bother itself with this information; the core handles + * all necessary locks and checks. + * + * This function takes ownership of the provided event so you should + * gst_event_ref() it if you want to reuse the event after this call. + * + * Returns: %TRUE if the event was handled. + */ +gboolean +gst_pad_send_event (GstPad * pad, GstEvent * event) +{ + gboolean result; + GstPadProbeType type; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (GST_PAD_IS_SINK (pad)) { + if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM; + } else if (GST_PAD_IS_SRC (pad)) { + if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event))) + goto wrong_direction; + type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM; + } else + goto unknown_direction; + + if (gst_pad_send_event_unchecked (pad, event, type) != GST_FLOW_OK) + result = FALSE; + else + result = TRUE; + + return result; + + /* ERROR handling */ +wrong_direction: + { + g_warning ("pad %s:%s sending %s event in wrong direction", + GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event)); + gst_event_unref (event); + return FALSE; + } +unknown_direction: + { + g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); + gst_event_unref (event); + return FALSE; + } +} + +/** + * gst_pad_set_element_private: + * @pad: the #GstPad to set the private data of. + * @priv: The private data to attach to the pad. + * + * Set the given private data gpointer on the pad. + * This function can only be used by the element that owns the pad. + * No locking is performed in this function. + */ +void +gst_pad_set_element_private (GstPad * pad, gpointer priv) +{ + pad->element_private = priv; +} + +/** + * gst_pad_get_element_private: + * @pad: the #GstPad to get the private data of. + * + * Gets the private data of a pad. + * No locking is performed in this function. + * + * Returns: (transfer none) (nullable): a #gpointer to the private data. + */ +gpointer +gst_pad_get_element_private (GstPad * pad) +{ + return pad->element_private; +} + +/** + * gst_pad_get_sticky_event: + * @pad: the #GstPad to get the event from. + * @event_type: the #GstEventType that should be retrieved. + * @idx: the index of the event + * + * Returns a new reference of the sticky event of type @event_type + * from the event. + * + * Returns: (transfer full) (nullable): a #GstEvent of type + * @event_type or %NULL when no event of @event_type was on + * @pad. Unref after usage. + */ +GstEvent * +gst_pad_get_sticky_event (GstPad * pad, GstEventType event_type, guint idx) +{ + GstEvent *event = NULL; + PadEvent *ev; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail ((event_type & GST_EVENT_TYPE_STICKY) != 0, NULL); + + GST_OBJECT_LOCK (pad); + ev = find_event_by_type (pad, event_type, idx); + if (ev && (event = ev->event)) + gst_event_ref (event); + GST_OBJECT_UNLOCK (pad); + + return event; +} + +typedef struct +{ + GstPadStickyEventsForeachFunction func; + gpointer user_data; +} ForeachDispatch; + +static gboolean +foreach_dispatch_function (GstPad * pad, PadEvent * ev, gpointer user_data) +{ + ForeachDispatch *data = user_data; + gboolean ret = TRUE; + + if (ev->event) { + GST_OBJECT_UNLOCK (pad); + + ret = data->func (pad, &ev->event, data->user_data); + + GST_OBJECT_LOCK (pad); + } + + return ret; +} + +/** + * gst_pad_sticky_events_foreach: + * @pad: the #GstPad that should be used for iteration. + * @foreach_func: (scope call): the #GstPadStickyEventsForeachFunction that + * should be called for every event. + * @user_data: (closure): the optional user data. + * + * Iterates all sticky events on @pad and calls @foreach_func for every + * event. If @foreach_func returns %FALSE the iteration is immediately stopped. + */ +void +gst_pad_sticky_events_foreach (GstPad * pad, + GstPadStickyEventsForeachFunction foreach_func, gpointer user_data) +{ + ForeachDispatch data; + + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (foreach_func != NULL); + + data.func = foreach_func; + data.user_data = user_data; + + GST_OBJECT_LOCK (pad); + events_foreach (pad, foreach_dispatch_function, &data); + GST_OBJECT_UNLOCK (pad); +} + +static void +do_stream_status (GstPad * pad, GstStreamStatusType type, + GThread * thread, GstTask * task) +{ + GstElement *parent; + + GST_DEBUG_OBJECT (pad, "doing stream-status %d", type); + + if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (pad)))) { + if (GST_IS_ELEMENT (parent)) { + GstMessage *message; + GValue value = { 0 }; + + if (type == GST_STREAM_STATUS_TYPE_ENTER) { + gchar *tname, *ename, *pname; + + /* create a good task name */ + ename = gst_element_get_name (parent); + pname = gst_pad_get_name (pad); + tname = g_strdup_printf ("%s:%s", ename, pname); + g_free (ename); + g_free (pname); + + gst_object_set_name (GST_OBJECT_CAST (task), tname); + g_free (tname); + } + + message = gst_message_new_stream_status (GST_OBJECT_CAST (pad), + type, parent); + + g_value_init (&value, GST_TYPE_TASK); + g_value_set_object (&value, task); + gst_message_set_stream_status_object (message, &value); + g_value_unset (&value); + + GST_DEBUG_OBJECT (pad, "posting stream-status %d", type); + gst_element_post_message (parent, message); + } + gst_object_unref (parent); + } +} + +static void +pad_enter_thread (GstTask * task, GThread * thread, gpointer user_data) +{ + do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_ENTER, + thread, task); +} + +static void +pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data) +{ + do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_LEAVE, + thread, task); +} + +/** + * gst_pad_start_task: + * @pad: the #GstPad to start the task of + * @func: the task function to call + * @user_data: user data passed to the task function + * @notify: called when @user_data is no longer referenced + * + * Starts a task that repeatedly calls @func with @user_data. This function + * is mostly used in pad activation functions to start the dataflow. + * The #GST_PAD_STREAM_LOCK of @pad will automatically be acquired + * before @func is called. + * + * Returns: a %TRUE if the task could be started. + */ +gboolean +gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer user_data, + GDestroyNotify notify) +{ + GstTask *task; + gboolean res; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + GST_DEBUG_OBJECT (pad, "start task"); + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task == NULL) { + task = gst_task_new (func, user_data, notify); + gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad)); + gst_task_set_enter_callback (task, pad_enter_thread, pad, NULL); + gst_task_set_leave_callback (task, pad_leave_thread, pad, NULL); + GST_INFO_OBJECT (pad, "created task %p", task); + GST_PAD_TASK (pad) = task; + gst_object_ref (task); + /* release lock to post the message */ + GST_OBJECT_UNLOCK (pad); + + do_stream_status (pad, GST_STREAM_STATUS_TYPE_CREATE, NULL, task); + + gst_object_unref (task); + + GST_OBJECT_LOCK (pad); + /* nobody else is supposed to have changed the pad now */ + if (GST_PAD_TASK (pad) != task) + goto concurrent_stop; + } + res = gst_task_set_state (task, GST_TASK_STARTED); + GST_OBJECT_UNLOCK (pad); + + return res; + + /* ERRORS */ +concurrent_stop: + { + GST_OBJECT_UNLOCK (pad); + return TRUE; + } +} + +/** + * gst_pad_pause_task: + * @pad: the #GstPad to pause the task of + * + * Pause the task of @pad. This function will also wait until the + * function executed by the task is finished if this function is not + * called from the task function. + * + * Returns: a %TRUE if the task could be paused or %FALSE when the pad + * has no task. + */ +gboolean +gst_pad_pause_task (GstPad * pad) +{ + GstTask *task; + gboolean res; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_DEBUG_OBJECT (pad, "pause task"); + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task == NULL) + goto no_task; + res = gst_task_set_state (task, GST_TASK_PAUSED); + /* unblock activation waits if any */ + pad->priv->in_activation = FALSE; + g_cond_broadcast (&pad->priv->activation_cond); + GST_OBJECT_UNLOCK (pad); + + /* wait for task function to finish, this lock is recursive so it does nothing + * when the pause is called from the task itself */ + GST_PAD_STREAM_LOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + + return res; + +no_task: + { + GST_DEBUG_OBJECT (pad, "pad has no task"); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +/** + * gst_pad_get_task_state: + * @pad: the #GstPad to get task state from + * + * Get @pad task state. If no task is currently + * set, #GST_TASK_STOPPED is returned. + * + * Returns: The current state of @pad's task. + * + * Since: 1.12 + */ +GstTaskState +gst_pad_get_task_state (GstPad * pad) +{ + GstTask *task; + GstTaskState res; + + g_return_val_if_fail (GST_IS_PAD (pad), GST_TASK_STOPPED); + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task == NULL) + goto no_task; + res = gst_task_get_state (task); + GST_OBJECT_UNLOCK (pad); + + return res; + +no_task: + { + GST_DEBUG_OBJECT (pad, "pad has no task"); + GST_OBJECT_UNLOCK (pad); + return GST_TASK_STOPPED; + } +} + +/** + * gst_pad_stop_task: + * @pad: the #GstPad to stop the task of + * + * Stop the task of @pad. This function will also make sure that the + * function executed by the task will effectively stop if not called + * from the GstTaskFunction. + * + * This function will deadlock if called from the GstTaskFunction of + * the task. Use gst_task_pause() instead. + * + * Regardless of whether the pad has a task, the stream lock is acquired and + * released so as to ensure that streaming through this pad has finished. + * + * Returns: a %TRUE if the task could be stopped or %FALSE on error. + */ +gboolean +gst_pad_stop_task (GstPad * pad) +{ + GstTask *task; + gboolean res; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_DEBUG_OBJECT (pad, "stop task"); + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task == NULL) + goto no_task; + GST_PAD_TASK (pad) = NULL; + res = gst_task_set_state (task, GST_TASK_STOPPED); + /* unblock activation waits if any */ + pad->priv->in_activation = FALSE; + g_cond_broadcast (&pad->priv->activation_cond); + GST_OBJECT_UNLOCK (pad); + + GST_PAD_STREAM_LOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + + if (!gst_task_join (task)) + goto join_failed; + + gst_object_unref (task); + + return res; + +no_task: + { + GST_DEBUG_OBJECT (pad, "no task"); + GST_OBJECT_UNLOCK (pad); + + GST_PAD_STREAM_LOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + + /* this is not an error */ + return TRUE; + } +join_failed: + { + /* this is bad, possibly the application tried to join the task from + * the task's thread. We install the task again so that it will be stopped + * again from the right thread next time hopefully. */ + GST_OBJECT_LOCK (pad); + GST_DEBUG_OBJECT (pad, "join failed"); + /* we can only install this task if there was no other task */ + if (GST_PAD_TASK (pad) == NULL) + GST_PAD_TASK (pad) = task; + GST_OBJECT_UNLOCK (pad); + + return FALSE; + } +} + +/** + * gst_pad_probe_info_get_event: + * @info: a #GstPadProbeInfo + * + * Returns: (transfer none) (nullable): The #GstEvent from the probe + */ + +GstEvent * +gst_pad_probe_info_get_event (GstPadProbeInfo * info) +{ + g_return_val_if_fail (info->type & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | + GST_PAD_PROBE_TYPE_EVENT_UPSTREAM), NULL); + + return GST_PAD_PROBE_INFO_EVENT (info); +} + + +/** + * gst_pad_probe_info_get_query: + * @info: a #GstPadProbeInfo + * + * Returns: (transfer none) (nullable): The #GstQuery from the probe + */ + +GstQuery * +gst_pad_probe_info_get_query (GstPadProbeInfo * info) +{ + g_return_val_if_fail (info->type & (GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM | + GST_PAD_PROBE_TYPE_QUERY_UPSTREAM), NULL); + + return GST_PAD_PROBE_INFO_QUERY (info); +} + +/** + * gst_pad_probe_info_get_buffer: + * @info: a #GstPadProbeInfo + * + * Returns: (transfer none) (nullable): The #GstBuffer from the probe + */ + +GstBuffer * +gst_pad_probe_info_get_buffer (GstPadProbeInfo * info) +{ + g_return_val_if_fail (info->type & GST_PAD_PROBE_TYPE_BUFFER, NULL); + + return GST_PAD_PROBE_INFO_BUFFER (info); +} + +/** + * gst_pad_probe_info_get_buffer_list: + * @info: a #GstPadProbeInfo + * + * Returns: (transfer none) (nullable): The #GstBufferList from the probe + */ + +GstBufferList * +gst_pad_probe_info_get_buffer_list (GstPadProbeInfo * info) +{ + g_return_val_if_fail (info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST, NULL); + + return GST_PAD_PROBE_INFO_BUFFER_LIST (info); +} + +/** + * gst_pad_get_last_flow_return: + * @pad: the #GstPad + * + * Gets the #GstFlowReturn return from the last data passed by this pad. + * + * Since: 1.4 + */ +GstFlowReturn +gst_pad_get_last_flow_return (GstPad * pad) +{ + GstFlowReturn ret; + + GST_OBJECT_LOCK (pad); + ret = GST_PAD_LAST_FLOW_RETURN (pad); + GST_OBJECT_UNLOCK (pad); + + return ret; +} diff --git a/gst/gstpad.h b/gst/gstpad.h new file mode 100644 index 0000000..079eac3 --- /dev/null +++ b/gst/gstpad.h @@ -0,0 +1,1569 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpad.h: Header for GstPad 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_PAD_H__ +#define __GST_PAD_H__ + +#include + +typedef struct _GstPad GstPad; +typedef struct _GstPadPrivate GstPadPrivate; +typedef struct _GstPadClass GstPadClass; +typedef struct _GstPadProbeInfo GstPadProbeInfo; + +/** + * GstPadDirection: + * @GST_PAD_UNKNOWN: direction is unknown. + * @GST_PAD_SRC: the pad is a source pad. + * @GST_PAD_SINK: the pad is a sink pad. + * + * The direction of a pad. + */ +typedef enum { + GST_PAD_UNKNOWN, + GST_PAD_SRC, + GST_PAD_SINK +} GstPadDirection; + +/** + * GstPadMode: + * @GST_PAD_MODE_NONE: Pad will not handle dataflow + * @GST_PAD_MODE_PUSH: Pad handles dataflow in downstream push mode + * @GST_PAD_MODE_PULL: Pad handles dataflow in upstream pull mode + * + * The status of a GstPad. After activating a pad, which usually happens when the + * parent element goes from READY to PAUSED, the GstPadMode defines if the + * pad operates in push or pull mode. + */ +typedef enum { + GST_PAD_MODE_NONE, + GST_PAD_MODE_PUSH, + GST_PAD_MODE_PULL +} GstPadMode; + +#include + +GST_API +const gchar * gst_pad_mode_get_name (GstPadMode mode); + +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/* + * Pad base class + */ +#define GST_TYPE_PAD (gst_pad_get_type ()) +#define GST_IS_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PAD)) +#define GST_IS_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PAD)) +#define GST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD, GstPad)) +#define GST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD, GstPadClass)) +#define GST_PAD_CAST(obj) ((GstPad*)(obj)) + + + +/** + * GstPadLinkReturn: + * @GST_PAD_LINK_OK : link succeeded + * @GST_PAD_LINK_WRONG_HIERARCHY: pads have no common grandparent + * @GST_PAD_LINK_WAS_LINKED : pad was already linked + * @GST_PAD_LINK_WRONG_DIRECTION: pads have wrong direction + * @GST_PAD_LINK_NOFORMAT : pads do not have common format + * @GST_PAD_LINK_NOSCHED : pads cannot cooperate in scheduling + * @GST_PAD_LINK_REFUSED : refused for some reason + * + * Result values from gst_pad_link and friends. + */ +typedef enum { + GST_PAD_LINK_OK = 0, + GST_PAD_LINK_WRONG_HIERARCHY = -1, + GST_PAD_LINK_WAS_LINKED = -2, + GST_PAD_LINK_WRONG_DIRECTION = -3, + GST_PAD_LINK_NOFORMAT = -4, + GST_PAD_LINK_NOSCHED = -5, + GST_PAD_LINK_REFUSED = -6 +} GstPadLinkReturn; + +/** + * GST_PAD_LINK_FAILED: + * @ret: the #GstPadLinkReturn value + * + * Macro to test if the given #GstPadLinkReturn value indicates a failed + * link step. + */ +#define GST_PAD_LINK_FAILED(ret) ((ret) < GST_PAD_LINK_OK) + +/** + * GST_PAD_LINK_SUCCESSFUL: + * @ret: the #GstPadLinkReturn value + * + * Macro to test if the given #GstPadLinkReturn value indicates a successful + * link step. + */ +#define GST_PAD_LINK_SUCCESSFUL(ret) ((ret) >= GST_PAD_LINK_OK) + +/** + * GstFlowReturn: + * @GST_FLOW_OK: Data passing was ok. + * @GST_FLOW_NOT_LINKED: Pad is not linked. + * @GST_FLOW_FLUSHING: Pad is flushing. + * @GST_FLOW_EOS: Pad is EOS. + * @GST_FLOW_NOT_NEGOTIATED: Pad is not negotiated. + * @GST_FLOW_ERROR: Some (fatal) error occurred. Element generating + * this error should post an error message with more + * details. + * @GST_FLOW_NOT_SUPPORTED: This operation is not supported. + * @GST_FLOW_CUSTOM_SUCCESS: Elements can use values starting from + * this (and higher) to define custom success + * codes. + * @GST_FLOW_CUSTOM_SUCCESS_1: Pre-defined custom success code (define your + * custom success code to this to avoid compiler + * warnings). + * @GST_FLOW_CUSTOM_SUCCESS_2: Pre-defined custom success code. + * @GST_FLOW_CUSTOM_ERROR: Elements can use values starting from + * this (and lower) to define custom error codes. + * @GST_FLOW_CUSTOM_ERROR_1: Pre-defined custom error code (define your + * custom error code to this to avoid compiler + * warnings). + * @GST_FLOW_CUSTOM_ERROR_2: Pre-defined custom error code. + * + * The result of passing data to a pad. + * + * Note that the custom return values should not be exposed outside of the + * element scope. + */ +typedef enum { + /* custom success starts here */ + GST_FLOW_CUSTOM_SUCCESS_2 = 102, + GST_FLOW_CUSTOM_SUCCESS_1 = 101, + GST_FLOW_CUSTOM_SUCCESS = 100, + + /* core predefined */ + GST_FLOW_OK = 0, + /* expected failures */ + GST_FLOW_NOT_LINKED = -1, + GST_FLOW_FLUSHING = -2, + /* error cases */ + GST_FLOW_EOS = -3, + GST_FLOW_NOT_NEGOTIATED = -4, + GST_FLOW_ERROR = -5, + GST_FLOW_NOT_SUPPORTED = -6, + + /* custom error starts here */ + GST_FLOW_CUSTOM_ERROR = -100, + GST_FLOW_CUSTOM_ERROR_1 = -101, + GST_FLOW_CUSTOM_ERROR_2 = -102 +} GstFlowReturn; + +GST_API +const gchar * gst_flow_get_name (GstFlowReturn ret); + +GST_API +GQuark gst_flow_to_quark (GstFlowReturn ret); + +GST_API +const gchar * gst_pad_link_get_name (GstPadLinkReturn ret); + +/** + * GstPadLinkCheck: + * @GST_PAD_LINK_CHECK_NOTHING: Don't check hierarchy or caps compatibility. + * @GST_PAD_LINK_CHECK_HIERARCHY: Check the pads have same parents/grandparents. + * Could be omitted if it is already known that the two elements that own the + * pads are in the same bin. + * @GST_PAD_LINK_CHECK_TEMPLATE_CAPS: Check if the pads are compatible by using + * their template caps. This is much faster than @GST_PAD_LINK_CHECK_CAPS, but + * would be unsafe e.g. if one pad has %GST_CAPS_ANY. + * @GST_PAD_LINK_CHECK_CAPS: Check if the pads are compatible by comparing the + * caps returned by gst_pad_query_caps(). + * @GST_PAD_LINK_CHECK_NO_RECONFIGURE: Disables pushing a reconfigure event when pads are + * linked. + * @GST_PAD_LINK_CHECK_DEFAULT: The default checks done when linking + * pads (i.e. the ones used by gst_pad_link()). + * + * The amount of checking to be done when linking pads. @GST_PAD_LINK_CHECK_CAPS + * and @GST_PAD_LINK_CHECK_TEMPLATE_CAPS are mutually exclusive. If both are + * specified, expensive but safe @GST_PAD_LINK_CHECK_CAPS are performed. + * + * > Only disable some of the checks if you are 100% certain you know the link + * > will not fail because of hierarchy/caps compatibility failures. If uncertain, + * > use the default checks (%GST_PAD_LINK_CHECK_DEFAULT) or the regular methods + * > for linking the pads. + */ + +typedef enum { + GST_PAD_LINK_CHECK_NOTHING = 0, + GST_PAD_LINK_CHECK_HIERARCHY = 1 << 0, + GST_PAD_LINK_CHECK_TEMPLATE_CAPS = 1 << 1, + GST_PAD_LINK_CHECK_CAPS = 1 << 2, + + + /* Not really checks, more like flags + * Added here to avoid creating a new gst_pad_link_variant */ + GST_PAD_LINK_CHECK_NO_RECONFIGURE = 1 << 3, + + GST_PAD_LINK_CHECK_DEFAULT = GST_PAD_LINK_CHECK_HIERARCHY | GST_PAD_LINK_CHECK_CAPS +} GstPadLinkCheck; + +/* pad states */ +/** + * GstPadActivateFunction: + * @pad: a #GstPad + * @parent: the parent of @pad + * + * This function is called when the pad is activated during the element + * READY to PAUSED state change. By default this function will call the + * activate function that puts the pad in push mode but elements can + * override this function to activate the pad in pull mode if they wish. + * + * Returns: %TRUE if the pad could be activated. + */ +typedef gboolean (*GstPadActivateFunction) (GstPad *pad, GstObject *parent); +/** + * GstPadActivateModeFunction: + * @pad: a #GstPad + * @parent: the parent of @pad + * @mode: the requested activation mode of @pad + * @active: activate or deactivate the pad. + * + * The prototype of the push and pull activate functions. + * + * Returns: %TRUE if the pad could be activated or deactivated. + */ +typedef gboolean (*GstPadActivateModeFunction) (GstPad *pad, GstObject *parent, + GstPadMode mode, gboolean active); + + +/* data passing */ +/** + * GstPadChainFunction: + * @pad: the sink #GstPad that performed the chain. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @buffer: (transfer full): the #GstBuffer that is chained, not %NULL. + * + * A function that will be called on sinkpads when chaining buffers. + * The function typically processes the data contained in the buffer and + * either consumes the data or passes it on to the internally linked pad(s). + * + * The implementer of this function receives a refcount to @buffer and should + * gst_buffer_unref() when the buffer is no longer needed. + * + * When a chain function detects an error in the data stream, it must post an + * error on the bus and return an appropriate #GstFlowReturn value. + * + * Returns: #GST_FLOW_OK for success + */ +typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstObject *parent, + GstBuffer *buffer); + +/** + * GstPadChainListFunction: + * @pad: the sink #GstPad that performed the chain. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @list: (transfer full): the #GstBufferList that is chained, not %NULL. + * + * A function that will be called on sinkpads when chaining buffer lists. + * The function typically processes the data contained in the buffer list and + * either consumes the data or passes it on to the internally linked pad(s). + * + * The implementer of this function receives a refcount to @list and + * should gst_buffer_list_unref() when the list is no longer needed. + * + * When a chainlist function detects an error in the data stream, it must + * post an error on the bus and return an appropriate #GstFlowReturn value. + * + * Returns: #GST_FLOW_OK for success + */ +typedef GstFlowReturn (*GstPadChainListFunction) (GstPad *pad, GstObject *parent, + GstBufferList *list); + +/** + * GstPadGetRangeFunction: + * @pad: the src #GstPad to perform the getrange on. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @offset: the offset of the range + * @length: the length of the range + * @buffer: a memory location to hold the result buffer, cannot be %NULL. + * + * This function will be called on source pads when a peer element + * request a buffer at the specified @offset and @length. If this function + * returns #GST_FLOW_OK, the result buffer will be stored in @buffer. The + * contents of @buffer is invalid for any other return value. + * + * This function is installed on a source pad with + * gst_pad_set_getrange_function() and can only be called on source pads after + * they are successfully activated with gst_pad_activate_mode() with the + * #GST_PAD_MODE_PULL. + * + * @offset and @length are always given in byte units. @offset must normally be a value + * between 0 and the length in bytes of the data available on @pad. The + * length (duration in bytes) can be retrieved with a #GST_QUERY_DURATION or with a + * #GST_QUERY_SEEKING. + * + * Any @offset larger or equal than the length will make the function return + * #GST_FLOW_EOS, which corresponds to EOS. In this case @buffer does not + * contain a valid buffer. + * + * The buffer size of @buffer will only be smaller than @length when @offset is + * near the end of the stream. In all other cases, the size of @buffer must be + * exactly the requested size. + * + * It is allowed to call this function with a 0 @length and valid @offset, in + * which case @buffer will contain a 0-sized buffer and the function returns + * #GST_FLOW_OK. + * + * When this function is called with a -1 @offset, the sequentially next buffer + * of length @length in the stream is returned. + * + * When this function is called with a -1 @length, a buffer with a default + * optimal length is returned in @buffer. The length might depend on the value + * of @offset. + * + * Returns: #GST_FLOW_OK for success and a valid buffer in @buffer. Any other + * return value leaves @buffer undefined. + */ +typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, GstObject *parent, + guint64 offset, guint length, + GstBuffer **buffer); + +/** + * GstPadEventFunction: + * @pad: the #GstPad to handle the event. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @event: (transfer full): the #GstEvent to handle. + * + * Function signature to handle an event for the pad. + * + * Returns: %TRUE if the pad could handle the event. + */ +typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent, + GstEvent *event); + +/** + * GstPadEventFullFunction: + * @pad: the #GstPad to handle the event. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @event: (transfer full): the #GstEvent to handle. + * + * Function signature to handle an event for the pad. + * + * This variant is for specific elements that will take into account the + * last downstream flow return (from a pad push), in which case they can + * return it. + * + * Returns: %GST_FLOW_OK if the event was handled properly, or any other + * #GstFlowReturn dependent on downstream state. + * + * Since: 1.8 + */ +typedef GstFlowReturn (*GstPadEventFullFunction) (GstPad *pad, GstObject *parent, + GstEvent *event); + + +/* internal links */ +/** + * GstPadIterIntLinkFunction: + * @pad: The #GstPad to query. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * + * The signature of the internal pad link iterator function. + * + * Returns: a new #GstIterator that will iterate over all pads that are + * linked to the given pad on the inside of the parent element. + * + * the caller must call gst_iterator_free() after usage. + */ +typedef GstIterator* (*GstPadIterIntLinkFunction) (GstPad *pad, GstObject *parent); + +/* generic query function */ +/** + * GstPadQueryFunction: + * @pad: the #GstPad to query. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @query: the #GstQuery object to execute + * + * The signature of the query function. + * + * Returns: %TRUE if the query could be performed. + */ +typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstObject *parent, + GstQuery *query); + + +/* linking */ +/** + * GstPadLinkFunction: + * @pad: the #GstPad that is linked. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * @peer: the peer #GstPad of the link + * + * Function signature to handle a new link on the pad. + * + * Returns: the result of the link with the specified peer. + */ +typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstObject *parent, GstPad *peer); +/** + * GstPadUnlinkFunction: + * @pad: the #GstPad that is linked. + * @parent: (allow-none): the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT + * flag is set, @parent is guaranteed to be not-%NULL and remain valid + * during the execution of this function. + * + * Function signature to handle a unlinking the pad prom its peer. + */ +typedef void (*GstPadUnlinkFunction) (GstPad *pad, GstObject *parent); + + +/* misc */ +/** + * GstPadForwardFunction: + * @pad: the #GstPad that is forwarded. + * @user_data: the gpointer to optional user data. + * + * A forward function is called for all internally linked pads, see + * gst_pad_forward(). + * + * Returns: %TRUE if the dispatching procedure has to be stopped. + */ +typedef gboolean (*GstPadForwardFunction) (GstPad *pad, gpointer user_data); + +/** + * GstPadProbeType: + * @GST_PAD_PROBE_TYPE_INVALID: invalid probe type + * @GST_PAD_PROBE_TYPE_IDLE: probe idle pads and block while the callback is called + * @GST_PAD_PROBE_TYPE_BLOCK: probe and block pads + * @GST_PAD_PROBE_TYPE_BUFFER: probe buffers + * @GST_PAD_PROBE_TYPE_BUFFER_LIST: probe buffer lists + * @GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM: probe downstream events + * @GST_PAD_PROBE_TYPE_EVENT_UPSTREAM: probe upstream events + * @GST_PAD_PROBE_TYPE_EVENT_FLUSH: probe flush events. This probe has to be + * explicitly enabled and is not included in the + * @@GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM or + * @@GST_PAD_PROBE_TYPE_EVENT_UPSTREAM probe types. + * @GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM: probe downstream queries + * @GST_PAD_PROBE_TYPE_QUERY_UPSTREAM: probe upstream queries + * @GST_PAD_PROBE_TYPE_PUSH: probe push + * @GST_PAD_PROBE_TYPE_PULL: probe pull + * @GST_PAD_PROBE_TYPE_BLOCKING: probe and block at the next opportunity, at data flow or when idle + * @GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM: probe downstream data (buffers, buffer lists, and events) + * @GST_PAD_PROBE_TYPE_DATA_UPSTREAM: probe upstream data (events) + * @GST_PAD_PROBE_TYPE_DATA_BOTH: probe upstream and downstream data (buffers, buffer lists, and events) + * @GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM: probe and block downstream data (buffers, buffer lists, and events) + * @GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM: probe and block upstream data (events) + * @GST_PAD_PROBE_TYPE_EVENT_BOTH: probe upstream and downstream events + * @GST_PAD_PROBE_TYPE_QUERY_BOTH: probe upstream and downstream queries + * @GST_PAD_PROBE_TYPE_ALL_BOTH: probe upstream events and queries and downstream buffers, buffer lists, events and queries + * @GST_PAD_PROBE_TYPE_SCHEDULING: probe push and pull + * + * The different probing types that can occur. When either one of + * @GST_PAD_PROBE_TYPE_IDLE or @GST_PAD_PROBE_TYPE_BLOCK is used, the probe will be a + * blocking probe. + */ +typedef enum +{ + GST_PAD_PROBE_TYPE_INVALID = 0, + /* flags to control blocking */ + GST_PAD_PROBE_TYPE_IDLE = (1 << 0), + GST_PAD_PROBE_TYPE_BLOCK = (1 << 1), + /* flags to select datatypes */ + GST_PAD_PROBE_TYPE_BUFFER = (1 << 4), + GST_PAD_PROBE_TYPE_BUFFER_LIST = (1 << 5), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM = (1 << 6), + GST_PAD_PROBE_TYPE_EVENT_UPSTREAM = (1 << 7), + GST_PAD_PROBE_TYPE_EVENT_FLUSH = (1 << 8), + GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM = (1 << 9), + GST_PAD_PROBE_TYPE_QUERY_UPSTREAM = (1 << 10), + /* flags to select scheduling mode */ + GST_PAD_PROBE_TYPE_PUSH = (1 << 12), + GST_PAD_PROBE_TYPE_PULL = (1 << 13), + + /* flag combinations */ + GST_PAD_PROBE_TYPE_BLOCKING = GST_PAD_PROBE_TYPE_IDLE | GST_PAD_PROBE_TYPE_BLOCK, + GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM = GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + GST_PAD_PROBE_TYPE_DATA_UPSTREAM = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, + GST_PAD_PROBE_TYPE_DATA_BOTH = GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM | GST_PAD_PROBE_TYPE_DATA_UPSTREAM, + GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM = GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM = GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_DATA_UPSTREAM, + GST_PAD_PROBE_TYPE_EVENT_BOTH = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, + GST_PAD_PROBE_TYPE_QUERY_BOTH = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM | GST_PAD_PROBE_TYPE_QUERY_UPSTREAM, + GST_PAD_PROBE_TYPE_ALL_BOTH = GST_PAD_PROBE_TYPE_DATA_BOTH | GST_PAD_PROBE_TYPE_QUERY_BOTH, + GST_PAD_PROBE_TYPE_SCHEDULING = GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_PULL +} GstPadProbeType; + + +/** + * GstPadProbeReturn: + * @GST_PAD_PROBE_OK: normal probe return value. This leaves the probe in + * place, and defers decisions about dropping or passing data to other + * probes, if any. If there are no other probes, the default behaviour + * for the probe type applies ('block' for blocking probes, + * and 'pass' for non-blocking probes). + * @GST_PAD_PROBE_DROP: drop data in data probes. For push mode this means that + * the data item is not sent downstream. For pull mode, it means that + * the data item is not passed upstream. In both cases, no other probes + * are called for this item and %GST_FLOW_OK or %TRUE is returned to the + * caller. + * @GST_PAD_PROBE_REMOVE: remove this probe. + * @GST_PAD_PROBE_PASS: pass the data item in the block probe and block on the + * next item. + * @GST_PAD_PROBE_HANDLED: Data has been handled in the probe and will not be + * forwarded further. For events and buffers this is the same behaviour as + * %GST_PAD_PROBE_DROP (except that in this case you need to unref the buffer + * or event yourself). For queries it will also return %TRUE to the caller. + * The probe can also modify the #GstFlowReturn value by using the + * #GST_PAD_PROBE_INFO_FLOW_RETURN() accessor. + * Note that the resulting query must contain valid entries. + * Since: 1.6 + * + * Different return values for the #GstPadProbeCallback. + */ +typedef enum +{ + GST_PAD_PROBE_DROP, + GST_PAD_PROBE_OK, + GST_PAD_PROBE_REMOVE, + GST_PAD_PROBE_PASS, + GST_PAD_PROBE_HANDLED +} GstPadProbeReturn; + + +/** + * GstPadProbeInfo: + * @type: the current probe type + * @id: the id of the probe + * @data: (allow-none): type specific data, check the @type field to know the + * datatype. This field can be %NULL. + * @offset: offset of pull probe, this field is valid when @type contains + * #GST_PAD_PROBE_TYPE_PULL + * @size: size of pull probe, this field is valid when @type contains + * #GST_PAD_PROBE_TYPE_PULL + * + * Info passed in the #GstPadProbeCallback. + */ +struct _GstPadProbeInfo +{ + GstPadProbeType type; + gulong id; + gpointer data; + guint64 offset; + guint size; + + /*< private >*/ + union { + gpointer _gst_reserved[GST_PADDING]; + struct { + GstFlowReturn flow_ret; + } abi; + } ABI; +}; + +#define GST_PAD_PROBE_INFO_TYPE(d) ((d)->type) +#define GST_PAD_PROBE_INFO_ID(d) ((d)->id) +#define GST_PAD_PROBE_INFO_DATA(d) ((d)->data) +#define GST_PAD_PROBE_INFO_FLOW_RETURN(d) ((d)->ABI.abi.flow_ret) + +#define GST_PAD_PROBE_INFO_BUFFER(d) GST_BUFFER_CAST(GST_PAD_PROBE_INFO_DATA(d)) +#define GST_PAD_PROBE_INFO_BUFFER_LIST(d) GST_BUFFER_LIST_CAST(GST_PAD_PROBE_INFO_DATA(d)) +#define GST_PAD_PROBE_INFO_EVENT(d) GST_EVENT_CAST(GST_PAD_PROBE_INFO_DATA(d)) +#define GST_PAD_PROBE_INFO_QUERY(d) GST_QUERY_CAST(GST_PAD_PROBE_INFO_DATA(d)) + +#define GST_PAD_PROBE_INFO_OFFSET(d) ((d)->offset) +#define GST_PAD_PROBE_INFO_SIZE(d) ((d)->size) + +GST_API +GstEvent* gst_pad_probe_info_get_event (GstPadProbeInfo * info); + +GST_API +GstQuery* gst_pad_probe_info_get_query (GstPadProbeInfo * info); + +GST_API +GstBuffer* gst_pad_probe_info_get_buffer (GstPadProbeInfo * info); + +GST_API +GstBufferList* gst_pad_probe_info_get_buffer_list (GstPadProbeInfo * info); + +/** + * GstPadProbeCallback: + * @pad: the #GstPad that is blocked + * @info: #GstPadProbeInfo + * @user_data: the gpointer to optional user data. + * + * Callback used by gst_pad_add_probe(). Gets called to notify about the current + * blocking type. + * + * The callback is allowed to modify the data pointer in @info. + * + * Returns: a #GstPadProbeReturn + */ +typedef GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info, + gpointer user_data); + +/** + * GstPadStickyEventsForeachFunction: + * @pad: the #GstPad. + * @event: (allow-none): a sticky #GstEvent. + * @user_data: the #gpointer to optional user data. + * + * Callback used by gst_pad_sticky_events_foreach(). + * + * When this function returns %TRUE, the next event will be + * returned. When %FALSE is returned, gst_pad_sticky_events_foreach() will return. + * + * When @event is set to %NULL, the item will be removed from the list of sticky events. + * @event can be replaced by assigning a new reference to it. + * This function is responsible for unreffing the old event when + * removing or modifying. + * + * Returns: %TRUE if the iteration should continue + */ +typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent **event, + gpointer user_data); + +/** + * GstPadFlags: + * @GST_PAD_FLAG_BLOCKED: is dataflow on a pad blocked + * @GST_PAD_FLAG_FLUSHING: is pad flushing + * @GST_PAD_FLAG_EOS: is pad in EOS state + * @GST_PAD_FLAG_BLOCKING: is pad currently blocking on a buffer or event + * @GST_PAD_FLAG_NEED_PARENT: ensure that there is a parent object before calling + * into the pad callbacks. + * @GST_PAD_FLAG_NEED_RECONFIGURE: the pad should be reconfigured/renegotiated. + * The flag has to be unset manually after + * reconfiguration happened. + * @GST_PAD_FLAG_PENDING_EVENTS: the pad has pending events + * @GST_PAD_FLAG_FIXED_CAPS: the pad is using fixed caps. This means that + * once the caps are set on the pad, the default caps query function + * will only return those caps. + * @GST_PAD_FLAG_PROXY_CAPS: the default event and query handler will forward + * all events and queries to the internally linked pads + * instead of discarding them. + * @GST_PAD_FLAG_PROXY_ALLOCATION: the default query handler will forward + * allocation queries to the internally linked pads + * instead of discarding them. + * @GST_PAD_FLAG_PROXY_SCHEDULING: the default query handler will forward + * scheduling queries to the internally linked pads + * instead of discarding them. + * @GST_PAD_FLAG_ACCEPT_INTERSECT: the default accept-caps handler will check + * it the caps intersect the query-caps result instead + * of checking for a subset. This is interesting for + * parsers that can accept incompletely specified caps. + * @GST_PAD_FLAG_ACCEPT_TEMPLATE: the default accept-caps handler will use + * the template pad caps instead of query caps to + * compare with the accept caps. Use this in combination + * with %GST_PAD_FLAG_ACCEPT_INTERSECT. (Since 1.6) + * @GST_PAD_FLAG_LAST: offset to define more flags + * + * Pad state flags + */ +typedef enum { + GST_PAD_FLAG_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), + GST_PAD_FLAG_FLUSHING = (GST_OBJECT_FLAG_LAST << 1), + GST_PAD_FLAG_EOS = (GST_OBJECT_FLAG_LAST << 2), + GST_PAD_FLAG_BLOCKING = (GST_OBJECT_FLAG_LAST << 3), + GST_PAD_FLAG_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 4), + GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 5), + GST_PAD_FLAG_PENDING_EVENTS = (GST_OBJECT_FLAG_LAST << 6), + GST_PAD_FLAG_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 7), + GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 8), + GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 9), + GST_PAD_FLAG_PROXY_SCHEDULING = (GST_OBJECT_FLAG_LAST << 10), + GST_PAD_FLAG_ACCEPT_INTERSECT = (GST_OBJECT_FLAG_LAST << 11), + GST_PAD_FLAG_ACCEPT_TEMPLATE = (GST_OBJECT_FLAG_LAST << 12), + /* padding */ + GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) +} GstPadFlags; + +/** + * GstPad: + * @element_private: private data owned by the parent element + * @padtemplate: padtemplate for this pad + * @direction: the direction of the pad, cannot change after creating + * the pad. + * + * The #GstPad structure. Use the functions to update the variables. + */ +struct _GstPad { + GstObject object; + + /*< public >*/ + gpointer element_private; + + GstPadTemplate *padtemplate; + + GstPadDirection direction; + + /*< private >*/ + /* streaming rec_lock */ + GRecMutex stream_rec_lock; + GstTask *task; + + /* block cond, mutex is from the object */ + GCond block_cond; + GHookList probes; + + GstPadMode mode; + GstPadActivateFunction activatefunc; + gpointer activatedata; + GDestroyNotify activatenotify; + GstPadActivateModeFunction activatemodefunc; + gpointer activatemodedata; + GDestroyNotify activatemodenotify; + + /* pad link */ + GstPad *peer; + GstPadLinkFunction linkfunc; + gpointer linkdata; + GDestroyNotify linknotify; + GstPadUnlinkFunction unlinkfunc; + gpointer unlinkdata; + GDestroyNotify unlinknotify; + + /* data transport functions */ + GstPadChainFunction chainfunc; + gpointer chaindata; + GDestroyNotify chainnotify; + GstPadChainListFunction chainlistfunc; + gpointer chainlistdata; + GDestroyNotify chainlistnotify; + GstPadGetRangeFunction getrangefunc; + gpointer getrangedata; + GDestroyNotify getrangenotify; + GstPadEventFunction eventfunc; + gpointer eventdata; + GDestroyNotify eventnotify; + + /* pad offset */ + gint64 offset; + + /* generic query method */ + GstPadQueryFunction queryfunc; + gpointer querydata; + GDestroyNotify querynotify; + + /* internal links */ + GstPadIterIntLinkFunction iterintlinkfunc; + gpointer iterintlinkdata; + GDestroyNotify iterintlinknotify; + + /* counts number of probes attached. */ + gint num_probes; + gint num_blocked; + + GstPadPrivate *priv; + + union { + gpointer _gst_reserved[GST_PADDING]; + struct { + GstFlowReturn last_flowret; + GstPadEventFullFunction eventfullfunc; + } abi; + } ABI; +}; + +struct _GstPadClass { + GstObjectClass parent_class; + + /* signal callbacks */ + void (*linked) (GstPad *pad, GstPad *peer); + void (*unlinked) (GstPad *pad, GstPad *peer); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + + +/***** helper macros *****/ +/* GstPad */ + +/** + * GST_PAD_NAME: + * @pad: a #GstPad + * + * Get name of the given pad. + * No locking is performed in this function, use gst_pad_get_name() instead. + */ +#define GST_PAD_NAME(pad) (GST_OBJECT_NAME(pad)) +/** + * GST_PAD_PARENT: + * @pad: a #GstPad + * + * Get the @pad parent. + * No locking is performed in this function, use gst_pad_get_parent() instead. + */ +#define GST_PAD_PARENT(pad) (GST_ELEMENT_CAST(GST_OBJECT_PARENT(pad))) +/** + * GST_PAD_ELEMENT_PRIVATE: + * @pad: a #GstPad + * + * Get the private data of @pad, which is usually some pad- or stream-specific + * structure created by the element and set on the pad when creating it. + * No locking is performed in this function. + */ +#define GST_PAD_ELEMENT_PRIVATE(pad) (GST_PAD_CAST(pad)->element_private) +/** + * GST_PAD_PAD_TEMPLATE: + * @pad: a #GstPad + * + * Get the @pad #GstPadTemplate. It describes the possible media types + * a @pad or an element factory can handle. + */ +#define GST_PAD_PAD_TEMPLATE(pad) (GST_PAD_CAST(pad)->padtemplate) +/** + * GST_PAD_DIRECTION: + * @pad: a #GstPad + * + * Get the #GstPadDirection of the given @pad. Accessor macro, use + * gst_pad_get_direction() instead. + */ +#define GST_PAD_DIRECTION(pad) (GST_PAD_CAST(pad)->direction) +/** + * GST_PAD_TASK: + * @pad: a #GstPad + * + * Get the #GstTask of @pad. Accessor macro used by GStreamer. Use the + * gst_pad_start_task(), gst_pad_stop_task() and gst_pad_pause_task() + * functions instead. + */ +#define GST_PAD_TASK(pad) (GST_PAD_CAST(pad)->task) +/** + * GST_PAD_MODE: + * @pad: a #GstPad + * + * Get the #GstPadMode of pad, which will be GST_PAD_MODE_NONE if the pad + * has not been activated yet, and otherwise either GST_PAD_MODE_PUSH or + * GST_PAD_MODE_PULL depending on which mode the pad was activated in. + */ +#define GST_PAD_MODE(pad) (GST_PAD_CAST(pad)->mode) +/** + * GST_PAD_ACTIVATEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadActivateFunction from @pad. + */ +#define GST_PAD_ACTIVATEFUNC(pad) (GST_PAD_CAST(pad)->activatefunc) +/** + * GST_PAD_ACTIVATEMODEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadActivateModeFunction from the given @pad. + */ +#define GST_PAD_ACTIVATEMODEFUNC(pad) (GST_PAD_CAST(pad)->activatemodefunc) +/** + * GST_PAD_CHAINFUNC: + * @pad: a #GstPad + * + * Get the #GstPadChainFunction from the given @pad. + */ +#define GST_PAD_CHAINFUNC(pad) (GST_PAD_CAST(pad)->chainfunc) +/** + * GST_PAD_CHAINLISTFUNC: + * @pad: a #GstPad + * + * Get the #GstPadChainListFunction from the given @pad. + */ +#define GST_PAD_CHAINLISTFUNC(pad) (GST_PAD_CAST(pad)->chainlistfunc) +/** + * GST_PAD_GETRANGEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadGetRangeFunction from the given @pad. + */ +#define GST_PAD_GETRANGEFUNC(pad) (GST_PAD_CAST(pad)->getrangefunc) +/** + * GST_PAD_EVENTFUNC: + * @pad: a #GstPad + * + * Get the #GstPadEventFunction from the given @pad, which + * is the function that handles events on the pad. You can + * use this to set your own event handling function on a pad + * after you create it. If your element derives from a base + * class, use the base class's virtual functions instead. + */ +#define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc) +/** + * GST_PAD_EVENTFULLFUNC: + * @pad: a #GstPad + * + * Get the #GstPadEventFullFunction from the given @pad, which + * is the function that handles events on the pad. You can + * use this to set your own event handling function on a pad + * after you create it. If your element derives from a base + * class, use the base class's virtual functions instead. + * + * Since: 1.8 + */ +#define GST_PAD_EVENTFULLFUNC(pad) (GST_PAD_CAST(pad)->ABI.abi.eventfullfunc) +/** + * GST_PAD_QUERYFUNC: + * @pad: a #GstPad + * + * Get the #GstPadQueryFunction from @pad, which is the function + * that handles queries on the pad. You can use this to set your + * own query handling function on a pad after you create it. If your + * element derives from a base class, use the base class's virtual + * functions instead. + */ +#define GST_PAD_QUERYFUNC(pad) (GST_PAD_CAST(pad)->queryfunc) +/** + * GST_PAD_ITERINTLINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadIterIntLinkFunction from the given @pad. + */ +#define GST_PAD_ITERINTLINKFUNC(pad) (GST_PAD_CAST(pad)->iterintlinkfunc) +/** + * GST_PAD_PEER: + * @pad: a #GstPad + * + * Return the pad's peer member. This member is a pointer to the linked @pad. + * No locking is performed in this function, use gst_pad_get_peer() instead. + */ +#define GST_PAD_PEER(pad) (GST_PAD_CAST(pad)->peer) +/** + * GST_PAD_LINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadLinkFunction for the given @pad. + */ +#define GST_PAD_LINKFUNC(pad) (GST_PAD_CAST(pad)->linkfunc) +/** + * GST_PAD_UNLINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadUnlinkFunction from the given @pad. + */ +#define GST_PAD_UNLINKFUNC(pad) (GST_PAD_CAST(pad)->unlinkfunc) +/** + * GST_PAD_IS_SRC: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is a source pad (i.e. produces data). + */ +#define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC) +/** + * GST_PAD_IS_SINK: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is a sink pad (i.e. consumes data). + */ +#define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK) +/** + * GST_PAD_IS_LINKED: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is linked to another pad. Use gst_pad_is_linked() + * instead. + */ +#define GST_PAD_IS_LINKED(pad) (GST_PAD_PEER(pad) != NULL) +/** + * GST_PAD_IS_ACTIVE: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad has been activated. + */ +#define GST_PAD_IS_ACTIVE(pad) (GST_PAD_MODE(pad) != GST_PAD_MODE_NONE) +/** + * GST_PAD_IS_BLOCKED: + * @pad: a #GstPad + * + * Check if the dataflow on a @pad is blocked. Use gst_pad_is_blocked() instead. + */ +#define GST_PAD_IS_BLOCKED(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED)) +/** + * GST_PAD_IS_BLOCKING: + * @pad: a #GstPad + * + * Check if the @pad is currently blocking on a buffer or event. Use + * gst_pad_is_blocking() instead. + */ +#define GST_PAD_IS_BLOCKING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING)) +/** + * GST_PAD_IS_FLUSHING: + * @pad: a #GstPad + * + * Check if the given @pad is flushing. + */ +#define GST_PAD_IS_FLUSHING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING)) +/** + * GST_PAD_SET_FLUSHING: + * @pad: a #GstPad + * + * Set the given @pad to flushing state, which means it will not accept any + * more events, queries or buffers, and return GST_FLOW_FLUSHING if any buffers + * are pushed on it. This usually happens when the pad is shut down or when + * a flushing seek happens. This is used inside GStreamer when flush start/stop + * events pass through pads, or when an element state is changed and pads are + * activated or deactivated. + */ +#define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING)) +/** + * GST_PAD_UNSET_FLUSHING: + * @pad: a #GstPad + * + * Unset the flushing flag. + */ +#define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING)) +/** + * GST_PAD_IS_EOS: + * @pad: a #GstPad + * + * Check if the @pad is in EOS state. + */ +#define GST_PAD_IS_EOS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) +/** + * GST_PAD_NEEDS_RECONFIGURE: + * @pad: a #GstPad + * + * Check if the @pad should be reconfigured/renegotiated. + * The flag has to be unset manually after reconfiguration happened. + * Use gst_pad_needs_reconfigure() or gst_pad_check_reconfigure() instead. + */ +#define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE)) +/** + * GST_PAD_HAS_PENDING_EVENTS: + * @pad: a #GstPad + * + * Check if the given @pad has pending events. This is used internally by + * GStreamer. + */ +#define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS)) +/** + * GST_PAD_IS_FIXED_CAPS: + * @pad: a #GstPad + * + * Check if the given @pad is using fixed caps, which means that + * once the caps are set on the @pad, the caps query function will + * only return those caps. See gst_pad_use_fixed_caps(). + */ +#define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS)) +/** + * GST_PAD_NEEDS_PARENT: + * @pad: a #GstPad + * + * Check if there is a parent object before calling into the @pad callbacks. + * This is used internally by GStreamer. + */ +#define GST_PAD_NEEDS_PARENT(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_PARENT)) +/** + * GST_PAD_IS_PROXY_CAPS: + * @pad: a #GstPad + * + * Check if the given @pad is set to proxy caps. This means that the default + * event and query handler will forward all events and queries to the + * internally linked @pads instead of discarding them. + */ +#define GST_PAD_IS_PROXY_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_CAPS)) +/** + * GST_PAD_SET_PROXY_CAPS: + * @pad: a #GstPad + * + * Set @pad to proxy caps, so that all caps-related events and queries are + * proxied down- or upstream to the other side of the element automatically. + * Set this if the element always outputs data in the exact same format as it + * receives as input. This is just for convenience to avoid implementing some + * standard event and query handling code in an element. + */ +#define GST_PAD_SET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_CAPS)) +/** + * GST_PAD_UNSET_PROXY_CAPS: + * @pad: a #GstPad + * + * Unset proxy caps flag. + */ +#define GST_PAD_UNSET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_CAPS)) +/** + * GST_PAD_IS_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Check if the given @pad is set as proxy allocation which means + * that the default query handler will forward allocation queries to the + * internally linked @pads instead of discarding them. + */ +#define GST_PAD_IS_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) +/** + * GST_PAD_SET_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Set @pad to proxy allocation queries, which means that the default query + * handler will forward allocation queries to the internally linked @pads + * instead of discarding them. + * Set this if the element always outputs data in the exact same format as it + * receives as input. This is just for convenience to avoid implementing some + * standard query handling code in an element. + */ +#define GST_PAD_SET_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) +/** + * GST_PAD_UNSET_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Unset proxy allocation flag. + */ +#define GST_PAD_UNSET_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) +/** + * GST_PAD_IS_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Check if the given @pad is set to proxy scheduling queries, which means that + * the default query handler will forward scheduling queries to the internally + * linked @pads instead of discarding them. + */ +#define GST_PAD_IS_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) +/** + * GST_PAD_SET_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Set @pad to proxy scheduling queries, which means that the default query + * handler will forward scheduling queries to the internally linked @pads + * instead of discarding them. You will usually want to handle scheduling + * queries explicitly if your element supports multiple scheduling modes. + */ +#define GST_PAD_SET_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) +/** + * GST_PAD_UNSET_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Unset proxy scheduling flag. + */ +#define GST_PAD_UNSET_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) +/** + * GST_PAD_IS_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Check if the pad's accept intersect flag is set. The default accept-caps + * handler will check if the caps intersect the query-caps result instead of + * checking for a subset. This is interesting for parser elements that can + * accept incompletely specified caps. + */ +#define GST_PAD_IS_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) +/** + * GST_PAD_SET_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Set @pad to by default accept caps by intersecting the result instead of + * checking for a subset. This is interesting for parser elements that can + * accept incompletely specified caps. + */ +#define GST_PAD_SET_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) +/** + * GST_PAD_UNSET_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Unset accept intersect flag. + */ +#define GST_PAD_UNSET_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) +/** + * GST_PAD_IS_ACCEPT_TEMPLATE: + * @pad: a #GstPad + * + * Check if the pad's accept caps operation will use the pad template caps. + * The default accept-caps will do a query caps to get the caps, which might + * be querying downstream causing unnecessary overhead. It is recommended to + * implement a proper accept-caps query handler or to use this flag to prevent + * recursive accept-caps handling. + * + * Since: 1.6 + */ +#define GST_PAD_IS_ACCEPT_TEMPLATE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE)) +/** + * GST_PAD_SET_ACCEPT_TEMPLATE: + * @pad: a #GstPad + * + * Set @pad to by default use the pad template caps to compare with + * the accept caps instead of using a caps query result. + * + * Since: 1.6 + */ +#define GST_PAD_SET_ACCEPT_TEMPLATE(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE)) +/** + * GST_PAD_UNSET_ACCEPT_TEMPLATE: + * @pad: a #GstPad + * + * Unset accept template flag. + * + * Since: 1.6 + */ +#define GST_PAD_UNSET_ACCEPT_TEMPLATE(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_ACCEPT_TEMPLATE)) +/** + * GST_PAD_GET_STREAM_LOCK: + * @pad: a #GstPad + * + * Get the stream lock of @pad. The stream lock is protecting the + * resources used in the data processing functions of @pad. Accessor + * macro, use GST_PAD_STREAM_LOCK() and GST_PAD_STREAM_UNLOCK() instead + * to take/release the pad's stream lock. + */ +#define GST_PAD_GET_STREAM_LOCK(pad) (&(GST_PAD_CAST(pad)->stream_rec_lock)) +/** + * GST_PAD_STREAM_LOCK: + * @pad: a #GstPad + * + * Take the pad's stream lock. The stream lock is recursive and will be taken + * when buffers or serialized downstream events are pushed on a pad. + */ +#define GST_PAD_STREAM_LOCK(pad) g_rec_mutex_lock(GST_PAD_GET_STREAM_LOCK(pad)) +/** + * GST_PAD_STREAM_TRYLOCK: + * @pad: a #GstPad + * + * Try to take the pad's stream lock, and return %TRUE if the lock could be + * taken, and otherwise %FALSE. + */ +#define GST_PAD_STREAM_TRYLOCK(pad) g_rec_mutex_trylock(GST_PAD_GET_STREAM_LOCK(pad)) +/** + * GST_PAD_STREAM_UNLOCK: + * @pad: a #GstPad + * + * Release the pad's stream lock. + */ +#define GST_PAD_STREAM_UNLOCK(pad) g_rec_mutex_unlock(GST_PAD_GET_STREAM_LOCK(pad)) +/** + * GST_PAD_LAST_FLOW_RETURN: + * @pad: a #GstPad + * + * Gets the last flow return on this pad + * + * Since: 1.4 + */ +#define GST_PAD_LAST_FLOW_RETURN(pad) (GST_PAD_CAST(pad)->ABI.abi.last_flowret) + +#define GST_PAD_BLOCK_GET_COND(pad) (&GST_PAD_CAST(pad)->block_cond) +#define GST_PAD_BLOCK_WAIT(pad) (g_cond_wait(GST_PAD_BLOCK_GET_COND (pad), GST_OBJECT_GET_LOCK (pad))) +#define GST_PAD_BLOCK_SIGNAL(pad) (g_cond_signal(GST_PAD_BLOCK_GET_COND (pad))) +#define GST_PAD_BLOCK_BROADCAST(pad) (g_cond_broadcast(GST_PAD_BLOCK_GET_COND (pad))) + +GST_API +GType gst_pad_get_type (void); + +/* creating pads */ + +GST_API +GstPad* gst_pad_new (const gchar *name, GstPadDirection direction); + +GST_API +GstPad* gst_pad_new_from_template (GstPadTemplate *templ, const gchar *name); + +GST_API +GstPad* gst_pad_new_from_static_template (GstStaticPadTemplate *templ, const gchar *name); + + +/** + * gst_pad_get_name: + * @pad: the pad to get the name from + * + * Get a copy of the name of the pad. g_free() after usage. + * + * MT safe. + */ +#define gst_pad_get_name(pad) gst_object_get_name (GST_OBJECT_CAST (pad)) +/** + * gst_pad_get_parent: + * @pad: the pad to get the parent of + * + * Get the parent of @pad. This function increases the refcount + * of the parent object so you should gst_object_unref() it after usage. + * Can return %NULL if the pad did not have a parent. + * + * MT safe. + * + * Returns: (nullable): the parent + */ +#define gst_pad_get_parent(pad) gst_object_get_parent (GST_OBJECT_CAST (pad)) + +GST_API +GstPadDirection gst_pad_get_direction (GstPad *pad); + +GST_API +gboolean gst_pad_set_active (GstPad *pad, gboolean active); + +GST_API +gboolean gst_pad_is_active (GstPad *pad); + +GST_API +gboolean gst_pad_activate_mode (GstPad *pad, GstPadMode mode, + gboolean active); +GST_API +gulong gst_pad_add_probe (GstPad *pad, + GstPadProbeType mask, + GstPadProbeCallback callback, + gpointer user_data, + GDestroyNotify destroy_data); +GST_API +void gst_pad_remove_probe (GstPad *pad, gulong id); + +GST_API +gboolean gst_pad_is_blocked (GstPad *pad); + +GST_API +gboolean gst_pad_is_blocking (GstPad *pad); + +GST_API +void gst_pad_mark_reconfigure (GstPad *pad); + +GST_API +gboolean gst_pad_needs_reconfigure (GstPad *pad); + +GST_API +gboolean gst_pad_check_reconfigure (GstPad *pad); + +GST_API +void gst_pad_set_element_private (GstPad *pad, gpointer priv); + +GST_API +gpointer gst_pad_get_element_private (GstPad *pad); + +GST_API +GstPadTemplate* gst_pad_get_pad_template (GstPad *pad); + +GST_API +GstFlowReturn gst_pad_store_sticky_event (GstPad *pad, GstEvent *event); + +GST_API +GstEvent* gst_pad_get_sticky_event (GstPad *pad, GstEventType event_type, + guint idx); + +GST_API +void gst_pad_sticky_events_foreach (GstPad *pad, GstPadStickyEventsForeachFunction foreach_func, gpointer user_data); + +/* data passing setup functions */ + +GST_API +void gst_pad_set_activate_function_full (GstPad *pad, + GstPadActivateFunction activate, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_activatemode_function_full (GstPad *pad, + GstPadActivateModeFunction activatemode, + gpointer user_data, + GDestroyNotify notify); +/* data passing functions */ + +GST_API +void gst_pad_set_chain_function_full (GstPad *pad, + GstPadChainFunction chain, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_chain_list_function_full (GstPad *pad, + GstPadChainListFunction chainlist, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_getrange_function_full (GstPad *pad, + GstPadGetRangeFunction get, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_event_function_full (GstPad *pad, + GstPadEventFunction event, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_event_full_function_full (GstPad *pad, + GstPadEventFullFunction event, + gpointer user_data, + GDestroyNotify notify); + +#define gst_pad_set_activate_function(p,f) gst_pad_set_activate_function_full((p),(f),NULL,NULL) +#define gst_pad_set_activatemode_function(p,f) gst_pad_set_activatemode_function_full((p),(f),NULL,NULL) +#define gst_pad_set_chain_function(p,f) gst_pad_set_chain_function_full((p),(f),NULL,NULL) +#define gst_pad_set_chain_list_function(p,f) gst_pad_set_chain_list_function_full((p),(f),NULL,NULL) +#define gst_pad_set_getrange_function(p,f) gst_pad_set_getrange_function_full((p),(f),NULL,NULL) +#define gst_pad_set_event_function(p,f) gst_pad_set_event_function_full((p),(f),NULL,NULL) +#define gst_pad_set_event_full_function(p,f) gst_pad_set_event_full_function_full((p),(f),NULL,NULL) + +/* pad links */ + +GST_API +void gst_pad_set_link_function_full (GstPad *pad, + GstPadLinkFunction link, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_pad_set_unlink_function_full (GstPad *pad, + GstPadUnlinkFunction unlink, + gpointer user_data, + GDestroyNotify notify); + +#define gst_pad_set_link_function(p,f) gst_pad_set_link_function_full((p),(f),NULL,NULL) +#define gst_pad_set_unlink_function(p,f) gst_pad_set_unlink_function_full((p),(f),NULL,NULL) + +GST_API +gboolean gst_pad_can_link (GstPad *srcpad, GstPad *sinkpad); + +GST_API +GstPadLinkReturn gst_pad_link (GstPad *srcpad, GstPad *sinkpad); + +GST_API +GstPadLinkReturn gst_pad_link_full (GstPad *srcpad, GstPad *sinkpad, GstPadLinkCheck flags); + +GST_API +gboolean gst_pad_unlink (GstPad *srcpad, GstPad *sinkpad); + +GST_API +gboolean gst_pad_is_linked (GstPad *pad); + +GST_API +GstPad* gst_pad_get_peer (GstPad *pad); + +GST_API +GstCaps* gst_pad_get_pad_template_caps (GstPad *pad); + +/* capsnego function for linked/unlinked pads */ + +GST_API +GstCaps * gst_pad_get_current_caps (GstPad * pad); + +GST_API +gboolean gst_pad_has_current_caps (GstPad * pad); + +/* capsnego for linked pads */ + +GST_API +GstCaps * gst_pad_get_allowed_caps (GstPad * pad); + +/* pad offsets */ + +GST_API +gint64 gst_pad_get_offset (GstPad *pad); + +GST_API +void gst_pad_set_offset (GstPad *pad, gint64 offset); + +/* data passing functions to peer */ + +GST_API +GstFlowReturn gst_pad_push (GstPad *pad, GstBuffer *buffer); + +GST_API +GstFlowReturn gst_pad_push_list (GstPad *pad, GstBufferList *list); + +GST_API +GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size, + GstBuffer **buffer); +GST_API +gboolean gst_pad_push_event (GstPad *pad, GstEvent *event); + +GST_API +gboolean gst_pad_event_default (GstPad *pad, GstObject *parent, + GstEvent *event); +GST_API +GstFlowReturn gst_pad_get_last_flow_return (GstPad *pad); + +/* data passing functions on pad */ + +GST_API +GstFlowReturn gst_pad_chain (GstPad *pad, GstBuffer *buffer); + +GST_API +GstFlowReturn gst_pad_chain_list (GstPad *pad, GstBufferList *list); + +GST_API +GstFlowReturn gst_pad_get_range (GstPad *pad, guint64 offset, guint size, + GstBuffer **buffer); +GST_API +gboolean gst_pad_send_event (GstPad *pad, GstEvent *event); + +/* pad tasks */ + +GST_API +gboolean gst_pad_start_task (GstPad *pad, GstTaskFunction func, + gpointer user_data, GDestroyNotify notify); +GST_API +gboolean gst_pad_pause_task (GstPad *pad); + +GST_API +gboolean gst_pad_stop_task (GstPad *pad); + +GST_API +GstTaskState gst_pad_get_task_state (GstPad *pad); + +/* internal links */ + +GST_API +void gst_pad_set_iterate_internal_links_function_full (GstPad * pad, + GstPadIterIntLinkFunction iterintlink, + gpointer user_data, + GDestroyNotify notify); + +GST_API +GstIterator * gst_pad_iterate_internal_links (GstPad * pad); + +GST_API +GstIterator * gst_pad_iterate_internal_links_default (GstPad * pad, GstObject *parent); + +#define gst_pad_set_iterate_internal_links_function(p,f) gst_pad_set_iterate_internal_links_function_full((p),(f),NULL,NULL) + +/* generic query function */ + +GST_API +gboolean gst_pad_query (GstPad *pad, GstQuery *query); + +GST_API +gboolean gst_pad_peer_query (GstPad *pad, GstQuery *query); + +GST_API +void gst_pad_set_query_function_full (GstPad *pad, GstPadQueryFunction query, + gpointer user_data, + GDestroyNotify notify); +GST_API +gboolean gst_pad_query_default (GstPad *pad, GstObject *parent, + GstQuery *query); + +#define gst_pad_set_query_function(p,f) gst_pad_set_query_function_full((p),(f),NULL,NULL) + +/* misc helper functions */ + +GST_API +gboolean gst_pad_forward (GstPad *pad, GstPadForwardFunction forward, + gpointer user_data); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPad, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PAD_H__ */ diff --git a/gst/gstpadtemplate.c b/gst/gstpadtemplate.c new file mode 100644 index 0000000..02a9132 --- /dev/null +++ b/gst/gstpadtemplate.c @@ -0,0 +1,553 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpadtemplate.c: Templates for pad creation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstpadtemplate + * @title: GstPadTemplate + * @short_description: Describe the media type of a pad. + * @see_also: #GstPad, #GstElementFactory + * + * Padtemplates describe the possible media types a pad or an elementfactory can + * handle. This allows for both inspection of handled types before loading the + * element plugin as well as identifying pads on elements that are not yet + * created (request or sometimes pads). + * + * Pad and PadTemplates have #GstCaps attached to it to describe the media type + * they are capable of dealing with. gst_pad_template_get_caps() or + * GST_PAD_TEMPLATE_CAPS() are used to get the caps of a padtemplate. It's not + * possible to modify the caps of a padtemplate after creation. + * + * PadTemplates have a #GstPadPresence property which identifies the lifetime + * of the pad and that can be retrieved with GST_PAD_TEMPLATE_PRESENCE(). Also + * the direction of the pad can be retrieved from the #GstPadTemplate with + * GST_PAD_TEMPLATE_DIRECTION(). + * + * The GST_PAD_TEMPLATE_NAME_TEMPLATE () is important for GST_PAD_REQUEST pads + * because it has to be used as the name in the gst_element_get_request_pad() + * call to instantiate a pad from this template. + * + * Padtemplates can be created with gst_pad_template_new() or with + * gst_static_pad_template_get (), which creates a #GstPadTemplate from a + * #GstStaticPadTemplate that can be filled with the + * convenient GST_STATIC_PAD_TEMPLATE() macro. + * + * A padtemplate can be used to create a pad (see gst_pad_new_from_template() + * or gst_pad_new_from_static_template ()) or to add to an element class + * (see gst_element_class_add_static_pad_template ()). + * + * The following code example shows the code to create a pad from a padtemplate. + * |[ + * GstStaticPadTemplate my_template = + * GST_STATIC_PAD_TEMPLATE ( + * "sink", // the name of the pad + * GST_PAD_SINK, // the direction of the pad + * GST_PAD_ALWAYS, // when this pad will be present + * GST_STATIC_CAPS ( // the capabilities of the padtemplate + * "audio/x-raw, " + * "channels = (int) [ 1, 6 ]" + * ) + * ); + * void + * my_method (void) + * { + * GstPad *pad; + * pad = gst_pad_new_from_static_template (&my_template, "sink"); + * ... + * } + * ]| + * + * The following example shows you how to add the padtemplate to an + * element class, this is usually done in the class_init of the class: + * |[ + * static void + * my_element_class_init (GstMyElementClass *klass) + * { + * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + * + * gst_element_class_add_static_pad_template (gstelement_class, &my_template); + * } + * ]| + */ + +#include "gst_private.h" + +#include "gstpad.h" +#include "gstpadtemplate.h" +#include "gstenumtypes.h" +#include "gstutils.h" +#include "gstinfo.h" +#include "gsterror.h" +#include "gstvalue.h" + +#define GST_CAT_DEFAULT GST_CAT_PADS + +enum +{ + PROP_NAME_TEMPLATE = 1, + PROP_DIRECTION, + PROP_PRESENCE, + PROP_CAPS, + PROP_GTYPE, +}; + +enum +{ + TEMPL_PAD_CREATED, + /* FILL ME */ + LAST_SIGNAL +}; + +static guint gst_pad_template_signals[LAST_SIGNAL] = { 0 }; + +static void gst_pad_template_dispose (GObject * object); +static void gst_pad_template_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_pad_template_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +#define gst_pad_template_parent_class parent_class +G_DEFINE_TYPE (GstPadTemplate, gst_pad_template, GST_TYPE_OBJECT); + +static void +gst_pad_template_class_init (GstPadTemplateClass * klass) +{ + GObjectClass *gobject_class; + GstObjectClass *gstobject_class; + + gobject_class = (GObjectClass *) klass; + gstobject_class = (GstObjectClass *) klass; + + /** + * GstPadTemplate::pad-created: + * @pad_template: the object which received the signal. + * @pad: the pad that was created. + * + * This signal is fired when an element creates a pad from this template. + */ + gst_pad_template_signals[TEMPL_PAD_CREATED] = + g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD); + + gobject_class->dispose = gst_pad_template_dispose; + + gobject_class->get_property = gst_pad_template_get_property; + gobject_class->set_property = gst_pad_template_set_property; + + /** + * GstPadTemplate:name-template: + * + * The name template of the pad template. + */ + g_object_class_install_property (gobject_class, PROP_NAME_TEMPLATE, + g_param_spec_string ("name-template", "Name template", + "The name template of the pad template", NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstPadTemplate:direction: + * + * The direction of the pad described by the pad template. + */ + g_object_class_install_property (gobject_class, PROP_DIRECTION, + g_param_spec_enum ("direction", "Direction", + "The direction of the pad described by the pad template", + GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstPadTemplate:presence: + * + * When the pad described by the pad template will become available. + */ + g_object_class_install_property (gobject_class, PROP_PRESENCE, + g_param_spec_enum ("presence", "Presence", + "When the pad described by the pad template will become available", + GST_TYPE_PAD_PRESENCE, GST_PAD_ALWAYS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstPadTemplate:caps: + * + * The capabilities of the pad described by the pad template. + */ + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Caps", + "The capabilities of the pad described by the pad template", + GST_TYPE_CAPS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstPadTemplate:gtype: + * + * The type of the pad described by the pad template. + * + * Since: 1.14 + */ + g_object_class_install_property (gobject_class, PROP_GTYPE, + g_param_spec_gtype ("gtype", "GType", + "The GType of the pad described by the pad template", + G_TYPE_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + gstobject_class->path_string_separator = "*"; +} + +static void +gst_pad_template_init (GstPadTemplate * templ) +{ + /* GstPadTemplate objects are usually leaked */ + GST_OBJECT_FLAG_SET (templ, GST_OBJECT_FLAG_MAY_BE_LEAKED); + GST_PAD_TEMPLATE_GTYPE (templ) = G_TYPE_NONE; +} + +static void +gst_pad_template_dispose (GObject * object) +{ + GstPadTemplate *templ = GST_PAD_TEMPLATE (object); + + g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ)); + if (GST_PAD_TEMPLATE_CAPS (templ)) { + gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ)); + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/* ALWAYS padtemplates cannot have conversion specifications (like src_%d), + * since it doesn't make sense. + * SOMETIMES padtemplates can do whatever they want, they are provided by the + * element. + * REQUEST padtemplates can have multiple specifiers in case of %d and %u, like + * src_%u_%u, but %s only can be used once in the template. + */ +static gboolean +name_is_valid (const gchar * name, GstPadPresence presence) +{ + const gchar *str, *underscore = NULL; + gboolean has_s = FALSE; + + if (presence == GST_PAD_ALWAYS) { + if (strchr (name, '%')) { + g_warning ("invalid name template %s: conversion specifications are not" + " allowed for GST_PAD_ALWAYS padtemplates", name); + return FALSE; + } + } else if (presence == GST_PAD_REQUEST) { + str = strchr (name, '%'); + + while (str) { + if (*(str + 1) != 's' && *(str + 1) != 'd' && *(str + 1) != 'u') { + g_warning + ("invalid name template %s: conversion specification must be of" + " type '%%d', '%%u' or '%%s' for GST_PAD_REQUEST padtemplate", + name); + return FALSE; + } + + if (*(str + 1) == 's' && (*(str + 2) != '\0' || has_s)) { + g_warning + ("invalid name template %s: conversion specification of type '%%s'" + "only can be used once in the GST_PAD_REQUEST padtemplate at the " + "very end and not allowed any other characters with '%%s'", name); + return FALSE; + } + + if (*(str + 1) == 's') { + has_s = TRUE; + } + + underscore = strchr (str, '_'); + str = strchr (str + 1, '%'); + + if (str && (!underscore || (underscore && str < underscore))) { + g_warning + ("invalid name template %s: each of conversion specifications " + "must be separated by an underscore", name); + return FALSE; + } + } + } + + return TRUE; +} + +G_DEFINE_POINTER_TYPE (GstStaticPadTemplate, gst_static_pad_template); + +/** + * gst_static_pad_template_get: + * @pad_template: the static pad template + * + * Converts a #GstStaticPadTemplate into a #GstPadTemplate. + * + * Returns: (transfer floating) (nullable): a new #GstPadTemplate. + */ +/* FIXME0.11: rename to gst_pad_template_new_from_static_pad_template() */ +GstPadTemplate * +gst_static_pad_template_get (GstStaticPadTemplate * pad_template) +{ + GstPadTemplate *new; + GstCaps *caps; + + if (!name_is_valid (pad_template->name_template, pad_template->presence)) + return NULL; + + caps = gst_static_caps_get (&pad_template->static_caps); + + new = g_object_new (gst_pad_template_get_type (), + "name", pad_template->name_template, + "name-template", pad_template->name_template, + "direction", pad_template->direction, + "presence", pad_template->presence, "caps", caps, NULL); + + gst_caps_unref (caps); + + return new; +} + +/** + * gst_pad_template_new_from_static_pad_template_with_gtype: + * @pad_template: the static pad template + * @pad_type: The #GType of the pad to create + * + * Converts a #GstStaticPadTemplate into a #GstPadTemplate with a type. + * + * Returns: (transfer floating): a new #GstPadTemplate. + * + * Since: 1.14 + */ +GstPadTemplate * +gst_pad_template_new_from_static_pad_template_with_gtype (GstStaticPadTemplate * + pad_template, GType pad_type) +{ + GstPadTemplate *new; + GstCaps *caps; + + g_return_val_if_fail (g_type_is_a (pad_type, GST_TYPE_PAD), NULL); + + if (!name_is_valid (pad_template->name_template, pad_template->presence)) + return NULL; + + caps = gst_static_caps_get (&pad_template->static_caps); + + new = g_object_new (gst_pad_template_get_type (), + "name", pad_template->name_template, + "name-template", pad_template->name_template, + "direction", pad_template->direction, + "presence", pad_template->presence, "caps", caps, "gtype", pad_type, + NULL); + + gst_caps_unref (caps); + + return new; +} + +/** + * gst_pad_template_new: + * @name_template: the name template. + * @direction: the #GstPadDirection of the template. + * @presence: the #GstPadPresence of the pad. + * @caps: (transfer none): a #GstCaps set for the template. + * + * Creates a new pad template with a name according to the given template + * and with the given arguments. + * + * Returns: (transfer floating) (nullable): a new #GstPadTemplate. + */ +GstPadTemplate * +gst_pad_template_new (const gchar * name_template, + GstPadDirection direction, GstPadPresence presence, GstCaps * caps) +{ + GstPadTemplate *new; + + g_return_val_if_fail (name_template != NULL, NULL); + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (direction == GST_PAD_SRC + || direction == GST_PAD_SINK, NULL); + g_return_val_if_fail (presence == GST_PAD_ALWAYS + || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL); + + if (!name_is_valid (name_template, presence)) { + return NULL; + } + + new = g_object_new (gst_pad_template_get_type (), + "name", name_template, "name-template", name_template, + "direction", direction, "presence", presence, "caps", caps, NULL); + + return new; +} + +/** + * gst_pad_template_new_with_gtype: + * @name_template: the name template. + * @direction: the #GstPadDirection of the template. + * @presence: the #GstPadPresence of the pad. + * @caps: (transfer none): a #GstCaps set for the template. + * @pad_type: The #GType of the pad to create + * + * Creates a new pad template with a name according to the given template + * and with the given arguments. + * + * Returns: (transfer floating): a new #GstPadTemplate. + * + * Since: 1.14 + */ +GstPadTemplate * +gst_pad_template_new_with_gtype (const gchar * name_template, + GstPadDirection direction, GstPadPresence presence, GstCaps * caps, + GType pad_type) +{ + GstPadTemplate *new; + + g_return_val_if_fail (name_template != NULL, NULL); + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (direction == GST_PAD_SRC + || direction == GST_PAD_SINK, NULL); + g_return_val_if_fail (presence == GST_PAD_ALWAYS + || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL); + g_return_val_if_fail (g_type_is_a (pad_type, GST_TYPE_PAD), NULL); + + if (!name_is_valid (name_template, presence)) { + return NULL; + } + + new = g_object_new (gst_pad_template_get_type (), + "name", name_template, "name-template", name_template, + "direction", direction, "presence", presence, "caps", caps, + "gtype", pad_type, NULL); + + return new; +} + +/** + * gst_static_pad_template_get_caps: + * @templ: a #GstStaticPadTemplate to get capabilities of. + * + * Gets the capabilities of the static pad template. + * + * Returns: (transfer full): the #GstCaps of the static pad template. + * Unref after usage. Since the core holds an additional + * ref to the returned caps, use gst_caps_make_writable() + * on the returned caps to modify it. + */ +GstCaps * +gst_static_pad_template_get_caps (GstStaticPadTemplate * templ) +{ + g_return_val_if_fail (templ, NULL); + + return gst_static_caps_get (&templ->static_caps); +} + +/** + * gst_pad_template_get_caps: + * @templ: a #GstPadTemplate to get capabilities of. + * + * Gets the capabilities of the pad template. + * + * Returns: (transfer full): the #GstCaps of the pad template. + * Unref after usage. + */ +GstCaps * +gst_pad_template_get_caps (GstPadTemplate * templ) +{ + GstCaps *caps; + g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); + + caps = GST_PAD_TEMPLATE_CAPS (templ); + + return (caps ? gst_caps_ref (caps) : NULL); +} + +/** + * gst_pad_template_pad_created: + * @templ: a #GstPadTemplate that has been created + * @pad: the #GstPad that created it + * + * Emit the pad-created signal for this template when created by this pad. + */ +void +gst_pad_template_pad_created (GstPadTemplate * templ, GstPad * pad) +{ + g_signal_emit (templ, gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad); +} + +static void +gst_pad_template_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + /* these properties are all construct-only */ + switch (prop_id) { + case PROP_NAME_TEMPLATE: + GST_PAD_TEMPLATE_NAME_TEMPLATE (object) = g_value_dup_string (value); + break; + case PROP_DIRECTION: + GST_PAD_TEMPLATE_DIRECTION (object) = + (GstPadDirection) g_value_get_enum (value); + break; + case PROP_PRESENCE: + GST_PAD_TEMPLATE_PRESENCE (object) = + (GstPadPresence) g_value_get_enum (value); + break; + case PROP_CAPS: + GST_PAD_TEMPLATE_CAPS (object) = g_value_dup_boxed (value); + if (GST_PAD_TEMPLATE_CAPS (object) != NULL) { + /* GstPadTemplate are usually leaked so are their caps */ + GST_MINI_OBJECT_FLAG_SET (GST_PAD_TEMPLATE_CAPS (object), + GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); + } + break; + case PROP_GTYPE: + GST_PAD_TEMPLATE_GTYPE (object) = g_value_get_gtype (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_pad_template_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + /* these properties are all construct-only */ + switch (prop_id) { + case PROP_NAME_TEMPLATE: + g_value_set_string (value, GST_PAD_TEMPLATE_NAME_TEMPLATE (object)); + break; + case PROP_DIRECTION: + g_value_set_enum (value, GST_PAD_TEMPLATE_DIRECTION (object)); + break; + case PROP_PRESENCE: + g_value_set_enum (value, GST_PAD_TEMPLATE_PRESENCE (object)); + break; + case PROP_CAPS: + g_value_set_boxed (value, GST_PAD_TEMPLATE_CAPS (object)); + break; + case PROP_GTYPE: + g_value_set_gtype (value, GST_PAD_TEMPLATE_GTYPE (object)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/gstpadtemplate.h b/gst/gstpadtemplate.h new file mode 100644 index 0000000..e3d0bc5 --- /dev/null +++ b/gst/gstpadtemplate.h @@ -0,0 +1,232 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpadtemplate.h: Header for GstPadTemplate 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_PAD_TEMPLATE_H__ +#define __GST_PAD_TEMPLATE_H__ + +#include + +typedef struct _GstPadTemplate GstPadTemplate; +typedef struct _GstPadTemplateClass GstPadTemplateClass; +typedef struct _GstStaticPadTemplate GstStaticPadTemplate; + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STATIC_PAD_TEMPLATE (gst_static_pad_template_get_type ()) + +#define GST_TYPE_PAD_TEMPLATE (gst_pad_template_get_type ()) +#define GST_PAD_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD_TEMPLATE,GstPadTemplate)) +#define GST_PAD_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD_TEMPLATE,GstPadTemplateClass)) +#define GST_IS_PAD_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PAD_TEMPLATE)) +#define GST_IS_PAD_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PAD_TEMPLATE)) + +/** + * GstPadPresence: + * @GST_PAD_ALWAYS: the pad is always available + * @GST_PAD_SOMETIMES: the pad will become available depending on the media stream + * @GST_PAD_REQUEST: the pad is only available on request with + * gst_element_request_pad(). + * + * Indicates when this pad will become available. + */ +typedef enum { + GST_PAD_ALWAYS, + GST_PAD_SOMETIMES, + GST_PAD_REQUEST +} GstPadPresence; + +/** + * GST_PAD_TEMPLATE_NAME_TEMPLATE: + * @templ: the template to query + * + * Get the nametemplate of the padtemplate. + */ +#define GST_PAD_TEMPLATE_NAME_TEMPLATE(templ) (((GstPadTemplate *)(templ))->name_template) + +/** + * GST_PAD_TEMPLATE_DIRECTION: + * @templ: the template to query + * + * Get the #GstPadDirection of the padtemplate. + */ +#define GST_PAD_TEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction) + +/** + * GST_PAD_TEMPLATE_PRESENCE: + * @templ: the template to query + * + * Get the #GstPadPresence of the padtemplate. + */ +#define GST_PAD_TEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence) + +/** + * GST_PAD_TEMPLATE_CAPS: + * @templ: the template to query + * + * Get a handle to the padtemplate #GstCaps + */ +#define GST_PAD_TEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps) + +/** + * GST_PAD_TEMPLATE_GTYPE: + * @templ: the template to query + * + * Get the #GType of the padtemplate + * + * Since: 1.14 + */ +#define GST_PAD_TEMPLATE_GTYPE(templ) (((GstPadTemplate *)(templ))->ABI.abi.gtype) + +/** + * GstPadTemplateFlags: + * @GST_PAD_TEMPLATE_FLAG_LAST: first flag that can be used by subclasses. + * + * Flags for the padtemplate + */ +typedef enum { + /* padding */ + GST_PAD_TEMPLATE_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 4) +} GstPadTemplateFlags; + +/** + * GST_PAD_TEMPLATE_IS_FIXED: + * @templ: the template to query + * + * Check if the properties of the padtemplate are fixed + */ +#define GST_PAD_TEMPLATE_IS_FIXED(templ) (GST_OBJECT_FLAG_IS_SET(templ, GST_PAD_TEMPLATE_FIXED)) + +/** + * GstPadTemplate: + * + * The padtemplate object. + */ +struct _GstPadTemplate { + GstObject object; + + gchar *name_template; + GstPadDirection direction; + GstPadPresence presence; + GstCaps *caps; + + /*< private >*/ + union { + gpointer _gst_reserved[GST_PADDING]; + struct { + GType gtype; + } abi; + } ABI; +}; + +struct _GstPadTemplateClass { + GstObjectClass parent_class; + + /* signal callbacks */ + void (*pad_created) (GstPadTemplate *templ, GstPad *pad); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstStaticPadTemplate: + * @name_template: the name of the template + * @direction: the direction of the template + * @presence: the presence of the template + * @static_caps: the caps of the template. + * + * Structure describing the #GstStaticPadTemplate. + */ +struct _GstStaticPadTemplate { + const gchar *name_template; + GstPadDirection direction; + GstPadPresence presence; + GstStaticCaps static_caps; +}; + +/** + * GST_STATIC_PAD_TEMPLATE: + * @padname: the name template of the pad + * @dir: the GstPadDirection of the pad + * @pres: the GstPadPresence of the pad + * @caps: the GstStaticCaps of the pad + * + * Convenience macro to fill the values of a GstStaticPadTemplate + * structure. + */ +#define GST_STATIC_PAD_TEMPLATE(padname, dir, pres, caps) \ +{ \ + /* name_template */ padname, \ + /* direction */ dir, \ + /* presence */ pres, \ + /* caps */ caps \ +} + +/* templates and factories */ + +GST_API +GType gst_pad_template_get_type (void); + +GST_API +GType gst_static_pad_template_get_type (void); + +GST_API +GstPadTemplate* gst_pad_template_new (const gchar *name_template, + GstPadDirection direction, GstPadPresence presence, + GstCaps *caps) G_GNUC_MALLOC; +GST_API +GstPadTemplate* gst_pad_template_new_with_gtype (const gchar *name_template, + GstPadDirection direction, GstPadPresence presence, + GstCaps *caps, GType pad_type) G_GNUC_MALLOC; +GST_API +GstPadTemplate * gst_static_pad_template_get (GstStaticPadTemplate *pad_template); + +GST_API +GstPadTemplate * gst_pad_template_new_from_static_pad_template_with_gtype ( + GstStaticPadTemplate * pad_template, + GType pad_type); + +GST_API +GstCaps* gst_static_pad_template_get_caps (GstStaticPadTemplate *templ); + +GST_API +GstCaps* gst_pad_template_get_caps (GstPadTemplate *templ); + +GST_API +void gst_pad_template_pad_created (GstPadTemplate * templ, GstPad * pad); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPadTemplate, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PAD_TEMPLATE_H__ */ + diff --git a/gst/gstparamspecs.c b/gst/gstparamspecs.c new file mode 100644 index 0000000..7de51d7 --- /dev/null +++ b/gst/gstparamspecs.c @@ -0,0 +1,369 @@ +/* GStreamer - GParamSpecs for some of our types + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstparamspec + * @title: GstParamSpec + * @short_description: GParamSpec implementations specific + * to GStreamer + * + * GParamSpec implementations specific to GStreamer. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "glib-compat-private.h" +#include "gstparamspecs.h" + +/* --- GstParamSpecFraction --- */ + +static void +_gst_param_fraction_init (GParamSpec * pspec) +{ + GstParamSpecFraction *fspec = GST_PARAM_SPEC_FRACTION (pspec); + + fspec->min_num = 0; + fspec->min_den = 1; + fspec->max_num = G_MAXINT; + fspec->max_den = 1; + fspec->def_num = 1; + fspec->def_den = 1; +} + +static void +_gst_param_fraction_set_default (GParamSpec * pspec, GValue * value) +{ + value->data[0].v_int = GST_PARAM_SPEC_FRACTION (pspec)->def_num; + value->data[1].v_int = GST_PARAM_SPEC_FRACTION (pspec)->def_den; +} + +static gboolean +_gst_param_fraction_validate (GParamSpec * pspec, GValue * value) +{ + GstParamSpecFraction *fspec = GST_PARAM_SPEC_FRACTION (pspec); + gboolean within_range = FALSE; + GValue f_this = { 0, }; + GValue f_min = { 0, }; + GValue f_max = { 0, }; + gint res; + + g_value_init (&f_this, GST_TYPE_FRACTION); + gst_value_set_fraction (&f_this, value->data[0].v_int, value->data[1].v_int); + + g_value_init (&f_min, GST_TYPE_FRACTION); + gst_value_set_fraction (&f_min, fspec->min_num, fspec->min_den); + + g_value_init (&f_max, GST_TYPE_FRACTION); + gst_value_set_fraction (&f_max, fspec->max_num, fspec->max_den); + + res = gst_value_compare (&f_min, &f_this); +#ifndef GST_DISABLE_GST_DEBUG + GST_LOG ("comparing %d/%d to %d/%d, result = %d", fspec->min_num, + fspec->min_den, value->data[0].v_int, value->data[1].v_int, res); +#endif + if (res != GST_VALUE_LESS_THAN && res != GST_VALUE_EQUAL) + goto out; + +#ifndef GST_DISABLE_GST_DEBUG + GST_LOG ("comparing %d/%d to %d/%d, result = %d", value->data[0].v_int, + value->data[1].v_int, fspec->max_num, fspec->max_den, res); +#endif + res = gst_value_compare (&f_this, &f_max); + if (res != GST_VALUE_LESS_THAN && res != GST_VALUE_EQUAL) + goto out; + + within_range = TRUE; + +out: + + g_value_unset (&f_min); + g_value_unset (&f_max); + g_value_unset (&f_this); + +#ifndef GST_DISABLE_GST_DEBUG + GST_LOG ("%swithin range", (within_range) ? "" : "not "); +#endif + + /* return FALSE if everything ok, otherwise TRUE */ + return !within_range; +} + +static gint +_gst_param_fraction_values_cmp (GParamSpec * pspec, const GValue * value1, + const GValue * value2) +{ + gint res; + + res = gst_value_compare (value1, value2); + + g_assert (res != GST_VALUE_UNORDERED); + + /* GST_VALUE_LESS_THAN is -1, EQUAL is 0, and GREATER_THAN is 1 */ + return res; +} + +GType +gst_param_spec_fraction_get_type (void) +{ + static volatile GType gst_faction_type = 0; + + /* register GST_TYPE_PARAM_FRACTION */ + if (g_once_init_enter (&gst_faction_type)) { + GType type; + static GParamSpecTypeInfo pspec_info = { + sizeof (GstParamSpecFraction), /* instance_size */ + 0, /* n_preallocs */ + _gst_param_fraction_init, /* instance_init */ + G_TYPE_INVALID, /* value_type */ + NULL, /* finalize */ + _gst_param_fraction_set_default, /* value_set_default */ + _gst_param_fraction_validate, /* value_validate */ + _gst_param_fraction_values_cmp, /* values_cmp */ + }; + pspec_info.value_type = gst_fraction_get_type (); + type = g_param_type_register_static ("GstParamFraction", &pspec_info); + g_once_init_leave (&gst_faction_type, type); + } + + return gst_faction_type; +} + +/** + * gst_param_spec_fraction: + * @name: canonical name of the property specified + * @nick: nick name for the property specified + * @blurb: description of the property specified + * @min_num: minimum value (fraction numerator) + * @min_denom: minimum value (fraction denominator) + * @max_num: maximum value (fraction numerator) + * @max_denom: maximum value (fraction denominator) + * @default_num: default value (fraction numerator) + * @default_denom: default value (fraction denominator) + * @flags: flags for the property specified + * + * This function creates a fraction GParamSpec for use by objects/elements + * that want to expose properties of fraction type. This function is typically + * used in connection with g_object_class_install_property() in a GObjects's + * instance_init function. + * + * Returns: (transfer full) (nullable): a newly created parameter specification + */ +GParamSpec * +gst_param_spec_fraction (const gchar * name, const gchar * nick, + const gchar * blurb, gint min_num, gint min_denom, gint max_num, + gint max_denom, gint default_num, gint default_denom, GParamFlags flags) +{ + GstParamSpecFraction *fspec; + GParamSpec *pspec; + GValue default_val = { 0, }; + + fspec = + g_param_spec_internal (GST_TYPE_PARAM_FRACTION, name, nick, blurb, flags); + + fspec->min_num = min_num; + fspec->min_den = min_denom; + fspec->max_num = max_num; + fspec->max_den = max_denom; + fspec->def_num = default_num; + fspec->def_den = default_denom; + + pspec = G_PARAM_SPEC (fspec); + + /* check that min <= default <= max */ + g_value_init (&default_val, GST_TYPE_FRACTION); + gst_value_set_fraction (&default_val, default_num, default_denom); + /* validate returns TRUE if the validation fails */ + if (_gst_param_fraction_validate (pspec, &default_val)) { + g_critical ("GstParamSpec of type 'fraction' for property '%s' has a " + "default value of %d/%d, which is not within the allowed range of " + "%d/%d to %d/%d", name, default_num, default_denom, min_num, + min_denom, max_num, max_denom); + g_param_spec_ref (pspec); + g_param_spec_sink (pspec); + g_param_spec_unref (pspec); + pspec = NULL; + } + g_value_unset (&default_val); + + return pspec; +} + +static void +_gst_param_array_init (GParamSpec * pspec) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + + aspec->element_spec = NULL; +} + +static void +_gst_param_array_finalize (GParamSpec * pspec) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + GParamSpecClass *parent_class = + g_type_class_peek (g_type_parent (GST_TYPE_PARAM_ARRAY_LIST)); + + if (aspec->element_spec) { + g_param_spec_unref (aspec->element_spec); + aspec->element_spec = NULL; + } + + parent_class->finalize (pspec); +} + +static gboolean +_gst_param_array_validate (GParamSpec * pspec, GValue * value) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + gboolean ret = FALSE; + + /* ensure array values validity against a present element spec */ + if (aspec->element_spec) { + GParamSpec *element_spec = aspec->element_spec; + guint i; + + for (i = 0; i < gst_value_array_get_size (value); i++) { + GValue *element = (GValue *) gst_value_array_get_value (value, i); + + /* need to fixup value type, or ensure that the array value is initialized at all */ + if (!g_value_type_compatible (G_VALUE_TYPE (element), + G_PARAM_SPEC_VALUE_TYPE (element_spec))) { + if (G_VALUE_TYPE (element) != 0) + g_value_unset (element); + g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec)); + g_param_value_set_default (element_spec, element); + ret = TRUE; + } + + /* validate array value against element_spec */ + if (g_param_value_validate (element_spec, element)) + ret = TRUE; + } + } + + return ret; +} + +static gint +_gst_param_array_values_cmp (GParamSpec * pspec, const GValue * value1, + const GValue * value2) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + guint size1, size2; + + if (!value1 || !value2) + return value2 ? -1 : value1 != value2; + + size1 = gst_value_array_get_size (value1); + size2 = gst_value_array_get_size (value2); + + if (size1 != size2) + return size1 < size2 ? -1 : 1; + else if (!aspec->element_spec) { + /* we need an element specification for comparisons, so there's not much + * to compare here, try to at least provide stable lesser/greater result + */ + return size1 < size2 ? -1 : size1 > size2; + } else { /* size1 == size2 */ + guint i; + + for (i = 0; i < size1; i++) { + const GValue *element1 = gst_value_array_get_value (value1, i); + const GValue *element2 = gst_value_array_get_value (value2, i); + gint cmp; + + /* need corresponding element types, provide stable result otherwise */ + if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2)) + return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1; + cmp = g_param_values_cmp (aspec->element_spec, element1, element2); + if (cmp) + return cmp; + } + return 0; + } +} + +GType +gst_param_spec_array_get_type (void) +{ + static volatile GType gst_array_type = 0; + + /* register GST_TYPE_PARAM_FRACTION */ + if (g_once_init_enter (&gst_array_type)) { + GType type; + static GParamSpecTypeInfo pspec_info = { + sizeof (GstParamSpecArray), /* instance_size */ + 0, /* n_preallocs */ + _gst_param_array_init, /* instance_init */ + G_TYPE_INVALID, /* value_type */ + _gst_param_array_finalize, /* finalize */ + NULL, /* value_set_default */ + _gst_param_array_validate, /* value_validate */ + _gst_param_array_values_cmp, /* values_cmp */ + }; + pspec_info.value_type = gst_value_array_get_type (); + type = g_param_type_register_static ("GstParamArray", &pspec_info); + g_once_init_leave (&gst_array_type, type); + } + + return gst_array_type; +} + +/** + * gst_param_spec_array: + * @name: canonical name of the property specified + * @nick: nick name for the property specified + * @blurb: description of the property specified + * @element_spec: GParamSpec of the array + * @flags: flags for the property specified + * + * This function creates a GstArray GParamSpec for use by objects/elements + * that want to expose properties of GstArray type. This function is + * typically * used in connection with g_object_class_install_property() in a + * GObjects's instance_init function. + * + * Returns: (transfer full): a newly created parameter specification + * + * Since: 1.14 + */ + +GParamSpec * +gst_param_spec_array (const gchar * name, + const gchar * nick, + const gchar * blurb, GParamSpec * element_spec, GParamFlags flags) +{ + GstParamSpecArray *aspec; + + g_return_val_if_fail (element_spec == NULL + || G_IS_PARAM_SPEC (element_spec), NULL); + + aspec = g_param_spec_internal (GST_TYPE_PARAM_ARRAY_LIST, + name, nick, blurb, flags); + if (aspec == NULL) + return NULL; + + if (element_spec) { + aspec->element_spec = g_param_spec_ref (element_spec); + g_param_spec_sink (element_spec); + } + + return G_PARAM_SPEC (aspec); +} diff --git a/gst/gstparamspecs.h b/gst/gstparamspecs.h new file mode 100644 index 0000000..1d69f95 --- /dev/null +++ b/gst/gstparamspecs.h @@ -0,0 +1,153 @@ +/* GStreamer - GParamSpecs for some of our types + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PARAMSPECS_H__ +#define __GST_PARAMSPECS_H__ + +#include + +G_BEGIN_DECLS + +/* --- paramspec flags */ + +/** + * GST_PARAM_CONTROLLABLE: (value 512) + * + * Use this flag on GObject properties to signal they can make sense to be. + * controlled over time. This hint is used by the GstController. + */ +#define GST_PARAM_CONTROLLABLE (1 << (G_PARAM_USER_SHIFT + 1)) + +/** + * GST_PARAM_MUTABLE_READY: (value 1024) + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the READY or lower state. + */ +#define GST_PARAM_MUTABLE_READY (1 << (G_PARAM_USER_SHIFT + 2)) + +/** + * GST_PARAM_MUTABLE_PAUSED: (value 2048) + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the PAUSED or lower state. + * This flag implies GST_PARAM_MUTABLE_READY. + */ +#define GST_PARAM_MUTABLE_PAUSED (1 << (G_PARAM_USER_SHIFT + 3)) + +/** + * GST_PARAM_MUTABLE_PLAYING: (value 4096) + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the PLAYING or lower state. + * This flag implies GST_PARAM_MUTABLE_PAUSED. + */ +#define GST_PARAM_MUTABLE_PLAYING (1 << (G_PARAM_USER_SHIFT + 4)) + +/** + * GST_PARAM_USER_SHIFT: (value 65536) + * + * Bits based on GST_PARAM_USER_SHIFT can be used by 3rd party applications. + */ +#define GST_PARAM_USER_SHIFT (1 << (G_PARAM_USER_SHIFT + 8)) + + +/* --- type macros --- */ + +#define GST_TYPE_PARAM_FRACTION (gst_param_spec_fraction_get_type ()) +#define GST_IS_PARAM_SPEC_FRACTION(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GST_TYPE_PARAM_FRACTION)) +#define GST_PARAM_SPEC_FRACTION(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GST_TYPE_PARAM_FRACTION, GstParamSpecFraction)) + + +#define GST_TYPE_PARAM_ARRAY_LIST (gst_param_spec_array_get_type ()) +#define GST_IS_PARAM_SPEC_ARRAY_LIST(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GST_TYPE_PARAM_ARRAY_LIST)) +#define GST_PARAM_SPEC_ARRAY_LIST(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GST_TYPE_PARAM_ARRAY_LIST, GstParamSpecArray)) + + +/* --- get_type functions --- */ + +GST_API +GType gst_param_spec_fraction_get_type (void); + +GST_API +GType gst_param_spec_array_get_type (void); + + +/* --- typedefs & structures --- */ + +typedef struct _GstParamSpecFraction GstParamSpecFraction; +typedef struct _GstParamSpecArray GstParamSpecArray; + +/** + * GstParamSpecFraction: + * @parent_instance: super class + * @min_num: minimal numerator + * @min_den: minimal denominator + * @max_num: maximal numerator + * @max_den: maximal denominator + * @def_num: default numerator + * @def_den: default denominator + * + * A GParamSpec derived structure that contains the meta data for fractional + * properties. + */ +struct _GstParamSpecFraction { + GParamSpec parent_instance; + + gint min_num, min_den; + gint max_num, max_den; + gint def_num, def_den; +}; + +/** + * GstParamSpecArray: + * @parent_instance: super class + * @value_array: the array of values + * + * A GParamSpec derived structure that contains the meta data for fractional + * properties. + */ +struct _GstParamSpecArray { + GParamSpec parent_instance; + + GParamSpec * element_spec; +}; + + +/* --- GParamSpec prototypes --- */ + +GST_API +GParamSpec * gst_param_spec_fraction (const gchar * name, + const gchar * nick, + const gchar * blurb, + gint min_num, gint min_denom, + gint max_num, gint max_denom, + gint default_num, gint default_denom, + GParamFlags flags) G_GNUC_MALLOC; +GST_API +GParamSpec * gst_param_spec_array (const gchar * name, + const gchar * nick, + const gchar * blurb, + GParamSpec * element_spec, + GParamFlags flags) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __GST_PARAMSPECS_H__ */ + diff --git a/gst/gstparse.c b/gst/gstparse.c new file mode 100644 index 0000000..e50d7e7 --- /dev/null +++ b/gst/gstparse.c @@ -0,0 +1,365 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2002 Andy Wingo + * 2008 Tim-Philipp Müller + * + * gstparse.c: get a pipeline from a text pipeline description + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstparse + * @title: GstParse + * @short_description: Get a pipeline from a text pipeline description + * + * These function allow to create a pipeline based on the syntax used in the + * gst-launch-1.0 utility (see man-page for syntax documentation). + * + * Please note that these functions take several measures to create + * somewhat dynamic pipelines. Due to that such pipelines are not always + * reusable (set the state to NULL and back to PLAYING). + */ + +#include "gst_private.h" +#include + +#include "gstparse.h" +#include "gsterror.h" +#include "gstinfo.h" +#ifndef GST_DISABLE_PARSE +#include "parse/types.h" +#endif + +G_DEFINE_BOXED_TYPE (GstParseContext, gst_parse_context, + (GBoxedCopyFunc) gst_parse_context_copy, + (GBoxedFreeFunc) gst_parse_context_free); + +/** + * gst_parse_error_quark: + * + * Get the error quark used by the parsing subsystem. + * + * Returns: the quark of the parse errors. + */ +GQuark +gst_parse_error_quark (void) +{ + static GQuark quark = 0; + + if (!quark) + quark = g_quark_from_static_string ("gst_parse_error"); + return quark; +} + + +/** + * gst_parse_context_new: + * + * Allocates a parse context for use with gst_parse_launch_full() or + * gst_parse_launchv_full(). + * + * Free-function: gst_parse_context_free + * + * Returns: (transfer full) (nullable): a newly-allocated parse context. Free + * with gst_parse_context_free() when no longer needed. + */ +GstParseContext * +gst_parse_context_new (void) +{ +#ifndef GST_DISABLE_PARSE + GstParseContext *ctx; + + ctx = g_slice_new (GstParseContext); + ctx->missing_elements = NULL; + + return ctx; +#else + return NULL; +#endif +} + +/** + * gst_parse_context_copy: + * @context: a #GstParseContext + * + * Copies the @context. + * + * Returns: (transfer full) (nullable): A copied #GstParseContext + */ +GstParseContext * +gst_parse_context_copy (const GstParseContext * context) +{ + GstParseContext *ret = NULL; +#ifndef GST_DISABLE_PARSE + + ret = gst_parse_context_new (); + if (context) { + GQueue missing_copy = G_QUEUE_INIT; + GList *l; + + for (l = context->missing_elements; l != NULL; l = l->next) + g_queue_push_tail (&missing_copy, g_strdup ((const gchar *) l->data)); + + ret->missing_elements = missing_copy.head; + } +#endif + return ret; +} + +/** + * gst_parse_context_free: + * @context: (transfer full): a #GstParseContext + * + * Frees a parse context previously allocated with gst_parse_context_new(). + */ +void +gst_parse_context_free (GstParseContext * context) +{ +#ifndef GST_DISABLE_PARSE + if (context) { + g_list_foreach (context->missing_elements, (GFunc) g_free, NULL); + g_list_free (context->missing_elements); + g_slice_free (GstParseContext, context); + } +#endif +} + +/** + * gst_parse_context_get_missing_elements: + * @context: a #GstParseContext + * + * Retrieve missing elements from a previous run of gst_parse_launch_full() + * or gst_parse_launchv_full(). Will only return results if an error code + * of %GST_PARSE_ERROR_NO_SUCH_ELEMENT was returned. + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*) (nullable): a + * %NULL-terminated array of element factory name strings of missing + * elements. Free with g_strfreev() when no longer needed. + */ +gchar ** +gst_parse_context_get_missing_elements (GstParseContext * context) +{ +#ifndef GST_DISABLE_PARSE + gchar **arr; + GList *l; + guint len, i; + + g_return_val_if_fail (context != NULL, NULL); + + len = g_list_length (context->missing_elements); + + if (G_UNLIKELY (len == 0)) + return NULL; + + arr = g_new (gchar *, len + 1); + + for (i = 0, l = context->missing_elements; l != NULL; l = l->next, ++i) + arr[i] = g_strdup (l->data); + + arr[i] = NULL; + + return arr; +#else + return NULL; +#endif +} + +#ifndef GST_DISABLE_PARSE +static gchar * +_gst_parse_escape (const gchar * str) +{ + GString *gstr = NULL; + gboolean in_quotes; + + g_return_val_if_fail (str != NULL, NULL); + + gstr = g_string_sized_new (strlen (str)); + + in_quotes = FALSE; + + while (*str) { + if (*str == '"' && (!in_quotes || (in_quotes && *(str - 1) != '\\'))) + in_quotes = !in_quotes; + + if (*str == ' ' && !in_quotes) + g_string_append_c (gstr, '\\'); + + g_string_append_c (gstr, *str); + str++; + } + + return g_string_free (gstr, FALSE); +} +#endif /* !GST_DISABLE_PARSE */ + +/** + * gst_parse_launchv: + * @argv: (in) (array zero-terminated=1): null-terminated array of arguments + * @error: pointer to a #GError + * + * Create a new element based on command line syntax. + * @error will contain an error message if an erroneous pipeline is specified. + * An error does not mean that the pipeline could not be constructed. + * + * Returns: (transfer floating) (nullable): a new element on success and %NULL + * on failure. + */ +GstElement * +gst_parse_launchv (const gchar ** argv, GError ** error) +{ + return gst_parse_launchv_full (argv, NULL, GST_PARSE_FLAG_NONE, error); +} + +/** + * gst_parse_launchv_full: + * @argv: (in) (array zero-terminated=1): null-terminated array of arguments + * @context: (allow-none): a parse context allocated with + * gst_parse_context_new(), or %NULL + * @flags: parsing options, or #GST_PARSE_FLAG_NONE + * @error: pointer to a #GError (which must be initialised to %NULL) + * + * Create a new element based on command line syntax. + * @error will contain an error message if an erroneous pipeline is specified. + * An error does not mean that the pipeline could not be constructed. + * + * Returns: (transfer floating) (nullable): a new element on success; on + * failure, either %NULL or a partially-constructed bin or element will be + * returned and @error will be set (unless you passed + * #GST_PARSE_FLAG_FATAL_ERRORS in @flags, then %NULL will always be returned + * on failure) + */ +GstElement * +gst_parse_launchv_full (const gchar ** argv, GstParseContext * context, + GstParseFlags flags, GError ** error) +{ +#ifndef GST_DISABLE_PARSE + GstElement *element; + GString *str; + const gchar **argvp, *arg; + gchar *tmp; + + g_return_val_if_fail (argv != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* let's give it a nice size. */ + str = g_string_sized_new (1024); + + argvp = argv; + while (*argvp) { + arg = *argvp; + GST_DEBUG ("escaping argument %s", arg); + tmp = _gst_parse_escape (arg); + g_string_append (str, tmp); + g_free (tmp); + g_string_append_c (str, ' '); + argvp++; + } + + element = gst_parse_launch_full (str->str, context, flags, error); + + g_string_free (str, TRUE); + + return element; +#else + /* gst_parse_launch_full() will set a GST_CORE_ERROR_DISABLED error for us */ + return gst_parse_launch_full ("", NULL, 0, error); +#endif +} + +/** + * gst_parse_launch: + * @pipeline_description: the command line describing the pipeline + * @error: the error message in case of an erroneous pipeline. + * + * Create a new pipeline based on command line syntax. + * Please note that you might get a return value that is not %NULL even though + * the @error is set. In this case there was a recoverable parsing error and you + * can try to play the pipeline. + * + * Returns: (transfer floating) (nullable): a new element on success, %NULL on + * failure. If more than one toplevel element is specified by the + * @pipeline_description, all elements are put into a #GstPipeline, which + * than is returned. + */ +GstElement * +gst_parse_launch (const gchar * pipeline_description, GError ** error) +{ + return gst_parse_launch_full (pipeline_description, NULL, GST_PARSE_FLAG_NONE, + error); +} + +/** + * gst_parse_launch_full: + * @pipeline_description: the command line describing the pipeline + * @context: (allow-none): a parse context allocated with + * gst_parse_context_new(), or %NULL + * @flags: parsing options, or #GST_PARSE_FLAG_NONE + * @error: the error message in case of an erroneous pipeline. + * + * Create a new pipeline based on command line syntax. + * Please note that you might get a return value that is not %NULL even though + * the @error is set. In this case there was a recoverable parsing error and you + * can try to play the pipeline. + * + * Returns: (transfer floating) (nullable): a new element on success, %NULL on + * failure. If more than one toplevel element is specified by the + * @pipeline_description, all elements are put into a #GstPipeline, which + * then is returned (unless the GST_PARSE_FLAG_PLACE_IN_BIN flag is set, in + * which case they are put in a #GstBin instead). + */ +GstElement * +gst_parse_launch_full (const gchar * pipeline_description, + GstParseContext * context, GstParseFlags flags, GError ** error) +{ +#ifndef GST_DISABLE_PARSE + GstElement *element; + GError *myerror = NULL; + + g_return_val_if_fail (pipeline_description != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + GST_CAT_INFO (GST_CAT_PIPELINE, "parsing pipeline description '%s'", + pipeline_description); + + element = priv_gst_parse_launch (pipeline_description, &myerror, context, + flags); + + /* don't return partially constructed pipeline if FATAL_ERRORS was given */ + if (G_UNLIKELY (myerror != NULL && element != NULL)) { + if ((flags & GST_PARSE_FLAG_FATAL_ERRORS)) { + gst_object_unref (element); + element = NULL; + } + } + + if (myerror) + g_propagate_error (error, myerror); + + return element; +#else + gchar *msg; + + GST_WARNING ("Disabled API called"); + + msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); + g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); + g_free (msg); + + return NULL; +#endif +} diff --git a/gst/gstparse.h b/gst/gstparse.h new file mode 100644 index 0000000..ac248e4 --- /dev/null +++ b/gst/gstparse.h @@ -0,0 +1,140 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstparse.h: get a pipeline from a text pipeline description + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PARSE_H__ +#define __GST_PARSE_H__ + +#include + +G_BEGIN_DECLS + +GST_API +GQuark gst_parse_error_quark (void); +/** + * GST_PARSE_ERROR: + * + * Get access to the error quark of the parse subsystem. + */ +#define GST_PARSE_ERROR gst_parse_error_quark () + +/* FIXME 2.0: rename to GstParseLaunchError, this is not only related to + *parsing */ +/** + * GstParseError: + * @GST_PARSE_ERROR_SYNTAX: A syntax error occurred. + * @GST_PARSE_ERROR_NO_SUCH_ELEMENT: The description contained an unknown element + * @GST_PARSE_ERROR_NO_SUCH_PROPERTY: An element did not have a specified property + * @GST_PARSE_ERROR_LINK: There was an error linking two pads. + * @GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY: There was an error setting a property + * @GST_PARSE_ERROR_EMPTY_BIN: An empty bin was specified. + * @GST_PARSE_ERROR_EMPTY: An empty description was specified + * @GST_PARSE_ERROR_DELAYED_LINK: A delayed link did not get resolved. + * + * The different parsing errors that can occur. + */ +typedef enum +{ + GST_PARSE_ERROR_SYNTAX, + GST_PARSE_ERROR_NO_SUCH_ELEMENT, + GST_PARSE_ERROR_NO_SUCH_PROPERTY, + GST_PARSE_ERROR_LINK, + GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY, + GST_PARSE_ERROR_EMPTY_BIN, + GST_PARSE_ERROR_EMPTY, + GST_PARSE_ERROR_DELAYED_LINK +} GstParseError; + +/** + * GstParseFlags: + * @GST_PARSE_FLAG_NONE: Do not use any special parsing options. + * @GST_PARSE_FLAG_FATAL_ERRORS: Always return %NULL when an error occurs + * (default behaviour is to return partially constructed bins or elements + * in some cases) + * @GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS: If a bin only has a single element, + * just return the element. + * @GST_PARSE_FLAG_PLACE_IN_BIN: If more than one toplevel element is described + * by the pipeline description string, put them in a #GstBin instead of a + * #GstPipeline. (Since 1.10) + * + * Parsing options. + */ +typedef enum +{ + GST_PARSE_FLAG_NONE = 0, + GST_PARSE_FLAG_FATAL_ERRORS = (1 << 0), + GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS = (1 << 1), + GST_PARSE_FLAG_PLACE_IN_BIN = (1 << 2) +} GstParseFlags; + +#define GST_TYPE_PARSE_CONTEXT (gst_parse_context_get_type()) + +/** + * GstParseContext: + * + * Opaque structure. + */ +typedef struct _GstParseContext GstParseContext; + +/* create, process and free a parse context */ + +GST_API +GType gst_parse_context_get_type (void); + +GST_API +GstParseContext * gst_parse_context_new (void) G_GNUC_MALLOC; + +GST_API +gchar ** gst_parse_context_get_missing_elements (GstParseContext * context) G_GNUC_MALLOC; + +GST_API +void gst_parse_context_free (GstParseContext * context); + +GST_API +GstParseContext * gst_parse_context_copy (const GstParseContext * context); + + +/* parse functions */ + +GST_API +GstElement * gst_parse_launch (const gchar * pipeline_description, + GError ** error) G_GNUC_MALLOC; +GST_API +GstElement * gst_parse_launchv (const gchar ** argv, + GError ** error) G_GNUC_MALLOC; +GST_API +GstElement * gst_parse_launch_full (const gchar * pipeline_description, + GstParseContext * context, + GstParseFlags flags, + GError ** error) G_GNUC_MALLOC; +GST_API +GstElement * gst_parse_launchv_full (const gchar ** argv, + GstParseContext * context, + GstParseFlags flags, + GError ** error) G_GNUC_MALLOC; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstParseContext, gst_parse_context_free) +#endif + +G_END_DECLS + +#endif /* __GST_PARSE_H__ */ diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c new file mode 100644 index 0000000..07b4cce --- /dev/null +++ b/gst/gstpipeline.c @@ -0,0 +1,1032 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004,2005 Wim Taymans + * + * gstpipeline.c: Overall pipeline management 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstpipeline + * @title: GstPipeline + * @short_description: Top-level bin with clocking and bus management + functionality. + * @see_also: #GstElement, #GstBin, #GstClock, #GstBus + * + * A #GstPipeline is a special #GstBin used as the toplevel container for + * the filter graph. The #GstPipeline will manage the selection and + * distribution of a global #GstClock as well as provide a #GstBus to the + * application. + * + * gst_pipeline_new() is used to create a pipeline. when you are done with + * the pipeline, use gst_object_unref() to free its resources including all + * added #GstElement objects (if not otherwise referenced). + * + * Elements are added and removed from the pipeline using the #GstBin + * methods like gst_bin_add() and gst_bin_remove() (see #GstBin). + * + * Before changing the state of the #GstPipeline (see #GstElement) a #GstBus + * can be retrieved with gst_pipeline_get_bus(). This bus can then be + * used to receive #GstMessage from the elements in the pipeline. + * + * By default, a #GstPipeline will automatically flush the pending #GstBus + * messages when going to the NULL state to ensure that no circular + * references exist when no messages are read from the #GstBus. This + * behaviour can be changed with gst_pipeline_set_auto_flush_bus(). + * + * When the #GstPipeline performs the PAUSED to PLAYING state change it will + * select a clock for the elements. The clock selection algorithm will by + * default select a clock provided by an element that is most upstream + * (closest to the source). For live pipelines (ones that return + * #GST_STATE_CHANGE_NO_PREROLL from the gst_element_set_state() call) this + * will select the clock provided by the live source. For normal pipelines + * this will select a clock provided by the sinks (most likely the audio + * sink). If no element provides a clock, a default #GstSystemClock is used. + * + * The clock selection can be controlled with the gst_pipeline_use_clock() + * method, which will enforce a given clock on the pipeline. With + * gst_pipeline_auto_clock() the default clock selection algorithm can be + * restored. + * + * A #GstPipeline maintains a running time for the elements. The running + * time is defined as the difference between the current clock time and + * the base time. When the pipeline goes to READY or a flushing seek is + * performed on it, the running time is reset to 0. When the pipeline is + * set from PLAYING to PAUSED, the current clock time is sampled and used to + * configure the base time for the elements when the pipeline is set + * to PLAYING again. The effect is that the running time (as the difference + * between the clock time and the base time) will count how much time was spent + * in the PLAYING state. This default behaviour can be changed with the + * gst_element_set_start_time() method. + */ + +#include "gst_private.h" +#include "gsterror.h" +#include "gst-i18n-lib.h" + +#include "gstpipeline.h" +#include "gstinfo.h" +#include "gstsystemclock.h" +#include "gstutils.h" + +GST_DEBUG_CATEGORY_STATIC (pipeline_debug); +#define GST_CAT_DEFAULT pipeline_debug + +/* Pipeline signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_DELAY 0 +#define DEFAULT_AUTO_FLUSH_BUS TRUE +#define DEFAULT_LATENCY GST_CLOCK_TIME_NONE + +enum +{ + PROP_0, + PROP_DELAY, + PROP_AUTO_FLUSH_BUS, + PROP_LATENCY +}; + +#define GST_PIPELINE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PIPELINE, GstPipelinePrivate)) + +struct _GstPipelinePrivate +{ + /* with LOCK */ + gboolean auto_flush_bus; + + /* when we need to update stream_time or clock when going back to + * PLAYING*/ + GstClockTime last_start_time; + gboolean update_clock; + + GstClockTime latency; +}; + + +static void gst_pipeline_dispose (GObject * object); +static void gst_pipeline_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_pipeline_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstClock *gst_pipeline_provide_clock_func (GstElement * element); +static GstStateChangeReturn gst_pipeline_change_state (GstElement * element, + GstStateChange transition); + +static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message); +static gboolean gst_pipeline_do_latency (GstBin * bin); + +/* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */ + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, \ + "debugging info for the 'pipeline' container element"); \ +} + +#define gst_pipeline_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstPipeline, gst_pipeline, GST_TYPE_BIN, _do_init); + +static void +gst_pipeline_class_init (GstPipelineClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GstBinClass *gstbin_class = GST_BIN_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstPipelinePrivate)); + + gobject_class->set_property = gst_pipeline_set_property; + gobject_class->get_property = gst_pipeline_get_property; + + /** + * GstPipeline:delay: + * + * The expected delay needed for elements to spin up to the + * PLAYING state expressed in nanoseconds. + * see gst_pipeline_set_delay() for more information on this option. + **/ + g_object_class_install_property (gobject_class, PROP_DELAY, + g_param_spec_uint64 ("delay", "Delay", + "Expected delay needed for elements " + "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPipeline:auto-flush-bus: + * + * Whether or not to automatically flush all messages on the + * pipeline's bus when going from READY to NULL state. Please see + * gst_pipeline_set_auto_flush_bus() for more information on this option. + **/ + g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS, + g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus", + "Whether to automatically flush the pipeline's bus when going " + "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPipeline:latency: + * + * Latency to configure on the pipeline. See gst_pipeline_set_latency(). + * + * Since: 1.6 + **/ + g_object_class_install_property (gobject_class, PROP_LATENCY, + g_param_spec_uint64 ("latency", "Latency", + "Latency to configure on the pipeline", 0, G_MAXUINT64, + DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gobject_class->dispose = gst_pipeline_dispose; + + gst_element_class_set_static_metadata (gstelement_class, "Pipeline object", + "Generic/Bin", + "Complete pipeline object", + "Erik Walthinsen , Wim Taymans "); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_pipeline_change_state); + gstelement_class->provide_clock = + GST_DEBUG_FUNCPTR (gst_pipeline_provide_clock_func); + gstbin_class->handle_message = + GST_DEBUG_FUNCPTR (gst_pipeline_handle_message); + gstbin_class->do_latency = GST_DEBUG_FUNCPTR (gst_pipeline_do_latency); +} + +static void +gst_pipeline_init (GstPipeline * pipeline) +{ + GstBus *bus; + + pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline); + + /* set default property values */ + pipeline->priv->auto_flush_bus = DEFAULT_AUTO_FLUSH_BUS; + pipeline->delay = DEFAULT_DELAY; + pipeline->priv->latency = DEFAULT_LATENCY; + + /* create and set a default bus */ + bus = gst_bus_new (); +#if 0 + /* FIXME, disabled for 0.10.5 release as it caused to many regressions */ + /* Start our bus in flushing if appropriate */ + if (pipeline->priv->auto_flush_bus) + gst_bus_set_flushing (bus, TRUE); +#endif + + gst_element_set_bus (GST_ELEMENT_CAST (pipeline), bus); + GST_DEBUG_OBJECT (pipeline, "set bus %" GST_PTR_FORMAT " on pipeline", bus); + gst_object_unref (bus); +} + +static void +gst_pipeline_dispose (GObject * object) +{ + GstPipeline *pipeline = GST_PIPELINE (object); + GstClock **clock_p = &pipeline->fixed_clock; + + GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "%p dispose", pipeline); + + /* clear and unref any fixed clock */ + gst_object_replace ((GstObject **) clock_p, NULL); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_pipeline_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPipeline *pipeline = GST_PIPELINE (object); + + switch (prop_id) { + case PROP_DELAY: + gst_pipeline_set_delay (pipeline, g_value_get_uint64 (value)); + break; + case PROP_AUTO_FLUSH_BUS: + gst_pipeline_set_auto_flush_bus (pipeline, g_value_get_boolean (value)); + break; + case PROP_LATENCY: + gst_pipeline_set_latency (pipeline, g_value_get_uint64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_pipeline_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstPipeline *pipeline = GST_PIPELINE (object); + + switch (prop_id) { + case PROP_DELAY: + g_value_set_uint64 (value, gst_pipeline_get_delay (pipeline)); + break; + case PROP_AUTO_FLUSH_BUS: + g_value_set_boolean (value, gst_pipeline_get_auto_flush_bus (pipeline)); + break; + case PROP_LATENCY: + g_value_set_uint64 (value, gst_pipeline_get_latency (pipeline)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* set the start_time to 0, this will cause us to select a new base_time and + * make the running_time start from 0 again. */ +static void +reset_start_time (GstPipeline * pipeline, GstClockTime start_time) +{ + GST_OBJECT_LOCK (pipeline); + if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) { + GST_DEBUG_OBJECT (pipeline, "reset start_time to 0"); + GST_ELEMENT_START_TIME (pipeline) = start_time; + pipeline->priv->last_start_time = -1; + } else { + GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time"); + } + GST_OBJECT_UNLOCK (pipeline); +} + +/** + * gst_pipeline_new: + * @name: (allow-none): name of new pipeline + * + * Create a new pipeline with the given name. + * + * Returns: (transfer floating): newly created GstPipeline + * + * MT safe. + */ +GstElement * +gst_pipeline_new (const gchar * name) +{ + return gst_element_factory_make ("pipeline", name); +} + +/* takes a snapshot of the running_time of the pipeline and store this as the + * element start_time. This is the time we will set as the running_time of the + * pipeline when we go to PLAYING next. */ +static void +pipeline_update_start_time (GstElement * element) +{ + GstPipeline *pipeline = GST_PIPELINE_CAST (element); + GstClock *clock; + + GST_OBJECT_LOCK (element); + if ((clock = element->clock)) { + GstClockTime now; + + gst_object_ref (clock); + GST_OBJECT_UNLOCK (element); + + /* calculate the time when we stopped */ + now = gst_clock_get_time (clock); + gst_object_unref (clock); + + GST_OBJECT_LOCK (element); + /* store the current running time */ + if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) { + if (now != GST_CLOCK_TIME_NONE) + GST_ELEMENT_START_TIME (pipeline) = now - element->base_time; + else + GST_WARNING_OBJECT (element, + "Clock %s returned invalid time, can't calculate " + "running_time when going to the PAUSED state", + GST_OBJECT_NAME (clock)); + + /* we went to PAUSED, when going to PLAYING select clock and new + * base_time */ + pipeline->priv->update_clock = TRUE; + } + GST_DEBUG_OBJECT (element, + "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT + ", base_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_ELEMENT_START_TIME (pipeline)), + GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time)); + } + GST_OBJECT_UNLOCK (element); +} + +/* MT safe */ +static GstStateChangeReturn +gst_pipeline_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + GstPipeline *pipeline = GST_PIPELINE_CAST (element); + GstClock *clock; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_NULL: + break; + case GST_STATE_CHANGE_READY_TO_READY: + break; + case GST_STATE_CHANGE_PAUSED_TO_PAUSED: + break; + case GST_STATE_CHANGE_PLAYING_TO_PLAYING: + break; + case GST_STATE_CHANGE_NULL_TO_READY: + GST_OBJECT_LOCK (element); + if (element->bus) + gst_bus_set_flushing (element->bus, FALSE); + GST_OBJECT_UNLOCK (element); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_OBJECT_LOCK (element); + pipeline->priv->update_clock = TRUE; + GST_OBJECT_UNLOCK (element); + + /* READY to PAUSED starts running_time from 0 */ + reset_start_time (pipeline, 0); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + GstClockTime now, start_time, last_start_time, delay; + gboolean update_clock; + GstClock *cur_clock; + + GST_DEBUG_OBJECT (element, "selecting clock and base_time"); + + GST_OBJECT_LOCK (element); + cur_clock = element->clock; + if (cur_clock) + gst_object_ref (cur_clock); + /* get the desired running_time of the first buffer aka the start_time */ + start_time = GST_ELEMENT_START_TIME (pipeline); + last_start_time = pipeline->priv->last_start_time; + pipeline->priv->last_start_time = start_time; + /* see if we need to update the clock */ + update_clock = pipeline->priv->update_clock; + pipeline->priv->update_clock = FALSE; + delay = pipeline->delay; + GST_OBJECT_UNLOCK (element); + + /* running time changed, either with a PAUSED or a flush, we need to check + * if there is a new clock & update the base time */ + /* only do this for top-level, however */ + if (GST_OBJECT_PARENT (element) == NULL && + (update_clock || last_start_time != start_time)) { + GST_DEBUG_OBJECT (pipeline, "Need to update start_time"); + + /* when going to PLAYING, select a clock when needed. If we just got + * flushed, we don't reselect the clock. */ + if (update_clock) { + GST_DEBUG_OBJECT (pipeline, "Need to update clock."); + clock = gst_element_provide_clock (element); + } else { + GST_DEBUG_OBJECT (pipeline, + "Don't need to update clock, using old clock."); + /* only try to ref if cur_clock is not NULL */ + if (cur_clock) + gst_object_ref (cur_clock); + clock = cur_clock; + } + + if (clock) { + now = gst_clock_get_time (clock); + } else { + GST_DEBUG_OBJECT (pipeline, "no clock, using base time of NONE"); + now = GST_CLOCK_TIME_NONE; + } + + if (clock != cur_clock) { + /* now distribute the clock (which could be NULL). If some + * element refuses the clock, this will return FALSE and + * we effectively fail the state change. */ + if (!gst_element_set_clock (element, clock)) + goto invalid_clock; + + /* if we selected and distributed a new clock, let the app + * know about it */ + gst_element_post_message (element, + gst_message_new_new_clock (GST_OBJECT_CAST (element), clock)); + } + + if (clock) + gst_object_unref (clock); + + if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) { + GstClockTime new_base_time = now - start_time + delay; + GST_DEBUG_OBJECT (element, + "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT + ", base_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time), GST_TIME_ARGS (now), + GST_TIME_ARGS (new_base_time)); + + gst_element_set_base_time (element, new_base_time); + } else { + GST_DEBUG_OBJECT (pipeline, + "NOT adjusting base_time because start_time is NONE"); + } + } else { + GST_DEBUG_OBJECT (pipeline, + "NOT adjusting base_time because we selected one before"); + } + + if (cur_clock) + gst_object_unref (cur_clock); + break; + } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + /* we take a start_time snapshot before calling the children state changes + * so that they know about when the pipeline PAUSED. */ + pipeline_update_start_time (element); + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + reset_start_time (pipeline, 0); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_NULL: + break; + case GST_STATE_CHANGE_READY_TO_READY: + break; + case GST_STATE_CHANGE_PAUSED_TO_PAUSED: + break; + case GST_STATE_CHANGE_PLAYING_TO_PLAYING: + break; + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + /* Take a new snapshot of the start_time after calling the state change on + * all children. This will be the running_time of the pipeline when we go + * back to PLAYING */ + pipeline_update_start_time (element); + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + { + GstBus *bus; + gboolean auto_flush; + + /* grab some stuff before we release the lock to flush out the bus */ + GST_OBJECT_LOCK (element); + if ((bus = element->bus)) + gst_object_ref (bus); + auto_flush = pipeline->priv->auto_flush_bus; + GST_OBJECT_UNLOCK (element); + + if (bus) { + if (auto_flush) { + gst_bus_set_flushing (bus, TRUE); + } else { + GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled"); + } + gst_object_unref (bus); + } + break; + } + } + return result; + + /* ERRORS */ +invalid_clock: + { + /* we generate this error when the selected clock was not + * accepted by some element */ + GST_ELEMENT_ERROR (pipeline, CORE, CLOCK, + (_("Selected clock cannot be used in pipeline.")), + ("Pipeline cannot operate with selected clock")); + GST_DEBUG_OBJECT (pipeline, + "Pipeline cannot operate with selected clock %p", clock); + if (clock) + gst_object_unref (clock); + return GST_STATE_CHANGE_FAILURE; + } +} + +/* intercept the bus messages from our children. We watch for the ASYNC_START + * message with is posted by the elements (sinks) that require a reset of the + * running_time after a flush. ASYNC_START also brings the pipeline back into + * the PAUSED, pending PAUSED state. When the ASYNC_DONE message is received the + * pipeline will redistribute the new base_time and will bring the elements back + * to the desired state of the pipeline. */ +static void +gst_pipeline_handle_message (GstBin * bin, GstMessage * message) +{ + GstPipeline *pipeline = GST_PIPELINE_CAST (bin); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_RESET_TIME: + { + GstClockTime running_time; + + gst_message_parse_reset_time (message, &running_time); + + /* reset our running time if we need to distribute a new base_time to the + * children. */ + reset_start_time (pipeline, running_time); + break; + } + case GST_MESSAGE_CLOCK_LOST: + { + GstClock *clock; + + gst_message_parse_clock_lost (message, &clock); + + GST_OBJECT_LOCK (bin); + if (clock == GST_ELEMENT_CAST (bin)->clock) { + GST_DEBUG_OBJECT (bin, "Used clock '%s' got lost", + GST_OBJECT_NAME (clock)); + pipeline->priv->update_clock = TRUE; + } + GST_OBJECT_UNLOCK (bin); + } + default: + break; + } + GST_BIN_CLASS (parent_class)->handle_message (bin, message); +} + +static gboolean +gst_pipeline_do_latency (GstBin * bin) +{ + GstPipeline *pipeline = GST_PIPELINE (bin); + GstQuery *query; + GstClockTime latency; + GstClockTime min_latency, max_latency; + gboolean res; + + GST_OBJECT_LOCK (pipeline); + latency = pipeline->priv->latency; + GST_OBJECT_UNLOCK (pipeline); + + if (latency == GST_CLOCK_TIME_NONE) + return GST_BIN_CLASS (parent_class)->do_latency (bin); + + GST_DEBUG_OBJECT (pipeline, "querying latency"); + + query = gst_query_new_latency (); + if ((res = gst_element_query (GST_ELEMENT_CAST (pipeline), query))) { + gboolean live; + + gst_query_parse_latency (query, &live, &min_latency, &max_latency); + + GST_DEBUG_OBJECT (pipeline, + "got min latency %" GST_TIME_FORMAT ", max latency %" + GST_TIME_FORMAT ", live %d", GST_TIME_ARGS (min_latency), + GST_TIME_ARGS (max_latency), live); + + if (max_latency < min_latency) { + /* this is an impossible situation, some parts of the pipeline might not + * work correctly. We post a warning for now. */ + GST_ELEMENT_WARNING (pipeline, CORE, CLOCK, (NULL), + ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %" + GST_TIME_FORMAT ". Add queues or other buffering elements.", + GST_TIME_ARGS (max_latency), GST_TIME_ARGS (min_latency))); + } + + if (latency < min_latency) { + /* This is a problematic situation as we will most likely drop lots of + * data if we configure a too low latency */ + GST_ELEMENT_WARNING (pipeline, CORE, CLOCK, (NULL), + ("Configured latency is lower than detected minimum latency: configured %" + GST_TIME_FORMAT " < min %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency), GST_TIME_ARGS (min_latency))); + } + } else { + /* this is not a real problem, we just don't configure any latency. */ + GST_WARNING_OBJECT (pipeline, "failed to query latency"); + } + gst_query_unref (query); + + + /* configure latency on elements */ + res = + gst_element_send_event (GST_ELEMENT_CAST (pipeline), + gst_event_new_latency (latency)); + if (res) { + GST_INFO_OBJECT (pipeline, "configured latency of %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + } else { + GST_WARNING_OBJECT (pipeline, + "did not really configure latency of %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + } + + return res; +} + +/** + * gst_pipeline_get_bus: + * @pipeline: a #GstPipeline + * + * Gets the #GstBus of @pipeline. The bus allows applications to receive + * #GstMessage packets. + * + * Returns: (transfer full): a #GstBus, unref after usage. + * + * MT safe. + */ +GstBus * +gst_pipeline_get_bus (GstPipeline * pipeline) +{ + return gst_element_get_bus (GST_ELEMENT_CAST (pipeline)); +} + +static GstClock * +gst_pipeline_provide_clock_func (GstElement * element) +{ + GstClock *clock = NULL; + GstPipeline *pipeline = GST_PIPELINE (element); + + /* if we have a fixed clock, use that one */ + GST_OBJECT_LOCK (pipeline); + if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) { + clock = pipeline->fixed_clock; + if (clock) + gst_object_ref (clock); + GST_OBJECT_UNLOCK (pipeline); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", + clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); + } else { + GST_OBJECT_UNLOCK (pipeline); + /* let the parent bin select a clock */ + clock = + GST_ELEMENT_CLASS (parent_class)->provide_clock (GST_ELEMENT + (pipeline)); + /* no clock, use a system clock */ + if (!clock) { + clock = gst_system_clock_obtain (); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)", + clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)", + clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); + } + } + return clock; +} + +/** + * gst_pipeline_get_clock: (skip) + * @pipeline: a #GstPipeline + * + * Gets the current clock used by @pipeline. Users of object + * oriented languages should use gst_pipeline_get_pipeline_clock() + * to avoid confusion with gst_element_get_clock() which has a different behavior. + * + * Unlike gst_element_get_clock(), this function will always return a + * clock, even if the pipeline is not in the PLAYING state. + * + * Returns: (transfer full): a #GstClock, unref after usage. + */ +GstClock * +gst_pipeline_get_clock (GstPipeline * pipeline) +{ + return gst_pipeline_get_pipeline_clock (pipeline); +} + +/** + * gst_pipeline_get_pipeline_clock: + * @pipeline: a #GstPipeline + * + * Gets the current clock used by @pipeline. + * + * Unlike gst_element_get_clock(), this function will always return a + * clock, even if the pipeline is not in the PLAYING state. + * + * Returns: (transfer full): a #GstClock, unref after usage. + * + * Since: 1.6 + */ +GstClock * +gst_pipeline_get_pipeline_clock (GstPipeline * pipeline) +{ + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL); + + return gst_pipeline_provide_clock_func (GST_ELEMENT_CAST (pipeline)); +} + + +/** + * gst_pipeline_use_clock: + * @pipeline: a #GstPipeline + * @clock: (transfer none) (allow-none): the clock to use + * + * Force @pipeline to use the given @clock. The pipeline will + * always use the given clock even if new clock providers are added + * to this pipeline. + * + * If @clock is %NULL all clocking will be disabled which will make + * the pipeline run as fast as possible. + * + * MT safe. + */ +void +gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock) +{ + GstClock **clock_p; + + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + + GST_OBJECT_LOCK (pipeline); + GST_OBJECT_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK); + + clock_p = &pipeline->fixed_clock; + gst_object_replace ((GstObject **) clock_p, (GstObject *) clock); + GST_OBJECT_UNLOCK (pipeline); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock, + (clock ? GST_OBJECT_NAME (clock) : "nil")); +} + +/** + * gst_pipeline_set_clock: (skip) + * @pipeline: a #GstPipeline + * @clock: (transfer none): the clock to set + * + * Set the clock for @pipeline. The clock will be distributed + * to all the elements managed by the pipeline. + * + * Returns: %TRUE if the clock could be set on the pipeline. %FALSE if + * some element did not accept the clock. + * + * MT safe. + */ +gboolean +gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock) +{ + g_return_val_if_fail (pipeline != NULL, FALSE); + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE); + + return + GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT_CAST (pipeline), + clock); +} + +/** + * gst_pipeline_auto_clock: + * @pipeline: a #GstPipeline + * + * Let @pipeline select a clock automatically. This is the default + * behaviour. + * + * Use this function if you previous forced a fixed clock with + * gst_pipeline_use_clock() and want to restore the default + * pipeline clock selection algorithm. + * + * MT safe. + */ +void +gst_pipeline_auto_clock (GstPipeline * pipeline) +{ + GstClock **clock_p; + + g_return_if_fail (pipeline != NULL); + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + + GST_OBJECT_LOCK (pipeline); + GST_OBJECT_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK); + + clock_p = &pipeline->fixed_clock; + gst_object_replace ((GstObject **) clock_p, NULL); + GST_OBJECT_UNLOCK (pipeline); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock"); +} + +/** + * gst_pipeline_set_delay: + * @pipeline: a #GstPipeline + * @delay: the delay + * + * Set the expected delay needed for all elements to perform the + * PAUSED to PLAYING state change. @delay will be added to the + * base time of the elements so that they wait an additional @delay + * amount of time before starting to process buffers and cannot be + * #GST_CLOCK_TIME_NONE. + * + * This option is used for tuning purposes and should normally not be + * used. + * + * MT safe. + */ +void +gst_pipeline_set_delay (GstPipeline * pipeline, GstClockTime delay) +{ + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + g_return_if_fail (delay != GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (pipeline); + pipeline->delay = delay; + GST_OBJECT_UNLOCK (pipeline); +} + +/** + * gst_pipeline_get_delay: + * @pipeline: a #GstPipeline + * + * Get the configured delay (see gst_pipeline_set_delay()). + * + * Returns: The configured delay. + * + * MT safe. + */ +GstClockTime +gst_pipeline_get_delay (GstPipeline * pipeline) +{ + GstClockTime res; + + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (pipeline); + res = pipeline->delay; + GST_OBJECT_UNLOCK (pipeline); + + return res; +} + +/** + * gst_pipeline_set_auto_flush_bus: + * @pipeline: a #GstPipeline + * @auto_flush: whether or not to automatically flush the bus when + * the pipeline goes from READY to NULL state + * + * Usually, when a pipeline goes from READY to NULL state, it automatically + * flushes all pending messages on the bus, which is done for refcounting + * purposes, to break circular references. + * + * This means that applications that update state using (async) bus messages + * (e.g. do certain things when a pipeline goes from PAUSED to READY) might + * not get to see messages when the pipeline is shut down, because they might + * be flushed before they can be dispatched in the main thread. This behaviour + * can be disabled using this function. + * + * It is important that all messages on the bus are handled when the + * automatic flushing is disabled else memory leaks will be introduced. + * + * MT safe. + */ +void +gst_pipeline_set_auto_flush_bus (GstPipeline * pipeline, gboolean auto_flush) +{ + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + + GST_OBJECT_LOCK (pipeline); + pipeline->priv->auto_flush_bus = auto_flush; + GST_OBJECT_UNLOCK (pipeline); +} + +/** + * gst_pipeline_get_auto_flush_bus: + * @pipeline: a #GstPipeline + * + * Check if @pipeline will automatically flush messages when going to + * the NULL state. + * + * Returns: whether the pipeline will automatically flush its bus when + * going from READY to NULL state or not. + * + * MT safe. + */ +gboolean +gst_pipeline_get_auto_flush_bus (GstPipeline * pipeline) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE); + + GST_OBJECT_LOCK (pipeline); + res = pipeline->priv->auto_flush_bus; + GST_OBJECT_UNLOCK (pipeline); + + return res; +} + +/** + * gst_pipeline_set_latency: + * @pipeline: a #GstPipeline + * @latency: latency to configure + * + * Sets the latency that should be configured on the pipeline. Setting + * GST_CLOCK_TIME_NONE will restore the default behaviour of using the minimum + * latency from the LATENCY query. Setting this is usually not required and + * the pipeline will figure out an appropriate latency automatically. + * + * Setting a too low latency, especially lower than the minimum latency from + * the LATENCY query, will most likely cause the pipeline to fail. + * + * Since: 1.6 + */ +void +gst_pipeline_set_latency (GstPipeline * pipeline, GstClockTime latency) +{ + gboolean changed; + + g_return_if_fail (GST_IS_PIPELINE (pipeline)); + + GST_OBJECT_LOCK (pipeline); + changed = (pipeline->priv->latency != latency); + pipeline->priv->latency = latency; + GST_OBJECT_UNLOCK (pipeline); + + if (changed) + gst_bin_recalculate_latency (GST_BIN_CAST (pipeline)); +} + +/** + * gst_pipeline_get_latency: + * @pipeline: a #GstPipeline + * + * Gets the latency that should be configured on the pipeline. See + * gst_pipeline_set_latency(). + * + * Returns: Latency to configure on the pipeline or GST_CLOCK_TIME_NONE + * + * Since: 1.6 + */ + +GstClockTime +gst_pipeline_get_latency (GstPipeline * pipeline) +{ + GstClockTime latency; + + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (pipeline); + latency = pipeline->priv->latency; + GST_OBJECT_UNLOCK (pipeline); + + return latency; +} diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h new file mode 100644 index 0000000..ac0befb --- /dev/null +++ b/gst/gstpipeline.h @@ -0,0 +1,140 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpipeline.h: Header for GstPipeline 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_PIPELINE_H__ +#define __GST_PIPELINE_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PIPELINE (gst_pipeline_get_type ()) +#define GST_PIPELINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PIPELINE, GstPipeline)) +#define GST_IS_PIPELINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PIPELINE)) +#define GST_PIPELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PIPELINE, GstPipelineClass)) +#define GST_IS_PIPELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PIPELINE)) +#define GST_PIPELINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PIPELINE, GstPipelineClass)) +#define GST_PIPELINE_CAST(obj) ((GstPipeline*)(obj)) + +typedef struct _GstPipeline GstPipeline; +typedef struct _GstPipelineClass GstPipelineClass; +typedef struct _GstPipelinePrivate GstPipelinePrivate; + +/** + * GstPipelineFlags: + * @GST_PIPELINE_FLAG_FIXED_CLOCK: this pipeline works with a fixed clock + * @GST_PIPELINE_FLAG_LAST: offset to define more flags + * + * Pipeline flags + */ +typedef enum { + GST_PIPELINE_FLAG_FIXED_CLOCK = (GST_BIN_FLAG_LAST << 0), + /* padding */ + GST_PIPELINE_FLAG_LAST = (GST_BIN_FLAG_LAST << 4) +} GstPipelineFlags; + +/** + * GstPipeline: + * @fixed_clock: The fixed clock of the pipeline, used when + * GST_PIPELINE_FLAG_FIXED_CLOCK is set. + * @stream_time: The stream time of the pipeline. A better name for this + * property would be the running_time, the total time spent in the + * PLAYING state without being flushed. (deprecated, use the start_time + * on GstElement). + * @delay: Extra delay added to base_time to compensate for computing delays + * when setting elements to PLAYING. + * + * The #GstPipeline structure. + */ +struct _GstPipeline { + GstBin bin; + + /*< public >*/ /* with LOCK */ + GstClock *fixed_clock; + + GstClockTime stream_time; + GstClockTime delay; + + /*< private >*/ + GstPipelinePrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstPipelineClass { + GstBinClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_pipeline_get_type (void); + +GST_API +GstElement* gst_pipeline_new (const gchar *name) G_GNUC_MALLOC; + +GST_API +GstBus* gst_pipeline_get_bus (GstPipeline *pipeline); + +GST_API +void gst_pipeline_use_clock (GstPipeline *pipeline, GstClock *clock); + +GST_API +gboolean gst_pipeline_set_clock (GstPipeline *pipeline, GstClock *clock); + +GST_API +GstClock* gst_pipeline_get_clock (GstPipeline *pipeline); + +GST_API +GstClock* gst_pipeline_get_pipeline_clock (GstPipeline *pipeline); + +GST_API +void gst_pipeline_auto_clock (GstPipeline *pipeline); + +GST_API +void gst_pipeline_set_delay (GstPipeline *pipeline, GstClockTime delay); + +GST_API +GstClockTime gst_pipeline_get_delay (GstPipeline *pipeline); + +GST_API +void gst_pipeline_set_latency (GstPipeline *pipeline, GstClockTime latency); + +GST_API +GstClockTime gst_pipeline_get_latency (GstPipeline *pipeline); + +GST_API +void gst_pipeline_set_auto_flush_bus (GstPipeline *pipeline, gboolean auto_flush); + +GST_API +gboolean gst_pipeline_get_auto_flush_bus (GstPipeline *pipeline); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPipeline, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PIPELINE_H__ */ + diff --git a/gst/gstplugin.c b/gst/gstplugin.c new file mode 100644 index 0000000..6838afd --- /dev/null +++ b/gst/gstplugin.c @@ -0,0 +1,1937 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstplugin.c: Plugin subsystem for loading elements, types, and libs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstplugin + * @title: GstPlugin + * @short_description: Container for features loaded from a shared object module + * @see_also: #GstPluginFeature, #GstElementFactory + * + * GStreamer is extensible, so #GstElement instances can be loaded at runtime. + * A plugin system can provide one or more of the basic + * GStreamer #GstPluginFeature subclasses. + * + * A plugin should export a symbol gst_plugin_desc that is a + * struct of type #GstPluginDesc. + * the plugin loader will check the version of the core library the plugin was + * linked against and will create a new #GstPlugin. It will then call the + * #GstPluginInitFunc function that was provided in the + * gst_plugin_desc. + * + * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistry), you + * can add any object that subclasses #GstPluginFeature. + * + * Usually plugins are always automatically loaded so you don't need to call + * gst_plugin_load() explicitly to bring it into memory. There are options to + * statically link plugins to an app or even use GStreamer without a plugin + * repository in which case gst_plugin_load() can be needed to bring the plugin + * into memory. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include +#include +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include "glib-compat-private.h" + +#include + +#define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING + +static guint _num_static_plugins; /* 0 */ +static GstPluginDesc *_static_plugins; /* NULL */ +static gboolean _gst_plugin_inited; +static gchar **_plugin_loading_whitelist; /* NULL */ + +/* static variables for segfault handling of plugin loading */ +static char *_gst_plugin_fault_handler_filename = NULL; + +/* list of valid licenses. + * One of these must be specified or the plugin won't be loaded + * Please file a bug to request any additional license be added. + * + * GPL: http://www.gnu.org/copyleft/gpl.html + * LGPL: http://www.gnu.org/copyleft/lesser.html + * QPL: http://www.trolltech.com/licenses/qpl.html + * MPL: http://www.opensource.org/licenses/mozilla1.1.php + * MIT/X11: http://www.opensource.org/licenses/mit-license.php + * 3-clause BSD: http://www.opensource.org/licenses/bsd-license.php + */ +static const gchar valid_licenses[] = "LGPL\000" /* GNU Lesser General Public License */ + "GPL\000" /* GNU General Public License */ + "QPL\000" /* Trolltech Qt Public License */ + "GPL/QPL\000" /* Combi-license of GPL + QPL */ + "MPL\000" /* MPL 1.1 license */ + "BSD\000" /* 3-clause BSD license */ + "MIT/X11\000" /* MIT/X11 license */ + "Proprietary\000" /* Proprietary license */ + GST_LICENSE_UNKNOWN; /* some other license */ + +static const guint8 valid_licenses_idx[] = { 0, 5, 9, 13, 21, 25, 29, 37, 49 }; + +static GstPlugin *gst_plugin_register_func (GstPlugin * plugin, + const GstPluginDesc * desc, gpointer user_data); +static void gst_plugin_desc_copy (GstPluginDesc * dest, + const GstPluginDesc * src); + +static void gst_plugin_ext_dep_free (GstPluginDep * dep); + +G_DEFINE_TYPE (GstPlugin, gst_plugin, GST_TYPE_OBJECT); + +static void +gst_plugin_init (GstPlugin * plugin) +{ + plugin->priv = + G_TYPE_INSTANCE_GET_PRIVATE (plugin, GST_TYPE_PLUGIN, GstPluginPrivate); +} + +static void +gst_plugin_finalize (GObject * object) +{ + GstPlugin *plugin = GST_PLUGIN_CAST (object); + + GST_DEBUG ("finalizing plugin %" GST_PTR_FORMAT, plugin); + + /* FIXME: make registry add a weak ref instead */ +#if 0 + GstRegistry *registry = gst_registry_get (); + GList *g; + for (g = registry->plugins; g; g = g->next) { + if (g->data == (gpointer) plugin) { + g_warning ("removing plugin that is still in registry"); + } + } +#endif + + g_free (plugin->filename); + g_free (plugin->basename); + + g_list_foreach (plugin->priv->deps, (GFunc) gst_plugin_ext_dep_free, NULL); + g_list_free (plugin->priv->deps); + plugin->priv->deps = NULL; + + if (plugin->priv->cache_data) { + gst_structure_free (plugin->priv->cache_data); + } + + G_OBJECT_CLASS (gst_plugin_parent_class)->finalize (object); +} + +static void +gst_plugin_class_init (GstPluginClass * klass) +{ + G_OBJECT_CLASS (klass)->finalize = gst_plugin_finalize; + + g_type_class_add_private (klass, sizeof (GstPluginPrivate)); +} + +GQuark +gst_plugin_error_quark (void) +{ + static GQuark quark = 0; + + if (!quark) + quark = g_quark_from_static_string ("gst_plugin_error"); + return quark; +} + +/** + * gst_plugin_register_static: + * @major_version: the major version number of the GStreamer core that the + * plugin was compiled for, you can just use GST_VERSION_MAJOR here + * @minor_version: the minor version number of the GStreamer core that the + * plugin was compiled for, you can just use GST_VERSION_MINOR here + * @name: a unique name of the plugin (ideally prefixed with an application- or + * library-specific namespace prefix in order to avoid name conflicts in + * case a similar plugin with the same name ever gets added to GStreamer) + * @description: description of the plugin + * @init_func: (scope call): pointer to the init function of this plugin. + * @version: version string of the plugin + * @license: effective license of plugin. Must be one of the approved licenses + * (see #GstPluginDesc above) or the plugin will not be registered. + * @source: source module plugin belongs to + * @package: shipped package plugin belongs to + * @origin: URL to provider of plugin + * + * Registers a static plugin, ie. a plugin which is private to an application + * or library and contained within the application or library (as opposed to + * being shipped as a separate module file). + * + * You must make sure that GStreamer has been initialised (with gst_init() or + * via gst_init_get_option_group()) before calling this function. + * + * Returns: %TRUE if the plugin was registered correctly, otherwise %FALSE. + */ +gboolean +gst_plugin_register_static (gint major_version, gint minor_version, + const gchar * name, const gchar * description, GstPluginInitFunc init_func, + const gchar * version, const gchar * license, const gchar * source, + const gchar * package, const gchar * origin) +{ + GstPluginDesc desc = { major_version, minor_version, name, description, + init_func, version, license, source, package, origin, NULL, + }; + GstPlugin *plugin; + gboolean res = FALSE; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (description != NULL, FALSE); + g_return_val_if_fail (init_func != NULL, FALSE); + g_return_val_if_fail (version != NULL, FALSE); + g_return_val_if_fail (license != NULL, FALSE); + g_return_val_if_fail (source != NULL, FALSE); + g_return_val_if_fail (package != NULL, FALSE); + g_return_val_if_fail (origin != NULL, FALSE); + + /* make sure gst_init() has been called */ + g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE); + + GST_LOG ("attempting to load static plugin \"%s\" now...", name); + plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + if (gst_plugin_register_func (plugin, &desc, NULL) != NULL) { + GST_INFO ("registered static plugin \"%s\"", name); + res = gst_registry_add_plugin (gst_registry_get (), plugin); + GST_INFO ("added static plugin \"%s\", result: %d", name, res); + } + return res; +} + +/** + * gst_plugin_register_static_full: + * @major_version: the major version number of the GStreamer core that the + * plugin was compiled for, you can just use GST_VERSION_MAJOR here + * @minor_version: the minor version number of the GStreamer core that the + * plugin was compiled for, you can just use GST_VERSION_MINOR here + * @name: a unique name of the plugin (ideally prefixed with an application- or + * library-specific namespace prefix in order to avoid name conflicts in + * case a similar plugin with the same name ever gets added to GStreamer) + * @description: description of the plugin + * @init_full_func: (scope call): pointer to the init function with user data + * of this plugin. + * @version: version string of the plugin + * @license: effective license of plugin. Must be one of the approved licenses + * (see #GstPluginDesc above) or the plugin will not be registered. + * @source: source module plugin belongs to + * @package: shipped package plugin belongs to + * @origin: URL to provider of plugin + * @user_data: gpointer to user data + * + * Registers a static plugin, ie. a plugin which is private to an application + * or library and contained within the application or library (as opposed to + * being shipped as a separate module file) with a #GstPluginInitFullFunc + * which allows user data to be passed to the callback function (useful + * for bindings). + * + * You must make sure that GStreamer has been initialised (with gst_init() or + * via gst_init_get_option_group()) before calling this function. + * + * Returns: %TRUE if the plugin was registered correctly, otherwise %FALSE. + */ +gboolean +gst_plugin_register_static_full (gint major_version, gint minor_version, + const gchar * name, const gchar * description, + GstPluginInitFullFunc init_full_func, const gchar * version, + const gchar * license, const gchar * source, const gchar * package, + const gchar * origin, gpointer user_data) +{ + GstPluginDesc desc = { major_version, minor_version, name, description, + (GstPluginInitFunc) init_full_func, version, license, source, package, + origin, NULL, + }; + GstPlugin *plugin; + gboolean res = FALSE; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (description != NULL, FALSE); + g_return_val_if_fail (init_full_func != NULL, FALSE); + g_return_val_if_fail (version != NULL, FALSE); + g_return_val_if_fail (license != NULL, FALSE); + g_return_val_if_fail (source != NULL, FALSE); + g_return_val_if_fail (package != NULL, FALSE); + g_return_val_if_fail (origin != NULL, FALSE); + + /* make sure gst_init() has been called */ + g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE); + + GST_LOG ("attempting to load static plugin \"%s\" now...", name); + plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + if (gst_plugin_register_func (plugin, &desc, user_data) != NULL) { + GST_INFO ("registered static plugin \"%s\"", name); + res = gst_registry_add_plugin (gst_registry_get (), plugin); + GST_INFO ("added static plugin \"%s\", result: %d", name, res); + } + return res; +} + +void +_priv_gst_plugin_initialize (void) +{ + const gchar *whitelist; + guint i; + + _gst_plugin_inited = TRUE; + + whitelist = g_getenv ("GST_PLUGIN_LOADING_WHITELIST"); + if (whitelist != NULL && *whitelist != '\0') { + _plugin_loading_whitelist = g_strsplit (whitelist, + G_SEARCHPATH_SEPARATOR_S, -1); + for (i = 0; _plugin_loading_whitelist[i] != NULL; ++i) { + GST_INFO ("plugins whitelist entry: %s", _plugin_loading_whitelist[i]); + } + } + + /* now register all static plugins */ + GST_INFO ("registering %u static plugins", _num_static_plugins); + for (i = 0; i < _num_static_plugins; ++i) { + gst_plugin_register_static (_static_plugins[i].major_version, + _static_plugins[i].minor_version, _static_plugins[i].name, + _static_plugins[i].description, _static_plugins[i].plugin_init, + _static_plugins[i].version, _static_plugins[i].license, + _static_plugins[i].source, _static_plugins[i].package, + _static_plugins[i].origin); + } + + if (_static_plugins) { + free (_static_plugins); + _static_plugins = NULL; + _num_static_plugins = 0; + } +} + +/* Whitelist entry format: + * + * plugin1,plugin2@pathprefix or + * plugin1,plugin2@* or just + * plugin1,plugin2 or + * source-package@pathprefix or + * source-package@* or just + * source-package + * + * ie. the bit before the path will be checked against both the plugin + * name and the plugin's source package name, to keep the format simple. + */ +static gboolean +gst_plugin_desc_matches_whitelist_entry (const GstPluginDesc * desc, + const gchar * filename, const gchar * pattern) +{ + const gchar *sep; + gboolean ret = FALSE; + gchar *name; + + GST_LOG ("Whitelist pattern '%s', plugin: %s of %s@%s", pattern, desc->name, + desc->source, GST_STR_NULL (filename)); + + /* do we have a path prefix? */ + sep = strchr (pattern, '@'); + if (sep != NULL && strcmp (sep, "@*") != 0 && strcmp (sep, "@") != 0) { + /* paths are not canonicalised or treated with realpath() here. This + * should be good enough for our use case, since we just use the paths + * autotools uses, and those will be constructed from the same prefix. */ + if (filename != NULL && !g_str_has_prefix (filename, sep + 1)) + return FALSE; + + GST_LOG ("%s matches path prefix %s", GST_STR_NULL (filename), sep + 1); + } + + if (sep != NULL) { + name = g_strndup (pattern, (gsize) (sep - pattern)); + } else { + name = g_strdup (pattern); + } + + g_strstrip (name); + if (!g_ascii_isalnum (*name)) { + GST_WARNING ("Invalid whitelist pattern: %s", pattern); + goto done; + } + + /* now check plugin names / source package name */ + if (strchr (name, ',') == NULL) { + /* only a single name: either a plugin name or the source package name */ + ret = (strcmp (desc->source, name) == 0 || strcmp (desc->name, name) == 0); + } else { + gchar **n, **names; + + /* multiple names: assume these are plugin names */ + names = g_strsplit (name, ",", -1); + for (n = names; n != NULL && *n != NULL; ++n) { + g_strstrip (*n); + if (strcmp (desc->name, *n) == 0) { + ret = TRUE; + break; + } + } + g_strfreev (names); + } + + GST_LOG ("plugin / source package name match: %d", ret); + +done: + + g_free (name); + return ret; +} + +gboolean +priv_gst_plugin_desc_is_whitelisted (const GstPluginDesc * desc, + const gchar * filename) +{ + gchar **entry; + + if (_plugin_loading_whitelist == NULL) + return TRUE; + + for (entry = _plugin_loading_whitelist; *entry != NULL; ++entry) { + if (gst_plugin_desc_matches_whitelist_entry (desc, filename, *entry)) { + GST_LOG ("Plugin %s is in whitelist", filename); + return TRUE; + } + } + + GST_LOG ("Plugin %s (package %s, file %s) not in whitelist", desc->name, + desc->source, filename); + return FALSE; +} + +gboolean +priv_gst_plugin_loading_have_whitelist (void) +{ + return (_plugin_loading_whitelist != NULL); +} + +guint32 +priv_gst_plugin_loading_get_whitelist_hash (void) +{ + guint32 hash = 0; + + if (_plugin_loading_whitelist != NULL) { + gchar **w; + + for (w = _plugin_loading_whitelist; *w != NULL; ++w) + hash ^= g_str_hash (*w); + } + + return hash; +} + +/* this function could be extended to check if the plugin license matches the + * applications license (would require the app to register its license somehow). + * We'll wait for someone who's interested in it to code it :) + */ +static gboolean +gst_plugin_check_license (const gchar * license) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (valid_licenses_idx); ++i) { + if (strcmp (license, valid_licenses + valid_licenses_idx[i]) == 0) + return TRUE; + } + return FALSE; +} + +static gboolean +gst_plugin_check_version (gint major, gint minor) +{ + /* return NULL if the major and minor version numbers are not compatible */ + /* with ours. */ + if (major != GST_VERSION_MAJOR || minor > GST_VERSION_MINOR) + return FALSE; + + return TRUE; +} + +static GstPlugin * +gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc, + gpointer user_data) +{ + if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) { + if (GST_CAT_DEFAULT) + GST_WARNING ("plugin \"%s\" has incompatible version " + "(plugin: %d.%d, gst: %d,%d), not loading", + GST_STR_NULL (plugin->filename), desc->major_version, + desc->minor_version, GST_VERSION_MAJOR, GST_VERSION_MINOR); + return NULL; + } + + if (!desc->license || !desc->description || !desc->source || + !desc->package || !desc->origin) { + if (GST_CAT_DEFAULT) + GST_WARNING ("plugin \"%s\" has missing detail in GstPluginDesc, not " + "loading", GST_STR_NULL (plugin->filename)); + return NULL; + } + + if (!gst_plugin_check_license (desc->license)) { + if (GST_CAT_DEFAULT) + GST_WARNING ("plugin \"%s\" has invalid license \"%s\", not loading", + GST_STR_NULL (plugin->filename), desc->license); + return NULL; + } + + if (GST_CAT_DEFAULT) + GST_LOG ("plugin \"%s\" looks good", GST_STR_NULL (plugin->filename)); + + gst_plugin_desc_copy (&plugin->desc, desc); + + /* make resident so we're really sure it never gets unloaded again. + * Theoretically this is not needed, but practically it doesn't hurt. + * And we're rather safe than sorry. */ + if (plugin->module) + g_module_make_resident (plugin->module); + + if (user_data) { + if (!(((GstPluginInitFullFunc) (desc->plugin_init)) (plugin, user_data))) { + if (GST_CAT_DEFAULT) + GST_WARNING ("plugin \"%s\" failed to initialise", + GST_STR_NULL (plugin->filename)); + return NULL; + } + } else { + if (!((desc->plugin_init) (plugin))) { + if (GST_CAT_DEFAULT) + GST_WARNING ("plugin \"%s\" failed to initialise", + GST_STR_NULL (plugin->filename)); + return NULL; + } + } + + if (GST_CAT_DEFAULT) + GST_LOG ("plugin \"%s\" initialised", GST_STR_NULL (plugin->filename)); + + return plugin; +} + +#ifdef HAVE_SIGACTION +static struct sigaction oldaction; +static gboolean _gst_plugin_fault_handler_is_setup = FALSE; + +/* + * _gst_plugin_fault_handler_restore: + * segfault handler restorer + */ +static void +_gst_plugin_fault_handler_restore (void) +{ + if (!_gst_plugin_fault_handler_is_setup) + return; + + _gst_plugin_fault_handler_is_setup = FALSE; + + sigaction (SIGSEGV, &oldaction, NULL); +} + +/* + * _gst_plugin_fault_handler_sighandler: + * segfault handler implementation + */ +static void +_gst_plugin_fault_handler_sighandler (int signum) +{ + /* We need to restore the fault handler or we'll keep getting it */ + _gst_plugin_fault_handler_restore (); + + switch (signum) { + case SIGSEGV: + g_print ("\nERROR: "); + g_print ("Caught a segmentation fault while loading plugin file:\n"); + g_print ("%s\n\n", _gst_plugin_fault_handler_filename); + g_print ("Please either:\n"); + g_print ("- remove it and restart.\n"); + g_print + ("- run with --gst-disable-segtrap --gst-disable-registry-fork and debug.\n"); + exit (-1); + break; + default: + g_print ("Caught unhandled signal on plugin loading\n"); + break; + } +} + +/* + * _gst_plugin_fault_handler_setup: + * sets up the segfault handler + */ +static void +_gst_plugin_fault_handler_setup (void) +{ + struct sigaction action; + + /* if asked to leave segfaults alone, just return */ + if (!gst_segtrap_is_enabled ()) + return; + + if (_gst_plugin_fault_handler_is_setup) + return; + + _gst_plugin_fault_handler_is_setup = TRUE; + + memset (&action, 0, sizeof (action)); + action.sa_handler = _gst_plugin_fault_handler_sighandler; + + sigaction (SIGSEGV, &action, &oldaction); +} +#else /* !HAVE_SIGACTION */ +static void +_gst_plugin_fault_handler_restore (void) +{ +} + +static void +_gst_plugin_fault_handler_setup (void) +{ +} +#endif /* HAVE_SIGACTION */ + +/* g_time_val_from_iso8601() doesn't do quite what we want */ +static gboolean +check_release_datetime (const gchar * date_time) +{ + guint64 val; + + /* we require YYYY-MM-DD or YYYY-MM-DDTHH:MMZ format */ + if (!g_ascii_isdigit (*date_time)) + return FALSE; + + val = g_ascii_strtoull (date_time, (gchar **) & date_time, 10); + if (val < 2000 || val > 2100 || *date_time != '-') + return FALSE; + + val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10); + if (val == 0 || val > 12 || *date_time != '-') + return FALSE; + + val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10); + if (val == 0 || val > 32) + return FALSE; + + /* end of string or date/time separator + HH:MMZ */ + if (*date_time == 'T' || *date_time == ' ') { + val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10); + if (val > 24 || *date_time != ':') + return FALSE; + + val = g_ascii_strtoull (date_time + 1, (gchar **) & date_time, 10); + if (val > 59 || *date_time != 'Z') + return FALSE; + + ++date_time; + } + + return (*date_time == '\0'); +} + +static GMutex gst_plugin_loading_mutex; + +#define CHECK_PLUGIN_DESC_FIELD(desc,field,fn) \ + if (G_UNLIKELY ((desc)->field == NULL || *(desc)->field == '\0')) { \ + g_warning ("Plugin description for '%s' has no valid %s field", fn, G_STRINGIFY (field)); \ + g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, \ + "Plugin %s has invalid plugin description field '%s'", \ + filename, G_STRINGIFY (field)); \ + goto return_error; \ + } + +/** + * gst_plugin_load_file: + * @filename: (type filename): the plugin filename to load + * @error: pointer to a %NULL-valued GError + * + * Loads the given plugin and refs it. Caller needs to unref after use. + * + * Returns: (transfer full): a reference to the existing loaded GstPlugin, a + * reference to the newly-loaded GstPlugin, or %NULL if an error occurred. + */ +GstPlugin * +gst_plugin_load_file (const gchar * filename, GError ** error) +{ + return _priv_gst_plugin_load_file_for_registry (filename, NULL, error); +} + +static gchar * +extract_symname (const char *filename) +{ + gchar *bname, *name, *symname; + const gchar *dot; + gsize prefix_len, len; + int i; + + bname = g_path_get_basename (filename); + for (i = 0; bname[i]; ++i) { + if (bname[i] == '-') + bname[i] = '_'; + } + + if (g_str_has_prefix (bname, "libgst")) + prefix_len = 6; + else if (g_str_has_prefix (bname, "lib")) + prefix_len = 3; + else if (g_str_has_prefix (bname, "gst")) + prefix_len = 3; + else + prefix_len = 0; /* use whole name (minus suffix) as plugin name */ + + dot = g_utf8_strchr (bname, -1, '.'); + if (dot) + len = dot - bname - prefix_len; + else + len = strlen (bname + prefix_len); + + name = g_strndup (bname + prefix_len, len); + g_free (bname); + + symname = g_strconcat ("gst_plugin_", name, "_get_desc", NULL); + g_free (name); + + return symname; +} + +/* Note: The return value is (transfer full) although we work with floating + * references here. If a new plugin instance is created, it is always sinked + * in the registry first and a new reference is returned + */ +GstPlugin * +_priv_gst_plugin_load_file_for_registry (const gchar * filename, + GstRegistry * registry, GError ** error) +{ + const GstPluginDesc *desc; + GstPlugin *plugin; + gchar *symname; + GModule *module; + gboolean ret; + gpointer ptr; + GStatBuf file_status; + gboolean new_plugin = TRUE; + GModuleFlags flags; + + g_return_val_if_fail (filename != NULL, NULL); + + if (registry == NULL) + registry = gst_registry_get (); + + g_mutex_lock (&gst_plugin_loading_mutex); + + plugin = gst_registry_lookup (registry, filename); + if (plugin) { + if (plugin->module) { + /* already loaded */ + g_mutex_unlock (&gst_plugin_loading_mutex); + return plugin; + } else { + /* load plugin and update fields */ + new_plugin = FALSE; + } + } + + GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "attempt to load plugin \"%s\"", + filename); + + if (!g_module_supported ()) { + GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "module loading not supported"); + g_set_error (error, + GST_PLUGIN_ERROR, + GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported"); + goto return_error; + } + + if (g_stat (filename, &file_status)) { + GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "problem accessing file"); + g_set_error (error, + GST_PLUGIN_ERROR, + GST_PLUGIN_ERROR_MODULE, "Problem accessing file %s: %s", filename, + g_strerror (errno)); + goto return_error; + } + + flags = G_MODULE_BIND_LOCAL; + /* libgstpython.so is the gst-python plugin loader. It needs to be loaded with + * G_MODULE_BIND_LAZY. + * + * Ideally there should be a generic way for plugins to specify that they + * need to be loaded with _LAZY. + * */ + if (strstr (filename, "libgstpython")) + flags |= G_MODULE_BIND_LAZY; + + module = g_module_open (filename, flags); + if (module == NULL) { + GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "module_open failed: %s", + g_module_error ()); + g_set_error (error, + GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Opening module failed: %s", + g_module_error ()); + /* If we failed to open the shared object, then it's probably because a + * plugin is linked against the wrong libraries. Print out an easy-to-see + * message in this case. */ + g_warning ("Failed to load plugin '%s': %s", filename, g_module_error ()); + goto return_error; + } + + symname = extract_symname (filename); + ret = g_module_symbol (module, symname, &ptr); + + if (ret) { + GstPluginDesc *(*get_desc) (void) = ptr; + ptr = get_desc (); + } else { + GST_DEBUG ("Could not find symbol '%s', falling back to gst_plugin_desc", + symname); + ret = g_module_symbol (module, "gst_plugin_desc", &ptr); + } + + g_free (symname); + + if (!ret) { + GST_DEBUG ("Could not find plugin entry point in \"%s\"", filename); + g_set_error (error, + GST_PLUGIN_ERROR, + GST_PLUGIN_ERROR_MODULE, + "File \"%s\" is not a GStreamer plugin", filename); + g_module_close (module); + goto return_error; + } + + desc = (const GstPluginDesc *) ptr; + + if (priv_gst_plugin_loading_have_whitelist () && + !priv_gst_plugin_desc_is_whitelisted (desc, filename)) { + GST_INFO ("Whitelist specified and plugin not in whitelist, not loading: " + "name=%s, package=%s, file=%s", desc->name, desc->source, filename); + g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, + "Not loading plugin file \"%s\", not in whitelist", filename); + g_module_close (module); + goto return_error; + } + + if (new_plugin) { + plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + plugin->file_mtime = file_status.st_mtime; + plugin->file_size = file_status.st_size; + plugin->filename = g_strdup (filename); + plugin->basename = g_path_get_basename (filename); + } + + plugin->module = module; + + if (new_plugin) { + /* check plugin description: complain about bad values and fail */ + CHECK_PLUGIN_DESC_FIELD (desc, name, filename); + CHECK_PLUGIN_DESC_FIELD (desc, description, filename); + CHECK_PLUGIN_DESC_FIELD (desc, version, filename); + CHECK_PLUGIN_DESC_FIELD (desc, license, filename); + CHECK_PLUGIN_DESC_FIELD (desc, source, filename); + CHECK_PLUGIN_DESC_FIELD (desc, package, filename); + CHECK_PLUGIN_DESC_FIELD (desc, origin, filename); + + if (desc->name != NULL && desc->name[0] == '"') { + g_warning ("Invalid plugin name '%s' - fix your GST_PLUGIN_DEFINE " + "(remove quotes around plugin name)", desc->name); + } + + if (desc->release_datetime != NULL && + !check_release_datetime (desc->release_datetime)) { + g_warning ("GstPluginDesc for '%s' has invalid datetime '%s'", + filename, desc->release_datetime); + g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, + "Plugin %s has invalid plugin description field 'release_datetime'", + filename); + goto return_error; + } + } + + GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...", + plugin, filename); + + /* this is where we load the actual .so, so let's trap SIGSEGV */ + _gst_plugin_fault_handler_setup (); + _gst_plugin_fault_handler_filename = plugin->filename; + + GST_LOG ("Plugin %p for file \"%s\" prepared, registering...", + plugin, filename); + + if (!gst_plugin_register_func (plugin, desc, NULL)) { + /* remove signal handler */ + _gst_plugin_fault_handler_restore (); + GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename); + /* plugin == NULL */ + g_set_error (error, + GST_PLUGIN_ERROR, + GST_PLUGIN_ERROR_MODULE, + "File \"%s\" appears to be a GStreamer plugin, but it failed to initialize", + filename); + goto return_error; + } + + /* remove signal handler */ + _gst_plugin_fault_handler_restore (); + _gst_plugin_fault_handler_filename = NULL; + GST_INFO ("plugin \"%s\" loaded", plugin->filename); + + if (new_plugin) { + gst_object_ref (plugin); + gst_registry_add_plugin (registry, plugin); + } + + g_mutex_unlock (&gst_plugin_loading_mutex); + return plugin; + +return_error: + { + if (plugin) + gst_object_unref (plugin); + g_mutex_unlock (&gst_plugin_loading_mutex); + return NULL; + } +} + +static void +gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src) +{ + dest->major_version = src->major_version; + dest->minor_version = src->minor_version; + dest->name = g_intern_string (src->name); + dest->description = g_intern_string (src->description); + dest->plugin_init = src->plugin_init; + dest->version = g_intern_string (src->version); + dest->license = g_intern_string (src->license); + dest->source = g_intern_string (src->source); + dest->package = g_intern_string (src->package); + dest->origin = g_intern_string (src->origin); + dest->release_datetime = g_intern_string (src->release_datetime); +} + +/** + * gst_plugin_get_name: + * @plugin: plugin to get the name of + * + * Get the short name of the plugin + * + * Returns: the name of the plugin + */ +const gchar * +gst_plugin_get_name (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.name; +} + +/** + * gst_plugin_get_description: + * @plugin: plugin to get long name of + * + * Get the long descriptive name of the plugin + * + * Returns: the long name of the plugin + */ +const gchar * +gst_plugin_get_description (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.description; +} + +/** + * gst_plugin_get_filename: + * @plugin: plugin to get the filename of + * + * get the filename of the plugin + * + * Returns: (type filename): the filename of the plugin + */ +const gchar * +gst_plugin_get_filename (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->filename; +} + +/** + * gst_plugin_get_version: + * @plugin: plugin to get the version of + * + * get the version of the plugin + * + * Returns: the version of the plugin + */ +const gchar * +gst_plugin_get_version (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.version; +} + +/** + * gst_plugin_get_license: + * @plugin: plugin to get the license of + * + * get the license of the plugin + * + * Returns: the license of the plugin + */ +const gchar * +gst_plugin_get_license (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.license; +} + +/** + * gst_plugin_get_source: + * @plugin: plugin to get the source of + * + * get the source module the plugin belongs to. + * + * Returns: the source of the plugin + */ +const gchar * +gst_plugin_get_source (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.source; +} + +/** + * gst_plugin_get_package: + * @plugin: plugin to get the package of + * + * get the package the plugin belongs to. + * + * Returns: the package of the plugin + */ +const gchar * +gst_plugin_get_package (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.package; +} + +/** + * gst_plugin_get_origin: + * @plugin: plugin to get the origin of + * + * get the URL where the plugin comes from + * + * Returns: the origin of the plugin + */ +const gchar * +gst_plugin_get_origin (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.origin; +} + +/** + * gst_plugin_get_release_date_string: + * @plugin: plugin to get the release date of + * + * Get the release date (and possibly time) in form of a string, if available. + * + * For normal GStreamer plugin releases this will usually just be a date in + * the form of "YYYY-MM-DD", while pre-releases and builds from git may contain + * a time component after the date as well, in which case the string will be + * formatted like "YYYY-MM-DDTHH:MMZ" (e.g. "2012-04-30T09:30Z"). + * + * There may be plugins that do not have a valid release date set on them. + * + * Returns: (nullable): the date string of the plugin, or %NULL if not + * available. + */ +const gchar * +gst_plugin_get_release_date_string (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, NULL); + + return plugin->desc.release_datetime; +} + +/** + * gst_plugin_is_loaded: + * @plugin: plugin to query + * + * queries if the plugin is loaded into memory + * + * Returns: %TRUE is loaded, %FALSE otherwise + */ +gboolean +gst_plugin_is_loaded (GstPlugin * plugin) +{ + g_return_val_if_fail (plugin != NULL, FALSE); + + return (plugin->module != NULL || plugin->filename == NULL); +} + +/** + * gst_plugin_get_cache_data: + * @plugin: a plugin + * + * Gets the plugin specific data cache. If it is %NULL there is no cached data + * stored. This is the case when the registry is getting rebuilt. + * + * Returns: (transfer none) (nullable): The cached data as a + * #GstStructure or %NULL. + */ +const GstStructure * +gst_plugin_get_cache_data (GstPlugin * plugin) +{ + g_return_val_if_fail (GST_IS_PLUGIN (plugin), NULL); + + return plugin->priv->cache_data; +} + +/** + * gst_plugin_set_cache_data: + * @plugin: a plugin + * @cache_data: (transfer full): a structure containing the data to cache + * + * Adds plugin specific data to cache. Passes the ownership of the structure to + * the @plugin. + * + * The cache is flushed every time the registry is rebuilt. + */ +void +gst_plugin_set_cache_data (GstPlugin * plugin, GstStructure * cache_data) +{ + g_return_if_fail (GST_IS_PLUGIN (plugin)); + g_return_if_fail (GST_IS_STRUCTURE (cache_data)); + + if (plugin->priv->cache_data) { + gst_structure_free (plugin->priv->cache_data); + } + plugin->priv->cache_data = cache_data; +} + +#if 0 +/** + * gst_plugin_feature_list: + * @plugin: plugin to query + * @filter: the filter to use + * @first: only return first match + * @user_data: user data passed to the filter function + * + * Runs a filter against all plugin features and returns a GList with + * the results. If the first flag is set, only the first match is + * returned (as a list with a single object). + * + * Returns: a GList of features, g_list_free after use. + */ +GList * +gst_plugin_feature_filter (GstPlugin * plugin, + GstPluginFeatureFilter filter, gboolean first, gpointer user_data) +{ + GList *list; + GList *g; + + list = gst_filter_run (plugin->features, (GstFilterFunc) filter, first, + user_data); + for (g = list; g; g = g->next) { + gst_object_ref (plugin); + } + + return list; +} + +typedef struct +{ + GstPluginFeatureFilter filter; + gboolean first; + gpointer user_data; + GList *result; +} +FeatureFilterData; + +static gboolean +_feature_filter (GstPlugin * plugin, gpointer user_data) +{ + GList *result; + FeatureFilterData *data = (FeatureFilterData *) user_data; + + result = gst_plugin_feature_filter (plugin, data->filter, data->first, + data->user_data); + if (result) { + data->result = g_list_concat (data->result, result); + return TRUE; + } + return FALSE; +} + +/** + * gst_plugin_list_feature_filter: + * @list: a #GList of plugins to query + * @filter: the filter function to use + * @first: only return first match + * @user_data: user data passed to the filter function + * + * Runs a filter against all plugin features of the plugins in the given + * list and returns a GList with the results. + * If the first flag is set, only the first match is + * returned (as a list with a single object). + * + * Returns: a GList of features, g_list_free after use. + */ +GList * +gst_plugin_list_feature_filter (GList * list, + GstPluginFeatureFilter filter, gboolean first, gpointer user_data) +{ + FeatureFilterData data; + GList *result; + + data.filter = filter; + data.first = first; + data.user_data = user_data; + data.result = NULL; + + result = gst_filter_run (list, (GstFilterFunc) _feature_filter, first, &data); + g_list_free (result); + + return data.result; +} + +/** + * gst_plugin_find_feature: + * @plugin: plugin to get the feature from + * @name: The name of the feature to find + * @type: The type of the feature to find + * + * Find a feature of the given name and type in the given plugin. + * + * Returns: a GstPluginFeature or %NULL if the feature was not found. + */ +GstPluginFeature * +gst_plugin_find_feature (GstPlugin * plugin, const gchar * name, GType type) +{ + GList *walk; + GstPluginFeature *result = NULL; + GstTypeNameData data; + + g_return_val_if_fail (name != NULL, NULL); + + data.type = type; + data.name = name; + + walk = gst_filter_run (plugin->features, + (GstFilterFunc) gst_plugin_feature_type_name_filter, TRUE, &data); + + if (walk) { + result = GST_PLUGIN_FEATURE (walk->data); + + gst_object_ref (result); + gst_plugin_feature_list_free (walk); + } + + return result; +} +#endif + +#if 0 +static gboolean +gst_plugin_feature_name_filter (GstPluginFeature * feature, const gchar * name) +{ + return !strcmp (name, GST_PLUGIN_FEATURE_NAME (feature)); +} +#endif + +#if 0 +/** + * gst_plugin_find_feature_by_name: + * @plugin: plugin to get the feature from + * @name: The name of the feature to find + * + * Find a feature of the given name in the given plugin. + * + * Returns: a GstPluginFeature or %NULL if the feature was not found. + */ +GstPluginFeature * +gst_plugin_find_feature_by_name (GstPlugin * plugin, const gchar * name) +{ + GList *walk; + GstPluginFeature *result = NULL; + + g_return_val_if_fail (name != NULL, NULL); + + walk = gst_filter_run (plugin->features, + (GstFilterFunc) gst_plugin_feature_name_filter, TRUE, (void *) name); + + if (walk) { + result = GST_PLUGIN_FEATURE (walk->data); + + gst_object_ref (result); + gst_plugin_feature_list_free (walk); + } + + return result; +} +#endif + +/** + * gst_plugin_load_by_name: + * @name: name of plugin to load + * + * Load the named plugin. Refs the plugin. + * + * Returns: (transfer full) (nullable): a reference to a loaded plugin, or + * %NULL on error. + */ +GstPlugin * +gst_plugin_load_by_name (const gchar * name) +{ + GstPlugin *plugin, *newplugin; + GError *error = NULL; + + GST_DEBUG ("looking up plugin %s in default registry", name); + plugin = gst_registry_find_plugin (gst_registry_get (), name); + if (plugin) { + GST_DEBUG ("loading plugin %s from file %s", name, plugin->filename); + newplugin = gst_plugin_load_file (plugin->filename, &error); + gst_object_unref (plugin); + + if (!newplugin) { + GST_WARNING ("load_plugin error: %s", error->message); + g_error_free (error); + return NULL; + } + /* newplugin was reffed by load_file */ + return newplugin; + } + + GST_DEBUG ("Could not find plugin %s in registry", name); + return NULL; +} + +/** + * gst_plugin_load: + * @plugin: (transfer none): plugin to load + * + * Loads @plugin. Note that the *return value* is the loaded plugin; @plugin is + * untouched. The normal use pattern of this function goes like this: + * + * |[ + * GstPlugin *loaded_plugin; + * loaded_plugin = gst_plugin_load (plugin); + * // presumably, we're no longer interested in the potentially-unloaded plugin + * gst_object_unref (plugin); + * plugin = loaded_plugin; + * ]| + * + * Returns: (transfer full) (nullable): a reference to a loaded plugin, or + * %NULL on error. + */ +GstPlugin * +gst_plugin_load (GstPlugin * plugin) +{ + GError *error = NULL; + GstPlugin *newplugin; + + if (gst_plugin_is_loaded (plugin)) { + return gst_object_ref (plugin); + } + + if (!(newplugin = gst_plugin_load_file (plugin->filename, &error))) + goto load_error; + + return newplugin; + +load_error: + { + GST_WARNING ("load_plugin error: %s", error->message); + g_error_free (error); + return NULL; + } +} + +/** + * gst_plugin_list_free: + * @list: (transfer full) (element-type Gst.Plugin): list of #GstPlugin + * + * Unrefs each member of @list, then frees the list. + */ +void +gst_plugin_list_free (GList * list) +{ + GList *g; + + for (g = list; g; g = g->next) { + gst_object_unref (GST_PLUGIN_CAST (g->data)); + } + g_list_free (list); +} + +/* ===== plugin dependencies ===== */ + +/* Scenarios: + * ENV + xyz where ENV can contain multiple values separated by SEPARATOR + * xyz may be "" (if ENV contains path to file rather than dir) + * ENV + *xyz same as above, but xyz acts as suffix filter + * ENV + xyz* same as above, but xyz acts as prefix filter (is this needed?) + * ENV + *xyz* same as above, but xyz acts as strstr filter (is this needed?) + * + * same as above, with additional paths hard-coded at compile-time: + * - only check paths + ... if ENV is not set or yields not paths + * - always check paths + ... in addition to ENV + * + * When user specifies set of environment variables, he/she may also use e.g. + * "HOME/.mystuff/plugins", and we'll expand the content of $HOME with the + * remainder + */ + +/* we store in registry: + * sets of: + * { + * - environment variables (array of strings) + * - last hash of env variable contents (uint) (so we can avoid doing stats + * if one of the env vars has changed; premature optimisation galore) + * - hard-coded paths (array of strings) + * - xyz filename/suffix/prefix strings (array of strings) + * - flags (int) + * - last hash of file/dir stats (int) + * } + * (= struct GstPluginDep) + */ + +static guint +gst_plugin_ext_dep_get_env_vars_hash (GstPlugin * plugin, GstPluginDep * dep) +{ + gchar **e; + guint hash; + + /* there's no deeper logic to what we do here; all we want to know (when + * checking if the plugin needs to be rescanned) is whether the content of + * one of the environment variables in the list is different from when it + * was last scanned */ + hash = 0; + for (e = dep->env_vars; e != NULL && *e != NULL; ++e) { + const gchar *val; + gchar env_var[256]; + + /* order matters: "val",NULL needs to yield a different hash than + * NULL,"val", so do a shift here whether the var is set or not */ + hash = hash << 5; + + /* want environment variable at beginning of string */ + if (!g_ascii_isalnum (**e)) { + GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment " + "variable string: %s", *e); + continue; + } + + /* user is allowed to specify e.g. "HOME/.pitivi/plugins" */ + g_strlcpy (env_var, *e, sizeof (env_var)); + g_strdelimit (env_var, "/\\", '\0'); + + if ((val = g_getenv (env_var))) + hash += g_str_hash (val); + } + + return hash; +} + +gboolean +_priv_plugin_deps_env_vars_changed (GstPlugin * plugin) +{ + GList *l; + + for (l = plugin->priv->deps; l != NULL; l = l->next) { + GstPluginDep *dep = l->data; + + if (dep->env_hash != gst_plugin_ext_dep_get_env_vars_hash (plugin, dep)) + return TRUE; + } + + return FALSE; +} + +static void +gst_plugin_ext_dep_extract_env_vars_paths (GstPlugin * plugin, + GstPluginDep * dep, GQueue * paths) +{ + gchar **evars; + + for (evars = dep->env_vars; evars != NULL && *evars != NULL; ++evars) { + const gchar *e; + gchar **components; + + /* want environment variable at beginning of string */ + if (!g_ascii_isalnum (**evars)) { + GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment " + "variable string: %s", *evars); + continue; + } + + /* user is allowed to specify e.g. "HOME/.pitivi/plugins", which we want to + * split into the env_var name component and the path component */ + components = g_strsplit_set (*evars, "/\\", 2); + g_assert (components != NULL); + + e = g_getenv (components[0]); + GST_LOG_OBJECT (plugin, "expanding %s = '%s' (path suffix: %s)", + components[0], GST_STR_NULL (e), GST_STR_NULL (components[1])); + + if (components[1] != NULL) { + g_strdelimit (components[1], "/\\", G_DIR_SEPARATOR); + } + + if (e != NULL && *e != '\0') { + gchar **arr; + guint i; + + arr = g_strsplit (e, G_SEARCHPATH_SEPARATOR_S, -1); + + for (i = 0; arr != NULL && arr[i] != NULL; ++i) { + gchar *full_path; + + if (!g_path_is_absolute (arr[i])) { + GST_INFO_OBJECT (plugin, "ignoring environment variable content '%s'" + ": either not an absolute path or not a path at all", arr[i]); + continue; + } + + if (components[1] != NULL) { + full_path = g_build_filename (arr[i], components[1], NULL); + } else { + full_path = g_strdup (arr[i]); + } + + if (!g_queue_find_custom (paths, full_path, (GCompareFunc) strcmp)) { + GST_LOG_OBJECT (plugin, "path: '%s'", full_path); + g_queue_push_tail (paths, full_path); + full_path = NULL; + } else { + GST_LOG_OBJECT (plugin, "path: '%s' (duplicate,ignoring)", full_path); + g_free (full_path); + } + } + + g_strfreev (arr); + } + + g_strfreev (components); + } + + GST_LOG_OBJECT (plugin, "Extracted %d paths from environment", paths->length); +} + +static guint +gst_plugin_ext_dep_get_hash_from_stat_entry (GStatBuf * s) +{ +#ifdef S_IFBLK + if (!(s->st_mode & (S_IFDIR | S_IFREG | S_IFBLK | S_IFCHR))) +#else + /* MSVC does not have S_IFBLK */ + if (!(s->st_mode & (S_IFDIR | S_IFREG | S_IFCHR))) +#endif + return (guint) - 1; + + /* completely random formula */ + return ((s->st_size << 3) + (s->st_mtime << 5)) ^ s->st_ctime; +} + +static gboolean +gst_plugin_ext_dep_direntry_matches (GstPlugin * plugin, const gchar * entry, + const gchar ** filenames, GstPluginDependencyFlags flags) +{ + /* no filenames specified, match all entries for now (could probably + * optimise by just taking the dir stat hash or so) */ + if (filenames == NULL || *filenames == NULL || **filenames == '\0') + return TRUE; + + while (*filenames != NULL) { + /* suffix match? */ + if (((flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX)) && + g_str_has_suffix (entry, *filenames)) { + return TRUE; + } else if (((flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX)) && + g_str_has_prefix (entry, *filenames)) { + return TRUE; + /* else it's an exact match that's needed */ + } else if (strcmp (entry, *filenames) == 0) { + return TRUE; + } + GST_LOG ("%s does not match %s, flags=0x%04x", entry, *filenames, flags); + ++filenames; + } + return FALSE; +} + +static guint +gst_plugin_ext_dep_scan_dir_and_match_names (GstPlugin * plugin, + const gchar * path, const gchar ** filenames, + GstPluginDependencyFlags flags, int depth) +{ + const gchar *entry; + gboolean recurse_dirs; + GError *err = NULL; + GDir *dir; + guint hash = 0; + + recurse_dirs = ! !(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); + + dir = g_dir_open (path, 0, &err); + if (dir == NULL) { + GST_DEBUG_OBJECT (plugin, "g_dir_open(%s) failed: %s", path, err->message); + g_error_free (err); + return (guint) - 1; + } + + /* FIXME: we're assuming here that we always get the directory entries in + * the same order, and not in a random order */ + while ((entry = g_dir_read_name (dir))) { + gboolean have_match; + GStatBuf s; + gchar *full_path; + guint fhash; + + have_match = + gst_plugin_ext_dep_direntry_matches (plugin, entry, filenames, flags); + + /* avoid the stat if possible */ + if (!have_match && !recurse_dirs) + continue; + + full_path = g_build_filename (path, entry, NULL); + if (g_stat (full_path, &s) < 0) { + fhash = (guint) - 1; + GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path, + g_strerror (errno)); + } else if (have_match) { + fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s); + GST_LOG_OBJECT (plugin, "stat: %s (result: %u)", full_path, fhash); + } else if ((s.st_mode & (S_IFDIR))) { + fhash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, full_path, + filenames, flags, depth + 1); + } else { + /* it's not a name match, we want to recurse, but it's not a directory */ + g_free (full_path); + continue; + } + + hash = hash + fhash; + g_free (full_path); + } + + g_dir_close (dir); + return hash; +} + +static guint +gst_plugin_ext_dep_scan_path_with_filenames (GstPlugin * plugin, + const gchar * path, const gchar ** filenames, + GstPluginDependencyFlags flags) +{ + const gchar *empty_filenames[] = { "", NULL }; + gboolean recurse_into_dirs, partial_names = FALSE; + guint i, hash = 0; + + /* to avoid special-casing below (FIXME?) */ + if (filenames == NULL || *filenames == NULL) + filenames = empty_filenames; + + recurse_into_dirs = ! !(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); + + if ((flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX) || + (flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX)) + partial_names = TRUE; + + /* if we can construct the exact paths to check with the data we have, just + * stat them one by one; this is more efficient than opening the directory + * and going through each entry to see if it matches one of our filenames. */ + if (!recurse_into_dirs && !partial_names) { + for (i = 0; filenames[i] != NULL; ++i) { + GStatBuf s; + gchar *full_path; + guint fhash; + + full_path = g_build_filename (path, filenames[i], NULL); + if (g_stat (full_path, &s) < 0) { + fhash = (guint) - 1; + GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path, + g_strerror (errno)); + } else { + fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s); + GST_LOG_OBJECT (plugin, "stat: %s (result: %08x)", full_path, fhash); + } + hash += fhash; + g_free (full_path); + } + } else { + hash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, path, + filenames, flags, 0); + } + + return hash; +} + +static guint +gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep) +{ + gboolean paths_are_default_only; + gboolean paths_are_relative_to_exe; + GQueue scan_paths = G_QUEUE_INIT; + guint scan_hash = 0; + gchar *path; + + GST_LOG_OBJECT (plugin, "start"); + + paths_are_default_only = + dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY; + paths_are_relative_to_exe = + dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE; + + gst_plugin_ext_dep_extract_env_vars_paths (plugin, dep, &scan_paths); + + if (g_queue_is_empty (&scan_paths) || !paths_are_default_only) { + gchar **paths; + + for (paths = dep->paths; paths != NULL && *paths != NULL; ++paths) { + const gchar *path = *paths; + gchar *full_path; + + if (paths_are_relative_to_exe && !g_path_is_absolute (path)) { + gchar *appdir; + + if (!_gst_executable_path) { + GST_FIXME_OBJECT (plugin, + "Path dependency %s relative to executable path but could not retrieve executable path", + path); + continue; + } + appdir = g_path_get_dirname (_gst_executable_path); + full_path = g_build_filename (appdir, path, NULL); + g_free (appdir); + } else { + full_path = g_strdup (path); + } + + if (!g_queue_find_custom (&scan_paths, full_path, (GCompareFunc) strcmp)) { + GST_LOG_OBJECT (plugin, "path: '%s'", full_path); + g_queue_push_tail (&scan_paths, full_path); + } else { + GST_LOG_OBJECT (plugin, "path: '%s' (duplicate, ignoring)", full_path); + g_free (full_path); + } + } + } + + while ((path = g_queue_pop_head (&scan_paths))) { + scan_hash += gst_plugin_ext_dep_scan_path_with_filenames (plugin, path, + (const gchar **) dep->names, dep->flags); + g_free (path); + } + + GST_LOG_OBJECT (plugin, "done, scan_hash: %08x", scan_hash); + return scan_hash; +} + +gboolean +_priv_plugin_deps_files_changed (GstPlugin * plugin) +{ + GList *l; + + for (l = plugin->priv->deps; l != NULL; l = l->next) { + GstPluginDep *dep = l->data; + + if (dep->stat_hash != gst_plugin_ext_dep_get_stat_hash (plugin, dep)) + return TRUE; + } + + return FALSE; +} + +static void +gst_plugin_ext_dep_free (GstPluginDep * dep) +{ + g_strfreev (dep->env_vars); + g_strfreev (dep->paths); + g_strfreev (dep->names); + g_slice_free (GstPluginDep, dep); +} + +static gboolean +gst_plugin_ext_dep_strv_equal (gchar ** arr1, gchar ** arr2) +{ + if (arr1 == arr2) + return TRUE; + if (arr1 == NULL || arr2 == NULL) + return FALSE; + for (; *arr1 != NULL && *arr2 != NULL; ++arr1, ++arr2) { + if (strcmp (*arr1, *arr2) != 0) + return FALSE; + } + return (*arr1 == *arr2); +} + +static gboolean +gst_plugin_ext_dep_equals (GstPluginDep * dep, const gchar ** env_vars, + const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags) +{ + if (dep->flags != flags) + return FALSE; + + return gst_plugin_ext_dep_strv_equal (dep->env_vars, (gchar **) env_vars) && + gst_plugin_ext_dep_strv_equal (dep->paths, (gchar **) paths) && + gst_plugin_ext_dep_strv_equal (dep->names, (gchar **) names); +} + +/** + * gst_plugin_add_dependency: + * @plugin: a #GstPlugin + * @env_vars: (allow-none) (array zero-terminated=1): %NULL-terminated array of environment variables affecting the + * feature set of the plugin (e.g. an environment variable containing + * paths where to look for additional modules/plugins of a library), + * or %NULL. Environment variable names may be followed by a path component + * which will be added to the content of the environment variable, e.g. + * "HOME/.mystuff/plugins". + * @paths: (allow-none) (array zero-terminated=1): %NULL-terminated array of directories/paths where dependent files + * may be, or %NULL. + * @names: (allow-none) (array zero-terminated=1): %NULL-terminated array of file names (or file name suffixes, + * depending on @flags) to be used in combination with the paths from + * @paths and/or the paths extracted from the environment variables in + * @env_vars, or %NULL. + * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE + * + * Make GStreamer aware of external dependencies which affect the feature + * set of this plugin (ie. the elements or typefinders associated with it). + * + * GStreamer will re-inspect plugins with external dependencies whenever any + * of the external dependencies change. This is useful for plugins which wrap + * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation + * library and makes visualisations available as GStreamer elements, or a + * codec loader which exposes elements and/or caps dependent on what external + * codec libraries are currently installed. + */ +void +gst_plugin_add_dependency (GstPlugin * plugin, const gchar ** env_vars, + const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags) +{ + GstPluginDep *dep; + GList *l; + + g_return_if_fail (GST_IS_PLUGIN (plugin)); + + if ((env_vars == NULL || env_vars[0] == NULL) && + (paths == NULL || paths[0] == NULL)) { + GST_DEBUG_OBJECT (plugin, + "plugin registered empty dependency set. Ignoring"); + return; + } + + for (l = plugin->priv->deps; l != NULL; l = l->next) { + if (gst_plugin_ext_dep_equals (l->data, env_vars, paths, names, flags)) { + GST_LOG_OBJECT (plugin, "dependency already registered"); + return; + } + } + + dep = g_slice_new (GstPluginDep); + + dep->env_vars = g_strdupv ((gchar **) env_vars); + dep->paths = g_strdupv ((gchar **) paths); + dep->names = g_strdupv ((gchar **) names); + dep->flags = flags; + + dep->env_hash = gst_plugin_ext_dep_get_env_vars_hash (plugin, dep); + dep->stat_hash = gst_plugin_ext_dep_get_stat_hash (plugin, dep); + + plugin->priv->deps = g_list_append (plugin->priv->deps, dep); + + GST_DEBUG_OBJECT (plugin, "added dependency:"); + for (; env_vars != NULL && *env_vars != NULL; ++env_vars) + GST_DEBUG_OBJECT (plugin, " evar: %s", *env_vars); + for (; paths != NULL && *paths != NULL; ++paths) + GST_DEBUG_OBJECT (plugin, " path: %s", *paths); + for (; names != NULL && *names != NULL; ++names) + GST_DEBUG_OBJECT (plugin, " name: %s", *names); +} + +/** + * gst_plugin_add_dependency_simple: + * @plugin: the #GstPlugin + * @env_vars: (allow-none): one or more environment variables (separated by ':', ';' or ','), + * or %NULL. Environment variable names may be followed by a path component + * which will be added to the content of the environment variable, e.g. + * "HOME/.mystuff/plugins:MYSTUFF_PLUGINS_PATH" + * @paths: (allow-none): one ore more directory paths (separated by ':' or ';' or ','), + * or %NULL. Example: "/usr/lib/mystuff/plugins" + * @names: (allow-none): one or more file names or file name suffixes (separated by commas), + * or %NULL + * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE + * + * Make GStreamer aware of external dependencies which affect the feature + * set of this plugin (ie. the elements or typefinders associated with it). + * + * GStreamer will re-inspect plugins with external dependencies whenever any + * of the external dependencies change. This is useful for plugins which wrap + * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation + * library and makes visualisations available as GStreamer elements, or a + * codec loader which exposes elements and/or caps dependent on what external + * codec libraries are currently installed. + * + * Convenience wrapper function for gst_plugin_add_dependency() which + * takes simple strings as arguments instead of string arrays, with multiple + * arguments separated by predefined delimiters (see above). + */ +void +gst_plugin_add_dependency_simple (GstPlugin * plugin, + const gchar * env_vars, const gchar * paths, const gchar * names, + GstPluginDependencyFlags flags) +{ + gchar **a_evars = NULL; + gchar **a_paths = NULL; + gchar **a_names = NULL; + + if (env_vars) + a_evars = g_strsplit_set (env_vars, ":;,", -1); + if (paths) + a_paths = g_strsplit_set (paths, ":;,", -1); + if (names) + a_names = g_strsplit_set (names, ",", -1); + + gst_plugin_add_dependency (plugin, (const gchar **) a_evars, + (const gchar **) a_paths, (const gchar **) a_names, flags); + + if (a_evars) + g_strfreev (a_evars); + if (a_paths) + g_strfreev (a_paths); + if (a_names) + g_strfreev (a_names); +} diff --git a/gst/gstplugin.h b/gst/gstplugin.h new file mode 100644 index 0000000..0fc2302 --- /dev/null +++ b/gst/gstplugin.h @@ -0,0 +1,404 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstplugin.h: Header for plugin subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_PLUGIN_H__ +#define __GST_PLUGIN_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstPlugin: + * + * The opaque plugin object + */ +typedef struct _GstPlugin GstPlugin; +typedef struct _GstPluginClass GstPluginClass; +typedef struct _GstPluginDesc GstPluginDesc; + +/** + * gst_plugin_error_quark: + * + * Get the error quark. + * + * Returns: The error quark used in GError messages + */ + +GST_API +GQuark gst_plugin_error_quark (void); +/** + * GST_PLUGIN_ERROR: + * + * The error message category quark + */ +#define GST_PLUGIN_ERROR gst_plugin_error_quark () + +/** + * GstPluginError: + * @GST_PLUGIN_ERROR_MODULE: The plugin could not be loaded + * @GST_PLUGIN_ERROR_DEPENDENCIES: The plugin has unresolved dependencies + * @GST_PLUGIN_ERROR_NAME_MISMATCH: The plugin has already be loaded from a different file + * + * The plugin loading errors + */ +typedef enum +{ + GST_PLUGIN_ERROR_MODULE, + GST_PLUGIN_ERROR_DEPENDENCIES, + GST_PLUGIN_ERROR_NAME_MISMATCH +} GstPluginError; + +/** + * GstPluginFlags: + * @GST_PLUGIN_FLAG_CACHED: Temporarily loaded plugins + * @GST_PLUGIN_FLAG_BLACKLISTED: The plugin won't be scanned (again) + * + * The plugin loading state + */ +typedef enum +{ + GST_PLUGIN_FLAG_CACHED = (GST_OBJECT_FLAG_LAST << 0), + GST_PLUGIN_FLAG_BLACKLISTED = (GST_OBJECT_FLAG_LAST << 1) +} GstPluginFlags; + +/** + * GstPluginDependencyFlags: + * @GST_PLUGIN_DEPENDENCY_FLAG_NONE : no special flags + * @GST_PLUGIN_DEPENDENCY_FLAG_RECURSE : recurse into subdirectories + * @GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY : use paths + * argument only if none of the environment variables is set + * @GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX : interpret + * filename argument as filter suffix and check all matching files in + * the directory + * @GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX : interpret + * filename argument as filter prefix and check all matching files in + * the directory. Since 1.8. + * @GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE : interpret + * non-absolute paths as relative to the main executable directory. Since + * 1.14. + * + * Flags used in connection with gst_plugin_add_dependency(). + */ +typedef enum { + GST_PLUGIN_DEPENDENCY_FLAG_NONE = 0, + GST_PLUGIN_DEPENDENCY_FLAG_RECURSE = (1 << 0), + GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY = (1 << 1), + GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX = (1 << 2), + GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX = (1 << 3), + GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE = (1 << 4) +} GstPluginDependencyFlags; + +/** + * GstPluginInitFunc: + * @plugin: The plugin object + * + * A plugin should provide a pointer to a function of this type in the + * plugin_desc struct. + * This function will be called by the loader at startup. One would then + * register each #GstPluginFeature. + * + * Returns: %TRUE if plugin initialised successfully + */ +/* FIXME 0.11: Make return void */ +typedef gboolean (*GstPluginInitFunc) (GstPlugin *plugin); + +/** + * GstPluginInitFullFunc: + * @plugin: The plugin object + * @user_data: extra data + * + * A plugin should provide a pointer to a function of either #GstPluginInitFunc + * or this type in the plugin_desc struct. + * The function will be called by the loader at startup. One would then + * register each #GstPluginFeature. This version allows + * user data to be passed to init function (useful for bindings). + * + * Returns: %TRUE if plugin initialised successfully + */ +/* FIXME 0.11: Merge with GstPluginInitFunc */ +typedef gboolean (*GstPluginInitFullFunc) (GstPlugin *plugin, gpointer user_data); + +/** + * GstPluginDesc: + * @major_version: the major version number of core that plugin was compiled for + * @minor_version: the minor version number of core that plugin was compiled for + * @name: a unique name of the plugin + * @description: description of plugin + * @plugin_init: pointer to the init function of this plugin. + * @version: version of the plugin + * @license: effective license of plugin + * @source: source module plugin belongs to + * @package: shipped package plugin belongs to + * @origin: URL to provider of plugin + * @release_datetime: (allow-none): date time string in ISO 8601 + * format (or rather, a subset thereof), or %NULL. Allowed are the + * following formats: "YYYY-MM-DD" and "YYY-MM-DDTHH:MMZ" (with + * 'T' a separator and 'Z' indicating UTC/Zulu time). This field + * should be set via the GST_PACKAGE_RELEASE_DATETIME + * preprocessor macro. + * + * A plugin should export a variable of this type called plugin_desc. The plugin + * loader will use the data provided there to initialize the plugin. + * + * The @licence parameter must be one of: LGPL, GPL, QPL, GPL/QPL, MPL, + * BSD, MIT/X11, Proprietary, unknown. + */ +struct _GstPluginDesc { + gint major_version; + gint minor_version; + const gchar *name; + const gchar *description; + GstPluginInitFunc plugin_init; + const gchar *version; + const gchar *license; + const gchar *source; + const gchar *package; + const gchar *origin; + const gchar *release_datetime; + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + + +#define GST_TYPE_PLUGIN (gst_plugin_get_type()) +#define GST_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLUGIN)) +#define GST_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLUGIN)) +#define GST_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLUGIN, GstPluginClass)) +#define GST_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLUGIN, GstPlugin)) +#define GST_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLUGIN, GstPluginClass)) +#define GST_PLUGIN_CAST(obj) ((GstPlugin*)(obj)) + +#ifdef GST_PACKAGE_RELEASE_DATETIME +#define __GST_PACKAGE_RELEASE_DATETIME GST_PACKAGE_RELEASE_DATETIME +#else +#define __GST_PACKAGE_RELEASE_DATETIME NULL +#endif + +/** + * GST_PLUGIN_STATIC_DECLARE: + * @name: short, but unique name of the plugin + * + * This macro can be used to initialize statically linked plugins. It is + * necessary to call this macro before the plugin can be used. + * It has to be used in combination with GST_PLUGIN_STATIC_REGISTER + * and must be placed outside any block to declare the plugin initialization + * function. + * + * Since: 1.2 + */ +#define GST_PLUGIN_STATIC_DECLARE(name) \ + extern void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void) + +/** + * GST_PLUGIN_STATIC_REGISTER: + * @name: short, but unique name of the plugin + * + * This macro can be used to initialize statically linked plugins. It is + * necessary to call this macro before the plugin can be used. + * It has to be used in combination with GST_PLUGIN_STATIC_DECLARE and + * calls the plugin initialization function. + * + * Since: 1.2 + */ +#define GST_PLUGIN_STATIC_REGISTER(name) G_PASTE(gst_plugin_, G_PASTE(name, _register)) () + +/** + * GST_PLUGIN_DEFINE: + * @major: major version number of the gstreamer-core that plugin was compiled for + * @minor: minor version number of the gstreamer-core that plugin was compiled for + * @name: short, but unique name of the plugin + * @description: information about the purpose of the plugin + * @init: function pointer to the plugin_init method with the signature of static gboolean plugin_init (GstPlugin * plugin). + * @version: full version string (e.g. VERSION from config.h) + * @license: under which licence the package has been released, e.g. GPL, LGPL. + * @package: the package-name (e.g. PACKAGE_NAME from config.h) + * @origin: a description from where the package comes from (e.g. the homepage URL) + * + * This macro needs to be used to define the entry point and meta data of a + * plugin. One would use this macro to export a plugin, so that it can be used + * by other applications. + * + * The macro uses a define named PACKAGE for the #GstPluginDesc,source field. + * When using autoconf, this is usually set automatically via the AC_INIT + * macro, and set in config.h. If you are not using autoconf, you will need to + * define PACKAGE yourself and set it to a short mnemonic string identifying + * your application/package, e.g. 'someapp' or 'my-plugins-foo. + * + * If defined, the GST_PACKAGE_RELEASE_DATETIME will also be used for the + * #GstPluginDesc,release_datetime field. + */ +#define GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin) \ +G_BEGIN_DECLS \ +GST_PLUGIN_EXPORT const GstPluginDesc * G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void); \ +GST_PLUGIN_EXPORT void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void); \ +\ +static const GstPluginDesc gst_plugin_desc = { \ + major, \ + minor, \ + G_STRINGIFY(name), \ + (gchar *) description, \ + init, \ + version, \ + license, \ + PACKAGE, \ + package, \ + origin, \ + __GST_PACKAGE_RELEASE_DATETIME, \ + GST_PADDING_INIT \ +}; \ +\ +const GstPluginDesc * \ +G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void) \ +{ \ + return &gst_plugin_desc; \ +} \ +\ +void \ +G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void) \ +{ \ + gst_plugin_register_static (major, minor, G_STRINGIFY(name), \ + description, init, version, license, \ + PACKAGE, package, origin); \ +} \ +G_END_DECLS + +/** + * GST_LICENSE_UNKNOWN: + * + * To be used in GST_PLUGIN_DEFINE if unsure about the licence. + */ +#define GST_LICENSE_UNKNOWN "unknown" + + +/* function for filters */ +/** + * GstPluginFilter: + * @plugin: the plugin to check + * @user_data: the user_data that has been passed on e.g. gst_registry_plugin_filter() + * + * A function that can be used with e.g. gst_registry_plugin_filter() + * to get a list of plugins that match certain criteria. + * + * Returns: %TRUE for a positive match, %FALSE otherwise + */ +typedef gboolean (*GstPluginFilter) (GstPlugin *plugin, + gpointer user_data); + +GST_API +GType gst_plugin_get_type (void); + +GST_API +gboolean gst_plugin_register_static (gint major_version, + gint minor_version, + const gchar *name, + const gchar *description, + GstPluginInitFunc init_func, + const gchar *version, + const gchar *license, + const gchar *source, + const gchar *package, + const gchar *origin); +GST_API +gboolean gst_plugin_register_static_full (gint major_version, + gint minor_version, + const gchar *name, + const gchar *description, + GstPluginInitFullFunc init_full_func, + const gchar *version, + const gchar *license, + const gchar *source, + const gchar *package, + const gchar *origin, + gpointer user_data); +GST_API +const gchar* gst_plugin_get_name (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_description (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_filename (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_version (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_license (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_source (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_package (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_origin (GstPlugin *plugin); + +GST_API +const gchar* gst_plugin_get_release_date_string (GstPlugin *plugin); + +GST_API +const GstStructure* gst_plugin_get_cache_data (GstPlugin * plugin); + +GST_API +void gst_plugin_set_cache_data (GstPlugin * plugin, GstStructure *cache_data); + +GST_API +gboolean gst_plugin_is_loaded (GstPlugin *plugin); + +GST_API +GstPlugin * gst_plugin_load_file (const gchar *filename, GError** error); + +GST_API +GstPlugin * gst_plugin_load (GstPlugin *plugin); + +GST_API +GstPlugin * gst_plugin_load_by_name (const gchar *name); + +GST_API +void gst_plugin_add_dependency (GstPlugin * plugin, + const gchar ** env_vars, + const gchar ** paths, + const gchar ** names, + GstPluginDependencyFlags flags); +GST_API +void gst_plugin_add_dependency_simple (GstPlugin * plugin, + const gchar * env_vars, + const gchar * paths, + const gchar * names, + GstPluginDependencyFlags flags); +GST_API +void gst_plugin_list_free (GList *list); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPlugin, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PLUGIN_H__ */ diff --git a/gst/gstpluginfeature.c b/gst/gstpluginfeature.c new file mode 100644 index 0000000..831236e --- /dev/null +++ b/gst/gstpluginfeature.c @@ -0,0 +1,407 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpluginfeature.c: Abstract base class for all plugin features + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstpluginfeature + * @title: GstPluginfeature + * @short_description: Base class for contents of a GstPlugin + * @see_also: #GstPlugin + * + * This is a base class for anything that can be added to a #GstPlugin. + */ + +#include "gst_private.h" + +#include "gstpluginfeature.h" +#include "gstplugin.h" +#include "gstregistry.h" +#include "gstinfo.h" + +#include +#include + +#define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING + +static void gst_plugin_feature_finalize (GObject * object); + +/* static guint gst_plugin_feature_signals[LAST_SIGNAL] = { 0 }; */ + +G_DEFINE_ABSTRACT_TYPE (GstPluginFeature, gst_plugin_feature, GST_TYPE_OBJECT); + +static void +gst_plugin_feature_class_init (GstPluginFeatureClass * klass) +{ + G_OBJECT_CLASS (klass)->finalize = gst_plugin_feature_finalize; +} + +static void +gst_plugin_feature_init (GstPluginFeature * feature) +{ + /* do nothing, needed because of G_DEFINE_TYPE */ +} + +static void +gst_plugin_feature_finalize (GObject * object) +{ + GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (object); + + GST_DEBUG ("finalizing feature %p: '%s'", feature, GST_OBJECT_NAME (feature)); + + if (feature->plugin != NULL) { + g_object_remove_weak_pointer ((GObject *) feature->plugin, + (gpointer *) & feature->plugin); + } + + G_OBJECT_CLASS (gst_plugin_feature_parent_class)->finalize (object); +} + +/** + * gst_plugin_feature_load: + * @feature: (transfer none): the plugin feature to check + * + * Loads the plugin containing @feature if it's not already loaded. @feature is + * unaffected; use the return value instead. + * + * Normally this function is used like this: + * |[ + * GstPluginFeature *loaded_feature; + * + * loaded_feature = gst_plugin_feature_load (feature); + * // presumably, we're no longer interested in the potentially-unloaded feature + * gst_object_unref (feature); + * feature = loaded_feature; + * ]| + * + * Returns: (transfer full) (nullable): a reference to the loaded + * feature, or %NULL on error + */ +GstPluginFeature * +gst_plugin_feature_load (GstPluginFeature * feature) +{ + GstPlugin *plugin; + GstPluginFeature *real_feature; + + g_return_val_if_fail (feature != NULL, FALSE); + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE); + + GST_DEBUG ("loading plugin for feature %p; '%s'", feature, + GST_OBJECT_NAME (feature)); + if (feature->loaded) + return gst_object_ref (feature); + + GST_DEBUG ("loading plugin %s", feature->plugin_name); + plugin = gst_plugin_load_by_name (feature->plugin_name); + if (!plugin) + goto load_failed; + + GST_DEBUG ("loaded plugin %s", feature->plugin_name); + gst_object_unref (plugin); + + real_feature = gst_registry_lookup_feature (gst_registry_get (), + GST_OBJECT_NAME (feature)); + + if (real_feature == NULL) + goto disappeared; + else if (!real_feature->loaded) + goto not_found; + + return real_feature; + + /* ERRORS */ +load_failed: + { + GST_WARNING ("Failed to load plugin containing feature '%s'.", + GST_OBJECT_NAME (feature)); + return NULL; + } +disappeared: + { + GST_INFO + ("Loaded plugin containing feature '%s', but feature disappeared.", + GST_OBJECT_NAME (feature)); + return NULL; + } +not_found: + { + GST_INFO ("Tried to load plugin containing feature '%s', but feature was " + "not found.", GST_OBJECT_NAME (real_feature)); + return NULL; + } +} + +/** + * gst_plugin_feature_set_rank: + * @feature: feature to rank + * @rank: rank value - higher number means more priority rank + * + * Specifies a rank for a plugin feature, so that autoplugging uses + * the most appropriate feature. + */ +void +gst_plugin_feature_set_rank (GstPluginFeature * feature, guint rank) +{ + g_return_if_fail (feature != NULL); + g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature)); + + feature->rank = rank; +} + +/** + * gst_plugin_feature_get_rank: + * @feature: a feature + * + * Gets the rank of a plugin feature. + * + * Returns: The rank of the feature + */ +guint +gst_plugin_feature_get_rank (GstPluginFeature * feature) +{ + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), GST_RANK_NONE); + + return feature->rank; +} + +/** + * gst_plugin_feature_get_plugin: + * @feature: a feature + * + * Get the plugin that provides this feature. + * + * Returns: (transfer full) (nullable): the plugin that provides this + * feature, or %NULL. Unref with gst_object_unref() when no + * longer needed. + */ +GstPlugin * +gst_plugin_feature_get_plugin (GstPluginFeature * feature) +{ + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), NULL); + + if (feature->plugin == NULL) + return NULL; + + return (GstPlugin *) gst_object_ref (feature->plugin); +} + +/** + * gst_plugin_feature_get_plugin_name: + * @feature: a feature + * + * Get the name of the plugin that provides this feature. + * + * Returns: (nullable): the name of the plugin that provides this + * feature, or %NULL if the feature is not associated with a + * plugin. + * + * Since: 1.2 + */ +const gchar * +gst_plugin_feature_get_plugin_name (GstPluginFeature * feature) +{ + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), NULL); + + if (feature->plugin == NULL) + return NULL; + + return gst_plugin_get_name (feature->plugin); +} + +/** + * gst_plugin_feature_list_free: + * @list: (transfer full) (element-type Gst.PluginFeature): list + * of #GstPluginFeature + * + * Unrefs each member of @list, then frees the list. + */ +void +gst_plugin_feature_list_free (GList * list) +{ + GList *g; + + for (g = list; g; g = g->next) { + GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (g->data); + + gst_object_unref (feature); + } + g_list_free (list); +} + +/** + * gst_plugin_feature_list_copy: + * @list: (transfer none) (element-type Gst.PluginFeature): list + * of #GstPluginFeature + * + * Copies the list of features. Caller should call @gst_plugin_feature_list_free + * when done with the list. + * + * Returns: (transfer full) (element-type Gst.PluginFeature): a copy of @list, + * with each feature's reference count incremented. + */ +GList * +gst_plugin_feature_list_copy (GList * list) +{ + GList *new_list = NULL; + + if (G_LIKELY (list)) { + GList *last; + + new_list = g_list_alloc (); + new_list->data = gst_object_ref (list->data); + new_list->prev = NULL; + last = new_list; + list = list->next; + while (list) { + last->next = g_list_alloc (); + last->next->prev = last; + last = last->next; + last->data = gst_object_ref (list->data); + list = list->next; + } + last->next = NULL; + } + + return new_list; +} + +/** + * gst_plugin_feature_list_debug: + * @list: (transfer none) (element-type Gst.PluginFeature): a #GList of + * plugin features + * + * Debug the plugin feature names in @list. + */ +void +gst_plugin_feature_list_debug (GList * list) +{ +#ifndef GST_DISABLE_GST_DEBUG + while (list) { + GST_DEBUG ("%s", + gst_plugin_feature_get_name ((GstPluginFeature *) list->data)); + list = list->next; + } +#endif +} + +/** + * gst_plugin_feature_check_version: + * @feature: a feature + * @min_major: minimum required major version + * @min_minor: minimum required minor version + * @min_micro: minimum required micro version + * + * Checks whether the given plugin feature is at least + * the required version + * + * Returns: %TRUE if the plugin feature has at least + * the required version, otherwise %FALSE. + */ +gboolean +gst_plugin_feature_check_version (GstPluginFeature * feature, + guint min_major, guint min_minor, guint min_micro) +{ + GstRegistry *registry; + GstPlugin *plugin; + gboolean ret = FALSE; + + g_return_val_if_fail (feature != NULL, FALSE); + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE); + + GST_DEBUG ("Looking up plugin '%s' containing plugin feature '%s'", + feature->plugin_name, GST_OBJECT_NAME (feature)); + + registry = gst_registry_get (); + plugin = gst_registry_find_plugin (registry, feature->plugin_name); + + if (plugin) { + const gchar *ver_str; + guint major, minor, micro, nano; + gint nscan; + + ver_str = gst_plugin_get_version (plugin); + g_return_val_if_fail (ver_str != NULL, FALSE); + + nscan = sscanf (ver_str, "%u.%u.%u.%u", &major, &minor, µ, &nano); + GST_DEBUG ("version string '%s' parsed to %d values", ver_str, nscan); + + if (nscan >= 3) { + if (major > min_major) + ret = TRUE; + else if (major < min_major) + ret = FALSE; + else if (minor > min_minor) + ret = TRUE; + else if (minor < min_minor) + ret = FALSE; + else if (micro > min_micro) + ret = TRUE; + /* micro is 1 smaller but we have a nano version, this is the upcoming + * release of the requested version and we're ok then */ + else if (nscan == 4 && nano > 0 && (micro + 1 == min_micro)) + ret = TRUE; + else + ret = (micro == min_micro); + + GST_DEBUG ("Checking whether %u.%u.%u >= %u.%u.%u? %s", major, minor, + micro, min_major, min_minor, min_micro, (ret) ? "yes" : "no"); + } else { + GST_WARNING ("Could not parse version string '%s' of plugin '%s'", + ver_str, feature->plugin_name); + } + + gst_object_unref (plugin); + } else { + GST_DEBUG ("Could not find plugin '%s'", feature->plugin_name); + } + + return ret; +} + +/** + * gst_plugin_feature_rank_compare_func: + * @p1: a #GstPluginFeature + * @p2: a #GstPluginFeature + * + * Compares the two given #GstPluginFeature instances. This function can be + * used as a #GCompareFunc when sorting by rank and then by name. + * + * Returns: negative value if the rank of p1 > the rank of p2 or the ranks are + * equal but the name of p1 comes before the name of p2; zero if the rank + * and names are equal; positive value if the rank of p1 < the rank of p2 or the + * ranks are equal but the name of p2 comes before the name of p1 + */ +gint +gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2) +{ + GstPluginFeature *f1, *f2; + gint diff; + + f1 = (GstPluginFeature *) p1; + f2 = (GstPluginFeature *) p2; + + diff = f2->rank - f1->rank; + if (diff != 0) + return diff; + + diff = strcmp (GST_OBJECT_NAME (f1), GST_OBJECT_NAME (f2)); + + return diff; +} diff --git a/gst/gstpluginfeature.h b/gst/gstpluginfeature.h new file mode 100644 index 0000000..d8db095 --- /dev/null +++ b/gst/gstpluginfeature.h @@ -0,0 +1,166 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstpluginfeature.h: Header for base GstPluginFeature + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_PLUGIN_FEATURE_H__ +#define __GST_PLUGIN_FEATURE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PLUGIN_FEATURE (gst_plugin_feature_get_type()) +#define GST_PLUGIN_FEATURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLUGIN_FEATURE, GstPluginFeature)) +#define GST_IS_PLUGIN_FEATURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLUGIN_FEATURE)) +#define GST_PLUGIN_FEATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLUGIN_FEATURE, GstPluginFeatureClass)) +#define GST_IS_PLUGIN_FEATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLUGIN_FEATURE)) +#define GST_PLUGIN_FEATURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLUGIN_FEATURE, GstPluginFeatureClass)) +#define GST_PLUGIN_FEATURE_CAST(obj) ((GstPluginFeature*)(obj)) + +/** + * GstPluginFeature: + * + * Opaque #GstPluginFeature structure. + */ +typedef struct _GstPluginFeature GstPluginFeature; +typedef struct _GstPluginFeatureClass GstPluginFeatureClass; + +/** + * GstRank: + * @GST_RANK_NONE: will be chosen last or not at all + * @GST_RANK_MARGINAL: unlikely to be chosen + * @GST_RANK_SECONDARY: likely to be chosen + * @GST_RANK_PRIMARY: will be chosen first + * + * Element priority ranks. Defines the order in which the autoplugger (or + * similar rank-picking mechanisms, such as e.g. gst_element_make_from_uri()) + * will choose this element over an alternative one with the same function. + * + * These constants serve as a rough guidance for defining the rank of a + * #GstPluginFeature. Any value is valid, including values bigger than + * @GST_RANK_PRIMARY. + */ +typedef enum { + GST_RANK_NONE = 0, + GST_RANK_MARGINAL = 64, + GST_RANK_SECONDARY = 128, + GST_RANK_PRIMARY = 256 +} GstRank; + +/** + * gst_plugin_feature_get_name: + * @feature: a #GstPluginFeature to get the name of @feature. + * + * Returns the name of @feature. + * For a nameless plugin feature, this returns %NULL. + * + * Returns: (transfer none) (nullable): the name of @feature. MT safe. + * + */ +#define gst_plugin_feature_get_name(feature) GST_OBJECT_NAME(feature) + +/** + * gst_plugin_feature_set_name: + * @feature: a #GstPluginFeature to set the name of. + * @name: the new name + * + * Sets the name of the plugin feature, getting rid of the old name if there was one. + */ +#define gst_plugin_feature_set_name(feature,name) gst_object_set_name(GST_OBJECT_CAST(feature),name) + +/** + * GstPluginFeatureFilter: + * @feature: the pluginfeature to check + * @user_data: the user_data that has been passed on e.g. + * gst_registry_feature_filter() + * + * A function that can be used with e.g. gst_registry_feature_filter() + * to get a list of pluginfeature that match certain criteria. + * + * Returns: %TRUE for a positive match, %FALSE otherwise + */ +typedef gboolean (*GstPluginFeatureFilter) (GstPluginFeature *feature, + gpointer user_data); + +/* normal GObject stuff */ + +GST_API +GType gst_plugin_feature_get_type (void); + +GST_API +GstPluginFeature * + gst_plugin_feature_load (GstPluginFeature *feature); + +GST_API +void gst_plugin_feature_set_rank (GstPluginFeature *feature, guint rank); + +GST_API +guint gst_plugin_feature_get_rank (GstPluginFeature *feature); + +GST_API +GstPlugin * gst_plugin_feature_get_plugin (GstPluginFeature *feature); + +GST_API +const gchar * gst_plugin_feature_get_plugin_name (GstPluginFeature *feature); + +GST_API +void gst_plugin_feature_list_free (GList *list); + +GST_API +GList *gst_plugin_feature_list_copy (GList *list) G_GNUC_MALLOC; + +GST_API +void gst_plugin_feature_list_debug (GList *list); + +/** + * GST_PLUGIN_FEATURE_LIST_DEBUG: + * @list: (transfer none) (element-type Gst.PluginFeature): a #GList of + * plugin features + * + * Debug the plugin feature names in @list. + */ +#ifndef GST_DISABLE_GST_DEBUG +#define GST_PLUGIN_FEATURE_LIST_DEBUG(list) gst_plugin_feature_list_debug(list) +#else +#define GST_PLUGIN_FEATURE_LIST_DEBUG(list) +#endif + +GST_API +gboolean gst_plugin_feature_check_version (GstPluginFeature *feature, + guint min_major, + guint min_minor, + guint min_micro); +GST_API +gint gst_plugin_feature_rank_compare_func (gconstpointer p1, + gconstpointer p2); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPluginFeature, gst_object_unref) +#endif + +G_END_DECLS + + +#endif /* __GST_PLUGIN_FEATURE_H__ */ + diff --git a/gst/gstpluginloader.c b/gst/gstpluginloader.c new file mode 100644 index 0000000..a933a4b --- /dev/null +++ b/gst/gstpluginloader.c @@ -0,0 +1,1061 @@ +/* GStreamer + * Copyright (C) 2008 Jan Schmidt + * + * gstpluginloader.c: GstPluginLoader helper for loading plugin files + * out of process. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifndef G_OS_WIN32 +#include +#include +#include +#include +#include +#else +#define WIN32_LEAN_AND_MEAN + +#define fsync(fd) _commit(fd) +#include + +#include +extern HMODULE _priv_gst_dll_handle; +#endif + +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#include + +#include + +#include +#include + +#include +#include +#include + +/* IMPORTANT: Bump the version number if the plugin loader packet protocol + * changes. Changes in the binary registry format itself are handled by + * bumping the GST_MAGIC_BINARY_VERSION_STR + */ +static const guint32 loader_protocol_version = 3; + +#define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING + +static GstPluginLoader *plugin_loader_new (GstRegistry * registry); +static gboolean plugin_loader_free (GstPluginLoader * loader); +static gboolean plugin_loader_load (GstPluginLoader * loader, + const gchar * filename, off_t file_size, time_t file_mtime); + +/* functions used in GstRegistry scanning */ +const GstPluginLoaderFuncs _priv_gst_plugin_loader_funcs = { + plugin_loader_new, plugin_loader_free, plugin_loader_load +}; + +typedef struct _PendingPluginEntry +{ + /* sequence number */ + guint32 tag; + gchar *filename; + off_t file_size; + time_t file_mtime; +} PendingPluginEntry; + +struct _GstPluginLoader +{ + GstRegistry *registry; + GstPoll *fdset; + + gboolean child_running; + GPid child_pid; + GstPollFD fd_w; + GstPollFD fd_r; + + gboolean is_child; + gboolean got_plugin_details; + + /* Transmit buffer */ + guint8 *tx_buf; + guint tx_buf_size; + guint tx_buf_write; + guint tx_buf_read; + + /* next sequence number (for PendingPluginEntry) */ + guint32 next_tag; + + guint8 *rx_buf; + guint rx_buf_size; + gboolean rx_done; + gboolean rx_got_sync; + + /* Head and tail of the pending plugins list. List of + PendingPluginEntry structs */ + GList *pending_plugins; + GList *pending_plugins_tail; +}; + +#define PACKET_EXIT 1 +#define PACKET_LOAD_PLUGIN 2 +#define PACKET_SYNC 3 +#define PACKET_PLUGIN_DETAILS 4 +#define PACKET_VERSION 5 + +#define BUF_INIT_SIZE 512 +#define BUF_GROW_EXTRA 512 +#define BUF_MAX_SIZE (32 * 1024 * 1024) + +#define HEADER_SIZE 12 +/* 4 magic hex bytes to mark each packet */ +#define HEADER_MAGIC 0xbefec0ae +#define ALIGNMENT (sizeof (void *)) + +static gboolean gst_plugin_loader_spawn (GstPluginLoader * loader); +static void put_packet (GstPluginLoader * loader, guint type, guint32 tag, + const guint8 * payload, guint32 payload_len); +static gboolean exchange_packets (GstPluginLoader * l); +static gboolean plugin_loader_replay_pending (GstPluginLoader * l); +static gboolean plugin_loader_load_and_sync (GstPluginLoader * l, + PendingPluginEntry * entry); +static void plugin_loader_create_blacklist_plugin (GstPluginLoader * l, + PendingPluginEntry * entry); +static void plugin_loader_cleanup_child (GstPluginLoader * loader); +static gboolean plugin_loader_sync_with_child (GstPluginLoader * l); + +static GstPluginLoader * +plugin_loader_new (GstRegistry * registry) +{ + GstPluginLoader *l = g_slice_new0 (GstPluginLoader); + + if (registry) + l->registry = gst_object_ref (registry); + l->fdset = gst_poll_new (FALSE); + gst_poll_fd_init (&l->fd_w); + gst_poll_fd_init (&l->fd_r); + + l->tx_buf_size = BUF_INIT_SIZE; + l->tx_buf = g_malloc (BUF_INIT_SIZE); + + l->next_tag = 0; + + l->rx_buf_size = BUF_INIT_SIZE; + l->rx_buf = g_malloc (BUF_INIT_SIZE); + + return l; +} + +static gboolean +plugin_loader_free (GstPluginLoader * loader) +{ + GList *cur; + gboolean got_plugin_details; + + fsync (loader->fd_w.fd); + + if (loader->child_running) { + put_packet (loader, PACKET_EXIT, 0, NULL, 0); + + /* Swap packets with the child until it exits cleanly */ + while (!loader->rx_done) { + if (exchange_packets (loader) || loader->rx_done) + continue; + + if (!plugin_loader_replay_pending (loader)) + break; + put_packet (loader, PACKET_EXIT, 0, NULL, 0); + } + + plugin_loader_cleanup_child (loader); + } else { + close (loader->fd_w.fd); + close (loader->fd_r.fd); + } + + gst_poll_free (loader->fdset); + + g_free (loader->rx_buf); + g_free (loader->tx_buf); + + if (loader->registry) + gst_object_unref (loader->registry); + + got_plugin_details = loader->got_plugin_details; + + /* Free any pending plugin entries */ + cur = loader->pending_plugins; + while (cur) { + PendingPluginEntry *entry = (PendingPluginEntry *) (cur->data); + g_free (entry->filename); + g_slice_free (PendingPluginEntry, entry); + + cur = g_list_delete_link (cur, cur); + } + + g_slice_free (GstPluginLoader, loader); + + return got_plugin_details; +} + +static gboolean +plugin_loader_load (GstPluginLoader * loader, const gchar * filename, + off_t file_size, time_t file_mtime) +{ + gint len; + PendingPluginEntry *entry; + + if (!gst_plugin_loader_spawn (loader)) + return FALSE; + + /* Send a packet to the child requesting that it load the given file */ + GST_LOG_OBJECT (loader->registry, + "Sending file %s to child. tag %u", filename, loader->next_tag); + + entry = g_slice_new (PendingPluginEntry); + entry->tag = loader->next_tag++; + entry->filename = g_strdup (filename); + entry->file_size = file_size; + entry->file_mtime = file_mtime; + loader->pending_plugins_tail = + g_list_append (loader->pending_plugins_tail, entry); + + if (loader->pending_plugins == NULL) + loader->pending_plugins = loader->pending_plugins_tail; + else + loader->pending_plugins_tail = g_list_next (loader->pending_plugins_tail); + + len = strlen (filename); + put_packet (loader, PACKET_LOAD_PLUGIN, entry->tag, + (guint8 *) filename, len + 1); + + if (!exchange_packets (loader)) { + if (!plugin_loader_replay_pending (loader)) + return FALSE; + } + + return TRUE; +} + +static gboolean +plugin_loader_replay_pending (GstPluginLoader * l) +{ + GList *cur, *next; + +restart: + if (!gst_plugin_loader_spawn (l)) + return FALSE; + + /* Load each plugin one by one synchronously until we find the + * crashing one */ + while ((cur = l->pending_plugins)) { + PendingPluginEntry *entry = (PendingPluginEntry *) (cur->data); + + if (!plugin_loader_load_and_sync (l, entry)) { + /* Create dummy plugin entry to block re-scanning this file */ + GST_ERROR ("Plugin file %s failed to load. Blacklisting", + entry->filename); + plugin_loader_create_blacklist_plugin (l, entry); + l->got_plugin_details = TRUE; + /* Now remove this crashy plugin from the head of the list */ + l->pending_plugins = g_list_delete_link (cur, cur); + g_free (entry->filename); + g_slice_free (PendingPluginEntry, entry); + if (l->pending_plugins == NULL) + l->pending_plugins_tail = NULL; + if (!gst_plugin_loader_spawn (l)) + return FALSE; + break; + } + } + + /* We exited after finding the crashing one. If there's any more pending, + * dispatch them post-haste, but don't wait */ + for (cur = l->pending_plugins; cur != NULL; cur = next) { + PendingPluginEntry *entry = (PendingPluginEntry *) (cur->data); + + next = g_list_next (cur); + + put_packet (l, PACKET_LOAD_PLUGIN, entry->tag, + (guint8 *) entry->filename, strlen (entry->filename) + 1); + + /* This might invalidate cur, which is why we grabbed 'next' above */ + if (!exchange_packets (l)) + goto restart; + } + + return TRUE; +} + +static gboolean +plugin_loader_sync_with_child (GstPluginLoader * l) +{ + put_packet (l, PACKET_SYNC, 0, NULL, 0); + + l->rx_got_sync = FALSE; + while (!l->rx_got_sync) { + if (!exchange_packets (l)) + return FALSE; + } + return TRUE; +} + +static gboolean +plugin_loader_load_and_sync (GstPluginLoader * l, PendingPluginEntry * entry) +{ + gint len; + + GST_DEBUG_OBJECT (l->registry, "Synchronously loading plugin file %s", + entry->filename); + + len = strlen (entry->filename); + put_packet (l, PACKET_LOAD_PLUGIN, entry->tag, + (guint8 *) entry->filename, len + 1); + + return plugin_loader_sync_with_child (l); +} + +static void +plugin_loader_create_blacklist_plugin (GstPluginLoader * l, + PendingPluginEntry * entry) +{ + GstPlugin *plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + + plugin->filename = g_strdup (entry->filename); + plugin->file_mtime = entry->file_mtime; + plugin->file_size = entry->file_size; + GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED); + + plugin->basename = g_path_get_basename (plugin->filename); + plugin->desc.name = g_intern_string (plugin->basename); + plugin->desc.description = "Plugin for blacklisted file"; + plugin->desc.version = "0.0.0"; + plugin->desc.license = "BLACKLIST"; + plugin->desc.source = plugin->desc.license; + plugin->desc.package = plugin->desc.license; + plugin->desc.origin = plugin->desc.license; + + GST_DEBUG ("Adding blacklist plugin '%s'", plugin->desc.name); + gst_registry_add_plugin (l->registry, plugin); +} + +#ifdef __APPLE__ +#if defined(__x86_64__) +#define USR_BIN_ARCH_SWITCH "-x86_64" +#elif defined(__i386__) +#define USR_BIN_ARCH_SWITCH "-i386" +#elif defined(__ppc__) +#define USR_BIN_ARCH_SWITCH "-ppc" +#elif defined(__ppc64__) +#define USR_BIN_ARCH_SWITCH "-ppc64" +#endif +#endif + +#define YES_MULTIARCH 1 +#define NO_MULTIARCH 2 + +#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) +static gboolean +gst_plugin_loader_use_usr_bin_arch (void) +{ + static volatile gsize multiarch = 0; + + if (g_once_init_enter (&multiarch)) { + gsize res = NO_MULTIARCH; + +#ifdef HAVE_SYS_UTSNAME_H + { + struct utsname uname_data; + + if (uname (&uname_data) == 0) { + /* Check for OS X >= 10.5 (darwin kernel 9.0) */ + GST_LOG ("%s %s", uname_data.sysname, uname_data.release); + if (g_ascii_strcasecmp (uname_data.sysname, "Darwin") == 0 && + g_strtod (uname_data.release, NULL) >= 9.0) { + res = YES_MULTIARCH; + } + } + } +#endif + + GST_INFO ("multiarch: %s", (res == YES_MULTIARCH) ? "yes" : "no"); + g_once_init_leave (&multiarch, res); + } + return (multiarch == YES_MULTIARCH); +} +#endif /* __APPLE__ && USR_BIN_ARCH_SWITCH */ + +static gboolean +gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) +{ + char *argv[6] = { NULL, }; + int c = 0; + +#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) + if (gst_plugin_loader_use_usr_bin_arch ()) { + argv[c++] = (char *) "/usr/bin/arch"; + argv[c++] = (char *) USR_BIN_ARCH_SWITCH; + } +#endif + argv[c++] = location; + argv[c++] = (char *) "-l"; + argv[c++] = _gst_executable_path; + argv[c++] = NULL; + + if (c > 4) { + GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s", + location, argv[1]); + } else { + GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location); + } + + if (!g_spawn_async_with_pipes (NULL, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDERR_TO_DEV_NULL */ , + NULL, NULL, &loader->child_pid, &loader->fd_w.fd, &loader->fd_r.fd, + NULL, NULL)) + return FALSE; + + gst_poll_add_fd (loader->fdset, &loader->fd_w); + gst_poll_add_fd (loader->fdset, &loader->fd_r); + + gst_poll_fd_ctl_read (loader->fdset, &loader->fd_r, TRUE); + + loader->tx_buf_write = loader->tx_buf_read = 0; + + put_packet (loader, PACKET_VERSION, 0, NULL, 0); + if (!plugin_loader_sync_with_child (loader)) + return FALSE; + + loader->child_running = TRUE; + + return TRUE; +} + +static gboolean +gst_plugin_loader_spawn (GstPluginLoader * loader) +{ + const gchar *env; + char *helper_bin; + gboolean res = FALSE; + + if (loader->child_running) + return TRUE; + + /* Find the gst-plugin-scanner: first try the env-var if it is set, + * otherwise use the installed version */ + env = g_getenv ("GST_PLUGIN_SCANNER_1_0"); + if (env == NULL) + env = g_getenv ("GST_PLUGIN_SCANNER"); + + if (env != NULL && *env != '\0') { + GST_LOG ("Trying GST_PLUGIN_SCANNER env var: %s", env); + helper_bin = g_strdup (env); + res = gst_plugin_loader_try_helper (loader, helper_bin); + g_free (helper_bin); + } + + if (!res) { + GST_LOG ("Trying installed plugin scanner"); + +#ifdef G_OS_WIN32 + { + gchar *basedir; + + basedir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + helper_bin = + g_build_filename (basedir, GST_PLUGIN_SCANNER_SUBDIR, + "gstreamer-" GST_API_VERSION, "gst-plugin-scanner.exe", NULL); + g_free (basedir); + } +#else + helper_bin = g_strdup (GST_PLUGIN_SCANNER_INSTALLED); +#endif + res = gst_plugin_loader_try_helper (loader, helper_bin); + g_free (helper_bin); + + if (!res) { + GST_INFO ("No gst-plugin-scanner available, or not working"); + } + } + + return loader->child_running; +} + +static void +plugin_loader_cleanup_child (GstPluginLoader * l) +{ + if (!l->child_running || l->is_child) + return; + + gst_poll_remove_fd (l->fdset, &l->fd_w); + gst_poll_remove_fd (l->fdset, &l->fd_r); + + close (l->fd_w.fd); + close (l->fd_r.fd); + +#ifndef G_OS_WIN32 + GST_LOG ("waiting for child process to exit"); + waitpid (l->child_pid, NULL, 0); +#else + g_warning ("FIXME: Implement child process shutdown for Win32"); +#endif + g_spawn_close_pid (l->child_pid); + + l->child_running = FALSE; +} + +gboolean +_gst_plugin_loader_client_run (void) +{ + gboolean res = TRUE; + GstPluginLoader *l; + + l = plugin_loader_new (NULL); + if (l == NULL) + return FALSE; + + /* On entry, the inward pipe is STDIN, and outward is STDOUT. + * Dup those somewhere better so that plugins printing things + * won't interfere with anything */ +#ifndef G_OS_WIN32 + { + int dup_fd; + + dup_fd = dup (0); /* STDIN */ + if (dup_fd == -1) { + GST_ERROR ("Failed to start. Could not dup STDIN, errno %d", errno); + res = FALSE; + goto beach; + } + l->fd_r.fd = dup_fd; + close (0); + + dup_fd = dup (1); /* STDOUT */ + if (dup_fd == -1) { + GST_ERROR ("Failed to start. Could not dup STDOUT, errno %d", errno); + res = FALSE; + goto beach; + } + l->fd_w.fd = dup_fd; + close (1); + + /* Dup stderr down to stdout so things that plugins print are visible, + * but don't care if it fails */ + dup2 (2, 1); + } +#else + /* FIXME: Use DuplicateHandle and friends on win32 */ + l->fd_w.fd = 1; /* STDOUT */ + l->fd_r.fd = 0; /* STDIN */ +#endif + + gst_poll_add_fd (l->fdset, &l->fd_w); + gst_poll_add_fd (l->fdset, &l->fd_r); + gst_poll_fd_ctl_read (l->fdset, &l->fd_r, TRUE); + + l->is_child = TRUE; + + GST_DEBUG ("Plugin scanner child running. Waiting for instructions"); + + /* Loop, listening for incoming packets on the fd and writing responses */ + while (!l->rx_done && exchange_packets (l)); + +#ifndef G_OS_WIN32 +beach: +#endif + + plugin_loader_free (l); + + return res; +} + +static void +put_packet (GstPluginLoader * l, guint type, guint32 tag, + const guint8 * payload, guint32 payload_len) +{ + guint8 *out; + guint len = payload_len + HEADER_SIZE; + + if (l->tx_buf_write + len >= l->tx_buf_size) { + GST_LOG ("Expanding tx buf from %d to %d for packet of size %d", + l->tx_buf_size, l->tx_buf_write + len + BUF_GROW_EXTRA, len); + l->tx_buf_size = l->tx_buf_write + len + BUF_GROW_EXTRA; + l->tx_buf = g_realloc (l->tx_buf, l->tx_buf_size); + } + + out = l->tx_buf + l->tx_buf_write; + + /* one byte packet type */ + out[0] = type; + /* 3 byte packet tag number */ + GST_WRITE_UINT24_BE (out + 1, tag); + /* 4 bytes packet length */ + GST_WRITE_UINT32_BE (out + 4, payload_len); + /* payload */ + if (payload && payload_len) + memcpy (out + HEADER_SIZE, payload, payload_len); + /* Write magic into the header */ + GST_WRITE_UINT32_BE (out + 8, HEADER_MAGIC); + + l->tx_buf_write += len; + gst_poll_fd_ctl_write (l->fdset, &l->fd_w, TRUE); +} + +static void +put_chunk (GstPluginLoader * l, GstRegistryChunk * chunk, guint * pos) +{ + guint padsize = 0; + guint len; + guint8 *out; + + /* Might need to align the chunk */ + if (chunk->align && ((*pos) % ALIGNMENT) != 0) + padsize = ALIGNMENT - ((*pos) % ALIGNMENT); + + len = padsize + chunk->size; + + if (G_UNLIKELY (l->tx_buf_write + len >= l->tx_buf_size)) { + guint new_size = MAX (l->tx_buf_write + len, + l->tx_buf_size + l->tx_buf_size / 4) + BUF_GROW_EXTRA; + GST_LOG ("Expanding tx buf from %d to %d for chunk of size %d", + l->tx_buf_size, new_size, chunk->size); + l->tx_buf_size = new_size; + l->tx_buf = g_realloc (l->tx_buf, l->tx_buf_size); + } + + out = l->tx_buf + l->tx_buf_write; + /* Clear the padding */ + if (padsize) + memset (out, 0, padsize); + memcpy (out + padsize, chunk->data, chunk->size); + + l->tx_buf_write += len; + *pos += len; + + gst_poll_fd_ctl_write (l->fdset, &l->fd_w, TRUE); +}; + +static gboolean +write_one (GstPluginLoader * l) +{ + guint8 *out; + guint32 to_write, magic; + int res; + + if (l->tx_buf_read + HEADER_SIZE > l->tx_buf_write) + return FALSE; + + out = l->tx_buf + l->tx_buf_read; + + magic = GST_READ_UINT32_BE (out + 8); + if (magic != HEADER_MAGIC) { + GST_ERROR ("Packet magic number is missing. Memory corruption detected"); + goto fail_and_cleanup; + } + + to_write = GST_READ_UINT32_BE (out + 4) + HEADER_SIZE; + /* Check that the magic is intact, and the size is sensible */ + if (to_write > l->tx_buf_size) { + GST_ERROR ("Indicated packet size is too large. Corruption detected"); + goto fail_and_cleanup; + } + + l->tx_buf_read += to_write; + + GST_LOG ("Writing packet of size %d bytes to fd %d", to_write, l->fd_w.fd); + + do { + res = write (l->fd_w.fd, out, to_write); + if (G_UNLIKELY (res < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + /* Failed to write -> child died */ + goto fail_and_cleanup; + } + to_write -= res; + out += res; + } while (to_write > 0); + + if (l->tx_buf_read == l->tx_buf_write) { + gst_poll_fd_ctl_write (l->fdset, &l->fd_w, FALSE); + l->tx_buf_read = l->tx_buf_write = 0; + } + + return TRUE; + +fail_and_cleanup: + plugin_loader_cleanup_child (l); + return FALSE; +} + +static gboolean +do_plugin_load (GstPluginLoader * l, const gchar * filename, guint tag) +{ + GstPlugin *newplugin; + GList *chunks = NULL; + + GST_DEBUG ("Plugin scanner loading file %s. tag %u", filename, tag); + +#if 0 /* Test code - crash based on filename */ + if (strstr (filename, "coreelements") == NULL) { + g_printerr ("Crashing on file %s\n", filename); + g_printerr ("%d", *(gint *) (NULL)); + } +#endif + + newplugin = gst_plugin_load_file ((gchar *) filename, NULL); + if (newplugin) { + guint hdr_pos; + guint offset; + + /* Now serialise the plugin details and send */ + if (!_priv_gst_registry_chunks_save_plugin (&chunks, + gst_registry_get (), newplugin)) + goto fail; + + /* Store where the header is, write an empty one, then write + * all the payload chunks, then fix up the header size */ + hdr_pos = l->tx_buf_write; + offset = HEADER_SIZE; + put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); + + if (chunks) { + GList *walk; + for (walk = chunks; walk; walk = g_list_next (walk)) { + GstRegistryChunk *cur = walk->data; + put_chunk (l, cur, &offset); + + _priv_gst_registry_chunk_free (cur); + } + + g_list_free (chunks); + + /* Store the size of the written payload */ + GST_WRITE_UINT32_BE (l->tx_buf + hdr_pos + 4, offset - HEADER_SIZE); + } +#if 0 /* Test code - corrupt the tx buffer based on filename */ + if (strstr (filename, "sink") != NULL) { + int fd, res; + g_printerr ("Corrupting tx buf on file %s\n", filename); + fd = open ("/dev/urandom", O_RDONLY); + res = read (fd, l->tx_buf, l->tx_buf_size); + close (fd); + } +#endif + + gst_object_unref (newplugin); + } else { + put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); + } + + return TRUE; +fail: + put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); + if (chunks) { + GList *walk; + for (walk = chunks; walk; walk = g_list_next (walk)) { + GstRegistryChunk *cur = walk->data; + + _priv_gst_registry_chunk_free (cur); + } + + g_list_free (chunks); + } + + return FALSE; +} + +static gboolean +check_protocol_version (GstPluginLoader * l, guint8 * payload, + guint payload_len) +{ + guint32 got_version; + guint8 *binary_reg_ver; + + if (payload_len < sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN) + return FALSE; + + got_version = GST_READ_UINT32_BE (payload); + GST_LOG ("Got VERSION %u from child. Ours is %u", got_version, + loader_protocol_version); + if (got_version != loader_protocol_version) + return FALSE; + + binary_reg_ver = payload + sizeof (guint32); + if (strcmp ((gchar *) binary_reg_ver, GST_MAGIC_BINARY_VERSION_STR)) { + GST_LOG ("Binary chunk format of child is different. Ours: %s, child %s\n", + GST_MAGIC_BINARY_VERSION_STR, binary_reg_ver); + return FALSE; + } + + return TRUE; +}; + +static gboolean +handle_rx_packet (GstPluginLoader * l, + guint pack_type, guint32 tag, guint8 * payload, guint payload_len) +{ + gboolean res = TRUE; + + switch (pack_type) { + case PACKET_EXIT: + gst_poll_fd_ctl_read (l->fdset, &l->fd_r, FALSE); + if (l->is_child) { + /* Respond */ + put_packet (l, PACKET_EXIT, 0, NULL, 0); + } + l->rx_done = TRUE; + return TRUE; + case PACKET_LOAD_PLUGIN:{ + if (!l->is_child) + return TRUE; + + /* Payload is the filename to load */ + res = do_plugin_load (l, (gchar *) payload, tag); + + break; + } + case PACKET_PLUGIN_DETAILS:{ + gchar *tmp = (gchar *) payload; + PendingPluginEntry *entry = NULL; + GList *cur; + + GST_DEBUG_OBJECT (l->registry, + "Received plugin details from child w/ tag %u. %d bytes info", + tag, payload_len); + + /* Assume that tagged details come back in the order + * we requested, and delete anything before (but not + * including) this one */ + cur = l->pending_plugins; + while (cur) { + PendingPluginEntry *e = (PendingPluginEntry *) (cur->data); + + if (e->tag > tag) + break; + + if (e->tag == tag) { + entry = e; + break; + } else { + cur = g_list_delete_link (cur, cur); + g_free (e->filename); + g_slice_free (PendingPluginEntry, e); + } + } + + l->pending_plugins = cur; + if (cur == NULL) + l->pending_plugins_tail = NULL; + + if (payload_len > 0) { + GstPlugin *newplugin = NULL; + if (!_priv_gst_registry_chunks_load_plugin (l->registry, &tmp, + tmp + payload_len, &newplugin)) { + /* Got garbage from the child, so fail and trigger replay of plugins */ + GST_ERROR_OBJECT (l->registry, + "Problems loading plugin details with tag %u from scanner", tag); + return FALSE; + } + + GST_OBJECT_FLAG_UNSET (newplugin, GST_PLUGIN_FLAG_CACHED); + GST_LOG_OBJECT (l->registry, + "marking plugin %p as registered as %s", newplugin, + newplugin->filename); + newplugin->registered = TRUE; + + /* We got a set of plugin details - remember it for later */ + l->got_plugin_details = TRUE; + } else if (entry != NULL) { + /* Create a blacklist entry for this file to prevent scanning every time */ + plugin_loader_create_blacklist_plugin (l, entry); + l->got_plugin_details = TRUE; + } + + if (entry != NULL) { + g_free (entry->filename); + g_slice_free (PendingPluginEntry, entry); + } + + /* Remove the plugin entry we just loaded */ + cur = l->pending_plugins; + if (cur != NULL) + cur = g_list_delete_link (cur, cur); + l->pending_plugins = cur; + if (cur == NULL) + l->pending_plugins_tail = NULL; + + break; + } + case PACKET_SYNC: + if (l->is_child) { + /* Respond with our reply - also a sync */ + put_packet (l, PACKET_SYNC, tag, NULL, 0); + GST_LOG ("Got SYNC in child - replying"); + } else + l->rx_got_sync = TRUE; + break; + case PACKET_VERSION: + if (l->is_child) { + /* Respond with our reply - a version packet, with the version */ + const gint version_len = + sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN; + guint8 version_info[sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN]; + memset (version_info, 0, version_len); + GST_WRITE_UINT32_BE (version_info, loader_protocol_version); + memcpy (version_info + sizeof (guint32), GST_MAGIC_BINARY_VERSION_STR, + strlen (GST_MAGIC_BINARY_VERSION_STR)); + put_packet (l, PACKET_VERSION, tag, version_info, version_len); + GST_LOG ("Got VERSION in child - replying %u", loader_protocol_version); + } else { + res = check_protocol_version (l, payload, payload_len); + } + break; + default: + return FALSE; /* Invalid packet -> something is wrong */ + } + + return res; +} + +static gboolean +read_one (GstPluginLoader * l) +{ + guint64 magic; + guint32 to_read, packet_len, tag; + guint8 *in; + gint res; + + to_read = HEADER_SIZE; + in = l->rx_buf; + do { + res = read (l->fd_r.fd, in, to_read); + if (G_UNLIKELY (res < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + GST_LOG ("Failed reading packet header"); + return FALSE; + } + to_read -= res; + in += res; + } while (to_read > 0); + + magic = GST_READ_UINT32_BE (l->rx_buf + 8); + if (magic != HEADER_MAGIC) { + GST_WARNING + ("Invalid packet (bad magic number) received from plugin scanner subprocess"); + return FALSE; + } + + packet_len = GST_READ_UINT32_BE (l->rx_buf + 4); + if (packet_len + HEADER_SIZE > BUF_MAX_SIZE) { + GST_WARNING + ("Received excessively large packet for plugin scanner subprocess"); + return FALSE; + } + tag = GST_READ_UINT24_BE (l->rx_buf + 1); + + if (packet_len > 0) { + if (packet_len + HEADER_SIZE >= l->rx_buf_size) { + GST_LOG ("Expanding rx buf from %d to %d", + l->rx_buf_size, packet_len + HEADER_SIZE + BUF_GROW_EXTRA); + l->rx_buf_size = packet_len + HEADER_SIZE + BUF_GROW_EXTRA; + l->rx_buf = g_realloc (l->rx_buf, l->rx_buf_size); + } + + in = l->rx_buf + HEADER_SIZE; + to_read = packet_len; + do { + res = read (l->fd_r.fd, in, to_read); + if (G_UNLIKELY (res < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + GST_ERROR ("Packet payload read failed"); + return FALSE; + } + to_read -= res; + in += res; + } while (to_read > 0); + } else { + GST_LOG ("No payload to read for 0 length packet type %d tag %u", + l->rx_buf[0], tag); + } + + return handle_rx_packet (l, l->rx_buf[0], tag, + l->rx_buf + HEADER_SIZE, packet_len); +} + +static gboolean +exchange_packets (GstPluginLoader * l) +{ + gint res; + + /* Wait for activity on our FDs */ + do { + do { + res = gst_poll_wait (l->fdset, GST_SECOND); + } while (res == -1 && (errno == EINTR || errno == EAGAIN)); + + if (res < 0) + return FALSE; + + GST_LOG ("Poll res = %d. %d bytes pending for write", res, + l->tx_buf_write - l->tx_buf_read); + + if (!l->rx_done) { + if (gst_poll_fd_has_error (l->fdset, &l->fd_r)) { + GST_LOG ("read fd %d errored", l->fd_r.fd); + goto fail_and_cleanup; + } + + if (gst_poll_fd_can_read (l->fdset, &l->fd_r)) { + if (!read_one (l)) + goto fail_and_cleanup; + } else if (gst_poll_fd_has_closed (l->fdset, &l->fd_r)) { + GST_LOG ("read fd %d closed", l->fd_r.fd); + goto fail_and_cleanup; + } + } + + if (l->tx_buf_read < l->tx_buf_write) { + if (gst_poll_fd_has_error (l->fdset, &l->fd_w)) { + GST_ERROR ("write fd %d errored", l->fd_w.fd); + goto fail_and_cleanup; + } + if (gst_poll_fd_can_write (l->fdset, &l->fd_w)) { + if (!write_one (l)) + goto fail_and_cleanup; + } else if (gst_poll_fd_has_closed (l->fdset, &l->fd_w)) { + GST_LOG ("write fd %d closed", l->fd_w.fd); + goto fail_and_cleanup; + } + } + } while (l->tx_buf_read < l->tx_buf_write); + + return TRUE; +fail_and_cleanup: + plugin_loader_cleanup_child (l); + return FALSE; +} diff --git a/gst/gstpluginloader.h b/gst/gstpluginloader.h new file mode 100644 index 0000000..dfbac59 --- /dev/null +++ b/gst/gstpluginloader.h @@ -0,0 +1,42 @@ +/* GStreamer + * Copyright (C) 2008 Jan Schmidt + * + * gstpluginloader.h: Helper for out-of-process plugin loading. Private header. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __GST_PLUGINLOADER_H__ +#define __GST_PLUGINLOADER_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstPluginLoader GstPluginLoader; + +typedef struct _GstPluginLoaderFuncs { + GstPluginLoader * (*create) (GstRegistry *registry); + gboolean (*destroy) (GstPluginLoader *loader); + gboolean (*load) (GstPluginLoader *loader, const gchar *filename, + off_t file_size, time_t file_mtime); +} GstPluginLoaderFuncs; + +extern const GstPluginLoaderFuncs _priv_gst_plugin_loader_funcs; + +G_END_DECLS + +#endif /* __GST_PLUGINLOADER_H__ */ diff --git a/gst/gstpoll.c b/gst/gstpoll.c new file mode 100644 index 0000000..fd672ed --- /dev/null +++ b/gst/gstpoll.c @@ -0,0 +1,1692 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2007 Peter Kjellerstedt + * Copyright (C) 2008 Ole André Vadla Ravnås + * + * gstpoll.c: File descriptor set + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstpoll + * @title: GstPoll + * @short_description: Keep track of file descriptors and make it possible + * to wait on them in a cancellable way + * + * A #GstPoll keeps track of file descriptors much like fd_set (used with + * select()) or a struct pollfd array (used with poll()). Once created with + * gst_poll_new(), the set can be used to wait for file descriptors to be + * readable and/or writable. It is possible to make this wait be controlled + * by specifying %TRUE for the @controllable flag when creating the set (or + * later calling gst_poll_set_controllable()). + * + * New file descriptors are added to the set using gst_poll_add_fd(), and + * removed using gst_poll_remove_fd(). Controlling which file descriptors + * should be waited for to become readable and/or writable are done using + * gst_poll_fd_ctl_read() and gst_poll_fd_ctl_write(). + * + * Use gst_poll_wait() to wait for the file descriptors to actually become + * readable and/or writable, or to timeout if no file descriptor is available + * in time. The wait can be controlled by calling gst_poll_restart() and + * gst_poll_set_flushing(). + * + * Once the file descriptor set has been waited for, one can use + * gst_poll_fd_has_closed() to see if the file descriptor has been closed, + * gst_poll_fd_has_error() to see if it has generated an error, + * gst_poll_fd_can_read() to see if it is possible to read from the file + * descriptor, and gst_poll_fd_can_write() to see if it is possible to + * write to it. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "glib-compat-private.h" + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include + +#include + +#ifdef G_OS_WIN32 +#include +#else +#define _GNU_SOURCE 1 +#ifdef HAVE_SYS_POLL_H +#include +#endif +#ifdef HAVE_POLL_H +#include +#endif +#include +#include +#endif + +#ifdef G_OS_WIN32 +# ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN /* This is just to placate gcc */ +# endif +#endif /* G_OS_WIN32 */ + +/* OS/X needs this because of bad headers */ +#include + +/* The poll() emulation on OS/X doesn't handle fds=NULL, nfds=0, + * so we prefer our own poll emulation. + */ +#if defined(BROKEN_POLL) +#undef HAVE_POLL +#endif + +#include "gstpoll.h" + +#define GST_CAT_DEFAULT GST_CAT_POLL + +#ifdef G_OS_WIN32 +typedef struct _WinsockFd WinsockFd; + +struct _WinsockFd +{ + gint fd; + glong event_mask; + WSANETWORKEVENTS events; + glong ignored_event_mask; +}; +#endif + +typedef enum +{ + GST_POLL_MODE_AUTO, + GST_POLL_MODE_SELECT, + GST_POLL_MODE_PSELECT, + GST_POLL_MODE_POLL, + GST_POLL_MODE_PPOLL, + GST_POLL_MODE_WINDOWS +} GstPollMode; + +struct _GstPoll +{ + GstPollMode mode; + + GMutex lock; + /* array of fds, always written to and read from with lock */ + GArray *fds; + /* array of active fds, only written to from the waiting thread with the + * lock and read from with the lock or without the lock from the waiting + * thread */ + GArray *active_fds; + +#ifndef G_OS_WIN32 + GstPollFD control_read_fd; + GstPollFD control_write_fd; +#else + GArray *active_fds_ignored; + GArray *events; + GArray *active_events; + + HANDLE wakeup_event; +#endif + + gboolean controllable; + volatile gint waiting; + volatile gint control_pending; + volatile gint flushing; + gboolean timer; + volatile gint rebuild; +}; + +static gboolean gst_poll_fd_ctl_read_unlocked (GstPoll * set, GstPollFD * fd, + gboolean active); +static gboolean gst_poll_add_fd_unlocked (GstPoll * set, GstPollFD * fd); + +#define IS_FLUSHING(s) (g_atomic_int_get(&(s)->flushing)) +#define SET_FLUSHING(s,val) (g_atomic_int_set(&(s)->flushing, (val))) + +#define INC_WAITING(s) (g_atomic_int_add(&(s)->waiting, 1)) +#define DEC_WAITING(s) (g_atomic_int_add(&(s)->waiting, -1)) +#define GET_WAITING(s) (g_atomic_int_get(&(s)->waiting)) + +#define TEST_REBUILD(s) (g_atomic_int_compare_and_exchange(&(s)->rebuild, 1, 0)) +#define MARK_REBUILD(s) (g_atomic_int_set(&(s)->rebuild, 1)) + +#ifndef G_OS_WIN32 + +static gboolean +wake_event (GstPoll * set) +{ + ssize_t num_written; + while ((num_written = write (set->control_write_fd.fd, "W", 1)) != 1) { + if (num_written == -1 && errno != EAGAIN && errno != EINTR) { + g_critical ("%p: failed to wake event: %s", set, strerror (errno)); + return FALSE; + } + } + return TRUE; +} + +static gboolean +release_event (GstPoll * set) +{ + gchar buf[1] = { '\0' }; + ssize_t num_read; + while ((num_read = read (set->control_read_fd.fd, buf, 1)) != 1) { + if (num_read == -1 && errno != EAGAIN && errno != EINTR) { + g_critical ("%p: failed to release event: %s", set, strerror (errno)); + return FALSE; + } + } + return TRUE; +} + +#else + +static void +format_last_error (gchar * buf, size_t buf_len) +{ + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM; + LPCVOID src = NULL; + DWORD lang = 0; + DWORD id; + id = GetLastError (); + FormatMessage (flags, src, id, lang, buf, (DWORD) buf_len, NULL); + SetLastError (id); +} + +static gboolean +wake_event (GstPoll * set) +{ + SetLastError (0); + errno = 0; + if (!SetEvent (set->wakeup_event)) { + gchar msg[1024] = ""; + format_last_error (msg, sizeof (msg)); + g_critical ("%p: failed to set wakup_event: %s", set, msg); + errno = EBADF; + return FALSE; + } + + return TRUE; +} + +static gboolean +release_event (GstPoll * set) +{ + DWORD status; + SetLastError (0); + errno = 0; + + status = WaitForSingleObject (set->wakeup_event, INFINITE); + if (status) { + const gchar *reason = "unknown"; + gchar msg[1024] = ""; + switch (status) { + case WAIT_ABANDONED: + reason = "WAIT_ABANDONED"; + break; + case WAIT_TIMEOUT: + reason = "WAIT_TIMEOUT"; + break; + case WAIT_FAILED: + format_last_error (msg, sizeof (msg)); + reason = msg; + break; + default: + reason = "other"; + break; + } + g_critical ("%p: failed to block on wakup_event: %s", set, reason); + errno = EBADF; + return FALSE; + } + + if (!ResetEvent (set->wakeup_event)) { + gchar msg[1024] = ""; + format_last_error (msg, sizeof (msg)); + g_critical ("%p: failed to reset wakup_event: %s", set, msg); + errno = EBADF; + return FALSE; + } + + return TRUE; +} + +#endif + +/* the poll/select call is also performed on a control socket, that way + * we can send special commands to control it */ +static inline gboolean +raise_wakeup (GstPoll * set) +{ + gboolean result = TRUE; + + /* makes testing control_pending and WAKE_EVENT() atomic. */ + g_mutex_lock (&set->lock); + + if (set->control_pending == 0) { + /* raise when nothing pending */ + GST_LOG ("%p: raise", set); + result = wake_event (set); + } + + if (result) { + set->control_pending++; + } + + g_mutex_unlock (&set->lock); + + return result; +} + +static inline gboolean +release_wakeup (GstPoll * set) +{ + gboolean result = FALSE; + + /* makes testing/modifying control_pending and RELEASE_EVENT() atomic. */ + g_mutex_lock (&set->lock); + + if (set->control_pending > 0) { + /* release, only if this was the last pending. */ + if (set->control_pending == 1) { + GST_LOG ("%p: release", set); + result = release_event (set); + } else { + result = TRUE; + } + + if (result) { + set->control_pending--; + } + } else { + errno = EWOULDBLOCK; + } + + g_mutex_unlock (&set->lock); + + return result; +} + +static inline gint +release_all_wakeup (GstPoll * set) +{ + gint old; + + /* makes testing control_pending and RELEASE_EVENT() atomic. */ + g_mutex_lock (&set->lock); + + if ((old = set->control_pending) > 0) { + GST_LOG ("%p: releasing %d", set, old); + if (release_event (set)) { + set->control_pending = 0; + } else { + old = 0; + } + } + + g_mutex_unlock (&set->lock); + + return old; +} + +static gint +find_index (GArray * array, GstPollFD * fd) +{ +#ifndef G_OS_WIN32 + struct pollfd *ifd; +#else + WinsockFd *ifd; +#endif + guint i; + + /* start by assuming the index found in the fd is still valid */ + if (fd->idx >= 0 && fd->idx < array->len) { +#ifndef G_OS_WIN32 + ifd = &g_array_index (array, struct pollfd, fd->idx); +#else + ifd = &g_array_index (array, WinsockFd, fd->idx); +#endif + + if (ifd->fd == fd->fd) { + return fd->idx; + } + } + + /* the pollfd array has changed and we need to lookup the fd again */ + for (i = 0; i < array->len; i++) { +#ifndef G_OS_WIN32 + ifd = &g_array_index (array, struct pollfd, i); +#else + ifd = &g_array_index (array, WinsockFd, i); +#endif + + if (ifd->fd == fd->fd) { + fd->idx = (gint) i; + return fd->idx; + } + } + + fd->idx = -1; + return fd->idx; +} + +#if !defined(HAVE_PPOLL) && defined(HAVE_POLL) +/* check if all file descriptors will fit in an fd_set */ +static gboolean +selectable_fds (GstPoll * set) +{ + guint i; + + g_mutex_lock (&set->lock); + for (i = 0; i < set->fds->len; i++) { + struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, i); + + if (pfd->fd >= FD_SETSIZE) + goto too_many; + } + g_mutex_unlock (&set->lock); + + return TRUE; + +too_many: + { + g_mutex_unlock (&set->lock); + return FALSE; + } +} + +/* check if the timeout will convert to a timeout value used for poll() + * without a loss of precision + */ +static gboolean +pollable_timeout (GstClockTime timeout) +{ + if (timeout == GST_CLOCK_TIME_NONE) + return TRUE; + + /* not a nice multiple of milliseconds */ + if (timeout % 1000000) + return FALSE; + + return TRUE; +} +#endif + +static GstPollMode +choose_mode (GstPoll * set, GstClockTime timeout) +{ + GstPollMode mode; + + if (set->mode == GST_POLL_MODE_AUTO) { +#ifdef HAVE_PPOLL + mode = GST_POLL_MODE_PPOLL; +#elif defined(HAVE_POLL) + if (!selectable_fds (set) || pollable_timeout (timeout)) { + mode = GST_POLL_MODE_POLL; + } else { +#ifdef HAVE_PSELECT + mode = GST_POLL_MODE_PSELECT; +#else + mode = GST_POLL_MODE_SELECT; +#endif + } +#elif defined(HAVE_PSELECT) + mode = GST_POLL_MODE_PSELECT; +#else + mode = GST_POLL_MODE_SELECT; +#endif + } else { + mode = set->mode; + } + return mode; +} + +#ifndef G_OS_WIN32 +static gint +pollfd_to_fd_set (GstPoll * set, fd_set * readfds, fd_set * writefds, + fd_set * errorfds) +{ + gint max_fd = -1; + guint i; + + FD_ZERO (readfds); + FD_ZERO (writefds); + FD_ZERO (errorfds); + + g_mutex_lock (&set->lock); + + for (i = 0; i < set->active_fds->len; i++) { + struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, i); + + if (pfd->fd < FD_SETSIZE) { + if (pfd->events & POLLIN) + FD_SET (pfd->fd, readfds); + if (pfd->events & POLLOUT) + FD_SET (pfd->fd, writefds); + if (pfd->events) + FD_SET (pfd->fd, errorfds); + if (pfd->fd > max_fd && (pfd->events & (POLLIN | POLLOUT))) + max_fd = pfd->fd; + } + } + + g_mutex_unlock (&set->lock); + + return max_fd; +} + +static void +fd_set_to_pollfd (GstPoll * set, fd_set * readfds, fd_set * writefds, + fd_set * errorfds) +{ + guint i; + + g_mutex_lock (&set->lock); + + for (i = 0; i < set->active_fds->len; i++) { + struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, i); + + if (pfd->fd < FD_SETSIZE) { + pfd->revents = 0; + if (FD_ISSET (pfd->fd, readfds)) + pfd->revents |= POLLIN; + if (FD_ISSET (pfd->fd, writefds)) + pfd->revents |= POLLOUT; + if (FD_ISSET (pfd->fd, errorfds)) + pfd->revents |= POLLERR; + } + } + + g_mutex_unlock (&set->lock); +} +#else /* G_OS_WIN32 */ +/* + * Translate errors thrown by the Winsock API used by GstPoll: + * WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents + */ +static gint +gst_poll_winsock_error_to_errno (DWORD last_error) +{ + switch (last_error) { + case WSA_INVALID_HANDLE: + case WSAEINVAL: + case WSAENOTSOCK: + return EBADF; + + case WSA_NOT_ENOUGH_MEMORY: + return ENOMEM; + + /* + * Anything else, including: + * WSA_INVALID_PARAMETER, WSAEFAULT, WSAEINPROGRESS, WSAENETDOWN, + * WSANOTINITIALISED + */ + default: + return EINVAL; + } +} + +static void +gst_poll_free_winsock_event (GstPoll * set, gint idx) +{ + WinsockFd *wfd = &g_array_index (set->fds, WinsockFd, idx); + HANDLE event = g_array_index (set->events, HANDLE, idx); + + WSAEventSelect (wfd->fd, event, 0); + CloseHandle (event); +} + +static void +gst_poll_update_winsock_event_mask (GstPoll * set, gint idx, glong flags, + gboolean active) +{ + WinsockFd *wfd; + + wfd = &g_array_index (set->fds, WinsockFd, idx); + + if (active) + wfd->event_mask |= flags; + else + wfd->event_mask &= ~flags; + + /* reset ignored state if the new mask doesn't overlap at all */ + if ((wfd->ignored_event_mask & wfd->event_mask) == 0) + wfd->ignored_event_mask = 0; +} + +static gboolean +gst_poll_prepare_winsock_active_sets (GstPoll * set) +{ + guint i; + + g_array_set_size (set->active_fds, 0); + g_array_set_size (set->active_fds_ignored, 0); + g_array_set_size (set->active_events, 0); + g_array_append_val (set->active_events, set->wakeup_event); + + for (i = 0; i < set->fds->len; i++) { + WinsockFd *wfd = &g_array_index (set->fds, WinsockFd, i); + HANDLE event = g_array_index (set->events, HANDLE, i); + + if (wfd->ignored_event_mask == 0) { + gint ret; + + g_array_append_val (set->active_fds, *wfd); + g_array_append_val (set->active_events, event); + + ret = WSAEventSelect (wfd->fd, event, wfd->event_mask); + if (G_UNLIKELY (ret != 0)) { + errno = gst_poll_winsock_error_to_errno (WSAGetLastError ()); + return FALSE; + } + } else { + g_array_append_val (set->active_fds_ignored, wfd); + } + } + + return TRUE; +} + +static gint +gst_poll_collect_winsock_events (GstPoll * set) +{ + gint res, i; + + /* + * We need to check which events are signaled, and call + * WSAEnumNetworkEvents for those that are, which resets + * the event and clears the internal network event records. + */ + res = 0; + for (i = 0; i < set->active_fds->len; i++) { + WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, i); + HANDLE event = g_array_index (set->active_events, HANDLE, i + 1); + DWORD wait_ret; + + wait_ret = WaitForSingleObject (event, 0); + if (wait_ret == WAIT_OBJECT_0) { + gint enum_ret = WSAEnumNetworkEvents (wfd->fd, event, &wfd->events); + + if (G_UNLIKELY (enum_ret != 0)) { + res = -1; + errno = gst_poll_winsock_error_to_errno (WSAGetLastError ()); + break; + } + + res++; + } else { + /* clear any previously stored result */ + memset (&wfd->events, 0, sizeof (wfd->events)); + } + } + + /* If all went well we also need to reset the ignored fds. */ + if (res >= 0) { + res += set->active_fds_ignored->len; + + for (i = 0; i < set->active_fds_ignored->len; i++) { + WinsockFd *wfd = g_array_index (set->active_fds_ignored, WinsockFd *, i); + + wfd->ignored_event_mask = 0; + } + + g_array_set_size (set->active_fds_ignored, 0); + } + + return res; +} +#endif + +/** + * gst_poll_new: (skip) + * @controllable: whether it should be possible to control a wait. + * + * Create a new file descriptor set. If @controllable, it + * is possible to restart or flush a call to gst_poll_wait() with + * gst_poll_restart() and gst_poll_set_flushing() respectively. + * + * Free-function: gst_poll_free + * + * Returns: (transfer full) (nullable): a new #GstPoll, or %NULL in + * case of an error. Free with gst_poll_free(). + */ +GstPoll * +gst_poll_new (gboolean controllable) +{ + GstPoll *nset; + + nset = g_slice_new0 (GstPoll); + GST_DEBUG ("%p: new controllable : %d", nset, controllable); + g_mutex_init (&nset->lock); +#ifndef G_OS_WIN32 + nset->mode = GST_POLL_MODE_AUTO; + nset->fds = g_array_new (FALSE, FALSE, sizeof (struct pollfd)); + nset->active_fds = g_array_new (FALSE, FALSE, sizeof (struct pollfd)); + nset->control_read_fd.fd = -1; + nset->control_write_fd.fd = -1; + { + gint control_sock[2]; + + if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0) + goto no_socket_pair; + + nset->control_read_fd.fd = control_sock[0]; + nset->control_write_fd.fd = control_sock[1]; + + gst_poll_add_fd_unlocked (nset, &nset->control_read_fd); + gst_poll_fd_ctl_read_unlocked (nset, &nset->control_read_fd, TRUE); + } +#else + nset->mode = GST_POLL_MODE_WINDOWS; + nset->fds = g_array_new (FALSE, FALSE, sizeof (WinsockFd)); + nset->active_fds = g_array_new (FALSE, FALSE, sizeof (WinsockFd)); + nset->active_fds_ignored = g_array_new (FALSE, FALSE, sizeof (WinsockFd *)); + nset->events = g_array_new (FALSE, FALSE, sizeof (HANDLE)); + nset->active_events = g_array_new (FALSE, FALSE, sizeof (HANDLE)); + + nset->wakeup_event = CreateEvent (NULL, TRUE, FALSE, NULL); +#endif + + /* ensure (re)build, though already sneakily set in non-windows case */ + MARK_REBUILD (nset); + + nset->controllable = controllable; + nset->control_pending = 0; + + return nset; + + /* ERRORS */ +#ifndef G_OS_WIN32 +no_socket_pair: + { + GST_WARNING ("%p: can't create socket pair !", nset); + gst_poll_free (nset); + return NULL; + } +#endif +} + +/** + * gst_poll_new_timer: (skip) + * + * Create a new poll object that can be used for scheduling cancellable + * timeouts. + * + * A timeout is performed with gst_poll_wait(). Multiple timeouts can be + * performed from different threads. + * + * Free-function: gst_poll_free + * + * Returns: (transfer full) (nullable): a new #GstPoll, or %NULL in + * case of an error. Free with gst_poll_free(). + */ +GstPoll * +gst_poll_new_timer (void) +{ + GstPoll *poll; + + /* make a new controllable poll set */ + if (!(poll = gst_poll_new (TRUE))) + goto done; + + /* we are a timer */ + poll->timer = TRUE; + +done: + return poll; +} + +/** + * gst_poll_free: + * @set: (transfer full): a file descriptor set. + * + * Free a file descriptor set. + */ +void +gst_poll_free (GstPoll * set) +{ + g_return_if_fail (set != NULL); + + GST_DEBUG ("%p: freeing", set); + +#ifndef G_OS_WIN32 + if (set->control_write_fd.fd >= 0) + close (set->control_write_fd.fd); + if (set->control_read_fd.fd >= 0) + close (set->control_read_fd.fd); +#else + CloseHandle (set->wakeup_event); + + { + guint i; + + for (i = 0; i < set->events->len; i++) + gst_poll_free_winsock_event (set, i); + } + + g_array_free (set->active_events, TRUE); + g_array_free (set->events, TRUE); + g_array_free (set->active_fds_ignored, TRUE); +#endif + + g_array_free (set->active_fds, TRUE); + g_array_free (set->fds, TRUE); + g_mutex_clear (&set->lock); + g_slice_free (GstPoll, set); +} + +/** + * gst_poll_get_read_gpollfd: + * @set: a #GstPoll + * @fd: a #GPollFD + * + * Get a GPollFD for the reading part of the control socket. This is useful when + * integrating with a GSource and GMainLoop. + */ +void +gst_poll_get_read_gpollfd (GstPoll * set, GPollFD * fd) +{ + g_return_if_fail (set != NULL); + g_return_if_fail (fd != NULL); + +#ifndef G_OS_WIN32 + fd->fd = set->control_read_fd.fd; +#else +#if GLIB_SIZEOF_VOID_P == 8 + fd->fd = (gint64) set->wakeup_event; +#else + fd->fd = (gint) set->wakeup_event; +#endif +#endif + fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; + fd->revents = 0; +} + +/** + * gst_poll_fd_init: + * @fd: a #GstPollFD + * + * Initializes @fd. Alternatively you can initialize it with + * #GST_POLL_FD_INIT. + */ +void +gst_poll_fd_init (GstPollFD * fd) +{ + g_return_if_fail (fd != NULL); + + fd->fd = -1; + fd->idx = -1; +} + +static gboolean +gst_poll_add_fd_unlocked (GstPoll * set, GstPollFD * fd) +{ + gint idx; + + GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx); + + idx = find_index (set->fds, fd); + if (idx < 0) { +#ifndef G_OS_WIN32 + struct pollfd nfd; + + nfd.fd = fd->fd; + nfd.events = POLLERR | POLLNVAL | POLLHUP; + nfd.revents = 0; + + g_array_append_val (set->fds, nfd); + + fd->idx = set->fds->len - 1; +#else + WinsockFd wfd; + HANDLE event; + + wfd.fd = fd->fd; + wfd.event_mask = FD_CLOSE; + memset (&wfd.events, 0, sizeof (wfd.events)); + wfd.ignored_event_mask = 0; + event = WSACreateEvent (); + + g_array_append_val (set->fds, wfd); + g_array_append_val (set->events, event); + + fd->idx = set->fds->len - 1; +#endif + MARK_REBUILD (set); + } else { + GST_WARNING ("%p: fd already added !", set); + } + + return TRUE; +} + +/** + * gst_poll_add_fd: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Add a file descriptor to the file descriptor set. + * + * Returns: %TRUE if the file descriptor was successfully added to the set. + */ +gboolean +gst_poll_add_fd (GstPoll * set, GstPollFD * fd) +{ + gboolean ret; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&set->lock); + + ret = gst_poll_add_fd_unlocked (set, fd); + + g_mutex_unlock (&set->lock); + + return ret; +} + +/** + * gst_poll_remove_fd: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Remove a file descriptor from the file descriptor set. + * + * Returns: %TRUE if the file descriptor was successfully removed from the set. + */ +gboolean +gst_poll_remove_fd (GstPoll * set, GstPollFD * fd) +{ + gint idx; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + + GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx); + + g_mutex_lock (&set->lock); + + /* get the index, -1 is an fd that is not added */ + idx = find_index (set->fds, fd); + if (idx >= 0) { +#ifdef G_OS_WIN32 + gst_poll_free_winsock_event (set, idx); + g_array_remove_index_fast (set->events, idx); +#endif + + /* remove the fd at index, we use _remove_index_fast, which copies the last + * element of the array to the freed index */ + g_array_remove_index_fast (set->fds, idx); + + /* mark fd as removed by setting the index to -1 */ + fd->idx = -1; + MARK_REBUILD (set); + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + + g_mutex_unlock (&set->lock); + + return idx >= 0; +} + +/** + * gst_poll_fd_ctl_write: + * @set: a file descriptor set. + * @fd: a file descriptor. + * @active: a new status. + * + * Control whether the descriptor @fd in @set will be monitored for + * writability. + * + * Returns: %TRUE if the descriptor was successfully updated. + */ +gboolean +gst_poll_fd_ctl_write (GstPoll * set, GstPollFD * fd, gboolean active) +{ + gint idx; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + GST_DEBUG ("%p: fd (fd:%d, idx:%d), active : %d", set, + fd->fd, fd->idx, active); + + g_mutex_lock (&set->lock); + + idx = find_index (set->fds, fd); + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, idx); + + if (active) + pfd->events |= POLLOUT; + else + pfd->events &= ~POLLOUT; + + GST_LOG ("%p: pfd->events now %d (POLLOUT:%d)", set, pfd->events, POLLOUT); +#else + gst_poll_update_winsock_event_mask (set, idx, FD_WRITE | FD_CONNECT, + active); +#endif + MARK_REBUILD (set); + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + + g_mutex_unlock (&set->lock); + + return idx >= 0; +} + +static gboolean +gst_poll_fd_ctl_read_unlocked (GstPoll * set, GstPollFD * fd, gboolean active) +{ + gint idx; + + GST_DEBUG ("%p: fd (fd:%d, idx:%d), active : %d", set, + fd->fd, fd->idx, active); + + idx = find_index (set->fds, fd); + + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, idx); + + if (active) + pfd->events |= (POLLIN | POLLPRI); + else + pfd->events &= ~(POLLIN | POLLPRI); +#else + gst_poll_update_winsock_event_mask (set, idx, FD_READ | FD_ACCEPT, active); +#endif + MARK_REBUILD (set); + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + + return idx >= 0; +} + +/** + * gst_poll_fd_ctl_read: + * @set: a file descriptor set. + * @fd: a file descriptor. + * @active: a new status. + * + * Control whether the descriptor @fd in @set will be monitored for + * readability. + * + * Returns: %TRUE if the descriptor was successfully updated. + */ +gboolean +gst_poll_fd_ctl_read (GstPoll * set, GstPollFD * fd, gboolean active) +{ + gboolean ret; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&set->lock); + + ret = gst_poll_fd_ctl_read_unlocked (set, fd, active); + + g_mutex_unlock (&set->lock); + + return ret; +} + +/** + * gst_poll_fd_ignored: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Mark @fd as ignored so that the next call to gst_poll_wait() will yield + * the same result for @fd as last time. This function must be called if no + * operation (read/write/recv/send/etc.) will be performed on @fd before + * the next call to gst_poll_wait(). + * + * The reason why this is needed is because the underlying implementation + * might not allow querying the fd more than once between calls to one of + * the re-enabling operations. + */ +void +gst_poll_fd_ignored (GstPoll * set, GstPollFD * fd) +{ +#ifdef G_OS_WIN32 + gint idx; + + g_return_if_fail (set != NULL); + g_return_if_fail (fd != NULL); + g_return_if_fail (fd->fd >= 0); + + g_mutex_lock (&set->lock); + + idx = find_index (set->fds, fd); + if (idx >= 0) { + WinsockFd *wfd = &g_array_index (set->fds, WinsockFd, idx); + + wfd->ignored_event_mask = wfd->event_mask & (FD_READ | FD_WRITE); + MARK_REBUILD (set); + } + + g_mutex_unlock (&set->lock); +#endif +} + +/** + * gst_poll_fd_has_closed: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Check if @fd in @set has closed the connection. + * + * Returns: %TRUE if the connection was closed. + */ +gboolean +gst_poll_fd_has_closed (const GstPoll * set, GstPollFD * fd) +{ + gboolean res = FALSE; + gint idx; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&((GstPoll *) set)->lock); + + idx = find_index (set->active_fds, fd); + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx); + + res = (pfd->revents & POLLHUP) != 0; +#else + WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx); + + res = (wfd->events.lNetworkEvents & FD_CLOSE) != 0; +#endif + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + g_mutex_unlock (&((GstPoll *) set)->lock); + + GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res); + + return res; +} + +/** + * gst_poll_fd_has_error: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Check if @fd in @set has an error. + * + * Returns: %TRUE if the descriptor has an error. + */ +gboolean +gst_poll_fd_has_error (const GstPoll * set, GstPollFD * fd) +{ + gboolean res = FALSE; + gint idx; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&((GstPoll *) set)->lock); + + idx = find_index (set->active_fds, fd); + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx); + + res = (pfd->revents & (POLLERR | POLLNVAL)) != 0; +#else + WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx); + + res = (wfd->events.iErrorCode[FD_CLOSE_BIT] != 0) || + (wfd->events.iErrorCode[FD_READ_BIT] != 0) || + (wfd->events.iErrorCode[FD_WRITE_BIT] != 0) || + (wfd->events.iErrorCode[FD_ACCEPT_BIT] != 0) || + (wfd->events.iErrorCode[FD_CONNECT_BIT] != 0); +#endif + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + g_mutex_unlock (&((GstPoll *) set)->lock); + + GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res); + + return res; +} + +static gboolean +gst_poll_fd_can_read_unlocked (const GstPoll * set, GstPollFD * fd) +{ + gboolean res = FALSE; + gint idx; + + idx = find_index (set->active_fds, fd); + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx); + + res = (pfd->revents & (POLLIN | POLLPRI)) != 0; +#else + WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx); + + res = (wfd->events.lNetworkEvents & (FD_READ | FD_ACCEPT)) != 0; +#endif + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res); + + return res; +} + +/** + * gst_poll_fd_can_read: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Check if @fd in @set has data to be read. + * + * Returns: %TRUE if the descriptor has data to be read. + */ +gboolean +gst_poll_fd_can_read (const GstPoll * set, GstPollFD * fd) +{ + gboolean res = FALSE; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&((GstPoll *) set)->lock); + + res = gst_poll_fd_can_read_unlocked (set, fd); + + g_mutex_unlock (&((GstPoll *) set)->lock); + + return res; +} + +/** + * gst_poll_fd_can_write: + * @set: a file descriptor set. + * @fd: a file descriptor. + * + * Check if @fd in @set can be used for writing. + * + * Returns: %TRUE if the descriptor can be used for writing. + */ +gboolean +gst_poll_fd_can_write (const GstPoll * set, GstPollFD * fd) +{ + gboolean res = FALSE; + gint idx; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (fd != NULL, FALSE); + g_return_val_if_fail (fd->fd >= 0, FALSE); + + g_mutex_lock (&((GstPoll *) set)->lock); + + idx = find_index (set->active_fds, fd); + if (idx >= 0) { +#ifndef G_OS_WIN32 + struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx); + + res = (pfd->revents & POLLOUT) != 0; +#else + WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx); + + res = (wfd->events.lNetworkEvents & FD_WRITE) != 0; +#endif + } else { + GST_WARNING ("%p: couldn't find fd !", set); + } + g_mutex_unlock (&((GstPoll *) set)->lock); + + GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res); + + return res; +} + +/** + * gst_poll_wait: + * @set: a #GstPoll. + * @timeout: a timeout in nanoseconds. + * + * Wait for activity on the file descriptors in @set. This function waits up to + * the specified @timeout. A timeout of #GST_CLOCK_TIME_NONE waits forever. + * + * For #GstPoll objects created with gst_poll_new(), this function can only be + * called from a single thread at a time. If called from multiple threads, + * -1 will be returned with errno set to EPERM. + * + * This is not true for timer #GstPoll objects created with + * gst_poll_new_timer(), where it is allowed to have multiple threads waiting + * simultaneously. + * + * Returns: The number of #GstPollFD in @set that have activity or 0 when no + * activity was detected after @timeout. If an error occurs, -1 is returned + * and errno is set. + */ +gint +gst_poll_wait (GstPoll * set, GstClockTime timeout) +{ + gboolean restarting; + gboolean is_timer; + int res; + gint old_waiting; + + g_return_val_if_fail (set != NULL, -1); + + GST_DEBUG ("%p: timeout :%" GST_TIME_FORMAT, set, GST_TIME_ARGS (timeout)); + + is_timer = set->timer; + + /* add one more waiter */ + old_waiting = INC_WAITING (set); + + /* we cannot wait from multiple threads unless we are a timer */ + if (G_UNLIKELY (old_waiting > 0 && !is_timer)) + goto already_waiting; + + /* flushing, exit immediately */ + if (G_UNLIKELY (IS_FLUSHING (set))) + goto flushing; + + do { + GstPollMode mode; + + res = -1; + restarting = FALSE; + + mode = choose_mode (set, timeout); + + if (TEST_REBUILD (set)) { + g_mutex_lock (&set->lock); +#ifndef G_OS_WIN32 + g_array_set_size (set->active_fds, set->fds->len); + memcpy (set->active_fds->data, set->fds->data, + set->fds->len * sizeof (struct pollfd)); +#else + if (!gst_poll_prepare_winsock_active_sets (set)) + goto winsock_error; +#endif + g_mutex_unlock (&set->lock); + } + + switch (mode) { + case GST_POLL_MODE_AUTO: + g_assert_not_reached (); + break; + case GST_POLL_MODE_PPOLL: + { +#ifdef HAVE_PPOLL + struct timespec ts; + struct timespec *tsptr; + + if (timeout != GST_CLOCK_TIME_NONE) { + GST_TIME_TO_TIMESPEC (timeout, ts); + tsptr = &ts; + } else { + tsptr = NULL; + } + + res = + ppoll ((struct pollfd *) set->active_fds->data, + set->active_fds->len, tsptr, NULL); +#else + g_assert_not_reached (); + errno = ENOSYS; +#endif + break; + } + case GST_POLL_MODE_POLL: + { +#ifdef HAVE_POLL + gint t; + + if (timeout != GST_CLOCK_TIME_NONE) { + t = GST_TIME_AS_MSECONDS (timeout); + } else { + t = -1; + } + + res = + poll ((struct pollfd *) set->active_fds->data, + set->active_fds->len, t); +#else + g_assert_not_reached (); + errno = ENOSYS; +#endif + break; + } + case GST_POLL_MODE_PSELECT: +#ifndef HAVE_PSELECT + { + g_assert_not_reached (); + errno = ENOSYS; + break; + } +#endif + case GST_POLL_MODE_SELECT: + { +#ifndef G_OS_WIN32 + fd_set readfds; + fd_set writefds; + fd_set errorfds; + gint max_fd; + + max_fd = pollfd_to_fd_set (set, &readfds, &writefds, &errorfds); + + if (mode == GST_POLL_MODE_SELECT) { + struct timeval tv; + struct timeval *tvptr; + + if (timeout != GST_CLOCK_TIME_NONE) { + GST_TIME_TO_TIMEVAL (timeout, tv); + tvptr = &tv; + } else { + tvptr = NULL; + } + + GST_DEBUG ("%p: Calling select", set); + res = select (max_fd + 1, &readfds, &writefds, &errorfds, tvptr); + GST_DEBUG ("%p: After select, res:%d", set, res); + } else { +#ifdef HAVE_PSELECT + struct timespec ts; + struct timespec *tsptr; + + if (timeout != GST_CLOCK_TIME_NONE) { + GST_TIME_TO_TIMESPEC (timeout, ts); + tsptr = &ts; + } else { + tsptr = NULL; + } + + GST_DEBUG ("%p: Calling pselect", set); + res = + pselect (max_fd + 1, &readfds, &writefds, &errorfds, tsptr, NULL); + GST_DEBUG ("%p: After pselect, res:%d", set, res); +#endif + } + + if (res >= 0) { + fd_set_to_pollfd (set, &readfds, &writefds, &errorfds); + } +#else /* G_OS_WIN32 */ + g_assert_not_reached (); + errno = ENOSYS; +#endif + break; + } + case GST_POLL_MODE_WINDOWS: + { +#ifdef G_OS_WIN32 + gint ignore_count = set->active_fds_ignored->len; + DWORD t, wait_ret; + + if (G_LIKELY (ignore_count == 0)) { + if (timeout != GST_CLOCK_TIME_NONE) + t = GST_TIME_AS_MSECONDS (timeout); + else + t = INFINITE; + } else { + /* already one or more ignored fds, so we quickly sweep the others */ + t = 0; + } + + if (set->active_events->len != 0) { + wait_ret = WSAWaitForMultipleEvents (set->active_events->len, + (HANDLE *) set->active_events->data, FALSE, t, FALSE); + } else { + wait_ret = WSA_WAIT_FAILED; + WSASetLastError (WSA_INVALID_PARAMETER); + } + + if (ignore_count == 0 && wait_ret == WSA_WAIT_TIMEOUT) { + res = 0; + } else if (wait_ret == WSA_WAIT_FAILED) { + res = -1; + errno = gst_poll_winsock_error_to_errno (WSAGetLastError ()); + } else { + /* the first entry is the wakeup event */ + if (wait_ret - WSA_WAIT_EVENT_0 >= 1) { + res = gst_poll_collect_winsock_events (set); + } else { + res = 1; /* wakeup event */ + } + } +#else + g_assert_not_reached (); + errno = ENOSYS; +#endif + break; + } + } + + if (!is_timer) { + /* Applications needs to clear the control socket themselves for timer + * polls. + * For other polls, we need to clear the control socket. If there was only + * one socket with activity and it was the control socket, we need to + * restart */ + if (release_all_wakeup (set) > 0 && res == 1) + restarting = TRUE; + } + + /* we got woken up and we are flushing, we need to stop */ + if (G_UNLIKELY (IS_FLUSHING (set))) + goto flushing; + + } while (G_UNLIKELY (restarting)); + + DEC_WAITING (set); + + return res; + + /* ERRORS */ +already_waiting: + { + GST_LOG ("%p: we are already waiting", set); + DEC_WAITING (set); + errno = EPERM; + return -1; + } +flushing: + { + GST_LOG ("%p: we are flushing", set); + DEC_WAITING (set); + errno = EBUSY; + return -1; + } +#ifdef G_OS_WIN32 +winsock_error: + { + GST_LOG ("%p: winsock error", set); + g_mutex_unlock (&set->lock); + DEC_WAITING (set); + return -1; + } +#endif +} + +/** + * gst_poll_set_controllable: + * @set: a #GstPoll. + * @controllable: new controllable state. + * + * When @controllable is %TRUE, this function ensures that future calls to + * gst_poll_wait() will be affected by gst_poll_restart() and + * gst_poll_set_flushing(). + * + * This function only works for non-timer #GstPoll objects created with + * gst_poll_new(). + * + * Returns: %TRUE if the controllability of @set could be updated. + */ +gboolean +gst_poll_set_controllable (GstPoll * set, gboolean controllable) +{ + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (!set->timer, FALSE); + + GST_LOG ("%p: controllable : %d", set, controllable); + + set->controllable = controllable; + + return TRUE; +} + +/** + * gst_poll_restart: + * @set: a #GstPoll. + * + * Restart any gst_poll_wait() that is in progress. This function is typically + * used after adding or removing descriptors to @set. + * + * If @set is not controllable, then this call will have no effect. + * + * This function only works for non-timer #GstPoll objects created with + * gst_poll_new(). + */ +void +gst_poll_restart (GstPoll * set) +{ + g_return_if_fail (set != NULL); + g_return_if_fail (!set->timer); + + if (set->controllable && GET_WAITING (set) > 0) { + /* we are controllable and waiting, wake up the waiter. The socket will be + * cleared by the _wait() thread and the poll will be restarted */ + raise_wakeup (set); + } +} + +/** + * gst_poll_set_flushing: + * @set: a #GstPoll. + * @flushing: new flushing state. + * + * When @flushing is %TRUE, this function ensures that current and future calls + * to gst_poll_wait() will return -1, with errno set to EBUSY. + * + * Unsetting the flushing state will restore normal operation of @set. + * + * This function only works for non-timer #GstPoll objects created with + * gst_poll_new(). + */ +void +gst_poll_set_flushing (GstPoll * set, gboolean flushing) +{ + g_return_if_fail (set != NULL); + g_return_if_fail (!set->timer); + + GST_LOG ("%p: flushing: %d", set, flushing); + + /* update the new state first */ + SET_FLUSHING (set, flushing); + + if (flushing && set->controllable && GET_WAITING (set) > 0) { + /* we are flushing, controllable and waiting, wake up the waiter. When we + * stop the flushing operation we don't clear the wakeup fd here, this will + * happen in the _wait() thread. */ + raise_wakeup (set); + } +} + +/** + * gst_poll_write_control: + * @set: a #GstPoll. + * + * Write a byte to the control socket of the controllable @set. + * This function is mostly useful for timer #GstPoll objects created with + * gst_poll_new_timer(). + * + * It will make any current and future gst_poll_wait() function return with + * 1, meaning the control socket is set. After an equal amount of calls to + * gst_poll_read_control() have been performed, calls to gst_poll_wait() will + * block again until their timeout expired. + * + * This function only works for timer #GstPoll objects created with + * gst_poll_new_timer(). + * + * Returns: %TRUE on success. %FALSE when when the byte could not be written. + * errno contains the detailed error code but will never be EAGAIN, EINTR or + * EWOULDBLOCK. %FALSE always signals a critical error. + */ +gboolean +gst_poll_write_control (GstPoll * set) +{ + gboolean res; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (set->timer, FALSE); + + res = raise_wakeup (set); + + return res; +} + +/** + * gst_poll_read_control: + * @set: a #GstPoll. + * + * Read a byte from the control socket of the controllable @set. + * + * This function only works for timer #GstPoll objects created with + * gst_poll_new_timer(). + * + * Returns: %TRUE on success. %FALSE when when there was no byte to read or + * reading the byte failed. If there was no byte to read, and only then, errno + * will contain EWOULDBLOCK or EAGAIN. For all other values of errno this always signals a + * critical error. + */ +gboolean +gst_poll_read_control (GstPoll * set) +{ + gboolean res; + + g_return_val_if_fail (set != NULL, FALSE); + g_return_val_if_fail (set->timer, FALSE); + + res = release_wakeup (set); + + return res; +} diff --git a/gst/gstpoll.h b/gst/gstpoll.h new file mode 100644 index 0000000..7b37176 --- /dev/null +++ b/gst/gstpoll.h @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2007 Peter Kjellerstedt + * + * gstpoll.h: File descriptor set + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_POLL_H__ +#define __GST_POLL_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +/** + * GstPoll: + * + * A set of file/network descriptors. + */ +typedef struct _GstPoll GstPoll; + +/** + * GstPollFD: + * @fd: a file descriptor + * + * A file descriptor object. + */ +typedef struct { + int fd; + + /*< private >*/ + gint idx; +} GstPollFD; + +/** + * GST_POLL_FD_INIT: + * + * A #GstPollFD must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_poll_fd_init(). + */ +#define GST_POLL_FD_INIT { -1, -1 } + +GST_API +GstPoll* gst_poll_new (gboolean controllable) G_GNUC_MALLOC; + +GST_API +GstPoll* gst_poll_new_timer (void) G_GNUC_MALLOC; + +GST_API +void gst_poll_free (GstPoll *set); + +GST_API +void gst_poll_get_read_gpollfd (GstPoll *set, GPollFD *fd); + +GST_API +void gst_poll_fd_init (GstPollFD *fd); + +GST_API +gboolean gst_poll_add_fd (GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_remove_fd (GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_fd_ctl_write (GstPoll *set, GstPollFD *fd, gboolean active); + +GST_API +gboolean gst_poll_fd_ctl_read (GstPoll *set, GstPollFD *fd, gboolean active); + +GST_API +void gst_poll_fd_ignored (GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_fd_has_closed (const GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_fd_has_error (const GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_fd_can_read (const GstPoll *set, GstPollFD *fd); + +GST_API +gboolean gst_poll_fd_can_write (const GstPoll *set, GstPollFD *fd); + +GST_API +gint gst_poll_wait (GstPoll *set, GstClockTime timeout); + +GST_API +gboolean gst_poll_set_controllable (GstPoll *set, gboolean controllable); + +GST_API +void gst_poll_restart (GstPoll *set); + +GST_API +void gst_poll_set_flushing (GstPoll *set, gboolean flushing); + +GST_API +gboolean gst_poll_write_control (GstPoll *set); + +GST_API +gboolean gst_poll_read_control (GstPoll *set) G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /* __GST_POLL_H__ */ diff --git a/gst/gstpreset.c b/gst/gstpreset.c new file mode 100644 index 0000000..01a1a29 --- /dev/null +++ b/gst/gstpreset.c @@ -0,0 +1,1344 @@ +/* GStreamer + * Copyright (C) 2006 Stefan Kost + * + * gstpreset.c: helper interface for element presets + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstpreset + * @title: GstPreset + * @short_description: helper interface for element presets + * + * This interface offers methods to query and manipulate parameter preset sets. + * A preset is a bunch of property settings, together with meta data and a name. + * The name of a preset serves as key for subsequent method calls to manipulate + * single presets. + * All instances of one type will share the list of presets. The list is created + * on demand, if presets are not used, the list is not created. + * + * The interface comes with a default implementation that serves most plugins. + * Wrapper plugins will override most methods to implement support for the + * native preset format of those wrapped plugins. + * One method that is useful to be overridden is gst_preset_get_property_names(). + * With that one can control which properties are saved and in which order. + * When implementing support for read-only presets, one should set the vmethods + * for gst_preset_save_preset() and gst_preset_delete_preset() to %NULL. + * Applications can use gst_preset_is_editable() to check for that. + * + * The default implementation supports presets located in a system directory, + * application specific directory and in the users home directory. When getting + * a list of presets individual presets are read and overlaid in 1) system, + * 2) application and 3) user order. Whenever an earlier entry is newer, the + * later entries will be updated. Since 1.8 you can also provide extra paths + * where to find presets through the GST_PRESET_PATH environment variable. + * Presets found in those paths will be concidered as "app presets". + */ +/* FIXME: + * - non racyness + * - we need to avoid two instances writing the preset file + * -> flock(fileno()), http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html + * -> open exclusive + * -> better save the new file to a tempfile and then rename? + * - we like to know when any other instance makes changes to the keyfile + * - then ui can be updated + * - and we make sure that we don't lose edits + * -> its the same problem actually, once for inside a process, once system- + * wide + * - can we use a lock inside a names shared memory segment? + * + * - should there be a 'preset-list' property to get the preset list + * (and to connect a notify:: to to listen for changes) + * we could use gnome_vfs_monitor_add() to monitor the user preset_file. + * + * - should there be a 'preset-name' property so that we can set a preset via + * gst-launch, or should we handle this with special syntax in gst-launch: + * gst-launch element preset: property=value ... + * - this would allow to have preset-bundles too (a preset on bins that + * specifies presets for children + */ + +#include "gst_private.h" + +#include "gstpreset.h" +#include "gstchildproxy.h" +#include "gstinfo.h" +#include "gstvalue.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +extern HMODULE _priv_gst_dll_handle; +#endif + +#define GST_CAT_DEFAULT preset_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/* defines for keyfile usage, this group contains the element type name and + * version these presets belong to. */ +#define PRESET_HEADER "_presets_" + +/* keys of the preset header section */ +#define PRESET_HEADER_ELEMENT_NAME "element-name" +#define PRESET_HEADER_VERSION "version" + +static GQuark preset_user_path_quark = 0; +static GQuark preset_app_path_quark = 0; +static GQuark preset_system_path_quark = 0; +static GQuark preset_quark = 0; + +/* the application can set a custom path that is checked in addition to standard + * system and user dirs. This helps to develop new presets first local to the + * application. + */ +static gchar *preset_app_dir = NULL; + +/* default iface implementation */ + +static gboolean gst_preset_default_save_presets_file (GstPreset * preset); + +/* + * preset_get_paths: + * @preset: a #GObject that implements #GstPreset + * @preset_user_path: (out) (allow-none): location for path or %NULL + * @preset_app_path: (out) (allow-none): location for path or %NULL + * @preset_system_path: (out) (allow-none): location for path or %NULL + * + * Fetch the preset_path for user local, application specific and system wide + * settings. Don't free after use. + * + * Returns: %FALSE if no paths could be found. + */ +static gboolean +preset_get_paths (GstPreset * preset, const gchar ** preset_user_path, + const gchar ** preset_app_path, const gchar ** preset_system_path) +{ + GType type = G_TYPE_FROM_INSTANCE (preset); + gchar *preset_path; + const gchar *element_name; + + /* we use the element name when we must construct the paths */ + element_name = G_OBJECT_TYPE_NAME (preset); + GST_INFO_OBJECT (preset, "element_name: '%s'", element_name); + + if (preset_user_path) { + /* preset user path requested, see if we have it cached in the qdata */ + if (!(preset_path = g_type_get_qdata (type, preset_user_path_quark))) { + gchar *preset_dir; + + /* user presets go in user's XDG data directory. */ + preset_dir = g_build_filename (g_get_user_data_dir (), + "gstreamer-" GST_API_VERSION, "presets", NULL); + GST_INFO_OBJECT (preset, "user_preset_dir: '%s'", preset_dir); + preset_path = + g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", preset_dir, + element_name); + GST_INFO_OBJECT (preset, "user_preset_path: '%s'", preset_path); + /* create dirs */ + g_mkdir_with_parents (preset_dir, 0755); + g_free (preset_dir); + + /* cache the preset path to the type */ + g_type_set_qdata (type, preset_user_path_quark, preset_path); + } + *preset_user_path = preset_path; + } + + if (preset_app_path) { + if (preset_app_dir) { + if (!(preset_path = g_type_get_qdata (type, preset_system_path_quark))) { + preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", + preset_app_dir, element_name); + GST_INFO_OBJECT (preset, "application_preset_path: '%s'", preset_path); + + /* cache the preset path to the type */ + g_type_set_qdata (type, preset_app_path_quark, preset_path); + } + *preset_app_path = preset_path; + } else { + *preset_app_path = NULL; + } + } + + if (preset_system_path) { + /* preset system path requested, see if we have it cached in the qdata */ + if (!(preset_path = g_type_get_qdata (type, preset_system_path_quark))) { + gchar *preset_dir; + + /* system presets in '$GST_DATADIR/gstreamer-1.0/presets/GstAudioPanorama.prs' */ +#ifdef G_OS_WIN32 + gchar *basedir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + preset_dir = + g_build_filename (basedir, "share", "gstreamer-" GST_API_VERSION, + "presets", NULL); + g_free (basedir); +#else + preset_dir = g_build_filename (GST_DATADIR, "gstreamer-" GST_API_VERSION, + "presets", NULL); +#endif + GST_INFO_OBJECT (preset, "system_preset_dir: '%s'", preset_dir); + preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", + preset_dir, element_name); + GST_INFO_OBJECT (preset, "system_preset_path: '%s'", preset_path); + /* create dirs */ + g_mkdir_with_parents (preset_dir, 0755); + g_free (preset_dir); + + /* cache the preset path to the type */ + g_type_set_qdata (type, preset_system_path_quark, preset_path); + } + *preset_system_path = preset_path; + } + return TRUE; +} + +static gboolean +preset_skip_property (GParamSpec * property) +{ + if (((property->flags & G_PARAM_READWRITE) != G_PARAM_READWRITE) || + (property->flags & G_PARAM_CONSTRUCT_ONLY)) + return TRUE; + /* FIXME: skip GST_PARAM_NOT_PRESETABLE, see #522205 */ + return FALSE; +} + +static guint64 +preset_parse_version (const gchar * str_version) +{ + guint major, minor, micro, nano; + gint num; + + major = minor = micro = nano = 0; + + /* parse version (e.g. 0.10.15.1) to guint64 */ + num = sscanf (str_version, "%u.%u.%u.%u", &major, &minor, µ, &nano); + /* make sure we have at least "major.minor" */ + if (num > 1) { + guint64 version; + + version = ((((major << 8 | minor) << 8) | micro) << 8) | nano; + GST_DEBUG ("version %s -> %" G_GUINT64_FORMAT, str_version, version); + return version; + } + return G_GUINT64_CONSTANT (0); +} + +static GKeyFile * +preset_open_and_parse_header (GstPreset * preset, const gchar * preset_path, + guint64 * preset_version) +{ + GKeyFile *in; + GError *error = NULL; + gboolean res; + const gchar *element_name; + gchar *name; + + in = g_key_file_new (); + + res = g_key_file_load_from_file (in, preset_path, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error); + if (!res || error != NULL) + goto load_error; + + /* element type name and preset name must match or we are dealing with a wrong + * preset file */ + element_name = G_OBJECT_TYPE_NAME (preset); + name = + g_key_file_get_value (in, PRESET_HEADER, PRESET_HEADER_ELEMENT_NAME, + NULL); + + if (!name || strcmp (name, element_name)) + goto wrong_name; + + g_free (name); + + /* get the version now so that the caller can check it */ + if (preset_version) { + gchar *str = + g_key_file_get_value (in, PRESET_HEADER, PRESET_HEADER_VERSION, NULL); + *preset_version = preset_parse_version (str); + g_free (str); + } + + return in; + + /* ERRORS */ +load_error: + { + GST_INFO_OBJECT (preset, "Unable to read preset file %s: %s", + preset_path, error->message); + g_error_free (error); + g_key_file_free (in); + return NULL; + } +wrong_name: + { + GST_WARNING_OBJECT (preset, + "Wrong element name in preset file %s. Expected %s, got %s", + preset_path, element_name, GST_STR_NULL (name)); + g_free (name); + g_key_file_free (in); + return NULL; + } +} + +static void +preset_merge (GKeyFile * system, GKeyFile * user) +{ + gchar *str; + gchar **groups, **keys; + gsize i, j, num_groups, num_keys; + + /* copy file comment if there is any */ + if ((str = g_key_file_get_comment (user, NULL, NULL, NULL))) { + g_key_file_set_comment (system, NULL, NULL, str, NULL); + g_free (str); + } + + /* get groups in user and copy into system */ + groups = g_key_file_get_groups (user, &num_groups); + for (i = 0; i < num_groups; i++) { + /* copy group comment if there is any */ + if ((str = g_key_file_get_comment (user, groups[i], NULL, NULL))) { + g_key_file_set_comment (system, groups[i], NULL, str, NULL); + g_free (str); + } + + /* ignore private groups */ + if (groups[i][0] == '_') + continue; + + /* if group already exists in system, remove and re-add keys from user */ + if (g_key_file_has_group (system, groups[i])) { + g_key_file_remove_group (system, groups[i], NULL); + } + + keys = g_key_file_get_keys (user, groups[i], &num_keys, NULL); + for (j = 0; j < num_keys; j++) { + /* copy key comment if there is any */ + if ((str = g_key_file_get_comment (user, groups[i], keys[j], NULL))) { + g_key_file_set_comment (system, groups[i], keys[j], str, NULL); + g_free (str); + } + str = g_key_file_get_value (user, groups[i], keys[j], NULL); + g_key_file_set_value (system, groups[i], keys[j], str); + g_free (str); + } + g_strfreev (keys); + } + g_strfreev (groups); +} + +typedef struct +{ + GKeyFile *preset; + guint64 version; +} PresetAndVersion; + +static gint +compare_preset_and_version (gconstpointer a, gconstpointer b, + gpointer user_data) +{ + const PresetAndVersion *pa = a, *pb = b; + + if (pa->version > pb->version) + return -1; + if (pa->version < pb->version) + return 1; + else + return 0; +} + +/* reads the user and system presets files and merges them together. This + * function caches the GKeyFile on the element type. If there is no existing + * preset file, a new in-memory GKeyFile will be created. */ +static GKeyFile * +preset_get_keyfile (GstPreset * preset) +{ + GKeyFile *presets; + GType type = G_TYPE_FROM_INSTANCE (preset); + + /* first see if the have a cached version for the type */ + if (!(presets = g_type_get_qdata (type, preset_quark))) { + const gchar *preset_user_path, *preset_app_path, *preset_system_path; + guint64 version_system = G_GUINT64_CONSTANT (0); + guint64 version_app = G_GUINT64_CONSTANT (0); + guint64 version_user = G_GUINT64_CONSTANT (0); + guint64 version = G_GUINT64_CONSTANT (0); + gboolean merged = FALSE; + GKeyFile *in_user, *in_app = NULL, *in_system; + GQueue in_env = G_QUEUE_INIT; + gboolean have_env = FALSE; + const gchar *envvar; + + /* try to load the user, app and system presets, we do this to get the + * versions of all files. */ + preset_get_paths (preset, &preset_user_path, &preset_app_path, + &preset_system_path); + in_user = preset_open_and_parse_header (preset, preset_user_path, + &version_user); + + if (preset_app_path) { + in_app = preset_open_and_parse_header (preset, preset_app_path, + &version_app); + } + + envvar = g_getenv ("GST_PRESET_PATH"); + if (envvar) { + gint i; + gchar **preset_dirs = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, -1); + + for (i = 0; preset_dirs[i]; i++) { + gchar *preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", + preset_dirs[i], G_OBJECT_TYPE_NAME (preset)); + GKeyFile *env_file; + guint64 env_version; + + env_file = preset_open_and_parse_header (preset, preset_path, + &env_version); + g_free (preset_path); + if (env_file) { + PresetAndVersion *pv = g_new (PresetAndVersion, 1); + pv->preset = env_file; + pv->version = env_version; + g_queue_push_tail (&in_env, pv); + have_env = TRUE; + } + } + g_strfreev (preset_dirs); + } + + in_system = preset_open_and_parse_header (preset, preset_system_path, + &version_system); + + /* compare version to check for merge */ + if (in_system) { + presets = in_system; + version = version_system; + } + + if (have_env) { + GList *l; + + /* merge the ones from the environment paths. If any of them has a + * higher version, take that as the "master" version. Lower versions are + * then just merged in. */ + g_queue_sort (&in_env, compare_preset_and_version, NULL); + /* highest version to lowest */ + for (l = in_env.head; l; l = l->next) { + PresetAndVersion *pv = l->data; + + if (version > pv->version) { + preset_merge (presets, pv->preset); + g_key_file_free (pv->preset); + } else { + if (presets) + g_key_file_free (presets); + presets = pv->preset; + version = pv->version; + } + g_free (pv); + } + g_queue_clear (&in_env); + } + + if (in_app) { + /* if system/env version is higher, merge */ + if (version > version_app) { + preset_merge (presets, in_app); + g_key_file_free (in_app); + } else { + if (presets) + g_key_file_free (presets); + presets = in_app; + version = version_app; + } + } + if (in_user) { + /* if system/env or app version is higher, merge */ + if (version > version_user) { + preset_merge (presets, in_user); + g_key_file_free (in_user); + merged = TRUE; + } else { + if (presets) + g_key_file_free (presets); + presets = in_user; + } + } + + if (!presets) { + /* we did not load a user, app or system presets file, create a new one */ + presets = g_key_file_new (); + g_key_file_set_string (presets, PRESET_HEADER, PRESET_HEADER_ELEMENT_NAME, + G_OBJECT_TYPE_NAME (preset)); + } + + /* attach the preset to the type */ + g_type_set_qdata (type, preset_quark, (gpointer) presets); + + if (merged) { + gst_preset_default_save_presets_file (preset); + } + } + return presets; +} + +static gint +compare_strings (gchar ** a, gchar ** b, gpointer user_data) +{ + return g_strcmp0 (*a, *b); +} + +/* get a list of all supported preset names for an element */ +static gchar ** +gst_preset_default_get_preset_names (GstPreset * preset) +{ + GKeyFile *presets; + gsize i, num_groups; + gchar **groups; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + /* get the groups, which are also the preset names */ + if (!(groups = g_key_file_get_groups (presets, &num_groups))) + goto no_groups; + + /* remove all private group names starting with '_' from the array */ + for (i = 0; i < num_groups; i++) { + if (groups[i][0] == '_') { + /* free private group */ + g_free (groups[i]); + /* move last element of list down */ + num_groups--; + /* move last element into removed element */ + groups[i] = groups[num_groups]; + groups[num_groups] = NULL; + } + } + if (!num_groups) { + GST_INFO_OBJECT (preset, "Empty preset file"); + g_strfreev (groups); + return NULL; + } + + /* sort the array now */ + g_qsort_with_data (groups, num_groups, sizeof (gchar *), + (GCompareDataFunc) compare_strings, NULL); + + return groups; + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "Could not load presets"); + return NULL; + } +no_groups: + { + GST_WARNING_OBJECT (preset, "Could not find preset groups"); + return NULL; + } +} + +/* get a list of all property names that are used for presets */ +static gchar ** +gst_preset_default_get_property_names (GstPreset * preset) +{ + GParamSpec **props; + guint i, j = 0, n_props; + GObjectClass *gclass; + gboolean is_child_proxy; + gchar **result = NULL; + + gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset)); + is_child_proxy = GST_IS_CHILD_PROXY (preset); + + /* get a list of object properties */ + props = g_object_class_list_properties (gclass, &n_props); + if (props) { + /* allocate array big enough to hold the worst case, including a terminating + * NULL pointer. */ + result = g_new (gchar *, n_props + 1); + + /* now filter out the properties that we can use for presets */ + GST_DEBUG_OBJECT (preset, " filtering properties: %u", n_props); + for (i = 0; i < n_props; i++) { + if (preset_skip_property (props[i])) + continue; + GST_DEBUG_OBJECT (preset, " using: %s", props[i]->name); + result[j++] = g_strdup (props[i]->name); + } + g_free (props); + } + + if (is_child_proxy) { + guint c, n_children; + GObject *child; + + n_children = gst_child_proxy_get_children_count ((GstChildProxy *) preset); + for (c = 0; c < n_children; c++) { + child = gst_child_proxy_get_child_by_index ((GstChildProxy *) preset, c); + gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (child)); + + props = g_object_class_list_properties (gclass, &n_props); + if (props) { + /* resize property name array */ + result = g_renew (gchar *, result, j + n_props + 1); + + /* now filter out the properties that we can use for presets */ + GST_DEBUG_OBJECT (preset, " filtering properties: %u", n_props); + for (i = 0; i < n_props; i++) { + if (preset_skip_property (props[i])) + continue; + GST_DEBUG_OBJECT (preset, " using: %s::%s", + GST_OBJECT_NAME (child), props[i]->name); + result[j++] = g_strdup_printf ("%s::%s", GST_OBJECT_NAME (child), + props[i]->name); + } + g_free (props); + } + + g_object_unref (child); + } + } + if (!result) { + GST_INFO_OBJECT (preset, "object has no properties"); + } else { + result[j] = NULL; + } + return result; +} + +/* load the presets of @name for the instance @preset. Returns %FALSE if something + * failed. */ +static gboolean +gst_preset_default_load_preset (GstPreset * preset, const gchar * name) +{ + GKeyFile *presets; + gchar **props; + guint i; + GObjectClass *gclass; + gboolean is_child_proxy; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + /* get the preset name */ + if (!g_key_file_has_group (presets, name)) + goto no_group; + + GST_DEBUG_OBJECT (preset, "loading preset : '%s'", name); + + /* get the properties that we can configure in this element */ + if (!(props = gst_preset_get_property_names (preset))) + goto no_properties; + + gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset)); + is_child_proxy = GST_IS_CHILD_PROXY (preset); + + /* for each of the property names, find the preset parameter and try to + * configure the property with its value */ + for (i = 0; props[i]; i++) { + gchar *str; + GValue gvalue = { 0, }; + GParamSpec *property = NULL; + + /* check if we have a settings for this element property */ + if (!(str = g_key_file_get_value (presets, name, props[i], NULL))) { + /* the element has a property but the parameter is not in the keyfile */ + GST_INFO_OBJECT (preset, "parameter '%s' not in preset", props[i]); + continue; + } + + GST_DEBUG_OBJECT (preset, "setting value '%s' for property '%s'", str, + props[i]); + + if (is_child_proxy) { + gst_child_proxy_lookup ((GstChildProxy *) preset, props[i], NULL, + &property); + } else { + property = g_object_class_find_property (gclass, props[i]); + } + if (!property) { + /* the parameter was in the keyfile, the element said it supported it but + * then the property was not found in the element. This should not happen. */ + GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]); + g_free (str); + continue; + } + + /* try to deserialize the property value from the keyfile and set it as + * the object property */ + g_value_init (&gvalue, property->value_type); + if (gst_value_deserialize (&gvalue, str)) { + if (is_child_proxy) { + gst_child_proxy_set_property ((GstChildProxy *) preset, props[i], + &gvalue); + } else { + g_object_set_property ((GObject *) preset, props[i], &gvalue); + } + } else { + GST_WARNING_OBJECT (preset, + "deserialization of value '%s' for property '%s' failed", str, + props[i]); + } + g_value_unset (&gvalue); + g_free (str); + } + g_strfreev (props); + + return TRUE; + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + return FALSE; + } +no_group: + { + GST_WARNING_OBJECT (preset, "no preset named '%s'", name); + return FALSE; + } +no_properties: + { + GST_INFO_OBJECT (preset, "no properties"); + return FALSE; + } +} + +/* save the presets file. A copy of the existing presets file is stored in a + * .bak file */ +static gboolean +gst_preset_default_save_presets_file (GstPreset * preset) +{ + GKeyFile *presets; + const gchar *preset_path; + GError *error = NULL; + gchar *bak_file_name; + gboolean backup = TRUE; + gchar *data; + gsize data_size; + + preset_get_paths (preset, &preset_path, NULL, NULL); + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + GST_DEBUG_OBJECT (preset, "saving preset file: '%s'", preset_path); + + /* create backup if possible */ + bak_file_name = g_strdup_printf ("%s.bak", preset_path); + if (g_file_test (bak_file_name, G_FILE_TEST_EXISTS)) { + if (g_unlink (bak_file_name)) { + backup = FALSE; + GST_INFO_OBJECT (preset, "cannot remove old backup file : %s", + bak_file_name); + } + } + if (backup) { + if (g_rename (preset_path, bak_file_name)) { + GST_INFO_OBJECT (preset, "cannot backup file : %s -> %s", preset_path, + bak_file_name); + } + } + g_free (bak_file_name); + + /* update gstreamer version */ + g_key_file_set_string (presets, PRESET_HEADER, PRESET_HEADER_VERSION, + PACKAGE_VERSION); + + /* get new contents, wee need this to save it */ + if (!(data = g_key_file_to_data (presets, &data_size, &error))) + goto convert_failed; + + /* write presets */ + if (!g_file_set_contents (preset_path, data, data_size, &error)) + goto write_failed; + + g_free (data); + + return TRUE; + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, + "no presets, trying to unlink possibly existing preset file: '%s'", + preset_path); + g_unlink (preset_path); + return FALSE; + } +convert_failed: + { + GST_WARNING_OBJECT (preset, "can not get the keyfile contents: %s", + error->message); + g_error_free (error); + g_free (data); + return FALSE; + } +write_failed: + { + GST_WARNING_OBJECT (preset, "Unable to store preset file %s: %s", + preset_path, error->message); + g_error_free (error); + g_free (data); + return FALSE; + } +} + +/* save the preset with the given name */ +static gboolean +gst_preset_default_save_preset (GstPreset * preset, const gchar * name) +{ + GKeyFile *presets; + gchar **props; + guint i; + GObjectClass *gclass; + gboolean is_child_proxy; + + GST_INFO_OBJECT (preset, "saving new preset: %s", name); + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + /* take copies of current gobject properties from preset */ + if (!(props = gst_preset_get_property_names (preset))) + goto no_properties; + + gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset)); + is_child_proxy = GST_IS_CHILD_PROXY (preset); + + /* loop over the object properties and store the property value in the + * keyfile */ + for (i = 0; props[i]; i++) { + GValue gvalue = { 0, }; + gchar *str; + GParamSpec *property = NULL; + + if (is_child_proxy) { + gst_child_proxy_lookup ((GstChildProxy *) preset, props[i], NULL, + &property); + } else { + property = g_object_class_find_property (gclass, props[i]); + } + if (!property) { + /* the element said it supported the property but then it does not have + * that property. This should not happen. */ + GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]); + continue; + } + + if (property->flags & G_PARAM_DEPRECATED) { + GST_INFO_OBJECT (preset, "Not saving property %s as it is deprecated", + property->name); + continue; + } + + g_value_init (&gvalue, property->value_type); + if (is_child_proxy) { + gst_child_proxy_get_property ((GstChildProxy *) preset, props[i], + &gvalue); + } else { + g_object_get_property ((GObject *) preset, props[i], &gvalue); + } + + if ((str = gst_value_serialize (&gvalue))) { + g_key_file_set_string (presets, name, props[i], (gpointer) str); + g_free (str); + } else { + GST_WARNING_OBJECT (preset, "serialization for property '%s' failed", + props[i]); + } + g_value_unset (&gvalue); + } + GST_INFO_OBJECT (preset, " saved"); + g_strfreev (props); + + /* save updated version */ + return gst_preset_default_save_presets_file (preset); + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + return FALSE; + } +no_properties: + { + GST_INFO_OBJECT (preset, "no properties"); + return FALSE; + } +} + +/* copies all keys and comments from one group to another, deleting the old + * group. */ +static gboolean +gst_preset_default_rename_preset (GstPreset * preset, const gchar * old_name, + const gchar * new_name) +{ + GKeyFile *presets; + gchar *str; + gchar **keys; + gsize i, num_keys; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + if (!g_key_file_has_group (presets, old_name)) + goto no_group; + + /* copy group comment if there is any */ + if ((str = g_key_file_get_comment (presets, old_name, NULL, NULL))) { + g_key_file_set_comment (presets, new_name, NULL, str, NULL); + g_free (str); + } + + /* get all keys from the old group and copy them in the new group */ + keys = g_key_file_get_keys (presets, old_name, &num_keys, NULL); + for (i = 0; i < num_keys; i++) { + /* copy key comment if there is any */ + if ((str = g_key_file_get_comment (presets, old_name, keys[i], NULL))) { + g_key_file_set_comment (presets, new_name, keys[i], str, NULL); + g_free (str); + } + /* copy key value */ + str = g_key_file_get_value (presets, old_name, keys[i], NULL); + g_key_file_set_value (presets, new_name, keys[i], str); + g_free (str); + } + g_strfreev (keys); + + /* remove old group */ + g_key_file_remove_group (presets, old_name, NULL); + + /* save updated version */ + return gst_preset_default_save_presets_file (preset); + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + return FALSE; + } +no_group: + { + GST_WARNING_OBJECT (preset, "no preset named %s", old_name); + return FALSE; + } +} + +/* delete a group from the keyfile */ +static gboolean +gst_preset_default_delete_preset (GstPreset * preset, const gchar * name) +{ + GKeyFile *presets; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + /* get the group */ + if (!g_key_file_has_group (presets, name)) + goto no_group; + + /* remove the group */ + g_key_file_remove_group (presets, name, NULL); + + /* save updated version */ + return gst_preset_default_save_presets_file (preset); + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + return FALSE; + } +no_group: + { + GST_WARNING_OBJECT (preset, "no preset named %s", name); + return FALSE; + } +} + +static gboolean +gst_preset_default_set_meta (GstPreset * preset, const gchar * name, + const gchar * tag, const gchar * value) +{ + GKeyFile *presets; + gchar *key; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + key = g_strdup_printf ("_meta/%s", tag); + if (value && *value) { + g_key_file_set_value (presets, name, key, value); + } else { + g_key_file_remove_key (presets, name, key, NULL); + } + g_free (key); + + /* save updated keyfile */ + return gst_preset_default_save_presets_file (preset); + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + return FALSE; + } +} + +/* the caller must free @value after usage */ +static gboolean +gst_preset_default_get_meta (GstPreset * preset, const gchar * name, + const gchar * tag, gchar ** value) +{ + GKeyFile *presets; + gchar *key; + + /* get the presets from the type */ + if (!(presets = preset_get_keyfile (preset))) + goto no_presets; + + key = g_strdup_printf ("_meta/%s", tag); + *value = g_key_file_get_value (presets, name, key, NULL); + g_free (key); + + return TRUE; + + /* ERRORS */ +no_presets: + { + GST_WARNING_OBJECT (preset, "no presets"); + *value = NULL; + return FALSE; + } +} + +/* wrapper */ + +/** + * gst_preset_get_preset_names: + * @preset: a #GObject that implements #GstPreset + * + * Get a copy of preset names as a %NULL terminated string array. + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): + * list with names, use g_strfreev() after usage. + */ +gchar ** +gst_preset_get_preset_names (GstPreset * preset) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), NULL); + + return (GST_PRESET_GET_INTERFACE (preset)->get_preset_names (preset)); +} + +/** + * gst_preset_get_property_names: + * @preset: a #GObject that implements #GstPreset + * + * Get a the names of the GObject properties that can be used for presets. + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): an + * array of property names which should be freed with g_strfreev() after use. + */ +gchar ** +gst_preset_get_property_names (GstPreset * preset) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), NULL); + + return (GST_PRESET_GET_INTERFACE (preset)->get_property_names (preset)); +} + +/** + * gst_preset_load_preset: + * @preset: a #GObject that implements #GstPreset + * @name: preset name to load + * + * Load the given preset. + * + * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name + */ +gboolean +gst_preset_load_preset (GstPreset * preset, const gchar * name) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (name, FALSE); + + return (GST_PRESET_GET_INTERFACE (preset)->load_preset (preset, name)); +} + +/** + * gst_preset_save_preset: + * @preset: a #GObject that implements #GstPreset + * @name: preset name to save + * + * Save the current object settings as a preset under the given name. If there + * is already a preset by this @name it will be overwritten. + * + * Returns: %TRUE for success, %FALSE + */ +gboolean +gst_preset_save_preset (GstPreset * preset, const gchar * name) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (name, FALSE); + + return (GST_PRESET_GET_INTERFACE (preset)->save_preset (preset, name)); +} + +/** + * gst_preset_rename_preset: + * @preset: a #GObject that implements #GstPreset + * @old_name: current preset name + * @new_name: new preset name + * + * Renames a preset. If there is already a preset by the @new_name it will be + * overwritten. + * + * Returns: %TRUE for success, %FALSE if e.g. there is no preset with @old_name + */ +gboolean +gst_preset_rename_preset (GstPreset * preset, const gchar * old_name, + const gchar * new_name) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (old_name, FALSE); + g_return_val_if_fail (new_name, FALSE); + + return (GST_PRESET_GET_INTERFACE (preset)->rename_preset (preset, old_name, + new_name)); +} + +/** + * gst_preset_delete_preset: + * @preset: a #GObject that implements #GstPreset + * @name: preset name to remove + * + * Delete the given preset. + * + * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name + */ +gboolean +gst_preset_delete_preset (GstPreset * preset, const gchar * name) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (name, FALSE); + + return (GST_PRESET_GET_INTERFACE (preset)->delete_preset (preset, name)); +} + +/** + * gst_preset_set_meta: + * @preset: a #GObject that implements #GstPreset + * @name: preset name + * @tag: meta data item name + * @value: (allow-none): new value + * + * Sets a new @value for an existing meta data item or adds a new item. Meta + * data @tag names can be something like e.g. "comment". Supplying %NULL for the + * @value will unset an existing value. + * + * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name + */ +gboolean +gst_preset_set_meta (GstPreset * preset, const gchar * name, const gchar * tag, + const gchar * value) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (name, FALSE); + g_return_val_if_fail (tag, FALSE); + + return GST_PRESET_GET_INTERFACE (preset)->set_meta (preset, name, tag, value); +} + +/** + * gst_preset_get_meta: + * @preset: a #GObject that implements #GstPreset + * @name: preset name + * @tag: meta data item name + * @value: (out callee-allocates): value + * + * Gets the @value for an existing meta data @tag. Meta data @tag names can be + * something like e.g. "comment". Returned values need to be released when done. + * + * Returns: %TRUE for success, %FALSE if e.g. there is no preset with that @name + * or no value for the given @tag + */ +gboolean +gst_preset_get_meta (GstPreset * preset, const gchar * name, const gchar * tag, + gchar ** value) +{ + g_return_val_if_fail (GST_IS_PRESET (preset), FALSE); + g_return_val_if_fail (name, FALSE); + g_return_val_if_fail (tag, FALSE); + g_return_val_if_fail (value, FALSE); + + return GST_PRESET_GET_INTERFACE (preset)->get_meta (preset, name, tag, value); +} + +/** + * gst_preset_set_app_dir: + * @app_dir: (type filename): the application specific preset dir + * + * Sets an extra directory as an absolute path that should be considered when + * looking for presets. Any presets in the application dir will shadow the + * system presets. + * + * Returns: %TRUE for success, %FALSE if the dir already has been set + */ +gboolean +gst_preset_set_app_dir (const gchar * app_dir) +{ + g_return_val_if_fail (app_dir, FALSE); + + if (!preset_app_dir) { + preset_app_dir = g_strdup (app_dir); + return TRUE; + } + return FALSE; +} + +/** + * gst_preset_get_app_dir: + * + * Gets the directory for application specific presets if set by the + * application. + * + * Returns: (nullable) (type filename): the directory or %NULL, don't free or modify + * the string + */ +const gchar * +gst_preset_get_app_dir (void) +{ + return preset_app_dir; +} + +/** + * gst_preset_is_editable: + * @preset: a #GObject that implements #GstPreset + * + * Check if one can add new presets, change existing ones and remove presets. + * + * Returns: %TRUE if presets are editable or %FALSE if they are static + * + * Since: 1.6 + */ +gboolean +gst_preset_is_editable (GstPreset * preset) +{ + GstPresetInterface *iface = GST_PRESET_GET_INTERFACE (preset); + + return iface->save_preset && iface->delete_preset; +} + +/* class internals */ + +static void +gst_preset_class_init (GstPresetInterface * iface) +{ + iface->get_preset_names = gst_preset_default_get_preset_names; + iface->get_property_names = gst_preset_default_get_property_names; + + iface->load_preset = gst_preset_default_load_preset; + iface->save_preset = gst_preset_default_save_preset; + iface->rename_preset = gst_preset_default_rename_preset; + iface->delete_preset = gst_preset_default_delete_preset; + + iface->set_meta = gst_preset_default_set_meta; + iface->get_meta = gst_preset_default_get_meta; +} + +static void +gst_preset_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /* init default implementation */ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "preset", + GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLACK, "preset interface"); + + /* create quarks for use with g_type_{g,s}et_qdata() */ + preset_quark = g_quark_from_static_string ("GstPreset::presets"); + preset_user_path_quark = + g_quark_from_static_string ("GstPreset::user_path"); + preset_app_path_quark = g_quark_from_static_string ("GstPreset::app_path"); + preset_system_path_quark = + g_quark_from_static_string ("GstPreset::system_path"); + +#if 0 + /* create interface properties, each element would need to override this + * g_object_class_override_property(gobject_class, PROP_PRESET_NAME, "preset-name"); + * and in _set_property() do + * case PROP_PRESET_NAME: { + * gchar *name = g_value_get_string (value); + * if (name) + * gst_preset_load_preset(preset, name); + * } break; + */ + g_object_interface_install_property (g_class, + g_param_spec_string ("preset-name", + "preset-name property", + "load given preset", NULL, G_PARAM_WRITABLE)); +#endif + + initialized = TRUE; + } +} + +GType +gst_preset_get_type (void) +{ + static volatile gsize type = 0; + + if (g_once_init_enter (&type)) { + GType _type; + const GTypeInfo info = { + sizeof (GstPresetInterface), + (GBaseInitFunc) gst_preset_base_init, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_preset_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + _type = g_type_register_static (G_TYPE_INTERFACE, "GstPreset", &info, 0); + g_once_init_leave (&type, _type); + } + return type; +} diff --git a/gst/gstpreset.h b/gst/gstpreset.h new file mode 100644 index 0000000..65c19a2 --- /dev/null +++ b/gst/gstpreset.h @@ -0,0 +1,118 @@ +/* GStreamer + * Copyright (C) 2006 Stefan Kost + * + * gstpreset.h: helper interface header for element presets + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PRESET_H__ +#define __GST_PRESET_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PRESET (gst_preset_get_type()) +#define GST_PRESET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PRESET, GstPreset)) +#define GST_IS_PRESET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PRESET)) +#define GST_PRESET_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_PRESET, GstPresetInterface)) + +/** + * GstPreset: + * + * Opaque #GstPreset data structure. + */ +typedef struct _GstPreset GstPreset; /* dummy object */ +typedef struct _GstPresetInterface GstPresetInterface; + +/** + * GstPresetInterface: + * @parent: parent interface type. + * @get_preset_names: virtual method to get list of presets + * @get_property_names: virtual methods to get properties that are persistent + * @load_preset: virtual methods to load a preset into properties + * @save_preset: virtual methods to save properties into a preset + * @rename_preset: virtual methods to rename a preset + * @delete_preset: virtual methods to remove a preset + * @set_meta: virtual methods to set textual meta data to a preset + * @get_meta: virtual methods to get textual meta data from a preset + * + * #GstPreset interface. + */ +struct _GstPresetInterface +{ + GTypeInterface parent; + + /* methods */ + gchar** (*get_preset_names) (GstPreset *preset); + + gchar** (*get_property_names) (GstPreset *preset); + + gboolean (*load_preset) (GstPreset *preset, const gchar *name); + gboolean (*save_preset) (GstPreset *preset, const gchar *name); + gboolean (*rename_preset) (GstPreset *preset, const gchar *old_name, + const gchar *new_name); + gboolean (*delete_preset) (GstPreset *preset, const gchar *name); + + gboolean (*set_meta) (GstPreset *preset, const gchar *name, + const gchar *tag, const gchar *value); + gboolean (*get_meta) (GstPreset *preset, const gchar *name, + const gchar *tag, gchar **value); + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_preset_get_type (void); + +GST_API +gchar** gst_preset_get_preset_names (GstPreset *preset) G_GNUC_MALLOC; + +GST_API +gchar** gst_preset_get_property_names (GstPreset *preset) G_GNUC_MALLOC; + +GST_API +gboolean gst_preset_load_preset (GstPreset *preset, const gchar *name); + +GST_API +gboolean gst_preset_save_preset (GstPreset *preset, const gchar *name); + +GST_API +gboolean gst_preset_rename_preset (GstPreset *preset, const gchar *old_name, + const gchar *new_name); +GST_API +gboolean gst_preset_delete_preset (GstPreset *preset, const gchar *name); + +GST_API +gboolean gst_preset_set_meta (GstPreset *preset, const gchar *name, + const gchar *tag, const gchar *value); +GST_API +gboolean gst_preset_get_meta (GstPreset *preset, const gchar *name, + const gchar *tag, gchar **value); +GST_API +gboolean gst_preset_set_app_dir (const gchar *app_dir); + +GST_API +const gchar *gst_preset_get_app_dir (void); + +GST_API +gboolean gst_preset_is_editable (GstPreset *preset); + +G_END_DECLS + +#endif /* __GST_PRESET_H__ */ diff --git a/gst/gstpromise.c b/gst/gstpromise.c new file mode 100644 index 0000000..55f5149 --- /dev/null +++ b/gst/gstpromise.c @@ -0,0 +1,405 @@ +/* GStreamer + * Copyright (C) 2017 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" + +#include "gstpromise.h" + +#define GST_CAT_DEFAULT gst_promise_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/** + * SECTION:gstpromise + * @title: GstPromise + * @short_description: a miniobject for future/promise-like functionality + * @see_also: + * + * The #GstPromise object implements the container for values that may + * be available later. i.e. a Future or a Promise in + * https://en.wikipedia.org/wiki/Futures_and_promises + * As with all Future/Promise-like functionality, there is the concept of the + * producer of the value and the consumer of the value. + * + * A #GstPromise is created with gst_promise_new() by the consumer and passed + * to the producer to avoid thread safety issues with the change callback. + * A #GstPromise can be replied to with a value (or an error) by the producer + * with gst_promise_reply(). gst_promise_interrupt() is for the consumer to + * indicate to the producer that the value is not needed anymore and producing + * that value can stop. The @GST_PROMISE_RESULT_EXPIRED state set by a call + * to gst_promise_expire() indicates to the consumer that a value will never + * be produced and is intended to be called by a third party that implements + * some notion of message handling such as #GstBus. + * A callback can also be installed at #GstPromise creation for + * result changes with gst_promise_new_with_change_func(). + * The change callback can be used to chain #GstPromises's together as in the + * following example. + * |[ + * const GstStructure *reply; + * GstPromise *p; + * if (gst_promise_wait (promise) != GST_PROMISE_RESULT_REPLIED) + * return; // interrupted or expired value + * reply = gst_promise_get_reply (promise); + * if (error in reply) + * return; // propagate error + * p = gst_promise_new_with_change_func (another_promise_change_func, user_data, notify); + * pass p to promise-using API + * ]| + * + * Each #GstPromise starts out with a #GstPromiseResult of + * %GST_PROMISE_RESULT_PENDING and only ever transitions once + * into one of the other #GstPromiseResult's. + * + * In order to support multi-threaded code, gst_promise_reply(), + * gst_promise_interrupt() and gst_promise_expire() may all be from + * different threads with some restrictions and the final result of the promise + * is whichever call is made first. There are two restrictions on ordering: + * + * 1. That gst_promise_reply() and gst_promise_interrupt() cannot be called + * after gst_promise_expire() + * 2. That gst_promise_reply() and gst_promise_interrupt() + * cannot be called twice. + * + * The change function set with gst_promise_new_with_change_func() is + * called directly from either the gst_promise_reply(), + * gst_promise_interrupt() or gst_promise_expire() and can be called + * from an arbitrary thread. #GstPromise using APIs can restrict this to + * a single thread or a subset of threads but that is entirely up to the API + * that uses #GstPromise. + */ + +static const int immutable_structure_refcount = 2; + +#define GST_PROMISE_REPLY(p) (((GstPromiseImpl *)(p))->reply) +#define GST_PROMISE_RESULT(p) (((GstPromiseImpl *)(p))->result) +#define GST_PROMISE_LOCK(p) (&(((GstPromiseImpl *)(p))->lock)) +#define GST_PROMISE_COND(p) (&(((GstPromiseImpl *)(p))->cond)) +#define GST_PROMISE_CHANGE_FUNC(p) (((GstPromiseImpl *)(p))->change_func) +#define GST_PROMISE_CHANGE_DATA(p) (((GstPromiseImpl *)(p))->user_data) +#define GST_PROMISE_CHANGE_NOTIFY(p) (((GstPromiseImpl *)(p))->notify) + +typedef struct +{ + GstPromise promise; + + GstPromiseResult result; + GstStructure *reply; + + GMutex lock; + GCond cond; + GstPromiseChangeFunc change_func; + gpointer user_data; + GDestroyNotify notify; +} GstPromiseImpl; + +/** + * gst_promise_wait: + * @promise: a #GstPromise + * + * Wait for @promise to move out of the %GST_PROMISE_RESULT_PENDING state. + * If @promise is not in %GST_PROMISE_RESULT_PENDING then it will return + * immediately with the current result. + * + * Returns: the result of the promise + * + * Since: 1.14 + */ +GstPromiseResult +gst_promise_wait (GstPromise * promise) +{ + GstPromiseResult ret; + + g_return_val_if_fail (promise != NULL, GST_PROMISE_RESULT_EXPIRED); + + g_mutex_lock (GST_PROMISE_LOCK (promise)); + ret = GST_PROMISE_RESULT (promise); + + while (ret == GST_PROMISE_RESULT_PENDING) { + GST_LOG ("%p waiting", promise); + g_cond_wait (GST_PROMISE_COND (promise), GST_PROMISE_LOCK (promise)); + ret = GST_PROMISE_RESULT (promise); + } + GST_LOG ("%p waited", promise); + + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + + return ret; +} + +/** + * gst_promise_reply: + * @promise: (allow-none): a #GstPromise + * @s: (transfer full): a #GstStructure with the the reply contents + * + * Set a reply on @promise. This will wake up any waiters with + * %GST_PROMISE_RESULT_REPLIED. Called by the producer of the value to + * indicate success (or failure). + * + * If @promise has already been interrupted by the consumer, then this reply + * is not visible to the consumer. + * + * Since: 1.14 + */ +void +gst_promise_reply (GstPromise * promise, GstStructure * s) +{ + GstPromiseChangeFunc change_func = NULL; + gpointer change_data = NULL; + + /* Caller requested that no reply is necessary */ + if (promise == NULL) + return; + + g_mutex_lock (GST_PROMISE_LOCK (promise)); + if (GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_PENDING && + GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_INTERRUPTED) { + GstPromiseResult result = GST_PROMISE_RESULT (promise); + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + g_return_if_fail (result == GST_PROMISE_RESULT_PENDING || + result == GST_PROMISE_RESULT_INTERRUPTED); + } + + /* XXX: is this necessary and valid? */ + if (GST_PROMISE_REPLY (promise) && GST_PROMISE_REPLY (promise) != s) + gst_structure_free (GST_PROMISE_REPLY (promise)); + + /* Only reply iff we are currently in pending */ + if (GST_PROMISE_RESULT (promise) == GST_PROMISE_RESULT_PENDING) { + if (s + && !gst_structure_set_parent_refcount (s, + (int *) &immutable_structure_refcount)) { + g_critical ("Input structure has a parent already!"); + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + return; + } + + GST_PROMISE_RESULT (promise) = GST_PROMISE_RESULT_REPLIED; + GST_LOG ("%p replied", promise); + + GST_PROMISE_REPLY (promise) = s; + + change_func = GST_PROMISE_CHANGE_FUNC (promise); + change_data = GST_PROMISE_CHANGE_DATA (promise); + } else { + /* eat the value */ + if (s) + gst_structure_free (s); + } + + g_cond_broadcast (GST_PROMISE_COND (promise)); + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + + if (change_func) + change_func (promise, change_data); +} + +/** + * gst_promise_get_reply: + * @promise: a #GstPromise + * + * Retrieve the reply set on @promise. @promise must be in + * %GST_PROMISE_RESULT_REPLIED and the returned structure is owned by @promise + * + * Returns: (transfer none): The reply set on @promise + * + * Since: 1.14 + */ +const GstStructure * +gst_promise_get_reply (GstPromise * promise) +{ + g_return_val_if_fail (promise != NULL, NULL); + + g_mutex_lock (GST_PROMISE_LOCK (promise)); + if (GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_REPLIED) { + GstPromiseResult result = GST_PROMISE_RESULT (promise); + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + g_return_val_if_fail (result == GST_PROMISE_RESULT_REPLIED, NULL); + } + + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + + return GST_PROMISE_REPLY (promise); +} + +/** + * gst_promise_interrupt: + * @promise: a #GstPromise + * + * Interrupt waiting for a @promise. This will wake up any waiters with + * %GST_PROMISE_RESULT_INTERRUPTED. Called when the consumer does not want + * the value produced anymore. + * + * Since: 1.14 + */ +void +gst_promise_interrupt (GstPromise * promise) +{ + GstPromiseChangeFunc change_func = NULL; + gpointer change_data = NULL; + + g_return_if_fail (promise != NULL); + + g_mutex_lock (GST_PROMISE_LOCK (promise)); + if (GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_PENDING && + GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_REPLIED) { + GstPromiseResult result = GST_PROMISE_RESULT (promise); + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + g_return_if_fail (result == GST_PROMISE_RESULT_PENDING || + result == GST_PROMISE_RESULT_REPLIED); + } + /* only interrupt if we are currently in pending */ + if (GST_PROMISE_RESULT (promise) == GST_PROMISE_RESULT_PENDING) { + GST_PROMISE_RESULT (promise) = GST_PROMISE_RESULT_INTERRUPTED; + g_cond_broadcast (GST_PROMISE_COND (promise)); + GST_LOG ("%p interrupted", promise); + + change_func = GST_PROMISE_CHANGE_FUNC (promise); + change_data = GST_PROMISE_CHANGE_DATA (promise); + } + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + + if (change_func) + change_func (promise, change_data); +} + +/** + * gst_promise_expire: + * @promise: a #GstPromise + * + * Expire a @promise. This will wake up any waiters with + * %GST_PROMISE_RESULT_EXPIRED. Called by a message loop when the parent + * message is handled and/or destroyed (possibly unanswered). + * + * Since: 1.14 + */ +void +gst_promise_expire (GstPromise * promise) +{ + GstPromiseChangeFunc change_func = NULL; + gpointer change_data = NULL; + + g_return_if_fail (promise != NULL); + + g_mutex_lock (GST_PROMISE_LOCK (promise)); + if (GST_PROMISE_RESULT (promise) == GST_PROMISE_RESULT_PENDING) { + GST_PROMISE_RESULT (promise) = GST_PROMISE_RESULT_EXPIRED; + g_cond_broadcast (GST_PROMISE_COND (promise)); + GST_LOG ("%p expired", promise); + + change_func = GST_PROMISE_CHANGE_FUNC (promise); + change_data = GST_PROMISE_CHANGE_DATA (promise); + GST_PROMISE_CHANGE_FUNC (promise) = NULL; + GST_PROMISE_CHANGE_DATA (promise) = NULL; + } + g_mutex_unlock (GST_PROMISE_LOCK (promise)); + + if (change_func) + change_func (promise, change_data); +} + +static void +gst_promise_free (GstMiniObject * object) +{ + GstPromise *promise = (GstPromise *) object; + + /* the promise *must* be dealt with in some way before destruction */ + g_warn_if_fail (GST_PROMISE_RESULT (promise) != GST_PROMISE_RESULT_PENDING); + + if (GST_PROMISE_CHANGE_NOTIFY (promise)) + GST_PROMISE_CHANGE_NOTIFY (promise) (GST_PROMISE_CHANGE_DATA (promise)); + + if (GST_PROMISE_REPLY (promise)) { + gst_structure_set_parent_refcount (GST_PROMISE_REPLY (promise), NULL); + gst_structure_free (GST_PROMISE_REPLY (promise)); + } + g_mutex_clear (GST_PROMISE_LOCK (promise)); + g_cond_clear (GST_PROMISE_COND (promise)); + GST_LOG ("%p finalized", promise); + + g_free (promise); +} + +static void +gst_promise_init (GstPromise * promise) +{ + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (gst_promise_debug, "gstpromise", 0, "gstpromise"); + g_once_init_leave (&_init, 1); + } + + gst_mini_object_init (GST_MINI_OBJECT (promise), 0, GST_TYPE_PROMISE, NULL, + NULL, gst_promise_free); + + GST_PROMISE_REPLY (promise) = NULL; + GST_PROMISE_RESULT (promise) = GST_PROMISE_RESULT_PENDING; + g_mutex_init (GST_PROMISE_LOCK (promise)); + g_cond_init (GST_PROMISE_COND (promise)); +} + +/** + * gst_promise_new: + * + * Returns: a new #GstPromise + * + * Since: 1.14 + */ +GstPromise * +gst_promise_new (void) +{ + GstPromise *promise = GST_PROMISE (g_new0 (GstPromiseImpl, 1)); + + gst_promise_init (promise); + GST_LOG ("new promise %p", promise); + + return promise; +} + +/** + * gst_promise_new_with_change_func: + * @func: (scope notified): a #GstPromiseChangeFunc to call + * @user_data: (closure): argument to call @func with + * @notify: notification function that @user_data is no longer needed + * + * @func will be called exactly once when transitioning out of + * %GST_PROMISE_RESULT_PENDING into any of the other #GstPromiseResult + * states. + * + * Returns: a new #GstPromise + * + * Since: 1.14 + */ +GstPromise * +gst_promise_new_with_change_func (GstPromiseChangeFunc func, gpointer user_data, + GDestroyNotify notify) +{ + GstPromise *promise = gst_promise_new (); + + GST_PROMISE_CHANGE_FUNC (promise) = func; + GST_PROMISE_CHANGE_DATA (promise) = user_data; + GST_PROMISE_CHANGE_NOTIFY (promise) = notify; + + return promise; +} + +GST_DEFINE_MINI_OBJECT_TYPE (GstPromise, gst_promise); diff --git a/gst/gstpromise.h b/gst/gstpromise.h new file mode 100644 index 0000000..eaf1e95 --- /dev/null +++ b/gst/gstpromise.h @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) 2017 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PROMISE_H__ +#define __GST_PROMISE_H__ + +#include + +G_BEGIN_DECLS + +GST_API +GType gst_promise_get_type(void); +#define GST_TYPE_PROMISE (gst_promise_get_type()) +#define GST_PROMISE(obj) ((GstPromise *) obj) + +typedef struct _GstPromise GstPromise; + +/** + * GstPromiseResult: + * @GST_PROMISE_RESULT_PENDING: Initial state. Waiting for transition to any + * other state. + * @GST_PROMISE_RESULT_INTERRUPTED: Interrupted by the consumer as it doesn't + * want the value anymore. + * @GST_PROMISE_RESULT_REPLIED: A producer marked a reply + * @GST_PROMISE_RESULT_EXPIRED: The promise expired (the carrying object + * lost all refs) and the promise will never be fulfilled. + * + * The result of a #GstPromise + * + * Since: 1.14 + */ +typedef enum +{ + GST_PROMISE_RESULT_PENDING, + GST_PROMISE_RESULT_INTERRUPTED, + GST_PROMISE_RESULT_REPLIED, + GST_PROMISE_RESULT_EXPIRED, +} GstPromiseResult; + +/** + * GstPromiseChangeFunc: + * @promise: a #GstPromise + * @user_data: (closure): user data + * + * Since: 1.14 + */ +typedef void (*GstPromiseChangeFunc) (GstPromise * promise, gpointer user_data); + +/** + * GstPromise: + * @parent: parent #GstMiniObject + * + * Since: 1.14 + */ +struct _GstPromise +{ + GstMiniObject parent; +}; + +GST_API +GstPromise * gst_promise_new (void); +GST_API +GstPromise * gst_promise_new_with_change_func (GstPromiseChangeFunc func, + gpointer user_data, + GDestroyNotify notify); + +GST_API +GstPromiseResult gst_promise_wait (GstPromise * promise); +GST_API +void gst_promise_reply (GstPromise * promise, + GstStructure * s); +GST_API +void gst_promise_interrupt (GstPromise * promise); +GST_API +void gst_promise_expire (GstPromise * promise); + +GST_API +const GstStructure * gst_promise_get_reply (GstPromise * promise); + +/** + * gst_promise_ref: + * @promise: a #GstPromise. + * + * Increases the refcount of the given @promise by one. + * + * Returns: (transfer full): @promise + * + * Since: 1.14 + */ +static inline GstPromise * +gst_promise_ref (GstPromise * promise) +{ + return (GstPromise *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (promise)); +} + +/** + * gst_promise_unref: + * @promise: (transfer full): a #GstPromise. + * + * Decreases the refcount of the promise. If the refcount reaches 0, the + * promise will be freed. + * + * Since: 1.14 + */ +static inline void +gst_promise_unref (GstPromise * promise) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (promise)); +} + +G_END_DECLS + +#endif /* __GST_PROMISE_H__ */ diff --git a/gst/gstprotection.c b/gst/gstprotection.c new file mode 100644 index 0000000..e6aed07 --- /dev/null +++ b/gst/gstprotection.c @@ -0,0 +1,294 @@ +/* GStreamer + * Copyright (C) <2013> YouView TV Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstprotection + * @title: GstProtection + * @short_description: Functions and classes to support encrypted streams. + * + * The GstProtectionMeta class enables the information needed to decrypt a + * #GstBuffer to be attached to that buffer. + * + * Typically, a demuxer element would attach GstProtectionMeta objects + * to the buffers that it pushes downstream. The demuxer would parse the + * protection information for a video/audio frame from its input data and use + * this information to populate the #GstStructure @info field, + * which is then encapsulated in a GstProtectionMeta object and attached to + * the corresponding output buffer using the gst_buffer_add_protection_meta() + * function. The information in this attached GstProtectionMeta would be + * used by a downstream decrypter element to recover the original unencrypted + * frame. + * + * Since: 1.6 + */ + +#include "gst_private.h" +#include "glib-compat-private.h" + +#include "gstprotection.h" + +#define GST_CAT_DEFAULT GST_CAT_PROTECTION + +static gboolean gst_protection_meta_init (GstMeta * meta, gpointer params, + GstBuffer * buffer); + +static void gst_protection_meta_free (GstMeta * meta, GstBuffer * buffer); + +static const gchar *gst_protection_factory_check (GstElementFactory * fact, + const gchar ** system_identifiers); + +GType +gst_protection_meta_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstProtectionMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +static gboolean +gst_protection_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GstProtectionMeta *protection_meta = (GstProtectionMeta *) meta; + + protection_meta->info = NULL; + + return TRUE; +} + +static void +gst_protection_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstProtectionMeta *protection_meta = (GstProtectionMeta *) meta; + + if (protection_meta->info) + gst_structure_free (protection_meta->info); +} + +static gboolean +gst_protection_meta_transform (GstBuffer * transbuf, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstProtectionMeta *protection_meta = (GstProtectionMeta *) meta; + + if (GST_META_TRANSFORM_IS_COPY (type)) { + GstMetaTransformCopy *copy = data; + if (!copy->region) { + /* only copy if the complete data is copied as well */ + gst_buffer_add_protection_meta (transbuf, + gst_structure_copy (protection_meta->info)); + } else { + return FALSE; + } + } else { + /* transform type not supported */ + return FALSE; + } + return TRUE; +} + +const GstMetaInfo * +gst_protection_meta_get_info (void) +{ + static const GstMetaInfo *protection_meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & protection_meta_info)) { + const GstMetaInfo *meta = + gst_meta_register (GST_PROTECTION_META_API_TYPE, "GstProtectionMeta", + sizeof (GstProtectionMeta), gst_protection_meta_init, + gst_protection_meta_free, gst_protection_meta_transform); + + g_once_init_leave ((GstMetaInfo **) & protection_meta_info, + (GstMetaInfo *) meta); + } + return protection_meta_info; +} + +/** + * gst_buffer_add_protection_meta: + * @buffer: #GstBuffer holding an encrypted sample, to which protection + * metadata should be added. + * @info: (transfer full): a #GstStructure holding cryptographic + * information relating to the sample contained in @buffer. This + * function takes ownership of @info. + * + * Attaches protection metadata to a #GstBuffer. + * + * Returns: (transfer none): a pointer to the added #GstProtectionMeta if successful; %NULL if + * unsuccessful. + * + * Since: 1.6 + */ +GstProtectionMeta * +gst_buffer_add_protection_meta (GstBuffer * buffer, GstStructure * info) +{ + GstProtectionMeta *meta; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (info != NULL, NULL); + + meta = + (GstProtectionMeta *) gst_buffer_add_meta (buffer, + GST_PROTECTION_META_INFO, NULL); + + meta->info = info; + + return meta; +} + +/** + * gst_protection_select_system: + * @system_identifiers: (transfer none) (array zero-terminated=1): A null terminated array of strings + * that contains the UUID values of each protection system that is to be + * checked. + * + * Iterates the supplied list of UUIDs and checks the GstRegistry for + * an element that supports one of the supplied UUIDs. If more than one + * element matches, the system ID of the highest ranked element is selected. + * + * Returns: (transfer none) (nullable): One of the strings from + * @system_identifiers that indicates the highest ranked element that + * implements the protection system indicated by that system ID, or %NULL if no + * element has been found. + * + * Since: 1.6 + */ +const gchar * +gst_protection_select_system (const gchar ** system_identifiers) +{ + GList *decryptors, *walk; + const gchar *retval = NULL; + + decryptors = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECRYPTOR, + GST_RANK_MARGINAL); + + for (walk = decryptors; !retval && walk; walk = g_list_next (walk)) { + GstElementFactory *fact = (GstElementFactory *) walk->data; + + retval = gst_protection_factory_check (fact, system_identifiers); + } + + gst_plugin_feature_list_free (decryptors); + + return retval; +} + +/** + * gst_protection_filter_systems_by_available_decryptors: + * @system_identifiers: (transfer none): A null terminated array of strings + * that contains the UUID values of each protection system that is to be + * checked. + * + * Iterates the supplied list of UUIDs and checks the GstRegistry for + * all the decryptors supporting one of the supplied UUIDs. + * + * Returns: (transfer full) (nullable): A null terminated array containing all + * the @system_identifiers supported by the set of available decryptors, or + * %NULL if no matches were found. + * + * Since: 1.14 + */ +gchar ** +gst_protection_filter_systems_by_available_decryptors (const gchar ** + system_identifiers) +{ + GList *decryptors, *walk; + gchar **retval; + guint i = 0, decryptors_number; + + decryptors = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECRYPTOR, + GST_RANK_MARGINAL); + + decryptors_number = g_list_length (decryptors); + + GST_TRACE ("found %u decrytors", decryptors_number); + + if (decryptors_number == 0) + return NULL; + + retval = g_new (gchar *, decryptors_number + 1); + + for (walk = decryptors; walk; walk = g_list_next (walk)) { + GstElementFactory *fact = (GstElementFactory *) walk->data; + const char *found_sys_id = + gst_protection_factory_check (fact, system_identifiers); + + GST_DEBUG ("factory %s is valid for %s", GST_OBJECT_NAME (fact), + found_sys_id); + + if (found_sys_id) { + retval[i++] = g_strdup (found_sys_id); + } + } + retval[i] = NULL; + + if (retval[0] == NULL) { + g_free (retval); + retval = NULL; + } + + gst_plugin_feature_list_free (decryptors); + + return retval; +} + +static const gchar * +gst_protection_factory_check (GstElementFactory * fact, + const gchar ** system_identifiers) +{ + const GList *template, *walk; + const gchar *retval = NULL; + + template = gst_element_factory_get_static_pad_templates (fact); + for (walk = template; walk && !retval; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + GstCaps *caps = gst_static_pad_template_get_caps (templ); + guint leng = gst_caps_get_size (caps); + guint i, j; + + for (i = 0; !retval && i < leng; ++i) { + GstStructure *st; + + st = gst_caps_get_structure (caps, i); + if (gst_structure_has_field_typed (st, + GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING)) { + const gchar *sys_id = + gst_structure_get_string (st, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD); + GST_DEBUG ("Found decryptor that supports protection system %s", + sys_id); + for (j = 0; !retval && system_identifiers[j]; ++j) { + GST_TRACE (" compare with %s", system_identifiers[j]); + if (g_ascii_strcasecmp (system_identifiers[j], sys_id) == 0) { + GST_DEBUG (" Selecting %s", system_identifiers[j]); + retval = system_identifiers[j]; + } + } + } + } + gst_caps_unref (caps); + } + + return retval; +} diff --git a/gst/gstprotection.h b/gst/gstprotection.h new file mode 100644 index 0000000..a7669ea --- /dev/null +++ b/gst/gstprotection.h @@ -0,0 +1,79 @@ +/* GStreamer + * Copyright (C) <2015> YouView TV Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PROTECTION_H__ +#define __GST_PROTECTION_H__ + +#include + +G_BEGIN_DECLS + +/** + * GST_PROTECTION_SYSTEM_ID_CAPS_FIELD: + * + * The field name in a GstCaps that is used to signal the UUID of the protection + * system. + * + * Since: 1.6 + */ +#define GST_PROTECTION_SYSTEM_ID_CAPS_FIELD "protection-system" + +typedef struct _GstProtectionMeta GstProtectionMeta; +/** + * GstProtectionMeta: + * @meta: the parent #GstMeta. + * @info: the cryptographic information needed to decrypt the sample. + * + * Metadata type that holds information about a sample from a protection-protected + * track, including the information needed to decrypt it (if it is encrypted). + * + * Since: 1.6 + */ +struct _GstProtectionMeta +{ + GstMeta meta; + + GstStructure *info; +}; + +GST_API +GType gst_protection_meta_api_get_type (void); + +#define GST_PROTECTION_META_API_TYPE (gst_protection_meta_api_get_type()) + +#define gst_buffer_get_protection_meta(b) \ + ((GstProtectionMeta*)gst_buffer_get_meta ((b), GST_PROTECTION_META_API_TYPE)) + +#define GST_PROTECTION_META_INFO (gst_protection_meta_get_info()) + +GST_API +const GstMetaInfo * gst_protection_meta_get_info (void); + +GST_API +GstProtectionMeta * gst_buffer_add_protection_meta (GstBuffer * buffer, + GstStructure * info); +GST_API +const gchar * gst_protection_select_system (const gchar ** system_identifiers); + +GST_API +gchar ** gst_protection_filter_systems_by_available_decryptors ( + const gchar ** system_identifiers); + +G_END_DECLS +#endif /* __GST_PROTECTION_META_H__ */ diff --git a/gst/gstquark.c b/gst/gstquark.c new file mode 100644 index 0000000..4500cc6 --- /dev/null +++ b/gst/gstquark.c @@ -0,0 +1,95 @@ +/* GStreamer + * Copyright (C) 2006 Jan Schmidt + * + * gstquark.c: Registered quarks for the _priv_gst_quark_table, private to + * GStreamer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "gst_private.h" +#include "gstquark.h" +#include "gstelementmetadata.h" + +/* These strings must match order and number declared in the GstQuarkId + * enum in gstquark.h! */ +static const gchar *_quark_strings[] = { + "format", "current", "duration", "rate", + "seekable", "segment-start", "segment-end", + "src_format", "src_value", "dest_format", "dest_value", + "start_format", "start_value", "stop_format", "stop_value", + "gerror", "debug", "buffer-percent", "buffering-mode", + "avg-in-rate", "avg-out-rate", "buffering-left", + "estimated-total", "old-state", "new-state", "pending-state", + "clock", "ready", "position", "reset-time", "live", "min-latency", + "max-latency", "busy", "type", "owner", "update", "applied-rate", + "start", "stop", "minsize", "maxsize", "async", "proportion", + "diff", "timestamp", "flags", "cur-type", "cur", "stop-type", + "latency", "uri", "object", "taglist", "GstEventSegment", + "GstEventBufferSize", "GstEventQOS", "GstEventSeek", "GstEventLatency", + "GstMessageError", "GstMessageWarning", "GstMessageInfo", + "GstMessageBuffering", "GstMessageStateChanged", "GstMessageClockProvide", + "GstMessageClockLost", "GstMessageNewClock", "GstMessageStructureChange", + "GstMessageSegmentStart", "GstMessageSegmentDone", + "GstMessageDurationChanged", + "GstMessageAsyncDone", "GstMessageRequestState", "GstMessageStreamStatus", + "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert", + "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering", + "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush", + "intermediate", "GstMessageStepStart", "active", "eos", "sink-message", + "message", "GstMessageQOS", "running-time", "stream-time", "jitter", + "quality", "processed", "dropped", "buffering-ranges", "GstMessageProgress", + "code", "text", "percent", "timeout", "GstBufferPoolConfig", "caps", "size", + "min-buffers", "max-buffers", "prefix", "padding", "align", "time", + "GstQueryAllocation", "need-pool", "meta", "pool", "GstEventCaps", + "GstEventReconfigure", "segment", "GstQueryScheduling", "pull-mode", + "allocator", "GstEventFlushStop", "options", "GstQueryAcceptCaps", + "result", "GstQueryCaps", "filter", "modes", "GstEventStreamConfig", + "setup-data", "stream-headers", "GstEventGap", "GstQueryDrain", "params", + "GstEventTocSelect", "uid", "GstQueryToc", GST_ELEMENT_METADATA_LONGNAME, + GST_ELEMENT_METADATA_KLASS, GST_ELEMENT_METADATA_DESCRIPTION, + GST_ELEMENT_METADATA_AUTHOR, "toc", "toc-entry", "updated", "extend-uid", + "uid", "tags", "sub-entries", "info", "GstMessageTag", "GstEventTag", + "GstMessageResetTime", + "GstMessageToc", "GstEventTocGlobal", "GstEventTocCurrent", + "GstEventSegmentDone", + "GstEventStreamStart", "stream-id", "GstQueryContext", + "GstMessageNeedContext", "GstMessageHaveContext", "context", "context-type", + "GstMessageStreamStart", "group-id", "uri-redirection", + "GstMessageDeviceAdded", "GstMessageDeviceRemoved", "device", + "uri-redirection-permanent", "GstMessagePropertyNotify", "property-name", + "property-value", "streams", "GstEventSelectStreams", + "GstMessageStreamCollection", "collection", "stream", "stream-collection", + "GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations", + "redirect-entry-taglists", "redirect-entry-structures", + "GstEventStreamGroupDone" +}; + +GQuark _priv_gst_quark_table[GST_QUARK_MAX]; + +void +_priv_gst_quarks_initialize (void) +{ + gint i; + + if (G_N_ELEMENTS (_quark_strings) != GST_QUARK_MAX) + g_warning ("the quark table is not consistent! %d != %d", + (int) G_N_ELEMENTS (_quark_strings), GST_QUARK_MAX); + + for (i = 0; i < GST_QUARK_MAX; i++) { + _priv_gst_quark_table[i] = g_quark_from_static_string (_quark_strings[i]); + } +} diff --git a/gst/gstquark.h b/gst/gstquark.h new file mode 100644 index 0000000..e41466b --- /dev/null +++ b/gst/gstquark.h @@ -0,0 +1,227 @@ +/* GStreamer + * Copyright (C) 2006 Jan Schmidt + * + * gstquark.h: Private header for storing quark info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_QUARK_H__ +#define __GST_QUARK_H__ + +#include + +/* These enums need to match the number and order + * of strings declared in _quark_table, in gstquark.c */ +typedef enum _GstQuarkId +{ + GST_QUARK_FORMAT = 0, + GST_QUARK_CURRENT = 1, + GST_QUARK_DURATION = 2, + GST_QUARK_RATE = 3, + GST_QUARK_SEEKABLE = 4, + GST_QUARK_SEGMENT_START = 5, + GST_QUARK_SEGMENT_END = 6, + GST_QUARK_SRC_FORMAT = 7, + GST_QUARK_SRC_VALUE = 8, + GST_QUARK_DEST_FORMAT = 9, + GST_QUARK_DEST_VALUE = 10, + GST_QUARK_START_FORMAT = 11, + GST_QUARK_START_VALUE = 12, + GST_QUARK_STOP_FORMAT = 13, + GST_QUARK_STOP_VALUE = 14, + GST_QUARK_GERROR = 15, + GST_QUARK_DEBUG = 16, + GST_QUARK_BUFFER_PERCENT = 17, + GST_QUARK_BUFFERING_MODE = 18, + GST_QUARK_AVG_IN_RATE = 19, + GST_QUARK_AVG_OUT_RATE = 20, + GST_QUARK_BUFFERING_LEFT = 21, + GST_QUARK_ESTIMATED_TOTAL = 22, + GST_QUARK_OLD_STATE = 23, + GST_QUARK_NEW_STATE = 24, + GST_QUARK_PENDING_STATE = 25, + GST_QUARK_CLOCK = 26, + GST_QUARK_READY = 27, + GST_QUARK_POSITION = 28, + GST_QUARK_RESET_TIME = 29, + GST_QUARK_LIVE = 30, + GST_QUARK_MIN_LATENCY = 31, + GST_QUARK_MAX_LATENCY = 32, + GST_QUARK_BUSY = 33, + GST_QUARK_TYPE = 34, + GST_QUARK_OWNER = 35, + GST_QUARK_UPDATE = 36, + GST_QUARK_APPLIED_RATE = 37, + GST_QUARK_START = 38, + GST_QUARK_STOP = 39, + GST_QUARK_MINSIZE = 40, + GST_QUARK_MAXSIZE = 41, + GST_QUARK_ASYNC = 42, + GST_QUARK_PROPORTION = 43, + GST_QUARK_DIFF = 44, + GST_QUARK_TIMESTAMP = 45, + GST_QUARK_FLAGS = 46, + GST_QUARK_CUR_TYPE = 47, + GST_QUARK_CUR = 48, + GST_QUARK_STOP_TYPE = 49, + GST_QUARK_LATENCY = 50, + GST_QUARK_URI = 51, + GST_QUARK_OBJECT = 52, + GST_QUARK_TAGLIST = 53, + GST_QUARK_EVENT_SEGMENT = 54, + GST_QUARK_EVENT_BUFFER_SIZE = 55, + GST_QUARK_EVENT_QOS = 56, + GST_QUARK_EVENT_SEEK = 57, + GST_QUARK_EVENT_LATENCY = 58, + GST_QUARK_MESSAGE_ERROR = 59, + GST_QUARK_MESSAGE_WARNING = 60, + GST_QUARK_MESSAGE_INFO = 61, + GST_QUARK_MESSAGE_BUFFERING = 62, + GST_QUARK_MESSAGE_STATE_CHANGED = 63, + GST_QUARK_MESSAGE_CLOCK_PROVIDE = 64, + GST_QUARK_MESSAGE_CLOCK_LOST = 65, + GST_QUARK_MESSAGE_NEW_CLOCK = 66, + GST_QUARK_MESSAGE_STRUCTURE_CHANGE = 67, + GST_QUARK_MESSAGE_SEGMENT_START = 68, + GST_QUARK_MESSAGE_SEGMENT_DONE = 69, + GST_QUARK_MESSAGE_DURATION_CHANGED = 70, + GST_QUARK_MESSAGE_ASYNC_DONE = 71, + GST_QUARK_MESSAGE_REQUEST_STATE = 72, + GST_QUARK_MESSAGE_STREAM_STATUS = 73, + GST_QUARK_QUERY_POSITION = 74, + GST_QUARK_QUERY_DURATION = 75, + GST_QUARK_QUERY_LATENCY = 76, + GST_QUARK_QUERY_CONVERT = 77, + GST_QUARK_QUERY_SEGMENT = 78, + GST_QUARK_QUERY_SEEKING = 79, + GST_QUARK_QUERY_FORMATS = 80, + GST_QUARK_QUERY_BUFFERING = 81, + GST_QUARK_QUERY_URI = 82, + GST_QUARK_EVENT_STEP = 83, + GST_QUARK_MESSAGE_STEP_DONE = 84, + GST_QUARK_AMOUNT = 85, + GST_QUARK_FLUSH = 86, + GST_QUARK_INTERMEDIATE = 87, + GST_QUARK_MESSAGE_STEP_START = 88, + GST_QUARK_ACTIVE = 89, + GST_QUARK_EOS = 90, + GST_QUARK_EVENT_SINK_MESSAGE = 91, + GST_QUARK_MESSAGE = 92, + GST_QUARK_MESSAGE_QOS = 93, + GST_QUARK_RUNNING_TIME = 94, + GST_QUARK_STREAM_TIME = 95, + GST_QUARK_JITTER = 96, + GST_QUARK_QUALITY = 97, + GST_QUARK_PROCESSED = 98, + GST_QUARK_DROPPED = 99, + GST_QUARK_BUFFERING_RANGES = 100, + GST_QUARK_MESSAGE_PROGRESS = 101, + GST_QUARK_CODE = 102, + GST_QUARK_TEXT = 103, + GST_QUARK_PERCENT = 104, + GST_QUARK_TIMEOUT = 105, + GST_QUARK_BUFFER_POOL_CONFIG = 106, + GST_QUARK_CAPS = 107, + GST_QUARK_SIZE = 108, + GST_QUARK_MIN_BUFFERS = 109, + GST_QUARK_MAX_BUFFERS = 110, + GST_QUARK_PREFIX = 111, + GST_QUARK_PADDING = 112, + GST_QUARK_ALIGN = 113, + GST_QUARK_TIME = 114, + GST_QUARK_QUERY_ALLOCATION = 115, + GST_QUARK_NEED_POOL = 116, + GST_QUARK_META = 117, + GST_QUARK_POOL = 118, + GST_QUARK_EVENT_CAPS = 119, + GST_QUARK_EVENT_RECONFIGURE = 120, + GST_QUARK_SEGMENT = 121, + GST_QUARK_QUERY_SCHEDULING = 122, + GST_QUARK_PULL_MODE = 123, + GST_QUARK_ALLOCATOR = 124, + GST_QUARK_EVENT_FLUSH_STOP = 125, + GST_QUARK_OPTIONS = 126, + GST_QUARK_QUERY_ACCEPT_CAPS = 127, + GST_QUARK_RESULT = 128, + GST_QUARK_QUERY_CAPS = 129, + GST_QUARK_FILTER = 130, + GST_QUARK_MODES = 131, + GST_QUARK_EVENT_STREAM_CONFIG = 132, + GST_QUARK_SETUP_DATA = 133, + GST_QUARK_STREAM_HEADERS = 134, + GST_QUARK_EVENT_GAP = 135, + GST_QUARK_QUERY_DRAIN = 136, + GST_QUARK_PARAMS = 137, + GST_QUARK_EVENT_TOC_SELECT = 138, + GST_QUARK_UID = 139, + GST_QUARK_QUERY_TOC = 140, + GST_QUARK_ELEMENT_METADATA_LONGNAME = 141, + GST_QUARK_ELEMENT_METADATA_KLASS = 142, + GST_QUARK_ELEMENT_METADATA_DESCRIPTION = 143, + GST_QUARK_ELEMENT_METADATA_AUTHOR = 144, + GST_QUARK_TOC = 145, + GST_QUARK_TOC_ENTRY = 146, + GST_QUARK_UPDATED = 147, + GST_QUARK_EXTEND_UID = 148, + GST_QUARK_TOC_UID = 149, + GST_QUARK_TAGS = 150, + GST_QUARK_SUB_ENTRIES = 151, + GST_QUARK_INFO = 152, + GST_QUARK_MESSAGE_TAG = 153, + GST_QUARK_EVENT_TAG = 154, + GST_QUARK_MESSAGE_RESET_TIME = 155, + GST_QUARK_MESSAGE_TOC = 156, + GST_QUARK_EVENT_TOC_GLOBAL = 157, + GST_QUARK_EVENT_TOC_CURRENT = 158, + GST_QUARK_EVENT_SEGMENT_DONE = 159, + GST_QUARK_EVENT_STREAM_START = 160, + GST_QUARK_STREAM_ID = 161, + GST_QUARK_QUERY_CONTEXT = 162, + GST_QUARK_MESSAGE_NEED_CONTEXT = 163, + GST_QUARK_MESSAGE_HAVE_CONTEXT = 164, + GST_QUARK_CONTEXT = 165, + GST_QUARK_CONTEXT_TYPE = 166, + GST_QUARK_MESSAGE_STREAM_START = 167, + GST_QUARK_GROUP_ID = 168, + GST_QUARK_URI_REDIRECTION = 169, + GST_QUARK_MESSAGE_DEVICE_ADDED = 170, + GST_QUARK_MESSAGE_DEVICE_REMOVED = 171, + GST_QUARK_DEVICE = 172, + GST_QUARK_URI_REDIRECTION_PERMANENT = 173, + GST_QUARK_MESSAGE_PROPERTY_NOTIFY = 174, + GST_QUARK_PROPERTY_NAME = 175, + GST_QUARK_PROPERTY_VALUE = 176, + GST_QUARK_STREAMS = 177, + GST_QUARK_EVENT_SELECT_STREAMS = 178, + GST_QUARK_MESSAGE_STREAM_COLLECTION = 179, + GST_QUARK_COLLECTION = 180, + GST_QUARK_STREAM = 181, + GST_QUARK_EVENT_STREAM_COLLECTION = 182, + GST_QUARK_MESSAGE_STREAMS_SELECTED = 183, + GST_QUARK_MESSAGE_REDIRECT = 184, + GST_QUARK_REDIRECT_ENTRY_LOCATIONS = 185, + GST_QUARK_REDIRECT_ENTRY_TAGLISTS = 186, + GST_QUARK_REDIRECT_ENTRY_STRUCTURES = 187, + GST_QUARK_EVENT_STREAM_GROUP_DONE = 188, + GST_QUARK_MAX = 189 +} GstQuarkId; + +extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; + +#define GST_QUARK(q) _priv_gst_quark_table[GST_QUARK_##q] + +#endif diff --git a/gst/gstquery.c b/gst/gstquery.c new file mode 100644 index 0000000..b6dba1a --- /dev/null +++ b/gst/gstquery.c @@ -0,0 +1,2653 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstquery.c: GstQueryType registration and Query parsing/creation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstquery + * @title: GstQuery + * @short_description: Provide functions to create queries, and to set and parse + * values in them. + * @see_also: #GstPad, #GstElement + * + * Queries can be performed on pads (gst_pad_query()) and elements + * (gst_element_query()). Please note that some queries might need a running + * pipeline to work. + * + * Queries can be created using the gst_query_new_*() functions. + * Query values can be set using gst_query_set_*(), and parsed using + * gst_query_parse_*() helpers. + * + * The following example shows how to query the duration of a pipeline: + * |[ + * GstQuery *query; + * gboolean res; + * query = gst_query_new_duration (GST_FORMAT_TIME); + * res = gst_element_query (pipeline, query); + * if (res) { + * gint64 duration; + * gst_query_parse_duration (query, NULL, &duration); + * g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + * } else { + * g_print ("duration query failed..."); + * } + * gst_query_unref (query); + * ]| + */ + + +#include "gst_private.h" +#include "gstinfo.h" +#include "gstquery.h" +#include "gstvalue.h" +#include "gstenumtypes.h" +#include "gstquark.h" +#include "gsturi.h" +#include "gstbufferpool.h" + +GST_DEBUG_CATEGORY_STATIC (gst_query_debug); +#define GST_CAT_DEFAULT gst_query_debug + +GType _gst_query_type = 0; + +typedef struct +{ + GstQuery query; + + GstStructure *structure; +} GstQueryImpl; + +#define GST_QUERY_STRUCTURE(q) (((GstQueryImpl *)(q))->structure) + + +typedef struct +{ + const gint type; + const gchar *name; + GQuark quark; +} GstQueryQuarks; + +static GstQueryQuarks query_quarks[] = { + {GST_QUERY_UNKNOWN, "unknown", 0}, + {GST_QUERY_POSITION, "position", 0}, + {GST_QUERY_DURATION, "duration", 0}, + {GST_QUERY_LATENCY, "latency", 0}, + {GST_QUERY_JITTER, "jitter", 0}, + {GST_QUERY_RATE, "rate", 0}, + {GST_QUERY_SEEKING, "seeking", 0}, + {GST_QUERY_SEGMENT, "segment", 0}, + {GST_QUERY_CONVERT, "convert", 0}, + {GST_QUERY_FORMATS, "formats", 0}, + {GST_QUERY_BUFFERING, "buffering", 0}, + {GST_QUERY_CUSTOM, "custom", 0}, + {GST_QUERY_URI, "uri", 0}, + {GST_QUERY_ALLOCATION, "allocation", 0}, + {GST_QUERY_SCHEDULING, "scheduling", 0}, + {GST_QUERY_ACCEPT_CAPS, "accept-caps", 0}, + {GST_QUERY_CAPS, "caps", 0}, + {GST_QUERY_DRAIN, "drain", 0}, + {GST_QUERY_CONTEXT, "context", 0}, + + {0, NULL, 0} +}; + +GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query); + +void +_priv_gst_query_initialize (void) +{ + gint i; + + _gst_query_type = gst_query_get_type (); + + GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system"); + + for (i = 0; query_quarks[i].name; i++) { + query_quarks[i].quark = g_quark_from_static_string (query_quarks[i].name); + } +} + +/** + * gst_query_type_get_name: + * @type: the query type + * + * Get a printable name for the given query type. Do not modify or free. + * + * Returns: a reference to the static name of the query. + */ +const gchar * +gst_query_type_get_name (GstQueryType type) +{ + gint i; + + for (i = 0; query_quarks[i].name; i++) { + if (type == query_quarks[i].type) + return query_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_query_type_to_quark: + * @type: the query type + * + * Get the unique quark for the given query type. + * + * Returns: the quark associated with the query type + */ +GQuark +gst_query_type_to_quark (GstQueryType type) +{ + gint i; + + for (i = 0; query_quarks[i].name; i++) { + if (type == query_quarks[i].type) + return query_quarks[i].quark; + } + return 0; +} + +/** + * gst_query_type_get_flags: + * @type: a #GstQueryType + * + * Gets the #GstQueryTypeFlags associated with @type. + * + * Returns: a #GstQueryTypeFlags. + */ +GstQueryTypeFlags +gst_query_type_get_flags (GstQueryType type) +{ + GstQueryTypeFlags ret; + + ret = type & ((1 << GST_QUERY_NUM_SHIFT) - 1); + + return ret; +} + +static void +_gst_query_free (GstQuery * query) +{ + GstStructure *s; + + g_return_if_fail (query != NULL); + + s = GST_QUERY_STRUCTURE (query); + if (s) { + gst_structure_set_parent_refcount (s, NULL); + gst_structure_free (s); + } + + g_slice_free1 (sizeof (GstQueryImpl), query); +} + +static GstQuery * +_gst_query_copy (GstQuery * query) +{ + GstQuery *copy; + GstStructure *s; + + s = GST_QUERY_STRUCTURE (query); + if (s) { + s = gst_structure_copy (s); + } + copy = gst_query_new_custom (query->type, s); + + return copy; +} + +/** + * gst_query_new_position: + * @format: the default #GstFormat for the new query + * + * Constructs a new query stream position query object. Use gst_query_unref() + * when done with it. A position query is used to query the current position + * of playback in the streams, in some format. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_position (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_POSITION, structure); + + return query; +} + +/** + * gst_query_set_position: + * @query: a #GstQuery with query type GST_QUERY_POSITION + * @format: the requested #GstFormat + * @cur: the position to set + * + * Answer a position query by setting the requested value in the given format. + */ +void +gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur) +{ + GstStructure *s; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); + + s = GST_QUERY_STRUCTURE (query); + g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s, + GST_QUARK (FORMAT)))); + + gst_structure_id_set (s, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL); +} + +/** + * gst_query_parse_position: + * @query: a #GstQuery + * @format: (out) (allow-none): the storage for the #GstFormat of the + * position values (may be %NULL) + * @cur: (out) (allow-none): the storage for the current position (may be %NULL) + * + * Parse a position query, writing the format into @format, and the position + * into @cur, if the respective parameters are non-%NULL. + */ +void +gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); + + structure = GST_QUERY_STRUCTURE (query); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (cur) + *cur = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (CURRENT))); +} + + +/** + * gst_query_new_duration: + * @format: the #GstFormat for this duration query + * + * Constructs a new stream duration query object to query in the given format. + * Use gst_query_unref() when done with it. A duration query will give the + * total length of the stream. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_duration (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_DURATION, structure); + + return query; +} + +/** + * gst_query_set_duration: + * @query: a #GstQuery + * @format: the #GstFormat for the duration + * @duration: the duration of the stream + * + * Answer a duration query by setting the requested value in the given format. + */ +void +gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration) +{ + GstStructure *s; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION); + + s = GST_QUERY_STRUCTURE (query); + g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s, + GST_QUARK (FORMAT)))); + gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL); +} + +/** + * gst_query_parse_duration: + * @query: a #GstQuery + * @format: (out) (allow-none): the storage for the #GstFormat of the duration + * value, or %NULL. + * @duration: (out) (allow-none): the storage for the total duration, or %NULL. + * + * Parse a duration query answer. Write the format of the duration into @format, + * and the value into @duration, if the respective variables are non-%NULL. + */ +void +gst_query_parse_duration (GstQuery * query, GstFormat * format, + gint64 * duration) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION); + + structure = GST_QUERY_STRUCTURE (query); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (duration) + *duration = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (DURATION))); +} + +/** + * gst_query_new_latency: + * + * Constructs a new latency query object. + * Use gst_query_unref() when done with it. A latency query is usually performed + * by sinks to compensate for additional latency introduced by elements in the + * pipeline. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a #GstQuery + */ +GstQuery * +gst_query_new_latency (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY), + GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE, + GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL); + + query = gst_query_new_custom (GST_QUERY_LATENCY, structure); + + return query; +} + +/** + * gst_query_set_latency: + * @query: a #GstQuery + * @live: if there is a live element upstream + * @min_latency: the minimal latency of the upstream elements + * @max_latency: the maximal latency of the upstream elements + * + * Answer a latency query by setting the requested values in the given format. + */ +void +gst_query_set_latency (GstQuery * query, gboolean live, + GstClockTime min_latency, GstClockTime max_latency) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); + g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (LIVE), G_TYPE_BOOLEAN, live, + GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency, + GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL); +} + +/** + * gst_query_parse_latency: + * @query: a #GstQuery + * @live: (out) (allow-none): storage for live or %NULL + * @min_latency: (out) (allow-none): the storage for the min latency or %NULL + * @max_latency: (out) (allow-none): the storage for the max latency or %NULL + * + * Parse a latency query answer. + */ +void +gst_query_parse_latency (GstQuery * query, gboolean * live, + GstClockTime * min_latency, GstClockTime * max_latency) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY); + + structure = GST_QUERY_STRUCTURE (query); + if (live) + *live = + g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (LIVE))); + if (min_latency) + *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (MIN_LATENCY))); + if (max_latency) + *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure, + GST_QUARK (MAX_LATENCY))); +} + +/** + * gst_query_new_convert: + * @src_format: the source #GstFormat for the new query + * @value: the value to convert + * @dest_format: the target #GstFormat + * + * Constructs a new convert query object. Use gst_query_unref() + * when done with it. A convert query is used to ask for a conversion between + * one format and another. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a #GstQuery + */ +GstQuery * +gst_query_new_convert (GstFormat src_format, gint64 value, + GstFormat dest_format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT), + GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format, + GST_QUARK (SRC_VALUE), G_TYPE_INT64, value, + GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format, + GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_CONVERT, structure); + + return query; +} + +/** + * gst_query_set_convert: + * @query: a #GstQuery + * @src_format: the source #GstFormat + * @src_value: the source value + * @dest_format: the destination #GstFormat + * @dest_value: the destination value + * + * Answer a convert query by setting the requested values. + */ +void +gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 dest_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format, + GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value, + GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format, + GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL); +} + +/** + * gst_query_parse_convert: + * @query: a #GstQuery + * @src_format: (out) (allow-none): the storage for the #GstFormat of the + * source value, or %NULL + * @src_value: (out) (allow-none): the storage for the source value, or %NULL + * @dest_format: (out) (allow-none): the storage for the #GstFormat of the + * destination value, or %NULL + * @dest_value: (out) (allow-none): the storage for the destination value, + * or %NULL + * + * Parse a convert query answer. Any of @src_format, @src_value, @dest_format, + * and @dest_value may be %NULL, in which case that value is omitted. + */ +void +gst_query_parse_convert (GstQuery * query, GstFormat * src_format, + gint64 * src_value, GstFormat * dest_format, gint64 * dest_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT); + + structure = GST_QUERY_STRUCTURE (query); + if (src_format) + *src_format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (SRC_FORMAT))); + if (src_value) + *src_value = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (SRC_VALUE))); + if (dest_format) + *dest_format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (DEST_FORMAT))); + if (dest_value) + *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (DEST_VALUE))); +} + +/** + * gst_query_new_segment: + * @format: the #GstFormat for the new query + * + * Constructs a new segment query object. Use gst_query_unref() + * when done with it. A segment query is used to discover information about the + * currently configured segment for playback. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_segment (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT), + GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), + GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_SEGMENT, structure); + + return query; +} + +/** + * gst_query_set_segment: + * @query: a #GstQuery + * @rate: the rate of the segment + * @format: the #GstFormat of the segment values (@start_value and @stop_value) + * @start_value: the start value + * @stop_value: the stop value + * + * Answer a segment query by setting the requested values. The normal + * playback segment of a pipeline is 0 to duration at the default rate of + * 1.0. If a seek was performed on the pipeline to play a different + * segment, this query will return the range specified in the last seek. + * + * @start_value and @stop_value will respectively contain the configured + * playback range start and stop values expressed in @format. + * The values are always between 0 and the duration of the media and + * @start_value <= @stop_value. @rate will contain the playback rate. For + * negative rates, playback will actually happen from @stop_value to + * @start_value. + */ +void +gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format, + gint64 start_value, gint64 stop_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (RATE), G_TYPE_DOUBLE, rate, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (START_VALUE), G_TYPE_INT64, start_value, + GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL); +} + +/** + * gst_query_parse_segment: + * @query: a #GstQuery + * @rate: (out) (allow-none): the storage for the rate of the segment, or %NULL + * @format: (out) (allow-none): the storage for the #GstFormat of the values, + * or %NULL + * @start_value: (out) (allow-none): the storage for the start value, or %NULL + * @stop_value: (out) (allow-none): the storage for the stop value, or %NULL + * + * Parse a segment query answer. Any of @rate, @format, @start_value, and + * @stop_value may be %NULL, which will cause this value to be omitted. + * + * See gst_query_set_segment() for an explanation of the function arguments. + */ +void +gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format, + gint64 * start_value, gint64 * stop_value) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT); + + structure = GST_QUERY_STRUCTURE (query); + if (rate) + *rate = g_value_get_double (gst_structure_id_get_value (structure, + GST_QUARK (RATE))); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (start_value) + *start_value = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (START_VALUE))); + if (stop_value) + *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (STOP_VALUE))); +} + +/** + * gst_query_new_custom: + * @type: the query type + * @structure: (allow-none) (transfer full): a structure for the query + * + * Constructs a new custom query object. Use gst_query_unref() + * when done with it. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full) (nullable): a new #GstQuery + */ +GstQuery * +gst_query_new_custom (GstQueryType type, GstStructure * structure) +{ + GstQueryImpl *query; + + query = g_slice_new0 (GstQueryImpl); + + GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type)); + + if (structure) { + /* structure must not have a parent */ + if (!gst_structure_set_parent_refcount (structure, + &query->query.mini_object.refcount)) + goto had_parent; + } + + gst_mini_object_init (GST_MINI_OBJECT_CAST (query), 0, _gst_query_type, + (GstMiniObjectCopyFunction) _gst_query_copy, NULL, + (GstMiniObjectFreeFunction) _gst_query_free); + + GST_QUERY_TYPE (query) = type; + GST_QUERY_STRUCTURE (query) = structure; + + return GST_QUERY_CAST (query); + + /* ERRORS */ +had_parent: + { + g_slice_free1 (sizeof (GstQueryImpl), query); + g_warning ("structure is already owned by another object"); + return NULL; + } +} + +/** + * gst_query_get_structure: + * @query: a #GstQuery + * + * Get the structure of a query. + * + * Returns: (transfer none) (nullable): the #GstStructure of the query. The + * structure is still owned by the query and will therefore be freed when the + * query is unreffed. + */ +const GstStructure * +gst_query_get_structure (GstQuery * query) +{ + g_return_val_if_fail (GST_IS_QUERY (query), NULL); + + return GST_QUERY_STRUCTURE (query); +} + +/** + * gst_query_writable_structure: + * @query: a #GstQuery + * + * Get the structure of a query. This method should be called with a writable + * @query so that the returned structure is guaranteed to be writable. + * + * Returns: (transfer none): the #GstStructure of the query. The structure is + * still owned by the query and will therefore be freed when the query + * is unreffed. + */ +GstStructure * +gst_query_writable_structure (GstQuery * query) +{ + GstStructure *structure; + + g_return_val_if_fail (GST_IS_QUERY (query), NULL); + g_return_val_if_fail (gst_query_is_writable (query), NULL); + + structure = GST_QUERY_STRUCTURE (query); + + if (structure == NULL) { + structure = + gst_structure_new_id_empty (gst_query_type_to_quark (GST_QUERY_TYPE + (query))); + gst_structure_set_parent_refcount (structure, &query->mini_object.refcount); + GST_QUERY_STRUCTURE (query) = structure; + } + return structure; +} + +/** + * gst_query_new_seeking: + * @format: the default #GstFormat for the new query + * + * Constructs a new query object for querying seeking properties of + * the stream. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_seeking (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE, + GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1), + GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_SEEKING, structure); + + return query; +} + +/** + * gst_query_set_seeking: + * @query: a #GstQuery + * @format: the format to set for the @segment_start and @segment_end values + * @seekable: the seekable flag to set + * @segment_start: the segment_start to set + * @segment_end: the segment_end to set + * + * Set the seeking query result fields in @query. + */ +void +gst_query_set_seeking (GstQuery * query, GstFormat format, + gboolean seekable, gint64 segment_start, gint64 segment_end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable, + GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start, + GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL); +} + +/** + * gst_query_parse_seeking: + * @query: a GST_QUERY_SEEKING type query #GstQuery + * @format: (out) (allow-none): the format to set for the @segment_start + * and @segment_end values, or %NULL + * @seekable: (out) (allow-none): the seekable flag to set, or %NULL + * @segment_start: (out) (allow-none): the segment_start to set, or %NULL + * @segment_end: (out) (allow-none): the segment_end to set, or %NULL + * + * Parse a seeking query, writing the format into @format, and + * other results into the passed parameters, if the respective parameters + * are non-%NULL + */ +void +gst_query_parse_seeking (GstQuery * query, GstFormat * format, + gboolean * seekable, gint64 * segment_start, gint64 * segment_end) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING); + + structure = GST_QUERY_STRUCTURE (query); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (seekable) + *seekable = g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (SEEKABLE))); + if (segment_start) + *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (SEGMENT_START))); + if (segment_end) + *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (SEGMENT_END))); +} + +static GArray * +ensure_array (GstStructure * s, GQuark quark, gsize element_size, + GDestroyNotify clear_func) +{ + GArray *array; + const GValue *value; + + value = gst_structure_id_get_value (s, quark); + if (value) { + array = (GArray *) g_value_get_boxed (value); + } else { + GValue new_array_val = { 0, }; + + array = g_array_new (FALSE, TRUE, element_size); + if (clear_func) + g_array_set_clear_func (array, clear_func); + + g_value_init (&new_array_val, G_TYPE_ARRAY); + g_value_take_boxed (&new_array_val, array); + + gst_structure_id_take_value (s, quark, &new_array_val); + } + return array; +} + +/** + * gst_query_new_formats: + * + * Constructs a new query object for querying formats of + * the stream. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_formats (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS)); + query = gst_query_new_custom (GST_QUERY_FORMATS, structure); + + return query; +} + +static void +gst_query_list_add_format (GValue * list, GstFormat format) +{ + GValue item = { 0, }; + + g_value_init (&item, GST_TYPE_FORMAT); + g_value_set_enum (&item, format); + gst_value_list_append_value (list, &item); + g_value_unset (&item); +} + +/** + * gst_query_set_formats: + * @query: a #GstQuery + * @n_formats: the number of formats to set. + * @...: A number of @GstFormats equal to @n_formats. + * + * Set the formats query result fields in @query. The number of formats passed + * must be equal to @n_formats. + */ +void +gst_query_set_formats (GstQuery * query, gint n_formats, ...) +{ + va_list ap; + GValue list = { 0, }; + gint i; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + g_return_if_fail (gst_query_is_writable (query)); + + g_value_init (&list, GST_TYPE_LIST); + + va_start (ap, n_formats); + for (i = 0; i < n_formats; i++) { + gst_query_list_add_format (&list, va_arg (ap, GstFormat)); + } + va_end (ap); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_set_value (structure, "formats", &list); + + g_value_unset (&list); + +} + +/** + * gst_query_set_formatsv: + * @query: a #GstQuery + * @n_formats: the number of formats to set. + * @formats: (in) (array length=n_formats): an array containing @n_formats + * @GstFormat values. + * + * Set the formats query result fields in @query. The number of formats passed + * in the @formats array must be equal to @n_formats. + */ +void +gst_query_set_formatsv (GstQuery * query, gint n_formats, + const GstFormat * formats) +{ + GValue list = { 0, }; + gint i; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + g_return_if_fail (gst_query_is_writable (query)); + + g_value_init (&list, GST_TYPE_LIST); + for (i = 0; i < n_formats; i++) { + gst_query_list_add_format (&list, formats[i]); + } + structure = GST_QUERY_STRUCTURE (query); + gst_structure_set_value (structure, "formats", &list); + + g_value_unset (&list); +} + +/** + * gst_query_parse_n_formats: + * @query: a #GstQuery + * @n_formats: (out) (allow-none): the number of formats in this query. + * + * Parse the number of formats in the formats @query. + */ +void +gst_query_parse_n_formats (GstQuery * query, guint * n_formats) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + + if (n_formats) { + const GValue *list; + + structure = GST_QUERY_STRUCTURE (query); + list = gst_structure_get_value (structure, "formats"); + if (list == NULL) + *n_formats = 0; + else + *n_formats = gst_value_list_get_size (list); + } +} + +/** + * gst_query_parse_nth_format: + * @query: a #GstQuery + * @nth: the nth format to retrieve. + * @format: (out) (allow-none): a pointer to store the nth format + * + * Parse the format query and retrieve the @nth format from it into + * @format. If the list contains less elements than @nth, @format will be + * set to GST_FORMAT_UNDEFINED. + */ +void +gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + + if (format) { + const GValue *list; + + structure = GST_QUERY_STRUCTURE (query); + list = gst_structure_get_value (structure, "formats"); + if (list == NULL) { + *format = GST_FORMAT_UNDEFINED; + } else { + if (nth < gst_value_list_get_size (list)) { + *format = + (GstFormat) g_value_get_enum (gst_value_list_get_value (list, nth)); + } else + *format = GST_FORMAT_UNDEFINED; + } + } +} + +/** + * gst_query_new_buffering: + * @format: the default #GstFormat for the new query + * + * Constructs a new query object for querying the buffering status of + * a stream. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_buffering (GstFormat format) +{ + GstQuery *query; + GstStructure *structure; + + /* by default, we configure the answer as no buffering with a 100% buffering + * progress */ + structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING), + GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE, + GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100, + GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM, + GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1, + GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1, + GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0), + GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1), + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), + GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL); + + query = gst_query_new_custom (GST_QUERY_BUFFERING, structure); + + return query; +} + +/** + * gst_query_set_buffering_percent: + * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. + * @busy: if buffering is busy + * @percent: a buffering percent + * + * Set the percentage of buffered data. This is a value between 0 and 100. + * The @busy indicator is %TRUE when the buffering is in progress. + */ +void +gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (percent >= 0 && percent <= 100); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, + GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL); +} + +/** + * gst_query_parse_buffering_percent: + * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. + * @busy: (out) (allow-none): if buffering is busy, or %NULL + * @percent: (out) (allow-none): a buffering percent, or %NULL + * + * Get the percentage of buffered data. This is a value between 0 and 100. + * The @busy indicator is %TRUE when the buffering is in progress. + */ +void +gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy, + gint * percent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + + structure = GST_QUERY_STRUCTURE (query); + if (busy) + *busy = g_value_get_boolean (gst_structure_id_get_value (structure, + GST_QUARK (BUSY))); + if (percent) + *percent = g_value_get_int (gst_structure_id_get_value (structure, + GST_QUARK (BUFFER_PERCENT))); +} + +/** + * gst_query_set_buffering_stats: + * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. + * @mode: a buffering mode + * @avg_in: the average input rate + * @avg_out: the average output rate + * @buffering_left: amount of buffering time left in milliseconds + * + * Configures the buffering stats values in @query. + */ +void +gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode, + gint avg_in, gint avg_out, gint64 buffering_left) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode, + GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in, + GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out, + GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL); +} + +/** + * gst_query_parse_buffering_stats: + * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. + * @mode: (out) (allow-none): a buffering mode, or %NULL + * @avg_in: (out) (allow-none): the average input rate, or %NULL + * @avg_out: (out) (allow-none): the average output rat, or %NULL + * @buffering_left: (out) (allow-none): amount of buffering time left in + * milliseconds, or %NULL + * + * Extracts the buffering stats values from @query. + */ +void +gst_query_parse_buffering_stats (GstQuery * query, + GstBufferingMode * mode, gint * avg_in, gint * avg_out, + gint64 * buffering_left) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + + structure = GST_QUERY_STRUCTURE (query); + if (mode) + *mode = (GstBufferingMode) + g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (BUFFERING_MODE))); + if (avg_in) + *avg_in = g_value_get_int (gst_structure_id_get_value (structure, + GST_QUARK (AVG_IN_RATE))); + if (avg_out) + *avg_out = g_value_get_int (gst_structure_id_get_value (structure, + GST_QUARK (AVG_OUT_RATE))); + if (buffering_left) + *buffering_left = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (BUFFERING_LEFT))); +} + +/** + * gst_query_set_buffering_range: + * @query: a #GstQuery + * @format: the format to set for the @start and @stop values + * @start: the start to set + * @stop: the stop to set + * @estimated_total: estimated total amount of download time remaining in + * milliseconds + * + * Set the available query result fields in @query. + */ +void +gst_query_set_buffering_range (GstQuery * query, GstFormat format, + gint64 start, gint64 stop, gint64 estimated_total) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (FORMAT), GST_TYPE_FORMAT, format, + GST_QUARK (START_VALUE), G_TYPE_INT64, start, + GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop, + GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL); +} + +/** + * gst_query_parse_buffering_range: + * @query: a GST_QUERY_BUFFERING type query #GstQuery + * @format: (out) (allow-none): the format to set for the @segment_start + * and @segment_end values, or %NULL + * @start: (out) (allow-none): the start to set, or %NULL + * @stop: (out) (allow-none): the stop to set, or %NULL + * @estimated_total: (out) (allow-none): estimated total amount of download + * time remaining in milliseconds, or %NULL + * + * Parse an available query, writing the format into @format, and + * other results into the passed parameters, if the respective parameters + * are non-%NULL + */ +void +gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, + gint64 * start, gint64 * stop, gint64 * estimated_total) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + + structure = GST_QUERY_STRUCTURE (query); + if (format) + *format = + (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure, + GST_QUARK (FORMAT))); + if (start) + *start = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (START_VALUE))); + if (stop) + *stop = g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (STOP_VALUE))); + if (estimated_total) + *estimated_total = + g_value_get_int64 (gst_structure_id_get_value (structure, + GST_QUARK (ESTIMATED_TOTAL))); +} + +/* GstQueryBufferingRange: internal struct for GArray */ +typedef struct +{ + gint64 start; + gint64 stop; +} GstQueryBufferingRange; + +/** + * gst_query_add_buffering_range: + * @query: a GST_QUERY_BUFFERING type query #GstQuery + * @start: start position of the range + * @stop: stop position of the range + * + * Set the buffering-ranges array field in @query. The current last + * start position of the array should be inferior to @start. + * + * Returns: a #gboolean indicating if the range was added or not. + */ +gboolean +gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop) +{ + GstQueryBufferingRange range; + GstStructure *structure; + GArray *array; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE); + g_return_val_if_fail (gst_query_is_writable (query), FALSE); + + if (G_UNLIKELY (start >= stop)) + return FALSE; + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); + + if (array->len > 1) { + GstQueryBufferingRange *last; + + last = &g_array_index (array, GstQueryBufferingRange, array->len - 1); + + if (G_UNLIKELY (start <= last->start)) + return FALSE; + } + + range.start = start; + range.stop = stop; + g_array_append_val (array, range); + + return TRUE; +} + +/** + * gst_query_get_n_buffering_ranges: + * @query: a GST_QUERY_BUFFERING type query #GstQuery + * + * Retrieve the number of values currently stored in the + * buffered-ranges array of the query's structure. + * + * Returns: the range array size as a #guint. + */ +guint +gst_query_get_n_buffering_ranges (GstQuery * query) +{ + GstStructure *structure; + GArray *array; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); + + return array->len; +} + + +/** + * gst_query_parse_nth_buffering_range: + * @query: a GST_QUERY_BUFFERING type query #GstQuery + * @index: position in the buffered-ranges array to read + * @start: (out) (allow-none): the start position to set, or %NULL + * @stop: (out) (allow-none): the stop position to set, or %NULL + * + * Parse an available query and get the start and stop values stored + * at the @index of the buffered ranges array. + * + * Returns: a #gboolean indicating if the parsing succeeded. + */ +gboolean +gst_query_parse_nth_buffering_range (GstQuery * query, guint index, + gint64 * start, gint64 * stop) +{ + GstQueryBufferingRange *range; + GstStructure *structure; + GArray *array; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + + array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES), + sizeof (GstQueryBufferingRange), NULL); + g_return_val_if_fail (index < array->len, FALSE); + + range = &g_array_index (array, GstQueryBufferingRange, index); + + if (start) + *start = range->start; + if (stop) + *stop = range->stop; + + return TRUE; +} + + +/** + * gst_query_new_uri: + * + * Constructs a new query URI query object. Use gst_query_unref() + * when done with it. An URI query is used to query the current URI + * that is used by the source or sink. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_uri (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_URI), + GST_QUARK (URI), G_TYPE_STRING, NULL, NULL); + + query = gst_query_new_custom (GST_QUERY_URI, structure); + + return query; +} + +/** + * gst_query_set_uri: + * @query: a #GstQuery with query type GST_QUERY_URI + * @uri: the URI to set + * + * Answer a URI query by setting the requested URI. + */ +void +gst_query_set_uri (GstQuery * query, const gchar * uri) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (gst_uri_is_valid (uri)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL); +} + +/** + * gst_query_parse_uri: + * @query: a #GstQuery + * @uri: (out) (transfer full) (allow-none): the storage for the current URI + * (may be %NULL) + * + * Parse an URI query, writing the URI into @uri as a newly + * allocated string, if the respective parameters are non-%NULL. + * Free the string with g_free() after usage. + */ +void +gst_query_parse_uri (GstQuery * query, gchar ** uri) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + + structure = GST_QUERY_STRUCTURE (query); + if (uri) + *uri = g_value_dup_string (gst_structure_id_get_value (structure, + GST_QUARK (URI))); +} + +/** + * gst_query_set_uri_redirection: + * @query: a #GstQuery with query type GST_QUERY_URI + * @uri: the URI to set + * + * Answer a URI query by setting the requested URI redirection. + * + * Since: 1.2 + */ +void +gst_query_set_uri_redirection (GstQuery * query, const gchar * uri) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (gst_uri_is_valid (uri)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION), + G_TYPE_STRING, uri, NULL); +} + +/** + * gst_query_parse_uri_redirection: + * @query: a #GstQuery + * @uri: (out) (transfer full) (allow-none): the storage for the redirect URI + * (may be %NULL) + * + * Parse an URI query, writing the URI into @uri as a newly + * allocated string, if the respective parameters are non-%NULL. + * Free the string with g_free() after usage. + * + * Since: 1.2 + */ +void +gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + + structure = GST_QUERY_STRUCTURE (query); + if (uri) { + if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION), + G_TYPE_STRING, uri, NULL)) + *uri = NULL; + } +} + +/** + * gst_query_set_uri_redirection_permanent: + * @query: a #GstQuery with query type %GST_QUERY_URI + * @permanent: whether the redirect is permanent or not + * + * Answer a URI query by setting the requested URI redirection + * to permanent or not. + * + * Since: 1.4 + */ +void +gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL); +} + +/** + * gst_query_parse_uri_redirection_permanent: + * @query: a #GstQuery + * @permanent: (out) (allow-none): if the URI redirection is permanent + * (may be %NULL) + * + * Parse an URI query, and set @permanent to %TRUE if there is a redirection + * and it should be considered permanent. If a redirection is permanent, + * applications should update their internal storage of the URI, otherwise + * they should make all future requests to the original URI. + * + * Since: 1.4 + */ +void +gst_query_parse_uri_redirection_permanent (GstQuery * query, + gboolean * permanent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + + structure = GST_QUERY_STRUCTURE (query); + if (permanent) { + if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL)) + *permanent = FALSE; + } +} + +/** + * gst_query_new_allocation: + * @caps: the negotiated caps + * @need_pool: return a pool + * + * Constructs a new query object for querying the allocation properties. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_allocation (GstCaps * caps, gboolean need_pool) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION), + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, + GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL); + + query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure); + + return query; +} + +/** + * gst_query_parse_allocation: + * @query: a #GstQuery + * @caps: (out) (transfer none) (allow-none): The #GstCaps + * @need_pool: (out) (allow-none): Whether a #GstBufferPool is needed + * + * Parse an allocation query, writing the requested caps in @caps and + * whether a pool is needed in @need_pool, if the respective parameters + * are non-%NULL. + * + * Pool details can be retrieved using gst_query_get_n_allocation_pools() and + * gst_query_parse_nth_allocation_pool(). + */ +void +gst_query_parse_allocation (GstQuery * query, GstCaps ** caps, + gboolean * need_pool) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + if (caps) { + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); + } + gst_structure_id_get (structure, + GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL); +} + +typedef struct +{ + GstBufferPool *pool; + guint size; + guint min_buffers; + guint max_buffers; +} AllocationPool; + +static void +allocation_pool_free (AllocationPool * ap) +{ + if (ap->pool) + gst_object_unref (ap->pool); +} + +/** + * gst_query_add_allocation_pool: + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @pool: (transfer none) (allow-none): the #GstBufferPool + * @size: the buffer size + * @min_buffers: the min buffers + * @max_buffers: the max buffers + * + * Set the pool parameters in @query. + */ +void +gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool, + guint size, guint min_buffers, guint max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + + if ((ap.pool = pool)) + gst_object_ref (pool); + ap.size = size; + ap.min_buffers = min_buffers; + ap.max_buffers = max_buffers; + + g_array_append_val (array, ap); +} + +/** + * gst_query_get_n_allocation_pools: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * pool array of the query's structure. + * + * Returns: the pool array size as a #guint. + */ +guint +gst_query_get_n_allocation_pools (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_pool: + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @index: index to parse + * @pool: (out) (allow-none) (transfer full): the #GstBufferPool + * @size: (out) (allow-none): the buffer size + * @min_buffers: (out) (allow-none): the min buffers + * @max_buffers: (out) (allow-none): the max buffers + * + * Get the pool parameters in @query. + * + * Unref @pool with gst_object_unref() when it's not needed any more. + */ +void +gst_query_parse_nth_allocation_pool (GstQuery * query, guint index, + GstBufferPool ** pool, guint * size, guint * min_buffers, + guint * max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool *ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + ap = &g_array_index (array, AllocationPool, index); + + if (pool) + if ((*pool = ap->pool)) + gst_object_ref (*pool); + if (size) + *size = ap->size; + if (min_buffers) + *min_buffers = ap->min_buffers; + if (max_buffers) + *max_buffers = ap->max_buffers; +} + +/** + * gst_query_set_nth_allocation_pool: + * @index: index to modify + * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION. + * @pool: (transfer none) (allow-none): the #GstBufferPool + * @size: the buffer size + * @min_buffers: the min buffers + * @max_buffers: the max buffers + * + * Set the pool parameters in @query. + */ +void +gst_query_set_nth_allocation_pool (GstQuery * query, guint index, + GstBufferPool * pool, guint size, guint min_buffers, guint max_buffers) +{ + GArray *array; + GstStructure *structure; + AllocationPool *oldap, ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (POOL), + sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + oldap = &g_array_index (array, AllocationPool, index); + allocation_pool_free (oldap); + + if ((ap.pool = pool)) + gst_object_ref (pool); + ap.size = size; + ap.min_buffers = min_buffers; + ap.max_buffers = max_buffers; + g_array_index (array, AllocationPool, index) = ap; +} + +/** + * gst_query_remove_nth_allocation_pool: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocation pool array to remove + * + * Remove the allocation pool at @index of the allocation pool array. + * + * Since: 1.2 + */ +void +gst_query_remove_nth_allocation_pool (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (POOL), sizeof (AllocationPool), + (GDestroyNotify) allocation_pool_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +typedef struct +{ + GType api; + GstStructure *params; +} AllocationMeta; + +static void +allocation_meta_free (AllocationMeta * am) +{ + if (am->params) + gst_structure_free (am->params); +} + +/** + * gst_query_add_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @api: the metadata API + * @params: (transfer none) (allow-none): API specific parameters + * + * Add @api with @params as one of the supported metadata API to @query. + */ +void +gst_query_add_allocation_meta (GstQuery * query, GType api, + const GstStructure * params) +{ + GArray *array; + GstStructure *structure; + AllocationMeta am; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (api != 0); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + am.api = api; + am.params = (params ? gst_structure_copy (params) : NULL); + + g_array_append_val (array, am); +} + +/** + * gst_query_get_n_allocation_metas: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * meta API array of the query's structure. + * + * Returns: the metadata API array size as a #guint. + */ +guint +gst_query_get_n_allocation_metas (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the metadata API array to read + * @params: (out) (transfer none) (allow-none): API specific parameters + * + * Parse an available query and get the metadata API + * at @index of the metadata API array. + * + * Returns: a #GType of the metadata API at @index. + */ +GType +gst_query_parse_nth_allocation_meta (GstQuery * query, guint index, + const GstStructure ** params) +{ + GArray *array; + GstStructure *structure; + AllocationMeta *am; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + g_return_val_if_fail (index < array->len, 0); + + am = &g_array_index (array, AllocationMeta, index); + + if (params) + *params = am->params; + + return am->api; +} + +/** + * gst_query_remove_nth_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the metadata API array to remove + * + * Remove the metadata API at @index of the metadata API array. + */ +void +gst_query_remove_nth_allocation_meta (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +/** + * gst_query_find_allocation_meta: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @api: the metadata API + * @index: (out) (transfer none) (allow-none): the index + * + * Check if @query has metadata @api set. When this function returns %TRUE, + * @index will contain the index where the requested API and the parameters + * can be found. + * + * Returns: %TRUE when @api is in the list of metadata. + */ +gboolean +gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index) +{ + GArray *array; + GstStructure *structure; + guint i, len; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE); + g_return_val_if_fail (api != 0, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta), + (GDestroyNotify) allocation_meta_free); + + len = array->len; + for (i = 0; i < len; i++) { + AllocationMeta *am = &g_array_index (array, AllocationMeta, i); + if (am->api == api) { + if (index) + *index = i; + return TRUE; + } + } + return FALSE; +} + +typedef struct +{ + GstAllocator *allocator; + GstAllocationParams params; +} AllocationParam; + +static void +allocation_param_free (AllocationParam * ap) +{ + if (ap->allocator) + gst_object_unref (ap->allocator); +} + +/** + * gst_query_add_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @allocator: (transfer none) (allow-none): the memory allocator + * @params: (transfer none) (allow-none): a #GstAllocationParams + * + * Add @allocator and its @params as a supported memory allocator. + */ +void +gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator, + const GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + g_return_if_fail (allocator != NULL || params != NULL); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + + if ((ap.allocator = allocator)) + gst_object_ref (allocator); + if (params) + ap.params = *params; + else + gst_allocation_params_init (&ap.params); + + g_array_append_val (array, ap); +} + +/** + * gst_query_get_n_allocation_params: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * + * Retrieve the number of values currently stored in the + * allocator params array of the query's structure. + * + * If no memory allocator is specified, the downstream element can handle + * the default memory allocator. The first memory allocator in the query + * should be generic and allow mapping to system memory, all following + * allocators should be ordered by preference with the preferred one first. + * + * Returns: the allocator array size as a #guint. + */ +guint +gst_query_get_n_allocation_params (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + + return array->len; +} + +/** + * gst_query_parse_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocator array to read + * @allocator: (out) (transfer full) (allow-none): variable to hold the result + * @params: (out) (allow-none): parameters for the allocator + * + * Parse an available query and get the allocator and its params + * at @index of the allocator array. + */ +void +gst_query_parse_nth_allocation_param (GstQuery * query, guint index, + GstAllocator ** allocator, GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam *ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + ap = &g_array_index (array, AllocationParam, index); + + if (allocator) + if ((*allocator = ap->allocator)) + gst_object_ref (*allocator); + if (params) + *params = ap->params; +} + +/** + * gst_query_set_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocator array to set + * @allocator: (transfer none) (allow-none): new allocator to set + * @params: (transfer none) (allow-none): parameters for the allocator + * + * Parse an available query and get the allocator and its params + * at @index of the allocator array. + */ +void +gst_query_set_nth_allocation_param (GstQuery * query, guint index, + GstAllocator * allocator, const GstAllocationParams * params) +{ + GArray *array; + GstStructure *structure; + AllocationParam *old, ap; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + + structure = GST_QUERY_STRUCTURE (query); + array = ensure_array (structure, GST_QUARK (ALLOCATOR), + sizeof (AllocationParam), (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + old = &g_array_index (array, AllocationParam, index); + allocation_param_free (old); + + if ((ap.allocator = allocator)) + gst_object_ref (allocator); + if (params) + ap.params = *params; + else + gst_allocation_params_init (&ap.params); + + g_array_index (array, AllocationParam, index) = ap; +} + +/** + * gst_query_remove_nth_allocation_param: + * @query: a GST_QUERY_ALLOCATION type query #GstQuery + * @index: position in the allocation param array to remove + * + * Remove the allocation param at @index of the allocation param array. + * + * Since: 1.2 + */ +void +gst_query_remove_nth_allocation_param (GstQuery * query, guint index) +{ + GArray *array; + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (AllocationParam), + (GDestroyNotify) allocation_param_free); + g_return_if_fail (index < array->len); + + g_array_remove_index (array, index); +} + +/** + * gst_query_new_scheduling: + * + * Constructs a new query object for querying the scheduling properties. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_scheduling (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING), + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0, + GST_QUARK (MINSIZE), G_TYPE_INT, 1, + GST_QUARK (MAXSIZE), G_TYPE_INT, -1, + GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL); + query = gst_query_new_custom (GST_QUERY_SCHEDULING, structure); + + return query; +} + +/** + * gst_query_set_scheduling: + * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING. + * @flags: #GstSchedulingFlags + * @minsize: the suggested minimum size of pull requests + * @maxsize: the suggested maximum size of pull requests + * @align: the suggested alignment of pull requests + * + * Set the scheduling properties. + */ +void +gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags, + gint minsize, gint maxsize, gint align) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags, + GST_QUARK (MINSIZE), G_TYPE_INT, minsize, + GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize, + GST_QUARK (ALIGN), G_TYPE_INT, align, NULL); +} + +/** + * gst_query_parse_scheduling: + * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING. + * @flags: (out) (allow-none): #GstSchedulingFlags + * @minsize: (out) (allow-none): the suggested minimum size of pull requests + * @maxsize: (out) (allow-none): the suggested maximum size of pull requests: + * @align: (out) (allow-none): the suggested alignment of pull requests + * + * Set the scheduling properties. + */ +void +gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags, + gint * minsize, gint * maxsize, gint * align) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_get (structure, + GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags, + GST_QUARK (MINSIZE), G_TYPE_INT, minsize, + GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize, + GST_QUARK (ALIGN), G_TYPE_INT, align, NULL); +} + +/** + * gst_query_add_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: a #GstPadMode + * + * Add @mode as one of the supported scheduling modes to @query. + */ +void +gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode) +{ + GstStructure *structure; + GArray *array; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + g_array_append_val (array, mode); +} + +/** + * gst_query_get_n_scheduling_modes: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * + * Retrieve the number of values currently stored in the + * scheduling mode array of the query's structure. + * + * Returns: the scheduling mode array size as a #guint. + */ +guint +gst_query_get_n_scheduling_modes (GstQuery * query) +{ + GArray *array; + GstStructure *structure; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + return array->len; +} + +/** + * gst_query_parse_nth_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @index: position in the scheduling modes array to read + * + * Parse an available query and get the scheduling mode + * at @index of the scheduling modes array. + * + * Returns: a #GstPadMode of the scheduling mode at @index. + */ +GstPadMode +gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index) +{ + GstStructure *structure; + GArray *array; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, + GST_PAD_MODE_NONE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + g_return_val_if_fail (index < array->len, GST_PAD_MODE_NONE); + + return g_array_index (array, GstPadMode, index); +} + +/** + * gst_query_has_scheduling_mode: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: the scheduling mode + * + * Check if @query has scheduling mode set. + * + * > When checking if upstream supports pull mode, it is usually not + * > enough to just check for GST_PAD_MODE_PULL with this function, you + * > also want to check whether the scheduling flags returned by + * > gst_query_parse_scheduling() have the seeking flag set (meaning + * > random access is supported, not only sequential pulls). + * + * Returns: %TRUE when @mode is in the list of scheduling modes. + */ +gboolean +gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode) +{ + GstStructure *structure; + GArray *array; + guint i, len; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + array = + ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL); + + len = array->len; + for (i = 0; i < len; i++) { + if (mode == g_array_index (array, GstPadMode, i)) + return TRUE; + } + return FALSE; +} + +/** + * gst_query_has_scheduling_mode_with_flags: + * @query: a GST_QUERY_SCHEDULING type query #GstQuery + * @mode: the scheduling mode + * @flags: #GstSchedulingFlags + * + * Check if @query has scheduling mode set and @flags is set in + * query scheduling flags. + * + * Returns: %TRUE when @mode is in the list of scheduling modes + * and @flags are compatible with query flags. + */ +gboolean +gst_query_has_scheduling_mode_with_flags (GstQuery * query, GstPadMode mode, + GstSchedulingFlags flags) +{ + GstSchedulingFlags sched_flags; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE); + + gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL); + + return ((flags & sched_flags) == flags) && + gst_query_has_scheduling_mode (query, mode); +} + +/** + * gst_query_new_accept_caps: + * @caps: a fixed #GstCaps + * + * Constructs a new query object for querying if @caps are accepted. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_accept_caps (GstCaps * caps) +{ + GstQuery *query; + GstStructure *structure; + + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + + structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS), + GST_QUARK (CAPS), GST_TYPE_CAPS, caps, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL); + query = gst_query_new_custom (GST_QUERY_ACCEPT_CAPS, structure); + + return query; +} + +/** + * gst_query_parse_accept_caps: + * @query: The query to parse + * @caps: (out) (transfer none): A pointer to the caps + * + * Get the caps from @query. The caps remains valid as long as @query remains + * valid. + */ +void +gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); + g_return_if_fail (caps != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); +} + +/** + * gst_query_set_accept_caps_result: + * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery + * @result: the result to set + * + * Set @result as the result for the @query. + */ +void +gst_query_set_accept_caps_result (GstQuery * query, gboolean result) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL); +} + +/** + * gst_query_parse_accept_caps_result: + * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery + * @result: (out) (allow-none): location for the result + * + * Parse the result from @query and store in @result. + */ +void +gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_get (structure, + GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL); +} + +/** + * gst_query_new_caps: + * @filter: a filter + * + * Constructs a new query object for querying the caps. + * + * The CAPS query should return the allowable caps for a pad in the context + * of the element's state, its link to other elements, and the devices or files + * it has opened. These caps must be a subset of the pad template caps. In the + * NULL state with no links, the CAPS query should ideally return the same caps + * as the pad template. In rare circumstances, an object property can affect + * the caps returned by the CAPS query, but this is discouraged. + * + * For most filters, the caps returned by CAPS query is directly affected by the + * allowed caps on other pads. For demuxers and decoders, the caps returned by + * the srcpad's getcaps function is directly related to the stream data. Again, + * the CAPS query should return the most specific caps it reasonably can, since this + * helps with autoplugging. + * + * The @filter is used to restrict the result caps, only the caps matching + * @filter should be returned from the CAPS query. Specifying a filter might + * greatly reduce the amount of processing an element needs to do. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_caps (GstCaps * filter) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS), + GST_QUARK (FILTER), GST_TYPE_CAPS, filter, + GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL); + query = gst_query_new_custom (GST_QUERY_CAPS, structure); + + return query; +} + +/** + * gst_query_parse_caps: + * @query: The query to parse + * @filter: (out) (transfer none): A pointer to the caps filter + * + * Get the filter from the caps @query. The caps remains valid as long as + * @query remains valid. + */ +void +gst_query_parse_caps (GstQuery * query, GstCaps ** filter) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (filter != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *filter = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (FILTER))); +} + +/** + * gst_query_set_caps_result: + * @query: The query to use + * @caps: (in): A pointer to the caps + * + * Set the @caps result in @query. + */ +void +gst_query_set_caps_result (GstQuery * query, GstCaps * caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL); +} + +/** + * gst_query_parse_caps_result: + * @query: The query to parse + * @caps: (out) (transfer none): A pointer to the caps + * + * Get the caps result from @query. The caps remains valid as long as + * @query remains valid. + */ +void +gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS); + g_return_if_fail (caps != NULL); + + structure = GST_QUERY_STRUCTURE (query); + *caps = g_value_get_boxed (gst_structure_id_get_value (structure, + GST_QUARK (CAPS))); +} + +#if 0 +void +gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter, + GstCapsIntersectMode mode) +{ + GstCaps *res, *caps = NULL; + + gst_query_parse_caps_result (query, &caps); + res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_query_set_caps_result (query, res); + gst_caps_unref (res); +} +#endif + +/** + * gst_query_new_drain: + * + * Constructs a new query object for querying the drain state. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + */ +GstQuery * +gst_query_new_drain (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new_id_empty (GST_QUARK (QUERY_DRAIN)); + query = gst_query_new_custom (GST_QUERY_DRAIN, structure); + + return query; +} + +/** + * gst_query_new_context: + * @context_type: Context type to query + * + * Constructs a new query object for querying the pipeline-local context. + * + * Free-function: gst_query_unref() + * + * Returns: (transfer full): a new #GstQuery + * + * Since: 1.2 + */ +GstQuery * +gst_query_new_context (const gchar * context_type) +{ + GstQuery *query; + GstStructure *structure; + + g_return_val_if_fail (context_type != NULL, NULL); + + structure = gst_structure_new_id (GST_QUARK (QUERY_CONTEXT), + GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL); + query = gst_query_new_custom (GST_QUERY_CONTEXT, structure); + + return query; +} + +/** + * gst_query_set_context: + * @query: a #GstQuery with query type GST_QUERY_CONTEXT + * @context: the requested #GstContext + * + * Answer a context query by setting the requested context. + * + * Since: 1.2 + */ +void +gst_query_set_context (GstQuery * query, GstContext * context) +{ + GstStructure *s; + const gchar *context_type; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT); + + gst_query_parse_context_type (query, &context_type); + g_return_if_fail (strcmp (gst_context_get_context_type (context), + context_type) == 0); + + s = GST_QUERY_STRUCTURE (query); + + gst_structure_id_set (s, + GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL); +} + +/** + * gst_query_parse_context: + * @query: The query to parse + * @context: (out) (transfer none): A pointer to store the #GstContext + * + * Get the context from the context @query. The context remains valid as long as + * @query remains valid. + * + * Since: 1.2 + */ +void +gst_query_parse_context (GstQuery * query, GstContext ** context) +{ + GstStructure *structure; + const GValue *v; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT); + g_return_if_fail (context != NULL); + + structure = GST_QUERY_STRUCTURE (query); + v = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT)); + if (v) + *context = g_value_get_boxed (v); + else + *context = NULL; +} + +/** + * gst_query_parse_context_type: + * @query: a GST_QUERY_CONTEXT type query + * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL + * + * Parse a context type from an existing GST_QUERY_CONTEXT query. + * + * Returns: a #gboolean indicating if the parsing succeeded. + * + * Since: 1.2 + */ +gboolean +gst_query_parse_context_type (GstQuery * query, const gchar ** context_type) +{ + GstStructure *structure; + const GValue *value; + + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE); + + structure = GST_QUERY_STRUCTURE (query); + + if (context_type) { + value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE)); + *context_type = g_value_get_string (value); + } + + return TRUE; +} diff --git a/gst/gstquery.h b/gst/gstquery.h new file mode 100644 index 0000000..d2b0388 --- /dev/null +++ b/gst/gstquery.h @@ -0,0 +1,653 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * 2011 Wim Taymans + * + * gstquery.h: GstQuery API declaration + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_QUERY_H__ +#define __GST_QUERY_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstQuery GstQuery; + +#include + +/** + * GstQueryTypeFlags: + * @GST_QUERY_TYPE_UPSTREAM: Set if the query can travel upstream. + * @GST_QUERY_TYPE_DOWNSTREAM: Set if the query can travel downstream. + * @GST_QUERY_TYPE_SERIALIZED: Set if the query should be serialized with data + * flow. + * + * #GstQueryTypeFlags indicate the aspects of the different #GstQueryType + * values. You can get the type flags of a #GstQueryType with the + * gst_query_type_get_flags() function. + */ +typedef enum { + GST_QUERY_TYPE_UPSTREAM = 1 << 0, + GST_QUERY_TYPE_DOWNSTREAM = 1 << 1, + GST_QUERY_TYPE_SERIALIZED = 1 << 2 +} GstQueryTypeFlags; + +/** + * GST_QUERY_TYPE_BOTH: (value 3) (type GstQueryTypeFlags) + * + * The same thing as #GST_QUERY_TYPE_UPSTREAM | #GST_QUERY_TYPE_DOWNSTREAM. + */ +#define GST_QUERY_TYPE_BOTH \ + ((GstQueryTypeFlags)(GST_QUERY_TYPE_UPSTREAM | GST_QUERY_TYPE_DOWNSTREAM)) + +#define GST_QUERY_NUM_SHIFT (8) + +/** + * GST_QUERY_MAKE_TYPE: + * @num: the query number to create + * @flags: the query flags + * + * when making custom query types, use this macro with the num and + * the given flags + */ +#define GST_QUERY_MAKE_TYPE(num,flags) \ + (((num) << GST_QUERY_NUM_SHIFT) | (flags)) + +#define FLAG(name) GST_QUERY_TYPE_##name + + +/** + * GstQueryType: + * @GST_QUERY_UNKNOWN: unknown query type + * @GST_QUERY_POSITION: current position in stream + * @GST_QUERY_DURATION: total duration of the stream + * @GST_QUERY_LATENCY: latency of stream + * @GST_QUERY_JITTER: current jitter of stream + * @GST_QUERY_RATE: current rate of the stream + * @GST_QUERY_SEEKING: seeking capabilities + * @GST_QUERY_SEGMENT: segment start/stop positions + * @GST_QUERY_CONVERT: convert values between formats + * @GST_QUERY_FORMATS: query supported formats for convert + * @GST_QUERY_BUFFERING: query available media for efficient seeking. + * @GST_QUERY_CUSTOM: a custom application or element defined query. + * @GST_QUERY_URI: query the URI of the source or sink. + * @GST_QUERY_ALLOCATION: the buffer allocation properties + * @GST_QUERY_SCHEDULING: the scheduling properties + * @GST_QUERY_ACCEPT_CAPS: the accept caps query + * @GST_QUERY_CAPS: the caps query + * @GST_QUERY_DRAIN: wait till all serialized data is consumed downstream + * @GST_QUERY_CONTEXT: query the pipeline-local context from + * downstream or upstream (since 1.2) + * + * Standard predefined Query types + */ +/* NOTE: don't forget to update the table in gstquery.c when changing + * this enum */ +typedef enum { + GST_QUERY_UNKNOWN = GST_QUERY_MAKE_TYPE (0, 0), + GST_QUERY_POSITION = GST_QUERY_MAKE_TYPE (10, FLAG(BOTH)), + GST_QUERY_DURATION = GST_QUERY_MAKE_TYPE (20, FLAG(BOTH)), + GST_QUERY_LATENCY = GST_QUERY_MAKE_TYPE (30, FLAG(BOTH)), + GST_QUERY_JITTER = GST_QUERY_MAKE_TYPE (40, FLAG(BOTH)), + GST_QUERY_RATE = GST_QUERY_MAKE_TYPE (50, FLAG(BOTH)), + GST_QUERY_SEEKING = GST_QUERY_MAKE_TYPE (60, FLAG(BOTH)), + GST_QUERY_SEGMENT = GST_QUERY_MAKE_TYPE (70, FLAG(BOTH)), + GST_QUERY_CONVERT = GST_QUERY_MAKE_TYPE (80, FLAG(BOTH)), + GST_QUERY_FORMATS = GST_QUERY_MAKE_TYPE (90, FLAG(BOTH)), + GST_QUERY_BUFFERING = GST_QUERY_MAKE_TYPE (110, FLAG(BOTH)), + GST_QUERY_CUSTOM = GST_QUERY_MAKE_TYPE (120, FLAG(BOTH)), + GST_QUERY_URI = GST_QUERY_MAKE_TYPE (130, FLAG(BOTH)), + GST_QUERY_ALLOCATION = GST_QUERY_MAKE_TYPE (140, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), + GST_QUERY_SCHEDULING = GST_QUERY_MAKE_TYPE (150, FLAG(UPSTREAM)), + GST_QUERY_ACCEPT_CAPS = GST_QUERY_MAKE_TYPE (160, FLAG(BOTH)), + GST_QUERY_CAPS = GST_QUERY_MAKE_TYPE (170, FLAG(BOTH)), + GST_QUERY_DRAIN = GST_QUERY_MAKE_TYPE (180, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), + GST_QUERY_CONTEXT = GST_QUERY_MAKE_TYPE (190, FLAG(BOTH)) +} GstQueryType; +#undef FLAG + +GST_API GType _gst_query_type; + +#define GST_TYPE_QUERY (_gst_query_type) +#define GST_IS_QUERY(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_QUERY)) +#define GST_QUERY_CAST(obj) ((GstQuery*)(obj)) +#define GST_QUERY(obj) (GST_QUERY_CAST(obj)) + +/** + * GST_QUERY_TYPE: + * @query: the query to query + * + * Get the #GstQueryType of the query. + */ +#define GST_QUERY_TYPE(query) (((GstQuery*)(query))->type) + +/** + * GST_QUERY_TYPE_NAME: + * @query: the query to query + * + * Get a constant string representation of the #GstQueryType of the query. + */ +#define GST_QUERY_TYPE_NAME(query) (gst_query_type_get_name(GST_QUERY_TYPE(query))) + +/** + * GST_QUERY_IS_UPSTREAM: + * @ev: the query to query + * + * Check if an query can travel upstream. + */ +#define GST_QUERY_IS_UPSTREAM(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_UPSTREAM) +/** + * GST_QUERY_IS_DOWNSTREAM: + * @ev: the query to query + * + * Check if an query can travel downstream. + */ +#define GST_QUERY_IS_DOWNSTREAM(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_DOWNSTREAM) +/** + * GST_QUERY_IS_SERIALIZED: + * @ev: the query to query + * + * Check if an query is serialized with the data stream. + */ +#define GST_QUERY_IS_SERIALIZED(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_SERIALIZED) + + +/** + * GstQuery: + * @mini_object: The parent #GstMiniObject type + * @type: the #GstQueryType + * + * The #GstQuery structure. + */ +struct _GstQuery +{ + GstMiniObject mini_object; + + /*< public > *//* with COW */ + GstQueryType type; +}; + +/** + * GstBufferingMode: + * @GST_BUFFERING_STREAM: a small amount of data is buffered + * @GST_BUFFERING_DOWNLOAD: the stream is being downloaded + * @GST_BUFFERING_TIMESHIFT: the stream is being downloaded in a ringbuffer + * @GST_BUFFERING_LIVE: the stream is a live stream + * + * The different types of buffering methods. + */ +typedef enum { + GST_BUFFERING_STREAM, + GST_BUFFERING_DOWNLOAD, + GST_BUFFERING_TIMESHIFT, + GST_BUFFERING_LIVE +} GstBufferingMode; + +#include +#include +#include +#include +#include +#include +#include + +GST_API +const gchar* gst_query_type_get_name (GstQueryType type); + +GST_API +GQuark gst_query_type_to_quark (GstQueryType type); + +GST_API +GstQueryTypeFlags + gst_query_type_get_flags (GstQueryType type); + + +GST_API +GType gst_query_get_type (void); + +/* refcounting */ +/** + * gst_query_ref: + * @q: a #GstQuery to increase the refcount of. + * + * Increases the refcount of the given query by one. + * + * Returns: @q + */ +static inline GstQuery * +gst_query_ref (GstQuery * q) +{ + return GST_QUERY_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (q))); +} + +/** + * gst_query_unref: + * @q: a #GstQuery to decrease the refcount of. + * + * Decreases the refcount of the query. If the refcount reaches 0, the query + * will be freed. + */ +static inline void +gst_query_unref (GstQuery * q) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (q)); +} + +/* copy query */ +/** + * gst_query_copy: + * @q: a #GstQuery to copy. + * + * Copies the given query using the copy function of the parent #GstStructure. + * + * Free-function: gst_query_unref + * + * Returns: (transfer full): a new copy of @q. + */ +static inline GstQuery * +gst_query_copy (const GstQuery * q) +{ + return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q))); +} + +/** + * gst_query_is_writable: + * @q: a #GstQuery + * + * Tests if you can safely write data into a query's structure. + */ +#define gst_query_is_writable(q) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (q)) +/** + * gst_query_make_writable: + * @q: (transfer full): a #GstQuery to make writable + * + * Makes a writable query from the given query. + * + * Returns: (transfer full): a new writable query (possibly same as @q) + */ +#define gst_query_make_writable(q) GST_QUERY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (q))) +/** + * gst_query_replace: + * @old_query: (inout) (transfer full) (nullable): pointer to a pointer to a + * #GstQuery to be replaced. + * @new_query: (allow-none) (transfer none): pointer to a #GstQuery that will + * replace the query pointed to by @old_query. + * + * Modifies a pointer to a #GstQuery to point to a different #GstQuery. The + * modification is done atomically (so this is useful for ensuring thread safety + * in some cases), and the reference counts are updated appropriately (the old + * query is unreffed, the new one is reffed). + * + * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL. + * + * Returns: %TRUE if @new_query was different from @old_query + */ +static inline gboolean +gst_query_replace (GstQuery **old_query, GstQuery *new_query) +{ + return gst_mini_object_replace ((GstMiniObject **) old_query, (GstMiniObject *) new_query); +} + +/* application specific query */ + +GST_API +GstQuery * gst_query_new_custom (GstQueryType type, GstStructure *structure) G_GNUC_MALLOC; + +GST_API +const GstStructure * + gst_query_get_structure (GstQuery *query); + +GST_API +GstStructure * gst_query_writable_structure (GstQuery *query); + +/* position query */ + +GST_API +GstQuery* gst_query_new_position (GstFormat format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_position (GstQuery *query, GstFormat format, gint64 cur); + +GST_API +void gst_query_parse_position (GstQuery *query, GstFormat *format, gint64 *cur); + +/* duration query */ + +GST_API +GstQuery* gst_query_new_duration (GstFormat format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_duration (GstQuery *query, GstFormat format, gint64 duration); + +GST_API +void gst_query_parse_duration (GstQuery *query, GstFormat *format, gint64 *duration); + +/* latency query */ + +GST_API +GstQuery* gst_query_new_latency (void) G_GNUC_MALLOC; + +GST_API +void gst_query_set_latency (GstQuery *query, gboolean live, GstClockTime min_latency, + GstClockTime max_latency); + +GST_API +void gst_query_parse_latency (GstQuery *query, gboolean *live, GstClockTime *min_latency, + GstClockTime *max_latency); + +/* convert query */ + +GST_API +GstQuery* gst_query_new_convert (GstFormat src_format, gint64 value, GstFormat dest_format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_convert (GstQuery *query, GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 dest_value); + +GST_API +void gst_query_parse_convert (GstQuery *query, GstFormat *src_format, gint64 *src_value, + GstFormat *dest_format, gint64 *dest_value); +/* segment query */ + +GST_API +GstQuery* gst_query_new_segment (GstFormat format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_segment (GstQuery *query, gdouble rate, GstFormat format, + gint64 start_value, gint64 stop_value); + +GST_API +void gst_query_parse_segment (GstQuery *query, gdouble *rate, GstFormat *format, + gint64 *start_value, gint64 *stop_value); + +/* seeking query */ + +GST_API +GstQuery* gst_query_new_seeking (GstFormat format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_seeking (GstQuery *query, GstFormat format, + gboolean seekable, + gint64 segment_start, + gint64 segment_end); + +GST_API +void gst_query_parse_seeking (GstQuery *query, GstFormat *format, + gboolean *seekable, + gint64 *segment_start, + gint64 *segment_end); +/* formats query */ + +GST_API +GstQuery* gst_query_new_formats (void) G_GNUC_MALLOC; + +GST_API +void gst_query_set_formats (GstQuery *query, gint n_formats, ...); + +GST_API +void gst_query_set_formatsv (GstQuery *query, gint n_formats, const GstFormat *formats); + +GST_API +void gst_query_parse_n_formats (GstQuery *query, guint *n_formats); + +GST_API +void gst_query_parse_nth_format (GstQuery *query, guint nth, GstFormat *format); + +/* buffering query */ + +GST_API +GstQuery* gst_query_new_buffering (GstFormat format) G_GNUC_MALLOC; + +GST_API +void gst_query_set_buffering_percent (GstQuery *query, gboolean busy, gint percent); + +GST_API +void gst_query_parse_buffering_percent (GstQuery *query, gboolean *busy, gint *percent); + +GST_API +void gst_query_set_buffering_stats (GstQuery *query, GstBufferingMode mode, + gint avg_in, gint avg_out, + gint64 buffering_left); + +GST_API +void gst_query_parse_buffering_stats (GstQuery *query, GstBufferingMode *mode, + gint *avg_in, gint *avg_out, + gint64 *buffering_left); + +GST_API +void gst_query_set_buffering_range (GstQuery *query, GstFormat format, + gint64 start, gint64 stop, + gint64 estimated_total); + +GST_API +void gst_query_parse_buffering_range (GstQuery *query, GstFormat *format, + gint64 *start, gint64 *stop, + gint64 *estimated_total); + +GST_API +gboolean gst_query_add_buffering_range (GstQuery *query, + gint64 start, gint64 stop); + +GST_API +guint gst_query_get_n_buffering_ranges (GstQuery *query); + +GST_API +gboolean gst_query_parse_nth_buffering_range (GstQuery *query, + guint index, gint64 *start, + gint64 *stop); + +/* URI query */ + +GST_API +GstQuery * gst_query_new_uri (void) G_GNUC_MALLOC; + +GST_API +void gst_query_parse_uri (GstQuery *query, gchar **uri); + +GST_API +void gst_query_set_uri (GstQuery *query, const gchar *uri); + +GST_API +void gst_query_parse_uri_redirection (GstQuery *query, gchar **uri); + +GST_API +void gst_query_set_uri_redirection (GstQuery *query, const gchar *uri); + +GST_API +void gst_query_parse_uri_redirection_permanent (GstQuery *query, gboolean * permanent); + +GST_API +void gst_query_set_uri_redirection_permanent (GstQuery *query, gboolean permanent); + +/* allocation query */ + +GST_API +GstQuery * gst_query_new_allocation (GstCaps *caps, gboolean need_pool) G_GNUC_MALLOC; + +GST_API +void gst_query_parse_allocation (GstQuery *query, GstCaps **caps, gboolean *need_pool); + +/* pools */ + +GST_API +void gst_query_add_allocation_pool (GstQuery *query, GstBufferPool *pool, + guint size, guint min_buffers, + guint max_buffers); + +GST_API +guint gst_query_get_n_allocation_pools (GstQuery *query); + +GST_API +void gst_query_parse_nth_allocation_pool (GstQuery *query, guint index, + GstBufferPool **pool, + guint *size, guint *min_buffers, + guint *max_buffers); + +GST_API +void gst_query_set_nth_allocation_pool (GstQuery *query, guint index, + GstBufferPool *pool, + guint size, guint min_buffers, + guint max_buffers); + +GST_API +void gst_query_remove_nth_allocation_pool (GstQuery *query, guint index); + +/* allocators */ + +GST_API +void gst_query_add_allocation_param (GstQuery *query, GstAllocator *allocator, + const GstAllocationParams *params); + +GST_API +guint gst_query_get_n_allocation_params (GstQuery *query); + +GST_API +void gst_query_parse_nth_allocation_param (GstQuery *query, guint index, + GstAllocator **allocator, + GstAllocationParams *params); + +GST_API +void gst_query_set_nth_allocation_param (GstQuery *query, guint index, + GstAllocator *allocator, + const GstAllocationParams *params); + +GST_API +void gst_query_remove_nth_allocation_param (GstQuery *query, guint index); + +/* metadata */ + +GST_API +void gst_query_add_allocation_meta (GstQuery *query, GType api, const GstStructure *params); + +GST_API +guint gst_query_get_n_allocation_metas (GstQuery *query); + +GST_API +GType gst_query_parse_nth_allocation_meta (GstQuery *query, guint index, + const GstStructure **params); + +GST_API +void gst_query_remove_nth_allocation_meta (GstQuery *query, guint index); + +GST_API +gboolean gst_query_find_allocation_meta (GstQuery *query, GType api, guint *index); + + +/* scheduling query */ +/** + * GstSchedulingFlags: + * @GST_SCHEDULING_FLAG_SEEKABLE: if seeking is possible + * @GST_SCHEDULING_FLAG_SEQUENTIAL: if sequential access is recommended + * @GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED: if bandwidth is limited and buffering possible (since 1.2) + * + * The different scheduling flags. + */ +typedef enum { + GST_SCHEDULING_FLAG_SEEKABLE = (1 << 0), + GST_SCHEDULING_FLAG_SEQUENTIAL = (1 << 1), + GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED = (1 << 2) +} GstSchedulingFlags; + +GST_API +GstQuery * gst_query_new_scheduling (void) G_GNUC_MALLOC; + +GST_API +void gst_query_set_scheduling (GstQuery *query, GstSchedulingFlags flags, + gint minsize, gint maxsize, gint align); + +GST_API +void gst_query_parse_scheduling (GstQuery *query, GstSchedulingFlags *flags, + gint *minsize, gint *maxsize, gint *align); + +GST_API +void gst_query_add_scheduling_mode (GstQuery *query, GstPadMode mode); + +GST_API +guint gst_query_get_n_scheduling_modes (GstQuery *query); + +GST_API +GstPadMode gst_query_parse_nth_scheduling_mode (GstQuery *query, guint index); + +GST_API +gboolean gst_query_has_scheduling_mode (GstQuery *query, GstPadMode mode); + +GST_API +gboolean gst_query_has_scheduling_mode_with_flags (GstQuery * query, GstPadMode mode, + GstSchedulingFlags flags); + +/* accept-caps query */ + +GST_API +GstQuery * gst_query_new_accept_caps (GstCaps *caps) G_GNUC_MALLOC; + +GST_API +void gst_query_parse_accept_caps (GstQuery *query, GstCaps **caps); + +GST_API +void gst_query_set_accept_caps_result (GstQuery *query, gboolean result); + +GST_API +void gst_query_parse_accept_caps_result (GstQuery *query, gboolean *result); + +/* caps query */ + +GST_API +GstQuery * gst_query_new_caps (GstCaps *filter) G_GNUC_MALLOC; + +GST_API +void gst_query_parse_caps (GstQuery *query, GstCaps **filter); + +GST_API +void gst_query_set_caps_result (GstQuery *query, GstCaps *caps); + +GST_API +void gst_query_parse_caps_result (GstQuery *query, GstCaps **caps); + +/* drain query */ + +GST_API +GstQuery * gst_query_new_drain (void) G_GNUC_MALLOC; + +/* context query */ + +GST_API +GstQuery * gst_query_new_context (const gchar * context_type) G_GNUC_MALLOC; + +GST_API +gboolean gst_query_parse_context_type (GstQuery * query, const gchar ** context_type); + +GST_API +void gst_query_set_context (GstQuery *query, GstContext *context); + +GST_API +void gst_query_parse_context (GstQuery *query, GstContext **context); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstQuery, gst_query_unref) +#endif + +G_END_DECLS + +#endif /* __GST_QUERY_H__ */ + diff --git a/gst/gstregistry.c b/gst/gstregistry.c new file mode 100644 index 0000000..bada33e --- /dev/null +++ b/gst/gstregistry.c @@ -0,0 +1,1873 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 David A. Schleef + * + * gstregistry.c: handle registry + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstregistry + * @title: GstRegistry + * @short_description: Abstract base class for management of #GstPlugin objects + * @see_also: #GstPlugin, #GstPluginFeature + * + * One registry holds the metadata of a set of plugins. + * + * Design: + * + * The #GstRegistry object is a list of plugins and some functions for dealing + * with them. Each #GstPlugin is matched 1-1 with a file on disk, and may or may + * not be loaded at a given time. + * + * The primary source, at all times, of plugin information is each plugin file + * itself. Thus, if an application wants information about a particular plugin, + * or wants to search for a feature that satisfies given criteria, the primary + * means of doing so is to load every plugin and look at the resulting + * information that is gathered in the default registry. Clearly, this is a time + * consuming process, so we cache information in the registry file. The format + * and location of the cache file is internal to gstreamer. + * + * On startup, plugins are searched for in the plugin search path. The following + * locations are checked in this order: + * + * * location from --gst-plugin-path commandline option. + * * the GST_PLUGIN_PATH environment variable. + * * the GST_PLUGIN_SYSTEM_PATH environment variable. + * * default locations (if GST_PLUGIN_SYSTEM_PATH is not set). + * Those default locations are: + * `$XDG_DATA_HOME/gstreamer-$GST_API_VERSION/plugins/` + * and `$prefix/libs/gstreamer-$GST_API_VERSION/`. + * [$XDG_DATA_HOME](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) defaults to + * `$HOME/.local/share`. + * + * The registry cache file is loaded from + * `$XDG_CACHE_HOME/gstreamer-$GST_API_VERSION/registry-$ARCH.bin` + * (where $XDG_CACHE_HOME defaults to `$HOME/.cache`) or the file listed in the `GST_REGISTRY` + * env var. One reason to change the registry location is for testing. + * + * For each plugin that is found in the plugin search path, there could be 3 + * possibilities for cached information: + * + * * the cache may not contain information about a given file. + * * the cache may have stale information. + * * the cache may have current information. + * + * In the first two cases, the plugin is loaded and the cache updated. In + * addition to these cases, the cache may have entries for plugins that are not + * relevant to the current process. These are marked as not available to the + * current process. If the cache is updated for whatever reason, it is marked + * dirty. + * + * A dirty cache is written out at the end of initialization. Each entry is + * checked to make sure the information is minimally valid. If not, the entry is + * simply dropped. + * + * ## Implementation notes: + * + * The "cache" and "registry" are different concepts and can represent + * different sets of plugins. For various reasons, at init time, the cache is + * stored in the default registry, and plugins not relevant to the current + * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are + * removed at the end of initialization. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gstconfig.h" +#include "gst_private.h" +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +/* For g_stat () */ +#include + +#include "gstinfo.h" +#include "gsterror.h" +#include "gstregistry.h" +#include "gstdeviceproviderfactory.h" + +#include "gstpluginloader.h" + +#include "gst-i18n-lib.h" + +#include "gst.h" +#include "glib-compat-private.h" + +#ifdef G_OS_WIN32 +#include +extern HMODULE _priv_gst_dll_handle; +#endif + +#define GST_CAT_DEFAULT GST_CAT_REGISTRY + +struct _GstRegistryPrivate +{ + GList *plugins; + GList *features; + + guint n_plugins; +#if 0 + GList *paths; +#endif + + int cache_file; + + /* hash to speedup _lookup_feature_locked() */ + GHashTable *feature_hash; + /* hash to speedup _lookup */ + GHashTable *basename_hash; + + /* updated whenever the feature list changes */ + guint32 cookie; + /* speedup for searching features */ + GList *element_factory_list; + guint32 efl_cookie; + GList *typefind_factory_list; + guint32 tfl_cookie; + GList *device_provider_factory_list; + guint32 dmfl_cookie; +}; + +/* the one instance of the default registry and the mutex protecting the + * variable. */ +static GMutex _gst_registry_mutex; +static GstRegistry *_gst_registry_default = NULL; + +/* defaults */ +#define DEFAULT_FORK TRUE + +/* control the behaviour of registry rebuild */ +static gboolean _gst_enable_registry_fork = DEFAULT_FORK; +/* List of plugins that need preloading/reloading after scanning registry */ +extern GSList *_priv_gst_preload_plugins; + +#ifndef GST_DISABLE_REGISTRY +/* Set to TRUE to disable registry, behaves similar to GST_DISABLE_REGISTRY */ +gboolean _priv_gst_disable_registry = FALSE; +/*set to TRUE when registry needn't to be updated */ +gboolean _priv_gst_disable_registry_update = FALSE; +extern GList *_priv_gst_plugin_paths; + +/* Set to TRUE when the registry cache should be disabled */ +gboolean _gst_disable_registry_cache = FALSE; + +static gboolean __registry_reuse_plugin_scanner = TRUE; +#endif + +/* Element signals and args */ +enum +{ + PLUGIN_ADDED, + FEATURE_ADDED, + LAST_SIGNAL +}; + +static void gst_registry_finalize (GObject * object); + +static guint gst_registry_signals[LAST_SIGNAL] = { 0 }; + +static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry * + registry, const char *name); +static GstPlugin *gst_registry_lookup_bn_locked (GstRegistry * registry, + const char *basename); + +#define gst_registry_parent_class parent_class +G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT); + +static void +gst_registry_class_init (GstRegistryClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstRegistryPrivate)); + + /** + * GstRegistry::plugin-added: + * @registry: the registry that emitted the signal + * @plugin: the plugin that has been added + * + * Signals that a plugin has been added to the registry (possibly + * replacing a previously-added one by the same name) + */ + gst_registry_signals[PLUGIN_ADDED] = + g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_PLUGIN); + + /** + * GstRegistry::feature-added: + * @registry: the registry that emitted the signal + * @feature: the feature that has been added + * + * Signals that a feature has been added to the registry (possibly + * replacing a previously-added one by the same name) + */ + gst_registry_signals[FEATURE_ADDED] = + g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_PLUGIN_FEATURE); + + gobject_class->finalize = gst_registry_finalize; +} + +static void +gst_registry_init (GstRegistry * registry) +{ + registry->priv = + G_TYPE_INSTANCE_GET_PRIVATE (registry, GST_TYPE_REGISTRY, + GstRegistryPrivate); + registry->priv->feature_hash = g_hash_table_new (g_str_hash, g_str_equal); + registry->priv->basename_hash = g_hash_table_new (g_str_hash, g_str_equal); +} + +static void +gst_registry_finalize (GObject * object) +{ + GstRegistry *registry = GST_REGISTRY (object); + GList *plugins, *p; + GList *features, *f; + + plugins = registry->priv->plugins; + registry->priv->plugins = NULL; + registry->priv->n_plugins = 0; + + GST_DEBUG_OBJECT (registry, "registry finalize"); + p = plugins; + while (p) { + GstPlugin *plugin = p->data; + + if (plugin) { + GST_LOG_OBJECT (registry, "removing plugin %s", + gst_plugin_get_name (plugin)); + gst_object_unref (plugin); + } + p = g_list_next (p); + } + g_list_free (plugins); + + features = registry->priv->features; + registry->priv->features = NULL; + + f = features; + while (f) { + GstPluginFeature *feature = f->data; + + if (feature) { + GST_LOG_OBJECT (registry, "removing feature %p (%s)", feature, + GST_OBJECT_NAME (feature)); + gst_object_unparent (GST_OBJECT_CAST (feature)); + } + f = g_list_next (f); + } + g_list_free (features); + + g_hash_table_destroy (registry->priv->feature_hash); + registry->priv->feature_hash = NULL; + g_hash_table_destroy (registry->priv->basename_hash); + registry->priv->basename_hash = NULL; + + if (registry->priv->element_factory_list) { + GST_DEBUG_OBJECT (registry, "Cleaning up cached element factory list"); + gst_plugin_feature_list_free (registry->priv->element_factory_list); + } + + if (registry->priv->typefind_factory_list) { + GST_DEBUG_OBJECT (registry, "Cleaning up cached typefind factory list"); + gst_plugin_feature_list_free (registry->priv->typefind_factory_list); + } + + if (registry->priv->device_provider_factory_list) { + GST_DEBUG_OBJECT (registry, + "Cleaning up cached device provider factory list"); + gst_plugin_feature_list_free (registry->priv->device_provider_factory_list); + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_registry_get: + * + * Retrieves the singleton plugin registry. The caller does not own a + * reference on the registry, as it is alive as long as GStreamer is + * initialized. + * + * Returns: (transfer none): the #GstRegistry. + */ +GstRegistry * +gst_registry_get (void) +{ + GstRegistry *registry; + + g_mutex_lock (&_gst_registry_mutex); + if (G_UNLIKELY (!_gst_registry_default)) { + _gst_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL); + gst_object_ref_sink (GST_OBJECT_CAST (_gst_registry_default)); + } + registry = _gst_registry_default; + g_mutex_unlock (&_gst_registry_mutex); + + return registry; +} + +#if 0 +/** + * gst_registry_add_path: + * @registry: the registry to add the path to + * @path: the path to add to the registry + * + * Add the given path to the registry. The syntax of the + * path is specific to the registry. If the path has already been + * added, do nothing. + */ +void +gst_registry_add_path (GstRegistry * registry, const gchar * path) +{ + g_return_if_fail (GST_IS_REGISTRY (registry)); + g_return_if_fail (path != NULL); + + if (strlen (path) == 0) + goto empty_path; + + GST_OBJECT_LOCK (registry); + if (g_list_find_custom (registry->priv->paths, path, (GCompareFunc) strcmp)) + goto was_added; + + GST_INFO ("Adding plugin path: \"%s\"", path); + registry->priv->paths = + g_list_append (registry->priv->paths, g_strdup (path)); + GST_OBJECT_UNLOCK (registry); + + return; + +empty_path: + { + GST_INFO ("Ignoring empty plugin path"); + return; + } +was_added: + { + g_warning ("path %s already added to registry", path); + GST_OBJECT_UNLOCK (registry); + return; + } +} + +/** + * gst_registry_get_path_list: + * @registry: the registry to get the pathlist of + * + * Get the list of paths for the given registry. + * + * Returns: (transfer container) (element-type char*): A #GList of paths as + * strings. g_list_free after use. + * + * MT safe. + */ +GList * +gst_registry_get_path_list (GstRegistry * registry) +{ + GList *list; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + + GST_OBJECT_LOCK (registry); + /* We don't need to copy the strings, because they won't be deleted + * as long as the GstRegistry is around */ + list = g_list_copy (registry->priv->paths); + GST_OBJECT_UNLOCK (registry); + + return list; +} +#endif + +/** + * gst_registry_add_plugin: + * @registry: the registry to add the plugin to + * @plugin: (transfer floating): the plugin to add + * + * Add the plugin to the registry. The plugin-added signal will be emitted. + * + * @plugin's reference count will be incremented, and any floating + * reference will be removed (see gst_object_ref_sink()) + * + * Returns: %TRUE on success. + * + * MT safe. + */ +gboolean +gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin) +{ + GstPlugin *existing_plugin; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); + g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE); + + GST_OBJECT_LOCK (registry); + if (G_LIKELY (plugin->basename)) { + /* we have a basename, see if we find the plugin */ + existing_plugin = + gst_registry_lookup_bn_locked (registry, plugin->basename); + if (existing_plugin) { + GST_DEBUG_OBJECT (registry, + "Replacing existing plugin \"%s\" %p with new plugin %p for filename \"%s\"", + GST_STR_NULL (existing_plugin->filename), existing_plugin, plugin, + GST_STR_NULL (plugin->filename)); + /* If the new plugin is blacklisted and the existing one isn't cached, do not + * accept if it's from a different location than the existing one */ + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED) && + strcmp (plugin->filename, existing_plugin->filename)) { + GST_WARNING_OBJECT (registry, + "Not replacing plugin because new one (%s) is blacklisted but for a different location than existing one (%s)", + plugin->filename, existing_plugin->filename); + /* Keep reference counting consistent */ + gst_object_ref_sink (plugin); + gst_object_unref (plugin); + GST_OBJECT_UNLOCK (registry); + return FALSE; + } + registry->priv->plugins = + g_list_remove (registry->priv->plugins, existing_plugin); + --registry->priv->n_plugins; + if (G_LIKELY (existing_plugin->basename)) + g_hash_table_remove (registry->priv->basename_hash, + existing_plugin->basename); + gst_object_unref (existing_plugin); + } + } + + GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"", + plugin, GST_STR_NULL (plugin->filename)); + + registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin); + ++registry->priv->n_plugins; + + if (G_LIKELY (plugin->basename)) + g_hash_table_replace (registry->priv->basename_hash, plugin->basename, + plugin); + + gst_object_ref_sink (plugin); + GST_OBJECT_UNLOCK (registry); + + GST_LOG_OBJECT (registry, "emitting plugin-added for filename \"%s\"", + GST_STR_NULL (plugin->filename)); + g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin); + + return TRUE; +} + +static void +gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry, + GstPlugin * plugin) +{ + GList *f; + + g_return_if_fail (GST_IS_REGISTRY (registry)); + g_return_if_fail (GST_IS_PLUGIN (plugin)); + + /* Remove all features for this plugin */ + f = registry->priv->features; + while (f != NULL) { + GList *next = g_list_next (f); + GstPluginFeature *feature = f->data; + + if (G_UNLIKELY (feature && feature->plugin == plugin)) { + GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %p (%s)", + feature, gst_plugin_feature_get_name (feature), plugin, + plugin->desc.name); + + registry->priv->features = + g_list_delete_link (registry->priv->features, f); + g_hash_table_remove (registry->priv->feature_hash, + GST_OBJECT_NAME (feature)); + gst_object_unparent (GST_OBJECT_CAST (feature)); + } + f = next; + } + registry->priv->cookie++; +} + +/** + * gst_registry_remove_plugin: + * @registry: the registry to remove the plugin from + * @plugin: (transfer none): the plugin to remove + * + * Remove the plugin from the registry. + * + * MT safe. + */ +void +gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin) +{ + g_return_if_fail (GST_IS_REGISTRY (registry)); + g_return_if_fail (GST_IS_PLUGIN (plugin)); + + GST_DEBUG_OBJECT (registry, "removing plugin %p (%s)", + plugin, gst_plugin_get_name (plugin)); + + GST_OBJECT_LOCK (registry); + registry->priv->plugins = g_list_remove (registry->priv->plugins, plugin); + --registry->priv->n_plugins; + if (G_LIKELY (plugin->basename)) + g_hash_table_remove (registry->priv->basename_hash, plugin->basename); + gst_registry_remove_features_for_plugin_unlocked (registry, plugin); + GST_OBJECT_UNLOCK (registry); + gst_object_unref (plugin); +} + +/** + * gst_registry_add_feature: + * @registry: the registry to add the plugin to + * @feature: (transfer floating): the feature to add + * + * Add the feature to the registry. The feature-added signal will be emitted. + * + * @feature's reference count will be incremented, and any floating + * reference will be removed (see gst_object_ref_sink()) + * + * Returns: %TRUE on success. + * + * MT safe. + */ +gboolean +gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature) +{ + GstPluginFeature *existing_feature; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE); + g_return_val_if_fail (GST_OBJECT_NAME (feature) != NULL, FALSE); + g_return_val_if_fail (feature->plugin_name != NULL, FALSE); + + GST_OBJECT_LOCK (registry); + existing_feature = gst_registry_lookup_feature_locked (registry, + GST_OBJECT_NAME (feature)); + if (G_UNLIKELY (existing_feature)) { + GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)", + existing_feature, GST_OBJECT_NAME (feature)); + /* Remove the existing feature from the list now, before we insert the new + * one, but don't unref yet because the hash is still storing a reference to + * it. */ + registry->priv->features = + g_list_remove (registry->priv->features, existing_feature); + } + + GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, + GST_OBJECT_NAME (feature)); + + registry->priv->features = g_list_prepend (registry->priv->features, feature); + g_hash_table_replace (registry->priv->feature_hash, GST_OBJECT_NAME (feature), + feature); + + if (G_UNLIKELY (existing_feature)) { + /* We unref now. No need to remove the feature name from the hash table, it + * got replaced by the new feature */ + gst_object_unparent (GST_OBJECT_CAST (existing_feature)); + } + + gst_object_set_parent (GST_OBJECT_CAST (feature), GST_OBJECT_CAST (registry)); + + registry->priv->cookie++; + GST_OBJECT_UNLOCK (registry); + + GST_LOG_OBJECT (registry, "emitting feature-added for %s", + GST_OBJECT_NAME (feature)); + g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature); + + return TRUE; +} + +/** + * gst_registry_remove_feature: + * @registry: the registry to remove the feature from + * @feature: (transfer none): the feature to remove + * + * Remove the feature from the registry. + * + * MT safe. + */ +void +gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature) +{ + g_return_if_fail (GST_IS_REGISTRY (registry)); + g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature)); + + GST_DEBUG_OBJECT (registry, "removing feature %p (%s)", + feature, gst_plugin_feature_get_name (feature)); + + GST_OBJECT_LOCK (registry); + registry->priv->features = g_list_remove (registry->priv->features, feature); + g_hash_table_remove (registry->priv->feature_hash, GST_OBJECT_NAME (feature)); + registry->priv->cookie++; + GST_OBJECT_UNLOCK (registry); + + gst_object_unparent ((GstObject *) feature); +} + +/** + * gst_registry_plugin_filter: + * @registry: registry to query + * @filter: (scope call): the filter to use + * @first: only return first match + * @user_data: (closure): user data passed to the filter function + * + * Runs a filter against all plugins in the registry and returns a #GList with + * the results. If the first flag is set, only the first match is + * returned (as a list with a single object). + * Every plugin is reffed; use gst_plugin_list_free() after use, which + * will unref again. + * + * Returns: (transfer full) (element-type Gst.Plugin): a #GList of #GstPlugin. + * Use gst_plugin_list_free() after usage. + * + * MT safe. + */ +GList * +gst_registry_plugin_filter (GstRegistry * registry, + GstPluginFilter filter, gboolean first, gpointer user_data) +{ + GstPlugin **plugins; + GList *walk, *list = NULL; + guint n_plugins, i; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + + GST_OBJECT_LOCK (registry); + n_plugins = registry->priv->n_plugins; + plugins = g_newa (GstPlugin *, n_plugins + 1); + for (walk = registry->priv->plugins, i = 0; walk != NULL; walk = walk->next) + plugins[i++] = gst_object_ref (walk->data); + GST_OBJECT_UNLOCK (registry); + + for (i = 0; i < n_plugins; ++i) { + if (filter == NULL || filter (plugins[i], user_data)) { + list = g_list_prepend (list, gst_object_ref (plugins[i])); + + if (first) + break; + } + } + + for (i = 0; i < n_plugins; ++i) + gst_object_unref (plugins[i]); + + return list; +} + +typedef struct +{ + const gchar *name; + GType type; +} GstTypeNameData; + +static gboolean +gst_plugin_feature_type_name_filter (GstPluginFeature * feature, + GstTypeNameData * data) +{ + g_assert (GST_IS_PLUGIN_FEATURE (feature)); + + return ((data->type == 0 || data->type == G_OBJECT_TYPE (feature)) && + (data->name == NULL || !strcmp (data->name, GST_OBJECT_NAME (feature)))); +} + +/* returns TRUE if the list was changed + * + * Must be called with the object lock taken */ +static gboolean +gst_registry_get_feature_list_or_create (GstRegistry * registry, + GList ** previous, guint32 * cookie, GType type) +{ + gboolean res = FALSE; + GstRegistryPrivate *priv = registry->priv; + + if (G_UNLIKELY (!*previous || priv->cookie != *cookie)) { + GstTypeNameData data; + const GList *walk; + + if (*previous) { + gst_plugin_feature_list_free (*previous); + *previous = NULL; + } + + data.type = type; + data.name = NULL; + + for (walk = registry->priv->features; walk != NULL; walk = walk->next) { + GstPluginFeature *feature = walk->data; + + if (gst_plugin_feature_type_name_filter (feature, &data)) { + *previous = g_list_prepend (*previous, gst_object_ref (feature)); + } + } + + *cookie = priv->cookie; + res = TRUE; + } + + return res; +} + +static gint +type_find_factory_rank_cmp (const GstPluginFeature * fac1, + const GstPluginFeature * fac2) +{ + if (G_LIKELY (fac1->rank != fac2->rank)) + return fac2->rank - fac1->rank; + + /* to make the order in which things happen more deterministic, + * sort by name when the ranks are the same. */ + return strcmp (GST_OBJECT_NAME (fac1), GST_OBJECT_NAME (fac2)); +} + +static GList * +gst_registry_get_element_factory_list (GstRegistry * registry) +{ + GList *list; + + GST_OBJECT_LOCK (registry); + + gst_registry_get_feature_list_or_create (registry, + ®istry->priv->element_factory_list, ®istry->priv->efl_cookie, + GST_TYPE_ELEMENT_FACTORY); + + /* Return reffed copy */ + list = gst_plugin_feature_list_copy (registry->priv->element_factory_list); + + GST_OBJECT_UNLOCK (registry); + + return list; +} + +static GList * +gst_registry_get_typefind_factory_list (GstRegistry * registry) +{ + GList *list; + + GST_OBJECT_LOCK (registry); + + if (G_UNLIKELY (gst_registry_get_feature_list_or_create (registry, + ®istry->priv->typefind_factory_list, + ®istry->priv->tfl_cookie, GST_TYPE_TYPE_FIND_FACTORY))) + registry->priv->typefind_factory_list = + g_list_sort (registry->priv->typefind_factory_list, + (GCompareFunc) type_find_factory_rank_cmp); + + /* Return reffed copy */ + list = gst_plugin_feature_list_copy (registry->priv->typefind_factory_list); + + GST_OBJECT_UNLOCK (registry); + + return list; +} + + +static GList * +gst_registry_get_device_provider_factory_list (GstRegistry * registry) +{ + GList *list; + + GST_OBJECT_LOCK (registry); + + gst_registry_get_feature_list_or_create (registry, + ®istry->priv->device_provider_factory_list, + ®istry->priv->dmfl_cookie, GST_TYPE_DEVICE_PROVIDER_FACTORY); + + /* Return reffed copy */ + list = + gst_plugin_feature_list_copy (registry-> + priv->device_provider_factory_list); + + GST_OBJECT_UNLOCK (registry); + + return list; +} + +/** + * gst_registry_feature_filter: + * @registry: registry to query + * @filter: (scope call): the filter to use + * @first: only return first match + * @user_data: (closure): user data passed to the filter function + * + * Runs a filter against all features of the plugins in the registry + * and returns a GList with the results. + * If the first flag is set, only the first match is + * returned (as a list with a single object). + * + * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of + * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. + * + * MT safe. + */ +GList * +gst_registry_feature_filter (GstRegistry * registry, + GstPluginFeatureFilter filter, gboolean first, gpointer user_data) +{ + GstPluginFeature **features; + GList *walk, *list = NULL; + guint n_features, i; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + + GST_OBJECT_LOCK (registry); + n_features = g_hash_table_size (registry->priv->feature_hash); + features = g_newa (GstPluginFeature *, n_features + 1); + for (walk = registry->priv->features, i = 0; walk != NULL; walk = walk->next) + features[i++] = gst_object_ref (walk->data); + GST_OBJECT_UNLOCK (registry); + + for (i = 0; i < n_features; ++i) { + if (filter == NULL || filter (features[i], user_data)) { + list = g_list_prepend (list, gst_object_ref (features[i])); + + if (first) + break; + } + } + + for (i = 0; i < n_features; ++i) + gst_object_unref (features[i]); + + return list; +} + +static gboolean +gst_registry_plugin_name_filter (GstPlugin * plugin, const gchar * name) +{ + return (plugin->desc.name && !strcmp (plugin->desc.name, name)); +} + +/** + * gst_registry_find_plugin: + * @registry: the registry to search + * @name: the plugin name to find + * + * Find the plugin with the given name in the registry. + * The plugin will be reffed; caller is responsible for unreffing. + * + * Returns: (transfer full) (nullable): the plugin with the given name + * or %NULL if the plugin was not found. gst_object_unref() after + * usage. + * + * MT safe. + */ +GstPlugin * +gst_registry_find_plugin (GstRegistry * registry, const gchar * name) +{ + GList *walk; + GstPlugin *result = NULL; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (name != NULL, NULL); + + walk = gst_registry_plugin_filter (registry, + (GstPluginFilter) gst_registry_plugin_name_filter, TRUE, (gpointer) name); + if (walk) { + result = GST_PLUGIN_CAST (walk->data); + + gst_object_ref (result); + gst_plugin_list_free (walk); + } + + return result; +} + +/** + * gst_registry_find_feature: + * @registry: the registry to search + * @name: the pluginfeature name to find + * @type: the pluginfeature type to find + * + * Find the pluginfeature with the given name and type in the registry. + * + * Returns: (transfer full) (nullable): the pluginfeature with the + * given name and type or %NULL if the plugin was not + * found. gst_object_unref() after usage. + * + * MT safe. + */ +GstPluginFeature * +gst_registry_find_feature (GstRegistry * registry, const gchar * name, + GType type) +{ + GstPluginFeature *feature = NULL; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL); + + feature = gst_registry_lookup_feature (registry, name); + if (feature && !g_type_is_a (G_TYPE_FROM_INSTANCE (feature), type)) { + gst_object_unref (feature); + feature = NULL; + } + + return feature; +} + +/** + * gst_registry_get_feature_list: + * @registry: a #GstRegistry + * @type: a #GType. + * + * Retrieves a #GList of #GstPluginFeature of @type. + * + * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of + * #GstPluginFeature of @type. Use gst_plugin_feature_list_free() after use + * + * MT safe. + */ +GList * +gst_registry_get_feature_list (GstRegistry * registry, GType type) +{ + GstTypeNameData data; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL); + + /* Speed up */ + if (type == GST_TYPE_ELEMENT_FACTORY) + return gst_registry_get_element_factory_list (registry); + else if (type == GST_TYPE_TYPE_FIND_FACTORY) + return gst_registry_get_typefind_factory_list (registry); + else if (type == GST_TYPE_DEVICE_PROVIDER_FACTORY) + return gst_registry_get_device_provider_factory_list (registry); + + data.type = type; + data.name = NULL; + + return gst_registry_feature_filter (registry, + (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter, + FALSE, &data); +} + +/** + * gst_registry_get_plugin_list: + * @registry: the registry to search + * + * Get a copy of all plugins registered in the given registry. The refcount + * of each element in the list in incremented. + * + * Returns: (transfer full) (element-type Gst.Plugin): a #GList of #GstPlugin. + * Use gst_plugin_list_free() after usage. + * + * MT safe. + */ +GList * +gst_registry_get_plugin_list (GstRegistry * registry) +{ + GList *list; + GList *g; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + + GST_OBJECT_LOCK (registry); + list = g_list_copy (registry->priv->plugins); + for (g = list; g; g = g->next) { + gst_object_ref (GST_PLUGIN_CAST (g->data)); + } + GST_OBJECT_UNLOCK (registry); + + return list; +} + +static GstPluginFeature * +gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name) +{ + return g_hash_table_lookup (registry->priv->feature_hash, name); +} + +/** + * gst_registry_lookup_feature: + * @registry: a #GstRegistry + * @name: a #GstPluginFeature name + * + * Find a #GstPluginFeature with @name in @registry. + * + * Returns: (transfer full): a #GstPluginFeature with its refcount incremented, + * use gst_object_unref() after usage. + * + * MT safe. + */ +GstPluginFeature * +gst_registry_lookup_feature (GstRegistry * registry, const char *name) +{ + GstPluginFeature *feature; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (name != NULL, NULL); + + GST_OBJECT_LOCK (registry); + feature = gst_registry_lookup_feature_locked (registry, name); + if (feature) + gst_object_ref (feature); + GST_OBJECT_UNLOCK (registry); + + return feature; +} + +static GstPlugin * +gst_registry_lookup_bn_locked (GstRegistry * registry, const char *basename) +{ + return g_hash_table_lookup (registry->priv->basename_hash, basename); +} + +static GstPlugin * +gst_registry_lookup_bn (GstRegistry * registry, const char *basename) +{ + GstPlugin *plugin; + + GST_OBJECT_LOCK (registry); + plugin = gst_registry_lookup_bn_locked (registry, basename); + if (plugin) + gst_object_ref (plugin); + GST_OBJECT_UNLOCK (registry); + + return plugin; +} + +/** + * gst_registry_lookup: + * @registry: the registry to look up in + * @filename: the name of the file to look up + * + * Look up a plugin in the given registry with the given filename. + * If found, plugin is reffed. + * + * Returns: (transfer full) (nullable): the #GstPlugin if found, or + * %NULL if not. gst_object_unref() after usage. + */ +GstPlugin * +gst_registry_lookup (GstRegistry * registry, const char *filename) +{ + GstPlugin *plugin; + gchar *basename; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (filename != NULL, NULL); + + basename = g_path_get_basename (filename); + if (G_UNLIKELY (basename == NULL)) + return NULL; + + plugin = gst_registry_lookup_bn (registry, basename); + + g_free (basename); + + return plugin; +} + +typedef enum +{ + REGISTRY_SCAN_HELPER_NOT_STARTED = 0, + REGISTRY_SCAN_HELPER_DISABLED, + REGISTRY_SCAN_HELPER_RUNNING +} GstRegistryScanHelperState; + +typedef struct +{ + GstRegistry *registry; + GstRegistryScanHelperState helper_state; + GstPluginLoader *helper; + gboolean changed; +} GstRegistryScanContext; + +static void +init_scan_context (GstRegistryScanContext * context, GstRegistry * registry) +{ + gboolean do_fork; + + context->registry = registry; + + /* see if forking is enabled and set up the scan helper state accordingly */ + do_fork = _gst_enable_registry_fork; + if (do_fork) { + const gchar *fork_env; + + /* forking enabled, see if it is disabled with an env var */ + if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) { + /* fork enabled for any value different from "no" */ + do_fork = strcmp (fork_env, "no") != 0; + } + } + + if (do_fork) + context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED; + else + context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; + + context->helper = NULL; + context->changed = FALSE; +} + +static void +clear_scan_context (GstRegistryScanContext * context) +{ + if (context->helper) { + context->changed |= _priv_gst_plugin_loader_funcs.destroy (context->helper); + context->helper = NULL; + } +} + +static gboolean +gst_registry_scan_plugin_file (GstRegistryScanContext * context, + const gchar * filename, off_t file_size, time_t file_mtime) +{ + gboolean changed = FALSE; + GstPlugin *newplugin = NULL; + +#ifdef G_OS_WIN32 + /* Disable external plugin loader on Windows until it is ported properly. */ + context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; +#endif + + + /* Have a plugin to load - see if the scan-helper needs starting */ + if (context->helper_state == REGISTRY_SCAN_HELPER_NOT_STARTED) { + GST_DEBUG ("Starting plugin scanner for file %s", filename); + context->helper = _priv_gst_plugin_loader_funcs.create (context->registry); + if (context->helper != NULL) + context->helper_state = REGISTRY_SCAN_HELPER_RUNNING; + else { + GST_WARNING ("Failed starting plugin scanner. Scanning in-process"); + context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; + } + } + + if (context->helper_state == REGISTRY_SCAN_HELPER_RUNNING) { + GST_DEBUG ("Using scan-helper to load plugin %s", filename); + if (!_priv_gst_plugin_loader_funcs.load (context->helper, + filename, file_size, file_mtime)) { + g_warning ("External plugin loader failed. This most likely means that " + "the plugin loader helper binary was not found or could not be run. " + "You might need to set the GST_PLUGIN_SCANNER environment variable " + "if your setup is unusual. This should normally not be required " + "though."); + context->helper_state = REGISTRY_SCAN_HELPER_DISABLED; + } + } + + /* Check if the helper is disabled (or just got disabled above) */ + if (context->helper_state == REGISTRY_SCAN_HELPER_DISABLED) { + /* Load plugin the old fashioned way... */ + + /* We don't use a GError here because a failure to load some shared + * objects as plugins is normal (particularly in the uninstalled case) + */ + newplugin = _priv_gst_plugin_load_file_for_registry (filename, + context->registry, NULL); + } + + if (newplugin) { + GST_DEBUG_OBJECT (context->registry, "marking new plugin %p as registered", + newplugin); + newplugin->registered = TRUE; + gst_object_unref (newplugin); + changed = TRUE; + } +#ifndef GST_DISABLE_REGISTRY + if (!__registry_reuse_plugin_scanner) { + clear_scan_context (context); + context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED; + } +#endif + + return changed; +} + +static gboolean +is_blacklisted_hidden_directory (const gchar * dirent) +{ + if (G_LIKELY (dirent[0] != '.')) + return FALSE; + + /* skip the .debug directory, these contain elf files that are not + * useful or worse, can crash dlopen () */ + if (strcmp (dirent, ".debug") == 0) + return TRUE; + + /* can also skip .git and .deps dirs, those won't contain useful files. + * This speeds up scanning a bit in uninstalled setups. */ + if (strcmp (dirent, ".git") == 0 || strcmp (dirent, ".deps") == 0) + return TRUE; + + return FALSE; +} + +static gboolean +gst_registry_scan_path_level (GstRegistryScanContext * context, + const gchar * path, int level) +{ + GDir *dir; + const gchar *dirent; + gchar *filename; + GstPlugin *plugin; + gboolean changed = FALSE; + + dir = g_dir_open (path, 0, NULL); + if (!dir) + return FALSE; + + while ((dirent = g_dir_read_name (dir))) { + GStatBuf file_status; + + filename = g_build_filename (path, dirent, NULL); + if (g_stat (filename, &file_status) < 0) { + /* Plugin will be removed from cache after the scan completes if it + * is still marked 'cached' */ + g_free (filename); + continue; + } + + if (file_status.st_mode & S_IFDIR) { + if (G_UNLIKELY (is_blacklisted_hidden_directory (dirent))) { + GST_TRACE_OBJECT (context->registry, "ignoring %s directory", dirent); + g_free (filename); + continue; + } + /* FIXME 2.0: Don't recurse into directories, this behaviour + * is inconsistent with other PATH environment variables + */ + if (level > 0) { + GST_LOG_OBJECT (context->registry, "recursing into directory %s", + filename); + changed |= gst_registry_scan_path_level (context, filename, level - 1); + } else { + GST_LOG_OBJECT (context->registry, "not recursing into directory %s, " + "recursion level too deep", filename); + } + g_free (filename); + continue; + } + if (!(file_status.st_mode & S_IFREG)) { + GST_TRACE_OBJECT (context->registry, "%s is not a regular file, ignoring", + filename); + g_free (filename); + continue; + } + if (!g_str_has_suffix (dirent, "." G_MODULE_SUFFIX) +#ifdef GST_EXTRA_MODULE_SUFFIX + && !g_str_has_suffix (dirent, GST_EXTRA_MODULE_SUFFIX) +#endif + ) { + GST_TRACE_OBJECT (context->registry, + "extension is not recognized as module file, ignoring file %s", + filename); + g_free (filename); + continue; + } + + GST_LOG_OBJECT (context->registry, "file %s looks like a possible module", + filename); + + /* try to avoid unnecessary plugin-move pain */ + if (g_str_has_prefix (dirent, "libgstvalve") || + g_str_has_prefix (dirent, "libgstselector")) { + GST_WARNING_OBJECT (context->registry, "ignoring old plugin %s which " + "has been merged into the corelements plugin", filename); + /* Plugin will be removed from cache after the scan completes if it + * is still marked 'cached' */ + g_free (filename); + continue; + } + + /* plug-ins are considered unique by basename; if the given name + * was already seen by the registry, we ignore it */ + plugin = gst_registry_lookup_bn (context->registry, dirent); + if (plugin) { + gboolean env_vars_changed, deps_changed = FALSE; + + if (plugin->registered) { + GST_DEBUG_OBJECT (context->registry, + "plugin already registered from path \"%s\"", + GST_STR_NULL (plugin->filename)); + g_free (filename); + gst_object_unref (plugin); + continue; + } + + env_vars_changed = _priv_plugin_deps_env_vars_changed (plugin); + + /* If a file with a certain basename is seen on a different path, + * update the plugin to ensure the registry cache will reflect up + * to date information */ + + if (plugin->file_mtime == file_status.st_mtime && + plugin->file_size == file_status.st_size && !env_vars_changed && + !(deps_changed = _priv_plugin_deps_files_changed (plugin)) && + !strcmp (plugin->filename, filename)) { + GST_LOG_OBJECT (context->registry, "file %s cached", filename); + GST_OBJECT_FLAG_UNSET (plugin, GST_PLUGIN_FLAG_CACHED); + GST_LOG_OBJECT (context->registry, + "marking plugin %p as registered as %s", plugin, filename); + plugin->registered = TRUE; + } else { + GST_INFO_OBJECT (context->registry, "cached info for %s is stale", + filename); + GST_DEBUG_OBJECT (context->registry, "mtime %" G_GINT64_FORMAT " != %" + G_GINT64_FORMAT " or size %" G_GINT64_FORMAT " != %" + G_GINT64_FORMAT " or external dependency env_vars changed: %d or" + " external dependencies changed: %d or old path %s != new path %s", + (gint64) plugin->file_mtime, (gint64) file_status.st_mtime, + (gint64) plugin->file_size, (gint64) file_status.st_size, + env_vars_changed, deps_changed, plugin->filename, filename); + gst_registry_remove_plugin (context->registry, plugin); + changed |= gst_registry_scan_plugin_file (context, filename, + file_status.st_size, file_status.st_mtime); + } + gst_object_unref (plugin); + + } else { + GST_DEBUG_OBJECT (context->registry, "file %s not yet in registry", + filename); + changed |= gst_registry_scan_plugin_file (context, filename, + file_status.st_size, file_status.st_mtime); + } + + g_free (filename); + } + + g_dir_close (dir); + + return changed; +} + +static gboolean +gst_registry_scan_path_internal (GstRegistryScanContext * context, + const gchar * path) +{ + gboolean changed; + + GST_DEBUG_OBJECT (context->registry, "scanning path %s", path); + changed = gst_registry_scan_path_level (context, path, 10); + + GST_DEBUG_OBJECT (context->registry, "registry changed in path %s: %d", path, + changed); + return changed; +} + +/** + * gst_registry_scan_path: + * @registry: the registry to add found plugins to + * @path: (type filename): the path to scan + * + * Scan the given path for plugins to add to the registry. The syntax of the + * path is specific to the registry. + * + * Returns: %TRUE if registry changed + */ +gboolean +gst_registry_scan_path (GstRegistry * registry, const gchar * path) +{ + GstRegistryScanContext context; + gboolean result; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + + init_scan_context (&context, registry); + + result = gst_registry_scan_path_internal (&context, path); + + clear_scan_context (&context); + result |= context.changed; + + return result; +} + +static gboolean +_gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature, + gpointer user_data) +{ + return (strcmp (feature->plugin_name, (gchar *) user_data) == 0); +} + +/** + * gst_registry_get_feature_list_by_plugin: + * @registry: a #GstRegistry. + * @name: a plugin name. + * + * Retrieves a #GList of features of the plugin with name @name. + * + * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of + * #GstPluginFeature. Use gst_plugin_feature_list_free() after usage. + */ +GList * +gst_registry_get_feature_list_by_plugin (GstRegistry * registry, + const gchar * name) +{ + g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL); + g_return_val_if_fail (name != NULL, NULL); + + return gst_registry_feature_filter (registry, + _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name); +} + +/* Unref and delete the default registry */ +void +_priv_gst_registry_cleanup (void) +{ + GstRegistry *registry; + + g_mutex_lock (&_gst_registry_mutex); + if ((registry = _gst_registry_default) != NULL) { + _gst_registry_default = NULL; + } + g_mutex_unlock (&_gst_registry_mutex); + + /* unref outside of the lock because we can. */ + if (registry) + gst_object_unref (registry); +} + +/** + * gst_registry_check_feature_version: + * @registry: a #GstRegistry + * @feature_name: the name of the feature (e.g. "oggdemux") + * @min_major: the minimum major version number + * @min_minor: the minimum minor version number + * @min_micro: the minimum micro version number + * + * Checks whether a plugin feature by the given name exists in + * @registry and whether its version is at least the + * version required. + * + * Returns: %TRUE if the feature could be found and the version is + * the same as the required version or newer, and %FALSE otherwise. + */ +gboolean +gst_registry_check_feature_version (GstRegistry * registry, + const gchar * feature_name, guint min_major, guint min_minor, + guint min_micro) +{ + GstPluginFeature *feature; + gboolean ret = FALSE; + + g_return_val_if_fail (feature_name != NULL, FALSE); + + GST_DEBUG ("Looking up plugin feature '%s'", feature_name); + + feature = gst_registry_lookup_feature (registry, feature_name); + if (feature) { + ret = gst_plugin_feature_check_version (feature, min_major, min_minor, + min_micro); + gst_object_unref (feature); + } else { + GST_DEBUG ("Could not find plugin feature '%s'", feature_name); + } + + return ret; +} + +static void +load_plugin_func (gpointer data, gpointer user_data) +{ + GstPlugin *plugin; + const gchar *filename; + GError *err = NULL; + + filename = (const gchar *) data; + GST_DEBUG ("Pre-loading plugin %s", filename); + + plugin = gst_plugin_load_file (filename, &err); + + if (plugin) { + GST_INFO ("Loaded plugin: \"%s\"", filename); + + gst_registry_add_plugin (gst_registry_get (), plugin); + } else { + if (err) { + /* Report error to user, and free error */ + GST_ERROR ("Failed to load plugin: %s", err->message); + g_error_free (err); + } else { + GST_WARNING ("Failed to load plugin: \"%s\"", filename); + } + } +} + +#ifndef GST_DISABLE_REGISTRY +/* Unref all plugins marked 'cached', to clear old plugins that no + * longer exist. Returns %TRUE if any plugins were removed */ +static gboolean +gst_registry_remove_cache_plugins (GstRegistry * registry) +{ + GList *g; + GList *g_next; + GstPlugin *plugin; + gboolean changed = FALSE; + + g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); + + GST_OBJECT_LOCK (registry); + + GST_DEBUG_OBJECT (registry, "removing cached plugins"); + g = registry->priv->plugins; + while (g) { + g_next = g->next; + plugin = g->data; + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_CACHED)) { + GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"", + GST_STR_NULL (plugin->filename)); + registry->priv->plugins = g_list_delete_link (registry->priv->plugins, g); + --registry->priv->n_plugins; + if (G_LIKELY (plugin->basename)) + g_hash_table_remove (registry->priv->basename_hash, plugin->basename); + gst_registry_remove_features_for_plugin_unlocked (registry, plugin); + gst_object_unref (plugin); + changed = TRUE; + } + g = g_next; + } + + GST_OBJECT_UNLOCK (registry); + + return changed; +} + +typedef enum +{ + REGISTRY_SCAN_AND_UPDATE_FAILURE = 0, + REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED, + REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED +} GstRegistryScanAndUpdateResult; + +/* + * scan_and_update_registry: + * @default_registry: the #GstRegistry + * @registry_file: registry filename + * @write_changes: write registry if it has changed? + * + * Scans for registry changes and eventually updates the registry cache. + * + * Return: %REGISTRY_SCAN_AND_UPDATE_FAILURE if the registry could not scanned + * or updated, %REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED if the + * registry is clean and %REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED if + * it has been updated and the cache needs to be re-read. + */ +static GstRegistryScanAndUpdateResult +scan_and_update_registry (GstRegistry * default_registry, + const gchar * registry_file, gboolean write_changes, GError ** error) +{ + const gchar *plugin_path; + gboolean changed = FALSE; + GList *l; + GstRegistryScanContext context; + + GST_INFO ("Validating plugins from registry cache: %s", registry_file); + + init_scan_context (&context, default_registry); + + /* It sounds tempting to just compare the mtime of directories with the mtime + * of the registry cache, but it does not work. It would not catch updated + * plugins, which might bring more or less features. + */ + + /* scan paths specified via --gst-plugin-path */ + GST_DEBUG ("scanning paths added via --gst-plugin-path"); + for (l = _priv_gst_plugin_paths; l != NULL; l = l->next) { + GST_INFO ("Scanning plugin path: \"%s\"", (gchar *) l->data); + changed |= gst_registry_scan_path_internal (&context, (gchar *) l->data); + } + /* keep plugin_paths around in case a re-scan is forced later on */ + + /* GST_PLUGIN_PATH specifies a list of directories to scan for + * additional plugins. These take precedence over the system plugins */ + plugin_path = g_getenv ("GST_PLUGIN_PATH_1_0"); + if (plugin_path == NULL) + plugin_path = g_getenv ("GST_PLUGIN_PATH"); + if (plugin_path) { + char **list; + int i; + + GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path); + list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; list[i]; i++) { + changed |= gst_registry_scan_path_internal (&context, list[i]); + } + g_strfreev (list); + } else { + GST_DEBUG ("GST_PLUGIN_PATH not set"); + } + + /* GST_PLUGIN_SYSTEM_PATH specifies a list of plugins that are always + * loaded by default. If not set, this defaults to the system-installed + * path, and the plugins installed in the user's home directory */ + plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH_1_0"); + if (plugin_path == NULL) + plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH"); + if (plugin_path == NULL) { + char *home_plugins; + + GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set"); + + /* plugins in the user's home directory take precedence over + * system-installed ones */ + home_plugins = g_build_filename (g_get_user_data_dir (), + "gstreamer-" GST_API_VERSION, "plugins", NULL); + + GST_DEBUG ("scanning home plugins %s", home_plugins); + changed |= gst_registry_scan_path_internal (&context, home_plugins); + g_free (home_plugins); + + /* add the main (installed) library path */ + +#ifdef G_OS_WIN32 + { + char *base_dir; + char *dir; + + base_dir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + + dir = g_build_filename (base_dir, +#ifdef _DEBUG + "debug" +#endif + "lib", "gstreamer-" GST_API_VERSION, NULL); + GST_DEBUG ("scanning DLL dir %s", dir); + + changed |= gst_registry_scan_path_internal (&context, dir); + + g_free (dir); + g_free (base_dir); + } +#else + GST_DEBUG ("scanning main plugins %s", PLUGINDIR); + changed |= gst_registry_scan_path_internal (&context, PLUGINDIR); +#endif + } else { + gchar **list; + gint i; + + GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path); + list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; list[i]; i++) { + changed |= gst_registry_scan_path_internal (&context, list[i]); + } + g_strfreev (list); + } + + clear_scan_context (&context); + changed |= context.changed; + + /* Remove cached plugins so stale info is cleared. */ + changed |= gst_registry_remove_cache_plugins (default_registry); + + if (!changed) { + GST_INFO ("Registry cache has not changed"); + return REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED; + } + + if (!write_changes) { + GST_INFO ("Registry cache changed, but writing is disabled. Not writing."); + return REGISTRY_SCAN_AND_UPDATE_FAILURE; + } + + GST_INFO ("Registry cache changed. Writing new registry cache"); + if (!priv_gst_registry_binary_write_cache (default_registry, + default_registry->priv->plugins, registry_file)) { + g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + _("Error writing registry cache to %s: %s"), + registry_file, g_strerror (errno)); + return REGISTRY_SCAN_AND_UPDATE_FAILURE; + } + + GST_INFO ("Registry cache written successfully"); + return REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED; +} + +static gboolean +ensure_current_registry (GError ** error) +{ + gchar *registry_file; + GstRegistry *default_registry; + gboolean ret = TRUE; + gboolean do_update = TRUE; + gboolean have_cache = TRUE; + + default_registry = gst_registry_get (); + + registry_file = g_strdup (g_getenv ("GST_REGISTRY_1_0")); + if (registry_file == NULL) + registry_file = g_strdup (g_getenv ("GST_REGISTRY")); + if (registry_file == NULL) { + registry_file = g_build_filename (g_get_user_cache_dir (), + "gstreamer-" GST_API_VERSION, "registry." TARGET_CPU ".bin", NULL); + } + + if (!_gst_disable_registry_cache) { + GST_INFO ("reading registry cache: %s", registry_file); + have_cache = priv_gst_registry_binary_read_cache (default_registry, + registry_file); + /* Only ever read the registry cache once, then disable it for + * subsequent updates during the program lifetime */ + _gst_disable_registry_cache = TRUE; + } + + if (have_cache) { + do_update = !_priv_gst_disable_registry_update; + if (do_update) { + const gchar *update_env; + + if ((update_env = g_getenv ("GST_REGISTRY_UPDATE"))) { + /* do update for any value different from "no" */ + do_update = (strcmp (update_env, "no") != 0); + } + } + } + + if (do_update) { + const gchar *reuse_env; + + if ((reuse_env = g_getenv ("GST_REGISTRY_REUSE_PLUGIN_SCANNER"))) { + /* do reuse for any value different from "no" */ + __registry_reuse_plugin_scanner = (strcmp (reuse_env, "no") != 0); + } + /* now check registry */ + GST_DEBUG ("Updating registry cache"); + scan_and_update_registry (default_registry, registry_file, TRUE, error); + } else { + GST_DEBUG ("Not updating registry cache (disabled)"); + } + + g_free (registry_file); + GST_INFO ("registry reading and updating done, result = %d", ret); + + return ret; +} +#endif /* GST_DISABLE_REGISTRY */ + +/** + * gst_registry_fork_is_enabled: + * + * By default GStreamer will perform scanning and rebuilding of the + * registry file using a helper child process. + * + * Applications might want to disable this behaviour with the + * gst_registry_fork_set_enabled() function, in which case new plugins + * are scanned (and loaded) into the application process. + * + * Returns: %TRUE if GStreamer will use the child helper process when + * rebuilding the registry. + */ +gboolean +gst_registry_fork_is_enabled (void) +{ + return _gst_enable_registry_fork; +} + +/** + * gst_registry_fork_set_enabled: + * @enabled: whether rebuilding the registry can use a temporary child helper process. + * + * Applications might want to disable/enable spawning of a child helper process + * when rebuilding the registry. See gst_registry_fork_is_enabled() for more + * information. + */ +void +gst_registry_fork_set_enabled (gboolean enabled) +{ + _gst_enable_registry_fork = enabled; +} + +/** + * gst_update_registry: + * + * Forces GStreamer to re-scan its plugin paths and update the default + * plugin registry. + * + * Applications will almost never need to call this function, it is only + * useful if the application knows new plugins have been installed (or old + * ones removed) since the start of the application (or, to be precise, the + * first call to gst_init()) and the application wants to make use of any + * newly-installed plugins without restarting the application. + * + * Applications should assume that the registry update is neither atomic nor + * thread-safe and should therefore not have any dynamic pipelines running + * (including the playbin and decodebin elements) and should also not create + * any elements or access the GStreamer registry while the update is in + * progress. + * + * Note that this function may block for a significant amount of time. + * + * Returns: %TRUE if the registry has been updated successfully (does not + * imply that there were changes), otherwise %FALSE. + */ +gboolean +gst_update_registry (void) +{ + gboolean res; + +#ifndef GST_DISABLE_REGISTRY + if (!_priv_gst_disable_registry) { + GError *err = NULL; + + res = ensure_current_registry (&err); + if (err) { + GST_WARNING ("registry update failed: %s", err->message); + g_error_free (err); + } else { + GST_LOG ("registry update succeeded"); + } + } else { + GST_INFO ("registry update disabled by environment"); + res = TRUE; + } + +#else + GST_WARNING ("registry update failed: %s", "registry disabled"); + res = TRUE; +#endif /* GST_DISABLE_REGISTRY */ + + if (_priv_gst_preload_plugins) { + GST_DEBUG ("Preloading indicated plugins..."); + g_slist_foreach (_priv_gst_preload_plugins, load_plugin_func, NULL); + } + + return res; +} + +/** + * gst_registry_get_feature_list_cookie: + * @registry: the registry + * + * Returns the registry's feature list cookie. This changes + * every time a feature is added or removed from the registry. + * + * Returns: the feature list cookie. + */ +guint32 +gst_registry_get_feature_list_cookie (GstRegistry * registry) +{ + g_return_val_if_fail (GST_IS_REGISTRY (registry), 0); + + return registry->priv->cookie; +} diff --git a/gst/gstregistry.h b/gst/gstregistry.h new file mode 100644 index 0000000..a5ae603 --- /dev/null +++ b/gst/gstregistry.h @@ -0,0 +1,134 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstregistry.h: Header for registry 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_REGISTRY_H__ +#define __GST_REGISTRY_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_REGISTRY (gst_registry_get_type ()) +#define GST_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REGISTRY, GstRegistry)) +#define GST_IS_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REGISTRY)) +#define GST_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REGISTRY, GstRegistryClass)) +#define GST_IS_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REGISTRY)) +#define GST_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_REGISTRY, GstRegistryClass)) + +typedef struct _GstRegistry GstRegistry; +typedef struct _GstRegistryClass GstRegistryClass; +typedef struct _GstRegistryPrivate GstRegistryPrivate; + +/** + * GstRegistry: + * + * Opaque #GstRegistry structure. + */ +struct _GstRegistry { + GstObject object; + + /*< private >*/ + GstRegistryPrivate *priv; +}; + +struct _GstRegistryClass { + GstObjectClass parent_class; +}; + +GST_API +GType gst_registry_get_type (void); + +GST_API +GstRegistry * gst_registry_get (void); + +GST_API +gboolean gst_registry_scan_path (GstRegistry *registry, const gchar *path); + +#if 0 +void gst_registry_add_path (GstRegistry * registry, const gchar * path); +GList* gst_registry_get_path_list (GstRegistry *registry); +#endif + +GST_API +gboolean gst_registry_add_plugin (GstRegistry *registry, GstPlugin *plugin); + +GST_API +void gst_registry_remove_plugin (GstRegistry *registry, GstPlugin *plugin); + +GST_API +gboolean gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature); + +GST_API +void gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature); + +GST_API +GList* gst_registry_get_plugin_list (GstRegistry *registry); + +GST_API +GList* gst_registry_plugin_filter (GstRegistry *registry, + GstPluginFilter filter, + gboolean first, + gpointer user_data); +GST_API +GList* gst_registry_feature_filter (GstRegistry *registry, + GstPluginFeatureFilter filter, + gboolean first, + gpointer user_data); +GST_API +GList * gst_registry_get_feature_list (GstRegistry *registry, + GType type); +GST_API +GList * gst_registry_get_feature_list_by_plugin (GstRegistry *registry, const gchar *name); + +GST_API +guint32 gst_registry_get_feature_list_cookie (GstRegistry *registry); + +GST_API +GstPlugin* gst_registry_find_plugin (GstRegistry *registry, const gchar *name); + +GST_API +GstPluginFeature* gst_registry_find_feature (GstRegistry *registry, const gchar *name, GType type); + +GST_API +GstPlugin * gst_registry_lookup (GstRegistry *registry, const char *filename); + +GST_API +GstPluginFeature * gst_registry_lookup_feature (GstRegistry *registry, const char *name); + +GST_API +gboolean gst_registry_check_feature_version (GstRegistry *registry, + const gchar *feature_name, + guint min_major, + guint min_minor, + guint min_micro); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstRegistry, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_REGISTRY_H__ */ + diff --git a/gst/gstregistrybinary.c b/gst/gstregistrybinary.c new file mode 100644 index 0000000..43e6288 --- /dev/null +++ b/gst/gstregistrybinary.c @@ -0,0 +1,636 @@ +/* GStreamer + * Copyright (C) 2006 Josep Torra + * 2006 Mathieu Garcia + * 2006,2007 Stefan Kost + * 2008 Sebastian Dröge + * + * gstregistrybinary.c: GstRegistryBinary object, support 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* FIXME: + * - keep registry binary blob and reference strings + * - don't free/unmmap contents when leaving gst_registry_binary_read_cache() + * - free at gst_deinit() / _priv_gst_registry_cleanup() ? + * - GstPlugin: + * - GST_PLUGIN_FLAG_CONST + * - GstPluginFeature, GstIndexFactory, GstElementFactory + * - needs Flags (GST_PLUGIN_FEATURE_FLAG_CONST) + * - can we turn loaded into flag? + * - why do we collect a list of binary chunks and not write immediately + * - because we need to process subchunks, before we can set e.g. nr_of_items + * in parent chunk + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include + +#if defined (_MSC_VER) && _MSC_VER >= 1400 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include /* for g_stat(), g_mapped_file(), ... */ + +#include "glib-compat-private.h" + + +#define GST_CAT_DEFAULT GST_CAT_REGISTRY + +/* reading macros */ +#define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \ + if (inptr + sizeof(element) >= endptr) \ + goto error_label; \ + outptr = (element *) inptr; \ + inptr += sizeof (element); \ +}G_STMT_END + +#define ALIGNMENT (sizeof (void *)) +#define alignment(_address) (gsize)_address%ALIGNMENT +#define align(_ptr) _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr)) + +/* Registry saving */ + +#ifdef G_OS_WIN32 +/* On win32, we can't use g_mkstmp(), because of cross-DLL file I/O problems. + * So, we just create the entire binary registry in memory, then write it out + * with g_file_set_contents(), which creates a temporary file internally + */ + +typedef struct BinaryRegistryCache +{ + const char *location; + guint8 *mem; + gssize len; +} BinaryRegistryCache; + +static BinaryRegistryCache * +gst_registry_binary_cache_init (GstRegistry * registry, const char *location) +{ + BinaryRegistryCache *cache = g_slice_new0 (BinaryRegistryCache); + cache->location = location; + return cache; +} + +static int +gst_registry_binary_cache_write (BinaryRegistryCache * cache, + unsigned long offset, const void *data, int length) +{ + cache->len = MAX (offset + length, cache->len); + cache->mem = g_realloc (cache->mem, cache->len); + + memcpy (cache->mem + offset, data, length); + + return length; +} + +static gboolean +gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success) +{ + gboolean ret = TRUE; + GError *error = NULL; + if (!g_file_set_contents (cache->location, (const gchar *) cache->mem, + cache->len, &error)) { + /* Probably the directory didn't exist; create it */ + gchar *dir; + dir = g_path_get_dirname (cache->location); + g_mkdir_with_parents (dir, 0777); + g_free (dir); + + g_error_free (error); + error = NULL; + + if (!g_file_set_contents (cache->location, (const gchar *) cache->mem, + cache->len, &error)) { + /* Probably the directory didn't exist; create it */ + gchar *dir; + dir = g_path_get_dirname (cache->location); + g_mkdir_with_parents (dir, 0777); + g_free (dir); + + g_error_free (error); + error = NULL; + + if (!g_file_set_contents (cache->location, (const gchar *) cache->mem, + cache->len, &error)) { + GST_ERROR ("Failed to write to cache file: %s", error->message); + g_error_free (error); + ret = FALSE; + } + } + } + + g_free (cache->mem); + g_slice_free (BinaryRegistryCache, cache); + return ret; +} + +#else +typedef struct BinaryRegistryCache +{ + const char *location; + char *tmp_location; + unsigned long currentoffset; + int cache_fd; +} BinaryRegistryCache; + +static BinaryRegistryCache * +gst_registry_binary_cache_init (GstRegistry * registry, const char *location) +{ + BinaryRegistryCache *cache = g_slice_new0 (BinaryRegistryCache); + + cache->location = location; + cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL); + cache->cache_fd = g_mkstemp (cache->tmp_location); + if (cache->cache_fd == -1) { + int ret; + GStatBuf statbuf; + gchar *dir; + + /* oops, I bet the directory doesn't exist */ + dir = g_path_get_dirname (location); + g_mkdir_with_parents (dir, 0777); + + ret = g_stat (dir, &statbuf); + if (ret != -1 && (statbuf.st_mode & 0700) != 0700) { + g_chmod (dir, 0700); + } + + g_free (dir); + + /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */ + g_free (cache->tmp_location); + cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL); + cache->cache_fd = g_mkstemp (cache->tmp_location); + + if (cache->cache_fd == -1) { + GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno)); + g_free (cache->tmp_location); + g_slice_free (BinaryRegistryCache, cache); + return NULL; + } + + ret = g_stat (cache->tmp_location, &statbuf); + if (ret != -1 && (statbuf.st_mode & 0600) != 0600) { + g_chmod (cache->tmp_location, 0600); + } + } + + return cache; +} + +static int +gst_registry_binary_cache_write (BinaryRegistryCache * cache, + unsigned long offset, const void *data, int length) +{ + long written; + if (offset != cache->currentoffset) { + if (lseek (cache->cache_fd, offset, SEEK_SET) < 0) { + GST_ERROR ("Seeking to new offset failed: %s", g_strerror (errno)); + return -1; + } + GST_LOG ("Seeked from offset %lu to %lu", offset, cache->currentoffset); + cache->currentoffset = offset; + } + + written = write (cache->cache_fd, data, length); + if (written != length) { + GST_ERROR ("Failed to write to cache file"); + } + cache->currentoffset += written; + + return written; +} + +static gboolean +gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success) +{ + /* only fsync if we're actually going to use and rename the file below */ + if (success && fsync (cache->cache_fd) < 0) + goto fsync_failed; + + if (close (cache->cache_fd) < 0) + goto close_failed; + + if (!success) + goto fail_after_close; + + /* Only do the rename if we wrote the entire file successfully */ + if (g_rename (cache->tmp_location, cache->location) < 0) { + GST_ERROR ("g_rename() failed: %s", g_strerror (errno)); + goto rename_failed; + } + + g_free (cache->tmp_location); + g_slice_free (BinaryRegistryCache, cache); + GST_INFO ("Wrote binary registry cache"); + return TRUE; + +/* ERRORS */ +fail_after_close: + { + g_unlink (cache->tmp_location); + g_free (cache->tmp_location); + g_slice_free (BinaryRegistryCache, cache); + return FALSE; + } +fsync_failed: + { + GST_ERROR ("fsync() failed: %s", g_strerror (errno)); + goto fail_after_close; + } +close_failed: + { + GST_ERROR ("close() failed: %s", g_strerror (errno)); + goto fail_after_close; + } +rename_failed: + { + GST_ERROR ("g_rename() failed: %s", g_strerror (errno)); + goto fail_after_close; + } +} +#endif + +/* + * gst_registry_binary_write_chunk: + * + * Write from a memory location to the registry cache file + * + * Returns: %TRUE for success + */ +inline static gboolean +gst_registry_binary_write_chunk (BinaryRegistryCache * cache, + GstRegistryChunk * chunk, unsigned long *file_position) +{ + gchar padder[ALIGNMENT] = { 0, }; + int padsize = 0; + + /* Padding to insert the struct that requiere word alignment */ + if ((chunk->align) && (alignment (*file_position) != 0)) { + padsize = ALIGNMENT - alignment (*file_position); + if (gst_registry_binary_cache_write (cache, *file_position, + padder, padsize) != padsize) { + GST_ERROR ("Failed to write binary registry padder"); + return FALSE; + } + *file_position += padsize; + } + + if (gst_registry_binary_cache_write (cache, *file_position, + chunk->data, chunk->size) != chunk->size) { + GST_ERROR ("Failed to write binary registry element"); + return FALSE; + } + + *file_position += chunk->size; + + return TRUE; +} + + +/* + * gst_registry_binary_initialize_magic: + * + * Initialize the GstBinaryRegistryMagic, setting both our magic number and + * gstreamer major/minor version + */ +inline static gboolean +gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m) +{ + memset (m, 0, sizeof (GstBinaryRegistryMagic)); + + if (!memcpy (m->magic, GST_MAGIC_BINARY_REGISTRY_STR, + GST_MAGIC_BINARY_REGISTRY_LEN) + || !strncpy (m->version, GST_MAGIC_BINARY_VERSION_STR, + GST_MAGIC_BINARY_VERSION_LEN)) { + GST_ERROR ("Failed to write magic to the registry magic structure"); + return FALSE; + } + + return TRUE; +} + +/** + * gst_registry_binary_write_cache: + * @registry: a #GstRegistry + * @location: a filename + * + * Write the @registry to a cache to file at given @location. + * + * Returns: %TRUE on success. + */ +gboolean +priv_gst_registry_binary_write_cache (GstRegistry * registry, GList * plugins, + const char *location) +{ + GList *walk; + GstBinaryRegistryMagic magic; + GList *to_write = NULL; + unsigned long file_position = 0; + BinaryRegistryCache *cache; + + GST_INFO ("Building binary registry cache image"); + + g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); + + if (!gst_registry_binary_initialize_magic (&magic)) + goto fail; + + /* iterate trough the list of plugins and fit them into binary structures */ + for (walk = plugins; walk != NULL; walk = walk->next) { + GstPlugin *plugin = GST_PLUGIN (walk->data); + + if (!plugin->filename) + continue; + + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_CACHED)) { + GStatBuf statbuf; + + if (g_stat (plugin->filename, &statbuf) < 0 || + plugin->file_mtime != statbuf.st_mtime || + plugin->file_size != statbuf.st_size) + continue; + } + + if (!_priv_gst_registry_chunks_save_plugin (&to_write, registry, plugin)) { + GST_ERROR ("Can't write binary plugin information for \"%s\"", + plugin->filename); + } + } + + _priv_gst_registry_chunks_save_global_header (&to_write, registry, + priv_gst_plugin_loading_get_whitelist_hash ()); + + GST_INFO ("Writing binary registry cache"); + + cache = gst_registry_binary_cache_init (registry, location); + if (!cache) + goto fail_free_list; + + /* write magic */ + if (gst_registry_binary_cache_write (cache, file_position, + &magic, sizeof (GstBinaryRegistryMagic)) != + sizeof (GstBinaryRegistryMagic)) { + GST_ERROR ("Failed to write binary registry magic"); + goto fail_free_list; + } + file_position += sizeof (GstBinaryRegistryMagic); + + /* write out data chunks */ + for (walk = to_write; walk; walk = g_list_next (walk)) { + GstRegistryChunk *cur = walk->data; + gboolean res; + + res = gst_registry_binary_write_chunk (cache, cur, &file_position); + + _priv_gst_registry_chunk_free (cur); + walk->data = NULL; + if (!res) + goto fail_free_list; + } + g_list_free (to_write); + + if (!gst_registry_binary_cache_finish (cache, TRUE)) + return FALSE; + + return TRUE; + + /* Errors */ +fail_free_list: + { + for (walk = to_write; walk; walk = g_list_next (walk)) { + GstRegistryChunk *cur = walk->data; + + if (cur) + _priv_gst_registry_chunk_free (cur); + } + g_list_free (to_write); + + if (cache) + (void) gst_registry_binary_cache_finish (cache, FALSE); + /* fall through */ + } +fail: + { + return FALSE; + } +} + + +/* Registry loading */ + +/* + * gst_registry_binary_check_magic: + * + * Check GstBinaryRegistryMagic validity. + * Return < 0 if something is wrong, -2 means + * that just the version of the registry is out of + * date, -1 is a general failure. + */ +static gint +gst_registry_binary_check_magic (gchar ** in, gsize size) +{ + GstBinaryRegistryMagic *m; + + align (*in); + GST_DEBUG ("Reading/casting for GstBinaryRegistryMagic at address %p", *in); + unpack_element (*in, m, GstBinaryRegistryMagic, (*in + size), fail); + + if (strncmp (m->magic, GST_MAGIC_BINARY_REGISTRY_STR, + GST_MAGIC_BINARY_REGISTRY_LEN) != 0) { + GST_WARNING + ("Binary registry magic is different : %02x%02x%02x%02x != %02x%02x%02x%02x", + GST_MAGIC_BINARY_REGISTRY_STR[0] & 0xff, + GST_MAGIC_BINARY_REGISTRY_STR[1] & 0xff, + GST_MAGIC_BINARY_REGISTRY_STR[2] & 0xff, + GST_MAGIC_BINARY_REGISTRY_STR[3] & 0xff, m->magic[0] & 0xff, + m->magic[1] & 0xff, m->magic[2] & 0xff, m->magic[3] & 0xff); + return -1; + } + if (strncmp (m->version, GST_MAGIC_BINARY_VERSION_STR, + GST_MAGIC_BINARY_VERSION_LEN)) { + GST_WARNING ("Binary registry magic version is different : %s != %s", + GST_MAGIC_BINARY_VERSION_STR, m->version); + return -2; + } + + return 0; + +fail: + GST_WARNING ("Not enough data for binary registry magic structure"); + return -1; +} + +/** + * gst_registry_binary_read_cache: + * @registry: a #GstRegistry + * @location: a filename + * + * Read the contents of the binary cache file at @location into @registry. + * + * Returns: %TRUE on success. + */ +gboolean +priv_gst_registry_binary_read_cache (GstRegistry * registry, + const char *location) +{ + GMappedFile *mapped = NULL; + gchar *contents = NULL; + gchar *in = NULL; + gsize size; + GError *err = NULL; + gboolean res = FALSE; + guint32 filter_env_hash = 0; + gint check_magic_result; +#ifndef GST_DISABLE_GST_DEBUG + GTimer *timer = NULL; + gdouble seconds; +#endif + + /* make sure these types exist */ + GST_TYPE_ELEMENT_FACTORY; + GST_TYPE_TYPE_FIND_FACTORY; + GST_TYPE_DEVICE_PROVIDER_FACTORY; + GST_TYPE_DYNAMIC_TYPE_FACTORY; + +#ifndef GST_DISABLE_GST_DEBUG + timer = g_timer_new (); +#endif + + mapped = g_mapped_file_new (location, FALSE, &err); + if (G_UNLIKELY (err != NULL)) { + GST_INFO ("Unable to mmap file %s : %s", location, err->message); + g_error_free (err); + err = NULL; + } + + if (mapped == NULL) { + /* Error mmap-ing the cache, try a plain memory read */ + + g_file_get_contents (location, &contents, &size, &err); + if (err != NULL) { + GST_INFO ("Unable to read file %s : %s", location, err->message); +#ifndef GST_DISABLE_GST_DEBUG + g_timer_destroy (timer); +#endif + g_error_free (err); + return FALSE; + } + } else { + /* This can't fail if g_mapped_file_new() succeeded */ + contents = g_mapped_file_get_contents (mapped); + size = g_mapped_file_get_length (mapped); + } + + /* in is a cursor pointer, we initialize it with the begin of registry and is updated on each read */ + in = contents; + GST_DEBUG ("File data at address %p", in); + if (G_UNLIKELY (size < sizeof (GstBinaryRegistryMagic))) { + GST_ERROR ("No or broken registry header for file at %s", location); + goto Error; + } + + /* check if header is valid */ + if (G_UNLIKELY ((check_magic_result = + gst_registry_binary_check_magic (&in, size)) < 0)) { + + if (check_magic_result == -1) + GST_ERROR + ("Binary registry type not recognized (invalid magic) for file at %s", + location); + goto Error; + } + + if (!_priv_gst_registry_chunks_load_global_header (registry, &in, + contents + size, &filter_env_hash)) { + GST_ERROR ("Couldn't read global header chunk"); + goto Error; + } + + if (filter_env_hash != priv_gst_plugin_loading_get_whitelist_hash ()) { + GST_INFO_OBJECT (registry, "Plugin loading filter environment changed, " + "ignoring plugin cache to force update with new filter environment"); + goto done; + } + + /* check if there are plugins in the file */ + if (G_UNLIKELY (!(((gsize) in + sizeof (GstRegistryChunkPluginElement)) < + (gsize) contents + size))) { + GST_INFO ("No binary plugins structure to read"); + /* empty file, this is not an error */ + } else { + gchar *end = contents + size; + /* read as long as we still have space for a GstRegistryChunkPluginElement */ + for (; + ((gsize) in + sizeof (GstRegistryChunkPluginElement)) < + (gsize) contents + size;) { + GST_DEBUG ("reading binary registry %" G_GSIZE_FORMAT "(%x)/%" + G_GSIZE_FORMAT, (gsize) in - (gsize) contents, + (guint) ((gsize) in - (gsize) contents), size); + if (!_priv_gst_registry_chunks_load_plugin (registry, &in, end, NULL)) { + GST_ERROR ("Problem while reading binary registry %s", location); + goto Error; + } + } + } + +done: + +#ifndef GST_DISABLE_GST_DEBUG + g_timer_stop (timer); + seconds = g_timer_elapsed (timer, NULL); +#endif + + GST_INFO ("loaded %s in %lf seconds", location, seconds); + + res = TRUE; + /* TODO: once we re-use the pointers to registry contents, return here */ + +Error: +#ifndef GST_DISABLE_GST_DEBUG + g_timer_destroy (timer); +#endif + if (mapped) { + g_mapped_file_unref (mapped); + } else { + g_free (contents); + } + return res; +} diff --git a/gst/gstregistrybinary.h b/gst/gstregistrybinary.h new file mode 100644 index 0000000..22e56d1 --- /dev/null +++ b/gst/gstregistrybinary.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2006 Josep Torra + * Copyright (C) 2006 Mathieu Garcia + * Copyright (C) 2006 Stefan Kost + * + * gstregistrybinary.h: Header for registry 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* SUGGESTIONS AND TODO : +** ==================== +** - Use a compressed registry, but would induce performance loss +** - Encrypt the registry, for security purpose, but would also reduce performances +*/ + +#ifndef __GST_REGISTRYBINARY_H__ +#define __GST_REGISTRYBINARY_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * GST_MAGIC_BINARY_REGISTRY_STR: + * + * A tag, written at the beginning of the file + */ +#define GST_MAGIC_BINARY_REGISTRY_STR "\xc0\xde\xf0\x0d" +/* + * GST_MAGIC_BINARY_REGISTRY_LEN: + * + * length of the header tag. + */ +#define GST_MAGIC_BINARY_REGISTRY_LEN (4) + +/* + * GST_MAGIC_BINARY_VERSION_STR: + * + * The current version of the binary registry format. + * This _must_ be updated whenever the registry format changes, + * we currently use the core version where this change happened. + */ +#define GST_MAGIC_BINARY_VERSION_STR "1.3.0" + +/* + * GST_MAGIC_BINARY_VERSION_LEN: + * + * Maximum length of the version string in the header. + */ +#define GST_MAGIC_BINARY_VERSION_LEN (64) + +typedef struct _GstBinaryRegistryMagic +{ + gchar magic[GST_MAGIC_BINARY_REGISTRY_LEN]; + gchar version[GST_MAGIC_BINARY_VERSION_LEN]; +} GstBinaryRegistryMagic; + +G_END_DECLS + +#endif /* !__GST_REGISTRYBINARY_H__ */ + diff --git a/gst/gstregistrychunks.c b/gst/gstregistrychunks.c new file mode 100644 index 0000000..bc86ed6 --- /dev/null +++ b/gst/gstregistrychunks.c @@ -0,0 +1,947 @@ +/* GStreamer + * Copyright (C) 2006 Josep Torra + * 2006 Mathieu Garcia + * 2006,2007 Stefan Kost + * 2008 Sebastian Dröge + * 2008 Jan Schmidt + * + * gstregistrychunks.c: GstRegistryChunk helper for serialising/deserialising + * plugin entries and features. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define GST_CAT_DEFAULT GST_CAT_REGISTRY + +/* count string length, but return -1 if we hit the eof */ +static gint +_strnlen (const gchar * str, gint maxlen) +{ + gint len = 0; + + while (G_LIKELY (len < maxlen)) { + if (G_UNLIKELY (str[len] == '\0')) + return len; + len++; + } + return -1; +} + +/* Macros */ +#define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \ + if (inptr + sizeof(element) > endptr) { \ + GST_ERROR ("Failed reading element " G_STRINGIFY (element) \ + ". Have %d bytes need %" G_GSIZE_FORMAT, \ + (int) (endptr - inptr), sizeof(element)); \ + goto error_label; \ + } \ + outptr = (element *) inptr; \ + inptr += sizeof (element); \ +}G_STMT_END + +#define unpack_const_string(inptr, outptr, endptr, error_label) G_STMT_START{\ + gint _len = _strnlen (inptr, (endptr-inptr)); \ + if (_len == -1) \ + goto error_label; \ + outptr = g_intern_string ((const gchar *)inptr); \ + inptr += _len + 1; \ +}G_STMT_END + +#define unpack_string(inptr, outptr, endptr, error_label) G_STMT_START{\ + gint _len = _strnlen (inptr, (endptr-inptr)); \ + if (_len == -1) \ + goto error_label; \ + outptr = g_memdup ((gconstpointer)inptr, _len + 1); \ + inptr += _len + 1; \ +}G_STMT_END + +#define unpack_string_nocopy(inptr, outptr, endptr, error_label) G_STMT_START{\ + gint _len = _strnlen (inptr, (endptr-inptr)); \ + if (_len == -1) \ + goto error_label; \ + outptr = (const gchar *)inptr; \ + inptr += _len + 1; \ +}G_STMT_END + +#define ALIGNMENT (sizeof (void *)) +#define alignment(_address) (gsize)_address%ALIGNMENT +#define align(_ptr) _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr)) + +void +_priv_gst_registry_chunk_free (GstRegistryChunk * chunk) +{ + if (!(chunk->flags & GST_REGISTRY_CHUNK_FLAG_CONST)) { + if ((chunk->flags & GST_REGISTRY_CHUNK_FLAG_MALLOC)) + g_free (chunk->data); + else + g_slice_free1 (chunk->size, chunk->data); + } + g_slice_free (GstRegistryChunk, chunk); +} + +/* + * gst_registry_chunks_save_const_string: + * + * Store a const string in a binary chunk. + * + * Returns: %TRUE for success + */ +inline static gboolean +gst_registry_chunks_save_const_string (GList ** list, const gchar * str) +{ + GstRegistryChunk *chunk; + + if (G_UNLIKELY (str == NULL)) { + GST_ERROR ("unexpected NULL string in plugin or plugin feature data"); + str = ""; + } + + chunk = g_slice_new (GstRegistryChunk); + chunk->data = (gpointer) str; + chunk->size = strlen ((gchar *) chunk->data) + 1; + chunk->flags = GST_REGISTRY_CHUNK_FLAG_CONST; + chunk->align = FALSE; + *list = g_list_prepend (*list, chunk); + return TRUE; +} + +/* + * gst_registry_chunks_save_string: + * + * Store a string in a binary chunk. + * + * Returns: %TRUE for success + */ +inline static gboolean +gst_registry_chunks_save_string (GList ** list, gchar * str) +{ + GstRegistryChunk *chunk; + + chunk = g_slice_new (GstRegistryChunk); + chunk->data = str; + chunk->size = strlen ((gchar *) chunk->data) + 1; + chunk->flags = GST_REGISTRY_CHUNK_FLAG_MALLOC; + chunk->align = FALSE; + *list = g_list_prepend (*list, chunk); + return TRUE; +} + +/* + * gst_registry_chunks_save_data: + * + * Store some data in a binary chunk. + * + * Returns: the initialized chunk + */ +inline static GstRegistryChunk * +gst_registry_chunks_make_data (gpointer data, gulong size) +{ + GstRegistryChunk *chunk; + + chunk = g_slice_new (GstRegistryChunk); + chunk->data = data; + chunk->size = size; + chunk->flags = GST_REGISTRY_CHUNK_FLAG_NONE; + chunk->align = TRUE; + return chunk; +} + + +/* + * gst_registry_chunks_save_pad_template: + * + * Store pad_templates in binary chunks. + * + * Returns: %TRUE for success + */ +static gboolean +gst_registry_chunks_save_pad_template (GList ** list, + GstStaticPadTemplate * template) +{ + GstRegistryChunkPadTemplate *pt; + GstRegistryChunk *chk; + + pt = g_slice_new (GstRegistryChunkPadTemplate); + chk = + gst_registry_chunks_make_data (pt, sizeof (GstRegistryChunkPadTemplate)); + + pt->presence = template->presence; + pt->direction = template->direction; + + /* pack pad template strings */ + gst_registry_chunks_save_const_string (list, + (gchar *) (template->static_caps.string)); + gst_registry_chunks_save_const_string (list, template->name_template); + + *list = g_list_prepend (*list, chk); + + return TRUE; +} + +/* + * gst_registry_chunks_save_feature: + * + * Store features in binary chunks. + * + * Returns: %TRUE for success + */ +static gboolean +gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) +{ + const gchar *type_name = G_OBJECT_TYPE_NAME (feature); + GstRegistryChunkPluginFeature *pf = NULL; + GstRegistryChunk *chk = NULL; + GList *walk; + gsize pf_size = 0; + + if (!type_name) { + GST_ERROR ("NULL feature type_name, aborting."); + return FALSE; + } + + if (GST_IS_ELEMENT_FACTORY (feature)) { + GstRegistryChunkElementFactory *ef; + GstElementFactory *factory = GST_ELEMENT_FACTORY (feature); + + /* Initialize with zeroes because of struct padding and + * valgrind complaining about copying unitialized memory + */ + ef = g_slice_new0 (GstRegistryChunkElementFactory); + pf_size = sizeof (GstRegistryChunkElementFactory); + chk = gst_registry_chunks_make_data (ef, pf_size); + ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0; + pf = (GstRegistryChunkPluginFeature *) ef; + + /* save interfaces */ + for (walk = factory->interfaces; walk; + walk = g_list_next (walk), ef->ninterfaces++) { + gst_registry_chunks_save_const_string (list, (gchar *) walk->data); + } + GST_DEBUG_OBJECT (feature, "saved %d interfaces %d pad templates", + ef->ninterfaces, ef->npadtemplates); + + /* save uritypes */ + if (GST_URI_TYPE_IS_VALID (factory->uri_type)) { + if (factory->uri_protocols && *factory->uri_protocols) { + GstRegistryChunk *subchk; + gchar **protocol; + + subchk = + gst_registry_chunks_make_data (&factory->uri_type, + sizeof (factory->uri_type)); + subchk->flags = GST_REGISTRY_CHUNK_FLAG_CONST; + + protocol = factory->uri_protocols; + while (*protocol) { + gst_registry_chunks_save_const_string (list, *protocol++); + ef->nuriprotocols++; + } + *list = g_list_prepend (*list, subchk); + GST_DEBUG_OBJECT (feature, "Saved %d UriTypes", ef->nuriprotocols); + } else { + g_warning ("GStreamer feature '%s' is URI handler but does not provide" + " any protocols it can handle", GST_OBJECT_NAME (feature)); + } + } + + /* save pad-templates */ + for (walk = factory->staticpadtemplates; walk; + walk = g_list_next (walk), ef->npadtemplates++) { + GstStaticPadTemplate *template = walk->data; + + if (!gst_registry_chunks_save_pad_template (list, template)) { + GST_ERROR_OBJECT (feature, "Can't fill pad template, aborting."); + goto fail; + } + } + + /* pack element metadata strings */ + gst_registry_chunks_save_string (list, + gst_structure_to_string (factory->metadata)); + } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { + GstRegistryChunkTypeFindFactory *tff; + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature); + gchar *str; + + /* Initialize with zeroes because of struct padding and + * valgrind complaining about copying unitialized memory + */ + tff = g_slice_new0 (GstRegistryChunkTypeFindFactory); + pf_size = sizeof (GstRegistryChunkTypeFindFactory); + chk = gst_registry_chunks_make_data (tff, pf_size); + tff->nextensions = 0; + pf = (GstRegistryChunkPluginFeature *) tff; + + /* save extensions */ + if (factory->extensions) { + while (factory->extensions[tff->nextensions]) { + gst_registry_chunks_save_const_string (list, + factory->extensions[tff->nextensions++]); + } + } + GST_DEBUG_OBJECT (feature, "saved %d extensions", tff->nextensions); + /* save caps */ + if (factory->caps) { + GstCaps *fcaps = gst_caps_ref (factory->caps); + /* we simplify the caps before saving. This is a lot faster + * when loading them later on */ + fcaps = gst_caps_simplify (fcaps); + str = gst_caps_to_string (fcaps); + gst_caps_unref (fcaps); + + gst_registry_chunks_save_string (list, str); + } else { + gst_registry_chunks_save_const_string (list, ""); + } + } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) { + GstRegistryChunkDeviceProviderFactory *tff; + GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature); + + /* Initialize with zeroes because of struct padding and + * valgrind complaining about copying unitialized memory + */ + tff = g_slice_new0 (GstRegistryChunkDeviceProviderFactory); + chk = + gst_registry_chunks_make_data (tff, + sizeof (GstRegistryChunkDeviceProviderFactory)); + pf = (GstRegistryChunkPluginFeature *) tff; + + + /* pack element metadata strings */ + gst_registry_chunks_save_string (list, + gst_structure_to_string (factory->metadata)); + } else if (GST_IS_TRACER_FACTORY (feature)) { + /* Initialize with zeroes because of struct padding and + * valgrind complaining about copying unitialized memory + */ + pf = g_slice_new0 (GstRegistryChunkPluginFeature); + pf_size = sizeof (GstRegistryChunkPluginFeature); + chk = gst_registry_chunks_make_data (pf, pf_size); + } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) { + GstRegistryChunkDynamicTypeFactory *tmp; + + tmp = g_slice_new0 (GstRegistryChunkDynamicTypeFactory); + chk = + gst_registry_chunks_make_data (tmp, + sizeof (GstRegistryChunkDynamicTypeFactory)); + pf = (GstRegistryChunkPluginFeature *) tmp; + } else { + GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name); + } + + if (pf) { + pf->rank = feature->rank; + *list = g_list_prepend (*list, chk); + + /* pack plugin feature strings */ + gst_registry_chunks_save_const_string (list, GST_OBJECT_NAME (feature)); + gst_registry_chunks_save_const_string (list, (gchar *) type_name); + + return TRUE; + } + + /* Errors */ +fail: + g_slice_free (GstRegistryChunk, chk); + g_slice_free1 (pf_size, pf); + return FALSE; +} + +static gboolean +gst_registry_chunks_save_plugin_dep (GList ** list, GstPluginDep * dep) +{ + GstRegistryChunkDep *ed; + GstRegistryChunk *chk; + gchar **s; + + ed = g_slice_new (GstRegistryChunkDep); + chk = gst_registry_chunks_make_data (ed, sizeof (GstRegistryChunkDep)); + + ed->flags = dep->flags; + ed->n_env_vars = 0; + ed->n_paths = 0; + ed->n_names = 0; + + ed->env_hash = dep->env_hash; + ed->stat_hash = dep->stat_hash; + + for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars) + gst_registry_chunks_save_string (list, g_strdup (*s)); + + for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths) + gst_registry_chunks_save_string (list, g_strdup (*s)); + + for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names) + gst_registry_chunks_save_string (list, g_strdup (*s)); + + *list = g_list_prepend (*list, chk); + + GST_LOG ("Saved external plugin dependency"); + return TRUE; +} + +/* + * _priv_gst_registry_chunks_save_plugin: + * + * Adapt a GstPlugin to our GstRegistryChunkPluginElement structure, and + * prepend it as a GstRegistryChunk in the provided list. + * + */ +gboolean +_priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry, + GstPlugin * plugin) +{ + GstRegistryChunkPluginElement *pe; + GstRegistryChunk *chk; + GList *plugin_features = NULL; + GList *walk; + + pe = g_slice_new (GstRegistryChunkPluginElement); + chk = + gst_registry_chunks_make_data (pe, + sizeof (GstRegistryChunkPluginElement)); + + pe->file_size = plugin->file_size; + pe->file_mtime = plugin->file_mtime; + pe->nfeatures = 0; + pe->n_deps = 0; + + /* pack external deps */ + for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) { + if (!gst_registry_chunks_save_plugin_dep (list, walk->data)) { + GST_ERROR ("Could not save external plugin dependency, aborting."); + goto fail; + } + ++pe->n_deps; + } + + /* pack plugin features */ + plugin_features = + gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name); + for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) { + GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data); + + if (!gst_registry_chunks_save_feature (list, feature)) { + GST_ERROR ("Can't fill plugin feature, aborting."); + goto fail; + } + } + + gst_plugin_feature_list_free (plugin_features); + + /* pack cache data */ + if (plugin->priv->cache_data) { + gchar *cache_str = gst_structure_to_string (plugin->priv->cache_data); + gst_registry_chunks_save_string (list, cache_str); + } else { + gst_registry_chunks_save_const_string (list, ""); + } + + /* pack plugin element strings */ + gst_registry_chunks_save_const_string (list, + (plugin->desc.release_datetime) ? plugin->desc.release_datetime : ""); + gst_registry_chunks_save_const_string (list, plugin->desc.origin); + gst_registry_chunks_save_const_string (list, plugin->desc.package); + gst_registry_chunks_save_const_string (list, plugin->desc.source); + gst_registry_chunks_save_const_string (list, plugin->desc.license); + gst_registry_chunks_save_const_string (list, plugin->desc.version); + gst_registry_chunks_save_const_string (list, plugin->filename); + gst_registry_chunks_save_const_string (list, plugin->desc.description); + gst_registry_chunks_save_const_string (list, plugin->desc.name); + + *list = g_list_prepend (*list, chk); + + GST_DEBUG ("Found %d features in plugin \"%s\"", pe->nfeatures, + plugin->desc.name); + return TRUE; + + /* Errors */ +fail: + gst_plugin_feature_list_free (plugin_features); + g_slice_free (GstRegistryChunk, chk); + g_slice_free (GstRegistryChunkPluginElement, pe); + return FALSE; +} + +/* + * gst_registry_chunks_load_pad_template: + * + * Make a new GstStaticPadTemplate from current GstRegistryChunkPadTemplate + * structure. + * + * Returns: new GstStaticPadTemplate + */ +static gboolean +gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in, + gchar * end) +{ + GstRegistryChunkPadTemplate *pt; + GstStaticPadTemplate *template = NULL; + + align (*in); + GST_DEBUG ("Reading/casting for GstRegistryChunkPadTemplate at address %p", + *in); + unpack_element (*in, pt, GstRegistryChunkPadTemplate, end, fail); + + template = g_slice_new (GstStaticPadTemplate); + template->presence = pt->presence; + template->direction = (GstPadDirection) pt->direction; + template->static_caps.caps = NULL; + + /* unpack pad template strings */ + unpack_const_string (*in, template->name_template, end, fail); + unpack_const_string (*in, template->static_caps.string, end, fail); + + __gst_element_factory_add_static_pad_template (factory, template); + GST_DEBUG ("Added pad_template %s", template->name_template); + + return TRUE; +fail: + GST_INFO ("Reading pad template failed"); + if (template) + g_slice_free (GstStaticPadTemplate, template); + return FALSE; +} + +/* + * gst_registry_chunks_load_feature: + * + * Make a new GstPluginFeature from current binary plugin feature structure + * + * Returns: new GstPluginFeature + */ +static gboolean +gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in, + gchar * end, GstPlugin * plugin) +{ + GstRegistryChunkPluginFeature *pf = NULL; + GstPluginFeature *feature = NULL; + const gchar *const_str, *type_name; + const gchar *feature_name; + const gchar *plugin_name; + gchar *str; + GType type; + guint i; + + plugin_name = plugin->desc.name; + + /* unpack plugin feature strings */ + unpack_string_nocopy (*in, type_name, end, fail); + + if (G_UNLIKELY (!type_name)) { + GST_ERROR ("No feature type name"); + return FALSE; + } + + /* unpack more plugin feature strings */ + unpack_string_nocopy (*in, feature_name, end, fail); + + GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name, + feature_name, type_name); + + if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) { + GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name, + plugin_name); + return FALSE; + } + if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) { + GST_ERROR ("Can't create feature from type"); + return FALSE; + } + gst_plugin_feature_set_name (feature, feature_name); + + if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) { + GST_ERROR ("typename : '%s' is not a plugin feature", type_name); + goto fail; + } + + if (GST_IS_ELEMENT_FACTORY (feature)) { + GstRegistryChunkElementFactory *ef; + guint n; + GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature); + gchar *str; + const gchar *meta_data_str; + + align (*in); + GST_LOG ("Reading/casting for GstRegistryChunkElementFactory at address %p", + *in); + unpack_element (*in, ef, GstRegistryChunkElementFactory, end, fail); + pf = (GstRegistryChunkPluginFeature *) ef; + + /* unpack element factory strings */ + unpack_string_nocopy (*in, meta_data_str, end, fail); + if (meta_data_str && *meta_data_str) { + factory->metadata = gst_structure_from_string (meta_data_str, NULL); + if (!factory->metadata) { + GST_ERROR + ("Error when trying to deserialize structure for metadata '%s'", + meta_data_str); + goto fail; + } + } + n = ef->npadtemplates; + GST_DEBUG ("Element factory : npadtemplates=%d", n); + + /* load pad templates */ + for (i = 0; i < n; i++) { + if (G_UNLIKELY (!gst_registry_chunks_load_pad_template (factory, in, + end))) { + GST_ERROR ("Error while loading binary pad template"); + goto fail; + } + } + + /* load uritypes */ + if (G_UNLIKELY ((n = ef->nuriprotocols))) { + GST_DEBUG ("Reading %d UriTypes at address %p", n, *in); + + align (*in); + factory->uri_type = *((guint *) * in); + *in += sizeof (factory->uri_type); + /*unpack_element(*in, &factory->uri_type, factory->uri_type, end, fail); */ + + factory->uri_protocols = g_new0 (gchar *, n + 1); + for (i = 0; i < n; i++) { + unpack_string (*in, str, end, fail); + factory->uri_protocols[i] = str; + } + } + /* load interfaces */ + if (G_UNLIKELY ((n = ef->ninterfaces))) { + GST_DEBUG ("Reading %d Interfaces at address %p", n, *in); + for (i = 0; i < n; i++) { + unpack_string_nocopy (*in, const_str, end, fail); + __gst_element_factory_add_interface (factory, const_str); + } + } + } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { + GstRegistryChunkTypeFindFactory *tff; + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature); + + align (*in); + GST_DEBUG + ("Reading/casting for GstRegistryChunkPluginFeature at address %p", + *in); + unpack_element (*in, tff, GstRegistryChunkTypeFindFactory, end, fail); + pf = (GstRegistryChunkPluginFeature *) tff; + + /* load typefinder caps */ + unpack_string_nocopy (*in, const_str, end, fail); + if (const_str != NULL && *const_str != '\0') + factory->caps = gst_caps_from_string (const_str); + else + factory->caps = NULL; + + /* load extensions */ + if (tff->nextensions) { + GST_DEBUG ("Reading %d Typefind extensions at address %p", + tff->nextensions, *in); + factory->extensions = g_new0 (gchar *, tff->nextensions + 1); + /* unpack in reverse order to maintain the correct order */ + for (i = tff->nextensions; i > 0; i--) { + unpack_string (*in, str, end, fail); + factory->extensions[i - 1] = str; + } + } + } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) { + GstRegistryChunkDeviceProviderFactory *dmf; + GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature); + const gchar *meta_data_str; + + align (*in); + GST_DEBUG + ("Reading/casting for GstRegistryChunkPluginFeature at address %p", + *in); + + unpack_element (*in, dmf, GstRegistryChunkDeviceProviderFactory, end, fail); + + pf = (GstRegistryChunkPluginFeature *) dmf; + + /* unpack element factory strings */ + unpack_string_nocopy (*in, meta_data_str, end, fail); + if (meta_data_str && *meta_data_str) { + factory->metadata = gst_structure_from_string (meta_data_str, NULL); + if (!factory->metadata) { + GST_ERROR + ("Error when trying to deserialize structure for metadata '%s'", + meta_data_str); + goto fail; + } + } + } else if (GST_IS_TRACER_FACTORY (feature)) { + align (*in); + GST_DEBUG + ("Reading/casting for GstRegistryChunkPluginFeature at address %p", + *in); + unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail); + } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) { + GstRegistryChunkDynamicTypeFactory *tmp; + + align (*in); + unpack_element (*in, tmp, GstRegistryChunkDynamicTypeFactory, end, fail); + + pf = (GstRegistryChunkPluginFeature *) tmp; + } else { + GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature)); + goto fail; + } + + feature->rank = pf->rank; + + feature->plugin_name = plugin_name; + feature->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & feature->plugin); + + gst_registry_add_feature (registry, feature); + GST_DEBUG ("Added feature %s, plugin %p %s", GST_OBJECT_NAME (feature), + plugin, plugin_name); + + return TRUE; + + /* Errors */ +fail: + GST_INFO ("Reading plugin feature failed"); + if (feature) { + if (GST_IS_OBJECT (feature)) + gst_object_unref (feature); + else + g_object_unref (feature); + } + return FALSE; +} + +static gchar ** +gst_registry_chunks_load_plugin_dep_strv (gchar ** in, gchar * end, guint n) +{ + gchar **arr; + + if (n == 0) + return NULL; + + arr = g_new0 (gchar *, n + 1); + while (n > 0) { + unpack_string (*in, arr[n - 1], end, fail); + --n; + } + return arr; +fail: + GST_INFO ("Reading plugin dependency strings failed"); + g_strfreev (arr); + return NULL; +} + +static gboolean +gst_registry_chunks_load_plugin_dep (GstPlugin * plugin, gchar ** in, + gchar * end) +{ + GstPluginDep *dep; + GstRegistryChunkDep *d; + gchar **s; + + align (*in); + GST_LOG_OBJECT (plugin, "Unpacking GstRegistryChunkDep from %p", *in); + unpack_element (*in, d, GstRegistryChunkDep, end, fail); + + dep = g_slice_new (GstPluginDep); + + dep->env_hash = d->env_hash; + dep->stat_hash = d->stat_hash; + + dep->flags = (GstPluginDependencyFlags) d->flags; + + dep->names = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_names); + dep->paths = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_paths); + dep->env_vars = + gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_env_vars); + + plugin->priv->deps = g_list_append (plugin->priv->deps, dep); + + GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: " + "env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash); + for (s = dep->env_vars; s != NULL && *s != NULL; ++s) + GST_LOG_OBJECT (plugin, " evar: %s", *s); + for (s = dep->paths; s != NULL && *s != NULL; ++s) + GST_LOG_OBJECT (plugin, " path: %s", *s); + for (s = dep->names; s != NULL && *s != NULL; ++s) + GST_LOG_OBJECT (plugin, " name: %s", *s); + + return TRUE; +fail: + GST_INFO ("Reading plugin dependency failed"); + return FALSE; +} + + +/* + * _priv_gst_registry_chunks_load_plugin: + * + * Make a new GstPlugin from current GstRegistryChunkPluginElement structure + * and add it to the GstRegistry. Return an offset to the next + * GstRegistryChunkPluginElement structure. + */ +gboolean +_priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in, + gchar * end, GstPlugin ** out_plugin) +{ +#ifndef GST_DISABLE_GST_DEBUG + gchar *start = *in; +#endif + GstRegistryChunkPluginElement *pe; + const gchar *cache_str = NULL; + GstPlugin *plugin = NULL; + guint i, n; + + align (*in); + GST_LOG ("Reading/casting for GstRegistryChunkPluginElement at address %p", + *in); + unpack_element (*in, pe, GstRegistryChunkPluginElement, end, fail); + + plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + + /* TODO: also set GST_PLUGIN_FLAG_CONST */ + GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_CACHED); + plugin->file_mtime = pe->file_mtime; + plugin->file_size = pe->file_size; + + /* unpack plugin element strings */ + unpack_const_string (*in, plugin->desc.name, end, fail); + unpack_const_string (*in, plugin->desc.description, end, fail); + unpack_string (*in, plugin->filename, end, fail); + unpack_const_string (*in, plugin->desc.version, end, fail); + unpack_const_string (*in, plugin->desc.license, end, fail); + unpack_const_string (*in, plugin->desc.source, end, fail); + unpack_const_string (*in, plugin->desc.package, end, fail); + unpack_const_string (*in, plugin->desc.origin, end, fail); + unpack_const_string (*in, plugin->desc.release_datetime, end, fail); + + GST_LOG ("read strings for name='%s'", plugin->desc.name); + GST_LOG (" desc.description='%s'", plugin->desc.description); + GST_LOG (" filename='%s'", plugin->filename); + GST_LOG (" desc.version='%s'", plugin->desc.version); + GST_LOG (" desc.license='%s'", plugin->desc.license); + GST_LOG (" desc.source='%s'", plugin->desc.source); + GST_LOG (" desc.package='%s'", plugin->desc.package); + GST_LOG (" desc.origin='%s'", plugin->desc.origin); + GST_LOG (" desc.datetime=%s", plugin->desc.release_datetime); + + if (plugin->desc.release_datetime[0] == '\0') + plugin->desc.release_datetime = NULL; + + /* unpack cache data */ + unpack_string_nocopy (*in, cache_str, end, fail); + if (cache_str != NULL && *cache_str != '\0') + plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL); + + /* If the license string is 'BLACKLIST', mark this as a blacklisted + * plugin */ + if (strcmp (plugin->desc.license, "BLACKLIST") == 0) + GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED); + + plugin->basename = g_path_get_basename (plugin->filename); + + /* Takes ownership of plugin */ + gst_registry_add_plugin (registry, plugin); + n = pe->nfeatures; + GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry", + plugin->desc.name, n); + + /* Load plugin features */ + for (i = 0; i < n; i++) { + if (G_UNLIKELY (!gst_registry_chunks_load_feature (registry, in, end, + plugin))) { + GST_ERROR ("Error while loading binary feature for plugin '%s'", + GST_STR_NULL (plugin->desc.name)); + gst_registry_remove_plugin (registry, plugin); + goto fail; + } + } + + /* Load external plugin dependencies */ + for (i = 0; i < pe->n_deps; ++i) { + if (G_UNLIKELY (!gst_registry_chunks_load_plugin_dep (plugin, in, end))) { + GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency " + "for plugin '%s'", GST_STR_NULL (plugin->desc.name)); + gst_registry_remove_plugin (registry, plugin); + goto fail; + } + } + + if (out_plugin) + *out_plugin = plugin; + + return TRUE; + + /* Errors */ +fail: + GST_INFO ("Reading plugin failed after %u bytes", (guint) (end - start)); + return FALSE; +} + +void +_priv_gst_registry_chunks_save_global_header (GList ** list, + GstRegistry * registry, guint32 filter_env_hash) +{ + GstRegistryChunkGlobalHeader *hdr; + GstRegistryChunk *chk; + + hdr = g_slice_new (GstRegistryChunkGlobalHeader); + chk = gst_registry_chunks_make_data (hdr, + sizeof (GstRegistryChunkGlobalHeader)); + + hdr->filter_env_hash = filter_env_hash; + + *list = g_list_prepend (*list, chk); + + GST_LOG ("Saved global header (filter_env_hash=0x%08x)", filter_env_hash); +} + +gboolean +_priv_gst_registry_chunks_load_global_header (GstRegistry * registry, + gchar ** in, gchar * end, guint32 * filter_env_hash) +{ + GstRegistryChunkGlobalHeader *hdr; + + align (*in); + GST_LOG ("Reading/casting for GstRegistryChunkGlobalHeader at %p", *in); + unpack_element (*in, hdr, GstRegistryChunkGlobalHeader, end, fail); + *filter_env_hash = hdr->filter_env_hash; + return TRUE; + + /* Errors */ +fail: + GST_WARNING ("Reading global header failed"); + return FALSE; +} diff --git a/gst/gstregistrychunks.h b/gst/gstregistrychunks.h new file mode 100644 index 0000000..e7b77b3 --- /dev/null +++ b/gst/gstregistrychunks.h @@ -0,0 +1,191 @@ +/* GStreamer + * Copyright (C) 2006 Josep Torra + * Copyright (C) 2006 Mathieu Garcia + * Copyright (C) 2006 Stefan Kost + * + * gstregistrybinary.h: Header for registry 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __GST_REGISTRYCHUNKS_H__ +#define __GST_REGISTRYCHUNKS_H__ + +#include +#include + +/* + * we reference strings directly from the plugins and in this case set CONST to + * avoid freeing them. If g_free() should be used, the MALLOC flag is set, + * otherwise g_slice_free1() will be used! + */ +enum { + GST_REGISTRY_CHUNK_FLAG_NONE = 0, + GST_REGISTRY_CHUNK_FLAG_CONST = 1, + GST_REGISTRY_CHUNK_FLAG_MALLOC = 2, +}; + +/* + * GstRegistryChunk: + * + * Header for binary blobs + */ +typedef struct _GstRegistryChunk +{ + gpointer data; + guint size; + guint flags; + gboolean align; +} GstRegistryChunk; + +typedef struct _GstRegistryChunkGlobalHeader +{ + guint32 filter_env_hash; +} GstRegistryChunkGlobalHeader; + +/* + * GstRegistryChunkPluginElement: + * + * @n_deps: Says how many dependency structures follows. + * + * @nfeatures: says how many binary plugin feature structures we will have + * right after the structure itself. + * + * A structure containing (staticely) every information needed for a plugin + */ + +typedef struct _GstRegistryChunkPluginElement +{ + gulong file_size; + gulong file_mtime; + + guint n_deps; + + guint nfeatures; +} GstRegistryChunkPluginElement; + +/* GstRegistryChunkDep: + */ +typedef struct _GstRegistryChunkDep +{ + guint flags; + guint n_env_vars; + guint n_paths; + guint n_names; + + guint env_hash; + guint stat_hash; +} GstRegistryChunkDep; + +/* + * GstRegistryChunkPluginFeature: + * @rank: rank of the feature + * + * A structure containing the plugin features + */ +typedef struct _GstRegistryChunkPluginFeature +{ + gulong rank; +} GstRegistryChunkPluginFeature; + +/* + * GstRegistryChunkElementFactory: + * @npadtemplates: stores the number of GstRegistryChunkPadTemplate structures + * following the structure + * @ninterfaces: stores the number of interface names following the structure + * @nuriprotocols: stores the number of protocol strings following the structure + * + * A structure containing the element factory fields + */ +typedef struct _GstRegistryChunkElementFactory +{ + GstRegistryChunkPluginFeature plugin_feature; + + guint npadtemplates; + guint ninterfaces; + guint nuriprotocols; +} GstRegistryChunkElementFactory; + +/* + * GstRegistryChunkTypeFindFactory: + * @nextensions: stores the number of typefind extensions + * + * A structure containing the type find factory fields + */ +typedef struct _GstRegistryChunkTypeFindFactory +{ + GstRegistryChunkPluginFeature plugin_feature; + + guint nextensions; +} GstRegistryChunkTypeFindFactory; + +/* + * GstRegistryChunkDeviceProviderFactory: + * + * A structure containing the device provider factory fields + */ +typedef struct _GstRegistryChunkDeviceProviderFactory +{ + GstRegistryChunkPluginFeature plugin_feature; + +} GstRegistryChunkDeviceProviderFactory; + +/* + * GstRegistryChunkDynamicTypeFactory: + * + * A structure containing the dynamic type factory flags field + */ +typedef struct _GstRegistryChunkDynamicTypeFactory +{ + GstRegistryChunkPluginFeature plugin_feature; + + guint type_flags; +} GstRegistryChunkDynamicTypeFactory; + +/* + * GstRegistryChunkPadTemplate: + * + * A structure containing the static pad templates of a plugin feature + */ +typedef struct _GstRegistryChunkPadTemplate +{ + guint direction; /* Either 0:"sink" or 1:"src" */ + GstPadPresence presence; +} GstRegistryChunkPadTemplate; + +G_BEGIN_DECLS + +gboolean +_priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry, + GstPlugin * plugin); + +gboolean +_priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in, + gchar *end, GstPlugin **out_plugin); + +void +_priv_gst_registry_chunks_save_global_header (GList ** list, + GstRegistry * registry, guint32 filter_env_hash); + +gboolean +_priv_gst_registry_chunks_load_global_header (GstRegistry * registry, + gchar ** in, gchar *end, guint32 * filter_env_hash); + +void +_priv_gst_registry_chunk_free (GstRegistryChunk *chunk); + +G_END_DECLS + +#endif /* __GST_REGISTRYCHUNKS_H__ */ diff --git a/gst/gstsample.c b/gst/gstsample.c new file mode 100644 index 0000000..6479048 --- /dev/null +++ b/gst/gstsample.c @@ -0,0 +1,262 @@ +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstsample.c: media sample + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstsample + * @title: GstSample + * @short_description: A media sample + * @see_also: #GstBuffer, #GstCaps, #GstSegment + * + * A #GstSample is a small object containing data, a type, timing and + * extra arbitrary information. + */ +#include "gst_private.h" + +#include "gstsample.h" + +GST_DEBUG_CATEGORY_STATIC (gst_sample_debug); +#define GST_CAT_DEFAULT gst_sample_debug + +struct _GstSample +{ + GstMiniObject mini_object; + + GstBuffer *buffer; + GstCaps *caps; + GstSegment segment; + GstStructure *info; + GstBufferList *buffer_list; +}; + +GType _gst_sample_type = 0; + +GST_DEFINE_MINI_OBJECT_TYPE (GstSample, gst_sample); + +void +_priv_gst_sample_initialize (void) +{ + _gst_sample_type = gst_sample_get_type (); + + GST_DEBUG_CATEGORY_INIT (gst_sample_debug, "sample", 0, "GstSample debug"); +} + +static GstSample * +_gst_sample_copy (GstSample * sample) +{ + GstSample *copy; + + copy = gst_sample_new (sample->buffer, sample->caps, &sample->segment, + (sample->info) ? gst_structure_copy (sample->info) : NULL); + + if (sample->buffer_list) + copy->buffer_list = (GstBufferList *) + gst_mini_object_ref (GST_MINI_OBJECT_CAST (sample->buffer_list)); + + return copy; +} + +static void +_gst_sample_free (GstSample * sample) +{ + GST_LOG ("free %p", sample); + + if (sample->buffer) + gst_buffer_unref (sample->buffer); + if (sample->caps) + gst_caps_unref (sample->caps); + if (sample->info) { + gst_structure_set_parent_refcount (sample->info, NULL); + gst_structure_free (sample->info); + } + if (sample->buffer_list) + gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample->buffer_list)); + + g_slice_free1 (sizeof (GstSample), sample); +} + +/** + * gst_sample_new: + * @buffer: (transfer none) (allow-none): a #GstBuffer, or %NULL + * @caps: (transfer none) (allow-none): a #GstCaps, or %NULL + * @segment: (transfer none) (allow-none): a #GstSegment, or %NULL + * @info: (transfer full) (allow-none): a #GstStructure, or %NULL + * + * Create a new #GstSample with the provided details. + * + * Free-function: gst_sample_unref + * + * Returns: (transfer full): the new #GstSample. gst_sample_unref() + * after usage. + */ +GstSample * +gst_sample_new (GstBuffer * buffer, GstCaps * caps, const GstSegment * segment, + GstStructure * info) +{ + GstSample *sample; + + sample = g_slice_new0 (GstSample); + + GST_LOG ("new %p", sample); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (sample), 0, _gst_sample_type, + (GstMiniObjectCopyFunction) _gst_sample_copy, NULL, + (GstMiniObjectFreeFunction) _gst_sample_free); + + sample->buffer = buffer ? gst_buffer_ref (buffer) : NULL; + sample->caps = caps ? gst_caps_ref (caps) : NULL; + + if (segment) + gst_segment_copy_into (segment, &sample->segment); + else + gst_segment_init (&sample->segment, GST_FORMAT_TIME); + + if (info) { + if (!gst_structure_set_parent_refcount (info, + &sample->mini_object.refcount)) + goto had_parent; + + sample->info = info; + } + return sample; + + /* ERRORS */ +had_parent: + { + gst_sample_unref (sample); + g_warning ("structure is already owned by another object"); + return NULL; + } +} + +/** + * gst_sample_get_buffer: + * @sample: a #GstSample + * + * Get the buffer associated with @sample + * + * Returns: (transfer none) (nullable): the buffer of @sample or %NULL + * when there is no buffer. The buffer remains valid as long as + * @sample is valid. If you need to hold on to it for longer than + * that, take a ref to the buffer with gst_buffer_ref(). + */ +GstBuffer * +gst_sample_get_buffer (GstSample * sample) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL); + + return sample->buffer; +} + +/** + * gst_sample_get_caps: + * @sample: a #GstSample + * + * Get the caps associated with @sample + * + * Returns: (transfer none) (nullable): the caps of @sample or %NULL + * when there is no caps. The caps remain valid as long as @sample is + * valid. If you need to hold on to the caps for longer than that, + * take a ref to the caps with gst_caps_ref(). + */ +GstCaps * +gst_sample_get_caps (GstSample * sample) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL); + + return sample->caps; +} + +/** + * gst_sample_get_segment: + * @sample: a #GstSample + * + * Get the segment associated with @sample + * + * Returns: (transfer none): the segment of @sample. + * The segment remains valid as long as @sample is valid. + */ +GstSegment * +gst_sample_get_segment (GstSample * sample) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL); + + return &sample->segment; +} + +/** + * gst_sample_get_info: + * @sample: a #GstSample + * + * Get extra information associated with @sample. + * + * Returns: (transfer none) (nullable): the extra info of @sample. + * The info remains valid as long as @sample is valid. + */ +const GstStructure * +gst_sample_get_info (GstSample * sample) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL); + + return sample->info; +} + +/** + * gst_sample_get_buffer_list: + * @sample: a #GstSample + * + * Get the buffer list associated with @sample + * + * Returns: (transfer none) (nullable): the buffer list of @sample or %NULL + * when there is no buffer list. The buffer list remains valid as long as + * @sample is valid. If you need to hold on to it for longer than + * that, take a ref to the buffer list with gst_mini_object_ref (). + * + * Since: 1.6 + */ +GstBufferList * +gst_sample_get_buffer_list (GstSample * sample) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL); + + return sample->buffer_list; +} + +/** + * gst_sample_set_buffer_list: + * @sample: a #GstSample + * @buffer_list: a #GstBufferList + * + * Set the buffer list associated with @sample + * + * Since: 1.6 + */ +void +gst_sample_set_buffer_list (GstSample * sample, GstBufferList * buffer_list) +{ + GstBufferList *old = NULL; + g_return_if_fail (GST_IS_SAMPLE (sample)); + old = sample->buffer_list; + sample->buffer_list = (GstBufferList *) + gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer_list)); + + if (old) + gst_mini_object_unref (GST_MINI_OBJECT_CAST (old)); +} diff --git a/gst/gstsample.h b/gst/gstsample.h new file mode 100644 index 0000000..84c6ef1 --- /dev/null +++ b/gst/gstsample.h @@ -0,0 +1,159 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstsample.h: Header for GstSample 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_SAMPLE_H__ +#define __GST_SAMPLE_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_sample_type; + +#define GST_TYPE_SAMPLE (_gst_sample_type) +#define GST_IS_SAMPLE(obj) (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_SAMPLE)) +#define GST_SAMPLE_CAST(obj) ((GstSample *)obj) +#define GST_SAMPLE(obj) (GST_SAMPLE_CAST(obj)) + +/** + * GstSample: + * + * The opaque structure of a #GstSample. A sample contains a typed memory + * block and the associated timing information. It is mainly used to + * exchange buffers with an application. + */ +typedef struct _GstSample GstSample; + +GST_API +GType gst_sample_get_type (void); + +/* allocation */ + +GST_API +GstSample * gst_sample_new (GstBuffer *buffer, + GstCaps *caps, + const GstSegment *segment, + GstStructure *info); +GST_API +GstBuffer * gst_sample_get_buffer (GstSample *sample); + +GST_API +GstCaps * gst_sample_get_caps (GstSample *sample); + +GST_API +GstSegment * gst_sample_get_segment (GstSample *sample); + +GST_API +const GstStructure * gst_sample_get_info (GstSample *sample); + +GST_API +GstBufferList * gst_sample_get_buffer_list (GstSample *sample); + +GST_API +void gst_sample_set_buffer_list (GstSample *sample, GstBufferList *buffer_list); + +/* refcounting */ +/** + * gst_sample_ref: + * @sample: a #GstSample + * + * Increases the refcount of the given sample by one. + * + * Returns: (transfer full): @sample + */ +static inline GstSample * +gst_sample_ref (GstSample * sample) +{ + return GST_SAMPLE_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST ( + sample))); +} + +/** + * gst_sample_unref: + * @sample: (transfer full): a #GstSample + * + * Decreases the refcount of the sample. If the refcount reaches 0, the + * sample will be freed. + */ +static inline void +gst_sample_unref (GstSample * sample) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample)); +} + +/* copy sample */ +/** + * gst_sample_copy: + * @buf: a #GstSample. + * + * Create a copy of the given sample. This will also make a newly allocated + * copy of the data the source sample contains. + * + * Returns: (transfer full): a new copy of @buf. + * + * Since: 1.2 + */ +static inline GstSample * +gst_sample_copy (const GstSample * buf) +{ + return GST_SAMPLE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf))); +} + +/** + * gst_value_set_sample: + * @v: a #GValue to receive the data + * @b: (transfer none): a #GstSample to assign to the GstValue + * + * Sets @b as the value of @v. Caller retains reference to sample. + */ +#define gst_value_set_sample(v,b) g_value_set_boxed((v),(b)) +/** + * gst_value_take_sample: + * @v: a #GValue to receive the data + * @b: (transfer full): a #GstSample to assign to the GstValue + * + * Sets @b as the value of @v. Caller gives away reference to sample. + */ +#define gst_value_take_sample(v,b) g_value_take_boxed(v,(b)) +/** + * gst_value_get_sample: + * @v: a #GValue to query + * + * Receives a #GstSample as the value of @v. Does not return a reference to + * the sample, so the pointer is only valid for as long as the caller owns + * a reference to @v. + * + * Returns: (transfer none): sample + */ +#define gst_value_get_sample(v) GST_SAMPLE_CAST (g_value_get_boxed(v)) + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSample, gst_sample_unref) +#endif + +G_END_DECLS + +#endif /* __GST_SAMPLE_H__ */ diff --git a/gst/gstsegment.c b/gst/gstsegment.c new file mode 100644 index 0000000..5248c05 --- /dev/null +++ b/gst/gstsegment.c @@ -0,0 +1,1231 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstsegment.c: GstSegment subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "gst_private.h" + +#include + +#include "gstutils.h" +#include "gstsegment.h" + +/** + * SECTION:gstsegment + * @title: GstSegment + * @short_description: Structure describing the configured region of interest + * in a media file. + * @see_also: #GstEvent + * + * This helper structure holds the relevant values for tracking the region of + * interest in a media file, called a segment. + * + * The structure can be used for two purposes: + * + * * performing seeks (handling seek events) + * * tracking playback regions (handling newsegment events) + * + * The segment is usually configured by the application with a seek event which + * is propagated upstream and eventually handled by an element that performs the seek. + * + * The configured segment is then propagated back downstream with a newsegment event. + * This information is then used to clip media to the segment boundaries. + * + * A segment structure is initialized with gst_segment_init(), which takes a #GstFormat + * that will be used as the format of the segment values. The segment will be configured + * with a start value of 0 and a stop/duration of -1, which is undefined. The default + * rate and applied_rate is 1.0. + * + * The public duration field contains the duration of the segment. When using + * the segment for seeking, the start and time members should normally be left + * to their default 0 value. The stop position is left to -1 unless explicitly + * configured to a different value after a seek event. + * + * The current position in the segment should be set by changing the position + * member in the structure. + * + * For elements that perform seeks, the current segment should be updated with the + * gst_segment_do_seek() and the values from the seek event. This method will update + * all the segment fields. The position field will contain the new playback position. + * If the start_type was different from GST_SEEK_TYPE_NONE, playback continues from + * the position position, possibly with updated flags or rate. + * + * For elements that want to use #GstSegment to track the playback region, + * update the segment fields with the information from the newsegment event. + * The gst_segment_clip() method can be used to check and clip + * the media data to the segment boundaries. + * + * For elements that want to synchronize to the pipeline clock, gst_segment_to_running_time() + * can be used to convert a timestamp to a value that can be used to synchronize + * to the clock. This function takes into account the base as well as + * any rate or applied_rate conversions. + * + * For elements that need to perform operations on media data in stream_time, + * gst_segment_to_stream_time() can be used to convert a timestamp and the segment + * info to stream time (which is always between 0 and the duration of the stream). + */ + +/* FIXME 2.0: remove unused format parameter. + * Most of the methods in gstsegment.c take and extra GstFormat format, just to + * verify segment->format == format. + * See https://bugzilla.gnome.org/show_bug.cgi?id=788979 + */ + +/** + * gst_segment_copy: + * @segment: (transfer none): a #GstSegment + * + * Create a copy of given @segment. + * + * Free-function: gst_segment_free + * + * Returns: (transfer full): a new #GstSegment, free with gst_segment_free(). + */ +GstSegment * +gst_segment_copy (const GstSegment * segment) +{ + GstSegment *result = NULL; + + if (segment) { + result = (GstSegment *) g_slice_copy (sizeof (GstSegment), segment); + } + return result; +} + +/** + * gst_segment_copy_into: + * @src: (transfer none): a #GstSegment + * @dest: (transfer none): a #GstSegment + * + * Copy the contents of @src into @dest. + */ +void +gst_segment_copy_into (const GstSegment * src, GstSegment * dest) +{ + memcpy (dest, src, sizeof (GstSegment)); +} + +G_DEFINE_BOXED_TYPE (GstSegment, gst_segment, + (GBoxedCopyFunc) gst_segment_copy, (GBoxedFreeFunc) gst_segment_free); + +/** + * gst_segment_new: + * + * Allocate a new #GstSegment structure and initialize it using + * gst_segment_init(). + * + * Free-function: gst_segment_free + * + * Returns: (transfer full): a new #GstSegment, free with gst_segment_free(). + */ +GstSegment * +gst_segment_new (void) +{ + GstSegment *result; + + result = g_slice_new0 (GstSegment); + gst_segment_init (result, GST_FORMAT_UNDEFINED); + + return result; +} + +/** + * gst_segment_free: + * @segment: (in) (transfer full): a #GstSegment + * + * Free the allocated segment @segment. + */ +void +gst_segment_free (GstSegment * segment) +{ + g_slice_free (GstSegment, segment); +} + +/** + * gst_segment_init: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * + * The start/position fields are set to 0 and the stop/duration + * fields are set to -1 (unknown). The default rate of 1.0 and no + * flags are set. + * + * Initialize @segment to its default values. + */ +void +gst_segment_init (GstSegment * segment, GstFormat format) +{ + g_return_if_fail (segment != NULL); + + segment->flags = GST_SEGMENT_FLAG_NONE; + segment->rate = 1.0; + segment->applied_rate = 1.0; + segment->format = format; + segment->base = 0; + segment->offset = 0; + segment->start = 0; + segment->stop = -1; + segment->time = 0; + segment->position = 0; + segment->duration = -1; +} + +/** + * gst_segment_do_seek: + * @segment: a #GstSegment structure. + * @rate: the rate of the segment. + * @format: the format of the segment. + * @flags: the segment flags for the segment + * @start_type: the seek method + * @start: the seek start value + * @stop_type: the seek method + * @stop: the seek stop value + * @update: (out) (allow-none): boolean holding whether position was updated. + * + * Update the segment structure with the field values of a seek event (see + * gst_event_new_seek()). + * + * After calling this method, the segment field position and time will + * contain the requested new position in the segment. The new requested + * position in the segment depends on @rate and @start_type and @stop_type. + * + * For positive @rate, the new position in the segment is the new @segment + * start field when it was updated with a @start_type different from + * #GST_SEEK_TYPE_NONE. If no update was performed on @segment start position + * (#GST_SEEK_TYPE_NONE), @start is ignored and @segment position is + * unmodified. + * + * For negative @rate, the new position in the segment is the new @segment + * stop field when it was updated with a @stop_type different from + * #GST_SEEK_TYPE_NONE. If no stop was previously configured in the segment, the + * duration of the segment will be used to update the stop position. + * If no update was performed on @segment stop position (#GST_SEEK_TYPE_NONE), + * @stop is ignored and @segment position is unmodified. + * + * The applied rate of the segment will be set to 1.0 by default. + * If the caller can apply a rate change, it should update @segment + * rate and applied_rate after calling this function. + * + * @update will be set to %TRUE if a seek should be performed to the segment + * position field. This field can be %FALSE if, for example, only the @rate + * has been changed but not the playback position. + * + * Returns: %TRUE if the seek could be performed. + */ +gboolean +gst_segment_do_seek (GstSegment * segment, gdouble rate, + GstFormat format, GstSeekFlags flags, + GstSeekType start_type, guint64 start, + GstSeekType stop_type, guint64 stop, gboolean * update) +{ + gboolean update_stop, update_start; + guint64 position, base; + + g_return_val_if_fail (rate != 0.0, FALSE); + g_return_val_if_fail (segment != NULL, FALSE); + g_return_val_if_fail (segment->format == format, FALSE); + + update_start = update_stop = TRUE; + + position = segment->position; + + /* segment->start is never invalid */ + switch (start_type) { + case GST_SEEK_TYPE_NONE: + /* no update to segment, take previous start */ + start = segment->start; + update_start = FALSE; + break; + case GST_SEEK_TYPE_SET: + /* start holds desired position, map -1 to the start */ + if (start == -1) + start = 0; + break; + case GST_SEEK_TYPE_END: + if (segment->duration != -1) { + /* add start to total length */ + start = segment->duration + start; + } else { + /* no update if duration unknown */ + start = segment->start; + update_start = FALSE; + } + break; + } + /* bring in sane range */ + if (segment->duration != -1) + start = MIN (start, segment->duration); + else + start = MAX ((gint64) start, 0); + + /* stop can be -1 if we have not configured a stop. */ + switch (stop_type) { + case GST_SEEK_TYPE_NONE: + stop = segment->stop; + update_stop = FALSE; + break; + case GST_SEEK_TYPE_SET: + /* stop holds required value */ + break; + case GST_SEEK_TYPE_END: + if (segment->duration != -1) { + stop = segment->duration + stop; + } else { + stop = segment->stop; + update_stop = FALSE; + } + break; + } + + /* if we have a valid stop time, make sure it is clipped */ + if (stop != -1) { + if (segment->duration != -1) + stop = CLAMP ((gint64) stop, 0, (gint64) segment->duration); + else + stop = MAX ((gint64) stop, 0); + } + + /* we can't have stop before start */ + if (stop != -1) { + if (start > stop) { + GST_WARNING ("segment update failed: start(%" G_GUINT64_FORMAT + ") > stop(%" G_GUINT64_FORMAT ")", start, stop); + g_return_val_if_fail (start <= stop, FALSE); + return FALSE; + } + } + + if (flags & GST_SEEK_FLAG_FLUSH) { + /* flush resets the running_time */ + base = 0; + } else { + /* make sure the position is inside the segment start/stop */ + position = CLAMP (position, segment->start, segment->stop); + + /* remember the elapsed time */ + base = gst_segment_to_running_time (segment, format, position); + GST_DEBUG ("updated segment.base: %" G_GUINT64_FORMAT, base); + } + + if (update_start && rate > 0.0) { + position = start; + } + if (update_stop && rate < 0.0) { + if (stop != -1) + position = stop; + else { + if (segment->duration != -1) + position = segment->duration; + else + position = 0; + } + } + + /* set update arg to reflect update of position */ + if (update) + *update = position != segment->position; + + /* update new values */ + /* be explicit about our GstSeekFlag -> GstSegmentFlag conversion */ + segment->flags = GST_SEGMENT_FLAG_NONE; + if ((flags & GST_SEEK_FLAG_FLUSH) != 0) + segment->flags |= GST_SEGMENT_FLAG_RESET; + if ((flags & GST_SEEK_FLAG_TRICKMODE) != 0) + segment->flags |= GST_SEGMENT_FLAG_TRICKMODE; + if ((flags & GST_SEEK_FLAG_SEGMENT) != 0) + segment->flags |= GST_SEGMENT_FLAG_SEGMENT; + if ((flags & GST_SEEK_FLAG_TRICKMODE_KEY_UNITS) != 0) + segment->flags |= GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS; + if ((flags & GST_SEEK_FLAG_TRICKMODE_NO_AUDIO) != 0) + segment->flags |= GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO; + + segment->rate = rate; + segment->applied_rate = 1.0; + + segment->base = base; + if (rate > 0.0) + segment->offset = position - start; + else { + if (stop != -1) + segment->offset = stop - position; + else if (segment->duration != -1) + segment->offset = segment->duration - position; + else + segment->offset = 0; + } + + segment->start = start; + segment->stop = stop; + segment->time = start; + segment->position = position; + + GST_INFO ("segment updated: %" GST_SEGMENT_FORMAT, segment); + + return TRUE; +} + +/** + * gst_segment_to_stream_time_full: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @position: the position in the segment + * @stream_time: (out): result stream-time + * + * Translate @position to the total stream time using the currently configured + * segment. Compared to gst_segment_to_stream_time() this function can return + * negative stream-time. + * + * This function is typically used by elements that need to synchronize buffers + * against the clock or eachother. + * + * @position can be any value and the result of this function for values outside + * of the segment is extrapolated. + * + * When 1 is returned, @position resulted in a positive stream-time returned + * in @stream_time. + * + * When this function returns -1, the returned @stream_time should be negated + * to get the real negative stream time. + * + * Returns: a 1 or -1 on success, 0 on failure. + * + * Since: 1.8 + */ +gint +gst_segment_to_stream_time_full (const GstSegment * segment, GstFormat format, + guint64 position, guint64 * stream_time) +{ + guint64 start, stop, time; + gdouble abs_applied_rate; + gint res; + + /* format does not matter for -1 */ + if (G_UNLIKELY (position == -1)) { + *stream_time = -1; + return 0; + } + + g_return_val_if_fail (segment != NULL, 0); + g_return_val_if_fail (segment->format == format, 0); + + stop = segment->stop; + + start = segment->start; + time = segment->time; + + /* time must be known */ + if (G_UNLIKELY (time == -1)) + return 0; + + abs_applied_rate = ABS (segment->applied_rate); + + /* add or subtract from segment time based on applied rate */ + if (G_LIKELY (segment->applied_rate > 0.0)) { + if (G_LIKELY (position > start)) { + /* bring to uncorrected position in segment */ + *stream_time = position - start; + /* correct for applied rate if needed */ + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *stream_time *= abs_applied_rate; + /* correct for segment time */ + *stream_time += time; + res = 1; + } else { + *stream_time = start - position; + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *stream_time *= abs_applied_rate; + if (*stream_time > time) { + *stream_time -= time; + res = -1; + } else { + *stream_time = time - *stream_time; + res = 1; + } + } + } else { + /* correct for segment time. Streams with a negative applied_rate + * have timestamps between start and stop, as usual, but have the + * time member starting high and going backwards. */ + /* cannot continue without a known segment stop */ + if (G_UNLIKELY (stop == -1)) + return 0; + if (G_UNLIKELY (position > stop)) { + *stream_time = position - stop; + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *stream_time *= abs_applied_rate; + if (*stream_time > time) { + *stream_time -= time; + res = -1; + } else { + *stream_time = time - *stream_time; + res = 1; + } + } else { + *stream_time = stop - position; + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *stream_time *= abs_applied_rate; + *stream_time += time; + res = 1; + } + } + + return res; +} + +/** + * gst_segment_to_stream_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @position: the position in the segment + * + * Translate @position to stream time using the currently configured + * segment. The @position value must be between @segment start and + * stop value. + * + * This function is typically used by elements that need to operate on + * the stream time of the buffers it receives, such as effect plugins. + * In those use cases, @position is typically the buffer timestamp or + * clock time that one wants to convert to the stream time. + * The stream time is always between 0 and the total duration of the + * media stream. + * + * Returns: the position in stream_time or -1 when an invalid position + * was given. + * + * Since: 1.8 + */ +guint64 +gst_segment_to_stream_time (const GstSegment * segment, GstFormat format, + guint64 position) +{ + guint64 result; + + g_return_val_if_fail (segment != NULL, -1); + g_return_val_if_fail (segment->format == format, -1); + + /* before the segment boundary */ + if (G_UNLIKELY (position < segment->start)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT + ")", position, segment->start); + return -1; + } + /* after the segment boundary */ + if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT + ")", position, segment->stop); + return -1; + } + + if (gst_segment_to_stream_time_full (segment, format, position, &result) == 1) + return result; + + return -1; +} + +/** + * gst_segment_position_from_stream_time_full: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @stream_time: the stream-time + * @position: (out): the resulting position in the segment + * + * Translate @stream_time to the segment position using the currently configured + * segment. Compared to gst_segment_position_from_stream_time() this function can + * return negative segment position. + * + * This function is typically used by elements that need to synchronize buffers + * against the clock or each other. + * + * @stream_time can be any value and the result of this function for values outside + * of the segment is extrapolated. + * + * When 1 is returned, @stream_time resulted in a positive position returned + * in @position. + * + * When this function returns -1, the returned @position should be negated + * to get the real negative segment position. + * + * Returns: a 1 or -1 on success, 0 on failure. + * + * Since: 1.8 + */ +gint +gst_segment_position_from_stream_time_full (const GstSegment * segment, + GstFormat format, guint64 stream_time, guint64 * position) +{ + guint64 start, time; + gdouble abs_applied_rate; + gint res; + + /* format does not matter for -1 */ + if (G_UNLIKELY (stream_time == -1)) { + *position = -1; + return 0; + } + + g_return_val_if_fail (segment != NULL, -1); + g_return_val_if_fail (segment->format == format, -1); + + start = segment->start; + time = segment->time; + + /* time must be known */ + if (G_UNLIKELY (time == -1)) + return 0; + + abs_applied_rate = ABS (segment->applied_rate); + + if (G_LIKELY (segment->applied_rate > 0.0)) { + if (G_LIKELY (stream_time > time)) { + res = 1; + *position = stream_time - time; + } else { + res = -1; + *position = time - stream_time; + } + /* correct for applied rate if needed */ + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *position /= abs_applied_rate; + + if (G_UNLIKELY (res == -1)) { + if (*position > start) { + *position -= start; + } else { + *position = start - *position; + res = 1; + } + } else { + *position += start; + } + } else { + GstClockTime stop = segment->stop; + /* cannot continue without a known segment stop */ + if (G_UNLIKELY (stop == -1)) + return 0; + if (G_UNLIKELY (time > stream_time)) { + res = -1; + *position = time - stream_time; + } else { + res = 1; + *position = stream_time - time; + } + if (G_UNLIKELY (abs_applied_rate != 1.0)) + *position /= abs_applied_rate; + if (G_UNLIKELY (stop < *position)) { + if (G_LIKELY (res == 1)) { + *position -= stop; + res = -1; + } else { + *position += stop; + res = 1; + } + } else { + if (G_LIKELY (res == 1)) { + *position = stop - *position; + res = 1; + } else { + *position += stop; + res = 1; + } + } + } + + return res; +} + +/** + * gst_segment_position_from_stream_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @stream_time: the stream_time in the segment + * + * Convert @stream_time into a position in the segment so that + * gst_segment_to_stream_time() with that position returns @stream_time. + * + * Returns: the position in the segment for @stream_time. This function returns + * -1 when @stream_time is -1 or when it is not inside @segment. + * + * Since: 1.8 + */ +guint64 +gst_segment_position_from_stream_time (const GstSegment * segment, + GstFormat format, guint64 stream_time) +{ + guint64 position; + gint res; + + g_return_val_if_fail (segment != NULL, -1); + g_return_val_if_fail (segment->format == format, -1); + + res = + gst_segment_position_from_stream_time_full (segment, format, stream_time, + &position); + + /* before the segment boundary */ + if (G_UNLIKELY (position < segment->start)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT + ")", position, segment->start); + return -1; + } + + /* after the segment boundary */ + if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT + ")", position, segment->stop); + return -1; + } + + if (res == 1) + return position; + + return -1; +} + +/** + * gst_segment_to_running_time_full: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @position: the position in the segment + * @running_time: (out) (allow-none): result running-time + * + * Translate @position to the total running time using the currently configured + * segment. Compared to gst_segment_to_running_time() this function can return + * negative running-time. + * + * This function is typically used by elements that need to synchronize buffers + * against the clock or eachother. + * + * @position can be any value and the result of this function for values outside + * of the segment is extrapolated. + * + * When 1 is returned, @position resulted in a positive running-time returned + * in @running_time. + * + * When this function returns -1, the returned @running_time should be negated + * to get the real negative running time. + * + * Returns: a 1 or -1 on success, 0 on failure. + * + * Since: 1.6 + */ +gint +gst_segment_to_running_time_full (const GstSegment * segment, GstFormat format, + guint64 position, guint64 * running_time) +{ + gint res = 0; + guint64 result; + guint64 start, stop, offset; + gdouble abs_rate; + + if (G_UNLIKELY (position == -1)) { + GST_DEBUG ("invalid position (-1)"); + goto done; + } + + g_return_val_if_fail (segment != NULL, 0); + g_return_val_if_fail (segment->format == format, 0); + + offset = segment->offset; + + if (G_LIKELY (segment->rate > 0.0)) { + start = segment->start + offset; + + /* bring to uncorrected position in segment */ + if (position < start) { + /* negative value */ + result = start - position; + res = -1; + } else { + result = position - start; + res = 1; + } + } else { + stop = segment->stop; + + /* cannot continue if no stop position set or invalid offset */ + g_return_val_if_fail (stop != -1, 0); + g_return_val_if_fail (stop >= offset, 0); + + stop -= offset; + + /* bring to uncorrected position in segment */ + if (position > stop) { + /* negative value */ + result = position - stop; + res = -1; + } else { + result = stop - position; + res = 1; + } + } + + if (running_time) { + /* scale based on the rate, avoid division by and conversion to + * float when not needed */ + abs_rate = ABS (segment->rate); + if (G_UNLIKELY (abs_rate != 1.0)) + result /= abs_rate; + + /* correct for base of the segment */ + if (res == 1) + /* positive, add base */ + *running_time = result + segment->base; + else if (segment->base >= result) { + /* negative and base is bigger, subtract from base and we have a + * positive value again */ + *running_time = segment->base - result; + res = 1; + } else { + /* negative and base is smaller, subtract base and remainder is + * negative */ + *running_time = result - segment->base; + } + } + return res; + +done: + { + if (running_time) + *running_time = -1; + return 0; + } +} + +/** + * gst_segment_to_running_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @position: the position in the segment + * + * Translate @position to the total running time using the currently configured + * segment. Position is a value between @segment start and stop time. + * + * This function is typically used by elements that need to synchronize to the + * global clock in a pipeline. The running time is a constantly increasing value + * starting from 0. When gst_segment_init() is called, this value will reset to + * 0. + * + * This function returns -1 if the position is outside of @segment start and stop. + * + * Returns: the position as the total running time or -1 when an invalid position + * was given. + */ +guint64 +gst_segment_to_running_time (const GstSegment * segment, GstFormat format, + guint64 position) +{ + guint64 result; + + g_return_val_if_fail (segment != NULL, -1); + g_return_val_if_fail (segment->format == format, -1); + + /* before the segment boundary */ + if (G_UNLIKELY (position < segment->start)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT + ")", position, segment->start); + return -1; + } + /* after the segment boundary */ + if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT + ")", position, segment->stop); + return -1; + } + + if (gst_segment_to_running_time_full (segment, format, position, + &result) == 1) + return result; + + return -1; +} + +/** + * gst_segment_clip: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @start: the start position in the segment + * @stop: the stop position in the segment + * @clip_start: (out) (allow-none): the clipped start position in the segment + * @clip_stop: (out) (allow-none): the clipped stop position in the segment + * + * Clip the given @start and @stop values to the segment boundaries given + * in @segment. @start and @stop are compared and clipped to @segment + * start and stop values. + * + * If the function returns %FALSE, @start and @stop are known to fall + * outside of @segment and @clip_start and @clip_stop are not updated. + * + * When the function returns %TRUE, @clip_start and @clip_stop will be + * updated. If @clip_start or @clip_stop are different from @start or @stop + * respectively, the region fell partially in the segment. + * + * Note that when @stop is -1, @clip_stop will be set to the end of the + * segment. Depending on the use case, this may or may not be what you want. + * + * Returns: %TRUE if the given @start and @stop times fall partially or + * completely in @segment, %FALSE if the values are completely outside + * of the segment. + */ +gboolean +gst_segment_clip (const GstSegment * segment, GstFormat format, guint64 start, + guint64 stop, guint64 * clip_start, guint64 * clip_stop) +{ + g_return_val_if_fail (segment != NULL, FALSE); + g_return_val_if_fail (segment->format == format, FALSE); + + /* if we have a stop position and a valid start and start is bigger, + * we're outside of the segment. (Special case) segment start and + * segment stop can be identical. In this case, if start is also identical, + * it's inside of segment */ + if (G_UNLIKELY (segment->stop != -1 && start != -1 && (start > segment->stop + || (segment->start != segment->stop && start == segment->stop)))) + return FALSE; + + /* if a stop position is given and is before the segment start, + * we're outside of the segment. Special case is were start + * and stop are equal to the segment start. In that case we + * are inside the segment. */ + if (G_UNLIKELY (stop != -1 && (stop < segment->start || (start != stop + && stop == segment->start)))) + return FALSE; + + if (clip_start) { + if (start == -1) + *clip_start = -1; + else + *clip_start = MAX (start, segment->start); + } + + if (clip_stop) { + if (stop == -1) + *clip_stop = segment->stop; + else if (segment->stop == -1) + *clip_stop = stop; + else + *clip_stop = MIN (stop, segment->stop); + } + + return TRUE; +} + +/** + * gst_segment_position_from_running_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @running_time: the running_time in the segment + * + * Convert @running_time into a position in the segment so that + * gst_segment_to_running_time() with that position returns @running_time. + * + * Returns: the position in the segment for @running_time. This function returns + * -1 when @running_time is -1 or when it is not inside @segment. + * + * Since: 1.8 + */ +guint64 +gst_segment_position_from_running_time (const GstSegment * segment, + GstFormat format, guint64 running_time) +{ + guint64 position; + gint res; + + g_return_val_if_fail (segment != NULL, -1); + g_return_val_if_fail (segment->format == format, -1); + + res = + gst_segment_position_from_running_time_full (segment, format, + running_time, &position); + + if (res != 1) + return -1; + + /* before the segment boundary */ + if (G_UNLIKELY (position < segment->start)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT + ")", position, segment->start); + return -1; + } + + /* after the segment boundary */ + if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) { + GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT + ")", position, segment->stop); + return -1; + } + + return position; +} + +/** + * gst_segment_position_from_running_time_full: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @running_time: the running-time + * @position: (out): the resulting position in the segment + * + * Translate @running_time to the segment position using the currently configured + * segment. Compared to gst_segment_position_from_running_time() this function can + * return negative segment position. + * + * This function is typically used by elements that need to synchronize buffers + * against the clock or each other. + * + * @running_time can be any value and the result of this function for values + * outside of the segment is extrapolated. + * + * When 1 is returned, @running_time resulted in a positive position returned + * in @position. + * + * When this function returns -1, the returned @position should be negated + * to get the real negative segment position. + * + * Returns: a 1 or -1 on success, 0 on failure. + * + * Since: 1.8 + */ +gint +gst_segment_position_from_running_time_full (const GstSegment * segment, + GstFormat format, guint64 running_time, guint64 * position) +{ + gint res; + guint64 start, stop, base; + gdouble abs_rate; + + if (G_UNLIKELY (running_time == -1)) { + *position = -1; + return 0; + } + + g_return_val_if_fail (segment != NULL, 0); + g_return_val_if_fail (segment->format == format, 0); + + base = segment->base; + + abs_rate = ABS (segment->rate); + + start = segment->start; + stop = segment->stop; + + if (G_LIKELY (segment->rate > 0.0)) { + /* start by subtracting the base time */ + if (G_LIKELY (running_time >= base)) { + *position = running_time - base; + /* move into the segment at the right rate */ + if (G_UNLIKELY (abs_rate != 1.0)) + *position = ceil (*position * abs_rate); + /* bring to corrected position in segment */ + *position += start + segment->offset; + res = 1; + } else { + *position = base - running_time; + if (G_UNLIKELY (abs_rate != 1.0)) + *position = ceil (*position * abs_rate); + if (start + segment->offset > *position) { + *position -= start + segment->offset; + res = -1; + } else { + *position = start + segment->offset - *position; + res = 1; + } + } + } else { + if (G_LIKELY (running_time >= base)) { + *position = running_time - base; + if (G_UNLIKELY (abs_rate != 1.0)) + *position = ceil (*position * abs_rate); + if (G_UNLIKELY (stop < *position + segment->offset)) { + *position += segment->offset - stop; + res = -1; + } else { + *position = stop - *position - segment->offset; + res = 1; + } + } else { + *position = base - running_time; + if (G_UNLIKELY (abs_rate != 1.0)) + *position = ceil (*position * abs_rate); + if (G_UNLIKELY (stop < segment->offset - *position)) { + *position -= segment->offset - stop; + res = -1; + } else { + *position = stop + *position - segment->offset; + res = 1; + } + } + } + return res; +} + +/** + * gst_segment_to_position: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @running_time: the running_time in the segment + * + * Convert @running_time into a position in the segment so that + * gst_segment_to_running_time() with that position returns @running_time. + * + * Returns: the position in the segment for @running_time. This function returns + * -1 when @running_time is -1 or when it is not inside @segment. + * + * Deprecated: Use gst_segment_position_from_running_time() instead. + */ +#ifndef GST_REMOVE_DEPRECATED +guint64 +gst_segment_to_position (const GstSegment * segment, GstFormat format, + guint64 running_time) +{ + return gst_segment_position_from_running_time (segment, format, running_time); +} +#endif + +/** + * gst_segment_set_running_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @running_time: the running_time in the segment + * + * Adjust the start/stop and base values of @segment such that the next valid + * buffer will be one with @running_time. + * + * Returns: %TRUE if the segment could be updated successfully. If %FALSE is + * returned, @running_time is -1 or not in @segment. + */ +gboolean +gst_segment_set_running_time (GstSegment * segment, GstFormat format, + guint64 running_time) +{ + guint64 position; + guint64 start, stop; + + /* start by bringing the running_time into the segment position */ + position = + gst_segment_position_from_running_time (segment, format, running_time); + + /* we must have a valid position now */ + if (G_UNLIKELY (position == -1)) + return FALSE; + + start = segment->start; + stop = segment->stop; + + if (G_LIKELY (segment->rate > 0.0)) { + /* update the start and time values */ + start = position; + } else { + /* reverse, update stop */ + stop = position; + } + /* and base time is exactly the running time */ + segment->time = gst_segment_to_stream_time (segment, format, start); + segment->start = start; + segment->stop = stop; + segment->base = running_time; + + return TRUE; +} + +/** + * gst_segment_offset_running_time: + * @segment: a #GstSegment structure. + * @format: the format of the segment. + * @offset: the offset to apply in the segment + * + * Adjust the values in @segment so that @offset is applied to all + * future running-time calculations. + * + * Since: 1.2.3 + * + * Returns: %TRUE if the segment could be updated successfully. If %FALSE is + * returned, @offset is not in @segment. + */ +gboolean +gst_segment_offset_running_time (GstSegment * segment, GstFormat format, + gint64 offset) +{ + g_return_val_if_fail (segment != NULL, FALSE); + g_return_val_if_fail (segment->format == format, FALSE); + + if (offset == 0) + return TRUE; + + if (offset > 0) { + /* positive offset, we can simply apply to the base time */ + segment->base += offset; + } else { + offset = -offset; + /* negative offset, first try to subtract from base */ + if (segment->base > offset) { + segment->base -= offset; + } else { + guint64 position; + + /* subtract all from segment.base, remainder in offset */ + offset -= segment->base; + segment->base = 0; + position = + gst_segment_position_from_running_time (segment, format, offset); + if (position == -1) + return FALSE; + + segment->offset = position - segment->start; + } + } + return TRUE; +} + +/** + * gst_segment_is_equal: + * @s0: a #GstSegment structure. + * @s1: a #GstSegment structure. + * + * Checks for two segments being equal. Equality here is defined + * as perfect equality, including floating point values. + * + * Since: 1.6 + * + * Returns: %TRUE if the segments are equal, %FALSE otherwise. + */ +gboolean +gst_segment_is_equal (const GstSegment * s0, const GstSegment * s1) +{ + if (s0->flags != s1->flags) + return FALSE; + if (s0->rate != s1->rate) + return FALSE; + if (s0->applied_rate != s1->applied_rate) + return FALSE; + if (s0->format != s1->format) + return FALSE; + if (s0->base != s1->base) + return FALSE; + if (s0->offset != s1->offset) + return FALSE; + if (s0->start != s1->start) + return FALSE; + if (s0->stop != s1->stop) + return FALSE; + if (s0->time != s1->time) + return FALSE; + if (s0->position != s1->position) + return FALSE; + if (s0->duration != s1->duration) + return FALSE; + return TRUE; +} diff --git a/gst/gstsegment.h b/gst/gstsegment.h new file mode 100644 index 0000000..b48d7e7 --- /dev/null +++ b/gst/gstsegment.h @@ -0,0 +1,281 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstsegment.h: Header for GstSegment subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_SEGMENT_H__ +#define __GST_SEGMENT_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_SEGMENT (gst_segment_get_type()) + +typedef struct _GstSegment GstSegment; + +/** + * GstSeekType: + * @GST_SEEK_TYPE_NONE: no change in position is required + * @GST_SEEK_TYPE_SET: absolute position is requested + * @GST_SEEK_TYPE_END: relative position to duration is requested + * + * The different types of seek events. When constructing a seek event with + * gst_event_new_seek() or when doing gst_segment_do_seek (). + */ +typedef enum { + /* one of these */ + GST_SEEK_TYPE_NONE = 0, + GST_SEEK_TYPE_SET = 1, + GST_SEEK_TYPE_END = 2 +} GstSeekType; + +/** + * GstSeekFlags: + * @GST_SEEK_FLAG_NONE: no flag + * @GST_SEEK_FLAG_FLUSH: flush pipeline + * @GST_SEEK_FLAG_ACCURATE: accurate position is requested, this might + * be considerably slower for some formats. + * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be + * faster but less accurate. + * @GST_SEEK_FLAG_SEGMENT: perform a segment seek. + * @GST_SEEK_FLAG_TRICKMODE: when doing fast forward or fast reverse playback, allow + * elements to skip frames instead of generating all + * frames. (Since 1.6) + * @GST_SEEK_FLAG_SNAP_BEFORE: go to a location before the requested position, + * if %GST_SEEK_FLAG_KEY_UNIT this means the keyframe at or before + * the requested position the one at or before the seek target. + * @GST_SEEK_FLAG_SNAP_AFTER: go to a location after the requested position, + * if %GST_SEEK_FLAG_KEY_UNIT this means the keyframe at of after the + * requested position. + * @GST_SEEK_FLAG_SNAP_NEAREST: go to a position near the requested position, + * if %GST_SEEK_FLAG_KEY_UNIT this means the keyframe closest + * to the requested position, if both keyframes are at an equal + * distance, behaves like %GST_SEEK_FLAG_SNAP_BEFORE. + * @GST_SEEK_FLAG_TRICKMODE_KEY_UNITS: when doing fast forward or fast reverse + * playback, request that elements only decode keyframes + * and skip all other content, for formats that have + * keyframes. (Since 1.6) + * @GST_SEEK_FLAG_TRICKMODE_NO_AUDIO: when doing fast forward or fast reverse + * playback, request that audio decoder elements skip + * decoding and output only gap events or silence. (Since 1.6) + * @GST_SEEK_FLAG_SKIP: Deprecated backward compatibility flag, replaced + * by %GST_SEEK_FLAG_TRICKMODE + * + * Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags + * can be used together. + * + * A non flushing seek might take some time to perform as the currently + * playing data in the pipeline will not be cleared. + * + * An accurate seek might be slower for formats that don't have any indexes + * or timestamp markers in the stream. Specifying this flag might require a + * complete scan of the file in those cases. + * + * When performing a segment seek: after the playback of the segment completes, + * no EOS will be emitted by the element that performed the seek, but a + * %GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. + * When this message is posted, it is possible to send a new seek event to + * continue playback. With this seek method it is possible to perform seamless + * looping or simple linear editing. + * + * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode + * playback, the %GST_SEEK_FLAG_TRICKMODE flag can be used to instruct decoders + * and demuxers to adjust the playback rate by skipping frames. This can improve + * performance and decrease CPU usage because not all frames need to be decoded. + * + * Beyond that, the %GST_SEEK_FLAG_TRICKMODE_KEY_UNITS flag can be used to + * request that decoders skip all frames except key units, and + * %GST_SEEK_FLAG_TRICKMODE_NO_AUDIO flags can be used to request that audio + * decoders do no decoding at all, and simple output silence. + * + * The %GST_SEEK_FLAG_SNAP_BEFORE flag can be used to snap to the previous + * relevant location, and the %GST_SEEK_FLAG_SNAP_AFTER flag can be used to + * select the next relevant location. If %GST_SEEK_FLAG_KEY_UNIT is specified, + * the relevant location is a keyframe. If both flags are specified, the nearest + * of these locations will be selected. If none are specified, the implementation is + * free to select whichever it wants. + * + * The before and after here are in running time, so when playing backwards, + * the next location refers to the one that will played in next, and not the + * one that is located after in the actual source stream. + * + * Also see part-seeking.txt in the GStreamer design documentation for more + * details on the meaning of these flags and the behaviour expected of + * elements that handle them. + */ +typedef enum { + GST_SEEK_FLAG_NONE = 0, + GST_SEEK_FLAG_FLUSH = (1 << 0), + GST_SEEK_FLAG_ACCURATE = (1 << 1), + GST_SEEK_FLAG_KEY_UNIT = (1 << 2), + GST_SEEK_FLAG_SEGMENT = (1 << 3), + GST_SEEK_FLAG_TRICKMODE = (1 << 4), + /* FIXME 2.0: Remove _SKIP flag, + * which was kept for backward compat when _TRICKMODE was added */ + GST_SEEK_FLAG_SKIP = (1 << 4), + GST_SEEK_FLAG_SNAP_BEFORE = (1 << 5), + GST_SEEK_FLAG_SNAP_AFTER = (1 << 6), + GST_SEEK_FLAG_SNAP_NEAREST = GST_SEEK_FLAG_SNAP_BEFORE | GST_SEEK_FLAG_SNAP_AFTER, + /* Careful to restart next flag with 1<<7 here */ + GST_SEEK_FLAG_TRICKMODE_KEY_UNITS = (1 << 7), + GST_SEEK_FLAG_TRICKMODE_NO_AUDIO = (1 << 8), +} GstSeekFlags; + +/** + * GstSegmentFlags: + * @GST_SEGMENT_FLAG_NONE: no flags + * @GST_SEGMENT_FLAG_RESET: reset the pipeline running_time to the segment + * running_time + * @GST_SEGMENT_FLAG_TRICKMODE: perform skip playback (Since 1.6) + * @GST_SEGMENT_FLAG_SEGMENT: send SEGMENT_DONE instead of EOS + * @GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS: Decode only keyframes, where + * possible (Since 1.6) + * @GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO: Do not decode any audio, where + * possible (Since 1.6) + * @GST_SEGMENT_FLAG_SKIP: Deprecated backward compatibility flag, replaced + * by @GST_SEGMENT_FLAG_TRICKMODE + * + * Flags for the GstSegment structure. Currently mapped to the corresponding + * values of the seek flags. + */ +/* Note: update gst_segment_do_seek() when adding new flags here */ +typedef enum { /*< flags >*/ + GST_SEGMENT_FLAG_NONE = GST_SEEK_FLAG_NONE, + GST_SEGMENT_FLAG_RESET = GST_SEEK_FLAG_FLUSH, + GST_SEGMENT_FLAG_TRICKMODE = GST_SEEK_FLAG_TRICKMODE, + /* FIXME 2.0: Remove _SKIP flag, + * which was kept for backward compat when _TRICKMODE was added */ + GST_SEGMENT_FLAG_SKIP = GST_SEEK_FLAG_TRICKMODE, + GST_SEGMENT_FLAG_SEGMENT = GST_SEEK_FLAG_SEGMENT, + GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS = GST_SEEK_FLAG_TRICKMODE_KEY_UNITS, + GST_SEGMENT_FLAG_TRICKMODE_NO_AUDIO = GST_SEEK_FLAG_TRICKMODE_NO_AUDIO +} GstSegmentFlags; + +/** + * GstSegment: + * @flags: flags for this segment + * @rate: the playback rate of the segment + * @applied_rate: the already applied rate to the segment + * @format: the format of the segment values + * @base: the running time (plus elapsed time, see offset) of the segment start + * @offset: the amount (in buffer timestamps) that has already been elapsed in + * the segment + * @start: the start of the segment in buffer timestamp time (PTS) + * @stop: the stop of the segment in buffer timestamp time (PTS) + * @time: the stream time of the segment start + * @position: the buffer timestamp position in the segment (used internally by + * elements such as sources, demuxers or parsers to track progress) + * @duration: the duration of the stream + * + * A helper structure that holds the configured region of + * interest in a media file. + */ +struct _GstSegment { + /*< public >*/ + GstSegmentFlags flags; + + gdouble rate; + gdouble applied_rate; + + GstFormat format; + guint64 base; + guint64 offset; + guint64 start; + guint64 stop; + guint64 time; + + guint64 position; + guint64 duration; + + /* < private > */ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_segment_get_type (void); + +GST_API +GstSegment * gst_segment_new (void) G_GNUC_MALLOC; + +GST_API +GstSegment * gst_segment_copy (const GstSegment *segment) G_GNUC_MALLOC; + +GST_API +void gst_segment_copy_into (const GstSegment *src, GstSegment *dest); + +GST_API +void gst_segment_free (GstSegment *segment); + +GST_API +void gst_segment_init (GstSegment *segment, GstFormat format); + +GST_API +gint gst_segment_to_stream_time_full (const GstSegment *segment, GstFormat format, guint64 position, guint64 * stream_time); + +GST_API +guint64 gst_segment_to_stream_time (const GstSegment *segment, GstFormat format, guint64 position); + +GST_API +gint gst_segment_position_from_stream_time_full (const GstSegment * segment, GstFormat format, guint64 stream_time, guint64 * position); + +GST_API +guint64 gst_segment_position_from_stream_time (const GstSegment * segment, GstFormat format, guint64 stream_time); + +GST_API +guint64 gst_segment_to_running_time (const GstSegment *segment, GstFormat format, guint64 position); + +GST_API +gint gst_segment_to_running_time_full (const GstSegment *segment, GstFormat format, guint64 position, + guint64 * running_time); + +GST_DEPRECATED_FOR(gst_segment_position_from_running_time) +guint64 gst_segment_to_position (const GstSegment *segment, GstFormat format, guint64 running_time); + +GST_API +gint gst_segment_position_from_running_time_full (const GstSegment *segment, GstFormat format, guint64 running_time, guint64 * position); + +GST_API +guint64 gst_segment_position_from_running_time (const GstSegment *segment, GstFormat format, guint64 running_time); + +GST_API +gboolean gst_segment_set_running_time (GstSegment *segment, GstFormat format, guint64 running_time); + +GST_API +gboolean gst_segment_offset_running_time (GstSegment *segment, GstFormat format, gint64 offset); + +GST_API +gboolean gst_segment_clip (const GstSegment *segment, GstFormat format, guint64 start, + guint64 stop, guint64 *clip_start, guint64 *clip_stop); +GST_API +gboolean gst_segment_do_seek (GstSegment * segment, gdouble rate, + GstFormat format, GstSeekFlags flags, + GstSeekType start_type, guint64 start, + GstSeekType stop_type, guint64 stop, gboolean * update); +GST_API +gboolean gst_segment_is_equal (const GstSegment * s0, const GstSegment * s1); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSegment, gst_segment_free) +#endif + +G_END_DECLS + +#endif /* __GST_SEGMENT_H__ */ diff --git a/gst/gststreamcollection.c b/gst/gststreamcollection.c new file mode 100644 index 0000000..f1fa1a4 --- /dev/null +++ b/gst/gststreamcollection.c @@ -0,0 +1,356 @@ +/* GStreamer + * + * Copyright (C) 2015 Centricular Ltd + * @author: Edward Hervey + * @author: Jan Schmidt + * + * gststreams.c: GstStreamCollection object and methods + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * MT safe. + */ + +/** + * SECTION:gststreamcollection + * @title: GstStreamCollection + * @short_description: Base class for collection of streams + * + * Since: 1.10 + */ + +#include "gst_private.h" + +#include "gstenumtypes.h" +#include "gstevent.h" +#include "gststreamcollection.h" + +GST_DEBUG_CATEGORY_STATIC (stream_collection_debug); +#define GST_CAT_DEFAULT stream_collection_debug + +#define GST_STREAM_COLLECTION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_STREAM_COLLECTION, GstStreamCollectionPrivate)) + +struct _GstStreamCollectionPrivate +{ + /* Maybe switch this to a GArray if performance is + * ever an issue? */ + GQueue *streams; +}; + +/* stream signals and properties */ +enum +{ + SIG_STREAM_NOTIFY, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_UPSTREAM_ID, + PROP_LAST +}; + +static guint gst_stream_collection_signals[LAST_SIGNAL] = { 0 }; + +static void gst_stream_collection_dispose (GObject * object); +static void gst_stream_collection_finalize (GObject * object); + +static void gst_stream_collection_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_stream_collection_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void +proxy_stream_notify_cb (GstStream * stream, GParamSpec * pspec, + GstStreamCollection * collection); + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (stream_collection_debug, "streamcollection", GST_DEBUG_BOLD, \ + "debugging info for the stream collection objects"); \ + \ +} + +#define gst_stream_collection_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstStreamCollection, gst_stream_collection, + GST_TYPE_OBJECT, _do_init); + +static void +gst_stream_collection_class_init (GstStreamCollectionClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstStreamCollectionPrivate)); + + gobject_class->set_property = gst_stream_collection_set_property; + gobject_class->get_property = gst_stream_collection_get_property; + + /** + * GstStream:upstream-id: + * + * stream-id + */ + g_object_class_install_property (gobject_class, PROP_UPSTREAM_ID, + g_param_spec_string ("upstream-id", "Upstream ID", + "The stream ID of the parent stream", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + /** + * GstStream::stream-notify: + * @collection: a #GstStreamCollection + * @prop_stream: the #GstStream that originated the signal + * @prop: the property that changed + * + * The stream notify signal is used to be notified of property changes to + * streams within the collection. + */ + gst_stream_collection_signals[SIG_STREAM_NOTIFY] = + g_signal_new ("stream-notify", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | + G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstStreamCollectionClass, + stream_notify), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, + 2, GST_TYPE_STREAM, G_TYPE_PARAM); + + gobject_class->dispose = gst_stream_collection_dispose; + gobject_class->finalize = gst_stream_collection_finalize; +} + +static void +gst_stream_collection_init (GstStreamCollection * collection) +{ + collection->priv = GST_STREAM_COLLECTION_GET_PRIVATE (collection); + collection->priv->streams = g_queue_new (); +} + +static void +release_gst_stream (GstStream * stream, GstStreamCollection * collection) +{ + g_signal_handlers_disconnect_by_func (stream, + proxy_stream_notify_cb, collection); + gst_object_unref (stream); +} + +static void +gst_stream_collection_dispose (GObject * object) +{ + GstStreamCollection *collection = GST_STREAM_COLLECTION_CAST (object); + + if (collection->upstream_id) { + g_free (collection->upstream_id); + collection->upstream_id = NULL; + } + + if (collection->priv->streams) { + g_queue_foreach (collection->priv->streams, + (GFunc) release_gst_stream, collection); + g_queue_clear (collection->priv->streams); + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_stream_collection_finalize (GObject * object) +{ + GstStreamCollection *collection = GST_STREAM_COLLECTION_CAST (object); + + if (collection->priv->streams) + g_queue_free (collection->priv->streams); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_stream_collection_new: + * @upstream_id: (allow-none): The stream id of the parent stream + * + * Create a new #GstStreamCollection. + * + * Returns: (transfer full): The new #GstStreamCollection. + * + * Since: 1.10 + */ +GstStreamCollection * +gst_stream_collection_new (const gchar * upstream_id) +{ + GstStreamCollection *collection; + + collection = + g_object_new (GST_TYPE_STREAM_COLLECTION, "upstream-id", upstream_id, + NULL); + + /* Clear floating flag */ + g_object_ref_sink (collection); + + return collection; +} + +static void +gst_stream_collection_set_upstream_id (GstStreamCollection * collection, + const gchar * upstream_id) +{ + g_return_if_fail (collection->upstream_id == NULL); + + /* Upstream ID should only be set once on construction, but let's + * not leak in case someone does something silly */ + if (collection->upstream_id) + g_free (collection->upstream_id); + + if (upstream_id) + collection->upstream_id = g_strdup (upstream_id); +} + +/** + * gst_stream_collection_get_upstream_id: + * @collection: a #GstStreamCollection + * + * Returns the upstream id of the @collection. + * + * Returns: (transfer none): The upstream id + * + * Since: 1.10 + */ +const gchar * +gst_stream_collection_get_upstream_id (GstStreamCollection * collection) +{ + const gchar *res; + + res = collection->upstream_id; + + return res; +} + +static void +gst_stream_collection_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamCollection *collection; + + collection = GST_STREAM_COLLECTION_CAST (object); + + switch (prop_id) { + case PROP_UPSTREAM_ID: + gst_stream_collection_set_upstream_id (collection, + g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stream_collection_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamCollection *collection; + + collection = GST_STREAM_COLLECTION_CAST (object); + + switch (prop_id) { + case PROP_UPSTREAM_ID: + g_value_set_string (value, + gst_stream_collection_get_upstream_id (collection)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +proxy_stream_notify_cb (GstStream * stream, GParamSpec * pspec, + GstStreamCollection * collection) +{ + GST_DEBUG_OBJECT (collection, "Stream %" GST_PTR_FORMAT " updated %s", + stream, pspec->name); + g_signal_emit (collection, gst_stream_collection_signals[SIG_STREAM_NOTIFY], + g_quark_from_string (pspec->name), stream, pspec); +} + +/** + * gst_stream_collection_add_stream: + * @collection: a #GstStreamCollection + * @stream: (transfer full): the #GstStream to add + * + * Add the given @stream to the @collection. + * + * Returns: %TRUE if the @stream was properly added, else %FALSE + * + * Since: 1.10 + */ +gboolean +gst_stream_collection_add_stream (GstStreamCollection * collection, + GstStream * stream) +{ + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), FALSE); + g_return_val_if_fail (GST_IS_STREAM (stream), FALSE); + g_return_val_if_fail (collection->priv->streams, FALSE); + + GST_DEBUG_OBJECT (collection, "Adding stream %" GST_PTR_FORMAT, stream); + + g_queue_push_tail (collection->priv->streams, stream); + g_signal_connect (stream, "notify", (GCallback) proxy_stream_notify_cb, + collection); + + return TRUE; +} + +/** + * gst_stream_collection_get_size: + * @collection: a #GstStreamCollection + * + * Get the number of streams this collection contains + * + * Returns: The number of streams that @collection contains + * + * Since: 1.10 + */ +guint +gst_stream_collection_get_size (GstStreamCollection * collection) +{ + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), 0); + g_return_val_if_fail (collection->priv->streams, 0); + + return g_queue_get_length (collection->priv->streams); +} + +/** + * gst_stream_collection_get_stream: + * @collection: a #GstStreamCollection + * @index: Index of the stream to retrieve + * + * Retrieve the #GstStream with index @index from the collection. + * + * The caller should not modify the returned #GstStream + * + * Returns: (transfer none) (nullable): A #GstStream + * + * Since: 1.10 + */ +GstStream * +gst_stream_collection_get_stream (GstStreamCollection * collection, guint index) +{ + g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL); + g_return_val_if_fail (collection->priv->streams, NULL); + + return g_queue_peek_nth (collection->priv->streams, index); +} diff --git a/gst/gststreamcollection.h b/gst/gststreamcollection.h new file mode 100644 index 0000000..11345c5 --- /dev/null +++ b/gst/gststreamcollection.h @@ -0,0 +1,121 @@ +/* GStreamer + * Copyright (C) 2015 Centricular Ltd + * @author: Edward Hervey + * @author: Jan Schmidt + * + * gststreams.h : Header for GstStreamCollection subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_STREAM_COLLECTION_H__ +#define __GST_STREAM_COLLECTION_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_COLLECTION (gst_stream_collection_get_type ()) +#define GST_IS_STREAM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAM_COLLECTION)) +#define GST_IS_STREAM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_STREAM_COLLECTION)) +#define GST_STREAM_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_STREAM_COLLECTION, GstStreamCollectionClass)) +#define GST_STREAM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAM_COLLECTION, GstStreamCollection)) +#define GST_STREAM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_STREAM_COLLECTION, GstStreamCollectionClass)) +#define GST_STREAM_COLLECTION_CAST(obj) ((GstStreamCollection*)(obj)) + +typedef struct _GstStreamCollection GstStreamCollection; +typedef struct _GstStreamCollectionClass GstStreamCollectionClass; +typedef struct _GstStreamCollectionPrivate GstStreamCollectionPrivate; + +#include +#include + +/** + * GstStreamCollection: + * + * A collection of #GstStream that are available. + * + * A #GstStreamCollection will be provided by elements that can make those + * streams available. Applications can use the collection to show the user + * what streams are available by using %gst_stream_collection_get_stream() + * + * Once posted, a #GstStreamCollection is immutable. Updates are made by sending + * a new #GstStreamCollection message, which may or may not share some of + * the #GstStream objects from the collection it replaces. The receiver can check + * the sender of a stream collection message to know which collection is + * obsoleted. + * + * Several elements in a pipeline can provide #GstStreamCollection. + * + * Applications can activate streams from a collection by using the + * #GST_EVENT_SELECT_STREAMS event on a pipeline, bin or element. + * + * Since: 1.10 + */ +struct _GstStreamCollection { + /*< private >*/ + GstObject object; + + gchar *upstream_id; + GstStreamCollectionPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstStreamCollectionClass: + * @parent_class: the parent class structure + * @stream_notify: default signal handler for the stream-notify signal + * + * GstStreamCollection class structure + */ +struct _GstStreamCollectionClass { + GstObjectClass parent_class; + + /* signals */ + void (*stream_notify) (GstStreamCollection *collection, GstStream *stream, GParamSpec * pspec); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_stream_collection_get_type (void); + +GST_API +GstStreamCollection *gst_stream_collection_new (const gchar *upstream_id); + +GST_API +const gchar *gst_stream_collection_get_upstream_id (GstStreamCollection *collection); + +GST_API +guint gst_stream_collection_get_size (GstStreamCollection *collection); + +GST_API +GstStream *gst_stream_collection_get_stream (GstStreamCollection *collection, guint index); + +GST_API +gboolean gst_stream_collection_add_stream (GstStreamCollection *collection, + GstStream *stream); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStreamCollection, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_STREAM_COLLECTION_H__ */ diff --git a/gst/gststreams.c b/gst/gststreams.c new file mode 100644 index 0000000..9c3272d --- /dev/null +++ b/gst/gststreams.c @@ -0,0 +1,552 @@ +/* GStreamer + * + * Copyright (C) 2015 Centricular Ltd + * @author: Edward Hervey + * @author: Jan Schmidt + * + * gststreams.c: GstStream and GstStreamCollection object and methods + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * MT safe. + */ + +/** + * SECTION:gststreams + * @title: GstStreams + * @short_description: Base class for stream objects + * + * A #GstStream is a high-level object defining a stream of data which is, or + * can be, present in a #GstPipeline. + * + * It is defined by a unique identifier, a "Stream ID". A #GstStream does not + * automatically imply the stream is present within a pipeline or element. + * + * Any element that can introduce new streams in a pipeline should create the + * appropriate #GstStream object, and can convey that object via the + * %GST_EVENT_STREAM_START event and/or the #GstStreamCollection. + * + * Elements that do not modify the nature of the stream can add extra information + * on it (such as enrich the #GstCaps, or #GstTagList). This is typically done + * by parsing elements. + * + * Since: 1.10 + */ + +#include "gst_private.h" + +#include "gstenumtypes.h" +#include "gstevent.h" +#include "gststreams.h" + +GST_DEBUG_CATEGORY_STATIC (streams_debug); +#define GST_CAT_DEFAULT streams_debug + +#define GST_STREAM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_STREAM, GstStreamPrivate)) + +struct _GstStreamPrivate +{ + GstStreamFlags flags; + GstStreamType type; + GstTagList *tags; + GstCaps *caps; +}; + +/* stream signals and properties */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_STREAM_ID, + PROP_STREAM_FLAGS, + PROP_STREAM_TYPE, + PROP_TAGS, + PROP_CAPS, + PROP_LAST +}; + +static GParamSpec *gst_stream_pspecs[PROP_LAST] = { 0 }; + +#if 0 +static guint gst_stream_signals[LAST_SIGNAL] = { 0 }; +#endif + +static void gst_stream_finalize (GObject * object); + +static void gst_stream_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_stream_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (streams_debug, "streams", GST_DEBUG_BOLD, \ + "debugging info for the stream and stream collection objects"); \ + \ +} + +#define gst_stream_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstStream, gst_stream, GST_TYPE_OBJECT, _do_init); + +static void +gst_stream_class_init (GstStreamClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstStreamPrivate)); + + gobject_class->set_property = gst_stream_set_property; + gobject_class->get_property = gst_stream_get_property; + + /** + * GstStream:stream-id: + * + * The unique identifier of the #GstStream. Can only be set at construction + * time. + */ + g_object_class_install_property (gobject_class, PROP_STREAM_ID, + g_param_spec_string ("stream-id", "Stream ID", + "The stream ID of the stream", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstStream:flags: + * + * The #GstStreamFlags of the #GstStream. Can only be set at construction time. + **/ + gst_stream_pspecs[PROP_STREAM_FLAGS] = + g_param_spec_flags ("stream-flags", "Stream Flags", "The stream flags", + GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_STREAM_FLAGS, + gst_stream_pspecs[PROP_STREAM_FLAGS]); + + /** + * GstStream:stream-type: + * + * The #GstStreamType of the #GstStream. Can only be set at construction time. + **/ + gst_stream_pspecs[PROP_STREAM_TYPE] = + g_param_spec_flags ("stream-type", "Stream Type", "The type of stream", + GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_STREAM_TYPE, + gst_stream_pspecs[PROP_STREAM_TYPE]); + + /** + * GstStream:caps: + * + * The #GstCaps of the #GstStream. + **/ + gst_stream_pspecs[PROP_CAPS] = + g_param_spec_boxed ("caps", "Caps", "The caps of the stream", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_CAPS, + gst_stream_pspecs[PROP_CAPS]); + + /** + * GstStream:tags: + * + * The #GstTagList of the #GstStream. + **/ + gst_stream_pspecs[PROP_TAGS] = + g_param_spec_boxed ("tags", "Tags", "The tags of the stream", + GST_TYPE_TAG_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_TAGS, + gst_stream_pspecs[PROP_TAGS]); + + gobject_class->finalize = gst_stream_finalize; +} + +static void +gst_stream_init (GstStream * stream) +{ + stream->priv = GST_STREAM_GET_PRIVATE (stream); + stream->priv->type = GST_STREAM_TYPE_UNKNOWN; +} + +static void +gst_stream_finalize (GObject * object) +{ + GstStream *stream = GST_STREAM_CAST (object); + + gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags, + (GstMiniObject *) NULL); + gst_caps_replace (&stream->priv->caps, NULL); + g_free ((gchar *) stream->stream_id); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_stream_new: + * @stream_id: (allow-none): the id for the new stream. If %NULL, + * a new one will be automatically generated + * @caps: (allow-none) (transfer none): the #GstCaps of the stream + * @type: the #GstStreamType of the stream + * @flags: the #GstStreamFlags of the stream + * + * Create a new #GstStream for the given @stream_id, @caps, @type + * and @flags + * + * Returns: (transfer full): The new #GstStream + * + * Since: 1.10 + */ +GstStream * +gst_stream_new (const gchar * stream_id, GstCaps * caps, GstStreamType type, + GstStreamFlags flags) +{ + GstStream *stream; + + stream = g_object_new (GST_TYPE_STREAM, "stream-id", stream_id, "caps", caps, + "stream-type", type, "stream-flags", flags, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (stream); + + return stream; +} + +static void +gst_stream_set_stream_id (GstStream * stream, const gchar * stream_id) +{ + GST_OBJECT_LOCK (stream); + g_assert (stream->stream_id == NULL); + if (stream_id) + stream->stream_id = g_strdup (stream_id); + else { + /* Create a randoom stream_id if NULL */ + GST_FIXME_OBJECT (stream, "Creating random stream-id, consider " + "implementing a deterministic way of creating a stream-id"); + stream->stream_id = + g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (), + g_random_int (), g_random_int ()); + } + + GST_OBJECT_UNLOCK (stream); +} + +/** + * gst_stream_get_stream_id: + * @stream: a #GstStream + * + * Returns the stream ID of @stream. + * + * Returns: (transfer none) (nullable): the stream ID of @stream. Only valid + * during the lifetime of @stream. + * + * Since: 1.10 + */ +const gchar * +gst_stream_get_stream_id (GstStream * stream) +{ + return stream->stream_id; +} + +/** + * gst_stream_set_stream_flags: + * @stream: a #GstStream + * @flags: the flags to set on @stream + * + * Set the @flags for the @stream. + * + * Since: 1.10 + */ +void +gst_stream_set_stream_flags (GstStream * stream, GstStreamFlags flags) +{ + GST_OBJECT_LOCK (stream); + stream->priv->flags = flags; + GST_OBJECT_UNLOCK (stream); + + g_object_notify_by_pspec (G_OBJECT (stream), + gst_stream_pspecs[PROP_STREAM_FLAGS]); +} + +/** + * gst_stream_get_stream_flags: + * @stream: a #GstStream + * + * Retrieve the current stream flags for @stream + * + * Returns: The #GstStreamFlags for @stream + * + * Since: 1.10 + */ +GstStreamFlags +gst_stream_get_stream_flags (GstStream * stream) +{ + GstStreamFlags res; + + GST_OBJECT_LOCK (stream); + res = stream->priv->flags; + GST_OBJECT_UNLOCK (stream); + + return res; +} + +/** + * gst_stream_set_stream_type: + * @stream: a #GstStream + * @stream_type: the type to set on @stream + * + * Set the stream type of @stream + * + * Since: 1.10 + */ +void +gst_stream_set_stream_type (GstStream * stream, GstStreamType stream_type) +{ + GST_OBJECT_LOCK (stream); + stream->priv->type = stream_type; + GST_OBJECT_UNLOCK (stream); + + g_object_notify_by_pspec (G_OBJECT (stream), + gst_stream_pspecs[PROP_STREAM_TYPE]); +} + +/** + * gst_stream_get_stream_type: + * @stream: a #GstStream + * + * Retrieve the stream type for @stream + * + * Returns: The #GstStreamType for @stream + * + * Since: 1.10 + */ +GstStreamType +gst_stream_get_stream_type (GstStream * stream) +{ + GstStreamType res; + + GST_OBJECT_LOCK (stream); + res = stream->priv->type; + GST_OBJECT_UNLOCK (stream); + + return res; +} + +/** + * gst_stream_set_tags: + * @stream: a #GstStream + * @tags: (transfer none) (allow-none): a #GstTagList + * + * Set the tags for the #GstStream + * + * Since: 1.10 + */ +void +gst_stream_set_tags (GstStream * stream, GstTagList * tags) +{ + gboolean notify = FALSE; + + GST_OBJECT_LOCK (stream); + if (stream->priv->tags == NULL || tags == NULL + || !gst_tag_list_is_equal (stream->priv->tags, tags)) { + gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags, + (GstMiniObject *) tags); + notify = TRUE; + } + GST_OBJECT_UNLOCK (stream); + + if (notify) + g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_TAGS]); +} + +/** + * gst_stream_get_tags: + * @stream: a #GstStream + * + * Retrieve the tags for @stream, if any + * + * Returns: (transfer full) (nullable): The #GstTagList for @stream + * + * Since: 1.10 + */ +GstTagList * +gst_stream_get_tags (GstStream * stream) +{ + GstTagList *res = NULL; + + GST_OBJECT_LOCK (stream); + if (stream->priv->tags) + res = gst_tag_list_ref (stream->priv->tags); + GST_OBJECT_UNLOCK (stream); + + return res; +} + +/** + * gst_stream_set_caps: + * @stream: a #GstStream + * @caps: (transfer none) (allow-none): a #GstCaps + * + * Set the caps for the #GstStream + * + * Since: 1.10 + */ +void +gst_stream_set_caps (GstStream * stream, GstCaps * caps) +{ + gboolean notify = FALSE; + + GST_OBJECT_LOCK (stream); + if (stream->priv->caps == NULL || (caps + && !gst_caps_is_equal (stream->priv->caps, caps))) { + gst_caps_replace (&stream->priv->caps, caps); + notify = TRUE; + } + GST_OBJECT_UNLOCK (stream); + + if (notify) + g_object_notify_by_pspec (G_OBJECT (stream), gst_stream_pspecs[PROP_CAPS]); +} + + +/** + * gst_stream_get_caps: + * @stream: a #GstStream + * + * Retrieve the caps for @stream, if any + * + * Returns: (transfer full) (nullable): The #GstCaps for @stream + * + * Since: 1.10 + */ +GstCaps * +gst_stream_get_caps (GstStream * stream) +{ + GstCaps *res = NULL; + + GST_OBJECT_LOCK (stream); + if (stream->priv->caps) + res = gst_caps_ref (stream->priv->caps); + GST_OBJECT_UNLOCK (stream); + + return res; +} + +static void +gst_stream_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStream *stream; + + stream = GST_STREAM_CAST (object); + + switch (prop_id) { + case PROP_STREAM_ID: + gst_stream_set_stream_id (stream, g_value_get_string (value)); + break; + case PROP_STREAM_FLAGS: + GST_OBJECT_LOCK (stream); + stream->priv->flags = g_value_get_flags (value); + GST_OBJECT_UNLOCK (stream); + break; + case PROP_STREAM_TYPE: + GST_OBJECT_LOCK (stream); + stream->priv->type = g_value_get_flags (value); + GST_OBJECT_UNLOCK (stream); + break; + case PROP_TAGS: + GST_OBJECT_LOCK (stream); + gst_mini_object_replace ((GstMiniObject **) & stream->priv->tags, + (GstMiniObject *) g_value_get_boxed (value)); + GST_OBJECT_UNLOCK (stream); + break; + case PROP_CAPS: + GST_OBJECT_LOCK (stream); + gst_mini_object_replace ((GstMiniObject **) & stream->priv->caps, + (GstMiniObject *) g_value_get_boxed (value)); + GST_OBJECT_UNLOCK (stream); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stream_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStream *stream; + + stream = GST_STREAM_CAST (object); + + switch (prop_id) { + case PROP_STREAM_ID: + g_value_set_string (value, gst_stream_get_stream_id (stream)); + break; + case PROP_STREAM_FLAGS: + g_value_set_flags (value, gst_stream_get_stream_flags (stream)); + break; + case PROP_STREAM_TYPE: + g_value_set_flags (value, gst_stream_get_stream_type (stream)); + break; + case PROP_TAGS: + g_value_take_boxed (value, gst_stream_get_tags (stream)); + break; + case PROP_CAPS: + g_value_take_boxed (value, gst_stream_get_caps (stream)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_stream_type_get_name: + * @stype: a #GstStreamType + * + * Get a descriptive string for a given #GstStreamType + * + * Returns: (nullable): A string describing the stream type + * + * Since: 1.10 + */ +const gchar * +gst_stream_type_get_name (GstStreamType stype) +{ + /* FIXME : Make this more flexible */ + switch (stype) { + case GST_STREAM_TYPE_UNKNOWN: + return "unknown"; + case GST_STREAM_TYPE_AUDIO: + return "audio"; + case GST_STREAM_TYPE_VIDEO: + return "video"; + case GST_STREAM_TYPE_CONTAINER: + return "container"; + case GST_STREAM_TYPE_TEXT: + return "text"; + default: + return NULL; + } + + return NULL; +} diff --git a/gst/gststreams.h b/gst/gststreams.h new file mode 100644 index 0000000..e3e52ad --- /dev/null +++ b/gst/gststreams.h @@ -0,0 +1,161 @@ +/* GStreamer + * Copyright (C) 2015 Centricular Ltd + * @author: Edward Hervey + * @author: Jan Schmidt + * + * gststreams.h : Header for GstStream subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_STREAMS_H__ +#define __GST_STREAMS_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM (gst_stream_get_type ()) +#define GST_IS_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAM)) +#define GST_IS_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_STREAM)) +#define GST_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_STREAM, GstStreamClass)) +#define GST_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAM, GstStream)) +#define GST_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_STREAM, GstStreamClass)) +#define GST_STREAM_CAST(obj) ((GstStream*)(obj)) + +/** + * GstStreamType: + * @GST_STREAM_TYPE_UNKNOWN: The stream is of unknown (unclassified) type. + * @GST_STREAM_TYPE_AUDIO: The stream is of audio data + * @GST_STREAM_TYPE_VIDEO: The stream carries video data + * @GST_STREAM_TYPE_CONTAINER: The stream is a muxed container type + * @GST_STREAM_TYPE_TEXT: The stream contains subtitle / subpicture data. + * + * #GstStreamType describes a high level classification set for + * flows of data in #GstStream objects. + * + * Note that this is a flag, and therefore users should not assume it + * will be a single value. Do not use the equality operator for checking + * whether a stream is of a certain type. + * + * Since: 1.10 + */ +typedef enum { + GST_STREAM_TYPE_UNKNOWN = 1 << 0, + GST_STREAM_TYPE_AUDIO = 1 << 1, + GST_STREAM_TYPE_VIDEO = 1 << 2, + GST_STREAM_TYPE_CONTAINER = 1 << 3, + GST_STREAM_TYPE_TEXT = 1 << 4 +} GstStreamType; + + +typedef struct _GstStream GstStream; +typedef struct _GstStreamClass GstStreamClass; +typedef struct _GstStreamPrivate GstStreamPrivate; + +/** + * GstStream: + * @stream_id: The Stream Identifier for this #GstStream + * + * A high-level object representing a single stream. It might be backed, or + * not, by an actual flow of data in a pipeline (#GstPad). + * + * A #GstStream does not care about data changes (such as decoding, encoding, + * parsing,...) as long as the underlying data flow corresponds to the same + * high-level flow (ex: a certain audio track). + * + * A #GstStream contains all the information pertinent to a stream, such as + * stream-id, tags, caps, type, ... + * + * Elements can subclass a #GstStream for internal usage (to contain information + * pertinent to streams of data). + * + * Since: 1.10 + */ +struct _GstStream { + /*< private >*/ + GstObject object; + + /*< public >*/ + const gchar *stream_id; + + /*< private >*/ + GstStreamPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstStreamClass: + * @parent_class: the parent class structure + * + * GstStream class structure + */ +struct _GstStreamClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_stream_get_type (void); + +#include + +GST_API +GstStream *gst_stream_new (const gchar *stream_id, + GstCaps *caps, + GstStreamType type, + GstStreamFlags flags); +GST_API +const gchar * gst_stream_get_stream_id (GstStream *stream); + +GST_API +void gst_stream_set_stream_flags (GstStream *stream, GstStreamFlags flags); + +GST_API +GstStreamFlags gst_stream_get_stream_flags (GstStream *stream); + +GST_API +void gst_stream_set_stream_type (GstStream *stream, GstStreamType stream_type); + +GST_API +GstStreamType gst_stream_get_stream_type (GstStream *stream); + +GST_API +void gst_stream_set_tags (GstStream *stream, GstTagList *tags); + +GST_API +GstTagList * gst_stream_get_tags (GstStream *stream); + +GST_API +void gst_stream_set_caps (GstStream *stream, GstCaps *caps); + +GST_API +GstCaps * gst_stream_get_caps (GstStream *stream); + +GST_API +const gchar * gst_stream_type_get_name (GstStreamType stype); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStream, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_STREAMS_H__ */ diff --git a/gst/gststructure.c b/gst/gststructure.c new file mode 100644 index 0000000..3b4d5b8 --- /dev/null +++ b/gst/gststructure.c @@ -0,0 +1,3142 @@ +/* GStreamer + * Copyright (C) 2003 David A. Schleef + * + * gststructure.c: lists of { GQuark, GValue } tuples + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gststructure + * @title: GstStructure + * @short_description: Generic structure containing fields of names and values + * @see_also: #GstCaps, #GstMessage, #GstEvent, #GstQuery + * + * A #GstStructure is a collection of key/value pairs. The keys are expressed + * as GQuarks and the values can be of any GType. + * + * In addition to the key/value pairs, a #GstStructure also has a name. The name + * starts with a letter and can be filled by letters, numbers and any of "/-_.:". + * + * #GstStructure is used by various GStreamer subsystems to store information + * in a flexible and extensible way. A #GstStructure does not have a refcount + * because it usually is part of a higher level object such as #GstCaps, + * #GstMessage, #GstEvent, #GstQuery. It provides a means to enforce mutability + * using the refcount of the parent with the gst_structure_set_parent_refcount() + * method. + * + * A #GstStructure can be created with gst_structure_new_empty() or + * gst_structure_new(), which both take a name and an optional set of + * key/value pairs along with the types of the values. + * + * Field values can be changed with gst_structure_set_value() or + * gst_structure_set(). + * + * Field values can be retrieved with gst_structure_get_value() or the more + * convenient gst_structure_get_*() functions. + * + * Fields can be removed with gst_structure_remove_field() or + * gst_structure_remove_fields(). + * + * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are + * not allowed. Strings may be %NULL however. + * + * Be aware that the current #GstCaps / #GstStructure serialization into string + * has limited support for nested #GstCaps / #GstStructure fields. It can only + * support one level of nesting. Using more levels will lead to unexpected + * behavior when using serialization features, such as gst_caps_to_string() or + * gst_value_serialize() and their counterparts. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* FIXME 2.0: suppress warnings for deprecated API such as GValueArray + * with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#include + +#include "gst_private.h" +#include "gstquark.h" +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_structure_debug); +#define GST_CAT_DEFAULT gst_structure_debug + +typedef struct _GstStructureField GstStructureField; + +struct _GstStructureField +{ + GQuark name; + GValue value; +}; + +typedef struct +{ + GstStructure s; + + /* owned by parent structure, NULL if no parent */ + gint *parent_refcount; + + GArray *fields; +} GstStructureImpl; + +#define GST_STRUCTURE_REFCOUNT(s) (((GstStructureImpl*)(s))->parent_refcount) +#define GST_STRUCTURE_FIELDS(s) (((GstStructureImpl*)(s))->fields) + +#define GST_STRUCTURE_FIELD(structure, index) \ + &g_array_index(GST_STRUCTURE_FIELDS(structure), GstStructureField, (index)) + +#define IS_MUTABLE(structure) \ + (!GST_STRUCTURE_REFCOUNT(structure) || \ + g_atomic_int_get (GST_STRUCTURE_REFCOUNT(structure)) == 1) + +#define IS_TAGLIST(structure) \ + (structure->name == GST_QUARK (TAGLIST)) + +static void gst_structure_set_field (GstStructure * structure, + GstStructureField * field); +static GstStructureField *gst_structure_get_field (const GstStructure * + structure, const gchar * fieldname); +static GstStructureField *gst_structure_id_get_field (const GstStructure * + structure, GQuark field); +static void gst_structure_transform_to_string (const GValue * src_value, + GValue * dest_value); +static GstStructure *gst_structure_copy_conditional (const GstStructure * + structure); + +GType _gst_structure_type = 0; + + +G_DEFINE_BOXED_TYPE (GstStructure, gst_structure, + gst_structure_copy_conditional, gst_structure_free); + +void +_priv_gst_structure_initialize (void) +{ + _gst_structure_type = gst_structure_get_type (); + + g_value_register_transform_func (_gst_structure_type, G_TYPE_STRING, + gst_structure_transform_to_string); + + GST_DEBUG_CATEGORY_INIT (gst_structure_debug, "structure", 0, + "GstStructure debug"); +} + +static GstStructure * +gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc) +{ + GstStructureImpl *structure; + + structure = g_slice_new (GstStructureImpl); + ((GstStructure *) structure)->type = _gst_structure_type; + ((GstStructure *) structure)->name = quark; + GST_STRUCTURE_REFCOUNT (structure) = NULL; + GST_STRUCTURE_FIELDS (structure) = + g_array_sized_new (FALSE, FALSE, sizeof (GstStructureField), prealloc); + + GST_TRACE ("created structure %p", structure); + + return GST_STRUCTURE_CAST (structure); +} + +/** + * gst_structure_new_id_empty: + * @quark: name of new structure + * + * Creates a new, empty #GstStructure with the given name as a GQuark. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new, empty #GstStructure + */ +GstStructure * +gst_structure_new_id_empty (GQuark quark) +{ + g_return_val_if_fail (quark != 0, NULL); + + return gst_structure_new_id_empty_with_size (quark, 0); +} + +#ifndef G_DISABLE_CHECKS +static gboolean +gst_structure_validate_name (const gchar * name) +{ + const gchar *s; + + g_return_val_if_fail (name != NULL, FALSE); + + if (G_UNLIKELY (!g_ascii_isalpha (*name))) { + GST_WARNING ("Invalid character '%c' at offset 0 in structure name: %s", + *name, name); + return FALSE; + } + + /* FIXME: test name string more */ + s = &name[1]; + while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL)) + s++; + if (G_UNLIKELY (*s != '\0')) { + GST_WARNING ("Invalid character '%c' at offset %" G_GUINTPTR_FORMAT " in" + " structure name: %s", *s, ((guintptr) s - (guintptr) name), name); + return FALSE; + } + + if (strncmp (name, "video/x-raw-", 12) == 0) { + g_warning ("0.10-style raw video caps are being created. Should be " + "video/x-raw,format=(string).. now."); + } else if (strncmp (name, "audio/x-raw-", 12) == 0) { + g_warning ("0.10-style raw audio caps are being created. Should be " + "audio/x-raw,format=(string).. now."); + } + + return TRUE; +} +#endif + +/** + * gst_structure_new_empty: + * @name: name of new structure + * + * Creates a new, empty #GstStructure with the given @name. + * + * See gst_structure_set_name() for constraints on the @name parameter. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new, empty #GstStructure + */ +GstStructure * +gst_structure_new_empty (const gchar * name) +{ + g_return_val_if_fail (gst_structure_validate_name (name), NULL); + + return gst_structure_new_id_empty_with_size (g_quark_from_string (name), 0); +} + +/** + * gst_structure_new: + * @name: name of new structure + * @firstfield: name of first field to set + * @...: additional arguments + * + * Creates a new #GstStructure with the given name. Parses the + * list of variable arguments and sets fields to the values listed. + * Variable arguments should be passed as field name, field type, + * and value. Last variable argument should be %NULL. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new #GstStructure + */ +GstStructure * +gst_structure_new (const gchar * name, const gchar * firstfield, ...) +{ + GstStructure *structure; + va_list varargs; + + va_start (varargs, firstfield); + structure = gst_structure_new_valist (name, firstfield, varargs); + va_end (varargs); + + return structure; +} + +/** + * gst_structure_new_valist: + * @name: name of new structure + * @firstfield: name of first field to set + * @varargs: variable argument list + * + * Creates a new #GstStructure with the given @name. Structure fields + * are set according to the varargs in a manner similar to + * gst_structure_new(). + * + * See gst_structure_set_name() for constraints on the @name parameter. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new #GstStructure + */ +GstStructure * +gst_structure_new_valist (const gchar * name, + const gchar * firstfield, va_list varargs) +{ + GstStructure *structure; + + structure = gst_structure_new_empty (name); + + if (structure) + gst_structure_set_valist (structure, firstfield, varargs); + + return structure; +} + +/** + * gst_structure_set_parent_refcount: + * @structure: a #GstStructure + * @refcount: (in): a pointer to the parent's refcount + * + * Sets the parent_refcount field of #GstStructure. This field is used to + * determine whether a structure is mutable or not. This function should only be + * called by code implementing parent objects of #GstStructure, as described in + * the MT Refcounting section of the design documents. + * + * Returns: %TRUE if the parent refcount could be set. + */ +gboolean +gst_structure_set_parent_refcount (GstStructure * structure, gint * refcount) +{ + g_return_val_if_fail (structure != NULL, FALSE); + + /* if we have a parent_refcount already, we can only clear + * if with a NULL refcount */ + if (GST_STRUCTURE_REFCOUNT (structure)) { + if (refcount != NULL) { + g_return_val_if_fail (refcount == NULL, FALSE); + return FALSE; + } + } else { + if (refcount == NULL) { + g_return_val_if_fail (refcount != NULL, FALSE); + return FALSE; + } + } + + GST_STRUCTURE_REFCOUNT (structure) = refcount; + + return TRUE; +} + +/** + * gst_structure_copy: + * @structure: a #GstStructure to duplicate + * + * Duplicates a #GstStructure and all its fields and values. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new #GstStructure. + */ +GstStructure * +gst_structure_copy (const GstStructure * structure) +{ + GstStructure *new_structure; + GstStructureField *field; + guint i, len; + + g_return_val_if_fail (structure != NULL, NULL); + + len = GST_STRUCTURE_FIELDS (structure)->len; + new_structure = gst_structure_new_id_empty_with_size (structure->name, len); + + for (i = 0; i < len; i++) { + GstStructureField new_field = { 0 }; + + field = GST_STRUCTURE_FIELD (structure, i); + + new_field.name = field->name; + gst_value_init_and_copy (&new_field.value, &field->value); + g_array_append_val (GST_STRUCTURE_FIELDS (new_structure), new_field); + } + GST_CAT_TRACE (GST_CAT_PERFORMANCE, "doing copy %p -> %p", + structure, new_structure); + + return new_structure; +} + +/** + * gst_structure_free: + * @structure: (in) (transfer full): the #GstStructure to free + * + * Frees a #GstStructure and all its fields and values. The structure must not + * have a parent when this function is called. + */ +void +gst_structure_free (GstStructure * structure) +{ + GstStructureField *field; + guint i, len; + + g_return_if_fail (structure != NULL); + g_return_if_fail (GST_STRUCTURE_REFCOUNT (structure) == NULL); + + len = GST_STRUCTURE_FIELDS (structure)->len; + for (i = 0; i < len; i++) { + field = GST_STRUCTURE_FIELD (structure, i); + + if (G_IS_VALUE (&field->value)) { + g_value_unset (&field->value); + } + } + g_array_free (GST_STRUCTURE_FIELDS (structure), TRUE); +#ifdef USE_POISONING + memset (structure, 0xff, sizeof (GstStructure)); +#endif + GST_TRACE ("free structure %p", structure); + + g_slice_free1 (sizeof (GstStructureImpl), structure); +} + +/** + * gst_structure_get_name: + * @structure: a #GstStructure + * + * Get the name of @structure as a string. + * + * Returns: the name of the structure. + */ +const gchar * +gst_structure_get_name (const GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, NULL); + + return g_quark_to_string (structure->name); +} + +/** + * gst_structure_has_name: + * @structure: a #GstStructure + * @name: structure name to check for + * + * Checks if the structure has the given name + * + * Returns: %TRUE if @name matches the name of the structure. + */ +gboolean +gst_structure_has_name (const GstStructure * structure, const gchar * name) +{ + const gchar *structure_name; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + /* getting the string is cheap and comparing short strings is too + * should be faster than getting the quark for name and comparing the quarks + */ + structure_name = g_quark_to_string (structure->name); + + return (structure_name && strcmp (structure_name, name) == 0); +} + +/** + * gst_structure_get_name_id: + * @structure: a #GstStructure + * + * Get the name of @structure as a GQuark. + * + * Returns: the quark representing the name of the structure. + */ +GQuark +gst_structure_get_name_id (const GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, 0); + + return structure->name; +} + +/** + * gst_structure_set_name: + * @structure: a #GstStructure + * @name: the new name of the structure + * + * Sets the name of the structure to the given @name. The string + * provided is copied before being used. It must not be empty, start with a + * letter and can be followed by letters, numbers and any of "/-_.:". + */ +void +gst_structure_set_name (GstStructure * structure, const gchar * name) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + g_return_if_fail (gst_structure_validate_name (name)); + + structure->name = g_quark_from_string (name); +} + +static inline void +gst_structure_id_set_value_internal (GstStructure * structure, GQuark field, + const GValue * value) +{ + GstStructureField gsfield = { 0, {0,} }; + + gsfield.name = field; + gst_value_init_and_copy (&gsfield.value, value); + + gst_structure_set_field (structure, &gsfield); +} + +/** + * gst_structure_id_set_value: + * @structure: a #GstStructure + * @field: a #GQuark representing a field + * @value: the new value of the field + * + * Sets the field with the given GQuark @field to @value. If the field + * does not exist, it is created. If the field exists, the previous + * value is replaced and freed. + */ +void +gst_structure_id_set_value (GstStructure * structure, + GQuark field, const GValue * value) +{ + + g_return_if_fail (structure != NULL); + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_id_set_value_internal (structure, field, value); +} + +/** + * gst_structure_set_value: + * @structure: a #GstStructure + * @fieldname: the name of the field to set + * @value: the new value of the field + * + * Sets the field with the given name @field to @value. If the field + * does not exist, it is created. If the field exists, the previous + * value is replaced and freed. + */ +void +gst_structure_set_value (GstStructure * structure, + const gchar * fieldname, const GValue * value) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_id_set_value_internal (structure, + g_quark_from_string (fieldname), value); +} + +static inline void +gst_structure_id_take_value_internal (GstStructure * structure, GQuark field, + GValue * value) +{ + GstStructureField gsfield = { 0, {0,} }; + + gsfield.name = field; + gsfield.value = *value; + + gst_structure_set_field (structure, &gsfield); + + /* we took ownership */ +#ifdef USE_POISONING + memset (value, 0, sizeof (GValue)); +#else + value->g_type = G_TYPE_INVALID; +#endif +} + +/** + * gst_structure_id_take_value: + * @structure: a #GstStructure + * @field: a #GQuark representing a field + * @value: (transfer full): the new value of the field + * + * Sets the field with the given GQuark @field to @value. If the field + * does not exist, it is created. If the field exists, the previous + * value is replaced and freed. + */ +void +gst_structure_id_take_value (GstStructure * structure, GQuark field, + GValue * value) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_id_take_value_internal (structure, field, value); +} + +/** + * gst_structure_take_value: + * @structure: a #GstStructure + * @fieldname: the name of the field to set + * @value: (transfer full): the new value of the field + * + * Sets the field with the given name @field to @value. If the field + * does not exist, it is created. If the field exists, the previous + * value is replaced and freed. The function will take ownership of @value. + */ +void +gst_structure_take_value (GstStructure * structure, const gchar * fieldname, + GValue * value) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_id_take_value_internal (structure, + g_quark_from_string (fieldname), value); +} + +static void +gst_structure_set_valist_internal (GstStructure * structure, + const gchar * fieldname, va_list varargs) +{ + gchar *err = NULL; + GType type; + + while (fieldname) { + GstStructureField field = { 0 }; + + field.name = g_quark_from_string (fieldname); + + type = va_arg (varargs, GType); + + G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err); + if (G_UNLIKELY (err)) { + g_critical ("%s", err); + return; + } + gst_structure_set_field (structure, &field); + + fieldname = va_arg (varargs, gchar *); + } +} + +/** + * gst_structure_set: + * @structure: a #GstStructure + * @fieldname: the name of the field to set + * @...: variable arguments + * + * Parses the variable arguments and sets fields accordingly. Fields that + * weren't already part of the structure are added as needed. + * Variable arguments should be in the form field name, field type + * (as a GType), value(s). The last variable argument should be %NULL. + */ +void +gst_structure_set (GstStructure * structure, const gchar * field, ...) +{ + va_list varargs; + + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure) || field == NULL); + + va_start (varargs, field); + gst_structure_set_valist_internal (structure, field, varargs); + va_end (varargs); +} + +/** + * gst_structure_set_valist: + * @structure: a #GstStructure + * @fieldname: the name of the field to set + * @varargs: variable arguments + * + * va_list form of gst_structure_set(). + */ +void +gst_structure_set_valist (GstStructure * structure, + const gchar * fieldname, va_list varargs) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_set_valist_internal (structure, fieldname, varargs); +} + +static void +gst_structure_id_set_valist_internal (GstStructure * structure, + GQuark fieldname, va_list varargs) +{ + gchar *err = NULL; + GType type; + + while (fieldname) { + GstStructureField field = { 0 }; + + field.name = fieldname; + type = va_arg (varargs, GType); + + G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err); + if (G_UNLIKELY (err)) { + g_critical ("%s", err); + return; + } + gst_structure_set_field (structure, &field); + + fieldname = va_arg (varargs, GQuark); + } +} + +/** + * gst_structure_id_set: + * @structure: a #GstStructure + * @fieldname: the GQuark for the name of the field to set + * @...: variable arguments + * + * Identical to gst_structure_set, except that field names are + * passed using the GQuark for the field name. This allows more efficient + * setting of the structure if the caller already knows the associated + * quark values. + * The last variable argument must be %NULL. + */ +void +gst_structure_id_set (GstStructure * structure, GQuark field, ...) +{ + va_list varargs; + + g_return_if_fail (structure != NULL); + + va_start (varargs, field); + gst_structure_id_set_valist_internal (structure, field, varargs); + va_end (varargs); +} + +/** + * gst_structure_id_set_valist: + * @structure: a #GstStructure + * @fieldname: the name of the field to set + * @varargs: variable arguments + * + * va_list form of gst_structure_id_set(). + */ +void +gst_structure_id_set_valist (GstStructure * structure, + GQuark fieldname, va_list varargs) +{ + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + + gst_structure_id_set_valist_internal (structure, fieldname, varargs); +} + +/** + * gst_structure_new_id: + * @name_quark: name of new structure + * @field_quark: the GQuark for the name of the field to set + * @...: variable arguments + * + * Creates a new #GstStructure with the given name as a GQuark, followed by + * fieldname quark, GType, argument(s) "triplets" in the same format as + * gst_structure_id_set(). Basically a convenience wrapper around + * gst_structure_new_id_empty() and gst_structure_id_set(). + * + * The last variable argument must be %NULL (or 0). + * + * Free-function: gst_structure_free + * + * Returns: (transfer full): a new #GstStructure + */ +GstStructure * +gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...) +{ + GstStructure *s; + va_list varargs; + + g_return_val_if_fail (name_quark != 0, NULL); + g_return_val_if_fail (field_quark != 0, NULL); + + s = gst_structure_new_id_empty (name_quark); + + va_start (varargs, field_quark); + gst_structure_id_set_valist_internal (s, field_quark, varargs); + va_end (varargs); + + return s; +} + +#if GST_VERSION_NANO == 1 +#define GIT_G_WARNING g_warning +#else +#define GIT_G_WARNING GST_WARNING +#endif + +/* If the structure currently contains a field with the same name, it is + * replaced with the provided field. Otherwise, the field is added to the + * structure. The field's value is not deeply copied. + */ +static void +gst_structure_set_field (GstStructure * structure, GstStructureField * field) +{ + GstStructureField *f; + GType field_value_type; + guint i, len; + + len = GST_STRUCTURE_FIELDS (structure)->len; + + field_value_type = G_VALUE_TYPE (&field->value); + if (field_value_type == G_TYPE_STRING) { + const gchar *s; + + s = g_value_get_string (&field->value); + /* only check for NULL strings in taglists, as they are allowed in message + * structs, e.g. error message debug strings */ + if (G_UNLIKELY (IS_TAGLIST (structure) && (s == NULL || *s == '\0'))) { + if (s == NULL) { + GIT_G_WARNING ("Trying to set NULL string on field '%s' on taglist. " + "Please file a bug.", g_quark_to_string (field->name)); + g_value_unset (&field->value); + return; + } else { + /* empty strings never make sense */ + GIT_G_WARNING ("Trying to set empty string on taglist field '%s'. " + "Please file a bug.", g_quark_to_string (field->name)); + g_value_unset (&field->value); + return; + } + } else if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) { + g_warning ("Trying to set string on %s field '%s', but string is not " + "valid UTF-8. Please file a bug.", + IS_TAGLIST (structure) ? "taglist" : "structure", + g_quark_to_string (field->name)); + g_value_unset (&field->value); + return; + } + } else if (G_UNLIKELY (field_value_type == G_TYPE_DATE)) { + const GDate *d; + + d = g_value_get_boxed (&field->value); + /* only check for NULL GDates in taglists, as they might make sense + * in other, generic structs */ + if (G_UNLIKELY ((IS_TAGLIST (structure) && d == NULL))) { + GIT_G_WARNING ("Trying to set NULL GDate on field '%s' on taglist. " + "Please file a bug.", g_quark_to_string (field->name)); + g_value_unset (&field->value); + return; + } else if (G_UNLIKELY (d != NULL && !g_date_valid (d))) { + g_warning + ("Trying to set invalid GDate on %s field '%s'. Please file a bug.", + IS_TAGLIST (structure) ? "taglist" : "structure", + g_quark_to_string (field->name)); + g_value_unset (&field->value); + return; + } + } + + for (i = 0; i < len; i++) { + f = GST_STRUCTURE_FIELD (structure, i); + + if (G_UNLIKELY (f->name == field->name)) { + g_value_unset (&f->value); + memcpy (f, field, sizeof (GstStructureField)); + return; + } + } + + g_array_append_val (GST_STRUCTURE_FIELDS (structure), *field); +} + +/* If there is no field with the given ID, NULL is returned. + */ +static GstStructureField * +gst_structure_id_get_field (const GstStructure * structure, GQuark field_id) +{ + GstStructureField *field; + guint i, len; + + len = GST_STRUCTURE_FIELDS (structure)->len; + + for (i = 0; i < len; i++) { + field = GST_STRUCTURE_FIELD (structure, i); + + if (G_UNLIKELY (field->name == field_id)) + return field; + } + + return NULL; +} + +/* If there is no field with the given ID, NULL is returned. + */ +static GstStructureField * +gst_structure_get_field (const GstStructure * structure, + const gchar * fieldname) +{ + g_return_val_if_fail (structure != NULL, NULL); + g_return_val_if_fail (fieldname != NULL, NULL); + + return gst_structure_id_get_field (structure, + g_quark_from_string (fieldname)); +} + +/** + * gst_structure_get_value: + * @structure: a #GstStructure + * @fieldname: the name of the field to get + * + * Get the value of the field with name @fieldname. + * + * Returns: (nullable): the #GValue corresponding to the field with the given + * name. + */ +const GValue * +gst_structure_get_value (const GstStructure * structure, + const gchar * fieldname) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, NULL); + g_return_val_if_fail (fieldname != NULL, NULL); + + field = gst_structure_get_field (structure, fieldname); + if (field == NULL) + return NULL; + + return &field->value; +} + +/** + * gst_structure_id_get_value: + * @structure: a #GstStructure + * @field: the #GQuark of the field to get + * + * Get the value of the field with GQuark @field. + * + * Returns: (nullable): the #GValue corresponding to the field with the given + * name identifier. + */ +const GValue * +gst_structure_id_get_value (const GstStructure * structure, GQuark field) +{ + GstStructureField *gsfield; + + g_return_val_if_fail (structure != NULL, NULL); + + gsfield = gst_structure_id_get_field (structure, field); + if (gsfield == NULL) + return NULL; + + return &gsfield->value; +} + +/** + * gst_structure_remove_field: + * @structure: a #GstStructure + * @fieldname: the name of the field to remove + * + * Removes the field with the given name. If the field with the given + * name does not exist, the structure is unchanged. + */ +void +gst_structure_remove_field (GstStructure * structure, const gchar * fieldname) +{ + GstStructureField *field; + GQuark id; + guint i, len; + + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + + id = g_quark_from_string (fieldname); + len = GST_STRUCTURE_FIELDS (structure)->len; + + for (i = 0; i < len; i++) { + field = GST_STRUCTURE_FIELD (structure, i); + + if (field->name == id) { + if (G_IS_VALUE (&field->value)) { + g_value_unset (&field->value); + } + GST_STRUCTURE_FIELDS (structure) = + g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i); + return; + } + } +} + +/** + * gst_structure_remove_fields: + * @structure: a #GstStructure + * @fieldname: the name of the field to remove + * @...: %NULL-terminated list of more fieldnames to remove + * + * Removes the fields with the given names. If a field does not exist, the + * argument is ignored. + */ +void +gst_structure_remove_fields (GstStructure * structure, + const gchar * fieldname, ...) +{ + va_list varargs; + + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + /* mutability checked in remove_field */ + + va_start (varargs, fieldname); + gst_structure_remove_fields_valist (structure, fieldname, varargs); + va_end (varargs); +} + +/** + * gst_structure_remove_fields_valist: + * @structure: a #GstStructure + * @fieldname: the name of the field to remove + * @varargs: %NULL-terminated list of more fieldnames to remove + * + * va_list form of gst_structure_remove_fields(). + */ +void +gst_structure_remove_fields_valist (GstStructure * structure, + const gchar * fieldname, va_list varargs) +{ + gchar *field = (gchar *) fieldname; + + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + /* mutability checked in remove_field */ + + while (field) { + gst_structure_remove_field (structure, field); + field = va_arg (varargs, char *); + } +} + +/** + * gst_structure_remove_all_fields: + * @structure: a #GstStructure + * + * Removes all fields in a GstStructure. + */ +void +gst_structure_remove_all_fields (GstStructure * structure) +{ + GstStructureField *field; + int i; + + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + + for (i = GST_STRUCTURE_FIELDS (structure)->len - 1; i >= 0; i--) { + field = GST_STRUCTURE_FIELD (structure, i); + + if (G_IS_VALUE (&field->value)) { + g_value_unset (&field->value); + } + GST_STRUCTURE_FIELDS (structure) = + g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i); + } +} + +/** + * gst_structure_get_field_type: + * @structure: a #GstStructure + * @fieldname: the name of the field + * + * Finds the field with the given name, and returns the type of the + * value it contains. If the field is not found, G_TYPE_INVALID is + * returned. + * + * Returns: the #GValue of the field + */ +GType +gst_structure_get_field_type (const GstStructure * structure, + const gchar * fieldname) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, G_TYPE_INVALID); + g_return_val_if_fail (fieldname != NULL, G_TYPE_INVALID); + + field = gst_structure_get_field (structure, fieldname); + if (field == NULL) + return G_TYPE_INVALID; + + return G_VALUE_TYPE (&field->value); +} + +/** + * gst_structure_n_fields: + * @structure: a #GstStructure + * + * Get the number of fields in the structure. + * + * Returns: the number of fields in the structure + */ +gint +gst_structure_n_fields (const GstStructure * structure) +{ + g_return_val_if_fail (structure != NULL, 0); + + return GST_STRUCTURE_FIELDS (structure)->len; +} + +/** + * gst_structure_nth_field_name: + * @structure: a #GstStructure + * @index: the index to get the name of + * + * Get the name of the given field number, counting from 0 onwards. + * + * Returns: the name of the given field number + */ +const gchar * +gst_structure_nth_field_name (const GstStructure * structure, guint index) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, NULL); + g_return_val_if_fail (index < GST_STRUCTURE_FIELDS (structure)->len, NULL); + + field = GST_STRUCTURE_FIELD (structure, index); + + return g_quark_to_string (field->name); +} + +/** + * gst_structure_foreach: + * @structure: a #GstStructure + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each field in the #GstStructure. The + * function must not modify the fields. Also see gst_structure_map_in_place() + * and gst_structure_filter_and_map_in_place(). + * + * Returns: %TRUE if the supplied function returns %TRUE For each of the fields, + * %FALSE otherwise. + */ +gboolean +gst_structure_foreach (const GstStructure * structure, + GstStructureForeachFunc func, gpointer user_data) +{ + guint i, len; + GstStructureField *field; + gboolean ret; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + len = GST_STRUCTURE_FIELDS (structure)->len; + + for (i = 0; i < len; i++) { + field = GST_STRUCTURE_FIELD (structure, i); + + ret = func (field->name, &field->value, user_data); + if (G_UNLIKELY (!ret)) + return FALSE; + } + + return TRUE; +} + +/** + * gst_structure_map_in_place: + * @structure: a #GstStructure + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each field in the #GstStructure. In + * contrast to gst_structure_foreach(), the function may modify but not delete the + * fields. The structure must be mutable. + * + * Returns: %TRUE if the supplied function returns %TRUE For each of the fields, + * %FALSE otherwise. + */ +gboolean +gst_structure_map_in_place (GstStructure * structure, + GstStructureMapFunc func, gpointer user_data) +{ + guint i, len; + GstStructureField *field; + gboolean ret; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + g_return_val_if_fail (func != NULL, FALSE); + len = GST_STRUCTURE_FIELDS (structure)->len; + + for (i = 0; i < len; i++) { + field = GST_STRUCTURE_FIELD (structure, i); + + ret = func (field->name, &field->value, user_data); + if (!ret) + return FALSE; + } + + return TRUE; +} + +/** + * gst_structure_filter_and_map_in_place: + * @structure: a #GstStructure + * @func: (scope call): a function to call for each field + * @user_data: (closure): private data + * + * Calls the provided function once for each field in the #GstStructure. In + * contrast to gst_structure_foreach(), the function may modify the fields. + * In contrast to gst_structure_map_in_place(), the field is removed from + * the structure if %FALSE is returned from the function. + * The structure must be mutable. + * + * Since: 1.6 + */ +void +gst_structure_filter_and_map_in_place (GstStructure * structure, + GstStructureFilterMapFunc func, gpointer user_data) +{ + guint i, len; + GstStructureField *field; + gboolean ret; + + g_return_if_fail (structure != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + g_return_if_fail (func != NULL); + len = GST_STRUCTURE_FIELDS (structure)->len; + + for (i = 0; i < len;) { + field = GST_STRUCTURE_FIELD (structure, i); + + ret = func (field->name, &field->value, user_data); + + if (!ret) { + if (G_IS_VALUE (&field->value)) { + g_value_unset (&field->value); + } + GST_STRUCTURE_FIELDS (structure) = + g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i); + len = GST_STRUCTURE_FIELDS (structure)->len; + } else { + i++; + } + } +} + +/** + * gst_structure_id_has_field: + * @structure: a #GstStructure + * @field: #GQuark of the field name + * + * Check if @structure contains a field named @field. + * + * Returns: %TRUE if the structure contains a field with the given name + */ +gboolean +gst_structure_id_has_field (const GstStructure * structure, GQuark field) +{ + GstStructureField *f; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (field != 0, FALSE); + + f = gst_structure_id_get_field (structure, field); + + return (f != NULL); +} + +/** + * gst_structure_has_field: + * @structure: a #GstStructure + * @fieldname: the name of a field + * + * Check if @structure contains a field named @fieldname. + * + * Returns: %TRUE if the structure contains a field with the given name + */ +gboolean +gst_structure_has_field (const GstStructure * structure, + const gchar * fieldname) +{ + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + + return gst_structure_id_has_field (structure, + g_quark_from_string (fieldname)); +} + +/** + * gst_structure_id_has_field_typed: + * @structure: a #GstStructure + * @field: #GQuark of the field name + * @type: the type of a value + * + * Check if @structure contains a field named @field and with GType @type. + * + * Returns: %TRUE if the structure contains a field with the given name and type + */ +gboolean +gst_structure_id_has_field_typed (const GstStructure * structure, + GQuark field, GType type) +{ + GstStructureField *f; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (field != 0, FALSE); + + f = gst_structure_id_get_field (structure, field); + if (f == NULL) + return FALSE; + + return (G_VALUE_TYPE (&f->value) == type); +} + +/** + * gst_structure_has_field_typed: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @type: the type of a value + * + * Check if @structure contains a field named @fieldname and with GType @type. + * + * Returns: %TRUE if the structure contains a field with the given name and type + */ +gboolean +gst_structure_has_field_typed (const GstStructure * structure, + const gchar * fieldname, GType type) +{ + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + + return gst_structure_id_has_field_typed (structure, + g_quark_from_string (fieldname), type); +} + +/* utility functions */ + +/** + * gst_structure_get_boolean: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a #gboolean to set + * + * Sets the boolean pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a boolean, this + * function returns %FALSE. + */ +gboolean +gst_structure_get_boolean (const GstStructure * structure, + const gchar * fieldname, gboolean * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_BOOLEAN) + return FALSE; + + *value = gst_g_value_get_boolean_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_int: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to an int to set + * + * Sets the int pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain an int, this function + * returns %FALSE. + */ +gboolean +gst_structure_get_int (const GstStructure * structure, + const gchar * fieldname, gint * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT) + return FALSE; + + *value = gst_g_value_get_int_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_uint: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a uint to set + * + * Sets the uint pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a uint, this function + * returns %FALSE. + */ +gboolean +gst_structure_get_uint (const GstStructure * structure, + const gchar * fieldname, guint * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT) + return FALSE; + + *value = gst_g_value_get_uint_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_int64: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a #gint64 to set + * + * Sets the #gint64 pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a #gint64, this function + * returns %FALSE. + * + * Since: 1.4 + */ +gboolean +gst_structure_get_int64 (const GstStructure * structure, + const gchar * fieldname, gint64 * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT64) + return FALSE; + + *value = gst_g_value_get_int64_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_uint64: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a #guint64 to set + * + * Sets the #guint64 pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a #guint64, this function + * returns %FALSE. + * + * Since: 1.4 + */ +gboolean +gst_structure_get_uint64 (const GstStructure * structure, + const gchar * fieldname, guint64 * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT64) + return FALSE; + + *value = gst_g_value_get_uint64_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_date: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out callee-allocates): a pointer to a #GDate to set + * + * Sets the date pointed to by @value corresponding to the date of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * On success @value will point to a newly-allocated copy of the date which + * should be freed with g_date_free() when no longer needed (note: this is + * inconsistent with e.g. gst_structure_get_string() which doesn't return a + * copy of the string). + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a data, this function + * returns %FALSE. + */ +gboolean +gst_structure_get_date (const GstStructure * structure, const gchar * fieldname, + GDate ** value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DATE) + return FALSE; + + /* FIXME: 2.0 g_value_dup_boxed() -> g_value_get_boxed() */ + *value = g_value_dup_boxed (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_date_time: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out callee-allocates): a pointer to a #GstDateTime to set + * + * Sets the datetime pointed to by @value corresponding to the datetime of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * On success @value will point to a reference of the datetime which + * should be unreffed with gst_date_time_unref() when no longer needed + * (note: this is inconsistent with e.g. gst_structure_get_string() + * which doesn't return a copy of the string). + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a data, this function + * returns %FALSE. + */ +gboolean +gst_structure_get_date_time (const GstStructure * structure, + const gchar * fieldname, GstDateTime ** value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL) + return FALSE; + if (!GST_VALUE_HOLDS_DATE_TIME (&field->value)) + return FALSE; + + /* FIXME 2.0: g_value_dup_boxed() -> g_value_get_boxed() */ + *value = g_value_dup_boxed (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_clock_time: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a #GstClockTime to set + * + * Sets the clock time pointed to by @value corresponding to the clock time + * of the given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a #GstClockTime, this + * function returns %FALSE. + */ +gboolean +gst_structure_get_clock_time (const GstStructure * structure, + const gchar * fieldname, GstClockTime * value) +{ + return gst_structure_get_uint64 (structure, fieldname, value); +} + +/** + * gst_structure_get_double: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a gdouble to set + * + * Sets the double pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a double, this + * function returns %FALSE. + */ +gboolean +gst_structure_get_double (const GstStructure * structure, + const gchar * fieldname, gdouble * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DOUBLE) + return FALSE; + + *value = gst_g_value_get_double_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_string: + * @structure: a #GstStructure + * @fieldname: the name of a field + * + * Finds the field corresponding to @fieldname, and returns the string + * contained in the field's value. Caller is responsible for making + * sure the field exists and has the correct type. + * + * The string should not be modified, and remains valid until the next + * call to a gst_structure_*() function with the given structure. + * + * Returns: (nullable): a pointer to the string or %NULL when the + * field did not exist or did not contain a string. + */ +const gchar * +gst_structure_get_string (const GstStructure * structure, + const gchar * fieldname) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, NULL); + g_return_val_if_fail (fieldname != NULL, NULL); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_STRING) + return NULL; + + return gst_g_value_get_string_unchecked (&field->value); +} + +/** + * gst_structure_get_enum: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @enumtype: the enum type of a field + * @value: (out): a pointer to an int to set + * + * Sets the int pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists, + * has the correct type and that the enumtype is correct. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain an enum of the given + * type, this function returns %FALSE. + */ +gboolean +gst_structure_get_enum (const GstStructure * structure, + const gchar * fieldname, GType enumtype, gint * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (enumtype != G_TYPE_INVALID, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL) + return FALSE; + if (!G_TYPE_CHECK_VALUE_TYPE (&field->value, enumtype)) + return FALSE; + + *value = g_value_get_enum (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_fraction: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value_numerator: (out): a pointer to an int to set + * @value_denominator: (out): a pointer to an int to set + * + * Sets the integers pointed to by @value_numerator and @value_denominator + * corresponding to the value of the given field. Caller is responsible + * for making sure the field exists and has the correct type. + * + * Returns: %TRUE if the values could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a GstFraction, this + * function returns %FALSE. + */ +gboolean +gst_structure_get_fraction (const GstStructure * structure, + const gchar * fieldname, gint * value_numerator, gint * value_denominator) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value_numerator != NULL, FALSE); + g_return_val_if_fail (value_denominator != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != GST_TYPE_FRACTION) + return FALSE; + + *value_numerator = gst_value_get_fraction_numerator (&field->value); + *value_denominator = gst_value_get_fraction_denominator (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_flagset: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value_flags: (out) (allow-none): a pointer to a guint for the flags field + * @value_mask: (out) (allow-none): a pointer to a guint for the mask field + * + * Read the GstFlagSet flags and mask out of the structure into the + * provided pointers. + * + * Returns: %TRUE if the values could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a GstFlagSet, this + * function returns %FALSE. + * + * Since: 1.6 + */ +gboolean +gst_structure_get_flagset (const GstStructure * structure, + const gchar * fieldname, guint * value_flags, guint * value_mask) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || !GST_VALUE_HOLDS_FLAG_SET (&field->value)) + return FALSE; + + if (value_flags) + *value_flags = gst_value_get_flagset_flags (&field->value); + if (value_mask) + *value_mask = gst_value_get_flagset_mask (&field->value); + + return TRUE; +} + +static GType +gst_structure_value_get_generic_type (const GValue * val) +{ + if (G_VALUE_TYPE (val) == GST_TYPE_LIST + || G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + GArray *array = g_value_peek_pointer (val); + + if (array->len > 0) { + GValue *value = &g_array_index (array, GValue, 0); + + return gst_structure_value_get_generic_type (value); + } else { + return G_TYPE_INT; + } + } else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE) { + return G_TYPE_INT; + } else if (G_VALUE_TYPE (val) == GST_TYPE_INT64_RANGE) { + return G_TYPE_INT64; + } else if (G_VALUE_TYPE (val) == GST_TYPE_DOUBLE_RANGE) { + return G_TYPE_DOUBLE; + } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { + return GST_TYPE_FRACTION; + } + return G_VALUE_TYPE (val); +} + +gboolean +priv_gst_structure_append_to_gstring (const GstStructure * structure, + GString * s) +{ + GstStructureField *field; + guint i, len; + + g_return_val_if_fail (s != NULL, FALSE); + + len = GST_STRUCTURE_FIELDS (structure)->len; + for (i = 0; i < len; i++) { + char *t; + GType type; + + field = GST_STRUCTURE_FIELD (structure, i); + + if (G_VALUE_TYPE (&field->value) == GST_TYPE_ARRAY) { + t = _priv_gst_value_serialize_any_list (&field->value, "< ", " >", FALSE); + } else if (G_VALUE_TYPE (&field->value) == GST_TYPE_LIST) { + t = _priv_gst_value_serialize_any_list (&field->value, "{ ", " }", FALSE); + } else { + t = gst_value_serialize (&field->value); + } + + type = gst_structure_value_get_generic_type (&field->value); + + g_string_append_len (s, ", ", 2); + /* FIXME: do we need to escape fieldnames? */ + g_string_append (s, g_quark_to_string (field->name)); + g_string_append_len (s, "=(", 2); + g_string_append (s, _priv_gst_value_gtype_to_abbr (type)); + g_string_append_c (s, ')'); + if (t) { + g_string_append (s, t); + g_free (t); + } else { + if (!G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_STRING) && + !(G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_POINTER) && + g_value_get_pointer (&field->value) == NULL)) + GST_WARNING ("No value transform to serialize field '%s' of type '%s'", + g_quark_to_string (field->name), + _priv_gst_value_gtype_to_abbr (type)); + /* TODO(ensonic): don't print NULL if field->value is not empty */ + g_string_append (s, "NULL"); + } + } + + g_string_append_c (s, ';'); + return TRUE; +} + +gboolean +priv__gst_structure_append_template_to_gstring (GQuark field_id, + const GValue * value, gpointer user_data) +{ + GType type = gst_structure_value_get_generic_type (value); + GString *s = (GString *) user_data; + + g_string_append_len (s, ", ", 2); + /* FIXME: do we need to escape fieldnames? */ + g_string_append (s, g_quark_to_string (field_id)); + g_string_append_len (s, "=(", 2); + g_string_append (s, _priv_gst_value_gtype_to_abbr (type)); + g_string_append_c (s, ')'); + + //TODO(ensonic): table like GstStructureAbbreviation (or extend it) + if (type == G_TYPE_INT) { + g_string_append_len (s, "%i", 2); + } else if (type == G_TYPE_UINT) { + g_string_append_len (s, "%u", 2); + } else if (type == G_TYPE_FLOAT) { + g_string_append_len (s, "%f", 2); + } else if (type == G_TYPE_DOUBLE) { + g_string_append_len (s, "%lf", 3); + } else if (type == G_TYPE_STRING) { + g_string_append_len (s, "%s", 2); + } else if (type == G_TYPE_BOOLEAN) { + /* we normally store this as a string, but can parse it also from an int */ + g_string_append_len (s, "%i", 2); + } else if (type == G_TYPE_INT64) { + g_string_append (s, "%" G_GINT64_FORMAT); + } else if (type == G_TYPE_UINT64) { + g_string_append (s, "%" G_GUINT64_FORMAT); + } else if (type == GST_TYPE_STRUCTURE) { + g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT); + } else if (g_type_is_a (type, G_TYPE_ENUM) + || g_type_is_a (type, G_TYPE_FLAGS)) { + g_string_append_len (s, "%i", 2); + } else if (type == G_TYPE_GTYPE) { + g_string_append_len (s, "%s", 2); + } else if (type == G_TYPE_POINTER) { + g_string_append_len (s, "%p", 2); + } else { + GST_WARNING ("unhandled type: %s", g_type_name (type)); + g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT); + } + + return TRUE; +} + +/** + * gst_structure_to_string: + * @structure: a #GstStructure + * + * Converts @structure to a human-readable string representation. + * + * For debugging purposes its easier to do something like this: + * |[ + * GST_LOG ("structure is %" GST_PTR_FORMAT, structure); + * ]| + * This prints the structure in human readable form. + * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * + * Free-function: g_free + * + * Returns: (transfer full): a pointer to string allocated by g_malloc(). + * g_free() after usage. + */ +gchar * +gst_structure_to_string (const GstStructure * structure) +{ + GString *s; + + /* NOTE: This function is potentially called by the debug system, + * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.) + * should be careful to avoid recursion. This includes any functions + * called by gst_structure_to_string. In particular, calls should + * not use the GST_PTR_FORMAT extension. */ + + g_return_val_if_fail (structure != NULL, NULL); + + /* we estimate a minimum size based on the number of fields in order to + * avoid unnecessary reallocs within GString */ + s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure)); + g_string_append (s, g_quark_to_string (structure->name)); + priv_gst_structure_append_to_gstring (structure, s); + return g_string_free (s, FALSE); +} + +static gboolean +gst_structure_parse_field (gchar * str, + gchar ** after, GstStructureField * field) +{ + gchar *name; + gchar *name_end; + gchar *s; + gchar c; + + s = str; + + while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1]))) + s++; + name = s; + if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &name_end))) { + GST_WARNING ("failed to parse simple string, str=%s", str); + return FALSE; + } + + s = name_end; + while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1]))) + s++; + + if (G_UNLIKELY (*s != '=')) { + GST_WARNING ("missing assignment operator in the field, str=%s", str); + return FALSE; + } + s++; + + c = *name_end; + *name_end = '\0'; + field->name = g_quark_from_string (name); + GST_DEBUG ("trying field name '%s'", name); + *name_end = c; + + if (G_UNLIKELY (!_priv_gst_value_parse_value (s, &s, &field->value, + G_TYPE_INVALID))) { + GST_WARNING ("failed to parse value %s", str); + return FALSE; + } + + *after = s; + return TRUE; +} + +gboolean +priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end, + gchar ** next) +{ + char *w; + char *r; + + r = str; + + /* skip spaces (FIXME: _isspace treats tabs and newlines as space!) */ + while (*r && (g_ascii_isspace (*r) || (r[0] == '\\' + && g_ascii_isspace (r[1])))) + r++; + + *start = r; + + if (G_UNLIKELY (!_priv_gst_value_parse_string (r, &w, &r, TRUE))) { + GST_WARNING ("Failed to parse structure string '%s'", str); + return FALSE; + } + + *end = w; + *next = r; + + return TRUE; +} + +gboolean +priv_gst_structure_parse_fields (gchar * str, gchar ** end, + GstStructure * structure) +{ + gchar *r; + GstStructureField field; + + r = str; + + do { + while (*r && (g_ascii_isspace (*r) || (r[0] == '\\' + && g_ascii_isspace (r[1])))) + r++; + if (*r == ';') { + /* end of structure, get the next char and finish */ + r++; + break; + } + if (*r == '\0') { + /* accept \0 as end delimiter */ + break; + } + if (G_UNLIKELY (*r != ',')) { + GST_WARNING ("Failed to find delimiter, r=%s", r); + return FALSE; + } + r++; + while (*r && (g_ascii_isspace (*r) || (r[0] == '\\' + && g_ascii_isspace (r[1])))) + r++; + + memset (&field, 0, sizeof (field)); + if (G_UNLIKELY (!gst_structure_parse_field (r, &r, &field))) { + GST_WARNING ("Failed to parse field, r=%s", r); + return FALSE; + } + gst_structure_set_field (structure, &field); + } while (TRUE); + + *end = r; + + return TRUE; +} + +/** + * gst_structure_new_from_string: + * @string: a string representation of a #GstStructure + * + * Creates a #GstStructure from a string representation. + * If end is not %NULL, a pointer to the place inside the given string + * where parsing ended will be returned. + * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full) (nullable): a new #GstStructure or %NULL + * when the string could not be parsed. Free with + * gst_structure_free() after use. + * + * Since: 1.2 + */ +GstStructure * +gst_structure_new_from_string (const gchar * string) +{ + return gst_structure_from_string (string, NULL); +} + +/** + * gst_structure_from_string: + * @string: a string representation of a #GstStructure. + * @end: (out) (allow-none) (transfer none) (skip): pointer to store the end of the string in. + * + * Creates a #GstStructure from a string representation. + * If end is not %NULL, a pointer to the place inside the given string + * where parsing ended will be returned. + * + * Free-function: gst_structure_free + * + * Returns: (transfer full) (nullable): a new #GstStructure or %NULL + * when the string could not be parsed. Free with + * gst_structure_free() after use. + */ +GstStructure * +gst_structure_from_string (const gchar * string, gchar ** end) +{ + char *name; + char *copy; + char *w; + char *r; + char save; + GstStructure *structure = NULL; + + g_return_val_if_fail (string != NULL, NULL); + + copy = g_strdup (string); + r = copy; + + if (!priv_gst_structure_parse_name (r, &name, &w, &r)) + goto error; + + save = *w; + *w = '\0'; + structure = gst_structure_new_empty (name); + *w = save; + + if (G_UNLIKELY (structure == NULL)) + goto error; + + if (!priv_gst_structure_parse_fields (r, &r, structure)) + goto error; + + if (end) + *end = (char *) string + (r - copy); + else if (*r) + g_warning ("gst_structure_from_string did not consume whole string," + " but caller did not provide end pointer (\"%s\")", string); + + g_free (copy); + return structure; + +error: + if (structure) + gst_structure_free (structure); + g_free (copy); + return NULL; +} + +static void +gst_structure_transform_to_string (const GValue * src_value, + GValue * dest_value) +{ + g_return_if_fail (src_value != NULL); + g_return_if_fail (dest_value != NULL); + + dest_value->data[0].v_pointer = + gst_structure_to_string (src_value->data[0].v_pointer); +} + +static GstStructure * +gst_structure_copy_conditional (const GstStructure * structure) +{ + if (structure) + return gst_structure_copy (structure); + return NULL; +} + +/* fixate utility functions */ + +/** + * gst_structure_fixate_field_nearest_int: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target: the target value of the fixation + * + * Fixates a #GstStructure by changing the given field to the nearest + * integer to @target that is a subset of the existing field. + * + * Returns: %TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_nearest_int (GstStructure * structure, + const char *field_name, int target) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == G_TYPE_INT) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_INT_RANGE) { + int x; + + x = gst_value_get_int_range_min (value); + if (target < x) + target = x; + x = gst_value_get_int_range_max (value); + if (target > x) + target = x; + gst_structure_set (structure, field_name, G_TYPE_INT, target, NULL); + return TRUE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + int best = 0; + int best_index = -1; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == G_TYPE_INT) { + int x = gst_g_value_get_int_unchecked (list_value); + + if (best_index == -1 || (ABS (target - x) < ABS (target - best))) { + best_index = i; + best = x; + } + } + } + if (best_index != -1) { + gst_structure_set (structure, field_name, G_TYPE_INT, best, NULL); + return TRUE; + } + return FALSE; + } + + return FALSE; +} + +/** + * gst_structure_fixate_field_nearest_double: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target: the target value of the fixation + * + * Fixates a #GstStructure by changing the given field to the nearest + * double to @target that is a subset of the existing field. + * + * Returns: %TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_nearest_double (GstStructure * structure, + const char *field_name, double target) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_DOUBLE_RANGE) { + double x; + + x = gst_value_get_double_range_min (value); + if (target < x) + target = x; + x = gst_value_get_double_range_max (value); + if (target > x) + target = x; + gst_structure_set (structure, field_name, G_TYPE_DOUBLE, target, NULL); + return TRUE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + double best = 0; + int best_index = -1; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == G_TYPE_DOUBLE) { + double x = gst_g_value_get_double_unchecked (list_value); + + if (best_index == -1 || (ABS (target - x) < ABS (target - best))) { + best_index = i; + best = x; + } + } + } + if (best_index != -1) { + gst_structure_set (structure, field_name, G_TYPE_DOUBLE, best, NULL); + return TRUE; + } + return FALSE; + } + + return FALSE; + +} + +/** + * gst_structure_fixate_field_boolean: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target: the target value of the fixation + * + * Fixates a #GstStructure by changing the given @field_name field to the given + * @target boolean if that field is not fixed yet. + * + * Returns: %TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_boolean (GstStructure * structure, + const char *field_name, gboolean target) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + int best = 0; + int best_index = -1; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == G_TYPE_BOOLEAN) { + gboolean x = gst_g_value_get_boolean_unchecked (list_value); + + if (best_index == -1 || x == target) { + best_index = i; + best = x; + } + } + } + if (best_index != -1) { + gst_structure_set (structure, field_name, G_TYPE_BOOLEAN, best, NULL); + return TRUE; + } + return FALSE; + } + + return FALSE; +} + +/** + * gst_structure_fixate_field_string: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target: the target value of the fixation + * + * Fixates a #GstStructure by changing the given @field_name field to the given + * @target string if that field is not fixed yet. + * + * Returns: %TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_string (GstStructure * structure, + const gchar * field_name, const gchar * target) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == G_TYPE_STRING) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + const gchar *best = NULL; + int best_index = -1; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == G_TYPE_STRING) { + const gchar *x = g_value_get_string (list_value); + + if (best_index == -1 || g_str_equal (x, target)) { + best_index = i; + best = x; + } + } + } + if (best_index != -1) { + gst_structure_set (structure, field_name, G_TYPE_STRING, best, NULL); + return TRUE; + } + return FALSE; + } + + return FALSE; +} + +/** + * gst_structure_fixate_field_nearest_fraction: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target_numerator: The numerator of the target value of the fixation + * @target_denominator: The denominator of the target value of the fixation + * + * Fixates a #GstStructure by changing the given field to the nearest + * fraction to @target_numerator/@target_denominator that is a subset + * of the existing field. + * + * Returns: %TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_nearest_fraction (GstStructure * structure, + const char *field_name, const gint target_numerator, + const gint target_denominator) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + g_return_val_if_fail (target_denominator != 0, FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION_RANGE) { + const GValue *x, *new_value; + GValue target = { 0 }; + g_value_init (&target, GST_TYPE_FRACTION); + gst_value_set_fraction (&target, target_numerator, target_denominator); + + new_value = ⌖ + x = gst_value_get_fraction_range_min (value); + if (gst_value_compare (&target, x) == GST_VALUE_LESS_THAN) + new_value = x; + x = gst_value_get_fraction_range_max (value); + if (gst_value_compare (&target, x) == GST_VALUE_GREATER_THAN) + new_value = x; + + gst_structure_set_value (structure, field_name, new_value); + g_value_unset (&target); + return TRUE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + const GValue *best = NULL; + gdouble target; + gdouble cur_diff; + gdouble best_diff = G_MAXDOUBLE; + + target = (gdouble) target_numerator / (gdouble) target_denominator; + + GST_DEBUG ("target %g, best %g", target, best_diff); + + best = NULL; + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) { + gint num, denom; + gdouble list_double; + + num = gst_value_get_fraction_numerator (list_value); + denom = gst_value_get_fraction_denominator (list_value); + + list_double = ((gdouble) num / (gdouble) denom); + cur_diff = target - list_double; + + GST_DEBUG ("curr diff %g, list %g", cur_diff, list_double); + + if (cur_diff < 0) + cur_diff = -cur_diff; + + if (!best || cur_diff < best_diff) { + GST_DEBUG ("new best %g", list_double); + best = list_value; + best_diff = cur_diff; + } + } + } + if (best != NULL) { + gst_structure_set_value (structure, field_name, best); + return TRUE; + } + } + + return FALSE; +} + +static gboolean +default_fixate (GQuark field_id, const GValue * value, gpointer data) +{ + GstStructure *s = data; + GValue v = { 0 }; + + if (gst_value_fixate (&v, value)) { + gst_structure_id_take_value (s, field_id, &v); + } + return TRUE; +} + +/** + * gst_structure_fixate_field: + * @structure: a #GstStructure + * @field_name: a field in @structure + * + * Fixates a #GstStructure by changing the given field with its fixated value. + * + * Returns: %TRUE if the structure field could be fixated + */ +gboolean +gst_structure_fixate_field (GstStructure * structure, const char *field_name) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + + if (!(field = gst_structure_get_field (structure, field_name))) + return FALSE; + + return default_fixate (field->name, &field->value, structure); +} + +/* our very own version of G_VALUE_LCOPY that allows NULL return locations + * (useful for message parsing functions where the return location is user + * supplied and the user may pass %NULL if the value isn't of interest) */ +#define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname) \ +G_STMT_START { \ + const GValue *_value = (value); \ + guint _flags = (flags); \ + GType _value_type = G_VALUE_TYPE (_value); \ + GTypeValueTable *_vtable = g_type_value_table_peek (_value_type); \ + const gchar *_lcopy_format = _vtable->lcopy_format; \ + GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, }; \ + guint _n_values = 0; \ + \ + while (*_lcopy_format != '\0') { \ + g_assert (*_lcopy_format == G_VALUE_COLLECT_POINTER); \ + _cvalues[_n_values++].v_pointer = va_arg ((var_args), gpointer); \ + _lcopy_format++; \ + } \ + if (_n_values == 2 && !!_cvalues[0].v_pointer != !!_cvalues[1].v_pointer) { \ + *(__error) = g_strdup_printf ("either all or none of the return " \ + "locations for field '%s' need to be NULL", fieldname); \ + } else if (_cvalues[0].v_pointer != NULL) { \ + *(__error) = _vtable->lcopy_value (_value, _n_values, _cvalues, _flags); \ + } \ +} G_STMT_END + +/** + * gst_structure_get_valist: + * @structure: a #GstStructure + * @first_fieldname: the name of the first field to read + * @args: variable arguments + * + * Parses the variable arguments and reads fields from @structure accordingly. + * valist-variant of gst_structure_get(). Look at the documentation of + * gst_structure_get() for more details. + * + * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields + */ +gboolean +gst_structure_get_valist (const GstStructure * structure, + const char *first_fieldname, va_list args) +{ + const char *field_name; + GType expected_type = G_TYPE_INVALID; + + g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE); + g_return_val_if_fail (first_fieldname != NULL, FALSE); + + field_name = first_fieldname; + while (field_name) { + const GValue *val = NULL; + gchar *err = NULL; + + expected_type = va_arg (args, GType); + + val = gst_structure_get_value (structure, field_name); + + if (val == NULL) + goto no_such_field; + + if (G_VALUE_TYPE (val) != expected_type) + goto wrong_type; + + GST_VALUE_LCOPY (val, args, 0, &err, field_name); + if (err) { + g_warning ("%s: %s", G_STRFUNC, err); + g_free (err); + return FALSE; + } + + field_name = va_arg (args, const gchar *); + } + + return TRUE; + +/* ERRORS */ +no_such_field: + { + GST_INFO ("Expected field '%s' in structure: %" GST_PTR_FORMAT, + field_name, structure); + return FALSE; + } +wrong_type: + { + GST_INFO ("Expected field '%s' in structure to be of type '%s', but " + "field was of type '%s': %" GST_PTR_FORMAT, field_name, + GST_STR_NULL (g_type_name (expected_type)), + G_VALUE_TYPE_NAME (gst_structure_get_value (structure, field_name)), + structure); + return FALSE; + } +} + +/** + * gst_structure_id_get_valist: + * @structure: a #GstStructure + * @first_field_id: the quark of the first field to read + * @args: variable arguments + * + * Parses the variable arguments and reads fields from @structure accordingly. + * valist-variant of gst_structure_id_get(). Look at the documentation of + * gst_structure_id_get() for more details. + * + * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields + */ +gboolean +gst_structure_id_get_valist (const GstStructure * structure, + GQuark first_field_id, va_list args) +{ + GQuark field_id; + GType expected_type = G_TYPE_INVALID; + + g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE); + g_return_val_if_fail (first_field_id != 0, FALSE); + + field_id = first_field_id; + while (field_id) { + const GValue *val = NULL; + gchar *err = NULL; + + expected_type = va_arg (args, GType); + + val = gst_structure_id_get_value (structure, field_id); + + if (val == NULL) + goto no_such_field; + + if (G_VALUE_TYPE (val) != expected_type) + goto wrong_type; + + GST_VALUE_LCOPY (val, args, 0, &err, g_quark_to_string (field_id)); + if (err) { + g_warning ("%s: %s", G_STRFUNC, err); + g_free (err); + return FALSE; + } + + field_id = va_arg (args, GQuark); + } + + return TRUE; + +/* ERRORS */ +no_such_field: + { + GST_DEBUG ("Expected field '%s' in structure: %" GST_PTR_FORMAT, + GST_STR_NULL (g_quark_to_string (field_id)), structure); + return FALSE; + } +wrong_type: + { + GST_DEBUG ("Expected field '%s' in structure to be of type '%s', but " + "field was of type '%s': %" GST_PTR_FORMAT, + g_quark_to_string (field_id), + GST_STR_NULL (g_type_name (expected_type)), + G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)), + structure); + return FALSE; + } +} + +/** + * gst_structure_get: + * @structure: a #GstStructure + * @first_fieldname: the name of the first field to read + * @...: variable arguments + * + * Parses the variable arguments and reads fields from @structure accordingly. + * Variable arguments should be in the form field name, field type + * (as a GType), pointer(s) to a variable(s) to hold the return value(s). + * The last variable argument should be %NULL. + * + * For refcounted (mini)objects you will receive a new reference which + * you must release with a suitable _unref() when no longer needed. For + * strings and boxed types you will receive a copy which you will need to + * release with either g_free() or the suitable function for the boxed type. + * + * Returns: %FALSE if there was a problem reading any of the fields (e.g. + * because the field requested did not exist, or was of a type other + * than the type specified), otherwise %TRUE. + */ +gboolean +gst_structure_get (const GstStructure * structure, const char *first_fieldname, + ...) +{ + gboolean ret; + va_list args; + + g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE); + g_return_val_if_fail (first_fieldname != NULL, FALSE); + + va_start (args, first_fieldname); + ret = gst_structure_get_valist (structure, first_fieldname, args); + va_end (args); + + return ret; +} + +/** + * gst_structure_id_get: + * @structure: a #GstStructure + * @first_field_id: the quark of the first field to read + * @...: variable arguments + * + * Parses the variable arguments and reads fields from @structure accordingly. + * Variable arguments should be in the form field id quark, field type + * (as a GType), pointer(s) to a variable(s) to hold the return value(s). + * The last variable argument should be %NULL (technically it should be a + * 0 quark, but we require %NULL so compilers that support it can check for + * the %NULL terminator and warn if it's not there). + * + * This function is just like gst_structure_get() only that it is slightly + * more efficient since it saves the string-to-quark lookup in the global + * quark hashtable. + * + * For refcounted (mini)objects you will receive a new reference which + * you must release with a suitable _unref() when no longer needed. For + * strings and boxed types you will receive a copy which you will need to + * release with either g_free() or the suitable function for the boxed type. + * + * Returns: %FALSE if there was a problem reading any of the fields (e.g. + * because the field requested did not exist, or was of a type other + * than the type specified), otherwise %TRUE. + */ +gboolean +gst_structure_id_get (const GstStructure * structure, GQuark first_field_id, + ...) +{ + gboolean ret; + va_list args; + + g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE); + g_return_val_if_fail (first_field_id != 0, FALSE); + + va_start (args, first_field_id); + ret = gst_structure_id_get_valist (structure, first_field_id, args); + va_end (args); + + return ret; +} + +static gboolean +gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2, + gpointer data) +{ + const GstStructure *struct1 = (const GstStructure *) data; + const GValue *val1 = gst_structure_id_get_value (struct1, field_id); + + if (G_UNLIKELY (val1 == NULL)) + return FALSE; + if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) { + return TRUE; + } + + return FALSE; +} + +/** + * gst_structure_is_equal: + * @structure1: a #GstStructure. + * @structure2: a #GstStructure. + * + * Tests if the two #GstStructure are equal. + * + * Returns: %TRUE if the two structures have the same name and field. + **/ +gboolean +gst_structure_is_equal (const GstStructure * structure1, + const GstStructure * structure2) +{ + g_return_val_if_fail (GST_IS_STRUCTURE (structure1), FALSE); + g_return_val_if_fail (GST_IS_STRUCTURE (structure2), FALSE); + + if (G_UNLIKELY (structure1 == structure2)) + return TRUE; + + if (structure1->name != structure2->name) { + return FALSE; + } + if (GST_STRUCTURE_FIELDS (structure1)->len != + GST_STRUCTURE_FIELDS (structure2)->len) { + return FALSE; + } + + return gst_structure_foreach (structure1, gst_structure_is_equal_foreach, + (gpointer) structure2); +} + + +typedef struct +{ + GstStructure *dest; + const GstStructure *intersect; +} +IntersectData; + +static gboolean +gst_structure_intersect_field1 (GQuark id, const GValue * val1, gpointer data) +{ + IntersectData *idata = (IntersectData *) data; + const GValue *val2 = gst_structure_id_get_value (idata->intersect, id); + + if (G_UNLIKELY (val2 == NULL)) { + gst_structure_id_set_value (idata->dest, id, val1); + } else { + GValue dest_value = { 0 }; + if (gst_value_intersect (&dest_value, val1, val2)) { + gst_structure_id_take_value (idata->dest, id, &dest_value); + } else { + return FALSE; + } + } + return TRUE; +} + +static gboolean +gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data) +{ + IntersectData *idata = (IntersectData *) data; + const GValue *val2 = gst_structure_id_get_value (idata->intersect, id); + + if (G_UNLIKELY (val2 == NULL)) { + gst_structure_id_set_value (idata->dest, id, val1); + } + return TRUE; +} + +/** + * gst_structure_intersect: + * @struct1: a #GstStructure + * @struct2: a #GstStructure + * + * Intersects @struct1 and @struct2 and returns the intersection. + * + * Returns: (nullable): Intersection of @struct1 and @struct2 + */ +GstStructure * +gst_structure_intersect (const GstStructure * struct1, + const GstStructure * struct2) +{ + IntersectData data; + + g_assert (struct1 != NULL); + g_assert (struct2 != NULL); + + if (G_UNLIKELY (struct1->name != struct2->name)) + return NULL; + + /* copy fields from struct1 which we have not in struct2 to target + * intersect if we have the field in both */ + data.dest = gst_structure_new_id_empty (struct1->name); + data.intersect = struct2; + if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1, + gst_structure_intersect_field1, &data))) + goto error; + + /* copy fields from struct2 which we have not in struct1 to target */ + data.intersect = struct1; + if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2, + gst_structure_intersect_field2, &data))) + goto error; + + return data.dest; + +error: + gst_structure_free (data.dest); + return NULL; +} + +static gboolean +gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1, + gpointer data) +{ + GstStructure *other = (GstStructure *) data; + const GValue *val2 = gst_structure_id_get_value (other, id); + + if (G_LIKELY (val2)) { + if (!gst_value_can_intersect (val1, val2)) { + return FALSE; + } else { + gint eq = gst_value_compare (val1, val2); + + if (eq == GST_VALUE_UNORDERED) { + /* we need to try interseting */ + if (!gst_value_intersect (NULL, val1, val2)) { + return FALSE; + } + } else if (eq != GST_VALUE_EQUAL) { + return FALSE; + } + } + } + return TRUE; +} + +/** + * gst_structure_can_intersect: + * @struct1: a #GstStructure + * @struct2: a #GstStructure + * + * Tries intersecting @struct1 and @struct2 and reports whether the result + * would not be empty. + * + * Returns: %TRUE if intersection would not be empty + */ +gboolean +gst_structure_can_intersect (const GstStructure * struct1, + const GstStructure * struct2) +{ + g_return_val_if_fail (GST_IS_STRUCTURE (struct1), FALSE); + g_return_val_if_fail (GST_IS_STRUCTURE (struct2), FALSE); + + if (G_UNLIKELY (struct1->name != struct2->name)) + return FALSE; + + /* tries to intersect if we have the field in both */ + return gst_structure_foreach ((GstStructure *) struct1, + gst_caps_structure_can_intersect_field, (gpointer) struct2); +} + +static gboolean +gst_caps_structure_is_superset_field (GQuark field_id, const GValue * value, + gpointer user_data) +{ + GstStructure *subset = user_data; + const GValue *other; + int comparison; + + if (!(other = gst_structure_id_get_value (subset, field_id))) + /* field is missing in the subset => no subset */ + return FALSE; + + comparison = gst_value_compare (value, other); + + /* equal values are subset */ + if (comparison == GST_VALUE_EQUAL) + return TRUE; + + /* ordered, but unequal, values are not */ + if (comparison != GST_VALUE_UNORDERED) + return FALSE; + + return gst_value_is_subset (other, value); +} + +/** + * gst_structure_is_subset: + * @subset: a #GstStructure + * @superset: a potentially greater #GstStructure + * + * Checks if @subset is a subset of @superset, i.e. has the same + * structure name and for all fields that are existing in @superset, + * @subset has a value that is a subset of the value in @superset. + * + * Returns: %TRUE if @subset is a subset of @superset + */ +gboolean +gst_structure_is_subset (const GstStructure * subset, + const GstStructure * superset) +{ + if ((superset->name != subset->name) || + (gst_structure_n_fields (superset) > gst_structure_n_fields (subset))) + return FALSE; + + return gst_structure_foreach ((GstStructure *) superset, + gst_caps_structure_is_superset_field, (gpointer) subset); +} + + +/** + * gst_structure_fixate: + * @structure: a #GstStructure + * + * Fixate all values in @structure using gst_value_fixate(). + * @structure will be modified in-place and should be writable. + */ +void +gst_structure_fixate (GstStructure * structure) +{ + g_return_if_fail (GST_IS_STRUCTURE (structure)); + + gst_structure_foreach (structure, default_fixate, structure); +} + +static gboolean +_gst_structure_get_any_list (GstStructure * structure, GType type, + const gchar * fieldname, GValueArray ** array) +{ + GstStructureField *field; + GValue val = G_VALUE_INIT; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (array != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != type) + return FALSE; + + g_value_init (&val, G_TYPE_VALUE_ARRAY); + + if (g_value_transform (&field->value, &val)) { + *array = g_value_get_boxed (&val); + return TRUE; + } + + g_value_unset (&val); + return FALSE; +} + +/** + * gst_structure_get_array: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @array: (out): a pointer to a #GValueArray + * + * This is useful in language bindings where unknown #GValue types are not + * supported. This function will convert the %GST_TYPE_ARRAY and + * %GST_TYPE_LIST into a newly allocated #GValueArray and return it through + * @array. Be aware that this is slower then getting the #GValue directly. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain an int, this function + * returns %FALSE. + */ +gboolean +gst_structure_get_array (GstStructure * structure, const gchar * fieldname, + GValueArray ** array) +{ + return _gst_structure_get_any_list (structure, GST_TYPE_ARRAY, fieldname, + array); +} + +/** + * gst_structure_get_list: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @array: (out): a pointer to a #GValueArray + * + * This is useful in language bindings where unknown #GValue types are not + * supported. This function will convert the %GST_TYPE_ARRAY and + * %GST_TYPE_LIST into a newly allocated GValueArray and return it through + * @array. Be aware that this is slower then getting the #GValue directly. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain an int, this function + * returns %FALSE. + * + * Since 1.12 + */ +gboolean +gst_structure_get_list (GstStructure * structure, const gchar * fieldname, + GValueArray ** array) +{ + return _gst_structure_get_any_list (structure, GST_TYPE_LIST, fieldname, + array); +} + +static void +_gst_structure_set_any_list (GstStructure * structure, GType type, + const gchar * fieldname, const GValueArray * array) +{ + GValue arval = G_VALUE_INIT; + GValue value = G_VALUE_INIT; + + g_return_if_fail (structure != NULL); + g_return_if_fail (fieldname != NULL); + g_return_if_fail (array != NULL); + g_return_if_fail (IS_MUTABLE (structure)); + + g_value_init (&value, type); + g_value_init (&arval, G_TYPE_VALUE_ARRAY); + g_value_set_static_boxed (&arval, array); + + if (g_value_transform (&arval, &value)) { + gst_structure_id_set_value_internal (structure, + g_quark_from_string (fieldname), &value); + } else { + g_warning ("Failed to convert a GValueArray"); + } + + g_value_unset (&arval); + g_value_unset (&value); +} + +/** + * gst_structure_set_array: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @array: a pointer to a #GValueArray + * + * This is useful in language bindings where unknown GValue types are not + * supported. This function will convert a @array to %GST_TYPE_ARRAY and set + * the field specified by @fieldname. Be aware that this is slower then using + * %GST_TYPE_ARRAY in a #GValue directly. + * + * Since 1.12 + */ +void +gst_structure_set_array (GstStructure * structure, const gchar * fieldname, + const GValueArray * array) +{ + _gst_structure_set_any_list (structure, GST_TYPE_ARRAY, fieldname, array); +} + +/** + * gst_structure_set_list: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @array: a pointer to a #GValueArray + * + * This is useful in language bindings where unknown GValue types are not + * supported. This function will convert a @array to %GST_TYPE_ARRAY and set + * the field specified by @fieldname. Be aware that this is slower then using + * %GST_TYPE_ARRAY in a #GValue directly. + * + * Since 1.12 + */ +void +gst_structure_set_list (GstStructure * structure, const gchar * fieldname, + const GValueArray * array) +{ + _gst_structure_set_any_list (structure, GST_TYPE_LIST, fieldname, array); +} diff --git a/gst/gststructure.h b/gst/gststructure.h new file mode 100644 index 0000000..e366fea --- /dev/null +++ b/gst/gststructure.h @@ -0,0 +1,377 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_STRUCTURE_H__ +#define __GST_STRUCTURE_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_structure_type; + +typedef struct _GstStructure GstStructure; + +#define GST_TYPE_STRUCTURE (_gst_structure_type) +#define GST_IS_STRUCTURE(object) ((object) && (GST_STRUCTURE(object)->type == GST_TYPE_STRUCTURE)) +#define GST_STRUCTURE_CAST(object) ((GstStructure *)(object)) +#define GST_STRUCTURE(object) (GST_STRUCTURE_CAST(object)) + + +/** + * GstStructureForeachFunc: + * @field_id: the #GQuark of the field name + * @value: the #GValue of the field + * @user_data: user data + * + * A function that will be called in gst_structure_foreach(). The function may + * not modify @value. + * + * Returns: %TRUE if the foreach operation should continue, %FALSE if + * the foreach operation should stop with %FALSE. + */ +typedef gboolean (*GstStructureForeachFunc) (GQuark field_id, + const GValue * value, + gpointer user_data); + +/** + * GstStructureMapFunc: + * @field_id: the #GQuark of the field name + * @value: the #GValue of the field + * @user_data: user data + * + * A function that will be called in gst_structure_map_in_place(). The function + * may modify @value. + * + * Returns: %TRUE if the map operation should continue, %FALSE if + * the map operation should stop with %FALSE. + */ +typedef gboolean (*GstStructureMapFunc) (GQuark field_id, + GValue * value, + gpointer user_data); + +/** + * GstStructureFilterMapFunc: + * @field_id: the #GQuark of the field name + * @value: the #GValue of the field + * @user_data: user data + * + * A function that will be called in gst_structure_filter_and_map_in_place(). + * The function may modify @value, and the value will be removed from + * the structure if %FALSE is returned. + * + * Returns: %TRUE if the field should be preserved, %FALSE if it + * should be removed. + */ +typedef gboolean (*GstStructureFilterMapFunc) (GQuark field_id, + GValue * value, + gpointer user_data); + +/** + * GstStructure: + * @type: the GType of a structure + * + * The GstStructure object. Most fields are private. + */ +struct _GstStructure { + GType type; + + /*< private >*/ + GQuark name; +}; + +GST_API +GType gst_structure_get_type (void); + +GST_API +GstStructure * gst_structure_new_empty (const gchar * name) G_GNUC_MALLOC; + +GST_API +GstStructure * gst_structure_new_id_empty (GQuark quark) G_GNUC_MALLOC; + +GST_API +GstStructure * gst_structure_new (const gchar * name, + const gchar * firstfield, + ...) G_GNUC_NULL_TERMINATED G_GNUC_MALLOC; +GST_API +GstStructure * gst_structure_new_valist (const gchar * name, + const gchar * firstfield, + va_list varargs) G_GNUC_MALLOC; +GST_API +GstStructure * gst_structure_new_id (GQuark name_quark, + GQuark field_quark, + ...) G_GNUC_MALLOC; +GST_API +GstStructure * gst_structure_new_from_string (const gchar * string); + +GST_API +GstStructure * gst_structure_copy (const GstStructure * structure) G_GNUC_MALLOC; + +GST_API +gboolean gst_structure_set_parent_refcount (GstStructure * structure, + gint * refcount); +GST_API +void gst_structure_free (GstStructure * structure); + +GST_API +const gchar * gst_structure_get_name (const GstStructure * structure); + +GST_API +GQuark gst_structure_get_name_id (const GstStructure * structure); + +GST_API +gboolean gst_structure_has_name (const GstStructure * structure, + const gchar * name); +GST_API +void gst_structure_set_name (GstStructure * structure, + const gchar * name); +GST_API +void gst_structure_id_set_value (GstStructure * structure, + GQuark field, + const GValue * value); +GST_API +void gst_structure_set_value (GstStructure * structure, + const gchar * fieldname, + const GValue * value); +GST_API +void gst_structure_set_array (GstStructure * structure, + const gchar * fieldname, + const GValueArray * array); +GST_API +void gst_structure_set_list (GstStructure * structure, + const gchar * fieldname, + const GValueArray * array); +GST_API +void gst_structure_id_take_value (GstStructure * structure, + GQuark field, + GValue * value); +GST_API +void gst_structure_take_value (GstStructure * structure, + const gchar * fieldname, + GValue * value); +GST_API +void gst_structure_set (GstStructure * structure, + const gchar * fieldname, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_structure_set_valist (GstStructure * structure, + const gchar * fieldname, + va_list varargs); +GST_API +void gst_structure_id_set (GstStructure * structure, + GQuark fieldname, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_structure_id_set_valist (GstStructure * structure, + GQuark fieldname, + va_list varargs); +GST_API +gboolean gst_structure_get_valist (const GstStructure * structure, + const char * first_fieldname, + va_list args); +GST_API +gboolean gst_structure_get (const GstStructure * structure, + const char * first_fieldname, + ...) G_GNUC_NULL_TERMINATED; +GST_API +gboolean gst_structure_id_get_valist (const GstStructure * structure, + GQuark first_field_id, + va_list args); +GST_API +gboolean gst_structure_id_get (const GstStructure * structure, + GQuark first_field_id, + ...) G_GNUC_NULL_TERMINATED; +GST_API +const GValue * gst_structure_id_get_value (const GstStructure * structure, + GQuark field); +GST_API +const GValue * gst_structure_get_value (const GstStructure * structure, + const gchar * fieldname); +GST_API +void gst_structure_remove_field (GstStructure * structure, + const gchar * fieldname); +GST_API +void gst_structure_remove_fields (GstStructure * structure, + const gchar * fieldname, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_structure_remove_fields_valist (GstStructure * structure, + const gchar * fieldname, + va_list varargs); +GST_API +void gst_structure_remove_all_fields (GstStructure * structure); + +GST_API +GType gst_structure_get_field_type (const GstStructure * structure, + const gchar * fieldname); +GST_API +gboolean gst_structure_foreach (const GstStructure * structure, + GstStructureForeachFunc func, + gpointer user_data); +GST_API +gboolean gst_structure_map_in_place (GstStructure * structure, + GstStructureMapFunc func, + gpointer user_data); +GST_API +void gst_structure_filter_and_map_in_place (GstStructure * structure, + GstStructureFilterMapFunc func, + gpointer user_data); +GST_API +gint gst_structure_n_fields (const GstStructure * structure); + +GST_API +const gchar * gst_structure_nth_field_name (const GstStructure * structure, + guint index); +GST_API +gboolean gst_structure_id_has_field (const GstStructure * structure, + GQuark field); +GST_API +gboolean gst_structure_id_has_field_typed (const GstStructure * structure, + GQuark field, + GType type); +GST_API +gboolean gst_structure_has_field (const GstStructure * structure, + const gchar * fieldname); +GST_API +gboolean gst_structure_has_field_typed (const GstStructure * structure, + const gchar * fieldname, + GType type); + +/* utility functions */ + +GST_API +gboolean gst_structure_get_boolean (const GstStructure * structure, + const gchar * fieldname, + gboolean * value); +GST_API +gboolean gst_structure_get_int (const GstStructure * structure, + const gchar * fieldname, + gint * value); +GST_API +gboolean gst_structure_get_uint (const GstStructure * structure, + const gchar * fieldname, + guint * value); +GST_API +gboolean gst_structure_get_int64 (const GstStructure * structure, + const gchar * fieldname, + gint64 * value); +GST_API +gboolean gst_structure_get_uint64 (const GstStructure * structure, + const gchar * fieldname, + guint64 * value); +GST_API +gboolean gst_structure_get_double (const GstStructure * structure, + const gchar * fieldname, + gdouble * value); +GST_API +gboolean gst_structure_get_date (const GstStructure * structure, + const gchar * fieldname, + GDate ** value); +GST_API +gboolean gst_structure_get_date_time (const GstStructure * structure, + const gchar * fieldname, + GstDateTime ** value); +GST_API +gboolean gst_structure_get_clock_time (const GstStructure * structure, + const gchar * fieldname, + GstClockTime * value); +GST_API +const gchar * gst_structure_get_string (const GstStructure * structure, + const gchar * fieldname); +GST_API +gboolean gst_structure_get_enum (const GstStructure * structure, + const gchar * fieldname, + GType enumtype, + gint * value); +GST_API +gboolean gst_structure_get_fraction (const GstStructure * structure, + const gchar * fieldname, + gint * value_numerator, + gint * value_denominator); +GST_API +gboolean gst_structure_get_flagset (const GstStructure * structure, + const gchar * fieldname, + guint * value_flags, + guint * value_mask); +GST_API +gboolean gst_structure_get_array (GstStructure * structure, + const gchar * fieldname, + GValueArray ** array); +GST_API +gboolean gst_structure_get_list (GstStructure * structure, + const gchar * fieldname, + GValueArray ** array); +GST_API +gchar * gst_structure_to_string (const GstStructure * structure) G_GNUC_MALLOC; + +GST_API +GstStructure * gst_structure_from_string (const gchar * string, + gchar ** end) G_GNUC_MALLOC; +GST_API +gboolean gst_structure_fixate_field_nearest_int (GstStructure * structure, + const char * field_name, + int target); +GST_API +gboolean gst_structure_fixate_field_nearest_double (GstStructure * structure, + const char * field_name, + double target); +GST_API +gboolean gst_structure_fixate_field_boolean (GstStructure * structure, + const char * field_name, + gboolean target); +GST_API +gboolean gst_structure_fixate_field_string (GstStructure * structure, + const char * field_name, + const gchar * target); +GST_API +gboolean gst_structure_fixate_field_nearest_fraction (GstStructure * structure, + const char * field_name, + const gint target_numerator, + const gint target_denominator); +GST_API +gboolean gst_structure_fixate_field (GstStructure * structure, + const char * field_name); +GST_API +void gst_structure_fixate (GstStructure * structure); + +GST_API +gboolean gst_structure_is_equal (const GstStructure * structure1, + const GstStructure * structure2); +GST_API +gboolean gst_structure_is_subset (const GstStructure * subset, + const GstStructure * superset); +GST_API +gboolean gst_structure_can_intersect (const GstStructure * struct1, + const GstStructure * struct2); +GST_API +GstStructure * gst_structure_intersect (const GstStructure * struct1, + const GstStructure * struct2) G_GNUC_MALLOC; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstStructure, gst_structure_free) +#endif + +G_END_DECLS + +#endif + diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c new file mode 100644 index 0000000..02f56b1 --- /dev/null +++ b/gst/gstsystemclock.c @@ -0,0 +1,1026 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2004 Wim Taymans + * + * gstsystemclock.c: Default clock, uses the system clock + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstsystemclock + * @title: GstSystemClock + * @short_description: Default clock that uses the current system time + * @see_also: #GstClock + * + * The GStreamer core provides a GstSystemClock based on the system time. + * Asynchronous callbacks are scheduled from an internal thread. + * + * Clock implementors are encouraged to subclass this systemclock as it + * implements the async notification. + * + * Subclasses can however override all of the important methods for sync and + * async notifications to implement their own callback methods or blocking + * wait operations. + */ + +#include "gst_private.h" +#include "gstinfo.h" +#include "gstsystemclock.h" +#include "gstenumtypes.h" +#include "gstpoll.h" +#include "gstutils.h" +#include "glib-compat-private.h" + +#include + +#ifdef G_OS_WIN32 +# define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ +# include /* QueryPerformance* stuff */ +# undef WIN32_LEAN_AND_MEAN +# ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN /* This is just to placate gcc */ +# endif +#endif /* G_OS_WIN32 */ + +#ifdef __APPLE__ +#include +#endif + +#define GET_ENTRY_STATUS(e) ((GstClockReturn) g_atomic_int_get(&GST_CLOCK_ENTRY_STATUS(e))) +#define SET_ENTRY_STATUS(e,val) (g_atomic_int_set(&GST_CLOCK_ENTRY_STATUS(e),(val))) +#define CAS_ENTRY_STATUS(e,old,val) (g_atomic_int_compare_and_exchange(\ + (&GST_CLOCK_ENTRY_STATUS(e)), (old), (val))) + +/* Define this to get some extra debug about jitter from each clock_wait */ +#undef WAIT_DEBUGGING + +#define GST_SYSTEM_CLOCK_GET_COND(clock) (&GST_SYSTEM_CLOCK_CAST(clock)->priv->entries_changed) +#define GST_SYSTEM_CLOCK_WAIT(clock) g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock)) +#define GST_SYSTEM_CLOCK_TIMED_WAIT(clock,tv) g_cond_timed_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv) +#define GST_SYSTEM_CLOCK_BROADCAST(clock) g_cond_broadcast(GST_SYSTEM_CLOCK_GET_COND(clock)) + +struct _GstSystemClockPrivate +{ + GThread *thread; /* thread for async notify */ + gboolean stopping; + + GList *entries; + GCond entries_changed; + + GstClockType clock_type; + GstPoll *timer; + gint wakeup_count; /* the number of entries with a pending wakeup */ + gboolean async_wakeup; /* if the wakeup was because of a async list change */ + +#ifdef G_OS_WIN32 + LARGE_INTEGER start; + LARGE_INTEGER frequency; +#endif /* G_OS_WIN32 */ +#ifdef __APPLE__ + struct mach_timebase_info mach_timebase; +#endif +}; + +#define GST_SYSTEM_CLOCK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_SYSTEM_CLOCK, \ + GstSystemClockPrivate)) + +#ifdef HAVE_POSIX_TIMERS +# ifdef HAVE_MONOTONIC_CLOCK +# define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC +# else +# define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME +# endif +#else +#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_REALTIME +#endif + +enum +{ + PROP_0, + PROP_CLOCK_TYPE, + /* FILL ME */ +}; + +/* the one instance of the systemclock */ +static GstClock *_the_system_clock = NULL; +static gboolean _external_default_clock = FALSE; + +static void gst_system_clock_dispose (GObject * object); +static void gst_system_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_system_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstClockTime gst_system_clock_get_internal_time (GstClock * clock); +static guint64 gst_system_clock_get_resolution (GstClock * clock); +static GstClockReturn gst_system_clock_id_wait_jitter (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter); +static GstClockReturn gst_system_clock_id_wait_jitter_unlocked + (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter, + gboolean restart); +static GstClockReturn gst_system_clock_id_wait_async (GstClock * clock, + GstClockEntry * entry); +static void gst_system_clock_id_unschedule (GstClock * clock, + GstClockEntry * entry); +static void gst_system_clock_async_thread (GstClock * clock); +static gboolean gst_system_clock_start_async (GstSystemClock * clock); +static void gst_system_clock_add_wakeup (GstSystemClock * sysclock); + +static GMutex _gst_sysclock_mutex; + +/* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */ + +#define gst_system_clock_parent_class parent_class +G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK); + +static void +gst_system_clock_class_init (GstSystemClockClass * klass) +{ + GObjectClass *gobject_class; + GstClockClass *gstclock_class; + + gobject_class = (GObjectClass *) klass; + gstclock_class = (GstClockClass *) klass; + + g_type_class_add_private (klass, sizeof (GstSystemClockPrivate)); + + gobject_class->dispose = gst_system_clock_dispose; + gobject_class->set_property = gst_system_clock_set_property; + gobject_class->get_property = gst_system_clock_get_property; + + g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE, + g_param_spec_enum ("clock-type", "Clock type", + "The type of underlying clock implementation used", + GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstclock_class->get_internal_time = gst_system_clock_get_internal_time; + gstclock_class->get_resolution = gst_system_clock_get_resolution; + gstclock_class->wait = gst_system_clock_id_wait_jitter; + gstclock_class->wait_async = gst_system_clock_id_wait_async; + gstclock_class->unschedule = gst_system_clock_id_unschedule; +} + +static void +gst_system_clock_init (GstSystemClock * clock) +{ + GstSystemClockPrivate *priv; + + GST_OBJECT_FLAG_SET (clock, + GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC | + GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC | + GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC | + GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC); + + clock->priv = priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock); + + priv->clock_type = DEFAULT_CLOCK_TYPE; + priv->timer = gst_poll_new_timer (); + + priv->entries = NULL; + g_cond_init (&priv->entries_changed); + +#ifdef G_OS_WIN32 + QueryPerformanceFrequency (&priv->frequency); + /* can be 0 if the hardware does not have hardware support */ + if (priv->frequency.QuadPart != 0) + /* we take a base time so that time starts from 0 to ease debugging */ + QueryPerformanceCounter (&priv->start); +#endif /* G_OS_WIN32 */ + +#ifdef __APPLE__ + mach_timebase_info (&priv->mach_timebase); +#endif + +#if 0 + /* Uncomment this to start the async clock thread straight away */ + GST_OBJECT_LOCK (clock); + gst_system_clock_start_async (clock); + GST_OBJECT_UNLOCK (clock); +#endif +} + +static void +gst_system_clock_dispose (GObject * object) +{ + GstClock *clock = (GstClock *) object; + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + GstSystemClockPrivate *priv = sysclock->priv; + GList *entries; + + /* else we have to stop the thread */ + GST_OBJECT_LOCK (clock); + priv->stopping = TRUE; + /* unschedule all entries */ + for (entries = priv->entries; entries; entries = g_list_next (entries)) { + GstClockEntry *entry = (GstClockEntry *) entries->data; + + GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry); + SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED); + } + GST_SYSTEM_CLOCK_BROADCAST (clock); + gst_system_clock_add_wakeup (sysclock); + GST_OBJECT_UNLOCK (clock); + + if (priv->thread) + g_thread_join (priv->thread); + priv->thread = NULL; + GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread"); + + g_list_foreach (priv->entries, (GFunc) gst_clock_id_unref, NULL); + g_list_free (priv->entries); + priv->entries = NULL; + + gst_poll_free (priv->timer); + g_cond_clear (&priv->entries_changed); + + G_OBJECT_CLASS (parent_class)->dispose (object); + + if (_the_system_clock == clock) { + _the_system_clock = NULL; + GST_CAT_DEBUG (GST_CAT_CLOCK, "disposed system clock"); + } +} + +static void +gst_system_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object); + + switch (prop_id) { + case PROP_CLOCK_TYPE: + sysclock->priv->clock_type = (GstClockType) g_value_get_enum (value); + GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d", + sysclock->priv->clock_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK (object); + + switch (prop_id) { + case PROP_CLOCK_TYPE: + g_value_set_enum (value, sysclock->priv->clock_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_system_clock_set_default: + * @new_clock: (allow-none): a #GstClock + * + * Sets the default system clock that can be obtained with + * gst_system_clock_obtain(). + * + * This is mostly used for testing and debugging purposes when you + * want to have control over the time reported by the default system + * clock. + * + * MT safe. + * + * Since: 1.4 + */ +void +gst_system_clock_set_default (GstClock * new_clock) +{ + GstClock *clock; + + g_mutex_lock (&_gst_sysclock_mutex); + clock = _the_system_clock; + + if (clock != NULL) + g_object_unref (clock); + + if (new_clock == NULL) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "resetting default system clock"); + _external_default_clock = FALSE; + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, "setting new default system clock to %p", + new_clock); + _external_default_clock = TRUE; + g_object_ref (new_clock); + } + _the_system_clock = new_clock; + g_mutex_unlock (&_gst_sysclock_mutex); +} + +/** + * gst_system_clock_obtain: + * + * Get a handle to the default system clock. The refcount of the + * clock will be increased so you need to unref the clock after + * usage. + * + * Returns: (transfer full): the default clock. + * + * MT safe. + */ +GstClock * +gst_system_clock_obtain (void) +{ + GstClock *clock; + + g_mutex_lock (&_gst_sysclock_mutex); + clock = _the_system_clock; + + if (clock == NULL) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "creating new static system clock"); + g_assert (!_external_default_clock); + clock = g_object_new (GST_TYPE_SYSTEM_CLOCK, + "name", "GstSystemClock", NULL); + + /* Clear floating flag */ + gst_object_ref_sink (clock); + _the_system_clock = clock; + g_mutex_unlock (&_gst_sysclock_mutex); + } else { + g_mutex_unlock (&_gst_sysclock_mutex); + GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock"); + } + + /* we ref it since we are a clock factory. */ + gst_object_ref (clock); + return clock; +} + +static void +gst_system_clock_remove_wakeup (GstSystemClock * sysclock) +{ + g_return_if_fail (sysclock->priv->wakeup_count > 0); + + sysclock->priv->wakeup_count--; + GST_CAT_DEBUG (GST_CAT_CLOCK, "reading control"); + while (!gst_poll_read_control (sysclock->priv->timer)) { + if (errno == EWOULDBLOCK) { + /* Try again and give other threads the chance to do something */ + g_thread_yield (); + continue; + } else { + /* Critical error, GstPoll will have printed a critical warning already */ + break; + } + } + GST_SYSTEM_CLOCK_BROADCAST (sysclock); + GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d", + sysclock->priv->wakeup_count); +} + +static void +gst_system_clock_add_wakeup (GstSystemClock * sysclock) +{ + GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control"); + gst_poll_write_control (sysclock->priv->timer); + sysclock->priv->wakeup_count++; + GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d", + sysclock->priv->wakeup_count); +} + +static void +gst_system_clock_wait_wakeup (GstSystemClock * sysclock) +{ + while (sysclock->priv->wakeup_count > 0) { + GST_SYSTEM_CLOCK_WAIT (sysclock); + } +} + +/* this thread reads the sorted clock entries from the queue. + * + * It waits on each of them and fires the callback when the timeout occurs. + * + * When an entry in the queue was canceled before we wait for it, it is + * simply skipped. + * + * When waiting for an entry, it can become canceled, in that case we don't + * call the callback but move to the next item in the queue. + * + * MT safe. + */ +static void +gst_system_clock_async_thread (GstClock * clock) +{ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + GstSystemClockPrivate *priv = sysclock->priv; + GstClockReturn status; + + GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread"); + GST_OBJECT_LOCK (clock); + /* signal spinup */ + GST_SYSTEM_CLOCK_BROADCAST (clock); + /* now enter our (almost) infinite loop */ + while (!priv->stopping) { + GstClockEntry *entry; + GstClockTime requested; + GstClockReturn res; + + /* check if something to be done */ + while (priv->entries == NULL) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting.."); + /* wait for work to do */ + GST_SYSTEM_CLOCK_WAIT (clock); + GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal"); + /* clock was stopping, exit */ + if (priv->stopping) + goto exit; + } + + /* see if we have a pending wakeup because the order of the list + * changed. */ + if (priv->async_wakeup) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup"); + gst_system_clock_remove_wakeup (sysclock); + priv->async_wakeup = FALSE; + } + + /* pick the next entry */ + entry = priv->entries->data; + + /* set entry status to busy before we release the clock lock */ + do { + status = GET_ENTRY_STATUS (entry); + + /* check for unscheduled */ + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) { + /* entry was unscheduled, move to the next one */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry); + goto next_entry; + } + + /* for periodic timers, status can be EARLY from a previous run */ + if (G_UNLIKELY (status != GST_CLOCK_OK && status != GST_CLOCK_EARLY)) + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + + /* mark the entry as busy but watch out for intermediate unscheduled + * statuses */ + } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_BUSY))); + + GST_OBJECT_UNLOCK (clock); + + requested = entry->time; + + /* now wait for the entry */ + res = + gst_system_clock_id_wait_jitter_unlocked (clock, (GstClockID) entry, + NULL, FALSE); + + GST_OBJECT_LOCK (clock); + + switch (res) { + case GST_CLOCK_UNSCHEDULED: + /* entry was unscheduled, move to the next */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p unscheduled", entry); + goto next_entry; + case GST_CLOCK_OK: + case GST_CLOCK_EARLY: + { + /* entry timed out normally, fire the callback and move to the next + * entry */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p timed out", entry); + if (entry->func) { + /* unlock before firing the callback */ + GST_OBJECT_UNLOCK (clock); + entry->func (clock, entry->time, (GstClockID) entry, + entry->user_data); + GST_OBJECT_LOCK (clock); + } + if (entry->type == GST_CLOCK_ENTRY_PERIODIC) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "updating periodic entry %p", entry); + /* adjust time now */ + entry->time = requested + entry->interval; + /* and resort the list now */ + priv->entries = + g_list_sort (priv->entries, gst_clock_id_compare_func); + /* and restart */ + continue; + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, "moving to next entry"); + goto next_entry; + } + } + case GST_CLOCK_BUSY: + /* somebody unlocked the entry but is was not canceled, This means that + * either a new entry was added in front of the queue or some other entry + * was canceled. Whatever it is, pick the head entry of the list and + * continue waiting. */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry %p needs restart", entry); + + /* we set the entry back to the OK state. This is needed so that the + * _unschedule() code can see if an entry is currently being waited + * on (when its state is BUSY). */ + SET_ENTRY_STATUS (entry, GST_CLOCK_OK); + continue; + default: + GST_CAT_DEBUG (GST_CAT_CLOCK, + "strange result %d waiting for %p, skipping", res, entry); + g_warning ("%s: strange result %d waiting for %p, skipping", + GST_OBJECT_NAME (clock), res, entry); + goto next_entry; + } + next_entry: + /* we remove the current entry and unref it */ + priv->entries = g_list_remove (priv->entries, entry); + gst_clock_id_unref ((GstClockID) entry); + } +exit: + /* signal exit */ + GST_SYSTEM_CLOCK_BROADCAST (clock); + GST_OBJECT_UNLOCK (clock); + GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread"); +} + +#ifdef HAVE_POSIX_TIMERS +static inline clockid_t +clock_type_to_posix_id (GstClockType clock_type) +{ +#ifdef HAVE_MONOTONIC_CLOCK + if (clock_type == GST_CLOCK_TYPE_MONOTONIC) + return CLOCK_MONOTONIC; + else +#endif + return CLOCK_REALTIME; +} +#endif + +/* MT safe */ +static GstClockTime +gst_system_clock_get_internal_time (GstClock * clock) +{ +#if defined __APPLE__ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + uint64_t mach_t = mach_absolute_time (); + return gst_util_uint64_scale (mach_t, sysclock->priv->mach_timebase.numer, + sysclock->priv->mach_timebase.denom); +#else +#ifdef G_OS_WIN32 + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + + if (sysclock->priv->frequency.QuadPart != 0) { + LARGE_INTEGER now; + + /* we prefer the highly accurate performance counters on windows */ + QueryPerformanceCounter (&now); + + return gst_util_uint64_scale (now.QuadPart - sysclock->priv->start.QuadPart, + GST_SECOND, sysclock->priv->frequency.QuadPart); + } else +#endif /* G_OS_WIN32 */ +#if !defined HAVE_POSIX_TIMERS || !defined HAVE_CLOCK_GETTIME + { + GTimeVal timeval; + + g_get_current_time (&timeval); + + return GST_TIMEVAL_TO_TIME (timeval); + } +#else + { + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + clockid_t ptype; + struct timespec ts; + + ptype = clock_type_to_posix_id (sysclock->priv->clock_type); + + if (G_UNLIKELY (clock_gettime (ptype, &ts))) + return GST_CLOCK_TIME_NONE; + + return GST_TIMESPEC_TO_TIME (ts); + } +#endif +#endif /* __APPLE__ */ +} + +static guint64 +gst_system_clock_get_resolution (GstClock * clock) +{ +#if defined __APPLE__ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + return gst_util_uint64_scale (GST_NSECOND, + sysclock->priv->mach_timebase.numer, sysclock->priv->mach_timebase.denom); +#else +#ifdef G_OS_WIN32 + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + + if (sysclock->priv->frequency.QuadPart != 0) { + return GST_SECOND / sysclock->priv->frequency.QuadPart; + } else +#endif /* G_OS_WIN32 */ +#if defined(HAVE_POSIX_TIMERS) && defined(HAVE_CLOCK_GETTIME) + { + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + clockid_t ptype; + struct timespec ts; + + ptype = clock_type_to_posix_id (sysclock->priv->clock_type); + + if (G_UNLIKELY (clock_getres (ptype, &ts))) + return GST_CLOCK_TIME_NONE; + + return GST_TIMESPEC_TO_TIME (ts); + } +#else + { + return 1 * GST_USECOND; + } +#endif +#endif /* __APPLE__ */ +} + +static inline void +gst_system_clock_cleanup_unscheduled (GstSystemClock * sysclock, + GstClockEntry * entry) +{ + /* try to clean up. + * The unschedule function managed to set the status to + * unscheduled. We now take the lock and mark the entry as unscheduled. + * This makes sure that the unschedule function doesn't perform a + * wakeup anymore. If the unschedule function has a change to perform + * the wakeup before us, we clean up here */ + GST_OBJECT_LOCK (sysclock); + entry->unscheduled = TRUE; + if (entry->woken_up) { + gst_system_clock_remove_wakeup (sysclock); + } + GST_OBJECT_UNLOCK (sysclock); +} + +/* synchronously wait on the given GstClockEntry. + * + * We do this by blocking on the global GstPoll timer with + * the requested timeout. This allows us to unblock the + * entry by writing on the control fd. + * + * Note that writing the global GstPoll unlocks all waiting entries. So + * we need to check if an unlocked entry has changed when it unlocks. + * + * Entries that arrive too late are simply not waited on and a + * GST_CLOCK_EARLY result is returned. + * + * MT safe. + */ +static GstClockReturn +gst_system_clock_id_wait_jitter_unlocked (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter, gboolean restart) +{ + GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock); + GstClockTime entryt, now; + GstClockTimeDiff diff; + GstClockReturn status; + + status = GET_ENTRY_STATUS (entry); + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) { + gst_system_clock_cleanup_unscheduled (sysclock, entry); + return GST_CLOCK_UNSCHEDULED; + } + + /* need to call the overridden method because we want to sync against the time + * of the clock, whatever the subclass uses as a clock. */ + now = gst_clock_get_time (clock); + + /* get the time of the entry */ + entryt = GST_CLOCK_ENTRY_TIME (entry); + + /* the diff of the entry with the clock is the amount of time we have to + * wait */ + diff = GST_CLOCK_DIFF (now, entryt); + if (G_LIKELY (jitter)) + *jitter = -diff; + + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p" + " time %" GST_TIME_FORMAT + " now %" GST_TIME_FORMAT + " diff (time-now) %" G_GINT64_FORMAT, + entry, GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), diff); + + if (G_LIKELY (diff > 0)) { +#ifdef WAIT_DEBUGGING + GstClockTime final; +#endif + + while (TRUE) { + gint pollret; + + /* now wait on the entry, it either times out or the fd is written. The + * status of the entry is BUSY only around the poll. */ + pollret = gst_poll_wait (sysclock->priv->timer, diff); + + /* get the new status, mark as DONE. We do this so that the unschedule + * function knows when we left the poll and doesn't need to wakeup the + * poll anymore. */ + do { + status = GET_ENTRY_STATUS (entry); + /* we were unscheduled, exit immediately */ + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) + break; + if (G_UNLIKELY (status != GST_CLOCK_BUSY)) + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_DONE))); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked, status %d, ret %d", + entry, status, pollret); + + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) { + gst_system_clock_cleanup_unscheduled (sysclock, entry); + goto done; + } else { + if (G_UNLIKELY (pollret != 0)) { + /* some other id got unlocked */ + if (!restart) { + /* this can happen if the entry got unlocked because of an async + * entry was added to the head of the async queue. */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup waiting for entry %p", entry); + goto done; + } + + /* wait till all the entries got woken up */ + GST_OBJECT_LOCK (sysclock); + gst_system_clock_wait_wakeup (sysclock); + GST_OBJECT_UNLOCK (sysclock); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p needs to be restarted", + entry); + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout", + entry); + } + + /* reschedule if gst_poll_wait returned early or we have to reschedule after + * an unlock*/ + now = gst_clock_get_time (clock); + diff = GST_CLOCK_DIFF (now, entryt); + + if (diff <= 0) { + /* timeout, this is fine, we can report success now */ + if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, GST_CLOCK_DONE, + GST_CLOCK_OK))) { + status = GET_ENTRY_STATUS (entry); + if (status != GST_CLOCK_UNSCHEDULED) + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + goto done; + } else { + status = GST_CLOCK_OK; + } + + GST_CAT_DEBUG (GST_CAT_CLOCK, + "entry %p finished, diff %" G_GINT64_FORMAT, entry, diff); + +#ifdef WAIT_DEBUGGING + final = gst_system_clock_get_internal_time (clock); + GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT + " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT + " %g target-offset %" G_GINT64_FORMAT " %g", entryt, now, + now - entryt, + (double) (GstClockTimeDiff) (now - entryt) / GST_SECOND, + (final - target), + ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND); +#endif + goto done; + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, + "entry %p restart, diff %" G_GINT64_FORMAT, entry, diff); + /* we are going to poll again, set status back to busy */ + do { + status = GET_ENTRY_STATUS (entry); + /* we were unscheduled, exit immediately */ + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) + goto done; + if (G_UNLIKELY (status != GST_CLOCK_DONE)) + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, + GST_CLOCK_BUSY))); + } + } + } + } else { + /* we are right on time or too late */ + if (G_UNLIKELY (diff == 0)) { + if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_OK))) { + status = GET_ENTRY_STATUS (entry); + if (G_LIKELY (status == GST_CLOCK_UNSCHEDULED)) + gst_system_clock_cleanup_unscheduled (sysclock, entry); + else + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + } else { + status = GST_CLOCK_OK; + } + } else { + if (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_EARLY))) { + status = GET_ENTRY_STATUS (entry); + if (G_LIKELY (status == GST_CLOCK_UNSCHEDULED)) + gst_system_clock_cleanup_unscheduled (sysclock, entry); + else + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + } else { + status = GST_CLOCK_EARLY; + } + } + } +done: + return status; +} + +static GstClockReturn +gst_system_clock_id_wait_jitter (GstClock * clock, GstClockEntry * entry, + GstClockTimeDiff * jitter) +{ + GstClockReturn status; + do { + status = GET_ENTRY_STATUS (entry); + + /* stop when we are unscheduled */ + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) + return status; + + if (G_UNLIKELY (status != GST_CLOCK_OK)) + GST_CAT_ERROR (GST_CAT_CLOCK, "unexpected status %d for entry %p", + status, entry); + + /* mark the entry as busy but watch out for intermediate unscheduled + * statuses */ + } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, GST_CLOCK_BUSY))); + + return gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter, TRUE); +} + +/* Start the async clock thread. Must be called with the object lock + * held */ +static gboolean +gst_system_clock_start_async (GstSystemClock * clock) +{ + GError *error = NULL; + GstSystemClockPrivate *priv = clock->priv; + + if (G_LIKELY (priv->thread != NULL)) + return TRUE; /* Thread already running. Nothing to do */ + + priv->thread = g_thread_try_new ("GstSystemClock", + (GThreadFunc) gst_system_clock_async_thread, clock, &error); + + if (G_UNLIKELY (error)) + goto no_thread; + + /* wait for it to spin up */ + GST_SYSTEM_CLOCK_WAIT (clock); + + return TRUE; + + /* ERRORS */ +no_thread: + { + g_warning ("could not create async clock thread: %s", error->message); + g_error_free (error); + } + return FALSE; +} + +/* Add an entry to the list of pending async waits. The entry is inserted + * in sorted order. If we inserted the entry at the head of the list, we + * need to signal the thread as it might either be waiting on it or waiting + * for a new entry. + * + * MT safe. + */ +static GstClockReturn +gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry) +{ + GstSystemClock *sysclock; + GstSystemClockPrivate *priv; + GstClockEntry *head; + + sysclock = GST_SYSTEM_CLOCK_CAST (clock); + priv = sysclock->priv; + + GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry); + + GST_OBJECT_LOCK (clock); + /* Start the clock async thread if needed */ + if (G_UNLIKELY (!gst_system_clock_start_async (sysclock))) + goto thread_error; + + if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)) + goto was_unscheduled; + + if (priv->entries) + head = priv->entries->data; + else + head = NULL; + + /* need to take a ref */ + gst_clock_id_ref ((GstClockID) entry); + /* insert the entry in sorted order */ + priv->entries = g_list_insert_sorted (priv->entries, entry, + gst_clock_id_compare_func); + + /* only need to send the signal if the entry was added to the + * front, else the thread is just waiting for another entry and + * will get to this entry automatically. */ + if (priv->entries->data == entry) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head); + if (head == NULL) { + /* the list was empty before, signal the cond so that the async thread can + * start taking a look at the queue */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal"); + GST_SYSTEM_CLOCK_BROADCAST (clock); + } else { + GstClockReturn status; + + status = GET_ENTRY_STATUS (head); + GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry %p status %d", head, status); + + if (status == GST_CLOCK_BUSY) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy"); + /* the async thread was waiting for an entry, unlock the wait so that it + * looks at the new head entry instead, we only need to do this once */ + if (!priv->async_wakeup) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread"); + priv->async_wakeup = TRUE; + gst_system_clock_add_wakeup (sysclock); + } + } + } + } + GST_OBJECT_UNLOCK (clock); + + return GST_CLOCK_OK; + + /* ERRORS */ +thread_error: + { + /* Could not start the async clock thread */ + GST_OBJECT_UNLOCK (clock); + return GST_CLOCK_ERROR; + } +was_unscheduled: + { + GST_OBJECT_UNLOCK (clock); + return GST_CLOCK_UNSCHEDULED; + } +} + +/* unschedule an entry. This will set the state of the entry to GST_CLOCK_UNSCHEDULED + * and will signal any thread waiting for entries to recheck their entry. + * We cannot really decide if the signal is needed or not because the entry + * could be waited on in async or sync mode. + * + * MT safe. + */ +static void +gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry) +{ + GstSystemClock *sysclock; + GstClockReturn status; + + sysclock = GST_SYSTEM_CLOCK_CAST (clock); + + GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry); + + GST_OBJECT_LOCK (clock); + /* change the entry status to unscheduled */ + do { + status = GET_ENTRY_STATUS (entry); + } while (G_UNLIKELY (!CAS_ENTRY_STATUS (entry, status, + GST_CLOCK_UNSCHEDULED))); + + if (G_LIKELY (status == GST_CLOCK_BUSY)) { + /* the entry was being busy, wake up all entries so that they recheck their + * status. We cannot wake up just one entry because allocating such a + * datastructure for each entry would be too heavy and unlocking an entry + * is usually done when shutting down or some other exceptional case. */ + GST_CAT_DEBUG (GST_CAT_CLOCK, "entry was BUSY, doing wakeup"); + if (!entry->unscheduled && !entry->woken_up) { + gst_system_clock_add_wakeup (sysclock); + entry->woken_up = TRUE; + } + } + GST_OBJECT_UNLOCK (clock); +} diff --git a/gst/gstsystemclock.h b/gst/gstsystemclock.h new file mode 100644 index 0000000..0cee1c9 --- /dev/null +++ b/gst/gstsystemclock.h @@ -0,0 +1,96 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstsystemclock.h: A clock implementation based on system time + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_SYSTEM_CLOCK_H__ +#define __GST_SYSTEM_CLOCK_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_SYSTEM_CLOCK (gst_system_clock_get_type ()) +#define GST_SYSTEM_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SYSTEM_CLOCK, GstSystemClock)) +#define GST_SYSTEM_CLOCK_CAST(obj) ((GstSystemClock *)(obj)) +#define GST_IS_SYSTEM_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SYSTEM_CLOCK)) +#define GST_SYSTEM_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SYSTEM_CLOCK, GstSystemClockClass)) +#define GST_IS_SYSTEM_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SYSTEM_CLOCK)) +#define GST_SYSTEM_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_SYSTEM_CLOCK, GstSystemClockClass)) + + +typedef struct _GstSystemClock GstSystemClock; +typedef struct _GstSystemClockClass GstSystemClockClass; +typedef struct _GstSystemClockPrivate GstSystemClockPrivate; + +/** + * GstClockType: + * @GST_CLOCK_TYPE_REALTIME: time since Epoch + * @GST_CLOCK_TYPE_MONOTONIC: monotonic time since some unspecified starting + * point + * @GST_CLOCK_TYPE_OTHER: some other time source is used (Since 1.0.5) + * + * The different kind of clocks. + */ +typedef enum { + GST_CLOCK_TYPE_REALTIME = 0, + GST_CLOCK_TYPE_MONOTONIC = 1, + GST_CLOCK_TYPE_OTHER = 2 +} GstClockType; + +/** + * GstSystemClock: + * + * The default implementation of a #GstClock that uses the system time. + */ +struct _GstSystemClock { + GstClock clock; + + /*< private >*/ + GstSystemClockPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstSystemClockClass { + GstClockClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_system_clock_get_type (void); + +GST_API +GstClock* gst_system_clock_obtain (void); + +GST_API +void gst_system_clock_set_default (GstClock *new_clock); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstSystemClock, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_SYSTEM_CLOCK_H__ */ diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c new file mode 100644 index 0000000..bdeab58 --- /dev/null +++ b/gst/gsttaglist.c @@ -0,0 +1,2064 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttaglist.c: tag support (aka metadata) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttaglist + * @title: GstTagList + * @short_description: List of tags and values used to describe media metadata + * + * List of tags and values used to describe media metadata. + * + * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are + * not allowed. Strings must not be empty or %NULL. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" +#include "math-compat.h" +#include "gst-i18n-lib.h" +#include "gsttaglist.h" +#include "gstinfo.h" +#include "gstvalue.h" +#include "gstbuffer.h" +#include "gstquark.h" +#include "gststructure.h" + +#include +#include + +/* FIXME: add category for tags */ +#define GST_CAT_TAGS GST_CAT_DEFAULT + +#define GST_TAG_IS_VALID(tag) (gst_tag_get_info (tag) != NULL) + +typedef struct _GstTagListImpl +{ + GstTagList taglist; + + GstStructure *structure; + GstTagScope scope; +} GstTagListImpl; + +#define GST_TAG_LIST_STRUCTURE(taglist) ((GstTagListImpl*)(taglist))->structure +#define GST_TAG_LIST_SCOPE(taglist) ((GstTagListImpl*)(taglist))->scope + +typedef struct +{ + GType type; /* type the data is in */ + + const gchar *nick; /* translated short description */ + const gchar *blurb; /* translated long description */ + + GstTagMergeFunc merge_func; /* functions to merge the values */ + GstTagFlag flag; /* type of tag */ + GQuark name_quark; /* quark for the name */ +} +GstTagInfo; + +#define g_value_get_char g_value_get_schar + +static GMutex __tag_mutex; +#define TAG_LOCK g_mutex_lock (&__tag_mutex) +#define TAG_UNLOCK g_mutex_unlock (&__tag_mutex) + +/* tags hash table: maps tag name string => GstTagInfo */ +static GHashTable *__tags; + +GType _gst_tag_list_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstTagList, gst_tag_list); + +static void __gst_tag_list_free (GstTagList * list); +static GstTagList *__gst_tag_list_copy (const GstTagList * list); + +/* FIXME: had code: + * g_value_register_transform_func (_gst_tag_list_type, G_TYPE_STRING, + * _gst_structure_transform_to_string); + */ +void +_priv_gst_tag_initialize (void) +{ + g_mutex_init (&__tag_mutex); + + _gst_tag_list_type = gst_tag_list_get_type (); + + __tags = g_hash_table_new (g_str_hash, g_str_equal); + gst_tag_register_static (GST_TAG_TITLE, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("title"), _("commonly used title"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_TITLE_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("title sortname"), _("commonly used title for sorting purposes"), NULL); + gst_tag_register_static (GST_TAG_ARTIST, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("artist"), + _("person(s) responsible for the recording"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_ARTIST_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("artist sortname"), + _("person(s) responsible for the recording for sorting purposes"), NULL); + gst_tag_register_static (GST_TAG_ALBUM, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("album"), + _("album containing this data"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_ALBUM_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("album sortname"), + _("album containing this data for sorting purposes"), NULL); + gst_tag_register_static (GST_TAG_ALBUM_ARTIST, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("album artist"), + _("The artist of the entire album, as it should be displayed"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_ALBUM_ARTIST_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("album artist sortname"), + _("The artist of the entire album, as it should be sorted"), NULL); + gst_tag_register_static (GST_TAG_DATE, GST_TAG_FLAG_META, G_TYPE_DATE, + _("date"), _("date the data was created (as a GDate structure)"), NULL); + gst_tag_register_static (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, + GST_TYPE_DATE_TIME, _("datetime"), + _("date and time the data was created (as a GstDateTime structure)"), + NULL); + gst_tag_register_static (GST_TAG_GENRE, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("genre"), + _("genre this data belongs to"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_COMMENT, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("comment"), + _("free text commenting the data"), gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_EXTENDED_COMMENT, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("extended comment"), + _("free text commenting the data in key=value or key[en]=comment form"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("track number"), + _("track number inside a collection"), gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("track count"), + _("count of tracks inside collection this track belongs to"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("disc number"), + _("disc number inside a collection"), gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_ALBUM_VOLUME_COUNT, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("disc count"), + _("count of discs inside collection this disc belongs to"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_LOCATION, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("location"), _("Origin of media as a URI (location, where the " + "original of the file or stream is hosted)"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("homepage"), + _("Homepage for this media (i.e. artist or movie homepage)"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("description"), + _("short text describing the content of the data"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING, + _("version"), _("version of this data"), NULL); + gst_tag_register_static (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING, + _("ISRC"), + _ + ("International Standard Recording Code - see http://www.ifpi.org/isrc/"), + NULL); + /* FIXME: organization (fix what? tpm) */ + gst_tag_register_static (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("organization"), _("organization"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META, + G_TYPE_STRING, _("copyright"), _("copyright notice of the data"), NULL); + gst_tag_register_static (GST_TAG_COPYRIGHT_URI, GST_TAG_FLAG_META, + G_TYPE_STRING, _("copyright uri"), + _("URI to the copyright notice of the data"), NULL); + gst_tag_register_static (GST_TAG_ENCODED_BY, GST_TAG_FLAG_META, G_TYPE_STRING, + _("encoded by"), _("name of the encoding person or organization"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_CONTACT, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("contact"), _("contact information"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_LICENSE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("license"), _("license of data"), NULL); + gst_tag_register_static (GST_TAG_LICENSE_URI, GST_TAG_FLAG_META, + G_TYPE_STRING, _("license uri"), + _("URI to the license of the data"), NULL); + gst_tag_register_static (GST_TAG_PERFORMER, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("performer"), + _("person(s) performing"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_COMPOSER, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("composer"), + _("person(s) who composed the recording"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_CONDUCTOR, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("conductor"), + _("conductor/performer refinement"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_DURATION, GST_TAG_FLAG_DECODED, + G_TYPE_UINT64, + _("duration"), _("length in GStreamer time units (nanoseconds)"), NULL); + gst_tag_register_static (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, + _("codec"), + _("codec the data is stored in"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_VIDEO_CODEC, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, + _("video codec"), _("codec the video data is stored in"), NULL); + gst_tag_register_static (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, + _("audio codec"), _("codec the audio data is stored in"), NULL); + gst_tag_register_static (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, + _("subtitle codec"), _("codec the subtitle data is stored in"), NULL); + gst_tag_register_static (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, _("container format"), + _("container format the data is stored in"), NULL); + gst_tag_register_static (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, _("bitrate"), _("exact or average bitrate in bits/s"), NULL); + gst_tag_register_static (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, _("nominal bitrate"), _("nominal bitrate in bits/s"), NULL); + gst_tag_register_static (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, _("minimum bitrate"), _("minimum bitrate in bits/s"), NULL); + gst_tag_register_static (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, _("maximum bitrate"), _("maximum bitrate in bits/s"), NULL); + gst_tag_register_static (GST_TAG_ENCODER, GST_TAG_FLAG_ENCODED, + G_TYPE_STRING, + _("encoder"), _("encoder used to encode this stream"), NULL); + gst_tag_register_static (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, + _("encoder version"), + _("version of the encoder used to encode this stream"), NULL); + gst_tag_register_static (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED, + G_TYPE_UINT, _("serial"), _("serial number of track"), NULL); + gst_tag_register_static (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in db"), NULL); + gst_tag_register_static (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("replaygain track peak"), _("peak of the track"), NULL); + gst_tag_register_static (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in db"), NULL); + gst_tag_register_static (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("replaygain album peak"), _("peak of the album"), NULL); + gst_tag_register_static (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("replaygain reference level"), + _("reference level of track and album gain values"), NULL); + gst_tag_register_static (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("language code"), + _("language code for this stream, conforming to ISO-639-1 or ISO-639-2"), + NULL); + gst_tag_register_static (GST_TAG_LANGUAGE_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("language name"), + _("freeform name of the language this stream is in"), NULL); + gst_tag_register_static (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE, + _("image"), _("image related to this stream"), gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, + /* TRANSLATORS: 'preview image' = image that shows a preview of the full image */ + _("preview image"), _("preview image related to this stream"), NULL); + gst_tag_register_static (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, _("attachment"), _("file attached to this stream"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("beats per minute"), + _("number of beats per minute in audio"), NULL); + gst_tag_register_static (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING, + _("keywords"), _("comma separated keywords describing the content"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("geo location name"), + _("human readable descriptive location of where " + "the media has been recorded or produced"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("geo location latitude"), + _("geo latitude location of where the media has been recorded or " + "produced in degrees according to WGS84 (zero at the equator, " + "negative values for southern latitudes)"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("geo location longitude"), + _("geo longitude location of where the media has been recorded or " + "produced in degrees according to WGS84 (zero at the prime meridian " + "in Greenwich/UK, negative values for western longitudes)"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("geo location elevation"), + _("geo elevation of where the media has been recorded or produced in " + "meters according to WGS84 (zero is average sea level)"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META, + G_TYPE_STRING, _("geo location country"), + _("country (english name) where the media has been recorded " + "or produced"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_CITY, GST_TAG_FLAG_META, + G_TYPE_STRING, _("geo location city"), + _("city (english name) where the media has been recorded " + "or produced"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("geo location sublocation"), + _("a location within a city where the media has been produced " + "or created (e.g. the neighborhood)"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location horizontal error"), + _("expected error of the horizontal positioning measures (in meters)"), + NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement speed"), + _("movement speed of the capturing device while performing the capture " + "in m/s"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement direction"), + _("indicates the movement direction of the device performing the capture" + " of a media. It is represented as degrees in floating point " + "representation, 0 means the geographic north, and increases " + "clockwise"), NULL); + gst_tag_register_static (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location capture direction"), + _("indicates the direction the device is pointing to when capturing " + " a media. It is represented as degrees in floating point " + " representation, 0 means the geographic north, and increases " + "clockwise"), NULL); + gst_tag_register_static (GST_TAG_SHOW_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, + /* TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here */ + _("show name"), + _("Name of the tv/podcast/series show the media is from"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_SHOW_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, + /* TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here */ + _("show sortname"), + _("Name of the tv/podcast/series show the media is from, for sorting " + "purposes"), NULL); + gst_tag_register_static (GST_TAG_SHOW_EPISODE_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, _("episode number"), + _("The episode number in the season the media is part of"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_SHOW_SEASON_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, _("season number"), + _("The season number of the show the media is part of"), + gst_tag_merge_use_first); + gst_tag_register_static (GST_TAG_LYRICS, GST_TAG_FLAG_META, G_TYPE_STRING, + _("lyrics"), _("The lyrics of the media, commonly used for songs"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_COMPOSER_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("composer sortname"), + _("person(s) who composed the recording, for sorting purposes"), NULL); + gst_tag_register_static (GST_TAG_GROUPING, GST_TAG_FLAG_META, G_TYPE_STRING, + _("grouping"), + _("Groups related media that spans multiple tracks, like the different " + "pieces of a concerto. It is a higher level than a track, " + "but lower than an album"), NULL); + gst_tag_register_static (GST_TAG_USER_RATING, GST_TAG_FLAG_META, G_TYPE_UINT, + _("user rating"), + _("Rating attributed by a user. The higher the rank, " + "the more the user likes this media"), NULL); + gst_tag_register_static (GST_TAG_DEVICE_MANUFACTURER, GST_TAG_FLAG_META, + G_TYPE_STRING, _("device manufacturer"), + _("Manufacturer of the device used to create this media"), NULL); + gst_tag_register_static (GST_TAG_DEVICE_MODEL, GST_TAG_FLAG_META, + G_TYPE_STRING, _("device model"), + _("Model of the device used to create this media"), NULL); + gst_tag_register_static (GST_TAG_APPLICATION_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("application name"), + _("Application used to create the media"), NULL); + gst_tag_register_static (GST_TAG_APPLICATION_DATA, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, _("application data"), + _("Arbitrary application data to be serialized into the media"), NULL); + gst_tag_register_static (GST_TAG_IMAGE_ORIENTATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("image orientation"), + _("How the image should be rotated or flipped before display"), NULL); + gst_tag_register_static (GST_TAG_PUBLISHER, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("publisher"), + _("Name of the label or publisher"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_INTERPRETED_BY, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("interpreted-by"), + _("Information about the people behind a remix and similar " + "interpretations"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_MIDI_BASE_NOTE, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("midi-base-note"), _("Midi note number of the audio track."), NULL); + gst_tag_register_static (GST_TAG_PRIVATE_DATA, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, + _("private-data"), _("Private data"), gst_tag_merge_use_first); + +} + +/** + * gst_tag_merge_use_first: + * @dest: (out caller-allocates): uninitialized GValue to store result in + * @src: GValue to copy from + * + * This is a convenience function for the func argument of gst_tag_register(). + * It creates a copy of the first value from the list. + */ +void +gst_tag_merge_use_first (GValue * dest, const GValue * src) +{ + const GValue *ret = gst_value_list_get_value (src, 0); + + g_value_init (dest, G_VALUE_TYPE (ret)); + g_value_copy (ret, dest); +} + +/** + * gst_tag_merge_strings_with_comma: + * @dest: (out caller-allocates): uninitialized GValue to store result in + * @src: GValue to copy from + * + * This is a convenience function for the func argument of gst_tag_register(). + * It concatenates all given strings using a comma. The tag must be registered + * as a G_TYPE_STRING or this function will fail. + */ +void +gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src) +{ + GString *str; + gint i, count; + + count = gst_value_list_get_size (src); + str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0))); + for (i = 1; i < count; i++) { + /* separator between two strings */ + g_string_append (str, _(", ")); + g_string_append (str, + g_value_get_string (gst_value_list_get_value (src, i))); + } + + g_value_init (dest, G_TYPE_STRING); + g_value_take_string (dest, str->str); + g_string_free (str, FALSE); +} + +static GstTagInfo * +gst_tag_lookup (const gchar * tag_name) +{ + GstTagInfo *ret; + + TAG_LOCK; + ret = g_hash_table_lookup (__tags, (gpointer) tag_name); + TAG_UNLOCK; + + return ret; +} + +/** + * gst_tag_register: + * @name: the name or identifier string + * @flag: a flag describing the type of tag info + * @type: the type this data is in + * @nick: human-readable name + * @blurb: a human-readable description about this tag + * @func: (allow-none) (scope call): function for merging multiple values of this tag, or %NULL + * + * Registers a new tag type for the use with GStreamer's type system. If a type + * with that name is already registered, that one is used. + * The old registration may have used a different type however. So don't rely + * on your supplied values. + * + * Important: if you do not supply a merge function the implication will be + * that there can only be one single value for this tag in a tag list and + * any additional values will silently be discarded when being added (unless + * #GST_TAG_MERGE_REPLACE, #GST_TAG_MERGE_REPLACE_ALL, or + * #GST_TAG_MERGE_PREPEND is used as merge mode, in which case the new + * value will replace the old one in the list). + * + * The merge function will be called from gst_tag_list_copy_value() when + * it is required that one or more values for a tag be condensed into + * one single value. This may happen from gst_tag_list_get_string(), + * gst_tag_list_get_int(), gst_tag_list_get_double() etc. What will happen + * exactly in that case depends on how the tag was registered and if a + * merge function was supplied and if so which one. + * + * Two default merge functions are provided: gst_tag_merge_use_first() and + * gst_tag_merge_strings_with_comma(). + */ +void +gst_tag_register (const gchar * name, GstTagFlag flag, GType type, + const gchar * nick, const gchar * blurb, GstTagMergeFunc func) +{ + g_return_if_fail (name != NULL); + g_return_if_fail (nick != NULL); + g_return_if_fail (blurb != NULL); + g_return_if_fail (type != 0 && type != GST_TYPE_LIST); + + gst_tag_register_static (g_intern_string (name), flag, type, + g_intern_string (nick), g_intern_string (blurb), func); +} + +/** + * gst_tag_register_static: + * @name: the name or identifier string (string constant) + * @flag: a flag describing the type of tag info + * @type: the type this data is in + * @nick: human-readable name or short description (string constant) + * @blurb: a human-readable description for this tag (string constant) + * @func: (allow-none) (scope call): function for merging multiple values of this tag, or %NULL + * + * Registers a new tag type for the use with GStreamer's type system. + * + * Same as gst_tag_register(), but @name, @nick, and @blurb must be + * static strings or inlined strings, as they will not be copied. (GStreamer + * plugins will be made resident once loaded, so this function can be used + * even from dynamically loaded plugins.) + */ +void +gst_tag_register_static (const gchar * name, GstTagFlag flag, GType type, + const gchar * nick, const gchar * blurb, GstTagMergeFunc func) +{ + GstTagInfo *info; + + g_return_if_fail (name != NULL); + g_return_if_fail (nick != NULL); + g_return_if_fail (blurb != NULL); + g_return_if_fail (type != 0 && type != GST_TYPE_LIST); + + info = gst_tag_lookup (name); + + if (info) { + g_return_if_fail (info->type == type); + return; + } + + info = g_slice_new (GstTagInfo); + info->flag = flag; + info->type = type; + info->name_quark = g_quark_from_static_string (name); + info->nick = nick; + info->blurb = blurb; + info->merge_func = func; + + TAG_LOCK; + g_hash_table_insert (__tags, (gpointer) name, info); + TAG_UNLOCK; +} + +/** + * gst_tag_exists: + * @tag: name of the tag + * + * Checks if the given type is already registered. + * + * Returns: %TRUE if the type is already registered + */ +gboolean +gst_tag_exists (const gchar * tag) +{ + g_return_val_if_fail (tag != NULL, FALSE); + + return gst_tag_lookup (tag) != NULL; +} + +/** + * gst_tag_get_type: + * @tag: the tag + * + * Gets the #GType used for this tag. + * + * Returns: the #GType of this tag + */ +GType +gst_tag_get_type (const gchar * tag) +{ + GstTagInfo *info; + + g_return_val_if_fail (tag != NULL, 0); + info = gst_tag_lookup (tag); + g_return_val_if_fail (info != NULL, 0); + + return info->type; +} + +/** + * gst_tag_get_nick: + * @tag: the tag + * + * Returns the human-readable name of this tag, You must not change or free + * this string. + * + * Returns: (nullable): the human-readable name of this tag + */ +const gchar * +gst_tag_get_nick (const gchar * tag) +{ + GstTagInfo *info; + + g_return_val_if_fail (tag != NULL, NULL); + info = gst_tag_lookup (tag); + if (!info) { + GST_WARNING ("Uknown tag: %s", tag); + + return tag; + } + + return info->nick; +} + +/** + * gst_tag_get_description: + * @tag: the tag + * + * Returns the human-readable description of this tag, You must not change or + * free this string. + * + * Returns: (nullable): the human-readable description of this tag + */ +const gchar * +gst_tag_get_description (const gchar * tag) +{ + GstTagInfo *info; + + g_return_val_if_fail (tag != NULL, NULL); + info = gst_tag_lookup (tag); + g_return_val_if_fail (info != NULL, NULL); + + return info->blurb; +} + +/** + * gst_tag_get_flag: + * @tag: the tag + * + * Gets the flag of @tag. + * + * Returns: the flag of this tag. + */ +GstTagFlag +gst_tag_get_flag (const gchar * tag) +{ + GstTagInfo *info; + + g_return_val_if_fail (tag != NULL, GST_TAG_FLAG_UNDEFINED); + info = gst_tag_lookup (tag); + g_return_val_if_fail (info != NULL, GST_TAG_FLAG_UNDEFINED); + + return info->flag; +} + +/** + * gst_tag_is_fixed: + * @tag: tag to check + * + * Checks if the given tag is fixed. A fixed tag can only contain one value. + * Unfixed tags can contain lists of values. + * + * Returns: %TRUE, if the given tag is fixed. + */ +gboolean +gst_tag_is_fixed (const gchar * tag) +{ + GstTagInfo *info; + + g_return_val_if_fail (tag != NULL, FALSE); + info = gst_tag_lookup (tag); + g_return_val_if_fail (info != NULL, FALSE); + + return info->merge_func == NULL; +} + +/* takes ownership of the structure */ +static GstTagList * +gst_tag_list_new_internal (GstStructure * s, GstTagScope scope) +{ + GstTagList *tag_list; + + g_assert (s != NULL); + + tag_list = (GstTagList *) g_slice_new (GstTagListImpl); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (tag_list), 0, GST_TYPE_TAG_LIST, + (GstMiniObjectCopyFunction) __gst_tag_list_copy, NULL, + (GstMiniObjectFreeFunction) __gst_tag_list_free); + + GST_TAG_LIST_STRUCTURE (tag_list) = s; + GST_TAG_LIST_SCOPE (tag_list) = scope; + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_TAGS, "created taglist %p", tag_list); +#endif + + return tag_list; +} + +static void +__gst_tag_list_free (GstTagList * list) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_TAGS, "freeing taglist %p", list); +#endif + + gst_structure_free (GST_TAG_LIST_STRUCTURE (list)); + + g_slice_free1 (sizeof (GstTagListImpl), list); +} + +static GstTagList * +__gst_tag_list_copy (const GstTagList * list) +{ + const GstStructure *s; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + + s = GST_TAG_LIST_STRUCTURE (list); + return gst_tag_list_new_internal (gst_structure_copy (s), + GST_TAG_LIST_SCOPE (list)); +} + +/** + * gst_tag_list_new_empty: + * + * Creates a new empty GstTagList. + * + * Free-function: gst_tag_list_unref + * + * Returns: (transfer full): An empty tag list + */ +GstTagList * +gst_tag_list_new_empty (void) +{ + GstStructure *s; + GstTagList *tag_list; + + s = gst_structure_new_id_empty (GST_QUARK (TAGLIST)); + tag_list = gst_tag_list_new_internal (s, GST_TAG_SCOPE_STREAM); + return tag_list; +} + +/** + * gst_tag_list_new: + * @tag: tag + * @...: %NULL-terminated list of values to set + * + * Creates a new taglist and appends the values for the given tags. It expects + * tag-value pairs like gst_tag_list_add(), and a %NULL terminator after the + * last pair. The type of the values is implicit and is documented in the API + * reference, but can also be queried at runtime with gst_tag_get_type(). It + * is an error to pass a value of a type not matching the tag type into this + * function. The tag list will make copies of any arguments passed + * (e.g. strings, buffers). + * + * After creation you might also want to set a #GstTagScope on the returned + * taglist to signal if the contained tags are global or stream tags. By + * default stream scope is assumes. See gst_tag_list_set_scope(). + * + * Free-function: gst_tag_list_unref + * + * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref() + * when no longer needed. + */ +GstTagList * +gst_tag_list_new (const gchar * tag, ...) +{ + GstTagList *list; + va_list args; + + g_return_val_if_fail (tag != NULL, NULL); + + list = gst_tag_list_new_empty (); + va_start (args, tag); + gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args); + va_end (args); + + return list; +} + +/** + * gst_tag_list_new_valist: + * @var_args: tag / value pairs to set + * + * Just like gst_tag_list_new(), only that it takes a va_list argument. + * Useful mostly for language bindings. + * + * Free-function: gst_tag_list_unref + * + * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref() + * when no longer needed. + */ +GstTagList * +gst_tag_list_new_valist (va_list var_args) +{ + GstTagList *list; + const gchar *tag; + + list = gst_tag_list_new_empty (); + + tag = va_arg (var_args, gchar *); + gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args); + + return list; +} + +/** + * gst_tag_list_set_scope: + * @list: a #GstTagList + * @scope: new scope for @list + * + * Sets the scope of @list to @scope. By default the scope + * of a taglist is stream scope. + * + */ +void +gst_tag_list_set_scope (GstTagList * list, GstTagScope scope) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + + GST_TAG_LIST_SCOPE (list) = scope; +} + +/** + * gst_tag_list_get_scope: + * @list: a #GstTagList + * + * Gets the scope of @list. + * + * Returns: The scope of @list + */ +GstTagScope +gst_tag_list_get_scope (const GstTagList * list) +{ + g_return_val_if_fail (GST_IS_TAG_LIST (list), GST_TAG_SCOPE_STREAM); + + return GST_TAG_LIST_SCOPE (list); +} + +/** + * gst_tag_list_to_string: + * @list: a #GstTagList + * + * Serializes a tag list to a string. + * + * Returns: (nullable): a newly-allocated string, or %NULL in case of + * an error. The string must be freed with g_free() when no longer + * needed. + */ +gchar * +gst_tag_list_to_string (const GstTagList * list) +{ + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + + return gst_structure_to_string (GST_TAG_LIST_STRUCTURE (list)); +} + +/** + * gst_tag_list_new_from_string: + * @str: a string created with gst_tag_list_to_string() + * + * Deserializes a tag list. + * + * Returns: (nullable): a new #GstTagList, or %NULL in case of an + * error. + */ +GstTagList * +gst_tag_list_new_from_string (const gchar * str) +{ + GstTagList *tag_list; + GstStructure *s; + + g_return_val_if_fail (str != NULL, NULL); + g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL); + + s = gst_structure_from_string (str, NULL); + if (s == NULL) + return NULL; + + tag_list = gst_tag_list_new_internal (s, GST_TAG_SCOPE_STREAM); + + return tag_list; +} + +/** + * gst_tag_list_n_tags: + * @list: A #GstTagList. + * + * Get the number of tags in @list. + * + * Returns: The number of tags in @list. + */ +gint +gst_tag_list_n_tags (const GstTagList * list) +{ + g_return_val_if_fail (list != NULL, 0); + g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); + + return gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)); +} + +/** + * gst_tag_list_nth_tag_name: + * @list: A #GstTagList. + * @index: the index + * + * Get the name of the tag in @list at @index. + * + * Returns: The name of the tag at @index. + */ +const gchar * +gst_tag_list_nth_tag_name (const GstTagList * list, guint index) +{ + g_return_val_if_fail (list != NULL, 0); + g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); + + return gst_structure_nth_field_name (GST_TAG_LIST_STRUCTURE (list), index); +} + +/** + * gst_tag_list_is_empty: + * @list: A #GstTagList. + * + * Checks if the given taglist is empty. + * + * Returns: %TRUE if the taglist is empty, otherwise %FALSE. + */ +gboolean +gst_tag_list_is_empty (const GstTagList * list) +{ + g_return_val_if_fail (list != NULL, FALSE); + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + + return (gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)) == 0); +} + +static gboolean +gst_tag_list_fields_equal (const GValue * value1, const GValue * value2) +{ + gdouble d1, d2; + + if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) + return TRUE; + + /* fields not equal: add some tolerance for doubles, otherwise bail out */ + if (!G_VALUE_HOLDS_DOUBLE (value1) || !G_VALUE_HOLDS_DOUBLE (value2)) + return FALSE; + + d1 = g_value_get_double (value1); + d2 = g_value_get_double (value2); + + /* This will only work for 'normal' values and values around 0, + * which should be good enough for our purposes here + * FIXME: maybe add this to gst_value_compare_double() ? */ + return (fabs (d1 - d2) < 0.0000001); +} + +/** + * gst_tag_list_is_equal: + * @list1: a #GstTagList. + * @list2: a #GstTagList. + * + * Checks if the two given taglists are equal. + * + * Returns: %TRUE if the taglists are equal, otherwise %FALSE + */ +gboolean +gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2) +{ + const GstStructure *s1, *s2; + gint num_fields1, num_fields2, i; + + g_return_val_if_fail (GST_IS_TAG_LIST (list1), FALSE); + g_return_val_if_fail (GST_IS_TAG_LIST (list2), FALSE); + + /* we don't just use gst_structure_is_equal() here so we can add some + * tolerance for doubles, though maybe we should just add that to + * gst_value_compare_double() as well? */ + s1 = GST_TAG_LIST_STRUCTURE (list1); + s2 = GST_TAG_LIST_STRUCTURE (list2); + + num_fields1 = gst_structure_n_fields (s1); + num_fields2 = gst_structure_n_fields (s2); + + if (num_fields1 != num_fields2) + return FALSE; + + for (i = 0; i < num_fields1; i++) { + const GValue *value1, *value2; + const gchar *tag_name; + + tag_name = gst_structure_nth_field_name (s1, i); + value1 = gst_structure_get_value (s1, tag_name); + value2 = gst_structure_get_value (s2, tag_name); + + if (value2 == NULL) + return FALSE; + + if (!gst_tag_list_fields_equal (value1, value2)) + return FALSE; + } + + return TRUE; +} + +typedef struct +{ + GstTagList *list; + GstTagMergeMode mode; +} +GstTagCopyData; + +static void +gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode, + const gchar * tag, const GValue * value, GstTagInfo * info) +{ + GstStructure *list = GST_TAG_LIST_STRUCTURE (tag_list); + const GValue *value2; + GQuark tag_quark; + + if (info == NULL) { + info = gst_tag_lookup (tag); + if (G_UNLIKELY (info == NULL)) { + g_warning ("unknown tag '%s'", tag); + return; + } + } + + if (G_UNLIKELY (!G_VALUE_HOLDS (value, info->type) && + !GST_VALUE_HOLDS_LIST (value))) { + g_warning ("tag '%s' should hold value of type '%s', but value of " + "type '%s' passed", info->nick, g_type_name (info->type), + g_type_name (G_VALUE_TYPE (value))); + return; + } + + tag_quark = info->name_quark; + + if (info->merge_func + && (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) { + GValue dest = { 0, }; + + switch (mode) { + case GST_TAG_MERGE_REPLACE_ALL: + case GST_TAG_MERGE_REPLACE: + gst_structure_id_set_value (list, tag_quark, value); + break; + case GST_TAG_MERGE_PREPEND: + if (GST_VALUE_HOLDS_LIST (value2) && !GST_VALUE_HOLDS_LIST (value)) + gst_value_list_prepend_value ((GValue *) value2, value); + else { + gst_value_list_merge (&dest, value, value2); + gst_structure_id_take_value (list, tag_quark, &dest); + } + break; + case GST_TAG_MERGE_APPEND: + if (GST_VALUE_HOLDS_LIST (value2) && !GST_VALUE_HOLDS_LIST (value)) + gst_value_list_append_value ((GValue *) value2, value); + else { + gst_value_list_merge (&dest, value2, value); + gst_structure_id_take_value (list, tag_quark, &dest); + } + break; + case GST_TAG_MERGE_KEEP: + case GST_TAG_MERGE_KEEP_ALL: + break; + default: + g_assert_not_reached (); + break; + } + } else { + switch (mode) { + case GST_TAG_MERGE_APPEND: + case GST_TAG_MERGE_KEEP: + if (gst_structure_id_get_value (list, tag_quark) != NULL) + break; + /* fall through */ + case GST_TAG_MERGE_REPLACE_ALL: + case GST_TAG_MERGE_REPLACE: + case GST_TAG_MERGE_PREPEND: + gst_structure_id_set_value (list, tag_quark, value); + break; + case GST_TAG_MERGE_KEEP_ALL: + break; + default: + g_assert_not_reached (); + break; + } + } +} + +static gboolean +gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value, + gpointer user_data) +{ + GstTagCopyData *copy = (GstTagCopyData *) user_data; + const gchar *tag; + + tag = g_quark_to_string (tag_quark); + gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL); + + return TRUE; +} + +/** + * gst_tag_list_insert: + * @into: list to merge into + * @from: list to merge from + * @mode: the mode to use + * + * Inserts the tags of the @from list into the first list using the given mode. + */ +void +gst_tag_list_insert (GstTagList * into, const GstTagList * from, + GstTagMergeMode mode) +{ + GstTagCopyData data; + + g_return_if_fail (GST_IS_TAG_LIST (into)); + g_return_if_fail (gst_tag_list_is_writable (into)); + g_return_if_fail (GST_IS_TAG_LIST (from)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + data.list = into; + data.mode = mode; + if (mode == GST_TAG_MERGE_REPLACE_ALL) { + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (into)); + } + gst_structure_foreach (GST_TAG_LIST_STRUCTURE (from), + gst_tag_list_copy_foreach, &data); +} + +/** + * gst_tag_list_merge: + * @list1: (allow-none): first list to merge + * @list2: (allow-none): second list to merge + * @mode: the mode to use + * + * Merges the two given lists into a new list. If one of the lists is %NULL, a + * copy of the other is returned. If both lists are %NULL, %NULL is returned. + * + * Free-function: gst_tag_list_unref + * + * Returns: (transfer full) (nullable): the new list + */ +GstTagList * +gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2, + GstTagMergeMode mode) +{ + GstTagList *list1_cp; + const GstTagList *list2_cp; + + g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL); + g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL); + g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL); + + /* nothing to merge */ + if (!list1 && !list2) { + return NULL; + } + + /* create empty list, we need to do this to correctly handling merge modes */ + list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new_empty (); + list2_cp = (list2) ? list2 : gst_tag_list_new_empty (); + + gst_tag_list_insert (list1_cp, list2_cp, mode); + + if (!list2) + gst_tag_list_unref ((GstTagList *) list2_cp); + + return list1_cp; +} + +/** + * gst_tag_list_get_tag_size: + * @list: a taglist + * @tag: the tag to query + * + * Checks how many value are stored in this tag list for the given tag. + * + * Returns: The number of tags stored + */ +guint +gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag) +{ + const GValue *value; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); + + value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); + if (value == NULL) + return 0; + if (G_VALUE_TYPE (value) != GST_TYPE_LIST) + return 1; + + return gst_value_list_get_size (value); +} + +/** + * gst_tag_list_add: + * @list: list to set tags in + * @mode: the mode to use + * @tag: tag + * @...: %NULL-terminated list of values to set + * + * Sets the values for the given tags using the specified mode. + */ +void +gst_tag_list_add (GstTagList * list, GstTagMergeMode mode, const gchar * tag, + ...) +{ + va_list args; + + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (tag != NULL); + + va_start (args, tag); + gst_tag_list_add_valist (list, mode, tag, args); + va_end (args); +} + +/** + * gst_tag_list_add_values: + * @list: list to set tags in + * @mode: the mode to use + * @tag: tag + * @...: GValues to set + * + * Sets the GValues for the given tags using the specified mode. + */ +void +gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode, + const gchar * tag, ...) +{ + va_list args; + + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (tag != NULL); + + va_start (args, tag); + gst_tag_list_add_valist_values (list, mode, tag, args); + va_end (args); +} + +/** + * gst_tag_list_add_valist: + * @list: list to set tags in + * @mode: the mode to use + * @tag: tag + * @var_args: tag / value pairs to set + * + * Sets the values for the given tags using the specified mode. + */ +void +gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode, + const gchar * tag, va_list var_args) +{ + GstTagInfo *info; + gchar *error = NULL; + + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (tag != NULL); + + if (mode == GST_TAG_MERGE_REPLACE_ALL) { + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list)); + } + + while (tag != NULL) { + GValue value = { 0, }; + + info = gst_tag_lookup (tag); + if (G_UNLIKELY (info == NULL)) { + g_warning ("unknown tag '%s'", tag); + return; + } + G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error); + if (error) { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + /* we purposely leak the value here, it might not be + * in a sane state if an error condition occoured + */ + return; + } + /* Facilitate GstBuffer -> GstSample transition */ + if (G_UNLIKELY (info->type == GST_TYPE_SAMPLE && + !GST_IS_SAMPLE (value.data[0].v_pointer))) { + g_warning ("Expected GstSample argument for tag '%s'", tag); + } else { + gst_tag_list_add_value_internal (list, mode, tag, &value, info); + } + g_value_unset (&value); + tag = va_arg (var_args, gchar *); + } +} + +/** + * gst_tag_list_add_valist_values: + * @list: list to set tags in + * @mode: the mode to use + * @tag: tag + * @var_args: tag / GValue pairs to set + * + * Sets the GValues for the given tags using the specified mode. + */ +void +gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode, + const gchar * tag, va_list var_args) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (tag != NULL); + + if (mode == GST_TAG_MERGE_REPLACE_ALL) { + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list)); + } + + while (tag != NULL) { + GstTagInfo *info; + + info = gst_tag_lookup (tag); + if (G_UNLIKELY (info == NULL)) { + g_warning ("unknown tag '%s'", tag); + return; + } + gst_tag_list_add_value_internal (list, mode, tag, va_arg (var_args, + GValue *), info); + tag = va_arg (var_args, gchar *); + } +} + +/** + * gst_tag_list_add_value: + * @list: list to set tags in + * @mode: the mode to use + * @tag: tag + * @value: GValue for this tag + * + * Sets the GValue for a given tag using the specified mode. + */ +void +gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode, + const gchar * tag, const GValue * value) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (tag != NULL); + + gst_tag_list_add_value_internal (list, mode, tag, value, NULL); +} + +/** + * gst_tag_list_remove_tag: + * @list: list to remove tag from + * @tag: tag to remove + * + * Removes the given tag from the taglist. + */ +void +gst_tag_list_remove_tag (GstTagList * list, const gchar * tag) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + g_return_if_fail (tag != NULL); + + gst_structure_remove_field (GST_TAG_LIST_STRUCTURE (list), tag); +} + +typedef struct +{ + GstTagForeachFunc func; + const GstTagList *tag_list; + gpointer data; +} +TagForeachData; + +static int +structure_foreach_wrapper (GQuark field_id, const GValue * value, + gpointer user_data) +{ + TagForeachData *data = (TagForeachData *) user_data; + + data->func (data->tag_list, g_quark_to_string (field_id), data->data); + return TRUE; +} + +/** + * gst_tag_list_foreach: + * @list: list to iterate over + * @func: (scope call): function to be called for each tag + * @user_data: (closure): user specified data + * + * Calls the given function for each tag inside the tag list. Note that if there + * is no tag, the function won't be called at all. + */ +void +gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func, + gpointer user_data) +{ + TagForeachData data; + + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (func != NULL); + + data.func = func; + data.tag_list = list; + data.data = user_data; + gst_structure_foreach (GST_TAG_LIST_STRUCTURE (list), + structure_foreach_wrapper, &data); +} + +/** + * gst_tag_list_get_value_index: + * @list: a #GstTagList + * @tag: tag to read out + * @index: number of entry to read out + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: (transfer none) (nullable): The GValue for the specified + * entry or %NULL if the tag wasn't available or the tag + * doesn't have as many entries + */ +const GValue * +gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag, + guint index) +{ + const GValue *value; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + g_return_val_if_fail (tag != NULL, NULL); + + value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); + if (value == NULL) + return NULL; + + if (GST_VALUE_HOLDS_LIST (value)) { + if (index >= gst_value_list_get_size (value)) + return NULL; + return gst_value_list_get_value (value, index); + } else { + if (index > 0) + return NULL; + return value; + } +} + +/** + * gst_tag_list_copy_value: + * @dest: (out caller-allocates): uninitialized #GValue to copy into + * @list: list to get the tag from + * @tag: tag to read out + * + * Copies the contents for the given tag into the value, + * merging multiple values into one if multiple values are associated + * with the tag. + * You must g_value_unset() the value after use. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +gboolean +gst_tag_list_copy_value (GValue * dest, const GstTagList * list, + const gchar * tag) +{ + const GValue *src; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE); + + src = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); + if (!src) + return FALSE; + + if (G_VALUE_TYPE (src) == GST_TYPE_LIST) { + GstTagInfo *info = gst_tag_lookup (tag); + + if (!info) + return FALSE; + + /* must be there or lists aren't allowed */ + g_assert (info->merge_func); + info->merge_func (dest, src); + } else { + g_value_init (dest, G_VALUE_TYPE (src)); + g_value_copy (src, dest); + } + return TRUE; +} + +/* FIXME 2.0: this whole merge function business is overdesigned, and the + * _get_foo() API is misleading as well - how many application developers will + * expect gst_tag_list_get_string (list, GST_TAG_ARTIST, &val) might return a + * string with multiple comma-separated artists? _get_foo() should just be + * a convenience wrapper around _get_foo_index (list, tag, 0, &val), + * supplemented by a special _tag_list_get_string_merged() function if needed + * (unless someone can actually think of real use cases where the merge + * function is not 'use first' for non-strings and merge for strings) */ + +/***** evil macros to get all the gst_tag_list_get_*() functions right *****/ + +#define TAG_MERGE_FUNCS(name,type,ret) \ +gboolean \ +gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag, \ + type *value) \ +{ \ + GValue v = { 0, }; \ + \ + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \ + g_return_val_if_fail (tag != NULL, FALSE); \ + g_return_val_if_fail (value != NULL, FALSE); \ + \ + if (!gst_tag_list_copy_value (&v, list, tag)) \ + return FALSE; \ + *value = COPY_FUNC (g_value_get_ ## name (&v)); \ + g_value_unset (&v); \ + return ret; \ +} \ + \ +gboolean \ +gst_tag_list_get_ ## name ## _index (const GstTagList *list, \ + const gchar *tag, \ + guint index, type *value) \ +{ \ + const GValue *v; \ + \ + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \ + g_return_val_if_fail (tag != NULL, FALSE); \ + g_return_val_if_fail (value != NULL, FALSE); \ + \ + if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) \ + return FALSE; \ + *value = COPY_FUNC (g_value_get_ ## name (v)); \ + return ret; \ +} + +#define COPY_FUNC /**/ +/** + * gst_tag_list_get_boolean: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_boolean_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (boolean, gboolean, TRUE); +/** + * gst_tag_list_get_int: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_int_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (int, gint, TRUE); +/** + * gst_tag_list_get_uint: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_uint_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (uint, guint, TRUE); +/** + * gst_tag_list_get_int64: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_int64_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (int64, gint64, TRUE); +/** + * gst_tag_list_get_uint64: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_uint64_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (uint64, guint64, TRUE); +/** + * gst_tag_list_get_float: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_float_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (float, gfloat, TRUE); +/** + * gst_tag_list_get_double: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_double_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (double, gdouble, TRUE); +/** + * gst_tag_list_get_pointer: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out) (transfer none): location for the result + * + * Copies the contents for the given tag into the value, merging multiple values + * into one if multiple values are associated with the tag. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_pointer_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out) (transfer none): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL)); + +static inline gchar * +_gst_strdup0 (const gchar * s) +{ + if (s == NULL || *s == '\0') + return NULL; + + return g_strdup (s); +} + +#undef COPY_FUNC +#define COPY_FUNC _gst_strdup0 + +/** + * gst_tag_list_get_string: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out callee-allocates) (transfer full): location for the result + * + * Copies the contents for the given tag into the value, possibly merging + * multiple values into one if multiple values are associated with the tag. + * + * Use gst_tag_list_get_string_index (list, tag, 0, value) if you want + * to retrieve the first string associated with this tag unmodified. + * + * The resulting string in @value will be in UTF-8 encoding and should be + * freed by the caller using g_free when no longer needed. The + * returned string is also guaranteed to be non-%NULL and non-empty. + * + * Free-function: g_free + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +/** + * gst_tag_list_get_string_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out callee-allocates) (transfer full): location for the result + * + * Gets the value that is at the given index for the given tag in the given + * list. + * + * The resulting string in @value will be in UTF-8 encoding and should be + * freed by the caller using g_free when no longer needed. The + * returned string is also guaranteed to be non-%NULL and non-empty. + * + * Free-function: g_free + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list. + */ +TAG_MERGE_FUNCS (string, gchar *, (*value != NULL)); + +/* + *FIXME 2.0: Instead of _peek (non-copy) and _get (copy), we could have + * _get (non-copy) and _dup (copy) for strings, seems more + * widely used + */ +/** + * gst_tag_list_peek_string_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out) (transfer none): location for the result + * + * Peeks at the value that is at the given index for the given tag in the given + * list. + * + * The resulting string in @value will be in UTF-8 encoding and doesn't need + * to be freed by the caller. The returned string is also guaranteed to + * be non-%NULL and non-empty. + * + * Returns: %TRUE, if a value was set, %FALSE if the tag didn't exist in the + * given list. + */ +gboolean +gst_tag_list_peek_string_index (const GstTagList * list, + const gchar * tag, guint index, const gchar ** value) +{ + const GValue *v; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) + return FALSE; + *value = g_value_get_string (v); + return *value != NULL && **value != '\0'; +} + +/** + * gst_tag_list_get_date: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out callee-allocates) (transfer full): address of a GDate pointer + * variable to store the result into + * + * Copies the first date for the given tag in the taglist into the variable + * pointed to by @value. Free the date with g_date_free() when it is no longer + * needed. + * + * Free-function: g_date_free + * + * Returns: %TRUE, if a date was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_date (const GstTagList * list, const gchar * tag, + GDate ** value) +{ + GValue v = { 0, }; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if (!gst_tag_list_copy_value (&v, list, tag)) + return FALSE; + *value = (GDate *) g_value_dup_boxed (&v); + g_value_unset (&v); + return (*value != NULL); +} + +/** + * gst_tag_list_get_date_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out callee-allocates) (transfer full): location for the result + * + * Gets the date that is at the given index for the given tag in the given + * list and copies it into the variable pointed to by @value. Free the date + * with g_date_free() when it is no longer needed. + * + * Free-function: g_date_free + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_date_index (const GstTagList * list, + const gchar * tag, guint index, GDate ** value) +{ + const GValue *v; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) + return FALSE; + *value = (GDate *) g_value_dup_boxed (v); + return (*value != NULL); +} + +/** + * gst_tag_list_get_date_time: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @value: (out callee-allocates) (transfer full): address of a #GstDateTime + * pointer variable to store the result into + * + * Copies the first datetime for the given tag in the taglist into the variable + * pointed to by @value. Unref the date with gst_date_time_unref() when + * it is no longer needed. + * + * Free-function: gst_date_time_unref + * + * Returns: %TRUE, if a datetime was copied, %FALSE if the tag didn't exist in + * the given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag, + GstDateTime ** value) +{ + GValue v = { 0, }; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if (!gst_tag_list_copy_value (&v, list, tag)) + return FALSE; + + *value = (GstDateTime *) g_value_dup_boxed (&v); + g_value_unset (&v); + return (*value != NULL); +} + +/** + * gst_tag_list_get_date_time_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @value: (out callee-allocates) (transfer full): location for the result + * + * Gets the datetime that is at the given index for the given tag in the given + * list and copies it into the variable pointed to by @value. Unref the datetime + * with gst_date_time_unref() when it is no longer needed. + * + * Free-function: gst_date_time_unref + * + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_date_time_index (const GstTagList * list, + const gchar * tag, guint index, GstDateTime ** value) +{ + const GValue *v; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) + return FALSE; + *value = (GstDateTime *) g_value_dup_boxed (v); + return (*value != NULL); +} + +/** + * gst_tag_list_get_sample: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @sample: (out callee-allocates) (transfer full): address of a GstSample + * pointer variable to store the result into + * + * Copies the first sample for the given tag in the taglist into the variable + * pointed to by @sample. Free the sample with gst_sample_unref() when it is + * no longer needed. You can retrieve the buffer from the sample using + * gst_sample_get_buffer() and the associated caps (if any) with + * gst_sample_get_caps(). + * + * Free-function: gst_sample_unref + * + * Returns: %TRUE, if a sample was returned, %FALSE if the tag didn't exist in + * the given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_sample (const GstTagList * list, const gchar * tag, + GstSample ** sample) +{ + GValue v = { 0, }; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (sample != NULL, FALSE); + + if (!gst_tag_list_copy_value (&v, list, tag)) + return FALSE; + *sample = g_value_dup_boxed (&v); + g_value_unset (&v); + return (*sample != NULL); +} + +/** + * gst_tag_list_get_sample_index: + * @list: a #GstTagList to get the tag from + * @tag: tag to read out + * @index: number of entry to read out + * @sample: (out callee-allocates) (transfer full): address of a GstSample + * pointer variable to store the result into + * + * Gets the sample that is at the given index for the given tag in the given + * list and copies it into the variable pointed to by @sample. Free the sample + * with gst_sample_unref() when it is no longer needed. You can retrieve the + * buffer from the sample using gst_sample_get_buffer() and the associated + * caps (if any) with gst_sample_get_caps(). + * + * Free-function: gst_sample_unref + * + * Returns: %TRUE, if a sample was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. + */ +gboolean +gst_tag_list_get_sample_index (const GstTagList * list, + const gchar * tag, guint index, GstSample ** sample) +{ + const GValue *v; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (sample != NULL, FALSE); + + if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) + return FALSE; + *sample = g_value_dup_boxed (v); + return (*sample != NULL); +} diff --git a/gst/gsttaglist.h b/gst/gsttaglist.h new file mode 100644 index 0000000..0466183 --- /dev/null +++ b/gst/gsttaglist.h @@ -0,0 +1,1169 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttaglist.h: Header for tag support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TAGLIST_H__ +#define __GST_TAGLIST_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstTagMergeMode: + * @GST_TAG_MERGE_UNDEFINED: undefined merge mode + * @GST_TAG_MERGE_REPLACE_ALL: replace all tags (clear list and append) + * @GST_TAG_MERGE_REPLACE: replace tags + * @GST_TAG_MERGE_APPEND: append tags + * @GST_TAG_MERGE_PREPEND: prepend tags + * @GST_TAG_MERGE_KEEP: keep existing tags + * @GST_TAG_MERGE_KEEP_ALL: keep all existing tags + * @GST_TAG_MERGE_COUNT: the number of merge modes + * + * The different tag merging modes are basically replace, overwrite and append, + * but they can be seen from two directions. Given two taglists: (A) the tags + * already in the element and (B) the ones that are supplied to the element ( + * e.g. via gst_tag_setter_merge_tags() / gst_tag_setter_add_tags() or a + * %GST_EVENT_TAG), how are these tags merged? + * In the table below this is shown for the cases that a tag exists in the list + * (A) or does not exists (!A) and combinations thereof. + * + * + * merge mode + * + * + * + * merge mode + * A + B + * A + !B + * !A + B + * !A + !B + * + * + * + * + * REPLACE_ALL + * B + * - + * B + * - + * + * + * REPLACE + * B + * A + * B + * - + * + * + * APPEND + * A, B + * A + * B + * - + * + * + * PREPEND + * B, A + * A + * B + * - + * + * + * KEEP + * A + * A + * B + * - + * + * + * KEEP_ALL + * A + * A + * - + * - + * + * + * + *
+ */ +typedef enum { + GST_TAG_MERGE_UNDEFINED, + GST_TAG_MERGE_REPLACE_ALL, + GST_TAG_MERGE_REPLACE, + GST_TAG_MERGE_APPEND, + GST_TAG_MERGE_PREPEND, + GST_TAG_MERGE_KEEP, + GST_TAG_MERGE_KEEP_ALL, + /* add more */ + GST_TAG_MERGE_COUNT +} GstTagMergeMode; + +#define GST_TAG_MODE_IS_VALID(mode) (((mode) > GST_TAG_MERGE_UNDEFINED) && ((mode) < GST_TAG_MERGE_COUNT)) + +/** + * GstTagFlag: + * @GST_TAG_FLAG_UNDEFINED: undefined flag + * @GST_TAG_FLAG_META: tag is meta data + * @GST_TAG_FLAG_ENCODED: tag is encoded + * @GST_TAG_FLAG_DECODED: tag is decoded + * @GST_TAG_FLAG_COUNT: number of tag flags + * + * Extra tag flags used when registering tags. + */ +/* FIXME: these are not really flags .. */ +typedef enum { + GST_TAG_FLAG_UNDEFINED, + GST_TAG_FLAG_META, + GST_TAG_FLAG_ENCODED, + GST_TAG_FLAG_DECODED, + GST_TAG_FLAG_COUNT +} GstTagFlag; + +#define GST_TAG_FLAG_IS_VALID(flag) (((flag) > GST_TAG_FLAG_UNDEFINED) && ((flag) < GST_TAG_FLAG_COUNT)) + +/** + * GstTagList: + * @mini_object: the parent type + * + * Object describing tags / metadata. + */ +typedef struct _GstTagList GstTagList; +struct _GstTagList { + GstMiniObject mini_object; +}; + +GST_API GType _gst_tag_list_type; + +#define GST_TAG_LIST(x) ((GstTagList *) (x)) +#define GST_TYPE_TAG_LIST (_gst_tag_list_type) +#define GST_IS_TAG_LIST(obj) (GST_IS_MINI_OBJECT_TYPE((obj), GST_TYPE_TAG_LIST)) + +/** + * GstTagForeachFunc: + * @list: the #GstTagList + * @tag: a name of a tag in @list + * @user_data: user data + * + * A function that will be called in gst_tag_list_foreach(). The function may + * not modify the tag list. + */ +typedef void (*GstTagForeachFunc) (const GstTagList * list, + const gchar * tag, + gpointer user_data); + +/** + * GstTagMergeFunc: + * @dest: the destination #GValue + * @src: the source #GValue + * + * A function for merging multiple values of a tag used when registering + * tags. + */ +typedef void (* GstTagMergeFunc) (GValue *dest, const GValue *src); + +GST_API +GType gst_tag_list_get_type (void); + +/* tag registration */ + +GST_API +void gst_tag_register (const gchar * name, + GstTagFlag flag, + GType type, + const gchar * nick, + const gchar * blurb, + GstTagMergeFunc func); +GST_API +void gst_tag_register_static (const gchar * name, + GstTagFlag flag, + GType type, + const gchar * nick, + const gchar * blurb, + GstTagMergeFunc func); + +/* some default merging functions */ + +GST_API +void gst_tag_merge_use_first (GValue * dest, const GValue * src); + +GST_API +void gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src); + +/* basic tag support */ + +GST_API +gboolean gst_tag_exists (const gchar * tag); + +GST_API +GType gst_tag_get_type (const gchar * tag); + +GST_API +const gchar * gst_tag_get_nick (const gchar * tag); + +GST_API +const gchar * gst_tag_get_description (const gchar * tag); + +GST_API +GstTagFlag gst_tag_get_flag (const gchar * tag); + +GST_API +gboolean gst_tag_is_fixed (const gchar * tag); + +/* tag lists */ + +/** + * GstTagScope: + * @GST_TAG_SCOPE_STREAM: tags specific to this single stream + * @GST_TAG_SCOPE_GLOBAL: global tags for the complete medium + * + * GstTagScope specifies if a taglist applies to the complete + * medium or only to one single stream. + */ +typedef enum { + GST_TAG_SCOPE_STREAM, + GST_TAG_SCOPE_GLOBAL +} GstTagScope; + +GST_API +GstTagList * gst_tag_list_new_empty (void) G_GNUC_MALLOC; + +GST_API +GstTagList * gst_tag_list_new (const gchar * tag, ...) G_GNUC_MALLOC; + +GST_API +GstTagList * gst_tag_list_new_valist (va_list var_args) G_GNUC_MALLOC; + +GST_API +void gst_tag_list_set_scope (GstTagList * list, GstTagScope scope); + +GST_API +GstTagScope gst_tag_list_get_scope (const GstTagList * list); + +GST_API +gchar * gst_tag_list_to_string (const GstTagList * list) G_GNUC_MALLOC; + +GST_API +GstTagList * gst_tag_list_new_from_string (const gchar * str) G_GNUC_MALLOC; + +GST_API +gint gst_tag_list_n_tags (const GstTagList * list); + +GST_API +const gchar* gst_tag_list_nth_tag_name (const GstTagList * list, guint index); + +GST_API +gboolean gst_tag_list_is_empty (const GstTagList * list); + +GST_API +gboolean gst_tag_list_is_equal (const GstTagList * list1, + const GstTagList * list2); +GST_API +void gst_tag_list_insert (GstTagList * into, + const GstTagList * from, + GstTagMergeMode mode); +GST_API +GstTagList * gst_tag_list_merge (const GstTagList * list1, + const GstTagList * list2, + GstTagMergeMode mode) G_GNUC_MALLOC; +GST_API +guint gst_tag_list_get_tag_size (const GstTagList * list, + const gchar * tag); +GST_API +void gst_tag_list_add (GstTagList * list, + GstTagMergeMode mode, + const gchar * tag, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_tag_list_add_values (GstTagList * list, + GstTagMergeMode mode, + const gchar * tag, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_tag_list_add_valist (GstTagList * list, + GstTagMergeMode mode, + const gchar * tag, + va_list var_args); +GST_API +void gst_tag_list_add_valist_values (GstTagList * list, + GstTagMergeMode mode, + const gchar * tag, + va_list var_args); +GST_API +void gst_tag_list_add_value (GstTagList * list, + GstTagMergeMode mode, + const gchar * tag, + const GValue * value); +GST_API +void gst_tag_list_remove_tag (GstTagList * list, + const gchar * tag); +GST_API +void gst_tag_list_foreach (const GstTagList * list, + GstTagForeachFunc func, + gpointer user_data); +GST_API +const GValue * + gst_tag_list_get_value_index (const GstTagList * list, + const gchar * tag, + guint index); +GST_API +gboolean gst_tag_list_copy_value (GValue * dest, + const GstTagList * list, + const gchar * tag); + +/* simplifications (FIXME: do we want them?) */ + +GST_API +gboolean gst_tag_list_get_boolean (const GstTagList * list, + const gchar * tag, + gboolean * value); +GST_API +gboolean gst_tag_list_get_boolean_index (const GstTagList * list, + const gchar * tag, + guint index, + gboolean * value); +GST_API +gboolean gst_tag_list_get_int (const GstTagList * list, + const gchar * tag, + gint * value); +GST_API +gboolean gst_tag_list_get_int_index (const GstTagList * list, + const gchar * tag, + guint index, + gint * value); +GST_API +gboolean gst_tag_list_get_uint (const GstTagList * list, + const gchar * tag, + guint * value); +GST_API +gboolean gst_tag_list_get_uint_index (const GstTagList * list, + const gchar * tag, + guint index, + guint * value); +GST_API +gboolean gst_tag_list_get_int64 (const GstTagList * list, + const gchar * tag, + gint64 * value); +GST_API +gboolean gst_tag_list_get_int64_index (const GstTagList * list, + const gchar * tag, + guint index, + gint64 * value); +GST_API +gboolean gst_tag_list_get_uint64 (const GstTagList * list, + const gchar * tag, + guint64 * value); +GST_API +gboolean gst_tag_list_get_uint64_index (const GstTagList * list, + const gchar * tag, + guint index, + guint64 * value); +GST_API +gboolean gst_tag_list_get_float (const GstTagList * list, + const gchar * tag, + gfloat * value); +GST_API +gboolean gst_tag_list_get_float_index (const GstTagList * list, + const gchar * tag, + guint index, + gfloat * value); +GST_API +gboolean gst_tag_list_get_double (const GstTagList * list, + const gchar * tag, + gdouble * value); +GST_API +gboolean gst_tag_list_get_double_index (const GstTagList * list, + const gchar * tag, + guint index, + gdouble * value); +GST_API +gboolean gst_tag_list_get_string (const GstTagList * list, + const gchar * tag, + gchar ** value); +GST_API +gboolean gst_tag_list_get_string_index (const GstTagList * list, + const gchar * tag, + guint index, + gchar ** value); +GST_API +gboolean gst_tag_list_peek_string_index (const GstTagList * list, + const gchar * tag, + guint index, + const gchar ** value); +GST_API +gboolean gst_tag_list_get_pointer (const GstTagList * list, + const gchar * tag, + gpointer * value); +GST_API +gboolean gst_tag_list_get_pointer_index (const GstTagList * list, + const gchar * tag, + guint index, + gpointer * value); +GST_API +gboolean gst_tag_list_get_date (const GstTagList * list, + const gchar * tag, + GDate ** value); +GST_API +gboolean gst_tag_list_get_date_index (const GstTagList * list, + const gchar * tag, + guint index, + GDate ** value); +GST_API +gboolean gst_tag_list_get_date_time (const GstTagList * list, + const gchar * tag, + GstDateTime ** value); +GST_API +gboolean gst_tag_list_get_date_time_index (const GstTagList * list, + const gchar * tag, + guint index, + GstDateTime ** value); +GST_API +gboolean gst_tag_list_get_sample (const GstTagList * list, + const gchar * tag, + GstSample ** sample); +GST_API +gboolean gst_tag_list_get_sample_index (const GstTagList * list, + const gchar * tag, + guint index, + GstSample ** sample); + +/* refcounting */ +/** + * gst_tag_list_ref: + * @taglist: the #GstTagList to reference + * + * Add a reference to a #GstTagList mini object. + * + * From this point on, until the caller calls gst_tag_list_unref() or + * gst_tag_list_make_writable(), it is guaranteed that the taglist object will + * not change. To use a #GstTagList object, you must always have a refcount on + * it -- either the one made implicitly by e.g. gst_tag_list_new(), or via + * taking one explicitly with this function. + * + * Returns: the same #GstTagList mini object. + */ +static inline GstTagList * +gst_tag_list_ref (GstTagList * taglist) +{ + return (GstTagList *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (taglist)); +} + +/** + * gst_tag_list_unref: + * @taglist: a #GstTagList. + * + * Unref a #GstTagList, and and free all its memory when the refcount reaches 0. + */ +static inline void +gst_tag_list_unref (GstTagList * taglist) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (taglist)); +} + +/** + * gst_tag_list_copy: + * @taglist: a #GstTagList. + * + * Creates a new #GstTagList as a copy of the old @taglist. The new taglist + * will have a refcount of 1, owned by the caller, and will be writable as + * a result. + * + * Note that this function is the semantic equivalent of a gst_tag_list_ref() + * followed by a gst_tag_list_make_writable(). If you only want to hold on to a + * reference to the data, you should use gst_tag_list_ref(). + * + * When you are finished with the taglist, call gst_tag_list_unref() on it. + * + * Returns: the new #GstTagList + */ +static inline GstTagList * +gst_tag_list_copy (const GstTagList * taglist) +{ + return GST_TAG_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (taglist))); +} + +/** + * gst_tag_list_is_writable: + * @taglist: a #GstTagList + * + * Tests if you can safely modify @taglist. It is only safe to modify taglist + * when there is only one owner of the taglist - ie, the refcount is 1. + */ +#define gst_tag_list_is_writable(taglist) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (taglist)) + +/** + * gst_tag_list_make_writable: + * @taglist: (transfer full): a #GstTagList + * + * Returns a writable copy of @taglist. + * + * If there is only one reference count on @taglist, the caller must be the + * owner, and so this function will return the taglist object unchanged. If on + * the other hand there is more than one reference on the object, a new taglist + * object will be returned (which will be a copy of @taglist). The caller's + * reference on @taglist will be removed, and instead the caller will own a + * reference to the returned object. + * + * In short, this function unrefs the taglist in the argument and refs the + * taglist that it returns. Don't access the argument after calling this + * function. See also: gst_tag_list_ref(). + * + * Returns: (transfer full): a writable taglist which may or may not be the + * same as @taglist + */ +#define gst_tag_list_make_writable(taglist) GST_TAG_LIST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (taglist))) + +/* GStreamer core tags */ +/** + * GST_TAG_TITLE: + * + * commonly used title (string) + * + * The title as it should be displayed, e.g. 'The Doll House' + */ +#define GST_TAG_TITLE "title" +/** + * GST_TAG_TITLE_SORTNAME: + * + * commonly used title, as used for sorting (string) + * + * The title as it should be sorted, e.g. 'Doll House, The' + */ +#define GST_TAG_TITLE_SORTNAME "title-sortname" +/** + * GST_TAG_ARTIST: + * + * person(s) responsible for the recording (string) + * + * The artist name as it should be displayed, e.g. 'Jimi Hendrix' or + * 'The Guitar Heroes' + */ +#define GST_TAG_ARTIST "artist" +/** + * GST_TAG_ARTIST_SORTNAME: + * + * person(s) responsible for the recording, as used for sorting (string) + * + * The artist name as it should be sorted, e.g. 'Hendrix, Jimi' or + * 'Guitar Heroes, The' + */ +#define GST_TAG_ARTIST_SORTNAME "artist-sortname" +/** + * GST_TAG_ALBUM: + * + * album containing this data (string) + * + * The album name as it should be displayed, e.g. 'The Jazz Guitar' + */ +#define GST_TAG_ALBUM "album" +/** + * GST_TAG_ALBUM_SORTNAME: + * + * album containing this data, as used for sorting (string) + * + * The album name as it should be sorted, e.g. 'Jazz Guitar, The' + */ +#define GST_TAG_ALBUM_SORTNAME "album-sortname" +/** + * GST_TAG_ALBUM_ARTIST: + * + * The artist of the entire album, as it should be displayed. + */ +#define GST_TAG_ALBUM_ARTIST "album-artist" +/** + * GST_TAG_ALBUM_ARTIST_SORTNAME: + * + * The artist of the entire album, as it should be sorted. + */ +#define GST_TAG_ALBUM_ARTIST_SORTNAME "album-artist-sortname" +/** + * GST_TAG_COMPOSER: + * + * person(s) who composed the recording (string) + */ +#define GST_TAG_COMPOSER "composer" +/** + * GST_TAG_CONDUCTOR: + * + * conductor/performer refinement (string) + * + * Since: 1.8 + */ +#define GST_TAG_CONDUCTOR "conductor" +/** + * GST_TAG_DATE: + * + * date the data was created (#GDate structure) + */ +#define GST_TAG_DATE "date" +/** + * GST_TAG_DATE_TIME: + * + * date and time the data was created (#GstDateTime structure) + */ +#define GST_TAG_DATE_TIME "datetime" +/** + * GST_TAG_GENRE: + * + * genre this data belongs to (string) + */ +#define GST_TAG_GENRE "genre" +/** + * GST_TAG_COMMENT: + * + * free text commenting the data (string) + */ +#define GST_TAG_COMMENT "comment" +/** + * GST_TAG_EXTENDED_COMMENT: + * + * key/value text commenting the data (string) + * + * Must be in the form of 'key=comment' or + * 'key[lc]=comment' where 'lc' is an ISO-639 + * language code. + * + * This tag is used for unknown Vorbis comment tags, + * unknown APE tags and certain ID3v2 comment fields. + */ +#define GST_TAG_EXTENDED_COMMENT "extended-comment" +/** + * GST_TAG_TRACK_NUMBER: + * + * track number inside a collection (unsigned integer) + */ +#define GST_TAG_TRACK_NUMBER "track-number" +/** + * GST_TAG_TRACK_COUNT: + * + * count of tracks inside collection this track belongs to (unsigned integer) + */ +#define GST_TAG_TRACK_COUNT "track-count" +/** + * GST_TAG_ALBUM_VOLUME_NUMBER: + * + * disc number inside a collection (unsigned integer) + */ +#define GST_TAG_ALBUM_VOLUME_NUMBER "album-disc-number" +/** + * GST_TAG_ALBUM_VOLUME_COUNT: + * + * count of discs inside collection this disc belongs to (unsigned integer) + */ +#define GST_TAG_ALBUM_VOLUME_COUNT "album-disc-count" +/** + * GST_TAG_LOCATION: + * + * Origin of media as a URI (location, where the original of the file or stream + * is hosted) (string) + */ +#define GST_TAG_LOCATION "location" +/** + * GST_TAG_HOMEPAGE: + * + * Homepage for this media (i.e. artist or movie homepage) (string) + */ +#define GST_TAG_HOMEPAGE "homepage" +/** + * GST_TAG_DESCRIPTION: + * + * short text describing the content of the data (string) + */ +#define GST_TAG_DESCRIPTION "description" +/** + * GST_TAG_VERSION: + * + * version of this data (string) + */ +#define GST_TAG_VERSION "version" +/** + * GST_TAG_ISRC: + * + * International Standard Recording Code - see http://www.ifpi.org/isrc/ (string) + */ +#define GST_TAG_ISRC "isrc" +/** + * GST_TAG_ORGANIZATION: + * + * organization (string) + */ +#define GST_TAG_ORGANIZATION "organization" +/** + * GST_TAG_COPYRIGHT: + * + * copyright notice of the data (string) + */ +#define GST_TAG_COPYRIGHT "copyright" +/** + * GST_TAG_COPYRIGHT_URI: + * + * URI to location where copyright details can be found (string) + */ +#define GST_TAG_COPYRIGHT_URI "copyright-uri" +/** + * GST_TAG_ENCODED_BY: + * + * name of the person or organisation that encoded the file. May contain a + * copyright message if the person or organisation also holds the copyright + * (string) + * + * Note: do not use this field to describe the encoding application. Use + * #GST_TAG_APPLICATION_NAME or #GST_TAG_COMMENT for that. + */ +#define GST_TAG_ENCODED_BY "encoded-by" +/** + * GST_TAG_CONTACT: + * + * contact information (string) + */ +#define GST_TAG_CONTACT "contact" +/** + * GST_TAG_LICENSE: + * + * license of data (string) + */ +#define GST_TAG_LICENSE "license" +/** + * GST_TAG_LICENSE_URI: + * + * URI to location where license details can be found (string) + */ +#define GST_TAG_LICENSE_URI "license-uri" +/** + * GST_TAG_PERFORMER: + * + * person(s) performing (string) + */ +#define GST_TAG_PERFORMER "performer" +/** + * GST_TAG_DURATION: + * + * length in GStreamer time units (nanoseconds) (unsigned 64-bit integer) + */ +#define GST_TAG_DURATION "duration" +/** + * GST_TAG_CODEC: + * + * codec the data is stored in (string) + */ +#define GST_TAG_CODEC "codec" +/** + * GST_TAG_VIDEO_CODEC: + * + * codec the video data is stored in (string) + */ +#define GST_TAG_VIDEO_CODEC "video-codec" +/** + * GST_TAG_AUDIO_CODEC: + * + * codec the audio data is stored in (string) + */ +#define GST_TAG_AUDIO_CODEC "audio-codec" +/** + * GST_TAG_SUBTITLE_CODEC: + * + * codec/format the subtitle data is stored in (string) + */ +#define GST_TAG_SUBTITLE_CODEC "subtitle-codec" +/** + * GST_TAG_CONTAINER_FORMAT: + * + * container format the data is stored in (string) + */ +#define GST_TAG_CONTAINER_FORMAT "container-format" +/** + * GST_TAG_BITRATE: + * + * exact or average bitrate in bits/s (unsigned integer) + */ +#define GST_TAG_BITRATE "bitrate" +/** + * GST_TAG_NOMINAL_BITRATE: + * + * nominal bitrate in bits/s (unsigned integer). The actual bitrate might be + * different from this target bitrate. + */ +#define GST_TAG_NOMINAL_BITRATE "nominal-bitrate" +/** + * GST_TAG_MINIMUM_BITRATE: + * + * minimum bitrate in bits/s (unsigned integer) + */ +#define GST_TAG_MINIMUM_BITRATE "minimum-bitrate" +/** + * GST_TAG_MAXIMUM_BITRATE: + * + * maximum bitrate in bits/s (unsigned integer) + */ +#define GST_TAG_MAXIMUM_BITRATE "maximum-bitrate" +/** + * GST_TAG_SERIAL: + * + * serial number of track (unsigned integer) + */ +#define GST_TAG_SERIAL "serial" +/** + * GST_TAG_ENCODER: + * + * encoder used to encode this stream (string) + */ +#define GST_TAG_ENCODER "encoder" +/** + * GST_TAG_ENCODER_VERSION: + * + * version of the encoder used to encode this stream (unsigned integer) + */ +#define GST_TAG_ENCODER_VERSION "encoder-version" +/** + * GST_TAG_TRACK_GAIN: + * + * track gain in db (double) + */ +#define GST_TAG_TRACK_GAIN "replaygain-track-gain" +/** + * GST_TAG_TRACK_PEAK: + * + * peak of the track (double) + */ +#define GST_TAG_TRACK_PEAK "replaygain-track-peak" +/** + * GST_TAG_ALBUM_GAIN: + * + * album gain in db (double) + */ +#define GST_TAG_ALBUM_GAIN "replaygain-album-gain" +/** + * GST_TAG_ALBUM_PEAK: + * + * peak of the album (double) + */ +#define GST_TAG_ALBUM_PEAK "replaygain-album-peak" +/** + * GST_TAG_REFERENCE_LEVEL: + * + * reference level of track and album gain values (double) + */ +#define GST_TAG_REFERENCE_LEVEL "replaygain-reference-level" +/** + * GST_TAG_LANGUAGE_CODE: + * + * ISO-639-2 or ISO-639-1 code for the language the content is in (string) + * + * There is utility API in libgsttag in gst-plugins-base to obtain a translated + * language name from the language code: gst_tag_get_language_name() + */ +#define GST_TAG_LANGUAGE_CODE "language-code" +/** + * GST_TAG_LANGUAGE_NAME: + * + * Name of the language the content is in (string) + * + * Free-form name of the language the content is in, if a language code + * is not available. This tag should not be set in addition to a language + * code. It is undefined what language or locale the language name is in. + */ +#define GST_TAG_LANGUAGE_NAME "language-name" +/** + * GST_TAG_IMAGE: + * + * image (sample) (sample taglist should specify the content type and preferably + * also set "image-type" field as #GstTagImageType) + */ +#define GST_TAG_IMAGE "image" +/** + * GST_TAG_PREVIEW_IMAGE: + * + * image that is meant for preview purposes, e.g. small icon-sized version + * (sample) (sample taglist should specify the content type) + */ +#define GST_TAG_PREVIEW_IMAGE "preview-image" + +/** + * GST_TAG_ATTACHMENT: + * + * generic file attachment (sample) (sample taglist should specify the content + * type and if possible set "filename" to the file name of the + * attachment) + */ +#define GST_TAG_ATTACHMENT "attachment" + +/** + * GST_TAG_BEATS_PER_MINUTE: + * + * number of beats per minute in audio (double) + */ +#define GST_TAG_BEATS_PER_MINUTE "beats-per-minute" + +/** + * GST_TAG_KEYWORDS: + * + * comma separated keywords describing the content (string). + */ +#define GST_TAG_KEYWORDS "keywords" + +/** + * GST_TAG_GEO_LOCATION_NAME: + * + * human readable descriptive location of where the media has been recorded or + * produced. (string). + */ +#define GST_TAG_GEO_LOCATION_NAME "geo-location-name" + +/** + * GST_TAG_GEO_LOCATION_LATITUDE: + * + * geo latitude location of where the media has been recorded or produced in + * degrees according to WGS84 (zero at the equator, negative values for southern + * latitudes) (double). + */ +#define GST_TAG_GEO_LOCATION_LATITUDE "geo-location-latitude" + +/** + * GST_TAG_GEO_LOCATION_LONGITUDE: + * + * geo longitude location of where the media has been recorded or produced in + * degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, + * negative values for western longitudes). (double). + */ +#define GST_TAG_GEO_LOCATION_LONGITUDE "geo-location-longitude" + +/** + * GST_TAG_GEO_LOCATION_ELEVATION: + * + * geo elevation of where the media has been recorded or produced in meters + * according to WGS84 (zero is average sea level) (double). + */ +#define GST_TAG_GEO_LOCATION_ELEVATION "geo-location-elevation" +/** + * GST_TAG_GEO_LOCATION_COUNTRY: + * + * The country (english name) where the media has been produced (string). + */ +#define GST_TAG_GEO_LOCATION_COUNTRY "geo-location-country" +/** + * GST_TAG_GEO_LOCATION_CITY: + * + * The city (english name) where the media has been produced (string). + */ +#define GST_TAG_GEO_LOCATION_CITY "geo-location-city" +/** + * GST_TAG_GEO_LOCATION_SUBLOCATION: + * + * A location 'smaller' than GST_TAG_GEO_LOCATION_CITY that specifies better + * where the media has been produced. (e.g. the neighborhood) (string). + * + * This tag has been added as this is how it is handled/named in XMP's + * Iptc4xmpcore schema. + */ +#define GST_TAG_GEO_LOCATION_SUBLOCATION "geo-location-sublocation" +/** + * GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR: + * + * Represents the expected error on the horizontal positioning in + * meters (double). + */ +#define GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR "geo-location-horizontal-error" +/** + * GST_TAG_GEO_LOCATION_MOVEMENT_SPEED: + * + * Speed of the capturing device when performing the capture. + * Represented in m/s. (double) + * + * See also #GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION + */ +#define GST_TAG_GEO_LOCATION_MOVEMENT_SPEED "geo-location-movement-speed" +/** + * GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION: + * + * Indicates the movement direction of the device performing the capture + * of a media. It is represented as degrees in floating point representation, + * 0 means the geographic north, and increases clockwise (double from 0 to 360) + * + * See also #GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION + */ +#define GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION "geo-location-movement-direction" +/** + * GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION: + * + * Indicates the direction the device is pointing to when capturing + * a media. It is represented as degrees in floating point representation, + * 0 means the geographic north, and increases clockwise (double from 0 to 360) + * + * See also #GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION + */ +#define GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION "geo-location-capture-direction" +/** + * GST_TAG_SHOW_NAME: + * + * Name of the show, used for displaying (string) + */ +#define GST_TAG_SHOW_NAME "show-name" +/** + * GST_TAG_SHOW_SORTNAME: + * + * Name of the show, used for sorting (string) + */ +#define GST_TAG_SHOW_SORTNAME "show-sortname" +/** + * GST_TAG_SHOW_EPISODE_NUMBER: + * + * Number of the episode within a season/show (unsigned integer) + */ +#define GST_TAG_SHOW_EPISODE_NUMBER "show-episode-number" +/** + * GST_TAG_SHOW_SEASON_NUMBER: + * + * Number of the season of a show/series (unsigned integer) + */ +#define GST_TAG_SHOW_SEASON_NUMBER "show-season-number" +/** + * GST_TAG_LYRICS: + * + * The lyrics of the media (string) + */ +#define GST_TAG_LYRICS "lyrics" +/** + * GST_TAG_COMPOSER_SORTNAME: + * + * The composer's name, used for sorting (string) + */ +#define GST_TAG_COMPOSER_SORTNAME "composer-sortname" +/** + * GST_TAG_GROUPING: + * + * Groups together media that are related and spans multiple tracks. An + * example are multiple pieces of a concerto. (string) + */ +#define GST_TAG_GROUPING "grouping" +/** + * GST_TAG_USER_RATING: + * + * Rating attributed by a person (likely the application user). + * The higher the value, the more the user likes this media + * (unsigned int from 0 to 100) + */ +#define GST_TAG_USER_RATING "user-rating" +/** + * GST_TAG_DEVICE_MANUFACTURER: + * + * Manufacturer of the device used to create the media (string) + */ +#define GST_TAG_DEVICE_MANUFACTURER "device-manufacturer" +/** + * GST_TAG_DEVICE_MODEL: + * + * Model of the device used to create the media (string) + */ +#define GST_TAG_DEVICE_MODEL "device-model" +/** + * GST_TAG_APPLICATION_NAME: + * + * Name of the application used to create the media (string) + */ +#define GST_TAG_APPLICATION_NAME "application-name" +/** + * GST_TAG_APPLICATION_DATA: + * + * Arbitrary application data (sample) + * + * Some formats allow applications to add their own arbitrary data + * into files. This data is application dependent. + */ +#define GST_TAG_APPLICATION_DATA "application-data" +/** + * GST_TAG_IMAGE_ORIENTATION: + * + * Represents the 'Orientation' tag from EXIF. Defines how the image + * should be rotated and mirrored for display. (string) + * + * This tag has a predefined set of allowed values: + * "rotate-0" + * "rotate-90" + * "rotate-180" + * "rotate-270" + * "flip-rotate-0" + * "flip-rotate-90" + * "flip-rotate-180" + * "flip-rotate-270" + * + * The naming is adopted according to a possible transformation to perform + * on the image to fix its orientation, obviously equivalent operations will + * yield the same result. + * + * Rotations indicated by the values are in clockwise direction and + * 'flip' means an horizontal mirroring. + */ +#define GST_TAG_IMAGE_ORIENTATION "image-orientation" +/** + * GST_TAG_PUBLISHER: + * + * Name of the label or publisher (string) + * + * Since: 1.2 + */ +#define GST_TAG_PUBLISHER "publisher" +/** + * GST_TAG_INTERPRETED_BY: + * + * Information about the people behind a remix and similar + * interpretations of another existing piece (string) + * + * Since: 1.2 + */ +#define GST_TAG_INTERPRETED_BY "interpreted-by" +/** + * GST_TAG_MIDI_BASE_NOTE: + * + * Midi note number + * of the audio track. This is useful for sample instruments and in particular + * for multi-samples. + * + * Since: 1.4 + */ +#define GST_TAG_MIDI_BASE_NOTE "midi-base-note" +/** + * GST_TAG_PRIVATE_DATA: + * + * Any private data that may be contained in tags (sample). + * + * It is represented by #GstSample in which #GstBuffer contains the + * binary data and the sample's info #GstStructure may contain any + * extra information that identifies the origin or meaning of the data. + * + * Private frames in ID3v2 tags ('PRIV' frames) will be represented + * using this tag, in which case the GstStructure will be named + * "ID3PrivateFrame" and contain a field named "owner" of type string + * which contains the owner-identification string from the tag. + * + * Since: 1.8 + */ +#define GST_TAG_PRIVATE_DATA "private-data" + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTagList, gst_tag_list_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TAGLIST_H__ */ diff --git a/gst/gsttagsetter.c b/gst/gsttagsetter.c new file mode 100644 index 0000000..ea54c35 --- /dev/null +++ b/gst/gsttagsetter.c @@ -0,0 +1,403 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttagsetter.c: interface for tag setting on 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttagsetter + * @title: GstTagsetter + * @short_description: Element interface that allows setting and retrieval + * of media metadata + * + * Element interface that allows setting of media metadata. + * + * Elements that support changing a stream's metadata will implement this + * interface. Examples of such elements are 'vorbisenc', 'theoraenc' and + * 'id3v2mux'. + * + * If you just want to retrieve metadata in your application then all you + * need to do is watch for tag messages on your pipeline's bus. This + * interface is only for setting metadata, not for extracting it. To set tags + * from the application, find tagsetter elements and set tags using e.g. + * gst_tag_setter_merge_tags() or gst_tag_setter_add_tags(). Also consider + * setting the #GstTagMergeMode that is used for tag events that arrive at the + * tagsetter element (default mode is to keep existing tags). + * The application should do that before the element goes to %GST_STATE_PAUSED. + * + * Elements implementing the #GstTagSetter interface often have to merge + * any tags received from upstream and the tags set by the application via + * the interface. This can be done like this: + * + * |[ + * GstTagMergeMode merge_mode; + * const GstTagList *application_tags; + * const GstTagList *event_tags; + * GstTagSetter *tagsetter; + * GstTagList *result; + * + * tagsetter = GST_TAG_SETTER (element); + * + * merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter); + * application_tags = gst_tag_setter_get_tag_list (tagsetter); + * event_tags = (const GstTagList *) element->event_tags; + * + * GST_LOG_OBJECT (tagsetter, "merging tags, merge mode = %d", merge_mode); + * GST_LOG_OBJECT (tagsetter, "event tags: %" GST_PTR_FORMAT, event_tags); + * GST_LOG_OBJECT (tagsetter, "set tags: %" GST_PTR_FORMAT, application_tags); + * + * result = gst_tag_list_merge (application_tags, event_tags, merge_mode); + * + * GST_LOG_OBJECT (tagsetter, "final tags: %" GST_PTR_FORMAT, result); + * ]| + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" +#include "gsttagsetter.h" +#include +#include + +static GQuark gst_tag_key; + +typedef struct +{ + GstTagMergeMode mode; + GstTagList *list; + GMutex lock; +} GstTagData; + +#define GST_TAG_DATA_LOCK(data) g_mutex_lock(&data->lock) +#define GST_TAG_DATA_UNLOCK(data) g_mutex_unlock(&data->lock) + +G_DEFINE_INTERFACE_WITH_CODE (GstTagSetter, gst_tag_setter, GST_TYPE_ELEMENT, + gst_tag_key = g_quark_from_static_string ("gst-tag-setter-data"); + ); + +static void +gst_tag_setter_default_init (GstTagSetterInterface * klass) +{ + /* nothing to do here, it's a dummy interface */ +} + +static void +gst_tag_data_free (gpointer p) +{ + GstTagData *data = (GstTagData *) p; + + if (data->list) + gst_tag_list_unref (data->list); + + g_mutex_clear (&data->lock); + + g_slice_free (GstTagData, data); +} + +static GstTagData * +gst_tag_setter_get_data (GstTagSetter * setter) +{ + GstTagData *data; + + data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key); + if (!data) { + /* make sure no other thread is creating a GstTagData at the same time */ + static GMutex create_mutex; /* no initialisation required */ + + g_mutex_lock (&create_mutex); + + data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key); + if (!data) { + data = g_slice_new (GstTagData); + g_mutex_init (&data->lock); + data->list = NULL; + data->mode = GST_TAG_MERGE_KEEP; + g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data, + gst_tag_data_free); + } + + g_mutex_unlock (&create_mutex); + } + + return data; +} + +/** + * gst_tag_setter_reset_tags: + * @setter: a #GstTagSetter + * + * Reset the internal taglist. Elements should call this from within the + * state-change handler. + */ +void +gst_tag_setter_reset_tags (GstTagSetter * setter) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + if (data->list) { + gst_tag_list_unref (data->list); + data->list = NULL; + } + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_merge_tags: + * @setter: a #GstTagSetter + * @list: a tag list to merge from + * @mode: the mode to merge with + * + * Merges the given list into the setter's list using the given mode. + */ +void +gst_tag_setter_merge_tags (GstTagSetter * setter, const GstTagList * list, + GstTagMergeMode mode) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + g_return_if_fail (GST_IS_TAG_LIST (list)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + if (data->list == NULL) { + if (mode != GST_TAG_MERGE_KEEP_ALL) + data->list = gst_tag_list_copy (list); + } else { + gst_tag_list_insert (data->list, list, mode); + } + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_add_tags: + * @setter: a #GstTagSetter + * @mode: the mode to use + * @tag: tag to set + * @...: more tag / value pairs to set + * + * Adds the given tag / value pairs on the setter using the given merge mode. + * The list must be terminated with %NULL. + */ +void +gst_tag_setter_add_tags (GstTagSetter * setter, GstTagMergeMode mode, + const gchar * tag, ...) +{ + va_list args; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + va_start (args, tag); + gst_tag_setter_add_tag_valist (setter, mode, tag, args); + va_end (args); +} + +/** + * gst_tag_setter_add_tag_values: + * @setter: a #GstTagSetter + * @mode: the mode to use + * @tag: tag to set + * @...: more tag / GValue pairs to set + * + * Adds the given tag / GValue pairs on the setter using the given merge mode. + * The list must be terminated with %NULL. + */ +void +gst_tag_setter_add_tag_values (GstTagSetter * setter, GstTagMergeMode mode, + const gchar * tag, ...) +{ + va_list args; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + va_start (args, tag); + gst_tag_setter_add_tag_valist_values (setter, mode, tag, args); + va_end (args); +} + +/** + * gst_tag_setter_add_tag_valist: + * @setter: a #GstTagSetter + * @mode: the mode to use + * @tag: tag to set + * @var_args: tag / value pairs to set + * + * Adds the given tag / value pairs on the setter using the given merge mode. + * The list must be terminated with %NULL. + */ +void +gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode, + const gchar * tag, va_list var_args) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + if (!data->list) + data->list = gst_tag_list_new_empty (); + + gst_tag_list_add_valist (data->list, mode, tag, var_args); + + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_add_tag_valist_values: + * @setter: a #GstTagSetter + * @mode: the mode to use + * @tag: tag to set + * @var_args: tag / GValue pairs to set + * + * Adds the given tag / GValue pairs on the setter using the given merge mode. + * The list must be terminated with %NULL. + */ +void +gst_tag_setter_add_tag_valist_values (GstTagSetter * setter, + GstTagMergeMode mode, const gchar * tag, va_list var_args) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + + if (!data->list) + data->list = gst_tag_list_new_empty (); + + gst_tag_list_add_valist_values (data->list, mode, tag, var_args); + + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_add_tag_value: + * @setter: a #GstTagSetter + * @mode: the mode to use + * @tag: tag to set + * @value: GValue to set for the tag + * + * Adds the given tag / GValue pair on the setter using the given merge mode. + */ +void +gst_tag_setter_add_tag_value (GstTagSetter * setter, + GstTagMergeMode mode, const gchar * tag, const GValue * value) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + + if (!data->list) + data->list = gst_tag_list_new_empty (); + + gst_tag_list_add_value (data->list, mode, tag, value); + + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_get_tag_list: + * @setter: a #GstTagSetter + * + * Returns the current list of tags the setter uses. The list should not be + * modified or freed. + * + * This function is not thread-safe. + * + * Returns: (transfer none) (nullable): a current snapshot of the + * taglist used in the setter or %NULL if none is used. + */ +const GstTagList * +gst_tag_setter_get_tag_list (GstTagSetter * setter) +{ + g_return_val_if_fail (GST_IS_TAG_SETTER (setter), NULL); + + return gst_tag_setter_get_data (setter)->list; +} + +/** + * gst_tag_setter_set_tag_merge_mode: + * @setter: a #GstTagSetter + * @mode: The mode with which tags are added + * + * Sets the given merge mode that is used for adding tags from events to tags + * specified by this interface. The default is #GST_TAG_MERGE_KEEP, which keeps + * the tags set with this interface and discards tags from events. + */ +void +gst_tag_setter_set_tag_merge_mode (GstTagSetter * setter, GstTagMergeMode mode) +{ + GstTagData *data; + + g_return_if_fail (GST_IS_TAG_SETTER (setter)); + g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + data->mode = mode; + GST_TAG_DATA_UNLOCK (data); +} + +/** + * gst_tag_setter_get_tag_merge_mode: + * @setter: a #GstTagSetter + * + * Queries the mode by which tags inside the setter are overwritten by tags + * from events + * + * Returns: the merge mode used inside the element. + */ +GstTagMergeMode +gst_tag_setter_get_tag_merge_mode (GstTagSetter * setter) +{ + GstTagMergeMode mode; + GstTagData *data; + + g_return_val_if_fail (GST_IS_TAG_SETTER (setter), GST_TAG_MERGE_UNDEFINED); + + data = gst_tag_setter_get_data (setter); + + GST_TAG_DATA_LOCK (data); + mode = data->mode; + GST_TAG_DATA_UNLOCK (data); + + return mode; +} diff --git a/gst/gsttagsetter.h b/gst/gsttagsetter.h new file mode 100644 index 0000000..8d5d237 --- /dev/null +++ b/gst/gsttagsetter.h @@ -0,0 +1,106 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttagsetter.h: Interfaces for tagging + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TAG_SETTER_H__ +#define __GST_TAG_SETTER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TAG_SETTER (gst_tag_setter_get_type ()) +#define GST_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter)) +#define GST_IS_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_SETTER)) +#define GST_TAG_SETTER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TAG_SETTER, GstTagSetterInterface)) + +/** + * GstTagSetter: + * + * Opaque #GstTagSetter data structure. + */ +typedef struct _GstTagSetter GstTagSetter; /* Dummy typedef */ +typedef struct _GstTagSetterInterface GstTagSetterInterface; + +/** + * GstTagSetterInterface: + * @g_iface: parent interface type. + * + * #GstTagSetterInterface interface. + */ +/* use an empty interface here to allow detection of elements using user-set + tags */ +struct _GstTagSetterInterface +{ + GTypeInterface g_iface; + + /* signals */ + + /* virtual table */ +}; + +GST_API +GType gst_tag_setter_get_type (void); + +GST_API +void gst_tag_setter_reset_tags (GstTagSetter * setter); + +GST_API +void gst_tag_setter_merge_tags (GstTagSetter * setter, + const GstTagList * list, + GstTagMergeMode mode); +GST_API +void gst_tag_setter_add_tags (GstTagSetter * setter, + GstTagMergeMode mode, + const gchar * tag, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_tag_setter_add_tag_values (GstTagSetter * setter, + GstTagMergeMode mode, + const gchar * tag, + ...) G_GNUC_NULL_TERMINATED; +GST_API +void gst_tag_setter_add_tag_valist (GstTagSetter * setter, + GstTagMergeMode mode, + const gchar * tag, + va_list var_args); +GST_API +void gst_tag_setter_add_tag_valist_values(GstTagSetter * setter, + GstTagMergeMode mode, + const gchar * tag, + va_list var_args); +GST_API +void gst_tag_setter_add_tag_value (GstTagSetter * setter, + GstTagMergeMode mode, + const gchar * tag, + const GValue * value); +GST_API +const GstTagList * + gst_tag_setter_get_tag_list (GstTagSetter * setter); + +GST_API +void gst_tag_setter_set_tag_merge_mode (GstTagSetter * setter, + GstTagMergeMode mode); +GST_API +GstTagMergeMode gst_tag_setter_get_tag_merge_mode (GstTagSetter * setter); + +G_END_DECLS + +#endif /* __GST_TAG_SETTER_H__ */ diff --git a/gst/gsttask.c b/gst/gsttask.c new file mode 100644 index 0000000..30959f8 --- /dev/null +++ b/gst/gsttask.c @@ -0,0 +1,860 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gsttask.c: Streaming tasks + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttask + * @title: GstTask + * @short_description: Abstraction of GStreamer streaming threads. + * @see_also: #GstElement, #GstPad + * + * #GstTask is used by #GstElement and #GstPad to provide the data passing + * threads in a #GstPipeline. + * + * A #GstPad will typically start a #GstTask to push or pull data to/from the + * peer pads. Most source elements start a #GstTask to push data. In some cases + * a demuxer element can start a #GstTask to pull data from a peer element. This + * is typically done when the demuxer can perform random access on the upstream + * peer element for improved performance. + * + * Although convenience functions exist on #GstPad to start/pause/stop tasks, it + * might sometimes be needed to create a #GstTask manually if it is not related to + * a #GstPad. + * + * Before the #GstTask can be run, it needs a #GRecMutex that can be set with + * gst_task_set_lock(). + * + * The task can be started, paused and stopped with gst_task_start(), gst_task_pause() + * and gst_task_stop() respectively or with the gst_task_set_state() function. + * + * A #GstTask will repeatedly call the #GstTaskFunction with the user data + * that was provided when creating the task with gst_task_new(). While calling + * the function it will acquire the provided lock. The provided lock is released + * when the task pauses or stops. + * + * Stopping a task with gst_task_stop() will not immediately make sure the task is + * not running anymore. Use gst_task_join() to make sure the task is completely + * stopped and the thread is stopped. + * + * After creating a #GstTask, use gst_object_unref() to free its resources. This can + * only be done when the task is not running anymore. + * + * Task functions can send a #GstMessage to send out-of-band data to the + * application. The application can receive messages from the #GstBus in its + * mainloop. + * + * For debugging purposes, the task will configure its object name as the thread + * name on Linux. Please note that the object name should be configured before the + * task is started; changing the object name after the task has been started, has + * no effect on the thread name. + */ + +#include "gst_private.h" + +#include "gstinfo.h" +#include "gsttask.h" +#include "glib-compat-private.h" + +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + +#ifdef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID +#include +#endif + +GST_DEBUG_CATEGORY_STATIC (task_debug); +#define GST_CAT_DEFAULT (task_debug) + +#define SET_TASK_STATE(t,s) (g_atomic_int_set (&GST_TASK_STATE(t), (s))) +#define GET_TASK_STATE(t) ((GstTaskState) g_atomic_int_get (&GST_TASK_STATE(t))) + +#define GST_TASK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_TASK, GstTaskPrivate)) + +struct _GstTaskPrivate +{ + /* callbacks for managing the thread of this task */ + GstTaskThreadFunc enter_func; + gpointer enter_user_data; + GDestroyNotify enter_notify; + + GstTaskThreadFunc leave_func; + gpointer leave_user_data; + GDestroyNotify leave_notify; + + /* configured pool */ + GstTaskPool *pool; + + /* remember the pool and id that is currently running. */ + gpointer id; + GstTaskPool *pool_id; +}; + +#ifdef _MSC_VER +#define WIN32_LEAN_AND_MEAN +#include + +struct _THREADNAME_INFO +{ + DWORD dwType; // must be 0x1000 + LPCSTR szName; // pointer to name (in user addr space) + DWORD dwThreadID; // thread ID (-1=caller thread) + DWORD dwFlags; // reserved for future use, must be zero +}; +typedef struct _THREADNAME_INFO THREADNAME_INFO; + +void +SetThreadName (DWORD dwThreadID, LPCSTR szThreadName) +{ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try { + RaiseException (0x406D1388, 0, sizeof (info) / sizeof (DWORD), + (const ULONG_PTR *) &info); + } + __except (EXCEPTION_CONTINUE_EXECUTION) { + } +} +#endif + +static void gst_task_finalize (GObject * object); + +static void gst_task_func (GstTask * task); + +static GMutex pool_lock; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (task_debug, "task", 0, "Processing tasks"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstTask, gst_task, GST_TYPE_OBJECT, _do_init); + +static void +init_klass_pool (GstTaskClass * klass) +{ + g_mutex_lock (&pool_lock); + if (klass->pool) { + gst_task_pool_cleanup (klass->pool); + gst_object_unref (klass->pool); + } + klass->pool = gst_task_pool_new (); + /* Classes are never destroyed so this ref will never be dropped */ + GST_OBJECT_FLAG_SET (klass->pool, GST_OBJECT_FLAG_MAY_BE_LEAKED); + gst_task_pool_prepare (klass->pool, NULL); + g_mutex_unlock (&pool_lock); +} + +static void +gst_task_class_init (GstTaskClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstTaskPrivate)); + + gobject_class->finalize = gst_task_finalize; + + init_klass_pool (klass); +} + +static void +gst_task_init (GstTask * task) +{ + GstTaskClass *klass; + + klass = GST_TASK_GET_CLASS (task); + + task->priv = GST_TASK_GET_PRIVATE (task); + task->running = FALSE; + task->thread = NULL; + task->lock = NULL; + g_cond_init (&task->cond); + SET_TASK_STATE (task, GST_TASK_STOPPED); + + /* use the default klass pool for this task, users can + * override this later */ + g_mutex_lock (&pool_lock); + task->priv->pool = gst_object_ref (klass->pool); + g_mutex_unlock (&pool_lock); +} + +static void +gst_task_finalize (GObject * object) +{ + GstTask *task = GST_TASK (object); + GstTaskPrivate *priv = task->priv; + + GST_DEBUG ("task %p finalize", task); + + if (priv->enter_notify) + priv->enter_notify (priv->enter_user_data); + + if (priv->leave_notify) + priv->leave_notify (priv->leave_user_data); + + if (task->notify) + task->notify (task->user_data); + + gst_object_unref (priv->pool); + + /* task thread cannot be running here since it holds a ref + * to the task so that the finalize could not have happened */ + g_cond_clear (&task->cond); + + G_OBJECT_CLASS (gst_task_parent_class)->finalize (object); +} + +/* should be called with the object LOCK */ +static void +gst_task_configure_name (GstTask * task) +{ +#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_NAME) + const gchar *name; + gchar thread_name[17] = { 0, }; + + GST_OBJECT_LOCK (task); + name = GST_OBJECT_NAME (task); + + /* set the thread name to something easily identifiable */ + if (!snprintf (thread_name, 17, "%s", GST_STR_NULL (name))) { + GST_DEBUG_OBJECT (task, "Could not create thread name for '%s'", name); + } else { + GST_DEBUG_OBJECT (task, "Setting thread name to '%s'", thread_name); + if (prctl (PR_SET_NAME, (unsigned long int) thread_name, 0, 0, 0)) + GST_DEBUG_OBJECT (task, "Failed to set thread name"); + } + GST_OBJECT_UNLOCK (task); +#elif defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID) + const gchar *name; + + GST_OBJECT_LOCK (task); + name = GST_OBJECT_NAME (task); + + /* set the thread name to something easily identifiable */ + GST_DEBUG_OBJECT (task, "Setting thread name to '%s'", name); + if (pthread_setname_np (name)) + GST_DEBUG_OBJECT (task, "Failed to set thread name"); + + GST_OBJECT_UNLOCK (task); +#elif defined (_MSC_VER) + const gchar *name; + name = GST_OBJECT_NAME (task); + + /* set the thread name to something easily identifiable */ + GST_DEBUG_OBJECT (task, "Setting thread name to '%s'", name); + SetThreadName (-1, name); +#endif +} + +static void +gst_task_func (GstTask * task) +{ + GRecMutex *lock; + GThread *tself; + GstTaskPrivate *priv; + + priv = task->priv; + + tself = g_thread_self (); + + GST_DEBUG ("Entering task %p, thread %p", task, tself); + + /* we have to grab the lock to get the mutex. We also + * mark our state running so that nobody can mess with + * the mutex. */ + GST_OBJECT_LOCK (task); + if (GET_TASK_STATE (task) == GST_TASK_STOPPED) + goto exit; + lock = GST_TASK_GET_LOCK (task); + if (G_UNLIKELY (lock == NULL)) + goto no_lock; + task->thread = tself; + GST_OBJECT_UNLOCK (task); + + /* fire the enter_func callback when we need to */ + if (priv->enter_func) + priv->enter_func (task, tself, priv->enter_user_data); + + /* locking order is TASK_LOCK, LOCK */ + g_rec_mutex_lock (lock); + /* configure the thread name now */ + gst_task_configure_name (task); + + while (G_LIKELY (GET_TASK_STATE (task) != GST_TASK_STOPPED)) { + GST_OBJECT_LOCK (task); + while (G_UNLIKELY (GST_TASK_STATE (task) == GST_TASK_PAUSED)) { + g_rec_mutex_unlock (lock); + + GST_TASK_SIGNAL (task); + GST_INFO_OBJECT (task, "Task going to paused"); + GST_TASK_WAIT (task); + GST_INFO_OBJECT (task, "Task resume from paused"); + GST_OBJECT_UNLOCK (task); + /* locking order.. */ + g_rec_mutex_lock (lock); + GST_OBJECT_LOCK (task); + } + + if (G_UNLIKELY (GET_TASK_STATE (task) == GST_TASK_STOPPED)) { + GST_OBJECT_UNLOCK (task); + break; + } else { + GST_OBJECT_UNLOCK (task); + } + + task->func (task->user_data); + } + + g_rec_mutex_unlock (lock); + + GST_OBJECT_LOCK (task); + task->thread = NULL; + +exit: + if (priv->leave_func) { + /* fire the leave_func callback when we need to. We need to do this before + * we signal the task and with the task lock released. */ + GST_OBJECT_UNLOCK (task); + priv->leave_func (task, tself, priv->leave_user_data); + GST_OBJECT_LOCK (task); + } + /* now we allow messing with the lock again by setting the running flag to + * %FALSE. Together with the SIGNAL this is the sign for the _join() to + * complete. + * Note that we still have not dropped the final ref on the task. We could + * check here if there is a pending join() going on and drop the last ref + * before releasing the lock as we can be sure that a ref is held by the + * caller of the join(). */ + task->running = FALSE; + GST_TASK_SIGNAL (task); + GST_OBJECT_UNLOCK (task); + + GST_DEBUG ("Exit task %p, thread %p", task, g_thread_self ()); + + gst_object_unref (task); + return; + +no_lock: + { + g_warning ("starting task without a lock"); + goto exit; + } +} + +/** + * gst_task_cleanup_all: + * + * Wait for all tasks to be stopped. This is mainly used internally + * to ensure proper cleanup of internal data structures in test suites. + * + * MT safe. + */ +void +gst_task_cleanup_all (void) +{ + GstTaskClass *klass; + + if ((klass = g_type_class_peek (GST_TYPE_TASK))) { + init_klass_pool (klass); + } + + /* GstElement owns a GThreadPool */ + _priv_gst_element_cleanup (); +} + +/** + * gst_task_new: + * @func: The #GstTaskFunction to use + * @user_data: User data to pass to @func + * @notify: the function to call when @user_data is no longer needed. + * + * Create a new Task that will repeatedly call the provided @func + * with @user_data as a parameter. Typically the task will run in + * a new thread. + * + * The function cannot be changed after the task has been created. You + * must create a new #GstTask to change the function. + * + * This function will not yet create and start a thread. Use gst_task_start() or + * gst_task_pause() to create and start the GThread. + * + * Before the task can be used, a #GRecMutex must be configured using the + * gst_task_set_lock() function. This lock will always be acquired while + * @func is called. + * + * Returns: (transfer full): A new #GstTask. + * + * MT safe. + */ +GstTask * +gst_task_new (GstTaskFunction func, gpointer user_data, GDestroyNotify notify) +{ + GstTask *task; + + g_return_val_if_fail (func != NULL, NULL); + + task = g_object_new (GST_TYPE_TASK, NULL); + task->func = func; + task->user_data = user_data; + task->notify = notify; + + GST_DEBUG ("Created task %p", task); + + /* clear floating flag */ + gst_object_ref_sink (task); + + return task; +} + +/** + * gst_task_set_lock: + * @task: The #GstTask to use + * @mutex: The #GRecMutex to use + * + * Set the mutex used by the task. The mutex will be acquired before + * calling the #GstTaskFunction. + * + * This function has to be called before calling gst_task_pause() or + * gst_task_start(). + * + * MT safe. + */ +void +gst_task_set_lock (GstTask * task, GRecMutex * mutex) +{ + g_return_if_fail (GST_IS_TASK (task)); + + GST_OBJECT_LOCK (task); + if (G_UNLIKELY (task->running)) + goto is_running; + GST_INFO ("setting stream lock %p on task %p", mutex, task); + GST_TASK_GET_LOCK (task) = mutex; + GST_OBJECT_UNLOCK (task); + + return; + + /* ERRORS */ +is_running: + { + GST_OBJECT_UNLOCK (task); + g_warning ("cannot call set_lock on a running task"); + } +} + +/** + * gst_task_get_pool: + * @task: a #GstTask + * + * Get the #GstTaskPool that this task will use for its streaming + * threads. + * + * MT safe. + * + * Returns: (transfer full): the #GstTaskPool used by @task. gst_object_unref() + * after usage. + */ +GstTaskPool * +gst_task_get_pool (GstTask * task) +{ + GstTaskPool *result; + GstTaskPrivate *priv; + + g_return_val_if_fail (GST_IS_TASK (task), NULL); + + priv = task->priv; + + GST_OBJECT_LOCK (task); + result = gst_object_ref (priv->pool); + GST_OBJECT_UNLOCK (task); + + return result; +} + +/** + * gst_task_set_pool: + * @task: a #GstTask + * @pool: (transfer none): a #GstTaskPool + * + * Set @pool as the new GstTaskPool for @task. Any new streaming threads that + * will be created by @task will now use @pool. + * + * MT safe. + */ +void +gst_task_set_pool (GstTask * task, GstTaskPool * pool) +{ + GstTaskPool *old; + GstTaskPrivate *priv; + + g_return_if_fail (GST_IS_TASK (task)); + g_return_if_fail (GST_IS_TASK_POOL (pool)); + + priv = task->priv; + + GST_OBJECT_LOCK (task); + if (priv->pool != pool) { + old = priv->pool; + priv->pool = gst_object_ref (pool); + } else + old = NULL; + GST_OBJECT_UNLOCK (task); + + if (old) + gst_object_unref (old); +} + +/** + * gst_task_set_enter_callback: + * @task: The #GstTask to use + * @enter_func: (in): a #GstTaskThreadFunc + * @user_data: user data passed to @enter_func + * @notify: called when @user_data is no longer referenced + * + * Call @enter_func when the task function of @task is entered. @user_data will + * be passed to @enter_func and @notify will be called when @user_data is no + * longer referenced. + */ +void +gst_task_set_enter_callback (GstTask * task, GstTaskThreadFunc enter_func, + gpointer user_data, GDestroyNotify notify) +{ + GDestroyNotify old_notify; + + g_return_if_fail (task != NULL); + g_return_if_fail (GST_IS_TASK (task)); + + GST_OBJECT_LOCK (task); + if ((old_notify = task->priv->enter_notify)) { + gpointer old_data = task->priv->enter_user_data; + + task->priv->enter_user_data = NULL; + task->priv->enter_notify = NULL; + GST_OBJECT_UNLOCK (task); + + old_notify (old_data); + + GST_OBJECT_LOCK (task); + } + task->priv->enter_func = enter_func; + task->priv->enter_user_data = user_data; + task->priv->enter_notify = notify; + GST_OBJECT_UNLOCK (task); +} + +/** + * gst_task_set_leave_callback: + * @task: The #GstTask to use + * @leave_func: (in): a #GstTaskThreadFunc + * @user_data: user data passed to @leave_func + * @notify: called when @user_data is no longer referenced + * + * Call @leave_func when the task function of @task is left. @user_data will + * be passed to @leave_func and @notify will be called when @user_data is no + * longer referenced. + */ +void +gst_task_set_leave_callback (GstTask * task, GstTaskThreadFunc leave_func, + gpointer user_data, GDestroyNotify notify) +{ + GDestroyNotify old_notify; + + g_return_if_fail (task != NULL); + g_return_if_fail (GST_IS_TASK (task)); + + GST_OBJECT_LOCK (task); + if ((old_notify = task->priv->leave_notify)) { + gpointer old_data = task->priv->leave_user_data; + + task->priv->leave_user_data = NULL; + task->priv->leave_notify = NULL; + GST_OBJECT_UNLOCK (task); + + old_notify (old_data); + + GST_OBJECT_LOCK (task); + } + task->priv->leave_func = leave_func; + task->priv->leave_user_data = user_data; + task->priv->leave_notify = notify; + GST_OBJECT_UNLOCK (task); +} + +/** + * gst_task_get_state: + * @task: The #GstTask to query + * + * Get the current state of the task. + * + * Returns: The #GstTaskState of the task + * + * MT safe. + */ +GstTaskState +gst_task_get_state (GstTask * task) +{ + GstTaskState result; + + g_return_val_if_fail (GST_IS_TASK (task), GST_TASK_STOPPED); + + result = GET_TASK_STATE (task); + + return result; +} + +/* make sure the task is running and start a thread if it's not. + * This function must be called with the task LOCK. */ +static gboolean +start_task (GstTask * task) +{ + gboolean res = TRUE; + GError *error = NULL; + GstTaskPrivate *priv; + + priv = task->priv; + + /* new task, We ref before so that it remains alive while + * the thread is running. */ + gst_object_ref (task); + /* mark task as running so that a join will wait until we schedule + * and exit the task function. */ + task->running = TRUE; + + /* push on the thread pool, we remember the original pool because the user + * could change it later on and then we join to the wrong pool. */ + priv->pool_id = gst_object_ref (priv->pool); + priv->id = + gst_task_pool_push (priv->pool_id, (GstTaskPoolFunction) gst_task_func, + task, &error); + + if (error != NULL) { + g_warning ("failed to create thread: %s", error->message); + g_error_free (error); + res = FALSE; + } + return res; +} + + +/** + * gst_task_set_state: + * @task: a #GstTask + * @state: the new task state + * + * Sets the state of @task to @state. + * + * The @task must have a lock associated with it using + * gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or + * this function will return %FALSE. + * + * MT safe. + * + * Returns: %TRUE if the state could be changed. + */ +gboolean +gst_task_set_state (GstTask * task, GstTaskState state) +{ + GstTaskState old; + gboolean res = TRUE; + + g_return_val_if_fail (GST_IS_TASK (task), FALSE); + + GST_DEBUG_OBJECT (task, "Changing task %p to state %d", task, state); + + GST_OBJECT_LOCK (task); + if (state != GST_TASK_STOPPED) + if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL)) + goto no_lock; + + /* if the state changed, do our thing */ + old = GET_TASK_STATE (task); + if (old != state) { + SET_TASK_STATE (task, state); + switch (old) { + case GST_TASK_STOPPED: + /* If the task already has a thread scheduled we don't have to do + * anything. */ + if (G_UNLIKELY (!task->running)) + res = start_task (task); + break; + case GST_TASK_PAUSED: + /* when we are paused, signal to go to the new state */ + GST_TASK_SIGNAL (task); + break; + case GST_TASK_STARTED: + /* if we were started, we'll go to the new state after the next + * iteration. */ + break; + } + } + GST_OBJECT_UNLOCK (task); + + return res; + + /* ERRORS */ +no_lock: + { + GST_WARNING_OBJECT (task, "state %d set on task without a lock", state); + GST_OBJECT_UNLOCK (task); + g_warning ("task without a lock can't be set to state %d", state); + return FALSE; + } +} + +/** + * gst_task_start: + * @task: The #GstTask to start + * + * Starts @task. The @task must have a lock associated with it using + * gst_task_set_lock() or this function will return %FALSE. + * + * Returns: %TRUE if the task could be started. + * + * MT safe. + */ +gboolean +gst_task_start (GstTask * task) +{ + return gst_task_set_state (task, GST_TASK_STARTED); +} + +/** + * gst_task_stop: + * @task: The #GstTask to stop + * + * Stops @task. This method merely schedules the task to stop and + * will not wait for the task to have completely stopped. Use + * gst_task_join() to stop and wait for completion. + * + * Returns: %TRUE if the task could be stopped. + * + * MT safe. + */ +gboolean +gst_task_stop (GstTask * task) +{ + return gst_task_set_state (task, GST_TASK_STOPPED); +} + +/** + * gst_task_pause: + * @task: The #GstTask to pause + * + * Pauses @task. This method can also be called on a task in the + * stopped state, in which case a thread will be started and will remain + * in the paused state. This function does not wait for the task to complete + * the paused state. + * + * Returns: %TRUE if the task could be paused. + * + * MT safe. + */ +gboolean +gst_task_pause (GstTask * task) +{ + return gst_task_set_state (task, GST_TASK_PAUSED); +} + +/** + * gst_task_join: + * @task: The #GstTask to join + * + * Joins @task. After this call, it is safe to unref the task + * and clean up the lock set with gst_task_set_lock(). + * + * The task will automatically be stopped with this call. + * + * This function cannot be called from within a task function as this + * would cause a deadlock. The function will detect this and print a + * g_warning. + * + * Returns: %TRUE if the task could be joined. + * + * MT safe. + */ +gboolean +gst_task_join (GstTask * task) +{ + GThread *tself; + GstTaskPrivate *priv; + gpointer id; + GstTaskPool *pool = NULL; + + g_return_val_if_fail (GST_IS_TASK (task), FALSE); + + priv = task->priv; + + tself = g_thread_self (); + + GST_DEBUG_OBJECT (task, "Joining task %p, thread %p", task, tself); + + /* we don't use a real thread join here because we are using + * thread pools */ + GST_OBJECT_LOCK (task); + if (G_UNLIKELY (tself == task->thread)) + goto joining_self; + SET_TASK_STATE (task, GST_TASK_STOPPED); + /* signal the state change for when it was blocked in PAUSED. */ + GST_TASK_SIGNAL (task); + /* we set the running flag when pushing the task on the thread pool. + * This means that the task function might not be called when we try + * to join it here. */ + while (G_LIKELY (task->running)) + GST_TASK_WAIT (task); + /* clean the thread */ + task->thread = NULL; + /* get the id and pool to join */ + pool = priv->pool_id; + id = priv->id; + priv->pool_id = NULL; + priv->id = NULL; + GST_OBJECT_UNLOCK (task); + + if (pool) { + if (id) + gst_task_pool_join (pool, id); + gst_object_unref (pool); + } + + GST_DEBUG_OBJECT (task, "Joined task %p", task); + + return TRUE; + + /* ERRORS */ +joining_self: + { + GST_WARNING_OBJECT (task, "trying to join task from its thread"); + GST_OBJECT_UNLOCK (task); + g_warning ("\nTrying to join task %p from its thread would deadlock.\n" + "You cannot change the state of an element from its streaming\n" + "thread. Use g_idle_add() or post a GstMessage on the bus to\n" + "schedule the state change from the main thread.\n", task); + return FALSE; + } +} diff --git a/gst/gsttask.h b/gst/gsttask.h new file mode 100644 index 0000000..f93d4c1 --- /dev/null +++ b/gst/gsttask.h @@ -0,0 +1,219 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * <2005> Wim Taymans + * + * gsttask.h: Streaming tasks + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TASK_H__ +#define __GST_TASK_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GstTaskFunction: + * @user_data: user data passed to the function + * + * A function that will repeatedly be called in the thread created by + * a #GstTask. + */ +typedef void (*GstTaskFunction) (gpointer user_data); + +/* --- standard type macros --- */ +#define GST_TYPE_TASK (gst_task_get_type ()) +#define GST_TASK(task) (G_TYPE_CHECK_INSTANCE_CAST ((task), GST_TYPE_TASK, GstTask)) +#define GST_IS_TASK(task) (G_TYPE_CHECK_INSTANCE_TYPE ((task), GST_TYPE_TASK)) +#define GST_TASK_CLASS(tclass) (G_TYPE_CHECK_CLASS_CAST ((tclass), GST_TYPE_TASK, GstTaskClass)) +#define GST_IS_TASK_CLASS(tclass) (G_TYPE_CHECK_CLASS_TYPE ((tclass), GST_TYPE_TASK)) +#define GST_TASK_GET_CLASS(task) (G_TYPE_INSTANCE_GET_CLASS ((task), GST_TYPE_TASK, GstTaskClass)) +#define GST_TASK_CAST(task) ((GstTask*)(task)) + +typedef struct _GstTask GstTask; +typedef struct _GstTaskClass GstTaskClass; +typedef struct _GstTaskPrivate GstTaskPrivate; + +/** + * GstTaskState: + * @GST_TASK_STARTED: the task is started and running + * @GST_TASK_STOPPED: the task is stopped + * @GST_TASK_PAUSED: the task is paused + * + * The different states a task can be in + */ +typedef enum { + GST_TASK_STARTED, + GST_TASK_STOPPED, + GST_TASK_PAUSED +} GstTaskState; + +/** + * GST_TASK_STATE: + * @task: Task to get the state of + * + * Get access to the state of the task. + */ +#define GST_TASK_STATE(task) (GST_TASK_CAST(task)->state) + +/** + * GST_TASK_GET_COND: + * @task: Task to get the cond of + * + * Get access to the cond of the task. + */ +#define GST_TASK_GET_COND(task) (&GST_TASK_CAST(task)->cond) +/** + * GST_TASK_WAIT: + * @task: Task to wait for + * + * Wait for the task cond to be signalled + */ +#define GST_TASK_WAIT(task) g_cond_wait(GST_TASK_GET_COND (task), GST_OBJECT_GET_LOCK (task)) +/** + * GST_TASK_SIGNAL: + * @task: Task to signal + * + * Signal the task cond + */ +#define GST_TASK_SIGNAL(task) g_cond_signal(GST_TASK_GET_COND (task)) +/** + * GST_TASK_BROADCAST: + * @task: Task to broadcast + * + * Send a broadcast signal to all waiting task conds + */ +#define GST_TASK_BROADCAST(task) g_cond_broadcast(GST_TASK_GET_COND (task)) + +/** + * GST_TASK_GET_LOCK: + * @task: Task to get the lock of + * + * Get access to the task lock. + */ +#define GST_TASK_GET_LOCK(task) (GST_TASK_CAST(task)->lock) + +/** + * GstTaskThreadFunc: + * @task: The #GstTask + * @thread: The #GThread + * @user_data: user data + * + * Custom GstTask thread callback functions that can be installed. + */ +typedef void (*GstTaskThreadFunc) (GstTask *task, GThread *thread, gpointer user_data); + +/** + * GstTask: + * @state: the state of the task + * @cond: used to pause/resume the task + * @lock: The lock taken when iterating the task function + * @func: the function executed by this task + * @user_data: user_data passed to the task function + * @notify: GDestroyNotify for @user_data + * @running: a flag indicating that the task is running + * + * The #GstTask object. + */ +struct _GstTask { + GstObject object; + + /*< public >*/ /* with LOCK */ + GstTaskState state; + GCond cond; + + GRecMutex *lock; + + GstTaskFunction func; + gpointer user_data; + GDestroyNotify notify; + + gboolean running; + + /*< private >*/ + GThread *thread; + + GstTaskPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTaskClass { + GstObjectClass parent_class; + + /*< private >*/ + GstTaskPool *pool; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +void gst_task_cleanup_all (void); + +GST_API +GType gst_task_get_type (void); + +GST_API +GstTask* gst_task_new (GstTaskFunction func, + gpointer user_data, GDestroyNotify notify); +GST_API +void gst_task_set_lock (GstTask *task, GRecMutex *mutex); + +GST_API +GstTaskPool * gst_task_get_pool (GstTask *task); + +GST_API +void gst_task_set_pool (GstTask *task, GstTaskPool *pool); + +GST_API +void gst_task_set_enter_callback (GstTask *task, + GstTaskThreadFunc enter_func, + gpointer user_data, + GDestroyNotify notify); +GST_API +void gst_task_set_leave_callback (GstTask *task, + GstTaskThreadFunc leave_func, + gpointer user_data, + GDestroyNotify notify); +GST_API +GstTaskState gst_task_get_state (GstTask *task); + +GST_API +gboolean gst_task_set_state (GstTask *task, GstTaskState state); + +GST_API +gboolean gst_task_start (GstTask *task); + +GST_API +gboolean gst_task_stop (GstTask *task); + +GST_API +gboolean gst_task_pause (GstTask *task); + +GST_API +gboolean gst_task_join (GstTask *task); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTask, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TASK_H__ */ diff --git a/gst/gsttaskpool.c b/gst/gsttaskpool.c new file mode 100644 index 0000000..8344d9a --- /dev/null +++ b/gst/gsttaskpool.c @@ -0,0 +1,274 @@ +/* GStreamer + * Copyright (C) 2009 Wim Taymans + * + * gsttaskpool.c: Pool for streaming threads + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttaskpool + * @title: GstTaskPool + * @short_description: Pool of GStreamer streaming threads + * @see_also: #GstTask, #GstPad + * + * This object provides an abstraction for creating threads. The default + * implementation uses a regular GThreadPool to start tasks. + * + * Subclasses can be made to create custom threads. + */ + +#include "gst_private.h" + +#include "gstinfo.h" +#include "gsttaskpool.h" + +GST_DEBUG_CATEGORY_STATIC (taskpool_debug); +#define GST_CAT_DEFAULT (taskpool_debug) + +#ifndef GST_DISABLE_GST_DEBUG +static void gst_task_pool_finalize (GObject * object); +#endif + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (taskpool_debug, "taskpool", 0, "Thread pool"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstTaskPool, gst_task_pool, GST_TYPE_OBJECT, _do_init); + +typedef struct +{ + GstTaskPoolFunction func; + gpointer user_data; +} TaskData; + +static void +default_func (TaskData * tdata, GstTaskPool * pool) +{ + GstTaskPoolFunction func; + gpointer user_data; + + func = tdata->func; + user_data = tdata->user_data; + g_slice_free (TaskData, tdata); + + func (user_data); +} + +static void +default_prepare (GstTaskPool * pool, GError ** error) +{ + GST_OBJECT_LOCK (pool); + pool->pool = g_thread_pool_new ((GFunc) default_func, pool, -1, FALSE, NULL); + GST_OBJECT_UNLOCK (pool); +} + +static void +default_cleanup (GstTaskPool * pool) +{ + GST_OBJECT_LOCK (pool); + if (pool->pool) { + /* Shut down all the threads, we still process the ones scheduled + * because the unref happens in the thread function. + * Also wait for currently running ones to finish. */ + g_thread_pool_free (pool->pool, FALSE, TRUE); + pool->pool = NULL; + } + GST_OBJECT_UNLOCK (pool); +} + +static gpointer +default_push (GstTaskPool * pool, GstTaskPoolFunction func, + gpointer user_data, GError ** error) +{ + TaskData *tdata; + + tdata = g_slice_new (TaskData); + tdata->func = func; + tdata->user_data = user_data; + + GST_OBJECT_LOCK (pool); + if (pool->pool) + g_thread_pool_push (pool->pool, tdata, error); + else { + g_slice_free (TaskData, tdata); + } + GST_OBJECT_UNLOCK (pool); + + return NULL; +} + +static void +default_join (GstTaskPool * pool, gpointer id) +{ + /* we do nothing here, we can't join from the pools */ +} + +static void +gst_task_pool_class_init (GstTaskPoolClass * klass) +{ + GObjectClass *gobject_class; + GstTaskPoolClass *gsttaskpool_class; + + gobject_class = (GObjectClass *) klass; + gsttaskpool_class = (GstTaskPoolClass *) klass; + +#ifndef GST_DISABLE_GST_DEBUG + gobject_class->finalize = gst_task_pool_finalize; +#endif + + gsttaskpool_class->prepare = default_prepare; + gsttaskpool_class->cleanup = default_cleanup; + gsttaskpool_class->push = default_push; + gsttaskpool_class->join = default_join; +} + +static void +gst_task_pool_init (GstTaskPool * pool) +{ +} + +#ifndef GST_DISABLE_GST_DEBUG +static void +gst_task_pool_finalize (GObject * object) +{ + GST_DEBUG ("taskpool %p finalize", object); + + G_OBJECT_CLASS (gst_task_pool_parent_class)->finalize (object); +} +#endif +/** + * gst_task_pool_new: + * + * Create a new default task pool. The default task pool will use a regular + * GThreadPool for threads. + * + * Returns: (transfer full): a new #GstTaskPool. gst_object_unref() after usage. + */ +GstTaskPool * +gst_task_pool_new (void) +{ + GstTaskPool *pool; + + pool = g_object_new (GST_TYPE_TASK_POOL, NULL); + + /* clear floating flag */ + gst_object_ref_sink (pool); + + return pool; +} + +/** + * gst_task_pool_prepare: + * @pool: a #GstTaskPool + * @error: an error return location + * + * Prepare the taskpool for accepting gst_task_pool_push() operations. + * + * MT safe. + */ +void +gst_task_pool_prepare (GstTaskPool * pool, GError ** error) +{ + GstTaskPoolClass *klass; + + g_return_if_fail (GST_IS_TASK_POOL (pool)); + + klass = GST_TASK_POOL_GET_CLASS (pool); + + if (klass->prepare) + klass->prepare (pool, error); +} + +/** + * gst_task_pool_cleanup: + * @pool: a #GstTaskPool + * + * Wait for all tasks to be stopped. This is mainly used internally + * to ensure proper cleanup of internal data structures in test suites. + * + * MT safe. + */ +void +gst_task_pool_cleanup (GstTaskPool * pool) +{ + GstTaskPoolClass *klass; + + g_return_if_fail (GST_IS_TASK_POOL (pool)); + + klass = GST_TASK_POOL_GET_CLASS (pool); + + if (klass->cleanup) + klass->cleanup (pool); +} + +/** + * gst_task_pool_push: + * @pool: a #GstTaskPool + * @func: (scope async): the function to call + * @user_data: (closure): data to pass to @func + * @error: return location for an error + * + * Start the execution of a new thread from @pool. + * + * Returns: (transfer none) (nullable): a pointer that should be used + * for the gst_task_pool_join function. This pointer can be %NULL, you + * must check @error to detect errors. + */ +gpointer +gst_task_pool_push (GstTaskPool * pool, GstTaskPoolFunction func, + gpointer user_data, GError ** error) +{ + GstTaskPoolClass *klass; + + g_return_val_if_fail (GST_IS_TASK_POOL (pool), NULL); + + klass = GST_TASK_POOL_GET_CLASS (pool); + + if (klass->push == NULL) + goto not_supported; + + return klass->push (pool, func, user_data, error); + + /* ERRORS */ +not_supported: + { + g_warning ("pushing tasks on pool %p is not supported", pool); + return NULL; + } +} + +/** + * gst_task_pool_join: + * @pool: a #GstTaskPool + * @id: the id + * + * Join a task and/or return it to the pool. @id is the id obtained from + * gst_task_pool_push(). + */ +void +gst_task_pool_join (GstTaskPool * pool, gpointer id) +{ + GstTaskPoolClass *klass; + + g_return_if_fail (GST_IS_TASK_POOL (pool)); + + klass = GST_TASK_POOL_GET_CLASS (pool); + + if (klass->join) + klass->join (pool, id); +} diff --git a/gst/gsttaskpool.h b/gst/gsttaskpool.h new file mode 100644 index 0000000..3b654d9 --- /dev/null +++ b/gst/gsttaskpool.h @@ -0,0 +1,112 @@ +/* GStreamer + * Copyright (C) <2009> Wim Taymans + * + * gsttaskpool.h: Pool for creating streaming threads + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TASK_POOL_H__ +#define __GST_TASK_POOL_H__ + +#include + +G_BEGIN_DECLS + +/* --- standard type macros --- */ +#define GST_TYPE_TASK_POOL (gst_task_pool_get_type ()) +#define GST_TASK_POOL(pool) (G_TYPE_CHECK_INSTANCE_CAST ((pool), GST_TYPE_TASK_POOL, GstTaskPool)) +#define GST_IS_TASK_POOL(pool) (G_TYPE_CHECK_INSTANCE_TYPE ((pool), GST_TYPE_TASK_POOL)) +#define GST_TASK_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_CAST ((pclass), GST_TYPE_TASK_POOL, GstTaskPoolClass)) +#define GST_IS_TASK_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_TYPE ((pclass), GST_TYPE_TASK_POOL)) +#define GST_TASK_POOL_GET_CLASS(pool) (G_TYPE_INSTANCE_GET_CLASS ((pool), GST_TYPE_TASK_POOL, GstTaskPoolClass)) +#define GST_TASK_POOL_CAST(pool) ((GstTaskPool*)(pool)) + +typedef struct _GstTaskPool GstTaskPool; +typedef struct _GstTaskPoolClass GstTaskPoolClass; + +/** + * GstTaskPoolFunction: + * @user_data: user data for the task function + * + * Task function, see gst_task_pool_push(). + */ +typedef void (*GstTaskPoolFunction) (void *user_data); + +/** + * GstTaskPool: + * + * The #GstTaskPool object. + */ +struct _GstTaskPool { + GstObject object; + + /*< private >*/ + GThreadPool *pool; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstTaskPoolClass: + * @parent_class: the parent class structure + * @prepare: prepare the threadpool + * @cleanup: make sure all threads are stopped + * @push: start a new thread + * @join: join a thread + * + * The #GstTaskPoolClass object. + */ +struct _GstTaskPoolClass { + GstObjectClass parent_class; + + /*< public >*/ + void (*prepare) (GstTaskPool *pool, GError **error); + void (*cleanup) (GstTaskPool *pool); + + gpointer (*push) (GstTaskPool *pool, GstTaskPoolFunction func, + gpointer user_data, GError **error); + void (*join) (GstTaskPool *pool, gpointer id); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_task_pool_get_type (void); + +GST_API +GstTaskPool * gst_task_pool_new (void); + +GST_API +void gst_task_pool_prepare (GstTaskPool *pool, GError **error); + +GST_API +gpointer gst_task_pool_push (GstTaskPool *pool, GstTaskPoolFunction func, + gpointer user_data, GError **error); +GST_API +void gst_task_pool_join (GstTaskPool *pool, gpointer id); + +GST_API +void gst_task_pool_cleanup (GstTaskPool *pool); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTaskPool, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TASK_POOL_H__ */ diff --git a/gst/gsttoc.c b/gst/gsttoc.c new file mode 100644 index 0000000..7e62d5f --- /dev/null +++ b/gst/gsttoc.c @@ -0,0 +1,829 @@ +/* GStreamer + * (c) 2010, 2012 Alexander Saprykin + * + * gsttoc.c: GstToc initialization and parsing/creation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttoc + * @title: GstToc + * @short_description: Generic table of contents support + * @see_also: #GstStructure, #GstEvent, #GstMessage, #GstQuery + * + * #GstToc functions are used to create/free #GstToc and #GstTocEntry structures. + * Also they are used to convert #GstToc into #GstStructure and vice versa. + * + * #GstToc lets you to inform other elements in pipeline or application that playing + * source has some kind of table of contents (TOC). These may be chapters, editions, + * angles or other types. For example: DVD chapters, Matroska chapters or cue sheet + * TOC. Such TOC will be useful for applications to display instead of just a + * playlist. + * + * Using TOC is very easy. Firstly, create #GstToc structure which represents root + * contents of the source. You can also attach TOC-specific tags to it. Then fill + * it with #GstTocEntry entries by appending them to the #GstToc using + * gst_toc_append_entry(), and appending subentries to a #GstTocEntry using + * gst_toc_entry_append_sub_entry(). + * + * Note that root level of the TOC can contain only either editions or chapters. You + * should not mix them together at the same level. Otherwise you will get serialization + * /deserialization errors. Make sure that no one of the entries has negative start and + * stop values. + * + * Use gst_event_new_toc() to create a new TOC #GstEvent, and gst_event_parse_toc() to + * parse received TOC event. Use gst_event_new_toc_select() to create a new TOC select #GstEvent, + * and gst_event_parse_toc_select() to parse received TOC select event. The same rule for + * the #GstMessage: gst_message_new_toc() to create new TOC #GstMessage, and + * gst_message_parse_toc() to parse received TOC message. + * + * TOCs can have global scope or current scope. Global scope TOCs contain + * all entries that can possibly be selected using a toc select event, and + * are what an application is usually interested in. TOCs with current scope + * only contain the parts of the TOC relevant to the currently selected/playing + * stream; the current scope TOC is used by downstream elements such as muxers + * to write correct TOC entries when transcoding files, for example. When + * playing a DVD, the global TOC would contain a hierarchy of all titles, + * chapters and angles, for example, while the current TOC would only contain + * the chapters for the currently playing title if playback of a specific + * title was requested. + * + * Applications and plugins should not rely on TOCs having a certain kind of + * structure, but should allow for different alternatives. For example, a + * simple CUE sheet embedded in a file may be presented as a flat list of + * track entries, or could have a top-level edition node (or some other + * alternative type entry) with track entries underneath that node; or even + * multiple top-level edition nodes (or some other alternative type entries) + * each with track entries underneath, in case the source file has extracted + * a track listing from different sources). + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" +#include "gstenumtypes.h" +#include "gsttaglist.h" +#include "gststructure.h" +#include "gstvalue.h" +#include "gsttoc.h" +#include "gstpad.h" +#include "gstquark.h" + +struct _GstTocEntry +{ + GstMiniObject mini_object; + + GstToc *toc; + GstTocEntry *parent; + + gchar *uid; + GstTocEntryType type; + GstClockTime start, stop; + GList *subentries; + GstTagList *tags; + GstTocLoopType loop_type; + gint repeat_count; +}; + +struct _GstToc +{ + GstMiniObject mini_object; + + GstTocScope scope; + GList *entries; + GstTagList *tags; +}; + +#undef gst_toc_copy +static GstToc *gst_toc_copy (const GstToc * toc); +static void gst_toc_free (GstToc * toc); +#undef gst_toc_entry_copy +static GstTocEntry *gst_toc_entry_copy (const GstTocEntry * toc); +static void gst_toc_entry_free (GstTocEntry * toc); + +GType _gst_toc_type = 0; +GType _gst_toc_entry_type = 0; + +GST_DEFINE_MINI_OBJECT_TYPE (GstToc, gst_toc); +GST_DEFINE_MINI_OBJECT_TYPE (GstTocEntry, gst_toc_entry); + +/** + * gst_toc_new: + * @scope: scope of this TOC + * + * Create a new #GstToc structure. + * + * Returns: (transfer full): newly allocated #GstToc structure, free it + * with gst_toc_unref(). + */ +GstToc * +gst_toc_new (GstTocScope scope) +{ + GstToc *toc; + + g_return_val_if_fail (scope == GST_TOC_SCOPE_GLOBAL || + scope == GST_TOC_SCOPE_CURRENT, NULL); + + toc = g_slice_new0 (GstToc); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (toc), 0, GST_TYPE_TOC, + (GstMiniObjectCopyFunction) gst_toc_copy, NULL, + (GstMiniObjectFreeFunction) gst_toc_free); + + toc->scope = scope; + toc->tags = gst_tag_list_new_empty (); + + return toc; +} + +/** + * gst_toc_get_scope: + * @toc: a #GstToc instance + * + * Returns: scope of @toc + */ +GstTocScope +gst_toc_get_scope (const GstToc * toc) +{ + g_return_val_if_fail (toc != NULL, GST_TOC_SCOPE_GLOBAL); + + return toc->scope; +} + +/** + * gst_toc_set_tags: + * @toc: A #GstToc instance + * @tags: (allow-none) (transfer full): A #GstTagList or %NULL + * + * Set a #GstTagList with tags for the complete @toc. + */ +void +gst_toc_set_tags (GstToc * toc, GstTagList * tags) +{ + g_return_if_fail (toc != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (toc))); + + if (toc->tags) + gst_tag_list_unref (toc->tags); + toc->tags = tags; +} + +/** + * gst_toc_merge_tags: + * @toc: A #GstToc instance + * @tags: (allow-none): A #GstTagList or %NULL + * @mode: A #GstTagMergeMode + * + * Merge @tags into the existing tags of @toc using @mode. + */ +void +gst_toc_merge_tags (GstToc * toc, GstTagList * tags, GstTagMergeMode mode) +{ + g_return_if_fail (toc != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (toc))); + + if (!toc->tags) { + toc->tags = gst_tag_list_ref (tags); + } else { + GstTagList *tmp = gst_tag_list_merge (toc->tags, tags, mode); + gst_tag_list_unref (toc->tags); + toc->tags = tmp; + } +} + +/** + * gst_toc_get_tags: + * @toc: A #GstToc instance + * + * Gets the tags for @toc. + * + * Returns: (transfer none): A #GstTagList for @entry + */ +GstTagList * +gst_toc_get_tags (const GstToc * toc) +{ + g_return_val_if_fail (toc != NULL, NULL); + + return toc->tags; +} + +/** + * gst_toc_append_entry: + * @toc: A #GstToc instance + * @entry: (transfer full): A #GstTocEntry + * + * Appends the #GstTocEntry @entry to @toc. + */ +void +gst_toc_append_entry (GstToc * toc, GstTocEntry * entry) +{ + g_return_if_fail (toc != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (toc))); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (entry))); + g_return_if_fail (entry->toc == NULL); + g_return_if_fail (entry->parent == NULL); + + toc->entries = g_list_append (toc->entries, entry); + entry->toc = toc; + + GST_LOG ("appended %s entry with uid %s to toc %p", + gst_toc_entry_type_get_nick (entry->type), entry->uid, toc); + + gst_toc_dump (toc); +} + +/** + * gst_toc_get_entries: + * @toc: A #GstToc instance + * + * Gets the list of #GstTocEntry of @toc. + * + * Returns: (transfer none) (element-type Gst.TocEntry): A #GList of #GstTocEntry for @entry + */ +GList * +gst_toc_get_entries (const GstToc * toc) +{ + g_return_val_if_fail (toc != NULL, NULL); + + return toc->entries; +} + +static GstTocEntry * +gst_toc_entry_new_internal (GstTocEntryType type, const gchar * uid) +{ + GstTocEntry *entry; + + entry = g_slice_new0 (GstTocEntry); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (entry), 0, GST_TYPE_TOC_ENTRY, + (GstMiniObjectCopyFunction) gst_toc_entry_copy, NULL, + (GstMiniObjectFreeFunction) gst_toc_entry_free); + + entry->uid = g_strdup (uid); + entry->type = type; + entry->tags = NULL; + entry->start = entry->stop = GST_CLOCK_TIME_NONE; + + return entry; +} + +/** + * gst_toc_entry_new: + * @type: entry type. + * @uid: unique ID (UID) in the whole TOC. + * + * Create new #GstTocEntry structure. + * + * Returns: newly allocated #GstTocEntry structure, free it with gst_toc_entry_unref(). + */ +GstTocEntry * +gst_toc_entry_new (GstTocEntryType type, const gchar * uid) +{ + g_return_val_if_fail (uid != NULL, NULL); + + return gst_toc_entry_new_internal (type, uid); +} + +static void +gst_toc_free (GstToc * toc) +{ + g_list_foreach (toc->entries, (GFunc) gst_mini_object_unref, NULL); + g_list_free (toc->entries); + + if (toc->tags != NULL) + gst_tag_list_unref (toc->tags); + + g_slice_free (GstToc, toc); +} + +static void +gst_toc_entry_free (GstTocEntry * entry) +{ + g_return_if_fail (entry != NULL); + + g_list_foreach (entry->subentries, (GFunc) gst_mini_object_unref, NULL); + g_list_free (entry->subentries); + + g_free (entry->uid); + + if (entry->tags != NULL) + gst_tag_list_unref (entry->tags); + + g_slice_free (GstTocEntry, entry); +} + +static GstTocEntry * +gst_toc_entry_find_sub_entry (const GstTocEntry * entry, const gchar * uid) +{ + GList *cur; + GstTocEntry *subentry, *subsubentry; + + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + cur = entry->subentries; + while (cur != NULL) { + subentry = cur->data; + + if (g_strcmp0 (subentry->uid, uid) == 0) + return subentry; + + subsubentry = gst_toc_entry_find_sub_entry (subentry, uid); + if (subsubentry != NULL) + return subsubentry; + + cur = cur->next; + } + + return NULL; +} + +/** + * gst_toc_find_entry: + * @toc: #GstToc to search in. + * @uid: UID to find #GstTocEntry with. + * + * Find #GstTocEntry with given @uid in the @toc. + * + * Returns: (transfer none) (nullable): #GstTocEntry with specified + * @uid from the @toc, or %NULL if not found. + */ +GstTocEntry * +gst_toc_find_entry (const GstToc * toc, const gchar * uid) +{ + GList *cur; + GstTocEntry *entry, *subentry; + + g_return_val_if_fail (toc != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + cur = toc->entries; + while (cur != NULL) { + entry = cur->data; + + if (g_strcmp0 (entry->uid, uid) == 0) + return entry; + + subentry = gst_toc_entry_find_sub_entry (entry, uid); + if (subentry != NULL) + return subentry; + cur = cur->next; + } + + return NULL; +} + +static GList * +gst_toc_deep_copy_toc_entries (GList * entry_list) +{ + GQueue new_entries = G_QUEUE_INIT; + GList *l; + + for (l = entry_list; l != NULL; l = l->next) + g_queue_push_tail (&new_entries, gst_toc_entry_copy (l->data)); + + return new_entries.head; +} + +/** + * gst_toc_entry_copy: + * @entry: #GstTocEntry to copy. + * + * Copy #GstTocEntry with all subentries (deep copy). + * + * Returns: (nullable): newly allocated #GstTocEntry in case of + * success, %NULL otherwise; free it when done with + * gst_toc_entry_unref(). + */ +static GstTocEntry * +gst_toc_entry_copy (const GstTocEntry * entry) +{ + GstTocEntry *ret; + GstTagList *list; + + g_return_val_if_fail (entry != NULL, NULL); + + ret = gst_toc_entry_new (entry->type, entry->uid); + + ret->start = entry->start; + ret->stop = entry->stop; + + if (GST_IS_TAG_LIST (entry->tags)) { + list = gst_tag_list_copy (entry->tags); + if (ret->tags) + gst_tag_list_unref (ret->tags); + ret->tags = list; + } + + ret->subentries = gst_toc_deep_copy_toc_entries (entry->subentries); + + return ret; +} + +/** + * gst_toc_copy: + * @toc: #GstToc to copy. + * + * Copy #GstToc with all subentries (deep copy). + * + * Returns: (nullable): newly allocated #GstToc in case of success, + * %NULL otherwise; free it when done with gst_toc_unref(). + */ +static GstToc * +gst_toc_copy (const GstToc * toc) +{ + GstToc *ret; + GstTagList *list; + + g_return_val_if_fail (toc != NULL, NULL); + + ret = gst_toc_new (toc->scope); + + if (GST_IS_TAG_LIST (toc->tags)) { + list = gst_tag_list_copy (toc->tags); + gst_tag_list_unref (ret->tags); + ret->tags = list; + } + + ret->entries = gst_toc_deep_copy_toc_entries (toc->entries); + + return ret; +} + +/** + * gst_toc_entry_set_start_stop_times: + * @entry: #GstTocEntry to set values. + * @start: start value to set. + * @stop: stop value to set. + * + * Set @start and @stop values for the @entry. + */ +void +gst_toc_entry_set_start_stop_times (GstTocEntry * entry, gint64 start, + gint64 stop) +{ + g_return_if_fail (entry != NULL); + + entry->start = start; + entry->stop = stop; +} + +/** + * gst_toc_entry_get_start_stop_times: + * @entry: #GstTocEntry to get values from. + * @start: (out) (allow-none): the storage for the start value, leave + * %NULL if not need. + * @stop: (out) (allow-none): the storage for the stop value, leave + * %NULL if not need. + * + * Get @start and @stop values from the @entry and write them into appropriate + * storages. + * + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. + */ +gboolean +gst_toc_entry_get_start_stop_times (const GstTocEntry * entry, gint64 * start, + gint64 * stop) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + if (start != NULL) + *start = entry->start; + if (stop != NULL) + *stop = entry->stop; + + return TRUE; +} + +/** + * gst_toc_entry_set_loop: + * @entry: #GstTocEntry to set values. + * @loop_type: loop_type value to set. + * @repeat_count: repeat_count value to set. + * + * Set @loop_type and @repeat_count values for the @entry. + * + * Since: 1.4 + */ +void +gst_toc_entry_set_loop (GstTocEntry * entry, GstTocLoopType loop_type, + gint repeat_count) +{ + g_return_if_fail (entry != NULL); + + entry->loop_type = loop_type; + entry->repeat_count = repeat_count; +} + +/** + * gst_toc_entry_get_loop: + * @entry: #GstTocEntry to get values from. + * @loop_type: (out) (allow-none): the storage for the loop_type + * value, leave %NULL if not need. + * @repeat_count: (out) (allow-none): the storage for the repeat_count + * value, leave %NULL if not need. + * + * Get @loop_type and @repeat_count values from the @entry and write them into + * appropriate storages. Loops are e.g. used by sampled instruments. GStreamer + * is not automatically applying the loop. The application can process this + * meta data and use it e.g. to send a seek-event to loop a section. + * + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gst_toc_entry_get_loop (const GstTocEntry * entry, GstTocLoopType * loop_type, + gint * repeat_count) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + if (loop_type != NULL) + *loop_type = entry->loop_type; + if (repeat_count != NULL) + *repeat_count = entry->repeat_count; + + return TRUE; +} + + +/** + * gst_toc_entry_type_get_nick: + * @type: a #GstTocEntryType. + * + * Converts @type to a string representation. + * + * Returns: Returns a human-readable string for @type. This string is + * only for debugging purpose and should not be displayed in a user + * interface. + */ +const gchar * +gst_toc_entry_type_get_nick (GstTocEntryType type) +{ + switch (type) { + case GST_TOC_ENTRY_TYPE_ANGLE: + return "angle"; + case GST_TOC_ENTRY_TYPE_VERSION: + return "version"; + case GST_TOC_ENTRY_TYPE_EDITION: + return "edition"; + case GST_TOC_ENTRY_TYPE_TITLE: + return "title"; + case GST_TOC_ENTRY_TYPE_TRACK: + return "track"; + case GST_TOC_ENTRY_TYPE_CHAPTER: + return "chapter"; + default: + break; + } + return "invalid"; +} + +/** + * gst_toc_entry_get_entry_type: + * @entry: a #GstTocEntry + * + * Returns: @entry's entry type + */ +GstTocEntryType +gst_toc_entry_get_entry_type (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, GST_TOC_ENTRY_TYPE_INVALID); + + return entry->type; +} + +/** + * gst_toc_entry_is_alternative: + * @entry: a #GstTocEntry + * + * Returns: %TRUE if @entry's type is an alternative type, otherwise %FALSE + */ +gboolean +gst_toc_entry_is_alternative (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + return GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE (entry->type); +} + +/** + * gst_toc_entry_is_sequence: + * @entry: a #GstTocEntry + * + * Returns: %TRUE if @entry's type is a sequence type, otherwise %FALSE + */ +gboolean +gst_toc_entry_is_sequence (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + return GST_TOC_ENTRY_TYPE_IS_SEQUENCE (entry->type); +} + +/** + * gst_toc_entry_get_uid: + * @entry: A #GstTocEntry instance + * + * Gets the UID of @entry. + * + * Returns: (transfer none): The UID of @entry + */ +const gchar * +gst_toc_entry_get_uid (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + + return entry->uid; +} + +/** + * gst_toc_entry_append_sub_entry: + * @entry: A #GstTocEntry instance + * @subentry: (transfer full): A #GstTocEntry + * + * Appends the #GstTocEntry @subentry to @entry. + */ +void +gst_toc_entry_append_sub_entry (GstTocEntry * entry, GstTocEntry * subentry) +{ + g_return_if_fail (entry != NULL); + g_return_if_fail (subentry != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (entry))); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST + (subentry))); + g_return_if_fail (subentry->toc == NULL); + g_return_if_fail (subentry->parent == NULL); + + entry->subentries = g_list_append (entry->subentries, subentry); + subentry->toc = entry->toc; + subentry->parent = entry; + + GST_LOG ("appended %s subentry with uid %s to entry %s", + gst_toc_entry_type_get_nick (subentry->type), subentry->uid, entry->uid); +} + +/** + * gst_toc_entry_get_sub_entries: + * @entry: A #GstTocEntry instance + * + * Gets the sub-entries of @entry. + * + * Returns: (transfer none) (element-type Gst.TocEntry): A #GList of #GstTocEntry of @entry + */ +GList * +gst_toc_entry_get_sub_entries (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + + return entry->subentries; +} + +/** + * gst_toc_entry_set_tags: + * @entry: A #GstTocEntry instance + * @tags: (allow-none) (transfer full): A #GstTagList or %NULL + * + * Set a #GstTagList with tags for the complete @entry. + */ +void +gst_toc_entry_set_tags (GstTocEntry * entry, GstTagList * tags) +{ + g_return_if_fail (entry != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (entry))); + + if (entry->tags) + gst_tag_list_unref (entry->tags); + entry->tags = tags; +} + +/** + * gst_toc_entry_merge_tags: + * @entry: A #GstTocEntry instance + * @tags: (allow-none): A #GstTagList or %NULL + * @mode: A #GstTagMergeMode + * + * Merge @tags into the existing tags of @entry using @mode. + */ +void +gst_toc_entry_merge_tags (GstTocEntry * entry, GstTagList * tags, + GstTagMergeMode mode) +{ + g_return_if_fail (entry != NULL); + g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (entry))); + + if (!entry->tags) { + entry->tags = gst_tag_list_ref (tags); + } else { + GstTagList *tmp = gst_tag_list_merge (entry->tags, tags, mode); + gst_tag_list_unref (entry->tags); + entry->tags = tmp; + } +} + +/** + * gst_toc_entry_get_tags: + * @entry: A #GstTocEntry instance + * + * Gets the tags for @entry. + * + * Returns: (transfer none): A #GstTagList for @entry + */ +GstTagList * +gst_toc_entry_get_tags (const GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + + return entry->tags; +} + +/** + * gst_toc_entry_get_toc: + * @entry: A #GstTocEntry instance + * + * Gets the parent #GstToc of @entry. + * + * Returns: (transfer none): The parent #GstToc of @entry + */ +GstToc * +gst_toc_entry_get_toc (GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + + return entry->toc; +} + +/** + * gst_toc_entry_get_parent: + * @entry: A #GstTocEntry instance + * + * Gets the parent #GstTocEntry of @entry. + * + * Returns: (transfer none) (nullable): The parent #GstTocEntry of @entry + */ +GstTocEntry * +gst_toc_entry_get_parent (GstTocEntry * entry) +{ + g_return_val_if_fail (entry != NULL, NULL); + + return entry->parent; +} + +#ifndef GST_DISABLE_GST_DEBUG +static void +gst_toc_dump_entries (GList * entries, guint depth) +{ + GList *e; + gchar *indent; + + indent = g_malloc0 (depth + 1); + memset (indent, ' ', depth); + for (e = entries; e != NULL; e = e->next) { + GstTocEntry *entry = e->data; + + GST_TRACE ("%s+ %s (%s), %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT ", " + "tags: %" GST_PTR_FORMAT, indent, entry->uid, + gst_toc_entry_type_get_nick (entry->type), + GST_TIME_ARGS (entry->start), GST_TIME_ARGS (entry->stop), entry->tags); + + if (entry->subentries != NULL) + gst_toc_dump_entries (entry->subentries, depth + 2); + } + g_free (indent); +} +#endif + +void +gst_toc_dump (GstToc * toc) +{ +#ifndef GST_DISABLE_GST_DEBUG + GST_TRACE (" Toc %p, scope: %s, tags: %" GST_PTR_FORMAT, toc, + (toc->scope == GST_TOC_SCOPE_GLOBAL) ? "global" : "current", toc->tags); + gst_toc_dump_entries (toc->entries, 2); +#endif +} + +void +_priv_gst_toc_initialize (void) +{ + _gst_toc_type = gst_toc_get_type (); + _gst_toc_entry_type = gst_toc_entry_get_type (); +} diff --git a/gst/gsttoc.h b/gst/gsttoc.h new file mode 100644 index 0000000..807c521 --- /dev/null +++ b/gst/gsttoc.h @@ -0,0 +1,251 @@ +/* GStreamer + * (c) 2010, 2012 Alexander Saprykin + * + * gsttoc.h: generic TOC API declaration + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TOC_H__ +#define __GST_TOC_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API GType _gst_toc_type; + +GST_API GType _gst_toc_entry_type; + +#define GST_TYPE_TOC (_gst_toc_type) +#define GST_TYPE_TOC_ENTRY (_gst_toc_entry_type) + +typedef struct _GstTocEntry GstTocEntry; +typedef struct _GstToc GstToc; + +/** + * GstTocScope: + * @GST_TOC_SCOPE_GLOBAL: global TOC representing all selectable options + * (this is what applications are usually interested in) + * @GST_TOC_SCOPE_CURRENT: TOC for the currently active/selected stream + * (this is a TOC representing the current stream from start to EOS, + * and is what a TOC writer / muxer is usually interested in; it will + * usually be a subset of the global TOC, e.g. just the chapters of + * the current title, or the chapters selected for playback from the + * current title) + * + * The scope of a TOC. + */ +typedef enum { + GST_TOC_SCOPE_GLOBAL = 1, + GST_TOC_SCOPE_CURRENT = 2 +} GstTocScope; + +/** + * GstTocEntryType: + * @GST_TOC_ENTRY_TYPE_ANGLE: entry is an angle (i.e. an alternative) + * @GST_TOC_ENTRY_TYPE_VERSION: entry is a version (i.e. alternative) + * @GST_TOC_ENTRY_TYPE_EDITION: entry is an edition (i.e. alternative) + * @GST_TOC_ENTRY_TYPE_INVALID: invalid entry type value + * @GST_TOC_ENTRY_TYPE_TITLE: entry is a title (i.e. a part of a sequence) + * @GST_TOC_ENTRY_TYPE_TRACK: entry is a track (i.e. a part of a sequence) + * @GST_TOC_ENTRY_TYPE_CHAPTER: entry is a chapter (i.e. a part of a sequence) + * + * The different types of TOC entries (see #GstTocEntry). + * + * There are two types of TOC entries: alternatives or parts in a sequence. + */ +typedef enum { + GST_TOC_ENTRY_TYPE_ANGLE = -3, + GST_TOC_ENTRY_TYPE_VERSION = -2, + GST_TOC_ENTRY_TYPE_EDITION = -1, + GST_TOC_ENTRY_TYPE_INVALID = 0, + GST_TOC_ENTRY_TYPE_TITLE = 1, + GST_TOC_ENTRY_TYPE_TRACK = 2, + GST_TOC_ENTRY_TYPE_CHAPTER = 3, +} GstTocEntryType; + +/** + * GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE: + * @entry_type: The #GstTocEntryType from a #GstTocEntry + * + * Checks if @entry_type indicates that its #GstTocEntry is an alternative. + */ +#define GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE(entry_type) (entry_type < 0) + +/** + * GST_TOC_ENTRY_TYPE_IS_SEQUENCE: + * @entry_type: The #GstTocEntryType from a #GstTocEntry + * + * Checks if @entry_type indicates that its #GstTocEntry is a sequence. + */ +#define GST_TOC_ENTRY_TYPE_IS_SEQUENCE(entry_type) (entry_type > 0) + +/** + * GstTocLoopType: + * @GST_TOC_LOOP_NONE: single forward playback + * @GST_TOC_LOOP_FORWARD: repeat forward + * @GST_TOC_LOOP_REVERSE: repeat backward + * @GST_TOC_LOOP_PING_PONG: repeat forward and backward + * + * How a #GstTocEntry should be repeated. By default, entries are played a + * single time. + * + * Since: 1.4 + */ +typedef enum { + GST_TOC_LOOP_NONE = 0, + GST_TOC_LOOP_FORWARD, + GST_TOC_LOOP_REVERSE, + GST_TOC_LOOP_PING_PONG +} GstTocLoopType; + +/** + * GST_TOC_REPEAT_COUNT_INFINITE: + * + * Special value for the repeat_count set in gst_toc_entry_set_loop() or + * returned by gst_toc_entry_set_loop() to indicate infinite looping. + * + * Since: 1.4 + */ +#define GST_TOC_REPEAT_COUNT_INFINITE (-1) + +/* functions to return type structures */ + +GST_API +GType gst_toc_get_type (void); + +GST_API +GType gst_toc_entry_get_type (void); + +/* functions to create, ref and unref/free TOCs */ + +GST_API +GstToc * gst_toc_new (GstTocScope scope); + +GST_API +GstTocScope gst_toc_get_scope (const GstToc *toc); + +GST_API +void gst_toc_set_tags (GstToc *toc, GstTagList * tags); + +GST_API +void gst_toc_merge_tags (GstToc *toc, GstTagList *tags, GstTagMergeMode mode); + +GST_API +GstTagList * gst_toc_get_tags (const GstToc *toc); + +GST_API +void gst_toc_append_entry (GstToc *toc, GstTocEntry *entry); + +GST_API +GList * gst_toc_get_entries (const GstToc *toc); + +GST_API +void gst_toc_dump (GstToc *toc); + +#define gst_toc_ref(toc) (GstToc*)gst_mini_object_ref(GST_MINI_OBJECT_CAST(toc)) +#define gst_toc_unref(toc) gst_mini_object_unref(GST_MINI_OBJECT_CAST(toc)) +#define gst_toc_copy(toc) (GstToc*)gst_mini_object_copy(GST_MINI_OBJECT_CAST(toc)) +#define gst_toc_make_writable(toc) (GstToc*)gst_mini_object_make_writable(GST_MINI_OBJECT_CAST(toc)) + +/* functions to create, ref and unref/free TOC entries */ + +GST_API +GstTocEntry * gst_toc_entry_new (GstTocEntryType type, const gchar *uid); + +#define gst_toc_entry_ref(entry) (GstTocEntry*)gst_mini_object_ref(GST_MINI_OBJECT_CAST(entry)) +#define gst_toc_entry_unref(entry) gst_mini_object_unref(GST_MINI_OBJECT_CAST(entry)) +#define gst_toc_entry_copy(entry) (GstTocEntry*)gst_mini_object_copy(GST_MINI_OBJECT_CAST(entry)) +#define gst_toc_entry_make_writable(entry) (GstTocEntry*)gst_mini_object_make_writable(GST_MINI_OBJECT_CAST(entry)) + +GST_API +GstTocEntry * gst_toc_find_entry (const GstToc *toc, const gchar *uid); + +GST_API +GstTocEntryType gst_toc_entry_get_entry_type (const GstTocEntry *entry); + +GST_API +const gchar * gst_toc_entry_get_uid (const GstTocEntry *entry); + +GST_API +void gst_toc_entry_append_sub_entry (GstTocEntry *entry, GstTocEntry *subentry); + +GST_API +GList * gst_toc_entry_get_sub_entries (const GstTocEntry *entry); + +GST_API +void gst_toc_entry_set_tags (GstTocEntry *entry, GstTagList *tags); + +GST_API +void gst_toc_entry_merge_tags (GstTocEntry *entry, GstTagList *tags, GstTagMergeMode mode); + +GST_API +GstTagList * gst_toc_entry_get_tags (const GstTocEntry *entry); + +GST_API +gboolean gst_toc_entry_is_alternative (const GstTocEntry *entry); + +GST_API +gboolean gst_toc_entry_is_sequence (const GstTocEntry *entry); + +GST_API +void gst_toc_entry_set_start_stop_times (GstTocEntry *entry, gint64 start, gint64 stop); + +GST_API +gboolean gst_toc_entry_get_start_stop_times (const GstTocEntry *entry, gint64 *start, gint64 *stop); + +GST_API +void gst_toc_entry_set_loop (GstTocEntry *entry, GstTocLoopType loop_type, gint repeat_count); + +GST_API +gboolean gst_toc_entry_get_loop (const GstTocEntry *entry, GstTocLoopType *loop_type, gint *repeat_count); + +GST_API +GstToc * gst_toc_entry_get_toc (GstTocEntry *entry); + +GST_API +GstTocEntry * gst_toc_entry_get_parent (GstTocEntry *entry); + + +GST_API +const gchar * gst_toc_entry_type_get_nick (GstTocEntryType type); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +static inline void +_gst_autoptr_toc_unref (GstToc *toc) +{ + gst_toc_unref (toc); +} + +static inline void +_gst_autoptr_toc_entry_unref (GstTocEntry *entry) +{ + gst_toc_entry_unref (entry); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstToc, _gst_autoptr_toc_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTocEntry, _gst_autoptr_toc_entry_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TOC_H__ */ + diff --git a/gst/gsttocsetter.c b/gst/gsttocsetter.c new file mode 100644 index 0000000..c746f23 --- /dev/null +++ b/gst/gsttocsetter.c @@ -0,0 +1,180 @@ +/* GStreamer + * Copyright (C) 2010, 2012 Alexander Saprykin + * + * gsttocsetter.c: interface for TOC setting on 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttocsetter + * @title: GstTocSetter + * @short_description: Element interface that allows setting and retrieval + * of the TOC + * + * Element interface that allows setting of the TOC. + * + * Elements that support some kind of chapters or editions (or tracks like in + * the FLAC cue sheet) will implement this interface. + * + * If you just want to retrieve the TOC in your application then all you + * need to do is watch for TOC messages on your pipeline's bus (or you can + * perform TOC query). This interface is only for setting TOC data, not for + * extracting it. To set TOC from the application, find proper tocsetter element + * and set TOC using gst_toc_setter_set_toc(). + * + * Elements implementing the #GstTocSetter interface can extend existing TOC + * by getting extend UID for that (you can use gst_toc_find_entry() to retrieve it) + * with any TOC entries received from downstream. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" +#include "gsttocsetter.h" +#include +#include + +static GQuark gst_toc_key; + +G_DEFINE_INTERFACE_WITH_CODE (GstTocSetter, gst_toc_setter, GST_TYPE_ELEMENT, + gst_toc_key = g_quark_from_static_string ("gst-toc-setter-data");); + +static void +gst_toc_setter_default_init (GstTocSetterInterface * klass) +{ + /* nothing to do here, it's a dummy interface */ +} + +typedef struct +{ + GstToc *toc; + GMutex lock; +} GstTocData; + +static void +gst_toc_data_free (gpointer p) +{ + GstTocData *data = (GstTocData *) p; + + if (data->toc) + gst_toc_unref (data->toc); + + g_mutex_clear (&data->lock); + + g_slice_free (GstTocData, data); +} + +static GstTocData * +gst_toc_setter_get_data (GstTocSetter * setter) +{ + GstTocData *data; + + data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key); + if (!data) { + static GMutex create_mutex; + + /* make sure no other thread is creating a GstTocData at the same time */ + g_mutex_lock (&create_mutex); + data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key); + if (!data) { + data = g_slice_new (GstTocData); + g_mutex_init (&data->lock); + data->toc = NULL; + g_object_set_qdata_full (G_OBJECT (setter), gst_toc_key, data, + gst_toc_data_free); + } + g_mutex_unlock (&create_mutex); + } + + return data; +} + +/** + * gst_toc_setter_reset: + * @setter: a #GstTocSetter. + * + * Reset the internal TOC. Elements should call this from within the + * state-change handler. + */ +void +gst_toc_setter_reset (GstTocSetter * setter) +{ + g_return_if_fail (GST_IS_TOC_SETTER (setter)); + + gst_toc_setter_set_toc (setter, NULL); +} + +/** + * gst_toc_setter_get_toc: + * @setter: a #GstTocSetter. + * + * Return current TOC the setter uses. The TOC should not be + * modified without making it writable first. + * + * Returns: (transfer full) (nullable): TOC set, or %NULL. Unref with + * gst_toc_unref() when no longer needed + */ +GstToc * +gst_toc_setter_get_toc (GstTocSetter * setter) +{ + GstTocData *data; + GstToc *ret = NULL; + + g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL); + + data = gst_toc_setter_get_data (setter); + g_mutex_lock (&data->lock); + + if (data->toc != NULL) + ret = gst_toc_ref (data->toc); + + g_mutex_unlock (&data->lock); + + return ret; +} + +/** + * gst_toc_setter_set_toc: + * @setter: a #GstTocSetter. + * @toc: (allow-none): a #GstToc to set. + * + * Set the given TOC on the setter. Previously set TOC will be + * unreffed before setting a new one. + */ +void +gst_toc_setter_set_toc (GstTocSetter * setter, GstToc * toc) +{ + GstTocData *data; + + g_return_if_fail (GST_IS_TOC_SETTER (setter)); + + data = gst_toc_setter_get_data (setter); + + g_mutex_lock (&data->lock); + + if (data->toc != toc) { + if (data->toc) + gst_toc_unref (data->toc); + + data->toc = (toc) ? gst_toc_ref (toc) : NULL; + } + + g_mutex_unlock (&data->lock); +} diff --git a/gst/gsttocsetter.h b/gst/gsttocsetter.h new file mode 100644 index 0000000..4d58187 --- /dev/null +++ b/gst/gsttocsetter.h @@ -0,0 +1,72 @@ +/* GStreamer + * Copyright (C) 2010, 2012 Alexander Saprykin + * + * gsttocsetter.h: Interfaces for TOC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TOC_SETTER_H__ +#define __GST_TOC_SETTER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TOC_SETTER (gst_toc_setter_get_type ()) +#define GST_TOC_SETTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TOC_SETTER, GstTocSetter)) +#define GST_IS_TOC_SETTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TOC_SETTER)) +#define GST_TOC_SETTER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TOC_SETTER, GstTocSetterInterface)) +/** + * GstTocSetter: + * + * Opaque #GstTocSetter data structure. + */ +typedef struct _GstTocSetter GstTocSetter; +typedef struct _GstTocSetterInterface GstTocSetterInterface; + +/** + * GstTocSetterInterface: + * @g_iface: parent interface type. + * + * #GstTocSetterInterface interface. + */ + +struct _GstTocSetterInterface +{ + GTypeInterface g_iface; + + /* signals */ + + /* virtual table */ +}; + +GST_API +GType gst_toc_setter_get_type (void); + +GST_API +void gst_toc_setter_reset (GstTocSetter *setter); + +GST_API +GstToc * gst_toc_setter_get_toc (GstTocSetter *setter); + +GST_API +void gst_toc_setter_set_toc (GstTocSetter *setter, GstToc *toc); + +G_END_DECLS + +#endif /* __GST_TOC_SETTER_H__ */ + diff --git a/gst/gsttracer.c b/gst/gsttracer.c new file mode 100644 index 0000000..958007f --- /dev/null +++ b/gst/gsttracer.c @@ -0,0 +1,198 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracer.c: tracer 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttracer + * @title: GstTracer + * @short_description: Tracing base class + * + * Tracing modules will subclass #GstTracer and register through + * gst_tracer_register(). Modules can attach to various hook-types - see + * gst_tracing_register_hook(). When invoked they receive hook specific + * contextual data, which they must not modify. + * + * Since: 1.8 + */ + +#define GST_USE_UNSTABLE_API + +#include "gst_private.h" +#include "gstenumtypes.h" +#include "gsttracer.h" +#include "gsttracerfactory.h" +#include "gsttracerutils.h" + +GST_DEBUG_CATEGORY_EXTERN (tracer_debug); +#define GST_CAT_DEFAULT tracer_debug + +/* tracing plugins base class */ + +enum +{ + PROP_0, + PROP_PARAMS, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +static void gst_tracer_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tracer_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +struct _GstTracerPrivate +{ + gchar *params; +}; + +#define gst_tracer_parent_class parent_class +G_DEFINE_ABSTRACT_TYPE (GstTracer, gst_tracer, GST_TYPE_OBJECT); + +static void +gst_tracer_dispose (GObject * object) +{ + GstTracer *tracer = GST_TRACER (object); + g_free (tracer->priv->params); +} + +static void +gst_tracer_class_init (GstTracerClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_tracer_set_property; + gobject_class->get_property = gst_tracer_get_property; + gobject_class->dispose = gst_tracer_dispose; + + properties[PROP_PARAMS] = + g_param_spec_string ("params", "Params", "Extra configuration parameters", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, properties); + g_type_class_add_private (klass, sizeof (GstTracerPrivate)); +} + +static void +gst_tracer_init (GstTracer * tracer) +{ + tracer->priv = G_TYPE_INSTANCE_GET_PRIVATE (tracer, GST_TYPE_TRACER, + GstTracerPrivate); +} + +static void +gst_tracer_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTracer *self = GST_TRACER_CAST (object); + + switch (prop_id) { + case PROP_PARAMS: + self->priv->params = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tracer_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTracer *self = GST_TRACER_CAST (object); + + switch (prop_id) { + case PROP_PARAMS: + g_value_set_string (value, self->priv->params); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* tracing modules */ + +/** + * gst_tracer_register: + * @plugin: (allow-none): A #GstPlugin, or %NULL for a static typefind function + * @name: The name for registering + * @type: GType of tracer to register + * + * Create a new tracer-factory capable of instantiating objects of the + * @type and add the factory to @plugin. + * + * Returns: %TRUE, if the registering succeeded, %FALSE on error + */ +gboolean +gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type) +{ + GstPluginFeature *existing_feature; + GstRegistry *registry; + GstTracerFactory *factory; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_TRACER), FALSE); + + registry = gst_registry_get (); + /* check if feature already exists, if it exists there is no need to update it + * when the registry is getting updated, outdated plugins and all their + * features are removed and readded. + */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + factory = GST_TRACER_FACTORY_CAST (existing_feature); + factory->type = type; + existing_feature->loaded = TRUE; + gst_object_unref (existing_feature); + return TRUE; + } + + factory = g_object_new (GST_TYPE_TRACER_FACTORY, NULL); + GST_DEBUG_OBJECT (factory, "new tracer factory for %s", name); + + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), + GST_RANK_NONE); + + factory->type = type; + GST_DEBUG_OBJECT (factory, "tracer factory for %u:%s", + (guint) type, g_type_name (type)); + + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; /* interned string */ + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + gst_registry_add_feature (gst_registry_get (), + GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; +} diff --git a/gst/gsttracer.h b/gst/gsttracer.h new file mode 100644 index 0000000..1d2726d --- /dev/null +++ b/gst/gsttracer.h @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracer.h: tracer 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TRACER_H__ +#define __GST_TRACER_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstTracer GstTracer; +typedef struct _GstTracerPrivate GstTracerPrivate; +typedef struct _GstTracerClass GstTracerClass; + +#define GST_TYPE_TRACER (gst_tracer_get_type()) +#define GST_TRACER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TRACER,GstTracer)) +#define GST_TRACER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TRACER,GstTracerClass)) +#define GST_IS_TRACER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TRACER)) +#define GST_IS_TRACER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TRACER)) +#define GST_TRACER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_TRACER,GstTracerClass)) +#define GST_TRACER_CAST(obj) ((GstTracer *)(obj)) + +struct _GstTracer { + GstObject parent; + /*< private >*/ + GstTracerPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTracerClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_tracer_get_type (void); + +#ifdef GST_USE_UNSTABLE_API + +GST_API +void gst_tracing_register_hook (GstTracer *tracer, const gchar *detail, + GCallback func); + +/* tracing modules */ + +GST_API +gboolean gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type); + +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracer, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TRACER_H__ */ + diff --git a/gst/gsttracerfactory.c b/gst/gsttracerfactory.c new file mode 100644 index 0000000..32c4c74 --- /dev/null +++ b/gst/gsttracerfactory.c @@ -0,0 +1,98 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracerfactory.c: tracing subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttracerfactory + * @title: GstTracerFactory + * @short_description: Information about registered tracer functions + * + * Use gst_tracer_factory_get_list() to get a list of tracer factories known to + * GStreamer. + */ + +#include "gst_private.h" +#include "gstinfo.h" +#include "gsttracerfactory.h" +#include "gstregistry.h" + +GST_DEBUG_CATEGORY (tracer_debug); +#define GST_CAT_DEFAULT tracer_debug + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (tracer_debug, "GST_TRACER", \ + GST_DEBUG_FG_BLUE, "tracing subsystem"); \ +} + +#define gst_tracer_factory_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstTracerFactory, gst_tracer_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_tracer_factory_class_init (GstTracerFactoryClass * klass) +{ +} + +static void +gst_tracer_factory_init (GstTracerFactory * factory) +{ +} + +/** + * gst_tracer_factory_get_list: + * + * Gets the list of all registered tracer factories. You must free the + * list using gst_plugin_feature_list_free(). + * + * The returned factories are sorted by factory name. + * + * Free-function: gst_plugin_feature_list_free + * + * Returns: (transfer full) (element-type Gst.TracerFactory): the list of all + * registered #GstTracerFactory. + * + * Since: 1.8 + */ +GList * +gst_tracer_factory_get_list (void) +{ + return gst_registry_get_feature_list (gst_registry_get (), + GST_TYPE_TRACER_FACTORY); +} + +/** + * gst_tracer_factory_get_tracer_type: + * @factory: factory to get managed #GType from + * + * Get the #GType for elements managed by this factory. The type can + * only be retrieved if the element factory is loaded, which can be + * assured with gst_plugin_feature_load(). + * + * Returns: the #GType for tracers managed by this factory or 0 if + * the factory is not loaded. + */ +GType +gst_tracer_factory_get_tracer_type (GstTracerFactory * factory) +{ + g_return_val_if_fail (GST_IS_TRACER_FACTORY (factory), 0); + + return factory->type; +} diff --git a/gst/gsttracerfactory.h b/gst/gsttracerfactory.h new file mode 100644 index 0000000..44b10ec --- /dev/null +++ b/gst/gsttracerfactory.h @@ -0,0 +1,66 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracerfactory.h: tracing subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TRACER_FACTORY_H__ +#define __GST_TRACER_FACTORY_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TRACER_FACTORY (gst_tracer_factory_get_type()) +#define GST_TRACER_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRACER_FACTORY, GstTracerFactory)) +#define GST_IS_TRACER_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRACER_FACTORY)) +#define GST_TRACER_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TRACER_FACTORY, GstTracerFactoryClass)) +#define GST_IS_TRACER_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TRACER_FACTORY)) +#define GST_TRACER_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TRACER_FACTORY, GstTracerFactoryClass)) +#define GST_TRACER_FACTORY_CAST(obj) ((GstTracerFactory *)(obj)) + +/** + * GstTracerFactory: + * + * Opaque object that stores information about a tracer function. + * + * Since: 1.8 + */ +typedef struct _GstTracerFactory GstTracerFactory; +typedef struct _GstTracerFactoryClass GstTracerFactoryClass; + +/* tracering interface */ + +GST_API +GType gst_tracer_factory_get_type (void); + +GST_API +GList * gst_tracer_factory_get_list (void); + +GST_API +GType gst_tracer_factory_get_tracer_type (GstTracerFactory * factory); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerFactory, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TRACER_FACTORY_H__ */ diff --git a/gst/gsttracerrecord.c b/gst/gsttracerrecord.c new file mode 100644 index 0000000..2446a6e --- /dev/null +++ b/gst/gsttracerrecord.c @@ -0,0 +1,269 @@ +/* GStreamer + * Copyright (C) 2016 Stefan Sauer + * + * gsttracerrecord.c: tracer log record 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttracerrecord + * @title: GstTracerRecord + * @short_description: Trace log entry class + * + * Tracing modules will create instances of this class to announce the data they + * will log and create a log formatter. + * + * Since: 1.8 + */ + +#define GST_USE_UNSTABLE_API + +#include "gst_private.h" +#include "gstenumtypes.h" +#include "gstinfo.h" +#include "gststructure.h" +#include "gsttracerrecord.h" +#include "gstvalue.h" +#include + +GST_DEBUG_CATEGORY_EXTERN (tracer_debug); +#define GST_CAT_DEFAULT tracer_debug + +struct _GstTracerRecord +{ + GstObject parent; + + GstStructure *spec; + gchar *format; +}; + +struct _GstTracerRecordClass +{ + GstObjectClass parent_class; +}; + +#define gst_tracer_record_parent_class parent_class +G_DEFINE_TYPE (GstTracerRecord, gst_tracer_record, GST_TYPE_OBJECT); + +static gboolean +build_field_template (GQuark field_id, const GValue * value, gpointer user_data) +{ + GString *s = (GString *) user_data; + const GstStructure *sub; + GValue template_value = { 0, }; + GType type = G_TYPE_INVALID; + GstTracerValueFlags flags = GST_TRACER_VALUE_FLAGS_NONE; + gboolean res; + + if (G_VALUE_TYPE (value) != GST_TYPE_STRUCTURE) { + GST_WARNING ("expected field of type GstStructure, but %s is %s", + g_quark_to_string (field_id), G_VALUE_TYPE_NAME (value)); + return FALSE; + } + + sub = gst_value_get_structure (value); + gst_structure_get (sub, "type", G_TYPE_GTYPE, &type, "flags", + GST_TYPE_TRACER_VALUE_FLAGS, &flags, NULL); + + if (flags & GST_TRACER_VALUE_FLAGS_OPTIONAL) { + gchar *opt_name = g_strconcat ("have-", g_quark_to_string (field_id), NULL); + + /* add a boolean field, that indicates the presence of the next field */ + g_value_init (&template_value, G_TYPE_BOOLEAN); + priv__gst_structure_append_template_to_gstring (g_quark_from_string + (opt_name), &template_value, s); + g_value_unset (&template_value); + g_free (opt_name); + } + + g_value_init (&template_value, type); + res = priv__gst_structure_append_template_to_gstring (field_id, + &template_value, s); + g_value_unset (&template_value); + return res; +} + +static void +gst_tracer_record_build_format (GstTracerRecord * self) +{ + GstStructure *structure = self->spec; + GString *s; + gchar *name = (gchar *) g_quark_to_string (structure->name); + gchar *p; + + g_return_if_fail (g_str_has_suffix (name, ".class")); + + /* announce the format */ + GST_TRACE ("%" GST_PTR_FORMAT, structure); + + /* cut off '.class' suffix */ + name = g_strdup (name); + p = strrchr (name, '.'); + g_assert (p != NULL); + *p = '\0'; + + s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure)); + g_string_append (s, name); + gst_structure_foreach (structure, build_field_template, s); + g_string_append_c (s, ';'); + + self->format = g_string_free (s, FALSE); + GST_DEBUG ("new format string: %s", self->format); + g_free (name); +} + +static void +gst_tracer_record_dispose (GObject * object) +{ + GstTracerRecord *self = GST_TRACER_RECORD (object); + + if (self->spec) { + gst_structure_free (self->spec); + self->spec = NULL; + } + g_free (self->format); + self->format = NULL; +} + +static void +gst_tracer_record_class_init (GstTracerRecordClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gst_tracer_record_dispose; +} + +static void +gst_tracer_record_init (GstTracerRecord * self) +{ +} + +/** + * gst_tracer_record_new: + * @name: name of new record, must end on ".class". + * @firstfield: name of first field to set + * @...: additional arguments + + * + * Create a new tracer record. The record instance can be used to efficiently + * log entries using gst_tracer_record_log(). + * + * The @name without the ".class" suffix will be used for the log records. + * There must be fields for each value that gets logged where the field name is + * the value name. The field must be a #GstStructure describing the value. The + * sub structure must contain a field called 'type' of %G_TYPE_GTYPE that + * contains the GType of the value. The resulting #GstTracerRecord will take + * ownership of the field structures. + * + * The way to deal with optional values is to log an additional boolean before + * the optional field, that if %TRUE signals that the optional field is valid + * and %FALSE signals that the optional field should be ignored. One must still + * log a placeholder value for the optional field though. Please also note, that + * pointer type values must not be NULL - the underlying serialisation can not + * handle that right now. + * + * > Please note that this is still under discussion and subject to change. + * + * Returns: (transfer full): a new #GstTracerRecord + */ +GstTracerRecord * +gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...) +{ + GstTracerRecord *self; + GstStructure *structure; + va_list varargs; + gchar *err = NULL; + GType type; + GQuark id; + + va_start (varargs, firstfield); + structure = gst_structure_new_empty (name); + + while (firstfield) { + GValue val = { 0, }; + + id = g_quark_from_string (firstfield); + type = va_arg (varargs, GType); + + /* all fields passed here must be GstStructures which we take over */ + if (type != GST_TYPE_STRUCTURE) { + GST_WARNING ("expected field of type GstStructure, but %s is %s", + firstfield, g_type_name (type)); + } + + G_VALUE_COLLECT_INIT (&val, type, varargs, G_VALUE_NOCOPY_CONTENTS, &err); + if (G_UNLIKELY (err)) { + g_critical ("%s", err); + break; + } + /* see boxed_proxy_collect_value */ + val.data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS; + gst_structure_id_take_value (structure, id, &val); + + firstfield = va_arg (varargs, gchar *); + } + va_end (varargs); + + self = g_object_new (GST_TYPE_TRACER_RECORD, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (self); + + self->spec = structure; + gst_tracer_record_build_format (self); + + return self; +} + +#ifndef GST_DISABLE_GST_DEBUG +/** + * gst_tracer_record_log: + * @self: the tracer-record + * @...: the args as described in the spec- + * + * Serialzes the trace event into the log. + * + * Right now this is using the gstreamer debug log with the level TRACE (7) and + * the category "GST_TRACER". + * + * > Please note that this is still under discussion and subject to change. + */ +void +gst_tracer_record_log (GstTracerRecord * self, ...) +{ + va_list var_args; + + /* + * does it make sense to use the {file, line, func} from the tracer hook? + * a) + * - we'd need to pass them in the macros to gst_tracer_dispatch() + * - and each tracer needs to grab them from the va_list and pass them here + * b) + * - we create a context in dispatch, pass that to the tracer + * - and the tracer will pass that here + * ideally we also use *our* ts instead of the one that + * gst_debug_log_default() will pick + */ + + va_start (var_args, self); + if (G_LIKELY (GST_LEVEL_TRACE <= _gst_debug_min)) { + gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_TRACE, "", "", 0, NULL, + self->format, var_args); + } + va_end (var_args); +} +#endif diff --git a/gst/gsttracerrecord.h b/gst/gsttracerrecord.h new file mode 100644 index 0000000..75221dc --- /dev/null +++ b/gst/gsttracerrecord.h @@ -0,0 +1,105 @@ +/* GStreamer + * Copyright (C) 2016 Stefan Sauer + * + * gsttracerrecord.h: tracer log record 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TRACER_RECORD_H__ +#define __GST_TRACER_RECORD_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstTracerRecord GstTracerRecord; +typedef struct _GstTracerRecordClass GstTracerRecordClass; + +#define GST_TYPE_TRACER_RECORD (gst_tracer_record_get_type()) +#define GST_TRACER_RECORD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TRACER_RECORD,GstTracerRecord)) +#define GST_TRACER_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TRACER_RECORD,GstTracerRecordClass)) +#define GST_IS_TRACER_RECORD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TRACER_RECORD)) +#define GST_IS_TRACER_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TRACER_RECORD)) +#define GST_TRACER_RECORD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_TRACER_RECORD,GstTracerRecordClass)) +#define GST_TRACER_RECORD_CAST(obj) ((GstTracerRecord *)(obj)) + +GST_API +GType gst_tracer_record_get_type (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerRecord, gst_object_unref) +#endif + +/** + * GstTracerValueScope: + * @GST_TRACER_VALUE_SCOPE_PROCESS: the value is related to the process + * @GST_TRACER_VALUE_SCOPE_THREAD: the value is related to a thread + * @GST_TRACER_VALUE_SCOPE_ELEMENT: the value is related to an #GstElement + * @GST_TRACER_VALUE_SCOPE_PAD: the value is related to a #GstPad + * + * Tracing record will contain fields that contain a meassured value or extra + * meta-data. One such meta data are values that tell where a measurement was + * taken. This enumerating declares to which scope such a meta data field + * relates to. If it is e.g. %GST_TRACER_VALUE_SCOPE_PAD, then each of the log + * events may contain values for different #GstPads. + * + * Since: 1.8 + */ +typedef enum +{ + GST_TRACER_VALUE_SCOPE_PROCESS, + GST_TRACER_VALUE_SCOPE_THREAD, + GST_TRACER_VALUE_SCOPE_ELEMENT, + GST_TRACER_VALUE_SCOPE_PAD +} GstTracerValueScope; + +/** + * GstTracerValueFlags: + * @GST_TRACER_VALUE_FLAGS_NONE: no flags + * @GST_TRACER_VALUE_FLAGS_OPTIONAL: the value is optional. When using this flag + * one need to have an additional boolean arg before this value in the + * var-args list passed to gst_tracer_record_log(). + * @GST_TRACER_VALUE_FLAGS_AGGREGATED: the value is a combined figure, since the + * start of tracing. Examples are averages or timestamps. + * + * Flag that describe the value. These flags help applications processing the + * logs to understand the values. + */ +typedef enum +{ + GST_TRACER_VALUE_FLAGS_NONE = 0, + GST_TRACER_VALUE_FLAGS_OPTIONAL = (1 << 0), + GST_TRACER_VALUE_FLAGS_AGGREGATED = (1 << 1), +} GstTracerValueFlags; + +#ifdef GST_USE_UNSTABLE_API + +GST_API +GstTracerRecord * gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...); + +#ifndef GST_DISABLE_GST_DEBUG +GST_API +void gst_tracer_record_log (GstTracerRecord *self, ...); +#else +#define gst_tracer_record_log(...) G_STMT_START {} G_STMT_END +#endif + +#endif + +G_END_DECLS + +#endif /* __GST_TRACER_RECORD_H__ */ diff --git a/gst/gsttracerutils.c b/gst/gsttracerutils.c new file mode 100644 index 0000000..3aecd48 --- /dev/null +++ b/gst/gsttracerutils.c @@ -0,0 +1,207 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracerutils.c: tracing subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* Tracing subsystem: + * + * The tracing subsystem provides hooks in the core library and API for modules + * to attach to them. + * + * The user can activate tracers by setting the environment variable GST_TRACE + * to a ';' separated list of tracers. + * + * Note that instanciating tracers at runtime is possible but is not thread safe + * and needs to be done before any pipeline state is set to PAUSED. + */ + +#define GST_USE_UNSTABLE_API + +#include "gst_private.h" +#include "gsttracer.h" +#include "gsttracerfactory.h" +#include "gsttracerutils.h" + +#ifndef GST_DISABLE_GST_TRACER_HOOKS + +/* tracer quarks */ + +/* These strings must match order and number declared in the GstTracerQuarkId + * enum in gsttracerutils.h! */ +static const gchar *_quark_strings[] = { + "pad-push-pre", "pad-push-post", "pad-push-list-pre", "pad-push-list-post", + "pad-pull-range-pre", "pad-pull-range-post", "pad-push-event-pre", + "pad-push-event-post", "pad-query-pre", "pad-query-post", + "element-post-message-pre", + "element-post-message-post", "element-query-pre", "element-query-post", + "element-new", "element-add-pad", "element-remove-pad", + "bin-add-pre", "bin-add-post", "bin-remove-pre", "bin-remove-post", + "pad-link-pre", "pad-link-post", "pad-unlink-pre", "pad-unlink-post", + "element-change-state-pre", "element-change-state-post", + "mini-object-created", "mini-object-destroyed", "object-created", + "object-destroyed", "mini-object-reffed", "mini-object-unreffed", + "object-reffed", "object-unreffed", +}; + +GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX]; + +/* tracing helpers */ + +gboolean _priv_tracer_enabled = FALSE; +GHashTable *_priv_tracers = NULL; + +/* Initialize the tracing system */ +void +_priv_gst_tracing_init (void) +{ + gint i = 0; + const gchar *env = g_getenv ("GST_TRACERS"); + + /* We initialize the tracer sub system even if the end + * user did not activate it through the env variable + * so that external tools can use it anyway */ + GST_DEBUG ("Initializing GstTracer"); + _priv_tracers = g_hash_table_new (NULL, NULL); + + if (G_N_ELEMENTS (_quark_strings) != GST_TRACER_QUARK_MAX) + g_warning ("the quark table is not consistent! %d != %d", + (gint) G_N_ELEMENTS (_quark_strings), GST_TRACER_QUARK_MAX); + + for (i = 0; i < GST_TRACER_QUARK_MAX; i++) { + _priv_gst_tracer_quark_table[i] = + g_quark_from_static_string (_quark_strings[i]); + } + + if (env != NULL && *env != '\0') { + GstRegistry *registry = gst_registry_get (); + GstPluginFeature *feature; + GstTracerFactory *factory; + gchar **t = g_strsplit_set (env, ";", 0); + gchar *params; + + GST_INFO ("enabling tracers: '%s'", env); + i = 0; + while (t[i]) { + // check t[i] for params + if ((params = strchr (t[i], '('))) { + gchar *end = strchr (¶ms[1], ')'); + *params = '\0'; + params++; + if (end) + *end = '\0'; + } else { + params = NULL; + } + + GST_INFO ("checking tracer: '%s'", t[i]); + + if ((feature = gst_registry_lookup_feature (registry, t[i]))) { + factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature)); + if (factory) { + GstTracer *tracer; + + GST_INFO_OBJECT (factory, "creating tracer: type-id=%u", + (guint) factory->type); + + tracer = g_object_new (factory->type, "params", params, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (tracer); + + /* tracers register them self to the hooks */ + gst_object_unref (tracer); + } else { + GST_WARNING_OBJECT (feature, + "loading plugin containing feature %s failed!", t[i]); + } + } else { + GST_WARNING ("no tracer named '%s'", t[i]); + } + i++; + } + g_strfreev (t); + } +} + +void +_priv_gst_tracing_deinit (void) +{ + GList *h_list, *h_node, *t_node; + GstTracerHook *hook; + + _priv_tracer_enabled = FALSE; + if (!_priv_tracers) + return; + + /* shutdown tracers for final reports */ + h_list = g_hash_table_get_values (_priv_tracers); + for (h_node = h_list; h_node; h_node = g_list_next (h_node)) { + for (t_node = h_node->data; t_node; t_node = g_list_next (t_node)) { + hook = (GstTracerHook *) t_node->data; + gst_object_unref (hook->tracer); + g_slice_free (GstTracerHook, hook); + } + g_list_free (h_node->data); + } + g_list_free (h_list); + g_hash_table_destroy (_priv_tracers); + _priv_tracers = NULL; +} + +static void +gst_tracing_register_hook_id (GstTracer * tracer, GQuark detail, GCallback func) +{ + gpointer key = GINT_TO_POINTER (detail); + GList *list = g_hash_table_lookup (_priv_tracers, key); + GstTracerHook *hook = g_slice_new0 (GstTracerHook); + hook->tracer = gst_object_ref (tracer); + hook->func = func; + + list = g_list_prepend (list, hook); + g_hash_table_replace (_priv_tracers, key, list); + GST_DEBUG ("registering tracer for '%s', list.len=%d", + (detail ? g_quark_to_string (detail) : "*"), g_list_length (list)); + _priv_tracer_enabled = TRUE; +} + +/** + * gst_tracing_register_hook: + * @tracer: the tracer + * @detail: the detailed hook + * @func: (scope async): the callback + * + * Register @func to be called when the trace hook @detail is getting invoked. + * Use %NULL for @detail to register to all hooks. + */ +void +gst_tracing_register_hook (GstTracer * tracer, const gchar * detail, + GCallback func) +{ + gst_tracing_register_hook_id (tracer, g_quark_try_string (detail), func); +} + +#else /* !GST_DISABLE_GST_TRACER_HOOKS */ + +void +gst_tracing_register_hook (GstTracer * tracer, const gchar * detail, + GCallback func) +{ +} + +#endif /* GST_DISABLE_GST_TRACER_HOOKS */ diff --git a/gst/gsttracerutils.h b/gst/gsttracerutils.h new file mode 100644 index 0000000..bbb1a0d --- /dev/null +++ b/gst/gsttracerutils.h @@ -0,0 +1,752 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracerutils.h: tracing subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TRACER_UTILS_H__ +#define __GST_TRACER_UTILS_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#ifndef GST_DISABLE_GST_TRACER_HOOKS + +/* tracing hooks */ + +void _priv_gst_tracing_init (void); +void _priv_gst_tracing_deinit (void); + +/* tracer quarks */ + +/* These enums need to match the number and order + * of strings declared in _quark_table, in gsttracerutils.c */ +typedef enum /*< skip >*/ +{ + GST_TRACER_QUARK_HOOK_PAD_PUSH_PRE = 0, + GST_TRACER_QUARK_HOOK_PAD_PUSH_POST, + GST_TRACER_QUARK_HOOK_PAD_PUSH_LIST_PRE, + GST_TRACER_QUARK_HOOK_PAD_PUSH_LIST_POST, + GST_TRACER_QUARK_HOOK_PAD_PULL_RANGE_PRE, + GST_TRACER_QUARK_HOOK_PAD_PULL_RANGE_POST, + GST_TRACER_QUARK_HOOK_PAD_PUSH_EVENT_PRE , + GST_TRACER_QUARK_HOOK_PAD_PUSH_EVENT_POST, + GST_TRACER_QUARK_HOOK_PAD_QUERY_PRE , + GST_TRACER_QUARK_HOOK_PAD_QUERY_POST, + GST_TRACER_QUARK_HOOK_ELEMENT_POST_MESSAGE_PRE, + GST_TRACER_QUARK_HOOK_ELEMENT_POST_MESSAGE_POST, + GST_TRACER_QUARK_HOOK_ELEMENT_QUERY_PRE, + GST_TRACER_QUARK_HOOK_ELEMENT_QUERY_POST, + GST_TRACER_QUARK_HOOK_ELEMENT_NEW, + GST_TRACER_QUARK_HOOK_ELEMENT_ADD_PAD, + GST_TRACER_QUARK_HOOK_ELEMENT_REMOVE_PAD, + GST_TRACER_QUARK_HOOK_BIN_ADD_PRE, + GST_TRACER_QUARK_HOOK_BIN_ADD_POST, + GST_TRACER_QUARK_HOOK_BIN_REMOVE_PRE, + GST_TRACER_QUARK_HOOK_BIN_REMOVE_POST, + GST_TRACER_QUARK_HOOK_PAD_LINK_PRE, + GST_TRACER_QUARK_HOOK_PAD_LINK_POST, + GST_TRACER_QUARK_HOOK_PAD_UNLINK_PRE, + GST_TRACER_QUARK_HOOK_PAD_UNLINK_POST, + GST_TRACER_QUARK_HOOK_ELEMENT_CHANGE_STATE_PRE, + GST_TRACER_QUARK_HOOK_ELEMENT_CHANGE_STATE_POST, + GST_TRACER_QUARK_HOOK_MINI_OBJECT_CREATED, + GST_TRACER_QUARK_HOOK_MINI_OBJECT_DESTROYED, + GST_TRACER_QUARK_HOOK_OBJECT_CREATED, + GST_TRACER_QUARK_HOOK_OBJECT_DESTROYED, + GST_TRACER_QUARK_HOOK_MINI_OBJECT_REFFED, + GST_TRACER_QUARK_HOOK_MINI_OBJECT_UNREFFED, + GST_TRACER_QUARK_HOOK_OBJECT_REFFED, + GST_TRACER_QUARK_HOOK_OBJECT_UNREFFED, + GST_TRACER_QUARK_MAX +} GstTracerQuarkId; + +extern GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX]; + +#define GST_TRACER_QUARK(q) _priv_gst_tracer_quark_table[GST_TRACER_QUARK_##q] + +/* tracing module helpers */ + +typedef struct { + GObject *tracer; + GCallback func; +} GstTracerHook; + +extern gboolean _priv_tracer_enabled; +/* key are hook-id quarks, values are GstTracerHook */ +extern GHashTable *_priv_tracers; + +#define GST_TRACER_IS_ENABLED (_priv_tracer_enabled) + +#define GST_TRACER_TS \ + GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ()) + +/* tracing hooks */ + +#define GST_TRACER_ARGS h->tracer, ts +#define GST_TRACER_DISPATCH(key,type,args) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED) { \ + GstClockTime ts = GST_TRACER_TS; \ + GList *__l, *__n; \ + GstTracerHook *h; \ + __l = g_hash_table_lookup (_priv_tracers, GINT_TO_POINTER (key)); \ + for (__n = __l; __n; __n = g_list_next (__n)) { \ + h = (GstTracerHook *) __n->data; \ + ((type)(h->func)) args; \ + } \ + __l = g_hash_table_lookup (_priv_tracers, NULL); \ + for (__n = __l; __n; __n = g_list_next (__n)) { \ + h = (GstTracerHook *) __n->data; \ + ((type)(h->func)) args; \ + } \ + } \ +}G_STMT_END + +/** + * GstTracerHookPadPushPre: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @buffer: the buffer + * + * Pre-hook for gst_pad_push() named "pad-push-pre". + */ +typedef void (*GstTracerHookPadPushPre) (GObject *self, GstClockTime ts, + GstPad *pad, GstBuffer *buffer); +#define GST_TRACER_PAD_PUSH_PRE(pad, buffer) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_PRE), \ + GstTracerHookPadPushPre, (GST_TRACER_ARGS, pad, buffer)); \ +}G_STMT_END + +/** + * GstTracerHookPadPushPost: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @res: the result of gst_pad_push() + * + * Post-hook for gst_pad_push() named "pad-push-post". + */ +typedef void (*GstTracerHookPadPushPost) (GObject * self, GstClockTime ts, + GstPad *pad, GstFlowReturn res); +#define GST_TRACER_PAD_PUSH_POST(pad, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_POST), \ + GstTracerHookPadPushPost, (GST_TRACER_ARGS, pad, res)); \ +}G_STMT_END + +/** + * GstTracerHookPadPushListPre: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @list: the buffer-list + * + * Pre-hook for gst_pad_push_list() named "pad-push-list-pre". + */ +typedef void (*GstTracerHookPadPushListPre) (GObject *self, GstClockTime ts, + GstPad *pad, GstBufferList *list); +#define GST_TRACER_PAD_PUSH_LIST_PRE(pad, list) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_LIST_PRE), \ + GstTracerHookPadPushListPre, (GST_TRACER_ARGS, pad, list)); \ +}G_STMT_END + +/** + * GstTracerHookPadPushListPost: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @res: the result of gst_pad_push_list() + * + * Post-hook for gst_pad_push_list() named "pad-push-list-post". + */ +typedef void (*GstTracerHookPadPushListPost) (GObject *self, GstClockTime ts, + GstPad *pad, + GstFlowReturn res); +#define GST_TRACER_PAD_PUSH_LIST_POST(pad, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_LIST_POST), \ + GstTracerHookPadPushListPost, (GST_TRACER_ARGS, pad, res)); \ +}G_STMT_END + +/** + * GstTracerHookPadPullRangePre: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @offset: the stream offset + * @size: the requested size + * + * Pre-hook for gst_pad_pull_range() named "pad-pull-range-pre". + */ +typedef void (*GstTracerHookPadPullRangePre) (GObject *self, GstClockTime ts, + GstPad *pad, guint64 offset, guint size); +#define GST_TRACER_PAD_PULL_RANGE_PRE(pad, offset, size) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PULL_RANGE_PRE), \ + GstTracerHookPadPullRangePre, (GST_TRACER_ARGS, pad, offset, size)); \ +}G_STMT_END + +/** + * GstTracerHookPadPullRangePost: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @buffer: the buffer + * @res: the result of gst_pad_pull_range() + * + * Post-hook for gst_pad_pull_range() named "pad-pull-range-post". + */ +typedef void (*GstTracerHookPadPullRangePost) (GObject *self, GstClockTime ts, + GstPad *pad, GstBuffer *buffer, GstFlowReturn res); +#define GST_TRACER_PAD_PULL_RANGE_POST(pad, buffer, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PULL_RANGE_POST), \ + GstTracerHookPadPullRangePost, (GST_TRACER_ARGS, pad, buffer, res)); \ +}G_STMT_END + +/** + * GstTracerHookPadPushEventPre: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @event: the event + * + * Pre-hook for gst_pad_push_event() named "pad-push-event-pre". + */ +typedef void (*GstTracerHookPadPushEventPre) (GObject *self, GstClockTime ts, + GstPad *pad, GstEvent *event); +#define GST_TRACER_PAD_PUSH_EVENT_PRE(pad, event) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_EVENT_PRE), \ + GstTracerHookPadPushEventPre, (GST_TRACER_ARGS, pad, event)); \ +}G_STMT_END + +/** + * GstTracerHookPadPushEventPost: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @res: the result of gst_pad_push_event() + * + * Post-hook for gst_pad_push_event() named "pad-push-event-post". + */ +typedef void (*GstTracerHookPadPushEventPost) (GObject *self, GstClockTime ts, + GstPad *pad, gboolean res); +#define GST_TRACER_PAD_PUSH_EVENT_POST(pad, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_PUSH_EVENT_POST), \ + GstTracerHookPadPushEventPost, (GST_TRACER_ARGS, pad, res)); \ +}G_STMT_END + +/** + * GstTracerHookPadQueryPre: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @query: the query + * + * Pre-hook for gst_pad_query() named "pad-query-pre". + */ +typedef void (*GstTracerHookPadQueryPre) (GObject *self, GstClockTime ts, + GstPad *pad, GstQuery *query); +#define GST_TRACER_PAD_QUERY_PRE(pad, query) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_QUERY_PRE), \ + GstTracerHookPadQueryPre, (GST_TRACER_ARGS, pad, query)); \ +}G_STMT_END + +/** + * GstTracerHookPadQueryPost: + * @self: the tracer instance + * @ts: the current timestamp + * @pad: the pad + * @query: the query + * @res: the result of gst_pad_query() + * + * Post-hook for gst_pad_query() named "pad-query-post". + */ +typedef void (*GstTracerHookPadQueryPost) (GObject *self, GstClockTime ts, + GstPad *pad, GstQuery *query, gboolean res); +#define GST_TRACER_PAD_QUERY_POST(pad, query, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_QUERY_POST), \ + GstTracerHookPadQueryPost, (GST_TRACER_ARGS, pad, query, res)); \ +}G_STMT_END + +/** + * GstTracerHookElementPostMessagePre: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @message: the message + * + * Pre-hook for gst_element_post_message() named "element-post-message-pre". + */ +typedef void (*GstTracerHookElementPostMessagePre) (GObject *self, + GstClockTime ts, GstElement *element, GstMessage *message); +#define GST_TRACER_ELEMENT_POST_MESSAGE_PRE(element, message) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_POST_MESSAGE_PRE), \ + GstTracerHookElementPostMessagePre, (GST_TRACER_ARGS, element, message)); \ +}G_STMT_END + +/** + * GstTracerHookElementPostMessagePost: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @res: the result of gst_element_post_message() + * + * Pre-hook for gst_element_post_message() named "element-post-message-post". + */ +typedef void (*GstTracerHookElementPostMessagePost) (GObject *self, + GstClockTime ts, GstElement *element, gboolean res); +#define GST_TRACER_ELEMENT_POST_MESSAGE_POST(element, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_POST_MESSAGE_POST), \ + GstTracerHookElementPostMessagePost, (GST_TRACER_ARGS, element, res)); \ +}G_STMT_END + +/** + * GstTracerHookElementQueryPre: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @query: the query + * + * Pre-hook for gst_element_query() named "element-query-pre". + */ +typedef void (*GstTracerHookElementQueryPre) (GObject *self, GstClockTime ts, + GstElement *element, GstQuery *query); +#define GST_TRACER_ELEMENT_QUERY_PRE(element, query) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_QUERY_PRE), \ + GstTracerHookElementQueryPre, (GST_TRACER_ARGS, element, query)); \ +}G_STMT_END + +/** + * GstTracerHookElementQueryPost: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @query: the query + * @res: the result of gst_element_query() + * + * Post-hook for gst_element_query() named "element-query-post". + */ +typedef void (*GstTracerHookElementQueryPost) (GObject *self, GstClockTime ts, + GstElement *element, GstQuery *query, gboolean res); +#define GST_TRACER_ELEMENT_QUERY_POST(element, query, res) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_QUERY_POST), \ + GstTracerHookElementQueryPost, (GST_TRACER_ARGS, element, query, res)); \ +}G_STMT_END + +/** + * GstTracerHookElementNew: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * + * Hook for whenever a new element is created, named "element-new". + */ +typedef void (*GstTracerHookElementNew) (GObject *self, GstClockTime ts, + GstElement *element); +#define GST_TRACER_ELEMENT_NEW(element) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_NEW), \ + GstTracerHookElementNew, (GST_TRACER_ARGS, element)); \ +}G_STMT_END + +/** + * GstTracerHookElementAddPad: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @pad: the pad + * + * Hook for gst_element_add_pad() named "element-add-pad". + */ +typedef void (*GstTracerHookElementAddPad) (GObject *self, GstClockTime ts, + GstElement *element, GstPad *pad); +#define GST_TRACER_ELEMENT_ADD_PAD(element, pad) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_ADD_PAD), \ + GstTracerHookElementAddPad, (GST_TRACER_ARGS, element, pad)); \ +}G_STMT_END + +/** + * GstTracerHookElementRemovePad: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @pad: the pad + * + * Hook for gst_element_remove_pad() named "element-remove-pad". + */ +typedef void (*GstTracerHookElementRemovePad) (GObject *self, GstClockTime ts, + GstElement *element, GstPad *pad); +#define GST_TRACER_ELEMENT_REMOVE_PAD(element, pad) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_REMOVE_PAD), \ + GstTracerHookElementRemovePad, (GST_TRACER_ARGS, element, pad)); \ +}G_STMT_END + +/** + * GstTracerHookElementChangeStatePre: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @transition: the transition + * + * Pre-hook for gst_element_change_state() named "element-change-state-pre". + */ +typedef void (*GstTracerHookElementChangeStatePre) (GObject *self, + GstClockTime ts, GstElement *element, GstStateChange transition); +#define GST_TRACER_ELEMENT_CHANGE_STATE_PRE(element, transition) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_CHANGE_STATE_PRE), \ + GstTracerHookElementChangeStatePre, (GST_TRACER_ARGS, element, transition)); \ +}G_STMT_END + +/** + * GstTracerHookElementChangeStatePost: + * @self: the tracer instance + * @ts: the current timestamp + * @element: the element + * @transition: the transition + * @result: the result of gst_pad_push() + * + * Post-hook for gst_element_change_state() named "element-change-state-post". + */ +typedef void (*GstTracerHookElementChangeStatePost) (GObject *self, + GstClockTime ts, GstElement *element, GstStateChange transition, + GstStateChangeReturn result); +#define GST_TRACER_ELEMENT_CHANGE_STATE_POST(element, transition, result) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_ELEMENT_CHANGE_STATE_POST), \ + GstTracerHookElementChangeStatePost, (GST_TRACER_ARGS, element, transition, result)); \ +}G_STMT_END + +/** + * GstTracerHookBinAddPre: + * @self: the tracer instance + * @ts: the current timestamp + * @bin: the bin + * @element: the element + * + * Pre-hook for gst_bin_add() named "bin-add-pre". + */ +typedef void (*GstTracerHookBinAddPre) (GObject *self, GstClockTime ts, + GstBin *bin, GstElement *element); +#define GST_TRACER_BIN_ADD_PRE(bin, element) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_BIN_ADD_PRE), \ + GstTracerHookBinAddPre, (GST_TRACER_ARGS, bin, element)); \ +}G_STMT_END + +/** + * GstTracerHookBinAddPost: + * @self: the tracer instance + * @ts: the current timestamp + * @bin: the bin + * @element: the element + * @result: the result of gst_bin_add() + * + * Post-hook for gst_bin_add() named "bin-add-post". + */ +typedef void (*GstTracerHookBinAddPost) (GObject *self, GstClockTime ts, + GstBin *bin, GstElement *element, gboolean result); +#define GST_TRACER_BIN_ADD_POST(bin, element, result) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_BIN_ADD_POST), \ + GstTracerHookBinAddPost, (GST_TRACER_ARGS, bin, element, result)); \ +}G_STMT_END + +/** + * GstTracerHookBinRemovePre: + * @self: the tracer instance + * @ts: the current timestamp + * @bin: the bin + * @element: the element + * + * Pre-hook for gst_bin_remove() named "bin-remove-pre". + */ +typedef void (*GstTracerHookBinRemovePre) (GObject *self, GstClockTime ts, + GstBin *bin, GstElement *element); +#define GST_TRACER_BIN_REMOVE_PRE(bin, element) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_BIN_REMOVE_PRE), \ + GstTracerHookBinRemovePre, (GST_TRACER_ARGS, bin, element)); \ +}G_STMT_END + +/** + * GstTracerHookBinRemovePost: + * @self: the tracer instance + * @ts: the current timestamp + * @bin: the bin + * @result: the result of gst_bin_remove() + * + * Post-hook for gst_bin_remove() named "bin-remove-post". + */ +typedef void (*GstTracerHookBinRemovePost) (GObject *self, GstClockTime ts, + GstBin *bin, gboolean result); +#define GST_TRACER_BIN_REMOVE_POST(bin, result) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_BIN_REMOVE_POST), \ + GstTracerHookBinRemovePost, (GST_TRACER_ARGS, bin, result)); \ +}G_STMT_END + +/** + * GstTracerHookPadLinkPre: + * @self: the tracer instance + * @ts: the current timestamp + * @srcpad: the srcpad + * @sinkpad: the sinkpad + * + * Pre-hook for gst_pad_link() named "pad-link-pre". + */ +typedef void (*GstTracerHookPadLinkPre) (GObject *self, GstClockTime ts, + GstPad *srcpad, GstPad *sinkpad); +#define GST_TRACER_PAD_LINK_PRE(srcpad, sinkpad) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_LINK_PRE), \ + GstTracerHookPadLinkPre, (GST_TRACER_ARGS, srcpad, sinkpad)); \ +}G_STMT_END + +/** + * GstTracerHookPadLinkPost: + * @self: the tracer instance + * @ts: the current timestamp + * @srcpad: the srcpad + * @sinkpad: the sinkpad + * @result: the result of gst_pad_link() + * + * Post-hook for gst_pad_link() named "pad-link-post". + */ +typedef void (*GstTracerHookPadLinkPost) (GObject *self, GstClockTime ts, + GstPad *srcpad, GstPad *sinkpad, GstPadLinkReturn result); +#define GST_TRACER_PAD_LINK_POST(srcpad, sinkpad, result) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_LINK_POST), \ + GstTracerHookPadLinkPost, (GST_TRACER_ARGS, srcpad, sinkpad, result)); \ +}G_STMT_END + +/** + * GstTracerHookPadUnlinkPre: + * @self: the tracer instance + * @ts: the current timestamp + * @srcpad: the srcpad + * @sinkpad: the sinkpad + * + * Pre-hook for gst_pad_unlink() named "pad-unlink-pre". + */ +typedef void (*GstTracerHookPadUnlinkPre) (GObject *self, GstClockTime ts, + GstPad *srcpad, GstPad *sinkpad); +#define GST_TRACER_PAD_UNLINK_PRE(srcpad, sinkpad) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_UNLINK_PRE), \ + GstTracerHookPadUnlinkPre, (GST_TRACER_ARGS, srcpad, sinkpad)); \ +}G_STMT_END + +/** + * GstTracerHookPadUnlinkPost: + * @self: the tracer instance + * @ts: the current timestamp + * @srcpad: the srcpad + * @sinkpad: the sinkpad + * @result: the result of gst_pad_push() + * + * Post-hook for gst_pad_unlink() named "pad-unlink-post". + */ +typedef void (*GstTracerHookPadUnlinkPost) (GObject *self, GstClockTime ts, + GstPad *srcpad, GstPad *sinkpad, gboolean result); +#define GST_TRACER_PAD_UNLINK_POST(srcpad, sinkpad, result) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_UNLINK_POST), \ + GstTracerHookPadUnlinkPost, (GST_TRACER_ARGS, srcpad, sinkpad, result)); \ +}G_STMT_END + +/** + * GstTracerHookMiniObjectCreated: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the mini object being created + * + * Hook called when a #GstMiniObject is created named "mini-object-created". + */ +typedef void (*GstTracerHookMiniObjectCreated) (GObject *self, GstClockTime ts, + GstMiniObject *object); +#define GST_TRACER_MINI_OBJECT_CREATED(object) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MINI_OBJECT_CREATED), \ + GstTracerHookMiniObjectCreated, (GST_TRACER_ARGS, object)); \ +}G_STMT_END + +/** + * GstTracerHookMiniObjectDestroyed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the mini object being destroyed + * + * Hook called when a #GstMiniObject is being destroyed named + * "mini-object-destroyed". + */ +typedef void (*GstTracerHookMiniObjectDestroyed) (GObject *self, GstClockTime ts, + GstMiniObject *object); +#define GST_TRACER_MINI_OBJECT_DESTROYED(object) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MINI_OBJECT_DESTROYED), \ + GstTracerHookMiniObjectDestroyed, (GST_TRACER_ARGS, object)); \ +}G_STMT_END + +/** + * GstTracerHookObjectUnreffed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the object being unreffed + * @refcount: the new refcount after unrefing @object + * + * Hook called when a #GstObject is being unreffed named + * "object-unreffed" + */ +typedef void (*GstTracerHookObjectUnreffed) (GObject *self, GstClockTime ts, + GstObject *object, gint new_refcount); +#define GST_TRACER_OBJECT_UNREFFED(object, new_refcount) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_OBJECT_UNREFFED), \ + GstTracerHookObjectUnreffed, (GST_TRACER_ARGS, object, new_refcount)); \ +}G_STMT_END + +/** + * GstTracerHookObjectReffed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the object being reffed + * @refcount: the new refcount after refing @object + * + * Hook called when a #GstObject is being reffed named + * "object-reffed". + */ +typedef void (*GstTracerHookObjectReffed) (GObject *self, GstClockTime ts, + GstObject *object, gint new_refcount); +#define GST_TRACER_OBJECT_REFFED(object, new_refcount) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_OBJECT_REFFED), \ + GstTracerHookObjectReffed, (GST_TRACER_ARGS, object, new_refcount)); \ +}G_STMT_END + +/** + * GstTracerHookMiniObjectUnreffed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the mini object being unreffed + * @refcount: the new refcount after unrefing @object + * + * Hook called when a #GstMiniObject is being unreffed named + * "mini-object-unreffed". + */ +typedef void (*GstTracerHookMiniObjectUnreffed) (GObject *self, GstClockTime ts, + GstMiniObject *object, gint new_refcount); +#define GST_TRACER_MINI_OBJECT_UNREFFED(object, new_refcount) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MINI_OBJECT_UNREFFED), \ + GstTracerHookMiniObjectUnreffed, (GST_TRACER_ARGS, object, new_refcount)); \ +}G_STMT_END + +/** + * GstTracerHookMiniObjectReffed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the mini object being reffed + * @refcount: the new refcount after refing @object + * + * Hook called when a #GstMiniObject is being reffed named + * "mini-object-reffed". + */ +typedef void (*GstTracerHookMiniObjectReffed) (GObject *self, GstClockTime ts, + GstMiniObject *object, gint new_refcount); +#define GST_TRACER_MINI_OBJECT_REFFED(object, new_refcount) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MINI_OBJECT_REFFED), \ + GstTracerHookMiniObjectReffed, (GST_TRACER_ARGS, object, new_refcount)); \ +}G_STMT_END + +/** + * GstTracerHookObjectCreated: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the object being created + * + * Hook called when a #GstObject is created named "object-created". + */ +typedef void (*GstTracerHookObjectCreated) (GObject *self, GstClockTime ts, + GstObject *object); +#define GST_TRACER_OBJECT_CREATED(object) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_OBJECT_CREATED), \ + GstTracerHookObjectCreated, (GST_TRACER_ARGS, object)); \ +}G_STMT_END + +/** + * GstTracerHookObjectDestroyed: + * @self: the tracer instance + * @ts: the current timestamp + * @object: the object being destroyed + * + * Hook called when a #GstObject is being destroyed named + * "object-destroyed". + */ +typedef void (*GstTracerHookObjectDestroyed) (GObject *self, GstClockTime ts, + GstObject *object); +#define GST_TRACER_OBJECT_DESTROYED(object) G_STMT_START{ \ + GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_OBJECT_DESTROYED), \ + GstTracerHookObjectDestroyed, (GST_TRACER_ARGS, object)); \ +}G_STMT_END + + +#else /* !GST_DISABLE_GST_TRACER_HOOKS */ + +static inline void +_priv_gst_tracing_init (void) +{ + GST_DEBUG ("Tracing hooks are disabled"); +} + +static inline void +_priv_gst_tracing_deinit (void) +{ +} + +#define GST_TRACER_PAD_PUSH_PRE(pad, buffer) +#define GST_TRACER_PAD_PUSH_POST(pad, res) +#define GST_TRACER_PAD_PUSH_LIST_PRE(pad, list) +#define GST_TRACER_PAD_PUSH_LIST_POST(pad, res) +#define GST_TRACER_PAD_PULL_RANGE_PRE(pad, offset, size) +#define GST_TRACER_PAD_PULL_RANGE_POST(pad, buffer, res) +#define GST_TRACER_PAD_PUSH_EVENT_PRE(pad, event) +#define GST_TRACER_PAD_PUSH_EVENT_POST(pad, res) +#define GST_TRACER_PAD_QUERY_PRE(pad, query) +#define GST_TRACER_PAD_QUERY_POST(pad, query, res) +#define GST_TRACER_ELEMENT_POST_MESSAGE_PRE(element, message) +#define GST_TRACER_ELEMENT_POST_MESSAGE_POST(element, res) +#define GST_TRACER_ELEMENT_QUERY_PRE(element, query) +#define GST_TRACER_ELEMENT_QUERY_POST(element, query, res) +#define GST_TRACER_ELEMENT_NEW(element) +#define GST_TRACER_ELEMENT_ADD_PAD(element, pad) +#define GST_TRACER_ELEMENT_REMOVE_PAD(element, pad) +#define GST_TRACER_ELEMENT_CHANGE_STATE_PRE(element, transition) +#define GST_TRACER_ELEMENT_CHANGE_STATE_POST(element, transition, res) +#define GST_TRACER_BIN_ADD_PRE(bin, element) +#define GST_TRACER_BIN_ADD_POST(bin, element, res) +#define GST_TRACER_BIN_REMOVE_PRE(bin, element) +#define GST_TRACER_BIN_REMOVE_POST(bin, res) +#define GST_TRACER_PAD_LINK_PRE(srcpad, sinkpad) +#define GST_TRACER_PAD_LINK_POST(srcpad, sinkpad, res) +#define GST_TRACER_PAD_UNLINK_PRE(srcpad, sinkpad) +#define GST_TRACER_PAD_UNLINK_POST(srcpad, sinkpad, res) +#define GST_TRACER_MINI_OBJECT_CREATED(object) +#define GST_TRACER_MINI_OBJECT_DESTROYED(object) +#define GST_TRACER_MINI_OBJECT_REFFED(object, new_refcount) +#define GST_TRACER_MINI_OBJECT_UNREFFED(object, new_refcount) +#define GST_TRACER_OBJECT_CREATED(object) +#define GST_TRACER_OBJECT_DESTROYED(object) +#define GST_TRACER_OBJECT_REFFED(object, new_refcount) +#define GST_TRACER_OBJECT_UNREFFED(object, new_refcount) + +#endif /* GST_DISABLE_GST_TRACER_HOOKS */ + +G_END_DECLS + +#endif /* __GST_TRACER_UTILS_H__ */ + diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c new file mode 100644 index 0000000..5c2b0d1 --- /dev/null +++ b/gst/gsttypefind.c @@ -0,0 +1,215 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefind.c: typefinding subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttypefind + * @title: GstTypefind + * @short_description: Stream type detection + * + * The following functions allow you to detect the media type of an unknown + * stream. + */ + +#include "gst_private.h" +#include "gstinfo.h" +#include "gsttypefind.h" +#include "gstregistry.h" +#include "gsttypefindfactory.h" + +GST_DEBUG_CATEGORY_EXTERN (type_find_debug); +#define GST_CAT_DEFAULT type_find_debug + +G_DEFINE_POINTER_TYPE (GstTypeFind, gst_type_find); + +/** + * gst_type_find_register: + * @plugin: (allow-none): A #GstPlugin, or %NULL for a static typefind function + * @name: The name for registering + * @rank: The rank (or importance) of this typefind function + * @func: The #GstTypeFindFunction to use + * @extensions: (allow-none): Optional comma-separated list of extensions + * that could belong to this type + * @possible_caps: Optionally the caps that could be returned when typefinding + * succeeds + * @data: Optional user data. This user data must be available until the plugin + * is unloaded. + * @data_notify: a #GDestroyNotify that will be called on @data when the plugin + * is unloaded. + * + * Registers a new typefind function to be used for typefinding. After + * registering this function will be available for typefinding. + * This function is typically called during an element's plugin initialization. + * + * Returns: %TRUE on success, %FALSE otherwise + */ +gboolean +gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank, + GstTypeFindFunction func, const gchar * extensions, + GstCaps * possible_caps, gpointer data, GDestroyNotify data_notify) +{ + GstTypeFindFactory *factory; + + g_return_val_if_fail (name != NULL, FALSE); + + GST_INFO ("registering typefind function for %s", name); + + factory = g_object_new (GST_TYPE_TYPE_FIND_FACTORY, NULL); + GST_DEBUG_OBJECT (factory, "using new typefind factory for %s", name); + + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); + + if (extensions) + factory->extensions = g_strsplit (extensions, ",", -1); + + gst_caps_replace (&factory->caps, possible_caps); + factory->function = func; + factory->user_data = data; + factory->user_data_notify = data_notify; + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; /* interned string */ + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + gst_registry_add_feature (gst_registry_get (), + GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; +} + +/*** typefind function interface **********************************************/ + +/** + * gst_type_find_peek: + * @find: The #GstTypeFind object the function was called with + * @offset: The offset + * @size: The number of bytes to return + * + * Returns the @size bytes of the stream to identify beginning at offset. If + * offset is a positive number, the offset is relative to the beginning of the + * stream, if offset is a negative number the offset is relative to the end of + * the stream. The returned memory is valid until the typefinding function + * returns and must not be freed. + * + * Returns: (transfer none) (array length=size) (nullable): the + * requested data, or %NULL if that data is not available. + */ +const guint8 * +gst_type_find_peek (GstTypeFind * find, gint64 offset, guint size) +{ + g_return_val_if_fail (find->peek != NULL, NULL); + + return find->peek (find->data, offset, size); +} + +/** + * gst_type_find_suggest: + * @find: The #GstTypeFind object the function was called with + * @probability: The probability in percent that the suggestion is right + * @caps: The fixed #GstCaps to suggest + * + * If a #GstTypeFindFunction calls this function it suggests the caps with the + * given probability. A #GstTypeFindFunction may supply different suggestions + * in one call. + * It is up to the caller of the #GstTypeFindFunction to interpret these values. + */ +void +gst_type_find_suggest (GstTypeFind * find, guint probability, GstCaps * caps) +{ + g_return_if_fail (find->suggest != NULL); + g_return_if_fail (probability <= 100); + g_return_if_fail (caps != NULL); + g_return_if_fail (gst_caps_is_fixed (caps)); + + find->suggest (find->data, probability, caps); +} + +/** + * gst_type_find_suggest_simple: + * @find: The #GstTypeFind object the function was called with + * @probability: The probability in percent that the suggestion is right + * @media_type: the media type of the suggested caps + * @fieldname: (allow-none): first field of the suggested caps, or %NULL + * @...: additional arguments to the suggested caps in the same format as the + * arguments passed to gst_structure_new() (ie. triplets of field name, + * field GType and field value) + * + * If a #GstTypeFindFunction calls this function it suggests the caps with the + * given probability. A #GstTypeFindFunction may supply different suggestions + * in one call. It is up to the caller of the #GstTypeFindFunction to interpret + * these values. + * + * This function is similar to gst_type_find_suggest(), only that instead of + * passing a #GstCaps argument you can create the caps on the fly in the same + * way as you can with gst_caps_new_simple(). + * + * Make sure you terminate the list of arguments with a %NULL argument and that + * the values passed have the correct type (in terms of width in bytes when + * passed to the vararg function - this applies particularly to gdouble and + * guint64 arguments). + */ +void +gst_type_find_suggest_simple (GstTypeFind * find, guint probability, + const char *media_type, const char *fieldname, ...) +{ + GstStructure *structure; + va_list var_args; + GstCaps *caps; + + g_return_if_fail (find->suggest != NULL); + g_return_if_fail (probability <= 100); + g_return_if_fail (media_type != NULL); + + caps = gst_caps_new_empty (); + + va_start (var_args, fieldname); + structure = gst_structure_new_valist (media_type, fieldname, var_args); + va_end (var_args); + + gst_caps_append_structure (caps, structure); + g_return_if_fail (gst_caps_is_fixed (caps)); + + find->suggest (find->data, probability, caps); + gst_caps_unref (caps); +} + +/** + * gst_type_find_get_length: + * @find: The #GstTypeFind the function was called with + * + * Get the length of the data stream. + * + * Returns: The length of the data stream, or 0 if it is not available. + */ +guint64 +gst_type_find_get_length (GstTypeFind * find) +{ + if (find->get_length == NULL) + return 0; + + return find->get_length (find->data); +} diff --git a/gst/gsttypefind.h b/gst/gsttypefind.h new file mode 100644 index 0000000..90c9e94 --- /dev/null +++ b/gst/gsttypefind.h @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefind.h: typefinding subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TYPE_FIND_H__ +#define __GST_TYPE_FIND_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TYPE_FIND (gst_type_find_get_type()) + +typedef struct _GstTypeFind GstTypeFind; + +/** + * GstTypeFindFunction: + * @find: A #GstTypeFind structure + * @user_data: optional data to pass to the function + * + * A function that will be called by typefinding. + */ +typedef void (* GstTypeFindFunction) (GstTypeFind *find, gpointer user_data); + +/** + * GstTypeFindProbability: + * @GST_TYPE_FIND_NONE: type undetected. + * @GST_TYPE_FIND_MINIMUM: unlikely typefind. + * @GST_TYPE_FIND_POSSIBLE: possible type detected. + * @GST_TYPE_FIND_LIKELY: likely a type was detected. + * @GST_TYPE_FIND_NEARLY_CERTAIN: nearly certain that a type was detected. + * @GST_TYPE_FIND_MAXIMUM: very certain a type was detected. + * + * The probability of the typefind function. Higher values have more certainty + * in doing a reliable typefind. + */ +typedef enum { + GST_TYPE_FIND_NONE = 0, + GST_TYPE_FIND_MINIMUM = 1, + GST_TYPE_FIND_POSSIBLE = 50, + GST_TYPE_FIND_LIKELY = 80, + GST_TYPE_FIND_NEARLY_CERTAIN = 99, + GST_TYPE_FIND_MAXIMUM = 100 +} GstTypeFindProbability; + +/** + * GstTypeFind: + * @peek: Method to peek data. + * @suggest: Method to suggest #GstCaps with a given probability. + * @data: The data used by the caller of the typefinding function. + * @get_length: Returns the length of current data. + * + * Object that stores typefind callbacks. To use with #GstTypeFindFactory. + */ +struct _GstTypeFind { + /* private to the caller of the typefind function */ + const guint8 * (* peek) (gpointer data, + gint64 offset, + guint size); + + void (* suggest) (gpointer data, + guint probability, + GstCaps *caps); + + gpointer data; + + /* optional */ + guint64 (* get_length) (gpointer data); + + /* */ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_API +GType gst_type_find_get_type (void); + +/* typefind function interface */ + +GST_API +const guint8 * gst_type_find_peek (GstTypeFind * find, + gint64 offset, + guint size); +GST_API +void gst_type_find_suggest (GstTypeFind * find, + guint probability, + GstCaps * caps); +GST_API +void gst_type_find_suggest_simple (GstTypeFind * find, + guint probability, + const char * media_type, + const char * fieldname, ...); +GST_API +guint64 gst_type_find_get_length (GstTypeFind * find); + +/* registration interface */ + +GST_API +gboolean gst_type_find_register (GstPlugin * plugin, + const gchar * name, + guint rank, + GstTypeFindFunction func, + const gchar * extensions, + GstCaps * possible_caps, + gpointer data, + GDestroyNotify data_notify); + +G_END_DECLS + +#endif /* __GST_TYPE_FIND_H__ */ diff --git a/gst/gsttypefindfactory.c b/gst/gsttypefindfactory.c new file mode 100644 index 0000000..fe6b375 --- /dev/null +++ b/gst/gsttypefindfactory.c @@ -0,0 +1,237 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefindfactory.c: typefinding subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttypefindfactory + * @title: GstTypeFindFactory + * @short_description: Information about registered typefind functions + * + * These functions allow querying informations about registered typefind + * functions. How to create and register these functions is described in + * the section + * "Writing typefind functions". + * + * The following example shows how to write a very simple typefinder that + * identifies the given data. You can get quite a bit more complicated than + * that though. + * |[ + * typedef struct { + * guint8 *data; + * guint size; + * guint probability; + * GstCaps *data; + * } MyTypeFind; + * static void + * my_peek (gpointer data, gint64 offset, guint size) + * { + * MyTypeFind *find = (MyTypeFind *) data; + * if (offset >= 0 && offset + size <= find->size) { + * return find->data + offset; + * } + * return NULL; + * } + * static void + * my_suggest (gpointer data, guint probability, GstCaps *caps) + * { + * MyTypeFind *find = (MyTypeFind *) data; + * if (probability > find->probability) { + * find->probability = probability; + * gst_caps_replace (&find->caps, caps); + * } + * } + * static GstCaps * + * find_type (guint8 *data, guint size) + * { + * GList *walk, *type_list; + * MyTypeFind find = {data, size, 0, NULL}; + * GstTypeFind gst_find = {my_peek, my_suggest, &find, }; + * walk = type_list = gst_type_find_factory_get_list (); + * while (walk) { + * GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); + * walk = g_list_next (walk) + * gst_type_find_factory_call_function (factory, &gst_find); + * } + * g_list_free (type_list); + * return find.caps; + * }; + * ]| + */ + +#include "gst_private.h" +#include "gstinfo.h" +#include "gsttypefind.h" +#include "gsttypefindfactory.h" +#include "gstregistry.h" + +GST_DEBUG_CATEGORY (type_find_debug); +#define GST_CAT_DEFAULT type_find_debug + +static void gst_type_find_factory_dispose (GObject * object); + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (type_find_debug, "GST_TYPEFIND", \ + GST_DEBUG_FG_GREEN, "typefinding subsystem"); \ +} + +#define gst_type_find_factory_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstTypeFindFactory, gst_type_find_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_type_find_factory_class_init (GstTypeFindFactoryClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gst_type_find_factory_dispose; +} + +static void +gst_type_find_factory_init (GstTypeFindFactory * factory) +{ + factory->user_data = factory; + factory->user_data_notify = NULL; +} + +static void +gst_type_find_factory_dispose (GObject * object) +{ + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (object); + + if (factory->caps) { + gst_caps_unref (factory->caps); + factory->caps = NULL; + } + if (factory->extensions) { + g_strfreev (factory->extensions); + factory->extensions = NULL; + } + if (factory->user_data_notify && factory->user_data) { + factory->user_data_notify (factory->user_data); + factory->user_data = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/** + * gst_type_find_factory_get_list: + * + * Gets the list of all registered typefind factories. You must free the + * list using gst_plugin_feature_list_free(). + * + * The returned factories are sorted by highest rank first, and then by + * factory name. + * + * Free-function: gst_plugin_feature_list_free + * + * Returns: (transfer full) (element-type Gst.TypeFindFactory): the list of all + * registered #GstTypeFindFactory. + */ +GList * +gst_type_find_factory_get_list (void) +{ + return gst_registry_get_feature_list (gst_registry_get (), + GST_TYPE_TYPE_FIND_FACTORY); +} + +/** + * gst_type_find_factory_get_caps: + * @factory: A #GstTypeFindFactory + * + * Gets the #GstCaps associated with a typefind factory. + * + * Returns: (transfer none): the #GstCaps associated with this factory + */ +GstCaps * +gst_type_find_factory_get_caps (GstTypeFindFactory * factory) +{ + g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL); + + return factory->caps; +} + +/** + * gst_type_find_factory_get_extensions: + * @factory: A #GstTypeFindFactory + * + * Gets the extensions associated with a #GstTypeFindFactory. The returned + * array should not be changed. If you need to change stuff in it, you should + * copy it using g_strdupv(). This function may return %NULL to indicate + * a 0-length list. + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8) (nullable): + * a %NULL-terminated array of extensions associated with this factory + */ +const gchar *const * +gst_type_find_factory_get_extensions (GstTypeFindFactory * factory) +{ + g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL); + + return (const gchar * const *) factory->extensions; +} + +/** + * gst_type_find_factory_call_function: + * @factory: A #GstTypeFindFactory + * @find: (transfer none): a properly setup #GstTypeFind entry. The get_data + * and suggest_type members must be set. + * + * Calls the #GstTypeFindFunction associated with this factory. + */ +void +gst_type_find_factory_call_function (GstTypeFindFactory * factory, + GstTypeFind * find) +{ + GstTypeFindFactory *new_factory; + + g_return_if_fail (GST_IS_TYPE_FIND_FACTORY (factory)); + g_return_if_fail (find != NULL); + g_return_if_fail (find->peek != NULL); + g_return_if_fail (find->suggest != NULL); + + new_factory = + GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + if (new_factory) { + if (new_factory->function) + new_factory->function (find, new_factory->user_data); + gst_object_unref (new_factory); + } +} + +/** + * gst_type_find_factory_has_function: + * @factory: A #GstTypeFindFactory + * + * Check whether the factory has a typefind function. Typefind factories + * without typefind functions are a last-effort fallback mechanism to + * e.g. assume a certain media type based on the file extension. + * + * Returns: %TRUE if the factory has a typefind functions set, otherwise %FALSE + */ +gboolean +gst_type_find_factory_has_function (GstTypeFindFactory * factory) +{ + g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), FALSE); + + return (factory->function != NULL); +} diff --git a/gst/gsttypefindfactory.h b/gst/gsttypefindfactory.h new file mode 100644 index 0000000..d0a7e1d --- /dev/null +++ b/gst/gsttypefindfactory.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefindfactory.h: typefinding subsystem + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TYPE_FIND_FACTORY_H__ +#define __GST_TYPE_FIND_FACTORY_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TYPE_FIND_FACTORY (gst_type_find_factory_get_type()) +#define GST_TYPE_FIND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TYPE_FIND_FACTORY, GstTypeFindFactory)) +#define GST_IS_TYPE_FIND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TYPE_FIND_FACTORY)) +#define GST_TYPE_FIND_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TYPE_FIND_FACTORY, GstTypeFindFactoryClass)) +#define GST_IS_TYPE_FIND_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TYPE_FIND_FACTORY)) +#define GST_TYPE_FIND_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TYPE_FIND_FACTORY, GstTypeFindFactoryClass)) + +/** + * GstTypeFindFactory: + * + * Opaque object that stores information about a typefind function. + */ +typedef struct _GstTypeFindFactory GstTypeFindFactory; +typedef struct _GstTypeFindFactoryClass GstTypeFindFactoryClass; + +/* typefinding interface */ + +GST_API +GType gst_type_find_factory_get_type (void); + +GST_API +GList * gst_type_find_factory_get_list (void); + +GST_API +const gchar * const * gst_type_find_factory_get_extensions (GstTypeFindFactory *factory); + +GST_API +GstCaps * gst_type_find_factory_get_caps (GstTypeFindFactory *factory); + +GST_API +gboolean gst_type_find_factory_has_function (GstTypeFindFactory *factory); + +GST_API +void gst_type_find_factory_call_function (GstTypeFindFactory *factory, + GstTypeFind *find); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTypeFindFactory, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TYPE_FIND_FACTORY_H__ */ diff --git a/gst/gsturi.c b/gst/gsturi.c new file mode 100644 index 0000000..96bbda2 --- /dev/null +++ b/gst/gsturi.c @@ -0,0 +1,2830 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * Copyright (C) 2011 Tim-Philipp Müller + * Copyright (C) 2014 David Waring, British Broadcasting Corporation + * + * + * gsturi.c: register URI handlers and IETF RFC 3986 URI manipulations. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsturihandler + * @title: GstUriHandler + * @short_description: Interface to ease URI handling in plugins. + * + * The #GstURIHandler is an interface that is implemented by Source and Sink + * #GstElement to unify handling of URI. + * + * An application can use the following functions to quickly get an element + * that handles the given URI for reading or writing + * (gst_element_make_from_uri()). + * + * Source and Sink plugins should implement this interface when possible. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst_private.h" +#include "gst.h" +#include "gsturi.h" +#include "gstinfo.h" +#include "gstregistry.h" + +#include "gst-i18n-lib.h" + +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_uri_handler_debug); +#define GST_CAT_DEFAULT gst_uri_handler_debug + +#ifndef HAVE_STRCASESTR +#define strcasestr _gst_ascii_strcasestr + +/* From https://github.com/freebsd/freebsd/blob/master/contrib/file/src/strcasestr.c + * Updated to use GLib types and GLib string functions + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Find the first occurrence of find in s, ignore case. + */ + +static gchar * +_gst_ascii_strcasestr (const gchar * s, const gchar * find) +{ + gchar c, sc; + gsize len; + + if ((c = *find++) != 0) { + c = g_ascii_tolower (c); + len = strlen (find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while (g_ascii_tolower (sc) != c); + } while (g_ascii_strncasecmp (s, find, len) != 0); + s--; + } + return (gchar *) (gintptr) (s); +} +#endif + +GType +gst_uri_handler_get_type (void) +{ + static volatile gsize urihandler_type = 0; + + if (g_once_init_enter (&urihandler_type)) { + GType _type; + static const GTypeInfo urihandler_info = { + sizeof (GstURIHandlerInterface), + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL + }; + + _type = g_type_register_static (G_TYPE_INTERFACE, + "GstURIHandler", &urihandler_info, 0); + + GST_DEBUG_CATEGORY_INIT (gst_uri_handler_debug, "GST_URI", GST_DEBUG_BOLD, + "handling of URIs"); + g_once_init_leave (&urihandler_type, _type); + } + return urihandler_type; +} + +GQuark +gst_uri_error_quark (void) +{ + return g_quark_from_static_string ("gst-uri-error-quark"); +} + +#define HEX_ESCAPE '%' + +#ifndef GST_REMOVE_DEPRECATED +static const guchar acceptable[96] = { /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */ + 0x00, 0x3F, 0x20, 0x20, 0x20, 0x00, 0x2C, 0x3F, 0x3F, 0x3F, 0x3F, 0x22, 0x20, 0x3F, 0x3F, 0x1C, /* 2X !"#$%&'()*+,-./ */ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x38, 0x20, 0x20, 0x2C, 0x20, 0x2C, /* 3X 0123456789:;<=>? */ + 0x30, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 4X @ABCDEFGHIJKLMNO */ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x3F, /* 5X PQRSTUVWXYZ[\]^_ */ + 0x20, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, /* 6X `abcdefghijklmno */ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x20, 0x20, 0x20, 0x3F, 0x20 /* 7X pqrstuvwxyz{|}~DEL */ +}; + +typedef enum +{ + UNSAFE_ALL = 0x1, /* Escape all unsafe characters */ + UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */ + UNSAFE_PATH = 0x4, /* Allows '/' and '?' and '&' and '=' */ + UNSAFE_DOS_PATH = 0x8, /* Allows '/' and '?' and '&' and '=' and ':' */ + UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */ + UNSAFE_SLASHES = 0x20 /* Allows all characters except for '/' and '%' */ +} UnsafeCharacterSet; + +/* Escape undesirable characters using % + * ------------------------------------- + * + * This function takes a pointer to a string in which + * some characters may be unacceptable unescaped. + * It returns a string which has these characters + * represented by a '%' character followed by two hex digits. + * + * This routine returns a g_malloced string. + */ + +static const gchar hex[16] = "0123456789ABCDEF"; + +static gchar * +escape_string_internal (const gchar * string, UnsafeCharacterSet mask) +{ +#define ACCEPTABLE_CHAR(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask)) + + const gchar *p; + gchar *q; + gchar *result; + guchar c; + gint unacceptable; + UnsafeCharacterSet use_mask; + + g_return_val_if_fail (mask == UNSAFE_ALL + || mask == UNSAFE_ALLOW_PLUS + || mask == UNSAFE_PATH + || mask == UNSAFE_DOS_PATH + || mask == UNSAFE_HOST || mask == UNSAFE_SLASHES, NULL); + + if (string == NULL) { + return NULL; + } + + unacceptable = 0; + use_mask = mask; + for (p = string; *p != '\0'; p++) { + c = *p; + if (!ACCEPTABLE_CHAR (c)) { + unacceptable++; + } + if ((use_mask == UNSAFE_HOST) && (unacceptable || (c == '/'))) { + /* when escaping a host, if we hit something that needs to be escaped, or we finally + * hit a path separator, revert to path mode (the host segment of the url is over). + */ + use_mask = UNSAFE_PATH; + } + } + + result = g_malloc (p - string + unacceptable * 2 + 1); + + use_mask = mask; + for (q = result, p = string; *p != '\0'; p++) { + c = *p; + + if (!ACCEPTABLE_CHAR (c)) { + *q++ = HEX_ESCAPE; /* means hex coming */ + *q++ = hex[c >> 4]; + *q++ = hex[c & 15]; + } else { + *q++ = c; + } + if ((use_mask == UNSAFE_HOST) && (!ACCEPTABLE_CHAR (c) || (c == '/'))) { + use_mask = UNSAFE_PATH; + } + } + + *q = '\0'; + + return result; +} +#endif + +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 : -1; +} + +static int +unescape_character (const char *scanner) +{ + int first_digit; + int second_digit; + + first_digit = hex_to_int (*scanner++); + if (first_digit < 0) { + return -1; + } + + second_digit = hex_to_int (*scanner); + if (second_digit < 0) { + return -1; + } + + return (first_digit << 4) | second_digit; +} + +/* unescape_string: + * @escaped_string: an escaped URI, path, or other string + * @illegal_characters: a string containing a sequence of characters + * considered "illegal", '\0' is automatically in this list. + * + * Decodes escaped characters (i.e. PERCENTxx sequences) in @escaped_string. + * Characters are encoded in PERCENTxy form, where xy is the ASCII hex code + * for character 16x+y. + * + * Return value: (nullable): a newly allocated string with the + * unescaped equivalents, or %NULL if @escaped_string contained one of + * the characters in @illegal_characters. + **/ +static char * +unescape_string (const gchar * escaped_string, const gchar * illegal_characters) +{ + const gchar *in; + gchar *out, *result; + gint character; + + if (escaped_string == NULL) { + return NULL; + } + + result = g_malloc (strlen (escaped_string) + 1); + + out = result; + for (in = escaped_string; *in != '\0'; in++) { + character = *in; + if (*in == HEX_ESCAPE) { + character = unescape_character (in + 1); + + /* Check for an illegal character. We consider '\0' illegal here. */ + if (character <= 0 + || (illegal_characters != NULL + && strchr (illegal_characters, (char) character) != NULL)) { + g_free (result); + return NULL; + } + in += 2; + } + *out++ = (char) character; + } + + *out = '\0'; + g_assert ((gsize) (out - result) <= strlen (escaped_string)); + return result; + +} + + +static void +gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr) +{ + gchar *check = (gchar *) uri; + + g_assert (uri != NULL); + g_assert (endptr != NULL); + + if (g_ascii_isalpha (*check)) { + check++; + while (g_ascii_isalnum (*check) || *check == '+' + || *check == '-' || *check == '.') + check++; + } + + *endptr = check; +} + +/** + * gst_uri_protocol_is_valid: + * @protocol: A string + * + * Tests if the given string is a valid protocol identifier. Protocols + * must consist of alphanumeric characters, '+', '-' and '.' and must + * start with a alphabetic character. See RFC 3986 Section 3.1. + * + * Returns: %TRUE if the string is a valid protocol identifier, %FALSE otherwise. + */ +gboolean +gst_uri_protocol_is_valid (const gchar * protocol) +{ + gchar *endptr; + + g_return_val_if_fail (protocol != NULL, FALSE); + + gst_uri_protocol_check_internal (protocol, &endptr); + + return *endptr == '\0' && ((gsize) (endptr - protocol)) >= 2; +} + +/** + * gst_uri_is_valid: + * @uri: A URI string + * + * Tests if the given string is a valid URI identifier. URIs start with a valid + * scheme followed by ":" and maybe a string identifying the location. + * + * Returns: %TRUE if the string is a valid URI + */ +gboolean +gst_uri_is_valid (const gchar * uri) +{ + gchar *endptr; + + g_return_val_if_fail (uri != NULL, FALSE); + + gst_uri_protocol_check_internal (uri, &endptr); + + return *endptr == ':' && ((gsize) (endptr - uri)) >= 2; +} + +/** + * gst_uri_get_protocol: + * @uri: A URI string + * + * Extracts the protocol out of a given valid URI. The returned string must be + * freed using g_free(). + * + * Returns: (nullable): The protocol for this URI. + */ +gchar * +gst_uri_get_protocol (const gchar * uri) +{ + gchar *colon; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (gst_uri_is_valid (uri), NULL); + + colon = strstr (uri, ":"); + + return g_ascii_strdown (uri, colon - uri); +} + +/** + * gst_uri_has_protocol: + * @uri: a URI string + * @protocol: a protocol string (e.g. "http") + * + * Checks if the protocol of a given valid URI matches @protocol. + * + * Returns: %TRUE if the protocol matches. + */ +gboolean +gst_uri_has_protocol (const gchar * uri, const gchar * protocol) +{ + gchar *colon; + + g_return_val_if_fail (uri != NULL, FALSE); + g_return_val_if_fail (protocol != NULL, FALSE); + g_return_val_if_fail (gst_uri_is_valid (uri), FALSE); + + colon = strstr (uri, ":"); + + if (colon == NULL) + return FALSE; + + return (g_ascii_strncasecmp (uri, protocol, (gsize) (colon - uri)) == 0); +} + +/** + * gst_uri_get_location: + * @uri: A URI string + * + * Extracts the location out of a given valid URI, ie. the protocol and "://" + * are stripped from the URI, which means that the location returned includes + * the hostname if one is specified. The returned string must be freed using + * g_free(). + * + * Free-function: g_free + * + * Returns: (transfer full) (nullable): the location for this URI. Returns + * %NULL if the URI isn't valid. If the URI does not contain a location, an + * empty string is returned. + */ +gchar * +gst_uri_get_location (const gchar * uri) +{ + const gchar *colon; + gchar *unescaped = NULL; + + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (gst_uri_is_valid (uri), NULL); + + colon = strstr (uri, "://"); + if (!colon) + return NULL; + + unescaped = unescape_string (colon + 3, "/"); + + /* On Windows an URI might look like file:///c:/foo/bar.txt or + * file:///c|/foo/bar.txt (some Netscape versions) and we want to + * return c:/foo/bar.txt as location rather than /c:/foo/bar.txt. + * Can't use g_filename_from_uri() here because it will only handle the + * file:// protocol */ +#ifdef G_OS_WIN32 + if (unescaped != NULL && unescaped[0] == '/' && + g_ascii_isalpha (unescaped[1]) && + (unescaped[2] == ':' || unescaped[2] == '|')) { + unescaped[2] = ':'; + memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1); + } +#endif + + GST_LOG ("extracted location '%s' from URI '%s'", GST_STR_NULL (unescaped), + uri); + return unescaped; +} + +/** + * gst_uri_construct: + * @protocol: Protocol for URI + * @location: (transfer none): Location for URI + * + * Constructs a URI for a given valid protocol and location. + * + * Free-function: g_free + * + * Returns: (transfer full): a new string for this URI. Returns %NULL if the + * given URI protocol is not valid, or the given location is %NULL. + * + * Deprecated: Use GstURI instead. + */ +#ifndef GST_REMOVE_DEPRECATED +gchar * +gst_uri_construct (const gchar * protocol, const gchar * location) +{ + char *escaped, *proto_lowercase; + char *retval; + + g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL); + g_return_val_if_fail (location != NULL, NULL); + + proto_lowercase = g_ascii_strdown (protocol, -1); + escaped = escape_string_internal (location, UNSAFE_PATH); + retval = g_strdup_printf ("%s://%s", proto_lowercase, escaped); + g_free (escaped); + g_free (proto_lowercase); + + return retval; +} +#endif + +typedef struct +{ + GstURIType type; + const gchar *protocol; +} +SearchEntry; + +static gboolean +search_by_entry (GstPluginFeature * feature, gpointer search_entry) +{ + const gchar *const *protocols; + GstElementFactory *factory; + SearchEntry *entry = (SearchEntry *) search_entry; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + factory = GST_ELEMENT_FACTORY_CAST (feature); + + if (factory->uri_type != entry->type) + return FALSE; + + protocols = gst_element_factory_get_uri_protocols (factory); + + if (protocols == NULL) { + g_warning ("Factory '%s' implements GstUriHandler interface but returned " + "no supported protocols!", gst_plugin_feature_get_name (feature)); + return FALSE; + } + + while (*protocols != NULL) { + if (g_ascii_strcasecmp (*protocols, entry->protocol) == 0) + return TRUE; + protocols++; + } + return FALSE; +} + +static gint +sort_by_rank (GstPluginFeature * first, GstPluginFeature * second) +{ + return gst_plugin_feature_get_rank (second) - + gst_plugin_feature_get_rank (first); +} + +static GList * +get_element_factories_from_uri_protocol (const GstURIType type, + const gchar * protocol) +{ + GList *possibilities; + SearchEntry entry; + + g_return_val_if_fail (protocol, NULL); + + entry.type = type; + entry.protocol = protocol; + possibilities = gst_registry_feature_filter (gst_registry_get (), + search_by_entry, FALSE, &entry); + + return possibilities; +} + +/** + * gst_uri_protocol_is_supported: + * @type: Whether to check for a source or a sink + * @protocol: Protocol that should be checked for (e.g. "http" or "smb") + * + * Checks if an element exists that supports the given URI protocol. Note + * that a positive return value does not imply that a subsequent call to + * gst_element_make_from_uri() is guaranteed to work. + * + * Returns: %TRUE +*/ +gboolean +gst_uri_protocol_is_supported (const GstURIType type, const gchar * protocol) +{ + GList *possibilities; + + g_return_val_if_fail (protocol, FALSE); + + possibilities = get_element_factories_from_uri_protocol (type, protocol); + + if (possibilities) { + g_list_free (possibilities); + return TRUE; + } else + return FALSE; +} + +/** + * gst_element_make_from_uri: + * @type: Whether to create a source or a sink + * @uri: URI to create an element for + * @elementname: (allow-none): Name of created element, can be %NULL. + * @error: (allow-none): address where to store error information, or %NULL. + * + * Creates an element for handling the given URI. + * + * Returns: (transfer floating) (nullable): a new element or %NULL if none + * could be created + */ +GstElement * +gst_element_make_from_uri (const GstURIType type, const gchar * uri, + const gchar * elementname, GError ** error) +{ + GList *possibilities, *walk; + gchar *protocol; + GstElement *ret = NULL; + + g_return_val_if_fail (gst_is_initialized (), NULL); + g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL); + g_return_val_if_fail (gst_uri_is_valid (uri), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + GST_DEBUG ("type:%d, uri:%s, elementname:%s", type, uri, elementname); + + protocol = gst_uri_get_protocol (uri); + possibilities = get_element_factories_from_uri_protocol (type, protocol); + + if (!possibilities) { + GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source", + uri); + /* The error message isn't great, but we don't expect applications to + * show that error to users, but call the missing plugins functions */ + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL, + _("No URI handler for the %s protocol found"), protocol); + g_free (protocol); + return NULL; + } + g_free (protocol); + + possibilities = g_list_sort (possibilities, (GCompareFunc) sort_by_rank); + walk = possibilities; + while (walk) { + GstElementFactory *factory = walk->data; + GError *uri_err = NULL; + + ret = gst_element_factory_create (factory, elementname); + if (ret != NULL) { + GstURIHandler *handler = GST_URI_HANDLER (ret); + + if (gst_uri_handler_set_uri (handler, uri, &uri_err)) + break; + + GST_WARNING ("%s didn't accept URI '%s': %s", GST_OBJECT_NAME (ret), uri, + uri_err->message); + + if (error != NULL && *error == NULL) + g_propagate_error (error, uri_err); + else + g_error_free (uri_err); + + gst_object_unref (ret); + ret = NULL; + } + walk = walk->next; + } + gst_plugin_feature_list_free (possibilities); + + GST_LOG_OBJECT (ret, "created %s for URL '%s'", + type == GST_URI_SINK ? "sink" : "source", uri); + + /* if the first handler didn't work, but we found another one that works */ + if (ret != NULL) + g_clear_error (error); + + return ret; +} + +/** + * gst_uri_handler_get_uri_type: + * @handler: A #GstURIHandler. + * + * Gets the type of the given URI handler + * + * Returns: the #GstURIType of the URI handler. + * Returns #GST_URI_UNKNOWN if the @handler isn't implemented correctly. + */ +GstURIType +gst_uri_handler_get_uri_type (GstURIHandler * handler) +{ + GstURIHandlerInterface *iface; + GstURIType ret; + + g_return_val_if_fail (GST_IS_URI_HANDLER (handler), GST_URI_UNKNOWN); + + iface = GST_URI_HANDLER_GET_INTERFACE (handler); + g_return_val_if_fail (iface != NULL, GST_URI_UNKNOWN); + g_return_val_if_fail (iface->get_type != NULL, GST_URI_UNKNOWN); + + ret = iface->get_type (G_OBJECT_TYPE (handler)); + g_return_val_if_fail (GST_URI_TYPE_IS_VALID (ret), GST_URI_UNKNOWN); + + return ret; +} + +/** + * gst_uri_handler_get_protocols: + * @handler: A #GstURIHandler. + * + * Gets the list of protocols supported by @handler. This list may not be + * modified. + * + * Returns: (transfer none) (element-type utf8) (nullable): the + * supported protocols. Returns %NULL if the @handler isn't + * implemented properly, or the @handler doesn't support any + * protocols. + */ +const gchar *const * +gst_uri_handler_get_protocols (GstURIHandler * handler) +{ + GstURIHandlerInterface *iface; + const gchar *const *ret; + + g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL); + + iface = GST_URI_HANDLER_GET_INTERFACE (handler); + g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (iface->get_protocols != NULL, NULL); + + ret = iface->get_protocols (G_OBJECT_TYPE (handler)); + g_return_val_if_fail (ret != NULL, NULL); + + return ret; +} + +/** + * gst_uri_handler_get_uri: + * @handler: A #GstURIHandler + * + * Gets the currently handled URI. + * + * Returns: (transfer full) (nullable): the URI currently handled by + * the @handler. Returns %NULL if there are no URI currently + * handled. The returned string must be freed with g_free() when no + * longer needed. + */ +gchar * +gst_uri_handler_get_uri (GstURIHandler * handler) +{ + GstURIHandlerInterface *iface; + gchar *ret; + + g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL); + + iface = GST_URI_HANDLER_GET_INTERFACE (handler); + g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (iface->get_uri != NULL, NULL); + ret = iface->get_uri (handler); + if (ret != NULL) + g_return_val_if_fail (gst_uri_is_valid (ret), NULL); + + return ret; +} + +/** + * gst_uri_handler_set_uri: + * @handler: A #GstURIHandler + * @uri: URI to set + * @error: (allow-none): address where to store a #GError in case of + * an error, or %NULL + * + * Tries to set the URI of the given handler. + * + * Returns: %TRUE if the URI was set successfully, else %FALSE. + */ +gboolean +gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) +{ + GstURIHandlerInterface *iface; + gboolean ret; + gchar *protocol; + + g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE); + g_return_val_if_fail (gst_uri_is_valid (uri), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + iface = GST_URI_HANDLER_GET_INTERFACE (handler); + g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (iface->set_uri != NULL, FALSE); + + protocol = gst_uri_get_protocol (uri); + + if (iface->get_protocols) { + const gchar *const *protocols; + const gchar *const *p; + gboolean found_protocol = FALSE; + + protocols = iface->get_protocols (G_OBJECT_TYPE (handler)); + if (protocols != NULL) { + for (p = protocols; *p != NULL; ++p) { + if (g_ascii_strcasecmp (protocol, *p) == 0) { + found_protocol = TRUE; + break; + } + } + + if (!found_protocol) { + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_UNSUPPORTED_PROTOCOL, + _("URI scheme '%s' not supported"), protocol); + g_free (protocol); + return FALSE; + } + } + } + + ret = iface->set_uri (handler, uri, error); + + g_free (protocol); + + return ret; +} + +static gchar * +gst_file_utils_canonicalise_path (const gchar * path) +{ + gchar **parts, **p, *clean_path; + +#ifdef G_OS_WIN32 + { + GST_WARNING ("FIXME: canonicalise win32 path"); + return g_strdup (path); + } +#endif + + parts = g_strsplit (path, "/", -1); + + p = parts; + while (*p != NULL) { + if (strcmp (*p, ".") == 0) { + /* just move all following parts on top of this, incl. NUL terminator */ + g_free (*p); + memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); + /* re-check the new current part again in the next iteration */ + continue; + } else if (strcmp (*p, "..") == 0 && p > parts) { + /* just move all following parts on top of the previous part, incl. + * NUL terminator */ + g_free (*(p - 1)); + g_free (*p); + memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); + /* re-check the new current part again in the next iteration */ + --p; + continue; + } + ++p; + } + if (*path == '/') { + guint num_parts; + + num_parts = g_strv_length (parts) + 1; /* incl. terminator */ + parts = g_renew (gchar *, parts, num_parts + 1); + memmove (parts + 1, parts, num_parts * sizeof (gchar *)); + parts[0] = g_strdup ("/"); + } + + clean_path = g_build_filenamev (parts); + g_strfreev (parts); + return clean_path; +} + +static gboolean +file_path_contains_relatives (const gchar * path) +{ + return (strstr (path, "/./") != NULL || strstr (path, "/../") != NULL || + strstr (path, G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S) != NULL || + strstr (path, G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S) != NULL); +} + +/** + * gst_filename_to_uri: + * @filename: (type filename): absolute or relative file name path + * @error: pointer to error, or %NULL + * + * Similar to g_filename_to_uri(), but attempts to handle relative file paths + * as well. Before converting @filename into an URI, it will be prefixed by + * the current working directory if it is a relative path, and then the path + * will be canonicalised so that it doesn't contain any './' or '../' segments. + * + * On Windows #filename should be in UTF-8 encoding. + * + * Returns: newly-allocated URI string, or NULL on error. The caller must + * free the URI string with g_free() when no longer needed. + */ +gchar * +gst_filename_to_uri (const gchar * filename, GError ** error) +{ + gchar *abs_location = NULL; + gchar *uri, *abs_clean; + + g_return_val_if_fail (filename != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + if (g_path_is_absolute (filename)) { + if (!file_path_contains_relatives (filename)) { + uri = g_filename_to_uri (filename, NULL, error); + goto beach; + } + + abs_location = g_strdup (filename); + } else { + gchar *cwd; + + cwd = g_get_current_dir (); + abs_location = g_build_filename (cwd, filename, NULL); + g_free (cwd); + + if (!file_path_contains_relatives (abs_location)) { + uri = g_filename_to_uri (abs_location, NULL, error); + goto beach; + } + } + + /* path is now absolute, but contains '.' or '..' */ + abs_clean = gst_file_utils_canonicalise_path (abs_location); + GST_LOG ("'%s' -> '%s' -> '%s'", filename, abs_location, abs_clean); + uri = g_filename_to_uri (abs_clean, NULL, error); + g_free (abs_clean); + +beach: + + g_free (abs_location); + GST_DEBUG ("'%s' -> '%s'", filename, uri); + return uri; +} + +/**************************************************************************** + * GstUri - GstMiniObject to parse and merge URIs according to IETF RFC 3986 + ****************************************************************************/ + +/** + * SECTION:gsturi + * @title: GstUri + * @short_description: URI parsing and manipulation. + * + * A #GstUri object can be used to parse and split a URI string into its + * constituant parts. Two #GstUri objects can be joined to make a new #GstUri + * using the algorithm described in RFC3986. + */ + +/* Definition for GstUri object */ +struct _GstUri +{ + /*< private > */ + GstMiniObject mini_object; + gchar *scheme; + gchar *userinfo; + gchar *host; + guint port; + GList *path; + GHashTable *query; + gchar *fragment; +}; + +GST_DEFINE_MINI_OBJECT_TYPE (GstUri, gst_uri); + +static GstUri *_gst_uri_copy (const GstUri * uri); +static void _gst_uri_free (GstUri * uri); +static GstUri *_gst_uri_new (void); +static GList *_remove_dot_segments (GList * path); + +/* private GstUri functions */ + +static GstUri * +_gst_uri_new (void) +{ + GstUri *uri; + + g_return_val_if_fail (gst_is_initialized (), NULL); + + uri = GST_URI_CAST (g_slice_new0 (GstUri)); + + if (uri) + gst_mini_object_init (GST_MINI_OBJECT_CAST (uri), 0, gst_uri_get_type (), + (GstMiniObjectCopyFunction) _gst_uri_copy, NULL, + (GstMiniObjectFreeFunction) _gst_uri_free); + + return uri; +} + +static void +_gst_uri_free (GstUri * uri) +{ + g_return_if_fail (GST_IS_URI (uri)); + + g_free (uri->scheme); + g_free (uri->userinfo); + g_free (uri->host); + g_list_free_full (uri->path, g_free); + if (uri->query) + g_hash_table_unref (uri->query); + g_free (uri->fragment); + + g_slice_free1 (sizeof (*uri), uri); +} + +static GHashTable * +_gst_uri_copy_query_table (GHashTable * orig) +{ + GHashTable *new = NULL; + + if (orig != NULL) { + GHashTableIter iter; + gpointer key, value; + new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + g_hash_table_iter_init (&iter, orig); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_hash_table_insert (new, g_strdup (key), g_strdup (value)); + } + } + + return new; +} + +static GstUri * +_gst_uri_copy (const GstUri * orig_uri) +{ + GstUri *new_uri; + + g_return_val_if_fail (GST_IS_URI (orig_uri), NULL); + + new_uri = _gst_uri_new (); + + if (new_uri) { + new_uri->scheme = g_strdup (orig_uri->scheme); + new_uri->userinfo = g_strdup (orig_uri->userinfo); + new_uri->host = g_strdup (orig_uri->host); + new_uri->port = orig_uri->port; + new_uri->path = g_list_copy_deep (orig_uri->path, (GCopyFunc) g_strdup, + NULL); + new_uri->query = _gst_uri_copy_query_table (orig_uri->query); + new_uri->fragment = g_strdup (orig_uri->fragment); + } + + return new_uri; +} + +/* + * _gst_uri_compare_lists: + * + * Compare two lists for equality. This compares the two lists, item for item, + * comparing items in the same position in the two lists. If @first is + * considered less than @second the result will be negative. If @first is + * considered to be more than @second then the result will be positive. If the + * lists are considered to be equal then the result will be 0. If two lists + * have the same items, but one list is shorter than the other, then the + * shorter list is considered to be less than the longer list. + */ +static gint +_gst_uri_compare_lists (GList * first, GList * second, GCompareFunc cmp_fn) +{ + GList *itr1, *itr2; + gint result; + + for (itr1 = first, itr2 = second; + itr1 != NULL || itr2 != NULL; itr1 = itr1->next, itr2 = itr2->next) { + if (itr1 == NULL) + return -1; + if (itr2 == NULL) + return 1; + result = cmp_fn (itr1->data, itr2->data); + if (result != 0) + return result; + } + return 0; +} + +typedef enum +{ + _GST_URI_NORMALIZE_LOWERCASE = 1, + _GST_URI_NORMALIZE_UPPERCASE = 2 +} _GstUriNormalizations; + +/* + * Find the first character that hasn't been normalized according to the @flags. + */ +static gchar * +_gst_uri_first_non_normalized_char (gchar * str, guint flags) +{ + gchar *pos; + + if (str == NULL) + return NULL; + + for (pos = str; *pos; pos++) { + if ((flags & _GST_URI_NORMALIZE_UPPERCASE) && g_ascii_islower (*pos)) + return pos; + if ((flags & _GST_URI_NORMALIZE_LOWERCASE) && g_ascii_isupper (*pos)) + return pos; + } + return NULL; +} + +static gboolean +_gst_uri_normalize_lowercase (gchar * str) +{ + gchar *pos; + gboolean ret = FALSE; + + for (pos = _gst_uri_first_non_normalized_char (str, + _GST_URI_NORMALIZE_LOWERCASE); + pos != NULL; + pos = _gst_uri_first_non_normalized_char (pos + 1, + _GST_URI_NORMALIZE_LOWERCASE)) { + *pos = g_ascii_tolower (*pos); + ret = TRUE; + } + + return ret; +} + +#define _gst_uri_normalize_scheme _gst_uri_normalize_lowercase +#define _gst_uri_normalize_hostname _gst_uri_normalize_lowercase + +static gboolean +_gst_uri_normalize_path (GList ** path) +{ + GList *new_path; + + new_path = _remove_dot_segments (*path); + if (_gst_uri_compare_lists (new_path, *path, (GCompareFunc) g_strcmp0) != 0) { + g_list_free_full (*path, g_free); + *path = new_path; + return TRUE; + } + g_list_free_full (new_path, g_free); + + return FALSE; +} + +static gboolean +_gst_uri_normalize_str_noop (gchar * str) +{ + return FALSE; +} + +static gboolean +_gst_uri_normalize_table_noop (GHashTable * table) +{ + return FALSE; +} + +#define _gst_uri_normalize_userinfo _gst_uri_normalize_str_noop +#define _gst_uri_normalize_query _gst_uri_normalize_table_noop +#define _gst_uri_normalize_fragment _gst_uri_normalize_str_noop + +/* RFC 3986 functions */ + +static GList * +_merge (GList * base, GList * path) +{ + GList *ret, *path_copy, *last; + + path_copy = g_list_copy_deep (path, (GCopyFunc) g_strdup, NULL); + /* if base is NULL make path absolute */ + if (base == NULL) { + if (path_copy != NULL && path_copy->data != NULL) { + path_copy = g_list_prepend (path_copy, NULL); + } + return path_copy; + } + + ret = g_list_copy_deep (base, (GCopyFunc) g_strdup, NULL); + last = g_list_last (ret); + ret = g_list_remove_link (ret, last); + g_list_free_full (last, g_free); + ret = g_list_concat (ret, path_copy); + + return ret; +} + +static GList * +_remove_dot_segments (GList * path) +{ + GList *out, *elem, *next; + + if (path == NULL) + return NULL; + + out = g_list_copy_deep (path, (GCopyFunc) g_strdup, NULL); + + for (elem = out; elem; elem = next) { + next = elem->next; + if (elem->data == NULL && elem != out && next != NULL) { + out = g_list_delete_link (out, elem); + } else if (g_strcmp0 (elem->data, ".") == 0) { + g_free (elem->data); + out = g_list_delete_link (out, elem); + } else if (g_strcmp0 (elem->data, "..") == 0) { + GList *prev = g_list_previous (elem); + if (prev && (prev != out || prev->data != NULL)) { + g_free (prev->data); + out = g_list_delete_link (out, prev); + } + g_free (elem->data); + if (next != NULL) { + out = g_list_delete_link (out, elem); + } else { + /* path ends in '/..' We need to keep the last '/' */ + elem->data = NULL; + } + } + } + + return out; +} + +static gchar * +_gst_uri_escape_userinfo (const gchar * userinfo) +{ + return g_uri_escape_string (userinfo, + G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, FALSE); +} + +static gchar * +_gst_uri_escape_host (const gchar * host) +{ + return g_uri_escape_string (host, + G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, FALSE); +} + +static gchar * +_gst_uri_escape_host_colon (const gchar * host) +{ + return g_uri_escape_string (host, + G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":", FALSE); +} + +static gchar * +_gst_uri_escape_path_segment (const gchar * segment) +{ + return g_uri_escape_string (segment, + G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, FALSE); +} + +static gchar * +_gst_uri_escape_http_query_element (const gchar * element) +{ + gchar *ret, *c; + + ret = g_uri_escape_string (element, "!$'()*,;:@/? ", FALSE); + for (c = ret; *c; c++) + if (*c == ' ') + *c = '+'; + return ret; +} + +static gchar * +_gst_uri_escape_fragment (const gchar * fragment) +{ + return g_uri_escape_string (fragment, + G_URI_RESERVED_CHARS_ALLOWED_IN_PATH "?", FALSE); +} + +static GList * +_gst_uri_string_to_list (const gchar * str, const gchar * sep, gboolean convert, + gboolean unescape) +{ + GList *new_list = NULL; + + if (str) { + guint pct_sep_len = 0; + gchar *pct_sep = NULL; + gchar **split_str; + + if (convert && !unescape) { + pct_sep = g_strdup_printf ("%%%2.2X", (guint) (*sep)); + pct_sep_len = 3; + } + + split_str = g_strsplit (str, sep, -1); + if (split_str) { + gchar **next_elem; + for (next_elem = split_str; *next_elem; next_elem += 1) { + gchar *elem = *next_elem; + if (*elem == '\0') { + new_list = g_list_append (new_list, NULL); + } else { + if (convert && !unescape) { + gchar *next_sep; + for (next_sep = strcasestr (elem, pct_sep); next_sep; + next_sep = strcasestr (next_sep + 1, pct_sep)) { + *next_sep = *sep; + memmove (next_sep + 1, next_sep + pct_sep_len, + strlen (next_sep + pct_sep_len) + 1); + } + } + if (unescape) { + *next_elem = g_uri_unescape_string (elem, NULL); + g_free (elem); + elem = *next_elem; + } + new_list = g_list_append (new_list, g_strdup (elem)); + } + } + } + g_strfreev (split_str); + if (convert && !unescape) + g_free (pct_sep); + } + + return new_list; +} + +static GHashTable * +_gst_uri_string_to_table (const gchar * str, const gchar * part_sep, + const gchar * kv_sep, gboolean convert, gboolean unescape) +{ + GHashTable *new_table = NULL; + + if (str) { + gchar *pct_part_sep = NULL, *pct_kv_sep = NULL; + gchar **split_parts; + + new_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + if (convert && !unescape) { + pct_part_sep = g_strdup_printf ("%%%2.2X", (guint) (*part_sep)); + pct_kv_sep = g_strdup_printf ("%%%2.2X", (guint) (*kv_sep)); + } + + split_parts = g_strsplit (str, part_sep, -1); + if (split_parts) { + gchar **next_part; + for (next_part = split_parts; *next_part; next_part += 1) { + gchar *part = *next_part; + gchar *kv_sep_pos; + gchar *key, *value; + /* if we are converting percent encoded versions of separators then + * substitute the part separator now. */ + if (convert && !unescape) { + gchar *next_sep; + for (next_sep = strcasestr (part, pct_part_sep); next_sep; + next_sep = strcasestr (next_sep + 1, pct_part_sep)) { + *next_sep = *part_sep; + memmove (next_sep + 1, next_sep + 3, strlen (next_sep + 3) + 1); + } + } + /* find the key/value separator within the part */ + kv_sep_pos = g_strstr_len (part, -1, kv_sep); + if (kv_sep_pos == NULL) { + if (unescape) { + key = g_uri_unescape_string (part, NULL); + } else { + key = g_strdup (part); + } + value = NULL; + } else { + if (unescape) { + key = g_uri_unescape_segment (part, kv_sep_pos, NULL); + value = g_uri_unescape_string (kv_sep_pos + 1, NULL); + } else { + key = g_strndup (part, kv_sep_pos - part); + value = g_strdup (kv_sep_pos + 1); + } + } + /* if we are converting percent encoded versions of separators then + * substitute the key/value separator in both key and value now. */ + if (convert && !unescape) { + gchar *next_sep; + for (next_sep = strcasestr (key, pct_kv_sep); next_sep; + next_sep = strcasestr (next_sep + 1, pct_kv_sep)) { + *next_sep = *kv_sep; + memmove (next_sep + 1, next_sep + 3, strlen (next_sep + 3) + 1); + } + if (value) { + for (next_sep = strcasestr (value, pct_kv_sep); next_sep; + next_sep = strcasestr (next_sep + 1, pct_kv_sep)) { + *next_sep = *kv_sep; + memmove (next_sep + 1, next_sep + 3, strlen (next_sep + 3) + 1); + } + } + } + /* add value to the table */ + g_hash_table_insert (new_table, key, value); + } + } + /* tidy up */ + g_strfreev (split_parts); + if (convert && !unescape) { + g_free (pct_part_sep); + g_free (pct_kv_sep); + } + } + + return new_table; +} + + +/* + * Method definitions. + */ + +/** + * gst_uri_new: + * @scheme: (nullable): The scheme for the new URI. + * @userinfo: (nullable): The user-info for the new URI. + * @host: (nullable): The host name for the new URI. + * @port: The port number for the new URI or %GST_URI_NO_PORT. + * @path: (nullable): The path for the new URI with '/' separating path + * elements. + * @query: (nullable): The query string for the new URI with '&' separating + * query elements. Elements containing '&' characters + * should encode them as "%26". + * @fragment: (nullable): The fragment name for the new URI. + * + * Creates a new #GstUri object with the given URI parts. The path and query + * strings will be broken down into their elements. All strings should not be + * escaped except where indicated. + * + * Returns: (transfer full): A new #GstUri object. + * + * Since: 1.6 + */ +GstUri * +gst_uri_new (const gchar * scheme, const gchar * userinfo, const gchar * host, + guint port, const gchar * path, const gchar * query, const gchar * fragment) +{ + GstUri *new_uri; + + new_uri = _gst_uri_new (); + if (new_uri) { + new_uri->scheme = g_strdup (scheme); + new_uri->userinfo = g_strdup (userinfo); + new_uri->host = g_strdup (host); + new_uri->port = port; + new_uri->path = _gst_uri_string_to_list (path, "/", FALSE, FALSE); + new_uri->query = _gst_uri_string_to_table (query, "&", "=", TRUE, FALSE); + new_uri->fragment = g_strdup (fragment); + } + + return new_uri; +} + +/** + * gst_uri_new_with_base: + * @base: (transfer none)(nullable): The base URI to join the new URI to. + * @scheme: (nullable): The scheme for the new URI. + * @userinfo: (nullable): The user-info for the new URI. + * @host: (nullable): The host name for the new URI. + * @port: The port number for the new URI or %GST_URI_NO_PORT. + * @path: (nullable): The path for the new URI with '/' separating path + * elements. + * @query: (nullable): The query string for the new URI with '&' separating + * query elements. Elements containing '&' characters + * should encode them as "%26". + * @fragment: (nullable): The fragment name for the new URI. + * + * Like gst_uri_new(), but joins the new URI onto a base URI. + * + * Returns: (transfer full): The new URI joined onto @base. + * + * Since: 1.6 + */ +GstUri * +gst_uri_new_with_base (GstUri * base, const gchar * scheme, + const gchar * userinfo, const gchar * host, guint port, const gchar * path, + const gchar * query, const gchar * fragment) +{ + GstUri *new_rel_uri; + GstUri *new_uri; + + g_return_val_if_fail (base == NULL || GST_IS_URI (base), NULL); + + new_rel_uri = gst_uri_new (scheme, userinfo, host, port, path, query, + fragment); + new_uri = gst_uri_join (base, new_rel_uri); + gst_uri_unref (new_rel_uri); + + return new_uri; +} + +/** + * gst_uri_from_string: + * @uri: The URI string to parse. + * + * Parses a URI string into a new #GstUri object. Will return NULL if the URI + * cannot be parsed. + * + * Returns: (transfer full) (nullable): A new #GstUri object, or NULL. + * + * Since: 1.6 + */ +GstUri * +gst_uri_from_string (const gchar * uri) +{ + const gchar *orig_uri = uri; + GstUri *uri_obj; + + uri_obj = _gst_uri_new (); + + if (uri_obj && uri != NULL) { + int i = 0; + + /* be helpful and skip initial white space */ + while (*uri == '\v' || g_ascii_isspace (*uri)) + uri++; + + if (g_ascii_isalpha (uri[i])) { + /* find end of scheme name */ + i++; + while (g_ascii_isalnum (uri[i]) || uri[i] == '+' || uri[i] == '-' || + uri[i] == '.') + i++; + } + if (i > 0 && uri[i] == ':') { + /* get scheme */ + uri_obj->scheme = g_strndup (uri, i); + uri += i + 1; + } + if (uri[0] == '/' && uri[1] == '/') { + const gchar *eoa, *eoui, *eoh, *reoh; + /* get authority [userinfo@]host[:port] */ + uri += 2; + /* find end of authority */ + eoa = uri + strcspn (uri, "/?#"); + + /* find end of userinfo */ + eoui = strchr (uri, '@'); + if (eoui != NULL && eoui < eoa) { + uri_obj->userinfo = g_uri_unescape_segment (uri, eoui, NULL); + uri = eoui + 1; + } + /* find end of host */ + if (uri[0] == '[') { + eoh = strchr (uri, ']'); + if (eoh == NULL || eoh > eoa) { + GST_DEBUG ("Unable to parse the host part of the URI '%s'.", + orig_uri); + gst_uri_unref (uri_obj); + return NULL; + } + reoh = eoh + 1; + uri++; + } else { + reoh = eoh = strchr (uri, ':'); + if (eoh == NULL || eoh > eoa) + reoh = eoh = eoa; + } + /* don't capture empty host strings */ + if (eoh != uri) + uri_obj->host = g_uri_unescape_segment (uri, eoh, NULL); + + uri = reoh; + if (uri < eoa) { + /* if port number is malformed then we can't parse this */ + if (uri[0] != ':' || strspn (uri + 1, "0123456789") != eoa - uri - 1) { + GST_DEBUG ("Unable to parse host/port part of the URI '%s'.", + orig_uri); + gst_uri_unref (uri_obj); + return NULL; + } + /* otherwise treat port as unsigned decimal number */ + uri++; + while (uri < eoa) { + uri_obj->port = uri_obj->port * 10 + g_ascii_digit_value (*uri); + uri++; + } + } + uri = eoa; + } + if (uri != NULL && uri[0] != '\0') { + /* get path */ + size_t len; + len = strcspn (uri, "?#"); + if (uri[len] == '\0') { + uri_obj->path = _gst_uri_string_to_list (uri, "/", FALSE, TRUE); + uri = NULL; + } else { + if (len > 0) { + gchar *path_str = g_strndup (uri, len); + uri_obj->path = _gst_uri_string_to_list (path_str, "/", FALSE, TRUE); + g_free (path_str); + } + uri += len; + } + } + if (uri != NULL && uri[0] == '?') { + /* get query */ + gchar *eoq; + eoq = strchr (++uri, '#'); + if (eoq == NULL) { + uri_obj->query = _gst_uri_string_to_table (uri, "&", "=", TRUE, TRUE); + uri = NULL; + } else { + if (eoq != uri) { + gchar *query_str = g_strndup (uri, eoq - uri); + uri_obj->query = _gst_uri_string_to_table (query_str, "&", "=", TRUE, + TRUE); + g_free (query_str); + } + uri = eoq; + } + } + if (uri != NULL && uri[0] == '#') { + uri_obj->fragment = g_uri_unescape_string (uri + 1, NULL); + } + } + + return uri_obj; +} + +/** + * gst_uri_from_string_with_base: + * @base: (transfer none)(nullable): The base URI to join the new URI with. + * @uri: The URI string to parse. + * + * Like gst_uri_from_string() but also joins with a base URI. + * + * Returns: (transfer full): A new #GstUri object. + * + * Since: 1.6 + */ +GstUri * +gst_uri_from_string_with_base (GstUri * base, const gchar * uri) +{ + GstUri *new_rel_uri; + GstUri *new_uri; + + g_return_val_if_fail (base == NULL || GST_IS_URI (base), NULL); + + new_rel_uri = gst_uri_from_string (uri); + new_uri = gst_uri_join (base, new_rel_uri); + gst_uri_unref (new_rel_uri); + + return new_uri; +} + +/** + * gst_uri_equal: + * @first: First #GstUri to compare. + * @second: Second #GstUri to compare. + * + * Compares two #GstUri objects to see if they represent the same normalized + * URI. + * + * Returns: %TRUE if the normalized versions of the two URI's would be equal. + * + * Since: 1.6 + */ +gboolean +gst_uri_equal (const GstUri * first, const GstUri * second) +{ + gchar *first_norm = NULL, *second_norm = NULL; + GList *first_norm_list = NULL, *second_norm_list = NULL; + const gchar *first_cmp, *second_cmp; + GHashTableIter table_iter; + gpointer key, value; + int result; + + g_return_val_if_fail ((first == NULL || GST_IS_URI (first)) && + (second == NULL || GST_IS_URI (second)), FALSE); + + if (first == second) + return TRUE; + + if (first == NULL || second == NULL) + return FALSE; + + if (first->port != second->port) + return FALSE; + +/* work out a version of field value (normalized or not) to compare. + * first_cmp, second_cmp will be the values to compare later. + * first_norm, second_norm will be non-NULL if normalized versions are used, + * and need to be freed later. + */ +#define GST_URI_NORMALIZED_FIELD(pos, field, norm_fn, flags) \ + pos##_cmp = pos->field; \ + if (_gst_uri_first_non_normalized_char ((gchar*)pos##_cmp, flags) != NULL) { \ + pos##_norm = g_strdup (pos##_cmp); \ + norm_fn (pos##_norm); \ + pos##_cmp = pos##_norm; \ + } + +/* compare two string values, normalizing if needed */ +#define GST_URI_NORMALIZED_CMP_STR(field, norm_fn, flags) \ + GST_URI_NORMALIZED_FIELD (first, field, norm_fn, flags) \ + GST_URI_NORMALIZED_FIELD (second, field, norm_fn, flags) \ + result = g_strcmp0 (first_cmp, second_cmp); \ + g_free (first_norm); \ + first_norm = NULL; \ + g_free (second_norm); \ + second_norm = NULL; \ + if (result != 0) return FALSE + +/* compare two string values */ +#define GST_URI_CMP_STR(field) \ + if (g_strcmp0 (first->field, second->field) != 0) return FALSE + +/* compare two GLists, normalize lists if needed before comparison */ +#define GST_URI_NORMALIZED_CMP_LIST(field, norm_fn, copy_fn, cmp_fn, free_fn) \ + first_norm_list = g_list_copy_deep (first->field, (GCopyFunc) copy_fn, NULL); \ + norm_fn (&first_norm_list); \ + second_norm_list = g_list_copy_deep (second->field, (GCopyFunc) copy_fn, NULL); \ + norm_fn (&second_norm_list); \ + result = _gst_uri_compare_lists (first_norm_list, second_norm_list, (GCompareFunc) cmp_fn); \ + g_list_free_full (first_norm_list, free_fn); \ + g_list_free_full (second_norm_list, free_fn); \ + if (result != 0) return FALSE + + GST_URI_CMP_STR (userinfo); + + GST_URI_CMP_STR (fragment); + + GST_URI_NORMALIZED_CMP_STR (scheme, _gst_uri_normalize_scheme, + _GST_URI_NORMALIZE_LOWERCASE); + + GST_URI_NORMALIZED_CMP_STR (host, _gst_uri_normalize_hostname, + _GST_URI_NORMALIZE_LOWERCASE); + + GST_URI_NORMALIZED_CMP_LIST (path, _gst_uri_normalize_path, g_strdup, + g_strcmp0, g_free); + + if (first->query == NULL && second->query != NULL) + return FALSE; + if (first->query != NULL && second->query == NULL) + return FALSE; + if (first->query != NULL) { + if (g_hash_table_size (first->query) != g_hash_table_size (second->query)) + return FALSE; + + g_hash_table_iter_init (&table_iter, first->query); + while (g_hash_table_iter_next (&table_iter, &key, &value)) { + if (!g_hash_table_contains (second->query, key)) + return FALSE; + result = g_strcmp0 (g_hash_table_lookup (second->query, key), value); + if (result != 0) + return FALSE; + } + } +#undef GST_URI_NORMALIZED_CMP_STR +#undef GST_URI_CMP_STR +#undef GST_URI_NORMALIZED_CMP_LIST +#undef GST_URI_NORMALIZED_FIELD + + return TRUE; +} + +/** + * gst_uri_join: + * @base_uri: (transfer none) (nullable): The base URI to join another to. + * @ref_uri: (transfer none) (nullable): The reference URI to join onto the + * base URI. + * + * Join a reference URI onto a base URI using the method from RFC 3986. + * If either URI is %NULL then the other URI will be returned with the ref count + * increased. + * + * Returns: (transfer full) (nullable): A #GstUri which represents the base + * with the reference URI joined on. + * + * Since: 1.6 + */ +GstUri * +gst_uri_join (GstUri * base_uri, GstUri * ref_uri) +{ + const gchar *r_scheme; + GstUri *t; + + g_return_val_if_fail ((base_uri == NULL || GST_IS_URI (base_uri)) && + (ref_uri == NULL || GST_IS_URI (ref_uri)), NULL); + + if (base_uri == NULL && ref_uri == NULL) + return NULL; + if (base_uri == NULL) { + g_return_val_if_fail (GST_IS_URI (ref_uri), NULL); + return gst_uri_ref (ref_uri); + } + if (ref_uri == NULL) { + g_return_val_if_fail (GST_IS_URI (base_uri), NULL); + return gst_uri_ref (base_uri); + } + + g_return_val_if_fail (GST_IS_URI (base_uri) && GST_IS_URI (ref_uri), NULL); + + t = _gst_uri_new (); + + if (t == NULL) + return t; + + /* process according to RFC3986 */ + r_scheme = ref_uri->scheme; + if (r_scheme != NULL && g_strcmp0 (base_uri->scheme, r_scheme) == 0) { + r_scheme = NULL; + } + if (r_scheme != NULL) { + t->scheme = g_strdup (r_scheme); + t->userinfo = g_strdup (ref_uri->userinfo); + t->host = g_strdup (ref_uri->host); + t->port = ref_uri->port; + t->path = _remove_dot_segments (ref_uri->path); + t->query = _gst_uri_copy_query_table (ref_uri->query); + } else { + if (ref_uri->host != NULL) { + t->userinfo = g_strdup (ref_uri->userinfo); + t->host = g_strdup (ref_uri->host); + t->port = ref_uri->port; + t->path = _remove_dot_segments (ref_uri->path); + t->query = _gst_uri_copy_query_table (ref_uri->query); + } else { + if (ref_uri->path == NULL) { + t->path = g_list_copy_deep (base_uri->path, (GCopyFunc) g_strdup, NULL); + if (ref_uri->query != NULL) + t->query = _gst_uri_copy_query_table (ref_uri->query); + else + t->query = _gst_uri_copy_query_table (base_uri->query); + } else { + if (ref_uri->path->data == NULL) + t->path = _remove_dot_segments (ref_uri->path); + else { + GList *mrgd = _merge (base_uri->path, ref_uri->path); + t->path = _remove_dot_segments (mrgd); + g_list_free_full (mrgd, g_free); + } + t->query = _gst_uri_copy_query_table (ref_uri->query); + } + t->userinfo = g_strdup (base_uri->userinfo); + t->host = g_strdup (base_uri->host); + t->port = base_uri->port; + } + t->scheme = g_strdup (base_uri->scheme); + } + t->fragment = g_strdup (ref_uri->fragment); + + return t; +} + +/** + * gst_uri_join_strings: + * @base_uri: The percent-encoded base URI. + * @ref_uri: The percent-encoded reference URI to join to the @base_uri. + * + * This is a convenience function to join two URI strings and return the result. + * The returned string should be g_free()'d after use. + * + * Returns: (transfer full): A string representing the percent-encoded join of + * the two URIs. + * + * Since: 1.6 + */ +gchar * +gst_uri_join_strings (const gchar * base_uri, const gchar * ref_uri) +{ + GstUri *base, *result; + gchar *result_uri; + + base = gst_uri_from_string (base_uri); + result = gst_uri_from_string_with_base (base, ref_uri); + result_uri = gst_uri_to_string (result); + gst_uri_unref (base); + gst_uri_unref (result); + + return result_uri; +} + +/** + * gst_uri_is_writable: + * @uri: The #GstUri object to test. + * + * Check if it is safe to write to this #GstUri. + * + * Check if the refcount of @uri is exactly 1, meaning that no other + * reference exists to the #GstUri and that the #GstUri is therefore writable. + * + * Modification of a #GstUri should only be done after verifying that it is + * writable. + * + * Returns: %TRUE if it is safe to write to the object. + * + * Since: 1.6 + */ +gboolean +gst_uri_is_writable (const GstUri * uri) +{ + g_return_val_if_fail (GST_IS_URI (uri), FALSE); + return gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (uri)); +} + +/** + * gst_uri_make_writable: + * @uri: (transfer full): The #GstUri object to make writable. + * + * Make the #GstUri writable. + * + * Checks if @uri is writable, and if so the original object is returned. If + * not, then a writable copy is made and returned. This gives away the + * reference to @uri and returns a reference to the new #GstUri. + * If @uri is %NULL then %NULL is returned. + * + * Returns: (transfer full): A writable version of @uri. + * + * Since: 1.6 + */ +GstUri * +gst_uri_make_writable (GstUri * uri) +{ + g_return_val_if_fail (GST_IS_URI (uri), NULL); + return + GST_URI_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (uri))); +} + +/** + * gst_uri_to_string: + * @uri: This #GstUri to convert to a string. + * + * Convert the URI to a string. + * + * Returns the URI as held in this object as a #gchar* nul-terminated string. + * The caller should g_free() the string once they are finished with it. + * The string is put together as described in RFC 3986. + * + * Returns: (transfer full): The string version of the URI. + * + * Since: 1.6 + */ +gchar * +gst_uri_to_string (const GstUri * uri) +{ + GString *uri_str; + gchar *escaped; + + g_return_val_if_fail (GST_IS_URI (uri), NULL); + + uri_str = g_string_new (NULL); + + if (uri->scheme != NULL) + g_string_append_printf (uri_str, "%s:", uri->scheme); + + if (uri->userinfo != NULL || uri->host != NULL || + uri->port != GST_URI_NO_PORT) + g_string_append (uri_str, "//"); + + if (uri->userinfo != NULL) { + escaped = _gst_uri_escape_userinfo (uri->userinfo); + g_string_append_printf (uri_str, "%s@", escaped); + g_free (escaped); + } + + if (uri->host != NULL) { + if (strchr (uri->host, ':') != NULL) { + escaped = _gst_uri_escape_host_colon (uri->host); + g_string_append_printf (uri_str, "[%s]", escaped); + g_free (escaped); + } else { + escaped = _gst_uri_escape_host (uri->host); + g_string_append (uri_str, escaped); + g_free (escaped); + } + } + + if (uri->port != GST_URI_NO_PORT) + g_string_append_printf (uri_str, ":%u", uri->port); + + if (uri->path != NULL) { + escaped = gst_uri_get_path_string (uri); + g_string_append (uri_str, escaped); + g_free (escaped); + } + + if (uri->query) { + g_string_append (uri_str, "?"); + escaped = gst_uri_get_query_string (uri); + g_string_append (uri_str, escaped); + g_free (escaped); + } + + if (uri->fragment != NULL) { + escaped = _gst_uri_escape_fragment (uri->fragment); + g_string_append_printf (uri_str, "#%s", escaped); + g_free (escaped); + } + + return g_string_free (uri_str, FALSE); +} + +/** + * gst_uri_is_normalized: + * @uri: The #GstUri to test to see if it is normalized. + * + * Tests the @uri to see if it is normalized. A %NULL @uri is considered to be + * normalized. + * + * Returns: TRUE if the URI is normalized or is %NULL. + * + * Since: 1.6 + */ +gboolean +gst_uri_is_normalized (const GstUri * uri) +{ + GList *new_path; + gboolean ret; + + if (uri == NULL) + return TRUE; + + g_return_val_if_fail (GST_IS_URI (uri), FALSE); + + /* check for non-normalized characters in uri parts */ + if (_gst_uri_first_non_normalized_char (uri->scheme, + _GST_URI_NORMALIZE_LOWERCASE) != NULL || + /*_gst_uri_first_non_normalized_char (uri->userinfo, + _GST_URI_NORMALIZE_PERCENTAGES) != NULL || */ + _gst_uri_first_non_normalized_char (uri->host, + _GST_URI_NORMALIZE_LOWERCASE /*| _GST_URI_NORMALIZE_PERCENTAGES */ ) + != NULL + /*|| _gst_uri_first_non_normalized_char (uri->path, + _GST_URI_NORMALIZE_PERCENTAGES) != NULL + || _gst_uri_first_non_normalized_char (uri->query, + _GST_URI_NORMALIZE_PERCENTAGES) != NULL + || _gst_uri_first_non_normalized_char (uri->fragment, + _GST_URI_NORMALIZE_PERCENTAGES) != NULL */ ) + return FALSE; + + /* also check path has had dot segments removed */ + new_path = _remove_dot_segments (uri->path); + ret = + (_gst_uri_compare_lists (new_path, uri->path, + (GCompareFunc) g_strcmp0) == 0); + g_list_free_full (new_path, g_free); + return ret; +} + +/** + * gst_uri_normalize: + * @uri: (transfer none): The #GstUri to normalize. + * + * Normalization will remove extra path segments ("." and "..") from the URI. It + * will also convert the scheme and host name to lower case and any + * percent-encoded values to uppercase. + * + * The #GstUri object must be writable. Check with gst_uri_is_writable() or use + * gst_uri_make_writable() first. + * + * Returns: TRUE if the URI was modified. + * + * Since: 1.6 + */ +gboolean +gst_uri_normalize (GstUri * uri) +{ + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + return _gst_uri_normalize_scheme (uri->scheme) | + _gst_uri_normalize_userinfo (uri->userinfo) | + _gst_uri_normalize_hostname (uri->host) | + _gst_uri_normalize_path (&uri->path) | + _gst_uri_normalize_query (uri->query) | + _gst_uri_normalize_fragment (uri->fragment); +} + +/** + * gst_uri_get_scheme: + * @uri: (nullable): This #GstUri object. + * + * Get the scheme name from the URI or %NULL if it doesn't exist. + * If @uri is %NULL then returns %NULL. + * + * Returns: (nullable): The scheme from the #GstUri object or %NULL. + */ +const gchar * +gst_uri_get_scheme (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + return (uri ? uri->scheme : NULL); +} + +/** + * gst_uri_set_scheme: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @scheme: The new scheme to set or %NULL to unset the scheme. + * + * Set or unset the scheme for the URI. + * + * Returns: %TRUE if the scheme was set/unset successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_scheme (GstUri * uri, const gchar * scheme) +{ + if (!uri) + return scheme == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_free (uri->scheme); + uri->scheme = g_strdup (scheme); + + return TRUE; +} + +/** + * gst_uri_get_userinfo: + * @uri: (nullable): This #GstUri object. + * + * Get the userinfo (usually in the form "username:password") from the URI + * or %NULL if it doesn't exist. If @uri is %NULL then returns %NULL. + * + * Returns: (nullable): The userinfo from the #GstUri object or %NULL. + * + * Since: 1.6 + */ +const gchar * +gst_uri_get_userinfo (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + return (uri ? uri->userinfo : NULL); +} + +/** + * gst_uri_set_userinfo: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @userinfo: The new user-information string to set or %NULL to unset. + * + * Set or unset the user information for the URI. + * + * Returns: %TRUE if the user information was set/unset successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_userinfo (GstUri * uri, const gchar * userinfo) +{ + if (!uri) + return userinfo == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_free (uri->userinfo); + uri->userinfo = g_strdup (userinfo); + + return TRUE; +} + +/** + * gst_uri_get_host: + * @uri: (nullable): This #GstUri object. + * + * Get the host name from the URI or %NULL if it doesn't exist. + * If @uri is %NULL then returns %NULL. + * + * Returns: (nullable): The host name from the #GstUri object or %NULL. + * + * Since: 1.6 + */ +const gchar * +gst_uri_get_host (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + return (uri ? uri->host : NULL); +} + +/** + * gst_uri_set_host: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @host: The new host string to set or %NULL to unset. + * + * Set or unset the host for the URI. + * + * Returns: %TRUE if the host was set/unset successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_host (GstUri * uri, const gchar * host) +{ + if (!uri) + return host == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_free (uri->host); + uri->host = g_strdup (host); + + return TRUE; +} + +/** + * gst_uri_get_port: + * @uri: (nullable): This #GstUri object. + * + * Get the port number from the URI or %GST_URI_NO_PORT if it doesn't exist. + * If @uri is %NULL then returns %GST_URI_NO_PORT. + * + * Returns: The port number from the #GstUri object or %GST_URI_NO_PORT. + * + * Since: 1.6 + */ +guint +gst_uri_get_port (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), GST_URI_NO_PORT); + return (uri ? uri->port : GST_URI_NO_PORT); +} + +/** + * gst_uri_set_port: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @port: The new port number to set or %GST_URI_NO_PORT to unset. + * + * Set or unset the port number for the URI. + * + * Returns: %TRUE if the port number was set/unset successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_port (GstUri * uri, guint port) +{ + if (!uri) + return port == GST_URI_NO_PORT; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + uri->port = port; + + return TRUE; +} + +/** + * gst_uri_get_path: + * @uri: The #GstUri to get the path from. + * + * Extract the path string from the URI object. + * + * Returns: (transfer full): (nullable): The path from the URI. Once finished + * with the string should be g_free()'d. + * + * Since: 1.6 + */ +gchar * +gst_uri_get_path (const GstUri * uri) +{ + GList *path_segment; + const gchar *sep = ""; + GString *ret; + + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->path) + return NULL; + + ret = g_string_new (NULL); + + for (path_segment = uri->path; path_segment; + path_segment = path_segment->next) { + g_string_append (ret, sep); + if (path_segment->data) { + g_string_append (ret, path_segment->data); + } + sep = "/"; + } + + return g_string_free (ret, FALSE); +} + +/** + * gst_uri_set_path: + * @uri: (transfer none) (nullable): The #GstUri to modify. + * @path: The new path to set with path segments separated by '/', or use %NULL + * to unset the path. + * + * Sets or unsets the path in the URI. + * + * Returns: %TRUE if the path was set successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_path (GstUri * uri, const gchar * path) +{ + if (!uri) + return path == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_list_free_full (uri->path, g_free); + uri->path = _gst_uri_string_to_list (path, "/", FALSE, FALSE); + + return TRUE; +} + +/** + * gst_uri_get_path_string: + * @uri: The #GstUri to get the path from. + * + * Extract the path string from the URI object as a percent encoded URI path. + * + * Returns: (transfer full) (nullable): The path from the URI. Once finished + * with the string should be g_free()'d. + * + * Since: 1.6 + */ +gchar * +gst_uri_get_path_string (const GstUri * uri) +{ + GList *path_segment; + const gchar *sep = ""; + GString *ret; + gchar *escaped; + + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->path) + return NULL; + + ret = g_string_new (NULL); + + for (path_segment = uri->path; path_segment; + path_segment = path_segment->next) { + g_string_append (ret, sep); + if (path_segment->data) { + escaped = _gst_uri_escape_path_segment (path_segment->data); + g_string_append (ret, escaped); + g_free (escaped); + } + sep = "/"; + } + + return g_string_free (ret, FALSE); +} + +/** + * gst_uri_set_path_string: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @path: The new percent encoded path to set with path segments separated by + * '/', or use %NULL to unset the path. + * + * Sets or unsets the path in the URI. + * + * Returns: %TRUE if the path was set successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_path_string (GstUri * uri, const gchar * path) +{ + if (!uri) + return path == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_list_free_full (uri->path, g_free); + uri->path = _gst_uri_string_to_list (path, "/", FALSE, TRUE); + return TRUE; +} + +/** + * gst_uri_get_path_segments: + * @uri: (nullable): The #GstUri to get the path from. + * + * Get a list of path segments from the URI. + * + * Returns: (transfer full) (element-type gchar*): A #GList of path segment + * strings or %NULL if no path segments are available. Free the list + * when no longer needed with g_list_free_full(list, g_free). + * + * Since: 1.6 + */ +GList * +gst_uri_get_path_segments (const GstUri * uri) +{ + GList *ret = NULL; + + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + + if (uri) { + ret = g_list_copy_deep (uri->path, (GCopyFunc) g_strdup, NULL); + } + + return ret; +} + +/** + * gst_uri_set_path_segments: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @path_segments: (transfer full)(nullable)(element-type gchar*): The new + * path list to set. + * + * Replace the path segments list in the URI. + * + * Returns: %TRUE if the path segments were set successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_path_segments (GstUri * uri, GList * path_segments) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), FALSE); + + if (!uri) { + if (path_segments) + g_list_free_full (path_segments, g_free); + return path_segments == NULL; + } + + g_return_val_if_fail (gst_uri_is_writable (uri), FALSE); + + g_list_free_full (uri->path, g_free); + uri->path = path_segments; + return TRUE; +} + +/** + * gst_uri_append_path: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @relative_path: Relative path to append to the end of the current path. + * + * Append a path onto the end of the path in the URI. The path is not + * normalized, call #gst_uri_normalize() to normalize the path. + * + * Returns: %TRUE if the path was appended successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_append_path (GstUri * uri, const gchar * relative_path) +{ + GList *rel_path_list; + + if (!uri) + return relative_path == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + if (!relative_path) + return TRUE; + + if (uri->path) { + GList *last_elem = g_list_last (uri->path); + if (last_elem->data == NULL) { + uri->path = g_list_delete_link (uri->path, last_elem); + } + } + rel_path_list = _gst_uri_string_to_list (relative_path, "/", FALSE, FALSE); + /* if path was absolute, make it relative by removing initial NULL element */ + if (rel_path_list && rel_path_list->data == NULL) { + rel_path_list = g_list_delete_link (rel_path_list, rel_path_list); + } + uri->path = g_list_concat (uri->path, rel_path_list); + return TRUE; +} + +/** + * gst_uri_append_path_segment: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @path_segment: The path segment string to append to the URI path. + * + * Append a single path segment onto the end of the URI path. + * + * Returns: %TRUE if the path was appended successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_append_path_segment (GstUri * uri, const gchar * path_segment) +{ + if (!uri) + return path_segment == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + if (!path_segment) + return TRUE; + + /* if base path ends in a directory (i.e. last element is NULL), remove it */ + if (uri->path && g_list_last (uri->path)->data == NULL) { + uri->path = g_list_delete_link (uri->path, g_list_last (uri->path)); + } + uri->path = g_list_append (uri->path, g_strdup (path_segment)); + return TRUE; +} + +/** + * gst_uri_get_query_string: + * @uri: (nullable): The #GstUri to get the query string from. + * + * Get a percent encoded URI query string from the @uri. + * + * Returns: (transfer full) (nullable): A percent encoded query string. Use + * g_free() when no longer needed. + * + * Since: 1.6 + */ +gchar * +gst_uri_get_query_string (const GstUri * uri) +{ + GHashTableIter iter; + gpointer key, value; + const gchar *sep = ""; + gchar *escaped; + GString *ret; + + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->query) + return NULL; + + ret = g_string_new (NULL); + g_hash_table_iter_init (&iter, uri->query); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_string_append (ret, sep); + escaped = _gst_uri_escape_http_query_element (key); + g_string_append (ret, escaped); + g_free (escaped); + if (value) { + escaped = _gst_uri_escape_http_query_element (value); + g_string_append_printf (ret, "=%s", escaped); + g_free (escaped); + } + sep = "&"; + } + + return g_string_free (ret, FALSE); +} + +/** + * gst_uri_set_query_string: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @query: The new percent encoded query string to use to populate the query + * table, or use %NULL to unset the query table. + * + * Sets or unsets the query table in the URI. + * + * Returns: %TRUE if the query table was set successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_query_string (GstUri * uri, const gchar * query) +{ + if (!uri) + return query == NULL; + + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + if (uri->query) + g_hash_table_unref (uri->query); + uri->query = _gst_uri_string_to_table (query, "&", "=", TRUE, TRUE); + + return TRUE; +} + +/** + * gst_uri_get_query_table: + * @uri: (nullable): The #GstUri to get the query table from. + * + * Get the query table from the URI. Keys and values in the table are freed + * with g_free when they are deleted. A value may be %NULL to indicate that + * the key should appear in the query string in the URI, but does not have a + * value. Free the returned #GHashTable with #g_hash_table_unref() when it is + * no longer required. Modifying this hash table will modify the query in the + * URI. + * + * Returns: (transfer full) (element-type gchar* gchar*) (nullable): The query + * hash table from the URI. + * + * Since: 1.6 + */ +GHashTable * +gst_uri_get_query_table (const GstUri * uri) +{ + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->query) + return NULL; + + return g_hash_table_ref (uri->query); +} + +/** + * gst_uri_set_query_table: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @query_table: (transfer none)(nullable)(element-type gchar* gchar*): The new + * query table to use. + * + * Set the query table to use in the URI. The old table is unreferenced and a + * reference to the new one is used instead. A value if %NULL for @query_table + * will remove the query string from the URI. + * + * Returns: %TRUE if the new table was sucessfully used for the query table. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_query_table (GstUri * uri, GHashTable * query_table) +{ + GHashTable *old_table = NULL; + + if (!uri) + return query_table == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + old_table = uri->query; + if (query_table) + uri->query = g_hash_table_ref (query_table); + else + uri->query = NULL; + if (old_table) + g_hash_table_unref (old_table); + + return TRUE; +} + +/** + * gst_uri_set_query_value: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @query_key: (transfer none): The key for the query entry. + * @query_value: (transfer none)(nullable): The value for the key. + * + * This inserts or replaces a key in the query table. A @query_value of %NULL + * indicates that the key has no associated value, but will still be present in + * the query string. + * + * Returns: %TRUE if the query table was sucessfully updated. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_query_value (GstUri * uri, const gchar * query_key, + const gchar * query_value) +{ + if (!uri) + return FALSE; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + if (!uri->query) { + uri->query = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + g_free); + } + g_hash_table_insert (uri->query, g_strdup (query_key), + g_strdup (query_value)); + + return TRUE; +} + +/** + * gst_uri_remove_query_key: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @query_key: The key to remove. + * + * Remove an entry from the query table by key. + * + * Returns: %TRUE if the key existed in the table and was removed. + * + * Since: 1.6 + */ +gboolean +gst_uri_remove_query_key (GstUri * uri, const gchar * query_key) +{ + gboolean result; + + if (!uri) + return FALSE; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + if (!uri->query) + return FALSE; + + result = g_hash_table_remove (uri->query, query_key); + /* if this was the last query entry, remove the query string completely */ + if (result && g_hash_table_size (uri->query) == 0) { + g_hash_table_unref (uri->query); + uri->query = NULL; + } + return result; +} + +/** + * gst_uri_query_has_key: + * @uri: (nullable): The #GstUri to examine. + * @query_key: The key to lookup. + * + * Check if there is a query table entry for the @query_key key. + * + * Returns: %TRUE if @query_key exists in the URI query table. + * + * Since: 1.6 + */ +gboolean +gst_uri_query_has_key (const GstUri * uri, const gchar * query_key) +{ + if (!uri) + return FALSE; + g_return_val_if_fail (GST_IS_URI (uri), FALSE); + if (!uri->query) + return FALSE; + + return g_hash_table_contains (uri->query, query_key); +} + +/** + * gst_uri_get_query_value: + * @uri: (nullable): The #GstUri to examine. + * @query_key: The key to lookup. + * + * Get the value associated with the @query_key key. Will return %NULL if the + * key has no value or if the key does not exist in the URI query table. Because + * %NULL is returned for both missing keys and keys with no value, you should + * use gst_uri_query_has_key() to determine if a key is present in the URI + * query. + * + * Returns: (nullable): The value for the given key, or %NULL if not found. + * + * Since: 1.6 + */ +const gchar * +gst_uri_get_query_value (const GstUri * uri, const gchar * query_key) +{ + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->query) + return NULL; + + return g_hash_table_lookup (uri->query, query_key); +} + +/** + * gst_uri_get_query_keys: + * @uri: (nullable): The #GstUri to examine. + * + * Get a list of the query keys from the URI. + * + * Returns: (transfer container) (element-type gchar*): A list of keys from + * the URI query. Free the list with g_list_free(). + * + * Since: 1.6 + */ +GList * +gst_uri_get_query_keys (const GstUri * uri) +{ + if (!uri) + return NULL; + g_return_val_if_fail (GST_IS_URI (uri), NULL); + if (!uri->query) + return NULL; + + return g_hash_table_get_keys (uri->query); +} + +/** + * gst_uri_get_fragment: + * @uri: (nullable): This #GstUri object. + * + * Get the fragment name from the URI or %NULL if it doesn't exist. + * If @uri is %NULL then returns %NULL. + * + * Returns: (nullable): The host name from the #GstUri object or %NULL. + * + * Since: 1.6 + */ +const gchar * +gst_uri_get_fragment (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + return (uri ? uri->fragment : NULL); +} + +/** + * gst_uri_set_fragment: + * @uri: (transfer none)(nullable): The #GstUri to modify. + * @fragment: (nullable): The fragment string to set. + * + * Sets the fragment string in the URI. Use a value of %NULL in @fragment to + * unset the fragment string. + * + * Returns: %TRUE if the fragment was set/unset successfully. + * + * Since: 1.6 + */ +gboolean +gst_uri_set_fragment (GstUri * uri, const gchar * fragment) +{ + if (!uri) + return fragment == NULL; + g_return_val_if_fail (GST_IS_URI (uri) && gst_uri_is_writable (uri), FALSE); + + g_free (uri->fragment); + uri->fragment = g_strdup (fragment); + return TRUE; +} + +/** + * gst_uri_get_media_fragment_table: + * @uri: (nullable): The #GstUri to get the fragment table from. + * + * Get the media fragment table from the URI, as defined by "Media Fragments URI 1.0". + * Hash table returned by this API is a list of "key-value" pairs, and the each + * pair is generated by splitting "URI fragment" per "&" sub-delims, then "key" + * and "value" are splitted by "=" sub-delims. The "key" returned by this API may + * be undefined keyword by standard. + * A value may be %NULL to indicate that the key should appear in the fragment + * string in the URI, but does not have a value. Free the returned #GHashTable + * with #g_hash_table_unref() when it is no longer required. + * Modifying this hash table does not affect the fragment in the URI. + * + * See more about Media Fragments URI 1.0 (W3C) at https://www.w3.org/TR/media-frags/ + * + * Returns: (transfer full) (element-type gchar* gchar*) (nullable): The + * fragment hash table from the URI. + * + * Since: 1.12 + */ +GHashTable * +gst_uri_get_media_fragment_table (const GstUri * uri) +{ + g_return_val_if_fail (uri == NULL || GST_IS_URI (uri), NULL); + + if (!uri->fragment) + return NULL; + return _gst_uri_string_to_table (uri->fragment, "&", "=", TRUE, TRUE); +} diff --git a/gst/gsturi.h b/gst/gsturi.h new file mode 100644 index 0000000..75145f9 --- /dev/null +++ b/gst/gsturi.h @@ -0,0 +1,401 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2014 David Waring, British Broadcasting Corporation + * + * + * gsturi.h: Header for uri to element mappings and URI manipulation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_URI_H__ +#define __GST_URI_H__ + +#include +#include + +G_BEGIN_DECLS + +#include + +GST_API +GQuark gst_uri_error_quark (void); + +/** + * GST_URI_ERROR: + * + * Get access to the error quark of the uri subsystem. + */ +#define GST_URI_ERROR gst_uri_error_quark () + +/** + * GstURIError: + * @GST_URI_ERROR_UNSUPPORTED_PROTOCOL: The protocol is not supported + * @GST_URI_ERROR_BAD_URI: There was a problem with the URI + * @GST_URI_ERROR_BAD_STATE: Could not set or change the URI because the + * URI handler was in a state where that is not possible or not permitted + * @GST_URI_ERROR_BAD_REFERENCE: There was a problem with the entity that + * the URI references + * + * Different URI-related errors that can occur. + */ +typedef enum +{ + GST_URI_ERROR_UNSUPPORTED_PROTOCOL, + GST_URI_ERROR_BAD_URI, + GST_URI_ERROR_BAD_STATE, + GST_URI_ERROR_BAD_REFERENCE +} GstURIError; + +/** + * GstURIType: + * @GST_URI_UNKNOWN: The URI direction is unknown + * @GST_URI_SINK: The URI is a consumer. + * @GST_URI_SRC: The URI is a producer. + * + * The different types of URI direction. + */ + +typedef enum { + GST_URI_UNKNOWN, + GST_URI_SINK, + GST_URI_SRC +} GstURIType; + +/** + * GST_URI_TYPE_IS_VALID: + * @type: A #GstURIType + * + * Tests if the type direction is valid. + */ +#define GST_URI_TYPE_IS_VALID(type) ((type) == GST_URI_SRC || (type) == GST_URI_SINK) + +/* uri handler functions */ +#define GST_TYPE_URI_HANDLER (gst_uri_handler_get_type ()) +#define GST_URI_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler)) +#define GST_IS_URI_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER)) +#define GST_URI_HANDLER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerInterface)) + +/** + * GstURIHandler: + * + * Opaque #GstURIHandler structure. + */ +typedef struct _GstURIHandler GstURIHandler; +typedef struct _GstURIHandlerInterface GstURIHandlerInterface; + +#include +#include "gstminiobject.h" + +/** + * GstURIHandlerInterface: + * @parent: The parent interface type + * @get_type: Method to tell whether the element handles source or sink URI. + * @get_protocols: Method to return the list of protocols handled by the element. + * @get_uri: Method to return the URI currently handled by the element. + * @set_uri: Method to set a new URI. + * + * Any #GstElement using this interface should implement these methods. + */ +struct _GstURIHandlerInterface { + GTypeInterface parent; + + /* vtable */ + /*< public >*/ + /* querying capabilities */ + GstURIType (* get_type) (GType type); + const gchar * const * (* get_protocols) (GType type); + + /* using the interface */ + gchar * (* get_uri) (GstURIHandler * handler); + gboolean (* set_uri) (GstURIHandler * handler, + const gchar * uri, + GError ** error); +}; + +/* general URI functions */ + +GST_API +gboolean gst_uri_protocol_is_valid (const gchar * protocol); + +GST_API +gboolean gst_uri_protocol_is_supported (const GstURIType type, + const gchar *protocol); +GST_API +gboolean gst_uri_is_valid (const gchar * uri); + +GST_API +gchar * gst_uri_get_protocol (const gchar * uri) G_GNUC_MALLOC; + +GST_API +gboolean gst_uri_has_protocol (const gchar * uri, + const gchar * protocol); +GST_API +gchar * gst_uri_get_location (const gchar * uri) G_GNUC_MALLOC; + +GST_DEPRECATED_FOR(gst_uri_new) +gchar * gst_uri_construct (const gchar * protocol, + const gchar * location) G_GNUC_MALLOC; +GST_API +gchar * gst_filename_to_uri (const gchar * filename, + GError ** error) G_GNUC_MALLOC; +GST_API +GstElement * gst_element_make_from_uri (const GstURIType type, + const gchar * uri, + const gchar * elementname, + GError ** error) G_GNUC_MALLOC; + +/* accessing the interface */ + +GST_API +GType gst_uri_handler_get_type (void); + +GST_API +GstURIType gst_uri_handler_get_uri_type (GstURIHandler * handler); + +GST_API +const gchar * const * gst_uri_handler_get_protocols (GstURIHandler * handler); + +GST_API +gchar * gst_uri_handler_get_uri (GstURIHandler * handler) G_GNUC_MALLOC; + +GST_API +gboolean gst_uri_handler_set_uri (GstURIHandler * handler, + const gchar * uri, + GError ** error); + +/* + * GstUri Type macros. + */ +#define GST_TYPE_URI (gst_uri_get_type ()) +#define GST_IS_URI(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_URI)) +#define GST_URI_CAST(obj) ((GstUri *)(obj)) +#define GST_URI_CONST_CAST(obj) ((const GstUri *)(obj)) +#define GST_URI(obj) (GST_URI_CAST(obj)) + +/** + * GstUri: + * + * This is a private structure that holds the various parts of a parsed URI. + */ +struct _GstUri; +typedef struct _GstUri GstUri; + +/** + * GST_URI_NO_PORT: + * + * Value for #GstUri.port to indicate no port number. + */ +#define GST_URI_NO_PORT 0 + +/* used by GST_TYPE_URI */ + +GST_API +GType gst_uri_get_type (void); + +/* + * Method definitions. + */ + +GST_API +GstUri * gst_uri_new (const gchar * scheme, + const gchar * userinfo, + const gchar * host, + guint port, + const gchar * path, + const gchar * query, + const gchar * fragment) G_GNUC_MALLOC; +GST_API +GstUri * gst_uri_new_with_base (GstUri * base, + const gchar * scheme, + const gchar * userinfo, + const gchar * host, + guint port, + const gchar * path, + const gchar * query, + const gchar * fragment) G_GNUC_MALLOC; +GST_API +GstUri * gst_uri_from_string (const gchar * uri) G_GNUC_MALLOC; + +GST_API +GstUri * gst_uri_from_string_with_base (GstUri * base, + const gchar * uri) G_GNUC_MALLOC; +GST_API +gboolean gst_uri_equal (const GstUri * first, + const GstUri * second); +GST_API +GstUri * gst_uri_join (GstUri * base_uri, + GstUri * ref_uri) G_GNUC_WARN_UNUSED_RESULT; +GST_API +gchar * gst_uri_join_strings (const gchar * base_uri, + const gchar * ref_uri) G_GNUC_MALLOC; +GST_API +gboolean gst_uri_is_writable (const GstUri * uri); + +GST_API +GstUri * gst_uri_make_writable (GstUri * uri) G_GNUC_WARN_UNUSED_RESULT; + +GST_API +gchar * gst_uri_to_string (const GstUri * uri) G_GNUC_MALLOC; + +GST_API +gboolean gst_uri_is_normalized (const GstUri * uri); + +GST_API +gboolean gst_uri_normalize (GstUri * uri); + +GST_API +const gchar * gst_uri_get_scheme (const GstUri * uri); + +GST_API +gboolean gst_uri_set_scheme (GstUri * uri, const gchar * scheme); + +GST_API +const gchar * gst_uri_get_userinfo (const GstUri * uri); + +GST_API +gboolean gst_uri_set_userinfo (GstUri * uri, const gchar * userinfo); + +GST_API +const gchar * gst_uri_get_host (const GstUri * uri); + +GST_API +gboolean gst_uri_set_host (GstUri * uri, const gchar * host); + +GST_API +guint gst_uri_get_port (const GstUri * uri); + +GST_API +gboolean gst_uri_set_port (GstUri * uri, guint port); + +GST_API +gchar * gst_uri_get_path (const GstUri * uri); + +GST_API +gboolean gst_uri_set_path (GstUri * uri, const gchar * path); + +GST_API +gchar * gst_uri_get_path_string (const GstUri * uri); + +GST_API +gboolean gst_uri_set_path_string (GstUri * uri, const gchar * path); + +GST_API +GList * gst_uri_get_path_segments (const GstUri * uri); + +GST_API +gboolean gst_uri_set_path_segments (GstUri * uri, GList * path_segments); + +GST_API +gboolean gst_uri_append_path (GstUri * uri, + const gchar * relative_path); +GST_API +gboolean gst_uri_append_path_segment (GstUri * uri, + const gchar * path_segment); +GST_API +gchar * gst_uri_get_query_string (const GstUri * uri); + +GST_API +gboolean gst_uri_set_query_string (GstUri * uri, const gchar * query); + +GST_API +GHashTable * gst_uri_get_query_table (const GstUri * uri); + +GST_API +gboolean gst_uri_set_query_table (GstUri * uri, + GHashTable * query_table); +GST_API +gboolean gst_uri_set_query_value (GstUri * uri, const gchar * query_key, + const gchar * query_value); +GST_API +gboolean gst_uri_remove_query_key (GstUri * uri, const gchar * query_key); + +GST_API +gboolean gst_uri_query_has_key (const GstUri * uri, + const gchar * query_key); + +GST_API +const gchar * gst_uri_get_query_value (const GstUri * uri, + const gchar * query_key); + +GST_API +GList * gst_uri_get_query_keys (const GstUri * uri); + +GST_API +const gchar * gst_uri_get_fragment (const GstUri * uri); + +GST_API +gboolean gst_uri_set_fragment (GstUri * uri, const gchar * fragment); + +GST_API +GHashTable * gst_uri_get_media_fragment_table (const GstUri * uri); + +/** + * gst_uri_copy: + * @uri: This #GstUri object. + * + * Create a new #GstUri object with the same data as this #GstUri object. + * If @uri is %NULL then returns %NULL. + * + * Returns: (transfer full): A new #GstUri object which is a copy of this + * #GstUri or %NULL. + */ +static inline GstUri * +gst_uri_copy (const GstUri * uri) +{ + return GST_URI_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (uri))); +} + +/** + * gst_uri_ref: + * @uri: (transfer none): This #GstUri object. + * + * Add a reference to this #GstUri object. See gst_mini_object_ref() for further + * info. + * + * Returns: This object with the reference count incremented. + */ +static inline GstUri * +gst_uri_ref (GstUri * uri) +{ + return GST_URI_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (uri))); +} + +/** + * gst_uri_unref: + * @uri: (transfer full): This #GstUri object. + * + * Decrement the reference count to this #GstUri object. + * + * If the reference count drops to 0 then finalize this object. + * + * See gst_mini_object_unref() for further info. + */ +static inline void +gst_uri_unref (GstUri * uri) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (uri)); +} + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstUri, gst_uri_unref) +#endif + +G_END_DECLS + +#endif /* __GST_URI_H__ */ diff --git a/gst/gstutils.c b/gst/gstutils.c new file mode 100644 index 0000000..13c1bcd --- /dev/null +++ b/gst/gstutils.c @@ -0,0 +1,4456 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2002 Thomas Vander Stichele + * 2004 Wim Taymans + * 2015 Jan Schmidt + * + * gstutils.c: Utility functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstutils + * @title: GstUtils + * @short_description: Various utility functions + * + */ + +/* FIXME 2.0: suppress warnings for deprecated API such as GValueArray + * with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#include "gst_private.h" +#include +#include + +#include "gstghostpad.h" +#include "gstutils.h" +#include "gsterror.h" +#include "gstinfo.h" +#include "gstparse.h" +#include "gstvalue.h" +#include "gst-i18n-lib.h" +#include "glib-compat-private.h" +#include + +/** + * gst_util_dump_mem: + * @mem: (array length=size): a pointer to the memory to dump + * @size: the size of the memory block to dump + * + * Dumps the memory block into a hex representation. Useful for debugging. + */ +void +gst_util_dump_mem (const guchar * mem, guint size) +{ + guint i, j; + GString *string = g_string_sized_new (50); + GString *chars = g_string_sized_new (18); + + i = j = 0; + while (i < size) { + if (g_ascii_isprint (mem[i])) + g_string_append_c (chars, mem[i]); + else + g_string_append_c (chars, '.'); + + g_string_append_printf (string, "%02x ", mem[i]); + + j++; + i++; + + if (j == 16 || i == size) { + g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j, mem + i - j, + string->str, chars->str); + g_string_set_size (string, 0); + g_string_set_size (chars, 0); + j = 0; + } + } + g_string_free (string, TRUE); + g_string_free (chars, TRUE); +} + +/** + * gst_util_dump_buffer: + * @buf: a #GstBuffer whose memory to dump + * + * Dumps the buffer memory into a hex representation. Useful for debugging. + * + * Since: 1.14 + */ +void +gst_util_dump_buffer (GstBuffer * buf) +{ + GstMapInfo map; + + if (gst_buffer_map (buf, &map, GST_MAP_READ)) { + gst_util_dump_mem (map.data, map.size); + gst_buffer_unmap (buf, &map); + } +} + +/** + * gst_util_set_value_from_string: + * @value: (out caller-allocates): the value to set + * @value_str: the string to get the value from + * + * Converts the string to the type of the value and + * sets the value with it. + * + * Note that this function is dangerous as it does not return any indication + * if the conversion worked or not. + */ +void +gst_util_set_value_from_string (GValue * value, const gchar * value_str) +{ + gboolean res; + + g_return_if_fail (value != NULL); + g_return_if_fail (value_str != NULL); + + GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str, + g_type_name (G_VALUE_TYPE (value))); + + res = gst_value_deserialize (value, value_str); + if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) { + /* backwards compat, all booleans that fail to parse are false */ + g_value_set_boolean (value, FALSE); + res = TRUE; + } + g_return_if_fail (res); +} + +/** + * gst_util_set_object_arg: + * @object: the object to set the argument of + * @name: the name of the argument to set + * @value: the string value to set + * + * Converts the string value to the type of the objects argument and + * sets the argument with it. + * + * Note that this function silently returns if @object has no property named + * @name or when @value cannot be converted to the type of the property. + */ +void +gst_util_set_object_arg (GObject * object, const gchar * name, + const gchar * value) +{ + GParamSpec *pspec; + GType value_type; + GValue v = { 0, }; + + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name); + if (!pspec) + return; + + value_type = pspec->value_type; + + GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s", + pspec->flags, g_type_name (value_type)); + + if (!(pspec->flags & G_PARAM_WRITABLE)) + return; + + g_value_init (&v, value_type); + + /* special case for element <-> xml (de)serialisation */ + if (value_type == GST_TYPE_STRUCTURE && strcmp (value, "NULL") == 0) { + g_value_set_boxed (&v, NULL); + goto done; + } + + if (!gst_value_deserialize (&v, value)) + return; + +done: + + g_object_set_property (object, pspec->name, &v); + g_value_unset (&v); +} + +/** + * gst_util_set_object_array: + * @object: the object to set the array to + * @name: the name of the property to set + * @array: a #GValueArray containing the values + * + * Transfer a #GValueArray to %GST_TYPE_ARRAY and set this value on the + * specified property name. This allow language bindings to set GST_TYPE_ARRAY + * properties which are otherwise not an accessible type. + * + * Since: 1.12 + */ +gboolean +gst_util_set_object_array (GObject * object, const gchar * name, + const GValueArray * array) +{ + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT; + gboolean ret = FALSE; + + g_value_init (&v1, G_TYPE_VALUE_ARRAY); + g_value_init (&v2, GST_TYPE_ARRAY); + + g_value_set_static_boxed (&v1, array); + + if (g_value_transform (&v1, &v2)) { + g_object_set_property (object, name, &v2); + ret = TRUE; + } + + g_value_unset (&v1); + g_value_unset (&v2); + + return ret; +} + +/** + * gst_util_get_object_array: + * @object: the object to set the array to + * @name: the name of the property to set + * @array: (out): a return #GValueArray + * + * Get a property of type %GST_TYPE_ARRAY and transform it into a + * #GValueArray. This allow language bindings to get GST_TYPE_ARRAY + * properties which are otherwise not an accessible type. + * + * Since: 1.12 + */ +gboolean +gst_util_get_object_array (GObject * object, const gchar * name, + GValueArray ** array) +{ + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT; + gboolean ret = FALSE; + + g_value_init (&v1, G_TYPE_VALUE_ARRAY); + g_value_init (&v2, GST_TYPE_ARRAY); + + g_object_get_property (object, name, &v2); + + if (g_value_transform (&v2, &v1)) { + *array = g_value_get_boxed (&v1); + ret = TRUE; + } + + g_value_unset (&v2); + + return ret; +} + +/* work around error C2520: conversion from unsigned __int64 to double + * not implemented, use signed __int64 + * + * These are implemented as functions because on some platforms a 64bit int to + * double conversion is not defined/implemented. + */ + +gdouble +gst_util_guint64_to_gdouble (guint64 value) +{ + if (value & G_GINT64_CONSTANT (0x8000000000000000)) + return (gdouble) ((gint64) value) + (gdouble) 18446744073709551616.; + else + return (gdouble) ((gint64) value); +} + +guint64 +gst_util_gdouble_to_guint64 (gdouble value) +{ + if (value < (gdouble) 9223372036854775808.) /* 1 << 63 */ + return ((guint64) ((gint64) value)); + + value -= (gdouble) 18446744073709551616.; + return ((guint64) ((gint64) value)); +} + +#ifndef HAVE_UINT128_T +/* convenience struct for getting high and low uint32 parts of + * a guint64 */ +typedef union +{ + guint64 ll; + struct + { +#if G_BYTE_ORDER == G_BIG_ENDIAN + guint32 high, low; +#else + guint32 low, high; +#endif + } l; +} GstUInt64; + +#if defined (__x86_64__) && defined (__GNUC__) +static inline void +gst_util_uint64_mul_uint64 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1, + guint64 arg2) +{ + __asm__ __volatile__ ("mulq %3":"=a" (c0->ll), "=d" (c1->ll) + :"a" (arg1), "g" (arg2) + ); +} +#else /* defined (__x86_64__) */ +/* multiply two 64-bit unsigned ints into a 128-bit unsigned int. the high + * and low 64 bits of the product are placed in c1 and c0 respectively. + * this operation cannot overflow. */ +static inline void +gst_util_uint64_mul_uint64 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1, + guint64 arg2) +{ + GstUInt64 a1, b0; + GstUInt64 v, n; + + /* prepare input */ + v.ll = arg1; + n.ll = arg2; + + /* do 128 bits multiply + * nh nl + * * vh vl + * ---------- + * a0 = vl * nl + * a1 = vl * nh + * b0 = vh * nl + * b1 = + vh * nh + * ------------------- + * c1h c1l c0h c0l + * + * "a0" is optimized away, result is stored directly in c0. "b1" is + * optimized away, result is stored directly in c1. + */ + c0->ll = (guint64) v.l.low * n.l.low; + a1.ll = (guint64) v.l.low * n.l.high; + b0.ll = (guint64) v.l.high * n.l.low; + + /* add the high word of a0 to the low words of a1 and b0 using c1 as + * scrach space to capture the carry. the low word of the result becomes + * the final high word of c0 */ + c1->ll = (guint64) c0->l.high + a1.l.low + b0.l.low; + c0->l.high = c1->l.low; + + /* add the carry from the result above (found in the high word of c1) and + * the high words of a1 and b0 to b1, the result is c1. */ + c1->ll = (guint64) v.l.high * n.l.high + c1->l.high + a1.l.high + b0.l.high; +} +#endif /* defined (__x86_64__) */ + +#if defined (__x86_64__) && defined (__GNUC__) +static inline guint64 +gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom) +{ + guint64 res; + + __asm__ __volatile__ ("divq %3":"=a" (res) + :"d" (c1.ll), "a" (c0.ll), "g" (denom) + ); + + return res; +} +#else +/* count leading zeros */ +static inline guint +gst_util_clz (guint32 val) +{ + guint s; + + s = val | (val >> 1); + s |= (s >> 2); + s |= (s >> 4); + s |= (s >> 8); + s = ~(s | (s >> 16)); + s = s - ((s >> 1) & 0x55555555); + s = (s & 0x33333333) + ((s >> 2) & 0x33333333); + s = (s + (s >> 4)) & 0x0f0f0f0f; + s += (s >> 8); + s = (s + (s >> 16)) & 0x3f; + + return s; +} + +/* based on Hacker's Delight p152 */ +static inline guint64 +gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom) +{ + GstUInt64 q1, q0, rhat; + GstUInt64 v, cmp1, cmp2; + guint s; + + v.ll = denom; + + /* count number of leading zeroes, we know they must be in the high + * part of denom since denom > G_MAXUINT32. */ + s = gst_util_clz (v.l.high); + + if (s > 0) { + /* normalize divisor and dividend */ + v.ll <<= s; + c1.ll = (c1.ll << s) | (c0.l.high >> (32 - s)); + c0.ll <<= s; + } + + q1.ll = c1.ll / v.l.high; + rhat.ll = c1.ll - q1.ll * v.l.high; + + cmp1.l.high = rhat.l.low; + cmp1.l.low = c0.l.high; + cmp2.ll = q1.ll * v.l.low; + + while (q1.l.high || cmp2.ll > cmp1.ll) { + q1.ll--; + rhat.ll += v.l.high; + if (rhat.l.high) + break; + cmp1.l.high = rhat.l.low; + cmp2.ll -= v.l.low; + } + c1.l.high = c1.l.low; + c1.l.low = c0.l.high; + c1.ll -= q1.ll * v.ll; + q0.ll = c1.ll / v.l.high; + rhat.ll = c1.ll - q0.ll * v.l.high; + + cmp1.l.high = rhat.l.low; + cmp1.l.low = c0.l.low; + cmp2.ll = q0.ll * v.l.low; + + while (q0.l.high || cmp2.ll > cmp1.ll) { + q0.ll--; + rhat.ll += v.l.high; + if (rhat.l.high) + break; + cmp1.l.high = rhat.l.low; + cmp2.ll -= v.l.low; + } + q0.l.high += q1.l.low; + + return q0.ll; +} +#endif /* defined (__GNUC__) */ + +/* This always gives the correct result because: + * a) val <= G_MAXUINT64-1 + * b) (c0,c1) <= G_MAXUINT64 * (G_MAXUINT64-1) + * or + * (c0,c1) == G_MAXUINT64 * G_MAXUINT64 and denom < G_MAXUINT64 + * (note: num==denom case is handled by short path) + * This means that (c0,c1) either has enough space for val + * or that the overall result will overflow anyway. + */ + +/* add correction with carry */ +#define CORRECT(c0,c1,val) \ + if (val) { \ + if (G_MAXUINT64 - c0.ll < val) { \ + if (G_UNLIKELY (c1.ll == G_MAXUINT64)) \ + /* overflow */ \ + return G_MAXUINT64; \ + c1.ll++; \ + } \ + c0.ll += val; \ + } + +static guint64 +gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num, + guint64 denom, guint64 correct) +{ + GstUInt64 c1, c0; + + /* compute 128-bit numerator product */ + gst_util_uint64_mul_uint64 (&c1, &c0, val, num); + + /* perform rounding correction */ + CORRECT (c0, c1, correct); + + /* high word as big as or bigger than denom --> overflow */ + if (G_UNLIKELY (c1.ll >= denom)) + return G_MAXUINT64; + + /* compute quotient, fits in 64 bits */ + return gst_util_div128_64 (c1, c0, denom); +} +#else + +#define GST_MAXUINT128 ((__uint128_t) -1) +static guint64 +gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num, + guint64 denom, guint64 correct) +{ + __uint128_t tmp; + + /* Calculate val * num */ + tmp = ((__uint128_t) val) * ((__uint128_t) num); + + /* overflow checks */ + if (G_UNLIKELY (GST_MAXUINT128 - correct < tmp)) + return G_MAXUINT64; + + /* perform rounding correction */ + tmp += correct; + + /* Divide by denom */ + tmp /= denom; + + /* if larger than G_MAXUINT64 --> overflow */ + if (G_UNLIKELY (tmp > G_MAXUINT64)) + return G_MAXUINT64; + + /* compute quotient, fits in 64 bits */ + return (guint64) tmp; +} + +#endif + +#if !defined (__x86_64__) && !defined (HAVE_UINT128_T) +static inline void +gst_util_uint64_mul_uint32 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1, + guint32 arg2) +{ + GstUInt64 a; + + a.ll = arg1; + + c0->ll = (guint64) a.l.low * arg2; + c1->ll = (guint64) a.l.high * arg2 + c0->l.high; + c0->l.high = 0; +} + +/* divide a 96-bit unsigned int by a 32-bit unsigned int when we know the + * quotient fits into 64 bits. the high 64 bits and low 32 bits of the + * numerator are expected in c1 and c0 respectively. */ +static inline guint64 +gst_util_div96_32 (guint64 c1, guint64 c0, guint32 denom) +{ + c0 += (c1 % denom) << 32; + return ((c1 / denom) << 32) + (c0 / denom); +} + +static inline guint64 +gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num, + guint32 denom, guint32 correct) +{ + GstUInt64 c1, c0; + + /* compute 96-bit numerator product */ + gst_util_uint64_mul_uint32 (&c1, &c0, val, num); + + /* condition numerator based on rounding mode */ + CORRECT (c0, c1, correct); + + /* high 32 bits as big as or bigger than denom --> overflow */ + if (G_UNLIKELY (c1.l.high >= denom)) + return G_MAXUINT64; + + /* compute quotient, fits in 64 bits */ + return gst_util_div96_32 (c1.ll, c0.ll, denom); +} +#endif + +/* the guts of the gst_util_uint64_scale() variants */ +static guint64 +_gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom, + guint64 correct) +{ + g_return_val_if_fail (denom != 0, G_MAXUINT64); + + if (G_UNLIKELY (num == 0)) + return 0; + + if (G_UNLIKELY (num == denom)) + return val; + + /* on 64bits we always use a full 128bits multiply/division */ +#if !defined (__x86_64__) && !defined (HAVE_UINT128_T) + /* denom is low --> try to use 96 bit muldiv */ + if (G_LIKELY (denom <= G_MAXUINT32)) { + /* num is low --> use 96 bit muldiv */ + if (G_LIKELY (num <= G_MAXUINT32)) + return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num, + (guint32) denom, correct); + + /* num is high but val is low --> swap and use 96-bit muldiv */ + if (G_LIKELY (val <= G_MAXUINT32)) + return gst_util_uint64_scale_uint32_unchecked (num, (guint32) val, + (guint32) denom, correct); + } +#endif /* !defined (__x86_64__) && !defined (HAVE_UINT128_T) */ + + /* val is high and num is high --> use 128-bit muldiv */ + return gst_util_uint64_scale_uint64_unchecked (val, num, denom, correct); +} + +/** + * gst_util_uint64_scale: + * @val: the number to scale + * @num: the numerator of the scale ratio + * @denom: the denominator of the scale ratio + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. + * + * This function can potentially be very slow if val and num are both + * greater than G_MAXUINT32. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer it is truncated. See also + * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil(), + * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), + * gst_util_uint64_scale_int_ceil(). + */ +guint64 +gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) +{ + return _gst_util_uint64_scale (val, num, denom, 0); +} + +/** + * gst_util_uint64_scale_round: + * @val: the number to scale + * @num: the numerator of the scale ratio + * @denom: the denominator of the scale ratio + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. + * + * This function can potentially be very slow if val and num are both + * greater than G_MAXUINT32. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer, it is rounded to the nearest integer + * (half-way cases are rounded up). See also gst_util_uint64_scale(), + * gst_util_uint64_scale_ceil(), gst_util_uint64_scale_int(), + * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil(). + */ +guint64 +gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom) +{ + return _gst_util_uint64_scale (val, num, denom, denom >> 1); +} + +/** + * gst_util_uint64_scale_ceil: + * @val: the number to scale + * @num: the numerator of the scale ratio + * @denom: the denominator of the scale ratio + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. + * + * This function can potentially be very slow if val and num are both + * greater than G_MAXUINT32. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer, it is rounded up. See also + * gst_util_uint64_scale(), gst_util_uint64_scale_round(), + * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), + * gst_util_uint64_scale_int_ceil(). + */ +guint64 +gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom) +{ + return _gst_util_uint64_scale (val, num, denom, denom - 1); +} + +/* the guts of the gst_util_uint64_scale_int() variants */ +static guint64 +_gst_util_uint64_scale_int (guint64 val, gint num, gint denom, gint correct) +{ + g_return_val_if_fail (denom > 0, G_MAXUINT64); + g_return_val_if_fail (num >= 0, G_MAXUINT64); + + if (G_UNLIKELY (num == 0)) + return 0; + + if (G_UNLIKELY (num == denom)) + return val; + + if (val <= G_MAXUINT32) { + /* simple case. num and denom are not negative so casts are OK. when + * not truncating, the additions to the numerator cannot overflow + * because val*num <= G_MAXUINT32 * G_MAXINT32 < G_MAXUINT64 - + * G_MAXINT32, so there's room to add another gint32. */ + val *= (guint64) num; + /* add rounding correction */ + val += correct; + + return val / (guint64) denom; + } +#if !defined (__x86_64__) && !defined (HAVE_UINT128_T) + /* num and denom are not negative so casts are OK */ + return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num, + (guint32) denom, (guint32) correct); +#else + /* always use full 128bits scale */ + return gst_util_uint64_scale_uint64_unchecked (val, num, denom, correct); +#endif +} + +/** + * gst_util_uint64_scale_int: + * @val: guint64 (such as a #GstClockTime) to scale. + * @num: numerator of the scale factor. + * @denom: denominator of the scale factor. + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. @num must be non-negative and + * @denom must be positive. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer, it is truncated. See also + * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil(), + * gst_util_uint64_scale(), gst_util_uint64_scale_round(), + * gst_util_uint64_scale_ceil(). + */ +guint64 +gst_util_uint64_scale_int (guint64 val, gint num, gint denom) +{ + return _gst_util_uint64_scale_int (val, num, denom, 0); +} + +/** + * gst_util_uint64_scale_int_round: + * @val: guint64 (such as a #GstClockTime) to scale. + * @num: numerator of the scale factor. + * @denom: denominator of the scale factor. + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. @num must be non-negative and + * @denom must be positive. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer, it is rounded to the nearest integer + * (half-way cases are rounded up). See also gst_util_uint64_scale_int(), + * gst_util_uint64_scale_int_ceil(), gst_util_uint64_scale(), + * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil(). + */ +guint64 +gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom) +{ + /* we can use a shift to divide by 2 because denom is required to be + * positive. */ + return _gst_util_uint64_scale_int (val, num, denom, denom >> 1); +} + +/** + * gst_util_uint64_scale_int_ceil: + * @val: guint64 (such as a #GstClockTime) to scale. + * @num: numerator of the scale factor. + * @denom: denominator of the scale factor. + * + * Scale @val by the rational number @num / @denom, avoiding overflows and + * underflows and without loss of precision. @num must be non-negative and + * @denom must be positive. + * + * Returns: @val * @num / @denom. In the case of an overflow, this + * function returns G_MAXUINT64. If the result is not exactly + * representable as an integer, it is rounded up. See also + * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(), + * gst_util_uint64_scale(), gst_util_uint64_scale_round(), + * gst_util_uint64_scale_ceil(). + */ +guint64 +gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom) +{ + return _gst_util_uint64_scale_int (val, num, denom, denom - 1); +} + +/** + * gst_util_seqnum_next: + * + * Return a constantly incrementing sequence number. + * + * This function is used internally to GStreamer to be able to determine which + * events and messages are "the same". For example, elements may set the seqnum + * on a segment-done message to be the same as that of the last seek event, to + * indicate that event and the message correspond to the same segment. + * + * This function never returns %GST_SEQNUM_INVALID (which is 0). + * + * Returns: A constantly incrementing 32-bit unsigned integer, which might + * overflow at some point. Use gst_util_seqnum_compare() to make sure + * you handle wraparound correctly. + */ +guint32 +gst_util_seqnum_next (void) +{ + static gint counter = 1; + gint ret = g_atomic_int_add (&counter, 1); + + /* Make sure we don't return 0 */ + if (G_UNLIKELY (ret == GST_SEQNUM_INVALID)) + ret = g_atomic_int_add (&counter, 1); + + return ret; +} + +/** + * gst_util_seqnum_compare: + * @s1: A sequence number. + * @s2: Another sequence number. + * + * Compare two sequence numbers, handling wraparound. + * + * The current implementation just returns (gint32)(@s1 - @s2). + * + * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a + * positive number if @s1 is after @s2. + */ +gint32 +gst_util_seqnum_compare (guint32 s1, guint32 s2) +{ + return (gint32) (s1 - s2); +} + +/* ----------------------------------------------------- + * + * The following code will be moved out of the main + * gstreamer library someday. + */ + +#include "gstpad.h" + +/** + * gst_element_create_all_pads: + * @element: (transfer none): a #GstElement to create pads for + * + * Creates a pad for each pad template that is always available. + * This function is only useful during object initialization of + * subclasses of #GstElement. + */ +void +gst_element_create_all_pads (GstElement * element) +{ + GList *padlist; + + /* FIXME: lock element */ + + padlist = + gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS + (G_OBJECT_GET_CLASS (element))); + + while (padlist) { + GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data; + + if (padtempl->presence == GST_PAD_ALWAYS) { + GstPad *pad; + + pad = gst_pad_new_from_template (padtempl, padtempl->name_template); + + gst_element_add_pad (element, pad); + } + padlist = padlist->next; + } +} + +/** + * gst_element_get_compatible_pad_template: + * @element: (transfer none): a #GstElement to get a compatible pad template for + * @compattempl: (transfer none): the #GstPadTemplate to find a compatible + * template for + * + * Retrieves a pad template from @element that is compatible with @compattempl. + * Pads from compatible templates can be linked together. + * + * Returns: (transfer none) (nullable): a compatible #GstPadTemplate, + * or %NULL if none was found. No unreferencing is necessary. + */ +GstPadTemplate * +gst_element_get_compatible_pad_template (GstElement * element, + GstPadTemplate * compattempl) +{ + GstPadTemplate *newtempl = NULL; + GList *padlist; + GstElementClass *class; + gboolean compatible; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (compattempl != NULL, NULL); + + class = GST_ELEMENT_GET_CLASS (element); + + padlist = gst_element_class_get_pad_template_list (class); + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "Looking for a suitable pad template in %s out of %d templates...", + GST_ELEMENT_NAME (element), g_list_length (padlist)); + + while (padlist) { + GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data; + + /* Ignore name + * Ignore presence + * Check direction (must be opposite) + * Check caps + */ + GST_CAT_LOG (GST_CAT_CAPS, + "checking pad template %s", padtempl->name_template); + if (padtempl->direction != compattempl->direction) { + GST_CAT_DEBUG (GST_CAT_CAPS, + "compatible direction: found %s pad template \"%s\"", + padtempl->direction == GST_PAD_SRC ? "src" : "sink", + padtempl->name_template); + + GST_CAT_DEBUG (GST_CAT_CAPS, + "intersecting %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (compattempl)); + GST_CAT_DEBUG (GST_CAT_CAPS, + "..and %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (padtempl)); + + compatible = gst_caps_can_intersect (GST_PAD_TEMPLATE_CAPS (compattempl), + GST_PAD_TEMPLATE_CAPS (padtempl)); + + GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible", + (compatible ? "" : "not ")); + + if (compatible) { + newtempl = padtempl; + break; + } + } + + padlist = g_list_next (padlist); + } + if (newtempl) + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "Returning new pad template %p", newtempl); + else + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "No compatible pad template found"); + + return newtempl; +} + +/** + * gst_element_get_pad_from_template: + * @element: (transfer none): a #GstElement. + * @templ: (transfer none): a #GstPadTemplate belonging to @element. + * + * Gets a pad from @element described by @templ. If the presence of @templ is + * #GST_PAD_REQUEST, requests a new pad. Can return %NULL for #GST_PAD_SOMETIMES + * templates. + * + * Returns: (transfer full) (nullable): the #GstPad, or %NULL if one + * could not be found or created. + */ +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; +} + +/* + * gst_element_request_compatible_pad: + * @element: a #GstElement. + * @templ: the #GstPadTemplate to which the new pad should be able to link. + * + * Requests a pad from @element. The returned pad should be unlinked and + * compatible with @templ. Might return an existing pad, or request a new one. + * + * Returns: (nullable): a #GstPad, or %NULL if one could not be found + * or created. + */ +static GstPad * +gst_element_request_compatible_pad (GstElement * element, + GstPadTemplate * templ) +{ + GstPadTemplate *templ_new; + GstPad *pad = NULL; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); + + /* FIXME: should really loop through the templates, testing each for + * compatibility and pad availability. */ + templ_new = gst_element_get_compatible_pad_template (element, templ); + if (templ_new) + pad = gst_element_get_pad_from_template (element, templ_new); + /* This can happen for non-request pads. */ + if (pad && GST_PAD_PEER (pad)) { + gst_object_unref (pad); + pad = NULL; + } + + return pad; +} + +/* + * Checks if the source pad and the sink pad can be linked. + * Both @srcpad and @sinkpad must be unlinked and have a parent. + */ +static gboolean +gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad) +{ + /* generic checks */ + g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); + g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); + + GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + if (GST_PAD_PEER (srcpad) != NULL) { + GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed", + GST_DEBUG_PAD_NAME (srcpad)); + return FALSE; + } + if (GST_PAD_PEER (sinkpad) != NULL) { + GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed", + GST_DEBUG_PAD_NAME (sinkpad)); + return FALSE; + } + if (!GST_PAD_IS_SRC (srcpad)) { + GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed", + GST_DEBUG_PAD_NAME (srcpad)); + return FALSE; + } + if (!GST_PAD_IS_SINK (sinkpad)) { + GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed", + GST_DEBUG_PAD_NAME (sinkpad)); + return FALSE; + } + if (GST_PAD_PARENT (srcpad) == NULL) { + GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed", + GST_DEBUG_PAD_NAME (srcpad)); + return FALSE; + } + if (GST_PAD_PARENT (sinkpad) == NULL) { + GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed", + GST_DEBUG_PAD_NAME (srcpad)); + return FALSE; + } + + return TRUE; +} + +/** + * gst_element_get_compatible_pad: + * @element: (transfer none): a #GstElement in which the pad should be found. + * @pad: (transfer none): the #GstPad to find a compatible one for. + * @caps: (allow-none): the #GstCaps to use as a filter. + * + * Looks for an unlinked pad to which the given pad can link. It is not + * guaranteed that linking the pads will work, though it should work in most + * cases. + * + * This function will first attempt to find a compatible unlinked ALWAYS pad, + * and if none can be found, it will request a compatible REQUEST pad by looking + * at the templates of @element. + * + * Returns: (transfer full) (nullable): the #GstPad to which a link + * can be made, or %NULL if one cannot be found. gst_object_unref() + * after usage. + */ +GstPad * +gst_element_get_compatible_pad (GstElement * element, GstPad * pad, + GstCaps * caps) +{ + GstIterator *pads; + GstPadTemplate *templ; + GstCaps *templcaps; + GstPad *foundpad = NULL; + gboolean done; + GValue padptr = { 0, }; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "finding pad in %s compatible with %s:%s", + GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad)); + + g_return_val_if_fail (GST_PAD_PEER (pad) == NULL, NULL); + + done = FALSE; + + /* try to get an existing unlinked pad */ + if (GST_PAD_IS_SRC (pad)) { + pads = gst_element_iterate_sink_pads (element); + } else if (GST_PAD_IS_SINK (pad)) { + pads = gst_element_iterate_src_pads (element); + } else { + pads = gst_element_iterate_pads (element); + } + + while (!done) { + switch (gst_iterator_next (pads, &padptr)) { + case GST_ITERATOR_OK: + { + GstPad *peer; + GstPad *current; + GstPad *srcpad; + GstPad *sinkpad; + + current = g_value_get_object (&padptr); + + GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", + GST_DEBUG_PAD_NAME (current)); + + if (GST_PAD_IS_SRC (current)) { + srcpad = current; + sinkpad = pad; + } else { + srcpad = pad; + sinkpad = current; + } + peer = gst_pad_get_peer (current); + + if (peer == NULL && gst_pad_check_link (srcpad, sinkpad)) { + GstCaps *temp, *intersection; + gboolean compatible; + + /* Now check if the two pads' caps are compatible */ + temp = gst_pad_query_caps (pad, NULL); + if (caps) { + intersection = gst_caps_intersect (temp, caps); + gst_caps_unref (temp); + } else { + intersection = temp; + } + + temp = gst_pad_query_caps (current, NULL); + compatible = gst_caps_can_intersect (temp, intersection); + gst_caps_unref (temp); + gst_caps_unref (intersection); + + if (compatible) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "found existing unlinked compatible pad %s:%s", + GST_DEBUG_PAD_NAME (current)); + gst_iterator_free (pads); + + current = gst_object_ref (current); + g_value_unset (&padptr); + + return current; + } else { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads"); + } + } else { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "already linked or cannot be linked (peer = %p)", peer); + } + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads"); + + g_value_reset (&padptr); + if (peer) + gst_object_unref (peer); + break; + } + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pads); + break; + case GST_ITERATOR_ERROR: + g_assert_not_reached (); + break; + } + } + g_value_unset (&padptr); + gst_iterator_free (pads); + + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "Could not find a compatible unlinked always pad to link to %s:%s, now checking request pads", + GST_DEBUG_PAD_NAME (pad)); + + /* try to create a new one */ + /* requesting is a little crazy, we need a template. Let's create one */ + templcaps = gst_pad_query_caps (pad, NULL); + if (caps) { + GstCaps *inter = gst_caps_intersect (templcaps, caps); + + gst_caps_unref (templcaps); + templcaps = inter; + } + templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), + GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps); + gst_caps_unref (templcaps); + + foundpad = gst_element_request_compatible_pad (element, templ); + gst_object_unref (templ); + + if (foundpad) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "found existing request pad %s:%s", GST_DEBUG_PAD_NAME (foundpad)); + return foundpad; + } + + GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, + "Could not find a compatible pad to link to %s:%s", + GST_DEBUG_PAD_NAME (pad)); + return NULL; +} + +/** + * gst_element_state_get_name: + * @state: a #GstState to get the name of. + * + * Gets a string representing the given state. + * + * Returns: (transfer none): a string with the name of the state. + */ +const gchar * +gst_element_state_get_name (GstState state) +{ + switch (state) { + case GST_STATE_VOID_PENDING: + return "VOID_PENDING"; + case GST_STATE_NULL: + return "NULL"; + case GST_STATE_READY: + return "READY"; + case GST_STATE_PLAYING: + return "PLAYING"; + case GST_STATE_PAUSED: + return "PAUSED"; + default: + /* This is a memory leak */ + return g_strdup_printf ("UNKNOWN!(%d)", state); + } +} + +/** + * gst_element_state_change_return_get_name: + * @state_ret: a #GstStateChangeReturn to get the name of. + * + * Gets a string representing the given state change result. + * + * Returns: (transfer none): a string with the name of the state + * result. + */ +const gchar * +gst_element_state_change_return_get_name (GstStateChangeReturn state_ret) +{ + switch (state_ret) { + case GST_STATE_CHANGE_FAILURE: + return "FAILURE"; + case GST_STATE_CHANGE_SUCCESS: + return "SUCCESS"; + case GST_STATE_CHANGE_ASYNC: + return "ASYNC"; + case GST_STATE_CHANGE_NO_PREROLL: + return "NO PREROLL"; + default: + /* This is a memory leak */ + return g_strdup_printf ("UNKNOWN!(%d)", state_ret); + } +} + +/** + * gst_state_change_get_name: + * @transition: a #GstStateChange to get the name of. + * + * Gets a string representing the given state transition. + * + * Returns: (transfer none): a string with the name of the state + * result. + * + * Since: 1.14 + */ +const gchar * +gst_state_change_get_name (GstStateChange transition) +{ + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + return "NULL->READY"; + case GST_STATE_CHANGE_READY_TO_PAUSED: + return "READY->PAUSED"; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + return "PAUSED->PLAYING"; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + return "PLAYING->PAUSED"; + case GST_STATE_CHANGE_PAUSED_TO_READY: + return "PAUSED->READY"; + case GST_STATE_CHANGE_READY_TO_NULL: + return "READY->NULL"; + case GST_STATE_CHANGE_NULL_TO_NULL: + return "NULL->NULL"; + case GST_STATE_CHANGE_READY_TO_READY: + return "READY->READY"; + case GST_STATE_CHANGE_PAUSED_TO_PAUSED: + return "PAUSED->PAUSED"; + case GST_STATE_CHANGE_PLAYING_TO_PLAYING: + return "PLAYING->PLAYING"; + } + + return "Unknown state return"; +} + + +static gboolean +gst_element_factory_can_accept_all_caps_in_direction (GstElementFactory * + factory, const GstCaps * caps, GstPadDirection direction) +{ + GList *templates; + + g_return_val_if_fail (factory != NULL, FALSE); + g_return_val_if_fail (caps != NULL, FALSE); + + templates = factory->staticpadtemplates; + + while (templates) { + GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data; + + if (template->direction == direction) { + GstCaps *templcaps = gst_static_caps_get (&template->static_caps); + + if (gst_caps_is_always_compatible (caps, templcaps)) { + gst_caps_unref (templcaps); + return TRUE; + } + gst_caps_unref (templcaps); + } + templates = g_list_next (templates); + } + + return FALSE; +} + +static gboolean +gst_element_factory_can_accept_any_caps_in_direction (GstElementFactory * + factory, const GstCaps * caps, GstPadDirection direction) +{ + GList *templates; + + g_return_val_if_fail (factory != NULL, FALSE); + g_return_val_if_fail (caps != NULL, FALSE); + + templates = factory->staticpadtemplates; + + while (templates) { + GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data; + + if (template->direction == direction) { + GstCaps *templcaps = gst_static_caps_get (&template->static_caps); + + if (gst_caps_can_intersect (caps, templcaps)) { + gst_caps_unref (templcaps); + return TRUE; + } + gst_caps_unref (templcaps); + } + templates = g_list_next (templates); + } + + return FALSE; +} + +/** + * gst_element_factory_can_sink_all_caps: + * @factory: factory to query + * @caps: the caps to check + * + * Checks if the factory can sink all possible capabilities. + * + * Returns: %TRUE if the caps are fully compatible. + */ +gboolean +gst_element_factory_can_sink_all_caps (GstElementFactory * factory, + const GstCaps * caps) +{ + return gst_element_factory_can_accept_all_caps_in_direction (factory, caps, + GST_PAD_SINK); +} + +/** + * gst_element_factory_can_src_all_caps: + * @factory: factory to query + * @caps: the caps to check + * + * Checks if the factory can src all possible capabilities. + * + * Returns: %TRUE if the caps are fully compatible. + */ +gboolean +gst_element_factory_can_src_all_caps (GstElementFactory * factory, + const GstCaps * caps) +{ + return gst_element_factory_can_accept_all_caps_in_direction (factory, caps, + GST_PAD_SRC); +} + +/** + * gst_element_factory_can_sink_any_caps: + * @factory: factory to query + * @caps: the caps to check + * + * Checks if the factory can sink any possible capability. + * + * Returns: %TRUE if the caps have a common subset. + */ +gboolean +gst_element_factory_can_sink_any_caps (GstElementFactory * factory, + const GstCaps * caps) +{ + return gst_element_factory_can_accept_any_caps_in_direction (factory, caps, + GST_PAD_SINK); +} + +/** + * gst_element_factory_can_src_any_caps: + * @factory: factory to query + * @caps: the caps to check + * + * Checks if the factory can src any possible capability. + * + * Returns: %TRUE if the caps have a common subset. + */ +gboolean +gst_element_factory_can_src_any_caps (GstElementFactory * factory, + const GstCaps * caps) +{ + return gst_element_factory_can_accept_any_caps_in_direction (factory, caps, + GST_PAD_SRC); +} + +/* if return val is true, *direct_child is a caller-owned ref on the direct + * child of ancestor that is part of object's ancestry */ +static gboolean +object_has_ancestor (GstObject * object, GstObject * ancestor, + GstObject ** direct_child) +{ + GstObject *child, *parent; + + if (direct_child) + *direct_child = NULL; + + child = gst_object_ref (object); + parent = gst_object_get_parent (object); + + while (parent) { + if (ancestor == parent) { + if (direct_child) + *direct_child = child; + else + gst_object_unref (child); + gst_object_unref (parent); + return TRUE; + } + + gst_object_unref (child); + child = parent; + parent = gst_object_get_parent (parent); + } + + gst_object_unref (child); + + return FALSE; +} + +/* caller owns return */ +static GstObject * +find_common_root (GstObject * o1, GstObject * o2) +{ + GstObject *top = o1; + GstObject *kid1, *kid2; + GstObject *root = NULL; + + while (GST_OBJECT_PARENT (top)) + top = GST_OBJECT_PARENT (top); + + /* the itsy-bitsy spider... */ + + if (!object_has_ancestor (o2, top, &kid2)) + return NULL; + + root = gst_object_ref (top); + while (TRUE) { + if (!object_has_ancestor (o1, kid2, &kid1)) { + gst_object_unref (kid2); + return root; + } + gst_object_unref (root); + root = kid2; + if (!object_has_ancestor (o2, kid1, &kid2)) { + gst_object_unref (kid1); + return root; + } + gst_object_unref (root); + root = kid1; + } +} + +/* caller does not own return */ +static GstPad * +ghost_up (GstElement * e, GstPad * pad) +{ + static gint ghost_pad_index = 0; + GstPad *gpad; + gchar *name; + GstState current; + GstState next; + GstObject *parent = GST_OBJECT_PARENT (e); + + name = g_strdup_printf ("ghost%d", ghost_pad_index++); + gpad = gst_ghost_pad_new (name, pad); + g_free (name); + + GST_STATE_LOCK (parent); + gst_element_get_state (GST_ELEMENT (parent), ¤t, &next, 0); + + if (current > GST_STATE_READY || next >= GST_STATE_PAUSED) + gst_pad_set_active (gpad, TRUE); + + if (!gst_element_add_pad ((GstElement *) parent, gpad)) { + g_warning ("Pad named %s already exists in element %s\n", + GST_OBJECT_NAME (gpad), GST_OBJECT_NAME (parent)); + GST_STATE_UNLOCK (parent); + return NULL; + } + GST_STATE_UNLOCK (parent); + + return gpad; +} + +static void +remove_pad (gpointer ppad, gpointer unused) +{ + GstPad *pad = ppad; + + if (!gst_element_remove_pad ((GstElement *) GST_OBJECT_PARENT (pad), pad)) + g_warning ("Couldn't remove pad %s from element %s", + GST_OBJECT_NAME (pad), GST_OBJECT_NAME (GST_OBJECT_PARENT (pad))); +} + +static gboolean +prepare_link_maybe_ghosting (GstPad ** src, GstPad ** sink, + GSList ** pads_created) +{ + GstObject *root; + GstObject *e1, *e2; + GSList *pads_created_local = NULL; + + g_assert (pads_created); + + e1 = GST_OBJECT_PARENT (*src); + e2 = GST_OBJECT_PARENT (*sink); + + if (G_UNLIKELY (e1 == NULL)) { + GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %" + GST_PTR_FORMAT, *src); + return FALSE; + } + if (G_UNLIKELY (e2 == NULL)) { + GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %" + GST_PTR_FORMAT, *sink); + return FALSE; + } + + if (GST_OBJECT_PARENT (e1) == GST_OBJECT_PARENT (e2)) { + GST_CAT_INFO (GST_CAT_PADS, "%s and %s in same bin, no need for ghost pads", + GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2)); + return TRUE; + } + + GST_CAT_INFO (GST_CAT_PADS, "%s and %s not in same bin, making ghost pads", + GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2)); + + /* we need to setup some ghost pads */ + root = find_common_root (e1, e2); + if (!root) { + if (GST_OBJECT_PARENT (e1) == NULL) + g_warning ("Trying to link elements %s and %s that don't share a common " + "ancestor: %s hasn't been added to a bin or pipeline, but %s is in %s", + GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2), + GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2), + GST_ELEMENT_NAME (GST_OBJECT_PARENT (e2))); + else if (GST_OBJECT_PARENT (e2) == NULL) + g_warning ("Trying to link elements %s and %s that don't share a common " + "ancestor: %s hasn't been added to a bin or pipeline, and %s is in %s", + GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2), + GST_ELEMENT_NAME (e2), GST_ELEMENT_NAME (e1), + GST_ELEMENT_NAME (GST_OBJECT_PARENT (e1))); + else + g_warning ("Trying to link elements %s and %s that don't share a common " + "ancestor: %s is in %s, and %s is in %s", + GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2), + GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (GST_OBJECT_PARENT (e1)), + GST_ELEMENT_NAME (e2), GST_ELEMENT_NAME (GST_OBJECT_PARENT (e2))); + return FALSE; + } + + while (GST_OBJECT_PARENT (e1) != root) { + *src = ghost_up ((GstElement *) e1, *src); + if (!*src) + goto cleanup_fail; + e1 = GST_OBJECT_PARENT (*src); + pads_created_local = g_slist_prepend (pads_created_local, *src); + } + while (GST_OBJECT_PARENT (e2) != root) { + *sink = ghost_up ((GstElement *) e2, *sink); + if (!*sink) + goto cleanup_fail; + e2 = GST_OBJECT_PARENT (*sink); + pads_created_local = g_slist_prepend (pads_created_local, *sink); + } + + gst_object_unref (root); + *pads_created = g_slist_concat (*pads_created, pads_created_local); + return TRUE; + +cleanup_fail: + gst_object_unref (root); + g_slist_foreach (pads_created_local, remove_pad, NULL); + g_slist_free (pads_created_local); + return FALSE; +} + +static gboolean +pad_link_maybe_ghosting (GstPad * src, GstPad * sink, GstPadLinkCheck flags) +{ + GSList *pads_created = NULL; + gboolean ret; + + if (!prepare_link_maybe_ghosting (&src, &sink, &pads_created)) { + ret = FALSE; + } else { + ret = (gst_pad_link_full (src, sink, flags) == GST_PAD_LINK_OK); + } + + if (!ret) { + g_slist_foreach (pads_created, remove_pad, NULL); + } + g_slist_free (pads_created); + + return ret; +} + +/** + * gst_pad_link_maybe_ghosting_full: + * @src: a #GstPad + * @sink: a #GstPad + * @flags: some #GstPadLinkCheck flags + * + * Links @src to @sink, creating any #GstGhostPad's in between as necessary. + * + * This is a convenience function to save having to create and add intermediate + * #GstGhostPad's as required for linking across #GstBin boundaries. + * + * If @src or @sink pads don't have parent elements or do not share a common + * ancestor, the link will fail. + * + * Calling gst_pad_link_maybe_ghosting_full() with + * @flags == %GST_PAD_LINK_CHECK_DEFAULT is the recommended way of linking + * pads with safety checks applied. + * + * Returns: whether the link succeeded. + * + * Since: 1.10 + */ +gboolean +gst_pad_link_maybe_ghosting_full (GstPad * src, GstPad * sink, + GstPadLinkCheck flags) +{ + g_return_val_if_fail (GST_IS_PAD (src), FALSE); + g_return_val_if_fail (GST_IS_PAD (sink), FALSE); + + return pad_link_maybe_ghosting (src, sink, flags); +} + +/** + * gst_pad_link_maybe_ghosting: + * @src: a #GstPad + * @sink: a #GstPad + * + * Links @src to @sink, creating any #GstGhostPad's in between as necessary. + * + * This is a convenience function to save having to create and add intermediate + * #GstGhostPad's as required for linking across #GstBin boundaries. + * + * If @src or @sink pads don't have parent elements or do not share a common + * ancestor, the link will fail. + * + * Returns: whether the link succeeded. + * + * Since: 1.10 + */ +gboolean +gst_pad_link_maybe_ghosting (GstPad * src, GstPad * sink) +{ + g_return_val_if_fail (GST_IS_PAD (src), FALSE); + g_return_val_if_fail (GST_IS_PAD (sink), FALSE); + + return gst_pad_link_maybe_ghosting_full (src, sink, + GST_PAD_LINK_CHECK_DEFAULT); +} + +static void +release_and_unref_pad (GstElement * element, GstPad * pad, gboolean requestpad) +{ + if (pad) { + if (requestpad) + gst_element_release_request_pad (element, pad); + gst_object_unref (pad); + } +} + +/** + * gst_element_link_pads_full: + * @src: a #GstElement containing the source pad. + * @srcpadname: (allow-none): the name of the #GstPad in source element + * or %NULL for any pad. + * @dest: (transfer none): the #GstElement containing the destination pad. + * @destpadname: (allow-none): the name of the #GstPad in destination element, + * or %NULL for any pad. + * @flags: the #GstPadLinkCheck to be performed when linking pads. + * + * Links the two named pads of the source and destination elements. + * Side effect is that if one of the pads has no parent, it becomes a + * child of the parent of the other element. If they have different + * parents, the link fails. + * + * Calling gst_element_link_pads_full() with @flags == %GST_PAD_LINK_CHECK_DEFAULT + * is the same as calling gst_element_link_pads() and the recommended way of + * linking pads with safety checks applied. + * + * This is a convenience function for gst_pad_link_full(). + * + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. + */ +gboolean +gst_element_link_pads_full (GstElement * src, const gchar * srcpadname, + GstElement * dest, const gchar * destpadname, GstPadLinkCheck flags) +{ + const GList *srcpads, *destpads, *srctempls, *desttempls, *l; + GstPad *srcpad, *destpad; + GstPadTemplate *srctempl, *desttempl; + GstElementClass *srcclass, *destclass; + gboolean srcrequest, destrequest; + + /* checks */ + g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE); + + GST_CAT_INFO (GST_CAT_ELEMENT_PADS, + "trying to link element %s:%s to element %s:%s", GST_ELEMENT_NAME (src), + srcpadname ? srcpadname : "(any)", GST_ELEMENT_NAME (dest), + destpadname ? destpadname : "(any)"); + + srcrequest = FALSE; + destrequest = FALSE; + + /* get a src pad */ + if (srcpadname) { + /* name specified, look it up */ + if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) { + if ((srcpad = gst_element_get_request_pad (src, srcpadname))) + srcrequest = TRUE; + } + if (!srcpad) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s", + GST_ELEMENT_NAME (src), srcpadname); + return FALSE; + } else { + if (!(GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC)) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no src pad", + GST_DEBUG_PAD_NAME (srcpad)); + release_and_unref_pad (src, srcpad, srcrequest); + return FALSE; + } + if (GST_PAD_PEER (srcpad) != NULL) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "pad %s:%s is already linked to %s:%s", GST_DEBUG_PAD_NAME (srcpad), + GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad))); + /* already linked request pads look like static pads, so the request pad + * was never requested a second time above, so no need to release it */ + gst_object_unref (srcpad); + return FALSE; + } + } + srcpads = NULL; + } else { + /* no name given, get the first available pad */ + GST_OBJECT_LOCK (src); + srcpads = GST_ELEMENT_PADS (src); + srcpad = srcpads ? GST_PAD_CAST (srcpads->data) : NULL; + if (srcpad) + gst_object_ref (srcpad); + GST_OBJECT_UNLOCK (src); + } + + /* get a destination pad */ + if (destpadname) { + /* name specified, look it up */ + if (!(destpad = gst_element_get_static_pad (dest, destpadname))) { + if ((destpad = gst_element_get_request_pad (dest, destpadname))) + destrequest = TRUE; + } + if (!destpad) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s", + GST_ELEMENT_NAME (dest), destpadname); + release_and_unref_pad (src, srcpad, srcrequest); + return FALSE; + } else { + if (!(GST_PAD_DIRECTION (destpad) == GST_PAD_SINK)) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no sink pad", + GST_DEBUG_PAD_NAME (destpad)); + release_and_unref_pad (src, srcpad, srcrequest); + release_and_unref_pad (dest, destpad, destrequest); + return FALSE; + } + if (GST_PAD_PEER (destpad) != NULL) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "pad %s:%s is already linked to %s:%s", + GST_DEBUG_PAD_NAME (destpad), + GST_DEBUG_PAD_NAME (GST_PAD_PEER (destpad))); + release_and_unref_pad (src, srcpad, srcrequest); + /* already linked request pads look like static pads, so the request pad + * was never requested a second time above, so no need to release it */ + gst_object_unref (destpad); + return FALSE; + } + } + destpads = NULL; + } else { + /* no name given, get the first available pad */ + GST_OBJECT_LOCK (dest); + destpads = GST_ELEMENT_PADS (dest); + destpad = destpads ? GST_PAD_CAST (destpads->data) : NULL; + if (destpad) + gst_object_ref (destpad); + GST_OBJECT_UNLOCK (dest); + } + + if (srcpadname && destpadname) { + gboolean result; + + /* two explicitly specified pads */ + result = pad_link_maybe_ghosting (srcpad, destpad, flags); + + if (result) { + gst_object_unref (srcpad); + gst_object_unref (destpad); + } else { + release_and_unref_pad (src, srcpad, srcrequest); + release_and_unref_pad (dest, destpad, destrequest); + } + return result; + } + + if (srcpad) { + /* loop through the allowed pads in the source, trying to find a + * compatible destination pad */ + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "looping through allowed src and dest pads"); + do { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s", + GST_DEBUG_PAD_NAME (srcpad)); + if ((GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC) && + (GST_PAD_PEER (srcpad) == NULL)) { + gboolean temprequest = FALSE; + GstPad *temp; + + if (destpadname) { + temp = destpad; + gst_object_ref (temp); + } else { + temp = gst_element_get_compatible_pad (dest, srcpad, NULL); + if (temp && GST_PAD_PAD_TEMPLATE (temp) + && GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (temp)) == + GST_PAD_REQUEST) { + temprequest = TRUE; + } + } + + if (temp && pad_link_maybe_ghosting (srcpad, temp, flags)) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp)); + if (destpad) + gst_object_unref (destpad); + gst_object_unref (srcpad); + gst_object_unref (temp); + return TRUE; + } + + if (temp) { + if (temprequest) + gst_element_release_request_pad (dest, temp); + gst_object_unref (temp); + } + } + /* find a better way for this mess */ + if (srcpads) { + srcpads = g_list_next (srcpads); + if (srcpads) { + gst_object_unref (srcpad); + srcpad = GST_PAD_CAST (srcpads->data); + gst_object_ref (srcpad); + } + } + } while (srcpads); + } + if (srcpadname) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s:%s to %s", + GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (dest)); + /* no need to release any request pad as both src- and destpadname must be + * set to end up here, but this case has already been taken care of above */ + if (destpad) + gst_object_unref (destpad); + destpad = NULL; + } + if (srcpad) { + release_and_unref_pad (src, srcpad, srcrequest); + srcpad = NULL; + } + + if (destpad) { + /* loop through the existing pads in the destination */ + do { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s", + GST_DEBUG_PAD_NAME (destpad)); + if ((GST_PAD_DIRECTION (destpad) == GST_PAD_SINK) && + (GST_PAD_PEER (destpad) == NULL)) { + GstPad *temp = gst_element_get_compatible_pad (src, destpad, NULL); + gboolean temprequest = FALSE; + + if (temp && GST_PAD_PAD_TEMPLATE (temp) + && GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (temp)) == + GST_PAD_REQUEST) { + temprequest = TRUE; + } + + if (temp && pad_link_maybe_ghosting (temp, destpad, flags)) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s", + GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad)); + gst_object_unref (temp); + gst_object_unref (destpad); + return TRUE; + } + + release_and_unref_pad (src, temp, temprequest); + } + if (destpads) { + destpads = g_list_next (destpads); + if (destpads) { + gst_object_unref (destpad); + destpad = GST_PAD_CAST (destpads->data); + gst_object_ref (destpad); + } + } + } while (destpads); + } + + if (destpadname) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s:%s", + GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME (destpad)); + release_and_unref_pad (dest, destpad, destrequest); + return FALSE; + } else { + /* no need to release any request pad as the case of unset destpatname and + * destpad being a requst pad has already been taken care of when looking + * though the destination pads above */ + if (destpad) { + gst_object_unref (destpad); + } + destpad = NULL; + } + + srcclass = GST_ELEMENT_GET_CLASS (src); + destclass = GST_ELEMENT_GET_CLASS (dest); + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "we might have request pads on both sides, checking..."); + srctempls = gst_element_class_get_pad_template_list (srcclass); + desttempls = gst_element_class_get_pad_template_list (destclass); + + if (srctempls && desttempls) { + while (srctempls) { + srctempl = (GstPadTemplate *) srctempls->data; + if (srctempl->presence == GST_PAD_REQUEST) { + for (l = desttempls; l; l = l->next) { + desttempl = (GstPadTemplate *) l->data; + if (desttempl->presence == GST_PAD_REQUEST && + desttempl->direction != srctempl->direction) { + GstCaps *srccaps, *destcaps; + + srccaps = gst_pad_template_get_caps (srctempl); + destcaps = gst_pad_template_get_caps (desttempl); + if (gst_caps_is_always_compatible (srccaps, destcaps)) { + srcpad = + gst_element_request_pad (src, srctempl, + srctempl->name_template, NULL); + destpad = + gst_element_request_pad (dest, desttempl, + desttempl->name_template, NULL); + if (srcpad && destpad + && pad_link_maybe_ghosting (srcpad, destpad, flags)) { + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "linked pad %s:%s to pad %s:%s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); + gst_object_unref (srcpad); + gst_object_unref (destpad); + gst_caps_unref (srccaps); + gst_caps_unref (destcaps); + return TRUE; + } + /* it failed, so we release the request pads */ + if (srcpad) { + gst_element_release_request_pad (src, srcpad); + gst_object_unref (srcpad); + } + if (destpad) { + gst_element_release_request_pad (dest, destpad); + gst_object_unref (destpad); + } + } + gst_caps_unref (srccaps); + gst_caps_unref (destcaps); + } + } + } + srctempls = srctempls->next; + } + } + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s", + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest)); + return FALSE; +} + +/** + * gst_element_link_pads: + * @src: a #GstElement containing the source pad. + * @srcpadname: (allow-none): the name of the #GstPad in source element + * or %NULL for any pad. + * @dest: (transfer none): the #GstElement containing the destination pad. + * @destpadname: (allow-none): the name of the #GstPad in destination element, + * or %NULL for any pad. + * + * Links the two named pads of the source and destination elements. + * Side effect is that if one of the pads has no parent, it becomes a + * child of the parent of the other element. If they have different + * parents, the link fails. + * + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. + */ +gboolean +gst_element_link_pads (GstElement * src, const gchar * srcpadname, + GstElement * dest, const gchar * destpadname) +{ + return gst_element_link_pads_full (src, srcpadname, dest, destpadname, + GST_PAD_LINK_CHECK_DEFAULT); +} + +/** + * gst_element_link_pads_filtered: + * @src: a #GstElement containing the source pad. + * @srcpadname: (allow-none): the name of the #GstPad in source element + * or %NULL for any pad. + * @dest: (transfer none): the #GstElement containing the destination pad. + * @destpadname: (allow-none): the name of the #GstPad in destination element + * or %NULL for any pad. + * @filter: (transfer none) (allow-none): the #GstCaps to filter the link, + * or %NULL for no filter. + * + * Links the two named pads of the source and destination elements. Side effect + * is that if one of the pads has no parent, it becomes a child of the parent of + * the other element. If they have different parents, the link fails. If @caps + * is not %NULL, makes sure that the caps of the link is a subset of @caps. + * + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. + */ +gboolean +gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname, + GstElement * dest, const gchar * destpadname, GstCaps * filter) +{ + /* checks */ + g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE); + g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), FALSE); + + if (filter) { + GstElement *capsfilter; + GstObject *parent; + GstState state, pending; + gboolean lr1, lr2; + + capsfilter = gst_element_factory_make ("capsfilter", NULL); + if (!capsfilter) { + GST_ERROR ("Could not make a capsfilter"); + return FALSE; + } + + parent = gst_object_get_parent (GST_OBJECT (src)); + g_return_val_if_fail (GST_IS_BIN (parent), FALSE); + + gst_element_get_state (GST_ELEMENT_CAST (parent), &state, &pending, 0); + + if (!gst_bin_add (GST_BIN (parent), capsfilter)) { + GST_ERROR ("Could not add capsfilter"); + gst_object_unref (parent); + return FALSE; + } + + if (pending != GST_STATE_VOID_PENDING) + state = pending; + + gst_element_set_state (capsfilter, state); + + gst_object_unref (parent); + + g_object_set (capsfilter, "caps", filter, NULL); + + lr1 = gst_element_link_pads (src, srcpadname, capsfilter, "sink"); + lr2 = gst_element_link_pads (capsfilter, "src", dest, destpadname); + if (lr1 && lr2) { + return TRUE; + } else { + if (!lr1) { + GST_INFO ("Could not link pads: %s:%s - capsfilter:sink", + GST_ELEMENT_NAME (src), srcpadname); + } else { + GST_INFO ("Could not link pads: capsfilter:src - %s:%s", + GST_ELEMENT_NAME (dest), destpadname); + } + gst_element_set_state (capsfilter, GST_STATE_NULL); + /* this will unlink and unref as appropriate */ + gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (capsfilter)), capsfilter); + return FALSE; + } + } else { + if (gst_element_link_pads (src, srcpadname, dest, destpadname)) { + return TRUE; + } else { + GST_INFO ("Could not link pads: %s:%s - %s:%s", GST_ELEMENT_NAME (src), + srcpadname, GST_ELEMENT_NAME (dest), destpadname); + return FALSE; + } + } +} + +/** + * gst_element_link: + * @src: (transfer none): a #GstElement containing the source pad. + * @dest: (transfer none): the #GstElement containing the destination pad. + * + * Links @src to @dest. The link must be from source to + * destination; the other direction will not be tried. The function looks for + * existing pads that aren't linked yet. It will request new pads if necessary. + * Such pads need to be released manually when unlinking. + * If multiple links are possible, only one is established. + * + * Make sure you have added your elements to a bin or pipeline with + * gst_bin_add() before trying to link them. + * + * Returns: %TRUE if the elements could be linked, %FALSE otherwise. + */ +gboolean +gst_element_link (GstElement * src, GstElement * dest) +{ + return gst_element_link_pads (src, NULL, dest, NULL); +} + +/** + * gst_element_link_many: + * @element_1: (transfer none): the first #GstElement in the link chain. + * @element_2: (transfer none): the second #GstElement in the link chain. + * @...: the %NULL-terminated list of elements to link in order. + * + * Chain together a series of elements. Uses gst_element_link(). + * Make sure you have added your elements to a bin or pipeline with + * gst_bin_add() before trying to link them. + * + * Returns: %TRUE on success, %FALSE otherwise. + */ +gboolean +gst_element_link_many (GstElement * element_1, GstElement * element_2, ...) +{ + gboolean res = TRUE; + va_list args; + + g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE); + + va_start (args, element_2); + + while (element_2) { + if (!gst_element_link (element_1, element_2)) { + res = FALSE; + break; + } + + element_1 = element_2; + element_2 = va_arg (args, GstElement *); + } + + va_end (args); + + return res; +} + +/** + * gst_element_link_filtered: + * @src: a #GstElement containing the source pad. + * @dest: (transfer none): the #GstElement containing the destination pad. + * @filter: (transfer none) (allow-none): the #GstCaps to filter the link, + * or %NULL for no filter. + * + * Links @src to @dest using the given caps as filtercaps. + * The link must be from source to + * destination; the other direction will not be tried. The function looks for + * existing pads that aren't linked yet. It will request new pads if necessary. + * If multiple links are possible, only one is established. + * + * Make sure you have added your elements to a bin or pipeline with + * gst_bin_add() before trying to link them. + * + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. + */ +gboolean +gst_element_link_filtered (GstElement * src, GstElement * dest, + GstCaps * filter) +{ + return gst_element_link_pads_filtered (src, NULL, dest, NULL, filter); +} + +/** + * gst_element_unlink_pads: + * @src: a (transfer none): #GstElement containing the source pad. + * @srcpadname: the name of the #GstPad in source element. + * @dest: (transfer none): a #GstElement containing the destination pad. + * @destpadname: the name of the #GstPad in destination element. + * + * Unlinks the two named pads of the source and destination elements. + * + * This is a convenience function for gst_pad_unlink(). + */ +void +gst_element_unlink_pads (GstElement * src, const gchar * srcpadname, + GstElement * dest, const gchar * destpadname) +{ + GstPad *srcpad, *destpad; + gboolean srcrequest, destrequest; + + srcrequest = destrequest = FALSE; + + g_return_if_fail (src != NULL); + g_return_if_fail (GST_IS_ELEMENT (src)); + g_return_if_fail (srcpadname != NULL); + g_return_if_fail (dest != NULL); + g_return_if_fail (GST_IS_ELEMENT (dest)); + g_return_if_fail (destpadname != NULL); + + /* obtain the pads requested */ + if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) + if ((srcpad = gst_element_get_request_pad (src, srcpadname))) + srcrequest = TRUE; + if (srcpad == NULL) { + GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname); + return; + } + if (!(destpad = gst_element_get_static_pad (dest, destpadname))) + if ((destpad = gst_element_get_request_pad (dest, destpadname))) + destrequest = TRUE; + if (destpad == NULL) { + GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"", + destpadname); + goto free_src; + } + + /* we're satisfied they can be unlinked, let's do it */ + gst_pad_unlink (srcpad, destpad); + + if (destrequest) + gst_element_release_request_pad (dest, destpad); + gst_object_unref (destpad); + +free_src: + if (srcrequest) + gst_element_release_request_pad (src, srcpad); + gst_object_unref (srcpad); +} + +/** + * gst_element_unlink_many: + * @element_1: (transfer none): the first #GstElement in the link chain. + * @element_2: (transfer none): the second #GstElement in the link chain. + * @...: the %NULL-terminated list of elements to unlink in order. + * + * Unlinks a series of elements. Uses gst_element_unlink(). + */ +void +gst_element_unlink_many (GstElement * element_1, GstElement * element_2, ...) +{ + va_list args; + + g_return_if_fail (element_1 != NULL && element_2 != NULL); + g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2)); + + va_start (args, element_2); + + while (element_2) { + gst_element_unlink (element_1, element_2); + + element_1 = element_2; + element_2 = va_arg (args, GstElement *); + } + + va_end (args); +} + +/** + * gst_element_unlink: + * @src: (transfer none): the source #GstElement to unlink. + * @dest: (transfer none): the sink #GstElement to unlink. + * + * Unlinks all source pads of the source element with all sink pads + * of the sink element to which they are linked. + * + * If the link has been made using gst_element_link(), it could have created an + * requestpad, which has to be released using gst_element_release_request_pad(). + */ +void +gst_element_unlink (GstElement * src, GstElement * dest) +{ + GstIterator *pads; + gboolean done = FALSE; + GValue data = { 0, }; + + g_return_if_fail (GST_IS_ELEMENT (src)); + g_return_if_fail (GST_IS_ELEMENT (dest)); + + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unlinking \"%s\" and \"%s\"", + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest)); + + pads = gst_element_iterate_pads (src); + while (!done) { + switch (gst_iterator_next (pads, &data)) { + case GST_ITERATOR_OK: + { + GstPad *pad = g_value_get_object (&data); + + if (GST_PAD_IS_SRC (pad)) { + GstPad *peerpad = gst_pad_get_peer (pad); + + /* see if the pad is linked and is really a pad of dest */ + if (peerpad) { + GstElement *peerelem; + + peerelem = gst_pad_get_parent_element (peerpad); + + if (peerelem == dest) { + gst_pad_unlink (pad, peerpad); + } + if (peerelem) + gst_object_unref (peerelem); + + gst_object_unref (peerpad); + } + } + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pads); + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + default: + g_assert_not_reached (); + break; + } + } + g_value_unset (&data); + gst_iterator_free (pads); +} + +/** + * gst_element_query_position: + * @element: a #GstElement to invoke the position query on. + * @format: the #GstFormat requested + * @cur: (out) (allow-none): a location in which to store the current + * position, or %NULL. + * + * Queries an element (usually top-level pipeline or playbin element) for the + * stream position in nanoseconds. This will be a value between 0 and the + * stream duration (if the stream duration is known). This query will usually + * only work once the pipeline is prerolled (i.e. reached PAUSED or PLAYING + * state). The application will receive an ASYNC_DONE message on the pipeline + * bus when that is the case. + * + * If one repeatedly calls this function one can also create a query and reuse + * it in gst_element_query(). + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_element_query_position (GstElement * element, GstFormat format, + gint64 * cur) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_position (format); + ret = gst_element_query (element, query); + + if (ret) + gst_query_parse_position (query, NULL, cur); + + gst_query_unref (query); + + return ret; +} + +/** + * gst_element_query_duration: + * @element: a #GstElement to invoke the duration query on. + * @format: the #GstFormat requested + * @duration: (out) (allow-none): A location in which to store the total duration, or %NULL. + * + * Queries an element (usually top-level pipeline or playbin element) for the + * total stream duration in nanoseconds. This query will only work once the + * pipeline is prerolled (i.e. reached PAUSED or PLAYING state). The application + * will receive an ASYNC_DONE message on the pipeline bus when that is the case. + * + * If the duration changes for some reason, you will get a DURATION_CHANGED + * message on the pipeline bus, in which case you should re-query the duration + * using this function. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_element_query_duration (GstElement * element, GstFormat format, + gint64 * duration) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_duration (format); + ret = gst_element_query (element, query); + + if (ret) + gst_query_parse_duration (query, NULL, duration); + + gst_query_unref (query); + + return ret; +} + +/** + * gst_element_query_convert: + * @element: a #GstElement to invoke the convert query on. + * @src_format: a #GstFormat to convert from. + * @src_val: a value to convert. + * @dest_format: the #GstFormat to convert to. + * @dest_val: (out): a pointer to the result. + * + * Queries an element to convert @src_val in @src_format to @dest_format. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_element_query_convert (GstElement * element, GstFormat src_format, + gint64 src_val, GstFormat dest_format, gint64 * dest_val) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE); + g_return_val_if_fail (dest_val != NULL, FALSE); + + if (dest_format == src_format || src_val == -1) { + *dest_val = src_val; + return TRUE; + } + + query = gst_query_new_convert (src_format, src_val, dest_format); + ret = gst_element_query (element, query); + + if (ret) + gst_query_parse_convert (query, NULL, NULL, NULL, dest_val); + + gst_query_unref (query); + + return ret; +} + +/** + * gst_element_seek_simple: + * @element: a #GstElement to seek on + * @format: a #GstFormat to execute the seek in, such as #GST_FORMAT_TIME + * @seek_flags: seek options; playback applications will usually want to use + * GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here + * @seek_pos: position to seek to (relative to the start); if you are doing + * a seek in #GST_FORMAT_TIME this value is in nanoseconds - + * multiply with #GST_SECOND to convert seconds to nanoseconds or + * with #GST_MSECOND to convert milliseconds to nanoseconds. + * + * Simple API to perform a seek on the given element, meaning it just seeks + * to the given position relative to the start of the stream. For more complex + * operations like segment seeks (e.g. for looping) or changing the playback + * rate or seeking relative to the last configured playback segment you should + * use gst_element_seek(). + * + * In a completely prerolled PAUSED or PLAYING pipeline, seeking is always + * guaranteed to return %TRUE on a seekable media type or %FALSE when the media + * type is certainly not seekable (such as a live stream). + * + * Some elements allow for seeking in the READY state, in this + * case they will store the seek event and execute it when they are put to + * PAUSED. If the element supports seek in READY, it will always return %TRUE when + * it receives the event in the READY state. + * + * Returns: %TRUE if the seek operation succeeded. Flushing seeks will trigger a + * preroll, which will emit %GST_MESSAGE_ASYNC_DONE. + */ +gboolean +gst_element_seek_simple (GstElement * element, GstFormat format, + GstSeekFlags seek_flags, gint64 seek_pos) +{ + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + g_return_val_if_fail (seek_pos >= 0, FALSE); + + return gst_element_seek (element, 1.0, format, seek_flags, + GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); +} + +/** + * gst_pad_use_fixed_caps: + * @pad: the pad to use + * + * A helper function you can use that sets the FIXED_CAPS flag + * This way the default CAPS query will always return the negotiated caps + * or in case the pad is not negotiated, the padtemplate caps. + * + * The negotiated caps are the caps of the last CAPS event that passed on the + * pad. Use this function on a pad that, once it negotiated to a CAPS, cannot + * be renegotiated to something else. + */ +void +gst_pad_use_fixed_caps (GstPad * pad) +{ + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FIXED_CAPS); +} + +/** + * gst_pad_get_parent_element: + * @pad: a pad + * + * Gets the parent of @pad, cast to a #GstElement. If a @pad has no parent or + * its parent is not an element, return %NULL. + * + * Returns: (transfer full) (nullable): the parent of the pad. The + * caller has a reference on the parent, so unref when you're finished + * with it. + * + * MT safe. + */ +GstElement * +gst_pad_get_parent_element (GstPad * pad) +{ + GstObject *p; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + p = gst_object_get_parent (GST_OBJECT_CAST (pad)); + + if (p && !GST_IS_ELEMENT (p)) { + gst_object_unref (p); + p = NULL; + } + return GST_ELEMENT_CAST (p); +} + +/** + * gst_object_default_error: + * @source: the #GstObject that initiated the error. + * @error: (in): the GError. + * @debug: (in) (allow-none): an additional debug information string, or %NULL + * + * A default error function that uses g_printerr() to display the error message + * and the optional debug sting.. + * + * The default handler will simply print the error string using g_print. + */ +void +gst_object_default_error (GstObject * source, const GError * error, + const gchar * debug) +{ + gchar *name = gst_object_get_path_string (source); + + g_printerr (_("ERROR: from element %s: %s\n"), name, error->message); + if (debug) + g_printerr (_("Additional debug info:\n%s\n"), debug); + + g_free (name); +} + +/** + * gst_bin_add_many: (skip) + * @bin: a #GstBin + * @element_1: (transfer floating): the #GstElement element to add to the bin + * @...: additional elements to add to the bin + * + * Adds a %NULL-terminated list of elements to a bin. This function is + * equivalent to calling gst_bin_add() for each member of the list. The return + * value of each gst_bin_add() is ignored. + */ +void +gst_bin_add_many (GstBin * bin, GstElement * element_1, ...) +{ + va_list args; + + g_return_if_fail (GST_IS_BIN (bin)); + g_return_if_fail (GST_IS_ELEMENT (element_1)); + + va_start (args, element_1); + + while (element_1) { + gst_bin_add (bin, element_1); + + element_1 = va_arg (args, GstElement *); + } + + va_end (args); +} + +/** + * gst_bin_remove_many: (skip) + * @bin: a #GstBin + * @element_1: (transfer none): the first #GstElement to remove from the bin + * @...: (transfer none): %NULL-terminated list of elements to remove from the bin + * + * Remove a list of elements from a bin. This function is equivalent + * to calling gst_bin_remove() with each member of the list. + */ +void +gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...) +{ + va_list args; + + g_return_if_fail (GST_IS_BIN (bin)); + g_return_if_fail (GST_IS_ELEMENT (element_1)); + + va_start (args, element_1); + + while (element_1) { + gst_bin_remove (bin, element_1); + + element_1 = va_arg (args, GstElement *); + } + + va_end (args); +} + +typedef struct +{ + GstQuery *query; + gboolean ret; +} QueryAcceptCapsData; + +static gboolean +query_accept_caps_func (GstPad * pad, QueryAcceptCapsData * data) +{ + if (G_LIKELY (gst_pad_peer_query (pad, data->query))) { + gboolean result; + + gst_query_parse_accept_caps_result (data->query, &result); + data->ret &= result; + } + return FALSE; +} + +/** + * gst_pad_proxy_query_accept_caps: + * @pad: a #GstPad to proxy. + * @query: an ACCEPT_CAPS #GstQuery. + * + * Checks if all internally linked pads of @pad accepts the caps in @query and + * returns the intersection of the results. + * + * This function is useful as a default accept caps query function for an element + * that can handle any stream format, but requires caps that are acceptable for + * all opposite pads. + * + * Returns: %TRUE if @query could be executed + */ +gboolean +gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query) +{ + QueryAcceptCapsData data; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_QUERY (query), FALSE); + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS, FALSE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, + "proxying accept caps query for %s:%s", GST_DEBUG_PAD_NAME (pad)); + + data.query = query; + /* value to hold the return, by default it holds TRUE */ + /* FIXME: TRUE is wrong when there are no pads */ + data.ret = TRUE; + + gst_pad_forward (pad, (GstPadForwardFunction) query_accept_caps_func, &data); + gst_query_set_accept_caps_result (query, data.ret); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "proxying accept caps query: %d", + data.ret); + + return data.ret; +} + +typedef struct +{ + GstQuery *query; + GstCaps *ret; +} QueryCapsData; + +static gboolean +query_caps_func (GstPad * pad, QueryCapsData * data) +{ + gboolean empty = FALSE; + + if (G_LIKELY (gst_pad_peer_query (pad, data->query))) { + GstCaps *peercaps, *intersection; + + gst_query_parse_caps_result (data->query, &peercaps); + GST_DEBUG_OBJECT (pad, "intersect with result %" GST_PTR_FORMAT, peercaps); + intersection = gst_caps_intersect (data->ret, peercaps); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, intersection); + + gst_caps_unref (data->ret); + data->ret = intersection; + + /* stop when empty */ + empty = gst_caps_is_empty (intersection); + } + return empty; +} + +/** + * gst_pad_proxy_query_caps: + * @pad: a #GstPad to proxy. + * @query: a CAPS #GstQuery. + * + * Calls gst_pad_query_caps() for all internally linked pads of @pad and returns + * the intersection of the results. + * + * This function is useful as a default caps query function for an element + * that can handle any stream format, but requires all its pads to have + * the same caps. Two such elements are tee and adder. + * + * Returns: %TRUE if @query could be executed + */ +gboolean +gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query) +{ + GstCaps *filter, *templ, *result; + QueryCapsData data; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_QUERY (query), FALSE); + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS, FALSE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "proxying caps query for %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + data.query = query; + + /* value to hold the return, by default it holds the filter or ANY */ + gst_query_parse_caps (query, &filter); + data.ret = filter ? gst_caps_ref (filter) : gst_caps_new_any (); + + gst_pad_forward (pad, (GstPadForwardFunction) query_caps_func, &data); + + templ = gst_pad_get_pad_template_caps (pad); + result = gst_caps_intersect (data.ret, templ); + gst_caps_unref (data.ret); + gst_caps_unref (templ); + + gst_query_set_caps_result (query, result); + gst_caps_unref (result); + + /* FIXME: return something depending on the processing */ + return TRUE; +} + +/** + * gst_pad_query_position: + * @pad: a #GstPad to invoke the position query on. + * @format: the #GstFormat requested + * @cur: (out) (allow-none): A location in which to store the current position, or %NULL. + * + * Queries a pad for the stream position. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_position (format); + if ((ret = gst_pad_query (pad, query))) + gst_query_parse_position (query, NULL, cur); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_peer_query_position: + * @pad: a #GstPad on whose peer to invoke the position query on. + * Must be a sink pad. + * @format: the #GstFormat requested + * @cur: (out) (allow-none): a location in which to store the current + * position, or %NULL. + * + * Queries the peer of a given sink pad for the stream position. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur) +{ + GstQuery *query; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_position (format); + if ((ret = gst_pad_peer_query (pad, query))) + gst_query_parse_position (query, NULL, cur); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_query_duration: + * @pad: a #GstPad to invoke the duration query on. + * @format: the #GstFormat requested + * @duration: (out) (allow-none): a location in which to store the total + * duration, or %NULL. + * + * Queries a pad for the total stream duration. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_duration (format); + if ((ret = gst_pad_query (pad, query))) + gst_query_parse_duration (query, NULL, duration); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_peer_query_duration: + * @pad: a #GstPad on whose peer pad to invoke the duration query on. + * Must be a sink pad. + * @format: the #GstFormat requested + * @duration: (out) (allow-none): a location in which to store the total + * duration, or %NULL. + * + * Queries the peer pad of a given sink pad for the total stream duration. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration) +{ + GstQuery *query; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE); + g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); + + query = gst_query_new_duration (format); + if ((ret = gst_pad_peer_query (pad, query))) + gst_query_parse_duration (query, NULL, duration); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_query_convert: + * @pad: a #GstPad to invoke the convert query on. + * @src_format: a #GstFormat to convert from. + * @src_val: a value to convert. + * @dest_format: the #GstFormat to convert to. + * @dest_val: (out): a pointer to the result. + * + * Queries a pad to convert @src_val in @src_format to @dest_format. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, + GstFormat dest_format, gint64 * dest_val) +{ + GstQuery *query; + gboolean ret; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE); + g_return_val_if_fail (dest_val != NULL, FALSE); + + if (dest_format == src_format || src_val == -1) { + *dest_val = src_val; + return TRUE; + } + + query = gst_query_new_convert (src_format, src_val, dest_format); + if ((ret = gst_pad_query (pad, query))) + gst_query_parse_convert (query, NULL, NULL, NULL, dest_val); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_peer_query_convert: + * @pad: a #GstPad, on whose peer pad to invoke the convert query on. + * Must be a sink pad. + * @src_format: a #GstFormat to convert from. + * @src_val: a value to convert. + * @dest_format: the #GstFormat to convert to. + * @dest_val: (out): a pointer to the result. + * + * Queries the peer pad of a given sink pad to convert @src_val in @src_format + * to @dest_format. + * + * Returns: %TRUE if the query could be performed. + */ +gboolean +gst_pad_peer_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, + GstFormat dest_format, gint64 * dest_val) +{ + GstQuery *query; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE); + g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE); + g_return_val_if_fail (dest_val != NULL, FALSE); + + query = gst_query_new_convert (src_format, src_val, dest_format); + if ((ret = gst_pad_peer_query (pad, query))) + gst_query_parse_convert (query, NULL, NULL, NULL, dest_val); + gst_query_unref (query); + + return ret; +} + +/** + * gst_pad_query_caps: + * @pad: a #GstPad to get the capabilities of. + * @filter: (allow-none): suggested #GstCaps, or %NULL + * + * Gets the capabilities this pad can produce or consume. + * Note that this method doesn't necessarily return the caps set by sending a + * gst_event_new_caps() - use gst_pad_get_current_caps() for that instead. + * gst_pad_query_caps returns all possible caps a pad can operate with, using + * the pad's CAPS query function, If the query fails, this function will return + * @filter, if not %NULL, otherwise ANY. + * + * When called on sinkpads @filter contains the caps that + * upstream could produce in the order preferred by upstream. When + * called on srcpads @filter contains the caps accepted by + * downstream in the preferred order. @filter might be %NULL but + * if it is not %NULL the returned caps will be a subset of @filter. + * + * Note that this function does not return writable #GstCaps, use + * gst_caps_make_writable() before modifying the caps. + * + * Returns: (transfer full): the caps of the pad with incremented ref-count. + */ +GstCaps * +gst_pad_query_caps (GstPad * pad, GstCaps * filter) +{ + GstCaps *result = NULL; + GstQuery *query; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "get pad caps with filter %" GST_PTR_FORMAT, filter); + + query = gst_query_new_caps (filter); + if (gst_pad_query (pad, query)) { + gst_query_parse_caps_result (query, &result); + gst_caps_ref (result); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "query returned %" GST_PTR_FORMAT, result); + } else if (filter) { + result = gst_caps_ref (filter); + } else { + result = gst_caps_new_any (); + } + gst_query_unref (query); + + return result; +} + +/** + * gst_pad_peer_query_caps: + * @pad: a #GstPad to get the capabilities of. + * @filter: (allow-none): a #GstCaps filter, or %NULL. + * + * Gets the capabilities of the peer connected to this pad. Similar to + * gst_pad_query_caps(). + * + * When called on srcpads @filter contains the caps that + * upstream could produce in the order preferred by upstream. When + * called on sinkpads @filter contains the caps accepted by + * downstream in the preferred order. @filter might be %NULL but + * if it is not %NULL the returned caps will be a subset of @filter. + * + * Returns: (transfer full): the caps of the peer pad with incremented + * ref-count. When there is no peer pad, this function returns @filter or, + * when @filter is %NULL, ANY caps. + */ +GstCaps * +gst_pad_peer_query_caps (GstPad * pad, GstCaps * filter) +{ + GstCaps *result = NULL; + GstQuery *query; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "get pad peer caps with filter %" GST_PTR_FORMAT, filter); + + query = gst_query_new_caps (filter); + if (gst_pad_peer_query (pad, query)) { + gst_query_parse_caps_result (query, &result); + gst_caps_ref (result); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, + "peer query returned %" GST_PTR_FORMAT, result); + } else if (filter) { + result = gst_caps_ref (filter); + } else { + result = gst_caps_new_any (); + } + gst_query_unref (query); + + return result; +} + +/** + * gst_pad_query_accept_caps: + * @pad: a #GstPad to check + * @caps: a #GstCaps to check on the pad + * + * Check if the given pad accepts the caps. + * + * Returns: %TRUE if the pad can accept the caps. + */ +gboolean +gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps) +{ + gboolean res = TRUE; + GstQuery *query; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %" + GST_PTR_FORMAT, caps); + + query = gst_query_new_accept_caps (caps); + if (gst_pad_query (pad, query)) { + gst_query_parse_accept_caps_result (query, &res); + GST_DEBUG_OBJECT (pad, "query returned %d", res); + } + gst_query_unref (query); + + return res; +} + +/** + * gst_pad_peer_query_accept_caps: + * @pad: a #GstPad to check the peer of + * @caps: a #GstCaps to check on the pad + * + * Check if the peer of @pad accepts @caps. If @pad has no peer, this function + * returns %TRUE. + * + * Returns: %TRUE if the peer of @pad can accept the caps or @pad has no peer. + */ +gboolean +gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps * caps) +{ + gboolean res = TRUE; + GstQuery *query; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + query = gst_query_new_accept_caps (caps); + if (gst_pad_peer_query (pad, query)) { + gst_query_parse_accept_caps_result (query, &res); + GST_DEBUG_OBJECT (pad, "query returned %d", res); + } + gst_query_unref (query); + + return res; +} + +static GstPad * +element_find_unlinked_pad (GstElement * element, GstPadDirection direction) +{ + GstIterator *iter; + GstPad *unlinked_pad = NULL; + gboolean done; + GValue data = { 0, }; + + switch (direction) { + case GST_PAD_SRC: + iter = gst_element_iterate_src_pads (element); + break; + case GST_PAD_SINK: + iter = gst_element_iterate_sink_pads (element); + break; + default: + g_return_val_if_reached (NULL); + } + + done = FALSE; + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK:{ + GstPad *peer; + GstPad *pad = g_value_get_object (&data); + + GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + peer = gst_pad_get_peer (pad); + if (peer == NULL) { + unlinked_pad = gst_object_ref (pad); + done = TRUE; + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "found existing unlinked pad %s:%s", + GST_DEBUG_PAD_NAME (unlinked_pad)); + } else { + gst_object_unref (peer); + } + g_value_reset (&data); + break; + } + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + g_return_val_if_reached (NULL); + break; + } + } + g_value_unset (&data); + gst_iterator_free (iter); + + return unlinked_pad; +} + +/** + * gst_bin_find_unlinked_pad: + * @bin: bin in which to look for elements with unlinked pads + * @direction: whether to look for an unlinked source or sink pad + * + * Recursively looks for elements with an unlinked pad of the given + * direction within the specified bin and returns an unlinked pad + * if one is found, or %NULL otherwise. If a pad is found, the caller + * owns a reference to it and should use gst_object_unref() on the + * pad when it is not needed any longer. + * + * Returns: (transfer full) (nullable): unlinked pad of the given + * direction, %NULL. + */ +GstPad * +gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction) +{ + GstIterator *iter; + gboolean done; + GstPad *pad = NULL; + GValue data = { 0, }; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL); + + done = FALSE; + iter = gst_bin_iterate_recurse (bin); + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK:{ + GstElement *element = g_value_get_object (&data); + + pad = element_find_unlinked_pad (element, direction); + if (pad != NULL) + done = TRUE; + g_value_reset (&data); + break; + } + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + g_return_val_if_reached (NULL); + break; + } + } + g_value_unset (&data); + gst_iterator_free (iter); + + return pad; +} + +static void +gst_bin_sync_children_states_foreach (const GValue * value, gpointer user_data) +{ + gboolean *success = user_data; + GstElement *element = g_value_get_object (value); + + if (gst_element_is_locked_state (element)) { + *success = TRUE; + } else { + *success = *success && gst_element_sync_state_with_parent (element); + + if (GST_IS_BIN (element)) + *success = *success + && gst_bin_sync_children_states (GST_BIN_CAST (element)); + } +} + +/** + * gst_bin_sync_children_states: + * @bin: a #GstBin + * + * Synchronizes the state of every child of @bin with the state + * of @bin. See also gst_element_sync_state_with_parent(). + * + * Returns: %TRUE if syncing the state was successful for all children, + * otherwise %FALSE. + * + * Since: 1.6 + */ +gboolean +gst_bin_sync_children_states (GstBin * bin) +{ + GstIterator *it; + GstIteratorResult res = GST_ITERATOR_OK; + gboolean success = TRUE; + + it = gst_bin_iterate_sorted (bin); + + do { + if (res == GST_ITERATOR_RESYNC) { + success = TRUE; + gst_iterator_resync (it); + } + res = + gst_iterator_foreach (it, gst_bin_sync_children_states_foreach, + &success); + } while (res == GST_ITERATOR_RESYNC); + gst_iterator_free (it); + + return success; +} + +/** + * gst_parse_bin_from_description: + * @bin_description: command line describing the bin + * @ghost_unlinked_pads: whether to automatically create ghost pads + * for unlinked source or sink pads within the bin + * @err: where to store the error message in case of an error, or %NULL + * + * This is a convenience wrapper around gst_parse_launch() to create a + * #GstBin from a gst-launch-style pipeline description. See + * gst_parse_launch() and the gst-launch man page for details about the + * syntax. Ghost pads on the bin for unlinked source or sink pads + * within the bin can automatically be created (but only a maximum of + * one ghost pad for each direction will be created; if you expect + * multiple unlinked source pads or multiple unlinked sink pads + * and want them all ghosted, you will have to create the ghost pads + * yourself). + * + * Returns: (transfer floating) (type Gst.Bin) (nullable): a + * newly-created bin, or %NULL if an error occurred. + */ +GstElement * +gst_parse_bin_from_description (const gchar * bin_description, + gboolean ghost_unlinked_pads, GError ** err) +{ + return gst_parse_bin_from_description_full (bin_description, + ghost_unlinked_pads, NULL, GST_PARSE_FLAG_NONE, err); +} + +/** + * gst_parse_bin_from_description_full: + * @bin_description: command line describing the bin + * @ghost_unlinked_pads: whether to automatically create ghost pads + * for unlinked source or sink pads within the bin + * @context: (transfer none) (allow-none): a parse context allocated with + * gst_parse_context_new(), or %NULL + * @flags: parsing options, or #GST_PARSE_FLAG_NONE + * @err: where to store the error message in case of an error, or %NULL + * + * This is a convenience wrapper around gst_parse_launch() to create a + * #GstBin from a gst-launch-style pipeline description. See + * gst_parse_launch() and the gst-launch man page for details about the + * syntax. Ghost pads on the bin for unlinked source or sink pads + * within the bin can automatically be created (but only a maximum of + * one ghost pad for each direction will be created; if you expect + * multiple unlinked source pads or multiple unlinked sink pads + * and want them all ghosted, you will have to create the ghost pads + * yourself). + * + * Returns: (transfer floating) (type Gst.Element) (nullable): a newly-created + * element, which is guaranteed to be a bin unless + * GST_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error + * occurred. + */ +GstElement * +gst_parse_bin_from_description_full (const gchar * bin_description, + gboolean ghost_unlinked_pads, GstParseContext * context, + GstParseFlags flags, GError ** err) +{ +#ifndef GST_DISABLE_PARSE + GstPad *pad = NULL; + GstElement *element; + GstBin *bin; + gchar *desc; + + g_return_val_if_fail (bin_description != NULL, NULL); + g_return_val_if_fail (err == NULL || *err == NULL, NULL); + + GST_DEBUG ("Making bin from description '%s'", bin_description); + + /* parse the pipeline to a bin */ + if (flags & GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS) { + element = gst_parse_launch_full (bin_description, context, flags, err); + } else { + desc = g_strdup_printf ("bin.( %s )", bin_description); + element = gst_parse_launch_full (desc, context, flags, err); + g_free (desc); + } + + if (element == NULL || (err && *err != NULL)) { + if (element) + gst_object_unref (element); + return NULL; + } + + if (GST_IS_BIN (element)) { + bin = GST_BIN (element); + } else { + return element; + } + + /* find pads and ghost them if necessary */ + if (ghost_unlinked_pads) { + if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); + gst_object_unref (pad); + } + if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + } + } + + return GST_ELEMENT (bin); +#else + gchar *msg; + + GST_WARNING ("Disabled API called"); + + msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED); + g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg); + g_free (msg); + + return NULL; +#endif +} + +/** + * gst_util_get_timestamp: + * + * Get a timestamp as GstClockTime to be used for interval measurements. + * The timestamp should not be interpreted in any other way. + * + * Returns: the timestamp + */ +GstClockTime +gst_util_get_timestamp (void) +{ +#if defined (HAVE_POSIX_TIMERS) && defined(HAVE_MONOTONIC_CLOCK) &&\ + defined (HAVE_CLOCK_GETTIME) + struct timespec now; + + clock_gettime (CLOCK_MONOTONIC, &now); + return GST_TIMESPEC_TO_TIME (now); +#else + return g_get_monotonic_time () * 1000; +#endif +} + +/** + * gst_util_array_binary_search: + * @array: the sorted input array + * @num_elements: number of elements in the array + * @element_size: size of every element in bytes + * @search_func: (scope call): function to compare two elements, @search_data will always be passed as second argument + * @mode: search mode that should be used + * @search_data: element that should be found + * @user_data: (closure): data to pass to @search_func + * + * Searches inside @array for @search_data by using the comparison function + * @search_func. @array must be sorted ascending. + * + * As @search_data is always passed as second argument to @search_func it's + * not required that @search_data has the same type as the array elements. + * + * The complexity of this search function is O(log (num_elements)). + * + * Returns: (transfer none) (nullable): The address of the found + * element or %NULL if nothing was found + */ +gpointer +gst_util_array_binary_search (gpointer array, guint num_elements, + gsize element_size, GCompareDataFunc search_func, GstSearchMode mode, + gconstpointer search_data, gpointer user_data) +{ + glong left = 0, right = num_elements - 1, m; + gint ret; + guint8 *data = (guint8 *) array; + + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (element_size > 0, NULL); + g_return_val_if_fail (search_func != NULL, NULL); + + /* 0. No elements => return NULL */ + if (num_elements == 0) + return NULL; + + /* 1. If search_data is before the 0th element return the 0th element */ + ret = search_func (data, search_data, user_data); + if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0) + return data; + else if (ret > 0) + return NULL; + + /* 2. If search_data is after the last element return the last element */ + ret = + search_func (data + (num_elements - 1) * element_size, search_data, + user_data); + if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0) + return data + (num_elements - 1) * element_size; + else if (ret < 0) + return NULL; + + /* 3. else binary search */ + while (TRUE) { + m = left + (right - left) / 2; + + ret = search_func (data + m * element_size, search_data, user_data); + + if (ret == 0) { + return data + m * element_size; + } else if (ret < 0) { + left = m + 1; + } else { + right = m - 1; + } + + /* No exact match found */ + if (right < left) { + if (mode == GST_SEARCH_MODE_EXACT) { + return NULL; + } else if (mode == GST_SEARCH_MODE_AFTER) { + if (ret < 0) + return (m < num_elements) ? data + (m + 1) * element_size : NULL; + else + return data + m * element_size; + } else { + if (ret < 0) + return data + m * element_size; + else + return (m > 0) ? data + (m - 1) * element_size : NULL; + } + } + } +} + +/* Finds the greatest common divisor. + * Returns 1 if none other found. + * This is Euclid's algorithm. */ + +/** + * gst_util_greatest_common_divisor: + * @a: First value as #gint + * @b: Second value as #gint + * + * Calculates the greatest common divisor of @a + * and @b. + * + * Returns: Greatest common divisor of @a and @b + */ +gint +gst_util_greatest_common_divisor (gint a, gint b) +{ + while (b != 0) { + int temp = a; + + a = b; + b = temp % b; + } + + return ABS (a); +} + +/** + * gst_util_greatest_common_divisor_int64: + * @a: First value as #gint64 + * @b: Second value as #gint64 + * + * Calculates the greatest common divisor of @a + * and @b. + * + * Returns: Greatest common divisor of @a and @b + */ +gint64 +gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b) +{ + while (b != 0) { + gint64 temp = a; + + a = b; + b = temp % b; + } + + return ABS (a); +} + + +/** + * gst_util_fraction_to_double: + * @src_n: Fraction numerator as #gint + * @src_d: Fraction denominator #gint + * @dest: (out): pointer to a #gdouble for the result + * + * Transforms a fraction to a #gdouble. + */ +void +gst_util_fraction_to_double (gint src_n, gint src_d, gdouble * dest) +{ + g_return_if_fail (dest != NULL); + g_return_if_fail (src_d != 0); + + *dest = ((gdouble) src_n) / ((gdouble) src_d); +} + +#define MAX_TERMS 30 +#define MIN_DIVISOR 1.0e-10 +#define MAX_ERROR 1.0e-20 + +/* use continued fractions to transform a double into a fraction, + * see http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac. + * This algorithm takes care of overflows. + */ + +/** + * gst_util_double_to_fraction: + * @src: #gdouble to transform + * @dest_n: (out): pointer to a #gint to hold the result numerator + * @dest_d: (out): pointer to a #gint to hold the result denominator + * + * Transforms a #gdouble to a fraction and simplifies + * the result. + */ +void +gst_util_double_to_fraction (gdouble src, gint * dest_n, gint * dest_d) +{ + + gdouble V, F; /* double being converted */ + gint N, D; /* will contain the result */ + gint A; /* current term in continued fraction */ + gint64 N1, D1; /* numerator, denominator of last approx */ + gint64 N2, D2; /* numerator, denominator of previous approx */ + gint i; + gint gcd; + gboolean negative = FALSE; + + g_return_if_fail (dest_n != NULL); + g_return_if_fail (dest_d != NULL); + + /* initialize fraction being converted */ + F = src; + if (F < 0.0) { + F = -F; + negative = TRUE; + } + + V = F; + /* initialize fractions with 1/0, 0/1 */ + N1 = 1; + D1 = 0; + N2 = 0; + D2 = 1; + N = 1; + D = 1; + + for (i = 0; i < MAX_TERMS; i++) { + /* get next term */ + A = (gint) F; /* no floor() needed, F is always >= 0 */ + /* get new divisor */ + F = F - A; + + /* calculate new fraction in temp */ + N2 = N1 * A + N2; + D2 = D1 * A + D2; + + /* guard against overflow */ + if (N2 > G_MAXINT || D2 > G_MAXINT) { + break; + } + + N = N2; + D = D2; + + /* save last two fractions */ + N2 = N1; + D2 = D1; + N1 = N; + D1 = D; + + /* quit if dividing by zero or close enough to target */ + if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) { + break; + } + + /* Take reciprocal */ + F = 1 / F; + } + /* fix for overflow */ + if (D == 0) { + N = G_MAXINT; + D = 1; + } + /* fix for negative */ + if (negative) + N = -N; + + /* simplify */ + gcd = gst_util_greatest_common_divisor (N, D); + if (gcd) { + N /= gcd; + D /= gcd; + } + + /* set results */ + *dest_n = N; + *dest_d = D; +} + +/** + * gst_util_fraction_multiply: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * @res_n: (out): Pointer to #gint to hold the result numerator + * @res_d: (out): Pointer to #gint to hold the result denominator + * + * Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores + * the result in @res_n and @res_d. + * + * Returns: %FALSE on overflow, %TRUE otherwise. + */ +gboolean +gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, + gint * res_n, gint * res_d) +{ + gint gcd; + + g_return_val_if_fail (res_n != NULL, FALSE); + g_return_val_if_fail (res_d != NULL, FALSE); + g_return_val_if_fail (a_d != 0, FALSE); + g_return_val_if_fail (b_d != 0, FALSE); + + /* early out if either is 0, as its gcd would be 0 */ + if (a_n == 0 || b_n == 0) { + *res_n = 0; + *res_d = 1; + return TRUE; + } + + gcd = gst_util_greatest_common_divisor (a_n, a_d); + a_n /= gcd; + a_d /= gcd; + + gcd = gst_util_greatest_common_divisor (b_n, b_d); + b_n /= gcd; + b_d /= gcd; + + gcd = gst_util_greatest_common_divisor (a_n, b_d); + a_n /= gcd; + b_d /= gcd; + + gcd = gst_util_greatest_common_divisor (a_d, b_n); + a_d /= gcd; + b_n /= gcd; + + /* This would result in overflow */ + if (a_n != 0 && G_MAXINT / ABS (a_n) < ABS (b_n)) + return FALSE; + if (G_MAXINT / ABS (a_d) < ABS (b_d)) + return FALSE; + + *res_n = a_n * b_n; + *res_d = a_d * b_d; + + gcd = gst_util_greatest_common_divisor (*res_n, *res_d); + *res_n /= gcd; + *res_d /= gcd; + + return TRUE; +} + +/** + * gst_util_fraction_add: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * @res_n: (out): Pointer to #gint to hold the result numerator + * @res_d: (out): Pointer to #gint to hold the result denominator + * + * Adds the fractions @a_n/@a_d and @b_n/@b_d and stores + * the result in @res_n and @res_d. + * + * Returns: %FALSE on overflow, %TRUE otherwise. + */ +gboolean +gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint * res_n, + gint * res_d) +{ + gint gcd; + + g_return_val_if_fail (res_n != NULL, FALSE); + g_return_val_if_fail (res_d != NULL, FALSE); + g_return_val_if_fail (a_d != 0, FALSE); + g_return_val_if_fail (b_d != 0, FALSE); + + gcd = gst_util_greatest_common_divisor (a_n, a_d); + a_n /= gcd; + a_d /= gcd; + + gcd = gst_util_greatest_common_divisor (b_n, b_d); + b_n /= gcd; + b_d /= gcd; + + if (a_n == 0) { + *res_n = b_n; + *res_d = b_d; + return TRUE; + } + if (b_n == 0) { + *res_n = a_n; + *res_d = a_d; + return TRUE; + } + + /* This would result in overflow */ + if (G_MAXINT / ABS (a_n) < ABS (b_n)) + return FALSE; + if (G_MAXINT / ABS (a_d) < ABS (b_d)) + return FALSE; + + *res_n = (a_n * b_d) + (a_d * b_n); + *res_d = a_d * b_d; + + gcd = gst_util_greatest_common_divisor (*res_n, *res_d); + if (gcd) { + *res_n /= gcd; + *res_d /= gcd; + } else { + /* res_n == 0 */ + *res_d = 1; + } + + return TRUE; +} + +/** + * gst_util_fraction_compare: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * + * Compares the fractions @a_n/@a_d and @b_n/@b_d and returns + * -1 if a < b, 0 if a = b and 1 if a > b. + * + * Returns: -1 if a < b; 0 if a = b; 1 if a > b. + */ +gint +gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d) +{ + gint64 new_num_1; + gint64 new_num_2; + gint gcd; + + g_return_val_if_fail (a_d != 0 && b_d != 0, 0); + + /* Simplify */ + gcd = gst_util_greatest_common_divisor (a_n, a_d); + a_n /= gcd; + a_d /= gcd; + + gcd = gst_util_greatest_common_divisor (b_n, b_d); + b_n /= gcd; + b_d /= gcd; + + /* fractions are reduced when set, so we can quickly see if they're equal */ + if (a_n == b_n && a_d == b_d) + return 0; + + /* extend to 64 bits */ + new_num_1 = ((gint64) a_n) * b_d; + new_num_2 = ((gint64) b_n) * a_d; + if (new_num_1 < new_num_2) + return -1; + if (new_num_1 > new_num_2) + return 1; + + /* Should not happen because a_d and b_d are not 0 */ + g_return_val_if_reached (0); +} + +static gchar * +gst_pad_create_stream_id_internal (GstPad * pad, GstElement * parent, + const gchar * stream_id) +{ + GstEvent *upstream_event; + gchar *upstream_stream_id = NULL, *new_stream_id; + GstPad *sinkpad; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL); + g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL); + + g_return_val_if_fail (parent->numsinkpads <= 1, NULL); + + /* If the element has multiple source pads it must + * provide a stream-id for every source pad, otherwise + * all source pads will have the same and are not + * distinguishable */ + g_return_val_if_fail (parent->numsrcpads <= 1 || stream_id, NULL); + + /* First try to get the upstream stream-start stream-id from the sinkpad. + * This will only work for non-source elements */ + sinkpad = gst_element_get_static_pad (parent, "sink"); + if (sinkpad) { + upstream_event = + gst_pad_get_sticky_event (sinkpad, GST_EVENT_STREAM_START, 0); + if (upstream_event) { + const gchar *tmp; + + gst_event_parse_stream_start (upstream_event, &tmp); + if (tmp) + upstream_stream_id = g_strdup (tmp); + gst_event_unref (upstream_event); + } + gst_object_unref (sinkpad); + } + + /* The only case where we don't have an upstream start-start event + * here is for source elements */ + if (!upstream_stream_id) { + GstQuery *query; + gchar *uri = NULL; + + /* Try to generate one from the URI query and + * if it fails take a random number instead */ + query = gst_query_new_uri (); + if (gst_element_query (parent, query)) { + gst_query_parse_uri (query, &uri); + } + + if (uri) { + GChecksum *cs; + + /* And then generate an SHA256 sum of the URI */ + cs = g_checksum_new (G_CHECKSUM_SHA256); + g_checksum_update (cs, (const guchar *) uri, strlen (uri)); + g_free (uri); + upstream_stream_id = g_strdup (g_checksum_get_string (cs)); + g_checksum_free (cs); + } else { + /* Just get some random number if the URI query fails */ + GST_FIXME_OBJECT (pad, "Creating random stream-id, consider " + "implementing a deterministic way of creating a stream-id"); + upstream_stream_id = + g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (), + g_random_int (), g_random_int ()); + } + + gst_query_unref (query); + } + + if (stream_id) { + new_stream_id = g_strconcat (upstream_stream_id, "/", stream_id, NULL); + } else { + new_stream_id = g_strdup (upstream_stream_id); + } + + g_free (upstream_stream_id); + + return new_stream_id; +} + +/** + * gst_pad_create_stream_id_printf_valist: + * @pad: A source #GstPad + * @parent: Parent #GstElement of @pad + * @stream_id: (allow-none): The stream-id + * @var_args: parameters for the @stream_id format string + * + * Creates a stream-id for the source #GstPad @pad by combining the + * upstream information with the optional @stream_id of the stream + * of @pad. @pad must have a parent #GstElement and which must have zero + * or one sinkpad. @stream_id can only be %NULL if the parent element + * of @pad has only a single source pad. + * + * This function generates an unique stream-id by getting the upstream + * stream-start event stream ID and appending @stream_id to it. If the + * element has no sinkpad it will generate an upstream stream-id by + * doing an URI query on the element and in the worst case just uses + * a random number. Source elements that don't implement the URI + * handler interface should ideally generate a unique, deterministic + * stream-id manually instead. + * + * Returns: A stream-id for @pad. g_free() after usage. + */ +gchar * +gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, + const gchar * stream_id, va_list var_args) +{ + gchar *expanded = NULL, *new_stream_id; + + if (stream_id) + expanded = g_strdup_vprintf (stream_id, var_args); + + new_stream_id = gst_pad_create_stream_id_internal (pad, parent, expanded); + + g_free (expanded); + + return new_stream_id; +} + +/** + * gst_pad_create_stream_id_printf: + * @pad: A source #GstPad + * @parent: Parent #GstElement of @pad + * @stream_id: (allow-none): The stream-id + * @...: parameters for the @stream_id format string + * + * Creates a stream-id for the source #GstPad @pad by combining the + * upstream information with the optional @stream_id of the stream + * of @pad. @pad must have a parent #GstElement and which must have zero + * or one sinkpad. @stream_id can only be %NULL if the parent element + * of @pad has only a single source pad. + * + * This function generates an unique stream-id by getting the upstream + * stream-start event stream ID and appending @stream_id to it. If the + * element has no sinkpad it will generate an upstream stream-id by + * doing an URI query on the element and in the worst case just uses + * a random number. Source elements that don't implement the URI + * handler interface should ideally generate a unique, deterministic + * stream-id manually instead. + * + * Returns: A stream-id for @pad. g_free() after usage. + */ +gchar * +gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent, + const gchar * stream_id, ...) +{ + va_list var_args; + gchar *new_stream_id; + + va_start (var_args, stream_id); + new_stream_id = + gst_pad_create_stream_id_printf_valist (pad, parent, stream_id, var_args); + va_end (var_args); + + return new_stream_id; +} + +/** + * gst_pad_create_stream_id: + * @pad: A source #GstPad + * @parent: Parent #GstElement of @pad + * @stream_id: (allow-none): The stream-id + * + * Creates a stream-id for the source #GstPad @pad by combining the + * upstream information with the optional @stream_id of the stream + * of @pad. @pad must have a parent #GstElement and which must have zero + * or one sinkpad. @stream_id can only be %NULL if the parent element + * of @pad has only a single source pad. + * + * This function generates an unique stream-id by getting the upstream + * stream-start event stream ID and appending @stream_id to it. If the + * element has no sinkpad it will generate an upstream stream-id by + * doing an URI query on the element and in the worst case just uses + * a random number. Source elements that don't implement the URI + * handler interface should ideally generate a unique, deterministic + * stream-id manually instead. + * + * Since stream IDs are sorted alphabetically, any numbers in the + * stream ID should be printed with a fixed number of characters, + * preceded by 0's, such as by using the format \%03u instead of \%u. + * + * Returns: A stream-id for @pad. g_free() after usage. + */ +gchar * +gst_pad_create_stream_id (GstPad * pad, GstElement * parent, + const gchar * stream_id) +{ + return gst_pad_create_stream_id_internal (pad, parent, stream_id); +} + +/** + * gst_pad_get_stream_id: + * @pad: A source #GstPad + * + * Returns the current stream-id for the @pad, or %NULL if none has been + * set yet, i.e. the pad has not received a stream-start event yet. + * + * This is a convenience wrapper around gst_pad_get_sticky_event() and + * gst_event_parse_stream_start(). + * + * The returned stream-id string should be treated as an opaque string, its + * contents should not be interpreted. + * + * Returns: (nullable): a newly-allocated copy of the stream-id for + * @pad, or %NULL. g_free() the returned string when no longer + * needed. + * + * Since: 1.2 + */ +gchar * +gst_pad_get_stream_id (GstPad * pad) +{ + const gchar *stream_id = NULL; + GstEvent *event; + gchar *ret = NULL; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + event = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0); + if (event != NULL) { + gst_event_parse_stream_start (event, &stream_id); + ret = g_strdup (stream_id); + gst_event_unref (event); + GST_LOG_OBJECT (pad, "pad has stream-id '%s'", ret); + } else { + GST_DEBUG_OBJECT (pad, "pad has not received a stream-start event yet"); + } + + return ret; +} + +/** + * gst_pad_get_stream: + * @pad: A source #GstPad + * + * Returns the current #GstStream for the @pad, or %NULL if none has been + * set yet, i.e. the pad has not received a stream-start event yet. + * + * This is a convenience wrapper around gst_pad_get_sticky_event() and + * gst_event_parse_stream(). + * + * Returns: (nullable) (transfer full): the current #GstStream for @pad, or %NULL. + * unref the returned stream when no longer needed. + * + * Since: 1.10 + */ +GstStream * +gst_pad_get_stream (GstPad * pad) +{ + GstStream *stream = NULL; + GstEvent *event; + + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + event = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0); + if (event != NULL) { + gst_event_parse_stream (event, &stream); + gst_event_unref (event); + GST_LOG_OBJECT (pad, "pad has stream object %p", stream); + } else { + GST_DEBUG_OBJECT (pad, "pad has not received a stream-start event yet"); + } + + return stream; +} + +/** + * gst_util_group_id_next: + * + * Return a constantly incrementing group id. + * + * This function is used to generate a new group-id for the + * stream-start event. + * + * This function never returns %GST_GROUP_ID_INVALID (which is 0) + * + * Returns: A constantly incrementing unsigned integer, which might + * overflow back to 0 at some point. + */ +guint +gst_util_group_id_next (void) +{ + static gint counter = 1; + gint ret = g_atomic_int_add (&counter, 1); + + /* Make sure we don't return GST_GROUP_ID_INVALID */ + if (G_UNLIKELY (ret == GST_GROUP_ID_INVALID)) + ret = g_atomic_int_add (&counter, 1); + + return ret; +} + +/* Compute log2 of the passed 64-bit number by finding the highest set bit */ +static guint +gst_log2 (GstClockTime in) +{ + const guint64 b[] = + { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000LL }; + const guint64 S[] = { 1, 2, 4, 8, 16, 32 }; + int i; + + guint count = 0; + for (i = 5; i >= 0; i--) { + if (in & b[i]) { + in >>= S[i]; + count |= S[i]; + } + } + + return count; +} + +/** + * gst_calculate_linear_regression: (skip) + * @xy: Pairs of (x,y) values + * @temp: Temporary scratch space used by the function + * @n: number of (x,y) pairs + * @m_num: (out): numerator of calculated slope + * @m_denom: (out): denominator of calculated slope + * @b: (out): Offset at Y-axis + * @xbase: (out): Offset at X-axis + * @r_squared: (out): R-squared + * + * Calculates the linear regression of the values @xy and places the + * result in @m_num, @m_denom, @b and @xbase, representing the function + * y(x) = m_num/m_denom * (x - xbase) + b + * that has the least-square distance from all points @x and @y. + * + * @r_squared will contain the remaining error. + * + * If @temp is not %NULL, it will be used as temporary space for the function, + * in which case the function works without any allocation at all. If @temp is + * %NULL, an allocation will take place. @temp should have at least the same + * amount of memory allocated as @xy, i.e. 2*n*sizeof(GstClockTime). + * + * > This function assumes (x,y) values with reasonable large differences + * > between them. It will not calculate the exact results if the differences + * > between neighbouring values are too small due to not being able to + * > represent sub-integer values during the calculations. + * + * Returns: %TRUE if the linear regression was successfully calculated + * + * Since: 1.12 + */ +/* http://mathworld.wolfram.com/LeastSquaresFitting.html + * with SLAVE_LOCK + */ +gboolean +gst_calculate_linear_regression (const GstClockTime * xy, + GstClockTime * temp, guint n, + GstClockTime * m_num, GstClockTime * m_denom, + GstClockTime * b, GstClockTime * xbase, gdouble * r_squared) +{ + const GstClockTime *x, *y; + GstClockTime *newx, *newy; + GstClockTime xmin, ymin, xbar, ybar, xbar4, ybar4; + GstClockTime xmax, ymax; + GstClockTimeDiff sxx, sxy, syy; + gint i, j; + gint pshift = 0; + gint max_bits; + + g_return_val_if_fail (xy != NULL, FALSE); + g_return_val_if_fail (m_num != NULL, FALSE); + g_return_val_if_fail (m_denom != NULL, FALSE); + g_return_val_if_fail (b != NULL, FALSE); + g_return_val_if_fail (xbase != NULL, FALSE); + g_return_val_if_fail (r_squared != NULL, FALSE); + + x = xy; + y = xy + 1; + + xbar = ybar = sxx = syy = sxy = 0; + + xmin = ymin = G_MAXUINT64; + xmax = ymax = 0; + for (i = j = 0; i < n; i++, j += 2) { + xmin = MIN (xmin, x[j]); + ymin = MIN (ymin, y[j]); + + xmax = MAX (xmax, x[j]); + ymax = MAX (ymax, y[j]); + } + + if (temp == NULL) { + /* Allocate up to 1kb on the stack, otherwise heap */ + newx = n > 64 ? g_new (GstClockTime, 2 * n) : g_newa (GstClockTime, 2 * n); + newy = newx + 1; + } else { + newx = temp; + newy = temp + 1; + } + + /* strip off unnecessary bits of precision */ + for (i = j = 0; i < n; i++, j += 2) { + newx[j] = x[j] - xmin; + newy[j] = y[j] - ymin; + } + +#ifdef DEBUGGING_ENABLED + GST_CAT_DEBUG (GST_CAT_CLOCK, "reduced numbers:"); + for (i = j = 0; i < n; i++, j += 2) + GST_CAT_DEBUG (GST_CAT_CLOCK, + " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, newx[j], newy[j]); +#endif + + /* have to do this precisely otherwise the results are pretty much useless. + * should guarantee that none of these accumulators can overflow */ + + /* quantities on the order of 1e10 to 1e13 -> 30-35 bits; + * window size a max of 2^10, so + this addition could end up around 2^45 or so -- ample headroom */ + for (i = j = 0; i < n; i++, j += 2) { + /* Just in case assumptions about headroom prove false, let's check */ + if ((newx[j] > 0 && G_MAXUINT64 - xbar <= newx[j]) || + (newy[j] > 0 && G_MAXUINT64 - ybar <= newy[j])) { + GST_CAT_WARNING (GST_CAT_CLOCK, + "Regression overflowed in clock slaving! xbar %" + G_GUINT64_FORMAT " newx[j] %" G_GUINT64_FORMAT " ybar %" + G_GUINT64_FORMAT " newy[j] %" G_GUINT64_FORMAT, xbar, newx[j], ybar, + newy[j]); + if (temp == NULL && n > 64) + g_free (newx); + return FALSE; + } + + xbar += newx[j]; + ybar += newy[j]; + } + xbar /= n; + ybar /= n; + + /* multiplying directly would give quantities on the order of 1e20-1e26 -> + * 60 bits to 70 bits times the window size that's 80 which is too much. + * Instead we (1) subtract off the xbar*ybar in the loop instead of after, + * to avoid accumulation; (2) shift off some estimated number of bits from + * each multiplicand to limit the expected ceiling. For strange + * distributions of input values, things can still overflow, in which + * case we drop precision and retry - at most a few times, in practice rarely + */ + + /* Guess how many bits we might need for the usual distribution of input, + * with a fallback loop that drops precision if things go pear-shaped */ + max_bits = gst_log2 (MAX (xmax - xmin, ymax - ymin)) * 7 / 8 + gst_log2 (n); + if (max_bits > 64) + pshift = max_bits - 64; + + i = 0; + do { +#ifdef DEBUGGING_ENABLED + GST_CAT_DEBUG (GST_CAT_CLOCK, + "Restarting regression with precision shift %u", pshift); +#endif + + xbar4 = xbar >> pshift; + ybar4 = ybar >> pshift; + sxx = syy = sxy = 0; + for (i = j = 0; i < n; i++, j += 2) { + GstClockTime newx4, newy4; + GstClockTimeDiff tmp; + + newx4 = newx[j] >> pshift; + newy4 = newy[j] >> pshift; + + tmp = (newx4 + xbar4) * (newx4 - xbar4); + if (G_UNLIKELY (tmp > 0 && sxx > 0 && (G_MAXINT64 - sxx <= tmp))) { + do { + /* Drop some precision and restart */ + pshift++; + sxx /= 4; + tmp /= 4; + } while (G_MAXINT64 - sxx <= tmp); + break; + } else if (G_UNLIKELY (tmp < 0 && sxx < 0 && (G_MININT64 - sxx >= tmp))) { + do { + /* Drop some precision and restart */ + pshift++; + sxx /= 4; + tmp /= 4; + } while (G_MININT64 - sxx >= tmp); + break; + } + sxx += tmp; + + tmp = newy4 * newy4 - ybar4 * ybar4; + if (G_UNLIKELY (tmp > 0 && syy > 0 && (G_MAXINT64 - syy <= tmp))) { + do { + pshift++; + syy /= 4; + tmp /= 4; + } while (G_MAXINT64 - syy <= tmp); + break; + } else if (G_UNLIKELY (tmp < 0 && syy < 0 && (G_MININT64 - syy >= tmp))) { + do { + pshift++; + syy /= 4; + tmp /= 4; + } while (G_MININT64 - syy >= tmp); + break; + } + syy += tmp; + + tmp = newx4 * newy4 - xbar4 * ybar4; + if (G_UNLIKELY (tmp > 0 && sxy > 0 && (G_MAXINT64 - sxy <= tmp))) { + do { + pshift++; + sxy /= 4; + tmp /= 4; + } while (G_MAXINT64 - sxy <= tmp); + break; + } else if (G_UNLIKELY (tmp < 0 && sxy < 0 && (G_MININT64 - sxy >= tmp))) { + do { + pshift++; + sxy /= 4; + tmp /= 4; + } while (G_MININT64 - sxy >= tmp); + break; + } + sxy += tmp; + } + } while (i < n); + + if (G_UNLIKELY (sxx == 0)) + goto invalid; + + *m_num = sxy; + *m_denom = sxx; + *b = (ymin + ybar) - gst_util_uint64_scale_round (xbar, *m_num, *m_denom); + /* Report base starting from the most recent observation */ + *xbase = xmax; + *b += gst_util_uint64_scale_round (xmax - xmin, *m_num, *m_denom); + + *r_squared = ((double) sxy * (double) sxy) / ((double) sxx * (double) syy); + +#ifdef DEBUGGING_ENABLED + GST_CAT_DEBUG (GST_CAT_CLOCK, " m = %g", ((double) *m_num) / *m_denom); + GST_CAT_DEBUG (GST_CAT_CLOCK, " b = %" G_GUINT64_FORMAT, *b); + GST_CAT_DEBUG (GST_CAT_CLOCK, " xbase = %" G_GUINT64_FORMAT, *xbase); + GST_CAT_DEBUG (GST_CAT_CLOCK, " r2 = %g", *r_squared); +#endif + + if (temp == NULL && n > 64) + g_free (newx); + + return TRUE; + +invalid: + { + GST_CAT_DEBUG (GST_CAT_CLOCK, "sxx == 0, regression failed"); + if (temp == NULL && n > 64) + g_free (newx); + return FALSE; + } +} diff --git a/gst/gstutils.h b/gst/gstutils.h new file mode 100644 index 0000000..2c89c28 --- /dev/null +++ b/gst/gstutils.h @@ -0,0 +1,1210 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2002 Thomas Vander Stichele + * + * gstutils.h: Header for various utility functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_UTILS_H__ +#define __GST_UTILS_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +GST_API +void gst_util_set_value_from_string (GValue *value, const gchar *value_str); + +GST_API +void gst_util_set_object_arg (GObject *object, const gchar *name, const gchar *value); + +GST_API +gboolean gst_util_set_object_array (GObject * object, const gchar * name, + const GValueArray * array); +GST_API +gboolean gst_util_get_object_array (GObject * object, const gchar * name, + GValueArray ** array); +GST_API +void gst_util_dump_mem (const guchar *mem, guint size); + +GST_API +void gst_util_dump_buffer (GstBuffer * buf); + +GST_API +guint64 gst_util_gdouble_to_guint64 (gdouble value) G_GNUC_CONST; + +GST_API +gdouble gst_util_guint64_to_gdouble (guint64 value) G_GNUC_CONST; + +/** + * gst_guint64_to_gdouble: + * @value: the #guint64 value to convert + * + * Convert @value to a gdouble. + * + * Returns: @value converted to a #gdouble. + */ + +/** + * gst_gdouble_to_guint64: + * @value: the #gdouble value to convert + * + * Convert @value to a guint64. + * + * Returns: @value converted to a #guint64. + */ +#ifdef WIN32 +#define gst_gdouble_to_guint64(value) gst_util_gdouble_to_guint64(value) +#define gst_guint64_to_gdouble(value) gst_util_guint64_to_gdouble(value) +#else +#define gst_gdouble_to_guint64(value) ((guint64) (value)) +#define gst_guint64_to_gdouble(value) ((gdouble) (value)) +#endif + +GST_API +guint64 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom); + +GST_API +guint64 gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom); + +GST_API +guint64 gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom); + +GST_API +guint64 gst_util_uint64_scale_int (guint64 val, gint num, gint denom); + +GST_API +guint64 gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom); + +GST_API +guint64 gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom); + +/** + * GST_SEQNUM_INVALID: + * + * A value which is guaranteed to never be returned by + * gst_util_seqnum_next(). + * + * Can be used as a default value in variables used to store seqnum. + * + * Since: 1.14 + */ +#define GST_SEQNUM_INVALID (0) + +GST_API +guint32 gst_util_seqnum_next (void); + +GST_API +gint32 gst_util_seqnum_compare (guint32 s1, guint32 s2); + +/** + * GST_GROUP_ID_INVALID: + * + * A value which is guaranteed to never be returned by + * gst_util_group_id_next(). + * + * Can be used as a default value in variables used to store group_id. + * + * Since: 1.14 + */ +#define GST_GROUP_ID_INVALID (0) + +GST_API +guint gst_util_group_id_next (void); + +/** + * GST_CALL_PARENT: + * @parent_class_cast: the name of the class cast macro for the parent type + * @name: name of the function to call + * @args: arguments enclosed in '( )' + * + * Just call the parent handler. This assumes that there is a variable + * named parent_class that points to the (duh!) parent class. Note that + * this macro is not to be used with things that return something, use + * the _WITH_DEFAULT version for that + */ +#define GST_CALL_PARENT(parent_class_cast, name, args) \ + ((parent_class_cast(parent_class)->name != NULL) ? \ + parent_class_cast(parent_class)->name args : (void) 0) + +/** + * GST_CALL_PARENT_WITH_DEFAULT: + * @parent_class_cast: the name of the class cast macro for the parent type + * @name: name of the function to call + * @args: arguments enclosed in '( )' + * @def_return: default result + * + * Same as GST_CALL_PARENT(), but in case there is no implementation, it + * evaluates to @def_return. + */ +#define GST_CALL_PARENT_WITH_DEFAULT(parent_class_cast, name, args, def_return)\ + ((parent_class_cast(parent_class)->name != NULL) ? \ + parent_class_cast(parent_class)->name args : def_return) + +/* Define PUT and GET functions for unaligned memory */ +#define _GST_GET(__data, __idx, __size, __shift) \ + (((guint##__size) (((const guint8 *) (__data))[__idx])) << (__shift)) + +#define _GST_PUT(__data, __idx, __size, __shift, __num) \ + (((guint8 *) (__data))[__idx] = (((guint##__size) (__num)) >> (__shift)) & 0xff) + +#ifndef __GTK_DOC_IGNORE__ +#if GST_HAVE_UNALIGNED_ACCESS +static inline guint16 __gst_fast_read16(const guint8 *v) { + return *(const guint16*)(const void*)(v); +} +static inline guint32 __gst_fast_read32(const guint8 *v) { + return *(const guint32*)(const void*)(v); +} +static inline guint64 __gst_fast_read64(const guint8 *v) { + return *(const guint64*)(const void*)(v); +} +static inline guint16 __gst_fast_read_swap16(const guint8 *v) { + return GUINT16_SWAP_LE_BE(*(const guint16*)(const void*)(v)); +} +static inline guint32 __gst_fast_read_swap32(const guint8 *v) { + return GUINT32_SWAP_LE_BE(*(const guint32*)(const void*)(v)); +} +static inline guint64 __gst_fast_read_swap64(const guint8 *v) { + return GUINT64_SWAP_LE_BE(*(const guint64*)(const void*)(v)); +} +# define _GST_FAST_READ(s, d) __gst_fast_read##s((const guint8 *)(d)) +# define _GST_FAST_READ_SWAP(s, d) __gst_fast_read_swap##s((const guint8 *)(d)) + +static inline void __gst_fast_write16 (guint8 *p, guint16 v) { + *(guint16*)(void*)(p) = v; +} +static inline void __gst_fast_write32 (guint8 *p, guint32 v) { + *(guint32*)(void*)(p) = v; +} +static inline void __gst_fast_write64 (guint8 *p, guint64 v) { + *(guint64*)(void*)(p) = v; +} +static inline void __gst_fast_write_swap16 (guint8 *p, guint16 v) { + *(guint16*)(void*)(p) = GUINT16_SWAP_LE_BE (v); +} +static inline void __gst_fast_write_swap32 (guint8 *p, guint32 v) { + *(guint32*)(void*)(p) = GUINT32_SWAP_LE_BE (v); +} +static inline void __gst_fast_write_swap64 (guint8 *p, guint64 v) { + *(guint64*)(void*)(p) = GUINT64_SWAP_LE_BE (v); +} +# define _GST_FAST_WRITE(s, d, v) __gst_fast_write##s((guint8 *)(d), (v)) +# define _GST_FAST_WRITE_SWAP(s, d, v) __gst_fast_write_swap##s((guint8 *)(d), (v)) +#endif +#endif + + +/** + * GST_READ_UINT64_BE: + * @data: memory location + * + * Read a 64 bit unsigned integer value in big endian format from the memory buffer. + */ + +/** + * GST_READ_UINT64_LE: + * @data: memory location + * + * Read a 64 bit unsigned integer value in little endian format from the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_READ_UINT64_BE(data) _GST_FAST_READ (64, data) +# define GST_READ_UINT64_LE(data) _GST_FAST_READ_SWAP (64, data) +# else +# define GST_READ_UINT64_BE(data) _GST_FAST_READ_SWAP (64, data) +# define GST_READ_UINT64_LE(data) _GST_FAST_READ (64, data) +# endif +#else +#define _GST_READ_UINT64_BE(data) (_GST_GET (data, 0, 64, 56) | \ + _GST_GET (data, 1, 64, 48) | \ + _GST_GET (data, 2, 64, 40) | \ + _GST_GET (data, 3, 64, 32) | \ + _GST_GET (data, 4, 64, 24) | \ + _GST_GET (data, 5, 64, 16) | \ + _GST_GET (data, 6, 64, 8) | \ + _GST_GET (data, 7, 64, 0)) + +#define _GST_READ_UINT64_LE(data) (_GST_GET (data, 7, 64, 56) | \ + _GST_GET (data, 6, 64, 48) | \ + _GST_GET (data, 5, 64, 40) | \ + _GST_GET (data, 4, 64, 32) | \ + _GST_GET (data, 3, 64, 24) | \ + _GST_GET (data, 2, 64, 16) | \ + _GST_GET (data, 1, 64, 8) | \ + _GST_GET (data, 0, 64, 0)) + +#define GST_READ_UINT64_BE(data) __gst_slow_read64_be((const guint8 *)(data)) +static inline guint64 __gst_slow_read64_be (const guint8 * data) { + return _GST_READ_UINT64_BE (data); +} +#define GST_READ_UINT64_LE(data) __gst_slow_read64_le((const guint8 *)(data)) +static inline guint64 __gst_slow_read64_le (const guint8 * data) { + return _GST_READ_UINT64_LE (data); +} +#endif + +/** + * GST_READ_UINT32_BE: + * @data: memory location + * + * Read a 32 bit unsigned integer value in big endian format from the memory buffer. + */ + +/** + * GST_READ_UINT32_LE: + * @data: memory location + * + * Read a 32 bit unsigned integer value in little endian format from the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_READ_UINT32_BE(data) _GST_FAST_READ (32, data) +# define GST_READ_UINT32_LE(data) _GST_FAST_READ_SWAP (32, data) +# else +# define GST_READ_UINT32_BE(data) _GST_FAST_READ_SWAP (32, data) +# define GST_READ_UINT32_LE(data) _GST_FAST_READ (32, data) +# endif +#else +#define _GST_READ_UINT32_BE(data) (_GST_GET (data, 0, 32, 24) | \ + _GST_GET (data, 1, 32, 16) | \ + _GST_GET (data, 2, 32, 8) | \ + _GST_GET (data, 3, 32, 0)) + +#define _GST_READ_UINT32_LE(data) (_GST_GET (data, 3, 32, 24) | \ + _GST_GET (data, 2, 32, 16) | \ + _GST_GET (data, 1, 32, 8) | \ + _GST_GET (data, 0, 32, 0)) + +#define GST_READ_UINT32_BE(data) __gst_slow_read32_be((const guint8 *)(data)) +static inline guint32 __gst_slow_read32_be (const guint8 * data) { + return _GST_READ_UINT32_BE (data); +} +#define GST_READ_UINT32_LE(data) __gst_slow_read32_le((const guint8 *)(data)) +static inline guint32 __gst_slow_read32_le (const guint8 * data) { + return _GST_READ_UINT32_LE (data); +} +#endif + +/** + * GST_READ_UINT24_BE: + * @data: memory location + * + * Read a 24 bit unsigned integer value in big endian format from the memory buffer. + */ +#define _GST_READ_UINT24_BE(data) (_GST_GET (data, 0, 32, 16) | \ + _GST_GET (data, 1, 32, 8) | \ + _GST_GET (data, 2, 32, 0)) + +#define GST_READ_UINT24_BE(data) __gst_slow_read24_be((const guint8 *)(data)) +static inline guint32 __gst_slow_read24_be (const guint8 * data) { + return _GST_READ_UINT24_BE (data); +} + +/** + * GST_READ_UINT24_LE: + * @data: memory location + * + * Read a 24 bit unsigned integer value in little endian format from the memory buffer. + */ +#define _GST_READ_UINT24_LE(data) (_GST_GET (data, 2, 32, 16) | \ + _GST_GET (data, 1, 32, 8) | \ + _GST_GET (data, 0, 32, 0)) + +#define GST_READ_UINT24_LE(data) __gst_slow_read24_le((const guint8 *)(data)) +static inline guint32 __gst_slow_read24_le (const guint8 * data) { + return _GST_READ_UINT24_LE (data); +} + +/** + * GST_READ_UINT16_BE: + * @data: memory location + * + * Read a 16 bit unsigned integer value in big endian format from the memory buffer. + */ +/** + * GST_READ_UINT16_LE: + * @data: memory location + * + * Read a 16 bit unsigned integer value in little endian format from the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_READ_UINT16_BE(data) _GST_FAST_READ (16, data) +# define GST_READ_UINT16_LE(data) _GST_FAST_READ_SWAP (16, data) +# else +# define GST_READ_UINT16_BE(data) _GST_FAST_READ_SWAP (16, data) +# define GST_READ_UINT16_LE(data) _GST_FAST_READ (16, data) +# endif +#else +#define _GST_READ_UINT16_BE(data) (_GST_GET (data, 0, 16, 8) | \ + _GST_GET (data, 1, 16, 0)) + +#define _GST_READ_UINT16_LE(data) (_GST_GET (data, 1, 16, 8) | \ + _GST_GET (data, 0, 16, 0)) + +#define GST_READ_UINT16_BE(data) __gst_slow_read16_be((const guint8 *)(data)) +static inline guint16 __gst_slow_read16_be (const guint8 * data) { + return _GST_READ_UINT16_BE (data); +} +#define GST_READ_UINT16_LE(data) __gst_slow_read16_le((const guint8 *)(data)) +static inline guint16 __gst_slow_read16_le (const guint8 * data) { + return _GST_READ_UINT16_LE (data); +} +#endif + +/** + * GST_READ_UINT8: + * @data: memory location + * + * Read an 8 bit unsigned integer value from the memory buffer. + */ +#define GST_READ_UINT8(data) (_GST_GET (data, 0, 8, 0)) + +/** + * GST_WRITE_UINT64_BE: + * @data: memory location + * @val: value to store + * + * Store a 64 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * GST_WRITE_UINT64_LE: + * @data: memory location + * @val: value to store + * + * Store a 64 bit unsigned integer value in little endian format into the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_WRITE_UINT64_BE(data,val) _GST_FAST_WRITE(64,data,val) +# define GST_WRITE_UINT64_LE(data,val) _GST_FAST_WRITE_SWAP(64,data,val) +# else +# define GST_WRITE_UINT64_BE(data,val) _GST_FAST_WRITE_SWAP(64,data,val) +# define GST_WRITE_UINT64_LE(data,val) _GST_FAST_WRITE(64,data,val) +# endif +#else +#define GST_WRITE_UINT64_BE(data,val) do { \ + gpointer __put_data = data; \ + guint64 __put_val = val; \ + _GST_PUT (__put_data, 0, 64, 56, __put_val); \ + _GST_PUT (__put_data, 1, 64, 48, __put_val); \ + _GST_PUT (__put_data, 2, 64, 40, __put_val); \ + _GST_PUT (__put_data, 3, 64, 32, __put_val); \ + _GST_PUT (__put_data, 4, 64, 24, __put_val); \ + _GST_PUT (__put_data, 5, 64, 16, __put_val); \ + _GST_PUT (__put_data, 6, 64, 8, __put_val); \ + _GST_PUT (__put_data, 7, 64, 0, __put_val); \ + } while (0) + +#define GST_WRITE_UINT64_LE(data,val) do { \ + gpointer __put_data = data; \ + guint64 __put_val = val; \ + _GST_PUT (__put_data, 0, 64, 0, __put_val); \ + _GST_PUT (__put_data, 1, 64, 8, __put_val); \ + _GST_PUT (__put_data, 2, 64, 16, __put_val); \ + _GST_PUT (__put_data, 3, 64, 24, __put_val); \ + _GST_PUT (__put_data, 4, 64, 32, __put_val); \ + _GST_PUT (__put_data, 5, 64, 40, __put_val); \ + _GST_PUT (__put_data, 6, 64, 48, __put_val); \ + _GST_PUT (__put_data, 7, 64, 56, __put_val); \ + } while (0) +#endif /* !GST_HAVE_UNALIGNED_ACCESS */ + +/** + * GST_WRITE_UINT32_BE: + * @data: memory location + * @val: value to store + * + * Store a 32 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * GST_WRITE_UINT32_LE: + * @data: memory location + * @val: value to store + * + * Store a 32 bit unsigned integer value in little endian format into the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_WRITE_UINT32_BE(data,val) _GST_FAST_WRITE(32,data,val) +# define GST_WRITE_UINT32_LE(data,val) _GST_FAST_WRITE_SWAP(32,data,val) +# else +# define GST_WRITE_UINT32_BE(data,val) _GST_FAST_WRITE_SWAP(32,data,val) +# define GST_WRITE_UINT32_LE(data,val) _GST_FAST_WRITE(32,data,val) +# endif +#else +#define GST_WRITE_UINT32_BE(data,val) do { \ + gpointer __put_data = data; \ + guint32 __put_val = val; \ + _GST_PUT (__put_data, 0, 32, 24, __put_val); \ + _GST_PUT (__put_data, 1, 32, 16, __put_val); \ + _GST_PUT (__put_data, 2, 32, 8, __put_val); \ + _GST_PUT (__put_data, 3, 32, 0, __put_val); \ + } while (0) + +#define GST_WRITE_UINT32_LE(data,val) do { \ + gpointer __put_data = data; \ + guint32 __put_val = val; \ + _GST_PUT (__put_data, 0, 32, 0, __put_val); \ + _GST_PUT (__put_data, 1, 32, 8, __put_val); \ + _GST_PUT (__put_data, 2, 32, 16, __put_val); \ + _GST_PUT (__put_data, 3, 32, 24, __put_val); \ + } while (0) +#endif /* !GST_HAVE_UNALIGNED_ACCESS */ + +/** + * GST_WRITE_UINT24_BE: + * @data: memory location + * @num: value to store + * + * Store a 24 bit unsigned integer value in big endian format into the memory buffer. + */ +#define GST_WRITE_UINT24_BE(data, num) do { \ + gpointer __put_data = data; \ + guint32 __put_val = num; \ + _GST_PUT (__put_data, 0, 32, 16, __put_val); \ + _GST_PUT (__put_data, 1, 32, 8, __put_val); \ + _GST_PUT (__put_data, 2, 32, 0, __put_val); \ + } while (0) + +/** + * GST_WRITE_UINT24_LE: + * @data: memory location + * @num: value to store + * + * Store a 24 bit unsigned integer value in little endian format into the memory buffer. + */ +#define GST_WRITE_UINT24_LE(data, num) do { \ + gpointer __put_data = data; \ + guint32 __put_val = num; \ + _GST_PUT (__put_data, 0, 32, 0, __put_val); \ + _GST_PUT (__put_data, 1, 32, 8, __put_val); \ + _GST_PUT (__put_data, 2, 32, 16, __put_val); \ + } while (0) + +/** + * GST_WRITE_UINT16_BE: + * @data: memory location + * @val: value to store + * + * Store a 16 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * GST_WRITE_UINT16_LE: + * @data: memory location + * @val: value to store + * + * Store a 16 bit unsigned integer value in little endian format into the memory buffer. + */ +#if GST_HAVE_UNALIGNED_ACCESS +# if (G_BYTE_ORDER == G_BIG_ENDIAN) +# define GST_WRITE_UINT16_BE(data,val) _GST_FAST_WRITE(16,data,val) +# define GST_WRITE_UINT16_LE(data,val) _GST_FAST_WRITE_SWAP(16,data,val) +# else +# define GST_WRITE_UINT16_BE(data,val) _GST_FAST_WRITE_SWAP(16,data,val) +# define GST_WRITE_UINT16_LE(data,val) _GST_FAST_WRITE(16,data,val) +# endif +#else +#define GST_WRITE_UINT16_BE(data,val) do { \ + gpointer __put_data = data; \ + guint16 __put_val = val; \ + _GST_PUT (__put_data, 0, 16, 8, __put_val); \ + _GST_PUT (__put_data, 1, 16, 0, __put_val); \ + } while (0) + +#define GST_WRITE_UINT16_LE(data,val) do { \ + gpointer __put_data = data; \ + guint16 __put_val = val; \ + _GST_PUT (__put_data, 0, 16, 0, __put_val); \ + _GST_PUT (__put_data, 1, 16, 8, __put_val); \ + } while (0) +#endif /* !GST_HAVE_UNALIGNED_ACCESS */ + +/** + * GST_WRITE_UINT8: + * @data: memory location + * @num: value to store + * + * Store an 8 bit unsigned integer value into the memory buffer. + */ +#define GST_WRITE_UINT8(data, num) do { \ + _GST_PUT (data, 0, 8, 0, num); \ + } while (0) + +/* Float endianness conversion macros */ + +/* FIXME: Remove this once we depend on a GLib version with this */ +#ifndef GFLOAT_FROM_LE +/** + * GFLOAT_SWAP_LE_BE: + * @in: input value + * + * Swap byte order of a 32-bit floating point value (float). + * + * Returns: @in byte-swapped. + */ +static inline gfloat +GFLOAT_SWAP_LE_BE(gfloat in) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = in; + u.i = GUINT32_SWAP_LE_BE (u.i); + return u.f; +} + +/** + * GDOUBLE_SWAP_LE_BE: + * @in: input value + * + * Swap byte order of a 64-bit floating point value (double). + * + * Returns: @in byte-swapped. + */ +static inline gdouble +GDOUBLE_SWAP_LE_BE(gdouble in) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = in; + u.i = GUINT64_SWAP_LE_BE (u.i); + return u.d; +} + +/** + * GDOUBLE_TO_LE: + * @val: value + * + * Convert 64-bit floating point value (double) from native byte order into + * little endian byte order. + */ +/** + * GDOUBLE_TO_BE: + * @val: value + * + * Convert 64-bit floating point value (double) from native byte order into + * big endian byte order. + */ +/** + * GDOUBLE_FROM_LE: + * @val: value + * + * Convert 64-bit floating point value (double) from little endian byte order + * into native byte order. + */ +/** + * GDOUBLE_FROM_BE: + * @val: value + * + * Convert 64-bit floating point value (double) from big endian byte order + * into native byte order. + */ + +/** + * GFLOAT_TO_LE: + * @val: value + * + * Convert 32-bit floating point value (float) from native byte order into + * little endian byte order. + */ +/** + * GFLOAT_TO_BE: + * @val: value + * + * Convert 32-bit floating point value (float) from native byte order into + * big endian byte order. + */ +/** + * GFLOAT_FROM_LE: + * @val: value + * + * Convert 32-bit floating point value (float) from little endian byte order + * into native byte order. + */ +/** + * GFLOAT_FROM_BE: + * @val: value + * + * Convert 32-bit floating point value (float) from big endian byte order + * into native byte order. + */ + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define GFLOAT_TO_LE(val) ((gfloat) (val)) +#define GFLOAT_TO_BE(val) (GFLOAT_SWAP_LE_BE (val)) +#define GDOUBLE_TO_LE(val) ((gdouble) (val)) +#define GDOUBLE_TO_BE(val) (GDOUBLE_SWAP_LE_BE (val)) + +#elif G_BYTE_ORDER == G_BIG_ENDIAN +#define GFLOAT_TO_LE(val) (GFLOAT_SWAP_LE_BE (val)) +#define GFLOAT_TO_BE(val) ((gfloat) (val)) +#define GDOUBLE_TO_LE(val) (GDOUBLE_SWAP_LE_BE (val)) +#define GDOUBLE_TO_BE(val) ((gdouble) (val)) + +#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ +#error unknown ENDIAN type +#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ + +#define GFLOAT_FROM_LE(val) (GFLOAT_TO_LE (val)) +#define GFLOAT_FROM_BE(val) (GFLOAT_TO_BE (val)) +#define GDOUBLE_FROM_LE(val) (GDOUBLE_TO_LE (val)) +#define GDOUBLE_FROM_BE(val) (GDOUBLE_TO_BE (val)) + +#endif /* !defined(GFLOAT_FROM_LE) */ + +/** + * GST_READ_FLOAT_LE: + * @data: memory location + * + * Read a 32 bit float value in little endian format from the memory buffer. + * + * Returns: The floating point value read from @data + */ +static inline gfloat +GST_READ_FLOAT_LE(const guint8 *data) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.i = GST_READ_UINT32_LE (data); + return u.f; +} + +/** + * GST_READ_FLOAT_BE: + * @data: memory location + * + * Read a 32 bit float value in big endian format from the memory buffer. + * + * Returns: The floating point value read from @data + */ +static inline gfloat +GST_READ_FLOAT_BE(const guint8 *data) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.i = GST_READ_UINT32_BE (data); + return u.f; +} + +/** + * GST_READ_DOUBLE_LE: + * @data: memory location + * + * Read a 64 bit double value in little endian format from the memory buffer. + * + * Returns: The double-precision floating point value read from @data + */ +static inline gdouble +GST_READ_DOUBLE_LE(const guint8 *data) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.i = GST_READ_UINT64_LE (data); + return u.d; +} + +/** + * GST_READ_DOUBLE_BE: + * @data: memory location + * + * Read a 64 bit double value in big endian format from the memory buffer. + * + * Returns: The double-precision floating point value read from @data + */ +static inline gdouble +GST_READ_DOUBLE_BE(const guint8 *data) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.i = GST_READ_UINT64_BE (data); + return u.d; +} + +/** + * GST_WRITE_FLOAT_LE: + * @data: memory location + * @num: value to store + * + * Store a 32 bit float value in little endian format into the memory buffer. + */ +static inline void +GST_WRITE_FLOAT_LE(guint8 *data, gfloat num) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = num; + GST_WRITE_UINT32_LE (data, u.i); +} + +/** + * GST_WRITE_FLOAT_BE: + * @data: memory location + * @num: value to store + * + * Store a 32 bit float value in big endian format into the memory buffer. + */ +static inline void +GST_WRITE_FLOAT_BE(guint8 *data, gfloat num) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = num; + GST_WRITE_UINT32_BE (data, u.i); +} + +/** + * GST_WRITE_DOUBLE_LE: + * @data: memory location + * @num: value to store + * + * Store a 64 bit double value in little endian format into the memory buffer. + */ +static inline void +GST_WRITE_DOUBLE_LE(guint8 *data, gdouble num) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = num; + GST_WRITE_UINT64_LE (data, u.i); +} + +/** + * GST_WRITE_DOUBLE_BE: + * @data: memory location + * @num: value to store + * + * Store a 64 bit double value in big endian format into the memory buffer. + */ +static inline void +GST_WRITE_DOUBLE_BE(guint8 *data, gdouble num) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = num; + GST_WRITE_UINT64_BE (data, u.i); +} + +/* Miscellaneous utility macros */ + +/** + * GST_ROUND_UP_2: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 2. + */ +#define GST_ROUND_UP_2(num) (((num)+1)&~1) +/** + * GST_ROUND_UP_4: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 4. + */ +#define GST_ROUND_UP_4(num) (((num)+3)&~3) +/** + * GST_ROUND_UP_8: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 8. + */ +#define GST_ROUND_UP_8(num) (((num)+7)&~7) +/** + * GST_ROUND_UP_16: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 16. + */ +#define GST_ROUND_UP_16(num) (((num)+15)&~15) +/** + * GST_ROUND_UP_32: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 32. + */ +#define GST_ROUND_UP_32(num) (((num)+31)&~31) +/** + * GST_ROUND_UP_64: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 64. + */ +#define GST_ROUND_UP_64(num) (((num)+63)&~63) +/** + * GST_ROUND_UP_128: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 128. + * Since: 1.4 + */ +#define GST_ROUND_UP_128(num) (((num)+127)&~127) +/** + * GST_ROUND_UP_N: + * @num: integrer value to round up + * @align: a power of two to round up to + * + * Rounds an integer value up to the next multiple of @align. @align MUST be a + * power of two. + */ +#define GST_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1))) + + +/** + * GST_ROUND_DOWN_2: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 2. + */ +#define GST_ROUND_DOWN_2(num) ((num)&(~1)) +/** + * GST_ROUND_DOWN_4: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 4. + */ +#define GST_ROUND_DOWN_4(num) ((num)&(~3)) +/** + * GST_ROUND_DOWN_8: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 8. + */ +#define GST_ROUND_DOWN_8(num) ((num)&(~7)) +/** + * GST_ROUND_DOWN_16: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 16. + */ +#define GST_ROUND_DOWN_16(num) ((num)&(~15)) +/** + * GST_ROUND_DOWN_32: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 32. + */ +#define GST_ROUND_DOWN_32(num) ((num)&(~31)) +/** + * GST_ROUND_DOWN_64: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 64. + */ +#define GST_ROUND_DOWN_64(num) ((num)&(~63)) +/** + * GST_ROUND_DOWN_128: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 128. + * Since: 1.4 + */ +#define GST_ROUND_DOWN_128(num) ((num)&(~127)) +/** + * GST_ROUND_DOWN_N: + * @num: integrer value to round down + * @align: a power of two to round down to + * + * Rounds an integer value down to the next multiple of @align. @align MUST be a + * power of two. + */ +#define GST_ROUND_DOWN_N(num,align) (((num) & ~((align) - 1))) + + +GST_API +void gst_object_default_error (GstObject * source, + const GError * error, + const gchar * debug); + +/* element functions */ + +GST_API +void gst_element_create_all_pads (GstElement *element); + +GST_API +GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad, + GstCaps *caps); +GST_API +GstPadTemplate* gst_element_get_compatible_pad_template (GstElement *element, GstPadTemplate *compattempl); + +GST_API +const gchar* gst_element_state_get_name (GstState state); + +GST_API +const gchar * gst_element_state_change_return_get_name (GstStateChangeReturn state_ret); + +GST_API +const gchar * gst_state_change_get_name (GstStateChange transition); + +GST_API +gboolean gst_element_link (GstElement *src, GstElement *dest); + +GST_API +gboolean gst_element_link_many (GstElement *element_1, + GstElement *element_2, ...) G_GNUC_NULL_TERMINATED; +GST_API +gboolean gst_element_link_filtered (GstElement * src, + GstElement * dest, + GstCaps *filter); +GST_API +void gst_element_unlink (GstElement *src, GstElement *dest); + +GST_API +void gst_element_unlink_many (GstElement *element_1, + GstElement *element_2, ...) G_GNUC_NULL_TERMINATED; +GST_API +gboolean gst_element_link_pads (GstElement *src, const gchar *srcpadname, + GstElement *dest, const gchar *destpadname); +GST_API +gboolean gst_element_link_pads_full (GstElement *src, const gchar *srcpadname, + GstElement *dest, const gchar *destpadname, + GstPadLinkCheck flags); +GST_API +void gst_element_unlink_pads (GstElement *src, const gchar *srcpadname, + GstElement *dest, const gchar *destpadname); +GST_API +gboolean gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname, + GstElement * dest, const gchar * destpadname, + GstCaps *filter); +GST_API +gboolean gst_element_seek_simple (GstElement *element, + GstFormat format, + GstSeekFlags seek_flags, + gint64 seek_pos); + +/* util elementfactory functions */ + +GST_API +gboolean gst_element_factory_can_sink_all_caps (GstElementFactory *factory, const GstCaps *caps); + +GST_API +gboolean gst_element_factory_can_src_all_caps (GstElementFactory *factory, const GstCaps *caps); + +GST_API +gboolean gst_element_factory_can_sink_any_caps (GstElementFactory *factory, const GstCaps *caps); + +GST_API +gboolean gst_element_factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps); + +/* util query functions */ + +GST_API +gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur); + +GST_API +gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration); + +GST_API +gboolean gst_element_query_convert (GstElement *element, GstFormat src_format, gint64 src_val, + GstFormat dest_format, gint64 *dest_val); + +/* pad functions */ + +GST_API +void gst_pad_use_fixed_caps (GstPad *pad); + +GST_API +GstElement* gst_pad_get_parent_element (GstPad *pad); + +/* util query functions */ + +GST_API +gboolean gst_pad_proxy_query_accept_caps (GstPad *pad, GstQuery *query); + +GST_API +gboolean gst_pad_proxy_query_caps (GstPad *pad, GstQuery *query); + +GST_API +gboolean gst_pad_query_position (GstPad *pad, GstFormat format, gint64 *cur); + +GST_API +gboolean gst_pad_query_duration (GstPad *pad, GstFormat format, gint64 *duration); + +GST_API +gboolean gst_pad_query_convert (GstPad *pad, GstFormat src_format, gint64 src_val, + GstFormat dest_format, gint64 *dest_val); +GST_API +GstCaps * gst_pad_query_caps (GstPad *pad, GstCaps *filter); + +GST_API +gboolean gst_pad_query_accept_caps (GstPad *pad, GstCaps *caps); + +GST_API +gboolean gst_pad_link_maybe_ghosting (GstPad *src, + GstPad *sink); +GST_API +gboolean gst_pad_link_maybe_ghosting_full (GstPad *src, + GstPad *sink, + GstPadLinkCheck flags); +GST_API +gboolean gst_pad_peer_query_position (GstPad *pad, GstFormat format, gint64 *cur); + +GST_API +gboolean gst_pad_peer_query_duration (GstPad *pad, GstFormat format, gint64 *duration); + +GST_API +gboolean gst_pad_peer_query_convert (GstPad *pad, GstFormat src_format, gint64 src_val, + GstFormat dest_format, gint64 *dest_val); +GST_API +GstCaps * gst_pad_peer_query_caps (GstPad * pad, GstCaps *filter); + +GST_API +gboolean gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps *caps); + +GST_API +gchar * gst_pad_create_stream_id (GstPad * pad, GstElement * parent, const gchar *stream_id) G_GNUC_MALLOC; + +GST_API +gchar * gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent, const gchar *stream_id, ...) G_GNUC_PRINTF (3, 4) G_GNUC_MALLOC; + +GST_API +gchar * gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, const gchar *stream_id, va_list var_args) G_GNUC_PRINTF (3, 0) G_GNUC_MALLOC; + +GST_API +gchar * gst_pad_get_stream_id (GstPad * pad); + +GST_API +GstStream * gst_pad_get_stream (GstPad * pad); + +/* bin functions */ + +GST_API +void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; + +GST_API +void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; + +GST_API +GstPad * gst_bin_find_unlinked_pad (GstBin *bin, GstPadDirection direction); + +GST_API +gboolean gst_bin_sync_children_states (GstBin *bin); + +/* parse utility functions */ + +GST_API +GstElement * gst_parse_bin_from_description (const gchar * bin_description, + gboolean ghost_unlinked_pads, + GError ** err); +GST_API +GstElement * gst_parse_bin_from_description_full (const gchar * bin_description, + gboolean ghost_unlinked_pads, + GstParseContext * context, + GstParseFlags flags, + GError ** err); +GST_API +GstClockTime gst_util_get_timestamp (void); + +/** + * GstSearchMode: + * @GST_SEARCH_MODE_EXACT : Only search for exact matches. + * @GST_SEARCH_MODE_BEFORE: Search for an exact match or the element just before. + * @GST_SEARCH_MODE_AFTER : Search for an exact match or the element just after. + * + * The different search modes. + */ +typedef enum { + GST_SEARCH_MODE_EXACT = 0, + GST_SEARCH_MODE_BEFORE, + GST_SEARCH_MODE_AFTER +} GstSearchMode; + +GST_API +gpointer gst_util_array_binary_search (gpointer array, guint num_elements, + gsize element_size, GCompareDataFunc search_func, + GstSearchMode mode, gconstpointer search_data, + gpointer user_data); + +/* fraction operations */ + +GST_API +gint gst_util_greatest_common_divisor (gint a, gint b); + +GST_API +gint64 gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b); + +GST_API +void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest); + +GST_API +void gst_util_double_to_fraction (gdouble src, gint *dest_n, gint *dest_d); + +GST_API +gboolean gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, + gint *res_n, gint *res_d); +GST_API +gboolean gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, + gint *res_n, gint *res_d); +GST_API +gint gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d); + +GST_API +gboolean gst_calculate_linear_regression (const GstClockTime * xy, + GstClockTime * temp, guint n, + GstClockTime * m_num, GstClockTime * m_denom, + GstClockTime * b, GstClockTime * xbase, + gdouble * r_squared); + + +G_END_DECLS + +#endif /* __GST_UTILS_H__ */ diff --git a/gst/gstvalue.c b/gst/gstvalue.c new file mode 100644 index 0000000..2f16ebc --- /dev/null +++ b/gst/gstvalue.c @@ -0,0 +1,7758 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstvalue + * @title: GstValue + * @short_description: GValue implementations specific + * to GStreamer + * + * GValue implementations specific to GStreamer. + * + * Note that operations on the same #GValue from multiple threads may lead to + * undefined behaviour. + */ + +/* Suppress warnings for GValueAraray */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include + +#include "gst_private.h" +#include "glib-compat-private.h" +#include +#include +#include "gstutils.h" + +/* GstValueUnionFunc: + * @dest: a #GValue for the result + * @value1: a #GValue operand + * @value2: a #GValue operand + * + * Used by gst_value_union() to perform unification for a specific #GValue + * type. Register a new implementation with gst_value_register_union_func(). + * + * Returns: %TRUE if a union was successful + */ +typedef gboolean (*GstValueUnionFunc) (GValue * dest, + const GValue * value1, const GValue * value2); + +/* GstValueIntersectFunc: + * @dest: (out caller-allocates): a #GValue for the result + * @value1: a #GValue operand + * @value2: a #GValue operand + * + * Used by gst_value_intersect() to perform intersection for a specific #GValue + * type. If the intersection is non-empty, the result is + * placed in @dest and %TRUE is returned. If the intersection is + * empty, @dest is unmodified and %FALSE is returned. + * Register a new implementation with gst_value_register_intersect_func(). + * + * Returns: %TRUE if the values can intersect + */ +typedef gboolean (*GstValueIntersectFunc) (GValue * dest, + const GValue * value1, const GValue * value2); + +/* GstValueSubtractFunc: + * @dest: (out caller-allocates): a #GValue for the result + * @minuend: a #GValue operand + * @subtrahend: a #GValue operand + * + * Used by gst_value_subtract() to perform subtraction for a specific #GValue + * type. Register a new implementation with gst_value_register_subtract_func(). + * + * Returns: %TRUE if the subtraction is not empty + */ +typedef gboolean (*GstValueSubtractFunc) (GValue * dest, + const GValue * minuend, const GValue * subtrahend); + +static void gst_value_register_union_func (GType type1, + GType type2, GstValueUnionFunc func); +static void gst_value_register_intersect_func (GType type1, + GType type2, GstValueIntersectFunc func); +static void gst_value_register_subtract_func (GType minuend_type, + GType subtrahend_type, GstValueSubtractFunc func); + +static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after, + GValue * value, GType type); +static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after, + GValue * value, GType type); + +typedef struct _GstValueUnionInfo GstValueUnionInfo; +struct _GstValueUnionInfo +{ + GType type1; + GType type2; + GstValueUnionFunc func; +}; + +typedef struct _GstValueIntersectInfo GstValueIntersectInfo; +struct _GstValueIntersectInfo +{ + GType type1; + GType type2; + GstValueIntersectFunc func; +}; + +typedef struct _GstValueSubtractInfo GstValueSubtractInfo; +struct _GstValueSubtractInfo +{ + GType minuend; + GType subtrahend; + GstValueSubtractFunc func; +}; + +struct _GstFlagSetClass +{ + GTypeClass parent; + GType flags_type; /* Type of the GFlags this flagset carries (can be 0) */ +}; + +typedef struct _GstFlagSetClass GstFlagSetClass; + +typedef struct _GstValueAbbreviation GstValueAbbreviation; + +struct _GstValueAbbreviation +{ + const gchar *type_name; + GType type; +}; + +#define FUNDAMENTAL_TYPE_ID_MAX \ + (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) +#define FUNDAMENTAL_TYPE_ID(type) \ + ((type) >> G_TYPE_FUNDAMENTAL_SHIFT) + +#define VALUE_LIST_ARRAY(v) ((GArray *) (v)->data[0].v_pointer) +#define VALUE_LIST_SIZE(v) (VALUE_LIST_ARRAY(v)->len) +#define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index (VALUE_LIST_ARRAY(v), GValue, (index))) + +static GArray *gst_value_table; +static GHashTable *gst_value_hash; +static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1]; +static GArray *gst_value_union_funcs; +static GArray *gst_value_intersect_funcs; +static GArray *gst_value_subtract_funcs; + +/* Forward declarations */ +static gchar *gst_value_serialize_fraction (const GValue * value); + +static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1); +static gint gst_value_compare_with_func (const GValue * value1, + const GValue * value2, GstValueCompareFunc compare); + +static gchar *gst_string_wrap (const gchar * s); +static gchar *gst_string_unwrap (const gchar * s); + +static void gst_value_move (GValue * dest, GValue * src); +static void _gst_value_list_append_and_take_value (GValue * value, + GValue * append_value); +static void _gst_value_array_append_and_take_value (GValue * value, + GValue * append_value); + +static inline GstValueTable * +gst_value_hash_lookup_type (GType type) +{ + if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type))) + return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)]; + else + return g_hash_table_lookup (gst_value_hash, (gpointer) type); +} + +static void +gst_value_hash_add_type (GType type, const GstValueTable * table) +{ + if (G_TYPE_IS_FUNDAMENTAL (type)) + gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table; + + g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table); +} + +/******** + * list * + ********/ + +/* two helper functions to serialize/stringify any type of list + * regular lists are done with { }, arrays with < > + */ +gchar * +_priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin, + const gchar * end, gboolean print_type) +{ + guint i; + GArray *array = value->data[0].v_pointer; + GString *s; + GValue *v; + gchar *s_val; + guint alen = array->len; + + /* estimate minimum string length to minimise re-allocs in GString */ + s = g_string_sized_new (2 + (6 * alen) + 2); + g_string_append (s, begin); + for (i = 0; i < alen; i++) { + v = &g_array_index (array, GValue, i); + s_val = gst_value_serialize (v); + if (s_val != NULL) { + if (print_type) { + g_string_append_c (s, '('); + g_string_append (s, _priv_gst_value_gtype_to_abbr (G_VALUE_TYPE (v))); + g_string_append_c (s, ')'); + } + g_string_append (s, s_val); + g_free (s_val); + if (i < alen - 1) { + g_string_append_len (s, ", ", 2); + } + } else { + GST_WARNING ("Could not serialize list/array value of type '%s'", + G_VALUE_TYPE_NAME (v)); + } + } + g_string_append (s, end); + return g_string_free (s, FALSE); +} + +static void +gst_value_transform_any_list_string (const GValue * src_value, + GValue * dest_value, const gchar * begin, const gchar * end) +{ + GValue *list_value; + GArray *array; + GString *s; + guint i; + gchar *list_s; + guint alen; + + array = src_value->data[0].v_pointer; + alen = array->len; + + /* estimate minimum string length to minimise re-allocs in GString */ + s = g_string_sized_new (2 + (10 * alen) + 2); + g_string_append (s, begin); + for (i = 0; i < alen; i++) { + list_value = &g_array_index (array, GValue, i); + + if (i != 0) { + g_string_append_len (s, ", ", 2); + } + list_s = g_strdup_value_contents (list_value); + g_string_append (s, list_s); + g_free (list_s); + } + g_string_append (s, end); + + dest_value->data[0].v_pointer = g_string_free (s, FALSE); +} + +static gchar * +_gst_value_serialize_g_value_array (const GValue * value, const gchar * begin, + const gchar * end) +{ + guint i; + GValueArray *array = value->data[0].v_pointer; + GString *s; + GValue *v; + gchar *s_val; + guint alen = 0; + + if (array) + alen = array->n_values; + + /* estimate minimum string length to minimise re-allocs in GString */ + s = g_string_sized_new (2 + (6 * alen) + 2); + g_string_append (s, begin); + for (i = 0; i < alen; i++) { + v = g_value_array_get_nth (array, i); + s_val = gst_value_serialize (v); + if (s_val != NULL) { + g_string_append (s, s_val); + g_free (s_val); + if (i < alen - 1) { + g_string_append_len (s, ", ", 2); + } + } else { + GST_WARNING ("Could not serialize list/array value of type '%s'", + G_VALUE_TYPE_NAME (v)); + } + } + g_string_append (s, end); + return g_string_free (s, FALSE); +} + +static void +_gst_value_transform_g_value_array_string (const GValue * src_value, + GValue * dest_value, const gchar * begin, const gchar * end) +{ + GValue *list_value; + GValueArray *array; + GString *s; + guint i; + gchar *list_s; + guint alen; + + array = src_value->data[0].v_pointer; + alen = array->n_values; + + /* estimate minimum string length to minimise re-allocs in GString */ + s = g_string_sized_new (2 + (10 * alen) + 2); + g_string_append (s, begin); + for (i = 0; i < alen; i++) { + list_value = g_value_array_get_nth (array, i); + + if (i != 0) { + g_string_append_len (s, ", ", 2); + } + list_s = g_strdup_value_contents (list_value); + g_string_append (s, list_s); + g_free (list_s); + } + g_string_append (s, end); + + dest_value->data[0].v_pointer = g_string_free (s, FALSE); +} + +/* + * helper function to see if a type is fixed. Is used internally here and + * there. Do not export, since it doesn't work for types where the content + * decides the fixedness (e.g. GST_TYPE_ARRAY). + */ +static gboolean +gst_type_is_fixed (GType type) +{ + /* the basic int, string, double types */ + if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { + return TRUE; + } + /* our fundamental types that are certainly not fixed */ + if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE || + type == GST_TYPE_INT64_RANGE || + type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE || + type == GST_TYPE_STRUCTURE) { + return FALSE; + } + /* other (boxed) types that are fixed */ + if (type == GST_TYPE_BUFFER) { + return TRUE; + } + /* heavy checks */ + if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <= + G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { + return TRUE; + } + + return FALSE; +} + +/* GValue functions usable for both regular lists and arrays */ +static void +gst_value_init_list_or_array (GValue * value) +{ + value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue)); +} + +static GArray * +copy_garray_of_gstvalue (const GArray * src) +{ + GArray *dest; + guint i, len; + + len = src->len; + dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len); + g_array_set_size (dest, len); + for (i = 0; i < len; i++) { + gst_value_init_and_copy (&g_array_index (dest, GValue, i), + &g_array_index (src, GValue, i)); + } + + return dest; +} + +static void +gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_pointer = + copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer); +} + +static void +gst_value_free_list_or_array (GValue * value) +{ + guint i, len; + GArray *src = (GArray *) value->data[0].v_pointer; + len = src->len; + + if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) { + for (i = 0; i < len; i++) { + g_value_unset (&g_array_index (src, GValue, i)); + } + g_array_free (src, TRUE); + } +} + +static gpointer +gst_value_list_or_array_peek_pointer (const GValue * value) +{ + return value->data[0].v_pointer; +} + +static gchar * +gst_value_collect_list_or_array (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + value->data[0].v_pointer = collect_values[0].v_pointer; + value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS; + } else { + value->data[0].v_pointer = + copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer); + } + return NULL; +} + +static gchar * +gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + GArray **dest = collect_values[0].v_pointer; + + if (!dest) + return g_strdup_printf ("value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!value->data[0].v_pointer) + return g_strdup_printf ("invalid value given for `%s'", + G_VALUE_TYPE_NAME (value)); + if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *dest = (GArray *) value->data[0].v_pointer; + } else { + *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer); + } + return NULL; +} + +static gboolean +gst_value_list_or_array_get_basic_type (const GValue * value, GType * type) +{ + if (G_UNLIKELY (value == NULL)) + return FALSE; + + if (GST_VALUE_HOLDS_LIST (value)) { + if (VALUE_LIST_SIZE (value) == 0) + return FALSE; + return gst_value_list_or_array_get_basic_type (VALUE_LIST_GET_VALUE (value, + 0), type); + } + if (GST_VALUE_HOLDS_ARRAY (value)) { + const GArray *array = (const GArray *) value->data[0].v_pointer; + if (array->len == 0) + return FALSE; + return gst_value_list_or_array_get_basic_type (&g_array_index (array, + GValue, 0), type); + } + + *type = G_VALUE_TYPE (value); + + return TRUE; +} + +#define IS_RANGE_COMPAT(type1,type2,t1,t2) \ + (((t1) == (type1) && (t2) == (type2)) || ((t2) == (type1) && (t1) == (type2))) + +static gboolean +gst_value_list_or_array_are_compatible (const GValue * value1, + const GValue * value2) +{ + GType basic_type1, basic_type2; + + /* empty or same type is OK */ + if (!gst_value_list_or_array_get_basic_type (value1, &basic_type1) || + !gst_value_list_or_array_get_basic_type (value2, &basic_type2) || + basic_type1 == basic_type2) + return TRUE; + + /* ranges are distinct types for each bound type... */ + if (IS_RANGE_COMPAT (G_TYPE_INT, GST_TYPE_INT_RANGE, basic_type1, + basic_type2)) + return TRUE; + if (IS_RANGE_COMPAT (G_TYPE_INT64, GST_TYPE_INT64_RANGE, basic_type1, + basic_type2)) + return TRUE; + if (IS_RANGE_COMPAT (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, basic_type1, + basic_type2)) + return TRUE; + if (IS_RANGE_COMPAT (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, basic_type1, + basic_type2)) + return TRUE; + + return FALSE; +} + +static inline void +_gst_value_list_append_and_take_value (GValue * value, GValue * append_value) +{ + g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1); + memset (append_value, 0, sizeof (GValue)); +} + +/** + * gst_value_list_append_and_take_value: + * @value: a #GValue of type #GST_TYPE_LIST + * @append_value: (transfer full): the value to append + * + * Appends @append_value to the GstValueList in @value. + * + * Since: 1.2 + */ +void +gst_value_list_append_and_take_value (GValue * value, GValue * append_value) +{ + g_return_if_fail (GST_VALUE_HOLDS_LIST (value)); + g_return_if_fail (G_IS_VALUE (append_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + append_value)); + + _gst_value_list_append_and_take_value (value, append_value); +} + +/** + * gst_value_list_append_value: + * @value: a #GValue of type #GST_TYPE_LIST + * @append_value: (transfer none): the value to append + * + * Appends @append_value to the GstValueList in @value. + */ +void +gst_value_list_append_value (GValue * value, const GValue * append_value) +{ + GValue val = { 0, }; + + g_return_if_fail (GST_VALUE_HOLDS_LIST (value)); + g_return_if_fail (G_IS_VALUE (append_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + append_value)); + + gst_value_init_and_copy (&val, append_value); + g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1); +} + +/** + * gst_value_list_prepend_value: + * @value: a #GValue of type #GST_TYPE_LIST + * @prepend_value: the value to prepend + * + * Prepends @prepend_value to the GstValueList in @value. + */ +void +gst_value_list_prepend_value (GValue * value, const GValue * prepend_value) +{ + GValue val = { 0, }; + + g_return_if_fail (GST_VALUE_HOLDS_LIST (value)); + g_return_if_fail (G_IS_VALUE (prepend_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + prepend_value)); + + gst_value_init_and_copy (&val, prepend_value); + g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1); +} + +/** + * gst_value_list_concat: + * @dest: (out caller-allocates): an uninitialized #GValue to take the result + * @value1: a #GValue + * @value2: a #GValue + * + * Concatenates copies of @value1 and @value2 into a list. Values that are not + * of type #GST_TYPE_LIST are treated as if they were lists of length 1. + * @dest will be initialized to the type #GST_TYPE_LIST. + */ +void +gst_value_list_concat (GValue * dest, const GValue * value1, + const GValue * value2) +{ + guint i, value1_length, value2_length; + GArray *array; + + g_return_if_fail (dest != NULL); + g_return_if_fail (G_VALUE_TYPE (dest) == 0); + g_return_if_fail (G_IS_VALUE (value1)); + g_return_if_fail (G_IS_VALUE (value2)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2)); + + value1_length = + (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1); + value2_length = + (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1); + g_value_init (dest, GST_TYPE_LIST); + array = (GArray *) dest->data[0].v_pointer; + g_array_set_size (array, value1_length + value2_length); + + if (GST_VALUE_HOLDS_LIST (value1)) { + for (i = 0; i < value1_length; i++) { + gst_value_init_and_copy (&g_array_index (array, GValue, i), + VALUE_LIST_GET_VALUE (value1, i)); + } + } else { + gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1); + } + + if (GST_VALUE_HOLDS_LIST (value2)) { + for (i = 0; i < value2_length; i++) { + gst_value_init_and_copy (&g_array_index (array, GValue, + i + value1_length), VALUE_LIST_GET_VALUE (value2, i)); + } + } else { + gst_value_init_and_copy (&g_array_index (array, GValue, value1_length), + value2); + } +} + +/* same as gst_value_list_concat() but takes ownership of GValues */ +static void +gst_value_list_concat_and_take_values (GValue * dest, GValue * val1, + GValue * val2) +{ + guint i, val1_length, val2_length; + gboolean val1_is_list; + gboolean val2_is_list; + GArray *array; + + g_assert (dest != NULL); + g_assert (G_VALUE_TYPE (dest) == 0); + g_assert (G_IS_VALUE (val1)); + g_assert (G_IS_VALUE (val2)); + g_assert (gst_value_list_or_array_are_compatible (val1, val2)); + + val1_is_list = GST_VALUE_HOLDS_LIST (val1); + val1_length = (val1_is_list ? VALUE_LIST_SIZE (val1) : 1); + + val2_is_list = GST_VALUE_HOLDS_LIST (val2); + val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1); + + g_value_init (dest, GST_TYPE_LIST); + array = (GArray *) dest->data[0].v_pointer; + g_array_set_size (array, val1_length + val2_length); + + if (val1_is_list) { + for (i = 0; i < val1_length; i++) { + g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i); + } + g_array_set_size (VALUE_LIST_ARRAY (val1), 0); + g_value_unset (val1); + } else { + g_array_index (array, GValue, 0) = *val1; + G_VALUE_TYPE (val1) = G_TYPE_INVALID; + } + + if (val2_is_list) { + for (i = 0; i < val2_length; i++) { + const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i); + g_array_index (array, GValue, i + val1_length) = *v2; + } + g_array_set_size (VALUE_LIST_ARRAY (val2), 0); + g_value_unset (val2); + } else { + g_array_index (array, GValue, val1_length) = *val2; + G_VALUE_TYPE (val2) = G_TYPE_INVALID; + } +} + +/** + * gst_value_list_merge: + * @dest: (out caller-allocates): an uninitialized #GValue to take the result + * @value1: a #GValue + * @value2: a #GValue + * + * Merges copies of @value1 and @value2. Values that are not + * of type #GST_TYPE_LIST are treated as if they were lists of length 1. + * + * The result will be put into @dest and will either be a list that will not + * contain any duplicates, or a non-list type (if @value1 and @value2 + * were equal). + */ +void +gst_value_list_merge (GValue * dest, const GValue * value1, + const GValue * value2) +{ + guint i, j, k, value1_length, value2_length, skipped; + const GValue *src; + gboolean skip; + GArray *array; + + g_return_if_fail (dest != NULL); + g_return_if_fail (G_VALUE_TYPE (dest) == 0); + g_return_if_fail (G_IS_VALUE (value1)); + g_return_if_fail (G_IS_VALUE (value2)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2)); + + value1_length = + (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1); + value2_length = + (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1); + g_value_init (dest, GST_TYPE_LIST); + array = (GArray *) dest->data[0].v_pointer; + g_array_set_size (array, value1_length + value2_length); + + if (GST_VALUE_HOLDS_LIST (value1)) { + for (i = 0; i < value1_length; i++) { + gst_value_init_and_copy (&g_array_index (array, GValue, i), + VALUE_LIST_GET_VALUE (value1, i)); + } + } else { + gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1); + } + + j = value1_length; + skipped = 0; + if (GST_VALUE_HOLDS_LIST (value2)) { + for (i = 0; i < value2_length; i++) { + skip = FALSE; + src = VALUE_LIST_GET_VALUE (value2, i); + for (k = 0; k < value1_length; k++) { + if (gst_value_compare (&g_array_index (array, GValue, k), + src) == GST_VALUE_EQUAL) { + skip = TRUE; + skipped++; + break; + } + } + if (!skip) { + gst_value_init_and_copy (&g_array_index (array, GValue, j), src); + j++; + } + } + } else { + skip = FALSE; + for (k = 0; k < value1_length; k++) { + if (gst_value_compare (&g_array_index (array, GValue, k), + value2) == GST_VALUE_EQUAL) { + skip = TRUE; + skipped++; + break; + } + } + if (!skip) { + gst_value_init_and_copy (&g_array_index (array, GValue, j), value2); + } + } + if (skipped) { + guint new_size = value1_length + (value2_length - skipped); + + if (new_size > 1) { + /* shrink list */ + g_array_set_size (array, new_size); + } else { + GValue single_dest; + + /* size is 1, take single value in list and make it new dest */ + single_dest = g_array_index (array, GValue, 0); + + /* clean up old value allocations: must set array size to 0, because + * allocated values are not inited meaning g_value_unset() will not + * work on them */ + g_array_set_size (array, 0); + g_value_unset (dest); + + /* the single value is our new result */ + *dest = single_dest; + } + } +} + +/** + * gst_value_list_get_size: + * @value: a #GValue of type #GST_TYPE_LIST + * + * Gets the number of values contained in @value. + * + * Returns: the number of values + */ +guint +gst_value_list_get_size (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0); + + return ((GArray *) value->data[0].v_pointer)->len; +} + +/** + * gst_value_list_get_value: + * @value: a #GValue of type #GST_TYPE_LIST + * @index: index of value to get from the list + * + * Gets the value that is a member of the list contained in @value and + * has the index @index. + * + * Returns: (transfer none): the value at the given index + */ +const GValue * +gst_value_list_get_value (const GValue * value, guint index) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL); + g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL); + + return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, + GValue, index); +} + +/** + * gst_value_array_append_value: + * @value: a #GValue of type #GST_TYPE_ARRAY + * @append_value: the value to append + * + * Appends @append_value to the GstValueArray in @value. + */ +void +gst_value_array_append_value (GValue * value, const GValue * append_value) +{ + GValue val = { 0, }; + + g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value)); + g_return_if_fail (G_IS_VALUE (append_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + append_value)); + + gst_value_init_and_copy (&val, append_value); + g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1); +} + +static inline void +_gst_value_array_append_and_take_value (GValue * value, GValue * append_value) +{ + g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1); + memset (append_value, 0, sizeof (GValue)); +} + +/** + * gst_value_array_append_and_take_value: + * @value: a #GValue of type #GST_TYPE_ARRAY + * @append_value: (transfer full): the value to append + * + * Appends @append_value to the GstValueArray in @value. + * + * Since: 1.2 + */ +void +gst_value_array_append_and_take_value (GValue * value, GValue * append_value) +{ + g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value)); + g_return_if_fail (G_IS_VALUE (append_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + append_value)); + + _gst_value_array_append_and_take_value (value, append_value); +} + +/** + * gst_value_array_prepend_value: + * @value: a #GValue of type #GST_TYPE_ARRAY + * @prepend_value: the value to prepend + * + * Prepends @prepend_value to the GstValueArray in @value. + */ +void +gst_value_array_prepend_value (GValue * value, const GValue * prepend_value) +{ + GValue val = { 0, }; + + g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value)); + g_return_if_fail (G_IS_VALUE (prepend_value)); + g_return_if_fail (gst_value_list_or_array_are_compatible (value, + prepend_value)); + + gst_value_init_and_copy (&val, prepend_value); + g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1); +} + +/** + * gst_value_array_get_size: + * @value: a #GValue of type #GST_TYPE_ARRAY + * + * Gets the number of values contained in @value. + * + * Returns: the number of values + */ +guint +gst_value_array_get_size (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0); + + return ((GArray *) value->data[0].v_pointer)->len; +} + +/** + * gst_value_array_get_value: + * @value: a #GValue of type #GST_TYPE_ARRAY + * @index: index of value to get from the array + * + * Gets the value that is a member of the array contained in @value and + * has the index @index. + * + * Returns: (transfer none): the value at the given index + */ +const GValue * +gst_value_array_get_value (const GValue * value, guint index) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL); + g_return_val_if_fail (index < gst_value_array_get_size (value), NULL); + + return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, + GValue, index); +} + +static void +gst_value_transform_list_string (const GValue * src_value, GValue * dest_value) +{ + gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }"); +} + +static void +gst_value_transform_array_string (const GValue * src_value, GValue * dest_value) +{ + gst_value_transform_any_list_string (src_value, dest_value, "< ", " >"); +} + +static void +gst_value_transform_g_value_array_string (const GValue * src_value, + GValue * dest_value) +{ + _gst_value_transform_g_value_array_string (src_value, dest_value, "< ", " >"); +} + +static void +gst_value_transform_g_value_array_any_list (const GValue * src_value, + GValue * dest_value) +{ + const GValueArray *varray; + GArray *array; + gint i; + + /* GLib will unset the value, memset to 0 the data instead of doing a proper + * reset. That's why we need to allocate the array here */ + gst_value_init_list_or_array (dest_value); + + varray = g_value_get_boxed (src_value); + array = dest_value->data[0].v_pointer; + + for (i = 0; i < varray->n_values; i++) { + GValue val = G_VALUE_INIT; + gst_value_init_and_copy (&val, &varray->values[i]); + g_array_append_vals (array, &val, 1); + } +} + +static void +gst_value_transform_any_list_g_value_array (const GValue * src_value, + GValue * dest_value) +{ + GValueArray *varray; + const GArray *array; + gint i; + + array = src_value->data[0].v_pointer; + varray = g_value_array_new (array->len); + + for (i = 0; i < array->len; i++) + g_value_array_append (varray, &g_array_index (array, GValue, i)); + + g_value_take_boxed (dest_value, varray); +} + +/* Do an unordered compare of the contents of a list */ +static gint +gst_value_compare_value_list (const GValue * value1, const GValue * value2) +{ + guint i, j; + GArray *array1 = value1->data[0].v_pointer; + GArray *array2 = value2->data[0].v_pointer; + GValue *v1; + GValue *v2; + gint len, to_remove; + guint8 *removed; + GstValueCompareFunc compare; + + /* get length and do initial length check. */ + len = array1->len; + if (len != array2->len) + return GST_VALUE_UNORDERED; + + /* place to mark removed value indices of array2 */ + removed = g_newa (guint8, len); + memset (removed, 0, len); + to_remove = len; + + /* loop over array1, all items should be in array2. When we find an + * item in array2, remove it from array2 by marking it as removed */ + for (i = 0; i < len; i++) { + v1 = &g_array_index (array1, GValue, i); + if ((compare = gst_value_get_compare_func (v1))) { + for (j = 0; j < len; j++) { + /* item is removed, we can skip it */ + if (removed[j]) + continue; + v2 = &g_array_index (array2, GValue, j); + if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) { + /* mark item as removed now that we found it in array2 and + * decrement the number of remaining items in array2. */ + removed[j] = 1; + to_remove--; + break; + } + } + /* item in array1 and not in array2, UNORDERED */ + if (j == len) + return GST_VALUE_UNORDERED; + } else + return GST_VALUE_UNORDERED; + } + /* if not all items were removed, array2 contained something not in array1 */ + if (to_remove != 0) + return GST_VALUE_UNORDERED; + + /* arrays are equal */ + return GST_VALUE_EQUAL; +} + +/* Perform an ordered comparison of the contents of an array */ +static gint +gst_value_compare_value_array (const GValue * value1, const GValue * value2) +{ + guint i; + GArray *array1 = value1->data[0].v_pointer; + GArray *array2 = value2->data[0].v_pointer; + guint len = array1->len; + GValue *v1; + GValue *v2; + + if (len != array2->len) + return GST_VALUE_UNORDERED; + + for (i = 0; i < len; i++) { + v1 = &g_array_index (array1, GValue, i); + v2 = &g_array_index (array2, GValue, i); + if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; + } + + return GST_VALUE_EQUAL; +} + +static gint +gst_value_compare_g_value_array (const GValue * value1, const GValue * value2) +{ + guint i; + GValueArray *array1 = value1->data[0].v_pointer; + GValueArray *array2 = value2->data[0].v_pointer; + guint len = array1->n_values; + GValue *v1; + GValue *v2; + + if (len != array2->n_values) + return GST_VALUE_UNORDERED; + + for (i = 0; i < len; i++) { + v1 = g_value_array_get_nth (array1, i); + v2 = g_value_array_get_nth (array2, i); + if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; + } + + return GST_VALUE_EQUAL; +} + +static gchar * +gst_value_serialize_value_list (const GValue * value) +{ + return _priv_gst_value_serialize_any_list (value, "{ ", " }", TRUE); +} + +static gboolean +gst_value_deserialize_value_list (GValue * dest, const gchar * s) +{ + gchar *s2 = (gchar *) s; + return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID); +} + +static gchar * +gst_value_serialize_value_array (const GValue * value) +{ + return _priv_gst_value_serialize_any_list (value, "< ", " >", TRUE); +} + +static gboolean +gst_value_deserialize_value_array (GValue * dest, const gchar * s) +{ + gchar *s2 = (gchar *) s; + return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID); +} + +static gchar * +gst_value_serialize_g_value_array (const GValue * value) +{ + return _gst_value_serialize_g_value_array (value, "< ", " >"); +} + +static gboolean +gst_value_deserialize_g_value_array (GValue * dest, const gchar * s) +{ + g_warning ("gst_value_deserialize_g_value_array: unimplemented"); + return FALSE; +} + +/************* + * int range * + * + * Values in the range are defined as any value greater or equal + * to min*step, AND lesser or equal to max*step. + * For step == 1, this falls back to the traditional range semantics. + * + * data[0] = (min << 32) | (max) + * data[1] = step + * + *************/ + +#define INT_RANGE_MIN(v) ((gint) (((v)->data[0].v_uint64) >> 32)) +#define INT_RANGE_MAX(v) ((gint) (((v)->data[0].v_uint64) & 0xffffffff)) +#define INT_RANGE_STEP(v) ((v)->data[1].v_int) + +static void +gst_value_init_int_range (GValue * value) +{ + G_STATIC_ASSERT (sizeof (gint) <= 2 * sizeof (guint64)); + + value->data[0].v_uint64 = 0; + value->data[1].v_int = 1; +} + +static void +gst_value_copy_int_range (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; + dest_value->data[1].v_int = src_value->data[1].v_int; +} + +static gchar * +gst_value_collect_int_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[0].v_int >= collect_values[1].v_int) + return g_strdup_printf ("range start is not smaller than end for `%s'", + G_VALUE_TYPE_NAME (value)); + + gst_value_set_int_range_step (value, collect_values[0].v_int, + collect_values[1].v_int, 1); + + return NULL; +} + +static gchar * +gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + guint32 *int_range_start = collect_values[0].v_pointer; + guint32 *int_range_end = collect_values[1].v_pointer; + + if (!int_range_start) + return g_strdup_printf ("start value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!int_range_end) + return g_strdup_printf ("end value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *int_range_start = INT_RANGE_MIN (value); + *int_range_end = INT_RANGE_MAX (value); + + return NULL; +} + +/** + * gst_value_set_int_range_step: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * @start: the start of the range + * @end: the end of the range + * @step: the step of the range + * + * Sets @value to the range specified by @start, @end and @step. + */ +void +gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step) +{ + guint64 sstart, sstop; + + g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); + g_return_if_fail (start < end); + g_return_if_fail (step > 0); + g_return_if_fail (start % step == 0); + g_return_if_fail (end % step == 0); + + sstart = (guint) (start / step); + sstop = (guint) (end / step); + value->data[0].v_uint64 = (sstart << 32) | sstop; + value->data[1].v_int = step; +} + +/** + * gst_value_set_int_range: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * @start: the start of the range + * @end: the end of the range + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_int_range (GValue * value, gint start, gint end) +{ + gst_value_set_int_range_step (value, start, end, 1); +} + +/** + * gst_value_get_int_range_min: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: the minimum of the range + */ +gint +gst_value_get_int_range_min (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); + + return INT_RANGE_MIN (value) * INT_RANGE_STEP (value); +} + +/** + * gst_value_get_int_range_max: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: the maximum of the range + */ +gint +gst_value_get_int_range_max (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); + + return INT_RANGE_MAX (value) * INT_RANGE_STEP (value); +} + +/** + * gst_value_get_int_range_step: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * + * Gets the step of the range specified by @value. + * + * Returns: the step of the range + */ +gint +gst_value_get_int_range_step (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); + + return INT_RANGE_STEP (value); +} + +static void +gst_value_transform_int_range_string (const GValue * src_value, + GValue * dest_value) +{ + if (INT_RANGE_STEP (src_value) == 1) + dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]", + INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value)); + else + dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]", + INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value), + INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value), + INT_RANGE_STEP (src_value)); +} + +static gint +gst_value_compare_int_range (const GValue * value1, const GValue * value2) +{ + /* calculate the number of values in each range */ + gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1; + gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1; + + /* they must be equal */ + if (n1 != n2) + return GST_VALUE_UNORDERED; + + /* if empty, equal */ + if (n1 == 0) + return GST_VALUE_EQUAL; + + /* if more than one value, then it is only equal if the step is equal + and bounds lie on the same value */ + if (n1 > 1) { + if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) && + INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) && + INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) { + return GST_VALUE_EQUAL; + } + return GST_VALUE_UNORDERED; + } else { + /* if just one, only if the value is equal */ + if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; + } +} + +static gchar * +gst_value_serialize_int_range (const GValue * value) +{ + if (INT_RANGE_STEP (value) == 1) + return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value), + INT_RANGE_MAX (value)); + else + return g_strdup_printf ("[ %d, %d, %d ]", + INT_RANGE_MIN (value) * INT_RANGE_STEP (value), + INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value)); +} + +static gboolean +gst_value_deserialize_int_range (GValue * dest, const gchar * s) +{ + g_warning ("unimplemented"); + return FALSE; +} + +/*************** + * int64 range * + * + * Values in the range are defined as any value greater or equal + * to min*step, AND lesser or equal to max*step. + * For step == 1, this falls back to the traditional range semantics. + ***************/ + +#define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0]) +#define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1]) +#define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2]) + +static void +gst_value_init_int64_range (GValue * value) +{ + gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64)); + value->data[0].v_pointer = vals; + INT64_RANGE_MIN (value) = 0; + INT64_RANGE_MAX (value) = 0; + INT64_RANGE_STEP (value) = 1; +} + +static void +gst_value_free_int64_range (GValue * value) +{ + g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value)); + g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer); + value->data[0].v_pointer = NULL; +} + +static void +gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value) +{ + gint64 *vals = (gint64 *) dest_value->data[0].v_pointer; + gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer; + + if (vals == NULL) { + gst_value_init_int64_range (dest_value); + } + + if (src_vals != NULL) { + INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value); + INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value); + INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value); + } +} + +static gchar * +gst_value_collect_int64_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + gint64 *vals = value->data[0].v_pointer; + + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[0].v_int64 >= collect_values[1].v_int64) + return g_strdup_printf ("range start is not smaller than end for `%s'", + G_VALUE_TYPE_NAME (value)); + + if (vals == NULL) { + gst_value_init_int64_range (value); + } + + gst_value_set_int64_range_step (value, collect_values[0].v_int64, + collect_values[1].v_int64, 1); + + return NULL; +} + +static gchar * +gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + guint64 *int_range_start = collect_values[0].v_pointer; + guint64 *int_range_end = collect_values[1].v_pointer; + guint64 *int_range_step = collect_values[2].v_pointer; + gint64 *vals = (gint64 *) value->data[0].v_pointer; + + if (!int_range_start) + return g_strdup_printf ("start value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!int_range_end) + return g_strdup_printf ("end value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!int_range_step) + return g_strdup_printf ("step value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + if (G_UNLIKELY (vals == NULL)) { + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + } + + *int_range_start = INT64_RANGE_MIN (value); + *int_range_end = INT64_RANGE_MAX (value); + *int_range_step = INT64_RANGE_STEP (value); + + return NULL; +} + +/** + * gst_value_set_int64_range_step: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * @start: the start of the range + * @end: the end of the range + * @step: the step of the range + * + * Sets @value to the range specified by @start, @end and @step. + */ +void +gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end, + gint64 step) +{ + g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value)); + g_return_if_fail (start < end); + g_return_if_fail (step > 0); + g_return_if_fail (start % step == 0); + g_return_if_fail (end % step == 0); + + INT64_RANGE_MIN (value) = start / step; + INT64_RANGE_MAX (value) = end / step; + INT64_RANGE_STEP (value) = step; +} + +/** + * gst_value_set_int64_range: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * @start: the start of the range + * @end: the end of the range + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_int64_range (GValue * value, gint64 start, gint64 end) +{ + gst_value_set_int64_range_step (value, start, end, 1); +} + +/** + * gst_value_get_int64_range_min: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: the minimum of the range + */ +gint64 +gst_value_get_int64_range_min (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); + + return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value); +} + +/** + * gst_value_get_int64_range_max: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: the maximum of the range + */ +gint64 +gst_value_get_int64_range_max (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); + + return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value); +} + +/** + * gst_value_get_int64_range_step: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the step of the range specified by @value. + * + * Returns: the step of the range + */ +gint64 +gst_value_get_int64_range_step (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); + + return INT64_RANGE_STEP (value); +} + +static void +gst_value_transform_int64_range_string (const GValue * src_value, + GValue * dest_value) +{ + if (INT64_RANGE_STEP (src_value) == 1) + dest_value->data[0].v_pointer = + g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]", + INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value)); + else + dest_value->data[0].v_pointer = + g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT + ",%" G_GINT64_FORMAT "]", + INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value), + INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value), + INT64_RANGE_STEP (src_value)); +} + +static gint +gst_value_compare_int64_range (const GValue * value1, const GValue * value2) +{ + /* calculate the number of values in each range */ + gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1; + gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1; + + /* they must be equal */ + if (n1 != n2) + return GST_VALUE_UNORDERED; + + /* if empty, equal */ + if (n1 == 0) + return GST_VALUE_EQUAL; + + /* if more than one value, then it is only equal if the step is equal + and bounds lie on the same value */ + if (n1 > 1) { + if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) && + INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) && + INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) { + return GST_VALUE_EQUAL; + } + return GST_VALUE_UNORDERED; + } else { + /* if just one, only if the value is equal */ + if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; + } +} + +static gchar * +gst_value_serialize_int64_range (const GValue * value) +{ + if (INT64_RANGE_STEP (value) == 1) + return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]", + INT64_RANGE_MIN (value), INT64_RANGE_MAX (value)); + else + return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %" + G_GINT64_FORMAT " ]", + INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value), + INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value), + INT64_RANGE_STEP (value)); +} + +static gboolean +gst_value_deserialize_int64_range (GValue * dest, const gchar * s) +{ + g_warning ("unimplemented"); + return FALSE; +} + +/**************** + * double range * + ****************/ + +static void +gst_value_init_double_range (GValue * value) +{ + value->data[0].v_double = 0; + value->data[1].v_double = 0; +} + +static void +gst_value_copy_double_range (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_double = src_value->data[0].v_double; + dest_value->data[1].v_double = src_value->data[1].v_double; +} + +static gchar * +gst_value_collect_double_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[0].v_double >= collect_values[1].v_double) + return g_strdup_printf ("range start is not smaller than end for `%s'", + G_VALUE_TYPE_NAME (value)); + + value->data[0].v_double = collect_values[0].v_double; + value->data[1].v_double = collect_values[1].v_double; + + return NULL; +} + +static gchar * +gst_value_lcopy_double_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + gdouble *double_range_start = collect_values[0].v_pointer; + gdouble *double_range_end = collect_values[1].v_pointer; + + if (!double_range_start) + return g_strdup_printf ("start value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!double_range_end) + return g_strdup_printf ("end value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *double_range_start = value->data[0].v_double; + *double_range_end = value->data[1].v_double; + + return NULL; +} + +/** + * gst_value_set_double_range: + * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE + * @start: the start of the range + * @end: the end of the range + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_double_range (GValue * value, gdouble start, gdouble end) +{ + g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value)); + g_return_if_fail (start < end); + + value->data[0].v_double = start; + value->data[1].v_double = end; +} + +/** + * gst_value_get_double_range_min: + * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: the minimum of the range + */ +gdouble +gst_value_get_double_range_min (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0); + + return value->data[0].v_double; +} + +/** + * gst_value_get_double_range_max: + * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: the maximum of the range + */ +gdouble +gst_value_get_double_range_max (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0); + + return value->data[1].v_double; +} + +static void +gst_value_transform_double_range_string (const GValue * src_value, + GValue * dest_value) +{ + gchar s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE]; + + dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]", + g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE, + src_value->data[0].v_double), + g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE, + src_value->data[1].v_double)); +} + +static gint +gst_value_compare_double_range (const GValue * value1, const GValue * value2) +{ + if (value2->data[0].v_double == value1->data[0].v_double && + value2->data[1].v_double == value1->data[1].v_double) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_double_range (const GValue * value) +{ + gchar d1[G_ASCII_DTOSTR_BUF_SIZE]; + gchar d2[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double); + g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double); + return g_strdup_printf ("[ %s, %s ]", d1, d2); +} + +static gboolean +gst_value_deserialize_double_range (GValue * dest, const gchar * s) +{ + g_warning ("unimplemented"); + return FALSE; +} + +/**************** + * fraction range * + ****************/ + +static void +gst_value_init_fraction_range (GValue * value) +{ + GValue *vals; + GType ftype; + + ftype = GST_TYPE_FRACTION; + + value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue)); + g_value_init (&vals[0], ftype); + g_value_init (&vals[1], ftype); +} + +static void +gst_value_free_fraction_range (GValue * value) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (vals != NULL) { + /* we know the two values contain fractions without internal allocs */ + /* g_value_unset (&vals[0]); */ + /* g_value_unset (&vals[1]); */ + g_slice_free1 (2 * sizeof (GValue), vals); + value->data[0].v_pointer = NULL; + } +} + +static void +gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value) +{ + GValue *vals = (GValue *) dest_value->data[0].v_pointer; + GValue *src_vals = (GValue *) src_value->data[0].v_pointer; + + if (vals == NULL) { + gst_value_init_fraction_range (dest_value); + vals = dest_value->data[0].v_pointer; + } + if (src_vals != NULL) { + g_value_copy (&src_vals[0], &vals[0]); + g_value_copy (&src_vals[1], &vals[1]); + } +} + +static gchar * +gst_value_collect_fraction_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (n_collect_values != 4) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[1].v_int == 0) + return g_strdup_printf ("passed '0' as first denominator for `%s'", + G_VALUE_TYPE_NAME (value)); + if (collect_values[3].v_int == 0) + return g_strdup_printf ("passed '0' as second denominator for `%s'", + G_VALUE_TYPE_NAME (value)); + if (gst_util_fraction_compare (collect_values[0].v_int, + collect_values[1].v_int, collect_values[2].v_int, + collect_values[3].v_int) >= 0) + return g_strdup_printf ("range start is not smaller than end for `%s'", + G_VALUE_TYPE_NAME (value)); + + if (vals == NULL) { + gst_value_init_fraction_range (value); + vals = value->data[0].v_pointer; + } + + gst_value_set_fraction (&vals[0], collect_values[0].v_int, + collect_values[1].v_int); + gst_value_set_fraction (&vals[1], collect_values[2].v_int, + collect_values[3].v_int); + + return NULL; +} + +static gchar * +gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + gint i; + gint *dest_values[4]; + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (G_UNLIKELY (n_collect_values != 4)) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + + for (i = 0; i < 4; i++) { + if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) { + return g_strdup_printf ("value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + } + dest_values[i] = collect_values[i].v_pointer; + } + + if (G_UNLIKELY (vals == NULL)) { + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + } + + dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]); + dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]); + dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]); + dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]); + return NULL; +} + +/** + * gst_value_set_fraction_range: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * @start: the start of the range (a GST_TYPE_FRACTION GValue) + * @end: the end of the range (a GST_TYPE_FRACTION GValue) + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_fraction_range (GValue * value, const GValue * start, + const GValue * end) +{ + GValue *vals; + + g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); + g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start)); + g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end)); + g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int, + start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0); + + vals = (GValue *) value->data[0].v_pointer; + if (vals == NULL) { + gst_value_init_fraction_range (value); + vals = value->data[0].v_pointer; + } + g_value_copy (start, &vals[0]); + g_value_copy (end, &vals[1]); +} + +/** + * gst_value_set_fraction_range_full: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * @numerator_start: the numerator start of the range + * @denominator_start: the denominator start of the range + * @numerator_end: the numerator end of the range + * @denominator_end: the denominator end of the range + * + * Sets @value to the range specified by @numerator_start/@denominator_start + * and @numerator_end/@denominator_end. + */ +void +gst_value_set_fraction_range_full (GValue * value, + gint numerator_start, gint denominator_start, + gint numerator_end, gint denominator_end) +{ + GValue start = { 0 }; + GValue end = { 0 }; + + g_return_if_fail (value != NULL); + g_return_if_fail (denominator_start != 0); + g_return_if_fail (denominator_end != 0); + g_return_if_fail (gst_util_fraction_compare (numerator_start, + denominator_start, numerator_end, denominator_end) < 0); + + g_value_init (&start, GST_TYPE_FRACTION); + g_value_init (&end, GST_TYPE_FRACTION); + + gst_value_set_fraction (&start, numerator_start, denominator_start); + gst_value_set_fraction (&end, numerator_end, denominator_end); + gst_value_set_fraction_range (value, &start, &end); + + /* we know the two values contain fractions without internal allocs */ + /* g_value_unset (&start); */ + /* g_value_unset (&end); */ +} + +/* FIXME 2.0: Don't leak the internal representation of fraction + * ranges but instead return the numerator and denominator + * separately. + * This would allow to store fraction ranges as + * data[0] = (min_n << 32) | (min_d) + * data[1] = (max_n << 32) | (max_d) + * without requiring an additional allocation for each value. + */ + +/** + * gst_value_get_fraction_range_min: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: (nullable): the minimum of the range + */ +const GValue * +gst_value_get_fraction_range_min (const GValue * value) +{ + GValue *vals; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL); + + vals = (GValue *) value->data[0].v_pointer; + if (vals != NULL) { + return &vals[0]; + } + + return NULL; +} + +/** + * gst_value_get_fraction_range_max: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: (nullable): the maximum of the range + */ +const GValue * +gst_value_get_fraction_range_max (const GValue * value) +{ + GValue *vals; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL); + + vals = (GValue *) value->data[0].v_pointer; + if (vals != NULL) { + return &vals[1]; + } + + return NULL; +} + +static gchar * +gst_value_serialize_fraction_range (const GValue * value) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + gchar *retval; + + if (vals == NULL) { + retval = g_strdup ("[ 0/1, 0/1 ]"); + } else { + gchar *start, *end; + + start = gst_value_serialize_fraction (&vals[0]); + end = gst_value_serialize_fraction (&vals[1]); + + retval = g_strdup_printf ("[ %s, %s ]", start, end); + g_free (start); + g_free (end); + } + + return retval; +} + +static void +gst_value_transform_fraction_range_string (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_pointer = + gst_value_serialize_fraction_range (src_value); +} + +static gint +gst_value_compare_fraction_range (const GValue * value1, const GValue * value2) +{ + GValue *vals1, *vals2; + GstValueCompareFunc compare; + + if (value2->data[0].v_pointer == value1->data[0].v_pointer) + return GST_VALUE_EQUAL; /* Only possible if both are NULL */ + + if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL) + return GST_VALUE_UNORDERED; + + vals1 = (GValue *) value1->data[0].v_pointer; + vals2 = (GValue *) value2->data[0].v_pointer; + if ((compare = gst_value_get_compare_func (&vals1[0]))) { + if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) == + GST_VALUE_EQUAL && + gst_value_compare_with_func (&vals1[1], &vals2[1], compare) == + GST_VALUE_EQUAL) + return GST_VALUE_EQUAL; + } + return GST_VALUE_UNORDERED; +} + +static gboolean +gst_value_deserialize_fraction_range (GValue * dest, const gchar * s) +{ + g_warning ("unimplemented"); + return FALSE; +} + +/*********** + * GstCaps * + ***********/ + +/** + * gst_value_set_caps: + * @value: a GValue initialized to GST_TYPE_CAPS + * @caps: (transfer none): the caps to set the value to + * + * Sets the contents of @value to @caps. A reference to the + * provided @caps will be taken by the @value. + */ +void +gst_value_set_caps (GValue * value, const GstCaps * caps) +{ + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS); + g_return_if_fail (caps == NULL || GST_IS_CAPS (caps)); + + g_value_set_boxed (value, caps); +} + +/** + * gst_value_get_caps: + * @value: a GValue initialized to GST_TYPE_CAPS + * + * Gets the contents of @value. The reference count of the returned + * #GstCaps will not be modified, therefore the caller must take one + * before getting rid of the @value. + * + * Returns: (transfer none): the contents of @value + */ +const GstCaps * +gst_value_get_caps (const GValue * value) +{ + g_return_val_if_fail (G_IS_VALUE (value), NULL); + g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL); + + return (GstCaps *) g_value_get_boxed (value); +} + +static gint +gst_value_compare_caps (const GValue * value1, const GValue * value2) +{ + GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1)); + GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2)); + + if (gst_caps_is_equal (caps1, caps2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_caps (const GValue * value) +{ + GstCaps *caps = g_value_get_boxed (value); + return priv_gst_string_take_and_wrap (gst_caps_to_string (caps)); +} + +static gboolean +gst_value_deserialize_caps (GValue * dest, const gchar * s) +{ + GstCaps *caps; + + if (*s != '"') { + caps = gst_caps_from_string (s); + } else { + gchar *str = gst_string_unwrap (s); + + if (G_UNLIKELY (!str)) + return FALSE; + + caps = gst_caps_from_string (str); + g_free (str); + } + + if (caps) { + g_value_take_boxed (dest, caps); + return TRUE; + } + return FALSE; +} + +/******************************************** + * Serialization/deserialization of GValues * + ********************************************/ + +static GstValueAbbreviation * +_priv_gst_value_get_abbrs (gint * n_abbrs) +{ + static GstValueAbbreviation *abbrs = NULL; + static volatile gsize num = 0; + + if (g_once_init_enter (&num)) { + /* dynamically generate the array */ + gsize _num; + GstValueAbbreviation dyn_abbrs[] = { + {"int", G_TYPE_INT} + , + {"i", G_TYPE_INT} + , + {"uint", G_TYPE_UINT} + , + {"u", G_TYPE_UINT} + , + {"float", G_TYPE_FLOAT} + , + {"f", G_TYPE_FLOAT} + , + {"double", G_TYPE_DOUBLE} + , + {"d", G_TYPE_DOUBLE} + , + {"buffer", GST_TYPE_BUFFER} + , + {"fraction", GST_TYPE_FRACTION} + , + {"boolean", G_TYPE_BOOLEAN} + , + {"bool", G_TYPE_BOOLEAN} + , + {"b", G_TYPE_BOOLEAN} + , + {"string", G_TYPE_STRING} + , + {"str", G_TYPE_STRING} + , + {"s", G_TYPE_STRING} + , + {"structure", GST_TYPE_STRUCTURE} + , + {"date", G_TYPE_DATE} + , + {"datetime", GST_TYPE_DATE_TIME} + , + {"bitmask", GST_TYPE_BITMASK} + , + {"flagset", GST_TYPE_FLAG_SET} + , + {"sample", GST_TYPE_SAMPLE} + , + {"taglist", GST_TYPE_TAG_LIST} + , + {"type", G_TYPE_GTYPE} + , + {"array", GST_TYPE_ARRAY} + , + {"list", GST_TYPE_LIST} + }; + _num = G_N_ELEMENTS (dyn_abbrs); + /* permanently allocate and copy the array now */ + abbrs = g_new0 (GstValueAbbreviation, _num); + memcpy (abbrs, dyn_abbrs, sizeof (GstValueAbbreviation) * _num); + g_once_init_leave (&num, _num); + } + *n_abbrs = num; + + return abbrs; +} + +/* given a type_name that could be a type abbreviation or a registered GType, + * return a matching GType */ +static GType +_priv_gst_value_gtype_from_abbr (const char *type_name) +{ + int i; + GstValueAbbreviation *abbrs; + gint n_abbrs; + GType ret; + + g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID); + + abbrs = _priv_gst_value_get_abbrs (&n_abbrs); + + for (i = 0; i < n_abbrs; i++) { + if (strcmp (type_name, abbrs[i].type_name) == 0) { + return abbrs[i].type; + } + } + + /* this is the fallback */ + ret = g_type_from_name (type_name); + /* If not found, try it as a dynamic type */ + if (G_UNLIKELY (ret == 0)) + ret = gst_dynamic_type_factory_load (type_name); + return ret; + +} + +const char * +_priv_gst_value_gtype_to_abbr (GType type) +{ + int i; + GstValueAbbreviation *abbrs; + gint n_abbrs; + + g_return_val_if_fail (type != G_TYPE_INVALID, NULL); + + abbrs = _priv_gst_value_get_abbrs (&n_abbrs); + + for (i = 0; i < n_abbrs; i++) { + if (type == abbrs[i].type) { + return abbrs[i].type_name; + } + } + + return g_type_name (type); +} + +/* + * _priv_gst_value_parse_string: + * @s: string to parse + * @end: out-pointer to char behind end of string + * @next: out-pointer to start of unread data + * @unescape: @TRUE if the substring is escaped. + * + * Find the end of a sub-string. If end == next, the string will not be + * null-terminated. In all other cases it will be. + * + * Note: This function modifies the string in @s (if unescape == @TRUE). + * + * Returns: @TRUE if a sub-string was found and @FALSE if the string is not + * terminated. + */ +gboolean +_priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next, + gboolean unescape) +{ + gchar *w; + + if (*s == 0) + return FALSE; + + if (*s != '"') { + int ret = _priv_gst_value_parse_simple_string (s, end); + *next = *end; + + return ret; + } + + /* Find the closing quotes */ + if (unescape) { + w = s; + s++; + while (*s != '"') { + if (G_UNLIKELY (*s == 0)) + return FALSE; + if (G_UNLIKELY (*s == '\\')) { + s++; + if (G_UNLIKELY (*s == 0)) + return FALSE; + } + *w = *s; + w++; + s++; + } + s++; + } else { + s++; + while (*s != '"') { + if (G_UNLIKELY (*s == 0)) + return FALSE; + if (G_UNLIKELY (*s == '\\')) { + s++; + if (G_UNLIKELY (*s == 0)) + return FALSE; + } + s++; + } + s++; + w = s; + } + + *end = w; + *next = s; + + return TRUE; +} + +static gboolean +_priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value, + GType type) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue value3 = { 0 }; + GType range_type; + gboolean ret, have_step = FALSE; + + if (*s != '[') + return FALSE; + s++; + + ret = _priv_gst_value_parse_value (s, &s, &value1, type); + if (!ret) + return FALSE; + + while (g_ascii_isspace (*s)) + s++; + + if (*s != ',') + return FALSE; + s++; + + while (g_ascii_isspace (*s)) + s++; + + ret = _priv_gst_value_parse_value (s, &s, &value2, type); + if (!ret) + return FALSE; + + while (g_ascii_isspace (*s)) + s++; + + /* optional step for int and int64 */ + if (G_VALUE_TYPE (&value1) == G_TYPE_INT + || G_VALUE_TYPE (&value1) == G_TYPE_INT64) { + if (*s == ',') { + s++; + + while (g_ascii_isspace (*s)) + s++; + + ret = _priv_gst_value_parse_value (s, &s, &value3, type); + if (!ret) + return FALSE; + + while (g_ascii_isspace (*s)) + s++; + + have_step = TRUE; + } + } + + if (*s != ']') + return FALSE; + s++; + + if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2)) + return FALSE; + if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3)) + return FALSE; + + if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) { + range_type = GST_TYPE_DOUBLE_RANGE; + g_value_init (value, range_type); + gst_value_set_double_range (value, + gst_g_value_get_double_unchecked (&value1), + gst_g_value_get_double_unchecked (&value2)); + } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) { + range_type = GST_TYPE_INT_RANGE; + g_value_init (value, range_type); + if (have_step) + gst_value_set_int_range_step (value, + gst_g_value_get_int_unchecked (&value1), + gst_g_value_get_int_unchecked (&value2), + gst_g_value_get_int_unchecked (&value3)); + else + gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1), + gst_g_value_get_int_unchecked (&value2)); + } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) { + range_type = GST_TYPE_INT64_RANGE; + g_value_init (value, range_type); + if (have_step) + gst_value_set_int64_range_step (value, + gst_g_value_get_int64_unchecked (&value1), + gst_g_value_get_int64_unchecked (&value2), + gst_g_value_get_int64_unchecked (&value3)); + else + gst_value_set_int64_range (value, + gst_g_value_get_int64_unchecked (&value1), + gst_g_value_get_int64_unchecked (&value2)); + } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) { + range_type = GST_TYPE_FRACTION_RANGE; + g_value_init (value, range_type); + gst_value_set_fraction_range (value, &value1, &value2); + } else { + return FALSE; + } + + *after = s; + return TRUE; +} + +static gboolean +_priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value, + GType type, char begin, char end) +{ + GValue list_value = { 0 }; + gboolean ret; + GArray *array; + + array = g_value_peek_pointer (value); + + if (*s != begin) + return FALSE; + s++; + + while (g_ascii_isspace (*s)) + s++; + if (*s == end) { + s++; + *after = s; + return TRUE; + } + + ret = _priv_gst_value_parse_value (s, &s, &list_value, type); + if (!ret) + return FALSE; + + g_array_append_val (array, list_value); + + while (g_ascii_isspace (*s)) + s++; + + while (*s != end) { + if (*s != ',') + return FALSE; + s++; + + while (g_ascii_isspace (*s)) + s++; + + memset (&list_value, 0, sizeof (list_value)); + ret = _priv_gst_value_parse_value (s, &s, &list_value, type); + if (!ret) + return FALSE; + + g_array_append_val (array, list_value); + while (g_ascii_isspace (*s)) + s++; + } + + s++; + + *after = s; + return TRUE; +} + +static gboolean +_priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value, + GType type) +{ + return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}'); +} + +static gboolean +_priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value, + GType type) +{ + return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>'); +} + +gboolean +_priv_gst_value_parse_simple_string (gchar * str, gchar ** end) +{ + char *s = str; + + while (G_LIKELY (GST_ASCII_IS_STRING (*s))) { + s++; + } + + *end = s; + + return (s != str); +} + +gboolean +_priv_gst_value_parse_value (gchar * str, + gchar ** after, GValue * value, GType default_type) +{ + gchar *type_name; + gchar *type_end; + gchar *value_s; + gchar *value_end; + gchar *s; + gchar c; + int ret = 0; + GType type = default_type; + + s = str; + while (g_ascii_isspace (*s)) + s++; + + /* check if there's a (type_name) 'cast' */ + type_name = NULL; + if (*s == '(') { + s++; + while (g_ascii_isspace (*s)) + s++; + type_name = s; + if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &type_end))) + return FALSE; + s = type_end; + while (g_ascii_isspace (*s)) + s++; + if (G_UNLIKELY (*s != ')')) + return FALSE; + s++; + while (g_ascii_isspace (*s)) + s++; + + c = *type_end; + *type_end = 0; + type = _priv_gst_value_gtype_from_abbr (type_name); + GST_DEBUG ("trying type name '%s'", type_name); + *type_end = c; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) { + GST_WARNING ("invalid type"); + return FALSE; + } + } + + while (g_ascii_isspace (*s)) + s++; + if (*s == '[') { + ret = _priv_gst_value_parse_range (s, &s, value, type); + } else if (*s == '{') { + g_value_init (value, GST_TYPE_LIST); + ret = _priv_gst_value_parse_list (s, &s, value, type); + } else if (*s == '<') { + g_value_init (value, GST_TYPE_ARRAY); + ret = _priv_gst_value_parse_array (s, &s, value, type); + } else { + value_s = s; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) { + GType try_types[] = + { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET, + G_TYPE_BOOLEAN, G_TYPE_STRING + }; + int i; + + if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE))) + return FALSE; + /* Set NULL terminator for deserialization */ + c = *value_end; + *value_end = '\0'; + + for (i = 0; i < G_N_ELEMENTS (try_types); i++) { + g_value_init (value, try_types[i]); + ret = gst_value_deserialize (value, value_s); + if (ret) + break; + g_value_unset (value); + } + } else { + g_value_init (value, type); + + if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, + (type != G_TYPE_STRING)))) + return FALSE; + /* Set NULL terminator for deserialization */ + c = *value_end; + *value_end = '\0'; + + ret = gst_value_deserialize (value, value_s); + if (G_UNLIKELY (!ret)) + g_value_unset (value); + } + *value_end = c; + } + + *after = s; + + return ret; +} + +/************** + * GstSegment * + **************/ + +static gchar * +gst_value_serialize_segment_internal (const GValue * value, gboolean escape) +{ + GstSegment *seg = g_value_get_boxed (value); + gchar *t, *res; + GstStructure *s; + + s = gst_structure_new ("GstSegment", + "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags, + "rate", G_TYPE_DOUBLE, seg->rate, + "applied-rate", G_TYPE_DOUBLE, seg->applied_rate, + "format", GST_TYPE_FORMAT, seg->format, + "base", G_TYPE_UINT64, seg->base, + "offset", G_TYPE_UINT64, seg->offset, + "start", G_TYPE_UINT64, seg->start, + "stop", G_TYPE_UINT64, seg->stop, + "time", G_TYPE_UINT64, seg->time, + "position", G_TYPE_UINT64, seg->position, + "duration", G_TYPE_UINT64, seg->duration, NULL); + t = gst_structure_to_string (s); + if (escape) { + res = g_strdup_printf ("\"%s\"", t); + g_free (t); + } else { + res = t; + } + gst_structure_free (s); + + return res; +} + +static gchar * +gst_value_serialize_segment (const GValue * value) +{ + return gst_value_serialize_segment_internal (value, TRUE); +} + +static gboolean +gst_value_deserialize_segment (GValue * dest, const gchar * s) +{ + GstStructure *str; + GstSegment seg; + gboolean res; + + str = gst_structure_from_string (s, NULL); + if (str == NULL) + return FALSE; + + res = gst_structure_get (str, + "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags, + "rate", G_TYPE_DOUBLE, &seg.rate, + "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate, + "format", GST_TYPE_FORMAT, &seg.format, + "base", G_TYPE_UINT64, &seg.base, + "offset", G_TYPE_UINT64, &seg.offset, + "start", G_TYPE_UINT64, &seg.start, + "stop", G_TYPE_UINT64, &seg.stop, + "time", G_TYPE_UINT64, &seg.time, + "position", G_TYPE_UINT64, &seg.position, + "duration", G_TYPE_UINT64, &seg.duration, NULL); + gst_structure_free (str); + + if (res) + g_value_set_boxed (dest, &seg); + + return res; +} + +/**************** + * GstStructure * + ****************/ + +/** + * gst_value_set_structure: + * @value: a GValue initialized to GST_TYPE_STRUCTURE + * @structure: the structure to set the value to + * + * Sets the contents of @value to @structure. + */ +void +gst_value_set_structure (GValue * value, const GstStructure * structure) +{ + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE); + g_return_if_fail (structure == NULL || GST_IS_STRUCTURE (structure)); + + g_value_set_boxed (value, structure); +} + +/** + * gst_value_get_structure: + * @value: a GValue initialized to GST_TYPE_STRUCTURE + * + * Gets the contents of @value. + * + * Returns: (transfer none): the contents of @value + */ +const GstStructure * +gst_value_get_structure (const GValue * value) +{ + g_return_val_if_fail (G_IS_VALUE (value), NULL); + g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL); + + return (GstStructure *) g_value_get_boxed (value); +} + +static gchar * +gst_value_serialize_structure (const GValue * value) +{ + GstStructure *structure = g_value_get_boxed (value); + + return priv_gst_string_take_and_wrap (gst_structure_to_string (structure)); +} + +static gboolean +gst_value_deserialize_structure (GValue * dest, const gchar * s) +{ + GstStructure *structure; + + if (*s != '"') { + structure = gst_structure_from_string (s, NULL); + } else { + gchar *str = gst_string_unwrap (s); + + if (G_UNLIKELY (!str)) + return FALSE; + + structure = gst_structure_from_string (str, NULL); + g_free (str); + } + + if (G_LIKELY (structure)) { + g_value_take_boxed (dest, structure); + return TRUE; + } + return FALSE; +} + +static gboolean +gst_value_compare_structure (const GValue * value1, const GValue * value2) +{ + GstStructure *structure1 = GST_STRUCTURE (g_value_get_boxed (value1)); + GstStructure *structure2 = GST_STRUCTURE (g_value_get_boxed (value2)); + + if (structure1 == structure2) + return GST_VALUE_EQUAL; + + if (!structure1 || !structure2) + return GST_VALUE_UNORDERED; + + if (gst_structure_is_equal (structure1, structure2)) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + +/******************* + * GstCapsFeatures * + *******************/ + +/** + * gst_value_set_caps_features: + * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES + * @features: the features to set the value to + * + * Sets the contents of @value to @features. + */ +void +gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features) +{ + g_return_if_fail (G_IS_VALUE (value)); + g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES); + g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features)); + + g_value_set_boxed (value, features); +} + +/** + * gst_value_get_caps_features: + * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES + * + * Gets the contents of @value. + * + * Returns: (transfer none): the contents of @value + */ +const GstCapsFeatures * +gst_value_get_caps_features (const GValue * value) +{ + g_return_val_if_fail (G_IS_VALUE (value), NULL); + g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL); + + return (GstCapsFeatures *) g_value_get_boxed (value); +} + +static gchar * +gst_value_serialize_caps_features (const GValue * value) +{ + GstCapsFeatures *features = g_value_get_boxed (value); + + return priv_gst_string_take_and_wrap (gst_caps_features_to_string (features)); +} + +static gboolean +gst_value_deserialize_caps_features (GValue * dest, const gchar * s) +{ + GstCapsFeatures *features; + + if (*s != '"') { + features = gst_caps_features_from_string (s); + } else { + gchar *str = gst_string_unwrap (s); + + if (G_UNLIKELY (!str)) + return FALSE; + + features = gst_caps_features_from_string (str); + g_free (str); + } + + if (G_LIKELY (features)) { + g_value_take_boxed (dest, features); + return TRUE; + } + return FALSE; +} + +/************** + * GstTagList * + **************/ +static gint +gst_value_compare_tag_list (const GValue * value1, const GValue * value2) +{ + GstTagList *taglist1 = GST_TAG_LIST (g_value_get_boxed (value1)); + GstTagList *taglist2 = GST_TAG_LIST (g_value_get_boxed (value2)); + + if (gst_tag_list_is_equal (taglist1, taglist2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gboolean +gst_value_deserialize_tag_list (GValue * dest, const gchar * s) +{ + GstTagList *taglist; + + if (*s != '"') { + taglist = gst_tag_list_new_from_string (s); + } else { + gchar *str = gst_string_unwrap (s); + + if (G_UNLIKELY (!str)) + return FALSE; + + taglist = gst_tag_list_new_from_string (str); + g_free (str); + } + + if (G_LIKELY (taglist != NULL)) { + g_value_take_boxed (dest, taglist); + return TRUE; + } + return FALSE; +} + +static gchar * +gst_value_serialize_tag_list (const GValue * value) +{ + GstTagList *taglist = g_value_get_boxed (value); + + return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist)); +} + + +/************* + * GstBuffer * + *************/ + +static gint +compare_buffer (GstBuffer * buf1, GstBuffer * buf2) +{ + gsize size1, size2; + GstMapInfo info1, info2; + gint result, mret; + + if (buf1 == buf2) + return GST_VALUE_EQUAL; + + size1 = gst_buffer_get_size (buf1); + size2 = gst_buffer_get_size (buf2); + + if (size1 != size2) + return GST_VALUE_UNORDERED; + + if (size1 == 0) + return GST_VALUE_EQUAL; + + if (!gst_buffer_map (buf1, &info1, GST_MAP_READ)) + return GST_VALUE_UNORDERED; + + if (!gst_buffer_map (buf2, &info2, GST_MAP_READ)) { + gst_buffer_unmap (buf1, &info1); + return GST_VALUE_UNORDERED; + } + + mret = memcmp (info1.data, info2.data, info1.size); + if (mret == 0) + result = GST_VALUE_EQUAL; + else if (mret < 0) + result = GST_VALUE_LESS_THAN; + else + result = GST_VALUE_GREATER_THAN; + + gst_buffer_unmap (buf1, &info1); + gst_buffer_unmap (buf2, &info2); + + return result; +} + +static gint +gst_value_compare_buffer (const GValue * value1, const GValue * value2) +{ + GstBuffer *buf1 = gst_value_get_buffer (value1); + GstBuffer *buf2 = gst_value_get_buffer (value2); + + return compare_buffer (buf1, buf2); +} + +static gchar * +gst_value_serialize_buffer (const GValue * value) +{ + GstMapInfo info; + guint8 *data; + gint i; + gchar *string; + GstBuffer *buffer; + + buffer = gst_value_get_buffer (value); + if (buffer == NULL) + return NULL; + + if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) + return NULL; + + data = info.data; + + string = g_malloc (info.size * 2 + 1); + for (i = 0; i < info.size; i++) { + sprintf (string + i * 2, "%02x", data[i]); + } + string[info.size * 2] = 0; + + gst_buffer_unmap (buffer, &info); + + return string; +} + +static gboolean +gst_value_deserialize_buffer (GValue * dest, const gchar * s) +{ + GstBuffer *buffer; + gint len; + gchar ts[3]; + GstMapInfo info; + guint8 *data; + gint i; + + len = strlen (s); + if (len & 1) + goto wrong_length; + + buffer = gst_buffer_new_allocate (NULL, len / 2, NULL); + if (!gst_buffer_map (buffer, &info, GST_MAP_WRITE)) + goto map_failed; + data = info.data; + + for (i = 0; i < len / 2; i++) { + if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1])) + goto wrong_char; + + ts[0] = s[i * 2 + 0]; + ts[1] = s[i * 2 + 1]; + ts[2] = 0; + + data[i] = (guint8) strtoul (ts, NULL, 16); + } + gst_buffer_unmap (buffer, &info); + + gst_value_take_buffer (dest, buffer); + + return TRUE; + + /* ERRORS */ +wrong_length: + { + return FALSE; + } +map_failed: + { + return FALSE; + } +wrong_char: + { + gst_buffer_unref (buffer); + gst_buffer_unmap (buffer, &info); + return FALSE; + } +} + +/************* + * GstSample * + *************/ + +/* This function is mostly used for comparing image/buffer tags in taglists */ +static gint +gst_value_compare_sample (const GValue * value1, const GValue * value2) +{ + GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1)); + GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2)); + + /* FIXME: should we take into account anything else such as caps? */ + return compare_buffer (buf1, buf2); +} + +static gchar * +gst_value_serialize_sample (const GValue * value) +{ + const GstStructure *info_structure; + GstSegment *segment; + GstBuffer *buffer; + GstCaps *caps; + GstSample *sample; + GValue val = { 0, }; + gchar *info_str, *caps_str, *tmp; + gchar *buf_str, *seg_str, *s; + + sample = g_value_get_boxed (value); + + buffer = gst_sample_get_buffer (sample); + if (buffer) { + g_value_init (&val, GST_TYPE_BUFFER); + g_value_set_boxed (&val, buffer); + buf_str = gst_value_serialize_buffer (&val); + g_value_unset (&val); + } else { + buf_str = g_strdup ("None"); + } + + caps = gst_sample_get_caps (sample); + if (caps) { + tmp = gst_caps_to_string (caps); + caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (caps_str, "=", '_'); + g_free (tmp); + } else { + caps_str = g_strdup ("None"); + } + + segment = gst_sample_get_segment (sample); + if (segment) { + g_value_init (&val, GST_TYPE_SEGMENT); + g_value_set_boxed (&val, segment); + tmp = gst_value_serialize_segment_internal (&val, FALSE); + seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (seg_str, "=", '_'); + g_free (tmp); + g_value_unset (&val); + } else { + seg_str = g_strdup ("None"); + } + + info_structure = gst_sample_get_info (sample); + if (info_structure) { + tmp = gst_structure_to_string (info_structure); + info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (info_str, "=", '_'); + g_free (tmp); + } else { + info_str = g_strdup ("None"); + } + + s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL); + g_free (buf_str); + g_free (caps_str); + g_free (seg_str); + g_free (info_str); + + return s; +} + +static gboolean +gst_value_deserialize_sample (GValue * dest, const gchar * s) +{ + GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT; + GstStructure *info; + GstSample *sample; + GstCaps *caps = NULL; + gboolean ret = FALSE; + gchar **fields; + gsize outlen; + gint len; + + GST_TRACE ("deserialize '%s'", s); + + fields = g_strsplit (s, ":", -1); + len = g_strv_length (fields); + if (len != 4) + goto wrong_length; + + g_value_init (&bval, GST_TYPE_BUFFER); + g_value_init (&sval, GST_TYPE_SEGMENT); + + if (!gst_value_deserialize_buffer (&bval, fields[0])) + goto fail; + + if (strcmp (fields[1], "None") != 0) { + g_strdelimit (fields[1], "_", '='); + g_base64_decode_inplace (fields[1], &outlen); + GST_TRACE ("caps : %s", fields[1]); + caps = gst_caps_from_string (fields[1]); + if (caps == NULL) + goto fail; + } + + if (strcmp (fields[2], "None") != 0) { + g_strdelimit (fields[2], "_", '='); + g_base64_decode_inplace (fields[2], &outlen); + GST_TRACE ("segment : %s", fields[2]); + if (!gst_value_deserialize_segment (&sval, fields[2])) + goto fail; + } + + if (strcmp (fields[3], "None") != 0) { + g_strdelimit (fields[3], "_", '='); + g_base64_decode_inplace (fields[3], &outlen); + GST_TRACE ("info : %s", fields[3]); + info = gst_structure_from_string (fields[3], NULL); + if (info == NULL) + goto fail; + } else { + info = NULL; + } + + sample = gst_sample_new (gst_value_get_buffer (&bval), caps, + g_value_get_boxed (&sval), info); + + g_value_take_boxed (dest, sample); + + ret = TRUE; + +fail: + if (caps) + gst_caps_unref (caps); + g_value_unset (&bval); + g_value_unset (&sval); + +wrong_length: + + g_strfreev (fields); + + return ret; +} + +/*********** + * boolean * + ***********/ + +static gint +gst_value_compare_boolean (const GValue * value1, const GValue * value2) +{ + if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_boolean (const GValue * value) +{ + if (value->data[0].v_int) { + return g_strdup ("true"); + } + return g_strdup ("false"); +} + +static gboolean +gst_value_deserialize_boolean (GValue * dest, const gchar * s) +{ + gboolean ret = FALSE; + + if (g_ascii_strcasecmp (s, "true") == 0 || + g_ascii_strcasecmp (s, "yes") == 0 || + g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) { + g_value_set_boolean (dest, TRUE); + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "false") == 0 || + g_ascii_strcasecmp (s, "no") == 0 || + g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) { + g_value_set_boolean (dest, FALSE); + ret = TRUE; + } + + return ret; +} + +#define CREATE_SERIALIZATION_START(_type,_macro) \ +static gint \ +gst_value_compare_ ## _type \ +(const GValue * value1, const GValue * value2) \ +{ \ + g ## _type val1 = g_value_get_ ## _type (value1); \ + g ## _type val2 = g_value_get_ ## _type (value2); \ + if (val1 > val2) \ + return GST_VALUE_GREATER_THAN; \ + if (val1 < val2) \ + return GST_VALUE_LESS_THAN; \ + return GST_VALUE_EQUAL; \ +} \ + \ +static gchar * \ +gst_value_serialize_ ## _type (const GValue * value) \ +{ \ + GValue val = { 0, }; \ + g_value_init (&val, G_TYPE_STRING); \ + if (!g_value_transform (value, &val)) \ + g_assert_not_reached (); \ + /* NO_COPY_MADNESS!!! */ \ + return (char *) g_value_get_string (&val); \ +} + +/* deserialize the given s into to as a gint64. + * check if the result is actually storeable in the given size number of + * bytes. + */ +static gboolean +gst_value_deserialize_int_helper (gint64 * to, const gchar * s, + gint64 min, gint64 max, gint size) +{ + gboolean ret = FALSE; + gchar *end; + guint64 mask = ~0; + + errno = 0; + *to = g_ascii_strtoull (s, &end, 0); + /* a range error is a definitive no-no */ + if (errno == ERANGE) { + return FALSE; + } + + if (*end == 0) { + ret = TRUE; + } else { + if (g_ascii_strcasecmp (s, "little_endian") == 0) { + *to = G_LITTLE_ENDIAN; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { + *to = G_BIG_ENDIAN; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { + *to = G_BYTE_ORDER; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "min") == 0) { + *to = min; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "max") == 0) { + *to = max; + ret = TRUE; + } + } + if (ret) { + /* by definition, a gint64 fits into a gint64; so ignore those */ + if (size != sizeof (mask)) { + if (*to >= 0) { + /* for positive numbers, we create a mask of 1's outside of the range + * and 0's inside the range. An and will thus keep only 1 bits + * outside of the range */ + mask <<= (size * 8); + if ((mask & *to) != 0) { + ret = FALSE; + } + } else { + /* for negative numbers, we do a 2's complement version */ + mask <<= ((size * 8) - 1); + if ((mask & *to) != mask) { + ret = FALSE; + } + } + } + } + return ret; +} + +#define CREATE_SERIALIZATION(_type,_macro) \ +CREATE_SERIALIZATION_START(_type,_macro) \ + \ +static gboolean \ +gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \ +{ \ + gint64 x; \ + \ + if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \ + G_MAX ## _macro, sizeof (g ## _type))) { \ + g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \ + return TRUE; \ + } else { \ + return FALSE; \ + } \ +} + +#define CREATE_USERIALIZATION(_type,_macro) \ +CREATE_SERIALIZATION_START(_type,_macro) \ + \ +static gboolean \ +gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \ +{ \ + gint64 x; \ + gchar *end; \ + gboolean ret = FALSE; \ + \ + errno = 0; \ + x = g_ascii_strtoull (s, &end, 0); \ + /* a range error is a definitive no-no */ \ + if (errno == ERANGE) { \ + return FALSE; \ + } \ + /* the cast ensures the range check later on makes sense */ \ + x = (g ## _type) x; \ + if (*end == 0) { \ + ret = TRUE; \ + } else { \ + if (g_ascii_strcasecmp (s, "little_endian") == 0) { \ + x = G_LITTLE_ENDIAN; \ + ret = TRUE; \ + } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \ + x = G_BIG_ENDIAN; \ + ret = TRUE; \ + } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \ + x = G_BYTE_ORDER; \ + ret = TRUE; \ + } else if (g_ascii_strcasecmp (s, "min") == 0) { \ + x = 0; \ + ret = TRUE; \ + } else if (g_ascii_strcasecmp (s, "max") == 0) { \ + x = G_MAX ## _macro; \ + ret = TRUE; \ + } \ + } \ + if (ret) { \ + if (x > G_MAX ## _macro) { \ + ret = FALSE; \ + } else { \ + g_value_set_ ## _type (dest, x); \ + } \ + } \ + return ret; \ +} + +CREATE_SERIALIZATION (int, INT); +CREATE_SERIALIZATION (int64, INT64); +CREATE_SERIALIZATION (long, LONG); + +CREATE_USERIALIZATION (uint, UINT); +CREATE_USERIALIZATION (uint64, UINT64); +CREATE_USERIALIZATION (ulong, ULONG); + +/* FIXME 2.0: remove this again, plugins shouldn't have uchar properties */ +#ifndef G_MAXUCHAR +#define G_MAXUCHAR 255 +#endif +CREATE_USERIALIZATION (uchar, UCHAR); + +/********** + * double * + **********/ +static gint +gst_value_compare_double (const GValue * value1, const GValue * value2) +{ + if (value1->data[0].v_double > value2->data[0].v_double) + return GST_VALUE_GREATER_THAN; + if (value1->data[0].v_double < value2->data[0].v_double) + return GST_VALUE_LESS_THAN; + if (value1->data[0].v_double == value2->data[0].v_double) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_double (const GValue * value) +{ + gchar d[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double); + return g_strdup (d); +} + +static gboolean +gst_value_deserialize_double (GValue * dest, const gchar * s) +{ + gdouble x; + gboolean ret = FALSE; + gchar *end; + + x = g_ascii_strtod (s, &end); + if (*end == 0) { + ret = TRUE; + } else { + if (g_ascii_strcasecmp (s, "min") == 0) { + x = -G_MAXDOUBLE; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "max") == 0) { + x = G_MAXDOUBLE; + ret = TRUE; + } + } + if (ret) { + g_value_set_double (dest, x); + } + return ret; +} + +/********* + * float * + *********/ + +static gint +gst_value_compare_float (const GValue * value1, const GValue * value2) +{ + if (value1->data[0].v_float > value2->data[0].v_float) + return GST_VALUE_GREATER_THAN; + if (value1->data[0].v_float < value2->data[0].v_float) + return GST_VALUE_LESS_THAN; + if (value1->data[0].v_float == value2->data[0].v_float) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_float (const GValue * value) +{ + gchar d[G_ASCII_DTOSTR_BUF_SIZE]; + + g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float); + return g_strdup (d); +} + +static gboolean +gst_value_deserialize_float (GValue * dest, const gchar * s) +{ + gdouble x; + gboolean ret = FALSE; + gchar *end; + + x = g_ascii_strtod (s, &end); + if (*end == 0) { + ret = TRUE; + } else { + if (g_ascii_strcasecmp (s, "min") == 0) { + x = -G_MAXFLOAT; + ret = TRUE; + } else if (g_ascii_strcasecmp (s, "max") == 0) { + x = G_MAXFLOAT; + ret = TRUE; + } + } + if (x > G_MAXFLOAT || x < -G_MAXFLOAT) + ret = FALSE; + if (ret) { + g_value_set_float (dest, (float) x); + } + return ret; +} + +/********** + * string * + **********/ + +static gint +gst_value_compare_string (const GValue * value1, const GValue * value2) +{ + if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) { + /* if only one is NULL, no match - otherwise both NULL == EQUAL */ + if (value1->data[0].v_pointer != value2->data[0].v_pointer) + return GST_VALUE_UNORDERED; + } else { + gint x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer); + + if (x < 0) + return GST_VALUE_LESS_THAN; + if (x > 0) + return GST_VALUE_GREATER_THAN; + } + + return GST_VALUE_EQUAL; +} + +static gint +gst_string_measure_wrapping (const gchar * s) +{ + gint len; + gboolean wrap = FALSE; + + if (G_UNLIKELY (s == NULL)) + return -1; + + /* Special case: the actual string NULL needs wrapping */ + if (G_UNLIKELY (strcmp (s, "NULL") == 0)) + return 4; + + len = 0; + while (*s) { + if (GST_ASCII_IS_STRING (*s)) { + len++; + } else if (*s < 0x20 || *s >= 0x7f) { + wrap = TRUE; + len += 4; + } else { + wrap = TRUE; + len += 2; + } + s++; + } + + /* Wrap the string if we found something that needs + * wrapping, or the empty string (len == 0) */ + return (wrap || len == 0) ? len : -1; +} + +static gchar * +gst_string_wrap_inner (const gchar * s, gint len) +{ + gchar *d, *e; + + e = d = g_malloc (len + 3); + + *e++ = '\"'; + while (*s) { + if (GST_ASCII_IS_STRING (*s)) { + *e++ = *s++; + } else if (*s < 0x20 || *s >= 0x7f) { + *e++ = '\\'; + *e++ = '0' + ((*(guchar *) s) >> 6); + *e++ = '0' + (((*s) >> 3) & 0x7); + *e++ = '0' + ((*s++) & 0x7); + } else { + *e++ = '\\'; + *e++ = *s++; + } + } + *e++ = '\"'; + *e = 0; + + g_assert (e - d <= len + 3); + return d; +} + +/* Do string wrapping/escaping */ +static gchar * +gst_string_wrap (const gchar * s) +{ + gint len = gst_string_measure_wrapping (s); + + if (G_LIKELY (len < 0)) + return g_strdup (s); + + return gst_string_wrap_inner (s, len); +} + +/* Same as above, but take ownership of the string */ +gchar * +priv_gst_string_take_and_wrap (gchar * s) +{ + gchar *out; + gint len = gst_string_measure_wrapping (s); + + if (G_LIKELY (len < 0)) + return s; + + out = gst_string_wrap_inner (s, len); + g_free (s); + + return out; +} + +/* + * This function takes a string delimited with double quotes (") + * and unescapes any \xxx octal numbers. + * + * If sequences of \y are found where y is not in the range of + * 0->3, y is copied unescaped. + * + * If \xyy is found where x is an octal number but y is not, an + * error is encountered and %NULL is returned. + * + * the input string must be \0 terminated. + */ +static gchar * +gst_string_unwrap (const gchar * s) +{ + gchar *ret; + gchar *read, *write; + + /* NULL string returns NULL */ + if (s == NULL) + return NULL; + + /* strings not starting with " are invalid */ + if (*s != '"') + return NULL; + + /* make copy of original string to hold the result. This + * string will always be smaller than the original */ + ret = g_strdup (s); + read = ret; + write = ret; + + /* need to move to the next position as we parsed the " */ + read++; + + while (*read) { + if (GST_ASCII_IS_STRING (*read)) { + /* normal chars are just copied */ + *write++ = *read++; + } else if (*read == '"') { + /* quote marks end of string */ + break; + } else if (*read == '\\') { + /* got an escape char, move to next position to read a tripplet + * of octal numbers */ + read++; + /* is the next char a possible first octal number? */ + if (*read >= '0' && *read <= '3') { + /* parse other 2 numbers, if one of them is not in the range of + * an octal number, we error. We also catch the case where a zero + * byte is found here. */ + if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7') + goto beach; + + /* now convert the octal number to a byte again. */ + *write++ = ((read[0] - '0') << 6) + + ((read[1] - '0') << 3) + (read[2] - '0'); + + read += 3; + } else { + /* if we run into a \0 here, we definitely won't get a quote later */ + if (*read == 0) + goto beach; + + /* else copy \X sequence */ + *write++ = *read++; + } + } else { + /* weird character, error */ + goto beach; + } + } + /* if the string is not ending in " and zero terminated, we error */ + if (*read != '"' || read[1] != '\0') + goto beach; + + /* null terminate result string and return */ + *write = '\0'; + return ret; + +beach: + g_free (ret); + return NULL; +} + +static gchar * +gst_value_serialize_string (const GValue * value) +{ + return gst_string_wrap (value->data[0].v_pointer); +} + +static gboolean +gst_value_deserialize_string (GValue * dest, const gchar * s) +{ + if (G_UNLIKELY (strcmp (s, "NULL") == 0)) { + g_value_set_string (dest, NULL); + return TRUE; + } else if (G_LIKELY (*s != '"' || s[strlen (s) - 1] != '"')) { + if (!g_utf8_validate (s, -1, NULL)) + return FALSE; + g_value_set_string (dest, s); + return TRUE; + } else { + /* strings delimited with double quotes should be unwrapped */ + gchar *str = gst_string_unwrap (s); + if (G_UNLIKELY (!str)) + return FALSE; + g_value_take_string (dest, str); + } + + return TRUE; +} + +/******** + * enum * + ********/ + +static gint +gst_value_compare_enum (const GValue * value1, const GValue * value2) +{ + GEnumValue *en1, *en2; + GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1)); + GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2)); + + g_return_val_if_fail (klass1, GST_VALUE_UNORDERED); + g_return_val_if_fail (klass2, GST_VALUE_UNORDERED); + en1 = g_enum_get_value (klass1, g_value_get_enum (value1)); + en2 = g_enum_get_value (klass2, g_value_get_enum (value2)); + g_type_class_unref (klass1); + g_type_class_unref (klass2); + g_return_val_if_fail (en1, GST_VALUE_UNORDERED); + g_return_val_if_fail (en2, GST_VALUE_UNORDERED); + if (en1->value < en2->value) + return GST_VALUE_LESS_THAN; + if (en1->value > en2->value) + return GST_VALUE_GREATER_THAN; + + return GST_VALUE_EQUAL; +} + +static gchar * +gst_value_serialize_enum (const GValue * value) +{ + GEnumValue *en; + GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value)); + + g_return_val_if_fail (klass, NULL); + en = g_enum_get_value (klass, g_value_get_enum (value)); + g_type_class_unref (klass); + + /* might be one of the custom formats registered later */ + if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) { + const GstFormatDefinition *format_def; + + format_def = gst_format_get_details ((GstFormat) g_value_get_enum (value)); + g_return_val_if_fail (format_def != NULL, NULL); + return g_strdup (format_def->description); + } + + g_return_val_if_fail (en, NULL); + return g_strdup (en->value_name); +} + +static gint +gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value, + const gchar * s) +{ + const GstFormatDefinition *format_def = + g_value_get_pointer (format_def_value); + + if (g_ascii_strcasecmp (s, format_def->nick) == 0) + return 0; + + return g_ascii_strcasecmp (s, format_def->description); +} + +static gboolean +gst_value_deserialize_enum (GValue * dest, const gchar * s) +{ + GEnumValue *en; + gchar *endptr = NULL; + GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest)); + + g_return_val_if_fail (klass, FALSE); + if (!(en = g_enum_get_value_by_name (klass, s))) { + if (!(en = g_enum_get_value_by_nick (klass, s))) { + gint i = strtol (s, &endptr, 0); + + if (endptr && *endptr == '\0') { + en = g_enum_get_value (klass, i); + } + } + } + g_type_class_unref (klass); + + /* might be one of the custom formats registered later */ + if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) { + GValue res = { 0, }; + const GstFormatDefinition *format_def; + GstIterator *iter; + gboolean found; + + iter = gst_format_iterate_definitions (); + + found = gst_iterator_find_custom (iter, + (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s); + + if (found) { + format_def = g_value_get_pointer (&res); + g_return_val_if_fail (format_def != NULL, FALSE); + g_value_set_enum (dest, (gint) format_def->value); + g_value_unset (&res); + } + gst_iterator_free (iter); + return found; + } + + /* enum name/nick not found */ + if (en == NULL) + return FALSE; + + g_value_set_enum (dest, en->value); + return TRUE; +} + +/******** + * flags * + ********/ + +/* we just compare the value here */ +static gint +gst_value_compare_gflags (const GValue * value1, const GValue * value2) +{ + guint fl1, fl2; + GFlagsClass *klass1 = + (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1)); + GFlagsClass *klass2 = + (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2)); + + g_return_val_if_fail (klass1, GST_VALUE_UNORDERED); + g_return_val_if_fail (klass2, GST_VALUE_UNORDERED); + fl1 = g_value_get_flags (value1); + fl2 = g_value_get_flags (value2); + g_type_class_unref (klass1); + g_type_class_unref (klass2); + if (fl1 < fl2) + return GST_VALUE_LESS_THAN; + if (fl1 > fl2) + return GST_VALUE_GREATER_THAN; + + return GST_VALUE_EQUAL; +} + +/* the different flags are serialized separated with a + */ +static gchar * +gst_value_serialize_gflags (const GValue * value) +{ + guint flags; + GFlagsValue *fl; + GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value)); + gchar *result, *tmp; + gboolean first = TRUE; + + g_return_val_if_fail (klass, NULL); + + flags = g_value_get_flags (value); + + /* if no flags are set, try to serialize to the _NONE string */ + if (!flags) { + fl = g_flags_get_first_value (klass, flags); + if (fl) + return g_strdup (fl->value_name); + else + return g_strdup ("0"); + } + + /* some flags are set, so serialize one by one */ + result = g_strdup (""); + while (flags) { + fl = g_flags_get_first_value (klass, flags); + if (fl != NULL) { + tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL); + g_free (result); + result = tmp; + first = FALSE; + + /* clear flag */ + flags &= ~fl->value; + } + } + g_type_class_unref (klass); + + return result; +} + +static gboolean +gst_value_gflags_str_to_flags (GFlagsClass * klass, const gchar * s, + guint * out_flags, guint * out_mask) +{ + GFlagsValue *fl; + gchar delimiter; + const gchar *pos = NULL; + const gchar *next; + gchar *cur_str, *endptr; + guint flags = 0; + guint mask = 0; + guint val; + + g_return_val_if_fail (klass, FALSE); + + /* split into parts delimited with + or / and + * compose the set of flags and mask. */ + pos = s; + + if (*pos == '\0') + goto done; /* Empty string, nothing to do */ + + /* As a special case if the first char isn't a delimiter, assume + * it's a '+' - for GFlags strings, which don't start with a + * delimiter, while GFlagSet always will */ + if (*pos == '/' || *pos == '+') { + delimiter = *pos; + pos++; + } else { + delimiter = '+'; + } + + do { + /* Find the next delimiter */ + next = pos; + while (*next != '\0' && *next != '+' && *next != '/') + next++; + cur_str = g_strndup (pos, next - pos); + + if ((fl = g_flags_get_value_by_name (klass, cur_str))) + val = fl->value; + else if ((fl = g_flags_get_value_by_nick (klass, cur_str))) + val = fl->value; + else { + val = strtoul (cur_str, &endptr, 0); + /* direct numeric value */ + if (endptr == NULL || *endptr != '\0') { + g_free (cur_str); + return FALSE; /* Invalid numeric or string we can't convert */ + } + } + g_free (cur_str); + + if (val) { + mask |= val; + if (delimiter == '+') + flags |= val; + } + + /* Advance to the next delimiter */ + pos = next; + delimiter = *pos; + pos++; + } while (delimiter != '\0'); + +done: + if (out_flags) + *out_flags = flags; + if (out_mask) + *out_mask = mask; + + return TRUE; +} + + +static gboolean +gst_value_deserialize_gflags (GValue * dest, const gchar * s) +{ + GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest)); + gboolean res = FALSE; + guint flags = 0; + + if (gst_value_gflags_str_to_flags (klass, s, &flags, NULL)) { + g_value_set_flags (dest, flags); + res = TRUE; + } + + g_type_class_unref (klass); + + return res; +} + +/********* + * gtype * + *********/ + +static gint +gst_value_compare_gtype (const GValue * value1, const GValue * value2) +{ + if (value1->data[0].v_pointer == value2->data[0].v_pointer) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; +} + +static gchar * +gst_value_serialize_gtype (const GValue * value) +{ + return g_strdup (g_type_name (g_value_get_gtype (value))); +} + +static gboolean +gst_value_deserialize_gtype (GValue * dest, const gchar * s) +{ + GType t = g_type_from_name (s); + gboolean ret = TRUE; + + if (t == G_TYPE_INVALID) + ret = FALSE; + if (ret) { + g_value_set_gtype (dest, t); + } + return ret; +} + +/**************** + * subset * + ****************/ + +static gboolean +gst_value_is_subset_int_range_int_range (const GValue * value1, + const GValue * value2) +{ + gint gcd; + + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE); + + if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) < + INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) + return FALSE; + if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) > + INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2)) + return FALSE; + + if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) { + if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) % + INT_RANGE_STEP (value1)) + return FALSE; + return TRUE; + } + + gcd = + gst_util_greatest_common_divisor (INT_RANGE_STEP (value1), + INT_RANGE_STEP (value2)); + if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2))) + return FALSE; + + return TRUE; +} + +static gboolean +gst_value_is_subset_int64_range_int64_range (const GValue * value1, + const GValue * value2) +{ + gint64 gcd; + + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE); + + if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2)) + return FALSE; + if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2)) + return FALSE; + + if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) { + if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) % + INT64_RANGE_STEP (value1)) + return FALSE; + return TRUE; + } + + gcd = + gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1), + INT64_RANGE_STEP (value2)); + if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2))) + return FALSE; + + return TRUE; +} + +/* A flag set is a subset of another if the superset allows the + * flags of the subset */ +static gboolean +gst_value_is_subset_flagset_flagset (const GValue * value1, + const GValue * value2) +{ + guint f1, f2; + guint m1, m2; + + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value2), FALSE); + + f1 = value1->data[0].v_uint; + f2 = value2->data[0].v_uint; + + m1 = value1->data[1].v_uint; + m2 = value2->data[1].v_uint; + + /* Not a subset if masked bits of superset disagree */ + if ((f1 & m1) != (f2 & (m1 & m2))) + return FALSE; + + return TRUE; +} + +static gboolean +gst_value_is_subset_structure_structure (const GValue * value1, + const GValue * value2) +{ + const GstStructure *s1, *s2; + + g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value2), FALSE); + + s1 = gst_value_get_structure (value1); + s2 = gst_value_get_structure (value2); + + return gst_structure_is_subset (s1, s2); +} + +/** + * gst_value_is_subset: + * @value1: a #GValue + * @value2: a #GValue + * + * Check that @value1 is a subset of @value2. + * + * Return: %TRUE is @value1 is a subset of @value2 + */ +gboolean +gst_value_is_subset (const GValue * value1, const GValue * value2) +{ + /* special case for int/int64 ranges, since we cannot compute + the difference for those when they have different steps, + and it's actually a lot simpler to compute whether a range + is a subset of another. */ + if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) { + return gst_value_is_subset_int_range_int_range (value1, value2); + } else if (GST_VALUE_HOLDS_INT64_RANGE (value1) + && GST_VALUE_HOLDS_INT64_RANGE (value2)) { + return gst_value_is_subset_int64_range_int64_range (value1, value2); + } else if (GST_VALUE_HOLDS_FLAG_SET (value1) && + GST_VALUE_HOLDS_FLAG_SET (value2)) { + return gst_value_is_subset_flagset_flagset (value1, value2); + } else if (GST_VALUE_HOLDS_STRUCTURE (value1) + && GST_VALUE_HOLDS_STRUCTURE (value2)) { + return gst_value_is_subset_structure_structure (value1, value2); + } + + /* + * 1 - [1,2] = empty + * -> !subset + * + * [1,2] - 1 = 2 + * -> 1 - [1,2] = empty + * -> subset + * + * [1,3] - [1,2] = 3 + * -> [1,2] - [1,3] = empty + * -> subset + * + * {1,2} - {1,3} = 2 + * -> {1,3} - {1,2} = 3 + * -> !subset + * + * First caps subtraction needs to return a non-empty set, second + * subtractions needs to give en empty set. + * Both substractions are switched below, as it's faster that way. + */ + if (!gst_value_subtract (NULL, value1, value2)) { + if (gst_value_subtract (NULL, value2, value1)) { + return TRUE; + } + } + return FALSE; +} + +/********* + * union * + *********/ + +static gboolean +gst_value_union_int_int_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + gint v = src1->data[0].v_int; + + /* check if it's already in the range */ + if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v && + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v && + v % INT_RANGE_STEP (src2) == 0) { + if (dest) + gst_value_init_and_copy (dest, src2); + return TRUE; + } + + /* check if it extends the range */ + if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) { + if (dest) { + guint64 new_min = INT_RANGE_MIN (src2) - 1; + guint64 new_max = INT_RANGE_MAX (src2); + + gst_value_init_and_copy (dest, src2); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); + } + return TRUE; + } + if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) { + if (dest) { + guint64 new_min = INT_RANGE_MIN (src2); + guint64 new_max = INT_RANGE_MAX (src2) + 1; + + gst_value_init_and_copy (dest, src2); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); + } + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_union_int_range_int_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + /* We can union in several special cases: + 1 - one is a subset of another + 2 - same step and not disjoint + 3 - different step, at least one with one value which matches a 'next' or 'previous' + - anything else ? + */ + + /* 1 - subset */ + if (gst_value_is_subset_int_range_int_range (src1, src2)) { + if (dest) + gst_value_init_and_copy (dest, src2); + return TRUE; + } + if (gst_value_is_subset_int_range_int_range (src2, src1)) { + if (dest) + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + /* 2 - same step and not disjoint */ + if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) { + if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 && + INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) || + (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 && + INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) { + if (dest) { + gint step = INT_RANGE_STEP (src1); + gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2)); + gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2)); + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range_step (dest, min, max, step); + } + return TRUE; + } + } + + /* 3 - single value matches next or previous */ + if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) { + gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1; + gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1; + if (n1 == 1 || n2 == 1) { + const GValue *range_value = NULL; + gint scalar = 0; + if (n1 == 1) { + range_value = src2; + scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1); + } else if (n2 == 1) { + range_value = src1; + scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2); + } + + if (scalar == + (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) { + if (dest) { + guint64 new_min = (guint) + ((INT_RANGE_MIN (range_value) - + 1) * INT_RANGE_STEP (range_value)); + guint64 new_max = (guint) + (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value)); + + gst_value_init_and_copy (dest, range_value); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); + } + return TRUE; + } else if (scalar == + (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) { + if (dest) { + guint64 new_min = (guint) + (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value)); + guint64 new_max = (guint) + ((INT_RANGE_MAX (range_value) + + 1) * INT_RANGE_STEP (range_value)); + gst_value_init_and_copy (dest, range_value); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); + } + return TRUE; + } + } + } + + /* If we get there, we did not find a way to make a union that can be + represented with our simplistic model. */ + return FALSE; +} + +static gboolean +gst_value_union_flagset_flagset (GValue * dest, const GValue * src1, + const GValue * src2) +{ + /* We can union 2 flag sets where they do not disagree on + * required (masked) flag bits */ + guint64 f1, f2; + guint64 m1, m2; + + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE); + + f1 = src1->data[0].v_uint; + f2 = src2->data[0].v_uint; + + m1 = src1->data[1].v_uint; + m2 = src2->data[1].v_uint; + + /* Can't union if masked bits disagree */ + if ((f1 & (m1 & m2)) != (f2 & (m1 & m2))) + return FALSE; + + if (dest) { + g_value_init (dest, GST_TYPE_FLAG_SET); + /* Copy masked bits from src2 to src1 */ + f1 &= ~m2; + f1 |= (f2 & m2); + m1 |= m2; + gst_value_set_flagset (dest, f1, m1); + } + + return TRUE; +} + +/* iterating over the result taking the union with the other structure's value */ +static gboolean +structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data) +{ + GstStructure *other = user_data; + const GValue *other_value; + GValue res_value = G_VALUE_INIT; + + other_value = gst_structure_id_get_value (other, field_id); + /* no value in the other struct, just keep this value */ + if (!other_value) + return TRUE; + + if (!gst_value_union (&res_value, val, other_value)) + return FALSE; + + g_value_unset (val); + gst_value_move (val, &res_value); + return TRUE; +} + +/* iterating over the other source structure adding missing values */ +static gboolean +structure_field_union_from (GQuark field_id, const GValue * other_val, + gpointer user_data) +{ + GstStructure *result = user_data; + const GValue *result_value; + + result_value = gst_structure_id_get_value (result, field_id); + if (!result_value) + gst_structure_id_set_value (result, field_id, other_val); + + return TRUE; +} + +static gboolean +gst_value_union_structure_structure (GValue * dest, const GValue * src1, + const GValue * src2) +{ + const GstStructure *s1, *s2; + GstStructure *result; + gboolean ret; + + g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src2), FALSE); + + s1 = gst_value_get_structure (src1); + s2 = gst_value_get_structure (src2); + + /* Can't join two structures with different names into a single structure */ + if (!gst_structure_has_name (s1, gst_structure_get_name (s2))) { + gst_value_list_concat (dest, src1, src2); + return TRUE; + } + + result = gst_structure_copy (s1); + ret = + gst_structure_map_in_place (result, structure_field_union_into, + (gpointer) s2); + if (!ret) + goto out; + ret = + gst_structure_foreach (s2, structure_field_union_from, (gpointer) result); + + if (ret) { + g_value_init (dest, GST_TYPE_STRUCTURE); + gst_value_set_structure (dest, result); + } + +out: + gst_structure_free (result); + return ret; +} + +/**************** + * intersection * + ****************/ + +static gboolean +gst_value_intersect_int_int_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int && + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int && + src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) { + if (dest) + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + gint min; + gint max; + gint step; + + step = + INT_RANGE_STEP (src1) / + gst_util_greatest_common_divisor (INT_RANGE_STEP (src1), + INT_RANGE_STEP (src2)); + if (G_MAXINT32 / INT_RANGE_STEP (src2) < step) + return FALSE; + step *= INT_RANGE_STEP (src2); + + min = + MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1), + INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2)); + min = (min + step - 1) / step * step; + max = + MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1), + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2)); + max = max / step * step; + + if (min < max) { + if (dest) { + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range_step (dest, min, max, step); + } + return TRUE; + } + if (min == max) { + if (dest) { + g_value_init (dest, G_TYPE_INT); + g_value_set_int (dest, min); + } + return TRUE; + } + + return FALSE; +} + +#define INT64_RANGE_MIN_VAL(v) (INT64_RANGE_MIN (v) * INT64_RANGE_STEP (v)) +#define INT64_RANGE_MAX_VAL(v) (INT64_RANGE_MAX (v) * INT64_RANGE_STEP (v)) + +static gboolean +gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + if (INT64_RANGE_MIN_VAL (src2) <= src1->data[0].v_int64 && + INT64_RANGE_MAX_VAL (src2) >= src1->data[0].v_int64 && + src1->data[0].v_int64 % INT64_RANGE_STEP (src2) == 0) { + if (dest) + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + gint64 min; + gint64 max; + gint64 step; + + step = + INT64_RANGE_STEP (src1) / + gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1), + INT64_RANGE_STEP (src2)); + if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step) + return FALSE; + step *= INT64_RANGE_STEP (src2); + + min = + MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1), + INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2)); + min = (min + step - 1) / step * step; + max = + MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1), + INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2)); + max = max / step * step; + + if (min < max) { + if (dest) { + g_value_init (dest, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range_step (dest, min, max, step); + } + return TRUE; + } + if (min == max) { + if (dest) { + g_value_init (dest, G_TYPE_INT64); + g_value_set_int64 (dest, min); + } + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_double_double_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + if (src2->data[0].v_double <= src1->data[0].v_double && + src2->data[1].v_double >= src1->data[0].v_double) { + if (dest) + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_double_range_double_range (GValue * dest, + const GValue * src1, const GValue * src2) +{ + gdouble min; + gdouble max; + + min = MAX (src1->data[0].v_double, src2->data[0].v_double); + max = MIN (src1->data[1].v_double, src2->data[1].v_double); + + if (min < max) { + if (dest) { + g_value_init (dest, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (dest, min, max); + } + return TRUE; + } + if (min == max) { + if (dest) { + g_value_init (dest, G_TYPE_DOUBLE); + g_value_set_int (dest, (int) min); + } + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_list (GValue * dest, const GValue * value1, + const GValue * value2) +{ + guint i, size; + GValue intersection = { 0, }; + gboolean ret = FALSE; + + size = VALUE_LIST_SIZE (value1); + for (i = 0; i < size; i++) { + const GValue *cur = VALUE_LIST_GET_VALUE (value1, i); + + /* quicker version when we don't need the resulting set */ + if (!dest) { + if (gst_value_intersect (NULL, cur, value2)) { + ret = TRUE; + break; + } + continue; + } + + if (gst_value_intersect (&intersection, cur, value2)) { + /* append value */ + if (!ret) { + gst_value_move (dest, &intersection); + ret = TRUE; + } else if (GST_VALUE_HOLDS_LIST (dest)) { + _gst_value_list_append_and_take_value (dest, &intersection); + } else { + GValue temp; + + gst_value_move (&temp, dest); + gst_value_list_merge (dest, &temp, &intersection); + g_value_unset (&temp); + g_value_unset (&intersection); + } + } + } + + return ret; +} + +static gboolean +gst_value_intersect_array (GValue * dest, const GValue * src1, + const GValue * src2) +{ + guint size; + guint n; + GValue val = { 0 }; + + /* only works on similar-sized arrays */ + size = gst_value_array_get_size (src1); + if (size != gst_value_array_get_size (src2)) + return FALSE; + + /* quicker value when we don't need the resulting set */ + if (!dest) { + for (n = 0; n < size; n++) { + if (!gst_value_intersect (NULL, gst_value_array_get_value (src1, n), + gst_value_array_get_value (src2, n))) { + return FALSE; + } + } + return TRUE; + } + + g_value_init (dest, GST_TYPE_ARRAY); + + for (n = 0; n < size; n++) { + if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n), + gst_value_array_get_value (src2, n))) { + g_value_unset (dest); + return FALSE; + } + _gst_value_array_append_and_take_value (dest, &val); + } + + return TRUE; +} + +static gboolean +gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + gint res1, res2; + GValue *vals; + GstValueCompareFunc compare; + + vals = src2->data[0].v_pointer; + + if (vals == NULL) + return FALSE; + + if ((compare = gst_value_get_compare_func (src1))) { + res1 = gst_value_compare_with_func (&vals[0], src1, compare); + res2 = gst_value_compare_with_func (&vals[1], src1, compare); + + if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) && + (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) { + if (dest) + gst_value_init_and_copy (dest, src1); + return TRUE; + } + } + + return FALSE; +} + +static gboolean +gst_value_intersect_fraction_range_fraction_range (GValue * dest, + const GValue * src1, const GValue * src2) +{ + GValue *min; + GValue *max; + gint res; + GValue *vals1, *vals2; + GstValueCompareFunc compare; + + vals1 = src1->data[0].v_pointer; + vals2 = src2->data[0].v_pointer; + g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE); + + if ((compare = gst_value_get_compare_func (&vals1[0]))) { + /* min = MAX (src1.start, src2.start) */ + res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_LESS_THAN) + min = &vals2[0]; /* Take the max of the 2 */ + else + min = &vals1[0]; + + /* max = MIN (src1.end, src2.end) */ + res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_GREATER_THAN) + max = &vals2[1]; /* Take the min of the 2 */ + else + max = &vals1[1]; + + res = gst_value_compare_with_func (min, max, compare); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_LESS_THAN) { + if (dest) { + g_value_init (dest, GST_TYPE_FRACTION_RANGE); + vals1 = dest->data[0].v_pointer; + g_value_copy (min, &vals1[0]); + g_value_copy (max, &vals1[1]); + } + return TRUE; + } + if (res == GST_VALUE_EQUAL) { + if (dest) + gst_value_init_and_copy (dest, min); + return TRUE; + } + } + + return FALSE; +} + +/* Two flagsets intersect if the masked bits in both + * flagsets are exactly equal */ +static gboolean +gst_value_intersect_flagset_flagset (GValue * dest, + const GValue * src1, const GValue * src2) +{ + guint f1, f2; + guint m1, m2; + GType type1, type2, flagset_type; + + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE); + + f1 = src1->data[0].v_uint; + f2 = src2->data[0].v_uint; + + m1 = src1->data[1].v_uint; + m2 = src2->data[1].v_uint; + + /* Don't intersect if masked bits disagree */ + if ((f1 & (m1 & m2)) != (f2 & (m1 & m2))) + return FALSE; + + /* Allow intersection with the generic FlagSet type, on one + * side, but not 2 different subtypes - that makes no sense */ + type1 = G_VALUE_TYPE (src1); + type2 = G_VALUE_TYPE (src2); + flagset_type = GST_TYPE_FLAG_SET; + + if (type1 != type2 && type1 != flagset_type && type2 != flagset_type) + return FALSE; + + if (dest) { + GType dest_type; + + /* Prefer an output type that matches a sub-type, + * rather than the generic type */ + if (type1 != flagset_type) + dest_type = type1; + else + dest_type = type2; + + g_value_init (dest, dest_type); + + /* The compatible set is all the bits from src1 that it + * cares about and all the bits from src2 that it cares + * about. */ + dest->data[0].v_uint = (f1 & m1) | (f2 & m2); + dest->data[1].v_uint = m1 | m2; + } + + return TRUE; +} + +static gboolean +gst_value_intersect_structure_structure (GValue * dest, + const GValue * src1, const GValue * src2) +{ + const GstStructure *s1, *s2; + GstStructure *d1; + + s1 = gst_value_get_structure (src1); + s2 = gst_value_get_structure (src2); + + d1 = gst_structure_intersect (s1, s2); + if (!d1) + return FALSE; + + if (dest) { + g_value_init (dest, GST_TYPE_STRUCTURE); + gst_value_set_structure (dest, d1); + } + + gst_structure_free (d1); + return TRUE; +} + +/*************** + * subtraction * + ***************/ + +static gboolean +gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint min = gst_value_get_int_range_min (subtrahend); + gint max = gst_value_get_int_range_max (subtrahend); + gint step = gst_value_get_int_range_step (subtrahend); + gint val = g_value_get_int (minuend); + + if (step == 0) + return FALSE; + + /* subtracting a range from an int only works if the int is not in the + * range */ + if (val < min || val > max || val % step) { + /* and the result is the int */ + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + return FALSE; +} + +/* creates a new int range based on input values. + */ +static gboolean +gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2, + gint max2, gint step) +{ + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + + g_return_val_if_fail (step > 0, FALSE); + g_return_val_if_fail (min1 % step == 0, FALSE); + g_return_val_if_fail (max1 % step == 0, FALSE); + g_return_val_if_fail (min2 % step == 0, FALSE); + g_return_val_if_fail (max2 % step == 0, FALSE); + + if (min1 <= max1 && min2 <= max2) { + pv1 = &v1; + pv2 = &v2; + } else if (min1 <= max1) { + pv1 = dest; + pv2 = NULL; + } else if (min2 <= max2) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (!dest) + return TRUE; + + if (min1 < max1) { + g_value_init (pv1, GST_TYPE_INT_RANGE); + gst_value_set_int_range_step (pv1, min1, max1, step); + } else if (min1 == max1) { + g_value_init (pv1, G_TYPE_INT); + g_value_set_int (pv1, min1); + } + if (min2 < max2) { + g_value_init (pv2, GST_TYPE_INT_RANGE); + gst_value_set_int_range_step (pv2, min2, max2, step); + } else if (min2 == max2) { + g_value_init (pv2, G_TYPE_INT); + g_value_set_int (pv2, min2); + } + + if (min1 <= max1 && min2 <= max2) { + gst_value_list_concat_and_take_values (dest, pv1, pv2); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint min = gst_value_get_int_range_min (minuend); + gint max = gst_value_get_int_range_max (minuend); + gint step = gst_value_get_int_range_step (minuend); + gint val = g_value_get_int (subtrahend); + + g_return_val_if_fail (min < max, FALSE); + + if (step == 0) + return FALSE; + + /* value is outside of the range, return range unchanged */ + if (val < min || val > max || val % step) { + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } else { + /* max must be MAXINT too as val <= max */ + if (val >= G_MAXINT - step + 1) { + max -= step; + val -= step; + } + /* min must be MININT too as val >= max */ + if (val <= G_MININT + step - 1) { + min += step; + val += step; + } + if (dest) + gst_value_create_new_range (dest, min, val - step, val + step, max, step); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint min1 = gst_value_get_int_range_min (minuend); + gint max1 = gst_value_get_int_range_max (minuend); + gint step1 = gst_value_get_int_range_step (minuend); + gint min2 = gst_value_get_int_range_min (subtrahend); + gint max2 = gst_value_get_int_range_max (subtrahend); + gint step2 = gst_value_get_int_range_step (subtrahend); + gint step; + + if (step1 != step2) { + /* ENOIMPL */ + g_assert (FALSE); + return FALSE; + } + step = step1; + + if (step == 0) + return FALSE; + + if (max2 >= max1 && min2 <= min1) { + return FALSE; + } else if (max2 >= max1) { + return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1), + step, 0, step); + } else if (min2 <= min1) { + return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1, + step, 0, step); + } else { + return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1), + MAX (max2 + step, min1), max1, step); + } +} + +static gboolean +gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint64 min = gst_value_get_int64_range_min (subtrahend); + gint64 max = gst_value_get_int64_range_max (subtrahend); + gint64 step = gst_value_get_int64_range_step (subtrahend); + gint64 val = g_value_get_int64 (minuend); + + if (step == 0) + return FALSE; + /* subtracting a range from an int64 only works if the int64 is not in the + * range */ + if (val < min || val > max || val % step) { + /* and the result is the int64 */ + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + return FALSE; +} + +/* creates a new int64 range based on input values. + */ +static gboolean +gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1, + gint64 min2, gint64 max2, gint64 step) +{ + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + + g_return_val_if_fail (step > 0, FALSE); + g_return_val_if_fail (min1 % step == 0, FALSE); + g_return_val_if_fail (max1 % step == 0, FALSE); + g_return_val_if_fail (min2 % step == 0, FALSE); + g_return_val_if_fail (max2 % step == 0, FALSE); + + if (min1 <= max1 && min2 <= max2) { + pv1 = &v1; + pv2 = &v2; + } else if (min1 <= max1) { + pv1 = dest; + pv2 = NULL; + } else if (min2 <= max2) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (!dest) + return TRUE; + + if (min1 < max1) { + g_value_init (pv1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range_step (pv1, min1, max1, step); + } else if (min1 == max1) { + g_value_init (pv1, G_TYPE_INT64); + g_value_set_int64 (pv1, min1); + } + if (min2 < max2) { + g_value_init (pv2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range_step (pv2, min2, max2, step); + } else if (min2 == max2) { + g_value_init (pv2, G_TYPE_INT64); + g_value_set_int64 (pv2, min2); + } + + if (min1 <= max1 && min2 <= max2) { + gst_value_list_concat_and_take_values (dest, pv1, pv2); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint64 min = gst_value_get_int64_range_min (minuend); + gint64 max = gst_value_get_int64_range_max (minuend); + gint64 step = gst_value_get_int64_range_step (minuend); + gint64 val = g_value_get_int64 (subtrahend); + + g_return_val_if_fail (min < max, FALSE); + + if (step == 0) + return FALSE; + + /* value is outside of the range, return range unchanged */ + if (val < min || val > max || val % step) { + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } else { + /* max must be MAXINT64 too as val <= max */ + if (val >= G_MAXINT64 - step + 1) { + max -= step; + val -= step; + } + /* min must be MININT64 too as val >= max */ + if (val <= G_MININT64 + step - 1) { + min += step; + val += step; + } + if (dest) + gst_value_create_new_int64_range (dest, min, val - step, val + step, max, + step); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int64_range_int64_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + gint64 min1 = gst_value_get_int64_range_min (minuend); + gint64 max1 = gst_value_get_int64_range_max (minuend); + gint64 step1 = gst_value_get_int64_range_step (minuend); + gint64 min2 = gst_value_get_int64_range_min (subtrahend); + gint64 max2 = gst_value_get_int64_range_max (subtrahend); + gint64 step2 = gst_value_get_int64_range_step (subtrahend); + gint64 step; + + if (step1 != step2) { + /* ENOIMPL */ + g_assert (FALSE); + return FALSE; + } + + if (step1 == 0) + return FALSE; + + step = step1; + + if (max2 >= max1 && min2 <= min1) { + return FALSE; + } else if (max2 >= max1) { + return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step, + max1), step, 0, step); + } else if (min2 <= min1) { + return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1), + max1, step, 0, step); + } else { + return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step, + max1), MAX (max2 + step, min1), max1, step); + } +} + +static gboolean +gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gdouble min = gst_value_get_double_range_min (subtrahend); + gdouble max = gst_value_get_double_range_max (subtrahend); + gdouble val = g_value_get_double (minuend); + + if (val < min || val > max) { + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + return FALSE; +} + +static gboolean +gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + /* since we don't have open ranges, we cannot create a hole in + * a double range. We return the original range */ + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; +} + +static gboolean +gst_value_subtract_double_range_double_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + /* since we don't have open ranges, we have to approximate */ + /* done like with ints */ + gdouble min1 = gst_value_get_double_range_min (minuend); + gdouble max2 = gst_value_get_double_range_max (minuend); + gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2); + gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1); + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + + if (min1 < max1 && min2 < max2) { + pv1 = &v1; + pv2 = &v2; + } else if (min1 < max1) { + pv1 = dest; + pv2 = NULL; + } else if (min2 < max2) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (!dest) + return TRUE; + + if (min1 < max1) { + g_value_init (pv1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (pv1, min1, max1); + } + if (min2 < max2) { + g_value_init (pv2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (pv2, min2, max2); + } + + if (min1 < max1 && min2 < max2) { + gst_value_list_concat_and_take_values (dest, pv1, pv2); + } + return TRUE; +} + +static gboolean +gst_value_subtract_from_list (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + guint i, size; + GValue subtraction = { 0, }; + gboolean ret = FALSE; + + size = VALUE_LIST_SIZE (minuend); + for (i = 0; i < size; i++) { + const GValue *cur = VALUE_LIST_GET_VALUE (minuend, i); + + /* quicker version when we can discard the result */ + if (!dest) { + if (gst_value_subtract (NULL, cur, subtrahend)) { + ret = TRUE; + break; + } + continue; + } + + if (gst_value_subtract (&subtraction, cur, subtrahend)) { + if (!ret) { + gst_value_move (dest, &subtraction); + ret = TRUE; + } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST + && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) { + _gst_value_list_append_and_take_value (dest, &subtraction); + } else { + GValue temp; + + gst_value_move (&temp, dest); + gst_value_list_concat_and_take_values (dest, &temp, &subtraction); + } + } + } + return ret; +} + +static gboolean +gst_value_subtract_list (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + guint i, size; + GValue data[2] = { {0,}, {0,} }; + GValue *subtraction = &data[0], *result = &data[1]; + + gst_value_init_and_copy (result, minuend); + size = VALUE_LIST_SIZE (subtrahend); + for (i = 0; i < size; i++) { + const GValue *cur = VALUE_LIST_GET_VALUE (subtrahend, i); + + if (gst_value_subtract (subtraction, result, cur)) { + GValue *temp = result; + + result = subtraction; + subtraction = temp; + g_value_unset (subtraction); + } else { + g_value_unset (result); + return FALSE; + } + } + if (dest) { + gst_value_move (dest, result); + } else { + g_value_unset (result); + } + return TRUE; +} + +static gboolean +gst_value_subtract_fraction_fraction_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + const GValue *min = gst_value_get_fraction_range_min (subtrahend); + const GValue *max = gst_value_get_fraction_range_max (subtrahend); + GstValueCompareFunc compare; + + if ((compare = gst_value_get_compare_func (minuend))) { + /* subtracting a range from an fraction only works if the fraction + * is not in the range */ + if (gst_value_compare_with_func (minuend, min, compare) == + GST_VALUE_LESS_THAN || + gst_value_compare_with_func (minuend, max, compare) == + GST_VALUE_GREATER_THAN) { + /* and the result is the value */ + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + } + return FALSE; +} + +static gboolean +gst_value_subtract_fraction_range_fraction (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + /* since we don't have open ranges, we cannot create a hole in + * a range. We return the original range */ + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; +} + +static gboolean +gst_value_subtract_fraction_range_fraction_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + /* since we don't have open ranges, we have to approximate */ + /* done like with ints and doubles. Creates a list of 2 fraction ranges */ + const GValue *min1 = gst_value_get_fraction_range_min (minuend); + const GValue *max2 = gst_value_get_fraction_range_max (minuend); + const GValue *max1 = gst_value_get_fraction_range_min (subtrahend); + const GValue *min2 = gst_value_get_fraction_range_max (subtrahend); + gint cmp1, cmp2; + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + GstValueCompareFunc compare; + + g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE); + g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE); + + compare = gst_value_get_compare_func (min1); + g_return_val_if_fail (compare, FALSE); + + cmp1 = gst_value_compare_with_func (max2, max1, compare); + g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); + if (cmp1 == GST_VALUE_LESS_THAN) + max1 = max2; + cmp1 = gst_value_compare_with_func (min1, min2, compare); + g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); + if (cmp1 == GST_VALUE_GREATER_THAN) + min2 = min1; + + cmp1 = gst_value_compare_with_func (min1, max1, compare); + cmp2 = gst_value_compare_with_func (min2, max2, compare); + + if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { + pv1 = &v1; + pv2 = &v2; + } else if (cmp1 == GST_VALUE_LESS_THAN) { + pv1 = dest; + pv2 = NULL; + } else if (cmp2 == GST_VALUE_LESS_THAN) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (!dest) + return TRUE; + + if (cmp1 == GST_VALUE_LESS_THAN) { + g_value_init (pv1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range (pv1, min1, max1); + } + if (cmp2 == GST_VALUE_LESS_THAN) { + g_value_init (pv2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range (pv2, min2, max2); + } + + if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { + gst_value_list_concat_and_take_values (dest, pv1, pv2); + } + return TRUE; +} + +/************** + * comparison * + **************/ + +/* + * gst_value_get_compare_func: + * @value1: a value to get the compare function for + * + * Determines the compare function to be used with values of the same type as + * @value1. The function can be given to gst_value_compare_with_func(). + * + * Returns: A #GstValueCompareFunc value + */ +static GstValueCompareFunc +gst_value_get_compare_func (const GValue * value1) +{ + GstValueTable *table, *best = NULL; + guint i; + GType type1; + + type1 = G_VALUE_TYPE (value1); + + /* this is a fast check */ + best = gst_value_hash_lookup_type (type1); + + /* slower checks */ + if (G_UNLIKELY (!best || !best->compare)) { + guint len = gst_value_table->len; + + best = NULL; + for (i = 0; i < len; i++) { + table = &g_array_index (gst_value_table, GstValueTable, i); + if (table->compare && g_type_is_a (type1, table->type)) { + if (!best || g_type_is_a (table->type, best->type)) + best = table; + } + } + } + if (G_LIKELY (best)) + return best->compare; + + return NULL; +} + +static inline gboolean +gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2) +{ + if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) + return FALSE; + + return gst_value_get_compare_func (value1) != NULL; +} + +/** + * gst_value_can_compare: + * @value1: a value to compare + * @value2: another value to compare + * + * Determines if @value1 and @value2 can be compared. + * + * Returns: %TRUE if the values can be compared + */ +gboolean +gst_value_can_compare (const GValue * value1, const GValue * value2) +{ + g_return_val_if_fail (G_IS_VALUE (value1), FALSE); + g_return_val_if_fail (G_IS_VALUE (value2), FALSE); + + return gst_value_can_compare_unchecked (value1, value2); +} + +static gboolean +gst_value_list_equals_range (const GValue * list, const GValue * value) +{ + const GValue *first; + guint list_size, n; + + g_assert (G_IS_VALUE (list)); + g_assert (G_IS_VALUE (value)); + g_assert (GST_VALUE_HOLDS_LIST (list)); + + /* TODO: compare against an empty list ? No type though... */ + list_size = VALUE_LIST_SIZE (list); + if (list_size == 0) + return FALSE; + + /* compare the basic types - they have to match */ + first = VALUE_LIST_GET_VALUE (list, 0); +#define CHECK_TYPES(type,prefix) \ + (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value)) + if (CHECK_TYPES (INT, G)) { + const gint rmin = gst_value_get_int_range_min (value); + const gint rmax = gst_value_get_int_range_max (value); + const gint rstep = gst_value_get_int_range_step (value); + if (rstep == 0) + return FALSE; + /* note: this will overflow for min 0 and max INT_MAX, but this + would only be equal to a list of INT_MAX elements, which seems + very unlikely */ + if (list_size != rmax / rstep - rmin / rstep + 1) + return FALSE; + for (n = 0; n < list_size; ++n) { + gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n)); + if (v < rmin || v > rmax || v % rstep) { + return FALSE; + } + } + return TRUE; + } else if (CHECK_TYPES (INT64, G)) { + const gint64 rmin = gst_value_get_int64_range_min (value); + const gint64 rmax = gst_value_get_int64_range_max (value); + const gint64 rstep = gst_value_get_int64_range_step (value); + GST_DEBUG ("List/range of int64s"); + if (rstep == 0) + return FALSE; + if (list_size != rmax / rstep - rmin / rstep + 1) + return FALSE; + for (n = 0; n < list_size; ++n) { + gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n)); + if (v < rmin || v > rmax || v % rstep) + return FALSE; + } + return TRUE; + } +#undef CHECK_TYPES + + /* other combinations don't make sense for equality */ + return FALSE; +} + +/* "Pure" variant of gst_value_compare which is guaranteed to + * not have list arguments and therefore does basic comparisions + */ +static inline gint +_gst_value_compare_nolist (const GValue * value1, const GValue * value2) +{ + GstValueCompareFunc compare; + + if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) + return GST_VALUE_UNORDERED; + + compare = gst_value_get_compare_func (value1); + if (compare) { + return compare (value1, value2); + } + + g_critical ("unable to compare values of type %s\n", + g_type_name (G_VALUE_TYPE (value1))); + return GST_VALUE_UNORDERED; +} + +/** + * gst_value_compare: + * @value1: a value to compare + * @value2: another value to compare + * + * Compares @value1 and @value2. If @value1 and @value2 cannot be + * compared, the function returns GST_VALUE_UNORDERED. Otherwise, + * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned. + * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned. + * If the values are equal, GST_VALUE_EQUAL is returned. + * + * Returns: comparison result + */ +gint +gst_value_compare (const GValue * value1, const GValue * value2) +{ + gboolean value1_is_list; + gboolean value2_is_list; + + g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN); + g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN); + + value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST; + value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST; + + /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal), + as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */ + if (value1_is_list && !value2_is_list) { + gint i, n, ret; + + if (gst_value_list_equals_range (value1, value2)) { + return GST_VALUE_EQUAL; + } + + n = gst_value_list_get_size (value1); + if (n == 0) + return GST_VALUE_UNORDERED; + + for (i = 0; i < n; i++) { + const GValue *elt; + + elt = gst_value_list_get_value (value1, i); + ret = gst_value_compare (elt, value2); + if (ret != GST_VALUE_EQUAL && n == 1) + return ret; + else if (ret != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; + } + + return GST_VALUE_EQUAL; + } else if (value2_is_list && !value1_is_list) { + gint i, n, ret; + + if (gst_value_list_equals_range (value2, value1)) { + return GST_VALUE_EQUAL; + } + + n = gst_value_list_get_size (value2); + if (n == 0) + return GST_VALUE_UNORDERED; + + for (i = 0; i < n; i++) { + const GValue *elt; + + elt = gst_value_list_get_value (value2, i); + ret = gst_value_compare (elt, value1); + if (ret != GST_VALUE_EQUAL && n == 1) + return ret; + else if (ret != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; + } + + return GST_VALUE_EQUAL; + } + + /* And now handle the generic case */ + return _gst_value_compare_nolist (value1, value2); +} + +/* + * gst_value_compare_with_func: + * @value1: a value to compare + * @value2: another value to compare + * @compare: compare function + * + * Compares @value1 and @value2 using the @compare function. Works like + * gst_value_compare() but allows to save time determining the compare function + * a multiple times. + * + * Returns: comparison result + */ +static gint +gst_value_compare_with_func (const GValue * value1, const GValue * value2, + GstValueCompareFunc compare) +{ + g_assert (compare); + + if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) + return GST_VALUE_UNORDERED; + + return compare (value1, value2); +} + +/* union */ + +/** + * gst_value_can_union: + * @value1: a value to union + * @value2: another value to union + * + * Determines if @value1 and @value2 can be non-trivially unioned. + * Any two values can be trivially unioned by adding both of them + * to a GstValueList. However, certain types have the possibility + * to be unioned in a simpler way. For example, an integer range + * and an integer can be unioned if the integer is a subset of the + * integer range. If there is the possibility that two values can + * be unioned, this function returns %TRUE. + * + * Returns: %TRUE if there is a function allowing the two values to + * be unioned. + */ +gboolean +gst_value_can_union (const GValue * value1, const GValue * value2) +{ + GstValueUnionInfo *union_info; + guint i, len; + + g_return_val_if_fail (G_IS_VALUE (value1), FALSE); + g_return_val_if_fail (G_IS_VALUE (value2), FALSE); + + len = gst_value_union_funcs->len; + + for (i = 0; i < len; i++) { + union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); + if (union_info->type1 == G_VALUE_TYPE (value1) && + union_info->type2 == G_VALUE_TYPE (value2)) + return TRUE; + if (union_info->type1 == G_VALUE_TYPE (value2) && + union_info->type2 == G_VALUE_TYPE (value1)) + return TRUE; + } + + return FALSE; +} + +/** + * gst_value_union: + * @dest: (out caller-allocates): the destination value + * @value1: a value to union + * @value2: another value to union + * + * Creates a GValue corresponding to the union of @value1 and @value2. + * + * Returns: %TRUE if the union succeeded. + */ +gboolean +gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) +{ + const GstValueUnionInfo *union_info; + guint i, len; + GType type1, type2; + + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (G_IS_VALUE (value1), FALSE); + g_return_val_if_fail (G_IS_VALUE (value2), FALSE); + g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2), + FALSE); + + len = gst_value_union_funcs->len; + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); + + for (i = 0; i < len; i++) { + union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); + if (union_info->type1 == type1 && union_info->type2 == type2) { + return union_info->func (dest, value1, value2); + } + if (union_info->type1 == type2 && union_info->type2 == type1) { + return union_info->func (dest, value2, value1); + } + } + + gst_value_list_concat (dest, value1, value2); + return TRUE; +} + +/* gst_value_register_union_func: (skip) + * @type1: a type to union + * @type2: another type to union + * @func: a function that implements creating a union between the two types + * + * Registers a union function that can create a union between #GValue items + * of the type @type1 and @type2. + * + * Union functions should be registered at startup before any pipelines are + * started, as gst_value_register_union_func() is not thread-safe and cannot + * be used at the same time as gst_value_union() or gst_value_can_union(). + */ +static void +gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func) +{ + GstValueUnionInfo union_info; + + union_info.type1 = type1; + union_info.type2 = type2; + union_info.func = func; + + g_array_append_val (gst_value_union_funcs, union_info); +} + +/* intersection */ + +/** + * gst_value_can_intersect: + * @value1: a value to intersect + * @value2: another value to intersect + * + * Determines if intersecting two values will produce a valid result. + * Two values will produce a valid intersection if they have the same + * type. + * + * Returns: %TRUE if the values can intersect + */ +gboolean +gst_value_can_intersect (const GValue * value1, const GValue * value2) +{ + GstValueIntersectInfo *intersect_info; + guint i, len; + GType type1, type2; + + g_return_val_if_fail (G_IS_VALUE (value1), FALSE); + g_return_val_if_fail (G_IS_VALUE (value2), FALSE); + + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); + + /* practically all GstValue types have a compare function (_can_compare=TRUE) + * GstStructure and GstCaps have not, but are intersectable */ + if (type1 == type2) + return TRUE; + + /* special cases */ + if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST) + return TRUE; + + if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) && + GST_VALUE_HOLDS_FLAG_SET (value2))) { + GType type1, type2, flagset_type; + + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); + flagset_type = GST_TYPE_FLAG_SET; + + /* Allow intersection with the generic FlagSet type, on one + * side, but not 2 different subtypes - that makes no sense */ + if (type1 == type2 || type1 == flagset_type || type2 == flagset_type) + return TRUE; + } + + /* check registered intersect functions */ + len = gst_value_intersect_funcs->len; + for (i = 0; i < len; i++) { + intersect_info = &g_array_index (gst_value_intersect_funcs, + GstValueIntersectInfo, i); + if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) || + (intersect_info->type1 == type2 && intersect_info->type2 == type1)) + return TRUE; + } + + return gst_value_can_compare_unchecked (value1, value2); +} + +/** + * gst_value_intersect: + * @dest: (out caller-allocates) (transfer full) (allow-none): + * a uninitialized #GValue that will hold the calculated + * intersection value. May be %NULL if the resulting set if not + * needed. + * @value1: a value to intersect + * @value2: another value to intersect + * + * Calculates the intersection of two values. If the values have + * a non-empty intersection, the value representing the intersection + * is placed in @dest, unless %NULL. If the intersection is non-empty, + * @dest is not modified. + * + * Returns: %TRUE if the intersection is non-empty + */ +gboolean +gst_value_intersect (GValue * dest, const GValue * value1, + const GValue * value2) +{ + GstValueIntersectInfo *intersect_info; + guint i, len; + GType type1, type2; + + g_return_val_if_fail (G_IS_VALUE (value1), FALSE); + g_return_val_if_fail (G_IS_VALUE (value2), FALSE); + + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); + + /* special cases first */ + if (type1 == GST_TYPE_LIST) + return gst_value_intersect_list (dest, value1, value2); + if (type2 == GST_TYPE_LIST) + return gst_value_intersect_list (dest, value2, value1); + + if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) { + if (dest) + gst_value_init_and_copy (dest, value1); + return TRUE; + } + + len = gst_value_intersect_funcs->len; + for (i = 0; i < len; i++) { + intersect_info = &g_array_index (gst_value_intersect_funcs, + GstValueIntersectInfo, i); + if (intersect_info->type1 == type1 && intersect_info->type2 == type2) { + return intersect_info->func (dest, value1, value2); + } + if (intersect_info->type1 == type2 && intersect_info->type2 == type1) { + return intersect_info->func (dest, value2, value1); + } + } + + /* Failed to find a direct intersection, check if these are + * GstFlagSet sub-types. */ + if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) && + GST_VALUE_HOLDS_FLAG_SET (value2))) { + return gst_value_intersect_flagset_flagset (dest, value1, value2); + } + + return FALSE; +} + + + +/* gst_value_register_intersect_func: (skip) + * @type1: the first type to intersect + * @type2: the second type to intersect + * @func: the intersection function + * + * Registers a function that is called to calculate the intersection + * of the values having the types @type1 and @type2. + * + * Intersect functions should be registered at startup before any pipelines are + * started, as gst_value_register_intersect_func() is not thread-safe and + * cannot be used at the same time as gst_value_intersect() or + * gst_value_can_intersect(). + */ +static void +gst_value_register_intersect_func (GType type1, GType type2, + GstValueIntersectFunc func) +{ + GstValueIntersectInfo intersect_info; + + intersect_info.type1 = type1; + intersect_info.type2 = type2; + intersect_info.func = func; + + g_array_append_val (gst_value_intersect_funcs, intersect_info); +} + + +/* subtraction */ + +/** + * gst_value_subtract: + * @dest: (out caller-allocates) (allow-none): the destination value + * for the result if the subtraction is not empty. May be %NULL, + * in which case the resulting set will not be computed, which can + * give a fair speedup. + * @minuend: the value to subtract from + * @subtrahend: the value to subtract + * + * Subtracts @subtrahend from @minuend and stores the result in @dest. + * Note that this means subtraction as in sets, not as in mathematics. + * + * Returns: %TRUE if the subtraction is not empty + */ +gboolean +gst_value_subtract (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + GstValueSubtractInfo *info; + guint i, len; + GType mtype, stype; + + g_return_val_if_fail (G_IS_VALUE (minuend), FALSE); + g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE); + + mtype = G_VALUE_TYPE (minuend); + stype = G_VALUE_TYPE (subtrahend); + + /* special cases first */ + if (mtype == GST_TYPE_LIST) + return gst_value_subtract_from_list (dest, minuend, subtrahend); + if (stype == GST_TYPE_LIST) + return gst_value_subtract_list (dest, minuend, subtrahend); + + len = gst_value_subtract_funcs->len; + for (i = 0; i < len; i++) { + info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); + if (info->minuend == mtype && info->subtrahend == stype) { + return info->func (dest, minuend, subtrahend); + } + } + + if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) { + if (dest) + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + + return FALSE; +} + +#if 0 +gboolean +gst_value_subtract (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend); + + g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend), + gst_value_serialize (subtrahend), + ret ? gst_value_serialize (dest) : "---"); + return ret; +} +#endif + +/** + * gst_value_can_subtract: + * @minuend: the value to subtract from + * @subtrahend: the value to subtract + * + * Checks if it's possible to subtract @subtrahend from @minuend. + * + * Returns: %TRUE if a subtraction is possible + */ +gboolean +gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) +{ + GstValueSubtractInfo *info; + guint i, len; + GType mtype, stype; + + g_return_val_if_fail (G_IS_VALUE (minuend), FALSE); + g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE); + + mtype = G_VALUE_TYPE (minuend); + stype = G_VALUE_TYPE (subtrahend); + + /* special cases */ + if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST) + return TRUE; + if (mtype == GST_TYPE_STRUCTURE || stype == GST_TYPE_STRUCTURE) + return FALSE; + + len = gst_value_subtract_funcs->len; + for (i = 0; i < len; i++) { + info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); + if (info->minuend == mtype && info->subtrahend == stype) + return TRUE; + } + + return gst_value_can_compare_unchecked (minuend, subtrahend); +} + +/* gst_value_register_subtract_func: (skip) + * @minuend_type: type of the minuend + * @subtrahend_type: type of the subtrahend + * @func: function to use + * + * Registers @func as a function capable of subtracting the values of + * @subtrahend_type from values of @minuend_type. + * + * Subtract functions should be registered at startup before any pipelines are + * started, as gst_value_register_subtract_func() is not thread-safe and + * cannot be used at the same time as gst_value_subtract(). + */ +static void +gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type, + GstValueSubtractFunc func) +{ + GstValueSubtractInfo info; + + g_return_if_fail (!gst_type_is_fixed (minuend_type) + || !gst_type_is_fixed (subtrahend_type)); + + info.minuend = minuend_type; + info.subtrahend = subtrahend_type; + info.func = func; + + g_array_append_val (gst_value_subtract_funcs, info); +} + +/** + * gst_value_register: + * @table: structure containing functions to register + * + * Registers functions to perform calculations on #GValue items of a given + * type. Each type can only be added once. + */ +void +gst_value_register (const GstValueTable * table) +{ + GstValueTable *found; + + g_return_if_fail (table != NULL); + + g_array_append_val (gst_value_table, *table); + + found = gst_value_hash_lookup_type (table->type); + if (found) + g_warning ("adding type %s multiple times", g_type_name (table->type)); + + /* FIXME: we're not really doing the const justice, we assume the table is + * static */ + gst_value_hash_add_type (table->type, table); +} + +/** + * gst_value_init_and_copy: + * @dest: (out caller-allocates): the target value + * @src: the source value + * + * Initialises the target value to be of the same type as source and then copies + * the contents from source to target. + */ +void +gst_value_init_and_copy (GValue * dest, const GValue * src) +{ + g_return_if_fail (G_IS_VALUE (src)); + g_return_if_fail (dest != NULL); + + g_value_init (dest, G_VALUE_TYPE (src)); + g_value_copy (src, dest); +} + +/* move src into dest and clear src */ +static void +gst_value_move (GValue * dest, GValue * src) +{ + g_assert (G_IS_VALUE (src)); + g_assert (dest != NULL); + + *dest = *src; + memset (src, 0, sizeof (GValue)); +} + +/** + * gst_value_serialize: + * @value: a #GValue to serialize + * + * tries to transform the given @value into a string representation that allows + * getting back this string later on using gst_value_deserialize(). + * + * Free-function: g_free + * + * Returns: (transfer full) (nullable): the serialization for @value + * or %NULL if none exists + */ +gchar * +gst_value_serialize (const GValue * value) +{ + guint i, len; + GValue s_val = { 0 }; + GstValueTable *table, *best; + gchar *s; + GType type; + + g_return_val_if_fail (G_IS_VALUE (value), NULL); + + type = G_VALUE_TYPE (value); + + best = gst_value_hash_lookup_type (type); + + if (G_UNLIKELY (!best || !best->serialize)) { + len = gst_value_table->len; + best = NULL; + for (i = 0; i < len; i++) { + table = &g_array_index (gst_value_table, GstValueTable, i); + if (table->serialize && g_type_is_a (type, table->type)) { + if (!best || g_type_is_a (table->type, best->type)) + best = table; + } + } + } + if (G_LIKELY (best)) + return best->serialize (value); + + g_value_init (&s_val, G_TYPE_STRING); + if (g_value_transform (value, &s_val)) { + s = gst_string_wrap (g_value_get_string (&s_val)); + } else { + s = NULL; + } + g_value_unset (&s_val); + + return s; +} + +/** + * gst_value_deserialize: + * @dest: (out caller-allocates): #GValue to fill with contents of + * deserialization + * @src: string to deserialize + * + * Tries to deserialize a string into the type specified by the given GValue. + * If the operation succeeds, %TRUE is returned, %FALSE otherwise. + * + * Returns: %TRUE on success + */ +gboolean +gst_value_deserialize (GValue * dest, const gchar * src) +{ + GstValueTable *table, *best; + guint i, len; + GType type; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (G_IS_VALUE (dest), FALSE); + + type = G_VALUE_TYPE (dest); + + best = gst_value_hash_lookup_type (type); + if (G_UNLIKELY (!best || !best->deserialize)) { + len = gst_value_table->len; + best = NULL; + for (i = 0; i < len; i++) { + table = &g_array_index (gst_value_table, GstValueTable, i); + if (table->deserialize && g_type_is_a (type, table->type)) { + if (!best || g_type_is_a (table->type, best->type)) + best = table; + } + } + } + if (G_LIKELY (best)) + return best->deserialize (dest, src); + + return FALSE; +} + +static gboolean +structure_field_is_fixed (GQuark field_id, const GValue * val, + gpointer user_data) +{ + return gst_value_is_fixed (val); +} + +/** + * gst_value_is_fixed: + * @value: the #GValue to check + * + * Tests if the given GValue, if available in a GstStructure (or any other + * container) contains a "fixed" (which means: one value) or an "unfixed" + * (which means: multiple possible values, such as data lists or data + * ranges) value. + * + * Returns: true if the value is "fixed". + */ + +gboolean +gst_value_is_fixed (const GValue * value) +{ + GType type; + + g_return_val_if_fail (G_IS_VALUE (value), FALSE); + + type = G_VALUE_TYPE (value); + + /* the most common types are just basic plain glib types */ + if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { + return TRUE; + } + + if (type == GST_TYPE_ARRAY) { + gint size, n; + const GValue *kid; + + /* check recursively */ + size = gst_value_array_get_size (value); + for (n = 0; n < size; n++) { + kid = gst_value_array_get_value (value, n); + if (!gst_value_is_fixed (kid)) + return FALSE; + } + return TRUE; + } else if (GST_VALUE_HOLDS_FLAG_SET (value)) { + /* Flagsets are only fixed if there are no 'don't care' bits */ + return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT); + } else if (GST_VALUE_HOLDS_STRUCTURE (value)) { + return gst_structure_foreach (gst_value_get_structure (value), + structure_field_is_fixed, NULL); + } + return gst_type_is_fixed (type); +} + +/** + * gst_value_fixate: + * @dest: the #GValue destination + * @src: the #GValue to fixate + * + * Fixate @src into a new value @dest. + * For ranges, the first element is taken. For lists and arrays, the + * first item is fixated and returned. + * If @src is already fixed, this function returns %FALSE. + * + * Returns: %TRUE if @dest contains a fixated version of @src. + */ +gboolean +gst_value_fixate (GValue * dest, const GValue * src) +{ + g_return_val_if_fail (G_IS_VALUE (src), FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) { + g_value_init (dest, G_TYPE_INT); + g_value_set_int (dest, gst_value_get_int_range_min (src)); + } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) { + g_value_init (dest, G_TYPE_DOUBLE); + g_value_set_double (dest, gst_value_get_double_range_min (src)); + } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) { + gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src)); + } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) { + GValue temp = { 0 }; + + /* list could be empty */ + if (gst_value_list_get_size (src) <= 0) + return FALSE; + + gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0)); + + if (!gst_value_fixate (dest, &temp)) { + gst_value_move (dest, &temp); + } else { + g_value_unset (&temp); + } + } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) { + gboolean res = FALSE; + guint n, len; + + len = gst_value_array_get_size (src); + g_value_init (dest, GST_TYPE_ARRAY); + for (n = 0; n < len; n++) { + GValue kid = { 0 }; + const GValue *orig_kid = gst_value_array_get_value (src, n); + + if (!gst_value_fixate (&kid, orig_kid)) + gst_value_init_and_copy (&kid, orig_kid); + else + res = TRUE; + _gst_value_array_append_and_take_value (dest, &kid); + } + + if (!res) + g_value_unset (dest); + + return res; + } else if (GST_VALUE_HOLDS_FLAG_SET (src)) { + guint flags; + + if (gst_value_get_flagset_mask (src) == GST_FLAG_SET_MASK_EXACT) + return FALSE; /* Already fixed */ + + flags = gst_value_get_flagset_flags (src); + g_value_init (dest, G_VALUE_TYPE (src)); + gst_value_set_flagset (dest, flags, GST_FLAG_SET_MASK_EXACT); + return TRUE; + } else if (GST_VALUE_HOLDS_STRUCTURE (src)) { + const GstStructure *str = (GstStructure *) gst_value_get_structure (src); + GstStructure *kid; + + if (!str) + return FALSE; + + kid = gst_structure_copy (str); + gst_structure_fixate (kid); + g_value_init (dest, GST_TYPE_STRUCTURE); + gst_value_set_structure (dest, kid); + gst_structure_free (kid); + return TRUE; + } else { + return FALSE; + } + return TRUE; +} + + +/************ + * fraction * + ************/ + +/* helper functions */ +static void +gst_value_init_fraction (GValue * value) +{ + value->data[0].v_int = 0; + value->data[1].v_int = 1; +} + +static void +gst_value_copy_fraction (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_int = src_value->data[0].v_int; + dest_value->data[1].v_int = src_value->data[1].v_int; +} + +static gchar * +gst_value_collect_fraction (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[1].v_int == 0) + return g_strdup_printf ("passed '0' as denominator for `%s'", + G_VALUE_TYPE_NAME (value)); + if (collect_values[0].v_int < -G_MAXINT) + return + g_strdup_printf + ("passed value smaller than -G_MAXINT as numerator for `%s'", + G_VALUE_TYPE_NAME (value)); + if (collect_values[1].v_int < -G_MAXINT) + return + g_strdup_printf + ("passed value smaller than -G_MAXINT as denominator for `%s'", + G_VALUE_TYPE_NAME (value)); + + gst_value_set_fraction (value, + collect_values[0].v_int, collect_values[1].v_int); + + return NULL; +} + +static gchar * +gst_value_lcopy_fraction (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + gint *numerator = collect_values[0].v_pointer; + gint *denominator = collect_values[1].v_pointer; + + if (!numerator) + return g_strdup_printf ("numerator for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!denominator) + return g_strdup_printf ("denominator for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *numerator = value->data[0].v_int; + *denominator = value->data[1].v_int; + + return NULL; +} + +/** + * gst_value_set_fraction: + * @value: a GValue initialized to #GST_TYPE_FRACTION + * @numerator: the numerator of the fraction + * @denominator: the denominator of the fraction + * + * Sets @value to the fraction specified by @numerator over @denominator. + * The fraction gets reduced to the smallest numerator and denominator, + * and if necessary the sign is moved to the numerator. + */ +void +gst_value_set_fraction (GValue * value, gint numerator, gint denominator) +{ + gint gcd = 0; + + g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value)); + g_return_if_fail (denominator != 0); + g_return_if_fail (denominator >= -G_MAXINT); + g_return_if_fail (numerator >= -G_MAXINT); + + /* normalize sign */ + if (denominator < 0) { + numerator = -numerator; + denominator = -denominator; + } + + /* check for reduction */ + gcd = gst_util_greatest_common_divisor (numerator, denominator); + if (gcd) { + numerator /= gcd; + denominator /= gcd; + } + + g_assert (denominator > 0); + + value->data[0].v_int = numerator; + value->data[1].v_int = denominator; +} + +/** + * gst_value_get_fraction_numerator: + * @value: a GValue initialized to #GST_TYPE_FRACTION + * + * Gets the numerator of the fraction specified by @value. + * + * Returns: the numerator of the fraction. + */ +gint +gst_value_get_fraction_numerator (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0); + + return value->data[0].v_int; +} + +/** + * gst_value_get_fraction_denominator: + * @value: a GValue initialized to #GST_TYPE_FRACTION + * + * Gets the denominator of the fraction specified by @value. + * + * Returns: the denominator of the fraction. + */ +gint +gst_value_get_fraction_denominator (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1); + + return value->data[1].v_int; +} + +/** + * gst_value_fraction_multiply: + * @product: a GValue initialized to #GST_TYPE_FRACTION + * @factor1: a GValue initialized to #GST_TYPE_FRACTION + * @factor2: a GValue initialized to #GST_TYPE_FRACTION + * + * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets + * @product to the product of the two fractions. + * + * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise. + */ +gboolean +gst_value_fraction_multiply (GValue * product, const GValue * factor1, + const GValue * factor2) +{ + gint n1, n2, d1, d2; + gint res_n, res_d; + + g_return_val_if_fail (product != NULL, FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE); + + n1 = factor1->data[0].v_int; + n2 = factor2->data[0].v_int; + d1 = factor1->data[1].v_int; + d2 = factor2->data[1].v_int; + + if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d)) + return FALSE; + + gst_value_set_fraction (product, res_n, res_d); + + return TRUE; +} + +/** + * gst_value_fraction_subtract: + * @dest: a GValue initialized to #GST_TYPE_FRACTION + * @minuend: a GValue initialized to #GST_TYPE_FRACTION + * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION + * + * Subtracts the @subtrahend from the @minuend and sets @dest to the result. + * + * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise. + */ +gboolean +gst_value_fraction_subtract (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + gint n1, n2, d1, d2; + gint res_n, res_d; + + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE); + + n1 = minuend->data[0].v_int; + n2 = subtrahend->data[0].v_int; + d1 = minuend->data[1].v_int; + d2 = subtrahend->data[1].v_int; + + if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d)) + return FALSE; + gst_value_set_fraction (dest, res_n, res_d); + + return TRUE; +} + +static gchar * +gst_value_serialize_fraction (const GValue * value) +{ + gint32 numerator = value->data[0].v_int; + gint32 denominator = value->data[1].v_int; + gboolean positive = TRUE; + + /* get the sign and make components absolute */ + if (numerator < 0) { + numerator = -numerator; + positive = !positive; + } + if (denominator < 0) { + denominator = -denominator; + positive = !positive; + } + + return g_strdup_printf ("%s%d/%d", + positive ? "" : "-", numerator, denominator); +} + +static gboolean +gst_value_deserialize_fraction (GValue * dest, const gchar * s) +{ + gint num, den; + gint num_chars; + + if (G_UNLIKELY (s == NULL)) + return FALSE; + + if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest))) + return FALSE; + + if (sscanf (s, "%d/%d%n", &num, &den, &num_chars) >= 2) { + if (s[num_chars] != 0) + return FALSE; + if (den == 0) + return FALSE; + + gst_value_set_fraction (dest, num, den); + return TRUE; + } else if (g_ascii_strcasecmp (s, "1/max") == 0) { + gst_value_set_fraction (dest, 1, G_MAXINT); + return TRUE; + } else if (sscanf (s, "%d%n", &num, &num_chars) >= 1) { + if (s[num_chars] != 0) + return FALSE; + gst_value_set_fraction (dest, num, 1); + return TRUE; + } else if (g_ascii_strcasecmp (s, "min") == 0) { + gst_value_set_fraction (dest, -G_MAXINT, 1); + return TRUE; + } else if (g_ascii_strcasecmp (s, "max") == 0) { + gst_value_set_fraction (dest, G_MAXINT, 1); + return TRUE; + } + + return FALSE; +} + +static void +gst_value_transform_fraction_string (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value); +} + +static void +gst_value_transform_string_fraction (const GValue * src_value, + GValue * dest_value) +{ + if (!gst_value_deserialize_fraction (dest_value, + src_value->data[0].v_pointer)) + /* If the deserialize fails, ensure we leave the fraction in a + * valid, if incorrect, state */ + gst_value_set_fraction (dest_value, 0, 1); +} + +static void +gst_value_transform_double_fraction (const GValue * src_value, + GValue * dest_value) +{ + gdouble src = g_value_get_double (src_value); + gint n, d; + + gst_util_double_to_fraction (src, &n, &d); + gst_value_set_fraction (dest_value, n, d); +} + +static void +gst_value_transform_float_fraction (const GValue * src_value, + GValue * dest_value) +{ + gfloat src = g_value_get_float (src_value); + gint n, d; + + gst_util_double_to_fraction (src, &n, &d); + gst_value_set_fraction (dest_value, n, d); +} + +static void +gst_value_transform_fraction_double (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_double = ((double) src_value->data[0].v_int) / + ((double) src_value->data[1].v_int); +} + +static void +gst_value_transform_fraction_float (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_float = ((float) src_value->data[0].v_int) / + ((float) src_value->data[1].v_int); +} + +static gint +gst_value_compare_fraction (const GValue * value1, const GValue * value2) +{ + gint n1, n2; + gint d1, d2; + gint ret; + + n1 = value1->data[0].v_int; + n2 = value2->data[0].v_int; + d1 = value1->data[1].v_int; + d2 = value2->data[1].v_int; + + /* fractions are reduced when set, so we can quickly see if they're equal */ + if (n1 == n2 && d1 == d2) + return GST_VALUE_EQUAL; + + if (d1 == 0 && d2 == 0) + return GST_VALUE_UNORDERED; + else if (d1 == 0) + return GST_VALUE_GREATER_THAN; + else if (d2 == 0) + return GST_VALUE_LESS_THAN; + + ret = gst_util_fraction_compare (n1, d1, n2, d2); + if (ret == -1) + return GST_VALUE_LESS_THAN; + else if (ret == 1) + return GST_VALUE_GREATER_THAN; + + /* Equality can't happen here because we check for that + * first already */ + g_return_val_if_reached (GST_VALUE_UNORDERED); +} + +/********* + * GDate * + *********/ + +static gint +gst_value_compare_date (const GValue * value1, const GValue * value2) +{ + const GDate *date1 = (const GDate *) g_value_get_boxed (value1); + const GDate *date2 = (const GDate *) g_value_get_boxed (value2); + guint32 j1, j2; + + if (date1 == date2) + return GST_VALUE_EQUAL; + + if ((date1 == NULL || !g_date_valid (date1)) + && (date2 != NULL && g_date_valid (date2))) { + return GST_VALUE_LESS_THAN; + } + + if ((date2 == NULL || !g_date_valid (date2)) + && (date1 != NULL && g_date_valid (date1))) { + return GST_VALUE_GREATER_THAN; + } + + if (date1 == NULL || date2 == NULL || !g_date_valid (date1) + || !g_date_valid (date2)) { + return GST_VALUE_UNORDERED; + } + + j1 = g_date_get_julian (date1); + j2 = g_date_get_julian (date2); + + if (j1 == j2) + return GST_VALUE_EQUAL; + else if (j1 < j2) + return GST_VALUE_LESS_THAN; + else + return GST_VALUE_GREATER_THAN; +} + +static gchar * +gst_value_serialize_date (const GValue * val) +{ + const GDate *date = (const GDate *) g_value_get_boxed (val); + + if (date == NULL || !g_date_valid (date)) + return g_strdup ("9999-99-99"); + + return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date), + g_date_get_month (date), g_date_get_day (date)); +} + +static gboolean +gst_value_deserialize_date (GValue * dest, const gchar * s) +{ + guint year, month, day; + + if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3) + return FALSE; + + if (!g_date_valid_dmy (day, month, year)) + return FALSE; + + g_value_take_boxed (dest, g_date_new_dmy (day, month, year)); + return TRUE; +} + +/************* + * GstDateTime * + *************/ + +static gint +gst_value_compare_date_time (const GValue * value1, const GValue * value2) +{ + const GstDateTime *date1 = (const GstDateTime *) g_value_get_boxed (value1); + const GstDateTime *date2 = (const GstDateTime *) g_value_get_boxed (value2); + + if (date1 == date2) + return GST_VALUE_EQUAL; + + if ((date1 == NULL) && (date2 != NULL)) { + return GST_VALUE_LESS_THAN; + } + if ((date2 == NULL) && (date1 != NULL)) { + return GST_VALUE_LESS_THAN; + } + + /* returns GST_VALUE_* */ + return __gst_date_time_compare (date1, date2); +} + +static gchar * +gst_value_serialize_date_time (const GValue * val) +{ + GstDateTime *date = (GstDateTime *) g_value_get_boxed (val); + + if (date == NULL) + return g_strdup ("null"); + + return __gst_date_time_serialize (date, TRUE); +} + +static gboolean +gst_value_deserialize_date_time (GValue * dest, const gchar * s) +{ + GstDateTime *datetime; + + if (!s || strcmp (s, "null") == 0) { + return FALSE; + } + + datetime = gst_date_time_new_from_iso8601_string (s); + if (datetime != NULL) { + g_value_take_boxed (dest, datetime); + return TRUE; + } + GST_WARNING ("Failed to deserialize date time string '%s'", s); + return FALSE; +} + +static void +gst_value_transform_date_string (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_pointer = gst_value_serialize_date (src_value); +} + +static void +gst_value_transform_string_date (const GValue * src_value, GValue * dest_value) +{ + gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer); +} + + +/************ + * bitmask * + ************/ + +/* helper functions */ +static void +gst_value_init_bitmask (GValue * value) +{ + value->data[0].v_uint64 = 0; +} + +static void +gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; +} + +static gchar * +gst_value_collect_bitmask (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 1) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + + gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64); + + return NULL; +} + +static gchar * +gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + guint64 *bitmask = collect_values[0].v_pointer; + + if (!bitmask) + return g_strdup_printf ("value for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *bitmask = value->data[0].v_uint64; + + return NULL; +} + +/** + * gst_value_set_bitmask: + * @value: a GValue initialized to #GST_TYPE_BITMASK + * @bitmask: the bitmask + * + * Sets @value to the bitmask specified by @bitmask. + */ +void +gst_value_set_bitmask (GValue * value, guint64 bitmask) +{ + g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value)); + + value->data[0].v_uint64 = bitmask; +} + +/** + * gst_value_get_bitmask: + * @value: a GValue initialized to #GST_TYPE_BITMASK + * + * Gets the bitmask specified by @value. + * + * Returns: the bitmask. + */ +guint64 +gst_value_get_bitmask (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0); + + return value->data[0].v_uint64; +} + +static gchar * +gst_value_serialize_bitmask (const GValue * value) +{ + guint64 bitmask = value->data[0].v_uint64; + + return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask); +} + +static gboolean +gst_value_deserialize_bitmask (GValue * dest, const gchar * s) +{ + gchar *endptr = NULL; + guint64 val; + + if (G_UNLIKELY (s == NULL)) + return FALSE; + + if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest))) + return FALSE; + + errno = 0; + val = g_ascii_strtoull (s, &endptr, 16); + if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL)) + return FALSE; + if (val == 0 && endptr == s) + return FALSE; + + gst_value_set_bitmask (dest, val); + + return TRUE; +} + +static void +gst_value_transform_bitmask_string (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value); +} + +static void +gst_value_transform_string_bitmask (const GValue * src_value, + GValue * dest_value) +{ + if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer)) + gst_value_set_bitmask (dest_value, 0); +} + +static void +gst_value_transform_uint64_bitmask (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; +} + +static void +gst_value_transform_bitmask_uint64 (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; +} + +static gint +gst_value_compare_bitmask (const GValue * value1, const GValue * value2) +{ + guint64 v1, v2; + + v1 = value1->data[0].v_uint64; + v2 = value2->data[0].v_uint64; + + if (v1 == v2) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + +/************ + * flagset * + ************/ + +/* helper functions */ +static void +gst_value_init_flagset (GValue * value) +{ + value->data[0].v_uint = 0; + value->data[1].v_uint = 0; +} + +static void +gst_value_copy_flagset (const GValue * src_value, GValue * dest_value) +{ + dest_value->data[0].v_uint = src_value->data[0].v_uint; + dest_value->data[1].v_uint = src_value->data[1].v_uint; +} + +static gchar * +gst_value_collect_flagset (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + + gst_value_set_flagset (value, + (guint) collect_values[0].v_int, (guint) collect_values[1].v_int); + + return NULL; +} + +static gchar * +gst_value_lcopy_flagset (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + guint *flags = collect_values[0].v_pointer; + guint *mask = collect_values[1].v_pointer; + + *flags = value->data[0].v_uint; + *mask = value->data[1].v_uint; + + return NULL; +} + +/** + * gst_value_set_flagset: + * @value: a GValue initialized to %GST_TYPE_FLAG_SET + * @flags: The value of the flags set or unset + * @mask: The mask indicate which flags bits must match for comparisons + * + * Sets @value to the flags and mask values provided in @flags and @mask. + * The @flags value indicates the values of flags, the @mask represents + * which bits in the flag value have been set, and which are "don't care" + * + * Since: 1.6 + */ +void +gst_value_set_flagset (GValue * value, guint flags, guint mask) +{ + g_return_if_fail (GST_VALUE_HOLDS_FLAG_SET (value)); + + /* Normalise and only keep flags mentioned in the mask */ + value->data[0].v_uint = flags & mask; + value->data[1].v_uint = mask; +} + +/** + * gst_value_get_flagset_flags: + * @value: a GValue initialized to #GST_TYPE_FLAG_SET + * + * Retrieve the flags field of a GstFlagSet @value. + * + * Returns: the flags field of the flagset instance. + * + * Since: 1.6 + */ +guint +gst_value_get_flagset_flags (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 0); + + return value->data[0].v_uint; +} + +/** + * gst_value_get_flagset_mask: + * @value: a GValue initialized to #GST_TYPE_FLAG_SET + * + * Retrieve the mask field of a GstFlagSet @value. + * + * Returns: the mask field of the flagset instance. + * + * Since: 1.6 + */ +guint +gst_value_get_flagset_mask (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 1); + + return value->data[1].v_uint; +} + +static gchar * +gst_value_serialize_flagset (const GValue * value) +{ + guint flags = value->data[0].v_uint; + guint mask = value->data[1].v_uint; + GstFlagSetClass *set_klass = + (GstFlagSetClass *) g_type_class_ref (G_VALUE_TYPE (value)); + gchar *result; + + result = g_strdup_printf ("%x:%x", flags, mask); + + /* If this flag set class has an associated GFlags GType, and some + * bits in the mask, serialize the bits in human-readable form to + * aid debugging */ + if (mask && set_klass->flags_type) { + GFlagsClass *flags_klass = + (GFlagsClass *) (g_type_class_ref (set_klass->flags_type)); + GFlagsValue *fl; + gchar *tmp; + gboolean first = TRUE; + + g_return_val_if_fail (flags_klass, NULL); + + /* some bits in the mask are set, so serialize one by one, according + * to whether that bit is set or cleared in the flags value */ + while (mask) { + fl = g_flags_get_first_value (flags_klass, mask); + if (fl == NULL) { + /* No more bits match in the flags mask - time to stop */ + mask = 0; + break; + } + + tmp = g_strconcat (result, + first ? ":" : "", + (flags & fl->value) ? "+" : "/", fl->value_nick, NULL); + g_free (result); + result = tmp; + first = FALSE; + + /* clear flag */ + mask &= ~fl->value; + } + g_type_class_unref (flags_klass); + + } + g_type_class_unref (set_klass); + + return result; +} + +static gboolean +is_valid_flags_string (const gchar * s) +{ + /* We're looking to match +this/that+other-thing/not-this-thing type strings */ + return g_regex_match_simple ("^([\\+\\/][\\w\\d-]+)+$", s, G_REGEX_CASELESS, + 0); +} + +static gboolean +gst_value_deserialize_flagset (GValue * dest, const gchar * s) +{ + gboolean res = FALSE; + guint flags, mask; + gchar *cur, *next; + + if (G_UNLIKELY (s == NULL)) + return FALSE; + + if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FLAG_SET (dest))) + return FALSE; + + /* Flagset strings look like %x:%x - hex flags : hex bitmask, + * 32-bit each, or like a concatenated list of flag nicks, + * with either '+' or '/' in front. The first form + * may optionally be followed by ':' and a set of text flag descriptions + * for easier debugging */ + + /* Try and interpret as hex form first, as it's the most efficient */ + /* Read the flags first */ + flags = strtoul (s, &next, 16); + if (G_UNLIKELY ((flags == 0 && errno == EINVAL) || s == next)) + goto try_as_flags_string; + /* Next char should be a colon */ + if (next[0] == ':') + next++; + + /* Read the mask */ + cur = next; + mask = strtoul (cur, &next, 16); + if (G_UNLIKELY ((mask == 0 && errno == EINVAL) || cur == next)) + goto try_as_flags_string; + + /* Next char should be NULL terminator, or a ':'. If ':', we need the flag string after */ + if (G_UNLIKELY (next[0] == 0)) { + res = TRUE; + goto done; + } + + if (next[0] != ':') + return FALSE; + + s = next + 1; + + if (g_str_equal (g_type_name (G_VALUE_TYPE (dest)), "GstFlagSet")) { + /* If we're parsing a generic flag set, that can mean we're guessing + * at the type in deserialising a GstStructure so at least check that + * we have a valid-looking string, so we don't cause deserialisation of + * other types of strings like 00:01:00:00 - https://bugzilla.gnome.org/show_bug.cgi?id=779755 */ + if (is_valid_flags_string (s)) { + res = TRUE; + goto done; + } + return FALSE; + } + + /* Otherwise, we already got a hex string for a valid non-generic flagset type */ + res = TRUE; + goto done; + +try_as_flags_string: + + { + const gchar *set_class = g_type_name (G_VALUE_TYPE (dest)); + GFlagsClass *flags_klass = NULL; + const gchar *end; + + if (g_str_equal (set_class, "GstFlagSet")) { + /* There's no hope to parse the fields of generic flag set if we didn't already + * catch a hex-string above */ + return FALSE; + } + + /* Flags class is the FlagSet class with 'Set' removed from the end */ + end = g_strrstr (set_class, "Set"); + + if (end != NULL) { + gchar *class_name = g_strndup (set_class, end - set_class); + GType flags_type = g_type_from_name (class_name); + if (flags_type == 0) { + GST_TRACE ("Looking for dynamic type %s", class_name); + gst_dynamic_type_factory_load (class_name); + } + + if (flags_type != 0) { + flags_klass = g_type_class_ref (flags_type); + GST_TRACE ("Going to parse %s as %s", s, class_name); + } + g_free (class_name); + } + + if (flags_klass) { + res = gst_value_gflags_str_to_flags (flags_klass, s, &flags, &mask); + g_type_class_unref (flags_klass); + } + } + +done: + if (res) + gst_value_set_flagset (dest, flags, mask); + return res; + +} + +static void +gst_value_transform_flagset_string (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_pointer = gst_value_serialize_flagset (src_value); +} + +static void +gst_value_transform_string_flagset (const GValue * src_value, + GValue * dest_value) +{ + if (!gst_value_deserialize_flagset (dest_value, src_value->data[0].v_pointer)) { + /* If the deserialize fails, ensure we leave the flags in a + * valid, if incorrect, state */ + gst_value_set_flagset (dest_value, 0, 0); + } +} + +static gint +gst_value_compare_flagset (const GValue * value1, const GValue * value2) +{ + guint v1, v2; + guint m1, m2; + + v1 = value1->data[0].v_uint; + v2 = value2->data[0].v_uint; + + m1 = value1->data[1].v_uint; + m2 = value2->data[1].v_uint; + + if (v1 == v2 && m1 == m2) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + +/*********************** + * GstAllocationParams * + ***********************/ +static gint +gst_value_compare_allocation_params (const GValue * value1, + const GValue * value2) +{ + GstAllocationParams *v1, *v2; + + v1 = value1->data[0].v_pointer; + v2 = value2->data[0].v_pointer; + + if (v1 == NULL && v1 == v2) + return GST_VALUE_EQUAL; + + if (v1 == NULL || v2 == NULL) + return GST_VALUE_UNORDERED; + + if (v1->flags == v2->flags && v1->align == v2->align && + v1->prefix == v2->prefix && v1->padding == v2->padding) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + + +/************ + * GObject * + ************/ + +static gint +gst_value_compare_object (const GValue * value1, const GValue * value2) +{ + gpointer v1, v2; + + v1 = value1->data[0].v_pointer; + v2 = value2->data[0].v_pointer; + + if (v1 == v2) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + +static void +gst_value_transform_object_string (const GValue * src_value, + GValue * dest_value) +{ + GstObject *obj; + gchar *str; + + obj = g_value_get_object (src_value); + if (obj) { + str = + g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj), + GST_OBJECT_NAME (obj)); + } else { + str = g_strdup ("NULL"); + } + + dest_value->data[0].v_pointer = str; +} + +static GTypeInfo _info = { + 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL, +}; + +static GTypeFundamentalInfo _finfo = { + 0 +}; + +#define FUNC_VALUE_GET_TYPE_CLASSED(type, name, csize, flags) \ +GType _gst_ ## type ## _type = 0; \ + \ +GType gst_ ## type ## _get_type (void) \ +{ \ + static volatile GType gst_ ## type ## _type = 0; \ + \ + if (g_once_init_enter (&gst_ ## type ## _type)) { \ + GType _type; \ + _info.class_size = csize; \ + _finfo.type_flags = flags; \ + _info.value_table = & _gst_ ## type ## _value_table; \ + _type = g_type_register_fundamental ( \ + g_type_fundamental_next (), \ + name, &_info, &_finfo, 0); \ + _gst_ ## type ## _type = _type; \ + g_once_init_leave(&gst_ ## type ## _type, _type); \ + } \ + \ + return gst_ ## type ## _type; \ +} + +#define FUNC_VALUE_GET_TYPE(type, name) \ + FUNC_VALUE_GET_TYPE_CLASSED(type, name, 0, 0) + +static const GTypeValueTable _gst_int_range_value_table = { + gst_value_init_int_range, + NULL, + gst_value_copy_int_range, + NULL, + (char *) "ii", + gst_value_collect_int_range, (char *) "pp", gst_value_lcopy_int_range +}; + +FUNC_VALUE_GET_TYPE (int_range, "GstIntRange"); + +static const GTypeValueTable _gst_int64_range_value_table = { + gst_value_init_int64_range, + gst_value_free_int64_range, + gst_value_copy_int64_range, + NULL, + (char *) "qq", + gst_value_collect_int64_range, + (char *) "pp", gst_value_lcopy_int64_range +}; + +FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range"); + +static const GTypeValueTable _gst_double_range_value_table = { + gst_value_init_double_range, + NULL, + gst_value_copy_double_range, + NULL, + (char *) "dd", + gst_value_collect_double_range, + (char *) "pp", gst_value_lcopy_double_range +}; + +FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange"); + +static const GTypeValueTable _gst_fraction_range_value_table = { + gst_value_init_fraction_range, + gst_value_free_fraction_range, + gst_value_copy_fraction_range, + NULL, + (char *) "iiii", + gst_value_collect_fraction_range, + (char *) "pppp", gst_value_lcopy_fraction_range +}; + +FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange"); + +static const GTypeValueTable _gst_value_list_value_table = { + gst_value_init_list_or_array, + gst_value_free_list_or_array, + gst_value_copy_list_or_array, + gst_value_list_or_array_peek_pointer, + (char *) "p", + gst_value_collect_list_or_array, + (char *) "p", gst_value_lcopy_list_or_array +}; + +FUNC_VALUE_GET_TYPE (value_list, "GstValueList"); + +static const GTypeValueTable _gst_value_array_value_table = { + gst_value_init_list_or_array, + gst_value_free_list_or_array, + gst_value_copy_list_or_array, + gst_value_list_or_array_peek_pointer, + (char *) "p", + gst_value_collect_list_or_array, + (char *) "p", gst_value_lcopy_list_or_array +}; + +FUNC_VALUE_GET_TYPE (value_array, "GstValueArray"); + +static const GTypeValueTable _gst_fraction_value_table = { + gst_value_init_fraction, + NULL, + gst_value_copy_fraction, + NULL, + (char *) "ii", + gst_value_collect_fraction, (char *) "pp", gst_value_lcopy_fraction +}; + +FUNC_VALUE_GET_TYPE (fraction, "GstFraction"); + +static const GTypeValueTable _gst_bitmask_value_table = { + gst_value_init_bitmask, + NULL, + gst_value_copy_bitmask, + NULL, + (char *) "q", + gst_value_collect_bitmask, (char *) "p", gst_value_lcopy_bitmask +}; + +FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask"); + +static const GTypeValueTable _gst_flagset_value_table = { + gst_value_init_flagset, + NULL, + gst_value_copy_flagset, + NULL, + (char *) "ii", + gst_value_collect_flagset, (char *) "pp", gst_value_lcopy_flagset +}; + +FUNC_VALUE_GET_TYPE_CLASSED (flagset, "GstFlagSet", + sizeof (GstFlagSetClass), G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE); + +GType +gst_g_thread_get_type (void) +{ + return G_TYPE_THREAD; +} + +#define SERIAL_VTABLE(t,c,s,d) { t, c, s, d } + +#define REGISTER_SERIALIZATION_CONST(_gtype, _type) \ +G_STMT_START { \ + static const GstValueTable gst_value = \ + SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \ + gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \ + gst_value_register (&gst_value); \ +} G_STMT_END + +#define REGISTER_SERIALIZATION(_gtype, _type) \ +G_STMT_START { \ + static GstValueTable gst_value = \ + SERIAL_VTABLE (0, gst_value_compare_ ## _type, \ + gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \ + gst_value.type = _gtype; \ + gst_value_register (&gst_value); \ +} G_STMT_END + +#define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type) \ +G_STMT_START { \ + static GstValueTable gst_value = \ + SERIAL_VTABLE (0, NULL, \ + gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \ + gst_value.type = _gtype; \ + gst_value_register (&gst_value); \ +} G_STMT_END + +#define REGISTER_SERIALIZATION_COMPARE_ONLY(_gtype, _type) \ +G_STMT_START { \ + static GstValueTable gst_value = \ + SERIAL_VTABLE (0, gst_value_compare_ ## _type, \ + NULL, NULL); \ + gst_value.type = _gtype; \ + gst_value_register (&gst_value); \ +} G_STMT_END + +/* These initial sizes are used for the tables + * below, and save a couple of reallocs at startup */ + +static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 40; +static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 8; +static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 16; +static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 16; + +void +_priv_gst_value_initialize (void) +{ + gst_value_table = + g_array_sized_new (FALSE, FALSE, sizeof (GstValueTable), + GST_VALUE_TABLE_DEFAULT_SIZE); + gst_value_hash = g_hash_table_new (NULL, NULL); + gst_value_union_funcs = g_array_sized_new (FALSE, FALSE, + sizeof (GstValueUnionInfo), GST_VALUE_UNION_TABLE_DEFAULT_SIZE); + gst_value_intersect_funcs = g_array_sized_new (FALSE, FALSE, + sizeof (GstValueIntersectInfo), GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE); + gst_value_subtract_funcs = g_array_sized_new (FALSE, FALSE, + sizeof (GstValueSubtractInfo), GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE); + + REGISTER_SERIALIZATION (gst_int_range_get_type (), int_range); + REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range); + REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range); + REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range); + REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list); + REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array); + REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array); + REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer); + REGISTER_SERIALIZATION (gst_sample_get_type (), sample); + REGISTER_SERIALIZATION (gst_fraction_get_type (), fraction); + REGISTER_SERIALIZATION (gst_caps_get_type (), caps); + REGISTER_SERIALIZATION (gst_tag_list_get_type (), tag_list); + REGISTER_SERIALIZATION (G_TYPE_DATE, date); + REGISTER_SERIALIZATION (gst_date_time_get_type (), date_time); + REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask); + REGISTER_SERIALIZATION (gst_structure_get_type (), structure); + REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset); + + REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment); + REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (), + caps_features); + + REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (), + allocation_params); + REGISTER_SERIALIZATION_COMPARE_ONLY (G_TYPE_OBJECT, object); + + REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double); + REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float); + + REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string); + REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean); + REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum); + + REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags); + + REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int); + + REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64); + REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long); + + REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint); + REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64); + REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong); + + REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar); + + REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype); + + g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING, + gst_value_transform_int_range_string); + g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING, + gst_value_transform_int64_range_string); + g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING, + gst_value_transform_double_range_string); + g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING, + gst_value_transform_fraction_range_string); + g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING, + gst_value_transform_list_string); + g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_VALUE_ARRAY, + gst_value_transform_any_list_g_value_array); + g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING, + gst_value_transform_array_string); + g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_VALUE_ARRAY, + gst_value_transform_any_list_g_value_array); + g_value_register_transform_func (G_TYPE_VALUE_ARRAY, G_TYPE_STRING, + gst_value_transform_g_value_array_string); + g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_ARRAY, + gst_value_transform_g_value_array_any_list); + g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_LIST, + gst_value_transform_g_value_array_any_list); + g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING, + gst_value_transform_fraction_string); + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION, + gst_value_transform_string_fraction); + g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE, + gst_value_transform_fraction_double); + g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT, + gst_value_transform_fraction_float); + g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION, + gst_value_transform_double_fraction); + g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION, + gst_value_transform_float_fraction); + g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING, + gst_value_transform_date_string); + g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE, + gst_value_transform_string_date); + g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING, + gst_value_transform_object_string); + g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64, + gst_value_transform_bitmask_uint64); + g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING, + gst_value_transform_bitmask_string); + g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK, + gst_value_transform_uint64_bitmask); + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK, + gst_value_transform_string_bitmask); + + g_value_register_transform_func (GST_TYPE_FLAG_SET, G_TYPE_STRING, + gst_value_transform_flagset_string); + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET, + gst_value_transform_string_flagset); + + gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE, + gst_value_intersect_int_int_range); + gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, + gst_value_intersect_int_range_int_range); + gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE, + gst_value_intersect_int64_int64_range); + gst_value_register_intersect_func (GST_TYPE_INT64_RANGE, + GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range); + gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, + gst_value_intersect_double_double_range); + gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE, + GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range); + gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY, + gst_value_intersect_array); + gst_value_register_intersect_func (GST_TYPE_FRACTION, + GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range); + gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, + gst_value_intersect_fraction_range_fraction_range); + gst_value_register_intersect_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET, + gst_value_intersect_flagset_flagset); + gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE, + gst_value_intersect_structure_structure); + + gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE, + gst_value_subtract_int_int_range); + gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT, + gst_value_subtract_int_range_int); + gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, + gst_value_subtract_int_range_int_range); + gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE, + gst_value_subtract_int64_int64_range); + gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64, + gst_value_subtract_int64_range_int64); + gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, + GST_TYPE_INT64_RANGE, gst_value_subtract_int64_range_int64_range); + gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, + gst_value_subtract_double_double_range); + gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE, + gst_value_subtract_double_range_double); + gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, + GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range); + gst_value_register_subtract_func (GST_TYPE_FRACTION, + GST_TYPE_FRACTION_RANGE, gst_value_subtract_fraction_fraction_range); + gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION, gst_value_subtract_fraction_range_fraction); + gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, + gst_value_subtract_fraction_range_fraction_range); + + /* see bug #317246, #64994, #65041 */ + { + volatile GType date_type = G_TYPE_DATE; + + g_type_name (date_type); + } + + gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE, + gst_value_union_int_int_range); + gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, + gst_value_union_int_range_int_range); + gst_value_register_union_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET, + gst_value_union_flagset_flagset); + gst_value_register_union_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE, + gst_value_union_structure_structure); + +#if GST_VERSION_NANO == 1 + /* If building from git master, check starting array sizes matched actual size + * so we can keep the defines in sync and save a few reallocs on startup */ + if (gst_value_table->len > GST_VALUE_TABLE_DEFAULT_SIZE) { + GST_ERROR ("Wrong initial gst_value_table size. " + "Please set GST_VALUE_TABLE_DEFAULT_SIZE to %u in gstvalue.c", + gst_value_table->len); + } + if (gst_value_union_funcs->len > GST_VALUE_UNION_TABLE_DEFAULT_SIZE) { + GST_ERROR ("Wrong initial gst_value_union_funcs table size. " + "Please set GST_VALUE_UNION_TABLE_DEFAULT_SIZE to %u in gstvalue.c", + gst_value_union_funcs->len); + } + if (gst_value_intersect_funcs->len > GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE) { + GST_ERROR ("Wrong initial gst_value_intersect_funcs table size. " + "Please set GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE to %u in gstvalue.c", + gst_value_intersect_funcs->len); + } + if (gst_value_subtract_funcs->len > GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE) { + GST_ERROR ("Wrong initial gst_value_subtract_funcs table size. " + "Please set GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE to %u in gstvalue.c", + gst_value_subtract_funcs->len); + } +#endif + +#if 0 + /* Implement these if needed */ + gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, + gst_value_union_fraction_fraction_range); + gst_value_register_union_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range); +#endif +} + +static void +gst_flagset_class_init (gpointer g_class, gpointer class_data) +{ + GstFlagSetClass *f_class = (GstFlagSetClass *) (g_class); + f_class->flags_type = (GType) GPOINTER_TO_SIZE (class_data); +} + +/** + * gst_flagset_register: + * @flags_type: a #GType of a #G_TYPE_FLAGS type. + * + * Create a new sub-class of #GST_TYPE_FLAG_SET + * which will pretty-print the human-readable flags + * when serializing, for easier debugging. + * + * Since: 1.6 + */ +GType +gst_flagset_register (GType flags_type) +{ + GTypeInfo info = { + sizeof (GstFlagSetClass), + NULL, NULL, + (GClassInitFunc) gst_flagset_class_init, + NULL, GSIZE_TO_POINTER (flags_type), 0, 0, NULL, NULL + }; + GType t; + gchar *class_name; + + g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0); + + class_name = g_strdup_printf ("%sSet", g_type_name (flags_type)); + + t = g_type_register_static (GST_TYPE_FLAG_SET, + g_intern_string (class_name), &info, 0); + g_free (class_name); + + return t; +} diff --git a/gst/gstvalue.h b/gst/gstvalue.h new file mode 100644 index 0000000..c44493c --- /dev/null +++ b/gst/gstvalue.h @@ -0,0 +1,728 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_VALUE_H__ +#define __GST_VALUE_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GST_MAKE_FOURCC: + * @a: the first character + * @b: the second character + * @c: the third character + * @d: the fourth character + * + * Transform four characters into a #guint32 fourcc value with host + * endianness. + * + * |[ + * guint32 fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G'); + * ]| + * + */ +#define GST_MAKE_FOURCC(a,b,c,d) \ + ( (guint32)(a) | ((guint32) (b)) << 8 | ((guint32) (c)) << 16 | ((guint32) (d)) << 24 ) + +/** + * GST_STR_FOURCC: + * @f: a string with at least four characters + * + * Transform an input string into a #guint32 fourcc value with host + * endianness. + * Caller is responsible for ensuring the input string consists of at least + * four characters. + * + * |[ + * guint32 fourcc = GST_STR_FOURCC ("MJPG"); + * ]| + * + */ +#define GST_STR_FOURCC(f) ((guint32)(((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24))) + +/** + * GST_FOURCC_FORMAT: + * + * Can be used together with #GST_FOURCC_ARGS to properly output a + * #guint32 fourcc value in a printf()-style text message. + * + * |[ + * printf ("fourcc: %" GST_FOURCC_FORMAT "\n", GST_FOURCC_ARGS (fcc)); + * ]| + * + */ +#define GST_FOURCC_FORMAT "c%c%c%c" + +/** + * GST_FOURCC_ARGS: + * @fourcc: a #guint32 fourcc value to output + * + * Can be used together with #GST_FOURCC_FORMAT to properly output a + * #guint32 fourcc value in a printf()-style text message. + */ + +#define __GST_PRINT_CHAR(c) \ + g_ascii_isprint(c) ? (c) : '.' +#define GST_FOURCC_ARGS(fourcc) \ + __GST_PRINT_CHAR((fourcc) & 0xff), \ + __GST_PRINT_CHAR(((fourcc) >> 8) & 0xff), \ + __GST_PRINT_CHAR(((fourcc) >> 16) & 0xff), \ + __GST_PRINT_CHAR(((fourcc) >> 24) & 0xff) +/** + * GST_VALUE_HOLDS_INT_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_INT_RANGE value. + */ +#define GST_VALUE_HOLDS_INT_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_int_range_type) + +/** + * GST_VALUE_HOLDS_INT64_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_INT64_RANGE value. + */ +#define GST_VALUE_HOLDS_INT64_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_int64_range_type) + +/** + * GST_VALUE_HOLDS_DOUBLE_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_DOUBLE_RANGE value. + */ +#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_double_range_type) + +/** + * GST_VALUE_HOLDS_FRACTION_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_FRACTION_RANGE value. + */ +#define GST_VALUE_HOLDS_FRACTION_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_range_type) + +/** + * GST_VALUE_HOLDS_LIST: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_LIST value. + */ +#define GST_VALUE_HOLDS_LIST(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_list_type) + +/** + * GST_VALUE_HOLDS_ARRAY: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_ARRAY value. + */ +#define GST_VALUE_HOLDS_ARRAY(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_array_type) + +/** + * GST_VALUE_HOLDS_CAPS: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_CAPS value. + */ +#define GST_VALUE_HOLDS_CAPS(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_caps_type) + +/** + * GST_VALUE_HOLDS_STRUCTURE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_STRUCTURE value. + */ +#define GST_VALUE_HOLDS_STRUCTURE(x) (G_VALUE_HOLDS((x), _gst_structure_type)) + +/** + * GST_VALUE_HOLDS_CAPS_FEATURES: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_CAPS_FEATURES value. + */ +#define GST_VALUE_HOLDS_CAPS_FEATURES(x) (G_VALUE_HOLDS((x), _gst_caps_features_type)) + +/** + * GST_VALUE_HOLDS_BUFFER: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_BUFFER value. + */ +#define GST_VALUE_HOLDS_BUFFER(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_buffer_type) + +/** + * GST_VALUE_HOLDS_SAMPLE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_SAMPLE value. + */ +#define GST_VALUE_HOLDS_SAMPLE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_sample_type) + +/** + * GST_VALUE_HOLDS_FRACTION: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_FRACTION value. + */ +#define GST_VALUE_HOLDS_FRACTION(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_type) + +/** + * GST_VALUE_HOLDS_DATE_TIME: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_DATE_TIME value. + */ +#define GST_VALUE_HOLDS_DATE_TIME(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_date_time_type) + +/** + * GST_VALUE_HOLDS_BITMASK: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_BITMASK value. + */ +#define GST_VALUE_HOLDS_BITMASK(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_bitmask_type) + +/** + * GST_VALUE_HOLDS_FLAG_SET: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_FLAG_SET value. + * + * Since: 1.6 + */ +#define GST_VALUE_HOLDS_FLAG_SET(x) (G_TYPE_CHECK_VALUE_TYPE ((x), GST_TYPE_FLAG_SET)) + +/** + * GST_FLAG_SET_MASK_EXACT: (value 4294967295) (type guint) + * + * A mask value with all bits set, for use as a + * GstFlagSet mask where all flag bits must match + * exactly + * + * Since: 1.6 + */ +#define GST_FLAG_SET_MASK_EXACT ((guint)(-1)) + +GST_API GType _gst_int_range_type; + +/** + * GST_TYPE_INT_RANGE: + * + * a #GValue type that represents an integer range + * + * Returns: the #GType of GstIntRange + */ +#define GST_TYPE_INT_RANGE (_gst_int_range_type) + +GST_API GType _gst_int64_range_type; + +/** + * GST_TYPE_INT64_RANGE: + * + * a #GValue type that represents an #gint64 range + * + * Returns: the #GType of GstInt64Range + */ +#define GST_TYPE_INT64_RANGE (_gst_int64_range_type) + +GST_API GType _gst_double_range_type; + +/** + * GST_TYPE_DOUBLE_RANGE: + * + * a #GValue type that represents a floating point range with double precision + * + * Returns: the #GType of GstIntRange + */ +#define GST_TYPE_DOUBLE_RANGE (_gst_double_range_type) + +GST_API GType _gst_fraction_range_type; + +/** + * GST_TYPE_FRACTION_RANGE: + * + * a #GValue type that represents a GstFraction range + * + * Returns: the #GType of GstFractionRange + */ +#define GST_TYPE_FRACTION_RANGE (_gst_fraction_range_type) + +GST_API GType _gst_value_list_type; + +/** + * GST_TYPE_LIST: + * + * a #GValue type that represents an unordered list of #GValue values. This + * is used for example to express a list of possible values for a field in + * a caps structure, like a list of possible sample rates, of which only one + * will be chosen in the end. This means that all values in the list are + * meaningful on their own. + * + * Returns: the #GType of GstValueList (which is not explicitly typed) + */ +#define GST_TYPE_LIST (_gst_value_list_type) + +GST_API GType _gst_value_array_type; + +/** + * GST_TYPE_ARRAY: + * + * a #GValue type that represents an ordered list of #GValue values. This is + * used to express a set of values that is meaningful only in their specific + * combination and order of values. Each value on its own is not particularly + * meaningful, only the ordered array in its entirety is meaningful. This is + * used for example to express channel layouts for multichannel audio where + * each channel needs to be mapped to a position in the room. + * + * Returns: the #GType of GstArrayList (which is not explicitly typed) + */ +#define GST_TYPE_ARRAY (_gst_value_array_type) + +GST_API GType _gst_fraction_type; + +/** + * GST_TYPE_FRACTION: + * + * a #GValue type that represents a fraction of an integer numerator over + * an integer denominator + * + * Returns: the #GType of GstFraction (which is not explicitly typed) + */ + +#define GST_TYPE_FRACTION (_gst_fraction_type) + +GST_API GType _gst_bitmask_type; + +/** + * GST_TYPE_BITMASK: + * + * a #GValue type that represents a 64-bit bitmask. + * + * Returns: the #GType of GstBitmask (which is not explicitly typed) + */ + +#define GST_TYPE_BITMASK (_gst_bitmask_type) + +GST_API GType _gst_flagset_type; + +/** + * GST_TYPE_FLAG_SET: + * + * a #GValue type that represents a 32-bit flag bitfield, with 32-bit + * mask indicating which of the bits in the field are explicitly set. + * Useful for negotiation. + * + * Returns: the #GType of GstFlags (which is not explicitly typed) + * + * Since: 1.6 + */ +#define GST_TYPE_FLAG_SET (_gst_flagset_type) + +/** + * GST_TYPE_G_THREAD: + * + * a boxed #GValue type for #GThread that represents a thread. + * + * Returns: the #GType of GstGThread + */ + +#define GST_TYPE_G_THREAD gst_g_thread_get_type () + +/** + * GST_VALUE_LESS_THAN: + * + * Indicates that the first value provided to a comparison function + * (gst_value_compare()) is lesser than the second one. + */ +#define GST_VALUE_LESS_THAN (-1) + +/** + * GST_VALUE_EQUAL: + * + * Indicates that the first value provided to a comparison function + * (gst_value_compare()) is equal to the second one. + */ +#define GST_VALUE_EQUAL 0 + +/** + * GST_VALUE_GREATER_THAN: + * + * Indicates that the first value provided to a comparison function + * (gst_value_compare()) is greater than the second one. + */ +#define GST_VALUE_GREATER_THAN 1 + +/** + * GST_VALUE_UNORDERED: + * + * Indicates that the comparison function (gst_value_compare()) can not + * determine a order for the two provided values. + */ +#define GST_VALUE_UNORDERED 2 + +/** + * GstValueCompareFunc: + * @value1: first value for comparison + * @value2: second value for comparison + * + * Used together with gst_value_compare() to compare #GValue items. + * + * Returns: one of GST_VALUE_LESS_THAN, GST_VALUE_EQUAL, GST_VALUE_GREATER_THAN + * or GST_VALUE_UNORDERED + */ +typedef gint (* GstValueCompareFunc) (const GValue *value1, + const GValue *value2); + +/** + * GstValueSerializeFunc: + * @value1: a #GValue + * + * Used by gst_value_serialize() to obtain a non-binary form of the #GValue. + * + * Free-function: g_free + * + * Returns: (transfer full): the string representation of the value + */ +typedef gchar * (* GstValueSerializeFunc) (const GValue *value1); + +/** + * GstValueDeserializeFunc: + * @dest: a #GValue + * @s: a string + * + * Used by gst_value_deserialize() to parse a non-binary form into the #GValue. + * + * Returns: %TRUE for success + */ +typedef gboolean (* GstValueDeserializeFunc) (GValue *dest, + const gchar *s); + +typedef struct _GstValueTable GstValueTable; +/** + * GstValueTable: + * @type: a #GType + * @compare: a #GstValueCompareFunc + * @serialize: a #GstValueSerializeFunc + * @deserialize: a #GstValueDeserializeFunc + * + * VTable for the #GValue @type. + */ +struct _GstValueTable { + GType type; + GstValueCompareFunc compare; + GstValueSerializeFunc serialize; + GstValueDeserializeFunc deserialize; + + /*< private >*/ + gpointer _gst_reserved [GST_PADDING]; +}; + +GST_API +GType gst_int_range_get_type (void); + +GST_API +GType gst_int64_range_get_type (void); + +GST_API +GType gst_double_range_get_type (void); + +GST_API +GType gst_fraction_range_get_type (void); + +GST_API +GType gst_fraction_get_type (void); + +GST_API +GType gst_value_list_get_type (void); + +GST_API +GType gst_value_array_get_type (void); + +GST_API +GType gst_bitmask_get_type (void); + +GST_API +GType gst_flagset_get_type (void); + +/* Hide this compatibility type from introspection */ +#ifndef __GI_SCANNER__ +GST_API +GType gst_g_thread_get_type (void); +#endif + +GST_API +void gst_value_register (const GstValueTable *table); + +GST_API +void gst_value_init_and_copy (GValue *dest, + const GValue *src); +GST_API +gchar * gst_value_serialize (const GValue *value) G_GNUC_MALLOC; + +GST_API +gboolean gst_value_deserialize (GValue *dest, + const gchar *src); + +/* list */ + +GST_API +void gst_value_list_append_value (GValue *value, + const GValue *append_value); +GST_API +void gst_value_list_append_and_take_value (GValue *value, + GValue *append_value); +GST_API +void gst_value_list_prepend_value (GValue *value, + const GValue *prepend_value); +GST_API +void gst_value_list_concat (GValue *dest, + const GValue *value1, + const GValue *value2); +GST_API +void gst_value_list_merge (GValue *dest, + const GValue *value1, + const GValue *value2); +GST_API +guint gst_value_list_get_size (const GValue *value); + +GST_API +const GValue * gst_value_list_get_value (const GValue *value, + guint index); + +/* array */ + +GST_API +void gst_value_array_append_value (GValue *value, + const GValue *append_value); +GST_API +void gst_value_array_append_and_take_value (GValue *value, + GValue *append_value); +GST_API +void gst_value_array_prepend_value (GValue *value, + const GValue *prepend_value); +GST_API +guint gst_value_array_get_size (const GValue *value); + +GST_API +const GValue * gst_value_array_get_value (const GValue *value, + guint index); + +/* int range */ + +GST_API +void gst_value_set_int_range (GValue *value, + gint start, + gint end); +GST_API +void gst_value_set_int_range_step (GValue *value, + gint start, + gint end, + gint step); +GST_API +gint gst_value_get_int_range_min (const GValue *value); + +GST_API +gint gst_value_get_int_range_max (const GValue *value); + +GST_API +gint gst_value_get_int_range_step (const GValue *value); + +/* int64 range */ + +GST_API +void gst_value_set_int64_range (GValue *value, + gint64 start, + gint64 end); +GST_API +void gst_value_set_int64_range_step (GValue *value, + gint64 start, + gint64 end, + gint64 step); +GST_API +gint64 gst_value_get_int64_range_min (const GValue *value); + +GST_API +gint64 gst_value_get_int64_range_max (const GValue *value); + +GST_API +gint64 gst_value_get_int64_range_step (const GValue *value); + +/* double range */ + +GST_API +void gst_value_set_double_range (GValue *value, + gdouble start, + gdouble end); +GST_API +gdouble gst_value_get_double_range_min (const GValue *value); + +GST_API +gdouble gst_value_get_double_range_max (const GValue *value); + +/* caps */ + +GST_API +const GstCaps * gst_value_get_caps (const GValue *value); + +GST_API +void gst_value_set_caps (GValue *value, + const GstCaps *caps); + +/* structure */ + +GST_API +const GstStructure * + gst_value_get_structure (const GValue *value); + +GST_API +void gst_value_set_structure (GValue *value, + const GstStructure *structure); + +/* caps features */ + +GST_API +const GstCapsFeatures * + gst_value_get_caps_features (const GValue *value); + +GST_API +void gst_value_set_caps_features (GValue *value, + const GstCapsFeatures *features); + +/* fraction */ + +GST_API +void gst_value_set_fraction (GValue *value, + gint numerator, + gint denominator); +GST_API +gint gst_value_get_fraction_numerator (const GValue *value); + +GST_API +gint gst_value_get_fraction_denominator (const GValue *value); + +GST_API +gboolean gst_value_fraction_multiply (GValue *product, + const GValue *factor1, + const GValue *factor2); +GST_API +gboolean gst_value_fraction_subtract (GValue * dest, + const GValue * minuend, + const GValue * subtrahend); + +/* fraction range */ + +GST_API +void gst_value_set_fraction_range (GValue *value, + const GValue *start, + const GValue *end); +GST_API +void gst_value_set_fraction_range_full (GValue *value, + gint numerator_start, + gint denominator_start, + gint numerator_end, + gint denominator_end); +GST_API +const GValue *gst_value_get_fraction_range_min (const GValue *value); + +GST_API +const GValue *gst_value_get_fraction_range_max (const GValue *value); + +/* bitmask */ + +GST_API +guint64 gst_value_get_bitmask (const GValue *value); + +GST_API +void gst_value_set_bitmask (GValue *value, + guint64 bitmask); +/* flagset */ + +GST_API +void gst_value_set_flagset (GValue * value, guint flags, guint mask); + +GST_API +guint gst_value_get_flagset_flags (const GValue * value); + +GST_API +guint gst_value_get_flagset_mask (const GValue * value); + +/* compare */ + +GST_API +gint gst_value_compare (const GValue *value1, + const GValue *value2); +GST_API +gboolean gst_value_can_compare (const GValue *value1, + const GValue *value2); +GST_API +gboolean gst_value_is_subset (const GValue *value1, + const GValue *value2); + +/* union */ + +GST_API +gboolean gst_value_union (GValue *dest, + const GValue *value1, + const GValue *value2); +GST_API +gboolean gst_value_can_union (const GValue *value1, + const GValue *value2); + +/* intersection */ + +GST_API +gboolean gst_value_intersect (GValue *dest, + const GValue *value1, + const GValue *value2); +GST_API +gboolean gst_value_can_intersect (const GValue *value1, + const GValue *value2); + +/* subtraction */ + +GST_API +gboolean gst_value_subtract (GValue *dest, + const GValue *minuend, + const GValue *subtrahend); +GST_API +gboolean gst_value_can_subtract (const GValue *minuend, + const GValue *subtrahend); + +/* fixation */ + +GST_API +gboolean gst_value_is_fixed (const GValue *value); + +GST_API +gboolean gst_value_fixate (GValue *dest, + const GValue *src); + +/* Flagset registration wrapper */ + +GST_API +GType gst_flagset_register (GType flags_type); + +G_END_DECLS + +#endif + + diff --git a/gst/gstversion.h.in b/gst/gstversion.h.in new file mode 100644 index 0000000..a74c2d1 --- /dev/null +++ b/gst/gstversion.h.in @@ -0,0 +1,91 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstversion.h: Version information for GStreamer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_VERSION_H__ +#define __GST_VERSION_H__ + +#include + +/** + * SECTION:gstversion + * @short_description: GStreamer version macros. + * + * Use the GST_VERSION_* macros e.g. when defining own plugins. The GStreamer + * runtime checks if these plugin and core version match and refuses to use a + * plugin compiled against a different version of GStreamer. + * You can also use the macros to keep the GStreamer version information in + * your application. + * + * Use the gst_version() function if you want to know which version of + * GStreamer you are currently linked against. + * + * The version macros get defined by including "gst/gst.h". + */ + +G_BEGIN_DECLS + +/** + * GST_VERSION_MAJOR: + * + * The major version of GStreamer at compile time: + */ +#define GST_VERSION_MAJOR (@GST_VERSION_MAJOR@) +/** + * GST_VERSION_MINOR: + * + * The minor version of GStreamer at compile time: + */ +#define GST_VERSION_MINOR (@GST_VERSION_MINOR@) +/** + * GST_VERSION_MICRO: + * + * The micro version of GStreamer at compile time: + */ +#define GST_VERSION_MICRO (@GST_VERSION_MICRO@) +/** + * GST_VERSION_NANO: + * + * The nano version of GStreamer at compile time: + * Actual releases have 0, GIT versions have 1, prerelease versions have 2-... + */ +#define GST_VERSION_NANO (@GST_VERSION_NANO@) + +/** + * GST_CHECK_VERSION: + * @major: a number indicating the major version + * @minor: a number indicating the minor version + * @micro: a number indicating the micro version + * + * Check whether a GStreamer version equal to or greater than + * major.minor.micro is present. + */ +#define GST_CHECK_VERSION(major,minor,micro) \ + (GST_VERSION_MAJOR > (major) || \ + (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR > (minor)) || \ + (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && \ + GST_VERSION_MICRO >= (micro)) || \ + (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && \ + GST_VERSION_MICRO + 1 == (micro) && GST_VERSION_NANO > 0)) + +G_END_DECLS + +#endif /* __GST_VERSION_H__ */ diff --git a/gst/math-compat.h b/gst/math-compat.h new file mode 100644 index 0000000..7573b3a --- /dev/null +++ b/gst/math-compat.h @@ -0,0 +1,112 @@ +/* GStreamer + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_MATH_COMPAT_H__ +#define __GST_MATH_COMPAT_H__ + +/* This header is not included automatically via gst/gst.h, you need to + * include it explicitly if you need it. */ + +#ifndef _USE_MATH_DEFINES +#define _USE_MATH_DEFINES /* so MSVC defines M_PI etc. */ +#endif +#include + +#include + +G_BEGIN_DECLS + +/* http://en.wikipedia.org/wiki/Math.h */ + +#define __GST_MATH_COMPAT_NEED_RINT +#define __GST_MATH_COMPAT_NEED_RINTF +#define __GST_MATH_COMPAT_NEED_ISNAN + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#undef __GST_MATH_COMPAT_NEED_RINT +#undef __GST_MATH_COMPAT_NEED_RINTF +#undef __GST_MATH_COMPAT_NEED_ISNAN +#endif + +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +#undef __GST_MATH_COMPAT_NEED_RINT +#undef __GST_MATH_COMPAT_NEED_RINTF +#undef __GST_MATH_COMPAT_NEED_ISNAN +#endif + +#ifndef M_PI +#define M_PI G_PI +#endif + +#ifndef M_PI_2 +#define M_PI_2 G_PI_2 +#endif + +#ifndef M_PI_4 +#define M_PI_4 G_PI_4 +#endif + +static inline double +__gst_math_compat_rint (double x) +{ + return floor (x + 0.5); +} + +static inline float +__gst_math_compat_rintf (float x) +{ + return floorf (x + 0.5); +} + +static inline gboolean +__gst_math_compat_isnan (double x) +{ + return x != x; +} + +#if defined (__GST_MATH_COMPAT_NEED_RINT) && !defined (rint) +#define rint(x) __gst_math_compat_rint(x) +#endif + +#if defined (__GST_MATH_COMPAT_NEED_RINTF) && !defined (rintf) +#define rintf(x) __gst_math_compat_rintf(x) +#endif + +#if defined (__GST_MATH_COMPAT_NEED_ISNAN) && !defined (isnan) +#define isnan(x) __gst_math_compat_isnan (x) +#endif + +#ifndef NAN +#if G_BYTE_ORDER == G_BIG_ENDIAN +#define __GST_NAN_BYTES { 0x7f, 0xc0, 0, 0 } +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN +#define __GST_NAN_BYTES { 0, 0, 0xc0, 0x7f } +#endif +static union { + unsigned char __c[4]; + float __d; +} __gst_nan_union G_GNUC_UNUSED = { + __GST_NAN_BYTES +}; +#define NAN (__gst_nan_union.__d) +#endif + +G_END_DECLS + +#endif /* __GST_MATH_COMPAT_H__ */ diff --git a/gst/meson.build b/gst/meson.build new file mode 100644 index 0000000..9225054 --- /dev/null +++ b/gst/meson.build @@ -0,0 +1,291 @@ +gst_sources = [ + 'gst.c', + 'gstobject.c', + 'gstallocator.c', + 'gstbin.c', + 'gstbuffer.c', + 'gstbufferlist.c', + 'gstbufferpool.c', + 'gstbus.c', + 'gstcaps.c', + 'gstcapsfeatures.c', + 'gstchildproxy.c', + 'gstclock.c', + 'gstcontext.c', + 'gstcontrolbinding.c', + 'gstcontrolsource.c', + 'gstdatetime.c', + 'gstdebugutils.c', + 'gstdevice.c', + 'gstdeviceprovider.c', + 'gstdeviceproviderfactory.c', + 'gstdynamictypefactory.c', + 'gstelement.c', + 'gstelementfactory.c', + 'gsterror.c', + 'gstevent.c', + 'gstformat.c', + 'gstghostpad.c', + 'gstdevicemonitor.c', + 'gstinfo.c', + 'gstiterator.c', + 'gstatomicqueue.c', + 'gstmessage.c', + 'gstmeta.c', + 'gstmemory.c', + 'gstminiobject.c', + 'gstpad.c', + 'gstpadtemplate.c', + 'gstparamspecs.c', + 'gstpipeline.c', + 'gstplugin.c', + 'gstpluginfeature.c', + 'gstpluginloader.c', + 'gstpoll.c', + 'gstpreset.c', + 'gstprotection.c', + 'gstquark.c', + 'gstquery.c', + 'gstregistry.c', + 'gstregistrychunks.c', + 'gstpromise.c', + 'gstsample.c', + 'gstsegment.c', + 'gststreamcollection.c', + 'gststreams.c', + 'gststructure.c', + 'gstsystemclock.c', + 'gsttaglist.c', + 'gsttagsetter.c', + 'gsttask.c', + 'gsttaskpool.c', + 'gsttoc.c', + 'gsttocsetter.c', + 'gsttracer.c', + 'gsttracerfactory.c', + 'gsttracerrecord.c', + 'gsttracerutils.c', + 'gsttypefind.c', + 'gsttypefindfactory.c', + 'gsturi.c', + 'gstutils.c', + 'gstvalue.c', + 'gstparse.c', +] + +gst_headers = [ + 'gst.h', + 'glib-compat.h', + 'gstobject.h', + 'gstallocator.h', + 'gstbin.h', + 'gstbuffer.h', + 'gstbufferlist.h', + 'gstbufferpool.h', + 'gstbus.h', + 'gstcaps.h', + 'gstcapsfeatures.h', + 'gstchildproxy.h', + 'gstclock.h', + 'gstcompat.h', + 'gstcontext.h', + 'gstcontrolbinding.h', + 'gstcontrolsource.h', + 'gstdatetime.h', + 'gstdebugutils.h', + 'gstelement.h', + 'gstelementmetadata.h', + 'gstdevice.h', + 'gstdeviceprovider.h', + 'gstdeviceproviderfactory.h', + 'gstdynamictypefactory.h', + 'gstelementfactory.h', + 'gsterror.h', + 'gstevent.h', + 'gstformat.h', + 'gstghostpad.h', + 'gstdevicemonitor.h', + 'gstinfo.h', + 'gstiterator.h', + 'gstatomicqueue.h', + 'gstmacros.h', + 'gstmessage.h', + 'gstmeta.h', + 'gstmemory.h', + 'gstminiobject.h', + 'gstpad.h', + 'gstpadtemplate.h', + 'gstparamspecs.h', + 'gstpipeline.h', + 'gstplugin.h', + 'gstpluginfeature.h', + 'gstpoll.h', + 'gstpreset.h', + 'gstprotection.h', + 'gstquery.h', + 'gstpromise.h', + 'gstsample.h', + 'gstsegment.h', + 'gststreamcollection.h', + 'gststreams.h', + 'gststructure.h', + 'gstsystemclock.h', + 'gsttaglist.h', + 'gsttagsetter.h', + 'gsttask.h', + 'gsttaskpool.h', + 'gsttoc.h', + 'gsttocsetter.h', + 'gsttracer.h', + 'gsttracerfactory.h', + 'gsttracerrecord.h', + 'gsttypefind.h', + 'gsttypefindfactory.h', + 'gsturi.h', + 'gstutils.h', + 'gstvalue.h', + 'gstregistry.h', + 'gstparse.h', + 'math-compat.h', +] +install_headers(gst_headers, subdir : 'gstreamer-1.0/gst') + +disable_registry = get_option('disable_registry') +if not disable_registry + gst_registry = ['gstregistrybinary.c'] +else + gst_registry = [] +endif + +# Make copy so configure_file consumes the copy and we can +# still add to the original cdata later. +gst_cdata = cdata + +if disable_gst_debug + gst_cdata.set('GST_DISABLE_GST_DEBUG_DEFINE', '#define GST_DISABLE_GST_DEBUG 1') +else + gst_cdata.set('GST_DISABLE_GST_DEBUG_DEFINE', '#undef GST_DISABLE_GST_DEBUG') +endif + +if disable_registry + gst_cdata.set('GST_DISABLE_REGISTRY_DEFINE', '#define GST_DISABLE_REGISTRY 1') +else + gst_cdata.set('GST_DISABLE_REGISTRY_DEFINE', '#undef GST_DISABLE_REGISTRY') +endif + +# FIXME: add --disable-parse option? (but autotools doesn't seem to set this +# define properly at all either even though it does expose the option) +gst_cdata.set('GST_DISABLE_PARSE_DEFINE', '#undef GST_DISABLE_PARSE') + +# FIXME: add --disable-plugin option? +gst_cdata.set('GST_DISABLE_PLUGIN_DEFINE', '#undef GST_DISABLE_PLUGIN') + +configure_file(input : 'gstconfig.h.in', + output : 'gstconfig.h', + install_dir : 'include/gstreamer-1.0/gst', + configuration : gst_cdata) + +version_cdata = configuration_data() +version_cdata.set('GST_VERSION_MAJOR', gst_version_major) +version_cdata.set('GST_VERSION_MINOR', gst_version_minor) +version_cdata.set('GST_VERSION_MICRO', gst_version_micro) +version_cdata.set('GST_VERSION_NANO', gst_version_nano) + +gst_version_h = configure_file(input : 'gstversion.h.in', + output : 'gstversion.h', + install_dir : 'include/gstreamer-1.0/gst', + configuration : version_cdata) + +gst_enums = gnome.mkenums('gstenumtypes', + sources : gst_headers, + h_template : 'gstenumtypes.h.template', + c_template : 'gstenumtypes.c.template', + install_header : true, + install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst')) + +gstenum_h = gst_enums[1] +gstenum_c = gst_enums[0] + + +subdir('parse') +subdir('printf') + +libgst_c_args = gst_c_args + [ + '-D_GNU_SOURCE', + '-DGST_EXPORTS', + '-DG_LOG_DOMAIN=g_log_domain_gstreamer', + '-DGST_DISABLE_DEPRECATED', +] + +disable_tracer_hooks = get_option('disable_tracer_hooks') +if disable_tracer_hooks + libgst_c_args += ['-DGST_DISABLE_GST_TRACER_HOOKS'] +endif + +# Make it possible to build both static and shared versions +# at the same time. By default use shared for unit tests etc. +# This choice is arbitrary. +if libtype != 'shared' + libgst_static = static_library('gstreamer-1.0', gst_sources, + gstenum_h, gstenum_c, grammar, parser, gst_registry, + c_args : [libgst_c_args], + include_directories : [configinc, + # HACK, change include paths in .y and .l in final version. + include_directories('parse')], + install : true, + link_with : printf_lib, + dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib] + backtrace_deps + platform_deps, + ) + libgst = libgst_static +endif + +# Make sure that subproject building gir files work +gst_incdirs = [configinc] +gst_gen_sources = [gstenum_h] +if libtype != 'static' + libgst_shared = shared_library('gstreamer-1.0', gst_sources, + gstenum_h, gstenum_c, grammar, parser, gst_registry, + version : libversion, + soversion : soversion, + c_args : libgst_c_args, + include_directories : [configinc, + # HACK, change include paths in .y and .l in final version. + include_directories('parse')], + link_with : printf_lib, + install : true, + dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib, dl_dep] + backtrace_deps + + platform_deps, + ) + libgst = libgst_shared + if build_gir + gst_gir_extra_args = gir_init_section + [ '--c-include=gst/gst.h' ] + if meson.is_subproject() + # FIXME: There must be a better way to do this + # Need to pass the include path to find gst/gst.h and gst/gstenumtypes.h (built) + gst_gir_extra_args += ['--cflags-begin', + '-I' + meson.current_source_dir() + '/..', + '-I' + meson.current_build_dir() + '/..', + '--cflags-end'] + endif + + gst_incdirs += [configinc] + gst_gen_sources += [gnome.generate_gir(libgst_shared, + sources : gst_sources + gst_headers + gst_enums + [gst_version_h], + namespace : 'Gst', + nsversion : apiversion, + identifier_prefix : 'Gst', + symbol_prefix : 'gst', + export_packages : 'gstreamer-1.0', + includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0' ], + install : true, + extra_args : gst_gir_extra_args, + )] + endif +endif + +gst_dep = declare_dependency(link_with : libgst, + include_directories : gst_incdirs, + dependencies : [glib_dep, gobject_dep, gmodule_dep], + # Everything that uses libgst needs this built to compile + sources : gst_gen_sources, +) diff --git a/gst/parse/Makefile.am b/gst/parse/Makefile.am new file mode 100644 index 0000000..844349a --- /dev/null +++ b/gst/parse/Makefile.am @@ -0,0 +1,46 @@ +# libgstparse.la is an optionally built helper library linked into core +noinst_LTLIBRARIES = libgstparse.la + +CLEANFILES = grammar.tab.h parse_lex.h grammar.output +EXTRA_DIST = \ + grammar.y \ + parse.l + +# uncomment these lines to dist the generated sources +#BUILT_SOURCES = grammar.tab.h grammar.tab.c parse_lex.h lex.priv_gst_parse_yy.c +#libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c + +# uncomment these lines to _NOT_ dist the generated sources +nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tag.h parse_lex.h +CLEANFILES += grammar.tab.c lex.priv_gst_parse_yy.c + +libgstparse_la_CFLAGS = $(GST_ALL_CFLAGS) -DGST_EXPORTS -DYYMALLOC=g_malloc -DYYFREE=g_free +libgstparse_la_LIBADD = $(GST_ALL_LIBS) + +noinst_HEADERS = types.h + +grammar.tab.c grammar.tab.h: grammar.y + $(AM_V_GEN)$(BISON_PATH) -d -v -ppriv_gst_parse_yy $(srcdir)/grammar.y -o grammar.tab.c && \ + mv grammar.tab.c grammar.tab_tmp.c && \ + echo '#ifdef HAVE_CONFIG_H' > grammar.tab_tmp2.c && \ + echo '#include ' >> grammar.tab_tmp2.c && \ + echo '#endif' >> grammar.tab_tmp2.c && \ + cat grammar.tab_tmp.c >> grammar.tab_tmp2.c && \ + rm grammar.tab_tmp.c && \ + mv grammar.tab_tmp2.c grammar.tab.c + +lex.priv_gst_parse_yy.c parse_lex.h: parse.l grammar.tab.h + $(AM_V_GEN)$(FLEX_PATH) --header-file=parse_lex.h -Ppriv_gst_parse_yy $^ && \ + mv lex.priv_gst_parse_yy.c lex.priv_gst_parse_yy_tmp.c && \ + echo '#ifdef HAVE_CONFIG_H' > lex.priv_gst_parse_yy_tmp2.c && \ + echo '#include ' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo '#endif' >> lex.priv_gst_parse_yy_tmp2.c && \ + { grep -q priv_gst_parse_yyget_column parse_lex.h || \ + { echo 'int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo 'void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c; }; } && \ + cat lex.priv_gst_parse_yy_tmp.c >> lex.priv_gst_parse_yy_tmp2.c && \ + rm lex.priv_gst_parse_yy_tmp.c && \ + mv lex.priv_gst_parse_yy_tmp2.c lex.priv_gst_parse_yy.c + +.NOTPARALLEL: + diff --git a/gst/parse/Makefile.in b/gst/parse/Makefile.in new file mode 100644 index 0000000..8636782 --- /dev/null +++ b/gst/parse/Makefile.in @@ -0,0 +1,850 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = gst/parse +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgstparse_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +nodist_libgstparse_la_OBJECTS = \ + libgstparse_la-lex.priv_gst_parse_yy.lo \ + libgstparse_la-grammar.tab.lo +libgstparse_la_OBJECTS = $(nodist_libgstparse_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstparse_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstparse_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(nodist_libgstparse_la_SOURCES) +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# libgstparse.la is an optionally built helper library linked into core +noinst_LTLIBRARIES = libgstparse.la +CLEANFILES = grammar.tab.h parse_lex.h grammar.output grammar.tab.c \ + lex.priv_gst_parse_yy.c +EXTRA_DIST = \ + grammar.y \ + parse.l + + +# uncomment these lines to dist the generated sources +#BUILT_SOURCES = grammar.tab.h grammar.tab.c parse_lex.h lex.priv_gst_parse_yy.c +#libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c + +# uncomment these lines to _NOT_ dist the generated sources +nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tag.h parse_lex.h +libgstparse_la_CFLAGS = $(GST_ALL_CFLAGS) -DGST_EXPORTS -DYYMALLOC=g_malloc -DYYFREE=g_free +libgstparse_la_LIBADD = $(GST_ALL_LIBS) +noinst_HEADERS = types.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/parse/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/parse/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstparse.la: $(libgstparse_la_OBJECTS) $(libgstparse_la_DEPENDENCIES) $(EXTRA_libgstparse_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstparse_la_LINK) $(libgstparse_la_OBJECTS) $(libgstparse_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstparse_la-grammar.tab.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstparse_la-lex.priv_gst_parse_yy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstparse_la-lex.priv_gst_parse_yy.lo: lex.priv_gst_parse_yy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstparse_la_CFLAGS) $(CFLAGS) -MT libgstparse_la-lex.priv_gst_parse_yy.lo -MD -MP -MF $(DEPDIR)/libgstparse_la-lex.priv_gst_parse_yy.Tpo -c -o libgstparse_la-lex.priv_gst_parse_yy.lo `test -f 'lex.priv_gst_parse_yy.c' || echo '$(srcdir)/'`lex.priv_gst_parse_yy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstparse_la-lex.priv_gst_parse_yy.Tpo $(DEPDIR)/libgstparse_la-lex.priv_gst_parse_yy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lex.priv_gst_parse_yy.c' object='libgstparse_la-lex.priv_gst_parse_yy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstparse_la_CFLAGS) $(CFLAGS) -c -o libgstparse_la-lex.priv_gst_parse_yy.lo `test -f 'lex.priv_gst_parse_yy.c' || echo '$(srcdir)/'`lex.priv_gst_parse_yy.c + +libgstparse_la-grammar.tab.lo: grammar.tab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstparse_la_CFLAGS) $(CFLAGS) -MT libgstparse_la-grammar.tab.lo -MD -MP -MF $(DEPDIR)/libgstparse_la-grammar.tab.Tpo -c -o libgstparse_la-grammar.tab.lo `test -f 'grammar.tab.c' || echo '$(srcdir)/'`grammar.tab.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstparse_la-grammar.tab.Tpo $(DEPDIR)/libgstparse_la-grammar.tab.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='grammar.tab.c' object='libgstparse_la-grammar.tab.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstparse_la_CFLAGS) $(CFLAGS) -c -o libgstparse_la-grammar.tab.lo `test -f 'grammar.tab.c' || echo '$(srcdir)/'`grammar.tab.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +grammar.tab.c grammar.tab.h: grammar.y + $(AM_V_GEN)$(BISON_PATH) -d -v -ppriv_gst_parse_yy $(srcdir)/grammar.y -o grammar.tab.c && \ + mv grammar.tab.c grammar.tab_tmp.c && \ + echo '#ifdef HAVE_CONFIG_H' > grammar.tab_tmp2.c && \ + echo '#include ' >> grammar.tab_tmp2.c && \ + echo '#endif' >> grammar.tab_tmp2.c && \ + cat grammar.tab_tmp.c >> grammar.tab_tmp2.c && \ + rm grammar.tab_tmp.c && \ + mv grammar.tab_tmp2.c grammar.tab.c + +lex.priv_gst_parse_yy.c parse_lex.h: parse.l grammar.tab.h + $(AM_V_GEN)$(FLEX_PATH) --header-file=parse_lex.h -Ppriv_gst_parse_yy $^ && \ + mv lex.priv_gst_parse_yy.c lex.priv_gst_parse_yy_tmp.c && \ + echo '#ifdef HAVE_CONFIG_H' > lex.priv_gst_parse_yy_tmp2.c && \ + echo '#include ' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo '#endif' >> lex.priv_gst_parse_yy_tmp2.c && \ + { grep -q priv_gst_parse_yyget_column parse_lex.h || \ + { echo 'int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo 'void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c; }; } && \ + cat lex.priv_gst_parse_yy_tmp.c >> lex.priv_gst_parse_yy_tmp2.c && \ + rm lex.priv_gst_parse_yy_tmp.c && \ + mv lex.priv_gst_parse_yy_tmp2.c lex.priv_gst_parse_yy.c + +.NOTPARALLEL: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/parse/gen_grammar.py.in b/gst/parse/gen_grammar.py.in new file mode 100755 index 0000000..3a7af00 --- /dev/null +++ b/gst/parse/gen_grammar.py.in @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +import subprocess, sys, shlex + +cfile = sys.argv[1] +hfile = sys.argv[2] +yfile = sys.argv[3] + +args = ['-d', '-v', '-ppriv_gst_parse_yy', yfile, '-o', cfile] +bison = [r'@BISON@'] + shlex.split(r'@BISON_ARGS@') +subprocess.check_call(bison + args) + +prefix = ''' +#ifdef HAVE_CONFIG_H +#include +#endif +''' + +contents = open(cfile).read() +content = prefix + contents +open(cfile, 'w').write(contents) diff --git a/gst/parse/gen_lex.py.in b/gst/parse/gen_lex.py.in new file mode 100755 index 0000000..e8c6844 --- /dev/null +++ b/gst/parse/gen_lex.py.in @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +import subprocess, sys, shlex + +cfile = sys.argv[1] +hfile = sys.argv[2] +lfile = sys.argv[3] +tabhfile = sys.argv[4] + +args = ['--header-file=' + hfile, '-o', cfile, '-Ppriv_gst_parse_yy', lfile] +flex = [r'@FLEX@'] + shlex.split(r'@FLEX_ARGS@') +subprocess.check_call(flex + args) + +prefix = '''#ifdef HAVE_CONFIG_H +#include +#endif +''' +parse_snippet = '''void priv_gst_parse_yyset_column (int column_no , void * yyscanner); +void priv_gst_parse_yyset_column (int column_no , void * yyscanner) +''' + +contents = open(cfile).read() +if not 'priv_gst_parse_yyget_column' in contents: + contents = parse_snippet + contents +contents = prefix + contents + +open(cfile, 'w').write(contents) diff --git a/gst/parse/grammar.y b/gst/parse/grammar.y new file mode 100644 index 0000000..65492ba --- /dev/null +++ b/gst/parse/grammar.y @@ -0,0 +1,1297 @@ +%{ +#include "../gst_private.h" + +#include +#include +#include +#include +#include + +#include "../gst-i18n-lib.h" + +#include "../gstconfig.h" +#include "../gstparse.h" +#include "../gstinfo.h" +#include "../gsterror.h" +#include "../gststructure.h" +#include "../gsturi.h" +#include "../gstutils.h" +#include "../gstvalue.h" +#include "../gstchildproxy.h" +#include "types.h" + +/* All error messages in this file are user-visible and need to be translated. + * Don't start the message with a capital, and don't end them with a period, + * as they will be presented inside a sentence/error. + */ + +#define YYERROR_VERBOSE 1 + +#define YYENABLE_NLS 0 + +#ifndef YYLTYPE_IS_TRIVIAL +#define YYLTYPE_IS_TRIVIAL 0 +#endif + +/******************************************************************************************* +*** Tracing memory leaks +*******************************************************************************************/ + +#ifdef __GST_PARSE_TRACE +static guint __strings; +static guint __links; +static guint __chains; +gchar * +__gst_parse_strdup (gchar *org) +{ + gchar *ret; + __strings++; + ret = g_strdup (org); + /* g_print ("ALLOCATED STR (%3u): %p %s\n", __strings, ret, ret); */ + return ret; +} +void +__gst_parse_strfree (gchar *str) +{ + if (str) { + /* g_print ("FREEING STR (%3u): %p %s\n", __strings - 1, str, str); */ + g_free (str); + g_return_if_fail (__strings > 0); + __strings--; + } +} +link_t *__gst_parse_link_new (void) +{ + link_t *ret; + __links++; + ret = g_slice_new0 (link_t); + /* g_print ("ALLOCATED LINK (%3u): %p\n", __links, ret); */ + return ret; +} +void +__gst_parse_link_free (link_t *data) +{ + if (data) { + /* g_print ("FREEING LINK (%3u): %p\n", __links - 1, data); */ + g_slice_free (link_t, data); + g_return_if_fail (__links > 0); + __links--; + } +} +chain_t * +__gst_parse_chain_new (void) +{ + chain_t *ret; + __chains++; + ret = g_slice_new0 (chain_t); + /* g_print ("@%p: ALLOCATED CHAIN (%3u):\n", ret, __chains); */ + return ret; +} +void +__gst_parse_chain_free (chain_t *data) +{ + /* g_print ("@%p: FREEING CHAIN (%3u):\n", data, __chains - 1); */ + g_slice_free (chain_t, data); + g_return_if_fail (__chains > 0); + __chains--; +} + +#endif /* __GST_PARSE_TRACE */ + +/******************************************************************************************* +*** define SET_ERROR macro/function +*******************************************************************************************/ +#ifdef G_HAVE_ISO_VARARGS + +# define SET_ERROR(error, type, ...) \ +G_STMT_START { \ + GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \ + if ((error) && !*(error)) { \ + g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \ + } \ +} G_STMT_END + +#elif defined(G_HAVE_GNUC_VARARGS) + +# define SET_ERROR(error, type, args...) \ +G_STMT_START { \ + GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \ + if ((error) && !*(error)) { \ + g_set_error ((error), GST_PARSE_ERROR, (type), args ); \ + } \ +} G_STMT_END + +#else + +static inline void +SET_ERROR (GError **error, gint type, const char *format, ...) +{ + if (error) { + if (*error) { + g_warning ("error while parsing"); + } else { + va_list varargs; + char *string; + + va_start (varargs, format); + string = g_strdup_vprintf (format, varargs); + va_end (varargs); + + g_set_error (error, GST_PARSE_ERROR, type, string); + + g_free (string); + } + } +} + +#endif /* G_HAVE_ISO_VARARGS */ + +/*** define YYPRINTF macro/function if we're debugging */ + +/* bison 1.35 calls this macro with side effects, we need to make sure the + side effects work - crappy bison */ + +#ifndef GST_DISABLE_GST_DEBUG +# define YYDEBUG 1 + +# ifdef G_HAVE_ISO_VARARGS + +/* # define YYFPRINTF(a, ...) GST_CAT_DEBUG (GST_CAT_PIPELINE, __VA_ARGS__) */ +# define YYFPRINTF(a, ...) \ +G_STMT_START { \ + GST_CAT_LOG (GST_CAT_PIPELINE, __VA_ARGS__); \ +} G_STMT_END + +# elif defined(G_HAVE_GNUC_VARARGS) + +# define YYFPRINTF(a, args...) \ +G_STMT_START { \ + GST_CAT_LOG (GST_CAT_PIPELINE, args); \ +} G_STMT_END + +# else + +static inline void +YYPRINTF(const char *format, ...) +{ + va_list varargs; + gchar *temp; + + va_start (varargs, format); + temp = g_strdup_vprintf (format, varargs); + GST_CAT_LOG (GST_CAT_PIPELINE, "%s", temp); + g_free (temp); + va_end (varargs); +} + +# endif /* G_HAVE_ISO_VARARGS */ + +#endif /* GST_DISABLE_GST_DEBUG */ + + +/* + * include headers generated by bison & flex, after defining (or not defining) YYDEBUG + */ +#include "grammar.tab.h" +#include "parse_lex.h" + +/******************************************************************************************* +*** report missing elements/bins/.. +*******************************************************************************************/ + + +static void add_missing_element(graph_t *graph,gchar *name){ + if ((graph)->ctx){ + (graph)->ctx->missing_elements = g_list_append ((graph)->ctx->missing_elements, g_strdup (name)); + } +} + + +/******************************************************************************************* +*** helpers for pipeline-setup +*******************************************************************************************/ + +#define TRY_SETUP_LINK(l) G_STMT_START { \ + if( (!(l)->src.element) && (!(l)->src.name) ){ \ + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no source [sink=%s@%p]"), \ + (l)->sink.name ? (l)->sink.name : "", \ + (l)->sink.element); \ + gst_parse_free_link (l); \ + }else if( (!(l)->sink.element) && (!(l)->sink.name) ){ \ + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no sink [source=%s@%p]"), \ + (l)->src.name ? (l)->src.name : "", \ + (l)->src.element); \ + gst_parse_free_link (l); \ + }else{ \ + graph->links = g_slist_append (graph->links, l ); \ + } \ +} G_STMT_END + +typedef struct { + gchar *src_pad; + gchar *sink_pad; + GstElement *sink; + GstCaps *caps; + gulong pad_added_signal_id, no_more_pads_signal_id; + gboolean all_pads; +} DelayedLink; + +typedef struct { + gchar *name; + gchar *value_str; + gulong signal_id; +} DelayedSet; + +static int gst_resolve_reference(reference_t *rr, GstElement *pipeline){ + GstBin *bin; + + if(rr->element) return 0; /* already resolved! */ + if(!rr->name) return -2; /* no chance! */ + + if (GST_IS_BIN (pipeline)){ + bin = GST_BIN (pipeline); + rr->element = gst_bin_get_by_name_recurse_up (bin, rr->name); + } else { + rr->element = strcmp (GST_ELEMENT_NAME (pipeline), rr->name) == 0 ? + gst_object_ref(pipeline) : NULL; + } + if(rr->element) return 0; /* resolved */ + else return -1; /* not found */ +} + +static void gst_parse_free_delayed_set (DelayedSet *set) +{ + g_free(set->name); + g_free(set->value_str); + g_slice_free(DelayedSet, set); +} + +static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object, + const gchar * name, gpointer data); + +static void gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str) +{ + DelayedSet *data = g_slice_new0 (DelayedSet); + + GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, element, "delaying property set %s to %s", + name, value_str); + + data->name = g_strdup(name); + data->value_str = g_strdup(value_str); + data->signal_id = g_signal_connect_data(element, "child-added", + G_CALLBACK (gst_parse_new_child), data, (GClosureNotify) + gst_parse_free_delayed_set, (GConnectFlags) 0); + + /* FIXME: we would need to listen on all intermediate bins too */ + if (GST_IS_BIN (element)) { + gchar **names, **current; + GstElement *parent, *child; + + current = names = g_strsplit (name, "::", -1); + parent = gst_bin_get_by_name (GST_BIN_CAST (element), current[0]); + current++; + while (parent && current[0]) { + child = gst_bin_get_by_name (GST_BIN (parent), current[0]); + if (!child && current[1]) { + char *sub_name = g_strjoinv ("::", ¤t[0]); + + gst_parse_add_delayed_set(parent, sub_name, value_str); + g_free (sub_name); + } + gst_object_unref (parent); + parent = child; + current++; + } + if (parent) + gst_object_unref (parent); + g_strfreev (names); + } +} + +static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object, + const gchar * name, gpointer data) +{ + DelayedSet *set = (DelayedSet *) data; + GParamSpec *pspec; + GValue v = { 0, }; + GObject *target = NULL; + GType value_type; + + GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, child_proxy, "new child %s, checking property %s", + name, set->name); + + if (gst_child_proxy_lookup (child_proxy, set->name, &target, &pspec)) { + gboolean got_value = FALSE; + + value_type = pspec->value_type; + + GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, child_proxy, "parsing delayed property %s as a %s from %s", + pspec->name, g_type_name (value_type), set->value_str); + g_value_init (&v, value_type); + if (gst_value_deserialize (&v, set->value_str)) + got_value = TRUE; + else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) { + GstElement *bin; + + bin = gst_parse_bin_from_description_full (set->value_str, TRUE, NULL, + GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN, NULL); + if (bin) { + g_value_set_object (&v, bin); + got_value = TRUE; + } + } + g_signal_handler_disconnect (child_proxy, set->signal_id); + if (!got_value) + goto error; + g_object_set_property (target, pspec->name, &v); + } else { + const gchar *obj_name = GST_OBJECT_NAME(object); + gint len = strlen (obj_name); + + /* do a delayed set */ + if ((strlen (set->name) > (len + 2)) && !strncmp (set->name, obj_name, len) && !strncmp (&set->name[len], "::", 2)) { + gst_parse_add_delayed_set (GST_ELEMENT(child_proxy), set->name, set->value_str); + } + } + +out: + if (G_IS_VALUE (&v)) + g_value_unset (&v); + if (target) + g_object_unref (target); + return; + +error: + GST_CAT_ERROR (GST_CAT_PIPELINE, "could not set property \"%s\" in %" + GST_PTR_FORMAT, pspec->name, target); + goto out; +} + +static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph) +{ + GParamSpec *pspec = NULL; + gchar *pos = value; + GValue v = { 0, }; + GObject *target = NULL; + GType value_type; + + /* do nothing if assignment is for missing element */ + if (element == NULL) + goto out; + + /* parse the string, so the property name is null-terminated and pos points + to the beginning of the value */ + while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++; + if (*pos == '=') { + *pos = '\0'; + } else { + *pos = '\0'; + pos++; + while (g_ascii_isspace (*pos)) pos++; + } + pos++; + while (g_ascii_isspace (*pos)) pos++; + /* truncate a string if it is delimited with double quotes */ + if (*pos == '"' && pos[strlen (pos) - 1] == '"') { + pos++; + pos[strlen (pos) - 1] = '\0'; + } + gst_parse_unescape (pos); + + if (GST_IS_CHILD_PROXY (element)) { + if (!gst_child_proxy_lookup (GST_CHILD_PROXY (element), value, &target, &pspec)) { + /* do a delayed set */ + gst_parse_add_delayed_set (element, value, pos); + } + } else { + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value); + if (pspec != NULL) { + target = G_OBJECT (g_object_ref (element)); + GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, target, "found %s property", value); + } else { + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \ + _("no property \"%s\" in element \"%s\""), value, \ + GST_ELEMENT_NAME (element)); + } + } + + if (pspec != NULL && target != NULL) { + gboolean got_value = FALSE; + + value_type = pspec->value_type; + + GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, element, "parsing property %s as a %s", + pspec->name, g_type_name (value_type)); + + g_value_init (&v, value_type); + if (gst_value_deserialize (&v, pos)) + got_value = TRUE; + else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) { + GstElement *bin; + + bin = gst_parse_bin_from_description_full (pos, TRUE, NULL, + GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN, NULL); + if (bin) { + g_value_set_object (&v, bin); + got_value = TRUE; + } + } + if (!got_value) + goto error; + g_object_set_property (target, pspec->name, &v); + } + +out: + gst_parse_strfree (value); + if (G_IS_VALUE (&v)) + g_value_unset (&v); + if (target) + g_object_unref (target); + return; + +error: + SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY, + _("could not set property \"%s\" in element \"%s\" to \"%s\""), + value, GST_ELEMENT_NAME (element), pos); + goto out; +} + +static void gst_parse_free_reference (reference_t *rr) +{ + if(rr->element) gst_object_unref(rr->element); + gst_parse_strfree (rr->name); + g_slist_foreach (rr->pads, (GFunc) gst_parse_strfree, NULL); + g_slist_free (rr->pads); +} + +static void gst_parse_free_link (link_t *link) +{ + gst_parse_free_reference (&(link->src)); + gst_parse_free_reference (&(link->sink)); + if (link->caps) gst_caps_unref (link->caps); + gst_parse_link_free (link); +} + +static void gst_parse_free_chain (chain_t *ch) +{ + GSList *walk; + gst_parse_free_reference (&(ch->first)); + gst_parse_free_reference (&(ch->last)); + for(walk=ch->elements;walk;walk=walk->next) + gst_object_unref (walk->data); + g_slist_free (ch->elements); + gst_parse_chain_free (ch); +} + +static void gst_parse_free_delayed_link (DelayedLink *link) +{ + g_free (link->src_pad); + g_free (link->sink_pad); + if (link->caps) gst_caps_unref (link->caps); + g_slice_free (DelayedLink, link); +} + +#define PRETTY_PAD_NAME_FMT "%s %s of %s named %s" +#define PRETTY_PAD_NAME_ARGS(elem, pad_name) \ + (pad_name ? "pad " : "some"), (pad_name ? pad_name : "pad"), \ + G_OBJECT_TYPE_NAME(elem), GST_STR_NULL (GST_ELEMENT_NAME (elem)) + +static void gst_parse_no_more_pads (GstElement *src, gpointer data) +{ + DelayedLink *link = data; + + /* Don't warn for all-pads links, as we expect those to + * still be active at no-more-pads */ + if (!link->all_pads) { + GST_ELEMENT_WARNING(src, PARSE, DELAYED_LINK, + (_("Delayed linking failed.")), + ("failed delayed linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT, + PRETTY_PAD_NAME_ARGS (src, link->src_pad), + PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad))); + } + /* we keep the handlers connected, so that in case an element still adds a pad + * despite no-more-pads, we will consider it for pending delayed links */ +} + +static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data) +{ + DelayedLink *link = data; + + GST_CAT_INFO (GST_CAT_PIPELINE, + "trying delayed linking %s " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT, + link->all_pads ? "all pads" : "one pad", + PRETTY_PAD_NAME_ARGS (src, link->src_pad), + PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad)); + + if (gst_element_link_pads_filtered (src, link->src_pad, link->sink, + link->sink_pad, link->caps)) { + /* do this here, we don't want to get any problems later on when + * unlocking states */ + GST_CAT_DEBUG (GST_CAT_PIPELINE, + "delayed linking %s " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT " worked", + link->all_pads ? "all pads" : "one pad", + PRETTY_PAD_NAME_ARGS (src, link->src_pad), + PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad)); + g_signal_handler_disconnect (src, link->no_more_pads_signal_id); + /* releases 'link' */ + if (!link->all_pads) + g_signal_handler_disconnect (src, link->pad_added_signal_id); + } +} + +/* both padnames and the caps may be NULL */ +static gboolean +gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad, + GstElement *sink, const gchar *sink_pad, + GstCaps *caps, gboolean all_pads) +{ + GList *templs = gst_element_class_get_pad_template_list ( + GST_ELEMENT_GET_CLASS (src)); + + for (; templs; templs = templs->next) { + GstPadTemplate *templ = (GstPadTemplate *) templs->data; + if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) && + (GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_SOMETIMES)) + { + DelayedLink *data = g_slice_new (DelayedLink); + + data->all_pads = all_pads; + + /* TODO: maybe we should check if src_pad matches this template's names */ + + GST_CAT_DEBUG (GST_CAT_PIPELINE, + "trying delayed link " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT, + PRETTY_PAD_NAME_ARGS (src, src_pad), + PRETTY_PAD_NAME_ARGS (sink, sink_pad)); + + data->src_pad = g_strdup (src_pad); + data->sink = sink; + data->sink_pad = g_strdup (sink_pad); + if (caps) { + data->caps = gst_caps_copy (caps); + } else { + data->caps = NULL; + } + data->pad_added_signal_id = g_signal_connect_data (src, "pad-added", + G_CALLBACK (gst_parse_found_pad), data, + (GClosureNotify) gst_parse_free_delayed_link, (GConnectFlags) 0); + data->no_more_pads_signal_id = g_signal_connect (src, "no-more-pads", + G_CALLBACK (gst_parse_no_more_pads), data); + return TRUE; + } + } + return FALSE; +} + +static gboolean +gst_parse_element_can_do_caps (GstElement * e, GstPadDirection dir, + GstCaps * link_caps) +{ + gboolean can_do = FALSE, done = FALSE; + GstIterator *it; + + it = (dir == GST_PAD_SRC) ? gst_element_iterate_src_pads (e) : gst_element_iterate_sink_pads (e); + + while (!done && !can_do) { + GValue v = G_VALUE_INIT; + GstPad *pad; + GstCaps *caps; + + switch (gst_iterator_next (it, &v)) { + case GST_ITERATOR_OK: + pad = g_value_get_object (&v); + + caps = gst_pad_get_current_caps (pad); + if (caps == NULL) + caps = gst_pad_query_caps (pad, NULL); + + can_do = gst_caps_can_intersect (caps, link_caps); + + GST_TRACE ("can_do: %d for %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, + can_do, caps, link_caps); + + gst_caps_unref (caps); + + g_value_unset (&v); + break; + case GST_ITERATOR_DONE: + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + } + } + + gst_iterator_free (it); + + return can_do; +} + +/* + * performs a link and frees the struct. src and sink elements must be given + * return values 0 - link performed + * 1 - link delayed + * <0 - error + */ +static gint +gst_parse_perform_link (link_t *link, graph_t *graph) +{ + GstElement *src = link->src.element; + GstElement *sink = link->sink.element; + GSList *srcs = link->src.pads; + GSList *sinks = link->sink.pads; + g_assert (GST_IS_ELEMENT (src)); + g_assert (GST_IS_ELEMENT (sink)); + + GST_CAT_INFO (GST_CAT_PIPELINE, + "linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT " (%u/%u) with caps \"%" GST_PTR_FORMAT "\"", + PRETTY_PAD_NAME_ARGS (src, link->src.name), + PRETTY_PAD_NAME_ARGS (sink, link->sink.name), + g_slist_length (srcs), g_slist_length (sinks), link->caps); + + if (!srcs || !sinks) { + gboolean found_one = gst_element_link_pads_filtered (src, + srcs ? (const gchar *) srcs->data : NULL, sink, + sinks ? (const gchar *) sinks->data : NULL, link->caps); + + if (found_one) { + if (!link->all_pads) + goto success; /* Linked one, and not an all-pads link = we're done */ + + /* Try and link more available pads */ + while (gst_element_link_pads_filtered (src, + srcs ? (const gchar *) srcs->data : NULL, sink, + sinks ? (const gchar *) sinks->data : NULL, link->caps)); + } + + /* We either didn't find any static pads, or this is a all-pads link, + * in which case watch for future pads and link those. Not a failure + * in the all-pads case if there's no sometimes pads to watch */ + if (gst_parse_perform_delayed_link (src, + srcs ? (const gchar *) srcs->data : NULL, + sink, sinks ? (const gchar *) sinks->data : NULL, link->caps, + link->all_pads) || link->all_pads) { + goto success; + } else { + goto error; + } + } + if (g_slist_length (link->src.pads) != g_slist_length (link->sink.pads)) { + goto error; + } + while (srcs && sinks) { + const gchar *src_pad = (const gchar *) srcs->data; + const gchar *sink_pad = (const gchar *) sinks->data; + srcs = g_slist_next (srcs); + sinks = g_slist_next (sinks); + if (gst_element_link_pads_filtered (src, src_pad, sink, sink_pad, + link->caps)) { + continue; + } else { + if (gst_parse_perform_delayed_link (src, src_pad, + sink, sink_pad, + link->caps, link->all_pads)) { + continue; + } else { + goto error; + } + } + } + +success: + gst_parse_free_link (link); + return 0; + +error: + if (link->caps != NULL) { + gboolean src_can_do_caps, sink_can_do_caps; + gchar *caps_str = gst_caps_to_string (link->caps); + + src_can_do_caps = + gst_parse_element_can_do_caps (src, GST_PAD_SRC, link->caps); + sink_can_do_caps = + gst_parse_element_can_do_caps (sink, GST_PAD_SINK, link->caps); + + if (!src_can_do_caps && sink_can_do_caps) { + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, + _("could not link %s to %s, %s can't handle caps %s"), + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), + GST_ELEMENT_NAME (src), caps_str); + } else if (src_can_do_caps && !sink_can_do_caps) { + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, + _("could not link %s to %s, %s can't handle caps %s"), + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), + GST_ELEMENT_NAME (sink), caps_str); + } else if (!src_can_do_caps && !sink_can_do_caps) { + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, + _("could not link %s to %s, neither element can handle caps %s"), + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), caps_str); + } else { + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, + _("could not link %s to %s with caps %s"), + GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), caps_str); + } + g_free (caps_str); + } else { + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, + _("could not link %s to %s"), GST_ELEMENT_NAME (src), + GST_ELEMENT_NAME (sink)); + } + gst_parse_free_link (link); + return -1; +} + + +static int yyerror (void *scanner, graph_t *graph, const char *s); +%} + +%union { + gchar *ss; + chain_t *cc; + link_t *ll; + reference_t rr; + GstElement *ee; + GSList *pp; + graph_t *gg; +} + +/* No grammar ambiguities expected, FAIL otherwise */ +%expect 0 + +%token PARSE_URL +%token IDENTIFIER +%left REF PADREF BINREF +%token ASSIGNMENT +%token LINK +%token LINK_ALL + +%type binopener +%type graph +%type chain bin chainlist openchain elementary +%type reference +%type link +%type element +%type morepads pads assignments + +%destructor { gst_parse_strfree ($$); } +%destructor { if($$) + gst_parse_free_chain($$); } +%destructor { gst_parse_free_link ($$); } +%destructor { gst_parse_free_reference(&($$));} +%destructor { gst_object_unref ($$); } +%destructor { GSList *walk; + for(walk=$$;walk;walk=walk->next) + gst_parse_strfree (walk->data); + g_slist_free ($$); } + + + +%left '(' ')' +%left ',' +%right '.' +%left '!' '=' ':' + +%lex-param { void *scanner } +%parse-param { void *scanner } +%parse-param { graph_t *graph } +%pure-parser + +%start graph +%% + +/************************************************************* +* Grammar explanation: +* _element_s are specified by an identifier of their type. +* a name can be give in the optional property-assignments +* coffeeelement +* fakesrc name=john +* identity silence=false name=frodo +* (cont'd) +**************************************************************/ +element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL); + if ($$ == NULL) { + add_missing_element(graph, $1); + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1); + } + gst_parse_strfree ($1); + } + | element ASSIGNMENT { gst_parse_element_set ($2, $1, graph); + $$ = $1; + } + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* a graph has (pure) _element_s, _bin_s and _link_s. +* since bins are special elements, bins and elements can +* be generalized as _elementary_. +* The construction of _bin_s will be discussed later. +* (cont'd) +* +**************************************************************/ +elementary: + element { $$ = gst_parse_chain_new (); + /* g_print ("@%p: CHAINing elementary\n", $$); */ + $$->first.element = $1? gst_object_ref($1) : NULL; + $$->last.element = $1? gst_object_ref($1) : NULL; + $$->first.name = $$->last.name = NULL; + $$->first.pads = $$->last.pads = NULL; + $$->elements = $1 ? g_slist_prepend (NULL, $1) : NULL; + } + | bin { $$=$1; } + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* a _chain_ is a list of _elementary_s that have _link_s inbetween +* which are represented through infix-notation. +* +* fakesrc ! sometransformation ! fakesink +* +* every _link_ can be augmented with _pads_. +* +* coffeesrc .sound ! speakersink +* multisrc .movie,ads ! .projector,smallscreen multisink +* +* and every _link_ can be setup to filter media-types +* mediasrc ! audio/x-raw, signed=TRUE ! stereosink +* +* User HINT: +* if the lexer does not recognize your media-type it +* will make it an element name. that results in errors +* like +* NO SUCH ELEMENT: no element audio7x-raw +* '7' vs. '/' in https://en.wikipedia.org/wiki/QWERTZ +* +* Parsing HINT: +* in the parser we need to differ between chains that can +* be extended by more elementaries (_openchain_) and others +* that are syntactically closed (handled later in this file). +* (e.g. fakesrc ! sinkreferencename.padname) +**************************************************************/ +chain: openchain { $$=$1; + if($$->last.name){ + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, + _("unexpected reference \"%s\" - ignoring"), $$->last.name); + gst_parse_strfree($$->last.name); + $$->last.name=NULL; + } + if($$->last.pads){ + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, + _("unexpected pad-reference \"%s\" - ignoring"), (gchar*)$$->last.pads->data); + g_slist_foreach ($$->last.pads, (GFunc) gst_parse_strfree, NULL); + g_slist_free ($$->last.pads); + $$->last.pads=NULL; + } + } + ; + +openchain: + elementary pads { $$=$1; + $$->last.pads = g_slist_concat ($$->last.pads, $2); + /* g_print ("@%p@%p: FKI elementary pads\n", $1, $$->last.pads); */ + } + | openchain link pads elementary pads + { + $2->src = $1->last; + $2->sink = $4->first; + $2->sink.pads = g_slist_concat ($3, $2->sink.pads); + TRY_SETUP_LINK($2); + $4->first = $1->first; + $4->elements = g_slist_concat ($1->elements, $4->elements); + gst_parse_chain_free($1); + $$ = $4; + $$->last.pads = g_slist_concat ($$->last.pads, $5); + } + ; + +link: LINK { $$ = gst_parse_link_new (); + $$->all_pads = FALSE; + if ($1) { + $$->caps = gst_caps_from_string ($1); + if ($$->caps == NULL) + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1); + gst_parse_strfree ($1); + } + } + | LINK_ALL { $$ = gst_parse_link_new (); + $$->all_pads = TRUE; + if ($1) { + $$->caps = gst_caps_from_string ($1); + if ($$->caps == NULL) + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1); + gst_parse_strfree ($1); + } + } + ; +pads: /* NOP */ { $$ = NULL; } + | PADREF morepads { $$ = $2; + $$ = g_slist_prepend ($$, $1); + } + ; +morepads: /* NOP */ { $$ = NULL; } + | ',' IDENTIFIER morepads { $$ = g_slist_prepend ($3, $2); } + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* the first and last elements of a _chain_ can be give +* as URL. This creates special elements that fit the URL. +* +* fakesrc ! http://fake-sink.org +* http://somesource.org ! fakesink +**************************************************************/ + +chain: openchain link PARSE_URL { GstElement *element = + gst_element_make_from_uri (GST_URI_SINK, $3, NULL, NULL); + /* FIXME: get and parse error properly */ + if (!element) { + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + _("no sink element for URI \"%s\""), $3); + } + $$ = $1; + $2->sink.element = element?gst_object_ref(element):NULL; + $2->src = $1->last; + TRY_SETUP_LINK($2); + $$->last.element = NULL; + $$->last.name = NULL; + $$->last.pads = NULL; + if(element) $$->elements = g_slist_append ($$->elements, element); + g_free ($3); + } + ; +openchain: + PARSE_URL { GstElement *element = + gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL); + /* FIXME: get and parse error properly */ + if (!element) { + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + _("no source element for URI \"%s\""), $1); + } + $$ = gst_parse_chain_new (); + /* g_print ("@%p: CHAINing srcURL\n", $$); */ + $$->first.element = NULL; + $$->first.name = NULL; + $$->first.pads = NULL; + $$->last.element = element ? gst_object_ref(element):NULL; + $$->last.name = NULL; + $$->last.pads = NULL; + $$->elements = element ? g_slist_prepend (NULL, element) : NULL; + g_free($1); + } + ; + + +/************************************************************* +* Grammar explanation: (cont'd) +* the first and last elements of a _chain_ can be linked +* to a named _reference_ (with optional pads). +* +* fakesrc ! nameOfSinkElement. +* fakesrc ! nameOfSinkElement.Padname +* fakesrc ! nameOfSinkElement.Padname, anotherPad +* nameOfSource.Padname ! fakesink +**************************************************************/ + +chain: openchain link reference { $$ = $1; + $2->sink= $3; + $2->src = $1->last; + TRY_SETUP_LINK($2); + $$->last.element = NULL; + $$->last.name = NULL; + $$->last.pads = NULL; + } + ; + + +openchain: + reference { $$ = gst_parse_chain_new (); + $$->last=$1; + $$->first.element = NULL; + $$->first.name = NULL; + $$->first.pads = NULL; + $$->elements = NULL; + } + ; +reference: REF morepads { + gchar *padname = $1; + GSList *pads = $2; + if (padname) { + while (*padname != '.') padname++; + *padname = '\0'; + padname++; + if (*padname != '\0') + pads = g_slist_prepend (pads, gst_parse_strdup (padname)); + } + $$.element=NULL; + $$.name=$1; + $$.pads=pads; + } + ; + + +/************************************************************* +* Grammar explanation: (cont'd) +* a _chainlist_ is just a list of _chain_s. +* +* You can specify _link_s with named +* _reference_ on each side. That +* works already after the explanations above. +* someSourceName.Pad ! someSinkName. +* someSourceName.Pad,anotherPad ! someSinkName.Apad,Bpad +* +* If a syntax error occurs, the already finished _chain_s +* and _links_ are kept intact. +*************************************************************/ + +chainlist: /* NOP */ { $$ = NULL; } + | chainlist chain { if ($1){ + gst_parse_free_reference(&($1->last)); + gst_parse_free_reference(&($2->first)); + $2->first = $1->first; + $2->elements = g_slist_concat ($1->elements, $2->elements); + gst_parse_chain_free ($1); + } + $$ = $2; + } + | chainlist error { $$=$1; + GST_CAT_DEBUG (GST_CAT_PIPELINE,"trying to recover from syntax error"); + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, _("syntax error")); + } + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* _bins_ +*************************************************************/ + + +assignments: /* NOP */ { $$ = NULL; } + | ASSIGNMENT assignments { $$ = g_slist_prepend ($2, $1); } + ; + +binopener: '(' { $$ = gst_parse_strdup("bin"); } + | BINREF { $$ = $1; } + ; +bin: binopener assignments chainlist ')' { + chain_t *chain = $3; + GSList *walk; + GstBin *bin = (GstBin *) gst_element_factory_make ($1, NULL); + if (!chain) { + SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN, + _("specified empty bin \"%s\", not allowed"), $1); + chain = gst_parse_chain_new (); + chain->first.element = chain->last.element = NULL; + chain->first.name = chain->last.name = NULL; + chain->first.pads = chain->last.pads = NULL; + chain->elements = NULL; + } + if (!bin) { + add_missing_element(graph, $1); + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + _("no bin \"%s\", unpacking elements"), $1); + /* clear property-list */ + g_slist_foreach ($2, (GFunc) gst_parse_strfree, NULL); + g_slist_free ($2); + $2 = NULL; + } else { + for (walk = chain->elements; walk; walk = walk->next ) + gst_bin_add (bin, GST_ELEMENT (walk->data)); + g_slist_free (chain->elements); + chain->elements = g_slist_prepend (NULL, bin); + } + $$ = chain; + /* set the properties now + * HINT: property-list cleared above, if bin==NULL + */ + for (walk = $2; walk; walk = walk->next) + gst_parse_element_set ((gchar *) walk->data, + GST_ELEMENT (bin), graph); + g_slist_free ($2); + gst_parse_strfree ($1); + } + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* _graph_ +*************************************************************/ + +graph: chainlist { $$ = graph; + $$->chain = $1; + if(!$1) { + SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed")); + } + } + ; + +%% + + +static int +yyerror (void *scanner, graph_t *graph, const char *s) +{ + /* FIXME: This should go into the GError somehow, but how? */ + GST_WARNING ("Error during parsing: %s", s); + return -1; +} + + +GstElement * +priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx, + GstParseFlags flags) +{ + graph_t g; + gchar *dstr; + GSList *walk; + GstBin *bin = NULL; + GstElement *ret; + yyscan_t scanner; + + g_return_val_if_fail (str != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + g.chain = NULL; + g.links = NULL; + g.error = error; + g.ctx = ctx; + g.flags = flags; + +#ifdef __GST_PARSE_TRACE + GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled"); + __strings = __chains = __links = 0; +#endif /* __GST_PARSE_TRACE */ + + /* g_print("Now scanning: %s\n", str); */ + + dstr = g_strdup (str); + priv_gst_parse_yylex_init (&scanner); + priv_gst_parse_yy_scan_string (dstr, scanner); + +#if YYDEBUG + yydebug = 1; +#endif + + if (yyparse (scanner, &g) != 0) { + SET_ERROR (error, GST_PARSE_ERROR_SYNTAX, + "Unrecoverable syntax error while parsing pipeline %s", str); + + priv_gst_parse_yylex_destroy (scanner); + g_free (dstr); + + goto error1; + } + priv_gst_parse_yylex_destroy (scanner); + g_free (dstr); + + GST_CAT_DEBUG (GST_CAT_PIPELINE, "got %u elements and %u links", + g.chain ? g_slist_length (g.chain->elements) : 0, + g_slist_length (g.links)); + + /* ensure chain is not NULL */ + if (!g.chain){ + g.chain=gst_parse_chain_new (); + g.chain->elements=NULL; + g.chain->first.element=NULL; + g.chain->first.name=NULL; + g.chain->first.pads=NULL; + g.chain->last.element=NULL; + g.chain->last.name=NULL; + g.chain->last.pads=NULL; + }; + + /* ensure elements is not empty */ + if(!g.chain->elements){ + g.chain->elements= g_slist_prepend (NULL, NULL); + }; + + /* put all elements in our bin if necessary */ + if(g.chain->elements->next){ + if (flags & GST_PARSE_FLAG_PLACE_IN_BIN) + bin = GST_BIN (gst_element_factory_make ("bin", NULL)); + else + bin = GST_BIN (gst_element_factory_make ("pipeline", NULL)); + g_assert (bin); + + for (walk = g.chain->elements; walk; walk = walk->next) { + if (walk->data != NULL) + gst_bin_add (bin, GST_ELEMENT (walk->data)); + } + g_slist_free (g.chain->elements); + g.chain->elements = g_slist_prepend (NULL, bin); + } + + ret = (GstElement *) g.chain->elements->data; + g_slist_free (g.chain->elements); + g.chain->elements=NULL; + if (GST_IS_BIN (ret)) + bin = GST_BIN (ret); + gst_parse_free_chain (g.chain); + g.chain = NULL; + + + /* resolve and perform links */ + for (walk = g.links; walk; walk = walk->next) { + link_t *l = (link_t *) walk->data; + int err; + err=gst_resolve_reference( &(l->src), ret); + if (err) { + if(-1==err){ + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No src-element named \"%s\" - omitting link", l->src.name); + }else{ + /* probably a missing element which we've handled already */ + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No src-element found - omitting link"); + } + gst_parse_free_link (l); + continue; + } + + err=gst_resolve_reference( &(l->sink), ret); + if (err) { + if(-1==err){ + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No sink-element named \"%s\" - omitting link", l->src.name); + }else{ + /* probably a missing element which we've handled already */ + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No sink-element found - omitting link"); + } + gst_parse_free_link (l); + continue; + } + gst_parse_perform_link (l, &g); + } + g_slist_free (g.links); + +out: +#ifdef __GST_PARSE_TRACE + GST_CAT_DEBUG (GST_CAT_PIPELINE, + "TRACE: %u strings, %u chains and %u links left", __strings, __chains, + __links); + if (__strings || __chains || __links) { + g_warning ("TRACE: %u strings, %u chains and %u links left", __strings, + __chains, __links); + } +#endif /* __GST_PARSE_TRACE */ + + return ret; + +error1: + if (g.chain) { + gst_parse_free_chain (g.chain); + g.chain=NULL; + } + + g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL); + g_slist_free (g.links); + + if (error) + g_assert (*error); + ret = NULL; + + goto out; +} diff --git a/gst/parse/meson.build b/gst/parse/meson.build new file mode 100644 index 0000000..b627d1c --- /dev/null +++ b/gst/parse/meson.build @@ -0,0 +1,71 @@ +cc = meson.get_compiler('c') + +# Find flex, configure lex generator +flex_cdata = configuration_data() + +flex_min_version='2.5.31' +flex = find_program('flex', 'win_flex') + +flexversion_res = run_command([flex, '--version']) +if flexversion_res.returncode() != 0 + error('Could not get flex version (@0@)'.format(flexversion_res.stderr())) +endif + +flexversion = flexversion_res.stdout().split('\n')[0].split(' ')[1].strip() +if flexversion.version_compare('<' + flex_min_version) + error('flex version @0@ >= @1@: NO'.format(flexversion, flex_min_version)) +else + message('flex version @0@ >= @1@: YES'.format(flexversion, flex_min_version)) +endif + +flex_cdata.set('FLEX', flex.path()) +if cc.get_id() == 'msvc' + flex_cdata.set('FLEX_ARGS', '--nounistd') +else + flex_cdata.set('FLEX_ARGS', '') +endif + +gen_lex = configure_file(input : 'gen_lex.py.in', + output : 'gen_lex.py', + configuration : flex_cdata) + +# Find bison, configure grammar generator +bison_cdata = configuration_data() + +bison_min_version='2.4' +bison = find_program('bison', 'win_bison') + +bversion_res = run_command([bison, '--version']) +if bversion_res.returncode() != 0 + error('Could not get bison version (@0@)'.format(bversion_res.stderr())) +endif + +bversion = bversion_res.stdout().split('\n')[0].split(' ')[-1].strip() +if bversion.version_compare('<' + bison_min_version) + error('bison version @0@ >= @1@: NO'.format(bversion, bison_min_version)) +else + message('bison version @0@ >= @1@: YES'.format(bversion, bison_min_version)) +endif + + + +bison_cdata.set('BISON', bison.path()) +bison_cdata.set('BISON_ARGS', '') + +gen_grammar = configure_file(input : 'gen_grammar.py.in', + output : 'gen_grammar.py', + configuration : bison_cdata) + +# Custom targets +parser = custom_target('parselex', + input : 'parse.l', + output : ['lex.priv_gst_parse_yy.c', 'parse_lex.h'], + command : [python3, gen_lex, '@OUTPUT0@', '@OUTPUT1@', '@INPUT@', 'DUMMY'] +) + +grammar = custom_target('parsegrammar', + input : 'grammar.y', + output : ['grammar.tab.c', 'grammar.tab.h'], + command : [python3, gen_grammar, '@OUTPUT0@', '@OUTPUT1@', '@INPUT@'], + depends : [parser], +) diff --git a/gst/parse/parse.l b/gst/parse/parse.l new file mode 100644 index 0000000..50acf5c --- /dev/null +++ b/gst/parse/parse.l @@ -0,0 +1,176 @@ +%{ +#include "../gst_private.h" + +#include +#include + +#include + +#include "types.h" +#include "../gstinfo.h" +#include "../gsturi.h" +#include "grammar.tab.h" + +#ifdef malloc +#undef malloc +#endif + +#ifdef free +#undef free +#endif + +#ifdef realloc +#undef realloc +#endif + +#define malloc g_malloc +#define free g_free +#define realloc g_realloc + +/* Override the default ECHO so as to avoid fortify warnings. Ignore the + embedded-NUL case for now. We know yytext is NUL-terminated. */ +#define ECHO g_fprintf(yyout, "%s", yytext) + +#ifdef G_HAVE_ISO_VARARGS +#define PRINT(...) GST_CAT_DEBUG (GST_CAT_PIPELINE, "flex: " __VA_ARGS__) +#elif defined(G_HAVE_GNUC_VARARGS) +#define PRINT(args...) GST_CAT_DEBUG (GST_CAT_PIPELINE, "flex: " args) +#else +static inline void +PRINT (const char *format, ...) +{ + va_list varargs; + + va_start (varargs, format); + GST_CAT_LEVEL_LOG_valist (GST_CAT_PIPELINE, GST_LEVEL_DEBUG, NULL, + format, varargs); + va_end (varargs); +} +#endif + +%} + +_operator [(){}.!:,;=] +_identifier [[:alnum:]_][[:alnum:]\-_%:]* + +_char ("\\".)|([^[:space:]]) +_string {_char}+|("\""([^\"]|"\\\"")*"\"")|("'"([^']|"\\\'")*"'") + +_assign [[:space:]]*"="[[:space:]]* + +_protocol [[:alpha:]][[:alnum:]+-\.]* +_url ({_protocol}"://"{_string}|["."{_identifier}]?"/"{_string})|({_protocol}"://") + +/* we must do this here, because nearly everything matches a {_string} */ +_assignment {_identifier}{_assign}{_string} + +/* get pad/element references and stuff with dots right */ +_padref "."{_identifier} +_ref {_identifier}"."{_identifier}? +_binref {_identifier}[[:space:]]*"."[[:space:]]*"(" + +/* links */ +_mimechar [[:alnum:]-] +_mimetype {_mimechar}+"/"{_mimechar}+ +_capschar ("\\".)|([^\;!]) +_capsstring {_capschar}+ +_caps {_mimetype}(","[^!]|{_capsstring})* +_link ([!:][[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)*[!:])|([!:]) + +%x value +%option noyywrap +%option nounput +%option reentrant +%option bison-bridge +%option never-interactive +%option noinput +%% + +{_assignment} { + /* "=" */ + PRINT ("ASSIGNMENT: %s", yytext); + yylval->ss = gst_parse_strdup (yytext); + BEGIN (INITIAL); + return ASSIGNMENT; +} + +{_padref} { + yytext++; + PRINT ("PADREF: %s", yytext); + yylval->ss = gst_parse_strdup (yytext); + BEGIN (INITIAL); + return PADREF; +} + +{_ref} { + PRINT ("REF: %s", yytext); + yylval->ss = gst_parse_strdup (yytext); + BEGIN (INITIAL); + return REF; +} + +{_binref} { + gchar *pos = yytext; + while (!g_ascii_isspace (*pos) && (*pos != '.')) pos++; + *pos = '\0'; + PRINT ("BINREF: %s", yytext); + yylval->ss = gst_parse_strdup (yytext); + BEGIN (INITIAL); + return BINREF; +} + +{_identifier} { + PRINT ("IDENTIFIER: %s", yytext); + yylval->ss = gst_parse_strdup (yytext); + BEGIN (INITIAL); + return IDENTIFIER; +} + +{_link} { + gchar *c = yytext; + gchar op; + gboolean link_all; + + PRINT ("LINK: %s", yytext); + /* First char is a link operator */ + link_all = (*c == ':'); + c++; + if (*c) { + while (g_ascii_isspace (*c)) c++; + c = yylval->ss = gst_parse_strdup (c); + while (*c) c++; + /* Last non-space char is a link operator */ + op = *--c; + if (op != '!' && op != ':') + g_assert_not_reached (); + if (op == ':') + link_all = TRUE; + + /* Walk backward past whitespaces - what remains + * is a filter caps string, or empty */ + while (g_ascii_isspace (*--c)); + *++c = '\0'; + } else { + yylval->ss = NULL; + } + BEGIN (INITIAL); + return link_all ? LINK_ALL : LINK; +} +{_url} { + PRINT ("URL: %s", yytext); + yylval->ss = g_strdup (yytext); + gst_parse_unescape (yylval->ss); + BEGIN (INITIAL); + return PARSE_URL; +} + +{_operator} { PRINT ("OPERATOR: [%s]", yytext); return *yytext; } + +[[:space:]]+ { PRINT ("SPACE: [%s]", yytext); } + +. { + PRINT ("Invalid Lexer element: %s\n", yytext); + return *yytext; +} + +%% diff --git a/gst/parse/types.h b/gst/parse/types.h new file mode 100644 index 0000000..66d13dd --- /dev/null +++ b/gst/parse/types.h @@ -0,0 +1,110 @@ +#ifndef __GST_PARSE_TYPES_H__ +#define __GST_PARSE_TYPES_H__ + +#include +#include "../gstelement.h" +#include "../gstparse.h" + +typedef struct { + GstElement *element; + gchar *name; + GSList *pads; +} reference_t; + +typedef struct { + reference_t src; + reference_t sink; + GstCaps *caps; + gboolean all_pads; +} link_t; + +typedef struct { + GSList *elements; + reference_t first; + reference_t last; +} chain_t; + +typedef struct _graph_t graph_t; +struct _graph_t { + chain_t *chain; /* links are supposed to be done now */ + GSList *links; + GError **error; + GstParseContext *ctx; /* may be NULL */ + GstParseFlags flags; +}; + + +/* + * Memory checking. Should probably be done with gsttrace stuff, but that + * doesn't really work. + * This is not safe from reentrance issues, but that doesn't matter as long as + * we lock a mutex before parsing anyway. + * + * FIXME: Disable this for now for the above reasons + */ +#if 0 +#ifdef GST_DEBUG_ENABLED +# define __GST_PARSE_TRACE +#endif +#endif + +#ifdef __GST_PARSE_TRACE +G_GNUC_INTERNAL gchar *__gst_parse_strdup (gchar *org); +G_GNUC_INTERNAL void __gst_parse_strfree (gchar *str); +G_GNUC_INTERNAL link_t *__gst_parse_link_new (void); +G_GNUC_INTERNAL void __gst_parse_link_free (link_t *data); +G_GNUC_INTERNAL chain_t *__gst_parse_chain_new (void); +G_GNUC_INTERNAL void __gst_parse_chain_free (chain_t *data); +# define gst_parse_strdup __gst_parse_strdup +# define gst_parse_strfree __gst_parse_strfree +# define gst_parse_link_new __gst_parse_link_new +# define gst_parse_link_free __gst_parse_link_free +# define gst_parse_chain_new __gst_parse_chain_new +# define gst_parse_chain_free __gst_parse_chain_free +#else /* __GST_PARSE_TRACE */ +# define gst_parse_strdup g_strdup +# define gst_parse_strfree g_free +# define gst_parse_link_new() g_slice_new0 (link_t) +# define gst_parse_link_free(l) g_slice_free (link_t, l) +# define gst_parse_chain_new() g_slice_new0 (chain_t) +# define gst_parse_chain_free(c) g_slice_free (chain_t, c) +#endif /* __GST_PARSE_TRACE */ + +static inline void +gst_parse_unescape (gchar *str) +{ + gchar *walk; + gboolean in_quotes; + + g_return_if_fail (str != NULL); + + walk = str; + in_quotes = FALSE; + + GST_DEBUG ("unescaping %s", str); + + while (*walk) { + if (*walk == '\\' && !in_quotes) { + walk++; + /* make sure we don't read beyond the end of the string */ + if (*walk == '\0') + break; + } else if (*walk == '"' && (!in_quotes || (in_quotes + && (*(walk - 1) != '\\')))) { + /* don't unescape inside quotes and don't switch + * state with escaped quoted inside quotes */ + in_quotes = !in_quotes; + } + *str = *walk; + str++; + walk++; + } + *str = '\0'; +} + +G_GNUC_INTERNAL GstElement *priv_gst_parse_launch (const gchar * str, + GError ** err, + GstParseContext * ctx, + GstParseFlags flags); + +#endif /* __GST_PARSE_TYPES_H__ */ diff --git a/gst/printf/Makefile.am b/gst/printf/Makefile.am new file mode 100644 index 0000000..f62b448 --- /dev/null +++ b/gst/printf/Makefile.am @@ -0,0 +1,32 @@ +AM_CPPFLAGS = $(GLIB_CFLAGS) -DSTATIC=G_GNUC_INTERNAL $(WARNING_CFLAGS) $(PRINTF_CFLAGS) + +# don't have a need for that and it's not portable so just ignore for now +AM_CPPFLAGS += -UHAVE_LONG_DOUBLE + +# just use internal emulation for printing long longs for now +AM_CPPFLAGS += -UHAVE_LONG_LONG_FORMAT + +# don't need any of this widechar stuff, so just disable it for now +AM_CPPFLAGS += -UHAVE_WCHAR_T -UHAVE_WCSLEN -UHAVE_WINT_T + +# in case anyone wants to add anything else or undo some of the undefs +AM_CPPFLAGS += $(PRINTF_EXTRA_CFLAGS) + +noinst_LTLIBRARIES = libgstprintf.la + +libgstprintf_la_CFLAGS = $(EXTRA_CFLAGS) +libgstprintf_la_SOURCES = \ + asnprintf.c \ + printf-args.c \ + printf-args.h \ + printf-parse.c \ + printf-parse.h \ + vasnprintf.c \ + vasnprintf.h \ + printf.c \ + printf.h \ + printf-extension.c \ + printf-extension.h \ + gst-printf.h + +EXTRA_DIST = README diff --git a/gst/printf/Makefile.in b/gst/printf/Makefile.in new file mode 100644 index 0000000..ba874bf --- /dev/null +++ b/gst/printf/Makefile.in @@ -0,0 +1,863 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = gst/printf +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libgstprintf_la_LIBADD = +am_libgstprintf_la_OBJECTS = libgstprintf_la-asnprintf.lo \ + libgstprintf_la-printf-args.lo libgstprintf_la-printf-parse.lo \ + libgstprintf_la-vasnprintf.lo libgstprintf_la-printf.lo \ + libgstprintf_la-printf-extension.lo +libgstprintf_la_OBJECTS = $(am_libgstprintf_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstprintf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstprintf_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstprintf_la_SOURCES) +DIST_SOURCES = $(libgstprintf_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# don't have a need for that and it's not portable so just ignore for now + +# just use internal emulation for printing long longs for now + +# don't need any of this widechar stuff, so just disable it for now + +# in case anyone wants to add anything else or undo some of the undefs +AM_CPPFLAGS = $(GLIB_CFLAGS) -DSTATIC=G_GNUC_INTERNAL \ + $(WARNING_CFLAGS) $(PRINTF_CFLAGS) -UHAVE_LONG_DOUBLE \ + -UHAVE_LONG_LONG_FORMAT -UHAVE_WCHAR_T -UHAVE_WCSLEN \ + -UHAVE_WINT_T $(PRINTF_EXTRA_CFLAGS) +noinst_LTLIBRARIES = libgstprintf.la +libgstprintf_la_CFLAGS = $(EXTRA_CFLAGS) +libgstprintf_la_SOURCES = \ + asnprintf.c \ + printf-args.c \ + printf-args.h \ + printf-parse.c \ + printf-parse.h \ + vasnprintf.c \ + vasnprintf.h \ + printf.c \ + printf.h \ + printf-extension.c \ + printf-extension.h \ + gst-printf.h + +EXTRA_DIST = README +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/printf/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/printf/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstprintf.la: $(libgstprintf_la_OBJECTS) $(libgstprintf_la_DEPENDENCIES) $(EXTRA_libgstprintf_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstprintf_la_LINK) $(libgstprintf_la_OBJECTS) $(libgstprintf_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-asnprintf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-printf-args.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-printf-extension.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-printf-parse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-printf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstprintf_la-vasnprintf.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstprintf_la-asnprintf.lo: asnprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-asnprintf.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-asnprintf.Tpo -c -o libgstprintf_la-asnprintf.lo `test -f 'asnprintf.c' || echo '$(srcdir)/'`asnprintf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-asnprintf.Tpo $(DEPDIR)/libgstprintf_la-asnprintf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asnprintf.c' object='libgstprintf_la-asnprintf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-asnprintf.lo `test -f 'asnprintf.c' || echo '$(srcdir)/'`asnprintf.c + +libgstprintf_la-printf-args.lo: printf-args.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-printf-args.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-printf-args.Tpo -c -o libgstprintf_la-printf-args.lo `test -f 'printf-args.c' || echo '$(srcdir)/'`printf-args.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-printf-args.Tpo $(DEPDIR)/libgstprintf_la-printf-args.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='printf-args.c' object='libgstprintf_la-printf-args.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-printf-args.lo `test -f 'printf-args.c' || echo '$(srcdir)/'`printf-args.c + +libgstprintf_la-printf-parse.lo: printf-parse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-printf-parse.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-printf-parse.Tpo -c -o libgstprintf_la-printf-parse.lo `test -f 'printf-parse.c' || echo '$(srcdir)/'`printf-parse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-printf-parse.Tpo $(DEPDIR)/libgstprintf_la-printf-parse.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='printf-parse.c' object='libgstprintf_la-printf-parse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-printf-parse.lo `test -f 'printf-parse.c' || echo '$(srcdir)/'`printf-parse.c + +libgstprintf_la-vasnprintf.lo: vasnprintf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-vasnprintf.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-vasnprintf.Tpo -c -o libgstprintf_la-vasnprintf.lo `test -f 'vasnprintf.c' || echo '$(srcdir)/'`vasnprintf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-vasnprintf.Tpo $(DEPDIR)/libgstprintf_la-vasnprintf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vasnprintf.c' object='libgstprintf_la-vasnprintf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-vasnprintf.lo `test -f 'vasnprintf.c' || echo '$(srcdir)/'`vasnprintf.c + +libgstprintf_la-printf.lo: printf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-printf.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-printf.Tpo -c -o libgstprintf_la-printf.lo `test -f 'printf.c' || echo '$(srcdir)/'`printf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-printf.Tpo $(DEPDIR)/libgstprintf_la-printf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='printf.c' object='libgstprintf_la-printf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-printf.lo `test -f 'printf.c' || echo '$(srcdir)/'`printf.c + +libgstprintf_la-printf-extension.lo: printf-extension.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -MT libgstprintf_la-printf-extension.lo -MD -MP -MF $(DEPDIR)/libgstprintf_la-printf-extension.Tpo -c -o libgstprintf_la-printf-extension.lo `test -f 'printf-extension.c' || echo '$(srcdir)/'`printf-extension.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstprintf_la-printf-extension.Tpo $(DEPDIR)/libgstprintf_la-printf-extension.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='printf-extension.c' object='libgstprintf_la-printf-extension.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstprintf_la_CFLAGS) $(CFLAGS) -c -o libgstprintf_la-printf-extension.lo `test -f 'printf-extension.c' || echo '$(srcdir)/'`printf-extension.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/printf/README b/gst/printf/README new file mode 100644 index 0000000..c8eac38 --- /dev/null +++ b/gst/printf/README @@ -0,0 +1,59 @@ +The files + + asnprintf.c + printf-args.c + printf-args.h + printf-parse.c + printf-parse.h + vasnprintf.c + vasnprintf.h + +are taken from the vasnprintf module of the GNUlib package, which can +be found at: + + http://www.gnu.org/software/gnulib/ + +All files have been modified to include g-gnulib.h. + +vasnprintf.c has also been modified to include support for long long +printing if the system printf doesn't. This code is protected by +#ifndef HAVE_LONG_LONG_FORMAT. + +Code has been added to printf-args.[ch], printf-parse.c and vasnprintf.c +to support printing of __int64 values with the I64 format modifier. This +is protected by #ifdef HAVE_INT64_AND_I64. + +The files + + printf.h + printf.c + g-gnulib.h + +have been written by me. printf.[hc] contain implementations of the +remaining functions in the printf family based on vasnprintf. +g-gnulib.h is included by all source files in order to move all +exported functions to the _g_gnulib namespace, replace malloc by +g_malloc and make sure that snprintf is only used if it implements +C99 return value semantics. + +Matthias Clasen +November 1, 2003 + +----- + +GStreamer modifications + +This was imported from GLib's gnulib subdirectory. + +g-gnulib.h and _g_gnulib namespace has been changed to gst-printf.h and +__gst_printf namespace for GStreamer. Also #define HAVE_SNPRINTF 0 has +been changed to #undef HAVE_SNPRINTF, and HAVE_ALLOCA has been replaced +by an #if defined(alloca) || defined(GLIB_HAVE_ALLOCA_H) + +printf-extension.[ch] were added to provide support for custom pointer +arguments (e.g. caps, events, etc.) + +Files have also been indented with gst-indent, so this is basically a +permanent fork and any patches will have to be merged manually. + +March 30, 2013. diff --git a/gst/printf/asnprintf.c b/gst/printf/asnprintf.c new file mode 100644 index 0000000..d606d38 --- /dev/null +++ b/gst/printf/asnprintf.c @@ -0,0 +1,40 @@ +/* Formatted output to strings. + Copyright (C) 1999, 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. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gst-printf.h" + +/* Specification. */ +#include "vasnprintf.h" + +#include + +char * +asnprintf (char *resultbuf, size_t * lengthp, const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = vasnprintf (resultbuf, lengthp, format, args); + va_end (args); + return result; +} diff --git a/gst/printf/gst-printf.h b/gst/printf/gst-printf.h new file mode 100644 index 0000000..db5972a --- /dev/null +++ b/gst/printf/gst-printf.h @@ -0,0 +1,59 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2003 Matthias Clasen + * + * 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 __G_GNULIB_H__ + +#include "config.h" +#include +#include + +/* Private namespace for gnulib functions */ +#define asnprintf __gst_asnprintf +#define vasnprintf __gst_vasnprintf +#define printf_parse __gst_printf_parse +#define printf_fetchargs __gst_printf_fetchargs + +/* Use GLib memory allocation */ +#undef malloc +#undef realloc +#undef free +#define malloc g_malloc +#define realloc g_realloc +#define free g_free + +/* Don't use snprintf(); we have to use sprintf instead and do our own + * length calculations, because glibc doesn't allow passing %n in a format + * string if the string is in writable memory (if glibc has been compiled + * with _FORTIFY_SOURCE=2 which seems to be the case on some distros/systems) */ +#undef HAVE_SNPRINTF + +/* based on glib's config.h.win32.in */ +#ifdef G_OS_WIN32 + +/* define to support printing 64-bit integers with format I64 */ +#define HAVE_INT64_AND_I64 1 + +#if defined (_MSC_VER) && _MSC_VER >= 1600 +#undef HAVE_INTMAX_T +#define HAVE_INTMAX_T 1 +#define HAVE_STDINT_H_WITH_UINTMAX 1 +#endif + +#endif /* G_OS_WIN32 */ + +#endif /* __G_GNULIB_H__ */ diff --git a/gst/printf/meson.build b/gst/printf/meson.build new file mode 100644 index 0000000..57ecb61 --- /dev/null +++ b/gst/printf/meson.build @@ -0,0 +1,84 @@ +printf_sources = [ + 'asnprintf.c', + 'printf-args.c', + 'printf-parse.c', + 'vasnprintf.c', + 'printf.c', + 'printf-extension.c', +] + +printf_args = gst_c_args + ['-DSTATIC=G_GNUC_INTERNAL'] + +# Don't have a need for that and it's not portable so just ignore for now +printf_args += ['-UHAVE_LONG_DOUBLE'] + +# Just use internal emulation for printing long longs for now +printf_args += ['-UHAVE_LONG_LONG_FORMAT'] + +# Don't need any of this widechar stuff, so just disable it for now +printf_args += ['-UHAVE_WCHAR_T', '-UHAVE_WCSLEN', '-UHAVE_WINT_T'] + +if cc.has_argument('-Wno-format-nonliteral') + printf_args += ['-Wno-format-nonliteral'] +endif + +# Check if 'long long' works and what format can be used to print it +# jm_AC_TYPE_LONG_LONG +if cc.compiles('''long long ll = 1LL; + int i = 63; + int some_func (void) { + long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll; + }''', name : 'long long') + printf_args += ['-DHAVE_LONG_LONG'] + have_long_long = true +else + have_long_long = false +endif + +# The following uintmax_t/intmax_t checks are also in glib +found_uintmax_t = false + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. +# jm_AC_HEADER_INTTYPES_H +if cc.compiles('''#include + #include + uintmax_t i = (uintmax_t) -1; + ''', name : 'uintmax_t in inttypes.h') + printf_args += ['-DHAVE_INTTYPES_H_WITH_UINTMAX'] + found_uintmax_t = true +endif + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. +# jm_AC_HEADER_STDINT_H +if cc.compiles('''#include + #include + uintmax_t i = (uintmax_t) -1; + ''', name : 'uintmax_t in stdint.h') + printf_args += ['-DHAVE_STDINT_H_WITH_UINTMAX'] + found_uintmax_t = true +endif + + +# Define intmax_t to 'long' or 'long long' +# if it is not already defined in or . +# For simplicity, we assume that a header file defines 'intmax_t' +# if and only if it defines 'uintmax_t'. +printf_args += ['-DHAVE_INTMAX_T'] +if not found_uintmax_t + if have_long_long + printf_args += ['-Dintmax_t=long long'] + else + printf_args += ['-Dintmax_t=long'] + endif +endif + +printf_lib = static_library('gstprintf', + printf_sources, + include_directories : [configinc], + c_args : printf_args, + install : false, + pic: true, + dependencies : [glib_dep]) diff --git a/gst/printf/printf-args.c b/gst/printf/printf-args.c new file mode 100644 index 0000000..1177ddb --- /dev/null +++ b/gst/printf/printf-args.c @@ -0,0 +1,133 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 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. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gst-printf.h" + +/* Specification. */ +#include "printf-args.h" + +#ifdef STATIC +STATIC +#endif + int +printf_fetchargs (va_list args, arguments * a) +{ + unsigned int i; + argument *ap; + + for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) + switch (ap->type) { + case TYPE_SCHAR: + ap->a.a_schar = va_arg (args, /*signed char */ int); + break; + case TYPE_UCHAR: + ap->a.a_uchar = va_arg (args, /*unsigned char */ int); + break; + case TYPE_SHORT: + ap->a.a_short = va_arg (args, /*short */ int); + break; + case TYPE_USHORT: + ap->a.a_ushort = va_arg (args, /*unsigned short */ int); + break; + case TYPE_INT: + ap->a.a_int = va_arg (args, int); + break; + case TYPE_UINT: + ap->a.a_uint = va_arg (args, unsigned int); + break; + case TYPE_LONGINT: + ap->a.a_longint = va_arg (args, long int); + break; + case TYPE_ULONGINT: + ap->a.a_ulongint = va_arg (args, unsigned long int); + break; +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + ap->a.a_longlongint = va_arg (args, long long int); + break; + case TYPE_ULONGLONGINT: + ap->a.a_ulonglongint = va_arg (args, unsigned long long int); + break; +#endif +#ifdef HAVE_INT64_AND_I64 + case TYPE_INT64: + ap->a.a_int64 = va_arg (args, __int64); + break; + case TYPE_UINT64: + ap->a.a_uint64 = va_arg (args, unsigned __int64); + break; +#endif + case TYPE_DOUBLE: + ap->a.a_double = va_arg (args, double); + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; +#endif + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: +#ifdef _WIN32 + ap->a.a_wide_char = va_arg (args, int); +#else + ap->a.a_wide_char = va_arg (args, wint_t); +#endif + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + break; +#endif + case TYPE_POINTER: + case TYPE_POINTER_EXT: + ap->a.a_pointer = va_arg (args, void *); + break; + case TYPE_COUNT_SCHAR_POINTER: + ap->a.a_count_schar_pointer = va_arg (args, signed char *); + break; + case TYPE_COUNT_SHORT_POINTER: + ap->a.a_count_short_pointer = va_arg (args, short *); + break; + case TYPE_COUNT_INT_POINTER: + ap->a.a_count_int_pointer = va_arg (args, int *); + break; + case TYPE_COUNT_LONGINT_POINTER: + ap->a.a_count_longint_pointer = va_arg (args, long int *); + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/gst/printf/printf-args.h b/gst/printf/printf-args.h new file mode 100644 index 0000000..12a3c18 --- /dev/null +++ b/gst/printf/printf-args.h @@ -0,0 +1,147 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 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 _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* Get wchar_t. */ +#ifdef HAVE_WCHAR_T +# include +#endif + +/* Get wint_t. */ +#ifdef HAVE_WINT_T +# include +#endif + +/* Get va_list. */ +#include + +#define POINTER_EXT_SIGNIFIER_CHAR '\a' + +/* Argument types */ +typedef enum +{ + TYPE_NONE, + TYPE_SCHAR, + TYPE_UCHAR, + TYPE_SHORT, + TYPE_USHORT, + TYPE_INT, + TYPE_UINT, + TYPE_LONGINT, + TYPE_ULONGINT, +#ifdef HAVE_LONG_LONG + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif +#ifdef HAVE_INT64_AND_I64 + TYPE_INT64, + TYPE_UINT64, +#endif + TYPE_DOUBLE, +#ifdef HAVE_LONG_DOUBLE + TYPE_LONGDOUBLE, +#endif + TYPE_CHAR, +#ifdef HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#ifdef HAVE_WCHAR_T + TYPE_WIDE_STRING, +#endif + TYPE_POINTER, + TYPE_POINTER_EXT, + TYPE_COUNT_SCHAR_POINTER, + TYPE_COUNT_SHORT_POINTER, + TYPE_COUNT_INT_POINTER, + TYPE_COUNT_LONGINT_POINTER +#ifdef HAVE_LONG_LONG +, TYPE_COUNT_LONGLONGINT_POINTER +#endif +} arg_type; + +/* Polymorphic argument */ +typedef struct +{ + arg_type type; + union + { + signed char a_schar; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long int a_longint; + unsigned long int a_ulongint; +#ifdef HAVE_LONG_LONG + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif +#ifdef HAVE_INT64_AND_I64 + __int64 a_int64; + unsigned __int64 a_uint64; +#endif + float a_float; + double a_double; +#ifdef HAVE_LONG_DOUBLE + long double a_longdouble; +#endif + int a_char; +#ifdef HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#ifdef HAVE_WCHAR_T + const wchar_t* a_wide_string; +#endif + void* a_pointer; + signed char * a_count_schar_pointer; + short * a_count_short_pointer; + int * a_count_int_pointer; + long int * a_count_longint_pointer; +#ifdef HAVE_LONG_LONG + long long int * a_count_longlongint_pointer; +#endif + } + a; + + /* string to replace pointer argument with for TYPE_POINTER_EXT */ + char *ext_string; +} +argument; + +typedef struct +{ + unsigned int count; + argument *arg; +} +arguments; + + +/* Fetch the arguments, putting them into a. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_fetchargs (va_list args, arguments *a); + +#endif /* _PRINTF_ARGS_H */ diff --git a/gst/printf/printf-extension.c b/gst/printf/printf-extension.c new file mode 100644 index 0000000..bf98c97 --- /dev/null +++ b/gst/printf/printf-extension.c @@ -0,0 +1,50 @@ +/* GStreamer printf extension hooks + * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "printf-extension.h" +#include "gst-printf.h" +#include +#include + +static PrintfPointerExtensionFunc ptr_ext_func; /* NULL */ + +void +__gst_printf_pointer_extension_set_func (PrintfPointerExtensionFunc func) +{ + /* since this is internal, we don't need to worry about thread-safety */ + ptr_ext_func = func; +} + +char * +__gst_printf_pointer_extension_serialize (const char *format, void *ptr) +{ + char *buf; + + if (ptr_ext_func == NULL) { + buf = malloc (32); + memset (buf, 0, 32); + sprintf (buf, "%p", ptr); + } else { + /* note: we map malloc/free to g_malloc/g_free in gst-printf.h, so the + * fact that gstinfo gives us a glib-allocated string and the printf + * routines free it with free() and not g_free() should not be a problem */ + buf = ptr_ext_func (format, ptr); + } + return buf; +} diff --git a/gst/printf/printf-extension.h b/gst/printf/printf-extension.h new file mode 100644 index 0000000..b103a1a --- /dev/null +++ b/gst/printf/printf-extension.h @@ -0,0 +1,31 @@ +/* GStreamer printf extension hooks + * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PRINTF_EXTENSION_H_INCLUDED__ +#define __GST_PRINTF_EXTENSION_H_INCLUDED__ + +typedef char * (*PrintfPointerExtensionFunc) (const char * format, void * ptr); + +/* we only need one global function, since it's only GstInfo registering extensions */ +void __gst_printf_pointer_extension_set_func (PrintfPointerExtensionFunc func); + +/* functions for internal printf implementation to handle the extensions */ +char * __gst_printf_pointer_extension_serialize (const char * format, void * ptr); + +#endif /* __GST_PRINTF_EXTENSION_H_INCLUDED__ */ diff --git a/gst/printf/printf-parse.c b/gst/printf/printf-parse.c new file mode 100644 index 0000000..d045ae8 --- /dev/null +++ b/gst/printf/printf-parse.c @@ -0,0 +1,481 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 2002-2003 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. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gst-printf.h" + +/* Specification. */ +#include "printf-parse.h" + +/* Get size_t, NULL. */ +#include + +/* Get intmax_t. */ +#ifdef HAVE_STDINT_H_WITH_UINTMAX +# include +#endif +#ifdef HAVE_INTTYPES_H_WITH_UINTMAX +# include +#endif + +/* malloc(), realloc(), free(). */ +#include + +#ifdef STATIC +STATIC +#endif + int +printf_parse (const char *format, char_directives * d, arguments * a) +{ + const char *cp = format; /* pointer into format */ + int arg_posn = 0; /* number of regular arguments consumed */ + unsigned int d_allocated; /* allocated elements of d->dir */ + unsigned int a_allocated; /* allocated elements of a->arg */ + unsigned int max_width_length = 0; + unsigned int max_precision_length = 0; + + d->count = 0; + d_allocated = 1; + d->dir = malloc (d_allocated * sizeof (char_directive)); + if (d->dir == NULL) + /* Out of memory. */ + return -1; + + a->count = 0; + a_allocated = 0; + a->arg = NULL; + +#define REGISTER_ARG(_index_,_type_) \ + { \ + unsigned int n = (_index_); \ + if (n >= a_allocated) \ + { \ + argument *memory; \ + a_allocated = 2 * a_allocated; \ + if (a_allocated <= n) \ + a_allocated = n + 1; \ + memory = (a->arg \ + ? realloc (a->arg, a_allocated * sizeof (argument)) \ + : malloc (a_allocated * sizeof (argument))); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto error; \ + a->arg = memory; \ + } \ + while (a->count <= n) { \ + a->arg[a->count].type = TYPE_NONE; \ + a->arg[a->count].ext_string = (char *) 0; \ + ++a->count; \ + } \ + if (a->arg[n].type == TYPE_NONE) \ + a->arg[n].type = (_type_); \ + else if (a->arg[n].type != (_type_)) \ + /* Ambiguous type for positional argument. */ \ + goto error; \ + } + + while (*cp != '\0') { + char c = *cp++; + if (c == '%') { + int arg_index = -1; + char_directive *dp = &d->dir[d->count]; /* pointer to next directive */ + + /* Initialize the next directive. */ + dp->dir_start = cp - 1; + dp->flags = 0; + dp->width_start = NULL; + dp->width_end = NULL; + dp->width_arg_index = -1; + dp->precision_start = NULL; + dp->precision_end = NULL; + dp->precision_arg_index = -1; + dp->arg_index = -1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') { + const char *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++); + if (*np == '$') { + unsigned int n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = 10 * n + (*np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + arg_index = n - 1; + cp = np + 1; + } + } + + /* Read the flags. */ + for (;;) { + if (*cp == '\'') { + dp->flags |= FLAG_GROUP; + cp++; + } else if (*cp == '-') { + dp->flags |= FLAG_LEFT; + cp++; + } else if (*cp == '+') { + dp->flags |= FLAG_SHOWSIGN; + cp++; + } else if (*cp == ' ') { + dp->flags |= FLAG_SPACE; + cp++; + } else if (*cp == '#') { + dp->flags |= FLAG_ALT; + cp++; + } else if (*cp == '0') { + dp->flags |= FLAG_ZERO; + cp++; + } else + break; + } + + /* Parse the field width. */ + if (*cp == '*') { + dp->width_start = cp; + cp++; + dp->width_end = cp; + if (max_width_length < 1) + max_width_length = 1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') { + const char *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++); + if (*np == '$') { + unsigned int n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = 10 * n + (*np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + dp->width_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->width_arg_index < 0) + dp->width_arg_index = arg_posn++; + REGISTER_ARG (dp->width_arg_index, TYPE_INT); + } else if (*cp >= '0' && *cp <= '9') { + unsigned int width_length; + + dp->width_start = cp; + for (; *cp >= '0' && *cp <= '9'; cp++); + dp->width_end = cp; + width_length = dp->width_end - dp->width_start; + if (max_width_length < width_length) + max_width_length = width_length; + } + + /* Parse the precision. */ + if (*cp == '.') { + cp++; + if (*cp == '*') { + dp->precision_start = cp - 1; + cp++; + dp->precision_end = cp; + if (max_precision_length < 2) + max_precision_length = 2; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') { + const char *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++); + if (*np == '$') { + unsigned int n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = 10 * n + (*np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + dp->precision_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->precision_arg_index < 0) + dp->precision_arg_index = arg_posn++; + REGISTER_ARG (dp->precision_arg_index, TYPE_INT); + } else { + unsigned int precision_length; + + dp->precision_start = cp - 1; + for (; *cp >= '0' && *cp <= '9'; cp++); + dp->precision_end = cp; + precision_length = dp->precision_end - dp->precision_start; + if (max_precision_length < precision_length) + max_precision_length = precision_length; + } + } + + { + arg_type type; + + /* Parse argument type/size specifiers. */ + { + int flags = 0; + + for (;;) { + if (*cp == 'h') { + flags |= (1 << (flags & 1)); + cp++; + } else if (*cp == 'L') { + flags |= 4; + cp++; + } else if (*cp == 'l') { + flags += 8; + cp++; + } +#ifdef HAVE_INT64_AND_I64 + else if (cp[0] == 'I' && cp[1] == '6' && cp[2] == '4') { + flags = 64; + cp += 3; + } +#endif + else if (cp[0] == 'I' && cp[1] == '3' && cp[2] == '2') { + //flags = 32; + cp += 3; + } +#ifdef HAVE_INTMAX_T + else if (*cp == 'j') { + if (sizeof (intmax_t) > sizeof (long)) { + /* intmax_t = long long */ + flags += 16; + } else if (sizeof (intmax_t) > sizeof (int)) { + /* intmax_t = long */ + flags += 8; + } + cp++; + } +#endif + else if (*cp == 'z' || *cp == 'Z') { + /* 'z' is standardized in ISO C 99, but glibc uses 'Z' + because the warning facility in gcc-2.95.2 understands + only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ + if (sizeof (size_t) > sizeof (long)) { + /* size_t = long long */ + flags += 16; + } else if (sizeof (size_t) > sizeof (int)) { + /* size_t = long */ + flags += 8; + } + cp++; + } else if (*cp == 't') { + if (sizeof (ptrdiff_t) > sizeof (long)) { + /* ptrdiff_t = long long */ + flags += 16; + } else if (sizeof (ptrdiff_t) > sizeof (int)) { + /* ptrdiff_t = long */ + flags += 8; + } + cp++; + } else + break; + } + + /* Read the conversion character. */ + c = *cp++; + switch (c) { + case 'd': + case 'i': +#ifdef HAVE_INT64_AND_I64 + if (flags == 64) + type = TYPE_INT64; + else +#endif +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_LONGINT; + else if (flags & 2) + type = TYPE_SCHAR; + else if (flags & 1) + type = TYPE_SHORT; + else + type = TYPE_INT; + break; + case 'o': + case 'u': + case 'x': + case 'X': +#ifdef HAVE_INT64_AND_I64 + if (flags == 64) + type = TYPE_UINT64; + else +#endif +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_ULONGINT; + else if (flags & 2) + type = TYPE_UCHAR; + else if (flags & 1) + type = TYPE_USHORT; + else + type = TYPE_UINT; + break; + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': +#ifdef HAVE_LONG_DOUBLE + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else +#endif + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#ifdef HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#ifdef HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#ifdef HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#ifdef HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + /* Old GST_PTR_FORMAT, handle for binary backwards compatibility */ + case 'P': + type = TYPE_POINTER_EXT; + dp->flags |= FLAG_PTR_EXT; + dp->ptr_ext_char = 'A'; + c = 'p'; + break; + case 'p': + /* Note: cp points already to the char after the 'p' now */ + if (cp[0] == POINTER_EXT_SIGNIFIER_CHAR && cp[1] != '\0') { + type = TYPE_POINTER_EXT; + dp->flags |= FLAG_PTR_EXT; + dp->ptr_ext_char = cp[1]; + cp += 2; + /* we do not use dp->conversion='s' on purpose here, so we + * can fall back to printing just the pointer with %p if the + * serialisation function returned NULL for some reason */ + } else { + type = TYPE_POINTER; + } + break; + /* Old GST_SEGMENT_FORMAT, handle for backwards compatibility */ + case 'Q': + type = TYPE_POINTER_EXT; + dp->flags |= FLAG_PTR_EXT; + dp->ptr_ext_char = 'B'; + c = 'p'; + break; + case 'n': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + if (flags >= 8) + type = TYPE_COUNT_LONGINT_POINTER; + else if (flags & 2) + type = TYPE_COUNT_SCHAR_POINTER; + else if (flags & 1) + type = TYPE_COUNT_SHORT_POINTER; + else + type = TYPE_COUNT_INT_POINTER; + break; + case '%': + type = TYPE_NONE; + break; + default: + /* Unknown conversion character. */ + goto error; + } + } + + if (type != TYPE_NONE) { + dp->arg_index = arg_index; + if (dp->arg_index < 0) + dp->arg_index = arg_posn++; + REGISTER_ARG (dp->arg_index, type); + } + dp->conversion = c; + dp->dir_end = cp; + } + + d->count++; + if (d->count >= d_allocated) { + char_directive *memory; + + d_allocated = 2 * d_allocated; + memory = realloc (d->dir, d_allocated * sizeof (char_directive)); + if (memory == NULL) + /* Out of memory. */ + goto error; + d->dir = memory; + } + } + } + d->dir[d->count].dir_start = cp; + + d->max_width_length = max_width_length; + d->max_precision_length = max_precision_length; + return 0; + +error: + if (a->arg) + free (a->arg); + if (d->dir) + free (d->dir); + return -1; +} diff --git a/gst/printf/printf-parse.h b/gst/printf/printf-parse.h new file mode 100644 index 0000000..96c2462 --- /dev/null +++ b/gst/printf/printf-parse.h @@ -0,0 +1,81 @@ +/* Parse printf format string. + Copyright (C) 1999, 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 _PRINTF_PARSE_H +#define _PRINTF_PARSE_H + +#include "printf-args.h" + +/* Private namespace for gnulib functions */ +#define printf_parse __gst_printf_parse + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 + +#define FLAG_PTR_EXT 1024 + +/* A parsed directive. */ +typedef struct +{ + const char* dir_start; + const char* dir_end; + int flags; + const char* width_start; + const char* width_end; + int width_arg_index; + const char* precision_start; + const char* precision_end; + int precision_arg_index; + char conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + int arg_index; + + /* extension char in case of TYPE_POINTER_EXT. We need to store this so + * we can pass it back to __gst_printf_pointer_extension_serialize() + * so it knows which pointer extension it is */ + char ptr_ext_char; +} +char_directive; + +/* A parsed format string. */ +typedef struct +{ + unsigned int count; + char_directive *dir; + unsigned int max_width_length; + unsigned int max_precision_length; +} +char_directives; + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_parse (const char *format, char_directives *d, arguments *a); + +#endif /* _PRINTF_PARSE_H */ diff --git a/gst/printf/printf.c b/gst/printf/printf.c new file mode 100644 index 0000000..d2bb373 --- /dev/null +++ b/gst/printf/printf.c @@ -0,0 +1,159 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2003 Matthias Clasen + * + * 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. + */ + +/* + * Modified by the GLib Team and others 2003. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include "gst-printf.h" +#include "vasnprintf.h" +#include "printf.h" + +#if 0 +int +__gst_printf (char const *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = __gst_vprintf (format, args); + va_end (args); + + return retval; +} + +int +__gst_fprintf (FILE * file, char const *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = __gst_vfprintf (file, format, args); + va_end (args); + + return retval; +} + +int +__gst_sprintf (char *string, char const *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = __gst_vsprintf (string, format, args); + va_end (args); + + return retval; +} + +int +__gst_snprintf (char *string, size_t n, char const *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = __gst_vsnprintf (string, n, format, args); + va_end (args); + + return retval; +} + +int +__gst_vprintf (char const *format, va_list args) +{ + return __gst_vfprintf (stdout, format, args); +} + +int +__gst_vfprintf (FILE * file, char const *format, va_list args) +{ + char *result; + size_t length; + + result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + fwrite (result, 1, length, file); + free (result); + + return length; +} + +int +__gst_vsprintf (char *string, char const *format, va_list args) +{ + char *result; + size_t length; + + result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + memcpy (string, result, length + 1); + free (result); + + return length; +} + +int +__gst_vsnprintf (char *string, size_t n, char const *format, va_list args) +{ + char *result; + size_t length; + + result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + if (n > 0) { + memcpy (string, result, MIN (length + 1, n)); + string[n - 1] = 0; + } + + free (result); + + return length; +} +#endif + +int +__gst_vasprintf (char **result, char const *format, va_list args) +{ + size_t length; + + *result = vasnprintf (NULL, &length, format, args); + if (*result == NULL) + return -1; + + return length; +} diff --git a/gst/printf/printf.h b/gst/printf/printf.h new file mode 100644 index 0000000..18e3cf9 --- /dev/null +++ b/gst/printf/printf.h @@ -0,0 +1,64 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2003 Matthias Clasen + * + * 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 __GNULIB_PRINTF_H__ +#define __GNULIB_PRINTF_H__ + +#include +#include + +#if 0 +int __gst_printf (char const *format, + ...); + +int __gst_fprintf (FILE *file, + char const *format, + ...); + +int __gst_sprintf (char *string, + char const *format, + ...); + +int __gst_snprintf (char *string, + size_t n, + char const *format, + ...); + +int __gst_vprintf (char const *format, + va_list args); + +int __gst_vfprintf (FILE *file, + char const *format, + va_list args); + +int __gst_vsprintf (char *string, + char const *format, + va_list args); + +int __gst_vsnprintf (char *string, + size_t n, + char const *format, + va_list args); +#endif + +int __gst_vasprintf (char **result, + char const *format, + va_list args); + + +#endif /* __GNULIB_PRINTF_H__ */ diff --git a/gst/printf/vasnprintf.c b/gst/printf/vasnprintf.c new file mode 100644 index 0000000..a97404c --- /dev/null +++ b/gst/printf/vasnprintf.c @@ -0,0 +1,1041 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-2003 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 _WIN32 +/* Tell glibc's to provide a prototype for snprintf(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gst-printf.h" + +/* Specification. */ +#include "vasnprintf.h" + +#include /* snprintf(), sprintf() */ +#include /* abort(), malloc(), realloc(), free() */ +#include /* memcpy(), strlen() */ +#include /* errno */ +#include /* CHAR_BIT */ +#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#include "printf-parse.h" +#include "printf-extension.h" + +#ifdef HAVE_WCHAR_T +# ifdef HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t * s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++); + return ptr - s; +} +# endif +# endif +#endif + +/* For those losing systems which don't have 'alloca' we have to add + some additional code emulating it. */ +#if defined (alloca) || defined (GLIB_HAVE_ALLOCA_H) +# define freea(p) /* nothing */ +#else +# define alloca(n) malloc (n) +# define freea(p) free (p) +#endif + +#ifndef HAVE_LONG_LONG_FORMAT +static inline int +print_long_long (char *buf, + int len, + int width, + int precision, + unsigned long flags, char conversion, unsigned long long number) +{ + int negative = FALSE; + char buffer[128]; + char *bufferend; + char *pointer; + int base; + static const char *upper = "0123456789ABCDEFX"; + static const char *lower = "0123456789abcdefx"; + const char *digits; + int i; + char *p; + int count; + +#define EMIT(c) \ + if (p - buf == len - 1) \ + { \ + *p++ = '\0'; \ + return len; \ + } \ + else \ + *p++ = c; + + p = buf; + + switch (conversion) { + case 'o': + base = 8; + digits = lower; + negative = FALSE; + break; + case 'x': + base = 16; + digits = lower; + negative = FALSE; + break; + case 'X': + base = 16; + digits = upper; + negative = FALSE; + break; + case 'u': + base = 10; + digits = lower; + negative = FALSE; + break; + default: + base = 10; + digits = lower; + negative = (long long) number < 0; + if (negative) + number = -((long long) number); + break; + } + + /* Build number */ + pointer = bufferend = &buffer[sizeof (buffer) - 1]; + *pointer-- = '\0'; + for (i = 1; i < (int) sizeof (buffer); i++) { + *pointer-- = digits[number % base]; + number /= base; + if (number == 0) + break; + } + + /* Adjust width */ + width -= (bufferend - pointer) - 1; + + /* Adjust precision */ + if (precision != -1) { + precision -= (bufferend - pointer) - 1; + if (precision < 0) + precision = 0; + flags |= FLAG_ZERO; + } + + /* Adjust width further */ + if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE)) + width--; + if (flags & FLAG_ALT) { + switch (base) { + case 16: + width -= 2; + break; + case 8: + width--; + break; + default: + break; + } + } + + /* Output prefixes spaces if needed */ + if (!((flags & FLAG_LEFT) || ((flags & FLAG_ZERO) && (precision == -1)))) { + count = (precision == -1) ? 0 : precision; + while (width-- > count) + *p++ = ' '; + } + + /* width has been adjusted for signs and alternatives */ + if (negative) { + EMIT ('-'); + } else if (flags & FLAG_SHOWSIGN) { + EMIT ('+'); + } else if (flags & FLAG_SPACE) { + EMIT (' '); + } + + if (flags & FLAG_ALT) { + switch (base) { + case 8: + EMIT ('0'); + break; + case 16: + EMIT ('0'); + EMIT (digits[16]); + break; + default: + break; + } /* switch base */ + } + + /* Output prefixed zero padding if needed */ + if (flags & FLAG_ZERO) { + if (precision == -1) + precision = width; + while (precision-- > 0) { + EMIT ('0'); + width--; + } + } + + /* Output the number itself */ + while (*(++pointer)) { + EMIT (*pointer); + } + + /* Output trailing spaces if needed */ + if (flags & FLAG_LEFT) { + while (width-- > 0) + EMIT (' '); + } + + EMIT ('\0'); + + return p - buf - 1; +} +#endif + +static void +printf_postprocess_args (char_directives * directives, arguments * arguments) +{ + int i; + + for (i = 0; i < directives->count; ++i) { + char_directive *dp; + argument *a; + + dp = &directives->dir[i]; + + /* %% has no arguments, for example */ + if (dp->arg_index < 0) + continue; + + a = &arguments->arg[dp->arg_index]; + + if (a->type == TYPE_POINTER_EXT) { + char fmt[4]; + + fmt[0] = 'p'; + fmt[1] = POINTER_EXT_SIGNIFIER_CHAR; + fmt[2] = dp->ptr_ext_char; + fmt[3] = '\0'; + + a->ext_string = + __gst_printf_pointer_extension_serialize (fmt, a->a.a_pointer); + } + } +} + +char * +vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args) +{ + char_directives d; + arguments a; + + if (printf_parse (format, &d, &a) < 0) { + errno = EINVAL; + return NULL; + } +#define CLEANUP() \ + free (d.dir); \ + if (a.arg) { \ + while (a.count--) { \ + if (a.arg[a.count].ext_string) \ + free (a.arg[a.count].ext_string); \ + } \ + free (a.arg); \ + } + + if (printf_fetchargs (args, &a) < 0) { + CLEANUP (); + errno = EINVAL; + return NULL; + } + + /* collect TYPE_POINTER_EXT argument strings */ + printf_postprocess_args (&d, &a); + + { + char *buf = + (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6); + const char *cp; + unsigned int i; + char_directive *dp; + /* Output string accumulator. */ + char *result; + size_t allocated; + size_t length; + + if (resultbuf != NULL) { + result = resultbuf; + allocated = *lengthp; + } else { + result = NULL; + allocated = 0; + } + length = 0; + /* Invariants: + result is either == resultbuf or == NULL or malloc-allocated. + If length > 0, then result != NULL. */ + +#define ENSURE_ALLOCATION(needed) \ + if ((needed) > allocated) \ + { \ + char *memory; \ + \ + allocated = (allocated > 0 ? 2 * allocated : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + if (result == resultbuf || result == NULL) \ + memory = (char *) malloc (allocated); \ + else \ + memory = (char *) realloc (result, allocated); \ + \ + if (memory == NULL) \ + { \ + if (!(result == resultbuf || result == NULL)) \ + free (result); \ + freea (buf); \ + CLEANUP (); \ + errno = ENOMEM; \ + return NULL; \ + } \ + if (result == resultbuf && length > 0) \ + memcpy (memory, result, length); \ + result = memory; \ + } + + for (cp = format, i = 0, dp = &d.dir[0];; cp = dp->dir_end, i++, dp++) { + if (cp != dp->dir_start) { + size_t n = dp->dir_start - cp; + + ENSURE_ALLOCATION (length + n); + memcpy (result + length, cp, n); + length += n; + } + if (i == d.count) + break; + + /* Execute a single directive. */ + if (dp->conversion == '%') { + if (!(dp->arg_index < 0)) + abort (); + ENSURE_ALLOCATION (length + 1); + result[length] = '%'; + length += 1; + } else { + if (!(dp->arg_index >= 0)) + abort (); + + if (dp->conversion == 'n') { + switch (a.arg[dp->arg_index].type) { + case TYPE_COUNT_SCHAR_POINTER: + *a.arg[dp->arg_index].a.a_count_schar_pointer = length; + break; + case TYPE_COUNT_SHORT_POINTER: + *a.arg[dp->arg_index].a.a_count_short_pointer = length; + break; + case TYPE_COUNT_INT_POINTER: + *a.arg[dp->arg_index].a.a_count_int_pointer = length; + break; + case TYPE_COUNT_LONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longint_pointer = length; + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } else { + arg_type type = a.arg[dp->arg_index].type; + char *p; + unsigned int prefix_count; + int prefixes[2]; +#ifndef HAVE_SNPRINTF + unsigned int tmp_length; + char tmpbuf[700]; + char *tmp; + + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + { + unsigned int width; + unsigned int precision; + + width = 0; + if (dp->width_start != dp->width_end) { + if (dp->width_arg_index >= 0) { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = (arg < 0 ? -arg : arg); + } else { + const char *digitp = dp->width_start; + + do + width = width * 10 + (*digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + precision = 6; + if (dp->precision_start != dp->precision_end) { + if (dp->precision_arg_index >= 0) { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + precision = (arg < 0 ? 0 : arg); + } else { + const char *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = precision * 10 + (*digitp++ - '0'); + } + } + + switch (dp->conversion) { + case 'd': + case 'i': + case 'u': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'o': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'x': + case 'X': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else +# endif +# ifdef HAVE_INT64_AND_I64 + if (type == TYPE_INT64 || type == TYPE_UINT64) + tmp_length = (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else + tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + break; + + case 'f': + case 'F': +# ifdef HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + tmp_length = (unsigned int) (LDBL_MAX_EXP * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + precision + 10; /* sign, decimal point etc. */ + else +# endif + tmp_length = (unsigned int) (DBL_MAX_EXP * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + precision + 10; /* sign, decimal point etc. */ + break; + + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': + tmp_length = precision + 12; /* sign, decimal point, exponent etc. */ + break; + + case 'c': +# ifdef HAVE_WINT_T + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# ifdef HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + tmp_length = (a.arg[dp->arg_index].a.a_wide_string == NULL ? 6 /* wcslen(L"(null)") */ + : local_wcslen (a.arg[dp->arg_index].a.a_wide_string)) + * MB_CUR_MAX; + else +# endif + tmp_length = a.arg[dp->arg_index].a.a_string == NULL ? 6 /* strlen("(null)") */ + : strlen (a.arg[dp->arg_index].a.a_string); + break; + + case 'p': + tmp_length = (unsigned int) (sizeof (void *) * CHAR_BIT * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + + /* make sure we always have enough space for a plain %p, so + */ + if (dp->flags & FLAG_PTR_EXT && a.arg[dp->arg_index].ext_string) + tmp_length += strlen (a.arg[dp->arg_index].ext_string); + break; + + default: + abort (); + } + + if (tmp_length < width) + tmp_length = width; + + tmp_length++; /* account for trailing NUL */ + } + + if (tmp_length <= sizeof (tmpbuf)) + tmp = tmpbuf; + else { + tmp = (char *) malloc (tmp_length); + if (tmp == NULL) { + /* Out of memory. */ + if (!(result == resultbuf || result == NULL)) + free (result); + freea (buf); + CLEANUP (); + errno = ENOMEM; + return NULL; + } + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + p = buf; + *p++ = '%'; + if (dp->flags & FLAG_GROUP) + *p++ = '\''; + if (dp->flags & FLAG_LEFT) + *p++ = '-'; + if (dp->flags & FLAG_SHOWSIGN) + *p++ = '+'; + if (dp->flags & FLAG_SPACE) + *p++ = ' '; + if (dp->flags & FLAG_ALT) + *p++ = '#'; + if (dp->flags & FLAG_ZERO) + *p++ = '0'; + if (dp->width_start != dp->width_end) { + size_t n = dp->width_end - dp->width_start; + memcpy (p, dp->width_start, n); + p += n; + } + if (dp->precision_start != dp->precision_end) { + size_t n = dp->precision_end - dp->precision_start; + memcpy (p, dp->precision_start, n); + p += n; + } + + switch (type) { +#ifdef HAVE_INT64_AND_I64 + case TYPE_INT64: + case TYPE_UINT64: + *p++ = 'I'; + *p++ = '6'; + *p++ = '4'; + break; +#endif +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: +#ifdef HAVE_INT64_AND_I64 /* The system (sn)printf uses %I64. Also assume + * that long long == __int64. + */ + *p++ = 'I'; + *p++ = '6'; + *p++ = '4'; + break; +#else + *p++ = 'l'; + /*FALLTHROUGH*/ +#endif +#endif + case TYPE_LONGINT: + case TYPE_ULONGINT: +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *p++ = 'l'; + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + *p++ = 'L'; + break; +#endif + default: + break; + } + *p = dp->conversion; +#ifdef HAVE_SNPRINTF + p[1] = '%'; + p[2] = 'n'; + p[3] = '\0'; +#else + p[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (dp->width_arg_index >= 0) { + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; + } + if (dp->precision_arg_index >= 0) { + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; + } +#ifdef HAVE_SNPRINTF + /* Prepare checking whether snprintf returns the count + via %n. */ + ENSURE_ALLOCATION (length + 1); + result[length] = '\0'; +#endif + + for (;;) { + size_t maxlen; + int count; +#ifdef HAVE_SNPRINTF + int retcount; +#endif + + maxlen = allocated - length; + count = -1; + +#ifdef HAVE_SNPRINTF + retcount = 0; + +#define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = snprintf (result + length, maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = snprintf (result + length, maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = snprintf (result + length, maxlen, buf, \ + prefixes[0], prefixes[1], arg, \ + &count); \ + break; \ + default: \ + abort (); \ + } +#else +#define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + count = sprintf (tmp, buf, arg); \ + break; \ + case 1: \ + count = sprintf (tmp, buf, prefixes[0], arg); \ + break; \ + case 2: \ + count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ + arg); \ + break; \ + default: \ + abort (); \ + } +#endif + + switch (type) { + case TYPE_SCHAR: + { + int arg = a.arg[dp->arg_index].a.a_schar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UCHAR: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uchar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_SHORT: + { + int arg = a.arg[dp->arg_index].a.a_short; + SNPRINTF_BUF (arg); + } + break; + case TYPE_USHORT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_ushort; + SNPRINTF_BUF (arg); + } + break; + case TYPE_INT: + { + int arg = a.arg[dp->arg_index].a.a_int; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGINT: + { + long int arg = a.arg[dp->arg_index].a.a_longint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGINT: + { + unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_INT64_AND_I64 + case TYPE_INT64: + { + __int64 arg = a.arg[dp->arg_index].a.a_int64; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT64: + { + unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64; + SNPRINTF_BUF (arg); + } + break; +#endif +#ifdef HAVE_LONG_LONG +#ifndef HAVE_LONG_LONG_FORMAT + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = + a.arg[dp->arg_index].a.a_ulonglongint; + int width; + int precision; + + width = 0; + if (dp->width_start != dp->width_end) { + if (dp->width_arg_index >= 0) { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = (arg < 0 ? -arg : arg); + } else { + const char *digitp = dp->width_start; + + do + width = width * 10 + (*digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + precision = -1; + if (dp->precision_start != dp->precision_end) { + if (dp->precision_arg_index >= 0) { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + precision = (arg < 0 ? 0 : arg); + } else { + const char *digitp = dp->precision_start + 1; + + precision = 0; + do + precision = precision * 10 + (*digitp++ - '0'); + while (digitp != dp->precision_end); + } + } +#ifdef HAVE_SNPRINTF + count = print_long_long (result + length, maxlen, + width, precision, dp->flags, dp->conversion, arg); +#else + count = print_long_long (tmp, tmp_length, + width, precision, dp->flags, dp->conversion, arg); +#endif + } + break; +#else + case TYPE_LONGLONGINT: + { + long long int arg = a.arg[dp->arg_index].a.a_longlongint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = + a.arg[dp->arg_index].a.a_ulonglongint; + SNPRINTF_BUF (arg); + } + break; +#endif +#endif + case TYPE_DOUBLE: + { + double arg = a.arg[dp->arg_index].a.a_double; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + { + wint_t arg = a.arg[dp->arg_index].a.a_wide_char; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_STRING: + { + const char *arg = a.arg[dp->arg_index].a.a_string == NULL + ? "(null)" : a.arg[dp->arg_index].a.a_string; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + { + const wchar_t *arg = + a.arg[dp->arg_index].a.a_wide_string == + NULL ? L"(null)" : a.arg[dp->arg_index].a.a_wide_string; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_POINTER: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + SNPRINTF_BUF (arg); + } + break; + case TYPE_POINTER_EXT: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + + if (a.arg[dp->arg_index].ext_string != NULL) { + arg = a.arg[dp->arg_index].ext_string; + *p = 's'; + } + + SNPRINTF_BUF (arg); + } + break; + default: + abort (); + } + +#ifdef HAVE_SNPRINTF + /* Portability: Not all implementations of snprintf() + are ISO C 99 compliant. Determine the number of + bytes that snprintf() has produced or would have + produced. */ + if (count >= 0) { + /* Verify that snprintf() has NUL-terminated its + result. */ + if (count < maxlen && result[length + count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } else { + /* snprintf() doesn't understand the '%n' + directive. */ + if (p[1] != '\0') { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + p[1] = '\0'; + continue; + } + count = retcount; + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) { + if (!(result == resultbuf || result == NULL)) + free (result); + freea (buf); + CLEANUP (); + errno = EINVAL; + return NULL; + } +#ifndef HAVE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + + /* Make room for the result. */ + if (count >= maxlen) { + /* Need at least count bytes. But allocate + proportionally, to avoid looping eternally if + snprintf() reports a too small count. */ + size_t n = length + count; + + if (n < 2 * allocated) + n = 2 * allocated; + + ENSURE_ALLOCATION (n); +#ifdef HAVE_SNPRINTF + continue; +#endif + } +#ifdef HAVE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count); + if (tmp != tmpbuf) + free (tmp); +#endif + + length += count; + break; + } + } + } + } + + /* Add the final NUL. */ + ENSURE_ALLOCATION (length + 1); + result[length] = '\0'; + + if (result != resultbuf && length + 1 < allocated) { + /* Shrink the allocated memory if possible. */ + char *memory; + + memory = (char *) realloc (result, length + 1); + if (memory != NULL) + result = memory; + } + + freea (buf); + CLEANUP (); + *lengthp = length; + return result; + } +} diff --git a/gst/printf/vasnprintf.h b/gst/printf/vasnprintf.h new file mode 100644 index 0000000..4920cff --- /dev/null +++ b/gst/printf/vasnprintf.h @@ -0,0 +1,61 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2003 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 _VASNPRINTF_H +#define _VASNPRINTF_H + +/* Get va_list. */ +#include + +/* Get size_t. */ +#include + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || defined (__STRICT_ANSI__) +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. */ +extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 3, 0))); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNPRINTF_H */ diff --git a/gstreamer.doap b/gstreamer.doap new file mode 100644 index 0000000..bd3530b --- /dev/null +++ b/gstreamer.doap @@ -0,0 +1,990 @@ + + + GStreamer + gstreamer + + 1999-10-31 + +GStreamer is a streaming media framework + + +GStreamer is a streaming media framework that allows the construction of +graphs of elements which operate on media data. +Applications using this library can do anything from real-time sound processing +over playing video to capturing audio, video, and even other types of media +data. +Its architecture allows for adding new data types or processing capabilities +simply by installing new plug-ins. +GStreamer is the core module, containing libraries, headers, the basic object +hierarchy, and a set of media-agnostic core elements. + + + + + + C + + + + + + + + + + + + + 1.14.1 + 1.14 + + 2018-05-17 + + + + + + + 1.14.0 + master + + 2018-03-19 + + + + + + + 1.13.91 + master + + 2018-03-13 + + + + + + + 1.13.90 + master + + 2018-03-03 + + + + + + + 1.13.1 + master + + 2018-02-15 + + + + + + + 1.12.4 + 1.12 + + 2017-12-07 + + + + + + + 1.12.3 + 1.12 + + 2017-09-18 + + + + + + + 1.12.2 + 1.12 + + 2017-07-14 + + + + + + + 1.12.1 + 1.12 + + 2017-06-20 + + + + + + + 1.12.0 + master + + 2017-05-04 + + + + + + + 1.11.91 + master + + 2017-04-27 + + + + + + + 1.11.90 + master + + 2017-04-07 + + + + + + + 1.11.2 + master + + 2017-02-24 + + + + + + + 1.11.1 + master + + 2017-01-12 + + + + + + + 1.10.0 + master + + 2016-11-01 + + + + + + + 1.9.90 + master + + 2016-09-30 + + + + + + + 1.9.2 + master + + 2016-09-01 + + + + + + + 1.9.1 + master + + 2016-06-06 + + + + + + + 1.8.0 + master + + 2016-03-24 + + + + + + + 1.7.91 + master + + 2016-03-15 + + + + + + + 1.7.90 + master + + 2016-03-01 + + + + + + + 1.7.2 + master + + 2016-02-19 + + + + + + + 1.7.1 + master + + 2015-12-24 + + + + + + + 1.6.2 + 1.6 + + 2015-12-14 + + + + + + + 1.6.1 + 1.6 + + 2015-10-30 + + + + + + + 1.6.0 + 1.6 + + 2015-09-25 + + + + + + + 1.5.91 + 1.5 + + 2015-09-18 + + + + + + + 1.5.90 + 1.5 + + 2015-08-19 + + + + + + + 1.5.2 + 1.5 + + 2015-06-24 + + + + + + + 1.5.1 + 1.5 + + 2015-06-07 + + + + + + + 1.4.0 + 1.4 + + 2014-07-19 + + + + + + + 1.3.91 + 1.3 + + 2014-07-11 + + + + + + + 1.3.90 + 1.3 + + 2014-06-28 + + + + + + + 1.3.3 + 1.3 + + 2014-06-22 + + + + + + + 1.3.2 + 1.3 + + 2014-05-21 + + + + + + + 1.3.1 + 1.3 + + 2014-05-03 + + + + + + + 1.2.0 + 1.2 + + 2013-09-24 + + + + + + + 1.1.90 + 1.1 + + 2013-09-19 + + + + + + + 1.1.4 + 1.1 + + 2013-08-28 + + + + + + + 1.1.3 + 1.1 + + 2013-07-29 + + + + + + + 1.1.2 + 1.1 + + 2013-07-11 + + + + + + + 1.1.1 + 1.1 + + 2013-06-05 + + + + + + + 1.0.2 + 1.0 + + 2012-10-24 + + + + + + + 1.0.1 + 1.0 + + 2012-10-07 + + + + + + + 1.0.0 + 1.0 + + 2012-09-24 + + + + + + + 0.11.99 + 0.11 + Allow Me to Introduce Myself + 2012-09-17 + + + + + + + 0.11.94 + 0.11 + Burning Spear + 2012-09-14 + + + + + + + 0.11.93 + 0.11 + Balrog Boogie + 2012-08-08 + + + + + + + 0.11.92 + 0.11 + High Hopes + 2012-06-07 + + + + + + + 0.11.91 + 0.11 + I will give you five magic beans! + 2012-05-13 + + + + + + + 0.11.90 + 0.11 + And all with pearl and ruby glowing was the fair palace door + 2012-04-12 + + + + + + + + 0.11.3 + 0.11 + Thrill of the Hunt + 2012-03-22 + + + + + + + + 0.11.2 + 0.11 + A Shiny white Tooth + 2012-02-16 + + + + + + + + 0.11.1 + 0.11 + Sweet New Blossom + 2011-09-29 + + + + + + + + 0.11.0 + 0.11 + It's a boy + 2011-08-02 + + + + + + + + 0.10.35 + 0.10 + Nuclear Fission + 2011-06-15 + + + + + + + + 0.10.34 + 0.10 + Misfits + 2011-05-13 + + + + + + + + 0.10.33 + 0.10 + Prior Spaceflight Experience is an Advantage + 2011-05-10 + + + + + + + + 0.10.32 + 0.10 + Take Me to the Bonus Level + 2011-01-21 + + + + + + + + 0.10.31 + 0.10 + Safety Pins + 2010-11-30 + + + + + + + + 0.10.30 + 0.10 + Safety First + 2010-07-15 + + + + + + + + 0.10.29 + 0.10 + It's a Trap + 2010-04-27 + + + + + + + + 0.10.28 + 0.10 + Same Old, Same Old + 2010-03-08 + + + + + + + + 0.10.27 + 0.10 + You're Shocked, We Know + 2010-03-05 + + + + + + + + 0.10.26 + 0.10 + Think Twice + 2010-02-09 + + + + + + + + 0.10.25 + 0.10 + Feel the burn + 2009-10-05 + + + + + + + + 0.10.24 + 0.10 + It matters + 2009-08-04 + + + + + + + + 0.10.23 + 0.10 + Alaboo Alaboo + 2009-05-10 + + + + + + + + 0.10.22 + 0.10 + I heard a disturbing sound + 2009-01-19 + + + + + + + + 0.10.21 + 0.10 + Take These Things From Me + 2008-10-02 + + + + + + + + 0.10.20 + 0.10 + You Crazy Diamond + 2008-06-18 + + + + + + + + 0.10.19 + 0.10 + Me Again + 2008-04-04 + + + + + + + 0.10.18 + 0.10 + So far away + 2008-03-21 + + + + + + + + 0.10.17 + 0.10 + Due Negligence + 2008-01-30 + + + + + + + + 0.10.15 + 0.10 + October + 2007-11-15 + + + + + + + + 0.10.14 + 0.10 + Breathing Vacuum + 2007-08-03 + + + + + + + + 0.10.13 + 0.10 + With or without you + 2007-06-05 + + + + + + + + 0.10.12 + 0.10 + Inevitable Demise + 2007-03-07 + + + + + + + + 0.10.11 + 0.10 + Love never runs on time + 2006-12-06 + + + + + + + + 0.10.10 + 0.10 + Pais + 2006-09-14 + + + + + + + + 0.10.9 + 0.10 + On the road again + 2006-07-14 + + + + + + + + 0.10.8 + 0.10 + Soepeke, ik zie ou nog altijd nie + 2006-06-10 + + + + + + + + 0.10.7 + 0.10 + Soepeke, ik zie ou + 2006-06-09 + + + + + + + + 0.10.6 + 0.10 + Leave the cannoli + 2006-05-14 + + + + + + + + + 0.10.5 + 0.10 + Fogo + 2006-04-28 + + + + + + + + 0.10.4 + 0.10 + Light + 2006-03-10 + + + + + + 0.10.3 + 0.10 + Like a virgin + 2006-02-08 + + + + + + 0.10.2 + 0.10 + If man is five + 2006-01-16 + + + + + + 0.10.1 + 0.10 + Nollaig chridheil + 2005-12-23 + + + + + + 0.10.0 + 0.10 + Maroilles + 2005-12-05 + + + + + + 0.8.12 + 0.8 + Cookies + 2006-02-09 + + + + + + + + Wim Taymans + 0d93fde052812d51a05fd86de9bdbf674423daa2 + + + + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..59990a1 --- /dev/null +++ b/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libs/Makefile.am b/libs/Makefile.am new file mode 100644 index 0000000..062cb55 --- /dev/null +++ b/libs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = gst diff --git a/libs/Makefile.in b/libs/Makefile.in new file mode 100644 index 0000000..d1a6e41 --- /dev/null +++ b/libs/Makefile.in @@ -0,0 +1,812 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = gst +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/Makefile.am b/libs/gst/Makefile.am new file mode 100644 index 0000000..c89aad1 --- /dev/null +++ b/libs/gst/Makefile.am @@ -0,0 +1,16 @@ +if HAVE_CHECK +SUBDIRS_CHECK = check +else +SUBDIRS_CHECK = +endif + +if GST_DISABLE_REGISTRY +SUBDIRS_HELPERS = +else +SUBDIRS_HELPERS = helpers +endif + +SUBDIRS_ALWAYS = base controller net + +SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_HELPERS) +DIST_SUBDIRS = $(SUBDIRS_ALWAYS) check helpers diff --git a/libs/gst/Makefile.in b/libs/gst/Makefile.in new file mode 100644 index 0000000..3429659 --- /dev/null +++ b/libs/gst/Makefile.in @@ -0,0 +1,817 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libs/gst +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@HAVE_CHECK_FALSE@SUBDIRS_CHECK = +@HAVE_CHECK_TRUE@SUBDIRS_CHECK = check +@GST_DISABLE_REGISTRY_FALSE@SUBDIRS_HELPERS = helpers +@GST_DISABLE_REGISTRY_TRUE@SUBDIRS_HELPERS = +SUBDIRS_ALWAYS = base controller net +SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_HELPERS) +DIST_SUBDIRS = $(SUBDIRS_ALWAYS) check helpers +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am new file mode 100644 index 0000000..76551f8 --- /dev/null +++ b/libs/gst/base/Makefile.am @@ -0,0 +1,108 @@ +lib_LTLIBRARIES = libgstbase-@GST_API_VERSION@.la + +libgstbase_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la +libgstbase_@GST_API_VERSION@_la_SOURCES = \ + gstadapter.c \ + gstaggregator.c \ + gstbaseparse.c \ + gstbasesink.c \ + gstbasesrc.c \ + gstbasetransform.c \ + gstbitreader.c \ + gstbytereader.c \ + gstbytewriter.c \ + gstcollectpads.c \ + gstdataqueue.c \ + gstflowcombiner.c \ + gstpushsrc.c \ + gstqueuearray.c \ + gsttypefindhelper.c + +libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstbase_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) +libgstbase_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +libgstbase_@GST_API_VERSION@includedir = \ + $(includedir)/gstreamer-@GST_API_VERSION@/gst/base + +libgstbase_@GST_API_VERSION@include_HEADERS = \ + base.h \ + base-prelude.h \ + gstadapter.h \ + gstaggregator.h \ + gstbaseparse.h \ + gstbasesink.h \ + gstbasesrc.h \ + gstbasetransform.h \ + gstbitreader.h \ + gstbytereader.h \ + gstbytewriter.h \ + gstcollectpads.h \ + gstdataqueue.h \ + gstflowcombiner.h \ + gstpushsrc.h \ + gstqueuearray.h \ + gsttypefindhelper.h + +noinst_HEADERS = \ + gstbytereader-docs.h \ + gstbytewriter-docs.h \ + gstbitreader-docs.h \ + gstindex.h + +EXTRA_DIST = gstindex.c gstmemindex.c + +CLEANFILES = *.gcno *.gcda *.gcov + +%.c.gcov: .libs/libgstbase_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstbase_@GST_API_VERSION@_la_SOURCES:=.gcov) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstBase-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@_la_SOURCES)) + +GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERSION@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ + GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ + CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ + $(INTROSPECTION_SCANNER) -v --namespace GstBase \ + --nsversion=@GST_API_VERSION@ \ + --warn-all \ + --identifier-prefix=Gst \ + --symbol-prefix=gst \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libs \ + -I$(top_builddir) \ + -I$(top_builddir)/libs \ + --c-include "gst/base/base.h" \ + --add-include-path=$(top_builddir)/gst \ + --library-path=$(top_builddir)/gst \ + --library=libgstbase-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --libtool="${LIBTOOL}" \ + --pkg gstreamer-@GST_API_VERSION@ \ + --pkg-export gstreamer-base-@GST_API_VERSION@ \ + --add-init-section="$(INTROSPECTION_INIT)" \ + --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)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif diff --git a/libs/gst/base/Makefile.in b/libs/gst/base/Makefile.in new file mode 100644 index 0000000..add96f9 --- /dev/null +++ b/libs/gst/base/Makefile.in @@ -0,0 +1,1155 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = libs/gst/base +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libgstbase_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am_libgstbase_@GST_API_VERSION@_la_OBJECTS = \ + libgstbase_@GST_API_VERSION@_la-gstadapter.lo \ + libgstbase_@GST_API_VERSION@_la-gstaggregator.lo \ + libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo \ + libgstbase_@GST_API_VERSION@_la-gstbasesink.lo \ + libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo \ + libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo \ + libgstbase_@GST_API_VERSION@_la-gstbitreader.lo \ + libgstbase_@GST_API_VERSION@_la-gstbytereader.lo \ + libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo \ + libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo \ + libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo \ + libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo \ + libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo \ + libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo \ + libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo +libgstbase_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstbase_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstbase_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) \ + $(libgstbase_@GST_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstbase_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgstbase_@GST_API_VERSION@_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstbase_@GST_API_VERSION@include_HEADERS) \ + $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libgstbase-@GST_API_VERSION@.la +libgstbase_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la + +libgstbase_@GST_API_VERSION@_la_SOURCES = \ + gstadapter.c \ + gstaggregator.c \ + gstbaseparse.c \ + gstbasesink.c \ + gstbasesrc.c \ + gstbasetransform.c \ + gstbitreader.c \ + gstbytereader.c \ + gstbytewriter.c \ + gstcollectpads.c \ + gstdataqueue.c \ + gstflowcombiner.c \ + gstpushsrc.c \ + gstqueuearray.c \ + gsttypefindhelper.c + +libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstbase_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) +libgstbase_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +libgstbase_@GST_API_VERSION@includedir = \ + $(includedir)/gstreamer-@GST_API_VERSION@/gst/base + +libgstbase_@GST_API_VERSION@include_HEADERS = \ + base.h \ + base-prelude.h \ + gstadapter.h \ + gstaggregator.h \ + gstbaseparse.h \ + gstbasesink.h \ + gstbasesrc.h \ + gstbasetransform.h \ + gstbitreader.h \ + gstbytereader.h \ + gstbytewriter.h \ + gstcollectpads.h \ + gstdataqueue.h \ + gstflowcombiner.h \ + gstpushsrc.h \ + gstqueuearray.h \ + gsttypefindhelper.h + +noinst_HEADERS = \ + gstbytereader-docs.h \ + gstbytewriter-docs.h \ + gstbitreader-docs.h \ + gstindex.h + +EXTRA_DIST = gstindex.c gstmemindex.c +CLEANFILES = *.gcno *.gcda *.gcov $(am__append_1) +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstBase-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@include_HEADERS)) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@_la_SOURCES)) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/base/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/base/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstbase-@GST_API_VERSION@.la: $(libgstbase_@GST_API_VERSION@_la_OBJECTS) $(libgstbase_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstbase_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstbase_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstbase_@GST_API_VERSION@_la_OBJECTS) $(libgstbase_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstadapter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstaggregator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbaseparse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasetransform.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbitreader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytereader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstbase_@GST_API_VERSION@_la-gstadapter.lo: gstadapter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstadapter.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstadapter.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstadapter.lo `test -f 'gstadapter.c' || echo '$(srcdir)/'`gstadapter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstadapter.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstadapter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstadapter.c' object='libgstbase_@GST_API_VERSION@_la-gstadapter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstadapter.lo `test -f 'gstadapter.c' || echo '$(srcdir)/'`gstadapter.c + +libgstbase_@GST_API_VERSION@_la-gstaggregator.lo: gstaggregator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstaggregator.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstaggregator.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstaggregator.lo `test -f 'gstaggregator.c' || echo '$(srcdir)/'`gstaggregator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstaggregator.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstaggregator.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstaggregator.c' object='libgstbase_@GST_API_VERSION@_la-gstaggregator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstaggregator.lo `test -f 'gstaggregator.c' || echo '$(srcdir)/'`gstaggregator.c + +libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo: gstbaseparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbaseparse.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo `test -f 'gstbaseparse.c' || echo '$(srcdir)/'`gstbaseparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbaseparse.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbaseparse.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbaseparse.c' object='libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbaseparse.lo `test -f 'gstbaseparse.c' || echo '$(srcdir)/'`gstbaseparse.c + +libgstbase_@GST_API_VERSION@_la-gstbasesink.lo: gstbasesink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbasesink.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesink.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbasesink.lo `test -f 'gstbasesink.c' || echo '$(srcdir)/'`gstbasesink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesink.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbasesink.c' object='libgstbase_@GST_API_VERSION@_la-gstbasesink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbasesink.lo `test -f 'gstbasesink.c' || echo '$(srcdir)/'`gstbasesink.c + +libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo: gstbasesrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesrc.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo `test -f 'gstbasesrc.c' || echo '$(srcdir)/'`gstbasesrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesrc.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasesrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbasesrc.c' object='libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbasesrc.lo `test -f 'gstbasesrc.c' || echo '$(srcdir)/'`gstbasesrc.c + +libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo: gstbasetransform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasetransform.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo `test -f 'gstbasetransform.c' || echo '$(srcdir)/'`gstbasetransform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasetransform.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbasetransform.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbasetransform.c' object='libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbasetransform.lo `test -f 'gstbasetransform.c' || echo '$(srcdir)/'`gstbasetransform.c + +libgstbase_@GST_API_VERSION@_la-gstbitreader.lo: gstbitreader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbitreader.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbitreader.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbitreader.lo `test -f 'gstbitreader.c' || echo '$(srcdir)/'`gstbitreader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbitreader.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbitreader.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbitreader.c' object='libgstbase_@GST_API_VERSION@_la-gstbitreader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbitreader.lo `test -f 'gstbitreader.c' || echo '$(srcdir)/'`gstbitreader.c + +libgstbase_@GST_API_VERSION@_la-gstbytereader.lo: gstbytereader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbytereader.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytereader.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbytereader.lo `test -f 'gstbytereader.c' || echo '$(srcdir)/'`gstbytereader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytereader.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytereader.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbytereader.c' object='libgstbase_@GST_API_VERSION@_la-gstbytereader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbytereader.lo `test -f 'gstbytereader.c' || echo '$(srcdir)/'`gstbytereader.c + +libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo: gstbytewriter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo `test -f 'gstbytewriter.c' || echo '$(srcdir)/'`gstbytewriter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbytewriter.c' object='libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo `test -f 'gstbytewriter.c' || echo '$(srcdir)/'`gstbytewriter.c + +libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo: gstcollectpads.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo `test -f 'gstcollectpads.c' || echo '$(srcdir)/'`gstcollectpads.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcollectpads.c' object='libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo `test -f 'gstcollectpads.c' || echo '$(srcdir)/'`gstcollectpads.c + +libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo: gstdataqueue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdataqueue.c' object='libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c + +libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo: gstflowcombiner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo `test -f 'gstflowcombiner.c' || echo '$(srcdir)/'`gstflowcombiner.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstflowcombiner.c' object='libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo `test -f 'gstflowcombiner.c' || echo '$(srcdir)/'`gstflowcombiner.c + +libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo: gstpushsrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo `test -f 'gstpushsrc.c' || echo '$(srcdir)/'`gstpushsrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstpushsrc.c' object='libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo `test -f 'gstpushsrc.c' || echo '$(srcdir)/'`gstpushsrc.c + +libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo: gstqueuearray.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo `test -f 'gstqueuearray.c' || echo '$(srcdir)/'`gstqueuearray.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueuearray.c' object='libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo `test -f 'gstqueuearray.c' || echo '$(srcdir)/'`gstqueuearray.c + +libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo: gsttypefindhelper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo `test -f 'gsttypefindhelper.c' || echo '$(srcdir)/'`gsttypefindhelper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttypefindhelper.c' object='libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo `test -f 'gsttypefindhelper.c' || echo '$(srcdir)/'`gsttypefindhelper.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstbase_@GST_API_VERSION@includeHEADERS: $(libgstbase_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstbase_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstbase_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-libgstbase_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstbase_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstbase_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-girDATA \ + install-libgstbase_@GST_API_VERSION@includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstbase_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-girDATA install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libgstbase_@GST_API_VERSION@includeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstbase_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +%.c.gcov: .libs/libgstbase_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstbase_@GST_API_VERSION@_la_SOURCES:=.gcov) + +@HAVE_INTROSPECTION_TRUE@GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ +@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ +@HAVE_INTROSPECTION_TRUE@ CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstBase \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Gst \ +@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=gst \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir)/libs \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir)/libs \ +@HAVE_INTROSPECTION_TRUE@ --c-include "gst/base/base.h" \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstbase-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-base-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --add-init-section="$(INTROSPECTION_INIT)" \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/base/README b/libs/gst/base/README new file mode 100644 index 0000000..7214ce2 --- /dev/null +++ b/libs/gst/base/README @@ -0,0 +1,6 @@ +Base classes +------------ + +GstBaseSink + FIXME: not much point making it operate in pull mode as a generic + base class I guess... diff --git a/libs/gst/base/base-prelude.h b/libs/gst/base/base-prelude.h new file mode 100644 index 0000000..4392817 --- /dev/null +++ b/libs/gst/base/base-prelude.h @@ -0,0 +1,31 @@ +/* GStreamer Base Library + * Copyright (C) 2018 GStreamer developers + * + * base-prelude.h: prelude include header for gst-base 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_PRELUDE_H__ +#define __GST_BASE_PRELUDE_H__ + +#include + +#ifndef GST_BASE_API +#define GST_BASE_API GST_EXPORT +#endif + +#endif /* __GST_BASE_PRELUDE_H__ */ diff --git a/libs/gst/base/base.h b/libs/gst/base/base.h new file mode 100644 index 0000000..b680e66 --- /dev/null +++ b/libs/gst/base/base.h @@ -0,0 +1,43 @@ +/* GStreamer + * Copyright (C) 2012 GStreamer developers + * + * base.h: single include header for gst-base 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_H__ +#define __GST_BASE_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* __GST_BASE_H__ */ diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c new file mode 100644 index 0000000..e3dff28 --- /dev/null +++ b/libs/gst/base/gstadapter.c @@ -0,0 +1,1795 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstadapter + * @title: GstAdapter + * @short_description: adapts incoming data on a sink pad into chunks of N bytes + * + * This class is for elements that receive buffers in an undesired size. + * While for example raw video contains one image per buffer, the same is not + * true for a lot of other formats, especially those that come directly from + * a file. So if you have undefined buffer sizes and require a specific size, + * this object is for you. + * + * An adapter is created with gst_adapter_new(). It can be freed again with + * g_object_unref(). + * + * The theory of operation is like this: All buffers received are put + * into the adapter using gst_adapter_push() and the data is then read back + * in chunks of the desired size using gst_adapter_map()/gst_adapter_unmap() + * and/or gst_adapter_copy(). After the data has been processed, it is freed + * using gst_adapter_unmap(). + * + * Other methods such as gst_adapter_take() and gst_adapter_take_buffer() + * combine gst_adapter_map() and gst_adapter_unmap() in one method and are + * potentially more convenient for some use cases. + * + * For example, a sink pad's chain function that needs to pass data to a library + * in 512-byte chunks could be implemented like this: + * |[ + * static GstFlowReturn + * sink_pad_chain (GstPad *pad, GstObject *parent, GstBuffer *buffer) + * { + * MyElement *this; + * GstAdapter *adapter; + * GstFlowReturn ret = GST_FLOW_OK; + * + * this = MY_ELEMENT (parent); + * + * adapter = this->adapter; + * + * // put buffer into adapter + * gst_adapter_push (adapter, buffer); + * + * // while we can read out 512 bytes, process them + * while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) { + * const guint8 *data = gst_adapter_map (adapter, 512); + * // use flowreturn as an error value + * ret = my_library_foo (data); + * gst_adapter_unmap (adapter); + * gst_adapter_flush (adapter, 512); + * } + * return ret; + * } + * ]| + * + * For another example, a simple element inside GStreamer that uses #GstAdapter + * is the libvisual element. + * + * An element using #GstAdapter in its sink pad chain function should ensure that + * when the FLUSH_STOP event is received, that any queued data is cleared using + * gst_adapter_clear(). Data should also be cleared or processed on EOS and + * when changing state from %GST_STATE_PAUSED to %GST_STATE_READY. + * + * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might + * need to clear the adapter after a discontinuity. + * + * The adapter will keep track of the timestamps of the buffers + * that were pushed. The last seen timestamp before the current position + * can be queried with gst_adapter_prev_pts(). This function can + * optionally return the number of bytes between the start of the buffer that + * carried the timestamp and the current adapter position. The distance is + * useful when dealing with, for example, raw audio samples because it allows + * you to calculate the timestamp of the current adapter position by using the + * last seen timestamp and the amount of bytes since. Additionally, the + * gst_adapter_prev_pts_at_offset() can be used to determine the last + * seen timestamp at a particular offset in the adapter. + * + * The adapter will also keep track of the offset of the buffers + * (#GST_BUFFER_OFFSET) that were pushed. The last seen offset before the + * current position can be queried with gst_adapter_prev_offset(). This function + * can optionally return the number of bytes between the start of the buffer + * that carried the offset and the current adapter position. + * + * Additionally the adapter also keeps track of the PTS, DTS and buffer offset + * at the last discontinuity, which can be retrieved with + * gst_adapter_pts_at_discont(), gst_adapter_dts_at_discont() and + * gst_adapter_offset_at_discont(). The number of bytes that were consumed + * since then can be queried with gst_adapter_distance_from_discont(). + * + * A last thing to note is that while #GstAdapter is pretty optimized, + * merging buffers still might be an operation that requires a malloc() and + * memcpy() operation, and these operations are not the fastest. Because of + * this, some functions like gst_adapter_available_fast() are provided to help + * speed up such cases should you want to. To avoid repeated memory allocations, + * gst_adapter_copy() can be used to copy data into a (statically allocated) + * user provided buffer. + * + * #GstAdapter is not MT safe. All operations on an adapter must be serialized by + * the caller. This is not normally a problem, however, as the normal use case + * of #GstAdapter is inside one pad's chain function, in which case access is + * serialized via the pad's STREAM_LOCK. + * + * Note that gst_adapter_push() takes ownership of the buffer passed. Use + * gst_buffer_ref() before pushing it into the adapter if you still want to + * access the buffer later. The adapter will never modify the data in the + * buffer pushed in it. + */ + +#include +#include "gstadapter.h" +#include + +/* default size for the assembled data buffer */ +#define DEFAULT_SIZE 4096 + +static void gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush); + +GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug); +#define GST_CAT_DEFAULT gst_adapter_debug + +struct _GstAdapter +{ + GObject object; + + /*< private > */ + GSList *buflist; + GSList *buflist_end; + gsize size; + gsize skip; + guint count; + + /* we keep state of assembled pieces */ + gpointer assembled_data; + gsize assembled_size; + gsize assembled_len; + + GstClockTime pts; + guint64 pts_distance; + GstClockTime dts; + guint64 dts_distance; + guint64 offset; + guint64 offset_distance; + + gsize scan_offset; + GSList *scan_entry; + + GstClockTime pts_at_discont; + GstClockTime dts_at_discont; + guint64 offset_at_discont; + + guint64 distance_from_discont; + + GstMapInfo info; +}; + +struct _GstAdapterClass +{ + GObjectClass parent_class; +}; + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size") +#define gst_adapter_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstAdapter, gst_adapter, G_TYPE_OBJECT, _do_init); + +static void gst_adapter_dispose (GObject * object); +static void gst_adapter_finalize (GObject * object); + +static void +gst_adapter_class_init (GstAdapterClass * klass) +{ + GObjectClass *object = G_OBJECT_CLASS (klass); + + object->dispose = gst_adapter_dispose; + object->finalize = gst_adapter_finalize; +} + +static void +gst_adapter_init (GstAdapter * adapter) +{ + adapter->assembled_data = g_malloc (DEFAULT_SIZE); + adapter->assembled_size = DEFAULT_SIZE; + adapter->pts = GST_CLOCK_TIME_NONE; + adapter->pts_distance = 0; + adapter->dts = GST_CLOCK_TIME_NONE; + adapter->dts_distance = 0; + adapter->offset = GST_BUFFER_OFFSET_NONE; + adapter->offset_distance = 0; + adapter->pts_at_discont = GST_CLOCK_TIME_NONE; + adapter->dts_at_discont = GST_CLOCK_TIME_NONE; + adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE; + adapter->distance_from_discont = 0; +} + +static void +gst_adapter_dispose (GObject * object) +{ + GstAdapter *adapter = GST_ADAPTER (object); + + gst_adapter_clear (adapter); + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); +} + +static void +gst_adapter_finalize (GObject * object) +{ + GstAdapter *adapter = GST_ADAPTER (object); + + g_free (adapter->assembled_data); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +/** + * gst_adapter_new: + * + * Creates a new #GstAdapter. Free with g_object_unref(). + * + * Returns: (transfer full): a new #GstAdapter + */ +GstAdapter * +gst_adapter_new (void) +{ + return g_object_new (GST_TYPE_ADAPTER, NULL); +} + +/** + * gst_adapter_clear: + * @adapter: a #GstAdapter + * + * Removes all buffers from @adapter. + */ +void +gst_adapter_clear (GstAdapter * adapter) +{ + g_return_if_fail (GST_IS_ADAPTER (adapter)); + + if (adapter->info.memory) + gst_adapter_unmap (adapter); + + g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL); + g_slist_free (adapter->buflist); + adapter->buflist = NULL; + adapter->buflist_end = NULL; + adapter->count = 0; + adapter->size = 0; + adapter->skip = 0; + adapter->assembled_len = 0; + adapter->pts = GST_CLOCK_TIME_NONE; + adapter->pts_distance = 0; + adapter->dts = GST_CLOCK_TIME_NONE; + adapter->dts_distance = 0; + adapter->offset = GST_BUFFER_OFFSET_NONE; + adapter->offset_distance = 0; + adapter->pts_at_discont = GST_CLOCK_TIME_NONE; + adapter->dts_at_discont = GST_CLOCK_TIME_NONE; + adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE; + adapter->distance_from_discont = 0; + adapter->scan_offset = 0; + adapter->scan_entry = NULL; +} + +static inline void +update_timestamps_and_offset (GstAdapter * adapter, GstBuffer * buf) +{ + GstClockTime pts, dts; + guint64 offset; + + pts = GST_BUFFER_PTS (buf); + if (GST_CLOCK_TIME_IS_VALID (pts)) { + GST_LOG_OBJECT (adapter, "new pts %" GST_TIME_FORMAT, GST_TIME_ARGS (pts)); + adapter->pts = pts; + adapter->pts_distance = 0; + } + dts = GST_BUFFER_DTS (buf); + if (GST_CLOCK_TIME_IS_VALID (dts)) { + GST_LOG_OBJECT (adapter, "new dts %" GST_TIME_FORMAT, GST_TIME_ARGS (dts)); + adapter->dts = dts; + adapter->dts_distance = 0; + } + offset = GST_BUFFER_OFFSET (buf); + if (offset != GST_BUFFER_OFFSET_NONE) { + GST_LOG_OBJECT (adapter, "new offset %" G_GUINT64_FORMAT, offset); + adapter->offset = offset; + adapter->offset_distance = 0; + } + + if (GST_BUFFER_IS_DISCONT (buf)) { + /* Take values as-is (might be NONE) */ + adapter->pts_at_discont = pts; + adapter->dts_at_discont = dts; + adapter->offset_at_discont = offset; + adapter->distance_from_discont = 0; + } +} + +/* copy data into @dest, skipping @skip bytes from the head buffers */ +static void +copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip, + gsize size) +{ + GSList *g; + GstBuffer *buf; + gsize bsize, csize; + + /* first step, do skipping */ + /* we might well be copying where we were scanning */ + if (adapter->scan_entry && (adapter->scan_offset <= skip)) { + g = adapter->scan_entry; + skip -= adapter->scan_offset; + } else { + g = adapter->buflist; + } + buf = g->data; + bsize = gst_buffer_get_size (buf); + while (G_UNLIKELY (skip >= bsize)) { + skip -= bsize; + g = g_slist_next (g); + buf = g->data; + bsize = gst_buffer_get_size (buf); + } + /* copy partial buffer */ + csize = MIN (bsize - skip, size); + GST_DEBUG ("bsize %" G_GSIZE_FORMAT ", skip %" G_GSIZE_FORMAT ", csize %" + G_GSIZE_FORMAT, bsize, skip, csize); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, "extract %" G_GSIZE_FORMAT + " bytes", csize); + gst_buffer_extract (buf, skip, dest, csize); + size -= csize; + dest += csize; + + /* second step, copy remainder */ + while (size > 0) { + g = g_slist_next (g); + buf = g->data; + bsize = gst_buffer_get_size (buf); + if (G_LIKELY (bsize > 0)) { + csize = MIN (bsize, size); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, + "extract %" G_GSIZE_FORMAT " bytes", csize); + gst_buffer_extract (buf, 0, dest, csize); + size -= csize; + dest += csize; + } + } +} + +/** + * gst_adapter_push: + * @adapter: a #GstAdapter + * @buf: (transfer full): a #GstBuffer to add to queue in the adapter + * + * Adds the data from @buf to the data stored inside @adapter and takes + * ownership of the buffer. + */ +void +gst_adapter_push (GstAdapter * adapter, GstBuffer * buf) +{ + gsize size; + + g_return_if_fail (GST_IS_ADAPTER (adapter)); + g_return_if_fail (GST_IS_BUFFER (buf)); + + size = gst_buffer_get_size (buf); + adapter->size += size; + + /* Note: merging buffers at this point is premature. */ + if (G_UNLIKELY (adapter->buflist == NULL)) { + GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " bytes", + buf, size); + adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf); + update_timestamps_and_offset (adapter, buf); + } else { + /* Otherwise append to the end, and advance our end pointer */ + GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " bytes at end, " + "size now %" G_GSIZE_FORMAT, buf, size, adapter->size); + adapter->buflist_end = g_slist_append (adapter->buflist_end, buf); + adapter->buflist_end = g_slist_next (adapter->buflist_end); + } + ++adapter->count; +} + +#if 0 +/* Internal method only. Tries to merge buffers at the head of the queue + * to form a single larger buffer of size 'size'. + * + * Returns %TRUE if it managed to merge anything. + */ +static gboolean +gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size) +{ + GstBuffer *cur, *head; + GSList *g; + gboolean ret = FALSE; + gsize hsize; + + g = adapter->buflist; + if (g == NULL) + return FALSE; + + head = g->data; + + hsize = gst_buffer_get_size (head); + + /* Remove skipped part from the buffer (otherwise the buffer might grow indefinitely) */ + head = gst_buffer_make_writable (head); + gst_buffer_resize (head, adapter->skip, hsize - adapter->skip); + hsize -= adapter->skip; + adapter->skip = 0; + g->data = head; + + g = g_slist_next (g); + + while (g != NULL && hsize < size) { + cur = g->data; + /* Merge the head buffer and the next in line */ + GST_LOG_OBJECT (adapter, "Merging buffers of size %" G_GSIZE_FORMAT " & %" + G_GSIZE_FORMAT " in search of target %" G_GSIZE_FORMAT, + hsize, gst_buffer_get_size (cur), size); + + head = gst_buffer_append (head, cur); + hsize = gst_buffer_get_size (head); + ret = TRUE; + + /* Delete the front list item, and store our new buffer in the 2nd list + * item */ + adapter->buflist = g_slist_delete_link (adapter->buflist, adapter->buflist); + g->data = head; + + /* invalidate scan position */ + adapter->scan_offset = 0; + adapter->scan_entry = NULL; + + g = g_slist_next (g); + } + + return ret; +} +#endif + +/** + * gst_adapter_map: + * @adapter: a #GstAdapter + * @size: the number of bytes to map/peek + * + * Gets the first @size bytes stored in the @adapter. The returned pointer is + * valid until the next function is called on the adapter. + * + * Note that setting the returned pointer as the data of a #GstBuffer is + * incorrect for general-purpose plugins. The reason is that if a downstream + * element stores the buffer so that it has access to it outside of the bounds + * of its chain function, the buffer will have an invalid data pointer after + * your element flushes the bytes. In that case you should use + * gst_adapter_take(), which returns a freshly-allocated buffer that you can set + * as #GstBuffer memory or the potentially more performant + * gst_adapter_take_buffer(). + * + * Returns %NULL if @size bytes are not available. + * + * Returns: (transfer none) (array length=size) (element-type guint8) (nullable): + * a pointer to the first @size bytes of data, or %NULL + */ +gconstpointer +gst_adapter_map (GstAdapter * adapter, gsize size) +{ + GstBuffer *cur; + gsize skip, csize; + gsize toreuse, tocopy; + guint8 *data; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (size > 0, NULL); + + if (adapter->info.memory) + gst_adapter_unmap (adapter); + + /* we don't have enough data, return NULL. This is unlikely + * as one usually does an _available() first instead of peeking a + * random size. */ + if (G_UNLIKELY (size > adapter->size)) + return NULL; + + /* we have enough assembled data, return it */ + if (adapter->assembled_len >= size) + return adapter->assembled_data; + +#if 0 + do { +#endif + cur = adapter->buflist->data; + skip = adapter->skip; + + csize = gst_buffer_get_size (cur); + if (csize >= size + skip) { + if (!gst_buffer_map (cur, &adapter->info, GST_MAP_READ)) + return FALSE; + + return (guint8 *) adapter->info.data + skip; + } + /* We may be able to efficiently merge buffers in our pool to + * gather a big enough chunk to return it from the head buffer directly */ +#if 0 + } while (gst_adapter_try_to_merge_up (adapter, size)); +#endif + + /* see how much data we can reuse from the assembled memory and how much + * we need to copy */ + toreuse = adapter->assembled_len; + tocopy = size - toreuse; + + /* Gonna need to copy stuff out */ + if (G_UNLIKELY (adapter->assembled_size < size)) { + adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE; + GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %" G_GSIZE_FORMAT, + adapter->assembled_size); + if (toreuse == 0) { + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "alloc new buffer"); + /* no g_realloc to avoid a memcpy that is not desired here since we are + * not going to reuse any data here */ + g_free (adapter->assembled_data); + adapter->assembled_data = g_malloc (adapter->assembled_size); + } else { + /* we are going to reuse all data, realloc then */ + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "reusing %" G_GSIZE_FORMAT " bytes", + toreuse); + adapter->assembled_data = + g_realloc (adapter->assembled_data, adapter->assembled_size); + } + } + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy remaining %" G_GSIZE_FORMAT + " bytes from adapter", tocopy); + data = adapter->assembled_data; + copy_into_unchecked (adapter, data + toreuse, skip + toreuse, tocopy); + adapter->assembled_len = size; + + return adapter->assembled_data; +} + +/** + * gst_adapter_unmap: + * @adapter: a #GstAdapter + * + * Releases the memory obtained with the last gst_adapter_map(). + */ +void +gst_adapter_unmap (GstAdapter * adapter) +{ + g_return_if_fail (GST_IS_ADAPTER (adapter)); + + if (adapter->info.memory) { + GstBuffer *cur = adapter->buflist->data; + GST_LOG_OBJECT (adapter, "unmap memory buffer %p", cur); + gst_buffer_unmap (cur, &adapter->info); + adapter->info.memory = NULL; + } +} + +/** + * gst_adapter_copy: (skip) + * @adapter: a #GstAdapter + * @dest: (out caller-allocates) (array length=size) (element-type guint8): + * the memory to copy into + * @offset: the bytes offset in the adapter to start from + * @size: the number of bytes to copy + * + * Copies @size bytes of data starting at @offset out of the buffers + * contained in #GstAdapter into an array @dest provided by the caller. + * + * The array @dest should be large enough to contain @size bytes. + * The user should check that the adapter has (@offset + @size) bytes + * available before calling this function. + */ +void +gst_adapter_copy (GstAdapter * adapter, gpointer dest, gsize offset, gsize size) +{ + g_return_if_fail (GST_IS_ADAPTER (adapter)); + g_return_if_fail (size > 0); + g_return_if_fail (offset + size <= adapter->size); + + copy_into_unchecked (adapter, dest, offset + adapter->skip, size); +} + +/** + * gst_adapter_copy_bytes: (rename-to gst_adapter_copy) + * @adapter: a #GstAdapter + * @offset: the bytes offset in the adapter to start from + * @size: the number of bytes to copy + * + * Similar to gst_adapter_copy, but more suitable for language bindings. @size + * bytes of data starting at @offset will be copied out of the buffers contained + * in @adapter and into a new #GBytes structure which is returned. Depending on + * the value of the @size argument an empty #GBytes structure may be returned. + * + * Returns: (transfer full): A new #GBytes structure containing the copied data. + * + * Since: 1.4 + */ +GBytes * +gst_adapter_copy_bytes (GstAdapter * adapter, gsize offset, gsize size) +{ + gpointer data; + data = g_malloc (size); + gst_adapter_copy (adapter, data, offset, size); + return g_bytes_new_take (data, size); +} + +/*Flushes the first @flush bytes in the @adapter*/ +static void +gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) +{ + GstBuffer *cur; + gsize size; + GSList *g; + + GST_LOG_OBJECT (adapter, "flushing %" G_GSIZE_FORMAT " bytes", flush); + + if (adapter->info.memory) + gst_adapter_unmap (adapter); + + /* clear state */ + adapter->size -= flush; + adapter->assembled_len = 0; + + /* take skip into account */ + flush += adapter->skip; + /* distance is always at least the amount of skipped bytes */ + adapter->pts_distance -= adapter->skip; + adapter->dts_distance -= adapter->skip; + adapter->offset_distance -= adapter->skip; + adapter->distance_from_discont -= adapter->skip; + + g = adapter->buflist; + cur = g->data; + size = gst_buffer_get_size (cur); + while (flush >= size) { + /* can skip whole buffer */ + GST_LOG_OBJECT (adapter, "flushing out head buffer"); + adapter->pts_distance += size; + adapter->dts_distance += size; + adapter->offset_distance += size; + adapter->distance_from_discont += size; + flush -= size; + + gst_buffer_unref (cur); + g = g_slist_delete_link (g, g); + --adapter->count; + + if (G_UNLIKELY (g == NULL)) { + GST_LOG_OBJECT (adapter, "adapter empty now"); + adapter->buflist_end = NULL; + break; + } + /* there is a new head buffer, update the timestamps */ + cur = g->data; + update_timestamps_and_offset (adapter, cur); + size = gst_buffer_get_size (cur); + } + adapter->buflist = g; + /* account for the remaining bytes */ + adapter->skip = flush; + adapter->pts_distance += flush; + adapter->dts_distance += flush; + adapter->offset_distance += flush; + adapter->distance_from_discont += flush; + /* invalidate scan position */ + adapter->scan_offset = 0; + adapter->scan_entry = NULL; +} + +/** + * gst_adapter_flush: + * @adapter: a #GstAdapter + * @flush: the number of bytes to flush + * + * Flushes the first @flush bytes in the @adapter. The caller must ensure that + * at least this many bytes are available. + * + * See also: gst_adapter_map(), gst_adapter_unmap() + */ +void +gst_adapter_flush (GstAdapter * adapter, gsize flush) +{ + g_return_if_fail (GST_IS_ADAPTER (adapter)); + g_return_if_fail (flush <= adapter->size); + + /* flushing out 0 bytes will do nothing */ + if (G_UNLIKELY (flush == 0)) + return; + + gst_adapter_flush_unchecked (adapter, flush); +} + +/* internal function, nbytes should be flushed if needed after calling this function */ +static guint8 * +gst_adapter_get_internal (GstAdapter * adapter, gsize nbytes) +{ + guint8 *data; + gsize toreuse, tocopy; + + /* see how much data we can reuse from the assembled memory and how much + * we need to copy */ + toreuse = MIN (nbytes, adapter->assembled_len); + tocopy = nbytes - toreuse; + + /* find memory to return */ + if (adapter->assembled_size >= nbytes && toreuse > 0) { + /* we reuse already allocated memory but only when we're going to reuse + * something from it because else we are worse than the malloc and copy + * case below */ + GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes of assembled" + " data", toreuse); + /* we have enough free space in the assembled array */ + data = adapter->assembled_data; + /* flush after this function should set the assembled_size to 0 */ + adapter->assembled_data = g_malloc (adapter->assembled_size); + } else { + GST_LOG_OBJECT (adapter, "allocating %" G_GSIZE_FORMAT " bytes", nbytes); + /* not enough bytes in the assembled array, just allocate new space */ + data = g_malloc (nbytes); + /* reuse what we can from the already assembled data */ + if (toreuse) { + GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes", toreuse); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, + "memcpy %" G_GSIZE_FORMAT " bytes", toreuse); + memcpy (data, adapter->assembled_data, toreuse); + } + } + if (tocopy) { + /* copy the remaining data */ + copy_into_unchecked (adapter, toreuse + data, toreuse + adapter->skip, + tocopy); + } + return data; +} + +/** + * gst_adapter_take: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to take + * + * Returns a freshly allocated buffer containing the first @nbytes bytes of the + * @adapter. The returned bytes will be flushed from the adapter. + * + * Caller owns returned value. g_free after usage. + * + * Free-function: g_free + * + * Returns: (transfer full) (array length=nbytes) (element-type guint8) (nullable): + * oven-fresh hot data, or %NULL if @nbytes bytes are not available + */ +gpointer +gst_adapter_take (GstAdapter * adapter, gsize nbytes) +{ + gpointer data; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes > 0, NULL); + + /* we don't have enough data, return NULL. This is unlikely + * as one usually does an _available() first instead of peeking a + * random size. */ + if (G_UNLIKELY (nbytes > adapter->size)) + return NULL; + + data = gst_adapter_get_internal (adapter, nbytes); + + gst_adapter_flush_unchecked (adapter, nbytes); + + return data; +} + +/** + * gst_adapter_get_buffer_fast: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to get + * + * Returns a #GstBuffer containing the first @nbytes of the @adapter, but + * does not flush them from the adapter. See gst_adapter_take_buffer_fast() + * for details. + * + * Caller owns a reference to the returned buffer. gst_buffer_unref() after + * usage. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full) (nullable): a #GstBuffer containing the first + * @nbytes of the adapter, or %NULL if @nbytes bytes are not available. + * gst_buffer_unref() when no longer needed. + * + * Since: 1.6 + */ +GstBuffer * +gst_adapter_get_buffer_fast (GstAdapter * adapter, gsize nbytes) +{ + GstBuffer *buffer = NULL; + GstBuffer *cur; + GSList *item; + gsize skip; + gsize left = nbytes; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes > 0, NULL); + + GST_LOG_OBJECT (adapter, "getting buffer of %" G_GSIZE_FORMAT " bytes", + nbytes); + + /* we don't have enough data, return NULL. This is unlikely + * as one usually does an _available() first instead of grabbing a + * random size. */ + if (G_UNLIKELY (nbytes > adapter->size)) + return NULL; + + skip = adapter->skip; + cur = adapter->buflist->data; + + if (skip == 0 && gst_buffer_get_size (cur) == nbytes) { + GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes" + " as head buffer", nbytes); + buffer = gst_buffer_ref (cur); + goto done; + } + + for (item = adapter->buflist; item && left > 0; item = item->next) { + gsize size, cur_size; + + cur = item->data; + cur_size = gst_buffer_get_size (cur); + size = MIN (cur_size - skip, left); + + GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes" + " via region copy", size); + if (buffer) + gst_buffer_copy_into (buffer, cur, + GST_BUFFER_COPY_MEMORY | GST_BUFFER_COPY_META, skip, size); + else + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size); + skip = 0; + left -= size; + } + +done: + + return buffer; +} + +/** + * gst_adapter_take_buffer_fast: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to take + * + * Returns a #GstBuffer containing the first @nbytes of the @adapter. + * The returned bytes will be flushed from the adapter. This function + * is potentially more performant than gst_adapter_take_buffer() since + * it can reuse the memory in pushed buffers by subbuffering or + * merging. Unlike gst_adapter_take_buffer(), the returned buffer may + * be composed of multiple non-contiguous #GstMemory objects, no + * copies are made. + * + * Note that no assumptions should be made as to whether certain buffer + * flags such as the DISCONT flag are set on the returned buffer, or not. + * The caller needs to explicitly set or unset flags that should be set or + * unset. + * + * This will also copy over all GstMeta of the input buffers except + * for meta with the %GST_META_FLAG_POOLED flag or with the "memory" tag. + * + * This function can return buffer up to the return value of + * gst_adapter_available() without making copies if possible. + * + * Caller owns a reference to the returned buffer. gst_buffer_unref() after + * usage. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full) (nullable): a #GstBuffer containing the first + * @nbytes of the adapter, or %NULL if @nbytes bytes are not available. + * gst_buffer_unref() when no longer needed. + * + * Since: 1.2 + */ +GstBuffer * +gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes) +{ + GstBuffer *buffer; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes > 0, NULL); + + buffer = gst_adapter_get_buffer_fast (adapter, nbytes); + if (buffer) + gst_adapter_flush_unchecked (adapter, nbytes); + + return buffer; +} + +static gboolean +foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data) +{ + GstBuffer *outbuf = user_data; + const GstMetaInfo *info = (*meta)->info; + gboolean do_copy = FALSE; + + if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) { + /* never call the transform_meta with memory specific metadata */ + GST_DEBUG ("not copying memory specific metadata %s", + g_type_name (info->api)); + do_copy = FALSE; + } else { + do_copy = TRUE; + GST_DEBUG ("copying metadata %s", g_type_name (info->api)); + } + + if (do_copy && info->transform_func) { + GstMetaTransformCopy copy_data = { FALSE, 0, -1 }; + GST_DEBUG ("copy metadata %s", g_type_name (info->api)); + /* simply copy then */ + info->transform_func (outbuf, *meta, inbuf, + _gst_meta_transform_copy, ©_data); + } + return TRUE; +} + +/** + * gst_adapter_get_buffer: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to get + * + * Returns a #GstBuffer containing the first @nbytes of the @adapter, but + * does not flush them from the adapter. See gst_adapter_take_buffer() + * for details. + * + * Caller owns a reference to the returned buffer. gst_buffer_unref() after + * usage. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full) (nullable): a #GstBuffer containing the first + * @nbytes of the adapter, or %NULL if @nbytes bytes are not available. + * gst_buffer_unref() when no longer needed. + * + * Since: 1.6 + */ +GstBuffer * +gst_adapter_get_buffer (GstAdapter * adapter, gsize nbytes) +{ + GstBuffer *buffer; + GstBuffer *cur; + gsize hsize, skip; + guint8 *data; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes > 0, NULL); + + GST_LOG_OBJECT (adapter, "getting buffer of %" G_GSIZE_FORMAT " bytes", + nbytes); + + /* we don't have enough data, return NULL. This is unlikely + * as one usually does an _available() first instead of grabbing a + * random size. */ + if (G_UNLIKELY (nbytes > adapter->size)) + return NULL; + + cur = adapter->buflist->data; + skip = adapter->skip; + hsize = gst_buffer_get_size (cur); + + /* our head buffer has enough data left, return it */ + if (skip == 0 && hsize == nbytes) { + GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes" + " as head buffer", nbytes); + buffer = gst_buffer_ref (cur); + goto done; + } else if (hsize >= nbytes + skip) { + GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes" + " via region copy", nbytes); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes); + goto done; + } +#if 0 + if (gst_adapter_try_to_merge_up (adapter, nbytes)) { + /* Merged something, let's try again for sub-buffering */ + cur = adapter->buflist->data; + skip = adapter->skip; + if (gst_buffer_get_size (cur) >= nbytes + skip) { + GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes" + " via sub-buffer", nbytes); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes); + goto done; + } + } +#endif + + data = gst_adapter_get_internal (adapter, nbytes); + + buffer = gst_buffer_new_wrapped (data, nbytes); + + { + GSList *g; + GstBuffer *cur; + gsize read_offset = 0; + + g = adapter->buflist; + while (g && read_offset < nbytes + adapter->skip) { + cur = g->data; + + gst_buffer_foreach_meta (cur, foreach_metadata, buffer); + read_offset += gst_buffer_get_size (cur); + + g = g_slist_next (g); + } + } + +done: + + return buffer; +} + +/** + * gst_adapter_take_buffer: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to take + * + * Returns a #GstBuffer containing the first @nbytes bytes of the + * @adapter. The returned bytes will be flushed from the adapter. + * This function is potentially more performant than + * gst_adapter_take() since it can reuse the memory in pushed buffers + * by subbuffering or merging. This function will always return a + * buffer with a single memory region. + * + * Note that no assumptions should be made as to whether certain buffer + * flags such as the DISCONT flag are set on the returned buffer, or not. + * The caller needs to explicitly set or unset flags that should be set or + * unset. + * + * Since 1.6 this will also copy over all GstMeta of the input buffers except + * for meta with the %GST_META_FLAG_POOLED flag or with the "memory" tag. + * + * Caller owns a reference to the returned buffer. gst_buffer_unref() after + * usage. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full) (nullable): a #GstBuffer containing the first + * @nbytes of the adapter, or %NULL if @nbytes bytes are not available. + * gst_buffer_unref() when no longer needed. + */ +GstBuffer * +gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes) +{ + GstBuffer *buffer; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes > 0, NULL); + + buffer = gst_adapter_get_buffer (adapter, nbytes); + if (buffer) + gst_adapter_flush_unchecked (adapter, nbytes); + + return buffer; +} + +/** + * gst_adapter_take_list: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to take + * + * Returns a #GList of buffers containing the first @nbytes bytes of the + * @adapter. The returned bytes will be flushed from the adapter. + * When the caller can deal with individual buffers, this function is more + * performant because no memory should be copied. + * + * Caller owns returned list and contained buffers. gst_buffer_unref() each + * buffer in the list before freeing the list after usage. + * + * Returns: (element-type Gst.Buffer) (transfer full) (nullable): a #GList of + * buffers containing the first @nbytes of the adapter, or %NULL if @nbytes + * bytes are not available + */ +GList * +gst_adapter_take_list (GstAdapter * adapter, gsize nbytes) +{ + GQueue queue = G_QUEUE_INIT; + GstBuffer *cur; + gsize hsize, skip, cur_size; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes <= adapter->size, NULL); + + GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes); + + while (nbytes > 0) { + cur = adapter->buflist->data; + skip = adapter->skip; + cur_size = gst_buffer_get_size (cur); + hsize = MIN (nbytes, cur_size - skip); + + cur = gst_adapter_take_buffer (adapter, hsize); + + g_queue_push_tail (&queue, cur); + + nbytes -= hsize; + } + return queue.head; +} + +/** + * gst_adapter_get_list: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to get + * + * Returns a #GList of buffers containing the first @nbytes bytes of the + * @adapter, but does not flush them from the adapter. See + * gst_adapter_take_list() for details. + * + * Caller owns returned list and contained buffers. gst_buffer_unref() each + * buffer in the list before freeing the list after usage. + * + * Returns: (element-type Gst.Buffer) (transfer full) (nullable): a #GList of + * buffers containing the first @nbytes of the adapter, or %NULL if @nbytes + * bytes are not available + * + * Since: 1.6 + */ +GList * +gst_adapter_get_list (GstAdapter * adapter, gsize nbytes) +{ + GQueue queue = G_QUEUE_INIT; + GstBuffer *cur, *buffer; + gsize hsize, skip, cur_size; + GSList *g = NULL; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + g_return_val_if_fail (nbytes <= adapter->size, NULL); + + GST_LOG_OBJECT (adapter, "getting %" G_GSIZE_FORMAT " bytes", nbytes); + + g = adapter->buflist; + skip = adapter->skip; + + while (nbytes > 0) { + cur = g->data; + cur_size = gst_buffer_get_size (cur); + hsize = MIN (nbytes, cur_size - skip); + + if (skip == 0 && cur_size == hsize) { + GST_LOG_OBJECT (adapter, + "inserting a buffer of %" G_GSIZE_FORMAT " bytes", hsize); + buffer = gst_buffer_ref (cur); + } else { + GST_LOG_OBJECT (adapter, "inserting a buffer of %" G_GSIZE_FORMAT " bytes" + " via region copy", hsize); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, hsize); + } + + g_queue_push_tail (&queue, buffer); + + nbytes -= hsize; + skip = 0; + g = g_slist_next (g); + } + + return queue.head; +} + +/** + * gst_adapter_take_buffer_list: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to take + * + * Returns a #GstBufferList of buffers containing the first @nbytes bytes of + * the @adapter. The returned bytes will be flushed from the adapter. + * When the caller can deal with individual buffers, this function is more + * performant because no memory should be copied. + * + * Caller owns the returned list. Call gst_buffer_list_unref() to free + * the list after usage. + * + * Returns: (transfer full) (nullable): a #GstBufferList of buffers containing + * the first @nbytes of the adapter, or %NULL if @nbytes bytes are not + * available + * + * Since: 1.6 + */ +GstBufferList * +gst_adapter_take_buffer_list (GstAdapter * adapter, gsize nbytes) +{ + GstBufferList *buffer_list; + GstBuffer *cur; + gsize hsize, skip, cur_size; + guint n_bufs; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + + if (nbytes > adapter->size) + return NULL; + + GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes); + + /* try to create buffer list with sufficient size, so no resize is done later */ + if (adapter->count < 64) + n_bufs = adapter->count; + else + n_bufs = (adapter->count * nbytes * 1.2 / adapter->size) + 1; + + buffer_list = gst_buffer_list_new_sized (n_bufs); + + while (nbytes > 0) { + cur = adapter->buflist->data; + skip = adapter->skip; + cur_size = gst_buffer_get_size (cur); + hsize = MIN (nbytes, cur_size - skip); + + gst_buffer_list_add (buffer_list, gst_adapter_take_buffer (adapter, hsize)); + nbytes -= hsize; + } + return buffer_list; +} + +/** + * gst_adapter_get_buffer_list: + * @adapter: a #GstAdapter + * @nbytes: the number of bytes to get + * + * Returns a #GstBufferList of buffers containing the first @nbytes bytes of + * the @adapter but does not flush them from the adapter. See + * gst_adapter_take_buffer_list() for details. + * + * Caller owns the returned list. Call gst_buffer_list_unref() to free + * the list after usage. + * + * Returns: (transfer full) (nullable): a #GstBufferList of buffers containing + * the first @nbytes of the adapter, or %NULL if @nbytes bytes are not + * available + * + * Since: 1.6 + */ +GstBufferList * +gst_adapter_get_buffer_list (GstAdapter * adapter, gsize nbytes) +{ + GstBufferList *buffer_list; + GstBuffer *cur, *buffer; + gsize hsize, skip, cur_size; + guint n_bufs; + GSList *g = NULL; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); + + if (nbytes > adapter->size) + return NULL; + + GST_LOG_OBJECT (adapter, "getting %" G_GSIZE_FORMAT " bytes", nbytes); + + /* try to create buffer list with sufficient size, so no resize is done later */ + if (adapter->count < 64) + n_bufs = adapter->count; + else + n_bufs = (adapter->count * nbytes * 1.2 / adapter->size) + 1; + + buffer_list = gst_buffer_list_new_sized (n_bufs); + + g = adapter->buflist; + skip = adapter->skip; + + while (nbytes > 0) { + cur = g->data; + cur_size = gst_buffer_get_size (cur); + hsize = MIN (nbytes, cur_size - skip); + + if (skip == 0 && cur_size == hsize) { + GST_LOG_OBJECT (adapter, + "inserting a buffer of %" G_GSIZE_FORMAT " bytes", hsize); + buffer = gst_buffer_ref (cur); + } else { + GST_LOG_OBJECT (adapter, "inserting a buffer of %" G_GSIZE_FORMAT " bytes" + " via region copy", hsize); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, hsize); + } + + gst_buffer_list_add (buffer_list, buffer); + + nbytes -= hsize; + skip = 0; + g = g_slist_next (g); + } + + return buffer_list; +} + +/** + * gst_adapter_available: + * @adapter: a #GstAdapter + * + * Gets the maximum amount of bytes available, that is it returns the maximum + * value that can be supplied to gst_adapter_map() without that function + * returning %NULL. + * + * Returns: number of bytes available in @adapter + */ +gsize +gst_adapter_available (GstAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0); + + return adapter->size; +} + +/** + * gst_adapter_available_fast: + * @adapter: a #GstAdapter + * + * Gets the maximum number of bytes that are immediately available without + * requiring any expensive operations (like copying the data into a + * temporary buffer). + * + * Returns: number of bytes that are available in @adapter without expensive + * operations + */ +gsize +gst_adapter_available_fast (GstAdapter * adapter) +{ + GstBuffer *cur; + gsize size; + GSList *g; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0); + + /* no data */ + if (adapter->size == 0) + return 0; + + /* some stuff we already assembled */ + if (adapter->assembled_len) + return adapter->assembled_len; + + /* take the first non-zero buffer */ + g = adapter->buflist; + while (TRUE) { + cur = g->data; + size = gst_buffer_get_size (cur); + if (size != 0) + break; + g = g_slist_next (g); + } + + /* we can quickly get the (remaining) data of the first buffer */ + return size - adapter->skip; +} + +/** + * gst_adapter_get_distance_from_discont: + * @adapter: a #GstAdapter + * + * Get the distance in bytes since the last buffer with the + * %GST_BUFFER_FLAG_DISCONT flag. + * + * The distance will be reset to 0 for all buffers with + * %GST_BUFFER_FLAG_DISCONT on them, and then calculated for all other + * following buffers based on their size. + * + * Since: 1.10 + * + * Returns: The offset. Can be %GST_BUFFER_OFFSET_NONE. + */ +guint64 +gst_adapter_distance_from_discont (GstAdapter * adapter) +{ + return adapter->distance_from_discont; +} + +/** + * gst_adapter_offset_at_discont: + * @adapter: a #GstAdapter + * + * Get the offset that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_BUFFER_OFFSET_NONE. + * + * Since: 1.10 + * + * Returns: The offset at the last discont or GST_BUFFER_OFFSET_NONE. + */ +guint64 +gst_adapter_offset_at_discont (GstAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_BUFFER_OFFSET_NONE); + + return adapter->offset_at_discont; +} + +/** + * gst_adapter_pts_at_discont: + * @adapter: a #GstAdapter + * + * Get the PTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_CLOCK_TIME_NONE. + * + * Since: 1.10 + * + * Returns: The PTS at the last discont or GST_CLOCK_TIME_NONE. + */ +GstClockTime +gst_adapter_pts_at_discont (GstAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + return adapter->pts_at_discont; +} + +/** + * gst_adapter_dts_at_discont: + * @adapter: a #GstAdapter + * + * Get the DTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_CLOCK_TIME_NONE. + * + * Since: 1.10 + * + * Returns: The DTS at the last discont or GST_CLOCK_TIME_NONE. + */ +GstClockTime +gst_adapter_dts_at_discont (GstAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + return adapter->dts_at_discont; +} + +/** + * gst_adapter_prev_offset: + * @adapter: a #GstAdapter + * @distance: (out) (allow-none): pointer to a location for distance, or %NULL + * + * Get the offset that was before the current byte in the adapter. When + * @distance is given, the amount of bytes between the offset and the current + * position is returned. + * + * The offset is reset to GST_BUFFER_OFFSET_NONE and the distance is set to 0 + * when the adapter is first created or when it is cleared. This also means that + * before the first byte with an offset is removed from the adapter, the offset + * and distance returned are GST_BUFFER_OFFSET_NONE and 0 respectively. + * + * Since: 1.10 + * + * Returns: The previous seen offset. + */ +guint64 +gst_adapter_prev_offset (GstAdapter * adapter, guint64 * distance) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_BUFFER_OFFSET_NONE); + + if (distance) + *distance = adapter->offset_distance; + + return adapter->offset; +} + +/** + * gst_adapter_prev_pts: + * @adapter: a #GstAdapter + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the pts that was before the current byte in the adapter. When + * @distance is given, the amount of bytes between the pts and the current + * position is returned. + * + * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * the adapter is first created or when it is cleared. This also means that before + * the first byte with a pts is removed from the adapter, the pts + * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. + * + * Returns: The previously seen pts. + */ +GstClockTime +gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + if (distance) + *distance = adapter->pts_distance; + + return adapter->pts; +} + +/** + * gst_adapter_prev_dts: + * @adapter: a #GstAdapter + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the dts that was before the current byte in the adapter. When + * @distance is given, the amount of bytes between the dts and the current + * position is returned. + * + * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * the adapter is first created or when it is cleared. This also means that before + * the first byte with a dts is removed from the adapter, the dts + * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. + * + * Returns: The previously seen dts. + */ +GstClockTime +gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + if (distance) + *distance = adapter->dts_distance; + + return adapter->dts; +} + +/** + * gst_adapter_prev_pts_at_offset: + * @adapter: a #GstAdapter + * @offset: the offset in the adapter at which to get timestamp + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the pts that was before the byte at offset @offset in the adapter. When + * @distance is given, the amount of bytes between the pts and the current + * position is returned. + * + * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * the adapter is first created or when it is cleared. This also means that before + * the first byte with a pts is removed from the adapter, the pts + * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. + * + * Since: 1.2 + * Returns: The previously seen pts at given offset. + */ +GstClockTime +gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset, + guint64 * distance) +{ + GstBuffer *cur; + GSList *g; + gsize read_offset = 0; + gsize pts_offset = 0; + GstClockTime pts = adapter->pts; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + g = adapter->buflist; + + while (g && read_offset < offset + adapter->skip) { + cur = g->data; + + if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (cur))) { + pts = GST_BUFFER_PTS (cur); + pts_offset = read_offset; + } + + read_offset += gst_buffer_get_size (cur); + g = g_slist_next (g); + } + + if (distance) + *distance = adapter->pts_distance + offset - pts_offset; + + return pts; +} + +/** + * gst_adapter_prev_dts_at_offset: + * @adapter: a #GstAdapter + * @offset: the offset in the adapter at which to get timestamp + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the dts that was before the byte at offset @offset in the adapter. When + * @distance is given, the amount of bytes between the dts and the current + * position is returned. + * + * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * the adapter is first created or when it is cleared. This also means that before + * the first byte with a dts is removed from the adapter, the dts + * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. + * + * Since: 1.2 + * Returns: The previously seen dts at given offset. + */ +GstClockTime +gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset, + guint64 * distance) +{ + GstBuffer *cur; + GSList *g; + gsize read_offset = 0; + gsize dts_offset = 0; + GstClockTime dts = adapter->dts; + + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + g = adapter->buflist; + + while (g && read_offset < offset + adapter->skip) { + cur = g->data; + + if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cur))) { + dts = GST_BUFFER_DTS (cur); + dts_offset = read_offset; + } + + read_offset += gst_buffer_get_size (cur); + g = g_slist_next (g); + } + + if (distance) + *distance = adapter->dts_distance + offset - dts_offset; + + return dts; +} + +/** + * gst_adapter_masked_scan_uint32_peek: + * @adapter: a #GstAdapter + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset into the adapter data from which to start scanning, returns + * the last scanned position. + * @size: number of bytes to scan from offset + * @value: (out) (allow-none): pointer to uint32 to return matching data + * + * Scan for pattern @pattern with applied mask @mask in the adapter data, + * starting from offset @offset. If a match is found, the value that matched + * is returned through @value, otherwise @value is left untouched. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * adapter for it to match, even if the first or last bytes are masked out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the adapter. + * + * Returns: offset of the first match, or -1 if no match was found. + */ +gssize +gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, + guint32 pattern, gsize offset, gsize size, guint32 * value) +{ + GSList *g; + gsize skip, bsize, i; + guint32 state; + GstMapInfo info; + guint8 *bdata; + GstBuffer *buf; + + g_return_val_if_fail (size > 0, -1); + g_return_val_if_fail (offset + size <= adapter->size, -1); + g_return_val_if_fail (((~mask) & pattern) == 0, -1); + + /* we can't find the pattern with less than 4 bytes */ + if (G_UNLIKELY (size < 4)) + return -1; + + skip = offset + adapter->skip; + + /* first step, do skipping and position on the first buffer */ + /* optimistically assume scanning continues sequentially */ + if (adapter->scan_entry && (adapter->scan_offset <= skip)) { + g = adapter->scan_entry; + skip -= adapter->scan_offset; + } else { + g = adapter->buflist; + adapter->scan_offset = 0; + adapter->scan_entry = NULL; + } + buf = g->data; + bsize = gst_buffer_get_size (buf); + while (G_UNLIKELY (skip >= bsize)) { + skip -= bsize; + g = g_slist_next (g); + adapter->scan_offset += bsize; + adapter->scan_entry = g; + buf = g->data; + bsize = gst_buffer_get_size (buf); + } + /* get the data now */ + if (!gst_buffer_map (buf, &info, GST_MAP_READ)) + return -1; + + bdata = (guint8 *) info.data + skip; + bsize = info.size - skip; + skip = 0; + + /* set the state to something that does not match */ + state = ~pattern; + + /* now find data */ + do { + bsize = MIN (bsize, size); + for (i = 0; i < bsize; i++) { + state = ((state << 8) | bdata[i]); + if (G_UNLIKELY ((state & mask) == pattern)) { + /* we have a match but we need to have skipped at + * least 4 bytes to fill the state. */ + if (G_LIKELY (skip + i >= 3)) { + if (G_LIKELY (value)) + *value = state; + gst_buffer_unmap (buf, &info); + return offset + skip + i - 3; + } + } + } + size -= bsize; + if (size == 0) + break; + + /* nothing found yet, go to next buffer */ + skip += bsize; + g = g_slist_next (g); + adapter->scan_offset += info.size; + adapter->scan_entry = g; + gst_buffer_unmap (buf, &info); + buf = g->data; + + if (!gst_buffer_map (buf, &info, GST_MAP_READ)) + return -1; + + bsize = info.size; + bdata = info.data; + } while (TRUE); + + gst_buffer_unmap (buf, &info); + + /* nothing found */ + return -1; +} + +/** + * gst_adapter_masked_scan_uint32: + * @adapter: a #GstAdapter + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset into the adapter data from which to start scanning, returns + * the last scanned position. + * @size: number of bytes to scan from offset + * + * Scan for pattern @pattern with applied mask @mask in the adapter data, + * starting from offset @offset. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * adapter for it to match, even if the first or last bytes are masked out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the adapter. + * + * This function calls gst_adapter_masked_scan_uint32_peek() passing %NULL + * for value. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Example: + * |[ + * // Assume the adapter contains 0x00 0x01 0x02 ... 0xfe 0xff + * + * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 256); + * // -> returns 0 + * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 1, 255); + * // -> returns -1 + * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 255); + * // -> returns 1 + * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0001, 0, 256); + * // -> returns -1 + * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0203, 0, 256); + * // -> returns 0 + * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 256); + * // -> returns 2 + * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 4); + * // -> returns -1 + * ]| + */ +gssize +gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask, + guint32 pattern, gsize offset, gsize size) +{ + return gst_adapter_masked_scan_uint32_peek (adapter, mask, pattern, offset, + size, NULL); +} diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h new file mode 100644 index 0000000..3e7610e --- /dev/null +++ b/libs/gst/base/gstadapter.h @@ -0,0 +1,151 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#ifndef __GST_ADAPTER_H__ +#define __GST_ADAPTER_H__ + +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_ADAPTER \ + (gst_adapter_get_type()) +#define GST_ADAPTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ADAPTER, GstAdapter)) +#define GST_ADAPTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ADAPTER, GstAdapterClass)) +#define GST_ADAPTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ADAPTER, GstAdapterClass)) +#define GST_IS_ADAPTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_ADAPTER)) +#define GST_IS_ADAPTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ADAPTER)) + +/** + * GstAdapter: + * + * The opaque #GstAdapter data structure. + */ +typedef struct _GstAdapter GstAdapter; +typedef struct _GstAdapterClass GstAdapterClass; + +GST_BASE_API +GType gst_adapter_get_type (void); + +GST_BASE_API +GstAdapter * gst_adapter_new (void) G_GNUC_MALLOC; + +GST_BASE_API +void gst_adapter_clear (GstAdapter *adapter); + +GST_BASE_API +void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf); + +GST_BASE_API +gconstpointer gst_adapter_map (GstAdapter *adapter, gsize size); + +GST_BASE_API +void gst_adapter_unmap (GstAdapter *adapter); + +GST_BASE_API +void gst_adapter_copy (GstAdapter *adapter, gpointer dest, + gsize offset, gsize size); +GST_BASE_API +GBytes * gst_adapter_copy_bytes (GstAdapter *adapter, + gsize offset, gsize size); +GST_BASE_API +void gst_adapter_flush (GstAdapter *adapter, gsize flush); + +GST_BASE_API +gpointer gst_adapter_take (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GList* gst_adapter_take_list (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBuffer * gst_adapter_take_buffer_fast (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBufferList * gst_adapter_take_buffer_list (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBuffer* gst_adapter_get_buffer (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GList* gst_adapter_get_list (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBuffer * gst_adapter_get_buffer_fast (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +GstBufferList * gst_adapter_get_buffer_list (GstAdapter *adapter, gsize nbytes); + +GST_BASE_API +gsize gst_adapter_available (GstAdapter *adapter); + +GST_BASE_API +gsize gst_adapter_available_fast (GstAdapter *adapter); + +GST_BASE_API +GstClockTime gst_adapter_prev_pts (GstAdapter *adapter, guint64 *distance); + +GST_BASE_API +GstClockTime gst_adapter_prev_dts (GstAdapter *adapter, guint64 *distance); + +GST_BASE_API +GstClockTime gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance); + +GST_BASE_API +GstClockTime gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance); + +GST_BASE_API +guint64 gst_adapter_prev_offset (GstAdapter *adapter, guint64 *distance); + +GST_BASE_API +GstClockTime gst_adapter_pts_at_discont (GstAdapter *adapter); + +GST_BASE_API +GstClockTime gst_adapter_dts_at_discont (GstAdapter *adapter); + +GST_BASE_API +guint64 gst_adapter_offset_at_discont (GstAdapter *adapter); + +GST_BASE_API +guint64 gst_adapter_distance_from_discont (GstAdapter *adapter); + +GST_BASE_API +gssize gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask, + guint32 pattern, gsize offset, gsize size); +GST_BASE_API +gssize gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, + guint32 pattern, gsize offset, gsize size, guint32 * value); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAdapter, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_ADAPTER_H__ */ diff --git a/libs/gst/base/gstaggregator.c b/libs/gst/base/gstaggregator.c new file mode 100644 index 0000000..b72b013 --- /dev/null +++ b/libs/gst/base/gstaggregator.c @@ -0,0 +1,3112 @@ +/* GStreamer aggregator base class + * Copyright (C) 2014 Mathieu Duponchelle + * Copyright (C) 2014 Thibault Saunier + * + * gstaggregator.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION: gstaggregator + * @title: GstAggregator + * @short_description: Base class for mixers and muxers, manages a set of input + * pads and aggregates their streams + * @see_also: gstcollectpads for historical reasons. + * + * Manages a set of pads with the purpose of aggregating their buffers. + * Control is given to the subclass when all pads have data. + * + * * Base class for mixers and muxers. Subclasses should at least implement + * the #GstAggregatorClass.aggregate() virtual method. + * + * * Installs a #GstPadChainFunction, a #GstPadEventFullFunction and a + * #GstPadQueryFunction to queue all serialized data packets per sink pad. + * Subclasses should not overwrite those, but instead implement + * #GstAggregatorClass.sink_event() and #GstAggregatorClass.sink_query() as + * needed. + * + * * When data is queued on all pads, the aggregate vmethod is called. + * + * * One can peek at the data on any given GstAggregatorPad with the + * gst_aggregator_pad_peek_buffer () method, and remove it from the pad + * with the gst_aggregator_pad_pop_buffer () method. When a buffer + * has been taken with pop_buffer (), a new buffer can be queued + * on that pad. + * + * * If the subclass wishes to push a buffer downstream in its aggregate + * implementation, it should do so through the + * gst_aggregator_finish_buffer () method. This method will take care + * of sending and ordering mandatory events such as stream start, caps + * and segment. + * + * * Same goes for EOS events, which should not be pushed directly by the + * subclass, it should instead return GST_FLOW_EOS in its aggregate + * implementation. + * + * * Note that the aggregator logic regarding gap event handling is to turn + * these into gap buffers with matching PTS and duration. It will also + * flag these buffers with GST_BUFFER_FLAG_GAP and GST_BUFFER_FLAG_DROPPABLE + * to ease their identification and subsequent processing. + * + * * Subclasses must use (a subclass of) #GstAggregatorPad for both their + * sink and source pads. + * See gst_element_class_add_static_pad_template_with_gtype(). + * + * This class used to live in gst-plugins-bad and was moved to core. + * + * Since: 1.14 + */ + +/** + * SECTION: gstaggregatorpad + * @title: GstAggregatorPad + * @short_description: #GstPad subclass for pads managed by #GstAggregator + * @see_also: gstcollectpads for historical reasons. + * + * Pads managed by a #GstAggregor subclass. + * + * This class used to live in gst-plugins-bad and was moved to core. + * + * Since: 1.14 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* strlen */ + +#include "gstaggregator.h" + +typedef enum +{ + GST_AGGREGATOR_START_TIME_SELECTION_ZERO, + GST_AGGREGATOR_START_TIME_SELECTION_FIRST, + GST_AGGREGATOR_START_TIME_SELECTION_SET +} GstAggregatorStartTimeSelection; + +static GType +gst_aggregator_start_time_selection_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {GST_AGGREGATOR_START_TIME_SELECTION_ZERO, + "Start at 0 running time (default)", "zero"}, + {GST_AGGREGATOR_START_TIME_SELECTION_FIRST, + "Start at first observed input running time", "first"}, + {GST_AGGREGATOR_START_TIME_SELECTION_SET, + "Set start time with start-time property", "set"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstAggregatorStartTimeSelection", values); + } + return gtype; +} + +/* Might become API */ +#if 0 +static void gst_aggregator_merge_tags (GstAggregator * aggregator, + const GstTagList * tags, GstTagMergeMode mode); +#endif +static void gst_aggregator_set_latency_property (GstAggregator * agg, + GstClockTime latency); +static GstClockTime gst_aggregator_get_latency_property (GstAggregator * agg); + +static GstClockTime gst_aggregator_get_latency_unlocked (GstAggregator * self); + +static void gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad); + +GST_DEBUG_CATEGORY_STATIC (aggregator_debug); +#define GST_CAT_DEFAULT aggregator_debug + +/* Locking order, locks in this element must always be taken in this order + * + * standard sink pad stream lock -> GST_PAD_STREAM_LOCK (aggpad) + * Aggregator pad flush lock -> PAD_FLUSH_LOCK(aggpad) + * standard src pad stream lock -> GST_PAD_STREAM_LOCK (srcpad) + * Aggregator src lock -> SRC_LOCK(agg) w/ SRC_WAIT/BROADCAST + * standard element object lock -> GST_OBJECT_LOCK(agg) + * Aggregator pad lock -> PAD_LOCK (aggpad) w/ PAD_WAIT/BROADCAST_EVENT(aggpad) + * standard src pad object lock -> GST_OBJECT_LOCK(srcpad) + * standard sink pad object lock -> GST_OBJECT_LOCK(aggpad) + */ + +/* GstAggregatorPad definitions */ +#define PAD_LOCK(pad) G_STMT_START { \ + GST_TRACE_OBJECT (pad, "Taking PAD lock from thread %p", \ + g_thread_self()); \ + g_mutex_lock(&pad->priv->lock); \ + GST_TRACE_OBJECT (pad, "Took PAD lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define PAD_UNLOCK(pad) G_STMT_START { \ + GST_TRACE_OBJECT (pad, "Releasing PAD lock from thread %p", \ + g_thread_self()); \ + g_mutex_unlock(&pad->priv->lock); \ + GST_TRACE_OBJECT (pad, "Release PAD lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + + +#define PAD_WAIT_EVENT(pad) G_STMT_START { \ + GST_LOG_OBJECT (pad, "Waiting for buffer to be consumed thread %p", \ + g_thread_self()); \ + g_cond_wait(&(((GstAggregatorPad* )pad)->priv->event_cond), \ + (&((GstAggregatorPad*)pad)->priv->lock)); \ + GST_LOG_OBJECT (pad, "DONE Waiting for buffer to be consumed on thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define PAD_BROADCAST_EVENT(pad) G_STMT_START { \ + GST_LOG_OBJECT (pad, "Signaling buffer consumed from thread %p", \ + g_thread_self()); \ + g_cond_broadcast(&(((GstAggregatorPad* )pad)->priv->event_cond)); \ + } G_STMT_END + + +#define PAD_FLUSH_LOCK(pad) G_STMT_START { \ + GST_TRACE_OBJECT (pad, "Taking lock from thread %p", \ + g_thread_self()); \ + g_mutex_lock(&pad->priv->flush_lock); \ + GST_TRACE_OBJECT (pad, "Took lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define PAD_FLUSH_UNLOCK(pad) G_STMT_START { \ + GST_TRACE_OBJECT (pad, "Releasing lock from thread %p", \ + g_thread_self()); \ + g_mutex_unlock(&pad->priv->flush_lock); \ + GST_TRACE_OBJECT (pad, "Release lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define SRC_LOCK(self) G_STMT_START { \ + GST_TRACE_OBJECT (self, "Taking src lock from thread %p", \ + g_thread_self()); \ + g_mutex_lock(&self->priv->src_lock); \ + GST_TRACE_OBJECT (self, "Took src lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define SRC_UNLOCK(self) G_STMT_START { \ + GST_TRACE_OBJECT (self, "Releasing src lock from thread %p", \ + g_thread_self()); \ + g_mutex_unlock(&self->priv->src_lock); \ + GST_TRACE_OBJECT (self, "Released src lock from thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define SRC_WAIT(self) G_STMT_START { \ + GST_LOG_OBJECT (self, "Waiting for src on thread %p", \ + g_thread_self()); \ + g_cond_wait(&(self->priv->src_cond), &(self->priv->src_lock)); \ + GST_LOG_OBJECT (self, "DONE Waiting for src on thread %p", \ + g_thread_self()); \ + } G_STMT_END + +#define SRC_BROADCAST(self) G_STMT_START { \ + GST_LOG_OBJECT (self, "Signaling src from thread %p", \ + g_thread_self()); \ + if (self->priv->aggregate_id) \ + gst_clock_id_unschedule (self->priv->aggregate_id); \ + g_cond_broadcast(&(self->priv->src_cond)); \ + } G_STMT_END + +struct _GstAggregatorPadPrivate +{ + /* Following fields are protected by the PAD_LOCK */ + GstFlowReturn flow_return; + gboolean pending_flush_start; + gboolean pending_flush_stop; + + gboolean first_buffer; + + GQueue data; /* buffers, events and queries */ + GstBuffer *clipped_buffer; + guint num_buffers; + + /* used to track fill state of queues, only used with live-src and when + * latency property is set to > 0 */ + GstClockTime head_position; + GstClockTime tail_position; + GstClockTime head_time; /* running time */ + GstClockTime tail_time; + GstClockTime time_level; /* how much head is ahead of tail */ + GstSegment head_segment; /* segment before the queue */ + + gboolean negotiated; + + gboolean eos; + + GMutex lock; + GCond event_cond; + /* This lock prevents a flush start processing happening while + * the chain function is also happening. + */ + GMutex flush_lock; +}; + +/* Must be called with PAD_LOCK held */ +static void +gst_aggregator_pad_reset_unlocked (GstAggregatorPad * aggpad) +{ + aggpad->priv->eos = FALSE; + aggpad->priv->flow_return = GST_FLOW_OK; + GST_OBJECT_LOCK (aggpad); + gst_segment_init (&aggpad->segment, GST_FORMAT_UNDEFINED); + gst_segment_init (&aggpad->priv->head_segment, GST_FORMAT_UNDEFINED); + GST_OBJECT_UNLOCK (aggpad); + aggpad->priv->head_position = GST_CLOCK_TIME_NONE; + aggpad->priv->tail_position = GST_CLOCK_TIME_NONE; + aggpad->priv->head_time = GST_CLOCK_TIME_NONE; + aggpad->priv->tail_time = GST_CLOCK_TIME_NONE; + aggpad->priv->time_level = 0; + aggpad->priv->first_buffer = TRUE; +} + +static gboolean +gst_aggregator_pad_flush (GstAggregatorPad * aggpad, GstAggregator * agg) +{ + GstAggregatorPadClass *klass = GST_AGGREGATOR_PAD_GET_CLASS (aggpad); + + PAD_LOCK (aggpad); + gst_aggregator_pad_reset_unlocked (aggpad); + PAD_UNLOCK (aggpad); + + if (klass->flush) + return klass->flush (aggpad, agg); + + return TRUE; +} + +/************************************* + * GstAggregator implementation * + *************************************/ +static GstElementClass *aggregator_parent_class = NULL; + +/* All members are protected by the object lock unless otherwise noted */ + +struct _GstAggregatorPrivate +{ + gint max_padserial; + + /* Our state is >= PAUSED */ + gboolean running; /* protected by src_lock */ + + /* seqnum from seek or segment, + * to be applied to synthetic segment/eos events */ + gint seqnum; + gboolean send_stream_start; /* protected by srcpad stream lock */ + gboolean send_segment; + gboolean flush_seeking; + gboolean pending_flush_start; + gboolean send_eos; /* protected by srcpad stream lock */ + + GstCaps *srccaps; /* protected by the srcpad stream lock */ + + GstTagList *tags; + gboolean tags_changed; + + gboolean peer_latency_live; /* protected by src_lock */ + GstClockTime peer_latency_min; /* protected by src_lock */ + GstClockTime peer_latency_max; /* protected by src_lock */ + gboolean has_peer_latency; /* protected by src_lock */ + + GstClockTime sub_latency_min; /* protected by src_lock */ + GstClockTime sub_latency_max; /* protected by src_lock */ + + /* aggregate */ + GstClockID aggregate_id; /* protected by src_lock */ + GMutex src_lock; + GCond src_cond; + + gboolean first_buffer; /* protected by object lock */ + GstAggregatorStartTimeSelection start_time_selection; + GstClockTime start_time; + + /* protected by the object lock */ + GstQuery *allocation_query; + GstAllocator *allocator; + GstBufferPool *pool; + GstAllocationParams allocation_params; + + /* properties */ + gint64 latency; /* protected by both src_lock and all pad locks */ +}; + +/* Seek event forwarding helper */ +typedef struct +{ + /* parameters */ + GstEvent *event; + gboolean flush; + gboolean only_to_active_pads; + + /* results */ + gboolean result; + gboolean one_actually_seeked; +} EventData; + +#define DEFAULT_LATENCY 0 +#define DEFAULT_START_TIME_SELECTION GST_AGGREGATOR_START_TIME_SELECTION_ZERO +#define DEFAULT_START_TIME (-1) + +enum +{ + PROP_0, + PROP_LATENCY, + PROP_START_TIME_SELECTION, + PROP_START_TIME, + PROP_LAST +}; + +static GstFlowReturn gst_aggregator_pad_chain_internal (GstAggregator * self, + GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head); + +static gboolean +gst_aggregator_pad_queue_is_empty (GstAggregatorPad * pad) +{ + return (g_queue_peek_tail (&pad->priv->data) == NULL && + pad->priv->clipped_buffer == NULL); +} + +static gboolean +gst_aggregator_check_pads_ready (GstAggregator * self) +{ + GstAggregatorPad *pad = NULL; + GList *l, *sinkpads; + gboolean have_buffer = TRUE; + gboolean have_event_or_query = FALSE; + + GST_LOG_OBJECT (self, "checking pads"); + + GST_OBJECT_LOCK (self); + + sinkpads = GST_ELEMENT_CAST (self)->sinkpads; + if (sinkpads == NULL) + goto no_sinkpads; + + for (l = sinkpads; l != NULL; l = l->next) { + pad = l->data; + + PAD_LOCK (pad); + + if (pad->priv->num_buffers == 0) { + if (!gst_aggregator_pad_queue_is_empty (pad)) + have_event_or_query = TRUE; + if (!pad->priv->eos) { + have_buffer = FALSE; + + /* If not live we need data on all pads, so leave the loop */ + if (!self->priv->peer_latency_live) { + PAD_UNLOCK (pad); + goto pad_not_ready; + } + } + } else if (self->priv->peer_latency_live) { + /* In live mode, having a single pad with buffers is enough to + * generate a start time from it. In non-live mode all pads need + * to have a buffer + */ + self->priv->first_buffer = FALSE; + } + + PAD_UNLOCK (pad); + } + + if (!have_buffer && !have_event_or_query) + goto pad_not_ready; + + if (have_buffer) + self->priv->first_buffer = FALSE; + + GST_OBJECT_UNLOCK (self); + GST_LOG_OBJECT (self, "pads are ready"); + return TRUE; + +no_sinkpads: + { + GST_LOG_OBJECT (self, "pads not ready: no sink pads"); + GST_OBJECT_UNLOCK (self); + return FALSE; + } +pad_not_ready: + { + if (have_event_or_query) + GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet," + " but waking up for serialized event"); + else + GST_LOG_OBJECT (pad, "pad not ready to be aggregated yet"); + GST_OBJECT_UNLOCK (self); + return have_event_or_query; + } +} + +static void +gst_aggregator_reset_flow_values (GstAggregator * self) +{ + GST_OBJECT_LOCK (self); + self->priv->send_stream_start = TRUE; + self->priv->send_segment = TRUE; + gst_segment_init (&GST_AGGREGATOR_PAD (self->srcpad)->segment, + GST_FORMAT_TIME); + self->priv->first_buffer = TRUE; + GST_OBJECT_UNLOCK (self); +} + +static inline void +gst_aggregator_push_mandatory_events (GstAggregator * self) +{ + GstAggregatorPrivate *priv = self->priv; + GstEvent *segment = NULL; + GstEvent *tags = NULL; + + if (self->priv->send_stream_start) { + gchar s_id[32]; + + GST_INFO_OBJECT (self, "pushing stream start"); + /* stream-start (FIXME: create id based on input ids) */ + g_snprintf (s_id, sizeof (s_id), "agg-%08x", g_random_int ()); + if (!gst_pad_push_event (GST_PAD (self->srcpad), + gst_event_new_stream_start (s_id))) { + GST_WARNING_OBJECT (self->srcpad, "Sending stream start event failed"); + } + self->priv->send_stream_start = FALSE; + } + + if (self->priv->srccaps) { + + GST_INFO_OBJECT (self, "pushing caps: %" GST_PTR_FORMAT, + self->priv->srccaps); + if (!gst_pad_push_event (GST_PAD (self->srcpad), + gst_event_new_caps (self->priv->srccaps))) { + GST_WARNING_OBJECT (self->srcpad, "Sending caps event failed"); + } + gst_caps_unref (self->priv->srccaps); + self->priv->srccaps = NULL; + } + + GST_OBJECT_LOCK (self); + if (self->priv->send_segment && !self->priv->flush_seeking) { + segment = + gst_event_new_segment (&GST_AGGREGATOR_PAD (self->srcpad)->segment); + + if (!self->priv->seqnum) + /* This code-path is in preparation to be able to run without a source + * connected. Then we won't have a seq-num from a segment event. */ + self->priv->seqnum = gst_event_get_seqnum (segment); + else + gst_event_set_seqnum (segment, self->priv->seqnum); + self->priv->send_segment = FALSE; + + GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segment); + } + + if (priv->tags && priv->tags_changed && !self->priv->flush_seeking) { + tags = gst_event_new_tag (gst_tag_list_ref (priv->tags)); + priv->tags_changed = FALSE; + } + GST_OBJECT_UNLOCK (self); + + if (segment) + gst_pad_push_event (self->srcpad, segment); + if (tags) + gst_pad_push_event (self->srcpad, tags); + +} + +/** + * gst_aggregator_set_src_caps: + * @self: The #GstAggregator + * @caps: The #GstCaps to set on the src pad. + * + * Sets the caps to be used on the src pad. + */ +void +gst_aggregator_set_src_caps (GstAggregator * self, GstCaps * caps) +{ + GST_PAD_STREAM_LOCK (self->srcpad); + gst_caps_replace (&self->priv->srccaps, caps); + gst_aggregator_push_mandatory_events (self); + GST_PAD_STREAM_UNLOCK (self->srcpad); +} + +static GstFlowReturn +gst_aggregator_default_finish_buffer (GstAggregator * self, GstBuffer * buffer) +{ + gst_aggregator_push_mandatory_events (self); + + GST_OBJECT_LOCK (self); + if (!self->priv->flush_seeking && gst_pad_is_active (self->srcpad)) { + GST_TRACE_OBJECT (self, "pushing buffer %" GST_PTR_FORMAT, buffer); + GST_OBJECT_UNLOCK (self); + return gst_pad_push (self->srcpad, buffer); + } else { + GST_INFO_OBJECT (self, "Not pushing (active: %i, flushing: %i)", + self->priv->flush_seeking, gst_pad_is_active (self->srcpad)); + GST_OBJECT_UNLOCK (self); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } +} + +/** + * gst_aggregator_finish_buffer: + * @aggregator: The #GstAggregator + * @buffer: (transfer full): the #GstBuffer to push. + * + * This method will push the provided output buffer downstream. If needed, + * mandatory events such as stream-start, caps, and segment events will be + * sent before pushing the buffer. + */ +GstFlowReturn +gst_aggregator_finish_buffer (GstAggregator * aggregator, GstBuffer * buffer) +{ + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (aggregator); + + g_assert (klass->finish_buffer != NULL); + + return klass->finish_buffer (aggregator, buffer); +} + +static void +gst_aggregator_push_eos (GstAggregator * self) +{ + GstEvent *event; + gst_aggregator_push_mandatory_events (self); + + event = gst_event_new_eos (); + + GST_OBJECT_LOCK (self); + self->priv->send_eos = FALSE; + gst_event_set_seqnum (event, self->priv->seqnum); + GST_OBJECT_UNLOCK (self); + + gst_pad_push_event (self->srcpad, event); +} + +static GstClockTime +gst_aggregator_get_next_time (GstAggregator * self) +{ + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); + + if (klass->get_next_time) + return klass->get_next_time (self); + + return GST_CLOCK_TIME_NONE; +} + +static gboolean +gst_aggregator_wait_and_check (GstAggregator * self, gboolean * timeout) +{ + GstClockTime latency; + GstClockTime start; + gboolean res; + + *timeout = FALSE; + + SRC_LOCK (self); + + latency = gst_aggregator_get_latency_unlocked (self); + + if (gst_aggregator_check_pads_ready (self)) { + GST_DEBUG_OBJECT (self, "all pads have data"); + SRC_UNLOCK (self); + + return TRUE; + } + + /* Before waiting, check if we're actually still running */ + if (!self->priv->running || !self->priv->send_eos) { + SRC_UNLOCK (self); + + return FALSE; + } + + start = gst_aggregator_get_next_time (self); + + /* If we're not live, or if we use the running time + * of the first buffer as start time, we wait until + * all pads have buffers. + * Otherwise (i.e. if we are live!), we wait on the clock + * and if a pad does not have a buffer in time we ignore + * that pad. + */ + GST_OBJECT_LOCK (self); + if (!GST_CLOCK_TIME_IS_VALID (latency) || + !GST_IS_CLOCK (GST_ELEMENT_CLOCK (self)) || + !GST_CLOCK_TIME_IS_VALID (start) || + (self->priv->first_buffer + && self->priv->start_time_selection == + GST_AGGREGATOR_START_TIME_SELECTION_FIRST)) { + /* We wake up here when something happened, and below + * then check if we're ready now. If we return FALSE, + * we will be directly called again. + */ + GST_OBJECT_UNLOCK (self); + SRC_WAIT (self); + } else { + GstClockTime base_time, time; + GstClock *clock; + GstClockReturn status; + GstClockTimeDiff jitter; + + GST_DEBUG_OBJECT (self, "got subclass start time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (start)); + + base_time = GST_ELEMENT_CAST (self)->base_time; + clock = gst_object_ref (GST_ELEMENT_CLOCK (self)); + GST_OBJECT_UNLOCK (self); + + time = base_time + start; + time += latency; + + GST_DEBUG_OBJECT (self, "possibly waiting for clock to reach %" + GST_TIME_FORMAT " (base %" GST_TIME_FORMAT " start %" GST_TIME_FORMAT + " latency %" GST_TIME_FORMAT " current %" GST_TIME_FORMAT ")", + GST_TIME_ARGS (time), + GST_TIME_ARGS (base_time), + GST_TIME_ARGS (start), GST_TIME_ARGS (latency), + GST_TIME_ARGS (gst_clock_get_time (clock))); + + self->priv->aggregate_id = gst_clock_new_single_shot_id (clock, time); + gst_object_unref (clock); + SRC_UNLOCK (self); + + jitter = 0; + status = gst_clock_id_wait (self->priv->aggregate_id, &jitter); + + SRC_LOCK (self); + if (self->priv->aggregate_id) { + gst_clock_id_unref (self->priv->aggregate_id); + self->priv->aggregate_id = NULL; + } + + GST_DEBUG_OBJECT (self, + "clock returned %d (jitter: %" GST_STIME_FORMAT ")", + status, GST_STIME_ARGS (jitter)); + + /* we timed out */ + if (status == GST_CLOCK_OK || status == GST_CLOCK_EARLY) { + SRC_UNLOCK (self); + *timeout = TRUE; + return TRUE; + } + } + + res = gst_aggregator_check_pads_ready (self); + SRC_UNLOCK (self); + + return res; +} + +static gboolean +gst_aggregator_do_events_and_queries (GstElement * self, GstPad * epad, + gpointer user_data) +{ + GstAggregatorPad *pad = GST_AGGREGATOR_PAD_CAST (epad); + GstAggregator *aggregator = GST_AGGREGATOR_CAST (self); + GstEvent *event = NULL; + GstQuery *query = NULL; + GstAggregatorClass *klass = NULL; + gboolean *processed_event = user_data; + + do { + event = NULL; + query = NULL; + + PAD_LOCK (pad); + if (pad->priv->clipped_buffer == NULL && + !GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) { + if (GST_IS_EVENT (g_queue_peek_tail (&pad->priv->data))) + event = gst_event_ref (g_queue_peek_tail (&pad->priv->data)); + if (GST_IS_QUERY (g_queue_peek_tail (&pad->priv->data))) + query = g_queue_peek_tail (&pad->priv->data); + } + PAD_UNLOCK (pad); + if (event || query) { + gboolean ret; + + if (processed_event) + *processed_event = TRUE; + if (klass == NULL) + klass = GST_AGGREGATOR_GET_CLASS (self); + + if (event) { + GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, event); + gst_event_ref (event); + ret = klass->sink_event (aggregator, pad, event); + + PAD_LOCK (pad); + if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) + pad->priv->negotiated = ret; + if (g_queue_peek_tail (&pad->priv->data) == event) + gst_event_unref (g_queue_pop_tail (&pad->priv->data)); + gst_event_unref (event); + } else if (query) { + GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, query); + ret = klass->sink_query (aggregator, pad, query); + + PAD_LOCK (pad); + if (g_queue_peek_tail (&pad->priv->data) == query) { + GstStructure *s; + + s = gst_query_writable_structure (query); + gst_structure_set (s, "gst-aggregator-retval", G_TYPE_BOOLEAN, ret, + NULL); + g_queue_pop_tail (&pad->priv->data); + } + } + + PAD_BROADCAST_EVENT (pad); + PAD_UNLOCK (pad); + } + } while (event || query); + + return TRUE; +} + +static gboolean +gst_aggregator_pad_skip_buffers (GstElement * self, GstPad * epad, + gpointer user_data) +{ + GList *item; + GstAggregatorPad *aggpad = (GstAggregatorPad *) epad; + GstAggregator *agg = (GstAggregator *) self; + GstAggregatorPadClass *klass = GST_AGGREGATOR_PAD_GET_CLASS (aggpad); + + if (!klass->skip_buffer) + return FALSE; + + PAD_LOCK (aggpad); + + item = g_queue_peek_head_link (&aggpad->priv->data); + while (item) { + GList *next = item->next; + + if (GST_IS_BUFFER (item->data) + && klass->skip_buffer (aggpad, agg, item->data)) { + GST_LOG_OBJECT (aggpad, "Skipping %" GST_PTR_FORMAT, item->data); + gst_aggregator_pad_buffer_consumed (aggpad); + gst_buffer_unref (item->data); + g_queue_delete_link (&aggpad->priv->data, item); + } else { + break; + } + + item = next; + } + + PAD_UNLOCK (aggpad); + + return TRUE; +} + +static void +gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad, + GstFlowReturn flow_return, gboolean full) +{ + GList *item; + + PAD_LOCK (aggpad); + if (flow_return == GST_FLOW_NOT_LINKED) + aggpad->priv->flow_return = MIN (flow_return, aggpad->priv->flow_return); + else + aggpad->priv->flow_return = flow_return; + + item = g_queue_peek_head_link (&aggpad->priv->data); + while (item) { + GList *next = item->next; + + /* In partial flush, we do like the pad, we get rid of non-sticky events + * and EOS/SEGMENT. + */ + if (full || GST_IS_BUFFER (item->data) || + GST_EVENT_TYPE (item->data) == GST_EVENT_EOS || + GST_EVENT_TYPE (item->data) == GST_EVENT_SEGMENT || + !GST_EVENT_IS_STICKY (item->data)) { + if (!GST_IS_QUERY (item->data)) + gst_mini_object_unref (item->data); + g_queue_delete_link (&aggpad->priv->data, item); + } + item = next; + } + aggpad->priv->num_buffers = 0; + gst_buffer_replace (&aggpad->priv->clipped_buffer, NULL); + + PAD_BROADCAST_EVENT (aggpad); + PAD_UNLOCK (aggpad); +} + +static GstFlowReturn +gst_aggregator_default_update_src_caps (GstAggregator * agg, GstCaps * caps, + GstCaps ** ret) +{ + *ret = gst_caps_ref (caps); + + return GST_FLOW_OK; +} + +static GstCaps * +gst_aggregator_default_fixate_src_caps (GstAggregator * agg, GstCaps * caps) +{ + caps = gst_caps_fixate (caps); + + return caps; +} + +static gboolean +gst_aggregator_default_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) +{ + return TRUE; +} + + +/* takes ownership of the pool, allocator and query */ +static gboolean +gst_aggregator_set_allocation (GstAggregator * self, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params, GstQuery * query) +{ + GstAllocator *oldalloc; + GstBufferPool *oldpool; + GstQuery *oldquery; + + GST_DEBUG ("storing allocation query"); + + GST_OBJECT_LOCK (self); + oldpool = self->priv->pool; + self->priv->pool = pool; + + oldalloc = self->priv->allocator; + self->priv->allocator = allocator; + + oldquery = self->priv->allocation_query; + self->priv->allocation_query = query; + + if (params) + self->priv->allocation_params = *params; + else + gst_allocation_params_init (&self->priv->allocation_params); + GST_OBJECT_UNLOCK (self); + + if (oldpool) { + GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool); + gst_buffer_pool_set_active (oldpool, FALSE); + gst_object_unref (oldpool); + } + if (oldalloc) { + gst_object_unref (oldalloc); + } + if (oldquery) { + gst_query_unref (oldquery); + } + return TRUE; +} + + +static gboolean +gst_aggregator_decide_allocation (GstAggregator * self, GstQuery * query) +{ + GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (self); + + if (aggclass->decide_allocation) + if (!aggclass->decide_allocation (self, query)) + return FALSE; + + return TRUE; +} + +static gboolean +gst_aggregator_do_allocation (GstAggregator * self, GstCaps * caps) +{ + GstQuery *query; + gboolean result = TRUE; + GstBufferPool *pool = NULL; + GstAllocator *allocator; + GstAllocationParams params; + + /* find a pool for the negotiated caps now */ + GST_DEBUG_OBJECT (self, "doing allocation query"); + query = gst_query_new_allocation (caps, TRUE); + if (!gst_pad_peer_query (self->srcpad, query)) { + /* not a problem, just debug a little */ + GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed"); + } + + GST_DEBUG_OBJECT (self, "calling decide_allocation"); + result = gst_aggregator_decide_allocation (self, query); + + GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, + query); + + if (!result) + goto no_decide_allocation; + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + } + + if (gst_query_get_n_allocation_pools (query) > 0) + gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); + + /* now store */ + result = + gst_aggregator_set_allocation (self, pool, allocator, ¶ms, query); + + return result; + + /* Errors */ +no_decide_allocation: + { + GST_WARNING_OBJECT (self, "Failed to decide allocation"); + gst_query_unref (query); + + return result; + } + +} + +/* WITH SRC_LOCK held */ +static GstFlowReturn +gst_aggregator_update_src_caps (GstAggregator * self) +{ + GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self); + GstCaps *downstream_caps, *template_caps, *caps = NULL; + GstFlowReturn ret = GST_FLOW_OK; + + template_caps = gst_pad_get_pad_template_caps (self->srcpad); + downstream_caps = gst_pad_peer_query_caps (self->srcpad, template_caps); + + if (gst_caps_is_empty (downstream_caps)) { + GST_INFO_OBJECT (self, "Downstream caps (%" + GST_PTR_FORMAT ") not compatible with pad template caps (%" + GST_PTR_FORMAT ")", downstream_caps, template_caps); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + + g_assert (agg_klass->update_src_caps); + GST_DEBUG_OBJECT (self, "updating caps from %" GST_PTR_FORMAT, + downstream_caps); + ret = agg_klass->update_src_caps (self, downstream_caps, &caps); + if (ret < GST_FLOW_OK) { + GST_WARNING_OBJECT (self, "Subclass failed to update provided caps"); + goto done; + } + if ((caps == NULL || gst_caps_is_empty (caps)) && ret >= GST_FLOW_OK) { + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps); + +#ifdef GST_ENABLE_EXTRA_CHECKS + if (!gst_caps_is_subset (caps, template_caps)) { + GstCaps *intersection; + + GST_ERROR_OBJECT (self, + "update_src_caps returned caps %" GST_PTR_FORMAT + " which are not a real subset of the template caps %" + GST_PTR_FORMAT, caps, template_caps); + g_warning ("%s: update_src_caps returned caps which are not a real " + "subset of the filter caps", GST_ELEMENT_NAME (self)); + + intersection = + gst_caps_intersect_full (template_caps, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + caps = intersection; + } +#endif + + if (gst_caps_is_any (caps)) { + goto done; + } + + if (!gst_caps_is_fixed (caps)) { + g_assert (agg_klass->fixate_src_caps); + + GST_DEBUG_OBJECT (self, "fixate caps from %" GST_PTR_FORMAT, caps); + if (!(caps = agg_klass->fixate_src_caps (self, caps))) { + GST_WARNING_OBJECT (self, "Subclass failed to fixate provided caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps); + } + + if (agg_klass->negotiated_src_caps) { + if (!agg_klass->negotiated_src_caps (self, caps)) { + GST_WARNING_OBJECT (self, "Subclass failed to accept negotiated caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + } + + gst_aggregator_set_src_caps (self, caps); + + if (!gst_aggregator_do_allocation (self, caps)) { + GST_WARNING_OBJECT (self, "Allocation negotiation failed"); + ret = GST_FLOW_NOT_NEGOTIATED; + } + +done: + gst_caps_unref (downstream_caps); + gst_caps_unref (template_caps); + + if (caps) + gst_caps_unref (caps); + + return ret; +} + +static void +gst_aggregator_aggregate_func (GstAggregator * self) +{ + GstAggregatorPrivate *priv = self->priv; + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); + gboolean timeout = FALSE; + + if (self->priv->running == FALSE) { + GST_DEBUG_OBJECT (self, "Not running anymore"); + return; + } + + GST_LOG_OBJECT (self, "Checking aggregate"); + while (priv->send_eos && priv->running) { + GstFlowReturn flow_return = GST_FLOW_OK; + gboolean processed_event = FALSE; + + gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self), + gst_aggregator_do_events_and_queries, NULL); + + if (self->priv->peer_latency_live) + gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self), + gst_aggregator_pad_skip_buffers, NULL); + + /* Ensure we have buffers ready (either in clipped_buffer or at the head of + * the queue */ + if (!gst_aggregator_wait_and_check (self, &timeout)) + continue; + + gst_element_foreach_sink_pad (GST_ELEMENT_CAST (self), + gst_aggregator_do_events_and_queries, &processed_event); + + if (processed_event) + continue; + + if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self))) { + flow_return = gst_aggregator_update_src_caps (self); + if (flow_return != GST_FLOW_OK) + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); + } + + if (timeout || flow_return >= GST_FLOW_OK) { + GST_TRACE_OBJECT (self, "Actually aggregating!"); + flow_return = klass->aggregate (self, timeout); + } + + if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA) + continue; + + GST_OBJECT_LOCK (self); + if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking) { + /* We don't want to set the pads to flushing, but we want to + * stop the thread, so just break here */ + GST_OBJECT_UNLOCK (self); + break; + } + GST_OBJECT_UNLOCK (self); + + if (flow_return == GST_FLOW_EOS || flow_return == GST_FLOW_ERROR) { + gst_aggregator_push_eos (self); + } + + GST_LOG_OBJECT (self, "flow return is %s", gst_flow_get_name (flow_return)); + + if (flow_return != GST_FLOW_OK) { + GList *item; + + GST_OBJECT_LOCK (self); + for (item = GST_ELEMENT (self)->sinkpads; item; item = item->next) { + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data); + + gst_aggregator_pad_set_flushing (aggpad, flow_return, TRUE); + } + GST_OBJECT_UNLOCK (self); + break; + } + } + + /* Pause the task here, the only ways to get here are: + * 1) We're stopping, in which case the task is stopped anyway + * 2) We got a flow error above, in which case it might take + * some time to forward the flow return upstream and we + * would otherwise call the task function over and over + * again without doing anything + */ + gst_pad_pause_task (self->srcpad); +} + +static gboolean +gst_aggregator_start (GstAggregator * self) +{ + GstAggregatorClass *klass; + gboolean result; + + self->priv->send_stream_start = TRUE; + self->priv->send_segment = TRUE; + self->priv->send_eos = TRUE; + self->priv->srccaps = NULL; + + gst_aggregator_set_allocation (self, NULL, NULL, NULL, NULL); + + klass = GST_AGGREGATOR_GET_CLASS (self); + + if (klass->start) + result = klass->start (self); + else + result = TRUE; + + return result; +} + +static gboolean +_check_pending_flush_stop (GstAggregatorPad * pad) +{ + gboolean res; + + PAD_LOCK (pad); + res = (!pad->priv->pending_flush_stop && !pad->priv->pending_flush_start); + PAD_UNLOCK (pad); + + return res; +} + +static gboolean +gst_aggregator_stop_srcpad_task (GstAggregator * self, GstEvent * flush_start) +{ + gboolean res = TRUE; + + GST_INFO_OBJECT (self, "%s srcpad task", + flush_start ? "Pausing" : "Stopping"); + + SRC_LOCK (self); + self->priv->running = FALSE; + SRC_BROADCAST (self); + SRC_UNLOCK (self); + + if (flush_start) { + res = gst_pad_push_event (self->srcpad, flush_start); + } + + gst_pad_stop_task (self->srcpad); + + return res; +} + +static void +gst_aggregator_start_srcpad_task (GstAggregator * self) +{ + GST_INFO_OBJECT (self, "Starting srcpad task"); + + self->priv->running = TRUE; + gst_pad_start_task (GST_PAD (self->srcpad), + (GstTaskFunction) gst_aggregator_aggregate_func, self, NULL); +} + +static GstFlowReturn +gst_aggregator_flush (GstAggregator * self) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstAggregatorPrivate *priv = self->priv; + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); + + GST_DEBUG_OBJECT (self, "Flushing everything"); + GST_OBJECT_LOCK (self); + priv->send_segment = TRUE; + priv->flush_seeking = FALSE; + priv->tags_changed = FALSE; + GST_OBJECT_UNLOCK (self); + if (klass->flush) + ret = klass->flush (self); + + return ret; +} + + +/* Called with GstAggregator's object lock held */ + +static gboolean +gst_aggregator_all_flush_stop_received_locked (GstAggregator * self) +{ + GList *tmp; + GstAggregatorPad *tmppad; + + for (tmp = GST_ELEMENT (self)->sinkpads; tmp; tmp = tmp->next) { + tmppad = (GstAggregatorPad *) tmp->data; + + if (_check_pending_flush_stop (tmppad) == FALSE) { + GST_DEBUG_OBJECT (tmppad, "Is not last %i -- %i", + tmppad->priv->pending_flush_start, tmppad->priv->pending_flush_stop); + return FALSE; + } + } + + return TRUE; +} + +static void +gst_aggregator_flush_start (GstAggregator * self, GstAggregatorPad * aggpad, + GstEvent * event) +{ + GstAggregatorPrivate *priv = self->priv; + GstAggregatorPadPrivate *padpriv = aggpad->priv; + + gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, FALSE); + + PAD_FLUSH_LOCK (aggpad); + PAD_LOCK (aggpad); + if (padpriv->pending_flush_start) { + GST_DEBUG_OBJECT (aggpad, "Expecting FLUSH_STOP now"); + + padpriv->pending_flush_start = FALSE; + padpriv->pending_flush_stop = TRUE; + } + PAD_UNLOCK (aggpad); + + GST_OBJECT_LOCK (self); + if (priv->flush_seeking) { + /* If flush_seeking we forward the first FLUSH_START */ + if (priv->pending_flush_start) { + priv->pending_flush_start = FALSE; + GST_OBJECT_UNLOCK (self); + + GST_INFO_OBJECT (self, "Flushing, pausing srcpad task"); + gst_aggregator_stop_srcpad_task (self, event); + + GST_INFO_OBJECT (self, "Getting STREAM_LOCK while seeking"); + GST_PAD_STREAM_LOCK (self->srcpad); + GST_LOG_OBJECT (self, "GOT STREAM_LOCK"); + event = NULL; + } else { + GST_OBJECT_UNLOCK (self); + gst_event_unref (event); + } + } else { + GST_OBJECT_UNLOCK (self); + gst_event_unref (event); + } + PAD_FLUSH_UNLOCK (aggpad); +} + +/* Must be called with the the PAD_LOCK held */ +static void +update_time_level (GstAggregatorPad * aggpad, gboolean head) +{ + GstAggregatorPadPrivate *priv = aggpad->priv; + + if (head) { + if (GST_CLOCK_TIME_IS_VALID (priv->head_position) && + priv->head_segment.format == GST_FORMAT_TIME) + priv->head_time = gst_segment_to_running_time (&priv->head_segment, + GST_FORMAT_TIME, priv->head_position); + else + priv->head_time = GST_CLOCK_TIME_NONE; + + if (!GST_CLOCK_TIME_IS_VALID (priv->tail_time)) + priv->tail_time = priv->head_time; + } else { + if (GST_CLOCK_TIME_IS_VALID (priv->tail_position) && + aggpad->segment.format == GST_FORMAT_TIME) + priv->tail_time = gst_segment_to_running_time (&aggpad->segment, + GST_FORMAT_TIME, priv->tail_position); + else + priv->tail_time = priv->head_time; + } + + if (priv->head_time == GST_CLOCK_TIME_NONE || + priv->tail_time == GST_CLOCK_TIME_NONE) { + priv->time_level = 0; + return; + } + + if (priv->tail_time > priv->head_time) + priv->time_level = 0; + else + priv->time_level = priv->head_time - priv->tail_time; +} + + +/* GstAggregator vmethods default implementations */ +static gboolean +gst_aggregator_default_sink_event (GstAggregator * self, + GstAggregatorPad * aggpad, GstEvent * event) +{ + gboolean res = TRUE; + GstPad *pad = GST_PAD (aggpad); + GstAggregatorPrivate *priv = self->priv; + + GST_DEBUG_OBJECT (aggpad, "Got event: %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + { + gst_aggregator_flush_start (self, aggpad, event); + /* We forward only in one case: right after flush_seeking */ + event = NULL; + goto eat; + } + case GST_EVENT_FLUSH_STOP: + { + gst_aggregator_pad_flush (aggpad, self); + GST_OBJECT_LOCK (self); + if (priv->flush_seeking) { + g_atomic_int_set (&aggpad->priv->pending_flush_stop, FALSE); + if (gst_aggregator_all_flush_stop_received_locked (self)) { + GST_OBJECT_UNLOCK (self); + /* That means we received FLUSH_STOP/FLUSH_STOP on + * all sinkpads -- Seeking is Done... sending FLUSH_STOP */ + gst_aggregator_flush (self); + gst_pad_push_event (self->srcpad, event); + event = NULL; + SRC_LOCK (self); + priv->send_eos = TRUE; + SRC_BROADCAST (self); + SRC_UNLOCK (self); + + GST_INFO_OBJECT (self, "Releasing source pad STREAM_LOCK"); + GST_PAD_STREAM_UNLOCK (self->srcpad); + gst_aggregator_start_srcpad_task (self); + } else { + GST_OBJECT_UNLOCK (self); + } + } else { + GST_OBJECT_UNLOCK (self); + } + + /* We never forward the event */ + goto eat; + } + case GST_EVENT_EOS: + { + SRC_LOCK (self); + PAD_LOCK (aggpad); + g_assert (aggpad->priv->num_buffers == 0); + aggpad->priv->eos = TRUE; + PAD_UNLOCK (aggpad); + SRC_BROADCAST (self); + SRC_UNLOCK (self); + goto eat; + } + case GST_EVENT_SEGMENT: + { + PAD_LOCK (aggpad); + GST_OBJECT_LOCK (aggpad); + gst_event_copy_segment (event, &aggpad->segment); + /* We've got a new segment, tail_position is now meaningless + * and may interfere with the time_level calculation + */ + aggpad->priv->tail_position = GST_CLOCK_TIME_NONE; + update_time_level (aggpad, FALSE); + GST_OBJECT_UNLOCK (aggpad); + PAD_UNLOCK (aggpad); + + GST_OBJECT_LOCK (self); + self->priv->seqnum = gst_event_get_seqnum (event); + GST_OBJECT_UNLOCK (self); + goto eat; + } + case GST_EVENT_STREAM_START: + { + goto eat; + } + case GST_EVENT_GAP: + { + GstClockTime pts, endpts; + GstClockTime duration; + GstBuffer *gapbuf; + + gst_event_parse_gap (event, &pts, &duration); + gapbuf = gst_buffer_new (); + + if (GST_CLOCK_TIME_IS_VALID (duration)) + endpts = pts + duration; + else + endpts = GST_CLOCK_TIME_NONE; + + GST_OBJECT_LOCK (aggpad); + res = gst_segment_clip (&aggpad->segment, GST_FORMAT_TIME, pts, endpts, + &pts, &endpts); + GST_OBJECT_UNLOCK (aggpad); + + if (!res) { + GST_WARNING_OBJECT (self, "GAP event outside segment, dropping"); + goto eat; + } + + if (GST_CLOCK_TIME_IS_VALID (endpts) && GST_CLOCK_TIME_IS_VALID (pts)) + duration = endpts - pts; + else + duration = GST_CLOCK_TIME_NONE; + + GST_BUFFER_PTS (gapbuf) = pts; + GST_BUFFER_DURATION (gapbuf) = duration; + GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_GAP); + GST_BUFFER_FLAG_SET (gapbuf, GST_BUFFER_FLAG_DROPPABLE); + + /* Remove GAP event so we can replace it with the buffer */ + if (g_queue_peek_tail (&aggpad->priv->data) == event) + gst_event_unref (g_queue_pop_tail (&aggpad->priv->data)); + + if (gst_aggregator_pad_chain_internal (self, aggpad, gapbuf, FALSE) != + GST_FLOW_OK) { + GST_WARNING_OBJECT (self, "Failed to chain gap buffer"); + res = FALSE; + } + + goto eat; + } + case GST_EVENT_TAG: + goto eat; + default: + { + break; + } + } + + GST_DEBUG_OBJECT (pad, "Forwarding event: %" GST_PTR_FORMAT, event); + return gst_pad_event_default (pad, GST_OBJECT (self), event); + +eat: + GST_DEBUG_OBJECT (pad, "Eating event: %" GST_PTR_FORMAT, event); + if (event) + gst_event_unref (event); + + return res; +} + +static gboolean +gst_aggregator_stop_pad (GstElement * self, GstPad * epad, gpointer user_data) +{ + GstAggregatorPad *pad = GST_AGGREGATOR_PAD_CAST (epad); + GstAggregator *agg = GST_AGGREGATOR_CAST (self); + + gst_aggregator_pad_flush (pad, agg); + + PAD_LOCK (pad); + pad->priv->flow_return = GST_FLOW_FLUSHING; + pad->priv->negotiated = FALSE; + PAD_BROADCAST_EVENT (pad); + PAD_UNLOCK (pad); + + return TRUE; +} + +static gboolean +gst_aggregator_stop (GstAggregator * agg) +{ + GstAggregatorClass *klass; + gboolean result; + + gst_aggregator_reset_flow_values (agg); + + /* Application needs to make sure no pads are added while it shuts us down */ + gst_element_foreach_sink_pad (GST_ELEMENT_CAST (agg), + gst_aggregator_stop_pad, NULL); + + klass = GST_AGGREGATOR_GET_CLASS (agg); + + if (klass->stop) + result = klass->stop (agg); + else + result = TRUE; + + agg->priv->has_peer_latency = FALSE; + agg->priv->peer_latency_live = FALSE; + agg->priv->peer_latency_min = agg->priv->peer_latency_max = 0; + + if (agg->priv->tags) + gst_tag_list_unref (agg->priv->tags); + agg->priv->tags = NULL; + + gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL); + + return result; +} + +/* GstElement vmethods implementations */ +static GstStateChangeReturn +gst_aggregator_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstAggregator *self = GST_AGGREGATOR (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!gst_aggregator_start (self)) + goto error_start; + break; + default: + break; + } + + if ((ret = + GST_ELEMENT_CLASS (aggregator_parent_class)->change_state (element, + transition)) == GST_STATE_CHANGE_FAILURE) + goto failure; + + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (!gst_aggregator_stop (self)) { + /* What to do in this case? Error out? */ + GST_ERROR_OBJECT (self, "Subclass failed to stop."); + } + break; + default: + break; + } + + return ret; + +/* ERRORS */ +failure: + { + GST_ERROR_OBJECT (element, "parent failed state change"); + return ret; + } +error_start: + { + GST_ERROR_OBJECT (element, "Subclass failed to start"); + return GST_STATE_CHANGE_FAILURE; + } +} + +static void +gst_aggregator_release_pad (GstElement * element, GstPad * pad) +{ + GstAggregator *self = GST_AGGREGATOR (element); + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + GST_INFO_OBJECT (pad, "Removing pad"); + + SRC_LOCK (self); + gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, TRUE); + gst_element_remove_pad (element, pad); + + self->priv->has_peer_latency = FALSE; + SRC_BROADCAST (self); + SRC_UNLOCK (self); +} + +static GstAggregatorPad * +gst_aggregator_default_create_new_pad (GstAggregator * self, + GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) +{ + GstAggregatorPad *agg_pad; + GstAggregatorPrivate *priv = self->priv; + gint serial = 0; + gchar *name = NULL; + GType pad_type = + GST_PAD_TEMPLATE_GTYPE (templ) == + G_TYPE_NONE ? GST_TYPE_AGGREGATOR_PAD : GST_PAD_TEMPLATE_GTYPE (templ); + + if (templ->direction != GST_PAD_SINK) + goto not_sink; + + if (templ->presence != GST_PAD_REQUEST) + goto not_request; + + GST_OBJECT_LOCK (self); + if (req_name == NULL || strlen (req_name) < 6 + || !g_str_has_prefix (req_name, "sink_")) { + /* no name given when requesting the pad, use next available int */ + serial = ++priv->max_padserial; + } else { + /* parse serial number from requested padname */ + serial = g_ascii_strtoull (&req_name[5], NULL, 10); + if (serial > priv->max_padserial) + priv->max_padserial = serial; + } + + name = g_strdup_printf ("sink_%u", serial); + agg_pad = g_object_new (pad_type, + "name", name, "direction", GST_PAD_SINK, "template", templ, NULL); + g_free (name); + + GST_OBJECT_UNLOCK (self); + + return agg_pad; + + /* errors */ +not_sink: + { + GST_WARNING_OBJECT (self, "request new pad that is not a SINK pad"); + return NULL; + } +not_request: + { + GST_WARNING_OBJECT (self, "request new pad that is not a REQUEST pad"); + return NULL; + } +} + +static GstPad * +gst_aggregator_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) +{ + GstAggregator *self; + GstAggregatorPad *agg_pad; + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (element); + GstAggregatorPrivate *priv = GST_AGGREGATOR (element)->priv; + + self = GST_AGGREGATOR (element); + + agg_pad = klass->create_new_pad (self, templ, req_name, caps); + if (!agg_pad) { + GST_ERROR_OBJECT (element, "Couldn't create new pad"); + return NULL; + } + + GST_DEBUG_OBJECT (element, "Adding pad %s", GST_PAD_NAME (agg_pad)); + + if (priv->running) + gst_pad_set_active (GST_PAD (agg_pad), TRUE); + + /* add the pad to the element */ + gst_element_add_pad (element, GST_PAD (agg_pad)); + + return GST_PAD (agg_pad); +} + +/* Must be called with SRC_LOCK held */ + +static gboolean +gst_aggregator_query_latency_unlocked (GstAggregator * self, GstQuery * query) +{ + gboolean query_ret, live; + GstClockTime our_latency, min, max; + + query_ret = gst_pad_query_default (self->srcpad, GST_OBJECT (self), query); + + if (!query_ret) { + GST_WARNING_OBJECT (self, "Latency query failed"); + return FALSE; + } + + gst_query_parse_latency (query, &live, &min, &max); + + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (min))) { + GST_ERROR_OBJECT (self, "Invalid minimum latency %" GST_TIME_FORMAT + ". Please file a bug at " PACKAGE_BUGREPORT ".", GST_TIME_ARGS (min)); + return FALSE; + } + + if (min > max && GST_CLOCK_TIME_IS_VALID (max)) { + GST_ELEMENT_WARNING (self, CORE, CLOCK, (NULL), + ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %" + GST_TIME_FORMAT ". Add queues or other buffering elements.", + GST_TIME_ARGS (max), GST_TIME_ARGS (min))); + return FALSE; + } + + our_latency = self->priv->latency; + + self->priv->peer_latency_live = live; + self->priv->peer_latency_min = min; + self->priv->peer_latency_max = max; + self->priv->has_peer_latency = TRUE; + + /* add our own */ + min += our_latency; + min += self->priv->sub_latency_min; + if (GST_CLOCK_TIME_IS_VALID (self->priv->sub_latency_max) + && GST_CLOCK_TIME_IS_VALID (max)) + max += self->priv->sub_latency_max + our_latency; + else + max = GST_CLOCK_TIME_NONE; + + SRC_BROADCAST (self); + + GST_DEBUG_OBJECT (self, "configured latency live:%s min:%" G_GINT64_FORMAT + " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max); + + gst_query_set_latency (query, live, min, max); + + return query_ret; +} + +/* + * MUST be called with the src_lock held. + * + * See gst_aggregator_get_latency() for doc + */ +static GstClockTime +gst_aggregator_get_latency_unlocked (GstAggregator * self) +{ + GstClockTime latency; + + g_return_val_if_fail (GST_IS_AGGREGATOR (self), 0); + + if (!self->priv->has_peer_latency) { + GstQuery *query = gst_query_new_latency (); + gboolean ret; + + ret = gst_aggregator_query_latency_unlocked (self, query); + gst_query_unref (query); + if (!ret) + return GST_CLOCK_TIME_NONE; + } + + if (!self->priv->has_peer_latency || !self->priv->peer_latency_live) + return GST_CLOCK_TIME_NONE; + + /* latency_min is never GST_CLOCK_TIME_NONE by construction */ + latency = self->priv->peer_latency_min; + + /* add our own */ + latency += self->priv->latency; + latency += self->priv->sub_latency_min; + + return latency; +} + +/** + * gst_aggregator_get_latency: + * @self: a #GstAggregator + * + * Retrieves the latency values reported by @self in response to the latency + * query, or %GST_CLOCK_TIME_NONE if there is not live source connected and the element + * will not wait for the clock. + * + * Typically only called by subclasses. + * + * Returns: The latency or %GST_CLOCK_TIME_NONE if the element does not sync + */ +GstClockTime +gst_aggregator_get_latency (GstAggregator * self) +{ + GstClockTime ret; + + SRC_LOCK (self); + ret = gst_aggregator_get_latency_unlocked (self); + SRC_UNLOCK (self); + + return ret; +} + +static gboolean +gst_aggregator_send_event (GstElement * element, GstEvent * event) +{ + GstAggregator *self = GST_AGGREGATOR (element); + + GST_STATE_LOCK (element); + if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK && + GST_STATE (element) < GST_STATE_PAUSED) { + gdouble rate; + GstFormat fmt; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + + gst_event_parse_seek (event, &rate, &fmt, &flags, &start_type, + &start, &stop_type, &stop); + + GST_OBJECT_LOCK (self); + gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt, + flags, start_type, start, stop_type, stop, NULL); + self->priv->seqnum = gst_event_get_seqnum (event); + self->priv->first_buffer = FALSE; + GST_OBJECT_UNLOCK (self); + + GST_DEBUG_OBJECT (element, "Storing segment %" GST_PTR_FORMAT, event); + } + GST_STATE_UNLOCK (element); + + + return GST_ELEMENT_CLASS (aggregator_parent_class)->send_event (element, + event); +} + +static gboolean +gst_aggregator_default_src_query (GstAggregator * self, GstQuery * query) +{ + gboolean res = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING: + { + GstFormat format; + + /* don't pass it along as some (file)sink might claim it does + * whereas with a collectpads in between that will not likely work */ + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + gst_query_set_seeking (query, format, FALSE, 0, -1); + res = TRUE; + + break; + } + case GST_QUERY_LATENCY: + SRC_LOCK (self); + res = gst_aggregator_query_latency_unlocked (self, query); + SRC_UNLOCK (self); + break; + default: + return gst_pad_query_default (self->srcpad, GST_OBJECT (self), query); + } + + return res; +} + +static gboolean +gst_aggregator_event_forward_func (GstPad * pad, gpointer user_data) +{ + EventData *evdata = user_data; + gboolean ret = TRUE; + GstPad *peer = gst_pad_get_peer (pad); + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + if (peer) { + if (evdata->only_to_active_pads && aggpad->priv->first_buffer) { + GST_DEBUG_OBJECT (pad, "not sending event to inactive pad"); + ret = TRUE; + } else { + ret = gst_pad_send_event (peer, gst_event_ref (evdata->event)); + GST_DEBUG_OBJECT (pad, "return of event push is %d", ret); + gst_object_unref (peer); + } + } + + if (ret == FALSE) { + if (GST_EVENT_TYPE (evdata->event) == GST_EVENT_SEEK) { + GstQuery *seeking = gst_query_new_seeking (GST_FORMAT_TIME); + + GST_DEBUG_OBJECT (pad, "Event %" GST_PTR_FORMAT " failed", evdata->event); + + if (gst_pad_query (peer, seeking)) { + gboolean seekable; + + gst_query_parse_seeking (seeking, NULL, &seekable, NULL, NULL); + + if (seekable == FALSE) { + GST_INFO_OBJECT (pad, + "Source not seekable, We failed but it does not matter!"); + + ret = TRUE; + } + } else { + GST_ERROR_OBJECT (pad, "Query seeking FAILED"); + } + + gst_query_unref (seeking); + } + + if (evdata->flush) { + PAD_LOCK (aggpad); + aggpad->priv->pending_flush_start = FALSE; + aggpad->priv->pending_flush_stop = FALSE; + PAD_UNLOCK (aggpad); + } + } else { + evdata->one_actually_seeked = TRUE; + } + + evdata->result &= ret; + + /* Always send to all pads */ + return FALSE; +} + +static void +gst_aggregator_forward_event_to_all_sinkpads (GstAggregator * self, + EventData * evdata) +{ + evdata->result = TRUE; + evdata->one_actually_seeked = FALSE; + + /* We first need to set all pads as flushing in a first pass + * as flush_start flush_stop is sometimes sent synchronously + * while we send the seek event */ + if (evdata->flush) { + GList *l; + + GST_OBJECT_LOCK (self); + for (l = GST_ELEMENT_CAST (self)->sinkpads; l != NULL; l = l->next) { + GstAggregatorPad *pad = l->data; + + PAD_LOCK (pad); + pad->priv->pending_flush_start = TRUE; + pad->priv->pending_flush_stop = FALSE; + PAD_UNLOCK (pad); + } + GST_OBJECT_UNLOCK (self); + } + + gst_pad_forward (self->srcpad, gst_aggregator_event_forward_func, evdata); + + gst_event_unref (evdata->event); +} + +static gboolean +gst_aggregator_do_seek (GstAggregator * self, GstEvent * event) +{ + gdouble rate; + GstFormat fmt; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + gboolean flush; + EventData evdata = { 0, }; + GstAggregatorPrivate *priv = self->priv; + + gst_event_parse_seek (event, &rate, &fmt, &flags, &start_type, + &start, &stop_type, &stop); + + GST_INFO_OBJECT (self, "starting SEEK"); + + flush = flags & GST_SEEK_FLAG_FLUSH; + + GST_OBJECT_LOCK (self); + if (flush) { + priv->pending_flush_start = TRUE; + priv->flush_seeking = TRUE; + } + + gst_segment_do_seek (&GST_AGGREGATOR_PAD (self->srcpad)->segment, rate, fmt, + flags, start_type, start, stop_type, stop, NULL); + + /* Seeking sets a position */ + self->priv->first_buffer = FALSE; + GST_OBJECT_UNLOCK (self); + + /* forward the seek upstream */ + evdata.event = event; + evdata.flush = flush; + evdata.only_to_active_pads = FALSE; + gst_aggregator_forward_event_to_all_sinkpads (self, &evdata); + event = NULL; + + if (!evdata.result || !evdata.one_actually_seeked) { + GST_OBJECT_LOCK (self); + priv->flush_seeking = FALSE; + priv->pending_flush_start = FALSE; + GST_OBJECT_UNLOCK (self); + } + + GST_INFO_OBJECT (self, "seek done, result: %d", evdata.result); + + return evdata.result; +} + +static gboolean +gst_aggregator_default_src_event (GstAggregator * self, GstEvent * event) +{ + EventData evdata = { 0, }; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* _do_seek() unrefs the event. */ + return gst_aggregator_do_seek (self, event); + case GST_EVENT_NAVIGATION: + /* navigation is rather pointless. */ + gst_event_unref (event); + return FALSE; + default: + break; + } + + /* Don't forward QOS events to pads that had no active buffer yet. Otherwise + * they will receive a QOS event that has earliest_time=0 (because we can't + * have negative timestamps), and consider their buffer as too late */ + evdata.event = event; + evdata.flush = FALSE; + evdata.only_to_active_pads = GST_EVENT_TYPE (event) == GST_EVENT_QOS; + gst_aggregator_forward_event_to_all_sinkpads (self, &evdata); + return evdata.result; +} + +static gboolean +gst_aggregator_src_pad_event_func (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); + + return klass->src_event (GST_AGGREGATOR (parent), event); +} + +static gboolean +gst_aggregator_src_pad_query_func (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); + + return klass->src_query (GST_AGGREGATOR (parent), query); +} + +static gboolean +gst_aggregator_src_pad_activate_mode_func (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active) +{ + GstAggregator *self = GST_AGGREGATOR (parent); + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); + + if (klass->src_activate) { + if (klass->src_activate (self, mode, active) == FALSE) { + return FALSE; + } + } + + if (active == TRUE) { + switch (mode) { + case GST_PAD_MODE_PUSH: + { + GST_INFO_OBJECT (pad, "Activating pad!"); + gst_aggregator_start_srcpad_task (self); + return TRUE; + } + default: + { + GST_ERROR_OBJECT (pad, "Only supported mode is PUSH"); + return FALSE; + } + } + } + + /* deactivating */ + GST_INFO_OBJECT (self, "Deactivating srcpad"); + gst_aggregator_stop_srcpad_task (self, FALSE); + + return TRUE; +} + +static gboolean +gst_aggregator_default_sink_query (GstAggregator * self, + GstAggregatorPad * aggpad, GstQuery * query) +{ + GstPad *pad = GST_PAD (aggpad); + + if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) { + GstQuery *decide_query = NULL; + GstAggregatorClass *agg_class; + gboolean ret; + + GST_OBJECT_LOCK (self); + PAD_LOCK (aggpad); + if (G_UNLIKELY (!aggpad->priv->negotiated)) { + GST_DEBUG_OBJECT (self, + "not negotiated yet, can't answer ALLOCATION query"); + PAD_UNLOCK (aggpad); + GST_OBJECT_UNLOCK (self); + + return FALSE; + } + + if ((decide_query = self->priv->allocation_query)) + gst_query_ref (decide_query); + PAD_UNLOCK (aggpad); + GST_OBJECT_UNLOCK (self); + + GST_DEBUG_OBJECT (self, + "calling propose allocation with query %" GST_PTR_FORMAT, decide_query); + + agg_class = GST_AGGREGATOR_GET_CLASS (self); + + /* pass the query to the propose_allocation vmethod if any */ + if (agg_class->propose_allocation) + ret = agg_class->propose_allocation (self, aggpad, decide_query, query); + else + ret = FALSE; + + if (decide_query) + gst_query_unref (decide_query); + + GST_DEBUG_OBJECT (self, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query); + return ret; + } + + return gst_pad_query_default (pad, GST_OBJECT (self), query); +} + +static void +gst_aggregator_finalize (GObject * object) +{ + GstAggregator *self = (GstAggregator *) object; + + g_mutex_clear (&self->priv->src_lock); + g_cond_clear (&self->priv->src_cond); + + G_OBJECT_CLASS (aggregator_parent_class)->finalize (object); +} + +/* + * gst_aggregator_set_latency_property: + * @agg: a #GstAggregator + * @latency: the new latency value (in nanoseconds). + * + * Sets the new latency value to @latency. This value is used to limit the + * amount of time a pad waits for data to appear before considering the pad + * as unresponsive. + */ +static void +gst_aggregator_set_latency_property (GstAggregator * self, GstClockTime latency) +{ + gboolean changed; + + g_return_if_fail (GST_IS_AGGREGATOR (self)); + g_return_if_fail (GST_CLOCK_TIME_IS_VALID (latency)); + + SRC_LOCK (self); + changed = (self->priv->latency != latency); + + if (changed) { + GList *item; + + GST_OBJECT_LOCK (self); + /* First lock all the pads */ + for (item = GST_ELEMENT_CAST (self)->sinkpads; item; item = item->next) { + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data); + PAD_LOCK (aggpad); + } + + self->priv->latency = latency; + + SRC_BROADCAST (self); + + /* Now wake up the pads */ + for (item = GST_ELEMENT_CAST (self)->sinkpads; item; item = item->next) { + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (item->data); + PAD_BROADCAST_EVENT (aggpad); + PAD_UNLOCK (aggpad); + } + GST_OBJECT_UNLOCK (self); + } + + SRC_UNLOCK (self); + + if (changed) + gst_element_post_message (GST_ELEMENT_CAST (self), + gst_message_new_latency (GST_OBJECT_CAST (self))); +} + +/* + * gst_aggregator_get_latency_property: + * @agg: a #GstAggregator + * + * Gets the latency value. See gst_aggregator_set_latency for + * more details. + * + * Returns: The time in nanoseconds to wait for data to arrive on a sink pad + * before a pad is deemed unresponsive. A value of -1 means an + * unlimited time. + */ +static GstClockTime +gst_aggregator_get_latency_property (GstAggregator * agg) +{ + GstClockTime res; + + g_return_val_if_fail (GST_IS_AGGREGATOR (agg), GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (agg); + res = agg->priv->latency; + GST_OBJECT_UNLOCK (agg); + + return res; +} + +static void +gst_aggregator_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAggregator *agg = GST_AGGREGATOR (object); + + switch (prop_id) { + case PROP_LATENCY: + gst_aggregator_set_latency_property (agg, g_value_get_uint64 (value)); + break; + case PROP_START_TIME_SELECTION: + agg->priv->start_time_selection = g_value_get_enum (value); + break; + case PROP_START_TIME: + agg->priv->start_time = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_aggregator_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAggregator *agg = GST_AGGREGATOR (object); + + switch (prop_id) { + case PROP_LATENCY: + g_value_set_uint64 (value, gst_aggregator_get_latency_property (agg)); + break; + case PROP_START_TIME_SELECTION: + g_value_set_enum (value, agg->priv->start_time_selection); + break; + case PROP_START_TIME: + g_value_set_uint64 (value, agg->priv->start_time); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* GObject vmethods implementations */ +static void +gst_aggregator_class_init (GstAggregatorClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + aggregator_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (GstAggregatorPrivate)); + + GST_DEBUG_CATEGORY_INIT (aggregator_debug, "aggregator", + GST_DEBUG_FG_MAGENTA, "GstAggregator"); + + klass->finish_buffer = gst_aggregator_default_finish_buffer; + + klass->sink_event = gst_aggregator_default_sink_event; + klass->sink_query = gst_aggregator_default_sink_query; + + klass->src_event = gst_aggregator_default_src_event; + klass->src_query = gst_aggregator_default_src_query; + + klass->create_new_pad = gst_aggregator_default_create_new_pad; + klass->update_src_caps = gst_aggregator_default_update_src_caps; + klass->fixate_src_caps = gst_aggregator_default_fixate_src_caps; + klass->negotiated_src_caps = gst_aggregator_default_negotiated_src_caps; + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad); + gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aggregator_send_event); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_aggregator_release_pad); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_aggregator_change_state); + + gobject_class->set_property = gst_aggregator_set_property; + gobject_class->get_property = gst_aggregator_get_property; + gobject_class->finalize = gst_aggregator_finalize; + + g_object_class_install_property (gobject_class, PROP_LATENCY, + g_param_spec_uint64 ("latency", "Buffer latency", + "Additional latency in live mode to allow upstream " + "to take longer to produce buffers for the current " + "position (in nanoseconds)", 0, G_MAXUINT64, + DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_START_TIME_SELECTION, + g_param_spec_enum ("start-time-selection", "Start Time Selection", + "Decides which start time is output", + gst_aggregator_start_time_selection_get_type (), + DEFAULT_START_TIME_SELECTION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_START_TIME, + g_param_spec_uint64 ("start-time", "Start Time", + "Start time to use if start-time-selection=set", 0, + G_MAXUINT64, + DEFAULT_START_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_aggregator_init (GstAggregator * self, GstAggregatorClass * klass) +{ + GstPadTemplate *pad_template; + GstAggregatorPrivate *priv; + + g_return_if_fail (klass->aggregate != NULL); + + self->priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_AGGREGATOR, + GstAggregatorPrivate); + + priv = self->priv; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src"); + g_return_if_fail (pad_template != NULL); + + priv->max_padserial = -1; + priv->tags_changed = FALSE; + + self->priv->peer_latency_live = FALSE; + self->priv->peer_latency_min = self->priv->sub_latency_min = 0; + self->priv->peer_latency_max = self->priv->sub_latency_max = 0; + self->priv->has_peer_latency = FALSE; + + self->srcpad = gst_pad_new_from_template (pad_template, "src"); + + gst_aggregator_reset_flow_values (self); + + gst_pad_set_event_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_event_func)); + gst_pad_set_query_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_query_func)); + gst_pad_set_activatemode_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_aggregator_src_pad_activate_mode_func)); + + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + self->priv->latency = DEFAULT_LATENCY; + self->priv->start_time_selection = DEFAULT_START_TIME_SELECTION; + self->priv->start_time = DEFAULT_START_TIME; + + g_mutex_init (&self->priv->src_lock); + g_cond_init (&self->priv->src_cond); +} + +/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init + * method to get to the padtemplates */ +GType +gst_aggregator_get_type (void) +{ + static volatile gsize type = 0; + + if (g_once_init_enter (&type)) { + GType _type; + static const GTypeInfo info = { + sizeof (GstAggregatorClass), + NULL, + NULL, + (GClassInitFunc) gst_aggregator_class_init, + NULL, + NULL, + sizeof (GstAggregator), + 0, + (GInstanceInitFunc) gst_aggregator_init, + }; + + _type = g_type_register_static (GST_TYPE_ELEMENT, + "GstAggregator", &info, G_TYPE_FLAG_ABSTRACT); + g_once_init_leave (&type, _type); + } + return type; +} + +/* Must be called with SRC lock and PAD lock held */ +static gboolean +gst_aggregator_pad_has_space (GstAggregator * self, GstAggregatorPad * aggpad) +{ + /* Empty queue always has space */ + if (aggpad->priv->num_buffers == 0 && aggpad->priv->clipped_buffer == NULL) + return TRUE; + + /* We also want at least two buffers, one is being processed and one is ready + * for the next iteration when we operate in live mode. */ + if (self->priv->peer_latency_live && aggpad->priv->num_buffers < 2) + return TRUE; + + /* zero latency, if there is a buffer, it's full */ + if (self->priv->latency == 0) + return FALSE; + + /* Allow no more buffers than the latency */ + return (aggpad->priv->time_level <= self->priv->latency); +} + +/* Must be called with the PAD_LOCK held */ +static void +apply_buffer (GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head) +{ + GstClockTime timestamp; + + if (GST_BUFFER_DTS_IS_VALID (buffer)) + timestamp = GST_BUFFER_DTS (buffer); + else + timestamp = GST_BUFFER_PTS (buffer); + + if (timestamp == GST_CLOCK_TIME_NONE) { + if (head) + timestamp = aggpad->priv->head_position; + else + timestamp = aggpad->priv->tail_position; + } + + /* add duration */ + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + timestamp += GST_BUFFER_DURATION (buffer); + + if (head) + aggpad->priv->head_position = timestamp; + else + aggpad->priv->tail_position = timestamp; + + update_time_level (aggpad, head); +} + +/* + * Can be called either from the sinkpad's chain function or from the srcpad's + * thread in the case of a buffer synthetized from a GAP event. + * Because of this second case, FLUSH_LOCK can't be used here. + */ + +static GstFlowReturn +gst_aggregator_pad_chain_internal (GstAggregator * self, + GstAggregatorPad * aggpad, GstBuffer * buffer, gboolean head) +{ + GstFlowReturn flow_return; + GstClockTime buf_pts; + + PAD_LOCK (aggpad); + flow_return = aggpad->priv->flow_return; + if (flow_return != GST_FLOW_OK) + goto flushing; + + PAD_UNLOCK (aggpad); + + buf_pts = GST_BUFFER_PTS (buffer); + + for (;;) { + SRC_LOCK (self); + GST_OBJECT_LOCK (self); + PAD_LOCK (aggpad); + + if (aggpad->priv->first_buffer) { + self->priv->has_peer_latency = FALSE; + aggpad->priv->first_buffer = FALSE; + } + + if ((gst_aggregator_pad_has_space (self, aggpad) || !head) + && aggpad->priv->flow_return == GST_FLOW_OK) { + if (head) + g_queue_push_head (&aggpad->priv->data, buffer); + else + g_queue_push_tail (&aggpad->priv->data, buffer); + apply_buffer (aggpad, buffer, head); + aggpad->priv->num_buffers++; + buffer = NULL; + SRC_BROADCAST (self); + break; + } + + flow_return = aggpad->priv->flow_return; + if (flow_return != GST_FLOW_OK) { + GST_OBJECT_UNLOCK (self); + SRC_UNLOCK (self); + goto flushing; + } + GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed"); + GST_OBJECT_UNLOCK (self); + SRC_UNLOCK (self); + PAD_WAIT_EVENT (aggpad); + + PAD_UNLOCK (aggpad); + } + + if (self->priv->first_buffer) { + GstClockTime start_time; + GstAggregatorPad *srcpad = GST_AGGREGATOR_PAD (self->srcpad); + + switch (self->priv->start_time_selection) { + case GST_AGGREGATOR_START_TIME_SELECTION_ZERO: + default: + start_time = 0; + break; + case GST_AGGREGATOR_START_TIME_SELECTION_FIRST: + GST_OBJECT_LOCK (aggpad); + if (aggpad->priv->head_segment.format == GST_FORMAT_TIME) { + start_time = buf_pts; + if (start_time != -1) { + start_time = MAX (start_time, aggpad->priv->head_segment.start); + start_time = + gst_segment_to_running_time (&aggpad->priv->head_segment, + GST_FORMAT_TIME, start_time); + } + } else { + start_time = 0; + GST_WARNING_OBJECT (aggpad, + "Ignoring request of selecting the first start time " + "as the segment is a %s segment instead of a time segment", + gst_format_get_name (aggpad->segment.format)); + } + GST_OBJECT_UNLOCK (aggpad); + break; + case GST_AGGREGATOR_START_TIME_SELECTION_SET: + start_time = self->priv->start_time; + if (start_time == -1) + start_time = 0; + break; + } + + if (start_time != -1) { + if (srcpad->segment.position == -1) + srcpad->segment.position = start_time; + else + srcpad->segment.position = MIN (start_time, srcpad->segment.position); + + GST_DEBUG_OBJECT (self, "Selecting start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + } + } + + PAD_UNLOCK (aggpad); + GST_OBJECT_UNLOCK (self); + SRC_UNLOCK (self); + + GST_DEBUG_OBJECT (aggpad, "Done chaining"); + + return flow_return; + +flushing: + PAD_UNLOCK (aggpad); + + GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping buffer", + gst_flow_get_name (flow_return)); + if (buffer) + gst_buffer_unref (buffer); + + return flow_return; +} + +static GstFlowReturn +gst_aggregator_pad_chain (GstPad * pad, GstObject * object, GstBuffer * buffer) +{ + GstFlowReturn ret; + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + PAD_FLUSH_LOCK (aggpad); + + ret = gst_aggregator_pad_chain_internal (GST_AGGREGATOR_CAST (object), + aggpad, buffer, TRUE); + + PAD_FLUSH_UNLOCK (aggpad); + + return ret; +} + +static gboolean +gst_aggregator_pad_query_func (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstAggregator *self = GST_AGGREGATOR (parent); + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + if (GST_QUERY_IS_SERIALIZED (query)) { + GstStructure *s; + gboolean ret = FALSE; + + SRC_LOCK (self); + PAD_LOCK (aggpad); + + if (aggpad->priv->flow_return != GST_FLOW_OK) { + SRC_UNLOCK (self); + goto flushing; + } + + g_queue_push_head (&aggpad->priv->data, query); + SRC_BROADCAST (self); + SRC_UNLOCK (self); + + while (!gst_aggregator_pad_queue_is_empty (aggpad) + && aggpad->priv->flow_return == GST_FLOW_OK) { + GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed"); + PAD_WAIT_EVENT (aggpad); + } + + s = gst_query_writable_structure (query); + if (gst_structure_get_boolean (s, "gst-aggregator-retval", &ret)) + gst_structure_remove_field (s, "gst-aggregator-retval"); + else + g_queue_remove (&aggpad->priv->data, query); + + if (aggpad->priv->flow_return != GST_FLOW_OK) + goto flushing; + + PAD_UNLOCK (aggpad); + + return ret; + } else { + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); + + return klass->sink_query (self, aggpad, query); + } + +flushing: + GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query", + gst_flow_get_name (aggpad->priv->flow_return)); + PAD_UNLOCK (aggpad); + + return FALSE; +} + +/* Queue serialized events and let the others go through directly. + * The queued events with be handled from the src-pad task in + * gst_aggregator_do_events_and_queries(). + */ +static GstFlowReturn +gst_aggregator_pad_event_func (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstAggregator *self = GST_AGGREGATOR (parent); + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + if (GST_EVENT_IS_SERIALIZED (event) + && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) { + SRC_LOCK (self); + PAD_LOCK (aggpad); + + if (aggpad->priv->flow_return != GST_FLOW_OK) + goto flushing; + + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + GST_OBJECT_LOCK (aggpad); + gst_event_copy_segment (event, &aggpad->priv->head_segment); + aggpad->priv->head_position = aggpad->priv->head_segment.position; + update_time_level (aggpad, TRUE); + GST_OBJECT_UNLOCK (aggpad); + } + + GST_DEBUG_OBJECT (aggpad, "Store event in queue: %" GST_PTR_FORMAT, event); + g_queue_push_head (&aggpad->priv->data, event); + SRC_BROADCAST (self); + PAD_UNLOCK (aggpad); + SRC_UNLOCK (self); + } else { + GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); + + if (!klass->sink_event (self, aggpad, event)) { + /* Copied from GstPad to convert boolean to a GstFlowReturn in + * the event handling func */ + ret = GST_FLOW_ERROR; + } + } + + return ret; + +flushing: + GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping event", + gst_flow_get_name (aggpad->priv->flow_return)); + PAD_UNLOCK (aggpad); + SRC_UNLOCK (self); + if (GST_EVENT_IS_STICKY (event)) + gst_pad_store_sticky_event (pad, event); + gst_event_unref (event); + + return aggpad->priv->flow_return; +} + +static gboolean +gst_aggregator_pad_activate_mode_func (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active) +{ + GstAggregator *self = GST_AGGREGATOR (parent); + GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); + + if (active == FALSE) { + SRC_LOCK (self); + gst_aggregator_pad_set_flushing (aggpad, GST_FLOW_FLUSHING, TRUE); + SRC_BROADCAST (self); + SRC_UNLOCK (self); + } else { + PAD_LOCK (aggpad); + aggpad->priv->flow_return = GST_FLOW_OK; + PAD_BROADCAST_EVENT (aggpad); + PAD_UNLOCK (aggpad); + } + + return TRUE; +} + +/*********************************** + * GstAggregatorPad implementation * + ************************************/ +G_DEFINE_TYPE (GstAggregatorPad, gst_aggregator_pad, GST_TYPE_PAD); + +static void +gst_aggregator_pad_constructed (GObject * object) +{ + GstPad *pad = GST_PAD (object); + + if (GST_PAD_IS_SINK (pad)) { + gst_pad_set_chain_function (pad, + GST_DEBUG_FUNCPTR (gst_aggregator_pad_chain)); + gst_pad_set_event_full_function_full (pad, + GST_DEBUG_FUNCPTR (gst_aggregator_pad_event_func), NULL, NULL); + gst_pad_set_query_function (pad, + GST_DEBUG_FUNCPTR (gst_aggregator_pad_query_func)); + gst_pad_set_activatemode_function (pad, + GST_DEBUG_FUNCPTR (gst_aggregator_pad_activate_mode_func)); + } +} + +static void +gst_aggregator_pad_finalize (GObject * object) +{ + GstAggregatorPad *pad = (GstAggregatorPad *) object; + + g_cond_clear (&pad->priv->event_cond); + g_mutex_clear (&pad->priv->flush_lock); + g_mutex_clear (&pad->priv->lock); + + G_OBJECT_CLASS (gst_aggregator_pad_parent_class)->finalize (object); +} + +static void +gst_aggregator_pad_dispose (GObject * object) +{ + GstAggregatorPad *pad = (GstAggregatorPad *) object; + + gst_aggregator_pad_set_flushing (pad, GST_FLOW_FLUSHING, TRUE); + + G_OBJECT_CLASS (gst_aggregator_pad_parent_class)->dispose (object); +} + +static void +gst_aggregator_pad_class_init (GstAggregatorPadClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstAggregatorPadPrivate)); + + gobject_class->constructed = gst_aggregator_pad_constructed; + gobject_class->finalize = gst_aggregator_pad_finalize; + gobject_class->dispose = gst_aggregator_pad_dispose; +} + +static void +gst_aggregator_pad_init (GstAggregatorPad * pad) +{ + pad->priv = + G_TYPE_INSTANCE_GET_PRIVATE (pad, GST_TYPE_AGGREGATOR_PAD, + GstAggregatorPadPrivate); + + g_queue_init (&pad->priv->data); + g_cond_init (&pad->priv->event_cond); + + g_mutex_init (&pad->priv->flush_lock); + g_mutex_init (&pad->priv->lock); + + gst_aggregator_pad_reset_unlocked (pad); + pad->priv->negotiated = FALSE; +} + +/* Must be called with the PAD_LOCK held */ +static void +gst_aggregator_pad_buffer_consumed (GstAggregatorPad * pad) +{ + pad->priv->num_buffers--; + GST_TRACE_OBJECT (pad, "Consuming buffer"); + PAD_BROADCAST_EVENT (pad); +} + +/* Must be called with the PAD_LOCK held */ +static void +gst_aggregator_pad_clip_buffer_unlocked (GstAggregatorPad * pad) +{ + GstAggregator *self = NULL; + GstAggregatorClass *aggclass = NULL; + GstBuffer *buffer = NULL; + + while (pad->priv->clipped_buffer == NULL && + GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->data))) { + buffer = g_queue_pop_tail (&pad->priv->data); + + apply_buffer (pad, buffer, FALSE); + + /* We only take the parent here so that it's not taken if the buffer is + * already clipped or if the queue is empty. + */ + if (self == NULL) { + self = GST_AGGREGATOR (gst_pad_get_parent_element (GST_PAD (pad))); + if (self == NULL) { + gst_buffer_unref (buffer); + return; + } + + aggclass = GST_AGGREGATOR_GET_CLASS (self); + } + + if (aggclass->clip) { + GST_TRACE_OBJECT (pad, "Clipping: %" GST_PTR_FORMAT, buffer); + + buffer = aggclass->clip (self, pad, buffer); + + if (buffer == NULL) { + gst_aggregator_pad_buffer_consumed (pad); + GST_TRACE_OBJECT (pad, "Clipping consumed the buffer"); + } + } + + pad->priv->clipped_buffer = buffer; + } + + if (self) + gst_object_unref (self); +} + +/** + * gst_aggregator_pad_pop_buffer: + * @pad: the pad to get buffer from + * + * Steal the ref to the buffer currently queued in @pad. + * + * Returns: (transfer full): The buffer in @pad or NULL if no buffer was + * queued. You should unref the buffer after usage. + */ +GstBuffer * +gst_aggregator_pad_pop_buffer (GstAggregatorPad * pad) +{ + GstBuffer *buffer; + + PAD_LOCK (pad); + + gst_aggregator_pad_clip_buffer_unlocked (pad); + + buffer = pad->priv->clipped_buffer; + + if (buffer) { + pad->priv->clipped_buffer = NULL; + gst_aggregator_pad_buffer_consumed (pad); + GST_DEBUG_OBJECT (pad, "Consumed: %" GST_PTR_FORMAT, buffer); + } + + PAD_UNLOCK (pad); + + return buffer; +} + +/** + * gst_aggregator_pad_drop_buffer: + * @pad: the pad where to drop any pending buffer + * + * Drop the buffer currently queued in @pad. + * + * Returns: TRUE if there was a buffer queued in @pad, or FALSE if not. + */ +gboolean +gst_aggregator_pad_drop_buffer (GstAggregatorPad * pad) +{ + GstBuffer *buf; + + buf = gst_aggregator_pad_pop_buffer (pad); + + if (buf == NULL) + return FALSE; + + gst_buffer_unref (buf); + return TRUE; +} + +/** + * gst_aggregator_pad_peek_buffer: + * @pad: the pad to get buffer from + * + * Returns: (transfer full): A reference to the buffer in @pad or + * NULL if no buffer was queued. You should unref the buffer after + * usage. + */ +GstBuffer * +gst_aggregator_pad_peek_buffer (GstAggregatorPad * pad) +{ + GstBuffer *buffer; + + PAD_LOCK (pad); + + gst_aggregator_pad_clip_buffer_unlocked (pad); + + if (pad->priv->clipped_buffer) { + buffer = gst_buffer_ref (pad->priv->clipped_buffer); + } else { + buffer = NULL; + } + PAD_UNLOCK (pad); + + return buffer; +} + +/** + * gst_aggregator_pad_has_buffer: + * @pad: the pad to check the buffer on + * + * Returns: %TRUE if the pad has a buffer available as the next thing. + * + * Since: 1.14.1 + */ +gboolean +gst_aggregator_pad_has_buffer (GstAggregatorPad * pad) +{ + gboolean has_buffer; + + PAD_LOCK (pad); + gst_aggregator_pad_clip_buffer_unlocked (pad); + has_buffer = (pad->priv->clipped_buffer != NULL); + PAD_UNLOCK (pad); + + return has_buffer; +} + +/** + * gst_aggregator_pad_is_eos: + * @pad: an aggregator pad + * + * Returns: %TRUE if the pad is EOS, otherwise %FALSE. + */ +gboolean +gst_aggregator_pad_is_eos (GstAggregatorPad * pad) +{ + gboolean is_eos; + + PAD_LOCK (pad); + is_eos = pad->priv->eos; + PAD_UNLOCK (pad); + + return is_eos; +} + +#if 0 +/* + * gst_aggregator_merge_tags: + * @self: a #GstAggregator + * @tags: a #GstTagList to merge + * @mode: the #GstTagMergeMode to use + * + * Adds tags to so-called pending tags, which will be processed + * before pushing out data downstream. + * + * Note that this is provided for convenience, and the subclass is + * not required to use this and can still do tag handling on its own. + * + * MT safe. + */ +void +gst_aggregator_merge_tags (GstAggregator * self, + const GstTagList * tags, GstTagMergeMode mode) +{ + GstTagList *otags; + + g_return_if_fail (GST_IS_AGGREGATOR (self)); + g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags)); + + /* FIXME Check if we can use OBJECT lock here! */ + GST_OBJECT_LOCK (self); + if (tags) + GST_DEBUG_OBJECT (self, "merging tags %" GST_PTR_FORMAT, tags); + otags = self->priv->tags; + self->priv->tags = gst_tag_list_merge (self->priv->tags, tags, mode); + if (otags) + gst_tag_list_unref (otags); + self->priv->tags_changed = TRUE; + GST_OBJECT_UNLOCK (self); +} +#endif + +/** + * gst_aggregator_set_latency: + * @self: a #GstAggregator + * @min_latency: minimum latency + * @max_latency: maximum latency + * + * Lets #GstAggregator sub-classes tell the baseclass what their internal + * latency is. Will also post a LATENCY message on the bus so the pipeline + * can reconfigure its global latency. + */ +void +gst_aggregator_set_latency (GstAggregator * self, + GstClockTime min_latency, GstClockTime max_latency) +{ + gboolean changed = FALSE; + + g_return_if_fail (GST_IS_AGGREGATOR (self)); + g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency)); + g_return_if_fail (max_latency >= min_latency); + + SRC_LOCK (self); + if (self->priv->sub_latency_min != min_latency) { + self->priv->sub_latency_min = min_latency; + changed = TRUE; + } + if (self->priv->sub_latency_max != max_latency) { + self->priv->sub_latency_max = max_latency; + changed = TRUE; + } + + if (changed) + SRC_BROADCAST (self); + SRC_UNLOCK (self); + + if (changed) { + gst_element_post_message (GST_ELEMENT_CAST (self), + gst_message_new_latency (GST_OBJECT_CAST (self))); + } +} + +/** + * gst_aggregator_get_buffer_pool: + * @self: a #GstAggregator + * + * Returns: (transfer full): the instance of the #GstBufferPool used + * by @trans; free it after use it + */ +GstBufferPool * +gst_aggregator_get_buffer_pool (GstAggregator * self) +{ + GstBufferPool *pool; + + g_return_val_if_fail (GST_IS_AGGREGATOR (self), NULL); + + GST_OBJECT_LOCK (self); + pool = self->priv->pool; + if (pool) + gst_object_ref (pool); + GST_OBJECT_UNLOCK (self); + + return pool; +} + +/** + * gst_aggregator_get_allocator: + * @self: a #GstAggregator + * @allocator: (out) (allow-none) (transfer full): the #GstAllocator + * used + * @params: (out) (allow-none) (transfer full): the + * #GstAllocationParams of @allocator + * + * Lets #GstAggregator sub-classes get the memory @allocator + * acquired by the base class and its @params. + * + * Unref the @allocator after use it. + */ +void +gst_aggregator_get_allocator (GstAggregator * self, + GstAllocator ** allocator, GstAllocationParams * params) +{ + g_return_if_fail (GST_IS_AGGREGATOR (self)); + + if (allocator) + *allocator = self->priv->allocator ? + gst_object_ref (self->priv->allocator) : NULL; + + if (params) + *params = self->priv->allocation_params; +} diff --git a/libs/gst/base/gstaggregator.h b/libs/gst/base/gstaggregator.h new file mode 100644 index 0000000..4c9c77d --- /dev/null +++ b/libs/gst/base/gstaggregator.h @@ -0,0 +1,346 @@ +/* GStreamer aggregator base class + * Copyright (C) 2014 Mathieu Duponchelle + * Copyright (C) 2014 Thibault Saunier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_AGGREGATOR_H__ +#define __GST_AGGREGATOR_H__ + +#include +#include + +G_BEGIN_DECLS + +/************************** + * GstAggregator Structs * + *************************/ + +typedef struct _GstAggregator GstAggregator; +typedef struct _GstAggregatorPrivate GstAggregatorPrivate; +typedef struct _GstAggregatorClass GstAggregatorClass; + +/************************ + * GstAggregatorPad API * + ***********************/ + +#define GST_TYPE_AGGREGATOR_PAD (gst_aggregator_pad_get_type()) +#define GST_AGGREGATOR_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPad)) +#define GST_AGGREGATOR_PAD_CAST(obj) ((GstAggregatorPad *)(obj)) +#define GST_AGGREGATOR_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPadClass)) +#define GST_AGGREGATOR_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AGGREGATOR_PAD, GstAggregatorPadClass)) +#define GST_IS_AGGREGATOR_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGGREGATOR_PAD)) +#define GST_IS_AGGREGATOR_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR_PAD)) + +/**************************** + * GstAggregatorPad Structs * + ***************************/ + +typedef struct _GstAggregatorPad GstAggregatorPad; +typedef struct _GstAggregatorPadClass GstAggregatorPadClass; +typedef struct _GstAggregatorPadPrivate GstAggregatorPadPrivate; + +/** + * GstAggregatorPad: + * @segment: last segment received. + * + * The implementation the GstPad to use with #GstAggregator + */ +struct _GstAggregatorPad +{ + GstPad parent; + + /* Protected by the OBJECT_LOCK */ + GstSegment segment; + + /* < Private > */ + GstAggregatorPadPrivate * priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstAggregatorPadClass: + * @flush: Optional + * Called when the pad has received a flush stop, this is the place + * to flush any information specific to the pad, it allows for individual + * pads to be flushed while others might not be. + * @skip_buffer: Optional + * Called before input buffers are queued in the pad, return %TRUE + * if the buffer should be skipped. + * + */ +struct _GstAggregatorPadClass +{ + GstPadClass parent_class; + + GstFlowReturn (*flush) (GstAggregatorPad * aggpad, GstAggregator * aggregator); + gboolean (*skip_buffer) (GstAggregatorPad * aggpad, GstAggregator * aggregator, GstBuffer * buffer); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GST_BASE_API +GType gst_aggregator_pad_get_type (void); + +/**************************** + * GstAggregatorPad methods * + ***************************/ + +GST_BASE_API +GstBuffer * gst_aggregator_pad_pop_buffer (GstAggregatorPad * pad); + +GST_BASE_API +GstBuffer * gst_aggregator_pad_peek_buffer (GstAggregatorPad * pad); + +GST_BASE_API +gboolean gst_aggregator_pad_drop_buffer (GstAggregatorPad * pad); + +GST_BASE_API +gboolean gst_aggregator_pad_has_buffer (GstAggregatorPad * pad); + +GST_BASE_API +gboolean gst_aggregator_pad_is_eos (GstAggregatorPad * pad); + +/********************* + * GstAggregator API * + ********************/ + +#define GST_TYPE_AGGREGATOR (gst_aggregator_get_type()) +#define GST_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AGGREGATOR,GstAggregator)) +#define GST_AGGREGATOR_CAST(obj) ((GstAggregator *)(obj)) +#define GST_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AGGREGATOR,GstAggregatorClass)) +#define GST_AGGREGATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AGGREGATOR,GstAggregatorClass)) +#define GST_IS_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AGGREGATOR)) +#define GST_IS_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR)) + +#define GST_AGGREGATOR_FLOW_NEED_DATA GST_FLOW_CUSTOM_ERROR + +/** + * GstAggregator: + * @srcpad: the aggregator's source pad + * @segment: the output segment + * + * Aggregator base class object structure. + */ +struct _GstAggregator +{ + GstElement parent; + + GstPad * srcpad; + + /*< private >*/ + GstAggregatorPrivate * priv; + + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +/** + * GstAggregatorClass: + * @flush: Optional. + * Called after a successful flushing seek, once all the flush + * stops have been received. Flush pad-specific data in + * #GstAggregatorPad->flush. + * @clip: Optional. + * Called when a buffer is received on a sink pad, the task of + * clipping it and translating it to the current segment falls + * on the subclass. The function should use the segment of data + * and the negotiated media type on the pad to perform + * clipping of input buffer. This function takes ownership of + * buf and should output a buffer or return NULL in + * if the buffer should be dropped. + * @finish_buffer: Optional. + * Called when a subclass calls gst_aggregator_finish_buffer() + * from their aggregate function to push out a buffer. + * Subclasses can override this to modify or decorate buffers + * before they get pushed out. This function takes ownership + * of the buffer passed. Subclasses that override this method + * should always chain up to the parent class virtual method. + * @sink_event: Optional. + * Called when an event is received on a sink pad, the subclass + * should always chain up. + * @sink_query: Optional. + * Called when a query is received on a sink pad, the subclass + * should always chain up. + * @src_event: Optional. + * Called when an event is received on the src pad, the subclass + * should always chain up. + * @src_query: Optional. + * Called when a query is received on the src pad, the subclass + * should always chain up. + * @src_activate: Optional. + * Called when the src pad is activated, it will start/stop its + * pad task right after that call. + * @aggregate: Mandatory. + * Called when buffers are queued on all sinkpads. Classes + * should iterate the GstElement->sinkpads and peek or steal + * buffers from the #GstAggregatorPads. If the subclass returns + * GST_FLOW_EOS, sending of the eos event will be taken care + * of. Once / if a buffer has been constructed from the + * aggregated buffers, the subclass should call _finish_buffer. + * @stop: Optional. + * Called when the element goes from PAUSED to READY. + * The subclass should free all resources and reset its state. + * @start: Optional. + * Called when the element goes from READY to PAUSED. + * The subclass should get ready to process + * aggregated buffers. + * @get_next_time: Optional. + * Called when the element needs to know the running time of the next + * rendered buffer for live pipelines. This causes deadline + * based aggregation to occur. Defaults to returning + * GST_CLOCK_TIME_NONE causing the element to wait for buffers + * on all sink pads before aggregating. + * @update_src_caps: Lets subclasses update the #GstCaps representing + * the src pad caps before usage. The result should end up + * in @ret. Return %GST_AGGREGATOR_FLOW_NEED_DATA to indicate that the + * element needs more information (caps, a buffer, etc) to + * choose the correct caps. Should return ANY caps if the + * stream has not caps at all. + * @fixate_src_caps: Optional. + * Fixate and return the src pad caps provided. The function takes + * ownership of @caps and returns a fixated version of + * @caps. @caps is not guaranteed to be writable. + * @negotiated_src_caps: Optional. + * Notifies subclasses what caps format has been negotiated + * @decide_allocation: Optional. + * Allows the subclass to influence the allocation choices. + * Setup the allocation parameters for allocating output + * buffers. The passed in query contains the result of the + * downstream allocation query. + * + * The aggregator base class will handle in a thread-safe way all manners of + * concurrent flushes, seeks, pad additions and removals, leaving to the + * subclass the responsibility of clipping buffers, and aggregating buffers in + * the way the implementor sees fit. + * + * It will also take care of event ordering (stream-start, segment, eos). + * + * Basically, a simple implementation will override @aggregate, and call + * _finish_buffer from inside that function. + */ +struct _GstAggregatorClass { + GstElementClass parent_class; + + GstFlowReturn (*flush) (GstAggregator * aggregator); + + GstBuffer * (*clip) (GstAggregator * aggregator, + GstAggregatorPad * aggregator_pad, + GstBuffer * buf); + + GstFlowReturn (*finish_buffer) (GstAggregator * aggregator, + GstBuffer * buffer); + + /* sinkpads virtual methods */ + gboolean (*sink_event) (GstAggregator * aggregator, + GstAggregatorPad * aggregator_pad, + GstEvent * event); + + gboolean (*sink_query) (GstAggregator * aggregator, + GstAggregatorPad * aggregator_pad, + GstQuery * query); + + /* srcpad virtual methods */ + gboolean (*src_event) (GstAggregator * aggregator, + GstEvent * event); + + gboolean (*src_query) (GstAggregator * aggregator, + GstQuery * query); + + gboolean (*src_activate) (GstAggregator * aggregator, + GstPadMode mode, + gboolean active); + + GstFlowReturn (*aggregate) (GstAggregator * aggregator, + gboolean timeout); + + gboolean (*stop) (GstAggregator * aggregator); + + gboolean (*start) (GstAggregator * aggregator); + + GstClockTime (*get_next_time) (GstAggregator * aggregator); + + GstAggregatorPad * (*create_new_pad) (GstAggregator * self, + GstPadTemplate * templ, + const gchar * req_name, + const GstCaps * caps); + GstFlowReturn (*update_src_caps) (GstAggregator * self, + GstCaps * caps, + GstCaps ** ret); + GstCaps * (*fixate_src_caps) (GstAggregator * self, + GstCaps * caps); + gboolean (*negotiated_src_caps) (GstAggregator * self, + GstCaps * caps); + gboolean (*decide_allocation) (GstAggregator * self, + GstQuery * query); + gboolean (*propose_allocation) (GstAggregator * self, + GstAggregatorPad * pad, + GstQuery * decide_query, + GstQuery * query); + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +/************************************ + * GstAggregator convenience macros * + ***********************************/ + +/** + * GST_AGGREGATOR_SRC_PAD: + * @agg: a #GstAggregator + * + * Convenience macro to access the source pad of #GstAggregator + * + * Since: 1.6 + */ +#define GST_AGGREGATOR_SRC_PAD(agg) (((GstAggregator *)(agg))->srcpad) + +/************************* + * GstAggregator methods * + ************************/ + +GST_BASE_API +GstFlowReturn gst_aggregator_finish_buffer (GstAggregator * aggregator, + GstBuffer * buffer); + +GST_BASE_API +void gst_aggregator_set_src_caps (GstAggregator * self, + GstCaps * caps); + +GST_BASE_API +void gst_aggregator_set_latency (GstAggregator * self, + GstClockTime min_latency, + GstClockTime max_latency); + +GST_BASE_API +GType gst_aggregator_get_type(void); + +GST_BASE_API +GstClockTime gst_aggregator_get_latency (GstAggregator * self); + +GST_BASE_API +GstBufferPool * gst_aggregator_get_buffer_pool (GstAggregator * self); + +GST_BASE_API +void gst_aggregator_get_allocator (GstAggregator * self, + GstAllocator ** allocator, + GstAllocationParams * params); + +G_END_DECLS + +#endif /* __GST_AGGREGATOR_H__ */ diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c new file mode 100644 index 0000000..8ac6a3f --- /dev/null +++ b/libs/gst/base/gstbaseparse.c @@ -0,0 +1,4952 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * Copyright (C) 2008 Sebastian Dröge . + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbaseparse + * @title: GstBaseParse + * @short_description: Base class for stream parsers + * @see_also: #GstBaseTransform + * + * This base class is for parser elements that process data and splits it + * into separate audio/video/whatever frames. + * + * It provides for: + * + * * provides one sink pad and one source pad + * * handles state changes + * * can operate in pull mode or push mode + * * handles seeking in both modes + * * handles events (SEGMENT/EOS/FLUSH) + * * handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT) + * * handles flushing + * + * The purpose of this base class is to provide the basic functionality of + * a parser and share a lot of rather complex code. + * + * # Description of the parsing mechanism: + * + * ## Set-up phase + * + * * #GstBaseParse calls @start to inform subclass that data processing is + * about to start now. + * + * * #GstBaseParse class calls @set_sink_caps to inform the subclass about + * incoming sinkpad caps. Subclass could already set the srcpad caps + * accordingly, but this might be delayed until calling + * gst_base_parse_finish_frame() with a non-queued frame. + * + * * At least at this point subclass needs to tell the #GstBaseParse class + * how big data chunks it wants to receive (min_frame_size). It can do + * this with gst_base_parse_set_min_frame_size(). + * + * * #GstBaseParse class sets up appropriate data passing mode (pull/push) + * and starts to process the data. + * + * ## Parsing phase + * + * * #GstBaseParse gathers at least min_frame_size bytes of data either + * by pulling it from upstream or collecting buffers in an internal + * #GstAdapter. + * + * * A buffer of (at least) min_frame_size bytes is passed to subclass with + * @handle_frame. Subclass checks the contents and can optionally + * return GST_FLOW_OK along with an amount of data to be skipped to find + * a valid frame (which will result in a subsequent DISCONT). + * If, otherwise, the buffer does not hold a complete frame, + * @handle_frame can merely return and will be called again when additional + * data is available. In push mode this amounts to an + * additional input buffer (thus minimal additional latency), in pull mode + * this amounts to some arbitrary reasonable buffer size increase. + * Of course, gst_base_parse_set_min_frame_size() could also be used if a + * very specific known amount of additional data is required. + * If, however, the buffer holds a complete valid frame, it can pass + * the size of this frame to gst_base_parse_finish_frame(). + * If acting as a converter, it can also merely indicate consumed input data + * while simultaneously providing custom output data. + * Note that baseclass performs some processing (such as tracking + * overall consumed data rate versus duration) for each finished frame, + * but other state is only updated upon each call to @handle_frame + * (such as tracking upstream input timestamp). + * + * Subclass is also responsible for setting the buffer metadata + * (e.g. buffer timestamp and duration, or keyframe if applicable). + * (although the latter can also be done by #GstBaseParse if it is + * appropriately configured, see below). Frame is provided with + * timestamp derived from upstream (as much as generally possible), + * duration obtained from configuration (see below), and offset + * if meaningful (in pull mode). + * + * Note that @check_valid_frame might receive any small + * amount of input data when leftover data is being drained (e.g. at EOS). + * + * * As part of finish frame processing, + * just prior to actually pushing the buffer in question, + * it is passed to @pre_push_frame which gives subclass yet one + * last chance to examine buffer metadata, or to send some custom (tag) + * events, or to perform custom (segment) filtering. + * + * * During the parsing process #GstBaseParseClass will handle both srcpad + * and sinkpad events. They will be passed to subclass if @event or + * @src_event callbacks have been provided. + * + * ## Shutdown phase + * + * * #GstBaseParse class calls @stop to inform the subclass that data + * parsing will be stopped. + * + * Subclass is responsible for providing pad template caps for + * source and sink pads. The pads need to be named "sink" and "src". It also + * needs to set the fixed caps on srcpad, when the format is ensured (e.g. + * when base class calls subclass' @set_sink_caps function). + * + * This base class uses %GST_FORMAT_DEFAULT as a meaning of frames. So, + * subclass conversion routine needs to know that conversion from + * %GST_FORMAT_TIME to %GST_FORMAT_DEFAULT must return the + * frame number that can be found from the given byte position. + * + * #GstBaseParse uses subclasses conversion methods also for seeking (or + * otherwise uses its own default one, see also below). + * + * Subclass @start and @stop functions will be called to inform the beginning + * and end of data processing. + * + * Things that subclass need to take care of: + * + * * Provide pad templates + * * Fixate the source pad caps when appropriate + * * Inform base class how big data chunks should be retrieved. This is + * done with gst_base_parse_set_min_frame_size() function. + * * Examine data chunks passed to subclass with @handle_frame and pass + * proper frame(s) to gst_base_parse_finish_frame(), and setting src pad + * caps and timestamps on frame. + * * Provide conversion functions + * * Update the duration information with gst_base_parse_set_duration() + * * Optionally passthrough using gst_base_parse_set_passthrough() + * * Configure various baseparse parameters using + * gst_base_parse_set_average_bitrate(), gst_base_parse_set_syncable() + * and gst_base_parse_set_frame_rate(). + * + * * In particular, if subclass is unable to determine a duration, but + * parsing (or specs) yields a frames per seconds rate, then this can be + * provided to #GstBaseParse to enable it to cater for + * buffer time metadata (which will be taken from upstream as much as + * possible). Internally keeping track of frame durations and respective + * sizes that have been pushed provides #GstBaseParse with an estimated + * bitrate. A default @convert (used if not overridden) will then use these + * rates to perform obvious conversions. These rates are also used to + * update (estimated) duration at regular frame intervals. + * + */ + +/* TODO: + * - In push mode provide a queue of adapter-"queued" buffers for upstream + * buffer metadata + * - Queue buffers/events until caps are set + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#include "gstbaseparse.h" + +/* FIXME: get rid of old GstIndex code */ +#include "gstindex.h" +#include "gstindex.c" +#include "gstmemindex.c" + +#define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC (1 << 0) + +#define MIN_FRAMES_TO_POST_BITRATE 10 +#define TARGET_DIFFERENCE (20 * GST_SECOND) +#define MAX_INDEX_ENTRIES 4096 +#define UPDATE_THRESHOLD 2 + +#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug); +#define GST_CAT_DEFAULT gst_base_parse_debug + +/* Supported formats */ +static const GstFormat fmtlist[] = { + GST_FORMAT_DEFAULT, + GST_FORMAT_BYTES, + GST_FORMAT_TIME, + GST_FORMAT_UNDEFINED +}; + +#define GST_BASE_PARSE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate)) + +struct _GstBaseParsePrivate +{ + GstPadMode pad_mode; + + GstAdapter *adapter; + + gint64 duration; + GstFormat duration_fmt; + gint64 estimated_duration; + gint64 estimated_drift; + + guint min_frame_size; + gboolean disable_passthrough; + gboolean passthrough; + gboolean pts_interpolate; + gboolean infer_ts; + gboolean syncable; + gboolean has_timing_info; + guint fps_num, fps_den; + gint update_interval; + guint bitrate; + guint lead_in, lead_out; + GstClockTime lead_in_ts, lead_out_ts; + GstClockTime min_latency, max_latency; + + gboolean discont; + gboolean flushing; + gboolean drain; + gboolean saw_gaps; + + gint64 offset; + gint64 sync_offset; + GstClockTime next_pts; + GstClockTime next_dts; + GstClockTime prev_pts; + GstClockTime prev_dts; + gboolean prev_dts_from_pts; + GstClockTime frame_duration; + gboolean seen_keyframe; + gboolean is_video; + gint flushed; + + guint64 framecount; + guint64 bytecount; + guint64 data_bytecount; + guint64 acc_duration; + GstClockTime first_frame_pts; + GstClockTime first_frame_dts; + gint64 first_frame_offset; + + gboolean post_min_bitrate; + gboolean post_avg_bitrate; + gboolean post_max_bitrate; + + guint min_bitrate; + guint avg_bitrate; + guint max_bitrate; + guint posted_avg_bitrate; + + /* frames/buffers that are queued and ready to go on OK */ + GQueue queued_frames; + + GstBuffer *cache; + + /* index entry storage, either ours or provided */ + GstIndex *index; + gint index_id; + gboolean own_index; + GMutex index_lock; + + /* seek table entries only maintained if upstream is BYTE seekable */ + gboolean upstream_seekable; + gboolean upstream_has_duration; + gint64 upstream_size; + GstFormat upstream_format; + /* minimum distance between two index entries */ + GstClockTimeDiff idx_interval; + guint64 idx_byte_interval; + /* ts and offset of last entry added */ + GstClockTime index_last_ts; + gint64 index_last_offset; + gboolean index_last_valid; + + /* timestamps currently produced are accurate, e.g. started from 0 onwards */ + gboolean exact_position; + /* seek events are temporarily kept to match them with newsegments */ + GSList *pending_seeks; + + /* reverse playback */ + GSList *buffers_pending; + GSList *buffers_head; + GSList *buffers_queued; + GSList *buffers_send; + GstClockTime last_pts; + GstClockTime last_dts; + gint64 last_offset; + + /* Pending serialized events */ + GList *pending_events; + + /* If baseparse has checked the caps to identify if it is + * handling video or audio */ + gboolean checked_media; + + /* offset of last parsed frame/data */ + gint64 prev_offset; + /* force a new frame, regardless of offset */ + gboolean new_frame; + /* whether we are merely scanning for a frame */ + gboolean scanning; + /* ... and resulting frame, if any */ + GstBaseParseFrame *scanned_frame; + + /* TRUE if we're still detecting the format, i.e. + * if ::detect() is still called for future buffers */ + gboolean detecting; + GList *detect_buffers; + guint detect_buffers_size; + + /* True when no buffers have been received yet */ + gboolean first_buffer; + + /* if TRUE, a STREAM_START event needs to be pushed */ + gboolean push_stream_start; + + /* When we need to skip more data than we have currently */ + guint skip; + + /* Tag handling (stream tags only, global tags are passed through as-is) */ + GstTagList *upstream_tags; + GstTagList *parser_tags; + GstTagMergeMode parser_tags_merge_mode; + gboolean tags_changed; +}; + +typedef struct _GstBaseParseSeek +{ + GstSegment segment; + gboolean accurate; + gint64 offset; + GstClockTime start_ts; +} GstBaseParseSeek; + +#define DEFAULT_DISABLE_PASSTHROUGH FALSE + +enum +{ + PROP_0, + PROP_DISABLE_PASSTHROUGH, + PROP_LAST +}; + +#define GST_BASE_PARSE_INDEX_LOCK(parse) \ + g_mutex_lock (&parse->priv->index_lock); +#define GST_BASE_PARSE_INDEX_UNLOCK(parse) \ + g_mutex_unlock (&parse->priv->index_lock); + +static GstElementClass *parent_class = NULL; + +static void gst_base_parse_class_init (GstBaseParseClass * klass); +static void gst_base_parse_init (GstBaseParse * parse, + GstBaseParseClass * klass); + +GType +gst_base_parse_get_type (void) +{ + static volatile gsize base_parse_type = 0; + + if (g_once_init_enter (&base_parse_type)) { + static const GTypeInfo base_parse_info = { + sizeof (GstBaseParseClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gst_base_parse_class_init, + NULL, + NULL, + sizeof (GstBaseParse), + 0, + (GInstanceInitFunc) gst_base_parse_init, + }; + GType _type; + + _type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseParse", &base_parse_info, G_TYPE_FLAG_ABSTRACT); + g_once_init_leave (&base_parse_type, _type); + } + return (GType) base_parse_type; +} + +static void gst_base_parse_finalize (GObject * object); + +static GstStateChangeReturn gst_base_parse_change_state (GstElement * element, + GstStateChange transition); +static void gst_base_parse_reset (GstBaseParse * parse); + +#if 0 +static void gst_base_parse_set_index (GstElement * element, GstIndex * index); +static GstIndex *gst_base_parse_get_index (GstElement * element); +#endif + +static gboolean gst_base_parse_sink_activate (GstPad * sinkpad, + GstObject * parent); +static gboolean gst_base_parse_sink_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_base_parse_handle_seek (GstBaseParse * parse, + GstEvent * event); +static void gst_base_parse_set_upstream_tags (GstBaseParse * parse, + GstTagList * taglist); + +static void gst_base_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static gboolean gst_base_parse_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_base_parse_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static void gst_base_parse_loop (GstPad * pad); + +static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); + +static gboolean gst_base_parse_sink_event_default (GstBaseParse * parse, + GstEvent * event); + +static gboolean gst_base_parse_src_event_default (GstBaseParse * parse, + GstEvent * event); + +static gboolean gst_base_parse_sink_query_default (GstBaseParse * parse, + GstQuery * query); +static gboolean gst_base_parse_src_query_default (GstBaseParse * parse, + GstQuery * query); + +static gint64 gst_base_parse_find_offset (GstBaseParse * parse, + GstClockTime time, gboolean before, GstClockTime * _ts); +static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse, + GstClockTime * _time, gint64 * _offset); + +static GstFlowReturn gst_base_parse_start_fragment (GstBaseParse * parse); +static GstFlowReturn gst_base_parse_finish_fragment (GstBaseParse * parse, + gboolean prev_head); +static GstFlowReturn gst_base_parse_send_buffers (GstBaseParse * parse); + +static inline GstFlowReturn gst_base_parse_check_sync (GstBaseParse * parse); + +static gboolean gst_base_parse_is_seekable (GstBaseParse * parse); + +static void gst_base_parse_push_pending_events (GstBaseParse * parse); + +static void +gst_base_parse_clear_queues (GstBaseParse * parse) +{ + g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_queued); + parse->priv->buffers_queued = NULL; + g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref, + NULL); + g_slist_free (parse->priv->buffers_pending); + parse->priv->buffers_pending = NULL; + g_slist_foreach (parse->priv->buffers_head, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_head); + parse->priv->buffers_head = NULL; + g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_send); + parse->priv->buffers_send = NULL; + + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + + g_queue_foreach (&parse->priv->queued_frames, + (GFunc) gst_base_parse_frame_free, NULL); + g_queue_clear (&parse->priv->queued_frames); + + gst_buffer_replace (&parse->priv->cache, NULL); + + g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (parse->priv->pending_events); + parse->priv->pending_events = NULL; + + parse->priv->checked_media = FALSE; +} + +static void +gst_base_parse_finalize (GObject * object) +{ + GstBaseParse *parse = GST_BASE_PARSE (object); + + g_object_unref (parse->priv->adapter); + + if (parse->priv->index) { + gst_object_unref (parse->priv->index); + parse->priv->index = NULL; + } + g_mutex_clear (&parse->priv->index_lock); + + gst_base_parse_clear_queues (parse); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_base_parse_class_init (GstBaseParseClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + g_type_class_add_private (klass, sizeof (GstBaseParsePrivate)); + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_parse_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_parse_get_property); + + /** + * GstBaseParse:disable-passthrough: + * + * If set to %TRUE, baseparse will unconditionally force parsing of the + * incoming data. This can be required in the rare cases where the incoming + * side-data (caps, pts, dts, ...) is not trusted by the user and wants to + * force validation and parsing of the incoming data. + * If set to %FALSE, decision of whether to parse the data or not is up to + * the implementation (standard behaviour). + */ + g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH, + g_param_spec_boolean ("disable-passthrough", "Disable passthrough", + "Force processing (disables passthrough)", + DEFAULT_DISABLE_PASSTHROUGH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class = (GstElementClass *) klass; + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_parse_change_state); + +#if 0 + gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index); + gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index); +#endif + + /* Default handlers */ + klass->sink_event = gst_base_parse_sink_event_default; + klass->src_event = gst_base_parse_src_event_default; + klass->sink_query = gst_base_parse_sink_query_default; + klass->src_query = gst_base_parse_src_query_default; + klass->convert = gst_base_parse_convert_default; + + GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0, + "baseparse element"); +} + +static void +gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) +{ + GstPadTemplate *pad_template; + + GST_DEBUG_OBJECT (parse, "gst_base_parse_init"); + + parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); + g_return_if_fail (pad_template != NULL); + parse->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_event_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_event)); + gst_pad_set_query_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_query)); + gst_pad_set_chain_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_chain)); + gst_pad_set_activate_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate)); + gst_pad_set_activatemode_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode)); + GST_PAD_SET_PROXY_ALLOCATION (parse->sinkpad); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + GST_DEBUG_OBJECT (parse, "sinkpad created"); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); + g_return_if_fail (pad_template != NULL); + parse->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_set_event_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_base_parse_src_event)); + gst_pad_set_query_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_base_parse_src_query)); + gst_pad_use_fixed_caps (parse->srcpad); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); + GST_DEBUG_OBJECT (parse, "src created"); + + g_queue_init (&parse->priv->queued_frames); + + parse->priv->adapter = gst_adapter_new (); + + parse->priv->pad_mode = GST_PAD_MODE_NONE; + + g_mutex_init (&parse->priv->index_lock); + + /* init state */ + gst_base_parse_reset (parse); + GST_DEBUG_OBJECT (parse, "init ok"); + + GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE); + + parse->priv->upstream_tags = NULL; + parse->priv->parser_tags = NULL; + parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND; +} + +static void +gst_base_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseParse *parse = GST_BASE_PARSE (object); + + switch (prop_id) { + case PROP_DISABLE_PASSTHROUGH: + parse->priv->disable_passthrough = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBaseParse *parse = GST_BASE_PARSE (object); + + switch (prop_id) { + case PROP_DISABLE_PASSTHROUGH: + g_value_set_boolean (value, parse->priv->disable_passthrough); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +GstBaseParseFrame * +gst_base_parse_frame_copy (GstBaseParseFrame * frame) +{ + GstBaseParseFrame *copy; + + copy = g_slice_dup (GstBaseParseFrame, frame); + copy->buffer = gst_buffer_ref (frame->buffer); + copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC; + + GST_TRACE ("copied frame %p -> %p", frame, copy); + + return copy; +} + +void +gst_base_parse_frame_free (GstBaseParseFrame * frame) +{ + GST_TRACE ("freeing frame %p", frame); + + if (frame->buffer) { + gst_buffer_unref (frame->buffer); + frame->buffer = NULL; + } + + if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) { + g_slice_free (GstBaseParseFrame, frame); + } else { + memset (frame, 0, sizeof (*frame)); + } +} + +G_DEFINE_BOXED_TYPE (GstBaseParseFrame, gst_base_parse_frame, + (GBoxedCopyFunc) gst_base_parse_frame_copy, + (GBoxedFreeFunc) gst_base_parse_frame_free); + +/** + * gst_base_parse_frame_init: + * @frame: #GstBaseParseFrame. + * + * Sets a #GstBaseParseFrame to initial state. Currently this means + * all public fields are zero-ed and a private flag is set to make + * sure gst_base_parse_frame_free() only frees the contents but not + * the actual frame. Use this function to initialise a #GstBaseParseFrame + * allocated on the stack. + */ +void +gst_base_parse_frame_init (GstBaseParseFrame * frame) +{ + memset (frame, 0, sizeof (GstBaseParseFrame)); + frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC; + GST_TRACE ("inited frame %p", frame); +} + +/** + * gst_base_parse_frame_new: + * @buffer: (transfer none): a #GstBuffer + * @flags: the flags + * @overhead: number of bytes in this frame which should be counted as + * metadata overhead, ie. not used to calculate the average bitrate. + * Set to -1 to mark the entire frame as metadata. If in doubt, set to 0. + * + * Allocates a new #GstBaseParseFrame. This function is mainly for bindings, + * elements written in C should usually allocate the frame on the stack and + * then use gst_base_parse_frame_init() to initialise it. + * + * Returns: a newly-allocated #GstBaseParseFrame. Free with + * gst_base_parse_frame_free() when no longer needed. + */ +GstBaseParseFrame * +gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags, + gint overhead) +{ + GstBaseParseFrame *frame; + + frame = g_slice_new0 (GstBaseParseFrame); + frame->buffer = gst_buffer_ref (buffer); + + GST_TRACE ("created frame %p", frame); + return frame; +} + +static inline void +gst_base_parse_update_flags (GstBaseParse * parse) +{ + parse->flags = 0; + + /* set flags one by one for clarity */ + if (G_UNLIKELY (parse->priv->drain)) + parse->flags |= GST_BASE_PARSE_FLAG_DRAINING; + + /* losing sync is pretty much a discont (and vice versa), no ? */ + if (G_UNLIKELY (parse->priv->discont)) + parse->flags |= GST_BASE_PARSE_FLAG_LOST_SYNC; +} + +static inline void +gst_base_parse_update_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + if (G_UNLIKELY (parse->priv->discont)) { + GST_DEBUG_OBJECT (parse, "marking DISCONT"); + GST_BUFFER_FLAG_SET (frame->buffer, GST_BUFFER_FLAG_DISCONT); + } else { + GST_BUFFER_FLAG_UNSET (frame->buffer, GST_BUFFER_FLAG_DISCONT); + } + + if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) { + GST_LOG_OBJECT (parse, "marking as new frame"); + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME; + } + + frame->offset = parse->priv->prev_offset = parse->priv->offset; +} + +static void +gst_base_parse_reset (GstBaseParse * parse) +{ + GST_OBJECT_LOCK (parse); + gst_segment_init (&parse->segment, GST_FORMAT_TIME); + parse->priv->duration = -1; + parse->priv->min_frame_size = 1; + parse->priv->discont = TRUE; + parse->priv->flushing = FALSE; + parse->priv->saw_gaps = FALSE; + parse->priv->offset = 0; + parse->priv->sync_offset = 0; + parse->priv->update_interval = -1; + parse->priv->fps_num = parse->priv->fps_den = 0; + parse->priv->frame_duration = GST_CLOCK_TIME_NONE; + parse->priv->lead_in = parse->priv->lead_out = 0; + parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; + parse->priv->bitrate = 0; + parse->priv->framecount = 0; + parse->priv->bytecount = 0; + parse->priv->acc_duration = 0; + parse->priv->first_frame_pts = GST_CLOCK_TIME_NONE; + parse->priv->first_frame_dts = GST_CLOCK_TIME_NONE; + parse->priv->first_frame_offset = -1; + parse->priv->estimated_duration = -1; + parse->priv->estimated_drift = 0; + parse->priv->next_pts = GST_CLOCK_TIME_NONE; + parse->priv->next_dts = 0; + parse->priv->syncable = TRUE; + parse->priv->disable_passthrough = DEFAULT_DISABLE_PASSTHROUGH; + parse->priv->passthrough = FALSE; + parse->priv->pts_interpolate = TRUE; + parse->priv->infer_ts = TRUE; + parse->priv->has_timing_info = FALSE; + parse->priv->min_bitrate = G_MAXUINT; + parse->priv->max_bitrate = 0; + parse->priv->avg_bitrate = 0; + parse->priv->posted_avg_bitrate = 0; + + parse->priv->index_last_ts = GST_CLOCK_TIME_NONE; + parse->priv->index_last_offset = -1; + parse->priv->index_last_valid = TRUE; + parse->priv->upstream_seekable = FALSE; + parse->priv->upstream_size = 0; + parse->priv->upstream_has_duration = FALSE; + parse->priv->upstream_format = GST_FORMAT_UNDEFINED; + parse->priv->idx_interval = 0; + parse->priv->idx_byte_interval = 0; + parse->priv->exact_position = TRUE; + parse->priv->seen_keyframe = FALSE; + parse->priv->checked_media = FALSE; + + parse->priv->last_dts = GST_CLOCK_TIME_NONE; + parse->priv->last_pts = GST_CLOCK_TIME_NONE; + parse->priv->last_offset = 0; + + parse->priv->skip = 0; + + g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref, + NULL); + g_list_free (parse->priv->pending_events); + parse->priv->pending_events = NULL; + + if (parse->priv->cache) { + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + } + + g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL); + g_slist_free (parse->priv->pending_seeks); + parse->priv->pending_seeks = NULL; + + if (parse->priv->adapter) + gst_adapter_clear (parse->priv->adapter); + + gst_base_parse_set_upstream_tags (parse, NULL); + + if (parse->priv->parser_tags) { + gst_tag_list_unref (parse->priv->parser_tags); + parse->priv->parser_tags = NULL; + } + parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND; + + parse->priv->new_frame = TRUE; + + parse->priv->first_buffer = TRUE; + + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + GST_OBJECT_UNLOCK (parse); +} + +static gboolean +gst_base_parse_check_bitrate_tag (GstBaseParse * parse, const gchar * tag) +{ + gboolean got_tag = FALSE; + guint n = 0; + + if (parse->priv->upstream_tags != NULL) + got_tag = gst_tag_list_get_uint (parse->priv->upstream_tags, tag, &n); + + if (!got_tag && parse->priv->parser_tags != NULL) + got_tag = gst_tag_list_get_uint (parse->priv->parser_tags, tag, &n); + + return got_tag; +} + +/* check if upstream or subclass tags contain bitrates already */ +static void +gst_base_parse_check_bitrate_tags (GstBaseParse * parse) +{ + parse->priv->post_min_bitrate = + !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MINIMUM_BITRATE); + parse->priv->post_avg_bitrate = + !gst_base_parse_check_bitrate_tag (parse, GST_TAG_BITRATE); + parse->priv->post_max_bitrate = + !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MAXIMUM_BITRATE); +} + +/* Queues new tag event with the current combined state of the stream tags + * (i.e. upstream tags merged with subclass tags and current baseparse tags) */ +static void +gst_base_parse_queue_tag_event_update (GstBaseParse * parse) +{ + GstTagList *merged_tags; + + GST_LOG_OBJECT (parse, "upstream : %" GST_PTR_FORMAT, + parse->priv->upstream_tags); + GST_LOG_OBJECT (parse, "parser : %" GST_PTR_FORMAT, + parse->priv->parser_tags); + GST_LOG_OBJECT (parse, "mode : %d", parse->priv->parser_tags_merge_mode); + + merged_tags = + gst_tag_list_merge (parse->priv->upstream_tags, parse->priv->parser_tags, + parse->priv->parser_tags_merge_mode); + + GST_DEBUG_OBJECT (parse, "merged : %" GST_PTR_FORMAT, merged_tags); + + if (merged_tags == NULL) + return; + + if (gst_tag_list_is_empty (merged_tags)) { + gst_tag_list_unref (merged_tags); + return; + } + + if (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE) { + /* only add bitrate tags to non-empty taglists for now, and only if neither + * upstream tags nor the subclass sets the bitrate tag in question already */ + if (parse->priv->min_bitrate != G_MAXUINT && parse->priv->post_min_bitrate) { + GST_LOG_OBJECT (parse, "adding min bitrate %u", parse->priv->min_bitrate); + gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP, + GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL); + } + if (parse->priv->max_bitrate != 0 && parse->priv->post_max_bitrate) { + GST_LOG_OBJECT (parse, "adding max bitrate %u", parse->priv->max_bitrate); + gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP, + GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL); + } + if (parse->priv->avg_bitrate != 0 && parse->priv->post_avg_bitrate) { + parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate; + GST_LOG_OBJECT (parse, "adding avg bitrate %u", parse->priv->avg_bitrate); + gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP, + GST_TAG_BITRATE, parse->priv->avg_bitrate, NULL); + } + } + + parse->priv->pending_events = + g_list_prepend (parse->priv->pending_events, + gst_event_new_tag (merged_tags)); +} + +/* gst_base_parse_parse_frame: + * @parse: #GstBaseParse. + * @buffer: #GstBuffer. + * + * Default callback for parse_frame. + */ +static GstFlowReturn +gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + GstBuffer *buffer = frame->buffer; + + if (!GST_BUFFER_PTS_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts)) { + GST_BUFFER_PTS (buffer) = parse->priv->next_pts; + } + if (!GST_BUFFER_DTS_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts)) { + GST_BUFFER_DTS (buffer) = parse->priv->next_dts; + } + if (!GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) { + GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration; + } + return GST_FLOW_OK; +} + +/* gst_base_parse_convert: + * @parse: #GstBaseParse. + * @src_format: #GstFormat describing the source format. + * @src_value: Source value to be converted. + * @dest_format: #GstFormat defining the converted format. + * @dest_value: Pointer where the conversion result will be put. + * + * Converts using configured "convert" vmethod in #GstBaseParse class. + * + * Returns: %TRUE if conversion was successful. + */ +static gboolean +gst_base_parse_convert (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + gboolean ret; + + g_return_val_if_fail (dest_value != NULL, FALSE); + + if (!klass->convert) + return FALSE; + + ret = klass->convert (parse, src_format, src_value, dest_format, dest_value); + +#ifndef GST_DISABLE_GST_DEBUG + { + if (ret) { + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { + GST_LOG_OBJECT (parse, + "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT, + GST_TIME_ARGS (src_value), *dest_value); + } else if (dest_format == GST_FORMAT_TIME && + src_format == GST_FORMAT_BYTES) { + GST_LOG_OBJECT (parse, + "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT, + src_value, GST_TIME_ARGS (*dest_value)); + } else { + GST_LOG_OBJECT (parse, + "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT, + GST_STR_NULL (gst_format_get_name (src_format)), + GST_STR_NULL (gst_format_get_name (dest_format)), + src_value, *dest_value); + } + } else { + GST_DEBUG_OBJECT (parse, "conversion failed"); + } + } +#endif + + return ret; +} + +static gboolean +update_upstream_provided (GQuark field_id, const GValue * value, + gpointer user_data) +{ + GstCaps *default_caps = user_data; + gint i; + gint caps_size; + + caps_size = gst_caps_get_size (default_caps); + for (i = 0; i < caps_size; i++) { + GstStructure *structure = gst_caps_get_structure (default_caps, i); + if (gst_structure_id_has_field (structure, field_id)) + gst_structure_id_set_value (structure, field_id, value); + } + + return TRUE; +} + +static GstCaps * +gst_base_parse_negotiate_default_caps (GstBaseParse * parse) +{ + GstCaps *caps, *templcaps; + GstCaps *sinkcaps = NULL; + GstCaps *default_caps = NULL; + GstStructure *structure; + + templcaps = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)); + caps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), templcaps); + if (caps) + gst_caps_unref (templcaps); + else + caps = templcaps; + templcaps = NULL; + + if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { + goto caps_error; + } + + GST_LOG_OBJECT (parse, "peer caps %" GST_PTR_FORMAT, caps); + + /* before fixating, try to use whatever upstream provided */ + default_caps = gst_caps_copy (caps); + sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); + + GST_LOG_OBJECT (parse, "current caps %" GST_PTR_FORMAT " for sinkpad", + sinkcaps); + + if (sinkcaps) { + structure = gst_caps_get_structure (sinkcaps, 0); + gst_structure_foreach (structure, update_upstream_provided, default_caps); + } + + default_caps = gst_caps_fixate (default_caps); + + if (!default_caps) { + GST_WARNING_OBJECT (parse, "Failed to create default caps !"); + goto caps_error; + } + + GST_INFO_OBJECT (parse, + "Chose default caps %" GST_PTR_FORMAT " for initial gap", default_caps); + + if (sinkcaps) + gst_caps_unref (sinkcaps); + gst_caps_unref (caps); + + return default_caps; + +caps_error: + { + if (caps) + gst_caps_unref (caps); + if (sinkcaps) + gst_caps_unref (sinkcaps); + return NULL; + } +} + +/* gst_base_parse_sink_event: + * @pad: #GstPad that received the event. + * @event: #GstEvent to be handled. + * + * Handler for sink pad events. + * + * Returns: %TRUE if the event was handled. + */ +static gboolean +gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstBaseParse *parse = GST_BASE_PARSE (parent); + GstBaseParseClass *bclass = GST_BASE_PARSE_GET_CLASS (parse); + gboolean ret; + + ret = bclass->sink_event (parse, event); + + return ret; +} + +/* gst_base_parse_sink_event_default: + * @parse: #GstBaseParse. + * @event: #GstEvent to be handled. + * + * Element-level event handler function. + * + * The event will be unreffed only if it has been handled and this + * function returns %TRUE + * + * Returns: %TRUE if the event was handled and not need forwarding. + */ +static gboolean +gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event) +{ + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + gboolean ret = FALSE; + gboolean forward_immediate = FALSE; + + GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event), + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps); + + if (klass->set_sink_caps) + ret = klass->set_sink_caps (parse, caps); + else + ret = TRUE; + + /* will send our own caps downstream */ + gst_event_unref (event); + event = NULL; + break; + } + case GST_EVENT_SEGMENT: + { + const GstSegment *in_segment; + GstSegment out_segment; + gint64 offset = 0, next_dts; + guint32 seqnum = gst_event_get_seqnum (event); + + gst_event_parse_segment (event, &in_segment); + gst_segment_init (&out_segment, GST_FORMAT_TIME); + out_segment.rate = in_segment->rate; + out_segment.applied_rate = in_segment->applied_rate; + + GST_DEBUG_OBJECT (parse, "segment %" GST_SEGMENT_FORMAT, in_segment); + + parse->priv->upstream_format = in_segment->format; + if (in_segment->format == GST_FORMAT_BYTES) { + GstBaseParseSeek *seek = NULL; + GSList *node; + + /* stop time is allowed to be open-ended, but not start & pos */ + offset = in_segment->time; + + GST_OBJECT_LOCK (parse); + for (node = parse->priv->pending_seeks; node; node = node->next) { + GstBaseParseSeek *tmp = node->data; + + if (tmp->offset == offset) { + seek = tmp; + break; + } + } + parse->priv->pending_seeks = + g_slist_remove (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + + if (seek) { + GST_DEBUG_OBJECT (parse, + "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT, + seek->accurate ? " accurate" : "", &seek->segment); + + out_segment.start = seek->segment.start; + out_segment.stop = seek->segment.stop; + out_segment.time = seek->segment.start; + + next_dts = seek->start_ts; + parse->priv->exact_position = seek->accurate; + g_free (seek); + } else { + /* best attempt convert */ + /* as these are only estimates, stop is kept open-ended to avoid + * premature cutting */ + gst_base_parse_convert (parse, GST_FORMAT_BYTES, in_segment->start, + GST_FORMAT_TIME, (gint64 *) & next_dts); + + out_segment.start = next_dts; + out_segment.stop = GST_CLOCK_TIME_NONE; + out_segment.time = next_dts; + + parse->priv->exact_position = (in_segment->start == 0); + } + + gst_event_unref (event); + + event = gst_event_new_segment (&out_segment); + gst_event_set_seqnum (event, seqnum); + + GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. %" + GST_SEGMENT_FORMAT, in_segment); + + } else if (in_segment->format != GST_FORMAT_TIME) { + /* Unknown incoming segment format. Output a default open-ended + * TIME segment */ + gst_event_unref (event); + + out_segment.start = 0; + out_segment.stop = GST_CLOCK_TIME_NONE; + out_segment.time = 0; + + event = gst_event_new_segment (&out_segment); + gst_event_set_seqnum (event, seqnum); + + next_dts = 0; + } else { + /* not considered BYTE seekable if it is talking to us in TIME, + * whatever else it might claim */ + parse->priv->upstream_seekable = FALSE; + next_dts = in_segment->start; + gst_event_copy_segment (event, &out_segment); + } + + memcpy (&parse->segment, &out_segment, sizeof (GstSegment)); + + /* + gst_segment_set_newsegment (&parse->segment, update, rate, + applied_rate, format, start, stop, start); + */ + + ret = TRUE; + + /* save the segment for later, right before we push a new buffer so that + * the caps are fixed and the next linked element can receive + * the segment but finish the current segment */ + GST_DEBUG_OBJECT (parse, "draining current segment"); + if (in_segment->rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_finish_fragment (parse, FALSE); + gst_adapter_clear (parse->priv->adapter); + + parse->priv->offset = offset; + parse->priv->sync_offset = offset; + parse->priv->next_dts = next_dts; + parse->priv->next_pts = GST_CLOCK_TIME_NONE; + parse->priv->last_pts = GST_CLOCK_TIME_NONE; + parse->priv->last_dts = GST_CLOCK_TIME_NONE; + parse->priv->prev_pts = GST_CLOCK_TIME_NONE; + parse->priv->prev_dts = GST_CLOCK_TIME_NONE; + parse->priv->prev_dts_from_pts = FALSE; + parse->priv->discont = TRUE; + parse->priv->seen_keyframe = FALSE; + parse->priv->skip = 0; + break; + } + + case GST_EVENT_SEGMENT_DONE: + /* need to drain now, rather than upon a new segment, + * since that would have SEGMENT_DONE come before potential + * delayed last part of the current segment */ + GST_DEBUG_OBJECT (parse, "draining current segment"); + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_finish_fragment (parse, FALSE); + /* Also forward event immediately, there might be no new data + * coming afterwards that would allow us to forward it later */ + forward_immediate = TRUE; + break; + + case GST_EVENT_FLUSH_START: + GST_OBJECT_LOCK (parse); + parse->priv->flushing = TRUE; + GST_OBJECT_UNLOCK (parse); + break; + + case GST_EVENT_FLUSH_STOP: + gst_adapter_clear (parse->priv->adapter); + gst_base_parse_clear_queues (parse); + parse->priv->flushing = FALSE; + parse->priv->discont = TRUE; + parse->priv->last_pts = GST_CLOCK_TIME_NONE; + parse->priv->last_dts = GST_CLOCK_TIME_NONE; + parse->priv->new_frame = TRUE; + parse->priv->skip = 0; + + forward_immediate = TRUE; + break; + + case GST_EVENT_EOS: + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_finish_fragment (parse, TRUE); + + /* If we STILL have zero frames processed, fire an error */ + if (parse->priv->framecount == 0 && !parse->priv->saw_gaps && + !parse->priv->first_buffer) { + GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, + ("No valid frames found before end of stream"), (NULL)); + } + + if (!parse->priv->saw_gaps + && parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) { + /* We've not posted bitrate tags yet - do so now */ + gst_base_parse_queue_tag_event_update (parse); + } + + /* newsegment and other serialized events before eos */ + gst_base_parse_push_pending_events (parse); + + forward_immediate = TRUE; + break; + case GST_EVENT_CUSTOM_DOWNSTREAM:{ + /* FIXME: Code duplicated from libgstvideo because core can't depend on -base */ +#ifndef GST_VIDEO_EVENT_STILL_STATE_NAME +#define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame" +#endif + + const GstStructure *s; + gboolean ev_still_state; + + s = gst_event_get_structure (event); + if (s != NULL && + gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME) && + gst_structure_get_boolean (s, "still-state", &ev_still_state)) { + if (ev_still_state) { + GST_DEBUG_OBJECT (parse, "draining current data for still-frame"); + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_finish_fragment (parse, TRUE); + } + forward_immediate = TRUE; + } + break; + } + case GST_EVENT_GAP: + { + GST_DEBUG_OBJECT (parse, "draining current data due to gap event"); + + /* Ensure we have caps before forwarding the event */ + if (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (parse))) { + GstCaps *default_caps = NULL; + if ((default_caps = gst_base_parse_negotiate_default_caps (parse))) { + GList *l; + GstEvent *caps_event = gst_event_new_caps (default_caps); + + GST_DEBUG_OBJECT (parse, + "Store caps event to pending list for initial pre-rolling"); + + /* Events are in decreasing order. Go down the list until we + * find the first pre-CAPS event and insert our CAPS event there. + * + * There should be a SEGMENT event already, which is > CAPS */ + for (l = parse->priv->pending_events; l; l = l->next) { + GstEvent *e = l->data; + + if (GST_EVENT_TYPE (e) < GST_EVENT_CAPS) { + parse->priv->pending_events = + g_list_insert_before (parse->priv->pending_events, l, + caps_event); + break; + } + } + /* No pending event that is < CAPS, so we have to add it at the very + * end of the list */ + if (!l) { + parse->priv->pending_events = + g_list_append (parse->priv->pending_events, caps_event); + } + gst_caps_unref (default_caps); + } else { + gst_event_unref (event); + event = NULL; + ret = FALSE; + GST_ELEMENT_ERROR (parse, STREAM, FORMAT, (NULL), + ("Parser output not negotiated before GAP event.")); + break; + } + } + + gst_base_parse_push_pending_events (parse); + + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_finish_fragment (parse, TRUE); + forward_immediate = TRUE; + parse->priv->saw_gaps = TRUE; + break; + } + case GST_EVENT_TAG: + { + GstTagList *tags = NULL; + + gst_event_parse_tag (event, &tags); + + /* We only care about stream tags here, global tags we just forward */ + if (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_STREAM) + break; + + gst_base_parse_set_upstream_tags (parse, tags); + gst_base_parse_queue_tag_event_update (parse); + parse->priv->tags_changed = FALSE; + gst_event_unref (event); + event = NULL; + ret = TRUE; + break; + } + case GST_EVENT_STREAM_START: + { + if (parse->priv->pad_mode != GST_PAD_MODE_PULL) + forward_immediate = TRUE; + + gst_base_parse_set_upstream_tags (parse, NULL); + parse->priv->tags_changed = TRUE; + break; + } + default: + break; + } + + /* Forward non-serialized events and EOS/FLUSH_STOP immediately. + * For EOS this is required because no buffer or serialized event + * will come after EOS and nothing could trigger another + * _finish_frame() call. * + * If the subclass handles sending of EOS manually it can return + * _DROPPED from ::finish() and all other subclasses should have + * decoded/flushed all remaining data before this + * + * For FLUSH_STOP this is required because it is expected + * to be forwarded immediately and no buffers are queued anyway. + */ + if (event) { + if (!GST_EVENT_IS_SERIALIZED (event) || forward_immediate) { + ret = gst_pad_push_event (parse->srcpad, event); + } else { + parse->priv->pending_events = + g_list_prepend (parse->priv->pending_events, event); + ret = TRUE; + } + } + + GST_DEBUG_OBJECT (parse, "event handled"); + + return ret; +} + +static gboolean +gst_base_parse_sink_query_default (GstBaseParse * parse, GstQuery * query) +{ + GstPad *pad; + gboolean res; + + pad = GST_BASE_PARSE_SINK_PAD (parse); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstBaseParseClass *bclass; + + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + if (bclass->get_sink_caps) { + GstCaps *caps, *filter; + + gst_query_parse_caps (query, &filter); + caps = bclass->get_sink_caps (parse, filter); + GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT, + caps); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + + res = TRUE; + } else { + GstCaps *caps, *template_caps, *filter; + + gst_query_parse_caps (query, &filter); + template_caps = gst_pad_get_pad_template_caps (pad); + if (filter != NULL) { + caps = + gst_caps_intersect_full (filter, template_caps, + GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (template_caps); + } else { + caps = template_caps; + } + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + + res = TRUE; + } + break; + } + default: + { + res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query); + break; + } + } + + return res; +} + +static gboolean +gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstBaseParseClass *bclass; + GstBaseParse *parse; + gboolean ret; + + parse = GST_BASE_PARSE (parent); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "%s query", GST_QUERY_TYPE_NAME (query)); + + if (bclass->sink_query) + ret = bclass->sink_query (parse, query); + else + ret = FALSE; + + GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT, + GST_QUERY_TYPE_NAME (query), ret, query); + + return ret; +} + +static gboolean +gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstBaseParseClass *bclass; + GstBaseParse *parse; + gboolean ret; + + parse = GST_BASE_PARSE (parent); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "%s query: %" GST_PTR_FORMAT, + GST_QUERY_TYPE_NAME (query), query); + + if (bclass->src_query) + ret = bclass->src_query (parse, query); + else + ret = FALSE; + + GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT, + GST_QUERY_TYPE_NAME (query), ret, query); + + return ret; +} + +/* gst_base_parse_src_event: + * @pad: #GstPad that received the event. + * @event: #GstEvent that was received. + * + * Handler for source pad events. + * + * Returns: %TRUE if the event was handled. + */ +static gboolean +gst_base_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstBaseParse *parse; + GstBaseParseClass *bclass; + gboolean ret = TRUE; + + parse = GST_BASE_PARSE (parent); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event), + GST_EVENT_TYPE_NAME (event)); + + if (bclass->src_event) + ret = bclass->src_event (parse, event); + else + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_base_parse_is_seekable (GstBaseParse * parse) +{ + /* FIXME: could do more here, e.g. check index or just send data from 0 + * in pull mode and let decoder/sink clip */ + return parse->priv->syncable; +} + +/* gst_base_parse_src_event_default: + * @parse: #GstBaseParse. + * @event: #GstEvent that was received. + * + * Default srcpad event handler. + * + * Returns: %TRUE if the event was handled and can be dropped. + */ +static gboolean +gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event) +{ + gboolean res = FALSE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + if (gst_base_parse_is_seekable (parse)) + res = gst_base_parse_handle_seek (parse, event); + break; + default: + res = gst_pad_event_default (parse->srcpad, GST_OBJECT_CAST (parse), + event); + break; + } + return res; +} + + +/** + * gst_base_parse_convert_default: + * @parse: #GstBaseParse. + * @src_format: #GstFormat describing the source format. + * @src_value: Source value to be converted. + * @dest_format: #GstFormat defining the converted format. + * @dest_value: (out): Pointer where the conversion result will be put. + * + * Default implementation of "convert" vmethod in #GstBaseParse class. + * + * Returns: %TRUE if conversion was successful. + */ +gboolean +gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + gboolean ret = FALSE; + guint64 bytes, duration; + + if (G_UNLIKELY (src_format == dest_format)) { + *dest_value = src_value; + return TRUE; + } + + if (G_UNLIKELY (src_value == -1)) { + *dest_value = -1; + return TRUE; + } + + if (G_UNLIKELY (src_value == 0)) { + *dest_value = 0; + return TRUE; + } + + if (parse->priv->upstream_format != GST_FORMAT_BYTES) { + /* don't do byte format conversions if we're not really parsing + * a raw elementary stream, since we don't really have BYTES + * position / duration info */ + if (src_format == GST_FORMAT_BYTES || dest_format == GST_FORMAT_BYTES) + goto no_slaved_conversions; + } + + /* need at least some frames */ + if (!parse->priv->framecount) + goto no_framecount; + + duration = parse->priv->acc_duration / GST_MSECOND; + bytes = parse->priv->bytecount; + + if (G_UNLIKELY (!duration || !bytes)) + goto no_duration_bytes; + + if (src_format == GST_FORMAT_BYTES) { + if (dest_format == GST_FORMAT_TIME) { + /* BYTES -> TIME conversion */ + GST_DEBUG_OBJECT (parse, "converting bytes -> time"); + *dest_value = gst_util_uint64_scale (src_value, duration, bytes); + *dest_value *= GST_MSECOND; + GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms", + *dest_value / GST_MSECOND); + ret = TRUE; + } else { + GST_DEBUG_OBJECT (parse, "converting bytes -> other not implemented"); + } + } else if (src_format == GST_FORMAT_TIME) { + if (dest_format == GST_FORMAT_BYTES) { + GST_DEBUG_OBJECT (parse, "converting time -> bytes"); + *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes, + duration); + GST_DEBUG_OBJECT (parse, + "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT, + src_value / GST_MSECOND, *dest_value); + ret = TRUE; + } else { + GST_DEBUG_OBJECT (parse, "converting time -> other not implemented"); + } + } else if (src_format == GST_FORMAT_DEFAULT) { + /* DEFAULT == frame-based */ + if (dest_format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (parse, "converting default -> time"); + if (parse->priv->fps_den) { + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * parse->priv->fps_den, parse->priv->fps_num); + ret = TRUE; + } + } else { + GST_DEBUG_OBJECT (parse, "converting default -> other not implemented"); + } + } else { + GST_DEBUG_OBJECT (parse, "conversion not implemented"); + } + return ret; + + /* ERRORS */ +no_framecount: + { + GST_DEBUG_OBJECT (parse, "no framecount"); + return FALSE; + } +no_duration_bytes: + { + GST_DEBUG_OBJECT (parse, "no duration %" G_GUINT64_FORMAT ", bytes %" + G_GUINT64_FORMAT, duration, bytes); + return FALSE; + } +no_slaved_conversions: + { + GST_DEBUG_OBJECT (parse, + "Can't do format conversions when upstream format is not BYTES"); + return FALSE; + } +} + +static void +gst_base_parse_update_duration (GstBaseParse * parse) +{ + gint64 ptot, dest_value; + + if (!gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &ptot)) + return; + + if (!gst_base_parse_convert (parse, GST_FORMAT_BYTES, ptot, + GST_FORMAT_TIME, &dest_value)) + return; + + /* inform if duration changed, but try to avoid spamming */ + parse->priv->estimated_drift += dest_value - parse->priv->estimated_duration; + + parse->priv->estimated_duration = dest_value; + GST_LOG_OBJECT (parse, + "updated estimated duration to %" GST_TIME_FORMAT, + GST_TIME_ARGS (dest_value)); + + if (parse->priv->estimated_drift > GST_SECOND || + parse->priv->estimated_drift < -GST_SECOND) { + gst_element_post_message (GST_ELEMENT (parse), + gst_message_new_duration_changed (GST_OBJECT (parse))); + parse->priv->estimated_drift = 0; + } +} + +/* gst_base_parse_update_bitrates: + * @parse: #GstBaseParse. + * @buffer: Current frame as a #GstBuffer + * + * Keeps track of the minimum and maximum bitrates, and also maintains a + * running average bitrate of the stream so far. + */ +static void +gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + guint64 data_len, frame_dur; + gint overhead; + guint frame_bitrate; + guint64 frame_bitrate64; + GstBuffer *buffer = frame->buffer; + + overhead = frame->overhead; + if (overhead == -1) + return; + + data_len = gst_buffer_get_size (buffer) - overhead; + parse->priv->data_bytecount += data_len; + + /* duration should be valid by now, + * either set by subclass or maybe based on fps settings */ + if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) { + guint64 avg_bitrate; + + /* Calculate duration of a frame from buffer properties */ + frame_dur = GST_BUFFER_DURATION (buffer); + avg_bitrate = gst_util_uint64_scale (GST_SECOND, + 8 * parse->priv->data_bytecount, parse->priv->acc_duration); + + if (avg_bitrate > G_MAXUINT) + return; + + parse->priv->avg_bitrate = avg_bitrate; + } else { + /* No way to figure out frame duration (is this even possible?) */ + return; + } + + /* override if subclass provided bitrate, e.g. metadata based */ + if (parse->priv->bitrate) { + parse->priv->avg_bitrate = parse->priv->bitrate; + /* spread this (confirmed) info ASAP */ + if (parse->priv->post_avg_bitrate && + parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate) + parse->priv->tags_changed = TRUE; + } + + if (!frame_dur) + return; + + frame_bitrate64 = gst_util_uint64_scale (GST_SECOND, 8 * data_len, frame_dur); + + if (frame_bitrate64 > G_MAXUINT) + return; + + frame_bitrate = (guint) frame_bitrate64; + + GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate, + parse->priv->avg_bitrate); + + if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) + return; + + if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE && + (parse->priv->post_min_bitrate || parse->priv->post_avg_bitrate + || parse->priv->post_max_bitrate)) + parse->priv->tags_changed = TRUE; + + if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) { + if (frame_bitrate < parse->priv->min_bitrate) { + parse->priv->min_bitrate = frame_bitrate; + if (parse->priv->post_min_bitrate) + parse->priv->tags_changed = TRUE; + } + + if (frame_bitrate > parse->priv->max_bitrate) { + parse->priv->max_bitrate = frame_bitrate; + if (parse->priv->post_max_bitrate) + parse->priv->tags_changed = TRUE; + } + + /* Only update the tag on a 2% change */ + if (parse->priv->post_avg_bitrate && parse->priv->avg_bitrate) { + guint64 diffprev = gst_util_uint64_scale_int (100, + ABSDIFF (parse->priv->avg_bitrate, parse->priv->posted_avg_bitrate), + parse->priv->avg_bitrate); + if (diffprev >= UPDATE_THRESHOLD) + parse->priv->tags_changed = TRUE; + } + } +} + +/** + * gst_base_parse_add_index_entry: + * @parse: #GstBaseParse. + * @offset: offset of entry + * @ts: timestamp associated with offset + * @key: whether entry refers to keyframe + * @force: add entry disregarding sanity checks + * + * Adds an entry to the index associating @offset to @ts. It is recommended + * to only add keyframe entries. @force allows to bypass checks, such as + * whether the stream is (upstream) seekable, another entry is already "close" + * to the new entry, etc. + * + * Returns: #gboolean indicating whether entry was added + */ +gboolean +gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, + GstClockTime ts, gboolean key, gboolean force) +{ + gboolean ret = FALSE; + GstIndexAssociation associations[2]; + + GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT + " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset); + + if (G_LIKELY (!force)) { + + if (!parse->priv->upstream_seekable) { + GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding"); + goto exit; + } + + /* FIXME need better helper data structure that handles these issues + * related to ongoing collecting of index entries */ + if (parse->priv->index_last_offset + parse->priv->idx_byte_interval >= + (gint64) offset) { + GST_LOG_OBJECT (parse, + "already have entries up to offset 0x%08" G_GINT64_MODIFIER "x", + parse->priv->index_last_offset + parse->priv->idx_byte_interval); + goto exit; + } + + if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) && + GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < + parse->priv->idx_interval) { + GST_LOG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->priv->index_last_ts)); + goto exit; + } + + /* if last is not really the last one */ + if (!parse->priv->index_last_valid) { + GstClockTime prev_ts; + + gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts); + if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) { + GST_LOG_OBJECT (parse, + "entry too close to existing entry %" GST_TIME_FORMAT, + GST_TIME_ARGS (prev_ts)); + parse->priv->index_last_offset = offset; + parse->priv->index_last_ts = ts; + goto exit; + } + } + } + + associations[0].format = GST_FORMAT_TIME; + associations[0].value = ts; + associations[1].format = GST_FORMAT_BYTES; + associations[1].value = offset; + + /* index might change on-the-fly, although that would be nutty app ... */ + GST_BASE_PARSE_INDEX_LOCK (parse); + gst_index_add_associationv (parse->priv->index, parse->priv->index_id, + (key) ? GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT : + GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT, 2, + (const GstIndexAssociation *) &associations); + GST_BASE_PARSE_INDEX_UNLOCK (parse); + + if (key) { + parse->priv->index_last_offset = offset; + parse->priv->index_last_ts = ts; + } + + ret = TRUE; + +exit: + return ret; +} + +/* check for seekable upstream, above and beyond a mere query */ +static void +gst_base_parse_check_seekability (GstBaseParse * parse) +{ + GstQuery *query; + gboolean seekable = FALSE; + gint64 start = -1, stop = -1; + guint idx_interval = 0; + guint64 idx_byte_interval = 0; + + query = gst_query_new_seeking (GST_FORMAT_BYTES); + if (!gst_pad_peer_query (parse->sinkpad, query)) { + GST_DEBUG_OBJECT (parse, "seeking query failed"); + goto done; + } + + gst_query_parse_seeking (query, NULL, &seekable, &start, &stop); + + /* try harder to query upstream size if we didn't get it the first time */ + if (seekable && stop == -1) { + GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop"); + gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &stop); + } + + /* if upstream doesn't know the size, it's likely that it's not seekable in + * practice even if it technically may be seekable */ + if (seekable && (start != 0 || stop <= start)) { + GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable"); + seekable = FALSE; + } + + /* let's not put every single frame into our index */ + if (seekable) { + if (stop < 10 * 1024 * 1024) + idx_interval = 100; + else if (stop < 100 * 1024 * 1024) + idx_interval = 500; + else + idx_interval = 1000; + + /* ensure that even for large files (e.g. very long audio files), the index + * stays reasonably-size, with some arbitrary limit to the total number of + * index entries */ + idx_byte_interval = (stop - start) / MAX_INDEX_ENTRIES; + GST_DEBUG_OBJECT (parse, + "Limiting index entries to %d, indexing byte interval %" + G_GUINT64_FORMAT " bytes", MAX_INDEX_ENTRIES, idx_byte_interval); + } + +done: + gst_query_unref (query); + + GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %" + G_GUINT64_FORMAT ")", seekable, start, stop); + parse->priv->upstream_seekable = seekable; + parse->priv->upstream_size = seekable ? stop : 0; + + GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval); + parse->priv->idx_interval = idx_interval * GST_MSECOND; + parse->priv->idx_byte_interval = idx_byte_interval; +} + +/* some misc checks on upstream */ +static void +gst_base_parse_check_upstream (GstBaseParse * parse) +{ + gint64 stop; + + if (gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_TIME, &stop)) + if (GST_CLOCK_TIME_IS_VALID (stop) && stop) { + /* upstream has one, accept it also, and no further updates */ + gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0); + parse->priv->upstream_has_duration = TRUE; + } + + GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d", + parse->priv->upstream_has_duration); +} + +/* checks src caps to determine if dealing with audio or video */ +/* TODO maybe forego automagic stuff and let subclass configure it ? */ +static void +gst_base_parse_check_media (GstBaseParse * parse) +{ + GstCaps *caps; + GstStructure *s; + + caps = gst_pad_get_current_caps (parse->srcpad); + if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) { + parse->priv->is_video = + g_str_has_prefix (gst_structure_get_name (s), "video"); + } else { + /* historical default */ + parse->priv->is_video = FALSE; + } + if (caps) + gst_caps_unref (caps); + + parse->priv->checked_media = TRUE; + GST_DEBUG_OBJECT (parse, "media is video: %d", parse->priv->is_video); +} + +/* takes ownership of frame */ +static void +gst_base_parse_queue_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) { + /* frame allocated on the heap, we can just take ownership */ + g_queue_push_tail (&parse->priv->queued_frames, frame); + GST_TRACE ("queued frame %p", frame); + } else { + GstBaseParseFrame *copy; + + /* probably allocated on the stack, must make a proper copy */ + copy = gst_base_parse_frame_copy (frame); + g_queue_push_tail (&parse->priv->queued_frames, copy); + GST_TRACE ("queued frame %p (copy of %p)", copy, frame); + gst_base_parse_frame_free (frame); + } +} + +/* makes sure that @buf is properly prepared and decorated for passing + * to baseclass, and an equally setup frame is returned setup with @buf. + * Takes ownership of @buf. */ +static GstBaseParseFrame * +gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer) +{ + GstBaseParseFrame *frame = NULL; + + buffer = gst_buffer_make_writable (buffer); + + GST_LOG_OBJECT (parse, + "preparing frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x) of size %" G_GSIZE_FORMAT, + GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer), + gst_buffer_get_size (buffer)); + + GST_BUFFER_OFFSET (buffer) = parse->priv->offset; + + gst_base_parse_update_flags (parse); + + frame = gst_base_parse_frame_new (buffer, 0, 0); + gst_buffer_unref (buffer); + gst_base_parse_update_frame (parse, frame); + + /* clear flags for next frame */ + parse->priv->discont = FALSE; + parse->priv->new_frame = FALSE; + + /* use default handler to provide initial (upstream) metadata */ + gst_base_parse_parse_frame (parse, frame); + + return frame; +} + +/* Wraps buffer in a frame and dispatches to subclass. + * Also manages data skipping and offset handling (including adapter flushing). + * Takes ownership of @buffer */ +static GstFlowReturn +gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer, + gint * skip, gint * flushed) +{ + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + GstBaseParseFrame *frame; + GstFlowReturn ret; + + g_return_val_if_fail (skip != NULL || flushed != NULL, GST_FLOW_ERROR); + + GST_LOG_OBJECT (parse, + "handling buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT + ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, + gst_buffer_get_size (buffer), GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + /* track what is being flushed during this single round of frame processing */ + parse->priv->flushed = 0; + *skip = 0; + + /* make it easy for _finish_frame to pick up input data */ + if (parse->priv->pad_mode == GST_PAD_MODE_PULL) { + gst_buffer_ref (buffer); + gst_adapter_push (parse->priv->adapter, buffer); + } + + frame = gst_base_parse_prepare_frame (parse, buffer); + ret = klass->handle_frame (parse, frame, skip); + + *flushed = parse->priv->flushed; + + GST_LOG_OBJECT (parse, "handle_frame skipped %d, flushed %d", + *skip, *flushed); + + /* subclass can only do one of these, or semantics are too unclear */ + g_assert (*skip == 0 || *flushed == 0); + + /* track skipping */ + if (*skip > 0) { + GstClockTime pts, dts; + GstBuffer *outbuf; + + GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", *skip); + if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) { + /* reverse playback, and no frames found yet, so we are skipping + * the leading part of a fragment, which may form the tail of + * fragment coming later, hopefully subclass skips efficiently ... */ + pts = gst_adapter_prev_pts (parse->priv->adapter, NULL); + dts = gst_adapter_prev_dts (parse->priv->adapter, NULL); + outbuf = gst_adapter_take_buffer (parse->priv->adapter, *skip); + outbuf = gst_buffer_make_writable (outbuf); + GST_BUFFER_PTS (outbuf) = pts; + GST_BUFFER_DTS (outbuf) = dts; + parse->priv->buffers_head = + g_slist_prepend (parse->priv->buffers_head, outbuf); + outbuf = NULL; + } else { + /* If we're asked to skip more than is available in the adapter, + we need to remember what we need to skip for next iteration */ + gsize av = gst_adapter_available (parse->priv->adapter); + GST_DEBUG ("Asked to skip %u (%" G_GSIZE_FORMAT " available)", *skip, av); + if (av >= *skip) { + gst_adapter_flush (parse->priv->adapter, *skip); + } else { + GST_DEBUG + ("This is more than available, flushing %" G_GSIZE_FORMAT + ", storing %u to skip", av, (guint) (*skip - av)); + parse->priv->skip = *skip - av; + gst_adapter_flush (parse->priv->adapter, av); + *skip = av; + } + } + if (!parse->priv->discont) + parse->priv->sync_offset = parse->priv->offset; + parse->priv->offset += *skip; + parse->priv->discont = TRUE; + /* check for indefinite skipping */ + if (ret == GST_FLOW_OK) + ret = gst_base_parse_check_sync (parse); + } + + parse->priv->offset += *flushed; + + if (parse->priv->pad_mode == GST_PAD_MODE_PULL) { + gst_adapter_clear (parse->priv->adapter); + } + + if (*skip == 0 && *flushed == 0) { + /* Carry over discont if we need more data */ + if (GST_BUFFER_IS_DISCONT (frame->buffer)) + parse->priv->discont = TRUE; + } + + gst_base_parse_frame_free (frame); + + return ret; +} + +/* gst_base_parse_push_pending_events: + * @parse: #GstBaseParse + * + * Pushes the pending events + */ +static void +gst_base_parse_push_pending_events (GstBaseParse * parse) +{ + if (G_UNLIKELY (parse->priv->pending_events)) { + GList *r = g_list_reverse (parse->priv->pending_events); + GList *l; + + parse->priv->pending_events = NULL; + for (l = r; l != NULL; l = l->next) { + gst_pad_push_event (parse->srcpad, GST_EVENT_CAST (l->data)); + } + g_list_free (r); + } +} + +/* gst_base_parse_handle_and_push_frame: + * @parse: #GstBaseParse. + * @klass: #GstBaseParseClass. + * @frame: (transfer full): a #GstBaseParseFrame + * + * Parses the frame from given buffer and pushes it forward. Also performs + * timestamp handling and checks the segment limits. + * + * This is called with srcpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +static GstFlowReturn +gst_base_parse_handle_and_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame) +{ + gint64 offset; + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; + offset = frame->offset; + + /* check if subclass/format can provide ts. + * If so, that allows and enables extra seek and duration determining options */ + if (G_UNLIKELY (parse->priv->first_frame_offset < 0)) { + if (GST_BUFFER_PTS_IS_VALID (buffer) && parse->priv->has_timing_info + && parse->priv->pad_mode == GST_PAD_MODE_PULL) { + parse->priv->first_frame_offset = offset; + parse->priv->first_frame_pts = GST_BUFFER_PTS (buffer); + parse->priv->first_frame_dts = GST_BUFFER_DTS (buffer); + GST_DEBUG_OBJECT (parse, "subclass provided dts %" GST_TIME_FORMAT + ", pts %" GST_TIME_FORMAT " for first frame at offset %" + G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->first_frame_dts), + GST_TIME_ARGS (parse->priv->first_frame_pts), + parse->priv->first_frame_offset); + if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) { + gint64 off; + GstClockTime last_ts = G_MAXINT64; + + GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine"); + gst_base_parse_locate_time (parse, &last_ts, &off); + if (GST_CLOCK_TIME_IS_VALID (last_ts)) + gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0); + } + } else { + /* disable further checks */ + parse->priv->first_frame_offset = 0; + } + } + + /* track upstream time if provided, not subclass' internal notion of it */ + if (parse->priv->upstream_format == GST_FORMAT_TIME) { + GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DTS (frame->buffer) = GST_CLOCK_TIME_NONE; + } + + /* interpolating and no valid pts yet, + * start with dts and carry on from there */ + if (parse->priv->infer_ts && parse->priv->pts_interpolate + && !GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts)) + parse->priv->next_pts = parse->priv->next_dts; + + /* again use default handler to add missing metadata; + * we may have new information on frame properties */ + gst_base_parse_parse_frame (parse, frame); + + parse->priv->next_pts = GST_CLOCK_TIME_NONE; + if (GST_BUFFER_DTS_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) { + parse->priv->next_dts = + GST_BUFFER_DTS (buffer) + GST_BUFFER_DURATION (buffer); + if (parse->priv->pts_interpolate && GST_BUFFER_PTS_IS_VALID (buffer)) { + GstClockTime next_pts = + GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer); + if (next_pts >= parse->priv->next_dts) + parse->priv->next_pts = next_pts; + } + } else { + /* we lost track, do not produce bogus time next time around + * (probably means parser subclass has given up on parsing as well) */ + GST_DEBUG_OBJECT (parse, "no next fallback timestamp"); + parse->priv->next_dts = GST_CLOCK_TIME_NONE; + } + + if (parse->priv->upstream_seekable && parse->priv->exact_position && + GST_BUFFER_PTS_IS_VALID (buffer)) + gst_base_parse_add_index_entry (parse, offset, + GST_BUFFER_PTS (buffer), + !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE); + + /* All OK, push queued frames if there are any */ + if (G_UNLIKELY (!g_queue_is_empty (&parse->priv->queued_frames))) { + GstBaseParseFrame *queued_frame; + + while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) { + gst_base_parse_push_frame (parse, queued_frame); + gst_base_parse_frame_free (queued_frame); + } + } + + return gst_base_parse_push_frame (parse, frame); +} + +/** + * gst_base_parse_push_frame: + * @parse: #GstBaseParse. + * @frame: (transfer none): a #GstBaseParseFrame + * + * Pushes the frame's buffer downstream, sends any pending events and + * does some timestamp and segment handling. Takes ownership of + * frame's buffer, though caller retains ownership of @frame. + * + * This must be called with sinkpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +GstFlowReturn +gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime last_start = GST_CLOCK_TIME_NONE; + GstClockTime last_stop = GST_CLOCK_TIME_NONE; + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + GstBuffer *buffer; + gsize size; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + + GST_TRACE_OBJECT (parse, "pushing frame %p", frame); + + buffer = frame->buffer; + + GST_LOG_OBJECT (parse, + "processing buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT + ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, + gst_buffer_get_size (buffer), + GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + /* update stats */ + parse->priv->bytecount += frame->size; + if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) { + parse->priv->framecount++; + if (GST_BUFFER_DURATION_IS_VALID (buffer)) { + parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); + } + } + /* 0 means disabled */ + if (parse->priv->update_interval < 0) + parse->priv->update_interval = 50; + else if (parse->priv->update_interval > 0 && + (parse->priv->framecount % parse->priv->update_interval) == 0) + gst_base_parse_update_duration (parse); + + if (GST_BUFFER_PTS_IS_VALID (buffer)) + last_start = last_stop = GST_BUFFER_PTS (buffer); + if (last_start != GST_CLOCK_TIME_NONE + && GST_BUFFER_DURATION_IS_VALID (buffer)) + last_stop = last_start + GST_BUFFER_DURATION (buffer); + + /* should have caps by now */ + if (!gst_pad_has_current_caps (parse->srcpad)) + goto no_caps; + + if (G_UNLIKELY (!parse->priv->checked_media)) { + /* have caps; check identity */ + gst_base_parse_check_media (parse); + } + + if (parse->priv->tags_changed) { + gst_base_parse_queue_tag_event_update (parse); + parse->priv->tags_changed = FALSE; + } + + /* Push pending events, including SEGMENT events */ + gst_base_parse_push_pending_events (parse); + + /* segment adjustment magic; only if we are running the whole show */ + if (!parse->priv->passthrough && parse->segment.rate > 0.0 && + (parse->priv->pad_mode == GST_PAD_MODE_PULL || + parse->priv->upstream_seekable)) { + /* handle gaps */ + if (GST_CLOCK_TIME_IS_VALID (parse->segment.position) && + GST_CLOCK_TIME_IS_VALID (last_start)) { + GstClockTimeDiff diff; + + /* only send newsegments with increasing start times, + * otherwise if these go back and forth downstream (sinks) increase + * accumulated time and running_time */ + diff = GST_CLOCK_DIFF (parse->segment.position, last_start); + if (G_UNLIKELY (diff > 2 * GST_SECOND + && last_start > parse->segment.start + && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) + || last_start < parse->segment.stop))) { + + GST_DEBUG_OBJECT (parse, + "Gap of %" G_GINT64_FORMAT " ns detected in stream " "(%" + GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). " + "Sending updated SEGMENT events", diff, + GST_TIME_ARGS (parse->segment.position), + GST_TIME_ARGS (last_start)); + + /* skip gap FIXME */ + gst_pad_push_event (parse->srcpad, + gst_event_new_segment (&parse->segment)); + + parse->segment.position = last_start; + } + } + } + + /* update bitrates and optionally post corresponding tags + * (following newsegment) */ + gst_base_parse_update_bitrates (parse, frame); + + if (klass->pre_push_frame) { + ret = klass->pre_push_frame (parse, frame); + } else { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + } + + /* Push pending events, if there are any new ones + * like tags added by pre_push_frame */ + if (parse->priv->tags_changed) { + gst_base_parse_queue_tag_event_update (parse); + parse->priv->tags_changed = FALSE; + } + gst_base_parse_push_pending_events (parse); + + /* take final ownership of frame buffer */ + if (frame->out_buffer) { + buffer = frame->out_buffer; + frame->out_buffer = NULL; + gst_buffer_replace (&frame->buffer, NULL); + } else { + buffer = frame->buffer; + frame->buffer = NULL; + } + + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + size = gst_buffer_get_size (buffer); + + parse->priv->seen_keyframe |= parse->priv->is_video && + !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && + GST_BUFFER_TIMESTAMP (buffer) > + parse->segment.stop + parse->priv->lead_out_ts) { + GST_LOG_OBJECT (parse, "Dropped frame, after segment"); + ret = GST_FLOW_EOS; + } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.start) && + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + + parse->priv->lead_in_ts < parse->segment.start) { + if (parse->priv->seen_keyframe) { + GST_LOG_OBJECT (parse, "Frame before segment, after keyframe"); + ret = GST_FLOW_OK; + } else { + GST_LOG_OBJECT (parse, "Dropped frame, before segment"); + ret = GST_BASE_PARSE_FLOW_DROPPED; + } + } else { + ret = GST_FLOW_OK; + } + } + + if (ret == GST_BASE_PARSE_FLOW_DROPPED) { + GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) dropped", size); + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) + parse->priv->discont = TRUE; + gst_buffer_unref (buffer); + ret = GST_FLOW_OK; + } else if (ret == GST_FLOW_OK) { + if (parse->segment.rate > 0.0) { + GST_LOG_OBJECT (parse, "pushing frame (%" G_GSIZE_FORMAT " bytes) now..", + size); + ret = gst_pad_push (parse->srcpad, buffer); + GST_LOG_OBJECT (parse, "frame pushed, flow %s", gst_flow_get_name (ret)); + } else if (!parse->priv->disable_passthrough && parse->priv->passthrough) { + + /* in backwards playback mode, if on passthrough we need to push buffers + * directly without accumulating them into the buffers_queued as baseparse + * will never check for a DISCONT while on passthrough and those buffers + * will never be pushed. + * + * also, as we are on reverse playback, it might be possible that + * passthrough might have just been enabled, so make sure to drain the + * buffers_queued list */ + if (G_UNLIKELY (parse->priv->buffers_queued != NULL)) { + gst_base_parse_finish_fragment (parse, TRUE); + ret = gst_base_parse_send_buffers (parse); + } + + if (ret == GST_FLOW_OK) { + GST_LOG_OBJECT (parse, + "pushing frame (%" G_GSIZE_FORMAT " bytes) now..", size); + ret = gst_pad_push (parse->srcpad, buffer); + GST_LOG_OBJECT (parse, "frame pushed, flow %s", + gst_flow_get_name (ret)); + } else { + GST_LOG_OBJECT (parse, + "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s", size, + gst_flow_get_name (ret)); + gst_buffer_unref (buffer); + } + + } else { + GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) queued for now", + size); + parse->priv->buffers_queued = + g_slist_prepend (parse->priv->buffers_queued, buffer); + ret = GST_FLOW_OK; + } + } else { + GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s", + size, gst_flow_get_name (ret)); + gst_buffer_unref (buffer); + /* if we are not sufficiently in control, let upstream decide on EOS */ + if (ret == GST_FLOW_EOS && !parse->priv->disable_passthrough && + (parse->priv->passthrough || + (parse->priv->pad_mode == GST_PAD_MODE_PUSH && + !parse->priv->upstream_seekable))) + ret = GST_FLOW_OK; + } + + /* Update current running segment position */ + if ((ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) + && last_stop != GST_CLOCK_TIME_NONE + && parse->segment.position < last_stop) + parse->segment.position = last_stop; + + return ret; + + /* ERRORS */ +no_caps: + { + if (GST_PAD_IS_FLUSHING (parse->srcpad)) + return GST_FLOW_FLUSHING; + + GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("No caps set"), (NULL)); + return GST_FLOW_ERROR; + } +} + +/** + * gst_base_parse_finish_frame: + * @parse: a #GstBaseParse + * @frame: a #GstBaseParseFrame + * @size: consumed input data represented by frame + * + * Collects parsed data and pushes this downstream. + * Source pad caps must be set when this is called. + * + * If @frame's out_buffer is set, that will be used as subsequent frame data. + * Otherwise, @size samples will be taken from the input and used for output, + * and the output's metadata (timestamps etc) will be taken as (optionally) + * set by the subclass on @frame's (input) buffer (which is otherwise + * ignored for any but the above purpose/information). + * + * Note that the latter buffer is invalidated by this call, whereas the + * caller retains ownership of @frame. + * + * Returns: a #GstFlowReturn that should be escalated to caller (of caller) + */ +GstFlowReturn +gst_base_parse_finish_frame (GstBaseParse * parse, GstBaseParseFrame * frame, + gint size) +{ + GstFlowReturn ret = GST_FLOW_OK; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (size > 0 || frame->out_buffer, GST_FLOW_ERROR); + g_return_val_if_fail (gst_adapter_available (parse->priv->adapter) >= size, + GST_FLOW_ERROR); + + GST_LOG_OBJECT (parse, "finished frame at offset %" G_GUINT64_FORMAT ", " + "flushing size %d", frame->offset, size); + + /* some one-time start-up */ + if (G_UNLIKELY (parse->priv->framecount == 0)) { + gst_base_parse_check_seekability (parse); + gst_base_parse_check_upstream (parse); + } + + parse->priv->flushed += size; + + if (parse->priv->scanning && frame->buffer) { + if (!parse->priv->scanned_frame) { + parse->priv->scanned_frame = gst_base_parse_frame_copy (frame); + } + goto exit; + } + + /* either PUSH or PULL mode arranges for adapter data */ + /* ensure output buffer */ + if (!frame->out_buffer) { + GstBuffer *src, *dest; + + frame->out_buffer = gst_adapter_take_buffer (parse->priv->adapter, size); + dest = frame->out_buffer; + src = frame->buffer; + GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src); + GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src); + GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src); + GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src); + GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src); + GST_MINI_OBJECT_FLAGS (dest) = GST_MINI_OBJECT_FLAGS (src); + } else { + gst_adapter_flush (parse->priv->adapter, size); + } + + /* use as input for subsequent processing */ + gst_buffer_replace (&frame->buffer, frame->out_buffer); + gst_buffer_unref (frame->out_buffer); + frame->out_buffer = NULL; + + /* mark input size consumed */ + frame->size = size; + + /* subclass might queue frames/data internally if it needs more + * frames to decide on the format, or might request us to queue here. */ + if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_DROP) { + gst_buffer_replace (&frame->buffer, NULL); + goto exit; + } else if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_QUEUE) { + GstBaseParseFrame *copy; + + copy = gst_base_parse_frame_copy (frame); + copy->flags &= ~GST_BASE_PARSE_FRAME_FLAG_QUEUE; + gst_base_parse_queue_frame (parse, copy); + goto exit; + } + + ret = gst_base_parse_handle_and_push_frame (parse, frame); + +exit: + return ret; +} + +/** + * gst_base_parse_drain: + * @parse: a #GstBaseParse + * + * Drains the adapter until it is empty. It decreases the min_frame_size to + * match the current adapter size and calls chain method until the adapter + * is emptied or chain returns with error. + * + * Since: 1.12 + */ +void +gst_base_parse_drain (GstBaseParse * parse) +{ + guint avail; + + GST_DEBUG_OBJECT (parse, "draining"); + parse->priv->drain = TRUE; + + for (;;) { + avail = gst_adapter_available (parse->priv->adapter); + if (!avail) + break; + + if (gst_base_parse_chain (parse->sinkpad, GST_OBJECT_CAST (parse), + NULL) != GST_FLOW_OK) { + break; + } + + /* nothing changed, maybe due to truncated frame; break infinite loop */ + if (avail == gst_adapter_available (parse->priv->adapter)) { + GST_DEBUG_OBJECT (parse, "no change during draining; flushing"); + gst_adapter_clear (parse->priv->adapter); + } + } + + parse->priv->drain = FALSE; +} + +/* gst_base_parse_send_buffers + * + * Sends buffers collected in send_buffers downstream, and ensures that list + * is empty at the end (errors or not). + */ +static GstFlowReturn +gst_base_parse_send_buffers (GstBaseParse * parse) +{ + GSList *send = NULL; + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + gboolean first = TRUE; + + send = parse->priv->buffers_send; + + /* send buffers */ + while (send) { + buf = GST_BUFFER_CAST (send->data); + GST_LOG_OBJECT (parse, "pushing buffer %p, dts %" + GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_DTS (buf)), + GST_TIME_ARGS (GST_BUFFER_PTS (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); + + /* Make sure the first buffer is always DISCONT. If we split + * GOPs inside the parser this is otherwise not guaranteed */ + if (first) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + first = FALSE; + } else { + /* likewise, subsequent buffers should never have DISCONT + * according to the "reverse fragment protocol", or such would + * confuse a downstream decoder + * (could be DISCONT due to aggregating upstream fragments by parsing) */ + GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); + } + + /* iterate output queue an push downstream */ + ret = gst_pad_push (parse->srcpad, buf); + send = g_slist_delete_link (send, send); + + /* clear any leftover if error */ + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + while (send) { + buf = GST_BUFFER_CAST (send->data); + gst_buffer_unref (buf); + send = g_slist_delete_link (send, send); + } + } + } + + parse->priv->buffers_send = send; + + return ret; +} + +/* gst_base_parse_start_fragment: + * + * Prepares for processing a reverse playback (forward) fragment + * by (re)setting proper state variables. + */ +static GstFlowReturn +gst_base_parse_start_fragment (GstBaseParse * parse) +{ + GST_LOG_OBJECT (parse, "starting fragment"); + + /* invalidate so no fall-back timestamping is performed; + * ok if taken from subclass or upstream */ + parse->priv->next_pts = GST_CLOCK_TIME_NONE; + parse->priv->prev_pts = GST_CLOCK_TIME_NONE; + parse->priv->next_dts = GST_CLOCK_TIME_NONE; + parse->priv->prev_dts = GST_CLOCK_TIME_NONE; + parse->priv->prev_dts_from_pts = FALSE; + /* prevent it hanging around stop all the time */ + parse->segment.position = GST_CLOCK_TIME_NONE; + /* mark next run */ + parse->priv->discont = TRUE; + + /* head of previous fragment is now pending tail of current fragment */ + parse->priv->buffers_pending = parse->priv->buffers_head; + parse->priv->buffers_head = NULL; + + return GST_FLOW_OK; +} + + +/* gst_base_parse_finish_fragment: + * + * Processes a reverse playback (forward) fragment: + * - append head of last fragment that was skipped to current fragment data + * - drain the resulting current fragment data (i.e. repeated chain) + * - add time/duration (if needed) to frames queued by chain + * - push queued data + */ +static GstFlowReturn +gst_base_parse_finish_fragment (GstBaseParse * parse, gboolean prev_head) +{ + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + gboolean seen_key = FALSE, seen_delta = FALSE; + + GST_LOG_OBJECT (parse, "finishing fragment"); + + /* restore order */ + parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending); + while (parse->priv->buffers_pending) { + buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data); + if (prev_head) { + GST_LOG_OBJECT (parse, "adding pending buffer (size %" G_GSIZE_FORMAT ")", + gst_buffer_get_size (buf)); + gst_adapter_push (parse->priv->adapter, buf); + } else { + GST_LOG_OBJECT (parse, "discarding head buffer"); + gst_buffer_unref (buf); + } + parse->priv->buffers_pending = + g_slist_delete_link (parse->priv->buffers_pending, + parse->priv->buffers_pending); + } + + /* chain looks for frames and queues resulting ones (in stead of pushing) */ + /* initial skipped data is added to buffers_pending */ + gst_base_parse_drain (parse); + + if (parse->priv->buffers_send) { + buf = GST_BUFFER_CAST (parse->priv->buffers_send->data); + seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } + + /* add metadata (if needed to queued buffers */ + GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->priv->last_pts)); + while (parse->priv->buffers_queued) { + buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data); + + /* no touching if upstream or parsing provided time */ + if (GST_BUFFER_PTS_IS_VALID (buf)) { + GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } else if (GST_BUFFER_DURATION_IS_VALID (buf)) { + if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_pts)) { + if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_pts)) + parse->priv->last_pts -= GST_BUFFER_DURATION (buf); + else + parse->priv->last_pts = 0; + GST_BUFFER_PTS (buf) = parse->priv->last_pts; + GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } + if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_dts)) { + if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_dts)) + parse->priv->last_dts -= GST_BUFFER_DURATION (buf); + else + parse->priv->last_dts = 0; + GST_BUFFER_DTS (buf) = parse->priv->last_dts; + GST_LOG_OBJECT (parse, "applied dts %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DTS (buf))); + } + } else { + /* no idea, very bad */ + GST_WARNING_OBJECT (parse, "could not determine time for buffer"); + } + + parse->priv->last_pts = GST_BUFFER_PTS (buf); + parse->priv->last_dts = GST_BUFFER_DTS (buf); + + /* reverse order for ascending sending */ + /* send downstream at keyframe not preceded by a keyframe + * (e.g. that should identify start of collection of IDR nals) */ + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { + if (seen_key) { + ret = gst_base_parse_send_buffers (parse); + /* if a problem, throw all to sending */ + if (ret != GST_FLOW_OK) { + parse->priv->buffers_send = + g_slist_reverse (parse->priv->buffers_queued); + parse->priv->buffers_queued = NULL; + break; + } + seen_key = FALSE; + } + seen_delta = TRUE; + } else { + seen_key = TRUE; + } + + parse->priv->buffers_send = + g_slist_prepend (parse->priv->buffers_send, buf); + parse->priv->buffers_queued = + g_slist_delete_link (parse->priv->buffers_queued, + parse->priv->buffers_queued); + } + + /* audio may have all marked as keyframe, so arrange to send here. Also + * we might have ended the loop above on a keyframe, in which case we + * should */ + if (!seen_delta || seen_key) + ret = gst_base_parse_send_buffers (parse); + + /* any trailing unused no longer usable (ideally none) */ + if (G_UNLIKELY (gst_adapter_available (parse->priv->adapter))) { + GST_DEBUG_OBJECT (parse, "discarding %" G_GSIZE_FORMAT " trailing bytes", + gst_adapter_available (parse->priv->adapter)); + gst_adapter_clear (parse->priv->adapter); + } + + return ret; +} + +/* small helper that checks whether we have been trying to resync too long */ +static inline GstFlowReturn +gst_base_parse_check_sync (GstBaseParse * parse) +{ + if (G_UNLIKELY (parse->priv->discont && + parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) { + GST_ELEMENT_ERROR (parse, STREAM, DECODE, + ("Failed to parse stream"), (NULL)); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_base_parse_process_streamheader (GstBaseParse * parse) +{ + GstCaps *caps; + GstStructure *str; + const GValue *value; + GstFlowReturn ret = GST_FLOW_OK; + + caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); + if (caps == NULL) + goto notfound; + + str = gst_caps_get_structure (caps, 0); + value = gst_structure_get_value (str, "streamheader"); + if (value == NULL) + goto notfound; + + GST_DEBUG_OBJECT (parse, "Found streamheader field on input caps"); + + if (GST_VALUE_HOLDS_ARRAY (value)) { + gint i; + gsize len = gst_value_array_get_size (value); + + for (i = 0; i < len; i++) { + GstBuffer *buffer = + gst_value_get_buffer (gst_value_array_get_value (value, i)); + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + GST_OBJECT_CAST (parse), gst_buffer_ref (buffer)); + } + + } else if (GST_VALUE_HOLDS_BUFFER (value)) { + GstBuffer *buffer = gst_value_get_buffer (value); + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + GST_OBJECT_CAST (parse), gst_buffer_ref (buffer)); + } + + gst_caps_unref (caps); + + return ret; + +notfound: + { + if (caps) { + gst_caps_unref (caps); + } + + GST_DEBUG_OBJECT (parse, "No streamheader on caps"); + return GST_FLOW_OK; + } +} + +static GstFlowReturn +gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstBaseParseClass *bclass; + GstBaseParse *parse; + GstFlowReturn ret = GST_FLOW_OK; + GstFlowReturn old_ret = GST_FLOW_OK; + GstBuffer *tmpbuf = NULL; + guint fsize = 1; + gint skip = -1; + guint min_size, av; + GstClockTime pts, dts; + + parse = GST_BASE_PARSE (parent); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + GST_DEBUG_OBJECT (parent, "chain"); + + /* early out for speed, if we need to skip */ + if (buffer && GST_BUFFER_IS_DISCONT (buffer)) + parse->priv->skip = 0; + if (parse->priv->skip > 0) { + gsize bsize = gst_buffer_get_size (buffer); + GST_DEBUG ("Got %" G_GSIZE_FORMAT " buffer, need to skip %u", bsize, + parse->priv->skip); + if (parse->priv->skip >= bsize) { + parse->priv->skip -= bsize; + GST_DEBUG ("All the buffer is skipped"); + parse->priv->offset += bsize; + parse->priv->sync_offset = parse->priv->offset; + return GST_FLOW_OK; + } + buffer = gst_buffer_make_writable (buffer); + gst_buffer_resize (buffer, parse->priv->skip, bsize - parse->priv->skip); + parse->priv->offset += parse->priv->skip; + GST_DEBUG ("Done skipping, we have %u left on this buffer", + (unsigned) (bsize - parse->priv->skip)); + parse->priv->skip = 0; + parse->priv->discont = TRUE; + } + + if (G_UNLIKELY (parse->priv->first_buffer)) { + parse->priv->first_buffer = FALSE; + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) { + /* this stream has no header buffers, check if we just prepend the + * streamheader from caps to the stream */ + GST_DEBUG_OBJECT (parse, "Looking for streamheader field on caps to " + "prepend to the stream"); + gst_base_parse_process_streamheader (parse); + } else { + GST_DEBUG_OBJECT (parse, "Stream has header buffers, not prepending " + "streamheader from caps"); + } + } + + if (parse->priv->detecting) { + GstBuffer *detect_buf; + + if (parse->priv->detect_buffers_size == 0) { + detect_buf = gst_buffer_ref (buffer); + } else { + GList *l; + guint offset = 0; + + detect_buf = gst_buffer_new (); + + for (l = parse->priv->detect_buffers; l; l = l->next) { + gsize tmpsize = gst_buffer_get_size (l->data); + + gst_buffer_copy_into (detect_buf, GST_BUFFER_CAST (l->data), + GST_BUFFER_COPY_MEMORY, offset, tmpsize); + offset += tmpsize; + } + if (buffer) + gst_buffer_copy_into (detect_buf, buffer, GST_BUFFER_COPY_MEMORY, + offset, gst_buffer_get_size (buffer)); + } + + ret = bclass->detect (parse, detect_buf); + gst_buffer_unref (detect_buf); + + if (ret == GST_FLOW_OK) { + GList *l; + + /* Detected something */ + parse->priv->detecting = FALSE; + + for (l = parse->priv->detect_buffers; l; l = l->next) { + if (ret == GST_FLOW_OK && !parse->priv->flushing) + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + parent, GST_BUFFER_CAST (l->data)); + else + gst_buffer_unref (GST_BUFFER_CAST (l->data)); + } + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + + if (ret != GST_FLOW_OK) { + return ret; + } + + /* Handle the current buffer */ + } else if (ret == GST_FLOW_NOT_NEGOTIATED) { + /* Still detecting, append buffer or error out if draining */ + + if (parse->priv->drain) { + GST_DEBUG_OBJECT (parse, "Draining but did not detect format yet"); + return GST_FLOW_ERROR; + } else if (parse->priv->flushing) { + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, + NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + } else { + parse->priv->detect_buffers = + g_list_append (parse->priv->detect_buffers, buffer); + parse->priv->detect_buffers_size += gst_buffer_get_size (buffer); + return GST_FLOW_OK; + } + } else { + /* Something went wrong, subclass responsible for error reporting */ + return ret; + } + + /* And now handle the current buffer if detection worked */ + } + + if (G_LIKELY (buffer)) { + GST_LOG_OBJECT (parse, + "buffer size: %" G_GSIZE_FORMAT ", offset = %" G_GINT64_FORMAT + ", dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT, + gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer), + GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_PTS (buffer))); + + if (G_UNLIKELY (!parse->priv->disable_passthrough + && parse->priv->passthrough)) { + GstBaseParseFrame frame; + + gst_base_parse_frame_init (&frame); + frame.buffer = gst_buffer_make_writable (buffer); + ret = gst_base_parse_push_frame (parse, &frame); + gst_base_parse_frame_free (&frame); + return ret; + } + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { + /* upstream feeding us in reverse playback; + * finish previous fragment and start new upon DISCONT */ + if (parse->segment.rate < 0.0) { + GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment"); + ret = gst_base_parse_finish_fragment (parse, TRUE); + gst_base_parse_start_fragment (parse); + } else { + /* discont in the stream, drain and mark discont for next output */ + gst_base_parse_drain (parse); + parse->priv->discont = TRUE; + } + } + gst_adapter_push (parse->priv->adapter, buffer); + } + + /* Parse and push as many frames as possible */ + /* Stop either when adapter is empty or we are flushing */ + while (!parse->priv->flushing) { + gint flush = 0; + gboolean updated_prev_pts = FALSE; + + /* note: if subclass indicates MAX fsize, + * this will not likely be available anyway ... */ + min_size = MAX (parse->priv->min_frame_size, fsize); + av = gst_adapter_available (parse->priv->adapter); + + if (G_UNLIKELY (parse->priv->drain)) { + min_size = av; + GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); + if (G_UNLIKELY (!min_size)) { + goto done; + } + } + + /* Collect at least min_frame_size bytes */ + if (av < min_size) { + GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", av); + goto done; + } + + /* move along with upstream timestamp (if any), + * but interpolate in between */ + pts = gst_adapter_prev_pts (parse->priv->adapter, NULL); + dts = gst_adapter_prev_dts (parse->priv->adapter, NULL); + if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) { + parse->priv->prev_pts = parse->priv->next_pts = pts; + updated_prev_pts = TRUE; + } + + if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) { + parse->priv->prev_dts = parse->priv->next_dts = dts; + parse->priv->prev_dts_from_pts = FALSE; + } + + /* we can mess with, erm interpolate, timestamps, + * and incoming stuff has PTS but no DTS seen so far, + * then pick up DTS from PTS and hope for the best ... */ + if (parse->priv->infer_ts && + parse->priv->pts_interpolate && + !GST_CLOCK_TIME_IS_VALID (dts) && + (!GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts) + || (parse->priv->prev_dts_from_pts && updated_prev_pts)) + && GST_CLOCK_TIME_IS_VALID (pts)) { + parse->priv->prev_dts = parse->priv->next_dts = pts; + parse->priv->prev_dts_from_pts = TRUE; + } + + /* always pass all available data */ + tmpbuf = gst_adapter_get_buffer (parse->priv->adapter, av); + + /* already inform subclass what timestamps we have planned, + * at least if provided by time-based upstream */ + if (parse->priv->upstream_format == GST_FORMAT_TIME) { + tmpbuf = gst_buffer_make_writable (tmpbuf); + GST_BUFFER_PTS (tmpbuf) = parse->priv->next_pts; + GST_BUFFER_DTS (tmpbuf) = parse->priv->next_dts; + GST_BUFFER_DURATION (tmpbuf) = GST_CLOCK_TIME_NONE; + } + + /* keep the adapter mapped, so keep track of what has to be flushed */ + ret = gst_base_parse_handle_buffer (parse, tmpbuf, &skip, &flush); + tmpbuf = NULL; + + if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) { + goto done; + } + if (skip == 0 && flush == 0) { + GST_LOG_OBJECT (parse, "nothing skipped and no frames finished, " + "breaking to get more data"); + /* ignore this return as it produced no data */ + ret = old_ret; + goto done; + } + if (old_ret == GST_FLOW_OK) + old_ret = ret; + } + +done: + GST_LOG_OBJECT (parse, "chain leaving"); + return ret; +} + +/* pull @size bytes at current offset, + * i.e. at least try to and possibly return a shorter buffer if near the end */ +static GstFlowReturn +gst_base_parse_pull_range (GstBaseParse * parse, guint size, + GstBuffer ** buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* Caching here actually makes much less difference than one would expect. + * We do it mainly to avoid pulling buffers of 1 byte all the time */ + if (parse->priv->cache) { + gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache); + gint cache_size = gst_buffer_get_size (parse->priv->cache); + + if (cache_offset <= parse->priv->offset && + (parse->priv->offset + size) <= (cache_offset + cache_size)) { + *buffer = gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, + parse->priv->offset - cache_offset, size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + return GST_FLOW_OK; + } + /* not enough data in the cache, free cache and get a new one */ + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + } + + /* refill the cache */ + ret = + gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size, + 64 * 1024), &parse->priv->cache); + if (ret != GST_FLOW_OK) { + parse->priv->cache = NULL; + return ret; + } + + if (gst_buffer_get_size (parse->priv->cache) >= size) { + *buffer = + gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, + size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + return GST_FLOW_OK; + } + + /* Not possible to get enough data, try a last time with + * requesting exactly the size we need */ + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + + ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size, + &parse->priv->cache); + + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret); + *buffer = NULL; + return ret; + } + + if (gst_buffer_get_size (parse->priv->cache) < size) { + GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %" + G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes", + parse->priv->offset, size, gst_buffer_get_size (parse->priv->cache)); + + *buffer = parse->priv->cache; + parse->priv->cache = NULL; + + return GST_FLOW_OK; + } + + *buffer = + gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_base_parse_handle_previous_fragment (GstBaseParse * parse) +{ + gint64 offset = 0; + GstClockTime ts = 0; + GstBuffer *buffer; + GstFlowReturn ret; + + GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT + ", last_offset = %" G_GINT64_FORMAT, + GST_TIME_ARGS (parse->priv->last_pts), parse->priv->last_offset); + + if (!parse->priv->last_offset + || parse->priv->last_pts <= parse->segment.start) { + GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->segment.start)); + ret = GST_FLOW_EOS; + goto exit; + } + + /* last fragment started at last_offset / last_ts; + * seek back 10s capped at 1MB */ + if (parse->priv->last_pts >= 10 * GST_SECOND) + ts = parse->priv->last_pts - 10 * GST_SECOND; + /* if we are exact now, we will be more so going backwards */ + if (parse->priv->exact_position) { + offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL); + } else { + if (!gst_base_parse_convert (parse, GST_FORMAT_TIME, ts, + GST_FORMAT_BYTES, &offset)) { + GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based"); + } + } + offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024, + parse->priv->last_offset - 1024); + offset = MAX (0, offset); + + GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT, + offset); + parse->priv->offset = offset; + + ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset, + &buffer); + if (ret != GST_FLOW_OK) + goto exit; + + /* offset will increase again as fragment is processed/parsed */ + parse->priv->last_offset = offset; + + gst_base_parse_start_fragment (parse); + gst_adapter_push (parse->priv->adapter, buffer); + ret = gst_base_parse_finish_fragment (parse, TRUE); + if (ret != GST_FLOW_OK) + goto exit; + + /* force previous fragment */ + parse->priv->offset = -1; + +exit: + return ret; +} + +/* PULL mode: + * pull and scan for next frame starting from current offset + * ajusts sync, drain and offset going along */ +static GstFlowReturn +gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass) +{ + GstBuffer *buffer; + GstFlowReturn ret = GST_FLOW_OK; + guint fsize, min_size; + gint flushed = 0; + gint skip = 0; + + GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); + + /* let's make this efficient for all subclass once and for all; + * maybe it does not need this much, but in the latter case, we know we are + * in pull mode here and might as well try to read and supply more anyway + * (so does the buffer caching mechanism) */ + fsize = 64 * 1024; + + while (TRUE) { + min_size = MAX (parse->priv->min_frame_size, fsize); + + GST_LOG_OBJECT (parse, "reading buffer size %u", min_size); + + ret = gst_base_parse_pull_range (parse, min_size, &buffer); + if (ret != GST_FLOW_OK) + goto done; + + /* if we got a short read, inform subclass we are draining leftover + * and no more is to be expected */ + if (gst_buffer_get_size (buffer) < min_size) { + GST_LOG_OBJECT (parse, "... but did not get that; marked draining"); + parse->priv->drain = TRUE; + } + + if (parse->priv->detecting) { + ret = klass->detect (parse, buffer); + if (ret == GST_FLOW_NOT_NEGOTIATED) { + /* If draining we error out, otherwise request a buffer + * with 64kb more */ + if (parse->priv->drain) { + gst_buffer_unref (buffer); + GST_ERROR_OBJECT (parse, "Failed to detect format but draining"); + return GST_FLOW_ERROR; + } else { + fsize += 64 * 1024; + gst_buffer_unref (buffer); + continue; + } + } else if (ret != GST_FLOW_OK) { + gst_buffer_unref (buffer); + GST_ERROR_OBJECT (parse, "detect() returned %s", + gst_flow_get_name (ret)); + return ret; + } + + /* Else handle this buffer normally */ + } + + ret = gst_base_parse_handle_buffer (parse, buffer, &skip, &flushed); + if (ret != GST_FLOW_OK) + break; + + /* If a large amount of data was requested to be skipped, _handle_buffer + might have set the priv->skip flag to an extra amount on top of skip. + In pull mode, we can just pull from the new offset directly. */ + parse->priv->offset += parse->priv->skip; + parse->priv->skip = 0; + + /* something flushed means something happened, + * and we should bail out of this loop so as not to occupy + * the task thread indefinitely */ + if (flushed) { + GST_LOG_OBJECT (parse, "frame finished, breaking loop"); + break; + } + /* nothing flushed, no skip and draining, so nothing left to do */ + if (!skip && parse->priv->drain) { + GST_LOG_OBJECT (parse, "no activity or result when draining; " + "breaking loop and marking EOS"); + ret = GST_FLOW_EOS; + break; + } + /* otherwise, get some more data + * note that is checked this does not happen indefinitely */ + if (!skip) { + GST_LOG_OBJECT (parse, "getting some more data"); + fsize += 64 * 1024; + } + parse->priv->drain = FALSE; + } + +done: + return ret; +} + +/* Loop that is used in pull mode to retrieve data from upstream */ +static void +gst_base_parse_loop (GstPad * pad) +{ + GstBaseParse *parse; + GstBaseParseClass *klass; + GstFlowReturn ret = GST_FLOW_OK; + + parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); + klass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_LOG_OBJECT (parse, "Entering parse loop"); + + if (G_UNLIKELY (parse->priv->push_stream_start)) { + gchar *stream_id; + GstEvent *event; + + stream_id = + gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (parse), + NULL); + + event = gst_event_new_stream_start (stream_id); + gst_event_set_group_id (event, gst_util_group_id_next ()); + + GST_DEBUG_OBJECT (parse, "Pushing STREAM_START"); + gst_pad_push_event (parse->srcpad, event); + parse->priv->push_stream_start = FALSE; + g_free (stream_id); + } + + /* reverse playback: + * first fragment (closest to stop time) is handled normally below, + * then we pull in fragments going backwards */ + if (parse->segment.rate < 0.0) { + /* check if we jumped back to a previous fragment, + * which is a post-first fragment */ + if (parse->priv->offset < 0) { + ret = gst_base_parse_handle_previous_fragment (parse); + goto done; + } + } + + ret = gst_base_parse_scan_frame (parse, klass); + + /* eat expected eos signalling past segment in reverse playback */ + if (parse->segment.rate < 0.0 && ret == GST_FLOW_EOS && + parse->segment.position >= parse->segment.stop) { + GST_DEBUG_OBJECT (parse, "downstream has reached end of segment"); + /* push what was accumulated during loop run */ + gst_base_parse_finish_fragment (parse, FALSE); + /* force previous fragment */ + parse->priv->offset = -1; + goto eos; + } + + if (ret != GST_FLOW_OK) + goto done; + +done: + if (ret == GST_FLOW_EOS) + goto eos; + else if (ret != GST_FLOW_OK) + goto pause; + + gst_object_unref (parse); + return; + + /* ERRORS */ +eos: + { + ret = GST_FLOW_EOS; + GST_DEBUG_OBJECT (parse, "eos"); + /* fall-through */ + } +pause: + { + gboolean push_eos = FALSE; + + GST_DEBUG_OBJECT (parse, "pausing task, reason %s", + gst_flow_get_name (ret)); + gst_pad_pause_task (parse->sinkpad); + + if (ret == GST_FLOW_EOS) { + /* handle end-of-stream/segment */ + if (parse->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { + gint64 stop; + + if ((stop = parse->segment.stop) == -1) + stop = parse->segment.duration; + + GST_DEBUG_OBJECT (parse, "sending segment_done"); + + gst_element_post_message + (GST_ELEMENT_CAST (parse), + gst_message_new_segment_done (GST_OBJECT_CAST (parse), + GST_FORMAT_TIME, stop)); + gst_pad_push_event (parse->srcpad, + gst_event_new_segment_done (GST_FORMAT_TIME, stop)); + } else { + /* If we STILL have zero frames processed, fire an error */ + if (parse->priv->framecount == 0) { + GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, + ("No valid frames found before end of stream"), (NULL)); + } + push_eos = TRUE; + } + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { + /* for fatal errors we post an error message, wrong-state is + * not fatal because it happens due to flushes and only means + * that we should stop now. */ + GST_ELEMENT_FLOW_ERROR (parse, ret); + push_eos = TRUE; + } + if (push_eos) { + if (parse->priv->estimated_duration <= 0) { + gst_base_parse_update_duration (parse); + } + /* Push pending events, including SEGMENT events */ + gst_base_parse_push_pending_events (parse); + + gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); + } + gst_object_unref (parse); + } +} + +static gboolean +gst_base_parse_sink_activate (GstPad * sinkpad, GstObject * parent) +{ + GstSchedulingFlags sched_flags; + GstBaseParse *parse; + GstQuery *query; + gboolean pull_mode; + + parse = GST_BASE_PARSE (parent); + + GST_DEBUG_OBJECT (parse, "sink activate"); + + query = gst_query_new_scheduling (); + if (!gst_pad_peer_query (sinkpad, query)) { + gst_query_unref (query); + goto baseparse_push; + } + + gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL); + + pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL) + && ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0); + + gst_query_unref (query); + + if (!pull_mode) + goto baseparse_push; + + GST_DEBUG_OBJECT (parse, "trying to activate in pull mode"); + if (!gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE)) + goto baseparse_push; + + parse->priv->push_stream_start = TRUE; + /* In pull mode, upstream is BYTES */ + parse->priv->upstream_format = GST_FORMAT_BYTES; + + return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_base_parse_loop, + sinkpad, NULL); + /* fallback */ +baseparse_push: + { + GST_DEBUG_OBJECT (parse, "trying to activate in push mode"); + return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); + } +} + +static gboolean +gst_base_parse_activate (GstBaseParse * parse, gboolean active) +{ + GstBaseParseClass *klass; + gboolean result = TRUE; + + GST_DEBUG_OBJECT (parse, "activate %d", active); + + klass = GST_BASE_PARSE_GET_CLASS (parse); + + if (active) { + if (parse->priv->pad_mode == GST_PAD_MODE_NONE && klass->start) + result = klass->start (parse); + + /* If the subclass implements ::detect we want to + * call it for the first buffers now */ + parse->priv->detecting = (klass->detect != NULL); + } else { + /* We must make sure streaming has finished before resetting things + * and calling the ::stop vfunc */ + GST_PAD_STREAM_LOCK (parse->sinkpad); + GST_PAD_STREAM_UNLOCK (parse->sinkpad); + + if (parse->priv->pad_mode != GST_PAD_MODE_NONE && klass->stop) + result = klass->stop (parse); + + parse->priv->pad_mode = GST_PAD_MODE_NONE; + parse->priv->upstream_format = GST_FORMAT_UNDEFINED; + } + GST_DEBUG_OBJECT (parse, "activate return: %d", result); + return result; +} + +static gboolean +gst_base_parse_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean result; + GstBaseParse *parse; + + parse = GST_BASE_PARSE (parent); + + GST_DEBUG_OBJECT (parse, "sink %sactivate in %s mode", + (active) ? "" : "de", gst_pad_mode_get_name (mode)); + + if (!gst_base_parse_activate (parse, active)) + goto activate_failed; + + switch (mode) { + case GST_PAD_MODE_PULL: + if (active) { + parse->priv->pending_events = + g_list_prepend (parse->priv->pending_events, + gst_event_new_segment (&parse->segment)); + result = TRUE; + } else { + result = gst_pad_stop_task (pad); + } + break; + default: + result = TRUE; + break; + } + if (result) + parse->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE; + + GST_DEBUG_OBJECT (parse, "sink activate return: %d", result); + + return result; + + /* ERRORS */ +activate_failed: + { + GST_DEBUG_OBJECT (parse, "activate failed"); + return FALSE; + } +} + +/** + * gst_base_parse_set_duration: + * @parse: #GstBaseParse. + * @fmt: #GstFormat. + * @duration: duration value. + * @interval: how often to update the duration estimate based on bitrate, or 0. + * + * Sets the duration of the currently playing media. Subclass can use this + * when it is able to determine duration and/or notices a change in the media + * duration. Alternatively, if @interval is non-zero (default), then stream + * duration is determined based on estimated bitrate, and updated every @interval + * frames. + */ +void +gst_base_parse_set_duration (GstBaseParse * parse, + GstFormat fmt, gint64 duration, gint interval) +{ + g_return_if_fail (parse != NULL); + + if (parse->priv->upstream_has_duration) { + GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update"); + goto exit; + } + + if (duration != parse->priv->duration) { + GstMessage *m; + + m = gst_message_new_duration_changed (GST_OBJECT (parse)); + gst_element_post_message (GST_ELEMENT (parse), m); + + /* TODO: what about duration tag? */ + } + parse->priv->duration = duration; + parse->priv->duration_fmt = fmt; + GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration); + if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) { + if (interval != 0) { + GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate"); + interval = 0; + } + } + GST_DEBUG_OBJECT (parse, "set update interval: %d", interval); + parse->priv->update_interval = interval; +exit: + return; +} + +/** + * gst_base_parse_set_average_bitrate: + * @parse: #GstBaseParse. + * @bitrate: average bitrate in bits/second + * + * Optionally sets the average bitrate detected in media (if non-zero), + * e.g. based on metadata, as it will be posted to the application. + * + * By default, announced average bitrate is estimated. The average bitrate + * is used to estimate the total duration of the stream and to estimate + * a seek position, if there's no index and the format is syncable + * (see gst_base_parse_set_syncable()). + */ +void +gst_base_parse_set_average_bitrate (GstBaseParse * parse, guint bitrate) +{ + parse->priv->bitrate = bitrate; + GST_DEBUG_OBJECT (parse, "bitrate %u", bitrate); +} + +/** + * gst_base_parse_set_min_frame_size: + * @parse: #GstBaseParse. + * @min_size: Minimum size of the data that this base class should give to + * subclass. + * + * Subclass can use this function to tell the base class that it needs to + * give at least #min_size buffers. + */ +void +gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) +{ + g_return_if_fail (parse != NULL); + + parse->priv->min_frame_size = min_size; + GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size); +} + +/** + * gst_base_parse_set_frame_rate: + * @parse: the #GstBaseParse to set + * @fps_num: frames per second (numerator). + * @fps_den: frames per second (denominator). + * @lead_in: frames needed before a segment for subsequent decode + * @lead_out: frames needed after a segment + * + * If frames per second is configured, parser can take care of buffer duration + * and timestamping. When performing segment clipping, or seeking to a specific + * location, a corresponding decoder might need an initial @lead_in and a + * following @lead_out number of frames to ensure the desired segment is + * entirely filled upon decoding. + */ +void +gst_base_parse_set_frame_rate (GstBaseParse * parse, guint fps_num, + guint fps_den, guint lead_in, guint lead_out) +{ + g_return_if_fail (parse != NULL); + + parse->priv->fps_num = fps_num; + parse->priv->fps_den = fps_den; + if (!fps_num || !fps_den) { + GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters", + fps_num, fps_den); + fps_num = fps_den = 0; + parse->priv->frame_duration = GST_CLOCK_TIME_NONE; + parse->priv->lead_in = parse->priv->lead_out = 0; + parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; + } else { + parse->priv->frame_duration = + gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); + parse->priv->lead_in = lead_in; + parse->priv->lead_out = lead_out; + parse->priv->lead_in_ts = + gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num); + parse->priv->lead_out_ts = + gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num); + /* aim for about 1.5s to estimate duration */ + if (parse->priv->update_interval < 0) { + guint64 interval = gst_util_uint64_scale (fps_num, 3, + G_GUINT64_CONSTANT (2) * fps_den); + + parse->priv->update_interval = MIN (interval, G_MAXINT); + + GST_LOG_OBJECT (parse, "estimated update interval to %d frames", + parse->priv->update_interval); + } + } + GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", + fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); + GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, " + "lead out: %d frames = %" G_GUINT64_FORMAT " ms", + lead_in, parse->priv->lead_in_ts / GST_MSECOND, + lead_out, parse->priv->lead_out_ts / GST_MSECOND); +} + +/** + * gst_base_parse_set_has_timing_info: + * @parse: a #GstBaseParse + * @has_timing: whether frames carry timing information + * + * Set if frames carry timing information which the subclass can (generally) + * parse and provide. In particular, intrinsic (rather than estimated) time + * can be obtained following a seek. + */ +void +gst_base_parse_set_has_timing_info (GstBaseParse * parse, gboolean has_timing) +{ + parse->priv->has_timing_info = has_timing; + GST_INFO_OBJECT (parse, "has_timing: %s", (has_timing) ? "yes" : "no"); +} + +/** + * gst_base_parse_set_syncable: + * @parse: a #GstBaseParse + * @syncable: set if frame starts can be identified + * + * Set if frame starts can be identified. This is set by default and + * determines whether seeking based on bitrate averages + * is possible for a format/stream. + */ +void +gst_base_parse_set_syncable (GstBaseParse * parse, gboolean syncable) +{ + parse->priv->syncable = syncable; + GST_INFO_OBJECT (parse, "syncable: %s", (syncable) ? "yes" : "no"); +} + +/** + * gst_base_parse_set_passthrough: + * @parse: a #GstBaseParse + * @passthrough: %TRUE if parser should run in passthrough mode + * + * Set if the nature of the format or configuration does not allow (much) + * parsing, and the parser should operate in passthrough mode (which only + * applies when operating in push mode). That is, incoming buffers are + * pushed through unmodified, i.e. no @check_valid_frame or @parse_frame + * callbacks will be invoked, but @pre_push_frame will still be invoked, + * so subclass can perform as much or as little is appropriate for + * passthrough semantics in @pre_push_frame. + */ +void +gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) +{ + parse->priv->passthrough = passthrough; + GST_INFO_OBJECT (parse, "passthrough: %s", (passthrough) ? "yes" : "no"); +} + +/** + * gst_base_parse_set_pts_interpolation: + * @parse: a #GstBaseParse + * @pts_interpolate: %TRUE if parser should interpolate PTS timestamps + * + * By default, the base class will guess PTS timestamps using a simple + * interpolation (previous timestamp + duration), which is incorrect for + * data streams with reordering, where PTS can go backward. Sub-classes + * implementing such formats should disable PTS interpolation. + */ +void +gst_base_parse_set_pts_interpolation (GstBaseParse * parse, + gboolean pts_interpolate) +{ + parse->priv->pts_interpolate = pts_interpolate; + GST_INFO_OBJECT (parse, "PTS interpolation: %s", + (pts_interpolate) ? "yes" : "no"); +} + +/** + * gst_base_parse_set_infer_ts: + * @parse: a #GstBaseParse + * @infer_ts: %TRUE if parser should infer DTS/PTS from each other + * + * By default, the base class might try to infer PTS from DTS and vice + * versa. While this is generally correct for audio data, it may not + * be otherwise. Sub-classes implementing such formats should disable + * timestamp inferring. + */ +void +gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts) +{ + parse->priv->infer_ts = infer_ts; + GST_INFO_OBJECT (parse, "TS inferring: %s", (infer_ts) ? "yes" : "no"); +} + +/** + * gst_base_parse_set_latency: + * @parse: a #GstBaseParse + * @min_latency: minimum parse latency + * @max_latency: maximum parse latency + * + * Sets the minimum and maximum (which may likely be equal) latency introduced + * by the parsing process. If there is such a latency, which depends on the + * particular parsing of the format, it typically corresponds to 1 frame duration. + */ +void +gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency, + GstClockTime max_latency) +{ + g_return_if_fail (min_latency != GST_CLOCK_TIME_NONE); + g_return_if_fail (min_latency <= max_latency); + + GST_OBJECT_LOCK (parse); + parse->priv->min_latency = min_latency; + parse->priv->max_latency = max_latency; + GST_OBJECT_UNLOCK (parse); + GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %" + GST_TIME_FORMAT, GST_TIME_ARGS (min_latency), + GST_TIME_ARGS (max_latency)); +} + +static gboolean +gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, + GstClockTime * duration) +{ + gboolean res = FALSE; + + g_return_val_if_fail (duration != NULL, FALSE); + + *duration = GST_CLOCK_TIME_NONE; + if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) { + GST_LOG_OBJECT (parse, "using provided duration"); + *duration = parse->priv->duration; + res = TRUE; + } else if (parse->priv->duration != -1) { + GST_LOG_OBJECT (parse, "converting provided duration"); + res = gst_base_parse_convert (parse, parse->priv->duration_fmt, + parse->priv->duration, format, (gint64 *) duration); + } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) { + GST_LOG_OBJECT (parse, "using estimated duration"); + *duration = parse->priv->estimated_duration; + res = TRUE; + } else { + GST_LOG_OBJECT (parse, "cannot estimate duration"); + } + + GST_LOG_OBJECT (parse, "res: %d, duration %" GST_TIME_FORMAT, res, + GST_TIME_ARGS (*duration)); + return res; +} + +static gboolean +gst_base_parse_src_query_default (GstBaseParse * parse, GstQuery * query) +{ + gboolean res = FALSE; + GstPad *pad; + + pad = GST_BASE_PARSE_SRC_PAD (parse); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 dest_value; + GstFormat format; + + GST_DEBUG_OBJECT (parse, "position query"); + gst_query_parse_position (query, &format, NULL); + + /* try upstream first */ + res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query); + if (!res) { + /* Fall back on interpreting segment */ + GST_OBJECT_LOCK (parse); + /* Only reply BYTES if upstream is in BYTES already, otherwise + * we're not in charge */ + if (format == GST_FORMAT_BYTES + && parse->priv->upstream_format == GST_FORMAT_BYTES) { + dest_value = parse->priv->offset; + res = TRUE; + } else if (format == parse->segment.format && + GST_CLOCK_TIME_IS_VALID (parse->segment.position)) { + dest_value = gst_segment_to_stream_time (&parse->segment, + parse->segment.format, parse->segment.position); + res = TRUE; + } + GST_OBJECT_UNLOCK (parse); + if (!res && parse->priv->upstream_format == GST_FORMAT_BYTES) { + /* no precise result, upstream no idea either, then best estimate */ + /* priv->offset is updated in both PUSH/PULL modes, *iff* we're + * in charge of things */ + res = gst_base_parse_convert (parse, + GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value); + } + if (res) + gst_query_set_position (query, format, dest_value); + } + break; + } + case GST_QUERY_DURATION: + { + GstFormat format; + GstClockTime duration; + + GST_DEBUG_OBJECT (parse, "duration query"); + gst_query_parse_duration (query, &format, NULL); + + /* consult upstream */ + res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query); + + /* otherwise best estimate from us */ + if (!res) { + res = gst_base_parse_get_duration (parse, format, &duration); + if (res) + gst_query_set_duration (query, format, duration); + } + break; + } + case GST_QUERY_SEEKING: + { + GstFormat fmt; + GstClockTime duration = GST_CLOCK_TIME_NONE; + gboolean seekable = FALSE; + + GST_DEBUG_OBJECT (parse, "seeking query"); + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + + /* consult upstream */ + res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query); + + /* we may be able to help if in TIME */ + if (fmt == GST_FORMAT_TIME && gst_base_parse_is_seekable (parse)) { + gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL); + /* already OK if upstream takes care */ + GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d", + res, seekable); + if (!(res && seekable)) { + if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration) + || duration == -1) { + /* seekable if we still have a chance to get duration later on */ + seekable = parse->priv->upstream_seekable && + (parse->priv->update_interval > 0); + } else { + seekable = parse->priv->upstream_seekable; + GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d", + seekable); + } + gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration); + res = TRUE; + } + } + break; + } + case GST_QUERY_FORMATS: + gst_query_set_formatsv (query, 3, fmtlist); + res = TRUE; + break; + case GST_QUERY_CONVERT: + { + GstFormat src_format, dest_format; + gint64 src_value, dest_value; + + gst_query_parse_convert (query, &src_format, &src_value, + &dest_format, &dest_value); + + res = gst_base_parse_convert (parse, src_format, src_value, + dest_format, &dest_value); + if (res) { + gst_query_set_convert (query, src_format, src_value, + dest_format, dest_value); + } + break; + } + case GST_QUERY_LATENCY: + { + if ((res = gst_pad_peer_query (parse->sinkpad, query))) { + gboolean live; + GstClockTime min_latency, max_latency; + + gst_query_parse_latency (query, &live, &min_latency, &max_latency); + GST_DEBUG_OBJECT (parse, "Peer latency: live %d, min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live, + GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); + + GST_OBJECT_LOCK (parse); + /* add our latency */ + min_latency += parse->priv->min_latency; + if (max_latency == -1 || parse->priv->max_latency == -1) + max_latency = -1; + else + max_latency += parse->priv->max_latency; + GST_OBJECT_UNLOCK (parse); + + gst_query_set_latency (query, live, min_latency, max_latency); + } + break; + } + case GST_QUERY_SEGMENT: + { + GstFormat format; + gint64 start, stop; + + format = parse->segment.format; + + start = + gst_segment_to_stream_time (&parse->segment, format, + parse->segment.start); + if ((stop = parse->segment.stop) == -1) + stop = parse->segment.duration; + else + stop = gst_segment_to_stream_time (&parse->segment, format, stop); + + gst_query_set_segment (query, parse->segment.rate, format, start, stop); + res = TRUE; + break; + } + default: + res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query); + break; + } + return res; +} + +/* scans for a cluster start from @pos, + * return GST_FLOW_OK and frame position/time in @pos/@time if found */ +static GstFlowReturn +gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, + GstClockTime * time, GstClockTime * duration) +{ + GstBaseParseClass *klass; + gint64 orig_offset; + gboolean orig_drain, orig_discont; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *buf = NULL; + GstBaseParseFrame *sframe = NULL; + + g_return_val_if_fail (pos != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (time != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (duration != NULL, GST_FLOW_ERROR); + + klass = GST_BASE_PARSE_GET_CLASS (parse); + + *time = GST_CLOCK_TIME_NONE; + *duration = GST_CLOCK_TIME_NONE; + + /* save state */ + orig_offset = parse->priv->offset; + orig_discont = parse->priv->discont; + orig_drain = parse->priv->drain; + + GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x)", *pos, *pos); + + /* jump elsewhere and locate next frame */ + parse->priv->offset = *pos; + /* mark as scanning so frames don't get processed all the way */ + parse->priv->scanning = TRUE; + ret = gst_base_parse_scan_frame (parse, klass); + parse->priv->scanning = FALSE; + /* retrieve frame found during scan */ + sframe = parse->priv->scanned_frame; + parse->priv->scanned_frame = NULL; + + if (ret != GST_FLOW_OK || !sframe) + goto done; + + /* get offset first, subclass parsing might dump other stuff in there */ + *pos = sframe->offset; + buf = sframe->buffer; + g_assert (buf); + + /* but it should provide proper time */ + *time = GST_BUFFER_TIMESTAMP (buf); + *duration = GST_BUFFER_DURATION (buf); + + GST_LOG_OBJECT (parse, + "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, + GST_TIME_ARGS (*time), *pos); + +done: + if (sframe) + gst_base_parse_frame_free (sframe); + + /* restore state */ + parse->priv->offset = orig_offset; + parse->priv->discont = orig_discont; + parse->priv->drain = orig_drain; + + return ret; +} + +/* bisect and scan through file for frame starting before @time, + * returns OK and @time/@offset if found, NONE and/or error otherwise + * If @time == G_MAXINT64, scan for duration ( == last frame) */ +static GstFlowReturn +gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, + gint64 * _offset) +{ + GstFlowReturn ret = GST_FLOW_OK; + gint64 lpos, hpos, newpos; + GstClockTime time, ltime, htime, newtime, dur; + gboolean cont = TRUE; + const GstClockTime tolerance = TARGET_DIFFERENCE; + const guint chunk = 4 * 1024; + + g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR); + + GST_DEBUG_OBJECT (parse, "Bisecting for time %" GST_TIME_FORMAT, + GST_TIME_ARGS (*_time)); + + /* TODO also make keyframe aware if useful some day */ + + time = *_time; + + /* basic cases */ + if (time == 0) { + *_offset = 0; + return GST_FLOW_OK; + } + + if (time == -1) { + *_offset = -1; + return GST_FLOW_OK; + } + + /* do not know at first */ + *_offset = -1; + *_time = GST_CLOCK_TIME_NONE; + + /* need initial positions; start and end */ + lpos = parse->priv->first_frame_offset; + ltime = parse->priv->first_frame_pts; + /* try other one if no luck */ + if (!GST_CLOCK_TIME_IS_VALID (ltime)) + ltime = parse->priv->first_frame_dts; + if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &htime)) { + GST_DEBUG_OBJECT (parse, "Unknown time duration, cannot bisect"); + return GST_FLOW_ERROR; + } + hpos = parse->priv->upstream_size; + + GST_DEBUG_OBJECT (parse, + "Bisection initial bounds: bytes %" G_GINT64_FORMAT " %" G_GINT64_FORMAT + ", times %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, lpos, hpos, + GST_TIME_ARGS (ltime), GST_TIME_ARGS (htime)); + + /* check preconditions are satisfied; + * start and end are needed, except for special case where we scan for + * last frame to determine duration */ + if (parse->priv->pad_mode != GST_PAD_MODE_PULL || !hpos || + !GST_CLOCK_TIME_IS_VALID (ltime) || + (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) { + return GST_FLOW_OK; + } + + /* shortcut cases */ + if (time < ltime) { + goto exit; + } else if (time < ltime + tolerance) { + *_offset = lpos; + *_time = ltime; + goto exit; + } else if (time >= htime) { + *_offset = hpos; + *_time = htime; + goto exit; + } + + while (htime > ltime && cont) { + GST_LOG_OBJECT (parse, + "lpos: %" G_GUINT64_FORMAT ", ltime: %" GST_TIME_FORMAT, lpos, + GST_TIME_ARGS (ltime)); + GST_LOG_OBJECT (parse, + "hpos: %" G_GUINT64_FORMAT ", htime: %" GST_TIME_FORMAT, hpos, + GST_TIME_ARGS (htime)); + if (G_UNLIKELY (time == G_MAXINT64)) { + newpos = hpos; + } else if (G_LIKELY (hpos > lpos)) { + newpos = + gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) + + lpos - chunk; + } else { + /* should mean lpos == hpos, since lpos <= hpos is invariant */ + newpos = lpos; + /* we check this case once, but not forever, so break loop */ + cont = FALSE; + } + + /* ensure */ + newpos = CLAMP (newpos, lpos, hpos); + GST_LOG_OBJECT (parse, + "estimated _offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT, + GST_TIME_ARGS (time), newpos); + + ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur); + if (ret == GST_FLOW_EOS) { + /* heuristic HACK */ + hpos = MAX (lpos, hpos - chunk); + continue; + } else if (ret != GST_FLOW_OK) { + goto exit; + } + + if (newtime == -1 || newpos == -1) { + GST_DEBUG_OBJECT (parse, "subclass did not provide metadata; aborting"); + break; + } + + if (G_UNLIKELY (time == G_MAXINT64)) { + *_offset = newpos; + *_time = newtime; + if (GST_CLOCK_TIME_IS_VALID (dur)) + *_time += dur; + break; + } else if (newtime > time) { + /* overshoot */ + hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos); + htime = newtime; + } else if (newtime + tolerance > time) { + /* close enough undershoot */ + *_offset = newpos; + *_time = newtime; + break; + } else if (newtime < ltime) { + /* so a position beyond lpos resulted in earlier time than ltime ... */ + GST_DEBUG_OBJECT (parse, "non-ascending time; aborting"); + break; + } else { + /* undershoot too far */ + newpos += newpos == lpos ? chunk : 0; + lpos = CLAMP (newpos, lpos, hpos); + ltime = newtime; + } + } + +exit: + GST_LOG_OBJECT (parse, "return offset %" G_GINT64_FORMAT ", time %" + GST_TIME_FORMAT, *_offset, GST_TIME_ARGS (*_time)); + return ret; +} + +static gint64 +gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time, + gboolean before, GstClockTime * _ts) +{ + gint64 bytes = 0, ts = 0; + GstIndexEntry *entry = NULL; + + if (time == GST_CLOCK_TIME_NONE) { + ts = time; + bytes = -1; + goto exit; + } + + GST_BASE_PARSE_INDEX_LOCK (parse); + if (parse->priv->index) { + /* Let's check if we have an index entry for that time */ + entry = gst_index_get_assoc_entry (parse->priv->index, + parse->priv->index_id, + before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER, + GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time); + } + + if (entry) { + gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes); + gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts); + + GST_DEBUG_OBJECT (parse, "found index entry for %" GST_TIME_FORMAT + " at %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT, + GST_TIME_ARGS (time), GST_TIME_ARGS (ts), bytes); + } else { + GST_DEBUG_OBJECT (parse, "no index entry found for %" GST_TIME_FORMAT, + GST_TIME_ARGS (time)); + if (!before) { + bytes = -1; + ts = GST_CLOCK_TIME_NONE; + } + } + GST_BASE_PARSE_INDEX_UNLOCK (parse); + +exit: + if (_ts) + *_ts = ts; + + return bytes; +} + +/* returns TRUE if seek succeeded */ +static gboolean +gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) +{ + gdouble rate; + GstFormat format; + GstSeekFlags flags; + GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type; + gboolean flush, update, res = TRUE, accurate; + gint64 start, stop, seekpos, seekstop; + GstSegment seeksegment = { 0, }; + GstClockTime start_ts; + guint32 seqnum; + GstEvent *segment_event; + + /* try upstream first, unless we're driving the streaming thread ourselves */ + if (parse->priv->pad_mode != GST_PAD_MODE_PULL) { + res = gst_pad_push_event (parse->sinkpad, gst_event_ref (event)); + if (res) + goto done; + } + + gst_event_parse_seek (event, &rate, &format, &flags, + &start_type, &start, &stop_type, &stop); + seqnum = gst_event_get_seqnum (event); + + GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, " + "start type %d at %" GST_TIME_FORMAT ", end type %d at %" + GST_TIME_FORMAT, gst_format_get_name (format), rate, + start_type, GST_TIME_ARGS (start), stop_type, GST_TIME_ARGS (stop)); + + /* we can only handle TIME, so check if subclass can convert + * to TIME format if it's some other format (such as DEFAULT) */ + if (format != GST_FORMAT_TIME) { + if (!gst_base_parse_convert (parse, format, start, GST_FORMAT_TIME, &start) + || !gst_base_parse_convert (parse, format, stop, GST_FORMAT_TIME, + &stop)) + goto no_convert_to_time; + + GST_INFO_OBJECT (parse, "converted %s format to start time " + "%" GST_TIME_FORMAT " and stop time %" GST_TIME_FORMAT, + gst_format_get_name (format), GST_TIME_ARGS (start), + GST_TIME_ARGS (stop)); + + format = GST_FORMAT_TIME; + } + + /* no negative rates in push mode (unless upstream takes care of that, but + * we've already tried upstream and it didn't handle the seek request) */ + if (rate < 0.0 && parse->priv->pad_mode == GST_PAD_MODE_PUSH) + goto negative_rate; + + if (start_type != GST_SEEK_TYPE_SET || + (stop_type != GST_SEEK_TYPE_SET && stop_type != GST_SEEK_TYPE_NONE)) + goto wrong_type; + + /* get flush flag */ + flush = flags & GST_SEEK_FLAG_FLUSH; + + /* copy segment, we need this because we still need the old + * segment when we close the current segment. */ + gst_segment_copy_into (&parse->segment, &seeksegment); + + GST_DEBUG_OBJECT (parse, "configuring seek"); + gst_segment_do_seek (&seeksegment, rate, format, flags, + start_type, start, stop_type, stop, &update); + + /* accurate seeking implies seek tables are used to obtain position, + * and the requested segment is maintained exactly, not adjusted any way */ + accurate = flags & GST_SEEK_FLAG_ACCURATE; + + /* maybe we can be accurate for (almost) free */ + gst_base_parse_find_offset (parse, seeksegment.position, TRUE, &start_ts); + if (seeksegment.position <= start_ts + TARGET_DIFFERENCE) { + GST_DEBUG_OBJECT (parse, "accurate seek possible"); + accurate = TRUE; + } + + if (accurate) { + GstClockTime startpos; + if (rate >= 0) + startpos = seeksegment.position; + else + startpos = start; + + /* accurate requested, so ... seek a bit before target */ + if (startpos < parse->priv->lead_in_ts) + startpos = 0; + else + startpos -= parse->priv->lead_in_ts; + + if (seeksegment.stop == -1 && seeksegment.duration != -1) + seeksegment.stop = seeksegment.start + seeksegment.duration; + + seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts); + seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE, + NULL); + } else { + if (rate >= 0) + start_ts = seeksegment.position; + else + start_ts = start; + + if (seeksegment.stop == -1 && seeksegment.duration != -1) + seeksegment.stop = seeksegment.start + seeksegment.duration; + + if (!gst_base_parse_convert (parse, format, start_ts, + GST_FORMAT_BYTES, &seekpos)) + goto convert_failed; + if (!gst_base_parse_convert (parse, format, seeksegment.stop, + GST_FORMAT_BYTES, &seekstop)) + goto convert_failed; + } + + GST_DEBUG_OBJECT (parse, + "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, + start_ts, seekpos); + GST_DEBUG_OBJECT (parse, + "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, + seeksegment.stop, seekstop); + + if (parse->priv->pad_mode == GST_PAD_MODE_PULL) { + gint64 last_stop; + + GST_DEBUG_OBJECT (parse, "seek in PULL mode"); + + if (flush) { + if (parse->srcpad) { + GstEvent *fevent = gst_event_new_flush_start (); + GST_DEBUG_OBJECT (parse, "sending flush start"); + + gst_event_set_seqnum (fevent, seqnum); + + gst_pad_push_event (parse->srcpad, gst_event_ref (fevent)); + /* unlock upstream pull_range */ + gst_pad_push_event (parse->sinkpad, fevent); + } + } else { + gst_pad_pause_task (parse->sinkpad); + } + + /* we should now be able to grab the streaming thread because we stopped it + * with the above flush/pause code */ + GST_PAD_STREAM_LOCK (parse->sinkpad); + + /* save current position */ + last_stop = parse->segment.position; + GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT, + last_stop); + + /* now commit to new position */ + + /* prepare for streaming again */ + if (flush) { + GstEvent *fevent = gst_event_new_flush_stop (TRUE); + GST_DEBUG_OBJECT (parse, "sending flush stop"); + gst_event_set_seqnum (fevent, seqnum); + gst_pad_push_event (parse->srcpad, gst_event_ref (fevent)); + gst_pad_push_event (parse->sinkpad, fevent); + gst_base_parse_clear_queues (parse); + } + + memcpy (&parse->segment, &seeksegment, sizeof (GstSegment)); + + /* store the newsegment event so it can be sent from the streaming thread. */ + /* This will be sent later in _loop() */ + segment_event = gst_event_new_segment (&parse->segment); + gst_event_set_seqnum (segment_event, seqnum); + parse->priv->pending_events = + g_list_prepend (parse->priv->pending_events, segment_event); + + GST_DEBUG_OBJECT (parse, "Created newseg format %d, " + "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT + ", time = %" GST_TIME_FORMAT, format, + GST_TIME_ARGS (parse->segment.start), + GST_TIME_ARGS (parse->segment.stop), + GST_TIME_ARGS (parse->segment.time)); + + /* one last chance in pull mode to stay accurate; + * maybe scan and subclass can find where to go */ + if (!accurate) { + gint64 scanpos; + GstClockTime ts = seeksegment.position; + + gst_base_parse_locate_time (parse, &ts, &scanpos); + if (scanpos >= 0) { + accurate = TRUE; + seekpos = scanpos; + /* running collected index now consists of several intervals, + * so optimized check no longer possible */ + parse->priv->index_last_valid = FALSE; + parse->priv->index_last_offset = 0; + parse->priv->index_last_ts = 0; + } + } + + /* mark discont if we are going to stream from another position. */ + if (seekpos != parse->priv->offset) { + GST_DEBUG_OBJECT (parse, + "mark DISCONT, we did a seek to another position"); + parse->priv->offset = seekpos; + parse->priv->last_offset = seekpos; + parse->priv->seen_keyframe = FALSE; + parse->priv->discont = TRUE; + parse->priv->next_dts = start_ts; + parse->priv->next_pts = GST_CLOCK_TIME_NONE; + parse->priv->last_dts = GST_CLOCK_TIME_NONE; + parse->priv->last_pts = GST_CLOCK_TIME_NONE; + parse->priv->sync_offset = seekpos; + parse->priv->exact_position = accurate; + } + + /* Start streaming thread if paused */ + gst_pad_start_task (parse->sinkpad, + (GstTaskFunction) gst_base_parse_loop, parse->sinkpad, NULL); + + GST_PAD_STREAM_UNLOCK (parse->sinkpad); + + /* handled seek */ + res = TRUE; + } else { + GstEvent *new_event; + GstBaseParseSeek *seek; + GstSeekFlags flags = (flush ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE); + + /* The only thing we need to do in PUSH-mode is to send the + seek event (in bytes) to upstream. Segment / flush handling happens + in corresponding src event handlers */ + GST_DEBUG_OBJECT (parse, "seek in PUSH mode"); + if (seekstop >= 0 && seekstop <= seekpos) + seekstop = seekpos; + new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop); + gst_event_set_seqnum (new_event, seqnum); + + /* store segment info so its precise details can be reconstructed when + * receiving newsegment; + * this matters for all details when accurate seeking, + * is most useful to preserve NONE stop time otherwise */ + seek = g_new0 (GstBaseParseSeek, 1); + seek->segment = seeksegment; + seek->accurate = accurate; + seek->offset = seekpos; + seek->start_ts = start_ts; + GST_OBJECT_LOCK (parse); + /* less optimal, but preserves order */ + parse->priv->pending_seeks = + g_slist_append (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + + res = gst_pad_push_event (parse->sinkpad, new_event); + + if (!res) { + GST_OBJECT_LOCK (parse); + parse->priv->pending_seeks = + g_slist_remove (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + g_free (seek); + } + } + +done: + gst_event_unref (event); + return res; + + /* ERRORS */ +negative_rate: + { + GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream."); + res = FALSE; + goto done; + } +wrong_type: + { + GST_DEBUG_OBJECT (parse, "unsupported seek type."); + res = FALSE; + goto done; + } +no_convert_to_time: + { + GST_DEBUG_OBJECT (parse, "seek in %s format was requested, but subclass " + "couldn't convert that into TIME format", gst_format_get_name (format)); + res = FALSE; + goto done; + } +convert_failed: + { + GST_DEBUG_OBJECT (parse, "conversion TIME to BYTES failed."); + res = FALSE; + goto done; + } +} + +static void +gst_base_parse_set_upstream_tags (GstBaseParse * parse, GstTagList * taglist) +{ + if (taglist == parse->priv->upstream_tags) + return; + + if (parse->priv->upstream_tags) { + gst_tag_list_unref (parse->priv->upstream_tags); + parse->priv->upstream_tags = NULL; + } + + GST_INFO_OBJECT (parse, "upstream tags: %" GST_PTR_FORMAT, taglist); + + if (taglist != NULL) + parse->priv->upstream_tags = gst_tag_list_ref (taglist); + + gst_base_parse_check_bitrate_tags (parse); +} + +#if 0 +static void +gst_base_parse_set_index (GstElement * element, GstIndex * index) +{ + GstBaseParse *parse = GST_BASE_PARSE (element); + + GST_BASE_PARSE_INDEX_LOCK (parse); + if (parse->priv->index) + gst_object_unref (parse->priv->index); + if (index) { + parse->priv->index = gst_object_ref (index); + gst_index_get_writer_id (index, GST_OBJECT_CAST (element), + &parse->priv->index_id); + parse->priv->own_index = FALSE; + } else { + parse->priv->index = NULL; + } + GST_BASE_PARSE_INDEX_UNLOCK (parse); +} + +static GstIndex * +gst_base_parse_get_index (GstElement * element) +{ + GstBaseParse *parse = GST_BASE_PARSE (element); + GstIndex *result = NULL; + + GST_BASE_PARSE_INDEX_LOCK (parse); + if (parse->priv->index) + result = gst_object_ref (parse->priv->index); + GST_BASE_PARSE_INDEX_UNLOCK (parse); + + return result; +} +#endif + +static GstStateChangeReturn +gst_base_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstBaseParse *parse; + GstStateChangeReturn result; + + parse = GST_BASE_PARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* If this is our own index destroy it as the + * old entries might be wrong for the new stream */ + GST_BASE_PARSE_INDEX_LOCK (parse); + if (parse->priv->own_index) { + gst_object_unref (parse->priv->index); + parse->priv->index = NULL; + parse->priv->own_index = FALSE; + } + + /* If no index was created, generate one */ + if (G_UNLIKELY (!parse->priv->index)) { + GST_DEBUG_OBJECT (parse, "no index provided creating our own"); + + parse->priv->index = g_object_new (gst_mem_index_get_type (), NULL); + gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse), + &parse->priv->index_id); + parse->priv->own_index = TRUE; + } + GST_BASE_PARSE_INDEX_UNLOCK (parse); + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_base_parse_reset (parse); + break; + default: + break; + } + + return result; +} + +/** + * gst_base_parse_set_ts_at_offset: + * @parse: a #GstBaseParse + * @offset: offset into current buffer + * + * This function should only be called from a @handle_frame implementation. + * + * #GstBaseParse creates initial timestamps for frames by using the last + * timestamp seen in the stream before the frame starts. In certain + * cases, the correct timestamps will occur in the stream after the + * start of the frame, but before the start of the actual picture data. + * This function can be used to set the timestamps based on the offset + * into the frame data that the picture starts. + * + * Since: 1.2 + */ +void +gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset) +{ + GstClockTime pts, dts; + + g_return_if_fail (GST_IS_BASE_PARSE (parse)); + + pts = gst_adapter_prev_pts_at_offset (parse->priv->adapter, offset, NULL); + dts = gst_adapter_prev_dts_at_offset (parse->priv->adapter, offset, NULL); + + if (!GST_CLOCK_TIME_IS_VALID (pts) || !GST_CLOCK_TIME_IS_VALID (dts)) { + GST_DEBUG_OBJECT (parse, + "offset adapter timestamps dts=%" GST_TIME_FORMAT " pts=%" + GST_TIME_FORMAT, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts)); + } + if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) + parse->priv->prev_pts = parse->priv->next_pts = pts; + + if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts)) { + parse->priv->prev_dts = parse->priv->next_dts = dts; + parse->priv->prev_dts_from_pts = FALSE; + } +} + +/** + * gst_base_parse_merge_tags: + * @parse: a #GstBaseParse + * @tags: (allow-none): a #GstTagList to merge, or NULL to unset + * previously-set tags + * @mode: the #GstTagMergeMode to use, usually #GST_TAG_MERGE_REPLACE + * + * Sets the parser subclass's tags and how they should be merged with any + * upstream stream tags. This will override any tags previously-set + * with gst_base_parse_merge_tags(). + * + * Note that this is provided for convenience, and the subclass is + * not required to use this and can still do tag handling on its own. + * + * Since: 1.6 + */ +void +gst_base_parse_merge_tags (GstBaseParse * parse, GstTagList * tags, + GstTagMergeMode mode) +{ + g_return_if_fail (GST_IS_BASE_PARSE (parse)); + g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags)); + g_return_if_fail (tags == NULL || mode != GST_TAG_MERGE_UNDEFINED); + + GST_OBJECT_LOCK (parse); + + if (tags != parse->priv->parser_tags) { + if (parse->priv->parser_tags) { + gst_tag_list_unref (parse->priv->parser_tags); + parse->priv->parser_tags = NULL; + parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND; + } + if (tags) { + parse->priv->parser_tags = gst_tag_list_ref (tags); + parse->priv->parser_tags_merge_mode = mode; + } + + GST_DEBUG_OBJECT (parse, "setting parser tags to %" GST_PTR_FORMAT + " (mode %d)", tags, parse->priv->parser_tags_merge_mode); + + gst_base_parse_check_bitrate_tags (parse); + parse->priv->tags_changed = TRUE; + } + + GST_OBJECT_UNLOCK (parse); +} diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h new file mode 100644 index 0000000..26c7e7b --- /dev/null +++ b/libs/gst/base/gstbaseparse.h @@ -0,0 +1,373 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + * + * Contact: 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_PARSE_H__ +#define __GST_BASE_PARSE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_PARSE (gst_base_parse_get_type()) +#define GST_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_PARSE,GstBaseParse)) +#define GST_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_PARSE,GstBaseParseClass)) +#define GST_BASE_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_PARSE,GstBaseParseClass)) +#define GST_IS_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_PARSE)) +#define GST_IS_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_PARSE)) +#define GST_BASE_PARSE_CAST(obj) ((GstBaseParse *)(obj)) + +/** + * GST_BASE_PARSE_SRC_PAD: + * @obj: base parse instance + * + * Gives the pointer to the source #GstPad object of the element. + */ +#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) + +/** + * GST_BASE_PARSE_SINK_PAD: + * @obj: base parse instance + * + * Gives the pointer to the sink #GstPad object of the element. + */ +#define GST_BASE_PARSE_SINK_PAD(obj) (GST_BASE_PARSE_CAST (obj)->sinkpad) + +/** + * GST_BASE_PARSE_FLOW_DROPPED: + * + * A #GstFlowReturn that can be returned from parse_frame to + * indicate that no output buffer was generated, or from pre_push_frame to + * to forego pushing buffer. + */ +#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS + +/* not public API, use accessor macros below */ +#define GST_BASE_PARSE_FLAG_LOST_SYNC (1 << 0) +#define GST_BASE_PARSE_FLAG_DRAINING (1 << 1) + +/** + * GST_BASE_PARSE_LOST_SYNC: + * @parse: base parse instance + * + * Obtains current sync status. + */ +#define GST_BASE_PARSE_LOST_SYNC(parse) (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_LOST_SYNC)) + +/** + * GST_BASE_PARSE_DRAINING: + * @parse: base parse instance + * + * Obtains current drain status (ie. whether EOS has been received and + * the parser is now processing the frames at the end of the stream) + */ +#define GST_BASE_PARSE_DRAINING(parse) (!!(GST_BASE_PARSE_CAST(parse)->flags & GST_BASE_PARSE_FLAG_DRAINING)) + +/** + * GstBaseParseFrameFlags: + * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag + * @GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME: set by baseclass if current frame + * is passed for processing to the subclass for the first time + * (and not set on subsequent calls with same data). + * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be + * counted as frame, e.g. if this frame is dependent on a previous one. + * As it is not counted as a frame, bitrate increases but frame to time + * conversions are maintained. + * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_frame can set this to indicate + * that regular segment clipping can still be performed (as opposed to + * any custom one having been done). + * @GST_BASE_PARSE_FRAME_FLAG_DROP: indicates to @finish_frame that the + * the frame should be dropped (and might be handled internally by subclass) + * @GST_BASE_PARSE_FRAME_FLAG_QUEUE: indicates to @finish_frame that the + * the frame should be queued for now and processed fully later + * when the first non-queued frame is finished + * + * Flags to be used in a #GstBaseParseFrame. + */ +typedef enum { + GST_BASE_PARSE_FRAME_FLAG_NONE = 0, + GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME = (1 << 0), + GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 1), + GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 2), + GST_BASE_PARSE_FRAME_FLAG_DROP = (1 << 3), + GST_BASE_PARSE_FRAME_FLAG_QUEUE = (1 << 4) +} GstBaseParseFrameFlags; + +/** + * GstBaseParseFrame: + * @buffer: input data to be parsed for frames. + * @out_buffer: output data. + * @offset: media specific offset of input frame + * Note that a converter may have a different one on the frame's buffer. + * @overhead: subclass can set this to indicates the metadata overhead + * for the given frame, which is then used to enable more accurate bitrate + * computations. If this is -1, it is assumed that this frame should be + * skipped in bitrate calculation. + * @flags: a combination of input and output #GstBaseParseFrameFlags that + * convey additional context to subclass or allow subclass to tune + * subsequent #GstBaseParse actions. + * + * Frame (context) data passed to each frame parsing virtual methods. In + * addition to providing the data to be checked for a valid frame or an already + * identified frame, it conveys additional metadata or control information + * from and to the subclass w.r.t. the particular frame in question (rather + * than global parameters). Some of these may apply to each parsing stage, others + * only to some a particular one. These parameters are effectively zeroed at start + * of each frame's processing, i.e. parsing virtual method invocation sequence. + */ +typedef struct { + GstBuffer * buffer; + GstBuffer * out_buffer; + guint flags; + guint64 offset; + gint overhead; + /*< private >*/ + gint size; + guint _gst_reserved_i[2]; + gpointer _gst_reserved_p[2]; + guint _private_flags; +} GstBaseParseFrame; + +typedef struct _GstBaseParse GstBaseParse; +typedef struct _GstBaseParseClass GstBaseParseClass; +typedef struct _GstBaseParsePrivate GstBaseParsePrivate; + +/** + * GstBaseParse: + * @element: the parent element. + * + * The opaque #GstBaseParse data structure. + */ +struct _GstBaseParse { + /*< public >*/ + GstElement element; + + /*< protected >*/ + /* source and sink pads */ + GstPad *sinkpad; + GstPad *srcpad; + + guint flags; + + /* MT-protected (with STREAM_LOCK) */ + GstSegment segment; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; + GstBaseParsePrivate *priv; +}; + +/** + * GstBaseParseClass: + * @parent_class: the parent class + * @start: Optional. + * Called when the element starts processing. + * Allows opening external resources. + * @stop: Optional. + * Called when the element stops processing. + * Allows closing external resources. + * @set_sink_caps: Optional. + * Allows the subclass to be notified of the actual caps set. + * @get_sink_caps: Optional. + * Allows the subclass to do its own sink get caps if needed. + * @handle_frame: Parses the input data into valid frames as defined by subclass + * which should be passed to gst_base_parse_finish_frame(). + * The frame's input buffer is guaranteed writable, + * whereas the input frame ownership is held by caller + * (so subclass should make a copy if it needs to hang on). + * Input buffer (data) is provided by baseclass with as much + * metadata set as possible by baseclass according to upstream + * information and/or subclass settings, + * though subclass may still set buffer timestamp and duration + * if desired. + * @convert: Optional. + * Convert between formats. + * @sink_event: Optional. + * Event handler on the sink pad. This function should chain + * up to the parent implementation to let the default handler + * run. + * @src_event: Optional. + * Event handler on the source pad. Should chain up to the + * parent to let the default handler run. + * @pre_push_frame: Optional. + * Called just prior to pushing a frame (after any pending + * events have been sent) to give subclass a chance to perform + * additional actions at this time (e.g. tag sending) or to + * decide whether this buffer should be dropped or not + * (e.g. custom segment clipping). + * @detect: Optional. + * Called until it doesn't return GST_FLOW_OK anymore for + * the first buffers. Can be used by the subclass to detect + * the stream format. + * @sink_query: Optional. + * Query handler on the sink pad. This function should chain + * up to the parent implementation to let the default handler + * run (Since 1.2) + * @src_query: Optional. + * Query handler on the source pad. Should chain up to the + * parent to let the default handler run (Since 1.2) + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At minimum @handle_frame needs to be overridden. + */ +struct _GstBaseParseClass { + GstElementClass parent_class; + + /*< public >*/ + /* virtual methods for subclasses */ + + gboolean (*start) (GstBaseParse * parse); + + gboolean (*stop) (GstBaseParse * parse); + + gboolean (*set_sink_caps) (GstBaseParse * parse, + GstCaps * caps); + + GstFlowReturn (*handle_frame) (GstBaseParse * parse, + GstBaseParseFrame * frame, + gint * skipsize); + + GstFlowReturn (*pre_push_frame) (GstBaseParse * parse, + GstBaseParseFrame * frame); + + gboolean (*convert) (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, + GstFormat dest_format, + gint64 * dest_value); + + gboolean (*sink_event) (GstBaseParse * parse, + GstEvent * event); + + gboolean (*src_event) (GstBaseParse * parse, + GstEvent * event); + + GstCaps * (*get_sink_caps) (GstBaseParse * parse, + GstCaps * filter); + + GstFlowReturn (*detect) (GstBaseParse * parse, + GstBuffer * buffer); + + gboolean (*sink_query) (GstBaseParse * parse, + GstQuery * query); + + gboolean (*src_query) (GstBaseParse * parse, + GstQuery * query); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE - 2]; +}; + +GST_BASE_API +GType gst_base_parse_get_type (void); + +GST_BASE_API +GType gst_base_parse_frame_get_type (void); + +GST_BASE_API +GstBaseParseFrame * gst_base_parse_frame_new (GstBuffer * buffer, + GstBaseParseFrameFlags flags, + gint overhead); +GST_BASE_API +void gst_base_parse_frame_init (GstBaseParseFrame * frame); + +GST_BASE_API +GstBaseParseFrame * gst_base_parse_frame_copy (GstBaseParseFrame * frame); +GST_BASE_API +void gst_base_parse_frame_free (GstBaseParseFrame * frame); + +GST_BASE_API +GstFlowReturn gst_base_parse_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); +GST_BASE_API +GstFlowReturn gst_base_parse_finish_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, + gint size); +GST_BASE_API +void gst_base_parse_set_duration (GstBaseParse * parse, + GstFormat fmt, + gint64 duration, + gint interval); +GST_BASE_API +void gst_base_parse_set_average_bitrate (GstBaseParse * parse, + guint bitrate); +GST_BASE_API +void gst_base_parse_set_min_frame_size (GstBaseParse * parse, + guint min_size); +GST_BASE_API +void gst_base_parse_set_has_timing_info (GstBaseParse * parse, + gboolean has_timing); +GST_BASE_API +void gst_base_parse_drain (GstBaseParse * parse); + +GST_BASE_API +void gst_base_parse_set_syncable (GstBaseParse * parse, + gboolean syncable); +GST_BASE_API +void gst_base_parse_set_passthrough (GstBaseParse * parse, + gboolean passthrough); +GST_BASE_API +void gst_base_parse_set_pts_interpolation (GstBaseParse * parse, + gboolean pts_interpolate); +GST_BASE_API +void gst_base_parse_set_infer_ts (GstBaseParse * parse, + gboolean infer_ts); +GST_BASE_API +void gst_base_parse_set_frame_rate (GstBaseParse * parse, + guint fps_num, + guint fps_den, + guint lead_in, + guint lead_out); +GST_BASE_API +void gst_base_parse_set_latency (GstBaseParse * parse, + GstClockTime min_latency, + GstClockTime max_latency); +GST_BASE_API +gboolean gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, + GstFormat dest_format, + gint64 * dest_value); +GST_BASE_API +gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, + guint64 offset, + GstClockTime ts, + gboolean key, + gboolean force); +GST_BASE_API +void gst_base_parse_set_ts_at_offset (GstBaseParse *parse, + gsize offset); +GST_BASE_API +void gst_base_parse_merge_tags (GstBaseParse * parse, + GstTagList * tags, + GstTagMergeMode mode); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParseFrame, gst_base_parse_frame_free) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseParse, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BASE_PARSE_H__ */ diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c new file mode 100644 index 0000000..ae02024 --- /dev/null +++ b/libs/gst/base/gstbasesink.c @@ -0,0 +1,5274 @@ +/* GStreamer + * Copyright (C) 2005-2007 Wim Taymans + * + * gstbasesink.c: Base class for sink 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbasesink + * @title: GstBaseSink + * @short_description: Base class for sink elements + * @see_also: #GstBaseTransform, #GstBaseSrc + * + * #GstBaseSink is the base class for sink elements in GStreamer, such as + * xvimagesink or filesink. It is a layer on top of #GstElement that provides a + * simplified interface to plugin writers. #GstBaseSink handles many details + * for you, for example: preroll, clock synchronization, state changes, + * activation in push or pull mode, and queries. + * + * In most cases, when writing sink elements, there is no need to implement + * class methods from #GstElement or to set functions on pads, because the + * #GstBaseSink infrastructure should be sufficient. + * + * #GstBaseSink provides support for exactly one sink pad, which should be + * named "sink". A sink implementation (subclass of #GstBaseSink) should + * install a pad template in its class_init function, like so: + * |[ + * static void + * my_element_class_init (GstMyElementClass *klass) + * { + * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + * + * // sinktemplate should be a #GstStaticPadTemplate with direction + * // %GST_PAD_SINK and name "sink" + * gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + * + * gst_element_class_set_static_metadata (gstelement_class, + * "Sink name", + * "Sink", + * "My Sink element", + * "The author "); + * } + * ]| + * + * #GstBaseSink will handle the prerolling correctly. This means that it will + * return %GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first + * buffer arrives in this element. The base class will call the + * #GstBaseSinkClass.preroll() vmethod with this preroll buffer and will then + * commit the state change to the next asynchronously pending state. + * + * When the element is set to PLAYING, #GstBaseSink will synchronise on the + * clock using the times returned from #GstBaseSinkClass.get_times(). If this + * function returns %GST_CLOCK_TIME_NONE for the start time, no synchronisation + * will be done. Synchronisation can be disabled entirely by setting the object + * #GstBaseSink:sync property to %FALSE. + * + * After synchronisation the virtual method #GstBaseSinkClass.render() will be + * called. Subclasses should minimally implement this method. + * + * Subclasses that synchronise on the clock in the #GstBaseSinkClass.render() + * method are supported as well. These classes typically receive a buffer in + * the render method and can then potentially block on the clock while + * rendering. A typical example is an audiosink. + * These subclasses can use gst_base_sink_wait_preroll() to perform the + * blocking wait. + * + * Upon receiving the EOS event in the PLAYING state, #GstBaseSink will wait + * for the clock to reach the time indicated by the stop time of the last + * #GstBaseSinkClass.get_times() call before posting an EOS message. When the + * element receives EOS in PAUSED, preroll completes, the event is queued and an + * EOS message is posted when going to PLAYING. + * + * #GstBaseSink will internally use the %GST_EVENT_SEGMENT events to schedule + * synchronisation and clipping of buffers. Buffers that fall completely outside + * of the current segment are dropped. Buffers that fall partially in the + * segment are rendered (and prerolled). Subclasses should do any subbuffer + * clipping themselves when needed. + * + * #GstBaseSink will by default report the current playback position in + * %GST_FORMAT_TIME based on the current clock time and segment information. + * If no clock has been set on the element, the query will be forwarded + * upstream. + * + * The #GstBaseSinkClass.set_caps() function will be called when the subclass + * should configure itself to process a specific media type. + * + * The #GstBaseSinkClass.start() and #GstBaseSinkClass.stop() virtual methods + * will be called when resources should be allocated. Any + * #GstBaseSinkClass.preroll(), #GstBaseSinkClass.render() and + * #GstBaseSinkClass.set_caps() function will be called between the + * #GstBaseSinkClass.start() and #GstBaseSinkClass.stop() calls. + * + * The #GstBaseSinkClass.event() virtual method will be called when an event is + * received by #GstBaseSink. Normally this method should only be overridden by + * very specific elements (such as file sinks) which need to handle the + * newsegment event specially. + * + * The #GstBaseSinkClass.unlock() method is called when the elements should + * unblock any blocking operations they perform in the + * #GstBaseSinkClass.render() method. This is mostly useful when the + * #GstBaseSinkClass.render() method performs a blocking write on a file + * descriptor, for example. + * + * The #GstBaseSink:max-lateness property affects how the sink deals with + * buffers that arrive too late in the sink. A buffer arrives too late in the + * sink when the presentation time (as a combination of the last segment, buffer + * timestamp and element base_time) plus the duration is before the current + * time of the clock. + * If the frame is later than max-lateness, the sink will drop the buffer + * without calling the render method. + * This feature is disabled if sync is disabled, the + * #GstBaseSinkClass.get_times() method does not return a valid start time or + * max-lateness is set to -1 (the default). + * Subclasses can use gst_base_sink_set_max_lateness() to configure the + * max-lateness value. + * + * The #GstBaseSink:qos property will enable the quality-of-service features of + * the basesink which gather statistics about the real-time performance of the + * clock synchronisation. For each buffer received in the sink, statistics are + * gathered and a QOS event is sent upstream with these numbers. This + * information can then be used by upstream elements to reduce their processing + * rate, for example. + * + * The #GstBaseSink:async property can be used to instruct the sink to never + * perform an ASYNC state change. This feature is mostly usable when dealing + * with non-synchronized streams or sparse streams. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "gstbasesink.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_base_sink_debug); +#define GST_CAT_DEFAULT gst_base_sink_debug + +#define GST_BASE_SINK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SINK, GstBaseSinkPrivate)) + +#define GST_FLOW_STEP GST_FLOW_CUSTOM_ERROR + +typedef struct +{ + gboolean valid; /* if this info is valid */ + guint32 seqnum; /* the seqnum of the STEP event */ + GstFormat format; /* the format of the amount */ + guint64 amount; /* the total amount of data to skip */ + guint64 position; /* the position in the stepped data */ + guint64 duration; /* the duration in time of the skipped data */ + guint64 start; /* running_time of the start */ + gdouble rate; /* rate of skipping */ + gdouble start_rate; /* rate before skipping */ + guint64 start_start; /* start position skipping */ + guint64 start_stop; /* stop position skipping */ + gboolean flush; /* if this was a flushing step */ + gboolean intermediate; /* if this is an intermediate step */ + gboolean need_preroll; /* if we need preroll after this step */ +} GstStepInfo; + +struct _GstBaseSinkPrivate +{ + gint qos_enabled; /* ATOMIC */ + gboolean async_enabled; + GstClockTimeDiff ts_offset; + GstClockTime render_delay; + + /* start, stop of current buffer, stream time, used to report position */ + GstClockTime current_sstart; + GstClockTime current_sstop; + + /* start, stop and jitter of current buffer, running time */ + GstClockTime current_rstart; + GstClockTime current_rstop; + GstClockTimeDiff current_jitter; + /* the running time of the previous buffer */ + GstClockTime prev_rstart; + + /* EOS sync time in running time */ + GstClockTime eos_rtime; + + /* last buffer that arrived in time, running time */ + GstClockTime last_render_time; + /* when the last buffer left the sink, running time */ + GstClockTime last_left; + + /* running averages go here these are done on running time */ + GstClockTime avg_pt, avg_in_diff; + gdouble avg_rate; /* average with infinite window */ + + /* number of rendered and dropped frames */ + guint64 rendered; + guint64 dropped; + + /* latency stuff */ + GstClockTime latency; + + /* if we already commited the state */ + gboolean commited; + /* state change to playing ongoing */ + gboolean to_playing; + + /* when we received EOS */ + gboolean received_eos; + + /* when we are prerolled and able to report latency */ + gboolean have_latency; + + /* the last buffer we prerolled or rendered. Useful for making snapshots */ + gint enable_last_sample; /* atomic */ + GstBuffer *last_buffer; + GstCaps *last_caps; + GstBufferList *last_buffer_list; + + /* negotiated caps */ + GstCaps *caps; + + /* blocksize for pulling */ + guint blocksize; + + gboolean discont; + + /* seqnum of the stream */ + guint32 seqnum; + + gboolean call_preroll; + gboolean step_unlock; + + /* we have a pending and a current step operation */ + GstStepInfo current_step; + GstStepInfo pending_step; + + /* Cached GstClockID */ + GstClockID cached_clock_id; + + /* for throttling and QoS */ + GstClockTime earliest_in_time; + GstClockTime throttle_time; + + /* for rate control */ + guint64 max_bitrate; + GstClockTime rc_time; + GstClockTime rc_next; + gsize rc_accumulated; + + gboolean drop_out_of_segment; +}; + +#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size)) + +/* generic running average, this has a neutral window size */ +#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8) + +/* the windows for these running averages are experimentally obtained. + * positive values get averaged more while negative values use a small + * window so we can react faster to badness. */ +#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16) +#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4) + +/* BaseSink properties */ + +#define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */ +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE + +#define DEFAULT_SYNC TRUE +#define DEFAULT_MAX_LATENESS -1 +#define DEFAULT_QOS FALSE +#define DEFAULT_ASYNC TRUE +#define DEFAULT_TS_OFFSET 0 +#define DEFAULT_BLOCKSIZE 4096 +#define DEFAULT_RENDER_DELAY 0 +#define DEFAULT_ENABLE_LAST_SAMPLE TRUE +#define DEFAULT_THROTTLE_TIME 0 +#define DEFAULT_MAX_BITRATE 0 +#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE + +enum +{ + PROP_0, + PROP_SYNC, + PROP_MAX_LATENESS, + PROP_QOS, + PROP_ASYNC, + PROP_TS_OFFSET, + PROP_ENABLE_LAST_SAMPLE, + PROP_LAST_SAMPLE, + PROP_BLOCKSIZE, + PROP_RENDER_DELAY, + PROP_THROTTLE_TIME, + PROP_MAX_BITRATE, + PROP_LAST +}; + +static GstElementClass *parent_class = NULL; + +static void gst_base_sink_class_init (GstBaseSinkClass * klass); +static void gst_base_sink_init (GstBaseSink * trans, gpointer g_class); +static void gst_base_sink_finalize (GObject * object); + +GType +gst_base_sink_get_type (void) +{ + static volatile gsize base_sink_type = 0; + + if (g_once_init_enter (&base_sink_type)) { + GType _type; + static const GTypeInfo base_sink_info = { + sizeof (GstBaseSinkClass), + NULL, + NULL, + (GClassInitFunc) gst_base_sink_class_init, + NULL, + NULL, + sizeof (GstBaseSink), + 0, + (GInstanceInitFunc) gst_base_sink_init, + }; + + _type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSink", &base_sink_info, G_TYPE_FLAG_ABSTRACT); + g_once_init_leave (&base_sink_type, _type); + } + return base_sink_type; +} + +static void gst_base_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_base_sink_send_event (GstElement * element, + GstEvent * event); +static gboolean default_element_query (GstElement * element, GstQuery * query); + +static GstCaps *gst_base_sink_default_get_caps (GstBaseSink * sink, + GstCaps * caps); +static gboolean gst_base_sink_default_set_caps (GstBaseSink * sink, + GstCaps * caps); +static void gst_base_sink_default_get_times (GstBaseSink * basesink, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_base_sink_set_flushing (GstBaseSink * basesink, + GstPad * pad, gboolean flushing); +static gboolean gst_base_sink_default_activate_pull (GstBaseSink * basesink, + gboolean active); +static gboolean gst_base_sink_default_do_seek (GstBaseSink * sink, + GstSegment * segment); +static gboolean gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink, + GstEvent * event, GstSegment * segment); + +static GstStateChangeReturn gst_base_sink_change_state (GstElement * element, + GstStateChange transition); + +static gboolean gst_base_sink_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_base_sink_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list); + +static void gst_base_sink_loop (GstPad * pad); +static gboolean gst_base_sink_pad_activate (GstPad * pad, GstObject * parent); +static gboolean gst_base_sink_pad_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_base_sink_default_event (GstBaseSink * basesink, + GstEvent * event); +static GstFlowReturn gst_base_sink_default_wait_event (GstBaseSink * basesink, + GstEvent * event); +static gboolean gst_base_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); + +static gboolean gst_base_sink_default_query (GstBaseSink * sink, + GstQuery * query); + +static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink); +static GstCaps *gst_base_sink_default_fixate (GstBaseSink * bsink, + GstCaps * caps); +static GstCaps *gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps); + +/* check if an object was too late */ +static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink, + GstMiniObject * obj, GstClockTime rstart, GstClockTime rstop, + GstClockReturn status, GstClockTimeDiff jitter, gboolean render); + +static void +gst_base_sink_class_init (GstBaseSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (gst_base_sink_debug, "basesink", 0, + "basesink element"); + + g_type_class_add_private (klass, sizeof (GstBaseSinkPrivate)); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_base_sink_finalize; + gobject_class->set_property = gst_base_sink_set_property; + gobject_class->get_property = gst_base_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_SYNC, + g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_LATENESS, + g_param_spec_int64 ("max-lateness", "Max Lateness", + "Maximum number of nanoseconds that a buffer can be late before it " + "is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_QOS, + g_param_spec_boolean ("qos", "Qos", + "Generate Quality-of-Service events upstream", DEFAULT_QOS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:async: + * + * If set to %TRUE, the basesink will perform asynchronous state changes. + * When set to %FALSE, the sink will not signal the parent when it prerolls. + * Use this option when dealing with sparse streams or when synchronisation is + * not required. + */ + g_object_class_install_property (gobject_class, PROP_ASYNC, + g_param_spec_boolean ("async", "Async", + "Go asynchronously to PAUSED", DEFAULT_ASYNC, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:ts-offset: + * + * Controls the final synchronisation, a negative value will render the buffer + * earlier while a positive value delays playback. This property can be + * used to fix synchronisation in bad files. + */ + g_object_class_install_property (gobject_class, PROP_TS_OFFSET, + g_param_spec_int64 ("ts-offset", "TS Offset", + "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64, + DEFAULT_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBaseSink:enable-last-sample: + * + * Enable the last-sample property. If %FALSE, basesink doesn't keep a + * reference to the last buffer arrived and the last-sample property is always + * set to %NULL. This can be useful if you need buffers to be released as soon + * as possible, eg. if you're using a buffer pool. + */ + g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE, + g_param_spec_boolean ("enable-last-sample", "Enable Last Buffer", + "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBaseSink:last-sample: + * + * The last buffer that arrived in the sink and was used for preroll or for + * rendering. This property can be used to generate thumbnails. This property + * can be %NULL when the sink has not yet received a buffer. + */ + g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE, + g_param_spec_boxed ("last-sample", "Last Sample", + "The last sample received in the sink", GST_TYPE_SAMPLE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:blocksize: + * + * The amount of bytes to pull when operating in pull mode. + */ + /* FIXME 2.0: blocksize property should be int, otherwise min>max.. */ + g_object_class_install_property (gobject_class, PROP_BLOCKSIZE, + g_param_spec_uint ("blocksize", "Block size", + "Size in bytes to pull per buffer (0 = default)", 0, G_MAXUINT, + DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:render-delay: + * + * The additional delay between synchronisation and actual rendering of the + * media. This property will add additional latency to the device in order to + * make other sinks compensate for the delay. + */ + g_object_class_install_property (gobject_class, PROP_RENDER_DELAY, + g_param_spec_uint64 ("render-delay", "Render Delay", + "Additional render delay of the sink in nanoseconds", 0, G_MAXUINT64, + DEFAULT_RENDER_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:throttle-time: + * + * The time to insert between buffers. This property can be used to control + * the maximum amount of buffers per second to render. Setting this property + * to a value bigger than 0 will make the sink create THROTTLE QoS events. + */ + g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME, + g_param_spec_uint64 ("throttle-time", "Throttle time", + "The time to keep between rendered buffers (0 = disabled)", 0, + G_MAXUINT64, DEFAULT_THROTTLE_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseSink:max-bitrate: + * + * Control the maximum amount of bits that will be rendered per second. + * Setting this property to a value bigger than 0 will make the sink delay + * rendering of the buffers when it would exceed to max-bitrate. + * + * Since: 1.2 + */ + g_object_class_install_property (gobject_class, PROP_MAX_BITRATE, + g_param_spec_uint64 ("max-bitrate", "Max Bitrate", + "The maximum bits per second to render (0 = disabled)", 0, + G_MAXUINT64, DEFAULT_MAX_BITRATE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_sink_change_state); + gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event); + gstelement_class->query = GST_DEBUG_FUNCPTR (default_element_query); + + klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_caps); + klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_set_caps); + klass->fixate = GST_DEBUG_FUNCPTR (gst_base_sink_default_fixate); + klass->activate_pull = + GST_DEBUG_FUNCPTR (gst_base_sink_default_activate_pull); + klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_times); + klass->query = GST_DEBUG_FUNCPTR (gst_base_sink_default_query); + klass->event = GST_DEBUG_FUNCPTR (gst_base_sink_default_event); + klass->wait_event = GST_DEBUG_FUNCPTR (gst_base_sink_default_wait_event); + + /* Registering debug symbols for function pointers */ + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_fixate); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_mode); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_event); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain_list); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_sink_query); +} + +static GstCaps * +gst_base_sink_query_caps (GstBaseSink * bsink, GstPad * pad, GstCaps * filter) +{ + GstBaseSinkClass *bclass; + GstCaps *caps = NULL; + gboolean fixed; + + bclass = GST_BASE_SINK_GET_CLASS (bsink); + fixed = GST_PAD_IS_FIXED_CAPS (pad); + + if (fixed || bsink->pad_mode == GST_PAD_MODE_PULL) { + /* if we are operating in pull mode or fixed caps, we only accept the + * currently negotiated caps */ + caps = gst_pad_get_current_caps (pad); + } + if (caps == NULL) { + if (bclass->get_caps) + caps = bclass->get_caps (bsink, filter); + + if (caps == NULL) { + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), + "sink"); + if (pad_template != NULL) { + caps = gst_pad_template_get_caps (pad_template); + + if (filter) { + GstCaps *intersection; + + intersection = + gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + caps = intersection; + } + } + } + } + + return caps; +} + +static GstCaps * +gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps) +{ + GST_DEBUG_OBJECT (bsink, "using default caps fixate function"); + return gst_caps_fixate (caps); +} + +static GstCaps * +gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps) +{ + GstBaseSinkClass *bclass; + + bclass = GST_BASE_SINK_GET_CLASS (bsink); + + if (bclass->fixate) + caps = bclass->fixate (bsink, caps); + + return caps; +} + +static void +gst_base_sink_init (GstBaseSink * basesink, gpointer g_class) +{ + GstPadTemplate *pad_template; + GstBaseSinkPrivate *priv; + + basesink->priv = priv = GST_BASE_SINK_GET_PRIVATE (basesink); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (pad_template != NULL); + + basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + + gst_pad_set_activate_function (basesink->sinkpad, gst_base_sink_pad_activate); + gst_pad_set_activatemode_function (basesink->sinkpad, + gst_base_sink_pad_activate_mode); + gst_pad_set_query_function (basesink->sinkpad, gst_base_sink_sink_query); + gst_pad_set_event_function (basesink->sinkpad, gst_base_sink_event); + gst_pad_set_chain_function (basesink->sinkpad, gst_base_sink_chain); + gst_pad_set_chain_list_function (basesink->sinkpad, gst_base_sink_chain_list); + gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad); + + basesink->pad_mode = GST_PAD_MODE_NONE; + g_mutex_init (&basesink->preroll_lock); + g_cond_init (&basesink->preroll_cond); + priv->have_latency = FALSE; + + basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH; + basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; + + basesink->sync = DEFAULT_SYNC; + basesink->max_lateness = DEFAULT_MAX_LATENESS; + g_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS); + priv->async_enabled = DEFAULT_ASYNC; + priv->ts_offset = DEFAULT_TS_OFFSET; + priv->render_delay = DEFAULT_RENDER_DELAY; + priv->blocksize = DEFAULT_BLOCKSIZE; + priv->cached_clock_id = NULL; + g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE); + priv->throttle_time = DEFAULT_THROTTLE_TIME; + priv->max_bitrate = DEFAULT_MAX_BITRATE; + + priv->drop_out_of_segment = DEFAULT_DROP_OUT_OF_SEGMENT; + + GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_SINK); +} + +static void +gst_base_sink_finalize (GObject * object) +{ + GstBaseSink *basesink; + + basesink = GST_BASE_SINK (object); + + g_mutex_clear (&basesink->preroll_lock); + g_cond_clear (&basesink->preroll_cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_base_sink_set_sync: + * @sink: the sink + * @sync: the new sync value. + * + * Configures @sink to synchronize on the clock or not. When + * @sync is %FALSE, incoming samples will be played as fast as + * possible. If @sync is %TRUE, the timestamps of the incoming + * buffers will be used to schedule the exact render time of its + * contents. + */ +void +gst_base_sink_set_sync (GstBaseSink * sink, gboolean sync) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->sync = sync; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_sync: + * @sink: the sink + * + * Checks if @sink is currently configured to synchronize against the + * clock. + * + * Returns: %TRUE if the sink is configured to synchronize against the clock. + */ +gboolean +gst_base_sink_get_sync (GstBaseSink * sink) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE); + + GST_OBJECT_LOCK (sink); + res = sink->sync; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_drop_out_of_segment: + * @sink: the sink + * @drop_out_of_segment: drop buffers outside the segment + * + * Configure @sink to drop buffers which are outside the current segment + * + * Since: 1.12 + */ +void +gst_base_sink_set_drop_out_of_segment (GstBaseSink * sink, + gboolean drop_out_of_segment) +{ + GstBaseSinkPrivate *priv; + + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + priv = GST_BASE_SINK_GET_PRIVATE (sink); + + GST_OBJECT_LOCK (sink); + priv->drop_out_of_segment = drop_out_of_segment; + GST_OBJECT_UNLOCK (sink); + +} + +/** + * gst_base_sink_get_drop_out_of_segment: + * @sink: the sink + * + * Checks if @sink is currently configured to drop buffers which are outside + * the current segment + * + * Returns: %TRUE if the sink is configured to drop buffers outside the + * current segment. + * + * Since: 1.12 + */ +gboolean +gst_base_sink_get_drop_out_of_segment (GstBaseSink * sink) +{ + GstBaseSinkPrivate *priv; + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE); + + priv = GST_BASE_SINK_GET_PRIVATE (sink); + + GST_OBJECT_LOCK (sink); + res = priv->drop_out_of_segment; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_max_lateness: + * @sink: the sink + * @max_lateness: the new max lateness value. + * + * Sets the new max lateness value to @max_lateness. This value is + * used to decide if a buffer should be dropped or not based on the + * buffer timestamp and the current clock time. A value of -1 means + * an unlimited time. + */ +void +gst_base_sink_set_max_lateness (GstBaseSink * sink, gint64 max_lateness) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->max_lateness = max_lateness; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_max_lateness: + * @sink: the sink + * + * Gets the max lateness value. See gst_base_sink_set_max_lateness() for + * more details. + * + * Returns: The maximum time in nanoseconds that a buffer can be late + * before it is dropped and not rendered. A value of -1 means an + * unlimited time. + */ +gint64 +gst_base_sink_get_max_lateness (GstBaseSink * sink) +{ + gint64 res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), -1); + + GST_OBJECT_LOCK (sink); + res = sink->max_lateness; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_qos_enabled: + * @sink: the sink + * @enabled: the new qos value. + * + * Configures @sink to send Quality-of-Service events upstream. + */ +void +gst_base_sink_set_qos_enabled (GstBaseSink * sink, gboolean enabled) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + g_atomic_int_set (&sink->priv->qos_enabled, enabled); +} + +/** + * gst_base_sink_is_qos_enabled: + * @sink: the sink + * + * Checks if @sink is currently configured to send Quality-of-Service events + * upstream. + * + * Returns: %TRUE if the sink is configured to perform Quality-of-Service. + */ +gboolean +gst_base_sink_is_qos_enabled (GstBaseSink * sink) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE); + + res = g_atomic_int_get (&sink->priv->qos_enabled); + + return res; +} + +/** + * gst_base_sink_set_async_enabled: + * @sink: the sink + * @enabled: the new async value. + * + * Configures @sink to perform all state changes asynchronously. When async is + * disabled, the sink will immediately go to PAUSED instead of waiting for a + * preroll buffer. This feature is useful if the sink does not synchronize + * against the clock or when it is dealing with sparse streams. + */ +void +gst_base_sink_set_async_enabled (GstBaseSink * sink, gboolean enabled) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_BASE_SINK_PREROLL_LOCK (sink); + g_atomic_int_set (&sink->priv->async_enabled, enabled); + GST_LOG_OBJECT (sink, "set async enabled to %d", enabled); + GST_BASE_SINK_PREROLL_UNLOCK (sink); +} + +/** + * gst_base_sink_is_async_enabled: + * @sink: the sink + * + * Checks if @sink is currently configured to perform asynchronous state + * changes to PAUSED. + * + * Returns: %TRUE if the sink is configured to perform asynchronous state + * changes. + */ +gboolean +gst_base_sink_is_async_enabled (GstBaseSink * sink) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE); + + res = g_atomic_int_get (&sink->priv->async_enabled); + + return res; +} + +/** + * gst_base_sink_set_ts_offset: + * @sink: the sink + * @offset: the new offset + * + * Adjust the synchronisation of @sink with @offset. A negative value will + * render buffers earlier than their timestamp. A positive value will delay + * rendering. This function can be used to fix playback of badly timestamped + * buffers. + */ +void +gst_base_sink_set_ts_offset (GstBaseSink * sink, GstClockTimeDiff offset) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->ts_offset = offset; + GST_LOG_OBJECT (sink, "set time offset to %" G_GINT64_FORMAT, offset); + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_ts_offset: + * @sink: the sink + * + * Get the synchronisation offset of @sink. + * + * Returns: The synchronisation offset. + */ +GstClockTimeDiff +gst_base_sink_get_ts_offset (GstBaseSink * sink) +{ + GstClockTimeDiff res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->ts_offset; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_get_last_sample: + * @sink: the sink + * + * Get the last sample that arrived in the sink and was used for preroll or for + * rendering. This property can be used to generate thumbnails. + * + * The #GstCaps on the sample can be used to determine the type of the buffer. + * + * Free-function: gst_sample_unref + * + * Returns: (transfer full) (nullable): a #GstSample. gst_sample_unref() after + * usage. This function returns %NULL when no buffer has arrived in the + * sink yet or when the sink is not in PAUSED or PLAYING. + */ +GstSample * +gst_base_sink_get_last_sample (GstBaseSink * sink) +{ + GstSample *res = NULL; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), NULL); + + GST_OBJECT_LOCK (sink); + if (sink->priv->last_buffer_list) { + GstBuffer *first_buffer = NULL; + + /* Set the first buffer in the list to last sample's buffer */ + first_buffer = gst_buffer_list_get (sink->priv->last_buffer_list, 0); + res = + gst_sample_new (first_buffer, sink->priv->last_caps, &sink->segment, + NULL); + gst_sample_set_buffer_list (res, sink->priv->last_buffer_list); + } else if (sink->priv->last_buffer) { + res = gst_sample_new (sink->priv->last_buffer, + sink->priv->last_caps, &sink->segment, NULL); + } + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/* with OBJECT_LOCK */ +static void +gst_base_sink_set_last_buffer_unlocked (GstBaseSink * sink, GstBuffer * buffer) +{ + GstBuffer *old; + + old = sink->priv->last_buffer; + if (G_LIKELY (old != buffer)) { + GST_DEBUG_OBJECT (sink, "setting last buffer to %p", buffer); + if (G_LIKELY (buffer)) + gst_buffer_ref (buffer); + sink->priv->last_buffer = buffer; + if (buffer) + /* copy over the caps */ + gst_caps_replace (&sink->priv->last_caps, sink->priv->caps); + else + gst_caps_replace (&sink->priv->last_caps, NULL); + } else { + old = NULL; + } + /* avoid unreffing with the lock because cleanup code might want to take the + * lock too */ + if (G_LIKELY (old)) { + GST_OBJECT_UNLOCK (sink); + gst_buffer_unref (old); + GST_OBJECT_LOCK (sink); + } +} + +/* with OBJECT_LOCK */ +static void +gst_base_sink_set_last_buffer_list_unlocked (GstBaseSink * sink, + GstBufferList * buffer_list) +{ + GstBufferList *old; + + old = sink->priv->last_buffer_list; + if (G_LIKELY (old != buffer_list)) { + GST_DEBUG_OBJECT (sink, "setting last buffer list to %p", buffer_list); + if (G_LIKELY (buffer_list)) + gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer_list)); + sink->priv->last_buffer_list = buffer_list; + } else { + old = NULL; + } + + /* avoid unreffing with the lock because cleanup code might want to take the + * lock too */ + if (G_LIKELY (old)) { + GST_OBJECT_UNLOCK (sink); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (old)); + GST_OBJECT_LOCK (sink); + } +} + +static void +gst_base_sink_set_last_buffer (GstBaseSink * sink, GstBuffer * buffer) +{ + if (!g_atomic_int_get (&sink->priv->enable_last_sample)) + return; + + GST_OBJECT_LOCK (sink); + gst_base_sink_set_last_buffer_unlocked (sink, buffer); + GST_OBJECT_UNLOCK (sink); +} + +static void +gst_base_sink_set_last_buffer_list (GstBaseSink * sink, + GstBufferList * buffer_list) +{ + if (!g_atomic_int_get (&sink->priv->enable_last_sample)) + return; + + GST_OBJECT_LOCK (sink); + gst_base_sink_set_last_buffer_list_unlocked (sink, buffer_list); + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_set_last_sample_enabled: + * @sink: the sink + * @enabled: the new enable-last-sample value. + * + * Configures @sink to store the last received sample in the last-sample + * property. + */ +void +gst_base_sink_set_last_sample_enabled (GstBaseSink * sink, gboolean enabled) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + /* Only take lock if we change the value */ + if (g_atomic_int_compare_and_exchange (&sink->priv->enable_last_sample, + !enabled, enabled) && !enabled) { + GST_OBJECT_LOCK (sink); + gst_base_sink_set_last_buffer_unlocked (sink, NULL); + gst_base_sink_set_last_buffer_list_unlocked (sink, NULL); + GST_OBJECT_UNLOCK (sink); + } +} + +/** + * gst_base_sink_is_last_sample_enabled: + * @sink: the sink + * + * Checks if @sink is currently configured to store the last received sample in + * the last-sample property. + * + * Returns: %TRUE if the sink is configured to store the last received sample. + */ +gboolean +gst_base_sink_is_last_sample_enabled (GstBaseSink * sink) +{ + g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE); + + return g_atomic_int_get (&sink->priv->enable_last_sample); +} + +/** + * gst_base_sink_get_latency: + * @sink: the sink + * + * Get the currently configured latency. + * + * Returns: The configured latency. + */ +GstClockTime +gst_base_sink_get_latency (GstBaseSink * sink) +{ + GstClockTime res; + + GST_OBJECT_LOCK (sink); + res = sink->priv->latency; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_query_latency: + * @sink: the sink + * @live: (out) (allow-none): if the sink is live + * @upstream_live: (out) (allow-none): if an upstream element is live + * @min_latency: (out) (allow-none): the min latency of the upstream elements + * @max_latency: (out) (allow-none): the max latency of the upstream elements + * + * Query the sink for the latency parameters. The latency will be queried from + * the upstream elements. @live will be %TRUE if @sink is configured to + * synchronize against the clock. @upstream_live will be %TRUE if an upstream + * element is live. + * + * If both @live and @upstream_live are %TRUE, the sink will want to compensate + * for the latency introduced by the upstream elements by setting the + * @min_latency to a strictly positive value. + * + * This function is mostly used by subclasses. + * + * Returns: %TRUE if the query succeeded. + */ +gboolean +gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live, + gboolean * upstream_live, GstClockTime * min_latency, + GstClockTime * max_latency) +{ + gboolean l, us_live, res, have_latency; + GstClockTime min, max, render_delay; + GstQuery *query; + GstClockTime us_min, us_max; + + /* we are live when we sync to the clock */ + GST_OBJECT_LOCK (sink); + l = sink->sync; + have_latency = sink->priv->have_latency; + render_delay = sink->priv->render_delay; + GST_OBJECT_UNLOCK (sink); + + /* assume no latency */ + min = 0; + max = -1; + us_live = FALSE; + + if (have_latency) { + GST_DEBUG_OBJECT (sink, "we are ready for LATENCY query"); + /* we are ready for a latency query this is when we preroll or when we are + * not async. */ + query = gst_query_new_latency (); + + /* ask the peer for the latency */ + if ((res = gst_pad_peer_query (sink->sinkpad, query))) { + /* get upstream min and max latency */ + gst_query_parse_latency (query, &us_live, &us_min, &us_max); + + if (us_live) { + /* upstream live, use its latency, subclasses should use these + * values to create the complete latency. */ + min = us_min; + max = us_max; + } + if (l) { + /* we need to add the render delay if we are live */ + min += render_delay; + if (max != -1) + max += render_delay; + } + } + gst_query_unref (query); + } else { + GST_DEBUG_OBJECT (sink, "we are not yet ready for LATENCY query"); + res = FALSE; + } + + /* not live, we tried to do the query, if it failed we return TRUE anyway */ + if (!res) { + if (!l) { + res = TRUE; + GST_DEBUG_OBJECT (sink, "latency query failed but we are not live"); + } else { + GST_DEBUG_OBJECT (sink, "latency query failed and we are live"); + } + } + + if (res) { + GST_DEBUG_OBJECT (sink, "latency query: live: %d, have_latency %d," + " upstream: %d, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, l, + have_latency, us_live, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + if (live) + *live = l; + if (upstream_live) + *upstream_live = us_live; + if (min_latency) + *min_latency = min; + if (max_latency) + *max_latency = max; + } + return res; +} + +/** + * gst_base_sink_set_render_delay: + * @sink: a #GstBaseSink + * @delay: the new delay + * + * Set the render delay in @sink to @delay. The render delay is the time + * between actual rendering of a buffer and its synchronisation time. Some + * devices might delay media rendering which can be compensated for with this + * function. + * + * After calling this function, this sink will report additional latency and + * other sinks will adjust their latency to delay the rendering of their media. + * + * This function is usually called by subclasses. + */ +void +gst_base_sink_set_render_delay (GstBaseSink * sink, GstClockTime delay) +{ + GstClockTime old_render_delay; + + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + old_render_delay = sink->priv->render_delay; + sink->priv->render_delay = delay; + GST_LOG_OBJECT (sink, "set render delay to %" GST_TIME_FORMAT, + GST_TIME_ARGS (delay)); + GST_OBJECT_UNLOCK (sink); + + if (delay != old_render_delay) { + GST_DEBUG_OBJECT (sink, "posting latency changed"); + gst_element_post_message (GST_ELEMENT_CAST (sink), + gst_message_new_latency (GST_OBJECT_CAST (sink))); + } +} + +/** + * gst_base_sink_get_render_delay: + * @sink: a #GstBaseSink + * + * Get the render delay of @sink. see gst_base_sink_set_render_delay() for more + * information about the render delay. + * + * Returns: the render delay of @sink. + */ +GstClockTime +gst_base_sink_get_render_delay (GstBaseSink * sink) +{ + GstClockTimeDiff res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->render_delay; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_blocksize: + * @sink: a #GstBaseSink + * @blocksize: the blocksize in bytes + * + * Set the number of bytes that the sink will pull when it is operating in pull + * mode. + */ +/* FIXME 2.0: blocksize property should be int, otherwise min>max.. */ +void +gst_base_sink_set_blocksize (GstBaseSink * sink, guint blocksize) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->blocksize = blocksize; + GST_LOG_OBJECT (sink, "set blocksize to %u", blocksize); + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_blocksize: + * @sink: a #GstBaseSink + * + * Get the number of bytes that the sink will pull when it is operating in pull + * mode. + * + * Returns: the number of bytes @sink will pull in pull mode. + */ +/* FIXME 2.0: blocksize property should be int, otherwise min>max.. */ +guint +gst_base_sink_get_blocksize (GstBaseSink * sink) +{ + guint res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->blocksize; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_throttle_time: + * @sink: a #GstBaseSink + * @throttle: the throttle time in nanoseconds + * + * Set the time that will be inserted between rendered buffers. This + * can be used to control the maximum buffers per second that the sink + * will render. + */ +void +gst_base_sink_set_throttle_time (GstBaseSink * sink, guint64 throttle) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->throttle_time = throttle; + GST_LOG_OBJECT (sink, "set throttle_time to %" G_GUINT64_FORMAT, throttle); + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_throttle_time: + * @sink: a #GstBaseSink + * + * Get the time that will be inserted between frames to control the + * maximum buffers per second. + * + * Returns: the number of nanoseconds @sink will put between frames. + */ +guint64 +gst_base_sink_get_throttle_time (GstBaseSink * sink) +{ + guint64 res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->throttle_time; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_max_bitrate: + * @sink: a #GstBaseSink + * @max_bitrate: the max_bitrate in bits per second + * + * Set the maximum amount of bits per second that the sink will render. + * + * Since: 1.2 + */ +void +gst_base_sink_set_max_bitrate (GstBaseSink * sink, guint64 max_bitrate) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->max_bitrate = max_bitrate; + GST_LOG_OBJECT (sink, "set max_bitrate to %" G_GUINT64_FORMAT, max_bitrate); + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_max_bitrate: + * @sink: a #GstBaseSink + * + * Get the maximum amount of bits per second that the sink will render. + * + * Returns: the maximum number of bits per second @sink will render. + * + * Since: 1.2 + */ +guint64 +gst_base_sink_get_max_bitrate (GstBaseSink * sink) +{ + guint64 res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->max_bitrate; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +static void +gst_base_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseSink *sink = GST_BASE_SINK (object); + + switch (prop_id) { + case PROP_SYNC: + gst_base_sink_set_sync (sink, g_value_get_boolean (value)); + break; + case PROP_MAX_LATENESS: + gst_base_sink_set_max_lateness (sink, g_value_get_int64 (value)); + break; + case PROP_QOS: + gst_base_sink_set_qos_enabled (sink, g_value_get_boolean (value)); + break; + case PROP_ASYNC: + gst_base_sink_set_async_enabled (sink, g_value_get_boolean (value)); + break; + case PROP_TS_OFFSET: + gst_base_sink_set_ts_offset (sink, g_value_get_int64 (value)); + break; + case PROP_BLOCKSIZE: + gst_base_sink_set_blocksize (sink, g_value_get_uint (value)); + break; + case PROP_RENDER_DELAY: + gst_base_sink_set_render_delay (sink, g_value_get_uint64 (value)); + break; + case PROP_ENABLE_LAST_SAMPLE: + gst_base_sink_set_last_sample_enabled (sink, g_value_get_boolean (value)); + break; + case PROP_THROTTLE_TIME: + gst_base_sink_set_throttle_time (sink, g_value_get_uint64 (value)); + break; + case PROP_MAX_BITRATE: + gst_base_sink_set_max_bitrate (sink, g_value_get_uint64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBaseSink *sink = GST_BASE_SINK (object); + + switch (prop_id) { + case PROP_SYNC: + g_value_set_boolean (value, gst_base_sink_get_sync (sink)); + break; + case PROP_MAX_LATENESS: + g_value_set_int64 (value, gst_base_sink_get_max_lateness (sink)); + break; + case PROP_QOS: + g_value_set_boolean (value, gst_base_sink_is_qos_enabled (sink)); + break; + case PROP_ASYNC: + g_value_set_boolean (value, gst_base_sink_is_async_enabled (sink)); + break; + case PROP_TS_OFFSET: + g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink)); + break; + case PROP_LAST_SAMPLE: + gst_value_take_sample (value, gst_base_sink_get_last_sample (sink)); + break; + case PROP_ENABLE_LAST_SAMPLE: + g_value_set_boolean (value, gst_base_sink_is_last_sample_enabled (sink)); + break; + case PROP_BLOCKSIZE: + g_value_set_uint (value, gst_base_sink_get_blocksize (sink)); + break; + case PROP_RENDER_DELAY: + g_value_set_uint64 (value, gst_base_sink_get_render_delay (sink)); + break; + case PROP_THROTTLE_TIME: + g_value_set_uint64 (value, gst_base_sink_get_throttle_time (sink)); + break; + case PROP_MAX_BITRATE: + g_value_set_uint64 (value, gst_base_sink_get_max_bitrate (sink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static GstCaps * +gst_base_sink_default_get_caps (GstBaseSink * sink, GstCaps * filter) +{ + return NULL; +} + +static gboolean +gst_base_sink_default_set_caps (GstBaseSink * sink, GstCaps * caps) +{ + return TRUE; +} + +/* with PREROLL_LOCK, STREAM_LOCK */ +static gboolean +gst_base_sink_commit_state (GstBaseSink * basesink) +{ + /* commit state and proceed to next pending state */ + GstState current, next, pending, post_pending; + gboolean post_paused = FALSE; + gboolean post_async_done = FALSE; + gboolean post_playing = FALSE; + + /* we are certainly not playing async anymore now */ + basesink->playing_async = FALSE; + + GST_OBJECT_LOCK (basesink); + current = GST_STATE (basesink); + next = GST_STATE_NEXT (basesink); + pending = GST_STATE_PENDING (basesink); + post_pending = pending; + + switch (pending) { + case GST_STATE_PLAYING: + { + GST_DEBUG_OBJECT (basesink, "commiting state to PLAYING"); + + basesink->need_preroll = FALSE; + post_async_done = TRUE; + basesink->priv->commited = TRUE; + post_playing = TRUE; + /* post PAUSED too when we were READY */ + if (current == GST_STATE_READY) { + post_paused = TRUE; + } + break; + } + case GST_STATE_PAUSED: + GST_DEBUG_OBJECT (basesink, "commiting state to PAUSED"); + post_paused = TRUE; + post_async_done = TRUE; + basesink->priv->commited = TRUE; + post_pending = GST_STATE_VOID_PENDING; + break; + case GST_STATE_READY: + case GST_STATE_NULL: + goto stopping; + case GST_STATE_VOID_PENDING: + goto nothing_pending; + default: + break; + } + + /* we can report latency queries now */ + basesink->priv->have_latency = TRUE; + + GST_STATE (basesink) = pending; + GST_STATE_NEXT (basesink) = GST_STATE_VOID_PENDING; + GST_STATE_PENDING (basesink) = GST_STATE_VOID_PENDING; + GST_STATE_RETURN (basesink) = GST_STATE_CHANGE_SUCCESS; + GST_OBJECT_UNLOCK (basesink); + + if (post_paused) { + GST_DEBUG_OBJECT (basesink, "posting PAUSED state change message"); + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_state_changed (GST_OBJECT_CAST (basesink), + current, next, post_pending)); + } + if (post_async_done) { + GST_DEBUG_OBJECT (basesink, "posting async-done message"); + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_async_done (GST_OBJECT_CAST (basesink), + GST_CLOCK_TIME_NONE)); + } + if (post_playing) { + if (post_paused) { + GstElementClass *klass; + + klass = GST_ELEMENT_GET_CLASS (basesink); + basesink->have_preroll = TRUE; + /* after releasing this lock, the state change function + * can execute concurrently with this thread. There is nothing we do to + * prevent this for now. subclasses should be prepared to handle it. */ + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + + if (klass->change_state) + klass->change_state (GST_ELEMENT_CAST (basesink), + GST_STATE_CHANGE_PAUSED_TO_PLAYING); + + GST_BASE_SINK_PREROLL_LOCK (basesink); + /* state change function could have been executed and we could be + * flushing now */ + if (G_UNLIKELY (basesink->flushing)) + goto stopping_unlocked; + } + GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message"); + /* FIXME, we released the PREROLL lock above, it's possible that this + * message is not correct anymore when the element went back to PAUSED */ + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_state_changed (GST_OBJECT_CAST (basesink), + next, pending, GST_STATE_VOID_PENDING)); + } + + GST_STATE_BROADCAST (basesink); + + return TRUE; + +nothing_pending: + { + /* Depending on the state, set our vars. We get in this situation when the + * state change function got a change to update the state vars before the + * streaming thread did. This is fine but we need to make sure that we + * update the need_preroll var since it was %TRUE when we got here and might + * become %FALSE if we got to PLAYING. */ + GST_DEBUG_OBJECT (basesink, "nothing to commit, now in %s", + gst_element_state_get_name (current)); + switch (current) { + case GST_STATE_PLAYING: + basesink->need_preroll = FALSE; + break; + case GST_STATE_PAUSED: + basesink->need_preroll = TRUE; + break; + default: + basesink->need_preroll = FALSE; + basesink->flushing = TRUE; + break; + } + /* we can report latency queries now */ + basesink->priv->have_latency = TRUE; + GST_OBJECT_UNLOCK (basesink); + return TRUE; + } +stopping_unlocked: + { + GST_OBJECT_LOCK (basesink); + goto stopping; + } +stopping: + { + /* app is going to READY */ + GST_DEBUG_OBJECT (basesink, "stopping"); + basesink->need_preroll = FALSE; + basesink->flushing = TRUE; + GST_OBJECT_UNLOCK (basesink); + return FALSE; + } +} + +static void +start_stepping (GstBaseSink * sink, GstSegment * segment, + GstStepInfo * pending, GstStepInfo * current) +{ + gint64 end; + GstMessage *message; + + GST_DEBUG_OBJECT (sink, "update pending step"); + + GST_OBJECT_LOCK (sink); + memcpy (current, pending, sizeof (GstStepInfo)); + pending->valid = FALSE; + GST_OBJECT_UNLOCK (sink); + + /* post message first */ + message = + gst_message_new_step_start (GST_OBJECT (sink), TRUE, current->format, + current->amount, current->rate, current->flush, current->intermediate); + gst_message_set_seqnum (message, current->seqnum); + gst_element_post_message (GST_ELEMENT (sink), message); + + /* get the running time of where we paused and remember it */ + current->start = gst_element_get_start_time (GST_ELEMENT_CAST (sink)); + gst_segment_set_running_time (segment, GST_FORMAT_TIME, current->start); + + /* set the new rate for the remainder of the segment */ + current->start_rate = segment->rate; + segment->rate *= current->rate; + + /* save values */ + if (segment->rate > 0.0) + current->start_stop = segment->stop; + else + current->start_start = segment->start; + + if (current->format == GST_FORMAT_TIME) { + /* calculate the running-time when the step operation should stop */ + if (current->amount != -1) + end = current->start + current->amount; + else + end = -1; + + if (!current->flush) { + gint64 position; + + /* update the segment clipping regions for non-flushing seeks */ + if (segment->rate > 0.0) { + if (end != -1) + position = + gst_segment_position_from_running_time (segment, GST_FORMAT_TIME, + end); + else + position = segment->stop; + + segment->stop = position; + segment->position = position; + } else { + if (end != -1) + position = + gst_segment_position_from_running_time (segment, GST_FORMAT_TIME, + end); + else + position = segment->start; + + segment->time = position; + segment->start = position; + segment->position = position; + } + } + } + + GST_DEBUG_OBJECT (sink, "segment now %" GST_SEGMENT_FORMAT, segment); + GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (current->start)); + + GST_DEBUG_OBJECT (sink, "step amount: %" G_GUINT64_FORMAT ", format: %s, " + "rate: %f", current->amount, gst_format_get_name (current->format), + current->rate); +} + +static void +stop_stepping (GstBaseSink * sink, GstSegment * segment, + GstStepInfo * current, gint64 rstart, gint64 rstop, gboolean eos) +{ + gint64 stop, position; + GstMessage *message; + + GST_DEBUG_OBJECT (sink, "step complete"); + + if (segment->rate > 0.0) + stop = rstart; + else + stop = rstop; + + GST_DEBUG_OBJECT (sink, + "step stop at running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (stop)); + + if (stop == -1) + current->duration = current->position; + else + current->duration = stop - current->start; + + GST_DEBUG_OBJECT (sink, "step elapsed running_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (current->duration)); + + position = current->start + current->duration; + + /* now move the segment to the new running time */ + gst_segment_set_running_time (segment, GST_FORMAT_TIME, position); + + if (current->flush) { + /* and remove the time we flushed, start time did not change */ + segment->base = current->start; + } else { + /* start time is now the stepped position */ + gst_element_set_start_time (GST_ELEMENT_CAST (sink), position); + } + + /* restore the previous rate */ + segment->rate = current->start_rate; + + if (segment->rate > 0.0) + segment->stop = current->start_stop; + else + segment->start = current->start_start; + + /* post the step done when we know the stepped duration in TIME */ + message = + gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format, + current->amount, current->rate, current->flush, current->intermediate, + current->duration, eos); + gst_message_set_seqnum (message, current->seqnum); + gst_element_post_message (GST_ELEMENT_CAST (sink), message); + + if (!current->intermediate) + sink->need_preroll = current->need_preroll; + + /* and the current step info finished and becomes invalid */ + current->valid = FALSE; +} + +static gboolean +handle_stepping (GstBaseSink * sink, GstSegment * segment, + GstStepInfo * current, guint64 * cstart, guint64 * cstop, guint64 * rstart, + guint64 * rstop) +{ + gboolean step_end = FALSE; + + /* stepping never stops */ + if (current->amount == -1) + return FALSE; + + /* see if we need to skip this buffer because of stepping */ + switch (current->format) { + case GST_FORMAT_TIME: + { + guint64 end; + guint64 first, last; + gdouble abs_rate; + + if (segment->rate > 0.0) { + if (segment->stop == *cstop) + *rstop = *rstart + current->amount; + + first = *rstart; + last = *rstop; + } else { + if (segment->start == *cstart) + *rstart = *rstop + current->amount; + + first = *rstop; + last = *rstart; + } + + end = current->start + current->amount; + current->position = first - current->start; + + abs_rate = ABS (segment->rate); + if (G_UNLIKELY (abs_rate != 1.0)) + current->position /= abs_rate; + + GST_DEBUG_OBJECT (sink, + "buffer: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (first), GST_TIME_ARGS (last)); + GST_DEBUG_OBJECT (sink, + "got time step %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "/%" + GST_TIME_FORMAT, GST_TIME_ARGS (current->position), + GST_TIME_ARGS (last - current->start), + GST_TIME_ARGS (current->amount)); + + if ((current->flush && current->position >= current->amount) + || last >= end) { + GST_DEBUG_OBJECT (sink, "step ended, we need clipping"); + step_end = TRUE; + if (segment->rate > 0.0) { + *rstart = end; + *cstart = + gst_segment_position_from_running_time (segment, GST_FORMAT_TIME, + end); + } else { + *rstop = end; + *cstop = + gst_segment_position_from_running_time (segment, GST_FORMAT_TIME, + end); + } + } + GST_DEBUG_OBJECT (sink, + "cstart %" GST_TIME_FORMAT ", rstart %" GST_TIME_FORMAT, + GST_TIME_ARGS (*cstart), GST_TIME_ARGS (*rstart)); + GST_DEBUG_OBJECT (sink, + "cstop %" GST_TIME_FORMAT ", rstop %" GST_TIME_FORMAT, + GST_TIME_ARGS (*cstop), GST_TIME_ARGS (*rstop)); + break; + } + case GST_FORMAT_BUFFERS: + GST_DEBUG_OBJECT (sink, + "got default step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + current->position, current->amount); + + if (current->position < current->amount) { + current->position++; + } else { + step_end = TRUE; + } + break; + case GST_FORMAT_DEFAULT: + default: + GST_DEBUG_OBJECT (sink, + "got unknown step %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + current->position, current->amount); + break; + } + return step_end; +} + +/* with STREAM_LOCK, PREROLL_LOCK + * + * Returns %TRUE if the object needs synchronisation and takes therefore + * part in prerolling. + * + * rsstart/rsstop contain the start/stop in stream time. + * rrstart/rrstop contain the start/stop in running time. + */ +static gboolean +gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj, + GstClockTime * rsstart, GstClockTime * rsstop, + GstClockTime * rrstart, GstClockTime * rrstop, GstClockTime * rrnext, + gboolean * do_sync, gboolean * stepped, GstStepInfo * step, + gboolean * step_end) +{ + GstBaseSinkClass *bclass; + GstClockTime start, stop; /* raw start/stop timestamps */ + guint64 cstart, cstop; /* clipped raw timestamps */ + guint64 rstart, rstop, rnext; /* clipped timestamps converted to running time */ + GstClockTime sstart, sstop; /* clipped timestamps converted to stream time */ + GstFormat format; + GstBaseSinkPrivate *priv; + GstSegment *segment; + gboolean eos; + + priv = basesink->priv; + segment = &basesink->segment; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + +again: + /* start with nothing */ + start = stop = GST_CLOCK_TIME_NONE; + eos = FALSE; + + if (G_UNLIKELY (GST_IS_EVENT (obj))) { + GstEvent *event = GST_EVENT_CAST (obj); + + switch (GST_EVENT_TYPE (event)) { + /* EOS event needs syncing */ + case GST_EVENT_EOS: + { + if (segment->rate >= 0.0) { + sstart = sstop = priv->current_sstop; + if (!GST_CLOCK_TIME_IS_VALID (sstart)) { + /* we have not seen a buffer yet, use the segment values */ + sstart = sstop = gst_segment_to_stream_time (segment, + segment->format, segment->stop); + } + } else { + sstart = sstop = priv->current_sstart; + if (!GST_CLOCK_TIME_IS_VALID (sstart)) { + /* we have not seen a buffer yet, use the segment values */ + sstart = sstop = gst_segment_to_stream_time (segment, + segment->format, segment->start); + } + } + + rstart = rstop = rnext = priv->eos_rtime; + *do_sync = GST_CLOCK_TIME_IS_VALID (rstart); + GST_DEBUG_OBJECT (basesink, "sync times for EOS %" GST_TIME_FORMAT, + GST_TIME_ARGS (rstart)); + /* if we are stepping, we end now */ + *step_end = step->valid; + eos = TRUE; + goto eos_done; + } + case GST_EVENT_GAP: + { + GstClockTime timestamp, duration; + gst_event_parse_gap (event, ×tamp, &duration); + + GST_DEBUG_OBJECT (basesink, "Got Gap time %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration)); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + start = timestamp; + if (GST_CLOCK_TIME_IS_VALID (duration)) + stop = start + duration; + } + *do_sync = TRUE; + break; + } + default: + /* other events do not need syncing */ + return FALSE; + } + } else { + /* else do buffer sync code */ + GstBuffer *buffer = GST_BUFFER_CAST (obj); + + /* just get the times to see if we need syncing, if the retuned start is -1 + * we don't sync. */ + if (bclass->get_times) + bclass->get_times (basesink, buffer, &start, &stop); + + if (!GST_CLOCK_TIME_IS_VALID (start)) { + /* we don't need to sync but we still want to get the timestamps for + * tracking the position */ + gst_base_sink_default_get_times (basesink, buffer, &start, &stop); + *do_sync = FALSE; + } else { + *do_sync = TRUE; + } + } + + GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT + ", stop: %" GST_TIME_FORMAT ", do_sync %d", GST_TIME_ARGS (start), + GST_TIME_ARGS (stop), *do_sync); + + /* collect segment and format for code clarity */ + format = segment->format; + + /* clip */ + if (G_UNLIKELY (!gst_segment_clip (segment, format, + start, stop, &cstart, &cstop))) { + if (step->valid) { + GST_DEBUG_OBJECT (basesink, "step out of segment"); + /* when we are stepping, pretend we're at the end of the segment */ + if (segment->rate > 0.0) { + cstart = segment->stop; + cstop = segment->stop; + } else { + cstart = segment->start; + cstop = segment->start; + } + goto do_times; + } + goto out_of_segment; + } + + if (G_UNLIKELY (start != cstart || stop != cstop)) { + GST_DEBUG_OBJECT (basesink, "clipped to: start %" GST_TIME_FORMAT + ", stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (cstart), + GST_TIME_ARGS (cstop)); + } + + /* set last stop position */ + if (G_LIKELY (stop != GST_CLOCK_TIME_NONE && cstop != GST_CLOCK_TIME_NONE)) + segment->position = cstop; + else + segment->position = cstart; + +do_times: + rstart = gst_segment_to_running_time (segment, format, cstart); + rstop = gst_segment_to_running_time (segment, format, cstop); + + if (GST_CLOCK_TIME_IS_VALID (stop)) + rnext = rstop; + else + rnext = rstart; + + if (G_UNLIKELY (step->valid)) { + if (!(*step_end = handle_stepping (basesink, segment, step, &cstart, &cstop, + &rstart, &rstop))) { + /* step is still busy, we discard data when we are flushing */ + *stepped = step->flush; + GST_DEBUG_OBJECT (basesink, "stepping busy"); + } + } + /* this can produce wrong values if we accumulated non-TIME segments. If this happens, + * upstream is behaving very badly */ + sstart = gst_segment_to_stream_time (segment, format, cstart); + sstop = gst_segment_to_stream_time (segment, format, cstop); + +eos_done: + /* eos_done label only called when doing EOS, we also stop stepping then */ + if (*step_end && step->flush) { + GST_DEBUG_OBJECT (basesink, "flushing step ended"); + stop_stepping (basesink, segment, step, rstart, rstop, eos); + *step_end = FALSE; + /* re-determine running start times for adjusted segment + * (which has a flushed amount of running/accumulated time removed) */ + if (!GST_IS_EVENT (obj)) { + GST_DEBUG_OBJECT (basesink, "refresh sync times"); + goto again; + } + } + + /* save times */ + *rsstart = sstart; + *rsstop = sstop; + *rrstart = rstart; + *rrstop = rstop; + *rrnext = rnext; + + /* buffers and EOS always need syncing and preroll */ + return TRUE; + + /* special cases */ +out_of_segment: + { + /* we usually clip in the chain function already but stepping could cause + * the segment to be updated later. we return %FALSE so that we don't try + * to sync on it. */ + GST_LOG_OBJECT (basesink, "buffer skipped, not in segment"); + return FALSE; + } +} + +/* with STREAM_LOCK, PREROLL_LOCK, LOCK + * adjust a timestamp with the latency and timestamp offset. This function does + * not adjust for the render delay. */ +static GstClockTime +gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time) +{ + GstClockTimeDiff ts_offset; + + /* don't do anything funny with invalid timestamps */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) + return time; + + time += basesink->priv->latency; + + /* apply offset, be careful for underflows */ + ts_offset = basesink->priv->ts_offset; + if (ts_offset < 0) { + ts_offset = -ts_offset; + if (ts_offset < time) + time -= ts_offset; + else + time = 0; + } else + time += ts_offset; + + /* subtract the render delay again, which was included in the latency */ + if (time > basesink->priv->render_delay) + time -= basesink->priv->render_delay; + else + time = 0; + + return time; +} + +/** + * gst_base_sink_wait_clock: + * @sink: the sink + * @time: the running_time to be reached + * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL + * + * This function will block until @time is reached. It is usually called by + * subclasses that use their own internal synchronisation. + * + * If @time is not valid, no synchronisation is done and %GST_CLOCK_BADTIME is + * returned. Likewise, if synchronisation is disabled in the element or there + * is no clock, no synchronisation is done and %GST_CLOCK_BADTIME is returned. + * + * This function should only be called with the PREROLL_LOCK held, like when + * receiving an EOS event in the #GstBaseSinkClass.event() vmethod or when + * receiving a buffer in + * the #GstBaseSinkClass.render() vmethod. + * + * The @time argument should be the running_time of when this method should + * return and is not adjusted with any latency or offset configured in the + * sink. + * + * Returns: #GstClockReturn + */ +GstClockReturn +gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time, + GstClockTimeDiff * jitter) +{ + GstClockReturn ret; + GstClock *clock; + GstClockTime base_time; + + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) + goto invalid_time; + + GST_OBJECT_LOCK (sink); + if (G_UNLIKELY (!sink->sync)) + goto no_sync; + + if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (sink)) == NULL)) + goto no_clock; + + base_time = GST_ELEMENT_CAST (sink)->base_time; + GST_LOG_OBJECT (sink, + "time %" GST_TIME_FORMAT ", base_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (time), GST_TIME_ARGS (base_time)); + + /* add base_time to running_time to get the time against the clock */ + time += base_time; + + /* Re-use existing clockid if available */ + /* FIXME: Casting to GstClockEntry only works because the types + * are the same */ + if (G_LIKELY (sink->priv->cached_clock_id != NULL + && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink-> + priv->cached_clock_id) == clock)) { + if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id, + time)) { + gst_clock_id_unref (sink->priv->cached_clock_id); + sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time); + } + } else { + if (sink->priv->cached_clock_id != NULL) + gst_clock_id_unref (sink->priv->cached_clock_id); + sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time); + } + GST_OBJECT_UNLOCK (sink); + + /* A blocking wait is performed on the clock. We save the ClockID + * so we can unlock the entry at any time. While we are blocking, we + * release the PREROLL_LOCK so that other threads can interrupt the + * entry. */ + sink->clock_id = sink->priv->cached_clock_id; + /* release the preroll lock while waiting */ + GST_BASE_SINK_PREROLL_UNLOCK (sink); + + ret = gst_clock_id_wait (sink->priv->cached_clock_id, jitter); + + GST_BASE_SINK_PREROLL_LOCK (sink); + sink->clock_id = NULL; + + return ret; + + /* no syncing needed */ +invalid_time: + { + GST_DEBUG_OBJECT (sink, "time not valid, no sync needed"); + return GST_CLOCK_BADTIME; + } +no_sync: + { + GST_DEBUG_OBJECT (sink, "sync disabled"); + GST_OBJECT_UNLOCK (sink); + return GST_CLOCK_BADTIME; + } +no_clock: + { + GST_DEBUG_OBJECT (sink, "no clock, can't sync"); + GST_OBJECT_UNLOCK (sink); + return GST_CLOCK_BADTIME; + } +} + +/** + * gst_base_sink_wait_preroll: + * @sink: the sink + * + * If the #GstBaseSinkClass.render() method performs its own synchronisation + * against the clock it must unblock when going from PLAYING to the PAUSED state + * and call this method before continuing to render the remaining data. + * + * If the #GstBaseSinkClass.render() method can block on something else than + * the clock, it must also be ready to unblock immediately on + * the #GstBaseSinkClass.unlock() method and cause the + * #GstBaseSinkClass.render() method to immediately call this function. + * In this case, the subclass must be prepared to continue rendering where it + * left off if this function returns %GST_FLOW_OK. + * + * This function will block until a state change to PLAYING happens (in which + * case this function returns %GST_FLOW_OK) or the processing must be stopped due + * to a state change to READY or a FLUSH event (in which case this function + * returns %GST_FLOW_FLUSHING). + * + * This function should only be called with the PREROLL_LOCK held, like in the + * render function. + * + * Returns: %GST_FLOW_OK if the preroll completed and processing can + * continue. Any other return value should be returned from the render vmethod. + */ +GstFlowReturn +gst_base_sink_wait_preroll (GstBaseSink * sink) +{ + sink->have_preroll = TRUE; + GST_DEBUG_OBJECT (sink, "waiting in preroll for flush or PLAYING"); + /* block until the state changes, or we get a flush, or something */ + GST_BASE_SINK_PREROLL_WAIT (sink); + sink->have_preroll = FALSE; + if (G_UNLIKELY (sink->flushing)) + goto stopping; + if (G_UNLIKELY (sink->priv->step_unlock)) + goto step_unlocked; + GST_DEBUG_OBJECT (sink, "continue after preroll"); + + return GST_FLOW_OK; + + /* ERRORS */ +stopping: + { + GST_DEBUG_OBJECT (sink, "preroll interrupted because of flush"); + return GST_FLOW_FLUSHING; + } +step_unlocked: + { + sink->priv->step_unlock = FALSE; + GST_DEBUG_OBJECT (sink, "preroll interrupted because of step"); + return GST_FLOW_STEP; + } +} + +/** + * gst_base_sink_do_preroll: + * @sink: the sink + * @obj: (transfer none): the mini object that caused the preroll + * + * If the @sink spawns its own thread for pulling buffers from upstream it + * should call this method after it has pulled a buffer. If the element needed + * to preroll, this function will perform the preroll and will then block + * until the element state is changed. + * + * This function should be called with the PREROLL_LOCK held. + * + * Returns: %GST_FLOW_OK if the preroll completed and processing can + * continue. Any other return value should be returned from the render vmethod. + */ +GstFlowReturn +gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj) +{ + GstFlowReturn ret; + + while (G_UNLIKELY (sink->need_preroll)) { + GST_DEBUG_OBJECT (sink, "prerolling object %p", obj); + + /* if it's a buffer, we need to call the preroll method */ + if (sink->priv->call_preroll) { + GstBaseSinkClass *bclass; + GstBuffer *buf; + + if (GST_IS_BUFFER_LIST (obj)) { + buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0); + gst_base_sink_set_last_buffer (sink, buf); + gst_base_sink_set_last_buffer_list (sink, GST_BUFFER_LIST_CAST (obj)); + g_assert (NULL != buf); + } else if (GST_IS_BUFFER (obj)) { + buf = GST_BUFFER_CAST (obj); + /* For buffer lists do not set last buffer for now */ + gst_base_sink_set_last_buffer (sink, buf); + gst_base_sink_set_last_buffer_list (sink, NULL); + } else { + buf = NULL; + } + + if (buf) { + GST_DEBUG_OBJECT (sink, "preroll buffer %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + bclass = GST_BASE_SINK_GET_CLASS (sink); + + if (bclass->prepare) + if ((ret = bclass->prepare (sink, buf)) != GST_FLOW_OK) + goto prepare_canceled; + + if (bclass->preroll) + if ((ret = bclass->preroll (sink, buf)) != GST_FLOW_OK) + goto preroll_canceled; + + sink->priv->call_preroll = FALSE; + } + } + + /* commit state */ + if (G_LIKELY (sink->playing_async)) { + if (G_UNLIKELY (!gst_base_sink_commit_state (sink))) + goto stopping; + } + + /* need to recheck here because the commit state could have + * made us not need the preroll anymore */ + if (G_LIKELY (sink->need_preroll)) { + /* block until the state changes, or we get a flush, or something */ + ret = gst_base_sink_wait_preroll (sink); + if ((ret != GST_FLOW_OK) && (ret != GST_FLOW_STEP)) + goto preroll_failed; + } + } + return GST_FLOW_OK; + + /* ERRORS */ +prepare_canceled: + { + GST_DEBUG_OBJECT (sink, "prepare failed, abort state"); + gst_element_abort_state (GST_ELEMENT_CAST (sink)); + return ret; + } +preroll_canceled: + { + GST_DEBUG_OBJECT (sink, "preroll failed, abort state"); + gst_element_abort_state (GST_ELEMENT_CAST (sink)); + return ret; + } +stopping: + { + GST_DEBUG_OBJECT (sink, "stopping while commiting state"); + return GST_FLOW_FLUSHING; + } +preroll_failed: + { + GST_DEBUG_OBJECT (sink, "preroll failed: %s", gst_flow_get_name (ret)); + return ret; + } +} + +/** + * gst_base_sink_wait: + * @sink: the sink + * @time: the running_time to be reached + * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL + * + * This function will wait for preroll to complete and will then block until @time + * is reached. It is usually called by subclasses that use their own internal + * synchronisation but want to let some synchronization (like EOS) be handled + * by the base class. + * + * This function should only be called with the PREROLL_LOCK held (like when + * receiving an EOS event in the ::event vmethod or when handling buffers in + * ::render). + * + * The @time argument should be the running_time of when the timeout should happen + * and will be adjusted with any latency and offset configured in the sink. + * + * Returns: #GstFlowReturn + */ +GstFlowReturn +gst_base_sink_wait (GstBaseSink * sink, GstClockTime time, + GstClockTimeDiff * jitter) +{ + GstClockReturn status; + GstFlowReturn ret; + + do { + GstClockTime stime; + + GST_DEBUG_OBJECT (sink, "checking preroll"); + + /* first wait for the playing state before we can continue */ + while (G_UNLIKELY (sink->need_preroll)) { + ret = gst_base_sink_wait_preroll (sink); + if ((ret != GST_FLOW_OK) && (ret != GST_FLOW_STEP)) + goto flushing; + } + + /* preroll done, we can sync since we are in PLAYING now. */ + GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %" + GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + /* compensate for latency, ts_offset and render delay */ + stime = gst_base_sink_adjust_time (sink, time); + + /* wait for the clock, this can be interrupted because we got shut down or + * we PAUSED. */ + status = gst_base_sink_wait_clock (sink, stime, jitter); + + GST_DEBUG_OBJECT (sink, "clock returned %d", status); + + /* 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 (sink->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_DEBUG_OBJECT (sink, "end of stream"); + + return GST_FLOW_OK; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (sink, "we are flushing"); + return GST_FLOW_FLUSHING; + } +} + +/* with STREAM_LOCK, PREROLL_LOCK + * + * Make sure we are in PLAYING and synchronize an object to the clock. + * + * If we need preroll, we are not in PLAYING. We try to commit the state + * if needed and then block if we still are not PLAYING. + * + * We start waiting on the clock in PLAYING. If we got interrupted, we + * immediately try to re-preroll. + * + * Some objects do not need synchronisation (most events) and so this function + * immediately returns GST_FLOW_OK. + * + * for objects that arrive later than max-lateness to be synchronized to the + * clock have the @late boolean set to %TRUE. + * + * This function keeps a running average of the jitter (the diff between the + * clock time and the requested sync time). The jitter is negative for + * objects that arrive in time and positive for late buffers. + * + * does not take ownership of obj. + */ +static GstFlowReturn +gst_base_sink_do_sync (GstBaseSink * basesink, + GstMiniObject * obj, gboolean * late, gboolean * step_end) +{ + GstClockTimeDiff jitter = 0; + gboolean syncable; + GstClockReturn status = GST_CLOCK_OK; + GstClockTime rstart, rstop, rnext, sstart, sstop, stime; + gboolean do_sync; + GstBaseSinkPrivate *priv; + GstFlowReturn ret; + GstStepInfo *current, *pending; + gboolean stepped; + + priv = basesink->priv; + +do_step: + sstart = sstop = rstart = rstop = rnext = GST_CLOCK_TIME_NONE; + do_sync = TRUE; + stepped = FALSE; + + priv->current_rstart = GST_CLOCK_TIME_NONE; + + /* get stepping info */ + current = &priv->current_step; + pending = &priv->pending_step; + + /* get timing information for this object against the render segment */ + syncable = gst_base_sink_get_sync_times (basesink, obj, + &sstart, &sstop, &rstart, &rstop, &rnext, &do_sync, &stepped, current, + step_end); + + if (G_UNLIKELY (stepped)) + goto step_skipped; + + /* a syncable object needs to participate in preroll and + * clocking. All buffers and EOS are syncable. */ + if (G_UNLIKELY (!syncable)) + goto not_syncable; + + /* store timing info for current object */ + priv->current_rstart = rstart; + priv->current_rstop = (GST_CLOCK_TIME_IS_VALID (rstop) ? rstop : rstart); + + /* save sync time for eos when the previous object needed sync */ + priv->eos_rtime = (do_sync ? rnext : GST_CLOCK_TIME_NONE); + + /* calculate inter frame spacing */ + if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (priv->prev_rstart) && + priv->prev_rstart < rstart)) { + GstClockTime in_diff; + + in_diff = rstart - priv->prev_rstart; + + if (priv->avg_in_diff == -1) + priv->avg_in_diff = in_diff; + else + priv->avg_in_diff = UPDATE_RUNNING_AVG (priv->avg_in_diff, in_diff); + + GST_LOG_OBJECT (basesink, "avg frame diff %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->avg_in_diff)); + + } + priv->prev_rstart = rstart; + + if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (priv->earliest_in_time) && + rstart < priv->earliest_in_time)) + goto qos_dropped; + +again: + /* first do preroll, this makes sure we commit our state + * to PAUSED and can continue to PLAYING. We cannot perform + * any clock sync in PAUSED because there is no clock. */ + ret = gst_base_sink_do_preroll (basesink, obj); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto preroll_failed; + + /* update the segment with a pending step if the current one is invalid and we + * have a new pending one. We only accept new step updates after a preroll */ + if (G_UNLIKELY (pending->valid && !current->valid)) { + start_stepping (basesink, &basesink->segment, pending, current); + goto do_step; + } + + /* After rendering we store the position of the last buffer so that we can use + * it to report the position. We need to take the lock here. */ + GST_OBJECT_LOCK (basesink); + priv->current_sstart = sstart; + priv->current_sstop = (GST_CLOCK_TIME_IS_VALID (sstop) ? sstop : sstart); + GST_OBJECT_UNLOCK (basesink); + + if (!do_sync) + goto done; + + /* adjust for latency */ + stime = gst_base_sink_adjust_time (basesink, rstart); + + /* adjust for rate control */ + if (priv->rc_next == -1 || (stime != -1 && stime >= priv->rc_next)) { + GST_DEBUG_OBJECT (basesink, "reset rc_time to time %" GST_TIME_FORMAT, + GST_TIME_ARGS (stime)); + priv->rc_time = stime; + priv->rc_accumulated = 0; + } else { + GST_DEBUG_OBJECT (basesink, "rate control next %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->rc_next)); + stime = priv->rc_next; + } + + /* preroll done, we can sync since we are in PLAYING now. */ + GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %" + GST_TIME_FORMAT ", adjusted %" GST_TIME_FORMAT, + GST_TIME_ARGS (rstart), GST_TIME_ARGS (stime)); + + /* This function will return immediately if start == -1, no clock + * or sync is disabled with GST_CLOCK_BADTIME. */ + status = gst_base_sink_wait_clock (basesink, stime, &jitter); + + GST_DEBUG_OBJECT (basesink, "clock returned %d, jitter %c%" GST_TIME_FORMAT, + status, (jitter < 0 ? '-' : ' '), GST_TIME_ARGS (ABS (jitter))); + + /* invalid time, no clock or sync disabled, just render */ + if (status == GST_CLOCK_BADTIME) + goto done; + + /* waiting could have been interrupted and we can be flushing now */ + if (G_UNLIKELY (basesink->flushing)) + goto flushing; + + /* check for unlocked by a state change, we are not flushing so + * we can try to preroll on the current buffer. */ + if (G_UNLIKELY (status == GST_CLOCK_UNSCHEDULED)) { + GST_DEBUG_OBJECT (basesink, "unscheduled, waiting some more"); + priv->call_preroll = TRUE; + goto again; + } + + /* successful syncing done, record observation */ + priv->current_jitter = jitter; + + /* check if the object should be dropped */ + *late = gst_base_sink_is_too_late (basesink, obj, rstart, rstop, + status, jitter, TRUE); + +done: + return GST_FLOW_OK; + + /* ERRORS */ +step_skipped: + { + GST_DEBUG_OBJECT (basesink, "skipped stepped object %p", obj); + *late = TRUE; + return GST_FLOW_OK; + } +not_syncable: + { + GST_DEBUG_OBJECT (basesink, "non syncable object %p", obj); + return GST_FLOW_OK; + } +qos_dropped: + { + GST_DEBUG_OBJECT (basesink, "dropped because of QoS %p", obj); + *late = TRUE; + return GST_FLOW_OK; + } +flushing: + { + GST_DEBUG_OBJECT (basesink, "we are flushing"); + return GST_FLOW_FLUSHING; + } +preroll_failed: + { + GST_DEBUG_OBJECT (basesink, "preroll failed"); + *step_end = FALSE; + return ret; + } +} + +static gboolean +gst_base_sink_send_qos (GstBaseSink * basesink, GstQOSType type, + gdouble proportion, GstClockTime time, GstClockTimeDiff diff) +{ + GstEvent *event; + gboolean res; + + /* generate Quality-of-Service event */ + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink, + "qos: type %d, proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %" + GST_TIME_FORMAT, type, proportion, diff, GST_TIME_ARGS (time)); + + event = gst_event_new_qos (type, proportion, diff, time); + + /* send upstream */ + res = gst_pad_push_event (basesink->sinkpad, event); + + return res; +} + +static void +gst_base_sink_perform_qos (GstBaseSink * sink, gboolean dropped) +{ + GstBaseSinkPrivate *priv; + GstClockTime start, stop; + GstClockTimeDiff jitter; + GstClockTime pt, entered, left; + GstClockTime duration; + gdouble rate; + + priv = sink->priv; + + start = priv->current_rstart; + + if (priv->current_step.valid) + return; + + /* if Quality-of-Service disabled, do nothing */ + if (!g_atomic_int_get (&priv->qos_enabled) || + !GST_CLOCK_TIME_IS_VALID (start)) + return; + + stop = priv->current_rstop; + jitter = priv->current_jitter; + + if (jitter < 0) { + /* this is the time the buffer entered the sink */ + if (start < -jitter) + entered = 0; + else + entered = start + jitter; + left = start; + } else { + /* this is the time the buffer entered the sink */ + entered = start + jitter; + /* this is the time the buffer left the sink */ + left = start + jitter; + } + + /* calculate duration of the buffer, only use buffer durations if not in + * trick mode or key-unit mode. Otherwise the buffer durations will be + * meaningless as frames are being dropped in-between without updating the + * durations. */ + duration = priv->avg_in_diff; + + /* if we have the time when the last buffer left us, calculate + * processing time */ + if (GST_CLOCK_TIME_IS_VALID (priv->last_left)) { + if (entered > priv->last_left) { + pt = entered - priv->last_left; + } else { + pt = 0; + } + } else { + pt = priv->avg_pt; + } + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, "start: %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", entered %" GST_TIME_FORMAT ", left %" + GST_TIME_FORMAT ", pt: %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ",jitter %" G_GINT64_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (entered), GST_TIME_ARGS (left), GST_TIME_ARGS (pt), + GST_TIME_ARGS (duration), jitter); + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, + "avg_pt: %" GST_TIME_FORMAT ", avg_rate: %g", + GST_TIME_ARGS (priv->avg_pt), priv->avg_rate); + + /* collect running averages. for first observations, we copy the + * values */ + if (!GST_CLOCK_TIME_IS_VALID (priv->avg_pt)) + priv->avg_pt = pt; + else + priv->avg_pt = UPDATE_RUNNING_AVG (priv->avg_pt, pt); + + if (duration != -1 && duration != 0) { + rate = + gst_guint64_to_gdouble (priv->avg_pt) / + gst_guint64_to_gdouble (duration); + } else { + rate = 1.0; + } + + if (GST_CLOCK_TIME_IS_VALID (priv->last_left)) { + if (dropped || priv->avg_rate < 0.0) { + priv->avg_rate = rate; + } else { + if (rate > 1.0) + priv->avg_rate = UPDATE_RUNNING_AVG_N (priv->avg_rate, rate); + else + priv->avg_rate = UPDATE_RUNNING_AVG_P (priv->avg_rate, rate); + } + } + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, sink, + "updated: avg_pt: %" GST_TIME_FORMAT + ", avg_rate: %g", GST_TIME_ARGS (priv->avg_pt), priv->avg_rate); + + + if (priv->avg_rate >= 0.0) { + GstQOSType type; + GstClockTimeDiff diff; + + /* if we have a valid rate, start sending QoS messages */ + if (priv->current_jitter < 0) { + /* make sure we never go below 0 when adding the jitter to the + * timestamp. */ + if (priv->current_rstart < -priv->current_jitter) + priv->current_jitter = -priv->current_rstart; + } + + if (priv->throttle_time > 0) { + diff = priv->throttle_time; + type = GST_QOS_TYPE_THROTTLE; + } else { + diff = priv->current_jitter; + if (diff <= 0) + type = GST_QOS_TYPE_OVERFLOW; + else + type = GST_QOS_TYPE_UNDERFLOW; + } + + gst_base_sink_send_qos (sink, type, priv->avg_rate, priv->current_rstart, + diff); + } + + /* record when this buffer will leave us */ + priv->last_left = left; +} + +/* reset all qos measuring */ +static void +gst_base_sink_reset_qos (GstBaseSink * sink) +{ + GstBaseSinkPrivate *priv; + + priv = sink->priv; + + priv->last_render_time = GST_CLOCK_TIME_NONE; + priv->prev_rstart = GST_CLOCK_TIME_NONE; + priv->earliest_in_time = GST_CLOCK_TIME_NONE; + priv->last_left = GST_CLOCK_TIME_NONE; + priv->avg_pt = GST_CLOCK_TIME_NONE; + priv->avg_rate = -1.0; + priv->avg_in_diff = GST_CLOCK_TIME_NONE; + priv->rendered = 0; + priv->dropped = 0; + +} + +/* Checks if the object was scheduled too late. + * + * rstart/rstop contain the running_time start and stop values + * of the object. + * + * status and jitter contain the return values from the clock wait. + * + * returns %TRUE if the buffer was too late. + */ +static gboolean +gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj, + GstClockTime rstart, GstClockTime rstop, + GstClockReturn status, GstClockTimeDiff jitter, gboolean render) +{ + gboolean late; + guint64 max_lateness; + GstBaseSinkPrivate *priv; + + priv = basesink->priv; + + late = FALSE; + + /* only for objects that were too late */ + if (G_LIKELY (status != GST_CLOCK_EARLY)) + goto in_time; + + max_lateness = basesink->max_lateness; + + /* check if frame dropping is enabled */ + if (max_lateness == -1) + goto no_drop; + + /* only check for buffers */ + if (G_UNLIKELY (!GST_IS_BUFFER (obj))) + goto not_buffer; + + /* can't do check if we don't have a timestamp */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (rstart))) + goto no_timestamp; + + /* we can add a valid stop time */ + if (GST_CLOCK_TIME_IS_VALID (rstop)) + max_lateness += rstop; + else { + max_lateness += rstart; + /* no stop time, use avg frame diff */ + if (priv->avg_in_diff != -1) + max_lateness += priv->avg_in_diff; + } + + /* if the jitter bigger than duration and lateness we are too late */ + if ((late = rstart + jitter > max_lateness)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink, + "buffer is too late %" GST_TIME_FORMAT + " > %" GST_TIME_FORMAT, GST_TIME_ARGS (rstart + jitter), + GST_TIME_ARGS (max_lateness)); + /* !!emergency!!, if we did not receive anything valid for more than a + * second, render it anyway so the user sees something */ + if (GST_CLOCK_TIME_IS_VALID (priv->last_render_time) && + rstart - priv->last_render_time > GST_SECOND) { + late = FALSE; + GST_ELEMENT_WARNING (basesink, CORE, CLOCK, + (_("A lot of buffers are being dropped.")), + ("There may be a timestamping problem, or this computer is too slow.")); + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, basesink, + "**emergency** last buffer at %" GST_TIME_FORMAT " > GST_SECOND", + GST_TIME_ARGS (priv->last_render_time)); + } + } + +done: + if (render && (!late || !GST_CLOCK_TIME_IS_VALID (priv->last_render_time))) { + priv->last_render_time = rstart; + /* the next allowed input timestamp */ + if (priv->throttle_time > 0) + priv->earliest_in_time = rstart + priv->throttle_time; + } + return late; + + /* all is fine */ +in_time: + { + GST_DEBUG_OBJECT (basesink, "object was scheduled in time"); + goto done; + } +no_drop: + { + GST_DEBUG_OBJECT (basesink, "frame dropping disabled"); + goto done; + } +not_buffer: + { + GST_DEBUG_OBJECT (basesink, "object is not a buffer"); + return FALSE; + } +no_timestamp: + { + GST_DEBUG_OBJECT (basesink, "buffer has no timestamp"); + return FALSE; + } +} + +static void +gst_base_sink_update_start_time (GstBaseSink * basesink) +{ + GstClock *clock; + + GST_OBJECT_LOCK (basesink); + if (GST_STATE (basesink) == GST_STATE_PLAYING + && (clock = GST_ELEMENT_CLOCK (basesink))) { + GstClockTime now; + + gst_object_ref (clock); + GST_OBJECT_UNLOCK (basesink); + + /* calculate the time when we stopped */ + now = gst_clock_get_time (clock); + gst_object_unref (clock); + + GST_OBJECT_LOCK (basesink); + /* store the current running time */ + if (GST_ELEMENT_START_TIME (basesink) != GST_CLOCK_TIME_NONE) { + if (now != GST_CLOCK_TIME_NONE) + GST_ELEMENT_START_TIME (basesink) = + now - GST_ELEMENT_CAST (basesink)->base_time; + else + GST_WARNING_OBJECT (basesink, + "Clock %s returned invalid time, can't calculate " + "running_time when going to the PAUSED state", + GST_OBJECT_NAME (clock)); + } + GST_DEBUG_OBJECT (basesink, + "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT + ", base_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_ELEMENT_START_TIME (basesink)), + GST_TIME_ARGS (now), + GST_TIME_ARGS (GST_ELEMENT_CAST (basesink)->base_time)); + } + GST_OBJECT_UNLOCK (basesink); +} + +static void +gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad) +{ + /* make sure we are not blocked on the clock also clear any pending + * eos state. */ + gst_base_sink_set_flushing (basesink, pad, TRUE); + + /* we grab the stream lock but that is not needed since setting the + * sink to flushing would make sure no state commit is being done + * anymore */ + GST_PAD_STREAM_LOCK (pad); + gst_base_sink_reset_qos (basesink); + /* and we need to commit our state again on the next + * prerolled buffer */ + basesink->playing_async = TRUE; + if (basesink->priv->async_enabled) { + gst_base_sink_update_start_time (basesink); + gst_element_lost_state (GST_ELEMENT_CAST (basesink)); + } else { + /* start time reset in above case as well; + * arranges for a.o. proper position reporting when flushing in PAUSED */ + gst_element_set_start_time (GST_ELEMENT_CAST (basesink), 0); + basesink->priv->have_latency = TRUE; + } + gst_base_sink_set_last_buffer (basesink, NULL); + gst_base_sink_set_last_buffer_list (basesink, NULL); + GST_PAD_STREAM_UNLOCK (pad); +} + +static void +gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad, + gboolean reset_time) +{ + /* unset flushing so we can accept new data, this also flushes out any EOS + * event. */ + gst_base_sink_set_flushing (basesink, pad, FALSE); + + /* for position reporting */ + GST_OBJECT_LOCK (basesink); + basesink->priv->current_sstart = GST_CLOCK_TIME_NONE; + basesink->priv->current_sstop = GST_CLOCK_TIME_NONE; + basesink->priv->eos_rtime = GST_CLOCK_TIME_NONE; + basesink->priv->call_preroll = TRUE; + basesink->priv->current_step.valid = FALSE; + basesink->priv->pending_step.valid = FALSE; + if (basesink->pad_mode == GST_PAD_MODE_PUSH) { + /* we need new segment info after the flush. */ + basesink->have_newsegment = FALSE; + if (reset_time) { + gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED); + GST_ELEMENT_START_TIME (basesink) = 0; + } + } + GST_OBJECT_UNLOCK (basesink); + + if (reset_time) { + GST_DEBUG_OBJECT (basesink, "posting reset-time message"); + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_reset_time (GST_OBJECT_CAST (basesink), 0)); + } +} + +static GstFlowReturn +gst_base_sink_default_wait_event (GstBaseSink * basesink, GstEvent * event) +{ + GstFlowReturn ret; + gboolean late, step_end = FALSE; + + ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (event), + &late, &step_end); + + return ret; +} + +static GstFlowReturn +gst_base_sink_wait_event (GstBaseSink * basesink, GstEvent * event) +{ + GstFlowReturn ret; + GstBaseSinkClass *bclass; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + if (G_LIKELY (bclass->wait_event)) + ret = bclass->wait_event (basesink, event); + else + ret = GST_FLOW_NOT_SUPPORTED; + + return ret; +} + +static gboolean +gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event) +{ + gboolean result = TRUE; + GstBaseSinkClass *bclass; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + { + GST_DEBUG_OBJECT (basesink, "flush-start %p", event); + gst_base_sink_flush_start (basesink, basesink->sinkpad); + break; + } + case GST_EVENT_FLUSH_STOP: + { + gboolean reset_time; + + gst_event_parse_flush_stop (event, &reset_time); + GST_DEBUG_OBJECT (basesink, "flush-stop %p, reset_time: %d", event, + reset_time); + gst_base_sink_flush_stop (basesink, basesink->sinkpad, reset_time); + break; + } + case GST_EVENT_EOS: + { + GstMessage *message; + guint32 seqnum; + + /* we set the received EOS flag here so that we can use it when testing if + * we are prerolled and to refuse more buffers. */ + basesink->priv->received_eos = TRUE; + + /* wait for EOS */ + if (G_UNLIKELY (gst_base_sink_wait_event (basesink, + event) != GST_FLOW_OK)) { + result = FALSE; + goto done; + } + + /* the EOS event is completely handled so we mark + * ourselves as being in the EOS state. eos is also + * protected by the object lock so we can read it when + * answering the POSITION query. */ + GST_OBJECT_LOCK (basesink); + basesink->eos = TRUE; + GST_OBJECT_UNLOCK (basesink); + + /* ok, now we can post the message */ + GST_DEBUG_OBJECT (basesink, "Now posting EOS"); + + seqnum = basesink->priv->seqnum = gst_event_get_seqnum (event); + GST_DEBUG_OBJECT (basesink, "Got seqnum #%" G_GUINT32_FORMAT, seqnum); + + message = gst_message_new_eos (GST_OBJECT_CAST (basesink)); + gst_message_set_seqnum (message, seqnum); + gst_element_post_message (GST_ELEMENT_CAST (basesink), message); + break; + } + case GST_EVENT_STREAM_START: + { + GstMessage *message; + guint32 seqnum; + guint group_id; + + seqnum = gst_event_get_seqnum (event); + GST_DEBUG_OBJECT (basesink, "Now posting STREAM_START (seqnum:%d)", + seqnum); + message = gst_message_new_stream_start (GST_OBJECT_CAST (basesink)); + if (gst_event_parse_group_id (event, &group_id)) { + gst_message_set_group_id (message, group_id); + } else { + GST_FIXME_OBJECT (basesink, "stream-start event without group-id. " + "Consider implementing group-id handling in the upstream " + "elements"); + } + gst_message_set_seqnum (message, seqnum); + gst_element_post_message (GST_ELEMENT_CAST (basesink), message); + break; + } + case GST_EVENT_CAPS: + { + GstCaps *caps, *current_caps; + + GST_DEBUG_OBJECT (basesink, "caps %p", event); + + gst_event_parse_caps (event, &caps); + current_caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (basesink)); + + if (current_caps && gst_caps_is_equal (current_caps, caps)) { + GST_DEBUG_OBJECT (basesink, + "New caps equal to old ones: %" GST_PTR_FORMAT, caps); + } else { + if (bclass->set_caps) + result = bclass->set_caps (basesink, caps); + + if (result) { + GST_OBJECT_LOCK (basesink); + gst_caps_replace (&basesink->priv->caps, caps); + GST_OBJECT_UNLOCK (basesink); + } + } + if (current_caps) + gst_caps_unref (current_caps); + break; + } + case GST_EVENT_SEGMENT: + /* configure the segment */ + /* The segment is protected with both the STREAM_LOCK and the OBJECT_LOCK. + * We protect with the OBJECT_LOCK so that we can use the values to + * safely answer a POSITION query. */ + GST_OBJECT_LOCK (basesink); + /* the newsegment event is needed to bring the buffer timestamps to the + * stream time and to drop samples outside of the playback segment. */ + gst_event_copy_segment (event, &basesink->segment); + GST_DEBUG_OBJECT (basesink, "configured segment %" GST_SEGMENT_FORMAT, + &basesink->segment); + basesink->have_newsegment = TRUE; + gst_base_sink_reset_qos (basesink); + GST_OBJECT_UNLOCK (basesink); + break; + case GST_EVENT_GAP: + { + if (G_UNLIKELY (gst_base_sink_wait_event (basesink, + event) != GST_FLOW_OK)) + result = FALSE; + break; + } + case GST_EVENT_TAG: + { + GstTagList *taglist; + + gst_event_parse_tag (event, &taglist); + + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_tag (GST_OBJECT_CAST (basesink), + gst_tag_list_copy (taglist))); + break; + } + case GST_EVENT_TOC: + { + GstToc *toc; + gboolean updated; + + gst_event_parse_toc (event, &toc, &updated); + + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_toc (GST_OBJECT_CAST (basesink), toc, updated)); + + gst_toc_unref (toc); + break; + } + case GST_EVENT_SINK_MESSAGE: + { + GstMessage *msg = NULL; + + gst_event_parse_sink_message (event, &msg); + if (msg) + gst_element_post_message (GST_ELEMENT_CAST (basesink), msg); + break; + } + default: + break; + } +done: + gst_event_unref (event); + + return result; +} + +static gboolean +gst_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstBaseSink *basesink; + gboolean result = TRUE; + GstBaseSinkClass *bclass; + + basesink = GST_BASE_SINK_CAST (parent); + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + GST_DEBUG_OBJECT (basesink, "received event %p %" GST_PTR_FORMAT, event, + event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + /* special case for this serialized event because we don't want to grab + * the PREROLL lock or check if we were flushing */ + if (bclass->event) + result = bclass->event (basesink, event); + break; + default: + if (GST_EVENT_IS_SERIALIZED (event)) { + GST_BASE_SINK_PREROLL_LOCK (basesink); + if (G_UNLIKELY (basesink->flushing)) + goto flushing; + + if (G_UNLIKELY (basesink->priv->received_eos)) + goto after_eos; + + if (bclass->event) + result = bclass->event (basesink, event); + + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + } else { + if (bclass->event) + result = bclass->event (basesink, event); + } + break; + } +done: + return result; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (basesink, "we are flushing"); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + gst_event_unref (event); + result = FALSE; + goto done; + } + +after_eos: + { + GST_DEBUG_OBJECT (basesink, "Event received after EOS, dropping"); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + gst_event_unref (event); + result = FALSE; + goto done; + } +} + +/* default implementation to calculate the start and end + * timestamps on a buffer, subclasses can override + */ +static void +gst_base_sink_default_get_times (GstBaseSink * basesink, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + GstClockTime timestamp, duration; + + /* first sync on DTS, else use PTS */ + timestamp = GST_BUFFER_DTS (buffer); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + timestamp = GST_BUFFER_PTS (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + duration = GST_BUFFER_DURATION (buffer); + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } +} + +/* must be called with PREROLL_LOCK */ +static gboolean +gst_base_sink_needs_preroll (GstBaseSink * basesink) +{ + gboolean is_prerolled, res; + + /* we have 2 cases where the PREROLL_LOCK is released: + * 1) we are blocking in the PREROLL_LOCK and thus are prerolled. + * 2) we are syncing on the clock + */ + is_prerolled = basesink->have_preroll || basesink->priv->received_eos; + res = !is_prerolled; + + GST_DEBUG_OBJECT (basesink, "have_preroll: %d, EOS: %d => needs preroll: %d", + basesink->have_preroll, basesink->priv->received_eos, res); + + return res; +} + +/* with STREAM_LOCK, PREROLL_LOCK + * + * Takes a buffer and compare the timestamps with the last segment. + * If the buffer falls outside of the segment boundaries, drop it. + * Else send the buffer for preroll and rendering. + * + * This function takes ownership of the buffer. + */ +static GstFlowReturn +gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad, + gpointer obj, gboolean is_list) +{ + GstBaseSinkClass *bclass; + GstBaseSinkPrivate *priv = basesink->priv; + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime start = GST_CLOCK_TIME_NONE, end = GST_CLOCK_TIME_NONE; + GstSegment *segment; + GstBuffer *sync_buf; + gboolean late, step_end, prepared = FALSE; + + if (G_UNLIKELY (basesink->flushing)) + goto flushing; + + if (G_UNLIKELY (priv->received_eos)) + goto was_eos; + + if (is_list) { + GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (obj); + + if (gst_buffer_list_length (buffer_list) == 0) + goto empty_list; + + sync_buf = gst_buffer_list_get (buffer_list, 0); + g_assert (NULL != sync_buf); + } else { + sync_buf = GST_BUFFER_CAST (obj); + } + + /* for code clarity */ + segment = &basesink->segment; + + if (G_UNLIKELY (!basesink->have_newsegment)) { + gboolean sync; + + sync = gst_base_sink_get_sync (basesink); + if (sync) { + GST_ELEMENT_WARNING (basesink, STREAM, FAILED, + (_("Internal data flow problem.")), + ("Received buffer without a new-segment. Assuming timestamps start from 0.")); + } + + /* this means this sink will assume timestamps start from 0 */ + GST_OBJECT_LOCK (basesink); + segment->start = 0; + segment->stop = -1; + basesink->segment.start = 0; + basesink->segment.stop = -1; + basesink->have_newsegment = TRUE; + GST_OBJECT_UNLOCK (basesink); + } + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + /* check if the buffer needs to be dropped, we first ask the subclass for the + * start and end */ + if (bclass->get_times) + bclass->get_times (basesink, sync_buf, &start, &end); + + if (!GST_CLOCK_TIME_IS_VALID (start)) { + /* if the subclass does not want sync, we use our own values so that we at + * least clip the buffer to the segment */ + gst_base_sink_default_get_times (basesink, sync_buf, &start, &end); + } + + GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT + ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end)); + + /* a dropped buffer does not participate in anything. Buffer can only be + * dropped if their PTS falls completly outside the segment, while we sync + * preferably on DTS */ + if (GST_CLOCK_TIME_IS_VALID (start) && (segment->format == GST_FORMAT_TIME)) { + GstClockTime pts = GST_BUFFER_PTS (sync_buf); + GstClockTime pts_end = GST_CLOCK_TIME_NONE; + + if (!GST_CLOCK_TIME_IS_VALID (pts)) + pts = start; + + if (GST_CLOCK_TIME_IS_VALID (end)) + pts_end = pts + (end - start); + + if (G_UNLIKELY (!gst_segment_clip (segment, + GST_FORMAT_TIME, pts, pts_end, NULL, NULL) + && priv->drop_out_of_segment)) + goto out_of_segment; + } + + if (bclass->prepare || bclass->prepare_list) { + gboolean do_sync = TRUE, stepped = FALSE, syncable = TRUE; + GstClockTime sstart, sstop, rstart, rstop, rnext; + GstStepInfo *current; + + late = FALSE; + step_end = FALSE; + + current = &priv->current_step; + syncable = + gst_base_sink_get_sync_times (basesink, obj, &sstart, &sstop, &rstart, + &rstop, &rnext, &do_sync, &stepped, current, &step_end); + + if (G_UNLIKELY (stepped)) + goto dropped; + + if (syncable && do_sync && gst_base_sink_get_sync (basesink)) { + GstClock *clock; + + GST_OBJECT_LOCK (basesink); + clock = GST_ELEMENT_CLOCK (basesink); + if (clock && GST_STATE (basesink) == GST_STATE_PLAYING) { + GstClockTime base_time; + GstClockTime stime; + GstClockTime now; + + base_time = GST_ELEMENT_CAST (basesink)->base_time; + stime = base_time + gst_base_sink_adjust_time (basesink, rstart); + now = gst_clock_get_time (clock); + GST_OBJECT_UNLOCK (basesink); + + late = + gst_base_sink_is_too_late (basesink, obj, rstart, rstop, + GST_CLOCK_EARLY, GST_CLOCK_DIFF (stime, now), FALSE); + } else { + GST_OBJECT_UNLOCK (basesink); + } + } + + /* We are about to prepare the first frame, make sure we have prerolled + * already. This prevent nesting prepare/render calls. */ + ret = gst_base_sink_do_preroll (basesink, obj); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto preroll_failed; + + if (G_UNLIKELY (late)) + goto dropped; + + if (!is_list) { + if (bclass->prepare) { + ret = bclass->prepare (basesink, GST_BUFFER_CAST (obj)); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto prepare_failed; + } + } else { + if (bclass->prepare_list) { + ret = bclass->prepare_list (basesink, GST_BUFFER_LIST_CAST (obj)); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto prepare_failed; + } + } + + prepared = TRUE; + } + +again: + late = FALSE; + step_end = FALSE; + + /* synchronize this object, non syncable objects return OK + * immediately. */ + ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (sync_buf), + &late, &step_end); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto sync_failed; + + /* Don't skip if prepare() was called on time */ + late = late && !prepared; + + /* drop late buffers unconditionally, let's hope it's unlikely */ + if (G_UNLIKELY (late)) + goto dropped; + + if (priv->max_bitrate) { + gsize size; + + if (is_list) + size = gst_buffer_list_calculate_size (GST_BUFFER_LIST_CAST (obj)); + else + size = gst_buffer_get_size (GST_BUFFER_CAST (obj)); + + priv->rc_accumulated += size; + priv->rc_next = priv->rc_time + gst_util_uint64_scale (priv->rc_accumulated, + 8 * GST_SECOND, priv->max_bitrate); + } + + GST_DEBUG_OBJECT (basesink, "rendering object %p", obj); + + if (!is_list) { + /* For buffer lists do not set last buffer for now. */ + gst_base_sink_set_last_buffer (basesink, GST_BUFFER_CAST (obj)); + gst_base_sink_set_last_buffer_list (basesink, NULL); + + if (bclass->render) + ret = bclass->render (basesink, GST_BUFFER_CAST (obj)); + } else { + GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (obj); + + if (bclass->render_list) + ret = bclass->render_list (basesink, buffer_list); + + /* Set the first buffer and buffer list to be included in last sample */ + gst_base_sink_set_last_buffer (basesink, sync_buf); + gst_base_sink_set_last_buffer_list (basesink, buffer_list); + } + + if (ret == GST_FLOW_STEP) + goto again; + + if (G_UNLIKELY (basesink->flushing)) + goto flushing; + + priv->rendered++; + +done: + if (step_end) { + /* the step ended, check if we need to activate a new step */ + GST_DEBUG_OBJECT (basesink, "step ended"); + stop_stepping (basesink, &basesink->segment, &priv->current_step, + priv->current_rstart, priv->current_rstop, basesink->eos); + goto again; + } + + gst_base_sink_perform_qos (basesink, late); + + GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + + return ret; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (basesink, "sink is flushing"); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return GST_FLOW_FLUSHING; + } +was_eos: + { + GST_DEBUG_OBJECT (basesink, "we are EOS, dropping object, return EOS"); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return GST_FLOW_EOS; + } +empty_list: + { + GST_DEBUG_OBJECT (basesink, "buffer list with no buffers"); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return GST_FLOW_OK; + } +out_of_segment: + { + GST_DEBUG_OBJECT (basesink, "dropping buffer, out of clipping segment"); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return GST_FLOW_OK; + } +prepare_failed: + { + GST_DEBUG_OBJECT (basesink, "prepare buffer failed %s", + gst_flow_get_name (ret)); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return ret; + } +sync_failed: + { + GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret)); + goto done; + } +dropped: + { + priv->dropped++; + GST_DEBUG_OBJECT (basesink, "buffer late, dropping"); + + if (g_atomic_int_get (&priv->qos_enabled)) { + GstMessage *qos_msg; + GstClockTime timestamp, duration; + + timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (sync_buf)); + duration = GST_BUFFER_DURATION (GST_BUFFER_CAST (sync_buf)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink, + "qos: dropped buffer rt %" GST_TIME_FORMAT ", st %" GST_TIME_FORMAT + ", ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->current_rstart), + GST_TIME_ARGS (priv->current_sstart), GST_TIME_ARGS (timestamp), + GST_TIME_ARGS (duration)); + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink, + "qos: rendered %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT, + priv->rendered, priv->dropped); + + qos_msg = + gst_message_new_qos (GST_OBJECT_CAST (basesink), basesink->sync, + priv->current_rstart, priv->current_sstart, timestamp, duration); + gst_message_set_qos_values (qos_msg, priv->current_jitter, priv->avg_rate, + 1000000); + gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, priv->rendered, + priv->dropped); + gst_element_post_message (GST_ELEMENT_CAST (basesink), qos_msg); + } + goto done; + } +preroll_failed: + { + GST_DEBUG_OBJECT (basesink, "preroll failed: %s", gst_flow_get_name (ret)); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + return ret; + } +} + +/* with STREAM_LOCK + */ +static GstFlowReturn +gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj, + gboolean is_list) +{ + GstFlowReturn result; + + if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH)) + goto wrong_mode; + + GST_BASE_SINK_PREROLL_LOCK (basesink); + result = gst_base_sink_chain_unlocked (basesink, pad, obj, is_list); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + +done: + return result; + + /* ERRORS */ +wrong_mode: + { + GST_OBJECT_LOCK (pad); + GST_WARNING_OBJECT (basesink, + "Push on pad %s:%s, but it was not activated in push mode", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj)); + /* we don't post an error message this will signal to the peer + * pushing that EOS is reached. */ + result = GST_FLOW_EOS; + goto done; + } +} + +static GstFlowReturn +gst_base_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GstBaseSink *basesink; + + basesink = GST_BASE_SINK (parent); + + return gst_base_sink_chain_main (basesink, pad, buf, FALSE); +} + +static GstFlowReturn +gst_base_sink_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list) +{ + GstBaseSink *basesink; + GstBaseSinkClass *bclass; + GstFlowReturn result; + + basesink = GST_BASE_SINK (parent); + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + if (G_LIKELY (bclass->render_list)) { + result = gst_base_sink_chain_main (basesink, pad, list, TRUE); + } else { + guint i, len; + GstBuffer *buffer; + + GST_LOG_OBJECT (pad, "chaining each buffer in list"); + + len = gst_buffer_list_length (list); + + result = GST_FLOW_OK; + for (i = 0; i < len; i++) { + buffer = gst_buffer_list_get (list, i); + result = gst_base_sink_chain_main (basesink, pad, + gst_buffer_ref (buffer), FALSE); + if (result != GST_FLOW_OK) + break; + } + gst_buffer_list_unref (list); + } + return result; +} + + +static gboolean +gst_base_sink_default_do_seek (GstBaseSink * sink, GstSegment * segment) +{ + gboolean res = TRUE; + + /* update our offset if the start/stop position was updated */ + if (segment->format == GST_FORMAT_BYTES) { + segment->time = segment->start; + } else if (segment->start == 0) { + /* seek to start, we can implement a default for this. */ + segment->time = 0; + } else { + res = FALSE; + GST_INFO_OBJECT (sink, "Can't do a default seek"); + } + + return res; +} + +#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET)) + +static gboolean +gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink, + GstEvent * event, GstSegment * segment) +{ + /* By default, we try one of 2 things: + * - For absolute seek positions, convert the requested position to our + * configured processing format and place it in the output segment \ + * - For relative seek positions, convert our current (input) values to the + * seek format, adjust by the relative seek offset and then convert back to + * the processing format + */ + GstSeekType start_type, stop_type; + gint64 start, stop; + GstSeekFlags flags; + GstFormat seek_format; + gdouble rate; + gboolean update; + gboolean res = TRUE; + + gst_event_parse_seek (event, &rate, &seek_format, &flags, + &start_type, &start, &stop_type, &stop); + + if (seek_format == segment->format) { + gst_segment_do_seek (segment, rate, seek_format, flags, + start_type, start, stop_type, stop, &update); + return TRUE; + } + + if (start_type != GST_SEEK_TYPE_NONE) { + /* FIXME: Handle seek_end by converting the input segment vals */ + res = + gst_pad_query_convert (sink->sinkpad, seek_format, start, + segment->format, &start); + start_type = GST_SEEK_TYPE_SET; + } + + if (res && stop_type != GST_SEEK_TYPE_NONE) { + /* FIXME: Handle seek_end by converting the input segment vals */ + res = + gst_pad_query_convert (sink->sinkpad, seek_format, stop, + segment->format, &stop); + stop_type = GST_SEEK_TYPE_SET; + } + + /* And finally, configure our output segment in the desired format */ + gst_segment_do_seek (segment, rate, segment->format, flags, start_type, start, + stop_type, stop, &update); + + if (!res) + goto no_format; + + return res; + +no_format: + { + GST_DEBUG_OBJECT (sink, "undefined format given, seek aborted."); + return FALSE; + } +} + +/* perform a seek, only executed in pull mode */ +static gboolean +gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event) +{ + gboolean flush; + gdouble rate; + GstFormat seek_format, dest_format; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gboolean seekseg_configured = FALSE; + gint64 start, stop; + gboolean update, res = TRUE; + GstSegment seeksegment; + + dest_format = sink->segment.format; + + if (event) { + GST_DEBUG_OBJECT (sink, "performing seek with event %p", event); + gst_event_parse_seek (event, &rate, &seek_format, &flags, + &start_type, &start, &stop_type, &stop); + + flush = flags & GST_SEEK_FLAG_FLUSH; + } else { + GST_DEBUG_OBJECT (sink, "performing seek without event"); + flush = FALSE; + } + + if (flush) { + GST_DEBUG_OBJECT (sink, "flushing upstream"); + gst_pad_push_event (pad, gst_event_new_flush_start ()); + gst_base_sink_flush_start (sink, pad); + } else { + GST_DEBUG_OBJECT (sink, "pausing pulling thread"); + } + + GST_PAD_STREAM_LOCK (pad); + + /* If we configured the seeksegment above, don't overwrite it now. Otherwise + * copy the current segment info into the temp segment that we can actually + * attempt the seek with. We only update the real segment if the seek succeeds. */ + if (!seekseg_configured) { + memcpy (&seeksegment, &sink->segment, sizeof (GstSegment)); + + /* now configure the final seek segment */ + if (event) { + if (sink->segment.format != seek_format) { + /* OK, here's where we give the subclass a chance to convert the relative + * seek into an absolute one in the processing format. We set up any + * absolute seek above, before taking the stream lock. */ + if (!gst_base_sink_default_prepare_seek_segment (sink, event, + &seeksegment)) { + GST_DEBUG_OBJECT (sink, + "Preparing the seek failed after flushing. " "Aborting seek"); + res = FALSE; + } + } else { + /* The seek format matches our processing format, no need to ask the + * the subclass to configure the segment. */ + gst_segment_do_seek (&seeksegment, rate, seek_format, flags, + start_type, start, stop_type, stop, &update); + } + } + /* Else, no seek event passed, so we're just (re)starting the + current segment. */ + } + + if (res) { + GST_DEBUG_OBJECT (sink, "segment configured from %" G_GINT64_FORMAT + " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT, + seeksegment.start, seeksegment.stop, seeksegment.position); + + /* do the seek, segment.position contains the new position. */ + res = gst_base_sink_default_do_seek (sink, &seeksegment); + } + + if (flush) { + GST_DEBUG_OBJECT (sink, "stop flushing upstream"); + gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE)); + gst_base_sink_flush_stop (sink, pad, TRUE); + } else if (res && sink->running) { + /* we are running the current segment and doing a non-flushing seek, + * close the segment first based on the position. */ + GST_DEBUG_OBJECT (sink, "closing running segment %" G_GINT64_FORMAT + " to %" G_GINT64_FORMAT, sink->segment.start, sink->segment.position); + } + + /* The subclass must have converted the segment to the processing format + * by now */ + if (res && seeksegment.format != dest_format) { + GST_DEBUG_OBJECT (sink, "Subclass failed to prepare a seek segment " + "in the correct format. Aborting seek."); + res = FALSE; + } + + GST_INFO_OBJECT (sink, "seeking done %d: %" GST_SEGMENT_FORMAT, res, + &seeksegment); + + /* if successful seek, we update our real segment and push + * out the new segment. */ + if (res) { + gst_segment_copy_into (&seeksegment, &sink->segment); + + if (sink->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { + gst_element_post_message (GST_ELEMENT (sink), + gst_message_new_segment_start (GST_OBJECT (sink), + sink->segment.format, sink->segment.position)); + } + } + + sink->priv->discont = TRUE; + sink->running = TRUE; + + GST_PAD_STREAM_UNLOCK (pad); + + return res; +} + +static void +set_step_info (GstBaseSink * sink, GstStepInfo * current, GstStepInfo * pending, + guint seqnum, GstFormat format, guint64 amount, gdouble rate, + gboolean flush, gboolean intermediate) +{ + GST_OBJECT_LOCK (sink); + pending->seqnum = seqnum; + pending->format = format; + pending->amount = amount; + pending->position = 0; + pending->rate = rate; + pending->flush = flush; + pending->intermediate = intermediate; + pending->valid = TRUE; + /* flush invalidates the current stepping segment */ + if (flush) + current->valid = FALSE; + GST_OBJECT_UNLOCK (sink); +} + +static gboolean +gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event) +{ + GstBaseSinkPrivate *priv; + GstBaseSinkClass *bclass; + gboolean flush, intermediate; + gdouble rate; + GstFormat format; + guint64 amount; + guint seqnum; + GstStepInfo *pending, *current; + GstMessage *message; + + bclass = GST_BASE_SINK_GET_CLASS (sink); + priv = sink->priv; + + GST_DEBUG_OBJECT (sink, "performing step with event %p", event); + + gst_event_parse_step (event, &format, &amount, &rate, &flush, &intermediate); + seqnum = gst_event_get_seqnum (event); + + pending = &priv->pending_step; + current = &priv->current_step; + + /* post message first */ + message = gst_message_new_step_start (GST_OBJECT (sink), FALSE, format, + amount, rate, flush, intermediate); + gst_message_set_seqnum (message, seqnum); + gst_element_post_message (GST_ELEMENT (sink), message); + + if (flush) { + /* we need to call ::unlock before locking PREROLL_LOCK + * since we lock it before going into ::render */ + if (bclass->unlock) + bclass->unlock (sink); + + GST_BASE_SINK_PREROLL_LOCK (sink); + /* now that we have the PREROLL lock, clear our unlock request */ + if (bclass->unlock_stop) + bclass->unlock_stop (sink); + + /* update the stepinfo and make it valid */ + set_step_info (sink, current, pending, seqnum, format, amount, rate, flush, + intermediate); + + if (sink->priv->async_enabled) { + /* and we need to commit our state again on the next + * prerolled buffer */ + sink->playing_async = TRUE; + priv->pending_step.need_preroll = TRUE; + sink->need_preroll = FALSE; + gst_base_sink_update_start_time (sink); + gst_element_lost_state (GST_ELEMENT_CAST (sink)); + } else { + sink->priv->have_latency = TRUE; + sink->need_preroll = FALSE; + } + priv->current_sstart = GST_CLOCK_TIME_NONE; + priv->current_sstop = GST_CLOCK_TIME_NONE; + priv->eos_rtime = GST_CLOCK_TIME_NONE; + priv->call_preroll = TRUE; + gst_base_sink_set_last_buffer (sink, NULL); + gst_base_sink_set_last_buffer_list (sink, NULL); + gst_base_sink_reset_qos (sink); + + if (sink->clock_id) { + gst_clock_id_unschedule (sink->clock_id); + } + + if (sink->have_preroll) { + GST_DEBUG_OBJECT (sink, "signal waiter"); + priv->step_unlock = TRUE; + GST_BASE_SINK_PREROLL_SIGNAL (sink); + } + GST_BASE_SINK_PREROLL_UNLOCK (sink); + } else { + /* update the stepinfo and make it valid */ + set_step_info (sink, current, pending, seqnum, format, amount, rate, flush, + intermediate); + } + + return TRUE; +} + +/* with STREAM_LOCK + */ +static void +gst_base_sink_loop (GstPad * pad) +{ + GstObject *parent; + GstBaseSink *basesink; + GstBuffer *buf = NULL; + GstFlowReturn result; + guint blocksize; + guint64 offset; + + parent = GST_OBJECT_PARENT (pad); + basesink = GST_BASE_SINK (parent); + + g_assert (basesink->pad_mode == GST_PAD_MODE_PULL); + + if ((blocksize = basesink->priv->blocksize) == 0) + blocksize = -1; + + offset = basesink->segment.position; + + GST_DEBUG_OBJECT (basesink, "pulling %" G_GUINT64_FORMAT ", %u", + offset, blocksize); + + result = gst_pad_pull_range (pad, offset, blocksize, &buf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + goto paused; + + if (G_UNLIKELY (buf == NULL)) + goto no_buffer; + + offset += gst_buffer_get_size (buf); + + basesink->segment.position = offset; + + GST_BASE_SINK_PREROLL_LOCK (basesink); + result = gst_base_sink_chain_unlocked (basesink, pad, buf, FALSE); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + if (G_UNLIKELY (result != GST_FLOW_OK)) + goto paused; + + return; + + /* ERRORS */ +paused: + { + GST_LOG_OBJECT (basesink, "pausing task, reason %s", + gst_flow_get_name (result)); + gst_pad_pause_task (pad); + if (result == GST_FLOW_EOS) { + /* perform EOS logic */ + if (basesink->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_segment_done (GST_OBJECT_CAST (basesink), + basesink->segment.format, basesink->segment.position)); + gst_base_sink_event (pad, parent, + gst_event_new_segment_done (basesink->segment.format, + basesink->segment.position)); + } else { + gst_base_sink_event (pad, parent, gst_event_new_eos ()); + } + } else if (result == GST_FLOW_NOT_LINKED || result <= GST_FLOW_EOS) { + /* for fatal errors we post an error message, post the error + * first so the app knows about the error first. + * wrong-state is not a fatal error because it happens due to + * flushing and posting an error message in that case is the + * wrong thing to do, e.g. when basesrc is doing a flushing + * seek. */ + GST_ELEMENT_FLOW_ERROR (basesink, result); + gst_base_sink_event (pad, parent, gst_event_new_eos ()); + } + return; + } +no_buffer: + { + GST_LOG_OBJECT (basesink, "no buffer, pausing"); + GST_ELEMENT_ERROR (basesink, STREAM, FAILED, + (_("Internal data flow error.")), ("element returned NULL buffer")); + result = GST_FLOW_ERROR; + goto paused; + } +} + +static gboolean +gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad, + gboolean flushing) +{ + GstBaseSinkClass *bclass; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + if (flushing) { + /* unlock any subclasses, we need to do this before grabbing the + * PREROLL_LOCK since we hold this lock before going into ::render. */ + if (bclass->unlock) + bclass->unlock (basesink); + } + + GST_BASE_SINK_PREROLL_LOCK (basesink); + basesink->flushing = flushing; + if (flushing) { + /* step 1, now that we have the PREROLL lock, clear our unlock request */ + if (bclass->unlock_stop) + bclass->unlock_stop (basesink); + + /* set need_preroll before we unblock the clock. If the clock is unblocked + * before timing out, we can reuse the buffer for preroll. */ + basesink->need_preroll = TRUE; + + /* step 2, unblock clock sync (if any) or any other blocking thing */ + if (basesink->clock_id) { + gst_clock_id_unschedule (basesink->clock_id); + } + + /* flush out the data thread if it's locked in finish_preroll, this will + * also flush out the EOS state */ + GST_DEBUG_OBJECT (basesink, + "flushing out data thread, need preroll to TRUE"); + + /* we can't have EOS anymore now */ + basesink->eos = FALSE; + basesink->priv->received_eos = FALSE; + basesink->have_preroll = FALSE; + basesink->priv->step_unlock = FALSE; + /* can't report latency anymore until we preroll again */ + if (basesink->priv->async_enabled) { + GST_OBJECT_LOCK (basesink); + basesink->priv->have_latency = FALSE; + GST_OBJECT_UNLOCK (basesink); + } + /* and signal any waiters now */ + GST_BASE_SINK_PREROLL_SIGNAL (basesink); + } + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + + return TRUE; +} + +static gboolean +gst_base_sink_default_activate_pull (GstBaseSink * basesink, gboolean active) +{ + gboolean result; + + if (active) { + /* start task */ + result = gst_pad_start_task (basesink->sinkpad, + (GstTaskFunction) gst_base_sink_loop, basesink->sinkpad, NULL); + } else { + /* step 2, make sure streaming finishes */ + result = gst_pad_stop_task (basesink->sinkpad); + } + + return result; +} + +static gboolean +gst_base_sink_pad_activate (GstPad * pad, GstObject * parent) +{ + gboolean result = FALSE; + GstBaseSink *basesink; + GstQuery *query; + gboolean pull_mode; + + basesink = GST_BASE_SINK (parent); + + GST_DEBUG_OBJECT (basesink, "Trying pull mode first"); + + gst_base_sink_set_flushing (basesink, pad, FALSE); + + /* we need to have the pull mode enabled */ + if (!basesink->can_activate_pull) { + GST_DEBUG_OBJECT (basesink, "pull mode disabled"); + goto fallback; + } + + /* check if downstreams supports pull mode at all */ + query = gst_query_new_scheduling (); + + if (!gst_pad_peer_query (pad, query)) { + gst_query_unref (query); + GST_DEBUG_OBJECT (basesink, "peer query faild, no pull mode"); + goto fallback; + } + + /* parse result of the query */ + pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_unref (query); + + if (!pull_mode) { + GST_DEBUG_OBJECT (basesink, "pull mode not supported"); + goto fallback; + } + + /* set the pad mode before starting the task so that it's in the + * correct state for the new thread. also the sink set_caps and get_caps + * function checks this */ + basesink->pad_mode = GST_PAD_MODE_PULL; + + /* we first try to negotiate a format so that when we try to activate + * downstream, it knows about our format */ + if (!gst_base_sink_negotiate_pull (basesink)) { + GST_DEBUG_OBJECT (basesink, "failed to negotiate in pull mode"); + goto fallback; + } + + /* ok activate now */ + if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) { + /* clear any pending caps */ + GST_OBJECT_LOCK (basesink); + gst_caps_replace (&basesink->priv->caps, NULL); + GST_OBJECT_UNLOCK (basesink); + GST_DEBUG_OBJECT (basesink, "failed to activate in pull mode"); + goto fallback; + } + + GST_DEBUG_OBJECT (basesink, "Success activating pull mode"); + result = TRUE; + goto done; + + /* push mode fallback */ +fallback: + GST_DEBUG_OBJECT (basesink, "Falling back to push mode"); + if ((result = gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE))) { + GST_DEBUG_OBJECT (basesink, "Success activating push mode"); + } + +done: + if (!result) { + GST_WARNING_OBJECT (basesink, "Could not activate pad in either mode"); + gst_base_sink_set_flushing (basesink, pad, TRUE); + } + + return result; +} + +static gboolean +gst_base_sink_pad_activate_push (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean result; + GstBaseSink *basesink; + + basesink = GST_BASE_SINK (parent); + + if (active) { + if (!basesink->can_activate_push) { + result = FALSE; + basesink->pad_mode = GST_PAD_MODE_NONE; + } else { + result = TRUE; + basesink->pad_mode = GST_PAD_MODE_PUSH; + } + } else { + if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH)) { + g_warning ("Internal GStreamer activation error!!!"); + result = FALSE; + } else { + gst_base_sink_set_flushing (basesink, pad, TRUE); + result = TRUE; + basesink->pad_mode = GST_PAD_MODE_NONE; + } + } + + return result; +} + +static gboolean +gst_base_sink_negotiate_pull (GstBaseSink * basesink) +{ + GstCaps *caps; + gboolean result; + + result = FALSE; + + /* this returns the intersection between our caps and the peer caps. If there + * is no peer, it returns %NULL and we can't operate in pull mode so we can + * fail the negotiation. */ + caps = gst_pad_get_allowed_caps (GST_BASE_SINK_PAD (basesink)); + if (caps == NULL || gst_caps_is_empty (caps)) + goto no_caps_possible; + + GST_DEBUG_OBJECT (basesink, "allowed caps: %" GST_PTR_FORMAT, caps); + + if (gst_caps_is_any (caps)) { + GST_DEBUG_OBJECT (basesink, "caps were ANY after fixating, " + "allowing pull()"); + /* neither side has template caps in this case, so they are prepared for + pull() without setcaps() */ + result = TRUE; + } else { + /* try to fixate */ + caps = gst_base_sink_fixate (basesink, caps); + GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps); + + if (gst_caps_is_fixed (caps)) { + if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps)) + goto could_not_set_caps; + + result = TRUE; + } + } + + gst_caps_unref (caps); + + return result; + +no_caps_possible: + { + GST_INFO_OBJECT (basesink, "Pipeline could not agree on caps"); + GST_DEBUG_OBJECT (basesink, "get_allowed_caps() returned EMPTY"); + if (caps) + gst_caps_unref (caps); + return FALSE; + } +could_not_set_caps: + { + GST_INFO_OBJECT (basesink, "Could not set caps: %" GST_PTR_FORMAT, caps); + gst_caps_unref (caps); + return FALSE; + } +} + +/* this won't get called until we implement an activate function */ +static gboolean +gst_base_sink_pad_activate_pull (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean result = FALSE; + GstBaseSink *basesink; + GstBaseSinkClass *bclass; + + basesink = GST_BASE_SINK (parent); + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + if (active) { + gint64 duration; + + /* we mark we have a newsegment here because pull based + * mode works just fine without having a newsegment before the + * first buffer */ + gst_segment_init (&basesink->segment, GST_FORMAT_BYTES); + GST_OBJECT_LOCK (basesink); + basesink->have_newsegment = TRUE; + GST_OBJECT_UNLOCK (basesink); + + /* get the peer duration in bytes */ + result = gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &duration); + if (result) { + GST_DEBUG_OBJECT (basesink, + "setting duration in bytes to %" G_GINT64_FORMAT, duration); + basesink->segment.duration = duration; + } else { + GST_DEBUG_OBJECT (basesink, "unknown duration"); + } + + if (bclass->activate_pull) + result = bclass->activate_pull (basesink, TRUE); + else + result = FALSE; + + if (!result) + goto activate_failed; + + } else { + if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PULL)) { + g_warning ("Internal GStreamer activation error!!!"); + result = FALSE; + } else { + result = gst_base_sink_set_flushing (basesink, pad, TRUE); + if (bclass->activate_pull) + result &= bclass->activate_pull (basesink, FALSE); + basesink->pad_mode = GST_PAD_MODE_NONE; + } + } + + return result; + + /* ERRORS */ +activate_failed: + { + /* reset, as starting the thread failed */ + basesink->pad_mode = GST_PAD_MODE_NONE; + + GST_ERROR_OBJECT (basesink, "subclass failed to activate in pull mode"); + return FALSE; + } +} + +static gboolean +gst_base_sink_pad_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_base_sink_pad_activate_pull (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_base_sink_pad_activate_push (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + +/* send an event to our sinkpad peer. */ +static gboolean +gst_base_sink_send_event (GstElement * element, GstEvent * event) +{ + GstPad *pad; + GstBaseSink *basesink = GST_BASE_SINK (element); + gboolean forward, result = TRUE; + GstPadMode mode; + + GST_OBJECT_LOCK (element); + /* get the pad and the scheduling mode */ + pad = gst_object_ref (basesink->sinkpad); + mode = basesink->pad_mode; + GST_OBJECT_UNLOCK (element); + + /* only push UPSTREAM events upstream */ + forward = GST_EVENT_IS_UPSTREAM (event); + + GST_DEBUG_OBJECT (basesink, "handling event %p %" GST_PTR_FORMAT, event, + event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_LATENCY: + { + GstClockTime latency; + + gst_event_parse_latency (event, &latency); + + /* store the latency. We use this to adjust the running_time before syncing + * it to the clock. */ + GST_OBJECT_LOCK (element); + basesink->priv->latency = latency; + if (!basesink->priv->have_latency) + forward = FALSE; + GST_OBJECT_UNLOCK (element); + GST_DEBUG_OBJECT (basesink, "latency set to %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + + /* We forward this event so that all elements know about the global pipeline + * latency. This is interesting for an element when it wants to figure out + * when a particular piece of data will be rendered. */ + break; + } + case GST_EVENT_SEEK: + /* in pull mode we will execute the seek */ + if (mode == GST_PAD_MODE_PULL) + result = gst_base_sink_perform_seek (basesink, pad, event); + break; + case GST_EVENT_STEP: + result = gst_base_sink_perform_step (basesink, pad, event); + forward = FALSE; + break; + default: + break; + } + + if (forward) { + GST_DEBUG_OBJECT (basesink, "sending event %p %" GST_PTR_FORMAT, event, + event); + result = gst_pad_push_event (pad, event); + } else { + /* not forwarded, unref the event */ + gst_event_unref (event); + } + + gst_object_unref (pad); + + GST_DEBUG_OBJECT (basesink, "handled event: %d", result); + + return result; +} + +static gboolean +gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format, + gint64 * cur, gboolean * upstream) +{ + GstClock *clock = NULL; + gboolean res = FALSE; + GstFormat oformat; + GstSegment *segment; + GstClockTime now, latency; + GstClockTimeDiff base_time; + gint64 time, base, offset, duration; + gdouble rate; + gint64 last; + gboolean last_seen, with_clock, in_paused; + + GST_OBJECT_LOCK (basesink); + /* we can only get the segment when we are not NULL or READY */ + if (!basesink->have_newsegment) + goto wrong_state; + + in_paused = FALSE; + /* when not in PLAYING or when we're busy with a state change, we + * cannot read from the clock so we report time based on the + * last seen timestamp. */ + if (GST_STATE (basesink) != GST_STATE_PLAYING || + GST_STATE_PENDING (basesink) != GST_STATE_VOID_PENDING) { + in_paused = TRUE; + } + + segment = &basesink->segment; + + /* get the format in the segment */ + oformat = segment->format; + + /* report with last seen position when EOS */ + last_seen = basesink->eos; + + /* assume we will use the clock for getting the current position */ + with_clock = TRUE; + if (!basesink->sync) + with_clock = FALSE; + + /* and we need a clock */ + if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (basesink)) == NULL)) + with_clock = FALSE; + else + gst_object_ref (clock); + + /* mainloop might be querying position when going to playing async, + * while (audio) rendering might be quickly advancing stream position, + * so use clock asap rather than last reported position */ + if (in_paused && with_clock && g_atomic_int_get (&basesink->priv->to_playing)) { + GST_DEBUG_OBJECT (basesink, "going to PLAYING, so not PAUSED"); + in_paused = FALSE; + } + + /* collect all data we need holding the lock */ + if (GST_CLOCK_TIME_IS_VALID (segment->time)) + time = segment->time; + else + time = 0; + + if (GST_CLOCK_TIME_IS_VALID (segment->offset)) + offset = segment->offset; + else + offset = 0; + + if (GST_CLOCK_TIME_IS_VALID (segment->stop)) + duration = segment->stop - segment->start; + else + duration = 0; + + base = segment->base; + rate = segment->rate * segment->applied_rate; + latency = basesink->priv->latency; + + if (in_paused) { + /* in paused, use start_time */ + base_time = GST_ELEMENT_START_TIME (basesink); + GST_DEBUG_OBJECT (basesink, "in paused, using start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (base_time)); + } else if (with_clock) { + /* else use clock when needed */ + base_time = GST_ELEMENT_CAST (basesink)->base_time; + GST_DEBUG_OBJECT (basesink, "using clock and base time %" GST_TIME_FORMAT, + GST_TIME_ARGS (base_time)); + } else { + /* else, no sync or clock -> no base time */ + GST_DEBUG_OBJECT (basesink, "no sync or no clock"); + base_time = -1; + } + + /* no base_time, we can't calculate running_time, use last seem timestamp to report + * time */ + if (base_time == -1) + last_seen = TRUE; + + if (oformat == GST_FORMAT_TIME) { + gint64 start, stop; + + start = basesink->priv->current_sstart; + stop = basesink->priv->current_sstop; + + if (last_seen) { + /* when we don't use the clock, we use the last position as a lower bound */ + if (stop == -1 || segment->rate > 0.0) + last = start; + else + last = stop; + + GST_DEBUG_OBJECT (basesink, "in PAUSED using last %" GST_TIME_FORMAT, + GST_TIME_ARGS (last)); + } else { + /* in playing and paused, use last stop time as upper bound */ + if (start == -1 || segment->rate > 0.0) + last = stop; + else + last = start; + + GST_DEBUG_OBJECT (basesink, "in PLAYING using last %" GST_TIME_FORMAT, + GST_TIME_ARGS (last)); + } + } else { + /* convert position to stream time */ + last = gst_segment_to_stream_time (segment, oformat, segment->position); + + GST_DEBUG_OBJECT (basesink, "in using last %" G_GINT64_FORMAT, last); + } + + /* need to release the object lock before we can get the time, + * a clock might take the LOCK of the provider, which could be + * a basesink subclass. */ + GST_OBJECT_UNLOCK (basesink); + + if (last_seen) { + /* in EOS or when no valid stream_time, report the value of last seen + * timestamp */ + if (last == -1) { + /* no timestamp, we need to ask upstream */ + GST_DEBUG_OBJECT (basesink, "no last seen timestamp, asking upstream"); + res = FALSE; + *upstream = TRUE; + goto done; + } + GST_DEBUG_OBJECT (basesink, "using last seen timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (last)); + *cur = last; + } else { + if (oformat != GST_FORMAT_TIME) { + /* convert base, time and duration to time */ + if (!gst_pad_query_convert (basesink->sinkpad, oformat, base, + GST_FORMAT_TIME, &base)) + goto convert_failed; + if (!gst_pad_query_convert (basesink->sinkpad, oformat, duration, + GST_FORMAT_TIME, &duration)) + goto convert_failed; + if (!gst_pad_query_convert (basesink->sinkpad, oformat, time, + GST_FORMAT_TIME, &time)) + goto convert_failed; + if (!gst_pad_query_convert (basesink->sinkpad, oformat, last, + GST_FORMAT_TIME, &last)) + goto convert_failed; + + /* assume time format from now on */ + oformat = GST_FORMAT_TIME; + } + + if (!in_paused && with_clock) { + now = gst_clock_get_time (clock); + } else { + now = base_time; + base_time = 0; + } + + /* subtract base time and base time from the clock time. + * Make sure we don't go negative. This is the current time in + * the segment which we need to scale with the combined + * rate and applied rate. */ + base_time += base; + base_time += latency; + if (GST_CLOCK_DIFF (base_time, now) < 0) + base_time = now; + + /* for negative rates we need to count back from the segment + * duration. */ + if (rate < 0.0) + time += duration; + + *cur = time + offset + gst_guint64_to_gdouble (now - base_time) * rate; + + /* never report more than last seen position */ + if (last != -1) { + if (rate > 0.0) + *cur = MIN (last, *cur); + else + *cur = MAX (last, *cur); + } + + GST_DEBUG_OBJECT (basesink, + "now %" GST_TIME_FORMAT " - base_time %" GST_TIME_FORMAT " - base %" + GST_TIME_FORMAT " + time %" GST_TIME_FORMAT " last %" GST_TIME_FORMAT, + GST_TIME_ARGS (now), GST_TIME_ARGS (base_time), GST_TIME_ARGS (base), + GST_TIME_ARGS (time), GST_TIME_ARGS (last)); + } + + if (oformat != format) { + /* convert to final format */ + if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, format, cur)) + goto convert_failed; + } + + res = TRUE; + +done: + GST_DEBUG_OBJECT (basesink, "res: %d, POSITION: %" GST_TIME_FORMAT, + res, GST_TIME_ARGS (*cur)); + + if (clock) + gst_object_unref (clock); + + return res; + + /* special cases */ +wrong_state: + { + /* in NULL or READY we always return FALSE and -1 */ + GST_DEBUG_OBJECT (basesink, "position in wrong state, return -1"); + res = FALSE; + *cur = -1; + GST_OBJECT_UNLOCK (basesink); + goto done; + } +convert_failed: + { + GST_DEBUG_OBJECT (basesink, "convert failed, try upstream"); + *upstream = TRUE; + res = FALSE; + goto done; + } +} + +static gboolean +gst_base_sink_get_duration (GstBaseSink * basesink, GstFormat format, + gint64 * dur, gboolean * upstream) +{ + gboolean res = FALSE; + + if (basesink->pad_mode == GST_PAD_MODE_PULL) { + gint64 uduration; + + /* get the duration in bytes, in pull mode that's all we are sure to + * know. We have to explicitly get this value from upstream instead of + * using our cached value because it might change. Duration caching + * should be done at a higher level. */ + res = + gst_pad_peer_query_duration (basesink->sinkpad, GST_FORMAT_BYTES, + &uduration); + if (res) { + basesink->segment.duration = uduration; + if (format != GST_FORMAT_BYTES) { + /* convert to the requested format */ + res = + gst_pad_query_convert (basesink->sinkpad, GST_FORMAT_BYTES, + uduration, format, dur); + } else { + *dur = uduration; + } + } + *upstream = FALSE; + } else { + *upstream = TRUE; + } + + return res; +} + +static gboolean +default_element_query (GstElement * element, GstQuery * query) +{ + gboolean res = FALSE; + + GstBaseSink *basesink = GST_BASE_SINK (element); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 cur = 0; + GstFormat format; + gboolean upstream = FALSE; + + gst_query_parse_position (query, &format, NULL); + + GST_DEBUG_OBJECT (basesink, "position query in format %s", + gst_format_get_name (format)); + + /* first try to get the position based on the clock */ + if ((res = + gst_base_sink_get_position (basesink, format, &cur, &upstream))) { + gst_query_set_position (query, format, cur); + } else if (upstream) { + /* fallback to peer query */ + res = gst_pad_peer_query (basesink->sinkpad, query); + } + if (!res) { + /* we can handle a few things if upstream failed */ + if (format == GST_FORMAT_PERCENT) { + gint64 dur = 0; + + res = gst_base_sink_get_position (basesink, GST_FORMAT_TIME, &cur, + &upstream); + if (!res && upstream) { + res = + gst_pad_peer_query_position (basesink->sinkpad, GST_FORMAT_TIME, + &cur); + } + if (res) { + res = gst_base_sink_get_duration (basesink, GST_FORMAT_TIME, &dur, + &upstream); + if (!res && upstream) { + res = + gst_pad_peer_query_duration (basesink->sinkpad, + GST_FORMAT_TIME, &dur); + } + } + if (res) { + gint64 pos; + + pos = gst_util_uint64_scale (100 * GST_FORMAT_PERCENT_SCALE, cur, + dur); + gst_query_set_position (query, GST_FORMAT_PERCENT, pos); + } + } + } + break; + } + case GST_QUERY_DURATION: + { + gint64 dur = 0; + GstFormat format; + gboolean upstream = FALSE; + + gst_query_parse_duration (query, &format, NULL); + + GST_DEBUG_OBJECT (basesink, "duration query in format %s", + gst_format_get_name (format)); + + if ((res = + gst_base_sink_get_duration (basesink, format, &dur, &upstream))) { + gst_query_set_duration (query, format, dur); + } else if (upstream) { + /* fallback to peer query */ + res = gst_pad_peer_query (basesink->sinkpad, query); + } + if (!res) { + /* we can handle a few things if upstream failed */ + if (format == GST_FORMAT_PERCENT) { + gst_query_set_duration (query, GST_FORMAT_PERCENT, + GST_FORMAT_PERCENT_MAX); + res = TRUE; + } + } + break; + } + case GST_QUERY_LATENCY: + { + gboolean live, us_live; + GstClockTime min, max; + + if ((res = gst_base_sink_query_latency (basesink, &live, &us_live, &min, + &max))) { + gst_query_set_latency (query, live, min, max); + } + break; + } + case GST_QUERY_JITTER: + break; + case GST_QUERY_RATE: + /* gst_query_set_rate (query, basesink->segment_rate); */ + res = TRUE; + break; + case GST_QUERY_SEGMENT: + { + if (basesink->pad_mode == GST_PAD_MODE_PULL) { + GstFormat format; + gint64 start, stop; + + format = basesink->segment.format; + + start = + gst_segment_to_stream_time (&basesink->segment, format, + basesink->segment.start); + if ((stop = basesink->segment.stop) == -1) + stop = basesink->segment.duration; + else + stop = gst_segment_to_stream_time (&basesink->segment, format, stop); + + gst_query_set_segment (query, basesink->segment.rate, format, start, + stop); + res = TRUE; + } else { + res = gst_pad_peer_query (basesink->sinkpad, query); + } + break; + } + case GST_QUERY_SEEKING: + case GST_QUERY_CONVERT: + case GST_QUERY_FORMATS: + default: + res = gst_pad_peer_query (basesink->sinkpad, query); + break; + } + GST_DEBUG_OBJECT (basesink, "query %s returns %d", + GST_QUERY_TYPE_NAME (query), res); + return res; +} + +static void +gst_base_sink_drain (GstBaseSink * basesink) +{ + GstBuffer *old; + GstBufferList *old_list; + + GST_OBJECT_LOCK (basesink); + if ((old = basesink->priv->last_buffer)) + basesink->priv->last_buffer = gst_buffer_copy_deep (old); + + if ((old_list = basesink->priv->last_buffer_list)) + basesink->priv->last_buffer_list = gst_buffer_list_copy_deep (old_list); + GST_OBJECT_UNLOCK (basesink); + + if (old) + gst_buffer_unref (old); + if (old_list) + gst_mini_object_unref (GST_MINI_OBJECT_CAST (old_list)); +} + +static gboolean +gst_base_sink_default_query (GstBaseSink * basesink, GstQuery * query) +{ + gboolean res; + GstBaseSinkClass *bclass; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ALLOCATION: + { + gst_base_sink_drain (basesink); + if (bclass->propose_allocation) + res = bclass->propose_allocation (basesink, query); + else + res = FALSE; + break; + } + case GST_QUERY_CAPS: + { + GstCaps *caps, *filter; + + gst_query_parse_caps (query, &filter); + caps = gst_base_sink_query_caps (basesink, basesink->sinkpad, filter); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + res = TRUE; + break; + } + case GST_QUERY_ACCEPT_CAPS: + { + GstCaps *caps, *allowed; + gboolean subset; + + /* slightly faster than the default implementation */ + gst_query_parse_accept_caps (query, &caps); + allowed = gst_base_sink_query_caps (basesink, basesink->sinkpad, NULL); + subset = gst_caps_is_subset (caps, allowed); + GST_DEBUG_OBJECT (basesink, "Checking if requested caps %" GST_PTR_FORMAT + " are a subset of pad caps %" GST_PTR_FORMAT " result %d", caps, + allowed, subset); + gst_caps_unref (allowed); + gst_query_set_accept_caps_result (query, subset); + res = TRUE; + break; + } + case GST_QUERY_DRAIN: + { + gst_base_sink_drain (basesink); + res = TRUE; + break; + } + case GST_QUERY_POSITION: + { + res = default_element_query (GST_ELEMENT (basesink), query); + break; + } + default: + res = + gst_pad_query_default (basesink->sinkpad, GST_OBJECT_CAST (basesink), + query); + break; + } + return res; +} + +static gboolean +gst_base_sink_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstBaseSink *basesink; + GstBaseSinkClass *bclass; + gboolean res; + + basesink = GST_BASE_SINK_CAST (parent); + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + if (bclass->query) + res = bclass->query (basesink, query); + else + res = FALSE; + + return res; +} + +static GstStateChangeReturn +gst_base_sink_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstBaseSink *basesink = GST_BASE_SINK (element); + GstBaseSinkClass *bclass; + GstBaseSinkPrivate *priv; + + priv = basesink->priv; + + bclass = GST_BASE_SINK_GET_CLASS (basesink); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (bclass->start) + if (!bclass->start (basesink)) + goto start_failed; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* need to complete preroll before this state change completes, there + * is no data flow in READY so we can safely assume we need to preroll. */ + GST_BASE_SINK_PREROLL_LOCK (basesink); + GST_DEBUG_OBJECT (basesink, "READY to PAUSED"); + basesink->have_newsegment = FALSE; + gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED); + basesink->offset = 0; + basesink->have_preroll = FALSE; + priv->step_unlock = FALSE; + basesink->need_preroll = TRUE; + basesink->playing_async = TRUE; + priv->current_sstart = GST_CLOCK_TIME_NONE; + priv->current_sstop = GST_CLOCK_TIME_NONE; + priv->eos_rtime = GST_CLOCK_TIME_NONE; + priv->latency = 0; + basesink->eos = FALSE; + priv->received_eos = FALSE; + gst_base_sink_reset_qos (basesink); + priv->rc_next = -1; + priv->commited = FALSE; + priv->call_preroll = TRUE; + priv->current_step.valid = FALSE; + priv->pending_step.valid = FALSE; + if (priv->async_enabled) { + GST_DEBUG_OBJECT (basesink, "doing async state change"); + /* when async enabled, post async-start message and return ASYNC from + * the state change function */ + ret = GST_STATE_CHANGE_ASYNC; + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); + } else { + priv->have_latency = TRUE; + } + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_BASE_SINK_PREROLL_LOCK (basesink); + g_atomic_int_set (&basesink->priv->to_playing, TRUE); + if (!gst_base_sink_needs_preroll (basesink)) { + GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, don't need preroll"); + /* no preroll needed anymore now. */ + basesink->playing_async = FALSE; + basesink->need_preroll = FALSE; + if (basesink->eos) { + GstMessage *message; + + /* need to post EOS message here */ + GST_DEBUG_OBJECT (basesink, "Now posting EOS"); + message = gst_message_new_eos (GST_OBJECT_CAST (basesink)); + gst_message_set_seqnum (message, basesink->priv->seqnum); + gst_element_post_message (GST_ELEMENT_CAST (basesink), message); + } else { + GST_DEBUG_OBJECT (basesink, "signal preroll"); + GST_BASE_SINK_PREROLL_SIGNAL (basesink); + } + } else { + GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled"); + basesink->need_preroll = TRUE; + basesink->playing_async = TRUE; + priv->call_preroll = TRUE; + priv->commited = FALSE; + if (priv->async_enabled) { + GST_DEBUG_OBJECT (basesink, "doing async state change"); + ret = GST_STATE_CHANGE_ASYNC; + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); + } + } + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + break; + 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; + } + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + /* completed transition, so need not be marked any longer + * And it should be unmarked, since e.g. losing our position upon flush + * does not really change state to PAUSED ... */ + g_atomic_int_set (&basesink->priv->to_playing, FALSE); + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + g_atomic_int_set (&basesink->priv->to_playing, FALSE); + GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED"); + /* FIXME, make sure we cannot enter _render first */ + + /* we need to call ::unlock before locking PREROLL_LOCK + * since we lock it before going into ::render */ + if (bclass->unlock) + bclass->unlock (basesink); + + GST_BASE_SINK_PREROLL_LOCK (basesink); + GST_DEBUG_OBJECT (basesink, "got preroll lock"); + /* now that we have the PREROLL lock, clear our unlock request */ + if (bclass->unlock_stop) + bclass->unlock_stop (basesink); + + if (basesink->clock_id) { + GST_DEBUG_OBJECT (basesink, "unschedule clock"); + gst_clock_id_unschedule (basesink->clock_id); + } + + /* if we don't have a preroll buffer we need to wait for a preroll and + * return ASYNC. */ + if (!gst_base_sink_needs_preroll (basesink)) { + GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED, we are prerolled"); + basesink->playing_async = FALSE; + basesink->need_preroll = FALSE; + } else { + if (GST_STATE_TARGET (GST_ELEMENT (basesink)) <= GST_STATE_READY) { + GST_DEBUG_OBJECT (basesink, "element is <= READY"); + ret = GST_STATE_CHANGE_SUCCESS; + } else { + GST_DEBUG_OBJECT (basesink, + "PLAYING to PAUSED, we are not prerolled"); + basesink->playing_async = TRUE; + basesink->need_preroll = TRUE; + priv->commited = FALSE; + priv->call_preroll = TRUE; + if (priv->async_enabled) { + GST_DEBUG_OBJECT (basesink, "doing async state change"); + ret = GST_STATE_CHANGE_ASYNC; + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_async_start (GST_OBJECT_CAST (basesink))); + } + } + } + GST_DEBUG_OBJECT (basesink, "rendered: %" G_GUINT64_FORMAT + ", dropped: %" G_GUINT64_FORMAT, priv->rendered, priv->dropped); + + gst_base_sink_reset_qos (basesink); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_BASE_SINK_PREROLL_LOCK (basesink); + /* start by resetting our position state with the object lock so that the + * position query gets the right idea. We do this before we post the + * messages so that the message handlers pick this up. */ + GST_OBJECT_LOCK (basesink); + basesink->have_newsegment = FALSE; + priv->current_sstart = GST_CLOCK_TIME_NONE; + priv->current_sstop = GST_CLOCK_TIME_NONE; + priv->have_latency = FALSE; + if (priv->cached_clock_id) { + gst_clock_id_unref (priv->cached_clock_id); + priv->cached_clock_id = NULL; + } + gst_caps_replace (&basesink->priv->caps, NULL); + GST_OBJECT_UNLOCK (basesink); + + gst_base_sink_set_last_buffer (basesink, NULL); + gst_base_sink_set_last_buffer_list (basesink, NULL); + priv->call_preroll = FALSE; + + if (!priv->commited) { + if (priv->async_enabled) { + GST_DEBUG_OBJECT (basesink, "PAUSED to READY, posting async-done"); + + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_state_changed (GST_OBJECT_CAST (basesink), + GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY)); + + gst_element_post_message (GST_ELEMENT_CAST (basesink), + gst_message_new_async_done (GST_OBJECT_CAST (basesink), + GST_CLOCK_TIME_NONE)); + } + priv->commited = TRUE; + } else { + GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll"); + } + GST_BASE_SINK_PREROLL_UNLOCK (basesink); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + if (bclass->stop) { + if (!bclass->stop (basesink)) { + GST_WARNING_OBJECT (basesink, "failed to stop"); + } + } + gst_base_sink_set_last_buffer (basesink, NULL); + gst_base_sink_set_last_buffer_list (basesink, NULL); + priv->call_preroll = FALSE; + break; + default: + break; + } + + return ret; + + /* ERRORS */ +start_failed: + { + GST_DEBUG_OBJECT (basesink, "failed to start"); + /* subclass is supposed to post a message but we post one as a fallback + * just in case */ + GST_ELEMENT_ERROR (basesink, CORE, STATE_CHANGE, (NULL), + ("Failed to start")); + return GST_STATE_CHANGE_FAILURE; + } +activate_failed: + { + GST_DEBUG_OBJECT (basesink, + "element failed to change states -- activation problem?"); + return GST_STATE_CHANGE_FAILURE; + } +} diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h new file mode 100644 index 0000000..af8ca98 --- /dev/null +++ b/libs/gst/base/gstbasesink.h @@ -0,0 +1,326 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstbasesink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_SINK_H__ +#define __GST_BASE_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_BASE_SINK (gst_base_sink_get_type()) +#define GST_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_SINK,GstBaseSink)) +#define GST_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_SINK,GstBaseSinkClass)) +#define GST_BASE_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_SINK, GstBaseSinkClass)) +#define GST_IS_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_SINK)) +#define GST_IS_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_SINK)) +#define GST_BASE_SINK_CAST(obj) ((GstBaseSink *) (obj)) + +/** + * GST_BASE_SINK_PAD: + * @obj: base sink instance + * + * Gives the pointer to the #GstPad object of the element. + */ +#define GST_BASE_SINK_PAD(obj) (GST_BASE_SINK_CAST (obj)->sinkpad) + +#define GST_BASE_SINK_GET_PREROLL_LOCK(obj) (&GST_BASE_SINK_CAST(obj)->preroll_lock) +#define GST_BASE_SINK_PREROLL_LOCK(obj) (g_mutex_lock(GST_BASE_SINK_GET_PREROLL_LOCK(obj))) +#define GST_BASE_SINK_PREROLL_TRYLOCK(obj) (g_mutex_trylock(GST_BASE_SINK_GET_PREROLL_LOCK(obj))) +#define GST_BASE_SINK_PREROLL_UNLOCK(obj) (g_mutex_unlock(GST_BASE_SINK_GET_PREROLL_LOCK(obj))) + +#define GST_BASE_SINK_GET_PREROLL_COND(obj) (&GST_BASE_SINK_CAST(obj)->preroll_cond) +#define GST_BASE_SINK_PREROLL_WAIT(obj) \ + g_cond_wait (GST_BASE_SINK_GET_PREROLL_COND (obj), GST_BASE_SINK_GET_PREROLL_LOCK (obj)) +#define GST_BASE_SINK_PREROLL_WAIT_UNTIL(obj, end_time) \ + g_cond_wait_until (GST_BASE_SINK_GET_PREROLL_COND (obj), GST_BASE_SINK_GET_PREROLL_LOCK (obj), end_time) +#define GST_BASE_SINK_PREROLL_SIGNAL(obj) g_cond_signal (GST_BASE_SINK_GET_PREROLL_COND (obj)); +#define GST_BASE_SINK_PREROLL_BROADCAST(obj) g_cond_broadcast (GST_BASE_SINK_GET_PREROLL_COND (obj)); + +typedef struct _GstBaseSink GstBaseSink; +typedef struct _GstBaseSinkClass GstBaseSinkClass; +typedef struct _GstBaseSinkPrivate GstBaseSinkPrivate; + +/** + * GstBaseSink: + * + * The opaque #GstBaseSink data structure. + */ +struct _GstBaseSink { + GstElement element; + + /*< protected >*/ + GstPad *sinkpad; + GstPadMode pad_mode; + + /*< protected >*/ /* with LOCK */ + guint64 offset; + gboolean can_activate_pull; + gboolean can_activate_push; + + /*< protected >*/ /* with PREROLL_LOCK */ + GMutex preroll_lock; + GCond preroll_cond; + gboolean eos; + gboolean need_preroll; + gboolean have_preroll; + gboolean playing_async; + + /*< protected >*/ /* with STREAM_LOCK */ + gboolean have_newsegment; + GstSegment segment; + + /*< private >*/ /* with LOCK */ + GstClockID clock_id; + gboolean sync; + gboolean flushing; + gboolean running; + + gint64 max_lateness; + + /*< private >*/ + GstBaseSinkPrivate *priv; + + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +/** + * GstBaseSinkClass: + * @parent_class: Element parent class + * @get_caps: Called to get sink pad caps from the subclass + * @set_caps: Notify subclass of changed caps + * @fixate: Only useful in pull mode. Implement if you have + * ideas about what should be the default values for the caps you support. + * @activate_pull: Subclasses should override this when they can provide an + * alternate method of spawning a thread to drive the pipeline in pull mode. + * Should start or stop the pulling thread, depending on the value of the + * "active" argument. Called after actually activating the sink pad in pull + * mode. The default implementation starts a task on the sink pad. + * @get_times: Called to get the start and end times for synchronising + * the passed buffer to the clock + * @propose_allocation: configure the allocation query + * @start: Start processing. Ideal for opening resources in the subclass + * @stop: Stop processing. Subclasses should use this to close resources. + * @unlock: Unlock any pending access to the resource. Subclasses should + * unblock any blocked function ASAP and call gst_base_sink_wait_preroll() + * @unlock_stop: Clear the previous unlock request. Subclasses should clear + * any state they set during #GstBaseSinkClass.unlock(), and be ready to + * continue where they left off after gst_base_sink_wait_preroll(), + * gst_base_sink_wait() or gst_wait_sink_wait_clock() return or + * #GstBaseSinkClass.render() is called again. + * @query: perform a #GstQuery on the element. + * @event: Override this to handle events arriving on the sink pad + * @wait_event: Override this to implement custom logic to wait for the event + * time (for events like EOS and GAP). Subclasses should always first + * chain up to the default implementation. + * @prepare: Called to prepare the buffer for @render and @preroll. This + * function is called before synchronisation is performed. + * @prepare_list: Called to prepare the buffer list for @render_list. This + * function is called before synchronisation is performed. + * @preroll: Called to present the preroll buffer if desired. + * @render: Called when a buffer should be presented or output, at the + * correct moment if the #GstBaseSink has been set to sync to the clock. + * @render_list: Same as @render but used with buffer lists instead of + * buffers. + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At the minimum, the @render method should be overridden to + * output/present buffers. + */ +struct _GstBaseSinkClass { + GstElementClass parent_class; + + /* get caps from subclass */ + GstCaps* (*get_caps) (GstBaseSink *sink, GstCaps *filter); + /* notify subclass of new caps */ + gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps); + + /* fixate sink caps during pull-mode negotiation */ + GstCaps * (*fixate) (GstBaseSink *sink, GstCaps *caps); + /* start or stop a pulling thread */ + gboolean (*activate_pull)(GstBaseSink *sink, gboolean active); + + /* get the start and end times for syncing on this buffer */ + void (*get_times) (GstBaseSink *sink, GstBuffer *buffer, + GstClockTime *start, GstClockTime *end); + + /* propose allocation parameters for upstream */ + gboolean (*propose_allocation) (GstBaseSink *sink, GstQuery *query); + + /* start and stop processing, ideal for opening/closing the resource */ + gboolean (*start) (GstBaseSink *sink); + gboolean (*stop) (GstBaseSink *sink); + + /* unlock any pending access to the resource. subclasses should unlock + * any function ASAP. */ + gboolean (*unlock) (GstBaseSink *sink); + /* Clear a previously indicated unlock request not that unlocking is + * complete. Sub-classes should clear any command queue or indicator they + * set during unlock */ + gboolean (*unlock_stop) (GstBaseSink *sink); + + /* notify subclass of query */ + gboolean (*query) (GstBaseSink *sink, GstQuery *query); + + /* notify subclass of event */ + gboolean (*event) (GstBaseSink *sink, GstEvent *event); + /* wait for eos or gap, subclasses should chain up to parent first */ + GstFlowReturn (*wait_event) (GstBaseSink *sink, GstEvent *event); + + /* notify subclass of buffer or list before doing sync */ + GstFlowReturn (*prepare) (GstBaseSink *sink, GstBuffer *buffer); + GstFlowReturn (*prepare_list) (GstBaseSink *sink, GstBufferList *buffer_list); + + /* notify subclass of preroll buffer or real buffer */ + GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer); + GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer); + /* Render a BufferList */ + GstFlowReturn (*render_list) (GstBaseSink *sink, GstBufferList *buffer_list); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GST_BASE_API +GType gst_base_sink_get_type (void); + +GST_BASE_API +GstFlowReturn gst_base_sink_do_preroll (GstBaseSink *sink, GstMiniObject *obj); + +GST_BASE_API +GstFlowReturn gst_base_sink_wait_preroll (GstBaseSink *sink); + +/* synchronizing against the clock */ + +GST_BASE_API +void gst_base_sink_set_sync (GstBaseSink *sink, gboolean sync); + +GST_BASE_API +gboolean gst_base_sink_get_sync (GstBaseSink *sink); + +/* Drop buffers which are out of segment */ + +GST_BASE_API +void gst_base_sink_set_drop_out_of_segment (GstBaseSink *sink, gboolean drop_out_of_segment); + +GST_BASE_API +gboolean gst_base_sink_get_drop_out_of_segment (GstBaseSink *sink); + +/* dropping late buffers */ + +GST_BASE_API +void gst_base_sink_set_max_lateness (GstBaseSink *sink, gint64 max_lateness); + +GST_BASE_API +gint64 gst_base_sink_get_max_lateness (GstBaseSink *sink); + +/* performing QoS */ + +GST_BASE_API +void gst_base_sink_set_qos_enabled (GstBaseSink *sink, gboolean enabled); + +GST_BASE_API +gboolean gst_base_sink_is_qos_enabled (GstBaseSink *sink); + +/* doing async state changes */ + +GST_BASE_API +void gst_base_sink_set_async_enabled (GstBaseSink *sink, gboolean enabled); + +GST_BASE_API +gboolean gst_base_sink_is_async_enabled (GstBaseSink *sink); + +/* tuning synchronisation */ + +GST_BASE_API +void gst_base_sink_set_ts_offset (GstBaseSink *sink, GstClockTimeDiff offset); + +GST_BASE_API +GstClockTimeDiff gst_base_sink_get_ts_offset (GstBaseSink *sink); + +/* last sample */ + +GST_BASE_API +GstSample * gst_base_sink_get_last_sample (GstBaseSink *sink); + +GST_BASE_API +void gst_base_sink_set_last_sample_enabled (GstBaseSink *sink, gboolean enabled); + +GST_BASE_API +gboolean gst_base_sink_is_last_sample_enabled (GstBaseSink *sink); + +/* latency */ + +GST_BASE_API +gboolean gst_base_sink_query_latency (GstBaseSink *sink, gboolean *live, gboolean *upstream_live, + GstClockTime *min_latency, GstClockTime *max_latency); +GST_BASE_API +GstClockTime gst_base_sink_get_latency (GstBaseSink *sink); + +/* render delay */ + +GST_BASE_API +void gst_base_sink_set_render_delay (GstBaseSink *sink, GstClockTime delay); + +GST_BASE_API +GstClockTime gst_base_sink_get_render_delay (GstBaseSink *sink); + +/* blocksize */ + +GST_BASE_API +void gst_base_sink_set_blocksize (GstBaseSink *sink, guint blocksize); + +GST_BASE_API +guint gst_base_sink_get_blocksize (GstBaseSink *sink); + +/* throttle-time */ + +GST_BASE_API +void gst_base_sink_set_throttle_time (GstBaseSink *sink, guint64 throttle); + +GST_BASE_API +guint64 gst_base_sink_get_throttle_time (GstBaseSink *sink); + +/* max-bitrate */ + +GST_BASE_API +void gst_base_sink_set_max_bitrate (GstBaseSink *sink, guint64 max_bitrate); + +GST_BASE_API +guint64 gst_base_sink_get_max_bitrate (GstBaseSink *sink); + +GST_BASE_API +GstClockReturn gst_base_sink_wait_clock (GstBaseSink *sink, GstClockTime time, + GstClockTimeDiff * jitter); +GST_BASE_API +GstFlowReturn gst_base_sink_wait (GstBaseSink *sink, GstClockTime time, + GstClockTimeDiff *jitter); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSink, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BASE_SINK_H__ */ diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c new file mode 100644 index 0000000..fd046bf --- /dev/null +++ b/libs/gst/base/gstbasesrc.c @@ -0,0 +1,4034 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gstbasesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbasesrc + * @title: GstBaseSrc + * @short_description: Base class for getrange based source elements + * @see_also: #GstPushSrc, #GstBaseTransform, #GstBaseSink + * + * This is a generic base class for source elements. The following + * types of sources are supported: + * + * * random access sources like files + * * seekable sources + * * live sources + * + * The source can be configured to operate in any #GstFormat with the + * gst_base_src_set_format() method. The currently set format determines + * the format of the internal #GstSegment and any %GST_EVENT_SEGMENT + * events. The default format for #GstBaseSrc is %GST_FORMAT_BYTES. + * + * #GstBaseSrc always supports push mode scheduling. If the following + * conditions are met, it also supports pull mode scheduling: + * + * * The format is set to %GST_FORMAT_BYTES (default). + * * #GstBaseSrcClass.is_seekable() returns %TRUE. + * + * If all the conditions are met for operating in pull mode, #GstBaseSrc is + * automatically seekable in push mode as well. The following conditions must + * be met to make the element seekable in push mode when the format is not + * %GST_FORMAT_BYTES: + * + * * #GstBaseSrcClass.is_seekable() returns %TRUE. + * * #GstBaseSrcClass.query() can convert all supported seek formats to the + * internal format as set with gst_base_src_set_format(). + * * #GstBaseSrcClass.do_seek() is implemented, performs the seek and returns + * %TRUE. + * + * When the element does not meet the requirements to operate in pull mode, the + * offset and length in the #GstBaseSrcClass.create() method should be ignored. + * It is recommended to subclass #GstPushSrc instead, in this situation. If the + * element can operate in pull mode but only with specific offsets and + * lengths, it is allowed to generate an error when the wrong values are passed + * to the #GstBaseSrcClass.create() function. + * + * #GstBaseSrc has support for live sources. Live sources are sources that when + * paused discard data, such as audio or video capture devices. A typical live + * source also produces data at a fixed rate and thus provides a clock to publish + * this rate. + * Use gst_base_src_set_live() to activate the live source mode. + * + * A live source does not produce data in the PAUSED state. This means that the + * #GstBaseSrcClass.create() method will not be called in PAUSED but only in + * PLAYING. To signal the pipeline that the element will not produce data, the + * return value from the READY to PAUSED state will be + * %GST_STATE_CHANGE_NO_PREROLL. + * + * A typical live source will timestamp the buffers it creates with the + * current running time of the pipeline. This is one reason why a live source + * can only produce data in the PLAYING state, when the clock is actually + * distributed and running. + * + * Live sources that synchronize and block on the clock (an audio source, for + * example) can use gst_base_src_wait_playing() when the + * #GstBaseSrcClass.create() function was interrupted by a state change to + * PAUSED. + * + * The #GstBaseSrcClass.get_times() method can be used to implement pseudo-live + * sources. It only makes sense to implement the #GstBaseSrcClass.get_times() + * function if the source is a live source. The #GstBaseSrcClass.get_times() + * function should return timestamps starting from 0, as if it were a non-live + * source. The base class will make sure that the timestamps are transformed + * into the current running_time. The base source will then wait for the + * calculated running_time before pushing out the buffer. + * + * For live sources, the base class will by default report a latency of 0. + * For pseudo live sources, the base class will by default measure the difference + * between the first buffer timestamp and the start time of get_times and will + * report this value as the latency. + * Subclasses should override the query function when this behaviour is not + * acceptable. + * + * There is only support in #GstBaseSrc for exactly one source pad, which + * should be named "src". A source implementation (subclass of #GstBaseSrc) + * should install a pad template in its class_init function, like so: + * |[ + * static void + * my_element_class_init (GstMyElementClass *klass) + * { + * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + * // srctemplate should be a #GstStaticPadTemplate with direction + * // %GST_PAD_SRC and name "src" + * gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + * + * gst_element_class_set_static_metadata (gstelement_class, + * "Source name", + * "Source", + * "My Source element", + * "The author "); + * } + * ]| + * + * ## Controlled shutdown of live sources in applications + * + * Applications that record from a live source may want to stop recording + * in a controlled way, so that the recording is stopped, but the data + * already in the pipeline is processed to the end (remember that many live + * sources would go on recording forever otherwise). For that to happen the + * application needs to make the source stop recording and send an EOS + * event down the pipeline. The application would then wait for an + * EOS message posted on the pipeline's bus to know when all data has + * been processed and the pipeline can safely be stopped. + * + * An application may send an EOS event to a source element to make it + * perform the EOS logic (send EOS event downstream or post a + * %GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done + * with the gst_element_send_event() function on the element or its parent bin. + * + * After the EOS has been sent to the element, the application should wait for + * an EOS message to be posted on the pipeline's bus. Once this EOS message is + * received, it may safely shut down the entire pipeline. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include + +#include "gstbasesrc.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug); +#define GST_CAT_DEFAULT gst_base_src_debug + +#define GST_LIVE_GET_LOCK(elem) (&GST_BASE_SRC_CAST(elem)->live_lock) +#define GST_LIVE_LOCK(elem) g_mutex_lock(GST_LIVE_GET_LOCK(elem)) +#define GST_LIVE_TRYLOCK(elem) g_mutex_trylock(GST_LIVE_GET_LOCK(elem)) +#define GST_LIVE_UNLOCK(elem) g_mutex_unlock(GST_LIVE_GET_LOCK(elem)) +#define GST_LIVE_GET_COND(elem) (&GST_BASE_SRC_CAST(elem)->live_cond) +#define GST_LIVE_WAIT(elem) g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem)) +#define GST_LIVE_WAIT_UNTIL(elem, end_time) g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem), end_time) +#define GST_LIVE_SIGNAL(elem) g_cond_signal (GST_LIVE_GET_COND (elem)); +#define GST_LIVE_BROADCAST(elem) g_cond_broadcast (GST_LIVE_GET_COND (elem)); + + +#define GST_ASYNC_GET_COND(elem) (&GST_BASE_SRC_CAST(elem)->priv->async_cond) +#define GST_ASYNC_WAIT(elem) g_cond_wait (GST_ASYNC_GET_COND (elem), GST_OBJECT_GET_LOCK (elem)) +#define GST_ASYNC_SIGNAL(elem) g_cond_signal (GST_ASYNC_GET_COND (elem)); + +#define CLEAR_PENDING_EOS(bsrc) \ + G_STMT_START { \ + g_atomic_int_set (&bsrc->priv->has_pending_eos, FALSE); \ + gst_event_replace (&bsrc->priv->pending_eos, NULL); \ + } G_STMT_END + + +/* BaseSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_BLOCKSIZE 4096 +#define DEFAULT_NUM_BUFFERS -1 +#define DEFAULT_DO_TIMESTAMP FALSE + +enum +{ + PROP_0, + PROP_BLOCKSIZE, + PROP_NUM_BUFFERS, +#ifndef GST_REMOVE_DEPRECATED + PROP_TYPEFIND, +#endif + PROP_DO_TIMESTAMP +}; + +#define GST_BASE_SRC_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SRC, GstBaseSrcPrivate)) + +/* The basesrc implementation need to respect the following locking order: + * 1. STREAM_LOCK + * 2. LIVE_LOCK + * 3. OBJECT_LOCK + */ +struct _GstBaseSrcPrivate +{ + gboolean discont; /* STREAM_LOCK */ + gboolean flushing; /* LIVE_LOCK */ + + GstFlowReturn start_result; /* OBJECT_LOCK */ + gboolean async; /* OBJECT_LOCK */ + + /* if a stream-start event should be sent */ + gboolean stream_start_pending; /* STREAM_LOCK */ + + /* if segment should be sent and a + * seqnum if it was originated by a seek */ + gboolean segment_pending; /* OBJECT_LOCK */ + guint32 segment_seqnum; /* OBJECT_LOCK */ + + /* if EOS is pending (atomic) */ + GstEvent *pending_eos; /* OBJECT_LOCK */ + gint has_pending_eos; /* atomic */ + + /* if the eos was caused by a forced eos from the application */ + gboolean forced_eos; /* LIVE_LOCK */ + + /* startup latency is the time it takes between going to PLAYING and producing + * the first BUFFER with running_time 0. This value is included in the latency + * reporting. */ + GstClockTime latency; /* OBJECT_LOCK */ + /* timestamp offset, this is the offset add to the values of gst_times for + * pseudo live sources */ + GstClockTimeDiff ts_offset; /* OBJECT_LOCK */ + + gboolean do_timestamp; /* OBJECT_LOCK */ + volatile gint dynamic_size; /* atomic */ + volatile gint automatic_eos; /* atomic */ + + /* stream sequence number */ + guint32 seqnum; /* STREAM_LOCK */ + + /* pending events (TAG, CUSTOM_BOTH, CUSTOM_DOWNSTREAM) to be + * pushed in the data stream */ + GList *pending_events; /* OBJECT_LOCK */ + volatile gint have_events; /* OBJECT_LOCK */ + + /* QoS *//* with LOCK */ + gdouble proportion; /* OBJECT_LOCK */ + GstClockTime earliest_time; /* OBJECT_LOCK */ + + GstBufferPool *pool; /* OBJECT_LOCK */ + GstAllocator *allocator; /* OBJECT_LOCK */ + GstAllocationParams params; /* OBJECT_LOCK */ + + GCond async_cond; /* OBJECT_LOCK */ + + /* for _submit_buffer_list() */ + GstBufferList *pending_bufferlist; +}; + +#define BASE_SRC_HAS_PENDING_BUFFER_LIST(src) \ + ((src)->priv->pending_bufferlist != NULL) + +static GstElementClass *parent_class = NULL; + +static void gst_base_src_class_init (GstBaseSrcClass * klass); +static void gst_base_src_init (GstBaseSrc * src, gpointer g_class); +static void gst_base_src_finalize (GObject * object); + + +GType +gst_base_src_get_type (void) +{ + static volatile gsize base_src_type = 0; + + if (g_once_init_enter (&base_src_type)) { + GType _type; + static const GTypeInfo base_src_info = { + sizeof (GstBaseSrcClass), + NULL, + NULL, + (GClassInitFunc) gst_base_src_class_init, + NULL, + NULL, + sizeof (GstBaseSrc), + 0, + (GInstanceInitFunc) gst_base_src_init, + }; + + _type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT); + g_once_init_leave (&base_src_type, _type); + } + return base_src_type; +} + +static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc, + GstCaps * filter); +static GstCaps *gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps); +static GstCaps *gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps); + +static gboolean gst_base_src_is_random_access (GstBaseSrc * src); +static gboolean gst_base_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static void gst_base_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_base_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event); +static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event); + +static gboolean gst_base_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static void gst_base_src_set_pool_flushing (GstBaseSrc * basesrc, + gboolean flushing); +static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc); +static gboolean gst_base_src_default_do_seek (GstBaseSrc * src, + GstSegment * segment); +static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query); +static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, + GstEvent * event, GstSegment * segment); +static GstFlowReturn gst_base_src_default_create (GstBaseSrc * basesrc, + guint64 offset, guint size, GstBuffer ** buf); +static GstFlowReturn gst_base_src_default_alloc (GstBaseSrc * basesrc, + guint64 offset, guint size, GstBuffer ** buf); +static gboolean gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, + GstQuery * query); + +static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc, + gboolean flushing); + +static gboolean gst_base_src_start (GstBaseSrc * basesrc); +static gboolean gst_base_src_stop (GstBaseSrc * basesrc); + +static GstStateChangeReturn gst_base_src_change_state (GstElement * element, + GstStateChange transition); + +static void gst_base_src_loop (GstPad * pad); +static GstFlowReturn gst_base_src_getrange (GstPad * pad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buf); +static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset, + guint length, GstBuffer ** buf); +static gboolean gst_base_src_seekable (GstBaseSrc * src); +static gboolean gst_base_src_negotiate (GstBaseSrc * basesrc); +static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset, + guint * length, gboolean force); + +static void +gst_base_src_class_init (GstBaseSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element"); + + g_type_class_add_private (klass, sizeof (GstBaseSrcPrivate)); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_base_src_finalize; + gobject_class->set_property = gst_base_src_set_property; + gobject_class->get_property = gst_base_src_get_property; + + g_object_class_install_property (gobject_class, PROP_BLOCKSIZE, + g_param_spec_uint ("blocksize", "Block size", + "Size in bytes to read per buffer (-1 = default)", 0, G_MAXUINT, + DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to output before sending EOS (-1 = unlimited)", + -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +#ifndef GST_REMOVE_DEPRECATED + g_object_class_install_property (gobject_class, PROP_TYPEFIND, + g_param_spec_boolean ("typefind", "Typefind", + "Run typefind before negotiating (deprecated, non-functional)", FALSE, + G_PARAM_READWRITE | G_PARAM_DEPRECATED | G_PARAM_STATIC_STRINGS)); +#endif + g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP, + g_param_spec_boolean ("do-timestamp", "Do timestamp", + "Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_src_change_state); + gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event); + + klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_src_default_get_caps); + klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate); + klass->fixate = GST_DEBUG_FUNCPTR (gst_base_src_default_fixate); + klass->prepare_seek_segment = + GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment); + klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek); + klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query); + klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event); + klass->create = GST_DEBUG_FUNCPTR (gst_base_src_default_create); + klass->alloc = GST_DEBUG_FUNCPTR (gst_base_src_default_alloc); + klass->decide_allocation = + GST_DEBUG_FUNCPTR (gst_base_src_decide_allocation_default); + + /* Registering debug symbols for function pointers */ + GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_mode); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getrange); + GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate); +} + +static void +gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class) +{ + GstPad *pad; + GstPadTemplate *pad_template; + + basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc); + + basesrc->is_live = FALSE; + g_mutex_init (&basesrc->live_lock); + g_cond_init (&basesrc->live_cond); + basesrc->num_buffers = DEFAULT_NUM_BUFFERS; + basesrc->num_buffers_left = -1; + basesrc->priv->automatic_eos = TRUE; + + basesrc->can_activate_push = TRUE; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (pad_template != NULL); + + GST_DEBUG_OBJECT (basesrc, "creating src pad"); + pad = gst_pad_new_from_template (pad_template, "src"); + + GST_DEBUG_OBJECT (basesrc, "setting functions on src pad"); + gst_pad_set_activatemode_function (pad, gst_base_src_activate_mode); + gst_pad_set_event_function (pad, gst_base_src_event); + gst_pad_set_query_function (pad, gst_base_src_query); + gst_pad_set_getrange_function (pad, gst_base_src_getrange); + + /* hold pointer to pad */ + basesrc->srcpad = pad; + GST_DEBUG_OBJECT (basesrc, "adding src pad"); + gst_element_add_pad (GST_ELEMENT (basesrc), pad); + + basesrc->blocksize = DEFAULT_BLOCKSIZE; + basesrc->clock_id = NULL; + /* we operate in BYTES by default */ + gst_base_src_set_format (basesrc, GST_FORMAT_BYTES); + basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP; + g_atomic_int_set (&basesrc->priv->have_events, FALSE); + + g_cond_init (&basesrc->priv->async_cond); + basesrc->priv->start_result = GST_FLOW_FLUSHING; + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED); + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING); + GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_FLAG_SOURCE); + + GST_DEBUG_OBJECT (basesrc, "init done"); +} + +static void +gst_base_src_finalize (GObject * object) +{ + GstBaseSrc *basesrc; + GstEvent **event_p; + + basesrc = GST_BASE_SRC (object); + + g_mutex_clear (&basesrc->live_lock); + g_cond_clear (&basesrc->live_cond); + g_cond_clear (&basesrc->priv->async_cond); + + event_p = &basesrc->pending_seek; + gst_event_replace (event_p, NULL); + + if (basesrc->priv->pending_events) { + g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref, + NULL); + g_list_free (basesrc->priv->pending_events); + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* Call with LIVE_LOCK held */ +static GstFlowReturn +gst_base_src_wait_playing_unlocked (GstBaseSrc * src) +{ + while (G_UNLIKELY (!src->live_running && !src->priv->flushing)) { + /* block until the state changes, or we get a flush, or something */ + GST_DEBUG_OBJECT (src, "live source waiting for running state"); + GST_LIVE_WAIT (src); + GST_DEBUG_OBJECT (src, "live source unlocked"); + } + + if (src->priv->flushing) + goto flushing; + + return GST_FLOW_OK; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (src, "we are flushing"); + return GST_FLOW_FLUSHING; + } +} + + +/** + * gst_base_src_wait_playing: + * @src: the src + * + * If the #GstBaseSrcClass.create() method performs its own synchronisation + * against the clock it must unblock when going from PLAYING to the PAUSED state + * and call this method before continuing to produce the remaining data. + * + * This function will block until a state change to PLAYING happens (in which + * case this function returns %GST_FLOW_OK) or the processing must be stopped due + * to a state change to READY or a FLUSH event (in which case this function + * returns %GST_FLOW_FLUSHING). + * + * Returns: %GST_FLOW_OK if @src is PLAYING and processing can + * continue. Any other return value should be returned from the create vmethod. + */ +GstFlowReturn +gst_base_src_wait_playing (GstBaseSrc * src) +{ + GstFlowReturn ret; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), GST_FLOW_ERROR); + + GST_LIVE_LOCK (src); + ret = gst_base_src_wait_playing_unlocked (src); + GST_LIVE_UNLOCK (src); + + return ret; +} + +/** + * gst_base_src_set_live: + * @src: base source instance + * @live: new live-mode + * + * If the element listens to a live source, @live should + * be set to %TRUE. + * + * A live source will not produce data in the PAUSED state and + * will therefore not be able to participate in the PREROLL phase + * of a pipeline. To signal this fact to the application and the + * pipeline, the state change return value of the live source will + * be GST_STATE_CHANGE_NO_PREROLL. + */ +void +gst_base_src_set_live (GstBaseSrc * src, gboolean live) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + GST_OBJECT_LOCK (src); + src->is_live = live; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_is_live: + * @src: base source instance + * + * Check if an element is in live mode. + * + * Returns: %TRUE if element is in live mode. + */ +gboolean +gst_base_src_is_live (GstBaseSrc * src) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE); + + GST_OBJECT_LOCK (src); + result = src->is_live; + GST_OBJECT_UNLOCK (src); + + return result; +} + +/** + * gst_base_src_set_format: + * @src: base source instance + * @format: the format to use + * + * Sets the default format of the source. This will be the format used + * for sending SEGMENT events and for performing seeks. + * + * If a format of GST_FORMAT_BYTES is set, the element will be able to + * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns %TRUE. + * + * This function must only be called in states < %GST_STATE_PAUSED. + */ +void +gst_base_src_set_format (GstBaseSrc * src, GstFormat format) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + g_return_if_fail (GST_STATE (src) <= GST_STATE_READY); + + GST_OBJECT_LOCK (src); + gst_segment_init (&src->segment, format); + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_set_dynamic_size: + * @src: base source instance + * @dynamic: new dynamic size mode + * + * If not @dynamic, size is only updated when needed, such as when trying to + * read past current tracked size. Otherwise, size is checked for upon each + * read. + */ +void +gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + g_atomic_int_set (&src->priv->dynamic_size, dynamic); +} + +/** + * gst_base_src_set_automatic_eos: + * @src: base source instance + * @automatic_eos: automatic eos + * + * If @automatic_eos is %TRUE, @src will automatically go EOS if a buffer + * after the total size is returned. By default this is %TRUE but sources + * that can't return an authoritative size and only know that they're EOS + * when trying to read more should set this to %FALSE. + * + * Since: 1.4 + */ +void +gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + g_atomic_int_set (&src->priv->automatic_eos, automatic_eos); +} + +/** + * gst_base_src_set_async: + * @src: base source instance + * @async: new async mode + * + * Configure async behaviour in @src, no state change will block. The open, + * close, start, stop, play and pause virtual methods will be executed in a + * different thread and are thus allowed to perform blocking operations. Any + * blocking operation should be unblocked with the unlock vmethod. + */ +void +gst_base_src_set_async (GstBaseSrc * src, gboolean async) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + GST_OBJECT_LOCK (src); + src->priv->async = async; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_is_async: + * @src: base source instance + * + * Get the current async behaviour of @src. See also gst_base_src_set_async(). + * + * Returns: %TRUE if @src is operating in async mode. + */ +gboolean +gst_base_src_is_async (GstBaseSrc * src) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE); + + GST_OBJECT_LOCK (src); + res = src->priv->async; + GST_OBJECT_UNLOCK (src); + + return res; +} + + +/** + * gst_base_src_query_latency: + * @src: the source + * @live: (out) (allow-none): if the source is live + * @min_latency: (out) (allow-none): the min latency of the source + * @max_latency: (out) (allow-none): the max latency of the source + * + * Query the source for the latency parameters. @live will be %TRUE when @src is + * configured as a live source. @min_latency and @max_latency will be set + * to the difference between the running time and the timestamp of the first + * buffer. + * + * This function is mostly used by subclasses. + * + * Returns: %TRUE if the query succeeded. + */ +gboolean +gst_base_src_query_latency (GstBaseSrc * src, gboolean * live, + GstClockTime * min_latency, GstClockTime * max_latency) +{ + GstClockTime min; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE); + + GST_OBJECT_LOCK (src); + if (live) + *live = src->is_live; + + /* if we have a startup latency, report this one, else report 0. Subclasses + * are supposed to override the query function if they want something + * else. */ + if (src->priv->latency != -1) + min = src->priv->latency; + else + min = 0; + + if (min_latency) + *min_latency = min; + if (max_latency) + *max_latency = min; + + GST_LOG_OBJECT (src, "latency: live %d, min %" GST_TIME_FORMAT + ", max %" GST_TIME_FORMAT, src->is_live, GST_TIME_ARGS (min), + GST_TIME_ARGS (min)); + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +/** + * gst_base_src_set_blocksize: + * @src: the source + * @blocksize: the new blocksize in bytes + * + * Set the number of bytes that @src will push out with each buffer. When + * @blocksize is set to -1, a default length will be used. + */ +void +gst_base_src_set_blocksize (GstBaseSrc * src, guint blocksize) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + GST_OBJECT_LOCK (src); + src->blocksize = blocksize; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_get_blocksize: + * @src: the source + * + * Get the number of bytes that @src will push out with each buffer. + * + * Returns: the number of bytes pushed with each buffer. + */ +guint +gst_base_src_get_blocksize (GstBaseSrc * src) +{ + gint res; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), 0); + + GST_OBJECT_LOCK (src); + res = src->blocksize; + GST_OBJECT_UNLOCK (src); + + return res; +} + + +/** + * gst_base_src_set_do_timestamp: + * @src: the source + * @timestamp: enable or disable timestamping + * + * Configure @src to automatically timestamp outgoing buffers based on the + * current running_time of the pipeline. This property is mostly useful for live + * sources. + */ +void +gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + GST_OBJECT_LOCK (src); + src->priv->do_timestamp = timestamp; + if (timestamp && src->segment.format != GST_FORMAT_TIME) + gst_segment_init (&src->segment, GST_FORMAT_TIME); + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_get_do_timestamp: + * @src: the source + * + * Query if @src timestamps outgoing buffers based on the current running_time. + * + * Returns: %TRUE if the base class will automatically timestamp outgoing buffers. + */ +gboolean +gst_base_src_get_do_timestamp (GstBaseSrc * src) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE); + + GST_OBJECT_LOCK (src); + res = src->priv->do_timestamp; + GST_OBJECT_UNLOCK (src); + + return res; +} + +/** + * gst_base_src_new_seamless_segment: + * @src: The source + * @start: The new start value for the segment + * @stop: Stop value for the new segment + * @time: The new time value for the start of the new segment + * + * Prepare a new seamless segment for emission downstream. This function must + * only be called by derived sub-classes, and only from the create() function, + * as the stream-lock needs to be held. + * + * The format for the new segment will be the current format of the source, as + * configured with gst_base_src_set_format() + * + * Returns: %TRUE if preparation of the seamless segment succeeded. + */ +gboolean +gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop, + gint64 time) +{ + gboolean res = TRUE; + + GST_OBJECT_LOCK (src); + + src->segment.base = gst_segment_to_running_time (&src->segment, + src->segment.format, src->segment.position); + src->segment.position = src->segment.start = start; + src->segment.stop = stop; + src->segment.time = time; + + /* Mark pending segment. Will be sent before next data */ + src->priv->segment_pending = TRUE; + src->priv->segment_seqnum = gst_util_seqnum_next (); + + GST_DEBUG_OBJECT (src, + "Starting new seamless segment. Start %" GST_TIME_FORMAT " stop %" + GST_TIME_FORMAT " time %" GST_TIME_FORMAT " base %" GST_TIME_FORMAT, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time), + GST_TIME_ARGS (src->segment.base)); + + GST_OBJECT_UNLOCK (src); + + src->priv->discont = TRUE; + src->running = TRUE; + + return res; +} + +/* called with STREAM_LOCK */ +static gboolean +gst_base_src_send_stream_start (GstBaseSrc * src) +{ + gboolean ret = TRUE; + + if (src->priv->stream_start_pending) { + gchar *stream_id; + GstEvent *event; + + stream_id = + gst_pad_create_stream_id (src->srcpad, GST_ELEMENT_CAST (src), NULL); + + GST_DEBUG_OBJECT (src, "Pushing STREAM_START"); + event = gst_event_new_stream_start (stream_id); + gst_event_set_group_id (event, gst_util_group_id_next ()); + + ret = gst_pad_push_event (src->srcpad, event); + src->priv->stream_start_pending = FALSE; + g_free (stream_id); + } + + return ret; +} + +/** + * gst_base_src_set_caps: + * @src: a #GstBaseSrc + * @caps: (transfer none): a #GstCaps + * + * Set new caps on the basesrc source pad. + * + * Returns: %TRUE if the caps could be set + */ +gboolean +gst_base_src_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstBaseSrcClass *bclass; + gboolean res = TRUE; + GstCaps *current_caps; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + gst_base_src_send_stream_start (src); + + current_caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (src)); + if (current_caps && gst_caps_is_equal (current_caps, caps)) { + GST_DEBUG_OBJECT (src, "New caps equal to old ones: %" GST_PTR_FORMAT, + caps); + res = TRUE; + } else { + if (bclass->set_caps) + res = bclass->set_caps (src, caps); + + if (res) + res = gst_pad_push_event (src->srcpad, gst_event_new_caps (caps)); + } + + if (current_caps) + gst_caps_unref (current_caps); + + return res; +} + +static GstCaps * +gst_base_src_default_get_caps (GstBaseSrc * bsrc, GstCaps * filter) +{ + GstCaps *caps = NULL; + GstPadTemplate *pad_template; + GstBaseSrcClass *bclass; + + bclass = GST_BASE_SRC_GET_CLASS (bsrc); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); + + if (pad_template != NULL) { + caps = gst_pad_template_get_caps (pad_template); + + if (filter) { + GstCaps *intersection; + + intersection = + gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + caps = intersection; + } + } + return caps; +} + +static GstCaps * +gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps) +{ + GST_DEBUG_OBJECT (bsrc, "using default caps fixate function"); + return gst_caps_fixate (caps); +} + +static GstCaps * +gst_base_src_fixate (GstBaseSrc * bsrc, GstCaps * caps) +{ + GstBaseSrcClass *bclass; + + bclass = GST_BASE_SRC_GET_CLASS (bsrc); + + if (bclass->fixate) + caps = bclass->fixate (bsrc, caps); + + return caps; +} + +static gboolean +gst_base_src_default_query (GstBaseSrc * src, GstQuery * query) +{ + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + gst_query_parse_position (query, &format, NULL); + + GST_DEBUG_OBJECT (src, "position query in format %s", + gst_format_get_name (format)); + + switch (format) { + case GST_FORMAT_PERCENT: + { + gint64 percent; + gint64 position; + gint64 duration; + + GST_OBJECT_LOCK (src); + position = src->segment.position; + duration = src->segment.duration; + GST_OBJECT_UNLOCK (src); + + if (position != -1 && duration != -1) { + if (position < duration) + percent = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, position, + duration); + else + percent = GST_FORMAT_PERCENT_MAX; + } else + percent = -1; + + gst_query_set_position (query, GST_FORMAT_PERCENT, percent); + res = TRUE; + break; + } + default: + { + gint64 position; + GstFormat seg_format; + + GST_OBJECT_LOCK (src); + position = + gst_segment_to_stream_time (&src->segment, src->segment.format, + src->segment.position); + seg_format = src->segment.format; + GST_OBJECT_UNLOCK (src); + + if (position != -1) { + /* convert to requested format */ + res = + gst_pad_query_convert (src->srcpad, seg_format, + position, format, &position); + } else + res = TRUE; + + if (res) + gst_query_set_position (query, format, position); + + break; + } + } + break; + } + case GST_QUERY_DURATION: + { + GstFormat format; + + gst_query_parse_duration (query, &format, NULL); + + GST_DEBUG_OBJECT (src, "duration query in format %s", + gst_format_get_name (format)); + + switch (format) { + case GST_FORMAT_PERCENT: + gst_query_set_duration (query, GST_FORMAT_PERCENT, + GST_FORMAT_PERCENT_MAX); + res = TRUE; + break; + default: + { + gint64 duration; + GstFormat seg_format; + guint length = 0; + + /* may have to refresh duration */ + gst_base_src_update_length (src, 0, &length, + g_atomic_int_get (&src->priv->dynamic_size)); + + /* this is the duration as configured by the subclass. */ + GST_OBJECT_LOCK (src); + duration = src->segment.duration; + seg_format = src->segment.format; + GST_OBJECT_UNLOCK (src); + + GST_LOG_OBJECT (src, "duration %" G_GINT64_FORMAT ", format %s", + duration, gst_format_get_name (seg_format)); + + if (duration != -1) { + /* convert to requested format, if this fails, we have a duration + * but we cannot answer the query, we must return FALSE. */ + res = + gst_pad_query_convert (src->srcpad, seg_format, + duration, format, &duration); + } else { + /* The subclass did not configure a duration, we assume that the + * media has an unknown duration then and we return TRUE to report + * this. Note that this is not the same as returning FALSE, which + * means that we cannot report the duration at all. */ + res = TRUE; + } + + if (res) + gst_query_set_duration (query, format, duration); + + break; + } + } + break; + } + + case GST_QUERY_SEEKING: + { + GstFormat format, seg_format; + gint64 duration; + + GST_OBJECT_LOCK (src); + duration = src->segment.duration; + seg_format = src->segment.format; + GST_OBJECT_UNLOCK (src); + + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == seg_format) { + gst_query_set_seeking (query, seg_format, + gst_base_src_seekable (src), 0, duration); + res = TRUE; + } else { + /* FIXME 2.0: return TRUE + seekable=FALSE for SEEKING query here */ + /* Don't reply to the query to make up for demuxers which don't + * handle the SEEKING query yet. Players like Totem will fall back + * to the duration when the SEEKING query isn't answered. */ + res = FALSE; + } + break; + } + case GST_QUERY_SEGMENT: + { + GstFormat format; + gint64 start, stop; + + GST_OBJECT_LOCK (src); + + format = src->segment.format; + + start = + gst_segment_to_stream_time (&src->segment, format, + src->segment.start); + if ((stop = src->segment.stop) == -1) + stop = src->segment.duration; + else + stop = gst_segment_to_stream_time (&src->segment, format, stop); + + gst_query_set_segment (query, src->segment.rate, format, start, stop); + + GST_OBJECT_UNLOCK (src); + res = TRUE; + break; + } + + case GST_QUERY_FORMATS: + { + gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, + GST_FORMAT_BYTES, GST_FORMAT_PERCENT); + res = TRUE; + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + + /* we can only convert between equal formats... */ + if (src_fmt == dest_fmt) { + dest_val = src_val; + res = TRUE; + } else + res = FALSE; + + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + case GST_QUERY_LATENCY: + { + GstClockTime min, max; + gboolean live; + + /* Subclasses should override and implement something useful */ + res = gst_base_src_query_latency (src, &live, &min, &max); + + GST_LOG_OBJECT (src, "report latency: live %d, min %" GST_TIME_FORMAT + ", max %" GST_TIME_FORMAT, live, GST_TIME_ARGS (min), + GST_TIME_ARGS (max)); + + gst_query_set_latency (query, live, min, max); + break; + } + case GST_QUERY_JITTER: + case GST_QUERY_RATE: + res = FALSE; + break; + case GST_QUERY_BUFFERING: + { + GstFormat format, seg_format; + gint64 start, stop, estimated; + + gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL); + + GST_DEBUG_OBJECT (src, "buffering query in format %s", + gst_format_get_name (format)); + + GST_OBJECT_LOCK (src); + if (src->random_access) { + estimated = 0; + start = 0; + if (format == GST_FORMAT_PERCENT) + stop = GST_FORMAT_PERCENT_MAX; + else + stop = src->segment.duration; + } else { + estimated = -1; + start = -1; + stop = -1; + } + seg_format = src->segment.format; + GST_OBJECT_UNLOCK (src); + + /* convert to required format. When the conversion fails, we can't answer + * the query. When the value is unknown, we can don't perform conversion + * but report TRUE. */ + if (format != GST_FORMAT_PERCENT && stop != -1) { + res = gst_pad_query_convert (src->srcpad, seg_format, + stop, format, &stop); + } else { + res = TRUE; + } + if (res && format != GST_FORMAT_PERCENT && start != -1) + res = gst_pad_query_convert (src->srcpad, seg_format, + start, format, &start); + + gst_query_set_buffering_range (query, format, start, stop, estimated); + break; + } + case GST_QUERY_SCHEDULING: + { + gboolean random_access; + + random_access = gst_base_src_is_random_access (src); + + /* we can operate in getrange mode if the native format is bytes + * and we are seekable, this condition is set in the random_access + * flag and is set in the _start() method. */ + gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0); + if (random_access) + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + + res = TRUE; + break; + } + case GST_QUERY_CAPS: + { + GstBaseSrcClass *bclass; + GstCaps *caps, *filter; + + bclass = GST_BASE_SRC_GET_CLASS (src); + if (bclass->get_caps) { + gst_query_parse_caps (query, &filter); + if ((caps = bclass->get_caps (src, filter))) { + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + res = TRUE; + } else { + res = FALSE; + } + } else + res = FALSE; + break; + } + case GST_QUERY_URI:{ + if (GST_IS_URI_HANDLER (src)) { + gchar *uri = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + + if (uri != NULL) { + gst_query_set_uri (query, uri); + g_free (uri); + res = TRUE; + } else { + res = FALSE; + } + } else { + res = FALSE; + } + break; + } + default: + res = FALSE; + break; + } + GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query), + res); + + return res; +} + +static gboolean +gst_base_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstBaseSrc *src; + GstBaseSrcClass *bclass; + gboolean result = FALSE; + + src = GST_BASE_SRC (parent); + bclass = GST_BASE_SRC_GET_CLASS (src); + + if (bclass->query) + result = bclass->query (src, query); + + return result; +} + +static gboolean +gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment) +{ + gboolean res = TRUE; + + /* update our offset if the start/stop position was updated */ + if (segment->format == GST_FORMAT_BYTES) { + segment->time = segment->start; + } else if (segment->start == 0) { + /* seek to start, we can implement a default for this. */ + segment->time = 0; + } else { + res = FALSE; + GST_INFO_OBJECT (src, "Can't do a default seek"); + } + + return res; +} + +static gboolean +gst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment) +{ + GstBaseSrcClass *bclass; + gboolean result = FALSE; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + GST_INFO_OBJECT (src, "seeking: %" GST_SEGMENT_FORMAT, segment); + + if (bclass->do_seek) + result = bclass->do_seek (src, segment); + + return result; +} + +#define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET)) + +static gboolean +gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event, + GstSegment * segment) +{ + /* By default, we try one of 2 things: + * - For absolute seek positions, convert the requested position to our + * configured processing format and place it in the output segment \ + * - For relative seek positions, convert our current (input) values to the + * seek format, adjust by the relative seek offset and then convert back to + * the processing format + */ + GstSeekType start_type, stop_type; + gint64 start, stop; + GstSeekFlags flags; + GstFormat seek_format, dest_format; + gdouble rate; + gboolean update; + gboolean res = TRUE; + + gst_event_parse_seek (event, &rate, &seek_format, &flags, + &start_type, &start, &stop_type, &stop); + dest_format = segment->format; + + if (seek_format == dest_format) { + gst_segment_do_seek (segment, rate, seek_format, flags, + start_type, start, stop_type, stop, &update); + return TRUE; + } + + if (start_type != GST_SEEK_TYPE_NONE) { + /* FIXME: Handle seek_end by converting the input segment vals */ + res = + gst_pad_query_convert (src->srcpad, seek_format, start, dest_format, + &start); + start_type = GST_SEEK_TYPE_SET; + } + + if (res && stop_type != GST_SEEK_TYPE_NONE) { + /* FIXME: Handle seek_end by converting the input segment vals */ + res = + gst_pad_query_convert (src->srcpad, seek_format, stop, dest_format, + &stop); + stop_type = GST_SEEK_TYPE_SET; + } + + /* And finally, configure our output segment in the desired format */ + gst_segment_do_seek (segment, rate, dest_format, flags, start_type, start, + stop_type, stop, &update); + + if (!res) + goto no_format; + + return res; + +no_format: + { + GST_DEBUG_OBJECT (src, "undefined format given, seek aborted."); + return FALSE; + } +} + +static gboolean +gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event, + GstSegment * seeksegment) +{ + GstBaseSrcClass *bclass; + gboolean result = FALSE; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + if (bclass->prepare_seek_segment) + result = bclass->prepare_seek_segment (src, event, seeksegment); + + return result; +} + +static GstFlowReturn +gst_base_src_default_alloc (GstBaseSrc * src, guint64 offset, + guint size, GstBuffer ** buffer) +{ + GstFlowReturn ret; + GstBaseSrcPrivate *priv = src->priv; + GstBufferPool *pool = NULL; + GstAllocator *allocator = NULL; + GstAllocationParams params; + + GST_OBJECT_LOCK (src); + if (priv->pool) { + pool = gst_object_ref (priv->pool); + } else if (priv->allocator) { + allocator = gst_object_ref (priv->allocator); + } + params = priv->params; + GST_OBJECT_UNLOCK (src); + + if (pool) { + ret = gst_buffer_pool_acquire_buffer (pool, buffer, NULL); + } else if (size != -1) { + *buffer = gst_buffer_new_allocate (allocator, size, ¶ms); + if (G_UNLIKELY (*buffer == NULL)) + goto alloc_failed; + + ret = GST_FLOW_OK; + } else { + GST_WARNING_OBJECT (src, "Not trying to alloc %u bytes. Blocksize not set?", + size); + goto alloc_failed; + } + +done: + if (pool) + gst_object_unref (pool); + if (allocator) + gst_object_unref (allocator); + + return ret; + + /* ERRORS */ +alloc_failed: + { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size); + ret = GST_FLOW_ERROR; + goto done; + } +} + +static GstFlowReturn +gst_base_src_default_create (GstBaseSrc * src, guint64 offset, + guint size, GstBuffer ** buffer) +{ + GstBaseSrcClass *bclass; + GstFlowReturn ret; + GstBuffer *res_buf; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + if (G_UNLIKELY (!bclass->alloc)) + goto no_function; + if (G_UNLIKELY (!bclass->fill)) + goto no_function; + + if (*buffer == NULL) { + /* downstream did not provide us with a buffer to fill, allocate one + * ourselves */ + ret = bclass->alloc (src, offset, size, &res_buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto alloc_failed; + } else { + res_buf = *buffer; + } + + if (G_LIKELY (size > 0)) { + /* only call fill when there is a size */ + ret = bclass->fill (src, offset, size, res_buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto not_ok; + } + + *buffer = res_buf; + + return GST_FLOW_OK; + + /* ERRORS */ +no_function: + { + GST_DEBUG_OBJECT (src, "no fill or alloc function"); + return GST_FLOW_NOT_SUPPORTED; + } +alloc_failed: + { + GST_DEBUG_OBJECT (src, "Failed to allocate buffer of %u bytes", size); + return ret; + } +not_ok: + { + GST_DEBUG_OBJECT (src, "fill returned %d (%s)", ret, + gst_flow_get_name (ret)); + if (*buffer == NULL) + gst_buffer_unref (res_buf); + return ret; + } +} + +/* this code implements the seeking. It is a good example + * handling all cases. + * + * A seek updates the currently configured segment.start + * and segment.stop values based on the SEEK_TYPE. If the + * segment.start value is updated, a seek to this new position + * should be performed. + * + * The seek can only be executed when we are not currently + * streaming any data, to make sure that this is the case, we + * acquire the STREAM_LOCK which is taken when we are in the + * _loop() function or when a getrange() is called. Normally + * we will not receive a seek if we are operating in pull mode + * though. When we operate as a live source we might block on the live + * cond, which does not release the STREAM_LOCK. Therefore we will try + * to grab the LIVE_LOCK instead of the STREAM_LOCK to make sure it is + * safe to perform the seek. + * + * When we are in the loop() function, we might be in the middle + * of pushing a buffer, which might block in a sink. To make sure + * that the push gets unblocked we push out a FLUSH_START event. + * Our loop function will get a FLUSHING return value from + * the push and will pause, effectively releasing the STREAM_LOCK. + * + * For a non-flushing seek, we pause the task, which might eventually + * release the STREAM_LOCK. We say eventually because when the sink + * blocks on the sample we might wait a very long time until the sink + * unblocks the sample. In any case we acquire the STREAM_LOCK and + * can continue the seek. A non-flushing seek is normally done in a + * running pipeline to perform seamless playback, this means that the sink is + * PLAYING and will return from its chain function. + * In the case of a non-flushing seek we need to make sure that the + * data we output after the seek is continuous with the previous data, + * this is because a non-flushing seek does not reset the running-time + * to 0. We do this by closing the currently running segment, ie. sending + * a new_segment event with the stop position set to the last processed + * position. + * + * After updating the segment.start/stop values, we prepare for + * streaming again. We push out a FLUSH_STOP to make the peer pad + * accept data again and we start our task again. + * + * A segment seek posts a message on the bus saying that the playback + * of the segment started. We store the segment flag internally because + * when we reach the segment.stop we have to post a segment.done + * instead of EOS when doing a segment seek. + */ +static gboolean +gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock) +{ + gboolean res = TRUE, tres; + gdouble rate; + GstFormat seek_format, dest_format; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + gboolean flush; + gboolean update; + gboolean relative_seek = FALSE; + gboolean seekseg_configured = FALSE; + GstSegment seeksegment; + guint32 seqnum; + GstEvent *tevent; + + GST_DEBUG_OBJECT (src, "doing seek: %" GST_PTR_FORMAT, event); + + GST_OBJECT_LOCK (src); + dest_format = src->segment.format; + GST_OBJECT_UNLOCK (src); + + if (event) { + gst_event_parse_seek (event, &rate, &seek_format, &flags, + &start_type, &start, &stop_type, &stop); + + relative_seek = SEEK_TYPE_IS_RELATIVE (start_type) || + SEEK_TYPE_IS_RELATIVE (stop_type); + + if (dest_format != seek_format && !relative_seek) { + /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it + * here before taking the stream lock, otherwise we must convert it later, + * once we have the stream lock and can read the last configures segment + * start and stop positions */ + gst_segment_init (&seeksegment, dest_format); + + if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) + goto prepare_failed; + + seekseg_configured = TRUE; + } + + flush = flags & GST_SEEK_FLAG_FLUSH; + seqnum = gst_event_get_seqnum (event); + } else { + flush = FALSE; + /* get next seqnum */ + seqnum = gst_util_seqnum_next (); + } + + /* send flush start */ + if (flush) { + tevent = gst_event_new_flush_start (); + gst_event_set_seqnum (tevent, seqnum); + gst_pad_push_event (src->srcpad, tevent); + } else + gst_pad_pause_task (src->srcpad); + + /* unblock streaming thread. */ + if (unlock) + gst_base_src_set_flushing (src, TRUE); + + /* grab streaming lock, this should eventually be possible, either + * because the task is paused, our streaming thread stopped + * or because our peer is flushing. */ + GST_PAD_STREAM_LOCK (src->srcpad); + if (G_UNLIKELY (src->priv->seqnum == seqnum)) { + /* we have seen this event before, issue a warning for now */ + GST_WARNING_OBJECT (src, "duplicate event found %" G_GUINT32_FORMAT, + seqnum); + } else { + src->priv->seqnum = seqnum; + GST_DEBUG_OBJECT (src, "seek with seqnum %" G_GUINT32_FORMAT, seqnum); + } + + if (unlock) + gst_base_src_set_flushing (src, FALSE); + + /* If we configured the seeksegment above, don't overwrite it now. Otherwise + * copy the current segment info into the temp segment that we can actually + * attempt the seek with. We only update the real segment if the seek succeeds. */ + if (!seekseg_configured) { + memcpy (&seeksegment, &src->segment, sizeof (GstSegment)); + + /* now configure the final seek segment */ + if (event) { + if (seeksegment.format != seek_format) { + /* OK, here's where we give the subclass a chance to convert the relative + * seek into an absolute one in the processing format. We set up any + * absolute seek above, before taking the stream lock. */ + if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) { + GST_DEBUG_OBJECT (src, "Preparing the seek failed after flushing. " + "Aborting seek"); + res = FALSE; + } + } else { + /* The seek format matches our processing format, no need to ask the + * the subclass to configure the segment. */ + gst_segment_do_seek (&seeksegment, rate, seek_format, flags, + start_type, start, stop_type, stop, &update); + } + } + /* Else, no seek event passed, so we're just (re)starting the + current segment. */ + } + + if (res) { + GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT + " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT, + seeksegment.start, seeksegment.stop, seeksegment.position); + + /* do the seek, segment.position contains the new position. */ + res = gst_base_src_do_seek (src, &seeksegment); + } + + /* and prepare to continue streaming */ + if (flush) { + tevent = gst_event_new_flush_stop (TRUE); + gst_event_set_seqnum (tevent, seqnum); + /* send flush stop, peer will accept data and events again. We + * are not yet providing data as we still have the STREAM_LOCK. */ + gst_pad_push_event (src->srcpad, tevent); + } + + /* The subclass must have converted the segment to the processing format + * by now */ + if (res && seeksegment.format != dest_format) { + GST_DEBUG_OBJECT (src, "Subclass failed to prepare a seek segment " + "in the correct format. Aborting seek."); + res = FALSE; + } + + /* if the seek was successful, we update our real segment and push + * out the new segment. */ + if (res) { + GST_OBJECT_LOCK (src); + memcpy (&src->segment, &seeksegment, sizeof (GstSegment)); + GST_OBJECT_UNLOCK (src); + + if (seeksegment.flags & GST_SEGMENT_FLAG_SEGMENT) { + GstMessage *message; + + message = gst_message_new_segment_start (GST_OBJECT (src), + seeksegment.format, seeksegment.position); + gst_message_set_seqnum (message, seqnum); + + gst_element_post_message (GST_ELEMENT (src), message); + } + + src->priv->segment_pending = TRUE; + src->priv->segment_seqnum = seqnum; + } + + src->priv->discont = TRUE; + src->running = TRUE; + /* and restart the task in case it got paused explicitly or by + * the FLUSH_START event we pushed out. */ + tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, + src->srcpad, NULL); + if (res && !tres) + res = FALSE; + + /* and release the lock again so we can continue streaming */ + GST_PAD_STREAM_UNLOCK (src->srcpad); + + return res; + + /* ERROR */ +prepare_failed: + GST_DEBUG_OBJECT (src, "Preparing the seek failed before flushing. " + "Aborting seek"); + return FALSE; +} + +/* all events send to this element directly. This is mainly done from the + * application. + */ +static gboolean +gst_base_src_send_event (GstElement * element, GstEvent * event) +{ + GstBaseSrc *src; + gboolean result = FALSE; + GstBaseSrcClass *bclass; + + src = GST_BASE_SRC (element); + bclass = GST_BASE_SRC_GET_CLASS (src); + + GST_DEBUG_OBJECT (src, "handling event %p %" GST_PTR_FORMAT, event, event); + + switch (GST_EVENT_TYPE (event)) { + /* bidirectional events */ + case GST_EVENT_FLUSH_START: + GST_DEBUG_OBJECT (src, "pushing flush-start event downstream"); + + result = gst_pad_push_event (src->srcpad, event); + gst_base_src_set_flushing (src, TRUE); + event = NULL; + break; + case GST_EVENT_FLUSH_STOP: + { + gboolean start; + + GST_PAD_STREAM_LOCK (src->srcpad); + gst_base_src_set_flushing (src, FALSE); + + GST_DEBUG_OBJECT (src, "pushing flush-stop event downstream"); + result = gst_pad_push_event (src->srcpad, event); + + /* For external flush, restart the task .. */ + GST_LIVE_LOCK (src); + src->priv->segment_pending = TRUE; + + GST_OBJECT_LOCK (src->srcpad); + start = (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH); + GST_OBJECT_UNLOCK (src->srcpad); + + /* ... and for live sources, only if in playing state */ + if (src->is_live) { + if (!src->live_running) + start = FALSE; + } + + if (start) + gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, + src->srcpad, NULL); + + GST_LIVE_UNLOCK (src); + GST_PAD_STREAM_UNLOCK (src->srcpad); + + event = NULL; + break; + } + + /* downstream serialized events */ + case GST_EVENT_EOS: + { + gboolean push_mode; + + /* queue EOS and make sure the task or pull function performs the EOS + * actions. + * + * For push mode, This will be done in 3 steps. It is required to not + * block here as gst_element_send_event() will hold the STATE_LOCK, hence + * blocking would prevent asynchronous state change to complete. + * + * 1. We stop the streaming thread + * 2. We set the pending eos + * 3. We start the streaming thread again, so it is performed + * asynchronously. + * + * For pull mode, we simply mark the pending EOS without flushing. + */ + + GST_OBJECT_LOCK (src->srcpad); + push_mode = GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH; + GST_OBJECT_UNLOCK (src->srcpad); + + if (push_mode) { + gst_base_src_set_flushing (src, TRUE); + + GST_PAD_STREAM_LOCK (src->srcpad); + gst_base_src_set_flushing (src, FALSE); + + GST_OBJECT_LOCK (src); + g_atomic_int_set (&src->priv->has_pending_eos, TRUE); + if (src->priv->pending_eos) + gst_event_unref (src->priv->pending_eos); + src->priv->pending_eos = event; + GST_OBJECT_UNLOCK (src); + + GST_DEBUG_OBJECT (src, + "EOS marked, start task for asynchronous handling"); + gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, + src->srcpad, NULL); + + GST_PAD_STREAM_UNLOCK (src->srcpad); + } else { + /* In pull mode, we need not to return flushing to downstream, though + * the stream lock is not kept after getrange was unblocked */ + GST_OBJECT_LOCK (src); + g_atomic_int_set (&src->priv->has_pending_eos, TRUE); + if (src->priv->pending_eos) + gst_event_unref (src->priv->pending_eos); + src->priv->pending_eos = event; + GST_OBJECT_UNLOCK (src); + + gst_base_src_set_pool_flushing (src, TRUE); + if (bclass->unlock) + bclass->unlock (src); + + GST_PAD_STREAM_LOCK (src->srcpad); + if (bclass->unlock_stop) + bclass->unlock_stop (src); + gst_base_src_set_pool_flushing (src, TRUE); + GST_PAD_STREAM_UNLOCK (src->srcpad); + } + + + event = NULL; + result = TRUE; + break; + } + case GST_EVENT_SEGMENT: + /* sending random SEGMENT downstream can break sync. */ + break; + case GST_EVENT_TAG: + case GST_EVENT_SINK_MESSAGE: + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_BOTH: + case GST_EVENT_PROTECTION: + /* Insert TAG, CUSTOM_DOWNSTREAM, CUSTOM_BOTH, PROTECTION in the dataflow */ + GST_OBJECT_LOCK (src); + src->priv->pending_events = + g_list_append (src->priv->pending_events, event); + g_atomic_int_set (&src->priv->have_events, TRUE); + GST_OBJECT_UNLOCK (src); + event = NULL; + result = TRUE; + break; + case GST_EVENT_BUFFERSIZE: + /* does not seem to make much sense currently */ + break; + + /* upstream events */ + case GST_EVENT_QOS: + /* elements should override send_event and do something */ + break; + case GST_EVENT_SEEK: + { + gboolean started; + + GST_OBJECT_LOCK (src->srcpad); + if (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PULL) + goto wrong_mode; + started = GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH; + GST_OBJECT_UNLOCK (src->srcpad); + + if (started) { + GST_DEBUG_OBJECT (src, "performing seek"); + /* when we are running in push mode, we can execute the + * seek right now. */ + result = gst_base_src_perform_seek (src, event, TRUE); + } else { + GstEvent **event_p; + + /* else we store the event and execute the seek when we + * get activated */ + GST_OBJECT_LOCK (src); + GST_DEBUG_OBJECT (src, "queueing seek"); + event_p = &src->pending_seek; + gst_event_replace ((GstEvent **) event_p, event); + GST_OBJECT_UNLOCK (src); + /* assume the seek will work */ + result = TRUE; + } + break; + } + case GST_EVENT_NAVIGATION: + /* could make sense for elements that do something with navigation events + * but then they would need to override the send_event function */ + break; + case GST_EVENT_LATENCY: + /* does not seem to make sense currently */ + break; + + /* custom events */ + case GST_EVENT_CUSTOM_UPSTREAM: + /* override send_event if you want this */ + break; + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + case GST_EVENT_CUSTOM_BOTH_OOB: + /* insert a random custom event into the pipeline */ + GST_DEBUG_OBJECT (src, "pushing custom OOB event downstream"); + result = gst_pad_push_event (src->srcpad, event); + /* we gave away the ref to the event in the push */ + event = NULL; + break; + default: + break; + } +done: + /* if we still have a ref to the event, unref it now */ + if (event) + gst_event_unref (event); + + return result; + + /* ERRORS */ +wrong_mode: + { + GST_DEBUG_OBJECT (src, "cannot perform seek when operating in pull mode"); + GST_OBJECT_UNLOCK (src->srcpad); + result = FALSE; + goto done; + } +} + +static gboolean +gst_base_src_seekable (GstBaseSrc * src) +{ + GstBaseSrcClass *bclass; + bclass = GST_BASE_SRC_GET_CLASS (src); + if (bclass->is_seekable) + return bclass->is_seekable (src); + else + return FALSE; +} + +static void +gst_base_src_update_qos (GstBaseSrc * src, + gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp) +{ + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, src, + "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %" + GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp)); + + GST_OBJECT_LOCK (src); + src->priv->proportion = proportion; + src->priv->earliest_time = timestamp + diff; + GST_OBJECT_UNLOCK (src); +} + + +static gboolean +gst_base_src_default_event (GstBaseSrc * src, GstEvent * event) +{ + gboolean result; + + GST_DEBUG_OBJECT (src, "handle event %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* is normally called when in push mode */ + if (!gst_base_src_seekable (src)) + goto not_seekable; + + result = gst_base_src_perform_seek (src, event, TRUE); + break; + case GST_EVENT_FLUSH_START: + /* cancel any blocking getrange, is normally called + * when in pull mode. */ + result = gst_base_src_set_flushing (src, TRUE); + break; + case GST_EVENT_FLUSH_STOP: + result = gst_base_src_set_flushing (src, FALSE); + break; + case GST_EVENT_QOS: + { + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + + gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp); + gst_base_src_update_qos (src, proportion, diff, timestamp); + result = TRUE; + break; + } + case GST_EVENT_RECONFIGURE: + result = TRUE; + break; + case GST_EVENT_LATENCY: + result = TRUE; + break; + default: + result = FALSE; + break; + } + return result; + + /* ERRORS */ +not_seekable: + { + GST_DEBUG_OBJECT (src, "is not seekable"); + return FALSE; + } +} + +static gboolean +gst_base_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstBaseSrc *src; + GstBaseSrcClass *bclass; + gboolean result = FALSE; + + src = GST_BASE_SRC (parent); + bclass = GST_BASE_SRC_GET_CLASS (src); + + if (bclass->event) { + if (!(result = bclass->event (src, event))) + goto subclass_failed; + } + +done: + gst_event_unref (event); + + return result; + + /* ERRORS */ +subclass_failed: + { + GST_DEBUG_OBJECT (src, "subclass refused event"); + goto done; + } +} + +static void +gst_base_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASE_SRC (object); + + switch (prop_id) { + case PROP_BLOCKSIZE: + gst_base_src_set_blocksize (src, g_value_get_uint (value)); + break; + case PROP_NUM_BUFFERS: + src->num_buffers = g_value_get_int (value); + break; +#ifndef GST_REMOVE_DEPRECATED + case PROP_TYPEFIND: + src->typefind = g_value_get_boolean (value); + break; +#endif + case PROP_DO_TIMESTAMP: + gst_base_src_set_do_timestamp (src, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBaseSrc *src; + + src = GST_BASE_SRC (object); + + switch (prop_id) { + case PROP_BLOCKSIZE: + g_value_set_uint (value, gst_base_src_get_blocksize (src)); + break; + case PROP_NUM_BUFFERS: + g_value_set_int (value, src->num_buffers); + break; +#ifndef GST_REMOVE_DEPRECATED + case PROP_TYPEFIND: + g_value_set_boolean (value, src->typefind); + break; +#endif + case PROP_DO_TIMESTAMP: + g_value_set_boolean (value, gst_base_src_get_do_timestamp (src)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* with STREAM_LOCK and LOCK */ +static GstClockReturn +gst_base_src_wait (GstBaseSrc * basesrc, GstClock * clock, GstClockTime time) +{ + GstClockReturn ret; + GstClockID id; + + id = gst_clock_new_single_shot_id (clock, time); + + basesrc->clock_id = id; + /* release the live lock while waiting */ + GST_LIVE_UNLOCK (basesrc); + + ret = gst_clock_id_wait (id, NULL); + + GST_LIVE_LOCK (basesrc); + gst_clock_id_unref (id); + basesrc->clock_id = NULL; + + return ret; +} + +/* perform synchronisation on a buffer. + * with STREAM_LOCK. + */ +static GstClockReturn +gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer) +{ + GstClockReturn result; + GstClockTime start, end; + GstBaseSrcClass *bclass; + GstClockTime base_time; + GstClock *clock; + GstClockTime now = GST_CLOCK_TIME_NONE, pts, dts, timestamp; + gboolean do_timestamp, first, pseudo_live, is_live; + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + start = end = -1; + if (bclass->get_times) + bclass->get_times (basesrc, buffer, &start, &end); + + /* get buffer timestamp */ + dts = GST_BUFFER_DTS (buffer); + pts = GST_BUFFER_PTS (buffer); + + if (GST_CLOCK_TIME_IS_VALID (dts)) + timestamp = dts; + else + timestamp = pts; + + /* grab the lock to prepare for clocking and calculate the startup + * latency. */ + GST_OBJECT_LOCK (basesrc); + + is_live = basesrc->is_live; + /* if we are asked to sync against the clock we are a pseudo live element */ + pseudo_live = (start != -1 && is_live); + /* check for the first buffer */ + first = (basesrc->priv->latency == -1); + + if (timestamp != -1 && pseudo_live) { + GstClockTime latency; + + /* we have a timestamp and a sync time, latency is the diff */ + if (timestamp <= start) + latency = start - timestamp; + else + latency = 0; + + if (first) { + GST_DEBUG_OBJECT (basesrc, "pseudo_live with latency %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + /* first time we calculate latency, just configure */ + basesrc->priv->latency = latency; + } else { + if (basesrc->priv->latency != latency) { + /* we have a new latency, FIXME post latency message */ + basesrc->priv->latency = latency; + GST_DEBUG_OBJECT (basesrc, "latency changed to %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + } + } + } else if (first) { + GST_DEBUG_OBJECT (basesrc, "no latency needed, live %d, sync %d", + is_live, start != -1); + basesrc->priv->latency = 0; + } + + /* get clock, if no clock, we can't sync or do timestamps */ + if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL) + goto no_clock; + else + gst_object_ref (clock); + + base_time = GST_ELEMENT_CAST (basesrc)->base_time; + + do_timestamp = basesrc->priv->do_timestamp; + GST_OBJECT_UNLOCK (basesrc); + + /* first buffer, calculate the timestamp offset */ + if (first) { + GstClockTime running_time; + + now = gst_clock_get_time (clock); + running_time = now - base_time; + + GST_LOG_OBJECT (basesrc, + "startup PTS: %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT + ", running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (pts), + GST_TIME_ARGS (dts), GST_TIME_ARGS (running_time)); + + if (pseudo_live && timestamp != -1) { + /* live source and we need to sync, add startup latency to all timestamps + * to get the real running_time. Live sources should always timestamp + * according to the current running time. */ + basesrc->priv->ts_offset = GST_CLOCK_DIFF (timestamp, running_time); + + GST_LOG_OBJECT (basesrc, "live with sync, ts_offset %" GST_TIME_FORMAT, + GST_TIME_ARGS (basesrc->priv->ts_offset)); + } else { + basesrc->priv->ts_offset = 0; + GST_LOG_OBJECT (basesrc, "no timestamp offset needed"); + } + + if (!GST_CLOCK_TIME_IS_VALID (dts)) { + if (do_timestamp) { + dts = running_time; + } else if (!GST_CLOCK_TIME_IS_VALID (pts)) { + if (GST_CLOCK_TIME_IS_VALID (basesrc->segment.start)) { + dts = basesrc->segment.start; + } else { + dts = 0; + } + } + GST_BUFFER_DTS (buffer) = dts; + + GST_LOG_OBJECT (basesrc, "created DTS %" GST_TIME_FORMAT, + GST_TIME_ARGS (dts)); + } + } else { + /* not the first buffer, the timestamp is the diff between the clock and + * base_time */ + if (do_timestamp && !GST_CLOCK_TIME_IS_VALID (dts)) { + now = gst_clock_get_time (clock); + + dts = now - base_time; + GST_BUFFER_DTS (buffer) = dts; + + GST_LOG_OBJECT (basesrc, "created DTS %" GST_TIME_FORMAT, + GST_TIME_ARGS (dts)); + } + } + if (!GST_CLOCK_TIME_IS_VALID (pts)) { + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) + pts = dts; + + GST_BUFFER_PTS (buffer) = dts; + + GST_LOG_OBJECT (basesrc, "created PTS %" GST_TIME_FORMAT, + GST_TIME_ARGS (pts)); + } + + /* if we don't have a buffer timestamp, we don't sync */ + if (!GST_CLOCK_TIME_IS_VALID (start)) + goto no_sync; + + if (is_live) { + /* for pseudo live sources, add our ts_offset to the timestamp */ + if (GST_CLOCK_TIME_IS_VALID (pts)) + GST_BUFFER_PTS (buffer) += basesrc->priv->ts_offset; + if (GST_CLOCK_TIME_IS_VALID (dts)) + GST_BUFFER_DTS (buffer) += basesrc->priv->ts_offset; + start += basesrc->priv->ts_offset; + } + + GST_LOG_OBJECT (basesrc, + "waiting for clock, base time %" GST_TIME_FORMAT + ", stream_start %" GST_TIME_FORMAT, + GST_TIME_ARGS (base_time), GST_TIME_ARGS (start)); + + result = gst_base_src_wait (basesrc, clock, start + base_time); + + gst_object_unref (clock); + + GST_LOG_OBJECT (basesrc, "clock entry done: %d", result); + + return result; + + /* special cases */ +no_clock: + { + GST_DEBUG_OBJECT (basesrc, "we have no clock"); + GST_OBJECT_UNLOCK (basesrc); + return GST_CLOCK_OK; + } +no_sync: + { + GST_DEBUG_OBJECT (basesrc, "no sync needed"); + gst_object_unref (clock); + return GST_CLOCK_OK; + } +} + +/* Called with STREAM_LOCK and LIVE_LOCK */ +static gboolean +gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length, + gboolean force) +{ + guint64 size, maxsize; + GstBaseSrcClass *bclass; + gint64 stop; + + /* only operate if we are working with bytes */ + if (src->segment.format != GST_FORMAT_BYTES) + return TRUE; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + stop = src->segment.stop; + /* get total file size */ + size = src->segment.duration; + + /* when not doing automatic EOS, just use the stop position. We don't use + * the size to check for EOS */ + if (!g_atomic_int_get (&src->priv->automatic_eos)) + maxsize = stop; + /* Otherwise, the max amount of bytes to read is the total + * size or up to the segment.stop if present. */ + else if (stop != -1) + maxsize = size != -1 ? MIN (size, stop) : stop; + else + maxsize = size; + + GST_DEBUG_OBJECT (src, + "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT + ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset, + *length, size, stop, maxsize); + + /* check size if we have one */ + if (maxsize != -1) { + /* if we run past the end, check if the file became bigger and + * retry. Mind wrap when checking. */ + if (G_UNLIKELY (offset >= maxsize || offset + *length >= maxsize || force)) { + /* see if length of the file changed */ + if (bclass->get_size) + if (!bclass->get_size (src, &size)) + size = -1; + + /* when not doing automatic EOS, just use the stop position. We don't use + * the size to check for EOS */ + if (!g_atomic_int_get (&src->priv->automatic_eos)) + maxsize = stop; + /* Otherwise, the max amount of bytes to read is the total + * size or up to the segment.stop if present. */ + else if (stop != -1) + maxsize = size != -1 ? MIN (size, stop) : stop; + else + maxsize = size; + + if (maxsize != -1) { + /* if we are at or past the end, EOS */ + if (G_UNLIKELY (offset >= maxsize)) + goto unexpected_length; + + /* else we can clip to the end */ + if (G_UNLIKELY (offset + *length >= maxsize)) + *length = maxsize - offset; + } + } + } + + /* keep track of current duration. segment is in bytes, we checked + * that above. */ + GST_OBJECT_LOCK (src); + src->segment.duration = size; + GST_OBJECT_UNLOCK (src); + + return TRUE; + + /* ERRORS */ +unexpected_length: + { + GST_WARNING_OBJECT (src, "processing at or past EOS"); + return FALSE; + } +} + +/* must be called with LIVE_LOCK */ +static GstFlowReturn +gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, + GstBuffer ** buf) +{ + GstFlowReturn ret; + GstBaseSrcClass *bclass; + GstClockReturn status; + GstBuffer *res_buf; + GstBuffer *in_buf; + gboolean own_res_buf; + + bclass = GST_BASE_SRC_GET_CLASS (src); + +again: + if (src->is_live) { + if (G_UNLIKELY (!src->live_running)) { + ret = gst_base_src_wait_playing_unlocked (src); + if (ret != GST_FLOW_OK) + goto stopped; + } + } + + if (G_UNLIKELY (!GST_BASE_SRC_IS_STARTED (src) + && !GST_BASE_SRC_IS_STARTING (src))) + goto not_started; + + if (G_UNLIKELY (!bclass->create)) + goto no_function; + + if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length, FALSE))) + goto unexpected_length; + + /* track position */ + GST_OBJECT_LOCK (src); + if (src->segment.format == GST_FORMAT_BYTES) + src->segment.position = offset; + GST_OBJECT_UNLOCK (src); + + /* normally we don't count buffers */ + if (G_UNLIKELY (src->num_buffers_left >= 0)) { + if (src->num_buffers_left == 0) + goto reached_num_buffers; + else + src->num_buffers_left--; + } + + /* don't enter the create function if a pending EOS event was set. For the + * logic of the has_pending_eos, check the event function of this class. */ + if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) { + src->priv->forced_eos = TRUE; + goto eos; + } + + GST_DEBUG_OBJECT (src, + "calling create offset %" G_GUINT64_FORMAT " length %u, time %" + G_GINT64_FORMAT, offset, length, src->segment.time); + + res_buf = in_buf = *buf; + own_res_buf = (*buf == NULL); + + GST_LIVE_UNLOCK (src); + ret = bclass->create (src, offset, length, &res_buf); + GST_LIVE_LOCK (src); + + /* As we released the LIVE_LOCK, the state may have changed */ + if (src->is_live) { + if (G_UNLIKELY (!src->live_running)) { + GstFlowReturn wait_ret; + wait_ret = gst_base_src_wait_playing_unlocked (src); + if (wait_ret != GST_FLOW_OK) { + if (ret == GST_FLOW_OK && own_res_buf) + gst_buffer_unref (res_buf); + ret = wait_ret; + goto stopped; + } + } + } + + /* The create function could be unlocked because we have a pending EOS. It's + * possible that we have a valid buffer from create that we need to + * discard when the create function returned _OK. */ + if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) { + if (ret == GST_FLOW_OK) { + if (own_res_buf) + gst_buffer_unref (res_buf); + } + src->priv->forced_eos = TRUE; + goto eos; + } + + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto not_ok; + + /* fallback in case the create function didn't fill a provided buffer */ + if (in_buf != NULL && res_buf != in_buf) { + GstMapInfo info; + gsize copied_size; + + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, src, "create function didn't " + "fill the provided buffer, copying"); + + if (!gst_buffer_map (in_buf, &info, GST_MAP_WRITE)) + goto map_failed; + + copied_size = gst_buffer_extract (res_buf, 0, info.data, info.size); + gst_buffer_unmap (in_buf, &info); + gst_buffer_set_size (in_buf, copied_size); + + gst_buffer_copy_into (in_buf, res_buf, GST_BUFFER_COPY_METADATA, 0, -1); + + gst_buffer_unref (res_buf); + res_buf = in_buf; + } + + if (res_buf == NULL) { + GstBufferList *pending_list = src->priv->pending_bufferlist; + + if (pending_list == NULL || gst_buffer_list_length (pending_list) == 0) + goto null_buffer; + + res_buf = gst_buffer_list_get_writable (pending_list, 0); + own_res_buf = FALSE; + } + + /* no timestamp set and we are at offset 0, we can timestamp with 0 */ + if (offset == 0 && src->segment.time == 0 + && GST_BUFFER_DTS (res_buf) == -1 && !src->is_live) { + GST_DEBUG_OBJECT (src, "setting first timestamp to 0"); + res_buf = gst_buffer_make_writable (res_buf); + GST_BUFFER_DTS (res_buf) = 0; + } + + /* now sync before pushing the buffer */ + status = gst_base_src_do_sync (src, res_buf); + + /* waiting for the clock could have made us flushing */ + if (G_UNLIKELY (src->priv->flushing)) + goto flushing; + + switch (status) { + case GST_CLOCK_EARLY: + /* the buffer is too late. We currently don't drop the buffer. */ + GST_DEBUG_OBJECT (src, "buffer too late!, returning anyway"); + break; + case GST_CLOCK_OK: + /* buffer synchronised properly */ + GST_DEBUG_OBJECT (src, "buffer ok"); + break; + case GST_CLOCK_UNSCHEDULED: + /* this case is triggered when we were waiting for the clock and + * it got unlocked because we did a state change. In any case, get rid of + * the buffer. */ + if (own_res_buf) + gst_buffer_unref (res_buf); + + if (!src->live_running) { + /* We return FLUSHING when we are not running to stop the dataflow also + * get rid of the produced buffer. */ + GST_DEBUG_OBJECT (src, + "clock was unscheduled (%d), returning FLUSHING", status); + ret = GST_FLOW_FLUSHING; + } else { + /* If we are running when this happens, we quickly switched between + * pause and playing. We try to produce a new buffer */ + GST_DEBUG_OBJECT (src, + "clock was unscheduled (%d), but we are running", status); + goto again; + } + break; + default: + /* all other result values are unexpected and errors */ + GST_ELEMENT_ERROR (src, CORE, CLOCK, + (_("Internal clock error.")), + ("clock returned unexpected return value %d", status)); + if (own_res_buf) + gst_buffer_unref (res_buf); + ret = GST_FLOW_ERROR; + break; + } + if (G_LIKELY (ret == GST_FLOW_OK)) + *buf = res_buf; + + return ret; + + /* ERROR */ +stopped: + { + GST_DEBUG_OBJECT (src, "wait_playing returned %d (%s)", ret, + gst_flow_get_name (ret)); + return ret; + } +not_ok: + { + GST_DEBUG_OBJECT (src, "create returned %d (%s)", ret, + gst_flow_get_name (ret)); + return ret; + } +map_failed: + { + GST_ELEMENT_ERROR (src, RESOURCE, BUSY, + (_("Failed to map buffer.")), + ("failed to map result buffer in WRITE mode")); + if (own_res_buf) + gst_buffer_unref (res_buf); + return GST_FLOW_ERROR; + } +not_started: + { + GST_DEBUG_OBJECT (src, "getrange but not started"); + return GST_FLOW_FLUSHING; + } +no_function: + { + GST_DEBUG_OBJECT (src, "no create function"); + return GST_FLOW_NOT_SUPPORTED; + } +unexpected_length: + { + GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT + ", size=%" G_GINT64_FORMAT ")", length, offset, src->segment.duration); + return GST_FLOW_EOS; + } +reached_num_buffers: + { + GST_DEBUG_OBJECT (src, "sent all buffers"); + return GST_FLOW_EOS; + } +flushing: + { + GST_DEBUG_OBJECT (src, "we are flushing"); + if (own_res_buf) + gst_buffer_unref (res_buf); + return GST_FLOW_FLUSHING; + } +eos: + { + GST_DEBUG_OBJECT (src, "we are EOS"); + return GST_FLOW_EOS; + } +null_buffer: + { + GST_ELEMENT_ERROR (src, STREAM, FAILED, + (_("Internal data flow error.")), + ("Subclass %s neither returned a buffer nor submitted a buffer list " + "from its create function", G_OBJECT_TYPE_NAME (src))); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_base_src_getrange (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) +{ + GstBaseSrc *src; + GstFlowReturn res; + + src = GST_BASE_SRC_CAST (parent); + + GST_LIVE_LOCK (src); + if (G_UNLIKELY (src->priv->flushing)) + goto flushing; + + res = gst_base_src_get_range (src, offset, length, buf); + +done: + GST_LIVE_UNLOCK (src); + + return res; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (src, "we are flushing"); + res = GST_FLOW_FLUSHING; + goto done; + } +} + +static gboolean +gst_base_src_is_random_access (GstBaseSrc * src) +{ + /* we need to start the basesrc to check random access */ + if (!GST_BASE_SRC_IS_STARTED (src)) { + GST_LOG_OBJECT (src, "doing start/stop to check get_range support"); + if (G_LIKELY (gst_base_src_start (src))) { + if (gst_base_src_start_wait (src) != GST_FLOW_OK) + goto start_failed; + gst_base_src_stop (src); + } + } + + return src->random_access; + + /* ERRORS */ +start_failed: + { + GST_DEBUG_OBJECT (src, "failed to start"); + return FALSE; + } +} + +/* Called with STREAM_LOCK */ +static void +gst_base_src_loop (GstPad * pad) +{ + GstBaseSrc *src; + GstBuffer *buf = NULL; + GstFlowReturn ret; + gint64 position; + gboolean eos; + guint blocksize; + GList *pending_events = NULL, *tmp; + + eos = FALSE; + + src = GST_BASE_SRC (GST_OBJECT_PARENT (pad)); + + /* Just leave immediately if we're flushing */ + GST_LIVE_LOCK (src); + if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad))) + goto flushing; + GST_LIVE_UNLOCK (src); + + /* Just return if EOS is pushed again, as the app might be unaware that an + * EOS have been sent already */ + if (GST_PAD_IS_EOS (pad)) { + GST_DEBUG_OBJECT (src, "Pad is marked as EOS, pause the task"); + gst_pad_pause_task (pad); + goto done; + } + + gst_base_src_send_stream_start (src); + + /* The stream-start event could've caused something to flush us */ + GST_LIVE_LOCK (src); + if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad))) + goto flushing; + GST_LIVE_UNLOCK (src); + + /* check if we need to renegotiate */ + if (gst_pad_check_reconfigure (pad)) { + if (!gst_base_src_negotiate (src)) { + gst_pad_mark_reconfigure (pad); + if (GST_PAD_IS_FLUSHING (pad)) { + GST_LIVE_LOCK (src); + goto flushing; + } else { + goto negotiate_failed; + } + } + } + + GST_LIVE_LOCK (src); + + if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad))) + goto flushing; + + blocksize = src->blocksize; + + /* if we operate in bytes, we can calculate an offset */ + if (src->segment.format == GST_FORMAT_BYTES) { + position = src->segment.position; + /* for negative rates, start with subtracting the blocksize */ + if (src->segment.rate < 0.0) { + /* we cannot go below segment.start */ + if (position > src->segment.start + blocksize) + position -= blocksize; + else { + /* last block, remainder up to segment.start */ + blocksize = position - src->segment.start; + position = src->segment.start; + } + } + } else + position = -1; + + GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %u", + GST_TIME_ARGS (position), blocksize); + + /* clean up just in case we got interrupted or so last time round */ + if (src->priv->pending_bufferlist != NULL) { + gst_buffer_list_unref (src->priv->pending_bufferlist); + src->priv->pending_bufferlist = NULL; + } + + ret = gst_base_src_get_range (src, position, blocksize, &buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s", + gst_flow_get_name (ret)); + GST_LIVE_UNLOCK (src); + goto pause; + } + + /* Note: at this point buf might be a single buf returned which we own or + * the first buf of a pending buffer list submitted via submit_buffer_list(), + * in which case the buffer is owned by the pending buffer list and not us. */ + g_assert (buf != NULL); + + /* push events to close/start our segment before we push the buffer. */ + if (G_UNLIKELY (src->priv->segment_pending)) { + GstEvent *seg_event = gst_event_new_segment (&src->segment); + + gst_event_set_seqnum (seg_event, src->priv->segment_seqnum); + src->priv->segment_seqnum = gst_util_seqnum_next (); + gst_pad_push_event (pad, seg_event); + src->priv->segment_pending = FALSE; + } + + if (g_atomic_int_get (&src->priv->have_events)) { + GST_OBJECT_LOCK (src); + /* take the events */ + pending_events = src->priv->pending_events; + src->priv->pending_events = NULL; + g_atomic_int_set (&src->priv->have_events, FALSE); + GST_OBJECT_UNLOCK (src); + } + + /* Push out pending events if any */ + if (G_UNLIKELY (pending_events != NULL)) { + for (tmp = pending_events; tmp; tmp = g_list_next (tmp)) { + GstEvent *ev = (GstEvent *) tmp->data; + gst_pad_push_event (pad, ev); + } + g_list_free (pending_events); + } + + /* figure out the new position */ + switch (src->segment.format) { + case GST_FORMAT_BYTES: + { + guint bufsize = gst_buffer_get_size (buf); + + /* we subtracted above for negative rates */ + if (src->segment.rate >= 0.0) + position += bufsize; + break; + } + case GST_FORMAT_TIME: + { + GstClockTime start, duration; + + start = GST_BUFFER_TIMESTAMP (buf); + duration = GST_BUFFER_DURATION (buf); + + if (GST_CLOCK_TIME_IS_VALID (start)) + position = start; + else + position = src->segment.position; + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + if (src->segment.rate >= 0.0) + position += duration; + else if (position > duration) + position -= duration; + else + position = 0; + } + break; + } + case GST_FORMAT_DEFAULT: + if (src->segment.rate >= 0.0) + position = GST_BUFFER_OFFSET_END (buf); + else + position = GST_BUFFER_OFFSET (buf); + break; + default: + position = -1; + break; + } + if (position != -1) { + if (src->segment.rate >= 0.0) { + /* positive rate, check if we reached the stop */ + if (src->segment.stop != -1) { + if (position >= src->segment.stop) { + eos = TRUE; + position = src->segment.stop; + } + } + } else { + /* negative rate, check if we reached the start. start is always set to + * something different from -1 */ + if (position <= src->segment.start) { + eos = TRUE; + position = src->segment.start; + } + /* when going reverse, all buffers are DISCONT */ + src->priv->discont = TRUE; + } + GST_OBJECT_LOCK (src); + src->segment.position = position; + GST_OBJECT_UNLOCK (src); + } + + if (G_UNLIKELY (src->priv->discont)) { + GST_INFO_OBJECT (src, "marking pending DISCONT"); + buf = gst_buffer_make_writable (buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + src->priv->discont = FALSE; + } + GST_LIVE_UNLOCK (src); + + /* push buffer or buffer list */ + if (src->priv->pending_bufferlist != NULL) { + ret = gst_pad_push_list (pad, src->priv->pending_bufferlist); + src->priv->pending_bufferlist = NULL; + } else { + ret = gst_pad_push (pad, buf); + } + + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + if (ret == GST_FLOW_NOT_NEGOTIATED) { + goto not_negotiated; + } + GST_INFO_OBJECT (src, "pausing after gst_pad_push() = %s", + gst_flow_get_name (ret)); + goto pause; + } + + /* Segment pending means that a new segment was configured + * during this loop run */ + if (G_UNLIKELY (eos && !src->priv->segment_pending)) { + GST_INFO_OBJECT (src, "pausing after end of segment"); + ret = GST_FLOW_EOS; + goto pause; + } + +done: + return; + + /* special cases */ +not_negotiated: + { + if (gst_pad_needs_reconfigure (pad)) { + GST_DEBUG_OBJECT (src, "Retrying to renegotiate"); + return; + } + /* fallthrough when push returns NOT_NEGOTIATED and we don't have + * a pending negotiation request on our srcpad */ + } +negotiate_failed: + { + GST_DEBUG_OBJECT (src, "Not negotiated"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto pause; + } +flushing: + { + GST_DEBUG_OBJECT (src, "we are flushing"); + GST_LIVE_UNLOCK (src); + ret = GST_FLOW_FLUSHING; + goto pause; + } +pause: + { + const gchar *reason = gst_flow_get_name (ret); + GstEvent *event; + + GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason); + src->running = FALSE; + gst_pad_pause_task (pad); + if (ret == GST_FLOW_EOS) { + gboolean flag_segment; + GstFormat format; + gint64 position; + + flag_segment = (src->segment.flags & GST_SEGMENT_FLAG_SEGMENT) != 0; + format = src->segment.format; + position = src->segment.position; + + /* perform EOS logic */ + if (src->priv->forced_eos) { + g_assert (g_atomic_int_get (&src->priv->has_pending_eos)); + GST_OBJECT_LOCK (src); + event = src->priv->pending_eos; + src->priv->pending_eos = NULL; + GST_OBJECT_UNLOCK (src); + + } else if (flag_segment) { + GstMessage *message; + + message = gst_message_new_segment_done (GST_OBJECT_CAST (src), + format, position); + gst_message_set_seqnum (message, src->priv->seqnum); + gst_element_post_message (GST_ELEMENT_CAST (src), message); + event = gst_event_new_segment_done (format, position); + gst_event_set_seqnum (event, src->priv->seqnum); + + } else { + event = gst_event_new_eos (); + gst_event_set_seqnum (event, src->priv->seqnum); + } + + gst_pad_push_event (pad, event); + src->priv->forced_eos = FALSE; + + } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_EOS) { + event = gst_event_new_eos (); + gst_event_set_seqnum (event, src->priv->seqnum); + /* for fatal errors we post an error message, post the error + * first so the app knows about the error first. + * Also don't do this for FLUSHING because it happens + * due to flushing and posting an error message because of + * that is the wrong thing to do, e.g. when we're doing + * a flushing seek. */ + GST_ELEMENT_FLOW_ERROR (src, ret); + gst_pad_push_event (pad, event); + } + goto done; + } +} + +static gboolean +gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool, + GstAllocator * allocator, GstAllocationParams * params) +{ + GstAllocator *oldalloc; + GstBufferPool *oldpool; + GstBaseSrcPrivate *priv = basesrc->priv; + + if (pool) { + GST_DEBUG_OBJECT (basesrc, "activate pool"); + if (!gst_buffer_pool_set_active (pool, TRUE)) + goto activate_failed; + } + + GST_OBJECT_LOCK (basesrc); + oldpool = priv->pool; + priv->pool = pool; + + oldalloc = priv->allocator; + priv->allocator = allocator; + + if (priv->pool) + gst_object_ref (priv->pool); + if (priv->allocator) + gst_object_ref (priv->allocator); + + if (params) + priv->params = *params; + else + gst_allocation_params_init (&priv->params); + GST_OBJECT_UNLOCK (basesrc); + + if (oldpool) { + /* only deactivate if the pool is not the one we're using */ + if (oldpool != pool) { + GST_DEBUG_OBJECT (basesrc, "deactivate old pool"); + gst_buffer_pool_set_active (oldpool, FALSE); + } + gst_object_unref (oldpool); + } + if (oldalloc) { + gst_object_unref (oldalloc); + } + return TRUE; + + /* ERRORS */ +activate_failed: + { + GST_ERROR_OBJECT (basesrc, "failed to activate bufferpool."); + return FALSE; + } +} + +static void +gst_base_src_set_pool_flushing (GstBaseSrc * basesrc, gboolean flushing) +{ + GstBaseSrcPrivate *priv = basesrc->priv; + GstBufferPool *pool; + + GST_OBJECT_LOCK (basesrc); + if ((pool = priv->pool)) + pool = gst_object_ref (pool); + GST_OBJECT_UNLOCK (basesrc); + + if (pool) { + gst_buffer_pool_set_flushing (pool, flushing); + gst_object_unref (pool); + } +} + + +static gboolean +gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, GstQuery * query) +{ + GstCaps *outcaps; + GstBufferPool *pool; + guint size, min, max; + GstAllocator *allocator; + GstAllocationParams params; + GstStructure *config; + gboolean update_allocator; + + gst_query_parse_allocation (query, &outcaps, NULL); + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + /* try the allocator */ + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + update_allocator = TRUE; + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + update_allocator = FALSE; + } + + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); + + if (pool == NULL) { + /* no pool, we can make our own */ + GST_DEBUG_OBJECT (basesrc, "no pool, making new pool"); + pool = gst_buffer_pool_new (); + } + } else { + pool = NULL; + size = min = max = 0; + } + + /* now configure */ + if (pool) { + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, outcaps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + + /* buffer pool may have to do some changes */ + if (!gst_buffer_pool_set_config (pool, config)) { + config = gst_buffer_pool_get_config (pool); + + /* If change are not acceptable, fallback to generic pool */ + if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min, + max)) { + GST_DEBUG_OBJECT (basesrc, "unsupported pool, making new pool"); + + gst_object_unref (pool); + pool = gst_buffer_pool_new (); + gst_buffer_pool_config_set_params (config, outcaps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + } + + if (!gst_buffer_pool_set_config (pool, config)) + goto config_failed; + } + } + + if (update_allocator) + gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms); + else + gst_query_add_allocation_param (query, allocator, ¶ms); + if (allocator) + gst_object_unref (allocator); + + if (pool) { + gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); + gst_object_unref (pool); + } + + return TRUE; + +config_failed: + GST_ELEMENT_ERROR (basesrc, RESOURCE, SETTINGS, + ("Failed to configure the buffer pool"), + ("Configuration is most likely invalid, please report this issue.")); + gst_object_unref (pool); + return FALSE; +} + +static gboolean +gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps) +{ + GstBaseSrcClass *bclass; + gboolean result = TRUE; + GstQuery *query; + GstBufferPool *pool = NULL; + GstAllocator *allocator = NULL; + GstAllocationParams params; + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + /* make query and let peer pad answer, we don't really care if it worked or + * not, if it failed, the allocation query would contain defaults and the + * subclass would then set better values if needed */ + query = gst_query_new_allocation (caps, TRUE); + if (!gst_pad_peer_query (basesrc->srcpad, query)) { + /* not a problem, just debug a little */ + GST_DEBUG_OBJECT (basesrc, "peer ALLOCATION query failed"); + } + + g_assert (bclass->decide_allocation != NULL); + result = bclass->decide_allocation (basesrc, query); + + GST_DEBUG_OBJECT (basesrc, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, + query); + + if (!result) + goto no_decide_allocation; + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + } + + if (gst_query_get_n_allocation_pools (query) > 0) + gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); + + result = gst_base_src_set_allocation (basesrc, pool, allocator, ¶ms); + + if (allocator) + gst_object_unref (allocator); + if (pool) + gst_object_unref (pool); + + gst_query_unref (query); + + return result; + + /* Errors */ +no_decide_allocation: + { + GST_WARNING_OBJECT (basesrc, "Subclass failed to decide allocation"); + gst_query_unref (query); + + return result; + } +} + +/* default negotiation code. + * + * Take intersection between src and sink pads, take first + * caps and fixate. + */ +static gboolean +gst_base_src_default_negotiate (GstBaseSrc * basesrc) +{ + GstCaps *thiscaps; + GstCaps *caps = NULL; + GstCaps *peercaps = NULL; + gboolean result = FALSE; + + /* first see what is possible on our source pad */ + thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL); + GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps); + /* nothing or anything is allowed, we're done */ + if (thiscaps == NULL || gst_caps_is_any (thiscaps)) + goto no_nego_needed; + + if (G_UNLIKELY (gst_caps_is_empty (thiscaps))) + goto no_caps; + + /* get the peer caps */ + peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), thiscaps); + GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps); + if (peercaps) { + /* The result is already a subset of our caps */ + caps = peercaps; + gst_caps_unref (thiscaps); + } else { + /* no peer, work with our own caps then */ + caps = thiscaps; + } + if (caps && !gst_caps_is_empty (caps)) { + /* now fixate */ + GST_DEBUG_OBJECT (basesrc, "have caps: %" GST_PTR_FORMAT, caps); + if (gst_caps_is_any (caps)) { + GST_DEBUG_OBJECT (basesrc, "any caps, we stop"); + /* hmm, still anything, so element can do anything and + * nego is not needed */ + result = TRUE; + } else { + caps = gst_base_src_fixate (basesrc, caps); + GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); + if (gst_caps_is_fixed (caps)) { + /* yay, fixed caps, use those then, it's possible that the subclass does + * not accept this caps after all and we have to fail. */ + result = gst_base_src_set_caps (basesrc, caps); + } + } + gst_caps_unref (caps); + } else { + if (caps) + gst_caps_unref (caps); + GST_DEBUG_OBJECT (basesrc, "no common caps"); + } + return result; + +no_nego_needed: + { + GST_DEBUG_OBJECT (basesrc, "no negotiation needed"); + if (thiscaps) + gst_caps_unref (thiscaps); + return TRUE; + } +no_caps: + { + GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT, + ("No supported formats found"), + ("This element did not produce valid caps")); + if (thiscaps) + gst_caps_unref (thiscaps); + return TRUE; + } +} + +static gboolean +gst_base_src_negotiate (GstBaseSrc * basesrc) +{ + GstBaseSrcClass *bclass; + gboolean result; + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + GST_DEBUG_OBJECT (basesrc, "starting negotiation"); + + if (G_LIKELY (bclass->negotiate)) + result = bclass->negotiate (basesrc); + else + result = TRUE; + + if (G_LIKELY (result)) { + GstCaps *caps; + + caps = gst_pad_get_current_caps (basesrc->srcpad); + + result = gst_base_src_prepare_allocation (basesrc, caps); + + if (caps) + gst_caps_unref (caps); + } + return result; +} + +static gboolean +gst_base_src_start (GstBaseSrc * basesrc) +{ + GstBaseSrcClass *bclass; + gboolean result; + + GST_LIVE_LOCK (basesrc); + + GST_OBJECT_LOCK (basesrc); + if (GST_BASE_SRC_IS_STARTING (basesrc)) + goto was_starting; + if (GST_BASE_SRC_IS_STARTED (basesrc)) + goto was_started; + + basesrc->priv->start_result = GST_FLOW_FLUSHING; + GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTING); + gst_segment_init (&basesrc->segment, basesrc->segment.format); + GST_OBJECT_UNLOCK (basesrc); + + basesrc->num_buffers_left = basesrc->num_buffers; + basesrc->running = FALSE; + basesrc->priv->segment_pending = FALSE; + basesrc->priv->segment_seqnum = gst_util_seqnum_next (); + basesrc->priv->forced_eos = FALSE; + GST_LIVE_UNLOCK (basesrc); + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + if (bclass->start) + result = bclass->start (basesrc); + else + result = TRUE; + + if (!result) + goto could_not_start; + + if (!gst_base_src_is_async (basesrc)) { + gst_base_src_start_complete (basesrc, GST_FLOW_OK); + /* not really waiting here, we call this to get the result + * from the start_complete call */ + result = gst_base_src_start_wait (basesrc) == GST_FLOW_OK; + } + + return result; + + /* ERROR */ +was_starting: + { + GST_DEBUG_OBJECT (basesrc, "was starting"); + GST_OBJECT_UNLOCK (basesrc); + GST_LIVE_UNLOCK (basesrc); + return TRUE; + } +was_started: + { + GST_DEBUG_OBJECT (basesrc, "was started"); + GST_OBJECT_UNLOCK (basesrc); + GST_LIVE_UNLOCK (basesrc); + return TRUE; + } +could_not_start: + { + GST_DEBUG_OBJECT (basesrc, "could not start"); + /* subclass is supposed to post a message but we post one as a fallback + * just in case. We don't have to call _stop. */ + GST_ELEMENT_ERROR (basesrc, CORE, STATE_CHANGE, (NULL), + ("Failed to start")); + gst_base_src_start_complete (basesrc, GST_FLOW_ERROR); + return FALSE; + } +} + +/** + * gst_base_src_start_complete: + * @basesrc: base source instance + * @ret: a #GstFlowReturn + * + * Complete an asynchronous start operation. When the subclass overrides the + * start method, it should call gst_base_src_start_complete() when the start + * operation completes either from the same thread or from an asynchronous + * helper thread. + */ +void +gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret) +{ + gboolean have_size; + guint64 size; + gboolean seekable; + GstFormat format; + GstPadMode mode; + GstEvent *event; + + if (ret != GST_FLOW_OK) + goto error; + + GST_DEBUG_OBJECT (basesrc, "starting source"); + format = basesrc->segment.format; + + /* figure out the size */ + have_size = FALSE; + size = -1; + if (format == GST_FORMAT_BYTES) { + GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + if (bclass->get_size) { + if (!(have_size = bclass->get_size (basesrc, &size))) + size = -1; + } + GST_DEBUG_OBJECT (basesrc, "setting size %" G_GUINT64_FORMAT, size); + /* only update the size when operating in bytes, subclass is supposed + * to set duration in the start method for other formats */ + GST_OBJECT_LOCK (basesrc); + basesrc->segment.duration = size; + GST_OBJECT_UNLOCK (basesrc); + } + + GST_DEBUG_OBJECT (basesrc, + "format: %s, have size: %d, size: %" G_GUINT64_FORMAT ", duration: %" + G_GINT64_FORMAT, gst_format_get_name (format), have_size, size, + basesrc->segment.duration); + + seekable = gst_base_src_seekable (basesrc); + GST_DEBUG_OBJECT (basesrc, "is seekable: %d", seekable); + + /* update for random access flag */ + basesrc->random_access = seekable && format == GST_FORMAT_BYTES; + + GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access); + + gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (basesrc)); + + GST_OBJECT_LOCK (basesrc->srcpad); + mode = GST_PAD_MODE (basesrc->srcpad); + GST_OBJECT_UNLOCK (basesrc->srcpad); + + /* take the stream lock here, we only want to let the task run when we have + * set the STARTED flag */ + GST_PAD_STREAM_LOCK (basesrc->srcpad); + switch (mode) { + case GST_PAD_MODE_PUSH: + /* do initial seek, which will start the task */ + GST_OBJECT_LOCK (basesrc); + event = basesrc->pending_seek; + basesrc->pending_seek = NULL; + GST_OBJECT_UNLOCK (basesrc); + + /* The perform seek code will start the task when finished. We don't have to + * unlock the streaming thread because it is not running yet */ + if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE))) + goto seek_failed; + + if (event) + gst_event_unref (event); + break; + case GST_PAD_MODE_PULL: + /* if not random_access, we cannot operate in pull mode for now */ + if (G_UNLIKELY (!basesrc->random_access)) + goto no_get_range; + break; + default: + goto not_activated_yet; + break; + } + + GST_OBJECT_LOCK (basesrc); + GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTED); + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING); + basesrc->priv->start_result = ret; + GST_ASYNC_SIGNAL (basesrc); + GST_OBJECT_UNLOCK (basesrc); + + GST_PAD_STREAM_UNLOCK (basesrc->srcpad); + + return; + +seek_failed: + { + GST_PAD_STREAM_UNLOCK (basesrc->srcpad); + GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek"); + gst_base_src_stop (basesrc); + if (event) + gst_event_unref (event); + ret = GST_FLOW_ERROR; + goto error; + } +no_get_range: + { + GST_PAD_STREAM_UNLOCK (basesrc->srcpad); + gst_base_src_stop (basesrc); + GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping"); + ret = GST_FLOW_ERROR; + goto error; + } +not_activated_yet: + { + GST_PAD_STREAM_UNLOCK (basesrc->srcpad); + gst_base_src_stop (basesrc); + GST_WARNING_OBJECT (basesrc, "pad not activated yet"); + ret = GST_FLOW_ERROR; + goto error; + } +error: + { + GST_OBJECT_LOCK (basesrc); + basesrc->priv->start_result = ret; + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING); + GST_ASYNC_SIGNAL (basesrc); + GST_OBJECT_UNLOCK (basesrc); + return; + } +} + +/** + * gst_base_src_start_wait: + * @basesrc: base source instance + * + * Wait until the start operation completes. + * + * Returns: a #GstFlowReturn. + */ +GstFlowReturn +gst_base_src_start_wait (GstBaseSrc * basesrc) +{ + GstFlowReturn result; + + GST_OBJECT_LOCK (basesrc); + while (GST_BASE_SRC_IS_STARTING (basesrc)) { + GST_ASYNC_WAIT (basesrc); + } + result = basesrc->priv->start_result; + GST_OBJECT_UNLOCK (basesrc); + + GST_DEBUG_OBJECT (basesrc, "got %s", gst_flow_get_name (result)); + + return result; +} + +static gboolean +gst_base_src_stop (GstBaseSrc * basesrc) +{ + GstBaseSrcClass *bclass; + gboolean result = TRUE; + + GST_DEBUG_OBJECT (basesrc, "stopping source"); + + /* flush all */ + gst_base_src_set_flushing (basesrc, TRUE); + + /* stop the task */ + gst_pad_stop_task (basesrc->srcpad); + /* stop flushing, this will balance unlock/unlock_stop calls */ + gst_base_src_set_flushing (basesrc, FALSE); + + GST_OBJECT_LOCK (basesrc); + if (!GST_BASE_SRC_IS_STARTED (basesrc) && !GST_BASE_SRC_IS_STARTING (basesrc)) + goto was_stopped; + + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING); + GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED); + basesrc->priv->start_result = GST_FLOW_FLUSHING; + GST_ASYNC_SIGNAL (basesrc); + GST_OBJECT_UNLOCK (basesrc); + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + if (bclass->stop) + result = bclass->stop (basesrc); + + if (basesrc->priv->pending_bufferlist != NULL) { + gst_buffer_list_unref (basesrc->priv->pending_bufferlist); + basesrc->priv->pending_bufferlist = NULL; + } + + gst_base_src_set_allocation (basesrc, NULL, NULL, NULL); + + return result; + +was_stopped: + { + GST_DEBUG_OBJECT (basesrc, "was stopped"); + GST_OBJECT_UNLOCK (basesrc); + return TRUE; + } +} + +/* start or stop flushing dataprocessing + */ +static gboolean +gst_base_src_set_flushing (GstBaseSrc * basesrc, gboolean flushing) +{ + GstBaseSrcClass *bclass; + + bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + GST_DEBUG_OBJECT (basesrc, "flushing %d", flushing); + + if (flushing) { + gst_base_src_set_pool_flushing (basesrc, TRUE); + /* unlock any subclasses to allow turning off the streaming thread */ + if (bclass->unlock) + bclass->unlock (basesrc); + } + + /* the live lock is released when we are blocked, waiting for playing, + * when we sync to the clock or creating a buffer */ + GST_LIVE_LOCK (basesrc); + basesrc->priv->flushing = flushing; + if (flushing) { + /* clear pending EOS if any */ + if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) { + GST_OBJECT_LOCK (basesrc); + CLEAR_PENDING_EOS (basesrc); + basesrc->priv->forced_eos = FALSE; + GST_OBJECT_UNLOCK (basesrc); + } + + /* unblock clock sync (if any) or any other blocking thing */ + if (basesrc->clock_id) + gst_clock_id_unschedule (basesrc->clock_id); + } else { + gst_base_src_set_pool_flushing (basesrc, FALSE); + + /* Drop all delayed events */ + GST_OBJECT_LOCK (basesrc); + if (basesrc->priv->pending_events) { + g_list_foreach (basesrc->priv->pending_events, (GFunc) gst_event_unref, + NULL); + g_list_free (basesrc->priv->pending_events); + basesrc->priv->pending_events = NULL; + g_atomic_int_set (&basesrc->priv->have_events, FALSE); + } + GST_OBJECT_UNLOCK (basesrc); + } + + GST_LIVE_SIGNAL (basesrc); + GST_LIVE_UNLOCK (basesrc); + + if (!flushing) { + /* Now wait for the stream lock to be released and clear our unlock request */ + GST_PAD_STREAM_LOCK (basesrc->srcpad); + if (bclass->unlock_stop) + bclass->unlock_stop (basesrc); + GST_PAD_STREAM_UNLOCK (basesrc->srcpad); + } + + return TRUE; +} + +/* the purpose of this function is to make sure that a live source blocks in the + * LIVE lock or leaves the LIVE lock and continues playing. */ +static gboolean +gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play) +{ + /* we are now able to grab the LIVE lock, when we get it, we can be + * waiting for PLAYING while blocked in the LIVE cond or we can be waiting + * for the clock. */ + GST_LIVE_LOCK (basesrc); + GST_DEBUG_OBJECT (basesrc, "unschedule clock"); + + /* unblock clock sync (if any) */ + if (basesrc->clock_id) + gst_clock_id_unschedule (basesrc->clock_id); + + /* configure what to do when we get to the LIVE lock. */ + GST_DEBUG_OBJECT (basesrc, "live running %d", live_play); + basesrc->live_running = live_play; + + if (live_play) { + gboolean start; + + /* for live sources we restart the timestamp correction */ + GST_OBJECT_LOCK (basesrc); + basesrc->priv->latency = -1; + GST_OBJECT_UNLOCK (basesrc); + /* have to restart the task in case it stopped because of the unlock when + * we went to PAUSED. Only do this if we operating in push mode. */ + GST_OBJECT_LOCK (basesrc->srcpad); + start = (GST_PAD_MODE (basesrc->srcpad) == GST_PAD_MODE_PUSH); + GST_OBJECT_UNLOCK (basesrc->srcpad); + if (start) + gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop, + basesrc->srcpad, NULL); + GST_DEBUG_OBJECT (basesrc, "signal"); + GST_LIVE_SIGNAL (basesrc); + } + GST_LIVE_UNLOCK (basesrc); + + return TRUE; +} + +static gboolean +gst_base_src_activate_push (GstPad * pad, GstObject * parent, gboolean active) +{ + GstBaseSrc *basesrc; + + basesrc = GST_BASE_SRC (parent); + + /* prepare subclass first */ + if (active) { + GST_DEBUG_OBJECT (basesrc, "Activating in push mode"); + + if (G_UNLIKELY (!basesrc->can_activate_push)) + goto no_push_activation; + + if (G_UNLIKELY (!gst_base_src_start (basesrc))) + goto error_start; + } else { + GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode"); + /* now we can stop the source */ + if (G_UNLIKELY (!gst_base_src_stop (basesrc))) + goto error_stop; + } + return TRUE; + + /* ERRORS */ +no_push_activation: + { + GST_WARNING_OBJECT (basesrc, "Subclass disabled push-mode activation"); + return FALSE; + } +error_start: + { + GST_WARNING_OBJECT (basesrc, "Failed to start in push mode"); + return FALSE; + } +error_stop: + { + GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode"); + return FALSE; + } +} + +static gboolean +gst_base_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active) +{ + GstBaseSrc *basesrc; + + basesrc = GST_BASE_SRC (parent); + + /* prepare subclass first */ + if (active) { + GST_DEBUG_OBJECT (basesrc, "Activating in pull mode"); + if (G_UNLIKELY (!gst_base_src_start (basesrc))) + goto error_start; + } else { + GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode"); + if (G_UNLIKELY (!gst_base_src_stop (basesrc))) + goto error_stop; + } + return TRUE; + + /* ERRORS */ +error_start: + { + GST_ERROR_OBJECT (basesrc, "Failed to start in pull mode"); + return FALSE; + } +error_stop: + { + GST_ERROR_OBJECT (basesrc, "Failed to stop in pull mode"); + return FALSE; + } +} + +static gboolean +gst_base_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstBaseSrc *src = GST_BASE_SRC (parent); + + src->priv->stream_start_pending = FALSE; + + GST_DEBUG_OBJECT (pad, "activating in mode %d", mode); + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_base_src_activate_pull (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + src->priv->stream_start_pending = active; + res = gst_base_src_activate_push (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + + +static GstStateChangeReturn +gst_base_src_change_state (GstElement * element, GstStateChange transition) +{ + GstBaseSrc *basesrc; + GstStateChangeReturn result; + gboolean no_preroll = FALSE; + + basesrc = GST_BASE_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + no_preroll = gst_base_src_is_live (basesrc); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_DEBUG_OBJECT (basesrc, "PAUSED->PLAYING"); + if (gst_base_src_is_live (basesrc)) { + /* now we can start playback */ + gst_base_src_set_playing (basesrc, TRUE); + } + break; + default: + break; + } + + if ((result = + GST_ELEMENT_CLASS (parent_class)->change_state (element, + transition)) == GST_STATE_CHANGE_FAILURE) + goto failure; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (basesrc, "PLAYING->PAUSED"); + if (gst_base_src_is_live (basesrc)) { + /* make sure we block in the live cond in PAUSED */ + gst_base_src_set_playing (basesrc, FALSE); + no_preroll = TRUE; + } + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + /* we don't need to unblock anything here, the pad deactivation code + * already did this */ + if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) { + GST_OBJECT_LOCK (basesrc); + CLEAR_PENDING_EOS (basesrc); + GST_OBJECT_UNLOCK (basesrc); + } + gst_event_replace (&basesrc->pending_seek, NULL); + break; + } + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + if (no_preroll && result == GST_STATE_CHANGE_SUCCESS) + result = GST_STATE_CHANGE_NO_PREROLL; + + return result; + + /* ERRORS */ +failure: + { + GST_DEBUG_OBJECT (basesrc, "parent failed state change"); + return result; + } +} + +/** + * gst_base_src_get_buffer_pool: + * @src: a #GstBaseSrc + * + * Returns: (transfer full): the instance of the #GstBufferPool used + * by the src; unref it after usage. + */ +GstBufferPool * +gst_base_src_get_buffer_pool (GstBaseSrc * src) +{ + GstBufferPool *ret = NULL; + + g_return_val_if_fail (GST_IS_BASE_SRC (src), NULL); + + GST_OBJECT_LOCK (src); + if (src->priv->pool) + ret = gst_object_ref (src->priv->pool); + GST_OBJECT_UNLOCK (src); + + return ret; +} + +/** + * gst_base_src_get_allocator: + * @src: a #GstBaseSrc + * @allocator: (out) (allow-none) (transfer full): the #GstAllocator + * used + * @params: (out) (allow-none) (transfer full): the + * #GstAllocationParams of @allocator + * + * Lets #GstBaseSrc sub-classes to know the memory @allocator + * used by the base class and its @params. + * + * Unref the @allocator after usage. + */ +void +gst_base_src_get_allocator (GstBaseSrc * src, + GstAllocator ** allocator, GstAllocationParams * params) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + GST_OBJECT_LOCK (src); + if (allocator) + *allocator = src->priv->allocator ? + gst_object_ref (src->priv->allocator) : NULL; + + if (params) + *params = src->priv->params; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_src_submit_buffer_list: + * @src: a #GstBaseSrc + * @buffer_list: (transfer full): a #GstBufferList + * + * Subclasses can call this from their create virtual method implementation + * to submit a buffer list to be pushed out later. This is useful in + * cases where the create function wants to produce multiple buffers to be + * pushed out in one go in form of a #GstBufferList, which can reduce overhead + * drastically, especially for packetised inputs (for data streams where + * the packetisation/chunking is not important it is usually more efficient + * to return larger buffers instead). + * + * Subclasses that use this function from their create function must return + * %GST_FLOW_OK and no buffer from their create virtual method implementation. + * If a buffer is returned after a buffer list has also been submitted via this + * function the behaviour is undefined. + * + * Subclasses must only call this function once per create function call and + * subclasses must only call this function when the source operates in push + * mode. + * + * Since: 1.14 + */ +void +gst_base_src_submit_buffer_list (GstBaseSrc * src, GstBufferList * buffer_list) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + g_return_if_fail (GST_IS_BUFFER_LIST (buffer_list)); + g_return_if_fail (BASE_SRC_HAS_PENDING_BUFFER_LIST (src) == FALSE); + + src->priv->pending_bufferlist = buffer_list; + + GST_LOG_OBJECT (src, "%u buffers submitted in buffer list", + gst_buffer_list_length (buffer_list)); +} diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h new file mode 100644 index 0000000..b782bbe --- /dev/null +++ b/libs/gst/base/gstbasesrc.h @@ -0,0 +1,324 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_SRC_H__ +#define __GST_BASE_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_SRC (gst_base_src_get_type()) +#define GST_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_SRC,GstBaseSrc)) +#define GST_BASE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_SRC,GstBaseSrcClass)) +#define GST_BASE_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_SRC, GstBaseSrcClass)) +#define GST_IS_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_SRC)) +#define GST_IS_BASE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_SRC)) +#define GST_BASE_SRC_CAST(obj) ((GstBaseSrc *)(obj)) + +/** + * GstBaseSrcFlags: + * @GST_BASE_SRC_FLAG_STARTING: has source is starting + * @GST_BASE_SRC_FLAG_STARTED: has source been started + * @GST_BASE_SRC_FLAG_LAST: offset to define more flags + * + * The #GstElement flags that a basesrc element may have. + */ +typedef enum { + GST_BASE_SRC_FLAG_STARTING = (GST_ELEMENT_FLAG_LAST << 0), + GST_BASE_SRC_FLAG_STARTED = (GST_ELEMENT_FLAG_LAST << 1), + /* padding */ + GST_BASE_SRC_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 6) +} GstBaseSrcFlags; + +#define GST_BASE_SRC_IS_STARTING(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTING) +#define GST_BASE_SRC_IS_STARTED(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTED) + +typedef struct _GstBaseSrc GstBaseSrc; +typedef struct _GstBaseSrcClass GstBaseSrcClass; +typedef struct _GstBaseSrcPrivate GstBaseSrcPrivate; + +/** + * GST_BASE_SRC_PAD: + * @obj: base source instance + * + * Gives the pointer to the #GstPad object of the element. + */ +#define GST_BASE_SRC_PAD(obj) (GST_BASE_SRC_CAST (obj)->srcpad) + + +/** + * GstBaseSrc: + * + * The opaque #GstBaseSrc data structure. + */ +struct _GstBaseSrc { + GstElement element; + + /*< protected >*/ + GstPad *srcpad; + + /* available to subclass implementations */ + /* MT-protected (with LIVE_LOCK) */ + GMutex live_lock; + GCond live_cond; + gboolean is_live; + gboolean live_running; + + /* MT-protected (with LOCK) */ + guint blocksize; /* size of buffers when operating push based */ + gboolean can_activate_push; /* some scheduling properties */ + gboolean random_access; + + GstClockID clock_id; /* for syncing */ + + /* MT-protected (with STREAM_LOCK *and* OBJECT_LOCK) */ + GstSegment segment; + /* MT-protected (with STREAM_LOCK) */ + gboolean need_newsegment; + + gint num_buffers; + gint num_buffers_left; + +#ifndef GST_REMOVE_DEPRECATED + gboolean typefind; /* unused */ +#endif + + gboolean running; + GstEvent *pending_seek; + + GstBaseSrcPrivate *priv; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +/** + * GstBaseSrcClass: + * @parent_class: Element parent class + * @get_caps: Called to get the caps to report + * @negotiate: Negotiated the caps with the peer. + * @fixate: Called during negotiation if caps need fixating. Implement instead of + * setting a fixate function on the source pad. + * @set_caps: Notify subclass of changed output caps + * @decide_allocation: configure the allocation query + * @start: Start processing. Subclasses should open resources and prepare + * to produce data. Implementation should call gst_base_src_start_complete() + * when the operation completes, either from the current thread or any other + * thread that finishes the start operation asynchronously. + * @stop: Stop processing. Subclasses should use this to close resources. + * @get_times: Given a buffer, return the start and stop time when it + * should be pushed out. The base class will sync on the clock using + * these times. + * @get_size: Return the total size of the resource, in the format set by + * gst_base_src_set_format(). + * @is_seekable: Check if the source can seek + * @prepare_seek_segment: Prepare the #GstSegment that will be passed to the + * #GstBaseSrcClass.do_seek() vmethod for executing a seek + * request. Sub-classes should override this if they support seeking in + * formats other than the configured native format. By default, it tries to + * convert the seek arguments to the configured native format and prepare a + * segment in that format. + * @do_seek: Perform seeking on the resource to the indicated segment. + * @unlock: Unlock any pending access to the resource. Subclasses should unblock + * any blocked function ASAP. In particular, any create() function in + * progress should be unblocked and should return GST_FLOW_FLUSHING. Any + * future #GstBaseSrcClass.create() function call should also return + * GST_FLOW_FLUSHING until the #GstBaseSrcClass.unlock_stop() function has + * been called. + * @unlock_stop: Clear the previous unlock request. Subclasses should clear any + * state they set during #GstBaseSrcClass.unlock(), such as clearing command + * queues. + * @query: Handle a requested query. + * @event: Override this to implement custom event handling. + * @create: Ask the subclass to create a buffer with offset and size. When the + * subclass returns GST_FLOW_OK, it MUST return a buffer of the requested size + * unless fewer bytes are available because an EOS condition is near. No + * buffer should be returned when the return value is different from + * GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the end of + * stream is reached. The default implementation will call + * #GstBaseSrcClass.alloc() and then call #GstBaseSrcClass.fill(). + * @alloc: Ask the subclass to allocate a buffer with for offset and size. The + * default implementation will create a new buffer from the negotiated allocator. + * @fill: Ask the subclass to fill the buffer with data for offset and size. The + * passed buffer is guaranteed to hold the requested amount of bytes. + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At the minimum, the @create method should be overridden to produce + * buffers. + */ +struct _GstBaseSrcClass { + GstElementClass parent_class; + + /*< public >*/ + /* virtual methods for subclasses */ + + /* get caps from subclass */ + GstCaps* (*get_caps) (GstBaseSrc *src, GstCaps *filter); + /* decide on caps */ + gboolean (*negotiate) (GstBaseSrc *src); + /* called if, in negotiation, caps need fixating */ + GstCaps * (*fixate) (GstBaseSrc *src, GstCaps *caps); + /* notify the subclass of new caps */ + gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps); + + /* setup allocation query */ + gboolean (*decide_allocation) (GstBaseSrc *src, GstQuery *query); + + /* start and stop processing, ideal for opening/closing the resource */ + gboolean (*start) (GstBaseSrc *src); + gboolean (*stop) (GstBaseSrc *src); + + /** + * GstBaseSrcClass::get_times: + * @start: (out): + * @end: (out): + * + * Given @buffer, return @start and @end time when it should be pushed + * out. The base class will sync on the clock using these times. + */ + void (*get_times) (GstBaseSrc *src, GstBuffer *buffer, + GstClockTime *start, GstClockTime *end); + + /* get the total size of the resource in the format set by + * gst_base_src_set_format() */ + gboolean (*get_size) (GstBaseSrc *src, guint64 *size); + + /* check if the resource is seekable */ + gboolean (*is_seekable) (GstBaseSrc *src); + + /* Prepare the segment on which to perform do_seek(), converting to the + * current basesrc format. */ + gboolean (*prepare_seek_segment) (GstBaseSrc *src, GstEvent *seek, + GstSegment *segment); + /* notify subclasses of a seek */ + gboolean (*do_seek) (GstBaseSrc *src, GstSegment *segment); + + /* unlock any pending access to the resource. subclasses should unlock + * any function ASAP. */ + gboolean (*unlock) (GstBaseSrc *src); + /* Clear any pending unlock request, as we succeeded in unlocking */ + gboolean (*unlock_stop) (GstBaseSrc *src); + + /* notify subclasses of a query */ + gboolean (*query) (GstBaseSrc *src, GstQuery *query); + + /* notify subclasses of an event */ + gboolean (*event) (GstBaseSrc *src, GstEvent *event); + + /** + * GstBaseSrcClass::create: + * @buf: (out): + * + * Ask the subclass to create a buffer with @offset and @size, the default + * implementation will call alloc and fill. + */ + GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer **buf); + /* ask the subclass to allocate an output buffer. The default implementation + * will use the negotiated allocator. */ + GstFlowReturn (*alloc) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer **buf); + /* ask the subclass to fill the buffer with data from offset and size */ + GstFlowReturn (*fill) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer *buf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GST_BASE_API +GType gst_base_src_get_type (void); + +GST_BASE_API +GstFlowReturn gst_base_src_wait_playing (GstBaseSrc *src); + +GST_BASE_API +void gst_base_src_set_live (GstBaseSrc *src, gboolean live); + +GST_BASE_API +gboolean gst_base_src_is_live (GstBaseSrc *src); + +GST_BASE_API +void gst_base_src_set_format (GstBaseSrc *src, GstFormat format); + +GST_BASE_API +void gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic); + +GST_BASE_API +void gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos); + +GST_BASE_API +void gst_base_src_set_async (GstBaseSrc *src, gboolean async); + +GST_BASE_API +gboolean gst_base_src_is_async (GstBaseSrc *src); + +GST_BASE_API +void gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret); + +GST_BASE_API +GstFlowReturn gst_base_src_start_wait (GstBaseSrc * basesrc); + +GST_BASE_API +gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live, + GstClockTime * min_latency, + GstClockTime * max_latency); +GST_BASE_API +void gst_base_src_set_blocksize (GstBaseSrc *src, guint blocksize); + +GST_BASE_API +guint gst_base_src_get_blocksize (GstBaseSrc *src); + +GST_BASE_API +void gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean timestamp); + +GST_BASE_API +gboolean gst_base_src_get_do_timestamp (GstBaseSrc *src); + +GST_BASE_API +gboolean gst_base_src_new_seamless_segment (GstBaseSrc *src, gint64 start, gint64 stop, gint64 time); + +GST_BASE_API +gboolean gst_base_src_set_caps (GstBaseSrc *src, GstCaps *caps); + +GST_BASE_API +GstBufferPool * gst_base_src_get_buffer_pool (GstBaseSrc *src); + +GST_BASE_API +void gst_base_src_get_allocator (GstBaseSrc *src, + GstAllocator **allocator, + GstAllocationParams *params); + +GST_BASE_API +void gst_base_src_submit_buffer_list (GstBaseSrc * src, + GstBufferList * buffer_list); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseSrc, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BASE_SRC_H__ */ diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c new file mode 100644 index 0000000..259cf95 --- /dev/null +++ b/libs/gst/base/gstbasetransform.c @@ -0,0 +1,2864 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * 2005 Andy Wingo + * 2005 Thomas Vander Stichele + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstbasetransform + * @title: GstBaseTransform + * @short_description: Base class for simple transform filters + * @see_also: #GstBaseSrc, #GstBaseSink + * + * This base class is for filter elements that process data. Elements + * that are suitable for implementation using #GstBaseTransform are ones + * where the size and caps of the output is known entirely from the input + * caps and buffer sizes. These include elements that directly transform + * one buffer into another, modify the contents of a buffer in-place, as + * well as elements that collate multiple input buffers into one output buffer, + * or that expand one input buffer into multiple output buffers. See below + * for more concrete use cases. + * + * It provides for: + * + * * one sinkpad and one srcpad + * * Possible formats on sink and source pad implemented + * with custom transform_caps function. By default uses + * same format on sink and source. + * + * * Handles state changes + * * Does flushing + * * Push mode + * * Pull mode if the sub-class transform can operate on arbitrary data + * + * # Use Cases + * + * ## Passthrough mode + * + * * Element has no interest in modifying the buffer. It may want to inspect it, + * in which case the element should have a transform_ip function. If there + * is no transform_ip function in passthrough mode, the buffer is pushed + * intact. + * + * * The #GstBaseTransformClass.passthrough_on_same_caps variable + * will automatically set/unset passthrough based on whether the + * element negotiates the same caps on both pads. + * + * * #GstBaseTransformClass.passthrough_on_same_caps on an element that + * doesn't implement a transform_caps function is useful for elements that + * only inspect data (such as level) + * + * * Example elements + * + * * Level + * * Videoscale, audioconvert, videoconvert, audioresample in certain modes. + * + * ## Modifications in-place - input buffer and output buffer are the same thing. + * + * * The element must implement a transform_ip function. + * * Output buffer size must <= input buffer size + * * If the always_in_place flag is set, non-writable buffers will be copied + * and passed to the transform_ip function, otherwise a new buffer will be + * created and the transform function called. + * + * * Incoming writable buffers will be passed to the transform_ip function + * immediately. + * * only implementing transform_ip and not transform implies always_in_place = %TRUE + * + * * Example elements: + * * Volume + * * Audioconvert in certain modes (signed/unsigned conversion) + * * videoconvert in certain modes (endianness swapping) + * + * ## Modifications only to the caps/metadata of a buffer + * + * * The element does not require writable data, but non-writable buffers + * should be subbuffered so that the meta-information can be replaced. + * + * * Elements wishing to operate in this mode should replace the + * prepare_output_buffer method to create subbuffers of the input buffer + * and set always_in_place to %TRUE + * + * * Example elements + * * Capsfilter when setting caps on outgoing buffers that have + * none. + * * identity when it is going to re-timestamp buffers by + * datarate. + * + * ## Normal mode + * * always_in_place flag is not set, or there is no transform_ip function + * * Element will receive an input buffer and output buffer to operate on. + * * Output buffer is allocated by calling the prepare_output_buffer function. + * * Example elements: + * * Videoscale, videoconvert, audioconvert when doing + * scaling/conversions + * + * ## Special output buffer allocations + * * Elements which need to do special allocation of their output buffers + * beyond allocating output buffers via the negotiated allocator or + * buffer pool should implement the prepare_output_buffer method. + * + * * Example elements: + * * efence + * + * # Sub-class settable flags on GstBaseTransform + * + * * passthrough + * + * * Implies that in the current configuration, the sub-class is not interested in modifying the buffers. + * * Elements which are always in passthrough mode whenever the same caps has been negotiated on both pads can set the class variable passthrough_on_same_caps to have this behaviour automatically. + * + * * always_in_place + * * Determines whether a non-writable buffer will be copied before passing + * to the transform_ip function. + * + * * Implied %TRUE if no transform function is implemented. + * * Implied %FALSE if ONLY transform function is implemented. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "../../../gst/gst_private.h" +#include "../../../gst/gst-i18n-lib.h" +#include "../../../gst/glib-compat-private.h" +#include "gstbasetransform.h" + +GST_DEBUG_CATEGORY_STATIC (gst_base_transform_debug); +#define GST_CAT_DEFAULT gst_base_transform_debug + +/* BaseTransform signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_PROP_QOS FALSE + +enum +{ + PROP_0, + PROP_QOS +}; + +#define GST_BASE_TRANSFORM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_TRANSFORM, GstBaseTransformPrivate)) + +struct _GstBaseTransformPrivate +{ + /* Set by sub-class */ + gboolean passthrough; + gboolean always_in_place; + + GstCaps *cache_caps1; + gsize cache_caps1_size; + GstCaps *cache_caps2; + gsize cache_caps2_size; + gboolean have_same_caps; + + gboolean negotiated; + + /* QoS *//* with LOCK */ + gboolean qos_enabled; + gdouble proportion; + GstClockTime earliest_time; + /* previous buffer had a discont */ + gboolean discont; + + GstPadMode pad_mode; + + gboolean gap_aware; + gboolean prefer_passthrough; + + /* QoS stats */ + guint64 processed; + guint64 dropped; + + GstClockTime position_out; + + GstBufferPool *pool; + gboolean pool_active; + GstAllocator *allocator; + GstAllocationParams params; + GstQuery *query; +}; + + +static GstElementClass *parent_class = NULL; + +static void gst_base_transform_class_init (GstBaseTransformClass * klass); +static void gst_base_transform_init (GstBaseTransform * trans, + GstBaseTransformClass * klass); +static GstFlowReturn default_submit_input_buffer (GstBaseTransform * trans, + gboolean is_discont, GstBuffer * input); +static GstFlowReturn default_generate_output (GstBaseTransform * trans, + GstBuffer ** outbuf); + +/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init + * method to get to the padtemplates */ +GType +gst_base_transform_get_type (void) +{ + static volatile gsize base_transform_type = 0; + + if (g_once_init_enter (&base_transform_type)) { + GType _type; + static const GTypeInfo base_transform_info = { + sizeof (GstBaseTransformClass), + NULL, + NULL, + (GClassInitFunc) gst_base_transform_class_init, + NULL, + NULL, + sizeof (GstBaseTransform), + 0, + (GInstanceInitFunc) gst_base_transform_init, + }; + + _type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT); + g_once_init_leave (&base_transform_type, _type); + } + return base_transform_type; +} + +static void gst_base_transform_finalize (GObject * object); +static void gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_base_transform_src_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_base_transform_sink_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_base_transform_activate (GstBaseTransform * trans, + gboolean active); +static gboolean gst_base_transform_get_unit_size (GstBaseTransform * trans, + GstCaps * caps, gsize * size); + +static gboolean gst_base_transform_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_base_transform_src_eventfunc (GstBaseTransform * trans, + GstEvent * event); +static gboolean gst_base_transform_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_base_transform_sink_eventfunc (GstBaseTransform * trans, + GstEvent * event); +static GstFlowReturn gst_base_transform_getrange (GstPad * pad, + GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer); +static GstFlowReturn gst_base_transform_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstCaps *gst_base_transform_default_transform_caps (GstBaseTransform * + trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static GstCaps *gst_base_transform_default_fixate_caps (GstBaseTransform * + trans, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); +static GstCaps *gst_base_transform_query_caps (GstBaseTransform * trans, + GstPad * pad, GstCaps * filter); +static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_base_transform_setcaps (GstBaseTransform * trans, + GstPad * pad, GstCaps * caps); +static gboolean gst_base_transform_default_decide_allocation (GstBaseTransform + * trans, GstQuery * query); +static gboolean gst_base_transform_default_propose_allocation (GstBaseTransform + * trans, GstQuery * decide_query, GstQuery * query); +static gboolean gst_base_transform_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_base_transform_default_query (GstBaseTransform * trans, + GstPadDirection direction, GstQuery * query); +static gboolean gst_base_transform_default_transform_size (GstBaseTransform * + trans, GstPadDirection direction, GstCaps * caps, gsize size, + GstCaps * othercaps, gsize * othersize); + +static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf); +static gboolean default_copy_metadata (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf); +static gboolean +gst_base_transform_default_transform_meta (GstBaseTransform * trans, + GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf); + +/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */ + + +static void +gst_base_transform_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_base_transform_class_init (GstBaseTransformClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0, + "basetransform element"); + + GST_DEBUG ("gst_base_transform_class_init"); + + g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate)); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_base_transform_set_property; + gobject_class->get_property = gst_base_transform_get_property; + + g_object_class_install_property (gobject_class, PROP_QOS, + g_param_spec_boolean ("qos", "QoS", "Handle Quality-of-Service events", + DEFAULT_PROP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_base_transform_finalize; + + klass->passthrough_on_same_caps = FALSE; + klass->transform_ip_on_passthrough = TRUE; + + klass->transform_caps = + GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_caps); + klass->fixate_caps = + GST_DEBUG_FUNCPTR (gst_base_transform_default_fixate_caps); + klass->accept_caps = + GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default); + klass->query = GST_DEBUG_FUNCPTR (gst_base_transform_default_query); + klass->decide_allocation = + GST_DEBUG_FUNCPTR (gst_base_transform_default_decide_allocation); + klass->propose_allocation = + GST_DEBUG_FUNCPTR (gst_base_transform_default_propose_allocation); + klass->transform_size = + GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_size); + klass->transform_meta = + GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_meta); + + klass->sink_event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc); + klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc); + klass->prepare_output_buffer = + GST_DEBUG_FUNCPTR (default_prepare_output_buffer); + klass->copy_metadata = GST_DEBUG_FUNCPTR (default_copy_metadata); + klass->submit_input_buffer = GST_DEBUG_FUNCPTR (default_submit_input_buffer); + klass->generate_output = GST_DEBUG_FUNCPTR (default_generate_output); +} + +static void +gst_base_transform_init (GstBaseTransform * trans, + GstBaseTransformClass * bclass) +{ + GstPadTemplate *pad_template; + GstBaseTransformPrivate *priv; + + GST_DEBUG ("gst_base_transform_init"); + + priv = trans->priv = GST_BASE_TRANSFORM_GET_PRIVATE (trans); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); + g_return_if_fail (pad_template != NULL); + trans->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_event_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_sink_event)); + gst_pad_set_chain_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_chain)); + gst_pad_set_activatemode_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_mode)); + gst_pad_set_query_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_query)); + gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); + g_return_if_fail (pad_template != NULL); + trans->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_set_event_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_src_event)); + gst_pad_set_getrange_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_getrange)); + gst_pad_set_activatemode_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_mode)); + gst_pad_set_query_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_query)); + gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad); + + priv->qos_enabled = DEFAULT_PROP_QOS; + priv->cache_caps1 = NULL; + priv->cache_caps2 = NULL; + priv->pad_mode = GST_PAD_MODE_NONE; + priv->gap_aware = FALSE; + priv->prefer_passthrough = TRUE; + + priv->passthrough = FALSE; + if (bclass->transform == NULL) { + /* If no transform function, always_in_place is TRUE */ + GST_DEBUG_OBJECT (trans, "setting in_place TRUE"); + priv->always_in_place = TRUE; + + if (bclass->transform_ip == NULL) { + GST_DEBUG_OBJECT (trans, "setting passthrough TRUE"); + priv->passthrough = TRUE; + } + } + + priv->processed = 0; + priv->dropped = 0; +} + +static GstCaps * +gst_base_transform_default_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) +{ + GstCaps *ret; + + GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps); + /* no transform function, use the identity transform */ + if (filter) { + ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + } else { + ret = gst_caps_ref (caps); + } + return ret; +} + +/* given @caps on the src or sink pad (given by @direction) + * calculate the possible caps on the other pad. + * + * Returns new caps, unref after usage. + */ +static GstCaps * +gst_base_transform_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) +{ + GstCaps *ret = NULL; + GstBaseTransformClass *klass; + + if (caps == NULL) + return NULL; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + /* if there is a custom transform function, use this */ + if (klass->transform_caps) { + GST_DEBUG_OBJECT (trans, "transform caps (direction = %d)", direction); + + GST_LOG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps); + ret = klass->transform_caps (trans, direction, caps, filter); + GST_LOG_OBJECT (trans, " to: %" GST_PTR_FORMAT, ret); + +#ifdef GST_ENABLE_EXTRA_CHECKS + if (filter) { + if (!gst_caps_is_subset (ret, filter)) { + GstCaps *intersection; + + GST_ERROR_OBJECT (trans, + "transform_caps returned caps %" GST_PTR_FORMAT + " which are not a real subset of the filter caps %" + GST_PTR_FORMAT, ret, filter); + g_warning ("%s: transform_caps returned caps which are not a real " + "subset of the filter caps", GST_ELEMENT_NAME (trans)); + + intersection = + gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (ret); + ret = intersection; + } + } +#endif + } + + GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_base_transform_default_transform_meta (GstBaseTransform * trans, + GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf) +{ + const GstMetaInfo *info = meta->info; + const gchar *const *tags; + + tags = gst_meta_api_type_get_tags (info->api); + + if (!tags) + return TRUE; + + return FALSE; +} + +static gboolean +gst_base_transform_default_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, gsize size, + GstCaps * othercaps, gsize * othersize) +{ + gsize inunitsize, outunitsize, units; + GstBaseTransformClass *klass; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (klass->get_unit_size == NULL) { + /* if there is no transform_size and no unit_size, it means the + * element does not modify the size of a buffer */ + *othersize = size; + } else { + /* there is no transform_size function, we have to use the unit_size + * functions. This method assumes there is a fixed unit_size associated with + * each caps. We provide the same amount of units on both sides. */ + if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize)) + goto no_in_size; + + GST_DEBUG_OBJECT (trans, + "input size %" G_GSIZE_FORMAT ", input unit size %" G_GSIZE_FORMAT, + size, inunitsize); + + /* input size must be a multiple of the unit_size of the input caps */ + if (inunitsize == 0 || (size % inunitsize != 0)) + goto no_multiple; + + /* get the amount of units */ + units = size / inunitsize; + + /* now get the unit size of the output */ + if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize)) + goto no_out_size; + + /* the output size is the unit_size times the amount of units on the + * input */ + *othersize = units * outunitsize; + GST_DEBUG_OBJECT (trans, "transformed size to %" G_GSIZE_FORMAT, + *othersize); + } + return TRUE; + + /* ERRORS */ +no_in_size: + { + GST_DEBUG_OBJECT (trans, "could not get in_size"); + g_warning ("%s: could not get in_size", GST_ELEMENT_NAME (trans)); + return FALSE; + } +no_multiple: + { + GST_DEBUG_OBJECT (trans, "Size %" G_GSIZE_FORMAT " is not a multiple of" + "unit size %" G_GSIZE_FORMAT, size, inunitsize); + g_warning ("%s: size %" G_GSIZE_FORMAT " is not a multiple of unit size %" + G_GSIZE_FORMAT, GST_ELEMENT_NAME (trans), size, inunitsize); + return FALSE; + } +no_out_size: + { + GST_DEBUG_OBJECT (trans, "could not get out_size"); + g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans)); + return FALSE; + } +} + +/* transform a buffer of @size with @caps on the pad with @direction to + * the size of a buffer with @othercaps and store the result in @othersize + * + * We have two ways of doing this: + * 1) use a custom transform size function, this is for complicated custom + * cases with no fixed unit_size. + * 2) use the unit_size functions where there is a relationship between the + * caps and the size of a buffer. + */ +static gboolean +gst_base_transform_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, + gsize size, GstCaps * othercaps, gsize * othersize) +{ + GstBaseTransformClass *klass; + gboolean ret = FALSE; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + GST_DEBUG_OBJECT (trans, + "asked to transform size %" G_GSIZE_FORMAT " for caps %" + GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s", + size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK"); + + if (klass->transform_size) { + /* if there is a custom transform function, use this */ + ret = klass->transform_size (trans, direction, caps, size, othercaps, + othersize); + } + return ret; +} + +/* get the caps that can be handled by @pad. We perform: + * + * - take the caps of peer of otherpad, + * - filter against the padtemplate of otherpad, + * - calculate all transforms of remaining caps + * - filter against template of @pad + * + * If there is no peer, we simply return the caps of the padtemplate of pad. + */ +static GstCaps * +gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad, + GstCaps * filter) +{ + GstPad *otherpad; + GstCaps *peercaps = NULL, *caps, *temp, *peerfilter = NULL; + GstCaps *templ, *otempl; + + otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad; + + templ = gst_pad_get_pad_template_caps (pad); + otempl = gst_pad_get_pad_template_caps (otherpad); + + /* first prepare the filter to be send onwards. We need to filter and + * transform it to valid caps for the otherpad. */ + if (filter) { + GST_DEBUG_OBJECT (pad, "filter caps %" GST_PTR_FORMAT, filter); + + /* filtered against our padtemplate of this pad */ + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + temp = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + + /* then see what we can transform this to */ + peerfilter = gst_base_transform_transform_caps (trans, + GST_PAD_DIRECTION (pad), temp, NULL); + GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, peerfilter); + gst_caps_unref (temp); + + if (!gst_caps_is_empty (peerfilter)) { + /* and filter against the template of the other pad */ + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, otempl); + /* We keep the caps sorted like the returned caps */ + temp = + gst_caps_intersect_full (peerfilter, otempl, + GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (peerfilter); + peerfilter = temp; + } + } + + GST_DEBUG_OBJECT (pad, "peer filter caps %" GST_PTR_FORMAT, peerfilter); + + if (peerfilter && gst_caps_is_empty (peerfilter)) { + GST_DEBUG_OBJECT (pad, "peer filter caps are empty"); + caps = peerfilter; + peerfilter = NULL; + goto done; + } + + /* query the peer with the transformed filter */ + peercaps = gst_pad_peer_query_caps (otherpad, peerfilter); + + if (peerfilter) + gst_caps_unref (peerfilter); + + if (peercaps) { + GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peercaps); + + /* filtered against our padtemplate on the other side */ + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, otempl); + temp = gst_caps_intersect_full (peercaps, otempl, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + } else { + temp = gst_caps_ref (otempl); + } + + /* then see what we can transform this to */ + caps = gst_base_transform_transform_caps (trans, + GST_PAD_DIRECTION (otherpad), temp, filter); + GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps); + gst_caps_unref (temp); + if (caps == NULL || gst_caps_is_empty (caps)) + goto done; + + if (peercaps) { + /* and filter against the template of this pad */ + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + /* We keep the caps sorted like the returned caps */ + temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (caps); + caps = temp; + + if (trans->priv->prefer_passthrough) { + /* Now try if we can put the untransformed downstream caps first */ + temp = gst_caps_intersect_full (peercaps, caps, GST_CAPS_INTERSECT_FIRST); + if (!gst_caps_is_empty (temp)) { + caps = gst_caps_merge (temp, caps); + } else { + gst_caps_unref (temp); + } + } + } else { + gst_caps_unref (caps); + /* no peer or the peer can do anything, our padtemplate is enough then */ + if (filter) { + caps = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST); + } else { + caps = gst_caps_ref (templ); + } + } + +done: + GST_DEBUG_OBJECT (trans, "returning %" GST_PTR_FORMAT, caps); + + if (peercaps) + gst_caps_unref (peercaps); + + gst_caps_unref (templ); + gst_caps_unref (otempl); + + return caps; +} + +/* takes ownership of the pool, allocator and query */ +static gboolean +gst_base_transform_set_allocation (GstBaseTransform * trans, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params, GstQuery * query) +{ + GstAllocator *oldalloc; + GstBufferPool *oldpool; + GstQuery *oldquery; + GstBaseTransformPrivate *priv = trans->priv; + + GST_OBJECT_LOCK (trans); + oldpool = priv->pool; + priv->pool = pool; + priv->pool_active = FALSE; + + oldalloc = priv->allocator; + priv->allocator = allocator; + + oldquery = priv->query; + priv->query = query; + + if (params) + priv->params = *params; + else + gst_allocation_params_init (&priv->params); + GST_OBJECT_UNLOCK (trans); + + if (oldpool) { + GST_DEBUG_OBJECT (trans, "deactivating old pool %p", oldpool); + gst_buffer_pool_set_active (oldpool, FALSE); + gst_object_unref (oldpool); + } + if (oldalloc) { + gst_object_unref (oldalloc); + } + if (oldquery) { + gst_query_unref (oldquery); + } + return TRUE; +} + +static gboolean +gst_base_transform_default_decide_allocation (GstBaseTransform * trans, + GstQuery * query) +{ + guint i, n_metas; + GstBaseTransformClass *klass; + GstCaps *outcaps; + GstBufferPool *pool; + guint size, min, max; + GstAllocator *allocator; + GstAllocationParams params; + GstStructure *config; + gboolean update_allocator; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + n_metas = gst_query_get_n_allocation_metas (query); + for (i = 0; i < n_metas; i++) { + GType api; + const GstStructure *params; + gboolean remove; + + api = gst_query_parse_nth_allocation_meta (query, i, ¶ms); + + /* by default we remove all metadata, subclasses should implement a + * filter_meta function */ + if (gst_meta_api_type_has_tag (api, _gst_meta_tag_memory)) { + /* remove all memory dependent metadata because we are going to have to + * allocate different memory for input and output. */ + GST_LOG_OBJECT (trans, "removing memory specific metadata %s", + g_type_name (api)); + remove = TRUE; + } else if (G_LIKELY (klass->filter_meta)) { + /* remove if the subclass said so */ + remove = !klass->filter_meta (trans, query, api, params); + GST_LOG_OBJECT (trans, "filter_meta for api %s returned: %s", + g_type_name (api), (remove ? "remove" : "keep")); + } else { + GST_LOG_OBJECT (trans, "removing metadata %s", g_type_name (api)); + remove = TRUE; + } + + if (remove) { + gst_query_remove_nth_allocation_meta (query, i); + i--; + n_metas--; + } + } + + gst_query_parse_allocation (query, &outcaps, NULL); + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + /* try the allocator */ + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + update_allocator = TRUE; + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + update_allocator = FALSE; + } + + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); + + if (pool == NULL) { + /* no pool, we can make our own */ + GST_DEBUG_OBJECT (trans, "no pool, making new pool"); + pool = gst_buffer_pool_new (); + } + } else { + pool = NULL; + size = min = max = 0; + } + + /* now configure */ + if (pool) { + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, outcaps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + + /* buffer pool may have to do some changes */ + if (!gst_buffer_pool_set_config (pool, config)) { + config = gst_buffer_pool_get_config (pool); + + /* If change are not acceptable, fallback to generic pool */ + if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min, + max)) { + GST_DEBUG_OBJECT (trans, "unsuported pool, making new pool"); + + gst_object_unref (pool); + pool = gst_buffer_pool_new (); + gst_buffer_pool_config_set_params (config, outcaps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + } + + if (!gst_buffer_pool_set_config (pool, config)) + goto config_failed; + } + } + + if (update_allocator) + gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms); + else + gst_query_add_allocation_param (query, allocator, ¶ms); + if (allocator) + gst_object_unref (allocator); + + if (pool) { + gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); + gst_object_unref (pool); + } + + return TRUE; + +config_failed: + if (pool) + gst_object_unref (pool); + + GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS, + ("Failed to configure the buffer pool"), + ("Configuration is most likely invalid, please report this issue.")); + return FALSE; +} + +static gboolean +gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps) +{ + GstQuery *query; + gboolean result = TRUE; + GstBufferPool *pool = NULL; + GstBaseTransformClass *klass; + GstBaseTransformPrivate *priv = trans->priv; + GstAllocator *allocator; + GstAllocationParams params; + + /* there are these possibilities: + * + * 1) we negotiated passthrough, we can proxy the bufferpool directly and we + * will do that whenever some upstream does an allocation query. + * 2) we need to do a transform, we need to get a bufferpool from downstream + * and configure it. When upstream does the ALLOCATION query, the + * propose_allocation vmethod will be called and we will configure the + * upstream allocator with our proposed values then. + */ + if (priv->passthrough || priv->always_in_place) { + /* we are in passthrough, the input buffer is never copied and always passed + * along. We never allocate an output buffer on the srcpad. What we do is + * let the upstream element decide if it wants to use a bufferpool and + * then we will proxy the downstream pool */ + GST_DEBUG_OBJECT (trans, "we're passthough, delay bufferpool"); + gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL); + return TRUE; + } + + /* not passthrough, we need to allocate */ + /* find a pool for the negotiated caps now */ + GST_DEBUG_OBJECT (trans, "doing allocation query"); + query = gst_query_new_allocation (outcaps, TRUE); + if (!gst_pad_peer_query (trans->srcpad, query)) { + /* not a problem, just debug a little */ + GST_DEBUG_OBJECT (trans, "peer ALLOCATION query failed"); + } + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + GST_DEBUG_OBJECT (trans, "calling decide_allocation"); + g_assert (klass->decide_allocation != NULL); + result = klass->decide_allocation (trans, query); + + GST_DEBUG_OBJECT (trans, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, + query); + + if (!result) + goto no_decide_allocation; + + /* check again in case the sub-class have switch to passthrough/in-place + * after looking at the meta APIs */ + if (priv->passthrough || priv->always_in_place) { + GST_DEBUG_OBJECT (trans, "no doing passthrough, delay bufferpool"); + gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL); + gst_query_unref (query); + return TRUE; + } + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + } + + if (gst_query_get_n_allocation_pools (query) > 0) + gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); + + /* now store */ + result = + gst_base_transform_set_allocation (trans, pool, allocator, ¶ms, + query); + + return result; + + /* Errors */ +no_decide_allocation: + { + GST_WARNING_OBJECT (trans, "Subclass failed to decide allocation"); + gst_query_unref (query); + + return result; + } +} + +/* function triggered when the in and out caps are negotiated and need + * to be configured in the subclass. */ +static gboolean +gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in, + GstCaps * out) +{ + gboolean ret = TRUE; + GstBaseTransformClass *klass; + GstBaseTransformPrivate *priv = trans->priv; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + GST_DEBUG_OBJECT (trans, "in caps: %" GST_PTR_FORMAT, in); + GST_DEBUG_OBJECT (trans, "out caps: %" GST_PTR_FORMAT, out); + + /* clear the cache */ + gst_caps_replace (&priv->cache_caps1, NULL); + gst_caps_replace (&priv->cache_caps2, NULL); + + /* figure out same caps state */ + priv->have_same_caps = gst_caps_is_equal (in, out); + GST_DEBUG_OBJECT (trans, "have_same_caps: %d", priv->have_same_caps); + + /* Set the passthrough if the class wants passthrough_on_same_caps + * and we have the same caps on each pad */ + if (klass->passthrough_on_same_caps) + gst_base_transform_set_passthrough (trans, priv->have_same_caps); + + /* now configure the element with the caps */ + if (klass->set_caps) { + GST_DEBUG_OBJECT (trans, "Calling set_caps method to setup caps"); + ret = klass->set_caps (trans, in, out); + } + + return ret; +} + +static GstCaps * +gst_base_transform_default_fixate_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + othercaps = gst_caps_fixate (othercaps); + GST_DEBUG_OBJECT (trans, "fixated to %" GST_PTR_FORMAT, othercaps); + + return othercaps; +} + +/* given a fixed @caps on @pad, create the best possible caps for the + * other pad. + * @caps must be fixed when calling this function. + * + * This function calls the transform caps vmethod of the basetransform to figure + * out the possible target formats. It then tries to select the best format from + * this list by: + * + * - attempt passthrough if the target caps is a superset of the input caps + * - fixating by using peer caps + * - fixating with transform fixate function + * - fixating with pad fixate functions. + * + * this function returns a caps that can be transformed into and is accepted by + * the peer element. + */ +static GstCaps * +gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad, + GstCaps * caps) +{ + GstBaseTransformClass *klass; + GstPad *otherpad, *otherpeer; + GstCaps *othercaps; + gboolean is_fixed; + + /* caps must be fixed here, this is a programming error if it's not */ + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad; + otherpeer = gst_pad_get_peer (otherpad); + + /* see how we can transform the input caps. We need to do this even for + * passthrough because it might be possible that this element cannot support + * passthrough at all. */ + othercaps = gst_base_transform_transform_caps (trans, + GST_PAD_DIRECTION (pad), caps, NULL); + + /* The caps we can actually output is the intersection of the transformed + * caps with the pad template for the pad */ + if (othercaps && !gst_caps_is_empty (othercaps)) { + GstCaps *intersect, *templ_caps; + + templ_caps = gst_pad_get_pad_template_caps (otherpad); + GST_DEBUG_OBJECT (trans, + "intersecting against padtemplate %" GST_PTR_FORMAT, templ_caps); + + intersect = + gst_caps_intersect_full (othercaps, templ_caps, + GST_CAPS_INTERSECT_FIRST); + + gst_caps_unref (othercaps); + gst_caps_unref (templ_caps); + othercaps = intersect; + } + + /* check if transform is empty */ + if (!othercaps || gst_caps_is_empty (othercaps)) + goto no_transform; + + /* if the othercaps are not fixed, we need to fixate them, first attempt + * is by attempting passthrough if the othercaps are a superset of caps. */ + /* FIXME. maybe the caps is not fixed because it has multiple structures of + * fixed caps */ + is_fixed = gst_caps_is_fixed (othercaps); + if (!is_fixed) { + GST_DEBUG_OBJECT (trans, + "transform returned non fixed %" GST_PTR_FORMAT, othercaps); + + /* Now let's see what the peer suggests based on our transformed caps */ + if (otherpeer) { + GstCaps *peercaps, *intersection, *templ_caps; + + GST_DEBUG_OBJECT (trans, + "Checking peer caps with filter %" GST_PTR_FORMAT, othercaps); + + peercaps = gst_pad_query_caps (otherpeer, othercaps); + GST_DEBUG_OBJECT (trans, "Resulted in %" GST_PTR_FORMAT, peercaps); + if (!gst_caps_is_empty (peercaps)) { + templ_caps = gst_pad_get_pad_template_caps (otherpad); + + GST_DEBUG_OBJECT (trans, + "Intersecting with template caps %" GST_PTR_FORMAT, templ_caps); + + intersection = + gst_caps_intersect_full (peercaps, templ_caps, + GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT, + intersection); + gst_caps_unref (peercaps); + gst_caps_unref (templ_caps); + peercaps = intersection; + + GST_DEBUG_OBJECT (trans, + "Intersecting with transformed caps %" GST_PTR_FORMAT, othercaps); + intersection = + gst_caps_intersect_full (peercaps, othercaps, + GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT, + intersection); + gst_caps_unref (peercaps); + gst_caps_unref (othercaps); + othercaps = intersection; + } else { + gst_caps_unref (othercaps); + othercaps = peercaps; + } + + is_fixed = gst_caps_is_fixed (othercaps); + } else { + GST_DEBUG_OBJECT (trans, "no peer, doing passthrough"); + gst_caps_unref (othercaps); + othercaps = gst_caps_ref (caps); + is_fixed = TRUE; + } + } + if (gst_caps_is_empty (othercaps)) + goto no_transform_possible; + + GST_DEBUG ("have %sfixed caps %" GST_PTR_FORMAT, (is_fixed ? "" : "non-"), + othercaps); + + /* second attempt at fixation, call the fixate vmethod */ + /* caps could be fixed but the subclass may want to add fields */ + if (klass->fixate_caps) { + GST_DEBUG_OBJECT (trans, "calling fixate_caps for %" GST_PTR_FORMAT + " using caps %" GST_PTR_FORMAT " on pad %s:%s", othercaps, caps, + GST_DEBUG_PAD_NAME (otherpad)); + /* note that we pass the complete array of structures to the fixate + * function, it needs to truncate itself */ + othercaps = + klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps); + is_fixed = gst_caps_is_fixed (othercaps); + GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps); + } + + /* caps should be fixed now, if not we have to fail. */ + if (!is_fixed) + goto could_not_fixate; + + /* and peer should accept */ + if (otherpeer && !gst_pad_query_accept_caps (otherpeer, othercaps)) + goto peer_no_accept; + + GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT + ", and got final caps %" GST_PTR_FORMAT, caps, othercaps); + + if (otherpeer) + gst_object_unref (otherpeer); + + return othercaps; + + /* ERRORS */ +no_transform: + { + GST_DEBUG_OBJECT (trans, + "transform returned useless %" GST_PTR_FORMAT, othercaps); + goto error_cleanup; + } +no_transform_possible: + { + GST_DEBUG_OBJECT (trans, + "transform could not transform %" GST_PTR_FORMAT + " in anything we support", caps); + goto error_cleanup; + } +could_not_fixate: + { + GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps); + goto error_cleanup; + } +peer_no_accept: + { + GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT + " to accept %" GST_PTR_FORMAT, otherpad, othercaps); + goto error_cleanup; + } +error_cleanup: + { + if (otherpeer) + gst_object_unref (otherpeer); + if (othercaps) + gst_caps_unref (othercaps); + return NULL; + } +} + +static gboolean +gst_base_transform_acceptcaps_default (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstPad *pad, *otherpad; + GstCaps *templ, *otempl, *ocaps = NULL; + gboolean ret = TRUE; + + pad = + (direction == + GST_PAD_SINK) ? GST_BASE_TRANSFORM_SINK_PAD (trans) : + GST_BASE_TRANSFORM_SRC_PAD (trans); + otherpad = + (direction == + GST_PAD_SINK) ? GST_BASE_TRANSFORM_SRC_PAD (trans) : + GST_BASE_TRANSFORM_SINK_PAD (trans); + + GST_DEBUG_OBJECT (trans, "accept caps %" GST_PTR_FORMAT, caps); + + templ = gst_pad_get_pad_template_caps (pad); + otempl = gst_pad_get_pad_template_caps (otherpad); + + /* get all the formats we can handle on this pad */ + GST_DEBUG_OBJECT (trans, "intersect with pad template: %" GST_PTR_FORMAT, + templ); + if (!gst_caps_can_intersect (caps, templ)) + goto reject_caps; + + GST_DEBUG_OBJECT (trans, "trying to transform with filter: %" + GST_PTR_FORMAT " (the other pad template)", otempl); + ocaps = gst_base_transform_transform_caps (trans, direction, caps, otempl); + if (!ocaps || gst_caps_is_empty (ocaps)) + goto no_transform_possible; + +done: + GST_DEBUG_OBJECT (trans, "accept-caps result: %d", ret); + if (ocaps) + gst_caps_unref (ocaps); + gst_caps_unref (templ); + gst_caps_unref (otempl); + return ret; + + /* ERRORS */ +reject_caps: + { + GST_DEBUG_OBJECT (trans, "caps can't intersect with the template"); + ret = FALSE; + goto done; + } +no_transform_possible: + { + GST_DEBUG_OBJECT (trans, + "transform could not transform %" GST_PTR_FORMAT + " in anything we support", caps); + ret = FALSE; + goto done; + } +} + +/* called when new caps arrive on the sink pad, + * We try to find the best caps for the other side using our _find_transform() + * function. If there are caps, we configure the transform for this new + * transformation. + */ +static gboolean +gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad, + GstCaps * incaps) +{ + GstBaseTransformPrivate *priv = trans->priv; + GstCaps *outcaps, *prev_incaps = NULL, *prev_outcaps = NULL; + gboolean ret = TRUE; + + GST_DEBUG_OBJECT (pad, "have new caps %p %" GST_PTR_FORMAT, incaps, incaps); + + /* find best possible caps for the other pad */ + outcaps = gst_base_transform_find_transform (trans, pad, incaps); + if (!outcaps || gst_caps_is_empty (outcaps)) + goto no_transform_possible; + + /* configure the element now */ + + /* if we have the same caps, we can optimize and reuse the input caps */ + if (gst_caps_is_equal (incaps, outcaps)) { + GST_INFO_OBJECT (trans, "reuse caps"); + gst_caps_unref (outcaps); + outcaps = gst_caps_ref (incaps); + } + + prev_incaps = gst_pad_get_current_caps (trans->sinkpad); + prev_outcaps = gst_pad_get_current_caps (trans->srcpad); + if (prev_incaps && prev_outcaps && gst_caps_is_equal (prev_incaps, incaps) + && gst_caps_is_equal (prev_outcaps, outcaps)) { + GST_DEBUG_OBJECT (trans, + "New caps equal to old ones: %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, + incaps, outcaps); + ret = TRUE; + } else { + /* call configure now */ + if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps))) + goto failed_configure; + + if (!prev_outcaps || !gst_caps_is_equal (outcaps, prev_outcaps)) + /* let downstream know about our caps */ + ret = gst_pad_set_caps (trans->srcpad, outcaps); + } + + if (ret) { + /* try to get a pool when needed */ + ret = gst_base_transform_do_bufferpool (trans, outcaps); + } + +done: + if (outcaps) + gst_caps_unref (outcaps); + if (prev_incaps) + gst_caps_unref (prev_incaps); + if (prev_outcaps) + gst_caps_unref (prev_outcaps); + + GST_OBJECT_LOCK (trans); + priv->negotiated = ret; + GST_OBJECT_UNLOCK (trans); + + return ret; + + /* ERRORS */ +no_transform_possible: + { + GST_WARNING_OBJECT (trans, + "transform could not transform %" GST_PTR_FORMAT + " in anything we support", incaps); + ret = FALSE; + goto done; + } +failed_configure: + { + GST_WARNING_OBJECT (trans, "FAILED to configure incaps %" GST_PTR_FORMAT + " and outcaps %" GST_PTR_FORMAT, incaps, outcaps); + ret = FALSE; + goto done; + } +} + +static gboolean +gst_base_transform_default_propose_allocation (GstBaseTransform * trans, + GstQuery * decide_query, GstQuery * query) +{ + gboolean ret; + + if (decide_query == NULL) { + GST_DEBUG_OBJECT (trans, "doing passthrough query"); + ret = gst_pad_peer_query (trans->srcpad, query); + } else { + guint i, n_metas; + /* non-passthrough, copy all metadata, decide_query does not contain the + * metadata anymore that depends on the buffer memory */ + n_metas = gst_query_get_n_allocation_metas (decide_query); + for (i = 0; i < n_metas; i++) { + GType api; + const GstStructure *params; + + api = gst_query_parse_nth_allocation_meta (decide_query, i, ¶ms); + GST_DEBUG_OBJECT (trans, "proposing metadata %s", g_type_name (api)); + gst_query_add_allocation_meta (query, api, params); + } + ret = TRUE; + } + return ret; +} + +static gboolean +gst_base_transform_reconfigure (GstBaseTransform * trans) +{ + gboolean reconfigure, ret = TRUE; + + reconfigure = gst_pad_check_reconfigure (trans->srcpad); + + if (G_UNLIKELY (reconfigure)) { + GstCaps *incaps; + + GST_DEBUG_OBJECT (trans, "we had a pending reconfigure"); + + incaps = gst_pad_get_current_caps (trans->sinkpad); + if (incaps == NULL) + goto done; + + /* if we need to reconfigure we pretend new caps arrived. This + * will reconfigure the transform with the new output format. */ + if (!gst_base_transform_setcaps (trans, trans->sinkpad, incaps)) { + GST_ELEMENT_WARNING (trans, STREAM, FORMAT, + ("not negotiated"), ("not negotiated")); + ret = FALSE; + } + + gst_caps_unref (incaps); + } + +done: + + if (!ret) + gst_pad_mark_reconfigure (trans->srcpad); + + return ret; +} + +static gboolean +gst_base_transform_default_query (GstBaseTransform * trans, + GstPadDirection direction, GstQuery * query) +{ + gboolean ret = FALSE; + GstPad *pad, *otherpad; + GstBaseTransformClass *klass; + GstBaseTransformPrivate *priv = trans->priv; + + if (direction == GST_PAD_SRC) { + pad = trans->srcpad; + otherpad = trans->sinkpad; + } else { + pad = trans->sinkpad; + otherpad = trans->srcpad; + } + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ALLOCATION: + { + GstQuery *decide_query = NULL; + + /* can only be done on the sinkpad */ + if (direction != GST_PAD_SINK) + goto done; + + ret = gst_base_transform_reconfigure (trans); + if (G_UNLIKELY (!ret)) + goto done; + + GST_OBJECT_LOCK (trans); + if (!priv->negotiated && !priv->passthrough && (klass->set_caps != NULL)) { + GST_DEBUG_OBJECT (trans, + "not negotiated yet but need negotiation, can't answer ALLOCATION query"); + GST_OBJECT_UNLOCK (trans); + goto done; + } + + decide_query = trans->priv->query; + trans->priv->query = NULL; + GST_OBJECT_UNLOCK (trans); + + GST_DEBUG_OBJECT (trans, + "calling propose allocation with query %" GST_PTR_FORMAT, + decide_query); + + /* pass the query to the propose_allocation vmethod if any */ + if (G_LIKELY (klass->propose_allocation)) + ret = klass->propose_allocation (trans, decide_query, query); + else + ret = FALSE; + + if (decide_query) { + GST_OBJECT_LOCK (trans); + + if (trans->priv->query == NULL) + trans->priv->query = decide_query; + else + gst_query_unref (decide_query); + + GST_OBJECT_UNLOCK (trans); + } + + GST_DEBUG_OBJECT (trans, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, + query); + break; + } + case GST_QUERY_POSITION: + { + GstFormat format; + + gst_query_parse_position (query, &format, NULL); + if (format == GST_FORMAT_TIME && trans->segment.format == GST_FORMAT_TIME) { + gint64 pos; + ret = TRUE; + + if ((direction == GST_PAD_SINK) + || (trans->priv->position_out == GST_CLOCK_TIME_NONE)) { + pos = + gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, + trans->segment.position); + } else { + pos = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, + trans->priv->position_out); + } + gst_query_set_position (query, format, pos); + } else { + ret = gst_pad_peer_query (otherpad, query); + } + break; + } + case GST_QUERY_ACCEPT_CAPS: + { + GstCaps *caps; + + gst_query_parse_accept_caps (query, &caps); + if (klass->accept_caps) { + ret = klass->accept_caps (trans, direction, caps); + gst_query_set_accept_caps_result (query, ret); + /* return TRUE, we answered the query */ + ret = TRUE; + } + break; + } + case GST_QUERY_CAPS: + { + GstCaps *filter, *caps; + + gst_query_parse_caps (query, &filter); + caps = gst_base_transform_query_caps (trans, pad, filter); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + ret = TRUE; + break; + } + default: + ret = gst_pad_peer_query (otherpad, query); + break; + } + +done: + return ret; +} + +static gboolean +gst_base_transform_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean ret = FALSE; + + trans = GST_BASE_TRANSFORM_CAST (parent); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->query) + ret = bclass->query (trans, GST_PAD_DIRECTION (pad), query); + + return ret; +} + +/* this function either returns the input buffer without incrementing the + * refcount or it allocates a new (writable) buffer */ +static GstFlowReturn +default_prepare_output_buffer (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf) +{ + GstBaseTransformPrivate *priv; + GstFlowReturn ret; + GstBaseTransformClass *bclass; + GstCaps *incaps, *outcaps; + gsize insize, outsize; + gboolean res; + + priv = trans->priv; + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + /* figure out how to allocate an output buffer */ + if (priv->passthrough) { + /* passthrough, we will not modify the incoming buffer so we can just + * reuse it */ + GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer"); + *outbuf = inbuf; + goto done; + } + + /* we can't reuse the input buffer */ + if (priv->pool) { + if (!priv->pool_active) { + GST_DEBUG_OBJECT (trans, "setting pool %p active", priv->pool); + if (!gst_buffer_pool_set_active (priv->pool, TRUE)) + goto activate_failed; + priv->pool_active = TRUE; + } + GST_DEBUG_OBJECT (trans, "using pool alloc"); + ret = gst_buffer_pool_acquire_buffer (priv->pool, outbuf, NULL); + if (ret != GST_FLOW_OK) + goto alloc_failed; + + goto copy_meta; + } + + /* no pool, we need to figure out the size of the output buffer first */ + if ((bclass->transform_ip != NULL) && priv->always_in_place) { + /* we want to do an in-place alloc */ + if (gst_buffer_is_writable (inbuf)) { + GST_DEBUG_OBJECT (trans, "inplace reuse writable input buffer"); + *outbuf = inbuf; + } else { + GST_DEBUG_OBJECT (trans, "making writable buffer copy"); + /* we make a copy of the input buffer */ + *outbuf = gst_buffer_copy (inbuf); + } + goto done; + } + + /* else use the transform function to get the size */ + incaps = gst_pad_get_current_caps (trans->sinkpad); + outcaps = gst_pad_get_current_caps (trans->srcpad); + + /* srcpad might be flushing already if we're being shut down */ + if (outcaps == NULL) + goto no_outcaps; + + GST_DEBUG_OBJECT (trans, "getting output size for alloc"); + /* copy transform, figure out the output size */ + insize = gst_buffer_get_size (inbuf); + res = gst_base_transform_transform_size (trans, + GST_PAD_SINK, incaps, insize, outcaps, &outsize); + + gst_caps_unref (incaps); + gst_caps_unref (outcaps); + + if (!res) + goto unknown_size; + + GST_DEBUG_OBJECT (trans, "doing alloc of size %" G_GSIZE_FORMAT, outsize); + *outbuf = gst_buffer_new_allocate (priv->allocator, outsize, &priv->params); + if (!*outbuf) { + ret = GST_FLOW_ERROR; + goto alloc_failed; + } + +copy_meta: + /* copy the metadata */ + if (bclass->copy_metadata) + if (!bclass->copy_metadata (trans, inbuf, *outbuf)) { + /* something failed, post a warning */ + GST_ELEMENT_WARNING (trans, STREAM, NOT_IMPLEMENTED, + ("could not copy metadata"), (NULL)); + } + +done: + return GST_FLOW_OK; + + /* ERRORS */ +activate_failed: + { + GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS, + ("failed to activate bufferpool"), ("failed to activate bufferpool")); + return GST_FLOW_ERROR; + } +unknown_size: + { + GST_ERROR_OBJECT (trans, "unknown output size"); + return GST_FLOW_ERROR; + } +alloc_failed: + { + GST_DEBUG_OBJECT (trans, "could not allocate buffer from pool"); + return ret; + } +no_outcaps: + { + GST_DEBUG_OBJECT (trans, "no output caps, source pad has been deactivated"); + gst_caps_unref (incaps); + return GST_FLOW_FLUSHING; + } +} + +typedef struct +{ + GstBaseTransform *trans; + GstBuffer *outbuf; +} CopyMetaData; + +static gboolean +foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data) +{ + CopyMetaData *data = user_data; + GstBaseTransform *trans = data->trans; + GstBaseTransformClass *klass; + const GstMetaInfo *info = (*meta)->info; + GstBuffer *outbuf = data->outbuf; + gboolean do_copy = FALSE; + + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) { + /* never call the transform_meta with memory specific metadata */ + GST_DEBUG_OBJECT (trans, "not copying memory specific metadata %s", + g_type_name (info->api)); + do_copy = FALSE; + } else if (klass->transform_meta) { + do_copy = klass->transform_meta (trans, outbuf, *meta, inbuf); + GST_DEBUG_OBJECT (trans, "transformed metadata %s: copy: %d", + g_type_name (info->api), do_copy); + } + + /* we only copy metadata when the subclass implemented a transform_meta + * function and when it returns %TRUE */ + if (do_copy) { + GstMetaTransformCopy copy_data = { FALSE, 0, -1 }; + /* simply copy then */ + if (info->transform_func) { + GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api)); + info->transform_func (outbuf, *meta, inbuf, + _gst_meta_transform_copy, ©_data); + } else { + GST_DEBUG_OBJECT (trans, "couldn't copy metadata %s", + g_type_name (info->api)); + } + } + return TRUE; +} + +static gboolean +default_copy_metadata (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf) +{ + GstBaseTransformPrivate *priv = trans->priv; + CopyMetaData data; + + /* now copy the metadata */ + GST_DEBUG_OBJECT (trans, "copying metadata"); + + /* this should not happen, buffers allocated from a pool or with + * new_allocate should always be writable. */ + if (!gst_buffer_is_writable (outbuf)) + goto not_writable; + + /* when we get here, the metadata should be writable */ + gst_buffer_copy_into (outbuf, inbuf, + GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1); + + /* clear the GAP flag when the subclass does not understand it */ + if (!priv->gap_aware) + GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP); + + + data.trans = trans; + data.outbuf = outbuf; + + gst_buffer_foreach_meta (inbuf, foreach_metadata, &data); + + return TRUE; + + /* ERRORS */ +not_writable: + { + GST_WARNING_OBJECT (trans, "buffer %p not writable", outbuf); + return FALSE; + } +} + +/* Given @caps calcultate the size of one unit. + * + * For video caps, this is the size of one frame (and thus one buffer). + * For audio caps, this is the size of one sample. + * + * These values are cached since they do not change and the calculation + * potentially involves parsing caps and other expensive stuff. + * + * We have two cache locations to store the size, one for the source caps + * and one for the sink caps. + * + * this function returns %FALSE if no size could be calculated. + */ +static gboolean +gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + gsize * size) +{ + gboolean res = FALSE; + GstBaseTransformClass *bclass; + GstBaseTransformPrivate *priv = trans->priv; + + /* see if we have the result cached */ + if (priv->cache_caps1 == caps) { + *size = priv->cache_caps1_size; + GST_DEBUG_OBJECT (trans, + "returned %" G_GSIZE_FORMAT " from first cache", *size); + return TRUE; + } + if (priv->cache_caps2 == caps) { + *size = priv->cache_caps2_size; + GST_DEBUG_OBJECT (trans, + "returned %" G_GSIZE_FORMAT " from second cached", *size); + return TRUE; + } + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + res = bclass->get_unit_size (trans, caps, size); + GST_DEBUG_OBJECT (trans, + "caps %" GST_PTR_FORMAT " has unit size %" G_GSIZE_FORMAT ", res %s", + caps, *size, res ? "TRUE" : "FALSE"); + + if (res) { + /* and cache the values */ + if (priv->cache_caps1 == NULL) { + gst_caps_replace (&priv->cache_caps1, caps); + priv->cache_caps1_size = *size; + GST_DEBUG_OBJECT (trans, + "caching %" G_GSIZE_FORMAT " in first cache", *size); + } else if (priv->cache_caps2 == NULL) { + gst_caps_replace (&priv->cache_caps2, caps); + priv->cache_caps2_size = *size; + GST_DEBUG_OBJECT (trans, + "caching %" G_GSIZE_FORMAT " in second cache", *size); + } else { + GST_DEBUG_OBJECT (trans, "no free spot to cache unit_size"); + } + } + return res; +} + +static gboolean +gst_base_transform_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean ret = TRUE; + + trans = GST_BASE_TRANSFORM_CAST (parent); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->sink_event) + ret = bclass->sink_event (trans, event); + else + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event) +{ + gboolean ret = TRUE, forward = TRUE; + GstBaseTransformPrivate *priv = trans->priv; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + break; + case GST_EVENT_FLUSH_STOP: + GST_OBJECT_LOCK (trans); + /* reset QoS parameters */ + priv->proportion = 1.0; + priv->earliest_time = -1; + priv->discont = FALSE; + priv->processed = 0; + priv->dropped = 0; + GST_OBJECT_UNLOCK (trans); + /* we need new segment info after the flush. */ + trans->have_segment = FALSE; + gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED); + priv->position_out = GST_CLOCK_TIME_NONE; + break; + case GST_EVENT_EOS: + break; + case GST_EVENT_TAG: + break; + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + /* clear any pending reconfigure flag */ + gst_pad_check_reconfigure (trans->srcpad); + ret = gst_base_transform_setcaps (trans, trans->sinkpad, caps); + if (!ret) + gst_pad_mark_reconfigure (trans->srcpad); + + forward = FALSE; + break; + } + case GST_EVENT_SEGMENT: + { + gst_event_copy_segment (event, &trans->segment); + trans->have_segment = TRUE; + + GST_DEBUG_OBJECT (trans, "received SEGMENT %" GST_SEGMENT_FORMAT, + &trans->segment); + break; + } + default: + break; + } + + if (ret && forward) + ret = gst_pad_push_event (trans->srcpad, event); + else + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_base_transform_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean ret = TRUE; + + trans = GST_BASE_TRANSFORM_CAST (parent); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->src_event) + ret = bclass->src_event (trans, event); + else + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_base_transform_src_eventfunc (GstBaseTransform * trans, GstEvent * event) +{ + gboolean ret; + + GST_DEBUG_OBJECT (trans, "handling event %p %" GST_PTR_FORMAT, event, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + break; + case GST_EVENT_NAVIGATION: + break; + case GST_EVENT_QOS: + { + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + + gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp); + gst_base_transform_update_qos (trans, proportion, diff, timestamp); + break; + } + default: + break; + } + + ret = gst_pad_push_event (trans->sinkpad, event); + + return ret; +} + +/* Takes the input buffer */ +static GstFlowReturn +default_submit_input_buffer (GstBaseTransform * trans, gboolean is_discont, + GstBuffer * inbuf) +{ + GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + GstBaseTransformPrivate *priv = trans->priv; + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime running_time; + GstClockTime timestamp; + + if (G_UNLIKELY (!gst_base_transform_reconfigure (trans))) + goto not_negotiated; + + if (GST_BUFFER_OFFSET_IS_VALID (inbuf)) + GST_DEBUG_OBJECT (trans, + "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT + " and offset %" G_GUINT64_FORMAT, inbuf, gst_buffer_get_size (inbuf), + GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)), GST_BUFFER_OFFSET (inbuf)); + else + GST_DEBUG_OBJECT (trans, + "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT + " and offset NONE", inbuf, gst_buffer_get_size (inbuf), + GST_TIME_ARGS (GST_BUFFER_PTS (inbuf))); + + /* Don't allow buffer handling before negotiation, except in passthrough mode + * or if the class doesn't implement a set_caps function (in which case it doesn't + * care about caps) + */ + if (!priv->negotiated && !priv->passthrough && (bclass->set_caps != NULL)) + goto not_negotiated; + + /* can only do QoS if the segment is in TIME */ + if (trans->segment.format != GST_FORMAT_TIME) + goto no_qos; + + /* QOS is done on the running time of the buffer, get it now */ + timestamp = GST_BUFFER_TIMESTAMP (inbuf); + running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME, + timestamp); + + if (running_time != -1) { + gboolean need_skip; + GstClockTime earliest_time; + gdouble proportion; + + /* lock for getting the QoS parameters that are set (in a different thread) + * with the QOS events */ + GST_OBJECT_LOCK (trans); + earliest_time = priv->earliest_time; + proportion = priv->proportion; + /* check for QoS, don't perform conversion for buffers + * that are known to be late. */ + need_skip = priv->qos_enabled && + earliest_time != -1 && running_time <= earliest_time; + GST_OBJECT_UNLOCK (trans); + + if (need_skip) { + GstMessage *qos_msg; + GstClockTime duration; + guint64 stream_time; + gint64 jitter; + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "skipping transform: qostime %" + GST_TIME_FORMAT " <= %" GST_TIME_FORMAT, + GST_TIME_ARGS (running_time), GST_TIME_ARGS (earliest_time)); + + priv->dropped++; + + duration = GST_BUFFER_DURATION (inbuf); + stream_time = + gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, + timestamp); + jitter = GST_CLOCK_DIFF (running_time, earliest_time); + + qos_msg = + gst_message_new_qos (GST_OBJECT_CAST (trans), FALSE, running_time, + stream_time, timestamp, duration); + gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000); + gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, + priv->processed, priv->dropped); + gst_element_post_message (GST_ELEMENT_CAST (trans), qos_msg); + + /* mark discont for next buffer */ + priv->discont = TRUE; + ret = GST_BASE_TRANSFORM_FLOW_DROPPED; + goto skip; + } + } + +no_qos: + /* Stash input buffer where the default generate_output + * function can find it */ + if (trans->queued_buf) + gst_buffer_unref (trans->queued_buf); + trans->queued_buf = inbuf; + return ret; +skip: + gst_buffer_unref (inbuf); + return ret; + +not_negotiated: + { + gst_buffer_unref (inbuf); + if (GST_PAD_IS_FLUSHING (trans->srcpad)) + return GST_FLOW_FLUSHING; + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static GstFlowReturn +default_generate_output (GstBaseTransform * trans, GstBuffer ** outbuf) +{ + GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + GstBaseTransformPrivate *priv = trans->priv; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *inbuf; + gboolean want_in_place; + + /* Retrieve stashed input buffer, if the default submit_input_buffer + * was run. Takes ownership back from there */ + inbuf = trans->queued_buf; + trans->queued_buf = NULL; + + /* This default processing method needs one input buffer to feed to + * the transform functions, we can't do anything without it */ + if (inbuf == NULL) + return GST_FLOW_OK; + + /* first try to allocate an output buffer based on the currently negotiated + * format. outbuf will contain a buffer suitable for doing the configured + * transform after this function. */ + if (bclass->prepare_output_buffer == NULL) + goto no_prepare; + + GST_DEBUG_OBJECT (trans, "calling prepare buffer"); + ret = bclass->prepare_output_buffer (trans, inbuf, outbuf); + + if (ret != GST_FLOW_OK || *outbuf == NULL) + goto no_buffer; + + GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", inbuf, + *outbuf); + + /* now perform the needed transform */ + if (priv->passthrough) { + /* In passthrough mode, give transform_ip a look at the + * buffer, without making it writable, or just push the + * data through */ + if (bclass->transform_ip_on_passthrough && bclass->transform_ip) { + GST_DEBUG_OBJECT (trans, "doing passthrough transform_ip"); + ret = bclass->transform_ip (trans, *outbuf); + } else { + GST_DEBUG_OBJECT (trans, "element is in passthrough"); + } + } else { + want_in_place = (bclass->transform_ip != NULL) && priv->always_in_place; + + if (want_in_place) { + GST_DEBUG_OBJECT (trans, "doing inplace transform"); + ret = bclass->transform_ip (trans, *outbuf); + } else { + GST_DEBUG_OBJECT (trans, "doing non-inplace transform"); + + if (bclass->transform) + ret = bclass->transform (trans, inbuf, *outbuf); + else + ret = GST_FLOW_NOT_SUPPORTED; + } + } + + /* only unref input buffer if we allocated a new outbuf buffer. If we reused + * the input buffer, no refcount is changed to keep the input buffer writable + * when needed. */ + if (*outbuf != inbuf) + gst_buffer_unref (inbuf); + + return ret; + + /* ERRORS */ +no_prepare: + { + gst_buffer_unref (inbuf); + GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED, + ("Sub-class has no prepare_output_buffer implementation"), (NULL)); + return GST_FLOW_NOT_SUPPORTED; + } +no_buffer: + { + gst_buffer_unref (inbuf); + *outbuf = NULL; + GST_WARNING_OBJECT (trans, "could not get buffer from pool: %s", + gst_flow_get_name (ret)); + return ret; + } +} + +/* FIXME, getrange is broken, need to pull range from the other + * end based on the transform_size result. + */ +static GstFlowReturn +gst_base_transform_getrange (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (parent); + GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent); + GstBaseTransformPrivate *priv = trans->priv; + GstFlowReturn ret; + GstBuffer *inbuf = NULL; + GstBuffer *outbuf = NULL; + + /* Try and generate a buffer, if the sub-class wants more data, + * pull some and repeat until a buffer (or error) is produced */ + do { + ret = klass->generate_output (trans, &outbuf); + + /* Consume the DROPPED return value and go get more data */ + if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) + ret = GST_FLOW_OK; + + if (ret != GST_FLOW_OK || outbuf != NULL) + break; + + /* No buffer generated, try and pull data */ + ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto pull_error; + + if (klass->before_transform) + klass->before_transform (trans, inbuf); + + /* Set discont flag so we can mark the next outgoing buffer */ + if (GST_BUFFER_IS_DISCONT (inbuf)) { + GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", inbuf); + priv->discont = TRUE; + } + + /* FIXME: Input offsets and lengths need to be translated, as per + * the FIXME above. For now, just advance somewhat */ + offset += gst_buffer_get_size (inbuf); + + ret = klass->submit_input_buffer (trans, priv->discont, inbuf); + if (ret != GST_FLOW_OK) { + if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) + ret = GST_FLOW_OK; + goto done; + } + } while (ret == GST_FLOW_OK && outbuf == NULL); + + *buffer = outbuf; + if (outbuf) { + /* apply DISCONT flag if the buffer is not yet marked as such */ + if (priv->discont) { + GST_DEBUG_OBJECT (trans, "we have a pending DISCONT"); + if (!GST_BUFFER_IS_DISCONT (outbuf)) { + GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer"); + outbuf = gst_buffer_make_writable (outbuf); + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + } + priv->discont = FALSE; + } + priv->processed++; + } +done: + return ret; + + /* ERRORS */ +pull_error: + { + GST_DEBUG_OBJECT (trans, "failed to pull a buffer: %s", + gst_flow_get_name (ret)); + goto done; + } +} + +/* The flow of the chain function is the reverse of the + * getrange() function - we have data, feed it to the sub-class + * and then iterate, pushing buffers it generates until it either + * wants more data or returns an error */ +static GstFlowReturn +gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent); + GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (trans); + GstBaseTransformPrivate *priv = trans->priv; + GstFlowReturn ret; + GstClockTime position = GST_CLOCK_TIME_NONE; + GstClockTime timestamp, duration; + GstBuffer *outbuf = NULL; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_DURATION (buffer); + + /* calculate end position of the incoming buffer */ + if (timestamp != GST_CLOCK_TIME_NONE) { + if (duration != GST_CLOCK_TIME_NONE) + position = timestamp + duration; + else + position = timestamp; + } + + if (klass->before_transform) + klass->before_transform (trans, buffer); + + /* Set discont flag so we can mark the outgoing buffer */ + if (GST_BUFFER_IS_DISCONT (buffer)) { + GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", buffer); + priv->discont = TRUE; + } + + /* Takes ownership of input buffer */ + ret = klass->submit_input_buffer (trans, priv->discont, buffer); + if (ret != GST_FLOW_OK) + goto done; + + do { + outbuf = NULL; + + ret = klass->generate_output (trans, &outbuf); + + /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but + * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */ + if (outbuf != NULL) { + if (ret == GST_FLOW_OK) { + GstClockTime position_out = GST_CLOCK_TIME_NONE; + + /* Remember last stop position */ + if (position != GST_CLOCK_TIME_NONE && + trans->segment.format == GST_FORMAT_TIME) + trans->segment.position = position; + + if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf)) { + position_out = GST_BUFFER_TIMESTAMP (outbuf); + if (GST_BUFFER_DURATION_IS_VALID (outbuf)) + position_out += GST_BUFFER_DURATION (outbuf); + } else if (position != GST_CLOCK_TIME_NONE) { + position_out = position; + } + if (position_out != GST_CLOCK_TIME_NONE + && trans->segment.format == GST_FORMAT_TIME) + priv->position_out = position_out; + + /* apply DISCONT flag if the buffer is not yet marked as such */ + if (trans->priv->discont) { + GST_DEBUG_OBJECT (trans, "we have a pending DISCONT"); + if (!GST_BUFFER_IS_DISCONT (outbuf)) { + GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer"); + outbuf = gst_buffer_make_writable (outbuf); + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + } + priv->discont = FALSE; + } + priv->processed++; + + ret = gst_pad_push (trans->srcpad, outbuf); + } else { + GST_DEBUG_OBJECT (trans, "we got return %s", gst_flow_get_name (ret)); + gst_buffer_unref (outbuf); + } + } + } while (ret == GST_FLOW_OK && outbuf != NULL); + +done: + /* convert internal flow to OK and mark discont for the next buffer. */ + if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) { + GST_DEBUG_OBJECT (trans, "dropped a buffer, marking DISCONT"); + priv->discont = TRUE; + ret = GST_FLOW_OK; + } + + return ret; +} + +static void +gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM_CAST (object); + + switch (prop_id) { + case PROP_QOS: + gst_base_transform_set_qos_enabled (trans, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM_CAST (object); + + switch (prop_id) { + case PROP_QOS: + g_value_set_boolean (value, gst_base_transform_is_qos_enabled (trans)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* not a vmethod of anything, just an internal method */ +static gboolean +gst_base_transform_activate (GstBaseTransform * trans, gboolean active) +{ + GstBaseTransformClass *bclass; + GstBaseTransformPrivate *priv = trans->priv; + gboolean result = TRUE; + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (active) { + GstCaps *incaps, *outcaps; + + if (priv->pad_mode == GST_PAD_MODE_NONE && bclass->start) + result &= bclass->start (trans); + + incaps = gst_pad_get_current_caps (trans->sinkpad); + outcaps = gst_pad_get_current_caps (trans->srcpad); + + GST_OBJECT_LOCK (trans); + if (incaps && outcaps) + priv->have_same_caps = + gst_caps_is_equal (incaps, outcaps) || priv->passthrough; + else + priv->have_same_caps = priv->passthrough; + GST_DEBUG_OBJECT (trans, "have_same_caps %d", priv->have_same_caps); + priv->negotiated = FALSE; + trans->have_segment = FALSE; + gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED); + priv->position_out = GST_CLOCK_TIME_NONE; + priv->proportion = 1.0; + priv->earliest_time = -1; + priv->discont = FALSE; + priv->processed = 0; + priv->dropped = 0; + GST_OBJECT_UNLOCK (trans); + + if (incaps) + gst_caps_unref (incaps); + if (outcaps) + gst_caps_unref (outcaps); + } else { + /* We must make sure streaming has finished before resetting things + * and calling the ::stop vfunc */ + GST_PAD_STREAM_LOCK (trans->sinkpad); + GST_PAD_STREAM_UNLOCK (trans->sinkpad); + + priv->have_same_caps = FALSE; + /* We can only reset the passthrough mode if the instance told us to + handle it in configure_caps */ + if (bclass->passthrough_on_same_caps) { + gst_base_transform_set_passthrough (trans, FALSE); + } + gst_caps_replace (&priv->cache_caps1, NULL); + gst_caps_replace (&priv->cache_caps2, NULL); + + /* Make sure any left over buffer is freed */ + gst_buffer_replace (&trans->queued_buf, NULL); + + if (priv->pad_mode != GST_PAD_MODE_NONE && bclass->stop) + result &= bclass->stop (trans); + + gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL); + } + + return result; +} + +static gboolean +gst_base_transform_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM_CAST (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + { + result = gst_base_transform_activate (trans, active); + + if (result) + trans->priv->pad_mode = active ? GST_PAD_MODE_PUSH : GST_PAD_MODE_NONE; + + break; + } + default: + result = TRUE; + break; + } + return result; +} + +static gboolean +gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM_CAST (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + { + result = + gst_pad_activate_mode (trans->sinkpad, GST_PAD_MODE_PULL, active); + + if (result) + result &= gst_base_transform_activate (trans, active); + + if (result) + trans->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE; + break; + } + default: + result = TRUE; + break; + } + + return result; +} + +/** + * gst_base_transform_set_passthrough: + * @trans: the #GstBaseTransform to set + * @passthrough: boolean indicating passthrough mode. + * + * Set passthrough mode for this filter by default. This is mostly + * useful for filters that do not care about negotiation. + * + * Always %TRUE for filters which don't implement either a transform + * or transform_ip method. + * + * MT safe. + */ +void +gst_base_transform_set_passthrough (GstBaseTransform * trans, + gboolean passthrough) +{ + GstBaseTransformClass *bclass; + + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + GST_OBJECT_LOCK (trans); + if (!passthrough) { + if (bclass->transform_ip || bclass->transform) + trans->priv->passthrough = FALSE; + } else { + trans->priv->passthrough = TRUE; + } + + GST_DEBUG_OBJECT (trans, "set passthrough %d", trans->priv->passthrough); + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_is_passthrough: + * @trans: the #GstBaseTransform to query + * + * See if @trans is configured as a passthrough transform. + * + * Returns: %TRUE is the transform is configured in passthrough mode. + * + * MT safe. + */ +gboolean +gst_base_transform_is_passthrough (GstBaseTransform * trans) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE); + + GST_OBJECT_LOCK (trans); + result = trans->priv->passthrough; + GST_OBJECT_UNLOCK (trans); + + return result; +} + +/** + * gst_base_transform_set_in_place: + * @trans: the #GstBaseTransform to modify + * @in_place: Boolean value indicating that we would like to operate + * on in_place buffers. + * + * Determines whether a non-writable buffer will be copied before passing + * to the transform_ip function. + * + * * Always %TRUE if no transform function is implemented. + * * Always %FALSE if ONLY transform function is implemented. + * + * MT safe. + */ +void +gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place) +{ + GstBaseTransformClass *bclass; + + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + GST_OBJECT_LOCK (trans); + + if (in_place) { + if (bclass->transform_ip) { + GST_DEBUG_OBJECT (trans, "setting in_place TRUE"); + trans->priv->always_in_place = TRUE; + } + } else { + if (bclass->transform) { + GST_DEBUG_OBJECT (trans, "setting in_place FALSE"); + trans->priv->always_in_place = FALSE; + } + } + + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_is_in_place: + * @trans: the #GstBaseTransform to query + * + * See if @trans is configured as a in_place transform. + * + * Returns: %TRUE is the transform is configured in in_place mode. + * + * MT safe. + */ +gboolean +gst_base_transform_is_in_place (GstBaseTransform * trans) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE); + + GST_OBJECT_LOCK (trans); + result = trans->priv->always_in_place; + GST_OBJECT_UNLOCK (trans); + + return result; +} + +/** + * gst_base_transform_update_qos: + * @trans: a #GstBaseTransform + * @proportion: the proportion + * @diff: the diff against the clock + * @timestamp: the timestamp of the buffer generating the QoS expressed in + * running_time. + * + * Set the QoS parameters in the transform. This function is called internally + * when a QOS event is received but subclasses can provide custom information + * when needed. + * + * MT safe. + */ +void +gst_base_transform_update_qos (GstBaseTransform * trans, + gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, + "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %" + GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp)); + + GST_OBJECT_LOCK (trans); + trans->priv->proportion = proportion; + trans->priv->earliest_time = timestamp + diff; + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_set_qos_enabled: + * @trans: a #GstBaseTransform + * @enabled: new state + * + * Enable or disable QoS handling in the transform. + * + * MT safe. + */ +void +gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "enabled: %d", enabled); + + GST_OBJECT_LOCK (trans); + trans->priv->qos_enabled = enabled; + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_is_qos_enabled: + * @trans: a #GstBaseTransform + * + * Queries if the transform will handle QoS. + * + * Returns: %TRUE if QoS is enabled. + * + * MT safe. + */ +gboolean +gst_base_transform_is_qos_enabled (GstBaseTransform * trans) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE); + + GST_OBJECT_LOCK (trans); + result = trans->priv->qos_enabled; + GST_OBJECT_UNLOCK (trans); + + return result; +} + +/** + * gst_base_transform_set_gap_aware: + * @trans: a #GstBaseTransform + * @gap_aware: New state + * + * If @gap_aware is %FALSE (the default), output buffers will have the + * %GST_BUFFER_FLAG_GAP flag unset. + * + * If set to %TRUE, the element must handle output buffers with this flag set + * correctly, i.e. it can assume that the buffer contains neutral data but must + * unset the flag if the output is no neutral data. + * + * MT safe. + */ +void +gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + GST_OBJECT_LOCK (trans); + trans->priv->gap_aware = gap_aware; + GST_DEBUG_OBJECT (trans, "set gap aware %d", trans->priv->gap_aware); + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_set_prefer_passthrough: + * @trans: a #GstBaseTransform + * @prefer_passthrough: New state + * + * If @prefer_passthrough is %TRUE (the default), @trans will check and + * prefer passthrough caps from the list of caps returned by the + * transform_caps vmethod. + * + * If set to %FALSE, the element must order the caps returned from the + * transform_caps function in such a way that the preferred format is + * first in the list. This can be interesting for transforms that can do + * passthrough transforms but prefer to do something else, like a + * capsfilter. + * + * MT safe. + * + * Since: 1.0.1 + */ +void +gst_base_transform_set_prefer_passthrough (GstBaseTransform * trans, + gboolean prefer_passthrough) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + GST_OBJECT_LOCK (trans); + trans->priv->prefer_passthrough = prefer_passthrough; + GST_DEBUG_OBJECT (trans, "prefer passthrough %d", prefer_passthrough); + GST_OBJECT_UNLOCK (trans); +} + +/** + * gst_base_transform_reconfigure_sink: + * @trans: a #GstBaseTransform + * + * Instructs @trans to request renegotiation upstream. This function is + * typically called after properties on the transform were set that + * influence the input format. + */ +void +gst_base_transform_reconfigure_sink (GstBaseTransform * trans) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + /* push the renegotiate event */ + if (!gst_pad_push_event (GST_BASE_TRANSFORM_SINK_PAD (trans), + gst_event_new_reconfigure ())) + GST_DEBUG_OBJECT (trans, "Renegotiate event wasn't handled"); +} + +/** + * gst_base_transform_reconfigure_src: + * @trans: a #GstBaseTransform + * + * Instructs @trans to renegotiate a new downstream transform on the next + * buffer. This function is typically called after properties on the transform + * were set that influence the output format. + */ +void +gst_base_transform_reconfigure_src (GstBaseTransform * trans) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + gst_pad_mark_reconfigure (trans->srcpad); +} + +/** + * gst_base_transform_get_buffer_pool: + * @trans: a #GstBaseTransform + * + * Returns: (transfer full): the instance of the #GstBufferPool used + * by @trans; free it after use it + */ +GstBufferPool * +gst_base_transform_get_buffer_pool (GstBaseTransform * trans) +{ + g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), NULL); + + if (trans->priv->pool) + return gst_object_ref (trans->priv->pool); + + return NULL; +} + +/** + * gst_base_transform_get_allocator: + * @trans: a #GstBaseTransform + * @allocator: (out) (allow-none) (transfer full): the #GstAllocator + * used + * @params: (out) (allow-none) (transfer full): the + * #GstAllocationParams of @allocator + * + * Lets #GstBaseTransform sub-classes to know the memory @allocator + * used by the base class and its @params. + * + * Unref the @allocator after use it. + */ +void +gst_base_transform_get_allocator (GstBaseTransform * trans, + GstAllocator ** allocator, GstAllocationParams * params) +{ + g_return_if_fail (GST_IS_BASE_TRANSFORM (trans)); + + if (allocator) + *allocator = trans->priv->allocator ? + gst_object_ref (trans->priv->allocator) : NULL; + + if (params) + *params = trans->priv->params; +} + +/** + * gst_base_transform_update_src_caps: + * @trans: a #GstBaseTransform + * @updated_caps: An updated version of the srcpad caps to be pushed + * downstream + * + * Updates the srcpad caps and send the caps downstream. This function + * can be used by subclasses when they have already negotiated their caps + * but found a change in them (or computed new informations). This way, + * they can notify downstream about that change without loosing any + * buffer. + * + * Returns: %TRUE if the caps could be send downstream %FALSE otherwise + * + * Since: 1.6 + */ +gboolean +gst_base_transform_update_src_caps (GstBaseTransform * trans, + GstCaps * updated_caps) +{ + g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE); + + if (gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (trans), + gst_event_new_caps (updated_caps))) { + gst_pad_mark_reconfigure (trans->srcpad); + + return TRUE; + } + + return FALSE; +} diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h new file mode 100644 index 0000000..cd7d5c5 --- /dev/null +++ b/libs/gst/base/gstbasetransform.h @@ -0,0 +1,359 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BASE_TRANSFORM_H__ +#define __GST_BASE_TRANSFORM_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_TRANSFORM (gst_base_transform_get_type()) +#define GST_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransform)) +#define GST_BASE_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_BASE_TRANSFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_IS_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_TRANSFORM)) +#define GST_IS_BASE_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_TRANSFORM)) +#define GST_BASE_TRANSFORM_CAST(obj) ((GstBaseTransform *)(obj)) + +/** + * GST_BASE_TRANSFORM_SINK_NAME: + * + * The name of the templates for the sink pad. + */ +#define GST_BASE_TRANSFORM_SINK_NAME "sink" +/** + * GST_BASE_TRANSFORM_SRC_NAME: + * + * The name of the templates for the source pad. + */ +#define GST_BASE_TRANSFORM_SRC_NAME "src" + +/** + * GST_BASE_TRANSFORM_SRC_PAD: + * @obj: base transform instance + * + * Gives the pointer to the source #GstPad object of the element. + */ +#define GST_BASE_TRANSFORM_SRC_PAD(obj) (GST_BASE_TRANSFORM_CAST (obj)->srcpad) + +/** + * GST_BASE_TRANSFORM_SINK_PAD: + * @obj: base transform instance + * + * Gives the pointer to the sink #GstPad object of the element. + */ +#define GST_BASE_TRANSFORM_SINK_PAD(obj) (GST_BASE_TRANSFORM_CAST (obj)->sinkpad) + +/** + * GST_BASE_TRANSFORM_FLOW_DROPPED: + * + * A #GstFlowReturn that can be returned from transform and transform_ip to + * indicate that no output buffer was generated. + */ +#define GST_BASE_TRANSFORM_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS + +typedef struct _GstBaseTransform GstBaseTransform; +typedef struct _GstBaseTransformClass GstBaseTransformClass; +typedef struct _GstBaseTransformPrivate GstBaseTransformPrivate; + +/** + * GstBaseTransform: + * + * The opaque #GstBaseTransform data structure. + */ +struct _GstBaseTransform { + GstElement element; + + /*< protected >*/ + /* source and sink pads */ + GstPad *sinkpad; + GstPad *srcpad; + + /* MT-protected (with STREAM_LOCK) */ + gboolean have_segment; + GstSegment segment; + /* Default submit_input_buffer places the buffer here, + * for consumption by the generate_output method: */ + GstBuffer *queued_buf; + + /*< private >*/ + GstBaseTransformPrivate *priv; + + gpointer _gst_reserved[GST_PADDING_LARGE-1]; +}; + +/** + * GstBaseTransformClass: + * @parent_class: Element parent class + * @passthrough_on_same_caps: If set to %TRUE, passthrough mode will be + * automatically enabled if the caps are the same. + * Set to %FALSE by default. + * @transform_ip_on_passthrough: If set to %TRUE, @transform_ip will be called in + * passthrough mode. The passed buffer might not be + * writable. When %FALSE, neither @transform nor + * @transform_ip will be called in passthrough mode. + * Set to %TRUE by default. + * @transform_caps: Optional. Given the pad in this direction and the given + * caps, what caps are allowed on the other pad in this + * element ? + * @fixate_caps: Optional. Given the pad in this direction and the given + * caps, fixate the caps on the other pad. The function takes + * ownership of @othercaps and returns a fixated version of + * @othercaps. @othercaps is not guaranteed to be writable. + * @accept_caps: Optional. + * Subclasses can override this method to check if @caps can be + * handled by the element. The default implementation might not be + * the most optimal way to check this in all cases. + * @set_caps: allows the subclass to be notified of the actual caps set. + * @query: Optional. + * Handle a requested query. Subclasses that implement this + * should must chain up to the parent if they didn't handle the + * query + * @decide_allocation: Setup the allocation parameters for allocating output + * buffers. The passed in query contains the result of the + * downstream allocation query. This function is only called + * when not operating in passthrough mode. The default + * implementation will remove all memory dependent metadata. + * If there is a @filter_meta method implementation, it will + * be called for all metadata API in the downstream query, + * otherwise the metadata API is removed. + * @filter_meta: Return %TRUE if the metadata API should be proposed in the + * upstream allocation query. The default implementation is %NULL + * and will cause all metadata to be removed. + * @propose_allocation: Propose buffer allocation parameters for upstream elements. + * This function must be implemented if the element reads or + * writes the buffer content. The query that was passed to + * the decide_allocation is passed in this method (or %NULL + * when the element is in passthrough mode). The default + * implementation will pass the query downstream when in + * passthrough mode and will copy all the filtered metadata + * API in non-passthrough mode. + * @transform_size: Optional. Given the size of a buffer in the given direction + * with the given caps, calculate the size in bytes of a buffer + * on the other pad with the given other caps. + * The default implementation uses get_unit_size and keeps + * the number of units the same. + * @get_unit_size: Required if the transform is not in-place. + * get the size in bytes of one unit for the given caps. + * @start: Optional. + * Called when the element starts processing. + * Allows opening external resources. + * @stop: Optional. + * Called when the element stops processing. + * Allows closing external resources. + * @sink_event: Optional. + * Event handler on the sink pad. The default implementation + * handles the event and forwards it downstream. + * @src_event: Optional. + * Event handler on the source pad. The default implementation + * handles the event and forwards it upstream. + * @prepare_output_buffer: Optional. + * Subclasses can override this to do their own + * allocation of output buffers. Elements that only do + * analysis can return a subbuffer or even just + * return a reference to the input buffer (if in + * passthrough mode). The default implementation will + * use the negotiated allocator or bufferpool and + * transform_size to allocate an output buffer or it + * will return the input buffer in passthrough mode. + * @copy_metadata: Optional. + * Copy the metadata from the input buffer to the output buffer. + * The default implementation will copy the flags, timestamps and + * offsets of the buffer. + * @transform_meta: Optional. Transform the metadata on the input buffer to the + * output buffer. By default this method copies all meta without + * tags. subclasses can implement this method and return %TRUE if + * the metadata is to be copied. + * @before_transform: Optional. + * This method is called right before the base class will + * start processing. Dynamic properties or other delayed + * configuration could be performed in this method. + * @transform: Required if the element does not operate in-place. + * Transforms one incoming buffer to one outgoing buffer. + * The function is allowed to change size/timestamp/duration + * of the outgoing buffer. + * @transform_ip: Required if the element operates in-place. + * Transform the incoming buffer in-place. + * @submit_input_buffer: Function which accepts a new input buffer and pre-processes it. + * The default implementation performs caps (re)negotiation, then + * QoS if needed, and places the input buffer into the @queued_buf + * member variable. If the buffer is dropped due to QoS, it returns + * GST_BASE_TRANSFORM_FLOW_DROPPED. If this input buffer is not + * contiguous with any previous input buffer, then @is_discont + * is set to %TRUE. (Since 1.6) + * @generate_output: Called after each new input buffer is submitted repeatedly + * until it either generates an error or fails to generate an output + * buffer. The default implementation takes the contents of the + * @queued_buf variable, generates an output buffer if needed + * by calling the class @prepare_output_buffer, and then + * calls either @transform or @transform_ip. Elements that don't + * do 1-to-1 transformations on input to output buffers can either + * return GST_BASE_TRANSFORM_FLOW_DROPPED or simply not generate + * an output buffer until they are ready to do so. (Since 1.6) + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At minimum either @transform or @transform_ip need to be overridden. + * If the element can overwrite the input data with the results (data is of the + * same type and quantity) it should provide @transform_ip. + */ +struct _GstBaseTransformClass { + GstElementClass parent_class; + + /*< public >*/ + gboolean passthrough_on_same_caps; + gboolean transform_ip_on_passthrough; + + /* virtual methods for subclasses */ + GstCaps* (*transform_caps) (GstBaseTransform *trans, + GstPadDirection direction, + GstCaps *caps, GstCaps *filter); + GstCaps* (*fixate_caps) (GstBaseTransform *trans, + GstPadDirection direction, GstCaps *caps, + GstCaps *othercaps); + gboolean (*accept_caps) (GstBaseTransform *trans, GstPadDirection direction, + GstCaps *caps); + gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *incaps, + GstCaps *outcaps); + gboolean (*query) (GstBaseTransform *trans, GstPadDirection direction, + GstQuery *query); + + /* decide allocation query for output buffers */ + gboolean (*decide_allocation) (GstBaseTransform *trans, GstQuery *query); + gboolean (*filter_meta) (GstBaseTransform *trans, GstQuery *query, + GType api, const GstStructure *params); + + /* propose allocation query parameters for input buffers */ + gboolean (*propose_allocation) (GstBaseTransform *trans, GstQuery *decide_query, + GstQuery *query); + + /** + * GstBaseTransformClass::transform_size: + * @othersize: (out): + */ + gboolean (*transform_size) (GstBaseTransform *trans, + GstPadDirection direction, + GstCaps *caps, gsize size, + GstCaps *othercaps, gsize *othersize); + + /** + * GstBaseTransformClass::get_unit_size: + * @size: (out): + */ + gboolean (*get_unit_size) (GstBaseTransform *trans, GstCaps *caps, + gsize *size); + + /* states */ + gboolean (*start) (GstBaseTransform *trans); + gboolean (*stop) (GstBaseTransform *trans); + + /* sink and src pad event handlers */ + gboolean (*sink_event) (GstBaseTransform *trans, GstEvent *event); + gboolean (*src_event) (GstBaseTransform *trans, GstEvent *event); + + /** + * GstBaseTransformClass::prepare_output_buffer: + * @outbuf: (out): + */ + GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans, + GstBuffer *input, GstBuffer **outbuf); + + /* metadata */ + gboolean (*copy_metadata) (GstBaseTransform *trans, GstBuffer *input, + GstBuffer *outbuf); + gboolean (*transform_meta) (GstBaseTransform *trans, GstBuffer *outbuf, + GstMeta *meta, GstBuffer *inbuf); + + void (*before_transform) (GstBaseTransform *trans, GstBuffer *buffer); + + /* transform */ + GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf, + GstBuffer *outbuf); + GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf); + + GstFlowReturn (*submit_input_buffer) (GstBaseTransform *trans, gboolean is_discont, GstBuffer *input); + + /** + * GstBaseTransformClass::generate_output: + * @outbuf: (out): + */ + GstFlowReturn (*generate_output) (GstBaseTransform *trans, GstBuffer **outbuf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE - 2]; +}; + +GST_BASE_API +GType gst_base_transform_get_type (void); + +GST_BASE_API +void gst_base_transform_set_passthrough (GstBaseTransform *trans, + gboolean passthrough); +GST_BASE_API +gboolean gst_base_transform_is_passthrough (GstBaseTransform *trans); + +GST_BASE_API +void gst_base_transform_set_in_place (GstBaseTransform *trans, + gboolean in_place); +GST_BASE_API +gboolean gst_base_transform_is_in_place (GstBaseTransform *trans); + +GST_BASE_API +void gst_base_transform_update_qos (GstBaseTransform *trans, + gdouble proportion, + GstClockTimeDiff diff, + GstClockTime timestamp); +GST_BASE_API +void gst_base_transform_set_qos_enabled (GstBaseTransform *trans, + gboolean enabled); +GST_BASE_API +gboolean gst_base_transform_is_qos_enabled (GstBaseTransform *trans); + +GST_BASE_API +void gst_base_transform_set_gap_aware (GstBaseTransform *trans, + gboolean gap_aware); +GST_BASE_API +void gst_base_transform_set_prefer_passthrough (GstBaseTransform *trans, + gboolean prefer_passthrough); +GST_BASE_API +GstBufferPool * gst_base_transform_get_buffer_pool (GstBaseTransform *trans); + +GST_BASE_API +void gst_base_transform_get_allocator (GstBaseTransform *trans, + GstAllocator **allocator, + GstAllocationParams *params); +GST_BASE_API +void gst_base_transform_reconfigure_sink (GstBaseTransform *trans); + +GST_BASE_API +void gst_base_transform_reconfigure_src (GstBaseTransform *trans); + +GST_BASE_API +gboolean gst_base_transform_update_src_caps (GstBaseTransform *trans, + GstCaps *updated_caps); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseTransform, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_BASE_TRANSFORM_H__ */ diff --git a/libs/gst/base/gstbitreader-docs.h b/libs/gst/base/gstbitreader-docs.h new file mode 100644 index 0000000..d2842d6 --- /dev/null +++ b/libs/gst/base/gstbitreader-docs.h @@ -0,0 +1,141 @@ +/* GStreamer bit reader dummy header for gtk-doc + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* This header is not installed, it just contains stuff for gtk-doc to parse, + * in particular docs and some dummy function declarations for the static + * inline functions we generate via macros in gstbitreader.h. + */ + +#error "This header should never be included in code, it is only for gtk-doc" + +/** + * gst_bit_reader_skip_unchecked: + * @reader: a #GstBitReader instance + * @nbits: the number of bits to skip + * + * Skips @nbits bits of the #GstBitReader instance without checking if there + * are enough bits available in the bit reader. + */ +void gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits); + +/** + * gst_bit_reader_skip_to_byte_unchecked: + * @reader: a #GstBitReader instance + * + * Skips until the next byte without checking if there are enough bits + * available in the bit reader. + */ +void gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader); + +/** + * gst_bit_reader_get_bits_uint8_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position without + * checking if there are enough bits available in the bit reader. + * + * Returns: unsigned 8 bit integer with the bits. + */ +guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_peek_bits_uint8_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position without + * checking if there are enough bits available in the bit reader + * + * Returns: unsigned 8 bit integer with the bits. + */ +guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_get_bits_uint16_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position without + * checking if there are enough bits available in the bit reader. + * + * Returns: unsigned 16 bit integer with the bits. + */ +guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_peek_bits_uint16_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position without + * checking if there are enough bits available in the bit reader + * + * Returns: unsigned 16 bit integer with the bits. + */ +guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_get_bits_uint32_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position without + * checking if there are enough bits available in the bit reader. + * + * Returns: unsigned 32 bit integer with the bits. + */ +guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_peek_bits_uint32_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position without + * checking if there are enough bits available in the bit reader + * + * Returns: unsigned 32 bit integer with the bits. + */ +guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_get_bits_uint64_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position without + * checking if there are enough bits available in the bit reader. + * + * Returns: unsigned 64 bit integer with the bits. + */ +guint64 gst_bit_reader_get_bits_uint64_unchecked (GstBitReader *reader, guint nbits); + +/** + * gst_bit_reader_peek_bits_uint64_unchecked: + * @reader: a #GstBitReader instance + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position without + * checking if there are enough bits available in the bit reader + * + * Returns: unsigned 64 bit integer with the bits. + */ +guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, guint nbits); + diff --git a/libs/gst/base/gstbitreader.c b/libs/gst/base/gstbitreader.c new file mode 100644 index 0000000..9df36d1 --- /dev/null +++ b/libs/gst/base/gstbitreader.c @@ -0,0 +1,296 @@ +/* GStreamer + * + * Copyright (C) 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GST_BIT_READER_DISABLE_INLINES +#include "gstbitreader.h" + +#include + +/** + * SECTION:gstbitreader + * @title: GstBitReader + * @short_description: Reads any number of bits from a memory buffer + * + * #GstBitReader provides a bit reader that can read any number of bits + * from a memory buffer. It provides functions for reading any number of bits + * into 8, 16, 32 and 64 bit variables. + */ + +/** + * gst_bit_reader_new: (skip) + * @data: (array length=size): Data from which the #GstBitReader + * should read + * @size: Size of @data in bytes + * + * Create a new #GstBitReader instance, which will read from @data. + * + * Free-function: gst_bit_reader_free + * + * Returns: (transfer full): a new #GstBitReader instance + */ +GstBitReader * +gst_bit_reader_new (const guint8 * data, guint size) +{ + GstBitReader *ret = g_slice_new0 (GstBitReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +/** + * gst_bit_reader_free: + * @reader: (in) (transfer full): a #GstBitReader instance + * + * Frees a #GstBitReader instance, which was previously allocated by + * gst_bit_reader_new(). + */ +void +gst_bit_reader_free (GstBitReader * reader) +{ + g_return_if_fail (reader != NULL); + + g_slice_free (GstBitReader, reader); +} + +/** + * gst_bit_reader_init: + * @reader: a #GstBitReader instance + * @data: (in) (array length=size): data from which the bit reader should read + * @size: Size of @data in bytes + * + * Initializes a #GstBitReader instance to read from @data. This function + * can be called on already initialized instances. + */ +void +gst_bit_reader_init (GstBitReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = reader->bit = 0; +} + +/** + * gst_bit_reader_set_pos: + * @reader: a #GstBitReader instance + * @pos: The new position in bits + * + * Sets the new position of a #GstBitReader instance to @pos in bits. + * + * Returns: %TRUE if the position could be set successfully, %FALSE + * otherwise. + */ +gboolean +gst_bit_reader_set_pos (GstBitReader * reader, guint pos) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (pos > reader->size * 8) + return FALSE; + + reader->byte = pos / 8; + reader->bit = pos % 8; + + return TRUE; +} + +/** + * gst_bit_reader_get_pos: + * @reader: a #GstBitReader instance + * + * Returns the current position of a #GstBitReader instance in bits. + * + * Returns: The current position of @reader in bits. + */ +guint +gst_bit_reader_get_pos (const GstBitReader * reader) +{ + return _gst_bit_reader_get_pos_inline (reader); +} + +/** + * gst_bit_reader_get_remaining: + * @reader: a #GstBitReader instance + * + * Returns the remaining number of bits of a #GstBitReader instance. + * + * Returns: The remaining number of bits of @reader instance. + */ +guint +gst_bit_reader_get_remaining (const GstBitReader * reader) +{ + return _gst_bit_reader_get_remaining_inline (reader); +} + +/** + * gst_bit_reader_get_size: + * @reader: a #GstBitReader instance + * + * Returns the total number of bits of a #GstBitReader instance. + * + * Returns: The total number of bits of @reader instance. + */ +guint +gst_bit_reader_get_size (const GstBitReader * reader) +{ + return _gst_bit_reader_get_size_inline (reader); +} + +/** + * gst_bit_reader_skip: + * @reader: a #GstBitReader instance + * @nbits: the number of bits to skip + * + * Skips @nbits bits of the #GstBitReader instance. + * + * Returns: %TRUE if @nbits bits could be skipped, %FALSE otherwise. + */ +gboolean +gst_bit_reader_skip (GstBitReader * reader, guint nbits) +{ + return _gst_bit_reader_skip_inline (reader, nbits); +} + +/** + * gst_bit_reader_skip_to_byte: + * @reader: a #GstBitReader instance + * + * Skips until the next byte. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_bit_reader_skip_to_byte (GstBitReader * reader) +{ + return _gst_bit_reader_skip_to_byte_inline (reader); +} + +/** + * gst_bit_reader_get_bits_uint8: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint8 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_get_bits_uint16: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint16 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_get_bits_uint32: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint32 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_get_bits_uint64: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint64 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_peek_bits_uint8: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint8 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_peek_bits_uint16: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint16 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_peek_bits_uint32: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint32 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_bit_reader_peek_bits_uint64: + * @reader: a #GstBitReader instance + * @val: (out): Pointer to a #guint64 to store the result + * @nbits: number of bits to read + * + * Read @nbits bits into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +#define GST_BIT_READER_READ_BITS(bits) \ +gboolean \ +gst_bit_reader_peek_bits_uint##bits (const GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + return _gst_bit_reader_peek_bits_uint##bits##_inline (reader, val, nbits); \ +} \ +\ +gboolean \ +gst_bit_reader_get_bits_uint##bits (GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + return _gst_bit_reader_get_bits_uint##bits##_inline (reader, val, nbits); \ +} + +GST_BIT_READER_READ_BITS (8); +GST_BIT_READER_READ_BITS (16); +GST_BIT_READER_READ_BITS (32); +GST_BIT_READER_READ_BITS (64); diff --git a/libs/gst/base/gstbitreader.h b/libs/gst/base/gstbitreader.h new file mode 100644 index 0000000..380edd3 --- /dev/null +++ b/libs/gst/base/gstbitreader.h @@ -0,0 +1,328 @@ +/* GStreamer + * + * Copyright (C) 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BIT_READER_H__ +#define __GST_BIT_READER_H__ + +#include +#include + +/* FIXME: inline functions */ + +G_BEGIN_DECLS + +#define GST_BIT_READER(reader) ((GstBitReader *) (reader)) + +/** + * GstBitReader: + * @data: (array length=size): Data from which the bit reader will + * read + * @size: Size of @data in bytes + * @byte: Current byte position + * @bit: Bit position in the current byte + * + * A bit reader instance. + */ +typedef struct { + const guint8 *data; + guint size; + + guint byte; /* Byte position */ + guint bit; /* Bit position in the current byte */ + + /* < private > */ + gpointer _gst_reserved[GST_PADDING]; +} GstBitReader; + +GST_BASE_API +GstBitReader * gst_bit_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC; + +GST_BASE_API +void gst_bit_reader_free (GstBitReader *reader); + +GST_BASE_API +void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size); + +GST_BASE_API +gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos); + +GST_BASE_API +guint gst_bit_reader_get_pos (const GstBitReader *reader); + +GST_BASE_API +guint gst_bit_reader_get_remaining (const GstBitReader *reader); + +GST_BASE_API +guint gst_bit_reader_get_size (const GstBitReader *reader); + +GST_BASE_API +gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader); + +GST_BASE_API +gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits); + +GST_BASE_API +gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits); + +/** + * GST_BIT_READER_INIT: + * @data: Data from which the #GstBitReader should read + * @size: Size of @data in bytes + * + * A #GstBitReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_bit_reader_init(). + */ +#define GST_BIT_READER_INIT(data, size) {data, size, 0, 0} + +/* Unchecked variants */ + +static inline void +gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits) +{ + reader->bit += nbits; + reader->byte += reader->bit / 8; + reader->bit = reader->bit % 8; +} + +static inline void +gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader) +{ + if (reader->bit) { + reader->bit = 0; + reader->byte++; + } +} + +#define __GST_BIT_READER_READ_BITS_UNCHECKED(bits) \ +static inline guint##bits \ +gst_bit_reader_peek_bits_uint##bits##_unchecked (const GstBitReader *reader, guint nbits) \ +{ \ + guint##bits ret = 0; \ + const guint8 *data; \ + guint byte, bit; \ + \ + data = reader->data; \ + byte = reader->byte; \ + bit = reader->bit; \ + \ + while (nbits > 0) { \ + guint toread = MIN (nbits, 8 - bit); \ + \ + ret <<= toread; \ + ret |= (data[byte] & (0xff >> bit)) >> (8 - toread - bit); \ + \ + bit += toread; \ + if (bit >= 8) { \ + byte++; \ + bit = 0; \ + } \ + nbits -= toread; \ + } \ + \ + return ret; \ +} \ +\ +static inline guint##bits \ +gst_bit_reader_get_bits_uint##bits##_unchecked (GstBitReader *reader, guint nbits) \ +{ \ + guint##bits ret; \ + \ + ret = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \ + \ + gst_bit_reader_skip_unchecked (reader, nbits); \ + \ + return ret; \ +} + +__GST_BIT_READER_READ_BITS_UNCHECKED (8) +__GST_BIT_READER_READ_BITS_UNCHECKED (16) +__GST_BIT_READER_READ_BITS_UNCHECKED (32) +__GST_BIT_READER_READ_BITS_UNCHECKED (64) + +#undef __GST_BIT_READER_READ_BITS_UNCHECKED + +/* unchecked variants -- do not use */ + +static inline guint +_gst_bit_reader_get_size_unchecked (const GstBitReader * reader) +{ + return reader->size * 8; +} + +static inline guint +_gst_bit_reader_get_pos_unchecked (const GstBitReader * reader) +{ + return reader->byte * 8 + reader->bit; +} + +static inline guint +_gst_bit_reader_get_remaining_unchecked (const GstBitReader * reader) +{ + return reader->size * 8 - (reader->byte * 8 + reader->bit); +} + +/* inlined variants -- do not use directly */ +static inline guint +_gst_bit_reader_get_size_inline (const GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_bit_reader_get_size_unchecked (reader); +} + +static inline guint +_gst_bit_reader_get_pos_inline (const GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_bit_reader_get_pos_unchecked (reader); +} + +static inline guint +_gst_bit_reader_get_remaining_inline (const GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_bit_reader_get_remaining_unchecked (reader); +} + +static inline gboolean +_gst_bit_reader_skip_inline (GstBitReader * reader, guint nbits) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) + return FALSE; + + gst_bit_reader_skip_unchecked (reader, nbits); + + return TRUE; +} + +static inline gboolean +_gst_bit_reader_skip_to_byte_inline (GstBitReader * reader) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (reader->byte > reader->size) + return FALSE; + + gst_bit_reader_skip_to_byte_unchecked (reader); + + return TRUE; +} + +#define __GST_BIT_READER_READ_BITS_INLINE(bits) \ +static inline gboolean \ +_gst_bit_reader_get_bits_uint##bits##_inline (GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + g_return_val_if_fail (nbits <= bits, FALSE); \ + \ + if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \ + return FALSE; \ +\ + *val = gst_bit_reader_get_bits_uint##bits##_unchecked (reader, nbits); \ + return TRUE; \ +} \ +\ +static inline gboolean \ +_gst_bit_reader_peek_bits_uint##bits##_inline (const GstBitReader *reader, guint##bits *val, guint nbits) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + g_return_val_if_fail (nbits <= bits, FALSE); \ + \ + if (_gst_bit_reader_get_remaining_unchecked (reader) < nbits) \ + return FALSE; \ +\ + *val = gst_bit_reader_peek_bits_uint##bits##_unchecked (reader, nbits); \ + return TRUE; \ +} + +__GST_BIT_READER_READ_BITS_INLINE (8) +__GST_BIT_READER_READ_BITS_INLINE (16) +__GST_BIT_READER_READ_BITS_INLINE (32) +__GST_BIT_READER_READ_BITS_INLINE (64) + +#undef __GST_BIT_READER_READ_BITS_INLINE + +#ifndef GST_BIT_READER_DISABLE_INLINES + +#define gst_bit_reader_get_size(reader) \ + _gst_bit_reader_get_size_inline (reader) +#define gst_bit_reader_get_pos(reader) \ + _gst_bit_reader_get_pos_inline (reader) +#define gst_bit_reader_get_remaining(reader) \ + _gst_bit_reader_get_remaining_inline (reader) + +/* we use defines here so we can add the G_LIKELY() */ + +#define gst_bit_reader_skip(reader, nbits)\ + G_LIKELY (_gst_bit_reader_skip_inline(reader, nbits)) +#define gst_bit_reader_skip_to_byte(reader)\ + G_LIKELY (_gst_bit_reader_skip_to_byte_inline(reader)) + +#define gst_bit_reader_get_bits_uint8(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_get_bits_uint8_inline (reader, val, nbits)) +#define gst_bit_reader_get_bits_uint16(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_get_bits_uint16_inline (reader, val, nbits)) +#define gst_bit_reader_get_bits_uint32(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_get_bits_uint32_inline (reader, val, nbits)) +#define gst_bit_reader_get_bits_uint64(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_get_bits_uint64_inline (reader, val, nbits)) + +#define gst_bit_reader_peek_bits_uint8(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_peek_bits_uint8_inline (reader, val, nbits)) +#define gst_bit_reader_peek_bits_uint16(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_peek_bits_uint16_inline (reader, val, nbits)) +#define gst_bit_reader_peek_bits_uint32(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_peek_bits_uint32_inline (reader, val, nbits)) +#define gst_bit_reader_peek_bits_uint64(reader, val, nbits) \ + G_LIKELY (_gst_bit_reader_peek_bits_uint64_inline (reader, val, nbits)) +#endif + +G_END_DECLS + +#endif /* __GST_BIT_READER_H__ */ diff --git a/libs/gst/base/gstbytereader-docs.h b/libs/gst/base/gstbytereader-docs.h new file mode 100644 index 0000000..b582c3f --- /dev/null +++ b/libs/gst/base/gstbytereader-docs.h @@ -0,0 +1,552 @@ +/* GStreamer byte reader dummy header for gtk-doc + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* This header is not installed, it just contains stuff for gtk-doc to parse, + * in particular docs and some dummy function declarations for the static + * inline functions we generate via macros in gstbytereader.h. + */ + +#error "This header should never be included in code, it is only for gtk-doc" + +/** + * gst_byte_reader_skip_unchecked: + * @reader: a #GstByteReader instance + * @nbytes: the number of bytes to skip + * + * Skips @nbytes bytes of the #GstByteReader instance without checking if + * there are enough bytes available in the byte reader. + */ +void gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes); + +/** + * gst_byte_reader_get_uint8_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 8 bit integer without checking if there are enough bytes + * available in the byte reader and update the current position. + * + * Returns: unsigned 8 bit integer. + */ +/** + * gst_byte_reader_peek_uint8_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 8 bit integer without checking if there are enough bytes + * available in the byte reader, but do not advance the current read position. + * + * Returns: unsigned 8 bit integer. + */ +/** + * gst_byte_reader_get_int8_unchecked: + * @reader: a #GstByteReader instance + * + * Read an signed 8 bit integer without checking if there are enough bytes + * available in the byte reader and update the current position. + * + * Returns: signed 8 bit integer. + */ +/** + * gst_byte_reader_peek_int8_unchecked: + * @reader: a #GstByteReader instance + * + * Read an signed 8 bit integer without checking if there are enough bytes + * available in the byte reader, but do not advance the current read position. + * + * Returns: signed 8 bit integer. + */ +guint8 gst_byte_reader_get_uint8_unchecked (GstByteReader * reader); +guint8 gst_byte_reader_peek_uint8_unchecked (GstByteReader * reader); +gint8 gst_byte_reader_get_int8_unchecked (GstByteReader * reader); +gint8 gst_byte_reader_peek_int8_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_get_uint16_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 16 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 16 bit integer. + */ +/** + * gst_byte_reader_peek_uint16_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 16 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 16 bit integer. + */ +/** + * gst_byte_reader_get_uint16_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 16 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 16 bit integer. + */ +/** + * gst_byte_reader_peek_uint16_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 16 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 16 bit integer. + */ +/** + * gst_byte_reader_get_int16_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 16 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 16 bit integer. + */ +/** + * gst_byte_reader_peek_int16_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 16 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 16 bit integer. + */ +/** + * gst_byte_reader_get_int16_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 16 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 16 bit integer. + */ +/** + * gst_byte_reader_peek_int16_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 16 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 16 bit integer. + */ +guint16 gst_byte_reader_get_uint16_le_unchecked (GstByteReader * reader); +guint16 gst_byte_reader_get_uint16_be_unchecked (GstByteReader * reader); +guint16 gst_byte_reader_peek_uint16_le_unchecked (GstByteReader * reader); +guint16 gst_byte_reader_peek_uint16_be_unchecked (GstByteReader * reader); +gint16 gst_byte_reader_get_int16_le_unchecked (GstByteReader * reader); +gint16 gst_byte_reader_get_int16_be_unchecked (GstByteReader * reader); +gint16 gst_byte_reader_peek_int16_le_unchecked (GstByteReader * reader); +gint16 gst_byte_reader_peek_int16_be_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_get_uint24_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 24 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 24 bit integer (as guint32) + */ +/** + * gst_byte_reader_peek_uint24_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 24 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 24 bit integer (as guint32) + */ +/** + * gst_byte_reader_get_uint24_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 24 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 24 bit integer (as guint32) + */ +/** + * gst_byte_reader_peek_uint24_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 24 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 24 bit integer (as guint32) + */ +/** + * gst_byte_reader_get_int24_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 24 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 24 bit integer (as gint32) + */ +/** + * gst_byte_reader_peek_int24_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 24 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 24 bit integer (as gint32) + */ +/** + * gst_byte_reader_get_int24_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 24 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 24 bit integer (as gint32) + */ +/** + * gst_byte_reader_peek_int24_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 24 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 24 bit integer (as gint32) + */ +guint32 gst_byte_reader_get_uint24_le_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_get_uint24_be_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_peek_uint24_le_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_peek_uint24_be_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_get_int24_le_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_get_int24_be_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_peek_int24_le_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_peek_int24_be_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_get_uint32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 32 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 32 bit integer. + */ +/** + * gst_byte_reader_peek_uint32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 32 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 32 bit integer. + */ +/** + * gst_byte_reader_get_uint32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 32 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 32 bit integer. + */ +/** + * gst_byte_reader_peek_uint32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 32 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 32 bit integer. + */ +/** + * gst_byte_reader_get_int32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 32 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 32 bit integer. + */ +/** + * gst_byte_reader_peek_int32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 32 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 32 bit integer. + */ +/** + * gst_byte_reader_get_int32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 32 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 32 bit integer. + */ +/** + * gst_byte_reader_peek_int32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 32 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 32 bit integer. + */ +guint32 gst_byte_reader_get_uint32_le_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_get_uint32_be_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_peek_uint32_le_unchecked (GstByteReader * reader); +guint32 gst_byte_reader_peek_uint32_be_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_get_int32_le_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_get_int32_be_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_peek_int32_le_unchecked (GstByteReader * reader); +gint32 gst_byte_reader_peek_int32_be_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_get_uint64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 64 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 64 bit integer. + */ +/** + * gst_byte_reader_peek_uint64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 64 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 64 bit integer. + */ +/** + * gst_byte_reader_get_uint64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 64 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: unsigned 64 bit integer. + */ +/** + * gst_byte_reader_peek_uint64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read an unsigned 64 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: unsigned 64 bit integer. + */ +/** + * gst_byte_reader_get_int64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 64 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 64 bit integer. + */ +/** + * gst_byte_reader_peek_int64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 64 bit integer in little endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 64 bit integer. + */ +/** + * gst_byte_reader_get_int64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 64 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader and update the + * current position. + * + * Returns: signed 64 bit integer. + */ +/** + * gst_byte_reader_peek_int64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a signed 64 bit integer in big endian format without checking + * if there are enough bytes available in the byte reader, but do not advance + * the current position. + * + * Returns: signed 64 bit integer. + */ +guint64 gst_byte_reader_get_uint64_le_unchecked (GstByteReader * reader); +guint64 gst_byte_reader_get_uint64_be_unchecked (GstByteReader * reader); +guint64 gst_byte_reader_peek_uint64_le_unchecked (GstByteReader * reader); +guint64 gst_byte_reader_peek_uint64_be_unchecked (GstByteReader * reader); +gint64 gst_byte_reader_get_int64_le_unchecked (GstByteReader * reader); +gint64 gst_byte_reader_get_int64_be_unchecked (GstByteReader * reader); +gint64 gst_byte_reader_peek_int64_le_unchecked (GstByteReader * reader); +gint64 gst_byte_reader_peek_int64_be_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_get_float32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 32 bit little endian float without checking if there is enough + * data available and update the current position. + * + * Returns: floating point value read + */ +/** + * gst_byte_reader_peek_float32_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 32 bit little endian float without checking if there is enough + * data available, but keep the current position. + * + * Returns: floating point value read + */ +/** + * gst_byte_reader_get_float32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 32 bit big endian float without checking if there is enough + * data available and update the current position. + * + * Returns: floating point value read + */ +/** + * gst_byte_reader_peek_float32_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 32 bit big endian float without checking if there is enough + * data available, but keep the current position. + * + * Returns: floating point value read + */ +/** + * gst_byte_reader_get_float64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 64 bit little endian float without checking if there is enough + * data available and update the current position. + * + * Returns: double precision floating point value read + */ +/** + * gst_byte_reader_peek_float64_le_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 64 bit little endian float without checking if there is enough + * data available, but keep the current position. + * + * Returns: double precision floating point value read + */ +/** + * gst_byte_reader_get_float64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 64 bit big endian float without checking if there is enough + * data available and update the current position. + * + * Returns: double precision floating point value read + */ +/** + * gst_byte_reader_peek_float64_be_unchecked: + * @reader: a #GstByteReader instance + * + * Read a 64 bit big endian float without checking if there is enough + * data available, but keep the current position. + * + * Returns: double precision floating point value read + */ + +gfloat gst_byte_reader_get_float32_le_unchecked (GstByteReader * reader); +gfloat gst_byte_reader_get_float32_be_unchecked (GstByteReader * reader); +gdouble gst_byte_reader_get_float64_le_unchecked (GstByteReader * reader); +gdouble gst_byte_reader_get_float64_be_unchecked (GstByteReader * reader); + +gfloat gst_byte_reader_peek_float32_le_unchecked (GstByteReader * reader); +gfloat gst_byte_reader_peek_float32_be_unchecked (GstByteReader * reader); +gdouble gst_byte_reader_peek_float64_le_unchecked (GstByteReader * reader); +gdouble gst_byte_reader_peek_float64_be_unchecked (GstByteReader * reader); + +/** + * gst_byte_reader_peek_data_unchecked: + * @reader: a #GstByteReader instance + * + * Returns: (transfer none): a constant pointer to the current data position + */ +const guint8 * gst_byte_reader_peek_data_unchecked (const GstByteReader * reader); +/** + * gst_byte_reader_get_data_unchecked: + * @reader: a #GstByteReader instance + * @size: Size in bytes + * + * Returns a constant pointer to the current data position without checking + * if at least @size bytes are left. Advances the current read position by + * @size bytes. + * + * Returns: (transfer none) (array length=size): a constant pointer to the + * current data position. + */ +const guint8 * gst_byte_reader_get_data_unchecked (GstByteReader * reader, guint size); +/** + * gst_byte_reader_dup_data_unchecked: + * @reader: a #GstByteReader instance + * @size: Size in bytes + * + * Returns a newly-allocated copy of the data at the current data position + * without checking if at least @size bytes are left. Advances the current read + * position by @size bytes. + * + * Free-function: g_free + * + * Returns: (transfer full) (array length=size): a newly-allocated copy of the + * data @size bytes in size. Free with g_free() when no longer needed. + */ +guint8 * gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size); + diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c new file mode 100644 index 0000000..72f720a --- /dev/null +++ b/libs/gst/base/gstbytereader.c @@ -0,0 +1,1259 @@ +/* GStreamer byte reader + * + * Copyright (C) 2008 Sebastian Dröge . + * Copyright (C) 2009,2014 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GST_BYTE_READER_DISABLE_INLINES +#include "gstbytereader.h" + +#include + +/** + * SECTION:gstbytereader + * @title: GstByteReader + * @short_description: Reads different integer, string and floating point + * types from a memory buffer + * + * #GstByteReader provides a byte reader that can read different integer and + * floating point types from a memory buffer. It provides functions for reading + * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits + * and functions for reading little/big endian floating points numbers of + * 32 and 64 bits. It also provides functions to read NUL-terminated strings + * in various character encodings. + */ + +/** + * gst_byte_reader_new: (skip) + * @data: (in) (transfer none) (array length=size): data from which the + * #GstByteReader should read + * @size: Size of @data in bytes + * + * Create a new #GstByteReader instance, which will read from @data. + * + * Free-function: gst_byte_reader_free + * + * Returns: (transfer full): a new #GstByteReader instance + */ +GstByteReader * +gst_byte_reader_new (const guint8 * data, guint size) +{ + GstByteReader *ret = g_slice_new0 (GstByteReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +/** + * gst_byte_reader_free: + * @reader: (in) (transfer full): a #GstByteReader instance + * + * Frees a #GstByteReader instance, which was previously allocated by + * gst_byte_reader_new(). + */ +void +gst_byte_reader_free (GstByteReader * reader) +{ + g_return_if_fail (reader != NULL); + + g_slice_free (GstByteReader, reader); +} + +/** + * gst_byte_reader_init: + * @reader: a #GstByteReader instance + * @data: (in) (transfer none) (array length=size): data from which + * the #GstByteReader should read + * @size: Size of @data in bytes + * + * Initializes a #GstByteReader instance to read from @data. This function + * can be called on already initialized instances. + */ +void +gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = 0; +} + +/** + * gst_byte_reader_peek_sub_reader: (skip) + * @reader: an existing and initialized #GstByteReader instance + * @sub_reader: a #GstByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #GstByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the + * current position of @reader. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +gst_byte_reader_peek_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size); +} + +/** + * gst_byte_reader_get_sub_reader: (skip) + * @reader: an existing and initialized #GstByteReader instance + * @sub_reader: a #GstByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #GstByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the + * position of @reader and moves it forward by @size bytes. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +gst_byte_reader_get_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size); +} + +/** + * gst_byte_reader_set_pos: + * @reader: a #GstByteReader instance + * @pos: The new position in bytes + * + * Sets the new position of a #GstByteReader instance to @pos in bytes. + * + * Returns: %TRUE if the position could be set successfully, %FALSE + * otherwise. + */ +gboolean +gst_byte_reader_set_pos (GstByteReader * reader, guint pos) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (pos > reader->size) + return FALSE; + + reader->byte = pos; + + return TRUE; +} + +/** + * gst_byte_reader_get_pos: + * @reader: a #GstByteReader instance + * + * Returns the current position of a #GstByteReader instance in bytes. + * + * Returns: The current position of @reader in bytes. + */ +guint +gst_byte_reader_get_pos (const GstByteReader * reader) +{ + return _gst_byte_reader_get_pos_inline (reader); +} + +/** + * gst_byte_reader_get_remaining: + * @reader: a #GstByteReader instance + * + * Returns the remaining number of bytes of a #GstByteReader instance. + * + * Returns: The remaining number of bytes of @reader instance. + */ +guint +gst_byte_reader_get_remaining (const GstByteReader * reader) +{ + return _gst_byte_reader_get_remaining_inline (reader); +} + +/** + * gst_byte_reader_get_size: + * @reader: a #GstByteReader instance + * + * Returns the total number of bytes of a #GstByteReader instance. + * + * Returns: The total number of bytes of @reader instance. + */ +guint +gst_byte_reader_get_size (const GstByteReader * reader) +{ + return _gst_byte_reader_get_size_inline (reader); +} + +#define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline +#define gst_byte_reader_get_size _gst_byte_reader_get_size_inline + +/** + * gst_byte_reader_skip: + * @reader: a #GstByteReader instance + * @nbytes: the number of bytes to skip + * + * Skips @nbytes bytes of the #GstByteReader instance. + * + * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise. + */ +gboolean +gst_byte_reader_skip (GstByteReader * reader, guint nbytes) +{ + return _gst_byte_reader_skip_inline (reader, nbytes); +} + +/** + * gst_byte_reader_get_uint8: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint8 to store the result + * + * Read an unsigned 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int8: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint8: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint8 to store the result + * + * Read an unsigned 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int8: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint16_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int16_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint16_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int16_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint16_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int16_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint16_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int16_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint24_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int24_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint24_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int24_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint24_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int24_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint24_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int24_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + + +/** + * gst_byte_reader_get_uint32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_uint64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_int64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_uint64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_int64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +#define GST_BYTE_READER_PEEK_GET(bits,type,name) \ +gboolean \ +gst_byte_reader_get_##name (GstByteReader * reader, type * val) \ +{ \ + return _gst_byte_reader_get_##name##_inline (reader, val); \ +} \ +\ +gboolean \ +gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \ +{ \ + return _gst_byte_reader_peek_##name##_inline (reader, val); \ +} + +/* *INDENT-OFF* */ + +GST_BYTE_READER_PEEK_GET(8,guint8,uint8) +GST_BYTE_READER_PEEK_GET(8,gint8,int8) + +GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le) +GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be) +GST_BYTE_READER_PEEK_GET(16,gint16,int16_le) +GST_BYTE_READER_PEEK_GET(16,gint16,int16_be) + +GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le) +GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be) +GST_BYTE_READER_PEEK_GET(24,gint32,int24_le) +GST_BYTE_READER_PEEK_GET(24,gint32,int24_be) + +GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le) +GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be) +GST_BYTE_READER_PEEK_GET(32,gint32,int32_le) +GST_BYTE_READER_PEEK_GET(32,gint32,int32_be) + +GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le) +GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be) +GST_BYTE_READER_PEEK_GET(64,gint64,int64_le) +GST_BYTE_READER_PEEK_GET(64,gint64,int64_be) + +/** + * gst_byte_reader_get_float32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_float32_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_float32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_float32_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_float64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_float64_le: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_get_float64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * gst_byte_reader_peek_float64_be: + * @reader: a #GstByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le) +GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be) +GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le) +GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be) + +/* *INDENT-ON* */ + +/** + * gst_byte_reader_get_data: + * @reader: a #GstByteReader instance + * @size: Size in bytes + * @val: (out) (transfer none) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Returns a constant pointer to the current data + * position if at least @size bytes are left and + * updates the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_byte_reader_get_data (GstByteReader * reader, guint size, + const guint8 ** val) +{ + return _gst_byte_reader_get_data_inline (reader, size, val); +} + +/** + * gst_byte_reader_peek_data: + * @reader: a #GstByteReader instance + * @size: Size in bytes + * @val: (out) (transfer none) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Returns a constant pointer to the current data + * position if at least @size bytes are left and + * keeps the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_byte_reader_peek_data (const GstByteReader * reader, guint size, + const guint8 ** val) +{ + return _gst_byte_reader_peek_data_inline (reader, size, val); +} + +/** + * gst_byte_reader_dup_data: + * @reader: a #GstByteReader instance + * @size: Size in bytes + * @val: (out) (transfer full) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data + * position if at least @size bytes are left and + * updates the current position. Free with g_free() when no longer needed. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val) +{ + return _gst_byte_reader_dup_data_inline (reader, size, val); +} + +/* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */ +static inline gint +_scan_for_start_code (const guint8 * data, guint size) +{ + guint8 *pdata = (guint8 *) data; + guint8 *pend = (guint8 *) (data + size - 4); + + while (pdata <= pend) { + if (pdata[2] > 1) { + pdata += 3; + } else if (pdata[1]) { + pdata += 2; + } else if (pdata[0] || pdata[2] != 1) { + pdata++; + } else { + return (pdata - data); + } + } + + /* nothing found */ + return -1; +} + +static inline guint +_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + const guint8 *data; + guint32 state; + guint i; + + g_return_val_if_fail (size > 0, -1); + g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte, + -1); + + /* we can't find the pattern with less than 4 bytes */ + if (G_UNLIKELY (size < 4)) + return -1; + + data = reader->data + reader->byte + offset; + + /* Handle special case found in MPEG and H264 */ + if ((pattern == 0x00000100) && (mask == 0xffffff00)) { + gint ret = _scan_for_start_code (data, size); + + if (ret == -1) + return ret; + + if (value != NULL) + *value = (1 << 8) | data[ret + 3]; + + return ret + offset; + } + + /* set the state to something that does not match */ + state = ~pattern; + + /* now find data */ + for (i = 0; i < size; i++) { + /* throw away one byte and move in the next byte */ + state = ((state << 8) | data[i]); + if (G_UNLIKELY ((state & mask) == pattern)) { + /* we have a match but we need to have skipped at + * least 4 bytes to fill the state. */ + if (G_LIKELY (i >= 3)) { + if (value) + *value = state; + return offset + i - 3; + } + } + } + + /* nothing found */ + return -1; +} + + +/** + * gst_byte_reader_masked_scan_uint32: + * @reader: a #GstByteReader + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset from which to start scanning, relative to the current + * position + * @size: number of bytes to scan from offset + * + * Scan for pattern @pattern with applied mask @mask in the byte reader data, + * starting from offset @offset relative to the current position. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * byte reader data for it to match, even if the first or last bytes are masked + * out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the byte reader. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Example: + * |[ + * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff + * + * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256); + * // -> returns 0 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255); + * // -> returns -1 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255); + * // -> returns 1 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256); + * // -> returns -1 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256); + * // -> returns 0 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256); + * // -> returns 2 + * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4); + * // -> returns -1 + * ]| + */ +guint +gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask, + guint32 pattern, guint offset, guint size) +{ + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL); +} + +/** + * gst_byte_reader_masked_scan_uint32_peek: + * @reader: a #GstByteReader + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset from which to start scanning, relative to the current + * position + * @size: number of bytes to scan from offset + * @value: (out): pointer to uint32 to return matching data + * + * Scan for pattern @pattern with applied mask @mask in the byte reader data, + * starting from offset @offset relative to the current position. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * byte reader data for it to match, even if the first or last bytes are masked + * out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the byte reader. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Since: 1.6 + */ +guint +gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value); +} + +#define GST_BYTE_READER_SCAN_STRING(bits) \ +static guint \ +gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \ +{ \ + guint len, off, max_len; \ + \ + max_len = (reader->size - reader->byte) / sizeof (guint##bits); \ + \ + /* need at least a single NUL terminator */ \ + if (max_len < 1) \ + return 0; \ + \ + len = 0; \ + off = reader->byte; \ + /* endianness does not matter if we are looking for a NUL terminator */ \ + while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \ + ++len; \ + off += sizeof (guint##bits); \ + /* have we reached the end without finding a NUL terminator? */ \ + if (len == max_len) \ + return 0; \ + } \ + /* return size in bytes including the NUL terminator (hence the +1) */ \ + return (len + 1) * sizeof (guint##bits); \ +} + +#define GST_READ_UINT8_LE GST_READ_UINT8 +GST_BYTE_READER_SCAN_STRING (8); +#undef GST_READ_UINT8_LE +GST_BYTE_READER_SCAN_STRING (16); +GST_BYTE_READER_SCAN_STRING (32); + +#define GST_BYTE_READER_SKIP_STRING(bits) \ +gboolean \ +gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \ +{ \ + guint size; /* size in bytes including the terminator */ \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + \ + size = gst_byte_reader_scan_string_utf##bits (reader); \ + reader->byte += size; \ + return (size > 0); \ +} + +/** + * gst_byte_reader_skip_string: + * @reader: a #GstByteReader instance + * + * Skips a NUL-terminated string in the #GstByteReader instance, advancing + * the current position to the byte after the string. This will work for + * any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +/** + * gst_byte_reader_skip_string_utf8: + * @reader: a #GstByteReader instance + * + * Skips a NUL-terminated string in the #GstByteReader instance, advancing + * the current position to the byte after the string. This will work for + * any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +GST_BYTE_READER_SKIP_STRING (8); + +/** + * gst_byte_reader_skip_string_utf16: + * @reader: a #GstByteReader instance + * + * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance, + * advancing the current position to the byte after the string. + * + * No input checking for valid UTF-16 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +GST_BYTE_READER_SKIP_STRING (16); + +/** + * gst_byte_reader_skip_string_utf32: + * @reader: a #GstByteReader instance + * + * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance, + * advancing the current position to the byte after the string. + * + * No input checking for valid UTF-32 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +GST_BYTE_READER_SKIP_STRING (32); + +/** + * gst_byte_reader_peek_string: + * @reader: a #GstByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator). + * The current position will be maintained. This will work for any + * NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +/** + * gst_byte_reader_peek_string_utf8: + * @reader: a #GstByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator). + * The current position will be maintained. This will work for any + * NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +gboolean +gst_byte_reader_peek_string_utf8 (const GstByteReader * reader, + const gchar ** str) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (gst_byte_reader_scan_string_utf8 (reader) > 0) { + *str = (const gchar *) (reader->data + reader->byte); + } else { + *str = NULL; + } + return (*str != NULL); +} + +/** + * gst_byte_reader_get_string_utf8: + * @reader: a #GstByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator), + * advancing the current position to the byte after the string. This will work + * for any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be found, %FALSE otherwise. + */ +gboolean +gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str) +{ + guint size; /* size in bytes including the terminator */ + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + size = gst_byte_reader_scan_string_utf8 (reader); + if (size == 0) { + *str = NULL; + return FALSE; + } + + *str = (const gchar *) (reader->data + reader->byte); + reader->byte += size; + return TRUE; +} + +#define GST_BYTE_READER_DUP_STRING(bits,type) \ +gboolean \ +gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \ +{ \ + guint size; /* size in bytes including the terminator */ \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (str != NULL, FALSE); \ + \ + size = gst_byte_reader_scan_string_utf##bits (reader); \ + if (size == 0) { \ + *str = NULL; \ + return FALSE; \ + } \ + *str = g_memdup (reader->data + reader->byte, size); \ + reader->byte += size; \ + return TRUE; \ +} + +/** + * gst_byte_reader_dup_string_utf8: + * @reader: a #GstByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Free-function: g_free + * + * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance, + * advancing the current position to the byte after the string. This will work + * for any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +GST_BYTE_READER_DUP_STRING (8, gchar); + +/** + * gst_byte_reader_dup_string_utf16: + * @reader: a #GstByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #guint16 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data position if there is + * a NUL-terminated UTF-16 string in the data (this could be an empty string + * as well), and advances the current position. + * + * No input checking for valid UTF-16 is done. This function is endianness + * agnostic - you should not assume the UTF-16 characters are in host + * endianness. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Note: there is no peek or get variant of this function to ensure correct + * byte alignment of the UTF-16 string. + * + * Returns: %TRUE if a string could be read, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +GST_BYTE_READER_DUP_STRING (16, guint16); + +/** + * gst_byte_reader_dup_string_utf32: + * @reader: a #GstByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #guint32 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data position if there is + * a NUL-terminated UTF-32 string in the data (this could be an empty string + * as well), and advances the current position. + * + * No input checking for valid UTF-32 is done. This function is endianness + * agnostic - you should not assume the UTF-32 characters are in host + * endianness. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Note: there is no peek or get variant of this function to ensure correct + * byte alignment of the UTF-32 string. + * + * Returns: %TRUE if a string could be read, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +GST_BYTE_READER_DUP_STRING (32, guint32); diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h new file mode 100644 index 0000000..b988739 --- /dev/null +++ b/libs/gst/base/gstbytereader.h @@ -0,0 +1,681 @@ +/* GStreamer byte reader + * + * Copyright (C) 2008 Sebastian Dröge . + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BYTE_READER_H__ +#define __GST_BYTE_READER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_BYTE_READER(reader) ((GstByteReader *) (reader)) + +/** + * GstByteReader: + * @data: (array length=size): Data from which the bit reader will + * read + * @size: Size of @data in bytes + * @byte: Current byte position + * + * A byte reader instance. + */ +typedef struct { + const guint8 *data; + guint size; + + guint byte; /* Byte position */ + + /* < private > */ + gpointer _gst_reserved[GST_PADDING]; +} GstByteReader; + +GST_BASE_API +GstByteReader * gst_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC; + +GST_BASE_API +void gst_byte_reader_free (GstByteReader *reader); + +GST_BASE_API +void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size); + +GST_BASE_API +gboolean gst_byte_reader_peek_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, + guint size); +GST_BASE_API +gboolean gst_byte_reader_get_sub_reader (GstByteReader * reader, + GstByteReader * sub_reader, + guint size); +GST_BASE_API +gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos); + +GST_BASE_API +guint gst_byte_reader_get_pos (const GstByteReader *reader); + +GST_BASE_API +guint gst_byte_reader_get_remaining (const GstByteReader *reader); + +GST_BASE_API +guint gst_byte_reader_get_size (const GstByteReader *reader); + +GST_BASE_API +gboolean gst_byte_reader_skip (GstByteReader *reader, guint nbytes); + +GST_BASE_API +gboolean gst_byte_reader_get_uint8 (GstByteReader *reader, guint8 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int8 (GstByteReader *reader, gint8 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint16_le (GstByteReader *reader, guint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int16_le (GstByteReader *reader, gint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint16_be (GstByteReader *reader, guint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int16_be (GstByteReader *reader, gint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint24_le (GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int24_le (GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint24_be (GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int24_be (GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint32_le (GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int32_le (GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint32_be (GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int32_be (GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint64_le (GstByteReader *reader, guint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int64_le (GstByteReader *reader, gint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_uint64_be (GstByteReader *reader, guint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_int64_be (GstByteReader *reader, gint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint8 (const GstByteReader *reader, guint8 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int8 (const GstByteReader *reader, gint8 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint16_le (const GstByteReader *reader, guint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int16_le (const GstByteReader *reader, gint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint16_be (const GstByteReader *reader, guint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int16_be (const GstByteReader *reader, gint16 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint24_le (const GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int24_le (const GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint24_be (const GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int24_be (const GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint32_le (const GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int32_le (const GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint32_be (const GstByteReader *reader, guint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int32_be (const GstByteReader *reader, gint32 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint64_le (const GstByteReader *reader, guint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int64_le (const GstByteReader *reader, gint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_uint64_be (const GstByteReader *reader, guint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_int64_be (const GstByteReader *reader, gint64 *val); + +GST_BASE_API +gboolean gst_byte_reader_get_float32_le (GstByteReader *reader, gfloat *val); + +GST_BASE_API +gboolean gst_byte_reader_get_float32_be (GstByteReader *reader, gfloat *val); + +GST_BASE_API +gboolean gst_byte_reader_get_float64_le (GstByteReader *reader, gdouble *val); + +GST_BASE_API +gboolean gst_byte_reader_get_float64_be (GstByteReader *reader, gdouble *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_float32_le (const GstByteReader *reader, gfloat *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_float32_be (const GstByteReader *reader, gfloat *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_float64_le (const GstByteReader *reader, gdouble *val); + +GST_BASE_API +gboolean gst_byte_reader_peek_float64_be (const GstByteReader *reader, gdouble *val); + +GST_BASE_API +gboolean gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val); + +GST_BASE_API +gboolean gst_byte_reader_get_data (GstByteReader * reader, guint size, const guint8 ** val); + +GST_BASE_API +gboolean gst_byte_reader_peek_data (const GstByteReader * reader, guint size, const guint8 ** val); + +#define gst_byte_reader_dup_string(reader,str) \ + gst_byte_reader_dup_string_utf8(reader,str) + +GST_BASE_API +gboolean gst_byte_reader_dup_string_utf8 (GstByteReader * reader, gchar ** str); + +GST_BASE_API +gboolean gst_byte_reader_dup_string_utf16 (GstByteReader * reader, guint16 ** str); + +GST_BASE_API +gboolean gst_byte_reader_dup_string_utf32 (GstByteReader * reader, guint32 ** str); + +#define gst_byte_reader_skip_string(reader) \ + gst_byte_reader_skip_string_utf8(reader) + +GST_BASE_API +gboolean gst_byte_reader_skip_string_utf8 (GstByteReader * reader); + +GST_BASE_API +gboolean gst_byte_reader_skip_string_utf16 (GstByteReader * reader); + +GST_BASE_API +gboolean gst_byte_reader_skip_string_utf32 (GstByteReader * reader); + +#define gst_byte_reader_get_string(reader,str) \ + gst_byte_reader_get_string_utf8(reader,str) + +#define gst_byte_reader_peek_string(reader,str) \ + gst_byte_reader_peek_string_utf8(reader,str) + +GST_BASE_API +gboolean gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str); + +GST_BASE_API +gboolean gst_byte_reader_peek_string_utf8 (const GstByteReader * reader, const gchar ** str); + +GST_BASE_API +guint gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, + guint32 mask, + guint32 pattern, + guint offset, + guint size); +GST_BASE_API +guint gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader, + guint32 mask, + guint32 pattern, + guint offset, + guint size, + guint32 * value); + +/** + * GST_BYTE_READER_INIT: + * @data: Data from which the #GstByteReader should read + * @size: Size of @data in bytes + * + * A #GstByteReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * gst_byte_reader_init(). + */ +#define GST_BYTE_READER_INIT(data, size) {data, size, 0} + +/* unchecked variants */ +static inline void +gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes) +{ + reader->byte += nbytes; +} + +#define __GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(bits,type,lower,upper,adj) \ +\ +static inline type \ +gst_byte_reader_peek_##lower##_unchecked (const GstByteReader * reader) \ +{ \ + type val = (type) GST_READ_##upper (reader->data + reader->byte); \ + adj \ + return val; \ +} \ +\ +static inline type \ +gst_byte_reader_get_##lower##_unchecked (GstByteReader * reader) \ +{ \ + type val = gst_byte_reader_peek_##lower##_unchecked (reader); \ + reader->byte += bits / 8; \ + return val; \ +} + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,guint8,uint8,UINT8,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,gint8,int8,UINT8,/* */) + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_le,UINT16_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_be,UINT16_BE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_le,UINT16_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_be,UINT16_BE,/* */) + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_le,UINT32_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_be,UINT32_BE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_le,UINT32_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_be,UINT32_BE,/* */) + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_le,UINT24_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_be,UINT24_BE,/* */) + +/* fix up the sign for 24-bit signed ints stored in 32-bit signed ints */ +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_le,UINT24_LE, + if (val & 0x00800000) val |= 0xff000000;) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_be,UINT24_BE, + if (val & 0x00800000) val |= 0xff000000;) + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_le,UINT64_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_be,UINT64_BE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_le,UINT64_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_be,UINT64_BE,/* */) + +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_le,FLOAT_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_be,FLOAT_BE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_le,DOUBLE_LE,/* */) +__GST_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_be,DOUBLE_BE,/* */) + +#undef __GET_PEEK_BITS_UNCHECKED + +static inline const guint8 * +gst_byte_reader_peek_data_unchecked (const GstByteReader * reader) +{ + return (const guint8 *) (reader->data + reader->byte); +} + +static inline const guint8 * +gst_byte_reader_get_data_unchecked (GstByteReader * reader, guint size) +{ + const guint8 *data; + + data = gst_byte_reader_peek_data_unchecked (reader); + gst_byte_reader_skip_unchecked (reader, size); + return data; +} + +static inline guint8 * +gst_byte_reader_dup_data_unchecked (GstByteReader * reader, guint size) +{ + gconstpointer data = gst_byte_reader_get_data_unchecked (reader, size); + return (guint8 *) g_memdup (data, size); +} + +/* Unchecked variants that should not be used */ +static inline guint +_gst_byte_reader_get_pos_unchecked (const GstByteReader * reader) +{ + return reader->byte; +} + +static inline guint +_gst_byte_reader_get_remaining_unchecked (const GstByteReader * reader) +{ + return reader->size - reader->byte; +} + +static inline guint +_gst_byte_reader_get_size_unchecked (const GstByteReader * reader) +{ + return reader->size; +} + +/* inlined variants (do not use directly) */ + +static inline guint +_gst_byte_reader_get_remaining_inline (const GstByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_byte_reader_get_remaining_unchecked (reader); +} + +static inline guint +_gst_byte_reader_get_size_inline (const GstByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_byte_reader_get_size_unchecked (reader); +} + +#define __GST_BYTE_READER_GET_PEEK_BITS_INLINE(bits,type,name) \ +\ +static inline gboolean \ +_gst_byte_reader_peek_##name##_inline (const GstByteReader * reader, type * val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (_gst_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \ + return FALSE; \ +\ + *val = gst_byte_reader_peek_##name##_unchecked (reader); \ + return TRUE; \ +} \ +\ +static inline gboolean \ +_gst_byte_reader_get_##name##_inline (GstByteReader * reader, type * val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (_gst_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \ + return FALSE; \ +\ + *val = gst_byte_reader_get_##name##_unchecked (reader); \ + return TRUE; \ +} + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(8,guint8,uint8) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(8,gint8,int8) + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_be) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_be) + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_be) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_be) + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_be) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_be) + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_be) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_be) + +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_be) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_le) +__GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_be) + +#undef __GST_BYTE_READER_GET_PEEK_BITS_INLINE + +#ifndef GST_BYTE_READER_DISABLE_INLINES + +#define gst_byte_reader_init(reader,data,size) \ + _gst_byte_reader_init_inline(reader,data,size) + +#define gst_byte_reader_get_remaining(reader) \ + _gst_byte_reader_get_remaining_inline(reader) + +#define gst_byte_reader_get_size(reader) \ + _gst_byte_reader_get_size_inline(reader) + +#define gst_byte_reader_get_pos(reader) \ + _gst_byte_reader_get_pos_inline(reader) + +/* we use defines here so we can add the G_LIKELY() */ +#define gst_byte_reader_get_uint8(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint8_inline(reader,val)) +#define gst_byte_reader_get_int8(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int8_inline(reader,val)) +#define gst_byte_reader_get_uint16_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint16_le_inline(reader,val)) +#define gst_byte_reader_get_int16_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int16_le_inline(reader,val)) +#define gst_byte_reader_get_uint16_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint16_be_inline(reader,val)) +#define gst_byte_reader_get_int16_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int16_be_inline(reader,val)) +#define gst_byte_reader_get_uint24_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint24_le_inline(reader,val)) +#define gst_byte_reader_get_int24_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int24_le_inline(reader,val)) +#define gst_byte_reader_get_uint24_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint24_be_inline(reader,val)) +#define gst_byte_reader_get_int24_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int24_be_inline(reader,val)) +#define gst_byte_reader_get_uint32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint32_le_inline(reader,val)) +#define gst_byte_reader_get_int32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int32_le_inline(reader,val)) +#define gst_byte_reader_get_uint32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint32_be_inline(reader,val)) +#define gst_byte_reader_get_int32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int32_be_inline(reader,val)) +#define gst_byte_reader_get_uint64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint64_le_inline(reader,val)) +#define gst_byte_reader_get_int64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int64_le_inline(reader,val)) +#define gst_byte_reader_get_uint64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_uint64_be_inline(reader,val)) +#define gst_byte_reader_get_int64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_int64_be_inline(reader,val)) + +#define gst_byte_reader_peek_uint8(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint8_inline(reader,val)) +#define gst_byte_reader_peek_int8(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int8_inline(reader,val)) +#define gst_byte_reader_peek_uint16_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint16_le_inline(reader,val)) +#define gst_byte_reader_peek_int16_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int16_le_inline(reader,val)) +#define gst_byte_reader_peek_uint16_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint16_be_inline(reader,val)) +#define gst_byte_reader_peek_int16_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int16_be_inline(reader,val)) +#define gst_byte_reader_peek_uint24_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint24_le_inline(reader,val)) +#define gst_byte_reader_peek_int24_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int24_le_inline(reader,val)) +#define gst_byte_reader_peek_uint24_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint24_be_inline(reader,val)) +#define gst_byte_reader_peek_int24_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int24_be_inline(reader,val)) +#define gst_byte_reader_peek_uint32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint32_le_inline(reader,val)) +#define gst_byte_reader_peek_int32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int32_le_inline(reader,val)) +#define gst_byte_reader_peek_uint32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint32_be_inline(reader,val)) +#define gst_byte_reader_peek_int32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int32_be_inline(reader,val)) +#define gst_byte_reader_peek_uint64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint64_le_inline(reader,val)) +#define gst_byte_reader_peek_int64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int64_le_inline(reader,val)) +#define gst_byte_reader_peek_uint64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_uint64_be_inline(reader,val)) +#define gst_byte_reader_peek_int64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_int64_be_inline(reader,val)) + +#define gst_byte_reader_get_float32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_float32_le_inline(reader,val)) +#define gst_byte_reader_get_float32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_float32_be_inline(reader,val)) +#define gst_byte_reader_get_float64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_get_float64_le_inline(reader,val)) +#define gst_byte_reader_get_float64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_get_float64_be_inline(reader,val)) +#define gst_byte_reader_peek_float32_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_float32_le_inline(reader,val)) +#define gst_byte_reader_peek_float32_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_float32_be_inline(reader,val)) +#define gst_byte_reader_peek_float64_le(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_float64_le_inline(reader,val)) +#define gst_byte_reader_peek_float64_be(reader,val) \ + G_LIKELY(_gst_byte_reader_peek_float64_be_inline(reader,val)) + +#endif /* GST_BYTE_READER_DISABLE_INLINES */ + +static inline void +_gst_byte_reader_init_inline (GstByteReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = 0; +} + +static inline gboolean +_gst_byte_reader_peek_sub_reader_inline (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (sub_reader != NULL, FALSE); + + if (_gst_byte_reader_get_remaining_unchecked (reader) < size) + return FALSE; + + sub_reader->data = reader->data + reader->byte; + sub_reader->byte = 0; + sub_reader->size = size; + return TRUE; +} + +static inline gboolean +_gst_byte_reader_get_sub_reader_inline (GstByteReader * reader, + GstByteReader * sub_reader, guint size) +{ + if (!_gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size)) + return FALSE; + gst_byte_reader_skip_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +_gst_byte_reader_dup_data_inline (GstByteReader * reader, guint size, guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = gst_byte_reader_dup_data_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +_gst_byte_reader_get_data_inline (GstByteReader * reader, guint size, const guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = gst_byte_reader_get_data_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +_gst_byte_reader_peek_data_inline (const GstByteReader * reader, guint size, const guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || _gst_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = gst_byte_reader_peek_data_unchecked (reader); + return TRUE; +} + +static inline guint +_gst_byte_reader_get_pos_inline (const GstByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return _gst_byte_reader_get_pos_unchecked (reader); +} + +static inline gboolean +_gst_byte_reader_skip_inline (GstByteReader * reader, guint nbytes) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (G_UNLIKELY (_gst_byte_reader_get_remaining_unchecked (reader) < nbytes)) + return FALSE; + + reader->byte += nbytes; + return TRUE; +} + +#ifndef GST_BYTE_READER_DISABLE_INLINES + +#define gst_byte_reader_dup_data(reader,size,val) \ + G_LIKELY(_gst_byte_reader_dup_data_inline(reader,size,val)) +#define gst_byte_reader_get_data(reader,size,val) \ + G_LIKELY(_gst_byte_reader_get_data_inline(reader,size,val)) +#define gst_byte_reader_peek_data(reader,size,val) \ + G_LIKELY(_gst_byte_reader_peek_data_inline(reader,size,val)) +#define gst_byte_reader_skip(reader,nbytes) \ + G_LIKELY(_gst_byte_reader_skip_inline(reader,nbytes)) + +#endif /* GST_BYTE_READER_DISABLE_INLINES */ + +G_END_DECLS + +#endif /* __GST_BYTE_READER_H__ */ diff --git a/libs/gst/base/gstbytewriter-docs.h b/libs/gst/base/gstbytewriter-docs.h new file mode 100644 index 0000000..3cc5962 --- /dev/null +++ b/libs/gst/base/gstbytewriter-docs.h @@ -0,0 +1,269 @@ +/* GStreamer byte writer dummy header for gtk-doc + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* This header is not installed, it just contains stuff for gtk-doc to parse, + * in particular docs and some dummy function declarations for the static + * inline functions we generate via macros in gstbitreader.h. + */ + +#error "This header should never be included in code, it is only for gtk-doc" + +/** + * gst_byte_writer_put_uint8_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned 8 bit integer to @writer without checking if there + * is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint8_unchecked (GstByteWriter *writer, guint8 val); + +/** + * gst_byte_writer_put_uint16_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 16 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint16_be_unchecked (GstByteWriter *writer, guint16 val); + +/** + * gst_byte_writer_put_uint24_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 24 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint24_be_unchecked (GstByteWriter *writer, guint32 val); + +/** + * gst_byte_writer_put_uint32_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 32 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint32_be_unchecked (GstByteWriter *writer, guint32 val); + +/** + * gst_byte_writer_put_uint64_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 64 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint64_be_unchecked (GstByteWriter *writer, guint64 val); + +/** + * gst_byte_writer_put_uint16_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 16 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint16_le_unchecked (GstByteWriter *writer, guint16 val); + +/** + * gst_byte_writer_put_uint24_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 24 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint24_le_unchecked (GstByteWriter *writer, guint32 val); + +/** + * gst_byte_writer_put_uint32_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 32 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint32_le_unchecked (GstByteWriter *writer, guint32 val); + +/** + * gst_byte_writer_put_uint64_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 64 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_uint64_le_unchecked (GstByteWriter *writer, guint64 val); + +/** + * gst_byte_writer_put_int8: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed 8 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int8_unchecked (GstByteWriter *writer, gint8 val); + +/** + * gst_byte_writer_put_int16_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 16 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int16_be_unchecked (GstByteWriter *writer, gint16 val); + +/** + * gst_byte_writer_put_int24_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 24 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int24_be_unchecked (GstByteWriter *writer, gint32 val); + +/** + * gst_byte_writer_put_int32_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 32 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int32_be_unchecked (GstByteWriter *writer, gint32 val); + +/** + * gst_byte_writer_put_int64_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 64 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int64_be_unchecked (GstByteWriter *writer, gint64 val); + +/** + * gst_byte_writer_put_int16_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 16 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int16_le_unchecked (GstByteWriter *writer, gint16 val); + +/** + * gst_byte_writer_put_int24_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 24 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int24_le_unchecked (GstByteWriter *writer, gint32 val); + +/** + * gst_byte_writer_put_int32_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 32 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int32_le_unchecked (GstByteWriter *writer, gint32 val); + +/** + * gst_byte_writer_put_int64_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 64 bit integer to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_int64_le_unchecked (GstByteWriter *writer, gint64 val); + +/** + * gst_byte_writer_put_float32_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a big endian 32 bit float to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_float32_be_unchecked (GstByteWriter *writer, gfloat val); + +/** + * gst_byte_writer_put_float64_be_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a big endian 64 bit float to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_float64_be_unchecked (GstByteWriter *writer, gdouble val); + +/** + * gst_byte_writer_put_float32_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a little endian 32 bit float to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_float32_le_unchecked (GstByteWriter *writer, gfloat val); + +/** + * gst_byte_writer_put_float64_le_unchecked: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a little endian 64 bit float to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_float64_le_unchecked (GstByteWriter *writer, gdouble val); + +/** + * gst_byte_writer_put_data_unchecked: + * @writer: #GstByteWriter instance + * @data: (in) (transfer none) (array length=size): Data to write + * @size: Size of @data in bytes + * + * Writes @size bytes of @data to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_put_data_unchecked (GstByteWriter *writer, const guint8 *data, guint size); + +/** + * gst_byte_writer_fill_unchecked: + * @writer: #GstByteWriter instance + * @value: Value to be written + * @size: Number of bytes to be written + + * + * Writes @size bytes containing @value to @writer without + * checking if there is enough free space available in the byte writer. + */ +void gst_byte_writer_fill_unchecked (GstByteWriter *writer, guint8 value, guint size); + diff --git a/libs/gst/base/gstbytewriter.c b/libs/gst/base/gstbytewriter.c new file mode 100644 index 0000000..705a35e --- /dev/null +++ b/libs/gst/base/gstbytewriter.c @@ -0,0 +1,683 @@ +/* GStreamer byte writer + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GST_BYTE_WRITER_DISABLE_INLINES +#include "gstbytewriter.h" + +/** + * SECTION:gstbytewriter + * @title: GstByteWriter + * @short_description: Writes different integer, string and floating point + * types to a memory buffer and allows reading + * + * #GstByteWriter provides a byte writer and reader that can write/read different + * integer and floating point types to/from a memory buffer. It provides functions + * for writing/reading signed/unsigned, little/big endian integers of 8, 16, 24, + * 32 and 64 bits and functions for reading little/big endian floating points numbers of + * 32 and 64 bits. It also provides functions to write/read NUL-terminated strings + * in various character encodings. + */ + +/** + * gst_byte_writer_new: (skip) + * + * Creates a new, empty #GstByteWriter instance + * + * Free-function: gst_byte_writer_free + * + * Returns: (transfer full): a new, empty #GstByteWriter instance + */ +GstByteWriter * +gst_byte_writer_new (void) +{ + GstByteWriter *ret = g_slice_new0 (GstByteWriter); + + ret->owned = TRUE; + return ret; +} + +/** + * gst_byte_writer_new_with_size: (skip) + * @size: Initial size of data + * @fixed: If %TRUE the data can't be reallocated + * + * Creates a new #GstByteWriter instance with the given + * initial data size. + * + * Free-function: gst_byte_writer_free + * + * Returns: (transfer full): a new #GstByteWriter instance + */ +GstByteWriter * +gst_byte_writer_new_with_size (guint size, gboolean fixed) +{ + GstByteWriter *ret = gst_byte_writer_new (); + + ret->alloc_size = size; + ret->parent.data = g_malloc (ret->alloc_size); + ret->fixed = fixed; + ret->owned = TRUE; + + return ret; +} + +/** + * gst_byte_writer_new_with_data: (skip) + * @data: Memory area for writing + * @size: Size of @data in bytes + * @initialized: If %TRUE the complete data can be read from the beginning + * + * Creates a new #GstByteWriter instance with the given + * memory area. If @initialized is %TRUE it is possible to + * read @size bytes from the #GstByteWriter from the beginning. + * + * Free-function: gst_byte_writer_free + * + * Returns: (transfer full): a new #GstByteWriter instance + */ +GstByteWriter * +gst_byte_writer_new_with_data (guint8 * data, guint size, gboolean initialized) +{ + GstByteWriter *ret = gst_byte_writer_new (); + + ret->parent.data = data; + ret->parent.size = (initialized) ? size : 0; + ret->alloc_size = size; + ret->fixed = TRUE; + ret->owned = FALSE; + + return ret; +} + +/** + * gst_byte_writer_init: + * @writer: #GstByteWriter instance + * + * Initializes @writer to an empty instance + */ +void +gst_byte_writer_init (GstByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + memset (writer, 0, sizeof (GstByteWriter)); + + writer->owned = TRUE; +} + +/** + * gst_byte_writer_init_with_size: + * @writer: #GstByteWriter instance + * @size: Initial size of data + * @fixed: If %TRUE the data can't be reallocated + * + * Initializes @writer with the given initial data size. + */ +void +gst_byte_writer_init_with_size (GstByteWriter * writer, guint size, + gboolean fixed) +{ + g_return_if_fail (writer != NULL); + + gst_byte_writer_init (writer); + + writer->parent.data = g_malloc (size); + writer->alloc_size = size; + writer->fixed = fixed; + writer->owned = TRUE; +} + +/** + * gst_byte_writer_init_with_data: + * @writer: #GstByteWriter instance + * @data: (array length=size) (transfer none): Memory area for writing + * @size: Size of @data in bytes + * @initialized: If %TRUE the complete data can be read from the beginning + * + * Initializes @writer with the given + * memory area. If @initialized is %TRUE it is possible to + * read @size bytes from the #GstByteWriter from the beginning. + */ +void +gst_byte_writer_init_with_data (GstByteWriter * writer, guint8 * data, + guint size, gboolean initialized) +{ + g_return_if_fail (writer != NULL); + + gst_byte_writer_init (writer); + + writer->parent.data = data; + writer->parent.size = (initialized) ? size : 0; + writer->alloc_size = size; + writer->fixed = TRUE; + writer->owned = FALSE; +} + +/** + * gst_byte_writer_reset: + * @writer: #GstByteWriter instance + * + * Resets @writer and frees the data if it's + * owned by @writer. + */ +void +gst_byte_writer_reset (GstByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + if (writer->owned) + g_free ((guint8 *) writer->parent.data); + memset (writer, 0, sizeof (GstByteWriter)); +} + +/** + * gst_byte_writer_reset_and_get_data: + * @writer: #GstByteWriter instance + * + * Resets @writer and returns the current data. + * + * Free-function: g_free + * + * Returns: (array) (transfer full): the current data. g_free() after + * usage. + */ +guint8 * +gst_byte_writer_reset_and_get_data (GstByteWriter * writer) +{ + guint8 *data; + + g_return_val_if_fail (writer != NULL, NULL); + + data = (guint8 *) writer->parent.data; + if (!writer->owned) + data = g_memdup (data, writer->parent.size); + writer->parent.data = NULL; + gst_byte_writer_reset (writer); + + return data; +} + +/** + * gst_byte_writer_reset_and_get_buffer: + * @writer: #GstByteWriter instance + * + * Resets @writer and returns the current data as buffer. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full): the current data as buffer. gst_buffer_unref() + * after usage. + */ +GstBuffer * +gst_byte_writer_reset_and_get_buffer (GstByteWriter * writer) +{ + GstBuffer *buffer; + gpointer data; + gsize size; + + g_return_val_if_fail (writer != NULL, NULL); + + size = writer->parent.size; + data = gst_byte_writer_reset_and_get_data (writer); + + buffer = gst_buffer_new (); + if (data != NULL) { + gst_buffer_append_memory (buffer, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); + } + + return buffer; +} + +/** + * gst_byte_writer_free: + * @writer: (in) (transfer full): #GstByteWriter instance + * + * Frees @writer and all memory allocated by it. + */ +void +gst_byte_writer_free (GstByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + gst_byte_writer_reset (writer); + g_slice_free (GstByteWriter, writer); +} + +/** + * gst_byte_writer_free_and_get_data: + * @writer: (in) (transfer full): #GstByteWriter instance + * + * Frees @writer and all memory allocated by it except + * the current data, which is returned. + * + * Free-function: g_free + * + * Returns: (transfer full): the current data. g_free() after usage. + */ +guint8 * +gst_byte_writer_free_and_get_data (GstByteWriter * writer) +{ + guint8 *data; + + g_return_val_if_fail (writer != NULL, NULL); + + data = gst_byte_writer_reset_and_get_data (writer); + g_slice_free (GstByteWriter, writer); + + return data; +} + +/** + * gst_byte_writer_free_and_get_buffer: + * @writer: (in) (transfer full): #GstByteWriter instance + * + * Frees @writer and all memory allocated by it except + * the current data, which is returned as #GstBuffer. + * + * Free-function: gst_buffer_unref + * + * Returns: (transfer full): the current data as buffer. gst_buffer_unref() + * after usage. + */ +GstBuffer * +gst_byte_writer_free_and_get_buffer (GstByteWriter * writer) +{ + GstBuffer *buffer; + + g_return_val_if_fail (writer != NULL, NULL); + + buffer = gst_byte_writer_reset_and_get_buffer (writer); + g_slice_free (GstByteWriter, writer); + + return buffer; +} + +/** + * gst_byte_writer_get_remaining: + * @writer: #GstByteWriter instance + * + * Returns the remaining size of data that can still be written. If + * -1 is returned the remaining size is only limited by system resources. + * + * Returns: the remaining size of data that can still be written + */ +guint +gst_byte_writer_get_remaining (const GstByteWriter * writer) +{ + g_return_val_if_fail (writer != NULL, -1); + + if (!writer->fixed) + return -1; + else + return writer->alloc_size - writer->parent.byte; +} + +/** + * gst_byte_writer_ensure_free_space: + * @writer: #GstByteWriter instance + * @size: Number of bytes that should be available + * + * Checks if enough free space from the current write cursor is + * available and reallocates if necessary. + * + * Returns: %TRUE if at least @size bytes are still available + */ +gboolean +gst_byte_writer_ensure_free_space (GstByteWriter * writer, guint size) +{ + return _gst_byte_writer_ensure_free_space_inline (writer, size); +} + + +#define CREATE_WRITE_FUNC(bits,type,name,write_func) \ +gboolean \ +gst_byte_writer_put_##name (GstByteWriter *writer, type val) \ +{ \ + return _gst_byte_writer_put_##name##_inline (writer, val); \ +} + +CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8); +CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8); +CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE); +CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE); +CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE); +CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE); +CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE); +CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE); +CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE); +CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE); +CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE); +CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE); +CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE); +CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE); +CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE); +CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE); +CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE); +CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE); + +CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE); +CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE); +CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE); +CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE); + +gboolean +gst_byte_writer_put_data (GstByteWriter * writer, const guint8 * data, + guint size) +{ + return _gst_byte_writer_put_data_inline (writer, data, size); +} + +gboolean +gst_byte_writer_fill (GstByteWriter * writer, guint8 value, guint size) +{ + return _gst_byte_writer_fill_inline (writer, value, size); +} + +#define CREATE_WRITE_STRING_FUNC(bits,type) \ +gboolean \ +gst_byte_writer_put_string_utf##bits (GstByteWriter *writer, const type * data) \ +{ \ + guint size = 0; \ + \ + g_return_val_if_fail (writer != NULL, FALSE); \ + \ + /* endianness does not matter if we are looking for a NUL terminator */ \ + while (data[size] != 0) { \ + /* have prevent overflow */ \ + if (G_UNLIKELY (size == G_MAXUINT)) \ + return FALSE; \ + ++size; \ + } \ + ++size; \ + \ + if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline(writer, size * (bits / 8)))) \ + return FALSE; \ + \ + _gst_byte_writer_put_data_inline (writer, (const guint8 *) data, size * (bits / 8)); \ + \ + return TRUE; \ +} + +CREATE_WRITE_STRING_FUNC (8, gchar); +CREATE_WRITE_STRING_FUNC (16, guint16); +CREATE_WRITE_STRING_FUNC (32, guint32); +/** + * gst_byte_writer_put_uint8: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned 8 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint16_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint24_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint32_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint64_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint16_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint24_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint32_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_uint64_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int8: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed 8 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int16_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int24_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int32_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int64_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int16_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int24_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int32_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_int64_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_float32_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a big endian 32 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_float64_be: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a big endian 64 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_float32_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a little endian 32 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_float64_le: + * @writer: #GstByteWriter instance + * @val: Value to write + * + * Writes a little endian 64 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_string_utf8: + * @writer: #GstByteWriter instance + * @data: (transfer none): UTF8 string to write + * + * Writes a NUL-terminated UTF8 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_string_utf16: + * @writer: #GstByteWriter instance + * @data: (transfer none) (array zero-terminated=1): UTF16 string to write + * + * Writes a NUL-terminated UTF16 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_string_utf32: + * @writer: #GstByteWriter instance + * @data: (transfer none) (array zero-terminated=1): UTF32 string to write + * + * Writes a NUL-terminated UTF32 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_put_data: + * @writer: #GstByteWriter instance + * @data: (transfer none) (array length=size): Data to write + * @size: Size of @data in bytes + * + * Writes @size bytes of @data to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * gst_byte_writer_fill: + * @writer: #GstByteWriter instance + * @value: Value to be written + * @size: Number of bytes to be written + * + * Writes @size bytes containing @value to @writer. + * + * Returns: %TRUE if the value could be written + */ + +/** + * gst_byte_writer_put_buffer: + * @writer: #GstByteWriter instance + * @buffer: (transfer none): source #GstBuffer + * @offset: offset to copy from + * @size: total size to copy. If -1, all data is copied + * + * Writes @size bytes of @data to @writer. + * + * Returns: %TRUE if the data could be written + * + */ diff --git a/libs/gst/base/gstbytewriter.h b/libs/gst/base/gstbytewriter.h new file mode 100644 index 0000000..365c774 --- /dev/null +++ b/libs/gst/base/gstbytewriter.h @@ -0,0 +1,468 @@ +/* GStreamer byte writer + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BYTE_WRITER_H__ +#define __GST_BYTE_WRITER_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_BYTE_WRITER(writer) ((GstByteWriter *) (writer)) + +/** + * GstByteWriter: + * @parent: #GstByteReader parent + * @alloc_size: Allocation size of the data + * @fixed: If %TRUE no reallocations are allowed + * @owned: If %FALSE no reallocations are allowed and copies of data are returned + * + * A byte writer instance. + */ +typedef struct { + GstByteReader parent; + + guint alloc_size; + + gboolean fixed; + gboolean owned; + + /* < private > */ + gpointer _gst_reserved[GST_PADDING]; +} GstByteWriter; + +GST_BASE_API +GstByteWriter * gst_byte_writer_new (void) G_GNUC_MALLOC; + +GST_BASE_API +GstByteWriter * gst_byte_writer_new_with_size (guint size, gboolean fixed) G_GNUC_MALLOC; + +GST_BASE_API +GstByteWriter * gst_byte_writer_new_with_data (guint8 *data, guint size, gboolean initialized) G_GNUC_MALLOC; + +GST_BASE_API +void gst_byte_writer_init (GstByteWriter *writer); + +GST_BASE_API +void gst_byte_writer_init_with_size (GstByteWriter *writer, guint size, gboolean fixed); + +GST_BASE_API +void gst_byte_writer_init_with_data (GstByteWriter *writer, guint8 *data, + guint size, gboolean initialized); +GST_BASE_API +void gst_byte_writer_free (GstByteWriter *writer); + +GST_BASE_API +guint8 * gst_byte_writer_free_and_get_data (GstByteWriter *writer); + +GST_BASE_API +GstBuffer * gst_byte_writer_free_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC; + +GST_BASE_API +void gst_byte_writer_reset (GstByteWriter *writer); + +GST_BASE_API +guint8 * gst_byte_writer_reset_and_get_data (GstByteWriter *writer); + +GST_BASE_API +GstBuffer * gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC; + +/** + * gst_byte_writer_get_pos: + * @writer: #GstByteWriter instance + * + * Returns: The current position of the read/write cursor + */ +/** + * gst_byte_writer_set_pos: + * @writer: #GstByteWriter instance + * @pos: new position + * + * Sets the current read/write cursor of @writer. The new position + * can only be between 0 and the current size. + * + * Returns: %TRUE if the new position could be set + */ +/** + * gst_byte_writer_get_size: + * @writer: #GstByteWriter instance + * + * Returns: The current, initialized size of the data + */ +static inline guint +gst_byte_writer_get_pos (const GstByteWriter *writer) +{ + return gst_byte_reader_get_pos ((const GstByteReader *) writer); +} + +static inline gboolean +gst_byte_writer_set_pos (GstByteWriter *writer, guint pos) +{ + return gst_byte_reader_set_pos (GST_BYTE_READER (writer), pos); +} + +static inline guint +gst_byte_writer_get_size (const GstByteWriter *writer) +{ + return gst_byte_reader_get_size ((const GstByteReader *) writer); +} + +GST_BASE_API +guint gst_byte_writer_get_remaining (const GstByteWriter *writer); + +GST_BASE_API +gboolean gst_byte_writer_ensure_free_space (GstByteWriter *writer, guint size); + +GST_BASE_API +gboolean gst_byte_writer_put_uint8 (GstByteWriter *writer, guint8 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int8 (GstByteWriter *writer, gint8 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint16_be (GstByteWriter *writer, guint16 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint16_le (GstByteWriter *writer, guint16 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int16_be (GstByteWriter *writer, gint16 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int16_le (GstByteWriter *writer, gint16 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint24_be (GstByteWriter *writer, guint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint24_le (GstByteWriter *writer, guint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int24_be (GstByteWriter *writer, gint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int24_le (GstByteWriter *writer, gint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint32_be (GstByteWriter *writer, guint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint32_le (GstByteWriter *writer, guint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int32_be (GstByteWriter *writer, gint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int32_le (GstByteWriter *writer, gint32 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint64_be (GstByteWriter *writer, guint64 val); + +GST_BASE_API +gboolean gst_byte_writer_put_uint64_le (GstByteWriter *writer, guint64 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int64_be (GstByteWriter *writer, gint64 val); + +GST_BASE_API +gboolean gst_byte_writer_put_int64_le (GstByteWriter *writer, gint64 val); + +GST_BASE_API +gboolean gst_byte_writer_put_float32_be (GstByteWriter *writer, gfloat val); + +GST_BASE_API +gboolean gst_byte_writer_put_float32_le (GstByteWriter *writer, gfloat val); + +GST_BASE_API +gboolean gst_byte_writer_put_float64_be (GstByteWriter *writer, gdouble val); + +GST_BASE_API +gboolean gst_byte_writer_put_float64_le (GstByteWriter *writer, gdouble val); + +GST_BASE_API +gboolean gst_byte_writer_put_data (GstByteWriter *writer, const guint8 *data, guint size); + +GST_BASE_API +gboolean gst_byte_writer_fill (GstByteWriter *writer, guint8 value, guint size); + +GST_BASE_API +gboolean gst_byte_writer_put_string_utf8 (GstByteWriter *writer, const gchar *data); + +GST_BASE_API +gboolean gst_byte_writer_put_string_utf16 (GstByteWriter *writer, const guint16 *data); + +GST_BASE_API +gboolean gst_byte_writer_put_string_utf32 (GstByteWriter *writer, const guint32 *data); +gboolean gst_byte_writer_put_buffer (GstByteWriter *writer, GstBuffer * buffer, gsize offset, gssize size); + +/** + * gst_byte_writer_put_string: + * @writer: #GstByteWriter instance + * @data: (in) (array zero-terminated=1): Null terminated string + * + * Write a NUL-terminated string to @writer (including the terminator). The + * string is assumed to be in an 8-bit encoding (e.g. ASCII,UTF-8 or + * ISO-8859-1). + * + * Returns: %TRUE if the string could be written + */ +#define gst_byte_writer_put_string(writer, data) \ + gst_byte_writer_put_string_utf8(writer, data) + +static inline guint +_gst_byte_writer_next_pow2 (guint n) +{ + guint ret = 16; + + /* We start with 16, smaller allocations make no sense */ + + while (ret < n && ret > 0) + ret <<= 1; + + return ret ? ret : n; +} + +static inline gboolean +_gst_byte_writer_ensure_free_space_inline (GstByteWriter * writer, guint size) +{ + gpointer data; + + if (G_LIKELY (size <= writer->alloc_size - writer->parent.byte)) + return TRUE; + if (G_UNLIKELY (writer->fixed || !writer->owned)) + return FALSE; + if (G_UNLIKELY (writer->parent.byte > G_MAXUINT - size)) + return FALSE; + + writer->alloc_size = _gst_byte_writer_next_pow2 (writer->parent.byte + size); + data = g_try_realloc ((guint8 *) writer->parent.data, writer->alloc_size); + if (G_UNLIKELY (data == NULL)) + return FALSE; + + writer->parent.data = (guint8 *) data; + + return TRUE; +} + +#define __GST_BYTE_WRITER_CREATE_WRITE_FUNC(bits,type,name,write_func) \ +static inline void \ +gst_byte_writer_put_##name##_unchecked (GstByteWriter *writer, type val) \ +{ \ + guint8 *write_data; \ + \ + write_data = (guint8 *) writer->parent.data + writer->parent.byte; \ + write_func (write_data, val); \ + writer->parent.byte += bits/8; \ + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); \ +} \ +\ +static inline gboolean \ +_gst_byte_writer_put_##name##_inline (GstByteWriter *writer, type val) \ +{ \ + g_return_val_if_fail (writer != NULL, FALSE); \ + \ + if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline(writer, bits/8))) \ + return FALSE; \ + \ + gst_byte_writer_put_##name##_unchecked (writer, val); \ + \ + return TRUE; \ +} + +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE) + +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE) +__GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE) + +#undef __GST_BYTE_WRITER_CREATE_WRITE_FUNC + +static inline void +gst_byte_writer_put_data_unchecked (GstByteWriter * writer, const guint8 * data, + guint size) +{ + memcpy ((guint8 *) & writer->parent.data[writer->parent.byte], data, size); + writer->parent.byte += size; + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); +} + +static inline gboolean +_gst_byte_writer_put_data_inline (GstByteWriter * writer, const guint8 * data, + guint size) +{ + g_return_val_if_fail (writer != NULL, FALSE); + + if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size))) + return FALSE; + + gst_byte_writer_put_data_unchecked (writer, data, size); + + return TRUE; +} + +static inline void +gst_byte_writer_fill_unchecked (GstByteWriter * writer, guint8 value, guint size) +{ + memset ((guint8 *) & writer->parent.data[writer->parent.byte], value, size); + writer->parent.byte += size; + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); +} + +static inline gboolean +_gst_byte_writer_fill_inline (GstByteWriter * writer, guint8 value, guint size) +{ + g_return_val_if_fail (writer != NULL, FALSE); + + if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size))) + return FALSE; + + gst_byte_writer_fill_unchecked (writer, value, size); + + return TRUE; +} + +static inline void +gst_byte_writer_put_buffer_unchecked (GstByteWriter * writer, GstBuffer * buffer, + gsize offset, gssize size) +{ + if (size == -1) { + size = gst_buffer_get_size (buffer); + + if (offset >= (gsize) size) + return; + + size -= offset; + } + + gst_buffer_extract (buffer, offset, + (guint8 *) & writer->parent.data[writer->parent.byte], size); + writer->parent.byte += size; + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); +} + +static inline gboolean +_gst_byte_writer_put_buffer_inline (GstByteWriter * writer, GstBuffer * buffer, + gsize offset, gssize size) +{ + g_return_val_if_fail (writer != NULL, FALSE); + g_return_val_if_fail (size >= -1, FALSE); + + if (size == -1) { + size = gst_buffer_get_size (buffer); + + if (offset >= (gsize) size) + return TRUE; + + size -= offset; + } + + if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size))) + return FALSE; + + gst_byte_writer_put_buffer_unchecked (writer, buffer, offset, size); + + return TRUE; +} + +#ifndef GST_BYTE_WRITER_DISABLE_INLINES + +/* we use defines here so we can add the G_LIKELY() */ + +#define gst_byte_writer_ensure_free_space(writer, size) \ + G_LIKELY (_gst_byte_writer_ensure_free_space_inline (writer, size)) +#define gst_byte_writer_put_uint8(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint8_inline (writer, val)) +#define gst_byte_writer_put_int8(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int8_inline (writer, val)) +#define gst_byte_writer_put_uint16_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint16_be_inline (writer, val)) +#define gst_byte_writer_put_uint16_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint16_le_inline (writer, val)) +#define gst_byte_writer_put_int16_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int16_be_inline (writer, val)) +#define gst_byte_writer_put_int16_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int16_le_inline (writer, val)) +#define gst_byte_writer_put_uint24_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint24_be_inline (writer, val)) +#define gst_byte_writer_put_uint24_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint24_le_inline (writer, val)) +#define gst_byte_writer_put_int24_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int24_be_inline (writer, val)) +#define gst_byte_writer_put_int24_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int24_le_inline (writer, val)) +#define gst_byte_writer_put_uint32_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint32_be_inline (writer, val)) +#define gst_byte_writer_put_uint32_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint32_le_inline (writer, val)) +#define gst_byte_writer_put_int32_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int32_be_inline (writer, val)) +#define gst_byte_writer_put_int32_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int32_le_inline (writer, val)) +#define gst_byte_writer_put_uint64_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint64_be_inline (writer, val)) +#define gst_byte_writer_put_uint64_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_uint64_le_inline (writer, val)) +#define gst_byte_writer_put_int64_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int64_be_inline (writer, val)) +#define gst_byte_writer_put_int64_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_int64_le_inline (writer, val)) + +#define gst_byte_writer_put_float32_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_float32_be_inline (writer, val)) +#define gst_byte_writer_put_float32_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_float32_le_inline (writer, val)) +#define gst_byte_writer_put_float64_be(writer, val) \ + G_LIKELY (_gst_byte_writer_put_float64_be_inline (writer, val)) +#define gst_byte_writer_put_float64_le(writer, val) \ + G_LIKELY (_gst_byte_writer_put_float64_le_inline (writer, val)) + +#define gst_byte_writer_put_data(writer, data, size) \ + G_LIKELY (_gst_byte_writer_put_data_inline (writer, data, size)) +#define gst_byte_writer_fill(writer, val, size) \ + G_LIKELY (_gst_byte_writer_fill_inline (writer, val, size)) +#define gst_byte_writer_put_buffer(writer, buffer, offset, size) \ + G_LIKELY (_gst_byte_writer_put_buffer_inline (writer, buffer, offset, size)) + +#endif + +G_END_DECLS + +#endif /* __GST_BYTE_WRITER_H__ */ diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c new file mode 100644 index 0000000..13fe2e1 --- /dev/null +++ b/libs/gst/base/gstcollectpads.c @@ -0,0 +1,2327 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * Copyright (C) 2008 Mark Nauwelaerts + * Copyright (C) 2010 Sebastian Dröge + * + * gstcollectpads.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstcollectpads + * @title: GstCollectPads + * @short_description: manages a set of pads that operate in collect mode + * @see_also: + * + * Manages a set of pads that operate in collect mode. This means that control + * is given to the manager of this object when all pads have data. + * + * * Collectpads are created with gst_collect_pads_new(). A callback should then + * be installed with gst_collect_pads_set_function (). + * + * * Pads are added to the collection with gst_collect_pads_add_pad()/ + * gst_collect_pads_remove_pad(). The pad has to be a sinkpad. When added, + * the chain, event and query functions of the pad are overridden. The + * element_private of the pad is used to store private information for the + * collectpads. + * + * * For each pad, data is queued in the _chain function or by + * performing a pull_range. + * + * * When data is queued on all pads in waiting mode, the callback function is called. + * + * * Data can be dequeued from the pad with the gst_collect_pads_pop() method. + * One can peek at the data with the gst_collect_pads_peek() function. + * These functions will return %NULL if the pad received an EOS event. When all + * pads return %NULL from a gst_collect_pads_peek(), the element can emit an EOS + * event itself. + * + * * Data can also be dequeued in byte units using the gst_collect_pads_available(), + * gst_collect_pads_read_buffer() and gst_collect_pads_flush() calls. + * + * * Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in + * their state change functions to start and stop the processing of the collectpads. + * The gst_collect_pads_stop() call should be called before calling the parent + * element state change function in the PAUSED_TO_READY state change to ensure + * no pad is blocked and the element can finish streaming. + * + * * gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode. + * CollectPads element is not waiting for data to be collected on non-waiting pads. + * Thus these pads may but need not have data when the callback is called. + * All pads are in waiting mode by default. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "gstcollectpads.h" + +#include "../../../gst/glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (collect_pads_debug); +#define GST_CAT_DEFAULT collect_pads_debug + +#define parent_class gst_collect_pads_parent_class +G_DEFINE_TYPE (GstCollectPads, gst_collect_pads, GST_TYPE_OBJECT); + +struct _GstCollectDataPrivate +{ + /* refcounting for struct, and destroy callback */ + GstCollectDataDestroyNotify destroy_notify; + gint refcount; +}; + +struct _GstCollectPadsPrivate +{ + /* with LOCK and/or STREAM_LOCK */ + gboolean started; + + /* with STREAM_LOCK */ + guint32 cookie; /* pad_list cookie */ + guint numpads; /* number of pads in @data */ + guint queuedpads; /* number of pads with a buffer */ + guint eospads; /* number of pads that are EOS */ + GstClockTime earliest_time; /* Current earliest time */ + GstCollectData *earliest_data; /* Pad data for current earliest time */ + + /* with LOCK */ + GSList *pad_list; /* list of GstCollectData* */ + guint32 pad_cookie; /* updated cookie */ + + GstCollectPadsFunction func; /* function and user_data for callback */ + gpointer user_data; + GstCollectPadsBufferFunction buffer_func; /* function and user_data for buffer callback */ + gpointer buffer_user_data; + GstCollectPadsCompareFunction compare_func; + gpointer compare_user_data; + GstCollectPadsEventFunction event_func; /* function and data for event callback */ + gpointer event_user_data; + GstCollectPadsQueryFunction query_func; + gpointer query_user_data; + GstCollectPadsClipFunction clip_func; + gpointer clip_user_data; + GstCollectPadsFlushFunction flush_func; + gpointer flush_user_data; + + /* no other lock needed */ + GMutex evt_lock; /* these make up sort of poor man's event signaling */ + GCond evt_cond; + guint32 evt_cookie; + + gboolean seeking; + gboolean pending_flush_start; + gboolean pending_flush_stop; +}; + +static void gst_collect_pads_clear (GstCollectPads * pads, + GstCollectData * data); +static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_collect_pads_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_collect_pads_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static void gst_collect_pads_finalize (GObject * object); +static GstFlowReturn gst_collect_pads_default_collected (GstCollectPads * + pads, gpointer user_data); +static gint gst_collect_pads_default_compare_func (GstCollectPads * pads, + GstCollectData * data1, GstClockTime timestamp1, GstCollectData * data2, + GstClockTime timestamp2, gpointer user_data); +static gboolean gst_collect_pads_recalculate_full (GstCollectPads * pads); +static void ref_data (GstCollectData * data); +static void unref_data (GstCollectData * data); + +static gboolean gst_collect_pads_event_default_internal (GstCollectPads * + pads, GstCollectData * data, GstEvent * event, gpointer user_data); +static gboolean gst_collect_pads_query_default_internal (GstCollectPads * + pads, GstCollectData * data, GstQuery * query, gpointer user_data); + + +/* Some properties are protected by LOCK, others by STREAM_LOCK + * However, manipulating either of these partitions may require + * to signal/wake a _WAIT, so use a separate (sort of) event to prevent races + * Alternative implementations are possible, e.g. some low-level re-implementing + * of the 2 above locks to drop both of them atomically when going into _WAIT. + */ +#define GST_COLLECT_PADS_GET_EVT_COND(pads) (&((GstCollectPads *)pads)->priv->evt_cond) +#define GST_COLLECT_PADS_GET_EVT_LOCK(pads) (&((GstCollectPads *)pads)->priv->evt_lock) +#define GST_COLLECT_PADS_EVT_WAIT(pads, cookie) G_STMT_START { \ + g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ + /* should work unless a lot of event'ing and thread starvation */\ + while (cookie == ((GstCollectPads *) pads)->priv->evt_cookie) \ + g_cond_wait (GST_COLLECT_PADS_GET_EVT_COND (pads), \ + GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ + cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \ + g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ +} G_STMT_END +#define GST_COLLECT_PADS_EVT_WAIT_TIMED(pads, cookie, timeout) G_STMT_START { \ + GTimeVal __tv; \ + \ + g_get_current_time (&tv); \ + g_time_val_add (&tv, timeout); \ + \ + g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ + /* should work unless a lot of event'ing and thread starvation */\ + while (cookie == ((GstCollectPads *) pads)->priv->evt_cookie) \ + g_cond_timed_wait (GST_COLLECT_PADS_GET_EVT_COND (pads), \ + GST_COLLECT_PADS_GET_EVT_LOCK (pads), &tv); \ + cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \ + g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ +} G_STMT_END +#define GST_COLLECT_PADS_EVT_BROADCAST(pads) G_STMT_START { \ + g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ + /* never mind wrap-around */ \ + ++(((GstCollectPads *) pads)->priv->evt_cookie); \ + g_cond_broadcast (GST_COLLECT_PADS_GET_EVT_COND (pads)); \ + g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ +} G_STMT_END +#define GST_COLLECT_PADS_EVT_INIT(cookie) G_STMT_START { \ + g_mutex_lock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ + cookie = ((GstCollectPads *) pads)->priv->evt_cookie; \ + g_mutex_unlock (GST_COLLECT_PADS_GET_EVT_LOCK (pads)); \ +} G_STMT_END + +static void +gst_collect_pads_class_init (GstCollectPadsClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GstCollectPadsPrivate)); + + GST_DEBUG_CATEGORY_INIT (collect_pads_debug, "collectpads", 0, + "GstCollectPads"); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collect_pads_finalize); +} + +static void +gst_collect_pads_init (GstCollectPads * pads) +{ + pads->priv = + G_TYPE_INSTANCE_GET_PRIVATE (pads, GST_TYPE_COLLECT_PADS, + GstCollectPadsPrivate); + + pads->data = NULL; + pads->priv->cookie = 0; + pads->priv->numpads = 0; + pads->priv->queuedpads = 0; + pads->priv->eospads = 0; + pads->priv->started = FALSE; + + g_rec_mutex_init (&pads->stream_lock); + + pads->priv->func = gst_collect_pads_default_collected; + pads->priv->user_data = NULL; + pads->priv->event_func = NULL; + pads->priv->event_user_data = NULL; + + /* members for default muxing */ + pads->priv->buffer_func = NULL; + pads->priv->buffer_user_data = NULL; + pads->priv->compare_func = gst_collect_pads_default_compare_func; + pads->priv->compare_user_data = NULL; + pads->priv->earliest_data = NULL; + pads->priv->earliest_time = GST_CLOCK_TIME_NONE; + + pads->priv->event_func = gst_collect_pads_event_default_internal; + pads->priv->query_func = gst_collect_pads_query_default_internal; + + /* members to manage the pad list */ + pads->priv->pad_cookie = 0; + pads->priv->pad_list = NULL; + + /* members for event */ + g_mutex_init (&pads->priv->evt_lock); + g_cond_init (&pads->priv->evt_cond); + pads->priv->evt_cookie = 0; + + pads->priv->seeking = FALSE; + pads->priv->pending_flush_start = FALSE; + pads->priv->pending_flush_stop = FALSE; +} + +static void +gst_collect_pads_finalize (GObject * object) +{ + GstCollectPads *pads = GST_COLLECT_PADS (object); + + GST_DEBUG_OBJECT (object, "finalize"); + + g_rec_mutex_clear (&pads->stream_lock); + + g_cond_clear (&pads->priv->evt_cond); + g_mutex_clear (&pads->priv->evt_lock); + + /* Remove pads and free pads list */ + g_slist_foreach (pads->priv->pad_list, (GFunc) unref_data, NULL); + g_slist_foreach (pads->data, (GFunc) unref_data, NULL); + g_slist_free (pads->data); + g_slist_free (pads->priv->pad_list); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_collect_pads_new: + * + * Create a new instance of #GstCollectPads. + * + * MT safe. + * + * Returns: (transfer full): a new #GstCollectPads, or %NULL in case of an error. + */ +GstCollectPads * +gst_collect_pads_new (void) +{ + GstCollectPads *newcoll; + + newcoll = g_object_new (GST_TYPE_COLLECT_PADS, NULL); + + /* clear floating flag */ + gst_object_ref_sink (newcoll); + + return newcoll; +} + +/* Must be called with GstObject lock! */ +static void +gst_collect_pads_set_buffer_function_locked (GstCollectPads * pads, + GstCollectPadsBufferFunction func, gpointer user_data) +{ + pads->priv->buffer_func = func; + pads->priv->buffer_user_data = user_data; +} + +/** + * gst_collect_pads_set_buffer_function: + * @pads: the collectpads to use + * @func: (scope call): the function to set + * @user_data: (closure): user data passed to the function + * + * Set the callback function and user data that will be called with + * the oldest buffer when all pads have been collected, or %NULL on EOS. + * If a buffer is passed, the callback owns a reference and must unref + * it. + * + * MT safe. + */ +void +gst_collect_pads_set_buffer_function (GstCollectPads * pads, + GstCollectPadsBufferFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_OBJECT_LOCK (pads); + gst_collect_pads_set_buffer_function_locked (pads, func, user_data); + GST_OBJECT_UNLOCK (pads); +} + +/** + * gst_collect_pads_set_compare_function: + * @pads: the pads to use + * @func: (scope call): the function to set + * @user_data: (closure): user data passed to the function + * + * Set the timestamp comparison function. + * + * MT safe. + */ +/* NOTE allowing to change comparison seems not advisable; +no known use-case, and collaboration with default algorithm is unpredictable. +If custom compairing/operation is needed, just use a collect function of +your own */ +void +gst_collect_pads_set_compare_function (GstCollectPads * pads, + GstCollectPadsCompareFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_OBJECT_LOCK (pads); + pads->priv->compare_func = func; + pads->priv->compare_user_data = user_data; + GST_OBJECT_UNLOCK (pads); +} + +/** + * gst_collect_pads_set_function: + * @pads: the collectpads to use + * @func: (scope call): the function to set + * @user_data: user data passed to the function + * + * CollectPads provides a default collection algorithm that will determine + * the oldest buffer available on all of its pads, and then delegate + * to a configured callback. + * However, if circumstances are more complicated and/or more control + * is desired, this sets a callback that will be invoked instead when + * all the pads added to the collection have buffers queued. + * Evidently, this callback is not compatible with + * gst_collect_pads_set_buffer_function() callback. + * If this callback is set, the former will be unset. + * + * MT safe. + */ +void +gst_collect_pads_set_function (GstCollectPads * pads, + GstCollectPadsFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_OBJECT_LOCK (pads); + pads->priv->func = func; + pads->priv->user_data = user_data; + gst_collect_pads_set_buffer_function_locked (pads, NULL, NULL); + GST_OBJECT_UNLOCK (pads); +} + +static void +ref_data (GstCollectData * data) +{ + g_assert (data != NULL); + + g_atomic_int_inc (&(data->priv->refcount)); +} + +static void +unref_data (GstCollectData * data) +{ + g_assert (data != NULL); + g_assert (data->priv->refcount > 0); + + if (!g_atomic_int_dec_and_test (&(data->priv->refcount))) + return; + + if (data->priv->destroy_notify) + data->priv->destroy_notify (data); + + g_object_unref (data->pad); + if (data->buffer) { + gst_buffer_unref (data->buffer); + } + g_free (data->priv); + g_free (data); +} + +/** + * gst_collect_pads_set_event_function: + * @pads: the collectpads to use + * @func: (scope call): the function to set + * @user_data: user data passed to the function + * + * Set the event callback function and user data that will be called when + * collectpads has received an event originating from one of the collected + * pads. If the event being processed is a serialized one, this callback is + * called with @pads STREAM_LOCK held, otherwise not. As this lock should be + * held when calling a number of CollectPads functions, it should be acquired + * if so (unusually) needed. + * + * MT safe. + */ +void +gst_collect_pads_set_event_function (GstCollectPads * pads, + GstCollectPadsEventFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_OBJECT_LOCK (pads); + pads->priv->event_func = func; + pads->priv->event_user_data = user_data; + GST_OBJECT_UNLOCK (pads); +} + +/** + * gst_collect_pads_set_query_function: + * @pads: the collectpads to use + * @func: (scope call): the function to set + * @user_data: user data passed to the function + * + * Set the query callback function and user data that will be called after + * collectpads has received a query originating from one of the collected + * pads. If the query being processed is a serialized one, this callback is + * called with @pads STREAM_LOCK held, otherwise not. As this lock should be + * held when calling a number of CollectPads functions, it should be acquired + * if so (unusually) needed. + * + * MT safe. + */ +void +gst_collect_pads_set_query_function (GstCollectPads * pads, + GstCollectPadsQueryFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_OBJECT_LOCK (pads); + pads->priv->query_func = func; + pads->priv->query_user_data = user_data; + GST_OBJECT_UNLOCK (pads); +} + +/** +* gst_collect_pads_clip_running_time: +* @pads: the collectpads to use +* @cdata: collect data of corresponding pad +* @buf: buffer being clipped +* @outbuf: (allow-none) (out): output buffer with running time, or NULL if clipped +* @user_data: user data (unused) +* +* Convenience clipping function that converts incoming buffer's timestamp +* to running time, or clips the buffer if outside configured segment. +* +* Since 1.6, this clipping function also sets the DTS parameter of the +* GstCollectData structure. This version of the running time DTS can be +* negative. G_MININT64 is used to indicate invalid value. +*/ +GstFlowReturn +gst_collect_pads_clip_running_time (GstCollectPads * pads, + GstCollectData * cdata, GstBuffer * buf, GstBuffer ** outbuf, + gpointer user_data) +{ + *outbuf = buf; + + /* invalid left alone and passed */ + if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS_OR_PTS (buf)))) { + GstClockTime time; + GstClockTime buf_dts, abs_dts; + gint dts_sign; + + time = GST_BUFFER_PTS (buf); + + if (GST_CLOCK_TIME_IS_VALID (time)) { + time = + gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time); + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) { + GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment %" + GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + gst_buffer_unref (buf); + *outbuf = NULL; + return GST_FLOW_OK; + } + } + + GST_LOG_OBJECT (cdata->pad, "buffer pts %" GST_TIME_FORMAT " -> %" + GST_TIME_FORMAT " running time", + GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time)); + *outbuf = gst_buffer_make_writable (buf); + GST_BUFFER_PTS (*outbuf) = time; + + dts_sign = gst_segment_to_running_time_full (&cdata->segment, + GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf), &abs_dts); + buf_dts = GST_BUFFER_DTS (*outbuf); + if (dts_sign > 0) { + GST_BUFFER_DTS (*outbuf) = abs_dts; + GST_COLLECT_PADS_DTS (cdata) = abs_dts; + } else if (dts_sign < 0) { + GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE; + GST_COLLECT_PADS_DTS (cdata) = -((gint64) abs_dts); + } else { + GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE; + GST_COLLECT_PADS_DTS (cdata) = GST_CLOCK_STIME_NONE; + } + + GST_LOG_OBJECT (cdata->pad, "buffer dts %" GST_TIME_FORMAT " -> %" + GST_STIME_FORMAT " running time", GST_TIME_ARGS (buf_dts), + GST_STIME_ARGS (GST_COLLECT_PADS_DTS (cdata))); + } + + return GST_FLOW_OK; +} + +/** + * gst_collect_pads_set_clip_function: + * @pads: the collectpads to use + * @clipfunc: (scope call): clip function to install + * @user_data: user data to pass to @clip_func + * + * Install a clipping function that is called right after a buffer is received + * on a pad managed by @pads. See #GstCollectPadsClipFunction for more info. + */ +void +gst_collect_pads_set_clip_function (GstCollectPads * pads, + GstCollectPadsClipFunction clipfunc, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + pads->priv->clip_func = clipfunc; + pads->priv->clip_user_data = user_data; +} + +/** + * gst_collect_pads_set_flush_function: + * @pads: the collectpads to use + * @func: (scope call): flush function to install + * @user_data: user data to pass to @func + * + * Install a flush function that is called when the internal + * state of all pads should be flushed as part of flushing seek + * handling. See #GstCollectPadsFlushFunction for more info. + * + * Since: 1.4 + */ +void +gst_collect_pads_set_flush_function (GstCollectPads * pads, + GstCollectPadsFlushFunction func, gpointer user_data) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + pads->priv->flush_func = func; + pads->priv->flush_user_data = user_data; +} + +/** + * gst_collect_pads_add_pad: + * @pads: the collectpads to use + * @pad: (transfer none): the pad to add + * @size: the size of the returned #GstCollectData structure + * @destroy_notify: (scope async): function to be called before the returned + * #GstCollectData structure is freed + * @lock: whether to lock this pad in usual waiting state + * + * Add a pad to the collection of collect pads. The pad has to be + * a sinkpad. The refcount of the pad is incremented. Use + * gst_collect_pads_remove_pad() to remove the pad from the collection + * again. + * + * You specify a size for the returned #GstCollectData structure + * so that you can use it to store additional information. + * + * You can also specify a #GstCollectDataDestroyNotify that will be called + * just before the #GstCollectData structure is freed. It is passed the + * pointer to the structure and should free any custom memory and resources + * allocated for it. + * + * Keeping a pad locked in waiting state is only relevant when using + * the default collection algorithm (providing the oldest buffer). + * It ensures a buffer must be available on this pad for a collection + * to take place. This is of typical use to a muxer element where + * non-subtitle streams should always be in waiting state, + * e.g. to assure that caps information is available on all these streams + * when initial headers have to be written. + * + * The pad will be automatically activated in push mode when @pads is + * started. + * + * MT safe. + * + * Returns: (nullable) (transfer none): a new #GstCollectData to identify the + * new pad. Or %NULL if wrong parameters are supplied. + */ +GstCollectData * +gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size, + GstCollectDataDestroyNotify destroy_notify, gboolean lock) +{ + GstCollectData *data; + + g_return_val_if_fail (pads != NULL, NULL); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); + g_return_val_if_fail (pad != NULL, NULL); + g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL); + g_return_val_if_fail (size >= sizeof (GstCollectData), NULL); + + GST_DEBUG_OBJECT (pads, "adding pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + data = g_malloc0 (size); + data->priv = g_new0 (GstCollectDataPrivate, 1); + data->collect = pads; + data->pad = gst_object_ref (pad); + data->buffer = NULL; + data->pos = 0; + gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED); + data->state = GST_COLLECT_PADS_STATE_WAITING; + data->state |= lock ? GST_COLLECT_PADS_STATE_LOCKED : 0; + data->priv->refcount = 1; + data->priv->destroy_notify = destroy_notify; + data->ABI.abi.dts = G_MININT64; + + GST_OBJECT_LOCK (pads); + GST_OBJECT_LOCK (pad); + gst_pad_set_element_private (pad, data); + GST_OBJECT_UNLOCK (pad); + pads->priv->pad_list = g_slist_append (pads->priv->pad_list, data); + gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_chain)); + gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_event)); + gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_query)); + /* backward compat, also add to data if stopped, so that the element already + * has this in the public data list before going PAUSED (typically) + * this can only be done when we are stopped because we don't take the + * STREAM_LOCK to protect the pads->data list. */ + if (!pads->priv->started) { + pads->data = g_slist_append (pads->data, data); + ref_data (data); + } + /* activate the pad when needed */ + if (pads->priv->started) + gst_pad_set_active (pad, TRUE); + pads->priv->pad_cookie++; + GST_OBJECT_UNLOCK (pads); + + return data; +} + +static gint +find_pad (GstCollectData * data, GstPad * pad) +{ + if (data->pad == pad) + return 0; + return 1; +} + +/** + * gst_collect_pads_remove_pad: + * @pads: the collectpads to use + * @pad: (transfer none): the pad to remove + * + * Remove a pad from the collection of collect pads. This function will also + * free the #GstCollectData and all the resources that were allocated with + * gst_collect_pads_add_pad(). + * + * The pad will be deactivated automatically when @pads is stopped. + * + * MT safe. + * + * Returns: %TRUE if the pad could be removed. + */ +gboolean +gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad) +{ + GstCollectData *data; + GSList *list; + + g_return_val_if_fail (pads != NULL, FALSE); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), FALSE); + g_return_val_if_fail (pad != NULL, FALSE); + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + + GST_DEBUG_OBJECT (pads, "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + GST_OBJECT_LOCK (pads); + list = + g_slist_find_custom (pads->priv->pad_list, pad, (GCompareFunc) find_pad); + if (!list) + goto unknown_pad; + + data = (GstCollectData *) list->data; + + GST_DEBUG_OBJECT (pads, "found pad %s:%s at %p", GST_DEBUG_PAD_NAME (pad), + data); + + /* clear the stuff we configured */ + gst_pad_set_chain_function (pad, NULL); + gst_pad_set_event_function (pad, NULL); + GST_OBJECT_LOCK (pad); + gst_pad_set_element_private (pad, NULL); + GST_OBJECT_UNLOCK (pad); + + /* backward compat, also remove from data if stopped, note that this function + * can only be called when we are stopped because we don't take the + * STREAM_LOCK to protect the pads->data list. */ + if (!pads->priv->started) { + GSList *dlist; + + dlist = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad); + if (dlist) { + GstCollectData *pdata = dlist->data; + + pads->data = g_slist_delete_link (pads->data, dlist); + unref_data (pdata); + } + } + /* remove from the pad list */ + pads->priv->pad_list = g_slist_delete_link (pads->priv->pad_list, list); + pads->priv->pad_cookie++; + + /* signal waiters because something changed */ + GST_COLLECT_PADS_EVT_BROADCAST (pads); + + /* deactivate the pad when needed */ + if (!pads->priv->started) + gst_pad_set_active (pad, FALSE); + + /* clean and free the collect data */ + unref_data (data); + + GST_OBJECT_UNLOCK (pads); + + return TRUE; + +unknown_pad: + { + GST_WARNING_OBJECT (pads, "cannot remove unknown pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + GST_OBJECT_UNLOCK (pads); + return FALSE; + } +} + +/* + * Must be called with STREAM_LOCK and OBJECT_LOCK. + */ +static void +gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads, + gboolean flushing) +{ + GSList *walk = NULL; + + GST_DEBUG ("sink-pads flushing=%d", flushing); + + /* Update the pads flushing flag */ + for (walk = pads->priv->pad_list; walk; walk = g_slist_next (walk)) { + GstCollectData *cdata = walk->data; + + if (GST_IS_PAD (cdata->pad)) { + GST_OBJECT_LOCK (cdata->pad); + if (flushing) + GST_PAD_SET_FLUSHING (cdata->pad); + else + GST_PAD_UNSET_FLUSHING (cdata->pad); + if (flushing) + GST_COLLECT_PADS_STATE_SET (cdata, GST_COLLECT_PADS_STATE_FLUSHING); + else + GST_COLLECT_PADS_STATE_UNSET (cdata, GST_COLLECT_PADS_STATE_FLUSHING); + gst_collect_pads_clear (pads, cdata); + GST_OBJECT_UNLOCK (cdata->pad); + } + } + + /* inform _chain of changes */ + GST_COLLECT_PADS_EVT_BROADCAST (pads); +} + +/** + * gst_collect_pads_set_flushing: + * @pads: the collectpads to use + * @flushing: desired state of the pads + * + * Change the flushing state of all the pads in the collection. No pad + * is able to accept anymore data when @flushing is %TRUE. Calling this + * function with @flushing %FALSE makes @pads accept data again. + * Caller must ensure that downstream streaming (thread) is not blocked, + * e.g. by sending a FLUSH_START downstream. + * + * MT safe. + */ +void +gst_collect_pads_set_flushing (GstCollectPads * pads, gboolean flushing) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + /* NOTE since this eventually calls _pop, some (STREAM_)LOCK is needed here */ + GST_COLLECT_PADS_STREAM_LOCK (pads); + GST_OBJECT_LOCK (pads); + gst_collect_pads_set_flushing_unlocked (pads, flushing); + GST_OBJECT_UNLOCK (pads); + GST_COLLECT_PADS_STREAM_UNLOCK (pads); +} + +/** + * gst_collect_pads_start: + * @pads: the collectpads to use + * + * Starts the processing of data in the collect_pads. + * + * MT safe. + */ +void +gst_collect_pads_start (GstCollectPads * pads) +{ + GSList *collected; + + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_DEBUG_OBJECT (pads, "starting collect pads"); + + /* make sure stop and collect cannot be called anymore */ + GST_COLLECT_PADS_STREAM_LOCK (pads); + + /* make pads streamable */ + GST_OBJECT_LOCK (pads); + + /* loop over the master pad list and reset the segment */ + collected = pads->priv->pad_list; + for (; collected; collected = g_slist_next (collected)) { + GstCollectData *data; + + data = collected->data; + gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED); + } + + gst_collect_pads_set_flushing_unlocked (pads, FALSE); + + /* Start collect pads */ + pads->priv->started = TRUE; + GST_OBJECT_UNLOCK (pads); + GST_COLLECT_PADS_STREAM_UNLOCK (pads); +} + +/** + * gst_collect_pads_stop: + * @pads: the collectpads to use + * + * Stops the processing of data in the collect_pads. this function + * will also unblock any blocking operations. + * + * MT safe. + */ +void +gst_collect_pads_stop (GstCollectPads * pads) +{ + GSList *collected; + + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + + GST_DEBUG_OBJECT (pads, "stopping collect pads"); + + /* make sure collect and start cannot be called anymore */ + GST_COLLECT_PADS_STREAM_LOCK (pads); + + /* make pads not accept data anymore */ + GST_OBJECT_LOCK (pads); + gst_collect_pads_set_flushing_unlocked (pads, TRUE); + + /* Stop collect pads */ + pads->priv->started = FALSE; + pads->priv->eospads = 0; + pads->priv->queuedpads = 0; + + /* loop over the master pad list and flush buffers */ + collected = pads->priv->pad_list; + for (; collected; collected = g_slist_next (collected)) { + GstCollectData *data; + GstBuffer **buffer_p; + + data = collected->data; + if (data->buffer) { + buffer_p = &data->buffer; + gst_buffer_replace (buffer_p, NULL); + data->pos = 0; + } + GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS); + } + + if (pads->priv->earliest_data) + unref_data (pads->priv->earliest_data); + pads->priv->earliest_data = NULL; + pads->priv->earliest_time = GST_CLOCK_TIME_NONE; + + GST_OBJECT_UNLOCK (pads); + /* Wake them up so they can end the chain functions. */ + GST_COLLECT_PADS_EVT_BROADCAST (pads); + + GST_COLLECT_PADS_STREAM_UNLOCK (pads); +} + +/** + * gst_collect_pads_peek: + * @pads: the collectpads to peek + * @data: the data to use + * + * Peek at the buffer currently queued in @data. This function + * should be called with the @pads STREAM_LOCK held, such as in the callback + * handler. + * + * MT safe. + * + * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no + * buffer is queued. should unref the buffer after usage. + */ +GstBuffer * +gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data) +{ + GstBuffer *result; + + g_return_val_if_fail (pads != NULL, NULL); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); + g_return_val_if_fail (data != NULL, NULL); + + if ((result = data->buffer)) + gst_buffer_ref (result); + + GST_DEBUG_OBJECT (pads, "Peeking at pad %s:%s: buffer=%" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (data->pad), result); + + return result; +} + +/** + * gst_collect_pads_pop: + * @pads: the collectpads to pop + * @data: the data to use + * + * Pop the buffer currently queued in @data. This function + * should be called with the @pads STREAM_LOCK held, such as in the callback + * handler. + * + * MT safe. + * + * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no + * buffer was queued. You should unref the buffer after usage. + */ +GstBuffer * +gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data) +{ + GstBuffer *result; + + g_return_val_if_fail (pads != NULL, NULL); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); + g_return_val_if_fail (data != NULL, NULL); + + if ((result = data->buffer)) { + data->buffer = NULL; + data->pos = 0; + /* one less pad with queued data now */ + if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) + pads->priv->queuedpads--; + } + + GST_COLLECT_PADS_EVT_BROADCAST (pads); + + GST_DEBUG_OBJECT (pads, "Pop buffer on pad %s:%s: buffer=%" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (data->pad), result); + + return result; +} + +/* pop and unref the currently queued buffer, should be called with STREAM_LOCK + * held */ +static void +gst_collect_pads_clear (GstCollectPads * pads, GstCollectData * data) +{ + GstBuffer *buf; + + if ((buf = gst_collect_pads_pop (pads, data))) + gst_buffer_unref (buf); +} + +/** + * gst_collect_pads_available: + * @pads: the collectpads to query + * + * Query how much bytes can be read from each queued buffer. This means + * that the result of this call is the maximum number of bytes that can + * be read from each of the pads. + * + * This function should be called with @pads STREAM_LOCK held, such as + * in the callback. + * + * MT safe. + * + * Returns: The maximum number of bytes queued on all pads. This function + * returns 0 if a pad has no queued buffer. + */ +/* we might pre-calculate this in some struct field, + * but would then have to maintain this in _chain and particularly _pop, etc, + * even if element is never interested in this information */ +guint +gst_collect_pads_available (GstCollectPads * pads) +{ + GSList *collected; + guint result = G_MAXUINT; + + g_return_val_if_fail (pads != NULL, 0); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0); + + collected = pads->data; + for (; collected; collected = g_slist_next (collected)) { + GstCollectData *pdata; + GstBuffer *buffer; + gint size; + + pdata = (GstCollectData *) collected->data; + + /* ignore pad with EOS */ + if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (pdata, + GST_COLLECT_PADS_STATE_EOS))) { + GST_DEBUG_OBJECT (pads, "pad %p is EOS", pdata); + continue; + } + + /* an empty buffer without EOS is weird when we get here.. */ + if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) { + GST_WARNING_OBJECT (pads, "pad %p has no buffer", pdata); + goto not_filled; + } + + /* this is the size left of the buffer */ + size = gst_buffer_get_size (buffer) - pdata->pos; + GST_DEBUG_OBJECT (pads, "pad %p has %d bytes left", pdata, size); + + /* need to return the min of all available data */ + if (size < result) + result = size; + } + /* nothing changed, all must be EOS then, return 0 */ + if (G_UNLIKELY (result == G_MAXUINT)) + result = 0; + + return result; + +not_filled: + { + return 0; + } +} + +/** + * gst_collect_pads_flush: + * @pads: the collectpads to query + * @data: the data to use + * @size: the number of bytes to flush + * + * Flush @size bytes from the pad @data. + * + * This function should be called with @pads STREAM_LOCK held, such as + * in the callback. + * + * MT safe. + * + * Returns: The number of bytes flushed This can be less than @size and + * is 0 if the pad was end-of-stream. + */ +guint +gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data, + guint size) +{ + guint flushsize; + gsize bsize; + GstBuffer *buffer; + + g_return_val_if_fail (pads != NULL, 0); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0); + g_return_val_if_fail (data != NULL, 0); + + /* no buffer, must be EOS */ + if ((buffer = data->buffer) == NULL) + return 0; + + bsize = gst_buffer_get_size (buffer); + + /* this is what we can flush at max */ + flushsize = MIN (size, bsize - data->pos); + + data->pos += size; + + if (data->pos >= bsize) + /* _clear will also reset data->pos to 0 */ + gst_collect_pads_clear (pads, data); + + return flushsize; +} + +/** + * gst_collect_pads_read_buffer: + * @pads: the collectpads to query + * @data: the data to use + * @size: the number of bytes to read + * + * Get a subbuffer of @size bytes from the given pad @data. + * + * This function should be called with @pads STREAM_LOCK held, such as in the + * callback. + * + * MT safe. + * + * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can + * be less that requested. A return of %NULL signals that the pad is + * end-of-stream. Unref the buffer after use. + */ +GstBuffer * +gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, + guint size) +{ + guint readsize, buf_size; + GstBuffer *buffer; + + g_return_val_if_fail (pads != NULL, NULL); + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); + g_return_val_if_fail (data != NULL, NULL); + + /* no buffer, must be EOS */ + if ((buffer = data->buffer) == NULL) + return NULL; + + buf_size = gst_buffer_get_size (buffer); + readsize = MIN (size, buf_size - data->pos); + + return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos, + readsize); +} + +/** + * gst_collect_pads_take_buffer: + * @pads: the collectpads to query + * @data: the data to use + * @size: the number of bytes to read + * + * Get a subbuffer of @size bytes from the given pad @data. Flushes the amount + * of read bytes. + * + * This function should be called with @pads STREAM_LOCK held, such as in the + * callback. + * + * MT safe. + * + * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can + * be less that requested. A return of %NULL signals that the pad is + * end-of-stream. Unref the buffer after use. + */ +GstBuffer * +gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data, + guint size) +{ + GstBuffer *buffer = gst_collect_pads_read_buffer (pads, data, size); + + if (buffer) { + gst_collect_pads_flush (pads, data, gst_buffer_get_size (buffer)); + } + return buffer; +} + +/** + * gst_collect_pads_set_waiting: + * @pads: the collectpads + * @data: the data to use + * @waiting: boolean indicating whether this pad should operate + * in waiting or non-waiting mode + * + * Sets a pad to waiting or non-waiting mode, if at least this pad + * has not been created with locked waiting state, + * in which case nothing happens. + * + * This function should be called with @pads STREAM_LOCK held, such as + * in the callback. + * + * MT safe. + */ +void +gst_collect_pads_set_waiting (GstCollectPads * pads, GstCollectData * data, + gboolean waiting) +{ + g_return_if_fail (pads != NULL); + g_return_if_fail (GST_IS_COLLECT_PADS (pads)); + g_return_if_fail (data != NULL); + + GST_DEBUG_OBJECT (pads, "Setting pad %s to waiting %d, locked %d", + GST_PAD_NAME (data->pad), waiting, + GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_LOCKED)); + + /* Do something only on a change and if not locked */ + if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_LOCKED) && + (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING) != + ! !waiting)) { + /* Set waiting state for this pad */ + if (waiting) + GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_WAITING); + else + GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_WAITING); + /* Update number of queued pads if needed */ + if (!data->buffer && + !GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS)) { + if (waiting) + pads->priv->queuedpads--; + else + pads->priv->queuedpads++; + } + + /* signal waiters because something changed */ + GST_COLLECT_PADS_EVT_BROADCAST (pads); + } +} + +/* see if pads were added or removed and update our stats. Any pad + * added after releasing the LOCK will get collected in the next + * round. + * + * We can do a quick check by checking the cookies, that get changed + * whenever the pad list is updated. + * + * Must be called with STREAM_LOCK. + */ +static void +gst_collect_pads_check_pads (GstCollectPads * pads) +{ + /* the master list and cookie are protected with LOCK */ + GST_OBJECT_LOCK (pads); + if (G_UNLIKELY (pads->priv->pad_cookie != pads->priv->cookie)) { + GSList *collected; + + /* clear list and stats */ + g_slist_foreach (pads->data, (GFunc) unref_data, NULL); + g_slist_free (pads->data); + pads->data = NULL; + pads->priv->numpads = 0; + pads->priv->queuedpads = 0; + pads->priv->eospads = 0; + if (pads->priv->earliest_data) + unref_data (pads->priv->earliest_data); + pads->priv->earliest_data = NULL; + pads->priv->earliest_time = GST_CLOCK_TIME_NONE; + + /* loop over the master pad list */ + collected = pads->priv->pad_list; + for (; collected; collected = g_slist_next (collected)) { + GstCollectData *data; + + /* update the stats */ + pads->priv->numpads++; + data = collected->data; + if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS)) + pads->priv->eospads++; + else if (data->buffer || !GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_WAITING)) + pads->priv->queuedpads++; + + /* add to the list of pads to collect */ + ref_data (data); + /* preserve order of adding/requesting pads */ + pads->data = g_slist_append (pads->data, data); + } + /* and update the cookie */ + pads->priv->cookie = pads->priv->pad_cookie; + } + GST_OBJECT_UNLOCK (pads); +} + +/* checks if all the pads are collected and call the collectfunction + * + * Should be called with STREAM_LOCK. + * + * Returns: The #GstFlowReturn of collection. + */ +static GstFlowReturn +gst_collect_pads_check_collected (GstCollectPads * pads) +{ + GstFlowReturn flow_ret = GST_FLOW_OK; + GstCollectPadsFunction func; + gpointer user_data; + + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR); + + GST_OBJECT_LOCK (pads); + func = pads->priv->func; + user_data = pads->priv->user_data; + GST_OBJECT_UNLOCK (pads); + + g_return_val_if_fail (pads->priv->func != NULL, GST_FLOW_NOT_SUPPORTED); + + /* check for new pads, update stats etc.. */ + gst_collect_pads_check_pads (pads); + + if (G_UNLIKELY (pads->priv->eospads == pads->priv->numpads)) { + /* If all our pads are EOS just collect once to let the element + * do its final EOS handling. */ + GST_DEBUG_OBJECT (pads, "All active pads (%d) are EOS, calling %s", + pads->priv->numpads, GST_DEBUG_FUNCPTR_NAME (func)); + + if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking, + TRUE, FALSE))) { + GST_INFO_OBJECT (pads, "finished seeking"); + } + do { + flow_ret = func (pads, user_data); + } while (flow_ret == GST_FLOW_OK); + } else { + gboolean collected = FALSE; + + /* We call the collected function as long as our condition matches. */ + while (((pads->priv->queuedpads + pads->priv->eospads) >= + pads->priv->numpads)) { + GST_DEBUG_OBJECT (pads, + "All active pads (%d + %d >= %d) have data, " "calling %s", + pads->priv->queuedpads, pads->priv->eospads, pads->priv->numpads, + GST_DEBUG_FUNCPTR_NAME (func)); + + if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking, + TRUE, FALSE))) { + GST_INFO_OBJECT (pads, "finished seeking"); + } + flow_ret = func (pads, user_data); + collected = TRUE; + + /* break on error */ + if (flow_ret != GST_FLOW_OK) + break; + /* Don't keep looping after telling the element EOS or flushing */ + if (pads->priv->queuedpads == 0) + break; + } + if (!collected) + GST_DEBUG_OBJECT (pads, "Not all active pads (%d) have data, continuing", + pads->priv->numpads); + } + return flow_ret; +} + + +/* General overview: + * - only pad with a buffer can determine earliest_data (and earliest_time) + * - only segment info determines (non-)waiting state + * - ? perhaps use _stream_time for comparison + * (which muxers might have use as well ?) + */ + +/* + * Function to recalculate the waiting state of all pads. + * + * Must be called with STREAM_LOCK. + * + * Returns %TRUE if a pad was set to waiting + * (from non-waiting state). + */ +static gboolean +gst_collect_pads_recalculate_waiting (GstCollectPads * pads) +{ + GSList *collected; + gboolean result = FALSE; + + /* If earliest time is not known, there is nothing to do. */ + if (pads->priv->earliest_data == NULL) + return FALSE; + + for (collected = pads->data; collected; collected = g_slist_next (collected)) { + GstCollectData *data = (GstCollectData *) collected->data; + int cmp_res; + GstClockTime comp_time; + + /* check if pad has a segment */ + if (data->segment.format == GST_FORMAT_UNDEFINED) { + GST_WARNING_OBJECT (pads, + "GstCollectPads has no time segment, assuming 0 based."); + gst_segment_init (&data->segment, GST_FORMAT_TIME); + GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT); + } + + /* check segment format */ + if (data->segment.format != GST_FORMAT_TIME) { + GST_ERROR_OBJECT (pads, "GstCollectPads can handle only time segments."); + continue; + } + + /* check if the waiting state should be changed */ + comp_time = data->segment.position; + cmp_res = pads->priv->compare_func (pads, data, comp_time, + pads->priv->earliest_data, pads->priv->earliest_time, + pads->priv->compare_user_data); + if (cmp_res > 0) + /* stop waiting */ + gst_collect_pads_set_waiting (pads, data, FALSE); + else { + if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) { + /* start waiting */ + gst_collect_pads_set_waiting (pads, data, TRUE); + result = TRUE; + } + } + } + + return result; +} + +/** + * gst_collect_pads_find_best_pad: + * @pads: the collectpads to use + * @data: returns the collectdata for earliest data + * @time: returns the earliest available buffertime + * + * Find the oldest/best pad, i.e. pad holding the oldest buffer and + * and return the corresponding #GstCollectData and buffertime. + * + * This function should be called with STREAM_LOCK held, + * such as in the callback. + */ +static void +gst_collect_pads_find_best_pad (GstCollectPads * pads, + GstCollectData ** data, GstClockTime * time) +{ + GSList *collected; + GstCollectData *best = NULL; + GstClockTime best_time = GST_CLOCK_TIME_NONE; + + g_return_if_fail (data != NULL); + g_return_if_fail (time != NULL); + + for (collected = pads->data; collected; collected = g_slist_next (collected)) { + GstBuffer *buffer; + GstCollectData *data = (GstCollectData *) collected->data; + GstClockTime timestamp; + + buffer = gst_collect_pads_peek (pads, data); + /* if we have a buffer check if it is better then the current best one */ + if (buffer != NULL) { + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + gst_buffer_unref (buffer); + if (best == NULL || pads->priv->compare_func (pads, data, timestamp, + best, best_time, pads->priv->compare_user_data) < 0) { + best = data; + best_time = timestamp; + } + } + } + + /* set earliest time */ + *data = best; + *time = best_time; + + GST_DEBUG_OBJECT (pads, "best pad %s, best time %" GST_TIME_FORMAT, + best ? GST_PAD_NAME (((GstCollectData *) best)->pad) : "(nil)", + GST_TIME_ARGS (best_time)); +} + +/* + * Function to recalculate earliest_data and earliest_timestamp. This also calls + * gst_collect_pads_recalculate_waiting + * + * Must be called with STREAM_LOCK. + */ +static gboolean +gst_collect_pads_recalculate_full (GstCollectPads * pads) +{ + if (pads->priv->earliest_data) + unref_data (pads->priv->earliest_data); + gst_collect_pads_find_best_pad (pads, &pads->priv->earliest_data, + &pads->priv->earliest_time); + if (pads->priv->earliest_data) + ref_data (pads->priv->earliest_data); + return gst_collect_pads_recalculate_waiting (pads); +} + +/* + * Default collect callback triggered when #GstCollectPads gathered all data. + * + * Called with STREAM_LOCK. + */ +static GstFlowReturn +gst_collect_pads_default_collected (GstCollectPads * pads, gpointer user_data) +{ + GstCollectData *best = NULL; + GstBuffer *buffer; + GstFlowReturn ret = GST_FLOW_OK; + GstCollectPadsBufferFunction func; + gpointer buffer_user_data; + + g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), GST_FLOW_ERROR); + + GST_OBJECT_LOCK (pads); + func = pads->priv->buffer_func; + buffer_user_data = pads->priv->buffer_user_data; + GST_OBJECT_UNLOCK (pads); + + g_return_val_if_fail (func != NULL, GST_FLOW_NOT_SUPPORTED); + + /* Find the oldest pad at all cost */ + if (gst_collect_pads_recalculate_full (pads)) { + /* waiting was switched on, + * so give another thread a chance to deliver a possibly + * older buffer; don't charge on yet with the current oldest */ + ret = GST_FLOW_OK; + goto done; + } + + best = pads->priv->earliest_data; + + /* No data collected means EOS. */ + if (G_UNLIKELY (best == NULL)) { + ret = func (pads, best, NULL, buffer_user_data); + if (ret == GST_FLOW_OK) + ret = GST_FLOW_EOS; + goto done; + } + + /* make sure that the pad we take a buffer from is waiting; + * otherwise popping a buffer will seem not to have happened + * and collectpads can get into a busy loop */ + gst_collect_pads_set_waiting (pads, best, TRUE); + + /* Send buffer */ + buffer = gst_collect_pads_pop (pads, best); + ret = func (pads, best, buffer, buffer_user_data); + + /* maybe non-waiting was forced to waiting above due to + * newsegment events coming too sparsely, + * so re-check to restore state to avoid hanging/waiting */ + gst_collect_pads_recalculate_full (pads); + +done: + return ret; +} + +/* + * Default timestamp compare function. + */ +static gint +gst_collect_pads_default_compare_func (GstCollectPads * pads, + GstCollectData * data1, GstClockTime timestamp1, + GstCollectData * data2, GstClockTime timestamp2, gpointer user_data) +{ + + GST_LOG_OBJECT (pads, "comparing %" GST_TIME_FORMAT + " and %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp1), + GST_TIME_ARGS (timestamp2)); + /* non-valid timestamps go first as they are probably headers or so */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp1))) + return GST_CLOCK_TIME_IS_VALID (timestamp2) ? -1 : 0; + + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp2))) + return 1; + + /* compare timestamp */ + if (timestamp1 < timestamp2) + return -1; + + if (timestamp1 > timestamp2) + return 1; + + return 0; +} + +/* called with STREAM_LOCK */ +static void +gst_collect_pads_handle_position_update (GstCollectPads * pads, + GstCollectData * data, GstClockTime new_pos) +{ + gint cmp_res; + + /* If oldest time is not known, or current pad got newsegment; + * recalculate the state */ + if (!pads->priv->earliest_data || pads->priv->earliest_data == data) { + gst_collect_pads_recalculate_full (pads); + goto exit; + } + + /* Check if the waiting state of the pad should change. */ + cmp_res = + pads->priv->compare_func (pads, data, new_pos, + pads->priv->earliest_data, pads->priv->earliest_time, + pads->priv->compare_user_data); + + if (cmp_res > 0) + /* Stop waiting */ + gst_collect_pads_set_waiting (pads, data, FALSE); + +exit: + return; + +} + +static GstClockTime +gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data, + GstClockTime time) +{ + GstClockTime otime = time; + GstBuffer *in, *out = NULL; + + if (pads->priv->clip_func) { + in = gst_buffer_new (); + GST_BUFFER_PTS (in) = time; + GST_BUFFER_DTS (in) = GST_CLOCK_TIME_NONE; + pads->priv->clip_func (pads, data, in, &out, pads->priv->clip_user_data); + if (out) { + otime = GST_BUFFER_PTS (out); + gst_buffer_unref (out); + } else { + /* FIXME should distinguish between ahead or after segment, + * let's assume after segment and use some large time ... */ + otime = G_MAXINT64 / 2; + } + } + + return otime; +} + +/** + * gst_collect_pads_event_default: + * @pads: the collectpads to use + * @data: collect data of corresponding pad + * @event: event being processed + * @discard: process but do not send event downstream + * + * Default #GstCollectPads event handling that elements should always + * chain up to to ensure proper operation. Element might however indicate + * event should not be forwarded downstream. + */ +gboolean +gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, + GstEvent * event, gboolean discard) +{ + gboolean res = TRUE; + GstCollectPadsBufferFunction buffer_func; + GstObject *parent; + GstPad *pad; + + GST_OBJECT_LOCK (pads); + buffer_func = pads->priv->buffer_func; + GST_OBJECT_UNLOCK (pads); + + pad = data->pad; + parent = GST_OBJECT_PARENT (pad); + + GST_DEBUG_OBJECT (pad, "Got '%s' event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + { + if (g_atomic_int_get (&pads->priv->seeking)) { + /* drop all but the first FLUSH_STARTs when seeking */ + if (!g_atomic_int_compare_and_exchange (&pads-> + priv->pending_flush_start, TRUE, FALSE)) + goto eat; + + /* unblock collect pads */ + gst_pad_event_default (pad, parent, event); + event = NULL; + + GST_COLLECT_PADS_STREAM_LOCK (pads); + /* Start flushing. We never call gst_collect_pads_set_flushing (FALSE), we + * instead wait until each pad gets its FLUSH_STOP and let that reset the pad to + * non-flushing (which happens in gst_collect_pads_event_default). + */ + gst_collect_pads_set_flushing (pads, TRUE); + + if (pads->priv->flush_func) + pads->priv->flush_func (pads, pads->priv->flush_user_data); + + g_atomic_int_set (&pads->priv->pending_flush_stop, TRUE); + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + goto eat; + } else { + /* forward event to unblock check_collected */ + GST_DEBUG_OBJECT (pad, "forwarding flush start"); + if (!(res = gst_pad_event_default (pad, parent, event))) { + GST_WARNING_OBJECT (pad, "forwarding flush start failed"); + } + event = NULL; + + /* now unblock the chain function. + * no cond per pad, so they all unblock, + * non-flushing block again */ + GST_COLLECT_PADS_STREAM_LOCK (pads); + GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_FLUSHING); + gst_collect_pads_clear (pads, data); + + /* cater for possible default muxing functionality */ + if (buffer_func) { + /* restore to initial state */ + gst_collect_pads_set_waiting (pads, data, TRUE); + /* if the current pad is affected, reset state, recalculate later */ + if (pads->priv->earliest_data == data) { + unref_data (data); + pads->priv->earliest_data = NULL; + pads->priv->earliest_time = GST_CLOCK_TIME_NONE; + } + } + + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + goto eat; + } + } + case GST_EVENT_FLUSH_STOP: + { + /* flush the 1 buffer queue */ + GST_COLLECT_PADS_STREAM_LOCK (pads); + GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_FLUSHING); + gst_collect_pads_clear (pads, data); + /* we need new segment info after the flush */ + gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED); + GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT); + /* if the pad was EOS, remove the EOS flag and + * decrement the number of eospads */ + if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_EOS))) { + if (!GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_WAITING)) + pads->priv->queuedpads++; + if (!g_atomic_int_get (&pads->priv->seeking)) { + pads->priv->eospads--; + } + GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS); + } + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + if (g_atomic_int_get (&pads->priv->seeking)) { + if (g_atomic_int_compare_and_exchange (&pads->priv->pending_flush_stop, + TRUE, FALSE)) + goto forward; + else + goto eat; + } else { + goto forward; + } + } + case GST_EVENT_EOS: + { + GST_COLLECT_PADS_STREAM_LOCK (pads); + /* if the pad was not EOS, make it EOS and so we + * have one more eospad */ + if (G_LIKELY (!GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_EOS))) { + GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_EOS); + if (!GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_WAITING)) + pads->priv->queuedpads--; + pads->priv->eospads++; + } + /* check if we need collecting anything, we ignore the result. */ + gst_collect_pads_check_collected (pads); + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + goto eat; + } + case GST_EVENT_SEGMENT: + { + GstSegment seg; + + GST_COLLECT_PADS_STREAM_LOCK (pads); + + gst_event_copy_segment (event, &seg); + + GST_DEBUG_OBJECT (data->pad, "got segment %" GST_SEGMENT_FORMAT, &seg); + + /* default collection can not handle other segment formats than time */ + if (buffer_func && seg.format != GST_FORMAT_TIME) { + GST_WARNING_OBJECT (pads, "GstCollectPads default collecting " + "can only handle time segments. Non time segment ignored."); + goto newsegment_done; + } + + /* need to update segment first */ + data->segment = seg; + GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT); + + /* now we can use for e.g. running time */ + seg.position = + gst_collect_pads_clip_time (pads, data, seg.start + seg.offset); + /* update again */ + data->segment = seg; + + /* default muxing functionality */ + if (!buffer_func) + goto newsegment_done; + + gst_collect_pads_handle_position_update (pads, data, seg.position); + + newsegment_done: + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + /* we must not forward this event since multiple segments will be + * accumulated and this is certainly not what we want. */ + goto eat; + } + case GST_EVENT_GAP: + { + GstClockTime start, duration; + + GST_COLLECT_PADS_STREAM_LOCK (pads); + + gst_event_parse_gap (event, &start, &duration); + /* FIXME, handle reverse playback case */ + if (GST_CLOCK_TIME_IS_VALID (duration)) + start += duration; + /* we do not expect another buffer until after gap, + * so that is our position now */ + data->segment.position = gst_collect_pads_clip_time (pads, data, start); + + gst_collect_pads_handle_position_update (pads, data, + data->segment.position); + + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + goto eat; + } + case GST_EVENT_STREAM_START: + /* drop stream start events, element must create its own start event, + * we can't just forward the first random stream start event we get */ + goto eat; + case GST_EVENT_CAPS: + goto eat; + default: + /* forward other events */ + goto forward; + } + +eat: + GST_DEBUG_OBJECT (pads, "dropping event: %" GST_PTR_FORMAT, event); + if (event) + gst_event_unref (event); + return res; + +forward: + if (discard) + goto eat; + else { + GST_DEBUG_OBJECT (pads, "forward event: %" GST_PTR_FORMAT, event); + return gst_pad_event_default (pad, parent, event); + } +} + +typedef struct +{ + GstEvent *event; + gboolean result; +} EventData; + +static gboolean +event_forward_func (GstPad * pad, EventData * data) +{ + gboolean ret = TRUE; + GstPad *peer = gst_pad_get_peer (pad); + + if (peer) { + ret = gst_pad_send_event (peer, gst_event_ref (data->event)); + gst_object_unref (peer); + } + + data->result &= ret; + /* Always send to all pads */ + return FALSE; +} + +static gboolean +forward_event_to_all_sinkpads (GstPad * srcpad, GstEvent * event) +{ + EventData data; + + data.event = event; + data.result = TRUE; + + gst_pad_forward (srcpad, (GstPadForwardFunction) event_forward_func, &data); + + gst_event_unref (event); + + return data.result; +} + +/** + * gst_collect_pads_src_event_default: + * @pads: the #GstCollectPads to use + * @pad: src #GstPad that received the event + * @event: event being processed + * + * Default #GstCollectPads event handling for the src pad of elements. + * Elements can chain up to this to let flushing seek event handling + * be done by #GstCollectPads. + * + * Since: 1.4 + */ +gboolean +gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad, + GstEvent * event) +{ + GstObject *parent; + gboolean res = TRUE; + + parent = GST_OBJECT_PARENT (pad); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + GstSeekFlags flags; + + pads->priv->eospads = 0; + + GST_INFO_OBJECT (pads, "starting seek"); + + gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); + if (flags & GST_SEEK_FLAG_FLUSH) { + g_atomic_int_set (&pads->priv->seeking, TRUE); + g_atomic_int_set (&pads->priv->pending_flush_start, TRUE); + /* forward the seek upstream */ + res = forward_event_to_all_sinkpads (pad, event); + event = NULL; + if (!res) { + g_atomic_int_set (&pads->priv->seeking, FALSE); + g_atomic_int_set (&pads->priv->pending_flush_start, FALSE); + } + } + + GST_INFO_OBJECT (pads, "seek done, result: %d", res); + + break; + } + default: + break; + } + + if (event) + res = gst_pad_event_default (pad, parent, event); + + return res; +} + +static gboolean +gst_collect_pads_event_default_internal (GstCollectPads * pads, + GstCollectData * data, GstEvent * event, gpointer user_data) +{ + return gst_collect_pads_event_default (pads, data, event, FALSE); +} + +static gboolean +gst_collect_pads_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = FALSE, need_unlock = FALSE; + GstCollectData *data; + GstCollectPads *pads; + GstCollectPadsEventFunction event_func; + gpointer event_user_data; + + /* some magic to get the managing collect_pads */ + GST_OBJECT_LOCK (pad); + data = (GstCollectData *) gst_pad_get_element_private (pad); + if (G_UNLIKELY (data == NULL)) + goto pad_removed; + ref_data (data); + GST_OBJECT_UNLOCK (pad); + + res = FALSE; + + pads = data->collect; + + GST_DEBUG_OBJECT (data->pad, "Got %s event on sink pad", + GST_EVENT_TYPE_NAME (event)); + + GST_OBJECT_LOCK (pads); + event_func = pads->priv->event_func; + event_user_data = pads->priv->event_user_data; + GST_OBJECT_UNLOCK (pads); + + if (GST_EVENT_IS_SERIALIZED (event)) { + GST_COLLECT_PADS_STREAM_LOCK (pads); + need_unlock = TRUE; + } + + if (G_LIKELY (event_func)) { + res = event_func (pads, data, event, event_user_data); + } + + if (need_unlock) + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + unref_data (data); + return res; + + /* ERRORS */ +pad_removed: + { + GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + +/** + * gst_collect_pads_query_default: + * @pads: the collectpads to use + * @data: collect data of corresponding pad + * @query: query being processed + * @discard: process but do not send event downstream + * + * Default #GstCollectPads query handling that elements should always + * chain up to to ensure proper operation. Element might however indicate + * query should not be forwarded downstream. + */ +gboolean +gst_collect_pads_query_default (GstCollectPads * pads, GstCollectData * data, + GstQuery * query, gboolean discard) +{ + gboolean res = TRUE; + GstObject *parent; + GstPad *pad; + + pad = data->pad; + parent = GST_OBJECT_PARENT (pad); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING: + { + GstFormat format; + + /* don't pass it along as some (file)sink might claim it does + * whereas with a collectpads in between that will not likely work */ + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + gst_query_set_seeking (query, format, FALSE, 0, -1); + res = TRUE; + discard = TRUE; + break; + } + default: + break; + } + + if (!discard) + return gst_pad_query_default (pad, parent, query); + else + return res; +} + +static gboolean +gst_collect_pads_query_default_internal (GstCollectPads * pads, + GstCollectData * data, GstQuery * query, gpointer user_data) +{ + return gst_collect_pads_query_default (pads, data, query, FALSE); +} + +static gboolean +gst_collect_pads_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = FALSE, need_unlock = FALSE; + GstCollectData *data; + GstCollectPads *pads; + GstCollectPadsQueryFunction query_func; + gpointer query_user_data; + + GST_DEBUG_OBJECT (pad, "Got %s query on sink pad", + GST_QUERY_TYPE_NAME (query)); + + /* some magic to get the managing collect_pads */ + GST_OBJECT_LOCK (pad); + data = (GstCollectData *) gst_pad_get_element_private (pad); + if (G_UNLIKELY (data == NULL)) + goto pad_removed; + ref_data (data); + GST_OBJECT_UNLOCK (pad); + + pads = data->collect; + + GST_OBJECT_LOCK (pads); + query_func = pads->priv->query_func; + query_user_data = pads->priv->query_user_data; + GST_OBJECT_UNLOCK (pads); + + if (GST_QUERY_IS_SERIALIZED (query)) { + GST_COLLECT_PADS_STREAM_LOCK (pads); + need_unlock = TRUE; + } + + if (G_LIKELY (query_func)) { + res = query_func (pads, data, query, query_user_data); + } + + if (need_unlock) + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + + unref_data (data); + return res; + + /* ERRORS */ +pad_removed: + { + GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + return FALSE; + } +} + + +/* For each buffer we receive we check if our collected condition is reached + * and if so we call the collected function. When this is done we check if + * data has been unqueued. If data is still queued we wait holding the stream + * lock to make sure no EOS event can happen while we are ready to be + * collected + */ +static GstFlowReturn +gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstCollectData *data; + GstCollectPads *pads; + GstFlowReturn ret; + GstBuffer **buffer_p; + guint32 cookie; + + GST_DEBUG ("Got buffer for pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + /* some magic to get the managing collect_pads */ + GST_OBJECT_LOCK (pad); + data = (GstCollectData *) gst_pad_get_element_private (pad); + if (G_UNLIKELY (data == NULL)) + goto no_data; + ref_data (data); + GST_OBJECT_UNLOCK (pad); + + pads = data->collect; + + GST_COLLECT_PADS_STREAM_LOCK (pads); + /* if not started, bail out */ + if (G_UNLIKELY (!pads->priv->started)) + goto not_started; + /* check if this pad is flushing */ + if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_FLUSHING))) + goto flushing; + /* pad was EOS, we can refuse this data */ + if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_EOS))) + goto eos; + + /* see if we need to clip */ + if (pads->priv->clip_func) { + GstBuffer *outbuf = NULL; + ret = + pads->priv->clip_func (pads, data, buffer, &outbuf, + pads->priv->clip_user_data); + buffer = outbuf; + + if (G_UNLIKELY (outbuf == NULL)) + goto clipped; + + if (G_UNLIKELY (ret == GST_FLOW_EOS)) + goto eos; + else if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto error; + } + + GST_DEBUG_OBJECT (pads, "Queuing buffer %p for pad %s:%s", buffer, + GST_DEBUG_PAD_NAME (pad)); + + /* One more pad has data queued */ + if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) + pads->priv->queuedpads++; + buffer_p = &data->buffer; + gst_buffer_replace (buffer_p, buffer); + + /* update segment last position if in TIME */ + if (G_LIKELY (data->segment.format == GST_FORMAT_TIME)) { + GstClockTime timestamp; + + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) + data->segment.position = timestamp; + } + + /* While we have data queued on this pad try to collect stuff */ + do { + /* Check if our collected condition is matched and call the collected + * function if it is */ + ret = gst_collect_pads_check_collected (pads); + /* when an error occurs, we want to report this back to the caller ASAP + * without having to block if the buffer was not popped */ + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto error; + + /* data was consumed, we can exit and accept new data */ + if (data->buffer == NULL) + break; + + /* Having the _INIT here means we don't care about any broadcast up to here + * (most of which occur with STREAM_LOCK held, so could not have happened + * anyway). We do care about e.g. a remove initiated broadcast as of this + * point. Putting it here also makes this thread ignores any evt it raised + * itself (as is a usual WAIT semantic). + */ + GST_COLLECT_PADS_EVT_INIT (cookie); + + /* pad could be removed and re-added */ + unref_data (data); + GST_OBJECT_LOCK (pad); + if (G_UNLIKELY ((data = gst_pad_get_element_private (pad)) == NULL)) + goto pad_removed; + ref_data (data); + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pads, "Pad %s:%s has a buffer queued, waiting", + GST_DEBUG_PAD_NAME (pad)); + + /* wait to be collected, this must happen from another thread triggered + * by the _chain function of another pad. We release the lock so we + * can get stopped or flushed as well. We can however not get EOS + * because we still hold the STREAM_LOCK. + */ + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + GST_COLLECT_PADS_EVT_WAIT (pads, cookie); + GST_COLLECT_PADS_STREAM_LOCK (pads); + + GST_DEBUG_OBJECT (pads, "Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad)); + + /* after a signal, we could be stopped */ + if (G_UNLIKELY (!pads->priv->started)) + goto not_started; + /* check if this pad is flushing */ + if (G_UNLIKELY (GST_COLLECT_PADS_STATE_IS_SET (data, + GST_COLLECT_PADS_STATE_FLUSHING))) + goto flushing; + } + while (data->buffer != NULL); + +unlock_done: + GST_COLLECT_PADS_STREAM_UNLOCK (pads); + /* data is definitely NULL if pad_removed goto was run. */ + if (data) + unref_data (data); + if (buffer) + gst_buffer_unref (buffer); + return ret; + +pad_removed: + { + GST_WARNING ("%s got removed from collectpads", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + ret = GST_FLOW_NOT_LINKED; + goto unlock_done; + } + /* ERRORS */ +no_data: + { + GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + gst_buffer_unref (buffer); + return GST_FLOW_NOT_LINKED; + } +not_started: + { + GST_DEBUG ("not started"); + gst_collect_pads_clear (pads, data); + ret = GST_FLOW_FLUSHING; + goto unlock_done; + } +flushing: + { + GST_DEBUG ("pad %s:%s is flushing", GST_DEBUG_PAD_NAME (pad)); + gst_collect_pads_clear (pads, data); + ret = GST_FLOW_FLUSHING; + goto unlock_done; + } +eos: + { + /* we should not post an error for this, just inform upstream that + * we don't expect anything anymore */ + GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad)); + ret = GST_FLOW_EOS; + goto unlock_done; + } +clipped: + { + GST_DEBUG ("clipped buffer on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + ret = GST_FLOW_OK; + goto unlock_done; + } +error: + { + /* we print the error, the element should post a reasonable error + * message for fatal errors */ + GST_DEBUG ("collect failed, reason %d (%s)", ret, gst_flow_get_name (ret)); + gst_collect_pads_clear (pads, data); + goto unlock_done; + } +} diff --git a/libs/gst/base/gstcollectpads.h b/libs/gst/base/gstcollectpads.h new file mode 100644 index 0000000..156e445 --- /dev/null +++ b/libs/gst/base/gstcollectpads.h @@ -0,0 +1,458 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * Copyright (C) 2008 Mark Nauwelaerts + * + * gstcollectpads.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_COLLECT_PADS_H__ +#define __GST_COLLECT_PADS_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_COLLECT_PADS (gst_collect_pads_get_type()) +#define GST_COLLECT_PADS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECT_PADS,GstCollectPads)) +#define GST_COLLECT_PADS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECT_PADS,GstCollectPadsClass)) +#define GST_COLLECT_PADS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_COLLECT_PADS,GstCollectPadsClass)) +#define GST_IS_COLLECT_PADS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECT_PADS)) +#define GST_IS_COLLECT_PADS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECT_PADS)) + +typedef struct _GstCollectData GstCollectData; +typedef struct _GstCollectDataPrivate GstCollectDataPrivate; +typedef struct _GstCollectPads GstCollectPads; +typedef struct _GstCollectPadsPrivate GstCollectPadsPrivate; +typedef struct _GstCollectPadsClass GstCollectPadsClass; + +/** + * GstCollectDataDestroyNotify: + * @data: the #GstCollectData that will be freed + * + * A function that will be called when the #GstCollectData will be freed. + * It is passed the pointer to the structure and should free any custom + * memory and resources allocated for it. + */ +typedef void (*GstCollectDataDestroyNotify) (GstCollectData *data); + +/** + * GstCollectPadsStateFlags: + * @GST_COLLECT_PADS_STATE_EOS: Set if collectdata's pad is EOS. + * @GST_COLLECT_PADS_STATE_FLUSHING: Set if collectdata's pad is flushing. + * @GST_COLLECT_PADS_STATE_NEW_SEGMENT: Set if collectdata's pad received a + * new_segment event. + * @GST_COLLECT_PADS_STATE_WAITING: Set if collectdata's pad must be waited + * for when collecting. + * @GST_COLLECT_PADS_STATE_LOCKED: Set collectdata's pad WAITING state must + * not be changed. + * #GstCollectPadsStateFlags indicate private state of a collectdata('s pad). + */ +typedef enum { + GST_COLLECT_PADS_STATE_EOS = 1 << 0, + GST_COLLECT_PADS_STATE_FLUSHING = 1 << 1, + GST_COLLECT_PADS_STATE_NEW_SEGMENT = 1 << 2, + GST_COLLECT_PADS_STATE_WAITING = 1 << 3, + GST_COLLECT_PADS_STATE_LOCKED = 1 << 4 +} GstCollectPadsStateFlags; + +/** + * GST_COLLECT_PADS_STATE: + * @data: a #GstCollectData. + * + * A flags word containing #GstCollectPadsStateFlags flags set + * on this collected pad. + */ +#define GST_COLLECT_PADS_STATE(data) (((GstCollectData *) data)->state) +/** + * GST_COLLECT_PADS_STATE_IS_SET: + * @data: a #GstCollectData. + * @flag: the #GstCollectPadsStateFlags to check. + * + * Gives the status of a specific flag on a collected pad. + */ +#define GST_COLLECT_PADS_STATE_IS_SET(data,flag) !!(GST_COLLECT_PADS_STATE (data) & flag) +/** + * GST_COLLECT_PADS_STATE_SET: + * @data: a #GstCollectData. + * @flag: the #GstCollectPadsStateFlags to set. + * + * Sets a state flag on a collected pad. + */ +#define GST_COLLECT_PADS_STATE_SET(data,flag) (GST_COLLECT_PADS_STATE (data) |= flag) +/** + * GST_COLLECT_PADS_STATE_UNSET: + * @data: a #GstCollectData. + * @flag: the #GstCollectPadsStateFlags to clear. + * + * Clears a state flag on a collected pad. + */ +#define GST_COLLECT_PADS_STATE_UNSET(data,flag) (GST_COLLECT_PADS_STATE (data) &= ~(flag)) + +/** + * GST_COLLECT_PADS_DTS: + * @data: A #GstCollectData. + * + * Returns the DTS that has been converted to running time when using + * gst_collect_pads_clip_running_time(). Unlike the value saved into + * the buffer, this value is of type gint64 and may be negative. This allow + * properly handling streams with frame reordering where the first DTS may + * be negative. If the initial DTS was not set, this value will be + * set to %G_MININT64. + * + * Since: 1.6 + */ +#define GST_COLLECT_PADS_DTS(data) (((GstCollectData *) data)->ABI.abi.dts) + +/** + * GST_COLLECT_PADS_DTS_IS_VALID: + * @data: A #GstCollectData. + * + * Check if running DTS value store is valid. + * + * Since: 1.6 + */ +#define GST_COLLECT_PADS_DTS_IS_VALID(data) (GST_CLOCK_STIME_IS_VALID (GST_COLLECT_PADS_DTS (data))) + +/** + * GstCollectData: + * @collect: owner #GstCollectPads + * @pad: #GstPad managed by this data + * @buffer: currently queued buffer. + * @pos: position in the buffer + * @segment: last segment received. + * @dts: the signed version of the DTS converted to running time. To access + * this memeber, use %GST_COLLECT_PADS_DTS macro. (Since 1.6) + * + * Structure used by the collect_pads. + */ +struct _GstCollectData +{ + /* with STREAM_LOCK of @collect */ + GstCollectPads *collect; + GstPad *pad; + GstBuffer *buffer; + guint pos; + GstSegment segment; + + /*< private >*/ + /* state: bitfield for easier extension; + * eos, flushing, new_segment, waiting */ + GstCollectPadsStateFlags state; + + GstCollectDataPrivate *priv; + + union { + struct { + /*< public >*/ + gint64 dts; + /*< private >*/ + } abi; + gpointer _gst_reserved[GST_PADDING]; + } ABI; +}; + +/** + * GstCollectPadsFunction: + * @pads: the #GstCollectPads that triggered the callback + * @user_data: user data passed to gst_collect_pads_set_function() + * + * A function that will be called when all pads have received data. + * + * Returns: %GST_FLOW_OK for success + */ +typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data); + +/** + * GstCollectPadsBufferFunction: + * @pads: the #GstCollectPads that triggered the callback + * @data: the #GstCollectData of pad that has received the buffer + * @buffer: (transfer full): the #GstBuffer + * @user_data: user data passed to gst_collect_pads_set_buffer_function() + * + * A function that will be called when a (considered oldest) buffer can be muxed. + * If all pads have reached EOS, this function is called with %NULL @buffer + * and %NULL @data. + * + * Returns: %GST_FLOW_OK for success + */ +typedef GstFlowReturn (*GstCollectPadsBufferFunction) (GstCollectPads *pads, GstCollectData *data, + GstBuffer *buffer, gpointer user_data); + +/** + * GstCollectPadsCompareFunction: + * @pads: the #GstCollectPads that is comparing the timestamps + * @data1: the first #GstCollectData + * @timestamp1: the first timestamp + * @data2: the second #GstCollectData + * @timestamp2: the second timestamp + * @user_data: user data passed to gst_collect_pads_set_compare_function() + * + * A function for comparing two timestamps of buffers or newsegments collected on one pad. + * + * Returns: Integer less than zero when first timestamp is deemed older than the second one. + * Zero if the timestamps are deemed equally old. + * Integer greater than zero when second timestamp is deemed older than the first one. + */ +typedef gint (*GstCollectPadsCompareFunction) (GstCollectPads *pads, + GstCollectData * data1, GstClockTime timestamp1, + GstCollectData * data2, GstClockTime timestamp2, + gpointer user_data); + +/** + * GstCollectPadsEventFunction: + * @pads: the #GstCollectPads that triggered the callback + * @pad: the #GstPad that received an event + * @event: the #GstEvent received + * @user_data: user data passed to gst_collect_pads_set_event_function() + * + * A function that will be called while processing an event. It takes + * ownership of the event and is responsible for chaining up (to + * gst_collect_pads_event_default()) or dropping events (such typical cases + * being handled by the default handler). + * + * Returns: %TRUE if the pad could handle the event + */ +typedef gboolean (*GstCollectPadsEventFunction) (GstCollectPads *pads, GstCollectData * pad, + GstEvent * event, gpointer user_data); + + +/** + * GstCollectPadsQueryFunction: + * @pads: the #GstCollectPads that triggered the callback + * @pad: the #GstPad that received an event + * @query: the #GstEvent received + * @user_data: user data passed to gst_collect_pads_set_query_function() + * + * A function that will be called while processing a query. It takes + * ownership of the query and is responsible for chaining up (to + * events downstream (with gst_pad_event_default()). + * + * Returns: %TRUE if the pad could handle the event + */ +typedef gboolean (*GstCollectPadsQueryFunction) (GstCollectPads *pads, GstCollectData * pad, + GstQuery * query, gpointer user_data); + +/** + * GstCollectPadsClipFunction: + * @pads: a #GstCollectPads + * @data: a #GstCollectData + * @inbuffer: (transfer full): the input #GstBuffer + * @outbuffer: (out): the output #GstBuffer + * @user_data: user data + * + * A function that will be called when @inbuffer is received on the pad managed + * by @data in the collectpad object @pads. + * + * The function should use the segment of @data and the negotiated media type on + * the pad to perform clipping of @inbuffer. + * + * This function takes ownership of @inbuffer and should output a buffer in + * @outbuffer or return %NULL in @outbuffer if the buffer should be dropped. + * + * Returns: a #GstFlowReturn that corresponds to the result of clipping. + */ +typedef GstFlowReturn (*GstCollectPadsClipFunction) (GstCollectPads *pads, GstCollectData *data, + GstBuffer *inbuffer, GstBuffer **outbuffer, + gpointer user_data); + + +/** + * GstCollectPadsFlushFunction: + * @pads: a #GstCollectPads + * @user_data: user data + * + * A function that will be called while processing a flushing seek event. + * + * The function should flush any internal state of the element and the state of + * all the pads. It should clear only the state not directly managed by the + * @pads object. It is therefore not necessary to call + * gst_collect_pads_set_flushing nor gst_collect_pads_clear from this function. + * + * Since: 1.4 + */ +typedef void (*GstCollectPadsFlushFunction) (GstCollectPads *pads, gpointer user_data); + +/** + * GST_COLLECT_PADS_GET_STREAM_LOCK: + * @pads: a #GstCollectPads + * + * Get the stream lock of @pads. The stream lock is used to coordinate and + * serialize execution among the various streams being collected, and in + * protecting the resources used to accomplish this. + */ +#define GST_COLLECT_PADS_GET_STREAM_LOCK(pads) (&((GstCollectPads *)pads)->stream_lock) +/** + * GST_COLLECT_PADS_STREAM_LOCK: + * @pads: a #GstCollectPads + * + * Lock the stream lock of @pads. + */ +#define GST_COLLECT_PADS_STREAM_LOCK(pads) g_rec_mutex_lock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads)) +/** + * GST_COLLECT_PADS_STREAM_UNLOCK: + * @pads: a #GstCollectPads + * + * Unlock the stream lock of @pads. + */ +#define GST_COLLECT_PADS_STREAM_UNLOCK(pads) g_rec_mutex_unlock(GST_COLLECT_PADS_GET_STREAM_LOCK (pads)) + +/** + * GstCollectPads: + * @data: (element-type GstBase.CollectData): #GList of #GstCollectData managed + * by this #GstCollectPads. + * + * Collectpads object. + */ +struct _GstCollectPads { + GstObject object; + + /*< public >*/ /* with LOCK and/or STREAM_LOCK */ + GSList *data; /* list of CollectData items */ + + /*< private >*/ + GRecMutex stream_lock; /* used to serialize collection among several streams */ + + GstCollectPadsPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstCollectPadsClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_BASE_API +GType gst_collect_pads_get_type (void); + +/* creating the object */ + +GST_BASE_API +GstCollectPads* gst_collect_pads_new (void); + +/* set the callbacks */ + +GST_BASE_API +void gst_collect_pads_set_function (GstCollectPads *pads, + GstCollectPadsFunction func, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_buffer_function (GstCollectPads *pads, + GstCollectPadsBufferFunction func, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_event_function (GstCollectPads *pads, + GstCollectPadsEventFunction func, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_query_function (GstCollectPads *pads, + GstCollectPadsQueryFunction func, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_compare_function (GstCollectPads *pads, + GstCollectPadsCompareFunction func, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_clip_function (GstCollectPads *pads, + GstCollectPadsClipFunction clipfunc, + gpointer user_data); +GST_BASE_API +void gst_collect_pads_set_flush_function (GstCollectPads *pads, + GstCollectPadsFlushFunction func, + gpointer user_data); + +/* pad management */ + +GST_BASE_API +GstCollectData* gst_collect_pads_add_pad (GstCollectPads *pads, GstPad *pad, guint size, + GstCollectDataDestroyNotify destroy_notify, + gboolean lock); +GST_BASE_API +gboolean gst_collect_pads_remove_pad (GstCollectPads *pads, GstPad *pad); + +/* start/stop collection */ + +GST_BASE_API +void gst_collect_pads_start (GstCollectPads *pads); + +GST_BASE_API +void gst_collect_pads_stop (GstCollectPads *pads); + +GST_BASE_API +void gst_collect_pads_set_flushing (GstCollectPads *pads, gboolean flushing); + +/* get collected buffers */ + +GST_BASE_API +GstBuffer* gst_collect_pads_peek (GstCollectPads *pads, GstCollectData *data); + +GST_BASE_API +GstBuffer* gst_collect_pads_pop (GstCollectPads *pads, GstCollectData *data); + +/* get collected bytes */ + +GST_BASE_API +guint gst_collect_pads_available (GstCollectPads *pads); + +GST_BASE_API +guint gst_collect_pads_flush (GstCollectPads *pads, GstCollectData *data, + guint size); +GST_BASE_API +GstBuffer* gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, + guint size); +GST_BASE_API +GstBuffer* gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data, + guint size); + +/* setting and unsetting waiting mode */ + +GST_BASE_API +void gst_collect_pads_set_waiting (GstCollectPads *pads, GstCollectData *data, + gboolean waiting); + +/* convenience helper */ + +GST_BASE_API +GstFlowReturn gst_collect_pads_clip_running_time (GstCollectPads * pads, + GstCollectData * cdata, + GstBuffer * buf, GstBuffer ** outbuf, + gpointer user_data); + +/* default handlers */ + +GST_BASE_API +gboolean gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, + GstEvent * event, gboolean discard); +GST_BASE_API +gboolean gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad, + GstEvent * event); +GST_BASE_API +gboolean gst_collect_pads_query_default (GstCollectPads * pads, GstCollectData * data, + GstQuery * query, gboolean discard); + + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCollectPads, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_COLLECT_PADS_H__ */ diff --git a/libs/gst/base/gstdataqueue.c b/libs/gst/base/gstdataqueue.c new file mode 100644 index 0000000..ab09cb6 --- /dev/null +++ b/libs/gst/base/gstdataqueue.c @@ -0,0 +1,812 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey + * + * gstdataqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstdataqueue + * @title: GstDataQueue + * @short_description: Threadsafe queueing object + * + * #GstDataQueue is an object that handles threadsafe queueing of objects. It + * also provides size-related functionality. This object should be used for + * any #GstElement that wishes to provide some sort of queueing functionality. + */ + +#include +#include "string.h" +#include "gstdataqueue.h" +#include "gstqueuearray.h" +#include "gst/glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (data_queue_debug); +#define GST_CAT_DEFAULT (data_queue_debug) +GST_DEBUG_CATEGORY_STATIC (data_queue_dataflow); + + +/* Queue signals and args */ +enum +{ + SIGNAL_EMPTY, + SIGNAL_FULL, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_CUR_LEVEL_VISIBLE, + PROP_CUR_LEVEL_BYTES, + PROP_CUR_LEVEL_TIME + /* FILL ME */ +}; + +struct _GstDataQueuePrivate +{ + /* the array of data we're keeping our grubby hands on */ + GstQueueArray *queue; + + GstDataQueueSize cur_level; /* size of the queue */ + GstDataQueueCheckFullFunction checkfull; /* Callback to check if the queue is full */ + gpointer *checkdata; + + GMutex qlock; /* lock for queue (vs object lock) */ + gboolean waiting_add; + GCond item_add; /* signals buffers now available for reading */ + gboolean waiting_del; + GCond item_del; /* signals space now available for writing */ + gboolean flushing; /* indicates whether conditions where signalled because + * of external flushing */ + GstDataQueueFullCallback fullcallback; + GstDataQueueEmptyCallback emptycallback; +}; + +#define GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ + GST_CAT_TRACE (data_queue_dataflow, \ + "locking qlock from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (&q->priv->qlock); \ + GST_CAT_TRACE (data_queue_dataflow, \ + "locked qlock from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define GST_DATA_QUEUE_MUTEX_LOCK_CHECK(q, label) G_STMT_START { \ + GST_DATA_QUEUE_MUTEX_LOCK (q); \ + if (q->priv->flushing) \ + goto label; \ + } G_STMT_END + +#define GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ + GST_CAT_TRACE (data_queue_dataflow, \ + "unlocking qlock from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (&q->priv->qlock); \ +} G_STMT_END + +#define STATUS(q, msg) \ + GST_CAT_LOG (data_queue_dataflow, \ + "queue:%p " msg ": %u visible items, %u " \ + "bytes, %"G_GUINT64_FORMAT \ + " ns, %u elements", \ + queue, \ + q->priv->cur_level.visible, \ + q->priv->cur_level.bytes, \ + q->priv->cur_level.time, \ + gst_queue_array_get_length (q->priv->queue)) + +static void gst_data_queue_finalize (GObject * object); + +static void gst_data_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_data_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static guint gst_data_queue_signals[LAST_SIGNAL] = { 0 }; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0, \ + "data queue object"); \ + GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0, \ + "dataflow inside the data queue object"); \ +} + +#define parent_class gst_data_queue_parent_class +G_DEFINE_TYPE_WITH_CODE (GstDataQueue, gst_data_queue, G_TYPE_OBJECT, _do_init); + +static void +gst_data_queue_class_init (GstDataQueueClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstDataQueuePrivate)); + + gobject_class->set_property = gst_data_queue_set_property; + gobject_class->get_property = gst_data_queue_get_property; + + /* signals */ + /** + * GstDataQueue::empty: (skip) + * @queue: the queue instance + * + * Reports that the queue became empty (empty). + * A queue is empty if the total amount of visible items inside it (num-visible, time, + * size) is lower than the boundary values which can be set through the GObject + * properties. + */ + gst_data_queue_signals[SIGNAL_EMPTY] = + g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstDataQueueClass, empty), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GstDataQueue::full: (skip) + * @queue: the queue instance + * + * Reports that the queue became full (full). + * A queue is full if the total amount of data inside it (num-visible, time, + * size) is higher than the boundary values which can be set through the GObject + * properties. + */ + gst_data_queue_signals[SIGNAL_FULL] = + g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstDataQueueClass, full), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* properties */ + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES, + g_param_spec_uint ("current-level-bytes", "Current level (kB)", + "Current amount of data in the queue (bytes)", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_VISIBLE, + g_param_spec_uint ("current-level-visible", + "Current level (visible items)", + "Current number of visible items in the queue", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME, + g_param_spec_uint64 ("current-level-time", "Current level (ns)", + "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_data_queue_finalize; +} + +static void +gst_data_queue_init (GstDataQueue * queue) +{ + queue->priv = + G_TYPE_INSTANCE_GET_PRIVATE (queue, GST_TYPE_DATA_QUEUE, + GstDataQueuePrivate); + + queue->priv->cur_level.visible = 0; /* no content */ + queue->priv->cur_level.bytes = 0; /* no content */ + queue->priv->cur_level.time = 0; /* no content */ + + queue->priv->checkfull = NULL; + + g_mutex_init (&queue->priv->qlock); + g_cond_init (&queue->priv->item_add); + g_cond_init (&queue->priv->item_del); + queue->priv->queue = gst_queue_array_new (50); + + GST_DEBUG ("initialized queue's not_empty & not_full conditions"); +} + +/** + * gst_data_queue_new: (skip) + * @checkfull: the callback used to tell if the element considers the queue full + * or not. + * @fullcallback: the callback which will be called when the queue is considered full. + * @emptycallback: the callback which will be called when the queue is considered empty. + * @checkdata: a #gpointer that will be passed to the @checkfull, @fullcallback, + * and @emptycallback callbacks. + * + * Creates a new #GstDataQueue. If @fullcallback or @emptycallback are supplied, then + * the #GstDataQueue will call the respective callback to signal full or empty condition. + * If the callbacks are NULL the #GstDataQueue will instead emit 'full' and 'empty' + * signals. + * + * Returns: a new #GstDataQueue. + * + * Since: 1.2 + */ +GstDataQueue * +gst_data_queue_new (GstDataQueueCheckFullFunction checkfull, + GstDataQueueFullCallback fullcallback, + GstDataQueueEmptyCallback emptycallback, gpointer checkdata) +{ + GstDataQueue *ret; + + g_return_val_if_fail (checkfull != NULL, NULL); + + ret = g_object_new (GST_TYPE_DATA_QUEUE, NULL); + ret->priv->checkfull = checkfull; + ret->priv->checkdata = checkdata; + ret->priv->fullcallback = fullcallback; + ret->priv->emptycallback = emptycallback; + + return ret; +} + +static void +gst_data_queue_cleanup (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + while (!gst_queue_array_is_empty (priv->queue)) { + GstDataQueueItem *item = gst_queue_array_pop_head (priv->queue); + + /* Just call the destroy notify on the item */ + item->destroy (item); + } + priv->cur_level.visible = 0; + priv->cur_level.bytes = 0; + priv->cur_level.time = 0; +} + +/* called only once, as opposed to dispose */ +static void +gst_data_queue_finalize (GObject * object) +{ + GstDataQueue *queue = GST_DATA_QUEUE (object); + GstDataQueuePrivate *priv = queue->priv; + + GST_DEBUG ("finalizing queue"); + + gst_data_queue_cleanup (queue); + gst_queue_array_free (priv->queue); + + GST_DEBUG ("free mutex"); + g_mutex_clear (&priv->qlock); + GST_DEBUG ("done free mutex"); + + g_cond_clear (&priv->item_add); + g_cond_clear (&priv->item_del); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static inline void +gst_data_queue_locked_flush (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + STATUS (queue, "before flushing"); + gst_data_queue_cleanup (queue); + STATUS (queue, "after flushing"); + /* we deleted something... */ + if (priv->waiting_del) + g_cond_signal (&priv->item_del); +} + +static inline gboolean +gst_data_queue_locked_is_empty (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + return (gst_queue_array_get_length (priv->queue) == 0); +} + +static inline gboolean +gst_data_queue_locked_is_full (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + return priv->checkfull (queue, priv->cur_level.visible, + priv->cur_level.bytes, priv->cur_level.time, priv->checkdata); +} + +/** + * gst_data_queue_flush: (skip) + * @queue: a #GstDataQueue. + * + * Flushes all the contents of the @queue. Any call to #gst_data_queue_push and + * #gst_data_queue_pop will be released. + * MT safe. + * + * Since: 1.2 + */ +void +gst_data_queue_flush (GstDataQueue * queue) +{ + GST_DEBUG ("queue:%p", queue); + GST_DATA_QUEUE_MUTEX_LOCK (queue); + gst_data_queue_locked_flush (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +/** + * gst_data_queue_is_empty: (skip) + * @queue: a #GstDataQueue. + * + * Queries if there are any items in the @queue. + * MT safe. + * + * Returns: %TRUE if @queue is empty. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_is_empty (GstDataQueue * queue) +{ + gboolean res; + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + res = gst_data_queue_locked_is_empty (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return res; +} + +/** + * gst_data_queue_is_full: (skip) + * @queue: a #GstDataQueue. + * + * Queries if @queue is full. This check will be done using the + * #GstDataQueueCheckFullFunction registered with @queue. + * MT safe. + * + * Returns: %TRUE if @queue is full. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_is_full (GstDataQueue * queue) +{ + gboolean res; + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + res = gst_data_queue_locked_is_full (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return res; +} + +/** + * gst_data_queue_set_flushing: (skip) + * @queue: a #GstDataQueue. + * @flushing: a #gboolean stating if the queue will be flushing or not. + * + * Sets the queue to flushing state if @flushing is %TRUE. If set to flushing + * state, any incoming data on the @queue will be discarded. Any call currently + * blocking on #gst_data_queue_push or #gst_data_queue_pop will return straight + * away with a return value of %FALSE. While the @queue is in flushing state, + * all calls to those two functions will return %FALSE. + * + * MT Safe. + * + * Since: 1.2 + */ +void +gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing) +{ + GstDataQueuePrivate *priv = queue->priv; + + GST_DEBUG ("queue:%p , flushing:%d", queue, flushing); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + priv->flushing = flushing; + if (flushing) { + /* release push/pop functions */ + if (priv->waiting_add) + g_cond_signal (&priv->item_add); + if (priv->waiting_del) + g_cond_signal (&priv->item_del); + } + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +static void +gst_data_queue_push_force_unlocked (GstDataQueue * queue, + GstDataQueueItem * item) +{ + GstDataQueuePrivate *priv = queue->priv; + + gst_queue_array_push_tail (priv->queue, item); + + if (item->visible) + priv->cur_level.visible++; + priv->cur_level.bytes += item->size; + priv->cur_level.time += item->duration; +} + +/** + * gst_data_queue_push_force: (skip) + * @queue: a #GstDataQueue. + * @item: a #GstDataQueueItem. + * + * Pushes a #GstDataQueueItem (or a structure that begins with the same fields) + * on the @queue. It ignores if the @queue is full or not and forces the @item + * to be pushed anyway. + * MT safe. + * + * Note that this function has slightly different semantics than gst_pad_push() + * and gst_pad_push_event(): this function only takes ownership of @item and + * the #GstMiniObject contained in @item if the push was successful. If %FALSE + * is returned, the caller is responsible for freeing @item and its contents. + * + * Returns: %TRUE if the @item was successfully pushed on the @queue. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item) +{ + GstDataQueuePrivate *priv = queue->priv; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before pushing"); + gst_data_queue_push_force_unlocked (queue, item); + STATUS (queue, "after pushing"); + if (priv->waiting_add) + g_cond_signal (&priv->item_add); + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +/** + * gst_data_queue_push: (skip) + * @queue: a #GstDataQueue. + * @item: a #GstDataQueueItem. + * + * Pushes a #GstDataQueueItem (or a structure that begins with the same fields) + * on the @queue. If the @queue is full, the call will block until space is + * available, OR the @queue is set to flushing state. + * MT safe. + * + * Note that this function has slightly different semantics than gst_pad_push() + * and gst_pad_push_event(): this function only takes ownership of @item and + * the #GstMiniObject contained in @item if the push was successful. If %FALSE + * is returned, the caller is responsible for freeing @item and its contents. + * + * Returns: %TRUE if the @item was successfully pushed on the @queue. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item) +{ + GstDataQueuePrivate *priv = queue->priv; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before pushing"); + + /* We ALWAYS need to check for queue fillness */ + if (gst_data_queue_locked_is_full (queue)) { + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + if (G_LIKELY (priv->fullcallback)) + priv->fullcallback (queue, priv->checkdata); + else + g_signal_emit (queue, gst_data_queue_signals[SIGNAL_FULL], 0); + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + /* signal might have removed some items */ + while (gst_data_queue_locked_is_full (queue)) { + priv->waiting_del = TRUE; + g_cond_wait (&priv->item_del, &priv->qlock); + priv->waiting_del = FALSE; + if (priv->flushing) + goto flushing; + } + } + + gst_data_queue_push_force_unlocked (queue, item); + + STATUS (queue, "after pushing"); + if (priv->waiting_add) + g_cond_signal (&priv->item_add); + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +static gboolean +_gst_data_queue_wait_non_empty (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + while (gst_data_queue_locked_is_empty (queue)) { + priv->waiting_add = TRUE; + g_cond_wait (&priv->item_add, &priv->qlock); + priv->waiting_add = FALSE; + if (priv->flushing) + return FALSE; + } + return TRUE; +} + +/** + * gst_data_queue_pop: (skip) + * @queue: a #GstDataQueue. + * @item: pointer to store the returned #GstDataQueueItem. + * + * Retrieves the first @item available on the @queue. If the queue is currently + * empty, the call will block until at least one item is available, OR the + * @queue is set to the flushing state. + * MT safe. + * + * Returns: %TRUE if an @item was successfully retrieved from the @queue. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item) +{ + GstDataQueuePrivate *priv = queue->priv; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before popping"); + + if (gst_data_queue_locked_is_empty (queue)) { + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + if (G_LIKELY (priv->emptycallback)) + priv->emptycallback (queue, priv->checkdata); + else + g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0); + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + if (!_gst_data_queue_wait_non_empty (queue)) + goto flushing; + } + + /* Get the item from the GQueue */ + *item = gst_queue_array_pop_head (priv->queue); + + /* update current level counter */ + if ((*item)->visible) + priv->cur_level.visible--; + priv->cur_level.bytes -= (*item)->size; + priv->cur_level.time -= (*item)->duration; + + STATUS (queue, "after popping"); + if (priv->waiting_del) + g_cond_signal (&priv->item_del); + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +static gint +is_of_type (gconstpointer a, gconstpointer b) +{ + return !G_TYPE_CHECK_INSTANCE_TYPE (a, GPOINTER_TO_SIZE (b)); +} + +/** + * gst_data_queue_peek: (skip) + * @queue: a #GstDataQueue. + * @item: pointer to store the returned #GstDataQueueItem. + * + * Retrieves the first @item available on the @queue without removing it. + * If the queue is currently empty, the call will block until at least + * one item is available, OR the @queue is set to the flushing state. + * MT safe. + * + * Returns: %TRUE if an @item was successfully retrieved from the @queue. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item) +{ + GstDataQueuePrivate *priv = queue->priv; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before peeking"); + + if (gst_data_queue_locked_is_empty (queue)) { + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + if (G_LIKELY (priv->emptycallback)) + priv->emptycallback (queue, priv->checkdata); + else + g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0); + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + if (!_gst_data_queue_wait_non_empty (queue)) + goto flushing; + } + + /* Get the item from the GQueue */ + *item = gst_queue_array_peek_head (priv->queue); + + STATUS (queue, "after peeking"); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +/** + * gst_data_queue_drop_head: (skip) + * @queue: The #GstDataQueue to drop an item from. + * @type: The #GType of the item to drop. + * + * Pop and unref the head-most #GstMiniObject with the given #GType. + * + * Returns: %TRUE if an element was removed. + * + * Since: 1.2 + */ +gboolean +gst_data_queue_drop_head (GstDataQueue * queue, GType type) +{ + gboolean res = FALSE; + GstDataQueueItem *leak = NULL; + guint idx; + GstDataQueuePrivate *priv = queue->priv; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + + GST_DEBUG ("queue:%p", queue); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + idx = gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type)); + + if (idx == -1) + goto done; + + leak = gst_queue_array_drop_element (priv->queue, idx); + + if (leak->visible) + priv->cur_level.visible--; + priv->cur_level.bytes -= leak->size; + priv->cur_level.time -= leak->duration; + + leak->destroy (leak); + + res = TRUE; + +done: + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + GST_DEBUG ("queue:%p , res:%d", queue, res); + + return res; +} + +/** + * gst_data_queue_limits_changed: (skip) + * @queue: The #GstDataQueue + * + * Inform the queue that the limits for the fullness check have changed and that + * any blocking gst_data_queue_push() should be unblocked to recheck the limits. + * + * Since: 1.2 + */ +void +gst_data_queue_limits_changed (GstDataQueue * queue) +{ + GstDataQueuePrivate *priv = queue->priv; + + g_return_if_fail (GST_IS_DATA_QUEUE (queue)); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + if (priv->waiting_del) { + GST_DEBUG ("signal del"); + g_cond_signal (&priv->item_del); + } + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +/** + * gst_data_queue_get_level: (skip) + * @queue: The #GstDataQueue + * @level: the location to store the result + * + * Get the current level of the queue. + * + * Since: 1.2 + */ +void +gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level) +{ + GstDataQueuePrivate *priv = queue->priv; + + memcpy (level, (&priv->cur_level), sizeof (GstDataQueueSize)); +} + +static void +gst_data_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_data_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstDataQueue *queue = GST_DATA_QUEUE (object); + GstDataQueuePrivate *priv = queue->priv; + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + + switch (prop_id) { + case PROP_CUR_LEVEL_BYTES: + g_value_set_uint (value, priv->cur_level.bytes); + break; + case PROP_CUR_LEVEL_VISIBLE: + g_value_set_uint (value, priv->cur_level.visible); + break; + case PROP_CUR_LEVEL_TIME: + g_value_set_uint64 (value, priv->cur_level.time); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} diff --git a/libs/gst/base/gstdataqueue.h b/libs/gst/base/gstdataqueue.h new file mode 100644 index 0000000..4492e6d --- /dev/null +++ b/libs/gst/base/gstdataqueue.h @@ -0,0 +1,186 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey + * + * gstdataqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_DATA_QUEUE_H__ +#define __GST_DATA_QUEUE_H__ + +#include +#include + +G_BEGIN_DECLS +#define GST_TYPE_DATA_QUEUE \ + (gst_data_queue_get_type()) +#define GST_DATA_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DATA_QUEUE,GstDataQueue)) +#define GST_DATA_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DATA_QUEUE,GstDataQueueClass)) +#define GST_IS_DATA_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DATA_QUEUE)) +#define GST_IS_DATA_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DATA_QUEUE)) + +typedef struct _GstDataQueue GstDataQueue; +typedef struct _GstDataQueueClass GstDataQueueClass; +typedef struct _GstDataQueueSize GstDataQueueSize; +typedef struct _GstDataQueueItem GstDataQueueItem; +typedef struct _GstDataQueuePrivate GstDataQueuePrivate; + +/** + * GstDataQueueItem: (skip) + * @object: the #GstMiniObject to queue. + * @size: the size in bytes of the miniobject. + * @duration: the duration in #GstClockTime of the miniobject. Can not be + * %GST_CLOCK_TIME_NONE. + * @visible: %TRUE if @object should be considered as a visible object. + * @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem. + * This function should also drop the reference to @object the owner of the + * #GstDataQueueItem is assumed to hold. + * + * Structure used by #GstDataQueue. You can supply a different structure, as + * long as the top of the structure is identical to this structure. + */ + +struct _GstDataQueueItem +{ + GstMiniObject *object; + guint size; + guint64 duration; + gboolean visible; + + /* user supplied destroy function */ + GDestroyNotify destroy; + + /* < private > */ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDataQueueSize: (skip) + * @visible: number of buffers + * @bytes: number of bytes + * @time: amount of time + * + * Structure describing the size of a queue. + */ +struct _GstDataQueueSize +{ + guint visible; + guint bytes; + guint64 time; +}; + +/** + * GstDataQueueCheckFullFunction: (skip) + * @queue: a #GstDataQueue. + * @visible: The number of visible items currently in the queue. + * @bytes: The amount of bytes currently in the queue. + * @time: The accumulated duration of the items currently in the queue. + * @checkdata: The #gpointer registered when the #GstDataQueue was created. + * + * The prototype of the function used to inform the queue that it should be + * considered as full. + * + * Returns: %TRUE if the queue should be considered full. + */ +typedef gboolean (*GstDataQueueCheckFullFunction) (GstDataQueue * queue, + guint visible, guint bytes, guint64 time, gpointer checkdata); + +typedef void (*GstDataQueueFullCallback) (GstDataQueue * queue, gpointer checkdata); +typedef void (*GstDataQueueEmptyCallback) (GstDataQueue * queue, gpointer checkdata); + +/** + * GstDataQueue: + * @object: the parent structure + * + * Opaque #GstDataQueue structure. + */ +struct _GstDataQueue +{ + GObject object; + + /*< private >*/ + GstDataQueuePrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDataQueueClass: + */ +struct _GstDataQueueClass +{ + GObjectClass parent_class; + + /* signals */ + void (*empty) (GstDataQueue * queue); + void (*full) (GstDataQueue * queue); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_BASE_API +GType gst_data_queue_get_type (void); + +GST_BASE_API +GstDataQueue * gst_data_queue_new (GstDataQueueCheckFullFunction checkfull, + GstDataQueueFullCallback fullcallback, + GstDataQueueEmptyCallback emptycallback, + gpointer checkdata) G_GNUC_MALLOC; +GST_BASE_API +gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item); + +GST_BASE_API +gboolean gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item); + +GST_BASE_API +gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item); + +GST_BASE_API +gboolean gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item); + +GST_BASE_API +void gst_data_queue_flush (GstDataQueue * queue); + +GST_BASE_API +void gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing); + +GST_BASE_API +gboolean gst_data_queue_drop_head (GstDataQueue * queue, GType type); + +GST_BASE_API +gboolean gst_data_queue_is_full (GstDataQueue * queue); + +GST_BASE_API +gboolean gst_data_queue_is_empty (GstDataQueue * queue); + +GST_BASE_API +void gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize *level); + +GST_BASE_API +void gst_data_queue_limits_changed (GstDataQueue * queue); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDataQueue, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DATA_QUEUE_H__ */ diff --git a/libs/gst/base/gstflowcombiner.c b/libs/gst/base/gstflowcombiner.c new file mode 100644 index 0000000..b8ade06 --- /dev/null +++ b/libs/gst/base/gstflowcombiner.c @@ -0,0 +1,342 @@ +/* GStreamer + * + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * Author: Thiago Santos + * + * gstflowcombiner.c: utility to combine multiple flow returns into a single one + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstflowcombiner + * @title: GstFlowCombiner + * @short_description: Utility to combine multiple flow returns into one + * + * Utility struct to help handling #GstFlowReturn combination. Useful for + * #GstElements that have multiple source pads and need to combine + * the different #GstFlowReturn for those pads. + * + * #GstFlowCombiner works by using the last #GstFlowReturn for all #GstPad + * it has in its list and computes the combined return value and provides + * it to the caller. + * + * To add a new pad to the #GstFlowCombiner use gst_flow_combiner_add_pad(). + * The new #GstPad is stored with a default value of %GST_FLOW_OK. + * + * In case you want a #GstPad to be removed, use gst_flow_combiner_remove_pad(). + * + * Please be aware that this struct isn't thread safe as its designed to be + * used by demuxers, those usually will have a single thread operating it. + * + * These functions will take refs on the passed #GstPads. + * + * Aside from reducing the user's code size, the main advantage of using this + * helper struct is to follow the standard rules for #GstFlowReturn combination. + * These rules are: + * + * * %GST_FLOW_EOS: only if all returns are EOS too + * * %GST_FLOW_NOT_LINKED: only if all returns are NOT_LINKED too + * * %GST_FLOW_ERROR or below: if at least one returns an error return + * * %GST_FLOW_NOT_NEGOTIATED: if at least one returns a not-negotiated return + * * %GST_FLOW_FLUSHING: if at least one returns flushing + * * %GST_FLOW_OK: otherwise + * + * %GST_FLOW_ERROR or below, GST_FLOW_NOT_NEGOTIATED and GST_FLOW_FLUSHING are + * returned immediatelly from the gst_flow_combiner_update_flow() function. + * + * Since: 1.4 + */ + +#include +#include "gstflowcombiner.h" + +struct _GstFlowCombiner +{ + GQueue pads; + + GstFlowReturn last_ret; + volatile gint ref_count; +}; + +GST_DEBUG_CATEGORY_STATIC (flowcombiner_dbg); +#define GST_CAT_DEFAULT flowcombiner_dbg + +G_DEFINE_BOXED_TYPE_WITH_CODE (GstFlowCombiner, gst_flow_combiner, + (GBoxedCopyFunc) gst_flow_combiner_ref, + (GBoxedFreeFunc) gst_flow_combiner_unref, + GST_DEBUG_CATEGORY_INIT (flowcombiner_dbg, "flowcombiner", 0, + "Flow Combiner")); + +/** + * gst_flow_combiner_new: + * + * Creates a new #GstFlowCombiner, use gst_flow_combiner_free() to free it. + * + * Returns: A new #GstFlowCombiner + * Since: 1.4 + */ +GstFlowCombiner * +gst_flow_combiner_new (void) +{ + GstFlowCombiner *combiner = g_slice_new (GstFlowCombiner); + + g_queue_init (&combiner->pads); + combiner->last_ret = GST_FLOW_OK; + combiner->ref_count = 1; + + /* Make sure debug category is initialised */ + gst_flow_combiner_get_type (); + + return combiner; +} + +/** + * gst_flow_combiner_free: + * @combiner: the #GstFlowCombiner to free + * + * Frees a #GstFlowCombiner struct and all its internal data. + * + * Since: 1.4 + */ +void +gst_flow_combiner_free (GstFlowCombiner * combiner) +{ + gst_flow_combiner_unref (combiner); +} + +/** + * gst_flow_combiner_ref: + * @combiner: the #GstFlowCombiner to add a reference to. + * + * Increments the reference count on the #GstFlowCombiner. + * + * Returns: the #GstFlowCombiner. + * + * Since: 1.12.1 + */ +GstFlowCombiner * +gst_flow_combiner_ref (GstFlowCombiner * combiner) +{ + g_return_val_if_fail (combiner != NULL, NULL); + + g_atomic_int_inc (&combiner->ref_count); + + return combiner; +} + +/** + * gst_flow_combiner_unref: + * @combiner: the #GstFlowCombiner to unreference. + * + * Decrements the reference count on the #GstFlowCombiner. + * + * Since: 1.12.1 + */ +void +gst_flow_combiner_unref (GstFlowCombiner * combiner) +{ + g_return_if_fail (combiner != NULL); + g_return_if_fail (combiner->ref_count > 0); + + if (g_atomic_int_dec_and_test (&combiner->ref_count)) { + GstPad *pad; + + while ((pad = g_queue_pop_head (&combiner->pads))) + gst_object_unref (pad); + + g_slice_free (GstFlowCombiner, combiner); + } +} + +/** + * gst_flow_combiner_clear: + * @combiner: the #GstFlowCombiner to clear + * + * Removes all pads from a #GstFlowCombiner and resets it to its initial state. + * + * Since: 1.6 + */ +void +gst_flow_combiner_clear (GstFlowCombiner * combiner) +{ + GstPad *pad; + + g_return_if_fail (combiner != NULL); + + while ((pad = g_queue_pop_head (&combiner->pads))) + gst_object_unref (pad); + combiner->last_ret = GST_FLOW_OK; +} + +/** + * gst_flow_combiner_reset: + * @combiner: the #GstFlowCombiner to clear + * + * Reset flow combiner and all pads to their initial state without removing pads. + * + * Since: 1.6 + */ +void +gst_flow_combiner_reset (GstFlowCombiner * combiner) +{ + GList *iter; + + g_return_if_fail (combiner != NULL); + + GST_DEBUG ("Reset flow returns"); + + for (iter = combiner->pads.head; iter; iter = iter->next) { + GST_PAD_LAST_FLOW_RETURN (iter->data) = GST_FLOW_OK; + } + + combiner->last_ret = GST_FLOW_OK; +} + +static GstFlowReturn +gst_flow_combiner_get_flow (GstFlowCombiner * combiner) +{ + GstFlowReturn cret = GST_FLOW_OK; + gboolean all_eos = TRUE; + gboolean all_notlinked = TRUE; + GList *iter; + + GST_DEBUG ("Combining flow returns"); + + for (iter = combiner->pads.head; iter; iter = iter->next) { + GstFlowReturn fret = GST_PAD_LAST_FLOW_RETURN (iter->data); + + if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) { + GST_DEBUG ("Error flow return found, returning"); + cret = fret; + goto done; + } + + if (fret != GST_FLOW_NOT_LINKED) { + all_notlinked = FALSE; + if (fret != GST_FLOW_EOS) + all_eos = FALSE; + } + } + if (all_notlinked) + cret = GST_FLOW_NOT_LINKED; + else if (all_eos) + cret = GST_FLOW_EOS; + +done: + GST_DEBUG ("Combined flow return: %s (%d)", gst_flow_get_name (cret), cret); + return cret; +} + +/** + * gst_flow_combiner_update_flow: + * @combiner: the #GstFlowCombiner + * @fret: the latest #GstFlowReturn received for a pad in this #GstFlowCombiner + * + * Computes the combined flow return for the pads in it. + * + * The #GstFlowReturn parameter should be the last flow return update for a pad + * in this #GstFlowCombiner. It will use this value to be able to shortcut some + * combinations and avoid looking over all pads again. e.g. The last combined + * return is the same as the latest obtained #GstFlowReturn. + * + * Returns: The combined #GstFlowReturn + * Since: 1.4 + */ +GstFlowReturn +gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret) +{ + GstFlowReturn ret; + + g_return_val_if_fail (combiner != NULL, GST_FLOW_ERROR); + + if (combiner->last_ret == fret) { + return fret; + } + + if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) { + ret = fret; + } else { + ret = gst_flow_combiner_get_flow (combiner); + } + combiner->last_ret = ret; + return ret; +} + +/** + * gst_flow_combiner_update_pad_flow: + * @combiner: the #GstFlowCombiner + * @pad: the #GstPad whose #GstFlowReturn to update + * @fret: the latest #GstFlowReturn received for a pad in this #GstFlowCombiner + * + * Sets the provided pad's last flow return to provided value and computes + * the combined flow return for the pads in it. + * + * The #GstFlowReturn parameter should be the last flow return update for a pad + * in this #GstFlowCombiner. It will use this value to be able to shortcut some + * combinations and avoid looking over all pads again. e.g. The last combined + * return is the same as the latest obtained #GstFlowReturn. + * + * Returns: The combined #GstFlowReturn + * Since: 1.6 + */ +GstFlowReturn +gst_flow_combiner_update_pad_flow (GstFlowCombiner * combiner, GstPad * pad, + GstFlowReturn fret) +{ + g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR); + + GST_PAD_LAST_FLOW_RETURN (pad) = fret; + + return gst_flow_combiner_update_flow (combiner, fret); +} + +/** + * gst_flow_combiner_add_pad: + * @combiner: the #GstFlowCombiner + * @pad: (transfer none): the #GstPad that is being added + * + * Adds a new #GstPad to the #GstFlowCombiner. + * + * Since: 1.4 + */ +void +gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad) +{ + g_return_if_fail (combiner != NULL); + g_return_if_fail (pad != NULL); + + g_queue_push_head (&combiner->pads, gst_object_ref (pad)); +} + +/** + * gst_flow_combiner_remove_pad: + * @combiner: the #GstFlowCombiner + * @pad: (transfer none): the #GstPad to remove + * + * Removes a #GstPad from the #GstFlowCombiner. + * + * Since: 1.4 + */ +void +gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad) +{ + g_return_if_fail (combiner != NULL); + g_return_if_fail (pad != NULL); + + if (g_queue_remove (&combiner->pads, pad)) + gst_object_unref (pad); +} diff --git a/libs/gst/base/gstflowcombiner.h b/libs/gst/base/gstflowcombiner.h new file mode 100644 index 0000000..bd06da8 --- /dev/null +++ b/libs/gst/base/gstflowcombiner.h @@ -0,0 +1,84 @@ +/* GStreamer + * + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * Author: Thiago Santos + * + * gstflowcombiner.h: utility to combine multiple flow returns into a single one + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FLOW_COMBINER_H__ +#define __GST_FLOW_COMBINER_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_FLOW_COMBINER gst_flow_combiner_get_type() + +/** + * GstFlowCombiner: + * + * Opaque helper structure to aggregate flow returns. + * + * Since: 1.4 + */ +typedef struct _GstFlowCombiner GstFlowCombiner; + +GST_BASE_API +GstFlowCombiner * gst_flow_combiner_new (void); + +GST_BASE_API +GstFlowCombiner * gst_flow_combiner_ref (GstFlowCombiner * combiner); + +GST_BASE_API +void gst_flow_combiner_unref (GstFlowCombiner * combiner); + +GST_BASE_API +void gst_flow_combiner_free (GstFlowCombiner * combiner); + +GST_BASE_API +GstFlowReturn gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret); + +GST_BASE_API +GstFlowReturn gst_flow_combiner_update_pad_flow (GstFlowCombiner * combiner, GstPad * pad, + GstFlowReturn fret); +GST_BASE_API +void gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad); + +GST_BASE_API +void gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad); + +GST_BASE_API +void gst_flow_combiner_clear (GstFlowCombiner * combiner); + +GST_BASE_API +void gst_flow_combiner_reset (GstFlowCombiner * combiner); + +GST_BASE_API +GType gst_flow_combiner_get_type (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstFlowCombiner, gst_flow_combiner_free) +#endif + +G_END_DECLS + +#endif /* __GST_FLOW_COMBINER_H__ */ diff --git a/libs/gst/base/gstindex.c b/libs/gst/base/gstindex.c new file mode 100644 index 0000000..80fbfe9 --- /dev/null +++ b/libs/gst/base/gstindex.c @@ -0,0 +1,1002 @@ +/* GStreamer + * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/) + * Written by Erik Walthinsen + * + * gstindex.c: Index for mappings and other data + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstindex + * @title: GstIndexEntry + * @short_description: Generate indexes on objects + * @see_also: #GstIndexFactory + * + * #GstIndex is used to generate a stream index of one or more elements + * in a pipeline. + * + * Elements will overload the set_index and get_index virtual methods in + * #GstElement. When streaming data, the element will add index entries if it + * has an index set. + * + * Each element that adds to the index will do that using a writer_id. The + * writer_id is obtained from gst_index_get_writer_id(). + * + * The application that wants to index the stream will create a new index object + * using gst_index_new() or gst_index_factory_make(). The index is assigned to a + * specific element, a bin or the whole pipeline. This will cause indexable + * elements to add entires to the index while playing. + */ + +/* FIXME: complete gobject annotations */ +/* FIXME-0.11: cleanup API + * - no one seems to use GstIndexGroup, GstIndexCertainty + * + * - the API for application to use the index is mostly missing + * - apps need to get a list of writers + * - apps need to be able to iterate over each writers index entry collection + * - gst_index_get_assoc_entry() should pass ownership + * - the GstIndexEntry structure is large and contains repetitive information + * - we want to allow Indexers to implement a saner storage and create + * GstIndexEntries on demand (the app has to free them), might even make + * sense to ask the app to provide a ptr and fill it. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* Index signals and args */ +enum +{ + ENTRY_ADDED, + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_RESOLVER + /* FILL ME */ +}; + +#if 0 +GST_DEBUG_CATEGORY_STATIC (index_debug); +#define GST_CAT_DEFAULT index_debug +#endif + +static void gst_index_finalize (GObject * object); + +static void gst_index_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_index_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstIndexGroup *gst_index_group_new (guint groupnum); +static void gst_index_group_free (GstIndexGroup * group); + +static gboolean gst_index_path_resolver (GstIndex * index, GstObject * writer, + gchar ** writer_string, gpointer data); +static gboolean gst_index_gtype_resolver (GstIndex * index, GstObject * writer, + gchar ** writer_string, gpointer data); +static void gst_index_add_entry (GstIndex * index, GstIndexEntry * entry); + +static guint gst_index_signals[LAST_SIGNAL] = { 0 }; + +typedef struct +{ + GstIndexResolverMethod method; + GstIndexResolver resolver; + gpointer user_data; +} +ResolverEntry; + +static const ResolverEntry resolvers[] = { + {GST_INDEX_RESOLVER_CUSTOM, NULL, NULL}, + {GST_INDEX_RESOLVER_GTYPE, gst_index_gtype_resolver, NULL}, + {GST_INDEX_RESOLVER_PATH, gst_index_path_resolver, NULL}, +}; + +#define GST_TYPE_INDEX_RESOLVER (gst_index_resolver_get_type()) +static GType +gst_index_resolver_get_type (void) +{ + static GType index_resolver_type = 0; + static const GEnumValue index_resolver[] = { + {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM", "custom"}, + {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE", "gtype"}, + {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH", "path"}, + {0, NULL, NULL}, + }; + + if (!index_resolver_type) { + index_resolver_type = + g_enum_register_static ("GstIndexResolver", index_resolver); + } + return index_resolver_type; +} + +G_DEFINE_BOXED_TYPE (GstIndexEntry, gst_index_entry, + (GBoxedCopyFunc) gst_index_entry_copy, + (GBoxedFreeFunc) gst_index_entry_free); + +#if 0 +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (index_debug, "GST_INDEX", GST_DEBUG_BOLD, \ + "Generic indexing support"); \ +} +#endif + +G_DEFINE_TYPE (GstIndex, gst_index, GST_TYPE_OBJECT); + +static void +gst_index_class_init (GstIndexClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * GstIndex::entry-added + * @gstindex: the object which received the signal. + * @arg1: The entry added to the index. + * + * Is emitted when a new entry is added to the index. + */ + gst_index_signals[ENTRY_ADDED] = + g_signal_new ("entry-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY); + + gobject_class->set_property = gst_index_set_property; + gobject_class->get_property = gst_index_get_property; + gobject_class->finalize = gst_index_finalize; + + g_object_class_install_property (gobject_class, ARG_RESOLVER, + g_param_spec_enum ("resolver", "Resolver", + "Select a predefined object to string mapper", + GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_index_init (GstIndex * index) +{ + index->curgroup = gst_index_group_new (0); + index->maxgroup = 0; + index->groups = g_list_prepend (NULL, index->curgroup); + + index->writers = g_hash_table_new (NULL, NULL); + index->last_id = 0; + + index->method = GST_INDEX_RESOLVER_PATH; + index->resolver = resolvers[index->method].resolver; + index->resolver_user_data = resolvers[index->method].user_data; + + GST_OBJECT_FLAG_SET (index, GST_INDEX_WRITABLE); + GST_OBJECT_FLAG_SET (index, GST_INDEX_READABLE); + + GST_DEBUG ("created new index"); +} + +static void +gst_index_free_writer (gpointer key, gpointer value, gpointer user_data) +{ + GstIndexEntry *entry = (GstIndexEntry *) value; + + if (entry) { + gst_index_entry_free (entry); + } +} + +static void +gst_index_finalize (GObject * object) +{ + GstIndex *index = GST_INDEX (object); + + if (index->groups) { + g_list_foreach (index->groups, (GFunc) gst_index_group_free, NULL); + g_list_free (index->groups); + index->groups = NULL; + } + + if (index->writers) { + g_hash_table_foreach (index->writers, gst_index_free_writer, NULL); + g_hash_table_destroy (index->writers); + index->writers = NULL; + } + + if (index->filter_user_data && index->filter_user_data_destroy) + index->filter_user_data_destroy (index->filter_user_data); + + if (index->resolver_user_data && index->resolver_user_data_destroy) + index->resolver_user_data_destroy (index->resolver_user_data); + + G_OBJECT_CLASS (gst_index_parent_class)->finalize (object); +} + +static void +gst_index_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstIndex *index; + + index = GST_INDEX (object); + + switch (prop_id) { + case ARG_RESOLVER: + index->method = (GstIndexResolverMethod) g_value_get_enum (value); + index->resolver = resolvers[index->method].resolver; + index->resolver_user_data = resolvers[index->method].user_data; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_index_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstIndex *index; + + index = GST_INDEX (object); + + switch (prop_id) { + case ARG_RESOLVER: + g_value_set_enum (value, index->method); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstIndexGroup * +gst_index_group_new (guint groupnum) +{ + GstIndexGroup *indexgroup = g_slice_new (GstIndexGroup); + + indexgroup->groupnum = groupnum; + indexgroup->entries = NULL; + indexgroup->certainty = GST_INDEX_UNKNOWN; + indexgroup->peergroup = -1; + + GST_DEBUG ("created new index group %d", groupnum); + + return indexgroup; +} + +static void +gst_index_group_free (GstIndexGroup * group) +{ + g_slice_free (GstIndexGroup, group); +} + +/* do not resurrect this, add a derived dummy index class instead */ +#if 0 +/** + * gst_index_new: + * + * Create a new dummy index object. Use gst_element_set_index() to assign that + * to an element or pipeline. This index is not storing anything, but will + * still emit e.g. the #GstIndex::entry-added signal. + * + * Returns: (transfer full): a new index object + */ +GstIndex * +gst_index_new (void) +{ + GstIndex *index; + + index = g_object_new (gst_index_get_type (), NULL); + + return index; +} + +/** + * gst_index_commit: + * @index: the index to commit + * @id: the writer that commited the index + * + * Tell the index that the writer with the given id is done + * with this index and is not going to write any more entries + * to it. + */ +void +gst_index_commit (GstIndex * index, gint id) +{ + GstIndexClass *iclass; + + iclass = GST_INDEX_GET_CLASS (index); + + if (iclass->commit) + iclass->commit (index, id); +} + +/** + * gst_index_get_group: + * @index: the index to get the current group from + * + * Get the id of the current group. + * + * Returns: the id of the current group. + */ +gint +gst_index_get_group (GstIndex * index) +{ + return index->curgroup->groupnum; +} + +/** + * gst_index_new_group: + * @index: the index to create the new group in + * + * Create a new group for the given index. It will be + * set as the current group. + * + * Returns: the id of the newly created group. + */ +gint +gst_index_new_group (GstIndex * index) +{ + index->curgroup = gst_index_group_new (++index->maxgroup); + index->groups = g_list_append (index->groups, index->curgroup); + GST_DEBUG ("created new group %d in index", index->maxgroup); + return index->maxgroup; +} + +/** + * gst_index_set_group: + * @index: the index to set the new group in + * @groupnum: the groupnumber to set + * + * Set the current groupnumber to the given argument. + * + * Returns: %TRUE if the operation succeeded, %FALSE if the group + * did not exist. + */ +gboolean +gst_index_set_group (GstIndex * index, gint groupnum) +{ + GList *list; + GstIndexGroup *indexgroup; + + /* first check for null change */ + if (groupnum == index->curgroup->groupnum) + return TRUE; + + /* else search for the proper group */ + list = index->groups; + while (list) { + indexgroup = (GstIndexGroup *) (list->data); + list = g_list_next (list); + if (indexgroup->groupnum == groupnum) { + index->curgroup = indexgroup; + GST_DEBUG ("switched to index group %d", indexgroup->groupnum); + return TRUE; + } + } + + /* couldn't find the group in question */ + GST_DEBUG ("couldn't find index group %d", groupnum); + return FALSE; +} +#endif + +#if 0 +/** + * gst_index_set_certainty: + * @index: the index to set the certainty on + * @certainty: the certainty to set + * + * Set the certainty of the given index. + */ +void +gst_index_set_certainty (GstIndex * index, GstIndexCertainty certainty) +{ + index->curgroup->certainty = certainty; +} + +/** + * gst_index_get_certainty: + * @index: the index to get the certainty of + * + * Get the certainty of the given index. + * + * Returns: the certainty of the index. + */ +GstIndexCertainty +gst_index_get_certainty (GstIndex * index) +{ + return index->curgroup->certainty; +} +#endif + +#if 0 +/** + * gst_index_set_filter: + * @index: the index to register the filter on + * @filter: the filter to register + * @user_data: data passed to the filter function + * + * Lets the app register a custom filter function so that + * it can select what entries should be stored in the index. + */ +void +gst_index_set_filter (GstIndex * index, + GstIndexFilter filter, gpointer user_data) +{ + g_return_if_fail (GST_IS_INDEX (index)); + + gst_index_set_filter_full (index, filter, user_data, NULL); +} + +/** + * gst_index_set_filter_full: + * @index: the index to register the filter on + * @filter: the filter to register + * @user_data: data passed to the filter function + * @user_data_destroy: function to call when @user_data is unset + * + * Lets the app register a custom filter function so that + * it can select what entries should be stored in the index. + */ +void +gst_index_set_filter_full (GstIndex * index, + GstIndexFilter filter, gpointer user_data, GDestroyNotify user_data_destroy) +{ + g_return_if_fail (GST_IS_INDEX (index)); + + if (index->filter_user_data && index->filter_user_data_destroy) + index->filter_user_data_destroy (index->filter_user_data); + + index->filter = filter; + index->filter_user_data = user_data; + index->filter_user_data_destroy = user_data_destroy; +} + +/** + * gst_index_set_resolver: + * @index: the index to register the resolver on + * @resolver: the resolver to register + * @user_data: data passed to the resolver function + * + * Lets the app register a custom function to map index + * ids to writer descriptions. + */ +void +gst_index_set_resolver (GstIndex * index, + GstIndexResolver resolver, gpointer user_data) +{ + gst_index_set_resolver_full (index, resolver, user_data, NULL); +} + +/** + * gst_index_set_resolver_full: + * @index: the index to register the resolver on + * @resolver: the resolver to register + * @user_data: data passed to the resolver function + * @user_data_destroy: destroy function for @user_data + * + * Lets the app register a custom function to map index + * ids to writer descriptions. + */ +void +gst_index_set_resolver_full (GstIndex * index, GstIndexResolver resolver, + gpointer user_data, GDestroyNotify user_data_destroy) +{ + g_return_if_fail (GST_IS_INDEX (index)); + + if (index->resolver_user_data && index->resolver_user_data_destroy) + index->resolver_user_data_destroy (index->resolver_user_data); + + index->resolver = resolver; + index->resolver_user_data = user_data; + index->resolver_user_data_destroy = user_data_destroy; + index->method = GST_INDEX_RESOLVER_CUSTOM; +} +#endif + +/** + * gst_index_entry_copy: + * @entry: the entry to copy + * + * Copies an entry and returns the result. + * + * Free-function: gst_index_entry_free + * + * Returns: (transfer full): a newly allocated #GstIndexEntry. + */ +GstIndexEntry * +gst_index_entry_copy (GstIndexEntry * entry) +{ + GstIndexEntry *new_entry = g_slice_new (GstIndexEntry); + + memcpy (new_entry, entry, sizeof (GstIndexEntry)); + return new_entry; +} + +/** + * gst_index_entry_free: + * @entry: (transfer full): the entry to free + * + * Free the memory used by the given entry. + */ +void +gst_index_entry_free (GstIndexEntry * entry) +{ + switch (entry->type) { + case GST_INDEX_ENTRY_ID: + if (entry->data.id.description) { + g_free (entry->data.id.description); + entry->data.id.description = NULL; + } + break; + case GST_INDEX_ENTRY_ASSOCIATION: + if (entry->data.assoc.assocs) { + g_free (entry->data.assoc.assocs); + entry->data.assoc.assocs = NULL; + } + break; + case GST_INDEX_ENTRY_OBJECT: + break; + case GST_INDEX_ENTRY_FORMAT: + break; + } + + g_slice_free (GstIndexEntry, entry); +} + +#if 0 +/** + * gst_index_add_format: + * @index: the index to add the entry to + * @id: the id of the index writer + * @format: the format to add to the index + * + * Adds a format entry into the index. This function is + * used to map dynamic #GstFormat ids to their original + * format key. + * + * Free-function: gst_index_entry_free + * + * Returns: (transfer full): a pointer to the newly added entry in the index. + */ +GstIndexEntry * +gst_index_add_format (GstIndex * index, gint id, GstFormat format) +{ + GstIndexEntry *entry; + const GstFormatDefinition *def; + + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + g_return_val_if_fail (format != 0, NULL); + + if (!GST_INDEX_IS_WRITABLE (index) || id == -1) + return NULL; + + entry = g_slice_new (GstIndexEntry); + entry->type = GST_INDEX_ENTRY_FORMAT; + entry->id = id; + entry->data.format.format = format; + + def = gst_format_get_details (format); + entry->data.format.key = def->nick; + + gst_index_add_entry (index, entry); + + return entry; +} +#endif + +/** + * gst_index_add_id: + * @index: the index to add the entry to + * @id: the id of the index writer + * @description: the description of the index writer + * + * Add an id entry into the index. + * + * Returns: a pointer to the newly added entry in the index. + */ +GstIndexEntry * +gst_index_add_id (GstIndex * index, gint id, gchar * description) +{ + GstIndexEntry *entry; + + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + g_return_val_if_fail (description != NULL, NULL); + + if (!GST_INDEX_IS_WRITABLE (index) || id == -1) + return NULL; + + entry = g_slice_new (GstIndexEntry); + entry->type = GST_INDEX_ENTRY_ID; + entry->id = id; + entry->data.id.description = description; + + gst_index_add_entry (index, entry); + + return entry; +} + +static gboolean +gst_index_path_resolver (GstIndex * index, GstObject * writer, + gchar ** writer_string, gpointer data) +{ + *writer_string = gst_object_get_path_string (writer); + + return TRUE; +} + +static gboolean +gst_index_gtype_resolver (GstIndex * index, GstObject * writer, + gchar ** writer_string, gpointer data) +{ + g_return_val_if_fail (writer != NULL, FALSE); + + if (GST_IS_PAD (writer)) { + GstObject *element = gst_object_get_parent (GST_OBJECT (writer)); + gchar *name; + + name = gst_object_get_name (writer); + if (element) { + *writer_string = g_strdup_printf ("%s.%s", + G_OBJECT_TYPE_NAME (element), name); + gst_object_unref (element); + } else { + *writer_string = name; + name = NULL; + } + + g_free (name); + + } else { + *writer_string = g_strdup (G_OBJECT_TYPE_NAME (writer)); + } + + return TRUE; +} + +/** + * gst_index_get_writer_id: + * @index: the index to get a unique write id for + * @writer: the #GstObject to allocate an id for + * @id: a pointer to a gint to hold the id + * + * Before entries can be added to the index, a writer + * should obtain a unique id. The methods to add new entries + * to the index require this id as an argument. + * + * The application can implement a custom function to map the writer object + * to a string. That string will be used to register or look up an id + * in the index. + * + * > The caller must not hold @writer's GST_OBJECT_LOCK(), as the default + * > resolver may call functions that take the object lock as well, and + * > the lock is not recursive. + * + * Returns: %TRUE if the writer would be mapped to an id. + */ +gboolean +gst_index_get_writer_id (GstIndex * index, GstObject * writer, gint * id) +{ + gchar *writer_string = NULL; + GstIndexEntry *entry; + GstIndexClass *iclass; + gboolean success = FALSE; + + g_return_val_if_fail (GST_IS_INDEX (index), FALSE); + g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE); + g_return_val_if_fail (id, FALSE); + + *id = -1; + + /* first try to get a previously cached id */ + entry = g_hash_table_lookup (index->writers, writer); + if (entry == NULL) { + + iclass = GST_INDEX_GET_CLASS (index); + + /* let the app make a string */ + if (index->resolver) { + gboolean res; + + res = + index->resolver (index, writer, &writer_string, + index->resolver_user_data); + if (!res) + return FALSE; + } else { + g_warning ("no resolver found"); + return FALSE; + } + + /* if the index has a resolver, make it map this string to an id */ + if (iclass->get_writer_id) { + success = iclass->get_writer_id (index, id, writer_string); + } + /* if the index could not resolve, we allocate one ourselves */ + if (!success) { + *id = ++index->last_id; + } + + entry = gst_index_add_id (index, *id, writer_string); + if (!entry) { + /* index is probably not writable, make an entry anyway + * to keep it in our cache */ + entry = g_slice_new (GstIndexEntry); + entry->type = GST_INDEX_ENTRY_ID; + entry->id = *id; + entry->data.id.description = writer_string; + } + g_hash_table_insert (index->writers, writer, entry); + } else { + *id = entry->id; + } + + return TRUE; +} + +static void +gst_index_add_entry (GstIndex * index, GstIndexEntry * entry) +{ + GstIndexClass *iclass; + + iclass = GST_INDEX_GET_CLASS (index); + + if (iclass->add_entry) { + iclass->add_entry (index, entry); + } + + g_signal_emit (index, gst_index_signals[ENTRY_ADDED], 0, entry); +} + +/** + * gst_index_add_associationv: + * @index: the index to add the entry to + * @id: the id of the index writer + * @flags: optinal flags for this entry + * @n: number of associations + * @list: (array length=n): list of associations + * + * Associate given format/value pairs with each other. + * + * Returns: a pointer to the newly added entry in the index. + */ +GstIndexEntry * +gst_index_add_associationv (GstIndex * index, gint id, + GstIndexAssociationFlags flags, gint n, const GstIndexAssociation * list) +{ + GstIndexEntry *entry; + + g_return_val_if_fail (n > 0, NULL); + g_return_val_if_fail (list != NULL, NULL); + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + + if (!GST_INDEX_IS_WRITABLE (index) || id == -1) + return NULL; + + entry = g_slice_new (GstIndexEntry); + + entry->type = GST_INDEX_ENTRY_ASSOCIATION; + entry->id = id; + entry->data.assoc.flags = flags; + entry->data.assoc.assocs = g_memdup (list, sizeof (GstIndexAssociation) * n); + entry->data.assoc.nassocs = n; + + gst_index_add_entry (index, entry); + + return entry; +} + +#if 0 +/** + * gst_index_add_association: + * @index: the index to add the entry to + * @id: the id of the index writer + * @flags: optinal flags for this entry + * @format: the format of the value + * @value: the value + * @...: other format/value pairs or 0 to end the list + * + * Associate given format/value pairs with each other. + * Be sure to pass gint64 values to this functions varargs, + * you might want to use a gint64 cast to be sure. + * + * Returns: a pointer to the newly added entry in the index. + */ +GstIndexEntry * +gst_index_add_association (GstIndex * index, gint id, + GstIndexAssociationFlags flags, GstFormat format, gint64 value, ...) +{ + va_list args; + GstIndexEntry *entry; + GstIndexAssociation *list; + gint n_assocs = 0; + GstFormat cur_format; + GArray *array; + + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + g_return_val_if_fail (format != 0, NULL); + + if (!GST_INDEX_IS_WRITABLE (index) || id == -1) + return NULL; + + array = g_array_new (FALSE, FALSE, sizeof (GstIndexAssociation)); + + { + GstIndexAssociation a; + + a.format = format; + a.value = value; + n_assocs = 1; + g_array_append_val (array, a); + } + + va_start (args, value); + + while ((cur_format = va_arg (args, GstFormat))) { + GstIndexAssociation a; + + a.format = cur_format; + a.value = va_arg (args, gint64); + n_assocs++; + g_array_append_val (array, a); + } + + va_end (args); + + list = (GstIndexAssociation *) g_array_free (array, FALSE); + + entry = gst_index_add_associationv (index, id, flags, n_assocs, list); + g_free (list); + + return entry; +} + +/** + * gst_index_add_object: + * @index: the index to add the object to + * @id: the id of the index writer + * @key: a key for the object + * @type: the GType of the object + * @object: a pointer to the object to add + * + * Add the given object to the index with the given key. + * + * This function is not yet implemented. + * + * Returns: a pointer to the newly added entry in the index. + */ +GstIndexEntry * +gst_index_add_object (GstIndex * index, gint id, gchar * key, + GType type, gpointer object) +{ + if (!GST_INDEX_IS_WRITABLE (index) || id == -1) + return NULL; + + return NULL; +} +#endif + +static gint +gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data) +{ + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +/** + * gst_index_get_assoc_entry: + * @index: the index to search + * @id: the id of the index writer + * @method: The lookup method to use + * @flags: Flags for the entry + * @format: the format of the value + * @value: the value to find + * + * Finds the given format/value in the index + * + * Returns: (nullable): the entry associated with the value or %NULL if the + * value was not found. + */ +GstIndexEntry * +gst_index_get_assoc_entry (GstIndex * index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value) +{ + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + + if (id == -1) + return NULL; + + return gst_index_get_assoc_entry_full (index, id, method, flags, format, + value, gst_index_compare_func, NULL); +} + +/** + * gst_index_get_assoc_entry_full: + * @index: the index to search + * @id: the id of the index writer + * @method: The lookup method to use + * @flags: Flags for the entry + * @format: the format of the value + * @value: the value to find + * @func: the function used to compare entries + * @user_data: user data passed to the compare function + * + * Finds the given format/value in the index with the given + * compare function and user_data. + * + * Returns: (nullable): the entry associated with the value or %NULL if the + * value was not found. + */ +GstIndexEntry * +gst_index_get_assoc_entry_full (GstIndex * index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data) +{ + GstIndexClass *iclass; + + g_return_val_if_fail (GST_IS_INDEX (index), NULL); + + if (id == -1) + return NULL; + + iclass = GST_INDEX_GET_CLASS (index); + + if (iclass->get_assoc_entry) + return iclass->get_assoc_entry (index, id, method, flags, format, value, + func, user_data); + + return NULL; +} + +/** + * gst_index_entry_assoc_map: + * @entry: the index to search + * @format: the format of the value the find + * @value: a pointer to store the value + * + * Gets alternative formats associated with the indexentry. + * + * Returns: %TRUE if there was a value associated with the given + * format. + */ +gboolean +gst_index_entry_assoc_map (GstIndexEntry * entry, + GstFormat format, gint64 * value) +{ + gint i; + + g_return_val_if_fail (entry != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) { + if (GST_INDEX_ASSOC_FORMAT (entry, i) == format) { + *value = GST_INDEX_ASSOC_VALUE (entry, i); + return TRUE; + } + } + return FALSE; +} diff --git a/libs/gst/base/gstindex.h b/libs/gst/base/gstindex.h new file mode 100644 index 0000000..4761465 --- /dev/null +++ b/libs/gst/base/gstindex.h @@ -0,0 +1,449 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstindex.h: Header for GstIndex, base class to handle efficient + * storage or caching of seeking information. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_INDEX_H__ +#define __GST_INDEX_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_INDEX (gst_index_get_type ()) +#define GST_INDEX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INDEX, GstIndex)) +#define GST_IS_INDEX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INDEX)) +#define GST_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INDEX, GstIndexClass)) +#define GST_IS_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INDEX)) +#define GST_INDEX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_INDEX, GstIndexClass)) + +#define GST_TYPE_INDEX_ENTRY (gst_index_entry_get_type()) + +typedef struct _GstIndexEntry GstIndexEntry; +typedef struct _GstIndexGroup GstIndexGroup; +typedef struct _GstIndex GstIndex; +typedef struct _GstIndexClass GstIndexClass; + +/** + * GstIndexCertainty: + * @GST_INDEX_UNKNOWN: accuracy is not known + * @GST_INDEX_CERTAIN: accuracy is perfect + * @GST_INDEX_FUZZY: accuracy is fuzzy + * + * The certainty of a group in the index. + */ +typedef enum { + GST_INDEX_UNKNOWN, + GST_INDEX_CERTAIN, + GST_INDEX_FUZZY +} GstIndexCertainty; + +/** + * GstIndexEntryType: + * @GST_INDEX_ENTRY_ID: This entry is an id that maps an index id to its owner object + * @GST_INDEX_ENTRY_ASSOCIATION: This entry is an association between formats + * @GST_INDEX_ENTRY_OBJECT: An object + * @GST_INDEX_ENTRY_FORMAT: A format definition + * + * The different types of entries in the index. + */ +typedef enum { + GST_INDEX_ENTRY_ID, + GST_INDEX_ENTRY_ASSOCIATION, + GST_INDEX_ENTRY_OBJECT, + GST_INDEX_ENTRY_FORMAT +} GstIndexEntryType; + +/** + * GstIndexLookupMethod: + * @GST_INDEX_LOOKUP_EXACT: There has to be an exact indexentry with the given format/value + * @GST_INDEX_LOOKUP_BEFORE: The exact entry or the one before it + * @GST_INDEX_LOOKUP_AFTER: The exact entry or the one after it + * + * Specify the method to find an index entry in the index. + */ +typedef enum { + GST_INDEX_LOOKUP_EXACT, + GST_INDEX_LOOKUP_BEFORE, + GST_INDEX_LOOKUP_AFTER +} GstIndexLookupMethod; + +/** + * GST_INDEX_NASSOCS: + * @entry: The entry to query + * + * Get the number of associations in the entry. + */ +#define GST_INDEX_NASSOCS(entry) ((entry)->data.assoc.nassocs) + +/** + * GST_INDEX_ASSOC_FLAGS: + * @entry: The entry to query + * + * Get the flags for this entry. + */ +#define GST_INDEX_ASSOC_FLAGS(entry) ((entry)->data.assoc.flags) + +/** + * GST_INDEX_ASSOC_FORMAT: + * @entry: The entry to query + * @i: The format index + * + * Get the i-th format of the entry. + */ +#define GST_INDEX_ASSOC_FORMAT(entry,i) ((entry)->data.assoc.assocs[(i)].format) + +/** + * GST_INDEX_ASSOC_VALUE: + * @entry: The entry to query + * @i: The value index + * + * Get the i-th value of the entry. + */ +#define GST_INDEX_ASSOC_VALUE(entry,i) ((entry)->data.assoc.assocs[(i)].value) + +typedef struct _GstIndexAssociation GstIndexAssociation; + +/** + * GstIndexAssociation: + * @format: the format of the association + * @value: the value of the association + * + * An association in an entry. + */ +struct _GstIndexAssociation { + GstFormat format; + gint64 value; +}; + +/** + * GstIndexAssociationFlags: + * @GST_INDEX_ASSOCIATION_FLAG_NONE: no extra flags + * @GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT: the entry marks a key unit, a key unit is one + * that marks a place where one can randomly seek to. + * @GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT: the entry marks a delta unit, a delta unit + * is one that marks a place where one can relatively seek to. + * @GST_INDEX_ASSOCIATION_FLAG_LAST: extra user defined flags should start here. + * + * Flags for an association entry. + */ +typedef enum { + GST_INDEX_ASSOCIATION_FLAG_NONE = 0, + GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT = (1 << 0), + GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT = (1 << 1), + + /* new flags should start here */ + GST_INDEX_ASSOCIATION_FLAG_LAST = (1 << 8) +} GstIndexAssociationFlags; + +/** + * GST_INDEX_FORMAT_FORMAT: + * @entry: The entry to query + * + * Get the format of the format entry + */ +#define GST_INDEX_FORMAT_FORMAT(entry) ((entry)->data.format.format) + +/** + * GST_INDEX_FORMAT_KEY: + * @entry: The entry to query + * + * Get the key of the format entry + */ +#define GST_INDEX_FORMAT_KEY(entry) ((entry)->data.format.key) + +/** + * GST_INDEX_ID_INVALID: + * + * Constant for an invalid index id + */ +#define GST_INDEX_ID_INVALID (-1) + +/** + * GST_INDEX_ID_DESCRIPTION: + * @entry: The entry to query + * + * Get the description of the id entry + */ +#define GST_INDEX_ID_DESCRIPTION(entry) ((entry)->data.id.description) + +/** + * GstIndexEntry: + * + * The basic element of an index. + */ +struct _GstIndexEntry { + /*< private >*/ + GstIndexEntryType type; + gint id; + + union { + struct { + gchar *description; + } id; + struct { + gint nassocs; + GstIndexAssociation + *assocs; + GstIndexAssociationFlags flags; + } assoc; + struct { + gchar *key; + GType type; + gpointer object; + } object; + struct { + GstFormat format; + const gchar *key; + } format; + } data; + // FIXME 2.0: add padding +}; + +/** + * GstIndexGroup: + * + * A group of related entries in an index. + */ + +struct _GstIndexGroup { + /*< private >*/ + /* unique ID of group in index */ + gint groupnum; + + /* list of entries */ + GList *entries; + + /* the certainty level of the group */ + GstIndexCertainty certainty; + + /* peer group that contains more certain entries */ + gint peergroup; + // FIXME 2.0: add padding +}; + +/** + * GstIndexFilter: + * @index: The index being queried + * @entry: The entry to be added. + * @user_data: User data passed to the function. + * + * Function to filter out entries in the index. + * + * Returns: This function should return %TRUE if the entry is to be added + * to the index, %FALSE otherwise. + * + */ +typedef gboolean (*GstIndexFilter) (GstIndex *index, + GstIndexEntry *entry, + gpointer user_data); +/** + * GstIndexResolverMethod: + * @GST_INDEX_RESOLVER_CUSTOM: Use a custom resolver + * @GST_INDEX_RESOLVER_GTYPE: Resolve based on the GType of the object + * @GST_INDEX_RESOLVER_PATH: Resolve on the path in graph + * + * The method used to resolve index writers + */ +typedef enum { + GST_INDEX_RESOLVER_CUSTOM, + GST_INDEX_RESOLVER_GTYPE, + GST_INDEX_RESOLVER_PATH +} GstIndexResolverMethod; + +/** + * GstIndexResolver: + * @index: the index being queried. + * @writer: The object that wants to write + * @writer_string: A description of the writer. + * @user_data: user_data as registered + * + * Function to resolve ids to writer descriptions. + * + * Returns: %TRUE if an id could be assigned to the writer. + */ +typedef gboolean (*GstIndexResolver) (GstIndex *index, + GstObject *writer, + gchar **writer_string, + gpointer user_data); + +/** + * GstIndexFlags: + * @GST_INDEX_WRITABLE: The index is writable + * @GST_INDEX_READABLE: The index is readable + * @GST_INDEX_FLAG_LAST: First flag that can be used by subclasses + * + * Flags for this index + */ +typedef enum { + GST_INDEX_WRITABLE = (GST_OBJECT_FLAG_LAST << 0), + GST_INDEX_READABLE = (GST_OBJECT_FLAG_LAST << 1), + + GST_INDEX_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 8) +} GstIndexFlags; + +/** + * GST_INDEX_IS_READABLE: + * @obj: The index to check + * + * Check if the index can be read from + */ +#define GST_INDEX_IS_READABLE(obj) (GST_OBJECT_FLAG_IS_SET (obj, GST_INDEX_READABLE)) + +/** + * GST_INDEX_IS_WRITABLE: + * @obj: The index to check + * + * Check if the index can be written to + */ +#define GST_INDEX_IS_WRITABLE(obj) (GST_OBJECT_FLAG_IS_SET (obj, GST_INDEX_WRITABLE)) + +/** + * GstIndex: + * + * Opaque #GstIndex structure. + */ +struct _GstIndex { + GstObject object; + + /*< private >*/ + GList *groups; + GstIndexGroup *curgroup; + gint maxgroup; + + GstIndexResolverMethod method; + GstIndexResolver resolver; + gpointer resolver_user_data; + GDestroyNotify resolver_user_data_destroy; + + GstIndexFilter filter; + gpointer filter_user_data; + GDestroyNotify filter_user_data_destroy; + + GHashTable *writers; + gint last_id; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstIndexClass { + GstObjectClass parent_class; + + /*< protected >*/ + gboolean (*get_writer_id) (GstIndex *index, gint *id, gchar *writer); + + void (*commit) (GstIndex *index, gint id); + + /* abstract methods */ + void (*add_entry) (GstIndex *index, GstIndexEntry *entry); + + GstIndexEntry* (*get_assoc_entry) (GstIndex *index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value, + GCompareDataFunc func, + gpointer user_data); + /* signals */ + void (*entry_added) (GstIndex *index, GstIndexEntry *entry); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +static +GType gst_index_get_type (void); + +#if 0 +GstIndex* gst_index_new (void); +void gst_index_commit (GstIndex *index, gint id); + +gint gst_index_get_group (GstIndex *index); +gint gst_index_new_group (GstIndex *index); +gboolean gst_index_set_group (GstIndex *index, gint groupnum); + +void gst_index_set_certainty (GstIndex *index, + GstIndexCertainty certainty); +GstIndexCertainty gst_index_get_certainty (GstIndex *index); + +static +void gst_index_set_filter (GstIndex *index, + GstIndexFilter filter, gpointer user_data); +static +void gst_index_set_filter_full (GstIndex *index, + GstIndexFilter filter, gpointer user_data, + GDestroyNotify user_data_destroy); + +void gst_index_set_resolver (GstIndex *index, + GstIndexResolver resolver, gpointer user_data); +void gst_index_set_resolver_full (GstIndex *index, GstIndexResolver resolver, + gpointer user_data, + GDestroyNotify user_data_destroy); +#endif + +static +gboolean gst_index_get_writer_id (GstIndex *index, GstObject *writer, gint *id); + +#if 0 +GstIndexEntry* gst_index_add_format (GstIndex *index, gint id, GstFormat format); +#endif + +static +GstIndexEntry* gst_index_add_associationv (GstIndex * index, gint id, GstIndexAssociationFlags flags, + gint n, const GstIndexAssociation * list); +#if 0 +GstIndexEntry* gst_index_add_association (GstIndex *index, gint id, GstIndexAssociationFlags flags, + GstFormat format, gint64 value, ...) +GstIndexEntry* gst_index_add_object (GstIndex *index, gint id, gchar *key, + GType type, gpointer object); +#endif + +static +GstIndexEntry* gst_index_add_id (GstIndex *index, gint id, + gchar *description); + +static +GstIndexEntry* gst_index_get_assoc_entry (GstIndex *index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value); +static +GstIndexEntry* gst_index_get_assoc_entry_full (GstIndex *index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value, + GCompareDataFunc func, + gpointer user_data); + +/* working with index entries */ +static +GType gst_index_entry_get_type (void); +static +GstIndexEntry * gst_index_entry_copy (GstIndexEntry *entry); +static +void gst_index_entry_free (GstIndexEntry *entry); +static +gboolean gst_index_entry_assoc_map (GstIndexEntry *entry, + GstFormat format, gint64 *value); + +G_END_DECLS + +#endif /* __GST_INDEX_H__ */ diff --git a/libs/gst/base/gstmemindex.c b/libs/gst/base/gstmemindex.c new file mode 100644 index 0000000..b667447 --- /dev/null +++ b/libs/gst/base/gstmemindex.c @@ -0,0 +1,430 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#define GST_TYPE_MEM_INDEX \ + (gst_index_get_type ()) +#define GST_MEM_INDEX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MEM_INDEX, GstMemIndex)) +#define GST_MEM_INDEX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MEM_INDEX, GstMemIndexClass)) +#define GST_IS_MEM_INDEX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MEM_INDEX)) +#define GST_IS_MEM_INDEX_CLASS(klass) \ + (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MEM_INDEX)) + +/* + * Object model: + * + * All entries are simply added to a GList first. Then we build + * an index to each entry for each id/format + * + * + * memindex + * -----------------------------... + * ! ! + * id1 id2 + * ------------ + * ! ! + * format1 format2 + * ! ! + * GTree GTree + * + * + * The memindex creates a MemIndexId object for each writer id, a + * Hashtable is kept to map the id to the MemIndexId + * + * The MemIndexId keeps a MemIndexFormatIndex for each format the + * specific writer wants indexed. + * + * The MemIndexFormatIndex keeps all the values of the particular + * format in a GTree, The values of the GTree point back to the entry. + * + * Finding a value for an id/format requires locating the correct GTree, + * then do a lookup in the Tree to get the required value. + */ + +typedef struct +{ + GstFormat format; + gint offset; + GTree *tree; +} +GstMemIndexFormatIndex; + +typedef struct +{ + gint id; + GHashTable *format_index; +} +GstMemIndexId; + +typedef struct _GstMemIndex GstMemIndex; +typedef struct _GstMemIndexClass GstMemIndexClass; + +struct _GstMemIndex +{ + GstIndex parent; + + GList *associations; + + GHashTable *id_index; +}; + +struct _GstMemIndexClass +{ + GstIndexClass parent_class; +}; + +static void gst_mem_index_finalize (GObject * object); + +static void gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry); +static GstIndexEntry *gst_mem_index_get_assoc_entry (GstIndex * index, gint id, + GstIndexLookupMethod method, GstIndexAssociationFlags flags, + GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data); + +#define CLASS(mem_index) GST_MEM_INDEX_CLASS (G_OBJECT_GET_CLASS (mem_index)) + +static GType gst_mem_index_get_type (void); + +G_DEFINE_TYPE (GstMemIndex, gst_mem_index, GST_TYPE_INDEX); + +static void +gst_mem_index_class_init (GstMemIndexClass * klass) +{ + GObjectClass *gobject_class; + GstIndexClass *gstindex_class; + + gobject_class = (GObjectClass *) klass; + gstindex_class = (GstIndexClass *) klass; + + gobject_class->finalize = gst_mem_index_finalize; + + gstindex_class->add_entry = GST_DEBUG_FUNCPTR (gst_mem_index_add_entry); + gstindex_class->get_assoc_entry = + GST_DEBUG_FUNCPTR (gst_mem_index_get_assoc_entry); +} + +static void +gst_mem_index_init (GstMemIndex * index) +{ + GST_DEBUG ("created new mem index"); + + index->associations = NULL; + index->id_index = g_hash_table_new (g_int_hash, g_int_equal); +} + +static void +gst_mem_index_free_format (gpointer key, gpointer value, gpointer user_data) +{ + GstMemIndexFormatIndex *index = (GstMemIndexFormatIndex *) value; + + if (index->tree) { + g_tree_destroy (index->tree); + } + + g_slice_free (GstMemIndexFormatIndex, index); +} + +static void +gst_mem_index_free_id (gpointer key, gpointer value, gpointer user_data) +{ + GstMemIndexId *id_index = (GstMemIndexId *) value; + + if (id_index->format_index) { + g_hash_table_foreach (id_index->format_index, gst_mem_index_free_format, + NULL); + g_hash_table_destroy (id_index->format_index); + id_index->format_index = NULL; + } + + g_slice_free (GstMemIndexId, id_index); +} + +static void +gst_mem_index_finalize (GObject * object) +{ + GstMemIndex *memindex = GST_MEM_INDEX (object); + + /* Delete the trees referencing the associations first */ + if (memindex->id_index) { + g_hash_table_foreach (memindex->id_index, gst_mem_index_free_id, NULL); + g_hash_table_destroy (memindex->id_index); + memindex->id_index = NULL; + } + + /* Then delete the associations themselves */ + if (memindex->associations) { + g_list_foreach (memindex->associations, (GFunc) gst_index_entry_free, NULL); + g_list_free (memindex->associations); + memindex->associations = NULL; + } + + G_OBJECT_CLASS (gst_mem_index_parent_class)->finalize (object); +} + +static void +gst_mem_index_add_id (GstIndex * index, GstIndexEntry * entry) +{ + GstMemIndex *memindex = GST_MEM_INDEX (index); + GstMemIndexId *id_index; + + id_index = g_hash_table_lookup (memindex->id_index, &entry->id); + + if (!id_index) { + id_index = g_slice_new0 (GstMemIndexId); + + id_index->id = entry->id; + id_index->format_index = g_hash_table_new (g_int_hash, g_int_equal); + g_hash_table_insert (memindex->id_index, &id_index->id, id_index); + } +} + +static gint +mem_index_compare (gconstpointer a, gconstpointer b, gpointer user_data) +{ + GstMemIndexFormatIndex *index = user_data; + gint64 val1, val2; + gint64 diff; + + val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset); + val2 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) b), index->offset); + + diff = (val2 - val1); + + return (diff == 0 ? 0 : (diff > 0 ? 1 : -1)); +} + +static void +gst_mem_index_index_format (GstMemIndexId * id_index, GstIndexEntry * entry, + gint assoc) +{ + GstMemIndexFormatIndex *index; + GstFormat *format; + + format = &GST_INDEX_ASSOC_FORMAT (entry, assoc); + + index = g_hash_table_lookup (id_index->format_index, format); + + if (!index) { + index = g_slice_new0 (GstMemIndexFormatIndex); + + index->format = *format; + index->offset = assoc; + index->tree = g_tree_new_with_data (mem_index_compare, index); + + g_hash_table_insert (id_index->format_index, &index->format, index); + } + + g_tree_insert (index->tree, entry, entry); +} + +static void +gst_mem_index_add_association (GstIndex * index, GstIndexEntry * entry) +{ + GstMemIndex *memindex = GST_MEM_INDEX (index); + GstMemIndexId *id_index; + + memindex->associations = g_list_prepend (memindex->associations, entry); + + id_index = g_hash_table_lookup (memindex->id_index, &entry->id); + if (id_index) { + gint i; + + for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) { + gst_mem_index_index_format (id_index, entry, i); + } + } +} + +static void +gst_mem_index_add_object (GstIndex * index, GstIndexEntry * entry) +{ +} + +static void +gst_mem_index_add_format (GstIndex * index, GstIndexEntry * entry) +{ +} + +static void +gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry) +{ + GST_LOG_OBJECT (index, "added this entry"); + + switch (entry->type) { + case GST_INDEX_ENTRY_ID: + gst_mem_index_add_id (index, entry); + break; + case GST_INDEX_ENTRY_ASSOCIATION: + gst_mem_index_add_association (index, entry); + break; + case GST_INDEX_ENTRY_OBJECT: + gst_mem_index_add_object (index, entry); + break; + case GST_INDEX_ENTRY_FORMAT: + gst_mem_index_add_format (index, entry); + break; + default: + break; + } +} + +typedef struct +{ + gint64 value; + GstMemIndexFormatIndex *index; + gboolean exact; + GstIndexEntry *lower; + gint64 low_diff; + GstIndexEntry *higher; + gint64 high_diff; +} +GstMemIndexSearchData; + +static gint +mem_index_search (gconstpointer a, gconstpointer b) +{ + GstMemIndexSearchData *data = (GstMemIndexSearchData *) b; + GstMemIndexFormatIndex *index = data->index; + gint64 val1, val2; + gint64 diff; + + val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset); + val2 = data->value; + + diff = (val1 - val2); + if (diff == 0) + return 0; + + /* exact matching, don't update low/high */ + if (data->exact) + return (diff > 0 ? 1 : -1); + + if (diff < 0) { + if (diff > data->low_diff) { + data->low_diff = diff; + data->lower = (GstIndexEntry *) a; + } + diff = -1; + } else { + if (diff < data->high_diff) { + data->high_diff = diff; + data->higher = (GstIndexEntry *) a; + } + diff = 1; + } + + return diff; +} + +static GstIndexEntry * +gst_mem_index_get_assoc_entry (GstIndex * index, gint id, + GstIndexLookupMethod method, + GstIndexAssociationFlags flags, + GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data) +{ + GstMemIndex *memindex = GST_MEM_INDEX (index); + GstMemIndexId *id_index; + GstMemIndexFormatIndex *format_index; + GstIndexEntry *entry; + GstMemIndexSearchData data; + + id_index = g_hash_table_lookup (memindex->id_index, &id); + if (!id_index) + return NULL; + + format_index = g_hash_table_lookup (id_index->format_index, &format); + if (!format_index) + return NULL; + + data.value = value; + data.index = format_index; + data.exact = (method == GST_INDEX_LOOKUP_EXACT); + + /* setup data for low/high checks if we are not looking + * for an exact match */ + if (!data.exact) { + data.low_diff = G_MININT64; + data.lower = NULL; + data.high_diff = G_MAXINT64; + data.higher = NULL; + } + + entry = g_tree_search (format_index->tree, mem_index_search, &data); + + /* get the low/high values if we're not exact */ + if (entry == NULL && !data.exact) { + if (method == GST_INDEX_LOOKUP_BEFORE) + entry = data.lower; + else if (method == GST_INDEX_LOOKUP_AFTER) { + entry = data.higher; + } + } + + if (entry && ((GST_INDEX_ASSOC_FLAGS (entry) & flags) != flags)) { + if (method != GST_INDEX_LOOKUP_EXACT) { + GList *l_entry = g_list_find (memindex->associations, entry); + + entry = NULL; + + while (l_entry) { + entry = (GstIndexEntry *) l_entry->data; + + if (entry->id == id && (GST_INDEX_ASSOC_FLAGS (entry) & flags) == flags) + break; + + if (method == GST_INDEX_LOOKUP_BEFORE) + l_entry = g_list_next (l_entry); + else if (method == GST_INDEX_LOOKUP_AFTER) { + l_entry = g_list_previous (l_entry); + } + } + } else { + entry = NULL; + } + } + + return entry; +} + +#if 0 +gboolean +gst_mem_index_plugin_init (GstPlugin * plugin) +{ + GstIndexFactory *factory; + + factory = gst_index_factory_new ("memindex", + "A index that stores entries in memory", gst_mem_index_get_type ()); + + if (factory == NULL) { + g_warning ("failed to create memindex factory"); + return FALSE; + } + + GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE (factory)->loaded = TRUE; + + gst_registry_add_feature (gst_registry_get_default (), + GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} +#endif diff --git a/libs/gst/base/gstpushsrc.c b/libs/gst/base/gstpushsrc.c new file mode 100644 index 0000000..db0a6d3 --- /dev/null +++ b/libs/gst/base/gstpushsrc.c @@ -0,0 +1,173 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gstpushsrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstpushsrc + * @title: GstPushSrc + * @short_description: Base class for push based source elements + * @see_also: #GstBaseSrc + * + * This class is mostly useful for elements that cannot do + * random access, or at least very slowly. The source usually + * prefers to push out a fixed size buffer. + * + * Subclasses usually operate in a format that is different from the + * default GST_FORMAT_BYTES format of #GstBaseSrc. + * + * Classes extending this base class will usually be scheduled + * in a push based mode. If the peer accepts to operate without + * offsets and within the limits of the allowed block size, this + * class can operate in getrange based mode automatically. To make + * this possible, the subclass should implement and override the + * SCHEDULING query. + * + * The subclass should extend the methods from the baseclass in + * addition to the ::create method. + * + * Seeking, flushing, scheduling and sync is all handled by this + * base class. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstpushsrc.h" +#include "gsttypefindhelper.h" + +GST_DEBUG_CATEGORY_STATIC (gst_push_src_debug); +#define GST_CAT_DEFAULT gst_push_src_debug + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_push_src_debug, "pushsrc", 0, \ + "pushsrc element"); + +#define gst_push_src_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstPushSrc, gst_push_src, GST_TYPE_BASE_SRC, _do_init); + +static gboolean gst_push_src_query (GstBaseSrc * src, GstQuery * query); +static GstFlowReturn gst_push_src_create (GstBaseSrc * bsrc, guint64 offset, + guint length, GstBuffer ** ret); +static GstFlowReturn gst_push_src_alloc (GstBaseSrc * bsrc, guint64 offset, + guint length, GstBuffer ** ret); +static GstFlowReturn gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset, + guint length, GstBuffer * ret); + +static void +gst_push_src_class_init (GstPushSrcClass * klass) +{ + GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; + + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_push_src_create); + gstbasesrc_class->alloc = GST_DEBUG_FUNCPTR (gst_push_src_alloc); + gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_push_src_fill); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_push_src_query); +} + +static void +gst_push_src_init (GstPushSrc * pushsrc) +{ + /* nop */ +} + +static gboolean +gst_push_src_query (GstBaseSrc * src, GstQuery * query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + { + /* a pushsrc can by default never operate in pull mode override + * if you want something different. */ + gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1, + 0); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + + ret = TRUE; + break; + } + default: + ret = GST_BASE_SRC_CLASS (parent_class)->query (src, query); + break; + } + return ret; +} + + +static GstFlowReturn +gst_push_src_create (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFlowReturn fret; + GstPushSrc *src; + GstPushSrcClass *pclass; + + src = GST_PUSH_SRC (bsrc); + pclass = GST_PUSH_SRC_GET_CLASS (src); + if (pclass->create) + fret = pclass->create (src, ret); + else + fret = + GST_BASE_SRC_CLASS (parent_class)->create (bsrc, offset, length, ret); + + return fret; +} + +static GstFlowReturn +gst_push_src_alloc (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFlowReturn fret; + GstPushSrc *src; + GstPushSrcClass *pclass; + + src = GST_PUSH_SRC (bsrc); + pclass = GST_PUSH_SRC_GET_CLASS (src); + if (pclass->alloc) + fret = pclass->alloc (src, ret); + else + fret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, ret); + + return fret; +} + +static GstFlowReturn +gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer * ret) +{ + GstFlowReturn fret; + GstPushSrc *src; + GstPushSrcClass *pclass; + + src = GST_PUSH_SRC (bsrc); + pclass = GST_PUSH_SRC_GET_CLASS (src); + if (pclass->fill) + fret = pclass->fill (src, ret); + else + fret = GST_BASE_SRC_CLASS (parent_class)->fill (bsrc, offset, length, ret); + + return fret; +} diff --git a/libs/gst/base/gstpushsrc.h b/libs/gst/base/gstpushsrc.h new file mode 100644 index 0000000..89e6776 --- /dev/null +++ b/libs/gst/base/gstpushsrc.h @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstpushsrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PUSH_SRC_H__ +#define __GST_PUSH_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PUSH_SRC (gst_push_src_get_type()) +#define GST_PUSH_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PUSH_SRC,GstPushSrc)) +#define GST_PUSH_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PUSH_SRC,GstPushSrcClass)) +#define GST_PUSH_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PUSH_SRC, GstPushSrcClass)) +#define GST_IS_PUSH_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PUSH_SRC)) +#define GST_IS_PUSH_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PUSH_SRC)) + +typedef struct _GstPushSrc GstPushSrc; +typedef struct _GstPushSrcClass GstPushSrcClass; + +/** + * GstPushSrc: + * + * The opaque #GstPushSrc data structure. + */ +struct _GstPushSrc { + GstBaseSrc parent; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstPushSrcClass: + * @parent_class: Element parent class + * @create: Ask the subclass to create a buffer. The subclass decides which + * size this buffer should be. Other then that, refer to + * #GstBaseSrc.create() for more details. If this method is + * not implemented, @alloc followed by @fill will be called. + * @alloc: Ask the subclass to allocate a buffer. The subclass decides which + * size this buffer should be. The default implementation will create + * a new buffer from the negotiated allocator. + * @fill: Ask the subclass to fill the buffer with data. + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At the minimum, the @fill method should be overridden to produce + * buffers. + */ +struct _GstPushSrcClass { + GstBaseSrcClass parent_class; + + /* ask the subclass to create a buffer, the default implementation + * uses alloc and fill */ + GstFlowReturn (*create) (GstPushSrc *src, GstBuffer **buf); + /* allocate memory for a buffer */ + GstFlowReturn (*alloc) (GstPushSrc *src, GstBuffer **buf); + /* ask the subclass to fill a buffer */ + GstFlowReturn (*fill) (GstPushSrc *src, GstBuffer *buf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_BASE_API +GType gst_push_src_get_type (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPushSrc, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PUSH_SRC_H__ */ diff --git a/libs/gst/base/gstqueuearray.c b/libs/gst/base/gstqueuearray.c new file mode 100644 index 0000000..c52ee39 --- /dev/null +++ b/libs/gst/base/gstqueuearray.c @@ -0,0 +1,642 @@ +/* GStreamer + * Copyright (C) 2009 Edward Hervey + * Copyright (C) 2015 Tim-Philipp Müller + * + * gstqueuearray.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstqueuearray + * @title: GstQueueArray + * @short_description: Array based queue object + * + * #GstQueueArray is an object that provides standard queue functionality + * based on an array instead of linked lists. This reduces the overhead + * caused by memory management by a large factor. + */ + + +#include +#include +#include "gstqueuearray.h" + +struct _GstQueueArray +{ + /* < private > */ + guint8 *array; + guint size; + guint head; + guint tail; + guint length; + guint elt_size; + gboolean struct_array; +}; + +/** + * gst_queue_array_new_for_struct: (skip) + * @struct_size: Size of each element (e.g. structure) in the array + * @initial_size: Initial size of the new queue + * + * Allocates a new #GstQueueArray object for elements (e.g. structures) + * of size @struct_size, with an initial queue size of @initial_size. + * + * Returns: a new #GstQueueArray object + * + * Since: 1.6 + */ +GstQueueArray * +gst_queue_array_new_for_struct (gsize struct_size, guint initial_size) +{ + GstQueueArray *array; + + g_return_val_if_fail (struct_size > 0, NULL); + + array = g_slice_new (GstQueueArray); + array->elt_size = struct_size; + array->size = initial_size; + array->array = g_malloc0 (struct_size * initial_size); + array->head = 0; + array->tail = 0; + array->length = 0; + array->struct_array = TRUE; + return array; +} + +/** + * gst_queue_array_new: (skip) + * @initial_size: Initial size of the new queue + * + * Allocates a new #GstQueueArray object with an initial + * queue size of @initial_size. + * + * Returns: a new #GstQueueArray object + * + * Since: 1.2 + */ +GstQueueArray * +gst_queue_array_new (guint initial_size) +{ + GstQueueArray *array; + + array = gst_queue_array_new_for_struct (sizeof (gpointer), initial_size); + array->struct_array = FALSE; + return array; +} + +/** + * gst_queue_array_free: (skip) + * @array: a #GstQueueArray object + * + * Frees queue @array and all memory associated to it. + * + * Since: 1.2 + */ +void +gst_queue_array_free (GstQueueArray * array) +{ + g_return_if_fail (array != NULL); + g_free (array->array); + g_slice_free (GstQueueArray, array); +} + +/** + * gst_queue_array_pop_head_struct: (skip) + * @array: a #GstQueueArray object + * + * Returns the head of the queue @array and removes it from the queue. + * + * Returns: pointer to element or struct, or NULL if @array was empty. The + * data pointed to by the returned pointer stays valid only as long as + * the queue array is not modified further! + * + * Since: 1.6 + */ +gpointer +gst_queue_array_pop_head_struct (GstQueueArray * array) +{ + gpointer p_struct; + g_return_val_if_fail (array != NULL, NULL); + /* empty array */ + if (G_UNLIKELY (array->length == 0)) + return NULL; + + p_struct = array->array + (array->elt_size * array->head); + + array->head++; + array->head %= array->size; + array->length--; + + return p_struct; +} + +/** + * gst_queue_array_pop_head: (skip) + * @array: a #GstQueueArray object + * + * Returns and head of the queue @array and removes + * it from the queue. + * + * Returns: The head of the queue + * + * Since: 1.2 + */ +gpointer +gst_queue_array_pop_head (GstQueueArray * array) +{ + gpointer ret; + g_return_val_if_fail (array != NULL, NULL); + + /* empty array */ + if (G_UNLIKELY (array->length == 0)) + return NULL; + + ret = *(gpointer *) (array->array + (sizeof (gpointer) * array->head)); + array->head++; + array->head %= array->size; + array->length--; + return ret; +} + +/** + * gst_queue_array_peek_head_struct: (skip) + * @array: a #GstQueueArray object + * + * Returns the head of the queue @array without removing it from the queue. + * + * Returns: pointer to element or struct, or NULL if @array was empty. The + * data pointed to by the returned pointer stays valid only as long as + * the queue array is not modified further! + * + * Since: 1.6 + */ +gpointer +gst_queue_array_peek_head_struct (GstQueueArray * array) +{ + g_return_val_if_fail (array != NULL, NULL); + /* empty array */ + if (G_UNLIKELY (array->length == 0)) + return NULL; + + return array->array + (array->elt_size * array->head); +} + +/** + * gst_queue_array_peek_head: (skip) + * @array: a #GstQueueArray object + * + * Returns the head of the queue @array and does not + * remove it from the queue. + * + * Returns: The head of the queue + * + * Since: 1.2 + */ +gpointer +gst_queue_array_peek_head (GstQueueArray * array) +{ + g_return_val_if_fail (array != NULL, NULL); + /* empty array */ + if (G_UNLIKELY (array->length == 0)) + return NULL; + + return *(gpointer *) (array->array + (sizeof (gpointer) * array->head)); +} + +static void +gst_queue_array_do_expand (GstQueueArray * array) +{ + guint elt_size = array->elt_size; + /* newsize is 50% bigger */ + guint oldsize = array->size; + guint newsize = MAX ((3 * oldsize) / 2, oldsize + 1); + + /* copy over data */ + if (array->tail != 0) { + guint8 *array2 = g_malloc0 (elt_size * newsize); + guint t1 = array->head; + guint t2 = oldsize - array->head; + + /* [0-----TAIL][HEAD------SIZE] + * + * We want to end up with + * [HEAD------------------TAIL][----FREEDATA------NEWSIZE] + * + * 1) move [HEAD-----SIZE] part to beginning of new array + * 2) move [0-------TAIL] part new array, after previous part + */ + + memcpy (array2, array->array + (elt_size * array->head), t2 * elt_size); + memcpy (array2 + t2 * elt_size, array->array, t1 * elt_size); + + g_free (array->array); + array->array = array2; + array->head = 0; + } else { + /* Fast path, we just need to grow the array */ + array->array = g_realloc (array->array, elt_size * newsize); + memset (array->array + elt_size * oldsize, 0, + elt_size * (newsize - oldsize)); + } + array->tail = oldsize; + array->size = newsize; +} + +/** + * gst_queue_array_push_element_tail: (skip) + * @array: a #GstQueueArray object + * @p_struct: address of element or structure to push to the tail of the queue + * + * Pushes the element at address @p_struct to the tail of the queue @array + * (Copies the contents of a structure of the struct_size specified when + * creating the queue into the array). + * + * Since: 1.6 + */ +void +gst_queue_array_push_tail_struct (GstQueueArray * array, gpointer p_struct) +{ + guint elt_size; + + g_return_if_fail (p_struct != NULL); + g_return_if_fail (array != NULL); + elt_size = array->elt_size; + + /* Check if we need to make room */ + if (G_UNLIKELY (array->length == array->size)) + gst_queue_array_do_expand (array); + + memcpy (array->array + elt_size * array->tail, p_struct, elt_size); + array->tail++; + array->tail %= array->size; + array->length++; +} + +/** + * gst_queue_array_push_tail: (skip) + * @array: a #GstQueueArray object + * @data: object to push + * + * Pushes @data to the tail of the queue @array. + * + * Since: 1.2 + */ +void +gst_queue_array_push_tail (GstQueueArray * array, gpointer data) +{ + g_return_if_fail (array != NULL); + + /* Check if we need to make room */ + if (G_UNLIKELY (array->length == array->size)) + gst_queue_array_do_expand (array); + + *(gpointer *) (array->array + sizeof (gpointer) * array->tail) = data; + array->tail++; + array->tail %= array->size; + array->length++; +} + +/** + * gst_queue_array_peek_tail: (skip) + * @array: a #GstQueueArray object + * + * Returns the tail of the queue @array, but does not remove it from the queue. + * + * Returns: The tail of the queue + * + * Since: 1.14 + */ +gpointer +gst_queue_array_peek_tail (GstQueueArray * array) +{ + guint len, idx; + + g_return_val_if_fail (array != NULL, NULL); + + len = array->length; + + /* empty array */ + if (len == 0) + return NULL; + + idx = (array->head + (len - 1)) % array->size; + + return *(gpointer *) (array->array + (sizeof (gpointer) * idx)); +} + +/** + * gst_queue_array_peek_tail_struct: (skip) + * @array: a #GstQueueArray object + * + * Returns the tail of the queue @array, but does not remove it from the queue. + * + * Returns: The tail of the queue + * + * Since: 1.14 + */ +gpointer +gst_queue_array_peek_tail_struct (GstQueueArray * array) +{ + guint len, idx; + + g_return_val_if_fail (array != NULL, NULL); + + len = array->length; + + /* empty array */ + if (len == 0) + return NULL; + + idx = (array->head + (len - 1)) % array->size; + + return array->array + (array->elt_size * idx); +} + +/** + * gst_queue_array_pop_tail: (skip) + * @array: a #GstQueueArray object + * + * Returns the tail of the queue @array and removes + * it from the queue. + * + * Returns: The tail of the queue + * + * Since: 1.14 + */ +gpointer +gst_queue_array_pop_tail (GstQueueArray * array) +{ + gpointer ret; + guint len, idx; + + g_return_val_if_fail (array != NULL, NULL); + + len = array->length; + + /* empty array */ + if (len == 0) + return NULL; + + idx = (array->head + (len - 1)) % array->size; + + ret = *(gpointer *) (array->array + (sizeof (gpointer) * idx)); + + array->tail = idx; + array->length--; + + return ret; +} + +/** + * gst_queue_array_pop_tail_struct: (skip) + * @array: a #GstQueueArray object + * + * Returns the tail of the queue @array and removes + * it from the queue. + * + * Returns: The tail of the queue + * + * Since: 1.14 + */ +gpointer +gst_queue_array_pop_tail_struct (GstQueueArray * array) +{ + gpointer ret; + guint len, idx; + + g_return_val_if_fail (array != NULL, NULL); + + len = array->length; + + /* empty array */ + if (len == 0) + return NULL; + + idx = (array->head + (len - 1)) % array->size; + + ret = array->array + (array->elt_size * idx); + + array->tail = idx; + array->length--; + + return ret; +} + +/** + * gst_queue_array_is_empty: (skip) + * @array: a #GstQueueArray object + * + * Checks if the queue @array is empty. + * + * Returns: %TRUE if the queue @array is empty + * + * Since: 1.2 + */ +gboolean +gst_queue_array_is_empty (GstQueueArray * array) +{ + g_return_val_if_fail (array != NULL, FALSE); + return (array->length == 0); +} + + +/** + * gst_queue_array_drop_struct: (skip) + * @array: a #GstQueueArray object + * @idx: index to drop + * @p_struct: address into which to store the data of the dropped structure, or NULL + * + * Drops the queue element at position @idx from queue @array and copies the + * data of the element or structure that was removed into @p_struct if + * @p_struct is set (not NULL). + * + * Returns: TRUE on success, or FALSE on error + * + * Since: 1.6 + */ +gboolean +gst_queue_array_drop_struct (GstQueueArray * array, guint idx, + gpointer p_struct) +{ + int first_item_index, last_item_index; + guint elt_size; + + g_return_val_if_fail (array != NULL, FALSE); + g_return_val_if_fail (array->length > 0, FALSE); + g_return_val_if_fail (idx < array->size, FALSE); + + elt_size = array->elt_size; + + first_item_index = array->head; + + /* tail points to the first free spot */ + last_item_index = (array->tail - 1 + array->size) % array->size; + + if (p_struct != NULL) + memcpy (p_struct, array->array + elt_size * idx, elt_size); + + /* simple case idx == first item */ + if (idx == first_item_index) { + /* move the head plus one */ + array->head++; + array->head %= array->size; + array->length--; + return TRUE; + } + + /* simple case idx == last item */ + if (idx == last_item_index) { + /* move tail minus one, potentially wrapping */ + array->tail = (array->tail - 1 + array->size) % array->size; + array->length--; + return TRUE; + } + + /* non-wrapped case */ + if (first_item_index < last_item_index) { + g_assert (first_item_index < idx && idx < last_item_index); + /* move everything beyond idx one step towards zero in array */ + memmove (array->array + elt_size * idx, + array->array + elt_size * (idx + 1), + (last_item_index - idx) * elt_size); + /* tail might wrap, ie if tail == 0 (and last_item_index == size) */ + array->tail = (array->tail - 1 + array->size) % array->size; + array->length--; + return TRUE; + } + + /* only wrapped cases left */ + g_assert (first_item_index > last_item_index); + + if (idx < last_item_index) { + /* idx is before last_item_index, move data towards zero */ + memmove (array->array + elt_size * idx, + array->array + elt_size * (idx + 1), + (last_item_index - idx) * elt_size); + /* tail should not wrap in this case! */ + g_assert (array->tail > 0); + array->tail--; + array->length--; + return TRUE; + } + + if (idx > first_item_index) { + /* idx is after first_item_index, move data to higher indices */ + memmove (array->array + elt_size * (first_item_index + 1), + array->array + elt_size * first_item_index, + (idx - first_item_index) * elt_size); + array->head++; + /* head should not wrap in this case! */ + g_assert (array->head < array->size); + array->length--; + return TRUE; + } + + g_return_val_if_reached (FALSE); +} + +/** + * gst_queue_array_drop_element: (skip) + * @array: a #GstQueueArray object + * @idx: index to drop + * + * Drops the queue element at position @idx from queue @array. + * + * Returns: the dropped element + * + * Since: 1.2 + */ +gpointer +gst_queue_array_drop_element (GstQueueArray * array, guint idx) +{ + gpointer ptr; + + if (!gst_queue_array_drop_struct (array, idx, &ptr)) + return NULL; + + return ptr; +} + +/** + * gst_queue_array_find: (skip) + * @array: a #GstQueueArray object + * @func: (allow-none): comparison function, or %NULL to find @data by value + * @data: data for comparison function + * + * Finds an element in the queue @array, either by comparing every element + * with @func or by looking up @data if no compare function @func is provided, + * and returning the index of the found element. + * + * Note that the index is not 0-based, but an internal index number with a + * random offset. The index can be used in connection with + * gst_queue_array_drop_element(). FIXME: return index 0-based and make + * gst_queue_array_drop_element() take a 0-based index. + * + * Returns: Index of the found element or -1 if nothing was found. + * + * Since: 1.2 + */ +guint +gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data) +{ + gpointer p_element; + guint elt_size; + guint i; + + /* For struct arrays we need to implement this differently so that + * the user gets a pointer to the element data not the dereferenced + * pointer itself */ + + g_return_val_if_fail (array != NULL, -1); + g_return_val_if_fail (array->struct_array == FALSE, -1); + + elt_size = array->elt_size; + + if (func != NULL) { + /* Scan from head to tail */ + for (i = 0; i < array->length; i++) { + p_element = array->array + ((i + array->head) % array->size) * elt_size; + if (func (*(gpointer *) p_element, data) == 0) + return (i + array->head) % array->size; + } + } else { + for (i = 0; i < array->length; i++) { + p_element = array->array + ((i + array->head) % array->size) * elt_size; + if (*(gpointer *) p_element == data) + return (i + array->head) % array->size; + } + } + + return -1; +} + +/** + * gst_queue_array_get_length: (skip) + * @array: a #GstQueueArray object + * + * Returns the length of the queue @array + * + * Returns: the length of the queue @array. + * + * Since: 1.2 + */ +guint +gst_queue_array_get_length (GstQueueArray * array) +{ + g_return_val_if_fail (array != NULL, 0); + return array->length; +} diff --git a/libs/gst/base/gstqueuearray.h b/libs/gst/base/gstqueuearray.h new file mode 100644 index 0000000..7f6db21 --- /dev/null +++ b/libs/gst/base/gstqueuearray.h @@ -0,0 +1,95 @@ +/* GStreamer + * Copyright (C) 2009-2010 Edward Hervey + * + * gstqueuearray.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#ifndef __GST_QUEUE_ARRAY_H__ +#define __GST_QUEUE_ARRAY_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstQueueArray: (skip) + */ +typedef struct _GstQueueArray GstQueueArray; + +GST_BASE_API +GstQueueArray * gst_queue_array_new (guint initial_size); + +GST_BASE_API +void gst_queue_array_free (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_pop_head (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_peek_head (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_pop_tail (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_peek_tail (GstQueueArray * array); + +GST_BASE_API +void gst_queue_array_push_tail (GstQueueArray * array, + gpointer data); +GST_BASE_API +gboolean gst_queue_array_is_empty (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_drop_element (GstQueueArray * array, + guint idx); +GST_BASE_API +guint gst_queue_array_find (GstQueueArray * array, + GCompareFunc func, + gpointer data); +GST_BASE_API +guint gst_queue_array_get_length (GstQueueArray * array); + +/* Functions for use with structures */ + +GST_BASE_API +GstQueueArray * gst_queue_array_new_for_struct (gsize struct_size, + guint initial_size); +GST_BASE_API +void gst_queue_array_push_tail_struct (GstQueueArray * array, + gpointer p_struct); +GST_BASE_API +gpointer gst_queue_array_pop_head_struct (GstQueueArray * array); + +GST_BASE_API +gpointer gst_queue_array_peek_head_struct (GstQueueArray * array); + +GST_BASE_API +gboolean gst_queue_array_drop_struct (GstQueueArray * array, + guint idx, + gpointer p_struct); +GST_BASE_API +gpointer gst_queue_array_pop_tail_struct (GstQueueArray * array); +GST_BASE_API +gpointer gst_queue_array_peek_tail_struct (GstQueueArray * array); + +G_END_DECLS + +#endif diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c new file mode 100644 index 0000000..1723f34 --- /dev/null +++ b/libs/gst/base/gsttypefindhelper.c @@ -0,0 +1,672 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * Copyright (C) 2000,2005 Wim Taymans + * Copyright (C) 2006 Tim-Philipp Müller + * + * gsttypefindhelper.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttypefindhelper + * @title: GstTypeFindHelper + * @short_description: Utility functions for typefinding + * + * Utility functions for elements doing typefinding: + * gst_type_find_helper() does typefinding in pull mode, while + * gst_type_find_helper_for_buffer() is useful for elements needing to do + * typefinding in push mode from a chain function. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gsttypefindhelper.h" + +/* ********************** typefinding in pull mode ************************ */ + +static void +helper_find_suggest (gpointer data, guint probability, GstCaps * caps); + +typedef struct +{ + GstBuffer *buffer; + GstMapInfo map; +} GstMappedBuffer; + +typedef struct +{ + GSList *buffers; /* buffer cache */ + guint64 size; + guint64 last_offset; + GstTypeFindHelperGetRangeFunction func; + GstTypeFindProbability best_probability; + GstCaps *caps; + GstTypeFindFactory *factory; /* for logging */ + GstObject *obj; /* for logging */ + GstObject *parent; +} GstTypeFindHelper; + +/* + * helper_find_peek: + * @data: helper data struct + * @off: stream offset + * @size: block size + * + * Get data pointer within a stream. Keeps a cache of read buffers (partly + * for performance reasons, but mostly because pointers returned by us need + * to stay valid until typefinding has finished) + * + * Returns: (nullable): address of the data or %NULL if buffer does not cover + * the requested range. + */ +static const guint8 * +helper_find_peek (gpointer data, gint64 offset, guint size) +{ + GstTypeFindHelper *helper; + GstBuffer *buffer; + GstFlowReturn ret; + GSList *insert_pos = NULL; + gsize buf_size; + guint64 buf_offset; + GstMappedBuffer *bmap; +#if 0 + GstCaps *caps; +#endif + + helper = (GstTypeFindHelper *) data; + + GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT + ", %u)", GST_OBJECT_NAME (helper->factory), offset, size); + + if (size == 0) + return NULL; + + if (offset < 0) { + if (helper->size == -1 || helper->size < -offset) + return NULL; + + offset += helper->size; + } + + /* see if we have a matching buffer already in our list */ + if (size > 0 && offset <= helper->last_offset) { + GSList *walk; + + for (walk = helper->buffers; walk; walk = walk->next) { + GstMappedBuffer *bmp = (GstMappedBuffer *) walk->data; + GstBuffer *buf = GST_BUFFER_CAST (bmp->buffer); + + buf_offset = GST_BUFFER_OFFSET (buf); + buf_size = bmp->map.size; + + /* buffers are kept sorted by end offset (highest first) in the list, so + * at this point we save the current position and stop searching if + * we're after the searched end offset */ + if (buf_offset <= offset) { + if ((offset + size) < (buf_offset + buf_size)) { + /* must already have been mapped before */ + return (guint8 *) bmp->map.data + (offset - buf_offset); + } + } else if (offset + size >= buf_offset + buf_size) { + insert_pos = walk; + break; + } + } + } + + buffer = NULL; + /* some typefinders go in 1 byte steps over 1k of data and request + * small buffers. It is really inefficient to pull each time, and pulling + * a larger chunk is almost free. Trying to pull a larger chunk at the end + * of the file is also not a problem here, we'll just get a truncated buffer + * in that case (and we'll have to double-check the size we actually get + * anyway, see below) */ + ret = + helper->func (helper->obj, helper->parent, offset, MAX (size, 4096), + &buffer); + + if (ret != GST_FLOW_OK) + goto error; + +#if 0 + caps = GST_BUFFER_CAPS (buffer); + + if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) { + GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability", + caps); + + gst_caps_replace (&helper->caps, caps); + helper->best_probability = GST_TYPE_FIND_MAXIMUM; + + gst_buffer_unref (buffer); + return NULL; + } +#endif + + /* getrange might silently return shortened buffers at the end of a file, + * we must, however, always return either the full requested data or %NULL */ + buf_offset = GST_BUFFER_OFFSET (buffer); + buf_size = gst_buffer_get_size (buffer); + + if (buf_size < size) { + GST_DEBUG ("dropping short buffer of size %" G_GSIZE_FORMAT "," + "requested size was %u", buf_size, size); + gst_buffer_unref (buffer); + return NULL; + } + + if (buf_offset != -1 && buf_offset != offset) { + GST_DEBUG ("dropping buffer with unexpected offset %" G_GUINT64_FORMAT ", " + "expected offset was %" G_GUINT64_FORMAT, buf_offset, offset); + gst_buffer_unref (buffer); + return NULL; + } + + bmap = g_slice_new0 (GstMappedBuffer); + + if (!gst_buffer_map (buffer, &bmap->map, GST_MAP_READ)) + goto map_failed; + + bmap->buffer = buffer; + + if (insert_pos) { + helper->buffers = g_slist_insert_before (helper->buffers, insert_pos, bmap); + } else { + /* if insert_pos is not set, our offset is bigger than the largest offset + * we have so far; since we keep the list sorted with highest offsets + * first, we need to prepend the buffer to the list */ + helper->last_offset = GST_BUFFER_OFFSET (buffer) + buf_size; + helper->buffers = g_slist_prepend (helper->buffers, bmap); + } + + return bmap->map.data; + +error: + { + GST_INFO ("typefind function returned: %s", gst_flow_get_name (ret)); + return NULL; + } +map_failed: + { + GST_ERROR ("map failed"); + gst_buffer_unref (buffer); + g_slice_free (GstMappedBuffer, bmap); + return NULL; + } +} + +/* + * helper_find_suggest: + * @data: helper data struct + * @probability: probability of the match + * @caps: caps of the type + * + * If given @probability is higher, replace previously store caps. + */ +static void +helper_find_suggest (gpointer data, guint probability, GstCaps * caps) +{ + GstTypeFindHelper *helper = (GstTypeFindHelper *) data; + + GST_LOG_OBJECT (helper->obj, + "'%s' called suggest (%u, %" GST_PTR_FORMAT ")", + GST_OBJECT_NAME (helper->factory), probability, caps); + + if (probability > helper->best_probability) { + gst_caps_replace (&helper->caps, caps); + helper->best_probability = probability; + } +} + +static guint64 +helper_find_get_length (gpointer data) +{ + GstTypeFindHelper *helper = (GstTypeFindHelper *) data; + + GST_LOG_OBJECT (helper->obj, "'%s' called get_length, returning %" + G_GUINT64_FORMAT, GST_OBJECT_NAME (helper->factory), helper->size); + + return helper->size; +} + +/** + * gst_type_find_helper_get_range: + * @obj: A #GstObject that will be passed as first argument to @func + * @parent: (allow-none): the parent of @obj or %NULL + * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will + * be used to access data at random offsets when doing the typefinding + * @size: The length in bytes + * @extension: extension of the media + * @prob: (out) (allow-none): location to store the probability of the found + * caps, or %NULL + * + * Utility function to do pull-based typefinding. Unlike gst_type_find_helper() + * however, this function will use the specified function @func to obtain the + * data needed by the typefind functions, rather than operating on a given + * source pad. This is useful mostly for elements like tag demuxers which + * strip off data at the beginning and/or end of a file and want to typefind + * the stripped data stream before adding their own source pad (the specified + * callback can then call the upstream peer pad with offsets adjusted for the + * tag size, for example). + * + * When @extension is not %NULL, this function will first try the typefind + * functions for the given extension, which might speed up the typefinding + * in many cases. + * + * Free-function: gst_caps_unref + * + * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data + * stream. Returns %NULL if no #GstCaps matches the data stream. + */ +GstCaps * +gst_type_find_helper_get_range (GstObject * obj, GstObject * parent, + GstTypeFindHelperGetRangeFunction func, guint64 size, + const gchar * extension, GstTypeFindProbability * prob) +{ + GstTypeFindHelper helper; + GstTypeFind find; + GSList *walk; + GList *l, *type_list; + GstCaps *result = NULL; + gint pos = 0; + + g_return_val_if_fail (GST_IS_OBJECT (obj), NULL); + g_return_val_if_fail (func != NULL, NULL); + + helper.buffers = NULL; + helper.size = size; + helper.last_offset = 0; + helper.func = func; + helper.best_probability = GST_TYPE_FIND_NONE; + helper.caps = NULL; + helper.obj = obj; + helper.parent = parent; + + find.data = &helper; + find.peek = helper_find_peek; + find.suggest = helper_find_suggest; + + if (size == 0 || size == (guint64) - 1) { + find.get_length = NULL; + } else { + find.get_length = helper_find_get_length; + } + + type_list = gst_type_find_factory_get_list (); + + /* move the typefinders for the extension first in the list. The idea is that + * when one of them returns MAX we don't need to search further as there is a + * very high chance we got the right type. */ + if (extension) { + GList *next; + + GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head", + extension); + + for (l = type_list; l; l = next) { + const gchar *const *ext; + GstTypeFindFactory *factory; + + next = l->next; + + factory = GST_TYPE_FIND_FACTORY (l->data); + + ext = gst_type_find_factory_get_extensions (factory); + if (ext == NULL) + continue; + + GST_LOG_OBJECT (obj, "testing factory %s for extension %s", + GST_OBJECT_NAME (factory), extension); + + while (*ext != NULL) { + if (strcmp (*ext, extension) == 0) { + /* found extension, move in front */ + GST_LOG_OBJECT (obj, "moving typefind for extension %s to head", + extension); + /* remove entry from list */ + type_list = g_list_delete_link (type_list, l); + /* insert at the position */ + type_list = g_list_insert (type_list, factory, pos); + /* next element will be inserted after this one */ + pos++; + break; + } + ++ext; + } + } + } + + for (l = type_list; l; l = l->next) { + helper.factory = GST_TYPE_FIND_FACTORY (l->data); + gst_type_find_factory_call_function (helper.factory, &find); + if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM) + break; + } + gst_plugin_feature_list_free (type_list); + + for (walk = helper.buffers; walk; walk = walk->next) { + GstMappedBuffer *bmap = (GstMappedBuffer *) walk->data; + + gst_buffer_unmap (bmap->buffer, &bmap->map); + gst_buffer_unref (bmap->buffer); + g_slice_free (GstMappedBuffer, bmap); + } + g_slist_free (helper.buffers); + + if (helper.best_probability > 0) + result = helper.caps; + + if (prob) + *prob = helper.best_probability; + + GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)", + result, (guint) helper.best_probability); + + return result; +} + +/** + * gst_type_find_helper: + * @src: A source #GstPad + * @size: The length in bytes + * + * Tries to find what type of data is flowing from the given source #GstPad. + * + * Free-function: gst_caps_unref + * + * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data + * stream. Returns %NULL if no #GstCaps matches the data stream. + */ + +GstCaps * +gst_type_find_helper (GstPad * src, guint64 size) +{ + GstTypeFindHelperGetRangeFunction func; + + g_return_val_if_fail (GST_IS_OBJECT (src), NULL); + g_return_val_if_fail (GST_PAD_GETRANGEFUNC (src) != NULL, NULL); + + func = (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (src)); + + return gst_type_find_helper_get_range (GST_OBJECT (src), + GST_OBJECT_PARENT (src), func, size, NULL, NULL); +} + +/* ********************** typefinding for buffers ************************* */ + +typedef struct +{ + const guint8 *data; /* buffer data */ + gsize size; + GstTypeFindProbability best_probability; + GstCaps *caps; + GstTypeFindFactory *factory; /* for logging */ + GstObject *obj; /* for logging */ +} GstTypeFindBufHelper; + +/* + * buf_helper_find_peek: + * @data: helper data struct + * @off: stream offset + * @size: block size + * + * Get data pointer within a buffer. + * + * Returns: (nullable): address inside the buffer or %NULL if buffer does not + * cover the requested range. + */ +static const guint8 * +buf_helper_find_peek (gpointer data, gint64 off, guint size) +{ + GstTypeFindBufHelper *helper; + + helper = (GstTypeFindBufHelper *) data; + GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT ", %u)", + GST_OBJECT_NAME (helper->factory), off, size); + + if (size == 0) + return NULL; + + if (off < 0) { + GST_LOG_OBJECT (helper->obj, "'%s' wanted to peek at end; not supported", + GST_OBJECT_NAME (helper->factory)); + return NULL; + } + + /* If we request beyond the available size, we're sure we can't return + * anything regardless of the requested offset */ + if (size > helper->size) + return NULL; + + /* Only return data if there's enough room left for the given offset. + * This is the same as "if (off + size <= helper->size)" except that + * it doesn't exceed type limits */ + if (off <= helper->size - size) + return helper->data + off; + + return NULL; +} + +/* + * buf_helper_find_suggest: + * @data: helper data struct + * @probability: probability of the match + * @caps: caps of the type + * + * If given @probability is higher, replace previously store caps. + */ +static void +buf_helper_find_suggest (gpointer data, guint probability, GstCaps * caps) +{ + GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data; + + GST_LOG_OBJECT (helper->obj, + "'%s' called suggest (%u, %" GST_PTR_FORMAT ")", + GST_OBJECT_NAME (helper->factory), probability, caps); + + /* Note: not >= as we call typefinders in order of rank, highest first */ + if (probability > helper->best_probability) { + gst_caps_replace (&helper->caps, caps); + helper->best_probability = probability; + } +} + +/** + * gst_type_find_helper_for_data: + * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging) + * @data: (transfer none) (array length=size): * a pointer with data to typefind + * @size: the size of @data + * @prob: (out) (allow-none): location to store the probability of the found + * caps, or %NULL + * + * Tries to find what type of data is contained in the given @data, the + * assumption being that the data represents the beginning of the stream or + * file. + * + * All available typefinders will be called on the data in order of rank. If + * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM, + * typefinding is stopped immediately and the found caps will be returned + * right away. Otherwise, all available typefind functions will the tried, + * and the caps with the highest probability will be returned, or %NULL if + * the content of @data could not be identified. + * + * Free-function: gst_caps_unref + * + * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data, + * or %NULL if no type could be found. The caller should free the caps + * returned with gst_caps_unref(). + */ +GstCaps * +gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size, + GstTypeFindProbability * prob) +{ + GstTypeFindBufHelper helper; + GstTypeFind find; + GList *l, *type_list; + GstCaps *result = NULL; + + g_return_val_if_fail (data != NULL, NULL); + + helper.data = data; + helper.size = size; + helper.best_probability = GST_TYPE_FIND_NONE; + helper.caps = NULL; + helper.obj = obj; + + if (helper.data == NULL || helper.size == 0) + return NULL; + + find.data = &helper; + find.peek = buf_helper_find_peek; + find.suggest = buf_helper_find_suggest; + find.get_length = NULL; + + type_list = gst_type_find_factory_get_list (); + + for (l = type_list; l; l = l->next) { + helper.factory = GST_TYPE_FIND_FACTORY (l->data); + gst_type_find_factory_call_function (helper.factory, &find); + if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM) + break; + } + gst_plugin_feature_list_free (type_list); + + if (helper.best_probability > 0) + result = helper.caps; + + if (prob) + *prob = helper.best_probability; + + GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)", + result, (guint) helper.best_probability); + + return result; +} + +/** + * gst_type_find_helper_for_buffer: + * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging) + * @buf: (in) (transfer none): a #GstBuffer with data to typefind + * @prob: (out) (allow-none): location to store the probability of the found + * caps, or %NULL + * + * Tries to find what type of data is contained in the given #GstBuffer, the + * assumption being that the buffer represents the beginning of the stream or + * file. + * + * All available typefinders will be called on the data in order of rank. If + * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM, + * typefinding is stopped immediately and the found caps will be returned + * right away. Otherwise, all available typefind functions will the tried, + * and the caps with the highest probability will be returned, or %NULL if + * the content of the buffer could not be identified. + * + * Free-function: gst_caps_unref + * + * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data, + * or %NULL if no type could be found. The caller should free the caps + * returned with gst_caps_unref(). + */ +GstCaps * +gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf, + GstTypeFindProbability * prob) +{ + GstCaps *result; + GstMapInfo info; + + g_return_val_if_fail (buf != NULL, NULL); + g_return_val_if_fail (GST_IS_BUFFER (buf), NULL); + g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 || + GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL); + + if (!gst_buffer_map (buf, &info, GST_MAP_READ)) + return NULL; + result = gst_type_find_helper_for_data (obj, info.data, info.size, prob); + gst_buffer_unmap (buf, &info); + + return result; +} + +/** + * gst_type_find_helper_for_extension: + * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging) + * @extension: an extension + * + * Tries to find the best #GstCaps associated with @extension. + * + * All available typefinders will be checked against the extension in order + * of rank. The caps of the first typefinder that can handle @extension will be + * returned. + * + * Free-function: gst_caps_unref + * + * Returns: (transfer full) (nullable): the #GstCaps corresponding to + * @extension, or %NULL if no type could be found. The caller should free + * the caps returned with gst_caps_unref(). + */ +GstCaps * +gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension) +{ + GList *l, *type_list; + GstCaps *result = NULL; + + g_return_val_if_fail (extension != NULL, NULL); + + GST_LOG_OBJECT (obj, "finding caps for extension %s", extension); + + type_list = gst_type_find_factory_get_list (); + + for (l = type_list; l; l = g_list_next (l)) { + GstTypeFindFactory *factory; + const gchar *const *ext; + + factory = GST_TYPE_FIND_FACTORY (l->data); + + /* we only want to check those factories without a function */ + if (gst_type_find_factory_has_function (factory)) + continue; + + /* get the extension that this typefind factory can handle */ + ext = gst_type_find_factory_get_extensions (factory); + if (ext == NULL) + continue; + + /* there are extension, see if one of them matches the requested + * extension */ + while (*ext != NULL) { + if (strcmp (*ext, extension) == 0) { + /* we found a matching extension, take the caps */ + if ((result = gst_type_find_factory_get_caps (factory))) { + gst_caps_ref (result); + goto done; + } + } + ++ext; + } + } +done: + gst_plugin_feature_list_free (type_list); + + GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result); + + return result; +} diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h new file mode 100644 index 0000000..6f032ca --- /dev/null +++ b/libs/gst/base/gsttypefindhelper.h @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * Copyright (C) 2000,2005 Wim Taymans + * Copyright (C) 2006 Tim-Philipp Müller + * + * gsttypefindhelper.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TYPEFINDHELPER_H__ +#define __GST_TYPEFINDHELPER_H__ + +#include +#include + +G_BEGIN_DECLS + +GST_BASE_API +GstCaps * gst_type_find_helper (GstPad *src, guint64 size); + +GST_BASE_API +GstCaps * gst_type_find_helper_for_data (GstObject *obj, + const guint8 *data, + gsize size, + GstTypeFindProbability *prob); +GST_BASE_API +GstCaps * gst_type_find_helper_for_buffer (GstObject *obj, + GstBuffer *buf, + GstTypeFindProbability *prob); +GST_BASE_API +GstCaps * gst_type_find_helper_for_extension (GstObject * obj, + const gchar * extension); + +/** + * GstTypeFindHelperGetRangeFunction: + * @obj: a #GstObject that will handle the getrange request + * @parent: (allow-none): the parent of @obj or %NULL + * @offset: the offset of the range + * @length: the length of the range + * @buffer: (out): a memory location to hold the result buffer + * + * This function will be called by gst_type_find_helper_get_range() when + * typefinding functions request to peek at the data of a stream at certain + * offsets. If this function returns GST_FLOW_OK, the result buffer will be + * stored in @buffer. The contents of @buffer is invalid for any other + * return value. + * + * This function is supposed to behave exactly like a #GstPadGetRangeFunction. + * + * Returns: GST_FLOW_OK for success + */ +typedef GstFlowReturn (*GstTypeFindHelperGetRangeFunction) (GstObject *obj, + GstObject *parent, + guint64 offset, + guint length, + GstBuffer **buffer); +GST_BASE_API +GstCaps * gst_type_find_helper_get_range (GstObject *obj, + GstObject *parent, + GstTypeFindHelperGetRangeFunction func, + guint64 size, + const gchar *extension, + GstTypeFindProbability *prob); + +G_END_DECLS + +#endif /* __GST_TYPEFINDHELPER_H__ */ diff --git a/libs/gst/base/meson.build b/libs/gst/base/meson.build new file mode 100644 index 0000000..760d2e7 --- /dev/null +++ b/libs/gst/base/meson.build @@ -0,0 +1,104 @@ +gst_base_sources = [ + 'gstadapter.c', + 'gstaggregator.c', + 'gstbaseparse.c', + 'gstbasesink.c', + 'gstbasesrc.c', + 'gstbasetransform.c', + 'gstbitreader.c', + 'gstbytereader.c', + 'gstbytewriter.c', + 'gstcollectpads.c', + 'gstdataqueue.c', + 'gstflowcombiner.c', + 'gstpushsrc.c', + 'gstqueuearray.c', + 'gsttypefindhelper.c', +] + +gst_base_headers = [ + 'base.h', + 'base-prelude.h', + 'gstadapter.h', + 'gstaggregator.h', + 'gstbaseparse.h', + 'gstbasesink.h', + 'gstbasesrc.h', + 'gstbasetransform.h', + 'gstbitreader.h', + 'gstbytereader.h', + 'gstbytewriter.h', + 'gstcollectpads.h', + 'gstdataqueue.h', + 'gstflowcombiner.h', + 'gstpushsrc.h', + 'gstqueuearray.h', + 'gsttypefindhelper.h', +] + +if libtype != 'shared' + gst_base_static = static_library('gstbase-@0@'.format(apiversion), + gst_base_sources, + c_args : gst_c_args, + install : true, + include_directories : [configinc, libsinc], + dependencies : [gobject_dep, glib_dep, gst_dep], + ) + gst_base = gst_base_static +endif + +gst_base_gen_sources = [] + +if libtype != 'static' + gst_base_shared = shared_library('gstbase-@0@'.format(apiversion), + gst_base_sources, + c_args : gst_c_args, + version : libversion, + soversion : soversion, + install : true, + include_directories : [configinc, libsinc], + dependencies : [gobject_dep, glib_dep, gst_dep], + ) + gst_base = gst_base_shared + if build_gir + gst_gir_extra_args = gir_init_section + [ '--c-include=gst/base/base.h' ] + gst_base_gen_sources += [gnome.generate_gir(gst_base_shared, + sources : gst_base_sources + gst_base_headers, + namespace : 'GstBase', + nsversion : apiversion, + identifier_prefix : 'Gst', + symbol_prefix : 'gst', + export_packages : 'gstreamer-base-1.0', + dependencies : [gst_dep], + include_directories : [configinc, libsinc, privinc], + includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'], + install : true, + extra_args : gst_gir_extra_args, + )] + endif +endif + +gst_base_dep = declare_dependency(link_with : gst_base, + include_directories : [libsinc], + dependencies : [gst_dep], + sources : gst_base_gen_sources) + +install_headers('base.h', + 'base-prelude.h', + 'gstadapter.h', + 'gstaggregator.h', + 'gstbaseparse.h', + 'gstbasesink.h', + 'gstbasesrc.h', + 'gstbasetransform.h', + 'gstbitreader.h', + 'gstbytereader.h', + 'gstbytewriter.h', + 'gstcollectpads.h', + 'gstdataqueue.h', + 'gstflowcombiner.h', + 'gstpushsrc.h', + 'gstqueuearray.h', + 'gsttypefindhelper.h', + subdir : 'gstreamer-1.0/gst/base', +) diff --git a/libs/gst/check/Makefile.am b/libs/gst/check/Makefile.am new file mode 100644 index 0000000..61a03bc --- /dev/null +++ b/libs/gst/check/Makefile.am @@ -0,0 +1,270 @@ +lib_LTLIBRARIES = libgstcheck-@GST_API_VERSION@.la + +SYMBOLS_FILE = exports.sym + +libgstcheck_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \ + $(SYMBOLS_FILE) +libgstcheck_@GST_API_VERSION@_la_SOURCES = \ + gstbufferstraw.c \ + gstcheck.c \ + gstconsistencychecker.c \ + gstharness.c \ + gsttestclock.c + +libgstcheck_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) \ + -UG_DISABLE_ASSERT \ + -I$(top_builddir)/libs \ + -I$(top_builddir)/libs/gst/check \ + -I$(top_builddir)/libs/gst/check/libcheck +libgstcheck_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) \ + $(top_builddir)/libs/gst/check/libcheck/libcheckinternal.la \ + $(LIBM) +libgstcheck_@GST_API_VERSION@_la_LDFLAGS = \ + -export-symbols $(SYMBOLS_FILE) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +libgstcheck_@GST_API_VERSION@includedir = \ + $(includedir)/gstreamer-@GST_API_VERSION@/gst/check + +libgstcheck_@GST_API_VERSION@include_HEADERS = \ + check.h \ + check-prelude.h \ + gstbufferstraw.h \ + gstcheck.h \ + gstconsistencychecker.h \ + gstharness.h \ + gsttestclock.h + +nodist_libgstcheck_@GST_API_VERSION@include_HEADERS = \ + internal-check.h + +CLEANFILES = *.gcno *.gcda *.gcov $(SYMBOLS_FILE) + +%.c.gcov: .libs/libgstcheck_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcheck_@GST_API_VERSION@_la_SOURCES:=.gcov) + +SUBDIRS = libcheck + +LIBGSTCHECK_EXPORTED_VARS = \ + _gst_check_threads_running \ + _gst_check_raised_critical \ + _gst_check_raised_warning \ + _gst_check_expecting_log \ + _gst_check_list_tests \ + buffers \ + check_cond \ + check_debug \ + check_mutex \ + mutex \ + start_cond \ + sync_cond \ + thread_list + +LIBGSTCHECK_EXPORTED_FUNCS = \ + _gst_check_run_test_func \ + gst_buffer_straw_get_buffer \ + gst_buffer_straw_start_pipeline \ + gst_buffer_straw_stop_pipeline \ + gst_check_abi_list \ + gst_check_caps_equal \ + gst_check_buffer_data \ + gst_check_chain_func \ + gst_check_drop_buffers \ + gst_check_element_push_buffer \ + gst_check_element_push_buffer_list \ + gst_check_init \ + gst_check_add_log_filter \ + gst_check_remove_log_filter \ + gst_check_clear_log_filter \ + gst_check_message_error \ + gst_check_run_suite \ + gst_check_setup_element \ + gst_check_setup_events \ + gst_check_setup_events_with_stream_id \ + gst_check_setup_sink_pad \ + gst_check_setup_sink_pad_from_template \ + gst_check_setup_sink_pad_by_name \ + gst_check_setup_sink_pad_by_name_from_template \ + gst_check_setup_src_pad \ + gst_check_setup_src_pad_from_template \ + gst_check_setup_src_pad_by_name \ + gst_check_setup_src_pad_by_name_from_template \ + gst_check_teardown_element \ + gst_check_teardown_pad_by_name \ + gst_check_teardown_sink_pad \ + gst_check_teardown_src_pad \ + gst_check_objects_destroyed_on_unref \ + gst_check_object_destroyed_on_unref \ + gst_consistency_checker_add_pad \ + gst_consistency_checker_new \ + gst_consistency_checker_reset \ + gst_consistency_checker_free \ + gst_harness_add_element_full \ + gst_harness_add_element_src_pad \ + gst_harness_add_element_sink_pad \ + gst_harness_add_parse \ + gst_harness_add_probe \ + gst_harness_add_sink \ + gst_harness_add_sink_harness \ + gst_harness_add_sink_parse \ + gst_harness_add_src \ + gst_harness_add_src_harness \ + gst_harness_add_src_parse \ + gst_harness_buffers_in_queue \ + gst_harness_buffers_received \ + gst_harness_crank_multiple_clock_waits \ + gst_harness_crank_single_clock_wait \ + gst_harness_create_buffer \ + gst_harness_dump_to_file \ + gst_harness_events_in_queue \ + gst_harness_events_received \ + gst_harness_find_element \ + gst_harness_get \ + gst_harness_get_allocator \ + gst_harness_get_last_pushed_timestamp \ + gst_harness_get_testclock \ + gst_harness_new \ + gst_harness_new_empty \ + gst_harness_new_full \ + gst_harness_new_parse \ + gst_harness_new_with_element \ + gst_harness_new_with_padnames \ + gst_harness_new_with_templates \ + gst_harness_play \ + gst_harness_pull \ + gst_harness_pull_event \ + gst_harness_pull_upstream_event \ + gst_harness_push \ + gst_harness_push_and_pull \ + gst_harness_push_event \ + gst_harness_push_from_src \ + gst_harness_push_to_sink \ + gst_harness_query_latency \ + gst_harness_push_upstream_event \ + gst_harness_set \ + gst_harness_set_caps \ + gst_harness_set_caps_str \ + gst_harness_set_drop_buffers \ + gst_harness_set_blocking_push_mode \ + gst_harness_set_forwarding \ + gst_harness_set_propose_allocator \ + gst_harness_set_sink_caps \ + gst_harness_set_src_caps \ + gst_harness_set_src_caps_str \ + gst_harness_set_sink_caps_str \ + gst_harness_set_time \ + gst_harness_set_upstream_latency \ + gst_harness_sink_push_many \ + gst_harness_src_crank_and_push_many \ + gst_harness_src_push_event \ + gst_harness_stress_custom_start \ + gst_harness_stress_property_start_full \ + gst_harness_stress_push_buffer_start_full \ + gst_harness_stress_push_buffer_with_cb_start_full \ + gst_harness_stress_push_event_start_full \ + gst_harness_stress_push_event_with_cb_start_full \ + gst_harness_stress_push_upstream_event_start_full \ + gst_harness_stress_push_upstream_event_with_cb_start_full \ + gst_harness_stress_requestpad_start_full \ + gst_harness_stress_statechange_start_full \ + gst_harness_stress_thread_stop \ + gst_harness_take_all_data \ + gst_harness_take_all_data_as_buffer \ + gst_harness_take_all_data_as_bytes \ + gst_harness_teardown \ + gst_harness_try_pull \ + gst_harness_try_pull_event \ + gst_harness_try_pull_upstream_event \ + gst_harness_upstream_events_in_queue \ + gst_harness_upstream_events_received \ + gst_harness_use_systemclock \ + gst_harness_use_testclock \ + gst_harness_wait_for_clock_id_waits \ + gst_test_clock_advance_time \ + gst_test_clock_crank \ + gst_test_clock_get_next_entry_time \ + gst_test_clock_get_type \ + gst_test_clock_has_id \ + gst_test_clock_id_list_get_latest_time \ + gst_test_clock_new \ + gst_test_clock_new_with_start_time \ + gst_test_clock_peek_id_count \ + gst_test_clock_peek_next_pending_id \ + gst_test_clock_process_id_list \ + gst_test_clock_process_next_clock_id \ + gst_test_clock_set_time \ + gst_test_clock_wait_for_multiple_pending_ids \ + gst_test_clock_wait_for_next_pending_id \ + gst_test_clock_wait_for_pending_id_count + +# For backwards compatibility with GStreamer < 1.5 +LIBGSTCHECK_EXPORTED_COMPAT_FUNCS = \ + _fail_unless + +LIBGSTCHECK_EXPORTED_SYMBOLS = \ + $(LIBGSTCHECK_EXPORTED_VARS) \ + $(LIBGSTCHECK_EXPORTED_FUNCS) \ + $(LIBGSTCHECK_EXPORTED_COMPAT_FUNCS) + +# Please do not even think about changing the alphabet below into A-Za-z. +# It is there for purpose. (Bug #602093) +CHECK_SYMS=`$(SED) -n -e 's/^..*CK_EXPORT[ ]\{1,\}\([_0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]\{1,\}\)..*$$/\1/p' @top_srcdir@/libs/gst/check/libcheck/check.h.in` +print-check-symbols: + @for s in $(CHECK_SYMS); do \ + echo $$s; \ + done; + +$(SYMBOLS_FILE): $(libgstcheck_@GST_API_VERSION@include_HEADERS) internal-check.h + $(AM_V_GEN)rm -f $(SYMBOLS_FILE) 2>/dev/null; \ + for s in $(LIBGSTCHECK_EXPORTED_SYMBOLS) $(CHECK_SYMS); do \ + echo $$s >> $(SYMBOLS_FILE); \ + done + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstCheck-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@_la_SOURCES)) + +GstCheck-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_API_VERSION@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ + GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ + CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ + $(INTROSPECTION_SCANNER) -v --namespace GstCheck \ + --nsversion=@GST_API_VERSION@ \ + --identifier-prefix=Gst \ + --symbol-prefix=gst \ + --warn-all \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libs \ + -I$(top_builddir) \ + -I$(top_builddir)/libs \ + --c-include "gst/check/check.h" \ + --add-include-path=$(top_builddir)/gst \ + --library-path=$(top_builddir)/gst \ + --library=libgstcheck-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --libtool="${LIBTOOL}" \ + --pkg gstreamer-@GST_API_VERSION@ \ + --pkg-export gstreamer-check-@GST_API_VERSION@ \ + --add-init-section="$(INTROSPECTION_INIT)" \ + --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)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif diff --git a/libs/gst/check/Makefile.in b/libs/gst/check/Makefile.in new file mode 100644 index 0000000..2252bd9 --- /dev/null +++ b/libs/gst/check/Makefile.in @@ -0,0 +1,1376 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = libs/gst/check +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libgstcheck_@GST_API_VERSION@include_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = internal-check.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" \ + "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am_libgstcheck_@GST_API_VERSION@_la_OBJECTS = \ + libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo \ + libgstcheck_@GST_API_VERSION@_la-gstcheck.lo \ + libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo \ + libgstcheck_@GST_API_VERSION@_la-gstharness.lo \ + libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo +libgstcheck_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstcheck_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstcheck_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) \ + $(libgstcheck_@GST_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstcheck_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgstcheck_@GST_API_VERSION@_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstcheck_@GST_API_VERSION@include_HEADERS) \ + $(nodist_libgstcheck_@GST_API_VERSION@include_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/libs/gst/check/libcheck/check.h.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libgstcheck-@GST_API_VERSION@.la +SYMBOLS_FILE = exports.sym +libgstcheck_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \ + $(SYMBOLS_FILE) + +libgstcheck_@GST_API_VERSION@_la_SOURCES = \ + gstbufferstraw.c \ + gstcheck.c \ + gstconsistencychecker.c \ + gstharness.c \ + gsttestclock.c + +libgstcheck_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) \ + -UG_DISABLE_ASSERT \ + -I$(top_builddir)/libs \ + -I$(top_builddir)/libs/gst/check \ + -I$(top_builddir)/libs/gst/check/libcheck + +libgstcheck_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) \ + $(top_builddir)/libs/gst/check/libcheck/libcheckinternal.la \ + $(LIBM) + +libgstcheck_@GST_API_VERSION@_la_LDFLAGS = \ + -export-symbols $(SYMBOLS_FILE) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +libgstcheck_@GST_API_VERSION@includedir = \ + $(includedir)/gstreamer-@GST_API_VERSION@/gst/check + +libgstcheck_@GST_API_VERSION@include_HEADERS = \ + check.h \ + check-prelude.h \ + gstbufferstraw.h \ + gstcheck.h \ + gstconsistencychecker.h \ + gstharness.h \ + gsttestclock.h + +nodist_libgstcheck_@GST_API_VERSION@include_HEADERS = \ + internal-check.h + +CLEANFILES = *.gcno *.gcda *.gcov $(SYMBOLS_FILE) $(am__append_1) +SUBDIRS = libcheck +LIBGSTCHECK_EXPORTED_VARS = \ + _gst_check_threads_running \ + _gst_check_raised_critical \ + _gst_check_raised_warning \ + _gst_check_expecting_log \ + _gst_check_list_tests \ + buffers \ + check_cond \ + check_debug \ + check_mutex \ + mutex \ + start_cond \ + sync_cond \ + thread_list + +LIBGSTCHECK_EXPORTED_FUNCS = \ + _gst_check_run_test_func \ + gst_buffer_straw_get_buffer \ + gst_buffer_straw_start_pipeline \ + gst_buffer_straw_stop_pipeline \ + gst_check_abi_list \ + gst_check_caps_equal \ + gst_check_buffer_data \ + gst_check_chain_func \ + gst_check_drop_buffers \ + gst_check_element_push_buffer \ + gst_check_element_push_buffer_list \ + gst_check_init \ + gst_check_add_log_filter \ + gst_check_remove_log_filter \ + gst_check_clear_log_filter \ + gst_check_message_error \ + gst_check_run_suite \ + gst_check_setup_element \ + gst_check_setup_events \ + gst_check_setup_events_with_stream_id \ + gst_check_setup_sink_pad \ + gst_check_setup_sink_pad_from_template \ + gst_check_setup_sink_pad_by_name \ + gst_check_setup_sink_pad_by_name_from_template \ + gst_check_setup_src_pad \ + gst_check_setup_src_pad_from_template \ + gst_check_setup_src_pad_by_name \ + gst_check_setup_src_pad_by_name_from_template \ + gst_check_teardown_element \ + gst_check_teardown_pad_by_name \ + gst_check_teardown_sink_pad \ + gst_check_teardown_src_pad \ + gst_check_objects_destroyed_on_unref \ + gst_check_object_destroyed_on_unref \ + gst_consistency_checker_add_pad \ + gst_consistency_checker_new \ + gst_consistency_checker_reset \ + gst_consistency_checker_free \ + gst_harness_add_element_full \ + gst_harness_add_element_src_pad \ + gst_harness_add_element_sink_pad \ + gst_harness_add_parse \ + gst_harness_add_probe \ + gst_harness_add_sink \ + gst_harness_add_sink_harness \ + gst_harness_add_sink_parse \ + gst_harness_add_src \ + gst_harness_add_src_harness \ + gst_harness_add_src_parse \ + gst_harness_buffers_in_queue \ + gst_harness_buffers_received \ + gst_harness_crank_multiple_clock_waits \ + gst_harness_crank_single_clock_wait \ + gst_harness_create_buffer \ + gst_harness_dump_to_file \ + gst_harness_events_in_queue \ + gst_harness_events_received \ + gst_harness_find_element \ + gst_harness_get \ + gst_harness_get_allocator \ + gst_harness_get_last_pushed_timestamp \ + gst_harness_get_testclock \ + gst_harness_new \ + gst_harness_new_empty \ + gst_harness_new_full \ + gst_harness_new_parse \ + gst_harness_new_with_element \ + gst_harness_new_with_padnames \ + gst_harness_new_with_templates \ + gst_harness_play \ + gst_harness_pull \ + gst_harness_pull_event \ + gst_harness_pull_upstream_event \ + gst_harness_push \ + gst_harness_push_and_pull \ + gst_harness_push_event \ + gst_harness_push_from_src \ + gst_harness_push_to_sink \ + gst_harness_query_latency \ + gst_harness_push_upstream_event \ + gst_harness_set \ + gst_harness_set_caps \ + gst_harness_set_caps_str \ + gst_harness_set_drop_buffers \ + gst_harness_set_blocking_push_mode \ + gst_harness_set_forwarding \ + gst_harness_set_propose_allocator \ + gst_harness_set_sink_caps \ + gst_harness_set_src_caps \ + gst_harness_set_src_caps_str \ + gst_harness_set_sink_caps_str \ + gst_harness_set_time \ + gst_harness_set_upstream_latency \ + gst_harness_sink_push_many \ + gst_harness_src_crank_and_push_many \ + gst_harness_src_push_event \ + gst_harness_stress_custom_start \ + gst_harness_stress_property_start_full \ + gst_harness_stress_push_buffer_start_full \ + gst_harness_stress_push_buffer_with_cb_start_full \ + gst_harness_stress_push_event_start_full \ + gst_harness_stress_push_event_with_cb_start_full \ + gst_harness_stress_push_upstream_event_start_full \ + gst_harness_stress_push_upstream_event_with_cb_start_full \ + gst_harness_stress_requestpad_start_full \ + gst_harness_stress_statechange_start_full \ + gst_harness_stress_thread_stop \ + gst_harness_take_all_data \ + gst_harness_take_all_data_as_buffer \ + gst_harness_take_all_data_as_bytes \ + gst_harness_teardown \ + gst_harness_try_pull \ + gst_harness_try_pull_event \ + gst_harness_try_pull_upstream_event \ + gst_harness_upstream_events_in_queue \ + gst_harness_upstream_events_received \ + gst_harness_use_systemclock \ + gst_harness_use_testclock \ + gst_harness_wait_for_clock_id_waits \ + gst_test_clock_advance_time \ + gst_test_clock_crank \ + gst_test_clock_get_next_entry_time \ + gst_test_clock_get_type \ + gst_test_clock_has_id \ + gst_test_clock_id_list_get_latest_time \ + gst_test_clock_new \ + gst_test_clock_new_with_start_time \ + gst_test_clock_peek_id_count \ + gst_test_clock_peek_next_pending_id \ + gst_test_clock_process_id_list \ + gst_test_clock_process_next_clock_id \ + gst_test_clock_set_time \ + gst_test_clock_wait_for_multiple_pending_ids \ + gst_test_clock_wait_for_next_pending_id \ + gst_test_clock_wait_for_pending_id_count + + +# For backwards compatibility with GStreamer < 1.5 +LIBGSTCHECK_EXPORTED_COMPAT_FUNCS = \ + _fail_unless + +LIBGSTCHECK_EXPORTED_SYMBOLS = \ + $(LIBGSTCHECK_EXPORTED_VARS) \ + $(LIBGSTCHECK_EXPORTED_FUNCS) \ + $(LIBGSTCHECK_EXPORTED_COMPAT_FUNCS) + + +# Please do not even think about changing the alphabet below into A-Za-z. +# It is there for purpose. (Bug #602093) +CHECK_SYMS = `$(SED) -n -e 's/^..*CK_EXPORT[ ]\{1,\}\([_0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]\{1,\}\)..*$$/\1/p' @top_srcdir@/libs/gst/check/libcheck/check.h.in` +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstCheck-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@include_HEADERS)) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, $(libgstcheck_@GST_API_VERSION@_la_SOURCES)) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/check/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/check/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +internal-check.h: $(top_builddir)/config.status $(top_srcdir)/libs/gst/check/libcheck/check.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstcheck-@GST_API_VERSION@.la: $(libgstcheck_@GST_API_VERSION@_la_OBJECTS) $(libgstcheck_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstcheck_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstcheck_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstcheck_@GST_API_VERSION@_la_OBJECTS) $(libgstcheck_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstcheck.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstharness.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gsttestclock.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo: gstbufferstraw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo -MD -MP -MF $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.Tpo -c -o libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo `test -f 'gstbufferstraw.c' || echo '$(srcdir)/'`gstbufferstraw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.Tpo $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstbufferstraw.c' object='libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcheck_@GST_API_VERSION@_la-gstbufferstraw.lo `test -f 'gstbufferstraw.c' || echo '$(srcdir)/'`gstbufferstraw.c + +libgstcheck_@GST_API_VERSION@_la-gstcheck.lo: gstcheck.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcheck_@GST_API_VERSION@_la-gstcheck.lo -MD -MP -MF $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstcheck.Tpo -c -o libgstcheck_@GST_API_VERSION@_la-gstcheck.lo `test -f 'gstcheck.c' || echo '$(srcdir)/'`gstcheck.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstcheck.Tpo $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstcheck.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcheck.c' object='libgstcheck_@GST_API_VERSION@_la-gstcheck.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcheck_@GST_API_VERSION@_la-gstcheck.lo `test -f 'gstcheck.c' || echo '$(srcdir)/'`gstcheck.c + +libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo: gstconsistencychecker.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo -MD -MP -MF $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.Tpo -c -o libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo `test -f 'gstconsistencychecker.c' || echo '$(srcdir)/'`gstconsistencychecker.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.Tpo $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstconsistencychecker.c' object='libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcheck_@GST_API_VERSION@_la-gstconsistencychecker.lo `test -f 'gstconsistencychecker.c' || echo '$(srcdir)/'`gstconsistencychecker.c + +libgstcheck_@GST_API_VERSION@_la-gstharness.lo: gstharness.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcheck_@GST_API_VERSION@_la-gstharness.lo -MD -MP -MF $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstharness.Tpo -c -o libgstcheck_@GST_API_VERSION@_la-gstharness.lo `test -f 'gstharness.c' || echo '$(srcdir)/'`gstharness.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstharness.Tpo $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gstharness.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstharness.c' object='libgstcheck_@GST_API_VERSION@_la-gstharness.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcheck_@GST_API_VERSION@_la-gstharness.lo `test -f 'gstharness.c' || echo '$(srcdir)/'`gstharness.c + +libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo: gsttestclock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo -MD -MP -MF $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gsttestclock.Tpo -c -o libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo `test -f 'gsttestclock.c' || echo '$(srcdir)/'`gsttestclock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gsttestclock.Tpo $(DEPDIR)/libgstcheck_@GST_API_VERSION@_la-gsttestclock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttestclock.c' object='libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcheck_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcheck_@GST_API_VERSION@_la-gsttestclock.lo `test -f 'gsttestclock.c' || echo '$(srcdir)/'`gsttestclock.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstcheck_@GST_API_VERSION@includeHEADERS: $(libgstcheck_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstcheck_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstcheck_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-libgstcheck_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstcheck_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstcheck_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) +install-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS: $(nodist_libgstcheck_@GST_API_VERSION@include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libgstcheck_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstcheck_@GST_API_VERSION@includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" || exit $$?; \ + done + +uninstall-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libgstcheck_@GST_API_VERSION@include_HEADERS)'; test -n "$(libgstcheck_@GST_API_VERSION@includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)" "$(DESTDIR)$(libgstcheck_@GST_API_VERSION@includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-girDATA \ + install-libgstcheck_@GST_API_VERSION@includeHEADERS \ + install-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstcheck_@GST_API_VERSION@includeHEADERS \ + uninstall-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libLTLIBRARIES \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-girDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES \ + install-libgstcheck_@GST_API_VERSION@includeHEADERS \ + install-man \ + install-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstcheck_@GST_API_VERSION@includeHEADERS \ + uninstall-nodist_libgstcheck_@GST_API_VERSION@includeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +%.c.gcov: .libs/libgstcheck_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcheck_@GST_API_VERSION@_la_SOURCES:=.gcov) +print-check-symbols: + @for s in $(CHECK_SYMS); do \ + echo $$s; \ + done; + +$(SYMBOLS_FILE): $(libgstcheck_@GST_API_VERSION@include_HEADERS) internal-check.h + $(AM_V_GEN)rm -f $(SYMBOLS_FILE) 2>/dev/null; \ + for s in $(LIBGSTCHECK_EXPORTED_SYMBOLS) $(CHECK_SYMS); do \ + echo $$s >> $(SYMBOLS_FILE); \ + done + +@HAVE_INTROSPECTION_TRUE@GstCheck-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ +@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ +@HAVE_INTROSPECTION_TRUE@ CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstCheck \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Gst \ +@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=gst \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir)/libs \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir)/libs \ +@HAVE_INTROSPECTION_TRUE@ --c-include "gst/check/check.h" \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstcheck-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-check-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --add-init-section="$(INTROSPECTION_INIT)" \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/check/check-prelude.h b/libs/gst/check/check-prelude.h new file mode 100644 index 0000000..6bf1366 --- /dev/null +++ b/libs/gst/check/check-prelude.h @@ -0,0 +1,31 @@ +/* GStreamer Check Library + * Copyright (C) 2018 GStreamer developers + * + * check-prelude.h: prelude include header for gst-check 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CHECK_PRELUDE_H__ +#define __GST_CHECK_PRELUDE_H__ + +#include + +#ifndef GST_CHECK_API +#define GST_CHECK_API GST_EXPORT +#endif + +#endif /* __GST_CHECK_PRELUDE_H__ */ diff --git a/libs/gst/check/check.h b/libs/gst/check/check.h new file mode 100644 index 0000000..512f06c --- /dev/null +++ b/libs/gst/check/check.h @@ -0,0 +1,33 @@ +/* GStreamer + * Copyright (C) 2012 GStreamer developers + * + * check.h: single include header for gst-check 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CHECK__H__ +#define __GST_CHECK__H__ + +#include + +#include +#include +#include +#include +#include + +#endif /* __GST_CHECK__H__ */ diff --git a/libs/gst/check/gstbufferstraw.c b/libs/gst/check/gstbufferstraw.c new file mode 100644 index 0000000..93a2c37 --- /dev/null +++ b/libs/gst/check/gstbufferstraw.c @@ -0,0 +1,170 @@ +/* GStreamer + * + * unit testing helper lib + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcheckbufferstraw + * @title: GstBufferStraw + * @short_description: Buffer interception code for GStreamer unit tests + * + * These macros and functions are for internal use of the unit tests found + * inside the 'check' directories of various GStreamer packages. + */ + +#include "gstbufferstraw.h" + +static GCond cond; +static GMutex lock; +static GstBuffer *buf = NULL; +static gulong id; + +/* called for every buffer. Waits until the global "buf" variable is unset, + * then sets it to the buffer received, and signals. */ +static GstPadProbeReturn +buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer unused) +{ + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); + + g_mutex_lock (&lock); + + while (buf != NULL) + g_cond_wait (&cond, &lock); + + /* increase the refcount because we store it globally for others to use */ + buf = gst_buffer_ref (buffer); + + g_cond_signal (&cond); + + g_mutex_unlock (&lock); + + return GST_PAD_PROBE_OK; +} + +/** + * gst_buffer_straw_start_pipeline: + * @bin: the pipeline to run + * @pad: a pad on an element in @bin + * + * Sets up a pipeline for buffer sucking. This will allow you to call + * gst_buffer_straw_get_buffer() to access buffers as they pass over @pad. + * + * This function is normally used in unit tests that want to verify that a + * particular element is outputting correct buffers. For example, you would make + * a pipeline via gst_parse_launch(), pull out the pad you want to monitor, then + * call gst_buffer_straw_get_buffer() to get the buffers that pass through @pad. + * The pipeline will block until you have sucked off the buffers. + * + * This function will set the state of @bin to PLAYING; to clean up, be sure to + * call gst_buffer_straw_stop_pipeline(). + * + * Note that you may not start two buffer straws at the same time. This function + * is intended for unit tests, not general API use. In fact it calls fail_if + * from libcheck, so you cannot use it outside unit tests. + */ +void +gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad) +{ + GstStateChangeReturn ret; + + id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, + buffer_probe, NULL, 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"); + } +} + +/** + * gst_buffer_straw_get_buffer: + * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline() + * @pad: the pad previously passed to gst_buffer_straw_start_pipeline() + * + * Get one buffer from @pad. Implemented via buffer probes. This function will + * block until the pipeline passes a buffer over @pad, so for robust behavior + * in unit tests, you need to use check's timeout to fail out in the case that a + * buffer never arrives. + * + * You must have previously called gst_buffer_straw_start_pipeline() on + * @pipeline and @pad. + * + * Returns: the captured #GstBuffer. + */ +GstBuffer * +gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad) +{ + GstBuffer *ret; + + g_mutex_lock (&lock); + + while (buf == NULL) + g_cond_wait (&cond, &lock); + + ret = buf; + buf = NULL; + + g_cond_signal (&cond); + + g_mutex_unlock (&lock); + + return ret; +} + +/** + * gst_buffer_straw_stop_pipeline: + * @bin: the pipeline previously started via gst_buffer_straw_start_pipeline() + * @pad: the pad previously passed to gst_buffer_straw_start_pipeline() + * + * Set @bin to #GST_STATE_NULL and release resource allocated in + * gst_buffer_straw_start_pipeline(). + * + * You must have previously called gst_buffer_straw_start_pipeline() on + * @pipeline and @pad. + */ +void +gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad) +{ + GstStateChangeReturn ret; + + g_mutex_lock (&lock); + if (buf) + gst_buffer_unref (buf); + buf = NULL; + gst_pad_remove_probe (pad, (guint) id); + id = 0; + g_cond_signal (&cond); + g_mutex_unlock (&lock); + + 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"); + } + + g_mutex_lock (&lock); + if (buf) + gst_buffer_unref (buf); + buf = NULL; + g_mutex_unlock (&lock); +} diff --git a/libs/gst/check/gstbufferstraw.h b/libs/gst/check/gstbufferstraw.h new file mode 100644 index 0000000..9eec1f9 --- /dev/null +++ b/libs/gst/check/gstbufferstraw.h @@ -0,0 +1,40 @@ +/* GStreamer + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_BUFFER_STRAW_H__ +#define __GST_BUFFER_STRAW_H__ + + +#include + +G_BEGIN_DECLS + +GST_CHECK_API +void gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad); + +GST_CHECK_API +GstBuffer * gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad); + +GST_CHECK_API +void gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad); + +G_END_DECLS + +#endif /* __GST_BUFFER_STRAW_H__ */ diff --git a/libs/gst/check/gstcheck.c b/libs/gst/check/gstcheck.c new file mode 100644 index 0000000..963d0c4 --- /dev/null +++ b/libs/gst/check/gstcheck.c @@ -0,0 +1,1286 @@ +/* GStreamer + * + * Common code for GStreamer unittests + * + * Copyright (C) 2004,2006 Thomas Vander Stichele + * Copyright (C) 2008 Thijs Vermeir + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstcheck + * @title: GstCheck + * @short_description: Common code for GStreamer unit tests + * + * These macros and functions are for internal use of the unit tests found + * inside the 'check' directories of various GStreamer packages. + * + * One notable feature is that one can use the environment variables GST_CHECKS + * and GST_CHECKS_IGNORE to select which tests to run or skip. Both variables + * can contain a comma separated list of test name globs (e.g. test_*). + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstcheck.h" + +GST_DEBUG_CATEGORY (check_debug); + +/* logging function for tests + * a test uses g_message() to log a debug line + * a gst unit test can be run with GST_TEST_DEBUG env var set to see the + * messages + */ + +gboolean _gst_check_threads_running = FALSE; +GList *thread_list = NULL; +GMutex mutex; +GCond start_cond; /* used to notify main thread of thread startups */ +GCond sync_cond; /* used to synchronize all threads and main thread */ + +GList *buffers = NULL; +GMutex check_mutex; +GCond check_cond; + +/* FIXME 2.0: shouldn't _gst_check_debug be static? Not used anywhere */ +gboolean _gst_check_debug = FALSE; +gboolean _gst_check_raised_critical = FALSE; +gboolean _gst_check_raised_warning = FALSE; +gboolean _gst_check_expecting_log = FALSE; +gboolean _gst_check_list_tests = FALSE; +static GQueue _gst_check_log_filters = G_QUEUE_INIT; +static GMutex _gst_check_log_filters_mutex; + +struct _GstCheckLogFilter +{ + gchar *log_domain; + GLogLevelFlags log_level; + GRegex *regex; + GstCheckLogFilterFunc func; + gpointer user_data; + GDestroyNotify destroy; +}; + + +static gboolean +gst_check_match_log_filter (const GstCheckLogFilter * filter, + const gchar * log_domain, GLogLevelFlags log_level, const gchar * message) +{ + if (g_strcmp0 (log_domain, filter->log_domain) != 0) + return FALSE; + + if ((log_level & filter->log_level) == 0) + return FALSE; + + if (!g_regex_match (filter->regex, message, 0, NULL)) + return FALSE; + + return TRUE; +} + +static GstCheckLogFilter * +gst_check_alloc_log_filter (const gchar * log_domain, GLogLevelFlags log_level, + GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data, + GDestroyNotify destroy_data) +{ + GstCheckLogFilter *filter; + + filter = g_slice_new (GstCheckLogFilter); + filter->log_domain = g_strdup (log_domain); + filter->log_level = log_level; + filter->regex = regex; + filter->func = func; + filter->user_data = user_data; + filter->destroy = destroy_data; + + return filter; +} + +static void +gst_check_free_log_filter (GstCheckLogFilter * filter) +{ + if (!filter) + return; + + g_free (filter->log_domain); + g_regex_unref (filter->regex); + if (filter->destroy) + filter->destroy (filter->user_data); + g_slice_free (GstCheckLogFilter, filter); +} + + +/** + * gst_check_add_log_filter: + * @log_domain: the log domain of the message + * @log_level: the log level of the message + * @regex: (transfer full): a #GRegex to match the message + * @func: the function to call for matching messages + * @user_data: the user data to pass to @func + * @destroy_data: #GDestroyNotify for @user_data + * + * Add a callback @func to be called for all log messages that matches + * @log_domain, @log_level and @regex. If @func is NULL the + * matching logs will be silently discarded by GstCheck. + * + * MT safe. + * + * Returns: A filter that can be passed to @gst_check_remove_log_filter. + * + * Since: 1.12 + **/ +GstCheckLogFilter * +gst_check_add_log_filter (const gchar * log_domain, GLogLevelFlags log_level, + GRegex * regex, GstCheckLogFilterFunc func, gpointer user_data, + GDestroyNotify destroy_data) +{ + GstCheckLogFilter *filter; + + g_return_val_if_fail (regex != NULL, NULL); + + filter = gst_check_alloc_log_filter (log_domain, log_level, regex, + func, user_data, destroy_data); + g_mutex_lock (&_gst_check_log_filters_mutex); + g_queue_push_tail (&_gst_check_log_filters, filter); + g_mutex_unlock (&_gst_check_log_filters_mutex); + + return filter; +} + +/** + * gst_check_remove_log_filter: + * @filter: Filter returned by @gst_check_add_log_filter + * + * Remove a filter that has been added by @gst_check_add_log_filter. + * + * MT safe. + * + * Since: 1.12 + **/ +void +gst_check_remove_log_filter (GstCheckLogFilter * filter) +{ + g_mutex_lock (&_gst_check_log_filters_mutex); + g_queue_remove (&_gst_check_log_filters, filter); + gst_check_free_log_filter (filter); + g_mutex_unlock (&_gst_check_log_filters_mutex); +} + +/** + * gst_check_clear_log_filter: + * + * Clear all filters added by @gst_check_add_log_filter. + * + * MT safe. + * + * Since: 1.12 + **/ +void +gst_check_clear_log_filter (void) +{ + g_mutex_lock (&_gst_check_log_filters_mutex); + g_queue_foreach (&_gst_check_log_filters, + (GFunc) gst_check_free_log_filter, NULL); + g_queue_clear (&_gst_check_log_filters); + g_mutex_unlock (&_gst_check_log_filters_mutex); +} + +typedef struct +{ + const gchar *domain; + const gchar *message; + GLogLevelFlags level; + gboolean discard; +} LogFilterApplyData; + +static void +gst_check_apply_log_filter (GstCheckLogFilter * filter, + LogFilterApplyData * data) +{ + if (gst_check_match_log_filter (filter, data->domain, data->level, + data->message)) { + if (filter->func) + data->discard |= filter->func (data->domain, data->level, + data->message, filter->user_data); + else + data->discard = TRUE; + } +} + +static gboolean +gst_check_filter_log_filter (const gchar * log_domain, + GLogLevelFlags log_level, const gchar * message) +{ + LogFilterApplyData data; + + data.domain = log_domain; + data.level = log_level; + data.message = message; + data.discard = FALSE; + + g_mutex_lock (&_gst_check_log_filters_mutex); + g_queue_foreach (&_gst_check_log_filters, (GFunc) gst_check_apply_log_filter, + &data); + g_mutex_unlock (&_gst_check_log_filters_mutex); + + if (data.discard) + GST_DEBUG ("Discarding message: %s", message); + + return data.discard; +} + +static gboolean +gst_check_log_fatal_func (const gchar * log_domain, GLogLevelFlags log_level, + const gchar * message, gpointer user_data) +{ + if (gst_check_filter_log_filter (log_domain, log_level, message)) + return FALSE; + + return TRUE; +} + + +static void gst_check_log_message_func + (const gchar * log_domain, GLogLevelFlags log_level, + const gchar * message, gpointer user_data) +{ + if (gst_check_filter_log_filter (log_domain, log_level, message)) + return; + + if (_gst_check_debug) { + g_print ("%s\n", message); + } +} + +static void gst_check_log_critical_func + (const gchar * log_domain, GLogLevelFlags log_level, + const gchar * message, gpointer user_data) +{ + if (gst_check_filter_log_filter (log_domain, log_level, message)) + return; + + if (!_gst_check_expecting_log) { + gchar *trace; + + g_print ("\n\nUnexpected critical/warning: %s\n", message); + + trace = gst_debug_get_stack_trace (GST_STACK_TRACE_SHOW_FULL); + if (trace) { + g_print ("\nStack trace:\n%s\n", trace); + g_free (trace); + } + fail ("Unexpected critical/warning: %s", message); + } + + if (_gst_check_debug) { + g_print ("\nExpected critical/warning: %s\n", message); + } + + if (log_level & G_LOG_LEVEL_CRITICAL) + _gst_check_raised_critical = TRUE; + if (log_level & G_LOG_LEVEL_WARNING) + _gst_check_raised_warning = TRUE; +} + +static gint +sort_plugins (GstPlugin * a, GstPlugin * b) +{ + int ret; + + ret = strcmp (gst_plugin_get_source (a), gst_plugin_get_source (b)); + if (ret == 0) + ret = strcmp (gst_plugin_get_name (a), gst_plugin_get_name (b)); + return ret; +} + +static void +print_plugins (void) +{ + GList *plugins, *l; + + plugins = gst_registry_get_plugin_list (gst_registry_get ()); + plugins = g_list_sort (plugins, (GCompareFunc) sort_plugins); + for (l = plugins; l != NULL; l = l->next) { + GstPlugin *plugin = GST_PLUGIN (l->data); + + if (strcmp (gst_plugin_get_source (plugin), "BLACKLIST") != 0) { + GST_LOG ("%20s@%s", gst_plugin_get_name (plugin), + GST_STR_NULL (gst_plugin_get_filename (plugin))); + } + } + gst_plugin_list_free (plugins); +} + +static void +gst_check_deinit (void) +{ + gst_deinit (); + gst_check_clear_log_filter (); +} + +/* gst_check_init: + * @argc: (inout) (allow-none): pointer to application's argc + * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv + * + * Initialize GStreamer testing + * + * NOTE: Needs to be called before creating the testsuite + * so that the tests can be listed. + * */ +void +gst_check_init (int *argc, char **argv[]) +{ + guint timeout_multiplier = 1; + GOptionContext *ctx; + GError *err = NULL; + GOptionEntry options[] = { + {"list-tests", 'l', 0, G_OPTION_ARG_NONE, &_gst_check_list_tests, + "List tests present in the testsuite", NULL}, + {NULL} + }; + + ctx = g_option_context_new ("gst-check"); + 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)) { + if (err) + g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message)); + else + g_printerr ("Error initializing: Unknown error!\n"); + g_clear_error (&err); + } + g_option_context_free (ctx); + + GST_DEBUG_CATEGORY_INIT (check_debug, "check", 0, "check regression tests"); + + if (atexit (gst_check_deinit) != 0) { + GST_ERROR ("failed to set gst_check_deinit as exit function"); + } + + if (g_getenv ("GST_TEST_DEBUG")) + _gst_check_debug = TRUE; + + g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE, gst_check_log_message_func, + NULL); + g_log_set_handler (NULL, G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, + gst_check_log_critical_func, NULL); + g_log_set_handler ("GStreamer", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, + gst_check_log_critical_func, NULL); + g_log_set_handler ("GLib-GObject", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, + gst_check_log_critical_func, NULL); + g_log_set_handler ("GLib-GIO", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, + gst_check_log_critical_func, NULL); + g_log_set_handler ("GLib", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING, + gst_check_log_critical_func, NULL); + g_test_log_set_fatal_handler (gst_check_log_fatal_func, NULL); + + print_plugins (); + +#ifdef TARGET_CPU + GST_INFO ("target CPU: %s", TARGET_CPU); +#endif + +#ifdef HAVE_CPU_ARM + timeout_multiplier = 10; +#endif + + if (timeout_multiplier > 1) { + const gchar *tmult = g_getenv ("CK_TIMEOUT_MULTIPLIER"); + + if (tmult == NULL) { + gchar num_str[32]; + + g_snprintf (num_str, sizeof (num_str), "%d", timeout_multiplier); + GST_INFO ("slow CPU, setting CK_TIMEOUT_MULTIPLIER to %s", num_str); + g_setenv ("CK_TIMEOUT_MULTIPLIER", num_str, TRUE); + } else { + GST_INFO ("CK_TIMEOUT_MULTIPLIER already set to '%s'", tmult); + } + } +} + +/* message checking */ +void +gst_check_message_error (GstMessage * message, GstMessageType type, + GQuark domain, gint code) +{ + GError *error; + gchar *debug; + + fail_unless (GST_MESSAGE_TYPE (message) == type, + "message is of type %s instead of expected type %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message)), + gst_message_type_get_name (type)); + gst_message_parse_error (message, &error, &debug); + fail_unless_equals_int (error->domain, domain); + fail_unless_equals_int (error->code, code); + g_error_free (error); + g_free (debug); +} + +/* helper functions */ +GstFlowReturn +gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GST_DEBUG_OBJECT (pad, "chain_func: received buffer %p", buffer); + buffers = g_list_append (buffers, buffer); + + g_mutex_lock (&check_mutex); + g_cond_signal (&check_cond); + g_mutex_unlock (&check_mutex); + + return GST_FLOW_OK; +} + +/** + * gst_check_setup_element: + * @factory: factory + * + * setup an element for a filter test with mysrcpad and mysinkpad + * + * Returns: (transfer full): a new element + */ +GstElement * +gst_check_setup_element (const gchar * factory) +{ + GstElement *element; + + GST_DEBUG ("setup_element"); + + element = gst_element_factory_make (factory, factory); + fail_if (element == NULL, "Could not create a '%s' element", factory); + ASSERT_OBJECT_REFCOUNT (element, factory, 1); + return element; +} + +void +gst_check_teardown_element (GstElement * element) +{ + GST_DEBUG ("teardown_element"); + + fail_unless (gst_element_set_state (element, GST_STATE_NULL) == + GST_STATE_CHANGE_SUCCESS, "could not set to null"); + ASSERT_OBJECT_REFCOUNT (element, "element", 1); + gst_object_unref (element); +} + +/** + * gst_check_setup_src_pad: + * @element: element to setup pad on + * @tmpl: pad template + * + * Does the same as #gst_check_setup_src_pad_by_name with the name parameter equal to "sink". + * + * Returns: (transfer full): A new pad that can be used to inject data on @element + */ +GstPad * +gst_check_setup_src_pad (GstElement * element, GstStaticPadTemplate * tmpl) +{ + return gst_check_setup_src_pad_by_name (element, tmpl, "sink"); +} + +/** + * gst_check_setup_src_pad_by_name: + * @element: element to setup src pad on + * @tmpl: pad template + * @name: Name of the @element sink pad that will be linked to the src pad that will be setup + * + * Creates a new src pad (based on the given @tmpl) and links it to the given @element sink pad (the pad that matches the given @name). + * Before using the src pad to push data on @element you need to call #gst_check_setup_events on the created src pad. + * + * Example of how to push a buffer on @element: + * + * |[ + * static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + * GST_PAD_SINK, + * GST_PAD_ALWAYS, + * GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING) + * ); + * static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + * GST_PAD_SRC, + * GST_PAD_ALWAYS, + * GST_STATIC_CAPS (YOUR_CAPS_TEMPLATE_STRING) + * ); + * + * GstElement * element = gst_check_setup_element ("element"); + * GstPad * mysrcpad = gst_check_setup_src_pad (element, &srctemplate); + * GstPad * mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate); + * + * gst_pad_set_active (mysrcpad, TRUE); + * gst_pad_set_active (mysinkpad, TRUE); + * fail_unless (gst_element_set_state (element, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing"); + * + * GstCaps * caps = gst_caps_from_string (YOUR_DESIRED_SINK_CAPS); + * gst_check_setup_events (mysrcpad, element, caps, GST_FORMAT_TIME); + * gst_caps_unref (caps); + * + * fail_unless (gst_pad_push (mysrcpad, gst_buffer_new_and_alloc(2)) == GST_FLOW_OK); + * ]| + * + * For very simple input/output test scenarios checkout #gst_check_element_push_buffer_list and #gst_check_element_push_buffer. + * + * Returns: (transfer full): A new pad that can be used to inject data on @element + */ +GstPad * +gst_check_setup_src_pad_by_name (GstElement * element, + GstStaticPadTemplate * tmpl, const gchar * name) +{ + GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl); + GstPad *srcpad; + + srcpad = gst_check_setup_src_pad_by_name_from_template (element, ptmpl, name); + + gst_object_unref (ptmpl); + + return srcpad; +} + +/** + * gst_check_setup_src_pad_from_template: + * @element: element to setup pad on + * @tmpl: pad template + * + * Returns: (transfer full): a new pad + * + * Since: 1.4 + */ +GstPad * +gst_check_setup_src_pad_from_template (GstElement * element, + GstPadTemplate * tmpl) +{ + return gst_check_setup_src_pad_by_name_from_template (element, tmpl, "sink"); +} + +/** + * gst_check_setup_src_pad_by_name_from_template: + * @element: element to setup pad on + * @tmpl: pad template + * @name: name + * + * Returns: (transfer full): a new pad + * + * Since: 1.4 + */ +GstPad * +gst_check_setup_src_pad_by_name_from_template (GstElement * element, + GstPadTemplate * tmpl, const gchar * name) +{ + GstPad *srcpad, *sinkpad; + + /* sending pad */ + srcpad = gst_pad_new_from_template (tmpl, "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); + + sinkpad = gst_element_get_static_pad (element, name); + if (sinkpad == NULL) + sinkpad = gst_element_get_request_pad (element, name); + fail_if (sinkpad == NULL, "Could not get sink pad from %s", + GST_ELEMENT_NAME (element)); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); + 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; +} + +void +gst_check_teardown_pad_by_name (GstElement * element, const gchar * name) +{ + GstPad *pad_peer, *pad_element; + + /* clean up floating src pad */ + pad_element = gst_element_get_static_pad (element, name); + /* We don't check the refcount here since there *might* be + * a pad cache holding an extra reference on pad_element. + * To get to a state where no pad cache will exist, + * we first unlink that pad. */ + pad_peer = gst_pad_get_peer (pad_element); + + if (pad_peer) { + if (gst_pad_get_direction (pad_element) == GST_PAD_SINK) + gst_pad_unlink (pad_peer, pad_element); + else + gst_pad_unlink (pad_element, pad_peer); + } + + /* pad refs held by both creator and this function (through _get) */ + ASSERT_OBJECT_REFCOUNT (pad_element, "element pad_element", 2); + gst_object_unref (pad_element); + /* one more ref is held by element itself */ + + if (pad_peer) { + /* pad refs held by both creator and this function (through _get_peer) */ + ASSERT_OBJECT_REFCOUNT (pad_peer, "check pad_peer", 2); + gst_object_unref (pad_peer); + gst_object_unref (pad_peer); + } +} + +void +gst_check_teardown_src_pad (GstElement * element) +{ + gst_check_teardown_pad_by_name (element, "sink"); +} + +/** + * gst_check_setup_sink_pad: + * @element: element to setup pad on + * @tmpl: pad template + * + * Does the same as #gst_check_setup_sink_pad_by_name with the name parameter equal to "src". + * + * Returns: (transfer full): a new pad that can be used to check the output of @element + */ +GstPad * +gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl) +{ + return gst_check_setup_sink_pad_by_name (element, tmpl, "src"); +} + +/** + * gst_check_setup_sink_pad_by_name: + * @element: element to setup pad on + * @tmpl: pad template + * @name: Name of the @element src pad that will be linked to the sink pad that will be setup + * + * Creates a new sink pad (based on the given @tmpl) and links it to the given @element src pad + * (the pad that matches the given @name). + * You can set event/chain/query functions on this pad to check the output of the @element. + * + * Returns: (transfer full): a new pad that can be used to check the output of @element + */ +GstPad * +gst_check_setup_sink_pad_by_name (GstElement * element, + GstStaticPadTemplate * tmpl, const gchar * name) +{ + GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl); + GstPad *sinkpad; + + sinkpad = + gst_check_setup_sink_pad_by_name_from_template (element, ptmpl, name); + + gst_object_unref (ptmpl); + + return sinkpad; +} + +/** + * gst_check_setup_sink_pad_from_template: + * @element: element to setup pad on + * @tmpl: pad template + * + * Returns: (transfer full): a new pad + * + * Since: 1.4 + */ +GstPad * +gst_check_setup_sink_pad_from_template (GstElement * element, + GstPadTemplate * tmpl) +{ + return gst_check_setup_sink_pad_by_name_from_template (element, tmpl, "src"); +} + +/** + * gst_check_setup_sink_pad_by_name_from_template: + * @element: element to setup pad on + * @tmpl: pad template + * @name: name + * + * Returns: (transfer full): a new pad + * + * Since: 1.4 + */ +GstPad * +gst_check_setup_sink_pad_by_name_from_template (GstElement * element, + GstPadTemplate * tmpl, const gchar * name) +{ + GstPad *srcpad, *sinkpad; + + /* receiving pad */ + sinkpad = gst_pad_new_from_template (tmpl, "sink"); + GST_DEBUG_OBJECT (element, "setting up receiving pad %p", sinkpad); + fail_if (sinkpad == NULL, "Could not create a sinkpad"); + + srcpad = gst_element_get_static_pad (element, name); + if (srcpad == NULL) + srcpad = gst_element_get_request_pad (element, name); + fail_if (srcpad == NULL, "Could not get source pad from %s", + GST_ELEMENT_NAME (element)); + gst_pad_set_chain_function (sinkpad, gst_check_chain_func); + + GST_DEBUG_OBJECT (element, "Linking element src pad and receiving sink pad"); + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK, + "Could not link %s source and sink pads", GST_ELEMENT_NAME (element)); + gst_object_unref (srcpad); /* because we got it higher up */ + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); + + GST_DEBUG_OBJECT (element, "set up srcpad, refcount is 1"); + return sinkpad; +} + +void +gst_check_teardown_sink_pad (GstElement * element) +{ + gst_check_teardown_pad_by_name (element, "src"); +} + +/** + * gst_check_drop_buffers: + * + * Unref and remove all buffers that are in the global @buffers GList, + * emptying the list. + */ +void +gst_check_drop_buffers (void) +{ + while (buffers != NULL) { + gst_buffer_unref (GST_BUFFER (buffers->data)); + buffers = g_list_delete_link (buffers, buffers); + } +} + +/** + * gst_check_caps_equal: + * @caps1: first caps to compare + * @caps2: second caps to compare + * + * Compare two caps with gst_caps_is_equal and fail unless they are + * equal. + */ +void +gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2) +{ + gchar *name1 = gst_caps_to_string (caps1); + gchar *name2 = gst_caps_to_string (caps2); + + fail_unless (gst_caps_is_equal (caps1, caps2), + "caps ('%s') is not equal to caps ('%s')", name1, name2); + g_free (name1); + g_free (name2); +} + + +/** + * gst_check_buffer_data: + * @buffer: buffer to compare + * @data: data to compare to + * @size: size of data to compare + * + * Compare the buffer contents with @data and @size. + */ +void +gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size) +{ + GstMapInfo info; + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + GST_MEMDUMP ("Converted data", info.data, info.size); + GST_MEMDUMP ("Expected data", data, size); + if (memcmp (info.data, data, size) != 0) { + g_print ("\nConverted data:\n"); + gst_util_dump_mem (info.data, info.size); + g_print ("\nExpected data:\n"); + gst_util_dump_mem (data, size); + fail ("buffer contents not equal"); + } + gst_buffer_unmap (buffer, &info); +} + +static gboolean +buffer_event_function (GstPad * pad, GstObject * noparent, GstEvent * event) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) { + GstCaps *event_caps; + GstCaps *expected_caps = gst_pad_get_element_private (pad); + + gst_event_parse_caps (event, &event_caps); + fail_unless (gst_caps_is_fixed (expected_caps)); + fail_unless (gst_caps_is_fixed (event_caps)); + fail_unless (gst_caps_is_equal_fixed (event_caps, expected_caps)); + gst_event_unref (event); + return TRUE; + } + + return gst_pad_event_default (pad, noparent, event); +} + +/** + * gst_check_element_push_buffer_list: + * @element_name: name of the element that needs to be created + * @buffer_in: (element-type GstBuffer) (transfer full): a list of buffers that needs to be + * pushed to the element + * @caps_in: the #GstCaps expected of the sinkpad of the element + * @buffer_out: (element-type GstBuffer) (transfer full): a list of buffers that we expect from + * the element + * @caps_out: the #GstCaps expected of the srcpad of the element + * @last_flow_return: the last buffer push needs to give this GstFlowReturn + * + * Create an element using the factory providing the @element_name and push the + * buffers in @buffer_in to this element. The element should create the buffers + * equal to the buffers in @buffer_out. We only check the size and the data of + * the buffers. This function unrefs the buffers in the two lists. + * The last_flow_return parameter indicates the expected flow return value from + * pushing the final buffer in the list. + * This can be used to set up a test which pushes some buffers and then an + * invalid buffer, when the final buffer is expected to fail, for example. + */ +/* FIXME 2.0: rename this function now that there's GstBufferList? */ +void +gst_check_element_push_buffer_list (const gchar * element_name, + GList * buffer_in, GstCaps * caps_in, GList * buffer_out, + GstCaps * caps_out, GstFlowReturn last_flow_return) +{ + GstElement *element; + GstPad *pad_peer; + GstPad *sink_pad = NULL; + GstPad *src_pad; + GstBuffer *buffer; + + /* check that there are no buffers waiting */ + gst_check_drop_buffers (); + /* create the element */ + element = gst_check_setup_element (element_name); + fail_if (element == NULL, "failed to create the element '%s'", element_name); + fail_unless (GST_IS_ELEMENT (element), "the element is no element"); + /* create the src pad */ + buffer = GST_BUFFER (buffer_in->data); + + fail_unless (GST_IS_BUFFER (buffer), "There should be a buffer in buffer_in"); + src_pad = gst_pad_new ("src", GST_PAD_SRC); + if (caps_in) { + fail_unless (gst_caps_is_fixed (caps_in)); + gst_pad_use_fixed_caps (src_pad); + } + /* activate the pad */ + gst_pad_set_active (src_pad, TRUE); + GST_DEBUG ("src pad activated"); + gst_check_setup_events (src_pad, element, caps_in, GST_FORMAT_BYTES); + pad_peer = gst_element_get_static_pad (element, "sink"); + fail_if (pad_peer == NULL); + fail_unless (gst_pad_link (src_pad, pad_peer) == GST_PAD_LINK_OK, + "Could not link source and %s sink pads", GST_ELEMENT_NAME (element)); + gst_object_unref (pad_peer); + /* don't create the sink_pad if there is no buffer_out list */ + if (buffer_out != NULL) { + + GST_DEBUG ("buffer out detected, creating the sink pad"); + /* get the sink caps */ + if (caps_out) { + gchar *temp; + + fail_unless (gst_caps_is_fixed (caps_out)); + temp = gst_caps_to_string (caps_out); + + GST_DEBUG ("sink caps requested by buffer out: '%s'", temp); + g_free (temp); + } + + /* get the sink pad */ + sink_pad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (GST_IS_PAD (sink_pad)); + /* configure the sink pad */ + gst_pad_set_chain_function (sink_pad, gst_check_chain_func); + gst_pad_set_active (sink_pad, TRUE); + if (caps_out) { + gst_pad_set_element_private (sink_pad, caps_out); + gst_pad_set_event_function (sink_pad, buffer_event_function); + } + /* get the peer pad */ + pad_peer = gst_element_get_static_pad (element, "src"); + fail_unless (gst_pad_link (pad_peer, sink_pad) == GST_PAD_LINK_OK, + "Could not link sink and %s source pads", GST_ELEMENT_NAME (element)); + gst_object_unref (pad_peer); + } + fail_unless (gst_element_set_state (element, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + /* push all the buffers in the buffer_in list */ + fail_unless (g_list_length (buffer_in) > 0, "the buffer_in list is empty"); + while (buffer_in != NULL) { + GstBuffer *next_buffer = GST_BUFFER (buffer_in->data); + + fail_unless (GST_IS_BUFFER (next_buffer), + "data in buffer_in should be a buffer"); + /* remove the buffer from the list */ + buffer_in = g_list_remove (buffer_in, next_buffer); + if (buffer_in == NULL) { + fail_unless (gst_pad_push (src_pad, next_buffer) == last_flow_return, + "we expect something else from the last buffer"); + } else { + fail_unless (gst_pad_push (src_pad, next_buffer) == GST_FLOW_OK, + "Failed to push buffer in"); + } + } + fail_unless (gst_element_set_state (element, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + /* check that there is a buffer out */ + fail_unless_equals_int (g_list_length (buffers), g_list_length (buffer_out)); + while (buffers != NULL) { + GstBuffer *new = GST_BUFFER (buffers->data); + GstBuffer *orig = GST_BUFFER (buffer_out->data); + GstMapInfo newinfo, originfo; + + fail_unless (gst_buffer_map (new, &newinfo, GST_MAP_READ)); + fail_unless (gst_buffer_map (orig, &originfo, GST_MAP_READ)); + + GST_LOG ("orig buffer: size %" G_GSIZE_FORMAT, originfo.size); + GST_LOG ("new buffer: size %" G_GSIZE_FORMAT, newinfo.size); + GST_MEMDUMP ("orig buffer", originfo.data, originfo.size); + GST_MEMDUMP ("new buffer", newinfo.data, newinfo.size); + + /* remove the buffers */ + buffers = g_list_remove (buffers, new); + buffer_out = g_list_remove (buffer_out, orig); + + fail_unless (originfo.size == newinfo.size, + "size of the buffers are not the same"); + fail_unless (memcmp (originfo.data, newinfo.data, newinfo.size) == 0, + "data is not the same"); +#if 0 + gst_check_caps_equal (GST_BUFFER_CAPS (orig), GST_BUFFER_CAPS (new)); +#endif + + gst_buffer_unmap (orig, &originfo); + gst_buffer_unmap (new, &newinfo); + + gst_buffer_unref (new); + gst_buffer_unref (orig); + } + /* teardown the element and pads */ + gst_pad_set_active (src_pad, FALSE); + gst_check_teardown_src_pad (element); + gst_pad_set_active (sink_pad, FALSE); + gst_check_teardown_sink_pad (element); + gst_check_teardown_element (element); +} + +/** + * gst_check_element_push_buffer: + * @element_name: name of the element that needs to be created + * @buffer_in: push this buffer to the element + * @caps_in: the #GstCaps expected of the sinkpad of the element + * @buffer_out: compare the result with this buffer + * @caps_out: the #GstCaps expected of the srcpad of the element + * + * Create an element using the factory providing the @element_name and + * push the @buffer_in to this element. The element should create one buffer + * and this will be compared with @buffer_out. We only check the caps + * and the data of the buffers. This function unrefs the buffers. + */ +void +gst_check_element_push_buffer (const gchar * element_name, + GstBuffer * buffer_in, GstCaps * caps_in, GstBuffer * buffer_out, + GstCaps * caps_out) +{ + GList *in = NULL; + GList *out = NULL; + + in = g_list_append (in, buffer_in); + out = g_list_append (out, buffer_out); + + gst_check_element_push_buffer_list (element_name, in, caps_in, out, caps_out, + GST_FLOW_OK); +} + +void +gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes) +{ + if (have_abi_sizes) { + gboolean ok = TRUE; + gint i; + + for (i = 0; list[i].name; i++) { + if (list[i].size != list[i].abi_size) { + ok = FALSE; + g_print ("sizeof(%s) is %d, expected %d\n", + list[i].name, list[i].size, list[i].abi_size); + } + } + fail_unless (ok, "failed ABI check"); + } else { + const gchar *fn; + + if ((fn = g_getenv ("GST_ABI"))) { + GError *err = NULL; + GString *s; + gint i; + + s = g_string_new ("\nGstCheckABIStruct list[] = {\n"); + for (i = 0; list[i].name; i++) { + g_string_append_printf (s, " {\"%s\", sizeof (%s), %d},\n", + list[i].name, list[i].name, list[i].size); + } + g_string_append (s, " {NULL, 0, 0}\n"); + g_string_append (s, "};\n"); + if (!g_file_set_contents (fn, s->str, s->len, &err)) { + g_print ("%s", s->str); + g_printerr ("\nFailed to write ABI information: %s\n", err->message); + g_clear_error (&err); + } else { + g_print ("\nWrote ABI information to '%s'.\n", fn); + } + g_string_free (s, TRUE); + } else { + g_print ("No structure size list was generated for this architecture.\n"); + g_print ("Run with GST_ABI environment variable set to output header.\n"); + } + } +} + +gint +gst_check_run_suite (Suite * suite, const gchar * name, const gchar * fname) +{ + SRunner *sr; + gchar *xmlfilename = NULL; + gint nf; + GTimer *timer; + + sr = srunner_create (suite); + + if (g_getenv ("GST_CHECK_XML")) { + /* how lucky we are to have __FILE__ end in .c */ + xmlfilename = g_strdup_printf ("%sheck.xml", fname); + + srunner_set_xml (sr, xmlfilename); + } + + timer = g_timer_new (); + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + g_print ("Check suite %s ran in %.3fs (tests failed: %d)\n", + name, g_timer_elapsed (timer, NULL), nf); + g_timer_destroy (timer); + g_free (xmlfilename); + srunner_free (sr); + return nf; +} + +static gboolean +gst_check_have_checks_list (const gchar * env_var_name) +{ + const gchar *env_val; + + env_val = g_getenv (env_var_name); + return (env_val != NULL && *env_val != '\0'); +} + +static gboolean +gst_check_func_is_in_list (const gchar * env_var, const gchar * func_name) +{ + const gchar *gst_checks; + gboolean res = FALSE; + gchar **funcs, **f; + + gst_checks = g_getenv (env_var); + + if (gst_checks == NULL || *gst_checks == '\0') + return FALSE; + + /* only run specified functions */ + funcs = g_strsplit (gst_checks, ",", -1); + for (f = funcs; f != NULL && *f != NULL; ++f) { + if (g_pattern_match_simple (*f, func_name)) { + res = TRUE; + break; + } + } + g_strfreev (funcs); + return res; +} + +gboolean +_gst_check_run_test_func (const gchar * func_name) +{ + /* if we have a whitelist, run it only if it's in the whitelist */ + if (gst_check_have_checks_list ("GST_CHECKS")) + return gst_check_func_is_in_list ("GST_CHECKS", func_name); + + /* if we have a blacklist, run it only if it's not in the blacklist */ + if (gst_check_have_checks_list ("GST_CHECKS_IGNORE")) + return !gst_check_func_is_in_list ("GST_CHECKS_IGNORE", func_name); + + /* no filter specified => run all checks */ + return TRUE; +} + +/** + * gst_check_setup_events_with_stream_id: + * @srcpad: The src #GstPad to push on + * @element: The #GstElement use to create the stream id + * @caps: (allow-none): #GstCaps in case caps event must be sent + * @format: The #GstFormat of the default segment to send + * @stream_id: A unique identifier for the stream + * + * Push stream-start, caps and segment event, which consist of the minimum + * required events to allow streaming. Caps is optional to allow raw src + * testing. + */ +void +gst_check_setup_events_with_stream_id (GstPad * srcpad, GstElement * element, + GstCaps * caps, GstFormat format, const gchar * stream_id) +{ + GstSegment segment; + + gst_segment_init (&segment, format); + + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_stream_start (stream_id))); + if (caps) + fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps))); + fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment))); +} + +/** + * gst_check_setup_events: + * @srcpad: The src #GstPad to push on + * @element: The #GstElement use to create the stream id + * @caps: (allow-none): #GstCaps in case caps event must be sent + * @format: The #GstFormat of the default segment to send + * + * Push stream-start, caps and segment event, which consist of the minimum + * required events to allow streaming. Caps is optional to allow raw src + * testing. If @element has more than one src or sink pad, use + * gst_check_setup_events_with_stream_id() instead. + */ +void +gst_check_setup_events (GstPad * srcpad, GstElement * element, + GstCaps * caps, GstFormat format) +{ + gchar *stream_id; + + stream_id = gst_pad_create_stream_id (srcpad, element, NULL); + gst_check_setup_events_with_stream_id (srcpad, element, caps, format, + stream_id); + g_free (stream_id); +} + +typedef struct _DestroyedObjectStruct +{ + GObject *object; + gboolean destroyed; +} DestroyedObjectStruct; + +static void +weak_notify (DestroyedObjectStruct * destroyed, GObject ** object) +{ + destroyed->destroyed = TRUE; +} + +/** + * gst_check_objects_destroyed_on_unref: + * @object_to_unref: The #GObject to unref + * @first_object: (allow-none): The first object that should be destroyed as a + * concequence of unrefing @object_to_unref. + * @... : Additional object that should have been destroyed. + * + * Unrefs @object_to_unref and checks that is has properly been + * destroyed, also checks that the other objects passed in + * parametter have been destroyed as a concequence of + * unrefing @object_to_unref. Last variable argument should be NULL. + * + * Since: 1.6 + */ +void +gst_check_objects_destroyed_on_unref (gpointer object_to_unref, + gpointer first_object, ...) +{ + GObject *object; + GList *objs = NULL, *tmp; + DestroyedObjectStruct *destroyed = g_slice_new0 (DestroyedObjectStruct); + + destroyed->object = object_to_unref; + g_object_weak_ref (object_to_unref, (GWeakNotify) weak_notify, destroyed); + objs = g_list_prepend (objs, destroyed); + + if (first_object) { + va_list varargs; + + object = first_object; + + va_start (varargs, first_object); + while (object) { + destroyed = g_slice_new0 (DestroyedObjectStruct); + destroyed->object = object; + g_object_weak_ref (object, (GWeakNotify) weak_notify, destroyed); + objs = g_list_prepend (objs, destroyed); + object = va_arg (varargs, GObject *); + } + va_end (varargs); + } + gst_object_unref (object_to_unref); + + for (tmp = objs; tmp; tmp = tmp->next) { + DestroyedObjectStruct *destroyed = tmp->data; + + if (!destroyed->destroyed) { + fail_unless (destroyed->destroyed, + "%s_%p is not destroyed, %d refcounts left!", + GST_IS_OBJECT (destroyed-> + object) ? GST_OBJECT_NAME (destroyed->object) : + G_OBJECT_TYPE_NAME (destroyed), destroyed->object, + destroyed->object->ref_count); + } + g_slice_free (DestroyedObjectStruct, tmp->data); + } + g_list_free (objs); +} + +/** + * gst_check_object_destroyed_on_unref: + * @object_to_unref: The #GObject to unref + * + * Unrefs @object_to_unref and checks that is has properly been + * destroyed. + * + * Since: 1.6 + */ +void +gst_check_object_destroyed_on_unref (gpointer object_to_unref) +{ + gst_check_objects_destroyed_on_unref (object_to_unref, NULL, NULL); +} + +/* For ABI compatibility with GStreamer < 1.5 */ +/* *INDENT-OFF* */ +void +_fail_unless (int result, const char *file, int line, const char *expr, ...) +G_GNUC_PRINTF (4, 5); +/* *INDENT-ON* */ + +void +_fail_unless (int result, const char *file, int line, const char *expr, ...) +{ + gchar *msg; + va_list args; + + if (result) { + _mark_point (file, line); + return; + } + + va_start (args, expr); + msg = g_strdup_vprintf (expr, args); + va_end (args); + + _ck_assert_failed (file, line, msg, NULL); + g_free (msg); +} diff --git a/libs/gst/check/gstcheck.h b/libs/gst/check/gstcheck.h new file mode 100644 index 0000000..94b8dae --- /dev/null +++ b/libs/gst/check/gstcheck.h @@ -0,0 +1,718 @@ +/* GStreamer + * + * Common code for GStreamer unittests + * + * Copyright (C) <2004> Thomas Vander Stichele + * Copyright (C) <2008> Thijs Vermeir + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CHECK_H__ +#define __GST_CHECK_H__ + +#include +#include +#include +#include + +#include +#include + +#define CK_DLL_EXP GST_CHECK_API +#include + +G_BEGIN_DECLS + +GST_CHECK_API GstDebugCategory *check_debug; +#define GST_CAT_DEFAULT check_debug + +/* logging function for tests + * a test uses g_message() to log a debug line + * a gst unit test can be run with GST_TEST_DEBUG env var set to see the + * messages + */ +GST_CHECK_API gboolean _gst_check_threads_running; +GST_CHECK_API gboolean _gst_check_raised_critical; +GST_CHECK_API gboolean _gst_check_raised_warning; +GST_CHECK_API gboolean _gst_check_expecting_log; +GST_CHECK_API gboolean _gst_check_list_tests; + +/* global variables used in test methods */ +GST_CHECK_API GList * buffers; + +GST_CHECK_API GMutex check_mutex; +GST_CHECK_API GCond check_cond; + +typedef struct +{ + const char *name; + int size; + int abi_size; +} +GstCheckABIStruct; + +typedef struct _GstCheckLogFilter GstCheckLogFilter; + +/** + * GstCheckLogFilterFunc: + * @log_domain: the log domain of the message + * @log_level: the log level of the message + * @message: the message that has occured + * @user_data: user data + * + * A function that is called for messages matching the filter added by + * @gst_check_add_log_filter. + * + * Returns: %TRUE if message should be discarded by GstCheck. + * + * Since: 1.12 + */ +typedef gboolean (*GstCheckLogFilterFunc) (const gchar * log_domain, + GLogLevelFlags log_level, const gchar * message, gpointer user_data); + +GST_CHECK_API +void gst_check_init (int *argc, char **argv[]); + +GST_CHECK_API +GstCheckLogFilter * gst_check_add_log_filter (const gchar * log, + GLogLevelFlags log_level, GRegex * regex, GstCheckLogFilterFunc func, + gpointer user_data, GDestroyNotify destroy_data); + +GST_CHECK_API +void gst_check_remove_log_filter (GstCheckLogFilter * filter); + +GST_CHECK_API +void gst_check_clear_log_filter (void); + +GST_CHECK_API +GstFlowReturn gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer); + +GST_CHECK_API +void gst_check_message_error (GstMessage * message, GstMessageType type, + GQuark domain, gint code); + +GST_CHECK_API +GstElement *gst_check_setup_element (const gchar * factory); + +GST_CHECK_API +void gst_check_teardown_element (GstElement * element); + +GST_CHECK_API +GstPad *gst_check_setup_src_pad (GstElement * element, + GstStaticPadTemplate * tmpl); + +GST_CHECK_API +GstPad *gst_check_setup_src_pad_from_template (GstElement * element, + GstPadTemplate * tmpl); + +GST_CHECK_API +GstPad * gst_check_setup_src_pad_by_name (GstElement * element, + GstStaticPadTemplate * tmpl, const gchar *name); + +GST_CHECK_API +GstPad * gst_check_setup_src_pad_by_name_from_template (GstElement * element, + GstPadTemplate * tmpl, const gchar *name); + +GST_CHECK_API +GstPad *gst_check_setup_sink_pad (GstElement * element, + GstStaticPadTemplate * tmpl); + +GST_CHECK_API +GstPad *gst_check_setup_sink_pad_from_template (GstElement * element, + GstPadTemplate * tmpl); + +GST_CHECK_API +GstPad * gst_check_setup_sink_pad_by_name (GstElement * element, + GstStaticPadTemplate * tmpl, const gchar *name); + +GST_CHECK_API +GstPad * gst_check_setup_sink_pad_by_name_from_template (GstElement * element, + GstPadTemplate * tmpl, const gchar *name); + +GST_CHECK_API +void gst_check_teardown_pad_by_name (GstElement * element, const gchar *name); + +GST_CHECK_API +void gst_check_teardown_src_pad (GstElement * element); + +GST_CHECK_API +void gst_check_drop_buffers (void); + +GST_CHECK_API +void gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2); + +GST_CHECK_API +void gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size); + +GST_CHECK_API +void gst_check_element_push_buffer_list (const gchar * element_name, + GList * buffer_in, GstCaps * caps_in, GList * buffer_out, + GstCaps * caps_out, GstFlowReturn last_flow_return); + +GST_CHECK_API +void gst_check_element_push_buffer (const gchar * element_name, + GstBuffer * buffer_in, GstCaps * caps_in, GstBuffer * buffer_out, + GstCaps *caps_out); + +GST_CHECK_API +void gst_check_teardown_sink_pad (GstElement * element); + +GST_CHECK_API +void gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes); + +GST_CHECK_API +gint gst_check_run_suite (Suite * suite, const gchar * name, + const gchar * fname); + +GST_CHECK_API +void gst_check_setup_events (GstPad * srcpad, GstElement * element, + GstCaps * caps, GstFormat format); + +GST_CHECK_API +void gst_check_setup_events_with_stream_id (GstPad * srcpad, + GstElement * element, GstCaps * caps, GstFormat format, + const gchar * stream_id); + +GST_CHECK_API +void gst_check_objects_destroyed_on_unref (gpointer object_to_unref, gpointer first_object, ...) + G_GNUC_NULL_TERMINATED; + +GST_CHECK_API +void gst_check_object_destroyed_on_unref (gpointer object_to_unref); + +#define fail_unless_message_error(msg, domain, code) \ +gst_check_message_error (msg, GST_MESSAGE_ERROR, \ + GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code) +#define assert_message_error(m, d, c) fail_unless_message_error(m, d, c) + +#ifdef GST_CHECK_TEST_ENVIRONMENT_BEACON +#define GST_DO_CHECK_TEST_ENVIRONMENT \ +G_STMT_START { \ + if (g_getenv (GST_CHECK_TEST_ENVIRONMENT_BEACON) == NULL) \ + fail ("Test environment not set up correctly! Expected environment " \ + "variable '%s' to be set.", GST_CHECK_TEST_ENVIRONMENT_BEACON); \ +} G_STMT_END + +#else +#define GST_DO_CHECK_TEST_ENVIRONMENT /* nothing to check */ +#endif + +/** + * GST_START_TEST: + * @__testname: test function name + * + * wrapper for checks START_TEST + */ +/** + * GST_END_TEST: + * + * wrapper for checks END_TEST + */ +#define GST_START_TEST(__testname) \ +static void __testname (int G_GNUC_UNUSED __i__) \ +{\ + GST_DEBUG ("test start"); \ + GST_DO_CHECK_TEST_ENVIRONMENT; \ + tcase_fn_start (""# __testname, __FILE__, __LINE__); + +#define GST_END_TEST GST_LOG ("cleaning up tasks"); \ + gst_task_cleanup_all (); \ + END_TEST + +/* additional fail macros */ +/** + * fail_unless_equals_int: + * @a: a #gint value or expression + * @b: a #gint value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define fail_unless_equals_int(a, b) \ +G_STMT_START { \ + int first = a; \ + int second = b; \ + fail_unless(first == second, \ + "'" #a "' (%d) is not equal to '" #b"' (%d)", first, second); \ +} G_STMT_END; +/** + * assert_equals_int: + * @a: a #gint value or expression + * @b: a #gint value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define assert_equals_int(a, b) fail_unless_equals_int(a, b) + +/** + * fail_unless_equals_int_hex: + * @a: a #gint value or expression + * @b: a #gint value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define fail_unless_equals_int_hex(a, b) \ +G_STMT_START { \ + int first = a; \ + int second = b; \ + fail_unless(first == second, \ + "'" #a "' (0x%08x) is not equal to '" #b"' (0x%08x)", first, second);\ +} G_STMT_END; + +/** + * assert_equals_int_hex: + * @a: a #gint value or expression + * @b: a #gint value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define assert_equals_int_hex(a, b) fail_unless_equals_int_hex(a, b) + +/** + * fail_unless_equals_int64: + * @a: a #gint64 value or expression + * @b: a #gint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define fail_unless_equals_int64(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GINT64_FORMAT") is not equal to '" #b"' (%" \ + G_GINT64_FORMAT")", first, second); \ +} G_STMT_END; +/** + * assert_equals_int64: + * @a: a #gint64 value or expression + * @b: a #gint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define assert_equals_int64(a, b) fail_unless_equals_int64(a, b) + +/** + * fail_unless_equals_int64_hex: + * @a: a #gint64 value or expression + * @b: a #gint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define fail_unless_equals_int64_hex(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (0x%016x) is not equal to '" #b"' (0x%016x)", first, second);\ +} G_STMT_END; +/** + * assert_equals_int64_hex: + * @a: a #gint64 value or expression + * @b: a #gint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define assert_equals_int64_hex(a,b) fail_unless_equals_int64_hex(a,b) + +/** + * fail_unless_equals_uint64: + * @a: a #guint64 value or expression + * @b: a #guint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define fail_unless_equals_uint64(a, b) \ +G_STMT_START { \ + guint64 first = a; \ + guint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GUINT64_FORMAT ") is not equal to '" #b"' (%" \ + G_GUINT64_FORMAT ")", first, second); \ +} G_STMT_END; +/** + * assert_equals_uint64: + * @a: a #guint64 value or expression + * @b: a #guint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to. This + * macro is for use in unit tests. + */ +#define assert_equals_uint64(a, b) fail_unless_equals_uint64(a, b) + +/** + * fail_unless_equals_uint64_hex: + * @a: a #gint64 value or expression + * @b: a #gint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define fail_unless_equals_uint64_hex(a, b) \ +G_STMT_START { \ + guint64 first = a; \ + guint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (0x%016x) is not equal to '" #b"' (0x%016x)", first, second);\ +} G_STMT_END; +/** + * assert_equals_uint64_hex: + * @a: a #guint64 value or expression + * @b: a #guint64 value or expression + * + * This macro checks that @a and @b are equal and aborts if this is not the + * case, printing both expressions and the values they evaluated to in + * hexadecimal format. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define assert_equals_uint64_hex(a,b) fail_unless_equals_uint64_hex(a,b) + +/** + * fail_unless_equals_string: + * @a: a string literal or expression + * @b: a string literal or expression + * + * This macro checks that @a and @b are equal (as per strcmp) and aborts if + * this is not the case, printing both expressions and the values they + * evaluated to. This macro is for use in unit tests. + */ +#define fail_unless_equals_string(a, b) \ +G_STMT_START { \ + const gchar * first = a; \ + const gchar * second = b; \ + fail_unless(g_strcmp0 (first, second) == 0, \ + "'" #a "' (%s) is not equal to '" #b"' (%s)", first, second); \ +} G_STMT_END; +/** + * assert_equals_string: + * @a: a string literal or expression + * @b: a string literal or expression + * + * This macro checks that @a and @b are equal (as per strcmp) and aborts if + * this is not the case, printing both expressions and the values they + * evaluated to. This macro is for use in unit tests. + */ +#define assert_equals_string(a, b) fail_unless_equals_string(a, b) + +/** + * fail_unless_equals_float: + * @a: a #gdouble or #gfloat value or expression + * @b: a #gdouble or #gfloat value or expression + * + * This macro checks that @a and @b are (almost) equal and aborts if this + * is not the case, printing both expressions and the values they evaluated + * to. This macro is for use in unit tests. + */ +#define fail_unless_equals_float(a, b) \ +G_STMT_START { \ + double first = a; \ + double second = b; \ + /* This will only work for 'normal' values and values around 0, \ + * which should be good enough for our purposes here */ \ + fail_unless(fabs (first - second) < 0.0000001, \ + "'" #a "' (%g) is not equal to '" #b "' (%g)", first, second);\ +} G_STMT_END; + +/** + * assert_equals_float: + * @a: a #gdouble or #gfloat value or expression + * @b: a #gdouble or #gfloat value or expression + * + * This macro checks that @a and @b are (almost) equal and aborts if this + * is not the case, printing both expressions and the values they evaluated + * to. This macro is for use in unit tests. + */ +#define assert_equals_float(a, b) fail_unless_equals_float(a, b) + +/** + * fail_unless_equals_pointer: + * @a: a pointer value or expression + * @b: a pointer value or expression + * + * This macro checks that @a and @b are equal and aborts if this + * is not the case, printing both expressions and the values they + * evaluated to. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define fail_unless_equals_pointer(a, b) \ +G_STMT_START { \ + gpointer first = a; \ + gpointer second = b; \ + fail_unless(first == second, \ + "'" #a "' (%p) is not equal to '" #b "' (%p)", first, second);\ +} G_STMT_END; + +/** + * assert_equals_pointer: + * @a: a pointer value or expression + * @b: a pointer value or expression + * + * This macro checks that @a and @b are equal and aborts if this + * is not the case, printing both expressions and the values they + * evaluated to. This macro is for use in unit tests. + * + * Since: 1.2 + */ +#define assert_equals_pointer(a, b) fail_unless_equals_pointer(a, b) + +/*** + * thread test macros and variables + */ +GST_CHECK_API GList *thread_list; +GST_CHECK_API GMutex mutex; +GST_CHECK_API GCond start_cond; /* used to notify main thread of thread startups */ +GST_CHECK_API GCond sync_cond; /* used to synchronize all threads and main thread */ + +#define MAIN_START_THREADS(count, function, data) \ +MAIN_INIT(); \ +MAIN_START_THREAD_FUNCTIONS(count, function, data); \ +MAIN_SYNCHRONIZE(); + +#define MAIN_INIT() \ +G_STMT_START { \ + g_mutex_init (&mutex); \ + g_cond_init (&start_cond); \ + g_cond_init (&sync_cond); \ + _gst_check_threads_running = TRUE; \ +} G_STMT_END; + +#define MAIN_START_THREAD_FUNCTIONS(count, function, data) \ +G_STMT_START { \ + int i; \ + for (i = 0; i < count; ++i) { \ + MAIN_START_THREAD_FUNCTION (i, function, data); \ + } \ +} G_STMT_END; + +#define MAIN_START_THREAD_FUNCTION(i, function, data) \ +G_STMT_START { \ + GThread *thread = NULL; \ + GST_DEBUG ("MAIN: creating thread %d", i); \ + g_mutex_lock (&mutex); \ + thread = g_thread_try_new ("gst-check", \ + (GThreadFunc) function, data, NULL); \ + /* wait for thread to signal us that it's ready */ \ + GST_DEBUG ("MAIN: waiting for thread %d", i); \ + g_cond_wait (&start_cond, &mutex); \ + g_mutex_unlock (&mutex); \ + \ + thread_list = g_list_append (thread_list, thread); \ +} G_STMT_END; + + +#define MAIN_SYNCHRONIZE() \ +G_STMT_START { \ + GST_DEBUG ("MAIN: synchronizing"); \ + g_cond_broadcast (&sync_cond); \ + GST_DEBUG ("MAIN: synchronized"); \ +} G_STMT_END; + +#define MAIN_STOP_THREADS() \ +G_STMT_START { \ + _gst_check_threads_running = FALSE; \ + \ + /* join all threads */ \ + GST_DEBUG ("MAIN: joining"); \ + g_list_foreach (thread_list, (GFunc) g_thread_join, NULL); \ + g_list_free (thread_list); \ + thread_list = NULL; \ + g_mutex_clear (&mutex); \ + g_cond_clear (&start_cond); \ + g_cond_clear (&sync_cond); \ + GST_DEBUG ("MAIN: joined"); \ +} G_STMT_END; + +#define THREAD_START() \ +THREAD_STARTED(); \ +THREAD_SYNCHRONIZE(); + +#define THREAD_STARTED() \ +G_STMT_START { \ + /* signal main thread that we started */ \ + GST_DEBUG ("THREAD %p: started", g_thread_self ()); \ + g_mutex_lock (&mutex); \ + g_cond_signal (&start_cond); \ +} G_STMT_END; + +#define THREAD_SYNCHRONIZE() \ +G_STMT_START { \ + /* synchronize everyone */ \ + GST_DEBUG ("THREAD %p: syncing", g_thread_self ()); \ + fail_if (g_mutex_trylock (&mutex), \ + "bug in unit test, mutex should be locked at this point");\ + g_cond_wait (&sync_cond, &mutex); \ + GST_DEBUG ("THREAD %p: synced", g_thread_self ()); \ + g_mutex_unlock (&mutex); \ +} G_STMT_END; + +#define THREAD_SWITCH() \ +G_STMT_START { \ + /* a minimal sleep is a context switch */ \ + g_usleep (1); \ +} G_STMT_END; + +#define THREAD_TEST_RUNNING() (!!_gst_check_threads_running) + +/* additional assertions */ +#define ASSERT_CRITICAL(code) \ +G_STMT_START { \ + _gst_check_expecting_log = TRUE; \ + _gst_check_raised_critical = FALSE; \ + code; \ + if (!_gst_check_raised_critical) \ + _ck_assert_failed (__FILE__, __LINE__, \ + "Expected g_critical, got nothing", NULL); \ + _gst_check_expecting_log = FALSE; \ +} G_STMT_END + +#define ASSERT_WARNING(code) \ +G_STMT_START { \ + _gst_check_expecting_log = TRUE; \ + _gst_check_raised_warning = FALSE; \ + code; \ + if (!_gst_check_raised_warning) \ + _ck_assert_failed (__FILE__, __LINE__, \ + "Expected g_warning, got nothing", NULL); \ + _gst_check_expecting_log = FALSE; \ +} G_STMT_END + + +#define ASSERT_OBJECT_REFCOUNT(object, name, value) \ +G_STMT_START { \ + int rc; \ + rc = GST_OBJECT_REFCOUNT_VALUE (object); \ + fail_unless (rc == value, \ + "%s (%p) refcount is %d instead of %d", \ + name, object, rc, value); \ +} G_STMT_END + +#define ASSERT_OBJECT_REFCOUNT_BETWEEN(object, name, lower, upper) \ +G_STMT_START { \ + int rc = GST_OBJECT_REFCOUNT_VALUE (object); \ + int lo = lower; \ + int hi = upper; \ + \ + fail_unless (rc >= lo, \ + "%s (%p) refcount %d is smaller than %d", \ + name, object, rc, lo); \ + fail_unless (rc <= hi, \ + "%s (%p) refcount %d is bigger than %d", \ + name, object, rc, hi); \ +} G_STMT_END + + +#define ASSERT_CAPS_REFCOUNT(caps, name, value) \ + ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value) + +#define ASSERT_BUFFER_REFCOUNT(buffer, name, value) \ + ASSERT_MINI_OBJECT_REFCOUNT(buffer, name, value) + +#define ASSERT_MINI_OBJECT_REFCOUNT(miniobj, name, value) \ +G_STMT_START { \ + int rc; \ + rc = GST_MINI_OBJECT_REFCOUNT_VALUE (miniobj); \ + fail_unless (rc == value, \ + name " (%p) refcount is %d instead of %d", miniobj, rc, value); \ +} G_STMT_END + +#define ASSERT_SET_STATE(element, state, ret) \ +fail_unless (gst_element_set_state (GST_ELEMENT(element), \ + state) == ret, \ + "could not change state to " #state); + +#define GST_CHECK_MAIN(name) \ +int main (int argc, char **argv) \ +{ \ + Suite *s; \ + gst_check_init (&argc, &argv); \ + s = name ## _suite (); \ + return gst_check_run_suite (s, # name, __FILE__); \ +} + +/* Hack to allow run-time selection of unit tests to run via the + * GST_CHECKS environment variable (test function names globs, comma + * separated), or GST_CHECKS_IGNORE with the same semantics */ + +GST_CHECK_API +gboolean _gst_check_run_test_func (const gchar * func_name); + +static inline void +__gst_tcase_add_test (TCase * tc, TFun tf, const char * fname, int signal, + int allowed_exit_value, int start, int end) +{ + if (_gst_check_list_tests) { + g_print ("Test: %s\n", fname); + return; + } + + if (_gst_check_run_test_func (fname)) { + _tcase_add_test (tc, tf, fname, signal, allowed_exit_value, start, end); + } +} + +#define _tcase_add_test __gst_tcase_add_test + +/* A special variant to add broken tests. These are normally skipped, but can be + * forced to run via GST_CHECKS */ +#define tcase_skip_broken_test(chain,test_func) \ +G_STMT_START { \ + const char *env = g_getenv ("GST_CHECKS"); \ + \ + if (env != NULL && g_pattern_match_simple (env, G_STRINGIFY (test_func))) { \ + tcase_add_test(chain,test_func); \ + } else { \ + g_printerr ("FIXME: skipping test %s because it's broken\n", G_STRINGIFY (test_func)); \ + } \ +} G_STMT_END + +#define tcase_skip_broken_loop_test(chain,test_func,a,b) \ + tcase_skip_broken_test (chain, test_func) + +G_END_DECLS + +#endif /* __GST_CHECK_H__ */ diff --git a/libs/gst/check/gstconsistencychecker.c b/libs/gst/check/gstconsistencychecker.c new file mode 100644 index 0000000..cf1dbf7 --- /dev/null +++ b/libs/gst/check/gstconsistencychecker.c @@ -0,0 +1,302 @@ +/* GStreamer + * + * unit testing helper lib + * + * Copyright (C) 2009 Edward Hervey + * Copyright (C) 2012 Stefan Sauer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstcheckconsistencychecker + * @title: GstStreamConsistencyChecker + * @short_description: Data flow consistency checker for GStreamer unit tests. + * + * These macros and functions are for internal use of the unit tests found + * inside the 'check' directories of various GStreamer packages. + */ + +#include "gstconsistencychecker.h" + +struct _GstStreamConsistency +{ + /* FIXME: do we want to track some states per pad? */ + volatile gboolean flushing; + volatile gboolean segment; + volatile gboolean eos; + volatile gboolean expect_flush; + volatile gboolean saw_serialized_event; + volatile gboolean saw_stream_start; + GstObject *parent; + GList *pads; +}; + +typedef struct _GstStreamConsistencyProbe +{ + GstPad *pad; + gulong probeid; +} GstStreamConsistencyProbe; + +static gboolean +source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, + GstStreamConsistency * consist) +{ + GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); + + GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing, + consist->segment, consist->eos, consist->expect_flush); + + if (GST_IS_BUFFER (data)) { + GST_DEBUG_OBJECT (pad, + "Buffer pts %" GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (GST_BUFFER_CAST (data))), + GST_TIME_ARGS (GST_BUFFER_DTS (GST_BUFFER_CAST (data)))); + /* If an EOS went through, a buffer would be invalid */ + fail_if (consist->eos, "Buffer received after EOS on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + /* Buffers need to be preceded by a segment event */ + fail_unless (consist->segment, "Buffer received without segment " + "on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + } else if (GST_IS_EVENT (data)) { + GstEvent *event = (GstEvent *) data; + + GST_DEBUG_OBJECT (pad, "Event : %s", GST_EVENT_TYPE_NAME (event)); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + /* getting two flush_start in a row seems to be okay + fail_if (consist->flushing, "Received another FLUSH_START"); + */ + consist->flushing = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + /* Receiving a flush-stop is only valid after receiving a flush-start */ + fail_unless (consist->flushing, + "Received a FLUSH_STOP without a FLUSH_START on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + fail_if (consist->eos, "Received a FLUSH_STOP after an EOS on " + "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + consist->flushing = consist->expect_flush = FALSE; + break; + case GST_EVENT_STREAM_START: + fail_if (consist->saw_serialized_event && !consist->saw_stream_start, + "Got a STREAM_START event after a serialized event on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + consist->saw_stream_start = TRUE; + break; + case GST_EVENT_CAPS: + /* ok to have these before segment event */ + /* FIXME check order more precisely, if so spec'ed somehow ? */ + break; + case GST_EVENT_SEGMENT: + fail_if ((consist->expect_flush && consist->flushing), + "Received SEGMENT while in a flushing seek on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + consist->segment = TRUE; + consist->eos = FALSE; + break; + case GST_EVENT_EOS: + /* FIXME : not 100% sure about whether two eos in a row is valid */ + fail_if (consist->eos, "Received EOS just after another EOS on " + "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + consist->eos = TRUE; + consist->segment = FALSE; + break; + case GST_EVENT_TAG: + GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT, + gst_event_get_structure (event)); + /* fall through */ + default: + if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_IS_DOWNSTREAM (event)) { + fail_if (consist->eos, "Event received after EOS"); + fail_unless (consist->segment, "Event %s received before segment " + "on pad %s:%s", GST_EVENT_TYPE_NAME (event), + GST_DEBUG_PAD_NAME (pad)); + } + /* FIXME : Figure out what to do for other events */ + break; + } + if (GST_EVENT_IS_SERIALIZED (event)) { + fail_if (!consist->saw_stream_start + && GST_EVENT_TYPE (event) != GST_EVENT_STREAM_START, + "Got a serialized event (%s) before a STREAM_START on pad %s:%s", + GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad)); + consist->saw_serialized_event = TRUE; + } + } + + return TRUE; +} + +static gboolean +sink_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, + GstStreamConsistency * consist) +{ + GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); + + GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing, + consist->segment, consist->eos, consist->expect_flush); + + if (GST_IS_BUFFER (data)) { + GST_DEBUG_OBJECT (pad, "Buffer %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (GST_BUFFER (data)))); + /* If an EOS went through, a buffer would be invalid */ + fail_if (consist->eos, "Buffer received after EOS on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + /* Buffers need to be preceded by a segment event */ + fail_unless (consist->segment, "Buffer received without segment " + "on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + } else if (GST_IS_EVENT (data)) { + GstEvent *event = (GstEvent *) data; + + GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event)); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstSeekFlags flags; + + gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, + NULL); + consist->expect_flush = + ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH); + break; + } + case GST_EVENT_SEGMENT: + fail_if ((consist->expect_flush && consist->flushing), + "Received SEGMENT while in a flushing seek on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + consist->segment = TRUE; + consist->eos = FALSE; + break; + default: + /* FIXME : Figure out what to do for other events */ + break; + } + } + + return TRUE; +} + +static void +add_pad (GstStreamConsistency * consist, GstPad * pad) +{ + GstStreamConsistencyProbe *p; + GstPadDirection dir; + + p = g_new0 (GstStreamConsistencyProbe, 1); + p->pad = g_object_ref (pad); + dir = gst_pad_get_direction (pad); + if (dir == GST_PAD_SRC) { + + p->probeid = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + (GstPadProbeCallback) source_pad_data_cb, consist, NULL); + + } else if (dir == GST_PAD_SINK) { + p->probeid = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + (GstPadProbeCallback) sink_pad_data_cb, consist, NULL); + } + consist->pads = g_list_prepend (consist->pads, p); +} + +/** + * gst_consistency_checker_new: (skip) + * @pad: The #GstPad on which the dataflow will be checked. + * + * Sets up a data probe on the given pad which will raise assertions if the + * data flow is inconsistent. + * + * Returns: A #GstStreamConsistency structure used to track data flow. + */ +GstStreamConsistency * +gst_consistency_checker_new (GstPad * pad) +{ + GstStreamConsistency *consist; + + g_return_val_if_fail (pad != NULL, NULL); + + consist = g_new0 (GstStreamConsistency, 1); + + if (!consist->pads) { + consist->parent = GST_OBJECT_PARENT (pad); + } + add_pad (consist, pad); + return consist; +} + +/** + * gst_consistency_checker_add_pad: + * @consist: The #GstStreamConsistency handle + * @pad: The #GstPad on which the dataflow will be checked. + * + * Sets up a data probe on the given pad which will raise assertions if the + * data flow is inconsistent. + * + * Returns: %TRUE if the pad was added + */ +gboolean +gst_consistency_checker_add_pad (GstStreamConsistency * consist, GstPad * pad) +{ + g_return_val_if_fail (consist != NULL, FALSE); + g_return_val_if_fail (pad != NULL, FALSE); + g_return_val_if_fail (GST_OBJECT_PARENT (pad) == consist->parent, FALSE); + + add_pad (consist, pad); + return TRUE; +} + +/** + * gst_consistency_checker_reset: + * @consist: The #GstStreamConsistency to reset. + * + * Reset the stream checker's internal variables. + */ + +void +gst_consistency_checker_reset (GstStreamConsistency * consist) +{ + consist->flushing = FALSE; + consist->segment = FALSE; + consist->eos = FALSE; + consist->expect_flush = FALSE; + consist->saw_serialized_event = FALSE; + consist->saw_stream_start = FALSE; +} + +/** + * gst_consistency_checker_free: + * @consist: The #GstStreamConsistency to free. + * + * Frees the allocated data and probes associated with @consist. + */ + +void +gst_consistency_checker_free (GstStreamConsistency * consist) +{ + GList *node; + GstStreamConsistencyProbe *p; + + /* Remove the data probes */ + for (node = consist->pads; node; node = g_list_next (node)) { + p = (GstStreamConsistencyProbe *) node->data; + gst_pad_remove_probe (p->pad, p->probeid); + gst_object_unref (p->pad); + g_free (p); + } + g_list_free (consist->pads); + g_free (consist); +} diff --git a/libs/gst/check/gstconsistencychecker.h b/libs/gst/check/gstconsistencychecker.h new file mode 100644 index 0000000..03ce583 --- /dev/null +++ b/libs/gst/check/gstconsistencychecker.h @@ -0,0 +1,52 @@ +/* GStreamer + * + * unit testing helper lib + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONSISTENCY_CHECKER_H__ +#define __GST_CONSISTENCY_CHECKER_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstStreamConsistency: + * + * Opaque consistency checker handle. + */ +typedef struct _GstStreamConsistency GstStreamConsistency; + +GST_CHECK_API +GstStreamConsistency * gst_consistency_checker_new (GstPad * pad); + +GST_CHECK_API +gboolean gst_consistency_checker_add_pad (GstStreamConsistency * consist, + GstPad * pad); + +GST_CHECK_API +void gst_consistency_checker_reset (GstStreamConsistency * consist); + +GST_CHECK_API +void gst_consistency_checker_free (GstStreamConsistency * consist); + +G_END_DECLS + +#endif /* __GST_CONSISTENCY_CHECKER_H__ */ diff --git a/libs/gst/check/gstharness.c b/libs/gst/check/gstharness.c new file mode 100644 index 0000000..5909ced --- /dev/null +++ b/libs/gst/check/gstharness.c @@ -0,0 +1,3314 @@ +/* GstHarness - A test-harness for GStreamer testing + * + * Copyright (C) 2012-2015 Pexip + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstharness + * @title: GstHarness + * @short_description: A test-harness for writing GStreamer unit tests + * @see_also: #GstTestClock + * + * #GstHarness is meant to make writing unit test for GStreamer much easier. + * It can be thought of as a way of treating a #GstElement as a black box, + * deterministically feeding it data, and controlling what data it outputs. + * + * The basic structure of #GstHarness is two "floating" #GstPads that connect + * to the harnessed #GstElement src and sink #GstPads like so: + * + * |[ + * __________________________ + * _____ | _____ _____ | _____ + * | | | | | | | | | | + * | src |--+-| sink| Element | src |-+--| sink| + * |_____| | |_____| |_____| | |_____| + * |__________________________| + * + * ]| + * + * With this, you can now simulate any environment the #GstElement might find + * itself in. By specifying the #GstCaps of the harness #GstPads, using + * functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(), + * you can test how the #GstElement interacts with different caps sets. + * + * Your harnessed #GstElement can of course also be a bin, and using + * gst_harness_new_parse() supporting standard gst-launch syntax, you can + * easily test a whole pipeline instead of just one element. + * + * You can then go on to push #GstBuffers and #GstEvents on to the srcpad, + * using functions like gst_harness_push() and gst_harness_push_event(), and + * then pull them out to examine them with gst_harness_pull() and + * gst_harness_pull_event(). + * + * ## A simple buffer-in buffer-out example + * + * |[ + * #include + * #include + * GstHarness *h; + * GstBuffer *in_buf; + * GstBuffer *out_buf; + * + * // attach the harness to the src and sink pad of GstQueue + * h = gst_harness_new ("queue"); + * + * // we must specify a caps before pushing buffers + * gst_harness_set_src_caps_str (h, "mycaps"); + * + * // create a buffer of size 42 + * in_buf = gst_harness_create_buffer (h, 42); + * + * // push the buffer into the queue + * gst_harness_push (h, in_buf); + * + * // pull the buffer from the queue + * out_buf = gst_harness_pull (h); + * + * // validate the buffer in is the same as buffer out + * fail_unless (in_buf == out_buf); + * + * // cleanup + * gst_buffer_unref (out_buf); + * gst_harness_teardown (h); + * + * ]| + * + * Another main feature of the #GstHarness is its integration with the + * #GstTestClock. Operating the #GstTestClock can be very challenging, but + * #GstHarness simplifies some of the most desired actions a lot, like wanting + * to manually advance the clock while at the same time releasing a #GstClockID + * that is waiting, with functions like gst_harness_crank_single_clock_wait(). + * + * #GstHarness also supports sub-harnesses, as a way of generating and + * validating data. A sub-harness is another #GstHarness that is managed by + * the "parent" harness, and can either be created by using the standard + * gst_harness_new type functions directly on the (GstHarness *)->src_harness, + * or using the much more convenient gst_harness_add_src() or + * gst_harness_add_sink_parse(). If you have a decoder-element you want to test, + * (like vp8dec) it can be very useful to add a src-harness with both a + * src-element (videotestsrc) and an encoder (vp8enc) to feed the decoder data + * with different configurations, by simply doing: + * + * |[ + * GstHarness * h = gst_harness_new (h, "vp8dec"); + * gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE); + * ]| + * + * and then feeding it data with: + * + * |[ + * gst_harness_push_from_src (h); + * ]| + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* we have code with side effects in asserts, so make sure they are active */ +#ifdef G_DISABLE_ASSERT +#error "GstHarness must be compiled with G_DISABLE_ASSERT undefined" +#endif + +#include "gstharness.h" + +#include +#include +#include + +static void gst_harness_stress_free (GstHarnessThread * t); + +#define HARNESS_KEY "harness" +#define HARNESS_REF "harness-ref" +#define HARNESS_LOCK(h) g_mutex_lock (&(h)->priv->priv_mutex) +#define HARNESS_UNLOCK(h) g_mutex_unlock (&(h)->priv->priv_mutex) + +static GstStaticPadTemplate hsrctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate hsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +struct _GstHarnessPrivate +{ + gchar *element_sinkpad_name; + gchar *element_srcpad_name; + + GstCaps *src_caps; + GstCaps *sink_caps; + + gboolean forwarding; + GstPad *sink_forward_pad; + GstTestClock *testclock; + + volatile gint recv_buffers; + volatile gint recv_events; + volatile gint recv_upstream_events; + + GAsyncQueue *buffer_queue; + GAsyncQueue *src_event_queue; + GAsyncQueue *sink_event_queue; + + GstClockTime latency_min; + GstClockTime latency_max; + gboolean has_clock_wait; + gboolean drop_buffers; + GstClockTime last_push_ts; + + GstBufferPool *pool; + GstAllocator *allocator; + GstAllocationParams allocation_params; + GstAllocator *propose_allocator; + GstAllocationParams propose_allocation_params; + + gboolean blocking_push_mode; + GCond blocking_push_cond; + GMutex blocking_push_mutex; + GMutex priv_mutex; + + GPtrArray *stress; +}; + +static GstFlowReturn +gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY); + GstHarnessPrivate *priv = h->priv; + (void) parent; + g_assert (h != NULL); + g_mutex_lock (&priv->blocking_push_mutex); + g_atomic_int_inc (&priv->recv_buffers); + + if (priv->drop_buffers) + gst_buffer_unref (buffer); + else + g_async_queue_push (priv->buffer_queue, buffer); + + if (priv->blocking_push_mode) { + g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex); + } + g_mutex_unlock (&priv->blocking_push_mutex); + + return GST_FLOW_OK; +} + +static gboolean +gst_harness_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY); + GstHarnessPrivate *priv = h->priv; + (void) parent; + g_assert (h != NULL); + g_atomic_int_inc (&priv->recv_upstream_events); + g_async_queue_push (priv->src_event_queue, event); + return TRUE; +} + +static gboolean +gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY); + GstHarnessPrivate *priv = h->priv; + gboolean ret = TRUE; + gboolean forward; + + g_assert (h != NULL); + (void) parent; + g_atomic_int_inc (&priv->recv_events); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + case GST_EVENT_CAPS: + case GST_EVENT_SEGMENT: + forward = TRUE; + break; + default: + forward = FALSE; + break; + } + + HARNESS_LOCK (h); + if (priv->forwarding && forward && priv->sink_forward_pad) { + GstPad *fwdpad = gst_object_ref (priv->sink_forward_pad); + HARNESS_UNLOCK (h); + ret = gst_pad_push_event (fwdpad, event); + gst_object_unref (fwdpad); + HARNESS_LOCK (h); + } else { + g_async_queue_push (priv->sink_event_queue, event); + } + HARNESS_UNLOCK (h); + + return ret; +} + +static void +gst_harness_decide_allocation (GstHarness * h, GstCaps * caps) +{ + GstHarnessPrivate *priv = h->priv; + GstQuery *query; + GstAllocator *allocator; + GstAllocationParams params; + GstBufferPool *pool = NULL; + guint size, min, max; + + query = gst_query_new_allocation (caps, FALSE); + gst_pad_peer_query (h->srcpad, query); + + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + } + + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); +#if 0 + /* Most elements create their own pools if pool == NULL. Not sure if we + * want to do that in the harness since we may want to test the pool + * implementation of the elements. Not creating a pool will however ignore + * the returned size. */ + if (pool == NULL) + pool = gst_buffer_pool_new (); +#endif + } else { + pool = NULL; + size = min = max = 0; + } + gst_query_unref (query); + + if (pool) { + GstStructure *config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + gst_buffer_pool_set_config (pool, config); + } + + if (pool != priv->pool) { + if (priv->pool != NULL) + gst_buffer_pool_set_active (priv->pool, FALSE); + if (pool) + gst_buffer_pool_set_active (pool, TRUE); + } + + priv->allocation_params = params; + if (priv->allocator) + gst_object_unref (priv->allocator); + priv->allocator = allocator; + if (priv->pool) + gst_object_unref (priv->pool); + priv->pool = pool; +} + +static void +gst_harness_negotiate (GstHarness * h) +{ + GstCaps *caps; + + caps = gst_pad_get_current_caps (h->srcpad); + if (caps != NULL) { + gst_harness_decide_allocation (h, caps); + gst_caps_unref (caps); + } else { + GST_FIXME_OBJECT (h, "Cannot negotiate allocation because caps is not set"); + } +} + +static gboolean +gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY); + GstHarnessPrivate *priv = h->priv; + gboolean res = TRUE; + g_assert (h != NULL); + + // FIXME: forward all queries? + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max); + break; + case GST_QUERY_CAPS: + { + GstCaps *caps, *filter = NULL; + + if (priv->sink_caps) { + caps = gst_caps_ref (priv->sink_caps); + } else { + caps = gst_pad_get_pad_template_caps (pad); + } + + gst_query_parse_caps (query, &filter); + if (filter != NULL) { + gst_caps_take (&caps, + gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST)); + } + + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + } + break; + case GST_QUERY_ALLOCATION: + { + HARNESS_LOCK (h); + if (priv->forwarding && priv->sink_forward_pad != NULL) { + GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad); + g_assert (peer != NULL); + HARNESS_UNLOCK (h); + res = gst_pad_query (peer, query); + gst_object_unref (peer); + HARNESS_LOCK (h); + } else { + GstCaps *caps; + gboolean need_pool; + guint size; + + gst_query_parse_allocation (query, &caps, &need_pool); + + /* FIXME: Can this be removed? */ + size = gst_query_get_n_allocation_params (query); + g_assert_cmpuint (0, ==, size); + gst_query_add_allocation_param (query, + priv->propose_allocator, &priv->propose_allocation_params); + + GST_DEBUG_OBJECT (pad, "proposing allocation %" GST_PTR_FORMAT, + priv->propose_allocator); + } + HARNESS_UNLOCK (h); + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + } + + return res; +} + +static gboolean +gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY); + GstHarnessPrivate *priv = h->priv; + gboolean res = TRUE; + g_assert (h != NULL); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max); + break; + case GST_QUERY_CAPS: + { + GstCaps *caps, *filter = NULL; + + if (priv->src_caps) { + caps = gst_caps_ref (priv->src_caps); + } else { + caps = gst_pad_get_pad_template_caps (pad); + } + + gst_query_parse_caps (query, &filter); + if (filter != NULL) { + gst_caps_take (&caps, + gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST)); + } + + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + } + break; + default: + res = gst_pad_query_default (pad, parent, query); + } + return res; +} + +static void +gst_harness_element_ref (GstHarness * h) +{ + guint *data; + + GST_OBJECT_LOCK (h->element); + data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF); + if (data == NULL) { + data = g_new0 (guint, 1); + *data = 1; + g_object_set_data_full (G_OBJECT (h->element), HARNESS_REF, data, g_free); + } else { + (*data)++; + } + GST_OBJECT_UNLOCK (h->element); +} + +static guint +gst_harness_element_unref (GstHarness * h) +{ + guint *data; + guint ret; + + GST_OBJECT_LOCK (h->element); + data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF); + g_assert (data != NULL); + (*data)--; + ret = *data; + GST_OBJECT_UNLOCK (h->element); + + return ret; +} + +static void +gst_harness_link_element_srcpad (GstHarness * h, + const gchar * element_srcpad_name) +{ + GstHarnessPrivate *priv = h->priv; + GstPad *srcpad = gst_element_get_static_pad (h->element, + element_srcpad_name); + GstPadLinkReturn link; + if (srcpad == NULL) + srcpad = gst_element_get_request_pad (h->element, element_srcpad_name); + g_assert (srcpad); + link = gst_pad_link (srcpad, h->sinkpad); + g_assert_cmpint (link, ==, GST_PAD_LINK_OK); + g_free (priv->element_srcpad_name); + priv->element_srcpad_name = gst_pad_get_name (srcpad); + + gst_object_unref (srcpad); +} + +static void +gst_harness_link_element_sinkpad (GstHarness * h, + const gchar * element_sinkpad_name) +{ + GstHarnessPrivate *priv = h->priv; + GstPad *sinkpad = gst_element_get_static_pad (h->element, + element_sinkpad_name); + GstPadLinkReturn link; + if (sinkpad == NULL) + sinkpad = gst_element_get_request_pad (h->element, element_sinkpad_name); + g_assert (sinkpad); + link = gst_pad_link (h->srcpad, sinkpad); + g_assert_cmpint (link, ==, GST_PAD_LINK_OK); + g_free (priv->element_sinkpad_name); + priv->element_sinkpad_name = gst_pad_get_name (sinkpad); + + gst_object_unref (sinkpad); +} + +static void +gst_harness_setup_src_pad (GstHarness * h, + GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name) +{ + GstHarnessPrivate *priv = h->priv; + g_assert (src_tmpl); + g_assert (h->srcpad == NULL); + + priv->src_event_queue = + g_async_queue_new_full ((GDestroyNotify) gst_event_unref); + + /* sending pad */ + h->srcpad = gst_pad_new_from_static_template (src_tmpl, "src"); + g_assert (h->srcpad); + g_object_set_data (G_OBJECT (h->srcpad), HARNESS_KEY, h); + + gst_pad_set_query_function (h->srcpad, gst_harness_src_query); + gst_pad_set_event_function (h->srcpad, gst_harness_src_event); + + gst_pad_set_active (h->srcpad, TRUE); + + if (element_sinkpad_name) + gst_harness_link_element_sinkpad (h, element_sinkpad_name); +} + +static void +gst_harness_setup_sink_pad (GstHarness * h, + GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name) +{ + GstHarnessPrivate *priv = h->priv; + g_assert (sink_tmpl); + g_assert (h->sinkpad == NULL); + + priv->buffer_queue = g_async_queue_new_full ( + (GDestroyNotify) gst_buffer_unref); + priv->sink_event_queue = g_async_queue_new_full ( + (GDestroyNotify) gst_event_unref); + + /* receiving pad */ + h->sinkpad = gst_pad_new_from_static_template (sink_tmpl, "sink"); + g_assert (h->sinkpad); + g_object_set_data (G_OBJECT (h->sinkpad), HARNESS_KEY, h); + + gst_pad_set_chain_function (h->sinkpad, gst_harness_chain); + gst_pad_set_query_function (h->sinkpad, gst_harness_sink_query); + gst_pad_set_event_function (h->sinkpad, gst_harness_sink_event); + + gst_pad_set_active (h->sinkpad, TRUE); + + if (element_srcpad_name) + gst_harness_link_element_srcpad (h, element_srcpad_name); +} + +static void +check_element_type (GstElement * element, gboolean * has_sinkpad, + gboolean * has_srcpad) +{ + GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element); + const GList *tmpl_list; + + *has_srcpad = element->numsrcpads > 0; + *has_sinkpad = element->numsinkpads > 0; + + tmpl_list = gst_element_class_get_pad_template_list (element_class); + + while (tmpl_list) { + GstPadTemplate *pad_tmpl = (GstPadTemplate *) tmpl_list->data; + tmpl_list = g_list_next (tmpl_list); + if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SRC) + *has_srcpad |= TRUE; + if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SINK) + *has_sinkpad |= TRUE; + } +} + +static void +turn_async_and_sync_off (GstElement * element) +{ + GObjectClass *class = G_OBJECT_GET_CLASS (element); + if (g_object_class_find_property (class, "async")) + g_object_set (element, "async", FALSE, NULL); + if (g_object_class_find_property (class, "sync")) + g_object_set (element, "sync", FALSE, NULL); +} + +static gboolean +gst_pad_is_request_pad (GstPad * pad) +{ + GstPadTemplate *temp; + gboolean is_request; + + if (pad == NULL) + return FALSE; + temp = gst_pad_get_pad_template (pad); + if (temp == NULL) + return FALSE; + is_request = GST_PAD_TEMPLATE_PRESENCE (temp) == GST_PAD_REQUEST; + gst_object_unref (temp); + return is_request; +} + +/** + * gst_harness_new_empty: (skip) + * + * Creates a new empty harness. Use gst_harness_add_element_full() to add + * an #GstElement to it. + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.8 + */ +GstHarness * +gst_harness_new_empty (void) +{ + GstHarness *h; + GstHarnessPrivate *priv; + + h = g_new0 (GstHarness, 1); + g_assert (h != NULL); + h->priv = g_new0 (GstHarnessPrivate, 1); + priv = h->priv; + + GST_DEBUG_OBJECT (h, "about to create new harness %p", h); + priv->last_push_ts = GST_CLOCK_TIME_NONE; + priv->latency_min = 0; + priv->latency_max = GST_CLOCK_TIME_NONE; + priv->drop_buffers = FALSE; + priv->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ()); + + priv->propose_allocator = NULL; + gst_allocation_params_init (&priv->propose_allocation_params); + + g_mutex_init (&priv->blocking_push_mutex); + g_cond_init (&priv->blocking_push_cond); + g_mutex_init (&priv->priv_mutex); + + priv->stress = g_ptr_array_new_with_free_func ( + (GDestroyNotify) gst_harness_stress_free); + + /* we have forwarding on as a default */ + gst_harness_set_forwarding (h, TRUE); + + return h; +} + +/** + * gst_harness_add_element_full: (skip) + * @h: a #GstHarness + * @element: a #GstElement to add to the harness (transfer none) + * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad. + * %NULL will not create a harness srcpad. + * @element_sinkpad_name: (allow-none): a #gchar with the name of the element + * sinkpad that is then linked to the harness srcpad. Can be a static or request + * or a sometimes pad that has been added. %NULL will not get/request a sinkpad + * from the element. (Like if the element is a src.) + * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad. + * %NULL will not create a harness sinkpad. + * @element_srcpad_name: (allow-none): a #gchar with the name of the element + * srcpad that is then linked to the harness sinkpad, similar to the + * @element_sinkpad_name. + * + * Adds a #GstElement to an empty #GstHarness + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_element_full (GstHarness * h, GstElement * element, + GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name, + GstStaticPadTemplate * hsink, const gchar * element_srcpad_name) +{ + GstClock *element_clock; + gboolean has_sinkpad, has_srcpad; + + g_return_if_fail (element != NULL); + g_return_if_fail (h->element == NULL); + + element_clock = GST_ELEMENT_CLOCK (element); + h->element = gst_object_ref (element); + check_element_type (element, &has_sinkpad, &has_srcpad); + + /* setup the loose srcpad linked to the element sinkpad */ + if (has_sinkpad) + gst_harness_setup_src_pad (h, hsrc, element_sinkpad_name); + + /* setup the loose sinkpad linked to the element srcpad */ + if (has_srcpad) + gst_harness_setup_sink_pad (h, hsink, element_srcpad_name); + + /* as a harness sink, we should not need sync and async */ + if (has_sinkpad && !has_srcpad) + turn_async_and_sync_off (h->element); + + if (h->srcpad != NULL) { + gboolean handled; + gchar *stream_id = g_strdup_printf ("%s-%p", + GST_OBJECT_NAME (h->element), h); + handled = gst_pad_push_event (h->srcpad, + gst_event_new_stream_start (stream_id)); + g_assert (handled); + g_free (stream_id); + } + + /* if the element already has a testclock attached, + we replace our own with it, if no clock we attach the testclock */ + if (element_clock) { + if (GST_IS_TEST_CLOCK (element_clock)) { + gst_object_replace ((GstObject **) & h->priv->testclock, + (GstObject *) GST_ELEMENT_CLOCK (element)); + } + } else { + gst_harness_use_testclock (h); + } + + /* don't start sources, they start producing data! */ + if (has_sinkpad) + gst_harness_play (h); + + gst_harness_element_ref (h); + + GST_DEBUG_OBJECT (h, "added element to harness %p " + "with element_srcpad_name (%p, %s, %s) and element_sinkpad_name (%p, %s, %s)", + h, h->srcpad, GST_DEBUG_PAD_NAME (h->srcpad), + h->sinkpad, GST_DEBUG_PAD_NAME (h->sinkpad)); +} + +/** + * gst_harness_new_full: (skip) + * @element: a #GstElement to attach the harness to (transfer none) + * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad. + * %NULL will not create a harness srcpad. + * @element_sinkpad_name: (allow-none): a #gchar with the name of the element + * sinkpad that is then linked to the harness srcpad. Can be a static or request + * or a sometimes pad that has been added. %NULL will not get/request a sinkpad + * from the element. (Like if the element is a src.) + * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad. + * %NULL will not create a harness sinkpad. + * @element_srcpad_name: (allow-none): a #gchar with the name of the element + * srcpad that is then linked to the harness sinkpad, similar to the + * @element_sinkpad_name. + * + * Creates a new harness. + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new_full (GstElement * element, + GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name, + GstStaticPadTemplate * hsink, const gchar * element_srcpad_name) +{ + GstHarness *h; + h = gst_harness_new_empty (); + gst_harness_add_element_full (h, element, + hsrc, element_sinkpad_name, hsink, element_srcpad_name); + return h; +} + +/** + * gst_harness_new_with_element: (skip) + * @element: a #GstElement to attach the harness to (transfer none) + * @element_sinkpad_name: (allow-none): a #gchar with the name of the element + * sinkpad that is then linked to the harness srcpad. %NULL does not attach a + * sinkpad + * @element_srcpad_name: (allow-none): a #gchar with the name of the element + * srcpad that is then linked to the harness sinkpad. %NULL does not attach a + * srcpad + * + * Creates a new harness. Works in the same way as gst_harness_new_full(), only + * that generic padtemplates are used for the harness src and sinkpads, which + * will be sufficient in most usecases. + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new_with_element (GstElement * element, + const gchar * element_sinkpad_name, const gchar * element_srcpad_name) +{ + return gst_harness_new_full (element, + &hsrctemplate, element_sinkpad_name, &hsinktemplate, element_srcpad_name); +} + +/** + * gst_harness_new_with_padnames: (skip) + * @element_name: a #gchar describing the #GstElement name + * @element_sinkpad_name: (allow-none): a #gchar with the name of the element + * sinkpad that is then linked to the harness srcpad. %NULL does not attach a + * sinkpad + * @element_srcpad_name: (allow-none): a #gchar with the name of the element + * srcpad that is then linked to the harness sinkpad. %NULL does not attach a + * srcpad + * + * Creates a new harness. Works like gst_harness_new_with_element(), + * except you specify the factoryname of the #GstElement + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new_with_padnames (const gchar * element_name, + const gchar * element_sinkpad_name, const gchar * element_srcpad_name) +{ + GstHarness *h; + GstElement *element = gst_element_factory_make (element_name, NULL); + g_assert (element != NULL); + + h = gst_harness_new_with_element (element, element_sinkpad_name, + element_srcpad_name); + gst_object_unref (element); + return h; +} + +/** + * gst_harness_new_with_templates: (skip) + * @element_name: a #gchar describing the #GstElement name + * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad. + * %NULL will not create a harness srcpad. + * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad. + * %NULL will not create a harness sinkpad. + * + * Creates a new harness, like gst_harness_new_full(), except it + * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new_with_templates (const gchar * element_name, + GstStaticPadTemplate * hsrc, GstStaticPadTemplate * hsink) +{ + GstHarness *h; + GstElement *element = gst_element_factory_make (element_name, NULL); + g_assert (element != NULL); + + h = gst_harness_new_full (element, hsrc, "sink", hsink, "src"); + gst_object_unref (element); + return h; +} + +/** + * gst_harness_new: (skip) + * @element_name: a #gchar describing the #GstElement name + * + * Creates a new harness. Works like gst_harness_new_with_padnames(), except it + * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new (const gchar * element_name) +{ + return gst_harness_new_with_padnames (element_name, "sink", "src"); +} + +/** + * gst_harness_add_parse: (skip) + * @h: a #GstHarness + * @launchline: a #gchar describing a gst-launch type line + * + * Parses the @launchline and puts that in a #GstBin, + * and then attches the supplied #GstHarness to the bin. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_parse (GstHarness * h, const gchar * launchline) +{ + GstBin *bin; + gchar *desc; + GstPad *pad; + GstIterator *iter; + gboolean done = FALSE; + GError *error = NULL; + + g_return_if_fail (launchline != NULL); + + desc = g_strdup_printf ("bin.( %s )", launchline); + bin = + (GstBin *) gst_parse_launch_full (desc, NULL, GST_PARSE_FLAG_FATAL_ERRORS, + &error); + + if (G_UNLIKELY (error != NULL)) { + g_error ("Unable to create pipeline '%s': %s", desc, error->message); + } + g_free (desc); + + /* find pads and ghost them if necessary */ + if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC)) != NULL) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); + gst_object_unref (pad); + } + if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK)) != NULL) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + } + + iter = gst_bin_iterate_sinks (bin); + while (!done) { + GValue item = { 0, }; + + switch (gst_iterator_next (iter, &item)) { + case GST_ITERATOR_OK: + turn_async_and_sync_off (GST_ELEMENT (g_value_get_object (&item))); + g_value_reset (&item); + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + gst_object_unref (bin); + gst_iterator_free (iter); + g_return_if_reached (); + break; + } + } + gst_iterator_free (iter); + + gst_harness_add_element_full (h, GST_ELEMENT_CAST (bin), + &hsrctemplate, "sink", &hsinktemplate, "src"); + gst_object_unref (bin); +} + +/** + * gst_harness_new_parse: (skip) + * @launchline: a #gchar describing a gst-launch type line + * + * Creates a new harness, parsing the @launchline and putting that in a #GstBin, + * and then attches the harness to the bin. + * + * MT safe. + * + * Returns: (transfer full): a #GstHarness, or %NULL if the harness could + * not be created + * + * Since: 1.6 + */ +GstHarness * +gst_harness_new_parse (const gchar * launchline) +{ + GstHarness *h; + h = gst_harness_new_empty (); + gst_harness_add_parse (h, launchline); + return h; +} + +/** + * gst_harness_teardown: + * @h: a #GstHarness + * + * Tears down a @GstHarness, freeing all resources allocated using it. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_teardown (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + + if (priv->blocking_push_mode) { + g_mutex_lock (&priv->blocking_push_mutex); + priv->blocking_push_mode = FALSE; + g_cond_signal (&priv->blocking_push_cond); + g_mutex_unlock (&priv->blocking_push_mutex); + } + + if (h->src_harness) { + gst_harness_teardown (h->src_harness); + } + + gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL); + if (h->sink_harness) { + gst_harness_teardown (h->sink_harness); + } + + if (priv->src_caps) + gst_caps_unref (priv->src_caps); + + if (priv->sink_caps) + gst_caps_unref (priv->sink_caps); + + if (h->srcpad) { + if (gst_pad_is_request_pad (GST_PAD_PEER (h->srcpad))) + gst_element_release_request_pad (h->element, GST_PAD_PEER (h->srcpad)); + g_free (priv->element_sinkpad_name); + + gst_pad_set_active (h->srcpad, FALSE); + gst_object_unref (h->srcpad); + + g_async_queue_unref (priv->src_event_queue); + } + + if (h->sinkpad) { + if (gst_pad_is_request_pad (GST_PAD_PEER (h->sinkpad))) + gst_element_release_request_pad (h->element, GST_PAD_PEER (h->sinkpad)); + g_free (priv->element_srcpad_name); + + gst_pad_set_active (h->sinkpad, FALSE); + gst_object_unref (h->sinkpad); + + g_async_queue_unref (priv->buffer_queue); + g_async_queue_unref (priv->sink_event_queue); + } + + gst_object_replace ((GstObject **) & priv->propose_allocator, NULL); + gst_object_replace ((GstObject **) & priv->allocator, NULL); + gst_object_replace ((GstObject **) & priv->pool, NULL); + + /* if we hold the last ref, set to NULL */ + if (gst_harness_element_unref (h) == 0) { + gboolean state_change; + GstState state, pending; + state_change = gst_element_set_state (h->element, GST_STATE_NULL); + g_assert (state_change == GST_STATE_CHANGE_SUCCESS); + state_change = gst_element_get_state (h->element, &state, &pending, 0); + g_assert (state_change == GST_STATE_CHANGE_SUCCESS); + g_assert (state == GST_STATE_NULL); + } + + g_cond_clear (&priv->blocking_push_cond); + g_mutex_clear (&priv->blocking_push_mutex); + g_mutex_clear (&priv->priv_mutex); + + g_ptr_array_unref (priv->stress); + + gst_object_unref (h->element); + + gst_object_replace ((GstObject **) & priv->testclock, NULL); + + g_free (h->priv); + g_free (h); +} + +/** + * gst_harness_add_element_src_pad: + * @h: a #GstHarness + * @srcpad: a #GstPad to link to the harness sinkpad + * + * Links the specifed #GstPad the @GstHarness sinkpad. This can be useful if + * perhaps the srcpad did not exist at the time of creating the harness, + * like a demuxer that provides a sometimes-pad after receiving data. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad) +{ + GstHarnessPrivate *priv = h->priv; + GstPadLinkReturn link; + if (h->sinkpad == NULL) + gst_harness_setup_sink_pad (h, &hsinktemplate, NULL); + link = gst_pad_link (srcpad, h->sinkpad); + g_assert_cmpint (link, ==, GST_PAD_LINK_OK); + g_free (priv->element_srcpad_name); + priv->element_srcpad_name = gst_pad_get_name (srcpad); +} + +/** + * gst_harness_add_element_sink_pad: + * @h: a #GstHarness + * @sinkpad: a #GstPad to link to the harness srcpad + * + * Links the specifed #GstPad the @GstHarness srcpad. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad) +{ + GstHarnessPrivate *priv = h->priv; + GstPadLinkReturn link; + if (h->srcpad == NULL) + gst_harness_setup_src_pad (h, &hsrctemplate, NULL); + link = gst_pad_link (h->srcpad, sinkpad); + g_assert_cmpint (link, ==, GST_PAD_LINK_OK); + g_free (priv->element_sinkpad_name); + priv->element_sinkpad_name = gst_pad_get_name (sinkpad); +} + +/** + * gst_harness_set_src_caps: + * @h: a #GstHarness + * @caps: (transfer full): a #GstCaps to set on the harness srcpad + * + * Sets the @GstHarness srcpad caps. This must be done before any buffers + * can legally be pushed from the harness to the element. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_src_caps (GstHarness * h, GstCaps * caps) +{ + GstHarnessPrivate *priv = h->priv; + GstSegment segment; + gboolean handled; + + handled = gst_pad_push_event (h->srcpad, gst_event_new_caps (caps)); + g_assert (handled); + gst_caps_take (&priv->src_caps, caps); + + gst_segment_init (&segment, GST_FORMAT_TIME); + handled = gst_pad_push_event (h->srcpad, gst_event_new_segment (&segment)); +} + +/** + * gst_harness_set_sink_caps: + * @h: a #GstHarness + * @caps: (transfer full): a #GstCaps to set on the harness sinkpad + * + * Sets the @GstHarness sinkpad caps. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps) +{ + GstHarnessPrivate *priv = h->priv; + + gst_caps_take (&priv->sink_caps, caps); + gst_pad_push_event (h->sinkpad, gst_event_new_reconfigure ()); +} + +/** + * gst_harness_set_caps: + * @h: a #GstHarness + * @in: (transfer full): a #GstCaps to set on the harness srcpad + * @out: (transfer full): a #GstCaps to set on the harness sinkpad + * + * Sets the @GstHarness srcpad and sinkpad caps. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out) +{ + gst_harness_set_sink_caps (h, out); + gst_harness_set_src_caps (h, in); +} + +/** + * gst_harness_set_src_caps_str: + * @h: a #GstHarness + * @str: a @gchar describing a #GstCaps to set on the harness srcpad + * + * Sets the @GstHarness srcpad caps using a string. This must be done before + * any buffers can legally be pushed from the harness to the element. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_src_caps_str (GstHarness * h, const gchar * str) +{ + gst_harness_set_src_caps (h, gst_caps_from_string (str)); +} + +/** + * gst_harness_set_sink_caps_str: + * @h: a #GstHarness + * @str: a @gchar describing a #GstCaps to set on the harness sinkpad + * + * Sets the @GstHarness sinkpad caps using a string. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str) +{ + gst_harness_set_sink_caps (h, gst_caps_from_string (str)); +} + +/** + * gst_harness_set_caps_str: + * @h: a #GstHarness + * @in: a @gchar describing a #GstCaps to set on the harness srcpad + * @out: a @gchar describing a #GstCaps to set on the harness sinkpad + * + * Sets the @GstHarness srcpad and sinkpad caps using strings. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_caps_str (GstHarness * h, const gchar * in, const gchar * out) +{ + gst_harness_set_sink_caps_str (h, out); + gst_harness_set_src_caps_str (h, in); +} + +/** + * gst_harness_use_systemclock: + * @h: a #GstHarness + * + * Sets the system #GstClock on the @GstHarness #GstElement + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_use_systemclock (GstHarness * h) +{ + GstClock *clock = gst_system_clock_obtain (); + g_assert (clock != NULL); + gst_element_set_clock (h->element, clock); + gst_object_unref (clock); +} + +/** + * gst_harness_use_testclock: + * @h: a #GstHarness + * + * Sets the #GstTestClock on the #GstHarness #GstElement + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_use_testclock (GstHarness * h) +{ + gst_element_set_clock (h->element, GST_CLOCK_CAST (h->priv->testclock)); +} + +/** + * gst_harness_get_testclock: + * @h: a #GstHarness + * + * Get the #GstTestClock. Useful if specific operations on the testclock is + * needed. + * + * MT safe. + * + * Returns: (transfer full): a #GstTestClock, or %NULL if the testclock is not + * present. + * + * Since: 1.6 + */ +GstTestClock * +gst_harness_get_testclock (GstHarness * h) +{ + return gst_object_ref (h->priv->testclock); +} + +/** + * gst_harness_set_time: + * @h: a #GstHarness + * @time: a #GstClockTime to advance the clock to + * + * Advance the #GstTestClock to a specific time. + * + * MT safe. + * + * Returns: a @gboolean %TRUE if the time could be set. %FALSE if not. + * + * Since: 1.6 + */ +gboolean +gst_harness_set_time (GstHarness * h, GstClockTime time) +{ + gst_test_clock_set_time (h->priv->testclock, time); + return TRUE; +} + +/** + * gst_harness_wait_for_clock_id_waits: + * @h: a #GstHarness + * @waits: a #guint describing the numbers of #GstClockID registered with + * the #GstTestClock + * @timeout: a #guint describing how many seconds to wait for @waits to be true + * + * Waits for @timeout seconds until @waits number of #GstClockID waits is + * registered with the #GstTestClock. Useful for writing deterministic tests, + * where you want to make sure that an expected number of waits have been + * reached. + * + * MT safe. + * + * Returns: a @gboolean %TRUE if the waits have been registered, %FALSE if not. + * (Could be that it timed out waiting or that more waits then waits was found) + * + * Since: 1.6 + */ +gboolean +gst_harness_wait_for_clock_id_waits (GstHarness * h, guint waits, guint timeout) +{ + GstTestClock *testclock = h->priv->testclock; + gint64 start_time; + gboolean ret; + + start_time = g_get_monotonic_time (); + while (gst_test_clock_peek_id_count (testclock) < waits) { + gint64 time_spent; + + g_usleep (G_USEC_PER_SEC / 1000); + time_spent = g_get_monotonic_time () - start_time; + if ((time_spent / G_USEC_PER_SEC) > timeout) + break; + } + + ret = (waits == gst_test_clock_peek_id_count (testclock)); + + return ret; +} + +/** + * gst_harness_crank_single_clock_wait: + * @h: a #GstHarness + * + * A "crank" consists of three steps: + * 1: Wait for a #GstClockID to be registered with the #GstTestClock. + * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for. + * 3: Release the #GstClockID wait. + * Together, this provides an easy way to not have to think about the details + * around clocks and time, but still being able to write deterministic tests + * that are dependant on this. A "crank" can be though of as the notion of + * manually driving the clock forward to its next logical step. + * + * MT safe. + * + * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not. + * + * Since: 1.6 + */ +gboolean +gst_harness_crank_single_clock_wait (GstHarness * h) +{ + return gst_test_clock_crank (h->priv->testclock); +} + +/** + * gst_harness_crank_multiple_clock_waits: + * @h: a #GstHarness + * @waits: a #guint describing the number of #GstClockIDs to crank + * + * Similar to gst_harness_crank_single_clock_wait(), this is the function to use + * if your harnessed element(s) are using more then one gst_clock_id_wait. + * Failing to do so can (and will) make it racy which #GstClockID you actually + * are releasing, where as this function will process all the waits at the + * same time, ensuring that one thread can't register another wait before + * both are released. + * + * MT safe. + * + * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not. + * + * Since: 1.6 + */ +gboolean +gst_harness_crank_multiple_clock_waits (GstHarness * h, guint waits) +{ + GstTestClock *testclock = h->priv->testclock; + GList *pending; + guint processed; + + gst_test_clock_wait_for_multiple_pending_ids (testclock, waits, &pending); + gst_harness_set_time (h, gst_test_clock_id_list_get_latest_time (pending)); + processed = gst_test_clock_process_id_list (testclock, pending); + + g_list_free_full (pending, gst_clock_id_unref); + return processed == waits; +} + +/** + * gst_harness_play: + * @h: a #GstHarness + * + * This will set the harnessed #GstElement to %GST_STATE_PLAYING. + * #GstElements without a sink-#GstPad and with the %GST_ELEMENT_FLAG_SOURCE + * flag set is concidered a src #GstElement + * Non-src #GstElements (like sinks and filters) are automatically set to + * playing by the #GstHarness, but src #GstElements are not to avoid them + * starting to produce buffers. + * Hence, for src #GstElement you must call gst_harness_play() explicitly. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_play (GstHarness * h) +{ + GstState state, pending; + gboolean state_change; + state_change = gst_element_set_state (h->element, GST_STATE_PLAYING); + g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change); + state_change = gst_element_get_state (h->element, &state, &pending, 0); + g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change); + g_assert_cmpint (GST_STATE_PLAYING, ==, state); +} + +/** + * gst_harness_set_blocking_push_mode: + * @h: a #GstHarness + * + * Setting this will make the harness block in the chain-function, and + * then release when gst_harness_pull() or gst_harness_try_pull() is called. + * Can be useful when wanting to control a src-element that is not implementing + * gst_clock_id_wait() so it can't be controlled by the #GstTestClock, since + * it otherwise would produce buffers as fast as possible. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_blocking_push_mode (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + priv->blocking_push_mode = TRUE; +} + +/** + * gst_harness_set_forwarding: + * @h: a #GstHarness + * @forwarding: a #gboolean to enable/disable forwarding + * + * As a convenience, a src-harness will forward %GST_EVENT_STREAM_START, + * %GST_EVENT_CAPS and %GST_EVENT_SEGMENT to the main-harness if forwarding + * is enabled, and forward any sticky-events from the main-harness to + * the sink-harness. It will also forward the %GST_QUERY_ALLOCATION. + * + * If forwarding is disabled, the user will have to either manually push + * these events from the src-harness using gst_harness_src_push_event(), or + * create and push them manually. While this will allow full control and + * inspection of these events, for the most cases having forwarding enabled + * will be sufficient when writing a test where the src-harness' main function + * is providing data for the main-harness. + * + * Forwarding is enabled by default. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_forwarding (GstHarness * h, gboolean forwarding) +{ + GstHarnessPrivate *priv = h->priv; + priv->forwarding = forwarding; + if (h->src_harness) + gst_harness_set_forwarding (h->src_harness, forwarding); + if (h->sink_harness) + gst_harness_set_forwarding (h->sink_harness, forwarding); +} + +static void +gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad) +{ + HARNESS_LOCK (h); + gst_object_replace ((GstObject **) & h->priv->sink_forward_pad, + (GstObject *) fwdpad); + HARNESS_UNLOCK (h); +} + +/** + * gst_harness_create_buffer: + * @h: a #GstHarness + * @size: a #gsize specifying the size of the buffer + * + * Allocates a buffer using a #GstBufferPool if present, or else using the + * configured #GstAllocator and #GstAllocationParams + * + * MT safe. + * + * Returns: a #GstBuffer of size @size + * + * Since: 1.6 + */ +GstBuffer * +gst_harness_create_buffer (GstHarness * h, gsize size) +{ + GstHarnessPrivate *priv = h->priv; + GstBuffer *ret = NULL; + GstFlowReturn flow; + + if (gst_pad_check_reconfigure (h->srcpad)) + gst_harness_negotiate (h); + + if (priv->pool) { + flow = gst_buffer_pool_acquire_buffer (priv->pool, &ret, NULL); + g_assert_cmpint (flow, ==, GST_FLOW_OK); + if (gst_buffer_get_size (ret) != size) { + GST_DEBUG_OBJECT (h, + "use fallback, pool is configured with a different size (%zu != %zu)", + size, gst_buffer_get_size (ret)); + gst_buffer_unref (ret); + ret = NULL; + } + } + + if (!ret) + ret = + gst_buffer_new_allocate (priv->allocator, size, + &priv->allocation_params); + + g_assert (ret != NULL); + return ret; +} + +/** + * gst_harness_push: + * @h: a #GstHarness + * @buffer: (transfer full): a #GstBuffer to push + * + * Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of + * interacting with an harnessed element. + * + * MT safe. + * + * Returns: a #GstFlowReturn with the result from the push + * + * Since: 1.6 + */ +GstFlowReturn +gst_harness_push (GstHarness * h, GstBuffer * buffer) +{ + GstHarnessPrivate *priv = h->priv; + g_assert (buffer != NULL); + priv->last_push_ts = GST_BUFFER_TIMESTAMP (buffer); + return gst_pad_push (h->srcpad, buffer); +} + +/** + * gst_harness_pull: + * @h: a #GstHarness + * + * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull + * will timeout in 60 seconds. This is the standard way of getting a buffer + * from a harnessed #GstElement. + * + * MT safe. + * + * Returns: (transfer full): a #GstBuffer or %NULL if timed out. + * + * Since: 1.6 + */ +GstBuffer * +gst_harness_pull (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + GstBuffer *buf = (GstBuffer *) g_async_queue_timeout_pop (priv->buffer_queue, + G_USEC_PER_SEC * 60); + + if (priv->blocking_push_mode) { + g_mutex_lock (&priv->blocking_push_mutex); + g_cond_signal (&priv->blocking_push_cond); + g_mutex_unlock (&priv->blocking_push_mutex); + } + + return buf; +} + +/** + * gst_harness_try_pull: + * @h: a #GstHarness + * + * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. Unlike + * gst_harness_pull this will not wait for any buffers if not any are present, + * and return %NULL straight away. + * + * MT safe. + * + * Returns: (transfer full): a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue + * + * Since: 1.6 + */ +GstBuffer * +gst_harness_try_pull (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + GstBuffer *buf = (GstBuffer *) g_async_queue_try_pop (priv->buffer_queue); + + if (priv->blocking_push_mode) { + g_mutex_lock (&priv->blocking_push_mutex); + g_cond_signal (&priv->blocking_push_cond); + g_mutex_unlock (&priv->blocking_push_mutex); + } + + return buf; +} + +/** + * gst_harness_push_and_pull: + * @h: a #GstHarness + * @buffer: (transfer full): a #GstBuffer to push + * + * Basically a gst_harness_push and a gst_harness_pull in one line. Reflects + * the fact that you often want to do exactly this in your test: Push one buffer + * in, and inspect the outcome. + * + * MT safe. + * + * Returns: (transfer full): a #GstBuffer or %NULL if timed out. + * + * Since: 1.6 + */ +GstBuffer * +gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer) +{ + gst_harness_push (h, buffer); + return gst_harness_pull (h); +} + +/** + * gst_harness_buffers_received: + * @h: a #GstHarness + * + * The total number of #GstBuffers that has arrived on the #GstHarness sinkpad. + * This number includes buffers that have been dropped as well as buffers + * that have already been pulled out. + * + * MT safe. + * + * Returns: a #guint number of buffers received + * + * Since: 1.6 + */ +guint +gst_harness_buffers_received (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_atomic_int_get (&priv->recv_buffers); +} + +/** + * gst_harness_buffers_in_queue: + * @h: a #GstHarness + * + * The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue + * + * MT safe. + * + * Returns: a #guint number of buffers in the queue + * + * Since: 1.6 + */ +guint +gst_harness_buffers_in_queue (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_async_queue_length (priv->buffer_queue); +} + +/** + * gst_harness_set_drop_buffers: + * @h: a #GstHarness + * @drop_buffers: a #gboolean specifying to drop outgoing buffers or not + * + * When set to %TRUE, instead of placing the buffers arriving from the harnessed + * #GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers) +{ + GstHarnessPrivate *priv = h->priv; + priv->drop_buffers = drop_buffers; +} + +/** + * gst_harness_take_all_data_as_buffer: + * @h: a #GstHarness + * + * Pulls all pending data from the harness and returns it as a single buffer. + * + * Returns: (transfer full): the data as a buffer. Unref with gst_buffer_unref() + * when no longer needed. + * + * Since: 1.14 + */ +GstBuffer * +gst_harness_take_all_data_as_buffer (GstHarness * h) +{ + GstHarnessPrivate *priv; + GstBuffer *ret, *buf; + + g_return_val_if_fail (h != NULL, NULL); + + priv = h->priv; + + g_async_queue_lock (priv->buffer_queue); + + ret = g_async_queue_try_pop_unlocked (priv->buffer_queue); + + if (ret == NULL) { + ret = gst_buffer_new (); + } else { + /* buffer appending isn't very efficient for larger numbers of buffers + * or lots of memories, but this function is not performance critical and + * we can still improve it if and when the need arises. For now KISS. */ + while ((buf = g_async_queue_try_pop_unlocked (priv->buffer_queue))) + ret = gst_buffer_append (ret, buf); + } + + g_async_queue_unlock (priv->buffer_queue); + + return ret; +} + +/** + * gst_harness_take_all_data: (skip) + * @h: a #GstHarness + * @size: (out): the size of the data in bytes + * + * Pulls all pending data from the harness and returns it as a single + * data slice. + * + * Returns: (transfer full): a pointer to the data, newly allocated. Free + * with g_free() when no longer needed. Will return %NULL if there is no + * data. + * + * Since: 1.14 + */ +guint8 * +gst_harness_take_all_data (GstHarness * h, gsize * size) +{ + GstBuffer *buf; + guint8 *data = NULL; + + g_return_val_if_fail (h != NULL, NULL); + g_return_val_if_fail (size != NULL, NULL); + + buf = gst_harness_take_all_data_as_buffer (h); + gst_buffer_extract_dup (buf, 0, -1, (gpointer *) & data, size); + gst_buffer_unref (buf); + return data; +} + +/** + * gst_harness_take_all_data_as_bytes: (rename-to gst_harness_take_all_data) + * @h: a #GstHarness + * + * Pulls all pending data from the harness and returns it as a single #GBytes. + * + * Returns: (transfer full): a pointer to the data, newly allocated. Free + * with g_free() when no longer needed. + * + * Since: 1.14 + */ +GBytes * +gst_harness_take_all_data_as_bytes (GstHarness * h) +{ + guint8 *data; + gsize size = 0; + + g_return_val_if_fail (h != NULL, NULL); + + data = gst_harness_take_all_data (h, &size); + return g_bytes_new_take (data, size); +} + + +/** + * gst_harness_dump_to_file: + * @h: a #GstHarness + * @filename: a #gchar with a the name of a file + * + * Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue + * to a file. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_dump_to_file (GstHarness * h, const gchar * filename) +{ + GError *err = NULL; + gpointer data; + gsize size; + + data = gst_harness_take_all_data (h, &size); + if (!g_file_set_contents (filename, data ? data : "", size, &err)) { + g_error ("GstHarness: Failed to write data to file: %s", err->message); + g_clear_error (&err); + } + g_free (data); +} + +/** + * gst_harness_get_last_pushed_timestamp: + * @h: a #GstHarness + * + * Get the timestamp of the last #GstBuffer pushed on the #GstHarness srcpad, + * typically with gst_harness_push or gst_harness_push_from_src. + * + * MT safe. + * + * Returns: a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no + * #GstBuffer has been pushed on the #GstHarness srcpad + * + * Since: 1.6 + */ +GstClockTime +gst_harness_get_last_pushed_timestamp (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return priv->last_push_ts; +} + +/** + * gst_harness_push_event: + * @h: a #GstHarness + * @event: a #GstEvent to push + * + * Pushes an #GstEvent on the #GstHarness srcpad. + * + * MT safe. + * + * Returns: a #gboolean with the result from the push + * + * Since: 1.6 + */ +gboolean +gst_harness_push_event (GstHarness * h, GstEvent * event) +{ + return gst_pad_push_event (h->srcpad, event); +} + +/** + * gst_harness_pull_event: + * @h: a #GstHarness + * + * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad. + * Timeouts after 60 seconds similar to gst_harness_pull. + * + * MT safe. + * + * Returns: a #GstEvent or %NULL if timed out. + * + * Since: 1.6 + */ +GstEvent * +gst_harness_pull_event (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return (GstEvent *) g_async_queue_timeout_pop (priv->sink_event_queue, + G_USEC_PER_SEC * 60); +} + +/** + * gst_harness_try_pull_event: + * @h: a #GstHarness + * + * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad. + * See gst_harness_try_pull for details. + * + * MT safe. + * + * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue + * + * Since: 1.6 + */ +GstEvent * +gst_harness_try_pull_event (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return (GstEvent *) g_async_queue_try_pop (priv->sink_event_queue); +} + +/** + * gst_harness_events_received: + * @h: a #GstHarness + * + * The total number of #GstEvents that has arrived on the #GstHarness sinkpad + * This number includes events handled by the harness as well as events + * that have already been pulled out. + * + * MT safe. + * + * Returns: a #guint number of events received + * + * Since: 1.6 + */ +guint +gst_harness_events_received (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_atomic_int_get (&priv->recv_events); +} + +/** + * gst_harness_events_in_queue: + * @h: a #GstHarness + * + * The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue + * + * MT safe. + * + * Returns: a #guint number of events in the queue + * + * Since: 1.6 + */ +guint +gst_harness_events_in_queue (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_async_queue_length (priv->sink_event_queue); +} + +/** + * gst_harness_push_upstream_event: + * @h: a #GstHarness + * @event: a #GstEvent to push + * + * Pushes an #GstEvent on the #GstHarness sinkpad. + * + * MT safe. + * + * Returns: a #gboolean with the result from the push + * + * Since: 1.6 + */ +gboolean +gst_harness_push_upstream_event (GstHarness * h, GstEvent * event) +{ + g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (GST_EVENT_IS_UPSTREAM (event), FALSE); + + return gst_pad_push_event (h->sinkpad, event); +} + +/** + * gst_harness_pull_upstream_event: + * @h: a #GstHarness + * + * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad. + * Timeouts after 60 seconds similar to gst_harness_pull. + * + * MT safe. + * + * Returns: a #GstEvent or %NULL if timed out. + * + * Since: 1.6 + */ +GstEvent * +gst_harness_pull_upstream_event (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return (GstEvent *) g_async_queue_timeout_pop (priv->src_event_queue, + G_USEC_PER_SEC * 60); +} + +/** + * gst_harness_try_pull_upstream_event: + * @h: a #GstHarness + * + * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad. + * See gst_harness_try_pull for details. + * + * MT safe. + * + * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue + * + * Since: 1.6 + */ +GstEvent * +gst_harness_try_pull_upstream_event (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return (GstEvent *) g_async_queue_try_pop (priv->src_event_queue); +} + +/** + * gst_harness_upstream_events_received: + * @h: a #GstHarness + * + * The total number of #GstEvents that has arrived on the #GstHarness srcpad + * This number includes events handled by the harness as well as events + * that have already been pulled out. + * + * MT safe. + * + * Returns: a #guint number of events received + * + * Since: 1.6 + */ +guint +gst_harness_upstream_events_received (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_atomic_int_get (&priv->recv_upstream_events); +} + +/** + * gst_harness_upstream_events_in_queue: + * @h: a #GstHarness + * + * The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue + * + * MT safe. + * + * Returns: a #guint number of events in the queue + * + * Since: 1.6 + */ +guint +gst_harness_upstream_events_in_queue (GstHarness * h) +{ + GstHarnessPrivate *priv = h->priv; + return g_async_queue_length (priv->src_event_queue); +} + +/** + * gst_harness_query_latency: + * @h: a #GstHarness + * + * Get the min latency reported by any harnessed #GstElement. + * + * MT safe. + * + * Returns: a #GstClockTime with min latency + * + * Since: 1.6 + */ +GstClockTime +gst_harness_query_latency (GstHarness * h) +{ + GstQuery *query; + gboolean is_live; + GstClockTime min = GST_CLOCK_TIME_NONE; + GstClockTime max; + + query = gst_query_new_latency (); + + if (gst_pad_peer_query (h->sinkpad, query)) { + gst_query_parse_latency (query, &is_live, &min, &max); + } + gst_query_unref (query); + + return min; +} + +/** + * gst_harness_set_upstream_latency: + * @h: a #GstHarness + * @latency: a #GstClockTime specifying the latency + * + * Sets the min latency reported by #GstHarness when receiving a latency-query + * + * Since: 1.6 + */ +void +gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency) +{ + GstHarnessPrivate *priv = h->priv; + priv->latency_min = latency; +} + +/** + * gst_harness_get_allocator: + * @h: a #GstHarness + * @allocator: (out) (allow-none) (transfer none): the #GstAllocator used + * @params: (out) (allow-none) (transfer full): the #GstAllocationParams of + * @allocator + * + * Gets the @allocator and its @params that has been decided to use after an + * allocation query. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_get_allocator (GstHarness * h, GstAllocator ** allocator, + GstAllocationParams * params) +{ + GstHarnessPrivate *priv = h->priv; + if (allocator) + *allocator = priv->allocator; + if (params) + *params = priv->allocation_params; +} + + +/** + * gst_harness_set_propose_allocator: + * @h: a #GstHarness + * @allocator: (allow-none) (transfer full): a #GstAllocator + * @params: (allow-none) (transfer none): a #GstAllocationParams + * + * Sets the @allocator and @params to propose when receiving an allocation + * query. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set_propose_allocator (GstHarness * h, GstAllocator * allocator, + const GstAllocationParams * params) +{ + GstHarnessPrivate *priv = h->priv; + if (allocator) + priv->propose_allocator = allocator; + if (params) + priv->propose_allocation_params = *params; +} + +/** + * gst_harness_add_src_harness: + * @h: a #GstHarness + * @src_harness: (transfer full): a #GstHarness to be added as a src-harness. + * @has_clock_wait: a #gboolean specifying if the #GstElement uses + * gst_clock_wait_id internally. + * + * A src-harness is a great way of providing the #GstHarness with data. + * By adding a src-type #GstElement, it is then easy to use functions like + * gst_harness_push_from_src or gst_harness_src_crank_and_push_many + * to provide your harnessed element with input. The @has_clock_wait variable + * is a greate way to control you src-element with, in that you can have it + * produce a buffer for you by simply cranking the clock, and not have it + * spin out of control producing buffers as fast as possible. + * + * If a src-harness already exists it will be replaced. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_src_harness (GstHarness * h, + GstHarness * src_harness, gboolean has_clock_wait) +{ + if (h->src_harness) + gst_harness_teardown (h->src_harness); + h->src_harness = src_harness; + gst_harness_set_forward_pad (h->src_harness, h->srcpad); + h->src_harness->priv->has_clock_wait = has_clock_wait; + gst_harness_set_forwarding (h->src_harness, h->priv->forwarding); +} + +/** + * gst_harness_add_src: + * @h: a #GstHarness + * @src_element_name: a #gchar with the name of a #GstElement + * @has_clock_wait: a #gboolean specifying if the #GstElement uses + * gst_clock_wait_id internally. + * + * Similar to gst_harness_add_src_harness, this is a convenience to + * directly create a src-harness using the @src_element_name name specified. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_src (GstHarness * h, + const gchar * src_element_name, gboolean has_clock_wait) +{ + GstHarness *src_harness = gst_harness_new (src_element_name); + gst_harness_add_src_harness (h, src_harness, has_clock_wait); +} + +/** + * gst_harness_add_src_parse: + * @h: a #GstHarness + * @launchline: a #gchar describing a gst-launch type line + * @has_clock_wait: a #gboolean specifying if the #GstElement uses + * gst_clock_wait_id internally. + * + * Similar to gst_harness_add_src, this allows you to specify a launch-line, + * which can be useful for both having more then one #GstElement acting as your + * src (Like a src producing raw buffers, and then an encoder, providing encoded + * data), but also by allowing you to set properties like "is-live" directly on + * the elements. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_src_parse (GstHarness * h, + const gchar * launchline, gboolean has_clock_wait) +{ + GstHarness *src_harness = gst_harness_new_parse (launchline); + gst_harness_add_src_harness (h, src_harness, has_clock_wait); +} + +/** + * gst_harness_push_from_src: + * @h: a #GstHarness + * + * Transfer data from the src-#GstHarness to the main-#GstHarness. It consists + * of 4 steps: + * 1: Make sure the src is started. (see: gst_harness_play) + * 2: Crank the clock (see: gst_harness_crank_single_clock_wait) + * 3: Pull a #GstBuffer from the src-#GstHarness (see: gst_harness_pull) + * 4: Push the same #GstBuffer into the main-#GstHarness (see: gst_harness_push) + * + * MT safe. + * + * Returns: a #GstFlowReturn with the result of the push + * + * Since: 1.6 + */ +GstFlowReturn +gst_harness_push_from_src (GstHarness * h) +{ + GstBuffer *buf; + gboolean crank; + + g_assert (h->src_harness); + + /* FIXME: this *is* the right time to start the src, + but maybe a flag so we don't keep telling it to play? */ + gst_harness_play (h->src_harness); + + if (h->src_harness->priv->has_clock_wait) { + crank = gst_harness_crank_single_clock_wait (h->src_harness); + g_assert (crank); + } + + buf = gst_harness_pull (h->src_harness); + g_assert (buf != NULL); + return gst_harness_push (h, buf); +} + +/** + * gst_harness_src_crank_and_push_many: + * @h: a #GstHarness + * @cranks: a #gint with the number of calls to gst_harness_crank_single_clock_wait + * @pushes: a #gint with the number of calls to gst_harness_push + * + * Transfer data from the src-#GstHarness to the main-#GstHarness. Similar to + * gst_harness_push_from_src, this variant allows you to specify how many cranks + * and how many pushes to perform. This can be useful for both moving a lot + * of data at the same time, as well as cases when one crank does not equal one + * buffer to push and v.v. + * + * MT safe. + * + * Returns: a #GstFlowReturn with the result of the push + * + * Since: 1.6 + */ +GstFlowReturn +gst_harness_src_crank_and_push_many (GstHarness * h, gint cranks, gint pushes) +{ + GstFlowReturn ret = GST_FLOW_OK; + gboolean crank; + int i; + + g_assert (h->src_harness); + gst_harness_play (h->src_harness); + + for (i = 0; i < cranks; i++) { + crank = gst_harness_crank_single_clock_wait (h->src_harness); + g_assert (crank); + } + + for (i = 0; i < pushes; i++) { + GstBuffer *buf; + buf = gst_harness_pull (h->src_harness); + g_assert (buf != NULL); + ret = gst_harness_push (h, buf); + if (ret != GST_FLOW_OK) + break; + } + + return ret; +} + +/** + * gst_harness_src_push_event: + * @h: a #GstHarness + * + * Similar to what gst_harness_src_push does with #GstBuffers, this transfers + * a #GstEvent from the src-#GstHarness to the main-#GstHarness. Note that + * some #GstEvents are being transferred automagically. Look at sink_forward_pad + * for details. + * + * MT safe. + * + * Returns: a #gboolean with the result of the push + * + * Since: 1.6 + */ +gboolean +gst_harness_src_push_event (GstHarness * h) +{ + return gst_harness_push_event (h, gst_harness_pull_event (h->src_harness)); +} + + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data) +{ + GstHarness *h = user_data; + return gst_pad_push_event (h->priv->sink_forward_pad, gst_event_ref (*ev)); +} + +/** + * gst_harness_add_sink_harness: + * @h: a #GstHarness + * @sink_harness: (transfer full): a #GstHarness to be added as a sink-harness. + * + * Similar to gst_harness_add_src, this allows you to send the data coming out + * of your harnessed #GstElement to a sink-element, allowing to test different + * responses the element output might create in sink elements. An example might + * be an existing sink providing some analytical data on the input it receives that + * can be useful to your testing. If the goal is to test a sink-element itself, + * this is better acheived using gst_harness_new directly on the sink. + * + * If a sink-harness already exists it will be replaced. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness) +{ + GstHarnessPrivate *priv = h->priv; + + if (h->sink_harness) { + gst_harness_set_forward_pad (h, NULL); + gst_harness_teardown (h->sink_harness); + } + h->sink_harness = sink_harness; + gst_harness_set_forward_pad (h, h->sink_harness->srcpad); + if (priv->forwarding && h->sinkpad) + gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, h); + gst_harness_set_forwarding (h->sink_harness, priv->forwarding); +} + +/** + * gst_harness_add_sink: + * @h: a #GstHarness + * @sink_element_name: a #gchar with the name of a #GstElement + * + * Similar to gst_harness_add_sink_harness, this is a convenience to + * directly create a sink-harness using the @sink_element_name name specified. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_sink (GstHarness * h, const gchar * sink_element_name) +{ + GstHarness *sink_harness = gst_harness_new (sink_element_name); + gst_harness_add_sink_harness (h, sink_harness); +} + +/** + * gst_harness_add_sink_parse: + * @h: a #GstHarness + * @launchline: a #gchar with the name of a #GstElement + * + * Similar to gst_harness_add_sink, this allows you to specify a launch-line + * instead of just an element name. See gst_harness_add_src_parse for details. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_sink_parse (GstHarness * h, const gchar * launchline) +{ + GstHarness *sink_harness = gst_harness_new_parse (launchline); + gst_harness_add_sink_harness (h, sink_harness); +} + +/** + * gst_harness_push_to_sink: + * @h: a #GstHarness + * + * Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness. + * See gst_harness_push_from_src for details. + * + * MT safe. + * + * Returns: a #GstFlowReturn with the result of the push + * + * Since: 1.6 + */ +GstFlowReturn +gst_harness_push_to_sink (GstHarness * h) +{ + GstBuffer *buf; + g_assert (h->sink_harness); + buf = gst_harness_pull (h); + g_assert (buf != NULL); + return gst_harness_push (h->sink_harness, buf); +} + +/** + * gst_harness_sink_push_many: + * @h: a #GstHarness + * @pushes: a #gint with the number of calls to gst_harness_push_to_sink + * + * Convenience that calls gst_harness_push_to_sink @pushes number of times. + * Will abort the pushing if any one push fails. + * + * MT safe. + * + * Returns: a #GstFlowReturn with the result of the push + * + * Since: 1.6 + */ +GstFlowReturn +gst_harness_sink_push_many (GstHarness * h, gint pushes) +{ + GstFlowReturn ret = GST_FLOW_OK; + int i; + g_assert (h->sink_harness); + for (i = 0; i < pushes; i++) { + ret = gst_harness_push_to_sink (h); + if (ret != GST_FLOW_OK) + break; + } + return ret; +} + +/** + * gst_harness_find_element: + * @h: a #GstHarness + * @element_name: a #gchar with a #GstElementFactory name + * + * Most useful in conjunction with gst_harness_new_parse, this will scan the + * #GstElements inside the #GstHarness, and check if any of them matches + * @element_name. Typical usecase being that you need to access one of the + * harnessed elements for properties and/or signals. + * + * MT safe. + * + * Returns: (transfer full) (allow-none): a #GstElement or %NULL if not found + * + * Since: 1.6 + */ +GstElement * +gst_harness_find_element (GstHarness * h, const gchar * element_name) +{ + gboolean done = FALSE; + GstIterator *iter; + GValue data = G_VALUE_INIT; + + iter = gst_bin_iterate_elements (GST_BIN (h->element)); + done = FALSE; + + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK: + { + GstElement *element = g_value_get_object (&data); + GstPluginFeature *feature = + GST_PLUGIN_FEATURE (gst_element_get_factory (element)); + if (!strcmp (element_name, gst_plugin_feature_get_name (feature))) { + gst_iterator_free (iter); + return element; + } + g_value_reset (&data); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (iter); + + return NULL; +} + +/** + * gst_harness_set: + * @h: a #GstHarness + * @element_name: a #gchar with a #GstElementFactory name + * @first_property_name: a #gchar with the first property name + * @...: value for the first property, followed optionally by more + * name/value pairs, followed by %NULL + * + * A convenience function to allows you to call g_object_set on a #GstElement + * that are residing inside the #GstHarness, by using normal g_object_set + * syntax. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_set (GstHarness * h, + const gchar * element_name, const gchar * first_property_name, ...) +{ + va_list var_args; + GstElement *element = gst_harness_find_element (h, element_name); + va_start (var_args, first_property_name); + g_object_set_valist (G_OBJECT (element), first_property_name, var_args); + va_end (var_args); + gst_object_unref (element); +} + +/** + * gst_harness_get: + * @h: a #GstHarness + * @element_name: a #gchar with a #GstElementFactory name + * @first_property_name: a #gchar with the first property name + * @...: return location for the first property, followed optionally by more + * name/return location pairs, followed by %NULL + * + * A convenience function to allows you to call g_object_get on a #GstElement + * that are residing inside the #GstHarness, by using normal g_object_get + * syntax. + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_get (GstHarness * h, + const gchar * element_name, const gchar * first_property_name, ...) +{ + va_list var_args; + GstElement *element = gst_harness_find_element (h, element_name); + va_start (var_args, first_property_name); + g_object_get_valist (G_OBJECT (element), first_property_name, var_args); + va_end (var_args); + gst_object_unref (element); +} + +/** + * gst_harness_add_probe: + * @h: a #GstHarness + * @element_name: a #gchar with a #GstElementFactory name + * @pad_name: a #gchar with the name of the pad to attach the probe to + * @mask: a #GstPadProbeType (see gst_pad_add_probe) + * @callback: a #GstPadProbeCallback (see gst_pad_add_probe) + * @user_data: a #gpointer (see gst_pad_add_probe) + * @destroy_data: a #GDestroyNotify (see gst_pad_add_probe) + * + * A convenience function to allows you to call gst_pad_add_probe on a + * #GstPad of a #GstElement that are residing inside the #GstHarness, + * by using normal gst_pad_add_probe syntax + * + * MT safe. + * + * Since: 1.6 + */ +void +gst_harness_add_probe (GstHarness * h, + const gchar * element_name, const gchar * pad_name, GstPadProbeType mask, + GstPadProbeCallback callback, gpointer user_data, + GDestroyNotify destroy_data) +{ + GstElement *element = gst_harness_find_element (h, element_name); + GstPad *pad = gst_element_get_static_pad (element, pad_name); + gst_pad_add_probe (pad, mask, callback, user_data, destroy_data); + gst_object_unref (pad); + gst_object_unref (element); +} + +/******************************************************************************/ +/* STRESS */ +/******************************************************************************/ +struct _GstHarnessThread +{ + GstHarness *h; + GThread *thread; + gboolean running; + + gulong sleep; + + GDestroyNotify freefunc; +}; + +typedef struct +{ + GstHarnessThread t; + + GFunc init; + GFunc callback; + gpointer data; +} GstHarnessCustomThread; + +typedef struct +{ + GstHarnessThread t; + + GstCaps *caps; + GstSegment segment; + GstHarnessPrepareBufferFunc func; + gpointer data; + GDestroyNotify notify; +} GstHarnessPushBufferThread; + +typedef struct +{ + GstHarnessThread t; + + GstHarnessPrepareEventFunc func; + gpointer data; + GDestroyNotify notify; +} GstHarnessPushEventThread; + +typedef struct +{ + GstHarnessThread t; + + gchar *name; + GValue value; +} GstHarnessPropThread; + +typedef struct +{ + GstHarnessThread t; + + GstPadTemplate *templ; + gchar *name; + GstCaps *caps; + gboolean release; + + GSList *pads; +} GstHarnessReqPadThread; + +static void +gst_harness_thread_init (GstHarnessThread * t, GDestroyNotify freefunc, + GstHarness * h, gulong sleep) +{ + t->freefunc = freefunc; + t->h = h; + t->sleep = sleep; + + g_ptr_array_add (h->priv->stress, t); +} + +static void +gst_harness_thread_free (GstHarnessThread * t) +{ + g_slice_free (GstHarnessThread, t); +} + +static void +gst_harness_custom_thread_free (GstHarnessCustomThread * t) +{ + g_slice_free (GstHarnessCustomThread, t); +} + +static void +gst_harness_push_buffer_thread_free (GstHarnessPushBufferThread * t) +{ + if (t != NULL) { + gst_caps_replace (&t->caps, NULL); + if (t->notify != NULL) + t->notify (t->data); + g_slice_free (GstHarnessPushBufferThread, t); + } +} + +static void +gst_harness_push_event_thread_free (GstHarnessPushEventThread * t) +{ + if (t != NULL) { + if (t->notify != NULL) + t->notify (t->data); + g_slice_free (GstHarnessPushEventThread, t); + } +} + +static void +gst_harness_property_thread_free (GstHarnessPropThread * t) +{ + if (t != NULL) { + g_free (t->name); + g_value_unset (&t->value); + g_slice_free (GstHarnessPropThread, t); + } +} + +static void +gst_harness_requestpad_release (GstPad * pad, GstElement * element) +{ + gst_element_release_request_pad (element, pad); + gst_object_unref (pad); +} + +static void +gst_harness_requestpad_release_pads (GstHarnessReqPadThread * rpt) +{ + g_slist_foreach (rpt->pads, (GFunc) gst_harness_requestpad_release, + rpt->t.h->element); + g_slist_free (rpt->pads); + rpt->pads = NULL; +} + +static void +gst_harness_requestpad_thread_free (GstHarnessReqPadThread * t) +{ + if (t != NULL) { + gst_object_replace ((GstObject **) & t->templ, NULL); + g_free (t->name); + gst_caps_replace (&t->caps, NULL); + + gst_harness_requestpad_release_pads (t); + g_slice_free (GstHarnessReqPadThread, t); + } +} + +#define GST_HARNESS_THREAD_START(ID, t) \ + (((GstHarnessThread *)t)->running = TRUE, \ + ((GstHarnessThread *)t)->thread = g_thread_new ( \ + "gst-harness-stress-"G_STRINGIFY(ID), \ + (GThreadFunc)gst_harness_stress_##ID##_func, t)) +#define GST_HARNESS_THREAD_END(t) \ + (t->running = FALSE, \ + GPOINTER_TO_UINT (g_thread_join (t->thread))) + +static void +gst_harness_stress_free (GstHarnessThread * t) +{ + if (t != NULL && t->freefunc != NULL) + t->freefunc (t); +} + +static gpointer +gst_harness_stress_custom_func (GstHarnessThread * t) +{ + GstHarnessCustomThread *ct = (GstHarnessCustomThread *) t; + guint count = 0; + + if (ct->init != NULL) + ct->init (ct, ct->data); + + while (t->running) { + ct->callback (ct, ct->data); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + + +static gpointer +gst_harness_stress_statechange_func (GstHarnessThread * t) +{ + guint count = 0; + + while (t->running) { + GstClock *clock = gst_element_get_clock (t->h->element); + GstIterator *it; + gboolean done = FALSE; + gboolean change; + + change = gst_element_set_state (t->h->element, GST_STATE_NULL); + g_assert (change == GST_STATE_CHANGE_SUCCESS); + g_thread_yield (); + + it = gst_element_iterate_sink_pads (t->h->element); + while (!done) { + GValue item = G_VALUE_INIT; + switch (gst_iterator_next (it, &item)) { + case GST_ITERATOR_OK: + { + GstPad *sinkpad = g_value_get_object (&item); + GstPad *srcpad = gst_pad_get_peer (sinkpad); + if (srcpad != NULL) { + gst_pad_unlink (srcpad, sinkpad); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + } + g_value_reset (&item); + break; + } + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + g_assert_not_reached (); + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + g_value_unset (&item); + } + gst_iterator_free (it); + + if (clock != NULL) { + gst_element_set_clock (t->h->element, clock); + gst_object_unref (clock); + } + change = gst_element_set_state (t->h->element, GST_STATE_PLAYING); + g_assert (change == GST_STATE_CHANGE_SUCCESS); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +static gpointer +gst_harness_stress_buffer_func (GstHarnessThread * t) +{ + GstHarnessPushBufferThread *pt = (GstHarnessPushBufferThread *) t; + guint count = 0; + gchar *sid; + gboolean handled; + + /* Push stream start, caps and segment events */ + sid = g_strdup_printf ("%s-%p", GST_OBJECT_NAME (t->h->element), t->h); + handled = gst_pad_push_event (t->h->srcpad, gst_event_new_stream_start (sid)); + g_assert (handled); + g_free (sid); + handled = gst_pad_push_event (t->h->srcpad, gst_event_new_caps (pt->caps)); + g_assert (handled); + handled = gst_pad_push_event (t->h->srcpad, + gst_event_new_segment (&pt->segment)); + g_assert (handled); + + while (t->running) { + gst_harness_push (t->h, pt->func (t->h, pt->data)); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +static gpointer +gst_harness_stress_event_func (GstHarnessThread * t) +{ + GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t; + guint count = 0; + + while (t->running) { + gst_harness_push_event (t->h, pet->func (t->h, pet->data)); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +static gpointer +gst_harness_stress_upstream_event_func (GstHarnessThread * t) +{ + GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t; + guint count = 0; + + while (t->running) { + gst_harness_push_upstream_event (t->h, pet->func (t->h, pet->data)); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +static gpointer +gst_harness_stress_property_func (GstHarnessThread * t) +{ + GstHarnessPropThread *pt = (GstHarnessPropThread *) t; + guint count = 0; + + while (t->running) { + GValue value = G_VALUE_INIT; + + g_object_set_property (G_OBJECT (t->h->element), pt->name, &pt->value); + + g_value_init (&value, G_VALUE_TYPE (&pt->value)); + g_object_get_property (G_OBJECT (t->h->element), pt->name, &value); + g_value_reset (&value); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +static gpointer +gst_harness_stress_requestpad_func (GstHarnessThread * t) +{ + GstHarnessReqPadThread *rpt = (GstHarnessReqPadThread *) t; + guint count = 0; + + while (t->running) { + GstPad *reqpad; + + if (rpt->release) + gst_harness_requestpad_release_pads (rpt); + + g_thread_yield (); + + reqpad = gst_element_request_pad (t->h->element, + rpt->templ, rpt->name, rpt->caps); + + g_assert (reqpad != NULL); + + rpt->pads = g_slist_prepend (rpt->pads, reqpad); + + count++; + g_usleep (t->sleep); + } + return GUINT_TO_POINTER (count); +} + +/** + * gst_harness_stress_thread_stop: + * @t: a #GstHarnessThread + * + * Stop the running #GstHarnessThread + * + * MT safe. + * + * Since: 1.6 + */ +guint +gst_harness_stress_thread_stop (GstHarnessThread * t) +{ + guint ret; + + g_return_val_if_fail (t != NULL, 0); + + ret = GST_HARNESS_THREAD_END (t); + g_ptr_array_remove (t->h->priv->stress, t); + return ret; +} + +/** + * gst_harness_stress_custom_start: (skip) + * @h: a #GstHarness + * @init: (allow-none): a #GFunc that is called initially and only once + * @callback: a #GFunc that is called as often as possible + * @data: a #gpointer with custom data to pass to the @callback function + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each call to the @callback + * + * Start a custom stress-thread that will call your @callback for every + * iteration allowing you to do something nasty. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_custom_start (GstHarness * h, + GFunc init, GFunc callback, gpointer data, gulong sleep) +{ + GstHarnessCustomThread *t = g_slice_new0 (GstHarnessCustomThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_custom_thread_free, h, sleep); + + t->init = init; + t->callback = callback; + t->data = data; + + GST_HARNESS_THREAD_START (custom, t); + return &t->t; +} + +/** + * gst_harness_stress_statechange_start_full: (skip) + * @h: a #GstHarness + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each state-change + * + * Change the state of your harnessed #GstElement from NULL to PLAYING and + * back again, only pausing for @sleep microseconds every time. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_statechange_start_full (GstHarness * h, gulong sleep) +{ + GstHarnessThread *t = g_slice_new0 (GstHarnessThread); + gst_harness_thread_init (t, + (GDestroyNotify) gst_harness_thread_free, h, sleep); + GST_HARNESS_THREAD_START (statechange, t); + return t; +} + +static GstBuffer * +gst_harness_ref_buffer (GstHarness * h, gpointer data) +{ + (void) h; + return gst_buffer_ref (GST_BUFFER_CAST (data)); +} + +static GstEvent * +gst_harness_ref_event (GstHarness * h, gpointer data) +{ + (void) h; + return gst_event_ref (GST_EVENT_CAST (data)); +} + +/** + * gst_harness_stress_push_buffer_start_full: (skip) + * @h: a #GstHarness + * @caps: a #GstCaps for the #GstBuffer + * @segment: a #GstSegment + * @buf: a #GstBuffer to push + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each call to gst_pad_push + * + * Push a #GstBuffer in intervals of @sleep microseconds. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_push_buffer_start_full (GstHarness * h, + GstCaps * caps, const GstSegment * segment, GstBuffer * buf, gulong sleep) +{ + return gst_harness_stress_push_buffer_with_cb_start_full (h, caps, segment, + gst_harness_ref_buffer, gst_buffer_ref (buf), + (GDestroyNotify) gst_buffer_unref, sleep); +} + +/** + * gst_harness_stress_push_buffer_with_cb_start_full: (skip) + * @h: a #GstHarness + * @caps: a #GstCaps for the #GstBuffer + * @segment: a #GstSegment + * @func: a #GstHarnessPrepareBufferFunc function called before every iteration + * to prepare / create a #GstBuffer for pushing + * @data: a #gpointer with data to the #GstHarnessPrepareBufferFunc function + * @notify: a #GDestroyNotify that is called when thread is stopped + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each call to gst_pad_push + * + * Push a #GstBuffer returned by @func in intervals of @sleep microseconds. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h, + GstCaps * caps, const GstSegment * segment, + GstHarnessPrepareBufferFunc func, gpointer data, GDestroyNotify notify, + gulong sleep) +{ + GstHarnessPushBufferThread *t = g_slice_new0 (GstHarnessPushBufferThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_push_buffer_thread_free, h, sleep); + + gst_caps_replace (&t->caps, caps); + t->segment = *segment; + t->func = func; + t->data = data; + t->notify = notify; + + GST_HARNESS_THREAD_START (buffer, t); + return &t->t; +} + +/** + * gst_harness_stress_push_event_start_full: (skip) + * @h: a #GstHarness + * @event: a #GstEvent to push + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each gst_event_push with @event + * + * Push the @event onto the harnessed #GstElement sinkpad in intervals of + * @sleep microseconds + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_push_event_start_full (GstHarness * h, + GstEvent * event, gulong sleep) +{ + return gst_harness_stress_push_event_with_cb_start_full (h, + gst_harness_ref_event, gst_event_ref (event), + (GDestroyNotify) gst_event_unref, sleep); +} + +/** + * gst_harness_stress_push_event_with_cb_start_full: (skip) + * @h: a #GstHarness + * @func: a #GstHarnessPrepareEventFunc function called before every iteration + * to prepare / create a #GstEvent for pushing + * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function + * @notify: a #GDestroyNotify that is called when thread is stopped + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each call to gst_pad_push + * + * Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad + * in intervals of @sleep microseconds. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.8 + */ +GstHarnessThread * +gst_harness_stress_push_event_with_cb_start_full (GstHarness * h, + GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify, + gulong sleep) +{ + GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep); + + t->func = func; + t->data = data; + t->notify = notify; + + GST_HARNESS_THREAD_START (event, t); + return &t->t; +} + +/** + * gst_harness_stress_push_upstream_event_start_full: (skip) + * @h: a #GstHarness + * @event: a #GstEvent to push + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each gst_event_push with @event + * + * Push the @event onto the harnessed #GstElement srcpad in intervals of + * @sleep microseconds. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_push_upstream_event_start_full (GstHarness * h, + GstEvent * event, gulong sleep) +{ + return gst_harness_stress_push_upstream_event_with_cb_start_full (h, + gst_harness_ref_event, gst_event_ref (event), + (GDestroyNotify) gst_event_unref, sleep); +} + +/** + * gst_harness_stress_push_upstream_event_with_cb_start_full: (skip) + * @h: a #GstHarness + * @func: a #GstHarnessPrepareEventFunc function called before every iteration + * to prepare / create a #GstEvent for pushing + * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function + * @notify: a #GDestroyNotify that is called when thread is stopped + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each call to gst_pad_push + * + * Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad + * in intervals of @sleep microseconds. + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.8 + */ +GstHarnessThread * +gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h, + GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify, + gulong sleep) +{ + GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep); + + t->func = func; + t->data = data; + t->notify = notify; + + GST_HARNESS_THREAD_START (upstream_event, t); + return &t->t; +} + +/** + * gst_harness_stress_property_start_full: (skip) + * @h: a #GstHarness + * @name: a #gchar specifying a property name + * @value: a #GValue to set the property to + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each g_object_set with @name and @value + * + * Call g_object_set with @name and @value in intervals of @sleep microseconds + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_property_start_full (GstHarness * h, + const gchar * name, const GValue * value, gulong sleep) +{ + GstHarnessPropThread *t = g_slice_new0 (GstHarnessPropThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_property_thread_free, h, sleep); + + t->name = g_strdup (name); + g_value_init (&t->value, G_VALUE_TYPE (value)); + g_value_copy (value, &t->value); + + GST_HARNESS_THREAD_START (property, t); + return &t->t; +} + +/** + * gst_harness_stress_requestpad_start_full: (skip) + * @h: a #GstHarness + * @templ: a #GstPadTemplate + * @name: a #gchar + * @caps: a #GstCaps + * @release: a #gboolean + * @sleep: a #gulong specifying how long to sleep in (microseconds) for + * each gst_element_request_pad + * + * Call gst_element_request_pad in intervals of @sleep microseconds + * + * MT safe. + * + * Returns: a #GstHarnessThread + * + * Since: 1.6 + */ +GstHarnessThread * +gst_harness_stress_requestpad_start_full (GstHarness * h, + GstPadTemplate * templ, const gchar * name, GstCaps * caps, + gboolean release, gulong sleep) +{ + GstHarnessReqPadThread *t = g_slice_new0 (GstHarnessReqPadThread); + gst_harness_thread_init (&t->t, + (GDestroyNotify) gst_harness_requestpad_thread_free, h, sleep); + + t->templ = gst_object_ref (templ); + t->name = g_strdup (name); + gst_caps_replace (&t->caps, caps); + t->release = release; + + GST_HARNESS_THREAD_START (requestpad, t); + return &t->t; +} diff --git a/libs/gst/check/gstharness.h b/libs/gst/check/gstharness.h new file mode 100644 index 0000000..5a81fe0 --- /dev/null +++ b/libs/gst/check/gstharness.h @@ -0,0 +1,463 @@ +/* GstHarness - A test-harness for GStreamer testing + * + * Copyright (C) 2012-2015 Pexip + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_HARNESS_H__ +#define __GST_HARNESS_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstHarnessThread: + * + * Opaque handle representing a GstHarness stress testing thread. + * + * Since: 1.6 + */ +typedef struct _GstHarnessThread GstHarnessThread; + +typedef struct _GstHarness GstHarness; +typedef struct _GstHarnessPrivate GstHarnessPrivate; + +/** + * GstHarness: + * @element: the element inside the harness + * @srcpad: the internal harness source pad + * @sinkpad: the internal harness sink pad + * @src_harness: the source (input) harness (if any) + * @sink_harness: the sink (output) harness (if any) + * + * Since: 1.6 + */ +struct _GstHarness { + GstElement * element; + + GstPad * srcpad; + GstPad * sinkpad; + + GstHarness * src_harness; + GstHarness * sink_harness; + + /*< private >*/ + GstHarnessPrivate * priv; +}; + +/* Harness creation */ + +GST_CHECK_API +GstHarness * gst_harness_new_empty (void); + +GST_CHECK_API +void gst_harness_add_element_full (GstHarness * h, + GstElement * element, + GstStaticPadTemplate * hsrc, + const gchar * element_sinkpad_name, + GstStaticPadTemplate * hsink, + const gchar * element_srcpad_name); + +GST_CHECK_API +GstHarness * gst_harness_new_full (GstElement * element, + GstStaticPadTemplate * hsrc, + const gchar * element_sinkpad_name, + GstStaticPadTemplate * hsink, + const gchar * element_srcpad_name); + +GST_CHECK_API +GstHarness * gst_harness_new_with_element (GstElement * element, + const gchar * element_sinkpad_name, + const gchar * element_srcpad_name); + +GST_CHECK_API +GstHarness * gst_harness_new_with_padnames (const gchar * element_name, + const gchar * element_sinkpad_name, + const gchar * element_srcpad_name); + +GST_CHECK_API +GstHarness * gst_harness_new_with_templates (const gchar * element_name, + GstStaticPadTemplate * hsrc, + GstStaticPadTemplate * hsink); + +GST_CHECK_API +GstHarness * gst_harness_new (const gchar * element_name); + +GST_CHECK_API +GstHarness * gst_harness_new_parse (const gchar * launchline); + +GST_CHECK_API +void gst_harness_add_parse (GstHarness * h, const gchar * launchline); + +GST_CHECK_API +void gst_harness_teardown (GstHarness * h); + +GST_CHECK_API +void gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad); + +GST_CHECK_API +void gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad); + +/* Caps Functions */ + +GST_CHECK_API +void gst_harness_set_src_caps (GstHarness * h, GstCaps * caps); + +GST_CHECK_API +void gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps); + +GST_CHECK_API +void gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out); + +GST_CHECK_API +void gst_harness_set_src_caps_str (GstHarness * h, const gchar * str); + +GST_CHECK_API +void gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str); + +GST_CHECK_API +void gst_harness_set_caps_str (GstHarness * h, + const gchar * in, + const gchar * out); + +/* Clock Functions */ + +GST_CHECK_API +void gst_harness_use_systemclock (GstHarness * h); + +GST_CHECK_API +void gst_harness_use_testclock (GstHarness * h); + +GST_CHECK_API +GstTestClock * gst_harness_get_testclock (GstHarness * h); + +GST_CHECK_API +gboolean gst_harness_set_time (GstHarness * h, GstClockTime time); + +GST_CHECK_API +gboolean gst_harness_wait_for_clock_id_waits (GstHarness * h, + guint waits, + guint timeout); + +GST_CHECK_API +gboolean gst_harness_crank_single_clock_wait (GstHarness * h); + +GST_CHECK_API +gboolean gst_harness_crank_multiple_clock_waits (GstHarness * h, + guint waits); + +/* misc */ + +GST_CHECK_API +void gst_harness_play (GstHarness * h); + +GST_CHECK_API +void gst_harness_set_blocking_push_mode (GstHarness * h); + +GST_CHECK_API +void gst_harness_set_forwarding (GstHarness * h, gboolean forwarding); + +/* buffers */ + +GST_CHECK_API +GstBuffer * gst_harness_create_buffer (GstHarness * h, gsize size); + +GST_CHECK_API +GstFlowReturn gst_harness_push (GstHarness * h, GstBuffer * buffer); + +GST_CHECK_API +GstBuffer * gst_harness_pull (GstHarness * h); + +GST_CHECK_API +GstBuffer * gst_harness_try_pull (GstHarness * h); + +GST_CHECK_API +GstBuffer * gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer); + +GST_CHECK_API +guint gst_harness_buffers_received (GstHarness * h); + +GST_CHECK_API +guint gst_harness_buffers_in_queue (GstHarness * h); + +GST_CHECK_API +void gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers); + +GST_CHECK_API +void gst_harness_dump_to_file (GstHarness * h, const gchar * filename); + +GST_CHECK_API +guint8 * gst_harness_take_all_data (GstHarness * h, gsize * size); + +GST_CHECK_API +GstBuffer * gst_harness_take_all_data_as_buffer (GstHarness * h); + +GST_CHECK_API +GBytes * gst_harness_take_all_data_as_bytes (GstHarness * h); + +GST_CHECK_API +GstClockTime gst_harness_get_last_pushed_timestamp (GstHarness * h); + +/* downstream events */ + +GST_CHECK_API +gboolean gst_harness_push_event (GstHarness * h, GstEvent * event); + +GST_CHECK_API +GstEvent * gst_harness_pull_event (GstHarness * h); + +GST_CHECK_API +GstEvent * gst_harness_try_pull_event (GstHarness * h); + +GST_CHECK_API +guint gst_harness_events_received (GstHarness * h); + +GST_CHECK_API +guint gst_harness_events_in_queue (GstHarness * h); + +/* upstream events */ + +GST_CHECK_API +gboolean gst_harness_push_upstream_event (GstHarness * h, GstEvent * event); + +GST_CHECK_API +GstEvent * gst_harness_pull_upstream_event (GstHarness * h); + +GST_CHECK_API +GstEvent * gst_harness_try_pull_upstream_event (GstHarness * h); + +GST_CHECK_API +guint gst_harness_upstream_events_received (GstHarness * h); + +GST_CHECK_API +guint gst_harness_upstream_events_in_queue (GstHarness * h); + +/* latency */ + +GST_CHECK_API +GstClockTime gst_harness_query_latency (GstHarness * h); + +GST_CHECK_API +void gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency); + +/* allocator and allocation params */ + +GST_CHECK_API +void gst_harness_set_propose_allocator (GstHarness * h, + GstAllocator * allocator, + const GstAllocationParams * params); + +GST_CHECK_API +void gst_harness_get_allocator (GstHarness * h, + GstAllocator ** allocator, + GstAllocationParams * params); + +/* src-harness */ + +GST_CHECK_API +void gst_harness_add_src_harness (GstHarness * h, + GstHarness * src_harness, + gboolean has_clock_wait); + +GST_CHECK_API +void gst_harness_add_src (GstHarness * h, + const gchar * src_element_name, + gboolean has_clock_wait); + +GST_CHECK_API +void gst_harness_add_src_parse (GstHarness * h, + const gchar * launchline, + gboolean has_clock_wait); + +GST_CHECK_API +GstFlowReturn gst_harness_push_from_src (GstHarness * h); + +GST_CHECK_API +GstFlowReturn gst_harness_src_crank_and_push_many (GstHarness * h, + gint cranks, + gint pushes); + +GST_CHECK_API +gboolean gst_harness_src_push_event (GstHarness * h); + +/* sink-harness */ + +GST_CHECK_API +void gst_harness_add_sink_harness (GstHarness * h, + GstHarness * sink_harness); + +GST_CHECK_API +void gst_harness_add_sink (GstHarness * h, + const gchar * sink_element_name); + +GST_CHECK_API +void gst_harness_add_sink_parse (GstHarness * h, + const gchar * launchline); + +GST_CHECK_API +GstFlowReturn gst_harness_push_to_sink (GstHarness * h); + +GST_CHECK_API +GstFlowReturn gst_harness_sink_push_many (GstHarness * h, gint pushes); + +/* convenience functions */ + +GST_CHECK_API +GstElement * gst_harness_find_element (GstHarness * h, + const gchar * element_name); + +GST_CHECK_API +void gst_harness_set (GstHarness * h, + const gchar * element_name, + const gchar * first_property_name, ...); + +GST_CHECK_API +void gst_harness_get (GstHarness * h, + const gchar * element_name, + const gchar * first_property_name, ...); + +GST_CHECK_API +void gst_harness_add_probe (GstHarness * h, + const gchar * element_name, + const gchar * pad_name, + GstPadProbeType mask, + GstPadProbeCallback callback, + gpointer user_data, + GDestroyNotify destroy_data); + +/* Stress */ + +GST_CHECK_API +guint gst_harness_stress_thread_stop (GstHarnessThread * t); + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_custom_start (GstHarness * h, + GFunc init, + GFunc callback, + gpointer data, + gulong sleep); + +#define gst_harness_stress_statechange_start(h) \ + gst_harness_stress_statechange_start_full (h, G_USEC_PER_SEC / 100) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_statechange_start_full (GstHarness * h, + gulong sleep); + +#define gst_harness_stress_push_buffer_start(h, c, s, b) \ + gst_harness_stress_push_buffer_start_full (h, c, s, b, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_buffer_start_full (GstHarness * h, + GstCaps * caps, + const GstSegment * segment, + GstBuffer * buf, + gulong sleep); + +/** + * GstHarnessPrepareBufferFunc: + * @h: a #GstHarness + * @data: user data + * + * Since: 1.6 + */ +typedef GstBuffer * (*GstHarnessPrepareBufferFunc) (GstHarness * h, gpointer data); + +#define gst_harness_stress_push_buffer_with_cb_start(h, c, s, f, d, n) \ + gst_harness_stress_push_buffer_with_cb_start_full (h, c, s, f, d, n, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h, + GstCaps * caps, + const GstSegment * segment, + GstHarnessPrepareBufferFunc func, + gpointer data, + GDestroyNotify notify, + gulong sleep); + +#define gst_harness_stress_push_event_start(h, e) \ + gst_harness_stress_push_event_start_full (h, e, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_event_start_full (GstHarness * h, + GstEvent * event, + gulong sleep); + +/** + * GstHarnessPrepareEventFunc: + * @h: a #GstHarness + * @data: user data + * + * Since: 1.8 + */ +typedef GstEvent * (*GstHarnessPrepareEventFunc) (GstHarness * h, gpointer data); + +#define gst_harness_stress_push_event_with_cb_start(h, f, d, n) \ + gst_harness_stress_push_event_with_cb_start_full (h, f, d, n, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_event_with_cb_start_full (GstHarness * h, + GstHarnessPrepareEventFunc func, + gpointer data, + GDestroyNotify notify, + gulong sleep); + +#define gst_harness_stress_send_upstream_event_start(h, e) \ + gst_harness_stress_push_upstream_event_start_full (h, e, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_upstream_event_start_full (GstHarness * h, + GstEvent * event, + gulong sleep); + +#define gst_harness_stress_send_upstream_event_with_cb_start(h, f, d, n) \ + gst_harness_stress_push_upstream_event_with_cb_start_full (h, f, d, n, 0) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h, + GstHarnessPrepareEventFunc func, + gpointer data, + GDestroyNotify notify, + gulong sleep); + + +#define gst_harness_stress_property_start(h, n, v) \ + gst_harness_stress_property_start_full (h, n, v, G_USEC_PER_SEC / 1000) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_property_start_full (GstHarness * h, + const gchar * name, + const GValue * value, + gulong sleep); + +#define gst_harness_stress_requestpad_start(h, t, n, c, r) \ + gst_harness_stress_requestpad_start_full (h, t, n, c, r, G_USEC_PER_SEC / 100) + +GST_CHECK_API +GstHarnessThread * gst_harness_stress_requestpad_start_full (GstHarness * h, + GstPadTemplate * templ, + const gchar * name, + GstCaps * caps, + gboolean release, + gulong sleep); + +G_END_DECLS + +#endif /* __GST_HARNESS_H__ */ diff --git a/libs/gst/check/gsttestclock.c b/libs/gst/check/gsttestclock.c new file mode 100644 index 0000000..14ac669 --- /dev/null +++ b/libs/gst/check/gsttestclock.c @@ -0,0 +1,1147 @@ +/* GstTestClock - A deterministic clock for GStreamer unit tests + * + * Copyright (C) 2008 Ole André Vadla Ravnås + * Copyright (C) 2012 Sebastian Rasmussen + * Copyright (C) 2012 Havard Graff + * Copyright (C) 2013 Haakon Sporsheim + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttestclock + * @title: GstTestClock + * @short_description: Controllable, deterministic clock for GStreamer unit tests + * @see_also: #GstSystemClock, #GstClock + * + * GstTestClock is an implementation of #GstClock which has different + * behaviour compared to #GstSystemClock. Time for #GstSystemClock advances + * according to the system time, while time for #GstTestClock changes only + * when gst_test_clock_set_time() or gst_test_clock_advance_time() are + * called. #GstTestClock provides unit tests with the possibility to + * precisely advance the time in a deterministic manner, independent of the + * system time or any other external factors. + * + * ## Advancing the time of a #GstTestClock + * + * |[ + * #include + * #include + * + * GstClock *clock; + * GstTestClock *test_clock; + * + * clock = gst_test_clock_new (); + * test_clock = GST_TEST_CLOCK (clock); + * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + * gst_test_clock_advance_time ( test_clock, 1 * GST_SECOND); + * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + * g_usleep (10 * G_USEC_PER_SEC); + * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + * gst_test_clock_set_time (test_clock, 42 * GST_SECOND); + * GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + * ... + * ]| + * + * #GstClock allows for setting up single shot or periodic clock notifications + * as well as waiting for these notifications synchronously (using + * gst_clock_id_wait()) or asynchronously (using gst_clock_id_wait_async() or + * gst_clock_id_wait_async()). This is used by many GStreamer elements, + * among them #GstBaseSrc and #GstBaseSink. + * + * #GstTestClock keeps track of these clock notifications. By calling + * gst_test_clock_wait_for_next_pending_id() or + * gst_test_clock_wait_for_multiple_pending_ids() a unit tests may wait for the + * next one or several clock notifications to be requested. Additionally unit + * tests may release blocked waits in a controlled fashion by calling + * gst_test_clock_process_next_clock_id(). This way a unit test can control the + * inaccuracy (jitter) of clock notifications, since the test can decide to + * release blocked waits when the clock time has advanced exactly to, or past, + * the requested clock notification time. + * + * There are also interfaces for determining if a notification belongs to a + * #GstTestClock or not, as well as getting the number of requested clock + * notifications so far. + * + * N.B.: When a unit test waits for a certain amount of clock notifications to + * be requested in gst_test_clock_wait_for_next_pending_id() or + * gst_test_clock_wait_for_multiple_pending_ids() then these functions may block + * for a long time. If they block forever then the expected clock notifications + * were never requested from #GstTestClock, and so the assumptions in the code + * of the unit test are wrong. The unit test case runner in gstcheck is + * expected to catch these cases either by the default test case timeout or the + * one set for the unit test by calling tcase_set_timeout\(\). + * + * The sample code below assumes that the element under test will delay a + * buffer pushed on the source pad by some latency until it arrives on the sink + * pad. Moreover it is assumed that the element will at some point call + * gst_clock_id_wait() to synchronously wait for a specific time. The first + * buffer sent will arrive exactly on time only delayed by the latency. The + * second buffer will arrive a little late (7ms) due to simulated jitter in the + * clock notification. + * + * ## Demonstration of how to work with clock notifications and #GstTestClock + * + * |[ + * #include + * #include + * #include + * + * GstClockTime latency; + * GstElement *element; + * GstPad *srcpad; + * GstClock *clock; + * GstTestClock *test_clock; + * GstBuffer buf; + * GstClockID pending_id; + * GstClockID processed_id; + * + * latency = 42 * GST_MSECOND; + * element = create_element (latency, ...); + * srcpad = get_source_pad (element); + * + * clock = gst_test_clock_new (); + * test_clock = GST_TEST_CLOCK (clock); + * gst_element_set_clock (element, clock); + * + * GST_INFO ("Set time, create and push the first buffer\n"); + * gst_test_clock_set_time (test_clock, 0); + * buf = create_test_buffer (gst_clock_get_time (clock), ...); + * gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK); + * + * GST_INFO ("Block until element is waiting for a clock notification\n"); + * gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + * GST_INFO ("Advance to the requested time of the clock notification\n"); + * gst_test_clock_advance_time (test_clock, latency); + * GST_INFO ("Release the next blocking wait and make sure it is the one from element\n"); + * processed_id = gst_test_clock_process_next_clock_id (test_clock); + * g_assert (processed_id == pending_id); + * g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK); + * gst_clock_id_unref (pending_id); + * gst_clock_id_unref (processed_id); + * + * GST_INFO ("Validate that element produced an output buffer and check its timestamp\n"); + * g_assert_cmpint (get_number_of_output_buffer (...), ==, 1); + * buf = get_buffer_pushed_by_element (element, ...); + * g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency); + * gst_buffer_unref (buf); + * GST_INFO ("Check that element does not wait for any clock notification\n"); + * g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL)); + * + * GST_INFO ("Set time, create and push the second buffer\n"); + * gst_test_clock_advance_time (test_clock, 10 * GST_SECOND); + * buf = create_test_buffer (gst_clock_get_time (clock), ...); + * gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK); + * + * GST_INFO ("Block until element is waiting for a new clock notification\n"); + * (gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + * GST_INFO ("Advance past 7ms beyond the requested time of the clock notification\n"); + * gst_test_clock_advance_time (test_clock, latency + 7 * GST_MSECOND); + * GST_INFO ("Release the next blocking wait and make sure it is the one from element\n"); + * processed_id = gst_test_clock_process_next_clock_id (test_clock); + * g_assert (processed_id == pending_id); + * g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK); + * gst_clock_id_unref (pending_id); + * gst_clock_id_unref (processed_id); + * + * GST_INFO ("Validate that element produced an output buffer and check its timestamp\n"); + * g_assert_cmpint (get_number_of_output_buffer (...), ==, 1); + * buf = get_buffer_pushed_by_element (element, ...); + * g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, + * 10 * GST_SECOND + latency + 7 * GST_MSECOND); + * gst_buffer_unref (buf); + * GST_INFO ("Check that element does not wait for any clock notification\n"); + * g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL)); + * ... + * ]| + * + * Since #GstTestClock is only supposed to be used in unit tests it calls + * g_assert(), g_assert_cmpint() or g_assert_cmpuint() to validate all function + * arguments. This will highlight any issues with the unit test code itself. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gsttestclock.h" + +enum +{ + PROP_0, + PROP_START_TIME, + PROP_CLOCK_TYPE +}; + +typedef struct _GstClockEntryContext GstClockEntryContext; + +struct _GstClockEntryContext +{ + GstClockEntry *clock_entry; + GstClockTimeDiff time_diff; +}; + +struct _GstTestClockPrivate +{ + GstClockType clock_type; + GstClockTime start_time; + GstClockTime internal_time; + GList *entry_contexts; + GCond entry_added_cond; + GCond entry_processed_cond; +}; + +#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC + +#define GST_TEST_CLOCK_GET_PRIVATE(obj) ((GST_TEST_CLOCK_CAST (obj))->priv) + +GST_DEBUG_CATEGORY_STATIC (test_clock_debug); +#define GST_CAT_TEST_CLOCK test_clock_debug + +#define _do_init \ +G_STMT_START { \ + GST_DEBUG_CATEGORY_INIT (test_clock_debug, "GST_TEST_CLOCK", \ + GST_DEBUG_BOLD, "Test clocks for unit tests"); \ +} G_STMT_END + +G_DEFINE_TYPE_WITH_CODE (GstTestClock, gst_test_clock, + GST_TYPE_CLOCK, _do_init); + +static GstObjectClass *parent_class = NULL; + +static void gst_test_clock_constructed (GObject * object); +static void gst_test_clock_dispose (GObject * object); +static void gst_test_clock_finalize (GObject * object); +static void gst_test_clock_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void gst_test_clock_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); + +static GstClockTime gst_test_clock_get_resolution (GstClock * clock); +static GstClockTime gst_test_clock_get_internal_time (GstClock * clock); +static GstClockReturn gst_test_clock_wait (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter); +static GstClockReturn gst_test_clock_wait_async (GstClock * clock, + GstClockEntry * entry); +static void gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry); + +static gboolean gst_test_clock_peek_next_pending_id_unlocked (GstTestClock * + test_clock, GstClockID * pending_id); +static guint gst_test_clock_peek_id_count_unlocked (GstTestClock * test_clock); + +static void gst_test_clock_add_entry (GstTestClock * test_clock, + GstClockEntry * entry, GstClockTimeDiff * jitter); +static void gst_test_clock_remove_entry (GstTestClock * test_clock, + GstClockEntry * entry); +static GstClockEntryContext *gst_test_clock_lookup_entry_context (GstTestClock * + test_clock, GstClockEntry * clock_entry); + +static gint gst_clock_entry_context_compare_func (gconstpointer a, + gconstpointer b); + +static void +gst_test_clock_class_init (GstTestClockClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstClockClass *gstclock_class = GST_CLOCK_CLASS (klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (GstTestClockPrivate)); + + gobject_class->constructed = GST_DEBUG_FUNCPTR (gst_test_clock_constructed); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_test_clock_dispose); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_test_clock_finalize); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_test_clock_get_property); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_test_clock_set_property); + + gstclock_class->get_resolution = + GST_DEBUG_FUNCPTR (gst_test_clock_get_resolution); + gstclock_class->get_internal_time = + GST_DEBUG_FUNCPTR (gst_test_clock_get_internal_time); + gstclock_class->wait = GST_DEBUG_FUNCPTR (gst_test_clock_wait); + gstclock_class->wait_async = GST_DEBUG_FUNCPTR (gst_test_clock_wait_async); + gstclock_class->unschedule = GST_DEBUG_FUNCPTR (gst_test_clock_unschedule); + + /** + * GstTestClock:start-time: + * + * When a #GstTestClock is constructed it will have a certain start time set. + * If the clock was created using gst_test_clock_new_with_start_time() then + * this property contains the value of the @start_time argument. If + * gst_test_clock_new() was called the clock started at time zero, and thus + * this property contains the value 0. + */ + pspec = g_param_spec_uint64 ("start-time", "Start Time", + "Start Time of the Clock", 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, PROP_START_TIME, pspec); + + g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE, + g_param_spec_enum ("clock-type", "Clock type", + "The kind of clock implementation to be reported by this clock", + GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + +} + +static void +gst_test_clock_init (GstTestClock * test_clock) +{ + GstTestClockPrivate *priv; + + test_clock->priv = G_TYPE_INSTANCE_GET_PRIVATE (test_clock, + GST_TYPE_TEST_CLOCK, GstTestClockPrivate); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + g_cond_init (&priv->entry_added_cond); + g_cond_init (&priv->entry_processed_cond); + priv->clock_type = DEFAULT_CLOCK_TYPE; + + GST_OBJECT_FLAG_SET (test_clock, + GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC | + GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC | + GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC | + GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC); +} + +static void +gst_test_clock_constructed (GObject * object) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (object); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + priv->internal_time = priv->start_time; + + G_OBJECT_CLASS (parent_class)->constructed (object); +} + +static void +gst_test_clock_dispose (GObject * object) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (object); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + while (priv->entry_contexts != NULL) { + GstClockEntryContext *ctx = priv->entry_contexts->data; + gst_test_clock_remove_entry (test_clock, ctx->clock_entry); + } + + GST_OBJECT_UNLOCK (test_clock); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_test_clock_finalize (GObject * object) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (object); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + g_cond_clear (&priv->entry_added_cond); + g_cond_clear (&priv->entry_processed_cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_test_clock_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (object); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + switch (property_id) { + case PROP_START_TIME: + g_value_set_uint64 (value, priv->start_time); + break; + case PROP_CLOCK_TYPE: + g_value_set_enum (value, priv->clock_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_clock_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (object); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + switch (property_id) { + case PROP_START_TIME: + priv->start_time = g_value_get_uint64 (value); + GST_CAT_TRACE_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "test clock start time initialized at %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->start_time)); + break; + case PROP_CLOCK_TYPE: + priv->clock_type = (GstClockType) g_value_get_enum (value); + GST_CAT_DEBUG (GST_CAT_TEST_CLOCK, "clock-type set to %d", + priv->clock_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static GstClockTime +gst_test_clock_get_resolution (GstClock * clock) +{ + (void) clock; + return 1; +} + +static GstClockTime +gst_test_clock_get_internal_time (GstClock * clock) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (clock); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GstClockTime result; + + GST_OBJECT_LOCK (test_clock); + + GST_CAT_TRACE_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "retrieving test clock time %" GST_TIME_FORMAT, + GST_TIME_ARGS (priv->internal_time)); + result = priv->internal_time; + + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +static GstClockReturn +gst_test_clock_wait (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (clock); + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "requesting synchronous clock notification at %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); + + if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED) + goto was_unscheduled; + + if (gst_test_clock_lookup_entry_context (test_clock, entry) == NULL) + gst_test_clock_add_entry (test_clock, entry, jitter); + + GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY; + + while (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_BUSY) + g_cond_wait (&priv->entry_processed_cond, GST_OBJECT_GET_LOCK (test_clock)); + + GST_OBJECT_UNLOCK (test_clock); + + return GST_CLOCK_ENTRY_STATUS (entry); + + /* ERRORS */ +was_unscheduled: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "entry was unscheduled"); + GST_OBJECT_UNLOCK (test_clock); + return GST_CLOCK_UNSCHEDULED; + } +} + +static GstClockReturn +gst_test_clock_wait_async (GstClock * clock, GstClockEntry * entry) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (clock); + + GST_OBJECT_LOCK (test_clock); + + if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED) + goto was_unscheduled; + + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "requesting asynchronous clock notification at %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); + + gst_test_clock_add_entry (test_clock, entry, NULL); + + GST_OBJECT_UNLOCK (test_clock); + + return GST_CLOCK_OK; + + /* ERRORS */ +was_unscheduled: + { + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "entry was unscheduled"); + GST_OBJECT_UNLOCK (test_clock); + return GST_CLOCK_UNSCHEDULED; + } +} + +static void +gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry) +{ + GstTestClock *test_clock = GST_TEST_CLOCK (clock); + + GST_OBJECT_LOCK (test_clock); + + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "unscheduling requested clock notification at %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry))); + + GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_UNSCHEDULED; + gst_test_clock_remove_entry (test_clock, entry); + + GST_OBJECT_UNLOCK (test_clock); +} + +static gboolean +gst_test_clock_peek_next_pending_id_unlocked (GstTestClock * test_clock, + GstClockID * pending_id) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GList *imminent_clock_id = g_list_first (priv->entry_contexts); + gboolean result = FALSE; + + if (imminent_clock_id != NULL) { + GstClockEntryContext *ctx = imminent_clock_id->data; + + if (pending_id != NULL) { + *pending_id = gst_clock_id_ref (ctx->clock_entry); + } + + result = TRUE; + } + + return result; +} + +static guint +gst_test_clock_peek_id_count_unlocked (GstTestClock * test_clock) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + return g_list_length (priv->entry_contexts); +} + +static void +gst_test_clock_add_entry (GstTestClock * test_clock, + GstClockEntry * entry, GstClockTimeDiff * jitter) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GstClockTime now; + GstClockEntryContext *ctx; + + now = gst_clock_adjust_unlocked (GST_CLOCK (test_clock), priv->internal_time); + + if (jitter != NULL) + *jitter = GST_CLOCK_DIFF (GST_CLOCK_ENTRY_TIME (entry), now); + + ctx = g_slice_new (GstClockEntryContext); + ctx->clock_entry = GST_CLOCK_ENTRY (gst_clock_id_ref (entry)); + ctx->time_diff = GST_CLOCK_DIFF (now, GST_CLOCK_ENTRY_TIME (entry)); + + priv->entry_contexts = g_list_insert_sorted (priv->entry_contexts, ctx, + gst_clock_entry_context_compare_func); + + g_cond_broadcast (&priv->entry_added_cond); +} + +static void +gst_test_clock_remove_entry (GstTestClock * test_clock, GstClockEntry * entry) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GstClockEntryContext *ctx; + + ctx = gst_test_clock_lookup_entry_context (test_clock, entry); + if (ctx != NULL) { + gst_clock_id_unref (ctx->clock_entry); + priv->entry_contexts = g_list_remove (priv->entry_contexts, ctx); + g_slice_free (GstClockEntryContext, ctx); + + g_cond_broadcast (&priv->entry_processed_cond); + } +} + +static GstClockEntryContext * +gst_test_clock_lookup_entry_context (GstTestClock * test_clock, + GstClockEntry * clock_entry) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GstClockEntryContext *result = NULL; + GList *cur; + + for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) { + GstClockEntryContext *ctx = cur->data; + + if (ctx->clock_entry == clock_entry) { + result = ctx; + break; + } + } + + return result; +} + +static gint +gst_clock_entry_context_compare_func (gconstpointer a, gconstpointer b) +{ + const GstClockEntryContext *ctx_a = a; + const GstClockEntryContext *ctx_b = b; + + return gst_clock_id_compare_func (ctx_a->clock_entry, ctx_b->clock_entry); +} + +static void +process_entry_context_unlocked (GstTestClock * test_clock, + GstClockEntryContext * ctx) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GstClockEntry *entry = ctx->clock_entry; + + if (ctx->time_diff >= 0) + GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK; + else + GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_EARLY; + + if (entry->func != NULL) { + GST_OBJECT_UNLOCK (test_clock); + entry->func (GST_CLOCK (test_clock), priv->internal_time, entry, + entry->user_data); + GST_OBJECT_LOCK (test_clock); + } + + gst_test_clock_remove_entry (test_clock, entry); + + if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_PERIODIC) { + GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry); + + if (entry->func != NULL) + gst_test_clock_add_entry (test_clock, entry, NULL); + } +} + +static GList * +gst_test_clock_get_pending_id_list_unlocked (GstTestClock * test_clock) +{ + GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + GQueue queue = G_QUEUE_INIT; + GList *cur; + + for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) { + GstClockEntryContext *ctx = cur->data; + + g_queue_push_tail (&queue, gst_clock_id_ref (ctx->clock_entry)); + } + + return queue.head; +} + +/** + * gst_test_clock_new: + * + * Creates a new test clock with its time set to zero. + * + * MT safe. + * + * Returns: (transfer full): a #GstTestClock cast to #GstClock. + * + * Since: 1.2 + */ +GstClock * +gst_test_clock_new (void) +{ + return gst_test_clock_new_with_start_time (0); +} + +/** + * gst_test_clock_new_with_start_time: + * @start_time: a #GstClockTime set to the desired start time of the clock. + * + * Creates a new test clock with its time set to the specified time. + * + * MT safe. + * + * Returns: (transfer full): a #GstTestClock cast to #GstClock. + * + * Since: 1.2 + */ +GstClock * +gst_test_clock_new_with_start_time (GstClockTime start_time) +{ + GstClock *clock; + + g_assert_cmpuint (start_time, !=, GST_CLOCK_TIME_NONE); + clock = g_object_new (GST_TYPE_TEST_CLOCK, "start-time", start_time, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (clock); + + return clock; +} + +/** + * gst_test_clock_set_time: + * @test_clock: a #GstTestClock of which to set the time + * @new_time: a #GstClockTime later than that returned by gst_clock_get_time() + * + * Sets the time of @test_clock to the time given by @new_time. The time of + * @test_clock is monotonically increasing, therefore providing a @new_time + * which is earlier or equal to the time of the clock as given by + * gst_clock_get_time() is a programming error. + * + * MT safe. + * + * Since: 1.2 + */ +void +gst_test_clock_set_time (GstTestClock * test_clock, GstClockTime new_time) +{ + GstTestClockPrivate *priv; + + g_return_if_fail (GST_IS_TEST_CLOCK (test_clock)); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + g_assert_cmpuint (new_time, !=, GST_CLOCK_TIME_NONE); + + GST_OBJECT_LOCK (test_clock); + + g_assert_cmpuint (new_time, >=, priv->internal_time); + + priv->internal_time = new_time; + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "clock set to %" GST_TIME_FORMAT, GST_TIME_ARGS (new_time)); + + GST_OBJECT_UNLOCK (test_clock); +} + +/** + * gst_test_clock_advance_time: + * @test_clock: a #GstTestClock for which to increase the time + * @delta: a positive #GstClockTimeDiff to be added to the time of the clock + * + * Advances the time of the @test_clock by the amount given by @delta. The + * time of @test_clock is monotonically increasing, therefore providing a + * @delta which is negative or zero is a programming error. + * + * MT safe. + * + * Since: 1.2 + */ +void +gst_test_clock_advance_time (GstTestClock * test_clock, GstClockTimeDiff delta) +{ + GstTestClockPrivate *priv; + + g_return_if_fail (GST_IS_TEST_CLOCK (test_clock)); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + g_assert_cmpint (delta, >=, 0); + g_assert_cmpuint (delta, <, G_MAXUINT64 - delta); + + GST_OBJECT_LOCK (test_clock); + + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "advancing clock by %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + GST_TIME_ARGS (delta), GST_TIME_ARGS (priv->internal_time + delta)); + priv->internal_time += delta; + + GST_OBJECT_UNLOCK (test_clock); +} + +/** + * gst_test_clock_peek_id_count: + * @test_clock: a #GstTestClock for which to count notifications + * + * Determine the number of pending clock notifications that have been + * requested from the @test_clock. + * + * MT safe. + * + * Returns: the number of pending clock notifications. + * + * Since: 1.2 + */ +guint +gst_test_clock_peek_id_count (GstTestClock * test_clock) +{ + guint result; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0); + + GST_OBJECT_LOCK (test_clock); + result = gst_test_clock_peek_id_count_unlocked (test_clock); + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_has_id: + * @test_clock: a #GstTestClock to ask if it provided the notification + * @id: (transfer none): a #GstClockID clock notification + * + * Checks whether @test_clock was requested to provide the clock notification + * given by @id. + * + * MT safe. + * + * Returns: %TRUE if the clock has been asked to provide the given clock + * notification, %FALSE otherwise. + * + * Since: 1.2 + */ +gboolean +gst_test_clock_has_id (GstTestClock * test_clock, GstClockID id) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE); + g_assert (id != NULL); + + GST_OBJECT_LOCK (test_clock); + result = gst_test_clock_lookup_entry_context (test_clock, id) != NULL; + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_peek_next_pending_id: + * @test_clock: a #GstTestClock to check the clock notifications for + * @pending_id: (allow-none) (out) (transfer full): a #GstClockID clock + * notification to look for + * + * Determines if the @pending_id is the next clock notification scheduled to + * be triggered given the current time of the @test_clock. + * + * MT safe. + * + * Return: %TRUE if @pending_id is the next clock notification to be + * triggered, %FALSE otherwise. + * + * Since: 1.2 + */ +gboolean +gst_test_clock_peek_next_pending_id (GstTestClock * test_clock, + GstClockID * pending_id) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), FALSE); + + GST_OBJECT_LOCK (test_clock); + result = gst_test_clock_peek_next_pending_id_unlocked (test_clock, + pending_id); + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_wait_for_next_pending_id: + * @test_clock: #GstTestClock for which to get the pending clock notification + * @pending_id: (allow-none) (out) (transfer full): #GstClockID + * with information about the pending clock notification + * + * Waits until a clock notification is requested from @test_clock. There is no + * timeout for this wait, see the main description of #GstTestClock. A reference + * to the pending clock notification is stored in @pending_id. + * + * MT safe. + * + * Since: 1.2 + */ +void +gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock, + GstClockID * pending_id) +{ + GstTestClockPrivate *priv; + + g_return_if_fail (GST_IS_TEST_CLOCK (test_clock)); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + while (priv->entry_contexts == NULL) + g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock)); + + if (!gst_test_clock_peek_next_pending_id_unlocked (test_clock, pending_id)) + g_assert_not_reached (); + + GST_OBJECT_UNLOCK (test_clock); +} + +/** + * gst_test_clock_wait_for_pending_id_count: + * @test_clock: #GstTestClock for which to await having enough pending clock + * @count: the number of pending clock notifications to wait for + * + * Blocks until at least @count clock notifications have been requested from + * @test_clock. There is no timeout for this wait, see the main description of + * #GstTestClock. + * + * Since: 1.2 + * + * Deprecated: use gst_test_clock_wait_for_multiple_pending_ids() instead. + */ +#ifndef GST_REMOVE_DEPRECATED +void +gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock, + guint count) +{ + gst_test_clock_wait_for_multiple_pending_ids (test_clock, count, NULL); +} +#endif + +/** + * gst_test_clock_process_next_clock_id: + * @test_clock: a #GstTestClock for which to retrieve the next pending clock + * notification + * + * MT safe. + * + * Returns: (transfer full): a #GstClockID containing the next pending clock + * notification. + * + * Since: 1.2 + */ +GstClockID +gst_test_clock_process_next_clock_id (GstTestClock * test_clock) +{ + GstTestClockPrivate *priv; + GstClockID result = NULL; + GstClockEntryContext *ctx = NULL; + GList *cur; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), NULL); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + for (cur = priv->entry_contexts; cur != NULL && result == NULL; + cur = cur->next) { + ctx = cur->data; + + if (priv->internal_time >= GST_CLOCK_ENTRY_TIME (ctx->clock_entry)) + result = gst_clock_id_ref (ctx->clock_entry); + } + + if (result != NULL) + process_entry_context_unlocked (test_clock, ctx); + + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_get_next_entry_time: + * @test_clock: a #GstTestClock to fetch the next clock notification time for + * + * Retrieve the requested time for the next pending clock notification. + * + * MT safe. + * + * Returns: a #GstClockTime set to the time of the next pending clock + * notification. If no clock notifications have been requested + * %GST_CLOCK_TIME_NONE will be returned. + * + * Since: 1.2 + */ +GstClockTime +gst_test_clock_get_next_entry_time (GstTestClock * test_clock) +{ + GstTestClockPrivate *priv; + GstClockTime result = GST_CLOCK_TIME_NONE; + GList *imminent_clock_id; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), GST_CLOCK_TIME_NONE); + + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + /* The list of pending clock notifications is sorted by time, + so the most imminent one is the first one in the list. */ + imminent_clock_id = g_list_first (priv->entry_contexts); + if (imminent_clock_id != NULL) { + GstClockEntryContext *ctx = imminent_clock_id->data; + result = GST_CLOCK_ENTRY_TIME (ctx->clock_entry); + } + + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_wait_for_multiple_pending_ids: + * @test_clock: #GstTestClock for which to await having enough pending clock + * @count: the number of pending clock notifications to wait for + * @pending_list: (out) (element-type Gst.ClockID) (transfer full) (allow-none): Address + * of a #GList pointer variable to store the list of pending #GstClockIDs + * that expired, or %NULL + * + * Blocks until at least @count clock notifications have been requested from + * @test_clock. There is no timeout for this wait, see the main description of + * #GstTestClock. + * + * MT safe. + * + * Since: 1.4 + */ +void +gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock, + guint count, GList ** pending_list) +{ + GstTestClockPrivate *priv; + + g_return_if_fail (GST_IS_TEST_CLOCK (test_clock)); + priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock); + + GST_OBJECT_LOCK (test_clock); + + while (g_list_length (priv->entry_contexts) < count) + g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock)); + + if (pending_list) + *pending_list = gst_test_clock_get_pending_id_list_unlocked (test_clock); + + GST_OBJECT_UNLOCK (test_clock); +} + +/** + * gst_test_clock_process_id_list: + * @test_clock: #GstTestClock for which to process the pending IDs + * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List + * of pending #GstClockIDs + * + * Processes and releases the pending IDs in the list. + * + * MT safe. + * + * Since: 1.4 + */ +guint +gst_test_clock_process_id_list (GstTestClock * test_clock, + const GList * pending_list) +{ + const GList *cur; + guint result = 0; + + g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0); + + GST_OBJECT_LOCK (test_clock); + + for (cur = pending_list; cur != NULL; cur = cur->next) { + GstClockID pending_id = cur->data; + GstClockEntryContext *ctx = + gst_test_clock_lookup_entry_context (test_clock, pending_id); + if (ctx) { + process_entry_context_unlocked (test_clock, ctx); + result++; + } + } + GST_OBJECT_UNLOCK (test_clock); + + return result; +} + +/** + * gst_test_clock_id_list_get_latest_time: + * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List + * of of pending #GstClockIDs + * + * Finds the latest time inside the list. + * + * MT safe. + * + * Since: 1.4 + */ +GstClockTime +gst_test_clock_id_list_get_latest_time (const GList * pending_list) +{ + const GList *cur; + GstClockTime result = 0; + + for (cur = pending_list; cur != NULL; cur = cur->next) { + GstClockID *pending_id = cur->data; + GstClockTime time = gst_clock_id_get_time (pending_id); + if (time > result) + result = time; + } + + return result; +} + +/** + * gst_test_clock_crank: + * @test_clock: #GstTestClock to crank + * + * A "crank" consists of three steps: + * 1: Wait for a #GstClockID to be registered with the #GstTestClock. + * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for. + * 3: Release the #GstClockID wait. + * A "crank" can be though of as the notion of + * manually driving the clock forward to its next logical step. + * + * Return: %TRUE if the crank was successful, %FALSE otherwise. + * + * MT safe. + * + * Since: 1.8 + */ +gboolean +gst_test_clock_crank (GstTestClock * test_clock) +{ + GstClockID res, pending; + gboolean result; + + gst_test_clock_wait_for_next_pending_id (test_clock, &pending); + gst_test_clock_set_time (test_clock, gst_clock_id_get_time (pending)); + res = gst_test_clock_process_next_clock_id (test_clock); + if (G_LIKELY (res == pending)) { + GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "cranked to time %" GST_TIME_FORMAT, + GST_TIME_ARGS (gst_clock_get_time (GST_CLOCK (test_clock)))); + result = TRUE; + } else { + GST_CAT_WARNING_OBJECT (GST_CAT_TEST_CLOCK, test_clock, + "testclock next id != pending (%p != %p)", res, pending); + result = FALSE; + } + + if (G_LIKELY (res != NULL)) + gst_clock_id_unref (res); + + gst_clock_id_unref (pending); + + return result; +} diff --git a/libs/gst/check/gsttestclock.h b/libs/gst/check/gsttestclock.h new file mode 100644 index 0000000..ac2219f --- /dev/null +++ b/libs/gst/check/gsttestclock.h @@ -0,0 +1,140 @@ +/* GstTestClock - A deterministic clock for GStreamer unit tests + * + * Copyright (C) 2008 Ole André Vadla Ravnås + * Copyright (C) 2012 Sebastian Rasmussen + * Copyright (C) 2012 Havard Graff + * Copyright (C) 2013 Haakon Sporsheim + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_TEST_CLOCK_H__ +#define __GST_TEST_CLOCK_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TEST_CLOCK (gst_test_clock_get_type ()) +#define GST_TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ + GST_TYPE_TEST_CLOCK, GstTestClock)) +#define GST_IS_TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ + GST_TYPE_TEST_CLOCK)) +#define GST_TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ + GST_TYPE_TEST_CLOCK, GstTestClockClass)) +#define GST_IS_TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE (\ + (klass), GST_TYPE_TEST_CLOCK)) +#define GST_TEST_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS (\ + (obj), GST_TYPE_TEST_CLOCK, GstTestClockClass)) +#define GST_TEST_CLOCK_CAST(obj) ((GstTestClock*)(obj)) + +typedef struct _GstTestClock GstTestClock; +typedef struct _GstTestClockClass GstTestClockClass; +typedef struct _GstTestClockPrivate GstTestClockPrivate; + +/** + * GstTestClock: + * + * A #GstTestClock structure which is based on a #GstClock along with some + * private data. + * + * Since: 1.2 + */ +struct _GstTestClock +{ + GstClock parent; + + /*< private >*/ + GstTestClockPrivate *priv; +}; + +/** + * GstTestClockClass: + * @parent_class: the parent class structure + * + * The class of a #GstTestClock, which has no virtual methods to override. + * + * Since: 1.2 + */ +struct _GstTestClockClass +{ + GstClockClass parent_class; +}; + +GST_CHECK_API +GType gst_test_clock_get_type (void); + +GST_CHECK_API +GstClock * gst_test_clock_new (void); + +GST_CHECK_API +GstClock * gst_test_clock_new_with_start_time (GstClockTime start_time); + +GST_CHECK_API +void gst_test_clock_set_time (GstTestClock * test_clock, + GstClockTime new_time); + +GST_CHECK_API +void gst_test_clock_advance_time (GstTestClock * test_clock, + GstClockTimeDiff delta); + +GST_CHECK_API +guint gst_test_clock_peek_id_count (GstTestClock * test_clock); + +GST_CHECK_API +gboolean gst_test_clock_has_id (GstTestClock * test_clock, GstClockID id); + +GST_CHECK_API +gboolean gst_test_clock_peek_next_pending_id (GstTestClock * test_clock, + GstClockID * pending_id); + +GST_CHECK_API +void gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock, + GstClockID * pending_id); + +GST_DEPRECATED_FOR(gst_test_clock_wait_for_multiple_pending_ids) +void gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock, + guint count); + +GST_CHECK_API +GstClockID gst_test_clock_process_next_clock_id (GstTestClock * test_clock); + +GST_CHECK_API +GstClockTime gst_test_clock_get_next_entry_time (GstTestClock * test_clock); + +GST_CHECK_API +void gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock, + guint count, + GList ** pending_list); + +GST_CHECK_API +guint gst_test_clock_process_id_list (GstTestClock * test_clock, + const GList * pending_list); + +GST_CHECK_API +GstClockTime gst_test_clock_id_list_get_latest_time (const GList * pending_list); + +GST_CHECK_API +gboolean gst_test_clock_crank (GstTestClock * test_clock); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTestClock, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TEST_CLOCK_H__ */ diff --git a/libs/gst/check/libcheck/Makefile.am b/libs/gst/check/libcheck/Makefile.am new file mode 100644 index 0000000..4b90803 --- /dev/null +++ b/libs/gst/check/libcheck/Makefile.am @@ -0,0 +1,80 @@ +noinst_LTLIBRARIES = libcheckinternal.la + +EXTRA_DIST = check.h.in + +CFILES =\ + check.c \ + check_error.c \ + check_list.c \ + check_log.c \ + check_msg.c \ + check_pack.c \ + check_print.c \ + check_run.c \ + check_str.c \ + libcompat/libcompat.c + +if !HAVE_ALARM +CFILES += libcompat/alarm.c +endif + +if !HAVE_CLOCK_GETTIME +CFILES += libcompat/clock_gettime.c +endif + +if !HAVE_GETTIMEOFDAY +CFILES += libcompat/gettimeofday.c +endif + +if !HAVE_LOCALTIME_R +CFILES += libcompat/localtime_r.c +endif + +if !HAVE_STRSIGNAL +CFILES += libcompat/strsignal.c +endif + +if !HAVE_STRDUP +CFILES += libcompat/strdup.c +endif + +if !HAVE_GETLINE +CFILES += libcompat/getline.c +endif + +if !HAVE_TIMER_CREATE_SETTIME_DELETE +CFILES +=\ + libcompat/timer_create.c \ + libcompat/timer_settime.c \ + libcompat/timer_delete.c +endif + +HFILES =\ + check_error.h \ + check_impl.h \ + check_list.h \ + check_log.h \ + check_msg.h \ + check_pack.h \ + check_print.h \ + check_str.h \ + libcompat/libcompat.h + +noinst_HEADERS = $(HFILES) + +libcheckinternal_la_SOURCES = $(CFILES) $(HFILES) + +libcheckinternal_la_CFLAGS = -I$(top_builddir)/libs/gst/check +libcheckinternal_la_LIBADD = + +# define HAVE_PTHREAD here as well so we keep changes to the code to a minimum +if HAVE_PTHREAD +libcheckinternal_la_CFLAGS += $(PTHREAD_CFLAGS) -D_GNU_SOURCE -DHAVE_PTHREAD +libcheckinternal_la_LIBADD += $(PTHREAD_LIBS) +else +libcheckinternal_la_CFLAGS += -D_GNU_SOURCE +endif + +# Don't want libcompat to think we don't have these and substitute replacements +# See libcompat/libcompat.h +libcheckinternal_la_CFLAGS += -DHAVE_SNPRINTF -DHAVE_VSNPRINTF -DHAVE_MALLOC -DHAVE_REALLOC diff --git a/libs/gst/check/libcheck/Makefile.in b/libs/gst/check/libcheck/Makefile.in new file mode 100644 index 0000000..8b5af67 --- /dev/null +++ b/libs/gst/check/libcheck/Makefile.in @@ -0,0 +1,1063 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_ALARM_FALSE@am__append_1 = libcompat/alarm.c +@HAVE_CLOCK_GETTIME_FALSE@am__append_2 = libcompat/clock_gettime.c +@HAVE_GETTIMEOFDAY_FALSE@am__append_3 = libcompat/gettimeofday.c +@HAVE_LOCALTIME_R_FALSE@am__append_4 = libcompat/localtime_r.c +@HAVE_STRSIGNAL_FALSE@am__append_5 = libcompat/strsignal.c +@HAVE_STRDUP_FALSE@am__append_6 = libcompat/strdup.c +@HAVE_GETLINE_FALSE@am__append_7 = libcompat/getline.c +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@am__append_8 = \ +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@ libcompat/timer_create.c \ +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@ libcompat/timer_settime.c \ +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@ libcompat/timer_delete.c + + +# define HAVE_PTHREAD here as well so we keep changes to the code to a minimum +@HAVE_PTHREAD_TRUE@am__append_9 = $(PTHREAD_CFLAGS) -D_GNU_SOURCE -DHAVE_PTHREAD +@HAVE_PTHREAD_TRUE@am__append_10 = $(PTHREAD_LIBS) +@HAVE_PTHREAD_FALSE@am__append_11 = -D_GNU_SOURCE +subdir = libs/gst/check/libcheck +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +@HAVE_PTHREAD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +libcheckinternal_la_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__libcheckinternal_la_SOURCES_DIST = check.c check_error.c \ + check_list.c check_log.c check_msg.c check_pack.c \ + check_print.c check_run.c check_str.c libcompat/libcompat.c \ + libcompat/alarm.c libcompat/clock_gettime.c \ + libcompat/gettimeofday.c libcompat/localtime_r.c \ + libcompat/strsignal.c libcompat/strdup.c libcompat/getline.c \ + libcompat/timer_create.c libcompat/timer_settime.c \ + libcompat/timer_delete.c check_error.h check_impl.h \ + check_list.h check_log.h check_msg.h check_pack.h \ + check_print.h check_str.h libcompat/libcompat.h +am__dirstamp = $(am__leading_dot)dirstamp +@HAVE_ALARM_FALSE@am__objects_1 = \ +@HAVE_ALARM_FALSE@ libcompat/libcheckinternal_la-alarm.lo +@HAVE_CLOCK_GETTIME_FALSE@am__objects_2 = libcompat/libcheckinternal_la-clock_gettime.lo +@HAVE_GETTIMEOFDAY_FALSE@am__objects_3 = libcompat/libcheckinternal_la-gettimeofday.lo +@HAVE_LOCALTIME_R_FALSE@am__objects_4 = libcompat/libcheckinternal_la-localtime_r.lo +@HAVE_STRSIGNAL_FALSE@am__objects_5 = libcompat/libcheckinternal_la-strsignal.lo +@HAVE_STRDUP_FALSE@am__objects_6 = \ +@HAVE_STRDUP_FALSE@ libcompat/libcheckinternal_la-strdup.lo +@HAVE_GETLINE_FALSE@am__objects_7 = \ +@HAVE_GETLINE_FALSE@ libcompat/libcheckinternal_la-getline.lo +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@am__objects_8 = libcompat/libcheckinternal_la-timer_create.lo \ +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@ libcompat/libcheckinternal_la-timer_settime.lo \ +@HAVE_TIMER_CREATE_SETTIME_DELETE_FALSE@ libcompat/libcheckinternal_la-timer_delete.lo +am__objects_9 = libcheckinternal_la-check.lo \ + libcheckinternal_la-check_error.lo \ + libcheckinternal_la-check_list.lo \ + libcheckinternal_la-check_log.lo \ + libcheckinternal_la-check_msg.lo \ + libcheckinternal_la-check_pack.lo \ + libcheckinternal_la-check_print.lo \ + libcheckinternal_la-check_run.lo \ + libcheckinternal_la-check_str.lo \ + libcompat/libcheckinternal_la-libcompat.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) \ + $(am__objects_5) $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) +am__objects_10 = +am_libcheckinternal_la_OBJECTS = $(am__objects_9) $(am__objects_10) +libcheckinternal_la_OBJECTS = $(am_libcheckinternal_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcheckinternal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcheckinternal_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcheckinternal_la_SOURCES) +DIST_SOURCES = $(am__libcheckinternal_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcheckinternal.la +EXTRA_DIST = check.h.in +CFILES = check.c check_error.c check_list.c check_log.c check_msg.c \ + check_pack.c check_print.c check_run.c check_str.c \ + libcompat/libcompat.c $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) $(am__append_8) +HFILES = \ + check_error.h \ + check_impl.h \ + check_list.h \ + check_log.h \ + check_msg.h \ + check_pack.h \ + check_print.h \ + check_str.h \ + libcompat/libcompat.h + +noinst_HEADERS = $(HFILES) +libcheckinternal_la_SOURCES = $(CFILES) $(HFILES) + +# Don't want libcompat to think we don't have these and substitute replacements +# See libcompat/libcompat.h +libcheckinternal_la_CFLAGS = -I$(top_builddir)/libs/gst/check \ + $(am__append_9) $(am__append_11) -DHAVE_SNPRINTF \ + -DHAVE_VSNPRINTF -DHAVE_MALLOC -DHAVE_REALLOC +libcheckinternal_la_LIBADD = $(am__append_10) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/check/libcheck/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/check/libcheck/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcompat/$(am__dirstamp): + @$(MKDIR_P) libcompat + @: > libcompat/$(am__dirstamp) +libcompat/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libcompat/$(DEPDIR) + @: > libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-libcompat.lo: libcompat/$(am__dirstamp) \ + libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-alarm.lo: libcompat/$(am__dirstamp) \ + libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-clock_gettime.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-gettimeofday.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-localtime_r.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-strsignal.lo: libcompat/$(am__dirstamp) \ + libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-strdup.lo: libcompat/$(am__dirstamp) \ + libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-getline.lo: libcompat/$(am__dirstamp) \ + libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-timer_create.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-timer_settime.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) +libcompat/libcheckinternal_la-timer_delete.lo: \ + libcompat/$(am__dirstamp) libcompat/$(DEPDIR)/$(am__dirstamp) + +libcheckinternal.la: $(libcheckinternal_la_OBJECTS) $(libcheckinternal_la_DEPENDENCIES) $(EXTRA_libcheckinternal_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcheckinternal_la_LINK) $(libcheckinternal_la_OBJECTS) $(libcheckinternal_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f libcompat/*.$(OBJEXT) + -rm -f libcompat/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_pack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_print.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_run.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcheckinternal_la-check_str.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-alarm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-clock_gettime.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-getline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-gettimeofday.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-libcompat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-localtime_r.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-strdup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-strsignal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-timer_create.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-timer_delete.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libcompat/$(DEPDIR)/libcheckinternal_la-timer_settime.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libcheckinternal_la-check.lo: check.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check.Tpo -c -o libcheckinternal_la-check.lo `test -f 'check.c' || echo '$(srcdir)/'`check.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check.Tpo $(DEPDIR)/libcheckinternal_la-check.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='libcheckinternal_la-check.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check.lo `test -f 'check.c' || echo '$(srcdir)/'`check.c + +libcheckinternal_la-check_error.lo: check_error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_error.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_error.Tpo -c -o libcheckinternal_la-check_error.lo `test -f 'check_error.c' || echo '$(srcdir)/'`check_error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_error.Tpo $(DEPDIR)/libcheckinternal_la-check_error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_error.c' object='libcheckinternal_la-check_error.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_error.lo `test -f 'check_error.c' || echo '$(srcdir)/'`check_error.c + +libcheckinternal_la-check_list.lo: check_list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_list.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_list.Tpo -c -o libcheckinternal_la-check_list.lo `test -f 'check_list.c' || echo '$(srcdir)/'`check_list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_list.Tpo $(DEPDIR)/libcheckinternal_la-check_list.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_list.c' object='libcheckinternal_la-check_list.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_list.lo `test -f 'check_list.c' || echo '$(srcdir)/'`check_list.c + +libcheckinternal_la-check_log.lo: check_log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_log.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_log.Tpo -c -o libcheckinternal_la-check_log.lo `test -f 'check_log.c' || echo '$(srcdir)/'`check_log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_log.Tpo $(DEPDIR)/libcheckinternal_la-check_log.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_log.c' object='libcheckinternal_la-check_log.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_log.lo `test -f 'check_log.c' || echo '$(srcdir)/'`check_log.c + +libcheckinternal_la-check_msg.lo: check_msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_msg.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_msg.Tpo -c -o libcheckinternal_la-check_msg.lo `test -f 'check_msg.c' || echo '$(srcdir)/'`check_msg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_msg.Tpo $(DEPDIR)/libcheckinternal_la-check_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_msg.c' object='libcheckinternal_la-check_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_msg.lo `test -f 'check_msg.c' || echo '$(srcdir)/'`check_msg.c + +libcheckinternal_la-check_pack.lo: check_pack.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_pack.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_pack.Tpo -c -o libcheckinternal_la-check_pack.lo `test -f 'check_pack.c' || echo '$(srcdir)/'`check_pack.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_pack.Tpo $(DEPDIR)/libcheckinternal_la-check_pack.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_pack.c' object='libcheckinternal_la-check_pack.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_pack.lo `test -f 'check_pack.c' || echo '$(srcdir)/'`check_pack.c + +libcheckinternal_la-check_print.lo: check_print.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_print.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_print.Tpo -c -o libcheckinternal_la-check_print.lo `test -f 'check_print.c' || echo '$(srcdir)/'`check_print.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_print.Tpo $(DEPDIR)/libcheckinternal_la-check_print.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_print.c' object='libcheckinternal_la-check_print.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_print.lo `test -f 'check_print.c' || echo '$(srcdir)/'`check_print.c + +libcheckinternal_la-check_run.lo: check_run.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_run.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_run.Tpo -c -o libcheckinternal_la-check_run.lo `test -f 'check_run.c' || echo '$(srcdir)/'`check_run.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_run.Tpo $(DEPDIR)/libcheckinternal_la-check_run.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_run.c' object='libcheckinternal_la-check_run.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_run.lo `test -f 'check_run.c' || echo '$(srcdir)/'`check_run.c + +libcheckinternal_la-check_str.lo: check_str.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcheckinternal_la-check_str.lo -MD -MP -MF $(DEPDIR)/libcheckinternal_la-check_str.Tpo -c -o libcheckinternal_la-check_str.lo `test -f 'check_str.c' || echo '$(srcdir)/'`check_str.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcheckinternal_la-check_str.Tpo $(DEPDIR)/libcheckinternal_la-check_str.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check_str.c' object='libcheckinternal_la-check_str.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcheckinternal_la-check_str.lo `test -f 'check_str.c' || echo '$(srcdir)/'`check_str.c + +libcompat/libcheckinternal_la-libcompat.lo: libcompat/libcompat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-libcompat.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-libcompat.Tpo -c -o libcompat/libcheckinternal_la-libcompat.lo `test -f 'libcompat/libcompat.c' || echo '$(srcdir)/'`libcompat/libcompat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-libcompat.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-libcompat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/libcompat.c' object='libcompat/libcheckinternal_la-libcompat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-libcompat.lo `test -f 'libcompat/libcompat.c' || echo '$(srcdir)/'`libcompat/libcompat.c + +libcompat/libcheckinternal_la-alarm.lo: libcompat/alarm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-alarm.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-alarm.Tpo -c -o libcompat/libcheckinternal_la-alarm.lo `test -f 'libcompat/alarm.c' || echo '$(srcdir)/'`libcompat/alarm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-alarm.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-alarm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/alarm.c' object='libcompat/libcheckinternal_la-alarm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-alarm.lo `test -f 'libcompat/alarm.c' || echo '$(srcdir)/'`libcompat/alarm.c + +libcompat/libcheckinternal_la-clock_gettime.lo: libcompat/clock_gettime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-clock_gettime.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-clock_gettime.Tpo -c -o libcompat/libcheckinternal_la-clock_gettime.lo `test -f 'libcompat/clock_gettime.c' || echo '$(srcdir)/'`libcompat/clock_gettime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-clock_gettime.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-clock_gettime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/clock_gettime.c' object='libcompat/libcheckinternal_la-clock_gettime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-clock_gettime.lo `test -f 'libcompat/clock_gettime.c' || echo '$(srcdir)/'`libcompat/clock_gettime.c + +libcompat/libcheckinternal_la-gettimeofday.lo: libcompat/gettimeofday.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-gettimeofday.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-gettimeofday.Tpo -c -o libcompat/libcheckinternal_la-gettimeofday.lo `test -f 'libcompat/gettimeofday.c' || echo '$(srcdir)/'`libcompat/gettimeofday.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-gettimeofday.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-gettimeofday.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/gettimeofday.c' object='libcompat/libcheckinternal_la-gettimeofday.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-gettimeofday.lo `test -f 'libcompat/gettimeofday.c' || echo '$(srcdir)/'`libcompat/gettimeofday.c + +libcompat/libcheckinternal_la-localtime_r.lo: libcompat/localtime_r.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-localtime_r.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-localtime_r.Tpo -c -o libcompat/libcheckinternal_la-localtime_r.lo `test -f 'libcompat/localtime_r.c' || echo '$(srcdir)/'`libcompat/localtime_r.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-localtime_r.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-localtime_r.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/localtime_r.c' object='libcompat/libcheckinternal_la-localtime_r.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-localtime_r.lo `test -f 'libcompat/localtime_r.c' || echo '$(srcdir)/'`libcompat/localtime_r.c + +libcompat/libcheckinternal_la-strsignal.lo: libcompat/strsignal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-strsignal.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-strsignal.Tpo -c -o libcompat/libcheckinternal_la-strsignal.lo `test -f 'libcompat/strsignal.c' || echo '$(srcdir)/'`libcompat/strsignal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-strsignal.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-strsignal.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/strsignal.c' object='libcompat/libcheckinternal_la-strsignal.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-strsignal.lo `test -f 'libcompat/strsignal.c' || echo '$(srcdir)/'`libcompat/strsignal.c + +libcompat/libcheckinternal_la-strdup.lo: libcompat/strdup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-strdup.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-strdup.Tpo -c -o libcompat/libcheckinternal_la-strdup.lo `test -f 'libcompat/strdup.c' || echo '$(srcdir)/'`libcompat/strdup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-strdup.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-strdup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/strdup.c' object='libcompat/libcheckinternal_la-strdup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-strdup.lo `test -f 'libcompat/strdup.c' || echo '$(srcdir)/'`libcompat/strdup.c + +libcompat/libcheckinternal_la-getline.lo: libcompat/getline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-getline.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-getline.Tpo -c -o libcompat/libcheckinternal_la-getline.lo `test -f 'libcompat/getline.c' || echo '$(srcdir)/'`libcompat/getline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-getline.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-getline.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/getline.c' object='libcompat/libcheckinternal_la-getline.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-getline.lo `test -f 'libcompat/getline.c' || echo '$(srcdir)/'`libcompat/getline.c + +libcompat/libcheckinternal_la-timer_create.lo: libcompat/timer_create.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-timer_create.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-timer_create.Tpo -c -o libcompat/libcheckinternal_la-timer_create.lo `test -f 'libcompat/timer_create.c' || echo '$(srcdir)/'`libcompat/timer_create.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-timer_create.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-timer_create.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/timer_create.c' object='libcompat/libcheckinternal_la-timer_create.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-timer_create.lo `test -f 'libcompat/timer_create.c' || echo '$(srcdir)/'`libcompat/timer_create.c + +libcompat/libcheckinternal_la-timer_settime.lo: libcompat/timer_settime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-timer_settime.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-timer_settime.Tpo -c -o libcompat/libcheckinternal_la-timer_settime.lo `test -f 'libcompat/timer_settime.c' || echo '$(srcdir)/'`libcompat/timer_settime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-timer_settime.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-timer_settime.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/timer_settime.c' object='libcompat/libcheckinternal_la-timer_settime.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-timer_settime.lo `test -f 'libcompat/timer_settime.c' || echo '$(srcdir)/'`libcompat/timer_settime.c + +libcompat/libcheckinternal_la-timer_delete.lo: libcompat/timer_delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -MT libcompat/libcheckinternal_la-timer_delete.lo -MD -MP -MF libcompat/$(DEPDIR)/libcheckinternal_la-timer_delete.Tpo -c -o libcompat/libcheckinternal_la-timer_delete.lo `test -f 'libcompat/timer_delete.c' || echo '$(srcdir)/'`libcompat/timer_delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libcompat/$(DEPDIR)/libcheckinternal_la-timer_delete.Tpo libcompat/$(DEPDIR)/libcheckinternal_la-timer_delete.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat/timer_delete.c' object='libcompat/libcheckinternal_la-timer_delete.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcheckinternal_la_CFLAGS) $(CFLAGS) -c -o libcompat/libcheckinternal_la-timer_delete.lo `test -f 'libcompat/timer_delete.c' || echo '$(srcdir)/'`libcompat/timer_delete.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf libcompat/.libs libcompat/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f libcompat/$(DEPDIR)/$(am__dirstamp) + -rm -f libcompat/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) libcompat/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) libcompat/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/check/libcheck/check.c b/libs/gst/check/libcheck/check.c new file mode 100644 index 0000000..5b8c434 --- /dev/null +++ b/libs/gst/check/libcheck/check.c @@ -0,0 +1,640 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include +#include +#include + +#include "internal-check.h" +#include "check_error.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_msg.h" + +#ifdef HAVE_UNISTD_H +#include /* for _POSIX_VERSION */ +#endif + +#ifndef DEFAULT_TIMEOUT +#define DEFAULT_TIMEOUT 4 +#endif + +/* + * When a process exits either normally, with exit(), or + * by an uncaught signal, The lower 0x377 bits are passed + * to the parent. Of those, only the lower 8 bits are + * returned by the WEXITSTATUS() macro. + */ +#define WEXITSTATUS_MASK 0xFF + +int check_major_version = CHECK_MAJOR_VERSION; +int check_minor_version = CHECK_MINOR_VERSION; +int check_micro_version = CHECK_MICRO_VERSION; + +const char* current_test_name = NULL; + +static int non_pass (int val); +static Fixture *fixture_create (SFun fun, int ischecked); +static void tcase_add_fixture (TCase * tc, SFun setup, SFun teardown, + int ischecked); +static void tr_init (TestResult * tr); +static void suite_free (Suite * s); +static void tcase_free (TCase * tc); + +Suite * +suite_create (const char *name) +{ + Suite *s; + + s = (Suite *) emalloc (sizeof (Suite)); /* freed in suite_free */ + if (name == NULL) + s->name = ""; + else + s->name = name; + s->tclst = check_list_create (); + return s; +} + +int +suite_tcase (Suite * s, const char *tcname) +{ + List *l; + TCase *tc; + + if (s == NULL) + return 0; + + l = s->tclst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + tc = (TCase *) check_list_val (l); + if (strcmp (tcname, tc->name) == 0) + return 1; + } + + return 0; +} + +static void +suite_free (Suite * s) +{ + List *l; + + if (s == NULL) + return; + l = s->tclst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + tcase_free ((TCase *) check_list_val (l)); + } + check_list_free (s->tclst); + free (s); +} + + +TCase * +tcase_create (const char *name) +{ + char *env; + double timeout_sec = DEFAULT_TIMEOUT; + + TCase *tc = (TCase *) emalloc (sizeof (TCase)); /*freed in tcase_free */ + + if (name == NULL) + tc->name = ""; + else + tc->name = name; + + env = getenv ("CK_DEFAULT_TIMEOUT"); + if (env != NULL) { + char *endptr = NULL; + double tmp = strtod (env, &endptr); + + if (tmp >= 0 && endptr != env && (*endptr) == '\0') { + timeout_sec = tmp; + } + } + + env = getenv ("CK_TIMEOUT_MULTIPLIER"); + if (env != NULL) { + char *endptr = NULL; + double tmp = strtod (env, &endptr); + + if (tmp >= 0 && endptr != env && (*endptr) == '\0') { + timeout_sec = timeout_sec * tmp; + } + } + + tc->timeout.tv_sec = (time_t) floor (timeout_sec); + tc->timeout.tv_nsec = + (long) ((timeout_sec - floor (timeout_sec)) * (double) NANOS_PER_SECONDS); + + tc->tflst = check_list_create (); + tc->unch_sflst = check_list_create (); + tc->ch_sflst = check_list_create (); + tc->unch_tflst = check_list_create (); + tc->ch_tflst = check_list_create (); + tc->tags = check_list_create (); + + return tc; +} + +/* + * Helper function to create a list of tags from + * a space separated string. + */ +List * +tag_string_to_list (const char *tags_string) +{ + List *list; + char *tags; + char *tag; + + list = check_list_create (); + + if (NULL == tags_string) { + return list; + } + + tags = strdup (tags_string); + tag = strtok (tags, " "); + while (tag) { + check_list_add_end (list, strdup (tag)); + tag = strtok (NULL, " "); + } + free (tags); + return list; +} + +void +tcase_set_tags (TCase * tc, const char *tags_orig) +{ + /* replace any pre-existing list */ + if (tc->tags) { + check_list_apply (tc->tags, free); + check_list_free (tc->tags); + } + tc->tags = tag_string_to_list (tags_orig); +} + +static void +tcase_free (TCase * tc) +{ + check_list_apply (tc->tflst, free); + check_list_apply (tc->unch_sflst, free); + check_list_apply (tc->ch_sflst, free); + check_list_apply (tc->unch_tflst, free); + check_list_apply (tc->ch_tflst, free); + check_list_apply (tc->tags, free); + check_list_free (tc->tflst); + check_list_free (tc->unch_sflst); + check_list_free (tc->ch_sflst); + check_list_free (tc->unch_tflst); + check_list_free (tc->ch_tflst); + check_list_free (tc->tags); + free (tc); +} + +unsigned int +tcase_matching_tag (TCase * tc, List * check_for) +{ + + if (NULL == check_for) { + return 0; + } + + for (check_list_front (check_for); !check_list_at_end (check_for); + check_list_advance (check_for)) { + for (check_list_front (tc->tags); !check_list_at_end (tc->tags); + check_list_advance (tc->tags)) { + if (0 == strcmp ((const char *) check_list_val (tc->tags), + (const char *) check_list_val (check_for))) { + return 1; + } + } + } + return 0; +} + +void +suite_add_tcase (Suite * s, TCase * tc) +{ + if (s == NULL || tc == NULL || check_list_contains (s->tclst, tc)) { + return; + } + + check_list_add_end (s->tclst, tc); +} + +void +_tcase_add_test (TCase * tc, TFun fn, const char *name, int _signal, + int allowed_exit_value, int start, int end) +{ + TF *tf; + + if (tc == NULL || fn == NULL || name == NULL) + return; + tf = (TF *) emalloc (sizeof (TF)); /* freed in tcase_free */ + tf->fn = fn; + tf->loop_start = start; + tf->loop_end = end; + tf->signal = _signal; /* 0 means no signal expected */ + tf->allowed_exit_value = (WEXITSTATUS_MASK & allowed_exit_value); /* 0 is default successful exit */ + tf->name = name; + check_list_add_end (tc->tflst, tf); +} + +static Fixture * +fixture_create (SFun fun, int ischecked) +{ + Fixture *f; + + f = (Fixture *) emalloc (sizeof (Fixture)); + f->fun = fun; + f->ischecked = ischecked; + + return f; +} + +void +tcase_add_unchecked_fixture (TCase * tc, SFun setup, SFun teardown) +{ + tcase_add_fixture (tc, setup, teardown, 0); +} + +void +tcase_add_checked_fixture (TCase * tc, SFun setup, SFun teardown) +{ + tcase_add_fixture (tc, setup, teardown, 1); +} + +static void +tcase_add_fixture (TCase * tc, SFun setup, SFun teardown, int ischecked) +{ + if (setup) { + if (ischecked) + check_list_add_end (tc->ch_sflst, fixture_create (setup, ischecked)); + else + check_list_add_end (tc->unch_sflst, fixture_create (setup, ischecked)); + } + + /* Add teardowns at front so they are run in reverse order. */ + if (teardown) { + if (ischecked) + check_list_add_front (tc->ch_tflst, fixture_create (teardown, ischecked)); + else + check_list_add_front (tc->unch_tflst, + fixture_create (teardown, ischecked)); + } +} + +void +tcase_set_timeout (TCase * tc, double timeout) +{ +#if defined(HAVE_FORK) + if (timeout >= 0) { + char *env = getenv ("CK_TIMEOUT_MULTIPLIER"); + + if (env != NULL) { + char *endptr = NULL; + double tmp = strtod (env, &endptr); + + if (tmp >= 0 && endptr != env && (*endptr) == '\0') { + timeout = timeout * tmp; + } + } + + tc->timeout.tv_sec = (time_t) floor (timeout); + tc->timeout.tv_nsec = + (long) ((timeout - floor (timeout)) * (double) NANOS_PER_SECONDS); + } +#else + (void) tc; + (void) timeout; + eprintf + ("This version does not support timeouts, as fork is not supported", + __FILE__, __LINE__); + /* Ignoring, as Check is not compiled with fork support. */ +#endif /* HAVE_FORK */ +} + +void +tcase_fn_start (const char *fname, const char *file, int line) +{ + send_ctx_info (CK_CTX_TEST); + send_loc_info (file, line); + + current_test_name = fname; +} + +const char * +tcase_name () +{ + return current_test_name; +} + +void +_mark_point (const char *file, int line) +{ + send_loc_info (file, line); +} + +void +_ck_assert_failed (const char *file, int line, const char *expr, ...) +{ + const char *msg; + va_list ap; + char buf[BUFSIZ]; + const char *to_send; + + send_loc_info (file, line); + + va_start (ap, expr); + msg = (const char *) va_arg (ap, char *); + + /* + * If a message was passed, format it with vsnprintf. + * Otherwise, print the expression as is. + */ + if (msg != NULL) { + vsnprintf (buf, BUFSIZ, msg, ap); + to_send = buf; + } else { + to_send = expr; + } + + va_end (ap); + send_failure_info (to_send); + if (cur_fork_status () == CK_FORK) { +#if defined(HAVE_FORK) && HAVE_FORK==1 + _exit (1); +#endif /* HAVE_FORK */ + } else { + longjmp (error_jmp_buffer, 1); + } +} + +SRunner * +srunner_create (Suite * s) +{ + SRunner *sr = (SRunner *) emalloc (sizeof (SRunner)); /* freed in srunner_free */ + + sr->slst = check_list_create (); + if (s != NULL) + check_list_add_end (sr->slst, s); + sr->stats = (TestStats *) emalloc (sizeof (TestStats)); /* freed in srunner_free */ + sr->stats->n_checked = sr->stats->n_failed = sr->stats->n_errors = 0; + sr->resultlst = check_list_create (); + sr->log_fname = NULL; + sr->xml_fname = NULL; + sr->tap_fname = NULL; + sr->loglst = NULL; + +#if defined(HAVE_FORK) + sr->fstat = CK_FORK_GETENV; +#else + /* + * Overriding the default of running tests in fork mode, + * as this system does not have fork() + */ + sr->fstat = CK_NOFORK; +#endif /* HAVE_FORK */ + + return sr; +} + +void +srunner_add_suite (SRunner * sr, Suite * s) +{ + if (s == NULL) + return; + + check_list_add_end (sr->slst, s); +} + +void +srunner_free (SRunner * sr) +{ + List *l; + TestResult *tr; + + if (sr == NULL) + return; + + free (sr->stats); + l = sr->slst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + suite_free ((Suite *) check_list_val (l)); + } + check_list_free (sr->slst); + + l = sr->resultlst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + tr = (TestResult *) check_list_val (l); + tr_free (tr); + } + check_list_free (sr->resultlst); + + free (sr); +} + +int +srunner_ntests_failed (SRunner * sr) +{ + return sr->stats->n_failed + sr->stats->n_errors; +} + +int +srunner_ntests_run (SRunner * sr) +{ + return sr->stats->n_checked; +} + +TestResult ** +srunner_failures (SRunner * sr) +{ + int i = 0; + TestResult **trarray; + List *rlst; + + trarray = + (TestResult **) emalloc (sizeof (trarray[0]) * + srunner_ntests_failed (sr)); + + rlst = sr->resultlst; + for (check_list_front (rlst); !check_list_at_end (rlst); + check_list_advance (rlst)) { + TestResult *tr = (TestResult *) check_list_val (rlst); + + if (non_pass (tr->rtype)) + trarray[i++] = tr; + + } + return trarray; +} + +TestResult ** +srunner_results (SRunner * sr) +{ + int i = 0; + TestResult **trarray; + List *rlst; + + trarray = + (TestResult **) emalloc (sizeof (trarray[0]) * srunner_ntests_run (sr)); + + rlst = sr->resultlst; + for (check_list_front (rlst); !check_list_at_end (rlst); + check_list_advance (rlst)) { + trarray[i++] = (TestResult *) check_list_val (rlst); + } + return trarray; +} + +static int +non_pass (int val) +{ + return val != CK_PASS; +} + +TestResult * +tr_create (void) +{ + TestResult *tr; + + tr = (TestResult *) emalloc (sizeof (TestResult)); + tr_init (tr); + return tr; +} + +static void +tr_init (TestResult * tr) +{ + tr->ctx = CK_CTX_INVALID; + tr->line = -1; + tr->rtype = CK_TEST_RESULT_INVALID; + tr->msg = NULL; + tr->file = NULL; + tr->tcname = NULL; + tr->tname = NULL; + tr->duration = -1; +} + +void +tr_free (TestResult * tr) +{ + free (tr->file); + free (tr->msg); + free (tr); +} + + +const char * +tr_msg (TestResult * tr) +{ + return tr->msg; +} + +int +tr_lno (TestResult * tr) +{ + return tr->line; +} + +const char * +tr_lfile (TestResult * tr) +{ + return tr->file; +} + +int +tr_rtype (TestResult * tr) +{ + return tr->rtype; +} + +enum ck_result_ctx +tr_ctx (TestResult * tr) +{ + return tr->ctx; +} + +const char * +tr_tcname (TestResult * tr) +{ + return tr->tcname; +} + +static enum fork_status _fstat = CK_FORK; + +void +set_fork_status (enum fork_status fstat) +{ + if (fstat == CK_FORK || fstat == CK_NOFORK || fstat == CK_FORK_GETENV) + _fstat = fstat; + else + eprintf ("Bad status in set_fork_status", __FILE__, __LINE__); +} + +enum fork_status +cur_fork_status (void) +{ + return _fstat; +} + +/** + * Not all systems support the same clockid_t's. This call checks + * if the CLOCK_MONOTONIC clockid_t is valid. If so, that is returned, + * otherwise, CLOCK_REALTIME is returned. + * + * The clockid_t that was found to work on the first call is + * cached for subsequent calls. + */ +clockid_t +check_get_clockid () +{ + static clockid_t clockid = -1; + + if (clockid == -1) { +/* + * Only check if we have librt available. Otherwise, the clockid + * will be ignored anyway, as the clock_gettime() and + * timer_create() functions will be re-implemented in libcompat. + * Worse, if librt and alarm() are unavailable, this check + * will result in an assert(0). + */ +#if defined(HAVE_POSIX_TIMERS) && defined(HAVE_MONOTONIC_CLOCK) + timer_t timerid; + + if (timer_create (CLOCK_MONOTONIC, NULL, &timerid) == 0) { + timer_delete (timerid); + clockid = CLOCK_MONOTONIC; + } else { + clockid = CLOCK_REALTIME; + } +#else + clockid = CLOCK_MONOTONIC; +#endif + } + + return clockid; +} diff --git a/libs/gst/check/libcheck/check.h.in b/libs/gst/check/libcheck/check.h.in new file mode 100644 index 0000000..9eb40bc --- /dev/null +++ b/libs/gst/check/libcheck/check.h.in @@ -0,0 +1,1338 @@ +/*-*- mode:C; -*- */ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_H +#define CHECK_H + +#include +#include + +/* + Macros and functions starting with _ (underscore) are internal and + may change without notice. You have been warned!. +*/ + + +#ifdef __cplusplus +#define CK_CPPSTART extern "C" { +#define CK_CPPEND } +CK_CPPSTART +#endif +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define GCC_VERSION_AT_LEAST(major, minor) \ +((__GNUC__ > (major)) || \ + (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) +#else +#define GCC_VERSION_AT_LEAST(major, minor) 0 +#endif +#if GCC_VERSION_AT_LEAST(2,95) +#define CK_ATTRIBUTE_UNUSED __attribute__ ((unused)) +#else +#define CK_ATTRIBUTE_UNUSED +#endif /* GCC 2.95 */ +#if GCC_VERSION_AT_LEAST(2,5) +#define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn)) +#else +#define CK_ATTRIBUTE_NORETURN +#endif /* GCC 2.5 */ +#include + +/* + * Used to create the linker script for hiding lib-local symbols. Shall + * be put directly in front of the exported symbol. + */ +#define CK_EXPORT + +/* + * Used for MSVC to create the export attribute + * CK_DLL_EXP is defined during the compilation of the library + * on the command line. + */ +#ifndef CK_DLL_EXP +# if defined(_MSC_VER) +# define CK_DLL_EXP __declspec(dllimport) +# else +# define CK_DLL_EXP extern +# endif +#endif + +/* check version numbers */ +#define CHECK_MAJOR_VERSION (@CHECK_MAJOR_VERSION@) +#define CHECK_MINOR_VERSION (@CHECK_MINOR_VERSION@) +#define CHECK_MICRO_VERSION (@CHECK_MICRO_VERSION@) +CK_DLL_EXP /*extern*/ int CK_EXPORT check_major_version; +CK_DLL_EXP /*extern*/ int CK_EXPORT check_minor_version; +CK_DLL_EXP /*extern*/ int CK_EXPORT check_micro_version; + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#if defined(_MSC_VER) +#define pid_t int +#endif + +/** + * Type for a test case + * + * A TCase represents a test case. Create with tcase_create, free + * with tcase_free. For the moment, test cases can only be run + * through a suite +*/ +typedef struct TCase TCase; + +/** + * Type for a test function + */ +typedef void (*TFun) (int); + +/** + * Type for a setup/teardown function + */ +typedef void (*SFun) (void); + +/** + * Type for a test suite + */ +typedef struct Suite Suite; + +/** + * Creates a test suite with the given name. + * + * Create a suite, which will contain test cases. Once + * created, use suite_add_tcase() to add test cases. + * When finished, create a suite runner from the + * suite using srunner_create() + * + * @param name name of the suite + * + * @return suite + * + * @since 0.6.0 + */ +CK_DLL_EXP Suite *CK_EXPORT suite_create (const char *name); + +/** + * Determines whether a given test suite contains a case named after a + * given string. + * + * @param s suite to check + * @param tcname test case to look for + * + * @return 1 iff the given test case is within the given suite; + * 0 otherwise + * + * @since 0.9.9 + */ +CK_DLL_EXP int CK_EXPORT suite_tcase (Suite * s, const char *tcname); + +/** + * Add a test case to a suite. + * + * Note that if the TCase has already been added attempting + * to add it again will be ignored. + * + * @param s suite to add test case to + * @param tc test case to add to suite + * + * @since 0.6.0 + */ +CK_DLL_EXP void CK_EXPORT suite_add_tcase (Suite * s, TCase * tc); + +/** + * Create a test case. + * + * Once created, tests can be added with the tcase_add_test() + * function, and the test case assigned to a suite with the + * suite_add_tcase() function. + * + * @param name name of the test case + * + * @return test case containing no tests + * + * @since 0.6.0 + * */ +CK_DLL_EXP TCase *CK_EXPORT tcase_create (const char *name); + +/** + * Associate a test case with certain tags. + * Replaces any existing tags with the new set. + * + * @param tc the test case + * + * @param tags string containing arbitrary tags separated by spaces. + * This will be copied. Passing NULL clears all tags. + * + * @since 0.11.0 + * */ +CK_DLL_EXP void CK_EXPORT tcase_set_tags (TCase * tc, const char *tags); +/** + * Add a test function to a test case + * + * @param tc test case to add test to + * @param tf test function to add to test case + * + * @since 0.6.0 + * */ +#define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0) + +/** + * Add a test function with signal handling to a test case + * + * The added test is expected to terminate by throwing the given signal + * + * @param tc test case to add test to + * @param tf test function to add to test case + * @param signal expected signal for test function to throw in order for + * the test to be considered passing + * + * @since 0.9.2 + * */ +#define tcase_add_test_raise_signal(tc,tf,signal) \ + _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 0, 1) + +/** + * Add a test function with an expected exit value to a test case + * + * The added test is expected to terminate by exiting with the given value + * + * @param tc test case to add test to + * @param tf test function to add to test case + * @param expected_exit_value exit value for test function to return in + * order for the test to be considered passing + * + * @since 0.9.7 + */ +#define tcase_add_exit_test(tc, tf, expected_exit_value) \ + _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),0,1) + +/** + * Add a looping test function to a test case + * + * The test will be called in a for(i = s; i < e; i++) loop with each + * iteration being executed in a new context. The loop variable 'i' is + * available in the test. + * + * @param tc test case to add test to + * @param tf function to add to test case + * @param s starting index for value "i" in test + * @param e ending index for value "i" in test + * + * @since 0.9.4 + */ +#define tcase_add_loop_test(tc,tf,s,e) \ + _tcase_add_test((tc),(tf),"" # tf "",0,0,(s),(e)) + +/** + * Add a looping test function with signal handling to a test case + * + * The test will be called in a for(i = s; i < e; i++) loop with each + * iteration being executed in a new context. The loop variable 'i' is + * available in the test. + * + * The added test is expected to terminate by throwing the given signal + * + * @param tc test case to add test to + * @param tf function to add to test case + * @param signal expected signal for test function to throw in order for + * the test to be considered passing + * @param s starting index for value "i" in test + * @param e ending index for value "i" in test + * + * @since 0.9.5 + */ +#define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \ + _tcase_add_test((tc),(tf),"" # tf "",(signal),0,(s),(e)) + +/** + * Add a looping test function with an expected exit value to a test case + * + * The test will be called in a for(i = s; i < e; i++) loop with each + * iteration being executed in a new context. The loop variable 'i' is + * available in the test. + * + * The added test is expected to terminate by exiting with the given value + * + * @param tc test case to add test to + * @param tf function to add to test case + * @param expected_exit_value exit value for test function to return in + * order for the test to be considered passing + * @param s starting index for value "i" in test + * @param e ending index for value "i" in test + * + * @since 0.9.7 + */ +#define tcase_add_loop_exit_test(tc,tf,expected_exit_value,s,e) \ + _tcase_add_test((tc),(tf),"" # tf "",0,(expected_exit_value),(s),(e)) + +/* Add a test function to a test case + (function version -- use this when the macro won't work +*/ +CK_DLL_EXP void CK_EXPORT _tcase_add_test (TCase * tc, TFun tf, + const char *fname, int _signal, int allowed_exit_value, int start, int end); + +/** + * Add unchecked fixture setup/teardown functions to a test case + * + * Unchecked fixture functions are run at the start and end of the + * test case, and not before and after unit tests. Further, + * unchecked fixture functions are not run in a separate address space, + * like test functions, and so must not exit or signal (e.g., + * segfault). + * + * Also, when run in CK_NOFORK mode, unchecked fixture functions may + * lead to different unit test behavior if unit tests change data + * setup by the fixture functions. + * + * Note that if a setup function fails, the remaining setup functions + * will be omitted, as will the test case and the teardown functions. + * If a teardown function fails the remaining teardown functins will be + * omitted. + * + * @param tc test case to add unchecked fixture setup/teardown to + * @param setup function to add to be executed before the test case; + * if NULL no setup function is added + * @param teardown function to add to be executed after the test case; + * if NULL no teardown function is added + * @since 0.8.0 + */ +CK_DLL_EXP void CK_EXPORT tcase_add_unchecked_fixture (TCase * tc, SFun setup, + SFun teardown); + +/** + * Add checked fixture setup/teardown functions to a test case + * + * Checked fixture functions are run before and after each unit test inside + * of the address space of the test. Thus, if using CK_FORK + * mode the separate process running the unit test will survive signals + * or unexpected exits in the fixture function. Also, if the setup + * function is idempotent, unit test behavior will be the same in + * CK_FORK and CK_NOFORK modes. + * + * However, since fixture functions are run before and after each unit + * test, they should not be expensive code. + * + * Note that if a setup function fails, the remaining setup functions + * will be omitted, as will the test and the teardown functions. If a + * teardown function fails the remaining teardown functins will be + * omitted. + * + * @param tc test case to add checked fixture setup/teardown to + * @param setup function to add to be executed before each unit test in + * the test case; if NULL no setup function is added + * @param teardown function to add to be executed after each unit test in + * the test case; if NULL no teardown function is added + * + * @since 0.8.0 +*/ +CK_DLL_EXP void CK_EXPORT tcase_add_checked_fixture (TCase * tc, SFun setup, + SFun teardown); + +/** + * Set the timeout for all tests in a test case. + * + * A test that lasts longer than the timeout (in seconds) will be killed + * and thus fail with an error. + * + * If not set, the default timeout is one assigned at compile time. If + * the environment variable CK_DEFAULT_TIMEOUT is defined and no timeout + * is set, the value in the environment variable is used. + * + * If Check is compile without fork() support this call is ignored, + * as timeouts are not possible. + * + * @param tc test case to assign timeout to + * @param timeout to use, in seconds. If the value contains a decimal + * portion, but no high resolution timer is available, + * the value is rounded up to the nearest second. + * + * @since 0.9.2 + */ +CK_DLL_EXP void CK_EXPORT tcase_set_timeout (TCase * tc, double timeout); + +/* Internal function to mark the start of a test function */ +CK_DLL_EXP void CK_EXPORT tcase_fn_start (const char *fname, const char *file, + int line); + +/** + * Start a unit test with START_TEST(unit_name), end with END_TEST. + * + * One must use braces within a START_/END_ pair to declare new variables + * + * @since 0.6.0 + */ +#define START_TEST(__testname)\ +static void __testname (int _i CK_ATTRIBUTE_UNUSED)\ +{\ + tcase_fn_start (""# __testname, __FILE__, __LINE__); + +/** + * End a unit test + * + * @since 0.6.0 + */ +#define END_TEST } + +/* + * Fail the test case unless expr is false + * + * This call is deprecated. + */ +#define fail_unless ck_assert_msg + +/* + * Fail the test case if expr is false + * + * This call is deprecated. + * + * NOTE: The space before the comma sign before ## is essential to be compatible + * with gcc 2.95.3 and earlier. + * FIXME: these macros may conflict with C89 if expr is + * FIXME: strcmp (str1, str2) due to excessive string length. + */ +#define fail_if(expr, ...)\ + (expr) ? \ + _ck_assert_failed(__FILE__, __LINE__, "Failure '"#expr"' occurred" , ## __VA_ARGS__, NULL) \ + : _mark_point(__FILE__, __LINE__) + +/* + * Fail the test + * + * This call is deprecated. + */ +#define fail ck_abort_msg + +/* + * This is called whenever an assertion fails. + * Note that it only has the noreturn modifier when + * using fork. If fork is unavailable, the function + * calls longjmp() when a test assertion fails. Marking + * the function as noreturn causes gcc to make assumptions + * which are not valid, as longjmp() is like a return. + */ +#if @HAVE_FORK@ +CK_DLL_EXP void CK_EXPORT +_ck_assert_failed (const char *file, int line, const char *expr, ...) + CK_ATTRIBUTE_NORETURN; +#else +CK_DLL_EXP void CK_EXPORT _ck_assert_failed (const char *file, int line, + const char *expr, ...); +#endif + +/** + * Fail the test if expression is false + * + * @param expr expression to evaluate + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert(expr) ck_assert_msg(expr, NULL) + +/* The space before the comma sign before ## is essential to be compatible + with gcc 2.95.3 and earlier. +*/ +/** + * Fail the test if the expression is false; print message on failure + * + * @param expr expression to evaluate + * @param ... message to print (in printf format) if expression is false + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert_msg(expr, ...) \ + (expr) ? \ + _mark_point(__FILE__, __LINE__) : \ + _ck_assert_failed(__FILE__, __LINE__, "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL) + +/** + * Unconditionally fail the test + * + * @note Once called, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_abort() ck_abort_msg(NULL) +/** + * Unconditionally fail the test; print a message + * + * @param ... message to print (in printf format) + * + * @note Once called, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_abort_msg(...) _ck_assert_failed(__FILE__, __LINE__, "Failed" , ## __VA_ARGS__, NULL) + +/* Signed and unsigned integer comparison macros with improved output compared to ck_assert(). */ +/* OP may be any comparison operator. */ +#define _ck_assert_int(X, OP, Y) do { \ + gint64 _ck_x = (X); \ + gint64 _ck_y = (Y); \ + ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: " \ + "%s==%" G_GINT64_FORMAT ", %s==%" G_GINT64_FORMAT, #X#OP#Y, #X, _ck_x, #Y, _ck_y); \ +} while (0) + +/** + * Check two signed integers to determine if X==Y + * + * If not X==Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y) +/** + * Check two signed integers to determine if X!=Y + * + * If not X!=Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert_int_ne(X, Y) _ck_assert_int(X, !=, Y) +/** + * Check two signed integers to determine if XY + * + * If not X>Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_int_gt(X, Y) _ck_assert_int(X, >, Y) +/** + * Check two signed integers to determine if X>=Y + * + * If not X>=Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_int_ge(X, Y) _ck_assert_int(X, >=, Y) + +#define _ck_assert_uint(X, OP, Y) do { \ + guint64 _ck_x = (X); \ + guint64 _ck_y = (Y); \ + ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: " \ + "%s==%" G_GUINT64_FORMAT ", %s==%" G_GUINT64_FORMAT, #X#OP#Y, #X, _ck_x, #Y, _ck_y); \ +} while (0) +/** + * Check two unsigned integers to determine if X==Y + * + * If not X==Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_uint_eq(X, Y) _ck_assert_uint(X, ==, Y) +/** + * Check two unsigned integers to determine if X!=Y + * + * If not X!=Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_uint_ne(X, Y) _ck_assert_uint(X, !=, Y) +/** + * Check two unsigned integers to determine if XY + * + * If not X>Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_uint_gt(X, Y) _ck_assert_uint(X, >, Y) +/** + * Check two unsigned integers to determine if X>=Y + * + * If not X>=Y, the test fails. + * + * @param X signed integer + * @param Y signed integer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_uint_ge(X, Y) _ck_assert_uint(X, >=, Y) + +/* String comparison macros with improved output compared to ck_assert() */ +/* OP might be any operator that can be used in '0 OP strcmp(X,Y)' comparison */ +/* The x and y parameter swap in strcmp() is needed to handle >, >=, <, <= operators */ +#define _ck_assert_str(X, OP, Y) do { \ + const char* _ck_x = (X); \ + const char* _ck_y = (Y); \ + ck_assert_msg(0 OP strcmp(_ck_y, _ck_x), \ + "Assertion '%s' failed: %s==\"%s\", %s==\"%s\"", #X#OP#Y, #X, _ck_x, #Y, _ck_y); \ +} while (0) +/** + * Check two strings to determine if 0==strcmp(X,Y) + * + * If not 0==strcmp(X,Y), the test fails. + * + * @param X string + * @param Y string to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert_str_eq(X, Y) _ck_assert_str(X, ==, Y) +/** + * Check two strings to determine if 0!=strcmp(X,Y) + * + * If not 0!=strcmp(X,Y), the test fails. + * + * @param X string + * @param Y string to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.6 + */ +#define ck_assert_str_ne(X, Y) _ck_assert_str(X, !=, Y) +/** + * Check two strings to determine if 00) + * + * If not 0=0) + * + * If not 0<=strcmp(X,Y), the test fails. + * + * @param X string + * @param Y string to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_str_le(X, Y) _ck_assert_str(X, <=, Y) +/** + * Check two strings to determine if 00) + * + * If not 0, Y) +/** + * Check two strings to determine if 0>=strcmp(X,Y) (e.g. strcmp(X,Y)<=0) + * + * If not 0>=strcmp(X,Y), the test fails. + * + * @param X string + * @param Y string to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_str_ge(X, Y) _ck_assert_str(X, >=, Y) + +/* Pointer comparison macros with improved output compared to ck_assert(). */ +/* OP may only be == or != */ +#define _ck_assert_ptr(X, OP, Y) do { \ + const void* _ck_x = (X); \ + const void* _ck_y = (Y); \ + ck_assert_msg(_ck_x OP _ck_y, "Assertion '%s' failed: %s==%#x, %s==%#x", #X#OP#Y, #X, _ck_x, #Y, _ck_y); \ +} while (0) + +/** + * Check if two pointers are equal. + * + * If the two passed pointers are not equal, the test + * fails. + * + * @param X pointer + * @param Y pointer to compare against X + * + * @note If the check fails, the remaining of the test is aborted + * + * @since 0.9.10 + */ +#define ck_assert_ptr_eq(X, Y) _ck_assert_ptr(X, ==, Y) + +/** + * Check if two pointers are not. + * + * If the two passed pointers are equal, the test fails. + * + * @param X pointer + * @param Y pointer to compare against X + * + * @since 0.9.10 + */ +#define ck_assert_ptr_ne(X, Y) _ck_assert_ptr(X, !=, Y) + +/** + * Mark the last point reached in a unit test. + * + * If the test throws a signal or exits, the location noted with the + * failure is the last location of a ck_assert*() or ck_abort() call. + * Use mark_point() to record intermediate locations (useful for tracking down + * crashes or exits). + * + * @since 0.6.0 +*/ +#define mark_point() _mark_point(__FILE__,__LINE__) + +/* Non macro version of #mark_point */ +CK_DLL_EXP void CK_EXPORT _mark_point (const char *file, int line); + +/** + * Enum describing the possible results of a test + */ +enum test_result +{ + CK_TEST_RESULT_INVALID, /**< Default value; should not encounter this */ + CK_PASS, /**< Test passed */ + CK_FAILURE, /**< Test completed but failed */ + CK_ERROR /**< Test failed to complete + (unexpected signal or non-zero early exit) */ +}; + +/** + * Enum specifying the verbosity of output a SRunner should produce + */ +enum print_output +{ + CK_SILENT, /**< No output */ + CK_MINIMAL, /**< Only summary output */ + CK_NORMAL, /**< All failed tests */ + CK_VERBOSE, /**< All tests */ + CK_ENV, /**< Look at environment var CK_VERBOSITY + for what verbosity to use, which can be + either "silent", "minimal", "normal", + or "verbose". If the environment variable + is not set, then CK_NORMAL will be used.*/ +#if @ENABLE_SUBUNIT@ + CK_SUBUNIT, /**< Run as a subunit child process */ +#endif + CK_LAST /**< Not a valid option */ +}; + +/** + * Holds state for a running of a test suite + */ +typedef struct SRunner SRunner; + +/** + * Opaque type for a test failure + */ +typedef struct TestResult TestResult; + +/** + * Enum representing the types of contexts for a test + */ +enum ck_result_ctx +{ + CK_CTX_INVALID, /**< Default value; should not encounter this */ + CK_CTX_SETUP, /**< Setup before a test */ + CK_CTX_TEST, /**< Body of test itself */ + CK_CTX_TEARDOWN /**< Teardown after a test */ +}; + +/** + * Retrieve type of result that the given test result represents. + * + * This is a member of test_result, and can represent a + * pass, failure, or error. + * + * @param tr test result to retrieve result from + * + * @return result of given test + * + * @since 0.6.0 + */ +CK_DLL_EXP int CK_EXPORT tr_rtype (TestResult * tr); + +/** + * Retrieve context in which the result occurred for the given test result. + * + * The types of contents include the test setup, teardown, or the + * body of the test itself. + * + * @param tr test result to retrieve context from + * + * @return context to which the given test result applies + * + * @since 0.8.0 + */ +CK_DLL_EXP enum ck_result_ctx CK_EXPORT tr_ctx (TestResult * tr); + +/** + * Retrieve failure message from test result, if applicable. + * + * @return pointer to a message, if one exists. NULL otherwise. + * + * @since 0.6.0 + */ +CK_DLL_EXP const char *CK_EXPORT tr_msg (TestResult * tr); + +/** + * Retrieve line number at which a failure occurred, if applicable. + * + * @return If the test resulted in a failure, returns the line number + * that the failure occurred on; otherwise returns -1. + * + * @since 0.6.0 + */ +CK_DLL_EXP int CK_EXPORT tr_lno (TestResult * tr); + +/** + * Retrieve file name at which a failure occurred, if applicable. + * + * @return If the test resulted in a failure, returns a string + * containing the name of the file where the failure + * occurred; otherwise returns NULL. + * + * @since 0.6.0 + */ +CK_DLL_EXP const char *CK_EXPORT tr_lfile (TestResult * tr); + +/** + * Retrieve test case name in which a failure occurred, if applicable. + * + * @return If the test resulted in a failure, returns a string + * containing the name of the test suite where the failure + * occurred; otherwise returns NULL. + * + * @since 0.6.0 + */ +CK_DLL_EXP const char *CK_EXPORT tr_tcname (TestResult * tr); + +/** + * Creates a suite runner for the given suite. + * + * Once created, additional suites can be added to the + * suite runner using srunner_add_suite(), and the suite runner can be + * run with srunner_run_all(). Once finished, the suite runner + * must be freed with srunner_free(). + * + * @param s suite to generate a suite runner for + * + * @return suite runner for the given suite + * + * @since 0.6.0 + */ +CK_DLL_EXP SRunner *CK_EXPORT srunner_create (Suite * s); + +/** + * Add an additional suite to a suite runner. + * + * The first suite in a suite runner is always added in srunner_create(). + * This call adds additional suites to a suite runner. + * + * @param sr suite runner to add the given suite + * @param s suite to add to the given suite runner + * + * @since 0.7.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_add_suite (SRunner * sr, Suite * s); + +/** + * Frees a suite runner, including all contained suite and test cases. + * + * This call is responsible for freeing all resources related to a + * suite runner and all contained suites and test cases. Suite and + * test cases need not be freed individually, as this call handles that. + * + * @param sr suite runner to free + * + * @since 0.6.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_free (SRunner * sr); + +/** + * Runs a suite runner and all contained suite, printing results to + * stdout as specified by the print_mode. + * + * In addition to running all suites, if the suite runner has been + * configured to output to a log, that is also performed. + * + * Note that if the CK_RUN_CASE, CK_RUN_SUITE, CK_INCLUDE_TAGS and/or + * CK_EXCLUDE_TAGS environment variables are defined, then only the + * named suites or test cases will run. + * + * @param sr suite runner to run all suites from + * @param print_mode the verbosity in which to report results to stdout + * + * @since 0.6.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_run_all (SRunner * sr, + enum print_output print_mode); + +/** + * Run a specific suite or test case from a suite runner, printing results + * to stdout as specified by the print_mode. + * + * In addition to running any applicable suites or test cases, if the + * suite runner has been configured to output to a log, that is also + * performed. + * + * Note that if the sname and tcname parameters are passed as null + * then the function will fallback to using the environment variables + * CK_RUN_SUITE and CK_RUN_CASE respectively in order to select the + * suite/cases. + * + * Similarly if the CK_INCLUDE_TAGS and/or CK_EXCLUDE_TAGS environment + * variables are defined then these will further filter the test cases + * (see srunner_run_tagged, below). + * + * @param sr suite runner where the given suite or test case must be + * @param sname suite name to run. A NULL means use the value of the + * environment variable CK_RUN_SUITE if set, otherwise run "any/every + * suite". + * @param tcname test case name to run. A NULL means use the value of + * the environment variable CK_RUN_CASE if set, otherwise run + * "any/every case". + * @param print_mode the verbosity in which to report results to stdout + * + * @since 0.9.9 + */ +CK_DLL_EXP void CK_EXPORT srunner_run (SRunner * sr, const char *sname, + const char *tcname, enum print_output print_mode); + + +/** + * Run a specific suite or test case or testcases with specific tags + * from a suite runner, printing results to stdout as specified by the + * print_mode. + * + * In addition to running any applicable suites or test cases, if the + * suite runner has been configured to output to a log, that is also + * performed. + * + * Note that if sname, tcname, include_tags, exclude_tags parameters + * are passed as NULL then if the environment variables CK_RUN_SUITE, + * CK_RUN_CASE, CK_INCLUDE_TAGS, CK_EXCLUDE_TAGS are defined then these + * values will be used instead. + * + * @param sr suite runner where the given suite or test case must be + * @param sname suite name to run. A NULL means use the value of the + * environment variable CK_RUN_SUITE if set, otherwise run "any/every + * suite". + * @param tcname test case name to run. A NULL means use the value of + * the environment variable CK_RUN_CASE if set, otherwise run + * "any/every case". + * @param include_tags space separate list of tags. Only run test + * cases that share one of these tags. A NULL means use the value of + * the environment variable CK_INCLUDE_TAGS if set, otherwise run + * "any/every test case". + * @param exclude_tags space separate list of tags. Only run test + * cases that do not share one of these tags even if they are selected + * by an included tag. A NULL means use the value of the environment + * variable CK_EXCLUDE_TAGS if set, otherwise run "any/every test + * case". + * @param print_mode the verbosity in which to report results to stdout + * + * @since 0.11.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_run_tagged (SRunner * sr, const char *sname, + const char *tcname, + const char *include_tags, + const char *exclude_tags, enum print_output print_mode); + +/** + * Retrieve the number of failed tests executed by a suite runner. + * + * This value represents both test failures and errors. + * + * @param sr suite runner to query for all failed tests + * + * @return number of test failures and errors found by the suite runner + * + * @since 0.6.1 + */ +CK_DLL_EXP int CK_EXPORT srunner_ntests_failed (SRunner * sr); + +/** + * Retrieve the total number of tests run by a suite runner. + * + * @param sr suite runner to query for all tests run + * + * @return number of all tests run by the suite runner + * + * @since 0.6.1 + */ +CK_DLL_EXP int CK_EXPORT srunner_ntests_run (SRunner * sr); + +/** + * Return an array of results for all failures found by a suite runner. + * + * Number of results is equal to srunner_nfailed_tests(). + * + * Information about individual results can be queried using: + * tr_rtype(), tr_ctx(), tr_msg(), tr_lno(), tr_lfile(), and tr_tcname(). + * + * Memory is malloc'ed and must be freed; however free the entire structure + * instead of individual test cases. + * + * @param sr suite runner to retrieve results from + * + * @return array of TestResult objects + * + * @since 0.6.0 + */ +CK_DLL_EXP TestResult **CK_EXPORT srunner_failures (SRunner * sr); + +/** + * Return an array of results for all tests run by a suite runner. + * + * Number of results is equal to srunner_ntests_run(), and excludes + * failures due to setup function failure. + * + * Information about individual results can be queried using: + * tr_rtype(), tr_ctx(), tr_msg(), tr_lno(), tr_lfile(), and tr_tcname(). + * + * Memory is malloc'ed and must be freed; however free the entire structure + * instead of individual test cases. + * + * @param sr suite runner to retrieve results from + * + * @return array of TestResult objects + * + * @since 0.6.1 +*/ +CK_DLL_EXP TestResult **CK_EXPORT srunner_results (SRunner * sr); + +/** + * Print the results contained in an SRunner to stdout. + * + * @param sr suite runner to print results for to stdout + * @param print_mode the print_output (verbosity) to use to report + * the result + * + * @since 0.7.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_print (SRunner * sr, + enum print_output print_mode); + +/** + * Set the suite runner to output the result in log format to the + * given file. + * + * Note: log file setting is an initialize only operation -- it should + * be done immediately after SRunner creation, and the log file can't be + * changed after being set. + * + * This setting does not conflict with the other log output types; + * all logging types can occur concurrently if configured. + * + * @param sr suite runner to log results of in log format + * @param fname file name to output log results to + * + * @since 0.7.1 +*/ +CK_DLL_EXP void CK_EXPORT srunner_set_log (SRunner * sr, const char *fname); + +/** + * Checks if the suite runner is assigned a file for log output. + * + * @param sr suite runner to check + * + * @return 1 iff the suite runner currently is configured to output + * in log format; 0 otherwise + * + * @since 0.7.1 + */ +CK_DLL_EXP int CK_EXPORT srunner_has_log (SRunner * sr); + +/** + * Retrieves the name of the currently assigned file + * for log output, if any exists. + * + * @return the name of the log file, or NULL if none is configured + * + * @since 0.7.1 + */ +CK_DLL_EXP const char *CK_EXPORT srunner_log_fname (SRunner * sr); + +/** + * Set the suite runner to output the result in XML format to the + * given file. + * + * Note: XML file setting is an initialize only operation -- it should + * be done immediately after SRunner creation, and the XML file can't be + * changed after being set. + * + * This setting does not conflict with the other log output types; + * all logging types can occur concurrently if configured. + * + * @param sr suite runner to log results of in XML format + * @param fname file name to output XML results to + * + * @since 0.9.1 +*/ +CK_DLL_EXP void CK_EXPORT srunner_set_xml (SRunner * sr, const char *fname); + +/** + * Checks if the suite runner is assigned a file for XML output. + * + * @param sr suite runner to check + * + * @return 1 iff the suite runner currently is configured to output + * in XML format; 0 otherwise + * + * @since 0.9.1 + */ +CK_DLL_EXP int CK_EXPORT srunner_has_xml (SRunner * sr); + +/** + * Retrieves the name of the currently assigned file + * for XML output, if any exists. + * + * @return the name of the XML file, or NULL if none is configured + * + * @since 0.9.1 + */ +CK_DLL_EXP const char *CK_EXPORT srunner_xml_fname (SRunner * sr); + +/** + * Set the suite runner to output the result in TAP format to the + * given file. + * + * Note: TAP file setting is an initialize only operation -- it should + * be done immediately after SRunner creation, and the TAP file can't be + * changed after being set. + * + * This setting does not conflict with the other log output types; + * all logging types can occur concurrently if configured. + * + * @param sr suite runner to log results of in TAP format + * @param fname file name to output TAP results to + * + * @since 0.9.12 +*/ +CK_DLL_EXP void CK_EXPORT srunner_set_tap (SRunner * sr, const char *fname); + +/** + * Checks if the suite runner is assigned a file for TAP output. + * + * @param sr suite runner to check + * + * @return 1 iff the suite runner currently is configured to output + * in TAP format; 0 otherwise + * + * @since 0.9.12 + */ +CK_DLL_EXP int CK_EXPORT srunner_has_tap (SRunner * sr); + +/** + * Retrieves the name of the currently assigned file + * for TAP output, if any exists. + * + * @return the name of the TAP file, or NULL if none is configured + * + * @since 0.9.12 + */ +CK_DLL_EXP const char *CK_EXPORT srunner_tap_fname (SRunner * sr); + +/** + * Enum describing the current fork usage. + */ +enum fork_status +{ + CK_FORK_GETENV, /**< look in the environment for CK_FORK */ + CK_FORK, /**< call fork to run tests */ + CK_NOFORK /**< don't call fork */ +}; + +/** + * Retrieve the current fork status for the given suite runner + * + * @param sr suite runner to check fork status of + * + * @since 0.8.0 + */ +CK_DLL_EXP enum fork_status CK_EXPORT srunner_fork_status (SRunner * sr); + +/** + * Set the fork status for a given suite runner. + * + * The default fork status is CK_FORK_GETENV, which will look + * for the CK_FORK environment variable, which can be set to + * "yes" or "no". If the environment variable is not present, + * CK_FORK will be used if fork() is available on the system, + * otherwise CK_NOFORK is used. + * + * If set to CK_FORK or CK_NOFORK, the environment variable + * if defined is ignored. + * + * If Check is compiled without support for fork(), attempting + * to set the status to CK_FORK is ignored. + * + * @param sr suite runner to assign the fork status to + * @param fstat fork status to assign + * + * @since 0.8.0 + */ +CK_DLL_EXP void CK_EXPORT srunner_set_fork_status (SRunner * sr, + enum fork_status fstat); + +/** + * Invoke fork() during a test and assign the child to the same + * process group that the rest of the test case uses. + * + * One can invoke fork() directly during a test; however doing so + * may not guarantee that any children processes are destroyed once + * the test finishes. Once a test has completed, all processes in + * the process group will be killed; using this wrapper will prevent + * orphan processes. + * + * If Check is compiled without fork() support this call simply + * return -1 and does nothing. + * + * @return On success, the PID of the child process is returned in + * the parent, and 0 is returned in the child. On failure, + * a value of -1 is returned to the parent process and no + * child process is created. + * + * @since 0.9.3 + */ +#if !defined(_MSC_VER) +CK_DLL_EXP pid_t CK_EXPORT check_fork (void); +#endif + +/** + * Wait for the pid and exit. + * + * This is to be used in conjunction with check_fork(). When called, + * will wait for the given process to terminate. If the process + * exited without error, exit(EXIT_SUCCESS) is invoked; otherwise + * exit(EXIT_FAILURE) is invoked. + * + * If Check is compiled without support for fork(), this invokes + * exit(EXIT_FAILURE). + * + * @param pid process to wait for, created by check_fork() + * + * @since 0.9.3 + */ +#if !defined(_MSC_VER) +CK_DLL_EXP void CK_EXPORT +check_waitpid_and_exit (pid_t pid) + CK_ATTRIBUTE_NORETURN; +#endif + +#ifdef __cplusplus +CK_CPPEND +#endif +#endif /* CHECK_H */ diff --git a/libs/gst/check/libcheck/check_error.c b/libs/gst/check/libcheck/check_error.c new file mode 100644 index 0000000..8f293aa --- /dev/null +++ b/libs/gst/check/libcheck/check_error.c @@ -0,0 +1,79 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include +#include +#include +#include + +#include "check_error.h" + +/** + * Storage for setjmp/longjmp context information used in NOFORK mode + */ +jmp_buf error_jmp_buffer; + + +/* FIXME: including a colon at the end is a bad way to indicate an error */ +void +eprintf (const char *fmt, const char *file, int line, ...) +{ + va_list args; + + fflush (stderr); + + fprintf (stderr, "%s:%d: ", file, line); + va_start (args, line); + vfprintf (stderr, fmt, args); + va_end (args); + + /*include system error information if format ends in colon */ + if (fmt[0] != '\0' && fmt[strlen (fmt) - 1] == ':') + fprintf (stderr, " %s", strerror (errno)); + fprintf (stderr, "\n"); + + exit (2); +} + +void * +emalloc (size_t n) +{ + void *p; + + p = malloc (n); + if (p == NULL) + eprintf ("malloc of %u bytes failed:", __FILE__, __LINE__ - 2, n); + return p; +} + +void * +erealloc (void *ptr, size_t n) +{ + void *p; + + p = realloc (ptr, n); + if (p == NULL) + eprintf ("realloc of %u bytes failed:", __FILE__, __LINE__ - 2, n); + return p; +} diff --git a/libs/gst/check/libcheck/check_error.h b/libs/gst/check/libcheck/check_error.h new file mode 100644 index 0000000..f325fc6 --- /dev/null +++ b/libs/gst/check/libcheck/check_error.h @@ -0,0 +1,40 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef ERROR_H +#define ERROR_H + +#include "libcompat/libcompat.h" +#include + +extern jmp_buf error_jmp_buffer; + +/* Include stdlib.h beforehand */ + +/* Print error message and die + If fmt ends in colon, include system error information */ +void +eprintf (const char *fmt, const char *file, int line, ...) + CK_ATTRIBUTE_NORETURN; +/* malloc or die */ + void *emalloc (size_t n); + void *erealloc (void *, size_t n); + +#endif /*ERROR_H */ diff --git a/libs/gst/check/libcheck/check_impl.h b/libs/gst/check/libcheck/check_impl.h new file mode 100644 index 0000000..16adfc7 --- /dev/null +++ b/libs/gst/check/libcheck/check_impl.h @@ -0,0 +1,141 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_IMPL_H +#define CHECK_IMPL_H + +/* This header should be included by any module that needs + to know the implementation details of the check structures + Include stdio.h, time.h, & list.h before this header +*/ + +#define US_PER_SEC 1000000 +#define NANOS_PER_SECONDS 1000000000 + +/** calculate the difference in useconds out of two "struct timespec"s */ +#define DIFF_IN_USEC(begin, end) \ + ( (((end).tv_sec - (begin).tv_sec) * US_PER_SEC) + \ + ((end).tv_nsec/1000) - ((begin).tv_nsec/1000) ) + +typedef struct TF +{ + TFun fn; + int loop_start; + int loop_end; + const char *name; + int signal; + signed char allowed_exit_value; +} TF; + +struct Suite +{ + const char *name; + List *tclst; /* List of test cases */ +}; + +typedef struct Fixture +{ + int ischecked; + SFun fun; +} Fixture; + +struct TCase +{ + const char *name; + struct timespec timeout; + List *tflst; /* list of test functions */ + List *unch_sflst; + List *unch_tflst; + List *ch_sflst; + List *ch_tflst; + List *tags; +}; + +typedef struct TestStats +{ + int n_checked; + int n_failed; + int n_errors; +} TestStats; + +struct TestResult +{ + enum test_result rtype; /* Type of result */ + enum ck_result_ctx ctx; /* When the result occurred */ + char *file; /* File where the test occured */ + int line; /* Line number where the test occurred */ + int iter; /* The iteration value for looping tests */ + int duration; /* duration of this test in microseconds */ + const char *tcname; /* Test case that generated the result */ + const char *tname; /* Test that generated the result */ + char *msg; /* Failure message */ +}; + +TestResult *tr_create (void); +void tr_reset (TestResult * tr); +void tr_free (TestResult * tr); + +enum cl_event +{ + CLINITLOG_SR, /* Initialize log file */ + CLENDLOG_SR, /* Tests are complete */ + CLSTART_SR, /* Suite runner start */ + CLSTART_S, /* Suite start */ + CLEND_SR, /* Suite runner end */ + CLEND_S, /* Suite end */ + CLSTART_T, /* A test case is about to run */ + CLEND_T /* Test case end */ +}; + +typedef void (*LFun) (SRunner *, FILE *, enum print_output, + void *, enum cl_event); + +typedef struct Log +{ + FILE *lfile; + LFun lfun; + int close; + enum print_output mode; +} Log; + +struct SRunner +{ + List *slst; /* List of Suite objects */ + TestStats *stats; /* Run statistics */ + List *resultlst; /* List of unit test results */ + const char *log_fname; /* name of log file */ + const char *xml_fname; /* name of xml output file */ + const char *tap_fname; /* name of tap output file */ + List *loglst; /* list of Log objects */ + enum fork_status fstat; /* controls if suites are forked or not + NOTE: Don't use this value directly, + instead use srunner_fork_status */ +}; + + +void set_fork_status (enum fork_status fstat); +enum fork_status cur_fork_status (void); + +clockid_t check_get_clockid (void); + +unsigned int tcase_matching_tag (TCase * tc, List * check_for); +List *tag_string_to_list (const char *tags_string); + +#endif /* CHECK_IMPL_H */ diff --git a/libs/gst/check/libcheck/check_list.c b/libs/gst/check/libcheck/check_list.c new file mode 100644 index 0000000..610a125 --- /dev/null +++ b/libs/gst/check/libcheck/check_list.c @@ -0,0 +1,164 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include + +#include "check_list.h" +#include "check_error.h" + + +enum +{ + LINIT = 1, + LGROW = 2 +}; + +struct List +{ + unsigned int n_elts; + unsigned int max_elts; + int current; /* pointer to the current node */ + int last; /* pointer to the node before END */ + void **data; +}; + +static void +maybe_grow (List * lp) +{ + if (lp->n_elts >= lp->max_elts) { + lp->max_elts *= LGROW; + lp->data = + (void **) erealloc (lp->data, lp->max_elts * sizeof (lp->data[0])); + } +} + +List * +check_list_create (void) +{ + List *lp; + + lp = (List *) emalloc (sizeof (List)); + lp->n_elts = 0; + lp->max_elts = LINIT; + lp->data = (void **) emalloc (sizeof (lp->data[0]) * LINIT); + lp->current = lp->last = -1; + return lp; +} + +void +check_list_add_front (List * lp, void *val) +{ + if (lp == NULL) + return; + maybe_grow (lp); + memmove (lp->data + 1, lp->data, lp->n_elts * sizeof lp->data[0]); + lp->last++; + lp->n_elts++; + lp->current = 0; + lp->data[lp->current] = val; +} + +void +check_list_add_end (List * lp, void *val) +{ + if (lp == NULL) + return; + maybe_grow (lp); + lp->last++; + lp->n_elts++; + lp->current = lp->last; + lp->data[lp->current] = val; +} + +int +check_list_at_end (List * lp) +{ + if (lp->current == -1) + return 1; + else + return (lp->current > lp->last); +} + +void +check_list_front (List * lp) +{ + if (lp->current == -1) + return; + lp->current = 0; +} + + +void +check_list_free (List * lp) +{ + if (lp == NULL) + return; + + free (lp->data); + free (lp); +} + +void * +check_list_val (List * lp) +{ + if (lp == NULL) + return NULL; + if (lp->current == -1 || lp->current > lp->last) + return NULL; + + return lp->data[lp->current]; +} + +void +check_list_advance (List * lp) +{ + if (lp == NULL) + return; + if (check_list_at_end (lp)) + return; + lp->current++; +} + + +void +check_list_apply (List * lp, void (*fp) (void *)) +{ + if (lp == NULL || fp == NULL) + return; + + for (check_list_front (lp); !check_list_at_end (lp); check_list_advance (lp)) + fp (check_list_val (lp)); + +} + +bool +check_list_contains (List * lp, void *val) +{ + for (check_list_front (lp); !check_list_at_end (lp); check_list_advance (lp)) { + if (check_list_val (lp) == val) { + return true; + } + } + + return false; +} diff --git a/libs/gst/check/libcheck/check_list.h b/libs/gst/check/libcheck/check_list.h new file mode 100644 index 0000000..005361e --- /dev/null +++ b/libs/gst/check/libcheck/check_list.h @@ -0,0 +1,61 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_LIST_H +#define CHECK_LIST_H + +#include + +typedef struct List List; + +/* Create an empty list */ +List *check_list_create (void); + +/* Is list at end? */ +int check_list_at_end (List * lp); + +/* Position list at front */ +void check_list_front (List * lp); + +/* Add a value to the front of the list, + positioning newly added value as current value. + More expensive than list_add_end, as it uses memmove. */ +void check_list_add_front (List * lp, void *val); + +/* Add a value to the end of the list, + positioning newly added value as current value */ +void check_list_add_end (List * lp, void *val); + +/* Give the value of the current node */ +void *check_list_val (List * lp); + +/* Position the list at the next node */ +void check_list_advance (List * lp); + +/* Free a list, but don't free values */ +void check_list_free (List * lp); + +void check_list_apply (List * lp, void (*fp) (void *)); + +/* Return true if the list contains the value, false otherwise */ +bool check_list_contains (List * lp, void *val); + + +#endif /* CHECK_LIST_H */ diff --git a/libs/gst/check/libcheck/check_log.c b/libs/gst/check/libcheck/check_log.c new file mode 100644 index 0000000..bb81d6b --- /dev/null +++ b/libs/gst/check/libcheck/check_log.c @@ -0,0 +1,548 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include +#if ENABLE_SUBUNIT +#include +#endif + +#include "check_error.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_log.h" +#include "check_print.h" +#include "check_str.h" + +/* + * If a log file is specified to be "-", then instead of + * opening a file the log output is printed to stdout. + */ +#define STDOUT_OVERRIDE_LOG_FILE_NAME "-" + +static void srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt); + +void +srunner_set_log (SRunner * sr, const char *fname) +{ + if (sr->log_fname) + return; + sr->log_fname = fname; +} + +int +srunner_has_log (SRunner * sr) +{ + return srunner_log_fname (sr) != NULL; +} + +const char * +srunner_log_fname (SRunner * sr) +{ + /* check if log filename have been set explicitly */ + if (sr->log_fname != NULL) + return sr->log_fname; + + return getenv ("CK_LOG_FILE_NAME"); +} + + +void +srunner_set_xml (SRunner * sr, const char *fname) +{ + if (sr->xml_fname) + return; + sr->xml_fname = fname; +} + +int +srunner_has_xml (SRunner * sr) +{ + return srunner_xml_fname (sr) != NULL; +} + +const char * +srunner_xml_fname (SRunner * sr) +{ + /* check if XML log filename have been set explicitly */ + if (sr->xml_fname != NULL) { + return sr->xml_fname; + } + + return getenv ("CK_XML_LOG_FILE_NAME"); +} + +void +srunner_set_tap (SRunner * sr, const char *fname) +{ + if (sr->tap_fname) + return; + sr->tap_fname = fname; +} + +int +srunner_has_tap (SRunner * sr) +{ + return srunner_tap_fname (sr) != NULL; +} + +const char * +srunner_tap_fname (SRunner * sr) +{ + /* check if tap log filename have been set explicitly */ + if (sr->tap_fname != NULL) { + return sr->tap_fname; + } + + return getenv ("CK_TAP_LOG_FILE_NAME"); +} + +void +srunner_register_lfun (SRunner * sr, FILE * lfile, int close, + LFun lfun, enum print_output printmode) +{ + Log *l = (Log *) emalloc (sizeof (Log)); + + if (printmode == CK_ENV) { + printmode = get_env_printmode (); + } + + l->lfile = lfile; + l->lfun = lfun; + l->close = close; + l->mode = printmode; + check_list_add_end (sr->loglst, l); + return; +} + +void +log_srunner_start (SRunner * sr) +{ + srunner_send_evt (sr, NULL, CLSTART_SR); +} + +void +log_srunner_end (SRunner * sr) +{ + srunner_send_evt (sr, NULL, CLEND_SR); +} + +void +log_suite_start (SRunner * sr, Suite * s) +{ + srunner_send_evt (sr, s, CLSTART_S); +} + +void +log_suite_end (SRunner * sr, Suite * s) +{ + srunner_send_evt (sr, s, CLEND_S); +} + +void +log_test_start (SRunner * sr, TCase * tc, TF * tfun) +{ + char buffer[100]; + + snprintf (buffer, 99, "%s:%s", tc->name, tfun->name); + srunner_send_evt (sr, buffer, CLSTART_T); +} + +void +log_test_end (SRunner * sr, TestResult * tr) +{ + srunner_send_evt (sr, tr, CLEND_T); +} + +static void +srunner_send_evt (SRunner * sr, void *obj, enum cl_event evt) +{ + List *l; + Log *lg; + + l = sr->loglst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + lg = (Log *) check_list_val (l); + fflush (lg->lfile); + lg->lfun (sr, lg->lfile, lg->mode, obj, evt); + fflush (lg->lfile); + } +} + +void +stdout_lfun (SRunner * sr, FILE * file, enum print_output printmode, + void *obj, enum cl_event evt) +{ + Suite *s; + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + if (printmode > CK_SILENT) { + fprintf (file, "Running suite(s):"); + } + break; + case CLSTART_S: + s = (Suite *) obj; + if (printmode > CK_SILENT) { + fprintf (file, " %s\n", s->name); + } + break; + case CLEND_SR: + if (printmode > CK_SILENT) { + /* we don't want a newline before printing here, newlines should + come after printing a string, not before. it's better to add + the newline above in CLSTART_S. + */ + srunner_fprint (file, sr, printmode); + } + break; + case CLEND_S: + break; + case CLSTART_T: + break; + case CLEND_T: + break; + default: + eprintf ("Bad event type received in stdout_lfun", __FILE__, __LINE__); + } + + +} + +void +lfile_lfun (SRunner * sr, FILE * file, + enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj, + enum cl_event evt) +{ + TestResult *tr; + Suite *s; + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + break; + case CLSTART_S: + s = (Suite *) obj; + fprintf (file, "Running suite %s\n", s->name); + break; + case CLEND_SR: + fprintf (file, "Results for all suites run:\n"); + srunner_fprint (file, sr, CK_MINIMAL); + break; + case CLEND_S: + break; + case CLSTART_T: + break; + case CLEND_T: + tr = (TestResult *) obj; + tr_fprint (file, tr, CK_VERBOSE); + break; + default: + eprintf ("Bad event type received in lfile_lfun", __FILE__, __LINE__); + } + + +} + +void +xml_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file, + enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj, + enum cl_event evt) +{ + TestResult *tr; + Suite *s; + static struct timespec ts_start = { 0, 0 }; + static char t[sizeof "yyyy-mm-dd hh:mm:ss"] = { 0 }; + + if (t[0] == 0) { + struct timeval inittv; + struct tm now; + + gettimeofday (&inittv, NULL); + clock_gettime (check_get_clockid (), &ts_start); + if (localtime_r ((const time_t *) &(inittv.tv_sec), &now) != NULL) { + strftime (t, sizeof ("yyyy-mm-dd hh:mm:ss"), "%Y-%m-%d %H:%M:%S", &now); + } + } + + switch (evt) { + case CLINITLOG_SR: + fprintf (file, "\n"); + fprintf (file, + "\n"); + fprintf (file, + "\n"); + fprintf (file, " %s\n", t); + break; + case CLENDLOG_SR: + { + struct timespec ts_end = { 0, 0 }; + unsigned long duration; + + /* calculate time the test were running */ + clock_gettime (check_get_clockid (), &ts_end); + duration = (unsigned long) DIFF_IN_USEC (ts_start, ts_end); + fprintf (file, " %lu.%06lu\n", + duration / US_PER_SEC, duration % US_PER_SEC); + fprintf (file, "\n"); + } + break; + case CLSTART_SR: + break; + case CLSTART_S: + s = (Suite *) obj; + fprintf (file, " \n"); + fprintf (file, " "); + fprint_xml_esc (file, s->name); + fprintf (file, "\n"); + break; + case CLEND_SR: + break; + case CLEND_S: + fprintf (file, " \n"); + break; + case CLSTART_T: + break; + case CLEND_T: + tr = (TestResult *) obj; + tr_xmlprint (file, tr, CK_VERBOSE); + break; + default: + eprintf ("Bad event type received in xml_lfun", __FILE__, __LINE__); + } + +} + +void +tap_lfun (SRunner * sr CK_ATTRIBUTE_UNUSED, FILE * file, + enum print_output printmode CK_ATTRIBUTE_UNUSED, void *obj, + enum cl_event evt) +{ + TestResult *tr; + + static int num_tests_run = 0; + + switch (evt) { + case CLINITLOG_SR: + /* As this is a new log file, reset the number of tests executed */ + num_tests_run = 0; + break; + case CLENDLOG_SR: + /* Output the test plan as the last line */ + fprintf (file, "1..%d\n", num_tests_run); + fflush (file); + break; + case CLSTART_SR: + break; + case CLSTART_S: + break; + case CLEND_SR: + break; + case CLEND_S: + break; + case CLSTART_T: + break; + case CLEND_T: + /* Print the test result to the tap file */ + num_tests_run += 1; + tr = (TestResult *) obj; + fprintf (file, "%s %d - %s:%s:%s: %s\n", + tr->rtype == CK_PASS ? "ok" : "not ok", num_tests_run, + tr->file, tr->tcname, tr->tname, tr->msg); + fflush (file); + break; + default: + eprintf ("Bad event type received in tap_lfun", __FILE__, __LINE__); + } +} + +#if ENABLE_SUBUNIT +void +subunit_lfun (SRunner * sr, FILE * file, enum print_output printmode, + void *obj, enum cl_event evt) +{ + TestResult *tr; + char const *name; + + /* assert(printmode == CK_SUBUNIT); */ + + switch (evt) { + case CLINITLOG_SR: + break; + case CLENDLOG_SR: + break; + case CLSTART_SR: + break; + case CLSTART_S: + break; + case CLEND_SR: + if (printmode > CK_SILENT) { + fprintf (file, "\n"); + srunner_fprint (file, sr, printmode); + } + break; + case CLEND_S: + break; + case CLSTART_T: + name = (const char *) obj; + subunit_test_start (name); + break; + case CLEND_T: + tr = (TestResult *) obj; + { + char *name = ck_strdup_printf ("%s:%s", tr->tcname, tr->tname); + char *msg = tr_short_str (tr); + + switch (tr->rtype) { + case CK_PASS: + subunit_test_pass (name); + break; + case CK_FAILURE: + subunit_test_fail (name, msg); + break; + case CK_ERROR: + subunit_test_error (name, msg); + break; + case CK_TEST_RESULT_INVALID: + default: + eprintf ("Bad result type in subunit_lfun", __FILE__, __LINE__); + free (name); + free (msg); + } + } + break; + default: + eprintf ("Bad event type received in subunit_lfun", __FILE__, __LINE__); + } +} +#endif + +static FILE * +srunner_open_file (const char *filename) +{ + FILE *f = NULL; + + if (strcmp (filename, STDOUT_OVERRIDE_LOG_FILE_NAME) == 0) { + f = stdout; + } else { + f = fopen (filename, "w"); + if (f == NULL) { + eprintf ("Error in call to fopen while opening file %s:", __FILE__, + __LINE__ - 2, filename); + } + } + return f; +} + +FILE * +srunner_open_lfile (SRunner * sr) +{ + FILE *f = NULL; + + if (srunner_has_log (sr)) { + f = srunner_open_file (srunner_log_fname (sr)); + } + return f; +} + +FILE * +srunner_open_xmlfile (SRunner * sr) +{ + FILE *f = NULL; + + if (srunner_has_xml (sr)) { + f = srunner_open_file (srunner_xml_fname (sr)); + } + return f; +} + +FILE * +srunner_open_tapfile (SRunner * sr) +{ + FILE *f = NULL; + + if (srunner_has_tap (sr)) { + f = srunner_open_file (srunner_tap_fname (sr)); + } + return f; +} + +void +srunner_init_logging (SRunner * sr, enum print_output print_mode) +{ + FILE *f; + + sr->loglst = check_list_create (); +#if ENABLE_SUBUNIT + if (print_mode != CK_SUBUNIT) +#endif + srunner_register_lfun (sr, stdout, 0, stdout_lfun, print_mode); +#if ENABLE_SUBUNIT + else + srunner_register_lfun (sr, stdout, 0, subunit_lfun, print_mode); +#endif + f = srunner_open_lfile (sr); + if (f) { + srunner_register_lfun (sr, f, f != stdout, lfile_lfun, print_mode); + } + f = srunner_open_xmlfile (sr); + if (f) { + srunner_register_lfun (sr, f, f != stdout, xml_lfun, print_mode); + } + f = srunner_open_tapfile (sr); + if (f) { + srunner_register_lfun (sr, f, f != stdout, tap_lfun, print_mode); + } + srunner_send_evt (sr, NULL, CLINITLOG_SR); +} + +void +srunner_end_logging (SRunner * sr) +{ + List *l; + int rval; + + srunner_send_evt (sr, NULL, CLENDLOG_SR); + + l = sr->loglst; + for (check_list_front (l); !check_list_at_end (l); check_list_advance (l)) { + Log *lg = (Log *) check_list_val (l); + + if (lg->close) { + rval = fclose (lg->lfile); + if (rval != 0) + eprintf ("Error in call to fclose while closing log file:", + __FILE__, __LINE__ - 2); + } + free (lg); + } + check_list_free (l); + sr->loglst = NULL; +} diff --git a/libs/gst/check/libcheck/check_log.h b/libs/gst/check/libcheck/check_log.h new file mode 100644 index 0000000..c1936f9 --- /dev/null +++ b/libs/gst/check/libcheck/check_log.h @@ -0,0 +1,55 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_LOG_H +#define CHECK_LOG_H + +void log_srunner_start (SRunner * sr); +void log_srunner_end (SRunner * sr); +void log_suite_start (SRunner * sr, Suite * s); +void log_suite_end (SRunner * sr, Suite * s); +void log_test_end (SRunner * sr, TestResult * tr); +void log_test_start (SRunner * sr, TCase * tc, TF * tfun); + +void stdout_lfun (SRunner * sr, FILE * file, enum print_output, + void *obj, enum cl_event evt); + +void lfile_lfun (SRunner * sr, FILE * file, enum print_output, + void *obj, enum cl_event evt); + +void xml_lfun (SRunner * sr, FILE * file, enum print_output, + void *obj, enum cl_event evt); + +void tap_lfun (SRunner * sr, FILE * file, enum print_output, + void *obj, enum cl_event evt); + +void subunit_lfun (SRunner * sr, FILE * file, enum print_output, + void *obj, enum cl_event evt); + +void srunner_register_lfun (SRunner * sr, FILE * lfile, int close, + LFun lfun, enum print_output); + +FILE *srunner_open_lfile (SRunner * sr); +FILE *srunner_open_xmlfile (SRunner * sr); +FILE *srunner_open_tapfile (SRunner * sr); +void srunner_init_logging (SRunner * sr, enum print_output print_mode); +void srunner_end_logging (SRunner * sr); + +#endif /* CHECK_LOG_H */ diff --git a/libs/gst/check/libcheck/check_msg.c b/libs/gst/check/libcheck/check_msg.c new file mode 100644 index 0000000..e862c5c --- /dev/null +++ b/libs/gst/check/libcheck/check_msg.c @@ -0,0 +1,315 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include +#include + +#include "check_error.h" +#include "internal-check.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_msg.h" +#include "check_pack.h" +#include "check_str.h" + + +/* 'Pipe' is implemented as a temporary file to overcome message + * volume limitations outlined in bug #482012. This scheme works well + * with the existing usage wherein the parent does not begin reading + * until the child has done writing and exited. + * + * Pipe life cycle: + * - The parent creates a tmpfile(). + * - The fork() call has the effect of duplicating the file descriptor + * and copying (on write) the FILE* data structures. + * - The child writes to the file, and its dup'ed file descriptor and + * data structures are cleaned up on child process exit. + * - Before reading, the parent rewind()'s the file to reset both + * FILE* and underlying file descriptor location data. + * - When finished, the parent fclose()'s the FILE*, deleting the + * temporary file, per tmpfile()'s semantics. + * + * This scheme may break down if the usage changes to asynchronous + * reading and writing. + */ + +static FILE *send_file1; +static char *send_file1_name; +static FILE *send_file2; +static char *send_file2_name; + +static FILE *get_pipe (void); +static void setup_pipe (void); +static void teardown_pipe (void); +static TestResult *construct_test_result (RcvMsg * rmsg, int waserror); +static void tr_set_loc_by_ctx (TestResult * tr, enum ck_result_ctx ctx, + RcvMsg * rmsg); +static FILE * +get_pipe (void) +{ + if (send_file2 != 0) { + return send_file2; + } + + if (send_file1 != 0) { + return send_file1; + } + + eprintf ("No messaging setup", __FILE__, __LINE__); + + return NULL; +} + +void +send_failure_info (const char *msg) +{ + FailMsg fmsg; + + fmsg.msg = strdup (msg); + ppack (get_pipe (), CK_MSG_FAIL, (CheckMsg *) & fmsg); + free (fmsg.msg); +} + +void +send_duration_info (int duration) +{ + DurationMsg dmsg; + + dmsg.duration = duration; + ppack (get_pipe (), CK_MSG_DURATION, (CheckMsg *) & dmsg); +} + +void +send_loc_info (const char *file, int line) +{ + LocMsg lmsg; + + lmsg.file = strdup (file); + lmsg.line = line; + ppack (get_pipe (), CK_MSG_LOC, (CheckMsg *) & lmsg); + free (lmsg.file); +} + +void +send_ctx_info (enum ck_result_ctx ctx) +{ + CtxMsg cmsg; + + cmsg.ctx = ctx; + ppack (get_pipe (), CK_MSG_CTX, (CheckMsg *) & cmsg); +} + +TestResult * +receive_test_result (int waserror) +{ + FILE *fp; + RcvMsg *rmsg; + TestResult *result; + + fp = get_pipe (); + if (fp == NULL) { + eprintf ("Error in call to get_pipe", __FILE__, __LINE__ - 2); + } + + rewind (fp); + rmsg = punpack (fp); + + if (rmsg == NULL) { + eprintf ("Error in call to punpack", __FILE__, __LINE__ - 4); + } + + teardown_pipe (); + setup_pipe (); + + result = construct_test_result (rmsg, waserror); + rcvmsg_free (rmsg); + return result; +} + +static void +tr_set_loc_by_ctx (TestResult * tr, enum ck_result_ctx ctx, RcvMsg * rmsg) +{ + if (ctx == CK_CTX_TEST) { + tr->file = rmsg->test_file; + tr->line = rmsg->test_line; + rmsg->test_file = NULL; + rmsg->test_line = -1; + } else { + tr->file = rmsg->fixture_file; + tr->line = rmsg->fixture_line; + rmsg->fixture_file = NULL; + rmsg->fixture_line = -1; + } +} + +static TestResult * +construct_test_result (RcvMsg * rmsg, int waserror) +{ + TestResult *tr; + + if (rmsg == NULL) + return NULL; + + tr = tr_create (); + + if (rmsg->msg != NULL || waserror) { + if (rmsg->failctx != CK_CTX_INVALID) { + tr->ctx = rmsg->failctx; + } else { + tr->ctx = rmsg->lastctx; + } + + tr->msg = rmsg->msg; + rmsg->msg = NULL; + tr_set_loc_by_ctx (tr, tr->ctx, rmsg); + } else if (rmsg->lastctx == CK_CTX_SETUP) { + tr->ctx = CK_CTX_SETUP; + tr->msg = NULL; + tr_set_loc_by_ctx (tr, CK_CTX_SETUP, rmsg); + } else { + tr->ctx = CK_CTX_TEST; + tr->msg = NULL; + tr->duration = rmsg->duration; + tr_set_loc_by_ctx (tr, CK_CTX_TEST, rmsg); + } + + return tr; +} + +void +setup_messaging (void) +{ + setup_pipe (); +} + +void +teardown_messaging (void) +{ + teardown_pipe (); +} + +/** + * Open a temporary file. + * + * If the file could be unlinked upon creation, the name + * of the file is not returned via 'name'. However, if the + * file could not be unlinked, the name is returned, + * expecting the caller to both delete the file and + * free the 'name' field after the file is closed. + */ +FILE * +open_tmp_file (char **name) +{ + FILE *file = NULL; + + *name = NULL; + +#if !HAVE_MKSTEMP + /* Windows does not like tmpfile(). This is likely because tmpfile() + * call unlink() on the file before returning it, to make sure the + * file is deleted when it is closed. The unlink() call also fails + * on Windows if the file is still open. */ + /* also note that mkstemp is apparently a C90 replacement for tmpfile */ + /* perhaps all we need to do on Windows is set TMPDIR to whatever is + stored in TEMP for tmpfile to work */ + /* and finally, the "b" from "w+b" is ignored on OS X, not sure about WIN32 */ + + file = tmpfile (); + if (file == NULL) { + char *tmp = getenv ("TEMP"); + char *tmp_file = tempnam (tmp, "check_"); + + /* + * Note, tempnam is not enough to get a unique name. Between + * getting the name and opening the file, something else also + * calling tempnam() could get the same name. It has been observed + * on MinGW-w64 builds on Wine that this exact thing happens + * if multiple instances of a unit tests are running concurrently. + * To prevent two concurrent unit tests from getting the same file, + * we append the pid to the file. The pid should be unique on the + * system. + */ + char *uniq_tmp_file = ck_strdup_printf ("%s.%d", tmp_file, getpid ()); + + file = fopen (uniq_tmp_file, "w+b"); + *name = uniq_tmp_file; + free (tmp_file); + } +#else + int fd = -1; + const char *tmp_dir = getenv ("TEMP"); + if (!tmp_dir) { + tmp_dir = "."; + } + + *name = ck_strdup_printf ("%s/check_XXXXXX", tmp_dir); + + if (-1 < (fd = mkstemp (*name))) { + file = fdopen (fd, "w+b"); + if (0 == unlink (*name) || NULL == file) { + free (*name); + *name = NULL; + } + } +#endif + return file; +} + +static void +setup_pipe (void) +{ + if (send_file1 == NULL) { + send_file1 = open_tmp_file (&send_file1_name); + return; + } + if (send_file2 == NULL) { + send_file2 = open_tmp_file (&send_file2_name); + return; + } + eprintf ("Only one nesting of suite runs supported", __FILE__, __LINE__); +} + +static void +teardown_pipe (void) +{ + if (send_file2 != 0) { + fclose (send_file2); + send_file2 = 0; + if (send_file2_name != NULL) { + unlink (send_file2_name); + free (send_file2_name); + send_file2_name = NULL; + } + } else if (send_file1 != 0) { + fclose (send_file1); + send_file1 = 0; + if (send_file1_name != NULL) { + unlink (send_file1_name); + free (send_file1_name); + send_file1_name = NULL; + } + } else { + eprintf ("No messaging setup", __FILE__, __LINE__); + } +} diff --git a/libs/gst/check/libcheck/check_msg.h b/libs/gst/check/libcheck/check_msg.h new file mode 100644 index 0000000..b99a757 --- /dev/null +++ b/libs/gst/check/libcheck/check_msg.h @@ -0,0 +1,39 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_MSG_NEW_H +#define CHECK_MSG_NEW_H + + +/* Functions implementing messaging during test runs */ + +void send_failure_info (const char *msg); +void send_loc_info (const char *file, int line); +void send_ctx_info (enum ck_result_ctx ctx); +void send_duration_info (int duration); + +TestResult *receive_test_result (int waserror); + +void setup_messaging (void); +void teardown_messaging (void); + +FILE *open_tmp_file (char **name); + +#endif /*CHECK_MSG_NEW_H */ diff --git a/libs/gst/check/libcheck/check_pack.c b/libs/gst/check/libcheck/check_pack.c new file mode 100644 index 0000000..146a584 --- /dev/null +++ b/libs/gst/check/libcheck/check_pack.c @@ -0,0 +1,493 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include + +#include "internal-check.h" +#include "check_error.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_pack.h" + +#ifndef HAVE_PTHREAD +#define pthread_mutex_lock(arg) +#define pthread_mutex_unlock(arg) +#define pthread_cleanup_push(f,a) { +#define pthread_cleanup_pop(e) } +#endif + +/* Maximum size for one message in the message stream. */ +#define CK_MAX_MSG_SIZE 8192 +/* This is used to implement a sliding window on the receiving + * side. When sending messages, we assure that no single message + * is bigger than this (actually we check against CK_MAX_MSG_SIZE/2). + * The usual size for a message is less than 80 bytes. + * All this is done instead of the previous approach to allocate (actually + * continuously reallocate) one big chunk for the whole message stream. + * Problems were seen in the wild with up to 4 GB reallocations. + */ + + +/* typedef an unsigned int that has at least 4 bytes */ +typedef uint32_t ck_uint32; + + +static void pack_int (char **buf, int val); +static int upack_int (char **buf); +static void pack_str (char **buf, const char *str); +static char *upack_str (char **buf); + +static int pack_ctx (char **buf, CtxMsg * cmsg); +static int pack_loc (char **buf, LocMsg * lmsg); +static int pack_fail (char **buf, FailMsg * fmsg); +static int pack_duration (char **buf, DurationMsg * fmsg); +static void upack_ctx (char **buf, CtxMsg * cmsg); +static void upack_loc (char **buf, LocMsg * lmsg); +static void upack_fail (char **buf, FailMsg * fmsg); +static void upack_duration (char **buf, DurationMsg * fmsg); + +static void check_type (int type, const char *file, int line); +static enum ck_msg_type upack_type (char **buf); +static void pack_type (char **buf, enum ck_msg_type type); + +static int read_buf (FILE * fdes, int size, char *buf); +static int get_result (char *buf, RcvMsg * rmsg); +static void rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx); +static void rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line); +static RcvMsg *rcvmsg_create (void); +void rcvmsg_free (RcvMsg * rmsg); + +typedef int (*pfun) (char **, CheckMsg *); +typedef void (*upfun) (char **, CheckMsg *); + +static pfun pftab[] = { + (pfun) pack_ctx, + (pfun) pack_fail, + (pfun) pack_loc, + (pfun) pack_duration +}; + +static upfun upftab[] = { + (upfun) upack_ctx, + (upfun) upack_fail, + (upfun) upack_loc, + (upfun) upack_duration +}; + +int +pack (enum ck_msg_type type, char **buf, CheckMsg * msg) +{ + if (buf == NULL) + return -1; + if (msg == NULL) + return 0; + + check_type (type, __FILE__, __LINE__); + + return pftab[type] (buf, msg); +} + +int +upack (char *buf, CheckMsg * msg, enum ck_msg_type *type) +{ + char *obuf; + + if (buf == NULL) + return -1; + + obuf = buf; + + *type = upack_type (&buf); + + check_type (*type, __FILE__, __LINE__); + + upftab[*type] (&buf, msg); + + return buf - obuf; +} + +static void +pack_int (char **buf, int val) +{ + unsigned char *ubuf = (unsigned char *) *buf; + ck_uint32 uval = val; + + ubuf[0] = (unsigned char) ((uval >> 24) & 0xFF); + ubuf[1] = (unsigned char) ((uval >> 16) & 0xFF); + ubuf[2] = (unsigned char) ((uval >> 8) & 0xFF); + ubuf[3] = (unsigned char) (uval & 0xFF); + + *buf += 4; +} + +static int +upack_int (char **buf) +{ + unsigned char *ubuf = (unsigned char *) *buf; + ck_uint32 uval; + + uval = + (ck_uint32) ((ubuf[0] << 24) | (ubuf[1] << 16) | (ubuf[2] << 8) | + ubuf[3]); + + *buf += 4; + + return (int) uval; +} + +static void +pack_str (char **buf, const char *val) +{ + int strsz; + + if (val == NULL) + strsz = 0; + else + strsz = strlen (val); + + pack_int (buf, strsz); + + if (strsz > 0) { + memcpy (*buf, val, strsz); + *buf += strsz; + } +} + +static char * +upack_str (char **buf) +{ + char *val; + int strsz; + + strsz = upack_int (buf); + + if (strsz > 0) { + val = (char *) emalloc (strsz + 1); + memcpy (val, *buf, strsz); + val[strsz] = 0; + *buf += strsz; + } else { + val = (char *) emalloc (1); + *val = 0; + } + + return val; +} + +static void +pack_type (char **buf, enum ck_msg_type type) +{ + pack_int (buf, (int) type); +} + +static enum ck_msg_type +upack_type (char **buf) +{ + return (enum ck_msg_type) upack_int (buf); +} + + +static int +pack_ctx (char **buf, CtxMsg * cmsg) +{ + char *ptr; + int len; + + len = 4 + 4; + *buf = ptr = (char *) emalloc (len); + + pack_type (&ptr, CK_MSG_CTX); + pack_int (&ptr, (int) cmsg->ctx); + + return len; +} + +static void +upack_ctx (char **buf, CtxMsg * cmsg) +{ + cmsg->ctx = (enum ck_result_ctx) upack_int (buf); +} + +static int +pack_duration (char **buf, DurationMsg * cmsg) +{ + char *ptr; + int len; + + len = 4 + 4; + *buf = ptr = (char *) emalloc (len); + + pack_type (&ptr, CK_MSG_DURATION); + pack_int (&ptr, cmsg->duration); + + return len; +} + +static void +upack_duration (char **buf, DurationMsg * cmsg) +{ + cmsg->duration = upack_int (buf); +} + +static int +pack_loc (char **buf, LocMsg * lmsg) +{ + char *ptr; + int len; + + len = 4 + 4 + (lmsg->file ? strlen (lmsg->file) : 0) + 4; + *buf = ptr = (char *) emalloc (len); + + pack_type (&ptr, CK_MSG_LOC); + pack_str (&ptr, lmsg->file); + pack_int (&ptr, lmsg->line); + + return len; +} + +static void +upack_loc (char **buf, LocMsg * lmsg) +{ + lmsg->file = upack_str (buf); + lmsg->line = upack_int (buf); +} + +static int +pack_fail (char **buf, FailMsg * fmsg) +{ + char *ptr; + int len; + + len = 4 + 4 + (fmsg->msg ? strlen (fmsg->msg) : 0); + *buf = ptr = (char *) emalloc (len); + + pack_type (&ptr, CK_MSG_FAIL); + pack_str (&ptr, fmsg->msg); + + return len; +} + +static void +upack_fail (char **buf, FailMsg * fmsg) +{ + fmsg->msg = upack_str (buf); +} + +static void +check_type (int type, const char *file, int line) +{ + if (type < 0 || type >= CK_MSG_LAST) + eprintf ("Bad message type arg %d", file, line, type); +} + +#ifdef HAVE_PTHREAD +static pthread_mutex_t ck_mutex_lock = PTHREAD_MUTEX_INITIALIZER; +static void +ppack_cleanup (void *mutex) +{ + pthread_mutex_unlock ((pthread_mutex_t *) mutex); +} +#endif + +void +ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg) +{ + char *buf = NULL; + int n; + ssize_t r; + + n = pack (type, &buf, msg); + /* Keep it on the safe side to not send too much data. */ + if (n > (CK_MAX_MSG_SIZE / 2)) + eprintf ("Message string too long", __FILE__, __LINE__ - 2); + + pthread_cleanup_push (ppack_cleanup, &ck_mutex_lock); + pthread_mutex_lock (&ck_mutex_lock); + r = fwrite (buf, 1, n, fdes); + fflush (fdes); + pthread_mutex_unlock (&ck_mutex_lock); + pthread_cleanup_pop (0); + if (r != n) + eprintf ("Error in call to fwrite:", __FILE__, __LINE__ - 2); + + free (buf); +} + +static int +read_buf (FILE * fdes, int size, char *buf) +{ + int n; + + n = fread (buf, 1, size, fdes); + + if (ferror (fdes)) { + eprintf ("Error in call to fread:", __FILE__, __LINE__ - 4); + } + + return n; +} + +static int +get_result (char *buf, RcvMsg * rmsg) +{ + enum ck_msg_type type; + CheckMsg msg; + int n; + + n = upack (buf, &msg, &type); + if (n == -1) + eprintf ("Error in call to upack", __FILE__, __LINE__ - 2); + + if (type == CK_MSG_CTX) { + CtxMsg *cmsg = (CtxMsg *) & msg; + + rcvmsg_update_ctx (rmsg, cmsg->ctx); + } else if (type == CK_MSG_LOC) { + LocMsg *lmsg = (LocMsg *) & msg; + + if (rmsg->failctx == CK_CTX_INVALID) { + rcvmsg_update_loc (rmsg, lmsg->file, lmsg->line); + } + free (lmsg->file); + } else if (type == CK_MSG_FAIL) { + FailMsg *fmsg = (FailMsg *) & msg; + + if (rmsg->msg == NULL) { + rmsg->msg = strdup (fmsg->msg); + rmsg->failctx = rmsg->lastctx; + } else { + /* Skip subsequent failure messages, only happens for CK_NOFORK */ + } + free (fmsg->msg); + } else if (type == CK_MSG_DURATION) { + DurationMsg *cmsg = (DurationMsg *) & msg; + + rmsg->duration = cmsg->duration; + } else + check_type (type, __FILE__, __LINE__); + + return n; +} + +static void +reset_rcv_test (RcvMsg * rmsg) +{ + rmsg->test_line = -1; + rmsg->test_file = NULL; +} + +static void +reset_rcv_fixture (RcvMsg * rmsg) +{ + rmsg->fixture_line = -1; + rmsg->fixture_file = NULL; +} + +static RcvMsg * +rcvmsg_create (void) +{ + RcvMsg *rmsg; + + rmsg = (RcvMsg *) emalloc (sizeof (RcvMsg)); + rmsg->lastctx = CK_CTX_INVALID; + rmsg->failctx = CK_CTX_INVALID; + rmsg->msg = NULL; + rmsg->duration = -1; + reset_rcv_test (rmsg); + reset_rcv_fixture (rmsg); + return rmsg; +} + +void +rcvmsg_free (RcvMsg * rmsg) +{ + free (rmsg->fixture_file); + free (rmsg->test_file); + free (rmsg->msg); + free (rmsg); +} + +static void +rcvmsg_update_ctx (RcvMsg * rmsg, enum ck_result_ctx ctx) +{ + if (rmsg->lastctx != CK_CTX_INVALID) { + free (rmsg->fixture_file); + reset_rcv_fixture (rmsg); + } + rmsg->lastctx = ctx; +} + +static void +rcvmsg_update_loc (RcvMsg * rmsg, const char *file, int line) +{ + if (rmsg->lastctx == CK_CTX_TEST) { + free (rmsg->test_file); + rmsg->test_line = line; + rmsg->test_file = strdup (file); + } else { + free (rmsg->fixture_file); + rmsg->fixture_line = line; + rmsg->fixture_file = strdup (file); + } +} + +RcvMsg * +punpack (FILE * fdes) +{ + int nread, nparse, n; + char *buf; + RcvMsg *rmsg; + + rmsg = rcvmsg_create (); + + /* Allcate a buffer */ + buf = (char *) emalloc (CK_MAX_MSG_SIZE); + /* Fill the buffer from the file */ + nread = read_buf (fdes, CK_MAX_MSG_SIZE, buf); + nparse = nread; + /* While not all parsed */ + while (nparse > 0) { + /* Parse one message */ + n = get_result (buf, rmsg); + nparse -= n; + if (nparse < 0) + eprintf ("Error in call to get_result", __FILE__, __LINE__ - 3); + /* Move remaining data in buffer to the beginning */ + memmove (buf, buf + n, nparse); + /* If EOF has not been seen */ + if (nread > 0) { + /* Read more data into empty space at end of the buffer */ + nread = read_buf (fdes, n, buf + nparse); + nparse += nread; + } + } + free (buf); + + if (rmsg->lastctx == CK_CTX_INVALID) { + free (rmsg); + rmsg = NULL; + } + + return rmsg; +} diff --git a/libs/gst/check/libcheck/check_pack.h b/libs/gst/check/libcheck/check_pack.h new file mode 100644 index 0000000..e73a196 --- /dev/null +++ b/libs/gst/check/libcheck/check_pack.h @@ -0,0 +1,84 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_PACK_H +#define CHECK_PACK_H + + +enum ck_msg_type +{ + CK_MSG_CTX, + CK_MSG_FAIL, + CK_MSG_LOC, + CK_MSG_DURATION, + CK_MSG_LAST +}; + +typedef struct CtxMsg +{ + enum ck_result_ctx ctx; +} CtxMsg; + +typedef struct LocMsg +{ + int line; + char *file; +} LocMsg; + +typedef struct FailMsg +{ + char *msg; +} FailMsg; + +typedef struct DurationMsg +{ + int duration; +} DurationMsg; + +typedef union +{ + CtxMsg ctx_msg; + FailMsg fail_msg; + LocMsg loc_msg; + DurationMsg duration_msg; +} CheckMsg; + +typedef struct RcvMsg +{ + enum ck_result_ctx lastctx; + enum ck_result_ctx failctx; + char *fixture_file; + int fixture_line; + char *test_file; + int test_line; + char *msg; + int duration; +} RcvMsg; + +void rcvmsg_free (RcvMsg * rmsg); + + +int pack (enum ck_msg_type type, char **buf, CheckMsg * msg); +int upack (char *buf, CheckMsg * msg, enum ck_msg_type *type); + +void ppack (FILE * fdes, enum ck_msg_type type, CheckMsg * msg); +RcvMsg *punpack (FILE * fdes); + +#endif /*CHECK_PACK_H */ diff --git a/libs/gst/check/libcheck/check_print.c b/libs/gst/check/libcheck/check_print.c new file mode 100644 index 0000000..c94e47c --- /dev/null +++ b/libs/gst/check/libcheck/check_print.c @@ -0,0 +1,236 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include + +#include "internal-check.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_str.h" +#include "check_print.h" + +static void srunner_fprint_summary (FILE * file, SRunner * sr, + enum print_output print_mode); +static void srunner_fprint_results (FILE * file, SRunner * sr, + enum print_output print_mode); + + +void +srunner_print (SRunner * sr, enum print_output print_mode) +{ + srunner_fprint (stdout, sr, print_mode); +} + +void +srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode) +{ + if (print_mode == CK_ENV) { + print_mode = get_env_printmode (); + } + + srunner_fprint_summary (file, sr, print_mode); + srunner_fprint_results (file, sr, print_mode); +} + +static void +srunner_fprint_summary (FILE * file, SRunner * sr, enum print_output print_mode) +{ +#if ENABLE_SUBUNIT + if (print_mode == CK_SUBUNIT) + return; +#endif + + if (print_mode >= CK_MINIMAL) { + char *str; + + str = sr_stat_str (sr); + fprintf (file, "%s\n", str); + free (str); + } + return; +} + +static void +srunner_fprint_results (FILE * file, SRunner * sr, enum print_output print_mode) +{ + List *resultlst; + +#if ENABLE_SUBUNIT + if (print_mode == CK_SUBUNIT) + return; +#endif + + resultlst = sr->resultlst; + + for (check_list_front (resultlst); !check_list_at_end (resultlst); + check_list_advance (resultlst)) { + TestResult *tr = (TestResult *) check_list_val (resultlst); + + tr_fprint (file, tr, print_mode); + } + return; +} + +void +fprint_xml_esc (FILE * file, const char *str) +{ + /* The valid XML characters are as follows: + * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + * Characters that are outside of ASCII must be encoded. Further, the + * following special characters: + * " ' < > & + * must be encoded. We assume that the incoming string may be a multibyte + * character. + */ + + for (; *str != '\0'; str++) { + char next = *str; + + /* handle special characters that must be escaped */ + if (next == '"' || next == '\'' || next == '<' || next == '>' + || next == '&') { + switch (next) { + case '"': + fputs (""", file); + break; + case '\'': + fputs ("'", file); + break; + case '<': + fputs ("<", file); + break; + case '>': + fputs (">", file); + break; + case '&': + fputs ("&", file); + break; + } + } + /* printable ASCII */ + else if (next >= ' ' && next <= '~') { + fputc (next, file); + } + /* Non-printable character */ + else if (next == 0x9 || next == 0xA || next == 0xD || next >= 0x20) { + fprintf (file, "&#x%X;", next); + } + /* If it did not get printed, it is not a valid XML character */ + } +} + +void +tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode) +{ + if (print_mode == CK_ENV) { + print_mode = get_env_printmode (); + } + + if ((print_mode >= CK_VERBOSE && tr->rtype == CK_PASS) || + (tr->rtype != CK_PASS && print_mode >= CK_NORMAL)) { + char *trstr = tr_str (tr); + + fprintf (file, "%s\n", trstr); + free (trstr); + } +} + +void +tr_xmlprint (FILE * file, TestResult * tr, + enum print_output print_mode CK_ATTRIBUTE_UNUSED) +{ + char result[10]; + char *path_name = NULL; + char *file_name = NULL; + char *slash = NULL; + + switch (tr->rtype) { + case CK_PASS: + snprintf (result, sizeof (result), "%s", "success"); + break; + case CK_FAILURE: + snprintf (result, sizeof (result), "%s", "failure"); + break; + case CK_ERROR: + snprintf (result, sizeof (result), "%s", "error"); + break; + case CK_TEST_RESULT_INVALID: + default: + abort (); + break; + } + + if (tr->file) { + slash = strrchr (tr->file, '/'); + if (slash == NULL) { + slash = strrchr (tr->file, '\\'); + } + + if (slash == NULL) { + path_name = strdup ("."); + file_name = tr->file; + } else { + path_name = strdup (tr->file); + path_name[slash - tr->file] = 0; /* Terminate the temporary string. */ + file_name = slash + 1; + } + } + + + fprintf (file, " \n", result); + fprintf (file, " %s\n", + (path_name == NULL ? "" : path_name)); + fprintf (file, " %s:%d\n", + (file_name == NULL ? "" : file_name), tr->line); + fprintf (file, " %s\n", tr->tname); + fprintf (file, " %d\n", tr->iter); + fprintf (file, " %d.%06d\n", + tr->duration < 0 ? -1 : tr->duration / US_PER_SEC, + tr->duration < 0 ? 0 : tr->duration % US_PER_SEC); + fprintf (file, " "); + fprint_xml_esc (file, tr->tcname); + fprintf (file, "\n"); + fprintf (file, " "); + fprint_xml_esc (file, tr->msg); + fprintf (file, "\n"); + fprintf (file, " \n"); + + free (path_name); +} + +enum print_output +get_env_printmode (void) +{ + char *env = getenv ("CK_VERBOSITY"); + + if (env == NULL) + return CK_NORMAL; + if (strcmp (env, "silent") == 0) + return CK_SILENT; + if (strcmp (env, "minimal") == 0) + return CK_MINIMAL; + if (strcmp (env, "verbose") == 0) + return CK_VERBOSE; + return CK_NORMAL; +} diff --git a/libs/gst/check/libcheck/check_print.h b/libs/gst/check/libcheck/check_print.h new file mode 100644 index 0000000..20c0d22 --- /dev/null +++ b/libs/gst/check/libcheck/check_print.h @@ -0,0 +1,32 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_PRINT_H +#define CHECK_PRINT_H + +/* escape XML special characters (" ' < > &) in str and print to file */ +void fprint_xml_esc (FILE * file, const char *str); +void tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode); +void tr_xmlprint (FILE * file, TestResult * tr, enum print_output print_mode); +void srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode); +enum print_output get_env_printmode (void); + + +#endif /* CHECK_PRINT_H */ diff --git a/libs/gst/check/libcheck/check_run.c b/libs/gst/check/libcheck/check_run.c new file mode 100644 index 0000000..f686ca0 --- /dev/null +++ b/libs/gst/check/libcheck/check_run.c @@ -0,0 +1,796 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal-check.h" +#include "check_error.h" +#include "check_list.h" +#include "check_impl.h" +#include "check_msg.h" +#include "check_log.h" + +enum rinfo +{ + CK_R_SIG, + CK_R_PASS, + CK_R_EXIT, + CK_R_FAIL_TEST, + CK_R_FAIL_FIXTURE +}; + +enum tf_type +{ + CK_FORK_TEST, + CK_NOFORK_TEST, + CK_NOFORK_FIXTURE +}; + + +/* all functions are defined in the same order they are declared. + functions that depend on forking are gathered all together. + non-static functions are at the end of the file. */ +static void srunner_run_init (SRunner * sr, enum print_output print_mode); +static void srunner_run_end (SRunner * sr, enum print_output print_mode); +static void srunner_iterate_suites (SRunner * sr, + const char *sname, const char *tcname, + const char *include_tags, + const char *exclude_tags, enum print_output print_mode); +static void srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc); +static void srunner_add_failure (SRunner * sr, TestResult * tf); +static TestResult *srunner_run_setup (List * func_list, + enum fork_status fork_usage, const char *test_name, const char *setup_name); +static int srunner_run_unchecked_setup (SRunner * sr, TCase * tc); +static TestResult *tcase_run_checked_setup (SRunner * sr, TCase * tc); +static void srunner_run_teardown (List * fixture_list, + enum fork_status fork_usage); +static void srunner_run_unchecked_teardown (SRunner * sr, TCase * tc); +static void tcase_run_checked_teardown (TCase * tc); +static void srunner_run_tcase (SRunner * sr, TCase * tc); +static TestResult *tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tf, + int i); +static TestResult *receive_result_info_nofork (const char *tcname, + const char *tname, int iter, int duration); +static void set_nofork_info (TestResult * tr); +static char *pass_msg (void); + +#if defined(HAVE_FORK) && HAVE_FORK==1 +static TestResult *tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tf, + int i); +static TestResult *receive_result_info_fork (const char *tcname, + const char *tname, int iter, + int status, int expected_signal, signed char allowed_exit_value); +static void set_fork_info (TestResult * tr, int status, int expected_signal, + signed char allowed_exit_value); +static char *signal_msg (int sig); +static char *signal_error_msg (int signal_received, int signal_expected); +static char *exit_msg (int exitstatus); +static int waserror (int status, int expected_signal); + +static int alarm_received; +static pid_t group_pid; +static struct sigaction sigint_old_action; +static struct sigaction sigterm_old_action; + +static void CK_ATTRIBUTE_UNUSED +sig_handler (int sig_nr) +{ + switch (sig_nr) { + case SIGALRM: + alarm_received = 1; + killpg (group_pid, SIGKILL); + break; + case SIGTERM: + case SIGINT: + { + pid_t own_group_pid; + int child_sig = SIGTERM; + + if (sig_nr == SIGINT) { + child_sig = SIGKILL; + sigaction (SIGINT, &sigint_old_action, NULL); + } else { + sigaction (SIGTERM, &sigterm_old_action, NULL); + } + + killpg (group_pid, child_sig); + + /* POSIX says that calling killpg(0) + * does not necessarily mean to call it on the callers + * group pid! */ + own_group_pid = getpgrp (); + killpg (own_group_pid, sig_nr); + break; + } + default: + eprintf ("Unhandled signal: %d", __FILE__, __LINE__, sig_nr); + break; + } +} +#endif /* HAVE_FORK */ + +#define MSG_LEN 100 + +static void +srunner_run_init (SRunner * sr, enum print_output print_mode) +{ + set_fork_status (srunner_fork_status (sr)); + setup_messaging (); + srunner_init_logging (sr, print_mode); + log_srunner_start (sr); +} + +static void +srunner_run_end (SRunner * sr, enum print_output CK_ATTRIBUTE_UNUSED print_mode) +{ + log_srunner_end (sr); + srunner_end_logging (sr); + teardown_messaging (); + set_fork_status (CK_FORK); +} + +static void +srunner_iterate_suites (SRunner * sr, + const char *sname, const char *tcname, + const char *include_tags, + const char *exclude_tags, enum print_output CK_ATTRIBUTE_UNUSED print_mode) +{ + List *include_tag_lst; + List *exclude_tag_lst; + List *slst; + List *tcl; + TCase *tc; + + slst = sr->slst; + + include_tag_lst = tag_string_to_list (include_tags); + exclude_tag_lst = tag_string_to_list (exclude_tags); + + for (check_list_front (slst); !check_list_at_end (slst); + check_list_advance (slst)) { + Suite *s = (Suite *) check_list_val (slst); + + if (((sname != NULL) && (strcmp (sname, s->name) != 0)) + || ((tcname != NULL) && (!suite_tcase (s, tcname)))) + continue; + + log_suite_start (sr, s); + + tcl = s->tclst; + + for (check_list_front (tcl); !check_list_at_end (tcl); + check_list_advance (tcl)) { + tc = (TCase *) check_list_val (tcl); + + if ((tcname != NULL) && (strcmp (tcname, tc->name) != 0)) { + continue; + } + if (include_tags != NULL) { + if (!tcase_matching_tag (tc, include_tag_lst)) { + continue; + } + } + if (exclude_tags != NULL) { + if (tcase_matching_tag (tc, exclude_tag_lst)) { + continue; + } + } + + srunner_run_tcase (sr, tc); + } + + log_suite_end (sr, s); + } + + check_list_apply (include_tag_lst, free); + check_list_apply (exclude_tag_lst, free); + check_list_free (include_tag_lst); + check_list_free (exclude_tag_lst); +} + +static void +srunner_iterate_tcase_tfuns (SRunner * sr, TCase * tc) +{ + List *tfl; + TF *tfun; + TestResult *tr = NULL; + + tfl = tc->tflst; + + for (check_list_front (tfl); !check_list_at_end (tfl); + check_list_advance (tfl)) { + int i; + + tfun = (TF *) check_list_val (tfl); + + for (i = tfun->loop_start; i < tfun->loop_end; i++) { + log_test_start (sr, tc, tfun); + switch (srunner_fork_status (sr)) { + case CK_FORK: +#if defined(HAVE_FORK) && HAVE_FORK==1 + tr = tcase_run_tfun_fork (sr, tc, tfun, i); +#else /* HAVE_FORK */ + eprintf ("This version does not support fork", __FILE__, __LINE__); +#endif /* HAVE_FORK */ + break; + case CK_NOFORK: + tr = tcase_run_tfun_nofork (sr, tc, tfun, i); + break; + case CK_FORK_GETENV: + default: + eprintf ("Bad fork status in SRunner", __FILE__, __LINE__); + } + + if (NULL != tr) { + srunner_add_failure (sr, tr); + log_test_end (sr, tr); + } + } + } +} + +static void +srunner_add_failure (SRunner * sr, TestResult * tr) +{ + check_list_add_end (sr->resultlst, tr); + sr->stats->n_checked++; /* count checks during setup, test, and teardown */ + if (tr->rtype == CK_FAILURE) + sr->stats->n_failed++; + else if (tr->rtype == CK_ERROR) + sr->stats->n_errors++; + +} + +static TestResult * +srunner_run_setup (List * fixture_list, enum fork_status fork_usage, + const char *test_name, const char *setup_name) +{ + TestResult *tr = NULL; + Fixture *setup_fixture; + + if (fork_usage == CK_FORK) { + send_ctx_info (CK_CTX_SETUP); + } + + for (check_list_front (fixture_list); !check_list_at_end (fixture_list); + check_list_advance (fixture_list)) { + setup_fixture = (Fixture *) check_list_val (fixture_list); + + if (fork_usage == CK_NOFORK) { + send_ctx_info (CK_CTX_SETUP); + + if (0 == setjmp (error_jmp_buffer)) { + setup_fixture->fun (); + } + + /* Stop the setup and return the failure in nofork mode. */ + tr = receive_result_info_nofork (test_name, setup_name, 0, -1); + if (tr->rtype != CK_PASS) { + break; + } + + free (tr->file); + free (tr->msg); + free (tr); + tr = NULL; + } else { + setup_fixture->fun (); + } + } + + return tr; +} + +static int +srunner_run_unchecked_setup (SRunner * sr, TCase * tc) +{ + TestResult *tr = NULL; + int rval = 1; + + set_fork_status (CK_NOFORK); + tr = srunner_run_setup (tc->unch_sflst, CK_NOFORK, tc->name, + "unchecked_setup"); + set_fork_status (srunner_fork_status (sr)); + + if (tr != NULL && tr->rtype != CK_PASS) { + srunner_add_failure (sr, tr); + rval = 0; + } + + return rval; +} + +static TestResult * +tcase_run_checked_setup (SRunner * sr, TCase * tc) +{ + TestResult *tr = srunner_run_setup (tc->ch_sflst, srunner_fork_status (sr), + tc->name, "checked_setup"); + + return tr; +} + +static void +srunner_run_teardown (List * fixture_list, enum fork_status fork_usage) +{ + Fixture *fixture; + + for (check_list_front (fixture_list); !check_list_at_end (fixture_list); + check_list_advance (fixture_list)) { + fixture = (Fixture *) check_list_val (fixture_list); + send_ctx_info (CK_CTX_TEARDOWN); + + if (fork_usage == CK_NOFORK) { + if (0 == setjmp (error_jmp_buffer)) { + fixture->fun (); + } else { + /* Abort the remaining teardowns */ + break; + } + } else { + fixture->fun (); + } + } +} + +static void +srunner_run_unchecked_teardown (SRunner * sr, TCase * tc) +{ + srunner_run_teardown (tc->unch_tflst, srunner_fork_status (sr)); +} + +static void +tcase_run_checked_teardown (TCase * tc) +{ + srunner_run_teardown (tc->ch_tflst, CK_NOFORK); +} + +static void +srunner_run_tcase (SRunner * sr, TCase * tc) +{ + if (srunner_run_unchecked_setup (sr, tc)) { + srunner_iterate_tcase_tfuns (sr, tc); + srunner_run_unchecked_teardown (sr, tc); + } +} + +static TestResult * +tcase_run_tfun_nofork (SRunner * sr, TCase * tc, TF * tfun, int i) +{ + TestResult *tr; + struct timespec ts_start = { 0, 0 }, ts_end = { + 0, 0}; + + tr = tcase_run_checked_setup (sr, tc); + if (tr == NULL) { + clock_gettime (check_get_clockid (), &ts_start); + if (0 == setjmp (error_jmp_buffer)) { + tfun->fn (i); + } + clock_gettime (check_get_clockid (), &ts_end); + tcase_run_checked_teardown (tc); + return receive_result_info_nofork (tc->name, tfun->name, i, + DIFF_IN_USEC (ts_start, ts_end)); + } + + return tr; +} + +static TestResult * +receive_result_info_nofork (const char *tcname, + const char *tname, int iter, int duration) +{ + TestResult *tr; + + tr = receive_test_result (0); + if (tr == NULL) { + eprintf ("Failed to receive test result", __FILE__, __LINE__); + } else { + tr->tcname = tcname; + tr->tname = tname; + tr->iter = iter; + tr->duration = duration; + set_nofork_info (tr); + } + + return tr; +} + +static void +set_nofork_info (TestResult * tr) +{ + if (tr->msg == NULL) { + tr->rtype = CK_PASS; + tr->msg = pass_msg (); + } else { + tr->rtype = CK_FAILURE; + } +} + +static char * +pass_msg (void) +{ + return strdup ("Passed"); +} + +#if defined(HAVE_FORK) && HAVE_FORK==1 +static TestResult * +tcase_run_tfun_fork (SRunner * sr, TCase * tc, TF * tfun, int i) +{ + pid_t pid_w; + pid_t pid; + int status = 0; + struct timespec ts_start = { 0, 0 }, ts_end = { + 0, 0}; + + timer_t timerid; + struct itimerspec timer_spec; + TestResult *tr; + + + pid = fork (); + if (pid == -1) + eprintf ("Error in call to fork:", __FILE__, __LINE__ - 2); + if (pid == 0) { + setpgid (0, 0); + group_pid = getpgrp (); + tr = tcase_run_checked_setup (sr, tc); + free (tr); + clock_gettime (check_get_clockid (), &ts_start); + tfun->fn (i); + clock_gettime (check_get_clockid (), &ts_end); + tcase_run_checked_teardown (tc); + send_duration_info (DIFF_IN_USEC (ts_start, ts_end)); + exit (EXIT_SUCCESS); + } else { + group_pid = pid; + } + + alarm_received = 0; + + if (timer_create (check_get_clockid (), + NULL /* fire SIGALRM if timer expires */ , + &timerid) == 0) { + /* Set the timer to fire once */ + timer_spec.it_value = tc->timeout; + timer_spec.it_interval.tv_sec = 0; + timer_spec.it_interval.tv_nsec = 0; + if (timer_settime (timerid, 0, &timer_spec, NULL) == 0) { + do { + pid_w = waitpid (pid, &status, 0); + } + while (pid_w == -1); + } else { + eprintf ("Error in call to timer_settime:", __FILE__, __LINE__); + } + + /* If the timer has not fired, disable it */ + timer_delete (timerid); + } else { + eprintf ("Error in call to timer_create:", __FILE__, __LINE__); + } + + killpg (pid, SIGKILL); /* Kill remaining processes. */ + + return receive_result_info_fork (tc->name, tfun->name, i, status, + tfun->signal, tfun->allowed_exit_value); +} + +static TestResult * +receive_result_info_fork (const char *tcname, + const char *tname, + int iter, int status, int expected_signal, signed char allowed_exit_value) +{ + TestResult *tr; + + tr = receive_test_result (waserror (status, expected_signal)); + if (tr == NULL) { + eprintf ("Failed to receive test result", __FILE__, __LINE__); + } else { + tr->tcname = tcname; + tr->tname = tname; + tr->iter = iter; + set_fork_info (tr, status, expected_signal, allowed_exit_value); + } + + return tr; +} + +static void +set_fork_info (TestResult * tr, int status, int signal_expected, + signed char allowed_exit_value) +{ + int was_sig = WIFSIGNALED (status); + int was_exit = WIFEXITED (status); + signed char exit_status = WEXITSTATUS (status); + int signal_received = WTERMSIG (status); + + if (was_sig) { + if (signal_expected == signal_received) { + if (alarm_received) { + /* Got alarm instead of signal */ + tr->rtype = CK_ERROR; + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = signal_error_msg (signal_received, signal_expected); + } else { + tr->rtype = CK_PASS; + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = pass_msg (); + } + } else if (signal_expected != 0) { + /* signal received, but not the expected one */ + tr->rtype = CK_ERROR; + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = signal_error_msg (signal_received, signal_expected); + } else { + /* signal received and none expected */ + tr->rtype = CK_ERROR; + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = signal_msg (signal_received); + } + } else if (signal_expected == 0) { + if (was_exit && exit_status == allowed_exit_value) { + tr->rtype = CK_PASS; + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = pass_msg (); + } else if (was_exit && exit_status != allowed_exit_value) { + if (tr->msg == NULL) { /* early exit */ + tr->rtype = CK_ERROR; + tr->msg = exit_msg (exit_status); + } else { + tr->rtype = CK_FAILURE; + } + } + } else { /* a signal was expected and none raised */ + if (was_exit) { + if (tr->msg != NULL) { + free (tr->msg); + } + tr->msg = exit_msg (exit_status); + tr->rtype = CK_FAILURE; /* normal exit status */ + } + } +} + +static char * +signal_msg (int signal) +{ + char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */ + + if (alarm_received) { + snprintf (msg, MSG_LEN, "Test timeout expired"); + } else { + snprintf (msg, MSG_LEN, "Received signal %d (%s)", + signal, strsignal (signal)); + } + return msg; +} + +static char * +signal_error_msg (int signal_received, int signal_expected) +{ + char *sig_r_str; + char *sig_e_str; + char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */ + + sig_r_str = strdup (strsignal (signal_received)); + sig_e_str = strdup (strsignal (signal_expected)); + if (alarm_received) { + snprintf (msg, MSG_LEN, + "Test timeout expired, expected signal %d (%s)", + signal_expected, sig_e_str); + } else { + snprintf (msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)", + signal_received, sig_r_str, signal_expected, sig_e_str); + } + free (sig_r_str); + free (sig_e_str); + return msg; +} + +static char * +exit_msg (int exitval) +{ + char *msg = (char *) emalloc (MSG_LEN); /* free'd by caller */ + + snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval); + return msg; +} + +static int +waserror (int status, int signal_expected) +{ + int was_sig = WIFSIGNALED (status); + int was_exit = WIFEXITED (status); + int exit_status = WEXITSTATUS (status); + int signal_received = WTERMSIG (status); + + return ((was_sig && (signal_received != signal_expected)) || + (was_exit && exit_status != 0)); +} +#endif /* HAVE_FORK */ + +enum fork_status +srunner_fork_status (SRunner * sr) +{ + if (sr->fstat == CK_FORK_GETENV) { + char *env = getenv ("CK_FORK"); + + if (env == NULL) +#if defined(HAVE_FORK) && HAVE_FORK==1 + return CK_FORK; +#else + return CK_NOFORK; +#endif + if (strcmp (env, "no") == 0) + return CK_NOFORK; + else { +#if defined(HAVE_FORK) && HAVE_FORK==1 + return CK_FORK; +#else /* HAVE_FORK */ + eprintf ("This version does not support fork", __FILE__, __LINE__); + /* Ignoring, as Check is not compiled with fork support. */ + return CK_NOFORK; +#endif /* HAVE_FORK */ + } + } else + return sr->fstat; +} + +void +srunner_set_fork_status (SRunner * sr, enum fork_status fstat) +{ +#if !defined(HAVE_FORK) || HAVE_FORK==0 + /* If fork() is unavailable, do not allow a fork mode to be set */ + if (fstat != CK_NOFORK) { + eprintf ("This version does not support fork", __FILE__, __LINE__); + /* Overriding, as Check is not compiled with fork support. */ + fstat = CK_NOFORK; + } +#endif /* ! HAVE_FORK */ + sr->fstat = fstat; +} + +void +srunner_run_all (SRunner * sr, enum print_output print_mode) +{ + srunner_run (sr, NULL, /* All test suites. */ + NULL, /* All test cases. */ + print_mode); +} + +void +srunner_run_tagged (SRunner * sr, const char *sname, const char *tcname, + const char *include_tags, const char *exclude_tags, + enum print_output print_mode) +{ +#if defined(HAVE_SIGACTION) && defined(HAVE_FORK) + static struct sigaction sigalarm_old_action; + static struct sigaction sigalarm_new_action; + static struct sigaction sigint_new_action; + static struct sigaction sigterm_new_action; +#endif /* HAVE_SIGACTION && HAVE_FORK */ + + /* Get the selected test suite and test case from the + environment. */ + if (!tcname) + tcname = getenv ("CK_RUN_CASE"); + if (!sname) + sname = getenv ("CK_RUN_SUITE"); + if (!include_tags) + include_tags = getenv ("CK_INCLUDE_TAGS"); + if (!exclude_tags) + exclude_tags = getenv ("CK_EXCLUDE_TAGS"); + + if (sr == NULL) + return; + if (print_mode >= CK_LAST) { + eprintf ("Bad print_mode argument to srunner_run_all: %d", + __FILE__, __LINE__, print_mode); + } +#if defined(HAVE_SIGACTION) && defined(HAVE_FORK) + memset (&sigalarm_new_action, 0, sizeof (sigalarm_new_action)); + sigalarm_new_action.sa_handler = sig_handler; + sigaction (SIGALRM, &sigalarm_new_action, &sigalarm_old_action); + + memset (&sigint_new_action, 0, sizeof (sigint_new_action)); + sigint_new_action.sa_handler = sig_handler; + sigaction (SIGINT, &sigint_new_action, &sigint_old_action); + + memset (&sigterm_new_action, 0, sizeof (sigterm_new_action)); + sigterm_new_action.sa_handler = sig_handler; + sigaction (SIGTERM, &sigterm_new_action, &sigterm_old_action); +#endif /* HAVE_SIGACTION && HAVE_FORK */ + srunner_run_init (sr, print_mode); + srunner_iterate_suites (sr, sname, tcname, include_tags, exclude_tags, + print_mode); + srunner_run_end (sr, print_mode); +#if defined(HAVE_SIGACTION) && defined(HAVE_FORK) + sigaction (SIGALRM, &sigalarm_old_action, NULL); + sigaction (SIGINT, &sigint_old_action, NULL); + sigaction (SIGTERM, &sigterm_old_action, NULL); +#endif /* HAVE_SIGACTION && HAVE_FORK */ +} + +void +srunner_run (SRunner * sr, const char *sname, const char *tcname, + enum print_output print_mode) +{ + srunner_run_tagged (sr, sname, tcname, NULL, NULL, print_mode); +} + +pid_t +check_fork (void) +{ +#if defined(HAVE_FORK) && HAVE_FORK==1 + pid_t pid = fork (); + + /* Set the process to a process group to be able to kill it easily. */ + if (pid >= 0) { + setpgid (pid, group_pid); + } + return pid; +#else /* HAVE_FORK */ + eprintf ("This version does not support fork", __FILE__, __LINE__); + return 0; +#endif /* HAVE_FORK */ +} + +void +check_waitpid_and_exit (pid_t pid CK_ATTRIBUTE_UNUSED) +{ +#if defined(HAVE_FORK) && HAVE_FORK==1 + pid_t pid_w; + int status; + + if (pid > 0) { + do { + pid_w = waitpid (pid, &status, 0); + } + while (pid_w == -1); + if (waserror (status, 0)) { + exit (EXIT_FAILURE); + } + } + exit (EXIT_SUCCESS); +#else /* HAVE_FORK */ + eprintf ("This version does not support fork", __FILE__, __LINE__); + /* Ignoring, as Check is not compiled with fork support. */ + exit (EXIT_FAILURE); +#endif /* HAVE_FORK */ +} diff --git a/libs/gst/check/libcheck/check_str.c b/libs/gst/check/libcheck/check_str.c new file mode 100644 index 0000000..b2e6407 --- /dev/null +++ b/libs/gst/check/libcheck/check_str.c @@ -0,0 +1,136 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat/libcompat.h" + +#include +#include + +#include "internal-check.h" +#include "check_list.h" +#include "check_error.h" +#include "check_impl.h" +#include "check_str.h" + +static const char *tr_type_str (TestResult * tr); +static int percent_passed (TestStats * t); + +char * +tr_str (TestResult * tr) +{ + const char *exact_msg; + char *rstr; + + exact_msg = (tr->rtype == CK_ERROR) ? "(after this point) " : ""; + + rstr = ck_strdup_printf ("%s:%d:%s:%s:%s:%d: %s%s", + tr->file, tr->line, + tr_type_str (tr), tr->tcname, tr->tname, tr->iter, exact_msg, tr->msg); + + return rstr; +} + +char * +tr_short_str (TestResult * tr) +{ + const char *exact_msg; + char *rstr; + + exact_msg = (tr->rtype == CK_ERROR) ? "(after this point) " : ""; + + rstr = ck_strdup_printf ("%s:%d: %s%s", + tr->file, tr->line, exact_msg, tr->msg); + + return rstr; +} + +char * +sr_stat_str (SRunner * sr) +{ + char *str; + TestStats *ts; + + ts = sr->stats; + + str = ck_strdup_printf ("%d%%: Checks: %d, Failures: %d, Errors: %d", + percent_passed (ts), ts->n_checked, ts->n_failed, ts->n_errors); + + return str; +} + +char * +ck_strdup_printf (const char *fmt, ...) +{ + /* Guess we need no more than 100 bytes. */ + int n; + size_t size = 100; + char *p; + va_list ap; + + p = (char *) emalloc (size); + + while (1) { + /* Try to print in the allocated space. */ + va_start (ap, fmt); + n = vsnprintf (p, size, fmt, ap); + va_end (ap); + /* If that worked, return the string. */ + if (n > -1 && n < (int) size) + return p; + + /* Else try again with more space. */ + if (n > -1) /* C99 conform vsnprintf() */ + size = (size_t) n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + + p = (char *) erealloc (p, size); + } +} + +static const char * +tr_type_str (TestResult * tr) +{ + const char *str = NULL; + + if (tr->ctx == CK_CTX_TEST) { + if (tr->rtype == CK_PASS) + str = "P"; + else if (tr->rtype == CK_FAILURE) + str = "F"; + else if (tr->rtype == CK_ERROR) + str = "E"; + } else + str = "S"; + + return str; +} + +static int +percent_passed (TestStats * t) +{ + if (t->n_failed == 0 && t->n_errors == 0) + return 100; + else if (t->n_checked == 0) + return 0; + else + return (int) ((float) (t->n_checked - (t->n_failed + t->n_errors)) / + (float) t->n_checked * 100); +} diff --git a/libs/gst/check/libcheck/check_str.h b/libs/gst/check/libcheck/check_str.h new file mode 100644 index 0000000..f7fdba7 --- /dev/null +++ b/libs/gst/check/libcheck/check_str.h @@ -0,0 +1,42 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef CHECK_STR_H +#define CHECK_STR_H + +/* Return a string representation of the given TestResult. Return + value has been malloc'd, and must be freed by the caller */ +char *tr_str (TestResult * tr); + +/* Return a string representation of the given TestResult message + without the test id or result type. This is suitable for separate + formatting of the test and the message. Return value has been + malloc'd, and must be freed by the caller */ +char *tr_short_str (TestResult * tr); + +/* Return a string representation of the given SRunner's run + statistics (% passed, num run, passed, errors, failures). Return + value has been malloc'd, and must be freed by the caller +*/ +char *sr_stat_str (SRunner * sr); + +char *ck_strdup_printf (const char *fmt, ...); + +#endif /* CHECK_STR_H */ diff --git a/libs/gst/check/libcheck/libcompat/alarm.c b/libs/gst/check/libcheck/libcompat/alarm.c new file mode 100644 index 0000000..a973f22 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/alarm.c @@ -0,0 +1,28 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +unsigned int +alarm (unsigned int seconds CK_ATTRIBUTE_UNUSED) +{ + assert (0); + return 0; +} diff --git a/libs/gst/check/libcheck/libcompat/clock_gettime.c b/libs/gst/check/libcheck/libcompat/clock_gettime.c new file mode 100644 index 0000000..51cfd8f --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/clock_gettime.c @@ -0,0 +1,89 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +#ifdef __APPLE__ +#include +#include +#include +#include +/* CoreServices.h is only available on macOS */ +# if TARGET_OS_MAC && !TARGET_OS_IPHONE +# include +# endif +#include +#endif + +#define NANOSECONDS_PER_SECOND 1000000000 + + + +int +clock_gettime (clockid_t clk_id CK_ATTRIBUTE_UNUSED, struct timespec *ts) +{ + +#ifdef __APPLE__ + /* OS X does not have clock_gettime, use mach_absolute_time */ + + static mach_timebase_info_data_t sTimebaseInfo; + uint64_t rawTime; + uint64_t nanos; + + rawTime = mach_absolute_time (); + + /* + * OS X has a function to convert abs time to nano seconds: AbsoluteToNanoseconds + * However, the function may not be available as we may not have + * access to CoreServices. Because of this, we convert the abs time + * to nano seconds manually. + */ + + /* + * First grab the time base used on the system, if this is the first + * time we are being called. We can check if the value is uninitialized, + * as the denominator will be zero. + */ + if (sTimebaseInfo.denom == 0) { + (void) mach_timebase_info (&sTimebaseInfo); + } + + /* + * Do the conversion. We hope that the multiplication doesn't + * overflow; the price you pay for working in fixed point. + */ + nanos = rawTime * sTimebaseInfo.numer / sTimebaseInfo.denom; + + /* + * Fill in the timespec container + */ + ts->tv_sec = nanos / NANOSECONDS_PER_SECOND; + ts->tv_nsec = nanos - (ts->tv_sec * NANOSECONDS_PER_SECOND); +#else + /* + * As there is no function to fall back onto to get the current + * time, zero out the time so the caller will have a sane value. + */ + ts->tv_sec = 0; + ts->tv_nsec = 0; +#endif + + return 0; +} diff --git a/libs/gst/check/libcheck/libcompat/getline.c b/libs/gst/check/libcheck/libcompat/getline.c new file mode 100644 index 0000000..edc073f --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/getline.c @@ -0,0 +1,56 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" +#include + +#define INITIAL_SIZE 16 +#define DELIMITER '\n' + +ssize_t +getline (char **lineptr, size_t * n, FILE * stream) +{ + ssize_t written = 0; + int character; + + if (*lineptr == NULL || *n < INITIAL_SIZE) { + free (*lineptr); + *lineptr = (char *) malloc (INITIAL_SIZE); + *n = INITIAL_SIZE; + } + + while ((character = fgetc (stream)) != EOF) { + written += 1; + if (written >= *n) { + *n = *n * 2; + *lineptr = realloc (*lineptr, *n); + } + + (*lineptr)[written - 1] = character; + + if (character == DELIMITER) { + break; + } + } + + (*lineptr)[written] = '\0'; + + return written; +} diff --git a/libs/gst/check/libcheck/libcompat/gettimeofday.c b/libs/gst/check/libcheck/libcompat/gettimeofday.c new file mode 100644 index 0000000..78b327e --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/gettimeofday.c @@ -0,0 +1,49 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" +#include + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + +int +gettimeofday (struct timeval *tv, void *tz) +{ +#if _MSC_VER + union + { + __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } now; + + GetSystemTimeAsFileTime (&now.ft); + tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL); + tv->tv_sec = (long) ((now.ns100 - EPOCHFILETIME) / 10000000LL); + return (0); +#else + // Return that there is no implementation of this on the system + errno = ENOSYS; + return -1; +#endif /* _MSC_VER */ +} diff --git a/libs/gst/check/libcheck/libcompat/libcompat.c b/libs/gst/check/libcheck/libcompat/libcompat.c new file mode 100644 index 0000000..fefcf38 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/libcompat.c @@ -0,0 +1,35 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +/* silence warnings about an empty library */ +void +ck_do_nothing (void) +{ + assert (0); + + /* + * to silence warning about this function actually + * returning, but being marked as noreturn. assert() + * must be marked as a function that returns. + */ + exit (1); +} diff --git a/libs/gst/check/libcheck/libcompat/libcompat.h b/libs/gst/check/libcheck/libcompat/libcompat.h new file mode 100644 index 0000000..b88121b --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/libcompat.h @@ -0,0 +1,237 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef LIBCOMPAT_H +#define LIBCOMPAT_H + +#if HAVE_CONFIG_H +#include +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define GCC_VERSION_AT_LEAST(major, minor) \ +((__GNUC__ > (major)) || \ + (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) +#else +#define GCC_VERSION_AT_LEAST(major, minor) 0 +#endif + +#if GCC_VERSION_AT_LEAST(2,95) +#define CK_ATTRIBUTE_UNUSED __attribute__ ((unused)) +#else +#define CK_ATTRIBUTE_UNUSED +#endif /* GCC 2.95 */ + +#if GCC_VERSION_AT_LEAST(2,5) +#define CK_ATTRIBUTE_NORETURN __attribute__ ((noreturn)) +#else +#define CK_ATTRIBUTE_NORETURN +#endif /* GCC 2.5 */ + +/* + * Used for MSVC to create the export attribute + * CK_DLL_EXP is defined during the compilation of the library + * on the command line. + */ +#ifndef CK_DLL_EXP +#define CK_DLL_EXP extern +#endif + +#if _MSC_VER +#include /* struct timeval, API used in gettimeofday implementation */ +#include /* read, write */ +#include /* getpid */ +#include /* for ssize_t */ +typedef SSIZE_T ssize_t; +#endif /* _MSC_VER */ + +/* defines size_t */ +#include + +/* provides assert */ +#include + +/* defines FILE */ +#include + +/* defines exit() */ +#include + +/* provides localtime and struct tm */ +#ifdef HAVE_SYS_TIME_H +#include +#endif /* !HAVE_SYS_TIME_H */ +#include + +/* declares fork(), _POSIX_VERSION. according to Autoconf.info, + unistd.h defines _POSIX_VERSION if the system is POSIX-compliant, + so we will use this as a test for all things uniquely provided by + POSIX like sigaction() and fork() */ +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +/* declares pthread_create and friends */ +#ifdef HAVE_PTHREAD +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +/* replacement functions for broken originals */ +#if !HAVE_DECL_ALARM +CK_DLL_EXP unsigned int alarm (unsigned int seconds); +#endif /* !HAVE_DECL_ALARM */ + +#if !HAVE_MALLOC +CK_DLL_EXP void *rpl_malloc (size_t n); +#endif /* !HAVE_MALLOC */ + +#if !HAVE_REALLOC +CK_DLL_EXP void *rpl_realloc (void *p, size_t n); +#endif /* !HAVE_REALLOC */ + +#if !HAVE_GETPID && HAVE__GETPID +#define getpid _getpid +#endif /* !HAVE_GETPID && HAVE__GETPID */ + +#if !HAVE_GETTIMEOFDAY +CK_DLL_EXP int gettimeofday (struct timeval *tv, void *tz); +#endif /* !HAVE_GETTIMEOFDAY */ + +#if !HAVE_DECL_LOCALTIME_R +#if !defined(localtime_r) +CK_DLL_EXP struct tm *localtime_r (const time_t * clock, struct tm *result); +#endif +#endif /* !HAVE_DECL_LOCALTIME_R */ + +#if !HAVE_DECL_STRDUP && !HAVE__STRDUP +CK_DLL_EXP char *strdup (const char *str); +#elif !HAVE_DECL_STRDUP && HAVE__STRDUP +#define strdup _strdup +#endif /* !HAVE_DECL_STRDUP && HAVE__STRDUP */ + +#if !HAVE_DECL_STRSIGNAL +CK_DLL_EXP char *strsignal (int sig); +#endif /* !HAVE_DECL_STRSIGNAL */ + +/* + * On systems where clock_gettime() is not available, or + * on systems where some clocks may not be supported, the + * definition for CLOCK_MONOTONIC and CLOCK_REALTIME may not + * be available. These should define which type of clock + * clock_gettime() should use. We define it here if it is + * not defined simply so the reimplementation can ignore it. + * + * We set the values of these clocks to some (hopefully) + * invalid value, to avoid the case where we define a + * clock with a valid value, and unintentionally use + * an actual good clock by accident. + */ +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC -1 +#endif +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME -1 +#endif + +#ifndef HAVE_LIBRT + +#ifdef STRUCT_TIMESPEC_DEFINITION_MISSING +/* + * The following structure is defined in POSIX 1003.1 for times + * specified in seconds and nanoseconds. If it is not defined in + * time.g, then we need to define it here + */ +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; +#endif /* STRUCT_TIMESPEC_DEFINITION_MISSING */ + +#ifdef STRUCT_ITIMERSPEC_DEFINITION_MISSING +/* + * The following structure is defined in POSIX.1b for timer start values and intervals. + * If it is not defined in time.h, then we need to define it here. + */ +struct itimerspec +{ + struct timespec it_interval; + struct timespec it_value; +}; +#endif /* STRUCT_ITIMERSPEC_DEFINITION_MISSING */ + +/* + * Do a simple forward declaration in case the struct is not defined. + * In the versions of timer_create in libcompat, sigevent is never + * used. + */ +struct sigevent; + +#ifndef HAVE_CLOCK_GETTIME +CK_DLL_EXP int clock_gettime (clockid_t clk_id, struct timespec *ts); +#endif +CK_DLL_EXP int timer_create (clockid_t clockid, struct sigevent *sevp, + timer_t * timerid); +CK_DLL_EXP int timer_settime (timer_t timerid, int flags, + const struct itimerspec *new_value, struct itimerspec *old_value); +CK_DLL_EXP int timer_delete (timer_t timerid); +#endif /* HAVE_LIBRT */ + +/* + * The following checks are to determine if the system's + * snprintf (or its variants) should be replaced with + * the C99 compliant version in libcompat. + */ +#if HAVE_CONFIG_H +#include +#endif +#if HAVE_STDARG_H +#include + +#if !HAVE_VSNPRINTF +CK_DLL_EXP int rpl_vsnprintf (char *, size_t, const char *, va_list); + +#define vsnprintf rpl_vsnprintf +#endif +#if !HAVE_SNPRINTF +CK_DLL_EXP int rpl_snprintf (char *, size_t, const char *, ...); + +#define snprintf rpl_snprintf +#endif +#endif /* HAVE_STDARG_H */ + +#if !HAVE_GETLINE +CK_DLL_EXP ssize_t getline (char **lineptr, size_t * n, FILE * stream); +#endif + +/* silence warnings about an empty library */ +CK_DLL_EXP void +ck_do_nothing (void) + CK_ATTRIBUTE_NORETURN; + +#endif /* !LIBCOMPAT_H */ diff --git a/libs/gst/check/libcheck/libcompat/localtime_r.c b/libs/gst/check/libcheck/libcompat/localtime_r.c new file mode 100644 index 0000000..06ac582 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/localtime_r.c @@ -0,0 +1,39 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +#if !defined(localtime_r) + +struct tm * +localtime_r (const time_t * clock, struct tm *result) +{ + struct tm *now = localtime (clock); + + if (now == NULL) { + return NULL; + } else { + *result = *now; + } + + return result; +} + +#endif /* !defined(localtime_r) */ diff --git a/libs/gst/check/libcheck/libcompat/strdup.c b/libs/gst/check/libcheck/libcompat/strdup.c new file mode 100644 index 0000000..1d6aa61 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/strdup.c @@ -0,0 +1,28 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +char * +strdup (const char *str CK_ATTRIBUTE_UNUSED) +{ + assert (0); + return NULL; +} diff --git a/libs/gst/check/libcheck/libcompat/strsignal.c b/libs/gst/check/libcheck/libcompat/strsignal.c new file mode 100644 index 0000000..fd93ad5 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/strsignal.c @@ -0,0 +1,30 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +char * +strsignal (int sig) +{ + static char signame[40]; + + sprintf (signame, "SIG #%d", sig); + return signame; +} diff --git a/libs/gst/check/libcheck/libcompat/timer_create.c b/libs/gst/check/libcheck/libcompat/timer_create.c new file mode 100644 index 0000000..2e250f0 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/timer_create.c @@ -0,0 +1,35 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +int +timer_create (clockid_t clockid CK_ATTRIBUTE_UNUSED, + struct sigevent *sevp CK_ATTRIBUTE_UNUSED, + timer_t * timerid CK_ATTRIBUTE_UNUSED) +{ + /* + * The create function does nothing. timer_settime will use + * alarm to set the timer, and timer_delete will stop the + * alarm + */ + + return 0; +} diff --git a/libs/gst/check/libcheck/libcompat/timer_delete.c b/libs/gst/check/libcheck/libcompat/timer_delete.c new file mode 100644 index 0000000..5740bd6 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/timer_delete.c @@ -0,0 +1,53 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +int +timer_delete (timer_t timerid CK_ATTRIBUTE_UNUSED) +{ +#ifdef HAVE_SETITIMER + /* + * If the system does not have timer_settime() but does have + * setitimer() use that instead of alarm(). + */ + struct itimerval interval; + + /* + * Setting values to '0' results in disabling the running timer. + */ + interval.it_value.tv_sec = 0; + interval.it_value.tv_usec = 0; + interval.it_interval.tv_sec = 0; + interval.it_interval.tv_usec = 0; + + return setitimer (ITIMER_REAL, &interval, NULL); +#else + /* + * There is only one timer, that used by alarm. + * Setting alarm(0) will not set a new alarm, and + * will kill the previous timer. + */ + + alarm (0); + + return 0; +#endif +} diff --git a/libs/gst/check/libcheck/libcompat/timer_settime.c b/libs/gst/check/libcheck/libcompat/timer_settime.c new file mode 100644 index 0000000..db2b1d5 --- /dev/null +++ b/libs/gst/check/libcheck/libcompat/timer_settime.c @@ -0,0 +1,57 @@ +/* + * Check: a unit test framework for C + * Copyright (C) 2001, 2002 Arien Malec + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "libcompat.h" + +int +timer_settime (timer_t timerid CK_ATTRIBUTE_UNUSED, + int flags CK_ATTRIBUTE_UNUSED, + const struct itimerspec *new_value, + struct itimerspec *old_value CK_ATTRIBUTE_UNUSED) +{ +#ifdef HAVE_SETITIMER + /* + * If the system does not have timer_settime() but does have + * setitimer() use that instead of alarm(). + */ + struct itimerval interval; + + interval.it_value.tv_sec = new_value->it_value.tv_sec; + interval.it_value.tv_usec = new_value->it_value.tv_nsec / 1000; + interval.it_interval.tv_sec = new_value->it_interval.tv_sec; + interval.it_interval.tv_usec = new_value->it_interval.tv_nsec / 1000; + + return setitimer (ITIMER_REAL, &interval, NULL); +#else + int seconds = new_value->it_value.tv_sec; + + /* + * As the alarm() call has only second precision, if the caller + * specifies partial seconds, we round up to the nearest second. + */ + if (new_value->it_value.tv_nsec > 0) { + seconds += 1; + } + + alarm (seconds); + + return 0; +#endif +} diff --git a/libs/gst/check/libcheck/meson.build b/libs/gst/check/libcheck/meson.build new file mode 100644 index 0000000..17d3f01 --- /dev/null +++ b/libs/gst/check/libcheck/meson.build @@ -0,0 +1,89 @@ +libcheck_files = [ + 'check.c', + 'check_error.c', + 'check_list.c', + 'check_log.c', + 'check_msg.c', + 'check_pack.c', + 'check_print.c', + 'check_run.c', + 'check_str.c', + 'libcompat/libcompat.c' +] + +if not cdata.has('HAVE_ALARM') + libcheck_files += ['libcompat/alarm.c'] +endif + +if not cdata.has('HAVE_GETTIMEOFDAY') + libcheck_files += ['libcompat/gettimeofday.c'] +endif + +if not cdata.has('HAVE_CLOCK_GETTIME') + libcheck_files += ['libcompat/clock_gettime.c'] +endif + +if not cdata.has('HAVE_DECL_LOCALTIME_R') + libcheck_files += ['libcompat/localtime_r.c'] +endif + +if not cdata.has('HAVE_DECL_STRSIGNAL') + libcheck_files += ['libcompat/strsignal.c'] +endif + +if not cdata.has('HAVE_DECL_STRDUP') and not cdata.has('HAVE__STRDUP') + libcheck_files += ['libcompat/strdup.c'] +endif + +if not cdata.has('HAVE_GETLINE') + libcheck_files += ['libcompat/getline.c'] +endif + +# FIXME: check that timer_create, timer_settime, timer_delete are in rt_lib +if not rt_lib.found() + libcheck_files += [ + 'libcompat/timer_create.c', + 'libcompat/timer_settime.c', + 'libcompat/timer_delete.c' + ] +endif + +configure_file(input : 'check.h.in', + output : 'check.h', + configuration : check_cdata) + +internal_check_h_inc = include_directories('..') + +# Must explicitly make symbols public if default visibility is hidden +if have_visibility_hidden + libcheck_visibility_args = ['-DCK_DLL_EXP=extern __attribute__ ((visibility ("default")))'] +else + if host_system == 'windows' + libcheck_visibility_args = ['-DCK_DLL_EXP=__declspec(dllexport)'] + else + libcheck_visibility_args = ['-DCK_DLL_EXP=extern'] + endif +endif + +no_warn_args = [] +foreach arg : [ + '-Wno-undef', + '-Wno-redundant-decls', + '-Wno-missing-prototypes', + '-Wno-missing-declarations', + '-Wno-old-style-definition', + '-Wno-declaration-after-statement'] + if cc.has_argument(arg) + no_warn_args += [arg] + endif +endforeach + +libcheck = static_library('check', + libcheck_files, + include_directories : [configinc, internal_check_h_inc], + dependencies : [rt_lib, mathlib], + c_args: gst_c_args + libcheck_visibility_args + no_warn_args + + # Don't want libcompat to think we don't have these and substitute + # replacements since we don't check for or define these. See libcompat.h + ['-DHAVE_VSNPRINTF', '-DHAVE_SNPRINTF', '-DHAVE_MALLOC', '-DHAVE_REALLOC'], + pic: true) diff --git a/libs/gst/check/meson.build b/libs/gst/check/meson.build new file mode 100644 index 0000000..d6e8d21 --- /dev/null +++ b/libs/gst/check/meson.build @@ -0,0 +1,73 @@ +gst_check_sources = [ + 'gstbufferstraw.c', + 'gstcheck.c', + 'gstconsistencychecker.c', + 'gstharness.c', + 'gsttestclock.c', +] +gst_check_headers = [ + 'check.h', + 'check-prelude.h', + 'gstbufferstraw.h', + 'gstcheck.h', + 'gstconsistencychecker.h', + 'gstharness.h', + 'gsttestclock.h', +] +install_headers(gst_check_headers, subdir : 'gstreamer-1.0/gst/check/') + + +check_cdata = configuration_data() + +check_cdata.set('ENABLE_SUBUNIT', 0) +check_cdata.set('CHECK_MAJOR_VERSION', 0) +check_cdata.set('CHECK_MINOR_VERSION', 9) +check_cdata.set('CHECK_MICRO_VERSION', 14) +if host_machine.system() != 'windows' + check_cdata.set('HAVE_FORK', 1) +else + check_cdata.set('HAVE_FORK', 0) +endif + +subdir('libcheck') + +configure_file(input : 'libcheck/check.h.in', + output : 'internal-check.h', + install : true, + install_dir : 'include/gstreamer-1.0/gst/check/', + configuration : check_cdata) + +gst_check = shared_library('gstcheck-@0@'.format(apiversion), + gst_check_sources, + c_args : gst_c_args + ['-DGST_EXPORTS'], + version : libversion, + soversion : soversion, + install : true, + include_directories : [configinc, libsinc], + link_with : [libcheck], + dependencies : [gobject_dep, glib_dep, gst_dep], +) + +gst_check_gen_sources = [] + +if build_gir + gst_gir_extra_args = gir_init_section + [ '--c-include=gst/check/check.h' ] + gst_check_gen_sources += [gnome.generate_gir(gst_check, + sources : gst_check_sources + gst_check_headers, + namespace : 'GstCheck', + nsversion : apiversion, + identifier_prefix : 'Gst', + symbol_prefix : 'gst', + export_packages : 'gstreamer-check-1.0', + dependencies : [gst_dep], + include_directories : [configinc, libsinc, privinc], + includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'], + install : true, + extra_args : gst_gir_extra_args, + )] +endif + +gst_check_dep = declare_dependency(link_with : gst_check, + include_directories : [libsinc], + dependencies : [gst_dep], + sources : gst_check_gen_sources) diff --git a/libs/gst/controller/Makefile.am b/libs/gst/controller/Makefile.am new file mode 100644 index 0000000..b1675c7 --- /dev/null +++ b/libs/gst/controller/Makefile.am @@ -0,0 +1,103 @@ +lib_LTLIBRARIES = libgstcontroller-@GST_API_VERSION@.la + +glib_enum_headers= \ + gstinterpolationcontrolsource.h \ + gstlfocontrolsource.h + +glib_enum_define = GST_CONTROLLER +glib_gen_prefix = gst +glib_gen_basename = controller +glib_gen_decl_banner=GST_CONTROLLER_API +glib_gen_decl_include=\#include + +built_sources = controller-enumtypes.c +built_headers = controller-enumtypes.h +BUILT_SOURCES = $(built_sources) $(built_headers) + +libgstcontroller_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/controller +libgstcontroller_@GST_API_VERSION@_include_HEADERS = \ + controller.h \ + controller-prelude.h \ + gstargbcontrolbinding.h \ + gstdirectcontrolbinding.h \ + gsttimedvaluecontrolsource.h \ + gstinterpolationcontrolsource.h \ + gstproxycontrolbinding.h \ + gsttriggercontrolsource.h \ + gstlfocontrolsource.h + +nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS = \ + controller-enumtypes.h + +libgstcontroller_@GST_API_VERSION@_la_SOURCES = \ + gstargbcontrolbinding.c \ + gstdirectcontrolbinding.c \ + gsttimedvaluecontrolsource.c \ + gstinterpolationcontrolsource.c \ + gstproxycontrolbinding.c \ + gsttriggercontrolsource.c \ + gstlfocontrolsource.c + +nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES = $(BUILT_SOURCES) + +libgstcontroller_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstcontroller_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(LIBM) +libgstcontroller_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +CLEANFILES = *.gcno *.gcda *.gcov $(BUILT_SOURCES) + +%.c.gcov: .libs/libgstcontroller_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcontroller_@GST_API_VERSION@_la_SOURCES:=.gcov) + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstController-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstcontroller_@GST_API_VERSION@_include_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstcontroller_@GST_API_VERSION@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES)) + +GstController-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@GST_API_VERSION@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ + GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ + CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ + $(INTROSPECTION_SCANNER) -v --namespace GstController \ + --nsversion=@GST_API_VERSION@ \ + --warn-all \ + --identifier-prefix=Gst \ + --symbol-prefix=gst \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libs \ + -I$(top_builddir) \ + -I$(top_builddir)/libs \ + --c-include "gst/controller/controller.h" \ + --add-include-path=$(top_builddir)/gst \ + --library-path=$(top_builddir)/gst \ + --library=libgstcontroller-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --libtool="${LIBTOOL}" \ + --pkg gstreamer-@GST_API_VERSION@ \ + --pkg-export gstreamer-controller-@GST_API_VERSION@ \ + --add-init-section="$(INTROSPECTION_INIT)" \ + --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)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif diff --git a/libs/gst/controller/Makefile.in b/libs/gst/controller/Makefile.in new file mode 100644 index 0000000..0e82941 --- /dev/null +++ b/libs/gst/controller/Makefile.in @@ -0,0 +1,1110 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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 +#glib_gen_decl_banner=GST_EXPORT +#glib_gen_decl_include=\#include + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = libs/gst/controller +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libgstcontroller_@GST_API_VERSION@_include_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" \ + "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgstcontroller_@GST_API_VERSION@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libgstcontroller_@GST_API_VERSION@_la_OBJECTS = libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo \ + libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo \ + libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo \ + libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo \ + libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo \ + libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo \ + libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo +am__objects_1 = \ + libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo +am__objects_2 = +am__objects_3 = $(am__objects_1) $(am__objects_2) +nodist_libgstcontroller_@GST_API_VERSION@_la_OBJECTS = \ + $(am__objects_3) +libgstcontroller_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstcontroller_@GST_API_VERSION@_la_OBJECTS) \ + $(nodist_libgstcontroller_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstcontroller_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) \ + $(CFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstcontroller_@GST_API_VERSION@_la_SOURCES) \ + $(nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgstcontroller_@GST_API_VERSION@_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstcontroller_@GST_API_VERSION@_include_HEADERS) \ + $(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/common/gst-glib-gen.mak $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libgstcontroller-@GST_API_VERSION@.la +glib_enum_headers = \ + gstinterpolationcontrolsource.h \ + gstlfocontrolsource.h + +glib_enum_define = GST_CONTROLLER +glib_gen_prefix = gst +glib_gen_basename = controller +glib_gen_decl_banner = GST_CONTROLLER_API +glib_gen_decl_include = \#include +built_sources = controller-enumtypes.c +built_headers = controller-enumtypes.h +BUILT_SOURCES = $(built_sources) $(built_headers) +libgstcontroller_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/controller +libgstcontroller_@GST_API_VERSION@_include_HEADERS = \ + controller.h \ + controller-prelude.h \ + gstargbcontrolbinding.h \ + gstdirectcontrolbinding.h \ + gsttimedvaluecontrolsource.h \ + gstinterpolationcontrolsource.h \ + gstproxycontrolbinding.h \ + gsttriggercontrolsource.h \ + gstlfocontrolsource.h + +nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS = \ + controller-enumtypes.h + +libgstcontroller_@GST_API_VERSION@_la_SOURCES = \ + gstargbcontrolbinding.c \ + gstdirectcontrolbinding.c \ + gsttimedvaluecontrolsource.c \ + gstinterpolationcontrolsource.c \ + gstproxycontrolbinding.c \ + gsttriggercontrolsource.c \ + gstlfocontrolsource.c + +nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES = $(BUILT_SOURCES) +libgstcontroller_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstcontroller_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(LIBM) +libgstcontroller_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +CLEANFILES = *.gcno *.gcda *.gcov $(BUILT_SOURCES) $(am__append_1) +enum_headers = $(foreach h,$(glib_enum_headers),\n\#include \"$(h)\") +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstController-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(libgstcontroller_@GST_API_VERSION@_include_HEADERS)) \ +@HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS)) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(libgstcontroller_@GST_API_VERSION@_la_SOURCES)) \ +@HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ +@HAVE_INTROSPECTION_TRUE@ $(nodist_libgstcontroller_@GST_API_VERSION@_la_SOURCES)) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/gst-glib-gen.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/controller/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/controller/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/gst-glib-gen.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstcontroller-@GST_API_VERSION@.la: $(libgstcontroller_@GST_API_VERSION@_la_OBJECTS) $(libgstcontroller_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstcontroller_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstcontroller_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstcontroller_@GST_API_VERSION@_la_OBJECTS) $(libgstcontroller_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo: gstargbcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo `test -f 'gstargbcontrolbinding.c' || echo '$(srcdir)/'`gstargbcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstargbcontrolbinding.c' object='libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gstargbcontrolbinding.lo `test -f 'gstargbcontrolbinding.c' || echo '$(srcdir)/'`gstargbcontrolbinding.c + +libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo: gstdirectcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo `test -f 'gstdirectcontrolbinding.c' || echo '$(srcdir)/'`gstdirectcontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdirectcontrolbinding.c' object='libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gstdirectcontrolbinding.lo `test -f 'gstdirectcontrolbinding.c' || echo '$(srcdir)/'`gstdirectcontrolbinding.c + +libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo: gsttimedvaluecontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo `test -f 'gsttimedvaluecontrolsource.c' || echo '$(srcdir)/'`gsttimedvaluecontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttimedvaluecontrolsource.c' object='libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gsttimedvaluecontrolsource.lo `test -f 'gsttimedvaluecontrolsource.c' || echo '$(srcdir)/'`gsttimedvaluecontrolsource.c + +libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo: gstinterpolationcontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo `test -f 'gstinterpolationcontrolsource.c' || echo '$(srcdir)/'`gstinterpolationcontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstinterpolationcontrolsource.c' object='libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gstinterpolationcontrolsource.lo `test -f 'gstinterpolationcontrolsource.c' || echo '$(srcdir)/'`gstinterpolationcontrolsource.c + +libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo: gstproxycontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo `test -f 'gstproxycontrolbinding.c' || echo '$(srcdir)/'`gstproxycontrolbinding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstproxycontrolbinding.c' object='libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gstproxycontrolbinding.lo `test -f 'gstproxycontrolbinding.c' || echo '$(srcdir)/'`gstproxycontrolbinding.c + +libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo: gsttriggercontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo `test -f 'gsttriggercontrolsource.c' || echo '$(srcdir)/'`gsttriggercontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttriggercontrolsource.c' object='libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gsttriggercontrolsource.lo `test -f 'gsttriggercontrolsource.c' || echo '$(srcdir)/'`gsttriggercontrolsource.c + +libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo: gstlfocontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo `test -f 'gstlfocontrolsource.c' || echo '$(srcdir)/'`gstlfocontrolsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstlfocontrolsource.c' object='libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-gstlfocontrolsource.lo `test -f 'gstlfocontrolsource.c' || echo '$(srcdir)/'`gstlfocontrolsource.c + +libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo: controller-enumtypes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo -MD -MP -MF $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.Tpo -c -o libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo `test -f 'controller-enumtypes.c' || echo '$(srcdir)/'`controller-enumtypes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.Tpo $(DEPDIR)/libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='controller-enumtypes.c' object='libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcontroller_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstcontroller_@GST_API_VERSION@_la-controller-enumtypes.lo `test -f 'controller-enumtypes.c' || echo '$(srcdir)/'`controller-enumtypes.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstcontroller_@GST_API_VERSION@_includeHEADERS: $(libgstcontroller_@GST_API_VERSION@_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstcontroller_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstcontroller_@GST_API_VERSION@_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" || exit $$?; \ + done + +uninstall-libgstcontroller_@GST_API_VERSION@_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstcontroller_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstcontroller_@GST_API_VERSION@_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'; $(am__uninstall_files_from_dir) +install-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS: $(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstcontroller_@GST_API_VERSION@_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" || exit $$?; \ + done + +uninstall-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libgstcontroller_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstcontroller_@GST_API_VERSION@_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)" "$(DESTDIR)$(libgstcontroller_@GST_API_VERSION@_includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-girDATA \ + install-libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + install-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + uninstall-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: all check install install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-girDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES \ + install-libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + install-man \ + install-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + uninstall-nodist_libgstcontroller_@GST_API_VERSION@_includeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +%.c.gcov: .libs/libgstcontroller_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcontroller_@GST_API_VERSION@_la_SOURCES:=.gcov) + +# 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$(glib_gen_decl_include)\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "$(glib_gen_decl_banner)\nGType @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 $@ + +@HAVE_INTROSPECTION_TRUE@GstController-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ +@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ +@HAVE_INTROSPECTION_TRUE@ CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstController \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Gst \ +@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=gst \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir)/libs \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir)/libs \ +@HAVE_INTROSPECTION_TRUE@ --c-include "gst/controller/controller.h" \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstcontroller-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-controller-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --add-init-section="$(INTROSPECTION_INIT)" \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/controller/controller-prelude.h b/libs/gst/controller/controller-prelude.h new file mode 100644 index 0000000..852b53d --- /dev/null +++ b/libs/gst/controller/controller-prelude.h @@ -0,0 +1,31 @@ +/* GStreamer Controller Library + * Copyright (C) 2018 GStreamer developers + * + * controller-prelude.h: prelude include header for gst-controller 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONTROLLER_PRELUDE_H__ +#define __GST_CONTROLLER_PRELUDE_H__ + +#include + +#ifndef GST_CONTROLLER_API +#define GST_CONTROLLER_API GST_EXPORT +#endif + +#endif /* __GST_CONTROLLER_PRELUDE_H__ */ diff --git a/libs/gst/controller/controller.h b/libs/gst/controller/controller.h new file mode 100644 index 0000000..79ae8ce --- /dev/null +++ b/libs/gst/controller/controller.h @@ -0,0 +1,35 @@ +/* GStreamer + * Copyright (C) 2012 GStreamer developers + * + * gstcontroller.h: single include header for gst-controller 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_CONTROLLER_H__ +#define __GST_CONTROLLER_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif /* __GST_CONTROLLER_H__ */ diff --git a/libs/gst/controller/controller_mkenum.py b/libs/gst/controller/controller_mkenum.py new file mode 100755 index 0000000..01d8478 --- /dev/null +++ b/libs/gst/controller/controller_mkenum.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +# This is in its own file rather than inside meson.build +# because a) mixing the two is ugly and b) trying to +# make special characters such as \n go through all +# backends is a fool's errand. + +import sys, os, shutil, subprocess + +h_array = ['--fhead', + "#ifndef __GST_CONTROLLER_ENUM_TYPES_H__\n#define __GST_CONTROLLER_ENUM_TYPES_H__\n\n#include \n#include \n#include \n\nG_BEGIN_DECLS\n", + '--fprod', + "\n/* enumerations from \"@filename@\" */\n", + '--vhead', + 'GST_CONTROLLER_API\nGType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n', + '--ftail', + 'G_END_DECLS\n\n#endif /* __GST_CONTROLLER_ENUM_TYPES_H__ */', + ] + +c_array = ['--fhead', + "#include \"controller-enumtypes.h\"\n\n#include \"controller.h\" \n#include \"gstinterpolationcontrolsource.h\" \n#include \"gstlfocontrolsource.h\"", + '--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", + ] + +cmd = [] +argn = 1 +# Find the full command needed to run glib-mkenums +# On UNIX-like, this is just the full path to glib-mkenums +# On Windows, this is the full path to interpreter + full path to glib-mkenums +for arg in sys.argv[1:]: + cmd.append(arg) + argn += 1 + if arg.endswith('glib-mkenums'): + break +ofilename = sys.argv[argn] +headers = sys.argv[argn + 1:] + +if ofilename.endswith('.h'): + arg_array = h_array +else: + arg_array = c_array + +cmd_array = cmd + arg_array + headers +pc = subprocess.Popen(cmd_array, stdout=subprocess.PIPE) +(stdo, _) = pc.communicate() +if pc.returncode != 0: + sys.exit(pc.returncode) +open(ofilename, 'wb').write(stdo) diff --git a/libs/gst/controller/gstargbcontrolbinding.c b/libs/gst/controller/gstargbcontrolbinding.c new file mode 100644 index 0000000..6fe79e3 --- /dev/null +++ b/libs/gst/controller/gstargbcontrolbinding.c @@ -0,0 +1,483 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstargbcontrolbinding.c: Attachment for multiple control sources to gargb + * properties + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstargbcontrolbinding + * @title: GstARGBControlBinding + * @short_description: attachment for control sources to argb properties + * + * A value mapping object that attaches multiple control sources to a guint + * gobject properties representing a color. A control value of 0.0 will turn the + * color component off and a value of 1.0 will be the color level. + */ + +#include +#include + +#include "gstargbcontrolbinding.h" + +#include + +#define GST_CAT_DEFAULT control_binding_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +static GObject *gst_argb_control_binding_constructor (GType type, + guint n_construct_params, GObjectConstructParam * construct_params); +static void gst_argb_control_binding_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_argb_control_binding_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_argb_control_binding_dispose (GObject * object); +static void gst_argb_control_binding_finalize (GObject * object); + +static gboolean gst_argb_control_binding_sync_values (GstControlBinding * _self, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync); +static GValue *gst_argb_control_binding_get_value (GstControlBinding * _self, + GstClockTime timestamp); +static gboolean gst_argb_control_binding_get_value_array (GstControlBinding * + _self, GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values); +static gboolean gst_argb_control_binding_get_g_value_array (GstControlBinding * + _self, GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstargbcontrolbinding", 0, \ + "dynamic parameter control source attachment"); + +#define gst_argb_control_binding_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstARGBControlBinding, gst_argb_control_binding, + GST_TYPE_CONTROL_BINDING, _do_init); + +enum +{ + PROP_0, + PROP_CS_A, + PROP_CS_R, + PROP_CS_G, + PROP_CS_B, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +/* vmethods */ + +static void +gst_argb_control_binding_class_init (GstARGBControlBindingClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstControlBindingClass *control_binding_class = + GST_CONTROL_BINDING_CLASS (klass); + + gobject_class->constructor = gst_argb_control_binding_constructor; + gobject_class->set_property = gst_argb_control_binding_set_property; + gobject_class->get_property = gst_argb_control_binding_get_property; + gobject_class->dispose = gst_argb_control_binding_dispose; + gobject_class->finalize = gst_argb_control_binding_finalize; + + control_binding_class->sync_values = gst_argb_control_binding_sync_values; + control_binding_class->get_value = gst_argb_control_binding_get_value; + control_binding_class->get_value_array = + gst_argb_control_binding_get_value_array; + control_binding_class->get_g_value_array = + gst_argb_control_binding_get_g_value_array; + + properties[PROP_CS_A] = + g_param_spec_object ("control-source-a", "ControlSource A", + "The control source for the alpha color component", + GST_TYPE_CONTROL_SOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_CS_R] = + g_param_spec_object ("control-source-r", "ControlSource R", + "The control source for the red color component", + GST_TYPE_CONTROL_SOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_CS_G] = + g_param_spec_object ("control-source-g", "ControlSource G", + "The control source for the green color component", + GST_TYPE_CONTROL_SOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_CS_B] = + g_param_spec_object ("control-source-b", "ControlSource B", + "The control source for the blue color component", + GST_TYPE_CONTROL_SOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, properties); +} + +static void +gst_argb_control_binding_init (GstARGBControlBinding * self) +{ +} + +static GObject * +gst_argb_control_binding_constructor (GType type, guint n_construct_params, + GObjectConstructParam * construct_params) +{ + GstARGBControlBinding *self; + + self = + GST_ARGB_CONTROL_BINDING (G_OBJECT_CLASS (parent_class)->constructor + (type, n_construct_params, construct_params)); + + if (GST_CONTROL_BINDING_PSPEC (self)) { + if (!(G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self)) == + G_TYPE_UINT)) { + GST_WARNING ("can't bind to paramspec type '%s'", + G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self))); + GST_CONTROL_BINDING_PSPEC (self) = NULL; + } else { + g_value_init (&self->cur_value, G_TYPE_UINT); + } + } + return (GObject *) self; +} + +static void +gst_argb_control_binding_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_CS_A: + gst_object_replace ((GstObject **) & self->cs_a, + g_value_get_object (value)); + break; + case PROP_CS_R: + gst_object_replace ((GstObject **) & self->cs_r, + g_value_get_object (value)); + break; + case PROP_CS_G: + gst_object_replace ((GstObject **) & self->cs_g, + g_value_get_object (value)); + break; + case PROP_CS_B: + gst_object_replace ((GstObject **) & self->cs_b, + g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_argb_control_binding_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_CS_A: + g_value_set_object (value, self->cs_a); + break; + case PROP_CS_R: + g_value_set_object (value, self->cs_r); + break; + case PROP_CS_G: + g_value_set_object (value, self->cs_g); + break; + case PROP_CS_B: + g_value_set_object (value, self->cs_b); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_argb_control_binding_dispose (GObject * object) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object); + + gst_object_replace ((GstObject **) & self->cs_a, NULL); + gst_object_replace ((GstObject **) & self->cs_r, NULL); + gst_object_replace ((GstObject **) & self->cs_g, NULL); + gst_object_replace ((GstObject **) & self->cs_b, NULL); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_argb_control_binding_finalize (GObject * object) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (object); + + g_value_unset (&self->cur_value); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_argb_control_binding_sync_values (GstControlBinding * _self, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self); + gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT, + _self->name, GST_TIME_ARGS (timestamp)); + + if (self->cs_a) + ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a); + if (self->cs_r) + ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r); + if (self->cs_g) + ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g); + if (self->cs_b) + ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b); + if (G_LIKELY (ret)) { + guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) | + (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) | + (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) | + ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255)); + GST_LOG_OBJECT (object, " new value 0x%08x", src_val); + /* always set the value for first time, but then only if it changed + * this should limit g_object_notify invocations. + * FIXME: can we detect negative playback rates? + */ + if ((timestamp < last_sync) || (src_val != self->last_value)) { + GValue *dst_val = &self->cur_value; + + g_value_set_uint (dst_val, src_val); + /* we can make this faster + * http://bugzilla.gnome.org/show_bug.cgi?id=536939 + */ + g_object_set_property ((GObject *) object, _self->name, dst_val); + self->last_value = src_val; + } + } else { + GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name); + } + return (ret); +} + +static GValue * +gst_argb_control_binding_get_value (GstControlBinding * _self, + GstClockTime timestamp) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self); + GValue *dst_val = NULL; + gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + /* get current value via control source */ + if (self->cs_a) + ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a); + if (self->cs_r) + ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r); + if (self->cs_g) + ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g); + if (self->cs_b) + ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b); + if (G_LIKELY (ret)) { + guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) | + (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) | + (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) | + ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255)); + dst_val = g_new0 (GValue, 1); + g_value_init (dst_val, G_TYPE_UINT); + g_value_set_uint (dst_val, src_val); + } else { + GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT, + _self->name, GST_TIME_ARGS (timestamp)); + } + + return dst_val; +} + +static gboolean +gst_argb_control_binding_get_value_array (GstControlBinding * _self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values_) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self); + gint i; + gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b = + NULL; + guint *values = (guint *) values_; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + if (self->cs_a) { + src_val_a = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_a, timestamp, + interval, n_values, src_val_a); + } + if (self->cs_r) { + src_val_r = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_r, timestamp, + interval, n_values, src_val_r); + } + if (self->cs_g) { + src_val_g = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_g, timestamp, + interval, n_values, src_val_g); + } + if (self->cs_b) { + src_val_b = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_b, timestamp, + interval, n_values, src_val_b); + } + if (G_LIKELY (ret)) { + for (i = 0; i < n_values; i++) { + gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0; + if (src_val_a && !isnan (src_val_a[i])) + a = src_val_a[i]; + if (src_val_r && !isnan (src_val_r[i])) + r = src_val_r[i]; + if (src_val_g && !isnan (src_val_g[i])) + g = src_val_g[i]; + if (src_val_b && !isnan (src_val_b[i])) + b = src_val_b[i]; + values[i] = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) | + (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) | + (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) | + ((guint) (CLAMP (b, 0.0, 1.0) * 255)); + } + } else { + GST_LOG ("failed to get control value for property %s at ts %" + GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp)); + } + g_free (src_val_a); + g_free (src_val_r); + g_free (src_val_g); + g_free (src_val_b); + return ret; +} + +static gboolean +gst_argb_control_binding_get_g_value_array (GstControlBinding * _self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self); + gint i; + gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b = + NULL; + guint src_val; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + if (self->cs_a) { + src_val_a = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_a, timestamp, + interval, n_values, src_val_a); + } + if (self->cs_r) { + src_val_r = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_r, timestamp, + interval, n_values, src_val_r); + } + if (self->cs_g) { + src_val_g = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_g, timestamp, + interval, n_values, src_val_g); + } + if (self->cs_b) { + src_val_b = g_new0 (gdouble, n_values); + ret &= gst_control_source_get_value_array (self->cs_b, timestamp, + interval, n_values, src_val_b); + } + if (G_LIKELY (ret)) { + for (i = 0; i < n_values; i++) { + gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0; + if (src_val_a && !isnan (src_val_a[i])) + a = src_val_a[i]; + if (src_val_r && !isnan (src_val_r[i])) + r = src_val_r[i]; + if (src_val_g && !isnan (src_val_g[i])) + g = src_val_g[i]; + if (src_val_b && !isnan (src_val_b[i])) + b = src_val_b[i]; + src_val = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) | + (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) | + (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) | + ((guint) (CLAMP (b, 0.0, 1.0) * 255)); + g_value_init (&values[i], G_TYPE_UINT); + g_value_set_uint (&values[i], src_val); + } + } else { + GST_LOG ("failed to get control value for property %s at ts %" + GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp)); + } + g_free (src_val_a); + g_free (src_val_r); + g_free (src_val_g); + g_free (src_val_b); + return ret; +} + +/* functions */ + +/** + * gst_argb_control_binding_new: + * @object: the object of the property + * @property_name: the property-name to attach the control source + * @cs_a: the control source for the alpha channel + * @cs_r: the control source for the red channel + * @cs_g: the control source for the green channel + * @cs_b: the control source for the blue channel + * + * Create a new control-binding that attaches the given #GstControlSource to the + * #GObject property. + * + * Returns: (transfer floating): the new #GstARGBControlBinding + */ +GstControlBinding * +gst_argb_control_binding_new (GstObject * object, const gchar * property_name, + GstControlSource * cs_a, GstControlSource * cs_r, GstControlSource * cs_g, + GstControlSource * cs_b) +{ + return (GstControlBinding *) g_object_new (GST_TYPE_ARGB_CONTROL_BINDING, + "object", object, "name", property_name, + "control-source-a", cs_a, + "control-source-r", cs_r, + "control-source-g", cs_g, "control-source-b", cs_b, NULL); +} + +/* functions */ diff --git a/libs/gst/controller/gstargbcontrolbinding.h b/libs/gst/controller/gstargbcontrolbinding.h new file mode 100644 index 0000000..caabed3 --- /dev/null +++ b/libs/gst/controller/gstargbcontrolbinding.h @@ -0,0 +1,105 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstargbcontrolbinding.h: Attachment for multiple control sources to gargb + * properties + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_ARGB_CONTROL_BINDING_H__ +#define __GST_ARGB_CONTROL_BINDING_H__ + +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_ARGB_CONTROL_BINDING \ + (gst_argb_control_binding_get_type()) +#define GST_ARGB_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ARGB_CONTROL_BINDING,GstARGBControlBinding)) +#define GST_ARGB_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ARGB_CONTROL_BINDING,GstARGBControlBindingClass)) +#define GST_IS_ARGB_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ARGB_CONTROL_BINDING)) +#define GST_IS_ARGB_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ARGB_CONTROL_BINDING)) +#define GST_ARGB_CONTROL_BINDING_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstARGBControlBindingClass)) + +typedef struct _GstARGBControlBinding GstARGBControlBinding; +typedef struct _GstARGBControlBindingClass GstARGBControlBindingClass; + +/** + * GstARGBControlBinding: + * @name: name of the property of this binding + * + * The instance structure of #GstARGBControlBinding. + */ +struct _GstARGBControlBinding { + GstControlBinding parent; + + /*< private >*/ + GstControlSource *cs_a; /* GstControlSources for this property */ + GstControlSource *cs_r; + GstControlSource *cs_g; + GstControlSource *cs_b; + + GValue cur_value; + guint32 last_value; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstARGBControlBindingClass: + * @parent_class: Parent class + * @convert: Class method to convert control-values + * + * The class structure of #GstARGBControlBinding. + */ + +struct _GstARGBControlBindingClass +{ + GstControlBindingClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_argb_control_binding_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GstControlBinding * gst_argb_control_binding_new (GstObject * object, const gchar * property_name, + GstControlSource * cs_a, GstControlSource * cs_r, + GstControlSource * cs_g, GstControlSource * cs_b); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstARGBControlBinding, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_ARGB_CONTROL_BINDING_H__ */ diff --git a/libs/gst/controller/gstdirectcontrolbinding.c b/libs/gst/controller/gstdirectcontrolbinding.c new file mode 100644 index 0000000..9e5955d --- /dev/null +++ b/libs/gst/controller/gstdirectcontrolbinding.c @@ -0,0 +1,549 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstdirectcontrolbinding.c: Direct attachment for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstdirectcontrolbinding + * @title: GstDirectControlBinding + * @short_description: direct attachment for control sources + * + * A value mapping object that attaches control sources to gobject properties. It + * will map the control values directly to the target property range. If a + * non-absolute direct control binding is used, the value range [0.0 ... 1.0] + * is mapped to full target property range, and all values outside the range + * will be clipped. An absolute control binding will not do any value + * transformations. + */ + +#include +#include + +#include "gstdirectcontrolbinding.h" + +#include + +#define GST_CAT_DEFAULT control_binding_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + + +static GObject *gst_direct_control_binding_constructor (GType type, + guint n_construct_params, GObjectConstructParam * construct_params); +static void gst_direct_control_binding_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_direct_control_binding_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_direct_control_binding_dispose (GObject * object); +static void gst_direct_control_binding_finalize (GObject * object); + +static gboolean gst_direct_control_binding_sync_values (GstControlBinding * + _self, GstObject * object, GstClockTime timestamp, GstClockTime last_sync); +static GValue *gst_direct_control_binding_get_value (GstControlBinding * _self, + GstClockTime timestamp); +static gboolean gst_direct_control_binding_get_value_array (GstControlBinding * + _self, GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values); +static gboolean gst_direct_control_binding_get_g_value_array (GstControlBinding + * _self, GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstdirectcontrolbinding", 0, \ + "dynamic parameter control source attachment"); + +#define gst_direct_control_binding_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstDirectControlBinding, gst_direct_control_binding, + GST_TYPE_CONTROL_BINDING, _do_init); + +enum +{ + PROP_0, + PROP_CS, + PROP_ABSOLUTE, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +/* mapping functions */ + +#define DEFINE_CONVERT(type,Type,TYPE,ROUNDING_OP) \ +static void \ +convert_g_value_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \ +{ \ + GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \ + g##type v; \ + \ + s = CLAMP (s, 0.0, 1.0); \ + v = (g##type) ROUNDING_OP (pspec->minimum * (1-s)) + (g##type) ROUNDING_OP (pspec->maximum * s); \ + g_value_set_##type (d, v); \ +} \ +\ +static void \ +convert_value_to_##type (GstDirectControlBinding *self, gdouble s, gpointer d_) \ +{ \ + GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \ + g##type *d = (g##type *)d_; \ + \ + s = CLAMP (s, 0.0, 1.0); \ + *d = (g##type) ROUNDING_OP (pspec->minimum * (1-s)) + (g##type) ROUNDING_OP (pspec->maximum * s); \ +} \ +\ +static void \ +abs_convert_g_value_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \ +{ \ + g##type v; \ + v = (g##type) ROUNDING_OP (s); \ + g_value_set_##type (d, v); \ +} \ +\ +static void \ +abs_convert_value_to_##type (GstDirectControlBinding *self, gdouble s, gpointer d_) \ +{ \ + g##type *d = (g##type *)d_; \ + *d = (g##type) ROUNDING_OP (s); \ +} + +DEFINE_CONVERT (int, Int, INT, rint); +DEFINE_CONVERT (uint, UInt, UINT, rint); +DEFINE_CONVERT (long, Long, LONG, rint); +DEFINE_CONVERT (ulong, ULong, ULONG, rint); +DEFINE_CONVERT (int64, Int64, INT64, rint); +DEFINE_CONVERT (uint64, UInt64, UINT64, rint); +DEFINE_CONVERT (float, Float, FLOAT, /*NOOP*/); +DEFINE_CONVERT (double, Double, DOUBLE, /*NOOP*/); + +static void +convert_g_value_to_boolean (GstDirectControlBinding * self, gdouble s, + GValue * d) +{ + s = CLAMP (s, 0.0, 1.0); + g_value_set_boolean (d, (gboolean) (s + 0.5)); +} + +static void +convert_value_to_boolean (GstDirectControlBinding * self, gdouble s, + gpointer d_) +{ + gboolean *d = (gboolean *) d_; + + s = CLAMP (s, 0.0, 1.0); + *d = (gboolean) (s + 0.5); +} + +static void +convert_g_value_to_enum (GstDirectControlBinding * self, gdouble s, GValue * d) +{ + GParamSpecEnum *pspec = + G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec); + GEnumClass *e = pspec->enum_class; + gint v; + + s = CLAMP (s, 0.0, 1.0); + v = s * (e->n_values - 1); + g_value_set_enum (d, e->values[v].value); +} + +static void +convert_value_to_enum (GstDirectControlBinding * self, gdouble s, gpointer d_) +{ + GParamSpecEnum *pspec = + G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec); + GEnumClass *e = pspec->enum_class; + gint *d = (gint *) d_; + + s = CLAMP (s, 0.0, 1.0); + *d = e->values[(gint) (s * (e->n_values - 1))].value; +} + +/* vmethods */ + +static void +gst_direct_control_binding_class_init (GstDirectControlBindingClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstControlBindingClass *control_binding_class = + GST_CONTROL_BINDING_CLASS (klass); + + gobject_class->constructor = gst_direct_control_binding_constructor; + gobject_class->set_property = gst_direct_control_binding_set_property; + gobject_class->get_property = gst_direct_control_binding_get_property; + gobject_class->dispose = gst_direct_control_binding_dispose; + gobject_class->finalize = gst_direct_control_binding_finalize; + + control_binding_class->sync_values = gst_direct_control_binding_sync_values; + control_binding_class->get_value = gst_direct_control_binding_get_value; + control_binding_class->get_value_array = + gst_direct_control_binding_get_value_array; + control_binding_class->get_g_value_array = + gst_direct_control_binding_get_g_value_array; + + properties[PROP_CS] = + g_param_spec_object ("control-source", "ControlSource", + "The control source", + GST_TYPE_CONTROL_SOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_ABSOLUTE] = + g_param_spec_boolean ("absolute", "Absolute", + "Whether the control values are absolute", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, properties); +} + +static void +gst_direct_control_binding_init (GstDirectControlBinding * self) +{ +} + +static GObject * +gst_direct_control_binding_constructor (GType type, guint n_construct_params, + GObjectConstructParam * construct_params) +{ + GstDirectControlBinding *self; + + self = + GST_DIRECT_CONTROL_BINDING (G_OBJECT_CLASS (parent_class)->constructor + (type, n_construct_params, construct_params)); + + if (GST_CONTROL_BINDING_PSPEC (self)) { + GType type, base; + + base = type = G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self)); + g_value_init (&self->cur_value, type); + while ((type = g_type_parent (type))) + base = type; + + GST_DEBUG (" using type %s", g_type_name (base)); + + /* select mapping function */ + +#define SET_CONVERT_FUNCTION(type) \ + if (self->ABI.abi.want_absolute) { \ + self->convert_g_value = abs_convert_g_value_to_##type; \ + self->convert_value = abs_convert_value_to_##type; \ + } \ + else { \ + self->convert_g_value = convert_g_value_to_##type; \ + self->convert_value = convert_value_to_##type; \ + } \ + self->byte_size = sizeof (g##type); + + + switch (base) { + case G_TYPE_INT: + SET_CONVERT_FUNCTION (int); + break; + case G_TYPE_UINT: + SET_CONVERT_FUNCTION (uint); + break; + case G_TYPE_LONG: + SET_CONVERT_FUNCTION (long); + break; + case G_TYPE_ULONG: + SET_CONVERT_FUNCTION (ulong); + break; + case G_TYPE_INT64: + SET_CONVERT_FUNCTION (int64); + break; + case G_TYPE_UINT64: + SET_CONVERT_FUNCTION (uint64); + break; + case G_TYPE_FLOAT: + SET_CONVERT_FUNCTION (float); + break; + case G_TYPE_DOUBLE: + SET_CONVERT_FUNCTION (double); + break; + case G_TYPE_BOOLEAN: + self->convert_g_value = convert_g_value_to_boolean; + self->convert_value = convert_value_to_boolean; + self->byte_size = sizeof (gboolean); + break; + case G_TYPE_ENUM: + self->convert_g_value = convert_g_value_to_enum; + self->convert_value = convert_value_to_enum; + self->byte_size = sizeof (gint); + break; + default: + GST_WARNING ("incomplete implementation for paramspec type '%s'", + G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self))); + GST_CONTROL_BINDING_PSPEC (self) = NULL; + break; + } + } + return (GObject *) self; +} + +static void +gst_direct_control_binding_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_CS: + self->cs = g_value_dup_object (value); + break; + case PROP_ABSOLUTE: + self->ABI.abi.want_absolute = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_direct_control_binding_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object); + + switch (prop_id) { + case PROP_CS: + g_value_set_object (value, self->cs); + break; + case PROP_ABSOLUTE: + g_value_set_boolean (value, self->ABI.abi.want_absolute); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_direct_control_binding_dispose (GObject * object) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object); + + if (self->cs) + gst_object_replace ((GstObject **) & self->cs, NULL); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_direct_control_binding_finalize (GObject * object) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (object); + + if (G_IS_VALUE (&self->cur_value)) + g_value_unset (&self->cur_value); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_direct_control_binding_sync_values (GstControlBinding * _self, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self); + gdouble src_val; + gboolean ret; + + g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT, + _self->name, GST_TIME_ARGS (timestamp)); + + ret = gst_control_source_get_value (self->cs, timestamp, &src_val); + if (G_LIKELY (ret)) { + GST_LOG_OBJECT (object, " new value %lf", src_val); + /* always set the value for first time, but then only if it changed + * this should limit g_object_notify invocations. + * FIXME: can we detect negative playback rates? + */ + if ((timestamp < last_sync) || (src_val != self->last_value)) { + GValue *dst_val = &self->cur_value; + + GST_LOG_OBJECT (object, " mapping %s to value of type %s", _self->name, + G_VALUE_TYPE_NAME (dst_val)); + /* run mapping function to convert gdouble to GValue */ + self->convert_g_value (self, src_val, dst_val); + /* we can make this faster + * http://bugzilla.gnome.org/show_bug.cgi?id=536939 + */ + g_object_set_property ((GObject *) object, _self->name, dst_val); + self->last_value = src_val; + } + } else { + GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name); + } + return (ret); +} + +static GValue * +gst_direct_control_binding_get_value (GstControlBinding * _self, + GstClockTime timestamp) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self); + GValue *dst_val = NULL; + gdouble src_val; + + g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), NULL); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + /* get current value via control source */ + if (gst_control_source_get_value (self->cs, timestamp, &src_val)) { + dst_val = g_new0 (GValue, 1); + g_value_init (dst_val, G_PARAM_SPEC_VALUE_TYPE (_self->pspec)); + self->convert_g_value (self, src_val, dst_val); + } else { + GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT, + _self->name, GST_TIME_ARGS (timestamp)); + } + + return dst_val; +} + +static gboolean +gst_direct_control_binding_get_value_array (GstControlBinding * _self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values_) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self); + gint i; + gdouble *src_val; + gboolean res = FALSE; + GstDirectControlBindingConvertValue convert; + gint byte_size; + guint8 *values = (guint8 *) values_; + + g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + convert = self->convert_value; + byte_size = self->byte_size; + + src_val = g_new0 (gdouble, n_values); + if ((res = gst_control_source_get_value_array (self->cs, timestamp, + interval, n_values, src_val))) { + for (i = 0; i < n_values; i++) { + /* we will only get NAN for sparse control sources, such as triggers */ + if (!isnan (src_val[i])) { + convert (self, src_val[i], (gpointer) values); + } else { + GST_LOG ("no control value for property %s at index %d", _self->name, + i); + } + values += byte_size; + } + } else { + GST_LOG ("failed to get control value for property %s at ts %" + GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp)); + } + g_free (src_val); + return res; +} + +static gboolean +gst_direct_control_binding_get_g_value_array (GstControlBinding * _self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self); + gint i; + gdouble *src_val; + gboolean res = FALSE; + GType type; + GstDirectControlBindingConvertGValue convert; + + g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE); + g_return_val_if_fail (values, FALSE); + g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE); + + convert = self->convert_g_value; + type = G_PARAM_SPEC_VALUE_TYPE (_self->pspec); + + src_val = g_new0 (gdouble, n_values); + if ((res = gst_control_source_get_value_array (self->cs, timestamp, + interval, n_values, src_val))) { + for (i = 0; i < n_values; i++) { + /* we will only get NAN for sparse control sources, such as triggers */ + if (!isnan (src_val[i])) { + g_value_init (&values[i], type); + convert (self, src_val[i], &values[i]); + } else { + GST_LOG ("no control value for property %s at index %d", _self->name, + i); + } + } + } else { + GST_LOG ("failed to get control value for property %s at ts %" + GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp)); + } + g_free (src_val); + return res; +} + +/* functions */ + +/** + * gst_direct_control_binding_new: + * @object: the object of the property + * @property_name: the property-name to attach the control source + * @cs: the control source + * + * Create a new control-binding that attaches the #GstControlSource to the + * #GObject property. It will map the control source range [0.0 ... 1.0] to + * the full target property range, and clip all values outside this range. + * + * Returns: (transfer floating): the new #GstDirectControlBinding + */ +GstControlBinding * +gst_direct_control_binding_new (GstObject * object, const gchar * property_name, + GstControlSource * cs) +{ + return (GstControlBinding *) g_object_new (GST_TYPE_DIRECT_CONTROL_BINDING, + "object", object, "name", property_name, "control-source", cs, NULL); +} + +/** + * gst_direct_control_binding_new_absolute: + * @object: the object of the property + * @property_name: the property-name to attach the control source + * @cs: the control source + * + * Create a new control-binding that attaches the #GstControlSource to the + * #GObject property. It will directly map the control source values to the + * target property range without any transformations. + * + * Returns: (transfer floating): the new #GstDirectControlBinding + * + * Since: 1.6 + */ +GstControlBinding * +gst_direct_control_binding_new_absolute (GstObject * object, + const gchar * property_name, GstControlSource * cs) +{ + return (GstControlBinding *) g_object_new (GST_TYPE_DIRECT_CONTROL_BINDING, + "object", object, "name", property_name, "control-source", cs, "absolute", + TRUE, NULL); +} diff --git a/libs/gst/controller/gstdirectcontrolbinding.h b/libs/gst/controller/gstdirectcontrolbinding.h new file mode 100644 index 0000000..c84b870 --- /dev/null +++ b/libs/gst/controller/gstdirectcontrolbinding.h @@ -0,0 +1,131 @@ +/* GStreamer + * + * Copyright (C) 2011 Stefan Sauer + * + * gstdirectcontrolbinding.h: Direct attachment for control sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_DIRECT_CONTROL_BINDING_H__ +#define __GST_DIRECT_CONTROL_BINDING_H__ + +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DIRECT_CONTROL_BINDING \ + (gst_direct_control_binding_get_type()) +#define GST_DIRECT_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECT_CONTROL_BINDING,GstDirectControlBinding)) +#define GST_DIRECT_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECT_CONTROL_BINDING,GstDirectControlBindingClass)) +#define GST_IS_DIRECT_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECT_CONTROL_BINDING)) +#define GST_IS_DIRECT_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECT_CONTROL_BINDING)) +#define GST_DIRECT_CONTROL_BINDING_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstDirectControlBindingClass)) + +typedef struct _GstDirectControlBinding GstDirectControlBinding; +typedef struct _GstDirectControlBindingClass GstDirectControlBindingClass; + +/** + * GstDirectControlBindingConvertValue: + * @self: the #GstDirectControlBinding instance + * @src_value: the value returned by the cotnrol source + * @dest_value: the target location + * + * Function to map a control-value to the target plain data type. + */ +typedef void (* GstDirectControlBindingConvertValue) (GstDirectControlBinding *self, gdouble src_value, gpointer dest_value); + +/** + * GstDirectControlBindingConvertGValue: + * @self: the #GstDirectControlBinding instance + * @src_value: the value returned by the cotnrol source + * @dest_value: the target GValue + * + * Function to map a control-value to the target GValue. + */ +typedef void (* GstDirectControlBindingConvertGValue) (GstDirectControlBinding *self, gdouble src_value, GValue *dest_value); + +/** + * GstDirectControlBinding: + * @name: name of the property of this binding + * + * The instance structure of #GstDirectControlBinding. + */ +struct _GstDirectControlBinding { + GstControlBinding parent; + + /*< private >*/ + GstControlSource *cs; /* GstControlSource for this property */ + GValue cur_value; + gdouble last_value; + gint byte_size; + + GstDirectControlBindingConvertValue convert_value; + GstDirectControlBindingConvertGValue convert_g_value; + + union { + gpointer _gst_reserved[GST_PADDING]; + struct { + gboolean want_absolute; + } abi; + } ABI; +}; + +/** + * GstDirectControlBindingClass: + * @parent_class: Parent class + * @convert: Class method to convert control-values + * + * The class structure of #GstDirectControlBinding. + */ + +struct _GstDirectControlBindingClass +{ + GstControlBindingClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_direct_control_binding_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GstControlBinding * gst_direct_control_binding_new (GstObject * object, const gchar * property_name, + GstControlSource * cs); +GST_CONTROLLER_API +GstControlBinding * gst_direct_control_binding_new_absolute (GstObject * object, const gchar * property_name, + GstControlSource * cs); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstDirectControlBinding, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_DIRECT_CONTROL_BINDING_H__ */ diff --git a/libs/gst/controller/gstinterpolationcontrolsource.c b/libs/gst/controller/gstinterpolationcontrolsource.c new file mode 100644 index 0000000..4c9f0c8 --- /dev/null +++ b/libs/gst/controller/gstinterpolationcontrolsource.c @@ -0,0 +1,742 @@ +/* GStreamer + * + * Copyright (C) 2007,2009 Sebastian Dröge + * + * gstinterpolationcontrolsource.c: Control source that provides several + * interpolation methods + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstinterpolationcontrolsource + * @title: GstInterpolationControlSource + * @short_description: interpolation control source + * + * #GstInterpolationControlSource is a #GstControlSource, that interpolates values between user-given + * control points. It supports several interpolation modes and property types. + * + * To use #GstInterpolationControlSource get a new instance by calling + * gst_interpolation_control_source_new(), bind it to a #GParamSpec and set some + * control points by calling gst_timed_value_control_source_set(). + * + * All functions are MT-safe. + * + */ + +#include +#include + +#include "gstinterpolationcontrolsource.h" +#include "gst/glib-compat-private.h" +#include "gst/math-compat.h" + +#define GST_CAT_DEFAULT controller_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/* helper functions */ + +static inline gboolean +_get_nearest_control_points (GstTimedValueControlSource * self, + GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2) +{ + GSequenceIter *iter; + + iter = gst_timed_value_control_source_find_control_point_iter (self, ts); + if (iter) { + *cp1 = g_sequence_get (iter); + iter = g_sequence_iter_next (iter); + if (iter && !g_sequence_iter_is_end (iter)) { + *cp2 = g_sequence_get (iter); + } else { + *cp2 = NULL; + } + return TRUE; + } + return FALSE; +} + +static inline void +_get_nearest_control_points2 (GstTimedValueControlSource * self, + GstClockTime ts, GstControlPoint ** cp1, GstControlPoint ** cp2, + GstClockTime * next_ts) +{ + GSequenceIter *iter1, *iter2 = NULL; + + *cp1 = *cp2 = NULL; + iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); + if (iter1) { + *cp1 = g_sequence_get (iter1); + iter2 = g_sequence_iter_next (iter1); + } else { + if (G_LIKELY (self->values)) { + /* all values in the control point list come after the given timestamp */ + iter2 = g_sequence_get_begin_iter (self->values); + /* why this? if !cp1 we don't interpolate anyway + * if we can eliminate this, we can also use _get_nearest_control_points() + * here, is this just to set next_ts? */ + } else { + /* no values */ + iter2 = NULL; + } + } + + if (iter2 && !g_sequence_iter_is_end (iter2)) { + *cp2 = g_sequence_get (iter2); + *next_ts = (*cp2)->timestamp; + } else { + *next_ts = GST_CLOCK_TIME_NONE; + } +} + + +/* steps-like (no-)interpolation, default */ +/* just returns the value for the most recent key-frame */ +static inline gdouble +_interpolate_none (GstTimedValueControlSource * self, GstControlPoint * cp) +{ + return cp->value; +} + +static gboolean +interpolate_none_get (GstTimedValueControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + gboolean ret = FALSE; + GSequenceIter *iter; + GstControlPoint *cp; + + g_mutex_lock (&self->lock); + + iter = + gst_timed_value_control_source_find_control_point_iter (self, timestamp); + if (iter) { + cp = g_sequence_get (iter); + *value = _interpolate_none (self, cp); + ret = TRUE; + } + g_mutex_unlock (&self->lock); + return ret; +} + +static gboolean +interpolate_none_get_value_array (GstTimedValueControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + gboolean ret = FALSE; + guint i; + GstClockTime ts = timestamp; + GstClockTime next_ts = 0; + GstControlPoint *cp1 = NULL, *cp2 = NULL; + + g_mutex_lock (&self->lock); + + for (i = 0; i < n_values; i++) { + GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT, + i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts)); + if (ts >= next_ts) { + _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts); + } + if (cp1) { + *values = _interpolate_none (self, cp1); + ret = TRUE; + GST_LOG ("values[%3d]=%lf", i, *values); + } else { + *values = NAN; + GST_LOG ("values[%3d]=-", i); + } + ts += interval; + values++; + } + g_mutex_unlock (&self->lock); + return ret; +} + + + +/* linear interpolation */ +/* smoothes inbetween values */ +static inline gdouble +_interpolate_linear (GstClockTime timestamp1, gdouble value1, + GstClockTime timestamp2, gdouble value2, GstClockTime timestamp) +{ + if (GST_CLOCK_TIME_IS_VALID (timestamp2)) { + gdouble slope; + + slope = + (value2 - value1) / gst_guint64_to_gdouble (timestamp2 - timestamp1); + return value1 + (gst_guint64_to_gdouble (timestamp - timestamp1) * slope); + } else { + return value1; + } +} + +static gboolean +interpolate_linear_get (GstTimedValueControlSource * self, + GstClockTime timestamp, gdouble * value) +{ + gboolean ret = FALSE; + GstControlPoint *cp1, *cp2; + + g_mutex_lock (&self->lock); + + if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) { + *value = _interpolate_linear (cp1->timestamp, cp1->value, + (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), + (cp2 ? cp2->value : 0.0), timestamp); + ret = TRUE; + } + g_mutex_unlock (&self->lock); + return ret; +} + +static gboolean +interpolate_linear_get_value_array (GstTimedValueControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + gboolean ret = FALSE; + guint i; + GstClockTime ts = timestamp; + GstClockTime next_ts = 0; + GstControlPoint *cp1 = NULL, *cp2 = NULL; + + g_mutex_lock (&self->lock); + + for (i = 0; i < n_values; i++) { + GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT, + i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts)); + if (ts >= next_ts) { + _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts); + } + if (cp1) { + *values = _interpolate_linear (cp1->timestamp, cp1->value, + (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), + (cp2 ? cp2->value : 0.0), ts); + ret = TRUE; + GST_LOG ("values[%3d]=%lf", i, *values); + } else { + *values = NAN; + GST_LOG ("values[%3d]=-", i); + } + ts += interval; + values++; + } + g_mutex_unlock (&self->lock); + return ret; +} + + + +/* cubic interpolation */ + +/* The following functions implement a natural cubic spline interpolator. + * For details look at http://en.wikipedia.org/wiki/Spline_interpolation + * + * Instead of using a real matrix with n^2 elements for the linear system + * of equations we use three arrays o, p, q to hold the tridiagonal matrix + * as following to save memory: + * + * p[0] q[0] 0 0 0 + * o[1] p[1] q[1] 0 0 + * 0 o[2] p[2] q[2] . + * . . . . . + */ + +static void +_interpolate_cubic_update_cache (GstTimedValueControlSource * self) +{ + gint i, n = self->nvalues; + gdouble *o = g_new0 (gdouble, n); + gdouble *p = g_new0 (gdouble, n); + gdouble *q = g_new0 (gdouble, n); + + gdouble *h = g_new0 (gdouble, n); + gdouble *b = g_new0 (gdouble, n); + gdouble *z = g_new0 (gdouble, n); + + GSequenceIter *iter; + GstControlPoint *cp; + GstClockTime x, x_next; + gdouble y_prev, y, y_next; + + /* Fill linear system of equations */ + iter = g_sequence_get_begin_iter (self->values); + cp = g_sequence_get (iter); + x = cp->timestamp; + y = cp->value; + + p[0] = 1.0; + + iter = g_sequence_iter_next (iter); + cp = g_sequence_get (iter); + x_next = cp->timestamp; + y_next = cp->value; + h[0] = gst_guint64_to_gdouble (x_next - x); + + for (i = 1; i < n - 1; i++) { + /* Shuffle x and y values */ + y_prev = y; + x = x_next; + y = y_next; + iter = g_sequence_iter_next (iter); + cp = g_sequence_get (iter); + x_next = cp->timestamp; + y_next = cp->value; + + h[i] = gst_guint64_to_gdouble (x_next - x); + o[i] = h[i - 1]; + p[i] = 2.0 * (h[i - 1] + h[i]); + q[i] = h[i]; + b[i] = (y_next - y) / h[i] - (y - y_prev) / h[i - 1]; + } + p[n - 1] = 1.0; + + /* Use Gauss elimination to set everything below the diagonal to zero */ + for (i = 1; i < n - 1; i++) { + gdouble a = o[i] / p[i - 1]; + p[i] -= a * q[i - 1]; + b[i] -= a * b[i - 1]; + } + + /* Solve everything else from bottom to top */ + for (i = n - 2; i > 0; i--) + z[i] = (b[i] - q[i] * z[i + 1]) / p[i]; + + /* Save cache next in the GstControlPoint */ + + iter = g_sequence_get_begin_iter (self->values); + for (i = 0; i < n; i++) { + cp = g_sequence_get (iter); + cp->cache.cubic.h = h[i]; + cp->cache.cubic.z = z[i]; + iter = g_sequence_iter_next (iter); + } + + /* Free our temporary arrays */ + g_free (o); + g_free (p); + g_free (q); + g_free (h); + g_free (b); + g_free (z); +} + +static inline gdouble +_interpolate_cubic (GstTimedValueControlSource * self, GstControlPoint * cp1, + gdouble value1, GstControlPoint * cp2, gdouble value2, + GstClockTime timestamp) +{ + if (!self->valid_cache) { + _interpolate_cubic_update_cache (self); + self->valid_cache = TRUE; + } + + if (cp2) { + gdouble diff1, diff2; + gdouble out; + + diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); + diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); + + out = + (cp2->cache.cubic.z * diff1 * diff1 * diff1 + + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; + out += + (value2 / cp1->cache.cubic.h - + cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; + out += + (value1 / cp1->cache.cubic.h - + cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; + return out; + } else { + return value1; + } +} + +static gboolean +interpolate_cubic_get (GstTimedValueControlSource * self, + GstClockTime timestamp, gdouble * value) +{ + gboolean ret = FALSE; + GstControlPoint *cp1, *cp2 = NULL; + + if (self->nvalues <= 2) + return interpolate_linear_get (self, timestamp, value); + + g_mutex_lock (&self->lock); + + if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) { + *value = _interpolate_cubic (self, cp1, cp1->value, cp2, + (cp2 ? cp2->value : 0.0), timestamp); + ret = TRUE; + } + g_mutex_unlock (&self->lock); + return ret; +} + +static gboolean +interpolate_cubic_get_value_array (GstTimedValueControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + gboolean ret = FALSE; + guint i; + GstClockTime ts = timestamp; + GstClockTime next_ts = 0; + GstControlPoint *cp1 = NULL, *cp2 = NULL; + + if (self->nvalues <= 2) + return interpolate_linear_get_value_array (self, timestamp, interval, + n_values, values); + + g_mutex_lock (&self->lock); + + for (i = 0; i < n_values; i++) { + GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT, + i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts)); + if (ts >= next_ts) { + _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts); + } + if (cp1) { + *values = _interpolate_cubic (self, cp1, cp1->value, cp2, + (cp2 ? cp2->value : 0.0), ts); + ret = TRUE; + GST_LOG ("values[%3d]=%lf", i, *values); + } else { + *values = NAN; + GST_LOG ("values[%3d]=-", i); + } + ts += interval; + values++; + } + g_mutex_unlock (&self->lock); + return ret; +} + + +/* monotonic cubic interpolation */ + +/* the following functions implement monotonic cubic spline interpolation. + * For details: http://en.wikipedia.org/wiki/Monotone_cubic_interpolation + * + * In contrast to the previous cubic mode, the values won't overshoot. + */ + +static void +_interpolate_cubic_monotonic_update_cache (GstTimedValueControlSource * self) +{ + gint i, n = self->nvalues; + gdouble *dxs = g_new0 (gdouble, n); + gdouble *dys = g_new0 (gdouble, n); + gdouble *ms = g_new0 (gdouble, n); + gdouble *c1s = g_new0 (gdouble, n); + + GSequenceIter *iter; + GstControlPoint *cp; + GstClockTime x, x_next, dx; + gdouble y, y_next, dy; + + /* Get consecutive differences and slopes */ + iter = g_sequence_get_begin_iter (self->values); + cp = g_sequence_get (iter); + x_next = cp->timestamp; + y_next = cp->value; + for (i = 0; i < n - 1; i++) { + x = x_next; + y = y_next; + iter = g_sequence_iter_next (iter); + cp = g_sequence_get (iter); + x_next = cp->timestamp; + y_next = cp->value; + + dx = gst_guint64_to_gdouble (x_next - x); + dy = y_next - y; + dxs[i] = dx; + dys[i] = dy; + ms[i] = dy / dx; + } + + /* Get degree-1 coefficients */ + c1s[0] = ms[0]; + for (i = 1; i < n; i++) { + gdouble m = ms[i - 1]; + gdouble m_next = ms[i]; + + if (m * m_next <= 0) { + c1s[i] = 0.0; + } else { + gdouble dx_next, dx_sum; + + dx = dxs[i], dx_next = dxs[i + 1], dx_sum = dx + dx_next; + c1s[i] = 3.0 * dx_sum / ((dx_sum + dx_next) / m + (dx_sum + dx) / m_next); + } + } + c1s[n - 1] = ms[n - 1]; + + /* Get degree-2 and degree-3 coefficients */ + iter = g_sequence_get_begin_iter (self->values); + for (i = 0; i < n - 1; i++) { + gdouble c1, m, inv_dx, common; + cp = g_sequence_get (iter); + + c1 = c1s[i]; + m = ms[i]; + inv_dx = 1.0 / dxs[i]; + common = c1 + c1s[i + 1] - m - m; + + cp->cache.cubic_monotonic.c1s = c1; + cp->cache.cubic_monotonic.c2s = (m - c1 - common) * inv_dx; + cp->cache.cubic_monotonic.c3s = common * inv_dx * inv_dx; + + iter = g_sequence_iter_next (iter); + } + + /* Free our temporary arrays */ + g_free (dxs); + g_free (dys); + g_free (ms); + g_free (c1s); +} + +static inline gdouble +_interpolate_cubic_monotonic (GstTimedValueControlSource * self, + GstControlPoint * cp1, gdouble value1, GstControlPoint * cp2, + gdouble value2, GstClockTime timestamp) +{ + if (!self->valid_cache) { + _interpolate_cubic_monotonic_update_cache (self); + self->valid_cache = TRUE; + } + + if (cp2) { + gdouble diff = gst_guint64_to_gdouble (timestamp - cp1->timestamp); + gdouble diff2 = diff * diff; + gdouble out; + + out = value1 + cp1->cache.cubic_monotonic.c1s * diff; + out += cp1->cache.cubic_monotonic.c2s * diff2; + out += cp1->cache.cubic_monotonic.c3s * diff * diff2; + return out; + } else { + return value1; + } +} + +static gboolean +interpolate_cubic_monotonic_get (GstTimedValueControlSource * self, + GstClockTime timestamp, gdouble * value) +{ + gboolean ret = FALSE; + GstControlPoint *cp1, *cp2 = NULL; + + if (self->nvalues <= 2) + return interpolate_linear_get (self, timestamp, value); + + g_mutex_lock (&self->lock); + + if (_get_nearest_control_points (self, timestamp, &cp1, &cp2)) { + *value = _interpolate_cubic_monotonic (self, cp1, cp1->value, cp2, + (cp2 ? cp2->value : 0.0), timestamp); + ret = TRUE; + } + g_mutex_unlock (&self->lock); + return ret; +} + +static gboolean +interpolate_cubic_monotonic_get_value_array (GstTimedValueControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + gboolean ret = FALSE; + guint i; + GstClockTime ts = timestamp; + GstClockTime next_ts = 0; + GstControlPoint *cp1 = NULL, *cp2 = NULL; + + if (self->nvalues <= 2) + return interpolate_linear_get_value_array (self, timestamp, interval, + n_values, values); + + g_mutex_lock (&self->lock); + + for (i = 0; i < n_values; i++) { + GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT, + i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts)); + if (ts >= next_ts) { + _get_nearest_control_points2 (self, ts, &cp1, &cp2, &next_ts); + } + if (cp1) { + *values = _interpolate_cubic_monotonic (self, cp1, cp1->value, cp2, + (cp2 ? cp2->value : 0.0), ts); + ret = TRUE; + GST_LOG ("values[%3d]=%lf", i, *values); + } else { + *values = NAN; + GST_LOG ("values[%3d]=-", i); + } + ts += interval; + values++; + } + g_mutex_unlock (&self->lock); + return ret; +} + + +static struct +{ + GstControlSourceGetValue get; + GstControlSourceGetValueArray get_value_array; +} interpolation_modes[] = { + { + (GstControlSourceGetValue) interpolate_none_get, + (GstControlSourceGetValueArray) interpolate_none_get_value_array}, { + (GstControlSourceGetValue) interpolate_linear_get, + (GstControlSourceGetValueArray) interpolate_linear_get_value_array}, { + (GstControlSourceGetValue) interpolate_cubic_get, + (GstControlSourceGetValueArray) interpolate_cubic_get_value_array}, { + (GstControlSourceGetValue) interpolate_cubic_monotonic_get, + (GstControlSourceGetValueArray) +interpolate_cubic_monotonic_get_value_array}}; + +static const guint num_interpolation_modes = G_N_ELEMENTS (interpolation_modes); + +enum +{ + PROP_MODE = 1 +}; + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, \ + "timeline value interpolating control source") + +G_DEFINE_TYPE_WITH_CODE (GstInterpolationControlSource, + gst_interpolation_control_source, GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, + _do_init); + +struct _GstInterpolationControlSourcePrivate +{ + GstInterpolationMode interpolation_mode; +}; + +/** + * gst_interpolation_control_source_new: + * + * This returns a new, unbound #GstInterpolationControlSource. + * + * Returns: (transfer full): a new, unbound #GstInterpolationControlSource. + */ +GstControlSource * +gst_interpolation_control_source_new (void) +{ + GstControlSource *csource = + g_object_new (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (csource); + + return csource; +} + +static gboolean + gst_interpolation_control_source_set_interpolation_mode + (GstInterpolationControlSource * self, GstInterpolationMode mode) +{ + GstControlSource *csource = GST_CONTROL_SOURCE (self); + + if (mode >= num_interpolation_modes || (int) mode < 0) { + GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode); + return FALSE; + } + + GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self); + csource->get_value = interpolation_modes[mode].get; + csource->get_value_array = interpolation_modes[mode].get_value_array; + + gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *) + csource); + self->priv->interpolation_mode = mode; + + GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self); + + return TRUE; +} + +static void +gst_interpolation_control_source_init (GstInterpolationControlSource * self) +{ + self->priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE, + GstInterpolationControlSourcePrivate); + gst_interpolation_control_source_set_interpolation_mode (self, + GST_INTERPOLATION_MODE_NONE); +} + +static void +gst_interpolation_control_source_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstInterpolationControlSource *self = + GST_INTERPOLATION_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_MODE: + gst_interpolation_control_source_set_interpolation_mode (self, + (GstInterpolationMode) g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_interpolation_control_source_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstInterpolationControlSource *self = + GST_INTERPOLATION_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum (value, self->priv->interpolation_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass + * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass); + + g_type_class_add_private (klass, + sizeof (GstInterpolationControlSourcePrivate)); + + gobject_class->set_property = gst_interpolation_control_source_set_property; + gobject_class->get_property = gst_interpolation_control_source_get_property; + + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", "Interpolation mode", + GST_TYPE_INTERPOLATION_MODE, GST_INTERPOLATION_MODE_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} diff --git a/libs/gst/controller/gstinterpolationcontrolsource.h b/libs/gst/controller/gstinterpolationcontrolsource.h new file mode 100644 index 0000000..65d164f --- /dev/null +++ b/libs/gst/controller/gstinterpolationcontrolsource.h @@ -0,0 +1,106 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * + * gstinterpolationcontrolsource.h: Control source that provides several + * interpolation methods + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_INTERPOLATION_CONTROL_SOURCE_H__ +#define __GST_INTERPOLATION_CONTROL_SOURCE_H__ + +#include +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_INTERPOLATION_CONTROL_SOURCE \ + (gst_interpolation_control_source_get_type ()) +#define GST_INTERPOLATION_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSource)) +#define GST_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass)) +#define GST_IS_INTERPOLATION_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE)) +#define GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE)) +#define GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass)) + +typedef struct _GstInterpolationControlSource GstInterpolationControlSource; +typedef struct _GstInterpolationControlSourceClass GstInterpolationControlSourceClass; +typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSourcePrivate; + +/** + * GstInterpolationMode: + * @GST_INTERPOLATION_MODE_NONE: steps-like interpolation, default + * @GST_INTERPOLATION_MODE_LINEAR: linear interpolation + * @GST_INTERPOLATION_MODE_CUBIC: cubic interpolation (natural), may overshoot + * the min or max values set by the control point, but is more 'curvy' + * @GST_INTERPOLATION_MODE_CUBIC_MONOTONIC: monotonic cubic interpolation, will not + * produce any values outside of the min-max range set by the control points + * (Since 1.8) + * + * The various interpolation modes available. + */ +typedef enum +{ + GST_INTERPOLATION_MODE_NONE, + GST_INTERPOLATION_MODE_LINEAR, + GST_INTERPOLATION_MODE_CUBIC, + GST_INTERPOLATION_MODE_CUBIC_MONOTONIC, +} GstInterpolationMode; + +/** + * GstInterpolationControlSource: + * + * The instance structure of #GstControlSource. + */ +struct _GstInterpolationControlSource { + GstTimedValueControlSource parent; + + /*< private >*/ + GstInterpolationControlSourcePrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstInterpolationControlSourceClass { + GstTimedValueControlSourceClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_interpolation_control_source_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GstControlSource * gst_interpolation_control_source_new (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstInterpolationControlSource, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_INTERPOLATION_CONTROL_SOURCE_H__ */ diff --git a/libs/gst/controller/gstlfocontrolsource.c b/libs/gst/controller/gstlfocontrolsource.c new file mode 100644 index 0000000..4419a19 --- /dev/null +++ b/libs/gst/controller/gstlfocontrolsource.c @@ -0,0 +1,595 @@ +/* GStreamer + * + * Copyright (C) 2007,2010 Sebastian Dröge + * + * gstlfocontrolsource.c: Control source that provides some periodic waveforms + * as control values. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstlfocontrolsource + * @title: GstLFOControlSource + * @short_description: LFO control source + * + * #GstLFOControlSource is a #GstControlSource, that provides several periodic + * waveforms as control values. + * + * To use #GstLFOControlSource get a new instance by calling + * gst_lfo_control_source_new(), bind it to a #GParamSpec and set the relevant + * properties. + * + * All functions are MT-safe. + */ + +#include + +#include +#include +#include + +#include "gstlfocontrolsource.h" + +#include "gst/glib-compat-private.h" + +#include + +#define GST_CAT_DEFAULT controller_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +struct _GstLFOControlSourcePrivate +{ + GstLFOWaveform waveform; + gdouble frequency; + GstClockTime period; + GstClockTime timeshift; + gdouble amplitude; + gdouble offset; +}; + +/* FIXME: as % in C is not the modulo operator we need here for + * negative numbers implement our own. Are there better ways? */ +static inline GstClockTime +_calculate_pos (GstClockTime timestamp, GstClockTime timeshift, + GstClockTime period) +{ + while (timestamp < timeshift) + timestamp += period; + + timestamp -= timeshift; + + return timestamp % period; +} + +static inline gdouble +_sine_get (GstLFOControlSource * self, gdouble amp, gdouble off, + GstClockTime timeshift, GstClockTime period, gdouble frequency, + GstClockTime timestamp) +{ + gdouble pos = + gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period)); + gdouble ret; + + ret = sin (2.0 * M_PI * (frequency / GST_SECOND) * pos); + ret *= amp; + ret += off; + + return ret; +} + +static gboolean +waveform_sine_get (GstLFOControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + GstLFOControlSourcePrivate *priv = self->priv; + + gst_object_sync_values (GST_OBJECT (self), timestamp); + g_mutex_lock (&self->lock); + *value = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, timestamp); + g_mutex_unlock (&self->lock); + return TRUE; +} + +static gboolean +waveform_sine_get_value_array (GstLFOControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + GstLFOControlSourcePrivate *priv = self->priv; + guint i; + GstClockTime ts = timestamp; + + for (i = 0; i < n_values; i++) { + gst_object_sync_values (GST_OBJECT (self), ts); + g_mutex_lock (&self->lock); + *values = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, ts); + g_mutex_unlock (&self->lock); + ts += interval; + values++; + } + return TRUE; +} + + +static inline gdouble +_square_get (GstLFOControlSource * self, gdouble amp, gdouble off, + GstClockTime timeshift, GstClockTime period, gdouble frequency, + GstClockTime timestamp) +{ + GstClockTime pos = _calculate_pos (timestamp, timeshift, period); + gdouble ret; + + if (pos >= period / 2) + ret = amp; + else + ret = -amp; + ret += off; + + return ret; +} + +static gboolean +waveform_square_get (GstLFOControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + GstLFOControlSourcePrivate *priv = self->priv; + + gst_object_sync_values (GST_OBJECT (self), timestamp); + g_mutex_lock (&self->lock); + *value = _square_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, timestamp); + g_mutex_unlock (&self->lock); + return TRUE; +} + +static gboolean +waveform_square_get_value_array (GstLFOControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + GstLFOControlSourcePrivate *priv = self->priv; + guint i; + GstClockTime ts = timestamp; + + for (i = 0; i < n_values; i++) { + gst_object_sync_values (GST_OBJECT (self), ts); + g_mutex_lock (&self->lock); + *values = _square_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, ts); + g_mutex_unlock (&self->lock); + ts += interval; + values++; + } + return TRUE; +} + +static inline gdouble +_saw_get (GstLFOControlSource * self, gdouble amp, gdouble off, + GstClockTime timeshift, GstClockTime period, gdouble frequency, + GstClockTime timestamp) +{ + gdouble pos = + gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period)); + gdouble per = gst_guint64_to_gdouble (period); + gdouble ret; + + ret = -((pos - per / 2.0) * ((2.0 * amp) / per)); + ret += off; + + return ret; +} + +static gboolean +waveform_saw_get (GstLFOControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + GstLFOControlSourcePrivate *priv = self->priv; + + gst_object_sync_values (GST_OBJECT (self), timestamp); + g_mutex_lock (&self->lock); + *value = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, timestamp); + g_mutex_unlock (&self->lock); + return TRUE; +} + +static gboolean +waveform_saw_get_value_array (GstLFOControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + GstLFOControlSourcePrivate *priv = self->priv; + guint i; + GstClockTime ts = timestamp; + + for (i = 0; i < n_values; i++) { + gst_object_sync_values (GST_OBJECT (self), ts); + g_mutex_lock (&self->lock); + *values = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, ts); + g_mutex_unlock (&self->lock); + ts += interval; + values++; + } + return TRUE; +} + +static inline gdouble +_rsaw_get (GstLFOControlSource * self, gdouble amp, gdouble off, + GstClockTime timeshift, GstClockTime period, gdouble frequency, + GstClockTime timestamp) +{ + gdouble pos = + gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period)); + gdouble per = gst_guint64_to_gdouble (period); + gdouble ret; + + ret = (pos - per / 2.0) * ((2.0 * amp) / per); + ret += off; + + return ret; +} + +static gboolean +waveform_rsaw_get (GstLFOControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + GstLFOControlSourcePrivate *priv = self->priv; + + gst_object_sync_values (GST_OBJECT (self), timestamp); + g_mutex_lock (&self->lock); + *value = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, timestamp); + g_mutex_unlock (&self->lock); + return TRUE; +} + +static gboolean +waveform_rsaw_get_value_array (GstLFOControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + GstLFOControlSourcePrivate *priv = self->priv; + guint i; + GstClockTime ts = timestamp; + + for (i = 0; i < n_values; i++) { + gst_object_sync_values (GST_OBJECT (self), ts); + g_mutex_lock (&self->lock); + *values = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, ts); + g_mutex_unlock (&self->lock); + ts += interval; + values++; + } + return TRUE; +} + + +static inline gdouble +_triangle_get (GstLFOControlSource * self, gdouble amp, gdouble off, + GstClockTime timeshift, GstClockTime period, gdouble frequency, + GstClockTime timestamp) +{ + gdouble pos = + gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period)); + gdouble per = gst_guint64_to_gdouble (period); + gdouble ret; + + if (pos <= 0.25 * per) + /* 1st quarter */ + ret = pos * ((4.0 * amp) / per); + else if (pos <= 0.75 * per) + /* 2nd & 3rd quarter */ + ret = -(pos - per / 2.0) * ((4.0 * amp) / per); + else + /* 4th quarter */ + ret = -(per - pos) * ((4.0 * amp) / per); + + ret += off; + + return ret; +} + +static gboolean +waveform_triangle_get (GstLFOControlSource * self, GstClockTime timestamp, + gdouble * value) +{ + GstLFOControlSourcePrivate *priv = self->priv; + + gst_object_sync_values (GST_OBJECT (self), timestamp); + g_mutex_lock (&self->lock); + *value = _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, timestamp); + g_mutex_unlock (&self->lock); + return TRUE; +} + +static gboolean +waveform_triangle_get_value_array (GstLFOControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + GstLFOControlSourcePrivate *priv = self->priv; + guint i; + GstClockTime ts = timestamp; + + for (i = 0; i < n_values; i++) { + gst_object_sync_values (GST_OBJECT (self), ts); + g_mutex_lock (&self->lock); + *values = + _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift, + priv->period, priv->frequency, ts); + g_mutex_unlock (&self->lock); + ts += interval; + values++; + } + return TRUE; +} + +static struct +{ + GstControlSourceGetValue get; + GstControlSourceGetValueArray get_value_array; +} waveforms[] = { + { + (GstControlSourceGetValue) waveform_sine_get, + (GstControlSourceGetValueArray) waveform_sine_get_value_array}, { + (GstControlSourceGetValue) waveform_square_get, + (GstControlSourceGetValueArray) waveform_square_get_value_array}, { + (GstControlSourceGetValue) waveform_saw_get, + (GstControlSourceGetValueArray) waveform_saw_get_value_array}, { + (GstControlSourceGetValue) waveform_rsaw_get, + (GstControlSourceGetValueArray) waveform_rsaw_get_value_array}, { + (GstControlSourceGetValue) waveform_triangle_get, + (GstControlSourceGetValueArray) waveform_triangle_get_value_array} +}; + +static const guint num_waveforms = G_N_ELEMENTS (waveforms); + +enum +{ + PROP_WAVEFORM = 1, + PROP_FREQUENCY, + PROP_TIMESHIFT, + PROP_AMPLITUDE, + PROP_OFFSET +}; + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "lfo control source", 0, "low frequency oscillator control source") + +#define gst_lfo_control_source_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstLFOControlSource, gst_lfo_control_source, + GST_TYPE_CONTROL_SOURCE, _do_init); + +static void +gst_lfo_control_source_reset (GstLFOControlSource * self) +{ + GstControlSource *csource = GST_CONTROL_SOURCE (self); + + csource->get_value = NULL; + csource->get_value_array = NULL; +} + +/** + * gst_lfo_control_source_new: + * + * This returns a new, unbound #GstLFOControlSource. + * + * Returns: (transfer full): a new, unbound #GstLFOControlSource. + */ +GstControlSource * +gst_lfo_control_source_new (void) +{ + GstControlSource *csource = g_object_new (GST_TYPE_LFO_CONTROL_SOURCE, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (csource); + + return csource; +} + +static gboolean +gst_lfo_control_source_set_waveform (GstLFOControlSource * self, + GstLFOWaveform waveform) +{ + GstControlSource *csource = GST_CONTROL_SOURCE (self); + + if (waveform >= num_waveforms || (int) waveform < 0) { + GST_WARNING ("waveform %d invalid or not implemented yet", waveform); + return FALSE; + } + + csource->get_value = waveforms[waveform].get; + csource->get_value_array = waveforms[waveform].get_value_array; + + self->priv->waveform = waveform; + + return TRUE; +} + +static void +gst_lfo_control_source_init (GstLFOControlSource * self) +{ + self->priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_LFO_CONTROL_SOURCE, + GstLFOControlSourcePrivate); + self->priv->waveform = gst_lfo_control_source_set_waveform (self, + GST_LFO_WAVEFORM_SINE); + self->priv->frequency = 1.0; + self->priv->amplitude = 1.0; + self->priv->period = GST_SECOND / self->priv->frequency; + self->priv->timeshift = 0; + + g_mutex_init (&self->lock); +} + +static void +gst_lfo_control_source_finalize (GObject * obj) +{ + GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (obj); + + gst_lfo_control_source_reset (self); + g_mutex_clear (&self->lock); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_lfo_control_source_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_WAVEFORM: + g_mutex_lock (&self->lock); + gst_lfo_control_source_set_waveform (self, + (GstLFOWaveform) g_value_get_enum (value)); + g_mutex_unlock (&self->lock); + break; + case PROP_FREQUENCY:{ + gdouble frequency = g_value_get_double (value); + + g_return_if_fail (((GstClockTime) (GST_SECOND / frequency)) != 0); + + g_mutex_lock (&self->lock); + self->priv->frequency = frequency; + self->priv->period = GST_SECOND / frequency; + g_mutex_unlock (&self->lock); + break; + } + case PROP_TIMESHIFT: + g_mutex_lock (&self->lock); + self->priv->timeshift = g_value_get_uint64 (value); + g_mutex_unlock (&self->lock); + break; + case PROP_AMPLITUDE: + g_mutex_lock (&self->lock); + self->priv->amplitude = g_value_get_double (value); + g_mutex_unlock (&self->lock); + break; + case PROP_OFFSET: + g_mutex_lock (&self->lock); + self->priv->offset = g_value_get_double (value); + g_mutex_unlock (&self->lock); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_lfo_control_source_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_WAVEFORM: + g_value_set_enum (value, self->priv->waveform); + break; + case PROP_FREQUENCY: + g_value_set_double (value, self->priv->frequency); + break; + case PROP_TIMESHIFT: + g_value_set_uint64 (value, self->priv->timeshift); + break; + case PROP_AMPLITUDE: + g_value_set_double (value, self->priv->amplitude); + break; + case PROP_OFFSET: + g_value_set_double (value, self->priv->offset); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstLFOControlSourcePrivate)); + + gobject_class->finalize = gst_lfo_control_source_finalize; + gobject_class->set_property = gst_lfo_control_source_set_property; + gobject_class->get_property = gst_lfo_control_source_get_property; + + /** + * GstLFOControlSource:waveform: + * + * Specifies the waveform that should be used for this #GstLFOControlSource. + */ + g_object_class_install_property (gobject_class, PROP_WAVEFORM, + g_param_spec_enum ("waveform", "Waveform", "Waveform", + GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstLFOControlSource:frequency: + * + * Specifies the frequency that should be used for the waveform + * of this #GstLFOControlSource. It should be large enough + * so that the period is longer than one nanosecond. + */ + g_object_class_install_property (gobject_class, PROP_FREQUENCY, + g_param_spec_double ("frequency", "Frequency", + "Frequency of the waveform", DBL_MIN, G_MAXDOUBLE, 1.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstLFOControlSource:timeshift: + * + * Specifies the timeshift to the right that should be used for the waveform + * of this #GstLFOControlSource in nanoseconds. + * + * To get a n nanosecond shift to the left use + * "(GST_SECOND / frequency) - n". + * + */ + g_object_class_install_property (gobject_class, PROP_TIMESHIFT, + g_param_spec_uint64 ("timeshift", "Timeshift", + "Timeshift of the waveform to the right", 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstLFOControlSource:amplitude: + * + * Specifies the amplitude for the waveform of this #GstLFOControlSource. + */ + g_object_class_install_property (gobject_class, PROP_AMPLITUDE, + g_param_spec_double ("amplitude", "Amplitude", + "Amplitude of the waveform", 0.0, 1.0, 1.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstLFOControlSource:offset: + * + * Specifies the value offset for the waveform of this #GstLFOControlSource. + */ + g_object_class_install_property (gobject_class, PROP_OFFSET, + g_param_spec_double ("offset", "Offset", "Offset of the waveform", + 0.0, 1.0, 1.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); +} diff --git a/libs/gst/controller/gstlfocontrolsource.h b/libs/gst/controller/gstlfocontrolsource.h new file mode 100644 index 0000000..41bc100 --- /dev/null +++ b/libs/gst/controller/gstlfocontrolsource.h @@ -0,0 +1,104 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * + * gstlfocontrolsource.h: Control source that provides some periodic waveforms + * as control values. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_LFO_CONTROL_SOURCE_H__ +#define __GST_LFO_CONTROL_SOURCE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_LFO_CONTROL_SOURCE \ + (gst_lfo_control_source_get_type ()) +#define GST_LFO_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSource)) +#define GST_LFO_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSourceClass)) +#define GST_IS_LFO_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_LFO_CONTROL_SOURCE)) +#define GST_IS_LFO_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_LFO_CONTROL_SOURCE)) +#define GST_LFO_CONTROL_SOURCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_LFO_CONTROL_SOURCE, GstLFOControlSourceClass)) + +typedef struct _GstLFOControlSource GstLFOControlSource; +typedef struct _GstLFOControlSourceClass GstLFOControlSourceClass; +typedef struct _GstLFOControlSourcePrivate GstLFOControlSourcePrivate; + +/** + * GstLFOWaveform: + * @GST_LFO_WAVEFORM_SINE: sine waveform + * @GST_LFO_WAVEFORM_SQUARE: square waveform + * @GST_LFO_WAVEFORM_SAW: saw waveform + * @GST_LFO_WAVEFORM_REVERSE_SAW: reverse saw waveform + * @GST_LFO_WAVEFORM_TRIANGLE: triangle waveform + * + * The various waveform modes available. + */ +typedef enum +{ + GST_LFO_WAVEFORM_SINE, + GST_LFO_WAVEFORM_SQUARE, + GST_LFO_WAVEFORM_SAW, + GST_LFO_WAVEFORM_REVERSE_SAW, + GST_LFO_WAVEFORM_TRIANGLE +} GstLFOWaveform; + +/** + * GstLFOControlSource: + * + * The instance structure of #GstControlSource. + */ +struct _GstLFOControlSource { + GstControlSource parent; + + /* */ + GstLFOControlSourcePrivate *priv; + GMutex lock; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstLFOControlSourceClass { + GstControlSourceClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_lfo_control_source_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GstControlSource *gst_lfo_control_source_new (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstLFOControlSource, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_LFO_CONTROL_SOURCE_H__ */ diff --git a/libs/gst/controller/gstproxycontrolbinding.c b/libs/gst/controller/gstproxycontrolbinding.c new file mode 100644 index 0000000..660a3df --- /dev/null +++ b/libs/gst/controller/gstproxycontrolbinding.c @@ -0,0 +1,200 @@ +/* + * GStreamer + * Copyright (C) 2016 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstproxycontrolbinding + * @title: GstProxyControlBinding + * @short_description: attachment for forwarding control sources + * @see_also: #GstControlBinding + * + * A #GstControlBinding that forwards requests to another #GstControlBinding + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstproxycontrolbinding.h" + +G_DEFINE_TYPE (GstProxyControlBinding, + gst_proxy_control_binding, GST_TYPE_CONTROL_BINDING); + +static void +gst_proxy_control_binding_init (GstProxyControlBinding * self) +{ + g_weak_ref_init (&self->ref_object, NULL); +} + +static void +gst_proxy_control_binding_finalize (GObject * object) +{ + GstProxyControlBinding *self = (GstProxyControlBinding *) object; + + g_weak_ref_clear (&self->ref_object); + g_free (self->property_name); + + G_OBJECT_CLASS (gst_proxy_control_binding_parent_class)->finalize (object); +} + +static gboolean +gst_proxy_control_binding_sync_values (GstControlBinding * binding, + GstObject * object, GstClockTime timestamp, GstClockTime last_sync) +{ + GstProxyControlBinding *self = (GstProxyControlBinding *) + binding; + gboolean ret = TRUE; + GstObject *ref_object; + + ref_object = g_weak_ref_get (&self->ref_object); + if (ref_object) { + GstControlBinding *ref_binding = + gst_object_get_control_binding (ref_object, self->property_name); + if (ref_binding) { + ret = gst_control_binding_sync_values (ref_binding, ref_object, + timestamp, last_sync); + gst_object_unref (ref_binding); + } + gst_object_unref (ref_object); + } + + return ret; +} + +static GValue * +gst_proxy_control_binding_get_value (GstControlBinding * binding, + GstClockTime timestamp) +{ + GstProxyControlBinding *self = (GstProxyControlBinding *) + binding; + GValue *ret = NULL; + GstObject *ref_object; + + ref_object = g_weak_ref_get (&self->ref_object); + if (ref_object) { + GstControlBinding *ref_binding = + gst_object_get_control_binding (ref_object, self->property_name); + if (ref_binding) { + ret = gst_control_binding_get_value (ref_binding, timestamp); + gst_object_unref (ref_binding); + } + gst_object_unref (ref_object); + } + + return ret; +} + +static gboolean +gst_proxy_control_binding_get_value_array (GstControlBinding * binding, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gpointer values) +{ + GstProxyControlBinding *self = (GstProxyControlBinding *) + binding; + gboolean ret = FALSE; + GstObject *ref_object; + + ref_object = g_weak_ref_get (&self->ref_object); + if (ref_object) { + GstControlBinding *ref_binding = + gst_object_get_control_binding (ref_object, self->property_name); + if (ref_binding) { + ret = gst_control_binding_get_value_array (ref_binding, timestamp, + interval, n_values, values); + gst_object_unref (ref_binding); + } + gst_object_unref (ref_object); + } + + return ret; +} + +static gboolean +gst_proxy_control_binding_get_g_value_array (GstControlBinding * + binding, GstClockTime timestamp, GstClockTime interval, guint n_values, + GValue * values) +{ + GstProxyControlBinding *self = (GstProxyControlBinding *) binding; + gboolean ret = FALSE; + GstObject *ref_object; + + ref_object = g_weak_ref_get (&self->ref_object); + if (ref_object) { + GstControlBinding *ref_binding = + gst_object_get_control_binding (ref_object, self->property_name); + if (ref_binding) { + ret = gst_control_binding_get_g_value_array (ref_binding, timestamp, + interval, n_values, values); + gst_object_unref (ref_binding); + } + gst_object_unref (ref_object); + } + + return ret; +} + +static void +gst_proxy_control_binding_class_init (GstProxyControlBindingClass * klass) +{ + GstControlBindingClass *cb_class = GST_CONTROL_BINDING_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + cb_class->sync_values = gst_proxy_control_binding_sync_values; + cb_class->get_value = gst_proxy_control_binding_get_value; + cb_class->get_value_array = gst_proxy_control_binding_get_value_array; + cb_class->get_g_value_array = gst_proxy_control_binding_get_g_value_array; + + gobject_class->finalize = gst_proxy_control_binding_finalize; +} + +/** + * gst_proxy_control_binding_new: + * @object: (transfer none): a #GstObject + * @property_name: the property name in @object to control + * @ref_object: (transfer none): a #GstObject to forward all + * #GstControlBinding requests to + * @ref_property_name: the property_name in @ref_object to control + * + * #GstProxyControlBinding forwards all access to data or sync_values() + * requests from @property_name on @object to the control binding at + * @ref_property_name on @ref_object. + * + * Returns: (transfer floating): a new #GstControlBinding that proxies the control interface between + * properties on different #GstObject's + * + * Since: 1.12 + */ +GstControlBinding * +gst_proxy_control_binding_new (GstObject * object, const gchar * property_name, + GstObject * ref_object, const gchar * ref_property_name) +{ + GstProxyControlBinding *cb; + + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + g_return_val_if_fail (GST_IS_OBJECT (ref_object), NULL); + g_return_val_if_fail (ref_property_name != NULL, NULL); + + cb = g_object_new (GST_TYPE_PROXY_CONTROL_BINDING, "object", object, + "name", property_name, NULL); + + g_weak_ref_set (&cb->ref_object, ref_object); + cb->property_name = g_strdup (ref_property_name); + + return (GstControlBinding *) cb; +} diff --git a/libs/gst/controller/gstproxycontrolbinding.h b/libs/gst/controller/gstproxycontrolbinding.h new file mode 100644 index 0000000..b39e760 --- /dev/null +++ b/libs/gst/controller/gstproxycontrolbinding.h @@ -0,0 +1,87 @@ +/* + * GStreamer + * Copyright (C) 2016 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PROXY_CONTROL_BINDING_H__ +#define __GST_PROXY_CONTROL_BINDING_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PROXY_CONTROL_BINDING (gst_proxy_control_binding_get_type()) +#define GST_PROXY_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROXY_CONTROL_BINDING,GstProxyControlBinding)) +#define GST_PROXY_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROXY_CONTROL_BINDING,GstProxyControlBindingClass)) +#define GST_IS_PROXY_CONTROL_BINDING(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROXY_CONTROL_BINDING)) +#define GST_IS_PROXY_CONTROL_BINDING_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROXY_CONTROL_BINDING)) +#define GST_PROXY_CONTROL_BINDING_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstProxyControlBindingClass)) + +typedef struct _GstProxyControlBinding GstProxyControlBinding; +typedef struct _GstProxyControlBindingClass GstProxyControlBindingClass; + +/** + * GstProxyControlBinding: + * + * Opaque #GstProxyControlBinding struct + */ +struct _GstProxyControlBinding +{ + /* */ + GstControlBinding parent; + + GWeakRef ref_object; + gchar *property_name; + + gpointer _padding[GST_PADDING]; +}; + +/** + * GstProxyControlBindingClass: + * + * Opaque #GstProxyControlBindingClass struct + */ +struct _GstProxyControlBindingClass +{ + /* */ + GstControlBindingClass parent_class; + + gpointer _padding[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_proxy_control_binding_get_type (void); + +GST_CONTROLLER_API +GstControlBinding * gst_proxy_control_binding_new (GstObject * object, + const gchar * property_name, + GstObject * ref_object, + const gchar * ref_property_name); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstProxyControlBinding, gst_object_unref) +#endif +G_END_DECLS + +#endif /* __GST_PROXY_CONTROL_BINDING_H__ */ diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c new file mode 100644 index 0000000..3ec43b0 --- /dev/null +++ b/libs/gst/controller/gsttimedvaluecontrolsource.c @@ -0,0 +1,510 @@ +/* GStreamer + * + * Copyright (C) 2007,2009 Sebastian Dröge + * 2011 Stefan Sauer + * + * gsttimedvaluecontrolsource.c: Base class for timeed value based control + * sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gsttimedvaluecontrolsource + * @title: GstTimedValueControlSource + * @short_description: timed value control source base class + * + * Base class for #GstControlSource that use time-stamped values. + * + * When overriding bind, chain up first to give this bind implementation a + * chance to setup things. + * + * All functions are MT-safe. + * + */ + +#include +#include + +#include "gstinterpolationcontrolsource.h" +#include "gst/glib-compat-private.h" + +#define GST_CAT_DEFAULT controller_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "timed value control source", 0, \ + "timed value control source base class") + +#define gst_timed_value_control_source_parent_class parent_class +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource, + gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init); + + +enum +{ + VALUE_CHANGED_SIGNAL, + VALUE_ADDED_SIGNAL, + VALUE_REMOVED_SIGNAL, + LAST_SIGNAL +}; + +static guint gst_timed_value_control_source_signals[LAST_SIGNAL] = { 0 }; + +/** + * gst_control_point_free: + * @cp: the object to free + * + * Frees all data allocated by a #GstControlPoint instance. + */ +void +gst_control_point_free (GstControlPoint * cp) +{ + g_return_if_fail (cp); + + g_slice_free (GstControlPoint, cp); +} + +GstControlPoint * +gst_control_point_copy (GstControlPoint * cp) +{ + return g_slice_dup (GstControlPoint, cp); +} + +GType +gst_control_point_get_type (void) +{ + static volatile gsize type_id = 0; + + if (g_once_init_enter (&type_id)) { + GType tmp = + g_boxed_type_register_static (g_intern_static_string + ("GstControlPoint"), + (GBoxedCopyFunc) gst_control_point_copy, + (GBoxedFreeFunc) gst_control_point_free); + g_once_init_leave (&type_id, tmp); + } + + return type_id; +} + +static void +gst_timed_value_control_source_reset (GstTimedValueControlSource * self) +{ + GstControlSource *csource = (GstControlSource *) self; + + csource->get_value = NULL; + csource->get_value_array = NULL; + + if (self->values) { + g_sequence_free (self->values); + self->values = NULL; + } + + self->nvalues = 0; + self->valid_cache = FALSE; +} + +/* + * gst_control_point_compare: + * @p1: a pointer to a #GstControlPoint + * @p2: a pointer to a #GstControlPoint + * + * Compare function for g_list operations that operates on two #GstControlPoint + * parameters. + */ +static gint +gst_control_point_compare (gconstpointer p1, gconstpointer p2) +{ + GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp; + GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp; + + return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); +} + +/* + * gst_control_point_find: + * @p1: a pointer to a #GstControlPoint + * @p2: a pointer to a #GstClockTime + * @user_data: supplied user data + * + * Compare function for g_sequence operations that operates on a #GstControlPoint and + * a #GstClockTime. + */ +static gint +gst_control_point_find (gconstpointer p1, gconstpointer p2, gpointer user_data) +{ + GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp; + GstClockTime ct2 = *(GstClockTime *) p2; + + return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); +} + +static GstControlPoint * +_make_new_cp (GstTimedValueControlSource * self, GstClockTime timestamp, + const gdouble value) +{ + GstControlPoint *cp; + + /* create a new GstControlPoint */ + cp = g_slice_new0 (GstControlPoint); + cp->timestamp = timestamp; + cp->value = value; + + return cp; +} + +static void +gst_timed_value_control_source_set_internal (GstTimedValueControlSource * + self, GstClockTime timestamp, const gdouble value) +{ + GstControlPoint *cp; + + g_mutex_lock (&self->lock); + + /* check if a control point for the timestamp already exists */ + if (G_LIKELY (self->values)) { + GSequenceIter *iter = g_sequence_lookup (self->values, ×tamp, + (GCompareDataFunc) gst_control_point_find, NULL); + + if (iter) { + GstControlPoint *cp = g_sequence_get (iter); + + /* update control point */ + cp->value = value; + g_mutex_unlock (&self->lock); + + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL], 0, cp); + goto done; + } + } else { + self->values = g_sequence_new ((GDestroyNotify) gst_control_point_free); + GST_INFO ("create new timed value sequence"); + } + + /* sort new cp into the prop->values list */ + cp = _make_new_cp (self, timestamp, value); + g_sequence_insert_sorted (self->values, cp, + (GCompareDataFunc) gst_control_point_compare, NULL); + self->nvalues++; + g_mutex_unlock (&self->lock); + + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL], 0, cp); + +done: + self->valid_cache = FALSE; +} + +/** + * gst_timed_value_control_source_find_control_point_iter: + * @self: the control source to search in + * @timestamp: the search key + * + * Find last value before given timestamp in control point list. + * If all values in the control point list come after the given + * timestamp or no values exist, %NULL is returned. + * + * For use in control source implementations. + * + * Returns: (transfer none): the found #GSequenceIter or %NULL + */ +GSequenceIter *gst_timed_value_control_source_find_control_point_iter + (GstTimedValueControlSource * self, GstClockTime timestamp) +{ + GSequenceIter *iter; + + if (!self->values) + return NULL; + + iter = + g_sequence_search (self->values, ×tamp, + (GCompareDataFunc) gst_control_point_find, NULL); + + /* g_sequence_search() returns the iter where timestamp + * would be inserted, i.e. the iter > timestamp, so + * we need to get the previous one. And of course, if + * there is no previous one, we return NULL. */ + if (g_sequence_iter_is_begin (iter)) + return NULL; + + return g_sequence_iter_prev (iter); +} + + +/** + * gst_timed_value_control_source_set: + * @self: the #GstTimedValueControlSource object + * @timestamp: the time the control-change is scheduled for + * @value: the control-value + * + * Set the value of given controller-handled property at a certain time. + * + * Returns: FALSE if the values couldn't be set, TRUE otherwise. + */ +gboolean +gst_timed_value_control_source_set (GstTimedValueControlSource * self, + GstClockTime timestamp, const gdouble value) +{ + g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + + gst_timed_value_control_source_set_internal (self, timestamp, value); + + return TRUE; +} + +/** + * gst_timed_value_control_source_set_from_list: + * @self: the #GstTimedValueControlSource object + * @timedvalues: (transfer none) (element-type GstTimedValue): a list + * with #GstTimedValue items + * + * Sets multiple timed values at once. + * + * Returns: FALSE if the values couldn't be set, TRUE otherwise. + */ +gboolean +gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * + self, const GSList * timedvalues) +{ + const GSList *node; + GstTimedValue *tv; + gboolean res = FALSE; + + g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE); + + for (node = timedvalues; node; node = g_slist_next (node)) { + tv = node->data; + if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) { + GST_WARNING ("GstTimedValued with invalid timestamp passed to %s", + GST_FUNCTION); + } else { + gst_timed_value_control_source_set_internal (self, tv->timestamp, + tv->value); + res = TRUE; + } + } + return res; +} + +/** + * gst_timed_value_control_source_unset: + * @self: the #GstTimedValueControlSource object + * @timestamp: the time the control-change should be removed from + * + * Used to remove the value of given controller-handled property at a certain + * time. + * + * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise. + */ +gboolean +gst_timed_value_control_source_unset (GstTimedValueControlSource * self, + GstClockTime timestamp) +{ + GSequenceIter *iter; + gboolean res = FALSE; + GstControlPoint *cp = NULL; + + g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE); + g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); + + g_mutex_lock (&self->lock); + /* check if a control point for the timestamp exists */ + if (G_LIKELY (self->values) && (iter = + g_sequence_lookup (self->values, ×tamp, + (GCompareDataFunc) gst_control_point_find, NULL))) { + + /* Iter contains the iter right after timestamp, i.e. + * we need to get the previous one and check the timestamp + */ + cp = g_slice_dup (GstControlPoint, g_sequence_get (iter)); + g_sequence_remove (iter); + self->nvalues--; + self->valid_cache = FALSE; + res = TRUE; + } + g_mutex_unlock (&self->lock); + + if (cp) { + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL], 0, cp); + g_slice_free (GstControlPoint, cp); + } + + return res; +} + +/** + * gst_timed_value_control_source_unset_all: + * @self: the #GstTimedValueControlSource object + * + * Used to remove all time-stamped values of given controller-handled property + * + */ +void +gst_timed_value_control_source_unset_all (GstTimedValueControlSource * self) +{ + g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self)); + + g_mutex_lock (&self->lock); + /* free GstControlPoint structures */ + if (self->values) { + g_sequence_free (self->values); + self->values = NULL; + } + self->nvalues = 0; + self->valid_cache = FALSE; + + g_mutex_unlock (&self->lock); +} + +static void +_append_control_point (GstControlPoint * cp, GQueue * res) +{ + g_queue_push_tail (res, cp); +} + +/** + * gst_timed_value_control_source_get_all: + * @self: the #GstTimedValueControlSource to get the list from + * + * Returns a read-only copy of the list of #GstTimedValue for the given property. + * Free the list after done with it. + * + * Returns: (transfer container) (element-type GstTimedValue): a copy + * of the list, or %NULL if the property isn't handled by the controller + */ +GList * +gst_timed_value_control_source_get_all (GstTimedValueControlSource * self) +{ + GQueue res = G_QUEUE_INIT; + + g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), NULL); + + g_mutex_lock (&self->lock); + if (G_LIKELY (self->values)) + g_sequence_foreach (self->values, (GFunc) _append_control_point, &res); + g_mutex_unlock (&self->lock); + + return res.head; +} + +/** + * gst_timed_value_control_source_get_count: + * @self: the #GstTimedValueControlSource to get the number of values from + * + * Get the number of control points that are set. + * + * Returns: the number of control points that are set. + */ +gint +gst_timed_value_control_source_get_count (GstTimedValueControlSource * self) +{ + g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), 0); + return self->nvalues; +} + +/** + * gst_timed_value_control_invalidate_cache: + * @self: the #GstTimedValueControlSource + * + * Reset the controlled value cache. + */ +void +gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self) +{ + g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self)); + self->valid_cache = FALSE; +} + +static void +gst_timed_value_control_source_init (GstTimedValueControlSource * self) +{ + g_mutex_init (&self->lock); +} + +static void +gst_timed_value_control_source_finalize (GObject * obj) +{ + GstTimedValueControlSource *self = GST_TIMED_VALUE_CONTROL_SOURCE (obj); + + g_mutex_lock (&self->lock); + gst_timed_value_control_source_reset (self); + g_mutex_unlock (&self->lock); + g_mutex_clear (&self->lock); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass + * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass); + + /** + * GstTimedValueControlSource::value-changed + * @self: The #GstTimedValueControlSource on which a #GstTimedValue has changed + * @timed_value: The #GstTimedValue where the value changed + * + * Emited right after the new value has been set on @timed_signals + * + * Since: 1.6 + */ + gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL] = + g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + /** + * GstTimedValueControlSource::value-added + * @self: The #GstTimedValueControlSource into which a #GstTimedValue has been + * added + * @timed_value: The newly added #GstTimedValue + * + * Emited right after the new value has been added to @self + * + * Since: 1.6 + */ + gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL] = + g_signal_new ("value-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + /** + * GstTimedValueControlSource::value-removed + * @self: The #GstTimedValueControlSource from which a #GstTimedValue has been + * removed + * @timed_value: The removed #GstTimedValue + * + * Emited when @timed_value is removed from @self + * + * Since: 1.6 + */ + gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL] = + g_signal_new ("value-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + + gobject_class->finalize = gst_timed_value_control_source_finalize; +} diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.h b/libs/gst/controller/gsttimedvaluecontrolsource.h new file mode 100644 index 0000000..65ba373 --- /dev/null +++ b/libs/gst/controller/gsttimedvaluecontrolsource.h @@ -0,0 +1,162 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * 2011 Stefan Sauer + * + * gsttimedvaluecontrolsource.h: Base class for timeed value based control + * sources + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_TIMED_VALUE_CONTROL_SOURCE_H__ +#define __GST_TIMED_VALUE_CONTROL_SOURCE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TIMED_VALUE_CONTROL_SOURCE \ + (gst_timed_value_control_source_get_type ()) +#define GST_TIMED_VALUE_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSource)) +#define GST_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass)) +#define GST_IS_TIMED_VALUE_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE)) +#define GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE)) +#define GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass)) + +typedef struct _GstTimedValueControlSource GstTimedValueControlSource; +typedef struct _GstTimedValueControlSourceClass GstTimedValueControlSourceClass; +typedef struct _GstTimedValueControlSourcePrivate GstTimedValueControlSourcePrivate; +typedef struct _GstControlPoint GstControlPoint; + +/** + * GstControlPoint: + * @timestamp: timestamp of the value change + * @value: the new value + * + * An internal structure for value+time and various temporary + * values used for interpolation. This "inherits" from + * GstTimedValue. + */ +struct _GstControlPoint +{ + /* fields from GstTimedValue. DO NOT CHANGE! */ + GstClockTime timestamp; + gdouble value; + + /*< private >*/ + + /* Caches for the interpolators */ + /* FIXME: we should not have this here already ... */ + union { + struct { /* 16 bytes */ + gdouble h; + gdouble z; + } cubic; + struct { /* 24 bytes */ + gdouble c1s, c2s, c3s; + } cubic_monotonic; + guint8 _gst_reserved[64]; + } cache; +}; + +GST_CONTROLLER_API +GType gst_control_point_get_type (void); + +/** + * GstTimedValueControlSource: + * + * The instance structure of #GstControlSource. + */ +struct _GstTimedValueControlSource { + GstControlSource parent; + + /*< protected >*/ + GMutex lock; + + GSequence *values; /* List of GstControlPoint */ + gint nvalues; /* Number of control points */ + gboolean valid_cache; + + /*< private >*/ + GstTimedValueControlSourcePrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTimedValueControlSourceClass { + GstControlSourceClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +#define GST_TIMED_VALUE_CONTROL_SOURCE_LOCK(o) \ + g_mutex_lock(&((GstTimedValueControlSource *)o)->lock) +#define GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK(o) \ + g_mutex_unlock(&((GstTimedValueControlSource *)o)->lock) + +GST_CONTROLLER_API +GType gst_timed_value_control_source_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GSequenceIter * gst_timed_value_control_source_find_control_point_iter ( + GstTimedValueControlSource * self, + GstClockTime timestamp); +GST_CONTROLLER_API +gboolean gst_timed_value_control_source_set (GstTimedValueControlSource * self, + GstClockTime timestamp, + const gdouble value); +GST_CONTROLLER_API +gboolean gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * self, + const GSList * timedvalues); +GST_CONTROLLER_API +gboolean gst_timed_value_control_source_unset (GstTimedValueControlSource * self, + GstClockTime timestamp); + +GST_CONTROLLER_API +void gst_timed_value_control_source_unset_all (GstTimedValueControlSource *self); + +GST_CONTROLLER_API +GList * gst_timed_value_control_source_get_all (GstTimedValueControlSource * self); + +GST_CONTROLLER_API +gint gst_timed_value_control_source_get_count (GstTimedValueControlSource * self); + +GST_CONTROLLER_API +void gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self); + +GST_CONTROLLER_API +void gst_control_point_free (GstControlPoint * cp); + +GST_CONTROLLER_API +GstControlPoint * gst_control_point_copy (GstControlPoint * cp); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTimedValueControlSource, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TIMED_VALUE_CONTROL_SOURCE_H__ */ diff --git a/libs/gst/controller/gsttriggercontrolsource.c b/libs/gst/controller/gsttriggercontrolsource.c new file mode 100644 index 0000000..aafa8de --- /dev/null +++ b/libs/gst/controller/gsttriggercontrolsource.c @@ -0,0 +1,263 @@ +/* GStreamer + * + * Copyright (C) 2007,2009 Sebastian Dröge + * 2011 Stefan Sauer + * + * gsttriggercontrolsource.c: Control source that provides some values at time- + * stamps + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + /** + * SECTION:gsttriggercontrolsource + * @title: GstTriggerControlSource + * @short_description: trigger control source + * + * #GstTriggerControlSource is a #GstControlSource, that returns values from user-given + * control points. It allows for a tolerance on the time-stamps. + * + * To use #GstTriggerControlSource get a new instance by calling + * gst_trigger_control_source_new(), bind it to a #GParamSpec and set some + * control points by calling gst_timed_value_control_source_set(). + * + * All functions are MT-safe. + */ + +#include +#include + +#include "gsttriggercontrolsource.h" +#include "gst/glib-compat-private.h" +#include "gst/math-compat.h" + +#define GST_CAT_DEFAULT controller_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +struct _GstTriggerControlSourcePrivate +{ + gint64 tolerance; +}; + +/* control point accessors */ + +/* returns the default value of the property, except for times with specific values */ +/* needed for one-shot events, such as notes and triggers */ + +static inline gdouble +_interpolate_trigger (GstTimedValueControlSource * self, GSequenceIter * iter, + GstClockTime timestamp) +{ + GstControlPoint *cp; + gint64 tolerance = ((GstTriggerControlSource *) self)->priv->tolerance; + gboolean found = FALSE; + + cp = g_sequence_get (iter); + if (GST_CLOCK_DIFF (cp->timestamp, timestamp) <= tolerance) { + found = TRUE; + } else { + if ((iter = g_sequence_iter_next (iter)) && !g_sequence_iter_is_end (iter)) { + cp = g_sequence_get (iter); + if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) { + found = TRUE; + } + } + } + if (found) { + return cp->value; + } + return NAN; +} + +static gboolean +interpolate_trigger_get (GstTimedValueControlSource * self, + GstClockTime timestamp, gdouble * value) +{ + gboolean ret = FALSE; + GSequenceIter *iter; + + g_mutex_lock (&self->lock); + + iter = + gst_timed_value_control_source_find_control_point_iter (self, timestamp); + if (iter) { + *value = _interpolate_trigger (self, iter, timestamp); + if (!isnan (*value)) + ret = TRUE; + } + g_mutex_unlock (&self->lock); + return ret; +} + +static gboolean +interpolate_trigger_get_value_array (GstTimedValueControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + gboolean ret = FALSE; + guint i; + GstClockTime ts = timestamp; + GstClockTime next_ts = 0; + gdouble val; + GSequenceIter *iter1 = NULL, *iter2 = NULL; + gboolean triggered = FALSE; + + g_mutex_lock (&self->lock); + for (i = 0; i < n_values; i++) { + val = NAN; + if (ts >= next_ts) { + iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); + if (!iter1) { + if (G_LIKELY (self->values)) + iter2 = g_sequence_get_begin_iter (self->values); + else + iter2 = NULL; + } else { + iter2 = g_sequence_iter_next (iter1); + } + + if (iter2 && !g_sequence_iter_is_end (iter2)) { + GstControlPoint *cp; + + cp = g_sequence_get (iter2); + next_ts = cp->timestamp; + } else { + next_ts = GST_CLOCK_TIME_NONE; + } + + if (iter1) { + val = _interpolate_trigger (self, iter1, ts); + if (!isnan (val)) + ret = TRUE; + } else { + g_mutex_unlock (&self->lock); + return FALSE; + } + triggered = TRUE; + } else if (triggered) { + if (iter1) { + val = _interpolate_trigger (self, iter1, ts); + if (!isnan (val)) + ret = TRUE; + } else { + g_mutex_unlock (&self->lock); + return FALSE; + } + triggered = FALSE; + } + *values = val; + ts += interval; + values++; + } + g_mutex_unlock (&self->lock); + return ret; +} + +enum +{ + PROP_TOLERANCE = 1, +}; + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "trigger control source", 0, \ + "timeline value trigger control source") + +G_DEFINE_TYPE_WITH_CODE (GstTriggerControlSource, gst_trigger_control_source, + GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, _do_init); + +/** + * gst_trigger_control_source_new: + * + * This returns a new, unbound #GstTriggerControlSource. + * + * Returns: (transfer full): a new, unbound #GstTriggerControlSource. + */ +GstControlSource * +gst_trigger_control_source_new (void) +{ + GstControlSource *csource = + g_object_new (GST_TYPE_TRIGGER_CONTROL_SOURCE, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (csource); + + return csource; +} + +static void +gst_trigger_control_source_init (GstTriggerControlSource * self) +{ + GstControlSource *csource = (GstControlSource *) self; + + self->priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_TRIGGER_CONTROL_SOURCE, + GstTriggerControlSourcePrivate); + + csource->get_value = (GstControlSourceGetValue) interpolate_trigger_get; + csource->get_value_array = (GstControlSourceGetValueArray) + interpolate_trigger_get_value_array; +} + +static void +gst_trigger_control_source_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_TOLERANCE: + GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self); + self->priv->tolerance = g_value_get_int64 (value); + GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_trigger_control_source_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object); + + switch (prop_id) { + case PROP_TOLERANCE: + g_value_set_int64 (value, self->priv->tolerance); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_trigger_control_source_class_init (GstTriggerControlSourceClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstTriggerControlSourcePrivate)); + + gobject_class->set_property = gst_trigger_control_source_set_property; + gobject_class->get_property = gst_trigger_control_source_get_property; + + g_object_class_install_property (gobject_class, PROP_TOLERANCE, + g_param_spec_int64 ("tolerance", "Tolerance", + "Amount of ns a control time can be off to still trigger", + 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + +} diff --git a/libs/gst/controller/gsttriggercontrolsource.h b/libs/gst/controller/gsttriggercontrolsource.h new file mode 100644 index 0000000..f98bed7 --- /dev/null +++ b/libs/gst/controller/gsttriggercontrolsource.h @@ -0,0 +1,89 @@ +/* GStreamer + * + * Copyright (C) 2007 Sebastian Dröge + * 2011 Stefan Sauer + * + * gsttriggercontrolsource.h: Control source that provides some values at time- + * stamps + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TRIGGER_CONTROL_SOURCE_H__ +#define __GST_TRIGGER_CONTROL_SOURCE_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TRIGGER_CONTROL_SOURCE \ + (gst_trigger_control_source_get_type ()) +#define GST_TRIGGER_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSource)) +#define GST_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass)) +#define GST_IS_TRIGGER_CONTROL_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE)) +#define GST_IS_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE)) +#define GST_TRIGGER_CONTROL_SOURCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass)) + +#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ()) + +typedef struct _GstTriggerControlSource GstTriggerControlSource; +typedef struct _GstTriggerControlSourceClass GstTriggerControlSourceClass; +typedef struct _GstTriggerControlSourcePrivate GstTriggerControlSourcePrivate; + +/** + * GstTriggerControlSource: + * + * The instance structure of #GstControlSource. + */ +struct _GstTriggerControlSource { + GstTimedValueControlSource parent; + + /*< private >*/ + GstTriggerControlSourcePrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstTriggerControlSourceClass { + GstTimedValueControlSourceClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_CONTROLLER_API +GType gst_trigger_control_source_get_type (void); + +/* Functions */ + +GST_CONTROLLER_API +GstControlSource *gst_trigger_control_source_new (void); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTriggerControlSource, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_TRIGGER_CONTROL_SOURCE_H__ */ diff --git a/libs/gst/controller/meson.build b/libs/gst/controller/meson.build new file mode 100644 index 0000000..1645c9e --- /dev/null +++ b/libs/gst/controller/meson.build @@ -0,0 +1,90 @@ +gst_controller_sources = [ + 'gstargbcontrolbinding.c', + 'gstdirectcontrolbinding.c', + 'gsttimedvaluecontrolsource.c', + 'gstinterpolationcontrolsource.c', + 'gstproxycontrolbinding.c', + 'gsttriggercontrolsource.c', + 'gstlfocontrolsource.c', +] + +controller_mkenum_headers = [ + 'gstinterpolationcontrolsource.h', + 'gstlfocontrolsource.h', +] + +gst_controller_headers = controller_mkenum_headers + [ + 'gstargbcontrolbinding.h', + 'gstdirectcontrolbinding.h', + 'gsttimedvaluecontrolsource.h', + 'gstinterpolationcontrolsource.h', + 'gstproxycontrolbinding.h', + 'gsttriggercontrolsource.h', + 'gstlfocontrolsource.h', + 'controller-prelude.h', + 'controller.h', +] +install_headers(gst_controller_headers, subdir : 'gstreamer-1.0/gst/controller/') + +mkenums = find_program('controller_mkenum.py') +gstcontroller_h = custom_target('gstcontrollerenum_h', + output : 'controller-enumtypes.h', + input : controller_mkenum_headers, + install : true, + install_dir : 'include/gstreamer-1.0/gst/controller/', + command : [mkenums, glib_mkenums, '@OUTPUT@', '@INPUT@']) + +gstcontroller_c = custom_target('gstcontrollerenum_c', + output : 'controller-enumtypes.c', + input : controller_mkenum_headers, + depends : [gstcontroller_h], + command : [mkenums, glib_mkenums, '@OUTPUT@', '@INPUT@']) +controller_gen_sources = [gstcontroller_h] + +if libtype != 'shared' + gst_controller_static = static_library('gstcontroller-@0@'.format(apiversion), + gst_controller_sources, gstcontroller_h, gstcontroller_c, + c_args : gst_c_args, + install : true, + include_directories : [configinc, libsinc], + dependencies : [gobject_dep, glib_dep, mathlib, gst_dep], + ) + gst_controller = gst_controller_static +endif + + +gst_controller_gen_sources = [gstcontroller_h] +if libtype != 'static' + gst_controller_shared = shared_library('gstcontroller-@0@'.format(apiversion), + gst_controller_sources, gstcontroller_h, gstcontroller_c, + c_args : gst_c_args, + install : true, + version : libversion, + soversion : soversion, + include_directories : [configinc, libsinc], + dependencies : [gobject_dep, glib_dep, mathlib, gst_dep], + ) + gst_controller = gst_controller_shared + if build_gir + gst_gir_extra_args = gir_init_section + [ '--c-include=gst/controller/controller.h' ] + gst_controller_gir = gnome.generate_gir(gst_controller_shared, + sources : gst_controller_sources + gst_controller_headers + [gstcontroller_h] + [gstcontroller_c], + namespace : 'GstController', + nsversion : apiversion, + identifier_prefix : 'Gst', + symbol_prefix : 'gst', + export_packages : 'gstreamer-controller-1.0', + dependencies : [gst_dep], + include_directories : [configinc, libsinc, privinc], + includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gst-1.0'], + install : true, + extra_args : gst_gir_extra_args, + ) + gst_controller_gen_sources += [gst_controller_gir] + endif +endif + +gst_controller_dep = declare_dependency(link_with : gst_controller, + include_directories : [libsinc], + sources: gst_controller_gen_sources, + dependencies : [gst_dep]) diff --git a/libs/gst/helpers/Makefile.am b/libs/gst/helpers/Makefile.am new file mode 100644 index 0000000..d72a652 --- /dev/null +++ b/libs/gst/helpers/Makefile.am @@ -0,0 +1,33 @@ +helpers_PROGRAMS = gst-plugin-scanner +helpersdir=$(libexecdir)/gstreamer-$(GST_API_VERSION) + +gst_plugin_scanner_SOURCES = gst-plugin-scanner.c +gst_plugin_scanner_CFLAGS = $(GST_OBJ_CFLAGS) +gst_plugin_scanner_LDADD = $(GST_OBJ_LIBS) + +if ENABLE_BASH_COMPLETION +helpers_PROGRAMS += gst-completion-helper +gst_completion_helper_SOURCES = gst-completion-helper.c +gst_completion_helper_CFLAGS = $(GST_OBJ_CFLAGS) +gst_completion_helper_LDADD = $(GST_OBJ_LIBS) +endif + +if HAVE_PTP +helpers_PROGRAMS += gst-ptp-helper +gst_ptp_helper_SOURCES = gst-ptp-helper.c +gst_ptp_helper_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) +gst_ptp_helper_LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS) $(CAP_LIBS) +endif + +install-data-hook: +if HAVE_PTP +if HAVE_PTP_HELPER_SETUID + - chown root $(DESTDIR)$(helpersdir)/gst-ptp-helper + - chmod u+s $(DESTDIR)$(helpersdir)/gst-ptp-helper +endif +if HAVE_PTP_HELPER_CAPABILITIES + - $(SETCAP) cap_net_bind_service,cap_net_admin+ep $(DESTDIR)$(helpersdir)/gst-ptp-helper +endif +endif + +EXTRA_DIST = ptp_helper_post_install.sh diff --git a/libs/gst/helpers/Makefile.in b/libs/gst/helpers/Makefile.in new file mode 100644 index 0000000..b61c74c --- /dev/null +++ b/libs/gst/helpers/Makefile.in @@ -0,0 +1,928 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +helpers_PROGRAMS = gst-plugin-scanner$(EXEEXT) $(am__EXEEXT_1) \ + $(am__EXEEXT_2) +@ENABLE_BASH_COMPLETION_TRUE@am__append_1 = gst-completion-helper +@HAVE_PTP_TRUE@am__append_2 = gst-ptp-helper +subdir = libs/gst/helpers +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@ENABLE_BASH_COMPLETION_TRUE@am__EXEEXT_1 = \ +@ENABLE_BASH_COMPLETION_TRUE@ gst-completion-helper$(EXEEXT) +@HAVE_PTP_TRUE@am__EXEEXT_2 = gst-ptp-helper$(EXEEXT) +am__installdirs = "$(DESTDIR)$(helpersdir)" +PROGRAMS = $(helpers_PROGRAMS) +am__gst_completion_helper_SOURCES_DIST = gst-completion-helper.c +@ENABLE_BASH_COMPLETION_TRUE@am_gst_completion_helper_OBJECTS = gst_completion_helper-gst-completion-helper.$(OBJEXT) +gst_completion_helper_OBJECTS = $(am_gst_completion_helper_OBJECTS) +am__DEPENDENCIES_1 = +@ENABLE_BASH_COMPLETION_TRUE@gst_completion_helper_DEPENDENCIES = \ +@ENABLE_BASH_COMPLETION_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +gst_completion_helper_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_completion_helper_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_gst_plugin_scanner_OBJECTS = \ + gst_plugin_scanner-gst-plugin-scanner.$(OBJEXT) +gst_plugin_scanner_OBJECTS = $(am_gst_plugin_scanner_OBJECTS) +gst_plugin_scanner_DEPENDENCIES = $(am__DEPENDENCIES_1) +gst_plugin_scanner_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_plugin_scanner_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__gst_ptp_helper_SOURCES_DIST = gst-ptp-helper.c +@HAVE_PTP_TRUE@am_gst_ptp_helper_OBJECTS = \ +@HAVE_PTP_TRUE@ gst_ptp_helper-gst-ptp-helper.$(OBJEXT) +gst_ptp_helper_OBJECTS = $(am_gst_ptp_helper_OBJECTS) +@HAVE_PTP_TRUE@gst_ptp_helper_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@HAVE_PTP_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +gst_ptp_helper_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_ptp_helper_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(gst_completion_helper_SOURCES) \ + $(gst_plugin_scanner_SOURCES) $(gst_ptp_helper_SOURCES) +DIST_SOURCES = $(am__gst_completion_helper_SOURCES_DIST) \ + $(gst_plugin_scanner_SOURCES) \ + $(am__gst_ptp_helper_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +helpersdir = $(libexecdir)/gstreamer-$(GST_API_VERSION) +gst_plugin_scanner_SOURCES = gst-plugin-scanner.c +gst_plugin_scanner_CFLAGS = $(GST_OBJ_CFLAGS) +gst_plugin_scanner_LDADD = $(GST_OBJ_LIBS) +@ENABLE_BASH_COMPLETION_TRUE@gst_completion_helper_SOURCES = gst-completion-helper.c +@ENABLE_BASH_COMPLETION_TRUE@gst_completion_helper_CFLAGS = $(GST_OBJ_CFLAGS) +@ENABLE_BASH_COMPLETION_TRUE@gst_completion_helper_LDADD = $(GST_OBJ_LIBS) +@HAVE_PTP_TRUE@gst_ptp_helper_SOURCES = gst-ptp-helper.c +@HAVE_PTP_TRUE@gst_ptp_helper_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) +@HAVE_PTP_TRUE@gst_ptp_helper_LDADD = $(GST_OBJ_LIBS) $(GIO_LIBS) $(CAP_LIBS) +EXTRA_DIST = ptp_helper_post_install.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/helpers/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/helpers/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-helpersPROGRAMS: $(helpers_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(helpers_PROGRAMS)'; test -n "$(helpersdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(helpersdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(helpersdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(helpersdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(helpersdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-helpersPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(helpers_PROGRAMS)'; test -n "$(helpersdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(helpersdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(helpersdir)" && rm -f $$files + +clean-helpersPROGRAMS: + @list='$(helpers_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +gst-completion-helper$(EXEEXT): $(gst_completion_helper_OBJECTS) $(gst_completion_helper_DEPENDENCIES) $(EXTRA_gst_completion_helper_DEPENDENCIES) + @rm -f gst-completion-helper$(EXEEXT) + $(AM_V_CCLD)$(gst_completion_helper_LINK) $(gst_completion_helper_OBJECTS) $(gst_completion_helper_LDADD) $(LIBS) + +gst-plugin-scanner$(EXEEXT): $(gst_plugin_scanner_OBJECTS) $(gst_plugin_scanner_DEPENDENCIES) $(EXTRA_gst_plugin_scanner_DEPENDENCIES) + @rm -f gst-plugin-scanner$(EXEEXT) + $(AM_V_CCLD)$(gst_plugin_scanner_LINK) $(gst_plugin_scanner_OBJECTS) $(gst_plugin_scanner_LDADD) $(LIBS) + +gst-ptp-helper$(EXEEXT): $(gst_ptp_helper_OBJECTS) $(gst_ptp_helper_DEPENDENCIES) $(EXTRA_gst_ptp_helper_DEPENDENCIES) + @rm -f gst-ptp-helper$(EXEEXT) + $(AM_V_CCLD)$(gst_ptp_helper_LINK) $(gst_ptp_helper_OBJECTS) $(gst_ptp_helper_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_completion_helper-gst-completion-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +gst_completion_helper-gst-completion-helper.o: gst-completion-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_completion_helper_CFLAGS) $(CFLAGS) -MT gst_completion_helper-gst-completion-helper.o -MD -MP -MF $(DEPDIR)/gst_completion_helper-gst-completion-helper.Tpo -c -o gst_completion_helper-gst-completion-helper.o `test -f 'gst-completion-helper.c' || echo '$(srcdir)/'`gst-completion-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_completion_helper-gst-completion-helper.Tpo $(DEPDIR)/gst_completion_helper-gst-completion-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-completion-helper.c' object='gst_completion_helper-gst-completion-helper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_completion_helper_CFLAGS) $(CFLAGS) -c -o gst_completion_helper-gst-completion-helper.o `test -f 'gst-completion-helper.c' || echo '$(srcdir)/'`gst-completion-helper.c + +gst_completion_helper-gst-completion-helper.obj: gst-completion-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_completion_helper_CFLAGS) $(CFLAGS) -MT gst_completion_helper-gst-completion-helper.obj -MD -MP -MF $(DEPDIR)/gst_completion_helper-gst-completion-helper.Tpo -c -o gst_completion_helper-gst-completion-helper.obj `if test -f 'gst-completion-helper.c'; then $(CYGPATH_W) 'gst-completion-helper.c'; else $(CYGPATH_W) '$(srcdir)/gst-completion-helper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_completion_helper-gst-completion-helper.Tpo $(DEPDIR)/gst_completion_helper-gst-completion-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-completion-helper.c' object='gst_completion_helper-gst-completion-helper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_completion_helper_CFLAGS) $(CFLAGS) -c -o gst_completion_helper-gst-completion-helper.obj `if test -f 'gst-completion-helper.c'; then $(CYGPATH_W) 'gst-completion-helper.c'; else $(CYGPATH_W) '$(srcdir)/gst-completion-helper.c'; fi` + +gst_plugin_scanner-gst-plugin-scanner.o: gst-plugin-scanner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_plugin_scanner_CFLAGS) $(CFLAGS) -MT gst_plugin_scanner-gst-plugin-scanner.o -MD -MP -MF $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Tpo -c -o gst_plugin_scanner-gst-plugin-scanner.o `test -f 'gst-plugin-scanner.c' || echo '$(srcdir)/'`gst-plugin-scanner.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Tpo $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-plugin-scanner.c' object='gst_plugin_scanner-gst-plugin-scanner.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_plugin_scanner_CFLAGS) $(CFLAGS) -c -o gst_plugin_scanner-gst-plugin-scanner.o `test -f 'gst-plugin-scanner.c' || echo '$(srcdir)/'`gst-plugin-scanner.c + +gst_plugin_scanner-gst-plugin-scanner.obj: gst-plugin-scanner.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_plugin_scanner_CFLAGS) $(CFLAGS) -MT gst_plugin_scanner-gst-plugin-scanner.obj -MD -MP -MF $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Tpo -c -o gst_plugin_scanner-gst-plugin-scanner.obj `if test -f 'gst-plugin-scanner.c'; then $(CYGPATH_W) 'gst-plugin-scanner.c'; else $(CYGPATH_W) '$(srcdir)/gst-plugin-scanner.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Tpo $(DEPDIR)/gst_plugin_scanner-gst-plugin-scanner.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-plugin-scanner.c' object='gst_plugin_scanner-gst-plugin-scanner.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_plugin_scanner_CFLAGS) $(CFLAGS) -c -o gst_plugin_scanner-gst-plugin-scanner.obj `if test -f 'gst-plugin-scanner.c'; then $(CYGPATH_W) 'gst-plugin-scanner.c'; else $(CYGPATH_W) '$(srcdir)/gst-plugin-scanner.c'; fi` + +gst_ptp_helper-gst-ptp-helper.o: gst-ptp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_ptp_helper_CFLAGS) $(CFLAGS) -MT gst_ptp_helper-gst-ptp-helper.o -MD -MP -MF $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Tpo -c -o gst_ptp_helper-gst-ptp-helper.o `test -f 'gst-ptp-helper.c' || echo '$(srcdir)/'`gst-ptp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Tpo $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-ptp-helper.c' object='gst_ptp_helper-gst-ptp-helper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_ptp_helper_CFLAGS) $(CFLAGS) -c -o gst_ptp_helper-gst-ptp-helper.o `test -f 'gst-ptp-helper.c' || echo '$(srcdir)/'`gst-ptp-helper.c + +gst_ptp_helper-gst-ptp-helper.obj: gst-ptp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_ptp_helper_CFLAGS) $(CFLAGS) -MT gst_ptp_helper-gst-ptp-helper.obj -MD -MP -MF $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Tpo -c -o gst_ptp_helper-gst-ptp-helper.obj `if test -f 'gst-ptp-helper.c'; then $(CYGPATH_W) 'gst-ptp-helper.c'; else $(CYGPATH_W) '$(srcdir)/gst-ptp-helper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Tpo $(DEPDIR)/gst_ptp_helper-gst-ptp-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-ptp-helper.c' object='gst_ptp_helper-gst-ptp-helper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_ptp_helper_CFLAGS) $(CFLAGS) -c -o gst_ptp_helper-gst-ptp-helper.obj `if test -f 'gst-ptp-helper.c'; then $(CYGPATH_W) 'gst-ptp-helper.c'; else $(CYGPATH_W) '$(srcdir)/gst-ptp-helper.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(helpersdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-helpersPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-helpersPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-helpersPROGRAMS + +.MAKE: install-am install-data-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-helpersPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-data-hook install-dvi install-dvi-am \ + install-exec install-exec-am install-helpersPROGRAMS \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-helpersPROGRAMS + +.PRECIOUS: Makefile + + +install-data-hook: +@HAVE_PTP_HELPER_SETUID_TRUE@@HAVE_PTP_TRUE@ - chown root $(DESTDIR)$(helpersdir)/gst-ptp-helper +@HAVE_PTP_HELPER_SETUID_TRUE@@HAVE_PTP_TRUE@ - chmod u+s $(DESTDIR)$(helpersdir)/gst-ptp-helper +@HAVE_PTP_HELPER_CAPABILITIES_TRUE@@HAVE_PTP_TRUE@ - $(SETCAP) cap_net_bind_service,cap_net_admin+ep $(DESTDIR)$(helpersdir)/gst-ptp-helper + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/helpers/gst-completion-helper.c b/libs/gst/helpers/gst-completion-helper.c new file mode 100644 index 0000000..95821c8 --- /dev/null +++ b/libs/gst/helpers/gst-completion-helper.c @@ -0,0 +1,271 @@ +/* GStreamer + * Copyright (C) 2015 Mathieu Duponchelle + * + * gst-completion-helper.c: tool to let other tools enjoy fast and powerful + * gstreamer-aware completion + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +static GList * +get_pad_templates_info (GstElement * element, GstElementFactory * factory, + GstPadDirection direction) +{ + const GList *pads; + GstStaticPadTemplate *padtemplate; + GList *caps_list = NULL; + + if (gst_element_factory_get_num_pad_templates (factory) == 0) { + g_print (" none\n"); + return NULL; + } + + pads = gst_element_factory_get_static_pad_templates (factory); + while (pads) { + padtemplate = (GstStaticPadTemplate *) (pads->data); + pads = g_list_next (pads); + + if (padtemplate->direction != direction) + continue; + + if (padtemplate->static_caps.string) { + caps_list = + g_list_append (caps_list, + gst_static_caps_get (&padtemplate->static_caps)); + } + + } + + return caps_list; +} + +static GList * +_get_pad_caps (const gchar * factory_name, GstPadDirection direction) +{ + GstElementFactory *factory = gst_element_factory_find (factory_name); + GstElement *element = gst_element_factory_make (factory_name, NULL); + + if (!element) + return NULL; + if (!factory) + return NULL; + factory = + GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + if (!factory) + return NULL; + return get_pad_templates_info (element, factory, direction); +} + +static gboolean +_are_linkable (GstPluginFeature * feature, GList * caps_list) +{ + gboolean print = FALSE; + GstElementFactory *factory = GST_ELEMENT_FACTORY (feature); + + GList *tmp; + print = FALSE; + for (tmp = caps_list; tmp; tmp = tmp->next) { + if (gst_element_factory_can_sink_any_caps (factory, tmp->data)) { + print = TRUE; + break; + } + } + + return print; +} + +static gboolean +_belongs_to_klass (GstElementFactory * factory, const gchar * klass) +{ + const gchar *factory_klass; + + + factory_klass = + gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS); + if (strstr (factory_klass, klass)) + return TRUE; + return FALSE; +} + +static void +_list_features (const gchar * compatible_with, const gchar * klass, + GstCaps * sinkcaps) +{ + GList *plugins, *orig_plugins; + GList *caps_list = NULL; + + if (compatible_with) { + caps_list = _get_pad_caps (compatible_with, GST_PAD_SRC); + } + + orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ()); + while (plugins) { + GList *features, *orig_features; + GstPlugin *plugin; + + plugin = (GstPlugin *) (plugins->data); + plugins = g_list_next (plugins); + + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) { + continue; + } + + orig_features = features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + while (features) { + GstPluginFeature *feature; + + if (G_UNLIKELY (features->data == NULL)) + goto next; + feature = GST_PLUGIN_FEATURE (features->data); + + if (GST_IS_ELEMENT_FACTORY (feature)) { + gboolean print = TRUE; + if (caps_list) + print = _are_linkable (feature, caps_list); + if (print && klass) + print = _belongs_to_klass (GST_ELEMENT_FACTORY (feature), klass); + if (print && sinkcaps) + print = + gst_element_factory_can_sink_any_caps (GST_ELEMENT_FACTORY + (feature), sinkcaps); + + if (print) + g_print ("%s ", gst_plugin_feature_get_name (feature)); + } + + next: + features = g_list_next (features); + } + + gst_plugin_feature_list_free (orig_features); + } + + g_list_free (caps_list); + g_print ("\n"); + gst_plugin_list_free (orig_plugins); +} + +static void +_print_element_properties_info (GstElement * element) +{ + GParamSpec **property_specs; + guint num_properties, i; + + property_specs = g_object_class_list_properties + (G_OBJECT_GET_CLASS (element), &num_properties); + + for (i = 0; i < num_properties; i++) { + GParamSpec *param = property_specs[i]; + + if (param->flags & G_PARAM_WRITABLE) { + g_print ("%s= ", g_param_spec_get_name (param)); + } + } + + g_free (property_specs); +} + +static void +_list_element_properties (const gchar * factory_name) +{ + GstElement *element = gst_element_factory_make (factory_name, NULL); + + _print_element_properties_info (element); +} + +int +main (int argc, char *argv[]) +{ + gboolean list_features = FALSE; + gchar *compatible_with = NULL; + gchar *element = NULL; + gchar *klass = NULL; + gchar *caps_str = NULL; + GstCaps *sinkcaps = NULL; + gint exit_code = EXIT_SUCCESS; + + GOptionEntry options[] = { + {"list-features", 'l', 0, G_OPTION_ARG_NONE, &list_features, + "list all the available features", NULL}, + {"compatible-with", '\0', 0, G_OPTION_ARG_STRING, &compatible_with, + "Only print the elements that could be queued after this feature name", + NULL}, + {"element-properties", '\0', 0, G_OPTION_ARG_STRING, &element, + "The element to list properties on", NULL}, + {"klass", '\0', 0, G_OPTION_ARG_STRING, &klass, + "Only print the elements belonging to that klass", NULL}, + {"sinkcaps", '\0', 0, G_OPTION_ARG_STRING, &caps_str, + "Only print the elements that can sink these caps", NULL}, + {NULL} + }; + + GOptionContext *ctx; + GError *err = NULL; + + ctx = g_option_context_new ("PIPELINE-DESCRIPTION"); + 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)) { + if (err) + g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message)); + else + g_printerr ("Error initializing: Unknown error!\n"); + g_clear_error (&err); + g_option_context_free (ctx); + exit (1); + } + g_option_context_free (ctx); + + if (caps_str) { + sinkcaps = gst_caps_from_string (caps_str); + if (!sinkcaps) { + exit_code = EXIT_FAILURE; + goto done; + } + } + + if (compatible_with || klass || sinkcaps) { + _list_features (compatible_with, klass, sinkcaps); + goto done; + } + + if (element) { + _list_element_properties (element); + goto done; + } + + if (list_features) { + _list_features (NULL, NULL, NULL); + goto done; + } + +done: + if (sinkcaps) + gst_caps_unref (sinkcaps); + exit (exit_code); +} diff --git a/libs/gst/helpers/gst-plugin-scanner.c b/libs/gst/helpers/gst-plugin-scanner.c new file mode 100644 index 0000000..cbefb29 --- /dev/null +++ b/libs/gst/helpers/gst-plugin-scanner.c @@ -0,0 +1,71 @@ +/* GStreamer + * Copyright (C) 2008 Jan Schmidt + * + * gst-plugin-scanner.c: tool to load plugins out of process for scanning + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Helper binary that does plugin-loading out of process and feeds results + * back to the parent over fds. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +int +main (int argc, char *argv[]) +{ + gboolean res; + char **my_argv; + int my_argc; + + /* We may or may not have an executable path */ + if (argc != 2 && argc != 3) + return 1; + + if (strcmp (argv[1], "-l")) + return 1; + + my_argc = 2; + my_argv = g_malloc (my_argc * sizeof (char *)); + my_argv[0] = argv[0]; + my_argv[1] = (char *) "--gst-disable-registry-update"; + +#ifndef GST_DISABLE_REGISTRY + _gst_disable_registry_cache = TRUE; +#endif + + if (argc == 3) + _gst_executable_path = g_strdup (argv[2]); + + res = gst_init_check (&my_argc, &my_argv, NULL); + + g_free (my_argv); + if (!res) + return 1; + + /* Create registry scanner listener and run */ + if (!_gst_plugin_loader_client_run ()) + return 1; + + return 0; +} diff --git a/libs/gst/helpers/gst-ptp-helper.c b/libs/gst/helpers/gst-ptp-helper.c new file mode 100644 index 0000000..91a2570 --- /dev/null +++ b/libs/gst/helpers/gst-ptp-helper.c @@ -0,0 +1,689 @@ +/* GStreamer + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* Helper process that runs setuid root or with appropriate privileges to + * listen on ports < 1024, do multicast operations and get MAC addresses of + * interfaces. Privileges are dropped after these operations are done. + * + * It listens on the PTP multicast group on port 319 and 320 and forwards + * everything received there to stdout, while forwarding everything received + * on stdout to those sockets. + * Additionally it provides the MAC address of a network interface via stdout + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_GETIFADDRS_AF_LINK +#include +#include +#endif + +#ifdef HAVE_PTP_HELPER_SETUID +#include +#include +#endif + +#ifdef HAVE_PTP_HELPER_CAPABILITIES +#include +#endif + +#include +#include + +#include +#include + +#define PTP_MULTICAST_GROUP "224.0.1.129" +#define PTP_EVENT_PORT 319 +#define PTP_GENERAL_PORT 320 + +static gchar **ifaces = NULL; +static gboolean verbose = FALSE; +static guint64 clock_id = (guint64) - 1; +static guint8 clock_id_array[8]; + +static GOptionEntry opt_entries[] = { + {"interface", 'i', 0, G_OPTION_ARG_STRING_ARRAY, &ifaces, + "Interface to listen on", NULL}, + {"clock-id", 'c', 0, G_OPTION_ARG_INT64, &clock_id, + "PTP clock id", NULL}, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Be verbose", NULL}, + {NULL} +}; + +static GSocketAddress *event_saddr, *general_saddr; +static GSocket *socket_event, *socket_general; +static GIOChannel *stdin_channel, *stdout_channel; + +static gboolean +have_socket_data_cb (GSocket * socket, GIOCondition condition, + gpointer user_data) +{ + gchar buffer[8192]; + gssize read; + gsize written; + GError *err = NULL; + GIOStatus status; + StdIOHeader header = { 0, }; + + read = g_socket_receive (socket, buffer, sizeof (buffer), NULL, &err); + if (read == -1) + g_error ("Failed to read from socket: %s", err->message); + g_clear_error (&err); + + if (verbose) + g_message ("Received %" G_GSSIZE_FORMAT " bytes from %s socket", read, + (socket == socket_event ? "event" : "general")); + + header.size = read; + header.type = (socket == socket_event) ? TYPE_EVENT : TYPE_GENERAL; + + status = + g_io_channel_write_chars (stdout_channel, (gchar *) & header, + sizeof (header), &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdout write status: %d", status); + } else if (written != sizeof (header)) { + g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written); + } + + status = + g_io_channel_write_chars (stdout_channel, buffer, read, &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdout write status: %d", status); + } else if (written != read) { + g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written); + } + + return G_SOURCE_CONTINUE; +} + +static gboolean +have_stdin_data_cb (GIOChannel * channel, GIOCondition condition, + gpointer user_data) +{ + GIOStatus status; + StdIOHeader header = { 0, }; + gchar buffer[8192]; + GError *err = NULL; + gsize read; + gssize written; + + if ((condition & G_IO_STATUS_EOF)) { + g_message ("EOF on stdin"); + exit (0); + } + + status = + g_io_channel_read_chars (channel, (gchar *) & header, sizeof (header), + &read, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to read from stdin: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdin"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdin read status: %d", status); + } else if (read != sizeof (header)) { + g_error ("Unexpected read size: %" G_GSIZE_FORMAT, read); + } else if (header.size > 8192) { + g_error ("Unexpected size: %u", header.size); + } + + status = g_io_channel_read_chars (channel, buffer, header.size, &read, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to read from stdin: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdin"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdin read status: %d", status); + } else if (read != header.size) { + g_error ("Unexpected read size: %" G_GSIZE_FORMAT, read); + } + + switch (header.type) { + case TYPE_EVENT: + case TYPE_GENERAL: + written = + g_socket_send_to (header.type == + TYPE_EVENT ? socket_event : socket_general, + (header.type == TYPE_EVENT ? event_saddr : general_saddr), buffer, + header.size, NULL, &err); + if (written == -1) + g_error ("Failed to write to socket: %s", err->message); + else if (written != header.size) + g_error ("Unexpected write size: %" G_GSSIZE_FORMAT, written); + g_clear_error (&err); + if (verbose) + g_message ("Sent %" G_GSSIZE_FORMAT " bytes to %s socket", read, + (header.type == TYPE_EVENT ? "event" : "general")); + break; + default: + break; + } + + return G_SOURCE_CONTINUE; +} + +static void +setup_sockets (void) +{ + GInetAddress *bind_addr, *mcast_addr; + GSocketAddress *bind_saddr; + GSource *socket_event_source, *socket_general_source; + gchar **probed_ifaces = NULL; + GError *err = NULL; + + /* Create sockets */ + socket_event = + g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, &err); + if (!socket_event) + g_error ("Couldn't create event socket: %s", err->message); + g_clear_error (&err); + g_socket_set_multicast_loopback (socket_event, FALSE); + + socket_general = + g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, &err); + if (!socket_general) + g_error ("Couldn't create general socket: %s", err->message); + g_clear_error (&err); + g_socket_set_multicast_loopback (socket_general, FALSE); + + /* Bind sockets */ + bind_addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); + bind_saddr = g_inet_socket_address_new (bind_addr, PTP_EVENT_PORT); + if (!g_socket_bind (socket_event, bind_saddr, TRUE, &err)) + g_error ("Couldn't bind event socket: %s", err->message); + g_object_unref (bind_saddr); + bind_saddr = g_inet_socket_address_new (bind_addr, PTP_GENERAL_PORT); + if (!g_socket_bind (socket_general, bind_saddr, TRUE, &err)) + g_error ("Couldn't bind general socket: %s", err->message); + g_object_unref (bind_saddr); + g_object_unref (bind_addr); + + /* Probe all non-loopback interfaces */ + if (!ifaces) { +#if defined(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR) + struct ifreq ifr; + struct ifconf ifc; + gchar buf[8192]; + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) { + guint i, idx = 0; + + probed_ifaces = g_new0 (gchar *, ifc.ifc_len + 1); + + for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) { + strncpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name, IFNAMSIZ); + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) { + if ((ifr.ifr_flags & IFF_LOOPBACK)) + continue; + probed_ifaces[idx] = g_strndup (ifc.ifc_req[i].ifr_name, IFNAMSIZ); + idx++; + } else { + g_warning ("can't get flags of interface '%s'", + ifc.ifc_req[i].ifr_name); + probed_ifaces[idx] = g_strndup (ifc.ifc_req[i].ifr_name, IFNAMSIZ); + idx++; + } + if (idx != 0) + ifaces = probed_ifaces; + } + } +#elif defined(HAVE_GETIFADDRS_AF_LINK) + struct ifaddrs *ifaddr, *ifa; + + if (getifaddrs (&ifaddr) != -1) { + GPtrArray *arr; + + arr = g_ptr_array_new (); + + for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_LOOPBACK)) + continue; + + if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK) + continue; + + g_ptr_array_add (arr, g_strdup (ifa->ifa_name)); + } + freeifaddrs (ifaddr); + + g_ptr_array_add (arr, NULL); + ifaces = probed_ifaces = (gchar **) g_ptr_array_free (arr, FALSE); + } +#else +#warning "Implement something to list all network interfaces" +#endif + } + + /* Get a clock id from the MAC address if none was given */ + if (clock_id == (guint64) - 1) { + gboolean success = FALSE; + +#if defined(HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR) + struct ifreq ifr; + + if (ifaces) { + gchar **ptr = ifaces; + + while (*ptr) { + memcpy (ifr.ifr_name, *ptr, IFNAMSIZ); + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFHWADDR, &ifr) == 0) { + clock_id_array[0] = ifr.ifr_hwaddr.sa_data[0]; + clock_id_array[1] = ifr.ifr_hwaddr.sa_data[1]; + clock_id_array[2] = ifr.ifr_hwaddr.sa_data[2]; + clock_id_array[3] = 0xff; + clock_id_array[4] = 0xfe; + clock_id_array[5] = ifr.ifr_hwaddr.sa_data[3]; + clock_id_array[6] = ifr.ifr_hwaddr.sa_data[4]; + clock_id_array[7] = ifr.ifr_hwaddr.sa_data[5]; + success = TRUE; + break; + } + } + + ptr++; + } else { + struct ifconf ifc; + gchar buf[8192]; + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) { + guint i; + + for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) { + strncpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name, IFNAMSIZ); + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) { + if ((ifr.ifr_flags & IFF_LOOPBACK)) + continue; + + if (ioctl (g_socket_get_fd (socket_event), SIOCGIFHWADDR, + &ifr) == 0) { + clock_id_array[0] = ifr.ifr_hwaddr.sa_data[0]; + clock_id_array[1] = ifr.ifr_hwaddr.sa_data[1]; + clock_id_array[2] = ifr.ifr_hwaddr.sa_data[2]; + clock_id_array[3] = 0xff; + clock_id_array[4] = 0xfe; + clock_id_array[5] = ifr.ifr_hwaddr.sa_data[3]; + clock_id_array[6] = ifr.ifr_hwaddr.sa_data[4]; + clock_id_array[7] = ifr.ifr_hwaddr.sa_data[5]; + success = TRUE; + break; + } + } else { + g_warning ("can't get flags of interface '%s'", + ifc.ifc_req[i].ifr_name); + } + } + } + } +#elif defined(HAVE_GETIFADDRS_AF_LINK) + struct ifaddrs *ifaddr, *ifa; + + if (getifaddrs (&ifaddr) != -1) { + for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr; + guint8 mac_addr[6]; + + if ((ifa->ifa_flags & IFF_LOOPBACK)) + continue; + + if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK) + continue; + + if (ifaces) { + gchar **p = ifaces; + gboolean found = FALSE; + + while (*p) { + if (strcmp (*p, ifa->ifa_name) == 0) { + found = TRUE; + break; + } + p++; + } + + if (!found) + continue; + } + + if (sdl->sdl_alen != 6) + continue; + + memcpy (mac_addr, LLADDR (sdl), sdl->sdl_alen); + + clock_id_array[0] = mac_addr[0]; + clock_id_array[1] = mac_addr[1]; + clock_id_array[2] = mac_addr[2]; + clock_id_array[3] = 0xff; + clock_id_array[4] = 0xfe; + clock_id_array[5] = mac_addr[3]; + clock_id_array[6] = mac_addr[4]; + clock_id_array[7] = mac_addr[5]; + success = TRUE; + break; + } + + freeifaddrs (ifaddr); + } +#else +#warning "Implement something to get MAC addresses of network interfaces" +#endif + + if (!success) { + g_warning ("can't get any MAC address, using random clock id"); + clock_id = (((guint64) g_random_int ()) << 32) | (g_random_int ()); + GST_WRITE_UINT64_BE (clock_id_array, clock_id); + clock_id_array[3] = 0xff; + clock_id_array[4] = 0xfe; + } + } else { + GST_WRITE_UINT64_BE (clock_id_array, clock_id); + } + + /* Join multicast groups */ + mcast_addr = g_inet_address_new_from_string (PTP_MULTICAST_GROUP); + if (ifaces) { + gchar **ptr = ifaces; + gboolean success = FALSE; + + while (*ptr) { + gint c = 0; + if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, *ptr, + &err) + && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE)) + g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr, + err->message); + else + c++; + g_clear_error (&err); + + if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE, + *ptr, &err) + && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE)) + g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr, + err->message); + else + c++; + g_clear_error (&err); + + if (c == 2) + success = TRUE; + ptr++; + } + + if (!success) { + /* Join multicast group without any interface */ + if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, NULL, + &err)) + g_error ("Couldn't join multicast group: %s", err->message); + g_clear_error (&err); + if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE, + NULL, &err)) + g_error ("Couldn't join multicast group: %s", err->message); + g_clear_error (&err); + } + } else { + /* Join multicast group without any interface */ + if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, NULL, + &err)) + g_error ("Couldn't join multicast group: %s", err->message); + g_clear_error (&err); + if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE, NULL, + &err)) + g_error ("Couldn't join multicast group: %s", err->message); + g_clear_error (&err); + } + + event_saddr = g_inet_socket_address_new (mcast_addr, PTP_EVENT_PORT); + general_saddr = g_inet_socket_address_new (mcast_addr, PTP_GENERAL_PORT); + + /* Create socket sources */ + socket_event_source = + g_socket_create_source (socket_event, G_IO_IN | G_IO_PRI, NULL); + g_source_set_priority (socket_event_source, G_PRIORITY_HIGH); + g_source_set_callback (socket_event_source, (GSourceFunc) have_socket_data_cb, + NULL, NULL); + g_source_attach (socket_event_source, NULL); + socket_general_source = + g_socket_create_source (socket_general, G_IO_IN | G_IO_PRI, NULL); + g_source_set_priority (socket_general_source, G_PRIORITY_DEFAULT); + g_source_set_callback (socket_general_source, + (GSourceFunc) have_socket_data_cb, NULL, NULL); + g_source_attach (socket_general_source, NULL); + + g_strfreev (probed_ifaces); +} + +static void +drop_privileges (void) +{ +#ifdef HAVE_PTP_HELPER_SETUID + /* Switch to the given user/group */ +#ifdef HAVE_PTP_HELPER_SETUID_GROUP + { + struct group *grp; + + grp = getgrnam (HAVE_PTP_HELPER_SETUID_GROUP); + if (!grp) + g_error ("Failed to get group information '%s': %s", + HAVE_PTP_HELPER_SETUID_GROUP, g_strerror (errno)); + + if (setgid (grp->gr_gid) != 0) + g_error ("Failed to change to group '%s': %s", + HAVE_PTP_HELPER_SETUID_GROUP, g_strerror (errno)); + } +#endif + +#ifdef HAVE_PTP_HELPER_SETUID_USER + { + struct passwd *pwd; + + pwd = getpwnam (HAVE_PTP_HELPER_SETUID_USER); + if (!pwd) + g_error ("Failed to get user information '%s': %s", + HAVE_PTP_HELPER_SETUID_USER, g_strerror (errno)); + +#ifndef HAVE_PTP_HELPER_SETUID_GROUP + if (setgid (pwd->pw_gid) != 0) + g_error ("Failed to change to user group '%s': %s", + HAVE_PTP_HELPER_SETUID_USER, g_strerror (errno)); +#endif + + if (setuid (pwd->pw_uid) != 0) + g_error ("Failed to change to user '%s': %s", HAVE_PTP_HELPER_SETUID_USER, + g_strerror (errno)); + } +#endif +#endif +#ifdef HAVE_PTP_HELPER_CAPABILITIES + /* Drop all capabilities */ + { + cap_t caps; + + caps = cap_get_proc (); + if (caps == 0) + g_error ("Failed to get process caps: %s", g_strerror (errno)); + if (cap_clear (caps) != 0) + g_error ("Failed to clear caps: %s", g_strerror (errno)); + if (cap_set_proc (caps) != 0) + g_error ("Failed to set process caps: %s", g_strerror (errno)); + } +#endif +} + +static void +setup_stdio_channels (void) +{ + GSource *stdin_source; + + /* Create stdin source */ + stdin_channel = g_io_channel_unix_new (STDIN_FILENO); + if (g_io_channel_set_encoding (stdin_channel, NULL, + NULL) == G_IO_STATUS_ERROR) + g_error ("Failed to set stdin to binary encoding"); + g_io_channel_set_buffered (stdin_channel, FALSE); + stdin_source = + g_io_create_watch (stdin_channel, G_IO_IN | G_IO_PRI | G_IO_HUP); + g_source_set_priority (stdin_source, G_PRIORITY_DEFAULT); + g_source_set_callback (stdin_source, (GSourceFunc) have_stdin_data_cb, NULL, + NULL); + g_source_attach (stdin_source, NULL); + + /* Create stdout channel */ + stdout_channel = g_io_channel_unix_new (STDOUT_FILENO); + if (g_io_channel_set_encoding (stdout_channel, NULL, + NULL) == G_IO_STATUS_ERROR) + g_error ("Failed to set stdout to binary encoding"); + g_io_channel_set_buffered (stdout_channel, FALSE); +} + +static void +write_clock_id (void) +{ + GError *err = NULL; + GIOStatus status; + StdIOHeader header = { 0, }; + gsize written; + + /* Write clock id to stdout */ + + header.type = TYPE_CLOCK_ID; + header.size = 8; + status = + g_io_channel_write_chars (stdout_channel, (gchar *) & header, + sizeof (header), &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdout write status: %d", status); + } else if (written != sizeof (header)) { + g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written); + } + + status = + g_io_channel_write_chars (stdout_channel, + (const gchar *) clock_id_array, sizeof (clock_id_array), &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_error ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + exit (0); + } else if (status != G_IO_STATUS_NORMAL) { + g_error ("Unexpected stdout write status: %d", status); + } else if (written != sizeof (clock_id_array)) { + g_error ("Unexpected write size: %" G_GSIZE_FORMAT, written); + } +} + +#ifdef __APPLE__ +static gint +dummy_poll (GPollFD * fds, guint nfds, gint timeout) +{ + return g_poll (fds, nfds, timeout); +} +#endif + +gint +main (gint argc, gchar ** argv) +{ + GOptionContext *opt_ctx; + GMainLoop *loop; + GError *err = NULL; + + /* FIXME: Work around some side effects of the changes from + * https://bugzilla.gnome.org/show_bug.cgi?id=741054 + * + * The modified poll function somehow calls setugid(), which + * then abort()s the application. Make sure that we use g_poll() + * here! + */ +#ifdef __APPLE__ + { + GMainContext *context = g_main_context_default (); + g_main_context_set_poll_func (context, dummy_poll); + } +#endif + +#ifdef HAVE_PTP_HELPER_SETUID + if (setuid (0) < 0) + g_error ("not running with superuser privileges"); +#endif + + opt_ctx = g_option_context_new ("- GStreamer PTP helper process"); + g_option_context_add_main_entries (opt_ctx, opt_entries, NULL); + if (!g_option_context_parse (opt_ctx, &argc, &argv, &err)) + g_error ("Error parsing options: %s", err->message); + g_clear_error (&err); + g_option_context_free (opt_ctx); + + setup_sockets (); + drop_privileges (); + setup_stdio_channels (); + write_clock_id (); + + /* Get running */ + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + /* We never exit cleanly, so don't do cleanup */ + g_assert_not_reached (); + + return 0; +} diff --git a/libs/gst/helpers/meson.build b/libs/gst/helpers/meson.build new file mode 100644 index 0000000..022821f --- /dev/null +++ b/libs/gst/helpers/meson.build @@ -0,0 +1,134 @@ +executable('gst-plugin-scanner', + 'gst-plugin-scanner.c', + c_args : gst_c_args, + include_directories : [configinc], + dependencies : [gobject_dep, gmodule_dep, glib_dep, mathlib, gst_dep], + link_with : [printf_lib], + install_dir : helpers_install_dir, + install: true, +) + +# Used in test env setup to make tests find plugin scanner in build tree +gst_scanner_dir = meson.current_build_dir() + +if bashcomp_found + executable('gst-completion-helper', + 'gst-completion-helper.c', + c_args : gst_c_args, + include_directories : [configinc], + dependencies : [gobject_dep, glib_dep, gst_dep], + install_dir : helpers_install_dir, + install: true, + ) +endif + +# Check PTP support +have_ptp = false +if host_machine.system() == 'android' + message('PTP not supported on Android because of permissions.') +elif host_machine.system() == 'windows' + message('PTP not supported on Windows, not ported yet.') +elif host_machine.system() == 'ios' # FIXME: is it also darwing on iOS ? + message('PTP not supported on iOS because of permissions.') +elif host_machine.system() == 'darwin' + if cc.has_header('MobileCoreServices/MobileCoreServices.h') + message('PTP not supported on iOS because of permissions.') + else + have_ptp = true + endif +elif ['linux', 'netbsd', 'freebsd', 'openbsd', 'kfreebsd', 'dragonfly', 'solaris'].contains(host_machine.system()) + message('PTP supported on ' + host_machine.system() + '.') + have_ptp = true +endif + +if have_ptp + cdata.set('HAVE_PTP', 1, description : 'PTP support available') + + if cc.compiles('''#include + #include + int some_func (void) { + struct ifreq ifr; + struct ifconf ifc; + ioctl(0, SIOCGIFCONF, &ifc); + ioctl(0, SIOCGIFFLAGS, &ifr); + ioctl(0, SIOCGIFHWADDR, &ifr); + return ifr.ifr_hwaddr.sa_data[0]; + }''', + name : 'SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR available') + cdata.set('HAVE_SIOCGIFCONF_SIOCGIFFLAGS_SIOCGIFHWADDR', 1, + description : 'SIOCGIFCONF, SIOCGIFFLAGS and SIOCGIFHWADDR is available') + endif + + if cc.compiles('''#include + #include + #include + int some_func (void) { + struct ifaddrs *ifaddr; + getifaddrs(&ifaddr); + return (ifaddr->ifa_flags & IFF_LOOPBACK) && ifaddr->ifa_addr->sa_family != AF_LINK; + }''', name : 'getifaddrs() and AF_LINK available') + cdata.set('HAVE_GETIFADDRS_AF_LINK', 1, + description : 'getifaddrs() and AF_LINK is available') + endif + + gst_ptp_have_cap = false + cap_dep = [] + if cc.has_header('sys/capability.h') + cap_dep = cc.find_library('cap', required : false) + if cap_dep.found() and cc.has_function('cap_init', dependencies : cap_dep) + gst_ptp_have_cap = true + endif + endif + + setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false) + + # user/group to change to in gst-ptp-helper + ptp_helper_setuid_user = get_option('with-ptp-helper-setuid-user') + if ptp_helper_setuid_user != '' + cdata.set_quoted('HAVE_PTP_HELPER_SETUID_USER', ptp_helper_setuid_user, + description : 'PTP helper setuid user') + endif + ptp_helper_setuid_group = get_option('with-ptp-helper-setuid-group') + if ptp_helper_setuid_group != '' + cdata.set_quoted('HAVE_PTP_HELPER_SETUID_GROUP', ptp_helper_setuid_group, + description : 'PTP helper setuid group') + endif + + # how to install gst-ptp-helper + with_ptp_helper_permissions = get_option('with-ptp-helper-permissions') + if with_ptp_helper_permissions == 'auto' + if gst_ptp_have_cap and setcap.found() + with_ptp_helper_permissions = 'capabilities' + else + with_ptp_helper_permissions = 'setuid-root' + endif + endif + message('How to install gst-ptp-helper: ' + with_ptp_helper_permissions) + + if with_ptp_helper_permissions == 'none' + # nothing to do + elif with_ptp_helper_permissions == 'setuid-root' + cdata.set('HAVE_PTP_HELPER_SETUID', 1, + description : 'Use setuid-root for permissions in PTP helper') + elif with_ptp_helper_permissions == 'capabilities' + if not setcap.found() + error('capabilities-based ptp-helper-permissions requested, but could not find setcap tool.') + endif + cdata.set('HAVE_PTP_HELPER_CAPABILITIES', 1, + description : 'Use capabilities for permissions in PTP helper') + else + error('Unexpected ptp helper permissions value: ' + with_ptp_helper_permissions) + endif + + executable('gst-ptp-helper', 'gst-ptp-helper.c', + c_args : gst_c_args, + include_directories : [configinc, libsinc], + dependencies : [gio_dep, gobject_dep, glib_dep, mathlib, gst_dep, cap_dep], + link_with : [printf_lib], + install_dir : helpers_install_dir, + install : true) + + meson.add_install_script('ptp_helper_post_install.sh', + helpers_install_dir, with_ptp_helper_permissions, + setcap.found() ? setcap.path() : '') +endif diff --git a/libs/gst/helpers/ptp_helper_post_install.sh b/libs/gst/helpers/ptp_helper_post_install.sh new file mode 100755 index 0000000..eefe1c9 --- /dev/null +++ b/libs/gst/helpers/ptp_helper_post_install.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Meson install script for gst-ptp-helper +# Fails silently at the moment if setting permissions/capabilities doesn't work +helpers_install_dir="$1" +with_ptp_helper_permissions="$2" +setcap="$3" + +ptp_helper="$MESON_INSTALL_DESTDIR_PREFIX/$helpers_install_dir/gst-ptp-helper" + +case "$with_ptp_helper_permissions" in + setuid-root) + echo "$0: permissions before: " + ls -l "$ptp_helper" + chown root "$ptp_helper" || true + chmod u+s "$ptp_helper" || true + echo "$0: permissions after: " + ls -l "$ptp_helper" + ;; + capabilities) + echo "Calling $setcap cap_net_bind_service,cap_net_admin+ep $ptp_helper" + $setcap cap_net_bind_service,cap_net_admin+ep "$ptp_helper" || true + ;; + *) + echo "$0 ERROR: unexpected permissions value '$with_ptp_helper_permissions'"; + exit 2; +esac diff --git a/libs/gst/meson.build b/libs/gst/meson.build new file mode 100644 index 0000000..38dcec9 --- /dev/null +++ b/libs/gst/meson.build @@ -0,0 +1,5 @@ +subdir('base') +subdir('controller') +subdir('net') +subdir('helpers') +subdir('check') diff --git a/libs/gst/net/Makefile.am b/libs/gst/net/Makefile.am new file mode 100644 index 0000000..de254e9 --- /dev/null +++ b/libs/gst/net/Makefile.am @@ -0,0 +1,100 @@ +lib_LTLIBRARIES = libgstnet-@GST_API_VERSION@.la + +libgstnet_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/net +libgstnet_@GST_API_VERSION@_include_HEADERS = \ + net.h \ + net-prelude.h \ + gstnet.h \ + gstnetaddressmeta.h \ + gstnetclientclock.h \ + gstnetcontrolmessagemeta.h \ + gstnettimepacket.h \ + gstnettimeprovider.h \ + gstptpclock.h + +libgstnet_@GST_API_VERSION@_la_SOURCES = \ + gstnetaddressmeta.c \ + gstnetclientclock.c \ + gstnetcontrolmessagemeta.c \ + gstnettimepacket.c \ + gstnettimeprovider.c \ + gstptpclock.c \ + gstntppacket.c \ + gstnetutils.c + +noinst_HEADERS = gstptp_private.h gstntppacket.h gstnetutils.h + +libgstnet_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) +libgstnet_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(GIO_LIBS) \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la +libgstnet_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +# try to prevent packaging errors +check-libexecdir-consistency: + @if test "${GST_PTP_HELPER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; then \ + echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \ + echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \ + echo "*** The same goes for prefix, libdir etc."; \ + echo "*** ${GST_PTP_HELPER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; \ + exit 1; \ + fi + +all-local: check-libexecdir-consistency + +CLEANFILES = *.gcno *.gcda *.gcov + +%.c.gcov: .libs/libgstnet_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstnet_@GST_API_VERSION@_la_SOURCES:=.gcov) + + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstNet-@GST_API_VERSION@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_la_SOURCES)) +gir_cincludes=--c-include="gst/net/net.h" + +GstNet-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_API_VERSION@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ + GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ + CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ + $(INTROSPECTION_SCANNER) -v --namespace GstNet \ + --identifier-prefix=Gst \ + --symbol-prefix=gst \ + --warn-all \ + --nsversion=@GST_API_VERSION@ \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libs \ + -I$(top_builddir) \ + -I$(top_builddir)/libs \ + $(gir_cincludes) \ + --add-include-path=$(top_builddir)/gst \ + --library-path=$(top_builddir)/gst \ + --library=libgstnet-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --include=Gio-2.0 \ + --libtool="${LIBTOOL}" \ + --pkg gstreamer-@GST_API_VERSION@ \ + --pkg gio-2.0 \ + --pkg-export="gstreamer-net-@GST_API_VERSION@" \ + --add-init-section="$(INTROSPECTION_INIT)" \ + --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)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif diff --git a/libs/gst/net/Makefile.in b/libs/gst/net/Makefile.in new file mode 100644 index 0000000..144848d --- /dev/null +++ b/libs/gst/net/Makefile.in @@ -0,0 +1,1086 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) +subdir = libs/gst/net +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libgstnet_@GST_API_VERSION@_include_HEADERS) \ + $(noinst_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgstnet_@GST_API_VERSION@_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la +am_libgstnet_@GST_API_VERSION@_la_OBJECTS = \ + libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo \ + libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo \ + libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo \ + libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo \ + libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo \ + libgstnet_@GST_API_VERSION@_la-gstptpclock.lo \ + libgstnet_@GST_API_VERSION@_la-gstntppacket.lo \ + libgstnet_@GST_API_VERSION@_la-gstnetutils.lo +libgstnet_@GST_API_VERSION@_la_OBJECTS = \ + $(am_libgstnet_@GST_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstnet_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) \ + $(libgstnet_@GST_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstnet_@GST_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(libgstnet_@GST_API_VERSION@_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(typelibs_DATA) +HEADERS = $(libgstnet_@GST_API_VERSION@_include_HEADERS) \ + $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +lib_LTLIBRARIES = libgstnet-@GST_API_VERSION@.la +libgstnet_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/net +libgstnet_@GST_API_VERSION@_include_HEADERS = \ + net.h \ + net-prelude.h \ + gstnet.h \ + gstnetaddressmeta.h \ + gstnetclientclock.h \ + gstnetcontrolmessagemeta.h \ + gstnettimepacket.h \ + gstnettimeprovider.h \ + gstptpclock.h + +libgstnet_@GST_API_VERSION@_la_SOURCES = \ + gstnetaddressmeta.c \ + gstnetclientclock.c \ + gstnetcontrolmessagemeta.c \ + gstnettimepacket.c \ + gstnettimeprovider.c \ + gstptpclock.c \ + gstntppacket.c \ + gstnetutils.c + +noinst_HEADERS = gstptp_private.h gstntppacket.h gstnetutils.h +libgstnet_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) +libgstnet_@GST_API_VERSION@_la_LIBADD = $(GST_OBJ_LIBS) $(GIO_LIBS) \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la + +libgstnet_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +CLEANFILES = *.gcno *.gcda *.gcov $(am__append_1) +@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstNet-@GST_API_VERSION@.gir +@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_include_HEADERS)) +@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, $(libgstnet_@GST_API_VERSION@_la_SOURCES)) +@HAVE_INTROSPECTION_TRUE@gir_cincludes = --c-include="gst/net/net.h" + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(BUILT_GIRSOURCES) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0/ +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libs/gst/net/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libs/gst/net/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstnet-@GST_API_VERSION@.la: $(libgstnet_@GST_API_VERSION@_la_OBJECTS) $(libgstnet_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstnet_@GST_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstnet_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstnet_@GST_API_VERSION@_la_OBJECTS) $(libgstnet_@GST_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetclientclock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimepacket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstntppacket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstptpclock.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo: gstnetaddressmeta.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo `test -f 'gstnetaddressmeta.c' || echo '$(srcdir)/'`gstnetaddressmeta.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnetaddressmeta.c' object='libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnetaddressmeta.lo `test -f 'gstnetaddressmeta.c' || echo '$(srcdir)/'`gstnetaddressmeta.c + +libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo: gstnetclientclock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetclientclock.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo `test -f 'gstnetclientclock.c' || echo '$(srcdir)/'`gstnetclientclock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetclientclock.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetclientclock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnetclientclock.c' object='libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnetclientclock.lo `test -f 'gstnetclientclock.c' || echo '$(srcdir)/'`gstnetclientclock.c + +libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo: gstnetcontrolmessagemeta.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo `test -f 'gstnetcontrolmessagemeta.c' || echo '$(srcdir)/'`gstnetcontrolmessagemeta.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnetcontrolmessagemeta.c' object='libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnetcontrolmessagemeta.lo `test -f 'gstnetcontrolmessagemeta.c' || echo '$(srcdir)/'`gstnetcontrolmessagemeta.c + +libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo: gstnettimepacket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimepacket.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo `test -f 'gstnettimepacket.c' || echo '$(srcdir)/'`gstnettimepacket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimepacket.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimepacket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnettimepacket.c' object='libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnettimepacket.lo `test -f 'gstnettimepacket.c' || echo '$(srcdir)/'`gstnettimepacket.c + +libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo: gstnettimeprovider.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo `test -f 'gstnettimeprovider.c' || echo '$(srcdir)/'`gstnettimeprovider.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnettimeprovider.c' object='libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnettimeprovider.lo `test -f 'gstnettimeprovider.c' || echo '$(srcdir)/'`gstnettimeprovider.c + +libgstnet_@GST_API_VERSION@_la-gstptpclock.lo: gstptpclock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstptpclock.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstptpclock.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstptpclock.lo `test -f 'gstptpclock.c' || echo '$(srcdir)/'`gstptpclock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstptpclock.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstptpclock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstptpclock.c' object='libgstnet_@GST_API_VERSION@_la-gstptpclock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstptpclock.lo `test -f 'gstptpclock.c' || echo '$(srcdir)/'`gstptpclock.c + +libgstnet_@GST_API_VERSION@_la-gstntppacket.lo: gstntppacket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstntppacket.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstntppacket.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstntppacket.lo `test -f 'gstntppacket.c' || echo '$(srcdir)/'`gstntppacket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstntppacket.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstntppacket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstntppacket.c' object='libgstnet_@GST_API_VERSION@_la-gstntppacket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstntppacket.lo `test -f 'gstntppacket.c' || echo '$(srcdir)/'`gstntppacket.c + +libgstnet_@GST_API_VERSION@_la-gstnetutils.lo: gstnetutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstnet_@GST_API_VERSION@_la-gstnetutils.lo -MD -MP -MF $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetutils.Tpo -c -o libgstnet_@GST_API_VERSION@_la-gstnetutils.lo `test -f 'gstnetutils.c' || echo '$(srcdir)/'`gstnetutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetutils.Tpo $(DEPDIR)/libgstnet_@GST_API_VERSION@_la-gstnetutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnetutils.c' object='libgstnet_@GST_API_VERSION@_la-gstnetutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnet_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstnet_@GST_API_VERSION@_la-gstnetutils.lo `test -f 'gstnetutils.c' || echo '$(srcdir)/'`gstnetutils.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libgstnet_@GST_API_VERSION@_includeHEADERS: $(libgstnet_@GST_API_VERSION@_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libgstnet_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstnet_@GST_API_VERSION@_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)" || exit $$?; \ + done + +uninstall-libgstnet_@GST_API_VERSION@_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libgstnet_@GST_API_VERSION@_include_HEADERS)'; test -n "$(libgstnet_@GST_API_VERSION@_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) all-local +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libgstnet_@GST_API_VERSION@_includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-girDATA \ + install-libgstnet_@GST_API_VERSION@_includeHEADERS \ + install-typelibsDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libgstnet_@GST_API_VERSION@_includeHEADERS \ + uninstall-typelibsDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-girDATA install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libgstnet_@GST_API_VERSION@_includeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-typelibsDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES \ + uninstall-libgstnet_@GST_API_VERSION@_includeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +# try to prevent packaging errors +check-libexecdir-consistency: + @if test "${GST_PTP_HELPER_INSTALLED}" != "${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; then \ + echo "*** Inconsistent libexecdir! Please use ./configure --libexecdir=/foo/bar"; \ + echo "*** to set the libexecdir and not make libexecdir=/foo/bar or the like."; \ + echo "*** The same goes for prefix, libdir etc."; \ + echo "*** ${GST_PTP_HELPER_INSTALLED} != ${libexecdir}/gstreamer-$(GST_API_VERSION)/gst-ptp-helper"; \ + exit 1; \ + fi + +all-local: check-libexecdir-consistency + +%.c.gcov: .libs/libgstnet_@GST_API_VERSION@_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstnet_@GST_API_VERSION@_la_SOURCES:=.gcov) + +@HAVE_INTROSPECTION_TRUE@GstNet-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_API_VERSION@.la +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" GI_SCANNER_DISABLE_CACHE=yes\ +@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_DISABLE=yes \ +@HAVE_INTROSPECTION_TRUE@ CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" PKG_CONFIG="$(PKG_CONFIG)" DLLTOOL="$(DLLTOOL)" \ +@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstNet \ +@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Gst \ +@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=gst \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir)/libs \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \ +@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir)/libs \ +@HAVE_INTROSPECTION_TRUE@ $(gir_cincludes) \ +@HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \ +@HAVE_INTROSPECTION_TRUE@ --library=libgstnet-@GST_API_VERSION@.la \ +@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --include=Gio-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ +@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \ +@HAVE_INTROSPECTION_TRUE@ --pkg gio-2.0 \ +@HAVE_INTROSPECTION_TRUE@ --pkg-export="gstreamer-net-@GST_API_VERSION@" \ +@HAVE_INTROSPECTION_TRUE@ --add-init-section="$(INTROSPECTION_INIT)" \ +@HAVE_INTROSPECTION_TRUE@ --output $@ \ +@HAVE_INTROSPECTION_TRUE@ $(gir_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(gir_sources) + +@HAVE_INTROSPECTION_TRUE@%.typelib: %.gir $(INTROSPECTION_COMPILER) +@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libs/gst/net/gstnet.h b/libs/gst/net/gstnet.h new file mode 100644 index 0000000..2817380 --- /dev/null +++ b/libs/gst/net/gstnet.h @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) 2005 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NET_H__ +#define __GST_NET_H__ + +#include + +#include +#include +#include +#include + +#endif /* __GST_NET_H__ */ diff --git a/libs/gst/net/gstnetaddressmeta.c b/libs/gst/net/gstnetaddressmeta.c new file mode 100644 index 0000000..de98a1c --- /dev/null +++ b/libs/gst/net/gstnetaddressmeta.c @@ -0,0 +1,138 @@ +/* GStreamer + * Copyright (C) <2011> 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstnetaddressmeta + * @title: GstNetAddressMeta + * @short_description: Network address metadata + * + * #GstNetAddressMeta can be used to store a network address (a #GSocketAddress) + * in a #GstBuffer so that it network elements can track the to and from address + * of the buffer. + */ + +#include + +#include "gstnetaddressmeta.h" + +static gboolean +net_address_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GstNetAddressMeta *nmeta = (GstNetAddressMeta *) meta; + + nmeta->addr = NULL; + + return TRUE; +} + +static gboolean +net_address_meta_transform (GstBuffer * transbuf, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstNetAddressMeta *smeta, *dmeta; + smeta = (GstNetAddressMeta *) meta; + + /* we always copy no matter what transform */ + dmeta = gst_buffer_add_net_address_meta (transbuf, smeta->addr); + if (!dmeta) + return FALSE; + + return TRUE; +} + +static void +net_address_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstNetAddressMeta *nmeta = (GstNetAddressMeta *) meta; + + if (nmeta->addr) + g_object_unref (nmeta->addr); + nmeta->addr = NULL; +} + +GType +gst_net_address_meta_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { "origin", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstNetAddressMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +const GstMetaInfo * +gst_net_address_meta_get_info (void) +{ + static const GstMetaInfo *meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & meta_info)) { + const GstMetaInfo *mi = gst_meta_register (GST_NET_ADDRESS_META_API_TYPE, + "GstNetAddressMeta", + sizeof (GstNetAddressMeta), + net_address_meta_init, + net_address_meta_free, net_address_meta_transform); + g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi); + } + return meta_info; +} + +/** + * gst_buffer_add_net_address_meta: + * @buffer: a #GstBuffer + * @addr: a @GSocketAddress to connect to @buffer + * + * Attaches @addr as metadata in a #GstNetAddressMeta to @buffer. + * + * Returns: (transfer none): a #GstNetAddressMeta connected to @buffer + */ +GstNetAddressMeta * +gst_buffer_add_net_address_meta (GstBuffer * buffer, GSocketAddress * addr) +{ + GstNetAddressMeta *meta; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (G_IS_SOCKET_ADDRESS (addr), NULL); + + meta = + (GstNetAddressMeta *) gst_buffer_add_meta (buffer, + GST_NET_ADDRESS_META_INFO, NULL); + + meta->addr = g_object_ref (addr); + + return meta; +} + +/** + * gst_buffer_get_net_address_meta: + * @buffer: a #GstBuffer + * + * Find the #GstNetAddressMeta on @buffer. + * + * Returns: (transfer none): the #GstNetAddressMeta or %NULL when there + * is no such metadata on @buffer. + */ +GstNetAddressMeta * +gst_buffer_get_net_address_meta (GstBuffer * buffer) +{ + return (GstNetAddressMeta *) + gst_buffer_get_meta (buffer, GST_NET_ADDRESS_META_API_TYPE); +} diff --git a/libs/gst/net/gstnetaddressmeta.h b/libs/gst/net/gstnetaddressmeta.h new file mode 100644 index 0000000..e949b31 --- /dev/null +++ b/libs/gst/net/gstnetaddressmeta.h @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) <2011> 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_NET_ADDRESS_META_H__ +#define __GST_NET_ADDRESS_META_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstNetAddressMeta GstNetAddressMeta; + +/** + * GstNetAddressMeta: + * @meta: the parent type + * @addr: a #GSocketAddress stored as metadata + * + * Buffer metadata for network addresses. + */ +struct _GstNetAddressMeta { + GstMeta meta; + + GSocketAddress *addr; +}; + +GST_NET_API +GType gst_net_address_meta_api_get_type (void); +#define GST_NET_ADDRESS_META_API_TYPE (gst_net_address_meta_api_get_type()) + +/* implementation */ + +GST_NET_API +const GstMetaInfo *gst_net_address_meta_get_info (void); +#define GST_NET_ADDRESS_META_INFO (gst_net_address_meta_get_info()) + +GST_NET_API +GstNetAddressMeta * gst_buffer_add_net_address_meta (GstBuffer *buffer, + GSocketAddress *addr); +GST_NET_API +GstNetAddressMeta * gst_buffer_get_net_address_meta (GstBuffer *buffer); + +G_END_DECLS + +#endif /* __GST_NET_ADDRESS_META_H__ */ + diff --git a/libs/gst/net/gstnetclientclock.c b/libs/gst/net/gstnetclientclock.c new file mode 100644 index 0000000..102ba19 --- /dev/null +++ b/libs/gst/net/gstnetclientclock.c @@ -0,0 +1,1495 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * 2005 Andy Wingo + * Copyright (C) 2012 Collabora Ltd. + * Copyright (C) 2015 Sebastian Dröge + * + * gstnetclientclock.h: clock that synchronizes itself to a time provider over + * the network + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstnetclientclock + * @title: GstNetClientClock + * @short_description: Special clock that synchronizes to a remote time + * provider. + * @see_also: #GstClock, #GstNetTimeProvider, #GstPipeline + * + * #GstNetClientClock implements a custom #GstClock that synchronizes its time + * to a remote time provider such as #GstNetTimeProvider. #GstNtpClock + * implements a #GstClock that synchronizes its time to a remote NTPv4 server. + * + * A new clock is created with gst_net_client_clock_new() or + * gst_ntp_clock_new(), which takes the address and port of the remote time + * provider along with a name and an initial time. + * + * This clock will poll the time provider and will update its calibration + * parameters based on the local and remote observations. + * + * The "round-trip" property limits the maximum round trip packets can take. + * + * Various parameters of the clock can be configured with the parent #GstClock + * "timeout", "window-size" and "window-threshold" object properties. + * + * A #GstNetClientClock and #GstNtpClock is typically set on a #GstPipeline with + * gst_pipeline_use_clock(). + * + * If you set a #GstBus on the clock via the "bus" object property, it will + * send @GST_MESSAGE_ELEMENT messages with an attached #GstStructure containing + * statistics about clock accuracy and network traffic. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstnettimepacket.h" +#include "gstntppacket.h" +#include "gstnetclientclock.h" +#include "gstnetutils.h" + +#include + +#include + +GST_DEBUG_CATEGORY_STATIC (ncc_debug); +#define GST_CAT_DEFAULT (ncc_debug) + +typedef struct +{ + GstClock *clock; /* GstNetClientInternalClock */ + + GList *clocks; /* GstNetClientClocks */ + + GstClockID remove_id; +} ClockCache; + +G_LOCK_DEFINE_STATIC (clocks_lock); +static GList *clocks = NULL; + +#define GST_TYPE_NET_CLIENT_INTERNAL_CLOCK \ + (gst_net_client_internal_clock_get_type()) +#define GST_NET_CLIENT_INTERNAL_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK,GstNetClientInternalClock)) +#define GST_NET_CLIENT_INTERNAL_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK,GstNetClientInternalClockClass)) +#define GST_IS_NET_CLIENT_INTERNAL_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK)) +#define GST_IS_NET_CLIENT_INTERNAL_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_CLIENT_INTERNAL_CLOCK)) + +typedef struct _GstNetClientInternalClock GstNetClientInternalClock; +typedef struct _GstNetClientInternalClockClass GstNetClientInternalClockClass; + +G_GNUC_INTERNAL GType gst_net_client_internal_clock_get_type (void); + +#define DEFAULT_ADDRESS "127.0.0.1" +#define DEFAULT_PORT 5637 +#define DEFAULT_TIMEOUT GST_SECOND +#define DEFAULT_ROUNDTRIP_LIMIT GST_SECOND +/* Minimum timeout will be immediately (ie, as fast as one RTT), but no + * more often than 1/20th second (arbitrarily, to spread observations a little) */ +#define DEFAULT_MINIMUM_UPDATE_INTERVAL (GST_SECOND / 20) +#define DEFAULT_BASE_TIME 0 +#define DEFAULT_QOS_DSCP -1 + +/* Maximum number of clock updates we can skip before updating */ +#define MAX_SKIPPED_UPDATES 5 + +#define MEDIAN_PRE_FILTERING_WINDOW 9 + +enum +{ + PROP_0, + PROP_ADDRESS, + PROP_PORT, + PROP_ROUNDTRIP_LIMIT, + PROP_MINIMUM_UPDATE_INTERVAL, + PROP_BUS, + PROP_BASE_TIME, + PROP_INTERNAL_CLOCK, + PROP_IS_NTP, + PROP_QOS_DSCP +}; + +struct _GstNetClientInternalClock +{ + GstSystemClock clock; + + GThread *thread; + + GSocket *socket; + GSocketAddress *servaddr; + GCancellable *cancel; + gboolean made_cancel_fd; + + GstClockTime timeout_expiration; + GstClockTime roundtrip_limit; + GstClockTime rtt_avg; + GstClockTime minimum_update_interval; + GstClockTime last_remote_poll_interval; + guint skipped_updates; + GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW]; + gint last_rtts_missing; + + gchar *address; + gint port; + gboolean is_ntp; + gint qos_dscp; + + /* Protected by OBJECT_LOCK */ + GList *busses; +}; + +struct _GstNetClientInternalClockClass +{ + GstSystemClockClass parent_class; +}; + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (ncc_debug, "netclock", 0, "Network client clock"); +G_DEFINE_TYPE_WITH_CODE (GstNetClientInternalClock, + gst_net_client_internal_clock, GST_TYPE_SYSTEM_CLOCK, _do_init); + +static void gst_net_client_internal_clock_finalize (GObject * object); +static void gst_net_client_internal_clock_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_net_client_internal_clock_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_net_client_internal_clock_constructed (GObject * object); + +static gboolean gst_net_client_internal_clock_start (GstNetClientInternalClock * + self); +static void gst_net_client_internal_clock_stop (GstNetClientInternalClock * + self); + +static void +gst_net_client_internal_clock_class_init (GstNetClientInternalClockClass * + klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_net_client_internal_clock_finalize; + gobject_class->get_property = gst_net_client_internal_clock_get_property; + gobject_class->set_property = gst_net_client_internal_clock_set_property; + gobject_class->constructed = gst_net_client_internal_clock_constructed; + + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_string ("address", "address", + "The IP address of the machine providing a time server", + DEFAULT_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_int ("port", "port", + "The port on which the remote server is listening", 0, G_MAXUINT16, + DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_IS_NTP, + g_param_spec_boolean ("is-ntp", "Is NTP", + "The clock is using the NTPv4 protocol", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_net_client_internal_clock_init (GstNetClientInternalClock * self) +{ + GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC); + + self->port = DEFAULT_PORT; + self->address = g_strdup (DEFAULT_ADDRESS); + self->is_ntp = FALSE; + self->qos_dscp = DEFAULT_QOS_DSCP; + + gst_clock_set_timeout (GST_CLOCK (self), DEFAULT_TIMEOUT); + + self->thread = NULL; + + self->servaddr = NULL; + self->rtt_avg = GST_CLOCK_TIME_NONE; + self->roundtrip_limit = DEFAULT_ROUNDTRIP_LIMIT; + self->minimum_update_interval = DEFAULT_MINIMUM_UPDATE_INTERVAL; + self->last_remote_poll_interval = GST_CLOCK_TIME_NONE; + self->skipped_updates = 0; + self->last_rtts_missing = MEDIAN_PRE_FILTERING_WINDOW; +} + +static void +gst_net_client_internal_clock_finalize (GObject * object) +{ + GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object); + + if (self->thread) { + gst_net_client_internal_clock_stop (self); + } + + g_free (self->address); + self->address = NULL; + + if (self->servaddr != NULL) { + g_object_unref (self->servaddr); + self->servaddr = NULL; + } + + if (self->socket != NULL) { + if (!g_socket_close (self->socket, NULL)) + GST_ERROR_OBJECT (self, "Failed to close socket"); + g_object_unref (self->socket); + self->socket = NULL; + } + + g_warn_if_fail (self->busses == NULL); + + G_OBJECT_CLASS (gst_net_client_internal_clock_parent_class)->finalize + (object); +} + +static void +gst_net_client_internal_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object); + + switch (prop_id) { + case PROP_ADDRESS: + GST_OBJECT_LOCK (self); + g_free (self->address); + self->address = g_value_dup_string (value); + if (self->address == NULL) + self->address = g_strdup (DEFAULT_ADDRESS); + GST_OBJECT_UNLOCK (self); + break; + case PROP_PORT: + GST_OBJECT_LOCK (self); + self->port = g_value_get_int (value); + GST_OBJECT_UNLOCK (self); + break; + case PROP_IS_NTP: + GST_OBJECT_LOCK (self); + self->is_ntp = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_net_client_internal_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object); + + switch (prop_id) { + case PROP_ADDRESS: + GST_OBJECT_LOCK (self); + g_value_set_string (value, self->address); + GST_OBJECT_UNLOCK (self); + break; + case PROP_PORT: + g_value_set_int (value, self->port); + break; + case PROP_IS_NTP: + g_value_set_boolean (value, self->is_ntp); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_net_client_internal_clock_constructed (GObject * object) +{ + GstNetClientInternalClock *self = GST_NET_CLIENT_INTERNAL_CLOCK (object); + + G_OBJECT_CLASS (gst_net_client_internal_clock_parent_class)->constructed + (object); + + if (!gst_net_client_internal_clock_start (self)) { + g_warning ("failed to start clock '%s'", GST_OBJECT_NAME (self)); + } + + /* all systems go, cap'n */ +} + +static gint +compare_clock_time (const GstClockTime * a, const GstClockTime * b) +{ + if (*a < *b) + return -1; + else if (*a > *b) + return 1; + return 0; +} + +static void +gst_net_client_internal_clock_observe_times (GstNetClientInternalClock * self, + GstClockTime local_1, GstClockTime remote_1, GstClockTime remote_2, + GstClockTime local_2) +{ + GstClockTime current_timeout = 0; + GstClockTime local_avg, remote_avg; + gdouble r_squared; + GstClock *clock; + GstClockTime rtt, rtt_limit, min_update_interval; + /* Use for discont tracking */ + GstClockTime time_before = 0; + GstClockTime min_guess = 0; + GstClockTimeDiff time_discont = 0; + gboolean synched, now_synched; + GstClockTime internal_time, external_time, rate_num, rate_den; + GstClockTime orig_internal_time, orig_external_time, orig_rate_num, + orig_rate_den; + GstClockTime max_discont; + GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW]; + GstClockTime median; + gint i; + + GST_OBJECT_LOCK (self); + rtt_limit = self->roundtrip_limit; + + GST_LOG_OBJECT (self, + "local1 %" G_GUINT64_FORMAT " remote1 %" G_GUINT64_FORMAT " remote2 %" + G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT, local_1, remote_1, + remote_2, local_2); + + /* If the server told us a poll interval and it's bigger than the + * one configured via the property, use the server's */ + if (self->last_remote_poll_interval != GST_CLOCK_TIME_NONE && + self->last_remote_poll_interval > self->minimum_update_interval) + min_update_interval = self->last_remote_poll_interval; + else + min_update_interval = self->minimum_update_interval; + GST_OBJECT_UNLOCK (self); + + if (local_2 < local_1) { + GST_LOG_OBJECT (self, "Dropping observation: receive time %" GST_TIME_FORMAT + " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (local_1), + GST_TIME_ARGS (local_2)); + goto bogus_observation; + } + + if (remote_2 < remote_1) { + GST_LOG_OBJECT (self, + "Dropping observation: remote receive time %" GST_TIME_FORMAT + " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (remote_1), + GST_TIME_ARGS (remote_2)); + goto bogus_observation; + } + + /* The round trip time is (assuming symmetric path delays) + * delta = (local_2 - local_1) - (remote_2 - remote_1) + */ + + rtt = GST_CLOCK_DIFF (local_1, local_2) - GST_CLOCK_DIFF (remote_1, remote_2); + + if ((rtt_limit > 0) && (rtt > rtt_limit)) { + GST_LOG_OBJECT (self, + "Dropping observation: RTT %" GST_TIME_FORMAT " > limit %" + GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (rtt_limit)); + goto bogus_observation; + } + + for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++) + self->last_rtts[i - 1] = self->last_rtts[i]; + self->last_rtts[i - 1] = rtt; + + if (self->last_rtts_missing) { + self->last_rtts_missing--; + } else { + memcpy (&last_rtts, &self->last_rtts, sizeof (last_rtts)); + g_qsort_with_data (&last_rtts, + MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime), + (GCompareDataFunc) compare_clock_time, NULL); + + median = last_rtts[MEDIAN_PRE_FILTERING_WINDOW / 2]; + + /* FIXME: We might want to use something else here, like only allowing + * things in the interquartile range, or also filtering away delays that + * are too small compared to the median. This here worked well enough + * in tests so far. + */ + if (rtt > 2 * median) { + GST_LOG_OBJECT (self, + "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * median %" + GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (median)); + goto bogus_observation; + } + } + + /* Track an average round trip time, for a bit of smoothing */ + /* Always update before discarding a sample, so genuine changes in + * the network get picked up, eventually */ + if (self->rtt_avg == GST_CLOCK_TIME_NONE) + self->rtt_avg = rtt; + else if (rtt < self->rtt_avg) /* Shorter RTTs carry more weight than longer */ + self->rtt_avg = (3 * self->rtt_avg + rtt) / 4; + else + self->rtt_avg = (15 * self->rtt_avg + rtt) / 16; + + if (rtt > 2 * self->rtt_avg) { + GST_LOG_OBJECT (self, + "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * avg %" + GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (self->rtt_avg)); + goto bogus_observation; + } + + /* The difference between the local and remote clock (again assuming + * symmetric path delays): + * + * local_1 + delta / 2 - remote_1 = theta + * or + * local_2 - delta / 2 - remote_2 = theta + * + * which gives after some simple algebraic transformations: + * + * (remote_1 - local_1) + (remote_2 - local_2) + * theta = ------------------------------------------- + * 2 + * + * + * Thus remote time at local_avg is equal to: + * + * local_avg + theta = + * + * local_1 + local_2 (remote_1 - local_1) + (remote_2 - local_2) + * ----------------- + ------------------------------------------- + * 2 2 + * + * = + * + * remote_1 + remote_2 + * ------------------- = remote_avg + * 2 + * + * We use this for our clock estimation, i.e. local_avg at remote clock + * being the same as remote_avg. + */ + + local_avg = (local_2 + local_1) / 2; + remote_avg = (remote_2 + remote_1) / 2; + + GST_LOG_OBJECT (self, + "remoteavg %" G_GUINT64_FORMAT " localavg %" G_GUINT64_FORMAT, + remote_avg, local_avg); + + clock = GST_CLOCK_CAST (self); + + /* Store what the clock produced as 'now' before this update */ + gst_clock_get_calibration (GST_CLOCK_CAST (self), &orig_internal_time, + &orig_external_time, &orig_rate_num, &orig_rate_den); + internal_time = orig_internal_time; + external_time = orig_external_time; + rate_num = orig_rate_num; + rate_den = orig_rate_den; + + min_guess = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_1, + internal_time, external_time, rate_num, rate_den); + time_before = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2, + internal_time, external_time, rate_num, rate_den); + + /* Maximum discontinuity, when we're synched with the master. Could make this a property, + * but this value seems to work fine */ + max_discont = self->rtt_avg / 4; + + /* If the remote observation was within a max_discont window around our min/max estimates, we're synched */ + synched = + (GST_CLOCK_DIFF (remote_avg, min_guess) < (GstClockTimeDiff) (max_discont) + && GST_CLOCK_DIFF (time_before, + remote_avg) < (GstClockTimeDiff) (max_discont)); + + if (gst_clock_add_observation_unapplied (GST_CLOCK_CAST (self), + local_avg, remote_avg, &r_squared, &internal_time, &external_time, + &rate_num, &rate_den)) { + + /* Now compare the difference (discont) in the clock + * after this observation */ + time_discont = GST_CLOCK_DIFF (time_before, + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2, + internal_time, external_time, rate_num, rate_den)); + + /* If we were in sync with the remote clock, clamp the allowed + * discontinuity to within quarter of one RTT. In sync means our send/receive estimates + * of remote time correctly windowed the actual remote time observation */ + if (synched && ABS (time_discont) > max_discont) { + GstClockTimeDiff offset; + GST_DEBUG_OBJECT (clock, + "Too large a discont, clamping to 1/4 average RTT = %" + GST_TIME_FORMAT, GST_TIME_ARGS (max_discont)); + if (time_discont > 0) { /* Too large a forward step - add a -ve offset */ + offset = max_discont - time_discont; + if (-offset > external_time) + external_time = 0; + else + external_time += offset; + } else { /* Too large a backward step - add a +ve offset */ + offset = -(max_discont + time_discont); + external_time += offset; + } + + time_discont += offset; + } + + /* Check if the new clock params would have made our observation within range */ + now_synched = + (GST_CLOCK_DIFF (remote_avg, + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), + local_1, internal_time, external_time, rate_num, + rate_den)) < (GstClockTimeDiff) (max_discont)) + && + (GST_CLOCK_DIFF (gst_clock_adjust_with_calibration + (GST_CLOCK_CAST (self), local_2, internal_time, external_time, + rate_num, rate_den), + remote_avg) < (GstClockTimeDiff) (max_discont)); + + /* Only update the clock if we had synch or just gained it */ + if (synched || now_synched || self->skipped_updates > MAX_SKIPPED_UPDATES) { + gst_clock_set_calibration (GST_CLOCK_CAST (self), internal_time, + external_time, rate_num, rate_den); + /* ghetto formula - shorter timeout for bad correlations */ + current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND; + current_timeout = + MIN (current_timeout, gst_clock_get_timeout (GST_CLOCK_CAST (self))); + self->skipped_updates = 0; + + /* FIXME: When do we consider the clock absolutely not synced anymore? */ + gst_clock_set_synced (GST_CLOCK (self), TRUE); + } else { + /* Restore original calibration vars for the report, we're not changing the clock */ + internal_time = orig_internal_time; + external_time = orig_external_time; + rate_num = orig_rate_num; + rate_den = orig_rate_den; + time_discont = 0; + self->skipped_updates++; + } + } + + /* Limit the polling to at most one per minimum_update_interval */ + if (rtt < min_update_interval) + current_timeout = MAX (min_update_interval - rtt, current_timeout); + + GST_OBJECT_LOCK (self); + if (self->busses) { + GstStructure *s; + GstMessage *msg; + GList *l; + + /* Output a stats message, whether we updated the clock or not */ + s = gst_structure_new ("gst-netclock-statistics", + "synchronised", G_TYPE_BOOLEAN, synched, + "rtt", G_TYPE_UINT64, rtt, + "rtt-average", G_TYPE_UINT64, self->rtt_avg, + "local", G_TYPE_UINT64, local_avg, + "remote", G_TYPE_UINT64, remote_avg, + "discontinuity", G_TYPE_INT64, time_discont, + "remote-min-estimate", G_TYPE_UINT64, min_guess, + "remote-max-estimate", G_TYPE_UINT64, time_before, + "remote-min-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote_avg, + min_guess), "remote-max-error", G_TYPE_INT64, + GST_CLOCK_DIFF (remote_avg, time_before), "request-send", G_TYPE_UINT64, + local_1, "request-receive", G_TYPE_UINT64, local_2, "r-squared", + G_TYPE_DOUBLE, r_squared, "timeout", G_TYPE_UINT64, current_timeout, + "internal-time", G_TYPE_UINT64, internal_time, "external-time", + G_TYPE_UINT64, external_time, "rate-num", G_TYPE_UINT64, rate_num, + "rate-den", G_TYPE_UINT64, rate_den, "rate", G_TYPE_DOUBLE, + (gdouble) (rate_num) / rate_den, "local-clock-offset", G_TYPE_INT64, + GST_CLOCK_DIFF (internal_time, external_time), NULL); + msg = gst_message_new_element (GST_OBJECT (self), s); + + for (l = self->busses; l; l = l->next) + gst_bus_post (l->data, gst_message_ref (msg)); + gst_message_unref (msg); + } + GST_OBJECT_UNLOCK (self); + + GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout)); + self->timeout_expiration = gst_util_get_timestamp () + current_timeout; + + return; + +bogus_observation: + /* Schedule a new packet again soon */ + self->timeout_expiration = gst_util_get_timestamp () + (GST_SECOND / 4); + return; +} + +static gpointer +gst_net_client_internal_clock_thread (gpointer data) +{ + GstNetClientInternalClock *self = data; + GSocket *socket = self->socket; + GError *err = NULL; + gint cur_qos_dscp = DEFAULT_QOS_DSCP; + + GST_INFO_OBJECT (self, "net client clock thread running, socket=%p", socket); + + g_socket_set_blocking (socket, TRUE); + g_socket_set_timeout (socket, 0); + + while (!g_cancellable_is_cancelled (self->cancel)) { + GstClockTime expiration_time = self->timeout_expiration; + GstClockTime now = gst_util_get_timestamp (); + gint64 socket_timeout; + + if (now >= expiration_time || (expiration_time - now) <= GST_MSECOND) { + socket_timeout = 0; + } else { + socket_timeout = (expiration_time - now) / GST_USECOND; + } + + GST_TRACE_OBJECT (self, "timeout: %" G_GINT64_FORMAT "us", socket_timeout); + + if (!g_socket_condition_timed_wait (socket, G_IO_IN, socket_timeout, + self->cancel, &err)) { + /* cancelled, timeout or error */ + if (err->code == G_IO_ERROR_CANCELLED) { + GST_INFO_OBJECT (self, "cancelled"); + g_clear_error (&err); + break; + } else if (err->code == G_IO_ERROR_TIMED_OUT) { + gint new_qos_dscp; + + /* timed out, let's send another packet */ + GST_DEBUG_OBJECT (self, "timed out"); + + /* before next sending check if need to change QoS */ + new_qos_dscp = self->qos_dscp; + if (cur_qos_dscp != new_qos_dscp && + gst_net_utils_set_socket_dscp (socket, new_qos_dscp)) { + GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp); + cur_qos_dscp = new_qos_dscp; + } + + if (self->is_ntp) { + GstNtpPacket *packet; + + packet = gst_ntp_packet_new (NULL, NULL); + + packet->transmit_time = + gst_clock_get_internal_time (GST_CLOCK_CAST (self)); + + GST_DEBUG_OBJECT (self, + "sending packet, local time = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->transmit_time)); + + gst_ntp_packet_send (packet, self->socket, self->servaddr, NULL); + + g_free (packet); + } else { + GstNetTimePacket *packet; + + packet = gst_net_time_packet_new (NULL); + + packet->local_time = + gst_clock_get_internal_time (GST_CLOCK_CAST (self)); + + GST_DEBUG_OBJECT (self, + "sending packet, local time = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->local_time)); + + gst_net_time_packet_send (packet, self->socket, self->servaddr, NULL); + + g_free (packet); + } + + /* reset timeout (but are expecting a response sooner anyway) */ + self->timeout_expiration = + gst_util_get_timestamp () + + gst_clock_get_timeout (GST_CLOCK_CAST (self)); + } else { + GST_DEBUG_OBJECT (self, "socket error: %s", err->message); + g_usleep (G_USEC_PER_SEC / 10); /* throttle */ + } + g_clear_error (&err); + } else { + GstClockTime new_local; + + /* got packet */ + + new_local = gst_clock_get_internal_time (GST_CLOCK_CAST (self)); + + if (self->is_ntp) { + GstNtpPacket *packet; + + packet = gst_ntp_packet_receive (socket, NULL, &err); + + if (packet != NULL) { + GST_LOG_OBJECT (self, "got packet back"); + GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->origin_time)); + GST_LOG_OBJECT (self, "remote_1 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->receive_time)); + GST_LOG_OBJECT (self, "remote_2 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->transmit_time)); + GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (new_local)); + GST_LOG_OBJECT (self, "poll_interval = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->poll_interval)); + + /* Remember the last poll interval we ever got from the server */ + if (packet->poll_interval != GST_CLOCK_TIME_NONE) + self->last_remote_poll_interval = packet->poll_interval; + + /* observe_times will reset the timeout */ + gst_net_client_internal_clock_observe_times (self, + packet->origin_time, packet->receive_time, packet->transmit_time, + new_local); + + g_free (packet); + } else if (err != NULL) { + if (g_error_matches (err, GST_NTP_ERROR, GST_NTP_ERROR_WRONG_VERSION) + || g_error_matches (err, GST_NTP_ERROR, GST_NTP_ERROR_KOD_DENY)) { + GST_ERROR_OBJECT (self, "fatal receive error: %s", err->message); + g_clear_error (&err); + break; + } else if (g_error_matches (err, GST_NTP_ERROR, + GST_NTP_ERROR_KOD_RATE)) { + GST_WARNING_OBJECT (self, "need to limit rate"); + + /* If the server did not tell us a poll interval before, double + * our minimum poll interval. Otherwise we assume that the server + * already told us something sensible and that this error here + * was just a spurious error */ + if (self->last_remote_poll_interval == GST_CLOCK_TIME_NONE) + self->minimum_update_interval *= 2; + + /* And wait a bit before we send the next packet instead of + * sending it immediately */ + self->timeout_expiration = + gst_util_get_timestamp () + + gst_clock_get_timeout (GST_CLOCK_CAST (self)); + } else { + GST_WARNING_OBJECT (self, "receive error: %s", err->message); + } + g_clear_error (&err); + } + } else { + GstNetTimePacket *packet; + + packet = gst_net_time_packet_receive (socket, NULL, &err); + + if (packet != NULL) { + GST_LOG_OBJECT (self, "got packet back"); + GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->local_time)); + GST_LOG_OBJECT (self, "remote = %" GST_TIME_FORMAT, + GST_TIME_ARGS (packet->remote_time)); + GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT, + GST_TIME_ARGS (new_local)); + + /* observe_times will reset the timeout */ + gst_net_client_internal_clock_observe_times (self, packet->local_time, + packet->remote_time, packet->remote_time, new_local); + + g_free (packet); + } else if (err != NULL) { + GST_WARNING_OBJECT (self, "receive error: %s", err->message); + g_clear_error (&err); + } + } + } + } + GST_INFO_OBJECT (self, "shutting down net client clock thread"); + return NULL; +} + +static gboolean +gst_net_client_internal_clock_start (GstNetClientInternalClock * self) +{ + GSocketAddress *servaddr; + GSocketAddress *myaddr; + GSocketAddress *anyaddr; + GInetAddress *inetaddr; + GSocket *socket; + GError *error = NULL; + GSocketFamily family; + GPollFD dummy_pollfd; + GResolver *resolver = NULL; + GError *err = NULL; + + g_return_val_if_fail (self->address != NULL, FALSE); + g_return_val_if_fail (self->servaddr == NULL, FALSE); + + /* create target address */ + inetaddr = g_inet_address_new_from_string (self->address); + if (inetaddr == NULL) { + GList *results; + + resolver = g_resolver_get_default (); + + results = g_resolver_lookup_by_name (resolver, self->address, NULL, &err); + if (!results) + goto failed_to_resolve; + + inetaddr = G_INET_ADDRESS (g_object_ref (results->data)); + g_resolver_free_addresses (results); + g_object_unref (resolver); + } + + family = g_inet_address_get_family (inetaddr); + + servaddr = g_inet_socket_address_new (inetaddr, self->port); + g_object_unref (inetaddr); + + g_assert (servaddr != NULL); + + GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address, + self->port); + + socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, &error); + + if (socket == NULL) + goto no_socket; + + GST_DEBUG_OBJECT (self, "binding socket"); + inetaddr = g_inet_address_new_any (family); + anyaddr = g_inet_socket_address_new (inetaddr, 0); + g_socket_bind (socket, anyaddr, TRUE, &error); + g_object_unref (anyaddr); + g_object_unref (inetaddr); + + if (error != NULL) + goto bind_error; + + /* check address we're bound to, mostly for debugging purposes */ + myaddr = g_socket_get_local_address (socket, &error); + + if (myaddr == NULL) + goto getsockname_error; + + GST_DEBUG_OBJECT (self, "socket opened on UDP port %d", + g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr))); + + g_object_unref (myaddr); + + self->cancel = g_cancellable_new (); + self->made_cancel_fd = + g_cancellable_make_pollfd (self->cancel, &dummy_pollfd); + + self->socket = socket; + self->servaddr = G_SOCKET_ADDRESS (servaddr); + + self->thread = g_thread_try_new ("GstNetClientInternalClock", + gst_net_client_internal_clock_thread, self, &error); + + if (error != NULL) + goto no_thread; + + return TRUE; + + /* ERRORS */ +no_socket: + { + GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message); + g_error_free (error); + return FALSE; + } +bind_error: + { + GST_ERROR_OBJECT (self, "bind failed: %s", error->message); + g_error_free (error); + g_object_unref (socket); + return FALSE; + } +getsockname_error: + { + GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message); + g_error_free (error); + g_object_unref (socket); + return FALSE; + } +failed_to_resolve: + { + GST_ERROR_OBJECT (self, "resolving '%s' failed: %s", + self->address, err->message); + g_clear_error (&err); + g_object_unref (resolver); + return FALSE; + } +no_thread: + { + GST_ERROR_OBJECT (self, "could not create thread: %s", error->message); + g_object_unref (self->servaddr); + self->servaddr = NULL; + g_object_unref (self->socket); + self->socket = NULL; + g_error_free (error); + return FALSE; + } +} + +static void +gst_net_client_internal_clock_stop (GstNetClientInternalClock * self) +{ + if (self->thread == NULL) + return; + + GST_INFO_OBJECT (self, "stopping..."); + g_cancellable_cancel (self->cancel); + + g_thread_join (self->thread); + self->thread = NULL; + + if (self->made_cancel_fd) + g_cancellable_release_fd (self->cancel); + + g_object_unref (self->cancel); + self->cancel = NULL; + + g_object_unref (self->servaddr); + self->servaddr = NULL; + + g_object_unref (self->socket); + self->socket = NULL; + + GST_INFO_OBJECT (self, "stopped"); +} + +#define GST_NET_CLIENT_CLOCK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_NET_CLIENT_CLOCK, GstNetClientClockPrivate)) + +struct _GstNetClientClockPrivate +{ + GstClock *internal_clock; + + GstClockTime roundtrip_limit; + GstClockTime minimum_update_interval; + + GstClockTime base_time, internal_base_time; + + gchar *address; + gint port; + gint qos_dscp; + + GstBus *bus; + + gboolean is_ntp; + + gulong synced_id; +}; + +G_DEFINE_TYPE (GstNetClientClock, gst_net_client_clock, GST_TYPE_SYSTEM_CLOCK); + +static void gst_net_client_clock_finalize (GObject * object); +static void gst_net_client_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_net_client_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_net_client_clock_constructed (GObject * object); + +static GstClockTime gst_net_client_clock_get_internal_time (GstClock * clock); + +static void +gst_net_client_clock_class_init (GstNetClientClockClass * klass) +{ + GObjectClass *gobject_class; + GstClockClass *clock_class; + + gobject_class = G_OBJECT_CLASS (klass); + clock_class = GST_CLOCK_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstNetClientClockPrivate)); + + gobject_class->finalize = gst_net_client_clock_finalize; + gobject_class->get_property = gst_net_client_clock_get_property; + gobject_class->set_property = gst_net_client_clock_set_property; + gobject_class->constructed = gst_net_client_clock_constructed; + + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_string ("address", "address", + "The IP address of the machine providing a time server", + DEFAULT_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_int ("port", "port", + "The port on which the remote server is listening", 0, G_MAXUINT16, + DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BUS, + g_param_spec_object ("bus", "bus", + "A GstBus on which to send clock status information", GST_TYPE_BUS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstNetClientInternalClock::round-trip-limit: + * + * Maximum allowed round-trip for packets. If this property is set to a nonzero + * value, all packets with a round-trip interval larger than this limit will be + * ignored. This is useful for networks with severe and fluctuating transport + * delays. Filtering out these packets increases stability of the synchronization. + * On the other hand, the lower the limit, the higher the amount of filtered + * packets. Empirical tests are typically necessary to estimate a good value + * for the limit. + * If the property is set to zero, the limit is disabled. + * + * Since: 1.4 + */ + g_object_class_install_property (gobject_class, PROP_ROUNDTRIP_LIMIT, + g_param_spec_uint64 ("round-trip-limit", "round-trip limit", + "Maximum tolerable round-trip interval for packets, in nanoseconds " + "(0 = no limit)", 0, G_MAXUINT64, DEFAULT_ROUNDTRIP_LIMIT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MINIMUM_UPDATE_INTERVAL, + g_param_spec_uint64 ("minimum-update-interval", "minimum update interval", + "Minimum polling interval for packets, in nanoseconds" + "(0 = no limit)", 0, G_MAXUINT64, DEFAULT_MINIMUM_UPDATE_INTERVAL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BASE_TIME, + g_param_spec_uint64 ("base-time", "Base Time", + "Initial time that is reported before synchronization", 0, + G_MAXUINT64, DEFAULT_BASE_TIME, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_INTERNAL_CLOCK, + g_param_spec_object ("internal-clock", "Internal Clock", + "Internal clock that directly slaved to the remote clock", + GST_TYPE_CLOCK, G_PARAM_READABLE | 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)); + + clock_class->get_internal_time = gst_net_client_clock_get_internal_time; +} + +static void +gst_net_client_clock_init (GstNetClientClock * self) +{ + GstNetClientClockPrivate *priv; + GstClock *clock; + + self->priv = priv = GST_NET_CLIENT_CLOCK_GET_PRIVATE (self); + + GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_CAN_SET_MASTER); + GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC); + + priv->port = DEFAULT_PORT; + priv->address = g_strdup (DEFAULT_ADDRESS); + priv->qos_dscp = DEFAULT_QOS_DSCP; + + priv->roundtrip_limit = DEFAULT_ROUNDTRIP_LIMIT; + priv->minimum_update_interval = DEFAULT_MINIMUM_UPDATE_INTERVAL; + + clock = gst_system_clock_obtain (); + priv->base_time = DEFAULT_BASE_TIME; + priv->internal_base_time = gst_clock_get_time (clock); + gst_object_unref (clock); +} + +/* Must be called with clocks_lock */ +static void +update_clock_cache (ClockCache * cache) +{ + GstClockTime roundtrip_limit = 0, minimum_update_interval = 0; + GList *l, *busses = NULL; + gint qos_dscp = DEFAULT_QOS_DSCP; + + GST_OBJECT_LOCK (cache->clock); + g_list_free_full (GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->busses, + (GDestroyNotify) gst_object_unref); + + for (l = cache->clocks; l; l = l->next) { + GstNetClientClock *clock = l->data; + + if (clock->priv->bus) + busses = g_list_prepend (busses, gst_object_ref (clock->priv->bus)); + + if (roundtrip_limit == 0) + roundtrip_limit = clock->priv->roundtrip_limit; + else + roundtrip_limit = MAX (roundtrip_limit, clock->priv->roundtrip_limit); + + if (minimum_update_interval == 0) + minimum_update_interval = clock->priv->minimum_update_interval; + else + minimum_update_interval = + MIN (minimum_update_interval, clock->priv->minimum_update_interval); + + qos_dscp = MAX (qos_dscp, clock->priv->qos_dscp); + } + GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->busses = busses; + GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->roundtrip_limit = + roundtrip_limit; + GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->minimum_update_interval = + minimum_update_interval; + GST_NET_CLIENT_INTERNAL_CLOCK (cache->clock)->qos_dscp = qos_dscp; + + GST_OBJECT_UNLOCK (cache->clock); +} + +static gboolean +remove_clock_cache (GstClock * clock, GstClockTime time, GstClockID id, + gpointer user_data) +{ + ClockCache *cache = user_data; + + G_LOCK (clocks_lock); + if (!cache->clocks) { + gst_clock_id_unref (cache->remove_id); + gst_object_unref (cache->clock); + clocks = g_list_remove (clocks, cache); + g_free (cache); + } + G_UNLOCK (clocks_lock); + + return TRUE; +} + +static void +gst_net_client_clock_finalize (GObject * object) +{ + GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); + GList *l; + + if (self->priv->synced_id) + g_signal_handler_disconnect (self->priv->internal_clock, + self->priv->synced_id); + self->priv->synced_id = 0; + + G_LOCK (clocks_lock); + for (l = clocks; l; l = l->next) { + ClockCache *cache = l->data; + + if (cache->clock == self->priv->internal_clock) { + cache->clocks = g_list_remove (cache->clocks, self); + + if (cache->clocks) { + update_clock_cache (cache); + } else { + GstClock *sysclock = gst_system_clock_obtain (); + GstClockTime time = gst_clock_get_time (sysclock) + 60 * GST_SECOND; + + cache->remove_id = gst_clock_new_single_shot_id (sysclock, time); + gst_clock_id_wait_async (cache->remove_id, remove_clock_cache, cache, + NULL); + gst_object_unref (sysclock); + } + break; + } + } + G_UNLOCK (clocks_lock); + + g_free (self->priv->address); + self->priv->address = NULL; + + if (self->priv->bus != NULL) { + gst_object_unref (self->priv->bus); + self->priv->bus = NULL; + } + + G_OBJECT_CLASS (gst_net_client_clock_parent_class)->finalize (object); +} + +static void +gst_net_client_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); + gboolean update = FALSE; + + switch (prop_id) { + case PROP_ADDRESS: + GST_OBJECT_LOCK (self); + g_free (self->priv->address); + self->priv->address = g_value_dup_string (value); + if (self->priv->address == NULL) + self->priv->address = g_strdup (DEFAULT_ADDRESS); + GST_OBJECT_UNLOCK (self); + break; + case PROP_PORT: + GST_OBJECT_LOCK (self); + self->priv->port = g_value_get_int (value); + GST_OBJECT_UNLOCK (self); + break; + case PROP_ROUNDTRIP_LIMIT: + GST_OBJECT_LOCK (self); + self->priv->roundtrip_limit = g_value_get_uint64 (value); + GST_OBJECT_UNLOCK (self); + update = TRUE; + break; + case PROP_MINIMUM_UPDATE_INTERVAL: + GST_OBJECT_LOCK (self); + self->priv->minimum_update_interval = g_value_get_uint64 (value); + GST_OBJECT_UNLOCK (self); + update = TRUE; + break; + case PROP_BUS: + GST_OBJECT_LOCK (self); + if (self->priv->bus) + gst_object_unref (self->priv->bus); + self->priv->bus = g_value_dup_object (value); + GST_OBJECT_UNLOCK (self); + update = TRUE; + break; + case PROP_BASE_TIME:{ + GstClock *clock; + + self->priv->base_time = g_value_get_uint64 (value); + clock = gst_system_clock_obtain (); + self->priv->internal_base_time = gst_clock_get_time (clock); + gst_object_unref (clock); + break; + } + case PROP_QOS_DSCP: + GST_OBJECT_LOCK (self); + self->priv->qos_dscp = g_value_get_int (value); + GST_OBJECT_UNLOCK (self); + update = TRUE; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + if (update && self->priv->internal_clock) { + GList *l; + + G_LOCK (clocks_lock); + for (l = clocks; l; l = l->next) { + ClockCache *cache = l->data; + + if (cache->clock == self->priv->internal_clock) { + update_clock_cache (cache); + } + } + G_UNLOCK (clocks_lock); + } +} + +static void +gst_net_client_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); + + switch (prop_id) { + case PROP_ADDRESS: + GST_OBJECT_LOCK (self); + g_value_set_string (value, self->priv->address); + GST_OBJECT_UNLOCK (self); + break; + case PROP_PORT: + g_value_set_int (value, self->priv->port); + break; + case PROP_ROUNDTRIP_LIMIT: + GST_OBJECT_LOCK (self); + g_value_set_uint64 (value, self->priv->roundtrip_limit); + GST_OBJECT_UNLOCK (self); + break; + case PROP_MINIMUM_UPDATE_INTERVAL: + GST_OBJECT_LOCK (self); + g_value_set_uint64 (value, self->priv->minimum_update_interval); + GST_OBJECT_UNLOCK (self); + break; + case PROP_BUS: + GST_OBJECT_LOCK (self); + g_value_set_object (value, self->priv->bus); + GST_OBJECT_UNLOCK (self); + break; + case PROP_BASE_TIME: + g_value_set_uint64 (value, self->priv->base_time); + break; + case PROP_INTERNAL_CLOCK: + g_value_set_object (value, self->priv->internal_clock); + break; + case PROP_QOS_DSCP: + GST_OBJECT_LOCK (self); + g_value_set_int (value, self->priv->qos_dscp); + GST_OBJECT_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_net_client_clock_synced_cb (GstClock * internal_clock, gboolean synced, + GstClock * self) +{ + gst_clock_set_synced (self, synced); +} + +static void +gst_net_client_clock_constructed (GObject * object) +{ + GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); + GstClock *internal_clock; + GList *l; + ClockCache *cache = NULL; + + G_OBJECT_CLASS (gst_net_client_clock_parent_class)->constructed (object); + + G_LOCK (clocks_lock); + for (l = clocks; l; l = l->next) { + ClockCache *tmp = l->data; + GstNetClientInternalClock *internal_clock = + GST_NET_CLIENT_INTERNAL_CLOCK (tmp->clock); + + if (strcmp (internal_clock->address, self->priv->address) == 0 && + internal_clock->port == self->priv->port) { + cache = tmp; + + if (cache->remove_id) { + gst_clock_id_unschedule (cache->remove_id); + cache->remove_id = NULL; + } + break; + } + } + + if (!cache) { + cache = g_new0 (ClockCache, 1); + + cache->clock = + g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, "address", + self->priv->address, "port", self->priv->port, "is-ntp", + self->priv->is_ntp, NULL); + gst_object_ref_sink (cache->clock); + clocks = g_list_prepend (clocks, cache); + + /* Not actually leaked but is cached for a while before being disposed, + * see gst_net_client_clock_finalize, so pretend it is to not confuse + * tests. */ + GST_OBJECT_FLAG_SET (cache->clock, GST_OBJECT_FLAG_MAY_BE_LEAKED); + } + + cache->clocks = g_list_prepend (cache->clocks, self); + + GST_OBJECT_LOCK (cache->clock); + if (gst_clock_is_synced (cache->clock)) + gst_clock_set_synced (GST_CLOCK (self), TRUE); + self->priv->synced_id = + g_signal_connect (cache->clock, "synced", + G_CALLBACK (gst_net_client_clock_synced_cb), self); + GST_OBJECT_UNLOCK (cache->clock); + + G_UNLOCK (clocks_lock); + + self->priv->internal_clock = internal_clock = cache->clock; + + /* all systems go, cap'n */ +} + +static GstClockTime +gst_net_client_clock_get_internal_time (GstClock * clock) +{ + GstNetClientClock *self = GST_NET_CLIENT_CLOCK (clock); + + if (!gst_clock_is_synced (self->priv->internal_clock)) { + GstClockTime now = gst_clock_get_internal_time (self->priv->internal_clock); + return gst_clock_adjust_with_calibration (self->priv->internal_clock, now, + self->priv->internal_base_time, self->priv->base_time, 1, 1); + } + + return gst_clock_get_time (self->priv->internal_clock); +} + +/** + * gst_net_client_clock_new: + * @name: a name for the clock + * @remote_address: the address or hostname of the remote clock provider + * @remote_port: the port of the remote clock provider + * @base_time: initial time of the clock + * + * Create a new #GstNetClientInternalClock that will report the time + * provided by the #GstNetTimeProvider on @remote_address and + * @remote_port. + * + * Returns: (transfer full): a new #GstClock that receives a time from the remote + * clock. + */ +GstClock * +gst_net_client_clock_new (const gchar * name, const gchar * remote_address, + gint remote_port, GstClockTime base_time) +{ + GstClock *ret; + + g_return_val_if_fail (remote_address != NULL, NULL); + g_return_val_if_fail (remote_port > 0, NULL); + g_return_val_if_fail (remote_port <= G_MAXUINT16, NULL); + g_return_val_if_fail (base_time != GST_CLOCK_TIME_NONE, NULL); + + ret = + g_object_new (GST_TYPE_NET_CLIENT_CLOCK, "name", name, "address", + remote_address, "port", remote_port, "base-time", base_time, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (ret); + + return ret; +} + +G_DEFINE_TYPE (GstNtpClock, gst_ntp_clock, GST_TYPE_NET_CLIENT_CLOCK); + +static void +gst_ntp_clock_class_init (GstNtpClockClass * klass) +{ +} + +static void +gst_ntp_clock_init (GstNtpClock * self) +{ + GST_NET_CLIENT_CLOCK (self)->priv->is_ntp = TRUE; +} + +/** + * gst_ntp_clock_new: + * @name: a name for the clock + * @remote_address: the address or hostname of the remote clock provider + * @remote_port: the port of the remote clock provider + * @base_time: initial time of the clock + * + * Create a new #GstNtpClock that will report the time provided by + * the NTPv4 server on @remote_address and @remote_port. + * + * Returns: (transfer full): a new #GstClock that receives a time from the remote + * clock. + * + * Since: 1.6 + */ +GstClock * +gst_ntp_clock_new (const gchar * name, const gchar * remote_address, + gint remote_port, GstClockTime base_time) +{ + GstClock *ret; + + g_return_val_if_fail (remote_address != NULL, NULL); + g_return_val_if_fail (remote_port > 0, NULL); + g_return_val_if_fail (remote_port <= G_MAXUINT16, NULL); + g_return_val_if_fail (base_time != GST_CLOCK_TIME_NONE, NULL); + + ret = + g_object_new (GST_TYPE_NTP_CLOCK, "name", name, "address", remote_address, + "port", remote_port, "base-time", base_time, NULL); + + gst_object_ref_sink (ret); + + return ret; +} diff --git a/libs/gst/net/gstnetclientclock.h b/libs/gst/net/gstnetclientclock.h new file mode 100644 index 0000000..b741e6b --- /dev/null +++ b/libs/gst/net/gstnetclientclock.h @@ -0,0 +1,110 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * 2005 Andy Wingo + * Copyright (C) 2012 Collabora Ltd. + * + * gstnetclientclock.h: clock that synchronizes itself to a time provider over + * the network + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NET_CLIENT_CLOCK_H__ +#define __GST_NET_CLIENT_CLOCK_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_NET_CLIENT_CLOCK \ + (gst_net_client_clock_get_type()) +#define GST_NET_CLIENT_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_CLIENT_CLOCK,GstNetClientClock)) +#define GST_NET_CLIENT_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_CLIENT_CLOCK,GstNetClientClockClass)) +#define GST_IS_NET_CLIENT_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_CLIENT_CLOCK)) +#define GST_IS_NET_CLIENT_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_CLIENT_CLOCK)) + +typedef struct _GstNetClientClock GstNetClientClock; +typedef struct _GstNetClientClockClass GstNetClientClockClass; +typedef struct _GstNetClientClockPrivate GstNetClientClockPrivate; + +/** + * GstNetClientClock: + * + * Opaque #GstNetClientClock structure. + */ +struct _GstNetClientClock { + GstSystemClock clock; + + /*< private >*/ + GstNetClientClockPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstNetClientClockClass { + GstSystemClockClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_NET_API +GType gst_net_client_clock_get_type (void); + +GST_NET_API +GstClock* gst_net_client_clock_new (const gchar *name, const gchar *remote_address, + gint remote_port, GstClockTime base_time); + +#define GST_TYPE_NTP_CLOCK \ + (gst_ntp_clock_get_type()) +#define GST_NTP_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NTP_CLOCK,GstNtpClock)) +#define GST_NTP_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NTP_CLOCK,GstNtpClockClass)) +#define GST_IS_NTP_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NTP_CLOCK)) +#define GST_IS_NTP_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NTP_CLOCK)) + +typedef struct _GstNetClientClock GstNtpClock; +typedef struct _GstNetClientClockClass GstNtpClockClass; + +GST_NET_API +GType gst_ntp_clock_get_type (void); + +GST_NET_API +GstClock* gst_ntp_clock_new (const gchar *name, const gchar *remote_address, + gint remote_port, GstClockTime base_time); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetClientClock, gst_object_unref) +#endif + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNtpClock, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_NET_CLIENT_CLOCK_H__ */ diff --git a/libs/gst/net/gstnetcontrolmessagemeta.c b/libs/gst/net/gstnetcontrolmessagemeta.c new file mode 100644 index 0000000..d6cc525 --- /dev/null +++ b/libs/gst/net/gstnetcontrolmessagemeta.c @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) <2014> William Manley + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstnetcontrolmessagemeta + * @title: GstNetControlMessageMeta + * @short_description: Network Control Message Meta + * + * #GstNetControlMessageMeta can be used to store control messages (ancillary + * data) which was received with or is to be sent alongside the buffer data. + * When used with socket sinks and sources which understand this meta it allows + * sending and receiving ancillary data such as unix credentials (See + * #GUnixCredentialsMessage) and Unix file descriptions (See #GUnixFDMessage). + */ + +#include + +#include "gstnetcontrolmessagemeta.h" + +static gboolean +net_control_message_meta_init (GstMeta * meta, gpointer params, + GstBuffer * buffer) +{ + GstNetControlMessageMeta *nmeta = (GstNetControlMessageMeta *) meta; + + nmeta->message = NULL; + + return TRUE; +} + +static gboolean +net_control_message_meta_transform (GstBuffer * transbuf, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstNetControlMessageMeta *smeta, *dmeta; + smeta = (GstNetControlMessageMeta *) meta; + + /* we always copy no matter what transform */ + dmeta = gst_buffer_add_net_control_message_meta (transbuf, smeta->message); + if (!dmeta) + return FALSE; + + return TRUE; +} + +static void +net_control_message_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstNetControlMessageMeta *nmeta = (GstNetControlMessageMeta *) meta; + + if (nmeta->message) + g_object_unref (nmeta->message); + nmeta->message = NULL; +} + +GType +gst_net_control_message_meta_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { "origin", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = + gst_meta_api_type_register ("GstNetControlMessageMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +const GstMetaInfo * +gst_net_control_message_meta_get_info (void) +{ + static const GstMetaInfo *meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & meta_info)) { + const GstMetaInfo *mi = + gst_meta_register (GST_NET_CONTROL_MESSAGE_META_API_TYPE, + "GstNetControlMessageMeta", + sizeof (GstNetControlMessageMeta), + net_control_message_meta_init, + net_control_message_meta_free, + net_control_message_meta_transform); + g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) mi); + } + return meta_info; +} + +/** + * gst_buffer_add_net_control_message_meta: + * @buffer: a #GstBuffer + * @message: a @GSocketControlMessage to attach to @buffer + * + * Attaches @message as metadata in a #GstNetControlMessageMeta to @buffer. + * + * Returns: (transfer none): a #GstNetControlMessageMeta connected to @buffer + */ +GstNetControlMessageMeta * +gst_buffer_add_net_control_message_meta (GstBuffer * buffer, + GSocketControlMessage * message) +{ + GstNetControlMessageMeta *meta; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), NULL); + + meta = + (GstNetControlMessageMeta *) gst_buffer_add_meta (buffer, + GST_NET_CONTROL_MESSAGE_META_INFO, NULL); + + meta->message = g_object_ref (message); + + return meta; +} diff --git a/libs/gst/net/gstnetcontrolmessagemeta.h b/libs/gst/net/gstnetcontrolmessagemeta.h new file mode 100644 index 0000000..b51b876 --- /dev/null +++ b/libs/gst/net/gstnetcontrolmessagemeta.h @@ -0,0 +1,69 @@ +/* GStreamer + * Copyright (C) <2014> William Manley + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_NET_CONTROL_MESSAGE_META_H__ +#define __GST_NET_CONTROL_MESSAGE_META_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstNetControlMessageMeta GstNetControlMessageMeta; + +/** + * GstNetControlMessageMeta: + * @meta: the parent type + * @message: a #GSocketControlMessage stored as metadata + * + * Buffer metadata for GSocket control messages, AKA ancillary data attached to + * data sent across a socket. + */ +struct _GstNetControlMessageMeta { + GstMeta meta; + + GSocketControlMessage *message; +}; + +GST_NET_API +GType gst_net_control_message_meta_api_get_type (void); + +#define GST_NET_CONTROL_MESSAGE_META_API_TYPE \ + (gst_net_control_message_meta_api_get_type()) + +#define gst_buffer_get_net_control_message_meta(b) ((GstNetControlMessageMeta*)\ + gst_buffer_get_meta((b),GST_NET_CONTROL_MESSAGE_META_API_TYPE)) + +/* implementation */ + +GST_NET_API +const GstMetaInfo *gst_net_control_message_meta_get_info (void); + +#define GST_NET_CONTROL_MESSAGE_META_INFO \ + (gst_net_control_message_meta_get_info()) + +GST_NET_API +GstNetControlMessageMeta * gst_buffer_add_net_control_message_meta (GstBuffer * buffer, + GSocketControlMessage * message); + +G_END_DECLS + +#endif /* __GST_NET_CONTROL_MESSAGE_META_H__ */ + diff --git a/libs/gst/net/gstnettimepacket.c b/libs/gst/net/gstnettimepacket.c new file mode 100644 index 0000000..f914988 --- /dev/null +++ b/libs/gst/net/gstnettimepacket.c @@ -0,0 +1,247 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * Copyright (C) 2010 Tim-Philipp Müller + * Copyright (C) 2012 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstnettimepacket + * @title: GstNetTimePacket + * @short_description: Helper structure to construct clock packets used + * by network clocks. + * @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider + * + * Various functions for receiving, sending an serializing #GstNetTimePacket + * structures. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef __CYGWIN__ +# include +# include +#endif + +#include "gstnettimepacket.h" + +G_DEFINE_BOXED_TYPE (GstNetTimePacket, gst_net_time_packet, + gst_net_time_packet_copy, gst_net_time_packet_free); + +/** + * gst_net_time_packet_new: + * @buffer: (array): a buffer from which to construct the packet, or NULL + * + * Creates a new #GstNetTimePacket from a buffer received over the network. The + * caller is responsible for ensuring that @buffer is at least + * #GST_NET_TIME_PACKET_SIZE bytes long. + * + * If @buffer is %NULL, the local and remote times will be set to + * #GST_CLOCK_TIME_NONE. + * + * MT safe. Caller owns return value (gst_net_time_packet_free to free). + * + * Returns: The new #GstNetTimePacket. + */ +GstNetTimePacket * +gst_net_time_packet_new (const guint8 * buffer) +{ + GstNetTimePacket *ret; + + g_assert (sizeof (GstClockTime) == 8); + + ret = g_new0 (GstNetTimePacket, 1); + + if (buffer) { + ret->local_time = GST_READ_UINT64_BE (buffer); + ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime)); + } else { + ret->local_time = GST_CLOCK_TIME_NONE; + ret->remote_time = GST_CLOCK_TIME_NONE; + } + + return ret; +} + +/** + * gst_net_time_packet_free: + * @packet: the #GstNetTimePacket + * + * Free @packet. + */ +void +gst_net_time_packet_free (GstNetTimePacket * packet) +{ + g_free (packet); +} + +/** + * gst_net_time_packet_copy: + * @packet: the #GstNetTimePacket + * + * Make a copy of @packet. + * + * Returns: a copy of @packet, free with gst_net_time_packet_free(). + */ +GstNetTimePacket * +gst_net_time_packet_copy (const GstNetTimePacket * packet) +{ + GstNetTimePacket *ret; + + ret = g_new0 (GstNetTimePacket, 1); + ret->local_time = packet->local_time; + ret->remote_time = packet->remote_time; + + return ret; +} + +/** + * gst_net_time_packet_serialize: + * @packet: the #GstNetTimePacket + * + * Serialized a #GstNetTimePacket into a newly-allocated sequence of + * #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is + * suitable for passing to write(2) or sendto(2) for communication over the + * network. + * + * MT safe. Caller owns return value (g_free to free). + * + * Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes. + */ +guint8 * +gst_net_time_packet_serialize (const GstNetTimePacket * packet) +{ + guint8 *ret; + + g_assert (sizeof (GstClockTime) == 8); + + ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE); + + GST_WRITE_UINT64_BE (ret, packet->local_time); + GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time); + + return ret; +} + +/** + * gst_net_time_packet_receive: + * @socket: socket to receive the time packet on + * @src_address: (out): address of variable to return sender address + * @error: return address for a #GError, or NULL + * + * Receives a #GstNetTimePacket over a socket. Handles interrupted system + * calls, but otherwise returns NULL on error. + * + * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free + * with gst_net_time_packet_free() when done. + */ +GstNetTimePacket * +gst_net_time_packet_receive (GSocket * socket, + GSocketAddress ** src_address, GError ** error) +{ + gchar buffer[GST_NET_TIME_PACKET_SIZE]; + GError *err = NULL; + gssize ret; + + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + while (TRUE) { + ret = g_socket_receive_from (socket, src_address, buffer, + GST_NET_TIME_PACKET_SIZE, NULL, &err); + + if (ret < 0) { + if (err->code == G_IO_ERROR_WOULD_BLOCK) { + g_error_free (err); + err = NULL; + continue; + } else { + goto receive_error; + } + } else if (ret < GST_NET_TIME_PACKET_SIZE) { + goto short_packet; + } else { + return gst_net_time_packet_new ((const guint8 *) buffer); + } + } + +receive_error: + { + GST_DEBUG ("receive error: %s", err->message); + g_propagate_error (error, err); + return NULL; + } +short_packet: + { + GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)", + ret, GST_NET_TIME_PACKET_SIZE); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE); + return NULL; + } +} + +/** + * gst_net_time_packet_send: + * @packet: the #GstNetTimePacket to send + * @socket: socket to send the time packet on + * @dest_address: address to send the time packet to + * @error: return address for a #GError, or NULL + * + * Sends a #GstNetTimePacket over a socket. + * + * MT safe. + * + * Returns: TRUE if successful, FALSE in case an error occurred. + */ +gboolean +gst_net_time_packet_send (const GstNetTimePacket * packet, + GSocket * socket, GSocketAddress * dest_address, GError ** error) +{ + gboolean was_blocking; + guint8 *buffer; + gssize res; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + was_blocking = g_socket_get_blocking (socket); + + if (was_blocking) + g_socket_set_blocking (socket, FALSE); + + /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */ + buffer = gst_net_time_packet_serialize (packet); + + res = g_socket_send_to (socket, dest_address, (const gchar *) buffer, + GST_NET_TIME_PACKET_SIZE, NULL, error); + + /* datagram packets should be sent as a whole or not at all */ + g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE); + + g_free (buffer); + + if (was_blocking) + g_socket_set_blocking (socket, TRUE); + + return (res == GST_NET_TIME_PACKET_SIZE); +} diff --git a/libs/gst/net/gstnettimepacket.h b/libs/gst/net/gstnettimepacket.h new file mode 100644 index 0000000..a04ea03 --- /dev/null +++ b/libs/gst/net/gstnettimepacket.h @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) 2005 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NET_TIME_PACKET_H__ +#define __GST_NET_TIME_PACKET_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GST_NET_TIME_PACKET_SIZE: + * + * The size of the packets sent between network clocks. + */ +#define GST_NET_TIME_PACKET_SIZE 16 + +typedef struct _GstNetTimePacket GstNetTimePacket; + +/** + * GstNetTimePacket: + * @local_time: the local time when this packet was sent + * @remote_time: the remote time observation + * + * Content of a #GstNetTimePacket. + */ +struct _GstNetTimePacket { + GstClockTime local_time; + GstClockTime remote_time; +}; + +GST_NET_API +GType gst_net_time_packet_get_type (void); + +GST_NET_API +GstNetTimePacket* gst_net_time_packet_new (const guint8 *buffer); + +GST_NET_API +GstNetTimePacket* gst_net_time_packet_copy (const GstNetTimePacket *packet); + +GST_NET_API +void gst_net_time_packet_free (GstNetTimePacket *packet); + +GST_NET_API +guint8* gst_net_time_packet_serialize (const GstNetTimePacket *packet); + +GST_NET_API +GstNetTimePacket* gst_net_time_packet_receive (GSocket * socket, + GSocketAddress ** src_address, + GError ** error); +GST_NET_API +gboolean gst_net_time_packet_send (const GstNetTimePacket * packet, + GSocket * socket, + GSocketAddress * dest_address, + GError ** error); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimePacket, gst_net_time_packet_free) +#endif + +G_END_DECLS + + +#endif /* __GST_NET_TIME_PACKET_H__ */ diff --git a/libs/gst/net/gstnettimeprovider.c b/libs/gst/net/gstnettimeprovider.c new file mode 100644 index 0000000..b5432a1 --- /dev/null +++ b/libs/gst/net/gstnettimeprovider.c @@ -0,0 +1,482 @@ +/* GStreamer + * Copyright (C) 2005 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstnettimeprovider + * @title: GstNetTimeProvider + * @short_description: Special object that exposed the time of a clock + * on the network. + * @see_also: #GstClock, #GstNetClientClock, #GstPipeline + * + * This object exposes the time of a #GstClock on the network. + * + * A #GstNetTimeProvider is created with gst_net_time_provider_new() which + * takes a #GstClock, an address and a port number as arguments. + * + * After creating the object, a client clock such as #GstNetClientClock can + * query the exposed clock over the network for its values. + * + * The #GstNetTimeProvider typically wraps the clock used by a #GstPipeline. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstnettimeprovider.h" +#include "gstnettimepacket.h" +#include "gstnetutils.h" + +GST_DEBUG_CATEGORY_STATIC (ntp_debug); +#define GST_CAT_DEFAULT (ntp_debug) + +#define DEFAULT_ADDRESS "0.0.0.0" +#define DEFAULT_PORT 5637 +#define DEFAULT_QOS_DSCP -1 + +#define IS_ACTIVE(self) (g_atomic_int_get (&((self)->priv->active))) + +enum +{ + PROP_0, + PROP_PORT, + PROP_ADDRESS, + PROP_CLOCK, + PROP_ACTIVE, + PROP_QOS_DSCP +}; + +#define GST_NET_TIME_PROVIDER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_NET_TIME_PROVIDER, GstNetTimeProviderPrivate)) + +struct _GstNetTimeProviderPrivate +{ + gchar *address; + int port; + gint qos_dscp; /* ATOMIC */ + + GThread *thread; + + GstClock *clock; + + gboolean active; /* ATOMIC */ + + GSocket *socket; + GCancellable *cancel; + gboolean made_cancel_fd; +}; + +static void gst_net_time_provider_initable_iface_init (gpointer g_iface); + +static gboolean gst_net_time_provider_start (GstNetTimeProvider * bself, + GError ** error); +static void gst_net_time_provider_stop (GstNetTimeProvider * bself); + +static gpointer gst_net_time_provider_thread (gpointer data); + +static void gst_net_time_provider_finalize (GObject * object); +static void gst_net_time_provider_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_net_time_provider_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (ntp_debug, "nettime", 0, "Network time provider"); \ + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gst_net_time_provider_initable_iface_init) + +#define gst_net_time_provider_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstNetTimeProvider, gst_net_time_provider, + GST_TYPE_OBJECT, _do_init); + +static void +gst_net_time_provider_class_init (GstNetTimeProviderClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + g_assert (sizeof (GstClockTime) == 8); + + g_type_class_add_private (klass, sizeof (GstNetTimeProviderPrivate)); + + gobject_class->finalize = gst_net_time_provider_finalize; + gobject_class->set_property = gst_net_time_provider_set_property; + gobject_class->get_property = gst_net_time_provider_get_property; + + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_int ("port", "port", + "The port to receive the packets from, 0=allocate", 0, G_MAXUINT16, + DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_string ("address", "address", + "The address to bind on, as a dotted quad (x.x.x.x)", DEFAULT_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CLOCK, + g_param_spec_object ("clock", "Clock", + "The clock to export over the network", GST_TYPE_CLOCK, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ACTIVE, + g_param_spec_boolean ("active", "Active", + "TRUE if the clock will respond to queries over the network", TRUE, + G_PARAM_READWRITE | G_PARAM_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)); +} + +static void +gst_net_time_provider_init (GstNetTimeProvider * self) +{ + self->priv = GST_NET_TIME_PROVIDER_GET_PRIVATE (self); + + self->priv->port = DEFAULT_PORT; + self->priv->address = g_strdup (DEFAULT_ADDRESS); + self->priv->qos_dscp = DEFAULT_QOS_DSCP; + self->priv->thread = NULL; + self->priv->active = TRUE; +} + +static void +gst_net_time_provider_finalize (GObject * object) +{ + GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object); + + if (self->priv->thread) { + gst_net_time_provider_stop (self); + g_assert (self->priv->thread == NULL); + } + + g_free (self->priv->address); + self->priv->address = NULL; + + if (self->priv->clock) + gst_object_unref (self->priv->clock); + self->priv->clock = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gpointer +gst_net_time_provider_thread (gpointer data) +{ + GstNetTimeProvider *self = data; + GCancellable *cancel = self->priv->cancel; + GSocket *socket = self->priv->socket; + GstNetTimePacket *packet; + GError *err = NULL; + gint cur_qos_dscp = DEFAULT_QOS_DSCP; + gint new_qos_dscp; + + GST_INFO_OBJECT (self, "time provider thread is running"); + + while (TRUE) { + GSocketAddress *sender_addr = NULL; + + + GST_LOG_OBJECT (self, "waiting on socket"); + if (!g_socket_condition_wait (socket, G_IO_IN, cancel, &err)) { + GST_INFO_OBJECT (self, "socket error: %s", err->message); + + if (err->code == G_IO_ERROR_CANCELLED) + break; + + /* try again */ + g_usleep (G_USEC_PER_SEC / 10); + g_error_free (err); + err = NULL; + continue; + } + + /* got data in */ + packet = gst_net_time_packet_receive (socket, &sender_addr, &err); + + if (err != NULL) { + GST_DEBUG_OBJECT (self, "receive error: %s", err->message); + g_usleep (G_USEC_PER_SEC / 10); + g_error_free (err); + err = NULL; + continue; + } + + /* before next sending check if need to change QoS */ + new_qos_dscp = self->priv->qos_dscp; + if (cur_qos_dscp != new_qos_dscp && + gst_net_utils_set_socket_dscp (socket, new_qos_dscp)) { + GST_DEBUG_OBJECT (self, "changed QoS DSCP to: %d", new_qos_dscp); + cur_qos_dscp = new_qos_dscp; + } + + if (IS_ACTIVE (self)) { + /* do what we were asked to and send the packet back */ + packet->remote_time = gst_clock_get_time (self->priv->clock); + + /* ignore errors */ + gst_net_time_packet_send (packet, socket, sender_addr, NULL); + g_object_unref (sender_addr); + g_free (packet); + } + } + + g_error_free (err); + + GST_INFO_OBJECT (self, "time provider thread is stopping"); + return NULL; +} + +static void +gst_net_time_provider_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object); + GstClock **clock_p = &self->priv->clock; + + switch (prop_id) { + case PROP_PORT: + self->priv->port = g_value_get_int (value); + break; + case PROP_ADDRESS: + g_free (self->priv->address); + if (g_value_get_string (value) == NULL) + self->priv->address = g_strdup (DEFAULT_ADDRESS); + else + self->priv->address = g_strdup (g_value_get_string (value)); + break; + case PROP_CLOCK: + gst_object_replace ((GstObject **) clock_p, + (GstObject *) g_value_get_object (value)); + break; + case PROP_ACTIVE: + g_atomic_int_set (&self->priv->active, g_value_get_boolean (value)); + break; + case PROP_QOS_DSCP: + g_atomic_int_set (&self->priv->qos_dscp, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_net_time_provider_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object); + + switch (prop_id) { + case PROP_PORT: + g_value_set_int (value, self->priv->port); + break; + case PROP_ADDRESS: + g_value_set_string (value, self->priv->address); + break; + case PROP_CLOCK: + g_value_set_object (value, self->priv->clock); + break; + case PROP_ACTIVE: + g_value_set_boolean (value, IS_ACTIVE (self)); + break; + case PROP_QOS_DSCP: + g_value_set_int (value, self->priv->qos_dscp); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_net_time_provider_start (GstNetTimeProvider * self, GError ** error) +{ + GSocketAddress *socket_addr, *bound_addr; + GInetAddress *inet_addr; + GPollFD dummy_pollfd; + GSocket *socket; + int port; + gchar *address; + GError *err = NULL; + + if (self->priv->address) { + inet_addr = g_inet_address_new_from_string (self->priv->address); + if (inet_addr == NULL) { + err = + g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to parse address '%s'", self->priv->address); + goto invalid_address; + } + } else { + inet_addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); + } + + GST_LOG_OBJECT (self, "creating socket"); + socket = g_socket_new (g_inet_address_get_family (inet_addr), + G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err); + + if (!socket) + goto no_socket; + + GST_DEBUG_OBJECT (self, "binding on port %d", self->priv->port); + socket_addr = g_inet_socket_address_new (inet_addr, self->priv->port); + if (!g_socket_bind (socket, socket_addr, TRUE, &err)) { + g_object_unref (socket_addr); + g_object_unref (inet_addr); + goto bind_error; + } + g_object_unref (socket_addr); + g_object_unref (inet_addr); + + bound_addr = g_socket_get_local_address (socket, NULL); + port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_addr)); + inet_addr = + g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (bound_addr)); + address = g_inet_address_to_string (inet_addr); + + if (g_strcmp0 (address, self->priv->address)) { + g_free (self->priv->address); + self->priv->address = address; + GST_DEBUG_OBJECT (self, "notifying address %s", address); + g_object_notify (G_OBJECT (self), "address"); + } else { + g_free (address); + } + if (port != self->priv->port) { + self->priv->port = port; + GST_DEBUG_OBJECT (self, "notifying port %d", port); + g_object_notify (G_OBJECT (self), "port"); + } + GST_DEBUG_OBJECT (self, "bound on UDP address %s, port %d", + self->priv->address, port); + g_object_unref (bound_addr); + + self->priv->socket = socket; + self->priv->cancel = g_cancellable_new (); + self->priv->made_cancel_fd = + g_cancellable_make_pollfd (self->priv->cancel, &dummy_pollfd); + + self->priv->thread = g_thread_try_new ("GstNetTimeProvider", + gst_net_time_provider_thread, self, &err); + + if (!self->priv->thread) + goto no_thread; + + return TRUE; + + /* ERRORS */ +invalid_address: + { + GST_ERROR_OBJECT (self, "invalid address: %s", self->priv->address); + g_propagate_error (error, err); + return FALSE; + } +no_socket: + { + GST_ERROR_OBJECT (self, "could not create socket: %s", err->message); + g_propagate_error (error, err); + g_object_unref (inet_addr); + return FALSE; + } +bind_error: + { + GST_ERROR_OBJECT (self, "bind failed: %s", err->message); + g_propagate_error (error, err); + g_object_unref (socket); + return FALSE; + } +no_thread: + { + GST_ERROR_OBJECT (self, "could not create thread: %s", err->message); + g_propagate_error (error, err); + g_object_unref (self->priv->socket); + self->priv->socket = NULL; + g_object_unref (self->priv->cancel); + self->priv->cancel = NULL; + return FALSE; + } +} + +static void +gst_net_time_provider_stop (GstNetTimeProvider * self) +{ + g_return_if_fail (self->priv->thread != NULL); + + GST_INFO_OBJECT (self, "stopping.."); + g_cancellable_cancel (self->priv->cancel); + + g_thread_join (self->priv->thread); + self->priv->thread = NULL; + + if (self->priv->made_cancel_fd) + g_cancellable_release_fd (self->priv->cancel); + + g_object_unref (self->priv->cancel); + self->priv->cancel = NULL; + + g_object_unref (self->priv->socket); + self->priv->socket = NULL; + + GST_INFO_OBJECT (self, "stopped"); +} + +static gboolean +gst_net_time_provider_initable_init (GInitable * initable, + GCancellable * cancellable, GError ** error) +{ + GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (initable); + + return gst_net_time_provider_start (self, error); +} + +static void +gst_net_time_provider_initable_iface_init (gpointer g_iface) +{ + GInitableIface *iface = g_iface; + + iface->init = gst_net_time_provider_initable_init; +} + +/** + * gst_net_time_provider_new: + * @clock: a #GstClock to export over the network + * @address: (allow-none): an address to bind on as a dotted quad + * (xxx.xxx.xxx.xxx), IPv6 address, or NULL to bind to all addresses + * @port: a port to bind on, or 0 to let the kernel choose + * + * Allows network clients to get the current time of @clock. + * + * Returns: (transfer full): the new #GstNetTimeProvider, or NULL on error + */ +GstNetTimeProvider * +gst_net_time_provider_new (GstClock * clock, const gchar * address, gint port) +{ + GstNetTimeProvider *ret; + + g_return_val_if_fail (clock && GST_IS_CLOCK (clock), NULL); + g_return_val_if_fail (port >= 0 && port <= G_MAXUINT16, NULL); + + ret = + g_initable_new (GST_TYPE_NET_TIME_PROVIDER, NULL, NULL, "clock", clock, + "address", address, "port", port, NULL); + + /* Clear floating flag */ + g_object_ref_sink (ret); + + return ret; +} diff --git a/libs/gst/net/gstnettimeprovider.h b/libs/gst/net/gstnettimeprovider.h new file mode 100644 index 0000000..d1f6de3 --- /dev/null +++ b/libs/gst/net/gstnettimeprovider.h @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * 2006 Joni Valtanen + * Copyright (C) 2012 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NET_TIME_PROVIDER_H__ +#define __GST_NET_TIME_PROVIDER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_NET_TIME_PROVIDER \ + (gst_net_time_provider_get_type()) +#define GST_NET_TIME_PROVIDER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NET_TIME_PROVIDER,GstNetTimeProvider)) +#define GST_NET_TIME_PROVIDER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NET_TIME_PROVIDER,GstNetTimeProviderClass)) +#define GST_IS_NET_TIME_PROVIDER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NET_TIME_PROVIDER)) +#define GST_IS_NET_TIME_PROVIDER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NET_TIME_PROVIDER)) + +typedef struct _GstNetTimeProvider GstNetTimeProvider; +typedef struct _GstNetTimeProviderClass GstNetTimeProviderClass; +typedef struct _GstNetTimeProviderPrivate GstNetTimeProviderPrivate; + +/** + * GstNetTimeProvider: + * + * Opaque #GstNetTimeProvider structure. + */ +struct _GstNetTimeProvider { + GstObject parent; + + /*< private >*/ + GstNetTimeProviderPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstNetTimeProviderClass { + GstObjectClass parent_class; + + gpointer _gst_reserved[GST_PADDING]; +}; + +GST_NET_API +GType gst_net_time_provider_get_type (void); + +GST_NET_API +GstNetTimeProvider* gst_net_time_provider_new (GstClock *clock, + const gchar *address, + gint port); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstNetTimeProvider, gst_object_unref) +#endif + +G_END_DECLS + + +#endif /* __GST_NET_TIME_PROVIDER_H__ */ diff --git a/libs/gst/net/gstnetutils.c b/libs/gst/net/gstnetutils.c new file mode 100644 index 0000000..a8a99d9 --- /dev/null +++ b/libs/gst/net/gstnetutils.c @@ -0,0 +1,66 @@ +/* GStreamer + * Copyright (C) 2017 Sebastian Dröge + * Copyright (C) 2017 Robert Rosengren + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstnetutils.h" +#include +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifndef G_OS_WIN32 +#include +#endif + +/** + * gst_net_time_packet_util_set_dscp: + * @socket: Socket to configure + * @qos_dscp: QoS DSCP value + * + * Configures IP_TOS value of socket, i.e. sets QoS DSCP. + * + * Returns: TRUE if successful, FALSE in case an error occurred. + */ +gboolean +gst_net_utils_set_socket_dscp (GSocket * socket, gint qos_dscp) +{ + gboolean ret = FALSE; + +#ifdef IP_TOS + gint tos, fd; + fd = g_socket_get_fd (socket); + + /* Extract and shift 6 bits of DSFIELD */ + tos = (qos_dscp & 0x3f) << 2; + + if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) { + GST_ERROR ("could not set TOS: %s", g_strerror (errno)); + } else { + ret = TRUE; + } +#endif + + return ret; +} diff --git a/libs/gst/net/gstnetutils.h b/libs/gst/net/gstnetutils.h new file mode 100644 index 0000000..053f187 --- /dev/null +++ b/libs/gst/net/gstnetutils.h @@ -0,0 +1,36 @@ +/* GStreamer + * Copyright (C) 2017 Sebastian Dröge + * Copyright (C) 2017 Robert Rosengren + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NET_UTILS_H__ +#define __GST_NET_UTILS_H__ + +#include +#include + +G_BEGIN_DECLS + +G_GNUC_INTERNAL +gboolean gst_net_utils_set_socket_dscp (GSocket * socket, + gint qos_dscp); + +G_END_DECLS + +#endif /* __GST_NET_UTILS_H__ */ diff --git a/libs/gst/net/gstntppacket.c b/libs/gst/net/gstntppacket.c new file mode 100644 index 0000000..8d88d75 --- /dev/null +++ b/libs/gst/net/gstntppacket.c @@ -0,0 +1,376 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * Copyright (C) 2010 Tim-Philipp Müller + * Copyright (C) 2012 Collabora Ltd. + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* THIS IS A PRIVATE API + * SECTION:gstntppacket + * @short_description: Helper structure to construct clock packets used + * by network clocks for NTPv4. + * @see_also: #GstClock, #GstNetClientClock, #GstNtpClock + * + * Various functions for receiving, sending an serializing #GstNtpPacket + * structures. + */ + +/* FIXME 2.0: Merge this with GstNetTimePacket! */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef __CYGWIN__ +# include +# include +#endif + +#include +#include + +#include "gstntppacket.h" + +G_DEFINE_BOXED_TYPE (GstNtpPacket, gst_ntp_packet, + gst_ntp_packet_copy, gst_ntp_packet_free); + + +static inline GstClockTime +ntp_timestamp_to_gst_clock_time (guint32 seconds, guint32 fraction) +{ + return gst_util_uint64_scale (seconds, GST_SECOND, 1) + + gst_util_uint64_scale (fraction, GST_SECOND, + G_GUINT64_CONSTANT (1) << 32); +} + +static inline guint32 +gst_clock_time_to_ntp_timestamp_seconds (GstClockTime gst) +{ + GstClockTime seconds = gst_util_uint64_scale (gst, 1, GST_SECOND); + + return seconds; +} + +static inline guint32 +gst_clock_time_to_ntp_timestamp_fraction (GstClockTime gst) +{ + GstClockTime seconds = gst_util_uint64_scale (gst, 1, GST_SECOND); + + return gst_util_uint64_scale (gst - seconds, G_GUINT64_CONSTANT (1) << 32, + GST_SECOND); +} + +/** + * gst_ntp_packet_new: + * @buffer: (array): a buffer from which to construct the packet, or NULL + * @error: a #GError + * + * Creates a new #GstNtpPacket from a buffer received over the network. The + * caller is responsible for ensuring that @buffer is at least + * #GST_NTP_PACKET_SIZE bytes long. + * + * If @buffer is %NULL, the local and remote times will be set to + * #GST_CLOCK_TIME_NONE. + * + * MT safe. Caller owns return value (gst_ntp_packet_free to free). + * + * Returns: The new #GstNtpPacket. + */ +GstNtpPacket * +gst_ntp_packet_new (const guint8 * buffer, GError ** error) +{ + GstNtpPacket *ret; + + g_assert (sizeof (GstClockTime) == 8); + + if (buffer) { + guint8 version = (buffer[0] >> 3) & 0x7; + guint8 stratum = buffer[1]; + gint8 poll_interval = buffer[2]; + + if (version != 4) { + g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_WRONG_VERSION, + "Invalid NTP version %d", version); + return NULL; + } + + /* Kiss-o'-Death packet! */ + if (stratum == 0) { + gchar code[5] = { buffer[3 * 4 + 0], buffer[3 * 4 + 1], buffer[3 * 4 + 2], + buffer[3 * 4 + 3], 0 + }; + + /* AUTH, AUTO, CRYP, DENY, RSTR, NKEY => DENY */ + if (strcmp (code, "AUTH") == 0 || + strcmp (code, "AUTO") == 0 || + strcmp (code, "CRYP") == 0 || + strcmp (code, "DENY") == 0 || + strcmp (code, "RSTR") == 0 || strcmp (code, "NKEY") == 0) { + g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_DENY, + "Kiss-o'-Death denied '%s'", code); + } else if (strcmp (code, "RATE") == 0) { + g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_RATE, + "Kiss-o'-Death '%s'", code); + } else { + g_set_error (error, GST_NTP_ERROR, GST_NTP_ERROR_KOD_UNKNOWN, + "Kiss-o'-Death unknown '%s'", code); + } + + return NULL; + } + + ret = g_new0 (GstNtpPacket, 1); + ret->origin_time = + ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 6 * 4), + GST_READ_UINT32_BE (buffer + 7 * 4)); + ret->receive_time = + ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 8 * 4), + GST_READ_UINT32_BE (buffer + 9 * 4)); + ret->transmit_time = + ntp_timestamp_to_gst_clock_time (GST_READ_UINT32_BE (buffer + 10 * 4), + GST_READ_UINT32_BE (buffer + 11 * 4)); + + /* Wireshark considers everything >= 3 as invalid */ + if (poll_interval >= 3) + ret->poll_interval = GST_CLOCK_TIME_NONE; + else if (poll_interval >= 0) + ret->poll_interval = GST_SECOND << poll_interval; + else + ret->poll_interval = GST_SECOND >> (-poll_interval); + } else { + ret = g_new0 (GstNtpPacket, 1); + ret->origin_time = 0; + ret->receive_time = 0; + ret->transmit_time = 0; + ret->poll_interval = 0; + } + + return ret; +} + +/** + * gst_ntp_packet_free: + * @packet: the #GstNtpPacket + * + * Free @packet. + */ +void +gst_ntp_packet_free (GstNtpPacket * packet) +{ + g_free (packet); +} + +/** + * gst_ntp_packet_copy: + * @packet: the #GstNtpPacket + * + * Make a copy of @packet. + * + * Returns: a copy of @packet, free with gst_ntp_packet_free(). + */ +GstNtpPacket * +gst_ntp_packet_copy (const GstNtpPacket * packet) +{ + GstNtpPacket *ret; + + ret = g_new0 (GstNtpPacket, 1); + ret->origin_time = packet->origin_time; + ret->receive_time = packet->receive_time; + ret->transmit_time = packet->transmit_time; + + return ret; +} + +/** + * gst_ntp_packet_serialize: + * @packet: the #GstNtpPacket + * + * Serialized a #GstNtpPacket into a newly-allocated sequence of + * #GST_NTP_PACKET_SIZE bytes, in network byte order. The value returned is + * suitable for passing to write(2) or sendto(2) for communication over the + * network. + * + * MT safe. Caller owns return value (g_free to free). + * + * Returns: A newly allocated sequence of #GST_NTP_PACKET_SIZE bytes. + */ +guint8 * +gst_ntp_packet_serialize (const GstNtpPacket * packet) +{ + guint8 *ret; + + g_assert (sizeof (GstClockTime) == 8); + + ret = g_new0 (guint8, GST_NTP_PACKET_SIZE); + /* Leap Indicator: unknown + * Version: 4 + * Mode: Client + */ + ret[0] = (3 << 6) | (4 << 3) | (3 << 0); + /* Stratum: unsynchronized */ + ret[1] = 16; + /* Polling interval: invalid */ + ret[2] = 3; + /* Precision: 0 */ + ret[3] = 0; + /* Root delay: 0 */ + GST_WRITE_UINT32_BE (ret + 4, 0); + /* Root disperson: 0 */ + GST_WRITE_UINT32_BE (ret + 2 * 4, 0); + /* Reference ID: \0 */ + GST_WRITE_UINT32_BE (ret + 3 * 4, 0); + /* Reference Timestamp: 0 */ + GST_WRITE_UINT32_BE (ret + 4 * 4, 0); + GST_WRITE_UINT32_BE (ret + 5 * 4, 0); + /* Origin timestamp (local time) */ + GST_WRITE_UINT32_BE (ret + 6 * 4, + gst_clock_time_to_ntp_timestamp_seconds (packet->origin_time)); + GST_WRITE_UINT32_BE (ret + 7 * 4, + gst_clock_time_to_ntp_timestamp_fraction (packet->origin_time)); + /* Receive timestamp (remote time) */ + GST_WRITE_UINT32_BE (ret + 8 * 4, + gst_clock_time_to_ntp_timestamp_seconds (packet->receive_time)); + GST_WRITE_UINT32_BE (ret + 9 * 4, + gst_clock_time_to_ntp_timestamp_fraction (packet->receive_time)); + /* Transmit timestamp (remote time) */ + GST_WRITE_UINT32_BE (ret + 10 * 4, + gst_clock_time_to_ntp_timestamp_seconds (packet->transmit_time)); + GST_WRITE_UINT32_BE (ret + 11 * 4, + gst_clock_time_to_ntp_timestamp_fraction (packet->transmit_time)); + + return ret; +} + +/** + * gst_ntp_packet_receive: + * @socket: socket to receive the time packet on + * @src_address: (out): address of variable to return sender address + * @error: return address for a #GError, or NULL + * + * Receives a #GstNtpPacket over a socket. Handles interrupted system + * calls, but otherwise returns NULL on error. + * + * Returns: (transfer full): a new #GstNtpPacket, or NULL on error. Free + * with gst_ntp_packet_free() when done. + */ +GstNtpPacket * +gst_ntp_packet_receive (GSocket * socket, + GSocketAddress ** src_address, GError ** error) +{ + gchar buffer[GST_NTP_PACKET_SIZE]; + GError *err = NULL; + gssize ret; + + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + while (TRUE) { + ret = g_socket_receive_from (socket, src_address, buffer, + GST_NTP_PACKET_SIZE, NULL, &err); + + if (ret < 0) { + if (err->code == G_IO_ERROR_WOULD_BLOCK) { + g_error_free (err); + err = NULL; + continue; + } else { + goto receive_error; + } + } else if (ret < GST_NTP_PACKET_SIZE) { + goto short_packet; + } else { + return gst_ntp_packet_new ((const guint8 *) buffer, error); + } + } + +receive_error: + { + GST_DEBUG ("receive error: %s", err->message); + g_propagate_error (error, err); + return NULL; + } +short_packet: + { + GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)", + ret, GST_NTP_PACKET_SIZE); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "short time packet (%d < %d)", (int) ret, GST_NTP_PACKET_SIZE); + return NULL; + } +} + +/** + * gst_ntp_packet_send: + * @packet: the #GstNtpPacket to send + * @socket: socket to send the time packet on + * @dest_address: address to send the time packet to + * @error: return address for a #GError, or NULL + * + * Sends a #GstNtpPacket over a socket. + * + * MT safe. + * + * Returns: TRUE if successful, FALSE in case an error occurred. + */ +gboolean +gst_ntp_packet_send (const GstNtpPacket * packet, + GSocket * socket, GSocketAddress * dest_address, GError ** error) +{ + gboolean was_blocking; + guint8 *buffer; + gssize res; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + was_blocking = g_socket_get_blocking (socket); + + if (was_blocking) + g_socket_set_blocking (socket, FALSE); + + /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */ + buffer = gst_ntp_packet_serialize (packet); + + res = g_socket_send_to (socket, dest_address, (const gchar *) buffer, + GST_NTP_PACKET_SIZE, NULL, error); + + /* datagram packets should be sent as a whole or not at all */ + g_assert (res < 0 || res == GST_NTP_PACKET_SIZE); + + g_free (buffer); + + if (was_blocking) + g_socket_set_blocking (socket, TRUE); + + return (res == GST_NTP_PACKET_SIZE); +} + +GQuark +gst_ntp_error_quark (void) +{ + static GQuark quark; + + /* Thread-safe because GQuark is */ + if (!quark) + quark = g_quark_from_static_string ("gst-ntp-error-quark"); + + return quark; +} diff --git a/libs/gst/net/gstntppacket.h b/libs/gst/net/gstntppacket.h new file mode 100644 index 0000000..0ecd5e8 --- /dev/null +++ b/libs/gst/net/gstntppacket.h @@ -0,0 +1,86 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_NTP_PACKET_H__ +#define __GST_NTP_PACKET_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GST_NTP_PACKET_SIZE: + * + * The size of the packets sent between NTP clocks. + */ +#define GST_NTP_PACKET_SIZE 48 + +typedef struct _GstNtpPacket GstNtpPacket; + +/** + * GstNtpPacket: + * @origin_time: the time the client packet was sent for the server + * @receive_time: the time the client packet was received + * @transmit_time: the time the packet was sent + * @poll_interval: maximum poll interval + * + * Content of a #GstNtpPacket. + */ +struct _GstNtpPacket { + GstClockTime origin_time; + GstClockTime receive_time; + GstClockTime transmit_time; + + GstClockTime poll_interval; +}; + +GType gst_ntp_packet_get_type(void) G_GNUC_INTERNAL; + +enum { + GST_NTP_ERROR_WRONG_VERSION, + GST_NTP_ERROR_KOD_DENY, + GST_NTP_ERROR_KOD_RATE, + GST_NTP_ERROR_KOD_UNKNOWN +}; + +GQuark gst_ntp_error_quark (void) G_GNUC_INTERNAL; +#define GST_NTP_ERROR (gst_ntp_error_quark ()) + +GstNtpPacket* gst_ntp_packet_new (const guint8 *buffer, + GError ** error) G_GNUC_INTERNAL; +GstNtpPacket* gst_ntp_packet_copy (const GstNtpPacket *packet) G_GNUC_INTERNAL; +void gst_ntp_packet_free (GstNtpPacket *packet) G_GNUC_INTERNAL; + +guint8* gst_ntp_packet_serialize (const GstNtpPacket *packet) G_GNUC_INTERNAL; + +GstNtpPacket* gst_ntp_packet_receive (GSocket * socket, + GSocketAddress ** src_address, + GError ** error) G_GNUC_INTERNAL; + +gboolean gst_ntp_packet_send (const GstNtpPacket * packet, + GSocket * socket, + GSocketAddress * dest_address, + GError ** error) G_GNUC_INTERNAL; + +G_END_DECLS + +#endif /* __GST_NET_TIME_PACKET_H__ */ diff --git a/libs/gst/net/gstptp_private.h b/libs/gst/net/gstptp_private.h new file mode 100644 index 0000000..18e0e07 --- /dev/null +++ b/libs/gst/net/gstptp_private.h @@ -0,0 +1,19 @@ +#ifndef __GST_PTP_PRIVATE_H__ +#define __GST_PTP_PRIVATE_H__ + +#include + +enum +{ + TYPE_EVENT, + TYPE_GENERAL, + TYPE_CLOCK_ID +}; + +typedef struct +{ + guint16 size; + guint8 type; +} StdIOHeader; + +#endif /* __GST_PTP_PRIVATE_H__ */ diff --git a/libs/gst/net/gstptpclock.c b/libs/gst/net/gstptpclock.c new file mode 100644 index 0000000..e1e0955 --- /dev/null +++ b/libs/gst/net/gstptpclock.c @@ -0,0 +1,2624 @@ +/* GStreamer + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:gstptpclock + * @title: GstPtpClock + * @short_description: Special clock that synchronizes to a remote time + * provider via PTP (IEEE1588:2008). + * @see_also: #GstClock, #GstNetClientClock, #GstPipeline + * + * GstPtpClock implements a PTP (IEEE1588:2008) ordinary clock in slave-only + * mode, that allows a GStreamer pipeline to synchronize to a PTP network + * clock in some specific domain. + * + * The PTP subsystem can be initialized with gst_ptp_init(), which then starts + * a helper process to do the actual communication via the PTP ports. This is + * required as PTP listens on ports < 1024 and thus requires special + * privileges. Once this helper process is started, the main process will + * synchronize to all PTP domains that are detected on the selected + * interfaces. + * + * gst_ptp_clock_new() then allows to create a GstClock that provides the PTP + * time from a master clock inside a specific PTP domain. This clock will only + * return valid timestamps once the timestamps in the PTP domain are known. To + * check this, you can use gst_clock_wait_for_sync(), the GstClock::synced + * signal and gst_clock_is_synced(). + * + * To gather statistics about the PTP clock synchronization, + * gst_ptp_statistics_callback_add() can be used. This gives the application + * the possibility to collect all kinds of statistics from the clock + * synchronization. + * + * Since: 1.6 + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstptpclock.h" + +#include "gstptp_private.h" + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif +#include + +#ifdef HAVE_UNISTD_H +#include +#elif defined(G_OS_WIN32) +#include +#endif + +#include + +GST_DEBUG_CATEGORY_STATIC (ptp_debug); +#define GST_CAT_DEFAULT (ptp_debug) + +/* IEEE 1588 7.7.3.1 */ +#define PTP_ANNOUNCE_RECEIPT_TIMEOUT 4 + +/* Use a running average for calculating the mean path delay instead + * of just using the last measurement. Enabling this helps in unreliable + * networks, like wifi, with often changing delays + * + * Undef for following IEEE1588-2008 by the letter + */ +#define USE_RUNNING_AVERAGE_DELAY 1 + +/* Filter out any measurements that are above a certain threshold compared to + * previous measurements. Enabling this helps filtering out outliers that + * happen fairly often in unreliable networks, like wifi. + * + * Undef for following IEEE1588-2008 by the letter + */ +#define USE_MEASUREMENT_FILTERING 1 + +/* Select the first clock from which we capture a SYNC message as the master + * clock of the domain until we are ready to run the best master clock + * algorithm. This allows faster syncing but might mean a change of the master + * clock in the beginning. As all clocks in a domain are supposed to use the + * same time, this shouldn't be much of a problem. + * + * Undef for following IEEE1588-2008 by the letter + */ +#define USE_OPPORTUNISTIC_CLOCK_SELECTION 1 + +/* Only consider SYNC messages for which we are allowed to send a DELAY_REQ + * afterwards. This allows better synchronization in networks with varying + * delays, as for every other SYNC message we would have to assume that it's + * the average of what we saw before. But that might be completely off + */ +#define USE_ONLY_SYNC_WITH_DELAY 1 + +/* Filter out delay measurements that are too far away from the median of the + * last delay measurements, currently those that are more than 2 times as big. + * This increases accuracy a lot on wifi. + */ +#define USE_MEDIAN_PRE_FILTERING 1 +#define MEDIAN_PRE_FILTERING_WINDOW 9 + +/* How many updates should be skipped at maximum when using USE_MEASUREMENT_FILTERING */ +#define MAX_SKIPPED_UPDATES 5 + +typedef enum +{ + PTP_MESSAGE_TYPE_SYNC = 0x0, + PTP_MESSAGE_TYPE_DELAY_REQ = 0x1, + PTP_MESSAGE_TYPE_PDELAY_REQ = 0x2, + PTP_MESSAGE_TYPE_PDELAY_RESP = 0x3, + PTP_MESSAGE_TYPE_FOLLOW_UP = 0x8, + PTP_MESSAGE_TYPE_DELAY_RESP = 0x9, + PTP_MESSAGE_TYPE_PDELAY_RESP_FOLLOW_UP = 0xA, + PTP_MESSAGE_TYPE_ANNOUNCE = 0xB, + PTP_MESSAGE_TYPE_SIGNALING = 0xC, + PTP_MESSAGE_TYPE_MANAGEMENT = 0xD +} PtpMessageType; + +typedef struct +{ + guint64 seconds_field; /* 48 bits valid */ + guint32 nanoseconds_field; +} PtpTimestamp; + +#define PTP_TIMESTAMP_TO_GST_CLOCK_TIME(ptp) (ptp.seconds_field * GST_SECOND + ptp.nanoseconds_field) +#define GST_CLOCK_TIME_TO_PTP_TIMESTAMP_SECONDS(gst) (((GstClockTime) gst) / GST_SECOND) +#define GST_CLOCK_TIME_TO_PTP_TIMESTAMP_NANOSECONDS(gst) (((GstClockTime) gst) % GST_SECOND) + +typedef struct +{ + guint64 clock_identity; + guint16 port_number; +} PtpClockIdentity; + +static gint +compare_clock_identity (const PtpClockIdentity * a, const PtpClockIdentity * b) +{ + if (a->clock_identity < b->clock_identity) + return -1; + else if (a->clock_identity > b->clock_identity) + return 1; + + if (a->port_number < b->port_number) + return -1; + else if (a->port_number > b->port_number) + return 1; + + return 0; +} + +typedef struct +{ + guint8 clock_class; + guint8 clock_accuracy; + guint16 offset_scaled_log_variance; +} PtpClockQuality; + +typedef struct +{ + guint8 transport_specific; + PtpMessageType message_type; + /* guint8 reserved; */ + guint8 version_ptp; + guint16 message_length; + guint8 domain_number; + /* guint8 reserved; */ + guint16 flag_field; + gint64 correction_field; /* 48.16 fixed point nanoseconds */ + /* guint32 reserved; */ + PtpClockIdentity source_port_identity; + guint16 sequence_id; + guint8 control_field; + gint8 log_message_interval; + + union + { + struct + { + PtpTimestamp origin_timestamp; + gint16 current_utc_offset; + /* guint8 reserved; */ + guint8 grandmaster_priority_1; + PtpClockQuality grandmaster_clock_quality; + guint8 grandmaster_priority_2; + guint64 grandmaster_identity; + guint16 steps_removed; + guint8 time_source; + } announce; + + struct + { + PtpTimestamp origin_timestamp; + } sync; + + struct + { + PtpTimestamp precise_origin_timestamp; + } follow_up; + + struct + { + PtpTimestamp origin_timestamp; + } delay_req; + + struct + { + PtpTimestamp receive_timestamp; + PtpClockIdentity requesting_port_identity; + } delay_resp; + + } message_specific; +} PtpMessage; + +static GMutex ptp_lock; +static GCond ptp_cond; +static gboolean initted = FALSE; +#ifdef HAVE_PTP +static gboolean supported = TRUE; +#else +static gboolean supported = FALSE; +#endif +static GPid ptp_helper_pid; +static GThread *ptp_helper_thread; +static GMainContext *main_context; +static GMainLoop *main_loop; +static GIOChannel *stdin_channel, *stdout_channel; +static GRand *delay_req_rand; +static GstClock *observation_system_clock; +static PtpClockIdentity ptp_clock_id = { GST_PTP_CLOCK_ID_NONE, 0 }; + +typedef struct +{ + GstClockTime receive_time; + + PtpClockIdentity master_clock_identity; + + guint8 grandmaster_priority_1; + PtpClockQuality grandmaster_clock_quality; + guint8 grandmaster_priority_2; + guint64 grandmaster_identity; + guint16 steps_removed; + guint8 time_source; + + guint16 sequence_id; +} PtpAnnounceMessage; + +typedef struct +{ + PtpClockIdentity master_clock_identity; + + GstClockTime announce_interval; /* last interval we received */ + GQueue announce_messages; +} PtpAnnounceSender; + +typedef struct +{ + guint domain; + PtpClockIdentity master_clock_identity; + + guint16 sync_seqnum; + GstClockTime sync_recv_time_local; /* t2 */ + GstClockTime sync_send_time_remote; /* t1, might be -1 if FOLLOW_UP pending */ + GstClockTime follow_up_recv_time_local; + + GSource *timeout_source; + guint16 delay_req_seqnum; + GstClockTime delay_req_send_time_local; /* t3, -1 if we wait for FOLLOW_UP */ + GstClockTime delay_req_recv_time_remote; /* t4, -1 if we wait */ + GstClockTime delay_resp_recv_time_local; + + gint64 correction_field_sync; /* sum of the correction fields of SYNC/FOLLOW_UP */ + gint64 correction_field_delay; /* sum of the correction fields of DELAY_RESP */ +} PtpPendingSync; + +static void +ptp_pending_sync_free (PtpPendingSync * sync) +{ + if (sync->timeout_source) { + g_source_destroy (sync->timeout_source); + g_source_unref (sync->timeout_source); + } + g_free (sync); +} + +typedef struct +{ + guint domain; + + GstClockTime last_ptp_time; + GstClockTime last_local_time; + gint skipped_updates; + + /* Used for selecting the master/grandmaster */ + GList *announce_senders; + + /* Last selected master clock */ + gboolean have_master_clock; + PtpClockIdentity master_clock_identity; + guint64 grandmaster_identity; + + /* Last SYNC or FOLLOW_UP timestamp we received */ + GstClockTime last_ptp_sync_time; + GstClockTime sync_interval; + + GstClockTime mean_path_delay; + GstClockTime last_delay_req, min_delay_req_interval; + guint16 last_delay_req_seqnum; + + GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW]; + gint last_path_delays_missing; + + GQueue pending_syncs; + + GstClock *domain_clock; +} PtpDomainData; + +static GList *domain_data; +static GMutex domain_clocks_lock; +static GList *domain_clocks; + +/* Protected by PTP lock */ +static void emit_ptp_statistics (guint8 domain, const GstStructure * stats); +static GHookList domain_stats_hooks; +static gint domain_stats_n_hooks; +static gboolean domain_stats_hooks_initted = FALSE; + +/* Converts log2 seconds to GstClockTime */ +static GstClockTime +log2_to_clock_time (gint l) +{ + if (l < 0) + return GST_SECOND >> (-l); + else + return GST_SECOND << l; +} + +static void +dump_ptp_message (PtpMessage * msg) +{ + GST_TRACE ("PTP message:"); + GST_TRACE ("\ttransport_specific: %u", msg->transport_specific); + GST_TRACE ("\tmessage_type: 0x%01x", msg->message_type); + GST_TRACE ("\tversion_ptp: %u", msg->version_ptp); + GST_TRACE ("\tmessage_length: %u", msg->message_length); + GST_TRACE ("\tdomain_number: %u", msg->domain_number); + GST_TRACE ("\tflag_field: 0x%04x", msg->flag_field); + GST_TRACE ("\tcorrection_field: %" G_GINT64_FORMAT ".%03u", + (msg->correction_field / 65536), + (guint) ((msg->correction_field & 0xffff) * 1000) / 65536); + GST_TRACE ("\tsource_port_identity: 0x%016" G_GINT64_MODIFIER "x %u", + msg->source_port_identity.clock_identity, + msg->source_port_identity.port_number); + GST_TRACE ("\tsequence_id: %u", msg->sequence_id); + GST_TRACE ("\tcontrol_field: 0x%02x", msg->control_field); + GST_TRACE ("\tmessage_interval: %" GST_TIME_FORMAT, + GST_TIME_ARGS (log2_to_clock_time (msg->log_message_interval))); + + switch (msg->message_type) { + case PTP_MESSAGE_TYPE_ANNOUNCE: + GST_TRACE ("\tANNOUNCE:"); + GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u", + msg->message_specific.announce.origin_timestamp.seconds_field, + msg->message_specific.announce.origin_timestamp.nanoseconds_field); + GST_TRACE ("\t\tcurrent_utc_offset: %d", + msg->message_specific.announce.current_utc_offset); + GST_TRACE ("\t\tgrandmaster_priority_1: %u", + msg->message_specific.announce.grandmaster_priority_1); + GST_TRACE ("\t\tgrandmaster_clock_quality: 0x%02x 0x%02x %u", + msg->message_specific.announce.grandmaster_clock_quality.clock_class, + msg->message_specific.announce. + grandmaster_clock_quality.clock_accuracy, + msg->message_specific.announce. + grandmaster_clock_quality.offset_scaled_log_variance); + GST_TRACE ("\t\tgrandmaster_priority_2: %u", + msg->message_specific.announce.grandmaster_priority_2); + GST_TRACE ("\t\tgrandmaster_identity: 0x%016" G_GINT64_MODIFIER "x", + msg->message_specific.announce.grandmaster_identity); + GST_TRACE ("\t\tsteps_removed: %u", + msg->message_specific.announce.steps_removed); + GST_TRACE ("\t\ttime_source: 0x%02x", + msg->message_specific.announce.time_source); + break; + case PTP_MESSAGE_TYPE_SYNC: + GST_TRACE ("\tSYNC:"); + GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u", + msg->message_specific.sync.origin_timestamp.seconds_field, + msg->message_specific.sync.origin_timestamp.nanoseconds_field); + break; + case PTP_MESSAGE_TYPE_FOLLOW_UP: + GST_TRACE ("\tFOLLOW_UP:"); + GST_TRACE ("\t\tprecise_origin_timestamp: %" G_GUINT64_FORMAT ".%09u", + msg->message_specific.follow_up. + precise_origin_timestamp.seconds_field, + msg->message_specific.follow_up. + precise_origin_timestamp.nanoseconds_field); + break; + case PTP_MESSAGE_TYPE_DELAY_REQ: + GST_TRACE ("\tDELAY_REQ:"); + GST_TRACE ("\t\torigin_timestamp: %" G_GUINT64_FORMAT ".%09u", + msg->message_specific.delay_req.origin_timestamp.seconds_field, + msg->message_specific.delay_req.origin_timestamp.nanoseconds_field); + break; + case PTP_MESSAGE_TYPE_DELAY_RESP: + GST_TRACE ("\tDELAY_RESP:"); + GST_TRACE ("\t\treceive_timestamp: %" G_GUINT64_FORMAT ".%09u", + msg->message_specific.delay_resp.receive_timestamp.seconds_field, + msg->message_specific.delay_resp.receive_timestamp.nanoseconds_field); + GST_TRACE ("\t\trequesting_port_identity: 0x%016" G_GINT64_MODIFIER + "x %u", + msg->message_specific.delay_resp. + requesting_port_identity.clock_identity, + msg->message_specific.delay_resp. + requesting_port_identity.port_number); + break; + default: + break; + } + GST_TRACE (" "); +} + +/* IEEE 1588-2008 5.3.3 */ +static gboolean +parse_ptp_timestamp (PtpTimestamp * timestamp, GstByteReader * reader) +{ + g_return_val_if_fail (gst_byte_reader_get_remaining (reader) >= 10, FALSE); + + timestamp->seconds_field = + (((guint64) gst_byte_reader_get_uint32_be_unchecked (reader)) << 16) | + gst_byte_reader_get_uint16_be_unchecked (reader); + timestamp->nanoseconds_field = + gst_byte_reader_get_uint32_be_unchecked (reader); + + if (timestamp->nanoseconds_field >= 1000000000) + return FALSE; + + return TRUE; +} + +/* IEEE 1588-2008 13.3 */ +static gboolean +parse_ptp_message_header (PtpMessage * msg, GstByteReader * reader) +{ + guint8 b; + + g_return_val_if_fail (gst_byte_reader_get_remaining (reader) >= 34, FALSE); + + b = gst_byte_reader_get_uint8_unchecked (reader); + msg->transport_specific = b >> 4; + msg->message_type = b & 0x0f; + + b = gst_byte_reader_get_uint8_unchecked (reader); + msg->version_ptp = b & 0x0f; + if (msg->version_ptp != 2) { + GST_WARNING ("Unsupported PTP message version (%u != 2)", msg->version_ptp); + return FALSE; + } + + msg->message_length = gst_byte_reader_get_uint16_be_unchecked (reader); + if (gst_byte_reader_get_remaining (reader) + 4 < msg->message_length) { + GST_WARNING ("Not enough data (%u < %u)", + gst_byte_reader_get_remaining (reader) + 4, msg->message_length); + return FALSE; + } + + msg->domain_number = gst_byte_reader_get_uint8_unchecked (reader); + gst_byte_reader_skip_unchecked (reader, 1); + + msg->flag_field = gst_byte_reader_get_uint16_be_unchecked (reader); + msg->correction_field = gst_byte_reader_get_uint64_be_unchecked (reader); + gst_byte_reader_skip_unchecked (reader, 4); + + msg->source_port_identity.clock_identity = + gst_byte_reader_get_uint64_be_unchecked (reader); + msg->source_port_identity.port_number = + gst_byte_reader_get_uint16_be_unchecked (reader); + + msg->sequence_id = gst_byte_reader_get_uint16_be_unchecked (reader); + msg->control_field = gst_byte_reader_get_uint8_unchecked (reader); + msg->log_message_interval = gst_byte_reader_get_uint8_unchecked (reader); + + return TRUE; +} + +/* IEEE 1588-2008 13.5 */ +static gboolean +parse_ptp_message_announce (PtpMessage * msg, GstByteReader * reader) +{ + g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_ANNOUNCE, FALSE); + + if (gst_byte_reader_get_remaining (reader) < 20) + return FALSE; + + if (!parse_ptp_timestamp (&msg->message_specific.announce.origin_timestamp, + reader)) + return FALSE; + + msg->message_specific.announce.current_utc_offset = + gst_byte_reader_get_uint16_be_unchecked (reader); + gst_byte_reader_skip_unchecked (reader, 1); + + msg->message_specific.announce.grandmaster_priority_1 = + gst_byte_reader_get_uint8_unchecked (reader); + msg->message_specific.announce.grandmaster_clock_quality.clock_class = + gst_byte_reader_get_uint8_unchecked (reader); + msg->message_specific.announce.grandmaster_clock_quality.clock_accuracy = + gst_byte_reader_get_uint8_unchecked (reader); + msg->message_specific.announce. + grandmaster_clock_quality.offset_scaled_log_variance = + gst_byte_reader_get_uint16_be_unchecked (reader); + msg->message_specific.announce.grandmaster_priority_2 = + gst_byte_reader_get_uint8_unchecked (reader); + msg->message_specific.announce.grandmaster_identity = + gst_byte_reader_get_uint64_be_unchecked (reader); + msg->message_specific.announce.steps_removed = + gst_byte_reader_get_uint16_be_unchecked (reader); + msg->message_specific.announce.time_source = + gst_byte_reader_get_uint8_unchecked (reader); + + return TRUE; +} + +/* IEEE 1588-2008 13.6 */ +static gboolean +parse_ptp_message_sync (PtpMessage * msg, GstByteReader * reader) +{ + g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_SYNC, FALSE); + + if (gst_byte_reader_get_remaining (reader) < 10) + return FALSE; + + if (!parse_ptp_timestamp (&msg->message_specific.sync.origin_timestamp, + reader)) + return FALSE; + + return TRUE; +} + +/* IEEE 1588-2008 13.6 */ +static gboolean +parse_ptp_message_delay_req (PtpMessage * msg, GstByteReader * reader) +{ + g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_DELAY_REQ, FALSE); + + if (gst_byte_reader_get_remaining (reader) < 10) + return FALSE; + + if (!parse_ptp_timestamp (&msg->message_specific.delay_req.origin_timestamp, + reader)) + return FALSE; + + return TRUE; +} + +/* IEEE 1588-2008 13.7 */ +static gboolean +parse_ptp_message_follow_up (PtpMessage * msg, GstByteReader * reader) +{ + g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_FOLLOW_UP, FALSE); + + if (gst_byte_reader_get_remaining (reader) < 10) + return FALSE; + + if (!parse_ptp_timestamp (&msg->message_specific. + follow_up.precise_origin_timestamp, reader)) + return FALSE; + + return TRUE; +} + +/* IEEE 1588-2008 13.8 */ +static gboolean +parse_ptp_message_delay_resp (PtpMessage * msg, GstByteReader * reader) +{ + g_return_val_if_fail (msg->message_type == PTP_MESSAGE_TYPE_DELAY_RESP, + FALSE); + + if (gst_byte_reader_get_remaining (reader) < 20) + return FALSE; + + if (!parse_ptp_timestamp (&msg->message_specific.delay_resp.receive_timestamp, + reader)) + return FALSE; + + msg->message_specific.delay_resp.requesting_port_identity.clock_identity = + gst_byte_reader_get_uint64_be_unchecked (reader); + msg->message_specific.delay_resp.requesting_port_identity.port_number = + gst_byte_reader_get_uint16_be_unchecked (reader); + + return TRUE; +} + +static gboolean +parse_ptp_message (PtpMessage * msg, const guint8 * data, gsize size) +{ + GstByteReader reader; + gboolean ret = FALSE; + + gst_byte_reader_init (&reader, data, size); + + if (!parse_ptp_message_header (msg, &reader)) { + GST_WARNING ("Failed to parse PTP message header"); + return FALSE; + } + + switch (msg->message_type) { + case PTP_MESSAGE_TYPE_SYNC: + ret = parse_ptp_message_sync (msg, &reader); + break; + case PTP_MESSAGE_TYPE_FOLLOW_UP: + ret = parse_ptp_message_follow_up (msg, &reader); + break; + case PTP_MESSAGE_TYPE_DELAY_REQ: + ret = parse_ptp_message_delay_req (msg, &reader); + break; + case PTP_MESSAGE_TYPE_DELAY_RESP: + ret = parse_ptp_message_delay_resp (msg, &reader); + break; + case PTP_MESSAGE_TYPE_ANNOUNCE: + ret = parse_ptp_message_announce (msg, &reader); + break; + default: + /* ignore for now */ + break; + } + + return ret; +} + +static gint +compare_announce_message (const PtpAnnounceMessage * a, + const PtpAnnounceMessage * b) +{ + /* IEEE 1588 Figure 27 */ + if (a->grandmaster_identity == b->grandmaster_identity) { + if (a->steps_removed + 1 < b->steps_removed) + return -1; + else if (a->steps_removed > b->steps_removed + 1) + return 1; + + /* Error cases are filtered out earlier */ + if (a->steps_removed < b->steps_removed) + return -1; + else if (a->steps_removed > b->steps_removed) + return 1; + + /* Error cases are filtered out earlier */ + if (a->master_clock_identity.clock_identity < + b->master_clock_identity.clock_identity) + return -1; + else if (a->master_clock_identity.clock_identity > + b->master_clock_identity.clock_identity) + return 1; + + /* Error cases are filtered out earlier */ + if (a->master_clock_identity.port_number < + b->master_clock_identity.port_number) + return -1; + else if (a->master_clock_identity.port_number > + b->master_clock_identity.port_number) + return 1; + else + g_assert_not_reached (); + + return 0; + } + + if (a->grandmaster_priority_1 < b->grandmaster_priority_1) + return -1; + else if (a->grandmaster_priority_1 > b->grandmaster_priority_1) + return 1; + + if (a->grandmaster_clock_quality.clock_class < + b->grandmaster_clock_quality.clock_class) + return -1; + else if (a->grandmaster_clock_quality.clock_class > + b->grandmaster_clock_quality.clock_class) + return 1; + + if (a->grandmaster_clock_quality.clock_accuracy < + b->grandmaster_clock_quality.clock_accuracy) + return -1; + else if (a->grandmaster_clock_quality.clock_accuracy > + b->grandmaster_clock_quality.clock_accuracy) + return 1; + + if (a->grandmaster_clock_quality.offset_scaled_log_variance < + b->grandmaster_clock_quality.offset_scaled_log_variance) + return -1; + else if (a->grandmaster_clock_quality.offset_scaled_log_variance > + b->grandmaster_clock_quality.offset_scaled_log_variance) + return 1; + + if (a->grandmaster_priority_2 < b->grandmaster_priority_2) + return -1; + else if (a->grandmaster_priority_2 > b->grandmaster_priority_2) + return 1; + + if (a->grandmaster_identity < b->grandmaster_identity) + return -1; + else if (a->grandmaster_identity > b->grandmaster_identity) + return 1; + else + g_assert_not_reached (); + + return 0; +} + +static void +select_best_master_clock (PtpDomainData * domain, GstClockTime now) +{ + GList *qualified_messages = NULL; + GList *l, *m; + PtpAnnounceMessage *best = NULL; + + /* IEEE 1588 9.3.2.5 */ + for (l = domain->announce_senders; l; l = l->next) { + PtpAnnounceSender *sender = l->data; + GstClockTime window = 4 * sender->announce_interval; + gint count = 0; + + for (m = sender->announce_messages.head; m; m = m->next) { + PtpAnnounceMessage *msg = m->data; + + if (now - msg->receive_time <= window) + count++; + } + + /* Only include the newest message of announce senders that had at least 2 + * announce messages in the last 4 announce intervals. Which also means + * that we wait at least 4 announce intervals before we select a master + * clock. Until then we just report based on the newest SYNC we received + */ + if (count >= 2) { + qualified_messages = + g_list_prepend (qualified_messages, + g_queue_peek_tail (&sender->announce_messages)); + } + } + + if (!qualified_messages) { + GST_DEBUG + ("No qualified announce messages for domain %u, can't select a master clock", + domain->domain); + domain->have_master_clock = FALSE; + return; + } + + for (l = qualified_messages; l; l = l->next) { + PtpAnnounceMessage *msg = l->data; + + if (!best || compare_announce_message (msg, best) < 0) + best = msg; + } + + if (domain->have_master_clock + && compare_clock_identity (&domain->master_clock_identity, + &best->master_clock_identity) == 0) { + GST_DEBUG ("Master clock in domain %u did not change", domain->domain); + } else { + GST_DEBUG ("Selected master clock for domain %u: 0x%016" G_GINT64_MODIFIER + "x %u with grandmaster clock 0x%016" G_GINT64_MODIFIER "x", + domain->domain, best->master_clock_identity.clock_identity, + best->master_clock_identity.port_number, best->grandmaster_identity); + + domain->have_master_clock = TRUE; + domain->grandmaster_identity = best->grandmaster_identity; + + /* Opportunistic master clock selection likely gave us the same master + * clock before, no need to reset all statistics */ + if (compare_clock_identity (&domain->master_clock_identity, + &best->master_clock_identity) != 0) { + memcpy (&domain->master_clock_identity, &best->master_clock_identity, + sizeof (PtpClockIdentity)); + domain->mean_path_delay = 0; + domain->last_delay_req = 0; + domain->last_path_delays_missing = 9; + domain->min_delay_req_interval = 0; + domain->sync_interval = 0; + domain->last_ptp_sync_time = 0; + domain->skipped_updates = 0; + g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free, + NULL); + g_queue_clear (&domain->pending_syncs); + } + + if (g_atomic_int_get (&domain_stats_n_hooks)) { + GstStructure *stats = + gst_structure_new (GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED, + "domain", G_TYPE_UINT, domain->domain, + "master-clock-id", G_TYPE_UINT64, + domain->master_clock_identity.clock_identity, + "master-clock-port", G_TYPE_UINT, + domain->master_clock_identity.port_number, + "grandmaster-clock-id", G_TYPE_UINT64, domain->grandmaster_identity, + NULL); + emit_ptp_statistics (domain->domain, stats); + gst_structure_free (stats); + } + } +} + +static void +handle_announce_message (PtpMessage * msg, GstClockTime receive_time) +{ + GList *l; + PtpDomainData *domain = NULL; + PtpAnnounceSender *sender = NULL; + PtpAnnounceMessage *announce; + + /* IEEE1588 9.3.2.2 e) + * Don't consider messages with the alternate master flag set + */ + if ((msg->flag_field & 0x0100)) + return; + + /* IEEE 1588 9.3.2.5 d) + * Don't consider announce messages with steps_removed>=255 + */ + if (msg->message_specific.announce.steps_removed >= 255) + return; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *tmp = l->data; + + if (tmp->domain == msg->domain_number) { + domain = tmp; + break; + } + } + + if (!domain) { + gchar *clock_name; + + domain = g_new0 (PtpDomainData, 1); + domain->domain = msg->domain_number; + clock_name = g_strdup_printf ("ptp-clock-%u", domain->domain); + domain->domain_clock = + g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", clock_name, NULL); + gst_object_ref_sink (domain->domain_clock); + g_free (clock_name); + g_queue_init (&domain->pending_syncs); + domain->last_path_delays_missing = 9; + domain_data = g_list_prepend (domain_data, domain); + + g_mutex_lock (&domain_clocks_lock); + domain_clocks = g_list_prepend (domain_clocks, domain); + g_mutex_unlock (&domain_clocks_lock); + + if (g_atomic_int_get (&domain_stats_n_hooks)) { + GstStructure *stats = + gst_structure_new (GST_PTP_STATISTICS_NEW_DOMAIN_FOUND, "domain", + G_TYPE_UINT, domain->domain, "clock", GST_TYPE_CLOCK, + domain->domain_clock, NULL); + emit_ptp_statistics (domain->domain, stats); + gst_structure_free (stats); + } + } + + for (l = domain->announce_senders; l; l = l->next) { + PtpAnnounceSender *tmp = l->data; + + if (compare_clock_identity (&tmp->master_clock_identity, + &msg->source_port_identity) == 0) { + sender = tmp; + break; + } + } + + if (!sender) { + sender = g_new0 (PtpAnnounceSender, 1); + + memcpy (&sender->master_clock_identity, &msg->source_port_identity, + sizeof (PtpClockIdentity)); + g_queue_init (&sender->announce_messages); + domain->announce_senders = + g_list_prepend (domain->announce_senders, sender); + } + + for (l = sender->announce_messages.head; l; l = l->next) { + PtpAnnounceMessage *tmp = l->data; + + /* IEEE 1588 9.3.2.5 c) + * Don't consider identical messages, i.e. duplicates + */ + if (tmp->sequence_id == msg->sequence_id) + return; + } + + sender->announce_interval = log2_to_clock_time (msg->log_message_interval); + + announce = g_new0 (PtpAnnounceMessage, 1); + announce->receive_time = receive_time; + announce->sequence_id = msg->sequence_id; + memcpy (&announce->master_clock_identity, &msg->source_port_identity, + sizeof (PtpClockIdentity)); + announce->grandmaster_identity = + msg->message_specific.announce.grandmaster_identity; + announce->grandmaster_priority_1 = + msg->message_specific.announce.grandmaster_priority_1; + announce->grandmaster_clock_quality.clock_class = + msg->message_specific.announce.grandmaster_clock_quality.clock_class; + announce->grandmaster_clock_quality.clock_accuracy = + msg->message_specific.announce.grandmaster_clock_quality.clock_accuracy; + announce->grandmaster_clock_quality.offset_scaled_log_variance = + msg->message_specific.announce. + grandmaster_clock_quality.offset_scaled_log_variance; + announce->grandmaster_priority_2 = + msg->message_specific.announce.grandmaster_priority_2; + announce->steps_removed = msg->message_specific.announce.steps_removed; + announce->time_source = msg->message_specific.announce.time_source; + g_queue_push_tail (&sender->announce_messages, announce); + + select_best_master_clock (domain, receive_time); +} + +static gboolean +send_delay_req_timeout (PtpPendingSync * sync) +{ + StdIOHeader header = { 0, }; + guint8 delay_req[44]; + GstByteWriter writer; + GIOStatus status; + gsize written; + GError *err = NULL; + + header.type = TYPE_EVENT; + header.size = 44; + + gst_byte_writer_init_with_data (&writer, delay_req, 44, FALSE); + gst_byte_writer_put_uint8_unchecked (&writer, PTP_MESSAGE_TYPE_DELAY_REQ); + gst_byte_writer_put_uint8_unchecked (&writer, 2); + gst_byte_writer_put_uint16_be_unchecked (&writer, 44); + gst_byte_writer_put_uint8_unchecked (&writer, sync->domain); + gst_byte_writer_put_uint8_unchecked (&writer, 0); + gst_byte_writer_put_uint16_be_unchecked (&writer, 0); + gst_byte_writer_put_uint64_be_unchecked (&writer, 0); + gst_byte_writer_put_uint32_be_unchecked (&writer, 0); + gst_byte_writer_put_uint64_be_unchecked (&writer, + ptp_clock_id.clock_identity); + gst_byte_writer_put_uint16_be_unchecked (&writer, ptp_clock_id.port_number); + gst_byte_writer_put_uint16_be_unchecked (&writer, sync->delay_req_seqnum); + gst_byte_writer_put_uint8_unchecked (&writer, 0x01); + gst_byte_writer_put_uint8_unchecked (&writer, 0x7f); + gst_byte_writer_put_uint64_be_unchecked (&writer, 0); + gst_byte_writer_put_uint16_be_unchecked (&writer, 0); + + status = + g_io_channel_write_chars (stdout_channel, (gchar *) & header, + sizeof (header), &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_warning ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + return G_SOURCE_REMOVE; + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status != G_IO_STATUS_NORMAL) { + g_warning ("Unexpected stdout write status: %d", status); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (written != sizeof (header)) { + g_warning ("Unexpected write size: %" G_GSIZE_FORMAT, written); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + + sync->delay_req_send_time_local = + gst_clock_get_time (observation_system_clock); + + status = + g_io_channel_write_chars (stdout_channel, + (const gchar *) delay_req, 44, &written, &err); + if (status == G_IO_STATUS_ERROR) { + g_warning ("Failed to write to stdout: %s", err->message); + g_clear_error (&err); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status == G_IO_STATUS_EOF) { + g_message ("EOF on stdout"); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status != G_IO_STATUS_NORMAL) { + g_warning ("Unexpected stdout write status: %d", status); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (written != 44) { + g_warning ("Unexpected write size: %" G_GSIZE_FORMAT, written); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + + return G_SOURCE_REMOVE; +} + +static gboolean +send_delay_req (PtpDomainData * domain, PtpPendingSync * sync) +{ + GstClockTime now = gst_clock_get_time (observation_system_clock); + guint timeout; + GSource *timeout_source; + + if (domain->last_delay_req != 0 + && domain->last_delay_req + domain->min_delay_req_interval > now) + return FALSE; + + domain->last_delay_req = now; + sync->delay_req_seqnum = domain->last_delay_req_seqnum++; + + /* IEEE 1588 9.5.11.2 */ + if (domain->last_delay_req == 0 || domain->min_delay_req_interval == 0) + timeout = 0; + else + timeout = + g_rand_int_range (delay_req_rand, 0, + (domain->min_delay_req_interval * 2) / GST_MSECOND); + + sync->timeout_source = timeout_source = g_timeout_source_new (timeout); + g_source_set_priority (timeout_source, G_PRIORITY_DEFAULT); + g_source_set_callback (timeout_source, (GSourceFunc) send_delay_req_timeout, + sync, NULL); + g_source_attach (timeout_source, main_context); + + return TRUE; +} + +/* Filtering of outliers for RTT and time calculations inspired + * by the code from gstnetclientclock.c + */ +static void +update_ptp_time (PtpDomainData * domain, PtpPendingSync * sync) +{ + GstClockTime internal_time, external_time, rate_num, rate_den; + GstClockTime corrected_ptp_time, corrected_local_time; + gdouble r_squared = 0.0; + gboolean synced; + GstClockTimeDiff discont = 0; + GstClockTime estimated_ptp_time = GST_CLOCK_TIME_NONE; +#ifdef USE_MEASUREMENT_FILTERING + GstClockTime orig_internal_time, orig_external_time, orig_rate_num, + orig_rate_den; + GstClockTime new_estimated_ptp_time; + GstClockTime max_discont, estimated_ptp_time_min, estimated_ptp_time_max; + gboolean now_synced; +#endif + +#ifdef USE_ONLY_SYNC_WITH_DELAY + GstClockTime mean_path_delay; + + if (sync->delay_req_send_time_local == GST_CLOCK_TIME_NONE) + return; + + /* IEEE 1588 11.3 */ + mean_path_delay = + (sync->delay_req_recv_time_remote - sync->sync_send_time_remote + + sync->sync_recv_time_local - sync->delay_req_send_time_local - + (sync->correction_field_sync + sync->correction_field_delay + + 32768) / 65536) / 2; +#endif + + /* IEEE 1588 11.2 */ + corrected_ptp_time = + sync->sync_send_time_remote + + (sync->correction_field_sync + 32768) / 65536; + +#ifdef USE_ONLY_SYNC_WITH_DELAY + corrected_local_time = sync->sync_recv_time_local - mean_path_delay; +#else + corrected_local_time = sync->sync_recv_time_local - domain->mean_path_delay; +#endif + +#ifdef USE_MEASUREMENT_FILTERING + /* We check this here and when updating the mean path delay, because + * we can get here without a delay response too */ + if (sync->follow_up_recv_time_local != GST_CLOCK_TIME_NONE + && sync->follow_up_recv_time_local > + sync->sync_recv_time_local + 2 * domain->mean_path_delay) { + GST_WARNING ("Sync-follow-up delay for domain %u too big: %" GST_TIME_FORMAT + " > 2 * %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (sync->follow_up_recv_time_local), + GST_TIME_ARGS (domain->mean_path_delay)); + synced = FALSE; + gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock), + &internal_time, &external_time, &rate_num, &rate_den); + goto out; + } +#endif + + /* Set an initial local-remote relation */ + if (domain->last_ptp_time == 0) + gst_clock_set_calibration (domain->domain_clock, corrected_local_time, + corrected_ptp_time, 1, 1); + +#ifdef USE_MEASUREMENT_FILTERING + /* Check if the corrected PTP time is +/- 3/4 RTT around what we would + * estimate with our present knowledge about the clock + */ + /* Store what the clock produced as 'now' before this update */ + gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock), + &orig_internal_time, &orig_external_time, &orig_rate_num, &orig_rate_den); + internal_time = orig_internal_time; + external_time = orig_external_time; + rate_num = orig_rate_num; + rate_den = orig_rate_den; + + /* 3/4 RTT window around the estimation */ + max_discont = domain->mean_path_delay * 3 / 2; + + /* Check if the estimated sync time is inside our window */ + estimated_ptp_time_min = corrected_local_time - max_discont; + estimated_ptp_time_min = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (domain->domain_clock), + estimated_ptp_time_min, internal_time, external_time, rate_num, rate_den); + estimated_ptp_time_max = corrected_local_time + max_discont; + estimated_ptp_time_max = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST (domain->domain_clock), + estimated_ptp_time_max, internal_time, external_time, rate_num, rate_den); + + synced = (estimated_ptp_time_min < corrected_ptp_time + && corrected_ptp_time < estimated_ptp_time_max); + + GST_DEBUG ("Adding observation for domain %u: %" GST_TIME_FORMAT " - %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (corrected_ptp_time), GST_TIME_ARGS (corrected_local_time)); + + GST_DEBUG ("Synced %d: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, synced, GST_TIME_ARGS (estimated_ptp_time_min), + GST_TIME_ARGS (corrected_ptp_time), + GST_TIME_ARGS (estimated_ptp_time_max)); + + if (gst_clock_add_observation_unapplied (domain->domain_clock, + corrected_local_time, corrected_ptp_time, &r_squared, + &internal_time, &external_time, &rate_num, &rate_den)) { + GST_DEBUG ("Regression gave r_squared: %f", r_squared); + + /* Old estimated PTP time based on receive time and path delay */ + estimated_ptp_time = corrected_local_time; + estimated_ptp_time = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST + (domain->domain_clock), estimated_ptp_time, orig_internal_time, + orig_external_time, orig_rate_num, orig_rate_den); + + /* New estimated PTP time based on receive time and path delay */ + new_estimated_ptp_time = corrected_local_time; + new_estimated_ptp_time = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST + (domain->domain_clock), new_estimated_ptp_time, internal_time, + external_time, rate_num, rate_den); + + discont = GST_CLOCK_DIFF (estimated_ptp_time, new_estimated_ptp_time); + if (synced && ABS (discont) > max_discont) { + GstClockTimeDiff offset; + GST_DEBUG ("Too large a discont %s%" GST_TIME_FORMAT + ", clamping to 1/4 average RTT = %" GST_TIME_FORMAT, + (discont < 0 ? "-" : ""), GST_TIME_ARGS (ABS (discont)), + GST_TIME_ARGS (max_discont)); + if (discont > 0) { /* Too large a forward step - add a -ve offset */ + offset = max_discont - discont; + if (-offset > external_time) + external_time = 0; + else + external_time += offset; + } else { /* Too large a backward step - add a +ve offset */ + offset = -(max_discont + discont); + external_time += offset; + } + + discont += offset; + } else { + GST_DEBUG ("Discont %s%" GST_TIME_FORMAT " (max: %" GST_TIME_FORMAT ")", + (discont < 0 ? "-" : ""), GST_TIME_ARGS (ABS (discont)), + GST_TIME_ARGS (max_discont)); + } + + /* Check if the estimated sync time is now (still) inside our window */ + estimated_ptp_time_min = corrected_local_time - max_discont; + estimated_ptp_time_min = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST + (domain->domain_clock), estimated_ptp_time_min, internal_time, + external_time, rate_num, rate_den); + estimated_ptp_time_max = corrected_local_time + max_discont; + estimated_ptp_time_max = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST + (domain->domain_clock), estimated_ptp_time_max, internal_time, + external_time, rate_num, rate_den); + + now_synced = (estimated_ptp_time_min < corrected_ptp_time + && corrected_ptp_time < estimated_ptp_time_max); + + GST_DEBUG ("Now synced %d: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, now_synced, GST_TIME_ARGS (estimated_ptp_time_min), + GST_TIME_ARGS (corrected_ptp_time), + GST_TIME_ARGS (estimated_ptp_time_max)); + + if (synced || now_synced || domain->skipped_updates > MAX_SKIPPED_UPDATES) { + gst_clock_set_calibration (GST_CLOCK_CAST (domain->domain_clock), + internal_time, external_time, rate_num, rate_den); + domain->skipped_updates = 0; + + domain->last_ptp_time = corrected_ptp_time; + domain->last_local_time = corrected_local_time; + } else { + domain->skipped_updates++; + } + } else { + domain->last_ptp_time = corrected_ptp_time; + domain->last_local_time = corrected_local_time; + } + +#else + GST_DEBUG ("Adding observation for domain %u: %" GST_TIME_FORMAT " - %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (corrected_ptp_time), GST_TIME_ARGS (corrected_local_time)); + + gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock), + &internal_time, &external_time, &rate_num, &rate_den); + + estimated_ptp_time = corrected_local_time; + estimated_ptp_time = + gst_clock_adjust_with_calibration (GST_CLOCK_CAST + (domain->domain_clock), estimated_ptp_time, internal_time, + external_time, rate_num, rate_den); + + gst_clock_add_observation (domain->domain_clock, + corrected_local_time, corrected_ptp_time, &r_squared); + + gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock), + &internal_time, &external_time, &rate_num, &rate_den); + + synced = TRUE; + domain->last_ptp_time = corrected_ptp_time; + domain->last_local_time = corrected_local_time; +#endif + +#ifdef USE_MEASUREMENT_FILTERING +out: +#endif + if (g_atomic_int_get (&domain_stats_n_hooks)) { + GstStructure *stats = gst_structure_new (GST_PTP_STATISTICS_TIME_UPDATED, + "domain", G_TYPE_UINT, domain->domain, + "mean-path-delay-avg", GST_TYPE_CLOCK_TIME, domain->mean_path_delay, + "local-time", GST_TYPE_CLOCK_TIME, corrected_local_time, + "ptp-time", GST_TYPE_CLOCK_TIME, corrected_ptp_time, + "estimated-ptp-time", GST_TYPE_CLOCK_TIME, estimated_ptp_time, + "discontinuity", G_TYPE_INT64, discont, + "synced", G_TYPE_BOOLEAN, synced, + "r-squared", G_TYPE_DOUBLE, r_squared, + "internal-time", GST_TYPE_CLOCK_TIME, internal_time, + "external-time", GST_TYPE_CLOCK_TIME, external_time, + "rate-num", G_TYPE_UINT64, rate_num, + "rate-den", G_TYPE_UINT64, rate_den, + "rate", G_TYPE_DOUBLE, (gdouble) (rate_num) / rate_den, + NULL); + emit_ptp_statistics (domain->domain, stats); + gst_structure_free (stats); + } + +} + +#ifdef USE_MEDIAN_PRE_FILTERING +static gint +compare_clock_time (const GstClockTime * a, const GstClockTime * b) +{ + if (*a < *b) + return -1; + else if (*a > *b) + return 1; + return 0; +} +#endif + +static gboolean +update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync) +{ +#ifdef USE_MEDIAN_PRE_FILTERING + GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW]; + GstClockTime median; + gint i; +#endif + + GstClockTime mean_path_delay, delay_req_delay = 0; + gboolean ret; + + /* IEEE 1588 11.3 */ + mean_path_delay = + (sync->delay_req_recv_time_remote - sync->sync_send_time_remote + + sync->sync_recv_time_local - sync->delay_req_send_time_local - + (sync->correction_field_sync + sync->correction_field_delay + + 32768) / 65536) / 2; + +#ifdef USE_MEDIAN_PRE_FILTERING + for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++) + domain->last_path_delays[i - 1] = domain->last_path_delays[i]; + domain->last_path_delays[i - 1] = mean_path_delay; + + if (domain->last_path_delays_missing) { + domain->last_path_delays_missing--; + } else { + memcpy (&last_path_delays, &domain->last_path_delays, + sizeof (last_path_delays)); + g_qsort_with_data (&last_path_delays, + MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime), + (GCompareDataFunc) compare_clock_time, NULL); + + median = last_path_delays[MEDIAN_PRE_FILTERING_WINDOW / 2]; + + /* FIXME: We might want to use something else here, like only allowing + * things in the interquartile range, or also filtering away delays that + * are too small compared to the median. This here worked well enough + * in tests so far. + */ + if (mean_path_delay > 2 * median) { + GST_WARNING ("Path delay for domain %u too big compared to median: %" + GST_TIME_FORMAT " > 2 * %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (mean_path_delay), GST_TIME_ARGS (median)); + ret = FALSE; + goto out; + } + } +#endif + +#ifdef USE_RUNNING_AVERAGE_DELAY + /* Track an average round trip time, for a bit of smoothing */ + /* Always update before discarding a sample, so genuine changes in + * the network get picked up, eventually */ + if (domain->mean_path_delay == 0) + domain->mean_path_delay = mean_path_delay; + else if (mean_path_delay < domain->mean_path_delay) /* Shorter RTTs carry more weight than longer */ + domain->mean_path_delay = + (3 * domain->mean_path_delay + mean_path_delay) / 4; + else + domain->mean_path_delay = + (15 * domain->mean_path_delay + mean_path_delay) / 16; +#else + domain->mean_path_delay = mean_path_delay; +#endif + +#ifdef USE_MEASUREMENT_FILTERING + if (sync->follow_up_recv_time_local != GST_CLOCK_TIME_NONE && + domain->mean_path_delay != 0 + && sync->follow_up_recv_time_local > + sync->sync_recv_time_local + 2 * domain->mean_path_delay) { + GST_WARNING ("Sync-follow-up delay for domain %u too big: %" GST_TIME_FORMAT + " > 2 * %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (sync->follow_up_recv_time_local - + sync->sync_recv_time_local), + GST_TIME_ARGS (domain->mean_path_delay)); + ret = FALSE; + goto out; + } + + if (mean_path_delay > 2 * domain->mean_path_delay) { + GST_WARNING ("Mean path delay for domain %u too big: %" GST_TIME_FORMAT + " > 2 * %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (mean_path_delay), + GST_TIME_ARGS (domain->mean_path_delay)); + ret = FALSE; + goto out; + } +#endif + + delay_req_delay = + sync->delay_resp_recv_time_local - sync->delay_req_send_time_local; + +#ifdef USE_MEASUREMENT_FILTERING + /* delay_req_delay is a RTT, so 2 times the path delay */ + if (delay_req_delay > 4 * domain->mean_path_delay) { + GST_WARNING ("Delay-request-response delay for domain %u too big: %" + GST_TIME_FORMAT " > 4 * %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (delay_req_delay), + GST_TIME_ARGS (domain->mean_path_delay)); + ret = FALSE; + goto out; + } +#endif + + ret = TRUE; + + GST_DEBUG ("Got mean path delay for domain %u: %" GST_TIME_FORMAT " (new: %" + GST_TIME_FORMAT ")", domain->domain, + GST_TIME_ARGS (domain->mean_path_delay), GST_TIME_ARGS (mean_path_delay)); + GST_DEBUG ("Delay request delay for domain %u: %" GST_TIME_FORMAT, + domain->domain, GST_TIME_ARGS (delay_req_delay)); + +#if defined(USE_MEASUREMENT_FILTERING) || defined(USE_MEDIAN_PRE_FILTERING) +out: +#endif + if (g_atomic_int_get (&domain_stats_n_hooks)) { + GstStructure *stats = + gst_structure_new (GST_PTP_STATISTICS_PATH_DELAY_MEASURED, + "domain", G_TYPE_UINT, domain->domain, + "mean-path-delay-avg", GST_TYPE_CLOCK_TIME, domain->mean_path_delay, + "mean-path-delay", GST_TYPE_CLOCK_TIME, mean_path_delay, + "delay-request-delay", GST_TYPE_CLOCK_TIME, delay_req_delay, NULL); + emit_ptp_statistics (domain->domain, stats); + gst_structure_free (stats); + } + + return ret; +} + +static void +handle_sync_message (PtpMessage * msg, GstClockTime receive_time) +{ + GList *l; + PtpDomainData *domain = NULL; + PtpPendingSync *sync = NULL; + + /* Don't consider messages with the alternate master flag set */ + if ((msg->flag_field & 0x0100)) + return; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *tmp = l->data; + + if (msg->domain_number == tmp->domain) { + domain = tmp; + break; + } + } + + if (!domain) { + gchar *clock_name; + + domain = g_new0 (PtpDomainData, 1); + domain->domain = msg->domain_number; + clock_name = g_strdup_printf ("ptp-clock-%u", domain->domain); + domain->domain_clock = + g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", clock_name, NULL); + gst_object_ref_sink (domain->domain_clock); + g_free (clock_name); + g_queue_init (&domain->pending_syncs); + domain->last_path_delays_missing = 9; + domain_data = g_list_prepend (domain_data, domain); + + g_mutex_lock (&domain_clocks_lock); + domain_clocks = g_list_prepend (domain_clocks, domain); + g_mutex_unlock (&domain_clocks_lock); + } + + /* If we have a master clock, ignore this message if it's not coming from there */ + if (domain->have_master_clock + && compare_clock_identity (&domain->master_clock_identity, + &msg->source_port_identity) != 0) + return; + +#ifdef USE_OPPORTUNISTIC_CLOCK_SELECTION + /* Opportunistic selection of master clock */ + if (!domain->have_master_clock) + memcpy (&domain->master_clock_identity, &msg->source_port_identity, + sizeof (PtpClockIdentity)); +#else + if (!domain->have_master_clock) + return; +#endif + + domain->sync_interval = log2_to_clock_time (msg->log_message_interval); + + /* Check if duplicated */ + for (l = domain->pending_syncs.head; l; l = l->next) { + PtpPendingSync *tmp = l->data; + + if (tmp->sync_seqnum == msg->sequence_id) + return; + } + + if (msg->message_specific.sync.origin_timestamp.seconds_field > + GST_CLOCK_TIME_NONE / GST_SECOND) { + GST_FIXME ("Unsupported sync message seconds field value: %" + G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT, + msg->message_specific.sync.origin_timestamp.seconds_field, + GST_CLOCK_TIME_NONE / GST_SECOND); + return; + } + + sync = g_new0 (PtpPendingSync, 1); + sync->domain = domain->domain; + sync->sync_seqnum = msg->sequence_id; + sync->sync_recv_time_local = receive_time; + sync->sync_send_time_remote = GST_CLOCK_TIME_NONE; + sync->follow_up_recv_time_local = GST_CLOCK_TIME_NONE; + sync->delay_req_send_time_local = GST_CLOCK_TIME_NONE; + sync->delay_req_recv_time_remote = GST_CLOCK_TIME_NONE; + sync->delay_resp_recv_time_local = GST_CLOCK_TIME_NONE; + + /* 0.5 correction factor for division later */ + sync->correction_field_sync = msg->correction_field; + + if ((msg->flag_field & 0x0200)) { + /* Wait for FOLLOW_UP */ + } else { + sync->sync_send_time_remote = + PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific. + sync.origin_timestamp); + + if (domain->last_ptp_sync_time != 0 + && domain->last_ptp_sync_time >= sync->sync_send_time_remote) { + GST_WARNING ("Backwards PTP times in domain %u: %" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (domain->last_ptp_sync_time), + GST_TIME_ARGS (sync->sync_send_time_remote)); + ptp_pending_sync_free (sync); + sync = NULL; + return; + } + domain->last_ptp_sync_time = sync->sync_send_time_remote; + + if (send_delay_req (domain, sync)) { + /* Sent delay request */ + } else { + update_ptp_time (domain, sync); + ptp_pending_sync_free (sync); + sync = NULL; + } + } + + if (sync) + g_queue_push_tail (&domain->pending_syncs, sync); +} + +static void +handle_follow_up_message (PtpMessage * msg, GstClockTime receive_time) +{ + GList *l; + PtpDomainData *domain = NULL; + PtpPendingSync *sync = NULL; + + /* Don't consider messages with the alternate master flag set */ + if ((msg->flag_field & 0x0100)) + return; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *tmp = l->data; + + if (msg->domain_number == tmp->domain) { + domain = tmp; + break; + } + } + + if (!domain) + return; + + /* If we have a master clock, ignore this message if it's not coming from there */ + if (domain->have_master_clock + && compare_clock_identity (&domain->master_clock_identity, + &msg->source_port_identity) != 0) + return; + + /* Check if we know about this one */ + for (l = domain->pending_syncs.head; l; l = l->next) { + PtpPendingSync *tmp = l->data; + + if (tmp->sync_seqnum == msg->sequence_id) { + sync = tmp; + break; + } + } + + if (!sync) + return; + + /* Got a FOLLOW_UP for this already */ + if (sync->sync_send_time_remote != GST_CLOCK_TIME_NONE) + return; + + if (sync->sync_recv_time_local >= receive_time) { + GST_ERROR ("Got bogus follow up in domain %u: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (sync->sync_recv_time_local), + GST_TIME_ARGS (receive_time)); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); + return; + } + + sync->correction_field_sync += msg->correction_field; + sync->sync_send_time_remote = + PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific. + follow_up.precise_origin_timestamp); + sync->follow_up_recv_time_local = receive_time; + + if (domain->last_ptp_sync_time >= sync->sync_send_time_remote) { + GST_WARNING ("Backwards PTP times in domain %u: %" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (domain->last_ptp_sync_time), + GST_TIME_ARGS (sync->sync_send_time_remote)); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); + sync = NULL; + return; + } + domain->last_ptp_sync_time = sync->sync_send_time_remote; + + if (send_delay_req (domain, sync)) { + /* Sent delay request */ + } else { + update_ptp_time (domain, sync); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); + sync = NULL; + } +} + +static void +handle_delay_resp_message (PtpMessage * msg, GstClockTime receive_time) +{ + GList *l; + PtpDomainData *domain = NULL; + PtpPendingSync *sync = NULL; + + /* Don't consider messages with the alternate master flag set */ + if ((msg->flag_field & 0x0100)) + return; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *tmp = l->data; + + if (msg->domain_number == tmp->domain) { + domain = tmp; + break; + } + } + + if (!domain) + return; + + /* If we have a master clock, ignore this message if it's not coming from there */ + if (domain->have_master_clock + && compare_clock_identity (&domain->master_clock_identity, + &msg->source_port_identity) != 0) + return; + + /* Not for us */ + if (msg->message_specific.delay_resp. + requesting_port_identity.clock_identity != ptp_clock_id.clock_identity + || msg->message_specific.delay_resp. + requesting_port_identity.port_number != ptp_clock_id.port_number) + return; + + domain->min_delay_req_interval = + log2_to_clock_time (msg->log_message_interval); + + /* Check if we know about this one */ + for (l = domain->pending_syncs.head; l; l = l->next) { + PtpPendingSync *tmp = l->data; + + if (tmp->delay_req_seqnum == msg->sequence_id) { + sync = tmp; + break; + } + } + + if (!sync) + return; + + /* Got a DELAY_RESP for this already */ + if (sync->delay_req_recv_time_remote != GST_CLOCK_TIME_NONE) + return; + + if (sync->delay_req_send_time_local > receive_time) { + GST_ERROR ("Got bogus delay response in domain %u: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (sync->delay_req_send_time_local), + GST_TIME_ARGS (receive_time)); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); + return; + } + + sync->correction_field_delay = msg->correction_field; + + sync->delay_req_recv_time_remote = + PTP_TIMESTAMP_TO_GST_CLOCK_TIME (msg->message_specific. + delay_resp.receive_timestamp); + sync->delay_resp_recv_time_local = receive_time; + + if (domain->mean_path_delay != 0 + && sync->sync_send_time_remote > sync->delay_req_recv_time_remote) { + GST_WARNING ("Sync send time after delay req receive time for domain %u: %" + GST_TIME_FORMAT " > %" GST_TIME_FORMAT, domain->domain, + GST_TIME_ARGS (sync->sync_send_time_remote), + GST_TIME_ARGS (sync->delay_req_recv_time_remote)); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); + return; + } + + if (update_mean_path_delay (domain, sync)) + update_ptp_time (domain, sync); + g_queue_remove (&domain->pending_syncs, sync); + ptp_pending_sync_free (sync); +} + +static void +handle_ptp_message (PtpMessage * msg, GstClockTime receive_time) +{ + /* Ignore our own messages */ + if (msg->source_port_identity.clock_identity == ptp_clock_id.clock_identity && + msg->source_port_identity.port_number == ptp_clock_id.port_number) + return; + + switch (msg->message_type) { + case PTP_MESSAGE_TYPE_ANNOUNCE: + handle_announce_message (msg, receive_time); + break; + case PTP_MESSAGE_TYPE_SYNC: + handle_sync_message (msg, receive_time); + break; + case PTP_MESSAGE_TYPE_FOLLOW_UP: + handle_follow_up_message (msg, receive_time); + break; + case PTP_MESSAGE_TYPE_DELAY_RESP: + handle_delay_resp_message (msg, receive_time); + break; + default: + break; + } +} + +static gboolean +have_stdin_data_cb (GIOChannel * channel, GIOCondition condition, + gpointer user_data) +{ + GIOStatus status; + StdIOHeader header; + gchar buffer[8192]; + GError *err = NULL; + gsize read; + + if ((condition & G_IO_STATUS_EOF)) { + GST_ERROR ("Got EOF on stdin"); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + + status = + g_io_channel_read_chars (channel, (gchar *) & header, sizeof (header), + &read, &err); + if (status == G_IO_STATUS_ERROR) { + GST_ERROR ("Failed to read from stdin: %s", err->message); + g_clear_error (&err); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status == G_IO_STATUS_EOF) { + GST_ERROR ("Got EOF on stdin"); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status != G_IO_STATUS_NORMAL) { + GST_ERROR ("Unexpected stdin read status: %d", status); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (read != sizeof (header)) { + GST_ERROR ("Unexpected read size: %" G_GSIZE_FORMAT, read); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (header.size > 8192) { + GST_ERROR ("Unexpected size: %u", header.size); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + + status = g_io_channel_read_chars (channel, buffer, header.size, &read, &err); + if (status == G_IO_STATUS_ERROR) { + GST_ERROR ("Failed to read from stdin: %s", err->message); + g_clear_error (&err); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status == G_IO_STATUS_EOF) { + GST_ERROR ("EOF on stdin"); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (status != G_IO_STATUS_NORMAL) { + GST_ERROR ("Unexpected stdin read status: %d", status); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } else if (read != header.size) { + GST_ERROR ("Unexpected read size: %" G_GSIZE_FORMAT, read); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + + switch (header.type) { + case TYPE_EVENT: + case TYPE_GENERAL:{ + GstClockTime receive_time = gst_clock_get_time (observation_system_clock); + PtpMessage msg; + + if (parse_ptp_message (&msg, (const guint8 *) buffer, header.size)) { + dump_ptp_message (&msg); + handle_ptp_message (&msg, receive_time); + } + break; + } + default: + case TYPE_CLOCK_ID:{ + if (header.size != 8) { + GST_ERROR ("Unexpected clock id size (%u != 8)", header.size); + g_main_loop_quit (main_loop); + return G_SOURCE_REMOVE; + } + g_mutex_lock (&ptp_lock); + ptp_clock_id.clock_identity = GST_READ_UINT64_BE (buffer); + ptp_clock_id.port_number = getpid (); + GST_DEBUG ("Got clock id 0x%016" G_GINT64_MODIFIER "x %u", + ptp_clock_id.clock_identity, ptp_clock_id.port_number); + g_cond_signal (&ptp_cond); + g_mutex_unlock (&ptp_lock); + break; + } + } + + return G_SOURCE_CONTINUE; +} + +/* Cleanup all announce messages and announce message senders + * that are timed out by now, and clean up all pending syncs + * that are missing their FOLLOW_UP or DELAY_RESP */ +static gboolean +cleanup_cb (gpointer data) +{ + GstClockTime now = gst_clock_get_time (observation_system_clock); + GList *l, *m, *n; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *domain = l->data; + + for (n = domain->announce_senders; n;) { + PtpAnnounceSender *sender = n->data; + gboolean timed_out = TRUE; + + /* Keep only 5 messages per sender around */ + while (g_queue_get_length (&sender->announce_messages) > 5) { + PtpAnnounceMessage *msg = g_queue_pop_head (&sender->announce_messages); + g_free (msg); + } + + for (m = sender->announce_messages.head; m; m = m->next) { + PtpAnnounceMessage *msg = m->data; + + if (msg->receive_time + + sender->announce_interval * PTP_ANNOUNCE_RECEIPT_TIMEOUT > now) { + timed_out = FALSE; + break; + } + } + + if (timed_out) { + GST_DEBUG ("Announce sender 0x%016" G_GINT64_MODIFIER "x %u timed out", + sender->master_clock_identity.clock_identity, + sender->master_clock_identity.port_number); + g_queue_foreach (&sender->announce_messages, (GFunc) g_free, NULL); + g_queue_clear (&sender->announce_messages); + } + + if (g_queue_get_length (&sender->announce_messages) == 0) { + GList *tmp = n->next; + + if (compare_clock_identity (&sender->master_clock_identity, + &domain->master_clock_identity) == 0) + GST_WARNING ("currently selected master clock timed out"); + g_free (sender); + domain->announce_senders = + g_list_delete_link (domain->announce_senders, n); + n = tmp; + } else { + n = n->next; + } + } + select_best_master_clock (domain, now); + + /* Clean up any pending syncs */ + for (n = domain->pending_syncs.head; n;) { + PtpPendingSync *sync = n->data; + gboolean timed_out = FALSE; + + /* Time out pending syncs after 4 sync intervals or 10 seconds, + * and pending delay reqs after 4 delay req intervals or 10 seconds + */ + if (sync->delay_req_send_time_local != GST_CLOCK_TIME_NONE && + ((domain->min_delay_req_interval != 0 + && sync->delay_req_send_time_local + + 4 * domain->min_delay_req_interval < now) + || (sync->delay_req_send_time_local + 10 * GST_SECOND < now))) { + timed_out = TRUE; + } else if ((domain->sync_interval != 0 + && sync->sync_recv_time_local + 4 * domain->sync_interval < now) + || (sync->sync_recv_time_local + 10 * GST_SECOND < now)) { + timed_out = TRUE; + } + + if (timed_out) { + GList *tmp = n->next; + ptp_pending_sync_free (sync); + g_queue_delete_link (&domain->pending_syncs, n); + n = tmp; + } else { + n = n->next; + } + } + } + + return G_SOURCE_CONTINUE; +} + +static gpointer +ptp_helper_main (gpointer data) +{ + GSource *cleanup_source; + + GST_DEBUG ("Starting PTP helper loop"); + + /* Check all 5 seconds, if we have to cleanup ANNOUNCE or pending syncs message */ + cleanup_source = g_timeout_source_new_seconds (5); + g_source_set_priority (cleanup_source, G_PRIORITY_DEFAULT); + g_source_set_callback (cleanup_source, (GSourceFunc) cleanup_cb, NULL, NULL); + g_source_attach (cleanup_source, main_context); + g_source_unref (cleanup_source); + + g_main_loop_run (main_loop); + GST_DEBUG ("Stopped PTP helper loop"); + + g_mutex_lock (&ptp_lock); + ptp_clock_id.clock_identity = GST_PTP_CLOCK_ID_NONE; + ptp_clock_id.port_number = 0; + initted = FALSE; + g_cond_signal (&ptp_cond); + g_mutex_unlock (&ptp_lock); + + return NULL; +} + +/** + * gst_ptp_is_supported: + * + * Check if PTP clocks are generally supported on this system, and if previous + * initializations did not fail. + * + * Returns: %TRUE if PTP clocks are generally supported on this system, and + * previous initializations did not fail. + * + * Since: 1.6 + */ +gboolean +gst_ptp_is_supported (void) +{ + return supported; +} + +/** + * gst_ptp_is_initialized: + * + * Check if the GStreamer PTP clock subsystem is initialized. + * + * Returns: %TRUE if the GStreamer PTP clock subsystem is intialized. + * + * Since: 1.6 + */ +gboolean +gst_ptp_is_initialized (void) +{ + return initted; +} + +/** + * gst_ptp_init: + * @clock_id: PTP clock id of this process' clock or %GST_PTP_CLOCK_ID_NONE + * @interfaces: (transfer none) (array zero-terminated=1) (allow-none): network interfaces to run the clock on + * + * Initialize the GStreamer PTP subsystem and create a PTP ordinary clock in + * slave-only mode for all domains on the given @interfaces with the + * given @clock_id. + * + * If @clock_id is %GST_PTP_CLOCK_ID_NONE, a clock id is automatically + * generated from the MAC address of the first network interface. + * + * This function is automatically called by gst_ptp_clock_new() with default + * parameters if it wasn't called before. + * + * Returns: %TRUE if the GStreamer PTP clock subsystem could be initialized. + * + * Since: 1.6 + */ +gboolean +gst_ptp_init (guint64 clock_id, gchar ** interfaces) +{ + gboolean ret; + const gchar *env; + gchar **argv = NULL; + gint argc, argc_c; + gint fd_r, fd_w; + GError *err = NULL; + GSource *stdin_source; + + GST_DEBUG_CATEGORY_INIT (ptp_debug, "ptp", 0, "PTP clock"); + + g_mutex_lock (&ptp_lock); + if (!supported) { + GST_ERROR ("PTP not supported"); + ret = FALSE; + goto done; + } + + if (initted) { + GST_DEBUG ("PTP already initialized"); + ret = TRUE; + goto done; + } + + if (ptp_helper_pid) { + GST_DEBUG ("PTP currently initializing"); + goto wait; + } + + if (!domain_stats_hooks_initted) { + g_hook_list_init (&domain_stats_hooks, sizeof (GHook)); + domain_stats_hooks_initted = TRUE; + } + + argc = 1; + if (clock_id != GST_PTP_CLOCK_ID_NONE) + argc += 2; + if (interfaces != NULL) + argc += 2 * g_strv_length (interfaces); + + argv = g_new0 (gchar *, argc + 2); + argc_c = 0; + + env = g_getenv ("GST_PTP_HELPER_1_0"); + if (env == NULL) + env = g_getenv ("GST_PTP_HELPER"); + if (env != NULL && *env != '\0') { + GST_LOG ("Trying GST_PTP_HELPER env var: %s", env); + argv[argc_c++] = g_strdup (env); + } else { + argv[argc_c++] = g_strdup (GST_PTP_HELPER_INSTALLED); + } + + if (clock_id != GST_PTP_CLOCK_ID_NONE) { + argv[argc_c++] = g_strdup ("-c"); + argv[argc_c++] = g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", clock_id); + } + + if (interfaces != NULL) { + gchar **ptr = interfaces; + + while (*ptr) { + argv[argc_c++] = g_strdup ("-i"); + argv[argc_c++] = g_strdup (*ptr); + ptr++; + } + } + + main_context = g_main_context_new (); + main_loop = g_main_loop_new (main_context, FALSE); + + ptp_helper_thread = + g_thread_try_new ("ptp-helper-thread", ptp_helper_main, NULL, &err); + if (!ptp_helper_thread) { + GST_ERROR ("Failed to start PTP helper thread: %s", err->message); + g_clear_error (&err); + ret = FALSE; + goto done; + } + + if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, + &ptp_helper_pid, &fd_w, &fd_r, NULL, &err)) { + GST_ERROR ("Failed to start ptp helper process: %s", err->message); + g_clear_error (&err); + ret = FALSE; + supported = FALSE; + goto done; + } + + stdin_channel = g_io_channel_unix_new (fd_r); + g_io_channel_set_encoding (stdin_channel, NULL, NULL); + g_io_channel_set_buffered (stdin_channel, FALSE); + g_io_channel_set_close_on_unref (stdin_channel, TRUE); + stdin_source = + g_io_create_watch (stdin_channel, G_IO_IN | G_IO_PRI | G_IO_HUP); + g_source_set_priority (stdin_source, G_PRIORITY_DEFAULT); + g_source_set_callback (stdin_source, (GSourceFunc) have_stdin_data_cb, NULL, + NULL); + g_source_attach (stdin_source, main_context); + g_source_unref (stdin_source); + + /* Create stdout channel */ + stdout_channel = g_io_channel_unix_new (fd_w); + g_io_channel_set_encoding (stdout_channel, NULL, NULL); + g_io_channel_set_close_on_unref (stdout_channel, TRUE); + g_io_channel_set_buffered (stdout_channel, FALSE); + + delay_req_rand = g_rand_new (); + observation_system_clock = + g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "ptp-observation-clock", + NULL); + gst_object_ref_sink (observation_system_clock); + + initted = TRUE; + +wait: + GST_DEBUG ("Waiting for PTP to be initialized"); + + while (ptp_clock_id.clock_identity == GST_PTP_CLOCK_ID_NONE && initted) + g_cond_wait (&ptp_cond, &ptp_lock); + + ret = initted; + if (ret) { + GST_DEBUG ("Initialized and got clock id 0x%016" G_GINT64_MODIFIER "x %u", + ptp_clock_id.clock_identity, ptp_clock_id.port_number); + } else { + GST_ERROR ("Failed to initialize"); + supported = FALSE; + } + +done: + g_strfreev (argv); + + if (!ret) { + if (ptp_helper_pid) { +#ifndef G_OS_WIN32 + kill (ptp_helper_pid, SIGKILL); + waitpid (ptp_helper_pid, NULL, 0); +#else + TerminateProcess (ptp_helper_pid, 1); + WaitForSingleObject (ptp_helper_pid, INFINITE); +#endif + g_spawn_close_pid (ptp_helper_pid); + } + ptp_helper_pid = 0; + + if (stdin_channel) + g_io_channel_unref (stdin_channel); + stdin_channel = NULL; + if (stdout_channel) + g_io_channel_unref (stdout_channel); + stdout_channel = NULL; + + if (main_loop && ptp_helper_thread) { + g_main_loop_quit (main_loop); + g_thread_join (ptp_helper_thread); + } + ptp_helper_thread = NULL; + if (main_loop) + g_main_loop_unref (main_loop); + main_loop = NULL; + if (main_context) + g_main_context_unref (main_context); + main_context = NULL; + + if (delay_req_rand) + g_rand_free (delay_req_rand); + delay_req_rand = NULL; + + if (observation_system_clock) + gst_object_unref (observation_system_clock); + observation_system_clock = NULL; + } + + g_mutex_unlock (&ptp_lock); + + return ret; +} + +/** + * gst_ptp_deinit: + * + * Deinitialize the GStreamer PTP subsystem and stop the PTP clock. If there + * are any remaining GstPtpClock instances, they won't be further synchronized + * to the PTP network clock. + * + * Since: 1.6 + */ +void +gst_ptp_deinit (void) +{ + GList *l, *m; + + g_mutex_lock (&ptp_lock); + + if (ptp_helper_pid) { +#ifndef G_OS_WIN32 + kill (ptp_helper_pid, SIGKILL); + waitpid (ptp_helper_pid, NULL, 0); +#else + TerminateProcess (ptp_helper_pid, 1); + WaitForSingleObject (ptp_helper_pid, INFINITE); +#endif + g_spawn_close_pid (ptp_helper_pid); + } + ptp_helper_pid = 0; + + if (stdin_channel) + g_io_channel_unref (stdin_channel); + stdin_channel = NULL; + if (stdout_channel) + g_io_channel_unref (stdout_channel); + stdout_channel = NULL; + + if (main_loop && ptp_helper_thread) { + GThread *tmp = ptp_helper_thread; + ptp_helper_thread = NULL; + g_mutex_unlock (&ptp_lock); + g_main_loop_quit (main_loop); + g_thread_join (tmp); + g_mutex_lock (&ptp_lock); + } + if (main_loop) + g_main_loop_unref (main_loop); + main_loop = NULL; + if (main_context) + g_main_context_unref (main_context); + main_context = NULL; + + if (delay_req_rand) + g_rand_free (delay_req_rand); + delay_req_rand = NULL; + if (observation_system_clock) + gst_object_unref (observation_system_clock); + observation_system_clock = NULL; + + for (l = domain_data; l; l = l->next) { + PtpDomainData *domain = l->data; + + for (m = domain->announce_senders; m; m = m->next) { + PtpAnnounceSender *sender = m->data; + + g_queue_foreach (&sender->announce_messages, (GFunc) g_free, NULL); + g_queue_clear (&sender->announce_messages); + g_free (sender); + } + g_list_free (domain->announce_senders); + + g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free, + NULL); + g_queue_clear (&domain->pending_syncs); + gst_object_unref (domain->domain_clock); + g_free (domain); + } + g_list_free (domain_data); + domain_data = NULL; + g_list_foreach (domain_clocks, (GFunc) g_free, NULL); + g_list_free (domain_clocks); + domain_clocks = NULL; + + ptp_clock_id.clock_identity = GST_PTP_CLOCK_ID_NONE; + ptp_clock_id.port_number = 0; + + initted = FALSE; + + g_mutex_unlock (&ptp_lock); +} + +#define DEFAULT_DOMAIN 0 + +enum +{ + PROP_0, + PROP_DOMAIN, + PROP_INTERNAL_CLOCK, + PROP_MASTER_CLOCK_ID, + PROP_GRANDMASTER_CLOCK_ID +}; + +#define GST_PTP_CLOCK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PTP_CLOCK, GstPtpClockPrivate)) + +struct _GstPtpClockPrivate +{ + guint domain; + GstClock *domain_clock; + gulong domain_stats_id; +}; + +#define gst_ptp_clock_parent_class parent_class +G_DEFINE_TYPE (GstPtpClock, gst_ptp_clock, GST_TYPE_SYSTEM_CLOCK); + +static void gst_ptp_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ptp_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_ptp_clock_finalize (GObject * object); + +static GstClockTime gst_ptp_clock_get_internal_time (GstClock * clock); + +static void +gst_ptp_clock_class_init (GstPtpClockClass * klass) +{ + GObjectClass *gobject_class; + GstClockClass *clock_class; + + gobject_class = G_OBJECT_CLASS (klass); + clock_class = GST_CLOCK_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstPtpClockPrivate)); + + gobject_class->finalize = gst_ptp_clock_finalize; + gobject_class->get_property = gst_ptp_clock_get_property; + gobject_class->set_property = gst_ptp_clock_set_property; + + g_object_class_install_property (gobject_class, PROP_DOMAIN, + g_param_spec_uint ("domain", "Domain", + "The PTP domain", 0, G_MAXUINT8, + DEFAULT_DOMAIN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_INTERNAL_CLOCK, + g_param_spec_object ("internal-clock", "Internal Clock", + "Internal clock", GST_TYPE_CLOCK, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MASTER_CLOCK_ID, + g_param_spec_uint64 ("master-clock-id", "Master Clock ID", + "Master Clock ID", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_GRANDMASTER_CLOCK_ID, + g_param_spec_uint64 ("grandmaster-clock-id", "Grand Master Clock ID", + "Grand Master Clock ID", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + clock_class->get_internal_time = gst_ptp_clock_get_internal_time; +} + +static void +gst_ptp_clock_init (GstPtpClock * self) +{ + GstPtpClockPrivate *priv; + + self->priv = priv = GST_PTP_CLOCK_GET_PRIVATE (self); + + GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_CAN_SET_MASTER); + GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC); + + priv->domain = DEFAULT_DOMAIN; +} + +static gboolean +gst_ptp_clock_ensure_domain_clock (GstPtpClock * self) +{ + gboolean got_clock = TRUE; + + if (G_UNLIKELY (!self->priv->domain_clock)) { + g_mutex_lock (&domain_clocks_lock); + if (!self->priv->domain_clock) { + GList *l; + + got_clock = FALSE; + + for (l = domain_clocks; l; l = l->next) { + PtpDomainData *clock_data = l->data; + + if (clock_data->domain == self->priv->domain + && clock_data->last_ptp_time != 0) { + self->priv->domain_clock = clock_data->domain_clock; + got_clock = TRUE; + break; + } + } + } + g_mutex_unlock (&domain_clocks_lock); + if (got_clock) { + g_object_notify (G_OBJECT (self), "internal-clock"); + gst_clock_set_synced (GST_CLOCK (self), TRUE); + } + } + + return got_clock; +} + +static gboolean +gst_ptp_clock_stats_callback (guint8 domain, const GstStructure * stats, + gpointer user_data) +{ + GstPtpClock *self = user_data; + + if (domain != self->priv->domain + || !gst_structure_has_name (stats, GST_PTP_STATISTICS_TIME_UPDATED)) + return TRUE; + + /* Let's set our internal clock */ + if (!gst_ptp_clock_ensure_domain_clock (self)) + return TRUE; + + self->priv->domain_stats_id = 0; + + return FALSE; +} + +static void +gst_ptp_clock_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPtpClock *self = GST_PTP_CLOCK (object); + + switch (prop_id) { + case PROP_DOMAIN: + self->priv->domain = g_value_get_uint (value); + gst_ptp_clock_ensure_domain_clock (self); + if (!self->priv->domain_clock) + self->priv->domain_stats_id = + gst_ptp_statistics_callback_add (gst_ptp_clock_stats_callback, self, + NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ptp_clock_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstPtpClock *self = GST_PTP_CLOCK (object); + + switch (prop_id) { + case PROP_DOMAIN: + g_value_set_uint (value, self->priv->domain); + break; + case PROP_INTERNAL_CLOCK: + gst_ptp_clock_ensure_domain_clock (self); + g_value_set_object (value, self->priv->domain_clock); + break; + case PROP_MASTER_CLOCK_ID: + case PROP_GRANDMASTER_CLOCK_ID:{ + GList *l; + + g_mutex_lock (&domain_clocks_lock); + g_value_set_uint64 (value, 0); + + for (l = domain_clocks; l; l = l->next) { + PtpDomainData *clock_data = l->data; + + if (clock_data->domain == self->priv->domain) { + if (prop_id == PROP_MASTER_CLOCK_ID) + g_value_set_uint64 (value, + clock_data->master_clock_identity.clock_identity); + else + g_value_set_uint64 (value, clock_data->grandmaster_identity); + break; + } + } + g_mutex_unlock (&domain_clocks_lock); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ptp_clock_finalize (GObject * object) +{ + GstPtpClock *self = GST_PTP_CLOCK (object); + + if (self->priv->domain_stats_id) + gst_ptp_statistics_callback_remove (self->priv->domain_stats_id); + + G_OBJECT_CLASS (gst_ptp_clock_parent_class)->finalize (object); +} + +static GstClockTime +gst_ptp_clock_get_internal_time (GstClock * clock) +{ + GstPtpClock *self = GST_PTP_CLOCK (clock); + + gst_ptp_clock_ensure_domain_clock (self); + + if (!self->priv->domain_clock) { + GST_ERROR_OBJECT (self, "Domain %u has no clock yet and is not synced", + self->priv->domain); + return GST_CLOCK_TIME_NONE; + } + + return gst_clock_get_time (self->priv->domain_clock); +} + +/** + * gst_ptp_clock_new: + * @name: Name of the clock + * @domain: PTP domain + * + * Creates a new PTP clock instance that exports the PTP time of the master + * clock in @domain. This clock can be slaved to other clocks as needed. + * + * If gst_ptp_init() was not called before, this will call gst_ptp_init() with + * default parameters. + * + * This clock only returns valid timestamps after it received the first + * times from the PTP master clock on the network. Once this happens the + * GstPtpClock::internal-clock property will become non-NULL. You can + * check this with gst_clock_wait_for_sync(), the GstClock::synced signal and + * gst_clock_is_synced(). + * + * Returns: (transfer full): A new #GstClock + * + * Since: 1.6 + */ +GstClock * +gst_ptp_clock_new (const gchar * name, guint domain) +{ + GstClock *clock; + + g_return_val_if_fail (domain <= G_MAXUINT8, NULL); + + if (!initted && !gst_ptp_init (GST_PTP_CLOCK_ID_NONE, NULL)) { + GST_ERROR ("Failed to initialize PTP"); + return NULL; + } + + clock = g_object_new (GST_TYPE_PTP_CLOCK, "name", name, "domain", domain, + NULL); + + /* Clear floating flag */ + gst_object_ref_sink (clock); + + return clock; +} + +typedef struct +{ + guint8 domain; + const GstStructure *stats; +} DomainStatsMarshalData; + +static void +domain_stats_marshaller (GHook * hook, DomainStatsMarshalData * data) +{ + GstPtpStatisticsCallback callback = (GstPtpStatisticsCallback) hook->func; + + if (!callback (data->domain, data->stats, hook->data)) + g_hook_destroy (&domain_stats_hooks, hook->hook_id); +} + +static void +emit_ptp_statistics (guint8 domain, const GstStructure * stats) +{ + DomainStatsMarshalData data = { domain, stats }; + + g_mutex_lock (&ptp_lock); + g_hook_list_marshal (&domain_stats_hooks, TRUE, + (GHookMarshaller) domain_stats_marshaller, &data); + g_mutex_unlock (&ptp_lock); +} + +/** + * gst_ptp_statistics_callback_add: + * @callback: GstPtpStatisticsCallback to call + * @user_data: Data to pass to the callback + * @destroy_data: GDestroyNotify to destroy the data + * + * Installs a new statistics callback for gathering PTP statistics. See + * GstPtpStatisticsCallback for a list of statistics that are provided. + * + * Returns: Id for the callback that can be passed to + * gst_ptp_statistics_callback_remove() + * + * Since: 1.6 + */ +gulong +gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback, + gpointer user_data, GDestroyNotify destroy_data) +{ + GHook *hook; + + g_mutex_lock (&ptp_lock); + + if (!domain_stats_hooks_initted) { + g_hook_list_init (&domain_stats_hooks, sizeof (GHook)); + domain_stats_hooks_initted = TRUE; + } + + hook = g_hook_alloc (&domain_stats_hooks); + hook->func = callback; + hook->data = user_data; + hook->destroy = destroy_data; + g_hook_prepend (&domain_stats_hooks, hook); + g_atomic_int_add (&domain_stats_n_hooks, 1); + + g_mutex_unlock (&ptp_lock); + + return hook->hook_id; +} + +/** + * gst_ptp_statistics_callback_remove: + * @id: Callback id to remove + * + * Removes a PTP statistics callback that was previously added with + * gst_ptp_statistics_callback_add(). + * + * Since: 1.6 + */ +void +gst_ptp_statistics_callback_remove (gulong id) +{ + g_mutex_lock (&ptp_lock); + if (g_hook_destroy (&domain_stats_hooks, id)) + g_atomic_int_add (&domain_stats_n_hooks, -1); + g_mutex_unlock (&ptp_lock); +} diff --git a/libs/gst/net/gstptpclock.h b/libs/gst/net/gstptpclock.h new file mode 100644 index 0000000..06ca5cf --- /dev/null +++ b/libs/gst/net/gstptpclock.h @@ -0,0 +1,163 @@ +/* GStreamer + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_PTP_CLOCK_H__ +#define __GST_PTP_CLOCK_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PTP_CLOCK \ + (gst_ptp_clock_get_type()) +#define GST_PTP_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PTP_CLOCK,GstPtpClock)) +#define GST_PTP_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PTP_CLOCK,GstPtpClockClass)) +#define GST_IS_PTP_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PTP_CLOCK)) +#define GST_IS_PTP_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PTP_CLOCK)) + +typedef struct _GstPtpClock GstPtpClock; +typedef struct _GstPtpClockClass GstPtpClockClass; +typedef struct _GstPtpClockPrivate GstPtpClockPrivate; + +/** + * GstPtpClock: + * + * Opaque #GstPtpClock structure. + */ +struct _GstPtpClock { + GstSystemClock clock; + + /*< private >*/ + GstPtpClockPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstPtpClockClass: + * @parent_class: parented to #GstSystemClockClass + * + * Opaque #GstPtpClockClass structure. + */ +struct _GstPtpClockClass { + GstSystemClockClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GST_PTP_CLOCK_ID_NONE: + * PTP clock identification that can be passed to gst_ptp_init() to + * automatically select one based on the MAC address of interfaces + */ +#define GST_PTP_CLOCK_ID_NONE ((guint64) -1) + +GST_NET_API +GType gst_ptp_clock_get_type (void); + +GST_NET_API +gboolean gst_ptp_is_supported (void); + +GST_NET_API +gboolean gst_ptp_is_initialized (void); + +GST_NET_API +gboolean gst_ptp_init (guint64 clock_id, + gchar ** interfaces); +GST_NET_API +void gst_ptp_deinit (void); + +#define GST_PTP_STATISTICS_NEW_DOMAIN_FOUND "GstPtpStatisticsNewDomainFound" +#define GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED "GstPtpStatisticsBestMasterClockSelected" +#define GST_PTP_STATISTICS_PATH_DELAY_MEASURED "GstPtpStatisticsPathDelayMeasured" +#define GST_PTP_STATISTICS_TIME_UPDATED "GstPtpStatisticsTimeUpdated" + +/** + * GstPtpStatisticsCallback: + * @domain: PTP domain identifier + * @stats: New statistics + * @user_data: Data passed to gst_ptp_statistics_callback_add() + * + * The statistics can be the following structures: + * + * GST_PTP_STATISTICS_NEW_DOMAIN_FOUND: + * "domain" G_TYPE_UINT The domain identifier of the domain + * "clock" GST_TYPE_CLOCK The internal clock that is slaved to the + * PTP domain + * + * GST_PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED: + * "domain" G_TYPE_UINT The domain identifier of the domain + * "master-clock-id" G_TYPE_UINT64 PTP clock identifier of the selected master + * clock + * "master-clock-port" G_TYPE_UINT PTP port number of the selected master clock + * "grandmaster-clock-id" G_TYPE_UINT64 PTP clock identifier of the grandmaster clock + * + * GST_PTP_STATISTICS_PATH_DELAY_MEASURED: + * "domain" G_TYPE_UINT The domain identifier of the domain + * "mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay + * "mean-path-delay" GST_TYPE_CLOCK_TIME Latest mean path delay + * "delay-request-delay" GST_TYPE_CLOCK_TIME Delay of DELAY_REQ / DELAY_RESP messages + * + * GST_PTP_STATISTICS_TIME_UPDATED: + * "domain" G_TYPE_UINT The domain identifier of the domain + * "mean-path-delay-avg" GST_TYPE_CLOCK_TIME Average mean path delay + * "local-time" GST_TYPE_CLOCK_TIME Local time that corresponds to ptp-time + * "ptp-time" GST_TYPE_CLOCK_TIME Newly measured PTP time at local-time + * "estimated-ptp-time" GST_TYPE_CLOCK_TIME Estimated PTP time based on previous measurements + * "discontinuity" G_TYPE_INT64 Difference between estimated and measured PTP time + * "synced" G_TYPE_BOOLEAN Currently synced to the remote clock + * "r-squared" G_TYPE_DOUBLE R² of clock estimation regression + * "internal-time" GST_TYPE_CLOCK_TIME Internal time clock parameter + * "external-time" GST_TYPE_CLOCK_TIME External time clock parameter + * "rate-num" G_TYPE_UINT64 Internal/external rate numerator + * "rate-den" G_TYPE_UINT64 Internal/external rate denominator + * "rate" G_TYPE_DOUBLE Internal/external rate + * + * If %FALSE is returned, the callback is removed and never called again. + * + */ +typedef gboolean (*GstPtpStatisticsCallback) (guint8 domain, + const GstStructure * stats, + gpointer user_data); +GST_NET_API +gulong gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback, + gpointer user_data, GDestroyNotify destroy_data); +GST_NET_API +void gst_ptp_statistics_callback_remove (gulong id); + +GST_NET_API +GstClock* gst_ptp_clock_new (const gchar *name, + guint domain); + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPtpClock, gst_object_unref) +#endif + +G_END_DECLS + +#endif /* __GST_PTP_CLOCK_H__ */ + diff --git a/libs/gst/net/meson.build b/libs/gst/net/meson.build new file mode 100644 index 0000000..0a76fd2 --- /dev/null +++ b/libs/gst/net/meson.build @@ -0,0 +1,70 @@ +gst_net_sources = [ + 'gstnetaddressmeta.c', + 'gstnetclientclock.c', + 'gstnetcontrolmessagemeta.c', + 'gstnettimepacket.c', + 'gstnettimeprovider.c', + 'gstptpclock.c', + 'gstntppacket.c', + 'gstnetutils.c', +] + +gst_net_headers = [ + 'gstnet.h', + 'gstnetaddressmeta.h', + 'gstnetclientclock.h', + 'gstnetcontrolmessagemeta.h', + 'gstnettimepacket.h', + 'gstnettimeprovider.h', + 'gstptpclock.h', + 'net-prelude.h', + 'net.h', +] +install_headers(gst_net_headers, subdir : 'gstreamer-1.0/gst/net/') + +if libtype != 'shared' + gst_net_static = static_library('gstnet-@0@'.format(apiversion), + gst_net_sources, + c_args : gst_c_args, + include_directories : [configinc, libsinc], + install : true, + dependencies : [gio_dep, gst_base_dep], + ) + gst_net = gst_net_static +endif + +gst_net_gen_sources = [] +if libtype != 'static' + gst_net_shared = shared_library('gstnet-@0@'.format(apiversion), + gst_net_sources, + c_args : gst_c_args, + include_directories : [configinc, libsinc], + version : libversion, + soversion : soversion, + install : true, + dependencies : [gio_dep, gst_base_dep], + ) + gst_net = gst_net_shared + if build_gir + gst_gir_extra_args = gir_init_section + [ '--c-include=gst/net/net.h' ] + gst_net_gir = gnome.generate_gir(gst_net_shared, + sources : gst_net_sources + gst_net_headers, + namespace : 'GstNet', + nsversion : apiversion, + identifier_prefix : 'Gst', + symbol_prefix : 'gst', + export_packages : 'gstreamer-net-1.0', + dependencies : [gst_base_dep], + include_directories : [configinc, libsinc], + includes : ['GLib-2.0', 'GObject-2.0', 'GModule-2.0', 'Gio-2.0', 'Gst-1.0'], + install : true, + extra_args : gst_gir_extra_args, + ) + gst_net_gen_sources += [gst_net_gir] + endif +endif + +gst_net_dep = declare_dependency(link_with : gst_net, + include_directories : [libsinc], + sources: gst_net_gen_sources, + dependencies : [gst_base_dep]) diff --git a/libs/gst/net/net-prelude.h b/libs/gst/net/net-prelude.h new file mode 100644 index 0000000..8db7565 --- /dev/null +++ b/libs/gst/net/net-prelude.h @@ -0,0 +1,31 @@ +/* GStreamer Net Library + * Copyright (C) 2018 GStreamer developers + * + * net-prelude.h: prelude include header for gst-net 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_NET_PRELUDE_H__ +#define __GST_NET_PRELUDE_H__ + +#include + +#ifndef GST_NET_API +#define GST_NET_API GST_EXPORT +#endif + +#endif /* __GST_NET_PRELUDE_H__ */ diff --git a/libs/gst/net/net.h b/libs/gst/net/net.h new file mode 100644 index 0000000..2575af5 --- /dev/null +++ b/libs/gst/net/net.h @@ -0,0 +1,35 @@ +/* GStreamer + * Copyright (C) 2012 GStreamer developers + * + * net.h: single include header for gst-net 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_NET__H__ +#define __GST_NET__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif /* __GST_NET__H__ */ diff --git a/libs/meson.build b/libs/meson.build new file mode 100644 index 0000000..668dcba --- /dev/null +++ b/libs/meson.build @@ -0,0 +1 @@ +subdir('gst') diff --git a/ltmain.sh b/ltmain.sh new file mode 100644 index 0000000..a736cf9 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,11156 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-2" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# 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 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# 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 3 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-2 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/m4/Makefile.am b/m4/Makefile.am new file mode 100644 index 0000000..af864e3 --- /dev/null +++ b/m4/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = $(wildcard *.m4) diff --git a/m4/Makefile.in b/m4/Makefile.in new file mode 100644 index 0000000..73ad8a7 --- /dev/null +++ b/m4/Makefile.in @@ -0,0 +1,632 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = m4 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = $(wildcard *.m4) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu m4/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/m4/check-checks.m4 b/m4/check-checks.m4 new file mode 100644 index 0000000..44baca4 --- /dev/null +++ b/m4/check-checks.m4 @@ -0,0 +1,127 @@ +dnl Check for things that check needs/wants and that we don't check for already +dnl AM_GST_CHECK_CHECKS() + +AC_DEFUN([AG_GST_CHECK_CHECKS], +[ +AC_MSG_NOTICE([Running check unit test framework checks now...]) + +CHECK_MAJOR_VERSION=0 +CHECK_MINOR_VERSION=10 +CHECK_MICRO_VERSION=0 +CHECK_VERSION=$CHECK_MAJOR_VERSION.$CHECK_MINOR_VERSION.$CHECK_MICRO_VERSION + +AC_SUBST(CHECK_MAJOR_VERSION) +AC_SUBST(CHECK_MINOR_VERSION) +AC_SUBST(CHECK_MICRO_VERSION) +AC_SUBST(CHECK_VERSION) + +dnl Checks for header files and declarations +AC_CHECK_HEADERS([unistd.h sys/wait.h sys/time.h], [], [], [AC_INCLUDES_DEFAULT]) + +dnl Check for localtime_r() +AC_CHECK_FUNCS([localtime_r]) +AM_CONDITIONAL(HAVE_LOCALTIME_R, test "x$ac_cv_func_localtime_r" = "xyes") + +dnl Check for gettimeofday() +AC_CHECK_FUNCS([gettimeofday]) +AM_CONDITIONAL(HAVE_GETTIMEOFDAY, test "x$ac_cv_func_gettimeofday" = "xyes") + +dnl Check for getpid() and _getpid() +AC_CHECK_FUNCS([getpid _getpid]) + +dnl Check for strdup() and _strdup() +AC_CHECK_DECLS([strdup]) +AC_CHECK_FUNCS([_strdup]) +AM_CONDITIONAL(HAVE_STRDUP, test "x$ac_cv_have_decl_strdup" = "xyes" -o "x$ac_cv_func__strdup" = "xyes") + +dnl Check for getline() +AC_CHECK_FUNCS([getline]) +AM_CONDITIONAL(HAVE_GETLINE, test "x$ac_cv_func_getline" = "xyes") + +dnl Check for mkstemp +AC_CHECK_FUNCS([mkstemp]) + +dnl Check for fork +AC_CHECK_FUNCS([fork], HAVE_FORK=1, HAVE_FORK=0) +AC_SUBST(HAVE_FORK) + +dnl Check for alarm, localtime_r and strsignal +dnl First check for time.h as it might be used by localtime_r +AC_CHECK_HEADERS([time.h]) +AC_CHECK_DECLS([alarm, localtime_r, strsignal], [], [], [ + AC_INCLUDES_DEFAULT +#if HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ +]) +AC_CHECK_FUNCS([alarm setitimer strsignal]) +AM_CONDITIONAL(HAVE_ALARM, test "x$ac_cv_func_alarm" = "xyes") +AM_CONDITIONAL(HAVE_LOCALTIME_R, test "x$ac_cv_func_localtime_r" = "xyes") +AM_CONDITIONAL(HAVE_STRSIGNAL, test "x$ac_cv_func_strsignal" = "xyes") + +dnl Check if struct timespec/itimerspec are defined in time.h. If not, we need +dnl to define it in libs/gst/check/libcheck/libcompat.h. Note the optional +dnl inclusion of pthread.h. On MinGW(-w64), the pthread.h file contains the +dnl timespec/itimerspec definitions. +AC_CHECK_MEMBERS([struct timespec.tv_sec, struct timespec.tv_nsec], [], + [AC_DEFINE_UNQUOTED(STRUCT_TIMESPEC_DEFINITION_MISSING, 1, + [Need to define the timespec structure])], [ +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ +]) +AC_CHECK_MEMBERS([struct itimerspec.it_interval, struct itimerspec.it_value], + [], [AC_DEFINE_UNQUOTED(STRUCT_ITIMERSPEC_DEFINITION_MISSING, 1, + [Need to define the itimerspec structure])], [ +#include +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ +]) + +dnl Check if types timer_t/clockid_t are defined. If not, we need to define it +dnl in libs/gst/check/libcheck/libcompat/libcompat.h. Note the optional +dnl inclusion of pthread.h. On MinGW(-w64), the pthread.h file contains the +dnl timer_t/clockid_t definitions. +AC_CHECK_TYPE(timer_t, [], [ + AC_DEFINE([timer_t], [int], [timer_t]) + ], [ + AC_INCLUDES_DEFAULT +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ +]) +AC_CHECK_TYPE(clockid_t, [], [ + AC_DEFINE([clockid_t], [int], [clockid_t]) + ], [ + AC_INCLUDES_DEFAULT +#if HAVE_PTHREAD +#include +#endif /* HAVE_PTHREAD */ +]) + +dnl Check for POSIX timer functions in librt +AC_CHECK_LIB([rt], [timer_create, timer_settime, timer_delete]) +AM_CONDITIONAL(HAVE_TIMER_CREATE_SETTIME_DELETE, test "x$ac_cv_lib_rt_timer_create__timer_settime__timer_delete" = "xyes") + +dnl Allow for checking HAVE_CLOCK_GETTIME in automake files +AM_CONDITIONAL(HAVE_CLOCK_GETTIME, test "x$CLOCK_GETTIME_FOUND" = "xyes") + +dnl Create _stdint.h in the top-level directory +AX_CREATE_STDINT_H + +dnl Disable subunit support for the time being +enable_subunit=false + +if test xfalse = x"$enable_subunit"; then +ENABLE_SUBUNIT="0" +else +ENABLE_SUBUNIT="1" +fi +AC_SUBST(ENABLE_SUBUNIT) +AC_DEFINE_UNQUOTED(ENABLE_SUBUNIT, $ENABLE_SUBUNIT, [Subunit protocol result output]) + +AM_CONDITIONAL(SUBUNIT, test x"$enable_subunit" != "xfalse") + +]) diff --git a/m4/codeset.m4 b/m4/codeset.m4 new file mode 100644 index 0000000..223955b --- /dev/null +++ b/m4/codeset.m4 @@ -0,0 +1,21 @@ +# codeset.m4 serial 2 (gettext-0.16) +dnl Copyright (C) 2000-2002, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, + [AC_TRY_LINK([#include ], + [char* cs = nl_langinfo(CODESET); return !cs;], + am_cv_langinfo_codeset=yes, + am_cv_langinfo_codeset=no) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE(HAVE_LANGINFO_CODESET, 1, + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 0000000..c9ae1f7 --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,381 @@ +# gettext.m4 serial 60 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value `$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings;], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE(ENABLE_NLS, 1, + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE(HAVE_GETTEXT, 1, + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE(HAVE_DCGETTEXT, 1, + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST(BUILD_INCLUDED_LIBINTL) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATOBJEXT) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST(DATADIRNAME) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST(INSTOBJEXT) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST(GENCAT) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST(INTLOBJS) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST(INTLLIBS) + + dnl Make all documented variables known to autoconf. + AC_SUBST(LIBINTL) + AC_SUBST(LTLIBINTL) + AC_SUBST(POSUB) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/glibc2.m4 b/m4/glibc2.m4 new file mode 100644 index 0000000..e8f5bfe --- /dev/null +++ b/m4/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 1 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, + ac_cv_gnu_library_2, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2=yes, + ac_cv_gnu_library_2=no) + ] + ) + AC_SUBST(GLIBC2) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 0000000..d95fd98 --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 3 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, + ac_cv_gnu_library_2_1, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2_1=yes, + ac_cv_gnu_library_2_1=no) + ] + ) + AC_SUBST(GLIBC21) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 0000000..66bc76f --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,180 @@ +# iconv.m4 serial AM6 (gettext-0.17) +dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_func_iconv=yes) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_lib_iconv=yes + am_cv_func_iconv=yes) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [ + dnl This tests against bugs in AIX 5.1 and HP-UX 11.11. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_TRY_RUN([ +#include +#include +int main () +{ + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + return 1; + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + return 1; + return 0; +}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE(HAVE_ICONV, 1, + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST(LIBICONV) + AC_SUBST(LTLIBICONV) +]) + +AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL(am_cv_proto_iconv, [ + AC_TRY_COMPILE([ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif +], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([$]{ac_t:- + }[$]am_cv_proto_iconv) + AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, + [Define as const if the declaration of iconv() needs const.]) + fi +]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 0000000..8c8a670 --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,84 @@ +# intdiv0.m4 serial 2 (gettext-0.17) +dnl Copyright (C) 2002, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_TRY_RUN([ +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/intl.m4 b/m4/intl.m4 new file mode 100644 index 0000000..934408b --- /dev/null +++ b/m4/intl.m4 @@ -0,0 +1,285 @@ +# intl.m4 serial 8 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006. + +AC_PREREQ(2.52) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() . + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init libintl_lock_init +#define glthread_lock_lock libintl_lock_lock +#define glthread_lock_unlock libintl_lock_unlock +#define glthread_lock_destroy libintl_lock_destroy +#define glthread_rwlock_init libintl_rwlock_init +#define glthread_rwlock_rdlock libintl_rwlock_rdlock +#define glthread_rwlock_wrlock libintl_rwlock_wrlock +#define glthread_rwlock_unlock libintl_rwlock_unlock +#define glthread_rwlock_destroy libintl_rwlock_destroy +#define glthread_recursive_lock_init libintl_recursive_lock_init +#define glthread_recursive_lock_lock libintl_recursive_lock_lock +#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock +#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy +#define glthread_once libintl_once +#define glthread_once_call libintl_once_call +#define glthread_once_singlethreaded libintl_once_singlethreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_TRY_LINK( + [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], + [], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ + argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(feof_unlocked, [#include ]) + gt_CHECK_DECL(fgets_unlocked, [#include ]) + + AM_ICONV + + dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, + dnl and a _NL_LOCALE_NAME macro always. + AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, + [AC_TRY_LINK([#include +#include ], + [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)); + return !cs; + ], + gt_cv_nl_locale_name=yes, + gt_cv_nl_locale_name=no) + ]) + if test $gt_cv_nl_locale_name = yes; then + AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, + [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) + fi + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) diff --git a/m4/intldir.m4 b/m4/intldir.m4 new file mode 100644 index 0000000..7a28843 --- /dev/null +++ b/m4/intldir.m4 @@ -0,0 +1,19 @@ +# intldir.m4 serial 1 (gettext-0.16) +dnl Copyright (C) 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +AC_PREREQ(2.52) + +dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory. +AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], []) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 0000000..d3f0d90 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# intlmacosx.m4 serial 1 (gettext-0.17) +dnl Copyright (C) 2004-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + gt_cv_func_CFPreferencesCopyAppValue, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 0000000..ce7a8a4 --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,33 @@ +# intmax.m4 serial 3 (gettext-0.16) +dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, + [AC_TRY_COMPILE([ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif +], [intmax_t x = -1; + return !x;], + gt_cv_c_intmax_t=yes, + gt_cv_c_intmax_t=no)]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 0000000..7c7f894 --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,36 @@ +# inttypes-pri.m4 serial 4 (gettext-0.16) +dnl Copyright (C) 1997-2002, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.52) + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + gt_cv_inttypes_pri_broken, + [ + AC_TRY_COMPILE([#include +#ifdef PRId32 +char *p = PRId32; +#endif +], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, + [Define if exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 0000000..edc8ecb --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 7 +dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + gl_cv_header_inttypes_h=yes, + gl_cv_header_inttypes_h=no)]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 0000000..19aa77e --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,30 @@ +# lcmessage.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 0000000..96c4e2c --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,110 @@ +# lib-ld.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(acl_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 new file mode 100644 index 0000000..e3d26fc --- /dev/null +++ b/m4/lib-link.m4 @@ -0,0 +1,709 @@ +# lib-link.m4 serial 13 (gettext-0.17) +dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.54) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + undefine([Name]) + undefine([NAME]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. If found, it +dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and +dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIB[]NAME" + AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + LIB[]NAME[]_PREFIX= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl acl_libext, +dnl acl_shlibext, +dnl acl_hardcode_libdir_flag_spec, +dnl acl_hardcode_libdir_separator, +dnl acl_hardcode_direct, +dnl acl_hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE(rpath, + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + dnl Autoconf >= 2.61 supports dots in --with options. + define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix], +[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIB[]NAME[]_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 0000000..a8684e1 --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,185 @@ +# lib-prefix.m4 serial 5 (gettext-0.15) +dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing +dnl the basename of the libdir, either "lib" or "lib64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. The current + dnl practice is that on a system supporting 32-bit and 64-bit instruction + dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit + dnl libraries go under $prefix/lib. We determine the compiler's default + dnl mode by looking at the compiler's library search path. If at least + dnl of its elements ends in /lib64 or points to a directory whose absolute + dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the + dnl default, namely "lib". + acl_libdirstem=lib + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi +]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..ee80844 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8387 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that 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, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/lock.m4 b/m4/lock.m4 new file mode 100644 index 0000000..9111933 --- /dev/null +++ b/m4/lock.m4 @@ -0,0 +1,316 @@ +# lock.m4 serial 7 (gettext-0.17) +dnl Copyright (C) 2005-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_LOCK_EARLY], +[ + AC_REQUIRE([gl_LOCK_EARLY_BODY]) +]) + +dnl The guts of gl_LOCK_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_LOCK_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + AC_ARG_ENABLE(threads, +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + [gl_use_threads=$enableval], + [case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its child + dnl process gets an endless segmentation fault inside execvp(). + osf*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_LOCK. Needs to be expanded only once. + +AC_DEFUN([gl_LOCK_BODY], +[ + AC_REQUIRE([gl_LOCK_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_MSG_CHECKING([whether imported symbols can be declared weak]) + gl_have_weak=no + AC_TRY_LINK([extern void xyzzy (); +#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes]) + AC_MSG_RESULT([$gl_have_weak]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_LOCK_EARLY_BODY. + AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_TRY_LINK([#include ], + [pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB(pthread, pthread_kill, + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1, + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB(pthread, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB(c_r, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], 1, + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], 1, + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1, + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_TRY_COMPILE([#include ], + [#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1, + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_TRY_LINK([#include +#include ], + [thr_self();], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], 1, + [Define if the old Solaris multithreading library can be used.]) + if test $gl_have_weak = yes; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1, + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS(pth) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_TRY_LINK([#include ], [pth_self();], gl_have_pth=yes) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], 1, + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_PTH_THREADS_WEAK], 1, + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], 1, + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST(LIBTHREAD) + AC_SUBST(LTLIBTHREAD) + AC_SUBST(LIBMULTITHREAD) + AC_SUBST(LTLIBMULTITHREAD) +]) + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_LOCK_EARLY]) + AC_REQUIRE([gl_LOCK_BODY]) + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 0000000..a72e53b --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,109 @@ +# longlong.m4 serial 13 +dnl Copyright (C) 1999-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug isn't important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [ac_cv_type_long_long_int=yes], + [ac_cv_type_long_long_int=no], + [ac_cv_type_long_long_int=yes])], + [ac_cv_type_long_long_int=no])]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 0000000..7967cc2 --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,31 @@ +# nls.m4 serial 3 (gettext-0.15) +dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 0000000..0734762 --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,449 @@ +# po.m4 serial 15 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.17]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; 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 + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP(notposix, [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], gt_cv_func_printf_posix="guessing no", + gt_cv_func_printf_posix="guessing yes") + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE(HAVE_POSIX_PRINTF, 1, + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 0000000..a56365c --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,92 @@ +# progtest.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ(2.50) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# 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. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + 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 +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 0000000..6cb4868 --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,68 @@ +# size_max.m4 serial 6 +dnl Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS(stdint.h) + dnl First test whether the system already has SIZE_MAX. + AC_MSG_CHECKING([for SIZE_MAX]) + AC_CACHE_VAL([gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], gl_cv_size_max=yes) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], size_t_bits_minus_1=) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], fits_in_uint=) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include + extern size_t foo; + extern unsigned long foo; + ], [], fits_in_uint=0) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + AC_MSG_RESULT([$gl_cv_size_max]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 0000000..db9a8ac --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 6 +dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + gl_cv_header_stdint_h=yes, + gl_cv_header_stdint_h=no)]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 0000000..641c489 --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 10 +dnl Copyright (C) 1997-2004, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE(HAVE_UINTMAX_T, 1, + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/m4/visibility.m4 b/m4/visibility.m4 new file mode 100644 index 0000000..2ff6330 --- /dev/null +++ b/m4/visibility.m4 @@ -0,0 +1,52 @@ +# visibility.m4 serial 1 (gettext-0.15) +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL(gl_cv_cc_visibility, [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + AC_TRY_COMPILE( + [extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void);], + [], + gl_cv_cc_visibility=yes, + gl_cv_cc_visibility=no) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 0000000..cde2129 --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, + [AC_TRY_COMPILE([#include + wchar_t foo = (wchar_t)'\0';], , + gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 0000000..af5ed93 --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,28 @@ +# wint_t.m4 serial 2 (gettext-0.17) +dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, + [AC_TRY_COMPILE([ +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be included + before . */ +#include +#include +#include +#include + wint_t foo = (wchar_t)'\0';], , + gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 0000000..85bb721 --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 3 +dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..4126fe9 --- /dev/null +++ b/meson.build @@ -0,0 +1,495 @@ +project('gstreamer', 'c', + version : '1.14.1', + meson_version : '>= 0.40.1', + default_options : [ 'warning_level=1', + 'buildtype=debugoptimized' ]) + +gst_version = meson.project_version() +version_arr = gst_version.split('.') +gst_version_major = version_arr[0].to_int() +gst_version_minor = version_arr[1].to_int() +gst_version_micro = version_arr[2].to_int() +if version_arr.length() == 4 + gst_version_nano = version_arr[3].to_int() +else + gst_version_nano = 0 +endif + +host_system = host_machine.system() + +apiversion = '1.0' +soversion = 0 +# maintaining compatibility with the previous libtool versioning +# current = minor * 100 + micro +libversion = '@0@.@1@.0'.format(soversion, gst_version_minor * 100 + gst_version_micro) + +prefix = get_option('prefix') +libtype = get_option('library_format') + +libexecdir = get_option('libexecdir') +helpers_install_dir = join_paths(libexecdir, 'gstreamer-1.0') + +cc = meson.get_compiler('c') + +# Ignore several spurious warnings for things gstreamer does very commonly +# If a warning is completely useless and spammy, use '/wdXXXX' to suppress it +# If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once +# NOTE: Only add warnings here if you are sure they're spurious +if cc.get_id() == 'msvc' + add_project_arguments( + '/wd4018', # implicit signed/unsigned conversion + '/wd4146', # unary minus on unsigned (beware INT_MIN) + '/wd4244', # lossy type conversion (e.g. double -> int) + '/wd4305', # truncating type conversion (e.g. double -> float) + language : 'c') +elif cc.has_argument('-Wl,-Bsymbolic-functions') + # FIXME: Add an option for this if people ask for it + add_project_link_arguments('-Wl,-Bsymbolic-functions', language : 'c') +endif + +# Symbol visibility +have_visibility_hidden = cc.has_argument('-fvisibility=hidden') +if have_visibility_hidden + add_project_arguments('-fvisibility=hidden', language: 'c') +endif + +# Disable strict aliasing +if cc.has_argument('-fno-strict-aliasing') + add_project_arguments('-fno-strict-aliasing', language: 'c') +endif + +cdata = configuration_data() +cdata.set_quoted('GST_API_VERSION', apiversion) +cdata.set_quoted('GST_DATADIR', join_paths(prefix, get_option('datadir'))) +cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir'))) +cdata.set_quoted('LIBDIR', join_paths(prefix, get_option('libdir'))) +cdata.set_quoted('GST_API_VERSION', '1.0') +cdata.set_quoted('GETTEXT_PACKAGE', 'gstreamer-1.0') +cdata.set_quoted('GST_LICENSE', 'LGPL') +cdata.set_quoted('PACKAGE', 'gstreamer') +cdata.set_quoted('PACKAGE_NAME', 'GStreamer') +cdata.set_quoted('PACKAGE_STRING', 'GStreamer @0@'.format(gst_version)) +cdata.set_quoted('PACKAGE_TARNAME', 'gstreamer') +cdata.set_quoted('PACKAGE_BUGREPORT', 'http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer') +cdata.set_quoted('PACKAGE_URL', '') +cdata.set_quoted('PACKAGE_VERSION', gst_version) +cdata.set_quoted('PLUGINDIR', join_paths(get_option('prefix'), get_option('libdir'), 'gstreamer-1.0')) +cdata.set_quoted('VERSION', gst_version) +# FIXME: --with-memory-alignment],[8,N,malloc,pagesize (default is 32)]) option +cdata.set('MEMORY_ALIGNMENT_MALLOC', 1) +cdata.set_quoted('GST_PLUGIN_SCANNER_INSTALLED', join_paths(prefix, helpers_install_dir, 'gst-plugin-scanner')) +cdata.set_quoted('GST_PTP_HELPER_INSTALLED', join_paths(prefix, helpers_install_dir, 'gst-ptp-helper')) +cdata.set_quoted('GST_PLUGIN_SCANNER_SUBDIR', libexecdir, + description: 'libexecdir path component, used to find plugin-scanner on relocatable builds on windows') + +if host_system == 'darwin' + cdata.set_quoted('GST_EXTRA_MODULE_SUFFIX', '.dylib') +endif + +if gst_version_nano > 0 + # Have GST_ERROR message printed when running from git + cdata.set('GST_LEVEL_DEFAULT', 'GST_LEVEL_ERROR') +else + cdata.set('GST_LEVEL_DEFAULT', 'GST_LEVEL_NONE') +endif + +# GStreamer package name and origin url +gst_package_name = get_option('with-package-name') +if gst_package_name == '' + if gst_version_nano == 0 + gst_package_name = 'GStreamer source release' + elif gst_version_nano == 1 + gst_package_name = 'GStreamer git' + else + gst_package_name = 'GStreamer prerelease' + endif +endif +cdata.set_quoted('GST_PACKAGE_NAME', gst_package_name) +cdata.set_quoted('GST_PACKAGE_ORIGIN', get_option('with-package-origin')) + +# These are only needed/used by the ABI tests +host_defines = [ + [ 'x86', 'HAVE_CPU_I386' ], + [ 'x86_64', 'HAVE_CPU_X86_64' ], + [ 'arm', 'HAVE_CPU_ARM' ], + [ 'aarch64', 'HAVE_CPU_AARCH64' ], + [ 'mips', 'HAVE_CPU_MIPS' ], + [ 'powerpc', 'HAVE_CPU_PPC' ], + [ 'powerpc64', 'HAVE_CPU_PPC64' ], + [ 'alpha', 'HAVE_CPU_ALPHA' ], + [ 'sparc', 'HAVE_CPU_SPARC' ], + [ 'ia64', 'HAVE_CPU_IA64' ], + [ 'hppa', 'HAVE_CPU_HPPA' ], + [ 'm68k', 'HAVE_CPU_M68K' ], + [ 's390', 'HAVE_CPU_S390' ], +] +foreach h : host_defines + if h.get(0) == host_machine.cpu() + cdata.set(h.get(1), 1) + endif +endforeach +# FIXME: should really be called HOST_CPU or such +cdata.set_quoted('TARGET_CPU', host_machine.cpu()) + +check_headers = [ + 'dlfcn.h', + 'inttypes.h', + 'memory.h', + 'poll.h', + 'stdint.h', + 'stdio_ext.h', + 'strings.h', + 'string.h', + 'sys/param.h', + 'sys/poll.h', + 'sys/prctl.h', + 'sys/socket.h', + 'sys/stat.h', + 'sys/times.h', + 'sys/time.h', + 'sys/types.h', + 'sys/utsname.h', + 'sys/wait.h', + 'ucontext.h', + 'unistd.h', + 'valgrind/valgrind.h', + 'sys/resource.h', +] + +if host_machine.system() == 'windows' + check_headers += ['winsock2.h'] +endif + +foreach h : check_headers + if cc.has_header(h) + define = 'HAVE_' + h.underscorify().to_upper() + cdata.set(define, 1) + endif +endforeach + +if cc.has_member('struct tm', 'tm_gmtoff', prefix : '#include ') + cdata.set('HAVE_TM_GMTOFF', 1) +endif + +check_functions = [ + 'gmtime_r', + 'sigaction', + 'getrusage', + 'fseeko', + 'ftello', + 'poll', + 'ppoll', + 'pselect', + 'getpagesize', + 'clock_gettime', + # These are needed by libcheck + 'getline', + 'mkstemp', + 'alarm', + 'gettimeofday', +] + +foreach f : check_functions + if cc.has_function(f) + define = 'HAVE_' + f.underscorify().to_upper() + cdata.set(define, 1) + endif +endforeach + +if cc.has_function('localtime_r', prefix : '#include') + cdata.set('HAVE_LOCALTIME_R', 1) + # Needed by libcheck + cdata.set('HAVE_DECL_LOCALTIME_R', 1) +endif + +if cc.links('''#include + int main() { + pthread_setname_np("example"); return 0; + }''', name : 'pthread_setname_np(const char*)') + cdata.set('HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID', 1) +endif + +# Check for posix timers and the monotonic clock +time_prefix = '#include \n' +if cdata.has('HAVE_UNISTD_H') + time_prefix += '#include ' +endif + +posix_timers_src = time_prefix + ''' +#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 || !defined(CLOCK_REALTIME) +#error Either _POSIX_TIMERS or CLOCK_REALTIME not defined +#endif +''' +if cc.compiles(posix_timers_src, name : 'posix timers from time.h') + cdata.set('HAVE_POSIX_TIMERS', 1) +endif + +monotonic_clock_src = time_prefix + ''' +#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 || !defined(CLOCK_MONOTONIC) +#error Either _POSIX_MONOTONIC_CLOCK or CLOCK_MONOTONIC not defined +#endif +''' +if cc.compiles(monotonic_clock_src, name : 'monotonic clock from time.h') + cdata.set('HAVE_MONOTONIC_CLOCK', 1) +endif + +# Check for __uint128_t (gcc) by checking for 128-bit division +uint128_t_src = '''int main() { +static __uint128_t v1 = 100; +static __uint128_t v2 = 10; +static __uint128_t u; +u = v1 / v2; +}''' +if cc.compiles(uint128_t_src, name : '__uint128_t available') + cdata.set('HAVE_UINT128_T', 1) +endif + +# All supported platforms have long long now +cdata.set('HAVE_LONG_LONG', 1) + +# We only want to use the __declspec(dllexport/import) dance in GST_EXPORT when +# building with MSVC +if cc.get_id() == 'msvc' + cdata.set('GSTCONFIG_BUILT_WITH_MSVC', 1) +else + cdata.set('GSTCONFIG_BUILT_WITH_MSVC', 0) +endif + +# ------------------------------------------------------------------------------------- +# config.h things needed by libcheck +# ------------------------------------------------------------------------------------- +if cc.has_function('getpid') + cdata.set('HAVE_GETPID', 1) +elif host_system == 'windows' and cc.has_function('_getpid') + cdata.set('HAVE_PROCESS_H', 1) # Used by gstreamer too + cdata.set('HAVE__GETPID', 1) +endif +if cc.has_function('strdup') + cdata.set('HAVE_DECL_STRDUP', 1) +elif host_system == 'windows' and cc.has_function('_strdup') + cdata.set('HAVE__STRDUP', 1) # Windows (MSVC) +endif +if host_machine.system() != 'windows' + cdata.set('HAVE_FORK', 1) +else + # libcheck requires HAVE_FORK to be 0 when fork() is not available + cdata.set('HAVE_FORK', 0) +endif +if cc.has_function('strsignal') + cdata.set('HAVE_DECL_STRSIGNAL', 1) +endif +# Check for availability of types +if not cc.has_type('clockid_t', prefix : '#include ') + cdata.set('clockid_t', 'int') +endif +if not cc.has_type('timer_t', prefix : '#include ') + cdata.set('timer_t', 'int') +endif +if not cc.has_members('struct timespec', 'tv_sec', 'tv_nsec', + prefix : '#include ') + cdata.set('STRUCT_TIMESPEC_DEFINITION_MISSING', 1) +endif +if not cc.has_members('struct itimerspec', 'it_interval', 'it_value', + prefix : '#include ') + cdata.set('STRUCT_ITIMERSPEC_DEFINITION_MISSING', 1) +endif + +# Platform deps; only ws2_32 and execinfo for now +platform_deps = [] +if host_machine.system() == 'windows' + platform_deps = [cc.find_library('ws2_32')] +endif + +backtrace_deps = [] +if not get_option('disable_libunwind') + unwind_dep = dependency('libunwind', required : false) + dw_dep = dependency('libdw', required: false) + backtrace_deps = [unwind_dep, dw_dep] + if unwind_dep.found() + cdata.set('HAVE_UNWIND', 1) + if dw_dep.found() + cdata.set('HAVE_DW', 1) + else + message('Support for backtraces is partial only.') + endif + else + if cc.has_function('backtrace') + cdata.set('HAVE_BACKTRACE', 1) + else + message('NO backtraces support.') + endif + endif +endif + +if cc.has_header('execinfo.h') + if cc.has_function('backtrace', prefix : '#include ') + cdata.set('HAVE_BACKTRACE', 1) + else + execinfo_dep = cc.find_library('execinfo', required : false) + if execinfo_dep.found() and cc.has_function('backtrace', prefix : '#include ', dependencies : execinfo_dep) + cdata.set('HAVE_BACKTRACE', 1) + platform_deps += execinfo_dep + endif + endif +endif + +disable_gst_debug = get_option('disable_gst_debug') +if disable_gst_debug + add_project_arguments(['-Wno-unused'], language: 'c') +endif + +warning_flags = [ + '-Wmissing-declarations', + '-Wmissing-prototypes', + '-Wredundant-decls', + '-Wundef', + '-Wwrite-strings', + '-Wformat', + '-Wformat-nonliteral', + '-Wformat-security', + '-Wold-style-definition', + '-Winit-self', + '-Wmissing-include-dirs', + '-Waddress', + '-Waggregate-return', + '-Wno-multichar', + '-Wnested-externs', + '-Wdeclaration-after-statement', + '-Wvla', + '-Wpointer-arith', +] + +foreach extra_arg : warning_flags + if cc.has_argument (extra_arg) + add_project_arguments([extra_arg], language: 'c') + endif +endforeach + +# Used by the gstutils test +gmp_dep = cc.find_library('gmp', required : false) +cdata.set('HAVE_GMP', gmp_dep.found()) +gsl_dep = cc.find_library('gsl', required : false) +gslcblas_dep = cc.find_library('gslcblas', required : false) +cdata.set('HAVE_GSL', gsl_dep.found() and gslcblas_dep.found()) +test_deps = [gmp_dep, gsl_dep, gslcblas_dep] + +# Used by gstinfo.c +dl_dep = cc.find_library('dl', required : false) +cdata.set('HAVE_DLADDR', cc.has_function('dladdr', dependencies : dl_dep)) + + +configinc = include_directories('.') +libsinc = include_directories('libs') +privinc = include_directories('gst') + +# Find dependencies +glib_dep = dependency('glib-2.0', version : '>=2.32.0', + fallback: ['glib', 'libglib_dep']) +gobject_dep = dependency('gobject-2.0', + fallback: ['glib', 'libgobject_dep']) +gmodule_dep = dependency('gmodule-2.0', + fallback: ['glib', 'libgmodule_dep']) +if host_machine.system() == 'windows' + gio_dep = dependency('gio-2.0', + fallback: ['glib', 'libgio_dep']) +else + gio_dep = [dependency('gio-2.0', + fallback: ['glib', 'libgio_dep']), + dependency('gio-unix-2.0', + fallback: ['glib', 'libgio_dep'])] +endif + +mathlib = cc.find_library('m', required : false) +# Needed for timer_create/settime/delete +# Also provides clock_gettime in glibc < 2.17 +rt_lib = cc.find_library('rt', required : false) + +gir = find_program('g-ir-scanner', required : false) +gnome = import('gnome') + +# Fixme, not very elegant. +build_gir = gir.found() and not meson.is_cross_build() and not get_option('disable_introspection') + +gir_init_section = [ '--add-init-section=extern void gst_init(gint*,gchar**);' + \ + 'g_setenv("GST_REGISTRY_DISABLE", "yes", TRUE);' + \ + 'g_setenv("GST_REGISTRY_1.0", "/no/way/this/exists.reg", TRUE);' + \ + 'g_setenv("GST_PLUGIN_PATH_1_0", "", TRUE);' + \ + 'g_setenv("GST_PLUGIN_SYSTEM_PATH_1_0", "", TRUE);' + \ + 'gst_init(NULL,NULL);' ] + +# Used by the *_mkenum.py helper scripts +glib_mkenums = find_program('glib-mkenums') + +gst_c_args = ['-DHAVE_CONFIG_H'] +if libtype == 'static' + gst_c_args += ['-DGST_STATIC_COMPILATION'] +endif + +# Used in gst/parse/meson.build and below +python3 = import('python3').find_python() + +bashcomp_dep = dependency('bash-completion', version : '>= 2.0', required : false) + +bashcomp_found = bashcomp_dep.found() +bash_completions_dir = '' +bash_helpers_dir = '' + +if bashcomp_found + # get_pkgconfig_variable() won't let us set the prefix + pkgconfig = find_program('pkg-config') + + runcmd = run_command(pkgconfig, + '--define-variable=prefix=.', + '--variable=completionsdir', + 'bash-completion') + + if (runcmd.returncode() == 0) + bash_completions_dir = runcmd.stdout().strip() + else + message('Found bash-completion but the .pc file did not set \'completionsdir\'.') + bashcomp_found = false + endif + + runcmd = run_command(pkgconfig, + '--define-variable=prefix=.', + '--variable=helpersdir', + 'bash-completion') + + if (runcmd.returncode() == 0) + bash_helpers_dir = runcmd.stdout().strip() + else + message('Found bash-completion, but the .pc file did not set \'helpersdir\'.') + bashcomp_found = false + endif +endif + +subdir('gst') +subdir('libs') +subdir('plugins') +subdir('tools') +subdir('pkgconfig') +subdir('tests') +subdir('data') + +# xgettext is optional (on Windows for instance) +if find_program('xgettext', required : false).found() + subdir('po') +endif + +configure_file(output : 'config.h', configuration : cdata) + +if build_machine.system() == 'windows' + message('Disabling gtk-doc while building on Windows') +elif get_option('disable_gtkdoc') + message('gtk-doc is disabled via options') +else + if find_program('gtkdoc-scan', required : false).found() + subdir('docs') + else + message('Not building documentation as gtk-doc was not found') + endif +endif + +run_command(python3, '-c', 'import shutil; shutil.copy("hooks/pre-commit.hook", ".git/hooks/pre-commit")') + +install_data('gst-element-check-1.0.m4', install_dir : join_paths(get_option('datadir'), 'aclocal')) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..5f4ac2b --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,24 @@ +option('build_tools', type : 'boolean', value : true) +option('poisoning', type : 'boolean', value : false) +option('disable_gtkdoc', type : 'boolean', value : false) +option('disable_examples', type : 'boolean', value : false) +option('disable_gst_debug', type : 'boolean', value : false) +option('disable_registry', type : 'boolean', value : false) +option('disable_tracer_hooks', type : 'boolean', value : false) +option('library_format', type : 'combo', choices : ['shared', 'static', 'both'], value : 'shared') +option('disable_introspection', + type : 'boolean', value : false, + description : 'Whether to disable the introspection generation') +option('disable_libunwind', + type : 'boolean', value : false, + description : 'Whether to disable the usage of libunwind (to generate backtraces)') +option('with-package-name', type : 'string', + description : 'package name to use in plugins') +option('with-package-origin', type : 'string', value : 'Unknown package origin', + description : 'package origin URL to use in plugins') +option('with-ptp-helper-setuid-user', type : 'string', + description : 'User to switch to when installing gst-ptp-helper setuid root') +option('with-ptp-helper-setuid-group', type : 'string', + description : 'Group to switch to when installing gst-ptp-helper setuid root') +option('with-ptp-helper-permissions', type : 'combo', + choices : ['none', 'setuid-root', 'capabilities', 'auto'], value : 'auto') diff --git a/missing b/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# 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. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am new file mode 100644 index 0000000..78a1e65 --- /dev/null +++ b/pkgconfig/Makefile.am @@ -0,0 +1,59 @@ +### all of the standard pc files we need to generate +if HAVE_CHECK +CHECK_PC_I = gstreamer-check-@GST_API_VERSION@.pc +CHECK_PC_U = gstreamer-check-@GST_API_VERSION@-uninstalled.pc +else +CHECK_PC_I = +CHECK_PC_U = +endif + +pcfiles = \ + gstreamer-@GST_API_VERSION@.pc \ + gstreamer-base-@GST_API_VERSION@.pc \ + $(CHECK_PC_I) \ + gstreamer-controller-@GST_API_VERSION@.pc \ + gstreamer-net-@GST_API_VERSION@.pc + +pcfiles_uninstalled = \ + gstreamer-@GST_API_VERSION@-uninstalled.pc \ + gstreamer-base-@GST_API_VERSION@-uninstalled.pc \ + $(CHECK_PC_U) \ + gstreamer-controller-@GST_API_VERSION@-uninstalled.pc \ + gstreamer-net-@GST_API_VERSION@-uninstalled.pc + +all-local: $(pcfiles) $(pcfiles_uninstalled) + +cp_verbose = $(cp_verbose_$(V)) +cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) +cp_verbose_0 = @echo " CP $@"; + +### how to generate pc files +%-@GST_API_VERSION@.pc: %.pc + $(cp_verbose_0)cp $< $@ +%-@GST_API_VERSION@-uninstalled.pc: %-uninstalled.pc +### the uninstalled libdir is depend of the build system used so set it here +### rather than hardcoding it in the file directly. + $(AM_V_GEN) sed \ + -e "s|[@]gstlibdir[@]|$(abs_top_builddir)/gst/.libs|" \ + -e "s|[@]checklibdir[@]|$(abs_top_builddir)/libs/gst/check/.libs|" \ + -e "s|[@]baselibdir[@]|$(abs_top_builddir)/libs/gst/base/.libs|" \ + -e "s|[@]netlibdir[@]|$(abs_top_builddir)/libs/gst/net/.libs|" \ + -e "s|[@]controllerlibdir[@]|$(abs_top_builddir)/libs/gst/controller/.libs|" \ + $< > $@.tmp && mv $@.tmp $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) + +EXTRA_DIST = \ + gstreamer.pc.in \ + gstreamer-uninstalled.pc.in \ + gstreamer-base.pc.in \ + gstreamer-base-uninstalled.pc.in \ + gstreamer-check.pc.in \ + gstreamer-check-uninstalled.pc.in \ + gstreamer-controller.pc.in \ + gstreamer-controller-uninstalled.pc.in \ + gstreamer-net.pc.in \ + gstreamer-net-uninstalled.pc.in + +CLEANFILES = $(pcfiles) $(pcfiles_uninstalled) diff --git a/pkgconfig/Makefile.in b/pkgconfig/Makefile.in new file mode 100644 index 0000000..b2910ec --- /dev/null +++ b/pkgconfig/Makefile.in @@ -0,0 +1,775 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = pkgconfig +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = gstreamer.pc gstreamer-uninstalled.pc \ + gstreamer-base.pc gstreamer-base-uninstalled.pc \ + gstreamer-check.pc gstreamer-check-uninstalled.pc \ + gstreamer-controller.pc gstreamer-controller-uninstalled.pc \ + gstreamer-net.pc gstreamer-net-uninstalled.pc +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/gstreamer-base-uninstalled.pc.in \ + $(srcdir)/gstreamer-base.pc.in \ + $(srcdir)/gstreamer-check-uninstalled.pc.in \ + $(srcdir)/gstreamer-check.pc.in \ + $(srcdir)/gstreamer-controller-uninstalled.pc.in \ + $(srcdir)/gstreamer-controller.pc.in \ + $(srcdir)/gstreamer-net-uninstalled.pc.in \ + $(srcdir)/gstreamer-net.pc.in \ + $(srcdir)/gstreamer-uninstalled.pc.in \ + $(srcdir)/gstreamer.pc.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@HAVE_CHECK_FALSE@CHECK_PC_I = + +### all of the standard pc files we need to generate +@HAVE_CHECK_TRUE@CHECK_PC_I = gstreamer-check-@GST_API_VERSION@.pc +@HAVE_CHECK_FALSE@CHECK_PC_U = +@HAVE_CHECK_TRUE@CHECK_PC_U = gstreamer-check-@GST_API_VERSION@-uninstalled.pc +pcfiles = \ + gstreamer-@GST_API_VERSION@.pc \ + gstreamer-base-@GST_API_VERSION@.pc \ + $(CHECK_PC_I) \ + gstreamer-controller-@GST_API_VERSION@.pc \ + gstreamer-net-@GST_API_VERSION@.pc + +pcfiles_uninstalled = \ + gstreamer-@GST_API_VERSION@-uninstalled.pc \ + gstreamer-base-@GST_API_VERSION@-uninstalled.pc \ + $(CHECK_PC_U) \ + gstreamer-controller-@GST_API_VERSION@-uninstalled.pc \ + gstreamer-net-@GST_API_VERSION@-uninstalled.pc + +cp_verbose = $(cp_verbose_$(V)) +cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) +cp_verbose_0 = @echo " CP $@"; +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) +EXTRA_DIST = \ + gstreamer.pc.in \ + gstreamer-uninstalled.pc.in \ + gstreamer-base.pc.in \ + gstreamer-base-uninstalled.pc.in \ + gstreamer-check.pc.in \ + gstreamer-check-uninstalled.pc.in \ + gstreamer-controller.pc.in \ + gstreamer-controller-uninstalled.pc.in \ + gstreamer-net.pc.in \ + gstreamer-net-uninstalled.pc.in + +CLEANFILES = $(pcfiles) $(pcfiles_uninstalled) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pkgconfig/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu pkgconfig/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +gstreamer.pc: $(top_builddir)/config.status $(srcdir)/gstreamer.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-base.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-base.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-base-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-base-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-check.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-check.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-check-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-check-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-controller.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-controller.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-controller-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-controller-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-net.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-net.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gstreamer-net-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/gstreamer-net-uninstalled.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) all-local +installdirs: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool cscopelist-am ctags-am distclean \ + distclean-generic distclean-libtool distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +all-local: $(pcfiles) $(pcfiles_uninstalled) + +### how to generate pc files +%-@GST_API_VERSION@.pc: %.pc + $(cp_verbose_0)cp $< $@ +%-@GST_API_VERSION@-uninstalled.pc: %-uninstalled.pc +### the uninstalled libdir is depend of the build system used so set it here +### rather than hardcoding it in the file directly. + $(AM_V_GEN) sed \ + -e "s|[@]gstlibdir[@]|$(abs_top_builddir)/gst/.libs|" \ + -e "s|[@]checklibdir[@]|$(abs_top_builddir)/libs/gst/check/.libs|" \ + -e "s|[@]baselibdir[@]|$(abs_top_builddir)/libs/gst/base/.libs|" \ + -e "s|[@]netlibdir[@]|$(abs_top_builddir)/libs/gst/net/.libs|" \ + -e "s|[@]controllerlibdir[@]|$(abs_top_builddir)/libs/gst/controller/.libs|" \ + $< > $@.tmp && mv $@.tmp $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pkgconfig/gstreamer-base-uninstalled.pc.in b/pkgconfig/gstreamer-base-uninstalled.pc.in new file mode 100644 index 0000000..08759f1 --- /dev/null +++ b/pkgconfig/gstreamer-base-uninstalled.pc.in @@ -0,0 +1,15 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=@baselibdir@ +includedir= +girdir=@abs_top_builddir@/libs/gst/base +typelibdir=@abs_top_builddir@/libs/gst/base + +Name: GStreamer base classes, uninstalled +Description: Base classes for GStreamer elements, Not Installed +Requires: gstreamer-@GST_API_VERSION@ = @VERSION@ +Version: @VERSION@ + +Libs: -L${libdir} -lgstbase-@GST_API_VERSION@ +Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs diff --git a/pkgconfig/gstreamer-base.pc.in b/pkgconfig/gstreamer-base.pc.in new file mode 100644 index 0000000..e24e050 --- /dev/null +++ b/pkgconfig/gstreamer-base.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer base classes +Description: Base classes for GStreamer elements +Requires: gstreamer-@GST_API_VERSION@ +Version: @VERSION@ +Libs: -L${libdir} -lgstbase-@GST_API_VERSION@ +Cflags: -I${includedir} diff --git a/pkgconfig/gstreamer-check-uninstalled.pc.in b/pkgconfig/gstreamer-check-uninstalled.pc.in new file mode 100644 index 0000000..85c2903 --- /dev/null +++ b/pkgconfig/gstreamer-check-uninstalled.pc.in @@ -0,0 +1,15 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=@checklibdir@ +includedir= +girdir=@abs_top_builddir@/libs/gst/check +typelibdir=@abs_top_builddir@/libs/gst/check + +Name: GStreamer check unit testing, uninstalled +Description: Unit testing helper library for GStreamer modules, Not Installed +Requires: gstreamer-@GST_API_VERSION@ = @VERSION@ +Version: @VERSION@ + +Libs: -L${libdir} -lgstcheck-@GST_API_VERSION@ @LIBM@ +Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs diff --git a/pkgconfig/gstreamer-check.pc.in b/pkgconfig/gstreamer-check.pc.in new file mode 100644 index 0000000..8c3a129 --- /dev/null +++ b/pkgconfig/gstreamer-check.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer check unit testing +Description: Unit testing helper library for GStreamer modules +Requires: gstreamer-@GST_API_VERSION@ +Version: @VERSION@ +Libs: -L${libdir} -lgstcheck-@GST_API_VERSION@ @LIBM@ +Cflags: -I${includedir} diff --git a/pkgconfig/gstreamer-controller-uninstalled.pc.in b/pkgconfig/gstreamer-controller-uninstalled.pc.in new file mode 100644 index 0000000..97983e7 --- /dev/null +++ b/pkgconfig/gstreamer-controller-uninstalled.pc.in @@ -0,0 +1,15 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=@controllerlibdir@ +includedir= +girdir=@abs_top_builddir@/libs/gst/controller +typelibdir=@abs_top_builddir@/libs/gst/controller + +Name: GStreamer controller, uninstalled +Description: Dynamic parameter control for GStreamer elements, Not Installed +Requires: gstreamer-@GST_API_VERSION@ = @VERSION@ +Version: @VERSION@ + +Libs: -L${libdir} -lgstcontroller-@GST_API_VERSION@ +Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs diff --git a/pkgconfig/gstreamer-controller.pc.in b/pkgconfig/gstreamer-controller.pc.in new file mode 100644 index 0000000..5118de4 --- /dev/null +++ b/pkgconfig/gstreamer-controller.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer controller +Description: Dynamic parameter control for GStreamer elements +Requires: gstreamer-@GST_API_VERSION@ +Version: @VERSION@ +Libs: -L${libdir} -lgstcontroller-@GST_API_VERSION@ +Cflags: -I${includedir} diff --git a/pkgconfig/gstreamer-net-uninstalled.pc.in b/pkgconfig/gstreamer-net-uninstalled.pc.in new file mode 100644 index 0000000..5d390c2 --- /dev/null +++ b/pkgconfig/gstreamer-net-uninstalled.pc.in @@ -0,0 +1,15 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=@netlibdir@ +includedir= +girdir=@abs_top_builddir@/libs/gst/net +typelibdir=@abs_top_builddir@/libs/gst/net + +Name: GStreamer networking library, uninstalled +Description: Network-enabled GStreamer plug-ins and clocking, uninstalled +Requires: gstreamer-@GST_API_VERSION@ = @VERSION@ gio-2.0 +Version: @VERSION@ + +Libs: -L${libdir} -lgstnet-@GST_API_VERSION@ +Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs diff --git a/pkgconfig/gstreamer-net.pc.in b/pkgconfig/gstreamer-net.pc.in new file mode 100644 index 0000000..aa4c3ab --- /dev/null +++ b/pkgconfig/gstreamer-net.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer networking library +Description: Network-enabled GStreamer plug-ins and clocking +Requires: gstreamer-@GST_API_VERSION@ gio-2.0 +Version: @VERSION@ +Libs: -L${libdir} -lgstnet-@GST_API_VERSION@ +Cflags: -I${includedir} diff --git a/pkgconfig/gstreamer-uninstalled.pc.in b/pkgconfig/gstreamer-uninstalled.pc.in new file mode 100644 index 0000000..d071612 --- /dev/null +++ b/pkgconfig/gstreamer-uninstalled.pc.in @@ -0,0 +1,20 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir=@gstlibdir@ +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@ +toolsdir=@abs_top_builddir@/tools +pluginsdir=@abs_top_builddir@ +girdir=@abs_top_builddir@/gst +bashhelpersdir=@abs_top_builddir@/data/bash-completion/helpers +helpersdir=@abs_top_builddir@/libs/gst/helpers +typelibdir=@abs_top_builddir@/gst + +Name: GStreamer Uninstalled +Description: Streaming media framework, Not Installed +Version: @VERSION@ +Requires: glib-2.0, gobject-2.0 +Requires.private: gmodule-no-export-2.0 @UNWIND_REQUIRE@ @DW_REQUIRE@ +Libs: -L${libdir} -lgstreamer-@GST_API_VERSION@ +Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/libs -I@abs_top_builddir@ -I@abs_top_builddir@/libs diff --git a/pkgconfig/gstreamer.pc.in b/pkgconfig/gstreamer.pc.in new file mode 100644 index 0000000..6ec3cb7 --- /dev/null +++ b/pkgconfig/gstreamer.pc.in @@ -0,0 +1,18 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +toolsdir=${exec_prefix}/bin +pluginsdir=@libdir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer +Description: Streaming media framework +Version: @VERSION@ +Requires: glib-2.0, gobject-2.0 +Requires.private: gmodule-no-export-2.0 @UNWIND_REQUIRE@ @DW_REQUIRE@ +Libs: -L${libdir} -lgstreamer-@GST_API_VERSION@ +Cflags: -I${includedir} diff --git a/pkgconfig/meson.build b/pkgconfig/meson.build new file mode 100644 index 0000000..edb0586 --- /dev/null +++ b/pkgconfig/meson.build @@ -0,0 +1,47 @@ +pkgconf = configuration_data() + +pkgconf.set('prefix', join_paths(get_option('prefix'))) +pkgconf.set('exec_prefix', '${prefix}') +pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir'))) +pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir'))) +pkgconf.set('GST_API_VERSION', apiversion) +pkgconf.set('VERSION', gst_version) +pkgconf.set('LIBM', mathlib.found() ? '-lm' : '') + +# Requires.private +pkgconf.set('UNWIND_REQUIRE', cdata.has('HAVE_UNWIND') ? 'libunwind' : '') +pkgconf.set('DW_REQUIRE', cdata.has('HAVE_DW') ? 'libdw' : '') + +# needed for generating -uninstalled.pc files +pkgconf.set('abs_top_builddir', join_paths(meson.current_build_dir(), '..')) +pkgconf.set('abs_top_srcdir', join_paths(meson.current_source_dir(), '..')) +pkgconf.set('gstlibdir', join_paths(meson.build_root(), libgst.outdir())) +pkgconf.set('baselibdir', join_paths(meson.build_root(), gst_base.outdir())) +pkgconf.set('controllerlibdir', join_paths(meson.build_root(), gst_controller.outdir())) +pkgconf.set('netlibdir', join_paths(meson.build_root(), gst_net.outdir())) + +pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir')) + +pkg_files = ['gstreamer-base', + 'gstreamer-controller', + 'gstreamer-check', + 'gstreamer-net', + 'gstreamer' +] + +pkgconf.set('checklibdir', join_paths(meson.build_root(), gst_check.outdir())) + +foreach p : pkg_files + infile = p + '.pc.in' + outfile = p + '-1.0.pc' + configure_file(input : infile, + output : outfile, + configuration : pkgconf, + install_dir : pkg_install_dir) + + infile = p + '-uninstalled.pc.in' + outfile = p + '-1.0-uninstalled.pc' + configure_file(input : infile, + output : outfile, + configuration : pkgconf) +endforeach diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 0000000..48a31fc --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = elements + +if !GST_DISABLE_GST_TRACER_HOOKS +SUBDIRS += tracers +endif + +DIST_SUBDIRS = elements tracers diff --git a/plugins/Makefile.in b/plugins/Makefile.in new file mode 100644 index 0000000..d2aace7 --- /dev/null +++ b/plugins/Makefile.in @@ -0,0 +1,813 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@GST_DISABLE_GST_TRACER_HOOKS_FALSE@am__append_1 = tracers +subdir = plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = elements $(am__append_1) +DIST_SUBDIRS = elements tracers +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am new file mode 100644 index 0000000..1bbc35f --- /dev/null +++ b/plugins/elements/Makefile.am @@ -0,0 +1,71 @@ + +plugin_LTLIBRARIES = libgstcoreelements.la + +libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la +libgstcoreelements_la_SOURCES = \ + gstcapsfilter.c \ + gstconcat.c \ + gstdataurisrc.c \ + gstdownloadbuffer.c \ + gstelements.c \ + gstelements_private.c \ + gstfakesrc.c \ + gstfakesink.c \ + gstfdsrc.c \ + gstfdsink.c \ + gstfilesink.c \ + gstfilesrc.c \ + gstfunnel.c \ + gstidentity.c \ + gstinputselector.c \ + gstoutputselector.c \ + gstmultiqueue.c \ + gstqueue.c \ + gstqueue2.c \ + gstsparsefile.c \ + gsttee.c \ + gsttypefindelement.c \ + gststreamiddemux.c \ + gstvalve.c + +libgstcoreelements_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstcoreelements_la_LIBADD = \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) +libgstcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = \ + gstcapsfilter.h \ + gstconcat.h \ + gstdataurisrc.h \ + gstdownloadbuffer.h \ + gstelements_private.h \ + gstfakesink.h \ + gstfakesrc.h \ + gstfdsrc.h \ + gstfdsink.h \ + gstfilesink.h \ + gstfilesrc.h \ + gstfunnel.h \ + gstidentity.h \ + gstinputselector.h \ + gstoutputselector.h \ + gstmultiqueue.h \ + gstqueue.h \ + gstqueue2.h \ + gstsparsefile.h \ + gsttee.h \ + gsttypefindelement.h \ + gststreamiddemux.h \ + gstvalve.h + +EXTRA_DIST = gstfdsrc.c \ + gstfdsink.c + + +CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out + +%.c.gcov: .libs/libgstcoreelements_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcoreelements_la_SOURCES:=.gcov) diff --git a/plugins/elements/Makefile.in b/plugins/elements/Makefile.in new file mode 100644 index 0000000..637780d --- /dev/null +++ b/plugins/elements/Makefile.in @@ -0,0 +1,1127 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = plugins/elements +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +am_libgstcoreelements_la_OBJECTS = \ + libgstcoreelements_la-gstcapsfilter.lo \ + libgstcoreelements_la-gstconcat.lo \ + libgstcoreelements_la-gstdataurisrc.lo \ + libgstcoreelements_la-gstdownloadbuffer.lo \ + libgstcoreelements_la-gstelements.lo \ + libgstcoreelements_la-gstelements_private.lo \ + libgstcoreelements_la-gstfakesrc.lo \ + libgstcoreelements_la-gstfakesink.lo \ + libgstcoreelements_la-gstfdsrc.lo \ + libgstcoreelements_la-gstfdsink.lo \ + libgstcoreelements_la-gstfilesink.lo \ + libgstcoreelements_la-gstfilesrc.lo \ + libgstcoreelements_la-gstfunnel.lo \ + libgstcoreelements_la-gstidentity.lo \ + libgstcoreelements_la-gstinputselector.lo \ + libgstcoreelements_la-gstoutputselector.lo \ + libgstcoreelements_la-gstmultiqueue.lo \ + libgstcoreelements_la-gstqueue.lo \ + libgstcoreelements_la-gstqueue2.lo \ + libgstcoreelements_la-gstsparsefile.lo \ + libgstcoreelements_la-gsttee.lo \ + libgstcoreelements_la-gsttypefindelement.lo \ + libgstcoreelements_la-gststreamiddemux.lo \ + libgstcoreelements_la-gstvalve.lo +libgstcoreelements_la_OBJECTS = $(am_libgstcoreelements_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstcoreelements_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstcoreelements_la_CFLAGS) $(CFLAGS) \ + $(libgstcoreelements_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstcoreelements_la_SOURCES) +DIST_SOURCES = $(libgstcoreelements_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +plugin_LTLIBRARIES = libgstcoreelements.la +libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la +libgstcoreelements_la_SOURCES = \ + gstcapsfilter.c \ + gstconcat.c \ + gstdataurisrc.c \ + gstdownloadbuffer.c \ + gstelements.c \ + gstelements_private.c \ + gstfakesrc.c \ + gstfakesink.c \ + gstfdsrc.c \ + gstfdsink.c \ + gstfilesink.c \ + gstfilesrc.c \ + gstfunnel.c \ + gstidentity.c \ + gstinputselector.c \ + gstoutputselector.c \ + gstmultiqueue.c \ + gstqueue.c \ + gstqueue2.c \ + gstsparsefile.c \ + gsttee.c \ + gsttypefindelement.c \ + gststreamiddemux.c \ + gstvalve.c + +libgstcoreelements_la_CFLAGS = $(GST_OBJ_CFLAGS) +libgstcoreelements_la_LIBADD = \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +libgstcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +noinst_HEADERS = \ + gstcapsfilter.h \ + gstconcat.h \ + gstdataurisrc.h \ + gstdownloadbuffer.h \ + gstelements_private.h \ + gstfakesink.h \ + gstfakesrc.h \ + gstfdsrc.h \ + gstfdsink.h \ + gstfilesink.h \ + gstfilesrc.h \ + gstfunnel.h \ + gstidentity.h \ + gstinputselector.h \ + gstoutputselector.h \ + gstmultiqueue.h \ + gstqueue.h \ + gstqueue2.h \ + gstsparsefile.h \ + gsttee.h \ + gsttypefindelement.h \ + gststreamiddemux.h \ + gstvalve.h + +EXTRA_DIST = gstfdsrc.c \ + gstfdsink.c + +CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/elements/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/elements/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstcoreelements.la: $(libgstcoreelements_la_OBJECTS) $(libgstcoreelements_la_DEPENDENCIES) $(EXTRA_libgstcoreelements_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstcoreelements_la_LINK) -rpath $(plugindir) $(libgstcoreelements_la_OBJECTS) $(libgstcoreelements_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstconcat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstdataurisrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstdownloadbuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstelements.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstelements_private.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfakesink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfakesrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfdsink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfdsrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfilesink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfilesrc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfunnel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstidentity.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstinputselector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstoutputselector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstqueue2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstsparsefile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gststreamiddemux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gsttee.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstvalve.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstcoreelements_la-gstcapsfilter.lo: gstcapsfilter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstcapsfilter.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Tpo -c -o libgstcoreelements_la-gstcapsfilter.lo `test -f 'gstcapsfilter.c' || echo '$(srcdir)/'`gstcapsfilter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Tpo $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcapsfilter.c' object='libgstcoreelements_la-gstcapsfilter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstcapsfilter.lo `test -f 'gstcapsfilter.c' || echo '$(srcdir)/'`gstcapsfilter.c + +libgstcoreelements_la-gstconcat.lo: gstconcat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstconcat.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstconcat.Tpo -c -o libgstcoreelements_la-gstconcat.lo `test -f 'gstconcat.c' || echo '$(srcdir)/'`gstconcat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstconcat.Tpo $(DEPDIR)/libgstcoreelements_la-gstconcat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstconcat.c' object='libgstcoreelements_la-gstconcat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstconcat.lo `test -f 'gstconcat.c' || echo '$(srcdir)/'`gstconcat.c + +libgstcoreelements_la-gstdataurisrc.lo: gstdataurisrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstdataurisrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstdataurisrc.Tpo -c -o libgstcoreelements_la-gstdataurisrc.lo `test -f 'gstdataurisrc.c' || echo '$(srcdir)/'`gstdataurisrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstdataurisrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstdataurisrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdataurisrc.c' object='libgstcoreelements_la-gstdataurisrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstdataurisrc.lo `test -f 'gstdataurisrc.c' || echo '$(srcdir)/'`gstdataurisrc.c + +libgstcoreelements_la-gstdownloadbuffer.lo: gstdownloadbuffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstdownloadbuffer.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstdownloadbuffer.Tpo -c -o libgstcoreelements_la-gstdownloadbuffer.lo `test -f 'gstdownloadbuffer.c' || echo '$(srcdir)/'`gstdownloadbuffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstdownloadbuffer.Tpo $(DEPDIR)/libgstcoreelements_la-gstdownloadbuffer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdownloadbuffer.c' object='libgstcoreelements_la-gstdownloadbuffer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstdownloadbuffer.lo `test -f 'gstdownloadbuffer.c' || echo '$(srcdir)/'`gstdownloadbuffer.c + +libgstcoreelements_la-gstelements.lo: gstelements.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstelements.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstelements.Tpo -c -o libgstcoreelements_la-gstelements.lo `test -f 'gstelements.c' || echo '$(srcdir)/'`gstelements.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstelements.Tpo $(DEPDIR)/libgstcoreelements_la-gstelements.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstelements.c' object='libgstcoreelements_la-gstelements.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstelements.lo `test -f 'gstelements.c' || echo '$(srcdir)/'`gstelements.c + +libgstcoreelements_la-gstelements_private.lo: gstelements_private.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstelements_private.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstelements_private.Tpo -c -o libgstcoreelements_la-gstelements_private.lo `test -f 'gstelements_private.c' || echo '$(srcdir)/'`gstelements_private.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstelements_private.Tpo $(DEPDIR)/libgstcoreelements_la-gstelements_private.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstelements_private.c' object='libgstcoreelements_la-gstelements_private.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstelements_private.lo `test -f 'gstelements_private.c' || echo '$(srcdir)/'`gstelements_private.c + +libgstcoreelements_la-gstfakesrc.lo: gstfakesrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfakesrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Tpo -c -o libgstcoreelements_la-gstfakesrc.lo `test -f 'gstfakesrc.c' || echo '$(srcdir)/'`gstfakesrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfakesrc.c' object='libgstcoreelements_la-gstfakesrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesrc.lo `test -f 'gstfakesrc.c' || echo '$(srcdir)/'`gstfakesrc.c + +libgstcoreelements_la-gstfakesink.lo: gstfakesink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfakesink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfakesink.Tpo -c -o libgstcoreelements_la-gstfakesink.lo `test -f 'gstfakesink.c' || echo '$(srcdir)/'`gstfakesink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfakesink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfakesink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfakesink.c' object='libgstcoreelements_la-gstfakesink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesink.lo `test -f 'gstfakesink.c' || echo '$(srcdir)/'`gstfakesink.c + +libgstcoreelements_la-gstfdsrc.lo: gstfdsrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfdsrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Tpo -c -o libgstcoreelements_la-gstfdsrc.lo `test -f 'gstfdsrc.c' || echo '$(srcdir)/'`gstfdsrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfdsrc.c' object='libgstcoreelements_la-gstfdsrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsrc.lo `test -f 'gstfdsrc.c' || echo '$(srcdir)/'`gstfdsrc.c + +libgstcoreelements_la-gstfdsink.lo: gstfdsink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfdsink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfdsink.Tpo -c -o libgstcoreelements_la-gstfdsink.lo `test -f 'gstfdsink.c' || echo '$(srcdir)/'`gstfdsink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfdsink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfdsink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfdsink.c' object='libgstcoreelements_la-gstfdsink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsink.lo `test -f 'gstfdsink.c' || echo '$(srcdir)/'`gstfdsink.c + +libgstcoreelements_la-gstfilesink.lo: gstfilesink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfilesink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfilesink.Tpo -c -o libgstcoreelements_la-gstfilesink.lo `test -f 'gstfilesink.c' || echo '$(srcdir)/'`gstfilesink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfilesink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfilesink.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfilesink.c' object='libgstcoreelements_la-gstfilesink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesink.lo `test -f 'gstfilesink.c' || echo '$(srcdir)/'`gstfilesink.c + +libgstcoreelements_la-gstfilesrc.lo: gstfilesrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfilesrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Tpo -c -o libgstcoreelements_la-gstfilesrc.lo `test -f 'gstfilesrc.c' || echo '$(srcdir)/'`gstfilesrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfilesrc.c' object='libgstcoreelements_la-gstfilesrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesrc.lo `test -f 'gstfilesrc.c' || echo '$(srcdir)/'`gstfilesrc.c + +libgstcoreelements_la-gstfunnel.lo: gstfunnel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfunnel.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfunnel.Tpo -c -o libgstcoreelements_la-gstfunnel.lo `test -f 'gstfunnel.c' || echo '$(srcdir)/'`gstfunnel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfunnel.Tpo $(DEPDIR)/libgstcoreelements_la-gstfunnel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfunnel.c' object='libgstcoreelements_la-gstfunnel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfunnel.lo `test -f 'gstfunnel.c' || echo '$(srcdir)/'`gstfunnel.c + +libgstcoreelements_la-gstidentity.lo: gstidentity.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstidentity.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstidentity.Tpo -c -o libgstcoreelements_la-gstidentity.lo `test -f 'gstidentity.c' || echo '$(srcdir)/'`gstidentity.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstidentity.Tpo $(DEPDIR)/libgstcoreelements_la-gstidentity.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstidentity.c' object='libgstcoreelements_la-gstidentity.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstidentity.lo `test -f 'gstidentity.c' || echo '$(srcdir)/'`gstidentity.c + +libgstcoreelements_la-gstinputselector.lo: gstinputselector.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstinputselector.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstinputselector.Tpo -c -o libgstcoreelements_la-gstinputselector.lo `test -f 'gstinputselector.c' || echo '$(srcdir)/'`gstinputselector.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstinputselector.Tpo $(DEPDIR)/libgstcoreelements_la-gstinputselector.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstinputselector.c' object='libgstcoreelements_la-gstinputselector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstinputselector.lo `test -f 'gstinputselector.c' || echo '$(srcdir)/'`gstinputselector.c + +libgstcoreelements_la-gstoutputselector.lo: gstoutputselector.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstoutputselector.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Tpo -c -o libgstcoreelements_la-gstoutputselector.lo `test -f 'gstoutputselector.c' || echo '$(srcdir)/'`gstoutputselector.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Tpo $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstoutputselector.c' object='libgstcoreelements_la-gstoutputselector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstoutputselector.lo `test -f 'gstoutputselector.c' || echo '$(srcdir)/'`gstoutputselector.c + +libgstcoreelements_la-gstmultiqueue.lo: gstmultiqueue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstmultiqueue.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Tpo -c -o libgstcoreelements_la-gstmultiqueue.lo `test -f 'gstmultiqueue.c' || echo '$(srcdir)/'`gstmultiqueue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Tpo $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstmultiqueue.c' object='libgstcoreelements_la-gstmultiqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstmultiqueue.lo `test -f 'gstmultiqueue.c' || echo '$(srcdir)/'`gstmultiqueue.c + +libgstcoreelements_la-gstqueue.lo: gstqueue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstqueue.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstqueue.Tpo -c -o libgstcoreelements_la-gstqueue.lo `test -f 'gstqueue.c' || echo '$(srcdir)/'`gstqueue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstqueue.Tpo $(DEPDIR)/libgstcoreelements_la-gstqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueue.c' object='libgstcoreelements_la-gstqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue.lo `test -f 'gstqueue.c' || echo '$(srcdir)/'`gstqueue.c + +libgstcoreelements_la-gstqueue2.lo: gstqueue2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstqueue2.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstqueue2.Tpo -c -o libgstcoreelements_la-gstqueue2.lo `test -f 'gstqueue2.c' || echo '$(srcdir)/'`gstqueue2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstqueue2.Tpo $(DEPDIR)/libgstcoreelements_la-gstqueue2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueue2.c' object='libgstcoreelements_la-gstqueue2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue2.lo `test -f 'gstqueue2.c' || echo '$(srcdir)/'`gstqueue2.c + +libgstcoreelements_la-gstsparsefile.lo: gstsparsefile.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstsparsefile.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstsparsefile.Tpo -c -o libgstcoreelements_la-gstsparsefile.lo `test -f 'gstsparsefile.c' || echo '$(srcdir)/'`gstsparsefile.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstsparsefile.Tpo $(DEPDIR)/libgstcoreelements_la-gstsparsefile.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsparsefile.c' object='libgstcoreelements_la-gstsparsefile.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstsparsefile.lo `test -f 'gstsparsefile.c' || echo '$(srcdir)/'`gstsparsefile.c + +libgstcoreelements_la-gsttee.lo: gsttee.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gsttee.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gsttee.Tpo -c -o libgstcoreelements_la-gsttee.lo `test -f 'gsttee.c' || echo '$(srcdir)/'`gsttee.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gsttee.Tpo $(DEPDIR)/libgstcoreelements_la-gsttee.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttee.c' object='libgstcoreelements_la-gsttee.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttee.lo `test -f 'gsttee.c' || echo '$(srcdir)/'`gsttee.c + +libgstcoreelements_la-gsttypefindelement.lo: gsttypefindelement.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gsttypefindelement.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Tpo -c -o libgstcoreelements_la-gsttypefindelement.lo `test -f 'gsttypefindelement.c' || echo '$(srcdir)/'`gsttypefindelement.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Tpo $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttypefindelement.c' object='libgstcoreelements_la-gsttypefindelement.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttypefindelement.lo `test -f 'gsttypefindelement.c' || echo '$(srcdir)/'`gsttypefindelement.c + +libgstcoreelements_la-gststreamiddemux.lo: gststreamiddemux.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gststreamiddemux.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gststreamiddemux.Tpo -c -o libgstcoreelements_la-gststreamiddemux.lo `test -f 'gststreamiddemux.c' || echo '$(srcdir)/'`gststreamiddemux.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gststreamiddemux.Tpo $(DEPDIR)/libgstcoreelements_la-gststreamiddemux.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gststreamiddemux.c' object='libgstcoreelements_la-gststreamiddemux.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gststreamiddemux.lo `test -f 'gststreamiddemux.c' || echo '$(srcdir)/'`gststreamiddemux.c + +libgstcoreelements_la-gstvalve.lo: gstvalve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstvalve.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstvalve.Tpo -c -o libgstcoreelements_la-gstvalve.lo `test -f 'gstvalve.c' || echo '$(srcdir)/'`gstvalve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstvalve.Tpo $(DEPDIR)/libgstcoreelements_la-gstvalve.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstvalve.c' object='libgstcoreelements_la-gstvalve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstvalve.lo `test -f 'gstvalve.c' || echo '$(srcdir)/'`gstvalve.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +%.c.gcov: .libs/libgstcoreelements_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcoreelements_la_SOURCES:=.gcov) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/elements/gstcapsfilter.c b/plugins/elements/gstcapsfilter.c new file mode 100644 index 0000000..69b23f7 --- /dev/null +++ b/plugins/elements/gstcapsfilter.c @@ -0,0 +1,576 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-capsfilter + * @title: capsfilter + * + * The element does not modify data as such, but can enforce limitations on the + * data format. + * + * ## Example launch line + * |[ + * gst-launch-1.0 videotestsrc ! capsfilter caps=video/x-raw,format=GRAY8 ! videoconvert ! autovideosink + * ]| Limits acceptable video from videotestsrc to be grayscale. Equivalent to + * |[ + * gst-launch-1.0 videotestsrc ! video/x-raw,format=GRAY8 ! videoconvert ! autovideosink + * ]| which is a short notation for the capsfilter element. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../../gst/gst-i18n-lib.h" +#include "gstcapsfilter.h" + +enum +{ + PROP_0, + PROP_FILTER_CAPS, + PROP_CAPS_CHANGE_MODE +}; + +#define DEFAULT_CAPS_CHANGE_MODE (GST_CAPS_FILTER_CAPS_CHANGE_MODE_IMMEDIATE) + +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); + + +GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug); +#define GST_CAT_DEFAULT gst_capsfilter_debug + +/* TODO: Add a drop-buffers mode */ +#define GST_TYPE_CAPS_FILTER_CAPS_CHANGE_MODE (gst_caps_filter_caps_change_mode_get_type()) +static GType +gst_caps_filter_caps_change_mode_get_type (void) +{ + static GType type = 0; + static const GEnumValue data[] = { + {GST_CAPS_FILTER_CAPS_CHANGE_MODE_IMMEDIATE, + "Only accept the current filter caps", "immediate"}, + {GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED, + "Temporarily accept previous filter caps", "delayed"}, + {0, NULL, NULL}, + }; + + if (!type) { + type = g_enum_register_static ("GstCapsFilterCapsChangeMode", data); + } + return type; +} + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, \ + "capsfilter element"); +#define gst_capsfilter_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstCapsFilter, gst_capsfilter, GST_TYPE_BASE_TRANSFORM, + _do_init); + + +static void gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_capsfilter_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_capsfilter_dispose (GObject * object); + +static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static gboolean gst_capsfilter_accept_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base, + GstBuffer * buf); +static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans, + GstBuffer * input, GstBuffer ** buf); +static gboolean gst_capsfilter_sink_event (GstBaseTransform * trans, + GstEvent * event); +static gboolean gst_capsfilter_stop (GstBaseTransform * trans); + +static void +gst_capsfilter_class_init (GstCapsFilterClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseTransformClass *trans_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->set_property = gst_capsfilter_set_property; + gobject_class->get_property = gst_capsfilter_get_property; + gobject_class->dispose = gst_capsfilter_dispose; + + g_object_class_install_property (gobject_class, PROP_FILTER_CAPS, + g_param_spec_boxed ("caps", _("Filter caps"), + _("Restrict the possible allowed capabilities (NULL means ANY). " + "Setting this property takes a reference to the supplied GstCaps " + "object."), GST_TYPE_CAPS, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CAPS_CHANGE_MODE, + g_param_spec_enum ("caps-change-mode", _("Caps Change Mode"), + _("Filter caps change behaviour"), + GST_TYPE_CAPS_FILTER_CAPS_CHANGE_MODE, DEFAULT_CAPS_CHANGE_MODE, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + gstelement_class = GST_ELEMENT_CLASS (klass); + gst_element_class_set_static_metadata (gstelement_class, + "CapsFilter", + "Generic", + "Pass data without modification, limiting formats", + "David Schleef "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + trans_class = GST_BASE_TRANSFORM_CLASS (klass); + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_capsfilter_transform_caps); + trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_capsfilter_transform_ip); + trans_class->accept_caps = GST_DEBUG_FUNCPTR (gst_capsfilter_accept_caps); + trans_class->prepare_output_buffer = + GST_DEBUG_FUNCPTR (gst_capsfilter_prepare_buf); + trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_capsfilter_sink_event); + trans_class->stop = GST_DEBUG_FUNCPTR (gst_capsfilter_stop); +} + +static void +gst_capsfilter_init (GstCapsFilter * filter) +{ + GstBaseTransform *trans = GST_BASE_TRANSFORM (filter); + gst_base_transform_set_gap_aware (trans, TRUE); + gst_base_transform_set_prefer_passthrough (trans, FALSE); + filter->filter_caps = gst_caps_new_any (); + filter->filter_caps_used = FALSE; + filter->got_sink_caps = FALSE; + filter->caps_change_mode = DEFAULT_CAPS_CHANGE_MODE; +} + +static void +gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCapsFilter *capsfilter = GST_CAPS_FILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS:{ + GstCaps *new_caps; + GstCaps *old_caps; + const GstCaps *new_caps_val = gst_value_get_caps (value); + + if (new_caps_val == NULL) { + new_caps = gst_caps_new_any (); + } else { + new_caps = (GstCaps *) new_caps_val; + gst_caps_ref (new_caps); + } + + GST_OBJECT_LOCK (capsfilter); + old_caps = capsfilter->filter_caps; + capsfilter->filter_caps = new_caps; + if (old_caps && capsfilter->filter_caps_used && + capsfilter->caps_change_mode == + GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED) { + capsfilter->previous_caps = + g_list_prepend (capsfilter->previous_caps, gst_caps_ref (old_caps)); + } else if (capsfilter->caps_change_mode != + GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED) { + g_list_free_full (capsfilter->previous_caps, + (GDestroyNotify) gst_caps_unref); + capsfilter->previous_caps = NULL; + } + capsfilter->filter_caps_used = FALSE; + GST_OBJECT_UNLOCK (capsfilter); + + gst_caps_unref (old_caps); + + GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps); + + gst_base_transform_reconfigure_sink (GST_BASE_TRANSFORM (object)); + break; + } + case PROP_CAPS_CHANGE_MODE:{ + GstCapsFilterCapsChangeMode old_change_mode; + + GST_OBJECT_LOCK (capsfilter); + old_change_mode = capsfilter->caps_change_mode; + capsfilter->caps_change_mode = g_value_get_enum (value); + + if (capsfilter->caps_change_mode != old_change_mode) { + g_list_free_full (capsfilter->previous_caps, + (GDestroyNotify) gst_caps_unref); + capsfilter->previous_caps = NULL; + } + GST_OBJECT_UNLOCK (capsfilter); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstCapsFilter *capsfilter = GST_CAPS_FILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + GST_OBJECT_LOCK (capsfilter); + gst_value_set_caps (value, capsfilter->filter_caps); + GST_OBJECT_UNLOCK (capsfilter); + break; + case PROP_CAPS_CHANGE_MODE: + g_value_set_enum (value, capsfilter->caps_change_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_capsfilter_dispose (GObject * object) +{ + GstCapsFilter *filter = GST_CAPS_FILTER (object); + + gst_caps_replace (&filter->filter_caps, NULL); + g_list_free_full (filter->pending_events, (GDestroyNotify) gst_event_unref); + filter->pending_events = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static GstCaps * +gst_capsfilter_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) +{ + GstCapsFilter *capsfilter = GST_CAPS_FILTER (base); + GstCaps *ret, *filter_caps, *tmp; + gboolean retried = FALSE; + GstCapsFilterCapsChangeMode caps_change_mode; + + GST_OBJECT_LOCK (capsfilter); + filter_caps = gst_caps_ref (capsfilter->filter_caps); + capsfilter->filter_caps_used = TRUE; + caps_change_mode = capsfilter->caps_change_mode; + GST_OBJECT_UNLOCK (capsfilter); + +retry: + if (filter) { + tmp = + gst_caps_intersect_full (filter, filter_caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (filter_caps); + filter_caps = tmp; + } + + ret = gst_caps_intersect_full (filter_caps, caps, GST_CAPS_INTERSECT_FIRST); + + GST_DEBUG_OBJECT (capsfilter, "input: %" GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (capsfilter, "filter: %" GST_PTR_FORMAT, filter); + GST_DEBUG_OBJECT (capsfilter, "caps filter: %" GST_PTR_FORMAT, + filter_caps); + GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret); + + if (gst_caps_is_empty (ret) + && caps_change_mode == + GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED && capsfilter->previous_caps + && !retried) { + GList *l; + + GST_DEBUG_OBJECT (capsfilter, + "Current filter caps are not compatible, retry with previous"); + GST_OBJECT_LOCK (capsfilter); + gst_caps_unref (filter_caps); + gst_caps_unref (ret); + filter_caps = gst_caps_new_empty (); + for (l = capsfilter->previous_caps; l; l = l->next) { + filter_caps = gst_caps_merge (filter_caps, gst_caps_ref (l->data)); + } + GST_OBJECT_UNLOCK (capsfilter); + retried = TRUE; + goto retry; + } + + gst_caps_unref (filter_caps); + + return ret; +} + +static gboolean +gst_capsfilter_accept_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) +{ + GstCapsFilter *capsfilter = GST_CAPS_FILTER (base); + GstCaps *filter_caps; + gboolean ret; + + GST_OBJECT_LOCK (capsfilter); + filter_caps = gst_caps_ref (capsfilter->filter_caps); + capsfilter->filter_caps_used = TRUE; + GST_OBJECT_UNLOCK (capsfilter); + + ret = gst_caps_can_intersect (caps, filter_caps); + GST_DEBUG_OBJECT (capsfilter, "can intersect: %d", ret); + if (!ret + && capsfilter->caps_change_mode == + GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED) { + GList *l; + + GST_OBJECT_LOCK (capsfilter); + for (l = capsfilter->previous_caps; l; l = l->next) { + ret = gst_caps_can_intersect (caps, l->data); + if (ret) + break; + } + GST_OBJECT_UNLOCK (capsfilter); + + /* Tell upstream to reconfigure, it's still + * looking at old caps */ + if (ret) + gst_base_transform_reconfigure_sink (base); + } + + gst_caps_unref (filter_caps); + + return ret; +} + +static GstFlowReturn +gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf) +{ + /* No actual work here. It's all done in the prepare output buffer + * func. */ + return GST_FLOW_OK; +} + +static void +gst_capsfilter_push_pending_events (GstCapsFilter * filter, GList * events) +{ + GList *l; + + for (l = g_list_last (events); l; l = l->prev) { + GST_LOG_OBJECT (filter, "Forwarding %s event", + GST_EVENT_TYPE_NAME (l->data)); + GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (GST_BASE_TRANSFORM_CAST + (filter), l->data); + } + g_list_free (events); +} + +/* Ouput buffer preparation ... if the buffer has no caps, and our allowed + * output caps is fixed, then send the caps downstream, making sure caps are + * sent before segment event. + * + * This ensures that caps event is sent if we can, so that pipelines like: + * gst-launch filesrc location=rawsamples.raw ! + * audio/x-raw,format=S16LE,rate=48000,channels=2 ! alsasink + * will work. + */ +static GstFlowReturn +gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input, + GstBuffer ** buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstCapsFilter *filter = GST_CAPS_FILTER (trans); + + /* always return the input as output buffer */ + *buf = input; + + if (GST_PAD_MODE (trans->srcpad) == GST_PAD_MODE_PUSH + && !filter->got_sink_caps) { + + /* No caps. See if the output pad only supports fixed caps */ + GstCaps *out_caps; + GList *pending_events = filter->pending_events; + + GST_LOG_OBJECT (trans, "Input pad does not have caps"); + + filter->pending_events = NULL; + + out_caps = gst_pad_get_current_caps (trans->srcpad); + if (out_caps == NULL) { + out_caps = gst_pad_get_allowed_caps (trans->srcpad); + g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); + } + + out_caps = gst_caps_simplify (out_caps); + + if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) { + GST_DEBUG_OBJECT (trans, "Have fixed output caps %" + GST_PTR_FORMAT " to apply to srcpad", out_caps); + + if (!gst_pad_has_current_caps (trans->srcpad)) { + if (gst_pad_set_caps (trans->srcpad, out_caps)) { + if (pending_events) { + gst_capsfilter_push_pending_events (filter, pending_events); + pending_events = NULL; + } + } else { + ret = GST_FLOW_NOT_NEGOTIATED; + } + } else { + gst_capsfilter_push_pending_events (filter, pending_events); + pending_events = NULL; + } + + g_list_free_full (pending_events, (GDestroyNotify) gst_event_unref); + gst_caps_unref (out_caps); + } else { + gchar *caps_str = gst_caps_to_string (out_caps); + + GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %" + GST_PTR_FORMAT, out_caps); + gst_caps_unref (out_caps); + + GST_ELEMENT_ERROR (trans, STREAM, FORMAT, + ("Filter caps do not completely specify the output format"), + ("Output caps are unfixed: %s", caps_str)); + + g_free (caps_str); + g_list_free_full (pending_events, (GDestroyNotify) gst_event_unref); + + ret = GST_FLOW_ERROR; + } + } else if (G_UNLIKELY (filter->pending_events)) { + GList *events = filter->pending_events; + + filter->pending_events = NULL; + + /* push pending events before a buffer */ + gst_capsfilter_push_pending_events (filter, events); + } + + return ret; +} + +/* Queue the segment event if there was no caps event */ +static gboolean +gst_capsfilter_sink_event (GstBaseTransform * trans, GstEvent * event) +{ + GstCapsFilter *filter = GST_CAPS_FILTER (trans); + gboolean ret; + + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + GList *l; + + for (l = filter->pending_events; l; l = l->next) { + if (GST_EVENT_TYPE (l->data) == GST_EVENT_SEGMENT || + GST_EVENT_TYPE (l->data) == GST_EVENT_EOS) { + gst_event_unref (l->data); + filter->pending_events = g_list_delete_link (filter->pending_events, l); + break; + } + } + } + + if (!GST_EVENT_IS_STICKY (event) + || GST_EVENT_TYPE (event) <= GST_EVENT_CAPS) + goto done; + + /* If we get EOS before any buffers, just push all pending events */ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GList *l; + + for (l = g_list_last (filter->pending_events); l; l = l->prev) { + GST_LOG_OBJECT (trans, "Forwarding %s event", + GST_EVENT_TYPE_NAME (l->data)); + GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, l->data); + } + g_list_free (filter->pending_events); + filter->pending_events = NULL; + } else if (!filter->got_sink_caps) { + GST_LOG_OBJECT (trans, "Got %s event before caps, queueing", + GST_EVENT_TYPE_NAME (event)); + + filter->pending_events = g_list_prepend (filter->pending_events, event); + + return TRUE; + } + +done: + + GST_LOG_OBJECT (trans, "Forwarding %s event", GST_EVENT_TYPE_NAME (event)); + ret = + GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, + gst_event_ref (event)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) { + filter->got_sink_caps = TRUE; + if (filter->caps_change_mode == GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED) { + GList *l; + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + + /* Remove all previous caps up to one that works. + * Note that this might keep some leftover caps if there + * are multiple compatible caps */ + GST_OBJECT_LOCK (filter); + for (l = g_list_last (filter->previous_caps); l; l = l->prev) { + if (gst_caps_can_intersect (caps, l->data)) { + while (l->next) { + gst_caps_unref (l->next->data); + l = g_list_delete_link (l, l->next); + } + break; + } + } + if (!l && gst_caps_can_intersect (caps, filter->filter_caps)) { + g_list_free_full (filter->previous_caps, + (GDestroyNotify) gst_caps_unref); + filter->previous_caps = NULL; + filter->filter_caps_used = TRUE; + } + GST_OBJECT_UNLOCK (filter); + } + } + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_capsfilter_stop (GstBaseTransform * trans) +{ + GstCapsFilter *filter = GST_CAPS_FILTER (trans); + + g_list_free_full (filter->pending_events, (GDestroyNotify) gst_event_unref); + filter->pending_events = NULL; + + GST_OBJECT_LOCK (filter); + g_list_free_full (filter->previous_caps, (GDestroyNotify) gst_caps_unref); + filter->previous_caps = NULL; + GST_OBJECT_UNLOCK (filter); + + filter->got_sink_caps = FALSE; + + return TRUE; +} diff --git a/plugins/elements/gstcapsfilter.h b/plugins/elements/gstcapsfilter.h new file mode 100644 index 0000000..8a57bc4 --- /dev/null +++ b/plugins/elements/gstcapsfilter.h @@ -0,0 +1,85 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstidentity.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_CAPS_FILTER_H__ +#define __GST_CAPS_FILTER_H__ + + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CAPS_FILTER \ + (gst_capsfilter_get_type()) +#define GST_CAPS_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPS_FILTER,GstCapsFilter)) +#define GST_CAPS_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPS_FILTER,GstCapsFilterClass)) +#define GST_IS_CAPS_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPS_FILTER)) +#define GST_IS_CAPS_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPS_FILTER)) + +typedef struct _GstCapsFilter GstCapsFilter; +typedef struct _GstCapsFilterClass GstCapsFilterClass; + +/** + * GstCapsFilterCapsChangeMode: + * @GST_CAPS_FILTER_CAPS_CHANGE_MODE_IMMEDIATE: Only accept the current filter caps + * @GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED: Temporarily accept previous filter caps + * + * Filter caps change behaviour + */ +typedef enum { + GST_CAPS_FILTER_CAPS_CHANGE_MODE_IMMEDIATE, + GST_CAPS_FILTER_CAPS_CHANGE_MODE_DELAYED +} GstCapsFilterCapsChangeMode; + +/** + * GstCapsFilter: + * + * The opaque #GstCapsFilter data structure. + */ +struct _GstCapsFilter { + GstBaseTransform trans; + + GstCaps *filter_caps; + gboolean filter_caps_used; + GstCapsFilterCapsChangeMode caps_change_mode; + gboolean got_sink_caps; + + GList *pending_events; + GList *previous_caps; +}; + +struct _GstCapsFilterClass { + GstBaseTransformClass trans_class; +}; + +G_GNUC_INTERNAL GType gst_capsfilter_get_type (void); + +G_END_DECLS + +#endif /* __GST_CAPS_FILTER_H__ */ + diff --git a/plugins/elements/gstconcat.c b/plugins/elements/gstconcat.c new file mode 100644 index 0000000..8513ef3 --- /dev/null +++ b/plugins/elements/gstconcat.c @@ -0,0 +1,864 @@ +/* GStreamer concat element + * + * Copyright (c) 2014 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +/** + * SECTION:element-concat + * @title: concat + * @see_also: #GstFunnel + * + * Concatenates streams together to one continous stream. + * + * All streams but the current one are blocked until the current one + * finished with %GST_EVENT_EOS. Then the next stream is enabled, while + * keeping the running time continous for %GST_FORMAT_TIME segments or + * keeping the segment continous for %GST_FORMAT_BYTES segments. + * + * Streams are switched in the order in which the sinkpads were requested. + * + * By default, the stream segment's base values are adjusted to ensure + * the segment transitions between streams are continuous. In some cases, + * it may be desirable to turn off these adjustments (for example, because + * another downstream element like a streamsynchronizer adjusts the base + * values on its own). The adjust-base property can be used for this purpose. + * + * ## Example launch line + * |[ + * gst-launch-1.0 concat name=c ! xvimagesink videotestsrc num-buffers=100 ! c. videotestsrc num-buffers=100 pattern=ball ! c. + * ]| Plays two video streams one after another. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstconcat.h" + +GST_DEBUG_CATEGORY_STATIC (gst_concat_debug); +#define GST_CAT_DEFAULT gst_concat_debug + +G_GNUC_INTERNAL GType gst_concat_pad_get_type (void); + +#define GST_TYPE_CONCAT_PAD (gst_concat_pad_get_type()) +#define GST_CONCAT_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CONCAT_PAD, GstConcatPad)) +#define GST_CONCAT_PAD_CAST(obj) ((GstConcatPad *)(obj)) +#define GST_CONCAT_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CONCAT_PAD, GstConcatPadClass)) +#define GST_IS_CONCAT_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CONCAT_PAD)) +#define GST_IS_CONCAT_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CONCAT_PAD)) + +typedef struct _GstConcatPad GstConcatPad; +typedef struct _GstConcatPadClass GstConcatPadClass; + +struct _GstConcatPad +{ + GstPad parent; + + GstSegment segment; + + /* Protected by the concat lock */ + gboolean flushing; +}; + +struct _GstConcatPadClass +{ + GstPadClass parent; +}; + +G_DEFINE_TYPE (GstConcatPad, gst_concat_pad, GST_TYPE_PAD); + +static void +gst_concat_pad_class_init (GstConcatPadClass * klass) +{ +} + +static void +gst_concat_pad_init (GstConcatPad * self) +{ + gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); + self->flushing = FALSE; +} + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_ACTIVE_PAD, + PROP_ADJUST_BASE +}; + +#define DEFAULT_ADJUST_BASE TRUE + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_concat_debug, "concat", 0, "concat element"); +#define gst_concat_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstConcat, gst_concat, GST_TYPE_ELEMENT, _do_init); + +static void gst_concat_dispose (GObject * object); +static void gst_concat_finalize (GObject * object); +static void gst_concat_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_concat_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_concat_change_state (GstElement * element, + GstStateChange transition); +static GstPad *gst_concat_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); +static void gst_concat_release_pad (GstElement * element, GstPad * pad); + +static GstFlowReturn gst_concat_sink_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_concat_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_concat_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static gboolean gst_concat_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_concat_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static gboolean gst_concat_switch_pad (GstConcat * self); + +static void gst_concat_notify_active_pad (GstConcat * self); + +static GParamSpec *pspec_active_pad = NULL; + +static void +gst_concat_class_init (GstConcatClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_concat_dispose); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_concat_finalize); + + gobject_class->get_property = gst_concat_get_property; + gobject_class->set_property = gst_concat_set_property; + + pspec_active_pad = g_param_spec_object ("active-pad", "Active pad", + "Currently active src pad", GST_TYPE_PAD, G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, + pspec_active_pad); + g_object_class_install_property (gobject_class, PROP_ADJUST_BASE, + g_param_spec_boolean ("adjust-base", "Adjust segment base", + "Adjust the base value of segments to ensure they are adjacent", + DEFAULT_ADJUST_BASE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, + "Concat", "Generic", "Concatenate multiple streams", + "Sebastian Dröge "); + + gst_element_class_add_static_pad_template (gstelement_class, &sink_template); + gst_element_class_add_static_pad_template (gstelement_class, &src_template); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_concat_request_new_pad); + gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_concat_release_pad); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_concat_change_state); +} + +static void +gst_concat_init (GstConcat * self) +{ + g_mutex_init (&self->lock); + g_cond_init (&self->cond); + + self->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_event_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_concat_src_event)); + gst_pad_set_query_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_concat_src_query)); + gst_pad_use_fixed_caps (self->srcpad); + + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + self->adjust_base = DEFAULT_ADJUST_BASE; +} + +static void +gst_concat_dispose (GObject * object) +{ + GstConcat *self = GST_CONCAT (object); + GList *item; + + gst_object_replace ((GstObject **) & self->current_sinkpad, NULL); + +restart: + for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { + GstPad *pad = GST_PAD (item->data); + + if (GST_PAD_IS_SINK (pad)) { + gst_element_release_request_pad (GST_ELEMENT (object), pad); + goto restart; + } + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_concat_finalize (GObject * object) +{ + GstConcat *self = GST_CONCAT (object); + + g_mutex_clear (&self->lock); + g_cond_clear (&self->cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_concat_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstConcat *self = GST_CONCAT (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD:{ + g_mutex_lock (&self->lock); + g_value_set_object (value, self->current_sinkpad); + g_mutex_unlock (&self->lock); + break; + } + case PROP_ADJUST_BASE:{ + g_mutex_lock (&self->lock); + g_value_set_boolean (value, self->adjust_base); + g_mutex_unlock (&self->lock); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_concat_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstConcat *self = GST_CONCAT (object); + + switch (prop_id) { + case PROP_ADJUST_BASE:{ + g_mutex_lock (&self->lock); + self->adjust_base = g_value_get_boolean (value); + g_mutex_unlock (&self->lock); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_concat_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstConcat *self = GST_CONCAT (element); + GstPad *sinkpad; + gchar *pad_name; + gboolean do_notify = FALSE; + + GST_DEBUG_OBJECT (element, "requesting pad"); + + g_mutex_lock (&self->lock); + pad_name = g_strdup_printf ("sink_%u", self->pad_count); + self->pad_count++; + g_mutex_unlock (&self->lock); + + sinkpad = GST_PAD_CAST (g_object_new (GST_TYPE_CONCAT_PAD, + "name", pad_name, "direction", templ->direction, "template", templ, + NULL)); + g_free (pad_name); + + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_concat_sink_chain)); + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_concat_sink_event)); + gst_pad_set_query_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_concat_sink_query)); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); + + gst_pad_set_active (sinkpad, TRUE); + + g_mutex_lock (&self->lock); + self->sinkpads = g_list_prepend (self->sinkpads, gst_object_ref (sinkpad)); + if (!self->current_sinkpad) { + do_notify = TRUE; + self->current_sinkpad = gst_object_ref (sinkpad); + } + g_mutex_unlock (&self->lock); + + gst_element_add_pad (element, sinkpad); + + if (do_notify) + gst_concat_notify_active_pad (self); + + return sinkpad; +} + +static void +gst_concat_release_pad (GstElement * element, GstPad * pad) +{ + GstConcat *self = GST_CONCAT (element); + GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad); + GList *l; + gboolean current_pad_removed = FALSE; + gboolean eos = FALSE; + gboolean do_notify = FALSE; + + GST_DEBUG_OBJECT (self, "releasing pad"); + + g_mutex_lock (&self->lock); + spad->flushing = TRUE; + g_cond_broadcast (&self->cond); + g_mutex_unlock (&self->lock); + + gst_pad_set_active (pad, FALSE); + + /* Now the pad is definitely not running anymore */ + + g_mutex_lock (&self->lock); + if (self->current_sinkpad == GST_PAD_CAST (spad)) { + eos = !gst_concat_switch_pad (self); + current_pad_removed = TRUE; + do_notify = TRUE; + } + + for (l = self->sinkpads; l; l = l->next) { + if ((gpointer) spad == l->data) { + gst_object_unref (spad); + self->sinkpads = g_list_delete_link (self->sinkpads, l); + break; + } + } + g_mutex_unlock (&self->lock); + + gst_element_remove_pad (GST_ELEMENT_CAST (self), pad); + + if (do_notify) + gst_concat_notify_active_pad (self); + + if (GST_STATE (self) > GST_STATE_READY) { + if (current_pad_removed && !eos) + gst_element_post_message (GST_ELEMENT_CAST (self), + gst_message_new_duration_changed (GST_OBJECT_CAST (self))); + + /* FIXME: Sending EOS from application thread */ + if (eos) + gst_pad_push_event (self->srcpad, gst_event_new_eos ()); + } +} + +/* Returns FALSE if flushing + * Must be called from the pad's streaming thread + */ +static gboolean +gst_concat_pad_wait (GstConcatPad * spad, GstConcat * self) +{ + g_mutex_lock (&self->lock); + if (spad->flushing) { + g_mutex_unlock (&self->lock); + GST_DEBUG_OBJECT (spad, "Flushing"); + return FALSE; + } + + while (spad != GST_CONCAT_PAD_CAST (self->current_sinkpad)) { + GST_TRACE_OBJECT (spad, "Not the current sinkpad - waiting"); + if (self->current_sinkpad == NULL && g_list_length (self->sinkpads) == 1) { + GST_LOG_OBJECT (spad, "Sole pad waiting, switching"); + /* If we are the only sinkpad, take active pad ownership */ + self->current_sinkpad = gst_object_ref (self->sinkpads->data); + break; + } + g_cond_wait (&self->cond, &self->lock); + if (spad->flushing) { + g_mutex_unlock (&self->lock); + GST_DEBUG_OBJECT (spad, "Flushing"); + return FALSE; + } + } + /* This pad can only become not the current sinkpad from + * a) This streaming thread (we hold the stream lock) + * b) Releasing the pad (takes the stream lock, see above) + * + * Unlocking here is thus safe and we can safely push + * serialized data to our srcpad + */ + GST_DEBUG_OBJECT (spad, "Now the current sinkpad"); + g_mutex_unlock (&self->lock); + + return TRUE; +} + +static GstFlowReturn +gst_concat_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstFlowReturn ret; + GstConcat *self = GST_CONCAT (parent); + GstConcatPad *spad = GST_CONCAT_PAD (pad); + + GST_LOG_OBJECT (pad, "received buffer %p", buffer); + + if (!gst_concat_pad_wait (spad, self)) + return GST_FLOW_FLUSHING; + + if (self->last_stop == GST_CLOCK_TIME_NONE) + self->last_stop = spad->segment.start; + + if (self->format == GST_FORMAT_TIME) { + GstClockTime start_time = GST_BUFFER_TIMESTAMP (buffer); + GstClockTime end_time = GST_CLOCK_TIME_NONE; + + if (start_time != GST_CLOCK_TIME_NONE) + end_time = start_time; + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + end_time += GST_BUFFER_DURATION (buffer); + + if (end_time != GST_CLOCK_TIME_NONE && end_time > self->last_stop) + self->last_stop = end_time; + } else { + self->last_stop += gst_buffer_get_size (buffer); + } + + ret = gst_pad_push (self->srcpad, buffer); + + GST_LOG_OBJECT (pad, "handled buffer %s", gst_flow_get_name (ret)); + + return ret; +} + +/* Returns FALSE if no further pad, must be called with concat lock */ +static gboolean +gst_concat_switch_pad (GstConcat * self) +{ + GList *l; + gboolean next; + GstSegment segment; + gint64 last_stop; + + segment = GST_CONCAT_PAD (self->current_sinkpad)->segment; + + last_stop = self->last_stop; + if (last_stop == GST_CLOCK_TIME_NONE) + last_stop = segment.stop; + if (last_stop == GST_CLOCK_TIME_NONE) + last_stop = segment.start; + g_assert (last_stop != GST_CLOCK_TIME_NONE); + + if (last_stop > segment.stop) + last_stop = segment.stop; + + if (segment.format == GST_FORMAT_TIME) + last_stop = + gst_segment_to_running_time (&segment, segment.format, last_stop); + else + last_stop += segment.start; + + self->current_start_offset += last_stop; + + for (l = self->sinkpads; l; l = l->next) { + if ((gpointer) self->current_sinkpad == l->data) { + l = l->prev; + GST_DEBUG_OBJECT (self, + "Switching from pad %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, + self->current_sinkpad, l ? l->data : NULL); + gst_object_unref (self->current_sinkpad); + self->current_sinkpad = l ? gst_object_ref (l->data) : NULL; + g_cond_broadcast (&self->cond); + break; + } + } + + next = self->current_sinkpad != NULL; + + self->last_stop = GST_CLOCK_TIME_NONE; + + return next; +} + +static void +gst_concat_notify_active_pad (GstConcat * self) +{ + g_object_notify_by_pspec ((GObject *) self, pspec_active_pad); +} + +static gboolean +gst_concat_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstConcat *self = GST_CONCAT (parent); + GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad); + gboolean ret = TRUE; + + GST_LOG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START:{ + if (!gst_concat_pad_wait (spad, self)) { + ret = FALSE; + gst_event_unref (event); + } else { + ret = gst_pad_event_default (pad, parent, event); + } + break; + } + case GST_EVENT_SEGMENT:{ + gboolean adjust_base; + + /* Drop segment event, we create our own one */ + gst_event_copy_segment (event, &spad->segment); + gst_event_unref (event); + + g_mutex_lock (&self->lock); + adjust_base = self->adjust_base; + if (self->format == GST_FORMAT_UNDEFINED) { + if (spad->segment.format != GST_FORMAT_TIME + && spad->segment.format != GST_FORMAT_BYTES) { + g_mutex_unlock (&self->lock); + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("Can only operate in TIME or BYTES format")); + ret = FALSE; + break; + } + self->format = spad->segment.format; + GST_DEBUG_OBJECT (self, "Operating in %s format", + gst_format_get_name (self->format)); + g_mutex_unlock (&self->lock); + } else if (self->format != spad->segment.format) { + g_mutex_unlock (&self->lock); + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("Operating in %s format but new pad has %s", + gst_format_get_name (self->format), + gst_format_get_name (spad->segment.format))); + ret = FALSE; + } else { + g_mutex_unlock (&self->lock); + } + + if (!gst_concat_pad_wait (spad, self)) { + ret = FALSE; + } else { + GstSegment segment = spad->segment; + + if (adjust_base) { + /* We know no duration */ + segment.duration = -1; + + /* Update segment values to be continous with last stream */ + if (self->format == GST_FORMAT_TIME) { + segment.base += self->current_start_offset; + } else { + /* Shift start/stop byte position */ + segment.start += self->current_start_offset; + if (segment.stop != -1) + segment.stop += self->current_start_offset; + } + } + + gst_pad_push_event (self->srcpad, gst_event_new_segment (&segment)); + } + break; + } + case GST_EVENT_EOS:{ + gst_event_unref (event); + + if (!gst_concat_pad_wait (spad, self)) { + ret = FALSE; + } else { + gboolean next; + + g_mutex_lock (&self->lock); + next = gst_concat_switch_pad (self); + g_mutex_unlock (&self->lock); + ret = TRUE; + + gst_concat_notify_active_pad (self); + + if (!next) { + gst_pad_push_event (self->srcpad, gst_event_new_eos ()); + } else { + gst_element_post_message (GST_ELEMENT_CAST (self), + gst_message_new_duration_changed (GST_OBJECT_CAST (self))); + } + } + break; + } + case GST_EVENT_FLUSH_START:{ + gboolean forward; + + g_mutex_lock (&self->lock); + spad->flushing = TRUE; + g_cond_broadcast (&self->cond); + forward = (self->current_sinkpad == GST_PAD_CAST (spad)); + if (!forward && g_list_length (self->sinkpads) == 1) + forward = TRUE; + g_mutex_unlock (&self->lock); + + if (forward) + ret = gst_pad_event_default (pad, parent, event); + else + gst_event_unref (event); + break; + } + case GST_EVENT_FLUSH_STOP:{ + gboolean forward; + + gst_segment_init (&spad->segment, GST_FORMAT_UNDEFINED); + spad->flushing = FALSE; + + g_mutex_lock (&self->lock); + forward = (self->current_sinkpad == GST_PAD_CAST (spad)); + if (!forward && g_list_length (self->sinkpads) == 1) + forward = TRUE; + g_mutex_unlock (&self->lock); + + if (forward) { + gboolean reset_time; + + gst_event_parse_flush_stop (event, &reset_time); + if (reset_time) { + GST_DEBUG_OBJECT (self, + "resetting start offset to 0 after flushing with reset_time = TRUE"); + self->current_start_offset = 0; + } + ret = gst_pad_event_default (pad, parent, event); + } else { + gst_event_unref (event); + } + break; + } + default:{ + /* Wait for other serialized events before forwarding */ + if (GST_EVENT_IS_SERIALIZED (event) && !gst_concat_pad_wait (spad, self)) { + gst_event_unref (event); + ret = FALSE; + } else { + ret = gst_pad_event_default (pad, parent, event); + } + break; + } + } + + return ret; +} + +static gboolean +gst_concat_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstConcat *self = GST_CONCAT (parent); + GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad); + gboolean ret = TRUE; + + GST_LOG_OBJECT (pad, "received query %" GST_PTR_FORMAT, query); + + switch (GST_QUERY_TYPE (query)) { + default: + /* Wait for other serialized queries before forwarding */ + if (GST_QUERY_IS_SERIALIZED (query) && !gst_concat_pad_wait (spad, self)) { + ret = FALSE; + } else { + ret = gst_pad_query_default (pad, parent, query); + } + break; + } + + return ret; +} + +static gboolean +gst_concat_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstConcat *self = GST_CONCAT (parent); + gboolean ret = TRUE; + + GST_LOG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + GstPad *sinkpad = NULL; + + g_mutex_lock (&self->lock); + if ((sinkpad = self->current_sinkpad)) + gst_object_ref (sinkpad); + /* If no current active sinkpad but only one sinkpad, try reactivating that pad */ + if (sinkpad == NULL && g_list_length (self->sinkpads) == 1) { + sinkpad = gst_object_ref (self->sinkpads->data); + } + g_mutex_unlock (&self->lock); + if (sinkpad) { + ret = gst_pad_push_event (sinkpad, event); + gst_object_unref (sinkpad); + } else { + gst_event_unref (event); + ret = FALSE; + } + break; + } + case GST_EVENT_QOS:{ + GstQOSType type; + GstClockTimeDiff diff; + GstClockTime timestamp; + gdouble proportion; + GstPad *sinkpad = NULL; + + g_mutex_lock (&self->lock); + if ((sinkpad = self->current_sinkpad)) + gst_object_ref (sinkpad); + g_mutex_unlock (&self->lock); + + if (sinkpad) { + gst_event_parse_qos (event, &type, &proportion, &diff, ×tamp); + gst_event_unref (event); + + if (timestamp != GST_CLOCK_TIME_NONE + && timestamp > self->current_start_offset) { + timestamp -= self->current_start_offset; + event = gst_event_new_qos (type, proportion, diff, timestamp); + ret = gst_pad_push_event (self->current_sinkpad, event); + } else { + ret = FALSE; + } + gst_object_unref (sinkpad); + } else { + gst_event_unref (event); + ret = FALSE; + } + break; + } + case GST_EVENT_FLUSH_STOP:{ + gboolean reset_time; + + gst_event_parse_flush_stop (event, &reset_time); + if (reset_time) { + GST_DEBUG_OBJECT (self, + "resetting start offset to 0 after flushing with reset_time = TRUE"); + self->current_start_offset = 0; + } + + ret = gst_pad_event_default (pad, parent, event); + break; + } + default: + ret = gst_pad_event_default (pad, parent, event); + break; + } + + return ret; +} + +static gboolean +gst_concat_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean ret = TRUE; + + GST_LOG_OBJECT (pad, "received query %" GST_PTR_FORMAT, query); + + switch (GST_QUERY_TYPE (query)) { + default: + ret = gst_pad_query_default (pad, parent, query); + break; + } + + return ret; +} + +static void +reset_pad (const GValue * data, gpointer user_data) +{ + GstPad *pad = g_value_get_object (data); + GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad); + + gst_segment_init (&spad->segment, GST_FORMAT_UNDEFINED); + spad->flushing = FALSE; +} + +static void +unblock_pad (const GValue * data, gpointer user_data) +{ + GstPad *pad = g_value_get_object (data); + GstConcatPad *spad = GST_CONCAT_PAD_CAST (pad); + + spad->flushing = TRUE; +} + +static GstStateChangeReturn +gst_concat_change_state (GstElement * element, GstStateChange transition) +{ + GstConcat *self = GST_CONCAT (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED:{ + GstIterator *iter = gst_element_iterate_sink_pads (element); + GstIteratorResult res; + + self->format = GST_FORMAT_UNDEFINED; + self->current_start_offset = 0; + self->last_stop = GST_CLOCK_TIME_NONE; + + while ((res = + gst_iterator_foreach (iter, reset_pad, + NULL)) == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); + gst_iterator_free (iter); + + if (res == GST_ITERATOR_ERROR) + return GST_STATE_CHANGE_FAILURE; + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY:{ + GstIterator *iter = gst_element_iterate_sink_pads (element); + GstIteratorResult res; + + g_mutex_lock (&self->lock); + while ((res = + gst_iterator_foreach (iter, unblock_pad, + NULL)) == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); + gst_iterator_free (iter); + g_cond_broadcast (&self->cond); + g_mutex_unlock (&self->lock); + + if (res == GST_ITERATOR_ERROR) + return GST_STATE_CHANGE_FAILURE; + + break; + } + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + return ret; +} diff --git a/plugins/elements/gstconcat.h b/plugins/elements/gstconcat.h new file mode 100644 index 0000000..a74db55 --- /dev/null +++ b/plugins/elements/gstconcat.h @@ -0,0 +1,75 @@ +/* GStreamer concat element + * + * Copyright (c) 2014 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef __GST_CONCAT_H__ +#define __GST_CONCAT_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CONCAT (gst_concat_get_type()) +#define GST_CONCAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_CONCAT, GstConcat)) +#define GST_CONCAT_CAST(obj) ((GstConcat*)obj) +#define GST_CONCAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_CONCAT,GstConcatClass)) +#define GST_IS_CONCAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONCAT)) +#define GST_IS_CONCAT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONCAT)) + +typedef struct _GstConcat GstConcat; +typedef struct _GstConcatClass GstConcatClass; + +/** + * GstConcat: + * + * The private concat structure + */ +struct _GstConcat +{ + /*< private >*/ + GstElement parent; + + GMutex lock; + GCond cond; + GList *sinkpads; /* Last is earliest */ + GstPad *current_sinkpad; + GstPad *srcpad; + guint pad_count; + + /* Format we're operating in */ + GstFormat format; + /* In format, running time or accumulated byte offset */ + guint64 current_start_offset; + /* Between current pad's segment start and stop */ + guint64 last_stop; + + gboolean adjust_base; +}; + +struct _GstConcatClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_concat_get_type (void); + +G_END_DECLS + +#endif /* __GST_CONCAT_H__ */ diff --git a/plugins/elements/gstdataurisrc.c b/plugins/elements/gstdataurisrc.c new file mode 100644 index 0000000..e35d012 --- /dev/null +++ b/plugins/elements/gstdataurisrc.c @@ -0,0 +1,465 @@ +/* GStreamer data:// uri source element + * Copyright (C) 2009 Igalia S.L + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-dataurisrc + * @title: dataurisrc + * + * dataurisrc handles data: URIs, see [RFC 2397](http://tools.ietf.org/html/rfc2397) for more information. + * + * ## Example launch line + * + * |[ + * gst-launch-1.0 -v dataurisrc uri="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfElEQVQ4je2MwQnAIAxFgziA4EnczIsO4MEROo/gzZWc4xdTbe1R6LGRR74heYS7iKElzfcMiRnt4hf8gk8EayB6luefue/HzlJfCA50XsNjYRxprZmenXNIKSGEsC+QUqK1hhgj521BzhnWWiilUGvdF5RS4L2HMQZCCJy8sHMm2TYdJAAAAABJRU5ErkJggg==" ! pngdec ! videoconvert ! imagefreeze ! videoconvert ! autovideosink + * ]| + * + * This pipeline displays a small 16x16 PNG image from the data URI. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdataurisrc.h" + +#include +#include + +GST_DEBUG_CATEGORY (data_uri_src_debug); +#define GST_CAT_DEFAULT (data_uri_src_debug) + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_URI, +}; + +static void gst_data_uri_src_finalize (GObject * object); +static void gst_data_uri_src_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_data_uri_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstCaps *gst_data_uri_src_get_caps (GstBaseSrc * src, GstCaps * filter); +static gboolean gst_data_uri_src_get_size (GstBaseSrc * src, guint64 * size); +static gboolean gst_data_uri_src_is_seekable (GstBaseSrc * src); +static GstFlowReturn gst_data_uri_src_create (GstBaseSrc * src, guint64 offset, + guint size, GstBuffer ** buf); +static gboolean gst_data_uri_src_start (GstBaseSrc * src); + +static void gst_data_uri_src_handler_init (gpointer g_iface, + gpointer iface_data); +static GstURIType gst_data_uri_src_get_uri_type (GType type); +static const gchar *const *gst_data_uri_src_get_protocols (GType type); +static gchar *gst_data_uri_src_get_uri (GstURIHandler * handler); +static gboolean gst_data_uri_src_set_uri (GstURIHandler * handler, + const gchar * uri, GError ** error); + + +#define gst_data_uri_src_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstDataURISrc, gst_data_uri_src, GST_TYPE_BASE_SRC, + G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, + gst_data_uri_src_handler_init)); + +static void +gst_data_uri_src_class_init (GstDataURISrcClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *element_class = (GstElementClass *) klass; + GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass; + + gobject_class->finalize = gst_data_uri_src_finalize; + gobject_class->set_property = gst_data_uri_src_set_property; + gobject_class->get_property = gst_data_uri_src_get_property; + + g_object_class_install_property (gobject_class, PROP_URI, + g_param_spec_string ("uri", + "URI", + "URI that should be used", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_static_pad_template (element_class, &src_template); + gst_element_class_set_static_metadata (element_class, + "data: URI source element", "Source", "Handles data: uris", + "Philippe Normand , " + "Sebastian Dröge "); + + GST_DEBUG_CATEGORY_INIT (data_uri_src_debug, "dataurisrc", 0, + "data: URI source"); + + basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_data_uri_src_get_caps); + basesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_data_uri_src_get_size); + basesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_data_uri_src_is_seekable); + basesrc_class->create = GST_DEBUG_FUNCPTR (gst_data_uri_src_create); + basesrc_class->start = GST_DEBUG_FUNCPTR (gst_data_uri_src_start); +} + +static void +gst_data_uri_src_init (GstDataURISrc * src) +{ +} + +static void +gst_data_uri_src_finalize (GObject * object) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (object); + + g_free (src->uri); + src->uri = NULL; + + if (src->buffer) + gst_buffer_unref (src->buffer); + src->buffer = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_data_uri_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (object); + + switch (prop_id) { + case PROP_URI: + gst_data_uri_src_set_uri (GST_URI_HANDLER (src), + g_value_get_string (value), NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_data_uri_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (object); + + switch (prop_id) { + case PROP_URI: + g_value_take_string (value, + gst_data_uri_src_get_uri (GST_URI_HANDLER (src))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstCaps * +gst_data_uri_src_get_caps (GstBaseSrc * basesrc, GstCaps * filter) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (basesrc); + GstCaps *caps; + + GST_OBJECT_LOCK (src); + caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (basesrc)); + if (!caps) + caps = gst_caps_new_any (); + GST_OBJECT_UNLOCK (src); + + return caps; +} + +static gboolean +gst_data_uri_src_get_size (GstBaseSrc * basesrc, guint64 * size) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (basesrc); + gboolean ret; + + GST_OBJECT_LOCK (src); + if (!src->buffer) { + ret = FALSE; + *size = -1; + } else { + ret = TRUE; + *size = gst_buffer_get_size (src->buffer); + } + GST_OBJECT_UNLOCK (src); + + return ret; +} + +static gboolean +gst_data_uri_src_is_seekable (GstBaseSrc * basesrc) +{ + return TRUE; +} + +static GstFlowReturn +gst_data_uri_src_create (GstBaseSrc * basesrc, guint64 offset, guint size, + GstBuffer ** buf) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (basesrc); + GstFlowReturn ret; + + GST_OBJECT_LOCK (src); + + if (!src->buffer) + goto no_buffer; + + /* This is only correct because GstBaseSrc already clips size for us to be no + * larger than the max. available size if a segment at the end is requested */ + if (offset + size > gst_buffer_get_size (src->buffer)) { + ret = GST_FLOW_EOS; + } else if (*buf != NULL) { + GstMapInfo src_info; + GstMapInfo dest_info; + gsize fill_size; + + gst_buffer_map (src->buffer, &src_info, GST_MAP_READ); + gst_buffer_map (*buf, &dest_info, GST_MAP_WRITE); + + fill_size = gst_buffer_fill (*buf, 0, src_info.data + offset, size); + + gst_buffer_unmap (*buf, &dest_info); + gst_buffer_unmap (src->buffer, &src_info); + gst_buffer_set_size (*buf, fill_size); + ret = GST_FLOW_OK; + } else { + *buf = + gst_buffer_copy_region (src->buffer, GST_BUFFER_COPY_ALL, offset, size); + ret = GST_FLOW_OK; + } + GST_OBJECT_UNLOCK (src); + + return ret; + +/* ERRORS */ +no_buffer: + { + GST_OBJECT_UNLOCK (src); + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), (NULL)); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static gboolean +gst_data_uri_src_start (GstBaseSrc * basesrc) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (basesrc); + + GST_OBJECT_LOCK (src); + + if (src->uri == NULL || *src->uri == '\0' || src->buffer == NULL) + goto no_uri; + + GST_OBJECT_UNLOCK (src); + + return TRUE; + +/* ERRORS */ +no_uri: + { + GST_OBJECT_UNLOCK (src); + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + ("No valid data URI specified, or the data URI could not be parsed."), + ("%s", src->uri)); + return FALSE; + } +} + +static GstURIType +gst_data_uri_src_get_uri_type (GType type) +{ + return GST_URI_SRC; +} + +static const gchar *const * +gst_data_uri_src_get_protocols (GType type) +{ + static const gchar *protocols[] = { "data", 0 }; + + return protocols; +} + +static gchar * +gst_data_uri_src_get_uri (GstURIHandler * handler) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (handler); + gchar *src_uri = NULL; + + GST_OBJECT_LOCK (src); + src_uri = g_strdup (src->uri); + GST_OBJECT_UNLOCK (src); + return src_uri; +} + +static gboolean +gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) +{ + GstDataURISrc *src = GST_DATA_URI_SRC (handler); + gboolean ret = FALSE; + gchar *mimetype = NULL; + const gchar *parameters_start; + const gchar *data_start; + const gchar *orig_uri = uri; + GstCaps *caps; + GstBuffer *buffer; + gboolean base64 = FALSE; + gchar *charset = NULL; + gpointer bdata; + gsize bsize; + + GST_OBJECT_LOCK (src); + if (GST_STATE (src) >= GST_STATE_PAUSED) + goto wrong_state; + GST_OBJECT_UNLOCK (src); + + /* uri must be an URI as defined in RFC 2397 + * data:[][;base64], + */ + if (strncmp ("data:", uri, 5) != 0) + goto invalid_uri; + + uri += 5; + + parameters_start = strchr (uri, ';'); + data_start = strchr (uri, ','); + if (data_start == NULL) + goto invalid_uri; + + if (data_start != uri && parameters_start != uri) + mimetype = + g_strndup (uri, + (parameters_start ? parameters_start : data_start) - uri); + else + mimetype = g_strdup ("text/plain"); + + GST_DEBUG_OBJECT (src, "Mimetype: %s", mimetype); + + if (parameters_start != NULL) { + gchar **walk; + gchar *parameters = + g_strndup (parameters_start + 1, data_start - parameters_start - 1); + gchar **parameters_strv; + + parameters_strv = g_strsplit (parameters, ";", -1); + + GST_DEBUG_OBJECT (src, "Parameters: "); + walk = parameters_strv; + while (*walk) { + GST_DEBUG_OBJECT (src, "\t %s", *walk); + if (strcmp ("base64", *walk) == 0) { + base64 = TRUE; + } else if (strncmp ("charset=", *walk, 8) == 0) { + charset = g_strdup (*walk + 8); + } + walk++; + } + g_free (parameters); + g_strfreev (parameters_strv); + } + + /* Skip comma */ + data_start += 1; + if (base64) { + bdata = g_base64_decode (data_start, &bsize); + } else { + /* URI encoded, i.e. "percent" encoding */ + bdata = g_uri_unescape_string (data_start, NULL); + if (bdata == NULL) + goto invalid_uri_encoded_data; + bsize = strlen (bdata) + 1; + } + /* Convert to UTF8 */ + if (strcmp ("text/plain", mimetype) == 0 && + charset && g_ascii_strcasecmp ("US-ASCII", charset) != 0 + && g_ascii_strcasecmp ("UTF-8", charset) != 0) { + gsize read; + gsize written; + gpointer data; + + data = + g_convert_with_fallback (bdata, -1, "UTF-8", charset, (char *) "*", + &read, &written, NULL); + g_free (bdata); + + bdata = data; + bsize = written; + } + buffer = gst_buffer_new_wrapped (bdata, bsize); + + caps = gst_type_find_helper_for_buffer (GST_OBJECT (src), buffer, NULL); + if (!caps) + caps = gst_caps_new_empty_simple (mimetype); + gst_base_src_set_caps (GST_BASE_SRC_CAST (src), caps); + gst_caps_unref (caps); + + GST_OBJECT_LOCK (src); + gst_buffer_replace (&src->buffer, buffer); + gst_buffer_unref (buffer); + g_free (src->uri); + src->uri = g_strdup (orig_uri); + GST_OBJECT_UNLOCK (src); + + ret = TRUE; + +out: + + g_free (mimetype); + g_free (charset); + + return ret; + +wrong_state: + { + GST_WARNING_OBJECT (src, "Can't set URI in %s state", + gst_element_state_get_name (GST_STATE (src))); + GST_OBJECT_UNLOCK (src); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE, + "Changing the 'uri' property on dataurisrc while it is running " + "is not supported"); + goto out; + } +invalid_uri: + { + GST_WARNING_OBJECT (src, "invalid URI '%s'", uri); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "Invalid data URI"); + goto out; + } +invalid_uri_encoded_data: + { + GST_WARNING_OBJECT (src, "Failed to parse data encoded in URI '%s'", uri); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "Could not parse data encoded in data URI"); + goto out; + } +} + +static void +gst_data_uri_src_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_data_uri_src_get_uri_type; + iface->get_protocols = gst_data_uri_src_get_protocols; + iface->get_uri = gst_data_uri_src_get_uri; + iface->set_uri = gst_data_uri_src_set_uri; +} diff --git a/plugins/elements/gstdataurisrc.h b/plugins/elements/gstdataurisrc.h new file mode 100644 index 0000000..c2cfd90 --- /dev/null +++ b/plugins/elements/gstdataurisrc.h @@ -0,0 +1,61 @@ +/* GStreamer + * + * Copyright (C) 2009 Igalia S.L + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_DATA_URI_SRC__ +#define __GST_DATA_URI_SRC__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DATA_URI_SRC \ + (gst_data_uri_src_get_type()) +#define GST_DATA_URI_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DATA_URI_SRC,GstDataURISrc)) +#define GST_DATA_URI_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DATA_URI_SRC,GstDataURISrcClass)) +#define GST_IS_DATA_URI_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DATA_URI_SRC)) +#define GST_IS_DATA_URI_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DATA_URI_SRC)) +typedef struct _GstDataURISrc GstDataURISrc; +typedef struct _GstDataURISrcClass GstDataURISrcClass; + +struct _GstDataURISrc +{ + GstBaseSrc parent; + + /* */ + gchar *uri; + GstBuffer *buffer; +}; + +struct _GstDataURISrcClass +{ + GstBaseSrcClass parent_class; +}; + +GType gst_data_uri_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_DATA_URI_SRC__ */ diff --git a/plugins/elements/gstdownloadbuffer.c b/plugins/elements/gstdownloadbuffer.c new file mode 100644 index 0000000..6f67e78 --- /dev/null +++ b/plugins/elements/gstdownloadbuffer.c @@ -0,0 +1,1962 @@ +/* GStreamer + * Copyright (C) 2014 Wim Taymans + * + * gstdownloadbuffer.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-downloadbuffer + * @title: downloadbuffer + * + * The downloadbuffer element provides on-disk buffering and caching of, typically, + * a network file. temp-template should be set to a value such as + * /tmp/gstreamer-XXXXXX and the element will allocate a random free filename and + * buffer the data in the file. + * + * With max-size-bytes and max-size-time you can configure the buffering limits. + * The downloadbuffer element will try to read-ahead these amounts of data. When + * the amount of read-ahead data drops below low-percent of the configured max, + * the element will start emitting BUFFERING messages until high-percent of max is + * reached again. + * + * The downloadbuffer provides push and pull based scheduling on its source pad + * and will efficiently seek in the upstream element when needed. + * + * The temp-location property will be used to notify the application of the + * allocated filename. + * + * When the downloadbuffer has completely downloaded the media, it will + * post an application message named "GstCacheDownloadComplete" + * with the following information: + * + * * + * G_TYPE_STRING + * "location": + * the location of the completely downloaded file. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdownloadbuffer.h" + +#include + +#include "gst/gst-i18n-lib.h" +#include "gst/glib-compat-private.h" + +#include + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#else +#include +#endif + +#ifdef __BIONIC__ +#include +#endif + +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); + +GST_DEBUG_CATEGORY_STATIC (downloadbuffer_debug); +#define GST_CAT_DEFAULT (downloadbuffer_debug) + +enum +{ + LAST_SIGNAL +}; + +/* other defines */ +#define DEFAULT_BUFFER_SIZE 4096 + +/* default property values */ +#define DEFAULT_MAX_SIZE_BYTES (2 * 1024 * 1024) /* 2 MB */ +#define DEFAULT_MAX_SIZE_TIME 2 * GST_SECOND /* 2 seconds */ +#define DEFAULT_LOW_PERCENT 10 +#define DEFAULT_HIGH_PERCENT 99 +#define DEFAULT_TEMP_REMOVE TRUE + +enum +{ + PROP_0, + PROP_MAX_SIZE_BYTES, + PROP_MAX_SIZE_TIME, + PROP_LOW_PERCENT, + PROP_HIGH_PERCENT, + PROP_TEMP_TEMPLATE, + PROP_TEMP_LOCATION, + PROP_TEMP_REMOVE, + PROP_LAST +}; + +#define GST_DOWNLOAD_BUFFER_CLEAR_LEVEL(l) G_STMT_START { \ + l.bytes = 0; \ + l.time = 0; \ +} G_STMT_END + +#define STATUS(elem, pad, msg) \ + GST_LOG_OBJECT (elem, "(%s:%s) " msg ": %u of %u " \ + "bytes, %" G_GUINT64_FORMAT " of %" G_GUINT64_FORMAT \ + " ns", \ + GST_DEBUG_PAD_NAME (pad), \ + elem->cur_level.bytes, \ + elem->max_level.bytes, \ + elem->cur_level.time, \ + elem->max_level.time) + +#define GST_DOWNLOAD_BUFFER_MUTEX_LOCK(q) G_STMT_START { \ + g_mutex_lock (&q->qlock); \ +} G_STMT_END + +#define GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK(q,res,label) G_STMT_START { \ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (q); \ + if (res != GST_FLOW_OK) \ + goto label; \ +} G_STMT_END + +#define GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK(q) G_STMT_START { \ + g_mutex_unlock (&q->qlock); \ +} G_STMT_END + +#define GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK(q, res, o, label) G_STMT_START { \ + STATUS (q, q->srcpad, "wait for ADD"); \ + q->waiting_add = TRUE; \ + q->waiting_offset = o; \ + g_cond_wait (&q->item_add, &q->qlock); \ + q->waiting_add = FALSE; \ + if (res != GST_FLOW_OK) { \ + STATUS (q, q->srcpad, "received ADD wakeup"); \ + goto label; \ + } \ + STATUS (q, q->srcpad, "received ADD"); \ +} G_STMT_END + +#define GST_DOWNLOAD_BUFFER_SIGNAL_ADD(q, o) G_STMT_START { \ + if (q->waiting_add && q->waiting_offset <= o) { \ + STATUS (q, q->sinkpad, "signal ADD"); \ + g_cond_signal (&q->item_add); \ + } \ +} G_STMT_END + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (downloadbuffer_debug, "downloadbuffer", 0, \ + "downloadbuffer element"); + +#define gst_download_buffer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstDownloadBuffer, gst_download_buffer, + GST_TYPE_ELEMENT, _do_init); + +static GstMessage *update_buffering (GstDownloadBuffer * dlbuf); + +static void gst_download_buffer_finalize (GObject * object); + +static void gst_download_buffer_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_download_buffer_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_download_buffer_chain (GstPad * pad, + GstObject * parent, GstBuffer * buffer); +static void gst_download_buffer_loop (GstPad * pad); + +static gboolean gst_download_buffer_handle_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_download_buffer_handle_sink_query (GstPad * pad, + GstObject * parent, GstQuery * query); + +static gboolean gst_download_buffer_handle_src_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_download_buffer_handle_src_query (GstPad * pad, + GstObject * parent, GstQuery * query); +static gboolean gst_download_buffer_handle_query (GstElement * element, + GstQuery * query); + +static GstFlowReturn gst_download_buffer_get_range (GstPad * pad, + GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer); + +static gboolean gst_download_buffer_src_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_download_buffer_sink_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static GstStateChangeReturn gst_download_buffer_change_state (GstElement * + element, GstStateChange transition); + +/* static guint gst_download_buffer_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_download_buffer_class_init (GstDownloadBufferClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_download_buffer_set_property; + gobject_class->get_property = gst_download_buffer_get_property; + + /* properties */ + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES, + g_param_spec_uint ("max-size-bytes", "Max. size (kB)", + "Max. amount of data to buffer (bytes, 0=disable)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME, + g_param_spec_uint64 ("max-size-time", "Max. size (ns)", + "Max. amount of data to buffer (in ns, 0=disable)", 0, G_MAXUINT64, + DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LOW_PERCENT, + g_param_spec_int ("low-percent", "Low percent", + "Low threshold for buffering to start. Only used if use-buffering is True", + 0, 100, DEFAULT_LOW_PERCENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT, + g_param_spec_int ("high-percent", "High percent", + "High threshold for buffering to finish. Only used if use-buffering is True", + 0, 100, DEFAULT_HIGH_PERCENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE, + g_param_spec_string ("temp-template", "Temporary File Template", + "File template to store temporary files in, should contain directory " + "and XXXXXX. (NULL == disabled)", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION, + g_param_spec_string ("temp-location", "Temporary File Location", + "Location to store temporary files in (Only read this property, " + "use temp-template to configure the name template)", + NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDownloadBuffer:temp-remove + * + * When temp-template is set, remove the temporary file when going to READY. + */ + g_object_class_install_property (gobject_class, PROP_TEMP_REMOVE, + g_param_spec_boolean ("temp-remove", "Remove the Temporary File", + "Remove the temp-location after use", + DEFAULT_TEMP_REMOVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* set several parent class virtual functions */ + gobject_class->finalize = gst_download_buffer_finalize; + + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gst_element_class_set_static_metadata (gstelement_class, "DownloadBuffer", + "Generic", "Download Buffer element", + "Wim Taymans "); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_download_buffer_change_state); + gstelement_class->query = + GST_DEBUG_FUNCPTR (gst_download_buffer_handle_query); +} + +static void +gst_download_buffer_init (GstDownloadBuffer * dlbuf) +{ + dlbuf->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); + + gst_pad_set_chain_function (dlbuf->sinkpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_chain)); + gst_pad_set_activatemode_function (dlbuf->sinkpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_sink_activate_mode)); + gst_pad_set_event_function (dlbuf->sinkpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_handle_sink_event)); + gst_pad_set_query_function (dlbuf->sinkpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_handle_sink_query)); + GST_PAD_SET_PROXY_CAPS (dlbuf->sinkpad); + gst_element_add_pad (GST_ELEMENT (dlbuf), dlbuf->sinkpad); + + dlbuf->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + + gst_pad_set_activatemode_function (dlbuf->srcpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_src_activate_mode)); + gst_pad_set_getrange_function (dlbuf->srcpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_get_range)); + gst_pad_set_event_function (dlbuf->srcpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_handle_src_event)); + gst_pad_set_query_function (dlbuf->srcpad, + GST_DEBUG_FUNCPTR (gst_download_buffer_handle_src_query)); + GST_PAD_SET_PROXY_CAPS (dlbuf->srcpad); + gst_element_add_pad (GST_ELEMENT (dlbuf), dlbuf->srcpad); + + /* levels */ + GST_DOWNLOAD_BUFFER_CLEAR_LEVEL (dlbuf->cur_level); + dlbuf->max_level.bytes = DEFAULT_MAX_SIZE_BYTES; + dlbuf->max_level.time = DEFAULT_MAX_SIZE_TIME; + dlbuf->low_percent = DEFAULT_LOW_PERCENT; + dlbuf->high_percent = DEFAULT_HIGH_PERCENT; + + dlbuf->srcresult = GST_FLOW_FLUSHING; + dlbuf->sinkresult = GST_FLOW_FLUSHING; + dlbuf->in_timer = g_timer_new (); + dlbuf->out_timer = g_timer_new (); + + g_mutex_init (&dlbuf->qlock); + dlbuf->waiting_add = FALSE; + g_cond_init (&dlbuf->item_add); + + /* tempfile related */ + dlbuf->temp_template = NULL; + dlbuf->temp_location = NULL; + dlbuf->temp_remove = DEFAULT_TEMP_REMOVE; +} + +/* called only once, as opposed to dispose */ +static void +gst_download_buffer_finalize (GObject * object) +{ + GstDownloadBuffer *dlbuf = GST_DOWNLOAD_BUFFER (object); + + g_mutex_clear (&dlbuf->qlock); + g_cond_clear (&dlbuf->item_add); + g_timer_destroy (dlbuf->in_timer); + g_timer_destroy (dlbuf->out_timer); + + /* temp_file path cleanup */ + g_free (dlbuf->temp_template); + g_free (dlbuf->temp_location); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +reset_positions (GstDownloadBuffer * dlbuf) +{ + dlbuf->write_pos = 0; + dlbuf->read_pos = 0; + dlbuf->filling = TRUE; + dlbuf->buffering_percent = 0; + dlbuf->is_buffering = TRUE; + dlbuf->seeking = FALSE; + GST_DOWNLOAD_BUFFER_CLEAR_LEVEL (dlbuf->cur_level); +} + +static void +reset_rate_timer (GstDownloadBuffer * dlbuf) +{ + dlbuf->bytes_in = 0; + dlbuf->bytes_out = 0; + dlbuf->byte_in_rate = 0.0; + dlbuf->byte_in_period = 0; + dlbuf->byte_out_rate = 0.0; + dlbuf->last_in_elapsed = 0.0; + dlbuf->last_out_elapsed = 0.0; + dlbuf->in_timer_started = FALSE; + dlbuf->out_timer_started = FALSE; +} + +/* the interval in seconds to recalculate the rate */ +#define RATE_INTERVAL 0.2 +/* Tuning for rate estimation. We use a large window for the input rate because + * it should be stable when connected to a network. The output rate is less + * stable (the elements preroll, queues behind a demuxer fill, ...) and should + * therefore adapt more quickly. + * However, initial input rate may be subject to a burst, and should therefore + * initially also adapt more quickly to changes, and only later on give higher + * weight to previous values. */ +#define AVG_IN(avg,val,w1,w2) ((avg) * (w1) + (val) * (w2)) / ((w1) + (w2)) +#define AVG_OUT(avg,val) ((avg) * 3.0 + (val)) / 4.0 + +static void +update_levels (GstDownloadBuffer * dlbuf, guint bytes) +{ + dlbuf->cur_level.bytes = bytes; + + if (dlbuf->byte_in_rate > 0.0) { + dlbuf->cur_level.time = + dlbuf->cur_level.bytes / dlbuf->byte_in_rate * GST_SECOND; + } + + GST_DEBUG ("levels: bytes %u/%u, time %" GST_TIME_FORMAT "/%" GST_TIME_FORMAT, + dlbuf->cur_level.bytes, dlbuf->max_level.bytes, + GST_TIME_ARGS (dlbuf->cur_level.time), + GST_TIME_ARGS (dlbuf->max_level.time)); +} + +static void +update_in_rates (GstDownloadBuffer * dlbuf) +{ + gdouble elapsed, period; + gdouble byte_in_rate; + + if (!dlbuf->in_timer_started) { + dlbuf->in_timer_started = TRUE; + g_timer_start (dlbuf->in_timer); + return; + } + + elapsed = g_timer_elapsed (dlbuf->in_timer, NULL); + + /* recalc after each interval. */ + if (dlbuf->last_in_elapsed + RATE_INTERVAL < elapsed) { + period = elapsed - dlbuf->last_in_elapsed; + + GST_DEBUG_OBJECT (dlbuf, + "rates: period %f, in %" G_GUINT64_FORMAT ", global period %f", + period, dlbuf->bytes_in, dlbuf->byte_in_period); + + byte_in_rate = dlbuf->bytes_in / period; + + if (dlbuf->byte_in_rate == 0.0) + dlbuf->byte_in_rate = byte_in_rate; + else + dlbuf->byte_in_rate = AVG_IN (dlbuf->byte_in_rate, byte_in_rate, + (double) dlbuf->byte_in_period, period); + + /* another data point, cap at 16 for long time running average */ + if (dlbuf->byte_in_period < 16 * RATE_INTERVAL) + dlbuf->byte_in_period += period; + + /* reset the values to calculate rate over the next interval */ + dlbuf->last_in_elapsed = elapsed; + dlbuf->bytes_in = 0; + GST_DEBUG_OBJECT (dlbuf, "rates: in %f", dlbuf->byte_in_rate); + } +} + +static void +update_out_rates (GstDownloadBuffer * dlbuf) +{ + gdouble elapsed, period; + gdouble byte_out_rate; + + if (!dlbuf->out_timer_started) { + dlbuf->out_timer_started = TRUE; + g_timer_start (dlbuf->out_timer); + return; + } + + elapsed = g_timer_elapsed (dlbuf->out_timer, NULL); + + /* recalc after each interval. */ + if (dlbuf->last_out_elapsed + RATE_INTERVAL < elapsed) { + period = elapsed - dlbuf->last_out_elapsed; + + GST_DEBUG_OBJECT (dlbuf, + "rates: period %f, out %" G_GUINT64_FORMAT, period, dlbuf->bytes_out); + + byte_out_rate = dlbuf->bytes_out / period; + + if (dlbuf->byte_out_rate == 0.0) + dlbuf->byte_out_rate = byte_out_rate; + else + dlbuf->byte_out_rate = AVG_OUT (dlbuf->byte_out_rate, byte_out_rate); + + /* reset the values to calculate rate over the next interval */ + dlbuf->last_out_elapsed = elapsed; + dlbuf->bytes_out = 0; + GST_DEBUG_OBJECT (dlbuf, "rates: out %f", dlbuf->byte_out_rate); + } +} + +static gboolean +get_buffering_percent (GstDownloadBuffer * dlbuf, gboolean * is_buffering, + gint * percent) +{ + gint perc; + + if (dlbuf->high_percent <= 0) { + if (percent) + *percent = 100; + if (is_buffering) + *is_buffering = FALSE; + return FALSE; + } + + /* Ensure the variables used to calculate buffering state are up-to-date. */ + update_in_rates (dlbuf); + update_out_rates (dlbuf); + + /* figure out the percent we are filled, we take the max of all formats. */ + if (dlbuf->max_level.bytes > 0) { + if (dlbuf->cur_level.bytes >= dlbuf->max_level.bytes) + perc = 100; + else + perc = dlbuf->cur_level.bytes * 100 / dlbuf->max_level.bytes; + } else + perc = 0; + + if (dlbuf->max_level.time > 0) { + if (dlbuf->cur_level.time >= dlbuf->max_level.time) + perc = 100; + else + perc = MAX (perc, dlbuf->cur_level.time * 100 / dlbuf->max_level.time); + } else + perc = MAX (0, perc); + + if (is_buffering) + *is_buffering = dlbuf->is_buffering; + + /* scale to high percent so that it becomes the 100% mark */ + perc = perc * 100 / dlbuf->high_percent; + /* clip */ + if (perc > 100) + perc = 100; + + if (percent) + *percent = perc; + + GST_DEBUG_OBJECT (dlbuf, "buffering %d, percent %d", dlbuf->is_buffering, + perc); + + return TRUE; +} + +static void +get_buffering_stats (GstDownloadBuffer * dlbuf, gint percent, + GstBufferingMode * mode, gint * avg_in, gint * avg_out, + gint64 * buffering_left) +{ + if (mode) + *mode = GST_BUFFERING_DOWNLOAD; + + if (avg_in) + *avg_in = dlbuf->byte_in_rate; + if (avg_out) + *avg_out = dlbuf->byte_out_rate; + + if (buffering_left) { + guint64 max, cur; + + *buffering_left = (percent == 100 ? 0 : -1); + + max = dlbuf->max_level.time; + cur = dlbuf->cur_level.time; + + if (percent != 100 && max > cur) + *buffering_left = (max - cur) / 1000000; + } +} + +static GstMessage * +update_buffering (GstDownloadBuffer * dlbuf) +{ + gint percent; + gboolean post = FALSE; + GstMessage *message = NULL; + + if (!get_buffering_percent (dlbuf, NULL, &percent)) + return NULL; + + if (dlbuf->is_buffering) { + post = TRUE; + /* if we were buffering see if we reached the high watermark */ + if (percent >= dlbuf->high_percent) + dlbuf->is_buffering = FALSE; + } else { + /* we were not buffering, check if we need to start buffering if we drop + * below the low threshold */ + if (percent < dlbuf->low_percent) { + dlbuf->is_buffering = TRUE; + post = TRUE; + } + } + + if (post) { + if (percent == dlbuf->buffering_percent) + post = FALSE; + else + dlbuf->buffering_percent = percent; + } + + if (post) { + GstBufferingMode mode; + gint avg_in, avg_out; + gint64 buffering_left; + + get_buffering_stats (dlbuf, percent, &mode, &avg_in, &avg_out, + &buffering_left); + + message = gst_message_new_buffering (GST_OBJECT_CAST (dlbuf), + (gint) percent); + gst_message_set_buffering_stats (message, mode, + avg_in, avg_out, buffering_left); + } + + return message; +} + +static gboolean +perform_seek_to_offset (GstDownloadBuffer * dlbuf, guint64 offset) +{ + GstEvent *event; + gboolean res; + + if (dlbuf->seeking) + return TRUE; + + /* until we receive the FLUSH_STOP from this seek, we skip data */ + dlbuf->seeking = TRUE; + dlbuf->write_pos = offset; + dlbuf->filling = FALSE; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + GST_DEBUG_OBJECT (dlbuf, "Seeking to %" G_GUINT64_FORMAT, offset); + + event = + gst_event_new_seek (1.0, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset, + GST_SEEK_TYPE_NONE, -1); + + res = gst_pad_push_event (dlbuf->sinkpad, event); + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + + return res; +} + +/* get the threshold for when we decide to seek rather than wait */ +static guint64 +get_seek_threshold (GstDownloadBuffer * dlbuf) +{ + guint64 threshold; + + /* FIXME, find a good threshold based on the incoming rate. */ + threshold = 1024 * 512; + + return threshold; +} + +/* called with DOWNLOAD_BUFFER_MUTEX */ +static void +gst_download_buffer_update_upstream_size (GstDownloadBuffer * dlbuf) +{ + gint64 upstream_size = 0; + + if (gst_pad_peer_query_duration (dlbuf->sinkpad, GST_FORMAT_BYTES, + &upstream_size)) { + GST_INFO_OBJECT (dlbuf, "upstream size: %" G_GINT64_FORMAT, upstream_size); + dlbuf->upstream_size = upstream_size; + } +} + +/* called with DOWNLOAD_BUFFER_MUTEX */ +static GstFlowReturn +gst_download_buffer_wait_for_data (GstDownloadBuffer * dlbuf, guint64 offset, + guint length) +{ + gsize start, stop; + guint64 wanted; + gboolean started; + + GST_DEBUG_OBJECT (dlbuf, "wait for %" G_GUINT64_FORMAT ", length %u", + offset, length); + + wanted = offset + length; + + /* pause the timer while we wait. The fact that we are waiting does not mean + * the byterate on the output pad is lower */ + if ((started = dlbuf->out_timer_started)) + g_timer_stop (dlbuf->out_timer); + + /* check range before us */ + if (gst_sparse_file_get_range_before (dlbuf->file, offset, &start, &stop)) { + GST_DEBUG_OBJECT (dlbuf, + "range before %" G_GSIZE_FORMAT " - %" G_GSIZE_FORMAT, start, stop); + if (start <= offset && offset < stop) { + GST_DEBUG_OBJECT (dlbuf, "we have the offset"); + /* we have the range, continue it */ + offset = stop; + } else { + guint64 threshold, dist; + + /* there is a range before us, check how far away it is */ + threshold = get_seek_threshold (dlbuf); + dist = offset - stop; + + if (dist <= threshold) { + GST_DEBUG_OBJECT (dlbuf, "not too far"); + /* not far away, continue it */ + offset = stop; + } + } + } + + if (dlbuf->write_pos != offset) + perform_seek_to_offset (dlbuf, offset); + + dlbuf->filling = TRUE; + if (dlbuf->write_pos > dlbuf->read_pos) + update_levels (dlbuf, dlbuf->write_pos - dlbuf->read_pos); + else + update_levels (dlbuf, 0); + + /* now wait for more data */ + GST_DEBUG_OBJECT (dlbuf, "waiting for more data"); + GST_DOWNLOAD_BUFFER_WAIT_ADD_CHECK (dlbuf, dlbuf->srcresult, wanted, + out_flushing); + GST_DEBUG_OBJECT (dlbuf, "got more data"); + + /* and continue if we were running before */ + if (started) + g_timer_continue (dlbuf->out_timer); + + return GST_FLOW_OK; + +out_flushing: + { + GST_DEBUG_OBJECT (dlbuf, "we are flushing"); + return GST_FLOW_FLUSHING; + } +} + +/* called with DOWNLOAD_BUFFER_MUTEX */ +static gboolean +check_upstream_size (GstDownloadBuffer * dlbuf, gsize offset, guint * length) +{ + gsize stop = offset + *length; + /* catch any reads beyond the size of the file here to make sure cache + * doesn't send seek events beyond the size of the file upstream, since + * that would confuse elements such as souphttpsrc and/or http servers. + * Demuxers often just loop until EOS at the end of the file to figure out + * when they've read all the end-headers or index chunks. */ + if (G_UNLIKELY (dlbuf->upstream_size == -1 || stop >= dlbuf->upstream_size)) { + gst_download_buffer_update_upstream_size (dlbuf); + } + + if (dlbuf->upstream_size != -1) { + if (offset >= dlbuf->upstream_size) + return FALSE; + + if (G_UNLIKELY (stop > dlbuf->upstream_size)) { + *length = dlbuf->upstream_size - offset; + GST_DEBUG_OBJECT (dlbuf, "adjusting length downto %u", *length); + } + } + return TRUE; +} + +/* called with DOWNLOAD_BUFFER_MUTEX */ +static GstFlowReturn +gst_download_buffer_read_buffer (GstDownloadBuffer * dlbuf, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstBuffer *buf; + GstMapInfo info; + GstFlowReturn ret = GST_FLOW_OK; + gsize res, remaining; + GError *error = NULL; + + length = (length == -1) ? DEFAULT_BUFFER_SIZE : length; + offset = (offset == -1) ? dlbuf->read_pos : offset; + + if (!check_upstream_size (dlbuf, offset, &length)) + goto hit_eos; + + /* allocate the output buffer of the requested size */ + if (*buffer == NULL) + buf = gst_buffer_new_allocate (NULL, length, NULL); + else + buf = *buffer; + + if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) + goto map_failed; + + GST_DEBUG_OBJECT (dlbuf, "Reading %u bytes from %" G_GUINT64_FORMAT, length, + offset); + + dlbuf->read_pos = offset; + + do { + res = + gst_sparse_file_read (dlbuf->file, offset, info.data, length, + &remaining, &error); + if (G_UNLIKELY (res == 0)) { + switch (error->code) { + case GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK: + /* we don't have the requested data in the file, decide what to + * do next. */ + ret = gst_download_buffer_wait_for_data (dlbuf, offset, length); + if (ret != GST_FLOW_OK) + goto out_flushing; + break; + default: + goto read_error; + } + g_clear_error (&error); + } + } while (res == 0); + + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, res); + + dlbuf->bytes_out += res; + dlbuf->read_pos += res; + + GST_DEBUG_OBJECT (dlbuf, + "Read %" G_GSIZE_FORMAT " bytes, remaining %" G_GSIZE_FORMAT, res, + remaining); + + if (dlbuf->read_pos + remaining == dlbuf->upstream_size) + update_levels (dlbuf, dlbuf->max_level.bytes); + else + update_levels (dlbuf, remaining); + + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + res; + + *buffer = buf; + + return ret; + + /* ERRORS */ +hit_eos: + { + GST_DEBUG_OBJECT (dlbuf, "EOS hit"); + return GST_FLOW_EOS; + } +map_failed: + { + GST_ELEMENT_ERROR (dlbuf, RESOURCE, BUSY, + (_("Failed to map buffer.")), ("failed to map buffer in WRITE mode")); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +out_flushing: + { + GST_DEBUG_OBJECT (dlbuf, "we are flushing"); + g_clear_error (&error); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_FLUSHING; + } +read_error: + { + GST_DEBUG_OBJECT (dlbuf, "we have a read error: %s", error->message); + g_clear_error (&error); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return ret; + } +} + +/* must be called with MUTEX_LOCK. Will briefly release the lock when notifying + * the temp filename. */ +static gboolean +gst_download_buffer_open_temp_location_file (GstDownloadBuffer * dlbuf) +{ + gint fd = -1; + gchar *name = NULL; + + if (dlbuf->file) + goto already_opened; + + GST_DEBUG_OBJECT (dlbuf, "opening temp file %s", dlbuf->temp_template); + + /* If temp_template was set, allocate a filename and open that file */ + + /* nothing to do */ + if (dlbuf->temp_template == NULL) + goto no_directory; + + /* make copy of the template, we don't want to change this */ + name = g_strdup (dlbuf->temp_template); +#ifdef __BIONIC__ + fd = g_mkstemp_full (name, O_RDWR | O_LARGEFILE, S_IRUSR | S_IWUSR); +#else + fd = g_mkstemp (name); +#endif + if (fd == -1) + goto mkstemp_failed; + + /* open the file for update/writing */ + dlbuf->file = gst_sparse_file_new (); + /* error creating file */ + if (!gst_sparse_file_set_fd (dlbuf->file, fd)) + goto open_failed; + + g_free (dlbuf->temp_location); + dlbuf->temp_location = name; + dlbuf->temp_fd = fd; + reset_positions (dlbuf); + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* we can't emit the notify with the lock */ + g_object_notify (G_OBJECT (dlbuf), "temp-location"); + + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + + GST_DEBUG_OBJECT (dlbuf, "opened temp file %s", dlbuf->temp_template); + + return TRUE; + + /* ERRORS */ +already_opened: + { + GST_DEBUG_OBJECT (dlbuf, "temp file was already open"); + return TRUE; + } +no_directory: + { + GST_ELEMENT_ERROR (dlbuf, RESOURCE, NOT_FOUND, + (_("No Temp directory specified.")), (NULL)); + return FALSE; + } +mkstemp_failed: + { + GST_ELEMENT_ERROR (dlbuf, RESOURCE, OPEN_READ, + (_("Could not create temp file \"%s\"."), dlbuf->temp_template), + GST_ERROR_SYSTEM); + g_free (name); + return FALSE; + } +open_failed: + { + GST_ELEMENT_ERROR (dlbuf, RESOURCE, OPEN_READ, + (_("Could not open file \"%s\" for reading."), name), GST_ERROR_SYSTEM); + g_free (name); + if (fd != -1) + close (fd); + return FALSE; + } +} + +static void +gst_download_buffer_close_temp_location_file (GstDownloadBuffer * dlbuf) +{ + /* nothing to do */ + if (dlbuf->file == NULL) + return; + + GST_DEBUG_OBJECT (dlbuf, "closing sparse file"); + + if (dlbuf->temp_remove) { + if (remove (dlbuf->temp_location) < 0) { + GST_WARNING_OBJECT (dlbuf, "Failed to remove temporary file %s: %s", + dlbuf->temp_location, g_strerror (errno)); + } + } + gst_sparse_file_free (dlbuf->file); + close (dlbuf->temp_fd); + dlbuf->file = NULL; +} + +static void +gst_download_buffer_flush_temp_file (GstDownloadBuffer * dlbuf) +{ + if (dlbuf->file == NULL) + return; + + GST_DEBUG_OBJECT (dlbuf, "flushing temp file"); + + gst_sparse_file_clear (dlbuf->file); +} + +static void +gst_download_buffer_locked_flush (GstDownloadBuffer * dlbuf, gboolean full, + gboolean clear_temp) +{ + if (clear_temp) + gst_download_buffer_flush_temp_file (dlbuf); + reset_positions (dlbuf); + gst_event_replace (&dlbuf->stream_start_event, NULL); + gst_event_replace (&dlbuf->segment_event, NULL); +} + +static gboolean +gst_download_buffer_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + gboolean ret = TRUE; + GstDownloadBuffer *dlbuf; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + { + GST_LOG_OBJECT (dlbuf, "received flush start event"); + if (GST_PAD_MODE (dlbuf->srcpad) == GST_PAD_MODE_PUSH) { + /* forward event */ + ret = gst_pad_push_event (dlbuf->srcpad, event); + + /* now unblock the chain function */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + dlbuf->srcresult = GST_FLOW_FLUSHING; + dlbuf->sinkresult = GST_FLOW_FLUSHING; + /* unblock the loop and chain functions */ + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, -1); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* make sure it pauses, this should happen since we sent + * flush_start downstream. */ + gst_pad_pause_task (dlbuf->srcpad); + GST_LOG_OBJECT (dlbuf, "loop stopped"); + } else { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + /* flush the sink pad */ + dlbuf->sinkresult = GST_FLOW_FLUSHING; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + gst_event_unref (event); + } + break; + } + case GST_EVENT_FLUSH_STOP: + { + GST_LOG_OBJECT (dlbuf, "received flush stop event"); + + if (GST_PAD_MODE (dlbuf->srcpad) == GST_PAD_MODE_PUSH) { + /* forward event */ + ret = gst_pad_push_event (dlbuf->srcpad, event); + + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + gst_download_buffer_locked_flush (dlbuf, FALSE, TRUE); + dlbuf->srcresult = GST_FLOW_OK; + dlbuf->sinkresult = GST_FLOW_OK; + dlbuf->unexpected = FALSE; + dlbuf->seeking = FALSE; + /* reset rate counters */ + reset_rate_timer (dlbuf); + gst_pad_start_task (dlbuf->srcpad, + (GstTaskFunction) gst_download_buffer_loop, dlbuf->srcpad, NULL); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } else { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + dlbuf->unexpected = FALSE; + dlbuf->sinkresult = GST_FLOW_OK; + dlbuf->seeking = FALSE; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + gst_event_unref (event); + } + break; + } + default: + if (GST_EVENT_IS_SERIALIZED (event)) { + GstMessage *msg = NULL; + + /* serialized events go in the buffer */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->sinkresult, + out_flushing); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_DEBUG_OBJECT (dlbuf, "we have EOS"); + /* Zero the thresholds, this makes sure the dlbuf is completely + * filled and we can read all data from the dlbuf. */ + /* update the buffering status */ + update_levels (dlbuf, dlbuf->max_level.bytes); + /* update the buffering */ + msg = update_buffering (dlbuf); + /* wakeup the waiter and let it recheck */ + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, -1); + break; + case GST_EVENT_SEGMENT: + gst_event_replace (&dlbuf->segment_event, event); + /* a new segment allows us to accept more buffers if we got EOS + * from downstream */ + dlbuf->unexpected = FALSE; + break; + case GST_EVENT_STREAM_START: + gst_event_replace (&dlbuf->stream_start_event, event); + break; + default: + break; + } + gst_event_unref (event); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + } else { + /* non-serialized events are passed upstream. */ + ret = gst_pad_push_event (dlbuf->srcpad, event); + } + break; + } + return ret; + + /* ERRORS */ +out_flushing: + { + GST_DEBUG_OBJECT (dlbuf, "refusing event, we are flushing"); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_event_unref (event); + return FALSE; + } +} + +static gboolean +gst_download_buffer_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstDownloadBuffer *dlbuf; + gboolean res; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + switch (GST_QUERY_TYPE (query)) { + default: + if (GST_QUERY_IS_SERIALIZED (query)) { + GST_DEBUG_OBJECT (dlbuf, "refusing serialized query %p", query); + res = FALSE; + } else { + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; +} + +static GstFlowReturn +gst_download_buffer_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstDownloadBuffer *dlbuf; + GstMapInfo info; + guint64 offset; + gsize res, available; + GError *error = NULL; + GstMessage *msg = NULL; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + GST_LOG_OBJECT (dlbuf, "received buffer %p of " + "size %" G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + /* we have to lock the dlbuf since we span threads */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->sinkresult, out_flushing); + /* when we received unexpected from downstream, refuse more buffers */ + if (dlbuf->unexpected) + goto out_eos; + + /* while we didn't receive the newsegment, we're seeking and we skip data */ + if (dlbuf->seeking) + goto out_seeking; + + /* put buffer in dlbuf now */ + offset = dlbuf->write_pos; + + /* sanity check */ + if (GST_BUFFER_OFFSET_IS_VALID (buffer) && + GST_BUFFER_OFFSET (buffer) != offset) { + GST_WARNING_OBJECT (dlbuf, "buffer offset does not match current writing " + "position! %" G_GINT64_FORMAT " != %" G_GINT64_FORMAT, + GST_BUFFER_OFFSET (buffer), offset); + } + + if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) + goto map_error; + + GST_DEBUG_OBJECT (dlbuf, "Writing %" G_GSIZE_FORMAT " bytes to %" + G_GUINT64_FORMAT, info.size, offset); + + res = + gst_sparse_file_write (dlbuf->file, offset, info.data, info.size, + &available, &error); + if (res == 0) + goto write_error; + + gst_buffer_unmap (buffer, &info); + gst_buffer_unref (buffer); + + dlbuf->write_pos = offset + info.size; + dlbuf->bytes_in += info.size; + + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, dlbuf->write_pos + available); + + /* we hit the end, see what to do */ + if (dlbuf->write_pos + available == dlbuf->upstream_size) { + gsize start, stop; + + /* we have everything up to the end, find a region to fill */ + if (gst_sparse_file_get_range_after (dlbuf->file, 0, &start, &stop)) { + if (stop < dlbuf->upstream_size) { + /* a hole to fill, seek to its end */ + perform_seek_to_offset (dlbuf, stop); + } else { + /* we filled all the holes, we are done */ + goto completed; + } + } + } else { + /* see if we need to skip this region or just read it again. The idea + * is that when the region is not big, we want to avoid a seek and just + * let it reread */ + guint64 threshold = get_seek_threshold (dlbuf); + + if (available > threshold) { + /* further than threshold, it's better to skip than to reread */ + perform_seek_to_offset (dlbuf, dlbuf->write_pos + available); + } + } + if (dlbuf->filling) { + if (dlbuf->write_pos > dlbuf->read_pos) + update_levels (dlbuf, dlbuf->write_pos - dlbuf->read_pos); + else + update_levels (dlbuf, 0); + } + + /* update the buffering */ + msg = update_buffering (dlbuf); + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + + return GST_FLOW_OK; + + /* ERRORS */ +out_flushing: + { + GstFlowReturn ret = dlbuf->sinkresult; + GST_LOG_OBJECT (dlbuf, + "exit because task paused, reason: %s", gst_flow_get_name (ret)); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_buffer_unref (buffer); + return ret; + } +out_eos: + { + GST_LOG_OBJECT (dlbuf, "exit because we received EOS"); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_buffer_unref (buffer); + return GST_FLOW_EOS; + } +out_seeking: + { + GST_LOG_OBJECT (dlbuf, "exit because we are seeking"); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } +map_error: + { + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_buffer_unref (buffer); + GST_ELEMENT_ERROR (dlbuf, RESOURCE, BUSY, + (_("Failed to map buffer.")), ("failed to map buffer in READ mode")); + return GST_FLOW_ERROR; + } +write_error: + { + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + gst_buffer_unmap (buffer, &info); + gst_buffer_unref (buffer); + GST_ELEMENT_ERROR (dlbuf, RESOURCE, WRITE, + (_("Error while writing to download file.")), ("%s", error->message)); + g_clear_error (&error); + return GST_FLOW_ERROR; + } +completed: + { + GstMessage *complete_message; + + GST_LOG_OBJECT (dlbuf, "we completed the download"); + dlbuf->write_pos = dlbuf->upstream_size; + dlbuf->filling = FALSE; + update_levels (dlbuf, dlbuf->max_level.bytes); + msg = update_buffering (dlbuf); + complete_message = gst_message_new_element (GST_OBJECT_CAST (dlbuf), + gst_structure_new ("GstCacheDownloadComplete", + "location", G_TYPE_STRING, dlbuf->temp_location, NULL)); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), complete_message); + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + + return GST_FLOW_EOS; + } +} + +/* called repeatedly with @pad as the source pad. This function should push out + * data to the peer element. */ +static void +gst_download_buffer_loop (GstPad * pad) +{ + GstDownloadBuffer *dlbuf; + GstFlowReturn ret; + GstBuffer *buffer = NULL; + GstMessage *msg = NULL; + + dlbuf = GST_DOWNLOAD_BUFFER (GST_PAD_PARENT (pad)); + + /* have to lock for thread-safety */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->srcresult, out_flushing); + + if (dlbuf->stream_start_event != NULL) { + gst_pad_push_event (dlbuf->srcpad, dlbuf->stream_start_event); + dlbuf->stream_start_event = NULL; + } + if (dlbuf->segment_event != NULL) { + gst_pad_push_event (dlbuf->srcpad, dlbuf->segment_event); + dlbuf->segment_event = NULL; + } + + ret = gst_download_buffer_read_buffer (dlbuf, -1, -1, &buffer); + if (ret != GST_FLOW_OK) + goto out_flushing; + + /* update the buffering */ + msg = update_buffering (dlbuf); + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + + ret = gst_pad_push (dlbuf->srcpad, buffer); + + /* need to check for srcresult here as well */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->srcresult, out_flushing); + dlbuf->srcresult = ret; + dlbuf->sinkresult = ret; + if (ret != GST_FLOW_OK) + goto out_flushing; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + return; + + /* ERRORS */ +out_flushing: + { + GstFlowReturn ret = dlbuf->srcresult; + + gst_pad_pause_task (dlbuf->srcpad); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + GST_LOG_OBJECT (dlbuf, "pause task, reason: %s", gst_flow_get_name (ret)); + /* let app know about us giving up if upstream is not expected to do so */ + if (ret == GST_FLOW_EOS) { + /* FIXME perform EOS logic, this is really a basesrc operating on a + * file. */ + gst_pad_push_event (dlbuf->srcpad, gst_event_new_eos ()); + } else if ((ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { + GST_ELEMENT_FLOW_ERROR (dlbuf, ret); + gst_pad_push_event (dlbuf->srcpad, gst_event_new_eos ()); + } + return; + } +} + +static gboolean +gst_download_buffer_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + gboolean res = TRUE; + GstDownloadBuffer *dlbuf = GST_DOWNLOAD_BUFFER (parent); + +#ifndef GST_DISABLE_GST_DEBUG + GST_DEBUG_OBJECT (dlbuf, "got event %p (%s)", + event, GST_EVENT_TYPE_NAME (event)); +#endif + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + /* now unblock the getrange function */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "flushing"); + dlbuf->srcresult = GST_FLOW_FLUSHING; + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, -1); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* when using a temp file, we eat the event */ + res = TRUE; + gst_event_unref (event); + break; + case GST_EVENT_FLUSH_STOP: + /* now unblock the getrange function */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + dlbuf->srcresult = GST_FLOW_OK; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* when using a temp file, we eat the event */ + res = TRUE; + gst_event_unref (event); + break; + case GST_EVENT_RECONFIGURE: + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + /* assume downstream is linked now and try to push again */ + if (dlbuf->srcresult == GST_FLOW_NOT_LINKED) { + dlbuf->srcresult = GST_FLOW_OK; + dlbuf->sinkresult = GST_FLOW_OK; + if (GST_PAD_MODE (pad) == GST_PAD_MODE_PUSH) { + gst_pad_start_task (pad, (GstTaskFunction) gst_download_buffer_loop, + pad, NULL); + } + } + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + res = gst_pad_push_event (dlbuf->sinkpad, event); + break; + default: + res = gst_pad_push_event (dlbuf->sinkpad, event); + break; + } + + return res; +} + +static gboolean +gst_download_buffer_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstDownloadBuffer *dlbuf; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos; + GstFormat format; + + if (!gst_pad_peer_query (dlbuf->sinkpad, query)) + goto peer_failed; + + /* get peer position */ + gst_query_parse_position (query, &format, &peer_pos); + + /* FIXME: this code assumes that there's no discont in the dlbuf */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= dlbuf->cur_level.bytes; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + case GST_FORMAT_TIME: + peer_pos -= dlbuf->cur_level.time; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + default: + GST_WARNING_OBJECT (dlbuf, "dropping query in %s format, don't " + "know how to adjust value", gst_format_get_name (format)); + return FALSE; + } + /* set updated position */ + gst_query_set_position (query, format, peer_pos); + break; + } + case GST_QUERY_DURATION: + { + GST_DEBUG_OBJECT (dlbuf, "doing peer query"); + + if (!gst_pad_peer_query (dlbuf->sinkpad, query)) + goto peer_failed; + + GST_DEBUG_OBJECT (dlbuf, "peer query success"); + break; + } + case GST_QUERY_BUFFERING: + { + gint percent; + gboolean is_buffering; + GstBufferingMode mode; + gint avg_in, avg_out; + gint64 buffering_left; + + GST_DEBUG_OBJECT (dlbuf, "query buffering"); + + get_buffering_percent (dlbuf, &is_buffering, &percent); + gst_query_set_buffering_percent (query, is_buffering, percent); + + get_buffering_stats (dlbuf, percent, &mode, &avg_in, &avg_out, + &buffering_left); + gst_query_set_buffering_stats (query, mode, avg_in, avg_out, + buffering_left); + + { + /* add ranges for download and ringbuffer buffering */ + GstFormat format; + gint64 start, stop; + guint64 write_pos; + gint64 estimated_total; + gint64 duration; + gsize offset, range_start, range_stop; + + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + write_pos = dlbuf->write_pos; + + /* get duration of upstream in bytes */ + gst_download_buffer_update_upstream_size (dlbuf); + duration = dlbuf->upstream_size; + + GST_DEBUG_OBJECT (dlbuf, "percent %d, duration %" G_GINT64_FORMAT + ", writing %" G_GINT64_FORMAT, percent, duration, write_pos); + + gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL); + + /* fill out the buffered ranges */ + start = offset = 0; + stop = -1; + estimated_total = -1; + while (gst_sparse_file_get_range_after (dlbuf->file, offset, + &range_start, &range_stop)) { + gboolean current_range; + + GST_DEBUG_OBJECT (dlbuf, + "range starting at %" G_GSIZE_FORMAT " and finishing at %" + G_GSIZE_FORMAT, range_start, range_stop); + + offset = range_stop; + + /* find the range we are currently downloading, we'll remember it + * after we convert to the target format */ + if (range_start <= write_pos && range_stop >= write_pos) { + current_range = TRUE; + /* calculate remaining and total download time */ + if (duration >= range_stop && avg_in > 0.0) + estimated_total = ((duration - range_stop) * 1000) / avg_in; + } else + current_range = FALSE; + + switch (format) { + case GST_FORMAT_PERCENT: + /* get our available data relative to the duration */ + if (duration == -1) { + range_start = 0; + range_stop = 0; + } else { + range_start = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, + range_start, duration); + range_stop = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, + range_stop, duration); + } + break; + case GST_FORMAT_BYTES: + break; + default: + range_start = -1; + range_stop = -1; + break; + } + + if (current_range) { + /* we are currently downloading this range */ + start = range_start; + stop = range_stop; + } + GST_DEBUG_OBJECT (dlbuf, + "range to format: %" G_GSIZE_FORMAT " - %" G_GSIZE_FORMAT, + range_start, range_stop); + if (range_start == range_stop) + continue; + gst_query_add_buffering_range (query, range_start, range_stop); + } + + GST_DEBUG_OBJECT (dlbuf, "estimated-total %" G_GINT64_FORMAT, + estimated_total); + + gst_query_set_buffering_range (query, format, start, stop, + estimated_total); + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } + break; + } + case GST_QUERY_SCHEDULING: + { + GstSchedulingFlags flags = 0; + + if (!gst_pad_peer_query (dlbuf->sinkpad, query)) + goto peer_failed; + + gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL); + + /* we can operate in pull mode when we are using a tempfile */ + flags |= GST_SCHEDULING_FLAG_SEEKABLE; + gst_query_set_scheduling (query, flags, 0, -1, 0); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + break; + } + default: + /* peer handled other queries */ + if (!gst_pad_query_default (pad, parent, query)) + goto peer_failed; + break; + } + + return TRUE; + + /* ERRORS */ +peer_failed: + { + GST_DEBUG_OBJECT (dlbuf, "failed peer query"); + return FALSE; + } +} + +static gboolean +gst_download_buffer_handle_query (GstElement * element, GstQuery * query) +{ + GstDownloadBuffer *dlbuf = GST_DOWNLOAD_BUFFER (element); + + /* simply forward to the srcpad query function */ + return gst_download_buffer_handle_src_query (dlbuf->srcpad, + GST_OBJECT_CAST (element), query); +} + +static GstFlowReturn +gst_download_buffer_get_range (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstDownloadBuffer *dlbuf; + GstFlowReturn ret; + GstMessage *msg = NULL; + + dlbuf = GST_DOWNLOAD_BUFFER_CAST (parent); + + GST_DOWNLOAD_BUFFER_MUTEX_LOCK_CHECK (dlbuf, dlbuf->srcresult, out_flushing); + /* FIXME - function will block when the range is not yet available */ + ret = gst_download_buffer_read_buffer (dlbuf, offset, length, buffer); + /* update the buffering */ + msg = update_buffering (dlbuf); + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + + return ret; + + /* ERRORS */ +out_flushing: + { + ret = dlbuf->srcresult; + + GST_DEBUG_OBJECT (dlbuf, "we are flushing"); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + return ret; + } +} + +/* sink currently only operates in push mode */ +static gboolean +gst_download_buffer_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean result; + GstDownloadBuffer *dlbuf; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "activating push mode"); + dlbuf->srcresult = GST_FLOW_OK; + dlbuf->sinkresult = GST_FLOW_OK; + dlbuf->unexpected = FALSE; + reset_rate_timer (dlbuf); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } else { + /* unblock chain function */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "deactivating push mode"); + dlbuf->srcresult = GST_FLOW_FLUSHING; + dlbuf->sinkresult = GST_FLOW_FLUSHING; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* wait until it is unblocked and clean up */ + GST_PAD_STREAM_LOCK (pad); + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + gst_download_buffer_locked_flush (dlbuf, TRUE, FALSE); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + GST_PAD_STREAM_UNLOCK (pad); + } + result = TRUE; + break; + default: + result = FALSE; + break; + } + return result; +} + +/* src operating in push mode, we start a task on the source pad that pushes out + * buffers from the dlbuf */ +static gboolean +gst_download_buffer_src_activate_push (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean result = FALSE; + GstDownloadBuffer *dlbuf; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + if (active) { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "activating push mode"); + dlbuf->srcresult = GST_FLOW_OK; + dlbuf->sinkresult = GST_FLOW_OK; + dlbuf->unexpected = FALSE; + result = + gst_pad_start_task (pad, (GstTaskFunction) gst_download_buffer_loop, + pad, NULL); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } else { + /* unblock loop function */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "deactivating push mode"); + dlbuf->srcresult = GST_FLOW_FLUSHING; + dlbuf->sinkresult = GST_FLOW_FLUSHING; + /* the item add signal will unblock */ + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, -1); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + /* step 2, make sure streaming finishes */ + result = gst_pad_stop_task (pad); + } + + return result; +} + +/* pull mode, downstream will call our getrange function */ +static gboolean +gst_download_buffer_src_activate_pull (GstPad * pad, GstObject * parent, + gboolean active) +{ + gboolean result; + GstDownloadBuffer *dlbuf; + + dlbuf = GST_DOWNLOAD_BUFFER (parent); + + if (active) { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + /* open the temp file now */ + result = gst_download_buffer_open_temp_location_file (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "activating pull mode"); + dlbuf->srcresult = GST_FLOW_OK; + dlbuf->sinkresult = GST_FLOW_OK; + dlbuf->unexpected = FALSE; + dlbuf->upstream_size = 0; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } else { + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + GST_DEBUG_OBJECT (dlbuf, "deactivating pull mode"); + dlbuf->srcresult = GST_FLOW_FLUSHING; + dlbuf->sinkresult = GST_FLOW_FLUSHING; + /* this will unlock getrange */ + GST_DOWNLOAD_BUFFER_SIGNAL_ADD (dlbuf, -1); + result = TRUE; + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + } + + return result; +} + +static gboolean +gst_download_buffer_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_download_buffer_src_activate_pull (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_download_buffer_src_activate_push (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + +static GstStateChangeReturn +gst_download_buffer_change_state (GstElement * element, + GstStateChange transition) +{ + GstDownloadBuffer *dlbuf; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + dlbuf = GST_DOWNLOAD_BUFFER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + if (!gst_download_buffer_open_temp_location_file (dlbuf)) + ret = GST_STATE_CHANGE_FAILURE; + gst_event_replace (&dlbuf->stream_start_event, NULL); + gst_event_replace (&dlbuf->segment_event, NULL); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + 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: + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + gst_download_buffer_close_temp_location_file (dlbuf); + gst_event_replace (&dlbuf->stream_start_event, NULL); + gst_event_replace (&dlbuf->segment_event, NULL); + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +#define CAPACITY_CHANGE(elem) \ + update_buffering (elem); + +static void +gst_download_buffer_set_temp_template (GstDownloadBuffer * dlbuf, + const gchar * template) +{ + GstState state; + + /* the element must be stopped in order to do this */ + GST_OBJECT_LOCK (dlbuf); + state = GST_STATE (dlbuf); + if (state != GST_STATE_READY && state != GST_STATE_NULL) + goto wrong_state; + GST_OBJECT_UNLOCK (dlbuf); + + /* set new location */ + g_free (dlbuf->temp_template); + dlbuf->temp_template = g_strdup (template); + + return; + +/* ERROR */ +wrong_state: + { + GST_WARNING_OBJECT (dlbuf, "setting temp-template property in wrong state"); + GST_OBJECT_UNLOCK (dlbuf); + } +} + +static void +gst_download_buffer_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstDownloadBuffer *dlbuf = GST_DOWNLOAD_BUFFER (object); + GstMessage *msg = NULL; + + /* someone could change levels here, and since this + * affects the get/put funcs, we need to lock for safety. */ + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + + switch (prop_id) { + case PROP_MAX_SIZE_BYTES: + dlbuf->max_level.bytes = g_value_get_uint (value); + msg = CAPACITY_CHANGE (dlbuf); + break; + case PROP_MAX_SIZE_TIME: + dlbuf->max_level.time = g_value_get_uint64 (value); + msg = CAPACITY_CHANGE (dlbuf); + break; + case PROP_LOW_PERCENT: + dlbuf->low_percent = g_value_get_int (value); + break; + case PROP_HIGH_PERCENT: + dlbuf->high_percent = g_value_get_int (value); + break; + case PROP_TEMP_TEMPLATE: + gst_download_buffer_set_temp_template (dlbuf, g_value_get_string (value)); + break; + case PROP_TEMP_REMOVE: + dlbuf->temp_remove = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (dlbuf), msg); + +} + +static void +gst_download_buffer_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstDownloadBuffer *dlbuf = GST_DOWNLOAD_BUFFER (object); + + GST_DOWNLOAD_BUFFER_MUTEX_LOCK (dlbuf); + + switch (prop_id) { + case PROP_MAX_SIZE_BYTES: + g_value_set_uint (value, dlbuf->max_level.bytes); + break; + case PROP_MAX_SIZE_TIME: + g_value_set_uint64 (value, dlbuf->max_level.time); + break; + case PROP_LOW_PERCENT: + g_value_set_int (value, dlbuf->low_percent); + break; + case PROP_HIGH_PERCENT: + g_value_set_int (value, dlbuf->high_percent); + break; + case PROP_TEMP_TEMPLATE: + g_value_set_string (value, dlbuf->temp_template); + break; + case PROP_TEMP_LOCATION: + g_value_set_string (value, dlbuf->temp_location); + break; + case PROP_TEMP_REMOVE: + g_value_set_boolean (value, dlbuf->temp_remove); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_DOWNLOAD_BUFFER_MUTEX_UNLOCK (dlbuf); +} diff --git a/plugins/elements/gstdownloadbuffer.h b/plugins/elements/gstdownloadbuffer.h new file mode 100644 index 0000000..f33bbf1 --- /dev/null +++ b/plugins/elements/gstdownloadbuffer.h @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 2014 Wim Taymans + * + * gstdownloadbuffer.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __GST_DOWNLOAD_BUFFER_H__ +#define __GST_DOWNLOAD_BUFFER_H__ + +#include +#include + +#include "gstsparsefile.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DOWNLOAD_BUFFER \ + (gst_download_buffer_get_type()) +#define GST_DOWNLOAD_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DOWNLOAD_BUFFER,GstDownloadBuffer)) +#define GST_DOWNLOAD_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DOWNLOAD_BUFFER,GstDownloadBufferClass)) +#define GST_IS_DOWNLOAD_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DOWNLOAD_BUFFER)) +#define GST_IS_DOWNLOAD_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DOWNLOAD_BUFFER)) +#define GST_DOWNLOAD_BUFFER_CAST(obj) \ + ((GstDownloadBuffer *)(obj)) + +typedef struct _GstDownloadBuffer GstDownloadBuffer; +typedef struct _GstDownloadBufferClass GstDownloadBufferClass; +typedef struct _GstDownloadBufferSize GstDownloadBufferSize; + +/* used to keep track of sizes (current and max) */ +struct _GstDownloadBufferSize +{ + guint bytes; + guint64 time; +}; + +struct _GstDownloadBuffer +{ + GstElement element; + + /*< private > */ + GstPad *sinkpad; + GstPad *srcpad; + + /* upstream size in bytes (if downstream is operating in pull mode) */ + guint64 upstream_size; + + /* flowreturn when srcpad is paused */ + GstFlowReturn srcresult; + GstFlowReturn sinkresult; + gboolean unexpected; + + /* the queue of data we're keeping our hands on */ + GstSparseFile *file; + guint64 write_pos; + guint64 read_pos; + gboolean filling; + + GstDownloadBufferSize cur_level; + GstDownloadBufferSize max_level; + gint low_percent; /* low/high watermarks for buffering */ + gint high_percent; + + /* current buffering state */ + gboolean is_buffering; + gint buffering_percent; + + /* for measuring input/output rates */ + GTimer *in_timer; + gboolean in_timer_started; + gdouble last_in_elapsed; + guint64 bytes_in; + gdouble byte_in_rate; + gdouble byte_in_period; + + GTimer *out_timer; + gboolean out_timer_started; + gdouble last_out_elapsed; + guint64 bytes_out; + gdouble byte_out_rate; + + GMutex qlock; /* lock for queue (vs object lock) */ + gboolean waiting_add; + GCond item_add; /* signals buffers now available for reading */ + guint64 waiting_offset; + + /* temp location stuff */ + gchar *temp_template; + gboolean temp_location_set; + gchar *temp_location; + gboolean temp_remove; + gint temp_fd; + gboolean seeking; + + GstEvent *stream_start_event; + GstEvent *segment_event; +}; + +struct _GstDownloadBufferClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_download_buffer_get_type (void); + +G_END_DECLS + +#endif /* __GST_DOWNLOAD_BUFFER_H__ */ diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c new file mode 100644 index 0000000..57f989d --- /dev/null +++ b/plugins/elements/gstelements.c @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstelements.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "gstcapsfilter.h" +#include "gstconcat.h" +#include "gstdataurisrc.h" +#include "gstdownloadbuffer.h" +#include "gstfakesink.h" +#include "gstfakesrc.h" +#include "gstfdsrc.h" +#include "gstfdsink.h" +#include "gstfilesink.h" +#include "gstfilesrc.h" +#include "gstfunnel.h" +#include "gstidentity.h" +#include "gstinputselector.h" +#include "gstoutputselector.h" +#include "gstmultiqueue.h" +#include "gstqueue.h" +#include "gstqueue2.h" +#include "gsttee.h" +#include "gsttypefindelement.h" +#include "gstvalve.h" +#include "gststreamiddemux.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "capsfilter", GST_RANK_NONE, + gst_capsfilter_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "concat", GST_RANK_NONE, + gst_concat_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "dataurisrc", GST_RANK_PRIMARY, + gst_data_uri_src_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "downloadbuffer", GST_RANK_NONE, + gst_download_buffer_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "fakesrc", GST_RANK_NONE, + gst_fake_src_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "fakesink", GST_RANK_NONE, + gst_fake_sink_get_type ())) + return FALSE; +#if defined(HAVE_SYS_SOCKET_H) || defined(_MSC_VER) + if (!gst_element_register (plugin, "fdsrc", GST_RANK_NONE, + gst_fd_src_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "fdsink", GST_RANK_NONE, + gst_fd_sink_get_type ())) + return FALSE; +#endif + if (!gst_element_register (plugin, "filesrc", GST_RANK_PRIMARY, + gst_file_src_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "funnel", GST_RANK_NONE, + gst_funnel_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "identity", GST_RANK_NONE, + gst_identity_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "input-selector", GST_RANK_NONE, + gst_input_selector_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "output-selector", GST_RANK_NONE, + gst_output_selector_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "queue", GST_RANK_NONE, + gst_queue_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "queue2", GST_RANK_NONE, + gst_queue2_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "filesink", GST_RANK_PRIMARY, + gst_file_sink_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "tee", GST_RANK_NONE, gst_tee_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "typefind", GST_RANK_NONE, + gst_type_find_element_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "multiqueue", GST_RANK_NONE, + gst_multi_queue_get_type ())) + return FALSE; + if (!gst_element_register (plugin, "valve", GST_RANK_NONE, + gst_valve_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "streamiddemux", GST_RANK_PRIMARY, + gst_streamid_demux_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, coreelements, + "GStreamer core elements", plugin_init, VERSION, GST_LICENSE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/plugins/elements/gstelements_private.c b/plugins/elements/gstelements_private.c new file mode 100644 index 0000000..2c0ca58 --- /dev/null +++ b/plugins/elements/gstelements_private.c @@ -0,0 +1,352 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * Copyright (C) 2011 Tim-Philipp Müller + * Copyright (C) 2014 Tim-Philipp Müller + * Copyright (C) 2014 Vincent Penquerc'h + * + * gstelements_private.c: Shared code for core 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_UIO_H +#include +#endif +#include +#include +#include +#include "gst/gst.h" +#include "gstelements_private.h" + +#ifdef G_OS_WIN32 +# define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ +# include +# undef WIN32_LEAN_AND_MEAN +# ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN +# endif +#endif /* G_OS_WIN32 */ + +#define BUFFER_FLAG_SHIFT 4 + +G_STATIC_ASSERT ((1 << BUFFER_FLAG_SHIFT) == GST_MINI_OBJECT_FLAG_LAST); + +/* Returns a newly allocated string describing the flags on this buffer */ +gchar * +gst_buffer_get_flags_string (GstBuffer * buffer) +{ + static const char flag_strings[] = + "\000\000\000\000live\000decode-only\000discont\000resync\000corrupted\000" + "marker\000header\000gap\000droppable\000delta-unit\000tag-memory\000" + "FIXME"; + static const guint8 flag_idx[] = { 0, 1, 2, 3, 4, 9, 21, 29, 36, 46, 53, + 60, 64, 74, 85, 96 + }; + int i, max_bytes; + char *flag_str, *end; + + /* max size is all flag strings plus a space or terminator after each one */ + max_bytes = sizeof (flag_strings); + flag_str = g_malloc (max_bytes); + + end = flag_str; + end[0] = '\0'; + for (i = BUFFER_FLAG_SHIFT; i < G_N_ELEMENTS (flag_idx); i++) { + if (GST_MINI_OBJECT_CAST (buffer)->flags & (1 << i)) { + strcpy (end, flag_strings + flag_idx[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + + return flag_str; +} + +/* Returns a newly-allocated string describing the metas on this buffer, or NULL */ +gchar * +gst_buffer_get_meta_string (GstBuffer * buffer) +{ + gpointer state = NULL; + GstMeta *meta; + GString *s = NULL; + + while ((meta = gst_buffer_iterate_meta (buffer, &state))) { + const gchar *desc = g_type_name (meta->info->type); + + if (s == NULL) + s = g_string_new (NULL); + else + g_string_append (s, ", "); + + g_string_append (s, desc); + } + + return (s != NULL) ? g_string_free (s, FALSE) : NULL; +} + +/* Define our own iovec structure here, so that we can use it unconditionally + * in the code below and use almost the same code path for systems where + * writev() is supported and those were it's not supported */ +#ifndef HAVE_SYS_UIO_H +struct iovec +{ + gpointer iov_base; + gsize iov_len; +}; +#endif + +/* completely arbitrary thresholds */ +#define FDSINK_MAX_ALLOCA_SIZE (64 * 1024) /* 64k */ +#define FDSINK_MAX_MALLOC_SIZE ( 8 * 1024 * 1024) /* 8M */ + +/* UIO_MAXIOV is documented in writev(2), but only + * declares it on osx/ios if defined(KERNEL) */ +#ifndef UIO_MAXIOV +#define UIO_MAXIOV 512 +#endif + +static gssize +gst_writev (gint fd, const struct iovec *iov, gint iovcnt, gsize total_bytes) +{ + gssize written; + +#ifdef HAVE_SYS_UIO_H + if (iovcnt <= UIO_MAXIOV) { + do { + written = writev (fd, iov, iovcnt); + } while (written < 0 && errno == EINTR); + } else +#endif + { + gint i; + + /* We merge the memories here because technically write()/writev() is + * supposed to be atomic, which it's not if we do multiple separate + * write() calls. It's very doubtful anyone cares though in our use + * cases, and it's not clear how that can be reconciled with the + * possibility of short writes, so in any case we might want to + * simplify this later or just remove it. */ + if (total_bytes <= FDSINK_MAX_MALLOC_SIZE) { + gchar *mem, *p; + + if (total_bytes <= FDSINK_MAX_ALLOCA_SIZE) + mem = g_alloca (total_bytes); + else + mem = g_malloc (total_bytes); + + p = mem; + for (i = 0; i < iovcnt; ++i) { + memcpy (p, iov[i].iov_base, iov[i].iov_len); + p += iov[i].iov_len; + } + + do { + written = write (fd, mem, total_bytes); + } while (written < 0 && errno == EINTR); + + if (total_bytes > FDSINK_MAX_ALLOCA_SIZE) + g_free (mem); + } else { + gssize ret; + + written = 0; + for (i = 0; i < iovcnt; ++i) { + do { + ret = write (fd, iov[i].iov_base, iov[i].iov_len); + } while (ret < 0 && errno == EINTR); + if (ret > 0) + written += ret; + if (ret != iov[i].iov_len) + break; + } + } + } + + return written; +} + +static gsize +fill_vectors (struct iovec *vecs, GstMapInfo * maps, guint n, GstBuffer * buf) +{ + GstMemory *mem; + gsize size = 0; + guint i; + + g_assert (gst_buffer_n_memory (buf) == n); + + for (i = 0; i < n; ++i) { + mem = gst_buffer_peek_memory (buf, i); + if (gst_memory_map (mem, &maps[i], GST_MAP_READ)) { + vecs[i].iov_base = maps[i].data; + vecs[i].iov_len = maps[i].size; + } else { + GST_WARNING ("Failed to map memory %p for reading", mem); + vecs[i].iov_base = (void *) ""; + vecs[i].iov_len = 0; + } + size += vecs[i].iov_len; + } + + return size; +} + +GstFlowReturn +gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, + GstBuffer ** buffers, guint num_buffers, guint8 * mem_nums, + guint total_mem_num, guint64 * bytes_written, guint64 skip) +{ + struct iovec *vecs; + GstMapInfo *map_infos; + GstFlowReturn flow_ret; + gsize size = 0; + guint i, j; + + GST_LOG_OBJECT (sink, "%u buffers, %u memories", num_buffers, total_mem_num); + + vecs = g_newa (struct iovec, total_mem_num); + map_infos = g_newa (GstMapInfo, total_mem_num); + + /* populate output vectors */ + for (i = 0, j = 0; i < num_buffers; ++i) { + size += fill_vectors (&vecs[j], &map_infos[j], mem_nums[i], buffers[i]); + j += mem_nums[i]; + } + + /* now write it all out! */ + { + gssize ret, left; + guint n_vecs = total_mem_num; + + left = size; + + if (skip) { + ret = skip; + errno = 0; + goto skip_first; + } + + do { +#ifndef HAVE_WIN32 + if (fdset != NULL) { + do { + GST_DEBUG_OBJECT (sink, "going into select, have %" G_GSSIZE_FORMAT + " bytes to write", left); + ret = gst_poll_wait (fdset, GST_CLOCK_TIME_NONE); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + if (ret == -1) { + if (errno == EBUSY) + goto stopped; + else + goto select_error; + } + } +#endif + + ret = gst_writev (fd, vecs, n_vecs, left); + + if (ret > 0) { + if (bytes_written) + *bytes_written += ret; + } + + skip_first: + + if (ret == left) + break; + + if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + /* do nothing, try again */ + } else if (ret < 0) { + goto write_error; + } else if (ret < left) { + /* skip vectors that have been written in full */ + while (ret >= vecs[0].iov_len) { + ret -= vecs[0].iov_len; + left -= vecs[0].iov_len; + ++vecs; + --n_vecs; + } + g_assert (n_vecs > 0); + /* skip partially written vector data */ + if (ret > 0) { + vecs[0].iov_len -= ret; + vecs[0].iov_base = ((guint8 *) vecs[0].iov_base) + ret; + left -= ret; + } + } +#ifdef HAVE_WIN32 + /* do short sleep on windows where we don't use gst_poll(), + * to avoid excessive busy looping */ + if (fdset != NULL) + g_usleep (1000); +#endif + + } + while (left > 0); + } + + flow_ret = GST_FLOW_OK; + +out: + + for (i = 0; i < total_mem_num; ++i) + gst_memory_unmap (map_infos[i].memory, &map_infos[i]); + + return flow_ret; + +/* ERRORS */ +#ifndef HAVE_WIN32 +select_error: + { + GST_ELEMENT_ERROR (sink, RESOURCE, READ, (NULL), + ("select on file descriptor: %s", g_strerror (errno))); + GST_DEBUG_OBJECT (sink, "Error during select: %s", g_strerror (errno)); + flow_ret = GST_FLOW_ERROR; + goto out; + } +stopped: + { + GST_DEBUG_OBJECT (sink, "Select stopped"); + flow_ret = GST_FLOW_FLUSHING; + goto out; + } +#endif +write_error: + { + switch (errno) { + case ENOSPC: + GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL)); + break; + default:{ + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), + ("Error while writing to file descriptor %d: %s", + fd, g_strerror (errno))); + } + } + flow_ret = GST_FLOW_ERROR; + goto out; + } +} diff --git a/plugins/elements/gstelements_private.h b/plugins/elements/gstelements_private.h new file mode 100644 index 0000000..d196594 --- /dev/null +++ b/plugins/elements/gstelements_private.h @@ -0,0 +1,44 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gst_private.h: Private header for within libgst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_ELEMENTS_PRIVATE_H__ +#define __GST_ELEMENTS_PRIVATE_H__ + +#include "gst/gst.h" + +G_BEGIN_DECLS + +G_GNUC_INTERNAL +gchar * gst_buffer_get_flags_string (GstBuffer *buffer); + +G_GNUC_INTERNAL +gchar * gst_buffer_get_meta_string (GstBuffer * buffer); + +G_GNUC_INTERNAL +GstFlowReturn gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, + GstBuffer ** buffers, guint num_buffers, + guint8 * mem_nums, guint total_mem_num, + guint64 * bytes_written, guint64 skip); + +G_END_DECLS + +#endif /* __GST_ELEMENTS_PRIVATE_H__ */ diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c new file mode 100644 index 0000000..b71f20f --- /dev/null +++ b/plugins/elements/gstfakesink.c @@ -0,0 +1,597 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstfakesink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-fakesink + * @title: fakesink + * @see_also: #GstFakeSrc + * + * Dummy sink that swallows everything. + * + * ## Example launch line + * |[ + * gst-launch-1.0 audiotestsrc num-buffers=1000 ! fakesink sync=false + * ]| Render 1000 audio buffers (of default size) as fast as possible. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstelements_private.h" +#include "gstfakesink.h" +#include + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_fake_sink_debug); +#define GST_CAT_DEFAULT gst_fake_sink_debug + +/* FakeSink signals and args */ +enum +{ + /* FILL ME */ + SIGNAL_HANDOFF, + SIGNAL_PREROLL_HANDOFF, + LAST_SIGNAL +}; + +#define DEFAULT_SYNC FALSE +#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE + +#define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE +#define DEFAULT_SILENT TRUE +#define DEFAULT_DUMP FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_LAST_MESSAGE NULL +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE +#define DEFAULT_CAN_ACTIVATE_PULL FALSE +#define DEFAULT_NUM_BUFFERS -1 + +enum +{ + PROP_0, + PROP_STATE_ERROR, + PROP_SILENT, + PROP_DUMP, + PROP_SIGNAL_HANDOFFS, + PROP_DROP_OUT_OF_SEGMENT, + PROP_LAST_MESSAGE, + PROP_CAN_ACTIVATE_PUSH, + PROP_CAN_ACTIVATE_PULL, + PROP_NUM_BUFFERS +}; + +#define GST_TYPE_FAKE_SINK_STATE_ERROR (gst_fake_sink_state_error_get_type()) +static GType +gst_fake_sink_state_error_get_type (void) +{ + static GType fakesink_state_error_type = 0; + static const GEnumValue fakesink_state_error[] = { + {FAKE_SINK_STATE_ERROR_NONE, "No state change errors", "none"}, + {FAKE_SINK_STATE_ERROR_NULL_READY, + "Fail state change from NULL to READY", "null-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_PAUSED, + "Fail state change from READY to PAUSED", "ready-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + "Fail state change from PAUSED to PLAYING", "paused-to-playing"}, + {FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + "Fail state change from PLAYING to PAUSED", "playing-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_READY, + "Fail state change from PAUSED to READY", "paused-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_NULL, + "Fail state change from READY to NULL", "ready-to-null"}, + {0, NULL, NULL}, + }; + + if (!fakesink_state_error_type) { + fakesink_state_error_type = + g_enum_register_static ("GstFakeSinkStateError", fakesink_state_error); + } + return fakesink_state_error_type; +} + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_fake_sink_debug, "fakesink", 0, "fakesink element"); +#define gst_fake_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFakeSink, gst_fake_sink, GST_TYPE_BASE_SINK, + _do_init); + +static void gst_fake_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_fake_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_fake_sink_finalize (GObject * obj); + +static GstStateChangeReturn gst_fake_sink_change_state (GstElement * element, + GstStateChange transition); + +static GstFlowReturn gst_fake_sink_preroll (GstBaseSink * bsink, + GstBuffer * buffer); +static GstFlowReturn gst_fake_sink_render (GstBaseSink * bsink, + GstBuffer * buffer); +static gboolean gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event); +static gboolean gst_fake_sink_query (GstBaseSink * bsink, GstQuery * query); + +static guint gst_fake_sink_signals[LAST_SIGNAL] = { 0 }; + +static GParamSpec *pspec_last_message = NULL; + +static void +gst_fake_sink_class_init (GstFakeSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbase_sink_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbase_sink_class = GST_BASE_SINK_CLASS (klass); + + gobject_class->set_property = gst_fake_sink_set_property; + gobject_class->get_property = gst_fake_sink_get_property; + gobject_class->finalize = gst_fake_sink_finalize; + + g_object_class_install_property (gobject_class, PROP_STATE_ERROR, + g_param_spec_enum ("state-error", "State Error", + "Generate a state change error", GST_TYPE_FAKE_SINK_STATE_ERROR, + DEFAULT_STATE_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "Last Message", + "The message describing current status", DEFAULT_LAST_MESSAGE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS, + g_param_spec_boolean ("signal-handoffs", "Signal handoffs", + "Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DROP_OUT_OF_SEGMENT, + g_param_spec_boolean ("drop-out-of-segment", + "Drop out-of-segment buffers", + "Drop and don't render / hand off out-of-segment buffers", + DEFAULT_DROP_OUT_OF_SEGMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout", + DEFAULT_DUMP, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + 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)); + g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to accept going EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstFakeSink::handoff: + * @fakesink: the fakesink instance + * @buffer: the buffer that just has been received + * @pad: the pad that received it + * + * This signal gets emitted before unreffing the buffer. + */ + gst_fake_sink_signals[SIGNAL_HANDOFF] = + g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + + /** + * GstFakeSink::preroll-handoff: + * @fakesink: the fakesink instance + * @buffer: the buffer that just has been received + * @pad: the pad that received it + * + * This signal gets emitted before unreffing the buffer. + */ + gst_fake_sink_signals[SIGNAL_PREROLL_HANDOFF] = + g_signal_new ("preroll-handoff", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSinkClass, preroll_handoff), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + + gst_element_class_set_static_metadata (gstelement_class, + "Fake Sink", + "Sink", + "Black hole for data", + "Erik Walthinsen , " + "Wim Taymans , " + "Mr. 'frag-me-more' Vanderwingo "); + + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_fake_sink_change_state); + + gstbase_sink_class->event = GST_DEBUG_FUNCPTR (gst_fake_sink_event); + gstbase_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_fake_sink_preroll); + gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_fake_sink_render); + gstbase_sink_class->query = GST_DEBUG_FUNCPTR (gst_fake_sink_query); +} + +static void +gst_fake_sink_init (GstFakeSink * fakesink) +{ + fakesink->silent = DEFAULT_SILENT; + fakesink->dump = DEFAULT_DUMP; + fakesink->last_message = g_strdup (DEFAULT_LAST_MESSAGE); + fakesink->state_error = DEFAULT_STATE_ERROR; + fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + fakesink->num_buffers = DEFAULT_NUM_BUFFERS; + + gst_base_sink_set_sync (GST_BASE_SINK (fakesink), DEFAULT_SYNC); + gst_base_sink_set_drop_out_of_segment (GST_BASE_SINK (fakesink), + DEFAULT_DROP_OUT_OF_SEGMENT); +} + +static void +gst_fake_sink_finalize (GObject * obj) +{ + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_fake_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFakeSink *sink; + + sink = GST_FAKE_SINK (object); + + switch (prop_id) { + case PROP_STATE_ERROR: + sink->state_error = (GstFakeSinkStateError) g_value_get_enum (value); + break; + case PROP_SILENT: + sink->silent = g_value_get_boolean (value); + break; + case PROP_DUMP: + sink->dump = g_value_get_boolean (value); + break; + case PROP_SIGNAL_HANDOFFS: + sink->signal_handoffs = g_value_get_boolean (value); + break; + case PROP_DROP_OUT_OF_SEGMENT: + gst_base_sink_set_drop_out_of_segment (GST_BASE_SINK (object), + g_value_get_boolean (value)); + break; + case PROP_CAN_ACTIVATE_PUSH: + GST_BASE_SINK (sink)->can_activate_push = g_value_get_boolean (value); + break; + case PROP_CAN_ACTIVATE_PULL: + GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value); + break; + case PROP_NUM_BUFFERS: + sink->num_buffers = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFakeSink *sink; + + sink = GST_FAKE_SINK (object); + + switch (prop_id) { + case PROP_STATE_ERROR: + g_value_set_enum (value, sink->state_error); + break; + case PROP_SILENT: + g_value_set_boolean (value, sink->silent); + break; + case PROP_DUMP: + g_value_set_boolean (value, sink->dump); + break; + case PROP_SIGNAL_HANDOFFS: + g_value_set_boolean (value, sink->signal_handoffs); + break; + case PROP_DROP_OUT_OF_SEGMENT: + g_value_set_boolean (value, + gst_base_sink_get_drop_out_of_segment (GST_BASE_SINK (object))); + break; + case PROP_LAST_MESSAGE: + GST_OBJECT_LOCK (sink); + g_value_set_string (value, sink->last_message); + GST_OBJECT_UNLOCK (sink); + break; + case PROP_CAN_ACTIVATE_PUSH: + g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_push); + break; + case PROP_CAN_ACTIVATE_PULL: + g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull); + break; + case PROP_NUM_BUFFERS: + g_value_set_int (value, sink->num_buffers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fake_sink_notify_last_message (GstFakeSink * sink) +{ + g_object_notify_by_pspec ((GObject *) sink, pspec_last_message); +} + +static gboolean +gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) +{ + GstFakeSink *sink = GST_FAKE_SINK (bsink); + + if (!sink->silent) { + const GstStructure *s; + const gchar *tstr; + gchar *sstr; + + GST_OBJECT_LOCK (sink); + g_free (sink->last_message); + + if (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE) { + GstMessage *msg; + const GstStructure *structure; + + gst_event_parse_sink_message (event, &msg); + structure = gst_message_get_structure (msg); + sstr = gst_structure_to_string (structure); + sink->last_message = + g_strdup_printf ("message ******* (%s:%s) M (type: %d, %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + GST_MESSAGE_TYPE (msg), sstr, msg); + gst_message_unref (msg); + } else { + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); + + if ((s = gst_event_get_structure (event))) { + sstr = gst_structure_to_string (s); + } else { + sstr = g_strdup (""); + } + + sink->last_message = + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + tstr, GST_EVENT_TYPE (event), sstr, event); + } + g_free (sstr); + GST_OBJECT_UNLOCK (sink); + + gst_fake_sink_notify_last_message (sink); + } + + return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); +} + +static GstFlowReturn +gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer) +{ + GstFakeSink *sink = GST_FAKE_SINK (bsink); + + if (sink->num_buffers_left == 0) + goto eos; + + if (!sink->silent) { + GST_OBJECT_LOCK (sink); + g_free (sink->last_message); + + sink->last_message = g_strdup_printf ("preroll ******* "); + GST_OBJECT_UNLOCK (sink); + + gst_fake_sink_notify_last_message (sink); + } + if (sink->signal_handoffs) { + g_signal_emit (sink, + gst_fake_sink_signals[SIGNAL_PREROLL_HANDOFF], 0, buffer, + bsink->sinkpad); + } + return GST_FLOW_OK; + + /* ERRORS */ +eos: + { + GST_DEBUG_OBJECT (sink, "we are EOS"); + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) +{ + GstFakeSink *sink = GST_FAKE_SINK_CAST (bsink); + + if (sink->num_buffers_left == 0) + goto eos; + + if (sink->num_buffers_left != -1) + sink->num_buffers_left--; + + if (!sink->silent) { + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar *flag_str, *meta_str; + + GST_OBJECT_LOCK (sink); + g_free (sink->last_message); + + if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DTS (buf))); + } else { + g_strlcpy (dts_str, "none", sizeof (dts_str)); + } + + if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } else { + g_strlcpy (pts_str, "none", sizeof (pts_str)); + } + + if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + } else { + g_strlcpy (dur_str, "none", sizeof (dur_str)); + } + + flag_str = gst_buffer_get_flags_string (buf); + meta_str = gst_buffer_get_meta_string (buf); + + sink->last_message = + g_strdup_printf ("chain ******* (%s:%s) (%u bytes, dts: %s, pts: %s" + ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" + G_GINT64_FORMAT ", flags: %08x %s, meta: %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + (guint) gst_buffer_get_size (buf), dts_str, pts_str, + dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_MINI_OBJECT_CAST (buf)->flags, flag_str, + meta_str ? meta_str : "none", buf); + g_free (flag_str); + g_free (meta_str); + GST_OBJECT_UNLOCK (sink); + + gst_fake_sink_notify_last_message (sink); + } + if (sink->signal_handoffs) + g_signal_emit (sink, gst_fake_sink_signals[SIGNAL_HANDOFF], 0, buf, + bsink->sinkpad); + + if (sink->dump) { + GstMapInfo info; + + if (gst_buffer_map (buf, &info, GST_MAP_READ)) { + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); + } + } + if (sink->num_buffers_left == 0) + goto eos; + + return GST_FLOW_OK; + + /* ERRORS */ +eos: + { + GST_DEBUG_OBJECT (sink, "we are EOS"); + return GST_FLOW_EOS; + } +} + +static gboolean +gst_fake_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + /* we don't supporting seeking */ + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + gst_query_set_seeking (query, fmt, FALSE, 0, -1); + ret = TRUE; + break; + } + default: + ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + } + + return ret; +} + +static GstStateChangeReturn +gst_fake_sink_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstFakeSink *fakesink = GST_FAKE_SINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_NULL_READY) + goto error; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_PAUSED) + goto error; + fakesink->num_buffers_left = fakesink->num_buffers; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_PLAYING) + goto error; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PLAYING_PAUSED) + goto error; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_READY) + goto error; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_NULL) + goto error; + GST_OBJECT_LOCK (fakesink); + g_free (fakesink->last_message); + fakesink->last_message = NULL; + GST_OBJECT_UNLOCK (fakesink); + break; + default: + break; + } + + return ret; + + /* ERROR */ +error: + GST_ELEMENT_ERROR (element, CORE, STATE_CHANGE, (NULL), + ("Erroring out on state change as requested")); + return GST_STATE_CHANGE_FAILURE; +} diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h new file mode 100644 index 0000000..72b3671 --- /dev/null +++ b/plugins/elements/gstfakesink.h @@ -0,0 +1,99 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfakesink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FAKE_SINK_H__ +#define __GST_FAKE_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_FAKE_SINK \ + (gst_fake_sink_get_type()) +#define GST_FAKE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FAKE_SINK,GstFakeSink)) +#define GST_FAKE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FAKE_SINK,GstFakeSinkClass)) +#define GST_IS_FAKE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAKE_SINK)) +#define GST_IS_FAKE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKE_SINK)) +#define GST_FAKE_SINK_CAST(obj) ((GstFakeSink *)obj) + +/** + * GstFakeSinkStateError: + * @FAKE_SINK_STATE_ERROR_NONE: no error + * @FAKE_SINK_STATE_ERROR_NULL_READY: cause the NULL to READY state change to fail + * @FAKE_SINK_STATE_ERROR_READY_PAUSED: cause the READY to PAUSED state change to fail: + * @FAKE_SINK_STATE_ERROR_PAUSED_PLAYING: cause the PAUSED to PLAYING state change to fail: + * @FAKE_SINK_STATE_ERROR_PLAYING_PAUSED: cause the PLAYING to PAUSED state change to fail: + * @FAKE_SINK_STATE_ERROR_PAUSED_READY: cause the PAUSED to READY state change to fail: + * @FAKE_SINK_STATE_ERROR_READY_NULL: cause the READY to NULL state change to fail: + * + * Possible state change errors for the state-error property. + */ +typedef enum { + FAKE_SINK_STATE_ERROR_NONE = 0, + FAKE_SINK_STATE_ERROR_NULL_READY, + FAKE_SINK_STATE_ERROR_READY_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_READY, + FAKE_SINK_STATE_ERROR_READY_NULL +} GstFakeSinkStateError; + +typedef struct _GstFakeSink GstFakeSink; +typedef struct _GstFakeSinkClass GstFakeSinkClass; + +/** + * GstFakeSink: + * + * The opaque #GstFakeSink data structure. + */ +struct _GstFakeSink { + GstBaseSink element; + + gboolean silent; + gboolean dump; + gboolean signal_handoffs; + GstFakeSinkStateError state_error; + gchar *last_message; + gint num_buffers; + gint num_buffers_left; +}; + +struct _GstFakeSinkClass { + GstBaseSinkClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad); + void (*preroll_handoff) (GstElement *element, GstBuffer *buf, GstPad *pad); +}; + +G_GNUC_INTERNAL GType gst_fake_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_FAKE_SINK_H__ */ diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c new file mode 100644 index 0000000..14f3226 --- /dev/null +++ b/plugins/elements/gstfakesrc.c @@ -0,0 +1,918 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfakesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-fakesrc + * @title: fakesrc + * @see_also: #GstFakeSink + * + * The fakesrc element is a multipurpose element that can generate + * a wide range of buffers and can operate in various scheduling modes. + * + * It is mostly used as a testing element, one trivial example for testing + * basic GStreamer core functionality is: + * + * ## Example launch line + * |[ + * gst-launch-1.0 -v fakesrc num-buffers=5 ! fakesink + * ]| This pipeline will push 5 empty buffers to the fakesink element and then + * sends an EOS. + * + */ + +/* FIXME: this ignores basesrc::blocksize property, which could be used as an + * alias to ::sizemax (see gst_base_src_get_blocksize()). + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstelements_private.h" +#include "gstfakesrc.h" + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_fake_src_debug); +#define GST_CAT_DEFAULT gst_fake_src_debug + +/* FakeSrc signals and args */ +enum +{ + /* FILL ME */ + SIGNAL_HANDOFF, + LAST_SIGNAL +}; + +#define DEFAULT_OUTPUT FAKE_SRC_FIRST_LAST_LOOP +#define DEFAULT_DATA FAKE_SRC_DATA_ALLOCATE +#define DEFAULT_SIZETYPE FAKE_SRC_SIZETYPE_EMPTY +#define DEFAULT_SIZEMIN 0 +#define DEFAULT_SIZEMAX 4096 +#define DEFAULT_FILLTYPE FAKE_SRC_FILLTYPE_ZERO +#define DEFAULT_DATARATE 0 +#define DEFAULT_SYNC FALSE +#define DEFAULT_PATTERN NULL +#define DEFAULT_EOS FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_SILENT TRUE +#define DEFAULT_DUMP FALSE +#define DEFAULT_PARENTSIZE 4096*10 +#define DEFAULT_CAN_ACTIVATE_PULL TRUE +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE +#define DEFAULT_FORMAT GST_FORMAT_BYTES + +enum +{ + PROP_0, + PROP_OUTPUT, + PROP_DATA, + PROP_SIZETYPE, + PROP_SIZEMIN, + PROP_SIZEMAX, + PROP_FILLTYPE, + PROP_DATARATE, + PROP_SYNC, + PROP_PATTERN, + PROP_EOS, + PROP_SIGNAL_HANDOFFS, + PROP_SILENT, + PROP_DUMP, + PROP_PARENTSIZE, + PROP_LAST_MESSAGE, + PROP_CAN_ACTIVATE_PULL, + PROP_CAN_ACTIVATE_PUSH, + PROP_IS_LIVE, + PROP_FORMAT, + PROP_LAST, +}; + +/* not implemented +#define GST_TYPE_FAKE_SRC_OUTPUT (gst_fake_src_output_get_type()) +static GType +gst_fake_src_output_get_type (void) +{ + static GType fakesrc_output_type = 0; + static const GEnumValue fakesrc_output[] = { + {FAKE_SRC_FIRST_LAST_LOOP, "1", "First-Last loop"}, + {FAKE_SRC_LAST_FIRST_LOOP, "2", "Last-First loop"}, + {FAKE_SRC_PING_PONG, "3", "Ping-Pong"}, + {FAKE_SRC_ORDERED_RANDOM, "4", "Ordered Random"}, + {FAKE_SRC_RANDOM, "5", "Random"}, + {FAKE_SRC_PATTERN_LOOP, "6", "Patttern loop"}, + {FAKE_SRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"}, + {FAKE_SRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"}, + {0, NULL, NULL}, + }; + + if (!fakesrc_output_type) { + fakesrc_output_type = + g_enum_register_static ("GstFakeSrcOutputType", fakesrc_output); + } + return fakesrc_output_type; +} +*/ + +#define GST_TYPE_FAKE_SRC_DATA (gst_fake_src_data_get_type()) +static GType +gst_fake_src_data_get_type (void) +{ + static GType fakesrc_data_type = 0; + static const GEnumValue fakesrc_data[] = { + {FAKE_SRC_DATA_ALLOCATE, "Allocate data", "allocate"}, + {FAKE_SRC_DATA_SUBBUFFER, "Subbuffer data", "subbuffer"}, + {0, NULL, NULL}, + }; + + if (!fakesrc_data_type) { + fakesrc_data_type = + g_enum_register_static ("GstFakeSrcDataType", fakesrc_data); + } + return fakesrc_data_type; +} + +#define GST_TYPE_FAKE_SRC_SIZETYPE (gst_fake_src_sizetype_get_type()) +static GType +gst_fake_src_sizetype_get_type (void) +{ + static GType fakesrc_sizetype_type = 0; + static const GEnumValue fakesrc_sizetype[] = { + {FAKE_SRC_SIZETYPE_EMPTY, "Send empty buffers", "empty"}, + {FAKE_SRC_SIZETYPE_FIXED, "Fixed size buffers (sizemax sized)", "fixed"}, + {FAKE_SRC_SIZETYPE_RANDOM, + "Random sized buffers (sizemin <= size <= sizemax)", "random"}, + {0, NULL, NULL}, + }; + + if (!fakesrc_sizetype_type) { + fakesrc_sizetype_type = + g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype); + } + return fakesrc_sizetype_type; +} + +#define GST_TYPE_FAKE_SRC_FILLTYPE (gst_fake_src_filltype_get_type()) +static GType +gst_fake_src_filltype_get_type (void) +{ + static GType fakesrc_filltype_type = 0; + static const GEnumValue fakesrc_filltype[] = { + {FAKE_SRC_FILLTYPE_NOTHING, "Leave data as malloced", "nothing"}, + {FAKE_SRC_FILLTYPE_ZERO, "Fill buffers with zeros", "zero"}, + {FAKE_SRC_FILLTYPE_RANDOM, "Fill buffers with random data", "random"}, + {FAKE_SRC_FILLTYPE_PATTERN, "Fill buffers with pattern 0x00 -> 0xff", + "pattern"}, + {FAKE_SRC_FILLTYPE_PATTERN_CONT, + "Fill buffers with pattern 0x00 -> 0xff that spans buffers", + "pattern-span"}, + {0, NULL, NULL}, + }; + + if (!fakesrc_filltype_type) { + fakesrc_filltype_type = + g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype); + } + return fakesrc_filltype_type; +} + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element"); +#define gst_fake_src_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFakeSrc, gst_fake_src, GST_TYPE_BASE_SRC, _do_init); + +static void gst_fake_src_finalize (GObject * object); +static void gst_fake_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_fake_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_fake_src_start (GstBaseSrc * basesrc); +static gboolean gst_fake_src_stop (GstBaseSrc * basesrc); +static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc); + +static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event); +static void gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end); +static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset, + guint length, GstBuffer ** buf); + +static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 }; + +static GParamSpec *pspec_last_message = NULL; + +static void +gst_fake_src_class_init (GstFakeSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbase_src_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbase_src_class = GST_BASE_SRC_CLASS (klass); + + gobject_class->finalize = gst_fake_src_finalize; + + gobject_class->set_property = gst_fake_src_set_property; + gobject_class->get_property = gst_fake_src_get_property; + +/* + FIXME: this is not implemented; would make sense once basesrc and fakesrc + support multiple pads + g_object_class_install_property (gobject_class, PROP_OUTPUT, + g_param_spec_enum ("output", "output", "Output method (currently unused)", + GST_TYPE_FAKE_SRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE)); +*/ + g_object_class_install_property (gobject_class, PROP_DATA, + g_param_spec_enum ("data", "data", "Data allocation method", + GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZETYPE, + g_param_spec_enum ("sizetype", "sizetype", + "How to determine buffer sizes", GST_TYPE_FAKE_SRC_SIZETYPE, + DEFAULT_SIZETYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SIZEMIN, + g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0, + G_MAXINT, DEFAULT_SIZEMIN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SIZEMAX, + g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0, + G_MAXINT, DEFAULT_SIZEMAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PARENTSIZE, + g_param_spec_int ("parentsize", "parentsize", + "Size of parent buffer for sub-buffered allocation", 0, G_MAXINT, + DEFAULT_PARENTSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FILLTYPE, + g_param_spec_enum ("filltype", "filltype", + "How to fill the buffer, if at all", GST_TYPE_FAKE_SRC_FILLTYPE, + DEFAULT_FILLTYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DATARATE, + g_param_spec_int ("datarate", "Datarate", + "Timestamps buffers with number of bytes per second (0 = none)", 0, + G_MAXINT, DEFAULT_DATARATE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SYNC, + g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate", + DEFAULT_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* FIXME 2.0: Remove unused pattern property. Not implemented */ + g_object_class_install_property (gobject_class, PROP_PATTERN, + g_param_spec_string ("pattern", "pattern", "Set the pattern (unused)", + DEFAULT_PATTERN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "last-message", + "The last status message", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS, + g_param_spec_boolean ("signal-handoffs", "Signal handoffs", + "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout", + DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH, + g_param_spec_boolean ("can-activate-push", "Can activate push", + "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL, + g_param_spec_boolean ("can-activate-pull", "Can activate pull", + "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_IS_LIVE, + g_param_spec_boolean ("is-live", "Is this a live source", + "True if the element cannot produce data in PAUSED", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + /** + * GstFakeSrc:format + * + * Set the format of the newsegment events to produce. + */ + g_object_class_install_property (gobject_class, PROP_FORMAT, + g_param_spec_enum ("format", "Format", + "The format of the segment events", GST_TYPE_FORMAT, + DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstFakeSrc::handoff: + * @fakesrc: the fakesrc instance + * @buffer: the buffer that will be pushed + * @pad: the pad that will sent it + * + * This signal gets emitted before sending the buffer. + */ + gst_fake_src_signals[SIGNAL_HANDOFF] = + g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + + gst_element_class_set_static_metadata (gstelement_class, + "Fake Source", + "Source", + "Push empty (no data) buffers around", + "Erik Walthinsen , " "Wim Taymans "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + + gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable); + gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start); + gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop); + gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler); + gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times); + gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create); +} + +static void +gst_fake_src_init (GstFakeSrc * fakesrc) +{ + fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP; + fakesrc->silent = DEFAULT_SILENT; + fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + fakesrc->dump = DEFAULT_DUMP; + fakesrc->pattern_byte = 0x00; + fakesrc->data = FAKE_SRC_DATA_ALLOCATE; + fakesrc->sizetype = FAKE_SRC_SIZETYPE_EMPTY; + fakesrc->filltype = FAKE_SRC_FILLTYPE_NOTHING; + fakesrc->sizemin = DEFAULT_SIZEMIN; + fakesrc->sizemax = DEFAULT_SIZEMAX; + fakesrc->parent = NULL; + fakesrc->parentsize = DEFAULT_PARENTSIZE; + fakesrc->last_message = NULL; + fakesrc->datarate = DEFAULT_DATARATE; + fakesrc->sync = DEFAULT_SYNC; + fakesrc->format = DEFAULT_FORMAT; +} + +static void +gst_fake_src_finalize (GObject * object) +{ + GstFakeSrc *src; + + src = GST_FAKE_SRC (object); + + g_free (src->last_message); + if (src->parent) { + gst_buffer_unref (src->parent); + src->parent = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event) +{ + GstFakeSrc *src; + + src = GST_FAKE_SRC (basesrc); + + if (!src->silent) { + const GstStructure *s; + const gchar *tstr; + gchar *sstr; + + GST_OBJECT_LOCK (src); + g_free (src->last_message); + + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); + + if ((s = gst_event_get_structure (event))) + sstr = gst_structure_to_string (s); + else + sstr = g_strdup (""); + + src->last_message = + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), + tstr, GST_EVENT_TYPE (event), sstr, event); + g_free (sstr); + GST_OBJECT_UNLOCK (src); + + g_object_notify_by_pspec ((GObject *) src, pspec_last_message); + } + + return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); +} + +static void +gst_fake_src_alloc_parent (GstFakeSrc * src) +{ + GstBuffer *buf; + + buf = gst_buffer_new_allocate (NULL, src->parentsize, NULL); + + src->parent = buf; + src->parentoffset = 0; +} + +static void +gst_fake_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFakeSrc *src; + GstBaseSrc *basesrc; + + src = GST_FAKE_SRC (object); + basesrc = GST_BASE_SRC (object); + + switch (prop_id) { + case PROP_OUTPUT: + g_warning ("not yet implemented"); + break; + case PROP_DATA: + src->data = (GstFakeSrcDataType) g_value_get_enum (value); + + if (src->data == FAKE_SRC_DATA_SUBBUFFER) { + if (!src->parent) + gst_fake_src_alloc_parent (src); + } else { + if (src->parent) { + gst_buffer_unref (src->parent); + src->parent = NULL; + } + } + break; + case PROP_SIZETYPE: + src->sizetype = (GstFakeSrcSizeType) g_value_get_enum (value); + break; + case PROP_SIZEMIN: + src->sizemin = g_value_get_int (value); + break; + case PROP_SIZEMAX: + src->sizemax = g_value_get_int (value); + break; + case PROP_PARENTSIZE: + src->parentsize = g_value_get_int (value); + break; + case PROP_FILLTYPE: + src->filltype = (GstFakeSrcFillType) g_value_get_enum (value); + break; + case PROP_DATARATE: + src->datarate = g_value_get_int (value); + break; + case PROP_SYNC: + src->sync = g_value_get_boolean (value); + break; + case PROP_PATTERN: + break; + case PROP_SILENT: + src->silent = g_value_get_boolean (value); + break; + case PROP_SIGNAL_HANDOFFS: + src->signal_handoffs = g_value_get_boolean (value); + break; + case PROP_DUMP: + src->dump = g_value_get_boolean (value); + break; + case PROP_CAN_ACTIVATE_PUSH: + g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, + GST_BASE_SRC_FLAG_STARTED)); + GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value); + break; + case PROP_CAN_ACTIVATE_PULL: + g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, + GST_BASE_SRC_FLAG_STARTED)); + src->can_activate_pull = g_value_get_boolean (value); + break; + case PROP_IS_LIVE: + gst_base_src_set_live (basesrc, g_value_get_boolean (value)); + break; + case PROP_FORMAT: + src->format = (GstFormat) g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFakeSrc *src; + GstBaseSrc *basesrc; + + g_return_if_fail (GST_IS_FAKE_SRC (object)); + + src = GST_FAKE_SRC (object); + basesrc = GST_BASE_SRC (object); + + switch (prop_id) { + case PROP_OUTPUT: + g_value_set_enum (value, src->output); + break; + case PROP_DATA: + g_value_set_enum (value, src->data); + break; + case PROP_SIZETYPE: + g_value_set_enum (value, src->sizetype); + break; + case PROP_SIZEMIN: + g_value_set_int (value, src->sizemin); + break; + case PROP_SIZEMAX: + g_value_set_int (value, src->sizemax); + break; + case PROP_PARENTSIZE: + g_value_set_int (value, src->parentsize); + break; + case PROP_FILLTYPE: + g_value_set_enum (value, src->filltype); + break; + case PROP_DATARATE: + g_value_set_int (value, src->datarate); + break; + case PROP_SYNC: + g_value_set_boolean (value, src->sync); + break; + case PROP_PATTERN: + break; + case PROP_SILENT: + g_value_set_boolean (value, src->silent); + break; + case PROP_SIGNAL_HANDOFFS: + g_value_set_boolean (value, src->signal_handoffs); + break; + case PROP_DUMP: + g_value_set_boolean (value, src->dump); + break; + case PROP_LAST_MESSAGE: + GST_OBJECT_LOCK (src); + g_value_set_string (value, src->last_message); + GST_OBJECT_UNLOCK (src); + 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; + case PROP_IS_LIVE: + g_value_set_boolean (value, gst_base_src_is_live (basesrc)); + break; + case PROP_FORMAT: + g_value_set_enum (value, src->format); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fake_src_prepare_buffer (GstFakeSrc * src, guint8 * data, gsize size) +{ + if (size == 0) + return; + + switch (src->filltype) { + case FAKE_SRC_FILLTYPE_ZERO: + memset (data, 0, size); + break; + case FAKE_SRC_FILLTYPE_RANDOM: + { + gint i; + guint8 *ptr = data; + + for (i = size; i; i--) { + *ptr++ = g_random_int_range (0, 256); + } + break; + } + case FAKE_SRC_FILLTYPE_PATTERN: + src->pattern_byte = 0x00; + case FAKE_SRC_FILLTYPE_PATTERN_CONT: + { + gint i; + guint8 *ptr = data; + + for (i = size; i; i--) { + *ptr++ = src->pattern_byte++; + } + break; + } + case FAKE_SRC_FILLTYPE_NOTHING: + default: + break; + } +} + +static GstBuffer * +gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size) +{ + GstBuffer *buf; + gpointer data; + gboolean do_prepare = FALSE; + + buf = gst_buffer_new (); + + if (size != 0) { + switch (src->filltype) { + case FAKE_SRC_FILLTYPE_NOTHING: + data = g_malloc (size); + break; + case FAKE_SRC_FILLTYPE_ZERO: + data = g_malloc0 (size); + break; + case FAKE_SRC_FILLTYPE_RANDOM: + case FAKE_SRC_FILLTYPE_PATTERN: + case FAKE_SRC_FILLTYPE_PATTERN_CONT: + default: + data = g_malloc (size); + do_prepare = TRUE; + break; + } + if (do_prepare) + gst_fake_src_prepare_buffer (src, data, size); + + gst_buffer_append_memory (buf, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); + } + + return buf; +} + +static guint +gst_fake_src_get_size (GstFakeSrc * src) +{ + guint size; + + switch (src->sizetype) { + case FAKE_SRC_SIZETYPE_FIXED: + size = src->sizemax; + break; + case FAKE_SRC_SIZETYPE_RANDOM: + size = g_random_int_range (src->sizemin, src->sizemax); + break; + case FAKE_SRC_SIZETYPE_EMPTY: + default: + size = 0; + break; + } + + return size; +} + +static GstBuffer * +gst_fake_src_create_buffer (GstFakeSrc * src, gsize * bufsize) +{ + GstBuffer *buf; + gsize size = gst_fake_src_get_size (src); + gboolean dump = src->dump; + GstMapInfo info; + + *bufsize = size; + + switch (src->data) { + case FAKE_SRC_DATA_ALLOCATE: + buf = gst_fake_src_alloc_buffer (src, size); + break; + case FAKE_SRC_DATA_SUBBUFFER: + /* see if we have a parent to subbuffer */ + if (!src->parent) { + gst_fake_src_alloc_parent (src); + g_assert (src->parent); + } + /* see if it's large enough */ + if ((src->parentsize - src->parentoffset) >= size) { + buf = + gst_buffer_copy_region (src->parent, GST_BUFFER_COPY_ALL, + src->parentoffset, size); + src->parentoffset += size; + } else { + /* the parent is useless now */ + gst_buffer_unref (src->parent); + src->parent = NULL; + /* try again (this will allocate a new parent) */ + return gst_fake_src_create_buffer (src, bufsize); + } + if (buf == NULL) + goto buffer_create_fail; + if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) + goto buffer_write_fail; + gst_fake_src_prepare_buffer (src, info.data, info.size); + gst_buffer_unmap (buf, &info); + break; + default: + g_warning ("fakesrc: dunno how to allocate buffers !"); + buf = gst_buffer_new (); + break; + } + if (dump) { + if (gst_buffer_map (buf, &info, GST_MAP_READ)) { + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); + } + } + + return buf; + +buffer_create_fail: + { + GST_ELEMENT_ERROR (src, RESOURCE, BUSY, (NULL), + ("Failed to create a buffer")); + return NULL; + } + +buffer_write_fail: + { + GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), + ("Failed to write to buffer")); + gst_buffer_unref (buf); + return NULL; + } +} + +static void +gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + GstFakeSrc *src; + + src = GST_FAKE_SRC (basesrc); + + /* sync on the timestamp of the buffer if requested. */ + if (src->sync) { + GstClockTime timestamp, duration; + + /* first sync on DTS, else use PTS */ + timestamp = GST_BUFFER_DTS (buffer); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + timestamp = GST_BUFFER_PTS (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + duration = GST_BUFFER_DURATION (buffer); + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } + } else { + *start = -1; + *end = -1; + } +} + +static GstFlowReturn +gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFakeSrc *src; + GstBuffer *buf; + GstClockTime time; + gsize size; + + src = GST_FAKE_SRC (basesrc); + + buf = gst_fake_src_create_buffer (src, &size); + GST_BUFFER_OFFSET (buf) = offset; + + if (src->datarate > 0) { + time = (src->bytes_sent * GST_SECOND) / src->datarate; + + GST_BUFFER_DURATION (buf) = size * GST_SECOND / src->datarate; + } else if (gst_base_src_is_live (basesrc)) { + GstClock *clock; + + clock = gst_element_get_clock (GST_ELEMENT (src)); + + if (clock) { + time = gst_clock_get_time (clock); + time -= gst_element_get_base_time (GST_ELEMENT (src)); + gst_object_unref (clock); + } else { + /* not an error not to have a clock */ + time = GST_CLOCK_TIME_NONE; + } + } else { + time = GST_CLOCK_TIME_NONE; + } + + GST_BUFFER_DTS (buf) = time; + GST_BUFFER_PTS (buf) = time; + + if (!src->silent) { + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar *flag_str; + + GST_OBJECT_LOCK (src); + g_free (src->last_message); + + if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DTS (buf))); + } else { + g_strlcpy (dts_str, "none", sizeof (dts_str)); + } + if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } else { + g_strlcpy (pts_str, "none", sizeof (pts_str)); + } + if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + } else { + g_strlcpy (dur_str, "none", sizeof (dur_str)); + } + + flag_str = gst_buffer_get_flags_string (buf); + src->last_message = + g_strdup_printf ("create ******* (%s:%s) (%u bytes, dts: %s, pts:%s" + ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" + G_GINT64_FORMAT ", flags: %08x %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size, + dts_str, pts_str, dur_str, GST_BUFFER_OFFSET (buf), + GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, + flag_str, buf); + g_free (flag_str); + GST_OBJECT_UNLOCK (src); + + g_object_notify_by_pspec ((GObject *) src, pspec_last_message); + } + + if (src->signal_handoffs) { + GST_LOG_OBJECT (src, "pre handoff emit"); + g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf, + basesrc->srcpad); + GST_LOG_OBJECT (src, "post handoff emit"); + } + + src->bytes_sent += size; + + *ret = buf; + return GST_FLOW_OK; +} + +static gboolean +gst_fake_src_start (GstBaseSrc * basesrc) +{ + GstFakeSrc *src; + + src = GST_FAKE_SRC (basesrc); + + src->pattern_byte = 0x00; + src->bytes_sent = 0; + + gst_base_src_set_format (basesrc, src->format); + + return TRUE; +} + +static gboolean +gst_fake_src_stop (GstBaseSrc * basesrc) +{ + GstFakeSrc *src; + + src = GST_FAKE_SRC (basesrc); + + GST_OBJECT_LOCK (src); + if (src->parent) { + gst_buffer_unref (src->parent); + src->parent = NULL; + } + g_free (src->last_message); + src->last_message = NULL; + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +static gboolean +gst_fake_src_is_seekable (GstBaseSrc * basesrc) +{ + GstFakeSrc *src = GST_FAKE_SRC (basesrc); + + return src->can_activate_pull; +} diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h new file mode 100644 index 0000000..0d54d82 --- /dev/null +++ b/plugins/elements/gstfakesrc.h @@ -0,0 +1,165 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfakesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FAKE_SRC_H__ +#define __GST_FAKE_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GstFakeSrcOutputType: + * @FAKE_SRC_FIRST_LAST_LOOP: first pad then last pad + * @FAKE_SRC_LAST_FIRST_LOOP: last pad then first pad + * @FAKE_SRC_PING_PONG: ping pong between pads + * @FAKE_SRC_ORDERED_RANDOM: ordered random pad + * @FAKE_SRC_RANDOM: random pad + * @FAKE_SRC_PATTERN_LOOP: loop between pads in a particular pattern + * @FAKE_SRC_PING_PONG_PATTERN: ping pong based on a pattern + * @FAKE_SRC_GET_ALWAYS_SUCEEDS: a get always succeeds on a pad + * + * The different output types. Unused currently. + */ +typedef enum { + FAKE_SRC_FIRST_LAST_LOOP = 1, + FAKE_SRC_LAST_FIRST_LOOP, + FAKE_SRC_PING_PONG, + FAKE_SRC_ORDERED_RANDOM, + FAKE_SRC_RANDOM, + FAKE_SRC_PATTERN_LOOP, + FAKE_SRC_PING_PONG_PATTERN, + FAKE_SRC_GET_ALWAYS_SUCEEDS +} GstFakeSrcOutputType; + +/** + * GstFakeSrcDataType: + * @FAKE_SRC_DATA_ALLOCATE: allocate buffers + * @FAKE_SRC_DATA_SUBBUFFER: subbuffer each buffer + * + * The different ways buffers are allocated. + */ +typedef enum { + FAKE_SRC_DATA_ALLOCATE = 1, + FAKE_SRC_DATA_SUBBUFFER +} GstFakeSrcDataType; + +/** + * GstFakeSrcSizeType: + * @FAKE_SRC_SIZETYPE_EMPTY: create empty buffers + * @FAKE_SRC_SIZETYPE_FIXED: fixed buffer size (sizemax sized) + * @FAKE_SRC_SIZETYPE_RANDOM: random buffer size (sizemin <= size <= sizemax) + * + * The different size of the allocated buffers. + */ +typedef enum { + FAKE_SRC_SIZETYPE_EMPTY = 1, + FAKE_SRC_SIZETYPE_FIXED, + FAKE_SRC_SIZETYPE_RANDOM +} GstFakeSrcSizeType; + +/** + * GstFakeSrcFillType: + * @FAKE_SRC_FILLTYPE_NOTHING: do not fill buffers + * @FAKE_SRC_FILLTYPE_ZERO: fill buffers with 0 + * @FAKE_SRC_FILLTYPE_RANDOM: fill buffers with random bytes + * @FAKE_SRC_FILLTYPE_PATTERN: fill buffers with a pattern + * @FAKE_SRC_FILLTYPE_PATTERN_CONT: fill buffers with a continuous pattern + * + * The different ways of filling the buffers. + */ +typedef enum { + FAKE_SRC_FILLTYPE_NOTHING = 1, + FAKE_SRC_FILLTYPE_ZERO, + FAKE_SRC_FILLTYPE_RANDOM, + FAKE_SRC_FILLTYPE_PATTERN, + FAKE_SRC_FILLTYPE_PATTERN_CONT +} GstFakeSrcFillType; + +#define GST_TYPE_FAKE_SRC \ + (gst_fake_src_get_type()) +#define GST_FAKE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FAKE_SRC,GstFakeSrc)) +#define GST_FAKE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FAKE_SRC,GstFakeSrcClass)) +#define GST_IS_FAKE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAKE_SRC)) +#define GST_IS_FAKE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKE_SRC)) + +typedef struct _GstFakeSrc GstFakeSrc; +typedef struct _GstFakeSrcClass GstFakeSrcClass; + +/** + * GstFakeSrc: + * + * Opaque #GstFakeSrc data structure. + */ +struct _GstFakeSrc { + GstBaseSrc element; + + /*< private >*/ + gboolean has_loop; + gboolean has_getrange; + + GstFakeSrcOutputType output; + GstFakeSrcDataType data; + GstFakeSrcSizeType sizetype; + GstFakeSrcFillType filltype; + + guint sizemin; + guint sizemax; + GstBuffer *parent; + guint parentsize; + guint parentoffset; + guint8 pattern_byte; + GList *patternlist; + gint datarate; + gboolean sync; + GstClock *clock; + + gboolean silent; + gboolean signal_handoffs; + gboolean dump; + gboolean can_activate_pull; + GstFormat format; + + guint64 bytes_sent; + + gchar *last_message; +}; + +struct _GstFakeSrcClass { + GstBaseSrcClass parent_class; + + /*< public >*/ + /* signals */ + void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad); +}; + +G_GNUC_INTERNAL GType gst_fake_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_FAKE_SRC_H__ */ diff --git a/plugins/elements/gstfdsink.c b/plugins/elements/gstfdsink.c new file mode 100644 index 0000000..54a169b --- /dev/null +++ b/plugins/elements/gstfdsink.c @@ -0,0 +1,651 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfdsink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-fdsink + * @title: fdsink + * @see_also: #GstFdSrc + * + * Write data to a unix file descriptor. + * + * This element will synchronize on the clock before writing the data on the + * socket. For file descriptors where this does not make sense (files, ...) the + * #GstBaseSink:sync property can be used to disable synchronisation. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../../gst/gst-i18n-lib.h" + +#include + +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _MSC_VER +#undef stat +#define stat _stat +#define fstat _fstat +#define S_ISREG(m) (((m)&S_IFREG)==S_IFREG) +#endif +#include +#include + +#include "gstfdsink.h" +#include "gstelements_private.h" + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#undef off_t +#define off_t guint64 +#endif + +#if defined(__BIONIC__) /* Android */ +#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 +#undef fstat +#define fstat fstat64 +#endif +#endif + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_fd_sink__debug); +#define GST_CAT_DEFAULT gst_fd_sink__debug + + +/* FdSink signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FD +}; + +static void gst_fd_sink_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +#define _do_init \ + G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_fd_sink_uri_handler_init); \ + GST_DEBUG_CATEGORY_INIT (gst_fd_sink__debug, "fdsink", 0, "fdsink element"); +#define gst_fd_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFdSink, gst_fd_sink, GST_TYPE_BASE_SINK, _do_init); + +static void gst_fd_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_fd_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_fd_sink_dispose (GObject * obj); + +static gboolean gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query); +static GstFlowReturn gst_fd_sink_render (GstBaseSink * sink, + GstBuffer * buffer); +static GstFlowReturn gst_fd_sink_render_list (GstBaseSink * bsink, + GstBufferList * buffer_list); +static gboolean gst_fd_sink_start (GstBaseSink * basesink); +static gboolean gst_fd_sink_stop (GstBaseSink * basesink); +static gboolean gst_fd_sink_unlock (GstBaseSink * basesink); +static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink); +static gboolean gst_fd_sink_event (GstBaseSink * sink, GstEvent * event); + +static gboolean gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset); + +static void +gst_fd_sink_class_init (GstFdSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasesink_class = GST_BASE_SINK_CLASS (klass); + + gobject_class->set_property = gst_fd_sink_set_property; + gobject_class->get_property = gst_fd_sink_get_property; + gobject_class->dispose = gst_fd_sink_dispose; + + gst_element_class_set_static_metadata (gstelement_class, + "Filedescriptor Sink", + "Sink/File", + "Write data to a file descriptor", "Erik Walthinsen "); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_fd_sink_render); + gstbasesink_class->render_list = GST_DEBUG_FUNCPTR (gst_fd_sink_render_list); + gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_fd_sink_start); + gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop); + gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock); + gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event); + gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_fd_sink_query); + + g_object_class_install_property (gobject_class, ARG_FD, + g_param_spec_int ("fd", "fd", "An open file descriptor to write to", + 0, G_MAXINT, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_fd_sink_init (GstFdSink * fdsink) +{ + fdsink->fd = 1; + fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd); + fdsink->bytes_written = 0; + fdsink->current_pos = 0; + + gst_base_sink_set_sync (GST_BASE_SINK (fdsink), FALSE); +} + +static void +gst_fd_sink_dispose (GObject * obj) +{ + GstFdSink *fdsink = GST_FD_SINK (obj); + + g_free (fdsink->uri); + fdsink->uri = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +static gboolean +gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + gboolean res = FALSE; + GstFdSink *fdsink; + + fdsink = GST_FD_SINK (bsink); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + 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, fdsink->current_pos); + res = TRUE; + break; + default: + break; + } + break; + } + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + res = TRUE; + break; + case GST_QUERY_URI: + gst_query_set_uri (query, fdsink->uri); + res = TRUE; + break; + case GST_QUERY_SEEKING:{ + GstFormat format; + + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) { + gst_query_set_seeking (query, GST_FORMAT_BYTES, fdsink->seekable, 0, + -1); + } else { + gst_query_set_seeking (query, format, FALSE, 0, -1); + } + res = TRUE; + break; + } + default: + res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + + } + return res; +} + +static GstFlowReturn +gst_fd_sink_render_buffers (GstFdSink * sink, GstBuffer ** buffers, + guint num_buffers, guint8 * mem_nums, guint total_mems) +{ + GstFlowReturn ret; + guint64 skip = 0; + + for (;;) { + guint64 bytes_written = 0; + + ret = gst_writev_buffers (GST_OBJECT_CAST (sink), sink->fd, sink->fdset, + buffers, num_buffers, mem_nums, total_mems, &bytes_written, skip); + + sink->bytes_written += bytes_written; + sink->current_pos += bytes_written; + skip += bytes_written; + + if (!sink->unlock) + break; + + ret = gst_base_sink_wait_preroll (GST_BASE_SINK (sink)); + if (ret != GST_FLOW_OK) + return ret; + } + + return ret; +} + +static GstFlowReturn +gst_fd_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list) +{ + GstFlowReturn flow; + GstBuffer **buffers; + GstFdSink *sink; + guint8 *mem_nums; + guint total_mems; + guint i, num_buffers; + + sink = GST_FD_SINK_CAST (bsink); + + num_buffers = gst_buffer_list_length (buffer_list); + if (num_buffers == 0) + goto no_data; + + /* extract buffers from list and count memories */ + buffers = g_newa (GstBuffer *, num_buffers); + mem_nums = g_newa (guint8, num_buffers); + for (i = 0, total_mems = 0; i < num_buffers; ++i) { + buffers[i] = gst_buffer_list_get (buffer_list, i); + mem_nums[i] = gst_buffer_n_memory (buffers[i]); + total_mems += mem_nums[i]; + } + + flow = + gst_fd_sink_render_buffers (sink, buffers, num_buffers, mem_nums, + total_mems); + + return flow; + +no_data: + { + GST_LOG_OBJECT (sink, "empty buffer list"); + return GST_FLOW_OK; + } +} + +static GstFlowReturn +gst_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer) +{ + GstFlowReturn flow; + GstFdSink *sink; + guint8 n_mem; + + sink = GST_FD_SINK_CAST (bsink); + + n_mem = gst_buffer_n_memory (buffer); + + if (n_mem > 0) + flow = gst_fd_sink_render_buffers (sink, &buffer, 1, &n_mem, n_mem); + else + flow = GST_FLOW_OK; + + return flow; +} + +static gboolean +gst_fd_sink_check_fd (GstFdSink * fdsink, int fd, GError ** error) +{ + struct stat stat_results; + off_t result; + + /* see that it is a valid file descriptor */ + if (fstat (fd, &stat_results) < 0) + goto invalid; + + if (!S_ISREG (stat_results.st_mode)) + goto not_seekable; + + /* see if it is a seekable stream */ + result = lseek (fd, 0, SEEK_CUR); + if (result == -1) { + switch (errno) { + case EINVAL: + case EBADF: + goto invalid; + + case ESPIPE: + goto not_seekable; + } + } else + GST_DEBUG_OBJECT (fdsink, "File descriptor %d is seekable", fd); + + return TRUE; + +invalid: + { + GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL), + ("File descriptor %d is not valid: %s", fd, g_strerror (errno))); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE, + "File descriptor %d is not valid: %s", fd, g_strerror (errno)); + return FALSE; + } +not_seekable: + { + GST_DEBUG_OBJECT (fdsink, "File descriptor %d is a pipe", fd); + return TRUE; + } +} + +static gboolean +gst_fd_sink_start (GstBaseSink * basesink) +{ + GstFdSink *fdsink; + GstPollFD fd = GST_POLL_FD_INIT; + + fdsink = GST_FD_SINK (basesink); + if (!gst_fd_sink_check_fd (fdsink, fdsink->fd, NULL)) + return FALSE; + + if ((fdsink->fdset = gst_poll_new (TRUE)) == NULL) + goto socket_pair; + + fd.fd = fdsink->fd; + gst_poll_add_fd (fdsink->fdset, &fd); + gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE); + + fdsink->bytes_written = 0; + fdsink->current_pos = 0; + + fdsink->seekable = gst_fd_sink_do_seek (fdsink, 0); + GST_INFO_OBJECT (fdsink, "seeking supported: %d", fdsink->seekable); + + return TRUE; + + /* ERRORS */ +socket_pair: + { + GST_ELEMENT_ERROR (fdsink, RESOURCE, OPEN_READ_WRITE, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } +} + +static gboolean +gst_fd_sink_stop (GstBaseSink * basesink) +{ + GstFdSink *fdsink = GST_FD_SINK (basesink); + + if (fdsink->fdset) { + gst_poll_free (fdsink->fdset); + fdsink->fdset = NULL; + } + + return TRUE; +} + +static gboolean +gst_fd_sink_unlock (GstBaseSink * basesink) +{ + GstFdSink *fdsink = GST_FD_SINK (basesink); + + GST_LOG_OBJECT (fdsink, "Flushing"); + GST_OBJECT_LOCK (fdsink); + fdsink->unlock = TRUE; + gst_poll_set_flushing (fdsink->fdset, TRUE); + GST_OBJECT_UNLOCK (fdsink); + + return TRUE; +} + +static gboolean +gst_fd_sink_unlock_stop (GstBaseSink * basesink) +{ + GstFdSink *fdsink = GST_FD_SINK (basesink); + + GST_LOG_OBJECT (fdsink, "No longer flushing"); + GST_OBJECT_LOCK (fdsink); + fdsink->unlock = FALSE; + gst_poll_set_flushing (fdsink->fdset, FALSE); + GST_OBJECT_UNLOCK (fdsink); + + return TRUE; +} + +static gboolean +gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd, GError ** error) +{ + if (new_fd < 0) { + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE, + "File descriptor %d is not valid", new_fd); + return FALSE; + } + + if (!gst_fd_sink_check_fd (fdsink, new_fd, error)) + goto invalid; + + /* assign the fd */ + GST_OBJECT_LOCK (fdsink); + if (fdsink->fdset) { + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = fdsink->fd; + gst_poll_remove_fd (fdsink->fdset, &fd); + + fd.fd = new_fd; + gst_poll_add_fd (fdsink->fdset, &fd); + gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE); + } + fdsink->fd = new_fd; + g_free (fdsink->uri); + fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd); + + GST_OBJECT_UNLOCK (fdsink); + + return TRUE; + +invalid: + { + return FALSE; + } +} + +static void +gst_fd_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFdSink *fdsink; + + fdsink = GST_FD_SINK (object); + + switch (prop_id) { + case ARG_FD:{ + int fd; + + fd = g_value_get_int (value); + gst_fd_sink_update_fd (fdsink, fd, NULL); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fd_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFdSink *fdsink; + + fdsink = GST_FD_SINK (object); + + switch (prop_id) { + case ARG_FD: + g_value_set_int (value, fdsink->fd); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset) +{ + off_t result; + + result = lseek (fdsink->fd, new_offset, SEEK_SET); + + if (result == -1) + goto seek_failed; + + fdsink->current_pos = new_offset; + + GST_DEBUG_OBJECT (fdsink, "File descriptor %d to seek to position " + "%" G_GUINT64_FORMAT, fdsink->fd, fdsink->current_pos); + + return TRUE; + + /* ERRORS */ +seek_failed: + { + GST_DEBUG_OBJECT (fdsink, "File descriptor %d failed to seek to position " + "%" G_GUINT64_FORMAT, fdsink->fd, new_offset); + return FALSE; + } +} + +static gboolean +gst_fd_sink_event (GstBaseSink * sink, GstEvent * event) +{ + GstEventType type; + GstFdSink *fdsink; + + fdsink = GST_FD_SINK (sink); + + type = GST_EVENT_TYPE (event); + + switch (type) { + case GST_EVENT_SEGMENT: + { + const GstSegment *segment; + + gst_event_parse_segment (event, &segment); + + if (segment->format == GST_FORMAT_BYTES) { + /* only try to seek and fail when we are going to a different + * position */ + if (fdsink->current_pos != segment->start) { + /* FIXME, the seek should be performed on the pos field, start/stop are + * just boundaries for valid bytes offsets. We should also fill the file + * with zeroes if the new position extends the current EOF (sparse streams + * and segment accumulation). */ + if (!gst_fd_sink_do_seek (fdsink, (guint64) segment->start)) + goto seek_failed; + } + } else { + GST_DEBUG_OBJECT (fdsink, + "Ignored SEGMENT event of format %u (%s)", (guint) segment->format, + gst_format_get_name (segment->format)); + } + break; + } + default: + break; + } + + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); + +seek_failed: + { + GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL), + ("Error while seeking on file descriptor %d: %s", + fdsink->fd, g_strerror (errno))); + gst_event_unref (event); + return FALSE; + } + +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_fd_sink_uri_get_type (GType type) +{ + return GST_URI_SINK; +} + +static const gchar *const * +gst_fd_sink_uri_get_protocols (GType type) +{ + static const gchar *protocols[] = { "fd", NULL }; + + return protocols; +} + +static gchar * +gst_fd_sink_uri_get_uri (GstURIHandler * handler) +{ + GstFdSink *sink = GST_FD_SINK (handler); + + /* FIXME: make thread-safe */ + return g_strdup (sink->uri); +} + +static gboolean +gst_fd_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) +{ + GstFdSink *sink = GST_FD_SINK (handler); + gint fd; + + if (sscanf (uri, "fd://%d", &fd) != 1) { + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File descriptor URI could not be parsed"); + return FALSE; + } + + return gst_fd_sink_update_fd (sink, fd, error); +} + +static void +gst_fd_sink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_fd_sink_uri_get_type; + iface->get_protocols = gst_fd_sink_uri_get_protocols; + iface->get_uri = gst_fd_sink_uri_get_uri; + iface->set_uri = gst_fd_sink_uri_set_uri; +} diff --git a/plugins/elements/gstfdsink.h b/plugins/elements/gstfdsink.h new file mode 100644 index 0000000..c038ce0 --- /dev/null +++ b/plugins/elements/gstfdsink.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfdsink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FD_SINK_H__ +#define __GST_FD_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_FD_SINK \ + (gst_fd_sink_get_type()) +#define GST_FD_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FD_SINK,GstFdSink)) +#define GST_FD_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FD_SINK,GstFdSinkClass)) +#define GST_IS_FD_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FD_SINK)) +#define GST_IS_FD_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FD_SINK)) +#define GST_FD_SINK_CAST(obj) ((GstFdSink *)(obj)) + +typedef struct _GstFdSink GstFdSink; +typedef struct _GstFdSinkClass GstFdSinkClass; + +/** + * GstFdSink: + * + * The opaque #GstFdSink data structure. + */ +struct _GstFdSink { + GstBaseSink parent; + + gchar *uri; + + GstPoll *fdset; + + int fd; + guint64 bytes_written; + guint64 current_pos; + + gboolean seekable; + gboolean unlock; /* OBJECT LOCK */ +}; + +struct _GstFdSinkClass { + GstBaseSinkClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_fd_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_FD_SINK_H__ */ diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c new file mode 100644 index 0000000..6d61efe --- /dev/null +++ b/plugins/elements/gstfdsrc.c @@ -0,0 +1,689 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Philippe Khalaf + * + * gstfdsrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-fdsrc + * @title: fdsrc + * @see_also: #GstFdSink + * + * Read data from a unix file descriptor. + * + * To generate data, enter some data on the console followed by enter. + * The above mentioned pipeline should dump data packets to the console. + * + * If the #GstFdSrc:timeout property is set to a value bigger than 0, fdsrc will + * generate an element message named "GstFdSrcTimeout" + * if no data was received in the given timeout. + * + * The message's structure contains one field: + * + * * #guint64 `timeout`: the timeout in microseconds that + * expired when waiting for data. + * + * ## Example launch line + * |[ + * echo "Hello GStreamer" | gst-launch-1.0 -v fdsrc ! fakesink dump=true + * ]| A simple pipeline to read from the standard input and dump the data + * with a fakesink as hex ascii block. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "gst/gst_private.h" + +#include + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#endif + +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _MSC_VER +#undef stat +#define stat _stat +#define fstat _fstat +#define S_ISREG(m) (((m)&S_IFREG)==S_IFREG) +#endif +#include +#include + +#include "gstfdsrc.h" + +#ifdef __BIONIC__ /* Android */ +#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 +#undef fstat +#define fstat fstat64 +#endif +#endif + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_fd_src_debug); +#define GST_CAT_DEFAULT gst_fd_src_debug + +#define DEFAULT_FD 0 +#define DEFAULT_TIMEOUT 0 + +enum +{ + PROP_0, + + PROP_FD, + PROP_TIMEOUT, + + PROP_LAST +}; + +static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data); + +#define _do_init \ + G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_fd_src_uri_handler_init); \ + GST_DEBUG_CATEGORY_INIT (gst_fd_src_debug, "fdsrc", 0, "fdsrc element"); +#define gst_fd_src_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFdSrc, gst_fd_src, GST_TYPE_PUSH_SRC, _do_init); + +static void gst_fd_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_fd_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_fd_src_dispose (GObject * obj); + +static gboolean gst_fd_src_start (GstBaseSrc * bsrc); +static gboolean gst_fd_src_stop (GstBaseSrc * bsrc); +static gboolean gst_fd_src_unlock (GstBaseSrc * bsrc); +static gboolean gst_fd_src_unlock_stop (GstBaseSrc * bsrc); +static gboolean gst_fd_src_is_seekable (GstBaseSrc * bsrc); +static gboolean gst_fd_src_get_size (GstBaseSrc * src, guint64 * size); +static gboolean gst_fd_src_do_seek (GstBaseSrc * src, GstSegment * segment); +static gboolean gst_fd_src_query (GstBaseSrc * src, GstQuery * query); + +static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf); + +static void +gst_fd_src_class_init (GstFdSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpush_src_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + gstpush_src_class = GST_PUSH_SRC_CLASS (klass); + + gobject_class->set_property = gst_fd_src_set_property; + gobject_class->get_property = gst_fd_src_get_property; + gobject_class->dispose = gst_fd_src_dispose; + + g_object_class_install_property (gobject_class, PROP_FD, + g_param_spec_int ("fd", "fd", "An open file descriptor to read from", + 0, G_MAXINT, DEFAULT_FD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstFdSrc:timeout + * + * Post a message after timeout microseconds + */ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT, + g_param_spec_uint64 ("timeout", "Timeout", + "Post a message after timeout microseconds (0 = disabled)", 0, + G_MAXUINT64, DEFAULT_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, + "Filedescriptor Source", + "Source/File", + "Read from a file descriptor", "Erik Walthinsen "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop); + gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_src_unlock); + gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_src_unlock_stop); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fd_src_is_seekable); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fd_src_get_size); + gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_fd_src_do_seek); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_fd_src_query); + + gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fd_src_create); +} + +static void +gst_fd_src_init (GstFdSrc * fdsrc) +{ + fdsrc->new_fd = DEFAULT_FD; + fdsrc->seekable_fd = FALSE; + fdsrc->fd = -1; + fdsrc->size = -1; + fdsrc->timeout = DEFAULT_TIMEOUT; + fdsrc->uri = g_strdup_printf ("fd://0"); + fdsrc->curoffset = 0; +} + +static void +gst_fd_src_dispose (GObject * obj) +{ + GstFdSrc *src = GST_FD_SRC (obj); + + g_free (src->uri); + src->uri = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +static void +gst_fd_src_update_fd (GstFdSrc * src, guint64 size) +{ + struct stat stat_results; + + GST_DEBUG_OBJECT (src, "fdset %p, old_fd %d, new_fd %d", src->fdset, src->fd, + src->new_fd); + + /* we need to always update the fdset since it may not have existed when + * gst_fd_src_update_fd () was called earlier */ + if (src->fdset != NULL) { + GstPollFD fd = GST_POLL_FD_INIT; + + if (src->fd >= 0) { + fd.fd = src->fd; + /* this will log a harmless warning, if it was never added */ + gst_poll_remove_fd (src->fdset, &fd); + } + + fd.fd = src->new_fd; + gst_poll_add_fd (src->fdset, &fd); + gst_poll_fd_ctl_read (src->fdset, &fd, TRUE); + } + + + if (src->fd != src->new_fd) { + GST_INFO_OBJECT (src, "Updating to fd %d", src->new_fd); + + src->fd = src->new_fd; + + GST_INFO_OBJECT (src, "Setting size to fd %" G_GUINT64_FORMAT, size); + src->size = size; + + g_free (src->uri); + src->uri = g_strdup_printf ("fd://%d", src->fd); + + if (fstat (src->fd, &stat_results) < 0) + goto not_seekable; + + if (!S_ISREG (stat_results.st_mode)) + goto not_seekable; + + /* Try a seek of 0 bytes offset to check for seekability */ + if (lseek (src->fd, 0, SEEK_CUR) < 0) + goto not_seekable; + + GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd); + src->seekable_fd = TRUE; + + gst_base_src_set_dynamic_size (GST_BASE_SRC (src), TRUE); + } + return; + +not_seekable: + { + GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd); + src->seekable_fd = FALSE; + gst_base_src_set_dynamic_size (GST_BASE_SRC (src), FALSE); + } +} + +static gboolean +gst_fd_src_start (GstBaseSrc * bsrc) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + + src->curoffset = 0; + + if ((src->fdset = gst_poll_new (TRUE)) == NULL) + goto socket_pair; + + gst_fd_src_update_fd (src, -1); + + return TRUE; + + /* ERRORS */ +socket_pair: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } +} + +static gboolean +gst_fd_src_stop (GstBaseSrc * bsrc) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + + if (src->fdset) { + gst_poll_free (src->fdset); + src->fdset = NULL; + } + + return TRUE; +} + +static gboolean +gst_fd_src_unlock (GstBaseSrc * bsrc) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + + GST_LOG_OBJECT (src, "Flushing"); + GST_OBJECT_LOCK (src); + gst_poll_set_flushing (src->fdset, TRUE); + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +static gboolean +gst_fd_src_unlock_stop (GstBaseSrc * bsrc) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + + GST_LOG_OBJECT (src, "No longer flushing"); + GST_OBJECT_LOCK (src); + gst_poll_set_flushing (src->fdset, FALSE); + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +static void +gst_fd_src_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstFdSrc *src = GST_FD_SRC (object); + + switch (prop_id) { + case PROP_FD: + src->new_fd = g_value_get_int (value); + + /* If state is ready or below, update the current fd immediately + * so it is reflected in get_properties and uri */ + GST_OBJECT_LOCK (object); + if (GST_STATE (GST_ELEMENT (src)) <= GST_STATE_READY) { + GST_DEBUG_OBJECT (src, "state ready or lower, updating to use new fd"); + gst_fd_src_update_fd (src, -1); + } else { + GST_DEBUG_OBJECT (src, "state above ready, not updating to new fd yet"); + } + GST_OBJECT_UNLOCK (object); + break; + case PROP_TIMEOUT: + src->timeout = g_value_get_uint64 (value); + GST_DEBUG_OBJECT (src, "poll timeout set to %" GST_TIME_FORMAT, + GST_TIME_ARGS (src->timeout)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_fd_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFdSrc *src = GST_FD_SRC (object); + + switch (prop_id) { + case PROP_FD: + g_value_set_int (value, src->fd); + break; + case PROP_TIMEOUT: + g_value_set_uint64 (value, src->timeout); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) +{ + GstFdSrc *src; + GstBuffer *buf; + gssize readbytes; + guint blocksize; + GstMapInfo info; + +#ifndef HAVE_WIN32 + GstClockTime timeout; + gboolean try_again; + gint retval; +#endif + + src = GST_FD_SRC (psrc); + +#ifndef HAVE_WIN32 + if (src->timeout > 0) { + timeout = src->timeout * GST_USECOND; + } else { + timeout = GST_CLOCK_TIME_NONE; + } + + do { + try_again = FALSE; + + GST_LOG_OBJECT (src, "doing poll, timeout %" GST_TIME_FORMAT, + GST_TIME_ARGS (src->timeout)); + + retval = gst_poll_wait (src->fdset, timeout); + GST_LOG_OBJECT (src, "poll returned %d", retval); + + if (G_UNLIKELY (retval == -1)) { + if (errno == EINTR || errno == EAGAIN) { + /* retry if interrupted */ + try_again = TRUE; + } else if (errno == EBUSY) { + goto stopped; + } else { + goto poll_error; + } + } else if (G_UNLIKELY (retval == 0)) { + try_again = TRUE; + /* timeout, post element message */ + gst_element_post_message (GST_ELEMENT_CAST (src), + gst_message_new_element (GST_OBJECT_CAST (src), + gst_structure_new ("GstFdSrcTimeout", + "timeout", G_TYPE_UINT64, src->timeout, NULL))); + } + } while (G_UNLIKELY (try_again)); /* retry if interrupted or timeout */ +#endif + + blocksize = GST_BASE_SRC (src)->blocksize; + + /* create the buffer */ + buf = gst_buffer_new_allocate (NULL, blocksize, NULL); + if (G_UNLIKELY (buf == NULL)) + goto alloc_failed; + + if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) + goto buffer_read_error; + + do { + readbytes = read (src->fd, info.data, blocksize); + GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes); + } while (readbytes == -1 && errno == EINTR); /* retry if interrupted */ + + if (readbytes < 0) + goto read_error; + + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, readbytes); + + if (readbytes == 0) + goto eos; + + GST_BUFFER_OFFSET (buf) = src->curoffset; + GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; + src->curoffset += readbytes; + + GST_LOG_OBJECT (psrc, "Read buffer of size %" G_GSSIZE_FORMAT, readbytes); + + /* we're done, return the buffer */ + *outbuf = buf; + + return GST_FLOW_OK; + + /* ERRORS */ +#ifndef HAVE_WIN32 +poll_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("poll on file descriptor: %s.", g_strerror (errno))); + GST_DEBUG_OBJECT (psrc, "Error during poll"); + return GST_FLOW_ERROR; + } +stopped: + { + GST_DEBUG_OBJECT (psrc, "Poll stopped"); + return GST_FLOW_FLUSHING; + } +#endif +alloc_failed: + { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize); + return GST_FLOW_ERROR; + } +eos: + { + GST_DEBUG_OBJECT (psrc, "Read 0 bytes. EOS."); + gst_buffer_unref (buf); + return GST_FLOW_EOS; + } +read_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("read on file descriptor: %s.", g_strerror (errno))); + GST_DEBUG_OBJECT (psrc, "Error reading from fd"); + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +buffer_read_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Can't write to buffer")); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_fd_src_query (GstBaseSrc * basesrc, GstQuery * query) +{ + gboolean ret = FALSE; + GstFdSrc *src = GST_FD_SRC (basesrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_URI: + gst_query_set_uri (query, src->uri); + ret = TRUE; + break; + default: + ret = FALSE; + break; + } + + if (!ret) + ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + + return ret; +} + +static gboolean +gst_fd_src_is_seekable (GstBaseSrc * bsrc) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + + return src->seekable_fd; +} + +static gboolean +gst_fd_src_get_size (GstBaseSrc * bsrc, guint64 * size) +{ + GstFdSrc *src = GST_FD_SRC (bsrc); + struct stat stat_results; + + if (src->size != -1) { + *size = src->size; + return TRUE; + } + + if (!src->seekable_fd) { + /* If it isn't seekable, we won't know the length (but fstat will still + * succeed, and wrongly say our length is zero. */ + return FALSE; + } + + if (fstat (src->fd, &stat_results) < 0) + goto could_not_stat; + + *size = stat_results.st_size; + + return TRUE; + + /* ERROR */ +could_not_stat: + { + return FALSE; + } +} + +static gboolean +gst_fd_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) +{ + gint res; + gint64 offset; + GstFdSrc *src = GST_FD_SRC (bsrc); + + offset = segment->start; + + /* No need to seek to the current position */ + if (offset == src->curoffset) + return TRUE; + + res = lseek (src->fd, offset, SEEK_SET); + if (G_UNLIKELY (res < 0 || res != offset)) + goto seek_failed; + + segment->position = segment->start; + segment->time = segment->start; + + return TRUE; + +seek_failed: + GST_DEBUG_OBJECT (src, "lseek returned %" G_GINT64_FORMAT, offset); + return FALSE; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_fd_src_uri_get_type (GType type) +{ + return GST_URI_SRC; +} + +static const gchar *const * +gst_fd_src_uri_get_protocols (GType type) +{ + static const gchar *protocols[] = { "fd", NULL }; + + return protocols; +} + +static gchar * +gst_fd_src_uri_get_uri (GstURIHandler * handler) +{ + GstFdSrc *src = GST_FD_SRC (handler); + + /* FIXME: make thread-safe */ + return g_strdup (src->uri); +} + +static gboolean +gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** err) +{ + gchar *protocol, *q; + GstFdSrc *src = GST_FD_SRC (handler); + gint fd; + guint64 size = (guint64) - 1; + + GST_INFO_OBJECT (src, "checking uri %s", uri); + + protocol = gst_uri_get_protocol (uri); + if (strcmp (protocol, "fd") != 0) { + g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "Wrong protocol for fdsrc in uri: '%s'", uri); + g_free (protocol); + return FALSE; + } + g_free (protocol); + + if (sscanf (uri, "fd://%d", &fd) != 1 || fd < 0) { + g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "Bad file descriptor number in uri: '%s'", uri); + return FALSE; + } + + if ((q = g_strstr_len (uri, -1, "?"))) { + gchar *sp, *end = NULL; + + GST_INFO_OBJECT (src, "found ?"); + + if ((sp = g_strstr_len (q, -1, "size="))) { + sp += strlen ("size="); + size = g_ascii_strtoull (sp, &end, 10); + if ((size == 0 && errno == EINVAL) || size == G_MAXUINT64 || end == sp) { + GST_INFO_OBJECT (src, "parsing size failed"); + size = -1; + } else { + GST_INFO_OBJECT (src, "found size %" G_GUINT64_FORMAT, size); + } + } + } + + src->new_fd = fd; + + GST_OBJECT_LOCK (src); + if (GST_STATE (GST_ELEMENT (src)) <= GST_STATE_READY) { + gst_fd_src_update_fd (src, size); + } + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +static void +gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_fd_src_uri_get_type; + iface->get_protocols = gst_fd_src_uri_get_protocols; + iface->get_uri = gst_fd_src_uri_get_uri; + iface->set_uri = gst_fd_src_uri_set_uri; +} diff --git a/plugins/elements/gstfdsrc.h b/plugins/elements/gstfdsrc.h new file mode 100644 index 0000000..bafae48 --- /dev/null +++ b/plugins/elements/gstfdsrc.h @@ -0,0 +1,87 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Philippe Khalaf + * + * gstfdsrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FD_SRC_H__ +#define __GST_FD_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_FD_SRC \ + (gst_fd_src_get_type()) +#define GST_FD_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FD_SRC,GstFdSrc)) +#define GST_FD_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FD_SRC,GstFdSrcClass)) +#define GST_IS_FD_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FD_SRC)) +#define GST_IS_FD_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FD_SRC)) + + +typedef struct _GstFdSrc GstFdSrc; +typedef struct _GstFdSrcClass GstFdSrcClass; + +/** + * GstFdSrc: + * + * Opaque #GstFdSrc data structure. + */ +struct _GstFdSrc { + GstPushSrc element; + + /*< private >*/ + /* new_fd is copied to fd on READY->PAUSED */ + gint new_fd; + + /* fd and flag indicating whether fd is seekable */ + gint fd; + gboolean seekable_fd; + guint64 size; + + /* poll timeout */ + guint64 timeout; + + gchar *uri; + + GstPoll *fdset; + + gulong curoffset; /* current offset in file */ +}; + +struct _GstFdSrcClass { + GstPushSrcClass parent_class; + + /* signals */ + void (*timeout) (GstElement *element); +}; + +G_GNUC_INTERNAL GType gst_fd_src_get_type(void); + +G_END_DECLS + +#endif /* __GST_FD_SRC_H__ */ diff --git a/plugins/elements/gstfilesink.c b/plugins/elements/gstfilesink.c new file mode 100644 index 0000000..58ae8d1 --- /dev/null +++ b/plugins/elements/gstfilesink.c @@ -0,0 +1,835 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2006 Wim Taymans + * + * gstfilesink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-filesink + * @title: filesink + * @see_also: #GstFileSrc + * + * Write incoming data to a file in the local file system. + * + * ## Example launch line + * |[ + * gst-launch-1.0 v4l2src num-buffers=1 ! jpegenc ! filesink location=capture1.jpeg + * ]| Capture one frame from a v4l2 camera and save as jpeg image. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../../gst/gst-i18n-lib.h" + +#include +#include /* for fseeko() */ +#ifdef HAVE_STDIO_EXT_H +#include /* for __fbufsize, for debugging */ +#endif +#include +#include "gstfilesink.h" +#include +#include + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#undef off_t +#define off_t guint64 +#undef ftruncate +#define ftruncate _chsize +#undef fsync +#define fsync _commit +#ifdef _MSC_VER /* Check if we are using MSVC, fileno is deprecated in favour */ +#define fileno _fileno /* of _fileno */ +#endif +#endif + +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "gstelements_private.h" +#include "gstfilesink.h" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#define GST_TYPE_FILE_SINK_BUFFER_MODE (gst_file_sink_buffer_mode_get_type ()) +static GType +gst_file_sink_buffer_mode_get_type (void) +{ + static GType buffer_mode_type = 0; + static const GEnumValue buffer_mode[] = { + {GST_FILE_SINK_BUFFER_MODE_DEFAULT, "Default buffering", "default"}, + {GST_FILE_SINK_BUFFER_MODE_FULL, "Fully buffered", "full"}, + {GST_FILE_SINK_BUFFER_MODE_LINE, "Line buffered", "line"}, + {GST_FILE_SINK_BUFFER_MODE_UNBUFFERED, "Unbuffered", "unbuffered"}, + {0, NULL, NULL}, + }; + + if (!buffer_mode_type) { + buffer_mode_type = + g_enum_register_static ("GstFileSinkBufferMode", buffer_mode); + } + return buffer_mode_type; +} + +GST_DEBUG_CATEGORY_STATIC (gst_file_sink_debug); +#define GST_CAT_DEFAULT gst_file_sink_debug + +#define DEFAULT_LOCATION NULL +#define DEFAULT_BUFFER_MODE GST_FILE_SINK_BUFFER_MODE_DEFAULT +#define DEFAULT_BUFFER_SIZE 64 * 1024 +#define DEFAULT_APPEND FALSE + +enum +{ + PROP_0, + PROP_LOCATION, + PROP_BUFFER_MODE, + PROP_BUFFER_SIZE, + PROP_APPEND, + PROP_LAST +}; + +/* Copy of glib's g_fopen due to win32 libc/cross-DLL brokenness: we can't + * use the 'file pointer' opened in glib (and returned from this function) + * in this library, as they may have unrelated C runtimes. */ +static FILE * +gst_fopen (const gchar * filename, const gchar * mode) +{ +#ifdef G_OS_WIN32 + wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); + wchar_t *wmode; + FILE *retval; + int save_errno; + + if (wfilename == NULL) { + errno = EINVAL; + return NULL; + } + + wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL); + + if (wmode == NULL) { + g_free (wfilename); + errno = EINVAL; + return NULL; + } + + retval = _wfopen (wfilename, wmode); + save_errno = errno; + + g_free (wfilename); + g_free (wmode); + + errno = save_errno; + return retval; +#else + return fopen (filename, mode); +#endif +} + +static void gst_file_sink_dispose (GObject * object); + +static void gst_file_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_file_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_file_sink_open_file (GstFileSink * sink); +static void gst_file_sink_close_file (GstFileSink * sink); + +static gboolean gst_file_sink_start (GstBaseSink * sink); +static gboolean gst_file_sink_stop (GstBaseSink * sink); +static gboolean gst_file_sink_event (GstBaseSink * sink, GstEvent * event); +static GstFlowReturn gst_file_sink_render (GstBaseSink * sink, + GstBuffer * buffer); +static GstFlowReturn gst_file_sink_render_list (GstBaseSink * sink, + GstBufferList * list); + +static gboolean gst_file_sink_do_seek (GstFileSink * filesink, + guint64 new_offset); +static gboolean gst_file_sink_get_current_offset (GstFileSink * filesink, + guint64 * p_pos); + +static gboolean gst_file_sink_query (GstBaseSink * bsink, GstQuery * query); + +static void gst_file_sink_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +#define _do_init \ + G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_file_sink_uri_handler_init); \ + GST_DEBUG_CATEGORY_INIT (gst_file_sink_debug, "filesink", 0, "filesink element"); +#define gst_file_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFileSink, gst_file_sink, GST_TYPE_BASE_SINK, + _do_init); + +static void +gst_file_sink_class_init (GstFileSinkClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass); + + gobject_class->dispose = gst_file_sink_dispose; + + gobject_class->set_property = gst_file_sink_set_property; + gobject_class->get_property = gst_file_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "File Location", + "Location of the file to write", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFER_MODE, + g_param_spec_enum ("buffer-mode", "Buffering mode", + "The buffering mode to use", GST_TYPE_FILE_SINK_BUFFER_MODE, + DEFAULT_BUFFER_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, + g_param_spec_uint ("buffer-size", "Buffering size", + "Size of buffer in number of bytes for line or full buffer-mode", 0, + G_MAXUINT, DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstFileSink:append + * + * Append to an already existing file. + */ + g_object_class_install_property (gobject_class, PROP_APPEND, + g_param_spec_boolean ("append", "Append", + "Append to an already existing file", DEFAULT_APPEND, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, + "File Sink", + "Sink/File", "Write stream to a file", + "Thomas Vander Stichele "); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_file_sink_start); + gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_file_sink_stop); + gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_file_sink_query); + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_file_sink_render); + gstbasesink_class->render_list = + GST_DEBUG_FUNCPTR (gst_file_sink_render_list); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_file_sink_event); + + if (sizeof (off_t) < 8) { + GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!", + sizeof (off_t)); + } +} + +static void +gst_file_sink_init (GstFileSink * filesink) +{ + filesink->filename = NULL; + filesink->file = NULL; + filesink->current_pos = 0; + filesink->buffer_mode = DEFAULT_BUFFER_MODE; + filesink->buffer_size = DEFAULT_BUFFER_SIZE; + filesink->buffer = NULL; + filesink->append = FALSE; + + gst_base_sink_set_sync (GST_BASE_SINK (filesink), FALSE); +} + +static void +gst_file_sink_dispose (GObject * object) +{ + GstFileSink *sink = GST_FILE_SINK (object); + + G_OBJECT_CLASS (parent_class)->dispose (object); + + g_free (sink->uri); + sink->uri = NULL; + g_free (sink->filename); + sink->filename = NULL; + g_free (sink->buffer); + sink->buffer = NULL; + sink->buffer_size = 0; +} + +static gboolean +gst_file_sink_set_location (GstFileSink * sink, const gchar * location, + GError ** error) +{ + if (sink->file) + goto was_open; + + g_free (sink->filename); + g_free (sink->uri); + if (location != NULL) { + /* we store the filename as we received it from the application. On Windows + * this should be in UTF8 */ + sink->filename = g_strdup (location); + sink->uri = gst_filename_to_uri (location, NULL); + GST_INFO_OBJECT (sink, "filename : %s", sink->filename); + GST_INFO_OBJECT (sink, "uri : %s", sink->uri); + } else { + sink->filename = NULL; + sink->uri = NULL; + } + + return TRUE; + + /* ERRORS */ +was_open: + { + g_warning ("Changing the `location' property on filesink when a file is " + "open is not supported."); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE, + "Changing the 'location' property on filesink when a file is " + "open is not supported"); + return FALSE; + } +} + +static void +gst_file_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFileSink *sink = GST_FILE_SINK (object); + + switch (prop_id) { + case PROP_LOCATION: + gst_file_sink_set_location (sink, g_value_get_string (value), NULL); + break; + case PROP_BUFFER_MODE: + sink->buffer_mode = g_value_get_enum (value); + break; + case PROP_BUFFER_SIZE: + sink->buffer_size = g_value_get_uint (value); + break; + case PROP_APPEND: + sink->append = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_file_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFileSink *sink = GST_FILE_SINK (object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_string (value, sink->filename); + break; + case PROP_BUFFER_MODE: + g_value_set_enum (value, sink->buffer_mode); + break; + case PROP_BUFFER_SIZE: + g_value_set_uint (value, sink->buffer_size); + break; + case PROP_APPEND: + g_value_set_boolean (value, sink->append); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_file_sink_open_file (GstFileSink * sink) +{ + gint mode; + + /* open the file */ + if (sink->filename == NULL || sink->filename[0] == '\0') + goto no_filename; + + if (sink->append) + sink->file = gst_fopen (sink->filename, "ab"); + else + sink->file = gst_fopen (sink->filename, "wb"); + if (sink->file == NULL) + goto open_failed; + + /* see if we are asked to perform a specific kind of buffering */ + if ((mode = sink->buffer_mode) != -1) { + guint buffer_size; + + /* free previous buffer if any */ + g_free (sink->buffer); + + if (mode == _IONBF) { + /* no buffering */ + sink->buffer = NULL; + buffer_size = 0; + } else { + /* allocate buffer */ + sink->buffer = g_malloc (sink->buffer_size); + buffer_size = sink->buffer_size; + } + /* Cygwin does not have __fbufsize, android adds it in API 23 */ +#if defined(HAVE_STDIO_EXT_H) && (!defined(__CYGWIN__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 23)) + GST_DEBUG_OBJECT (sink, "change buffer size %u to %u, mode %d", + (guint) __fbufsize (sink->file), buffer_size, mode); +#else + GST_DEBUG_OBJECT (sink, "change buffer size to %u, mode %d", + sink->buffer_size, mode); +#endif + if (setvbuf (sink->file, sink->buffer, mode, buffer_size) != 0) { + GST_WARNING_OBJECT (sink, "warning: setvbuf failed: %s", + g_strerror (errno)); + } + } + + sink->current_pos = 0; + /* try to seek in the file to figure out if it is seekable */ + sink->seekable = gst_file_sink_do_seek (sink, 0); + + GST_DEBUG_OBJECT (sink, "opened file %s, seekable %d", + sink->filename, sink->seekable); + + return TRUE; + + /* ERRORS */ +no_filename: + { + GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, + (_("No file name specified for writing.")), (NULL)); + return FALSE; + } +open_failed: + { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + (_("Could not open file \"%s\" for writing."), sink->filename), + GST_ERROR_SYSTEM); + return FALSE; + } +} + +static void +gst_file_sink_close_file (GstFileSink * sink) +{ + if (sink->file) { + if (fclose (sink->file) != 0) + GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE, + (_("Error closing file \"%s\"."), sink->filename), GST_ERROR_SYSTEM); + + GST_DEBUG_OBJECT (sink, "closed file"); + sink->file = NULL; + + g_free (sink->buffer); + sink->buffer = NULL; + } +} + +static gboolean +gst_file_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + gboolean res; + GstFileSink *self; + GstFormat format; + + self = GST_FILE_SINK (bsink); + + 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, self->current_pos); + res = TRUE; + break; + default: + res = FALSE; + break; + } + break; + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + res = TRUE; + break; + + case GST_QUERY_URI: + gst_query_set_uri (query, self->uri); + res = TRUE; + break; + + case GST_QUERY_SEEKING: + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) { + gst_query_set_seeking (query, GST_FORMAT_BYTES, self->seekable, 0, -1); + } else { + gst_query_set_seeking (query, format, FALSE, 0, -1); + } + res = TRUE; + break; + + default: + res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + } + return res; +} + +#ifdef HAVE_FSEEKO +# define __GST_STDIO_SEEK_FUNCTION "fseeko" +#elif defined (G_OS_UNIX) || defined (G_OS_WIN32) +# define __GST_STDIO_SEEK_FUNCTION "lseek" +#else +# define __GST_STDIO_SEEK_FUNCTION "fseek" +#endif + +static gboolean +gst_file_sink_do_seek (GstFileSink * filesink, guint64 new_offset) +{ + GST_DEBUG_OBJECT (filesink, "Seeking to offset %" G_GUINT64_FORMAT + " using " __GST_STDIO_SEEK_FUNCTION, new_offset); + + if (fflush (filesink->file)) + goto flush_failed; + +#ifdef HAVE_FSEEKO + if (fseeko (filesink->file, (off_t) new_offset, SEEK_SET) != 0) + goto seek_failed; +#elif defined (G_OS_UNIX) || defined (G_OS_WIN32) + if (lseek (fileno (filesink->file), (off_t) new_offset, + SEEK_SET) == (off_t) - 1) + goto seek_failed; +#else + if (fseek (filesink->file, (long) new_offset, SEEK_SET) != 0) + goto seek_failed; +#endif + + /* adjust position reporting after seek; + * presumably this should basically yield new_offset */ + gst_file_sink_get_current_offset (filesink, &filesink->current_pos); + + return TRUE; + + /* ERRORS */ +flush_failed: + { + GST_DEBUG_OBJECT (filesink, "Flush failed: %s", g_strerror (errno)); + return FALSE; + } +seek_failed: + { + GST_DEBUG_OBJECT (filesink, "Seeking failed: %s", g_strerror (errno)); + return FALSE; + } +} + +/* handle events (search) */ +static gboolean +gst_file_sink_event (GstBaseSink * sink, GstEvent * event) +{ + GstEventType type; + GstFileSink *filesink; + + filesink = GST_FILE_SINK (sink); + + type = GST_EVENT_TYPE (event); + + switch (type) { + case GST_EVENT_SEGMENT: + { + const GstSegment *segment; + + gst_event_parse_segment (event, &segment); + + if (segment->format == GST_FORMAT_BYTES) { + /* only try to seek and fail when we are going to a different + * position */ + if (filesink->current_pos != segment->start) { + /* FIXME, the seek should be performed on the pos field, start/stop are + * just boundaries for valid bytes offsets. We should also fill the file + * with zeroes if the new position extends the current EOF (sparse streams + * and segment accumulation). */ + if (!gst_file_sink_do_seek (filesink, (guint64) segment->start)) + goto seek_failed; + } else { + GST_DEBUG_OBJECT (filesink, "Ignored SEGMENT, no seek needed"); + } + } else { + GST_DEBUG_OBJECT (filesink, + "Ignored SEGMENT event of format %u (%s)", (guint) segment->format, + gst_format_get_name (segment->format)); + } + break; + } + case GST_EVENT_FLUSH_STOP: + if (filesink->current_pos != 0 && filesink->seekable) { + gst_file_sink_do_seek (filesink, 0); + if (ftruncate (fileno (filesink->file), 0)) + goto flush_failed; + } + break; + case GST_EVENT_EOS: + if (fflush (filesink->file)) + goto flush_failed; + break; + default: + break; + } + + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); + + /* ERRORS */ +seek_failed: + { + GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK, + (_("Error while seeking in file \"%s\"."), filesink->filename), + GST_ERROR_SYSTEM); + gst_event_unref (event); + return FALSE; + } +flush_failed: + { + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filesink->filename), + GST_ERROR_SYSTEM); + gst_event_unref (event); + return FALSE; + } +} + +static gboolean +gst_file_sink_get_current_offset (GstFileSink * filesink, guint64 * p_pos) +{ + off_t ret = -1; + +#ifdef HAVE_FTELLO + ret = ftello (filesink->file); +#elif defined (G_OS_UNIX) || defined (G_OS_WIN32) + if (fflush (filesink->file)) { + GST_DEBUG_OBJECT (filesink, "Flush failed: %s", g_strerror (errno)); + /* ignore and continue */ + } + ret = lseek (fileno (filesink->file), 0, SEEK_CUR); +#else + ret = (off_t) ftell (filesink->file); +#endif + + if (ret != (off_t) - 1) + *p_pos = (guint64) ret; + + return (ret != (off_t) - 1); +} + +static GstFlowReturn +gst_file_sink_render_buffers (GstFileSink * sink, GstBuffer ** buffers, + guint num_buffers, guint8 * mem_nums, guint total_mems) +{ + GST_DEBUG_OBJECT (sink, + "writing %u buffers (%u memories) at position %" G_GUINT64_FORMAT, + num_buffers, total_mems, sink->current_pos); + + return gst_writev_buffers (GST_OBJECT_CAST (sink), fileno (sink->file), NULL, + buffers, num_buffers, mem_nums, total_mems, &sink->current_pos, 0); +} + +static GstFlowReturn +gst_file_sink_render_list (GstBaseSink * bsink, GstBufferList * buffer_list) +{ + GstFlowReturn flow; + GstBuffer **buffers; + GstFileSink *sink; + guint8 *mem_nums; + guint total_mems; + guint i, num_buffers; + gboolean sync_after = FALSE; + + sink = GST_FILE_SINK_CAST (bsink); + + num_buffers = gst_buffer_list_length (buffer_list); + if (num_buffers == 0) + goto no_data; + + /* extract buffers from list and count memories */ + buffers = g_newa (GstBuffer *, num_buffers); + mem_nums = g_newa (guint8, num_buffers); + for (i = 0, total_mems = 0; i < num_buffers; ++i) { + buffers[i] = gst_buffer_list_get (buffer_list, i); + mem_nums[i] = gst_buffer_n_memory (buffers[i]); + total_mems += mem_nums[i]; + if (GST_BUFFER_FLAG_IS_SET (buffers[i], GST_BUFFER_FLAG_SYNC_AFTER)) + sync_after = TRUE; + } + + flow = + gst_file_sink_render_buffers (sink, buffers, num_buffers, mem_nums, + total_mems); + + if (flow == GST_FLOW_OK && sync_after) { + if (fflush (sink->file) || fsync (fileno (sink->file))) { + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), sink->filename), + ("%s", g_strerror (errno))); + flow = GST_FLOW_ERROR; + } + } + + return flow; + +no_data: + { + GST_LOG_OBJECT (sink, "empty buffer list"); + return GST_FLOW_OK; + } +} + +static GstFlowReturn +gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer) +{ + GstFileSink *filesink; + GstFlowReturn flow; + guint8 n_mem; + + filesink = GST_FILE_SINK_CAST (sink); + + n_mem = gst_buffer_n_memory (buffer); + + if (n_mem > 0) + flow = gst_file_sink_render_buffers (filesink, &buffer, 1, &n_mem, n_mem); + else + flow = GST_FLOW_OK; + + if (flow == GST_FLOW_OK && + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_SYNC_AFTER)) { + if (fflush (filesink->file) || fsync (fileno (filesink->file))) { + GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filesink->filename), + ("%s", g_strerror (errno))); + flow = GST_FLOW_ERROR; + } + } + + return flow; +} + +static gboolean +gst_file_sink_start (GstBaseSink * basesink) +{ + return gst_file_sink_open_file (GST_FILE_SINK (basesink)); +} + +static gboolean +gst_file_sink_stop (GstBaseSink * basesink) +{ + gst_file_sink_close_file (GST_FILE_SINK (basesink)); + return TRUE; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_file_sink_uri_get_type (GType type) +{ + return GST_URI_SINK; +} + +static const gchar *const * +gst_file_sink_uri_get_protocols (GType type) +{ + static const gchar *protocols[] = { "file", NULL }; + + return protocols; +} + +static gchar * +gst_file_sink_uri_get_uri (GstURIHandler * handler) +{ + GstFileSink *sink = GST_FILE_SINK (handler); + + /* FIXME: make thread-safe */ + return g_strdup (sink->uri); +} + +static gboolean +gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) +{ + gchar *location; + gboolean ret; + GstFileSink *sink = GST_FILE_SINK (handler); + + /* allow file://localhost/foo/bar by stripping localhost but fail + * for every other hostname */ + if (g_str_has_prefix (uri, "file://localhost/")) { + char *tmp; + + /* 16 == strlen ("file://localhost") */ + tmp = g_strconcat ("file://", uri + 16, NULL); + /* we use gst_uri_get_location() although we already have the + * "location" with uri + 16 because it provides unescaping */ + location = gst_uri_get_location (tmp); + g_free (tmp); + } else if (strcmp (uri, "file://") == 0) { + /* Special case for "file://" as this is used by some applications + * to test with gst_element_make_from_uri if there's an element + * that supports the URI protocol. */ + gst_file_sink_set_location (sink, NULL, NULL); + return TRUE; + } else { + location = gst_uri_get_location (uri); + } + + if (!location) { + g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI without location"); + return FALSE; + } + + if (!g_path_is_absolute (location)) { + g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI location must be an absolute path"); + g_free (location); + return FALSE; + } + + ret = gst_file_sink_set_location (sink, location, error); + g_free (location); + + return ret; +} + +static void +gst_file_sink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_file_sink_uri_get_type; + iface->get_protocols = gst_file_sink_uri_get_protocols; + iface->get_uri = gst_file_sink_uri_get_uri; + iface->set_uri = gst_file_sink_uri_set_uri; +} diff --git a/plugins/elements/gstfilesink.h b/plugins/elements/gstfilesink.h new file mode 100644 index 0000000..6e3897c --- /dev/null +++ b/plugins/elements/gstfilesink.h @@ -0,0 +1,96 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstfilesink.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_FILE_SINK_H__ +#define __GST_FILE_SINK_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_FILE_SINK \ + (gst_file_sink_get_type()) +#define GST_FILE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILE_SINK,GstFileSink)) +#define GST_FILE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILE_SINK,GstFileSinkClass)) +#define GST_IS_FILE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILE_SINK)) +#define GST_IS_FILE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILE_SINK)) +#define GST_FILE_SINK_CAST(obj) ((GstFileSink *)(obj)) + +typedef struct _GstFileSink GstFileSink; +typedef struct _GstFileSinkClass GstFileSinkClass; + +/** + * GstFileSinkBufferMode: + * @GST_FILE_SINK_BUFFER_MODE_DEFAULT: Default buffering + * @GST_FILE_SINK_BUFFER_MODE_FULL: Fully buffered + * @GST_FILE_SINK_BUFFER_MODE_LINE: Line buffered + * @GST_FILE_SINK_BUFFER_MODE_UNBUFFERED: Unbuffered + * + * File read buffering mode. + */ +typedef enum { + GST_FILE_SINK_BUFFER_MODE_DEFAULT = -1, + GST_FILE_SINK_BUFFER_MODE_FULL = _IOFBF, + GST_FILE_SINK_BUFFER_MODE_LINE = _IOLBF, + GST_FILE_SINK_BUFFER_MODE_UNBUFFERED = _IONBF +} GstFileSinkBufferMode; + +/** + * GstFileSink: + * + * Opaque #GstFileSink structure. + */ +struct _GstFileSink { + GstBaseSink parent; + + /*< private >*/ + gchar *filename; + gchar *uri; + FILE *file; + + gboolean seekable; + guint64 current_pos; + + gint buffer_mode; + guint buffer_size; + gchar *buffer; + + gboolean append; +}; + +struct _GstFileSinkClass { + GstBaseSinkClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_file_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_FILE_SINK_H__ */ diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c new file mode 100644 index 0000000..76ab12c --- /dev/null +++ b/plugins/elements/gstfilesrc.c @@ -0,0 +1,676 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gstfilesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-filesrc + * @title: filesrc + * @see_also: #GstFileSrc + * + * Read data from a file in the local file system. + * + * ## Example launch line + * |[ + * gst-launch-1.0 filesrc location=song.ogg ! decodebin ! audioconvert ! audioresample ! autoaudiosink + * ]| Play song.ogg audio file which must be in the current working directory. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gstfilesrc.h" + +#include +#include +#include +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +/* On win32, stat* default to 32 bit; we need the 64-bit + * variants, so explicitly define it that way. */ +#undef stat +#define stat __stat64 +#undef fstat +#define fstat _fstat64 +#undef lseek +#define lseek _lseeki64 +#undef off_t +#define off_t guint64 +/* Prevent stat.h from defining the stat* functions as + * _stat*, since we're explicitly overriding that */ +#undef _INC_STAT_INL +#endif +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef __BIONIC__ /* Android */ +#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 +#undef fstat +#define fstat fstat64 +#endif +#endif + +#include +#include + +#include "../../gst/gst-i18n-lib.h" + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#ifndef S_ISREG +#define S_ISREG(mode) ((mode)&_S_IFREG) +#endif +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode)&_S_IFDIR) +#endif +#ifndef S_ISSOCK +#define S_ISSOCK(x) (0) +#endif +#ifndef O_BINARY +#define O_BINARY (0) +#endif + +/* Copy of glib's g_open due to win32 libc/cross-DLL brokenness: we can't + * use the 'file descriptor' opened in glib (and returned from this function) + * in this library, as they may have unrelated C runtimes. */ +static int +gst_open (const gchar * filename, int flags, int mode) +{ +#ifdef G_OS_WIN32 + wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); + int retval; + int save_errno; + + if (wfilename == NULL) { + errno = EINVAL; + return -1; + } + + retval = _wopen (wfilename, flags, mode); + save_errno = errno; + + g_free (wfilename); + + errno = save_errno; + return retval; +#elif defined (__BIONIC__) + return open (filename, flags | O_LARGEFILE, mode); +#else + return open (filename, flags, mode); +#endif +} + +GST_DEBUG_CATEGORY_STATIC (gst_file_src_debug); +#define GST_CAT_DEFAULT gst_file_src_debug + +/* FileSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_BLOCKSIZE 4*1024 + +enum +{ + PROP_0, + PROP_LOCATION +}; + +static void gst_file_src_finalize (GObject * object); + +static void gst_file_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_file_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_file_src_start (GstBaseSrc * basesrc); +static gboolean gst_file_src_stop (GstBaseSrc * basesrc); + +static gboolean gst_file_src_is_seekable (GstBaseSrc * src); +static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size); +static GstFlowReturn gst_file_src_fill (GstBaseSrc * src, guint64 offset, + guint length, GstBuffer * buf); + +static void gst_file_src_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +#define _do_init \ + G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_file_src_uri_handler_init); \ + GST_DEBUG_CATEGORY_INIT (gst_file_src_debug, "filesrc", 0, "filesrc element"); +#define gst_file_src_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFileSrc, gst_file_src, GST_TYPE_BASE_SRC, _do_init); + +static void +gst_file_src_class_init (GstFileSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + + gobject_class->set_property = gst_file_src_set_property; + gobject_class->get_property = gst_file_src_get_property; + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "File Location", + "Location of the file to read", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + gobject_class->finalize = gst_file_src_finalize; + + gst_element_class_set_static_metadata (gstelement_class, + "File Source", + "Source/File", + "Read from arbitrary point in a file", + "Erik Walthinsen "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size); + gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_file_src_fill); + + if (sizeof (off_t) < 8) { + GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!", + sizeof (off_t)); + } +} + +static void +gst_file_src_init (GstFileSrc * src) +{ + src->filename = NULL; + src->fd = 0; + src->uri = NULL; + + src->is_regular = FALSE; + + gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE); +} + +static void +gst_file_src_finalize (GObject * object) +{ + GstFileSrc *src; + + src = GST_FILE_SRC (object); + + g_free (src->filename); + g_free (src->uri); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_file_src_set_location (GstFileSrc * src, const gchar * location, + GError ** err) +{ + GstState state; + + /* the element must be stopped in order to do this */ + GST_OBJECT_LOCK (src); + state = GST_STATE (src); + if (state != GST_STATE_READY && state != GST_STATE_NULL) + goto wrong_state; + GST_OBJECT_UNLOCK (src); + + g_free (src->filename); + g_free (src->uri); + + /* clear the filename if we get a NULL */ + if (location == NULL) { + src->filename = NULL; + src->uri = NULL; + } else { + /* we store the filename as received by the application. On Windows this + * should be UTF8 */ + src->filename = g_strdup (location); + src->uri = gst_filename_to_uri (location, NULL); + GST_INFO ("filename : %s", src->filename); + GST_INFO ("uri : %s", src->uri); + } + g_object_notify (G_OBJECT (src), "location"); + /* FIXME 2.0: notify "uri" property once there is one */ + + return TRUE; + + /* ERROR */ +wrong_state: + { + g_warning ("Changing the `location' property on filesrc when a file is " + "open is not supported."); + if (err) + g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE, + "Changing the `location' property on filesrc when a file is " + "open is not supported."); + GST_OBJECT_UNLOCK (src); + return FALSE; + } +} + +static void +gst_file_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFileSrc *src; + + g_return_if_fail (GST_IS_FILE_SRC (object)); + + src = GST_FILE_SRC (object); + + switch (prop_id) { + case PROP_LOCATION: + gst_file_src_set_location (src, g_value_get_string (value), NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_file_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFileSrc *src; + + g_return_if_fail (GST_IS_FILE_SRC (object)); + + src = GST_FILE_SRC (object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_string (value, src->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*** + * read code below + * that is to say, you shouldn't read the code below, but the code that reads + * stuff is below. Well, you shouldn't not read the code below, feel free + * to read it of course. It's just that "read code below" is a pretty crappy + * documentation string because it sounds like we're expecting you to read + * the code to understand what it does, which, while true, is really not + * the sort of attitude we want to be advertising. No sir. + * + */ +static GstFlowReturn +gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer * buf) +{ + GstFileSrc *src; + guint to_read, bytes_read; + int ret; + GstMapInfo info; + guint8 *data; + + src = GST_FILE_SRC_CAST (basesrc); + + if (G_UNLIKELY (offset != -1 && src->read_position != offset)) { + off_t res; + + res = lseek (src->fd, offset, SEEK_SET); + if (G_UNLIKELY (res < 0 || res != offset)) + goto seek_failed; + + src->read_position = offset; + } + + if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) + goto buffer_write_fail; + data = info.data; + + bytes_read = 0; + to_read = length; + while (to_read > 0) { + GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", + to_read, offset + bytes_read); + errno = 0; + ret = read (src->fd, data + bytes_read, to_read); + if (G_UNLIKELY (ret < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + goto could_not_read; + } + + /* files should eos if they read 0 and more was requested */ + if (G_UNLIKELY (ret == 0)) { + /* .. but first we should return any remaining data */ + if (bytes_read > 0) + break; + goto eos; + } + + to_read -= ret; + bytes_read += ret; + + src->read_position += ret; + } + + gst_buffer_unmap (buf, &info); + if (bytes_read != length) + gst_buffer_resize (buf, 0, bytes_read); + + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + bytes_read; + + return GST_FLOW_OK; + + /* ERROR */ +seek_failed: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + return GST_FLOW_ERROR; + } +could_not_read: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, 0); + return GST_FLOW_ERROR; + } +eos: + { + GST_DEBUG ("EOS"); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, 0); + return GST_FLOW_EOS; + } +buffer_write_fail: + { + GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Can't write to buffer")); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_file_src_is_seekable (GstBaseSrc * basesrc) +{ + GstFileSrc *src = GST_FILE_SRC (basesrc); + + return src->seekable; +} + +static gboolean +gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size) +{ + struct stat stat_results; + GstFileSrc *src; + + src = GST_FILE_SRC (basesrc); + + if (!src->seekable) { + /* If it isn't seekable, we won't know the length (but fstat will still + * succeed, and wrongly say our length is zero. */ + return FALSE; + } + + if (fstat (src->fd, &stat_results) < 0) + goto could_not_stat; + + *size = stat_results.st_size; + + return TRUE; + + /* ERROR */ +could_not_stat: + { + return FALSE; + } +} + +/* open the file, necessary to go to READY state */ +static gboolean +gst_file_src_start (GstBaseSrc * basesrc) +{ + GstFileSrc *src = GST_FILE_SRC (basesrc); + struct stat stat_results; + + if (src->filename == NULL || src->filename[0] == '\0') + goto no_filename; + + GST_INFO_OBJECT (src, "opening file %s", src->filename); + + /* open the file */ + src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0); + + if (src->fd < 0) + goto open_failed; + + /* check if it is a regular file, otherwise bail out */ + if (fstat (src->fd, &stat_results) < 0) + goto no_stat; + + if (S_ISDIR (stat_results.st_mode)) + goto was_directory; + + if (S_ISSOCK (stat_results.st_mode)) + goto was_socket; + + src->read_position = 0; + + /* record if it's a regular (hence seekable and lengthable) file */ + if (S_ISREG (stat_results.st_mode)) + src->is_regular = TRUE; + + /* We need to check if the underlying file is seekable. */ + { + off_t res = lseek (src->fd, 0, SEEK_END); + + if (res < 0) { + GST_LOG_OBJECT (src, "disabling seeking, lseek failed: %s", + g_strerror (errno)); + src->seekable = FALSE; + } else { + res = lseek (src->fd, 0, SEEK_SET); + + if (res < 0) { + /* We really don't like not being able to go back to 0 */ + src->seekable = FALSE; + goto lseek_wonky; + } + + src->seekable = TRUE; + } + } + + /* We can only really do seeking on regular files - for other file types, we + * don't know their length, so seeking isn't useful/meaningful */ + src->seekable = src->seekable && src->is_regular; + + gst_base_src_set_dynamic_size (basesrc, src->seekable); + + return TRUE; + + /* ERROR */ +no_filename: + { + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, + (_("No file name specified for reading.")), (NULL)); + goto error_exit; + } +open_failed: + { + switch (errno) { + case ENOENT: + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), + ("No such file \"%s\"", src->filename)); + break; + default: + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not open file \"%s\" for reading."), src->filename), + GST_ERROR_SYSTEM); + break; + } + goto error_exit; + } +no_stat: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not get info on \"%s\"."), src->filename), (NULL)); + goto error_close; + } +was_directory: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("\"%s\" is a directory."), src->filename), (NULL)); + goto error_close; + } +was_socket: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("File \"%s\" is a socket."), src->filename), (NULL)); + goto error_close; + } +lseek_wonky: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Could not seek back to zero after seek test in file \"%s\"", + src->filename)); + goto error_close; + } +error_close: + close (src->fd); +error_exit: + return FALSE; +} + +/* unmap and close the file */ +static gboolean +gst_file_src_stop (GstBaseSrc * basesrc) +{ + GstFileSrc *src = GST_FILE_SRC (basesrc); + + /* close the file */ + close (src->fd); + + /* zero out a lot of our state */ + src->fd = 0; + src->is_regular = FALSE; + + return TRUE; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_file_src_uri_get_type (GType type) +{ + return GST_URI_SRC; +} + +static const gchar *const * +gst_file_src_uri_get_protocols (GType type) +{ + static const gchar *protocols[] = { "file", NULL }; + + return protocols; +} + +static gchar * +gst_file_src_uri_get_uri (GstURIHandler * handler) +{ + GstFileSrc *src = GST_FILE_SRC (handler); + + /* FIXME: make thread-safe */ + return g_strdup (src->uri); +} + +static gboolean +gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** err) +{ + gchar *location, *hostname = NULL; + gboolean ret = FALSE; + GstFileSrc *src = GST_FILE_SRC (handler); + + if (strcmp (uri, "file://") == 0) { + /* Special case for "file://" as this is used by some applications + * to test with gst_element_make_from_uri if there's an element + * that supports the URI protocol. */ + gst_file_src_set_location (src, NULL, NULL); + return TRUE; + } + + location = g_filename_from_uri (uri, &hostname, err); + + if (!location || (err != NULL && *err != NULL)) { + GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri, + (err != NULL && *err != NULL) ? (*err)->message : "unknown error"); + goto beach; + } + + if ((hostname) && (strcmp (hostname, "localhost"))) { + /* Only 'localhost' is permitted */ + GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname); + g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI with invalid hostname '%s'", hostname); + goto beach; + } +#ifdef G_OS_WIN32 + /* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths + * correctly on windows, it leaves them with an extra backslash + * at the start if they're of the mozilla-style file://///host/path/file + * form. Correct this. + */ + if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\') + memmove (location, location + 1, strlen (location + 1) + 1); +#endif + + ret = gst_file_src_set_location (src, location, err); + +beach: + if (location) + g_free (location); + if (hostname) + g_free (hostname); + + return ret; +} + +static void +gst_file_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_file_src_uri_get_type; + iface->get_protocols = gst_file_src_uri_get_protocols; + iface->get_uri = gst_file_src_uri_get_uri; + iface->set_uri = gst_file_src_uri_set_uri; +} diff --git a/plugins/elements/gstfilesrc.h b/plugins/elements/gstfilesrc.h new file mode 100644 index 0000000..e73cfc3 --- /dev/null +++ b/plugins/elements/gstfilesrc.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstfilesrc.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_FILE_SRC_H__ +#define __GST_FILE_SRC_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_FILE_SRC \ + (gst_file_src_get_type()) +#define GST_FILE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILE_SRC,GstFileSrc)) +#define GST_FILE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILE_SRC,GstFileSrcClass)) +#define GST_IS_FILE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILE_SRC)) +#define GST_IS_FILE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILE_SRC)) +#define GST_FILE_SRC_CAST(obj) ((GstFileSrc*) obj) + +typedef struct _GstFileSrc GstFileSrc; +typedef struct _GstFileSrcClass GstFileSrcClass; + +/** + * GstFileSrc: + * + * Opaque #GstFileSrc structure. + */ +struct _GstFileSrc { + GstBaseSrc element; + + /*< private >*/ + gchar *filename; /* filename */ + gchar *uri; /* caching the URI */ + gint fd; /* open file descriptor */ + guint64 read_position; /* position of fd */ + + gboolean seekable; /* whether the file is seekable */ + gboolean is_regular; /* whether it's a (symlink to a) + regular file */ +}; + +struct _GstFileSrcClass { + GstBaseSrcClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_file_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_FILE_SRC_H__ */ diff --git a/plugins/elements/gstfunnel.c b/plugins/elements/gstfunnel.c new file mode 100644 index 0000000..af52f38 --- /dev/null +++ b/plugins/elements/gstfunnel.c @@ -0,0 +1,475 @@ +/* + * GStreamer Funnel element + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete + * Copyright 2007 Nokia Corp. + * + * gstfunnel.c: Simple Funnel element + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:element-funnel + * @title: funnel + * + * Takes packets from various input sinks into one output source. + * + * funnel always outputs a single, open ended segment from + * 0 with in %GST_FORMAT_TIME and outputs the buffers of the + * different sinkpads with timestamps that are set to the + * running time for that stream. funnel does not synchronize + * the different input streams but simply forwards all buffers + * immediately when they arrive. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstfunnel.h" + +GST_DEBUG_CATEGORY_STATIC (gst_funnel_debug); +#define GST_CAT_DEFAULT gst_funnel_debug + +GType gst_funnel_pad_get_type (void); +#define GST_TYPE_FUNNEL_PAD \ + (gst_funnel_pad_get_type()) +#define GST_FUNNEL_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FUNNEL_PAD, GstFunnelPad)) +#define GST_FUNNEL_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_FUNNEL_PAD, GstFunnelPadClass)) +#define GST_IS_FUNNEL_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FUNNEL_PAD)) +#define GST_IS_FUNNEL_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_FUNNEL_PAD)) +#define GST_FUNNEL_PAD_CAST(obj) \ + ((GstFunnelPad *)(obj)) + +typedef struct _GstFunnelPad GstFunnelPad; +typedef struct _GstFunnelPadClass GstFunnelPadClass; + +struct _GstFunnelPad +{ + GstPad parent; + + gboolean got_eos; +}; + +struct _GstFunnelPadClass +{ + GstPadClass parent; +}; + +G_DEFINE_TYPE (GstFunnelPad, gst_funnel_pad, GST_TYPE_PAD); + +#define DEFAULT_FORWARD_STICKY_EVENTS TRUE + +enum +{ + PROP_0, + PROP_FORWARD_STICKY_EVENTS +}; + +static void +gst_funnel_pad_class_init (GstFunnelPadClass * klass) +{ +} + +static void +gst_funnel_pad_init (GstFunnelPad * pad) +{ + pad->got_eos = FALSE; +} + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_funnel_debug, "funnel", 0, "funnel element"); +#define gst_funnel_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstFunnel, gst_funnel, GST_TYPE_ELEMENT, _do_init); + +static GstStateChangeReturn gst_funnel_change_state (GstElement * element, + GstStateChange transition); +static GstPad *gst_funnel_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); +static void gst_funnel_release_pad (GstElement * element, GstPad * pad); + +static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_funnel_sink_chain_list (GstPad * pad, + GstObject * parent, GstBufferList * list); +static gboolean gst_funnel_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); + +static void +gst_funnel_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (object); + + switch (prop_id) { + case PROP_FORWARD_STICKY_EVENTS: + funnel->forward_sticky_events = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_funnel_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (object); + + switch (prop_id) { + case PROP_FORWARD_STICKY_EVENTS: + g_value_set_boolean (value, funnel->forward_sticky_events); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_funnel_dispose (GObject * object) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (object); + GList *item; + + gst_object_replace ((GstObject **) & funnel->last_sinkpad, NULL); + +restart: + for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { + GstPad *pad = GST_PAD (item->data); + + if (GST_PAD_IS_SINK (pad)) { + gst_element_release_request_pad (GST_ELEMENT (object), pad); + goto restart; + } + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_funnel_class_init (GstFunnelClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_funnel_set_property; + gobject_class->get_property = gst_funnel_get_property; + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_funnel_dispose); + + g_object_class_install_property (gobject_class, PROP_FORWARD_STICKY_EVENTS, + g_param_spec_boolean ("forward-sticky-events", "Forward sticky events", + "Forward sticky events on stream changes", + DEFAULT_FORWARD_STICKY_EVENTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + gst_element_class_set_static_metadata (gstelement_class, + "Funnel pipe fitting", "Generic", "N-to-1 pipe fitting", + "Olivier Crete "); + + gst_element_class_add_static_pad_template (gstelement_class, &sink_template); + gst_element_class_add_static_pad_template (gstelement_class, &src_template); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_funnel_request_new_pad); + gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_funnel_release_pad); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_funnel_change_state); +} + +static void +gst_funnel_init (GstFunnel * funnel) +{ + funnel->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_use_fixed_caps (funnel->srcpad); + + gst_element_add_pad (GST_ELEMENT (funnel), funnel->srcpad); + + funnel->forward_sticky_events = DEFAULT_FORWARD_STICKY_EVENTS; +} + +static GstPad * +gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstPad *sinkpad; + + GST_DEBUG_OBJECT (element, "requesting pad"); + + sinkpad = GST_PAD_CAST (g_object_new (GST_TYPE_FUNNEL_PAD, + "name", name, "direction", templ->direction, "template", templ, + NULL)); + + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_funnel_sink_chain)); + gst_pad_set_chain_list_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_funnel_sink_chain_list)); + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_funnel_sink_event)); + + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); + + gst_pad_set_active (sinkpad, TRUE); + + gst_element_add_pad (element, sinkpad); + + GST_DEBUG_OBJECT (element, "requested pad %s:%s", + GST_DEBUG_PAD_NAME (sinkpad)); + + return sinkpad; +} + +static gboolean +gst_funnel_all_sinkpads_eos_unlocked (GstFunnel * funnel, GstPad * pad) +{ + GstElement *element = GST_ELEMENT_CAST (funnel); + GList *item; + gboolean all_eos = FALSE; + + + if (element->numsinkpads == 0) + goto done; + + for (item = element->sinkpads; item != NULL; item = g_list_next (item)) { + GstFunnelPad *sinkpad = GST_FUNNEL_PAD_CAST (item->data); + + if (!sinkpad->got_eos) { + return FALSE; + } + } + + all_eos = TRUE; + +done: + return all_eos; +} + +static void +gst_funnel_release_pad (GstElement * element, GstPad * pad) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (element); + GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); + gboolean got_eos; + gboolean send_eos = FALSE; + + GST_DEBUG_OBJECT (funnel, "releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + gst_pad_set_active (pad, FALSE); + + got_eos = fpad->got_eos; + + gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad); + + GST_OBJECT_LOCK (funnel); + if (!got_eos && gst_funnel_all_sinkpads_eos_unlocked (funnel, NULL)) { + GST_DEBUG_OBJECT (funnel, "Pad removed. All others are EOS. Sending EOS"); + send_eos = TRUE; + } + GST_OBJECT_UNLOCK (funnel); + + if (send_eos) + if (!gst_pad_push_event (funnel->srcpad, gst_event_new_eos ())) + GST_WARNING_OBJECT (funnel, "Failure pushing EOS"); +} + +static gboolean +forward_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstPad *srcpad = user_data; + + if (GST_EVENT_TYPE (*event) != GST_EVENT_EOS) + gst_pad_push_event (srcpad, gst_event_ref (*event)); + + return TRUE; +} + +static GstFlowReturn +gst_funnel_sink_chain_object (GstPad * pad, GstFunnel * funnel, + gboolean is_list, GstMiniObject * obj) +{ + GstFlowReturn res; + + GST_DEBUG_OBJECT (pad, "received %" GST_PTR_FORMAT, obj); + + GST_PAD_STREAM_LOCK (funnel->srcpad); + + if ((funnel->last_sinkpad == NULL) || (funnel->forward_sticky_events + && (funnel->last_sinkpad != pad))) { + gst_object_replace ((GstObject **) & funnel->last_sinkpad, + GST_OBJECT (pad)); + + GST_DEBUG_OBJECT (pad, "Forwarding sticky events"); + gst_pad_sticky_events_foreach (pad, forward_events, funnel->srcpad); + } + + if (is_list) + res = gst_pad_push_list (funnel->srcpad, GST_BUFFER_LIST_CAST (obj)); + else + res = gst_pad_push (funnel->srcpad, GST_BUFFER_CAST (obj)); + + GST_PAD_STREAM_UNLOCK (funnel->srcpad); + + GST_LOG_OBJECT (pad, "handled buffer%s %s", (is_list ? "list" : ""), + gst_flow_get_name (res)); + + return res; +} + +static GstFlowReturn +gst_funnel_sink_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (parent); + + return gst_funnel_sink_chain_object (pad, funnel, TRUE, + GST_MINI_OBJECT_CAST (list)); +} + +static GstFlowReturn +gst_funnel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (parent); + + return gst_funnel_sink_chain_object (pad, funnel, FALSE, + GST_MINI_OBJECT_CAST (buffer)); +} + +static gboolean +gst_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstFunnel *funnel = GST_FUNNEL_CAST (parent); + GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); + gboolean forward = TRUE; + gboolean res = TRUE; + gboolean unlock = FALSE; + + GST_DEBUG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event); + + if (GST_EVENT_IS_STICKY (event)) { + unlock = TRUE; + GST_PAD_STREAM_LOCK (funnel->srcpad); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GST_OBJECT_LOCK (funnel); + fpad->got_eos = TRUE; + if (!gst_funnel_all_sinkpads_eos_unlocked (funnel, pad)) { + forward = FALSE; + } else { + forward = TRUE; + } + GST_OBJECT_UNLOCK (funnel); + } else if (pad != funnel->last_sinkpad) { + forward = FALSE; + } + } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + unlock = TRUE; + GST_PAD_STREAM_LOCK (funnel->srcpad); + GST_OBJECT_LOCK (funnel); + fpad->got_eos = FALSE; + GST_OBJECT_UNLOCK (funnel); + } + + if (forward && GST_EVENT_IS_SERIALIZED (event)) { + /* If no data is coming and we receive serialized event, need to forward all sticky events. + * Otherwise downstream has an inconsistent set of sticky events when + * handling the new event. */ + if (!unlock) { + unlock = TRUE; + GST_PAD_STREAM_LOCK (funnel->srcpad); + } + + if ((funnel->last_sinkpad == NULL) || (funnel->forward_sticky_events + && (funnel->last_sinkpad != pad))) { + gst_object_replace ((GstObject **) & funnel->last_sinkpad, + GST_OBJECT (pad)); + gst_pad_sticky_events_foreach (pad, forward_events, funnel->srcpad); + } + } + + if (forward) + res = gst_pad_push_event (funnel->srcpad, event); + else + gst_event_unref (event); + + if (unlock) + GST_PAD_STREAM_UNLOCK (funnel->srcpad); + + return res; +} + +static void +reset_pad (const GValue * data, gpointer user_data) +{ + GstPad *pad = g_value_get_object (data); + GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); + GstFunnel *funnel = user_data; + + GST_OBJECT_LOCK (funnel); + fpad->got_eos = FALSE; + GST_OBJECT_UNLOCK (funnel); +} + +static GstStateChangeReturn +gst_funnel_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + + 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: + { + GstIterator *iter = gst_element_iterate_sink_pads (element); + GstIteratorResult res; + + do { + res = gst_iterator_foreach (iter, reset_pad, element); + if (res == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); + } while (res == GST_ITERATOR_RESYNC); + gst_iterator_free (iter); + + if (res == GST_ITERATOR_ERROR) + return GST_STATE_CHANGE_FAILURE; + + } + break; + default: + break; + } + + return ret; +} diff --git a/plugins/elements/gstfunnel.h b/plugins/elements/gstfunnel.h new file mode 100644 index 0000000..8c02109 --- /dev/null +++ b/plugins/elements/gstfunnel.h @@ -0,0 +1,71 @@ +/* + * GStreamer Funnel element + * + * Copyright 2007 Collabora Ltd. + * @author: Olivier Crete + * Copyright 2007 Nokia Corp. + * + * gstfunnel.h: Simple Funnel element + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef __GST_FUNNEL_H__ +#define __GST_FUNNEL_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_FUNNEL \ + (gst_funnel_get_type ()) +#define GST_FUNNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FUNNEL,GstFunnel)) +#define GST_FUNNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FUNNEL,GstFunnelClass)) +#define GST_IS_FUNNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FUNNEL)) +#define GST_IS_FUNNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FUNNEL)) +#define GST_FUNNEL_CAST(obj) ((GstFunnel *)(obj)) + +typedef struct _GstFunnel GstFunnel; +typedef struct _GstFunnelClass GstFunnelClass; + +/** + * GstFunnel: + * + * Opaque #GstFunnel data structure. + */ +struct _GstFunnel { + GstElement element; + + /*< private >*/ + GstPad *srcpad; + + GstPad *last_sinkpad; + gboolean forward_sticky_events; +}; + +struct _GstFunnelClass { + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_funnel_get_type (void); + +G_END_DECLS + +#endif /* __GST_FUNNEL_H__ */ diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c new file mode 100644 index 0000000..a3eb5cd --- /dev/null +++ b/plugins/elements/gstidentity.c @@ -0,0 +1,1003 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstidentity.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-identity + * @title: identity + * + * Dummy element that passes incoming data through unmodified. It has some + * useful diagnostic functions, such as offset and timestamp checking. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstelements_private.h" +#include "../../gst/gst-i18n-lib.h" +#include "gstidentity.h" + +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); + +GST_DEBUG_CATEGORY_STATIC (gst_identity_debug); +#define GST_CAT_DEFAULT gst_identity_debug + +/* Identity signals and args */ +enum +{ + SIGNAL_HANDOFF, + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_SLEEP_TIME 0 +#define DEFAULT_DUPLICATE 1 +#define DEFAULT_ERROR_AFTER -1 +#define DEFAULT_DROP_PROBABILITY 0.0 +#define DEFAULT_DROP_BUFFER_FLAGS 0 +#define DEFAULT_DATARATE 0 +#define DEFAULT_SILENT TRUE +#define DEFAULT_SINGLE_SEGMENT FALSE +#define DEFAULT_DUMP FALSE +#define DEFAULT_SYNC FALSE +#define DEFAULT_CHECK_IMPERFECT_TIMESTAMP FALSE +#define DEFAULT_CHECK_IMPERFECT_OFFSET FALSE +#define DEFAULT_SIGNAL_HANDOFFS TRUE +#define DEFAULT_TS_OFFSET 0 +#define DEFAULT_DROP_ALLOCATION FALSE + +enum +{ + PROP_0, + PROP_SLEEP_TIME, + PROP_ERROR_AFTER, + PROP_DROP_PROBABILITY, + PROP_DROP_BUFFER_FLAGS, + PROP_DATARATE, + PROP_SILENT, + PROP_SINGLE_SEGMENT, + PROP_LAST_MESSAGE, + PROP_DUMP, + PROP_SYNC, + PROP_TS_OFFSET, + PROP_CHECK_IMPERFECT_TIMESTAMP, + PROP_CHECK_IMPERFECT_OFFSET, + PROP_SIGNAL_HANDOFFS, + PROP_DROP_ALLOCATION +}; + + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element"); +#define gst_identity_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstIdentity, gst_identity, GST_TYPE_BASE_TRANSFORM, + _do_init); + +static void gst_identity_finalize (GObject * object); +static void gst_identity_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_identity_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_identity_sink_event (GstBaseTransform * trans, + GstEvent * event); +static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_identity_start (GstBaseTransform * trans); +static gboolean gst_identity_stop (GstBaseTransform * trans); +static GstStateChangeReturn gst_identity_change_state (GstElement * element, + GstStateChange transition); +static gboolean gst_identity_accept_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_identity_query (GstBaseTransform * base, + GstPadDirection direction, GstQuery * query); + +static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; + +static GParamSpec *pspec_last_message = NULL; + +static void +gst_identity_finalize (GObject * object) +{ + GstIdentity *identity; + + identity = GST_IDENTITY (object); + + g_free (identity->last_message); + g_cond_clear (&identity->blocked_cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_identity_class_init (GstIdentityClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseTransformClass *gstbasetrans_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = gst_identity_set_property; + gobject_class->get_property = gst_identity_get_property; + + g_object_class_install_property (gobject_class, PROP_SLEEP_TIME, + g_param_spec_uint ("sleep-time", "Sleep time", + "Microseconds to sleep between processing", 0, G_MAXUINT, + DEFAULT_SLEEP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ERROR_AFTER, + g_param_spec_int ("error-after", "Error After", "Error after N buffers", + G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DROP_PROBABILITY, + g_param_spec_float ("drop-probability", "Drop Probability", + "The Probability a buffer is dropped", 0.0, 1.0, + DEFAULT_DROP_PROBABILITY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstIdentity:drop-buffer-flags: + * + * Drop buffers with the given flags. + * + * Since: 1.8 + **/ + g_object_class_install_property (gobject_class, PROP_DROP_BUFFER_FLAGS, + g_param_spec_flags ("drop-buffer-flags", "Check flags to drop buffers", + "Drop buffers with the given flags", + GST_TYPE_BUFFER_FLAGS, DEFAULT_DROP_BUFFER_FLAGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DATARATE, + g_param_spec_int ("datarate", "Datarate", + "(Re)timestamps buffers with number of bytes per second (0 = inactive)", + 0, G_MAXINT, DEFAULT_DATARATE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SINGLE_SEGMENT, + g_param_spec_boolean ("single-segment", "Single Segment", + "Timestamp buffers and eat segments so as to appear as one segment", + DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "last-message", + "last-message", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (gobject_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout", + DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SYNC, + g_param_spec_boolean ("sync", "Synchronize", + "Synchronize to pipeline clock", DEFAULT_SYNC, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TS_OFFSET, + g_param_spec_int64 ("ts-offset", "Timestamp offset for synchronisation", + "Timestamp offset in nanoseconds for synchronisation, negative for earlier sync", + G_MININT64, G_MAXINT64, DEFAULT_TS_OFFSET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_CHECK_IMPERFECT_TIMESTAMP, + g_param_spec_boolean ("check-imperfect-timestamp", + "Check for discontiguous timestamps", + "Send element messages if timestamps and durations do not match up", + DEFAULT_CHECK_IMPERFECT_TIMESTAMP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CHECK_IMPERFECT_OFFSET, + g_param_spec_boolean ("check-imperfect-offset", + "Check for discontiguous offset", + "Send element messages if offset and offset_end do not match up", + DEFAULT_CHECK_IMPERFECT_OFFSET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstIdentity:signal-handoffs + * + * If set to %TRUE, the identity will emit a handoff signal when handling a buffer. + * When set to %FALSE, no signal will be emitted, which might improve performance. + */ + g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS, + g_param_spec_boolean ("signal-handoffs", + "Signal handoffs", "Send a signal before pushing the buffer", + DEFAULT_SIGNAL_HANDOFFS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DROP_ALLOCATION, + g_param_spec_boolean ("drop-allocation", "Drop allocation query", + "Don't forward allocation queries", DEFAULT_DROP_ALLOCATION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstIdentity::handoff: + * @identity: the identity instance + * @buffer: the buffer that just has been received + * @pad: the pad that received it + * + * This signal gets emitted before passing the buffer downstream. + */ + gst_identity_signals[SIGNAL_HANDOFF] = + g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); + + gobject_class->finalize = gst_identity_finalize; + + gst_element_class_set_static_metadata (gstelement_class, + "Identity", + "Generic", + "Pass data without modification", "Erik Walthinsen "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_identity_change_state); + + gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_identity_sink_event); + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_identity_transform_ip); + gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start); + gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop); + gstbasetrans_class->accept_caps = + GST_DEBUG_FUNCPTR (gst_identity_accept_caps); + gstbasetrans_class->query = gst_identity_query; +} + +static void +gst_identity_init (GstIdentity * identity) +{ + identity->sleep_time = DEFAULT_SLEEP_TIME; + identity->error_after = DEFAULT_ERROR_AFTER; + identity->drop_probability = DEFAULT_DROP_PROBABILITY; + identity->drop_buffer_flags = DEFAULT_DROP_BUFFER_FLAGS; + identity->datarate = DEFAULT_DATARATE; + identity->silent = DEFAULT_SILENT; + identity->single_segment = DEFAULT_SINGLE_SEGMENT; + identity->sync = DEFAULT_SYNC; + identity->check_imperfect_timestamp = DEFAULT_CHECK_IMPERFECT_TIMESTAMP; + identity->check_imperfect_offset = DEFAULT_CHECK_IMPERFECT_OFFSET; + identity->dump = DEFAULT_DUMP; + identity->last_message = NULL; + identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + identity->ts_offset = DEFAULT_TS_OFFSET; + g_cond_init (&identity->blocked_cond); + + gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE); +} + +static void +gst_identity_notify_last_message (GstIdentity * identity) +{ + g_object_notify_by_pspec ((GObject *) identity, pspec_last_message); +} + +static GstFlowReturn +gst_identity_do_sync (GstIdentity * identity, GstClockTime running_time) +{ + GstFlowReturn ret = GST_FLOW_OK; + + if (identity->sync && + GST_BASE_TRANSFORM_CAST (identity)->segment.format == GST_FORMAT_TIME) { + GstClock *clock; + + GST_OBJECT_LOCK (identity); + + if (identity->flushing) { + GST_OBJECT_UNLOCK (identity); + return GST_FLOW_FLUSHING; + } + + while (identity->blocked) + g_cond_wait (&identity->blocked_cond, GST_OBJECT_GET_LOCK (identity)); + + if (identity->flushing) { + GST_OBJECT_UNLOCK (identity); + return GST_FLOW_FLUSHING; + } + + if ((clock = GST_ELEMENT (identity)->clock)) { + GstClockReturn cret; + GstClockTime timestamp; + GstClockTimeDiff ts_offset = identity->ts_offset; + + timestamp = running_time + GST_ELEMENT (identity)->base_time + + identity->upstream_latency; + if (ts_offset < 0) { + ts_offset = -ts_offset; + if (ts_offset < timestamp) + timestamp -= ts_offset; + else + timestamp = 0; + } else + timestamp += ts_offset; + + /* save id if we need to unlock */ + identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp); + GST_OBJECT_UNLOCK (identity); + + cret = gst_clock_id_wait (identity->clock_id, NULL); + + GST_OBJECT_LOCK (identity); + if (identity->clock_id) { + gst_clock_id_unref (identity->clock_id); + identity->clock_id = NULL; + } + if (cret == GST_CLOCK_UNSCHEDULED || identity->flushing) + ret = GST_FLOW_FLUSHING; + } + GST_OBJECT_UNLOCK (identity); + } + + return ret; +} + +static gboolean +gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) +{ + GstIdentity *identity; + gboolean ret = TRUE; + + identity = GST_IDENTITY (trans); + + if (!identity->silent) { + const GstStructure *s; + const gchar *tstr; + gchar *sstr; + + GST_OBJECT_LOCK (identity); + g_free (identity->last_message); + + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); + if ((s = gst_event_get_structure (event))) + sstr = gst_structure_to_string (s); + else + sstr = g_strdup (""); + + identity->last_message = + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (trans->sinkpad), tstr, GST_EVENT_TYPE (event), + sstr, event); + g_free (sstr); + GST_OBJECT_UNLOCK (identity); + + gst_identity_notify_last_message (identity); + } + + if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) { + if (!trans->have_segment) { + GstEvent *news; + GstSegment segment; + + gst_event_copy_segment (event, &segment); + gst_event_copy_segment (event, &trans->segment); + trans->have_segment = TRUE; + + /* This is the first segment, send out a (0, -1) segment */ + gst_segment_init (&segment, segment.format); + news = gst_event_new_segment (&segment); + + gst_pad_event_default (trans->sinkpad, GST_OBJECT_CAST (trans), news); + } else { + /* need to track segment for proper running time */ + gst_event_copy_segment (event, &trans->segment); + } + } + + if (GST_EVENT_TYPE (event) == GST_EVENT_GAP && + trans->have_segment && trans->segment.format == GST_FORMAT_TIME) { + GstClockTime start, dur; + + gst_event_parse_gap (event, &start, &dur); + if (GST_CLOCK_TIME_IS_VALID (start)) { + start = gst_segment_to_running_time (&trans->segment, + GST_FORMAT_TIME, start); + + gst_identity_do_sync (identity, start); + + /* also transform GAP timestamp similar to buffer timestamps */ + if (identity->single_segment) { + gst_event_unref (event); + event = gst_event_new_gap (start, dur); + } + } + } + + /* Reset previous timestamp, duration and offsets on SEGMENT + * to prevent false warnings when checking for perfect streams */ + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + identity->prev_timestamp = identity->prev_duration = GST_CLOCK_TIME_NONE; + identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE; + } + + if (identity->single_segment && GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + /* eat up segments */ + gst_event_unref (event); + ret = TRUE; + } else { + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) { + GST_OBJECT_LOCK (identity); + identity->flushing = TRUE; + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + } + GST_OBJECT_UNLOCK (identity); + } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + GST_OBJECT_LOCK (identity); + identity->flushing = FALSE; + GST_OBJECT_UNLOCK (identity); + } + + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); + } + + return ret; +} + +static void +gst_identity_check_imperfect_timestamp (GstIdentity * identity, GstBuffer * buf) +{ + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buf); + + /* invalid timestamp drops us out of check. FIXME: maybe warn ? */ + if (timestamp != GST_CLOCK_TIME_NONE) { + /* check if we had a previous buffer to compare to */ + if (identity->prev_timestamp != GST_CLOCK_TIME_NONE && + identity->prev_duration != GST_CLOCK_TIME_NONE) { + GstClockTime t_expected; + GstClockTimeDiff dt; + + t_expected = identity->prev_timestamp + identity->prev_duration; + dt = GST_CLOCK_DIFF (t_expected, timestamp); + if (dt != 0) { + /* + * "imperfect-timestamp" bus message: + * @identity: the identity instance + * @delta: the GST_CLOCK_DIFF to the prev timestamp + * @prev-timestamp: the previous buffer timestamp + * @prev-duration: the previous buffer duration + * @prev-offset: the previous buffer offset + * @prev-offset-end: the previous buffer offset end + * @cur-timestamp: the current buffer timestamp + * @cur-duration: the current buffer duration + * @cur-offset: the current buffer offset + * @cur-offset-end: the current buffer offset end + * + * This bus message gets emitted if the check-imperfect-timestamp + * property is set and there is a gap in time between the + * last buffer and the newly received buffer. + */ + gst_element_post_message (GST_ELEMENT (identity), + gst_message_new_element (GST_OBJECT (identity), + gst_structure_new ("imperfect-timestamp", + "delta", G_TYPE_INT64, dt, + "prev-timestamp", G_TYPE_UINT64, + identity->prev_timestamp, "prev-duration", G_TYPE_UINT64, + identity->prev_duration, "prev-offset", G_TYPE_UINT64, + identity->prev_offset, "prev-offset-end", G_TYPE_UINT64, + identity->prev_offset_end, "cur-timestamp", G_TYPE_UINT64, + timestamp, "cur-duration", G_TYPE_UINT64, + GST_BUFFER_DURATION (buf), "cur-offset", G_TYPE_UINT64, + GST_BUFFER_OFFSET (buf), "cur-offset-end", G_TYPE_UINT64, + GST_BUFFER_OFFSET_END (buf), NULL))); + } + } else { + GST_DEBUG_OBJECT (identity, "can't check data-contiguity, no " + "offset_end was set on previous buffer"); + } + } +} + +static void +gst_identity_check_imperfect_offset (GstIdentity * identity, GstBuffer * buf) +{ + guint64 offset; + + offset = GST_BUFFER_OFFSET (buf); + + if (identity->prev_offset_end != offset && + identity->prev_offset_end != GST_BUFFER_OFFSET_NONE && + offset != GST_BUFFER_OFFSET_NONE) { + /* + * "imperfect-offset" bus message: + * @identity: the identity instance + * @prev-timestamp: the previous buffer timestamp + * @prev-duration: the previous buffer duration + * @prev-offset: the previous buffer offset + * @prev-offset-end: the previous buffer offset end + * @cur-timestamp: the current buffer timestamp + * @cur-duration: the current buffer duration + * @cur-offset: the current buffer offset + * @cur-offset-end: the current buffer offset end + * + * This bus message gets emitted if the check-imperfect-offset + * property is set and there is a gap in offsets between the + * last buffer and the newly received buffer. + */ + gst_element_post_message (GST_ELEMENT (identity), + gst_message_new_element (GST_OBJECT (identity), + gst_structure_new ("imperfect-offset", "prev-timestamp", + G_TYPE_UINT64, identity->prev_timestamp, "prev-duration", + G_TYPE_UINT64, identity->prev_duration, "prev-offset", + G_TYPE_UINT64, identity->prev_offset, "prev-offset-end", + G_TYPE_UINT64, identity->prev_offset_end, "cur-timestamp", + G_TYPE_UINT64, GST_BUFFER_TIMESTAMP (buf), "cur-duration", + G_TYPE_UINT64, GST_BUFFER_DURATION (buf), "cur-offset", + G_TYPE_UINT64, GST_BUFFER_OFFSET (buf), "cur-offset-end", + G_TYPE_UINT64, GST_BUFFER_OFFSET_END (buf), NULL))); + } else { + GST_DEBUG_OBJECT (identity, "can't check offset contiguity, no offset " + "and/or offset_end were set on previous buffer"); + } +} + +static const gchar * +print_pretty_time (gchar * ts_str, gsize ts_str_len, GstClockTime ts) +{ + if (ts == GST_CLOCK_TIME_NONE) + return "none"; + + g_snprintf (ts_str, ts_str_len, "%" GST_TIME_FORMAT, GST_TIME_ARGS (ts)); + return ts_str; +} + +static void +gst_identity_update_last_message_for_buffer (GstIdentity * identity, + const gchar * action, GstBuffer * buf, gsize size) +{ + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar *flag_str, *meta_str; + + GST_OBJECT_LOCK (identity); + + flag_str = gst_buffer_get_flags_string (buf); + meta_str = gst_buffer_get_meta_string (buf); + + g_free (identity->last_message); + identity->last_message = g_strdup_printf ("%s ******* (%s:%s) " + "(%" G_GSIZE_FORMAT " bytes, dts: %s, pts: %s, duration: %s, offset: %" + G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT + ", flags: %08x %s, meta: %s) %p", action, + GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size, + print_pretty_time (dts_str, sizeof (dts_str), GST_BUFFER_DTS (buf)), + print_pretty_time (pts_str, sizeof (pts_str), GST_BUFFER_PTS (buf)), + print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_BUFFER_FLAGS (buf), flag_str, meta_str ? meta_str : "none", buf); + g_free (flag_str); + + GST_OBJECT_UNLOCK (identity); + + gst_identity_notify_last_message (identity); +} + +static GstFlowReturn +gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstIdentity *identity = GST_IDENTITY (trans); + GstClockTime rundts = GST_CLOCK_TIME_NONE; + GstClockTime runpts = GST_CLOCK_TIME_NONE; + GstClockTime ts, duration, runtimestamp; + gsize size; + + size = gst_buffer_get_size (buf); + + if (identity->check_imperfect_timestamp) + gst_identity_check_imperfect_timestamp (identity, buf); + if (identity->check_imperfect_offset) + gst_identity_check_imperfect_offset (identity, buf); + + /* update prev values */ + identity->prev_timestamp = GST_BUFFER_TIMESTAMP (buf); + identity->prev_duration = GST_BUFFER_DURATION (buf); + identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf); + identity->prev_offset = GST_BUFFER_OFFSET (buf); + + if (identity->error_after >= 0) { + identity->error_after--; + if (identity->error_after == 0) + goto error_after; + } + + if (identity->drop_probability > 0.0) { + if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) + goto dropped; + } + + if (GST_BUFFER_FLAG_IS_SET (buf, identity->drop_buffer_flags)) + goto dropped; + + if (identity->dump) { + GstMapInfo info; + + if (gst_buffer_map (buf, &info, GST_MAP_READ)) { + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); + } + } + + if (!identity->silent) { + gst_identity_update_last_message_for_buffer (identity, "chain", buf, size); + } + + if (identity->datarate > 0) { + GstClockTime time = gst_util_uint64_scale_int (identity->offset, + GST_SECOND, identity->datarate); + + GST_BUFFER_PTS (buf) = GST_BUFFER_DTS (buf) = time; + GST_BUFFER_DURATION (buf) = size * GST_SECOND / identity->datarate; + } + + if (identity->signal_handoffs) + g_signal_emit (identity, gst_identity_signals[SIGNAL_HANDOFF], 0, buf); + + if (trans->segment.format == GST_FORMAT_TIME) { + rundts = gst_segment_to_running_time (&trans->segment, + GST_FORMAT_TIME, GST_BUFFER_DTS (buf)); + runpts = gst_segment_to_running_time (&trans->segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buf)); + } + + if (GST_CLOCK_TIME_IS_VALID (rundts)) + runtimestamp = rundts; + else if (GST_CLOCK_TIME_IS_VALID (runpts)) + runtimestamp = runpts; + else + runtimestamp = 0; + ret = gst_identity_do_sync (identity, runtimestamp); + + identity->offset += size; + + if (identity->sleep_time && ret == GST_FLOW_OK) + g_usleep (identity->sleep_time); + + if (identity->single_segment && (trans->segment.format == GST_FORMAT_TIME) + && (ret == GST_FLOW_OK)) { + GST_BUFFER_DTS (buf) = rundts; + GST_BUFFER_PTS (buf) = runpts; + GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE; + } + + return ret; + + /* ERRORS */ +error_after: + { + GST_ELEMENT_ERROR (identity, CORE, FAILED, + (_("Failed after iterations as requested.")), (NULL)); + return GST_FLOW_ERROR; + } +dropped: + { + if (!identity->silent) { + gst_identity_update_last_message_for_buffer (identity, "dropping", buf, + size); + } + + ts = GST_BUFFER_TIMESTAMP (buf); + if (GST_CLOCK_TIME_IS_VALID (ts)) { + duration = GST_BUFFER_DURATION (buf); + gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (identity), + gst_event_new_gap (ts, duration)); + } + + /* return DROPPED to basetransform. */ + return GST_BASE_TRANSFORM_FLOW_DROPPED; + } +} + +static void +gst_identity_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstIdentity *identity; + + identity = GST_IDENTITY (object); + + switch (prop_id) { + case PROP_SLEEP_TIME: + identity->sleep_time = g_value_get_uint (value); + break; + case PROP_SILENT: + identity->silent = g_value_get_boolean (value); + break; + case PROP_SINGLE_SEGMENT: + identity->single_segment = g_value_get_boolean (value); + break; + case PROP_DUMP: + identity->dump = g_value_get_boolean (value); + break; + case PROP_ERROR_AFTER: + identity->error_after = g_value_get_int (value); + break; + case PROP_DROP_PROBABILITY: + identity->drop_probability = g_value_get_float (value); + break; + case PROP_DROP_BUFFER_FLAGS: + identity->drop_buffer_flags = g_value_get_flags (value); + break; + case PROP_DATARATE: + identity->datarate = g_value_get_int (value); + break; + case PROP_SYNC: + identity->sync = g_value_get_boolean (value); + break; + case PROP_TS_OFFSET: + identity->ts_offset = g_value_get_int64 (value); + break; + case PROP_CHECK_IMPERFECT_TIMESTAMP: + identity->check_imperfect_timestamp = g_value_get_boolean (value); + break; + case PROP_CHECK_IMPERFECT_OFFSET: + identity->check_imperfect_offset = g_value_get_boolean (value); + break; + case PROP_SIGNAL_HANDOFFS: + identity->signal_handoffs = g_value_get_boolean (value); + break; + case PROP_DROP_ALLOCATION: + identity->drop_allocation = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + if (identity->datarate > 0 || identity->single_segment) + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), FALSE); + else + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE); +} + +static void +gst_identity_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstIdentity *identity; + + identity = GST_IDENTITY (object); + + switch (prop_id) { + case PROP_SLEEP_TIME: + g_value_set_uint (value, identity->sleep_time); + break; + case PROP_ERROR_AFTER: + g_value_set_int (value, identity->error_after); + break; + case PROP_DROP_PROBABILITY: + g_value_set_float (value, identity->drop_probability); + break; + case PROP_DROP_BUFFER_FLAGS: + g_value_set_flags (value, identity->drop_buffer_flags); + break; + case PROP_DATARATE: + g_value_set_int (value, identity->datarate); + break; + case PROP_SILENT: + g_value_set_boolean (value, identity->silent); + break; + case PROP_SINGLE_SEGMENT: + g_value_set_boolean (value, identity->single_segment); + break; + case PROP_DUMP: + g_value_set_boolean (value, identity->dump); + break; + case PROP_LAST_MESSAGE: + GST_OBJECT_LOCK (identity); + g_value_set_string (value, identity->last_message); + GST_OBJECT_UNLOCK (identity); + break; + case PROP_SYNC: + g_value_set_boolean (value, identity->sync); + break; + case PROP_TS_OFFSET: + identity->ts_offset = g_value_get_int64 (value); + break; + case PROP_CHECK_IMPERFECT_TIMESTAMP: + g_value_set_boolean (value, identity->check_imperfect_timestamp); + break; + case PROP_CHECK_IMPERFECT_OFFSET: + g_value_set_boolean (value, identity->check_imperfect_offset); + break; + case PROP_SIGNAL_HANDOFFS: + g_value_set_boolean (value, identity->signal_handoffs); + break; + case PROP_DROP_ALLOCATION: + g_value_set_boolean (value, identity->drop_allocation); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_identity_start (GstBaseTransform * trans) +{ + GstIdentity *identity; + + identity = GST_IDENTITY (trans); + + identity->offset = 0; + identity->prev_timestamp = GST_CLOCK_TIME_NONE; + identity->prev_duration = GST_CLOCK_TIME_NONE; + identity->prev_offset_end = GST_BUFFER_OFFSET_NONE; + identity->prev_offset = GST_BUFFER_OFFSET_NONE; + + return TRUE; +} + +static gboolean +gst_identity_stop (GstBaseTransform * trans) +{ + GstIdentity *identity; + + identity = GST_IDENTITY (trans); + + GST_OBJECT_LOCK (identity); + g_free (identity->last_message); + identity->last_message = NULL; + GST_OBJECT_UNLOCK (identity); + + return TRUE; +} + +static gboolean +gst_identity_accept_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) +{ + gboolean ret; + GstPad *pad; + + /* Proxy accept-caps */ + + if (direction == GST_PAD_SRC) + pad = GST_BASE_TRANSFORM_SINK_PAD (base); + else + pad = GST_BASE_TRANSFORM_SRC_PAD (base); + + ret = gst_pad_peer_query_accept_caps (pad, caps); + + return ret; +} + +static gboolean +gst_identity_query (GstBaseTransform * base, GstPadDirection direction, + GstQuery * query) +{ + GstIdentity *identity; + gboolean ret; + + identity = GST_IDENTITY (base); + + if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION && + identity->drop_allocation) { + GST_DEBUG_OBJECT (identity, "Dropping allocation query."); + return FALSE; + } + + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->query (base, direction, query); + + if (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY) { + gboolean live = FALSE; + GstClockTime min = 0, max = 0; + + if (ret) { + gst_query_parse_latency (query, &live, &min, &max); + + if (identity->sync && max < min) { + GST_ELEMENT_WARNING (base, CORE, CLOCK, (NULL), + ("Impossible to configure latency before identity sync=true:" + " max %" GST_TIME_FORMAT " < min %" + GST_TIME_FORMAT ". Add queues or other buffering elements.", + GST_TIME_ARGS (max), GST_TIME_ARGS (min))); + } + } + + /* Ignore the upstream latency if it is not live */ + GST_OBJECT_LOCK (identity); + if (live) + identity->upstream_latency = min; + else + identity->upstream_latency = 0; + GST_OBJECT_UNLOCK (identity); + + gst_query_set_latency (query, live || identity->sync, min, max); + ret = TRUE; + } + return ret; +} + +static GstStateChangeReturn +gst_identity_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstIdentity *identity = GST_IDENTITY (element); + gboolean no_preroll = FALSE; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_OBJECT_LOCK (identity); + identity->flushing = FALSE; + identity->blocked = TRUE; + GST_OBJECT_UNLOCK (identity); + if (identity->sync) + no_preroll = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_OBJECT_LOCK (identity); + identity->blocked = FALSE; + g_cond_broadcast (&identity->blocked_cond); + GST_OBJECT_UNLOCK (identity); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_OBJECT_LOCK (identity); + identity->flushing = TRUE; + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + } + identity->blocked = FALSE; + g_cond_broadcast (&identity->blocked_cond); + GST_OBJECT_UNLOCK (identity); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_OBJECT_LOCK (identity); + identity->upstream_latency = 0; + identity->blocked = TRUE; + GST_OBJECT_UNLOCK (identity); + if (identity->sync) + no_preroll = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + if (no_preroll && ret == GST_STATE_CHANGE_SUCCESS) + ret = GST_STATE_CHANGE_NO_PREROLL; + + return ret; +} diff --git a/plugins/elements/gstidentity.h b/plugins/elements/gstidentity.h new file mode 100644 index 0000000..e902732 --- /dev/null +++ b/plugins/elements/gstidentity.h @@ -0,0 +1,95 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstidentity.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_IDENTITY_H__ +#define __GST_IDENTITY_H__ + + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_IDENTITY \ + (gst_identity_get_type()) +#define GST_IDENTITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IDENTITY,GstIdentity)) +#define GST_IDENTITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IDENTITY,GstIdentityClass)) +#define GST_IS_IDENTITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IDENTITY)) +#define GST_IS_IDENTITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY)) + +typedef struct _GstIdentity GstIdentity; +typedef struct _GstIdentityClass GstIdentityClass; + +/** + * GstIdentity: + * + * Opaque #GstIdentity data structure + */ +struct _GstIdentity { + GstBaseTransform element; + + /*< private >*/ + GstClockID clock_id; + gboolean flushing; + gint error_after; + gfloat drop_probability; + gint datarate; + guint sleep_time; + gboolean silent; + gboolean dump; + gboolean sync; + gboolean check_imperfect_timestamp; + gboolean check_imperfect_offset; + gboolean single_segment; + GstBufferFlags drop_buffer_flags; + GstClockTime prev_timestamp; + GstClockTime prev_duration; + guint64 prev_offset; + guint64 prev_offset_end; + gchar *last_message; + guint64 offset; + gboolean signal_handoffs; + GstClockTime upstream_latency; + GCond blocked_cond; + gboolean blocked; + GstClockTimeDiff ts_offset; + gboolean drop_allocation; +}; + +struct _GstIdentityClass { + GstBaseTransformClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element, GstBuffer *buf); +}; + +G_GNUC_INTERNAL GType gst_identity_get_type (void); + +G_END_DECLS + +#endif /* __GST_IDENTITY_H__ */ diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c new file mode 100644 index 0000000..e157d5c --- /dev/null +++ b/plugins/elements/gstinputselector.c @@ -0,0 +1,1746 @@ +/* GStreamer input selector + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2005 Jan Schmidt + * Copyright (C) 2007 Wim Taymans + * Copyright (C) 2007 Andy Wingo + * Copyright (C) 2008 Nokia Corporation. (contact ) + * Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-input-selector + * @title: input-selector + * @see_also: #GstOutputSelector + * + * Direct one out of N input streams to the output pad. + * + * The input pads are from a GstPad subclass and have additional + * properties, which users may find useful, namely: + * + * * "running-time": Running time of stream on pad (#gint64) + * * "tags": The currently active tags on the pad (#GstTagList, boxed type) + * * "active": If the pad is currently active (#gboolean) + * * "always-ok" : Make an inactive pads return #GST_FLOW_OK instead of + * #GST_FLOW_NOT_LINKED + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstinputselector.h" + +#define DEBUG_CACHED_BUFFERS 0 + +GST_DEBUG_CATEGORY_STATIC (input_selector_debug); +#define GST_CAT_DEFAULT input_selector_debug + +#define GST_TYPE_INPUT_SELECTOR_SYNC_MODE (gst_input_selector_sync_mode_get_type()) +static GType +gst_input_selector_sync_mode_get_type (void) +{ + static GType type = 0; + static const GEnumValue data[] = { + {GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT, + "Sync using the current active segment", + "active-segment"}, + {GST_INPUT_SELECTOR_SYNC_MODE_CLOCK, "Sync using the clock", "clock"}, + {0, NULL, NULL}, + }; + + if (!type) { + type = g_enum_register_static ("GstInputSelectorSyncMode", data); + } + return type; +} + +#define GST_INPUT_SELECTOR_GET_LOCK(sel) (&((GstInputSelector*)(sel))->lock) +#define GST_INPUT_SELECTOR_GET_COND(sel) (&((GstInputSelector*)(sel))->cond) +#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ + GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) + +static GstStaticPadTemplate gst_input_selector_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_input_selector_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_N_PADS, + PROP_ACTIVE_PAD, + PROP_SYNC_STREAMS, + PROP_SYNC_MODE, + PROP_CACHE_BUFFERS +}; + +#define DEFAULT_SYNC_STREAMS TRUE +#define DEFAULT_SYNC_MODE GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT +#define DEFAULT_CACHE_BUFFERS FALSE +#define DEFAULT_PAD_ALWAYS_OK TRUE + +enum +{ + PROP_PAD_0, + PROP_PAD_RUNNING_TIME, + PROP_PAD_TAGS, + PROP_PAD_ACTIVE, + PROP_PAD_ALWAYS_OK +}; + +static void gst_input_selector_active_pad_changed (GstInputSelector * sel, + GParamSpec * pspec, gpointer user_data); +static inline gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * + sel, GstPad * pad); +static GstPad *gst_input_selector_get_active_sinkpad (GstInputSelector * sel); +static GstPad *gst_input_selector_get_linked_pad (GstInputSelector * sel, + 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; +typedef struct _GstSelectorPadCachedBuffer GstSelectorPadCachedBuffer; + +struct _GstSelectorPad +{ + GstPad parent; + + gboolean pushed; /* when buffer was pushed downstream since activation */ + guint group_id; /* Group ID from the last stream-start */ + gboolean group_done; /* when Stream Group Done has been + received */ + gboolean eos; /* when EOS has been received */ + gboolean eos_sent; /* when EOS was sent downstream */ + gboolean discont; /* after switching we create a discont */ + gboolean flushing; /* set after flush-start and before flush-stop */ + gboolean always_ok; + GstTagList *tags; /* last tags received on the pad */ + + GstSegment segment; /* the current segment on the pad */ + guint32 segment_seqnum; /* sequence number of the current segment */ + + gboolean events_pending; /* TRUE if sticky events need to be updated */ + + gboolean sending_cached_buffers; + GQueue *cached_buffers; +}; + +struct _GstSelectorPadCachedBuffer +{ + GstBuffer *buffer; + GstSegment segment; +}; + +struct _GstSelectorPadClass +{ + GstPadClass parent; +}; + +GType gst_selector_pad_get_type (void); +static void gst_selector_pad_finalize (GObject * object); +static void gst_selector_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_selector_pad_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); + +static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); +static void gst_selector_pad_reset (GstSelectorPad * pad); +static gboolean gst_selector_pad_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_selector_pad_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad, + GstObject * parent); +static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstObject * parent, + GstBuffer * buf); +static void gst_selector_pad_cache_buffer (GstSelectorPad * selpad, + GstBuffer * buffer); +static void gst_selector_pad_free_cached_buffers (GstSelectorPad * selpad); + +G_DEFINE_TYPE (GstSelectorPad, gst_selector_pad, GST_TYPE_PAD); + +static void +gst_selector_pad_class_init (GstSelectorPadClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = gst_selector_pad_finalize; + + gobject_class->get_property = gst_selector_pad_get_property; + gobject_class->set_property = gst_selector_pad_set_property; + + g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME, + g_param_spec_int64 ("running-time", "Running time", + "Running time of stream on pad", 0, G_MAXINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + 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)); + /* FIXME: better property name? */ + g_object_class_install_property (gobject_class, PROP_PAD_ALWAYS_OK, + g_param_spec_boolean ("always-ok", "Always OK", + "Make an inactive pad return OK instead of NOT_LINKED", + DEFAULT_PAD_ALWAYS_OK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_selector_pad_init (GstSelectorPad * pad) +{ + pad->always_ok = DEFAULT_PAD_ALWAYS_OK; + gst_selector_pad_reset (pad); +} + +static void +gst_selector_pad_finalize (GObject * object) +{ + GstSelectorPad *pad; + + pad = GST_SELECTOR_PAD_CAST (object); + + if (pad->tags) + gst_tag_list_unref (pad->tags); + gst_selector_pad_free_cached_buffers (pad); + + G_OBJECT_CLASS (gst_selector_pad_parent_class)->finalize (object); +} + +static void +gst_selector_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); + + switch (prop_id) { + case PROP_PAD_ALWAYS_OK: + GST_OBJECT_LOCK (object); + spad->always_ok = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_selector_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); + + switch (prop_id) { + case PROP_PAD_RUNNING_TIME: + g_value_set_int64 (value, gst_selector_pad_get_running_time (spad)); + break; + case PROP_PAD_TAGS: + GST_OBJECT_LOCK (object); + g_value_set_boxed (value, spad->tags); + GST_OBJECT_UNLOCK (object); + break; + case PROP_PAD_ACTIVE: + { + GstInputSelector *sel; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (spad)); + if (sel) { + g_value_set_boolean (value, gst_input_selector_is_active_sinkpad (sel, + GST_PAD_CAST (spad))); + gst_object_unref (sel); + } else { + g_value_set_boolean (value, FALSE); + } + break; + } + case PROP_PAD_ALWAYS_OK: + GST_OBJECT_LOCK (object); + g_value_set_boolean (value, spad->always_ok); + GST_OBJECT_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gint64 +gst_selector_pad_get_running_time (GstSelectorPad * pad) +{ + gint64 ret = 0; + + GST_OBJECT_LOCK (pad); + if (pad->segment.format == GST_FORMAT_TIME) { + ret = + gst_segment_to_running_time (&pad->segment, pad->segment.format, + pad->segment.position); + } + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pad, "running time: %" GST_TIME_FORMAT + " segment: %" GST_SEGMENT_FORMAT, GST_TIME_ARGS (ret), &pad->segment); + + return ret; +} + +/* must be called with the SELECTOR_LOCK */ +static void +gst_selector_pad_reset (GstSelectorPad * pad) +{ + GST_OBJECT_LOCK (pad); + pad->pushed = FALSE; + pad->group_done = FALSE; + pad->eos = FALSE; + pad->eos_sent = FALSE; + pad->events_pending = FALSE; + pad->discont = FALSE; + pad->flushing = FALSE; + gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED); + pad->sending_cached_buffers = FALSE; + gst_selector_pad_free_cached_buffers (pad); + GST_OBJECT_UNLOCK (pad); +} + +static GstSelectorPadCachedBuffer * +gst_selector_pad_new_cached_buffer (GstSelectorPad * selpad, GstBuffer * buffer) +{ + GstSelectorPadCachedBuffer *cached_buffer = + g_slice_new (GstSelectorPadCachedBuffer); + cached_buffer->buffer = buffer; + cached_buffer->segment = selpad->segment; + return cached_buffer; +} + +static void +gst_selector_pad_free_cached_buffer (GstSelectorPadCachedBuffer * cached_buffer) +{ + if (cached_buffer->buffer) + gst_buffer_unref (cached_buffer->buffer); + g_slice_free (GstSelectorPadCachedBuffer, cached_buffer); +} + +/* must be called with the SELECTOR_LOCK */ +static void +gst_selector_pad_cache_buffer (GstSelectorPad * selpad, GstBuffer * buffer) +{ + if (selpad->segment.format != GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (selpad, "Buffer %p with segment not in time format, " + "not caching", buffer); + gst_buffer_unref (buffer); + return; + } + + GST_DEBUG_OBJECT (selpad, "Caching buffer %p", buffer); + if (!selpad->cached_buffers) + selpad->cached_buffers = g_queue_new (); + g_queue_push_tail (selpad->cached_buffers, + gst_selector_pad_new_cached_buffer (selpad, buffer)); +} + +/* must be called with the SELECTOR_LOCK */ +static void +gst_selector_pad_free_cached_buffers (GstSelectorPad * selpad) +{ + if (!selpad->cached_buffers) + return; + + GST_DEBUG_OBJECT (selpad, "Freeing cached buffers"); + g_queue_free_full (selpad->cached_buffers, + (GDestroyNotify) gst_selector_pad_free_cached_buffer); + selpad->cached_buffers = NULL; +} + +/* strictly get the linked pad from the sinkpad. If the pad is active we return + * the srcpad else we return NULL */ +static GstIterator * +gst_selector_pad_iterate_linked_pads (GstPad * pad, GstObject * parent) +{ + GstInputSelector *sel; + GstPad *otherpad; + GstIterator *it = NULL; + GValue val = { 0, }; + + sel = GST_INPUT_SELECTOR (parent); + + otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE); + if (otherpad) { + g_value_init (&val, GST_TYPE_PAD); + g_value_set_object (&val, otherpad); + it = gst_iterator_new_single (GST_TYPE_PAD, &val); + g_value_unset (&val); + gst_object_unref (otherpad); + } + + return it; +} + +static gboolean +forward_sticky_events (GstPad * sinkpad, GstEvent ** event, gpointer user_data) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (user_data); + + GST_DEBUG_OBJECT (sinkpad, "forward sticky event %" GST_PTR_FORMAT, *event); + + if (GST_EVENT_TYPE (*event) == GST_EVENT_SEGMENT) { + GstSegment *seg = &GST_SELECTOR_PAD (sinkpad)->segment; + GstEvent *e; + + e = gst_event_new_segment (seg); + gst_event_set_seqnum (e, GST_SELECTOR_PAD_CAST (sinkpad)->segment_seqnum); + + gst_pad_push_event (sel->srcpad, e); + } else if (GST_EVENT_TYPE (*event) == GST_EVENT_STREAM_START + && !sel->have_group_id) { + GstEvent *tmp = + gst_pad_get_sticky_event (sel->srcpad, GST_EVENT_STREAM_START, 0); + + /* Only push stream-start once if not all our streams have a stream-id */ + if (!tmp) { + gst_pad_push_event (sel->srcpad, gst_event_ref (*event)); + } else { + gst_event_unref (tmp); + } + } else { + gst_pad_push_event (sel->srcpad, gst_event_ref (*event)); + } + + return TRUE; +} + +static gboolean +gst_input_selector_eos_wait (GstInputSelector * self, GstSelectorPad * pad, + GstEvent * eos_event) +{ + while (!self->eos && !self->flushing && !pad->flushing) { + GstPad *active_sinkpad; + active_sinkpad = gst_input_selector_get_active_sinkpad (self); + if (pad == GST_SELECTOR_PAD_CAST (active_sinkpad) && pad->eos + && !pad->eos_sent) { + GST_DEBUG_OBJECT (pad, "send EOS event"); + GST_INPUT_SELECTOR_UNLOCK (self); + /* if we have a pending events, push them now */ + if (pad->events_pending) { + gst_pad_sticky_events_foreach (GST_PAD_CAST (pad), + forward_sticky_events, self); + pad->events_pending = FALSE; + } + + gst_pad_push_event (self->srcpad, gst_event_ref (eos_event)); + GST_INPUT_SELECTOR_LOCK (self); + /* Wake up other pads so they can continue when syncing to + * running time, as this pad just switched to EOS and + * may enable others to progress */ + GST_INPUT_SELECTOR_BROADCAST (self); + pad->eos_sent = TRUE; + } else { + /* we can be unlocked here when we are shutting down (flushing) or when we + * get unblocked */ + GST_INPUT_SELECTOR_WAIT (self); + } + } + + return self->flushing; +} + +static gboolean +gst_input_selector_all_eos (GstInputSelector * sel) +{ + GList *walk; + + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) { + GstSelectorPad *selpad; + + selpad = GST_SELECTOR_PAD_CAST (walk->data); + if (!selpad->eos) { + return FALSE; + } + + } + + return TRUE; +} + +static gboolean +gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + gboolean forward; + gboolean new_tags = FALSE; + GstInputSelector *sel; + GstSelectorPad *selpad; + GstPad *prev_active_sinkpad; + GstPad *active_sinkpad; + + sel = GST_INPUT_SELECTOR (parent); + selpad = GST_SELECTOR_PAD_CAST (pad); + GST_DEBUG_OBJECT (selpad, "received event %" GST_PTR_FORMAT, event); + + GST_INPUT_SELECTOR_LOCK (sel); + prev_active_sinkpad = + sel->active_sinkpad ? gst_object_ref (sel->active_sinkpad) : NULL; + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + gst_object_ref (active_sinkpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (prev_active_sinkpad != active_sinkpad) { + if (prev_active_sinkpad) + g_object_notify (G_OBJECT (prev_active_sinkpad), "active"); + g_object_notify (G_OBJECT (active_sinkpad), "active"); + g_object_notify (G_OBJECT (sel), "active-pad"); + } + if (prev_active_sinkpad) + gst_object_unref (prev_active_sinkpad); + gst_object_unref (active_sinkpad); + + GST_INPUT_SELECTOR_LOCK (sel); + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + + /* only forward if we are dealing with the active sinkpad */ + forward = (pad == active_sinkpad); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START:{ + if (!gst_event_parse_group_id (event, &selpad->group_id)) { + sel->have_group_id = FALSE; + selpad->group_id = 0; + } + break; + } + case GST_EVENT_FLUSH_START: + /* Unblock the pad if it's waiting */ + selpad->flushing = TRUE; + sel->eos = FALSE; + selpad->group_done = FALSE; + GST_INPUT_SELECTOR_BROADCAST (sel); + break; + case GST_EVENT_FLUSH_STOP: + gst_selector_pad_reset (selpad); + break; + case GST_EVENT_SEGMENT: + { + gst_event_copy_segment (event, &selpad->segment); + selpad->segment_seqnum = gst_event_get_seqnum (event); + + GST_DEBUG_OBJECT (pad, "configured SEGMENT %" GST_SEGMENT_FORMAT, + &selpad->segment); + break; + } + case GST_EVENT_TAG: + { + GstTagList *tags, *oldtags, *newtags; + + gst_event_parse_tag (event, &tags); + + GST_OBJECT_LOCK (selpad); + oldtags = selpad->tags; + + newtags = gst_tag_list_merge (oldtags, tags, GST_TAG_MERGE_REPLACE); + selpad->tags = newtags; + GST_OBJECT_UNLOCK (selpad); + + if (oldtags) + gst_tag_list_unref (oldtags); + GST_DEBUG_OBJECT (pad, "received tags %" GST_PTR_FORMAT, newtags); + + new_tags = TRUE; + break; + } + case GST_EVENT_EOS: + selpad->eos = TRUE; + GST_DEBUG_OBJECT (pad, "received EOS"); + if (gst_input_selector_all_eos (sel)) { + GST_DEBUG_OBJECT (pad, "All sink pad received EOS"); + sel->eos = TRUE; + GST_INPUT_SELECTOR_BROADCAST (sel); + } else { + gst_input_selector_eos_wait (sel, selpad, event); + forward = FALSE; + } + break; + case GST_EVENT_GAP:{ + GstClockTime ts, dur; + + GST_DEBUG_OBJECT (pad, "Received gap event: %" GST_PTR_FORMAT, event); + + gst_event_parse_gap (event, &ts, &dur); + if (GST_CLOCK_TIME_IS_VALID (ts)) { + if (GST_CLOCK_TIME_IS_VALID (dur)) + ts += dur; + + /* update the segment position */ + GST_OBJECT_LOCK (pad); + selpad->segment.position = ts; + GST_OBJECT_UNLOCK (pad); + if (sel->sync_streams && active_sinkpad == pad) + GST_INPUT_SELECTOR_BROADCAST (sel); + } + + } + break; + case GST_EVENT_STREAM_GROUP_DONE:{ + GST_DEBUG_OBJECT (sel, "Stream group-done in inputselector pad %s", + GST_OBJECT_NAME (selpad)); + gst_event_parse_stream_group_done (event, &selpad->group_id); + selpad->group_done = TRUE; + if (sel->sync_streams && active_sinkpad == pad) + GST_INPUT_SELECTOR_BROADCAST (sel); + break; + } + default: + break; + } + GST_INPUT_SELECTOR_UNLOCK (sel); + if (new_tags) + g_object_notify (G_OBJECT (selpad), "tags"); + if (forward) { + GST_DEBUG_OBJECT (pad, "forwarding event"); + res = gst_pad_push_event (sel->srcpad, event); + } else { + /* If we aren't forwarding the event because the pad is not the + * active_sinkpad, then set the flag on the pad + * that says a segment needs sending if/when that pad is activated. + * For all other cases, we send the event immediately, which makes + * sparse streams and other segment updates work correctly downstream. + */ + if (GST_EVENT_IS_STICKY (event)) + selpad->events_pending = TRUE; + gst_event_unref (event); + } + + return res; +} + +static gboolean +gst_selector_pad_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = FALSE; + GstInputSelector *self = (GstInputSelector *) parent; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + case GST_QUERY_POSITION: + case GST_QUERY_DURATION: + /* always proxy caps/position/duration query, regardless of active pad or not + * See https://bugzilla.gnome.org/show_bug.cgi?id=775445 */ + res = gst_pad_peer_query (self->srcpad, query); + break; + case GST_QUERY_ALLOCATION:{ + GstPad *active_sinkpad; + GstInputSelector *sel = GST_INPUT_SELECTOR (parent); + + /* Only do the allocation query for the active sinkpad, + * after switching a reconfigure event is sent and upstream + * should reconfigure and do a new allocation query + */ + if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) { + GST_INPUT_SELECTOR_LOCK (sel); + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (pad != active_sinkpad) { + res = FALSE; + goto done; + } + } + } + /* fall through */ + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + +done: + return res; +} + +static GstClockTime +gst_input_selector_get_clipped_running_time (GstSegment * seg, GstBuffer * buf) +{ + GstClockTime running_time; + + running_time = GST_BUFFER_PTS (buf); + /* If possible try to get the running time at the end of the buffer */ + if (GST_BUFFER_DURATION_IS_VALID (buf)) + running_time += GST_BUFFER_DURATION (buf); + /* Only use the segment to convert to running time if the segment is + * in TIME format, otherwise do our best to try to sync */ + if (GST_CLOCK_TIME_IS_VALID (seg->stop)) { + if (running_time > seg->stop) { + running_time = seg->stop; + } + } + return gst_segment_to_running_time (seg, GST_FORMAT_TIME, running_time); +} + +/* must be called without the SELECTOR_LOCK, will wait until the running time + * of the active pad is after this pad or return TRUE when flushing */ +static gboolean +gst_input_selector_wait_running_time (GstInputSelector * sel, + GstSelectorPad * selpad, GstBuffer * buf) +{ + GstSegment *seg; + + GST_DEBUG_OBJECT (selpad, "entering wait for buffer %p", buf); + + /* If we have no valid timestamp we can't sync this buffer */ + if (!GST_BUFFER_PTS_IS_VALID (buf)) { + GST_DEBUG_OBJECT (selpad, "leaving wait for buffer with " + "invalid timestamp"); + return FALSE; + } + + seg = &selpad->segment; + + /* Wait until + * a) this is the active pad + * b) the pad or the selector is flushing + * c) the buffer running time is before the current running time + * (either active-seg or clock, depending on sync-mode) + */ + + GST_INPUT_SELECTOR_LOCK (sel); + while (TRUE) { + GstPad *active_sinkpad; + GstSelectorPad *active_selpad; + GstClock *clock; + gint64 cur_running_time; + GstClockTime running_time; + + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad); + + if (seg->format != GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (selpad, + "Not waiting because we don't have a TIME segment"); + GST_INPUT_SELECTOR_UNLOCK (sel); + return FALSE; + } + + running_time = gst_input_selector_get_clipped_running_time (seg, buf); + /* If this is outside the segment don't sync */ + if (running_time == -1) { + GST_DEBUG_OBJECT (selpad, + "Not waiting because buffer is outside segment"); + GST_INPUT_SELECTOR_UNLOCK (sel); + return FALSE; + } + + cur_running_time = GST_CLOCK_TIME_NONE; + if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK) { + clock = gst_element_get_clock (GST_ELEMENT_CAST (sel)); + if (clock) { + GstClockTime base_time; + + cur_running_time = gst_clock_get_time (clock); + base_time = gst_element_get_base_time (GST_ELEMENT_CAST (sel)); + if (base_time <= cur_running_time) + cur_running_time -= base_time; + else + cur_running_time = 0; + + gst_object_unref (clock); + } + } else { + GstSegment *active_seg; + + active_seg = &active_selpad->segment; + + /* If the active segment is configured but not to time format + * we can't do any syncing at all */ + if ((active_seg->format != GST_FORMAT_TIME + && active_seg->format != GST_FORMAT_UNDEFINED)) { + GST_DEBUG_OBJECT (selpad, + "Not waiting because active segment isn't in TIME format"); + GST_INPUT_SELECTOR_UNLOCK (sel); + return FALSE; + } + + /* Get active pad's running time, if no configured segment yet keep at -1 */ + if (active_seg->format == GST_FORMAT_TIME) + cur_running_time = gst_segment_to_running_time (active_seg, + GST_FORMAT_TIME, active_seg->position); + } + + /* Don't wait if the group is finished on the active pad, + * as the running time won't progress now */ + if (selpad != active_selpad && active_selpad->group_done && + selpad->group_id == active_selpad->group_id) { + GST_DEBUG_OBJECT (selpad, "Active pad received group-done. Unblocking"); + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + } + + if (selpad != active_selpad && !sel->eos && !sel->flushing + && !selpad->flushing && (cur_running_time == GST_CLOCK_TIME_NONE + || running_time >= cur_running_time)) { + GST_DEBUG_OBJECT (selpad, + "Waiting for active streams to advance. %" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT, GST_TIME_ARGS (running_time), + GST_TIME_ARGS (cur_running_time)); + GST_INPUT_SELECTOR_WAIT (sel); + } else { + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + } + } + + /* Return TRUE if the selector or the pad is flushing */ + return (sel->flushing || selpad->flushing); +} + +#if DEBUG_CACHED_BUFFERS +static void +gst_input_selector_debug_cached_buffers (GstInputSelector * sel) +{ + GList *walk; + + if (gst_debug_category_get_threshold (input_selector_debug) < GST_LEVEL_DEBUG) + return; + + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = walk->next) { + GstSelectorPad *selpad; + GString *timestamps; + GList *l; + + selpad = GST_SELECTOR_PAD_CAST (walk->data); + if (!selpad->cached_buffers) { + GST_DEBUG_OBJECT (selpad, "Cached buffers timestamps: "); + continue; + } + + timestamps = g_string_new ("Cached buffers timestamps:"); + for (l = selpad->cached_buffers->head; l != NULL; l = l->next) { + GstSelectorPadCachedBuffer *cached_buffer = l->data; + + g_string_append_printf (timestamps, " %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (cached_buffer->buffer))); + } + GST_DEBUG_OBJECT (selpad, "%s", timestamps->str); + g_string_free (timestamps, TRUE); + } +} +#endif + +/* must be called with the SELECTOR_LOCK */ +static void +gst_input_selector_cleanup_old_cached_buffers (GstInputSelector * sel, + GstPad * pad) +{ + GstClock *clock; + gint64 cur_running_time; + GList *walk; + + cur_running_time = GST_CLOCK_TIME_NONE; + if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK) { + clock = gst_element_get_clock (GST_ELEMENT_CAST (sel)); + if (clock) { + GstClockTime base_time; + + cur_running_time = gst_clock_get_time (clock); + base_time = gst_element_get_base_time (GST_ELEMENT_CAST (sel)); + if (base_time <= cur_running_time) + cur_running_time -= base_time; + else + cur_running_time = 0; + + gst_object_unref (clock); + } + } else { + GstPad *active_sinkpad; + GstSelectorPad *active_selpad; + GstSegment *active_seg; + + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad); + active_seg = &active_selpad->segment; + + /* Get active pad's running time, if no configured segment yet keep at -1 */ + if (active_seg->format == GST_FORMAT_TIME) + cur_running_time = gst_segment_to_running_time (active_seg, + GST_FORMAT_TIME, active_seg->position); + } + + if (!GST_CLOCK_TIME_IS_VALID (cur_running_time)) + return; + + GST_DEBUG_OBJECT (sel, "Cleaning up old cached buffers"); + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { + GstSelectorPad *selpad; + GstSegment *seg; + GstSelectorPadCachedBuffer *cached_buffer; + GSList *maybe_remove; + guint queue_position; + + selpad = GST_SELECTOR_PAD_CAST (walk->data); + if (!selpad->cached_buffers) + continue; + + seg = &selpad->segment; + + maybe_remove = NULL; + queue_position = 0; + while ((cached_buffer = g_queue_peek_nth (selpad->cached_buffers, + queue_position))) { + GstBuffer *buffer = cached_buffer->buffer; + GstClockTime running_time; + GSList *l; + + /* If we have no valid timestamp we can't sync this buffer */ + if (!GST_BUFFER_PTS_IS_VALID (buffer)) { + maybe_remove = g_slist_append (maybe_remove, cached_buffer); + queue_position = g_slist_length (maybe_remove); + continue; + } + + /* the buffer is still valid if its duration is valid and the + * timestamp + duration is >= time, or if its duration is invalid + * and the timestamp is >= time */ + running_time = gst_input_selector_get_clipped_running_time (seg, buffer); + GST_DEBUG_OBJECT (selpad, + "checking if buffer %p running time=%" GST_TIME_FORMAT + " >= stream time=%" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS (running_time), GST_TIME_ARGS (cur_running_time)); + if (running_time >= cur_running_time) { + break; + } + + GST_DEBUG_OBJECT (selpad, "Removing old cached buffer %p", buffer); + g_queue_pop_nth (selpad->cached_buffers, queue_position); + gst_selector_pad_free_cached_buffer (cached_buffer); + + for (l = maybe_remove; l != NULL; l = g_slist_next (l)) { + /* A buffer after some invalid buffers was removed, it means the invalid buffers + * are old, lets also remove them */ + cached_buffer = l->data; + g_queue_remove (selpad->cached_buffers, cached_buffer); + gst_selector_pad_free_cached_buffer (cached_buffer); + } + + g_slist_free (maybe_remove); + maybe_remove = NULL; + queue_position = 0; + } + + g_slist_free (maybe_remove); + maybe_remove = NULL; + + if (g_queue_is_empty (selpad->cached_buffers)) { + g_queue_free (selpad->cached_buffers); + selpad->cached_buffers = NULL; + } + } + +#if DEBUG_CACHED_BUFFERS + gst_input_selector_debug_cached_buffers (sel); +#endif +} + +static GstFlowReturn +gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GstInputSelector *sel; + GstFlowReturn res; + GstPad *active_sinkpad; + GstPad *prev_active_sinkpad = NULL; + GstSelectorPad *selpad; + + sel = GST_INPUT_SELECTOR (parent); + selpad = GST_SELECTOR_PAD_CAST (pad); + + GST_DEBUG_OBJECT (selpad, + "entering chain for buf %p with timestamp %" GST_TIME_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + + GST_INPUT_SELECTOR_LOCK (sel); + + if (sel->flushing) { + GST_INPUT_SELECTOR_UNLOCK (sel); + goto flushing; + } + + GST_LOG_OBJECT (pad, "getting active pad"); + + prev_active_sinkpad = + sel->active_sinkpad ? gst_object_ref (sel->active_sinkpad) : NULL; + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + + /* In sync mode wait until the active pad has advanced + * after the running time of the current buffer */ + if (sel->sync_streams) { + /* call chain for each cached buffer if we are not the active pad + * or if we are the active pad but didn't push anything yet. */ + if (active_sinkpad != pad || !selpad->pushed) { + /* no need to check for sel->cache_buffers as selpad->cached_buffers + * will only be valid if cache_buffers is TRUE */ + if (selpad->cached_buffers && !selpad->sending_cached_buffers) { + GstSelectorPadCachedBuffer *cached_buffer; + GstSegment saved_segment; + + saved_segment = selpad->segment; + + selpad->sending_cached_buffers = TRUE; + while (!sel->eos && !sel->flushing && !selpad->flushing && + (cached_buffer = g_queue_pop_head (selpad->cached_buffers))) { + GST_DEBUG_OBJECT (pad, "Cached buffers found, " + "invoking chain for cached buffer %p", cached_buffer->buffer); + + selpad->segment = cached_buffer->segment; + selpad->events_pending = TRUE; + GST_INPUT_SELECTOR_UNLOCK (sel); + gst_selector_pad_chain (pad, parent, cached_buffer->buffer); + GST_INPUT_SELECTOR_LOCK (sel); + + /* We just passed the ownership of the buffer to the chain function */ + cached_buffer->buffer = NULL; + gst_selector_pad_free_cached_buffer (cached_buffer); + + /* we may have cleaned up the queue in the meantime because of + * old buffers */ + if (!selpad->cached_buffers) { + break; + } + } + selpad->sending_cached_buffers = FALSE; + + /* all cached buffers sent, restore segment for current buffer */ + selpad->segment = saved_segment; + selpad->events_pending = TRUE; + + /* Might have changed while calling chain for cached buffers */ + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + } + } + + if (active_sinkpad != pad) { + GST_INPUT_SELECTOR_UNLOCK (sel); + if (gst_input_selector_wait_running_time (sel, selpad, buf)) + goto flushing; + GST_INPUT_SELECTOR_LOCK (sel); + } + + /* Might have changed while waiting */ + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + } + + /* update the segment on the srcpad */ + if (GST_BUFFER_PTS_IS_VALID (buf)) { + GstClockTime start_time = GST_BUFFER_PTS (buf); + + GST_LOG_OBJECT (pad, "received start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + if (GST_BUFFER_DURATION_IS_VALID (buf)) + GST_LOG_OBJECT (pad, "received end time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time + GST_BUFFER_DURATION (buf))); + + GST_OBJECT_LOCK (pad); + selpad->segment.position = start_time; + GST_OBJECT_UNLOCK (pad); + } + + /* Ignore buffers from pads except the selected one */ + if (pad != active_sinkpad) + goto ignore; + + /* Tell all non-active pads that we advanced the running time */ + if (sel->sync_streams) + GST_INPUT_SELECTOR_BROADCAST (sel); + + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (prev_active_sinkpad != active_sinkpad) { + if (prev_active_sinkpad) + g_object_notify (G_OBJECT (prev_active_sinkpad), "active"); + g_object_notify (G_OBJECT (active_sinkpad), "active"); + g_object_notify (G_OBJECT (sel), "active-pad"); + } + + /* if we have a pending events, push them now */ + if (G_UNLIKELY (prev_active_sinkpad != active_sinkpad + || selpad->events_pending)) { + gst_pad_sticky_events_foreach (GST_PAD_CAST (selpad), forward_sticky_events, + sel); + selpad->events_pending = FALSE; + } + + if (prev_active_sinkpad) { + gst_object_unref (prev_active_sinkpad); + prev_active_sinkpad = NULL; + } + + if (selpad->discont) { + buf = gst_buffer_make_writable (buf); + + GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + selpad->discont = FALSE; + } + + /* forward */ + GST_LOG_OBJECT (pad, "Forwarding buffer %p with timestamp %" GST_TIME_FORMAT, + buf, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + + /* Only make the buffer read-only when necessary */ + if (sel->sync_streams && sel->cache_buffers) + buf = gst_buffer_ref (buf); + res = gst_pad_push (sel->srcpad, buf); + GST_LOG_OBJECT (pad, "Buffer %p forwarded result=%d", buf, res); + + GST_INPUT_SELECTOR_LOCK (sel); + + if (sel->sync_streams && sel->cache_buffers) { + /* Might have changed while pushing */ + active_sinkpad = gst_input_selector_get_active_sinkpad (sel); + /* only set pad to pushed if we are still the active pad */ + if (active_sinkpad == pad) + selpad->pushed = TRUE; + + /* cache buffer as we may need it again if we change pads */ + gst_selector_pad_cache_buffer (selpad, buf); + gst_input_selector_cleanup_old_cached_buffers (sel, pad); + } else { + selpad->pushed = TRUE; + } + GST_INPUT_SELECTOR_UNLOCK (sel); + +done: + + if (prev_active_sinkpad) + gst_object_unref (prev_active_sinkpad); + prev_active_sinkpad = NULL; + + return res; + + /* dropped buffers */ +ignore: + { + gboolean active_pad_pushed = GST_SELECTOR_PAD_CAST (active_sinkpad)->pushed; + + GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf); + /* when we drop a buffer, we're creating a discont on this pad */ + selpad->discont = TRUE; + GST_INPUT_SELECTOR_UNLOCK (sel); + gst_buffer_unref (buf); + + /* figure out what to return upstream */ + GST_OBJECT_LOCK (selpad); + if (selpad->always_ok || !active_pad_pushed) + res = GST_FLOW_OK; + else + res = GST_FLOW_NOT_LINKED; + GST_OBJECT_UNLOCK (selpad); + + goto done; + } +flushing: + { + GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf); + gst_buffer_unref (buf); + res = GST_FLOW_FLUSHING; + goto done; + } +} + +static void gst_input_selector_dispose (GObject * object); +static void gst_input_selector_finalize (GObject * object); + +static void gst_input_selector_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_input_selector_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPad *gst_input_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused, const GstCaps * caps); +static void gst_input_selector_release_pad (GstElement * element, GstPad * pad); + +static GstStateChangeReturn gst_input_selector_change_state (GstElement * + element, GstStateChange transition); + +static gboolean gst_input_selector_event (GstPad * pad, GstObject * parent, + GstEvent * event); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (input_selector_debug, \ + "input-selector", 0, "An input stream selector element"); +#define gst_input_selector_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstInputSelector, gst_input_selector, GST_TYPE_ELEMENT, + _do_init); + +static void +gst_input_selector_class_init (GstInputSelectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->dispose = gst_input_selector_dispose; + gobject_class->finalize = gst_input_selector_finalize; + + gobject_class->set_property = gst_input_selector_set_property; + gobject_class->get_property = gst_input_selector_get_property; + + g_object_class_install_property (gobject_class, PROP_N_PADS, + g_param_spec_uint ("n-pads", "Number of Pads", + "The number of sink pads", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_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 | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + /** + * GstInputSelector:sync-streams + * + * If set to %TRUE all inactive streams will be synced to the + * running time of the active stream or to the current clock. + * + * To make sure no buffers are dropped by input-selector + * that might be needed when switching the active pad, + * sync-mode should be set to "clock" and cache-buffers to TRUE. + */ + g_object_class_install_property (gobject_class, PROP_SYNC_STREAMS, + g_param_spec_boolean ("sync-streams", "Sync Streams", + "Synchronize inactive streams to the running time of the active " + "stream or to the current clock", + DEFAULT_SYNC_STREAMS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + /** + * GstInputSelector:sync-mode + * + * Select how input-selector will sync buffers when in sync-streams mode. + * + * Note that when using the "active-segment" mode, the "active-segment" may + * be ahead of current clock time when switching the active pad, as the current + * active pad may have pushed more buffers than what was displayed/consumed, + * which may cause delays and some missing buffers. + */ + g_object_class_install_property (gobject_class, PROP_SYNC_MODE, + g_param_spec_enum ("sync-mode", "Sync mode", + "Behavior in sync-streams mode", GST_TYPE_INPUT_SELECTOR_SYNC_MODE, + DEFAULT_SYNC_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + /** + * GstInputSelector:cache-buffers + * + * If set to %TRUE and GstInputSelector:sync-streams is also set to %TRUE, + * the active pad will cache the buffers still considered valid (after current + * running time, see sync-mode) to avoid missing frames if/when the pad is + * reactivated. + * + * The active pad may push more buffers than what is currently displayed/consumed + * and when changing pads those buffers will be discarded and the only way to + * reactivate that pad without loosing the already consumed buffers is to enable cache. + */ + g_object_class_install_property (gobject_class, PROP_CACHE_BUFFERS, + g_param_spec_boolean ("cache-buffers", "Cache Buffers", + "Cache buffers for active-pad", + DEFAULT_CACHE_BUFFERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + gst_element_class_set_static_metadata (gstelement_class, "Input selector", + "Generic", "N-to-1 input stream selector", + "Julien Moutte , " + "Jan Schmidt , " + "Wim Taymans "); + gst_element_class_add_static_pad_template_with_gtype (gstelement_class, + &gst_input_selector_sink_factory, GST_TYPE_SELECTOR_PAD); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_input_selector_src_factory); + + gstelement_class->request_new_pad = gst_input_selector_request_new_pad; + gstelement_class->release_pad = gst_input_selector_release_pad; + gstelement_class->change_state = gst_input_selector_change_state; +} + +static void +gst_input_selector_init (GstInputSelector * sel) +{ + sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_iterate_internal_links_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); + gst_pad_set_event_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_input_selector_event)); + GST_OBJECT_FLAG_SET (sel->srcpad, GST_PAD_FLAG_PROXY_CAPS); + gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); + /* sinkpad management */ + sel->active_sinkpad = NULL; + sel->padcount = 0; + sel->sync_streams = DEFAULT_SYNC_STREAMS; + sel->sync_mode = DEFAULT_SYNC_MODE; + sel->have_group_id = TRUE; + + g_mutex_init (&sel->lock); + g_cond_init (&sel->cond); + sel->eos = FALSE; + + /* lets give a change for downstream to do something on + * active-pad change before we start pushing new buffers */ + g_signal_connect_data (sel, "notify::active-pad", + (GCallback) gst_input_selector_active_pad_changed, NULL, + NULL, G_CONNECT_AFTER); +} + +static void +gst_input_selector_dispose (GObject * object) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + if (sel->active_sinkpad) { + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_input_selector_finalize (GObject * object) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + g_mutex_clear (&sel->lock); + g_cond_clear (&sel->cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* this function must be called with the SELECTOR_LOCK. It returns TRUE when the + * active pad changed. */ +static gboolean +gst_input_selector_set_active_pad (GstInputSelector * self, GstPad * pad) +{ + GstSelectorPad *old, *new; + GstPad **active_pad_p; + + if (pad == self->active_sinkpad) + return FALSE; + + old = GST_SELECTOR_PAD_CAST (self->active_sinkpad); + new = GST_SELECTOR_PAD_CAST (pad); + + GST_DEBUG_OBJECT (self, "setting active pad to %s:%s", + GST_DEBUG_PAD_NAME (new)); + + if (old) + old->pushed = FALSE; + if (new) + new->pushed = FALSE; + + /* Send a new SEGMENT event on the new pad next */ + if (old != new && new) + new->events_pending = TRUE; + + active_pad_p = &self->active_sinkpad; + gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad)); + + if (old && old != new) + gst_pad_push_event (GST_PAD_CAST (old), gst_event_new_reconfigure ()); + if (new) + gst_pad_push_event (GST_PAD_CAST (new), gst_event_new_reconfigure ()); + + GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT, + self->active_sinkpad); + + if (old != new && new && new->eos) { + new->eos_sent = FALSE; + GST_INPUT_SELECTOR_BROADCAST (self); + } + + return TRUE; +} + +static void +gst_input_selector_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + { + GstPad *pad; + + pad = g_value_get_object (value); + + GST_INPUT_SELECTOR_LOCK (sel); + +#if DEBUG_CACHED_BUFFERS + gst_input_selector_debug_cached_buffers (sel); +#endif + + gst_input_selector_set_active_pad (sel, pad); + +#if DEBUG_CACHED_BUFFERS + gst_input_selector_debug_cached_buffers (sel); +#endif + + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + } + case PROP_SYNC_STREAMS: + GST_INPUT_SELECTOR_LOCK (sel); + sel->sync_streams = g_value_get_boolean (value); + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + case PROP_SYNC_MODE: + GST_INPUT_SELECTOR_LOCK (sel); + sel->sync_mode = g_value_get_enum (value); + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + case PROP_CACHE_BUFFERS: + GST_INPUT_SELECTOR_LOCK (object); + sel->cache_buffers = g_value_get_boolean (value); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_input_selector_active_pad_changed (GstInputSelector * sel, + GParamSpec * pspec, gpointer user_data) +{ + /* Wake up all non-active pads in sync mode, they might be + * the active pad now */ + if (sel->sync_streams) + GST_INPUT_SELECTOR_BROADCAST (sel); +} + +static void +gst_input_selector_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_N_PADS: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_uint (value, sel->n_pads); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_ACTIVE_PAD: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_object (value, sel->active_sinkpad); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_SYNC_STREAMS: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_boolean (value, sel->sync_streams); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_SYNC_MODE: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_enum (value, sel->sync_mode); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_CACHE_BUFFERS: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_boolean (value, sel->cache_buffers); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_input_selector_get_linked_pad (GstInputSelector * sel, GstPad * pad, + gboolean strict) +{ + GstPad *otherpad = NULL; + + GST_INPUT_SELECTOR_LOCK (sel); + if (pad == sel->srcpad) + otherpad = sel->active_sinkpad; + else if (pad == sel->active_sinkpad || !strict) + otherpad = sel->srcpad; + if (otherpad) + gst_object_ref (otherpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + return otherpad; +} + +static gboolean +gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstInputSelector *sel; + gboolean result = FALSE; + GstIterator *iter; + gboolean done = FALSE; + GValue item = { 0, }; + GstPad *eventpad; + GList *pushed_pads = NULL; + + sel = GST_INPUT_SELECTOR (parent); + /* Send upstream events to all sinkpads */ + iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel)); + + /* This is now essentially a copy of gst_pad_event_default_dispatch + * with a different iterator */ + while (!done) { + switch (gst_iterator_next (iter, &item)) { + case GST_ITERATOR_OK: + eventpad = g_value_get_object (&item); + + /* if already pushed, skip */ + if (g_list_find (pushed_pads, eventpad)) { + g_value_reset (&item); + break; + } + + gst_event_ref (event); + result |= gst_pad_push_event (eventpad, event); + + g_value_reset (&item); + break; + case GST_ITERATOR_RESYNC: + /* We don't reset the result here because we don't push the event + * again on pads that got the event already and because we need + * to consider the result of the previous pushes */ + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_ERROR_OBJECT (pad, "Could not iterate over sinkpads"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + g_value_unset (&item); + gst_iterator_free (iter); + + g_list_free (pushed_pads); + + gst_event_unref (event); + + return result; +} + +/* check if the pad is the active sinkpad */ +static inline gboolean +gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) +{ + gboolean res; + + GST_INPUT_SELECTOR_LOCK (sel); + res = (pad == sel->active_sinkpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + return res; +} + +/* Get or create the active sinkpad, must be called with SELECTOR_LOCK */ +static GstPad * +gst_input_selector_get_active_sinkpad (GstInputSelector * sel) +{ + GstPad *active_sinkpad; + + active_sinkpad = sel->active_sinkpad; + if (active_sinkpad == NULL) { + GValue item = G_VALUE_INIT; + GstIterator *iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel)); + GstIteratorResult ires; + + while ((ires = gst_iterator_next (iter, &item)) == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); + if (ires == GST_ITERATOR_OK) { + /* If no pad is currently selected, we return the first usable pad to + * guarantee consistency */ + + active_sinkpad = sel->active_sinkpad = g_value_dup_object (&item); + g_value_reset (&item); + GST_DEBUG_OBJECT (sel, "Activating pad %s:%s", + GST_DEBUG_PAD_NAME (active_sinkpad)); + } else + GST_WARNING_OBJECT (sel, "Couldn't find a default sink pad"); + gst_iterator_free (iter); + } + + return active_sinkpad; +} + +static GstPad * +gst_input_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused, const GstCaps * caps) +{ + GstInputSelector *sel; + gchar *name = NULL; + GstPad *sinkpad = NULL; + + g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL); + + sel = GST_INPUT_SELECTOR (element); + + GST_INPUT_SELECTOR_LOCK (sel); + + GST_LOG_OBJECT (sel, "Creating new pad sink_%u", sel->padcount); + name = g_strdup_printf ("sink_%u", sel->padcount++); + sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, + "name", name, "direction", templ->direction, "template", templ, NULL); + g_free (name); + + sel->n_pads++; + + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_event)); + gst_pad_set_query_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_query)); + 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_selector_pad_iterate_linked_pads)); + + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); + gst_pad_set_active (sinkpad, TRUE); + gst_element_add_pad (GST_ELEMENT (sel), sinkpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + return sinkpad; +} + +static void +gst_input_selector_release_pad (GstElement * element, GstPad * pad) +{ + GstInputSelector *sel; + + sel = GST_INPUT_SELECTOR (element); + GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + GST_INPUT_SELECTOR_LOCK (sel); + /* if the pad was the active pad, makes us select a new one */ + if (sel->active_sinkpad == pad) { + GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + sel->n_pads--; + GST_INPUT_SELECTOR_UNLOCK (sel); + + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT (sel), pad); +} + +static void +gst_input_selector_reset (GstInputSelector * sel) +{ + GList *walk; + + GST_INPUT_SELECTOR_LOCK (sel); + /* clear active pad */ + if (sel->active_sinkpad) { + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + sel->eos_sent = FALSE; + + /* reset each of our sinkpads state */ + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { + GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data); + + gst_selector_pad_reset (selpad); + + if (selpad->tags) { + gst_tag_list_unref (selpad->tags); + selpad->tags = NULL; + } + } + sel->have_group_id = TRUE; + GST_INPUT_SELECTOR_UNLOCK (sel); +} + +static GstStateChangeReturn +gst_input_selector_change_state (GstElement * element, + GstStateChange transition) +{ + GstInputSelector *self = GST_INPUT_SELECTOR (element); + GstStateChangeReturn result; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_INPUT_SELECTOR_LOCK (self); + self->eos = FALSE; + self->flushing = FALSE; + GST_INPUT_SELECTOR_UNLOCK (self); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* first unlock before we call the parent state change function, which + * tries to acquire the stream lock when going to ready. */ + GST_INPUT_SELECTOR_LOCK (self); + self->eos = TRUE; + self->flushing = TRUE; + GST_INPUT_SELECTOR_BROADCAST (self); + GST_INPUT_SELECTOR_UNLOCK (self); + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_input_selector_reset (self); + break; + default: + break; + } + + return result; +} diff --git a/plugins/elements/gstinputselector.h b/plugins/elements/gstinputselector.h new file mode 100644 index 0000000..3dff175 --- /dev/null +++ b/plugins/elements/gstinputselector.h @@ -0,0 +1,92 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_INPUT_SELECTOR_H__ +#define __GST_INPUT_SELECTOR_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_INPUT_SELECTOR \ + (gst_input_selector_get_type()) +#define GST_INPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INPUT_SELECTOR, GstInputSelector)) +#define GST_INPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INPUT_SELECTOR, GstInputSelectorClass)) +#define GST_IS_INPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INPUT_SELECTOR)) +#define GST_IS_INPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INPUT_SELECTOR)) + +typedef struct _GstInputSelector GstInputSelector; +typedef struct _GstInputSelectorClass GstInputSelectorClass; + +#define GST_INPUT_SELECTOR_GET_LOCK(sel) (&((GstInputSelector*)(sel))->lock) +#define GST_INPUT_SELECTOR_GET_COND(sel) (&((GstInputSelector*)(sel))->cond) +#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ + GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) + +/** + * GstInputSelectorSyncMode: + * @GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT: Sync using the current active segment. + * @GST_INPUT_SELECTOR_SYNC_MODE_CLOCK: Sync using the clock. + * + * The different ways that input-selector can behave when in sync-streams mode. + */ +typedef enum { + GST_INPUT_SELECTOR_SYNC_MODE_ACTIVE_SEGMENT, + GST_INPUT_SELECTOR_SYNC_MODE_CLOCK +} GstInputSelectorSyncMode; + +struct _GstInputSelector { + GstElement element; + + GstPad *srcpad; + + GstPad *active_sinkpad; + guint n_pads; /* number of pads */ + guint padcount; /* sequence number for pads */ + gboolean sync_streams; + GstInputSelectorSyncMode sync_mode; + gboolean cache_buffers; + + gboolean have_group_id; + + GMutex lock; + GCond cond; + gboolean eos; + gboolean eos_sent; + gboolean flushing; +}; + +struct _GstInputSelectorClass { + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_input_selector_get_type (void); + +G_END_DECLS + +#endif /* __GST_INPUT_SELECTOR_H__ */ diff --git a/plugins/elements/gstmultiqueue.c b/plugins/elements/gstmultiqueue.c new file mode 100644 index 0000000..bcf8efa --- /dev/null +++ b/plugins/elements/gstmultiqueue.c @@ -0,0 +1,3088 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey + * Copyright (C) 2007 Jan Schmidt + * Copyright (C) 2007 Wim Taymans + * Copyright (C) 2011 Sebastian Dröge + * + * gstmultiqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-multiqueue + * @title: multiqueue + * @see_also: #GstQueue + * + * Multiqueue is similar to a normal #GstQueue with the following additional + * features: + * + * 1) Multiple streamhandling + * + * * The element handles queueing data on more than one stream at once. To + * achieve such a feature it has request sink pads (sink%u) and + * 'sometimes' src pads (src%u). When requesting a given sinkpad with gst_element_request_pad(), + * the associated srcpad for that stream will be created. + * Example: requesting sink1 will generate src1. + * + * 2) Non-starvation on multiple stream + * + * * 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 will be + * considered as 'not-empty' in the queue-size-growing algorithm. + * + * 3) Non-linked srcpads graceful handling + * + * * 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. + * + * Data is queued until one of the limits specified by the + * #GstMultiQueue:max-size-buffers, #GstMultiQueue:max-size-bytes and/or + * #GstMultiQueue:max-size-time properties has been reached. Any attempt to push + * more buffers into the queue will block the pushing thread until more space + * becomes available. #GstMultiQueue:extra-size-buffers, + * + * + * #GstMultiQueue:extra-size-bytes and #GstMultiQueue:extra-size-time are + * currently unused. + * + * The default queue size limits are 5 buffers, 10MB of data, or + * two second worth of data, whichever is reached first. Note that the number + * of buffers will dynamically grow depending on the fill level of + * other queues. + * + * The #GstMultiQueue::underrun signal is emitted when all of the queues + * are empty. The #GstMultiQueue::overrun signal is emitted when one of the + * queues is filled. + * Both signals are emitted from the context of the streaming thread. + * + * When using #GstMultiQueue:sync-by-running-time the unlinked streams will + * be throttled by the highest running-time of linked streams. This allows + * further relinking of those unlinked streams without them being in the + * future (i.e. to achieve gapless playback). + * When dealing with streams which have got different consumption requirements + * downstream (ex: video decoders which will consume more buffer (in time) than + * audio decoders), it is recommended to group streams of the same type + * by using the pad "group-id" property. This will further throttle streams + * in time within that group. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "gstmultiqueue.h" +#include + +/** + * GstSingleQueue: + * @sinkpad: associated sink #GstPad + * @srcpad: associated source #GstPad + * + * Structure containing all information and properties about + * a single queue. + */ +typedef struct _GstSingleQueue GstSingleQueue; + +struct _GstSingleQueue +{ + /* unique identifier of the queue */ + guint id; + /* group of streams to which this queue belongs to */ + guint groupid; + GstClockTimeDiff group_high_time; + + GstMultiQueue *mqueue; + + GstPad *sinkpad; + GstPad *srcpad; + + /* flowreturn of previous srcpad push */ + GstFlowReturn srcresult; + /* If something was actually pushed on + * this pad after flushing/pad activation + * and the srcresult corresponds to something + * real + */ + gboolean pushed; + + /* segments */ + GstSegment sink_segment; + GstSegment src_segment; + gboolean has_src_segment; /* preferred over initializing the src_segment to + * UNDEFINED as this doesn't requires adding ifs + * in every segment usage */ + + /* position of src/sink */ + GstClockTimeDiff sinktime, srctime; + /* cached input value, used for interleave */ + GstClockTimeDiff cached_sinktime; + /* TRUE if either position needs to be recalculated */ + gboolean sink_tainted, src_tainted; + + /* queue of data */ + GstDataQueue *queue; + GstDataQueueSize max_size, extra_size; + GstClockTime cur_time; + gboolean is_eos; + gboolean is_segment_done; + gboolean is_sparse; + gboolean flushing; + gboolean active; + + /* Protected by global lock */ + guint32 nextid; /* ID of the next object waiting to be pushed */ + guint32 oldid; /* ID of the last object pushed (last in a series) */ + guint32 last_oldid; /* Previously observed old_id, reset to MAXUINT32 on flush */ + GstClockTimeDiff next_time; /* End running time of next buffer to be pushed */ + GstClockTimeDiff last_time; /* Start running time of last pushed buffer */ + GCond turn; /* SingleQueue turn waiting conditional */ + + /* for serialized queries */ + GCond query_handled; + gboolean last_query; + GstQuery *last_handled_query; + + /* For interleave calculation */ + GThread *thread; /* Streaming thread of SingleQueue */ + GstClockTime interleave; /* Calculated interleve within the thread */ +}; + + +/* Extension of GstDataQueueItem structure for our usage */ +typedef struct _GstMultiQueueItem GstMultiQueueItem; + +struct _GstMultiQueueItem +{ + GstMiniObject *object; + guint size; + guint64 duration; + gboolean visible; + + GDestroyNotify destroy; + guint32 posid; + + gboolean is_query; +}; + +static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, guint id); +static void gst_single_queue_free (GstSingleQueue * squeue); + +static void wake_up_next_non_linked (GstMultiQueue * mq); +static void compute_high_id (GstMultiQueue * mq); +static void compute_high_time (GstMultiQueue * mq, guint groupid); +static void single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq); +static void single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq); + +static void update_buffering (GstMultiQueue * mq, GstSingleQueue * sq); +static void gst_multi_queue_post_buffering (GstMultiQueue * mq); +static void recheck_buffering_status (GstMultiQueue * mq); + +static void gst_single_queue_flush_queue (GstSingleQueue * sq, gboolean full); + +static void calculate_interleave (GstMultiQueue * mq, GstSingleQueue * sq); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (multi_queue_debug); +#define GST_CAT_DEFAULT (multi_queue_debug) + +/* Signals and args */ +enum +{ + SIGNAL_UNDERRUN, + SIGNAL_OVERRUN, + LAST_SIGNAL +}; + +/* default limits, we try to keep up to 2 seconds of data and if there is not + * time, up to 10 MB. The number of buffers is dynamically scaled to make sure + * there is data in the queues. Normally, the byte and time limits are not hit + * in theses conditions. */ +#define DEFAULT_MAX_SIZE_BYTES 10 * 1024 * 1024 /* 10 MB */ +#define DEFAULT_MAX_SIZE_BUFFERS 5 +#define DEFAULT_MAX_SIZE_TIME 2 * GST_SECOND + +/* second limits. When we hit one of the above limits we are probably dealing + * with a badly muxed file and we scale the limits to these emergency values. + * This is currently not yet implemented. + * Since we dynamically scale the queue buffer size up to the limits but avoid + * going above the max-size-buffers when we can, we don't really need this + * aditional extra size. */ +#define DEFAULT_EXTRA_SIZE_BYTES 10 * 1024 * 1024 /* 10 MB */ +#define DEFAULT_EXTRA_SIZE_BUFFERS 5 +#define DEFAULT_EXTRA_SIZE_TIME 3 * GST_SECOND + +#define DEFAULT_USE_BUFFERING FALSE +#define DEFAULT_LOW_WATERMARK 0.01 +#define DEFAULT_HIGH_WATERMARK 0.99 +#define DEFAULT_SYNC_BY_RUNNING_TIME FALSE +#define DEFAULT_USE_INTERLEAVE FALSE +#define DEFAULT_UNLINKED_CACHE_TIME 250 * GST_MSECOND + +#define DEFAULT_MINIMUM_INTERLEAVE (250 * GST_MSECOND) + +enum +{ + PROP_0, + PROP_EXTRA_SIZE_BYTES, + PROP_EXTRA_SIZE_BUFFERS, + PROP_EXTRA_SIZE_TIME, + PROP_MAX_SIZE_BYTES, + PROP_MAX_SIZE_BUFFERS, + PROP_MAX_SIZE_TIME, + PROP_USE_BUFFERING, + PROP_LOW_PERCENT, + PROP_HIGH_PERCENT, + PROP_LOW_WATERMARK, + PROP_HIGH_WATERMARK, + PROP_SYNC_BY_RUNNING_TIME, + PROP_USE_INTERLEAVE, + PROP_UNLINKED_CACHE_TIME, + PROP_MINIMUM_INTERLEAVE, + PROP_LAST +}; + +/* Explanation for buffer levels and percentages: + * + * The buffering_level functions here return a value in a normalized range + * that specifies the current fill level of a queue. The range goes from 0 to + * MAX_BUFFERING_LEVEL. The low/high watermarks also use this same range. + * + * This is not to be confused with the buffering_percent value, which is + * a *relative* quantity - relative to the low/high watermarks. + * buffering_percent = 0% means overall buffering_level is at the low watermark. + * buffering_percent = 100% means overall buffering_level is at the high watermark. + * buffering_percent is used for determining if the fill level has reached + * the high watermark, and for producing BUFFERING messages. This value + * always uses a 0..100 range (since it is a percentage). + * + * To avoid future confusions, whenever "buffering level" is mentioned, it + * refers to the absolute level which is in the 0..MAX_BUFFERING_LEVEL + * range. Whenever "buffering_percent" is mentioned, it refers to the + * percentage value that is relative to the low/high watermark. */ + +/* Using a buffering level range of 0..1000000 to allow for a + * resolution in ppm (1 ppm = 0.0001%) */ +#define MAX_BUFFERING_LEVEL 1000000 + +/* How much 1% makes up in the buffer level range */ +#define BUF_LEVEL_PERCENT_FACTOR ((MAX_BUFFERING_LEVEL) / 100) + +/* GstMultiQueuePad */ + +#define DEFAULT_PAD_GROUP_ID 0 + +enum +{ + PROP_PAD_0, + PROP_PAD_GROUP_ID, +}; + +#define GST_TYPE_MULTIQUEUE_PAD (gst_multiqueue_pad_get_type()) +#define GST_MULTIQUEUE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTIQUEUE_PAD,GstMultiQueuePad)) +#define GST_IS_MULTIQUEUE_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTIQUEUE_PAD)) +#define GST_MULTIQUEUE_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_MULTIQUEUE_PAD,GstMultiQueuePadClass)) +#define GST_IS_MULTIQUEUE_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_MULTIQUEUE_PAD)) +#define GST_MULTIQUEUE_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_MULTIQUEUE_PAD,GstMultiQueuePadClass)) + +struct _GstMultiQueuePad +{ + GstPad parent; + + GstSingleQueue *sq; +}; + +struct _GstMultiQueuePadClass +{ + GstPadClass parent_class; +}; + +GType gst_multiqueue_pad_get_type (void); + +G_DEFINE_TYPE (GstMultiQueuePad, gst_multiqueue_pad, GST_TYPE_PAD); +static void +gst_multiqueue_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstMultiQueuePad *pad = GST_MULTIQUEUE_PAD (object); + + switch (prop_id) { + case PROP_PAD_GROUP_ID: + if (pad->sq) + g_value_set_uint (value, pad->sq->groupid); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_multiqueue_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMultiQueuePad *pad = GST_MULTIQUEUE_PAD (object); + + switch (prop_id) { + case PROP_PAD_GROUP_ID: + GST_OBJECT_LOCK (pad); + if (pad->sq) + pad->sq->groupid = g_value_get_uint (value); + GST_OBJECT_UNLOCK (pad); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_multiqueue_pad_class_init (GstMultiQueuePadClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->set_property = gst_multiqueue_pad_set_property; + gobject_class->get_property = gst_multiqueue_pad_get_property; + + /** + * GstMultiQueuePad:group-id: + * + * Group to which this pad belongs. + * + * Since: 1.10 + */ + g_object_class_install_property (gobject_class, PROP_PAD_GROUP_ID, + g_param_spec_uint ("group-id", "Group ID", + "Group to which this pad belongs", 0, G_MAXUINT32, + DEFAULT_PAD_GROUP_ID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_multiqueue_pad_init (GstMultiQueuePad * pad) +{ + +} + + +#define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ + g_mutex_lock (&q->qlock); \ +} G_STMT_END + +#define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ + g_mutex_unlock (&q->qlock); \ +} G_STMT_END + +#define SET_PERCENT(mq, perc) G_STMT_START { \ + if (perc != mq->buffering_percent) { \ + mq->buffering_percent = perc; \ + mq->buffering_percent_changed = TRUE; \ + GST_DEBUG_OBJECT (mq, "buffering %d percent", perc); \ + } \ +} G_STMT_END + +/* Convenience function */ +static inline GstClockTimeDiff +my_segment_to_running_time (GstSegment * segment, GstClockTime val) +{ + GstClockTimeDiff res = GST_CLOCK_STIME_NONE; + + if (GST_CLOCK_TIME_IS_VALID (val)) { + gboolean sign = + gst_segment_to_running_time_full (segment, GST_FORMAT_TIME, val, &val); + if (sign > 0) + res = val; + else if (sign < 0) + res = -val; + } + return res; +} + +static void gst_multi_queue_finalize (GObject * object); +static void gst_multi_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_multi_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPad *gst_multi_queue_request_new_pad (GstElement * element, + GstPadTemplate * temp, const gchar * name, const GstCaps * caps); +static void gst_multi_queue_release_pad (GstElement * element, GstPad * pad); +static GstStateChangeReturn gst_multi_queue_change_state (GstElement * + element, GstStateChange transition); + +static void gst_multi_queue_loop (GstPad * pad); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (multi_queue_debug, "multiqueue", 0, "multiqueue element"); +#define gst_multi_queue_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstMultiQueue, gst_multi_queue, GST_TYPE_ELEMENT, + _do_init); + +static guint gst_multi_queue_signals[LAST_SIGNAL] = { 0 }; + +static void +gst_multi_queue_class_init (GstMultiQueueClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_multi_queue_set_property; + gobject_class->get_property = gst_multi_queue_get_property; + + /* SIGNALS */ + + /** + * GstMultiQueue::underrun: + * @multiqueue: the multiqueue instance + * + * This signal is emitted from the streaming thread when there is + * no data in any of the queues inside the multiqueue instance (underrun). + * + * This indicates either starvation or EOS from the upstream data sources. + */ + gst_multi_queue_signals[SIGNAL_UNDERRUN] = + g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstMultiQueueClass, underrun), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GstMultiQueue::overrun: + * @multiqueue: the multiqueue instance + * + * Reports that one of the queues in the multiqueue is full (overrun). + * A queue is full if the total amount of data inside it (num-buffers, time, + * size) is higher than the boundary values which can be set through the + * GObject properties. + * + * This can be used as an indicator of pre-roll. + */ + gst_multi_queue_signals[SIGNAL_OVERRUN] = + g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstMultiQueueClass, overrun), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* PROPERTIES */ + + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES, + g_param_spec_uint ("max-size-bytes", "Max. size (kB)", + "Max. amount of data in the queue (bytes, 0=disable)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS, + g_param_spec_uint ("max-size-buffers", "Max. size (buffers)", + "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT, + DEFAULT_MAX_SIZE_BUFFERS, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME, + g_param_spec_uint64 ("max-size-time", "Max. size (ns)", + "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64, + DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EXTRA_SIZE_BYTES, + g_param_spec_uint ("extra-size-bytes", "Extra Size (kB)", + "Amount of data the queues can grow if one of them is empty (bytes, 0=disable)" + " (NOT IMPLEMENTED)", + 0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EXTRA_SIZE_BUFFERS, + g_param_spec_uint ("extra-size-buffers", "Extra Size (buffers)", + "Amount of buffers the queues can grow if one of them is empty (0=disable)" + " (NOT IMPLEMENTED)", + 0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BUFFERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EXTRA_SIZE_TIME, + g_param_spec_uint64 ("extra-size-time", "Extra Size (ns)", + "Amount of time the queues can grow if one of them is empty (in ns, 0=disable)" + " (NOT IMPLEMENTED)", + 0, G_MAXUINT64, DEFAULT_EXTRA_SIZE_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstMultiQueue:use-buffering: + * + * Enable the buffering option in multiqueue so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + */ + g_object_class_install_property (gobject_class, PROP_USE_BUFFERING, + g_param_spec_boolean ("use-buffering", "Use buffering", + "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds", + DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + /** + * GstMultiQueue:low-percent: + * + * Low threshold percent for buffering to start. + */ + g_object_class_install_property (gobject_class, PROP_LOW_PERCENT, + g_param_spec_int ("low-percent", "Low percent", + "Low threshold for buffering to start. Only used if use-buffering is True " + "(Deprecated: use low-watermark instead)", + 0, 100, DEFAULT_LOW_WATERMARK * 100, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstMultiQueue:high-percent: + * + * High threshold percent for buffering to finish. + */ + g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT, + g_param_spec_int ("high-percent", "High percent", + "High threshold for buffering to finish. Only used if use-buffering is True " + "(Deprecated: use high-watermark instead)", + 0, 100, DEFAULT_HIGH_WATERMARK * 100, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstMultiQueue:low-watermark: + * + * Low threshold watermark for buffering to start. + * + * Since: 1.10 + */ + g_object_class_install_property (gobject_class, PROP_LOW_WATERMARK, + g_param_spec_double ("low-watermark", "Low watermark", + "Low threshold for buffering to start. Only used if use-buffering is True", + 0.0, 1.0, DEFAULT_LOW_WATERMARK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstMultiQueue:high-watermark: + * + * High threshold watermark for buffering to finish. + * + * Since: 1.10 + */ + g_object_class_install_property (gobject_class, PROP_HIGH_WATERMARK, + g_param_spec_double ("high-watermark", "High watermark", + "High threshold for buffering to finish. Only used if use-buffering is True", + 0.0, 1.0, DEFAULT_HIGH_WATERMARK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstMultiQueue:sync-by-running-time: + * + * If enabled multiqueue will synchronize deactivated or not-linked streams + * to the activated and linked streams by taking the running time. + * Otherwise multiqueue will synchronize the deactivated or not-linked + * streams by keeping the order in which buffers and events arrived compared + * to active and linked streams. + */ + g_object_class_install_property (gobject_class, PROP_SYNC_BY_RUNNING_TIME, + g_param_spec_boolean ("sync-by-running-time", "Sync By Running Time", + "Synchronize deactivated or not-linked streams by running time", + DEFAULT_SYNC_BY_RUNNING_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_USE_INTERLEAVE, + g_param_spec_boolean ("use-interleave", "Use interleave", + "Adjust time limits based on input interleave", + DEFAULT_USE_INTERLEAVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_UNLINKED_CACHE_TIME, + g_param_spec_uint64 ("unlinked-cache-time", "Unlinked cache time (ns)", + "Extra buffering in time for unlinked streams (if 'sync-by-running-time')", + 0, G_MAXUINT64, DEFAULT_UNLINKED_CACHE_TIME, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MINIMUM_INTERLEAVE, + g_param_spec_uint64 ("min-interleave-time", "Minimum interleave time", + "Minimum extra buffering for deinterleaving (size of the queues) when use-interleave=true", + 0, G_MAXUINT64, DEFAULT_MINIMUM_INTERLEAVE, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_multi_queue_finalize; + + gst_element_class_set_static_metadata (gstelement_class, + "MultiQueue", + "Generic", "Multiple data queue", "Edward Hervey "); + gst_element_class_add_static_pad_template_with_gtype (gstelement_class, + &sinktemplate, GST_TYPE_MULTIQUEUE_PAD); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_multi_queue_request_new_pad); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_multi_queue_release_pad); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_multi_queue_change_state); +} + +static void +gst_multi_queue_init (GstMultiQueue * mqueue) +{ + mqueue->nbqueues = 0; + mqueue->queues = NULL; + + mqueue->max_size.bytes = DEFAULT_MAX_SIZE_BYTES; + mqueue->max_size.visible = DEFAULT_MAX_SIZE_BUFFERS; + mqueue->max_size.time = DEFAULT_MAX_SIZE_TIME; + + mqueue->extra_size.bytes = DEFAULT_EXTRA_SIZE_BYTES; + mqueue->extra_size.visible = DEFAULT_EXTRA_SIZE_BUFFERS; + mqueue->extra_size.time = DEFAULT_EXTRA_SIZE_TIME; + + mqueue->use_buffering = DEFAULT_USE_BUFFERING; + mqueue->low_watermark = DEFAULT_LOW_WATERMARK * MAX_BUFFERING_LEVEL; + mqueue->high_watermark = DEFAULT_HIGH_WATERMARK * MAX_BUFFERING_LEVEL; + + mqueue->sync_by_running_time = DEFAULT_SYNC_BY_RUNNING_TIME; + mqueue->use_interleave = DEFAULT_USE_INTERLEAVE; + mqueue->min_interleave_time = DEFAULT_MINIMUM_INTERLEAVE; + mqueue->unlinked_cache_time = DEFAULT_UNLINKED_CACHE_TIME; + + mqueue->counter = 1; + mqueue->highid = -1; + mqueue->high_time = GST_CLOCK_STIME_NONE; + + g_mutex_init (&mqueue->qlock); + g_mutex_init (&mqueue->buffering_post_lock); +} + +static void +gst_multi_queue_finalize (GObject * object) +{ + GstMultiQueue *mqueue = GST_MULTI_QUEUE (object); + + g_list_foreach (mqueue->queues, (GFunc) gst_single_queue_free, NULL); + g_list_free (mqueue->queues); + mqueue->queues = NULL; + mqueue->queues_cookie++; + + /* free/unref instance data */ + g_mutex_clear (&mqueue->qlock); + g_mutex_clear (&mqueue->buffering_post_lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +#define SET_CHILD_PROPERTY(mq,format) G_STMT_START { \ + GList * tmp = mq->queues; \ + while (tmp) { \ + GstSingleQueue *q = (GstSingleQueue*)tmp->data; \ + q->max_size.format = mq->max_size.format; \ + update_buffering (mq, q); \ + gst_data_queue_limits_changed (q->queue); \ + tmp = g_list_next(tmp); \ + }; \ +} G_STMT_END + +static void +gst_multi_queue_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMultiQueue *mq = GST_MULTI_QUEUE (object); + + switch (prop_id) { + case PROP_MAX_SIZE_BYTES: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + mq->max_size.bytes = g_value_get_uint (value); + SET_CHILD_PROPERTY (mq, bytes); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); + break; + case PROP_MAX_SIZE_BUFFERS: + { + GList *tmp; + gint new_size = g_value_get_uint (value); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + mq->max_size.visible = new_size; + + tmp = mq->queues; + while (tmp) { + GstDataQueueSize size; + GstSingleQueue *q = (GstSingleQueue *) tmp->data; + gst_data_queue_get_level (q->queue, &size); + + GST_DEBUG_OBJECT (mq, "Queue %d: Requested buffers size: %d," + " current: %d, current max %d", q->id, new_size, size.visible, + q->max_size.visible); + + /* do not reduce max size below current level if the single queue + * has grown because of empty queue */ + if (new_size == 0) { + q->max_size.visible = new_size; + } else if (q->max_size.visible == 0) { + q->max_size.visible = MAX (new_size, size.visible); + } else if (new_size > size.visible) { + q->max_size.visible = new_size; + } + update_buffering (mq, q); + gst_data_queue_limits_changed (q->queue); + tmp = g_list_next (tmp); + } + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); + + break; + } + case PROP_MAX_SIZE_TIME: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + mq->max_size.time = g_value_get_uint64 (value); + SET_CHILD_PROPERTY (mq, time); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); + break; + case PROP_EXTRA_SIZE_BYTES: + mq->extra_size.bytes = g_value_get_uint (value); + break; + case PROP_EXTRA_SIZE_BUFFERS: + mq->extra_size.visible = g_value_get_uint (value); + break; + case PROP_EXTRA_SIZE_TIME: + mq->extra_size.time = g_value_get_uint64 (value); + break; + case PROP_USE_BUFFERING: + mq->use_buffering = g_value_get_boolean (value); + recheck_buffering_status (mq); + break; + case PROP_LOW_PERCENT: + mq->low_watermark = g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + /* Recheck buffering status - the new low_watermark value might + * be above the current fill level. If the old low_watermark one + * was below the current level, this means that mq->buffering is + * disabled and needs to be re-enabled. */ + recheck_buffering_status (mq); + break; + case PROP_HIGH_PERCENT: + mq->high_watermark = g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + recheck_buffering_status (mq); + break; + case PROP_LOW_WATERMARK: + mq->low_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + recheck_buffering_status (mq); + break; + case PROP_HIGH_WATERMARK: + mq->high_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + recheck_buffering_status (mq); + break; + case PROP_SYNC_BY_RUNNING_TIME: + mq->sync_by_running_time = g_value_get_boolean (value); + break; + case PROP_USE_INTERLEAVE: + mq->use_interleave = g_value_get_boolean (value); + break; + case PROP_UNLINKED_CACHE_TIME: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + mq->unlinked_cache_time = g_value_get_uint64 (value); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); + break; + case PROP_MINIMUM_INTERLEAVE: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + mq->min_interleave_time = g_value_get_uint64 (value); + if (mq->use_interleave) + calculate_interleave (mq, NULL); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_multi_queue_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstMultiQueue *mq = GST_MULTI_QUEUE (object); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + switch (prop_id) { + case PROP_EXTRA_SIZE_BYTES: + g_value_set_uint (value, mq->extra_size.bytes); + break; + case PROP_EXTRA_SIZE_BUFFERS: + g_value_set_uint (value, mq->extra_size.visible); + break; + case PROP_EXTRA_SIZE_TIME: + g_value_set_uint64 (value, mq->extra_size.time); + break; + case PROP_MAX_SIZE_BYTES: + g_value_set_uint (value, mq->max_size.bytes); + break; + case PROP_MAX_SIZE_BUFFERS: + g_value_set_uint (value, mq->max_size.visible); + break; + case PROP_MAX_SIZE_TIME: + g_value_set_uint64 (value, mq->max_size.time); + break; + case PROP_USE_BUFFERING: + g_value_set_boolean (value, mq->use_buffering); + break; + case PROP_LOW_PERCENT: + g_value_set_int (value, mq->low_watermark / BUF_LEVEL_PERCENT_FACTOR); + break; + case PROP_HIGH_PERCENT: + g_value_set_int (value, mq->high_watermark / BUF_LEVEL_PERCENT_FACTOR); + break; + case PROP_LOW_WATERMARK: + g_value_set_double (value, mq->low_watermark / + (gdouble) MAX_BUFFERING_LEVEL); + break; + case PROP_HIGH_WATERMARK: + g_value_set_double (value, mq->high_watermark / + (gdouble) MAX_BUFFERING_LEVEL); + break; + case PROP_SYNC_BY_RUNNING_TIME: + g_value_set_boolean (value, mq->sync_by_running_time); + break; + case PROP_USE_INTERLEAVE: + g_value_set_boolean (value, mq->use_interleave); + break; + case PROP_UNLINKED_CACHE_TIME: + g_value_set_uint64 (value, mq->unlinked_cache_time); + break; + case PROP_MINIMUM_INTERLEAVE: + g_value_set_uint64 (value, mq->min_interleave_time); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); +} + +static GstIterator * +gst_multi_queue_iterate_internal_links (GstPad * pad, GstObject * parent) +{ + GstIterator *it = NULL; + GstPad *opad; + GstSingleQueue *squeue; + GstMultiQueue *mq = GST_MULTI_QUEUE (parent); + GValue val = { 0, }; + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + squeue = gst_pad_get_element_private (pad); + if (!squeue) + goto out; + + if (squeue->sinkpad == pad) + opad = gst_object_ref (squeue->srcpad); + else if (squeue->srcpad == pad) + opad = gst_object_ref (squeue->sinkpad); + else + goto out; + + g_value_init (&val, GST_TYPE_PAD); + g_value_set_object (&val, opad); + it = gst_iterator_new_single (GST_TYPE_PAD, &val); + g_value_unset (&val); + + gst_object_unref (opad); + +out: + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + return it; +} + + +/* + * GstElement methods + */ + +static GstPad * +gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp, + const gchar * name, const GstCaps * caps) +{ + GstMultiQueue *mqueue = GST_MULTI_QUEUE (element); + GstSingleQueue *squeue; + GstPad *new_pad; + guint temp_id = -1; + + if (name) { + sscanf (name + 4, "_%u", &temp_id); + GST_LOG_OBJECT (element, "name : %s (id %d)", GST_STR_NULL (name), temp_id); + } + + /* Create a new single queue, add the sink and source pad and return the sink pad */ + squeue = gst_single_queue_new (mqueue, temp_id); + + new_pad = squeue ? squeue->sinkpad : NULL; + + GST_DEBUG_OBJECT (mqueue, "Returning pad %" GST_PTR_FORMAT, new_pad); + + return new_pad; +} + +static void +gst_multi_queue_release_pad (GstElement * element, GstPad * pad) +{ + GstMultiQueue *mqueue = GST_MULTI_QUEUE (element); + GstSingleQueue *sq = NULL; + GList *tmp; + + GST_LOG_OBJECT (element, "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + GST_MULTI_QUEUE_MUTEX_LOCK (mqueue); + /* Find which single queue it belongs to, knowing that it should be a sinkpad */ + for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) { + sq = (GstSingleQueue *) tmp->data; + + if (sq->sinkpad == pad) + break; + } + + if (!tmp) { + GST_WARNING_OBJECT (mqueue, "That pad doesn't belong to this element ???"); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + return; + } + + /* FIXME: The removal of the singlequeue should probably not happen until it + * finishes draining */ + + /* remove it from the list */ + mqueue->queues = g_list_delete_link (mqueue->queues, tmp); + mqueue->queues_cookie++; + + /* FIXME : recompute next-non-linked */ + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + + /* delete SingleQueue */ + gst_data_queue_set_flushing (sq->queue, TRUE); + + gst_pad_set_active (sq->srcpad, FALSE); + gst_pad_set_active (sq->sinkpad, FALSE); + gst_pad_set_element_private (sq->srcpad, NULL); + gst_pad_set_element_private (sq->sinkpad, NULL); + gst_element_remove_pad (element, sq->srcpad); + gst_element_remove_pad (element, sq->sinkpad); + gst_single_queue_free (sq); +} + +static GstStateChangeReturn +gst_multi_queue_change_state (GstElement * element, GstStateChange transition) +{ + GstMultiQueue *mqueue = GST_MULTI_QUEUE (element); + GstSingleQueue *sq = NULL; + GstStateChangeReturn result; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED:{ + GList *tmp; + + /* Set all pads to non-flushing */ + GST_MULTI_QUEUE_MUTEX_LOCK (mqueue); + for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) { + sq = (GstSingleQueue *) tmp->data; + sq->flushing = FALSE; + } + + /* the visible limit might not have been set on single queues that have grown because of other queueus were empty */ + SET_CHILD_PROPERTY (mqueue, visible); + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + gst_multi_queue_post_buffering (mqueue); + + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY:{ + GList *tmp; + + /* Un-wait all waiting pads */ + GST_MULTI_QUEUE_MUTEX_LOCK (mqueue); + for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) { + sq = (GstSingleQueue *) tmp->data; + sq->flushing = TRUE; + g_cond_signal (&sq->turn); + + sq->last_query = FALSE; + g_cond_signal (&sq->query_handled); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + break; + } + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + default: + break; + } + + return result; +} + +static gboolean +gst_single_queue_start (GstMultiQueue * mq, GstSingleQueue * sq) +{ + GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id); + return gst_pad_start_task (sq->srcpad, + (GstTaskFunction) gst_multi_queue_loop, sq->srcpad, NULL); +} + +static gboolean +gst_single_queue_pause (GstMultiQueue * mq, GstSingleQueue * sq) +{ + gboolean result; + + GST_LOG_OBJECT (mq, "SingleQueue %d : pausing task", sq->id); + result = gst_pad_pause_task (sq->srcpad); + sq->sink_tainted = sq->src_tainted = TRUE; + return result; +} + +static gboolean +gst_single_queue_stop (GstMultiQueue * mq, GstSingleQueue * sq) +{ + gboolean result; + + GST_LOG_OBJECT (mq, "SingleQueue %d : stopping task", sq->id); + result = gst_pad_stop_task (sq->srcpad); + sq->sink_tainted = sq->src_tainted = TRUE; + return result; +} + +static void +gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush, + gboolean full) +{ + GST_DEBUG_OBJECT (mq, "flush %s queue %d", (flush ? "start" : "stop"), + sq->id); + + if (flush) { + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->srcresult = GST_FLOW_FLUSHING; + gst_data_queue_set_flushing (sq->queue, TRUE); + + sq->flushing = TRUE; + + /* wake up non-linked task */ + GST_LOG_OBJECT (mq, "SingleQueue %d : waking up eventually waiting task", + sq->id); + g_cond_signal (&sq->turn); + sq->last_query = FALSE; + g_cond_signal (&sq->query_handled); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } else { + gst_single_queue_flush_queue (sq, full); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&sq->src_segment, GST_FORMAT_TIME); + sq->has_src_segment = FALSE; + /* All pads start off not-linked for a smooth kick-off */ + sq->srcresult = GST_FLOW_OK; + sq->pushed = FALSE; + sq->cur_time = 0; + sq->max_size.visible = mq->max_size.visible; + sq->is_eos = FALSE; + sq->is_segment_done = FALSE; + sq->nextid = 0; + sq->oldid = 0; + sq->last_oldid = G_MAXUINT32; + sq->next_time = GST_CLOCK_STIME_NONE; + sq->last_time = GST_CLOCK_STIME_NONE; + sq->cached_sinktime = GST_CLOCK_STIME_NONE; + sq->group_high_time = GST_CLOCK_STIME_NONE; + gst_data_queue_set_flushing (sq->queue, FALSE); + + /* We will become active again on the next buffer/gap */ + sq->active = FALSE; + + /* Reset high time to be recomputed next */ + mq->high_time = GST_CLOCK_STIME_NONE; + + sq->flushing = FALSE; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } +} + +/* WITH LOCK TAKEN */ +static gint +get_buffering_level (GstSingleQueue * sq) +{ + GstDataQueueSize size; + gint buffering_level, tmp; + + gst_data_queue_get_level (sq->queue, &size); + + GST_DEBUG_OBJECT (sq->mqueue, + "queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT "/%" + G_GUINT64_FORMAT, sq->id, size.visible, sq->max_size.visible, + size.bytes, sq->max_size.bytes, sq->cur_time, sq->max_size.time); + + /* get bytes and time buffer levels and take the max */ + if (sq->is_eos || sq->is_segment_done || sq->srcresult == GST_FLOW_NOT_LINKED + || sq->is_sparse) { + buffering_level = MAX_BUFFERING_LEVEL; + } else { + buffering_level = 0; + if (sq->max_size.time > 0) { + tmp = + gst_util_uint64_scale (sq->cur_time, + MAX_BUFFERING_LEVEL, sq->max_size.time); + buffering_level = MAX (buffering_level, tmp); + } + if (sq->max_size.bytes > 0) { + tmp = + gst_util_uint64_scale_int (size.bytes, + MAX_BUFFERING_LEVEL, sq->max_size.bytes); + buffering_level = MAX (buffering_level, tmp); + } + } + + return buffering_level; +} + +/* WITH LOCK TAKEN */ +static void +update_buffering (GstMultiQueue * mq, GstSingleQueue * sq) +{ + gint buffering_level, percent; + + /* nothing to dowhen we are not in buffering mode */ + if (!mq->use_buffering) + return; + + buffering_level = get_buffering_level (sq); + + /* scale so that if buffering_level equals the high watermark, + * the percentage is 100% */ + percent = gst_util_uint64_scale (buffering_level, 100, mq->high_watermark); + /* clip */ + if (percent > 100) + percent = 100; + + if (mq->buffering) { + if (buffering_level >= mq->high_watermark) { + mq->buffering = FALSE; + } + /* make sure it increases */ + percent = MAX (mq->buffering_percent, percent); + + SET_PERCENT (mq, percent); + } else { + GList *iter; + gboolean is_buffering = TRUE; + + for (iter = mq->queues; iter; iter = g_list_next (iter)) { + GstSingleQueue *oq = (GstSingleQueue *) iter->data; + + if (get_buffering_level (oq) >= mq->high_watermark) { + is_buffering = FALSE; + + break; + } + } + + if (is_buffering && buffering_level < mq->low_watermark) { + mq->buffering = TRUE; + SET_PERCENT (mq, percent); + } + } +} + +static void +gst_multi_queue_post_buffering (GstMultiQueue * mq) +{ + GstMessage *msg = NULL; + + g_mutex_lock (&mq->buffering_post_lock); + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (mq->buffering_percent_changed) { + gint percent = mq->buffering_percent; + + mq->buffering_percent_changed = FALSE; + + GST_DEBUG_OBJECT (mq, "Going to post buffering: %d%%", percent); + msg = gst_message_new_buffering (GST_OBJECT_CAST (mq), percent); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (mq), msg); + + g_mutex_unlock (&mq->buffering_post_lock); +} + +static void +recheck_buffering_status (GstMultiQueue * mq) +{ + if (!mq->use_buffering && mq->buffering) { + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + mq->buffering = FALSE; + GST_DEBUG_OBJECT (mq, + "Buffering property disabled, but queue was still buffering; " + "setting buffering percentage to 100%%"); + SET_PERCENT (mq, 100); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + + if (mq->use_buffering) { + GList *tmp; + gint old_perc; + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + /* force buffering percentage to be recalculated */ + old_perc = mq->buffering_percent; + mq->buffering_percent = 0; + + tmp = mq->queues; + while (tmp) { + GstSingleQueue *q = (GstSingleQueue *) tmp->data; + update_buffering (mq, q); + gst_data_queue_limits_changed (q->queue); + tmp = g_list_next (tmp); + } + + GST_DEBUG_OBJECT (mq, + "Recalculated buffering percentage: old: %d%% new: %d%%", + old_perc, mq->buffering_percent); + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + + gst_multi_queue_post_buffering (mq); +} + +static void +calculate_interleave (GstMultiQueue * mq, GstSingleQueue * sq) +{ + GstClockTimeDiff low, high; + GstClockTime interleave, other_interleave = 0; + GList *tmp; + + low = high = GST_CLOCK_STIME_NONE; + interleave = mq->interleave; + /* Go over all single queues and calculate lowest/highest value */ + for (tmp = mq->queues; tmp; tmp = tmp->next) { + GstSingleQueue *oq = (GstSingleQueue *) tmp->data; + /* Ignore sparse streams for interleave calculation */ + if (oq->is_sparse) + continue; + /* If a stream is not active yet (hasn't received any buffers), set + * a maximum interleave to allow it to receive more data */ + if (!oq->active) { + GST_LOG_OBJECT (mq, + "queue %d is not active yet, forcing interleave to 5s", oq->id); + mq->interleave = 5 * GST_SECOND; + /* Update max-size time */ + mq->max_size.time = mq->interleave; + SET_CHILD_PROPERTY (mq, time); + goto beach; + } + + /* Calculate within each streaming thread */ + if (sq && sq->thread != oq->thread) { + if (oq->interleave > other_interleave) + other_interleave = oq->interleave; + continue; + } + + if (GST_CLOCK_STIME_IS_VALID (oq->cached_sinktime)) { + if (low == GST_CLOCK_STIME_NONE || oq->cached_sinktime < low) + low = oq->cached_sinktime; + if (high == GST_CLOCK_STIME_NONE || oq->cached_sinktime > high) + high = oq->cached_sinktime; + } + GST_LOG_OBJECT (mq, + "queue %d , sinktime:%" GST_STIME_FORMAT " low:%" GST_STIME_FORMAT + " high:%" GST_STIME_FORMAT, oq->id, + GST_STIME_ARGS (oq->cached_sinktime), GST_STIME_ARGS (low), + GST_STIME_ARGS (high)); + } + + if (GST_CLOCK_STIME_IS_VALID (low) && GST_CLOCK_STIME_IS_VALID (high)) { + interleave = high - low; + /* Padding of interleave and minimum value */ + interleave = (150 * interleave / 100) + mq->min_interleave_time; + if (sq) + sq->interleave = interleave; + + interleave = MAX (interleave, other_interleave); + + /* Update the stored interleave if: + * * No data has arrived yet (high == low) + * * Or it went higher + * * Or it went lower and we've gone past the previous interleave needed */ + if (high == low || interleave > mq->interleave || + ((mq->last_interleave_update + (2 * MIN (GST_SECOND, + mq->interleave)) < low) + && interleave < (mq->interleave * 3 / 4))) { + /* Update the interleave */ + mq->interleave = interleave; + mq->last_interleave_update = high; + /* Update max-size time */ + mq->max_size.time = mq->interleave; + SET_CHILD_PROPERTY (mq, time); + } + } + +beach: + GST_DEBUG_OBJECT (mq, + "low:%" GST_STIME_FORMAT " high:%" GST_STIME_FORMAT " interleave:%" + GST_TIME_FORMAT " mq->interleave:%" GST_TIME_FORMAT + " last_interleave_update:%" GST_STIME_FORMAT, GST_STIME_ARGS (low), + GST_STIME_ARGS (high), GST_TIME_ARGS (interleave), + GST_TIME_ARGS (mq->interleave), + GST_STIME_ARGS (mq->last_interleave_update)); +} + + +/* calculate the diff between running time on the sink and src of the queue. + * This is the total amount of time in the queue. + * WITH LOCK TAKEN */ +static void +update_time_level (GstMultiQueue * mq, GstSingleQueue * sq) +{ + GstClockTimeDiff sink_time, src_time; + + if (sq->sink_tainted) { + sink_time = sq->sinktime = my_segment_to_running_time (&sq->sink_segment, + sq->sink_segment.position); + + GST_DEBUG_OBJECT (mq, + "queue %d sink_segment.position:%" GST_TIME_FORMAT ", sink_time:%" + GST_STIME_FORMAT, sq->id, GST_TIME_ARGS (sq->sink_segment.position), + GST_STIME_ARGS (sink_time)); + + if (G_UNLIKELY (sq->last_time == GST_CLOCK_STIME_NONE)) { + /* If the single queue still doesn't have a last_time set, this means + * that nothing has been pushed out yet. + * In order for the high_time computation to be as efficient as possible, + * we set the last_time */ + sq->last_time = sink_time; + } + if (G_UNLIKELY (sink_time != GST_CLOCK_STIME_NONE)) { + /* if we have a time, we become untainted and use the time */ + sq->sink_tainted = FALSE; + if (mq->use_interleave) { + sq->cached_sinktime = sink_time; + calculate_interleave (mq, sq); + } + } + } else + sink_time = sq->sinktime; + + if (sq->src_tainted) { + GstSegment *segment; + gint64 position; + + if (sq->has_src_segment) { + segment = &sq->src_segment; + position = sq->src_segment.position; + } else { + /* + * If the src pad had no segment yet, use the sink segment + * to avoid signalling overrun if the received sink segment has a + * a position > max-size-time while the src pad time would be the default=0 + * + * This can happen when switching pads on chained/adaptive streams and the + * new chain has a segment with a much larger position + */ + segment = &sq->sink_segment; + position = sq->sink_segment.position; + } + + src_time = sq->srctime = my_segment_to_running_time (segment, position); + /* if we have a time, we become untainted and use the time */ + if (G_UNLIKELY (src_time != GST_CLOCK_STIME_NONE)) { + sq->src_tainted = FALSE; + } + } else + src_time = sq->srctime; + + GST_DEBUG_OBJECT (mq, + "queue %d, sink %" GST_STIME_FORMAT ", src %" GST_STIME_FORMAT, sq->id, + GST_STIME_ARGS (sink_time), GST_STIME_ARGS (src_time)); + + /* This allows for streams with out of order timestamping - sometimes the + * emerging timestamp is later than the arriving one(s) */ + if (G_LIKELY (GST_CLOCK_STIME_IS_VALID (sink_time) && + GST_CLOCK_STIME_IS_VALID (src_time) && sink_time > src_time)) + sq->cur_time = sink_time - src_time; + else + sq->cur_time = 0; + + /* updating the time level can change the buffering state */ + update_buffering (mq, sq); + + return; +} + +/* take a SEGMENT event and apply the values to segment, updating the time + * level of queue. */ +static void +apply_segment (GstMultiQueue * mq, GstSingleQueue * sq, GstEvent * event, + GstSegment * segment) +{ + gst_event_copy_segment (event, segment); + + /* now configure the values, we use these to track timestamps on the + * sinkpad. */ + if (segment->format != GST_FORMAT_TIME) { + /* non-time format, pretent the current time segment is closed with a + * 0 start and unknown stop time. */ + segment->format = GST_FORMAT_TIME; + segment->start = 0; + segment->stop = -1; + segment->time = 0; + } + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + /* Make sure we have a valid initial segment position (and not garbage + * from upstream) */ + if (segment->rate > 0.0) + segment->position = segment->start; + else + segment->position = segment->stop; + if (segment == &sq->sink_segment) + sq->sink_tainted = TRUE; + else { + sq->has_src_segment = TRUE; + sq->src_tainted = TRUE; + } + + GST_DEBUG_OBJECT (mq, + "queue %d, configured SEGMENT %" GST_SEGMENT_FORMAT, sq->id, segment); + + /* segment can update the time level of the queue */ + update_time_level (mq, sq); + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); +} + +/* take a buffer and update segment, updating the time level of the queue. */ +static void +apply_buffer (GstMultiQueue * mq, GstSingleQueue * sq, GstClockTime timestamp, + GstClockTime duration, GstSegment * segment) +{ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + /* if no timestamp is set, assume it's continuous with the previous + * time */ + if (timestamp == GST_CLOCK_TIME_NONE) + timestamp = segment->position; + + /* add duration */ + if (duration != GST_CLOCK_TIME_NONE) + timestamp += duration; + + GST_DEBUG_OBJECT (mq, "queue %d, %s position updated to %" GST_TIME_FORMAT, + sq->id, segment == &sq->sink_segment ? "sink" : "src", + GST_TIME_ARGS (timestamp)); + + segment->position = timestamp; + + if (segment == &sq->sink_segment) + sq->sink_tainted = TRUE; + else + sq->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (mq, sq); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); +} + +static void +apply_gap (GstMultiQueue * mq, GstSingleQueue * sq, GstEvent * event, + GstSegment * segment) +{ + GstClockTime timestamp; + GstClockTime duration; + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + gst_event_parse_gap (event, ×tamp, &duration); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + timestamp += duration; + } + + segment->position = timestamp; + + if (segment == &sq->sink_segment) + sq->sink_tainted = TRUE; + else + sq->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (mq, sq); + } + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); +} + +static GstClockTimeDiff +get_running_time (GstSegment * segment, GstMiniObject * object, gboolean end) +{ + GstClockTimeDiff time = GST_CLOCK_STIME_NONE; + + if (GST_IS_BUFFER (object)) { + GstBuffer *buf = GST_BUFFER_CAST (object); + GstClockTime btime = GST_BUFFER_DTS_OR_PTS (buf); + + if (GST_CLOCK_TIME_IS_VALID (btime)) { + if (end && GST_BUFFER_DURATION_IS_VALID (buf)) + btime += GST_BUFFER_DURATION (buf); + if (btime > segment->stop) + btime = segment->stop; + time = my_segment_to_running_time (segment, btime); + } + } else if (GST_IS_BUFFER_LIST (object)) { + GstBufferList *list = GST_BUFFER_LIST_CAST (object); + gint i, n; + GstBuffer *buf; + + n = gst_buffer_list_length (list); + for (i = 0; i < n; i++) { + GstClockTime btime; + buf = gst_buffer_list_get (list, i); + btime = GST_BUFFER_DTS_OR_PTS (buf); + if (GST_CLOCK_TIME_IS_VALID (btime)) { + if (end && GST_BUFFER_DURATION_IS_VALID (buf)) + btime += GST_BUFFER_DURATION (buf); + if (btime > segment->stop) + btime = segment->stop; + time = my_segment_to_running_time (segment, btime); + if (!end) + goto done; + } else if (!end) { + goto done; + } + } + } else if (GST_IS_EVENT (object)) { + GstEvent *event = GST_EVENT_CAST (object); + + /* For newsegment events return the running time of the start position */ + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + const GstSegment *new_segment; + + gst_event_parse_segment (event, &new_segment); + if (new_segment->format == GST_FORMAT_TIME) { + time = + my_segment_to_running_time ((GstSegment *) new_segment, + new_segment->start); + } + } + } + +done: + return time; +} + +static GstFlowReturn +gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq, + GstMiniObject * object, gboolean * allow_drop) +{ + GstFlowReturn result = sq->srcresult; + + if (GST_IS_BUFFER (object)) { + GstBuffer *buffer; + GstClockTime timestamp, duration; + + buffer = GST_BUFFER_CAST (object); + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + duration = GST_BUFFER_DURATION (buffer); + + apply_buffer (mq, sq, timestamp, duration, &sq->src_segment); + + /* Applying the buffer may have made the queue non-full again, unblock it if needed */ + gst_data_queue_limits_changed (sq->queue); + + if (G_UNLIKELY (*allow_drop)) { + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Dropping EOS buffer %p with ts %" GST_TIME_FORMAT, + sq->id, buffer, GST_TIME_ARGS (timestamp)); + gst_buffer_unref (buffer); + } else { + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT, + sq->id, buffer, GST_TIME_ARGS (timestamp)); + result = gst_pad_push (sq->srcpad, buffer); + } + } else if (GST_IS_EVENT (object)) { + GstEvent *event; + + event = GST_EVENT_CAST (object); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEGMENT_DONE: + *allow_drop = FALSE; + break; + case GST_EVENT_EOS: + result = GST_FLOW_EOS; + if (G_UNLIKELY (*allow_drop)) + *allow_drop = FALSE; + break; + case GST_EVENT_STREAM_START: + result = GST_FLOW_OK; + if (G_UNLIKELY (*allow_drop)) + *allow_drop = FALSE; + break; + case GST_EVENT_SEGMENT: + apply_segment (mq, sq, event, &sq->src_segment); + /* Applying the segment may have made the queue non-full again, unblock it if needed */ + gst_data_queue_limits_changed (sq->queue); + if (G_UNLIKELY (*allow_drop)) { + result = GST_FLOW_OK; + *allow_drop = FALSE; + } + break; + case GST_EVENT_GAP: + apply_gap (mq, sq, event, &sq->src_segment); + /* Applying the gap may have made the queue non-full again, unblock it if needed */ + gst_data_queue_limits_changed (sq->queue); + break; + default: + break; + } + + if (G_UNLIKELY (*allow_drop)) { + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Dropping EOS event %p of type %s", + sq->id, event, GST_EVENT_TYPE_NAME (event)); + gst_event_unref (event); + } else { + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Pushing event %p of type %s", + sq->id, event, GST_EVENT_TYPE_NAME (event)); + + gst_pad_push_event (sq->srcpad, event); + } + } else if (GST_IS_QUERY (object)) { + GstQuery *query; + gboolean res; + + query = GST_QUERY_CAST (object); + + if (G_UNLIKELY (*allow_drop)) { + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Dropping EOS query %p", sq->id, query); + gst_query_unref (query); + res = FALSE; + } else { + res = gst_pad_peer_query (sq->srcpad, query); + } + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->last_query = res; + sq->last_handled_query = query; + g_cond_signal (&sq->query_handled); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } else { + g_warning ("Unexpected object in singlequeue %u (refcounting problem?)", + sq->id); + } + return result; + + /* ERRORS */ +} + +static GstMiniObject * +gst_multi_queue_item_steal_object (GstMultiQueueItem * item) +{ + GstMiniObject *res; + + res = item->object; + item->object = NULL; + + return res; +} + +static void +gst_multi_queue_item_destroy (GstMultiQueueItem * item) +{ + if (!item->is_query && item->object) + gst_mini_object_unref (item->object); + g_slice_free (GstMultiQueueItem, item); +} + +/* takes ownership of passed mini object! */ +static GstMultiQueueItem * +gst_multi_queue_buffer_item_new (GstMiniObject * object, guint32 curid) +{ + GstMultiQueueItem *item; + + item = g_slice_new (GstMultiQueueItem); + item->object = object; + item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy; + item->posid = curid; + item->is_query = GST_IS_QUERY (object); + + item->size = gst_buffer_get_size (GST_BUFFER_CAST (object)); + item->duration = GST_BUFFER_DURATION (object); + if (item->duration == GST_CLOCK_TIME_NONE) + item->duration = 0; + item->visible = TRUE; + return item; +} + +static GstMultiQueueItem * +gst_multi_queue_mo_item_new (GstMiniObject * object, guint32 curid) +{ + GstMultiQueueItem *item; + + item = g_slice_new (GstMultiQueueItem); + item->object = object; + item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy; + item->posid = curid; + item->is_query = GST_IS_QUERY (object); + + item->size = 0; + item->duration = 0; + item->visible = FALSE; + return item; +} + +/* Each main loop attempts to push buffers until the return value + * is not-linked. not-linked pads are not allowed to push data beyond + * any linked pads, so they don't 'rush ahead of the pack'. + */ +static void +gst_multi_queue_loop (GstPad * pad) +{ + GstSingleQueue *sq; + GstMultiQueueItem *item; + GstDataQueueItem *sitem; + GstMultiQueue *mq; + GstMiniObject *object = NULL; + guint32 newid; + GstFlowReturn result; + GstClockTimeDiff next_time; + gboolean is_buffer; + gboolean do_update_buffering = FALSE; + gboolean dropping = FALSE; + + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = sq->mqueue; + +next: + GST_DEBUG_OBJECT (mq, "SingleQueue %d : trying to pop an object", sq->id); + + if (sq->flushing) + goto out_flushing; + + /* Get something from the queue, blocking until that happens, or we get + * flushed */ + if (!(gst_data_queue_pop (sq->queue, &sitem))) + goto out_flushing; + + item = (GstMultiQueueItem *) sitem; + newid = item->posid; + + /* steal the object and destroy the item */ + object = gst_multi_queue_item_steal_object (item); + gst_multi_queue_item_destroy (item); + + is_buffer = GST_IS_BUFFER (object); + + /* Get running time of the item. Events will have GST_CLOCK_STIME_NONE */ + next_time = get_running_time (&sq->src_segment, object, FALSE); + + GST_LOG_OBJECT (mq, "SingleQueue %d : newid:%d , oldid:%d", + sq->id, newid, sq->last_oldid); + + /* If we're not-linked, we do some extra work because we might need to + * wait before pushing. If we're linked but there's a gap in the IDs, + * or it's the first loop, or we just passed the previous highid, + * we might need to wake some sleeping pad up, so there's extra work + * there too */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->srcresult == GST_FLOW_NOT_LINKED + || (sq->last_oldid == G_MAXUINT32) || (newid != (sq->last_oldid + 1)) + || sq->last_oldid > mq->highid) { + GST_LOG_OBJECT (mq, "CHECKING sq->srcresult: %s", + gst_flow_get_name (sq->srcresult)); + + /* Check again if we're flushing after the lock is taken, + * the flush flag might have been changed in the meantime */ + if (sq->flushing) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + goto out_flushing; + } + + /* Update the nextid so other threads know when to wake us up */ + sq->nextid = newid; + /* Take into account the extra cache time since we're unlinked */ + if (GST_CLOCK_STIME_IS_VALID (next_time)) + next_time += mq->unlinked_cache_time; + sq->next_time = next_time; + + /* Update the oldid (the last ID we output) for highid tracking */ + if (sq->last_oldid != G_MAXUINT32) + sq->oldid = sq->last_oldid; + + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + gboolean should_wait; + /* Go to sleep until it's time to push this buffer */ + + /* Recompute the highid */ + compute_high_id (mq); + /* Recompute the high time */ + compute_high_time (mq, sq->groupid); + + GST_DEBUG_OBJECT (mq, + "groupid %d high_time %" GST_STIME_FORMAT " next_time %" + GST_STIME_FORMAT, sq->groupid, GST_STIME_ARGS (sq->group_high_time), + GST_STIME_ARGS (next_time)); + + if (mq->sync_by_running_time) { + if (sq->group_high_time == GST_CLOCK_STIME_NONE) { + should_wait = GST_CLOCK_STIME_IS_VALID (next_time) && + (mq->high_time == GST_CLOCK_STIME_NONE + || next_time > mq->high_time); + } else { + should_wait = GST_CLOCK_STIME_IS_VALID (next_time) && + next_time > sq->group_high_time; + } + } else + should_wait = newid > mq->highid; + + while (should_wait && sq->srcresult == GST_FLOW_NOT_LINKED) { + + GST_DEBUG_OBJECT (mq, + "queue %d sleeping for not-linked wakeup with " + "newid %u, highid %u, next_time %" GST_STIME_FORMAT + ", high_time %" GST_STIME_FORMAT, sq->id, newid, mq->highid, + GST_STIME_ARGS (next_time), GST_STIME_ARGS (sq->group_high_time)); + + /* Wake up all non-linked pads before we sleep */ + wake_up_next_non_linked (mq); + + mq->numwaiting++; + g_cond_wait (&sq->turn, &mq->qlock); + mq->numwaiting--; + + if (sq->flushing) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + goto out_flushing; + } + + /* Recompute the high time and ID */ + compute_high_time (mq, sq->groupid); + compute_high_id (mq); + + GST_DEBUG_OBJECT (mq, "queue %d woken from sleeping for not-linked " + "wakeup with newid %u, highid %u, next_time %" GST_STIME_FORMAT + ", high_time %" GST_STIME_FORMAT " mq high_time %" GST_STIME_FORMAT, + sq->id, newid, mq->highid, + GST_STIME_ARGS (next_time), GST_STIME_ARGS (sq->group_high_time), + GST_STIME_ARGS (mq->high_time)); + + if (mq->sync_by_running_time) { + if (sq->group_high_time == GST_CLOCK_STIME_NONE) { + should_wait = GST_CLOCK_STIME_IS_VALID (next_time) && + (mq->high_time == GST_CLOCK_STIME_NONE + || next_time > mq->high_time); + } else { + should_wait = GST_CLOCK_STIME_IS_VALID (next_time) && + next_time > sq->group_high_time; + } + } else + should_wait = newid > mq->highid; + } + + /* Re-compute the high_id in case someone else pushed */ + compute_high_id (mq); + compute_high_time (mq, sq->groupid); + } else { + compute_high_id (mq); + compute_high_time (mq, sq->groupid); + /* Wake up all non-linked pads */ + wake_up_next_non_linked (mq); + } + /* We're done waiting, we can clear the nextid and nexttime */ + sq->nextid = 0; + sq->next_time = GST_CLOCK_STIME_NONE; + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + if (sq->flushing) + goto out_flushing; + + GST_LOG_OBJECT (mq, "sq:%d BEFORE PUSHING sq->srcresult: %s", sq->id, + gst_flow_get_name (sq->srcresult)); + + /* Update time stats */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + next_time = get_running_time (&sq->src_segment, object, TRUE); + if (GST_CLOCK_STIME_IS_VALID (next_time)) { + if (sq->last_time == GST_CLOCK_STIME_NONE || sq->last_time < next_time) + sq->last_time = next_time; + if (mq->high_time == GST_CLOCK_STIME_NONE || mq->high_time <= next_time) { + /* Wake up all non-linked pads now that we advanced the high time */ + mq->high_time = next_time; + wake_up_next_non_linked (mq); + } + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + /* Try to push out the new object */ + result = gst_single_queue_push_one (mq, sq, object, &dropping); + object = NULL; + + /* Check if we pushed something already and if this is + * now a switch from an active to a non-active stream. + * + * If it is, we reset all the waiting streams, let them + * push another buffer to see if they're now active again. + * This allows faster switching between streams and prevents + * deadlocks if downstream does any waiting too. + */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->pushed && sq->srcresult == GST_FLOW_OK + && result == GST_FLOW_NOT_LINKED) { + GList *tmp; + + GST_LOG_OBJECT (mq, "SingleQueue %d : Changed from active to non-active", + sq->id); + + compute_high_id (mq); + compute_high_time (mq, sq->groupid); + do_update_buffering = TRUE; + + /* maybe no-one is waiting */ + if (mq->numwaiting > 0) { + /* Else figure out which singlequeue(s) need waking up */ + for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *sq2 = (GstSingleQueue *) tmp->data; + + if (sq2->srcresult == GST_FLOW_NOT_LINKED) { + GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq2->id); + sq2->pushed = FALSE; + sq2->srcresult = GST_FLOW_OK; + g_cond_signal (&sq2->turn); + } + } + } + } + + if (is_buffer) + sq->pushed = TRUE; + + /* now hold on a bit; + * can not simply throw this result to upstream, because + * that might already be onto another segment, so we have to make + * sure we are relaying the correct info wrt proper segment */ + if (result == GST_FLOW_EOS && !dropping && + sq->srcresult != GST_FLOW_NOT_LINKED) { + GST_DEBUG_OBJECT (mq, "starting EOS drop on sq %d", sq->id); + dropping = TRUE; + /* pretend we have not seen EOS yet for upstream's sake */ + result = sq->srcresult; + } else if (dropping && gst_data_queue_is_empty (sq->queue)) { + /* queue empty, so stop dropping + * we can commit the result we have now, + * which is either OK after a segment, or EOS */ + GST_DEBUG_OBJECT (mq, "committed EOS drop on sq %d", sq->id); + dropping = FALSE; + result = GST_FLOW_EOS; + } + sq->srcresult = result; + sq->last_oldid = newid; + + if (do_update_buffering) + update_buffering (mq, sq); + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_multi_queue_post_buffering (mq); + + GST_LOG_OBJECT (mq, "sq:%d AFTER PUSHING sq->srcresult: %s (is_eos:%d)", + sq->id, gst_flow_get_name (sq->srcresult), GST_PAD_IS_EOS (sq->srcpad)); + + /* Need to make sure wake up any sleeping pads when we exit */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (mq->numwaiting > 0 && (GST_PAD_IS_EOS (sq->srcpad) + || sq->srcresult == GST_FLOW_EOS)) { + compute_high_time (mq, sq->groupid); + compute_high_id (mq); + wake_up_next_non_linked (mq); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + if (dropping) + goto next; + + if (result != GST_FLOW_OK && result != GST_FLOW_NOT_LINKED + && result != GST_FLOW_EOS) + goto out_flushing; + + return; + +out_flushing: + { + if (object) + gst_mini_object_unref (object); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->last_query = FALSE; + g_cond_signal (&sq->query_handled); + + /* Post an error message if we got EOS while downstream + * has returned an error flow return. After EOS there + * will be no further buffer which could propagate the + * error upstream */ + if ((sq->is_eos || sq->is_segment_done) && sq->srcresult < GST_FLOW_EOS) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + GST_ELEMENT_FLOW_ERROR (mq, sq->srcresult); + } else { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + + /* upstream needs to see fatal result ASAP to shut things down, + * but might be stuck in one of our other full queues; + * so empty this one and trigger dynamic queue growth. At + * this point the srcresult is not OK, NOT_LINKED + * or EOS, i.e. a real failure */ + gst_single_queue_flush_queue (sq, FALSE); + single_queue_underrun_cb (sq->queue, sq); + gst_data_queue_set_flushing (sq->queue, TRUE); + gst_pad_pause_task (sq->srcpad); + GST_CAT_LOG_OBJECT (multi_queue_debug, mq, + "SingleQueue[%d] task paused, reason:%s", + sq->id, gst_flow_get_name (sq->srcresult)); + return; + } +} + +/** + * gst_multi_queue_chain: + * + * This is similar to GstQueue's chain function, except: + * _ we don't have leak behaviours, + * _ we push with a unique id (curid) + */ +static GstFlowReturn +gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstSingleQueue *sq; + GstMultiQueue *mq; + GstMultiQueueItem *item; + guint32 curid; + GstClockTime timestamp, duration; + + sq = gst_pad_get_element_private (pad); + mq = sq->mqueue; + + /* if eos, we are always full, so avoid hanging incoming indefinitely */ + if (sq->is_eos) + goto was_eos; + + sq->active = TRUE; + + /* Get a unique incrementing id */ + curid = g_atomic_int_add ((gint *) & mq->counter, 1); + + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + duration = GST_BUFFER_DURATION (buffer); + + GST_LOG_OBJECT (mq, + "SingleQueue %d : about to enqueue buffer %p with id %d (pts:%" + GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT " dur:%" GST_TIME_FORMAT ")", + sq->id, buffer, curid, GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), + GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), GST_TIME_ARGS (duration)); + + item = gst_multi_queue_buffer_item_new (GST_MINI_OBJECT_CAST (buffer), curid); + + /* Update interleave before pushing data into queue */ + if (mq->use_interleave) { + GstClockTime val = timestamp; + GstClockTimeDiff dval; + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (val == GST_CLOCK_TIME_NONE) + val = sq->sink_segment.position; + if (duration != GST_CLOCK_TIME_NONE) + val += duration; + + dval = my_segment_to_running_time (&sq->sink_segment, val); + if (GST_CLOCK_STIME_IS_VALID (dval)) { + sq->cached_sinktime = dval; + GST_DEBUG_OBJECT (mq, + "Queue %d cached sink time now %" G_GINT64_FORMAT " %" + GST_STIME_FORMAT, sq->id, sq->cached_sinktime, + GST_STIME_ARGS (sq->cached_sinktime)); + calculate_interleave (mq, sq); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + + if (!(gst_data_queue_push (sq->queue, (GstDataQueueItem *) item))) + goto flushing; + + /* update time level, we must do this after pushing the data in the queue so + * that we never end up filling the queue first. */ + apply_buffer (mq, sq, timestamp, duration, &sq->sink_segment); + +done: + return sq->srcresult; + + /* ERRORS */ +flushing: + { + GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s", + sq->id, gst_flow_get_name (sq->srcresult)); + gst_multi_queue_item_destroy (item); + goto done; + } +was_eos: + { + GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return EOS"); + gst_buffer_unref (buffer); + return GST_FLOW_EOS; + } +} + +static gboolean +gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstSingleQueue *sq; + GstMultiQueue *mq; + + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = (GstMultiQueue *) gst_pad_get_parent (pad); + + /* mq is NULL if the pad is activated/deactivated before being + * added to the multiqueue */ + if (mq) + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + /* All pads start off linked until they push one buffer */ + sq->srcresult = GST_FLOW_OK; + sq->pushed = FALSE; + gst_data_queue_set_flushing (sq->queue, FALSE); + } else { + sq->srcresult = GST_FLOW_FLUSHING; + sq->last_query = FALSE; + g_cond_signal (&sq->query_handled); + gst_data_queue_set_flushing (sq->queue, TRUE); + + /* Wait until streaming thread has finished */ + if (mq) + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + GST_PAD_STREAM_LOCK (pad); + if (mq) + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + gst_data_queue_flush (sq->queue); + if (mq) + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + GST_PAD_STREAM_UNLOCK (pad); + if (mq) + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + } + res = TRUE; + break; + default: + res = FALSE; + break; + } + + if (mq) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_object_unref (mq); + } + + return res; +} + +static GstFlowReturn +gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstSingleQueue *sq; + GstMultiQueue *mq; + guint32 curid; + GstMultiQueueItem *item; + gboolean res = TRUE; + GstFlowReturn flowret = GST_FLOW_OK; + GstEventType type; + GstEvent *sref = NULL; + + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = (GstMultiQueue *) parent; + + type = GST_EVENT_TYPE (event); + + switch (type) { + case GST_EVENT_STREAM_START: + { + if (mq->sync_by_running_time) { + GstStreamFlags stream_flags; + gst_event_parse_stream_flags (event, &stream_flags); + if ((stream_flags & GST_STREAM_FLAG_SPARSE)) { + GST_INFO_OBJECT (mq, "SingleQueue %d is a sparse stream", sq->id); + sq->is_sparse = TRUE; + } + } + + sq->thread = g_thread_self (); + + /* Remove EOS flag */ + sq->is_eos = FALSE; + break; + } + case GST_EVENT_FLUSH_START: + GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush start event", + sq->id); + + res = gst_pad_push_event (sq->srcpad, event); + + gst_single_queue_flush (mq, sq, TRUE, FALSE); + gst_single_queue_pause (mq, sq); + goto done; + + case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush stop event", + sq->id); + + res = gst_pad_push_event (sq->srcpad, event); + + gst_single_queue_flush (mq, sq, FALSE, FALSE); + gst_single_queue_start (mq, sq); + goto done; + + case GST_EVENT_SEGMENT: + sq->is_segment_done = FALSE; + sref = gst_event_ref (event); + break; + case GST_EVENT_GAP: + /* take ref because the queue will take ownership and we need the event + * afterwards to update the segment */ + sref = gst_event_ref (event); + if (mq->use_interleave) { + GstClockTime val, dur; + GstClockTime stime; + gst_event_parse_gap (event, &val, &dur); + if (GST_CLOCK_TIME_IS_VALID (val)) { + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (GST_CLOCK_TIME_IS_VALID (dur)) + val += dur; + stime = my_segment_to_running_time (&sq->sink_segment, val); + if (GST_CLOCK_STIME_IS_VALID (stime)) { + sq->cached_sinktime = stime; + calculate_interleave (mq, sq); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + } + break; + + default: + if (!(GST_EVENT_IS_SERIALIZED (event))) { + res = gst_pad_push_event (sq->srcpad, event); + goto done; + } + break; + } + + /* if eos, we are always full, so avoid hanging incoming indefinitely */ + if (sq->is_eos) + goto was_eos; + + /* Get an unique incrementing id. */ + curid = g_atomic_int_add ((gint *) & mq->counter, 1); + + item = gst_multi_queue_mo_item_new ((GstMiniObject *) event, curid); + + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Enqueuing event %p of type %s with id %d", + sq->id, event, GST_EVENT_TYPE_NAME (event), curid); + + if (!gst_data_queue_push (sq->queue, (GstDataQueueItem *) item)) + goto flushing; + + /* mark EOS when we received one, we must do that after putting the + * buffer in the queue because EOS marks the buffer as filled. */ + switch (type) { + case GST_EVENT_SEGMENT_DONE: + sq->is_segment_done = TRUE; + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + update_buffering (mq, sq); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + single_queue_overrun_cb (sq->queue, sq); + gst_multi_queue_post_buffering (mq); + break; + case GST_EVENT_EOS: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->is_eos = TRUE; + + /* Post an error message if we got EOS while downstream + * has returned an error flow return. After EOS there + * will be no further buffer which could propagate the + * error upstream */ + if (sq->srcresult < GST_FLOW_EOS) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + GST_ELEMENT_FLOW_ERROR (mq, sq->srcresult); + } else { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } + + /* EOS affects the buffering state */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + update_buffering (mq, sq); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + single_queue_overrun_cb (sq->queue, sq); + gst_multi_queue_post_buffering (mq); + break; + case GST_EVENT_SEGMENT: + apply_segment (mq, sq, sref, &sq->sink_segment); + gst_event_unref (sref); + /* a new segment allows us to accept more buffers if we got EOS + * from downstream */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->srcresult == GST_FLOW_EOS) + sq->srcresult = GST_FLOW_OK; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + break; + case GST_EVENT_GAP: + sq->active = TRUE; + apply_gap (mq, sq, sref, &sq->sink_segment); + gst_event_unref (sref); + default: + break; + } + +done: + if (res == FALSE) + flowret = GST_FLOW_ERROR; + GST_DEBUG_OBJECT (mq, "SingleQueue %d : returning %s", sq->id, + gst_flow_get_name (flowret)); + return flowret; + +flushing: + { + GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s", + sq->id, gst_flow_get_name (sq->srcresult)); + if (sref) + gst_event_unref (sref); + gst_multi_queue_item_destroy (item); + return sq->srcresult; + } +was_eos: + { + GST_DEBUG_OBJECT (mq, "we are EOS, dropping event, return GST_FLOW_EOS"); + gst_event_unref (event); + return GST_FLOW_EOS; + } +} + +static gboolean +gst_multi_queue_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res; + GstSingleQueue *sq; + GstMultiQueue *mq; + + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = (GstMultiQueue *) parent; + + switch (GST_QUERY_TYPE (query)) { + default: + if (GST_QUERY_IS_SERIALIZED (query)) { + guint32 curid; + GstMultiQueueItem *item; + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->srcresult != GST_FLOW_OK) + goto out_flushing; + + /* serialized events go in the queue. We need to be certain that we + * don't cause deadlocks waiting for the query return value. We check if + * the queue is empty (nothing is blocking downstream and the query can + * be pushed for sure) or we are not buffering. If we are buffering, + * the pipeline waits to unblock downstream until our queue fills up + * completely, which can not happen if we block on the query.. + * Therefore we only potentially block when we are not buffering. */ + if (!mq->use_buffering || gst_data_queue_is_empty (sq->queue)) { + /* Get an unique incrementing id. */ + curid = g_atomic_int_add ((gint *) & mq->counter, 1); + + item = gst_multi_queue_mo_item_new ((GstMiniObject *) query, curid); + + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Enqueuing query %p of type %s with id %d", + sq->id, query, GST_QUERY_TYPE_NAME (query), curid); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + res = gst_data_queue_push (sq->queue, (GstDataQueueItem *) item); + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (!res || sq->flushing) + goto out_flushing; + /* it might be that the query has been taken out of the queue + * while we were unlocked. So, we need to check if the last + * handled query is the same one than the one we just + * pushed. If it is, we don't need to wait for the condition + * variable, otherwise we wait for the condition variable to + * be signaled. */ + while (!sq->flushing && sq->srcresult == GST_FLOW_OK + && sq->last_handled_query != query) + g_cond_wait (&sq->query_handled, &mq->qlock); + res = sq->last_query; + sq->last_handled_query = NULL; + } else { + GST_DEBUG_OBJECT (mq, "refusing query, we are buffering and the " + "queue is not empty"); + res = FALSE; + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } else { + /* default handling */ + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; + +out_flushing: + { + GST_DEBUG_OBJECT (mq, "Flushing"); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + return FALSE; + } +} + +static gboolean +gst_multi_queue_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + GstMultiQueue *mq; + GstSingleQueue *sq; + gboolean result; + + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = sq->mqueue; + + GST_DEBUG_OBJECT (mq, "SingleQueue %d", sq->id); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + gst_single_queue_flush (mq, sq, FALSE, TRUE); + result = parent ? gst_single_queue_start (mq, sq) : TRUE; + } else { + gst_single_queue_flush (mq, sq, TRUE, TRUE); + result = gst_single_queue_stop (mq, sq); + } + break; + default: + result = FALSE; + break; + } + return result; +} + +static gboolean +gst_multi_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstSingleQueue *sq = gst_pad_get_element_private (pad); + GstMultiQueue *mq = sq->mqueue; + gboolean ret; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_RECONFIGURE: + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + sq->srcresult = GST_FLOW_OK; + g_cond_signal (&sq->turn); + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + ret = gst_pad_push_event (sq->sinkpad, event); + break; + default: + ret = gst_pad_push_event (sq->sinkpad, event); + break; + } + + return ret; +} + +static gboolean +gst_multi_queue_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res; + + /* FIXME, Handle position offset depending on queue size */ + switch (GST_QUERY_TYPE (query)) { + default: + /* default handling */ + res = gst_pad_query_default (pad, parent, query); + break; + } + return res; +} + +/* + * Next-non-linked functions + */ + +/* WITH LOCK TAKEN */ +static void +wake_up_next_non_linked (GstMultiQueue * mq) +{ + GList *tmp; + + /* maybe no-one is waiting */ + if (mq->numwaiting < 1) + return; + + if (mq->sync_by_running_time && GST_CLOCK_STIME_IS_VALID (mq->high_time)) { + /* Else figure out which singlequeue(s) need waking up */ + for (tmp = mq->queues; tmp; tmp = tmp->next) { + GstSingleQueue *sq = (GstSingleQueue *) tmp->data; + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + GstClockTimeDiff high_time; + + if (GST_CLOCK_STIME_IS_VALID (sq->group_high_time)) + high_time = sq->group_high_time; + else + high_time = mq->high_time; + + if (GST_CLOCK_STIME_IS_VALID (sq->next_time) && + GST_CLOCK_STIME_IS_VALID (high_time) + && sq->next_time <= high_time) { + GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id); + g_cond_signal (&sq->turn); + } + } + } + } else { + /* Else figure out which singlequeue(s) need waking up */ + for (tmp = mq->queues; tmp; tmp = tmp->next) { + GstSingleQueue *sq = (GstSingleQueue *) tmp->data; + if (sq->srcresult == GST_FLOW_NOT_LINKED && + sq->nextid != 0 && sq->nextid <= mq->highid) { + GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id); + g_cond_signal (&sq->turn); + } + } + } +} + +/* WITH LOCK TAKEN */ +static void +compute_high_id (GstMultiQueue * mq) +{ + /* The high-id is either the highest id among the linked pads, or if all + * pads are not-linked, it's the lowest not-linked pad */ + GList *tmp; + guint32 lowest = G_MAXUINT32; + guint32 highid = G_MAXUINT32; + + for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *sq = (GstSingleQueue *) tmp->data; + + GST_LOG_OBJECT (mq, "inspecting sq:%d , nextid:%d, oldid:%d, srcresult:%s", + sq->id, sq->nextid, sq->oldid, gst_flow_get_name (sq->srcresult)); + + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + /* No need to consider queues which are not waiting */ + if (sq->nextid == 0) { + GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id); + continue; + } + + if (sq->nextid < lowest) + lowest = sq->nextid; + } else if (!GST_PAD_IS_EOS (sq->srcpad) && sq->srcresult != GST_FLOW_EOS) { + /* If we don't have a global highid, or the global highid is lower than + * this single queue's last outputted id, store the queue's one, + * unless the singlequeue output is at EOS */ + if ((highid == G_MAXUINT32) || (sq->oldid > highid)) + highid = sq->oldid; + } + } + + if (highid == G_MAXUINT32 || lowest < highid) + mq->highid = lowest; + else + mq->highid = highid; + + GST_LOG_OBJECT (mq, "Highid is now : %u, lowest non-linked %u", mq->highid, + lowest); +} + +/* WITH LOCK TAKEN */ +static void +compute_high_time (GstMultiQueue * mq, guint groupid) +{ + /* The high-time is either the highest last time among the linked + * pads, or if all pads are not-linked, it's the lowest nex time of + * not-linked pad */ + GList *tmp; + GstClockTimeDiff highest = GST_CLOCK_STIME_NONE; + GstClockTimeDiff lowest = GST_CLOCK_STIME_NONE; + GstClockTimeDiff group_high = GST_CLOCK_STIME_NONE; + GstClockTimeDiff group_low = GST_CLOCK_STIME_NONE; + GstClockTimeDiff res; + /* Number of streams which belong to groupid */ + guint group_count = 0; + + if (!mq->sync_by_running_time) + /* return GST_CLOCK_STIME_NONE; */ + return; + + for (tmp = mq->queues; tmp; tmp = tmp->next) { + GstSingleQueue *sq = (GstSingleQueue *) tmp->data; + + GST_LOG_OBJECT (mq, + "inspecting sq:%d (group:%d) , next_time:%" GST_STIME_FORMAT + ", last_time:%" GST_STIME_FORMAT ", srcresult:%s", sq->id, sq->groupid, + GST_STIME_ARGS (sq->next_time), GST_STIME_ARGS (sq->last_time), + gst_flow_get_name (sq->srcresult)); + + if (sq->groupid == groupid) + group_count++; + + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + /* No need to consider queues which are not waiting */ + if (!GST_CLOCK_STIME_IS_VALID (sq->next_time)) { + GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id); + continue; + } + + if (lowest == GST_CLOCK_STIME_NONE || sq->next_time < lowest) + lowest = sq->next_time; + if (sq->groupid == groupid && (group_low == GST_CLOCK_STIME_NONE + || sq->next_time < group_low)) + group_low = sq->next_time; + } else if (!GST_PAD_IS_EOS (sq->srcpad) && sq->srcresult != GST_FLOW_EOS) { + /* If we don't have a global high time, or the global high time + * is lower than this single queue's last outputted time, store + * the queue's one, unless the singlequeue output is at EOS. */ + if (highest == GST_CLOCK_STIME_NONE + || (sq->last_time != GST_CLOCK_STIME_NONE && sq->last_time > highest)) + highest = sq->last_time; + if (sq->groupid == groupid && (group_high == GST_CLOCK_STIME_NONE + || (sq->last_time != GST_CLOCK_STIME_NONE + && sq->last_time > group_high))) + group_high = sq->last_time; + } + GST_LOG_OBJECT (mq, + "highest now %" GST_STIME_FORMAT " lowest %" GST_STIME_FORMAT, + GST_STIME_ARGS (highest), GST_STIME_ARGS (lowest)); + if (sq->groupid == groupid) + GST_LOG_OBJECT (mq, + "grouphigh %" GST_STIME_FORMAT " grouplow %" GST_STIME_FORMAT, + GST_STIME_ARGS (group_high), GST_STIME_ARGS (group_low)); + } + + if (highest == GST_CLOCK_STIME_NONE) + mq->high_time = lowest; + else + mq->high_time = highest; + + /* If there's only one stream of a given type, use the global high */ + if (group_count < 2) + res = GST_CLOCK_STIME_NONE; + else if (group_high == GST_CLOCK_STIME_NONE) + res = group_low; + else + res = group_high; + + GST_LOG_OBJECT (mq, "group count %d for groupid %u", group_count, groupid); + GST_LOG_OBJECT (mq, + "MQ High time is now : %" GST_STIME_FORMAT ", group %d high time %" + GST_STIME_FORMAT ", lowest non-linked %" GST_STIME_FORMAT, + GST_STIME_ARGS (mq->high_time), groupid, GST_STIME_ARGS (mq->high_time), + GST_STIME_ARGS (lowest)); + + for (tmp = mq->queues; tmp; tmp = tmp->next) { + GstSingleQueue *sq = (GstSingleQueue *) tmp->data; + if (groupid == sq->groupid) + sq->group_high_time = res; + } +} + +#define IS_FILLED(q, format, value) (((q)->max_size.format) != 0 && \ + ((q)->max_size.format) <= (value)) + +/* + * GstSingleQueue functions + */ +static void +single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq) +{ + GstMultiQueue *mq = sq->mqueue; + GList *tmp; + GstDataQueueSize size; + gboolean filled = TRUE; + gboolean empty_found = FALSE; + + gst_data_queue_get_level (sq->queue, &size); + + GST_LOG_OBJECT (mq, + "Single Queue %d: EOS %d, visible %u/%u, bytes %u/%u, time %" + G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, sq->id, sq->is_eos, size.visible, + sq->max_size.visible, size.bytes, sq->max_size.bytes, sq->cur_time, + sq->max_size.time); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + /* check if we reached the hard time/bytes limits; + time limit is only taken into account for non-sparse streams */ + if (sq->is_eos || IS_FILLED (sq, bytes, size.bytes) || + (!sq->is_sparse && IS_FILLED (sq, time, sq->cur_time))) { + goto done; + } + + /* Search for empty queues */ + for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *oq = (GstSingleQueue *) tmp->data; + + if (oq == sq) + continue; + + if (oq->srcresult == GST_FLOW_NOT_LINKED) { + GST_LOG_OBJECT (mq, "Queue %d is not-linked", oq->id); + continue; + } + + GST_LOG_OBJECT (mq, "Checking Queue %d", oq->id); + if (gst_data_queue_is_empty (oq->queue) && !oq->is_sparse) { + GST_LOG_OBJECT (mq, "Queue %d is empty", oq->id); + empty_found = TRUE; + break; + } + } + + /* if hard limits are not reached then we allow one more buffer in the full + * queue, but only if any of the other singelqueues are empty */ + if (empty_found) { + if (IS_FILLED (sq, visible, size.visible)) { + sq->max_size.visible = size.visible + 1; + GST_DEBUG_OBJECT (mq, + "Bumping single queue %d max visible to %d", + sq->id, sq->max_size.visible); + filled = FALSE; + } + } + +done: + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + /* Overrun is always forwarded, since this is blocking the upstream element */ + if (filled) { + GST_DEBUG_OBJECT (mq, "Queue %d is filled, signalling overrun", sq->id); + g_signal_emit (mq, gst_multi_queue_signals[SIGNAL_OVERRUN], 0); + } +} + +static void +single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq) +{ + gboolean empty = TRUE; + GstMultiQueue *mq = sq->mqueue; + GList *tmp; + + if (sq->srcresult == GST_FLOW_NOT_LINKED) { + GST_LOG_OBJECT (mq, "Single Queue %d is empty but not-linked", sq->id); + return; + } else { + GST_LOG_OBJECT (mq, + "Single Queue %d is empty, Checking other single queues", sq->id); + } + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *oq = (GstSingleQueue *) tmp->data; + + if (gst_data_queue_is_full (oq->queue)) { + GstDataQueueSize size; + + gst_data_queue_get_level (oq->queue, &size); + if (IS_FILLED (oq, visible, size.visible)) { + oq->max_size.visible = size.visible + 1; + GST_DEBUG_OBJECT (mq, + "queue %d is filled, bumping its max visible to %d", oq->id, + oq->max_size.visible); + gst_data_queue_limits_changed (oq->queue); + } + } + if (!gst_data_queue_is_empty (oq->queue) || oq->is_sparse) + empty = FALSE; + } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + + if (empty) { + GST_DEBUG_OBJECT (mq, "All queues are empty, signalling it"); + g_signal_emit (mq, gst_multi_queue_signals[SIGNAL_UNDERRUN], 0); + } +} + +static gboolean +single_queue_check_full (GstDataQueue * dataq, guint visible, guint bytes, + guint64 time, GstSingleQueue * sq) +{ + gboolean res; + GstMultiQueue *mq = sq->mqueue; + + GST_DEBUG_OBJECT (mq, + "queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT "/%" + G_GUINT64_FORMAT, sq->id, visible, sq->max_size.visible, bytes, + sq->max_size.bytes, sq->cur_time, sq->max_size.time); + + /* we are always filled on EOS */ + if (sq->is_eos || sq->is_segment_done) + return TRUE; + + /* we never go past the max visible items unless we are in buffering mode */ + if (!mq->use_buffering && IS_FILLED (sq, visible, visible)) + return TRUE; + + /* check time or bytes */ + res = IS_FILLED (sq, bytes, bytes); + /* We only care about limits in time if we're not a sparse stream or + * we're not syncing by running time */ + if (!sq->is_sparse || !mq->sync_by_running_time) { + /* If unlinked, take into account the extra unlinked cache time */ + if (mq->sync_by_running_time && sq->srcresult == GST_FLOW_NOT_LINKED) { + if (sq->cur_time > mq->unlinked_cache_time) + res |= IS_FILLED (sq, time, sq->cur_time - mq->unlinked_cache_time); + else + res = FALSE; + } else + res |= IS_FILLED (sq, time, sq->cur_time); + } + + return res; +} + +static void +gst_single_queue_flush_queue (GstSingleQueue * sq, gboolean full) +{ + GstDataQueueItem *sitem; + GstMultiQueueItem *mitem; + gboolean was_flushing = FALSE; + + while (!gst_data_queue_is_empty (sq->queue)) { + GstMiniObject *data; + + /* FIXME: If this fails here although the queue is not empty, + * we're flushing... but we want to rescue all sticky + * events nonetheless. + */ + if (!gst_data_queue_pop (sq->queue, &sitem)) { + was_flushing = TRUE; + gst_data_queue_set_flushing (sq->queue, FALSE); + continue; + } + + mitem = (GstMultiQueueItem *) sitem; + + data = sitem->object; + + if (!full && !mitem->is_query && GST_IS_EVENT (data) + && GST_EVENT_IS_STICKY (data) + && GST_EVENT_TYPE (data) != GST_EVENT_SEGMENT + && GST_EVENT_TYPE (data) != GST_EVENT_EOS) { + gst_pad_store_sticky_event (sq->srcpad, GST_EVENT_CAST (data)); + } + + sitem->destroy (sitem); + } + + gst_data_queue_flush (sq->queue); + if (was_flushing) + gst_data_queue_set_flushing (sq->queue, TRUE); + + GST_MULTI_QUEUE_MUTEX_LOCK (sq->mqueue); + update_buffering (sq->mqueue, sq); + GST_MULTI_QUEUE_MUTEX_UNLOCK (sq->mqueue); + gst_multi_queue_post_buffering (sq->mqueue); +} + +static void +gst_single_queue_free (GstSingleQueue * sq) +{ + /* DRAIN QUEUE */ + gst_data_queue_flush (sq->queue); + g_object_unref (sq->queue); + g_cond_clear (&sq->turn); + g_cond_clear (&sq->query_handled); + g_free (sq); +} + +static GstSingleQueue * +gst_single_queue_new (GstMultiQueue * mqueue, guint id) +{ + GstSingleQueue *sq; + GstMultiQueuePad *mqpad; + GstPadTemplate *templ; + gchar *name; + GList *tmp; + guint temp_id = (id == -1) ? 0 : id; + + GST_MULTI_QUEUE_MUTEX_LOCK (mqueue); + + /* Find an unused queue ID, if possible the passed one */ + for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *sq2 = (GstSingleQueue *) tmp->data; + /* This works because the IDs are sorted in ascending order */ + if (sq2->id == temp_id) { + /* If this ID was requested by the caller return NULL, + * otherwise just get us the next one */ + if (id == -1) { + temp_id = sq2->id + 1; + } else { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + return NULL; + } + } else if (sq2->id > temp_id) { + break; + } + } + + sq = g_new0 (GstSingleQueue, 1); + mqueue->nbqueues++; + sq->id = temp_id; + sq->groupid = DEFAULT_PAD_GROUP_ID; + sq->group_high_time = GST_CLOCK_STIME_NONE; + + mqueue->queues = g_list_insert_before (mqueue->queues, tmp, sq); + mqueue->queues_cookie++; + + /* copy over max_size and extra_size so we don't need to take the lock + * any longer when checking if the queue is full. */ + sq->max_size.visible = mqueue->max_size.visible; + sq->max_size.bytes = mqueue->max_size.bytes; + sq->max_size.time = mqueue->max_size.time; + + sq->extra_size.visible = mqueue->extra_size.visible; + sq->extra_size.bytes = mqueue->extra_size.bytes; + sq->extra_size.time = mqueue->extra_size.time; + + GST_DEBUG_OBJECT (mqueue, "Creating GstSingleQueue id:%d", sq->id); + + sq->mqueue = mqueue; + sq->srcresult = GST_FLOW_FLUSHING; + sq->pushed = FALSE; + sq->queue = gst_data_queue_new ((GstDataQueueCheckFullFunction) + single_queue_check_full, + (GstDataQueueFullCallback) single_queue_overrun_cb, + (GstDataQueueEmptyCallback) single_queue_underrun_cb, sq); + sq->is_eos = FALSE; + sq->is_sparse = FALSE; + sq->flushing = FALSE; + sq->active = FALSE; + gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&sq->src_segment, GST_FORMAT_TIME); + + sq->nextid = 0; + sq->oldid = 0; + sq->next_time = GST_CLOCK_STIME_NONE; + sq->last_time = GST_CLOCK_STIME_NONE; + g_cond_init (&sq->turn); + g_cond_init (&sq->query_handled); + + sq->sinktime = GST_CLOCK_STIME_NONE; + sq->srctime = GST_CLOCK_STIME_NONE; + sq->sink_tainted = TRUE; + sq->src_tainted = TRUE; + + name = g_strdup_printf ("sink_%u", sq->id); + templ = gst_static_pad_template_get (&sinktemplate); + sq->sinkpad = g_object_new (GST_TYPE_MULTIQUEUE_PAD, "name", name, + "direction", templ->direction, "template", templ, NULL); + gst_object_unref (templ); + g_free (name); + + mqpad = (GstMultiQueuePad *) sq->sinkpad; + mqpad->sq = sq; + + gst_pad_set_chain_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_chain)); + gst_pad_set_activatemode_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode)); + gst_pad_set_event_full_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event)); + gst_pad_set_query_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query)); + gst_pad_set_iterate_internal_links_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); + GST_OBJECT_FLAG_SET (sq->sinkpad, GST_PAD_FLAG_PROXY_CAPS); + + name = g_strdup_printf ("src_%u", sq->id); + sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name); + g_free (name); + + gst_pad_set_activatemode_function (sq->srcpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_mode)); + gst_pad_set_event_function (sq->srcpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_src_event)); + gst_pad_set_query_function (sq->srcpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_src_query)); + gst_pad_set_iterate_internal_links_function (sq->srcpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); + GST_OBJECT_FLAG_SET (sq->srcpad, GST_PAD_FLAG_PROXY_CAPS); + + gst_pad_set_element_private (sq->sinkpad, (gpointer) sq); + gst_pad_set_element_private (sq->srcpad, (gpointer) sq); + + GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); + + /* only activate the pads when we are not in the NULL state + * and add the pad under the state_lock to prevend state changes + * between activating and adding */ + g_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue)); + if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) { + gst_pad_set_active (sq->srcpad, TRUE); + gst_pad_set_active (sq->sinkpad, TRUE); + } + gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad); + gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad); + if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) { + gst_single_queue_start (mqueue, sq); + } + g_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue)); + + GST_DEBUG_OBJECT (mqueue, "GstSingleQueue [%d] created and pads added", + sq->id); + + return sq; +} diff --git a/plugins/elements/gstmultiqueue.h b/plugins/elements/gstmultiqueue.h new file mode 100644 index 0000000..524fcf9 --- /dev/null +++ b/plugins/elements/gstmultiqueue.h @@ -0,0 +1,105 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey + * + * gstmultiqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_MULTI_QUEUE_H__ +#define __GST_MULTI_QUEUE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_MULTI_QUEUE \ + (gst_multi_queue_get_type()) +#define GST_MULTI_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTI_QUEUE,GstMultiQueue)) +#define GST_MULTI_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_QUEUE,GstMultiQueueClass)) +#define GST_IS_MULTI_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTI_QUEUE)) +#define GST_IS_MULTI_QUEUE_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTI_QUEUE)) + +typedef struct _GstMultiQueue GstMultiQueue; +typedef struct _GstMultiQueueClass GstMultiQueueClass; + +typedef struct _GstMultiQueuePad GstMultiQueuePad; +typedef struct _GstMultiQueuePadClass GstMultiQueuePadClass; + +/** + * GstMultiQueue: + * + * Opaque #GstMultiQueue structure. + */ +struct _GstMultiQueue { + GstElement element; + + gboolean sync_by_running_time; + gboolean use_interleave; + GstClockTime min_interleave_time; + + /* number of queues */ + guint nbqueues; + + /* The list of individual queues */ + GList *queues; + guint32 queues_cookie; + + GstDataQueueSize max_size, extra_size; + gboolean use_buffering; + gint low_watermark, high_watermark; + gboolean buffering; + gint buffering_percent; + + guint counter; /* incoming object counter, use atomic accesses */ + guint32 highid; /* contains highest id of last outputted object */ + GstClockTimeDiff high_time; /* highest start running time */ + + GMutex qlock; /* Global queue lock (vs object lock or individual */ + /* queues lock). Protects nbqueues, queues, global */ + /* GstMultiQueueSize, counter and highid */ + + gint numwaiting; /* number of not-linked pads waiting */ + + gboolean buffering_percent_changed; + GMutex buffering_post_lock; /* assures only one posted at a time */ + + GstClockTime interleave; /* Input interleave */ + GstClockTimeDiff last_interleave_update; + + GstClockTime unlinked_cache_time; +}; + +struct _GstMultiQueueClass { + GstElementClass parent_class; + + /* signals emitted when ALL queues are either full or empty */ + void (*underrun) (GstMultiQueue *queue); + void (*overrun) (GstMultiQueue *queue); +}; + +G_GNUC_INTERNAL GType gst_multi_queue_get_type (void); + +G_END_DECLS + + +#endif /* __GST_MULTI_QUEUE_H__ */ diff --git a/plugins/elements/gstoutputselector.c b/plugins/elements/gstoutputselector.c new file mode 100644 index 0000000..03cf206 --- /dev/null +++ b/plugins/elements/gstoutputselector.c @@ -0,0 +1,659 @@ +/* GStreamer output selector + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-output-selector + * @title: output-selector + * @see_also: #GstOutputSelector, #GstInputSelector + * + * Direct input stream to one out of N output pads. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstoutputselector.h" + +GST_DEBUG_CATEGORY_STATIC (output_selector_debug); +#define GST_CAT_DEFAULT output_selector_debug + +static GstStaticPadTemplate gst_output_selector_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_output_selector_src_factory = +GST_STATIC_PAD_TEMPLATE ("src_%u", + GST_PAD_SRC, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +#define GST_TYPE_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE (gst_output_selector_pad_negotiation_mode_get_type()) +static GType +gst_output_selector_pad_negotiation_mode_get_type (void) +{ + static GType pad_negotiation_mode_type = 0; + static const GEnumValue pad_negotiation_modes[] = { + {GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE, "None", "none"}, + {GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL, "All", "all"}, + {GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ACTIVE, "Active", "active"}, + {0, NULL, NULL} + }; + + if (!pad_negotiation_mode_type) { + pad_negotiation_mode_type = + g_enum_register_static ("GstOutputSelectorPadNegotiationMode", + pad_negotiation_modes); + } + return pad_negotiation_mode_type; +} + + +enum +{ + PROP_0, + PROP_ACTIVE_PAD, + PROP_RESEND_LATEST, + PROP_PAD_NEGOTIATION_MODE +}; + +#define DEFAULT_PAD_NEGOTIATION_MODE GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL + +#define _do_init \ +GST_DEBUG_CATEGORY_INIT (output_selector_debug, \ + "output-selector", 0, "Output stream selector"); +#define gst_output_selector_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstOutputSelector, gst_output_selector, + GST_TYPE_ELEMENT, _do_init); + +static void gst_output_selector_dispose (GObject * object); +static void gst_output_selector_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_output_selector_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstPad *gst_output_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused, const GstCaps * caps); +static void gst_output_selector_release_pad (GstElement * element, + GstPad * pad); +static GstFlowReturn gst_output_selector_chain (GstPad * pad, + GstObject * parent, GstBuffer * buf); +static GstStateChangeReturn gst_output_selector_change_state (GstElement * + element, GstStateChange transition); +static gboolean gst_output_selector_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_output_selector_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static void gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * + sel, gint mode); + +static void +gst_output_selector_class_init (GstOutputSelectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->dispose = gst_output_selector_dispose; + + gobject_class->set_property = gst_output_selector_set_property; + gobject_class->get_property = gst_output_selector_get_property; + + g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, + g_param_spec_object ("active-pad", "Active pad", + "Currently active src pad", GST_TYPE_PAD, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_RESEND_LATEST, + g_param_spec_boolean ("resend-latest", "Resend latest buffer", + "Resend latest buffer after a switch to a new pad", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PAD_NEGOTIATION_MODE, + g_param_spec_enum ("pad-negotiation-mode", "Pad negotiation mode", + "The mode to be used for pad negotiation", + GST_TYPE_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE, + DEFAULT_PAD_NEGOTIATION_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, "Output selector", + "Generic", "1-to-N output stream selector", + "Stefan Kost "); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_output_selector_sink_factory); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_output_selector_src_factory); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_output_selector_request_new_pad); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_output_selector_release_pad); + + gstelement_class->change_state = gst_output_selector_change_state; +} + +static void +gst_output_selector_init (GstOutputSelector * sel) +{ + sel->sinkpad = + gst_pad_new_from_static_template (&gst_output_selector_sink_factory, + "sink"); + gst_pad_set_chain_function (sel->sinkpad, + GST_DEBUG_FUNCPTR (gst_output_selector_chain)); + gst_pad_set_event_function (sel->sinkpad, + GST_DEBUG_FUNCPTR (gst_output_selector_event)); + gst_pad_set_query_function (sel->sinkpad, + GST_DEBUG_FUNCPTR (gst_output_selector_query)); + + gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad); + + /* srcpad management */ + sel->active_srcpad = NULL; + sel->nb_srcpads = 0; + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); + sel->pending_srcpad = NULL; + + sel->resend_latest = FALSE; + sel->latest_buffer = NULL; + gst_output_selector_switch_pad_negotiation_mode (sel, + DEFAULT_PAD_NEGOTIATION_MODE); +} + +static void +gst_output_selector_reset (GstOutputSelector * osel) +{ + GST_OBJECT_LOCK (osel); + if (osel->pending_srcpad != NULL) { + gst_object_unref (osel->pending_srcpad); + osel->pending_srcpad = NULL; + } + + if (osel->latest_buffer != NULL) { + gst_buffer_unref (osel->latest_buffer); + osel->latest_buffer = NULL; + } + GST_OBJECT_UNLOCK (osel); + gst_segment_init (&osel->segment, GST_FORMAT_UNDEFINED); +} + +static void +gst_output_selector_dispose (GObject * object) +{ + GstOutputSelector *osel = GST_OUTPUT_SELECTOR (object); + + gst_output_selector_reset (osel); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_output_selector_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + { + GstPad *next_pad; + + next_pad = g_value_get_object (value); + + GST_INFO_OBJECT (sel, "Activating pad %s:%s", + GST_DEBUG_PAD_NAME (next_pad)); + + GST_OBJECT_LOCK (object); + if (next_pad != sel->active_srcpad) { + /* switch to new srcpad in next chain run */ + if (sel->pending_srcpad != NULL) { + GST_INFO ("replacing pending switch"); + gst_object_unref (sel->pending_srcpad); + } + if (next_pad) + gst_object_ref (next_pad); + sel->pending_srcpad = next_pad; + } else { + GST_INFO ("pad already active"); + if (sel->pending_srcpad != NULL) { + gst_object_unref (sel->pending_srcpad); + sel->pending_srcpad = NULL; + } + } + GST_OBJECT_UNLOCK (object); + break; + } + case PROP_RESEND_LATEST:{ + sel->resend_latest = g_value_get_boolean (value); + break; + } + case PROP_PAD_NEGOTIATION_MODE:{ + gst_output_selector_switch_pad_negotiation_mode (sel, + g_value_get_enum (value)); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_output_selector_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + GST_OBJECT_LOCK (object); + g_value_set_object (value, + sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad); + GST_OBJECT_UNLOCK (object); + break; + case PROP_RESEND_LATEST:{ + GST_OBJECT_LOCK (object); + g_value_set_boolean (value, sel->resend_latest); + GST_OBJECT_UNLOCK (object); + break; + } + case PROP_PAD_NEGOTIATION_MODE: + g_value_set_enum (value, sel->pad_negotiation_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_output_selector_get_active (GstOutputSelector * sel) +{ + GstPad *active = NULL; + + GST_OBJECT_LOCK (sel); + if (sel->pending_srcpad) + active = gst_object_ref (sel->pending_srcpad); + else if (sel->active_srcpad) + active = gst_object_ref (sel->active_srcpad); + GST_OBJECT_UNLOCK (sel); + + return active; +} + +static void +gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * sel, + gint mode) +{ + sel->pad_negotiation_mode = mode; +} + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstPad *srcpad = GST_PAD_CAST (user_data); + + gst_pad_push_event (srcpad, gst_event_ref (*event)); + + return TRUE; +} + +static GstPad * +gst_output_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) +{ + gchar *padname; + GstPad *srcpad; + GstOutputSelector *osel; + + osel = GST_OUTPUT_SELECTOR (element); + + GST_DEBUG_OBJECT (osel, "requesting pad"); + + GST_OBJECT_LOCK (osel); + padname = g_strdup_printf ("src_%u", osel->nb_srcpads++); + srcpad = gst_pad_new_from_template (templ, padname); + GST_OBJECT_UNLOCK (osel); + + gst_pad_set_active (srcpad, TRUE); + + /* Forward sticky events to the new srcpad */ + gst_pad_sticky_events_foreach (osel->sinkpad, forward_sticky_events, srcpad); + + gst_element_add_pad (GST_ELEMENT (osel), srcpad); + + /* Set the first requested src pad as active by default */ + GST_OBJECT_LOCK (osel); + if (osel->active_srcpad == NULL) { + osel->active_srcpad = srcpad; + GST_OBJECT_UNLOCK (osel); + g_object_notify (G_OBJECT (osel), "active-pad"); + } else { + GST_OBJECT_UNLOCK (osel); + } + g_free (padname); + + return srcpad; +} + +static void +gst_output_selector_release_pad (GstElement * element, GstPad * pad) +{ + GstOutputSelector *osel; + + osel = GST_OUTPUT_SELECTOR (element); + + GST_DEBUG_OBJECT (osel, "releasing pad"); + + /* Disable active pad if it's the to be removed pad */ + GST_OBJECT_LOCK (osel); + if (osel->active_srcpad == pad) { + osel->active_srcpad = NULL; + GST_OBJECT_UNLOCK (osel); + g_object_notify (G_OBJECT (osel), "active-pad"); + } else { + GST_OBJECT_UNLOCK (osel); + } + + gst_pad_set_active (pad, FALSE); + + gst_element_remove_pad (GST_ELEMENT_CAST (osel), pad); +} + +static gboolean +gst_output_selector_switch (GstOutputSelector * osel) +{ + gboolean res = FALSE; + GstEvent *ev = NULL; + GstSegment *seg = NULL; + GstPad *active_srcpad; + + /* Switch */ + GST_OBJECT_LOCK (osel); + GST_INFO_OBJECT (osel, "switching to pad %" GST_PTR_FORMAT, + osel->pending_srcpad); + if (!osel->pending_srcpad) { + GST_OBJECT_UNLOCK (osel); + return TRUE; + } + + if (gst_pad_is_linked (osel->pending_srcpad)) { + osel->active_srcpad = osel->pending_srcpad; + res = TRUE; + } + gst_object_unref (osel->pending_srcpad); + osel->pending_srcpad = NULL; + active_srcpad = res ? gst_object_ref (osel->active_srcpad) : NULL; + GST_OBJECT_UNLOCK (osel); + + /* Send SEGMENT event and latest buffer if switching succeeded + * and we already have a valid segment configured */ + if (res) { + GstBuffer *latest_buffer; + + g_object_notify (G_OBJECT (osel), "active-pad"); + + GST_OBJECT_LOCK (osel); + latest_buffer = + osel->latest_buffer ? gst_buffer_ref (osel->latest_buffer) : NULL; + GST_OBJECT_UNLOCK (osel); + + gst_pad_sticky_events_foreach (osel->sinkpad, forward_sticky_events, + active_srcpad); + + /* update segment if required */ + if (osel->segment.format != GST_FORMAT_UNDEFINED) { + /* Send SEGMENT to the pad we are going to switch to */ + seg = &osel->segment; + /* If resending then mark segment start and position accordingly */ + if (osel->resend_latest && latest_buffer && + GST_BUFFER_TIMESTAMP_IS_VALID (latest_buffer)) { + seg->position = GST_BUFFER_TIMESTAMP (latest_buffer); + } + + ev = gst_event_new_segment (seg); + + if (!gst_pad_push_event (active_srcpad, ev)) { + GST_WARNING_OBJECT (osel, + "newsegment handling failed in %" GST_PTR_FORMAT, active_srcpad); + } + } + + /* Resend latest buffer to newly switched pad */ + if (osel->resend_latest && latest_buffer) { + GST_INFO ("resending latest buffer"); + gst_pad_push (active_srcpad, latest_buffer); + } else if (latest_buffer) { + gst_buffer_unref (latest_buffer); + } + + gst_object_unref (active_srcpad); + } else { + GST_WARNING_OBJECT (osel, "switch failed, pad not linked"); + } + + return res; +} + +static GstFlowReturn +gst_output_selector_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GstFlowReturn res; + GstOutputSelector *osel; + GstClockTime position, duration; + GstPad *active_srcpad; + + osel = GST_OUTPUT_SELECTOR (parent); + + /* + * The _switch function might push a buffer if 'resend-latest' is true. + * + * Elements/Applications (e.g. camerabin) might use pad probes to + * switch output-selector's active pad. If we simply switch and don't + * recheck any pending pad switch the following codepath could end + * up pushing a buffer on a non-active pad. This is bad. + * + * So we always should check the pending_srcpad before going further down + * the chain and pushing the new buffer + */ + while (osel->pending_srcpad) { + /* Do the switch */ + gst_output_selector_switch (osel); + } + + active_srcpad = gst_output_selector_get_active (osel); + if (!active_srcpad) { + GST_DEBUG_OBJECT (osel, "No active srcpad"); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } + + GST_OBJECT_LOCK (osel); + if (osel->latest_buffer) { + gst_buffer_unref (osel->latest_buffer); + osel->latest_buffer = NULL; + } + + if (osel->resend_latest) { + /* Keep reference to latest buffer to resend it after switch */ + osel->latest_buffer = gst_buffer_ref (buf); + } + GST_OBJECT_UNLOCK (osel); + + /* Keep track of last stop and use it in SEGMENT start after + switching to a new src pad */ + position = GST_BUFFER_TIMESTAMP (buf); + if (GST_CLOCK_TIME_IS_VALID (position)) { + duration = GST_BUFFER_DURATION (buf); + if (GST_CLOCK_TIME_IS_VALID (duration)) { + position += duration; + } + GST_LOG_OBJECT (osel, "setting last stop %" GST_TIME_FORMAT, + GST_TIME_ARGS (position)); + osel->segment.position = position; + } + + GST_LOG_OBJECT (osel, "pushing buffer to %" GST_PTR_FORMAT, active_srcpad); + res = gst_pad_push (active_srcpad, buf); + + gst_object_unref (active_srcpad); + + return res; +} + +static GstStateChangeReturn +gst_output_selector_change_state (GstElement * element, + GstStateChange transition) +{ + GstOutputSelector *sel; + GstStateChangeReturn result; + + sel = GST_OUTPUT_SELECTOR (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_output_selector_reset (sel); + break; + default: + break; + } + + return result; +} + +static gboolean +gst_output_selector_forward_event (GstOutputSelector * sel, GstEvent * event) +{ + gboolean res = TRUE; + GstPad *active; + + switch (sel->pad_negotiation_mode) { + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL: + /* Send to all src pads */ + res = gst_pad_event_default (sel->sinkpad, GST_OBJECT_CAST (sel), event); + break; + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE: + gst_event_unref (event); + break; + default: + active = gst_output_selector_get_active (sel); + if (active) { + res = gst_pad_push_event (active, event); + gst_object_unref (active); + } else { + gst_event_unref (event); + } + break; + } + + return res; +} + +static gboolean +gst_output_selector_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + GstOutputSelector *sel; + GstPad *active = NULL; + + sel = GST_OUTPUT_SELECTOR (parent); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + { + res = gst_output_selector_forward_event (sel, event); + break; + } + case GST_EVENT_SEGMENT: + { + gst_event_copy_segment (event, &sel->segment); + GST_DEBUG_OBJECT (sel, "configured SEGMENT %" GST_SEGMENT_FORMAT, + &sel->segment); + /* fall through */ + } + default: + { + active = gst_output_selector_get_active (sel); + if (active) { + res = gst_pad_push_event (active, event); + gst_object_unref (active); + } else { + gst_event_unref (event); + } + break; + } + } + + return res; +} + +static gboolean +gst_output_selector_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = TRUE; + GstOutputSelector *sel; + GstPad *active = NULL; + + sel = GST_OUTPUT_SELECTOR (parent); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + switch (sel->pad_negotiation_mode) { + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL: + /* Send caps to all src pads */ + res = gst_pad_proxy_query_caps (pad, query); + break; + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE: + res = FALSE; + break; + default: + active = gst_output_selector_get_active (sel); + if (active) { + res = gst_pad_peer_query (active, query); + gst_object_unref (active); + } else { + res = FALSE; + } + break; + } + break; + } + case GST_QUERY_DRAIN: + if (sel->latest_buffer) { + gst_buffer_unref (sel->latest_buffer); + sel->latest_buffer = NULL; + } + /* fall through */ + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + + return res; +} diff --git a/plugins/elements/gstoutputselector.h b/plugins/elements/gstoutputselector.h new file mode 100644 index 0000000..c39c5b1 --- /dev/null +++ b/plugins/elements/gstoutputselector.h @@ -0,0 +1,87 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_OUTPUT_SELECTOR_H__ +#define __GST_OUTPUT_SELECTOR_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_OUTPUT_SELECTOR \ + (gst_output_selector_get_type()) +#define GST_OUTPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OUTPUT_SELECTOR, GstOutputSelector)) +#define GST_OUTPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OUTPUT_SELECTOR, GstOutputSelectorClass)) +#define GST_IS_OUTPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OUTPUT_SELECTOR)) +#define GST_IS_OUTPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OUTPUT_SELECTOR)) + +typedef struct _GstOutputSelector GstOutputSelector; +typedef struct _GstOutputSelectorClass GstOutputSelectorClass; + +struct _GstOutputSelector { + GstElement element; + + GstPad *sinkpad; + + GstPad *active_srcpad; + GstPad *pending_srcpad; + guint nb_srcpads; + + gint pad_negotiation_mode; + + GstSegment segment; + + /* resend latest buffer after switch */ + gboolean resend_latest; + GstBuffer *latest_buffer; + +}; + +struct _GstOutputSelectorClass { + GstElementClass parent_class; +}; + +/** + * GstOutputSelectorPadNegotiationMode: + * @GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE: don't propagate the input + * stream. + * @GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL: direct input stream to all + * output pads. + * @GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ACTIVE: direct input stream to the + * currently active output pad as described by the #GstOutputSelector:active-pad + * property. + * + * To what output pad the input stream should be directed. + */ +typedef enum +{ + GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE, + GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL, + GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ACTIVE +} GstOutputSelectorPadNegotiationMode; + +G_GNUC_INTERNAL GType gst_output_selector_get_type (void); + +G_END_DECLS + +#endif /* __GST_OUTPUT_SELECTOR_H__ */ diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c new file mode 100644 index 0000000..a8753ea --- /dev/null +++ b/plugins/elements/gstqueue.c @@ -0,0 +1,1902 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2003 Colin Walters + * 2005 Wim Taymans + * + * gstqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-queue + * @title: queue + * + * Data is queued until one of the limits specified by the + * #GstQueue:max-size-buffers, #GstQueue:max-size-bytes and/or + * #GstQueue:max-size-time properties has been reached. Any attempt to push + * more buffers into the queue will block the pushing thread until more space + * becomes available. + * + * The queue will create a new thread on the source pad to decouple the + * processing on sink and source pad. + * + * You can query how many buffers are queued by reading the + * #GstQueue:current-level-buffers property. You can track changes + * by connecting to the notify::current-level-buffers signal (which + * like all signals will be emitted from the streaming thread). The same + * applies to the #GstQueue:current-level-time and + * #GstQueue:current-level-bytes properties. + * + * The default queue size limits are 200 buffers, 10MB of data, or + * one second worth of data, whichever is reached first. + * + * As said earlier, the queue blocks by default when one of the specified + * maximums (bytes, time, buffers) has been reached. You can set the + * #GstQueue:leaky property to specify that instead of blocking it should + * leak (drop) new or old buffers. + * + * The #GstQueue::underrun signal is emitted when the queue has less data than + * the specified minimum thresholds require (by default: when the queue is + * empty). The #GstQueue::overrun signal is emitted when the queue is filled + * up. Both signals are emitted from the context of the streaming thread. + */ + +#include "gst/gst_private.h" + +#include +#include "gstqueue.h" + +#include "../../gst/gst-i18n-lib.h" +#include "../../gst/glib-compat-private.h" + +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); + +GST_DEBUG_CATEGORY_STATIC (queue_debug); +#define GST_CAT_DEFAULT (queue_debug) +GST_DEBUG_CATEGORY_STATIC (queue_dataflow); + +#define STATUS(queue, pad, msg) \ + GST_CAT_LOG_OBJECT (queue_dataflow, queue, \ + "(%s:%s) " msg ": %u of %u-%u buffers, %u of %u-%u " \ + "bytes, %" G_GUINT64_FORMAT " of %" G_GUINT64_FORMAT \ + "-%" G_GUINT64_FORMAT " ns, %u items", \ + GST_DEBUG_PAD_NAME (pad), \ + queue->cur_level.buffers, \ + queue->min_threshold.buffers, \ + queue->max_size.buffers, \ + queue->cur_level.bytes, \ + queue->min_threshold.bytes, \ + queue->max_size.bytes, \ + queue->cur_level.time, \ + queue->min_threshold.time, \ + queue->max_size.time, \ + gst_queue_array_get_length (queue->queue)) + +/* Queue signals and args */ +enum +{ + SIGNAL_UNDERRUN, + SIGNAL_RUNNING, + SIGNAL_OVERRUN, + SIGNAL_PUSHING, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + /* FIXME: don't we have another way of doing this + * "Gstreamer format" (frame/byte/time) queries? */ + PROP_CUR_LEVEL_BUFFERS, + PROP_CUR_LEVEL_BYTES, + PROP_CUR_LEVEL_TIME, + PROP_MAX_SIZE_BUFFERS, + PROP_MAX_SIZE_BYTES, + PROP_MAX_SIZE_TIME, + PROP_MIN_THRESHOLD_BUFFERS, + PROP_MIN_THRESHOLD_BYTES, + PROP_MIN_THRESHOLD_TIME, + PROP_LEAKY, + PROP_SILENT, + PROP_FLUSH_ON_EOS +}; + +/* default property values */ +#define DEFAULT_MAX_SIZE_BUFFERS 200 /* 200 buffers */ +#define DEFAULT_MAX_SIZE_BYTES (10 * 1024 * 1024) /* 10 MB */ +#define DEFAULT_MAX_SIZE_TIME GST_SECOND /* 1 second */ + +#define GST_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ + g_mutex_lock (&q->qlock); \ +} G_STMT_END + +#define GST_QUEUE_MUTEX_LOCK_CHECK(q,label) G_STMT_START { \ + GST_QUEUE_MUTEX_LOCK (q); \ + if (q->srcresult != GST_FLOW_OK) \ + goto label; \ +} G_STMT_END + +#define GST_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ + g_mutex_unlock (&q->qlock); \ +} G_STMT_END + +#define GST_QUEUE_WAIT_DEL_CHECK(q, label) G_STMT_START { \ + STATUS (q, q->sinkpad, "wait for DEL"); \ + q->waiting_del = TRUE; \ + g_cond_wait (&q->item_del, &q->qlock); \ + q->waiting_del = FALSE; \ + if (q->srcresult != GST_FLOW_OK) { \ + STATUS (q, q->srcpad, "received DEL wakeup"); \ + goto label; \ + } \ + STATUS (q, q->sinkpad, "received DEL"); \ +} G_STMT_END + +#define GST_QUEUE_WAIT_ADD_CHECK(q, label) G_STMT_START { \ + STATUS (q, q->srcpad, "wait for ADD"); \ + q->waiting_add = TRUE; \ + g_cond_wait (&q->item_add, &q->qlock); \ + q->waiting_add = FALSE; \ + if (q->srcresult != GST_FLOW_OK) { \ + STATUS (q, q->srcpad, "received ADD wakeup"); \ + goto label; \ + } \ + STATUS (q, q->srcpad, "received ADD"); \ +} G_STMT_END + +#define GST_QUEUE_SIGNAL_DEL(q) G_STMT_START { \ + if (q->waiting_del) { \ + STATUS (q, q->srcpad, "signal DEL"); \ + g_cond_signal (&q->item_del); \ + } \ +} G_STMT_END + +#define GST_QUEUE_SIGNAL_ADD(q) G_STMT_START { \ + if (q->waiting_add) { \ + STATUS (q, q->sinkpad, "signal ADD"); \ + g_cond_signal (&q->item_add); \ + } \ +} G_STMT_END + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (queue_debug, "queue", 0, "queue element"); \ + GST_DEBUG_CATEGORY_INIT (queue_dataflow, "queue_dataflow", 0, \ + "dataflow inside the queue element"); +#define gst_queue_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstQueue, gst_queue, GST_TYPE_ELEMENT, _do_init); + +static void gst_queue_finalize (GObject * object); +static void gst_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_queue_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_queue_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list); +static GstFlowReturn gst_queue_push_one (GstQueue * queue); +static void gst_queue_loop (GstPad * pad); + +static GstFlowReturn gst_queue_handle_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static gboolean gst_queue_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static void gst_queue_locked_flush (GstQueue * queue, gboolean full); + +static gboolean gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); + +static gboolean gst_queue_is_empty (GstQueue * queue); +static gboolean gst_queue_is_filled (GstQueue * queue); + + +typedef struct +{ + GstMiniObject *item; + gsize size; + gboolean is_query; +} GstQueueItem; + +#define GST_TYPE_QUEUE_LEAKY (queue_leaky_get_type ()) + +static GType +queue_leaky_get_type (void) +{ + static GType queue_leaky_type = 0; + static const GEnumValue queue_leaky[] = { + {GST_QUEUE_NO_LEAK, "Not Leaky", "no"}, + {GST_QUEUE_LEAK_UPSTREAM, "Leaky on upstream (new buffers)", "upstream"}, + {GST_QUEUE_LEAK_DOWNSTREAM, "Leaky on downstream (old buffers)", + "downstream"}, + {0, NULL, NULL}, + }; + + if (!queue_leaky_type) { + queue_leaky_type = g_enum_register_static ("GstQueueLeaky", queue_leaky); + } + return queue_leaky_type; +} + +static guint gst_queue_signals[LAST_SIGNAL] = { 0 }; + +static void +gst_queue_class_init (GstQueueClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_queue_set_property; + gobject_class->get_property = gst_queue_get_property; + + /* signals */ + /** + * GstQueue::underrun: + * @queue: the queue instance + * + * Reports that the buffer became empty (underrun). + * A buffer is empty if the total amount of data inside it (num-buffers, time, + * size) is lower than the boundary values which can be set through the + * GObject properties. + */ + gst_queue_signals[SIGNAL_UNDERRUN] = + g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstQueueClass, underrun), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GstQueue::running: + * @queue: the queue instance + * + * Reports that enough (min-threshold) data is in the queue. Use this signal + * together with the underrun signal to pause the pipeline on underrun and + * wait for the queue to fill-up before resume playback. + */ + gst_queue_signals[SIGNAL_RUNNING] = + g_signal_new ("running", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstQueueClass, running), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GstQueue::overrun: + * @queue: the queue instance + * + * Reports that the buffer became full (overrun). + * A buffer is full if the total amount of data inside it (num-buffers, time, + * size) is higher than the boundary values which can be set through the + * GObject properties. + */ + gst_queue_signals[SIGNAL_OVERRUN] = + g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstQueueClass, overrun), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GstQueue::pushing: + * @queue: the queue instance + * + * Reports when the queue has enough data to start pushing data again on the + * source pad. + */ + gst_queue_signals[SIGNAL_PUSHING] = + g_signal_new ("pushing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstQueueClass, pushing), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* properties */ + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES, + g_param_spec_uint ("current-level-bytes", "Current level (kB)", + "Current amount of data in the queue (bytes)", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BUFFERS, + g_param_spec_uint ("current-level-buffers", "Current level (buffers)", + "Current number of buffers in the queue", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME, + g_param_spec_uint64 ("current-level-time", "Current level (ns)", + "Current amount of data in the queue (in ns)", + 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES, + g_param_spec_uint ("max-size-bytes", "Max. size (kB)", + "Max. amount of data in the queue (bytes, 0=disable)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS, + g_param_spec_uint ("max-size-buffers", "Max. size (buffers)", + "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT, + DEFAULT_MAX_SIZE_BUFFERS, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME, + g_param_spec_uint64 ("max-size-time", "Max. size (ns)", + "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64, + DEFAULT_MAX_SIZE_TIME, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_BYTES, + g_param_spec_uint ("min-threshold-bytes", "Min. threshold (kB)", + "Min. amount of data in the queue to allow reading (bytes, 0=disable)", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_BUFFERS, + g_param_spec_uint ("min-threshold-buffers", "Min. threshold (buffers)", + "Min. number of buffers in the queue to allow reading (0=disable)", 0, + G_MAXUINT, 0, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_TIME, + g_param_spec_uint64 ("min-threshold-time", "Min. threshold (ns)", + "Min. amount of data in the queue to allow reading (in ns, 0=disable)", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LEAKY, + g_param_spec_enum ("leaky", "Leaky", + "Where the queue leaks, if at all", + GST_TYPE_QUEUE_LEAKY, GST_QUEUE_NO_LEAK, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + /** + * GstQueue:silent + * + * Don't emit queue signals. Makes queues more lightweight if no signals are + * needed. + */ + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't emit queue signals", FALSE, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + /** + * GstQueue:flush-on-eos + * + * Discard all data in the queue when an EOS event is received, and pass + * on the EOS event as soon as possible (instead of waiting until all + * buffers in the queue have been processed, which is the default behaviour). + * + * Flushing the queue on EOS might be useful when capturing and encoding + * from a live source, to finish up the recording quickly in cases when + * the encoder is slow. Note that this might mean some data from the end of + * the recording data might be lost though (never more than the configured + * max. sizes though). + * + * Since: 1.2 + */ + g_object_class_install_property (gobject_class, PROP_FLUSH_ON_EOS, + g_param_spec_boolean ("flush-on-eos", "Flush on EOS", + "Discard all data in the queue when an EOS event is received", FALSE, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_queue_finalize; + + gst_element_class_set_static_metadata (gstelement_class, + "Queue", + "Generic", "Simple data queue", "Erik Walthinsen "); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + /* Registering debug symbols for function pointers */ + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_mode); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_query); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_event); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain_list); +} + +static void +gst_queue_init (GstQueue * queue) +{ + queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); + + gst_pad_set_chain_function (queue->sinkpad, gst_queue_chain); + gst_pad_set_chain_list_function (queue->sinkpad, gst_queue_chain_list); + gst_pad_set_activatemode_function (queue->sinkpad, + gst_queue_sink_activate_mode); + gst_pad_set_event_full_function (queue->sinkpad, gst_queue_handle_sink_event); + gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query); + GST_PAD_SET_PROXY_CAPS (queue->sinkpad); + gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); + + queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + + gst_pad_set_activatemode_function (queue->srcpad, + gst_queue_src_activate_mode); + gst_pad_set_event_function (queue->srcpad, gst_queue_handle_src_event); + gst_pad_set_query_function (queue->srcpad, gst_queue_handle_src_query); + GST_PAD_SET_PROXY_CAPS (queue->srcpad); + gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); + + GST_QUEUE_CLEAR_LEVEL (queue->cur_level); + queue->max_size.buffers = DEFAULT_MAX_SIZE_BUFFERS; + queue->max_size.bytes = DEFAULT_MAX_SIZE_BYTES; + queue->max_size.time = DEFAULT_MAX_SIZE_TIME; + GST_QUEUE_CLEAR_LEVEL (queue->min_threshold); + GST_QUEUE_CLEAR_LEVEL (queue->orig_min_threshold); + gst_segment_init (&queue->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&queue->src_segment, GST_FORMAT_TIME); + queue->head_needs_discont = queue->tail_needs_discont = FALSE; + + queue->leaky = GST_QUEUE_NO_LEAK; + queue->srcresult = GST_FLOW_FLUSHING; + + g_mutex_init (&queue->qlock); + g_cond_init (&queue->item_add); + g_cond_init (&queue->item_del); + g_cond_init (&queue->query_handled); + + queue->queue = + gst_queue_array_new_for_struct (sizeof (GstQueueItem), + DEFAULT_MAX_SIZE_BUFFERS * 3 / 2); + + queue->sinktime = GST_CLOCK_STIME_NONE; + queue->srctime = GST_CLOCK_STIME_NONE; + + queue->sink_tainted = TRUE; + queue->src_tainted = TRUE; + + queue->newseg_applied_to_src = FALSE; + + GST_DEBUG_OBJECT (queue, + "initialized queue's not_empty & not_full conditions"); +} + +/* called only once, as opposed to dispose */ +static void +gst_queue_finalize (GObject * object) +{ + GstQueue *queue = GST_QUEUE (object); + GstQueueItem *qitem; + + GST_DEBUG_OBJECT (queue, "finalizing queue"); + + while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) { + /* FIXME: if it's a query, shouldn't we unref that too? */ + if (!qitem->is_query) + gst_mini_object_unref (qitem->item); + } + gst_queue_array_free (queue->queue); + + g_mutex_clear (&queue->qlock); + g_cond_clear (&queue->item_add); + g_cond_clear (&queue->item_del); + g_cond_clear (&queue->query_handled); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* Convenience function */ +static inline GstClockTimeDiff +my_segment_to_running_time (GstSegment * segment, GstClockTime val) +{ + GstClockTimeDiff res = GST_CLOCK_STIME_NONE; + + if (GST_CLOCK_TIME_IS_VALID (val)) { + gboolean sign = + gst_segment_to_running_time_full (segment, GST_FORMAT_TIME, val, &val); + if (sign > 0) + res = val; + else if (sign < 0) + res = -val; + } + return res; +} + +/* calculate the diff between running time on the sink and src of the queue. + * This is the total amount of time in the queue. */ +static void +update_time_level (GstQueue * queue) +{ + gint64 sink_time, src_time; + + if (queue->sink_tainted) { + GST_LOG_OBJECT (queue, "update sink time"); + queue->sinktime = + my_segment_to_running_time (&queue->sink_segment, + queue->sink_segment.position); + queue->sink_tainted = FALSE; + } + sink_time = queue->sinktime; + + if (queue->src_tainted) { + GST_LOG_OBJECT (queue, "update src time"); + queue->srctime = + my_segment_to_running_time (&queue->src_segment, + queue->src_segment.position); + queue->src_tainted = FALSE; + } + src_time = queue->srctime; + + GST_LOG_OBJECT (queue, "sink %" GST_STIME_FORMAT ", src %" GST_STIME_FORMAT, + GST_STIME_ARGS (sink_time), GST_STIME_ARGS (src_time)); + + if (GST_CLOCK_STIME_IS_VALID (src_time) + && GST_CLOCK_STIME_IS_VALID (sink_time) && sink_time >= src_time) + queue->cur_level.time = sink_time - src_time; + else + queue->cur_level.time = 0; +} + +/* take a SEGMENT event and apply the values to segment, updating the time + * level of queue. */ +static void +apply_segment (GstQueue * queue, GstEvent * event, GstSegment * segment, + gboolean sink) +{ + gst_event_copy_segment (event, segment); + + /* now configure the values, we use these to track timestamps on the + * sinkpad. */ + if (segment->format != GST_FORMAT_TIME) { + /* non-time format, pretent the current time segment is closed with a + * 0 start and unknown stop time. */ + segment->format = GST_FORMAT_TIME; + segment->start = 0; + segment->stop = -1; + segment->time = 0; + } + if (sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + GST_DEBUG_OBJECT (queue, "configured SEGMENT %" GST_SEGMENT_FORMAT, segment); + + /* segment can update the time level of the queue */ + update_time_level (queue); +} + +static void +apply_gap (GstQueue * queue, GstEvent * event, + GstSegment * segment, gboolean is_sink) +{ + GstClockTime timestamp; + GstClockTime duration; + + gst_event_parse_gap (event, ×tamp, &duration); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + timestamp += duration; + } + + segment->position = timestamp; + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); + } +} + + +/* take a buffer and update segment, updating the time level of the queue. */ +static void +apply_buffer (GstQueue * queue, GstBuffer * buffer, GstSegment * segment, + gboolean sink) +{ + GstClockTime duration, timestamp; + + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + duration = GST_BUFFER_DURATION (buffer); + + /* if no timestamp is set, assume it's continuous with the previous + * time */ + if (timestamp == GST_CLOCK_TIME_NONE) + timestamp = segment->position; + + /* add duration */ + if (duration != GST_CLOCK_TIME_NONE) + timestamp += duration; + + GST_LOG_OBJECT (queue, "%s position updated to %" GST_TIME_FORMAT, + segment == &queue->sink_segment ? "sink" : "src", + GST_TIME_ARGS (timestamp)); + + segment->position = timestamp; + if (sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + + /* calc diff with other end */ + update_time_level (queue); +} + +static gboolean +buffer_list_apply_time (GstBuffer ** buf, guint idx, gpointer user_data) +{ + GstClockTime *timestamp = user_data; + GstClockTime btime; + + GST_TRACE ("buffer %u has pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT, idx, GST_TIME_ARGS (GST_BUFFER_DTS (*buf)), + GST_TIME_ARGS (GST_BUFFER_PTS (*buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (*buf))); + + btime = GST_BUFFER_DTS_OR_PTS (*buf); + if (GST_CLOCK_TIME_IS_VALID (btime)) + *timestamp = btime; + + if (GST_BUFFER_DURATION_IS_VALID (*buf)) + *timestamp += GST_BUFFER_DURATION (*buf); + + GST_TRACE ("ts now %" GST_TIME_FORMAT, GST_TIME_ARGS (*timestamp)); + + return TRUE; +} + +/* take a buffer list and update segment, updating the time level of the queue */ +static void +apply_buffer_list (GstQueue * queue, GstBufferList * buffer_list, + GstSegment * segment, gboolean sink) +{ + GstClockTime timestamp; + + /* if no timestamp is set, assume it's continuous with the previous time */ + timestamp = segment->position; + + gst_buffer_list_foreach (buffer_list, buffer_list_apply_time, ×tamp); + + GST_DEBUG_OBJECT (queue, "position updated to %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); + + segment->position = timestamp; + + if (sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); +} + +static void +gst_queue_locked_flush (GstQueue * queue, gboolean full) +{ + GstQueueItem *qitem; + + while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) { + /* Then lose another reference because we are supposed to destroy that + data when flushing */ + if (!full && !qitem->is_query && GST_IS_EVENT (qitem->item) + && GST_EVENT_IS_STICKY (qitem->item) + && GST_EVENT_TYPE (qitem->item) != GST_EVENT_SEGMENT + && GST_EVENT_TYPE (qitem->item) != GST_EVENT_EOS) { + gst_pad_store_sticky_event (queue->srcpad, GST_EVENT_CAST (qitem->item)); + } + if (!qitem->is_query) + gst_mini_object_unref (qitem->item); + memset (qitem, 0, sizeof (GstQueueItem)); + } + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE_CLEAR_LEVEL (queue->cur_level); + queue->min_threshold.buffers = queue->orig_min_threshold.buffers; + queue->min_threshold.bytes = queue->orig_min_threshold.bytes; + queue->min_threshold.time = queue->orig_min_threshold.time; + gst_segment_init (&queue->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&queue->src_segment, GST_FORMAT_TIME); + queue->head_needs_discont = queue->tail_needs_discont = FALSE; + + queue->sinktime = queue->srctime = GST_CLOCK_STIME_NONE; + queue->sink_tainted = queue->src_tainted = TRUE; + + /* we deleted a lot of something */ + GST_QUEUE_SIGNAL_DEL (queue); +} + +/* enqueue an item an update the level stats, with QUEUE_LOCK */ +static inline void +gst_queue_locked_enqueue_buffer (GstQueue * queue, gpointer item) +{ + GstQueueItem qitem; + GstBuffer *buffer = GST_BUFFER_CAST (item); + gsize bsize = gst_buffer_get_size (buffer); + + /* add buffer to the statistics */ + queue->cur_level.buffers++; + queue->cur_level.bytes += bsize; + apply_buffer (queue, buffer, &queue->sink_segment, TRUE); + + qitem.item = item; + qitem.is_query = FALSE; + qitem.size = bsize; + gst_queue_array_push_tail_struct (queue->queue, &qitem); + GST_QUEUE_SIGNAL_ADD (queue); +} + +static inline void +gst_queue_locked_enqueue_buffer_list (GstQueue * queue, gpointer item) +{ + GstQueueItem qitem; + GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (item); + gsize bsize; + + bsize = gst_buffer_list_calculate_size (buffer_list); + + /* add buffer to the statistics */ + queue->cur_level.buffers += gst_buffer_list_length (buffer_list); + queue->cur_level.bytes += bsize; + apply_buffer_list (queue, buffer_list, &queue->sink_segment, TRUE); + + qitem.item = item; + qitem.is_query = FALSE; + qitem.size = bsize; + gst_queue_array_push_tail_struct (queue->queue, &qitem); + GST_QUEUE_SIGNAL_ADD (queue); +} + +static inline void +gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item) +{ + GstQueueItem qitem; + GstEvent *event = GST_EVENT_CAST (item); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from upstream"); + /* Zero the thresholds, this makes sure the queue is completely + * filled and we can read all data from the queue. */ + if (queue->flush_on_eos) + gst_queue_locked_flush (queue, FALSE); + else + GST_QUEUE_CLEAR_LEVEL (queue->min_threshold); + /* mark the queue as EOS. This prevents us from accepting more data. */ + queue->eos = TRUE; + break; + case GST_EVENT_SEGMENT: + apply_segment (queue, event, &queue->sink_segment, TRUE); + /* if the queue is empty, apply sink segment on the source */ + if (gst_queue_array_is_empty (queue->queue)) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "Apply segment on srcpad"); + apply_segment (queue, event, &queue->src_segment, FALSE); + queue->newseg_applied_to_src = TRUE; + } + /* a new segment allows us to accept more buffers if we got EOS + * from downstream */ + queue->unexpected = FALSE; + break; + case GST_EVENT_GAP: + apply_gap (queue, event, &queue->sink_segment, TRUE); + break; + default: + break; + } + + qitem.item = item; + qitem.is_query = FALSE; + qitem.size = 0; + gst_queue_array_push_tail_struct (queue->queue, &qitem); + GST_QUEUE_SIGNAL_ADD (queue); +} + +/* dequeue an item from the queue and update level stats, with QUEUE_LOCK */ +static GstMiniObject * +gst_queue_locked_dequeue (GstQueue * queue) +{ + GstQueueItem *qitem; + GstMiniObject *item; + gsize bufsize; + + qitem = gst_queue_array_pop_head_struct (queue->queue); + if (qitem == NULL) + goto no_item; + + item = qitem->item; + bufsize = qitem->size; + + if (GST_IS_BUFFER (item)) { + GstBuffer *buffer = GST_BUFFER_CAST (item); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved buffer %p from queue", buffer); + + queue->cur_level.buffers--; + queue->cur_level.bytes -= bufsize; + apply_buffer (queue, buffer, &queue->src_segment, FALSE); + + /* if the queue is empty now, update the other side */ + if (queue->cur_level.buffers == 0) + queue->cur_level.time = 0; + } else if (GST_IS_BUFFER_LIST (item)) { + GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (item); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved buffer list %p from queue", buffer_list); + + queue->cur_level.buffers -= gst_buffer_list_length (buffer_list); + queue->cur_level.bytes -= bufsize; + apply_buffer_list (queue, buffer_list, &queue->src_segment, FALSE); + + /* if the queue is empty now, update the other side */ + if (queue->cur_level.buffers == 0) + queue->cur_level.time = 0; + } else if (GST_IS_EVENT (item)) { + GstEvent *event = GST_EVENT_CAST (item); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved event %p from queue", event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* queue is empty now that we dequeued the EOS */ + GST_QUEUE_CLEAR_LEVEL (queue->cur_level); + break; + case GST_EVENT_SEGMENT: + /* apply newsegment if it has not already been applied */ + if (G_LIKELY (!queue->newseg_applied_to_src)) { + apply_segment (queue, event, &queue->src_segment, FALSE); + } else { + queue->newseg_applied_to_src = FALSE; + } + break; + case GST_EVENT_GAP: + apply_gap (queue, event, &queue->src_segment, FALSE); + break; + default: + break; + } + } else if (GST_IS_QUERY (item)) { + GstQuery *query = GST_QUERY_CAST (item); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved query %p from queue", query); + } else { + g_warning + ("Unexpected item %p dequeued from queue %s (refcounting problem?)", + item, GST_OBJECT_NAME (queue)); + item = NULL; + } + GST_QUEUE_SIGNAL_DEL (queue); + + return item; + + /* ERRORS */ +no_item: + { + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "the queue is empty"); + return NULL; + } +} + +static GstFlowReturn +gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean ret = TRUE; + GstQueue *queue; + + queue = GST_QUEUE (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "Received event '%s'", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + /* forward event */ + ret = gst_pad_push_event (queue->srcpad, event); + + /* now unblock the chain function */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + /* unblock the loop and chain functions */ + GST_QUEUE_SIGNAL_ADD (queue); + GST_QUEUE_SIGNAL_DEL (queue); + GST_QUEUE_MUTEX_UNLOCK (queue); + + /* make sure it pauses, this should happen since we sent + * flush_start downstream. */ + gst_pad_pause_task (queue->srcpad); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped"); + + /* unblock query handler after the streaming thread is shut down. + * Otherwise downstream might have a query that is already unreffed + * upstream */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE_MUTEX_UNLOCK (queue); + break; + case GST_EVENT_FLUSH_STOP: + /* forward event */ + ret = gst_pad_push_event (queue->srcpad, event); + + GST_QUEUE_MUTEX_LOCK (queue); + gst_queue_locked_flush (queue, FALSE); + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + if (gst_pad_is_active (queue->srcpad)) { + gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop, + queue->srcpad, NULL); + } else { + GST_INFO_OBJECT (queue->srcpad, "not re-starting task on srcpad, " + "pad not active any longer"); + } + GST_QUEUE_MUTEX_UNLOCK (queue); + + STATUS (queue, pad, "after flush"); + break; + default: + if (GST_EVENT_IS_SERIALIZED (event)) { + /* serialized events go in the queue */ + GST_QUEUE_MUTEX_LOCK (queue); + + /* STREAM_START and SEGMENT reset the EOS status of a + * pad. Change the cached sinkpad flow result accordingly */ + if (queue->srcresult == GST_FLOW_EOS + && (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START + || GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) + queue->srcresult = GST_FLOW_OK; + + if (queue->srcresult != GST_FLOW_OK) { + /* Errors in sticky event pushing are no problem and ignored here + * as they will cause more meaningful errors during data flow. + * For EOS events, that are not followed by data flow, we still + * return FALSE here though and report an error. + */ + if (!GST_EVENT_IS_STICKY (event)) { + GST_QUEUE_MUTEX_UNLOCK (queue); + goto out_flow_error; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + if (queue->srcresult == GST_FLOW_NOT_LINKED + || queue->srcresult < GST_FLOW_EOS) { + GST_QUEUE_MUTEX_UNLOCK (queue); + GST_ELEMENT_FLOW_ERROR (queue, queue->srcresult); + } else { + GST_QUEUE_MUTEX_UNLOCK (queue); + } + goto out_flow_error; + } + } + + /* refuse more events on EOS unless they unset the EOS status */ + if (queue->eos) { + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + case GST_EVENT_SEGMENT: + /* Restart the loop */ + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + gst_pad_start_task (queue->srcpad, + (GstTaskFunction) gst_queue_loop, queue->srcpad, NULL); + } else { + queue->eos = FALSE; + queue->unexpected = FALSE; + } + + break; + default: + goto out_eos; + } + } + + gst_queue_locked_enqueue_event (queue, event); + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + /* non-serialized events are forwarded downstream immediately */ + ret = gst_pad_push_event (queue->srcpad, event); + } + break; + } + if (ret == FALSE) { + GST_ERROR_OBJECT (queue, "Failed to push event"); + return GST_FLOW_ERROR; + } + return GST_FLOW_OK; + + /* ERRORS */ +out_eos: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS"); + GST_QUEUE_MUTEX_UNLOCK (queue); + gst_event_unref (event); + return GST_FLOW_EOS; + } +out_flow_error: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "refusing event, we have a downstream flow error: %s", + gst_flow_get_name (queue->srcresult)); + gst_event_unref (event); + return queue->srcresult; + } +} + +static gboolean +gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstQueue *queue = GST_QUEUE_CAST (parent); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + default: + if (G_UNLIKELY (GST_QUERY_IS_SERIALIZED (query))) { + GstQueueItem qitem; + + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + GST_LOG_OBJECT (queue, "queuing query %p (%s)", query, + GST_QUERY_TYPE_NAME (query)); + qitem.item = GST_MINI_OBJECT_CAST (query); + qitem.is_query = TRUE; + qitem.size = 0; + gst_queue_array_push_tail_struct (queue->queue, &qitem); + GST_QUEUE_SIGNAL_ADD (queue); + while (queue->srcresult == GST_FLOW_OK && + queue->last_handled_query != query) + g_cond_wait (&queue->query_handled, &queue->qlock); + queue->last_handled_query = NULL; + if (queue->srcresult != GST_FLOW_OK) + goto out_flushing; + res = queue->last_query; + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; + + /* ERRORS */ +out_flushing: + { + GST_DEBUG_OBJECT (queue, "we are flushing"); + GST_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +static gboolean +gst_queue_is_empty (GstQueue * queue) +{ + GstQueueItem *tail; + + tail = gst_queue_array_peek_tail_struct (queue->queue); + + if (tail == NULL) + return TRUE; + + /* Only consider the queue empty if the minimum thresholds + * are not reached and data is at the queue tail. Otherwise + * we would block forever on serialized queries. + */ + if (!GST_IS_BUFFER (tail->item) && !GST_IS_BUFFER_LIST (tail->item)) + return FALSE; + + /* It is possible that a max size is reached before all min thresholds are. + * Therefore, only consider it empty if it is not filled. */ + return ((queue->min_threshold.buffers > 0 && + queue->cur_level.buffers < queue->min_threshold.buffers) || + (queue->min_threshold.bytes > 0 && + queue->cur_level.bytes < queue->min_threshold.bytes) || + (queue->min_threshold.time > 0 && + queue->cur_level.time < queue->min_threshold.time)) && + !gst_queue_is_filled (queue); +} + +static gboolean +gst_queue_is_filled (GstQueue * queue) +{ + return (((queue->max_size.buffers > 0 && + queue->cur_level.buffers >= queue->max_size.buffers) || + (queue->max_size.bytes > 0 && + queue->cur_level.bytes >= queue->max_size.bytes) || + (queue->max_size.time > 0 && + queue->cur_level.time >= queue->max_size.time))); +} + +static void +gst_queue_leak_downstream (GstQueue * queue) +{ + /* for as long as the queue is filled, dequeue an item and discard it */ + while (gst_queue_is_filled (queue)) { + GstMiniObject *leak; + + leak = gst_queue_locked_dequeue (queue); + /* there is nothing to dequeue and the queue is still filled.. This should + * not happen */ + g_assert (leak != NULL); + + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "queue is full, leaking item %p on downstream end", leak); + if (GST_IS_EVENT (leak) && GST_EVENT_IS_STICKY (leak)) { + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "Storing sticky event %s on srcpad", GST_EVENT_TYPE_NAME (leak)); + gst_pad_store_sticky_event (queue->srcpad, GST_EVENT_CAST (leak)); + } + + if (!GST_IS_QUERY (leak)) + gst_mini_object_unref (leak); + + /* last buffer needs to get a DISCONT flag */ + queue->head_needs_discont = TRUE; + } +} + +static gboolean +discont_first_buffer (GstBuffer ** buffer, guint i, gpointer user_data) +{ + GstQueue *queue = user_data; + GstBuffer *subbuffer = gst_buffer_make_writable (*buffer); + + if (subbuffer) { + *buffer = subbuffer; + GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_DISCONT); + } else { + GST_DEBUG_OBJECT (queue, "Could not mark buffer as DISCONT"); + } + + return FALSE; +} + +static GstFlowReturn +gst_queue_chain_buffer_or_list (GstPad * pad, GstObject * parent, + GstMiniObject * obj, gboolean is_list) +{ + GstQueue *queue; + + queue = GST_QUEUE_CAST (parent); + + /* we have to lock the queue since we span threads */ + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + /* when we received EOS, we refuse any more data */ + if (queue->eos) + goto out_eos; + if (queue->unexpected) + goto out_unexpected; + + if (!is_list) { + GstClockTime duration, timestamp; + GstBuffer *buffer = GST_BUFFER_CAST (obj); + + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + duration = GST_BUFFER_DURATION (buffer); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of size %" + G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer), + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration)); + } else { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "received buffer list %p with %u buffers", obj, + gst_buffer_list_length (GST_BUFFER_LIST_CAST (obj))); + } + + /* We make space available if we're "full" according to whatever + * the user defined as "full". Note that this only applies to buffers. + * We always handle events and they don't count in our statistics. */ + while (gst_queue_is_filled (queue)) { + if (!queue->silent) { + GST_QUEUE_MUTEX_UNLOCK (queue); + g_signal_emit (queue, gst_queue_signals[SIGNAL_OVERRUN], 0); + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + /* we recheck, the signal could have changed the thresholds */ + if (!gst_queue_is_filled (queue)) + break; + } + + /* how are we going to make space for this buffer? */ + switch (queue->leaky) { + case GST_QUEUE_LEAK_UPSTREAM: + /* next buffer needs to get a DISCONT flag */ + queue->tail_needs_discont = TRUE; + /* leak current buffer */ + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "queue is full, leaking buffer on upstream end"); + /* now we can clean up and exit right away */ + goto out_unref; + case GST_QUEUE_LEAK_DOWNSTREAM: + gst_queue_leak_downstream (queue); + break; + default: + g_warning ("Unknown leaky type, using default"); + /* fall-through */ + case GST_QUEUE_NO_LEAK: + { + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "queue is full, waiting for free space"); + + /* don't leak. Instead, wait for space to be available */ + do { + /* for as long as the queue is filled, wait till an item was deleted. */ + GST_QUEUE_WAIT_DEL_CHECK (queue, out_flushing); + } while (gst_queue_is_filled (queue)); + + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is not full"); + + if (!queue->silent) { + GST_QUEUE_MUTEX_UNLOCK (queue); + g_signal_emit (queue, gst_queue_signals[SIGNAL_RUNNING], 0); + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + } + break; + } + } + } + + if (queue->tail_needs_discont) { + if (!is_list) { + GstBuffer *buffer = GST_BUFFER_CAST (obj); + GstBuffer *subbuffer = gst_buffer_make_writable (buffer); + + if (subbuffer) { + buffer = subbuffer; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + } else { + GST_DEBUG_OBJECT (queue, "Could not mark buffer as DISCONT"); + } + + obj = GST_MINI_OBJECT_CAST (buffer); + } else { + GstBufferList *buffer_list = GST_BUFFER_LIST_CAST (obj); + + buffer_list = gst_buffer_list_make_writable (buffer_list); + gst_buffer_list_foreach (buffer_list, discont_first_buffer, queue); + obj = GST_MINI_OBJECT_CAST (buffer_list); + } + queue->tail_needs_discont = FALSE; + } + + /* put buffer in queue now */ + if (is_list) + gst_queue_locked_enqueue_buffer_list (queue, obj); + else + gst_queue_locked_enqueue_buffer (queue, obj); + GST_QUEUE_MUTEX_UNLOCK (queue); + + return GST_FLOW_OK; + + /* special conditions */ +out_unref: + { + GST_QUEUE_MUTEX_UNLOCK (queue); + + gst_mini_object_unref (obj); + + return GST_FLOW_OK; + } +out_flushing: + { + GstFlowReturn ret = queue->srcresult; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "exit because task paused, reason: %s", gst_flow_get_name (ret)); + GST_QUEUE_MUTEX_UNLOCK (queue); + gst_mini_object_unref (obj); + + return ret; + } +out_eos: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); + GST_QUEUE_MUTEX_UNLOCK (queue); + + gst_mini_object_unref (obj); + + return GST_FLOW_EOS; + } +out_unexpected: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); + GST_QUEUE_MUTEX_UNLOCK (queue); + + gst_mini_object_unref (obj); + + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_queue_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list) +{ + return gst_queue_chain_buffer_or_list (pad, parent, + GST_MINI_OBJECT_CAST (buffer_list), TRUE); +} + +static GstFlowReturn +gst_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + return gst_queue_chain_buffer_or_list (pad, parent, + GST_MINI_OBJECT_CAST (buffer), FALSE); +} + +/* dequeue an item from the queue an push it downstream. This functions returns + * the result of the push. */ +static GstFlowReturn +gst_queue_push_one (GstQueue * queue) +{ + GstFlowReturn result = queue->srcresult; + GstMiniObject *data; + gboolean is_list; + + data = gst_queue_locked_dequeue (queue); + if (data == NULL) + goto no_item; + +next: + is_list = GST_IS_BUFFER_LIST (data); + + if (GST_IS_BUFFER (data) || is_list) { + if (!is_list) { + GstBuffer *buffer; + + buffer = GST_BUFFER_CAST (data); + + if (queue->head_needs_discont) { + GstBuffer *subbuffer = gst_buffer_make_writable (buffer); + + if (subbuffer) { + buffer = subbuffer; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + } else { + GST_DEBUG_OBJECT (queue, "Could not mark buffer as DISCONT"); + } + queue->head_needs_discont = FALSE; + } + + GST_QUEUE_MUTEX_UNLOCK (queue); + result = gst_pad_push (queue->srcpad, buffer); + } else { + GstBufferList *buffer_list; + + buffer_list = GST_BUFFER_LIST_CAST (data); + + if (queue->head_needs_discont) { + buffer_list = gst_buffer_list_make_writable (buffer_list); + gst_buffer_list_foreach (buffer_list, discont_first_buffer, queue); + queue->head_needs_discont = FALSE; + } + + GST_QUEUE_MUTEX_UNLOCK (queue); + result = gst_pad_push_list (queue->srcpad, buffer_list); + } + + /* need to check for srcresult here as well */ + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + + if (result == GST_FLOW_EOS) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream"); + /* stop pushing buffers, we dequeue all items until we see an item that we + * can push again, which is EOS or SEGMENT. If there is nothing in the + * queue we can push, we set a flag to make the sinkpad refuse more + * buffers with an EOS return value. */ + while ((data = gst_queue_locked_dequeue (queue))) { + if (GST_IS_BUFFER (data)) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer %p", data); + gst_buffer_unref (GST_BUFFER_CAST (data)); + } else if (GST_IS_BUFFER_LIST (data)) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer list %p", data); + gst_buffer_list_unref (GST_BUFFER_LIST_CAST (data)); + } else if (GST_IS_EVENT (data)) { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); + + if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT + || type == GST_EVENT_STREAM_START) { + /* we found a pushable item in the queue, push it out */ + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pushing pushable event %s after EOS", + GST_EVENT_TYPE_NAME (event)); + goto next; + } + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS event %p", event); + gst_event_unref (event); + } else if (GST_IS_QUERY (data)) { + GstQuery *query = GST_QUERY_CAST (data); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping query %p because of EOS", query); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + } + } + /* no more items in the queue. Set the unexpected flag so that upstream + * make us refuse any more buffers on the sinkpad. Since we will still + * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the + * task function does not shut down. */ + queue->unexpected = TRUE; + result = GST_FLOW_OK; + } + } else if (GST_IS_EVENT (data)) { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); + + GST_QUEUE_MUTEX_UNLOCK (queue); + + gst_pad_push_event (queue->srcpad, event); + + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + /* if we're EOS, return EOS so that the task pauses. */ + if (type == GST_EVENT_EOS) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pushed EOS event %p, return EOS", event); + result = GST_FLOW_EOS; + } + } else if (GST_IS_QUERY (data)) { + GstQuery *query = GST_QUERY_CAST (data); + gboolean ret; + + GST_QUEUE_MUTEX_UNLOCK (queue); + ret = gst_pad_peer_query (queue->srcpad, query); + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing_query); + queue->last_query = ret; + queue->last_handled_query = query; + g_cond_signal (&queue->query_handled); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "did query %p, return %d", query, queue->last_query); + } + return result; + + /* ERRORS */ +no_item: + { + GST_CAT_ERROR_OBJECT (queue_dataflow, queue, + "exit because we have no item in the queue"); + return GST_FLOW_ERROR; + } +out_flushing: + { + GstFlowReturn ret = queue->srcresult; + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "exit because task paused, reason: %s", gst_flow_get_name (ret)); + return ret; + } +out_flushing_query: + { + GstFlowReturn ret = queue->srcresult; + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "exit because task paused, reason: %s", gst_flow_get_name (ret)); + return ret; + } +} + +static void +gst_queue_loop (GstPad * pad) +{ + GstQueue *queue; + GstFlowReturn ret; + + queue = (GstQueue *) GST_PAD_PARENT (pad); + + /* have to lock for thread-safety */ + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + + while (gst_queue_is_empty (queue)) { + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is empty"); + if (!queue->silent) { + GST_QUEUE_MUTEX_UNLOCK (queue); + g_signal_emit (queue, gst_queue_signals[SIGNAL_UNDERRUN], 0); + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + } + + /* we recheck, the signal could have changed the thresholds */ + while (gst_queue_is_empty (queue)) { + GST_QUEUE_WAIT_ADD_CHECK (queue, out_flushing); + } + + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is not empty"); + if (!queue->silent) { + GST_QUEUE_MUTEX_UNLOCK (queue); + g_signal_emit (queue, gst_queue_signals[SIGNAL_RUNNING], 0); + g_signal_emit (queue, gst_queue_signals[SIGNAL_PUSHING], 0); + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + } + } + + ret = gst_queue_push_one (queue); + queue->srcresult = ret; + if (ret != GST_FLOW_OK) + goto out_flushing; + + GST_QUEUE_MUTEX_UNLOCK (queue); + + return; + + /* ERRORS */ +out_flushing: + { + gboolean eos = queue->eos; + GstFlowReturn ret = queue->srcresult; + + gst_pad_pause_task (queue->srcpad); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pause task, reason: %s", gst_flow_get_name (ret)); + if (ret == GST_FLOW_FLUSHING) { + gst_queue_locked_flush (queue, FALSE); + } else { + GST_QUEUE_SIGNAL_DEL (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + } + GST_QUEUE_MUTEX_UNLOCK (queue); + /* let app know about us giving up if upstream is not expected to do so */ + /* EOS is already taken care of elsewhere */ + if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { + GST_ELEMENT_FLOW_ERROR (queue, ret); + gst_pad_push_event (queue->srcpad, gst_event_new_eos ()); + } + return; + } +} + +static gboolean +gst_queue_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + GstQueue *queue = GST_QUEUE (parent); + +#ifndef GST_DISABLE_GST_DEBUG + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%d)", + event, GST_EVENT_TYPE (event)); +#endif + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_RECONFIGURE: + GST_QUEUE_MUTEX_LOCK (queue); + if (queue->srcresult == GST_FLOW_NOT_LINKED) { + /* when we got not linked, assume downstream is linked again now and we + * can try to start pushing again */ + queue->srcresult = GST_FLOW_OK; + gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad, NULL); + } + GST_QUEUE_MUTEX_UNLOCK (queue); + + res = gst_pad_push_event (queue->sinkpad, event); + break; + default: + res = gst_pad_event_default (pad, parent, event); + break; + } + + + return res; +} + +static gboolean +gst_queue_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstQueue *queue = GST_QUEUE (parent); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING:{ + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + res = TRUE; + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + + if (!res) + return FALSE; + + /* Adjust peer response for data contained in queue */ + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos; + GstFormat format; + + /* get peer position */ + gst_query_parse_position (query, &format, &peer_pos); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= queue->cur_level.bytes; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + case GST_FORMAT_TIME: + peer_pos -= queue->cur_level.time; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + default: + GST_DEBUG_OBJECT (queue, "Can't adjust query in %s format, don't " + "know how to adjust value", gst_format_get_name (format)); + return TRUE; + } + /* set updated position */ + gst_query_set_position (query, format, peer_pos); + break; + } + case GST_QUERY_LATENCY: + { + gboolean live; + GstClockTime min, max; + + gst_query_parse_latency (query, &live, &min, &max); + + /* we can delay up to the limit of the queue in time. If we have no time + * limit, the best thing we can do is to return an infinite delay. In + * reality a better estimate would be the byte/buffer rate but that is not + * possible right now. */ + /* TODO: Use CONVERT query? */ + if (queue->max_size.time > 0 && max != -1 + && queue->leaky == GST_QUEUE_NO_LEAK) + max += queue->max_size.time; + else if (queue->max_size.time > 0 && queue->leaky != GST_QUEUE_NO_LEAK) + max = MIN (queue->max_size.time, max); + else + max = -1; + + /* adjust for min-threshold */ + if (queue->min_threshold.time > 0) + min += queue->min_threshold.time; + + gst_query_set_latency (query, live, min, max); + break; + } + default: + /* peer handled other queries */ + break; + } + + return TRUE; +} + +static gboolean +gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean result; + GstQueue *queue; + + queue = GST_QUEUE (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + /* step 1, unblock chain function */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + /* the item del signal will unblock */ + GST_QUEUE_SIGNAL_DEL (queue); + GST_QUEUE_MUTEX_UNLOCK (queue); + + /* step 2, wait until streaming thread stopped and flush queue */ + GST_PAD_STREAM_LOCK (pad); + GST_QUEUE_MUTEX_LOCK (queue); + gst_queue_locked_flush (queue, TRUE); + GST_QUEUE_MUTEX_UNLOCK (queue); + GST_PAD_STREAM_UNLOCK (pad); + } + result = TRUE; + break; + default: + result = FALSE; + break; + } + return result; +} + +static gboolean +gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean result; + GstQueue *queue; + + queue = GST_QUEUE (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + result = + gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad, + NULL); + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + /* step 1, unblock loop function */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + /* the item add signal will unblock */ + g_cond_signal (&queue->item_add); + GST_QUEUE_MUTEX_UNLOCK (queue); + + /* step 2, make sure streaming finishes */ + result = gst_pad_stop_task (pad); + + GST_QUEUE_MUTEX_LOCK (queue); + gst_queue_locked_flush (queue, FALSE); + GST_QUEUE_MUTEX_UNLOCK (queue); + } + break; + default: + result = FALSE; + break; + } + return result; +} + +static void +queue_capacity_change (GstQueue * queue) +{ + if (queue->leaky == GST_QUEUE_LEAK_DOWNSTREAM) { + gst_queue_leak_downstream (queue); + } + + /* changing the capacity of the queue must wake up + * the _chain function, it might have more room now + * to store the buffer/event in the queue */ + GST_QUEUE_SIGNAL_DEL (queue); +} + +/* Changing the minimum required fill level must + * wake up the _loop function as it might now + * be able to preceed. + */ +#define QUEUE_THRESHOLD_CHANGE(q)\ + GST_QUEUE_SIGNAL_ADD (q); + +static void +gst_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstQueue *queue = GST_QUEUE (object); + + /* someone could change levels here, and since this + * affects the get/put funcs, we need to lock for safety. */ + GST_QUEUE_MUTEX_LOCK (queue); + + switch (prop_id) { + case PROP_MAX_SIZE_BYTES: + queue->max_size.bytes = g_value_get_uint (value); + queue_capacity_change (queue); + break; + case PROP_MAX_SIZE_BUFFERS: + queue->max_size.buffers = g_value_get_uint (value); + queue_capacity_change (queue); + break; + case PROP_MAX_SIZE_TIME: + queue->max_size.time = g_value_get_uint64 (value); + queue_capacity_change (queue); + break; + case PROP_MIN_THRESHOLD_BYTES: + queue->min_threshold.bytes = g_value_get_uint (value); + queue->orig_min_threshold.bytes = queue->min_threshold.bytes; + QUEUE_THRESHOLD_CHANGE (queue); + break; + case PROP_MIN_THRESHOLD_BUFFERS: + queue->min_threshold.buffers = g_value_get_uint (value); + queue->orig_min_threshold.buffers = queue->min_threshold.buffers; + QUEUE_THRESHOLD_CHANGE (queue); + break; + case PROP_MIN_THRESHOLD_TIME: + queue->min_threshold.time = g_value_get_uint64 (value); + queue->orig_min_threshold.time = queue->min_threshold.time; + QUEUE_THRESHOLD_CHANGE (queue); + break; + case PROP_LEAKY: + queue->leaky = g_value_get_enum (value); + break; + case PROP_SILENT: + queue->silent = g_value_get_boolean (value); + break; + case PROP_FLUSH_ON_EOS: + queue->flush_on_eos = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_QUEUE_MUTEX_UNLOCK (queue); +} + +static void +gst_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstQueue *queue = GST_QUEUE (object); + + GST_QUEUE_MUTEX_LOCK (queue); + + switch (prop_id) { + case PROP_CUR_LEVEL_BYTES: + g_value_set_uint (value, queue->cur_level.bytes); + break; + case PROP_CUR_LEVEL_BUFFERS: + g_value_set_uint (value, queue->cur_level.buffers); + break; + case PROP_CUR_LEVEL_TIME: + g_value_set_uint64 (value, queue->cur_level.time); + break; + case PROP_MAX_SIZE_BYTES: + g_value_set_uint (value, queue->max_size.bytes); + break; + case PROP_MAX_SIZE_BUFFERS: + g_value_set_uint (value, queue->max_size.buffers); + break; + case PROP_MAX_SIZE_TIME: + g_value_set_uint64 (value, queue->max_size.time); + break; + case PROP_MIN_THRESHOLD_BYTES: + g_value_set_uint (value, queue->min_threshold.bytes); + break; + case PROP_MIN_THRESHOLD_BUFFERS: + g_value_set_uint (value, queue->min_threshold.buffers); + break; + case PROP_MIN_THRESHOLD_TIME: + g_value_set_uint64 (value, queue->min_threshold.time); + break; + case PROP_LEAKY: + g_value_set_enum (value, queue->leaky); + break; + case PROP_SILENT: + g_value_set_boolean (value, queue->silent); + break; + case PROP_FLUSH_ON_EOS: + g_value_set_boolean (value, queue->flush_on_eos); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_QUEUE_MUTEX_UNLOCK (queue); +} diff --git a/plugins/elements/gstqueue.h b/plugins/elements/gstqueue.h new file mode 100644 index 0000000..2a9cb36 --- /dev/null +++ b/plugins/elements/gstqueue.h @@ -0,0 +1,160 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstqueue.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_QUEUE_H__ +#define __GST_QUEUE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_QUEUE \ + (gst_queue_get_type()) +#define GST_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QUEUE,GstQueue)) +#define GST_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QUEUE,GstQueueClass)) +#define GST_IS_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QUEUE)) +#define GST_IS_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE)) +#define GST_QUEUE_CAST(obj) \ + ((GstQueue *)(obj)) + +typedef struct _GstQueue GstQueue; +typedef struct _GstQueueSize GstQueueSize; +typedef enum _GstQueueLeaky GstQueueLeaky; +typedef struct _GstQueueClass GstQueueClass; + +/** + * GstQueueLeaky: + * @GST_QUEUE_NO_LEAK: Not Leaky + * @GST_QUEUE_LEAK_UPSTREAM: Leaky on upstream (new buffers) + * @GST_QUEUE_LEAK_DOWNSTREAM: Leaky on downstream (old buffers) + * + * Buffer dropping scheme to avoid the queue to block when full. + */ +enum _GstQueueLeaky { + GST_QUEUE_NO_LEAK = 0, + GST_QUEUE_LEAK_UPSTREAM = 1, + GST_QUEUE_LEAK_DOWNSTREAM = 2 +}; + +/* + * GstQueueSize: + * @buffers: number of buffers + * @bytes: number of bytes + * @time: amount of time + * + * Structure describing the size of a queue. + */ +struct _GstQueueSize { + guint buffers; + guint bytes; + guint64 time; +}; + +#define GST_QUEUE_CLEAR_LEVEL(l) G_STMT_START { \ + l.buffers = 0; \ + l.bytes = 0; \ + l.time = 0; \ +} G_STMT_END + +/** + * GstQueue: + * + * Opaque #GstQueue structure. + */ +struct _GstQueue { + GstElement element; + + /*< private >*/ + GstPad *sinkpad; + GstPad *srcpad; + + /* segments to keep track of timestamps */ + GstSegment sink_segment; + GstSegment src_segment; + + /* position of src/sink */ + GstClockTimeDiff sinktime, srctime; + /* TRUE if either position needs to be recalculated */ + gboolean sink_tainted, src_tainted; + + /* flowreturn when srcpad is paused */ + GstFlowReturn srcresult; + gboolean unexpected; + gboolean eos; + + /* the queue of data we're keeping our grubby hands on */ + GstQueueArray *queue; + + GstQueueSize + cur_level, /* currently in the queue */ + max_size, /* max. amount of data allowed in the queue */ + min_threshold, /* min. amount of data required to wake reader */ + orig_min_threshold; /* Original min.threshold, for reset in EOS */ + + /* whether we leak data, and at which end */ + gint leaky; + + GMutex qlock; /* lock for queue (vs object lock) */ + gboolean waiting_add; + GCond item_add; /* signals buffers now available for reading */ + gboolean waiting_del; + GCond item_del; /* signals space now available for writing */ + + gboolean head_needs_discont, tail_needs_discont; + gboolean push_newsegment; + + gboolean silent; /* don't emit signals */ + + /* whether the first new segment has been applied to src */ + gboolean newseg_applied_to_src; + + GCond query_handled; + gboolean last_query; + GstQuery *last_handled_query; + + gboolean flush_on_eos; /* flush on EOS */ +}; + +struct _GstQueueClass { + GstElementClass parent_class; + + /* signals - 'running' is called from both sides + * which might make it sort of non-useful... */ + void (*underrun) (GstQueue *queue); + void (*running) (GstQueue *queue); + void (*overrun) (GstQueue *queue); + + void (*pushing) (GstQueue *queue); +}; + +G_GNUC_INTERNAL GType gst_queue_get_type (void); + +G_END_DECLS + + +#endif /* __GST_QUEUE_H__ */ diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c new file mode 100644 index 0000000..fb5452e --- /dev/null +++ b/plugins/elements/gstqueue2.c @@ -0,0 +1,3912 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2003 Colin Walters + * 2000,2005,2007 Wim Taymans + * 2007 Thiago Sousa Santos + * SA 2010 ST-Ericsson + * + * gstqueue2.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-queue2 + * @title: queue2 + * + * Data is queued until one of the limits specified by the + * #GstQueue2:max-size-buffers, #GstQueue2:max-size-bytes and/or + * #GstQueue2:max-size-time properties has been reached. Any attempt to push + * more buffers into the queue will block the pushing thread until more space + * becomes available. + * + * The queue will create a new thread on the source pad to decouple the + * processing on sink and source pad. + * + * You can query how many buffers are queued by reading the + * #GstQueue2:current-level-buffers property. + * + * The default queue size limits are 100 buffers, 2MB of data, or + * two seconds worth of data, whichever is reached first. + * + * If you set temp-template to a value such as /tmp/gstreamer-XXXXXX, the element + * will allocate a random free filename and buffer data in the file. + * By using this, it will buffer the entire stream data on the file independently + * of the queue size limits, they will only be used for buffering statistics. + * + * The temp-location property will be used to notify the application of the + * allocated filename. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstqueue2.h" + +#include + +#include "gst/gst-i18n-lib.h" +#include "gst/glib-compat-private.h" + +#include + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#undef off_t +#define off_t guint64 +#else +#include +#endif + +#ifdef __BIONIC__ /* Android */ +#include +#endif + +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); + +GST_DEBUG_CATEGORY_STATIC (queue_debug); +#define GST_CAT_DEFAULT (queue_debug) +GST_DEBUG_CATEGORY_STATIC (queue_dataflow); + +enum +{ + LAST_SIGNAL +}; + +/* other defines */ +#define DEFAULT_BUFFER_SIZE 4096 +#define QUEUE_IS_USING_TEMP_FILE(queue) ((queue)->temp_template != NULL) +#define QUEUE_IS_USING_RING_BUFFER(queue) ((queue)->ring_buffer_max_size != 0) /* for consistency with the above macro */ +#define QUEUE_IS_USING_QUEUE(queue) (!QUEUE_IS_USING_TEMP_FILE(queue) && !QUEUE_IS_USING_RING_BUFFER (queue)) + +#define QUEUE_MAX_BYTES(queue) MIN((queue)->max_level.bytes, (queue)->ring_buffer_max_size) + +/* default property values */ +#define DEFAULT_MAX_SIZE_BUFFERS 100 /* 100 buffers */ +#define DEFAULT_MAX_SIZE_BYTES (2 * 1024 * 1024) /* 2 MB */ +#define DEFAULT_MAX_SIZE_TIME 2 * GST_SECOND /* 2 seconds */ +#define DEFAULT_USE_BUFFERING FALSE +#define DEFAULT_USE_TAGS_BITRATE FALSE +#define DEFAULT_USE_RATE_ESTIMATE TRUE +#define DEFAULT_LOW_PERCENT 10 +#define DEFAULT_HIGH_PERCENT 99 +#define DEFAULT_LOW_WATERMARK 0.01 +#define DEFAULT_HIGH_WATERMARK 0.99 +#define DEFAULT_TEMP_REMOVE TRUE +#define DEFAULT_RING_BUFFER_MAX_SIZE 0 + +enum +{ + PROP_0, + PROP_CUR_LEVEL_BUFFERS, + PROP_CUR_LEVEL_BYTES, + PROP_CUR_LEVEL_TIME, + PROP_MAX_SIZE_BUFFERS, + PROP_MAX_SIZE_BYTES, + PROP_MAX_SIZE_TIME, + PROP_USE_BUFFERING, + PROP_USE_TAGS_BITRATE, + PROP_USE_RATE_ESTIMATE, + PROP_LOW_PERCENT, + PROP_HIGH_PERCENT, + PROP_LOW_WATERMARK, + PROP_HIGH_WATERMARK, + PROP_TEMP_TEMPLATE, + PROP_TEMP_LOCATION, + PROP_TEMP_REMOVE, + PROP_RING_BUFFER_MAX_SIZE, + PROP_AVG_IN_RATE, + PROP_LAST +}; + +/* Explanation for buffer levels and percentages: + * + * The buffering_level functions here return a value in a normalized range + * that specifies the queue's current fill level. The range goes from 0 to + * MAX_BUFFERING_LEVEL. The low/high watermarks also use this same range. + * + * This is not to be confused with the buffering_percent value, which is + * a *relative* quantity - relative to the low/high watermarks. + * buffering_percent = 0% means buffering_level is at the low watermark. + * buffering_percent = 100% means buffering_level is at the high watermark. + * buffering_percent is used for determining if the fill level has reached + * the high watermark, and for producing BUFFERING messages. This value + * always uses a 0..100 range (since it is a percentage). + * + * To avoid future confusions, whenever "buffering level" is mentioned, it + * refers to the absolute level which is in the 0..MAX_BUFFERING_LEVEL + * range. Whenever "buffering_percent" is mentioned, it refers to the + * percentage value that is relative to the low/high watermark. */ + +/* Using a buffering level range of 0..1000000 to allow for a + * resolution in ppm (1 ppm = 0.0001%) */ +#define MAX_BUFFERING_LEVEL 1000000 + +/* How much 1% makes up in the buffer level range */ +#define BUF_LEVEL_PERCENT_FACTOR ((MAX_BUFFERING_LEVEL) / 100) + +#define GST_QUEUE2_CLEAR_LEVEL(l) G_STMT_START { \ + l.buffers = 0; \ + l.bytes = 0; \ + l.time = 0; \ + l.rate_time = 0; \ +} G_STMT_END + +#define STATUS(queue, pad, msg) \ + GST_CAT_LOG_OBJECT (queue_dataflow, queue, \ + "(%s:%s) " msg ": %u of %u buffers, %u of %u " \ + "bytes, %" G_GUINT64_FORMAT " of %" G_GUINT64_FORMAT \ + " ns, %"G_GUINT64_FORMAT" items", \ + GST_DEBUG_PAD_NAME (pad), \ + queue->cur_level.buffers, \ + queue->max_level.buffers, \ + queue->cur_level.bytes, \ + queue->max_level.bytes, \ + queue->cur_level.time, \ + queue->max_level.time, \ + (guint64) (!QUEUE_IS_USING_QUEUE(queue) ? \ + queue->current->writing_pos - queue->current->max_reading_pos : \ + queue->queue.length)) + +#define GST_QUEUE2_MUTEX_LOCK(q) G_STMT_START { \ + g_mutex_lock (&q->qlock); \ +} G_STMT_END + +#define GST_QUEUE2_MUTEX_LOCK_CHECK(q,res,label) G_STMT_START { \ + GST_QUEUE2_MUTEX_LOCK (q); \ + if (res != GST_FLOW_OK) \ + goto label; \ +} G_STMT_END + +#define GST_QUEUE2_MUTEX_UNLOCK(q) G_STMT_START { \ + g_mutex_unlock (&q->qlock); \ +} G_STMT_END + +#define GST_QUEUE2_WAIT_DEL_CHECK(q, res, label) G_STMT_START { \ + STATUS (queue, q->sinkpad, "wait for DEL"); \ + q->waiting_del = TRUE; \ + g_cond_wait (&q->item_del, &queue->qlock); \ + q->waiting_del = FALSE; \ + if (res != GST_FLOW_OK) { \ + STATUS (queue, q->srcpad, "received DEL wakeup"); \ + goto label; \ + } \ + STATUS (queue, q->sinkpad, "received DEL"); \ +} G_STMT_END + +#define GST_QUEUE2_WAIT_ADD_CHECK(q, res, label) G_STMT_START { \ + STATUS (queue, q->srcpad, "wait for ADD"); \ + q->waiting_add = TRUE; \ + g_cond_wait (&q->item_add, &q->qlock); \ + q->waiting_add = FALSE; \ + if (res != GST_FLOW_OK) { \ + STATUS (queue, q->srcpad, "received ADD wakeup"); \ + goto label; \ + } \ + STATUS (queue, q->srcpad, "received ADD"); \ +} G_STMT_END + +#define GST_QUEUE2_SIGNAL_DEL(q) G_STMT_START { \ + if (q->waiting_del) { \ + STATUS (q, q->srcpad, "signal DEL"); \ + g_cond_signal (&q->item_del); \ + } \ +} G_STMT_END + +#define GST_QUEUE2_SIGNAL_ADD(q) G_STMT_START { \ + if (q->waiting_add) { \ + STATUS (q, q->sinkpad, "signal ADD"); \ + g_cond_signal (&q->item_add); \ + } \ +} G_STMT_END + +#define SET_PERCENT(q, perc) G_STMT_START { \ + if (perc != q->buffering_percent) { \ + q->buffering_percent = perc; \ + q->percent_changed = TRUE; \ + GST_DEBUG_OBJECT (q, "buffering %d percent", perc); \ + get_buffering_stats (q, perc, &q->mode, &q->avg_in, &q->avg_out, \ + &q->buffering_left); \ + } \ +} G_STMT_END + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (queue_debug, "queue2", 0, "queue element"); \ + GST_DEBUG_CATEGORY_INIT (queue_dataflow, "queue2_dataflow", 0, \ + "dataflow inside the queue element"); +#define gst_queue2_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstQueue2, gst_queue2, GST_TYPE_ELEMENT, _do_init); + +static void gst_queue2_finalize (GObject * object); + +static void gst_queue2_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_queue2_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_queue2_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_queue2_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list); +static GstFlowReturn gst_queue2_push_one (GstQueue2 * queue); +static void gst_queue2_loop (GstPad * pad); + +static GstFlowReturn gst_queue2_handle_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +static gboolean gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_queue2_handle_query (GstElement * element, + GstQuery * query); + +static GstFlowReturn gst_queue2_get_range (GstPad * pad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buffer); + +static gboolean gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static GstStateChangeReturn gst_queue2_change_state (GstElement * element, + GstStateChange transition); + +static gboolean gst_queue2_is_empty (GstQueue2 * queue); +static gboolean gst_queue2_is_filled (GstQueue2 * queue); + +static void update_cur_level (GstQueue2 * queue, GstQueue2Range * range); +static void update_in_rates (GstQueue2 * queue, gboolean force); +static GstMessage *gst_queue2_get_buffering_message (GstQueue2 * queue); +static void gst_queue2_post_buffering (GstQueue2 * queue); + +typedef enum +{ + GST_QUEUE2_ITEM_TYPE_UNKNOWN = 0, + GST_QUEUE2_ITEM_TYPE_BUFFER, + GST_QUEUE2_ITEM_TYPE_BUFFER_LIST, + GST_QUEUE2_ITEM_TYPE_EVENT, + GST_QUEUE2_ITEM_TYPE_QUERY +} GstQueue2ItemType; + +typedef struct +{ + GstQueue2ItemType type; + GstMiniObject *item; +} GstQueue2Item; + +/* static guint gst_queue2_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_queue2_class_init (GstQueue2Class * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_queue2_set_property; + gobject_class->get_property = gst_queue2_get_property; + + /* properties */ + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES, + g_param_spec_uint ("current-level-bytes", "Current level (kB)", + "Current amount of data in the queue (bytes)", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BUFFERS, + g_param_spec_uint ("current-level-buffers", "Current level (buffers)", + "Current number of buffers in the queue", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME, + g_param_spec_uint64 ("current-level-time", "Current level (ns)", + "Current amount of data in the queue (in ns)", + 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES, + g_param_spec_uint ("max-size-bytes", "Max. size (kB)", + "Max. amount of data in the queue (bytes, 0=disable)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS, + g_param_spec_uint ("max-size-buffers", "Max. size (buffers)", + "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT, + DEFAULT_MAX_SIZE_BUFFERS, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME, + g_param_spec_uint64 ("max-size-time", "Max. size (ns)", + "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64, + DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_USE_BUFFERING, + g_param_spec_boolean ("use-buffering", "Use buffering", + "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds", + DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_USE_TAGS_BITRATE, + g_param_spec_boolean ("use-tags-bitrate", "Use bitrate from tags", + "Use a bitrate from upstream tags to estimate buffer duration if not provided", + DEFAULT_USE_TAGS_BITRATE, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_USE_RATE_ESTIMATE, + g_param_spec_boolean ("use-rate-estimate", "Use Rate Estimate", + "Estimate the bitrate of the stream to calculate time level", + DEFAULT_USE_RATE_ESTIMATE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_LOW_PERCENT, + g_param_spec_int ("low-percent", "Low percent", + "Low threshold for buffering to start. Only used if use-buffering is True " + "(Deprecated: use low-watermark instead)", + 0, 100, DEFAULT_LOW_WATERMARK * 100, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT, + g_param_spec_int ("high-percent", "High percent", + "High threshold for buffering to finish. Only used if use-buffering is True " + "(Deprecated: use high-watermark instead)", + 0, 100, DEFAULT_HIGH_WATERMARK * 100, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_LOW_WATERMARK, + g_param_spec_double ("low-watermark", "Low watermark", + "Low threshold for buffering to start. Only used if use-buffering is True", + 0.0, 1.0, DEFAULT_LOW_WATERMARK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HIGH_WATERMARK, + g_param_spec_double ("high-watermark", "High watermark", + "High threshold for buffering to finish. Only used if use-buffering is True", + 0.0, 1.0, DEFAULT_HIGH_WATERMARK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE, + g_param_spec_string ("temp-template", "Temporary File Template", + "File template to store temporary files in, should contain directory " + "and XXXXXX. (NULL == disabled)", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION, + g_param_spec_string ("temp-location", "Temporary File Location", + "Location to store temporary files in (Only read this property, " + "use temp-template to configure the name template)", + NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstQueue2:temp-remove + * + * When temp-template is set, remove the temporary file when going to READY. + */ + g_object_class_install_property (gobject_class, PROP_TEMP_REMOVE, + g_param_spec_boolean ("temp-remove", "Remove the Temporary File", + "Remove the temp-location after use", + DEFAULT_TEMP_REMOVE, 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. + */ + 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 = disabled)", + 0, G_MAXUINT64, DEFAULT_RING_BUFFER_MAX_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstQueue2:avg-in-rate + * + * The average input data rate. + */ + g_object_class_install_property (gobject_class, PROP_AVG_IN_RATE, + g_param_spec_int64 ("avg-in-rate", "Input data rate (bytes/s)", + "Average input data rate (bytes/s)", + 0, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* set several parent class virtual functions */ + gobject_class->finalize = gst_queue2_finalize; + + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gst_element_class_set_static_metadata (gstelement_class, "Queue 2", + "Generic", + "Simple data queue", + "Erik Walthinsen , " + "Wim Taymans "); + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_queue2_change_state); + gstelement_class->query = GST_DEBUG_FUNCPTR (gst_queue2_handle_query); +} + +static void +gst_queue2_init (GstQueue2 * queue) +{ + queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); + + gst_pad_set_chain_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_chain)); + gst_pad_set_chain_list_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_chain_list)); + gst_pad_set_activatemode_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_mode)); + gst_pad_set_event_full_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event)); + gst_pad_set_query_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query)); + GST_PAD_SET_PROXY_CAPS (queue->sinkpad); + gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); + + queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + + gst_pad_set_activatemode_function (queue->srcpad, + GST_DEBUG_FUNCPTR (gst_queue2_src_activate_mode)); + gst_pad_set_getrange_function (queue->srcpad, + GST_DEBUG_FUNCPTR (gst_queue2_get_range)); + gst_pad_set_event_function (queue->srcpad, + GST_DEBUG_FUNCPTR (gst_queue2_handle_src_event)); + gst_pad_set_query_function (queue->srcpad, + GST_DEBUG_FUNCPTR (gst_queue2_handle_src_query)); + GST_PAD_SET_PROXY_CAPS (queue->srcpad); + gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); + + /* levels */ + GST_QUEUE2_CLEAR_LEVEL (queue->cur_level); + queue->max_level.buffers = DEFAULT_MAX_SIZE_BUFFERS; + queue->max_level.bytes = DEFAULT_MAX_SIZE_BYTES; + queue->max_level.time = DEFAULT_MAX_SIZE_TIME; + queue->max_level.rate_time = DEFAULT_MAX_SIZE_TIME; + queue->use_buffering = DEFAULT_USE_BUFFERING; + queue->use_rate_estimate = DEFAULT_USE_RATE_ESTIMATE; + queue->low_watermark = DEFAULT_LOW_WATERMARK * MAX_BUFFERING_LEVEL; + queue->high_watermark = DEFAULT_HIGH_WATERMARK * MAX_BUFFERING_LEVEL; + + gst_segment_init (&queue->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&queue->src_segment, GST_FORMAT_TIME); + + queue->sinktime = GST_CLOCK_TIME_NONE; + queue->srctime = GST_CLOCK_TIME_NONE; + queue->sink_tainted = TRUE; + queue->src_tainted = TRUE; + + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + queue->is_eos = FALSE; + queue->in_timer = g_timer_new (); + queue->out_timer = g_timer_new (); + + g_mutex_init (&queue->qlock); + queue->waiting_add = FALSE; + g_cond_init (&queue->item_add); + queue->waiting_del = FALSE; + g_cond_init (&queue->item_del); + g_queue_init (&queue->queue); + + g_cond_init (&queue->query_handled); + queue->last_query = FALSE; + + g_mutex_init (&queue->buffering_post_lock); + queue->buffering_percent = 100; + + /* tempfile related */ + queue->temp_template = NULL; + queue->temp_location = NULL; + queue->temp_remove = DEFAULT_TEMP_REMOVE; + + queue->ring_buffer = NULL; + queue->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE; + + GST_DEBUG_OBJECT (queue, + "initialized queue's not_empty & not_full conditions"); +} + +/* called only once, as opposed to dispose */ +static void +gst_queue2_finalize (GObject * object) +{ + GstQueue2 *queue = GST_QUEUE2 (object); + + GST_DEBUG_OBJECT (queue, "finalizing queue"); + + while (!g_queue_is_empty (&queue->queue)) { + GstQueue2Item *qitem = g_queue_pop_head (&queue->queue); + + if (qitem->type != GST_QUEUE2_ITEM_TYPE_QUERY) + gst_mini_object_unref (qitem->item); + g_slice_free (GstQueue2Item, qitem); + } + + queue->last_query = FALSE; + g_queue_clear (&queue->queue); + g_mutex_clear (&queue->qlock); + g_mutex_clear (&queue->buffering_post_lock); + g_cond_clear (&queue->item_add); + g_cond_clear (&queue->item_del); + g_cond_clear (&queue->query_handled); + g_timer_destroy (queue->in_timer); + g_timer_destroy (queue->out_timer); + + /* temp_file path cleanup */ + g_free (queue->temp_template); + g_free (queue->temp_location); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +debug_ranges (GstQueue2 * queue) +{ + GstQueue2Range *walk; + + for (walk = queue->ranges; walk; walk = walk->next) { + GST_DEBUG_OBJECT (queue, + "range [%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT "] (rb [%" + G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT "]), reading %" G_GUINT64_FORMAT + " current range? %s", walk->offset, walk->writing_pos, walk->rb_offset, + walk->rb_writing_pos, walk->reading_pos, + walk == queue->current ? "**y**" : " n "); + } +} + +/* clear all the downloaded ranges */ +static void +clean_ranges (GstQueue2 * queue) +{ + GST_DEBUG_OBJECT (queue, "clean queue ranges"); + + g_slice_free_chain (GstQueue2Range, queue->ranges, next); + queue->ranges = NULL; + queue->current = NULL; +} + +/* find a range that contains @offset or NULL when nothing does */ +static GstQueue2Range * +find_range (GstQueue2 * queue, guint64 offset) +{ + GstQueue2Range *range = NULL; + GstQueue2Range *walk; + + /* first do a quick check for the current range */ + for (walk = queue->ranges; walk; walk = walk->next) { + if (offset >= walk->offset && offset <= walk->writing_pos) { + /* we can reuse an existing range */ + range = walk; + break; + } + } + if (range) { + GST_DEBUG_OBJECT (queue, + "found range for %" G_GUINT64_FORMAT ": [%" G_GUINT64_FORMAT "-%" + G_GUINT64_FORMAT "]", offset, range->offset, range->writing_pos); + } else { + GST_DEBUG_OBJECT (queue, "no range for %" G_GUINT64_FORMAT, offset); + } + return range; +} + +static void +update_cur_level (GstQueue2 * queue, GstQueue2Range * range) +{ + guint64 max_reading_pos, writing_pos; + + writing_pos = range->writing_pos; + max_reading_pos = range->max_reading_pos; + + if (writing_pos > max_reading_pos) + queue->cur_level.bytes = writing_pos - max_reading_pos; + else + queue->cur_level.bytes = 0; +} + +/* make a new range for @offset or reuse an existing range */ +static GstQueue2Range * +add_range (GstQueue2 * queue, guint64 offset, gboolean update_existing) +{ + GstQueue2Range *range, *prev, *next; + + GST_DEBUG_OBJECT (queue, "find range for %" G_GUINT64_FORMAT, offset); + + if ((range = find_range (queue, offset))) { + GST_DEBUG_OBJECT (queue, + "reusing range %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT, range->offset, + range->writing_pos); + if (update_existing && range->writing_pos != offset) { + GST_DEBUG_OBJECT (queue, "updating range writing position to " + "%" G_GUINT64_FORMAT, offset); + range->writing_pos = offset; + } + } else { + GST_DEBUG_OBJECT (queue, + "new range %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT, offset, offset); + + range = g_slice_new0 (GstQueue2Range); + range->offset = offset; + /* we want to write to the next location in the ring buffer */ + range->rb_offset = queue->current ? queue->current->rb_writing_pos : 0; + range->writing_pos = offset; + range->rb_writing_pos = range->rb_offset; + range->reading_pos = offset; + range->max_reading_pos = offset; + + /* insert sorted */ + prev = NULL; + next = queue->ranges; + while (next) { + if (next->offset > offset) { + /* insert before next */ + GST_DEBUG_OBJECT (queue, + "insert before range %p, offset %" G_GUINT64_FORMAT, next, + next->offset); + break; + } + /* try next */ + prev = next; + next = next->next; + } + range->next = next; + if (prev) + prev->next = range; + else + queue->ranges = range; + } + debug_ranges (queue); + + /* update the stats for this range */ + update_cur_level (queue, range); + + return range; +} + + +/* clear and init the download ranges for offset 0 */ +static void +init_ranges (GstQueue2 * queue) +{ + GST_DEBUG_OBJECT (queue, "init queue ranges"); + + /* get rid of all the current ranges */ + clean_ranges (queue); + /* make a range for offset 0 */ + queue->current = add_range (queue, 0, TRUE); +} + +/* calculate the diff between running time on the sink and src of the queue. + * This is the total amount of time in the queue. */ +static void +update_time_level (GstQueue2 * queue) +{ + if (queue->sink_tainted) { + queue->sinktime = + gst_segment_to_running_time (&queue->sink_segment, GST_FORMAT_TIME, + queue->sink_segment.position); + queue->sink_tainted = FALSE; + } + + if (queue->src_tainted) { + queue->srctime = + gst_segment_to_running_time (&queue->src_segment, GST_FORMAT_TIME, + queue->src_segment.position); + queue->src_tainted = FALSE; + } + + GST_DEBUG_OBJECT (queue, "sink %" GST_TIME_FORMAT ", src %" GST_TIME_FORMAT, + GST_TIME_ARGS (queue->sinktime), GST_TIME_ARGS (queue->srctime)); + + if (queue->sinktime != GST_CLOCK_TIME_NONE + && queue->srctime != GST_CLOCK_TIME_NONE + && queue->sinktime >= queue->srctime) + queue->cur_level.time = queue->sinktime - queue->srctime; + else + queue->cur_level.time = 0; +} + +/* take a SEGMENT event and apply the values to segment, updating the time + * level of queue. */ +static void +apply_segment (GstQueue2 * queue, GstEvent * event, GstSegment * segment, + gboolean is_sink) +{ + gst_event_copy_segment (event, segment); + + if (segment->format == GST_FORMAT_BYTES) { + if (!QUEUE_IS_USING_QUEUE (queue) && is_sink) { + /* start is where we'll be getting from and as such writing next */ + queue->current = add_range (queue, segment->start, TRUE); + } + } + + /* now configure the values, we use these to track timestamps on the + * sinkpad. */ + if (segment->format != GST_FORMAT_TIME) { + /* non-time format, pretend the current time segment is closed with a + * 0 start and unknown stop time. */ + segment->format = GST_FORMAT_TIME; + segment->start = 0; + segment->stop = -1; + segment->time = 0; + } + + GST_DEBUG_OBJECT (queue, "configured SEGMENT %" GST_SEGMENT_FORMAT, segment); + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* segment can update the time level of the queue */ + update_time_level (queue); +} + +static void +apply_gap (GstQueue2 * queue, GstEvent * event, + GstSegment * segment, gboolean is_sink) +{ + GstClockTime timestamp; + GstClockTime duration; + + gst_event_parse_gap (event, ×tamp, &duration); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + timestamp += duration; + } + + segment->position = timestamp; + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); + } +} + +/* take a buffer and update segment, updating the time level of the queue. */ +static void +apply_buffer (GstQueue2 * queue, GstBuffer * buffer, GstSegment * segment, + guint64 size, gboolean is_sink) +{ + GstClockTime duration, timestamp; + + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); + duration = GST_BUFFER_DURATION (buffer); + + /* If we have no duration, pick one from the bitrate if we can */ + if (duration == GST_CLOCK_TIME_NONE && queue->use_tags_bitrate) { + guint bitrate = + is_sink ? queue->sink_tags_bitrate : queue->src_tags_bitrate; + if (bitrate) + duration = gst_util_uint64_scale (size, 8 * GST_SECOND, bitrate); + } + + /* if no timestamp is set, assume it's continuous with the previous + * time */ + if (timestamp == GST_CLOCK_TIME_NONE) + timestamp = segment->position; + + /* add duration */ + if (duration != GST_CLOCK_TIME_NONE) + timestamp += duration; + + GST_DEBUG_OBJECT (queue, "position updated to %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); + + segment->position = timestamp; + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); +} + +struct BufListData +{ + GstClockTime timestamp; + guint bitrate; +}; + +static gboolean +buffer_list_apply_time (GstBuffer ** buf, guint idx, gpointer data) +{ + struct BufListData *bld = data; + GstClockTime *timestamp = &bld->timestamp; + GstClockTime btime; + + GST_TRACE ("buffer %u has pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT, idx, + GST_TIME_ARGS (GST_BUFFER_PTS (*buf)), + GST_TIME_ARGS (GST_BUFFER_DTS (*buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (*buf))); + + btime = GST_BUFFER_DTS_OR_PTS (*buf); + if (GST_CLOCK_TIME_IS_VALID (btime)) + *timestamp = btime; + + if (GST_BUFFER_DURATION_IS_VALID (*buf)) + *timestamp += GST_BUFFER_DURATION (*buf); + else if (bld->bitrate != 0) { + guint64 size = gst_buffer_get_size (*buf); + + /* If we have no duration, pick one from the bitrate if we can */ + *timestamp += gst_util_uint64_scale (bld->bitrate, 8 * GST_SECOND, size); + } + + + GST_TRACE ("ts now %" GST_TIME_FORMAT, GST_TIME_ARGS (*timestamp)); + return TRUE; +} + +/* take a buffer list and update segment, updating the time level of the queue */ +static void +apply_buffer_list (GstQueue2 * queue, GstBufferList * buffer_list, + GstSegment * segment, gboolean is_sink) +{ + struct BufListData bld; + + /* if no timestamp is set, assume it's continuous with the previous time */ + bld.timestamp = segment->position; + + if (queue->use_tags_bitrate) { + if (is_sink) + bld.bitrate = queue->sink_tags_bitrate; + else + bld.bitrate = queue->src_tags_bitrate; + } else + bld.bitrate = 0; + + gst_buffer_list_foreach (buffer_list, buffer_list_apply_time, &bld); + + GST_DEBUG_OBJECT (queue, "last_stop updated to %" GST_TIME_FORMAT, + GST_TIME_ARGS (bld.timestamp)); + + segment->position = bld.timestamp; + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); +} + +static inline gint +normalize_to_buffering_level (guint64 cur_level, guint64 max_level, + guint64 alt_max) +{ + guint64 p; + + if (max_level == 0) + return 0; + + if (alt_max > 0) + p = gst_util_uint64_scale (cur_level, MAX_BUFFERING_LEVEL, + MIN (max_level, alt_max)); + else + p = gst_util_uint64_scale (cur_level, MAX_BUFFERING_LEVEL, max_level); + + return MIN (p, MAX_BUFFERING_LEVEL); +} + +static gboolean +get_buffering_level (GstQueue2 * queue, gboolean * is_buffering, + gint * buffering_level) +{ + gint buflevel, buflevel2; + + if (queue->high_watermark <= 0) { + if (buffering_level) + *buffering_level = MAX_BUFFERING_LEVEL; + if (is_buffering) + *is_buffering = FALSE; + return FALSE; + } +#define GET_BUFFER_LEVEL_FOR_QUANTITY(format,alt_max) \ + normalize_to_buffering_level (queue->cur_level.format,queue->max_level.format,(alt_max)) + + if (queue->is_eos || queue->srcresult == GST_FLOW_NOT_LINKED) { + /* on EOS and NOT_LINKED we are always 100% full, we set the var + * here so that we can reuse the logic below to stop buffering */ + buflevel = MAX_BUFFERING_LEVEL; + GST_LOG_OBJECT (queue, "we are %s", queue->is_eos ? "EOS" : "NOT_LINKED"); + } else { + GST_LOG_OBJECT (queue, + "Cur level bytes/time/buffers %u/%" GST_TIME_FORMAT "/%u", + queue->cur_level.bytes, GST_TIME_ARGS (queue->cur_level.time), + queue->cur_level.buffers); + + /* figure out the buffering level we are filled, we take the max of all formats. */ + if (!QUEUE_IS_USING_RING_BUFFER (queue)) { + buflevel = GET_BUFFER_LEVEL_FOR_QUANTITY (bytes, 0); + } else { + guint64 rb_size = queue->ring_buffer_max_size; + buflevel = GET_BUFFER_LEVEL_FOR_QUANTITY (bytes, rb_size); + } + + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (time, 0); + buflevel = MAX (buflevel, buflevel2); + + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (buffers, 0); + buflevel = MAX (buflevel, buflevel2); + + /* also apply the rate estimate when we need to */ + if (queue->use_rate_estimate) { + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (rate_time, 0); + buflevel = MAX (buflevel, buflevel2); + } + + /* Don't get to 0% unless we're really empty */ + if (queue->cur_level.bytes > 0) + buflevel = MAX (1, buflevel); + } +#undef GET_BUFFER_LEVEL_FOR_QUANTITY + + if (is_buffering) + *is_buffering = queue->is_buffering; + + if (buffering_level) + *buffering_level = buflevel; + + GST_DEBUG_OBJECT (queue, "buffering %d, level %d", queue->is_buffering, + buflevel); + + return TRUE; +} + +static gint +convert_to_buffering_percent (GstQueue2 * queue, gint buffering_level) +{ + int percent; + + /* scale so that if buffering_level equals the high watermark, + * the percentage is 100% */ + percent = buffering_level * 100 / queue->high_watermark; + /* clip */ + if (percent > 100) + percent = 100; + + return percent; +} + +static void +get_buffering_stats (GstQueue2 * queue, gint percent, GstBufferingMode * mode, + gint * avg_in, gint * avg_out, gint64 * buffering_left) +{ + if (mode) { + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (QUEUE_IS_USING_RING_BUFFER (queue)) + *mode = GST_BUFFERING_TIMESHIFT; + else + *mode = GST_BUFFERING_DOWNLOAD; + } else { + *mode = GST_BUFFERING_STREAM; + } + } + + if (avg_in) + *avg_in = queue->byte_in_rate; + if (avg_out) + *avg_out = queue->byte_out_rate; + + if (buffering_left) { + *buffering_left = (percent == 100 ? 0 : -1); + + if (queue->use_rate_estimate) { + guint64 max, cur; + + max = queue->max_level.rate_time; + cur = queue->cur_level.rate_time; + + if (percent != 100 && max > cur) + *buffering_left = (max - cur) / 1000000; + } + } +} + +/* Called with the lock taken */ +static GstMessage * +gst_queue2_get_buffering_message (GstQueue2 * queue) +{ + GstMessage *msg = NULL; + + if (queue->percent_changed) { + gint percent = queue->buffering_percent; + + queue->percent_changed = FALSE; + + GST_DEBUG_OBJECT (queue, "Going to post buffering: %d%%", percent); + msg = gst_message_new_buffering (GST_OBJECT_CAST (queue), percent); + + gst_message_set_buffering_stats (msg, queue->mode, queue->avg_in, + queue->avg_out, queue->buffering_left); + } + + return msg; +} + +static void +gst_queue2_post_buffering (GstQueue2 * queue) +{ + GstMessage *msg = NULL; + + g_mutex_lock (&queue->buffering_post_lock); + GST_QUEUE2_MUTEX_LOCK (queue); + msg = gst_queue2_get_buffering_message (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + if (msg != NULL) + gst_element_post_message (GST_ELEMENT_CAST (queue), msg); + + g_mutex_unlock (&queue->buffering_post_lock); +} + +static void +update_buffering (GstQueue2 * queue) +{ + gint buffering_level, percent; + + /* Ensure the variables used to calculate buffering state are up-to-date. */ + if (queue->current) + update_cur_level (queue, queue->current); + update_in_rates (queue, FALSE); + + if (!get_buffering_level (queue, NULL, &buffering_level)) + return; + + percent = convert_to_buffering_percent (queue, buffering_level); + + if (queue->is_buffering) { + /* if we were buffering see if we reached the high watermark */ + if (percent >= 100) + queue->is_buffering = FALSE; + + SET_PERCENT (queue, percent); + } else { + /* we were not buffering, check if we need to start buffering if we drop + * below the low threshold */ + if (buffering_level < queue->low_watermark) { + queue->is_buffering = TRUE; + SET_PERCENT (queue, percent); + } + } +} + +static void +reset_rate_timer (GstQueue2 * queue) +{ + queue->bytes_in = 0; + queue->bytes_out = 0; + queue->byte_in_rate = 0.0; + queue->byte_in_period = 0; + queue->byte_out_rate = 0.0; + queue->last_update_in_rates_elapsed = 0.0; + queue->last_in_elapsed = 0.0; + queue->last_out_elapsed = 0.0; + queue->in_timer_started = FALSE; + queue->out_timer_started = FALSE; +} + +/* the interval in seconds to recalculate the rate */ +#define RATE_INTERVAL 0.2 +/* Tuning for rate estimation. We use a large window for the input rate because + * it should be stable when connected to a network. The output rate is less + * stable (the elements preroll, queues behind a demuxer fill, ...) and should + * therefore adapt more quickly. + * However, initial input rate may be subject to a burst, and should therefore + * initially also adapt more quickly to changes, and only later on give higher + * weight to previous values. */ +#define AVG_IN(avg,val,w1,w2) ((avg) * (w1) + (val) * (w2)) / ((w1) + (w2)) +#define AVG_OUT(avg,val) ((avg) * 3.0 + (val)) / 4.0 + +static void +update_in_rates (GstQueue2 * queue, gboolean force) +{ + gdouble elapsed, period; + gdouble byte_in_rate; + + if (!queue->in_timer_started) { + queue->in_timer_started = TRUE; + g_timer_start (queue->in_timer); + return; + } + + queue->last_update_in_rates_elapsed = elapsed = + g_timer_elapsed (queue->in_timer, NULL); + + /* recalc after each interval. */ + if (force || queue->last_in_elapsed + RATE_INTERVAL < elapsed) { + period = elapsed - queue->last_in_elapsed; + + GST_DEBUG_OBJECT (queue, + "rates: period %f, in %" G_GUINT64_FORMAT ", global period %f", + period, queue->bytes_in, queue->byte_in_period); + + byte_in_rate = queue->bytes_in / period; + + if (queue->byte_in_rate == 0.0) + queue->byte_in_rate = byte_in_rate; + else + queue->byte_in_rate = AVG_IN (queue->byte_in_rate, byte_in_rate, + (double) queue->byte_in_period, period); + + /* another data point, cap at 16 for long time running average */ + if (queue->byte_in_period < 16 * RATE_INTERVAL) + queue->byte_in_period += period; + + /* reset the values to calculate rate over the next interval */ + queue->last_in_elapsed = elapsed; + queue->bytes_in = 0; + } + + if (queue->byte_in_rate > 0.0) { + queue->cur_level.rate_time = + queue->cur_level.bytes / queue->byte_in_rate * GST_SECOND; + } + GST_DEBUG_OBJECT (queue, "rates: in %f, time %" GST_TIME_FORMAT, + queue->byte_in_rate, GST_TIME_ARGS (queue->cur_level.rate_time)); +} + +static void +update_out_rates (GstQueue2 * queue) +{ + gdouble elapsed, period; + gdouble byte_out_rate; + + if (!queue->out_timer_started) { + queue->out_timer_started = TRUE; + g_timer_start (queue->out_timer); + return; + } + + elapsed = g_timer_elapsed (queue->out_timer, NULL); + + /* recalc after each interval. */ + if (queue->last_out_elapsed + RATE_INTERVAL < elapsed) { + period = elapsed - queue->last_out_elapsed; + + GST_DEBUG_OBJECT (queue, + "rates: period %f, out %" G_GUINT64_FORMAT, period, queue->bytes_out); + + byte_out_rate = queue->bytes_out / period; + + if (queue->byte_out_rate == 0.0) + queue->byte_out_rate = byte_out_rate; + else + queue->byte_out_rate = AVG_OUT (queue->byte_out_rate, byte_out_rate); + + /* reset the values to calculate rate over the next interval */ + queue->last_out_elapsed = elapsed; + queue->bytes_out = 0; + } + if (queue->byte_in_rate > 0.0) { + queue->cur_level.rate_time = + queue->cur_level.bytes / queue->byte_in_rate * GST_SECOND; + } + GST_DEBUG_OBJECT (queue, "rates: out %f, time %" GST_TIME_FORMAT, + queue->byte_out_rate, GST_TIME_ARGS (queue->cur_level.rate_time)); +} + +static void +update_cur_pos (GstQueue2 * queue, GstQueue2Range * range, guint64 pos) +{ + guint64 reading_pos, max_reading_pos; + + reading_pos = pos; + max_reading_pos = range->max_reading_pos; + + max_reading_pos = MAX (max_reading_pos, reading_pos); + + GST_DEBUG_OBJECT (queue, + "updating max_reading_pos from %" G_GUINT64_FORMAT " to %" + G_GUINT64_FORMAT, range->max_reading_pos, max_reading_pos); + range->max_reading_pos = max_reading_pos; + + update_cur_level (queue, range); +} + +static gboolean +perform_seek_to_offset (GstQueue2 * queue, guint64 offset) +{ + GstEvent *event; + gboolean res; + + /* until we receive the FLUSH_STOP from this seek, we skip data */ + queue->seeking = TRUE; + GST_QUEUE2_MUTEX_UNLOCK (queue); + + debug_ranges (queue); + + GST_DEBUG_OBJECT (queue, "Seeking to %" G_GUINT64_FORMAT, offset); + + event = + gst_event_new_seek (1.0, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset, + GST_SEEK_TYPE_NONE, -1); + + res = gst_pad_push_event (queue->sinkpad, event); + GST_QUEUE2_MUTEX_LOCK (queue); + + if (res) { + /* Between us sending the seek event and re-acquiring the lock, the source + * thread might already have pushed data and moved along the range's + * writing_pos beyond the seek offset. In that case we don't want to set + * the writing position back to the requested seek position, as it would + * cause data to be written to the wrong offset in the file or ring buffer. + * We still do the add_range call to switch the current range to the + * requested range, or create one if one doesn't exist yet. */ + queue->current = add_range (queue, offset, FALSE); + } + + return res; +} + +/* get the threshold for when we decide to seek rather than wait */ +static guint64 +get_seek_threshold (GstQueue2 * queue) +{ + guint64 threshold; + + /* FIXME, find a good threshold based on the incoming rate. */ + threshold = 1024 * 512; + + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + threshold = MIN (threshold, + QUEUE_MAX_BYTES (queue) - queue->cur_level.bytes); + } + return threshold; +} + +/* see if there is enough data in the file to read a full buffer */ +static gboolean +gst_queue2_have_data (GstQueue2 * queue, guint64 offset, guint length) +{ + GstQueue2Range *range; + + GST_DEBUG_OBJECT (queue, "looking for offset %" G_GUINT64_FORMAT ", len %u", + offset, length); + + if ((range = find_range (queue, offset))) { + if (queue->current != range) { + GST_DEBUG_OBJECT (queue, "switching ranges, do seek to range position"); + perform_seek_to_offset (queue, range->writing_pos); + } + + GST_INFO_OBJECT (queue, "cur_level.bytes %u (max %" G_GUINT64_FORMAT ")", + queue->cur_level.bytes, QUEUE_MAX_BYTES (queue)); + + /* we have a range for offset */ + GST_DEBUG_OBJECT (queue, + "we have a range %p, offset %" G_GUINT64_FORMAT ", writing_pos %" + G_GUINT64_FORMAT, range, range->offset, range->writing_pos); + + if (!QUEUE_IS_USING_RING_BUFFER (queue) && queue->is_eos) + return TRUE; + + if (offset + length <= range->writing_pos) + return TRUE; + else + GST_DEBUG_OBJECT (queue, + "Need more data (%" G_GUINT64_FORMAT " bytes more)", + (offset + length) - range->writing_pos); + + } else { + GST_INFO_OBJECT (queue, "not found in any range off %" G_GUINT64_FORMAT + " len %u", offset, length); + /* we don't have the range, see how far away we are */ + if (!queue->is_eos && queue->current) { + guint64 threshold = get_seek_threshold (queue); + + if (offset >= queue->current->offset && offset <= + queue->current->writing_pos + threshold) { + GST_INFO_OBJECT (queue, + "requested data is within range, wait for data"); + return FALSE; + } + } + + /* too far away, do a seek */ + perform_seek_to_offset (queue, offset); + } + + return FALSE; +} + +#ifdef HAVE_FSEEKO +#define FSEEK_FILE(file,offset) (fseeko (file, (off_t) offset, SEEK_SET) != 0) +#elif defined (G_OS_UNIX) || defined (G_OS_WIN32) +#define FSEEK_FILE(file,offset) (lseek (fileno (file), (off_t) offset, SEEK_SET) == (off_t) -1) +#else +#define FSEEK_FILE(file,offset) (fseek (file, offset, SEEK_SET) != 0) +#endif + +static GstFlowReturn +gst_queue2_read_data_at_offset (GstQueue2 * queue, guint64 offset, guint length, + guint8 * dst, gint64 * read_return) +{ + guint8 *ring_buffer; + size_t res; + + ring_buffer = queue->ring_buffer; + + if (QUEUE_IS_USING_TEMP_FILE (queue) && FSEEK_FILE (queue->temp_file, offset)) + goto seek_failed; + + /* this should not block */ + GST_LOG_OBJECT (queue, "Reading %d bytes from offset %" G_GUINT64_FORMAT, + length, offset); + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + res = fread (dst, 1, length, queue->temp_file); + } else { + memcpy (dst, ring_buffer + offset, length); + res = length; + } + + GST_LOG_OBJECT (queue, "read %" G_GSIZE_FORMAT " bytes", res); + + if (G_UNLIKELY (res < length)) { + if (!QUEUE_IS_USING_TEMP_FILE (queue)) + goto could_not_read; + /* check for errors or EOF */ + if (ferror (queue->temp_file)) + goto could_not_read; + if (feof (queue->temp_file) && length > 0) + goto eos; + } + + *read_return = res; + + return GST_FLOW_OK; + +seek_failed: + { + GST_ELEMENT_ERROR (queue, RESOURCE, SEEK, (NULL), GST_ERROR_SYSTEM); + return GST_FLOW_ERROR; + } +could_not_read: + { + GST_ELEMENT_ERROR (queue, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + return GST_FLOW_ERROR; + } +eos: + { + GST_DEBUG ("non-regular file hits EOS"); + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, + GstBuffer ** buffer) +{ + GstBuffer *buf; + GstMapInfo info; + guint8 *data; + guint64 file_offset; + guint block_length, remaining, read_length; + guint64 rb_size; + guint64 max_size; + guint64 rpos; + GstFlowReturn ret = GST_FLOW_OK; + + /* allocate the output buffer of the requested size */ + if (*buffer == NULL) + buf = gst_buffer_new_allocate (NULL, length, NULL); + else + buf = *buffer; + + if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) + goto buffer_write_fail; + data = info.data; + + GST_DEBUG_OBJECT (queue, "Reading %u bytes from %" G_GUINT64_FORMAT, length, + offset); + + rpos = offset; + rb_size = queue->ring_buffer_max_size; + max_size = QUEUE_MAX_BYTES (queue); + + remaining = length; + while (remaining > 0) { + /* configure how much/whether to read */ + if (!gst_queue2_have_data (queue, rpos, remaining)) { + read_length = 0; + + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + guint64 level; + + /* calculate how far away the offset is */ + if (queue->current->writing_pos > rpos) + level = queue->current->writing_pos - rpos; + else + level = 0; + + GST_DEBUG_OBJECT (queue, + "reading %" G_GUINT64_FORMAT ", writing %" G_GUINT64_FORMAT + ", level %" G_GUINT64_FORMAT ", max %" G_GUINT64_FORMAT, + rpos, queue->current->writing_pos, level, max_size); + + if (level >= max_size) { + /* we don't have the data but if we have a ring buffer that is full, we + * need to read */ + GST_DEBUG_OBJECT (queue, + "ring buffer full, reading QUEUE_MAX_BYTES %" + G_GUINT64_FORMAT " bytes", max_size); + read_length = max_size; + } else if (queue->is_eos) { + /* won't get any more data so read any data we have */ + if (level) { + GST_DEBUG_OBJECT (queue, + "EOS hit but read %" G_GUINT64_FORMAT " bytes that we have", + level); + read_length = level; + remaining = level; + length = level; + } else + goto hit_eos; + } + } + + if (read_length == 0) { + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + GST_DEBUG_OBJECT (queue, + "update current position [%" G_GUINT64_FORMAT "-%" + G_GUINT64_FORMAT "]", rpos, queue->current->max_reading_pos); + update_cur_pos (queue, queue->current, rpos); + GST_QUEUE2_SIGNAL_DEL (queue); + } + + if (queue->use_buffering) + update_buffering (queue); + + GST_DEBUG_OBJECT (queue, "waiting for add"); + GST_QUEUE2_WAIT_ADD_CHECK (queue, queue->srcresult, out_flushing); + continue; + } + } else { + /* we have the requested data so read it */ + read_length = remaining; + } + + /* set range reading_pos to actual reading position for this read */ + queue->current->reading_pos = rpos; + + /* configure how much and from where to read */ + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + file_offset = + (queue->current->rb_offset + (rpos - + queue->current->offset)) % rb_size; + if (file_offset + read_length > rb_size) { + block_length = rb_size - file_offset; + } else { + block_length = read_length; + } + } else { + file_offset = rpos; + block_length = read_length; + } + + /* while we still have data to read, we loop */ + while (read_length > 0) { + gint64 read_return; + + ret = + gst_queue2_read_data_at_offset (queue, file_offset, block_length, + data, &read_return); + if (ret != GST_FLOW_OK) + goto read_error; + + file_offset += read_return; + if (QUEUE_IS_USING_RING_BUFFER (queue)) + file_offset %= rb_size; + + data += read_return; + read_length -= read_return; + block_length = read_length; + remaining -= read_return; + + rpos = (queue->current->reading_pos += read_return); + update_cur_pos (queue, queue->current, queue->current->reading_pos); + } + GST_QUEUE2_SIGNAL_DEL (queue); + GST_DEBUG_OBJECT (queue, "%u bytes left to read", remaining); + } + + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, length); + + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + length; + + *buffer = buf; + + return ret; + + /* ERRORS */ +hit_eos: + { + GST_DEBUG_OBJECT (queue, "EOS hit and we don't have any requested data"); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_EOS; + } +out_flushing: + { + GST_DEBUG_OBJECT (queue, "we are flushing"); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_FLUSHING; + } +read_error: + { + GST_DEBUG_OBJECT (queue, "we have a read error"); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return ret; + } +buffer_write_fail: + { + GST_ELEMENT_ERROR (queue, RESOURCE, WRITE, (NULL), + ("Can't write to buffer")); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +/* should be called with QUEUE_LOCK */ +static GstMiniObject * +gst_queue2_read_item_from_file (GstQueue2 * queue) +{ + GstMiniObject *item; + + if (queue->stream_start_event != NULL) { + item = GST_MINI_OBJECT_CAST (queue->stream_start_event); + queue->stream_start_event = NULL; + } else if (queue->starting_segment != NULL) { + item = GST_MINI_OBJECT_CAST (queue->starting_segment); + queue->starting_segment = NULL; + } else { + GstFlowReturn ret; + GstBuffer *buffer = NULL; + guint64 reading_pos; + + reading_pos = queue->current->reading_pos; + + ret = + gst_queue2_create_read (queue, reading_pos, DEFAULT_BUFFER_SIZE, + &buffer); + + switch (ret) { + case GST_FLOW_OK: + item = GST_MINI_OBJECT_CAST (buffer); + break; + case GST_FLOW_EOS: + item = GST_MINI_OBJECT_CAST (gst_event_new_eos ()); + break; + default: + item = NULL; + break; + } + } + return item; +} + +/* must be called with MUTEX_LOCK. Will briefly release the lock when notifying + * the temp filename. */ +static gboolean +gst_queue2_open_temp_location_file (GstQueue2 * queue) +{ + gint fd = -1; + gchar *name = NULL; + + if (queue->temp_file) + goto already_opened; + + GST_DEBUG_OBJECT (queue, "opening temp file %s", queue->temp_template); + + /* If temp_template was set, allocate a filename and open that file */ + + /* nothing to do */ + if (queue->temp_template == NULL) + goto no_directory; + + /* make copy of the template, we don't want to change this */ + name = g_strdup (queue->temp_template); + +#ifdef __BIONIC__ + fd = g_mkstemp_full (name, O_RDWR | O_LARGEFILE, S_IRUSR | S_IWUSR); +#else + fd = g_mkstemp (name); +#endif + + if (fd == -1) + goto mkstemp_failed; + + /* open the file for update/writing */ + queue->temp_file = fdopen (fd, "wb+"); + /* error creating file */ + if (queue->temp_file == NULL) + goto open_failed; + + g_free (queue->temp_location); + queue->temp_location = name; + + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* we can't emit the notify with the lock */ + g_object_notify (G_OBJECT (queue), "temp-location"); + + GST_QUEUE2_MUTEX_LOCK (queue); + + GST_DEBUG_OBJECT (queue, "opened temp file %s", queue->temp_template); + + return TRUE; + + /* ERRORS */ +already_opened: + { + GST_DEBUG_OBJECT (queue, "temp file was already open"); + return TRUE; + } +no_directory: + { + GST_ELEMENT_ERROR (queue, RESOURCE, NOT_FOUND, + (_("No Temp directory specified.")), (NULL)); + return FALSE; + } +mkstemp_failed: + { + GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ, + (_("Could not create temp file \"%s\"."), queue->temp_template), + GST_ERROR_SYSTEM); + g_free (name); + return FALSE; + } +open_failed: + { + GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ, + (_("Could not open file \"%s\" for reading."), name), GST_ERROR_SYSTEM); + g_free (name); + if (fd != -1) + close (fd); + return FALSE; + } +} + +static void +gst_queue2_close_temp_location_file (GstQueue2 * queue) +{ + /* nothing to do */ + if (queue->temp_file == NULL) + return; + + GST_DEBUG_OBJECT (queue, "closing temp file"); + + fflush (queue->temp_file); + fclose (queue->temp_file); + + if (queue->temp_remove) { + if (remove (queue->temp_location) < 0) { + GST_WARNING_OBJECT (queue, "Failed to remove temporary file %s: %s", + queue->temp_location, g_strerror (errno)); + } + } + + queue->temp_file = NULL; + clean_ranges (queue); +} + +static void +gst_queue2_flush_temp_file (GstQueue2 * queue) +{ + if (queue->temp_file == NULL) + return; + + GST_DEBUG_OBJECT (queue, "flushing temp file"); + + queue->temp_file = g_freopen (queue->temp_location, "wb+", queue->temp_file); +} + +static void +gst_queue2_locked_flush (GstQueue2 * queue, gboolean full, gboolean clear_temp) +{ + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (QUEUE_IS_USING_TEMP_FILE (queue) && clear_temp) + gst_queue2_flush_temp_file (queue); + init_ranges (queue); + } else { + while (!g_queue_is_empty (&queue->queue)) { + GstQueue2Item *qitem = g_queue_pop_head (&queue->queue); + + if (!full && qitem->type == GST_QUEUE2_ITEM_TYPE_EVENT + && GST_EVENT_IS_STICKY (qitem->item) + && GST_EVENT_TYPE (qitem->item) != GST_EVENT_SEGMENT + && GST_EVENT_TYPE (qitem->item) != GST_EVENT_EOS) { + gst_pad_store_sticky_event (queue->srcpad, + GST_EVENT_CAST (qitem->item)); + } + + /* Then lose another reference because we are supposed to destroy that + data when flushing */ + if (qitem->type != GST_QUEUE2_ITEM_TYPE_QUERY) + gst_mini_object_unref (qitem->item); + g_slice_free (GstQueue2Item, qitem); + } + } + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE2_CLEAR_LEVEL (queue->cur_level); + gst_segment_init (&queue->sink_segment, GST_FORMAT_TIME); + gst_segment_init (&queue->src_segment, GST_FORMAT_TIME); + queue->sinktime = queue->srctime = GST_CLOCK_TIME_NONE; + queue->sink_tainted = queue->src_tainted = TRUE; + if (queue->starting_segment != NULL) + gst_event_unref (queue->starting_segment); + queue->starting_segment = NULL; + queue->segment_event_received = FALSE; + gst_event_replace (&queue->stream_start_event, NULL); + + /* we deleted a lot of something */ + GST_QUEUE2_SIGNAL_DEL (queue); +} + +static gboolean +gst_queue2_wait_free_space (GstQueue2 * queue) +{ + /* We make space available if we're "full" according to whatever + * the user defined as "full". */ + if (gst_queue2_is_filled (queue)) { + gboolean started; + + /* pause the timer while we wait. The fact that we are waiting does not mean + * the byterate on the input pad is lower */ + if ((started = queue->in_timer_started)) + g_timer_stop (queue->in_timer); + + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "queue is full, waiting for free space"); + do { + /* Wait for space to be available, we could be unlocked because of a flush. */ + GST_QUEUE2_WAIT_DEL_CHECK (queue, queue->sinkresult, out_flushing); + } + while (gst_queue2_is_filled (queue)); + + /* and continue if we were running before */ + if (started) + g_timer_continue (queue->in_timer); + } + return TRUE; + + /* ERRORS */ +out_flushing: + { + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is flushing"); + return FALSE; + } +} + +static gboolean +gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) +{ + GstMapInfo info; + guint8 *data, *ring_buffer; + guint size, rb_size; + guint64 writing_pos, new_writing_pos; + GstQueue2Range *range, *prev, *next; + gboolean do_seek = FALSE; + + if (QUEUE_IS_USING_RING_BUFFER (queue)) + writing_pos = queue->current->rb_writing_pos; + else + writing_pos = queue->current->writing_pos; + ring_buffer = queue->ring_buffer; + rb_size = queue->ring_buffer_max_size; + + if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) + goto buffer_read_error; + + size = info.size; + data = info.data; + + GST_DEBUG_OBJECT (queue, "Writing %u bytes to %" G_GUINT64_FORMAT, size, + writing_pos); + + /* sanity check */ + if (GST_BUFFER_OFFSET_IS_VALID (buffer) && + GST_BUFFER_OFFSET (buffer) != queue->current->writing_pos) { + GST_WARNING_OBJECT (queue, "buffer offset does not match current writing " + "position! %" G_GINT64_FORMAT " != %" G_GINT64_FORMAT, + GST_BUFFER_OFFSET (buffer), queue->current->writing_pos); + } + + while (size > 0) { + guint to_write; + + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + gint64 space; + + /* calculate the space in the ring buffer not used by data from + * the current range */ + while (QUEUE_MAX_BYTES (queue) <= queue->cur_level.bytes) { + /* wait until there is some free space */ + GST_QUEUE2_WAIT_DEL_CHECK (queue, queue->sinkresult, out_flushing); + } + /* get the amount of space we have */ + space = QUEUE_MAX_BYTES (queue) - queue->cur_level.bytes; + + /* calculate if we need to split or if we can write the entire + * buffer now */ + to_write = MIN (size, space); + + /* the writing position in the ring buffer after writing (part + * or all of) the buffer */ + new_writing_pos = (writing_pos + to_write) % rb_size; + + prev = NULL; + range = queue->ranges; + + /* if we need to overwrite data in the ring buffer, we need to + * update the ranges + * + * warning: this code is complicated and includes some + * simplifications - pen, paper and diagrams for the cases + * recommended! */ + while (range) { + guint64 range_data_start, range_data_end; + GstQueue2Range *range_to_destroy = NULL; + + if (range == queue->current) + goto next_range; + + range_data_start = range->rb_offset; + range_data_end = range->rb_writing_pos; + + /* handle the special case where the range has no data in it */ + if (range->writing_pos == range->offset) { + if (range != queue->current) { + GST_DEBUG_OBJECT (queue, + "Removing range: offset %" G_GUINT64_FORMAT ", wpos %" + G_GUINT64_FORMAT, range->offset, range->writing_pos); + /* remove range */ + range_to_destroy = range; + if (prev) + prev->next = range->next; + } + goto next_range; + } + + if (range_data_end > range_data_start) { + if (writing_pos >= range_data_end && new_writing_pos >= writing_pos) + goto next_range; + + if (new_writing_pos > range_data_start) { + if (new_writing_pos >= range_data_end) { + GST_DEBUG_OBJECT (queue, + "Removing range: offset %" G_GUINT64_FORMAT ", wpos %" + G_GUINT64_FORMAT, range->offset, range->writing_pos); + /* remove range */ + range_to_destroy = range; + if (prev) + prev->next = range->next; + } else { + GST_DEBUG_OBJECT (queue, + "advancing offsets from %" G_GUINT64_FORMAT " (%" + G_GUINT64_FORMAT ") to %" G_GUINT64_FORMAT " (%" + G_GUINT64_FORMAT ")", range->offset, range->rb_offset, + range->offset + new_writing_pos - range_data_start, + new_writing_pos); + range->offset += (new_writing_pos - range_data_start); + range->rb_offset = new_writing_pos; + } + } + } else { + guint64 new_wpos_virt = writing_pos + to_write; + + if (new_wpos_virt <= range_data_start) + goto next_range; + + if (new_wpos_virt > rb_size && new_writing_pos >= range_data_end) { + GST_DEBUG_OBJECT (queue, + "Removing range: offset %" G_GUINT64_FORMAT ", wpos %" + G_GUINT64_FORMAT, range->offset, range->writing_pos); + /* remove range */ + range_to_destroy = range; + if (prev) + prev->next = range->next; + } else { + GST_DEBUG_OBJECT (queue, + "advancing offsets from %" G_GUINT64_FORMAT " (%" + G_GUINT64_FORMAT ") to %" G_GUINT64_FORMAT " (%" + G_GUINT64_FORMAT ")", range->offset, range->rb_offset, + range->offset + new_writing_pos - range_data_start, + new_writing_pos); + range->offset += (new_wpos_virt - range_data_start); + range->rb_offset = new_writing_pos; + } + } + + next_range: + if (!range_to_destroy) + prev = range; + + range = range->next; + if (range_to_destroy) { + if (range_to_destroy == queue->ranges) + queue->ranges = range; + g_slice_free (GstQueue2Range, range_to_destroy); + range_to_destroy = NULL; + } + } + } else { + to_write = size; + new_writing_pos = writing_pos + to_write; + } + + if (QUEUE_IS_USING_TEMP_FILE (queue) + && FSEEK_FILE (queue->temp_file, writing_pos)) + goto seek_failed; + + if (new_writing_pos > writing_pos) { + GST_INFO_OBJECT (queue, + "writing %u bytes to range [%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT + "] (rb wpos %" G_GUINT64_FORMAT ")", to_write, queue->current->offset, + queue->current->writing_pos, queue->current->rb_writing_pos); + /* either not using ring buffer or no wrapping, just write */ + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + if (fwrite (data, to_write, 1, queue->temp_file) != 1) + goto handle_error; + } else { + memcpy (ring_buffer + writing_pos, data, to_write); + } + + if (!QUEUE_IS_USING_RING_BUFFER (queue)) { + /* try to merge with next range */ + while ((next = queue->current->next)) { + GST_INFO_OBJECT (queue, + "checking merge with next range %" G_GUINT64_FORMAT " < %" + G_GUINT64_FORMAT, new_writing_pos, next->offset); + if (new_writing_pos < next->offset) + break; + + GST_DEBUG_OBJECT (queue, "merging ranges %" G_GUINT64_FORMAT, + next->writing_pos); + + /* remove the group */ + queue->current->next = next->next; + + /* We use the threshold to decide if we want to do a seek or simply + * read the data again. If there is not so much data in the range we + * prefer to avoid to seek and read it again. */ + if (next->writing_pos > new_writing_pos + get_seek_threshold (queue)) { + /* the new range had more data than the threshold, it's worth keeping + * it and doing a seek. */ + new_writing_pos = next->writing_pos; + do_seek = TRUE; + } + g_slice_free (GstQueue2Range, next); + } + goto update_and_signal; + } + } else { + /* wrapping */ + guint block_one, block_two; + + block_one = rb_size - writing_pos; + block_two = to_write - block_one; + + if (block_one > 0) { + GST_INFO_OBJECT (queue, "writing %u bytes", block_one); + /* write data to end of ring buffer */ + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + if (fwrite (data, block_one, 1, queue->temp_file) != 1) + goto handle_error; + } else { + memcpy (ring_buffer + writing_pos, data, block_one); + } + } + + if (QUEUE_IS_USING_TEMP_FILE (queue) && FSEEK_FILE (queue->temp_file, 0)) + goto seek_failed; + + if (block_two > 0) { + GST_INFO_OBJECT (queue, "writing %u bytes", block_two); + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + if (fwrite (data + block_one, block_two, 1, queue->temp_file) != 1) + goto handle_error; + } else { + memcpy (ring_buffer, data + block_one, block_two); + } + } + } + + update_and_signal: + /* update the writing positions */ + size -= to_write; + GST_INFO_OBJECT (queue, + "wrote %u bytes to %" G_GUINT64_FORMAT " (%u bytes remaining to write)", + to_write, writing_pos, size); + + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + data += to_write; + queue->current->writing_pos += to_write; + queue->current->rb_writing_pos = writing_pos = new_writing_pos; + } else { + queue->current->writing_pos = writing_pos = new_writing_pos; + } + if (do_seek) + perform_seek_to_offset (queue, new_writing_pos); + + update_cur_level (queue, queue->current); + + /* update the buffering status */ + if (queue->use_buffering) { + GstMessage *msg; + update_buffering (queue); + msg = gst_queue2_get_buffering_message (queue); + if (msg) { + GST_QUEUE2_MUTEX_UNLOCK (queue); + g_mutex_lock (&queue->buffering_post_lock); + gst_element_post_message (GST_ELEMENT_CAST (queue), msg); + g_mutex_unlock (&queue->buffering_post_lock); + GST_QUEUE2_MUTEX_LOCK (queue); + } + } + + GST_INFO_OBJECT (queue, "cur_level.bytes %u (max %" G_GUINT64_FORMAT ")", + queue->cur_level.bytes, QUEUE_MAX_BYTES (queue)); + + GST_QUEUE2_SIGNAL_ADD (queue); + } + + gst_buffer_unmap (buffer, &info); + + return TRUE; + + /* ERRORS */ +out_flushing: + { + GST_DEBUG_OBJECT (queue, "we are flushing"); + gst_buffer_unmap (buffer, &info); + /* FIXME - GST_FLOW_EOS ? */ + return FALSE; + } +seek_failed: + { + GST_ELEMENT_ERROR (queue, RESOURCE, SEEK, (NULL), GST_ERROR_SYSTEM); + gst_buffer_unmap (buffer, &info); + return FALSE; + } +handle_error: + { + switch (errno) { + case ENOSPC:{ + GST_ELEMENT_ERROR (queue, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL)); + break; + } + default:{ + GST_ELEMENT_ERROR (queue, RESOURCE, WRITE, + (_("Error while writing to download file.")), + ("%s", g_strerror (errno))); + } + } + gst_buffer_unmap (buffer, &info); + return FALSE; + } +buffer_read_error: + { + GST_ELEMENT_ERROR (queue, RESOURCE, READ, (NULL), + ("Can't read from buffer")); + return FALSE; + } +} + +static gboolean +buffer_list_create_write (GstBuffer ** buf, guint idx, gpointer q) +{ + GstQueue2 *queue = q; + + GST_TRACE_OBJECT (queue, + "writing buffer %u of size %" G_GSIZE_FORMAT " bytes", idx, + gst_buffer_get_size (*buf)); + + if (!gst_queue2_create_write (queue, *buf)) { + GST_INFO_OBJECT (queue, "create_write() returned FALSE, bailing out"); + return FALSE; + } + return TRUE; +} + +/* enqueue an item an update the level stats */ +static void +gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, + GstQueue2ItemType item_type) +{ + if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { + GstBuffer *buffer; + guint size; + + buffer = GST_BUFFER_CAST (item); + size = gst_buffer_get_size (buffer); + + /* add buffer to the statistics */ + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers++; + queue->cur_level.bytes += size; + } + queue->bytes_in += size; + + /* apply new buffer to segment stats */ + apply_buffer (queue, buffer, &queue->sink_segment, size, TRUE); + /* update the byterate stats */ + update_in_rates (queue, FALSE); + + if (!QUEUE_IS_USING_QUEUE (queue)) { + /* FIXME - check return value? */ + gst_queue2_create_write (queue, buffer); + } + } else if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GstBufferList *buffer_list; + guint size; + + buffer_list = GST_BUFFER_LIST_CAST (item); + + size = gst_buffer_list_calculate_size (buffer_list); + GST_LOG_OBJECT (queue, "total size of buffer list: %u bytes", size); + + /* add buffer to the statistics */ + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers += gst_buffer_list_length (buffer_list); + queue->cur_level.bytes += size; + } + queue->bytes_in += size; + + /* apply new buffer to segment stats */ + apply_buffer_list (queue, buffer_list, &queue->sink_segment, TRUE); + + /* update the byterate stats */ + update_in_rates (queue, FALSE); + + if (!QUEUE_IS_USING_QUEUE (queue)) { + gst_buffer_list_foreach (buffer_list, buffer_list_create_write, queue); + } + } else if (item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { + GstEvent *event; + + event = GST_EVENT_CAST (item); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* Zero the thresholds, this makes sure the queue is completely + * filled and we can read all data from the queue. */ + GST_DEBUG_OBJECT (queue, "we have EOS"); + queue->is_eos = TRUE; + /* Force updating the input bitrate */ + update_in_rates (queue, TRUE); + break; + case GST_EVENT_SEGMENT: + apply_segment (queue, event, &queue->sink_segment, TRUE); + /* This is our first new segment, we hold it + * as we can't save it on the temp file */ + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (queue->segment_event_received) + goto unexpected_event; + + queue->segment_event_received = TRUE; + if (queue->starting_segment != NULL) + gst_event_unref (queue->starting_segment); + queue->starting_segment = event; + item = NULL; + } + /* a new segment allows us to accept more buffers if we got EOS + * from downstream */ + queue->unexpected = FALSE; + break; + case GST_EVENT_GAP: + apply_gap (queue, event, &queue->sink_segment, TRUE); + break; + case GST_EVENT_STREAM_START: + if (!QUEUE_IS_USING_QUEUE (queue)) { + gst_event_replace (&queue->stream_start_event, event); + gst_event_unref (event); + item = NULL; + } + break; + case GST_EVENT_CAPS:{ + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + GST_INFO ("got caps: %" GST_PTR_FORMAT, caps); + + if (!QUEUE_IS_USING_QUEUE (queue)) { + GST_LOG ("Dropping caps event, not using queue"); + gst_event_unref (event); + item = NULL; + } + break; + } + default: + if (!QUEUE_IS_USING_QUEUE (queue)) + goto unexpected_event; + break; + } + } else if (GST_IS_QUERY (item)) { + /* Can't happen as we check that in the caller */ + if (!QUEUE_IS_USING_QUEUE (queue)) + g_assert_not_reached (); + } else { + g_warning ("Unexpected item %p added in queue %s (refcounting problem?)", + item, GST_OBJECT_NAME (queue)); + /* we can't really unref since we don't know what it is */ + item = NULL; + } + + if (item) { + /* update the buffering status */ + if (queue->use_buffering) + update_buffering (queue); + + if (QUEUE_IS_USING_QUEUE (queue)) { + GstQueue2Item *qitem = g_slice_new (GstQueue2Item); + qitem->type = item_type; + qitem->item = item; + g_queue_push_tail (&queue->queue, qitem); + } else { + gst_mini_object_unref (GST_MINI_OBJECT_CAST (item)); + } + + GST_QUEUE2_SIGNAL_ADD (queue); + } + + return; + + /* ERRORS */ +unexpected_event: + { + gboolean is_custom = GST_EVENT_TYPE (item) < GST_EVENT_CUSTOM_UPSTREAM; + + GST_WARNING_OBJECT (queue, "%s%s event can't be added to temp file: " + "%" GST_PTR_FORMAT, is_custom ? "Unexpected " : "", + GST_EVENT_TYPE_NAME (item), GST_EVENT_CAST (item)); + gst_event_unref (GST_EVENT_CAST (item)); + return; + } +} + +/* dequeue an item from the queue and update level stats */ +static GstMiniObject * +gst_queue2_locked_dequeue (GstQueue2 * queue, GstQueue2ItemType * item_type) +{ + GstMiniObject *item; + + if (!QUEUE_IS_USING_QUEUE (queue)) { + item = gst_queue2_read_item_from_file (queue); + } else { + GstQueue2Item *qitem = g_queue_pop_head (&queue->queue); + + if (qitem == NULL) + goto no_item; + + item = qitem->item; + g_slice_free (GstQueue2Item, qitem); + } + + if (item == NULL) + goto no_item; + + if (GST_IS_BUFFER (item)) { + GstBuffer *buffer; + guint size; + + buffer = GST_BUFFER_CAST (item); + size = gst_buffer_get_size (buffer); + *item_type = GST_QUEUE2_ITEM_TYPE_BUFFER; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved buffer %p from queue", buffer); + + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers--; + queue->cur_level.bytes -= size; + } + queue->bytes_out += size; + + apply_buffer (queue, buffer, &queue->src_segment, size, FALSE); + /* update the byterate stats */ + update_out_rates (queue); + /* update the buffering */ + if (queue->use_buffering) + update_buffering (queue); + + } else if (GST_IS_EVENT (item)) { + GstEvent *event = GST_EVENT_CAST (item); + + *item_type = GST_QUEUE2_ITEM_TYPE_EVENT; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved event %p from queue", event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* queue is empty now that we dequeued the EOS */ + GST_QUEUE2_CLEAR_LEVEL (queue->cur_level); + break; + case GST_EVENT_SEGMENT: + apply_segment (queue, event, &queue->src_segment, FALSE); + break; + case GST_EVENT_GAP: + apply_gap (queue, event, &queue->src_segment, FALSE); + break; + default: + break; + } + } else if (GST_IS_BUFFER_LIST (item)) { + GstBufferList *buffer_list; + guint size; + + buffer_list = GST_BUFFER_LIST_CAST (item); + size = gst_buffer_list_calculate_size (buffer_list); + *item_type = GST_QUEUE2_ITEM_TYPE_BUFFER_LIST; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved buffer list %p from queue", buffer_list); + + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers -= gst_buffer_list_length (buffer_list); + queue->cur_level.bytes -= size; + } + queue->bytes_out += size; + + apply_buffer_list (queue, buffer_list, &queue->src_segment, FALSE); + /* update the byterate stats */ + update_out_rates (queue); + /* update the buffering */ + if (queue->use_buffering) + update_buffering (queue); + } else if (GST_IS_QUERY (item)) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved query %p from queue", item); + *item_type = GST_QUEUE2_ITEM_TYPE_QUERY; + } else { + g_warning + ("Unexpected item %p dequeued from queue %s (refcounting problem?)", + item, GST_OBJECT_NAME (queue)); + item = NULL; + *item_type = GST_QUEUE2_ITEM_TYPE_UNKNOWN; + } + GST_QUEUE2_SIGNAL_DEL (queue); + + return item; + + /* ERRORS */ +no_item: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "the queue is empty"); + return NULL; + } +} + +static GstFlowReturn +gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + gboolean ret = TRUE; + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "Received event '%s'", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + { + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { + /* forward event */ + ret = gst_pad_push_event (queue->srcpad, event); + + /* now unblock the chain function */ + GST_QUEUE2_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + /* unblock the loop and chain functions */ + GST_QUEUE2_SIGNAL_ADD (queue); + GST_QUEUE2_SIGNAL_DEL (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* make sure it pauses, this should happen since we sent + * flush_start downstream. */ + gst_pad_pause_task (queue->srcpad); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped"); + + GST_QUEUE2_MUTEX_LOCK (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + GST_QUEUE2_MUTEX_LOCK (queue); + /* flush the sink pad */ + queue->sinkresult = GST_FLOW_FLUSHING; + GST_QUEUE2_SIGNAL_DEL (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + gst_event_unref (event); + } + break; + } + case GST_EVENT_FLUSH_STOP: + { + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { + /* forward event */ + ret = gst_pad_push_event (queue->srcpad, event); + + GST_QUEUE2_MUTEX_LOCK (queue); + gst_queue2_locked_flush (queue, FALSE, TRUE); + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + queue->seeking = FALSE; + queue->src_tags_bitrate = queue->sink_tags_bitrate = 0; + /* reset rate counters */ + reset_rate_timer (queue); + gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue2_loop, + queue->srcpad, NULL); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + GST_QUEUE2_MUTEX_LOCK (queue); + queue->segment_event_received = FALSE; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + queue->sinkresult = GST_FLOW_OK; + queue->seeking = FALSE; + queue->src_tags_bitrate = queue->sink_tags_bitrate = 0; + GST_QUEUE2_MUTEX_UNLOCK (queue); + + gst_event_unref (event); + } + break; + } + case GST_EVENT_TAG:{ + if (queue->use_tags_bitrate) { + GstTagList *tags; + guint bitrate; + + gst_event_parse_tag (event, &tags); + if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &bitrate) || + gst_tag_list_get_uint (tags, GST_TAG_NOMINAL_BITRATE, &bitrate)) { + GST_QUEUE2_MUTEX_LOCK (queue); + queue->sink_tags_bitrate = bitrate; + GST_QUEUE2_MUTEX_UNLOCK (queue); + GST_LOG_OBJECT (queue, "Sink pad bitrate from tags now %u", bitrate); + } + } + /* Fall-through */ + } + default: + if (GST_EVENT_IS_SERIALIZED (event)) { + /* serialized events go in the queue */ + + /* STREAM_START and SEGMENT reset the EOS status of a + * pad. Change the cached sinkpad flow result accordingly */ + if (queue->sinkresult == GST_FLOW_EOS + && (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START + || GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) + queue->sinkresult = GST_FLOW_OK; + + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing); + if (queue->srcresult != GST_FLOW_OK) { + /* Errors in sticky event pushing are no problem and ignored here + * as they will cause more meaningful errors during data flow. + * For EOS events, that are not followed by data flow, we still + * return FALSE here though and report an error. + */ + if (!GST_EVENT_IS_STICKY (event)) { + goto out_flow_error; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + if (queue->srcresult == GST_FLOW_NOT_LINKED + || queue->srcresult < GST_FLOW_EOS) { + GST_ELEMENT_FLOW_ERROR (queue, queue->srcresult); + } + goto out_flow_error; + } + } + + /* refuse more events on EOS unless they unset the EOS status */ + if (queue->is_eos) { + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + case GST_EVENT_SEGMENT: + /* Restart the loop */ + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { + queue->srcresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + queue->seeking = FALSE; + queue->src_tags_bitrate = queue->sink_tags_bitrate = 0; + /* reset rate counters */ + reset_rate_timer (queue); + gst_pad_start_task (queue->srcpad, + (GstTaskFunction) gst_queue2_loop, queue->srcpad, NULL); + } else { + queue->is_eos = FALSE; + queue->unexpected = FALSE; + queue->seeking = FALSE; + queue->src_tags_bitrate = queue->sink_tags_bitrate = 0; + } + + break; + default: + goto out_eos; + } + } + + gst_queue2_locked_enqueue (queue, event, GST_QUEUE2_ITEM_TYPE_EVENT); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + } else { + /* non-serialized events are passed downstream. */ + ret = gst_pad_push_event (queue->srcpad, event); + } + break; + } + if (ret == FALSE) + return GST_FLOW_ERROR; + return GST_FLOW_OK; + + /* ERRORS */ +out_flushing: + { + GstFlowReturn ret = queue->sinkresult; + GST_DEBUG_OBJECT (queue, "refusing event, we are %s", + gst_flow_get_name (ret)); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_event_unref (event); + return ret; + } +out_eos: + { + GST_DEBUG_OBJECT (queue, "refusing event, we are EOS"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_event_unref (event); + return GST_FLOW_EOS; + } +out_flow_error: + { + GST_LOG_OBJECT (queue, + "refusing event, we have a downstream flow error: %s", + gst_flow_get_name (queue->srcresult)); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_event_unref (event); + return queue->srcresult; + } +} + +static gboolean +gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstQueue2 *queue; + gboolean res; + + queue = GST_QUEUE2 (parent); + + switch (GST_QUERY_TYPE (query)) { + default: + if (GST_QUERY_IS_SERIALIZED (query)) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received query %p", query); + /* serialized events go in the queue. We need to be certain that we + * don't cause deadlocks waiting for the query return value. We check if + * the queue is empty (nothing is blocking downstream and the query can + * be pushed for sure) or we are not buffering. If we are buffering, + * the pipeline waits to unblock downstream until our queue fills up + * completely, which can not happen if we block on the query.. + * Therefore we only potentially block when we are not buffering. */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing); + if (QUEUE_IS_USING_QUEUE (queue) && (gst_queue2_is_empty (queue) + || !queue->use_buffering)) { + if (!g_atomic_int_get (&queue->downstream_may_block)) { + gst_queue2_locked_enqueue (queue, query, + GST_QUEUE2_ITEM_TYPE_QUERY); + + STATUS (queue, queue->sinkpad, "wait for QUERY"); + while (queue->sinkresult == GST_FLOW_OK && + queue->last_handled_query != query) + g_cond_wait (&queue->query_handled, &queue->qlock); + queue->last_handled_query = NULL; + if (queue->sinkresult != GST_FLOW_OK) + goto out_flushing; + res = queue->last_query; + } else { + GST_DEBUG_OBJECT (queue, "refusing query, downstream might block"); + res = FALSE; + } + } else { + GST_DEBUG_OBJECT (queue, + "refusing query, we are not using the queue"); + res = FALSE; + } + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + } else { + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; + + /* ERRORS */ +out_flushing: + { + GST_DEBUG_OBJECT (queue, "refusing query, we are %s", + gst_flow_get_name (queue->sinkresult)); + GST_QUEUE2_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +static gboolean +gst_queue2_is_empty (GstQueue2 * queue) +{ + /* never empty on EOS */ + if (queue->is_eos) + return FALSE; + + if (!QUEUE_IS_USING_QUEUE (queue) && queue->current) { + return queue->current->writing_pos <= queue->current->max_reading_pos; + } else { + if (queue->queue.length == 0) + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_queue2_is_filled (GstQueue2 * queue) +{ + gboolean res; + + /* always filled on EOS */ + if (queue->is_eos) + return TRUE; + +#define CHECK_FILLED(format,alt_max) ((queue->max_level.format) > 0 && \ + (queue->cur_level.format) >= ((alt_max) ? \ + MIN ((queue->max_level.format), (alt_max)) : (queue->max_level.format))) + + /* if using a ring buffer we're filled if all ring buffer space is used + * _by the current range_ */ + if (QUEUE_IS_USING_RING_BUFFER (queue)) { + guint64 rb_size = queue->ring_buffer_max_size; + GST_DEBUG_OBJECT (queue, + "max bytes %u, rb size %" G_GUINT64_FORMAT ", cur bytes %u", + queue->max_level.bytes, rb_size, queue->cur_level.bytes); + return CHECK_FILLED (bytes, rb_size); + } + + /* if using file, we're never filled if we don't have EOS */ + if (QUEUE_IS_USING_TEMP_FILE (queue)) + return FALSE; + + /* we are never filled when we have no buffers at all */ + if (queue->cur_level.buffers == 0) + return FALSE; + + /* we are filled if one of the current levels exceeds the max */ + res = CHECK_FILLED (buffers, 0) || CHECK_FILLED (bytes, 0) + || CHECK_FILLED (time, 0); + + /* if we need to, use the rate estimate to check against the max time we are + * allowed to queue */ + if (queue->use_rate_estimate) + res |= CHECK_FILLED (rate_time, 0); + +#undef CHECK_FILLED + return res; +} + +static GstFlowReturn +gst_queue2_chain_buffer_or_buffer_list (GstQueue2 * queue, + GstMiniObject * item, GstQueue2ItemType item_type) +{ + /* we have to lock the queue since we span threads */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing); + /* when we received EOS, we refuse more data */ + if (queue->is_eos) + goto out_eos; + /* when we received unexpected from downstream, refuse more buffers */ + if (queue->unexpected) + goto out_unexpected; + + /* while we didn't receive the newsegment, we're seeking and we skip data */ + if (queue->seeking) + goto out_seeking; + + if (!gst_queue2_wait_free_space (queue)) + goto out_flushing; + + /* put buffer in queue now */ + gst_queue2_locked_enqueue (queue, item, item_type); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + + return GST_FLOW_OK; + + /* special conditions */ +out_flushing: + { + GstFlowReturn ret = queue->sinkresult; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "exit because task paused, reason: %s", gst_flow_get_name (ret)); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_mini_object_unref (item); + + return ret; + } +out_eos: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_mini_object_unref (item); + + return GST_FLOW_EOS; + } +out_seeking: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we are seeking"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_mini_object_unref (item); + + return GST_FLOW_OK; + } +out_unexpected: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_mini_object_unref (item); + + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_queue2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of " + "size %" G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + return gst_queue2_chain_buffer_or_buffer_list (queue, + GST_MINI_OBJECT_CAST (buffer), GST_QUEUE2_ITEM_TYPE_BUFFER); +} + +static GstFlowReturn +gst_queue2_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list) +{ + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "received buffer list %p", buffer_list); + + return gst_queue2_chain_buffer_or_buffer_list (queue, + GST_MINI_OBJECT_CAST (buffer_list), GST_QUEUE2_ITEM_TYPE_BUFFER_LIST); +} + +static GstMiniObject * +gst_queue2_dequeue_on_eos (GstQueue2 * queue, GstQueue2ItemType * item_type) +{ + GstMiniObject *data; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream"); + + /* stop pushing buffers, we dequeue all items until we see an item that we + * can push again, which is EOS or SEGMENT. If there is nothing in the + * queue we can push, we set a flag to make the sinkpad refuse more + * buffers with an EOS return value until we receive something + * pushable again or we get flushed. */ + while ((data = gst_queue2_locked_dequeue (queue, item_type))) { + if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer %p", data); + gst_buffer_unref (GST_BUFFER_CAST (data)); + } else if (*item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); + + if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT + || type == GST_EVENT_STREAM_START) { + /* we found a pushable item in the queue, push it out */ + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pushing pushable event %s after EOS", GST_EVENT_TYPE_NAME (event)); + return data; + } + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS event %p", event); + gst_event_unref (event); + } else if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer list %p", data); + gst_buffer_list_unref (GST_BUFFER_LIST_CAST (data)); + } else if (*item_type == GST_QUEUE2_ITEM_TYPE_QUERY) { + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "dropping EOS query %p", data); + } + } + /* no more items in the queue. Set the unexpected flag so that upstream + * make us refuse any more buffers on the sinkpad. Since we will still + * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the + * task function does not shut down. */ + queue->unexpected = TRUE; + return NULL; +} + +/* dequeue an item from the queue an push it downstream. This functions returns + * the result of the push. */ +static GstFlowReturn +gst_queue2_push_one (GstQueue2 * queue) +{ + GstFlowReturn result = queue->srcresult; + GstMiniObject *data; + GstQueue2ItemType item_type; + + data = gst_queue2_locked_dequeue (queue, &item_type); + if (data == NULL) + goto no_item; + +next: + STATUS (queue, queue->srcpad, "We have something dequeud"); + g_atomic_int_set (&queue->downstream_may_block, + item_type == GST_QUEUE2_ITEM_TYPE_BUFFER || + item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + + if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { + GstBuffer *buffer; + + buffer = GST_BUFFER_CAST (data); + + result = gst_pad_push (queue->srcpad, buffer); + g_atomic_int_set (&queue->downstream_may_block, 0); + + /* need to check for srcresult here as well */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + if (result == GST_FLOW_EOS) { + data = gst_queue2_dequeue_on_eos (queue, &item_type); + if (data != NULL) + goto next; + /* Since we will still accept EOS and SEGMENT we return _FLOW_OK + * to the caller so that the task function does not shut down */ + result = GST_FLOW_OK; + } + } else if (item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); + + if (type == GST_EVENT_TAG) { + if (queue->use_tags_bitrate) { + GstTagList *tags; + guint bitrate; + + gst_event_parse_tag (event, &tags); + if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &bitrate) || + gst_tag_list_get_uint (tags, GST_TAG_NOMINAL_BITRATE, &bitrate)) { + GST_QUEUE2_MUTEX_LOCK (queue); + queue->src_tags_bitrate = bitrate; + GST_QUEUE2_MUTEX_UNLOCK (queue); + GST_LOG_OBJECT (queue, "src pad bitrate from tags now %u", bitrate); + } + } + } + + gst_pad_push_event (queue->srcpad, event); + + /* if we're EOS, return EOS so that the task pauses. */ + if (type == GST_EVENT_EOS) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pushed EOS event %p, return EOS", event); + result = GST_FLOW_EOS; + } + + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + } else if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GstBufferList *buffer_list; + + buffer_list = GST_BUFFER_LIST_CAST (data); + + result = gst_pad_push_list (queue->srcpad, buffer_list); + g_atomic_int_set (&queue->downstream_may_block, 0); + + /* need to check for srcresult here as well */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + if (result == GST_FLOW_EOS) { + data = gst_queue2_dequeue_on_eos (queue, &item_type); + if (data != NULL) + goto next; + /* Since we will still accept EOS and SEGMENT we return _FLOW_OK + * to the caller so that the task function does not shut down */ + result = GST_FLOW_OK; + } + } else if (item_type == GST_QUEUE2_ITEM_TYPE_QUERY) { + GstQuery *query = GST_QUERY_CAST (data); + + GST_LOG_OBJECT (queue->srcpad, "Peering query %p", query); + queue->last_handled_query = query; + queue->last_query = gst_pad_peer_query (queue->srcpad, query); + GST_LOG_OBJECT (queue->srcpad, "Peered query"); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "did query %p, return %d", query, queue->last_query); + g_cond_signal (&queue->query_handled); + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + result = GST_FLOW_OK; + } + return result; + + /* ERRORS */ +no_item: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "exit because we have no item in the queue"); + return GST_FLOW_ERROR; + } +out_flushing: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we are %s", + gst_flow_get_name (queue->srcresult)); + return queue->srcresult; + } +} + +/* called repeatedly with @pad as the source pad. This function should push out + * data to the peer element. */ +static void +gst_queue2_loop (GstPad * pad) +{ + GstQueue2 *queue; + GstFlowReturn ret; + + queue = GST_QUEUE2 (GST_PAD_PARENT (pad)); + + /* have to lock for thread-safety */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + + if (gst_queue2_is_empty (queue)) { + gboolean started; + + /* pause the timer while we wait. The fact that we are waiting does not mean + * the byterate on the output pad is lower */ + if ((started = queue->out_timer_started)) + g_timer_stop (queue->out_timer); + + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, + "queue is empty, waiting for new data"); + do { + /* Wait for data to be available, we could be unlocked because of a flush. */ + GST_QUEUE2_WAIT_ADD_CHECK (queue, queue->srcresult, out_flushing); + } + while (gst_queue2_is_empty (queue)); + + /* and continue if we were running before */ + if (started) + g_timer_continue (queue->out_timer); + } + ret = gst_queue2_push_one (queue); + queue->srcresult = ret; + queue->sinkresult = ret; + if (ret != GST_FLOW_OK) + goto out_flushing; + + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + + return; + + /* ERRORS */ +out_flushing: + { + gboolean eos = queue->is_eos; + GstFlowReturn ret = queue->srcresult; + + gst_pad_pause_task (queue->srcpad); + if (ret == GST_FLOW_FLUSHING) { + gst_queue2_locked_flush (queue, FALSE, FALSE); + } else { + GST_QUEUE2_SIGNAL_DEL (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + } + GST_QUEUE2_MUTEX_UNLOCK (queue); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pause task, reason: %s", gst_flow_get_name (queue->srcresult)); + /* Recalculate buffering levels before stopping since the source flow + * might cause a different buffering level (like NOT_LINKED making + * the queue appear as full) */ + if (queue->use_buffering) + update_buffering (queue); + gst_queue2_post_buffering (queue); + /* let app know about us giving up if upstream is not expected to do so */ + /* EOS is already taken care of elsewhere */ + if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { + GST_ELEMENT_FLOW_ERROR (queue, ret); + gst_pad_push_event (queue->srcpad, gst_event_new_eos ()); + } + return; + } +} + +static gboolean +gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + GstQueue2 *queue = GST_QUEUE2 (parent); + +#ifndef GST_DISABLE_GST_DEBUG + GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%s)", + event, GST_EVENT_TYPE_NAME (event)); +#endif + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + if (QUEUE_IS_USING_QUEUE (queue)) { + /* just forward upstream */ + res = gst_pad_push_event (queue->sinkpad, event); + } else { + /* now unblock the getrange function */ + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "flushing"); + queue->srcresult = GST_FLOW_FLUSHING; + GST_QUEUE2_SIGNAL_ADD (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* when using a temp file, we eat the event */ + res = TRUE; + gst_event_unref (event); + } + break; + case GST_EVENT_FLUSH_STOP: + if (QUEUE_IS_USING_QUEUE (queue)) { + /* just forward upstream */ + res = gst_pad_push_event (queue->sinkpad, event); + } else { + /* now unblock the getrange function */ + GST_QUEUE2_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_OK; + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* when using a temp file, we eat the event */ + res = TRUE; + gst_event_unref (event); + } + break; + case GST_EVENT_RECONFIGURE: + GST_QUEUE2_MUTEX_LOCK (queue); + /* assume downstream is linked now and try to push again */ + if (queue->srcresult == GST_FLOW_NOT_LINKED) { + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + if (GST_PAD_MODE (pad) == GST_PAD_MODE_PUSH) { + gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, pad, + NULL); + } + } + GST_QUEUE2_MUTEX_UNLOCK (queue); + + res = gst_pad_push_event (queue->sinkpad, event); + break; + default: + res = gst_pad_push_event (queue->sinkpad, event); + break; + } + + return res; +} + +static gboolean +gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 peer_pos; + GstFormat format; + + if (!gst_pad_peer_query (queue->sinkpad, query)) + goto peer_failed; + + /* get peer position */ + gst_query_parse_position (query, &format, &peer_pos); + + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= queue->cur_level.bytes; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + case GST_FORMAT_TIME: + peer_pos -= queue->cur_level.time; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + default: + GST_WARNING_OBJECT (queue, "dropping query in %s format, don't " + "know how to adjust value", gst_format_get_name (format)); + return FALSE; + } + /* set updated position */ + gst_query_set_position (query, format, peer_pos); + break; + } + case GST_QUERY_DURATION: + { + GST_DEBUG_OBJECT (queue, "doing peer query"); + + if (!gst_pad_peer_query (queue->sinkpad, query)) + goto peer_failed; + + GST_DEBUG_OBJECT (queue, "peer query success"); + break; + } + case GST_QUERY_BUFFERING: + { + gint percent; + gboolean is_buffering; + GstBufferingMode mode; + gint avg_in, avg_out; + gint64 buffering_left; + + GST_DEBUG_OBJECT (queue, "query buffering"); + + get_buffering_level (queue, &is_buffering, &percent); + percent = convert_to_buffering_percent (queue, percent); + gst_query_set_buffering_percent (query, is_buffering, percent); + + get_buffering_stats (queue, percent, &mode, &avg_in, &avg_out, + &buffering_left); + gst_query_set_buffering_stats (query, mode, avg_in, avg_out, + buffering_left); + + if (!QUEUE_IS_USING_QUEUE (queue)) { + /* add ranges for download and ringbuffer buffering */ + GstFormat format; + gint64 start, stop, range_start, range_stop; + guint64 writing_pos; + gint64 estimated_total; + gint64 duration; + gboolean peer_res, is_eos; + GstQueue2Range *queued_ranges; + + /* we need a current download region */ + if (queue->current == NULL) + return FALSE; + + writing_pos = queue->current->writing_pos; + is_eos = queue->is_eos; + + if (is_eos) { + /* we're EOS, we know the duration in bytes now */ + peer_res = TRUE; + duration = writing_pos; + } else { + /* get duration of upstream in bytes */ + peer_res = gst_pad_peer_query_duration (queue->sinkpad, + GST_FORMAT_BYTES, &duration); + } + + GST_DEBUG_OBJECT (queue, "percent %d, duration %" G_GINT64_FORMAT + ", writing %" G_GINT64_FORMAT, percent, duration, writing_pos); + + /* calculate remaining and total download time */ + if (peer_res && avg_in > 0.0) + estimated_total = ((duration - writing_pos) * 1000) / avg_in; + else + estimated_total = -1; + + GST_DEBUG_OBJECT (queue, "estimated-total %" G_GINT64_FORMAT, + estimated_total); + + gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL); + + switch (format) { + case GST_FORMAT_PERCENT: + /* we need duration */ + if (!peer_res) + goto peer_failed; + + start = 0; + /* get our available data relative to the duration */ + if (duration != -1) + stop = + gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, writing_pos, + duration); + else + stop = -1; + break; + case GST_FORMAT_BYTES: + start = 0; + stop = writing_pos; + break; + default: + start = -1; + stop = -1; + break; + } + + /* fill out the buffered ranges */ + for (queued_ranges = queue->ranges; queued_ranges; + queued_ranges = queued_ranges->next) { + switch (format) { + case GST_FORMAT_PERCENT: + if (duration == -1) { + range_start = 0; + range_stop = 0; + break; + } + range_start = + gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, + queued_ranges->offset, duration); + range_stop = + gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, + queued_ranges->writing_pos, duration); + break; + case GST_FORMAT_BYTES: + range_start = queued_ranges->offset; + range_stop = queued_ranges->writing_pos; + break; + default: + range_start = -1; + range_stop = -1; + break; + } + if (range_start == range_stop) + continue; + GST_DEBUG_OBJECT (queue, + "range starting at %" G_GINT64_FORMAT " and finishing at %" + G_GINT64_FORMAT, range_start, range_stop); + gst_query_add_buffering_range (query, range_start, range_stop); + } + + gst_query_set_buffering_range (query, format, start, stop, + estimated_total); + } + break; + } + case GST_QUERY_SCHEDULING: + { + gboolean pull_mode; + GstSchedulingFlags flags = 0; + + if (!gst_pad_peer_query (queue->sinkpad, query)) + goto peer_failed; + + gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL); + + /* we can operate in pull mode when we are using a tempfile */ + pull_mode = !QUEUE_IS_USING_QUEUE (queue); + + if (pull_mode) + flags |= GST_SCHEDULING_FLAG_SEEKABLE; + gst_query_set_scheduling (query, flags, 0, -1, 0); + if (pull_mode) + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + break; + } + default: + /* peer handled other queries */ + if (!gst_pad_query_default (pad, parent, query)) + goto peer_failed; + break; + } + + return TRUE; + + /* ERRORS */ +peer_failed: + { + GST_DEBUG_OBJECT (queue, "failed peer query"); + return FALSE; + } +} + +static gboolean +gst_queue2_handle_query (GstElement * element, GstQuery * query) +{ + GstQueue2 *queue = GST_QUEUE2 (element); + + /* simply forward to the srcpad query function */ + return gst_queue2_handle_src_query (queue->srcpad, GST_OBJECT_CAST (element), + query); +} + +static void +gst_queue2_update_upstream_size (GstQueue2 * queue) +{ + gint64 upstream_size = -1; + + if (gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES, + &upstream_size)) { + GST_INFO_OBJECT (queue, "upstream size: %" G_GINT64_FORMAT, upstream_size); + + /* upstream_size can be negative but queue->upstream_size is unsigned. + * Prevent setting negative values to it (the query can return -1) */ + if (upstream_size >= 0) + queue->upstream_size = upstream_size; + else + queue->upstream_size = 0; + } +} + +static GstFlowReturn +gst_queue2_get_range (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstQueue2 *queue; + GstFlowReturn ret; + + queue = GST_QUEUE2_CAST (parent); + + length = (length == -1) ? DEFAULT_BUFFER_SIZE : length; + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + offset = (offset == -1) ? queue->current->reading_pos : offset; + + GST_DEBUG_OBJECT (queue, + "Getting range: offset %" G_GUINT64_FORMAT ", length %u", offset, length); + + /* catch any reads beyond the size of the file here to make sure queue2 + * doesn't send seek events beyond the size of the file upstream, since + * that would confuse elements such as souphttpsrc and/or http servers. + * Demuxers often just loop until EOS at the end of the file to figure out + * when they've read all the end-headers or index chunks. */ + if (G_UNLIKELY (offset >= queue->upstream_size)) { + gst_queue2_update_upstream_size (queue); + if (queue->upstream_size > 0 && offset >= queue->upstream_size) + goto out_unexpected; + } + + if (G_UNLIKELY (offset + length > queue->upstream_size)) { + gst_queue2_update_upstream_size (queue); + if (queue->upstream_size > 0 && offset + length >= queue->upstream_size) { + length = queue->upstream_size - offset; + GST_DEBUG_OBJECT (queue, "adjusting length downto %d", length); + } + } + + /* FIXME - function will block when the range is not yet available */ + ret = gst_queue2_create_read (queue, offset, length, buffer); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); + + return ret; + + /* ERRORS */ +out_flushing: + { + ret = queue->srcresult; + + GST_DEBUG_OBJECT (queue, "we are %s", gst_flow_get_name (ret)); + GST_QUEUE2_MUTEX_UNLOCK (queue); + return ret; + } +out_unexpected: + { + GST_DEBUG_OBJECT (queue, "read beyond end of file"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + return GST_FLOW_EOS; + } +} + +/* sink currently only operates in push mode */ +static gboolean +gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean result; + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "activating push mode"); + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + reset_rate_timer (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + /* unblock chain function */ + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "deactivating push mode"); + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + GST_QUEUE2_SIGNAL_DEL (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* wait until it is unblocked and clean up */ + GST_PAD_STREAM_LOCK (pad); + GST_QUEUE2_MUTEX_LOCK (queue); + gst_queue2_locked_flush (queue, TRUE, FALSE); + GST_QUEUE2_MUTEX_UNLOCK (queue); + GST_PAD_STREAM_UNLOCK (pad); + } + result = TRUE; + break; + default: + result = FALSE; + break; + } + return result; +} + +/* src operating in push mode, we start a task on the source pad that pushes out + * buffers from the queue */ +static gboolean +gst_queue2_src_activate_push (GstPad * pad, GstObject * parent, gboolean active) +{ + gboolean result = FALSE; + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + if (active) { + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "activating push mode"); + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + result = + gst_pad_start_task (pad, (GstTaskFunction) gst_queue2_loop, pad, NULL); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + /* unblock loop function */ + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "deactivating push mode"); + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + /* the item add signal will unblock */ + GST_QUEUE2_SIGNAL_ADD (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + + /* step 2, make sure streaming finishes */ + result = gst_pad_stop_task (pad); + + GST_QUEUE2_MUTEX_LOCK (queue); + gst_queue2_locked_flush (queue, FALSE, FALSE); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } + + return result; +} + +/* pull mode, downstream will call our getrange function */ +static gboolean +gst_queue2_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active) +{ + gboolean result; + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + if (active) { + GST_QUEUE2_MUTEX_LOCK (queue); + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + /* open the temp file now */ + result = gst_queue2_open_temp_location_file (queue); + } else if (!queue->ring_buffer) { + queue->ring_buffer = g_malloc (queue->ring_buffer_max_size); + result = ! !queue->ring_buffer; + } else { + result = TRUE; + } + + GST_DEBUG_OBJECT (queue, "activating pull mode"); + init_ranges (queue); + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + queue->upstream_size = 0; + } else { + GST_DEBUG_OBJECT (queue, "no temp file, cannot activate pull mode"); + /* this is not allowed, we cannot operate in pull mode without a temp + * file. */ + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + result = FALSE; + } + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "deactivating pull mode"); + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + /* this will unlock getrange */ + GST_QUEUE2_SIGNAL_ADD (queue); + result = TRUE; + GST_QUEUE2_MUTEX_UNLOCK (queue); + } + + return result; +} + +static gboolean +gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean res; + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_queue2_src_activate_pull (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_queue2_src_activate_push (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + +static GstStateChangeReturn +gst_queue2_change_state (GstElement * element, GstStateChange transition) +{ + GstQueue2 *queue; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + queue = GST_QUEUE2 (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_QUEUE2_MUTEX_LOCK (queue); + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + if (!gst_queue2_open_temp_location_file (queue)) + ret = GST_STATE_CHANGE_FAILURE; + } else { + if (queue->ring_buffer) { + g_free (queue->ring_buffer); + queue->ring_buffer = NULL; + } + if (!(queue->ring_buffer = g_malloc (queue->ring_buffer_max_size))) + ret = GST_STATE_CHANGE_FAILURE; + } + init_ranges (queue); + } + queue->segment_event_received = FALSE; + queue->starting_segment = NULL; + gst_event_replace (&queue->stream_start_event, NULL); + GST_QUEUE2_MUTEX_UNLOCK (queue); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + 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: + GST_QUEUE2_MUTEX_LOCK (queue); + if (!QUEUE_IS_USING_QUEUE (queue)) { + if (QUEUE_IS_USING_TEMP_FILE (queue)) { + gst_queue2_close_temp_location_file (queue); + } else if (queue->ring_buffer) { + g_free (queue->ring_buffer); + queue->ring_buffer = NULL; + } + clean_ranges (queue); + } + if (queue->starting_segment != NULL) { + gst_event_unref (queue->starting_segment); + queue->starting_segment = NULL; + } + gst_event_replace (&queue->stream_start_event, NULL); + GST_QUEUE2_MUTEX_UNLOCK (queue); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +/* changing the capacity of the queue must wake up + * the _chain function, it might have more room now + * to store the buffer/event in the queue */ +#define QUEUE_CAPACITY_CHANGE(q) \ + GST_QUEUE2_SIGNAL_DEL (queue); \ + if (queue->use_buffering) \ + update_buffering (queue); + +/* Changing the minimum required fill level must + * wake up the _loop function as it might now + * be able to preceed. + */ +#define QUEUE_THRESHOLD_CHANGE(q)\ + GST_QUEUE2_SIGNAL_ADD (queue); + +static void +gst_queue2_set_temp_template (GstQueue2 * queue, const gchar * template) +{ + GstState state; + + /* the element must be stopped in order to do this */ + GST_OBJECT_LOCK (queue); + state = GST_STATE (queue); + if (state != GST_STATE_READY && state != GST_STATE_NULL) + goto wrong_state; + GST_OBJECT_UNLOCK (queue); + + /* set new location */ + g_free (queue->temp_template); + queue->temp_template = g_strdup (template); + + return; + +/* ERROR */ +wrong_state: + { + GST_WARNING_OBJECT (queue, "setting temp-template property in wrong state"); + GST_OBJECT_UNLOCK (queue); + } +} + +static void +gst_queue2_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstQueue2 *queue = GST_QUEUE2 (object); + + /* someone could change levels here, and since this + * affects the get/put funcs, we need to lock for safety. */ + GST_QUEUE2_MUTEX_LOCK (queue); + + switch (prop_id) { + case PROP_MAX_SIZE_BYTES: + queue->max_level.bytes = g_value_get_uint (value); + QUEUE_CAPACITY_CHANGE (queue); + break; + case PROP_MAX_SIZE_BUFFERS: + queue->max_level.buffers = g_value_get_uint (value); + QUEUE_CAPACITY_CHANGE (queue); + break; + case PROP_MAX_SIZE_TIME: + queue->max_level.time = g_value_get_uint64 (value); + /* set rate_time to the same value. We use an extra field in the level + * structure so that we can easily access and compare it */ + queue->max_level.rate_time = queue->max_level.time; + QUEUE_CAPACITY_CHANGE (queue); + break; + case PROP_USE_BUFFERING: + queue->use_buffering = g_value_get_boolean (value); + if (!queue->use_buffering && queue->is_buffering) { + GST_DEBUG_OBJECT (queue, "Disabled buffering while buffering, " + "posting 100%% message"); + SET_PERCENT (queue, 100); + queue->is_buffering = FALSE; + } + + if (queue->use_buffering) { + queue->is_buffering = TRUE; + update_buffering (queue); + } + break; + case PROP_USE_TAGS_BITRATE: + queue->use_tags_bitrate = g_value_get_boolean (value); + break; + case PROP_USE_RATE_ESTIMATE: + queue->use_rate_estimate = g_value_get_boolean (value); + break; + case PROP_LOW_PERCENT: + queue->low_watermark = g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_HIGH_PERCENT: + queue->high_watermark = + g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_LOW_WATERMARK: + queue->low_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_HIGH_WATERMARK: + queue->high_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_TEMP_TEMPLATE: + gst_queue2_set_temp_template (queue, g_value_get_string (value)); + break; + case PROP_TEMP_REMOVE: + queue->temp_remove = g_value_get_boolean (value); + break; + case PROP_RING_BUFFER_MAX_SIZE: + queue->ring_buffer_max_size = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_queue2_post_buffering (queue); +} + +static void +gst_queue2_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstQueue2 *queue = GST_QUEUE2 (object); + + GST_QUEUE2_MUTEX_LOCK (queue); + + switch (prop_id) { + case PROP_CUR_LEVEL_BYTES: + g_value_set_uint (value, queue->cur_level.bytes); + break; + case PROP_CUR_LEVEL_BUFFERS: + g_value_set_uint (value, queue->cur_level.buffers); + break; + case PROP_CUR_LEVEL_TIME: + g_value_set_uint64 (value, queue->cur_level.time); + break; + case PROP_MAX_SIZE_BYTES: + g_value_set_uint (value, queue->max_level.bytes); + break; + case PROP_MAX_SIZE_BUFFERS: + g_value_set_uint (value, queue->max_level.buffers); + break; + case PROP_MAX_SIZE_TIME: + g_value_set_uint64 (value, queue->max_level.time); + break; + case PROP_USE_BUFFERING: + g_value_set_boolean (value, queue->use_buffering); + break; + case PROP_USE_TAGS_BITRATE: + g_value_set_boolean (value, queue->use_tags_bitrate); + break; + case PROP_USE_RATE_ESTIMATE: + g_value_set_boolean (value, queue->use_rate_estimate); + break; + case PROP_LOW_PERCENT: + g_value_set_int (value, queue->low_watermark / BUF_LEVEL_PERCENT_FACTOR); + break; + case PROP_HIGH_PERCENT: + g_value_set_int (value, queue->high_watermark / BUF_LEVEL_PERCENT_FACTOR); + break; + case PROP_LOW_WATERMARK: + g_value_set_double (value, queue->low_watermark / + (gdouble) MAX_BUFFERING_LEVEL); + break; + case PROP_HIGH_WATERMARK: + g_value_set_double (value, queue->high_watermark / + (gdouble) MAX_BUFFERING_LEVEL); + break; + case PROP_TEMP_TEMPLATE: + g_value_set_string (value, queue->temp_template); + break; + case PROP_TEMP_LOCATION: + g_value_set_string (value, queue->temp_location); + break; + case PROP_TEMP_REMOVE: + g_value_set_boolean (value, queue->temp_remove); + break; + case PROP_RING_BUFFER_MAX_SIZE: + g_value_set_uint64 (value, queue->ring_buffer_max_size); + break; + case PROP_AVG_IN_RATE: + { + gdouble in_rate = queue->byte_in_rate; + + /* During the first RATE_INTERVAL, byte_in_rate will not have been + * calculated, so calculate it here. */ + if (in_rate == 0.0 && queue->bytes_in + && queue->last_update_in_rates_elapsed > 0.0) + in_rate = queue->bytes_in / queue->last_update_in_rates_elapsed; + + g_value_set_int64 (value, (gint64) in_rate); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_QUEUE2_MUTEX_UNLOCK (queue); +} diff --git a/plugins/elements/gstqueue2.h b/plugins/elements/gstqueue2.h new file mode 100644 index 0000000..34e3aba --- /dev/null +++ b/plugins/elements/gstqueue2.h @@ -0,0 +1,182 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2003 Colin Walters + * 2000,2005,2007 Wim Taymans + * 2007 Thiago Sousa Santos + * + * gstqueue2.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef __GST_QUEUE2_H__ +#define __GST_QUEUE2_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_QUEUE2 \ + (gst_queue2_get_type()) +#define GST_QUEUE2(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QUEUE2,GstQueue2)) +#define GST_QUEUE2_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QUEUE2,GstQueue2Class)) +#define GST_IS_QUEUE2(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QUEUE2)) +#define GST_IS_QUEUE2_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE2)) +#define GST_QUEUE2_CAST(obj) \ + ((GstQueue2 *)(obj)) + +typedef struct _GstQueue2 GstQueue2; +typedef struct _GstQueue2Size GstQueue2Size; +typedef struct _GstQueue2Class GstQueue2Class; +typedef struct _GstQueue2Range GstQueue2Range; + +/* used to keep track of sizes (current and max) */ +struct _GstQueue2Size +{ + guint buffers; + guint bytes; + guint64 time; + guint64 rate_time; +}; + +struct _GstQueue2Range +{ + GstQueue2Range *next; + + guint64 offset; /* offset of range start in source */ + guint64 rb_offset; /* offset of range start in ring buffer */ + guint64 writing_pos; /* writing position in source */ + guint64 rb_writing_pos; /* writing position in ring buffer */ + guint64 reading_pos; /* reading position in source */ + guint64 max_reading_pos; /* latest requested offset in source */ +}; + +struct _GstQueue2 +{ + GstElement element; + + /*< private > */ + GstPad *sinkpad; + GstPad *srcpad; + + /* upstream size in bytes (if downstream is operating in pull mode) */ + guint64 upstream_size; + + /* segments to keep track of timestamps */ + GstSegment sink_segment; + GstSegment src_segment; + + /* Position of src/sink */ + GstClockTime sinktime, srctime; + /* TRUE if either position needs to be recalculated */ + gboolean sink_tainted, src_tainted; + /* Bitrates taken from tags */ + guint sink_tags_bitrate; + guint src_tags_bitrate; + + /* flowreturn when srcpad is paused */ + GstFlowReturn srcresult; + GstFlowReturn sinkresult; + gboolean is_eos; + gboolean unexpected; + + /* the queue of data we're keeping our hands on */ + GQueue queue; + + GCond query_handled; + gboolean last_query; /* result of last serialized query */ + GstQuery *last_handled_query; + + GstQueue2Size cur_level; /* currently in the queue */ + GstQueue2Size max_level; /* max. amount of data allowed in the queue */ + gboolean use_buffering; + gboolean use_tags_bitrate; + gboolean use_rate_estimate; + GstClockTime buffering_interval; + + /* low/high watermarks for buffering */ + gint low_watermark; + gint high_watermark; + + /* current buffering state */ + gboolean is_buffering; + gint buffering_percent; + + /* for measuring input/output rates */ + GTimer *in_timer; + gboolean in_timer_started; + gdouble last_update_in_rates_elapsed; + gdouble last_in_elapsed; + guint64 bytes_in; + gdouble byte_in_rate; + gdouble byte_in_period; + + GTimer *out_timer; + gboolean out_timer_started; + gdouble last_out_elapsed; + guint64 bytes_out; + gdouble byte_out_rate; + + GMutex qlock; /* lock for queue (vs object lock) */ + gboolean waiting_add; + GCond item_add; /* signals buffers now available for reading */ + gboolean waiting_del; + GCond item_del; /* signals space now available for writing */ + + /* temp location stuff */ + gchar *temp_template; + gboolean temp_location_set; + gchar *temp_location; + gboolean temp_remove; + FILE *temp_file; + /* list of downloaded areas and the current area */ + GstQueue2Range *ranges; + GstQueue2Range *current; + /* we need this to send the first new segment event of the stream + * because we can't save it on the file */ + gboolean segment_event_received; + GstEvent *starting_segment; + gboolean seeking; + + GstEvent *stream_start_event; + + guint64 ring_buffer_max_size; + guint8 * ring_buffer; + + volatile gint downstream_may_block; + + GstBufferingMode mode; + gint64 buffering_left; + gint avg_in; + gint avg_out; + gboolean percent_changed; + GMutex buffering_post_lock; /* assures only one posted at a time */ +}; + +struct _GstQueue2Class +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_queue2_get_type (void); + +G_END_DECLS + +#endif /* __GST_QUEUE2_H__ */ diff --git a/plugins/elements/gstsparsefile.c b/plugins/elements/gstsparsefile.c new file mode 100644 index 0000000..0ff6b16 --- /dev/null +++ b/plugins/elements/gstsparsefile.c @@ -0,0 +1,667 @@ +/* GStreamer + * Copyright (C) 2014 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstsparsefile.h" + +#ifdef G_OS_WIN32 +#include /* lseek, open, close, read */ +#undef lseek +#define lseek _lseeki64 +#undef off_t +#define off_t guint64 +#else +#include +#endif + +#ifdef HAVE_FSEEKO +#define FSEEK_FILE(file,offset) (fseeko (file, (off_t) offset, SEEK_SET) != 0) +#elif defined (G_OS_UNIX) || defined (G_OS_WIN32) +#define FSEEK_FILE(file,offset) (lseek (fileno (file), (off_t) offset, SEEK_SET) == (off_t) -1) +#else +#define FSEEK_FILE(file,offset) (fseek (file, offset, SEEK_SET) != 0) +#endif + +#define GST_SPARSE_FILE_IO_ERROR \ + g_quark_from_static_string("gst-sparse-file-io-error-quark") + +static GstSparseFileIOErrorEnum +gst_sparse_file_io_error_from_errno (gint err_no); + +typedef struct _GstSparseRange GstSparseRange; + +struct _GstSparseRange +{ + GstSparseRange *next; + + gsize start; + gsize stop; +}; + +#define RANGE_CONTAINS(r,o) ((r)->start <= (o) && (r)->stop > (o)) + +struct _GstSparseFile +{ + gint fd; + FILE *file; + gsize current_pos; + + GstSparseRange *ranges; + guint n_ranges; + + GstSparseRange *write_range; + GstSparseRange *read_range; +}; + +static GstSparseRange * +get_write_range (GstSparseFile * file, gsize offset) +{ + GstSparseRange *next, *prev, *result = NULL; + + if (file->write_range && file->write_range->stop == offset) + return file->write_range; + + prev = NULL; + next = file->ranges; + while (next) { + if (next->start > offset) + break; + + if (next->stop >= offset) { + result = next; + break; + } + prev = next; + next = next->next; + } + if (result == NULL) { + result = g_slice_new0 (GstSparseRange); + result->start = offset; + result->stop = offset; + + result->next = next; + if (prev) + prev->next = result; + else + file->ranges = result; + + file->write_range = result; + file->read_range = NULL; + + file->n_ranges++; + } + return result; +} + +static GstSparseRange * +get_read_range (GstSparseFile * file, gsize offset, gsize count) +{ + GstSparseRange *walk, *result = NULL; + + if (file->read_range && RANGE_CONTAINS (file->read_range, offset)) + return file->read_range; + + for (walk = file->ranges; walk; walk = walk->next) { + if (walk->start > offset) + break; + + if (walk->stop >= offset + count) { + result = walk; + break; + } + } + return result; +} + +/** + * gst_sparse_file_new: + * + * Make a new #GstSparseFile + * + * Returns: a new #GstSparseFile, gst_sparse_file_free() after usage. + * + * Since: 1.4 + */ +GstSparseFile * +gst_sparse_file_new (void) +{ + GstSparseFile *result; + + result = g_slice_new0 (GstSparseFile); + result->current_pos = 0; + result->ranges = NULL; + result->n_ranges = 0; + + return result; +} + +/** + * gst_sparse_file_set_fd: + * @file: a #GstSparseFile + * @fd: a file descriptor + * + * Store the data for @file in the file represented with @fd. + * + * Returns: %TRUE when @fd could be set + * + * Since: 1.4 + */ +gboolean +gst_sparse_file_set_fd (GstSparseFile * file, gint fd) +{ + g_return_val_if_fail (file != NULL, FALSE); + g_return_val_if_fail (fd != 0, FALSE); + + file->file = fdopen (fd, "wb+"); + file->fd = fd; + + return file->file != NULL; +} + +/** + * gst_sparse_file_clear: + * @file: a #GstSparseFile + * + * Clear all the ranges in @file. + */ +void +gst_sparse_file_clear (GstSparseFile * file) +{ + g_return_if_fail (file != NULL); + + if (file->file) { + fclose (file->file); + file->file = fdopen (file->fd, "wb+"); + } + g_slice_free_chain (GstSparseRange, file->ranges, next); + file->current_pos = 0; + file->ranges = NULL; + file->n_ranges = 0; +} + +/** + * gst_sparse_file_free: + * @file: a #GstSparseFile + * + * Free the memory used by @file. + * + * Since: 1.4 + */ +void +gst_sparse_file_free (GstSparseFile * file) +{ + g_return_if_fail (file != NULL); + + if (file->file) { + fflush (file->file); + fclose (file->file); + } + g_slice_free_chain (GstSparseRange, file->ranges, next); + g_slice_free (GstSparseFile, file); +} + +/** + * gst_sparse_file_write: + * @file: a #GstSparseFile + * @offset: the offset + * @data: the data + * @count: amount of bytes + * @available: amount of bytes already available + * @error: a #GError + * + * Write @count bytes from @data to @file at @offset. + * + * If @available is not %NULL, it will be updated with the amount of + * data already available after the last written byte. + * + * Returns: The number of bytes written or 0 on error. + * + * Since: 1.4 + */ +gsize +gst_sparse_file_write (GstSparseFile * file, gsize offset, gconstpointer data, + gsize count, gsize * available, GError ** error) +{ + GstSparseRange *range, *next; + gsize stop; + + g_return_val_if_fail (file != NULL, 0); + g_return_val_if_fail (count != 0, 0); + + if (file->file) { + if (file->current_pos != offset) { + GST_DEBUG ("seeking to %" G_GSIZE_FORMAT, offset); + if (FSEEK_FILE (file->file, offset)) + goto error; + } + if (fwrite (data, count, 1, file->file) != 1) + goto error; + } + + file->current_pos = offset + count; + + /* update the new stop position in the range */ + range = get_write_range (file, offset); + stop = offset + count; + range->stop = MAX (range->stop, stop); + + /* see if we can merge with next region */ + while ((next = range->next)) { + if (next->start > range->stop) + break; + + GST_DEBUG ("merging range %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT ", next %" + G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT, range->start, range->stop, + next->start, next->stop); + + range->stop = MAX (next->stop, range->stop); + range->next = next->next; + + if (file->write_range == next) + file->write_range = NULL; + if (file->read_range == next) + file->read_range = NULL; + g_slice_free (GstSparseRange, next); + file->n_ranges--; + } + if (available) + *available = range->stop - stop; + + return count; + + /* ERRORS */ +error: + { + g_set_error (error, GST_SPARSE_FILE_IO_ERROR, + gst_sparse_file_io_error_from_errno (errno), "Error writing file: %s", + g_strerror (errno)); + return 0; + } +} + +/** + * gst_sparse_file_read: + * @file: a #GstSparseFile + * @offset: the offset + * @data: the data + * @count: amount of bytes + * @remaining: amount of bytes remaining + * @error: a #GError + * + * Read @count bytes from @file at @offset into @data. + * + * On error, @error will be set. If there are no @count bytes available + * at @offset, %GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK is returned. + * + * @remaining will be set to the amount of bytes remaining in the read + * range. + * + * Returns: The number of bytes read of 0 on error. + * + * Since: 1.4 + */ +gsize +gst_sparse_file_read (GstSparseFile * file, gsize offset, gpointer data, + gsize count, gsize * remaining, GError ** error) +{ + GstSparseRange *range; + gsize res = 0; + + g_return_val_if_fail (file != NULL, 0); + g_return_val_if_fail (count != 0, 0); + + if ((range = get_read_range (file, offset, count)) == NULL) + goto no_range; + + if (file->file) { + if (file->current_pos != offset) { + GST_DEBUG ("seeking from %" G_GSIZE_FORMAT " to %" G_GSIZE_FORMAT, + file->current_pos, offset); + if (FSEEK_FILE (file->file, offset)) + goto error; + } + res = fread (data, 1, count, file->file); + if (G_UNLIKELY (res < count)) + goto error; + } + + file->current_pos = offset + res; + + if (remaining) + *remaining = range->stop - file->current_pos; + + return count; + + /* ERRORS */ +no_range: + { + g_set_error_literal (error, GST_SPARSE_FILE_IO_ERROR, + GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK, "Offset not written to file yet"); + return 0; + } +error: + { + if (ferror (file->file)) { + g_set_error (error, GST_SPARSE_FILE_IO_ERROR, + gst_sparse_file_io_error_from_errno (errno), "Error reading file: %s", + g_strerror (errno)); + } else if (feof (file->file)) { + return res; + } + return 0; + } +} + +/** + * gst_sparse_file_n_ranges: + * @file: a #GstSparseFile + * + * Get the number of ranges that are written in @file. + * + * Returns: the number of written ranges. + * + * Since: 1.4 + */ +guint +gst_sparse_file_n_ranges (GstSparseFile * file) +{ + g_return_val_if_fail (file != NULL, 0); + + return file->n_ranges; +} + +/** + * gst_sparse_file_get_range_before: + * @file: a #GstSparseFile + * @offset: the range offset + * @start: result start + * @stop: result stop + * + * Get the start and stop offset of the range containing data before or + * including @offset. + * + * Returns: %TRUE if the range with data before @offset exists. + * + * Since: 1.4 + */ +gboolean +gst_sparse_file_get_range_before (GstSparseFile * file, gsize offset, + gsize * start, gsize * stop) +{ + GstSparseRange *walk, *result = NULL; + + g_return_val_if_fail (file != NULL, FALSE); + + for (walk = file->ranges; walk; walk = walk->next) { + GST_DEBUG ("start %" G_GSIZE_FORMAT " > %" G_GSIZE_FORMAT, + walk->stop, offset); + if (walk->start > offset) + break; + + if (walk->start <= offset) + result = walk; + } + + if (result) { + if (start) + *start = result->start; + if (stop) + *stop = result->stop; + } + return result != NULL; +} + +/** + * gst_sparse_file_get_range_after: + * @file: a #GstSparseFile + * @offset: the range offset + * @start: result start + * @stop: result stop + * + * Get the start and stop offset of the range containing data after or + * including @offset. + * + * Returns: %TRUE if the range with data after @offset exists. + * + * Since: 1.4 + */ +gboolean +gst_sparse_file_get_range_after (GstSparseFile * file, gsize offset, + gsize * start, gsize * stop) +{ + GstSparseRange *walk, *result = NULL; + + g_return_val_if_fail (file != NULL, FALSE); + + for (walk = file->ranges; walk; walk = walk->next) { + GST_DEBUG ("stop %" G_GSIZE_FORMAT " > %" G_GSIZE_FORMAT, + walk->stop, offset); + if (walk->stop > offset) { + result = walk; + break; + } + } + if (result) { + if (start) + *start = result->start; + if (stop) + *stop = result->stop; + } + return result != NULL; +} + +/* we don't want to rely on libgio just for g_io_error_from_errno() */ +static GstSparseFileIOErrorEnum +gst_sparse_file_io_error_from_errno (gint err_no) +{ + switch (err_no) { +#ifdef EEXIST + case EEXIST: + return GST_SPARSE_FILE_IO_ERROR_EXISTS; + break; +#endif + +#ifdef EISDIR + case EISDIR: + return GST_SPARSE_FILE_IO_ERROR_IS_DIRECTORY; + break; +#endif + +#ifdef EACCES + case EACCES: + return GST_SPARSE_FILE_IO_ERROR_PERMISSION_DENIED; + break; +#endif + +#ifdef ENAMETOOLONG + case ENAMETOOLONG: + return GST_SPARSE_FILE_IO_ERROR_FILENAME_TOO_LONG; + break; +#endif + +#ifdef ENOENT + case ENOENT: + return GST_SPARSE_FILE_IO_ERROR_NOT_FOUND; + break; +#endif + +#ifdef ENOTDIR + case ENOTDIR: + return GST_SPARSE_FILE_IO_ERROR_NOT_DIRECTORY; + break; +#endif + +#ifdef EROFS + case EROFS: + return GST_SPARSE_FILE_IO_ERROR_READ_ONLY; + break; +#endif + +#ifdef ELOOP + case ELOOP: + return GST_SPARSE_FILE_IO_ERROR_TOO_MANY_LINKS; + break; +#endif + +#ifdef ENOSPC + case ENOSPC: + return GST_SPARSE_FILE_IO_ERROR_NO_SPACE; + break; +#endif + +#ifdef ENOMEM + case ENOMEM: + return GST_SPARSE_FILE_IO_ERROR_NO_SPACE; + break; +#endif + +#ifdef EINVAL + case EINVAL: + return GST_SPARSE_FILE_IO_ERROR_INVALID_ARGUMENT; + break; +#endif + +#ifdef EPERM + case EPERM: + return GST_SPARSE_FILE_IO_ERROR_PERMISSION_DENIED; + break; +#endif + +#ifdef ECANCELED + case ECANCELED: + return GST_SPARSE_FILE_IO_ERROR_CANCELLED; + break; +#endif + + /* ENOTEMPTY == EEXIST on AIX for backward compatibility reasons */ +#if defined (ENOTEMPTY) && (!defined (EEXIST) || (ENOTEMPTY != EEXIST)) + case ENOTEMPTY: + return GST_SPARSE_FILE_IO_ERROR_NOT_EMPTY; + break; +#endif + +#ifdef ENOTSUP + case ENOTSUP: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + + /* EOPNOTSUPP == ENOTSUP on Linux, but POSIX considers them distinct */ +#if defined (EOPNOTSUPP) && (!defined (ENOTSUP) || (EOPNOTSUPP != ENOTSUP)) + case EOPNOTSUPP: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + +#ifdef ESOCKTNOSUPPORT + case ESOCKTNOSUPPORT: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + +#ifdef EPFNOSUPPORT + case EPFNOSUPPORT: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: + return GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED; + break; +#endif + +#ifdef ETIMEDOUT + case ETIMEDOUT: + return GST_SPARSE_FILE_IO_ERROR_TIMED_OUT; + break; +#endif + +#ifdef EBUSY + case EBUSY: + return GST_SPARSE_FILE_IO_ERROR_BUSY; + break; +#endif + +#ifdef EWOULDBLOCK + case EWOULDBLOCK: + return GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK; + break; +#endif + + /* EWOULDBLOCK == EAGAIN on most systems, but POSIX considers them distinct */ +#if defined (EAGAIN) && (!defined (EWOULDBLOCK) || (EWOULDBLOCK != EAGAIN)) + case EAGAIN: + return GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK; + break; +#endif + +#ifdef EMFILE + case EMFILE: + return GST_SPARSE_FILE_IO_ERROR_TOO_MANY_OPEN_FILES; + break; +#endif + +#ifdef EADDRINUSE + case EADDRINUSE: + return GST_SPARSE_FILE_IO_ERROR_ADDRESS_IN_USE; + break; +#endif + +#ifdef EHOSTUNREACH + case EHOSTUNREACH: + return GST_SPARSE_FILE_IO_ERROR_HOST_UNREACHABLE; + break; +#endif + +#ifdef ENETUNREACH + case ENETUNREACH: + return GST_SPARSE_FILE_IO_ERROR_NETWORK_UNREACHABLE; + break; +#endif + +#ifdef ECONNREFUSED + case ECONNREFUSED: + return GST_SPARSE_FILE_IO_ERROR_CONNECTION_REFUSED; + break; +#endif + +#ifdef EPIPE + case EPIPE: + return GST_SPARSE_FILE_IO_ERROR_BROKEN_PIPE; + break; +#endif + + default: + return GST_SPARSE_FILE_IO_ERROR_FAILED; + break; + } +} diff --git a/plugins/elements/gstsparsefile.h b/plugins/elements/gstsparsefile.h new file mode 100644 index 0000000..76f73d3 --- /dev/null +++ b/plugins/elements/gstsparsefile.h @@ -0,0 +1,108 @@ +/* GStreamer + * Copyright (C) 2014 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#ifndef __GST_SPARSE_FILE_H__ +#define __GST_SPARSE_FILE_H__ + +G_BEGIN_DECLS + +typedef struct _GstSparseFile GstSparseFile; + +/* NOTE: Remove this before making this public API again! */ +typedef enum { + GST_SPARSE_FILE_IO_ERROR_FAILED, + GST_SPARSE_FILE_IO_ERROR_NOT_FOUND, + GST_SPARSE_FILE_IO_ERROR_EXISTS, + GST_SPARSE_FILE_IO_ERROR_IS_DIRECTORY, + GST_SPARSE_FILE_IO_ERROR_NOT_DIRECTORY, + GST_SPARSE_FILE_IO_ERROR_NOT_EMPTY, + GST_SPARSE_FILE_IO_ERROR_NOT_REGULAR_FILE, + GST_SPARSE_FILE_IO_ERROR_NOT_SYMBOLIC_LINK, + GST_SPARSE_FILE_IO_ERROR_NOT_MOUNTABLE_FILE, + GST_SPARSE_FILE_IO_ERROR_FILENAME_TOO_LONG, + GST_SPARSE_FILE_IO_ERROR_INVALID_FILENAME, + GST_SPARSE_FILE_IO_ERROR_TOO_MANY_LINKS, + GST_SPARSE_FILE_IO_ERROR_NO_SPACE, + GST_SPARSE_FILE_IO_ERROR_INVALID_ARGUMENT, + GST_SPARSE_FILE_IO_ERROR_PERMISSION_DENIED, + GST_SPARSE_FILE_IO_ERROR_NOT_SUPPORTED, + GST_SPARSE_FILE_IO_ERROR_NOT_MOUNTED, + GST_SPARSE_FILE_IO_ERROR_ALREADY_MOUNTED, + GST_SPARSE_FILE_IO_ERROR_CLOSED, + GST_SPARSE_FILE_IO_ERROR_CANCELLED, + GST_SPARSE_FILE_IO_ERROR_PENDING, + GST_SPARSE_FILE_IO_ERROR_READ_ONLY, + GST_SPARSE_FILE_IO_ERROR_CANT_CREATE_BACKUP, + GST_SPARSE_FILE_IO_ERROR_WRONG_ETAG, + GST_SPARSE_FILE_IO_ERROR_TIMED_OUT, + GST_SPARSE_FILE_IO_ERROR_WOULD_RECURSE, + GST_SPARSE_FILE_IO_ERROR_BUSY, + GST_SPARSE_FILE_IO_ERROR_WOULD_BLOCK, + GST_SPARSE_FILE_IO_ERROR_HOST_NOT_FOUND, + GST_SPARSE_FILE_IO_ERROR_WOULD_MERGE, + GST_SPARSE_FILE_IO_ERROR_FAILED_HANDLED, + GST_SPARSE_FILE_IO_ERROR_TOO_MANY_OPEN_FILES, + GST_SPARSE_FILE_IO_ERROR_NOT_INITIALIZED, + GST_SPARSE_FILE_IO_ERROR_ADDRESS_IN_USE, + GST_SPARSE_FILE_IO_ERROR_PARTIAL_INPUT, + GST_SPARSE_FILE_IO_ERROR_INVALID_DATA, + GST_SPARSE_FILE_IO_ERROR_DBUS_ERROR, + GST_SPARSE_FILE_IO_ERROR_HOST_UNREACHABLE, + GST_SPARSE_FILE_IO_ERROR_NETWORK_UNREACHABLE, + GST_SPARSE_FILE_IO_ERROR_CONNECTION_REFUSED, + GST_SPARSE_FILE_IO_ERROR_PROXY_FAILED, + GST_SPARSE_FILE_IO_ERROR_PROXY_AUTH_FAILED, + GST_SPARSE_FILE_IO_ERROR_PROXY_NEED_AUTH, + GST_SPARSE_FILE_IO_ERROR_PROXY_NOT_ALLOWED, + GST_SPARSE_FILE_IO_ERROR_BROKEN_PIPE +} GstSparseFileIOErrorEnum; + +GstSparseFile * gst_sparse_file_new (void); +void gst_sparse_file_free (GstSparseFile *file); + +gboolean gst_sparse_file_set_fd (GstSparseFile *file, gint fd); +void gst_sparse_file_clear (GstSparseFile *file); + +gsize gst_sparse_file_write (GstSparseFile *file, + gsize offset, + gconstpointer data, + gsize count, + gsize *available, + GError **error); + +gsize gst_sparse_file_read (GstSparseFile *file, + gsize offset, + gpointer data, + gsize count, + gsize *remaining, + GError **error); + +guint gst_sparse_file_n_ranges (GstSparseFile *file); + +gboolean gst_sparse_file_get_range_before (GstSparseFile *file, gsize offset, + gsize *start, gsize *stop); + +gboolean gst_sparse_file_get_range_after (GstSparseFile *file, gsize offset, + gsize *start, gsize *stop); + +G_END_DECLS + +#endif /* __GST_SPARSE_FILE_H__ */ diff --git a/plugins/elements/gststreamiddemux.c b/plugins/elements/gststreamiddemux.c new file mode 100644 index 0000000..f0b1dd2 --- /dev/null +++ b/plugins/elements/gststreamiddemux.c @@ -0,0 +1,413 @@ +/* GStreamer streamiddemux element + * + * Copyright 2013 LGE Corporation. + * @author: Hoonhee Lee + * @author: Jeongseok Kim + * @author: Wonchul Lee + * + * gststreamiddemux.c: Simple stream-id-demultiplexer element + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:element-streamiddemux + * @title: streamiddemux + * + * The basic concept was started from de-funneling element which restores one + * serialized stream via #GstFunnel to its original state. #GstStreamidDemux + * classifies each stream base on stream ids. + * + * The stream id demux always takes one input and checks how many streams + * are contained in a stream by STREAM_START event. Likewise #GstFunnel, + * #GstStreamidDemux does not synchronize the different output streams. + * + * #GstStreamidDemux:active-pad provides information about which output pad + * is activated at the moment. + * + * @see_also: #GstFunnel, #gst_event_new_stream_start + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gststreamiddemux.h" + +GST_DEBUG_CATEGORY_STATIC (streamid_demux_debug); +#define GST_CAT_DEFAULT streamid_demux_debug + +enum +{ + PROP_0, + PROP_ACTIVE_PAD, + PROP_LAST +}; + +static GstStaticPadTemplate gst_streamid_demux_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_streamid_demux_src_factory = +GST_STATIC_PAD_TEMPLATE ("src_%u", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +#define _do_init \ +GST_DEBUG_CATEGORY_INIT (streamid_demux_debug, \ + "streamiddemux", 0, "Streamid demuxer"); +#define gst_streamid_demux_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstStreamidDemux, gst_streamid_demux, + GST_TYPE_ELEMENT, _do_init); + +static void gst_streamid_demux_dispose (GObject * object); +static void gst_streamid_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GstFlowReturn gst_streamid_demux_chain (GstPad * pad, + GstObject * parent, GstBuffer * buf); +static gboolean gst_streamid_demux_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static GstStateChangeReturn gst_streamid_demux_change_state (GstElement * + element, GstStateChange transition); +static GstPad *gst_streamid_demux_get_srcpad_by_stream_id (GstStreamidDemux * + demux, const gchar * stream_id); +static gboolean gst_streamid_demux_srcpad_create (GstStreamidDemux * demux, + GstPad * pad, const gchar * stream_id); +static void gst_streamid_demux_reset (GstStreamidDemux * demux); +static void gst_streamid_demux_release_srcpad (const GValue * item, + GstStreamidDemux * demux); + +static void +gst_streamid_demux_class_init (GstStreamidDemuxClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->get_property = gst_streamid_demux_get_property; + gobject_class->dispose = gst_streamid_demux_dispose; + + g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, + g_param_spec_object ("active-pad", "Active pad", + "The currently active src pad", GST_TYPE_PAD, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, "Streamid Demux", + "Generic", "1-to-N output stream by stream-id", + "HoonHee Lee "); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_streamid_demux_sink_factory); + + gst_element_class_add_static_pad_template (gstelement_class, + &gst_streamid_demux_src_factory); + + gstelement_class->change_state = gst_streamid_demux_change_state; +} + +static void +gst_streamid_demux_init (GstStreamidDemux * demux) +{ + demux->sinkpad = + gst_pad_new_from_static_template (&gst_streamid_demux_sink_factory, + "sink"); + gst_pad_set_chain_function (demux->sinkpad, + GST_DEBUG_FUNCPTR (gst_streamid_demux_chain)); + gst_pad_set_event_function (demux->sinkpad, + GST_DEBUG_FUNCPTR (gst_streamid_demux_event)); + + gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad); + + /* srcpad management */ + demux->active_srcpad = NULL; + demux->nb_srcpads = 0; + + /* initialize hash table for srcpad */ + demux->stream_id_pairs = + g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, + (GDestroyNotify) gst_object_unref); +} + +static void +gst_streamid_demux_dispose (GObject * object) +{ + GstStreamidDemux *demux = GST_STREAMID_DEMUX (object); + + gst_streamid_demux_reset (demux); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_streamid_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamidDemux *demux = GST_STREAMID_DEMUX (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + GST_OBJECT_LOCK (demux); + g_value_set_object (value, demux->active_srcpad); + GST_OBJECT_UNLOCK (demux); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstPad *srcpad = GST_PAD_CAST (user_data); + + gst_pad_push_event (srcpad, gst_event_ref (*event)); + + return TRUE; +} + +static gboolean +gst_streamid_demux_srcpad_create (GstStreamidDemux * demux, GstPad * pad, + const gchar * stream_id) +{ + gchar *padname = NULL; + GstPad *srcpad = NULL; + GstPadTemplate *pad_tmpl = NULL; + + padname = g_strdup_printf ("src_%u", demux->nb_srcpads++); + pad_tmpl = gst_static_pad_template_get (&gst_streamid_demux_src_factory); + + GST_LOG_OBJECT (demux, "generating a srcpad:%s", padname); + srcpad = gst_pad_new_from_template (pad_tmpl, padname); + gst_object_unref (pad_tmpl); + g_free (padname); + g_return_val_if_fail (srcpad != NULL, FALSE); + + demux->active_srcpad = srcpad; + g_hash_table_insert (demux->stream_id_pairs, g_strdup (stream_id), + gst_object_ref (srcpad)); + + return TRUE; +} + +static GstFlowReturn +gst_streamid_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GstFlowReturn res = GST_FLOW_OK; + GstStreamidDemux *demux = NULL; + GstPad *srcpad = NULL; + + demux = GST_STREAMID_DEMUX (parent); + + GST_LOG_OBJECT (demux, "pushing buffer to %" GST_PTR_FORMAT, + demux->active_srcpad); + + GST_OBJECT_LOCK (demux); + if (demux->active_srcpad) { + srcpad = gst_object_ref (demux->active_srcpad); + GST_OBJECT_UNLOCK (demux); + res = gst_pad_push (srcpad, buf); + gst_object_unref (srcpad); + } else { + GST_OBJECT_UNLOCK (demux); + goto no_active_srcpad; + } + + GST_LOG_OBJECT (demux, "handled buffer %s", gst_flow_get_name (res)); + return res; + +/* ERROR */ +no_active_srcpad: + { + GST_WARNING_OBJECT (demux, "srcpad is not initialized"); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static GstPad * +gst_streamid_demux_get_srcpad_by_stream_id (GstStreamidDemux * demux, + const gchar * stream_id) +{ + GstPad *srcpad = NULL; + + GST_DEBUG_OBJECT (demux, "stream_id = %s", stream_id); + if (demux->stream_id_pairs == NULL || stream_id == NULL) { + goto done; + } + + srcpad = g_hash_table_lookup (demux->stream_id_pairs, stream_id); + + if (srcpad) { + GST_DEBUG_OBJECT (demux, "srcpad = %s:%s matched", + GST_DEBUG_PAD_NAME (srcpad)); + } + +done: + return srcpad; +} + +static gboolean +gst_streamid_demux_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + GstStreamidDemux *demux; + const gchar *stream_id = NULL; + GstPad *active_srcpad = NULL; + + demux = GST_STREAMID_DEMUX (parent); + + GST_DEBUG_OBJECT (demux, "event = %s, sticky = %d", + GST_EVENT_TYPE_NAME (event), GST_EVENT_IS_STICKY (event)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START) { + gst_event_parse_stream_start (event, &stream_id); + if (!stream_id) + goto no_stream_id; + + GST_OBJECT_LOCK (demux); + active_srcpad = + gst_streamid_demux_get_srcpad_by_stream_id (demux, stream_id); + if (!active_srcpad) { + /* try to generate a srcpad */ + if (gst_streamid_demux_srcpad_create (demux, pad, stream_id)) { + GST_OBJECT_UNLOCK (demux); + + gst_pad_set_active (demux->active_srcpad, TRUE); + /* Forward sticky events to the new srcpad */ + gst_pad_sticky_events_foreach (demux->sinkpad, forward_sticky_events, + demux->active_srcpad); + gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->active_srcpad); + } else { + GST_OBJECT_UNLOCK (demux); + goto fail_create_srcpad; + } + } else if (demux->active_srcpad != active_srcpad) { + demux->active_srcpad = active_srcpad; + GST_OBJECT_UNLOCK (demux); + + g_object_notify (G_OBJECT (demux), "active-pad"); + } else + GST_OBJECT_UNLOCK (demux); + } + + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START + || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP + || GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + res = gst_pad_event_default (pad, parent, event); + } else if (demux->active_srcpad) { + GstPad *srcpad = NULL; + GST_OBJECT_LOCK (demux); + srcpad = gst_object_ref (demux->active_srcpad); + GST_OBJECT_UNLOCK (demux); + res = gst_pad_push_event (srcpad, event); + gst_object_unref (srcpad); + } else { + gst_event_unref (event); + } + return res; + + /* ERRORS */ +no_stream_id: + { + GST_ELEMENT_ERROR (demux, STREAM, DEMUX, + ("Error occurred trying to get stream-id to create a srcpad"), + ("no stream-id found at %s", GST_EVENT_TYPE_NAME (event))); + + gst_event_unref (event); + return FALSE; + } + +fail_create_srcpad: + { + GST_ELEMENT_ERROR (demux, STREAM, FAILED, + ("Error occurred trying to create a srcpad"), + ("Failed to create a srcpad via stream-id:%s", stream_id)); + gst_event_unref (event); + return FALSE; + } +} + +static void +gst_streamid_demux_release_srcpad (const GValue * item, + GstStreamidDemux * demux) +{ + GstPad *pad = g_value_get_object (item); + + if (pad != NULL) { + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (demux), pad); + } +} + +static void +gst_streamid_demux_reset (GstStreamidDemux * demux) +{ + GstIterator *it = NULL; + GstIteratorResult itret = GST_ITERATOR_OK; + + GST_OBJECT_LOCK (demux); + if (demux->active_srcpad != NULL) + demux->active_srcpad = NULL; + + demux->nb_srcpads = 0; + GST_OBJECT_UNLOCK (demux); + + if (demux->stream_id_pairs != NULL) { + g_hash_table_unref (demux->stream_id_pairs); + demux->stream_id_pairs = NULL; + } + + it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (demux)); + while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) { + itret = + gst_iterator_foreach (it, + (GstIteratorForeachFunction) gst_streamid_demux_release_srcpad, demux); + if (itret == GST_ITERATOR_RESYNC) + gst_iterator_resync (it); + } + gst_iterator_free (it); +} + +static GstStateChangeReturn +gst_streamid_demux_change_state (GstElement * element, + GstStateChange transition) +{ + GstStreamidDemux *demux; + GstStateChangeReturn result; + + demux = GST_STREAMID_DEMUX (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_streamid_demux_reset (demux); + break; + default: + break; + } + + return result; +} diff --git a/plugins/elements/gststreamiddemux.h b/plugins/elements/gststreamiddemux.h new file mode 100644 index 0000000..e8b74a9 --- /dev/null +++ b/plugins/elements/gststreamiddemux.h @@ -0,0 +1,71 @@ +/* + * GStreamer streamiddemux eleement + * + * Copyright 2013 LGE Corporation. + * @author: Hoonhee Lee + * @author: Jeongseok Kim + * @author: Wonchul Lee + * + * gststreamiddemux.h: Simple stream-id-demultiplexer element + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __GST_STREAMID_DEMUX_H__ +#define __GST_STREAMID_DEMUX_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_STREAMID_DEMUX \ + (gst_streamid_demux_get_type()) +#define GST_STREAMID_DEMUX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAMID_DEMUX, GstStreamidDemux)) +#define GST_STREAMID_DEMUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_STREAMID_DEMUX, GstStreamidDemuxClass)) +#define GST_IS_STREAMID_DEMUX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAMID_DEMUX)) +#define GST_IS_STREAMID_DEMUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_STREAMID_DEMUX)) +typedef struct _GstStreamidDemux GstStreamidDemux; +typedef struct _GstStreamidDemuxClass GstStreamidDemuxClass; + +/** + * GstStreamidDemux: + * + * The opaque #GstStreamidDemux data structure. + */ +struct _GstStreamidDemux +{ + GstElement element; + + GstPad *sinkpad; + + guint nb_srcpads; + GstPad *active_srcpad; + + /* This table contains srcpad and stream-id */ + GHashTable *stream_id_pairs; +}; + +struct _GstStreamidDemuxClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_streamid_demux_get_type (void); + +G_END_DECLS +#endif /* __GST_STREAMID_DEMUX_H__ */ diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c new file mode 100644 index 0000000..b4aeb08 --- /dev/null +++ b/plugins/elements/gsttee.c @@ -0,0 +1,1241 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2001,2002,2003,2004,2005 Wim Taymans + * 2007 Wim Taymans + * + * gsttee.c: Tee element, one in N out + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-tee + * @title: tee + * @see_also: #GstIdentity + * + * Split data to multiple pads. Branching the data flow is useful when e.g. + * capturing a video where the video is shown on the screen and also encoded and + * written to a file. Another example is playing music and hooking up a + * visualisation module. + * + * One needs to use separate queue elements (or a multiqueue) in each branch to + * provide separate threads for each branch. Otherwise a blocked dataflow in one + * branch would stall the other branches. + * + * ## Example launch line + * |[ + * gst-launch-1.0 filesrc location=song.ogg ! decodebin ! tee name=t ! queue ! audioconvert ! audioresample ! autoaudiosink t. ! queue ! audioconvert ! goom ! videoconvert ! autovideosink + * ]| + * + * Play song.ogg audio file which must be in the current working directory + * and render visualisations using the goom element (this can be easier done + * using the playbin element, this is just an example pipeline). + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gsttee.h" +#include "gst/glib-compat-private.h" + +#include +#include + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_tee_debug); +#define GST_CAT_DEFAULT gst_tee_debug + +#define GST_TYPE_TEE_PULL_MODE (gst_tee_pull_mode_get_type()) +static GType +gst_tee_pull_mode_get_type (void) +{ + static GType type = 0; + static const GEnumValue data[] = { + {GST_TEE_PULL_MODE_NEVER, "Never activate in pull mode", "never"}, + {GST_TEE_PULL_MODE_SINGLE, "Only one src pad can be active in pull mode", + "single"}, + {0, NULL, NULL}, + }; + + if (!type) { + type = g_enum_register_static ("GstTeePullMode", data); + } + return type; +} + +#define DEFAULT_PROP_NUM_SRC_PADS 0 +#define DEFAULT_PROP_HAS_CHAIN TRUE +#define DEFAULT_PROP_SILENT TRUE +#define DEFAULT_PROP_LAST_MESSAGE NULL +#define DEFAULT_PULL_MODE GST_TEE_PULL_MODE_NEVER +#define DEFAULT_PROP_ALLOW_NOT_LINKED FALSE + +enum +{ + PROP_0, + PROP_NUM_SRC_PADS, + PROP_HAS_CHAIN, + PROP_SILENT, + PROP_LAST_MESSAGE, + PROP_PULL_MODE, + PROP_ALLOC_PAD, + PROP_ALLOW_NOT_LINKED, +}; + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src_%u", + GST_PAD_SRC, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element"); +#define gst_tee_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstTee, gst_tee, GST_TYPE_ELEMENT, _do_init); + +static GParamSpec *pspec_last_message = NULL; +static GParamSpec *pspec_alloc_pad = NULL; + +GType gst_tee_pad_get_type (void); + +#define GST_TYPE_TEE_PAD \ + (gst_tee_pad_get_type()) +#define GST_TEE_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEE_PAD, GstTeePad)) +#define GST_TEE_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEE_PAD, GstTeePadClass)) +#define GST_IS_TEE_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEE_PAD)) +#define GST_IS_TEE_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEE_PAD)) +#define GST_TEE_PAD_CAST(obj) \ + ((GstTeePad *)(obj)) + +typedef struct _GstTeePad GstTeePad; +typedef struct _GstTeePadClass GstTeePadClass; + +struct _GstTeePad +{ + GstPad parent; + + guint index; + gboolean pushed; + GstFlowReturn result; + gboolean removed; +}; + +struct _GstTeePadClass +{ + GstPadClass parent; +}; + +G_DEFINE_TYPE (GstTeePad, gst_tee_pad, GST_TYPE_PAD); + +static void +gst_tee_pad_class_init (GstTeePadClass * klass) +{ +} + +static void +gst_tee_pad_reset (GstTeePad * pad) +{ + pad->pushed = FALSE; + pad->result = GST_FLOW_NOT_LINKED; + pad->removed = FALSE; +} + +static void +gst_tee_pad_init (GstTeePad * pad) +{ + gst_tee_pad_reset (pad); +} + +static GstPad *gst_tee_request_new_pad (GstElement * element, + GstPadTemplate * temp, const gchar * unused, const GstCaps * caps); +static void gst_tee_release_pad (GstElement * element, GstPad * pad); + +static void gst_tee_finalize (GObject * object); +static void gst_tee_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tee_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_tee_dispose (GObject * object); + +static GstFlowReturn gst_tee_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list); +static gboolean gst_tee_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_tee_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_tee_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static GstFlowReturn gst_tee_src_get_range (GstPad * pad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buf); + +static void +gst_tee_dispose (GObject * object) +{ + GList *item; + +restart: + for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { + GstPad *pad = GST_PAD (item->data); + if (GST_PAD_IS_SRC (pad)) { + gst_element_release_request_pad (GST_ELEMENT (object), pad); + goto restart; + } + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_tee_finalize (GObject * object) +{ + GstTee *tee; + + tee = GST_TEE (object); + + g_hash_table_unref (tee->pad_indexes); + + g_free (tee->last_message); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_tee_class_init (GstTeeClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->finalize = gst_tee_finalize; + gobject_class->set_property = gst_tee_set_property; + gobject_class->get_property = gst_tee_get_property; + gobject_class->dispose = gst_tee_dispose; + + g_object_class_install_property (gobject_class, PROP_NUM_SRC_PADS, + g_param_spec_int ("num-src-pads", "Num Src Pads", + "The number of source pads", 0, G_MAXINT, DEFAULT_PROP_NUM_SRC_PADS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HAS_CHAIN, + g_param_spec_boolean ("has-chain", "Has Chain", + "If the element can operate in push mode", DEFAULT_PROP_HAS_CHAIN, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't produce last_message events", DEFAULT_PROP_SILENT, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "Last Message", + "The message describing current status", DEFAULT_PROP_LAST_MESSAGE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (gobject_class, PROP_PULL_MODE, + g_param_spec_enum ("pull-mode", "Pull mode", + "Behavior of tee in pull mode", GST_TYPE_TEE_PULL_MODE, + DEFAULT_PULL_MODE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_alloc_pad = g_param_spec_object ("alloc-pad", "Allocation Src Pad", + "The pad ALLOCATION queries will be proxied to (DEPRECATED, has no effect)", + GST_TYPE_PAD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED); + g_object_class_install_property (gobject_class, PROP_ALLOC_PAD, + pspec_alloc_pad); + + /** + * GstTee:allow-not-linked + * + * This property makes sink pad return GST_FLOW_OK even if there are no + * source pads or any of them is linked. + * + * This is useful to avoid errors when you have a dynamic pipeline and during + * a reconnection you can have all the pads unlinked or removed. + * + * Since: 1.6 + */ + g_object_class_install_property (gobject_class, PROP_ALLOW_NOT_LINKED, + g_param_spec_boolean ("allow-not-linked", "Allow not linked", + "Return GST_FLOW_OK even if there are no source pads or they are " + "all unlinked", DEFAULT_PROP_ALLOW_NOT_LINKED, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_set_static_metadata (gstelement_class, + "Tee pipe fitting", + "Generic", + "1-to-N pipe fitting", + "Erik Walthinsen , " "Wim Taymans "); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + gst_element_class_add_static_pad_template (gstelement_class, &src_template); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_tee_request_new_pad); + gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad); +} + +static void +gst_tee_init (GstTee * tee) +{ + tee->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); + tee->sink_mode = GST_PAD_MODE_NONE; + + gst_pad_set_event_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_sink_event)); + gst_pad_set_query_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_sink_query)); + gst_pad_set_activatemode_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_sink_activate_mode)); + gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain)); + gst_pad_set_chain_list_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_chain_list)); + GST_OBJECT_FLAG_SET (tee->sinkpad, GST_PAD_FLAG_PROXY_CAPS); + gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); + + tee->pad_indexes = g_hash_table_new (NULL, NULL); + + tee->last_message = NULL; +} + +static void +gst_tee_notify_alloc_pad (GstTee * tee) +{ + g_object_notify_by_pspec ((GObject *) tee, pspec_alloc_pad); +} + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstPad *srcpad = GST_PAD_CAST (user_data); + GstFlowReturn ret; + + ret = gst_pad_store_sticky_event (srcpad, *event); + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (srcpad, "storing sticky event %p (%s) failed: %s", *event, + GST_EVENT_TYPE_NAME (*event), gst_flow_get_name (ret)); + } + + return TRUE; +} + +static GstPad * +gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name_templ, const GstCaps * caps) +{ + gchar *name; + GstPad *srcpad; + GstTee *tee; + GstPadMode mode; + gboolean res; + guint index = 0; + + tee = GST_TEE (element); + + GST_DEBUG_OBJECT (tee, "requesting pad"); + + GST_OBJECT_LOCK (tee); + + if (name_templ && sscanf (name_templ, "src_%u", &index) == 1) { + GST_LOG_OBJECT (element, "name: %s (index %d)", name_templ, index); + if (g_hash_table_contains (tee->pad_indexes, GUINT_TO_POINTER (index))) { + GST_ERROR_OBJECT (element, "pad name %s is not unique", name_templ); + GST_OBJECT_UNLOCK (tee); + return NULL; + } + if (index >= tee->next_pad_index) + tee->next_pad_index = index + 1; + } else { + index = tee->next_pad_index; + + while (g_hash_table_contains (tee->pad_indexes, GUINT_TO_POINTER (index))) + index++; + + tee->next_pad_index = index + 1; + } + + g_hash_table_insert (tee->pad_indexes, GUINT_TO_POINTER (index), NULL); + + name = g_strdup_printf ("src_%u", index); + + srcpad = GST_PAD_CAST (g_object_new (GST_TYPE_TEE_PAD, + "name", name, "direction", templ->direction, "template", templ, + NULL)); + GST_TEE_PAD_CAST (srcpad)->index = index; + g_free (name); + + mode = tee->sink_mode; + + GST_OBJECT_UNLOCK (tee); + + switch (mode) { + case GST_PAD_MODE_PULL: + /* we already have a src pad in pull mode, and our pull mode can only be + SINGLE, so fall through to activate this new pad in push mode */ + case GST_PAD_MODE_PUSH: + res = gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); + break; + default: + res = TRUE; + break; + } + + if (!res) + goto activate_failed; + + gst_pad_set_activatemode_function (srcpad, + GST_DEBUG_FUNCPTR (gst_tee_src_activate_mode)); + gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query)); + gst_pad_set_getrange_function (srcpad, + GST_DEBUG_FUNCPTR (gst_tee_src_get_range)); + GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS); + /* Forward sticky events to the new srcpad */ + gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad); + gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad); + + return srcpad; + + /* ERRORS */ +activate_failed: + { + gboolean changed = FALSE; + + GST_OBJECT_LOCK (tee); + GST_DEBUG_OBJECT (tee, "warning failed to activate request pad"); + if (tee->allocpad == srcpad) { + tee->allocpad = NULL; + changed = TRUE; + } + GST_OBJECT_UNLOCK (tee); + gst_object_unref (srcpad); + if (changed) { + gst_tee_notify_alloc_pad (tee); + } + return NULL; + } +} + +static void +gst_tee_release_pad (GstElement * element, GstPad * pad) +{ + GstTee *tee; + gboolean changed = FALSE; + guint index; + + tee = GST_TEE (element); + + GST_DEBUG_OBJECT (tee, "releasing pad"); + + GST_OBJECT_LOCK (tee); + index = GST_TEE_PAD_CAST (pad)->index; + /* mark the pad as removed so that future pad_alloc fails with NOT_LINKED. */ + GST_TEE_PAD_CAST (pad)->removed = TRUE; + if (tee->allocpad == pad) { + tee->allocpad = NULL; + changed = TRUE; + } + GST_OBJECT_UNLOCK (tee); + + gst_object_ref (pad); + gst_element_remove_pad (GST_ELEMENT_CAST (tee), pad); + + gst_pad_set_active (pad, FALSE); + + gst_object_unref (pad); + + if (changed) { + gst_tee_notify_alloc_pad (tee); + } + + GST_OBJECT_LOCK (tee); + g_hash_table_remove (tee->pad_indexes, GUINT_TO_POINTER (index)); + GST_OBJECT_UNLOCK (tee); +} + +static void +gst_tee_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstTee *tee = GST_TEE (object); + + GST_OBJECT_LOCK (tee); + switch (prop_id) { + case PROP_HAS_CHAIN: + tee->has_chain = g_value_get_boolean (value); + break; + case PROP_SILENT: + tee->silent = g_value_get_boolean (value); + break; + case PROP_PULL_MODE: + tee->pull_mode = (GstTeePullMode) g_value_get_enum (value); + break; + case PROP_ALLOC_PAD: + { + GstPad *pad = g_value_get_object (value); + GST_OBJECT_LOCK (pad); + if (GST_OBJECT_PARENT (pad) == GST_OBJECT_CAST (object)) + tee->allocpad = pad; + else + GST_WARNING_OBJECT (object, "Tried to set alloc pad %s which" + " is not my pad", GST_OBJECT_NAME (pad)); + GST_OBJECT_UNLOCK (pad); + break; + } + case PROP_ALLOW_NOT_LINKED: + tee->allow_not_linked = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (tee); +} + +static void +gst_tee_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstTee *tee = GST_TEE (object); + + GST_OBJECT_LOCK (tee); + switch (prop_id) { + case PROP_NUM_SRC_PADS: + g_value_set_int (value, GST_ELEMENT (tee)->numsrcpads); + break; + case PROP_HAS_CHAIN: + g_value_set_boolean (value, tee->has_chain); + break; + case PROP_SILENT: + g_value_set_boolean (value, tee->silent); + break; + case PROP_LAST_MESSAGE: + g_value_set_string (value, tee->last_message); + break; + case PROP_PULL_MODE: + g_value_set_enum (value, tee->pull_mode); + break; + case PROP_ALLOC_PAD: + g_value_set_object (value, tee->allocpad); + break; + case PROP_ALLOW_NOT_LINKED: + g_value_set_boolean (value, tee->allow_not_linked); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (tee); +} + +static gboolean +gst_tee_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res; + + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_event_default (pad, parent, event); + break; + } + + return res; +} + +struct AllocQueryCtx +{ + GstTee *tee; + GstQuery *query; + GstAllocationParams params; + guint size; + guint min_buffers; + gboolean first_query; + guint num_pads; +}; + +/* This function will aggregate some of the allocation query information with + * the strategy to force upstream allocation. Depending on downstream + * allocation would otherwise make dynamic pipelines much more complicated as + * application would need to now drain buffer in certain cases before getting + * rid of a tee branch. */ +static gboolean +gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data) +{ + struct AllocQueryCtx *ctx = user_data; + GstPad *src_pad = g_value_get_object (item); + GstPad *peer_pad; + GstCaps *caps; + GstQuery *query; + guint count, i, size, min; + + GST_DEBUG_OBJECT (ctx->tee, "Aggregating allocation from pad %s:%s", + GST_DEBUG_PAD_NAME (src_pad)); + + peer_pad = gst_pad_get_peer (src_pad); + if (!peer_pad) { + if (ctx->tee->allow_not_linked) { + GST_DEBUG_OBJECT (ctx->tee, "Pad %s:%s has no peer, but allowed.", + GST_DEBUG_PAD_NAME (src_pad)); + return TRUE; + } else { + GST_DEBUG_OBJECT (ctx->tee, "Pad %s:%s has no peer, ignoring allocation.", + GST_DEBUG_PAD_NAME (src_pad)); + g_value_set_boolean (ret, FALSE); + return FALSE; + } + } + + gst_query_parse_allocation (ctx->query, &caps, NULL); + + query = gst_query_new_allocation (caps, FALSE); + if (!gst_pad_query (peer_pad, query)) { + GST_DEBUG_OBJECT (ctx->tee, + "Allocation query failed on pad %s, ignoring allocation", + GST_PAD_NAME (src_pad)); + g_value_set_boolean (ret, FALSE); + gst_query_unref (query); + gst_object_unref (peer_pad); + return FALSE; + } + + gst_object_unref (peer_pad); + + /* Allocation Params: + * store the maximum alignment, prefix and pading, but ignore the + * allocators and the flags which are tied to downstream allocation */ + count = gst_query_get_n_allocation_params (query); + for (i = 0; i < count; i++) { + GstAllocationParams params = { 0, }; + + gst_query_parse_nth_allocation_param (query, i, NULL, ¶ms); + + GST_DEBUG_OBJECT (ctx->tee, "Aggregating AllocationParams align=%" + G_GSIZE_FORMAT " prefix=%" G_GSIZE_FORMAT " padding=%" + G_GSIZE_FORMAT, params.align, params.prefix, params.padding); + + if (ctx->params.align < params.align) + ctx->params.align = params.align; + + if (ctx->params.prefix < params.prefix) + ctx->params.prefix = params.prefix; + + if (ctx->params.padding < params.padding) + ctx->params.padding = params.padding; + } + + /* Allocation Pool: + * We want to keep the biggest size and biggest minimum number of buffers to + * make sure downstream requirement can be satisfied. We don't really care + * about the maximum, as this is a parameter of the downstream provided + * pool. We only read the first allocation pool as the minimum number of + * buffers is normally constant regardless of the pool being used. */ + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, NULL, &size, &min, NULL); + + GST_DEBUG_OBJECT (ctx->tee, + "Aggregating allocation pool size=%u min_buffers=%u", size, min); + + if (ctx->size < size) + ctx->size = size; + + if (ctx->min_buffers < min) + ctx->min_buffers = min; + } + + /* Allocation Meta: + * For allocation meta, we'll need to aggregate the argument using the new + * GstMetaInfo::agggregate_func */ + count = gst_query_get_n_allocation_metas (query); + for (i = 0; i < count; i++) { + guint ctx_index; + GType api; + const GstStructure *param; + + api = gst_query_parse_nth_allocation_meta (query, i, ¶m); + + /* For the first query, copy all metas */ + if (ctx->first_query) { + gst_query_add_allocation_meta (ctx->query, api, param); + continue; + } + + /* Afterward, aggregate the common params */ + if (gst_query_find_allocation_meta (ctx->query, api, &ctx_index)) { + const GstStructure *ctx_param; + + gst_query_parse_nth_allocation_meta (ctx->query, ctx_index, &ctx_param); + + /* Keep meta which has no params */ + if (ctx_param == NULL && param == NULL) + continue; + + GST_DEBUG_OBJECT (ctx->tee, "Dropping allocation meta %s", + g_type_name (api)); + gst_query_remove_nth_allocation_meta (ctx->query, ctx_index); + } + } + + /* Finally, cleanup metas from the stored query that aren't support on this + * pad. */ + count = gst_query_get_n_allocation_metas (ctx->query); + for (i = 0; i < count;) { + GType api = gst_query_parse_nth_allocation_meta (ctx->query, i, NULL); + + if (!gst_query_find_allocation_meta (query, api, NULL)) { + GST_DEBUG_OBJECT (ctx->tee, "Dropping allocation meta %s", + g_type_name (api)); + gst_query_remove_nth_allocation_meta (ctx->query, i); + count--; + continue; + } + + i++; + } + + ctx->first_query = FALSE; + ctx->num_pads++; + gst_query_unref (query); + + return TRUE; +} + + +static void +gst_tee_clear_query_allocation_meta (GstQuery * query) +{ + guint count = gst_query_get_n_allocation_metas (query); + guint i; + + for (i = 1; i <= count; i++) + gst_query_remove_nth_allocation_meta (query, count - i); +} + +static gboolean +gst_tee_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstTee *tee = GST_TEE (parent); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ALLOCATION: + { + GstIterator *iter; + GValue ret = G_VALUE_INIT; + struct AllocQueryCtx ctx = { tee, query, }; + + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, TRUE); + + ctx.first_query = TRUE; + gst_allocation_params_init (&ctx.params); + + iter = gst_element_iterate_src_pads (GST_ELEMENT (tee)); + while (GST_ITERATOR_RESYNC == + gst_iterator_fold (iter, gst_tee_query_allocation, &ret, &ctx)) { + gst_iterator_resync (iter); + ctx.first_query = TRUE; + gst_allocation_params_init (&ctx.params); + ctx.size = 0; + ctx.min_buffers = 0; + ctx.num_pads = 0; + gst_tee_clear_query_allocation_meta (query); + } + + gst_iterator_free (iter); + res = g_value_get_boolean (&ret); + g_value_unset (&ret); + + if (res) { + GST_DEBUG_OBJECT (tee, "Aggregated AllocationParams to align=%" + G_GSIZE_FORMAT " prefix=%" G_GSIZE_FORMAT " padding=%" + G_GSIZE_FORMAT, ctx.params.align, ctx.params.prefix, + ctx.params.padding); + + GST_DEBUG_OBJECT (tee, + "Aggregated allocation pools size=%u min_buffers=%u", ctx.size, + ctx.min_buffers); + +#ifndef GST_DISABLE_GST_DEBUG + { + guint count = gst_query_get_n_allocation_metas (query); + guint i; + + GST_DEBUG_OBJECT (tee, "Aggregated %u allocation meta:", count); + + for (i = 0; i < count; i++) + GST_DEBUG_OBJECT (tee, " + aggregated allocation meta %s", + g_type_name (gst_query_parse_nth_allocation_meta (ctx.query, i, + NULL))); + } +#endif + + /* Allocate one more buffers when multiplexing so we don't starve the + * downstream threads. */ + if (ctx.num_pads > 1) + ctx.min_buffers++; + + /* Check that we actually have parameters besides the defaults. */ + if (ctx.params.align || ctx.params.prefix || ctx.params.padding) { + gst_query_add_allocation_param (ctx.query, NULL, &ctx.params); + } + /* When size == 0, buffers created from this pool would have no memory + * allocated. */ + if (ctx.size) { + gst_query_add_allocation_pool (ctx.query, NULL, ctx.size, + ctx.min_buffers, 0); + } + } else { + gst_tee_clear_query_allocation_meta (query); + } + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + return res; +} + +static void +gst_tee_do_message (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list) +{ + GST_OBJECT_LOCK (tee); + g_free (tee->last_message); + if (is_list) { + tee->last_message = + g_strdup_printf ("chain-list ******* (%s:%s)t %p", + GST_DEBUG_PAD_NAME (pad), data); + } else { + tee->last_message = + g_strdup_printf ("chain ******* (%s:%s)t (%" G_GSIZE_FORMAT + " bytes, %" G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad), + gst_buffer_get_size (data), GST_BUFFER_TIMESTAMP (data), data); + } + GST_OBJECT_UNLOCK (tee); + + g_object_notify_by_pspec ((GObject *) tee, pspec_last_message); +} + +static GstFlowReturn +gst_tee_do_push (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list) +{ + GstFlowReturn res; + + /* Push */ + if (pad == tee->pull_pad) { + /* don't push on the pad we're pulling from */ + res = GST_FLOW_OK; + } else if (is_list) { + res = + gst_pad_push_list (pad, + gst_buffer_list_ref (GST_BUFFER_LIST_CAST (data))); + } else { + res = gst_pad_push (pad, gst_buffer_ref (GST_BUFFER_CAST (data))); + } + return res; +} + +static void +clear_pads (GstPad * pad, GstTee * tee) +{ + GST_TEE_PAD_CAST (pad)->pushed = FALSE; + GST_TEE_PAD_CAST (pad)->result = GST_FLOW_NOT_LINKED; +} + +static GstFlowReturn +gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list) +{ + GList *pads; + guint32 cookie; + GstFlowReturn ret, cret; + + if (G_UNLIKELY (!tee->silent)) + gst_tee_do_message (tee, tee->sinkpad, data, is_list); + + GST_OBJECT_LOCK (tee); + pads = GST_ELEMENT_CAST (tee)->srcpads; + + /* special case for zero pads */ + if (G_UNLIKELY (!pads)) + goto no_pads; + + /* special case for just one pad that avoids reffing the buffer */ + if (!pads->next) { + GstPad *pad = GST_PAD_CAST (pads->data); + + /* Keep another ref around, a pad probe + * might release and destroy the pad */ + gst_object_ref (pad); + GST_OBJECT_UNLOCK (tee); + + if (pad == tee->pull_pad) { + ret = GST_FLOW_OK; + } else if (is_list) { + ret = gst_pad_push_list (pad, GST_BUFFER_LIST_CAST (data)); + } else { + ret = gst_pad_push (pad, GST_BUFFER_CAST (data)); + } + + if (GST_TEE_PAD_CAST (pad)->removed) + ret = GST_FLOW_NOT_LINKED; + + if (ret == GST_FLOW_NOT_LINKED && tee->allow_not_linked) { + ret = GST_FLOW_OK; + } + + gst_object_unref (pad); + + return ret; + } + + /* mark all pads as 'not pushed on yet' */ + g_list_foreach (pads, (GFunc) clear_pads, tee); + +restart: + if (tee->allow_not_linked) { + cret = GST_FLOW_OK; + } else { + cret = GST_FLOW_NOT_LINKED; + } + pads = GST_ELEMENT_CAST (tee)->srcpads; + cookie = GST_ELEMENT_CAST (tee)->pads_cookie; + + while (pads) { + GstPad *pad; + + pad = GST_PAD_CAST (pads->data); + + if (G_LIKELY (!GST_TEE_PAD_CAST (pad)->pushed)) { + /* not yet pushed, release lock and start pushing */ + gst_object_ref (pad); + GST_OBJECT_UNLOCK (tee); + + GST_LOG_OBJECT (pad, "Starting to push %s %p", + is_list ? "list" : "buffer", data); + + ret = gst_tee_do_push (tee, pad, data, is_list); + + GST_LOG_OBJECT (pad, "Pushing item %p yielded result %s", data, + gst_flow_get_name (ret)); + + GST_OBJECT_LOCK (tee); + /* keep track of which pad we pushed and the result value */ + GST_TEE_PAD_CAST (pad)->pushed = TRUE; + GST_TEE_PAD_CAST (pad)->result = ret; + gst_object_unref (pad); + pad = NULL; + } else { + /* already pushed, use previous return value */ + ret = GST_TEE_PAD_CAST (pad)->result; + GST_LOG_OBJECT (pad, "pad already pushed with %s", + gst_flow_get_name (ret)); + } + + /* before we go combining the return value, check if the pad list is still + * the same. It could be possible that the pad we just pushed was removed + * and the return value it not valid anymore */ + if (G_UNLIKELY (GST_ELEMENT_CAST (tee)->pads_cookie != cookie)) { + GST_LOG_OBJECT (tee, "pad list changed"); + /* the list of pads changed, restart iteration. Pads that we already + * pushed on and are still in the new list, will not be pushed on + * again. */ + goto restart; + } + + /* stop pushing more buffers when we have a fatal error */ + if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) + goto error; + + /* keep all other return values, overwriting the previous one. */ + if (G_LIKELY (ret != GST_FLOW_NOT_LINKED)) { + GST_LOG_OBJECT (tee, "Replacing ret val %d with %d", cret, ret); + cret = ret; + } + pads = g_list_next (pads); + } + GST_OBJECT_UNLOCK (tee); + + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + + /* no need to unset gvalue */ + return cret; + + /* ERRORS */ +no_pads: + { + if (tee->allow_not_linked) { + GST_DEBUG_OBJECT (tee, "there are no pads, dropping %s", + is_list ? "buffer-list" : "buffer"); + ret = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (tee, "there are no pads, return not-linked"); + ret = GST_FLOW_NOT_LINKED; + } + goto end; + } +error: + { + GST_DEBUG_OBJECT (tee, "received error %s", gst_flow_get_name (ret)); + goto end; + } +end: + { + GST_OBJECT_UNLOCK (tee); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return ret; + } +} + +static GstFlowReturn +gst_tee_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstFlowReturn res; + GstTee *tee; + + tee = GST_TEE_CAST (parent); + + GST_DEBUG_OBJECT (tee, "received buffer %p", buffer); + + res = gst_tee_handle_data (tee, buffer, FALSE); + + GST_DEBUG_OBJECT (tee, "handled buffer %s", gst_flow_get_name (res)); + + return res; +} + +static GstFlowReturn +gst_tee_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list) +{ + GstFlowReturn res; + GstTee *tee; + + tee = GST_TEE_CAST (parent); + + GST_DEBUG_OBJECT (tee, "received list %p", list); + + res = gst_tee_handle_data (tee, list, TRUE); + + GST_DEBUG_OBJECT (tee, "handled list %s", gst_flow_get_name (res)); + + return res; +} + +static gboolean +gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean res; + GstTee *tee; + + tee = GST_TEE (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + { + GST_OBJECT_LOCK (tee); + tee->sink_mode = active ? mode : GST_PAD_MODE_NONE; + + if (active && !tee->has_chain) + goto no_chain; + GST_OBJECT_UNLOCK (tee); + res = TRUE; + break; + } + default: + res = FALSE; + break; + } + return res; + + /* ERRORS */ +no_chain: + { + GST_OBJECT_UNLOCK (tee); + GST_INFO_OBJECT (tee, + "Tee cannot operate in push mode with has-chain==FALSE"); + return FALSE; + } +} + +static gboolean +gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + GstTee *tee; + gboolean res; + GstPad *sinkpad; + + tee = GST_TEE (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + { + GST_OBJECT_LOCK (tee); + + if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) + goto cannot_pull; + + if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad) + goto cannot_pull_multiple_srcs; + + sinkpad = gst_object_ref (tee->sinkpad); + + GST_OBJECT_UNLOCK (tee); + + res = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, active); + gst_object_unref (sinkpad); + + if (!res) + goto sink_activate_failed; + + GST_OBJECT_LOCK (tee); + if (active) { + if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE) + tee->pull_pad = pad; + } else { + if (pad == tee->pull_pad) + tee->pull_pad = NULL; + } + tee->sink_mode = (active ? GST_PAD_MODE_PULL : GST_PAD_MODE_NONE); + GST_OBJECT_UNLOCK (tee); + break; + } + default: + res = TRUE; + break; + } + + return res; + + /* ERRORS */ +cannot_pull: + { + GST_OBJECT_UNLOCK (tee); + GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode " + "set to NEVER"); + return FALSE; + } +cannot_pull_multiple_srcs: + { + GST_OBJECT_UNLOCK (tee); + GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, " + "pull-mode set to SINGLE"); + return FALSE; + } +sink_activate_failed: + { + GST_INFO_OBJECT (tee, "Failed to %sactivate sink pad in pull mode", + active ? "" : "de"); + return FALSE; + } +} + +static gboolean +gst_tee_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstTee *tee; + gboolean res; + GstPad *sinkpad; + + tee = GST_TEE (parent); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + { + gboolean pull_mode; + + GST_OBJECT_LOCK (tee); + pull_mode = TRUE; + if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) { + GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode " + "set to NEVER"); + pull_mode = FALSE; + } else if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && tee->pull_pad) { + GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, " + "pull-mode set to SINGLE"); + pull_mode = FALSE; + } + + sinkpad = gst_object_ref (tee->sinkpad); + GST_OBJECT_UNLOCK (tee); + + if (pull_mode) { + /* ask peer if we can operate in pull mode */ + res = gst_pad_peer_query (sinkpad, query); + } else { + res = TRUE; + } + gst_object_unref (sinkpad); + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + + return res; +} + +static void +gst_tee_push_eos (const GValue * vpad, GstTee * tee) +{ + GstPad *pad = g_value_get_object (vpad); + + if (pad != tee->pull_pad) + gst_pad_push_event (pad, gst_event_new_eos ()); +} + +static void +gst_tee_pull_eos (GstTee * tee) +{ + GstIterator *iter; + + iter = gst_element_iterate_src_pads (GST_ELEMENT (tee)); + while (gst_iterator_foreach (iter, + (GstIteratorForeachFunction) gst_tee_push_eos, + tee) == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); + gst_iterator_free (iter); +} + +static GstFlowReturn +gst_tee_src_get_range (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) +{ + GstTee *tee; + GstFlowReturn ret; + + tee = GST_TEE (parent); + + ret = gst_pad_pull_range (tee->sinkpad, offset, length, buf); + + if (ret == GST_FLOW_OK) + ret = gst_tee_handle_data (tee, gst_buffer_ref (*buf), FALSE); + else if (ret == GST_FLOW_EOS) + gst_tee_pull_eos (tee); + + return ret; +} diff --git a/plugins/elements/gsttee.h b/plugins/elements/gsttee.h new file mode 100644 index 0000000..e4ce310 --- /dev/null +++ b/plugins/elements/gsttee.h @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gsttee.h: Header for GstTee 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TEE_H__ +#define __GST_TEE_H__ + +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_TEE \ + (gst_tee_get_type()) +#define GST_TEE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEE,GstTee)) +#define GST_TEE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEE,GstTeeClass)) +#define GST_IS_TEE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEE)) +#define GST_IS_TEE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEE)) +#define GST_TEE_CAST(obj) ((GstTee*) obj) + +typedef struct _GstTee GstTee; +typedef struct _GstTeeClass GstTeeClass; + +/** + * GstTeePullMode: + * @GST_TEE_PULL_MODE_NEVER: Never activate in pull mode. + * @GST_TEE_PULL_MODE_SINGLE: Only one src pad can be active in pull mode. + * + * The different ways that tee can behave in pull mode. @TEE_PULL_MODE_NEVER + * disables pull mode. + */ +typedef enum { + GST_TEE_PULL_MODE_NEVER, + GST_TEE_PULL_MODE_SINGLE, +} GstTeePullMode; + +/** + * GstTee: + * + * Opaque #GstTee data structure. + */ +struct _GstTee { + GstElement element; + + /*< private >*/ + GstPad *sinkpad; + GstPad *allocpad; + + GHashTable *pad_indexes; + guint next_pad_index; + + gboolean has_chain; + gboolean silent; + gchar *last_message; + + GstPadMode sink_mode; + GstTeePullMode pull_mode; + GstPad *pull_pad; + + gboolean allow_not_linked; +}; + +struct _GstTeeClass { + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_tee_get_type (void); + +G_END_DECLS + +#endif /* __GST_TEE_H__ */ diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c new file mode 100644 index 0000000..5da2d75 --- /dev/null +++ b/plugins/elements/gsttypefindelement.c @@ -0,0 +1,1343 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefindelement.c: element that detects type of stream + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-typefind + * @title: typefind + * + * Determines the media-type of a stream. It applies typefind functions in the + * order of their rank. Once the type has been detected it sets its src pad caps + * to the found media type. + * + * Whenever a type is found the #GstTypeFindElement::have-type signal is + * emitted, either from the streaming thread or the application thread + * (the latter may happen when typefinding is done pull-based from the + * state change function). + * + * Plugins can register custom typefinders by using #GstTypeFindFactory. + */ + +/* FIXME: need a better solution for non-seekable streams */ + +/* way of operation: + * 1) get a list of all typefind functions sorted best to worst + * 2) if all elements have been called with all requested data goto 8 + * 3) call all functions once with all available data + * 4) if a function returns a value >= PROP_MAXIMUM goto 8 (never implemented)) + * 5) all functions with a result > PROP_MINIMUM or functions that did not get + * all requested data (where peek returned NULL) stay in list + * 6) seek to requested offset of best function that still has open data + * requests + * 7) goto 2 + * 8) take best available result and use its caps + * + * The element has two scheduling modes: + * + * 1) chain based, it will collect buffers and run the typefind function on + * the buffer until something is found. + * 2) getrange based, it will proxy the getrange function to the sinkpad. It + * is assumed that the peer element is happy with whatever format we + * eventually read. + * + * By default it tries to do pull based typefinding (this avoids joining + * received buffers and holding them back in store.) + * + * When the element has no connected srcpad, and the sinkpad can operate in + * getrange based mode, the element starts its own task to figure out the + * type of the stream. + * + * Most of the actual implementation is in libs/gst/base/gsttypefindhelper.c. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst/gst_private.h" + +#include "gsttypefindelement.h" +#include "gst/gst-i18n-lib.h" +#include "gst/base/gsttypefindhelper.h" + +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug); +#define GST_CAT_DEFAULT gst_type_find_element_debug + +/* generic templates */ +static GstStaticPadTemplate type_find_element_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate type_find_element_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +/* Require at least 2kB of data before we attempt typefinding in chain-mode. + * 128kB is massive overkill for the maximum, but doesn't do any harm */ +#define TYPE_FIND_MIN_SIZE (2*1024) +#define TYPE_FIND_MAX_SIZE (128*1024) + +/* TypeFind signals and args */ +enum +{ + HAVE_TYPE, + LAST_SIGNAL +}; +enum +{ + PROP_0, + PROP_CAPS, + PROP_MINIMUM, + PROP_FORCE_CAPS, + PROP_LAST +}; +enum +{ + MODE_NORMAL, /* act as identity */ + MODE_TYPEFIND, /* do typefinding */ + MODE_ERROR /* had fatal error */ +}; + + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind", \ + GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element"); +#define gst_type_find_element_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstTypeFindElement, gst_type_find_element, + GST_TYPE_ELEMENT, _do_init); + +static void gst_type_find_element_dispose (GObject * object); +static void gst_type_find_element_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_type_find_element_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static gboolean gst_type_find_element_src_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_type_find_handle_src_query (GstPad * pad, + GstObject * parent, GstQuery * query); + +static gboolean gst_type_find_element_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_type_find_element_setcaps (GstTypeFindElement * typefind, + GstCaps * caps); +static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad, + GstObject * parent, GstBuffer * buffer); +static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad, + GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer); + +static GstStateChangeReturn +gst_type_find_element_change_state (GstElement * element, + GstStateChange transition); +static gboolean gst_type_find_element_activate_sink (GstPad * pad, + GstObject * parent); +static gboolean gst_type_find_element_activate_sink_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_type_find_element_activate_src_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static GstFlowReturn +gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, + gboolean check_avail, gboolean at_eos); +static void gst_type_find_element_send_cached_events (GstTypeFindElement * + typefind); + +static void gst_type_find_element_loop (GstPad * pad); + +static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 }; + +static void +gst_type_find_element_have_type (GstTypeFindElement * typefind, + guint probability, GstCaps * caps) +{ + GstEvent *event; + + g_assert (caps != NULL); + + GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u", + caps, probability); + + /* Do nothing if downstream is pulling from us */ + if (GST_PAD_MODE (typefind->src) == GST_PAD_MODE_PULL) + return; + + GST_OBJECT_LOCK (typefind); + + /* Now actually send the CAPS event downstream. + * + * Try to directly send the CAPS event downstream that we created in + * gst_type_find_element_emit_have_type() if it is still there, instead + * of creating a new one. No need to create an equivalent one, replacing + * it in the sticky event list and possibly causing renegotiation + */ + event = gst_pad_get_sticky_event (typefind->src, GST_EVENT_CAPS, 0); + if (event) { + GstCaps *event_caps; + + gst_event_parse_caps (event, &event_caps); + if (caps != event_caps) { + gst_event_unref (event); + event = gst_event_new_caps (caps); + } + } else { + event = gst_event_new_caps (caps); + } + + GST_OBJECT_UNLOCK (typefind); + + gst_pad_push_event (typefind->src, event); +} + +static void +gst_type_find_element_emit_have_type (GstTypeFindElement * typefind, + guint probability, GstCaps * caps) +{ + GstEvent *event; + + /* Update caps field immediatly so that caps queries and properties can be + * honored in all "have-type" signal handlers. + */ + GST_OBJECT_LOCK (typefind); + if (typefind->caps) + gst_caps_unref (typefind->caps); + typefind->caps = gst_caps_ref (caps); + GST_OBJECT_UNLOCK (typefind); + + /* Only store the caps event at this point. We give signal handlers + * the chance to look at the caps before they are sent downstream. + * They are only forwarded downstream later in the default signal + * handler after all application signal handlers + */ + event = gst_event_new_caps (caps); + gst_pad_store_sticky_event (typefind->src, event); + gst_event_unref (event); + + g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, + probability, caps); +} + +static void +gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class); + + gobject_class->set_property = gst_type_find_element_set_property; + gobject_class->get_property = gst_type_find_element_get_property; + gobject_class->dispose = gst_type_find_element_dispose; + + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", _("caps"), + _("detected capabilities in stream"), GST_TYPE_CAPS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MINIMUM, + g_param_spec_uint ("minimum", _("minimum"), + "minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM, + GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FORCE_CAPS, + g_param_spec_boxed ("force-caps", _("force caps"), + _("force caps without doing a typefind"), GST_TYPE_CAPS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstTypeFindElement::have-type: + * @typefind: the typefind instance + * @probability: the probability of the type found + * @caps: the caps of the type found + * + * This signal gets emitted when the type and its probability has + * been found. + */ + gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type", + G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE); + + typefind_class->have_type = + GST_DEBUG_FUNCPTR (gst_type_find_element_have_type); + + gst_element_class_set_static_metadata (gstelement_class, + "TypeFind", + "Generic", + "Finds the media type of a stream", + "Benjamin Otte "); + gst_element_class_add_static_pad_template (gstelement_class, + &type_find_element_src_template); + gst_element_class_add_static_pad_template (gstelement_class, + &type_find_element_sink_template); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_type_find_element_change_state); +} + +static void +gst_type_find_element_init (GstTypeFindElement * typefind) +{ + /* sinkpad */ + typefind->sink = + gst_pad_new_from_static_template (&type_find_element_sink_template, + "sink"); + + gst_pad_set_activate_function (typefind->sink, + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink)); + gst_pad_set_activatemode_function (typefind->sink, + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink_mode)); + gst_pad_set_chain_function (typefind->sink, + GST_DEBUG_FUNCPTR (gst_type_find_element_chain)); + gst_pad_set_event_function (typefind->sink, + GST_DEBUG_FUNCPTR (gst_type_find_element_sink_event)); + GST_PAD_SET_PROXY_ALLOCATION (typefind->sink); + gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink); + + /* srcpad */ + typefind->src = + gst_pad_new_from_static_template (&type_find_element_src_template, "src"); + + gst_pad_set_activatemode_function (typefind->src, + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_mode)); + gst_pad_set_getrange_function (typefind->src, + GST_DEBUG_FUNCPTR (gst_type_find_element_getrange)); + gst_pad_set_event_function (typefind->src, + GST_DEBUG_FUNCPTR (gst_type_find_element_src_event)); + gst_pad_set_query_function (typefind->src, + GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query)); + gst_pad_use_fixed_caps (typefind->src); + gst_element_add_pad (GST_ELEMENT (typefind), typefind->src); + + typefind->mode = MODE_TYPEFIND; + typefind->caps = NULL; + typefind->min_probability = 1; + + typefind->adapter = gst_adapter_new (); +} + +static void +gst_type_find_element_dispose (GObject * object) +{ + GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object); + + if (typefind->adapter) { + g_object_unref (typefind->adapter); + typefind->adapter = NULL; + } + + if (typefind->force_caps) { + gst_caps_unref (typefind->force_caps); + typefind->force_caps = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_type_find_element_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (object); + + switch (prop_id) { + case PROP_MINIMUM: + typefind->min_probability = g_value_get_uint (value); + break; + case PROP_FORCE_CAPS: + GST_OBJECT_LOCK (typefind); + if (typefind->force_caps) + gst_caps_unref (typefind->force_caps); + typefind->force_caps = g_value_dup_boxed (value); + GST_OBJECT_UNLOCK (typefind); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_type_find_element_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (object); + + switch (prop_id) { + case PROP_CAPS: + GST_OBJECT_LOCK (typefind); + g_value_set_boxed (value, typefind->caps); + GST_OBJECT_UNLOCK (typefind); + break; + case PROP_MINIMUM: + g_value_set_uint (value, typefind->min_probability); + break; + case PROP_FORCE_CAPS: + GST_OBJECT_LOCK (typefind); + g_value_set_boxed (value, typefind->force_caps); + GST_OBJECT_UNLOCK (typefind); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_type_find_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + GstTypeFindElement *typefind; + gboolean res = FALSE; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + GST_DEBUG_OBJECT (typefind, "Handling src query %s", + GST_QUERY_TYPE_NAME (query)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + /* FIXME, filter out the scheduling modes that we understand */ + res = gst_pad_peer_query (typefind->sink, query); + break; + case GST_QUERY_CAPS: + { + GST_DEBUG_OBJECT (typefind, + "Got caps query, our caps are %" GST_PTR_FORMAT, typefind->caps); + + /* We can hijack caps query if we typefind already */ + if (typefind->caps) { + gst_query_set_caps_result (query, typefind->caps); + res = TRUE; + } else { + res = gst_pad_peer_query (typefind->sink, query); + } + break; + } + case GST_QUERY_POSITION: + { + gint64 peer_pos; + GstFormat format; + + if (!(res = gst_pad_peer_query (typefind->sink, query))) + goto out; + + gst_query_parse_position (query, &format, &peer_pos); + + GST_OBJECT_LOCK (typefind); + /* FIXME: this code assumes that there's no discont in the queue */ + switch (format) { + case GST_FORMAT_BYTES: + peer_pos -= gst_adapter_available (typefind->adapter); + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; + break; + default: + /* FIXME */ + break; + } + GST_OBJECT_UNLOCK (typefind); + gst_query_set_position (query, format, peer_pos); + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } +out: + return res; +} + +static gboolean +gst_type_find_element_seek (GstTypeFindElement * typefind, GstEvent * event) +{ + GstSeekFlags flags; + GstSeekType start_type, stop_type; + GstFormat format; + gboolean flush; + gdouble rate; + gint64 start, stop; + GstSegment seeksegment = { 0, }; + + gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, + &stop_type, &stop); + + /* we can only seek on bytes */ + if (format != GST_FORMAT_BYTES) { + GST_DEBUG_OBJECT (typefind, "Can only seek on BYTES"); + return FALSE; + } + + /* copy segment, we need this because we still need the old + * segment when we close the current segment. */ + memcpy (&seeksegment, &typefind->segment, sizeof (GstSegment)); + + GST_DEBUG_OBJECT (typefind, "configuring seek"); + gst_segment_do_seek (&seeksegment, rate, format, flags, + start_type, start, stop_type, stop, NULL); + + flush = ! !(flags & GST_SEEK_FLAG_FLUSH); + + GST_DEBUG_OBJECT (typefind, "New segment %" GST_SEGMENT_FORMAT, &seeksegment); + + if (flush) { + GST_DEBUG_OBJECT (typefind, "Starting flush"); + gst_pad_push_event (typefind->sink, gst_event_new_flush_start ()); + gst_pad_push_event (typefind->src, gst_event_new_flush_start ()); + } else { + GST_DEBUG_OBJECT (typefind, "Non-flushing seek, pausing task"); + gst_pad_pause_task (typefind->sink); + } + + /* 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_DEBUG_OBJECT (typefind, "Waiting for streaming to stop"); + GST_PAD_STREAM_LOCK (typefind->sink); + + if (flush) { + GST_DEBUG_OBJECT (typefind, "Stopping flush"); + gst_pad_push_event (typefind->sink, gst_event_new_flush_stop (TRUE)); + gst_pad_push_event (typefind->src, gst_event_new_flush_stop (TRUE)); + } + + /* now update the real segment info */ + GST_DEBUG_OBJECT (typefind, "Committing new seek segment"); + memcpy (&typefind->segment, &seeksegment, sizeof (GstSegment)); + typefind->offset = typefind->segment.start; + + /* notify start of new segment */ + if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { + GstMessage *msg; + + msg = gst_message_new_segment_start (GST_OBJECT (typefind), + GST_FORMAT_BYTES, typefind->segment.start); + gst_element_post_message (GST_ELEMENT (typefind), msg); + } + + typefind->need_segment = TRUE; + + /* restart our task since it might have been stopped when we did the + * flush. */ + gst_pad_start_task (typefind->sink, + (GstTaskFunction) gst_type_find_element_loop, typefind->sink, NULL); + + /* streaming can continue now */ + GST_PAD_STREAM_UNLOCK (typefind->sink); + + return TRUE; +} + +static gboolean +gst_type_find_element_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent); + gboolean result; + + if (typefind->mode != MODE_NORMAL) { + /* need to do more? */ + GST_LOG_OBJECT (typefind, "Still typefinding. Not passing event upstream"); + gst_event_unref (event); + return FALSE; + } + + /* Only handle seeks here if driving the pipeline */ + if (typefind->segment.format != GST_FORMAT_UNDEFINED && + GST_EVENT_TYPE (event) == GST_EVENT_SEEK) { + result = gst_type_find_element_seek (typefind, event); + gst_event_unref (event); + return result; + } else { + return gst_pad_push_event (typefind->sink, event); + } +} + +static void +start_typefinding (GstTypeFindElement * typefind) +{ + GST_DEBUG_OBJECT (typefind, "starting typefinding"); + + GST_OBJECT_LOCK (typefind); + if (typefind->caps) + gst_caps_replace (&typefind->caps, NULL); + typefind->initial_offset = GST_BUFFER_OFFSET_NONE; + GST_OBJECT_UNLOCK (typefind); + + typefind->mode = MODE_TYPEFIND; +} + +static void +stop_typefinding (GstTypeFindElement * typefind) +{ + GstState state; + gboolean push_cached_buffers; + gsize avail; + GstBuffer *buffer; + GstClockTime pts, dts; + + gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0); + + push_cached_buffers = (state >= GST_STATE_PAUSED && typefind->caps); + + GST_DEBUG_OBJECT (typefind, "stopping typefinding%s", + push_cached_buffers ? " and pushing cached events and buffers" : ""); + + typefind->mode = MODE_NORMAL; + if (push_cached_buffers) + gst_type_find_element_send_cached_events (typefind); + + GST_OBJECT_LOCK (typefind); + avail = gst_adapter_available (typefind->adapter); + if (avail == 0) + goto no_data; + + pts = gst_adapter_prev_pts (typefind->adapter, NULL); + dts = gst_adapter_prev_dts (typefind->adapter, NULL); + buffer = gst_adapter_take_buffer (typefind->adapter, avail); + GST_BUFFER_PTS (buffer) = pts; + GST_BUFFER_DTS (buffer) = dts; + GST_BUFFER_OFFSET (buffer) = typefind->initial_offset; + GST_OBJECT_UNLOCK (typefind); + + if (!push_cached_buffers) { + gst_buffer_unref (buffer); + } else { + GstPad *peer = gst_pad_get_peer (typefind->src); + + /* make sure the user gets a meaningful error message in this case, + * which is not a core bug or bug of any kind (as the default error + * message emitted by gstpad.c otherwise would make you think) */ + if (peer && GST_PAD_CHAINFUNC (peer) == NULL) { + GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while " + "downstream element only works in pull mode, erroring out"); + GST_ELEMENT_ERROR (typefind, STREAM, FAILED, + ("%s cannot work in push mode. The operation is not supported " + "with this source element or protocol.", + G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))), + ("Downstream pad %s:%s has no chainfunction, and the upstream " + "element does not support pull mode", GST_DEBUG_PAD_NAME (peer))); + typefind->mode = MODE_ERROR; /* make the chain function error out */ + gst_buffer_unref (buffer); + } else { + gst_pad_push (typefind->src, buffer); + } + if (peer) + gst_object_unref (peer); + } + return; + + /* ERRORS */ +no_data: + { + GST_DEBUG_OBJECT (typefind, "we have no data to typefind"); + GST_OBJECT_UNLOCK (typefind); + return; + } +} + +static gboolean +gst_type_find_element_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + gboolean res = FALSE; + GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent); + + GST_DEBUG_OBJECT (typefind, "got %s event in mode %d", + GST_EVENT_TYPE_NAME (event), typefind->mode); + + switch (typefind->mode) { + case MODE_TYPEFIND: + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + /* Parse and push out our caps and data */ + gst_event_parse_caps (event, &caps); + res = gst_type_find_element_setcaps (typefind, caps); + + gst_event_unref (event); + break; + } + case GST_EVENT_GAP: + { + GST_FIXME_OBJECT (typefind, + "GAP events during typefinding not handled properly"); + + /* FIXME: These would need to be inserted in the stream at + * the right position between buffers, but we combine all + * buffers with a GstAdapter. Drop the GAP event for now, + * which will only cause an implicit GAP between buffers. + */ + gst_event_unref (event); + res = TRUE; + break; + } + case GST_EVENT_EOS: + { + GST_INFO_OBJECT (typefind, "Got EOS and no type found yet"); + gst_type_find_element_chain_do_typefinding (typefind, FALSE, TRUE); + + res = gst_pad_push_event (typefind->src, event); + break; + } + case GST_EVENT_FLUSH_STOP:{ + GList *l; + + GST_OBJECT_LOCK (typefind); + + for (l = typefind->cached_events; l; l = l->next) { + if (GST_EVENT_IS_STICKY (l->data) && + GST_EVENT_TYPE (l->data) != GST_EVENT_SEGMENT && + GST_EVENT_TYPE (l->data) != GST_EVENT_EOS) { + gst_pad_store_sticky_event (typefind->src, l->data); + } + gst_event_unref (l->data); + } + + g_list_free (typefind->cached_events); + typefind->cached_events = NULL; + gst_adapter_clear (typefind->adapter); + GST_OBJECT_UNLOCK (typefind); + /* fall through */ + } + case GST_EVENT_FLUSH_START: + res = gst_pad_push_event (typefind->src, event); + break; + default: + /* Forward events that would happen before the caps event + * directly instead of storing them. There's no reason not + * to send them directly and we should only store events + * for later sending that would need to come after the caps + * event */ + if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) { + res = gst_pad_push_event (typefind->src, event); + } else { + GST_DEBUG_OBJECT (typefind, "Saving %s event to send later", + GST_EVENT_TYPE_NAME (event)); + GST_OBJECT_LOCK (typefind); + typefind->cached_events = + g_list_append (typefind->cached_events, event); + GST_OBJECT_UNLOCK (typefind); + res = TRUE; + } + break; + } + break; + case MODE_NORMAL: + res = gst_pad_push_event (typefind->src, event); + break; + case MODE_ERROR: + break; + default: + g_assert_not_reached (); + } + return res; +} + +static void +gst_type_find_element_send_cached_events (GstTypeFindElement * typefind) +{ + GList *l, *cached_events; + + GST_OBJECT_LOCK (typefind); + cached_events = typefind->cached_events; + typefind->cached_events = NULL; + GST_OBJECT_UNLOCK (typefind); + + for (l = cached_events; l != NULL; l = l->next) { + GstEvent *event = GST_EVENT (l->data); + + GST_DEBUG_OBJECT (typefind, "sending cached %s event", + GST_EVENT_TYPE_NAME (event)); + gst_pad_push_event (typefind->src, event); + } + g_list_free (cached_events); +} + +static gboolean +gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps) +{ + /* don't operate on ANY caps */ + if (gst_caps_is_any (caps)) + return TRUE; + + /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */ + typefind->mode = MODE_NORMAL; + gst_type_find_element_emit_have_type (typefind, GST_TYPE_FIND_MAXIMUM, caps); + + /* Shortcircuit typefinding if we get caps */ + GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from " + "upstream: %" GST_PTR_FORMAT, caps); + + stop_typefinding (typefind); + + return TRUE; +} + +static gchar * +gst_type_find_get_extension (GstTypeFindElement * typefind, GstPad * pad) +{ + GstQuery *query; + gchar *uri, *result; + size_t len; + gint find; + + query = gst_query_new_uri (); + + /* try getting the caps with an uri query and from the extension */ + if (!gst_pad_peer_query (pad, query)) + goto peer_query_failed; + + gst_query_parse_uri (query, &uri); + if (uri == NULL) + goto no_uri; + + GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri); + + /* find the extension on the uri, this is everything after a '.' */ + len = strlen (uri); + find = len - 1; + + while (find >= 0) { + if (uri[find] == '.') + break; + find--; + } + if (find < 0) + goto no_extension; + + result = g_strdup (&uri[find + 1]); + + GST_DEBUG_OBJECT (typefind, "found extension %s", result); + gst_query_unref (query); + g_free (uri); + + return result; + + /* ERRORS */ +peer_query_failed: + { + GST_WARNING_OBJECT (typefind, "failed to query peer uri"); + gst_query_unref (query); + return NULL; + } +no_uri: + { + GST_WARNING_OBJECT (typefind, "could not parse the peer uri"); + gst_query_unref (query); + return NULL; + } +no_extension: + { + GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri); + gst_query_unref (query); + g_free (uri); + return NULL; + } +} + +static GstCaps * +gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad, + GstTypeFindProbability * probability) +{ + gchar *ext; + GstCaps *caps; + + ext = gst_type_find_get_extension (typefind, pad); + if (!ext) + return NULL; + + caps = gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind), ext); + if (caps) + *probability = GST_TYPE_FIND_MAXIMUM; + + g_free (ext); + + return caps; +} + +static GstFlowReturn +gst_type_find_element_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer) +{ + GstTypeFindElement *typefind; + GstFlowReturn res = GST_FLOW_OK; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + + GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode); + + switch (typefind->mode) { + case MODE_ERROR: + /* we should already have called GST_ELEMENT_ERROR */ + return GST_FLOW_ERROR; + case MODE_NORMAL: + /* don't take object lock as typefind->caps should not change anymore */ + return gst_pad_push (typefind->src, buffer); + case MODE_TYPEFIND: + { + GST_OBJECT_LOCK (typefind); + if (typefind->initial_offset == GST_BUFFER_OFFSET_NONE) + typefind->initial_offset = GST_BUFFER_OFFSET (buffer); + gst_adapter_push (typefind->adapter, buffer); + GST_OBJECT_UNLOCK (typefind); + + res = gst_type_find_element_chain_do_typefinding (typefind, TRUE, FALSE); + + if (typefind->mode == MODE_ERROR) + res = GST_FLOW_ERROR; + + break; + } + default: + g_assert_not_reached (); + return GST_FLOW_ERROR; + } + + return res; +} + +static GstFlowReturn +gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, + gboolean check_avail, gboolean at_eos) +{ + GstTypeFindProbability probability; + GstCaps *caps = NULL; + gsize avail; + const guint8 *data; + gboolean have_min, have_max; + + GST_OBJECT_LOCK (typefind); + if (typefind->force_caps) { + caps = gst_caps_ref (typefind->force_caps); + probability = GST_TYPE_FIND_MAXIMUM; + } + + if (!caps) { + avail = gst_adapter_available (typefind->adapter); + + if (check_avail) { + have_min = avail >= TYPE_FIND_MIN_SIZE; + have_max = avail >= TYPE_FIND_MAX_SIZE; + } else { + have_min = avail > 0; + have_max = TRUE; + } + + if (!have_min) + goto not_enough_data; + + /* map all available data */ + data = gst_adapter_map (typefind->adapter, avail); + caps = gst_type_find_helper_for_data (GST_OBJECT (typefind), + data, avail, &probability); + gst_adapter_unmap (typefind->adapter); + + if (caps == NULL && have_max) + goto no_type_found; + else if (caps == NULL) + goto wait_for_data; + + /* found a type */ + if (probability < typefind->min_probability) + goto low_probability; + } + + GST_OBJECT_UNLOCK (typefind); + + /* probability is good enough too, so let's make it known ... emiting this + * signal calls our object handler which sets the caps. */ + /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */ + typefind->mode = MODE_NORMAL; + gst_type_find_element_emit_have_type (typefind, probability, caps); + + /* .. and send out the accumulated data */ + stop_typefinding (typefind); + gst_caps_unref (caps); + + return GST_FLOW_OK; + +not_enough_data: + { + GST_OBJECT_UNLOCK (typefind); + + if (at_eos) { + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, + (_("Stream doesn't contain enough data.")), + ("Can't typefind stream")); + return GST_FLOW_ERROR; + } else { + GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet " + "(%" G_GSIZE_FORMAT " bytes)", avail); + return GST_FLOW_OK; + } + } +no_type_found: + { + GST_OBJECT_UNLOCK (typefind); + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); + stop_typefinding (typefind); + return GST_FLOW_ERROR; + } +wait_for_data: + { + GST_OBJECT_UNLOCK (typefind); + + if (at_eos) { + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, + (_("Stream doesn't contain enough data.")), + ("Can't typefind stream")); + return GST_FLOW_ERROR; + } else { + GST_DEBUG_OBJECT (typefind, + "no caps found with %" G_GSIZE_FORMAT " bytes of data, " + "waiting for more data", avail); + return GST_FLOW_OK; + } + } +low_probability: + { + GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but " + "probability is %u which is lower than the required minimum of %u", + caps, probability, typefind->min_probability); + + gst_caps_unref (caps); + + if (have_max) + goto no_type_found; + + GST_OBJECT_UNLOCK (typefind); + GST_DEBUG_OBJECT (typefind, "waiting for more data to try again"); + return GST_FLOW_OK; + } +} + +static GstFlowReturn +gst_type_find_element_getrange (GstPad * srcpad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buffer) +{ + GstTypeFindElement *typefind; + GstFlowReturn ret; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + + ret = gst_pad_pull_range (typefind->sink, offset, length, buffer); + + return ret; +} + +static gboolean +gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + /* make sure our task stops pushing, we can't call _stop here because this + * activation might happen from the streaming thread. */ + gst_pad_pause_task (typefind->sink); + res = gst_pad_activate_mode (typefind->sink, mode, active); + break; + default: + res = TRUE; + break; + } + return res; +} + +static void +gst_type_find_element_loop (GstPad * pad) +{ + GstTypeFindElement *typefind; + GstFlowReturn ret = GST_FLOW_OK; + + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + + if (typefind->need_stream_start) { + gchar *stream_id; + GstEvent *event; + + stream_id = gst_pad_create_stream_id (typefind->src, + GST_ELEMENT_CAST (typefind), NULL); + + GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START"); + event = gst_event_new_stream_start (stream_id); + gst_event_set_group_id (event, gst_util_group_id_next ()); + gst_pad_push_event (typefind->src, event); + + typefind->need_stream_start = FALSE; + g_free (stream_id); + } + + if (typefind->mode == MODE_TYPEFIND) { + GstPad *peer = NULL; + GstCaps *found_caps = NULL; + GstTypeFindProbability probability = GST_TYPE_FIND_NONE; + + GST_DEBUG_OBJECT (typefind, "find type in pull mode"); + + GST_OBJECT_LOCK (typefind); + if (typefind->force_caps) { + found_caps = gst_caps_ref (typefind->force_caps); + probability = GST_TYPE_FIND_MAXIMUM; + } + GST_OBJECT_UNLOCK (typefind); + + if (!found_caps) { + peer = gst_pad_get_peer (pad); + if (peer) { + gint64 size; + gchar *ext; + + if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) { + GST_WARNING_OBJECT (typefind, "Could not query upstream length!"); + gst_object_unref (peer); + + ret = GST_FLOW_ERROR; + goto pause; + } + + /* the size if 0, we cannot continue */ + if (size == 0) { + /* keep message in sync with message in sink event handler */ + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, + (_("Stream contains no data.")), ("Can't typefind empty stream")); + gst_object_unref (peer); + ret = GST_FLOW_ERROR; + goto pause; + } + ext = gst_type_find_get_extension (typefind, pad); + + found_caps = + gst_type_find_helper_get_range (GST_OBJECT_CAST (peer), + GST_OBJECT_PARENT (peer), + (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)), + (guint64) size, ext, &probability); + g_free (ext); + + GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps); + + gst_object_unref (peer); + } + } + + if (!found_caps || probability < typefind->min_probability) { + GST_DEBUG ("Trying to guess using extension"); + gst_caps_replace (&found_caps, NULL); + found_caps = + gst_type_find_guess_by_extension (typefind, pad, &probability); + } + + if (!found_caps || probability < typefind->min_probability) { + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); + gst_caps_replace (&found_caps, NULL); + ret = GST_FLOW_ERROR; + goto pause; + } + + GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); + /* Set to MODE_NORMAL before emitting have-type, in case it triggers a seek */ + typefind->mode = MODE_NORMAL; + gst_type_find_element_emit_have_type (typefind, probability, found_caps); + gst_caps_unref (found_caps); + } else if (typefind->mode == MODE_NORMAL) { + GstBuffer *outbuf = NULL; + + if (typefind->need_segment) { + typefind->need_segment = FALSE; + gst_pad_push_event (typefind->src, + gst_event_new_segment (&typefind->segment)); + } + + /* Pull 4k blocks and send downstream */ + ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf); + if (ret != GST_FLOW_OK) + goto pause; + + typefind->offset += gst_buffer_get_size (outbuf); + + ret = gst_pad_push (typefind->src, outbuf); + if (ret != GST_FLOW_OK) + goto pause; + } else { + /* Error out */ + ret = GST_FLOW_ERROR; + goto pause; + } + + return; + +pause: + { + const gchar *reason = gst_flow_get_name (ret); + gboolean push_eos = FALSE; + + GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason); + gst_pad_pause_task (typefind->sink); + + if (ret == GST_FLOW_EOS) { + /* perform EOS logic */ + + if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { + gint64 stop; + + /* for segment playback we need to post when (in stream time) + * we stopped, this is either stop (when set) or the duration. */ + if ((stop = typefind->segment.stop) == -1) + stop = typefind->offset; + + GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment"); + gst_element_post_message (GST_ELEMENT (typefind), + gst_message_new_segment_done (GST_OBJECT (typefind), + GST_FORMAT_BYTES, stop)); + gst_pad_push_event (typefind->src, + gst_event_new_segment_done (GST_FORMAT_BYTES, stop)); + } else { + push_eos = TRUE; + } + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { + /* for fatal errors we post an error message */ + GST_ELEMENT_FLOW_ERROR (typefind, ret); + push_eos = TRUE; + } + if (push_eos) { + /* send EOS, and prevent hanging if no streams yet */ + GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream"); + gst_pad_push_event (typefind->src, gst_event_new_eos ()); + } + return; + } +} + +static gboolean +gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + if (active) { + gst_segment_init (&typefind->segment, GST_FORMAT_BYTES); + typefind->need_segment = TRUE; + typefind->need_stream_start = TRUE; + typefind->offset = 0; + res = TRUE; + } else { + res = gst_pad_stop_task (pad); + gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED); + } + break; + case GST_PAD_MODE_PUSH: + if (active) { + gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED); + start_typefinding (typefind); + } else { + stop_typefinding (typefind); + gst_segment_init (&typefind->segment, GST_FORMAT_UNDEFINED); + } + res = TRUE; + break; + default: + res = FALSE; + break; + } + return res; +} + +static gboolean +gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) +{ + GstQuery *query; + gboolean pull_mode; + + query = gst_query_new_scheduling (); + + if (!gst_pad_peer_query (pad, query)) { + gst_query_unref (query); + goto typefind_push; + } + + pull_mode = gst_query_has_scheduling_mode_with_flags (query, + GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); + + gst_query_unref (query); + + if (!pull_mode) + goto typefind_push; + + if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) + goto typefind_push; + + /* only start our task if we ourselves decide to start in pull mode */ + return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop, + pad, NULL); + +typefind_push: + { + return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); + } +} + +static GstStateChangeReturn +gst_type_find_element_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (element); + + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + GST_OBJECT_LOCK (typefind); + gst_caps_replace (&typefind->caps, NULL); + + g_list_foreach (typefind->cached_events, + (GFunc) gst_mini_object_unref, NULL); + g_list_free (typefind->cached_events); + typefind->cached_events = NULL; + typefind->mode = MODE_TYPEFIND; + GST_OBJECT_UNLOCK (typefind); + break; + default: + break; + } + + return ret; +} diff --git a/plugins/elements/gsttypefindelement.h b/plugins/elements/gsttypefindelement.h new file mode 100644 index 0000000..0152622 --- /dev/null +++ b/plugins/elements/gsttypefindelement.h @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gsttypefindelement.h: element that detects type of stream + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TYPE_FIND_ELEMENT_H__ +#define __GST_TYPE_FIND_ELEMENT_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TYPE_FIND_ELEMENT (gst_type_find_element_get_type ()) +#define GST_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElement)) +#define GST_IS_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TYPE_FIND_ELEMENT)) +#define GST_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElementClass)) +#define GST_IS_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TYPE_FIND_ELEMENT)) + +typedef struct _GstTypeFindElement GstTypeFindElement; +typedef struct _GstTypeFindElementClass GstTypeFindElementClass; + +/** + * GstTypeFindElement: + * + * Opaque #GstTypeFindElement data structure + */ +struct _GstTypeFindElement { + GstElement element; + + GstPad * sink; + GstPad * src; + + guint min_probability; + GstCaps * caps; + + guint mode; + GstAdapter * adapter; + + GList * cached_events; + GstCaps * force_caps; + + guint64 initial_offset; + + /* Only used when driving the pipeline */ + gboolean need_segment; + gboolean need_stream_start; + GstSegment segment; + guint64 offset; +}; + +struct _GstTypeFindElementClass { + GstElementClass parent_class; + + /* signals */ + void (*have_type) (GstTypeFindElement *element, + guint probability, + GstCaps *caps); +}; + +G_GNUC_INTERNAL GType gst_type_find_element_get_type (void); + +G_END_DECLS + +#endif /* __GST_TYPE_FIND_ELEMENT_H__ */ diff --git a/plugins/elements/gstvalve.c b/plugins/elements/gstvalve.c new file mode 100644 index 0000000..9dbc7a6 --- /dev/null +++ b/plugins/elements/gstvalve.c @@ -0,0 +1,257 @@ +/* GStreamer valve element + * Copyright 2007-2009 Collabora Ltd + * @author: Olivier Crete + * Copyright 2007-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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +/** + * SECTION:element-valve + * @title: valve + * + * The valve is a simple element that drops buffers when the #GstValve:drop + * property is set to %TRUE and lets then through otherwise. + * + * Any downstream error received while the #GstValve:drop property is %TRUE + * is ignored. So downstream element can be set to %GST_STATE_NULL and removed, + * without using pad blocking. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvalve.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (valve_debug); +#define GST_CAT_DEFAULT (valve_debug) + +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); + +enum +{ + PROP_0, + PROP_DROP +}; + +#define DEFAULT_DROP FALSE + +static void gst_valve_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_valve_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_valve_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_valve_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_valve_query (GstPad * pad, GstObject * parent, + GstQuery * query); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve"); +#define gst_valve_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstValve, gst_valve, GST_TYPE_ELEMENT, _do_init); + +static void +gst_valve_class_init (GstValveClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) (klass); + + gobject_class->set_property = gst_valve_set_property; + gobject_class->get_property = gst_valve_get_property; + + g_object_class_install_property (gobject_class, PROP_DROP, + g_param_spec_boolean ("drop", "Drop buffers and events", + "Whether to drop buffers and events or let them through", + DEFAULT_DROP, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + + gst_element_class_set_static_metadata (gstelement_class, "Valve element", + "Filter", "Drops buffers and events or lets them through", + "Olivier Crete "); +} + +static void +gst_valve_init (GstValve * valve) +{ + valve->drop = FALSE; + valve->discont = FALSE; + + valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + gst_pad_set_query_function (valve->srcpad, + GST_DEBUG_FUNCPTR (gst_valve_query)); + GST_PAD_SET_PROXY_CAPS (valve->srcpad); + gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad); + + valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); + gst_pad_set_chain_function (valve->sinkpad, + GST_DEBUG_FUNCPTR (gst_valve_chain)); + gst_pad_set_event_function (valve->sinkpad, + GST_DEBUG_FUNCPTR (gst_valve_sink_event)); + gst_pad_set_query_function (valve->sinkpad, + GST_DEBUG_FUNCPTR (gst_valve_query)); + GST_PAD_SET_PROXY_CAPS (valve->sinkpad); + GST_PAD_SET_PROXY_ALLOCATION (valve->sinkpad); + gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad); +} + + +static void +gst_valve_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstValve *valve = GST_VALVE (object); + + switch (prop_id) { + case PROP_DROP: + g_atomic_int_set (&valve->drop, g_value_get_boolean (value)); + gst_pad_push_event (valve->sinkpad, gst_event_new_reconfigure ()); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_valve_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstValve *valve = GST_VALVE (object); + + switch (prop_id) { + case PROP_DROP: + g_value_set_boolean (value, g_atomic_int_get (&valve->drop)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstValve *valve = user_data; + + if (!gst_pad_push_event (valve->srcpad, gst_event_ref (*event))) + valve->need_repush_sticky = TRUE; + + return TRUE; +} + +static void +gst_valve_repush_sticky (GstValve * valve) +{ + valve->need_repush_sticky = FALSE; + gst_pad_sticky_events_foreach (valve->sinkpad, forward_sticky_events, valve); +} + +static GstFlowReturn +gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstValve *valve = GST_VALVE (parent); + GstFlowReturn ret = GST_FLOW_OK; + + if (g_atomic_int_get (&valve->drop)) { + gst_buffer_unref (buffer); + valve->discont = TRUE; + } else { + if (valve->discont) { + buffer = gst_buffer_make_writable (buffer); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + valve->discont = FALSE; + } + + if (valve->need_repush_sticky) + gst_valve_repush_sticky (valve); + + ret = gst_pad_push (valve->srcpad, buffer); + } + + + /* Ignore errors if "drop" was changed while the thread was blocked + * downwards + */ + if (g_atomic_int_get (&valve->drop)) + ret = GST_FLOW_OK; + + return ret; +} + + +static gboolean +gst_valve_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstValve *valve; + gboolean is_sticky = GST_EVENT_IS_STICKY (event); + gboolean ret = TRUE; + + valve = GST_VALVE (parent); + + if (g_atomic_int_get (&valve->drop)) { + valve->need_repush_sticky |= is_sticky; + gst_event_unref (event); + } else { + if (valve->need_repush_sticky) + gst_valve_repush_sticky (valve); + ret = gst_pad_event_default (pad, parent, event); + } + + /* Ignore errors if "drop" was changed while the thread was blocked + * downwards. + */ + if (g_atomic_int_get (&valve->drop)) { + valve->need_repush_sticky |= is_sticky; + ret = TRUE; + } + + return ret; +} + + + +static gboolean +gst_valve_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstValve *valve = GST_VALVE (parent); + + if (GST_QUERY_IS_SERIALIZED (query) && g_atomic_int_get (&valve->drop)) + return FALSE; + + return gst_pad_query_default (pad, parent, query); +} diff --git a/plugins/elements/gstvalve.h b/plugins/elements/gstvalve.h new file mode 100644 index 0000000..eb3c29e --- /dev/null +++ b/plugins/elements/gstvalve.h @@ -0,0 +1,77 @@ +/* GStreamer valve element + * + * Copyright 2007 Collabora Ltd, + * Copyright 2007 Nokia Corporation + * @author: Olivier Crete + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef __GST_VALVE_H__ +#define __GST_VALVE_H__ + +#include + +G_BEGIN_DECLS +/* #define's don't like whitespacey bits */ +#define GST_TYPE_VALVE \ + (gst_valve_get_type()) +#define GST_VALVE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_TYPE_VALVE,GstValve)) +#define GST_VALVE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_TYPE_VALVE,GstValveClass)) +#define GST_IS_VALVE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VALVE)) +#define GST_IS_VALVE_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VALVE)) + +typedef struct _GstValve GstValve; +typedef struct _GstValveClass GstValveClass; + +/** + * GstValve: + * + * The private valve structure + */ +struct _GstValve +{ + /*< private >*/ + GstElement parent; + + /* atomic boolean */ + volatile gint drop; + + /* Protected by the stream lock */ + gboolean discont; + gboolean need_repush_sticky; + + GstPad *srcpad; + GstPad *sinkpad; +}; + +struct _GstValveClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_valve_get_type (void); + +G_END_DECLS + +#endif /* __GST_VALVE_H__ */ diff --git a/plugins/elements/meson.build b/plugins/elements/meson.build new file mode 100644 index 0000000..3518fcc --- /dev/null +++ b/plugins/elements/meson.build @@ -0,0 +1,50 @@ +gst_elements_sources = [ + 'gstcapsfilter.c', + 'gstconcat.c', + 'gstdataurisrc.c', + 'gstdownloadbuffer.c', + 'gstelements.c', + 'gstelements_private.c', + 'gstfakesink.c', + 'gstfakesrc.c', + 'gstfdsink.c', + 'gstfdsrc.c', + 'gstfilesrc.c', + 'gstfilesink.c', + 'gstfunnel.c', + 'gstidentity.c', + 'gstinputselector.c', + 'gstmultiqueue.c', + 'gstoutputselector.c', + 'gstqueue2.c', + 'gstqueue.c', + 'gstsparsefile.c', + 'gststreamiddemux.c', + 'gsttee.c', + 'gsttypefindelement.c', + 'gstvalve.c', +] + +if libtype != 'shared' + gst_elements_static = static_library('gstcoreelements', + gst_elements_sources, + c_args : gst_c_args, + include_directories : [configinc], + dependencies : [gobject_dep, glib_dep, gst_dep, gst_base_dep], + install : true, + install_dir : join_paths(get_option('libdir'), 'gstreamer-1.0'), + ) + gst_elements = gst_elements_static +endif + +if libtype != 'static' + gst_elements_shared = shared_library('gstcoreelements', + gst_elements_sources, + c_args : gst_c_args, + include_directories : [configinc], + dependencies : [gobject_dep, glib_dep, gst_dep, gst_base_dep], + install : true, + install_dir : join_paths(get_option('libdir'), 'gstreamer-1.0'), + ) + gst_elements = gst_elements_shared +endif diff --git a/plugins/meson.build b/plugins/meson.build new file mode 100644 index 0000000..cb65dc0 --- /dev/null +++ b/plugins/meson.build @@ -0,0 +1,4 @@ +subdir('elements') +if not disable_tracer_hooks + subdir('tracers') +endif diff --git a/plugins/tracers/Makefile.am b/plugins/tracers/Makefile.am new file mode 100644 index 0000000..576ccd5 --- /dev/null +++ b/plugins/tracers/Makefile.am @@ -0,0 +1,43 @@ + +plugin_LTLIBRARIES = libgstcoretracers.la + +if HAVE_GETRUSAGE +RUSAGE_SOURCES = gstrusage.c +else +RUSAGE_SOURCES = +endif + +if GST_DISABLE_GST_DEBUG +LOG_SOURCES = +else +LOG_SOURCES = gstlog.c +endif + +libgstcoretracers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la +libgstcoretracers_la_SOURCES = \ + gstlatency.c \ + gstleaks.c \ + $(LOG_SOURCES) \ + $(RUSAGE_SOURCES) \ + gststats.c \ + gsttracers.c + +libgstcoretracers_la_CFLAGS = $(GST_OBJ_CFLAGS) \ + -DGST_USE_UNSTABLE_API +libgstcoretracers_la_LIBADD = $(GST_OBJ_LIBS) +libgstcoretracers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = \ + gstlatency.h \ + gstleaks.h \ + gstlog.h \ + gstrusage.h \ + gststats.h + +CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out + +%.c.gcov: .libs/libgstcoretracers_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcoretracers_la_SOURCES:=.gcov) + diff --git a/plugins/tracers/Makefile.in b/plugins/tracers/Makefile.in new file mode 100644 index 0000000..244f7bd --- /dev/null +++ b/plugins/tracers/Makefile.in @@ -0,0 +1,932 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = plugins/tracers +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__libgstcoretracers_la_SOURCES_DIST = gstlatency.c gstleaks.c \ + gstlog.c gstrusage.c gststats.c gsttracers.c +@GST_DISABLE_GST_DEBUG_FALSE@am__objects_1 = \ +@GST_DISABLE_GST_DEBUG_FALSE@ libgstcoretracers_la-gstlog.lo +@HAVE_GETRUSAGE_TRUE@am__objects_2 = \ +@HAVE_GETRUSAGE_TRUE@ libgstcoretracers_la-gstrusage.lo +am_libgstcoretracers_la_OBJECTS = libgstcoretracers_la-gstlatency.lo \ + libgstcoretracers_la-gstleaks.lo $(am__objects_1) \ + $(am__objects_2) libgstcoretracers_la-gststats.lo \ + libgstcoretracers_la-gsttracers.lo +libgstcoretracers_la_OBJECTS = $(am_libgstcoretracers_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgstcoretracers_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libgstcoretracers_la_CFLAGS) $(CFLAGS) \ + $(libgstcoretracers_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgstcoretracers_la_SOURCES) +DIST_SOURCES = $(am__libgstcoretracers_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +plugin_LTLIBRARIES = libgstcoretracers.la +@HAVE_GETRUSAGE_FALSE@RUSAGE_SOURCES = +@HAVE_GETRUSAGE_TRUE@RUSAGE_SOURCES = gstrusage.c +@GST_DISABLE_GST_DEBUG_FALSE@LOG_SOURCES = gstlog.c +@GST_DISABLE_GST_DEBUG_TRUE@LOG_SOURCES = +libgstcoretracers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la +libgstcoretracers_la_SOURCES = \ + gstlatency.c \ + gstleaks.c \ + $(LOG_SOURCES) \ + $(RUSAGE_SOURCES) \ + gststats.c \ + gsttracers.c + +libgstcoretracers_la_CFLAGS = $(GST_OBJ_CFLAGS) \ + -DGST_USE_UNSTABLE_API + +libgstcoretracers_la_LIBADD = $(GST_OBJ_LIBS) +libgstcoretracers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +noinst_HEADERS = \ + gstlatency.h \ + gstleaks.h \ + gstlog.h \ + gstrusage.h \ + gststats.h + +CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/tracers/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/tracers/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgstcoretracers.la: $(libgstcoretracers_la_OBJECTS) $(libgstcoretracers_la_DEPENDENCIES) $(EXTRA_libgstcoretracers_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstcoretracers_la_LINK) -rpath $(plugindir) $(libgstcoretracers_la_OBJECTS) $(libgstcoretracers_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gstlatency.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gstleaks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gstlog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gstrusage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gststats.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoretracers_la-gsttracers.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstcoretracers_la-gstlatency.lo: gstlatency.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gstlatency.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gstlatency.Tpo -c -o libgstcoretracers_la-gstlatency.lo `test -f 'gstlatency.c' || echo '$(srcdir)/'`gstlatency.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gstlatency.Tpo $(DEPDIR)/libgstcoretracers_la-gstlatency.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstlatency.c' object='libgstcoretracers_la-gstlatency.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gstlatency.lo `test -f 'gstlatency.c' || echo '$(srcdir)/'`gstlatency.c + +libgstcoretracers_la-gstleaks.lo: gstleaks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gstleaks.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gstleaks.Tpo -c -o libgstcoretracers_la-gstleaks.lo `test -f 'gstleaks.c' || echo '$(srcdir)/'`gstleaks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gstleaks.Tpo $(DEPDIR)/libgstcoretracers_la-gstleaks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstleaks.c' object='libgstcoretracers_la-gstleaks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gstleaks.lo `test -f 'gstleaks.c' || echo '$(srcdir)/'`gstleaks.c + +libgstcoretracers_la-gstlog.lo: gstlog.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gstlog.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gstlog.Tpo -c -o libgstcoretracers_la-gstlog.lo `test -f 'gstlog.c' || echo '$(srcdir)/'`gstlog.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gstlog.Tpo $(DEPDIR)/libgstcoretracers_la-gstlog.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstlog.c' object='libgstcoretracers_la-gstlog.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gstlog.lo `test -f 'gstlog.c' || echo '$(srcdir)/'`gstlog.c + +libgstcoretracers_la-gstrusage.lo: gstrusage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gstrusage.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gstrusage.Tpo -c -o libgstcoretracers_la-gstrusage.lo `test -f 'gstrusage.c' || echo '$(srcdir)/'`gstrusage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gstrusage.Tpo $(DEPDIR)/libgstcoretracers_la-gstrusage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstrusage.c' object='libgstcoretracers_la-gstrusage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gstrusage.lo `test -f 'gstrusage.c' || echo '$(srcdir)/'`gstrusage.c + +libgstcoretracers_la-gststats.lo: gststats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gststats.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gststats.Tpo -c -o libgstcoretracers_la-gststats.lo `test -f 'gststats.c' || echo '$(srcdir)/'`gststats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gststats.Tpo $(DEPDIR)/libgstcoretracers_la-gststats.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gststats.c' object='libgstcoretracers_la-gststats.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gststats.lo `test -f 'gststats.c' || echo '$(srcdir)/'`gststats.c + +libgstcoretracers_la-gsttracers.lo: gsttracers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -MT libgstcoretracers_la-gsttracers.lo -MD -MP -MF $(DEPDIR)/libgstcoretracers_la-gsttracers.Tpo -c -o libgstcoretracers_la-gsttracers.lo `test -f 'gsttracers.c' || echo '$(srcdir)/'`gsttracers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoretracers_la-gsttracers.Tpo $(DEPDIR)/libgstcoretracers_la-gsttracers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttracers.c' object='libgstcoretracers_la-gsttracers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoretracers_la_CFLAGS) $(CFLAGS) -c -o libgstcoretracers_la-gsttracers.lo `test -f 'gsttracers.c' || echo '$(srcdir)/'`gsttracers.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + +.PRECIOUS: Makefile + + +%.c.gcov: .libs/libgstcoretracers_la-%.gcda %.c + $(GCOV) -b -f -o $^ > $@.out + +gcov: $(libgstcoretracers_la_SOURCES:=.gcov) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/tracers/gstlatency.c b/plugins/tracers/gstlatency.c new file mode 100644 index 0000000..de4a71c --- /dev/null +++ b/plugins/tracers/gstlatency.c @@ -0,0 +1,255 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstlatency.c: tracing module that logs processing latency stats + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-latencytracer + * @short_description: log processing latency stats + * + * A tracing module that determines src-to-sink latencies by injecting custom + * events at sources and process them at sinks. + */ +/* TODO(ensonic): if there are two sources feeding into a mixer/muxer and later + * we fan-out with tee and have two sinks, each sink would get all two events, + * the later event would overwrite the former. Unfortunately when the buffer + * arrives on the sink we don't know to which event it correlates. Better would + * be to use the buffer meta in 1.0 instead of the event. Or we track a min/max + * latency. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstlatency.h" + +GST_DEBUG_CATEGORY_STATIC (gst_latency_debug); +#define GST_CAT_DEFAULT gst_latency_debug + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_latency_debug, "latency", 0, "latency tracer"); +#define gst_latency_tracer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstLatencyTracer, gst_latency_tracer, GST_TYPE_TRACER, + _do_init); + +static GQuark latency_probe_id; +static GQuark latency_probe_pad; +static GQuark latency_probe_ts; + +static GstTracerRecord *tr_latency; + +/* data helpers */ + +/* + * Get the element/bin owning the pad. + * + * in: a normal pad + * out: the element + * + * in: a proxy pad + * out: the element that contains the peer of the proxy + * + * in: a ghost pad + * out: the bin owning the ghostpad + */ +/* TODO(ensonic): gst_pad_get_parent_element() would not work here, should we + * add this as new api, e.g. gst_pad_find_parent_element(); + */ +static GstElement * +get_real_pad_parent (GstPad * pad) +{ + GstObject *parent; + + if (!pad) + return NULL; + + parent = GST_OBJECT_PARENT (pad); + + /* if parent of pad is a ghost-pad, then pad is a proxy_pad */ + if (parent && GST_IS_GHOST_PAD (parent)) { + pad = GST_PAD_CAST (parent); + parent = GST_OBJECT_PARENT (pad); + } + return GST_ELEMENT_CAST (parent); +} + +/* hooks */ + +static void +log_latency (const GstStructure * data, GstPad * sink_pad, guint64 sink_ts) +{ + GstPad *src_pad; + guint64 src_ts; + gchar *src, *sink; + + gst_structure_id_get (data, + latency_probe_pad, GST_TYPE_PAD, &src_pad, + latency_probe_ts, G_TYPE_UINT64, &src_ts, NULL); + + src = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (src_pad)); + sink = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (sink_pad)); + + gst_tracer_record_log (tr_latency, src, sink, + GST_CLOCK_DIFF (src_ts, sink_ts), sink_ts); + g_free (src); + g_free (sink); +} + +static void +send_latency_probe (GstElement * parent, GstPad * pad, guint64 ts) +{ + /* allow for non-parented pads to send latency probes as used in e.g. + * rtspsrc for TCP connections */ + if (!parent || (!GST_IS_BIN (parent) && + GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE))) { + GstEvent *latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, + gst_structure_new_id (latency_probe_id, + latency_probe_pad, GST_TYPE_PAD, pad, + latency_probe_ts, G_TYPE_UINT64, ts, + NULL)); + gst_pad_push_event (pad, latency_probe); + } +} + +static void +calculate_latency (GstElement * parent, GstPad * pad, guint64 ts) +{ + if (parent && (!GST_IS_BIN (parent)) && + GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SINK)) { + GstEvent *ev = g_object_get_qdata ((GObject *) pad, latency_probe_id); + + if (ev) { + g_object_set_qdata ((GObject *) pad, latency_probe_id, NULL); + log_latency (gst_event_get_structure (ev), pad, ts); + gst_event_unref (ev); + } + } +} + +static void +do_push_buffer_pre (GstTracer * self, guint64 ts, GstPad * pad) +{ + GstPad *peer_pad = GST_PAD_PEER (pad); + GstElement *parent = get_real_pad_parent (pad); + GstElement *peer_parent = get_real_pad_parent (peer_pad); + + send_latency_probe (parent, pad, ts); + calculate_latency (peer_parent, peer_pad, ts); +} + +static void +do_pull_range_pre (GstTracer * self, guint64 ts, GstPad * pad) +{ + GstPad *peer_pad = GST_PAD_PEER (pad); + GstElement *parent = get_real_pad_parent (peer_pad); + + send_latency_probe (parent, peer_pad, ts); +} + +static void +do_pull_range_post (GstTracer * self, guint64 ts, GstPad * pad) +{ + GstElement *parent = get_real_pad_parent (pad); + + calculate_latency (parent, pad, ts); +} + +static void +do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev) +{ + GstPad *peer_pad = GST_PAD_PEER (pad); + GstElement *parent = get_real_pad_parent (peer_pad); + + if (parent && (!GST_IS_BIN (parent)) && + GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SINK)) { + if (GST_EVENT_TYPE (ev) == GST_EVENT_CUSTOM_DOWNSTREAM) { + const GstStructure *data = gst_event_get_structure (ev); + + if (gst_structure_get_name_id (data) == latency_probe_id) { + /* store event and calculate latency when the buffer that follows + * has been processed */ + g_object_set_qdata ((GObject *) peer_pad, latency_probe_id, + gst_event_ref (ev)); + } + } + } +} + +/* tracer class */ + +static void +gst_latency_tracer_class_init (GstLatencyTracerClass * klass) +{ + latency_probe_id = g_quark_from_static_string ("latency_probe.id"); + latency_probe_pad = g_quark_from_static_string ("latency_probe.pad"); + latency_probe_ts = g_quark_from_static_string ("latency_probe.ts"); + + /* announce trace formats */ + /* *INDENT-OFF* */ + tr_latency = gst_tracer_record_new ("latency.class", + "src", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "sink", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "time", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, + "time it took for the buffer to go from src to sink ns", + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "ts when the latency has been logged", + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + NULL); + /* *INDENT-ON* */ +} + +static void +gst_latency_tracer_init (GstLatencyTracer * self) +{ + GstTracer *tracer = GST_TRACER (self); + + /* in push mode, pre/post will be called before/after the peer chain + * function has been called. For this reaosn, we only use -pre to avoid + * accounting for the processing time of the peer element (the sink) */ + gst_tracing_register_hook (tracer, "pad-push-pre", + G_CALLBACK (do_push_buffer_pre)); + gst_tracing_register_hook (tracer, "pad-push-list-pre", + G_CALLBACK (do_push_buffer_pre)); + + /* while in pull mode, pre/post will happend before and after the upstream + * pull_range call is made, so it already only account for the upstream + * processing time. As a side effect, in pull mode, we can measure the + * source processing latency, while in push mode, we can't */ + gst_tracing_register_hook (tracer, "pad-pull-range-pre", + G_CALLBACK (do_pull_range_pre)); + gst_tracing_register_hook (tracer, "pad-pull-range-post", + G_CALLBACK (do_pull_range_post)); + + gst_tracing_register_hook (tracer, "pad-push-event-pre", + G_CALLBACK (do_push_event_pre)); +} diff --git a/plugins/tracers/gstlatency.h b/plugins/tracers/gstlatency.h new file mode 100644 index 0000000..e234303 --- /dev/null +++ b/plugins/tracers/gstlatency.h @@ -0,0 +1,66 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstrusage.h: tracing module that logs resource usage stats + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_LATENCY_TRACER_H__ +#define __GST_LATENCY_TRACER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_LATENCY_TRACER \ + (gst_latency_tracer_get_type()) +#define GST_LATENCY_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LATENCY_TRACER,GstLatencyTracer)) +#define GST_LATENCY_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_LATENCY_TRACER,GstLatencyTracerClass)) +#define GST_IS_LATENCY_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LATENCY_TRACER)) +#define GST_IS_LATENCY_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LATENCY_TRACER)) +#define GST_LATENCY_TRACER_CAST(obj) ((GstLatencyTracer *)(obj)) + +typedef struct _GstLatencyTracer GstLatencyTracer; +typedef struct _GstLatencyTracerClass GstLatencyTracerClass; + +/** + * GstLatencyTracer: + * + * Opaque #GstLatencyTracer data structure + */ +struct _GstLatencyTracer { + GstTracer parent; + + /*< private >*/ +}; + +struct _GstLatencyTracerClass { + GstTracerClass parent_class; + + /* signals */ +}; + +G_GNUC_INTERNAL GType gst_latency_tracer_get_type (void); + +G_END_DECLS + +#endif /* __GST_LATENCY_TRACER_H__ */ diff --git a/plugins/tracers/gstleaks.c b/plugins/tracers/gstleaks.c new file mode 100644 index 0000000..f95b7c7 --- /dev/null +++ b/plugins/tracers/gstleaks.c @@ -0,0 +1,767 @@ +/* GStreamer + * Copyright (C) 2016 Collabora Ltd. + * + * gstleaks.c: tracing module detecting object leaks + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-leakstracer + * @short_description: detect GstObject and GstMiniObject leaks + * + * A tracing module tracking the lifetime of objects by logging those still + * alive when program is exiting and raising a warning. + * The type of objects tracked can be filtered using the parameters of the + * tracer, for example: GST_TRACERS=leaks(filters="GstEvent,GstMessage",stack-traces-flags=full) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstleaks.h" + +#ifdef G_OS_UNIX +#include +#endif /* G_OS_UNIX */ + +GST_DEBUG_CATEGORY_STATIC (gst_leaks_debug); +#define GST_CAT_DEFAULT gst_leaks_debug + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_leaks_debug, "leaks", 0, "leaks tracer"); +#define gst_leaks_tracer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstLeaksTracer, gst_leaks_tracer, + GST_TYPE_TRACER, _do_init); + +static GstTracerRecord *tr_alive; +static GstTracerRecord *tr_refings; +#ifdef G_OS_UNIX +static GstTracerRecord *tr_added = NULL; +static GstTracerRecord *tr_removed = NULL; +#endif /* G_OS_UNIX */ +static GQueue instances = G_QUEUE_INIT; + +typedef struct +{ + gboolean reffed; + gchar *trace; + gint new_refcount; + GstClockTime ts; +} ObjectRefingInfo; + +typedef struct +{ + gchar *creation_trace; + + GList *refing_infos; +} ObjectRefingInfos; + +static void +object_refing_info_free (ObjectRefingInfo * refinfo) +{ + g_free (refinfo->trace); + g_free (refinfo); +} + +static void +object_refing_infos_free (ObjectRefingInfos * infos) +{ + g_list_free_full (infos->refing_infos, + (GDestroyNotify) object_refing_info_free); + + g_free (infos->creation_trace); + g_free (infos); +} + +static void +set_print_stack_trace_from_string (GstLeaksTracer * self, const gchar * str) +{ + gchar *trace; + + /* Test if we can retrieve backtrace */ + trace = gst_debug_get_stack_trace (FALSE); + if (!trace) + return; + + g_free (trace); + + if (g_strcmp0 (str, "full") == 0) + self->trace_flags = GST_STACK_TRACE_SHOW_FULL; + else + self->trace_flags = 0; +} + +static void +set_print_stack_trace (GstLeaksTracer * self, GstStructure * params) +{ + const gchar *trace_flags = g_getenv ("GST_LEAKS_TRACER_STACK_TRACE"); + + self->trace_flags = -1; + if (!trace_flags && params) + trace_flags = gst_structure_get_string (params, "stack-traces-flags"); + + if (!trace_flags) + return; + + set_print_stack_trace_from_string (self, trace_flags); +} + +static void +set_filters (GstLeaksTracer * self, const gchar * filters) +{ + guint i; + GStrv tmp = g_strsplit (filters, ",", -1); + + self->filter = g_array_sized_new (FALSE, FALSE, sizeof (GType), + g_strv_length (tmp)); + for (i = 0; tmp[i]; i++) { + GType type; + + type = g_type_from_name (tmp[i]); + if (type == 0) { + /* The type may not yet be known by the type system, typically because + * the plugin implementing it as not yet be loaded. Save it for now as + * it will have another chance to be added to the filter later in + * should_handle_object_type() when/if the object type is actually + * used. */ + if (!self->unhandled_filter) + self->unhandled_filter = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + + g_hash_table_add (self->unhandled_filter, g_strdup (tmp[i])); + g_atomic_int_inc (&self->unhandled_filter_count); + continue; + } + + GST_DEBUG_OBJECT (self, "add filter on %s", tmp[i]); + + g_array_append_val (self->filter, type); + } + + g_strfreev (tmp); +} + +static void +set_params_from_structure (GstLeaksTracer * self, GstStructure * params) +{ + const gchar *filters = gst_structure_get_string (params, "filters"); + + if (filters) + set_filters (self, filters); + gst_structure_get_boolean (params, "check-refs", &self->check_refs); +} + +static void +set_params (GstLeaksTracer * self) +{ + gchar *params, *tmp; + GstStructure *params_struct = NULL; + + g_object_get (self, "params", ¶ms, NULL); + if (!params) + goto set_stacktrace; + + tmp = g_strdup_printf ("leaks,%s", params); + params_struct = gst_structure_from_string (tmp, NULL); + g_free (tmp); + + if (params_struct) + set_params_from_structure (self, params_struct); + else + set_filters (self, params); + + g_free (params); + +set_stacktrace: + set_print_stack_trace (self, params_struct); + + if (params_struct) + gst_structure_free (params_struct); +} + +static gboolean +_expand_unhandled_filters (gchar * typename, gpointer unused_value, + GstLeaksTracer * self) +{ + GType type; + + type = g_type_from_name (typename); + + if (type == 0) + return FALSE; + + g_atomic_int_dec_and_test (&self->unhandled_filter_count); + g_array_append_val (self->filter, type); + + return TRUE; +} + +static gboolean +should_handle_object_type (GstLeaksTracer * self, GType object_type) +{ + guint i, len; + + if (!self->filter) + /* No filtering, handle all types */ + return TRUE; + + if (object_type == 0) + return FALSE; + + + if (g_atomic_int_get (&self->unhandled_filter_count)) { + GST_OBJECT_LOCK (self); + g_hash_table_foreach_remove (self->unhandled_filter, + (GHRFunc) _expand_unhandled_filters, self); + GST_OBJECT_UNLOCK (self); + } + + len = self->filter->len; + for (i = 0; i < len; i++) { + GType type = g_array_index (self->filter, GType, i); + + if (g_type_is_a (object_type, type)) + return TRUE; + } + + return FALSE; +} + +#ifdef G_OS_UNIX +/* The object may be destroyed when we log it using the checkpointing system so + * we have to save its type name */ +typedef struct +{ + gpointer object; + const gchar *type_name; +} ObjectLog; + +static ObjectLog * +object_log_new (gpointer obj) +{ + ObjectLog *o = g_slice_new (ObjectLog); + + o->object = obj; + + if (G_IS_OBJECT (obj)) + o->type_name = G_OBJECT_TYPE_NAME (obj); + else + o->type_name = g_type_name (GST_MINI_OBJECT_TYPE (obj)); + + return o; +} + +static void +object_log_free (ObjectLog * obj) +{ + g_slice_free (ObjectLog, obj); +} +#endif /* G_OS_UNIX */ + +static void +handle_object_destroyed (GstLeaksTracer * self, gpointer object) +{ + GST_OBJECT_LOCK (self); + if (self->done) { + g_warning + ("object %p destroyed while the leaks tracer was finalizing. Some threads are still running?", + object); + goto out; + } + + g_hash_table_remove (self->objects, object); +#ifdef G_OS_UNIX + if (self->removed) + g_hash_table_add (self->removed, object_log_new (object)); +#endif /* G_OS_UNIX */ +out: + GST_OBJECT_UNLOCK (self); +} + +static void +object_weak_cb (gpointer data, GObject * object) +{ + GstLeaksTracer *self = data; + + handle_object_destroyed (self, object); +} + +static void +mini_object_weak_cb (gpointer data, GstMiniObject * object) +{ + GstLeaksTracer *self = data; + + handle_object_destroyed (self, object); +} + +static void +handle_object_created (GstLeaksTracer * self, gpointer object, GType type, + gboolean gobject) +{ + ObjectRefingInfos *infos; + + + if (!should_handle_object_type (self, type)) + return; + + infos = g_malloc0 (sizeof (ObjectRefingInfos)); + if (gobject) + g_object_weak_ref ((GObject *) object, object_weak_cb, self); + else + gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (object), + mini_object_weak_cb, self); + + GST_OBJECT_LOCK (self); + if ((gint) self->trace_flags != -1) + infos->creation_trace = gst_debug_get_stack_trace (self->trace_flags); + + g_hash_table_insert (self->objects, object, infos); + +#ifdef G_OS_UNIX + if (self->added) + g_hash_table_add (self->added, object_log_new (object)); +#endif /* G_OS_UNIX */ + GST_OBJECT_UNLOCK (self); +} + +static void +mini_object_created_cb (GstTracer * tracer, GstClockTime ts, + GstMiniObject * object) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + + handle_object_created (self, object, GST_MINI_OBJECT_TYPE (object), FALSE); +} + +static void +object_created_cb (GstTracer * tracer, GstClockTime ts, GstObject * object) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + GType object_type = G_OBJECT_TYPE (object); + + /* Can't track tracers as they may be disposed after the leak tracer itself */ + if (g_type_is_a (object_type, GST_TYPE_TRACER)) + return; + + handle_object_created (self, object, object_type, TRUE); +} + +static void +handle_object_reffed (GstLeaksTracer * self, gpointer object, gint new_refcount, + gboolean reffed, GstClockTime ts) +{ + ObjectRefingInfos *infos; + ObjectRefingInfo *refinfo; + + if (!self->check_refs) + return; + + GST_OBJECT_LOCK (self); + infos = g_hash_table_lookup (self->objects, object); + if (!infos) + goto out; + + refinfo = g_malloc0 (sizeof (ObjectRefingInfo)); + refinfo->ts = ts; + refinfo->new_refcount = new_refcount; + refinfo->reffed = reffed; + if ((gint) self->trace_flags != -1) + refinfo->trace = gst_debug_get_stack_trace (self->trace_flags); + + infos->refing_infos = g_list_prepend (infos->refing_infos, refinfo); + +out: + GST_OBJECT_UNLOCK (self); +} + +static void +object_reffed_cb (GstTracer * tracer, GstClockTime ts, GstObject * object, + gint new_refcount) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + + handle_object_reffed (self, object, new_refcount, TRUE, ts); +} + +static void +object_unreffed_cb (GstTracer * tracer, GstClockTime ts, GstObject * object, + gint new_refcount) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + + handle_object_reffed (self, object, new_refcount, FALSE, ts); +} + +static void +mini_object_reffed_cb (GstTracer * tracer, GstClockTime ts, + GstMiniObject * object, gint new_refcount) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + + handle_object_reffed (self, object, new_refcount, TRUE, ts); +} + +static void +mini_object_unreffed_cb (GstTracer * tracer, GstClockTime ts, + GstMiniObject * object, gint new_refcount) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer); + + handle_object_reffed (self, object, new_refcount, FALSE, ts); +} + +static void +gst_leaks_tracer_init (GstLeaksTracer * self) +{ + self->objects = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) object_refing_infos_free); + + g_queue_push_tail (&instances, self); +} + +static void +gst_leaks_tracer_constructed (GObject * object) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER (object); + GstTracer *tracer = GST_TRACER (object); + + set_params (self); + + gst_tracing_register_hook (tracer, "mini-object-created", + G_CALLBACK (mini_object_created_cb)); + gst_tracing_register_hook (tracer, "object-created", + G_CALLBACK (object_created_cb)); + + if (self->check_refs) { + gst_tracing_register_hook (tracer, "object-reffed", + G_CALLBACK (object_reffed_cb)); + gst_tracing_register_hook (tracer, "mini-object-reffed", + G_CALLBACK (mini_object_reffed_cb)); + gst_tracing_register_hook (tracer, "mini-object-unreffed", + G_CALLBACK (mini_object_unreffed_cb)); + gst_tracing_register_hook (tracer, "object-unreffed", + G_CALLBACK (object_unreffed_cb)); + } + + /* We rely on weak pointers rather than (mini-)object-destroyed hooks so we + * are notified of objects being destroyed even during the shuting down of + * the tracing system. */ + + ((GObjectClass *) gst_leaks_tracer_parent_class)->constructed (object); +} + +typedef struct +{ + gpointer obj; + const gchar *type_name; + guint ref_count; + gchar *desc; + ObjectRefingInfos *infos; +} Leak; + +/* The content of the returned Leak struct is valid until the self->objects + * hash table has been modified. */ +static Leak * +leak_new (gpointer obj, GType type, guint ref_count, ObjectRefingInfos * infos) +{ + Leak *leak = g_slice_new (Leak); + + leak->obj = obj; + leak->type_name = g_type_name (type); + leak->ref_count = ref_count; + leak->desc = gst_info_strdup_printf ("%" GST_PTR_FORMAT, obj); + leak->infos = infos; + + return leak; +} + +static void +leak_free (Leak * leak) +{ + g_free (leak->desc); + g_slice_free (Leak, leak); +} + +static gint +sort_leaks (gconstpointer _a, gconstpointer _b) +{ + const Leak *a = _a, *b = _b; + + return g_strcmp0 (a->type_name, b->type_name); +} + +static GList * +create_leaks_list (GstLeaksTracer * self) +{ + GList *l = NULL; + GHashTableIter iter; + gpointer obj, infos; + + g_hash_table_iter_init (&iter, self->objects); + while (g_hash_table_iter_next (&iter, &obj, &infos)) { + GType type; + guint ref_count; + + if (GST_IS_OBJECT (obj)) { + if (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLAG_MAY_BE_LEAKED)) + continue; + + type = G_OBJECT_TYPE (obj); + ref_count = ((GObject *) obj)->ref_count; + } else { + if (GST_MINI_OBJECT_FLAG_IS_SET (obj, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED)) + continue; + + type = GST_MINI_OBJECT_TYPE (obj); + ref_count = ((GstMiniObject *) obj)->refcount; + } + + l = g_list_prepend (l, leak_new (obj, type, ref_count, infos)); + } + + /* Sort leaks by type name so they are grouped together making the output + * easier to read */ + l = g_list_sort (l, sort_leaks); + + return l; +} + +/* Return TRUE if at least one leaked object has been logged */ +static gboolean +log_leaked (GstLeaksTracer * self) +{ + GList *ref, *leaks, *l; + gboolean ret = FALSE; + + GST_TRACE_OBJECT (self, "start listing currently alive objects"); + + leaks = create_leaks_list (self); + if (!leaks) { + GST_TRACE_OBJECT (self, "No objects alive currently"); + goto done; + } + + for (l = leaks; l != NULL; l = g_list_next (l)) { + Leak *leak = l->data; + + gst_tracer_record_log (tr_alive, leak->type_name, leak->obj, leak->desc, + leak->ref_count, + leak->infos->creation_trace ? leak->infos->creation_trace : ""); + + leak->infos->refing_infos = g_list_reverse (leak->infos->refing_infos); + for (ref = leak->infos->refing_infos; ref; ref = ref->next) { + ObjectRefingInfo *refinfo = (ObjectRefingInfo *) ref->data; + + gst_tracer_record_log (tr_refings, refinfo->ts, leak->type_name, + leak->obj, refinfo->reffed ? "reffed" : "unreffed", + refinfo->new_refcount, refinfo->trace ? refinfo->trace : ""); + } + } + + g_list_free_full (leaks, (GDestroyNotify) leak_free); + + ret = TRUE; + +done: + GST_TRACE_OBJECT (self, "done listing currently alive objects"); + + return ret; +} + +static void +gst_leaks_tracer_finalize (GObject * object) +{ + GstLeaksTracer *self = GST_LEAKS_TRACER (object); + gboolean leaks; + GHashTableIter iter; + gpointer obj; + + self->done = TRUE; + + /* Tracers are destroyed as part of gst_deinit() so now is a good time to + * report all the objects which are still alive. */ + leaks = log_leaked (self); + + /* Remove weak references */ + g_hash_table_iter_init (&iter, self->objects); + while (g_hash_table_iter_next (&iter, &obj, NULL)) { + if (GST_IS_OBJECT (obj)) + g_object_weak_unref (obj, object_weak_cb, self); + else + gst_mini_object_weak_unref (GST_MINI_OBJECT_CAST (obj), + mini_object_weak_cb, self); + } + + g_clear_pointer (&self->objects, g_hash_table_unref); + if (self->filter) + g_array_free (self->filter, TRUE); + g_clear_pointer (&self->added, g_hash_table_unref); + g_clear_pointer (&self->removed, g_hash_table_unref); + g_clear_pointer (&self->unhandled_filter, g_hash_table_unref); + + g_queue_remove (&instances, self); + + if (leaks) + g_warning ("Leaks detected"); + + ((GObjectClass *) gst_leaks_tracer_parent_class)->finalize (object); +} + +#define RECORD_FIELD_TYPE_TS \ + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, GST_TYPE_CLOCK_TIME, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) +#define RECORD_FIELD_TYPE_NAME \ + "type-name", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, G_TYPE_STRING, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) +#define RECORD_FIELD_ADDRESS \ + "address", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, G_TYPE_POINTER, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, \ + GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) +#define RECORD_FIELD_DESC \ + "description", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, G_TYPE_STRING, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) +#define RECORD_FIELD_REF_COUNT \ + "ref-count", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, G_TYPE_UINT, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) +#define RECORD_FIELD_TRACE \ + "trace", GST_TYPE_STRUCTURE, gst_structure_new ("value", \ + "type", G_TYPE_GTYPE, G_TYPE_STRING, \ + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, \ + NULL) + +#ifdef G_OS_UNIX +static void +sig_usr1_handler_foreach (gpointer data, gpointer user_data) +{ + GstLeaksTracer *tracer = data; + + GST_OBJECT_LOCK (tracer); + log_leaked (tracer); + GST_OBJECT_UNLOCK (tracer); +} + +static void +sig_usr1_handler (G_GNUC_UNUSED int signal) +{ + g_queue_foreach (&instances, sig_usr1_handler_foreach, NULL); +} + +static void +log_checkpoint (GHashTable * hash, GstTracerRecord * record) +{ + GHashTableIter iter; + gpointer o; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, &o, NULL)) { + ObjectLog *obj = o; + + gst_tracer_record_log (record, obj->type_name, obj->object); + } +} + +static void +do_checkpoint (GstLeaksTracer * self) +{ + GST_TRACE_OBJECT (self, "listing objects created since last checkpoint"); + log_checkpoint (self->added, tr_added); + GST_TRACE_OBJECT (self, "listing objects removed since last checkpoint"); + log_checkpoint (self->removed, tr_removed); + + g_hash_table_remove_all (self->added); + g_hash_table_remove_all (self->removed); +} + +static void +sig_usr2_handler_foreach (gpointer data, gpointer user_data) +{ + GstLeaksTracer *tracer = data; + + GST_OBJECT_LOCK (tracer); + + if (!tracer->added) { + GST_TRACE_OBJECT (tracer, "First checkpoint, start tracking objects"); + + tracer->added = g_hash_table_new_full (NULL, NULL, + (GDestroyNotify) object_log_free, NULL); + tracer->removed = g_hash_table_new_full (NULL, NULL, + (GDestroyNotify) object_log_free, NULL); + } else { + do_checkpoint (tracer); + } + + GST_OBJECT_UNLOCK (tracer); +} + +static void +sig_usr2_handler (G_GNUC_UNUSED int signal) +{ + g_queue_foreach (&instances, sig_usr2_handler_foreach, NULL); +} + +static void +setup_signals (void) +{ + tr_added = gst_tracer_record_new ("object-added.class", + RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL); + GST_OBJECT_FLAG_SET (tr_added, GST_OBJECT_FLAG_MAY_BE_LEAKED); + + tr_removed = gst_tracer_record_new ("object-removed.class", + RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, NULL); + GST_OBJECT_FLAG_SET (tr_removed, GST_OBJECT_FLAG_MAY_BE_LEAKED); + + signal (SIGUSR1, sig_usr1_handler); + signal (SIGUSR2, sig_usr2_handler); +} +#endif /* G_OS_UNIX */ + +static void +gst_leaks_tracer_class_init (GstLeaksTracerClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = gst_leaks_tracer_constructed; + gobject_class->finalize = gst_leaks_tracer_finalize; + + tr_alive = gst_tracer_record_new ("object-alive.class", + RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, RECORD_FIELD_DESC, + RECORD_FIELD_REF_COUNT, RECORD_FIELD_TRACE, NULL); + GST_OBJECT_FLAG_SET (tr_alive, GST_OBJECT_FLAG_MAY_BE_LEAKED); + + tr_refings = gst_tracer_record_new ("object-refings.class", + RECORD_FIELD_TYPE_TS, RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, + RECORD_FIELD_DESC, RECORD_FIELD_REF_COUNT, RECORD_FIELD_TRACE, NULL); + GST_OBJECT_FLAG_SET (tr_alive, GST_OBJECT_FLAG_MAY_BE_LEAKED); + + if (g_getenv ("GST_LEAKS_TRACER_SIG")) { +#ifdef G_OS_UNIX + setup_signals (); +#else + g_warning ("System doesn't support POSIX signals"); +#endif /* G_OS_UNIX */ + } +} diff --git a/plugins/tracers/gstleaks.h b/plugins/tracers/gstleaks.h new file mode 100644 index 0000000..71277b8 --- /dev/null +++ b/plugins/tracers/gstleaks.h @@ -0,0 +1,84 @@ +/* GStreamer + * Copyright (C) 2016 Collabora Ltd. + * + * gstleaks.c: tracing module detecting object leaks + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_LEAKS_TRACER_H__ +#define __GST_LEAKS_TRACER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_LEAKS_TRACER \ + (gst_leaks_tracer_get_type()) +#define GST_LEAKS_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LEAKS_TRACER,GstLeaksTracer)) +#define GST_LEAKS_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_LEAKS_TRACER,GstLeaksTracerClass)) +#define GST_IS_LEAKS_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LEAKS_TRACER)) +#define GST_IS_LEAKS_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LEAKS_TRACER)) +#define GST_LEAKS_TRACER_CAST(obj) ((GstLeaksTracer *)(obj)) + +typedef struct _GstLeaksTracer GstLeaksTracer; +typedef struct _GstLeaksTracerClass GstLeaksTracerClass; + +/** + * GstLeaksTracer: + * + * Opaque #GstLeaksTracer data structure + */ +struct _GstLeaksTracer { + GstTracer parent; + + /*< private >*/ + /* gpointer (object currently alive) -> gchar * (its creation trace, or + * NULL). Protected by object lock */ + GHashTable *objects; + /* array of GType used as filtering */ + GArray *filter; + /* Set of owned ObjectLog. Protected by object lock */ + GHashTable *added; + /* Set of owned ObjectLog. Protected by object lock */ + GHashTable *removed; + /* If not NULL, contain a set of string representing type filter not + * (yet?) known by the type system. + * Protected by object lock. */ + GHashTable *unhandled_filter; + /* The number of elements in unhandled_filter */ + gint unhandled_filter_count; + gboolean done; + + gboolean check_refs; + + GstStackTraceFlags trace_flags; +}; + +struct _GstLeaksTracerClass { + GstTracerClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_leaks_tracer_get_type (void); + +G_END_DECLS + +#endif /* __GST_LEAKS_TRACER_H__ */ diff --git a/plugins/tracers/gstlog.c b/plugins/tracers/gstlog.c new file mode 100644 index 0000000..cc7471a --- /dev/null +++ b/plugins/tracers/gstlog.c @@ -0,0 +1,375 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstlog.c: tracing module that logs events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-logtracer + * @short_description: log hook event + * + * A tracing module that logs all data from all hooks. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstlog.h" + +GST_DEBUG_CATEGORY_STATIC (gst_log_debug); +#define GST_CAT_DEFAULT gst_log_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_BIN); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_BUFFER); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_BUFFER_LIST); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_EVENT); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_MESSAGE); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_QUERY); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_STATES); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_PADS); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_ELEMENT_PADS); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_ELEMENT_FACTORY); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_log_debug, "log", 0, "log tracer"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_BUFFER, "GST_BUFFER"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_BUFFER_LIST, "GST_BUFFER_LIST"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_EVENT, "GST_EVENT"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_MESSAGE, "GST_MESSAGE"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_STATES, "GST_STATES"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_PADS, "GST_PADS"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_ELEMENT_PADS, "GST_ELEMENT_PADS"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_ELEMENT_FACTORY, "GST_ELEMENT_FACTORY"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_QUERY, "query"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_BIN, "bin"); +#define gst_log_tracer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstLogTracer, gst_log_tracer, GST_TYPE_TRACER, + _do_init); + +static void +do_log (GstDebugCategory * cat, const char *func, GObject * obj, + const char *fmt, ...) +{ + va_list var_args; + + va_start (var_args, fmt); + gst_debug_log_valist (cat, GST_LEVEL_TRACE, "", func, 0, obj, fmt, var_args); + va_end (var_args); +} + +static void +do_push_buffer_pre (GstTracer * self, guint64 ts, GstPad * pad, + GstBuffer * buffer) +{ + do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", buffer=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), pad, buffer); +} + +static void +do_push_buffer_post (GstTracer * self, guint64 ts, GstPad * pad, + GstFlowReturn res) +{ + do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), pad, res); +} + +static void +do_push_buffer_list_pre (GstTracer * self, guint64 ts, GstPad * pad, + GstBufferList * list) +{ + do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", list=%p", + GST_TIME_ARGS (ts), pad, list); +} + +static void +do_push_buffer_list_post (GstTracer * self, guint64 ts, GstPad * pad, + GstFlowReturn res) +{ + do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), pad, res); +} + +static void +do_pull_range_pre (GstTracer * self, guint64 ts, GstPad * pad, guint64 offset, + guint size) +{ + do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", offset=%" G_GUINT64_FORMAT + ", size=%u", GST_TIME_ARGS (ts), pad, offset, size); +} + +static void +do_pull_range_post (GstTracer * self, guint64 ts, GstPad * pad, + GstBuffer * buffer, GstFlowReturn res) +{ + do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", buffer=%" GST_PTR_FORMAT + ", res=%d", GST_TIME_ARGS (ts), pad, buffer, res); +} + +static void +do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * event) +{ + do_log (GST_CAT_EVENT, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", event=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), pad, event); +} + +static void +do_push_event_post (GstTracer * self, guint64 ts, GstPad * pad, gboolean res) +{ + do_log (GST_CAT_EVENT, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), pad, res); +} + +static void +do_pad_query_pre (GstTracer * self, guint64 ts, GstPad * pad, GstQuery * query) +{ + do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", query=%" + GST_PTR_FORMAT, GST_TIME_ARGS (ts), pad, query); +} + +static void +do_pad_query_post (GstTracer * self, guint64 ts, GstPad * pad, gboolean res) +{ + do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) pad, + "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), pad, res); +} + +static void +do_post_message_pre (GstTracer * self, guint64 ts, GstElement * elem, + GstMessage * msg) +{ + do_log (GST_CAT_MESSAGE, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", message=%" + GST_PTR_FORMAT, GST_TIME_ARGS (ts), elem, msg); +} + +static void +do_post_message_post (GstTracer * self, guint64 ts, GstElement * elem, + gboolean res) +{ + do_log (GST_CAT_MESSAGE, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), elem, res); +} + +static void +do_element_query_pre (GstTracer * self, guint64 ts, GstElement * elem, + GstQuery * query) +{ + do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", query=%" + GST_PTR_FORMAT, GST_TIME_ARGS (ts), elem, query); +} + +static void +do_element_query_post (GstTracer * self, guint64 ts, GstElement * elem, + gboolean res) +{ + do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), elem, res); +} + +static void +do_element_new (GstTracer * self, guint64 ts, GstElement * elem) +{ + do_log (GST_CAT_ELEMENT_FACTORY, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), elem); +} + +static void +do_element_add_pad (GstTracer * self, guint64 ts, GstElement * elem, + GstPad * pad) +{ + do_log (GST_CAT_ELEMENT_PADS, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", pad=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), elem, pad); +} + +static void +do_element_remove_pad (GstTracer * self, guint64 ts, GstElement * elem, + GstPad * pad) +{ + do_log (GST_CAT_ELEMENT_PADS, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", pad=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), elem, pad); +} + +static void +do_element_change_state_pre (GstTracer * self, guint64 ts, GstElement * elem, + GstStateChange change) +{ + do_log (GST_CAT_STATES, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%d", + GST_TIME_ARGS (ts), elem, (gint) change); +} + +static void +do_element_change_state_post (GstTracer * self, guint64 ts, GstElement * elem, + GstStateChange change, GstStateChangeReturn res) +{ + do_log (GST_CAT_STATES, GST_FUNCTION, (GObject *) elem, + "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%d, res=%d", + GST_TIME_ARGS (ts), elem, (gint) change, (gint) res); +} + +static void +do_bin_add_pre (GstTracer * self, guint64 ts, GstBin * bin, GstElement * elem) +{ + do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin, + "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", element=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), bin, elem); +} + +static void +do_bin_add_post (GstTracer * self, guint64 ts, GstBin * bin, GstElement * elem, + gboolean res) +{ + do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin, + "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", element=%" GST_PTR_FORMAT + ", res=%d", GST_TIME_ARGS (ts), bin, elem, res); +} + +static void +do_bin_remove_pre (GstTracer * self, guint64 ts, GstBin * bin, + GstElement * elem) +{ + do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin, + "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", element=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), bin, elem); +} + +static void +do_bin_remove_post (GstTracer * self, guint64 ts, GstBin * bin, gboolean res) +{ + do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin, + "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", res=%d", + GST_TIME_ARGS (ts), bin, res); +} + +static void +do_pad_link_pre (GstTracer * self, guint64 ts, GstPad * src, GstPad * sink) +{ + do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src, + "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), src, sink); +} + +static void +do_pad_link_post (GstTracer * self, guint64 ts, GstPad * src, GstPad * sink, + GstPadLinkReturn res) +{ + do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src, + "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT + ", res=%d", GST_TIME_ARGS (ts), src, sink, (gint) res); +} + +static void +do_pad_unlink_pre (GstTracer * self, guint64 ts, GstPad * src, + GstElement * sink) +{ + do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src, + "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT, + GST_TIME_ARGS (ts), src, sink); +} + +static void +do_pad_unlink_post (GstTracer * self, guint64 ts, GstPad * src, + GstElement * sink, gboolean res) +{ + do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src, + "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT + ", res=%d", GST_TIME_ARGS (ts), src, sink, (gint) res); +} + +/* tracer class */ + +static void +gst_log_tracer_class_init (GstLogTracerClass * klass) +{ +} + +static void +gst_log_tracer_init (GstLogTracer * self) +{ + GstTracer *tracer = GST_TRACER (self); + + gst_tracing_register_hook (tracer, "pad-push-pre", + G_CALLBACK (do_push_buffer_pre)); + gst_tracing_register_hook (tracer, "pad-push-post", + G_CALLBACK (do_push_buffer_post)); + gst_tracing_register_hook (tracer, "pad-push-list-pre", + G_CALLBACK (do_push_buffer_list_pre)); + gst_tracing_register_hook (tracer, "pad-push-list-post", + G_CALLBACK (do_push_buffer_list_post)); + gst_tracing_register_hook (tracer, "pad-pull-range-pre", + G_CALLBACK (do_pull_range_pre)); + gst_tracing_register_hook (tracer, "pad-pull-range-post", + G_CALLBACK (do_pull_range_post)); + gst_tracing_register_hook (tracer, "pad-push-event-pre", + G_CALLBACK (do_push_event_pre)); + gst_tracing_register_hook (tracer, "pad-push-event-post", + G_CALLBACK (do_push_event_post)); + gst_tracing_register_hook (tracer, "pad-query-pre", + G_CALLBACK (do_pad_query_pre)); + gst_tracing_register_hook (tracer, "pad-query-post", + G_CALLBACK (do_pad_query_post)); + gst_tracing_register_hook (tracer, "element-post-message-pre", + G_CALLBACK (do_post_message_pre)); + gst_tracing_register_hook (tracer, "element-post-message-post", + G_CALLBACK (do_post_message_post)); + gst_tracing_register_hook (tracer, "element-query-pre", + G_CALLBACK (do_element_query_pre)); + gst_tracing_register_hook (tracer, "element-query-post", + G_CALLBACK (do_element_query_post)); + gst_tracing_register_hook (tracer, "element-new", + G_CALLBACK (do_element_new)); + gst_tracing_register_hook (tracer, "element-add-pad", + G_CALLBACK (do_element_add_pad)); + gst_tracing_register_hook (tracer, "element-remove-pad", + G_CALLBACK (do_element_remove_pad)); + gst_tracing_register_hook (tracer, "element-change-state-pre", + G_CALLBACK (do_element_change_state_pre)); + gst_tracing_register_hook (tracer, "element-change-state-post", + G_CALLBACK (do_element_change_state_post)); + gst_tracing_register_hook (tracer, "bin-add-pre", + G_CALLBACK (do_bin_add_pre)); + gst_tracing_register_hook (tracer, "bin-add-post", + G_CALLBACK (do_bin_add_post)); + gst_tracing_register_hook (tracer, "bin-remove-pre", + G_CALLBACK (do_bin_remove_pre)); + gst_tracing_register_hook (tracer, "bin-remove-post", + G_CALLBACK (do_bin_remove_post)); + gst_tracing_register_hook (tracer, "pad-link-pre", + G_CALLBACK (do_pad_link_pre)); + gst_tracing_register_hook (tracer, "pad-link-post", + G_CALLBACK (do_pad_link_post)); + gst_tracing_register_hook (tracer, "pad-unlink-pre", + G_CALLBACK (do_pad_unlink_pre)); + gst_tracing_register_hook (tracer, "pad-unlink-post", + G_CALLBACK (do_pad_unlink_post)); +} diff --git a/plugins/tracers/gstlog.h b/plugins/tracers/gstlog.h new file mode 100644 index 0000000..6f0dd7f --- /dev/null +++ b/plugins/tracers/gstlog.h @@ -0,0 +1,66 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstlog.h: tracing module that logs events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_LOG_TRACER_H__ +#define __GST_LOG_TRACER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_LOG_TRACER \ + (gst_log_tracer_get_type()) +#define GST_LOG_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LOG_TRACER,GstLogTracer)) +#define GST_LOG_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_LOG_TRACER,GstLogTracerClass)) +#define GST_IS_LOG_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LOG_TRACER)) +#define GST_IS_LOG_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LOG_TRACER)) +#define GST_LOG_TRACER_CAST(obj) ((GstLogTracer *)(obj)) + +typedef struct _GstLogTracer GstLogTracer; +typedef struct _GstLogTracerClass GstLogTracerClass; + +/** + * GstLogTracer: + * + * Opaque #GstLogTracer data structure + */ +struct _GstLogTracer { + GstTracer parent; + + /*< private >*/ +}; + +struct _GstLogTracerClass { + GstTracerClass parent_class; + + /* signals */ +}; + +G_GNUC_INTERNAL GType gst_log_tracer_get_type (void); + +G_END_DECLS + +#endif /* __GST_LOG_TRACER_H__ */ diff --git a/plugins/tracers/gstrusage.c b/plugins/tracers/gstrusage.c new file mode 100644 index 0000000..9086f1e --- /dev/null +++ b/plugins/tracers/gstrusage.c @@ -0,0 +1,376 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstrusage.c: tracing module that logs resource usage stats + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-rusagetracer + * @short_description: log resource usage stats + * + * A tracing module that take rusage() snapshots and logs them. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gstrusage.h" + +#ifdef HAVE_SYS_RESOURCE_H +#ifndef __USE_GNU +# define __USE_GNU /* RUSAGE_THREAD */ +#endif +#include +#endif + +GST_DEBUG_CATEGORY_STATIC (gst_rusage_debug); +#define GST_CAT_DEFAULT gst_rusage_debug + +G_LOCK_DEFINE (_proc); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_rusage_debug, "rusage", 0, "rusage tracer"); +#define gst_rusage_tracer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstRUsageTracer, gst_rusage_tracer, GST_TYPE_TRACER, + _do_init); + +/* remember x measurements per self->window */ +#define WINDOW_SUBDIV 100 + +/* number of cpus to scale cpu-usage in threads */ +static glong num_cpus = 1; + +static GstTracerRecord *tr_proc, *tr_thread; + +typedef struct +{ + /* time spend in this thread */ + GstClockTime tthread; + GstTraceValues *tvs_thread; +} GstThreadStats; + +/* data helper */ + +static void +free_trace_value (gpointer data) +{ + g_slice_free (GstTraceValue, data); +} + +static GstTraceValues * +make_trace_values (GstClockTime window) +{ + GstTraceValues *self = g_slice_new0 (GstTraceValues); + self->window = window; + g_queue_init (&self->values); + return self; +} + +static void +free_trace_values (GstTraceValues * self) +{ + g_queue_foreach (&self->values, (GFunc) free_trace_value, NULL); + g_queue_clear (&self->values); + g_slice_free (GstTraceValues, self); +} + +static gboolean +update_trace_value (GstTraceValues * self, GstClockTime nts, + GstClockTime nval, GstClockTime * dts, GstClockTime * dval) +{ + GstTraceValue *lv; + GstClockTimeDiff dt; + GstClockTime window = self->window; + GQueue *q = &self->values; + GList *node = q->tail; + gboolean ret = FALSE; + + + /* search from the tail of the queue for a good GstTraceValue */ + while (node) { + lv = node->data; + dt = GST_CLOCK_DIFF (lv->ts, nts); + if (dt < window) { + break; + } else { + node = g_list_previous (node); + } + } + + if (node) { + /* calculate the windowed value */ + *dts = dt; + *dval = GST_CLOCK_DIFF (lv->val, nval); + + /* drop all older measurements */ + while (q->tail != node) { + free_trace_value (g_queue_pop_tail (q)); + } + ret = TRUE; + } else { + *dts = nts; + *dval = nval; + } + + /* don't push too many data items */ + lv = q->head ? q->head->data : NULL; + if (!lv || (GST_CLOCK_DIFF (lv->ts, nts) > (window / WINDOW_SUBDIV))) { + /* push the new measurement */ + lv = g_slice_new0 (GstTraceValue); + lv->ts = nts; + lv->val = nval; + g_queue_push_head (q, lv); + } + return ret; +} + + +static void +free_thread_stats (gpointer data) +{ + free_trace_values (((GstThreadStats *) data)->tvs_thread); + g_slice_free (GstThreadStats, data); +} + +static void +do_stats (GstTracer * obj, guint64 ts) +{ + GstRUsageTracer *self = GST_RUSAGE_TRACER_CAST (obj); + GstThreadStats *stats; + gpointer thread_id = g_thread_self (); + guint avg_cpuload, cur_cpuload; + struct rusage ru; + GstClockTime tproc = G_GUINT64_CONSTANT (0); + GstClockTime tthread = G_GUINT64_CONSTANT (0); + GstClockTime dts, dtproc; + +#ifdef HAVE_CLOCK_GETTIME + { + struct timespec now; + + if (!clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &now)) { + tproc = GST_TIMESPEC_TO_TIME (now); + } else { + GST_WARNING_OBJECT (obj, + "clock_gettime (CLOCK_PROCESS_CPUTIME_ID,...) failed: %s", + g_strerror (errno)); + getrusage (RUSAGE_SELF, &ru); + tproc = + GST_TIMEVAL_TO_TIME (ru.ru_utime) + GST_TIMEVAL_TO_TIME (ru.ru_stime); + } + + /* cpu time per thread */ + if (!clock_gettime (CLOCK_THREAD_CPUTIME_ID, &now)) { + tthread = GST_TIMESPEC_TO_TIME (now); + } else { + GST_WARNING_OBJECT (obj, + "clock_gettime (CLOCK_THREAD_CPUTIME_ID,...) failed: %s", + g_strerror (errno)); +#ifdef RUSAGE_THREAD + getrusage (RUSAGE_THREAD, &ru); + tthread = + GST_TIMEVAL_TO_TIME (ru.ru_utime) + GST_TIMEVAL_TO_TIME (ru.ru_stime); +#endif + } + } +#else + getrusage (RUSAGE_SELF, &ru); + tproc = GST_TIMEVAL_TO_TIME (ru.ru_utime) + GST_TIMEVAL_TO_TIME (ru.ru_stime); +#ifdef RUSAGE_THREAD + getrusage (RUSAGE_THREAD, &ru); + tthread = + GST_TIMEVAL_TO_TIME (ru.ru_utime) + GST_TIMEVAL_TO_TIME (ru.ru_stime); +#endif +#endif + /* get stats record for current thread */ + if (!(stats = g_hash_table_lookup (self->threads, thread_id))) { + stats = g_slice_new0 (GstThreadStats); + stats->tvs_thread = make_trace_values (GST_SECOND); + g_hash_table_insert (self->threads, thread_id, stats); + } + stats->tthread = tthread; + + /* Calibrate ts for the process and main thread. For tthread[main] and tproc + * the time is larger than ts, as our base-ts is taken after the process has + * started. + */ + if (G_UNLIKELY (thread_id == self->main_thread_id)) { + self->main_thread_id = NULL; + /* when the registry gets updated, the tproc is less than the debug time ? */ + /* TODO(ensonic): we still see cases where tproc overtakes ts, especially + * when with sync=false, can this be due to multiple cores in use? */ + if (tproc > ts) { + self->tproc_base = tproc - ts; + GST_DEBUG ("rusage: calibrating by %" G_GUINT64_FORMAT ", thread: %" + G_GUINT64_FORMAT ", proc: %" G_GUINT64_FORMAT, + self->tproc_base, stats->tthread, tproc); + stats->tthread -= self->tproc_base; + } + } + /* we always need to correct proc time */ + tproc -= self->tproc_base; + + /* FIXME: how can we take cpu-frequency scaling into account? + * - looking at /sys/devices/system/cpu/cpu0/cpufreq/ + * scale_factor=scaling_max_freq/scaling_cur_freq + * - as a workaround we can switch it via /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor + * cpufreq-selector -g performance + * cpufreq-selector -g ondemand + */ + /* *INDENT-OFF* */ + avg_cpuload = (guint) gst_util_uint64_scale (stats->tthread, + G_GINT64_CONSTANT (1000), ts); + update_trace_value (stats->tvs_thread, ts, stats->tthread, &dts, &dtproc); + cur_cpuload = (guint) gst_util_uint64_scale (dtproc, + G_GINT64_CONSTANT (1000), dts); + gst_tracer_record_log (tr_thread, (guint64) (guintptr) thread_id, ts, + MIN (avg_cpuload, 1000), MIN (cur_cpuload, 1000), stats->tthread); + + avg_cpuload = (guint) gst_util_uint64_scale (tproc / num_cpus, + G_GINT64_CONSTANT (1000), ts); + G_LOCK (_proc); + update_trace_value (self->tvs_proc, ts, tproc, &dts, &dtproc); + G_UNLOCK (_proc); + cur_cpuload = (guint) gst_util_uint64_scale (dtproc / num_cpus, + G_GINT64_CONSTANT (1000), dts); + gst_tracer_record_log (tr_proc, (guint64) getpid (), ts, + MIN (avg_cpuload, 1000), MIN (cur_cpuload, 1000), tproc); + /* *INDENT-ON* */ +} + +/* tracer class */ + +static void +gst_rusage_tracer_finalize (GObject * obj) +{ + GstRUsageTracer *self = GST_RUSAGE_TRACER (obj); + + g_hash_table_destroy (self->threads); + free_trace_values (self->tvs_proc); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_rusage_tracer_class_init (GstRUsageTracerClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gst_rusage_tracer_finalize; + + if ((num_cpus = sysconf (_SC_NPROCESSORS_ONLN)) == -1) { + GST_WARNING ("failed to get number of cpus online"); + if ((num_cpus = sysconf (_SC_NPROCESSORS_CONF)) == -1) { + GST_WARNING ("failed to get number of cpus, assuming 1"); + num_cpus = 1; + } + } + GST_DEBUG ("rusage: num_cpus=%ld", num_cpus); + + /* announce trace formats */ + /* *INDENT-OFF* */ + tr_thread = gst_tracer_record_new ("thread-rusage.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "average-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "description", G_TYPE_STRING, "average cpu usage per thread in ‰", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_AGGREGATED, + "min", G_TYPE_UINT, 0, + "max", G_TYPE_UINT, 1000, + NULL), + "current-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "description", G_TYPE_STRING, "current cpu usage per thread in ‰", + "min", G_TYPE_UINT, 0, + "max", G_TYPE_UINT, 1000, + NULL), + "time", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "time spent in thread in ns", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_AGGREGATED, + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + NULL); + tr_proc = gst_tracer_record_new ("proc-rusage.class", + "process-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PROCESS, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "average-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "description", G_TYPE_STRING, "average cpu usage per process in ‰", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_AGGREGATED, + "min", G_TYPE_UINT, 0, + "max", G_TYPE_UINT, 1000, + NULL), + "current-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "description", G_TYPE_STRING, "current cpu usage per process in ‰", + "min", G_TYPE_UINT, 0, + "max", G_TYPE_UINT, 1000, + NULL), + "time", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "time spent in process in ns", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_AGGREGATED, + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + NULL); + /* *INDENT-ON* */ +} + +static void +gst_rusage_tracer_init (GstRUsageTracer * self) +{ + GstTracer *tracer = GST_TRACER (self); + gint i; + const gchar *hooks[] = { "pad-push-pre", "pad-push-post", "pad-push-list-pre", + "pad-push-list-post", "pad-pull-range-pre", "pad-pull-range-post", + "pad-push-event-pre", "pad-push-event-post", "pad-query-pre", + "pad-query-post", "element-post-message-pre", "element-post-message-post", + "element-query-pre", "element-query-post", "element-new", "element-add-pad", + "element-remove-pad", "element-change-state-pre", + "element-change-state-post", "bin-add-pre", "bin-add-post", + "bin-remove-pre", "bin-remove-post", "pad-link-pre", "pad-link-post", + "pad-unlink-pre", "pad-unlink-post" + }; + + for (i = 0; i < G_N_ELEMENTS (hooks); i++) { + gst_tracing_register_hook (tracer, hooks[i], G_CALLBACK (do_stats)); + } + + self->threads = g_hash_table_new_full (NULL, NULL, NULL, free_thread_stats); + self->tvs_proc = make_trace_values (GST_SECOND); + self->main_thread_id = g_thread_self (); + + GST_DEBUG ("rusage: main thread=%p", self->main_thread_id); +} diff --git a/plugins/tracers/gstrusage.h b/plugins/tracers/gstrusage.h new file mode 100644 index 0000000..b5abbca --- /dev/null +++ b/plugins/tracers/gstrusage.h @@ -0,0 +1,84 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gstrusage.h: tracing module that logs resource usage stats + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_RUSAGE_TRACER_H__ +#define __GST_RUSAGE_TRACER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_RUSAGE_TRACER \ + (gst_rusage_tracer_get_type()) +#define GST_RUSAGE_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RUSAGE_TRACER,GstRUsageTracer)) +#define GST_RUSAGE_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RUSAGE_TRACER,GstRUsageTracerClass)) +#define GST_IS_RUSAGE_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RUSAGE_TRACER)) +#define GST_IS_RUSAGE_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RUSAGE_TRACER)) +#define GST_RUSAGE_TRACER_CAST(obj) ((GstRUsageTracer *)(obj)) + +typedef struct _GstRUsageTracer GstRUsageTracer; +typedef struct _GstRUsageTracerClass GstRUsageTracerClass; + +typedef struct +{ + GstClockTime ts; + GstClockTime val; +} GstTraceValue; + +typedef struct +{ + GstClockTime window; + GQueue values; /* GstTraceValue* */ +} GstTraceValues; + +/** + * GstRUsageTracer: + * + * Opaque #GstRUsageTracer data structure + */ +struct _GstRUsageTracer { + GstTracer parent; + + /*< private >*/ + GHashTable *threads; + GstTraceValues *tvs_proc; + + /* for ts calibration */ + gpointer main_thread_id; + guint64 tproc_base; +}; + +struct _GstRUsageTracerClass { + GstTracerClass parent_class; + + /* signals */ +}; + +G_GNUC_INTERNAL GType gst_rusage_tracer_get_type (void); + +G_END_DECLS + +#endif /* __GST_RUSAGE_TRACER_H__ */ diff --git a/plugins/tracers/gststats.c b/plugins/tracers/gststats.c new file mode 100644 index 0000000..7ca1eca --- /dev/null +++ b/plugins/tracers/gststats.c @@ -0,0 +1,778 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gststats.c: tracing module that logs events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:element-statstracer + * @short_description: log event stats + * + * A tracing module that builds usage statistic for elements and pads. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gststats.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_stats_debug); +#define GST_CAT_DEFAULT gst_stats_debug + +static GQuark data_quark; +G_LOCK_DEFINE (_elem_stats); +G_LOCK_DEFINE (_pad_stats); + +#define _do_init \ + GST_DEBUG_CATEGORY_INIT (gst_stats_debug, "stats", 0, "stats tracer"); \ + data_quark = g_quark_from_static_string ("gststats:data"); +#define gst_stats_tracer_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstStatsTracer, gst_stats_tracer, GST_TYPE_TRACER, + _do_init); + +static GstTracerRecord *tr_new_element; +static GstTracerRecord *tr_new_pad; +static GstTracerRecord *tr_buffer; +static GstTracerRecord *tr_element_query; +static GstTracerRecord *tr_event; +static GstTracerRecord *tr_message; +static GstTracerRecord *tr_query; + +typedef struct +{ + /* we can't rely on the address to be unique over time */ + guint index; + /* for pre + post */ + GstClockTime last_ts; + /* hierarchy */ + guint parent_ix; +} GstPadStats; + +typedef struct +{ + /* we can't rely on the address to be unique over time */ + guint index; + /* for pre + post */ + GstClockTime last_ts; + /* time spend in this element */ + GstClockTime treal; + /* hierarchy */ + guint parent_ix; +} GstElementStats; + +/* data helper */ + +static GstElementStats no_elem_stats = { 0, }; + +static GstElementStats * +fill_element_stats (GstStatsTracer * self, GstElement * element) +{ + GstElementStats *stats = g_slice_new0 (GstElementStats); + + stats->index = self->num_elements++; + stats->parent_ix = G_MAXUINT; + return stats; +} + +static void +log_new_element_stats (GstElementStats * stats, GstElement * element, + GstClockTime elapsed) +{ + gst_tracer_record_log (tr_new_element, (guint64) (guintptr) g_thread_self (), + elapsed, stats->index, stats->parent_ix, GST_OBJECT_NAME (element), + G_OBJECT_TYPE_NAME (element), GST_IS_BIN (element)); +} + +static void +free_element_stats (gpointer data) +{ + g_slice_free (GstElementStats, data); +} + +static GstElementStats * +create_element_stats (GstStatsTracer * self, GstElement * element) +{ + GstElementStats *stats; + + stats = fill_element_stats (self, element); + g_object_set_qdata_full ((GObject *) element, data_quark, stats, + free_element_stats); + + return stats; +} + +static inline GstElementStats * +get_element_stats (GstStatsTracer * self, GstElement * element) +{ + GstElementStats *stats; + gboolean is_new = FALSE; + + if (!element) { + no_elem_stats.index = G_MAXUINT; + return &no_elem_stats; + } + + G_LOCK (_elem_stats); + if (!(stats = g_object_get_qdata ((GObject *) element, data_quark))) { + stats = create_element_stats (self, element); + is_new = TRUE; + } + G_UNLOCK (_elem_stats); + if (G_UNLIKELY (stats->parent_ix == G_MAXUINT)) { + GstElement *parent = GST_ELEMENT_PARENT (element); + if (parent) { + GstElementStats *parent_stats = get_element_stats (self, parent); + stats->parent_ix = parent_stats->index; + } + } + if (G_UNLIKELY (is_new)) { + log_new_element_stats (stats, element, GST_CLOCK_TIME_NONE); + } + return stats; +} + +/* + * Get the element/bin owning the pad. + * + * in: a normal pad + * out: the element + * + * in: a proxy pad + * out: the element that contains the peer of the proxy + * + * in: a ghost pad + * out: the bin owning the ghostpad + */ +/* TODO(ensonic): gst_pad_get_parent_element() would not work here, should we + * add this as new api, e.g. gst_pad_find_parent_element(); + */ +static GstElement * +get_real_pad_parent (GstPad * pad) +{ + GstObject *parent; + + if (!pad) + return NULL; + + parent = GST_OBJECT_PARENT (pad); + + /* if parent of pad is a ghost-pad, then pad is a proxy_pad */ + if (parent && GST_IS_GHOST_PAD (parent)) { + pad = GST_PAD_CAST (parent); + parent = GST_OBJECT_PARENT (pad); + } + return GST_ELEMENT_CAST (parent); +} + +static GstPadStats no_pad_stats = { 0, }; + +static GstPadStats * +fill_pad_stats (GstStatsTracer * self, GstPad * pad) +{ + GstPadStats *stats = g_slice_new0 (GstPadStats); + + stats->index = self->num_pads++; + stats->parent_ix = G_MAXUINT; + + return stats; +} + +static void +log_new_pad_stats (GstPadStats * stats, GstPad * pad) +{ + gst_tracer_record_log (tr_new_pad, (guint64) (guintptr) g_thread_self (), + stats->index, stats->parent_ix, GST_OBJECT_NAME (pad), + G_OBJECT_TYPE_NAME (pad), GST_IS_GHOST_PAD (pad), + GST_PAD_DIRECTION (pad)); +} + +static void +free_pad_stats (gpointer data) +{ + g_slice_free (GstPadStats, data); +} + +static GstPadStats * +get_pad_stats (GstStatsTracer * self, GstPad * pad) +{ + GstPadStats *stats; + gboolean is_new = FALSE; + + if (!pad) { + no_pad_stats.index = G_MAXUINT; + return &no_pad_stats; + } + + G_LOCK (_pad_stats); + if (!(stats = g_object_get_qdata ((GObject *) pad, data_quark))) { + stats = fill_pad_stats (self, pad); + g_object_set_qdata_full ((GObject *) pad, data_quark, stats, + free_pad_stats); + is_new = TRUE; + } + G_UNLOCK (_pad_stats); + if (G_UNLIKELY (stats->parent_ix == G_MAXUINT)) { + GstElement *elem = get_real_pad_parent (pad); + if (elem) { + GstElementStats *elem_stats = get_element_stats (self, elem); + + stats->parent_ix = elem_stats->index; + } + } + if (G_UNLIKELY (is_new)) { + log_new_pad_stats (stats, pad); + } + return stats; +} + +static void +do_buffer_stats (GstStatsTracer * self, GstPad * this_pad, + GstPadStats * this_pad_stats, GstPad * that_pad, + GstPadStats * that_pad_stats, GstBuffer * buf, GstClockTime elapsed) +{ + GstElement *this_elem = get_real_pad_parent (this_pad); + GstElementStats *this_elem_stats = get_element_stats (self, this_elem); + GstElement *that_elem = get_real_pad_parent (that_pad); + GstElementStats *that_elem_stats = get_element_stats (self, that_elem); + GstClockTime pts = GST_BUFFER_PTS (buf); + GstClockTime dts = GST_BUFFER_DTS (buf); + GstClockTime dur = GST_BUFFER_DURATION (buf); + + gst_tracer_record_log (tr_buffer, (guint64) (guintptr) g_thread_self (), + elapsed, this_pad_stats->index, this_elem_stats->index, + that_pad_stats->index, that_elem_stats->index, gst_buffer_get_size (buf), + GST_CLOCK_TIME_IS_VALID (pts), pts, GST_CLOCK_TIME_IS_VALID (dts), dts, + GST_CLOCK_TIME_IS_VALID (dur), dur, GST_BUFFER_FLAGS (buf)); +} + +static void +do_query_stats (GstStatsTracer * self, GstPad * this_pad, + GstPadStats * this_pad_stats, GstPad * that_pad, + GstPadStats * that_pad_stats, GstQuery * qry, GstClockTime elapsed, + gboolean have_res, gboolean res) +{ + GstElement *this_elem = get_real_pad_parent (this_pad); + GstElementStats *this_elem_stats = get_element_stats (self, this_elem); + GstElement *that_elem = get_real_pad_parent (that_pad); + GstElementStats *that_elem_stats = get_element_stats (self, that_elem); + + gst_tracer_record_log (tr_query, (guint64) (guintptr) g_thread_self (), + elapsed, this_pad_stats->index, this_elem_stats->index, + that_pad_stats->index, that_elem_stats->index, GST_QUERY_TYPE_NAME (qry), + gst_query_get_structure (qry), have_res, res); +} + +static void +do_element_stats (GstStatsTracer * self, GstPad * pad, GstClockTime elapsed1, + GstClockTime elapsed2) +{ + GstClockTimeDiff elapsed = GST_CLOCK_DIFF (elapsed1, elapsed2); + GstObject *parent = GST_OBJECT_PARENT (pad); + GstElement *this = + GST_ELEMENT_CAST (GST_IS_PAD (parent) ? GST_OBJECT_PARENT (parent) : + parent); + GstElementStats *this_stats = get_element_stats (self, this); + GstPad *peer_pad = GST_PAD_PEER (pad); + GstElementStats *peer_stats; + + if (!peer_pad) + return; + + /* walk the ghost pad chain downstream to get the real pad */ + /* if parent of peer_pad is a ghost-pad, then peer_pad is a proxy_pad */ + parent = GST_OBJECT_PARENT (peer_pad); + if (parent && GST_IS_GHOST_PAD (parent)) { + peer_pad = GST_PAD_CAST (parent); + /* if this is now the ghost pad, get the peer of this */ + get_pad_stats (self, peer_pad); + if ((parent = GST_OBJECT_PARENT (peer_pad))) { + get_element_stats (self, GST_ELEMENT_CAST (parent)); + } + peer_pad = GST_PAD_PEER (GST_GHOST_PAD_CAST (peer_pad)); + parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL; + } + /* walk the ghost pad chain upstream to get the real pad */ + /* if peer_pad is a ghost-pad, then parent is a bin and it is the parent of + * a proxy_pad */ + while (peer_pad && GST_IS_GHOST_PAD (peer_pad)) { + get_pad_stats (self, peer_pad); + get_element_stats (self, GST_ELEMENT_CAST (parent)); + peer_pad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (peer_pad)); + parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL; + } + + if (!parent) { + printf ("%" GST_TIME_FORMAT + " transmission on unparented target pad %s_%s -> %s_%s\n", + GST_TIME_ARGS (elapsed), GST_DEBUG_PAD_NAME (pad), + GST_DEBUG_PAD_NAME (peer_pad)); + return; + } + peer_stats = get_element_stats (self, GST_ELEMENT_CAST (parent)); + + /* we'd like to gather time spend in each element, but this does not make too + * much sense yet + * pure push/pull-based: + * - the time spend in the push/pull_range is accounted for the peer and + * removed from the current element + * - this works for chains + * - drawback is sink elements that block to sync have a high time usage + * - we could rerun the ests with sync=false + * both: + * - a.g. demuxers both push and pull. thus we subtract time for the pull + * and the push operations, but never add anything. + * - can we start a counter after push/pull in such elements and add then + * time to the element upon next pad activity? + */ +#if 1 + /* this does not make sense for demuxers */ + this_stats->treal -= elapsed; + peer_stats->treal += elapsed; +#else + /* this creates several >100% figures */ + this_stats->treal += GST_CLOCK_DIFF (this_stats->last_ts, elapsed2) - elapsed; + peer_stats->treal += elapsed; + this_stats->last_ts = elapsed2; + peer_stats->last_ts = elapsed2; +#endif +} + +/* hooks */ + +static void +do_push_buffer_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, + GstBuffer * buffer) +{ + GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); + GstPad *that_pad = GST_PAD_PEER (this_pad); + GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); + + do_buffer_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, + buffer, ts); +} + +static void +do_push_buffer_post (GstStatsTracer * self, guint64 ts, GstPad * pad, + GstFlowReturn res) +{ + GstPadStats *stats = get_pad_stats (self, pad); + + do_element_stats (self, pad, stats->last_ts, ts); +} + +typedef struct +{ + GstStatsTracer *self; + GstPad *this_pad; + GstPadStats *this_pad_stats; + GstPad *that_pad; + GstPadStats *that_pad_stats; + guint64 ts; +} DoPushBufferListArgs; + +static gboolean +do_push_buffer_list_item (GstBuffer ** buffer, guint idx, gpointer user_data) +{ + DoPushBufferListArgs *args = (DoPushBufferListArgs *) user_data; + + do_buffer_stats (args->self, args->this_pad, args->this_pad_stats, + args->that_pad, args->that_pad_stats, *buffer, args->ts); + return TRUE; +} + +static void +do_push_buffer_list_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, + GstBufferList * list) +{ + GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); + GstPad *that_pad = GST_PAD_PEER (this_pad); + GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); + DoPushBufferListArgs args = { self, this_pad, this_pad_stats, that_pad, + that_pad_stats, ts + }; + + gst_buffer_list_foreach (list, do_push_buffer_list_item, &args); +} + +static void +do_push_buffer_list_post (GstStatsTracer * self, guint64 ts, GstPad * pad, + GstFlowReturn res) +{ + GstPadStats *stats = get_pad_stats (self, pad); + + do_element_stats (self, pad, stats->last_ts, ts); +} + +static void +do_pull_range_pre (GstStatsTracer * self, guint64 ts, GstPad * pad) +{ + GstPadStats *stats = get_pad_stats (self, pad); + stats->last_ts = ts; +} + +static void +do_pull_range_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad, + GstBuffer * buffer) +{ + GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); + guint64 last_ts = this_pad_stats->last_ts; + GstPad *that_pad = GST_PAD_PEER (this_pad); + GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); + + if (buffer != NULL) { + do_buffer_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, + buffer, ts); + } + do_element_stats (self, this_pad, last_ts, ts); +} + +static void +do_push_event_pre (GstStatsTracer * self, guint64 ts, GstPad * pad, + GstEvent * ev) +{ + GstElement *elem = get_real_pad_parent (pad); + GstElementStats *elem_stats = get_element_stats (self, elem); + GstPadStats *pad_stats = get_pad_stats (self, pad); + + elem_stats->last_ts = ts; + gst_tracer_record_log (tr_event, (guint64) (guintptr) g_thread_self (), ts, + pad_stats->index, elem_stats->index, GST_EVENT_TYPE_NAME (ev)); +} + +static void +do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem, + GstMessage * msg) +{ + GstElementStats *stats = get_element_stats (self, elem); + const GstStructure *msg_s = gst_message_get_structure (msg); + GstStructure *s = + msg_s ? (GstStructure *) msg_s : gst_structure_new_empty ("dummy"); + + stats->last_ts = ts; + /* FIXME: work out whether using NULL instead of a dummy struct would work */ + gst_tracer_record_log (tr_message, (guint64) (guintptr) g_thread_self (), ts, + stats->index, GST_MESSAGE_TYPE_NAME (msg), s); + if (s != msg_s) + gst_structure_free (s); +} + +static void +do_element_new (GstStatsTracer * self, guint64 ts, GstElement * elem) +{ + GstElementStats *stats; + + stats = create_element_stats (self, elem); + log_new_element_stats (stats, elem, ts); +} + +static void +do_element_query_pre (GstStatsTracer * self, guint64 ts, GstElement * elem, + GstQuery * qry) +{ + GstElementStats *stats = get_element_stats (self, elem); + + stats->last_ts = ts; + gst_tracer_record_log (tr_element_query, + (guint64) (guintptr) g_thread_self (), ts, stats->index, + GST_QUERY_TYPE_NAME (qry)); +} + +static void +do_query_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, + GstQuery * qry) +{ + GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); + GstPad *that_pad = GST_PAD_PEER (this_pad); + GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); + + do_query_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, + qry, ts, FALSE, FALSE); +} + +static void +do_query_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad, + GstQuery * qry, gboolean res) +{ + GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); + GstPad *that_pad = GST_PAD_PEER (this_pad); + GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); + + do_query_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, + qry, ts, TRUE, res); +} + +/* tracer class */ + +static void +gst_stats_tracer_class_init (GstStatsTracerClass * klass) +{ + /* announce trace formats */ + /* *INDENT-OFF* */ + tr_buffer = gst_tracer_record_new ("buffer.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "peer-pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "peer-element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "buffer-size", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "description", G_TYPE_STRING, "size of buffer in bytes", + "min", G_TYPE_UINT, 0, + "max", G_TYPE_UINT, G_MAXUINT, + NULL), + "buffer-pts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "presentation timestamp of the buffer in ns", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_OPTIONAL, + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + "buffer-dts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "decoding timestamp of the buffer in ns", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_OPTIONAL, + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + "buffer-duration", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "duration of the buffer in ns", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_OPTIONAL, + "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0), + "max", G_TYPE_UINT64, G_MAXUINT64, + NULL), + "buffer-flags", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, GST_TYPE_BUFFER_FLAGS, + "description", G_TYPE_STRING, "flags of the buffer", + NULL), + NULL); + tr_event = gst_tracer_record_new ("event.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the event", + NULL), + NULL); + tr_message = gst_tracer_record_new ("message.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the message", + NULL), + "structure", GST_TYPE_STRUCTURE, gst_structure_new ("structure", + "type", G_TYPE_GTYPE, GST_TYPE_STRUCTURE, + "description", G_TYPE_STRING, "message structure", + NULL), + NULL); + tr_element_query = gst_tracer_record_new ("element-query.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the query", + NULL), + NULL); + tr_query = gst_tracer_record_new ("query.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "peer-pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "peer-element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the query", + NULL), + "structure", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, GST_TYPE_STRUCTURE, + "description", G_TYPE_STRING, "query structure", + NULL), + "res", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_BOOLEAN, + "description", G_TYPE_STRING, "query result", + "flags", GST_TYPE_TRACER_VALUE_FLAGS, GST_TRACER_VALUE_FLAGS_OPTIONAL, + NULL), + NULL); + tr_new_element = gst_tracer_record_new ("new-element.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "description", G_TYPE_STRING, "event ts", + NULL), + "ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "parent-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the element", + NULL), + "type", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "type name of the element", + NULL), + "is-bin", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_BOOLEAN, + "description", G_TYPE_STRING, "is element a bin", + NULL), + NULL); + tr_new_pad = gst_tracer_record_new ("new-pad.class", + "thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT64, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_THREAD, + NULL), + "ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD, + NULL), + "parent-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope", + "type", G_TYPE_GTYPE, G_TYPE_UINT, + "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, + NULL), + "name", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "name of the pad", + NULL), + "type", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + "description", G_TYPE_STRING, "type name of the pad", + NULL), + "is-ghostpad", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_BOOLEAN, + "description", G_TYPE_STRING, "is pad a ghostpad", + NULL), + "pad-direction", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, GST_TYPE_PAD_DIRECTION, + "description", G_TYPE_STRING, "ipad direction", + NULL), + NULL); + /* *INDENT-ON* */ +} + +static void +gst_stats_tracer_init (GstStatsTracer * self) +{ + GstTracer *tracer = GST_TRACER (self); + + gst_tracing_register_hook (tracer, "pad-push-pre", + G_CALLBACK (do_push_buffer_pre)); + gst_tracing_register_hook (tracer, "pad-push-post", + G_CALLBACK (do_push_buffer_post)); + gst_tracing_register_hook (tracer, "pad-push-list-pre", + G_CALLBACK (do_push_buffer_list_pre)); + gst_tracing_register_hook (tracer, "pad-push-list-post", + G_CALLBACK (do_push_buffer_list_post)); + gst_tracing_register_hook (tracer, "pad-pull-range-pre", + G_CALLBACK (do_pull_range_pre)); + gst_tracing_register_hook (tracer, "pad-pull-range-post", + G_CALLBACK (do_pull_range_post)); + gst_tracing_register_hook (tracer, "pad-push-event-pre", + G_CALLBACK (do_push_event_pre)); + gst_tracing_register_hook (tracer, "element-new", + G_CALLBACK (do_element_new)); + gst_tracing_register_hook (tracer, "element-post-message-pre", + G_CALLBACK (do_post_message_pre)); + gst_tracing_register_hook (tracer, "element-query-pre", + G_CALLBACK (do_element_query_pre)); + gst_tracing_register_hook (tracer, "pad-query-pre", + G_CALLBACK (do_query_pre)); + gst_tracing_register_hook (tracer, "pad-query-post", + G_CALLBACK (do_query_post)); +} diff --git a/plugins/tracers/gststats.h b/plugins/tracers/gststats.h new file mode 100644 index 0000000..a846b1b --- /dev/null +++ b/plugins/tracers/gststats.h @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gststats.h: tracing module that logs events + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_STATS_TRACER_H__ +#define __GST_STATS_TRACER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STATS_TRACER \ + (gst_stats_tracer_get_type()) +#define GST_STATS_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STATS_TRACER,GstStatsTracer)) +#define GST_STATS_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STATS_TRACER,GstStatsTracerClass)) +#define GST_IS_STATS_TRACER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STATS_TRACER)) +#define GST_IS_STATS_TRACER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STATS_TRACER)) +#define GST_STATS_TRACER_CAST(obj) ((GstStatsTracer *)(obj)) + +typedef struct _GstStatsTracer GstStatsTracer; +typedef struct _GstStatsTracerClass GstStatsTracerClass; + +/** + * GstStatsTracer: + * + * Opaque #GstStatsTracer data structure + */ +struct _GstStatsTracer { + GstTracer parent; + + /*< private >*/ + guint num_elements, num_pads; +}; + +struct _GstStatsTracerClass { + GstTracerClass parent_class; + + /* signals */ +}; + +G_GNUC_INTERNAL GType gst_stats_tracer_get_type (void); + +G_END_DECLS + +#endif /* __GST_STATS_TRACER_H__ */ diff --git a/plugins/tracers/gsttracers.c b/plugins/tracers/gsttracers.c new file mode 100644 index 0000000..b03e25a --- /dev/null +++ b/plugins/tracers/gsttracers.c @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gsttracers.c: tracing modules + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gstlatency.h" +#include "gstlog.h" +#include "gstrusage.h" +#include "gststats.h" +#include "gstleaks.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_tracer_register (plugin, "latency", gst_latency_tracer_get_type ())) + return FALSE; +#ifndef GST_DISABLE_GST_DEBUG + if (!gst_tracer_register (plugin, "log", gst_log_tracer_get_type ())) + return FALSE; +#endif +#ifdef HAVE_GETRUSAGE + if (!gst_tracer_register (plugin, "rusage", gst_rusage_tracer_get_type ())) + return FALSE; +#endif + if (!gst_tracer_register (plugin, "stats", gst_stats_tracer_get_type ())) + return FALSE; + if (!gst_tracer_register (plugin, "leaks", gst_leaks_tracer_get_type ())) + return FALSE; + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, coretracers, + "GStreamer core tracers", plugin_init, VERSION, GST_LICENSE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/plugins/tracers/meson.build b/plugins/tracers/meson.build new file mode 100644 index 0000000..5227a1a --- /dev/null +++ b/plugins/tracers/meson.build @@ -0,0 +1,27 @@ +gst_tracers_sources = [ + 'gstlatency.c', + 'gstleaks.c', + 'gststats.c', + 'gsttracers.c', +] + +if not disable_gst_debug + gst_tracers_sources += ['gstlog.c'] +endif + +if cdata.has('HAVE_GETRUSAGE') + gst_tracers_sources += ['gstrusage.c'] +endif + +tracers_args = gst_c_args + ['-DGST_USE_UNSTABLE_API'] + +gst_tracers = library('gstcoretracers', + gst_tracers_sources, + c_args : tracers_args, + include_directories : [configinc], + dependencies : [gst_dep], + link_with : printf_lib, + install : true, + install_dir : '@0@/gstreamer-1.0'.format(get_option('libdir')), +) + diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..368a2ba --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +af ast az be bg ca cs da de en_GB eo es el eu fi fr fur gl hr hu id it ja lt nb nl pl pt_BR ro ru rw sk sl sq sr sv tr uk vi zh_CN zh_TW diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..fecf500 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,429 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.17 +GETTEXT_MACRO_VERSION = 0.17 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: check-macro-version all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +check-macro-version: + @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \ + package_gnu='GNU '; \ + else \ + package_gnu=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + $(mkdir_p) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + $(mkdir_p) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && $(SHELL) ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..8f4e7d0 --- /dev/null +++ b/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 = gstreamer-1.0 + +# 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/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..fe3d9c6 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,26 @@ +# Files from the GStreamer distribution which have already been +# marked to allow runtime translations of messages + +gst/gst.c +gst/gstelement.c +gst/gsterror.c +gst/gstpipeline.c +gst/gstregistry.c +gst/gsttaglist.c +gst/gsturi.c +gst/gstutils.c +gst/parse/grammar.y +libs/gst/base/gstbasesink.c +libs/gst/base/gstbasesrc.c +plugins/elements/gstcapsfilter.c +plugins/elements/gstdownloadbuffer.c +plugins/elements/gstfakesink.c +plugins/elements/gstfdsink.c +plugins/elements/gstfilesink.c +plugins/elements/gstfilesrc.c +plugins/elements/gstidentity.c +plugins/elements/gstqueue.c +plugins/elements/gstqueue2.c +plugins/elements/gsttypefindelement.c +tools/gst-inspect.c +tools/gst-launch.c diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 0000000..9c2a995 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,47 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/af.gmo b/po/af.gmo new file mode 100644 index 0000000..8076224 Binary files /dev/null and b/po/af.gmo differ diff --git a/po/af.po b/po/af.po new file mode 100644 index 0000000..309cab2 --- /dev/null +++ b/po/af.po @@ -0,0 +1,1410 @@ +# Translation of gstreamer 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: gstreamer 0.9.7\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2005-12-05 11:45+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 "Print the GStreamer version" +msgstr "Vertoon die GStreamer weergawe" + +msgid "Make all warnings fatal" +msgstr "Maak alle waarskuwings fataal" + +msgid "Print available debug categories and exit" +msgstr "Vertoon beskikbare ontfoutkategorië en stop" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Verstek ontfoutvlak vanaf 1 (slegs fout) tot 5 (enigiets) of 0 vir geen " +"afvoer" + +msgid "LEVEL" +msgstr "VLAK" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Komma-geskeide lys van kategorie_naam:vlak pare om die individuele " +"kategorieë op te stel. Byvoorbeeld: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LYS" + +msgid "Disable colored debugging output" +msgstr "Skakel gekleurde ontfout-afvoer af" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Skakel ontfouting af" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Aktiveer volledige diagnostiese boodskappe vir inproplaaiing" + +msgid "Colon-separated paths containing plugins" +msgstr "Dubbelpunt-geskeide paaie wat inproppe bevat" + +msgid "PATHS" +msgstr "PAAIE" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Komma-geskeide lys van inproppe om vooraf te laai by die lys gestoor in die " +"omgewingsveranderlike GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "INPROPPE" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Moenie segmenteringsfoute tydens inproplaaiing ondervang nie" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "GStreamer Opsies" + +msgid "Show GStreamer Options" +msgstr "Wys GStreamer opsies" + +msgid "Unknown option" +msgstr "Onbekende opsie" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer het 'n fout teëgekom in die algemene kernbiblioteek." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer ontwikkelaars was te lui om 'n foutkode vir hierdie fout toe te " +"ken. " + +msgid "Internal GStreamer error: code not implemented." +msgstr "Interne GStreamer-fout: code not implemented." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "Interne GStreamer-fout: pad problem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Interne GStreamer-fout: thread problem." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Interne GStreamer-fout: negotiation problem." + +msgid "Internal GStreamer error: event problem." +msgstr "Interne GStreamer-fout: event problem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Interne GStreamer-fout: seek problem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Interne GStreamer-fout: caps problem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Interne GStreamer-fout: tag problem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Jou GStreamer-installasie kort 'n inprop." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Interne GStreamer-fout: seek problem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "" +"GStreamer het 'n fout teëgekom in 'n algemene ondersteuningsbiblioteek." + +msgid "Could not initialize supporting library." +msgstr "Ondersteuningsbiblioteek kon nie aan die gang gesit word nie." + +msgid "Could not close supporting library." +msgstr "Kon nie ondersteunende biblioteek toemaak nie." + +#, fuzzy +msgid "Could not configure supporting library." +msgstr "Kon nie ondersteunende biblioteek toemaak nie." + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer het 'n algemene hulpbronfout teëgekom." + +msgid "Resource not found." +msgstr "Hulpbron nie gevind nie." + +msgid "Resource busy or not available." +msgstr "Hulpbron is besig of nie beskikbaar nie." + +msgid "Could not open resource for reading." +msgstr "Kon nie hulpbron oopmaak om te lees nie." + +msgid "Could not open resource for writing." +msgstr "Kon nie hulpbron oopmaak om te skryf nie." + +msgid "Could not open resource for reading and writing." +msgstr "Kon nie hulpbron oopmaak vir lees en skryf nie." + +msgid "Could not close resource." +msgstr "Kon nie hulpbron toemaak nie." + +msgid "Could not read from resource." +msgstr "Kon nie uit hulpbron lees nie." + +msgid "Could not write to resource." +msgstr "Kon nie na hulpbron skryf nie." + +msgid "Could not perform seek on resource." +msgstr "Kon nie soekopdrag uitvoer op hulpbron nie." + +msgid "Could not synchronize on resource." +msgstr "Kon nie hulpbron sinkroniseer nie." + +msgid "Could not get/set settings from/on resource." +msgstr "Kon nie hulpbronstellings verkry/verander nie." + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Kon nie na hulpbron skryf nie." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer het 'n algemene stroomfout teëgekom." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Element implementeer nie die hantering van hierdie stroom nie. Meld asb. 'n " +"fout aan." + +msgid "Could not determine type of stream." +msgstr "Kon nie die stroomtipe bepaal nie." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Die stroom is nie van dieselfde tipe as wat deur die element hanteer word " +"nie." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Daar is nie 'n kodek beskikbaar om hierdie stroom se tipe te hanteer nie." + +msgid "Could not decode stream." +msgstr "Kon nie stroom dekodeer nie." + +msgid "Could not encode stream." +msgstr "Kon nie stroom enkodeer nie." + +msgid "Could not demultiplex stream." +msgstr "Kon nie stroom demultiplekseer nie." + +msgid "Could not multiplex stream." +msgstr "Kon nie stroom multiplekseer nie." + +msgid "The stream is in the wrong format." +msgstr "" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "Geen foutboodskap vir domein %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Geen standaard foutboodskap vir domein %s en kode %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "titel" + +msgid "commonly used title" +msgstr "algemeenbekende titel" + +msgid "title sortname" +msgstr "" + +#, fuzzy +msgid "commonly used title for sorting purposes" +msgstr "algemeenbekende titel" + +msgid "artist" +msgstr "kunstenaar" + +msgid "person(s) responsible for the recording" +msgstr "persoon(e) verantwoordelik vir die opname" + +msgid "artist sortname" +msgstr "" + +#, fuzzy +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persoon(e) verantwoordelik vir die opname" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album wat hierdie data bevat" + +msgid "album sortname" +msgstr "" + +#, fuzzy +msgid "album containing this data for sorting purposes" +msgstr "album wat hierdie data bevat" + +#, fuzzy +msgid "album artist" +msgstr "kunstenaar" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "die datum waarop die data geskep is (as 'n GDate-struktuur)" + +#, fuzzy +msgid "datetime" +msgstr "datum" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "die datum waarop die data geskep is (as 'n GDate-struktuur)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre waartoe hierdie data behoort" + +msgid "comment" +msgstr "kommentaar" + +msgid "free text commenting the data" +msgstr "vrye teks met kommentaar op die data" + +#, fuzzy +msgid "extended comment" +msgstr "kommentaar" + +#, fuzzy +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "vrye teks met kommentaar op die data" + +msgid "track number" +msgstr "snitnommer" + +msgid "track number inside a collection" +msgstr "snitnommer binne die versameling" + +msgid "track count" +msgstr "aantal snitte" + +msgid "count of tracks inside collection this track belongs to" +msgstr "aantal snitte in die versameling waaruit hierdie snit kom" + +msgid "disc number" +msgstr "skyfnommer" + +msgid "disc number inside a collection" +msgstr "skyfnommer binne 'n versameling" + +msgid "disc count" +msgstr "aantal skywe" + +msgid "count of discs inside collection this disc belongs to" +msgstr "aantal skywe in die versameling waaruit hierdie skyf kom" + +msgid "location" +msgstr "ligging" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "beskrywing" + +msgid "short text describing the content of the data" +msgstr "kort teks wat die inhoud van die data beskryf" + +msgid "version" +msgstr "weergawe" + +msgid "version of this data" +msgstr "weergawe van hierdie data" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "Internasionale Standaard Opnamekode - sien http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organization" + +msgid "copyright" +msgstr "kopiereg" + +msgid "copyright notice of the data" +msgstr "kopieregnota van die data" + +#, fuzzy +msgid "copyright uri" +msgstr "kopiereg" + +#, fuzzy +msgid "URI to the copyright notice of the data" +msgstr "kopieregnota van die data" + +#, fuzzy +msgid "encoded by" +msgstr "enkodeerder" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "kontak" + +msgid "contact information" +msgstr "kontakinformasie" + +msgid "license" +msgstr "lisensie" + +msgid "license of data" +msgstr "datalisensie" + +#, fuzzy +msgid "license uri" +msgstr "lisensie" + +#, fuzzy +msgid "URI to the license of the data" +msgstr "datalisensie" + +msgid "performer" +msgstr "kunstenaar" + +msgid "person(s) performing" +msgstr "kunstenaar(s)" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "persoon(e) verantwoordelik vir die opname" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "duur" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "lengte in GStreamer tydeenhede (nanosekondes)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "kodek waarmee die data gestoor is" + +msgid "video codec" +msgstr "video-kodek" + +msgid "codec the video data is stored in" +msgstr "kodek waarmee die videodata gestoor is" + +msgid "audio codec" +msgstr "oudio-kodek" + +msgid "codec the audio data is stored in" +msgstr "kodek waarmee die oudiodata gestoor is" + +#, fuzzy +msgid "subtitle codec" +msgstr "video-kodek" + +#, fuzzy +msgid "codec the subtitle data is stored in" +msgstr "kodek waarmee die videodata gestoor is" + +#, fuzzy +msgid "container format" +msgstr "kontakinformasie" + +#, fuzzy +msgid "container format the data is stored in" +msgstr "kodek waarmee die data gestoor is" + +msgid "bitrate" +msgstr "bistempo" + +msgid "exact or average bitrate in bits/s" +msgstr "presiese of gimiddelde bistempo in bisse/sekonde" + +msgid "nominal bitrate" +msgstr "nominale bistempo" + +msgid "nominal bitrate in bits/s" +msgstr "nomminale bistempo is bisse/sekonde" + +msgid "minimum bitrate" +msgstr "minimum bistempo" + +msgid "minimum bitrate in bits/s" +msgstr "minimum bistempo is bisse/s" + +msgid "maximum bitrate" +msgstr "maksimum bistempo" + +msgid "maximum bitrate in bits/s" +msgstr "maksimum bistempo in bisse/sekonde" + +msgid "encoder" +msgstr "enkodeerder" + +msgid "encoder used to encode this stream" +msgstr "enkodeerder wat hierdie stroom enkodeer" + +msgid "encoder version" +msgstr "enkodeerderweergawe" + +msgid "version of the encoder used to encode this stream" +msgstr "weergawe van die enkodeerder wat hierdie stroom enkodeer" + +msgid "serial" +msgstr "reeks" + +msgid "serial number of track" +msgstr "serienommer van snit" + +msgid "replaygain track gain" +msgstr "terugspeelversterking snitversterking" + +msgid "track gain in db" +msgstr "snitversterking (in db)" + +msgid "replaygain track peak" +msgstr "terugspeelversterking snittoppunt" + +msgid "peak of the track" +msgstr "toppunt van die snit" + +msgid "replaygain album gain" +msgstr "terugspeelversterking albumversterking" + +msgid "album gain in db" +msgstr "albumversterking (in db)" + +msgid "replaygain album peak" +msgstr "terugspeelversterking albumtoppunt" + +msgid "peak of the album" +msgstr "toppunt van die album" + +#, fuzzy +msgid "replaygain reference level" +msgstr "terugspeelversterking snittoppunt" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "taalkode" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "taalkode vir hierdie stroom, wat voldoen aan ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "taalkode" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +#, fuzzy +msgid "image related to this stream" +msgstr "enkodeerder wat hierdie stroom enkodeer" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +#, fuzzy +msgid "file attached to this stream" +msgstr "enkodeerder wat hierdie stroom enkodeer" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +#, fuzzy +msgid "comma separated keywords describing the content" +msgstr "kort teks wat die inhoud van die data beskryf" + +#, fuzzy +msgid "geo location name" +msgstr "ligging" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +#, fuzzy +msgid "geo location country" +msgstr "ligging" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location city" +msgstr "ligging" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location sublocation" +msgstr "ligging" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "ligging" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "ligging" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "ligging" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "ligging" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#, fuzzy +msgid "episode number" +msgstr "skyfnommer" + +msgid "The episode number in the season the media is part of" +msgstr "" + +#, fuzzy +msgid "season number" +msgstr "skyfnommer" + +msgid "The season number of the show the media is part of" +msgstr "" + +#, fuzzy +msgid "lyrics" +msgstr "lisensie" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "persoon(e) verantwoordelik vir die opname" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +#, fuzzy +msgid "user rating" +msgstr "duur" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "weergawe van die enkodeerder wat hierdie stroom enkodeer" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "weergawe van die enkodeerder wat hierdie stroom enkodeer" + +#, fuzzy +msgid "application name" +msgstr "ligging" + +#, fuzzy +msgid "Application used to create the media" +msgstr "weergawe van die enkodeerder wat hierdie stroom enkodeer" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FOUT: vanaf element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Addisionele ontfout-inligting:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "Geen eienskap \"%s\" in element \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "kon nie eienskap \"%s\" in element \"%s\" stel na \"%s\" nie" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "Kon nie %s aan %s verbind nie" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "kon nie aan bestemming-element vir URI \"%s\" verbind nie" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "Kon nie %s aan %s verbind nie" + +#, c-format +msgid "could not link %s to %s" +msgstr "Kon nie %s aan %s verbind nie" + +#, c-format +msgid "no element \"%s\"" +msgstr "geen element \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kon nie caps \"%s\" ontleed nie" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "geen bestemming-element vir URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "geen bronelement vir URI \"%s\"" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "gespesifiseerde leë houer \"%s\" is ontoelaatbaar" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "geen houer \"%s\", dit word oorgeslaan" + +msgid "empty pipeline not allowed" +msgstr "leë pyplyn word nie toegelaat nie" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "Interne datavloeiprobleem." + +msgid "Internal data flow error." +msgstr "Interne datavloeifout." + +#, fuzzy +msgid "Internal clock error." +msgstr "Interne datavloeifout." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, fuzzy, c-format +msgid "Could not create temp file \"%s\"." +msgstr "kon nie inligting oor \"%s\" kry nie." + +#, fuzzy, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Kon nie lêer \"%s\" oopmaak om te lees nie. %s." + +#, fuzzy +msgid "Error while writing to download file." +msgstr "Fout tydens skryf na lêer \"%s\"." + +msgid "No file name specified for writing." +msgstr "Geen lêernaam om heen te skryf nie." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Kon nie lêer \"%s\" oopmaak om in te skryf nie." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fout met toemaak van lêer \"%s\"." + +#, fuzzy, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fout tydens skryf na lêer \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fout tydens skryf na lêer \"%s\"." + +msgid "No file name specified for reading." +msgstr "Geen lêernaam om uit te lees nie." + +#, fuzzy, c-format +msgid "Could not get info on \"%s\"." +msgstr "kon nie inligting oor \"%s\" kry nie." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" is 'n gids." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Lêer \"%s\" is 'n sok." + +msgid "Failed after iterations as requested." +msgstr "Mislukking na die vasgestelde aantal probeerslae." + +msgid "caps" +msgstr "caps" + +msgid "detected capabilities in stream" +msgstr "vermoëns wat bespeur kon word in die stroom" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "album wat hierdie data bevat" + +#, fuzzy +msgid "Stream contains no data." +msgstr "album wat hierdie data bevat" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +#, fuzzy +msgid "writable" +msgstr "titel" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +#, fuzzy +msgid "Total count: " +msgstr "aantal snitte" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +msgid "Print all elements" +msgstr "Druk alle elemente" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, fuzzy, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Kon nie lêer \"%s\" oopmaak om in te skryf nie." + +#, fuzzy, c-format +msgid "No such element or plugin '%s'\n" +msgstr "geen bronelement vir URI \"%s\"" + +msgid "Index statistics" +msgstr "" + +#, fuzzy, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Boodskap vanaf element \"%s\" (%s):" + +#, fuzzy, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Boodskap vanaf element \"%s\" (%s):" + +#, fuzzy, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Boodskap vanaf element \"%s\" (%s):" + +#, fuzzy, c-format +msgid "Got message #%u (%s): " +msgstr "Boodskap vanaf element \"%s\" (%s):" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "EOS gekry vanaf element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETIKET GEVIND : gevind by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ETIKET GEVIND : gevind by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETIKET GEVIND : gevind by element \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ETIKET GEVIND : gevind by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ETIKET GEVIND : gevind by element \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, fuzzy, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "FOUT: vanaf element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +#, fuzzy +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Pyplyn word gestel na SPEEL ...\n" + +#, fuzzy +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Stel pyplyn na POUSEER ...\n" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +#, fuzzy +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Pyplyn word gestel na NULL ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "geen element \"%s\"" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "FOUT: vanaf element %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Wys etikette (ook bekend as metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Wys statusinligting en kennisgewings van eienskappe" + +#, fuzzy +msgid "Do not print any progress information" +msgstr "Moenie statusinligting van TIPE wys nie" + +msgid "Output messages" +msgstr "Afvoerboodskappe" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Moenie 'n fouthanteerder installeer nie" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FOUT: pyplyn kon nie opgestel word nie: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FOUT: pyplyn kon nie opgestel word nie.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "WAARSKUWING: foutiewe pyplyn: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FOUT: die pyplynelement kon nie gevind word nie.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Stel pyplyn na POUSEER ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FOUT: pyplyn wil nie pouseer nie.\n" + +#, fuzzy +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Pyplyn is VOORGEROL ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Pyplyn doen VOORROLLING ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FOUT: pyplyn wil nie voorrol nie.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Pyplyn is VOORGEROL ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Pyplyn word gestel na SPEEL ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FOUT: pyplyn wil nie speel nie.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Pyplyn word gestel na NULL ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "Uitvoering het geëindig na %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Pyplyn word gestel na GEREED ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Pyplyn word gestel na NULL ...\n" + +#, fuzzy +msgid "Freeing pipeline ...\n" +msgstr "Pyplyn word gestel na NULL ...\n" + +#, fuzzy +#~ msgid "Internal data stream error." +#~ msgstr "Interne datavloeifout." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Moenie statusinligting van TIPE wys nie" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPE1, TIPE2,..." + +#~ msgid "link without source element" +#~ msgstr "verbinding sonder bron-element" + +#~ msgid "link without sink element" +#~ msgstr "verbinding sonder bestemming-element" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "geen element vir URI \"%s\" om heen te skakel nie" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Druk \"alloc trace\" (indien aangeskakel tydens kompilering)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Gebruik so: gst-xmllaunch [ element.eienskap=waarde ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "FOUT: ontleding van xml-lêer '%s' het misluk.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "FOUT: geen topvlak pyplynelement in lêer '%s' nie.\n" + +#, fuzzy +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "WAARSKUWING: slegs een topvlak element word tans ondersteun." + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "FOUT: onverstaanbare bevellynparameter %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "WAARSKUWING: element genaamd '%s' nie gevind nie.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Stoor xml-voorstelling van pyplyn na LÊER en stop" + +#~ msgid "FILE" +#~ msgstr "LÊER" + +#, fuzzy +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Moenie 'n fouthanteerder installeer nie" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Interne GStreamer-fout: state change failed." + +#~ msgid "original location of file as a URI" +#~ msgstr "oorsprong van lêer gegee as 'n URI" + +#~ msgid "Element \"%s\" has gone from PLAYING to PAUSED, quitting.\n" +#~ msgstr "Element \"%s\" het verander van SPEEL na POUSE, verlaat dus.\n" + +#~ msgid "ERROR: Pipeline can't PREROLL ...\n" +#~ msgstr "FOUT: pyplyn kan nie VOORROL nie ...\n" + +#~ msgid " ns.\n" +#~ msgstr " ns.\n" + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "pyplyn word VRYGEMAAK ...\n" diff --git a/po/ast.gmo b/po/ast.gmo new file mode 100644 index 0000000..452a120 Binary files /dev/null and b/po/ast.gmo differ diff --git a/po/ast.po b/po/ast.po new file mode 100644 index 0000000..af48a0c --- /dev/null +++ b/po/ast.po @@ -0,0 +1,1389 @@ +# translation of gstreamer-0.10.22.2.po to Asturian +# asturian translation for gstreamer +# This file is put in the public domain. +# +# Astur , 2009. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.28.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-06-07 22:01+0100\n" +"Last-Translator: astur \n" +"Language-Team: Asturian \n" +"Language: ast\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Launchpad-Export-Date: 2010-06-06 21:16+0000\n" +"X-Generator: Launchpad (build Unknown)\n" +"X-Poedit-Language: asturian\n" + +msgid "Print the GStreamer version" +msgstr "Amosar la versión de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Facer que toles alvertencies seyan fatales" + +msgid "Print available debug categories and exit" +msgstr "Amosar les categoríes de depuración disponibles y colar" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Nivel de depuración por defeutu dende 1 (solo n'error) a 5 (cualesquiera) o " +"0 pa ensin-salida" + +msgid "LEVEL" +msgstr "NIVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Llista de pares nome_de_categoría:nivel separtada por comes p'afitar los " +"niveles específicos de les categoríes de mmou individual. Por exemplu: " +"GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Desactivar la coloración de la salida depurada" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Desactivar depuración" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Activar el diagnósticu detalláu de la carga de los complementos" + +msgid "Colon-separated paths containing plugins" +msgstr "Rutas separtaes por dos puntos «:», que contengan complementos" + +msgid "PATHS" +msgstr "RUTES" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Llista de complementos (plugins) separtaos por comes a precargar n'adición a " +"la llista atroxada na variable d'entornu GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "COMPLEMENTOS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Desactivar atrapáu de fallos de segmentación durante la carga del complementu" + +msgid "Disable updating the registry" +msgstr "Desactivar l'anovamientu del rexistru" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Desactivar el llanzamientu d'un procesu d'aida al escanear el rexistru" + +msgid "GStreamer Options" +msgstr "Opciones de GStreamer" + +msgid "Show GStreamer Options" +msgstr "Amosar opciones de GStreamer" + +msgid "Unknown option" +msgstr "Opción desconocía" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer alcontró un error nuna biblioteca principal." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Los desendolcadores de GStreamer fueron enforma vagos p'asignar un códigu pa " +"esti error." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Fallu internu de GStreamer: códigu non implementáu." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Fallu de GStreamer: falló'l cambéu d'estáu y dalgún elementu nun pudo unviar " +"un mensaxe de fallu apropiáu col motivu del fallu." + +msgid "Internal GStreamer error: pad problem." +msgstr "Fallu internu de GStreamer: problema col pad." + +msgid "Internal GStreamer error: thread problem." +msgstr "Fallu internu de GStreamer: problema de filu." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Fallu internu de GStreamer: problema de negociación." + +msgid "Internal GStreamer error: event problem." +msgstr "Fallu internu de GStreamer: problema con un eventu." + +msgid "Internal GStreamer error: seek problem." +msgstr "Fallu internu de GStreamer: problema de gueta." + +msgid "Internal GStreamer error: caps problem." +msgstr "Fallu internu de GStreamer: problema de mayúscules." + +msgid "Internal GStreamer error: tag problem." +msgstr "Fallu internu de GStreamer: problema con una etiqueta." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "A la so instalación de GStreamer fálta-y un complementu." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Fallu internu de GStreamer: problema col reló." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Esta aplicación ta intentando usar funcionalidaes de GStreamer que foron " +"desactivaes." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer alcontró un fallu nuna llibrería de sofitu xeneral." + +msgid "Could not initialize supporting library." +msgstr "Nun pudo anicializase la biblioteca de sofitu." + +msgid "Could not close supporting library." +msgstr "Nun pudo zarrase la llibrería de sofitu." + +msgid "Could not configure supporting library." +msgstr "Nun pudo configurase la biblioteca de sofitu" + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer alcontró un fallu xeneral de recursu." + +msgid "Resource not found." +msgstr "Recursu non alcontráu." + +msgid "Resource busy or not available." +msgstr "Recursu ocupáu o non disponible" + +msgid "Could not open resource for reading." +msgstr "Nun pudo abrise'l recursu pa llectura." + +msgid "Could not open resource for writing." +msgstr "Nun pudo abrise'l recursu pa escritura." + +msgid "Could not open resource for reading and writing." +msgstr "Nun pudo abrise'l recursu pa llectura y escritura." + +msgid "Could not close resource." +msgstr "Nun pudo zarrase'l recursu." + +msgid "Could not read from resource." +msgstr "Nun pudo lleese del recursu." + +msgid "Could not write to resource." +msgstr "Nun pudo escribise nel recursu." + +msgid "Could not perform seek on resource." +msgstr "Nun pudo facese una busca nel recursu." + +msgid "Could not synchronize on resource." +msgstr "Nun pudo sincronizase col recursu." + +msgid "Could not get/set settings from/on resource." +msgstr "Nun se pudieron obtenese/afitase les opciones de/nel preséu." + +msgid "No space left on the resource." +msgstr "Nun queda espaciu llibre nel recursu." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Nun queda espaciu llibre nel recursu." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer alcontró un fallu xeneral de fluxu." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"L'elementu nun implementa el remanamientu d'esti stream. Por favor, " +"notifique'l fallu." + +msgid "Could not determine type of stream." +msgstr "Nun pudo determinase la triba de fluxu." + +msgid "The stream is of a different type than handled by this element." +msgstr "El fluxu ye d'una triba distinta a la que puede remanar esti elementu." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Nun hai presente dengún codec que pueda remanar esta triba de streams." + +msgid "Could not decode stream." +msgstr "Nun pudo decodificase'l fluxu." + +msgid "Could not encode stream." +msgstr "Nun pudo codificase'l fluxu." + +msgid "Could not demultiplex stream." +msgstr "Nun pudo demultiplexase'l fluxu." + +msgid "Could not multiplex stream." +msgstr "Nun pudo multiplexase'l fluxu." + +msgid "The stream is in the wrong format." +msgstr "El fluxu ta nún formatu fallíu" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Esti fluxu ta cifráu, y el descifráu nun ta sofitáu." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"El fluxu ta cifráu y nun puede descifrase porque nun se suministró una " +"contraseña afayaíza." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nun hai mensaxe de fallu pal dominiu %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nun hai mensaxe de fallu standard pal dominiu %s y códigu %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "El reló esbilláu nun puede usase nuna tubería." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "títulu" + +msgid "commonly used title" +msgstr "títulu usáu por vezu" + +msgid "title sortname" +msgstr "nome curtiu de títulu" + +msgid "commonly used title for sorting purposes" +msgstr "títulu usáu por vezu pa ordenación" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "persona(es) responsable(s) de la grabación" + +msgid "artist sortname" +msgstr "nome curtiu del artista" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persona(es) responsable(s) de la grabación pa ordenación" + +msgid "album" +msgstr "álbum" + +msgid "album containing this data" +msgstr "álbum que contién estos datos" + +msgid "album sortname" +msgstr "nome curtiu d'álbum" + +msgid "album containing this data for sorting purposes" +msgstr "l'álbum contién estos datos pa cuestiones de sofitu" + +msgid "album artist" +msgstr "album artist" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "L'artista del álbum completu, talo y como tien d'amosase" + +msgid "album artist sortname" +msgstr "nome curtiu de album artist" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "L'artista del álbum completu, talo y como tien d'axeitase" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data na que se crearon estos datos (como cadarma GDate)" + +#, fuzzy +msgid "datetime" +msgstr "data" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data na que se crearon estos datos (como cadarma GDate)" + +msgid "genre" +msgstr "xéneru" + +msgid "genre this data belongs to" +msgstr "xéneru al que pertenecen estos datos" + +msgid "comment" +msgstr "comentariu" + +msgid "free text commenting the data" +msgstr "testu llibre que comenta los datos" + +msgid "extended comment" +msgstr "comentariu estendíu" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"testu llibre comentando los datos de forma: llave=valor ó " +"llave[en]=comentariu" + +msgid "track number" +msgstr "númberu de pista" + +msgid "track number inside a collection" +msgstr "númberu de pista dientro d'una colección" + +msgid "track count" +msgstr "contador de pistes" + +msgid "count of tracks inside collection this track belongs to" +msgstr "númberu de pistes dientro de la colección a la que pertenez ésta" + +msgid "disc number" +msgstr "númberu de discu" + +msgid "disc number inside a collection" +msgstr "númberu de discu dientro d'una colección" + +msgid "disc count" +msgstr "candidá de discos" + +msgid "count of discs inside collection this disc belongs to" +msgstr "númberu de discos de la colección a la que pertenez esti discu" + +msgid "location" +msgstr "allugamientu" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Orixe del mediu como un URI (ubicación, au ta allugáu'l ficheru o fluxu " +"orixinal)" + +msgid "homepage" +msgstr "páxina principal" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Páxina principal pa esti sofitu (ex. páxina principal del artista o película)" + +msgid "description" +msgstr "descrición" + +msgid "short text describing the content of the data" +msgstr "testu curtiu que describi'l conteníu de los datos" + +msgid "version" +msgstr "versión" + +msgid "version of this data" +msgstr "versión de los datos" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - vea http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organización" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "avisu de copyright de los datos" + +msgid "copyright uri" +msgstr "uri del copyright" + +msgid "URI to the copyright notice of the data" +msgstr "URI de los datos del copyright" + +#, fuzzy +msgid "encoded by" +msgstr "codificador" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "contautu" + +msgid "contact information" +msgstr "información de contautu" + +msgid "license" +msgstr "llicencia" + +msgid "license of data" +msgstr "llicencia de los datos" + +msgid "license uri" +msgstr "uri de la llicencia" + +msgid "URI to the license of the data" +msgstr "URI de los datos de la llicencia" + +msgid "performer" +msgstr "intérprete" + +msgid "person(s) performing" +msgstr "persona(es) executora(es)" + +msgid "composer" +msgstr "compositor" + +msgid "person(s) who composed the recording" +msgstr "persona(es) que compuso la grabación" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "duración" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "llonxitú n'unidaes de tiempu de GStreamer (nanosegundos)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec col que s'atroxen los datos" + +msgid "video codec" +msgstr "codec de vídeu" + +msgid "codec the video data is stored in" +msgstr "codec nel que s'atroxen los datos del vídeo" + +msgid "audio codec" +msgstr "codec del audio" + +msgid "codec the audio data is stored in" +msgstr "codec nel que s'atroxen los datos del audio" + +msgid "subtitle codec" +msgstr "códec del subtítulu" + +msgid "codec the subtitle data is stored in" +msgstr "códec nel que tán atroxaos los datos del subtítulu" + +msgid "container format" +msgstr "formatu del contenedor" + +msgid "container format the data is stored in" +msgstr "formatu del contenedor nel que tán atroxaos los datos" + +msgid "bitrate" +msgstr "tasa de bits" + +msgid "exact or average bitrate in bits/s" +msgstr "tasa de bits media o exauta en bits/s" + +msgid "nominal bitrate" +msgstr "tasa de bits nominal" + +msgid "nominal bitrate in bits/s" +msgstr "tasa de bits nominal en bits/s" + +msgid "minimum bitrate" +msgstr "tasa mínima de bits" + +msgid "minimum bitrate in bits/s" +msgstr "tasa de bits mínima en bits/s" + +msgid "maximum bitrate" +msgstr "tasa de bits máxima" + +msgid "maximum bitrate in bits/s" +msgstr "tasa de bits máxima en bits/s" + +msgid "encoder" +msgstr "codificador" + +msgid "encoder used to encode this stream" +msgstr "codificador usáu pa codificar esti fluxu" + +msgid "encoder version" +msgstr "versión del codificador" + +msgid "version of the encoder used to encode this stream" +msgstr "versión del codificador usáu pa codificar esti fluxu" + +msgid "serial" +msgstr "serie" + +msgid "serial number of track" +msgstr "númberu de serie de la pista" + +msgid "replaygain track gain" +msgstr "ganancia na reproducción de la pista" + +msgid "track gain in db" +msgstr "ganancia de la pista en db" + +msgid "replaygain track peak" +msgstr "picu de ganancia na reproducción de la pista" + +msgid "peak of the track" +msgstr "peak de la pista" + +msgid "replaygain album gain" +msgstr "ganancia na reproducción del álbum" + +msgid "album gain in db" +msgstr "ganancia del álbum en db" + +msgid "replaygain album peak" +msgstr "picu de ganancia na reproducción del álbum" + +msgid "peak of the album" +msgstr "estremu del album" + +msgid "replaygain reference level" +msgstr "nivel de referencia de replaygain" + +msgid "reference level of track and album gain values" +msgstr "nivel de referencia de los valores de ganancia de la pista y del álbum" + +msgid "language code" +msgstr "códigu del llinguax" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "códigu del llinguax pa esti fluxu, según la norma ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "códigu del llinguax" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "imaxe" + +msgid "image related to this stream" +msgstr "imaxe rellacionada con esti fluxu" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "previsualizar imaxe" + +msgid "preview image related to this stream" +msgstr "previsualizar la imaxe rellacionada con esti fluxu" + +msgid "attachment" +msgstr "axuntu" + +msgid "file attached to this stream" +msgstr "ficheru axuntu a esti fluxu" + +msgid "beats per minute" +msgstr "pulsos per minutu" + +msgid "number of beats per minute in audio" +msgstr "númberu de pulsos per minutu n'audio" + +msgid "keywords" +msgstr "pallabres contraseña" + +msgid "comma separated keywords describing the content" +msgstr "pallabres contraseña separtaes por comes describiendo'l conteníu" + +msgid "geo location name" +msgstr "nome de la xeollocalización" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "llocalización descriptiva y lleíble d'aú se grabó o se fizo'l conteníu" + +msgid "geo location latitude" +msgstr "llatitú de la xeollocalización" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"llatitú xeográfica au se grabó o fizo'l mediu, en graos d'acordies con WGS84 " +"(cero ye l'ecuador, valores negativos pa llatitúes meridionales)" + +msgid "geo location longitude" +msgstr "llonxitú de la xeollocalización" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"llonxitú xeográfica au se grabó o fizo'l mediu, en graos d'acordies con " +"WGS84 (cero ye'l primer meridianu en Greenwich/GB, valores negativos pa " +"llonxitúes occidentales)" + +msgid "geo location elevation" +msgstr "elevación de la xeollocalización" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"elevación xeográfica au se grabó o fexo'l mediu, en metros d'acordies con " +"WGS84 (cero ye'l nivel mediu del mar)" + +msgid "geo location country" +msgstr "nome de la xeollocalización" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "país (nome n'inglés) au se fizo o grabó'l mediu" + +msgid "geo location city" +msgstr "ciudá de la xeollocalización" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "ciudá (nome n'inglés) au se fizo o grabó'l mediu" + +msgid "geo location sublocation" +msgstr "sub-allugamientu de la xeollocalización" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "un allugamientu nuna ciudá au se fizo o creó'l mediu (ex. n'agüeria)" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "nome de la xeollocalización" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "llonxitú de la xeollocalización" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "elevación de la xeollocalización" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "elevación de la xeollocalización" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "amosar nome" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nome del programa/podcast/serie" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "amosar nome d'ordenación" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Nome del programa/podcast/serie, col envís d'ordenación" + +msgid "episode number" +msgstr "númberu d'episodiu" + +msgid "The episode number in the season the media is part of" +msgstr "El númberu d'episodiu na temporada" + +msgid "season number" +msgstr "númberu de temporada" + +msgid "The season number of the show the media is part of" +msgstr "El númberu de temporada del programa" + +msgid "lyrics" +msgstr "lletres" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Les lletres del ficheru multimedia, davezu usáu pa canciones" + +msgid "composer sortname" +msgstr "nome ordenáu del compositor" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "persona(es) que compuso la grabación, col envís d'ordenación" + +msgid "grouping" +msgstr "agrupación" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Agrupa temes rellacionaos que s'esparden varies pistes, como les diferentes " +"partes d'un conciertu. Ye un nivel más altu que'l d'una pista, pero más baxu " +"que'l d'un Álbum" + +msgid "user rating" +msgstr "puntuación d'usuariu" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Puntuación atribuyía por un usuariu. Cuanto mayor seya la puntuación más-y " +"va prestar al usuariu" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "versión del codificador usáu pa codificar esti fluxu" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "versión del codificador usáu pa codificar esti fluxu" + +#, fuzzy +msgid "application name" +msgstr "nome de la xeollocalización" + +msgid "Application used to create the media" +msgstr "" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FALLU: dende l'elementu %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Información adicional de depuráu:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nun esiste la propiedá «%s» nel elementu «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nun pudo afitase la propiedá \"%s\" nel elementu \"%s\" a \"%s\"" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nun pudo enllazase %s a %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "nun se puede enllazar con dengún elementu sink pal URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nun pudo enllazase %s a %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nun pudo enllazase %s a %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nun esiste l'elementu «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nun pudieron analizase les capacidaes «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "nun hai dengún elementu sink pal URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "nun hai dengún elementu fonte pal URI \"%s\"" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "binariu baleru especificáu \"%s\", non permitíu" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nun esiste'l binariu «%s», saltando" + +msgid "empty pipeline not allowed" +msgstr "nun se permiten tuberíes baleres" + +msgid "A lot of buffers are being dropped." +msgstr "Perdiéronse abondos búferes." + +msgid "Internal data flow problem." +msgstr "Problema del fluxu internu de datos." + +msgid "Internal data flow error." +msgstr "Fallu del fluxu internu de datos." + +msgid "Internal clock error." +msgstr "Fallu del reló internu." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Filtrar capacidaes" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restrinxir la posibilidá de capacidaes permitíes (NULL significa ANY). " +"Definir esta propiedá toma una referencia del oxetu provistu GstCaps." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Nun s'especificó un direutoriu Temporal" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nun pudo crease'l ficheru temporal \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nun pudo abrise'l ficheru «%s» pa la so llectura." + +msgid "Error while writing to download file." +msgstr "Fallu al escribir pa descargar el ficheru." + +msgid "No file name specified for writing." +msgstr "Nun s'especificó un nome de ficheru pa escritura." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nun pudo abrise'l ficheru \"%s\" pa escritura." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fallu al zarrar el ficheru \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fallu durante'l posicionamientu nel ficheru «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fallu al escribir al ficheru \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nun s'especificó un nome de ficheru pa llectura." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nun pudo obtenese información de «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" ye un direutoriu." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "El ficheru \"%s\" ye un socket." + +msgid "Failed after iterations as requested." +msgstr "Fallu dempués de les iteraciones requeríes." + +msgid "caps" +msgstr "mayúscules" + +msgid "detected capabilities in stream" +msgstr "capacidaes deteutaes nel ficheru stream" + +msgid "minimum" +msgstr "mínimu" + +msgid "force caps" +msgstr "forciar mayúscules" + +msgid "force caps without doing a typefind" +msgstr "forciar mayúscules ensin facer «typefind»" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "El fluxu nun caltién datos" + +msgid "Stream contains no data." +msgstr "El fluxu nun caltién datos" + +msgid "Implemented Interfaces:\n" +msgstr "Interfaces implementaes:\n" + +msgid "readable" +msgstr "llexible" + +msgid "writable" +msgstr "escribible" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "controlable" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "Ficheros na llista prieta:" + +msgid "Total count: " +msgstr "Cuenta total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d ficheru na llista prieta" +msgstr[1] "%d ficheros na llista prieta" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d complementu" +msgstr[1] "%d complementos" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entrada na llista prieta" +msgstr[1] "%d entraes na llista prieta" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d característica" +msgstr[1] "%d carauterístiques" + +msgid "Print all elements" +msgstr "Imprentar tolos elementos" + +msgid "Print list of blacklisted files" +msgstr "Imprentar llista de los ficheros na llista prieta" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Imprentar una llista de carauterístiques analizables por una máquina que " +"proporciona'l complementu especificáu.\n" +" Útil xunto con mecanismos con " +"complementos automáticos esternos d'instalación" + +msgid "List the plugin contents" +msgstr "Llistar el conteníu del complementu" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Imprentar los esquemes URI sofitaos, colos elementos que los implementen" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nun pudo cargase'l ficheru del complementu: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nun esiste l'elementu o complementu «%s»\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Obtúvose'l mensaxe #%u del elementu «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Obtúvose'l mensax #%u dende tabla \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Obtúvose'l mensax #%u del oxetu «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Obtúvose'l mensax #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "¿Obtuvo EOS dende l'elementu \"%s\".?\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETIQUETA ALCONTRADA: alcontrada pol elementu \"%s\"\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ALCONTRADA ETIQUETA : alcontrada por tabla \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ALCONTRADA ETIQUETA : alcontrada por oxetu \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "ALCONTRADA ETIQUETA\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ETIQUETA ALCONTRADA: alcontrada pol elementu \"%s\"\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ALCONTRADA ETIQUETA : alcontrada por oxetu \"%s\".\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "ALCONTRADA ETIQUETA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ATENCIÓN: dende l'elementu %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Pre-endolcáu, esperando al buffer a que fine...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Pre-endolcáu, esperando al buffer a que fine...\n" + +msgid "buffering..." +msgstr "atroxando nel búfer…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Atroxáu, afite la tubería a REPRODUCIENDO...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Atroxando, afite la tubería a PAUSA...\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribuyir llatencia…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Afitando l'estáu a %s según lo solicitó %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrumpir: parando'l conductu …\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "nun esiste l'elementu «%s»" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ATENCIÓN: dende l'elementu %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Etiquetes de salides (tamién conocíes como metadatos)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Estáu de salida y notificaciones de propiedá" + +msgid "Do not print any progress information" +msgstr "Nun amosar denguna información de progresu" + +msgid "Output messages" +msgstr "Mensaxes de salida" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Nun instalar un remanador de fallos" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forciar EOS nes fontes enantes de zarrar la tubería" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FALLU: nun pudo criase la conexón: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FALLU: nun pudo criase la conexón.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ALVERTENCIA: Conexón errónea: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FALLU: Nun s'atopó l'elementu de «conexón».\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Afitando'l fluxu a POSÁU ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FALLU: El fluxu nun quier ponese en posa.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "El fluxu ye en vivo y nun necesita PRECACHEÁU ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "El fluxu ta PRECACHEÁNDOSE ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FALLU: El fluxu nun quier precachease.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "El fluxu ta precacheáu ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Afitando'l fluxu pa REPRODUCCIÓN ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FALLU: el fluxu nun quier reproducise.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS al apagar activáu; Forciando EOS na tubería\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS al apagar activáu; Forciando EOS na tubería\n" + +msgid "Waiting for EOS...\n" +msgstr "Esperando a EOS…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS recibíu: parando'l conductu …\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrumpir: parando'l conductu …\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Asocedió un fallu al esperar a EOS\n" + +msgid "Execution ended after %" +msgstr "La execución finó tres de %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Afitando pipeline a READY...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Afitando pipeline a NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Lliberando la tubería…\n" + +#~ msgid "link without source element" +#~ msgstr "enllaz ensin elementos de fonte" + +#~ msgid "link without sink element" +#~ msgstr "enllaz ensin elementu sink" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "nun hai dengún elementu au apunta'l URI \"%s\"" + +#~ msgid "Internal data stream error." +#~ msgstr "Fallu del stream internu de datos." + +#~ msgid "maximum" +#~ msgstr "máximu" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Usu: gst-xmllaunch [ elementu.propiedá=valor ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROR: falló l'analís del ficheru xml «%s».\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "FALLU: nun hai elementos de fluxu de primer nivel nel ficheru «%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "ALVERTENCIA: nesti intre namái se sofita un elementu de nivel superior.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "FALLU: nun pudo analizase l'argumentu %d de la llinia d'órdenes: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "AVISU: elementu '%s' non alcontráu.\n" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Nun amosar la información del estáu de TRIBA" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TRIBA1,TRIBA2,…" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Guardar una representación xml de la conexón al FICHERU y colar" + +#~ msgid "FILE" +#~ msgstr "FICHERU" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Imprentar la traza d'asignaciones (si s'activó al compilar)" diff --git a/po/az.gmo b/po/az.gmo new file mode 100644 index 0000000..c21c48d Binary files /dev/null and b/po/az.gmo differ diff --git a/po/az.po b/po/az.po new file mode 100644 index 0000000..5684b2f --- /dev/null +++ b/po/az.po @@ -0,0 +1,1293 @@ +# Translation of 'gstreamer' 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: gstreamer-0.8.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2004-03-19 18:40+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 "Print the GStreamer version" +msgstr "GStreamer buraxılışını göstər" + +msgid "Make all warnings fatal" +msgstr "Bütün xətaları ölümcül et" + +msgid "Print available debug categories and exit" +msgstr "" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" + +msgid "LEVEL" +msgstr "SƏVİYYƏ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" + +msgid "LIST" +msgstr "SİYAHI" + +msgid "Disable colored debugging output" +msgstr "" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Xəta ayırmasını bağla" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" + +msgid "Colon-separated paths containing plugins" +msgstr "" + +msgid "PATHS" +msgstr "CIĞIRLAR" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +msgid "PLUGINS" +msgstr "ƏLAVƏLƏR" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "" + +#, fuzzy +msgid "Show GStreamer Options" +msgstr "GStreamer buraxılışını göstər" + +msgid "Unknown option" +msgstr "" + +msgid "GStreamer encountered a general core library error." +msgstr "" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +msgid "Internal GStreamer error: code not implemented." +msgstr "" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "" + +msgid "Internal GStreamer error: thread problem." +msgstr "" + +msgid "GStreamer error: negotiation problem." +msgstr "" + +msgid "Internal GStreamer error: event problem." +msgstr "" + +msgid "Internal GStreamer error: seek problem." +msgstr "" + +msgid "Internal GStreamer error: caps problem." +msgstr "" + +msgid "Internal GStreamer error: tag problem." +msgstr "" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +msgid "GStreamer error: clock problem." +msgstr "" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "" + +msgid "Could not initialize supporting library." +msgstr "" + +msgid "Could not close supporting library." +msgstr "" + +msgid "Could not configure supporting library." +msgstr "" + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "" + +msgid "Resource not found." +msgstr "" + +msgid "Resource busy or not available." +msgstr "" + +msgid "Could not open resource for reading." +msgstr "" + +msgid "Could not open resource for writing." +msgstr "" + +msgid "Could not open resource for reading and writing." +msgstr "" + +msgid "Could not close resource." +msgstr "" + +msgid "Could not read from resource." +msgstr "" + +msgid "Could not write to resource." +msgstr "" + +msgid "Could not perform seek on resource." +msgstr "" + +msgid "Could not synchronize on resource." +msgstr "" + +msgid "Could not get/set settings from/on resource." +msgstr "" + +msgid "No space left on the resource." +msgstr "" + +msgid "Not authorized to access resource." +msgstr "" + +msgid "GStreamer encountered a general stream error." +msgstr "" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" + +msgid "Could not determine type of stream." +msgstr "" + +msgid "The stream is of a different type than handled by this element." +msgstr "" + +msgid "There is no codec present that can handle the stream's type." +msgstr "" + +msgid "Could not decode stream." +msgstr "" + +msgid "Could not encode stream." +msgstr "" + +msgid "Could not demultiplex stream." +msgstr "" + +msgid "Could not multiplex stream." +msgstr "" + +msgid "The stream is in the wrong format." +msgstr "" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "commonly used title" +msgstr "" + +msgid "title sortname" +msgstr "" + +msgid "commonly used title for sorting purposes" +msgstr "" + +msgid "artist" +msgstr "" + +msgid "person(s) responsible for the recording" +msgstr "" + +msgid "artist sortname" +msgstr "" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" + +msgid "album" +msgstr "" + +msgid "album containing this data" +msgstr "" + +msgid "album sortname" +msgstr "" + +msgid "album containing this data for sorting purposes" +msgstr "" + +msgid "album artist" +msgstr "" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "tarix" + +msgid "date the data was created (as a GDate structure)" +msgstr "" + +#, fuzzy +msgid "datetime" +msgstr "tarix" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" + +msgid "genre" +msgstr "" + +msgid "genre this data belongs to" +msgstr "" + +msgid "comment" +msgstr "şərh" + +msgid "free text commenting the data" +msgstr "" + +#, fuzzy +msgid "extended comment" +msgstr "şərh" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" + +msgid "track number" +msgstr "" + +msgid "track number inside a collection" +msgstr "" + +msgid "track count" +msgstr "" + +msgid "count of tracks inside collection this track belongs to" +msgstr "" + +msgid "disc number" +msgstr "" + +msgid "disc number inside a collection" +msgstr "" + +msgid "disc count" +msgstr "" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" + +msgid "location" +msgstr "" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "izahat" + +msgid "short text describing the content of the data" +msgstr "" + +msgid "version" +msgstr "buraxılış" + +msgid "version of this data" +msgstr "" + +msgid "ISRC" +msgstr "" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" + +msgid "organization" +msgstr "" + +msgid "copyright" +msgstr "müəllif hüququ" + +msgid "copyright notice of the data" +msgstr "mə'lumatın müəllif hüququ qeydi" + +#, fuzzy +msgid "copyright uri" +msgstr "müəllif hüququ" + +#, fuzzy +msgid "URI to the copyright notice of the data" +msgstr "mə'lumatın müəllif hüququ qeydi" + +msgid "encoded by" +msgstr "" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "əlaqə" + +msgid "contact information" +msgstr "əlaqə mə'lumatı" + +msgid "license" +msgstr "lisenziya" + +msgid "license of data" +msgstr "mə'lumatın lisenziyası" + +#, fuzzy +msgid "license uri" +msgstr "lisenziya" + +#, fuzzy +msgid "URI to the license of the data" +msgstr "mə'lumatın lisenziyası" + +msgid "performer" +msgstr "ifaçı" + +msgid "person(s) performing" +msgstr "ifa edən şəxs(lər)" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "ifa edən şəxs(lər)" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "sürəklik" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "" + +msgid "codec" +msgstr "" + +msgid "codec the data is stored in" +msgstr "" + +msgid "video codec" +msgstr "" + +msgid "codec the video data is stored in" +msgstr "" + +msgid "audio codec" +msgstr "" + +msgid "codec the audio data is stored in" +msgstr "" + +msgid "subtitle codec" +msgstr "" + +msgid "codec the subtitle data is stored in" +msgstr "" + +#, fuzzy +msgid "container format" +msgstr "əlaqə mə'lumatı" + +msgid "container format the data is stored in" +msgstr "" + +msgid "bitrate" +msgstr "" + +msgid "exact or average bitrate in bits/s" +msgstr "" + +msgid "nominal bitrate" +msgstr "" + +msgid "nominal bitrate in bits/s" +msgstr "" + +msgid "minimum bitrate" +msgstr "" + +msgid "minimum bitrate in bits/s" +msgstr "" + +msgid "maximum bitrate" +msgstr "" + +msgid "maximum bitrate in bits/s" +msgstr "" + +msgid "encoder" +msgstr "" + +msgid "encoder used to encode this stream" +msgstr "" + +msgid "encoder version" +msgstr "" + +msgid "version of the encoder used to encode this stream" +msgstr "" + +msgid "serial" +msgstr "seriya nömrəsi" + +msgid "serial number of track" +msgstr "mahnının seriya nömrəsi" + +msgid "replaygain track gain" +msgstr "" + +msgid "track gain in db" +msgstr "" + +msgid "replaygain track peak" +msgstr "" + +msgid "peak of the track" +msgstr "" + +msgid "replaygain album gain" +msgstr "" + +msgid "album gain in db" +msgstr "" + +msgid "replaygain album peak" +msgstr "" + +msgid "peak of the album" +msgstr "" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +msgid "language name" +msgstr "" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +msgid "image related to this stream" +msgstr "" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +msgid "file attached to this stream" +msgstr "" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +msgid "comma separated keywords describing the content" +msgstr "" + +msgid "geo location name" +msgstr "" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +msgid "geo location country" +msgstr "" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location city" +msgstr "" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location sublocation" +msgstr "" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +msgid "geo location horizontal error" +msgstr "" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +msgid "geo location movement direction" +msgstr "" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +msgid "geo location capture direction" +msgstr "" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +msgid "episode number" +msgstr "" + +msgid "The episode number in the season the media is part of" +msgstr "" + +msgid "season number" +msgstr "" + +msgid "The season number of the show the media is part of" +msgstr "" + +#, fuzzy +msgid "lyrics" +msgstr "lisenziya" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "ifa edən şəxs(lər)" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +#, fuzzy +msgid "user rating" +msgstr "sürəklik" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +msgid "Manufacturer of the device used to create this media" +msgstr "" + +msgid "device model" +msgstr "" + +msgid "Model of the device used to create this media" +msgstr "" + +msgid "application name" +msgstr "" + +msgid "Application used to create the media" +msgstr "" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +msgid "Delayed linking failed." +msgstr "" + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s" +msgstr "" + +#, c-format +msgid "no element \"%s\"" +msgstr "" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "" + +msgid "empty pipeline not allowed" +msgstr "" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "" + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "" + +msgid "Error while writing to download file." +msgstr "" + +msgid "No file name specified for writing." +msgstr "" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "" + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "" + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "" + +msgid "No file name specified for reading." +msgstr "" + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "" + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "" + +msgid "Failed after iterations as requested." +msgstr "" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "" + +msgid "minimum" +msgstr "minimal" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +msgid "Stream doesn't contain enough data." +msgstr "" + +msgid "Stream contains no data." +msgstr "" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +msgid "writable" +msgstr "" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +msgid "Total count: " +msgstr "" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +msgid "Print all elements" +msgstr "" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TAG\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, c-format +msgid "Missing element: %s\n" +msgstr "" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "" + +msgid "Output tags (also known as metadata)" +msgstr "" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "" + +msgid "Do not print any progress information" +msgstr "" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +msgid "Freeing pipeline ...\n" +msgstr "" + +#~ msgid "FILE" +#~ msgstr "FAYL" + +#~ msgid "')" +#~ msgstr "')" + +#~ msgid "SCHEDULER" +#~ msgstr "VAXTLAŞDIRICI" + +#~ msgid "Registry to use" +#~ msgstr "İşlədiləcək qeyd bazası" + +#~ msgid "REGISTRY" +#~ msgstr "QEYDBAZASI" diff --git a/po/be.gmo b/po/be.gmo new file mode 100644 index 0000000..7265b65 Binary files /dev/null and b/po/be.gmo differ diff --git a/po/be.po b/po/be.po new file mode 100644 index 0000000..8a43bce --- /dev/null +++ b/po/be.po @@ -0,0 +1,1290 @@ +# Belarusian translation of gstreamer. +# This file is put in the public domain. +# Ales Nyakhaychyk , 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.9.7\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2006-01-18 22:26+0200\n" +"Last-Translator: Ales Nyakhaychyk \n" +"Language-Team: Belarusian \n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Print the GStreamer version" +msgstr "Друкуе вэрсыю GStreamer" + +msgid "Make all warnings fatal" +msgstr "Робіць усе папярэджаньні фатальнымі" + +msgid "Print available debug categories and exit" +msgstr "Друкуе наяўныя катэгорыі адладкі й выходзіць" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Прадвызначаны ўзровень адладкі ад 1 (толькі памылкі) да 5 (усё) ці 0 каб " +"выключыць вывад" + +msgid "LEVEL" +msgstr "УЗРОВЕНЬ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Разьмежаваны коскамі сьпіс пар categor_name:level для выстаўленьня " +"адмысловых узроўняў для асобных катэгорыяў. Напрыклад, GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "СЬПІС" + +msgid "Disable colored debugging output" +msgstr "Выключае каляровы вывад адладкі" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Выключае адладку" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Уключае шматслоўную дыягностыку загрузкі ўтулак" + +msgid "Colon-separated paths containing plugins" +msgstr "Падзелены двукроп'ямі сьпіс шляхоў, дзе месьцяцца ўтулкі" + +msgid "PATHS" +msgstr "ШЛЯХІ" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +msgid "PLUGINS" +msgstr "" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "" + +msgid "Show GStreamer Options" +msgstr "" + +msgid "Unknown option" +msgstr "" + +msgid "GStreamer encountered a general core library error." +msgstr "" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +msgid "Internal GStreamer error: code not implemented." +msgstr "" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "" + +msgid "Internal GStreamer error: thread problem." +msgstr "" + +msgid "GStreamer error: negotiation problem." +msgstr "" + +msgid "Internal GStreamer error: event problem." +msgstr "" + +msgid "Internal GStreamer error: seek problem." +msgstr "" + +msgid "Internal GStreamer error: caps problem." +msgstr "" + +msgid "Internal GStreamer error: tag problem." +msgstr "" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +msgid "GStreamer error: clock problem." +msgstr "" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "" + +msgid "Could not initialize supporting library." +msgstr "" + +msgid "Could not close supporting library." +msgstr "" + +#, fuzzy +msgid "Could not configure supporting library." +msgstr "Немагчыма адчыніць расурс для запісу." + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "" + +msgid "Resource not found." +msgstr "Расурс ня знойдзены." + +msgid "Resource busy or not available." +msgstr "Расурс заняты ці недаступны." + +msgid "Could not open resource for reading." +msgstr "Немагчыма адчыніць расурс для чытаньня." + +msgid "Could not open resource for writing." +msgstr "Немагчыма адчыніць расурс для запісу." + +msgid "Could not open resource for reading and writing." +msgstr "Немагчыма адчыніць расурс для чытаньня і запісу." + +msgid "Could not close resource." +msgstr "Немагчыма зачыніць расурс." + +msgid "Could not read from resource." +msgstr "Немагчыма прачытаць з расурсу." + +msgid "Could not write to resource." +msgstr "Немагчыма запісаць у расурс." + +msgid "Could not perform seek on resource." +msgstr "" + +msgid "Could not synchronize on resource." +msgstr "" + +msgid "Could not get/set settings from/on resource." +msgstr "" + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Немагчыма запісаць у расурс." + +msgid "GStreamer encountered a general stream error." +msgstr "" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" + +msgid "Could not determine type of stream." +msgstr "Немагчыма вызначыць тып плыні." + +msgid "The stream is of a different type than handled by this element." +msgstr "" + +msgid "There is no codec present that can handle the stream's type." +msgstr "" + +msgid "Could not decode stream." +msgstr "Немагчыма дэкадаваць плыню." + +msgid "Could not encode stream." +msgstr "Немагчыма закадаваць плыню." + +msgid "Could not demultiplex stream." +msgstr "" + +msgid "Could not multiplex stream." +msgstr "" + +msgid "The stream is in the wrong format." +msgstr "" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "Адсутнічае паведамленьне аб памылцы для маёнтка %s" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "загаловак" + +msgid "commonly used title" +msgstr "агульна ўжывальная назва" + +msgid "title sortname" +msgstr "" + +#, fuzzy +msgid "commonly used title for sorting purposes" +msgstr "агульна ўжывальная назва" + +msgid "artist" +msgstr "выканаўца" + +msgid "person(s) responsible for the recording" +msgstr "асоба(ы) адказныя за запіс" + +msgid "artist sortname" +msgstr "" + +#, fuzzy +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "асоба(ы) адказныя за запіс" + +msgid "album" +msgstr "альбом" + +msgid "album containing this data" +msgstr "альбом, якія зьмяшчае гэтыя даньі" + +msgid "album sortname" +msgstr "" + +#, fuzzy +msgid "album containing this data for sorting purposes" +msgstr "альбом, якія зьмяшчае гэтыя даньі" + +#, fuzzy +msgid "album artist" +msgstr "выканаўца" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "дата" + +msgid "date the data was created (as a GDate structure)" +msgstr "дата, калі гэтыя даньні былі створана (як структура GDate)" + +#, fuzzy +msgid "datetime" +msgstr "дата" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "дата, калі гэтыя даньні былі створана (як структура GDate)" + +msgid "genre" +msgstr "жанр" + +msgid "genre this data belongs to" +msgstr "жанр да ягока належаць гэтыя даньні" + +msgid "comment" +msgstr "камэнтар" + +msgid "free text commenting the data" +msgstr "любы тэкс, які камэнтуе гэтыя даньні" + +#, fuzzy +msgid "extended comment" +msgstr "камэнтар" + +#, fuzzy +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "любы тэкс, які камэнтуе гэтыя даньні" + +msgid "track number" +msgstr "нумр запісу" + +msgid "track number inside a collection" +msgstr "нумар запісу ў межах калекцыі" + +msgid "track count" +msgstr "колькасьць запісаў" + +msgid "count of tracks inside collection this track belongs to" +msgstr "колькасьць запісаў ў межах калекцыі да якой гэты запіс належыць" + +msgid "disc number" +msgstr "нумар дыска" + +msgid "disc number inside a collection" +msgstr "нумар дыска ў межах калекцыі" + +msgid "disc count" +msgstr "" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" + +msgid "location" +msgstr "" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "" + +msgid "short text describing the content of the data" +msgstr "" + +msgid "version" +msgstr "" + +msgid "version of this data" +msgstr "" + +msgid "ISRC" +msgstr "" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" + +msgid "organization" +msgstr "" + +msgid "copyright" +msgstr "" + +msgid "copyright notice of the data" +msgstr "" + +msgid "copyright uri" +msgstr "" + +msgid "URI to the copyright notice of the data" +msgstr "" + +msgid "encoded by" +msgstr "" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "" + +msgid "contact information" +msgstr "" + +msgid "license" +msgstr "" + +msgid "license of data" +msgstr "" + +msgid "license uri" +msgstr "" + +msgid "URI to the license of the data" +msgstr "" + +msgid "performer" +msgstr "" + +msgid "person(s) performing" +msgstr "" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "асоба(ы) адказныя за запіс" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "" + +msgid "codec" +msgstr "" + +msgid "codec the data is stored in" +msgstr "" + +msgid "video codec" +msgstr "" + +msgid "codec the video data is stored in" +msgstr "" + +msgid "audio codec" +msgstr "" + +msgid "codec the audio data is stored in" +msgstr "" + +msgid "subtitle codec" +msgstr "" + +msgid "codec the subtitle data is stored in" +msgstr "" + +msgid "container format" +msgstr "" + +msgid "container format the data is stored in" +msgstr "" + +msgid "bitrate" +msgstr "" + +msgid "exact or average bitrate in bits/s" +msgstr "" + +msgid "nominal bitrate" +msgstr "" + +msgid "nominal bitrate in bits/s" +msgstr "" + +msgid "minimum bitrate" +msgstr "" + +msgid "minimum bitrate in bits/s" +msgstr "" + +msgid "maximum bitrate" +msgstr "" + +msgid "maximum bitrate in bits/s" +msgstr "" + +msgid "encoder" +msgstr "" + +msgid "encoder used to encode this stream" +msgstr "" + +msgid "encoder version" +msgstr "" + +msgid "version of the encoder used to encode this stream" +msgstr "" + +msgid "serial" +msgstr "" + +msgid "serial number of track" +msgstr "" + +msgid "replaygain track gain" +msgstr "" + +msgid "track gain in db" +msgstr "" + +msgid "replaygain track peak" +msgstr "" + +msgid "peak of the track" +msgstr "" + +msgid "replaygain album gain" +msgstr "" + +msgid "album gain in db" +msgstr "" + +msgid "replaygain album peak" +msgstr "" + +msgid "peak of the album" +msgstr "" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +msgid "language name" +msgstr "" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +msgid "image related to this stream" +msgstr "" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +msgid "file attached to this stream" +msgstr "" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +msgid "comma separated keywords describing the content" +msgstr "" + +msgid "geo location name" +msgstr "" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +msgid "geo location country" +msgstr "" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location city" +msgstr "" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location sublocation" +msgstr "" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +msgid "geo location horizontal error" +msgstr "" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +msgid "geo location movement direction" +msgstr "" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +msgid "geo location capture direction" +msgstr "" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#, fuzzy +msgid "episode number" +msgstr "нумар дыска" + +msgid "The episode number in the season the media is part of" +msgstr "" + +#, fuzzy +msgid "season number" +msgstr "нумар дыска" + +msgid "The season number of the show the media is part of" +msgstr "" + +msgid "lyrics" +msgstr "" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "асоба(ы) адказныя за запіс" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +msgid "user rating" +msgstr "" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +msgid "Manufacturer of the device used to create this media" +msgstr "" + +msgid "device model" +msgstr "" + +msgid "Model of the device used to create this media" +msgstr "" + +msgid "application name" +msgstr "" + +msgid "Application used to create the media" +msgstr "" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr "" + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Дадатковая адладачная інфармацыя:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +msgid "Delayed linking failed." +msgstr "" + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s" +msgstr "" + +#, c-format +msgid "no element \"%s\"" +msgstr "" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "" + +msgid "empty pipeline not allowed" +msgstr "" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, fuzzy, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Немагчыма закадаваць плыню." + +#, fuzzy, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Немагчыма адчыніць расурс для чытаньня." + +msgid "Error while writing to download file." +msgstr "" + +msgid "No file name specified for writing." +msgstr "" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "" + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "" + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "" + +msgid "No file name specified for reading." +msgstr "" + +#, fuzzy, c-format +msgid "Could not get info on \"%s\"." +msgstr "Немагчыма закадаваць плыню." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "" + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "" + +msgid "Failed after iterations as requested." +msgstr "" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "" + +msgid "minimum" +msgstr "" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "альбом, якія зьмяшчае гэтыя даньі" + +#, fuzzy +msgid "Stream contains no data." +msgstr "альбом, якія зьмяшчае гэтыя даньі" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +#, fuzzy +msgid "writable" +msgstr "загаловак" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +#, fuzzy +msgid "Total count: " +msgstr "колькасьць запісаў" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +msgid "Print all elements" +msgstr "" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TAG\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, c-format +msgid "Missing element: %s\n" +msgstr "" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "" + +msgid "Output tags (also known as metadata)" +msgstr "" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "" + +msgid "Do not print any progress information" +msgstr "" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +msgid "Freeing pipeline ...\n" +msgstr "" diff --git a/po/bg.gmo b/po/bg.gmo new file mode 100644 index 0000000..869a0f1 Binary files /dev/null and b/po/bg.gmo differ diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 0000000..cfa36ae --- /dev/null +++ b/po/bg.po @@ -0,0 +1,1338 @@ +# Bulgarian translation of gstreamer. +# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software Fondation, Inc. +# Copyright (C) 2011, 2016, 2017 Free Software Fondation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Alexander Shopov , 2005, 2006, 2007, 2008, 2009, 2010. +# Alexander Shopov , 2011, 2016, 2017. +# +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-08 11:35+0200\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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgid "Print the GStreamer version" +msgstr "Отпечатване на версията на GStreamer" + +msgid "Make all warnings fatal" +msgstr "Всички предупреждения да са фатални" + +msgid "Print available debug categories and exit" +msgstr "Отпечатване на наличните категории за изчистване на грешки и изход" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Стандартното ниво за изчистване на грешки — от 1 (само грешки) до 9 (всичко) " +"или 0 — без никакви съобщения за изчистване на грешки" + +msgid "LEVEL" +msgstr "НИВО" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Списък от двойки име_на_категория:ниво разделени със запетаи. Той указва " +"конкретните нива за съобщения за изчистване на грешки на отделните " +"категории. Например: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "СПИСЪК" + +msgid "Disable colored debugging output" +msgstr "Спиране на оцветените съобщения за изчистване на грешки" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Смяна на режима на оцветяване на съобщенията за изчистване на грешки. " +"Възможните стойности са: „off“ (изключване), „on“ (включване), " +"„disable“ (спиране), „auto“ (автоматично), „unix“ (стандартно за unix)" + +msgid "Disable debugging" +msgstr "Спиране на съобщенията за изчистване на грешки" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Включване на подробни съобщения при зареждане на приставка" + +msgid "Colon-separated paths containing plugins" +msgstr "Пътища с приставки, разделени с двоеточие" + +msgid "PATHS" +msgstr "ПЪТИЩА" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Списък от приставки, разделени със запетая, които да бъдат предварително " +"заредени в допълнение към тези от списъка в променливата на средата " +"GST_PPLUGIN_PATH" + +msgid "PLUGINS" +msgstr "ПРИСТАВКИ" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Спиране на прихващането на сегментационни грешки по времето на зареждане на " +"приставка" + +msgid "Disable updating the registry" +msgstr "Регистърът да не се прочита" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Без стартирането на спомагателен процес при изчитането на регистъра" + +msgid "GStreamer Options" +msgstr "Настройки на GStreamer" + +msgid "Show GStreamer Options" +msgstr "Показване на опциите на GStreamer" + +msgid "Unknown option" +msgstr "Непозната опция" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer получи обща грешка в основна библиотека." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Разработчиците на GStreamer са били прекалено мързеливи и не са задали код " +"за грешка на този проблем." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Вътрешна грешка на GStreamer: кодът не е реализиран." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Грешка на GStreamer: неуспешна промяна на състоянието, а някой от елементите " +"пропусна да подаде съобщение за грешка с причината за това." + +msgid "Internal GStreamer error: pad problem." +msgstr "Вътрешна грешка на GStreamer: проблем в допълването." + +msgid "Internal GStreamer error: thread problem." +msgstr "Вътрешна грешка на GStreamer: проблем с нишките." + +msgid "GStreamer error: negotiation problem." +msgstr "Вътрешна грешка на GStreamer: проблем с договарянето." + +msgid "Internal GStreamer error: event problem." +msgstr "Вътрешна грешка на GStreamer: проблем със събитията." + +msgid "Internal GStreamer error: seek problem." +msgstr "Вътрешна грешка на GStreamer: проблем при позиционирането." + +msgid "Internal GStreamer error: caps problem." +msgstr "Вътрешна грешка на GStreamer: проблем с възможностите." + +msgid "Internal GStreamer error: tag problem." +msgstr "Вътрешна грешка на GStreamer: проблем с етикетите." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Липсва необходима приставка в тази инсталация на GStreamer" + +msgid "GStreamer error: clock problem." +msgstr "Грешка на GStreamer: проблем с часовника." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Това приложение се опитва да ползва функционалност на GStreamer, която е " +"изключена." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer получи обща грешка в помощна библиотека." + +msgid "Could not initialize supporting library." +msgstr "Помощната библиотека не може да бъде инициализирана." + +msgid "Could not close supporting library." +msgstr "Помощната библиотека не може да бъде затворена." + +msgid "Could not configure supporting library." +msgstr "Помощната библиотека не може да бъде настроена." + +msgid "Encoding error." +msgstr "Грешка при кодиране." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer получи обща грешка в ресурс." + +msgid "Resource not found." +msgstr "Ресурсът не е открит." + +msgid "Resource busy or not available." +msgstr "Ресурсът е зает или не е достъпен." + +msgid "Could not open resource for reading." +msgstr "Ресурсът не може да бъде отворен за четене." + +msgid "Could not open resource for writing." +msgstr "Ресурсът не може да бъде отворен за запис." + +msgid "Could not open resource for reading and writing." +msgstr "Ресурсът не може да бъде отворен за четене и запис." + +msgid "Could not close resource." +msgstr "Ресурсът не може да бъде затворен." + +msgid "Could not read from resource." +msgstr "Не може да се чете от ресурса." + +msgid "Could not write to resource." +msgstr "Не може да се записва в ресурса." + +msgid "Could not perform seek on resource." +msgstr "Не може да се позиционира в ресурса." + +msgid "Could not synchronize on resource." +msgstr "Не може да се синхронизира по ресурса." + +msgid "Could not get/set settings from/on resource." +msgstr "Не може да се получи/зададе настройка от/на ресурса." + +msgid "No space left on the resource." +msgstr "Върху ресурса не е останало свободно място." + +msgid "Not authorized to access resource." +msgstr "Няма права за достъп до ресурса." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer получи обща грешка в потока от данни." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Елементът не осъществява обработката на този поток. Моля, подайте доклад за " +"грешка." + +msgid "Could not determine type of stream." +msgstr "Видът на потока от данни не може да бъде определен." + +msgid "The stream is of a different type than handled by this element." +msgstr "Потокът от данни не е от вида, който се обработва от елемента." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Няма кодер за обработката на този вид поток от данни." + +msgid "Could not decode stream." +msgstr "Потокът от данни не може да бъде декодиран." + +msgid "Could not encode stream." +msgstr "Потокът от данни не може да бъде кодиран." + +msgid "Could not demultiplex stream." +msgstr "Потокът от данни не може да бъде разделен (демултиплексиран)." + +msgid "Could not multiplex stream." +msgstr "Потокът от данни не може да бъде уплътнен (мултиплексиран)." + +msgid "The stream is in the wrong format." +msgstr "Потокът е с грешен формат." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Потокът е шифриран. Дешифрирането му не се поддържа." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Потокът е шифриран. Дешифрирането му е невъзможно, защото не е подаден " +"подходящ ключ." + +#, c-format +msgid "No error message for domain %s." +msgstr "Няма съобщение за грешка за областта „%s“." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Няма стандартно съобщение за грешка за областта „%s“ с код %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Избраният часовник не може да се използва в конвейер." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Грешка при запазване на кеша на регистъра в „%s“: %s" + +msgid "title" +msgstr "заглавие" + +msgid "commonly used title" +msgstr "популярно заглавие" + +msgid "title sortname" +msgstr "заглавие, ползва се при подреждане" + +msgid "commonly used title for sorting purposes" +msgstr "популярно заглавие, ползва се при подреждане" + +msgid "artist" +msgstr "изпълнител" + +msgid "person(s) responsible for the recording" +msgstr "отговорник/ци за записа" + +msgid "artist sortname" +msgstr "име на изпълнител, ползва се при подреждане" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "отговорник/ци за записа, ползва се при подреждане" + +msgid "album" +msgstr "албум" + +msgid "album containing this data" +msgstr "албум съдържащ тези данни" + +msgid "album sortname" +msgstr "албум, ползва се при подреждане" + +msgid "album containing this data for sorting purposes" +msgstr "албум съдържащ тези данни, ползва се при подреждане" + +msgid "album artist" +msgstr "изпълнител на албум" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "изпълнител на целия албум, ползва се при показване" + +msgid "album artist sortname" +msgstr "изпълнител на албум, ползва се при подреждане" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "изпълнител на целия албум, ползва се при подреждане" + +msgid "date" +msgstr "дата" + +msgid "date the data was created (as a GDate structure)" +msgstr "дата на създаване на данните (като структура GDate)" + +msgid "datetime" +msgstr "момент" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "момент на създаване на данните (като структура GstDateTime)" + +msgid "genre" +msgstr "жанр" + +msgid "genre this data belongs to" +msgstr "жанр на тези данни" + +msgid "comment" +msgstr "коментар" + +msgid "free text commenting the data" +msgstr "свободен текст относно данните" + +msgid "extended comment" +msgstr "допълнителен коментар" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"свободен текст относно данните във формат ключ=стойност или " +"ключ[език]=коментар" + +msgid "track number" +msgstr "номер на песента" + +msgid "track number inside a collection" +msgstr "номер на песента в колекция" + +msgid "track count" +msgstr "брой песни" + +msgid "count of tracks inside collection this track belongs to" +msgstr "брой песните в колекцията, към която принадлежи тази песен" + +msgid "disc number" +msgstr "номер на диска" + +msgid "disc number inside a collection" +msgstr "номер на диска от колекция" + +msgid "disc count" +msgstr "брой дискове" + +msgid "count of discs inside collection this disc belongs to" +msgstr "брой дискове в колекция, към която принадлежи този диск" + +msgid "location" +msgstr "адрес" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Произход на медията като адрес (мястото в Интернет, откъдето е оригиналният " +"файл или поток)" + +msgid "homepage" +msgstr "сайт" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Страница в Интернет за тази медия (напр. сайт на изпълнител или филм)" + +msgid "description" +msgstr "описание" + +msgid "short text describing the content of the data" +msgstr "кратък текст — съдържание" + +msgid "version" +msgstr "версия" + +msgid "version of this data" +msgstr "версия на тези данни" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "Стандартен, международен код на запис — http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "организация" + +msgid "copyright" +msgstr "авторски права" + +msgid "copyright notice of the data" +msgstr "означение на авторските права на данните" + +msgid "copyright uri" +msgstr "адрес за авторски права" + +msgid "URI to the copyright notice of the data" +msgstr "адрес на означението на авторските права на данните" + +msgid "encoded by" +msgstr "кодирано от" + +msgid "name of the encoding person or organization" +msgstr "име на човека или организацията извършващи кодирането" + +msgid "contact" +msgstr "контакт" + +msgid "contact information" +msgstr "информация за контакт" + +msgid "license" +msgstr "лиценз" + +msgid "license of data" +msgstr "лиценз на данните" + +msgid "license uri" +msgstr "адрес на лиценза" + +msgid "URI to the license of the data" +msgstr "адрес на лиценза на данните" + +msgid "performer" +msgstr "изпълнител" + +msgid "person(s) performing" +msgstr "кой изпълнява данните" + +msgid "composer" +msgstr "композитор" + +msgid "person(s) who composed the recording" +msgstr "композитор/и на записа" + +msgid "conductor" +msgstr "диригент" + +msgid "conductor/performer refinement" +msgstr "информация за диригента или изпълнителя" + +msgid "duration" +msgstr "продължителност" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "продължителност в единици на GStreamer (наносекунди)" + +msgid "codec" +msgstr "кодер" + +msgid "codec the data is stored in" +msgstr "кодер, чрез който са съхранени данните" + +msgid "video codec" +msgstr "видео кодер" + +msgid "codec the video data is stored in" +msgstr "кодер, чрез който са съхранени видео данните" + +msgid "audio codec" +msgstr "аудио кодер" + +msgid "codec the audio data is stored in" +msgstr "кодер, чрез който са съхранени аудио данните" + +msgid "subtitle codec" +msgstr "кодер за субтитрите" + +msgid "codec the subtitle data is stored in" +msgstr "кодер, чрез който са съхранени данните на субтитрите" + +msgid "container format" +msgstr "информация за контейнера" + +msgid "container format the data is stored in" +msgstr "формат на контейнера, в който са съхранени данните" + +msgid "bitrate" +msgstr "скорост на битовете" + +msgid "exact or average bitrate in bits/s" +msgstr "точна или усреднена скорост на битовете" + +msgid "nominal bitrate" +msgstr "номинална скорост на битовете" + +msgid "nominal bitrate in bits/s" +msgstr "номинална скорост на битовете [bits/s]" + +msgid "minimum bitrate" +msgstr "минимална скорост на битовете" + +msgid "minimum bitrate in bits/s" +msgstr "минимална скорост на битовете [bits/s]" + +msgid "maximum bitrate" +msgstr "максимална скорост на битовете" + +msgid "maximum bitrate in bits/s" +msgstr "максимална скорост на битовете [bits/s]" + +msgid "encoder" +msgstr "кодер" + +msgid "encoder used to encode this stream" +msgstr "кодер, чрез който е кодиран този поток" + +msgid "encoder version" +msgstr "версия на кодера" + +msgid "version of the encoder used to encode this stream" +msgstr "версия на кодера, чрез който е кодиран този поток" + +msgid "serial" +msgstr "сер. №" + +msgid "serial number of track" +msgstr "сериен номер на песента" + +msgid "replaygain track gain" +msgstr "усилване на песента при изпълнение" + +msgid "track gain in db" +msgstr "усилване на песента [db]" + +msgid "replaygain track peak" +msgstr "максимално усилване на песента при изпълнение" + +msgid "peak of the track" +msgstr "максимално усилване на песента" + +msgid "replaygain album gain" +msgstr "усилване на албума при изпълнение" + +msgid "album gain in db" +msgstr "усилване на албума [db]" + +msgid "replaygain album peak" +msgstr "максимално усилване на албума при изпълнение" + +msgid "peak of the album" +msgstr "максимално усилване на албума" + +msgid "replaygain reference level" +msgstr "еталонно максимално усилване на песента при изпълнение" + +msgid "reference level of track and album gain values" +msgstr "еталонно ниво на усилването на песните и албумите" + +msgid "language code" +msgstr "езиков код" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "езиковият код на този поток според ISO-639-1 или ISO-639-2" + +msgid "language name" +msgstr "име на езика" + +msgid "freeform name of the language this stream is in" +msgstr "свободно име на езика на потока" + +msgid "image" +msgstr "изображение" + +msgid "image related to this stream" +msgstr "изображение свързано с този поток" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "изображение за преглед" + +msgid "preview image related to this stream" +msgstr "изображение за преглед свързано с този поток" + +msgid "attachment" +msgstr "притурка" + +msgid "file attached to this stream" +msgstr "файл прикачен към този поток" + +msgid "beats per minute" +msgstr "такта в минута" + +msgid "number of beats per minute in audio" +msgstr "брой тактове в минута в аудио" + +msgid "keywords" +msgstr "ключови думи" + +msgid "comma separated keywords describing the content" +msgstr "ключови думи за съдържанието, разделени със запетаи" + +msgid "geo location name" +msgstr "местоположение" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "разбираемо описание на мястото на запис или създаване на медията" + +msgid "geo location latitude" +msgstr "географска ширина" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"географска ширина на мястото на запис или създаване на медията в градуси " +"според WGS84 (0 при екватора, отрицателна в южното полукълбо)" + +msgid "geo location longitude" +msgstr "географска дължина" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"географска дължина на мястото на запис или създаване на медията в градуси " +"според WGS84 (0 при Гринуич, Великобритания, отрицателна в западното " +"полукълбо)" + +msgid "geo location elevation" +msgstr "надморска височина" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"надморска височина на мястото на запис или създаване на медията в метри " +"според WGS84 (0 при средното морско равнище)" + +msgid "geo location country" +msgstr "държава по координати" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "държавата на запис или създаване на медията (на английски)" + +msgid "geo location city" +msgstr "град по координати" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "град на запис или създаване на медията (на английски)" + +msgid "geo location sublocation" +msgstr "квартал по координати" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "място в града на запис или създаване на медията (напр. квартал)" + +msgid "geo location horizontal error" +msgstr "хоризонтална грешка по координати" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "очаквана грешка по хоризонтал [m]" + +msgid "geo location movement speed" +msgstr "скорост по координати" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "скорост на движение на входното устройство при записа [m/s]" + +msgid "geo location movement direction" +msgstr "посока на движение по координати" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"посока на движение на входното устройство при записа. Стойността е в градуси " +"в десетично представяне. 0 е географският север. Стойността расте по посока " +"на часовниковата стрелка" + +msgid "geo location capture direction" +msgstr "посока на заснемане по координати" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"посока на входното устройство при записа. Стойността е в градуси в десетично " +"представяне. 0 е географският север. Стойността расте по посока на " +"часовниковата стрелка" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "име на шоу" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Името на телевизионно или Интернет шоу, поредица от серии, от което е медията" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "име на шоу за подреждане" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Името на телевизионно или Интернет шоу, поредица от серии, от което е " +"медията, ползва се при подреждане" + +msgid "episode number" +msgstr "номер на епизода" + +msgid "The episode number in the season the media is part of" +msgstr "Номерът на епизода в поредицата за сезона" + +msgid "season number" +msgstr "номер на сезона" + +msgid "The season number of the show the media is part of" +msgstr "Номерът на сезона в поредицата, от която е медията" + +msgid "lyrics" +msgstr "текст" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Текстът на медията, често се използва за песни" + +msgid "composer sortname" +msgstr "композитор при подреждане" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "Композитор/и за записа, ползва се при подреждане" + +msgid "grouping" +msgstr "групиране" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Сбира в една група произведение, което е от няколко части, напр. частите на " +"концерт. Това ниво е по-високо от песен, но по-ниско от албум." + +msgid "user rating" +msgstr "оценка" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Оценка според потребителя. По-висока стойност означава по-силно предпочитание" + +msgid "device manufacturer" +msgstr "производител на устройство" + +msgid "Manufacturer of the device used to create this media" +msgstr "Производител на устройството, с което е създадена медията" + +msgid "device model" +msgstr "модел на устройство" + +msgid "Model of the device used to create this media" +msgstr "Модел на устройството, с което е създадена медията" + +msgid "application name" +msgstr "име на програма" + +msgid "Application used to create the media" +msgstr "Програмата, с което е създадена медията" + +msgid "application data" +msgstr "данни от програмата" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Произволни данни от програма, поставени в медията" + +msgid "image orientation" +msgstr "ориентация" + +msgid "How the image should be rotated or flipped before display" +msgstr "Как да се завърти изображението при показване" + +msgid "publisher" +msgstr "издател" + +msgid "Name of the label or publisher" +msgstr "Името на издателя или издателската къща" + +msgid "interpreted-by" +msgstr "интерпретирано от" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Информация за хората създали ремикс или друга интерпретация" + +msgid "midi-base-note" +msgstr "нота за midi" + +msgid "Midi note number of the audio track." +msgstr "Номер на нотата по Midi за песента" + +msgid "private-data" +msgstr "собствени данни" + +msgid "Private data" +msgstr "Собствени данни" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Няма модул за обработка на протокола „%s“" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Схемата „%s“ в адреса не се поддържа" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ГРЕШКА: от елемент „%s“: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Допълнителна информация за изчистване на грешки:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "връзка без източник [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "връзка без приемник [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "елементът „2$%s“ няма свойството „1$%s“" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "свойството „%s“ на елемента „%s“ не може да се зададе да е „%s“" + +msgid "Delayed linking failed." +msgstr "Неуспешно отложено свързване." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "„%s“ не може да се свърже към „%s“, „%s“ не поддържа „%s“" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "„%s“ не може да се свърже към „%s“, никой от тях не поддържа „%s“" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "„%s“ не може да се свърже към „%s“ с възможност „%s“" + +#, c-format +msgid "could not link %s to %s" +msgstr "„%s“ не може да се свърже към „%s“" + +#, c-format +msgid "no element \"%s\"" +msgstr "елементът „%s“ липсва" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "неочакван указател „%s“ — прескача се" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "неочакван указател за допълване „%s“ — прескача се" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "възможностите „%s“ не могат да бъдат анализирани" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "няма елемент-приемник за адрес „%s“" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "няма елемент-източник за адрес „%s“" + +msgid "syntax error" +msgstr "синтактична грешка" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "указан е празен резервоар „%s“, това е забранено" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "няма резервоар на име „%s“, елементите се разпакетират" + +msgid "empty pipeline not allowed" +msgstr "не е позволен празен конвейер" + +msgid "A lot of buffers are being dropped." +msgstr "Много буфери се пропускат." + +msgid "Internal data flow problem." +msgstr "Вътрешен проблем на потока от данни." + +msgid "Internal data flow error." +msgstr "Вътрешна грешка на потока от данни." + +msgid "Internal clock error." +msgstr "Вътрешна грешка на часовника." + +msgid "Failed to map buffer." +msgstr "Неуспешно поместване на буфера в паметта." + +msgid "Filter caps" +msgstr "Възможности на филтър" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Ограничаване на позволените възможности („NULL“ означава всякакви). " +"Задаването на това свойство поема указател към подадения обект GstCaps." + +msgid "Caps Change Mode" +msgstr "Режим на смяна на възможностите" + +msgid "Filter caps change behaviour" +msgstr "Филтриране на поведението на смяна на възможностите" + +msgid "No Temp directory specified." +msgstr "Не е указана временна папка" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Не може да се създаде временният файл „%s“." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Файлът „%s“ не може да се отвори за четене." + +msgid "Error while writing to download file." +msgstr "Грешка при запис в сваления файл." + +msgid "No file name specified for writing." +msgstr "Не е указано име на файл за запис." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Файлът „%s“ не може да се отвори за запис." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Грешка при затварянето на файла „%s“." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Грешка при позициониране във файл „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Грешка при запис във файл „%s“." + +msgid "No file name specified for reading." +msgstr "Не е указано име на файл за четене." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Не може да се получи информация за „%s“." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s“ е папка." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Файлът „%s“ е гнездо." + +msgid "Failed after iterations as requested." +msgstr "Грешка след заявения брой повторения." + +msgid "caps" +msgstr "възможности" + +msgid "detected capabilities in stream" +msgstr "засечените възможности на потока" + +msgid "minimum" +msgstr "минимум" + +msgid "force caps" +msgstr "принудително прилагане на възможности" + +msgid "force caps without doing a typefind" +msgstr "принудително прилагане на възможности без търсене на видовете" + +msgid "Stream doesn't contain enough data." +msgstr "Потокът не съдържа достатъчно данни." + +msgid "Stream contains no data." +msgstr "Потокът не съдържа никакви данни" + +msgid "Implemented Interfaces:\n" +msgstr "Реализирани интерфейси:\n" + +msgid "readable" +msgstr "с права за четене" + +msgid "writable" +msgstr "с права за запис" + +msgid "deprecated" +msgstr "изоставен" + +msgid "controllable" +msgstr "може да се контролира" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" +"може да се променя само в състоянията NULL (зануляване), READY (готовност), " +"PAUSED (на пауза) или PLAYING (изпълнение)" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" +"може да се променя само в състоянията NULL (зануляване), READY (готовност) " +"или PAUSED (на пауза)" + +msgid "changeable only in NULL or READY state" +msgstr "" +"може да се променя само в състоянията NULL (зануляване) или READY (готовност)" + +msgid "Blacklisted files:" +msgstr "Забранени файлове:" + +msgid "Total count: " +msgstr "Общ брой:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d забранен файл" +msgstr[1] "%d забранени файла" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d приставка" +msgstr[1] "%d приставки" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d забранен запис" +msgstr[1] "%d забранени записа" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d свойство" +msgstr[1] "%d свойства" + +msgid "Print all elements" +msgstr "Отпечатване на всички елементи" + +msgid "Print list of blacklisted files" +msgstr "Отпечатване на списъка със забранените файлове" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Отпечатване на списък с възможностите на указаната приставка или всички " +"приставки.\n" +" Удобно във връзка с външни механизми " +"за автоматично инсталиране на приставки" + +msgid "List the plugin contents" +msgstr "Отпечатване на съдържанието на приставките" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "Списък с разделител наклонена черта („/“) от елементи. (неподреден)" + +msgid "Check if the specified element or plugin exists" +msgstr "Проверка дали избраният елемент или приставка съществуват" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"При проверката за съществуване на елемент или приставка да се проверява дали " +"версията е минимум указаната" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Отпечатване на поддържаните схеми за адреси URI, както и елементите с тяхна " +"реализация" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Файлът на приставката не може да бъде зареден: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Няма такъв елемент или приставка „%s“\n" + +msgid "Index statistics" +msgstr "Статистика на индекса" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Получено е съобщение #%u от елемент „%s“ (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Получено е съобщение #%u от допълването „%s:%s“ (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Получено е съобщение #%u от обект „%s“ (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Получено е съобщение #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Получен е EOS (край на потока) от елемент „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ОТКРИТ ЕТИКЕТ : открит около елемент „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ОТКРИТ ЕТИКЕТ : открит около допълването „%s:%s“.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ОТКРИТ ЕТИКЕТ : открит около обект „%s“.\n" + +msgid "FOUND TAG\n" +msgstr "ОТКРИТ ЕТИКЕТ\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ОТКРИТО СЪДЪРЖАНИЕ : открито около елемент „%s“.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ОТКРИТО СЪДЪРЖАНИЕ : открито около обект „%s“.\n" + +msgid "FOUND TOC\n" +msgstr "ОТКРИТО СЪДЪРЖАНИЕ\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"ИНФОРМАЦИЯ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: от елемент %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Буфериран, изчаква се завършването на буферирането…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Буфериран, изчаква се завършването…\n" + +msgid "buffering..." +msgstr "буфериране…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Буферирането завърши, конвейерът се дава за ИЗПЪЛНЕНИЕ…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Буфериране, конвейерът се дава НА ПАУЗА…\n" + +msgid "Redistribute latency...\n" +msgstr "Преразпределяне на латентността…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Задаване на състоянието на %s по заявка на %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Прекъсване: Конвейерът се спира…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Напредък: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Липсващ елемент: „%s“\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Получен е контекст от елемента „%s“: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Извеждане на етикетите (метаданните)" + +msgid "Output TOC (chapters and editions)" +msgstr "Извеждане на съдържанието (глави и издания)" + +msgid "Output status information and property notifications" +msgstr "Извеждане на съобщения за състоянието и промяната на свойства" + +msgid "Do not print any progress information" +msgstr "Да не се извежда информация за напредъка" + +msgid "Output messages" +msgstr "Изходни съобщения" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Без извеждане на информацията за състоянието на указаното свойство, ако е " +"включен подробния изход (може да се ползва много пъти)" + +msgid "PROPERTY-NAME" +msgstr "ИМЕ-НА-СВОЙСТВО" + +msgid "Do not install a fault handler" +msgstr "Да не се инсталира модул за обработка на грешки" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" +"Принудително извеждане на EOS за източниците преди спирането на конвейера" + +msgid "Gather and print index statistics" +msgstr "Събиране и показване на статистика за индекса" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ГРЕШКА: конвейерът не може да бъде конструиран: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ГРЕШКА: конвейерът не може да бъде конструиран.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: конвейер с грешки: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ГРЕШКА: не е открит елемент за конвейер — „pipeline“.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Конвейерът се дава НА ПАУЗА…\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ГРЕШКА: конвейерът не изпълнява даването на пауза.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Конвейерът работи и не се нуждае от БУФЕРИРАНЕ…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Конвейерът се БУФЕРИРА…\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ГРЕШКА: конвейерът не иска да превърти напред.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Конвейерът е БУФЕРИРАН…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Конвейерът се дава за ИЗПЪЛНЕНИЕ…\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ГРЕШКА: конвейерът не иска да проработи.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Включен е EOS при спиране — извеждане на EOS по конвейера\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Включен е EOS при спиране — извеждане на EOS след грешка\n" + +msgid "Waiting for EOS...\n" +msgstr "Изчакване на EOS…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Получен е край на поток: конвейерът се спира…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Прекъсване при изчакване: конвейерът се спира…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Възникна грешка при изчакването на EOS\n" + +msgid "Execution ended after %" +msgstr "Изпълнението завърши след %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Конвейерът е в ГОТОВНОСТ…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Конвейерът се ЗАНУЛЯВА…\n" + +msgid "Freeing pipeline ...\n" +msgstr "Конвейерът се освобождава…\n" diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 0000000..4b937aa --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/ca.gmo b/po/ca.gmo new file mode 100644 index 0000000..d6fa1d1 Binary files /dev/null and b/po/ca.gmo differ diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 0000000..68bd1a5 --- /dev/null +++ b/po/ca.po @@ -0,0 +1,1591 @@ +# Catalan translation for gstreamer. +# Copyright © 2004, 2005, 2010 Free Software Foundation, Inc. +# This file is distributed under the same licence as the gstreamer package. +# Jordi Mallach , 2004, 2005, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-11-04 19:41+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" +"Plural-Forms: nplurals=2; plural=n!=1;\n" + +msgid "Print the GStreamer version" +msgstr "Imprimeix la versió de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Fes fatals tots els avisos" + +msgid "Print available debug categories and exit" +msgstr "Imprimeix les categories de depuració disponibles i surt" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Nivell de depuració per defecte des de 1 (només errors) a 5 (tot) o 0 per a " +"cap sortida" + +msgid "LEVEL" +msgstr "NIVELL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Llista separada per comes de parelles nom_categoria:nivell per a establir " +"nivells específics per a les categories individuals. Per exemple: " +"GST_AUTOPLUG:5, GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LLISTA" + +msgid "Disable colored debugging output" +msgstr "Inhabilita la sortida de depuració colorejada" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Inhabilita la depuració" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Habilita els diagnòstics detallats de càrrega de connectors" + +msgid "Colon-separated paths containing plugins" +msgstr "Camins separats per dos punts que contenen connectors" + +msgid "PATHS" +msgstr "CAMINS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Llista separada per comes de connectors a precarregar a més de la llista " +"emmagatzemada en la variable d'entorn GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "CONNECTORS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Inhabilita la captura de violacions de segment durant la càrrega de " +"connectors" + +msgid "Disable updating the registry" +msgstr "Inhabilita l'actualització del registre" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Inhabilita el llançament d'un procés auxiliar mentre s'analitza el registre" + +msgid "GStreamer Options" +msgstr "Opcions del GStreamer" + +msgid "Show GStreamer Options" +msgstr "Mostra les opcions del GStreamer" + +msgid "Unknown option" +msgstr "Opció desconeguda" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer ha trobat un error general de la biblioteca principal." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Els desenvolupadors de GStreamers han sigut tan ganduls que no han assignat " +"un codi d'error per a aquest error." + +msgid "Internal GStreamer error: code not implemented." +msgstr "S'ha produït un error intern de GStreamer: codi no implementat." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"S'ha produït un error del GStreamer: el canvi d'estat ha fallat i algun " +"element no ha pogut enviar un missatge d'error amb la raó de la fallida." + +msgid "Internal GStreamer error: pad problem." +msgstr "S'ha produït un error intern de GStreamer: problema de ceŀla." + +msgid "Internal GStreamer error: thread problem." +msgstr "S'ha produït un error intern de GStreamer: problema de fils." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "S'ha produït un error intern de GStreamer: problema de negociació." + +msgid "Internal GStreamer error: event problem." +msgstr "S'ha produït un error intern de GStreamer: problema d'esdeveniment." + +msgid "Internal GStreamer error: seek problem." +msgstr "S'ha produït un error intern de GStreamer: problema de cerca." + +msgid "Internal GStreamer error: caps problem." +msgstr "S'ha produït un error intern de GStreamer: problema de capacitats." + +msgid "Internal GStreamer error: tag problem." +msgstr "S'ha produït un error intern de GStreamer: problema d'etiqueta." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "La vostra instal·lació del GStreamer manca un connector." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "S'ha produït un error intern de GStreamer: problema de rellotge." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Aquesta aplicació està tractant d'emprar funcionalitat del GStreamer que " +"s'ha inhabilitat." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer ha trobat un error general de la biblioteca de recolzament." + +msgid "Could not initialize supporting library." +msgstr "No s'ha pogut inicialitzar la biblioteca de recolzament." + +msgid "Could not close supporting library." +msgstr "No s'ha pogut tancar la biblioteca de recolzament." + +msgid "Could not configure supporting library." +msgstr "No s'ha pogut configurar la biblioteca de recolzament." + +msgid "Encoding error." +msgstr "S'ha produït un error de codificació." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer ha trobat un error general de recursos." + +msgid "Resource not found." +msgstr "No s'ha trobat el recurs." + +msgid "Resource busy or not available." +msgstr "El recurs està ocupat o no està disponible." + +msgid "Could not open resource for reading." +msgstr "No s'ha pogut obrir el recurs per a la lectura." + +msgid "Could not open resource for writing." +msgstr "No s'ha pogut obrir el recurs per a l'escriptura." + +msgid "Could not open resource for reading and writing." +msgstr "No s'ha pogut obrir el recurs per a l'escriptura i la lectura." + +msgid "Could not close resource." +msgstr "No s'ha pogut tancar el recurs." + +msgid "Could not read from resource." +msgstr "No s'ha pogut llegir des del recurs." + +msgid "Could not write to resource." +msgstr "No s'ha pogut escriure al recurs." + +msgid "Could not perform seek on resource." +msgstr "No s'ha pogut fer una cerca al recurs." + +msgid "Could not synchronize on resource." +msgstr "No s'ha pogut sincronitzar al recurs." + +msgid "Could not get/set settings from/on resource." +msgstr "No s'ha pogut obtenir/establir els paràmetres des del/al recurs." + +msgid "No space left on the resource." +msgstr "No resta espai al recurs." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "No resta espai al recurs." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer ha trobat un error general de flux." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"L'element no implementa la gestió d'aquest flux. Envieu un informe d'error." + +msgid "Could not determine type of stream." +msgstr "No s'ha pogut determinar el tipus de flux." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"El flux és d'un tipus diferent del qual és gestionat per aquest element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "No hi ha cap còdec present que puga gestionar el tipus del flux." + +msgid "Could not decode stream." +msgstr "No s'ha pogut decodificar el flux." + +msgid "Could not encode stream." +msgstr "No s'ha pogut codificar el flux." + +msgid "Could not demultiplex stream." +msgstr "No s'ha pogut demultiplexar el flux." + +msgid "Could not multiplex stream." +msgstr "No s'ha pogut multiplexar el flux." + +msgid "The stream is in the wrong format." +msgstr "El flux és en el format erroni." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "El flux és xifrat i no s'ha implementat el desxifratge." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"El flux és xifrat i no es pot desxifrar perquè no s'ha proveït una clau " +"adequada." + +#, c-format +msgid "No error message for domain %s." +msgstr "No hi ha cap missatge d'error per al domini %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" +"No s'ha trobat cap missatge d'error estàndard per al domini %s i el codi %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "El rellotge seleccionat no es pot emprar al conducte." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "títol" + +msgid "commonly used title" +msgstr "títol usat habitualment" + +msgid "title sortname" +msgstr "nom d'ordenació del títol" + +msgid "commonly used title for sorting purposes" +msgstr "títol usat habitualment per a l'ordenació" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "persones responsables de la gravació" + +msgid "artist sortname" +msgstr "nom d'ordenació de l'artista" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persones responsables de la gravació per a l'ordenació" + +msgid "album" +msgstr "àlbum" + +msgid "album containing this data" +msgstr "àlbum que conté aquesta dades" + +msgid "album sortname" +msgstr "nom d'ordenació de l'àlbum" + +msgid "album containing this data for sorting purposes" +msgstr "àlbum que conté aquesta dades per a l'ordenació" + +msgid "album artist" +msgstr "artista de l'àlbum" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "L'artista de l'àlbum sencer, tal i com s'hauria de mostrar" + +msgid "album artist sortname" +msgstr "nom d'ordenació de l'artista de l'àlbum" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "L'artista de l'àlbum sencer, tal i com s'hauria d'ordenar" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data en la qual es van crear les dades (com a una estructura GDate)" + +msgid "datetime" +msgstr "datahora" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"data i hora en què es van crear les dades (com a una estructura GstDateTime)" + +msgid "genre" +msgstr "gènere" + +msgid "genre this data belongs to" +msgstr "gènere al qual pertanyen aquestes dades" + +msgid "comment" +msgstr "comentari" + +msgid "free text commenting the data" +msgstr "text lliure comentant les dades" + +msgid "extended comment" +msgstr "comentari estés" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"text lliure comentant les dades en forma clau=valor o clau[ca]=comentari" + +msgid "track number" +msgstr "número de pista" + +msgid "track number inside a collection" +msgstr "número de pista dins d'una col·lecció" + +msgid "track count" +msgstr "compte de pistes" + +msgid "count of tracks inside collection this track belongs to" +msgstr "compte de pistes dins de la col·lecció a la qual pertany aquesta pista" + +msgid "disc number" +msgstr "número de disc" + +msgid "disc number inside a collection" +msgstr "número de disc dins d'una col·lecció" + +msgid "disc count" +msgstr "compte de disc" + +msgid "count of discs inside collection this disc belongs to" +msgstr "comte de discs dins de la col·lecció a la qual pertany aquest disc" + +msgid "location" +msgstr "ubicació" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Origen del medi com a URI (ubicació, on s'allotja el fitxer o flux original)" + +msgid "homepage" +msgstr "pàgina principal" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Pàgina principal d'aquest medi (p. ex. la pàgina principal de l'artista o " +"peŀlícula)" + +msgid "description" +msgstr "descripció" + +msgid "short text describing the content of the data" +msgstr "text curt descrivint el contingut de les dades" + +msgid "version" +msgstr "versió" + +msgid "version of this data" +msgstr "versió d'aquestes dades" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - vegeu http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organització" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "nota de copyright de les dades" + +msgid "copyright uri" +msgstr "uri del copyright" + +msgid "URI to the copyright notice of the data" +msgstr "URI a la nota del copyright de les dades" + +#, fuzzy +msgid "encoded by" +msgstr "codificador" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "contacte" + +msgid "contact information" +msgstr "informació de contacte" + +msgid "license" +msgstr "llicència" + +msgid "license of data" +msgstr "llicència de les dades" + +msgid "license uri" +msgstr "uri de la llicència" + +msgid "URI to the license of the data" +msgstr "URI a la llicència de les dades" + +msgid "performer" +msgstr "músic" + +msgid "person(s) performing" +msgstr "persones que toquen" + +msgid "composer" +msgstr "compositor" + +msgid "person(s) who composed the recording" +msgstr "persones que composaren la gravació" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "durada" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "durada en la unitat de temps de GStreamer (nanosegons)" + +msgid "codec" +msgstr "còdec" + +msgid "codec the data is stored in" +msgstr "còdec en el qual estan emmagatzemades les dades" + +msgid "video codec" +msgstr "còdec de vídeo" + +msgid "codec the video data is stored in" +msgstr "còdel en el qual estan emmagatzemades les dades de vídeo" + +msgid "audio codec" +msgstr "còdec d'àudio" + +msgid "codec the audio data is stored in" +msgstr "còdec en el qual estan emmagatzemades les dades d'àudio" + +msgid "subtitle codec" +msgstr "còdec de subtítols" + +msgid "codec the subtitle data is stored in" +msgstr "còdel en el qual estan emmagatzemades les dades de subtítols" + +msgid "container format" +msgstr "format del contenidor" + +msgid "container format the data is stored in" +msgstr "format de contenidor en què estan emmagatzemades les dades" + +msgid "bitrate" +msgstr "ràtio de bits" + +msgid "exact or average bitrate in bits/s" +msgstr "mitja o valor exacte de ràtio de bits en bits/s" + +msgid "nominal bitrate" +msgstr "ràtio de bits nominal" + +msgid "nominal bitrate in bits/s" +msgstr "ràtio de bits nominal en bits/s" + +msgid "minimum bitrate" +msgstr "ràtio de bits mínim" + +msgid "minimum bitrate in bits/s" +msgstr "ràtio de bits mínim en bits/s" + +msgid "maximum bitrate" +msgstr "ràtio de bits màxim" + +msgid "maximum bitrate in bits/s" +msgstr "ràtio de bits màxim en bits/s" + +msgid "encoder" +msgstr "codificador" + +msgid "encoder used to encode this stream" +msgstr "codificador utilitzat per a codificar aquest flux" + +msgid "encoder version" +msgstr "versió del codificador" + +msgid "version of the encoder used to encode this stream" +msgstr "versió del codificador utilitzat per a codificar aquest flux" + +msgid "serial" +msgstr "número de sèrie" + +msgid "serial number of track" +msgstr "número de sèrie de la pista" + +msgid "replaygain track gain" +msgstr "ganància de replaygain de la pista" + +msgid "track gain in db" +msgstr "ganància de la pista en db" + +msgid "replaygain track peak" +msgstr "cim de les pistes del replaygain" + +msgid "peak of the track" +msgstr "cim de les pistes" + +msgid "replaygain album gain" +msgstr "ganància de l'àlbum del replaygain" + +msgid "album gain in db" +msgstr "ganància de l'àlbum en db" + +msgid "replaygain album peak" +msgstr "cim de l'àlbum del replaygain" + +msgid "peak of the album" +msgstr "cim de l'àlbum" + +msgid "replaygain reference level" +msgstr "nivell de referència del replaygain" + +msgid "reference level of track and album gain values" +msgstr "nivell de referència dels valors de guany de la pista i àlbum" + +msgid "language code" +msgstr "codi de la llengua" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "codi de la llengua per a aquest flux, conformant amb ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "codi de la llengua" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "imatge" + +msgid "image related to this stream" +msgstr "imatge relacionada amb aquest flux" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "previsualització de la imatge" + +msgid "preview image related to this stream" +msgstr "previsualització de la imatge relacionada amb aquest flux" + +msgid "attachment" +msgstr "adjunt" + +msgid "file attached to this stream" +msgstr "fitxer adjuntat a aquest flux" + +msgid "beats per minute" +msgstr "cops per minut" + +msgid "number of beats per minute in audio" +msgstr "nombre de cops per minut a l'àudio" + +msgid "keywords" +msgstr "paraules clau" + +msgid "comma separated keywords describing the content" +msgstr "paraules clau separades per comes que descriuen el contingut" + +msgid "geo location name" +msgstr "nom de la geolocalització" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"ubicació descriptiva llegible pels humans del lloc on s'ha enregistrat o " +"produït el medi" + +msgid "geo location latitude" +msgstr "latitud de la geolocalització" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitud de la geolocalització del lloc on s'ha enregistrat o produït el " +"medi, en graus concordants a WGS84 (zero a l'equador, valors negatius per a " +"latituds al sud)" + +msgid "geo location longitude" +msgstr "longitud de la geolocalització" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitud de la geolocalització del lloc on s'ha enregistrat o produït el " +"medi, en graus concordants a WGS84 (zero al meridià inicial a Greenwich/UK, " +"valors negatius per a longituds occidentals)" + +msgid "geo location elevation" +msgstr "elevació de la geolocalització" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"elevació de la geolocalització del lloc on s'ha enregistrat o produït el " +"medi, en graus concordants a WGS84 (zero és el nivell del mar mitjà)" + +msgid "geo location country" +msgstr "estat de la geolocalització" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "estat (nom en anglès) del lloc on s'ha enregistrat o produït el medi" + +msgid "geo location city" +msgstr "ciutat de la geolocalització" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "ciutat (nom en anglès) del lloc on s'ha enregistrat o produït el medi" + +msgid "geo location sublocation" +msgstr "sububicació de la geolocalització" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"una ubicació dins de la ciutat on s'ha enregistrat o produït el medi (p. ex. " +"el barri)" + +msgid "geo location horizontal error" +msgstr "error horitzontal de la geolocalització" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "error esperat de les mesures de posicionament horitzonat (en metres)" + +msgid "geo location movement speed" +msgstr "velocitat del moviment de la geolocalització" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"velocitat del moviment del dispositiu de captura mentre es prenia la captura " +"en m/s" + +msgid "geo location movement direction" +msgstr "direcció del moviment de la geolocalització" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica la direcció del moviment del dispositiu que prenia la captura d'un " +"medi. Es representa en graus en representació de coma flotant, 0 vol dir el " +"nord geogràfic, i augmenta en sentit de les agulles del rellotge" + +msgid "geo location capture direction" +msgstr "direcció de la captura de la geolocalització" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica la direcció on apunta el dispositiu mentre captura un medi. Es " +"representa en graus en representació de coma flotant, 0 vol dir el nord " +"geogràfic, i augmenta en sentit de les agulles del rellotge" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nom del programa" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nom del programa de TV/podcast/sèrie al qual pertany el medi" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nom d'ordenació del programa" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Nom programa de TV/podcast/sèrie al qual pertany el medi, per a l'ordenació" + +msgid "episode number" +msgstr "número d'episodi" + +msgid "The episode number in the season the media is part of" +msgstr "El número d'episodi de la temporada al qual pertany el medi" + +msgid "season number" +msgstr "número de temporada" + +msgid "The season number of the show the media is part of" +msgstr "El número de temporada del programa al qual pertany el medi" + +msgid "lyrics" +msgstr "lletres" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Les lletres del medi, habitualment emprat per a cançons" + +msgid "composer sortname" +msgstr "nom d'ordenació del compositor" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "persones que composaren la gravació, per a l'ordenació" + +msgid "grouping" +msgstr "agrupació" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"medis agrupats que es composen de diverses pistes, com les diferents peces " +"d'un concert. És de nivell més alt que una pista, però més baix que un àlbum" + +msgid "user rating" +msgstr "valoració de l'usuari" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Valoració atribuïda per un usuari. Com més alta és, més li agrada el medi a " +"l'usuari" + +msgid "device manufacturer" +msgstr "fabricant del dispositiu" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricant del dispositiu emprat per a crear aquest medi" + +msgid "device model" +msgstr "model del dispositiu" + +msgid "Model of the device used to create this media" +msgstr "Model del dispositiu emprat per a crear aquest medi" + +msgid "application name" +msgstr "nom de l'aplicació" + +msgid "Application used to create the media" +msgstr "Aplicació emprada per a crear el medi" + +msgid "application data" +msgstr "dades de l'aplicació" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Dades arbitràries de l'aplicació a serialitzar al medi" + +msgid "image orientation" +msgstr "orientació de la imatge" + +msgid "How the image should be rotated or flipped before display" +msgstr "Com s'hauria de rotar o girar la imatge abans de mostrar-la" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERROR: des de l'element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Informació de depuració addicional:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "no hi ha cap propietat «%s» en l'element «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "no s'ha pogut establir la propietat «%s» en l'element «%s» a «%s»" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "no s'ha pogut enllaçar %s a %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "No s'ha pogut enllaçar l'element de sortida per a l'URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "no s'ha pogut enllaçar %s a %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "no s'ha pogut enllaçar %s a %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "no hi ha cap element «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "no s'han pogut analitzar les capacitats «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "no hi ha cap element de sortida per a l'URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "no hi ha cap element font per a l'URI «%s»" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "el binari especificat «%s» és buit, no es permet" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "el binari «%s» no existeix, es descarta" + +msgid "empty pipeline not allowed" +msgstr "no es permet un conducte buit" + +msgid "A lot of buffers are being dropped." +msgstr "S'estan descartant moltes memòries intermèdies." + +msgid "Internal data flow problem." +msgstr "Hi ha un problema intern de flux de dades." + +msgid "Internal data flow error." +msgstr "S'ha produït un error intern de flux de dades." + +msgid "Internal clock error." +msgstr "S'ha produït un error intern del rellotge." + +#, fuzzy +msgid "Failed to map buffer." +msgstr "No s'ha pogut codificar la imatge." + +msgid "Filter caps" +msgstr "Filtra les capacitats" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restringeix les capacitats que es poden permetre (NUL vol dir QUALSEVOL). " +"Establir aquesta propietat pren una referència a l'objecte GstCaps proveït." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "No s'ha especificat un directori temporal." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "No s'ha pogut crear el fitxer temporal «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "No s'ha pogut obrir el fitxer «%s» per a la lectura." + +msgid "Error while writing to download file." +msgstr "S'ha produït un error en escriure al fitxer de baixada." + +msgid "No file name specified for writing." +msgstr "No s'ha especificat cap nom de fitxer per a l'escriptura." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "No s'ha pogut obrir «%s» per a l'escriptura." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "S'ha produït un error en tancar el fitxer «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "S'ha produït un error en cercar al fitxer «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "S'ha produït un error en escriure al fitxer «%s»." + +msgid "No file name specified for reading." +msgstr "No s'ha especificat cap fitxer per a llegir." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "No s'ha pogut obtenir informació sobre «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» és un directori." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "El fitxer «%s» és un sòcol." + +msgid "Failed after iterations as requested." +msgstr "Ha fallat després de les iteracions com s'ha demanat." + +msgid "caps" +msgstr "capacitats" + +msgid "detected capabilities in stream" +msgstr "capacitats detectades al flux" + +msgid "minimum" +msgstr "mínim" + +msgid "force caps" +msgstr "força les capacitats" + +msgid "force caps without doing a typefind" +msgstr "força les capacitats sense fer un «typefind»" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "El flux no conté dades." + +msgid "Stream contains no data." +msgstr "El flux no conté dades." + +msgid "Implemented Interfaces:\n" +msgstr "Interfícies implementades:\n" + +msgid "readable" +msgstr "llegible" + +msgid "writable" +msgstr "escrivible" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "controlable" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "es pot canviar als estats NUL, PREPARAT, EN PAUSA o REPRODUINT" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "es pot canviar als estats NUL, PREPARAT o EN PAUSA" + +msgid "changeable only in NULL or READY state" +msgstr "es pot canviar als estats NUL o PREPARAT" + +msgid "Blacklisted files:" +msgstr "Fitxers a la llista negra:" + +msgid "Total count: " +msgstr "Compte total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d fitxer a la llista negra" +msgstr[1] "%d fitxers a la llista negra" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d connector" +msgstr[1] "%d connectors" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entrada de la llista negra" +msgstr[1] "%d entrades de la llista negra" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funcionalitat" +msgstr[1] "%d funcionalitats" + +msgid "Print all elements" +msgstr "Imprimeix tots els elements" + +msgid "Print list of blacklisted files" +msgstr "Mostra una llista de fitxers a la llista negra" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Mostra una llista analitzable per màquines de funcionalitats que proveeixen " +"el connector o especificat, o tots els connectors.\n" +" Útil amb connexions amb mecanismes " +"externs d'instaŀlació de connectors" + +msgid "List the plugin contents" +msgstr "Mostra el contingut d'un connector" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Mostra els esquemes d'URI implementats, amb els elements que els implementen" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "No s'ha pogut carregar el fitxer de connector: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "L'element o connector «%s» no existeix\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "S'ha rebut el missatge #%u de l'element «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "S'ha rebut el missatge #%u de la ceŀla «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "S'ha rebut el missatge #%u de l'objecte «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "S'ha rebut el missatge %u: (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "S'ha obtingut un final del flux de l'element «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "MARCADOR TROBAT: trobat per l'element «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "MARCADOR TROBAT: trobat per la ceŀla «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "MARCADOR TROBAT: trobat per l'objecte «%s».\n" + +msgid "FOUND TAG\n" +msgstr "MARCADOR TROBAT\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "MARCADOR TROBAT: trobat per l'element «%s».\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "MARCADOR TROBAT: trobat per l'objecte «%s».\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "MARCADOR TROBAT\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVÍS: des de l'element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" +"S'ha preparat, s'està esperant a que s'òmpliga la memòria intermèdial…\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" +"S'ha preparat, s'està esperant a que s'òmpliga la memòria intermèdial…\n" + +msgid "buffering..." +msgstr "s'està omplint la memòria intermèdia…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"S'està omplert la memòria intermèdia, s'estableix el conducte REPRODUINT…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" +"S'està omplint la memòria intermèdia, s'estableix el conducte a EN PAUSA…\n" + +# S'està redistribuint? jm +msgid "Redistribute latency...\n" +msgstr "Redistribució de la latència…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "S'està establint l'estat a %s a petició de %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrupció: S'està aturant el conducte…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "no hi ha cap element «%s»" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "AVÍS: des de l'element %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Mostra els marcadors (també coneguts com metadades)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Mostra la informació d'estat i notificacions de propietats" + +msgid "Do not print any progress information" +msgstr "No mostres informació del progrés" + +msgid "Output messages" +msgstr "Missatges de sortida" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "No instal·les un gestor de fallades" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Força el final del flux abans de tancar el conducte" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERROR: no s'ha pogut construir el conducte: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERROR: no s'ha pogut construir el conducte.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "AVÍS: el conducte és erroni: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERROR: l'element «conducte» no s'ha trobat.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "S'està establint el conducte a EN PAUSA…\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROR: el conducte no es vol posar en pausa.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "El conducte és en directe i no necessita PREPARACIÓ…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "El conducte s'està PREPARANT…\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERROR: el conducte no vol preparar-se.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "El conducte s'ha PREPARAT…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "S'està establint el conducte a REPRODUINT…\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERROR: el conducte no vol reproduir-se.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"S'ha habilitat el final del flux en tancar -- S'està forçant un final del " +"flux al conducte\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" +"S'ha habilitat el final del flux en tancar -- S'està forçant un final del " +"flux al conducte\n" + +msgid "Waiting for EOS...\n" +msgstr "S'està esperant al final del flux…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "S'ha rebut un final del flux - s'està aturant el conducte…\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrupció: S'està aturant el conducte…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "S'ha produït un error en esperar al final del flux\n" + +msgid "Execution ended after %" +msgstr "L'execució ha finalitzat després de %" + +msgid "Setting pipeline to READY ...\n" +msgstr "S'està establint el conducte a PREPARAT…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "S'està establint el conducte a NUL…\n" + +msgid "Freeing pipeline ...\n" +msgstr "S'està alliberant el conducte…\n" + +#~ msgid "Internal data stream error." +#~ msgstr "S'ha produït un error intern de flux de dades." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "No mostres informació d'estat de TIPUS" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPUS1,TIPUS2,…" + +#~ msgid "link without source element" +#~ msgstr "l'enllaç no té un element font" + +#~ msgid "link without sink element" +#~ msgstr "l'enllaç no té un element sortida" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "no hi ha cap element el qual enllaçar a l'URI «%s»" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Imprimeix una traça d'alloc (si s'ha habilitat al compilar)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Forma d'ús: gst-xmllaunch [ element.propietat=valor … ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROR: l'anàlisi del fitxer xml «%s» ha fallat.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERROR: no hi ha cap conducte de nivell superior en el fitxer «%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "AVÍS: només es gestiona un element de primer nivell ara mateix.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERROR: no s'ha pogut analitzar l'argument de la línia d'ordres %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "AVÍS: no s'ha trobat l'element anomenat «%s».\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Desa la representació xml del conducte a FITXER i surt" + +#~ msgid "FILE" +#~ msgstr "FITXER" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "No instaŀles gestors de senyals per a SIGUSR1 i SIGUSR2" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: ha fallat el canvi d'estat." + +#~ msgid "original location of file as a URI" +#~ msgstr "ubicació original del fitxer com una URI" + +#~ msgid "Could not open file \"%s\" for reading: %s." +#~ msgstr "No s'ha pogut obrir el fitxer «%s» per a la lectura: %s." + +#~ msgid "Element \"%s\" has gone from PLAYING to PAUSED, quitting.\n" +#~ msgstr "L'element «%s» ha canviat de REPRODUINT a PAUSAT, s'està sortint.\n" + +#~ msgid "ERROR: Pipeline can't PREROLL ...\n" +#~ msgstr "ERROR: el conducte no pot PREPARAR-SE.\n" + +#~ msgid " ns.\n" +#~ msgstr " ns.\n" + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "S'ESTÀ ALLIBERANT el conducte…\n" + +#~ msgid "NO_PREROLL pipeline ...\n" +#~ msgstr "Conducte SENSE PREPARACIÓ…\n" + +#~ msgid "PREROLL pipeline ...\n" +#~ msgstr "Conducte en PREPARACIÓ…\n" + +# Argh, PREROLLED vs READY. jm +#~ msgid "PREROLLED pipeline ...\n" +#~ msgstr "Conducte PREPARAT…\n" + +#~ msgid "RUNNING pipeline ...\n" +#~ msgstr "Conducte EN EXECUCIÓ…\n" + +#~ msgid "READY pipeline ...\n" +#~ msgstr "Conducte PREPARAT…\n" + +#~ msgid "NULL pipeline ...\n" +#~ msgstr "Conducte NUL…\n" + +#~ msgid "" +#~ "GStreamer developers were too lazy to assign an error code to this " +#~ "error. Please file a bug." +#~ msgstr "" +#~ "Els desenvolupadors de GStreamers han sigut tan ganduls que no han " +#~ "assignat un codi d'error per a aquest error. Si us plau, envieu un " +#~ "informe d'error." + +#~ msgid "Internal GStreamer error: code not implemented. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: codi no implementat. Envieu un " +#~ "informe d'error." + +#~ msgid "Internal GStreamer error: state change failed. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: ha fallat el canvi d'estat. " +#~ "Envieu un informe d'error." + +#~ msgid "Internal GStreamer error: thread problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema de fils. Envieu un " +#~ "informe d'error." + +#~ msgid "Internal GStreamer error: negotiation problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema de negociació. Envieu " +#~ "un informe d'error." + +#~ msgid "Internal GStreamer error: event problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema d'esdeveniment. " +#~ "Envieu un informe d'error." + +#~ msgid "Internal GStreamer error: seek problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema de cerca. Envieu un " +#~ "informe d'error." + +#~ msgid "Internal GStreamer error: capabilities problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema de capacitats. Envieu " +#~ "un informe d'error." + +#~ msgid "Internal GStreamer error: tag problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema d'etiqueta. Envieu un " +#~ "informe d'error." + +#~ msgid "Could not set settings." +#~ msgstr "No s'ha pogut establir els paràmetres." + +#~ msgid "date the data was created (in Julian calendar days)" +#~ msgstr "" +#~ "data en la qual es van crear les dades (en dies del calendari Julià)" + +#~ msgid "stream type" +#~ msgstr "tipus de flux" + +#~ msgid "detected type of stream" +#~ msgstr "s'ha detectat el tipus de flux" + +#~ msgid "Added plugin %s with %d feature.\n" +#~ msgid_plural "Added plugin %s with %d features.\n" +#~ msgstr[0] "S'ha afegit el connector %s amb %d funcionalitat.\n" +#~ msgstr[1] "S'ha afegit el connector %s amb %d funcionalitats.\n" + +#~ msgid "Loaded %d plugins with %d feature.\n" +#~ msgid_plural "Loaded %d plugins with %d features.\n" +#~ msgstr[0] "S'han carregat %d connectors amb %d funcionalitat.\n" +#~ msgstr[1] "S'han carregat %d connectors amb %d funcionalitats.\n" + +#~ msgid "print version information and exit" +#~ msgstr "imprimeix la informació sobre la versió i surt" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Inhabilita les intruccions d'UCP accelerades" + +#~ msgid "SCHEDULER" +#~ msgstr "PLANIFICADOR" + +#~ msgid "Registry to use" +#~ msgstr "Registre a utilitzar" + +#~ msgid "REGISTRY" +#~ msgstr "REGISTRE" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "llista de camins per a carregar connectors (separats per «%s»)" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Planificador a utilitzar (per defecte és «%s»)" + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "" +#~ "S'ha produït un error intern de GStreamer: problema del planificador. " +#~ "Envieu un informe d'error." + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "" +#~ "No hi ha cap element present per a gestionar el tipus mime %s del flux." + +#~ msgid "" +#~ "Execution ended after %s iterations (sum %s ns, average %s ns, min %s ns, " +#~ "max %s ns).\n" +#~ msgstr "" +#~ "L'execució ha finalitzat després de %s iteracions (suma %s ns, mitja %s " +#~ "ns, mín %s, màx %s).\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Nombre de vegades a iterar el conducte" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " S'està intentant executar tot i així.\n" + +#~ msgid "Added plugin %s with %d %s.\n" +#~ msgstr "S'ha afegit el connector %s amb %d %s.\n" + +#~ msgid "Added path %s to %s \n" +#~ msgstr "S'ha afegit el camí %s a %s\n" + +#~ msgid "Rebuilding %s (%s) ...\n" +#~ msgstr "S'està reconstruint %s (%s)…\n" + +#~ msgid "Trying to load %s ...\n" +#~ msgstr "S'està intentant carregar %s…\n" + +#~ msgid "Error loading %s\n" +#~ msgstr "S'ha produït un error en carregar %s\n" + +#~ msgid "Loaded %d plugins with %d %s.\n" +#~ msgstr "S'han carregat %d connectors amb %d %s.\n" + +#~ msgid " iterations (sum %" +#~ msgstr "iteracions (suma %" + +#~ msgid " ns, average %" +#~ msgstr " ns, mitja %" + +#~ msgid " ns, min %" +#~ msgstr " ns, mínim %" + +#~ msgid " ns, max %" +#~ msgstr " ns, màxim %" + +#~ msgid " ns).\n" +#~ msgstr " ns).\n" diff --git a/po/cs.gmo b/po/cs.gmo new file mode 100644 index 0000000..824d1fb Binary files /dev/null and b/po/cs.gmo differ diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 0000000..ff9b376 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,1352 @@ +# Czech translation of gstreamer. +# Copyright (C) 2004, 2005, 2007, 2008 gstreamer's COPYRIGHT HOLDER +# This file is put in the public domain. +# +# Miloslav Trmac , 2004, 2005, 2007, 2008. +# Marek Černocký , 2011, 2013, 2015, 2016, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-09-13 15:04+0200\n" +"Last-Translator: Marek Černocký \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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Gtranslator 2.91.7\n" + +msgid "Print the GStreamer version" +msgstr "Vypsat verzi systému GStreamer" + +msgid "Make all warnings fatal" +msgstr "Chápat všechna varování jako fatální" + +msgid "Print available debug categories and exit" +msgstr "Vypsat dostupné kategorie ladění a skončit" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Výchozí úroveň ladění od 1 (jen chyby) do 9 (vše) nebo 0 pro žádný výstup" + +msgid "LEVEL" +msgstr "ÚROVEŇ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Čárkami oddělovaný seznam dvojic název_kategorie:úroveň pro nastavení " +"konkrétních úrovní pro jednotlivé kategorie. Příklad: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "SEZNAM" + +msgid "Disable colored debugging output" +msgstr "Zakázat obarvený ladicí výstup" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Změnit režim obarvení ladicího záznamu. Možné režimy: off, on, disable, " +"auto, unix" + +msgid "Disable debugging" +msgstr "Zakázat ladění" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Povolit podrobnou diagnostiku načítání zásuvných modulů" + +msgid "Colon-separated paths containing plugins" +msgstr "Dvojtečkou oddělované cesty obsahující zásuvné moduly" + +msgid "PATHS" +msgstr "CESTY" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Čárkami oddělovaný seznam zásuvných modulů, které se mají načíst dopředu, " +"navíc k seznamu uloženému v proměnné prostředí GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "ZÁSUVNÉ_MODULY" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Zakázat zachytávání porušení segmentace při načítání zásuvných modulů" + +msgid "Disable updating the registry" +msgstr "Zakázat aktualizaci registru" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Zakázat větvení pomocných procesů při prohledávání registru" + +msgid "GStreamer Options" +msgstr "Přepínače GStreamer" + +msgid "Show GStreamer Options" +msgstr "Zobrazit přepínače GStreamer" + +msgid "Unknown option" +msgstr "Neznámý přepínač" + +msgid "GStreamer encountered a general core library error." +msgstr "V systému GStreamer došlo k obecné chybě základní knihovny." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Vývojáři systému GStreamer byli příliš líní na to, aby této chybě přiřadili " +"kód." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Interní chyba systému GStreamer: kód neimplementován." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Chyba systému GStreamer: selhala změna stavu a některý element selhal při " +"posílání příslušné chybové zprávy s důvodem selhání." + +msgid "Internal GStreamer error: pad problem." +msgstr "Interní chyba systému GStreamer: problém přípojky." + +msgid "Internal GStreamer error: thread problem." +msgstr "Interní chyba systému GStreamer: problém s vlákny." + +msgid "GStreamer error: negotiation problem." +msgstr "Chyba systému GStreamer: problém při vyjednávání." + +msgid "Internal GStreamer error: event problem." +msgstr "Interní chyba systému GStreamer: problém s událostmi." + +msgid "Internal GStreamer error: seek problem." +msgstr "Interní chyba systému GStreamer: problém s posunem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Interní chyba systému GStreamer: problém se schopnostmi." + +msgid "Internal GStreamer error: tag problem." +msgstr "Interní chyba systému GStreamer: problém se štítky." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Vaší instalaci systému GStreamer schází zásuvný modul." + +msgid "GStreamer error: clock problem." +msgstr "Chyba systému GStreamer: problém s hodinami." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Tato aplikace se pokouší používat funkce systému GStreamer, které byly " +"zakázány." + +msgid "GStreamer encountered a general supporting library error." +msgstr "V systému GStreamer došlo k chybě obecné podpůrné knihovny." + +msgid "Could not initialize supporting library." +msgstr "Nelze inicializovat podpůrnou knihovnu." + +msgid "Could not close supporting library." +msgstr "Nelze zavřít podpůrnou knihovnu." + +msgid "Could not configure supporting library." +msgstr "Nelze nastavit podpůrnou knihovnu." + +msgid "Encoding error." +msgstr "Chyba při kódování." + +msgid "GStreamer encountered a general resource error." +msgstr "V systému GStreamer došlo k obecné chybě prostředků." + +msgid "Resource not found." +msgstr "Prostředek nebyl nalezen." + +msgid "Resource busy or not available." +msgstr "Prostředek se právě používá nebo není k dispozici." + +msgid "Could not open resource for reading." +msgstr "Nelze otevřít prostředek pro čtení." + +msgid "Could not open resource for writing." +msgstr "Nelze otevřít prostředek pro zápis." + +msgid "Could not open resource for reading and writing." +msgstr "Nelze otevřít prostředek pro čtení a zápis." + +msgid "Could not close resource." +msgstr "Nelze zavřít prostředek." + +msgid "Could not read from resource." +msgstr "Nelze číst z prostředku." + +msgid "Could not write to resource." +msgstr "Nelze zapisovat do prostředku." + +msgid "Could not perform seek on resource." +msgstr "Nelze se posouvat v prostředku." + +msgid "Could not synchronize on resource." +msgstr "Nelze se synchronizovat s prostředkem." + +msgid "Could not get/set settings from/on resource." +msgstr "Nelze získat/změnit nastavení prostředku." + +msgid "No space left on the resource." +msgstr "V prostředku nezbývá místo." + +msgid "Not authorized to access resource." +msgstr "Není autorizováno pro přístup k prostředku." + +msgid "GStreamer encountered a general stream error." +msgstr "V systému GStreamer došlo k obecné chybě proudu." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Element neimplementuje obsluhu tohoto proudu. Nahlaste to prosím jako chybu." + +msgid "Could not determine type of stream." +msgstr "Nelze zjistit typ proudu." + +msgid "The stream is of a different type than handled by this element." +msgstr "Proud je jiného typu, než jaký tento element obsluhuje." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Není přítomen žádný kodek, který umí obsloužit typ tohoto proudu." + +msgid "Could not decode stream." +msgstr "Nelze dekódovat proud." + +msgid "Could not encode stream." +msgstr "Nelze zakódovat proud." + +msgid "Could not demultiplex stream." +msgstr "Nelze demultiplexovat proud." + +msgid "Could not multiplex stream." +msgstr "Nelze multiplexovat proud." + +msgid "The stream is in the wrong format." +msgstr "Proud je v nesprávném formátu." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Proud je zašifrován a dešifrování není podporováno." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Proud je zašifrován a nelze jej dešifrovat, protože nebyl poskytnut vhodný " +"klíč." + +#, c-format +msgid "No error message for domain %s." +msgstr "Pro doménu %s není žádná zpráva o chybě." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Pro doménu %s a kód %d není žádná standardní zpráva o chybě." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Vybrané hodiny nelze použít v rouře." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Chyba při zápisu mezipaměti registru do %s: %s" + +msgid "title" +msgstr "název" + +msgid "commonly used title" +msgstr "Obecně používaný název" + +msgid "title sortname" +msgstr "název pro účel řazení" + +msgid "commonly used title for sorting purposes" +msgstr "Obecně používaný název; pro účel řazení" + +msgid "artist" +msgstr "umělec" + +msgid "person(s) responsible for the recording" +msgstr "Osoba čí osoby odpovědné za nahrávku" + +msgid "artist sortname" +msgstr "umělec pro účel řazení" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "Osoba či osoby odpovědné za nahrávku; pro účel řazení" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "Album obsahující tato data" + +msgid "album sortname" +msgstr "album pro účel řazení" + +msgid "album containing this data for sorting purposes" +msgstr "Album obsahující tato data; pro účel řazení" + +msgid "album artist" +msgstr "umělec alba" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Umělec daného alba v podobě, jak se má zobrazovat" + +msgid "album artist sortname" +msgstr "umělec alba pro účel řazení" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Umělec alba v podobě, podle které se má řadit" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "Datum, kdy byla data vytvořena (jako struktura GDate)" + +msgid "datetime" +msgstr "datum a čas" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "Datum a čas, kdy byla data vytvořena (jako struktura GstDateTime)" + +msgid "genre" +msgstr "žánr" + +msgid "genre this data belongs to" +msgstr "Žánr, do kterého tato data patří" + +msgid "comment" +msgstr "poznámka" + +msgid "free text commenting the data" +msgstr "Volný text komentující data" + +msgid "extended comment" +msgstr "rozšířená poznámka" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"Volný text komentující data ve tvaru klíč=hodnota nebo klíč[cs]=poznámka" + +msgid "track number" +msgstr "číslo stopy" + +msgid "track number inside a collection" +msgstr "Číslo stopy v rámci sbírky" + +msgid "track count" +msgstr "počet stop" + +msgid "count of tracks inside collection this track belongs to" +msgstr "Počet stop v rámci sbírky, do kterého tato stopa patří" + +msgid "disc number" +msgstr "číslo disku" + +msgid "disc number inside a collection" +msgstr "Číslo disku v rámci sbírky" + +msgid "disc count" +msgstr "počet disků" + +msgid "count of discs inside collection this disc belongs to" +msgstr "Počet disků v rámci sbírky, do kterého tento disk patří" + +msgid "location" +msgstr "umístění" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Původ média jako URI (umístění, kde je nabízen originál souboru nebo proudu)" + +msgid "homepage" +msgstr "domovská stránka" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Domovská stránka tohoto média (např. domovská stránka umělce nebo filmu)" + +msgid "description" +msgstr "popis" + +msgid "short text describing the content of the data" +msgstr "Krátký text popisující obsah dat" + +msgid "version" +msgstr "verze" + +msgid "version of this data" +msgstr "Verze těchto dat" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code – http://www.intergram.cz/cs/isrc/" + +msgid "organization" +msgstr "organizace" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "Oznámení o autorských právech k datům" + +msgid "copyright uri" +msgstr "uri copyrightu" + +msgid "URI to the copyright notice of the data" +msgstr "Adresa URI oznámení o autorských právech k datům" + +msgid "encoded by" +msgstr "zakódoval" + +msgid "name of the encoding person or organization" +msgstr "Jméno osoby nebo název organizace odpovědných za kódování" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "Kontaktní informace" + +msgid "license" +msgstr "licence" + +msgid "license of data" +msgstr "Licence dat" + +msgid "license uri" +msgstr "uri licence" + +msgid "URI to the license of the data" +msgstr "Adresa URI licence k datům" + +msgid "performer" +msgstr "výkonný umělec" + +msgid "person(s) performing" +msgstr "Vystupující osoba či osoby" + +msgid "composer" +msgstr "skladatel" + +msgid "person(s) who composed the recording" +msgstr "Osoby či osoby, které nahrávku složily" + +msgid "conductor" +msgstr "dirigent" + +msgid "conductor/performer refinement" +msgstr "Dirigent/upřesnění účinkujícího" + +msgid "duration" +msgstr "trvání" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "Délka v jednotkách času GStreamer (nanosekundách)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "Kodek, ve kterém jsou data uchována" + +msgid "video codec" +msgstr "kodek videa" + +msgid "codec the video data is stored in" +msgstr "Kodek, ve kterém jsou uchována data videa" + +msgid "audio codec" +msgstr "kodek zvuku" + +msgid "codec the audio data is stored in" +msgstr "Kodek, ve kterém jsou uchována data zvuku" + +msgid "subtitle codec" +msgstr "kodek titulků" + +msgid "codec the subtitle data is stored in" +msgstr "Kodek, ve kterém jsou uchována data titulků" + +msgid "container format" +msgstr "formát kontejneru" + +msgid "container format the data is stored in" +msgstr "Formát kontejneru, ve kterém jdou uchována data" + +msgid "bitrate" +msgstr "datový tok" + +msgid "exact or average bitrate in bits/s" +msgstr "Přesný nebo průměrný datový tok v bitech/s" + +msgid "nominal bitrate" +msgstr "nominální datový tok" + +msgid "nominal bitrate in bits/s" +msgstr "Nominální datový tok v bitech/s" + +msgid "minimum bitrate" +msgstr "minimální datový tok" + +msgid "minimum bitrate in bits/s" +msgstr "Minimální datový tok v bitech/s" + +msgid "maximum bitrate" +msgstr "maximální datový tok" + +msgid "maximum bitrate in bits/s" +msgstr "Maximální datový tok v bitech/s" + +msgid "encoder" +msgstr "kodér" + +msgid "encoder used to encode this stream" +msgstr "Kodér používaný pro kódování tohoto proudu" + +msgid "encoder version" +msgstr "verze kodéru" + +msgid "version of the encoder used to encode this stream" +msgstr "Verze kodéru používaného pro kódování tohoto proudu" + +msgid "serial" +msgstr "sériové číslo" + +msgid "serial number of track" +msgstr "Sériové číslo stopy" + +msgid "replaygain track gain" +msgstr "hlasitost přehrávání stopy" + +msgid "track gain in db" +msgstr "Zesílení stopy v db" + +msgid "replaygain track peak" +msgstr "špičková hlasitost přehrávání stopy" + +msgid "peak of the track" +msgstr "Špičkové zesílení stopy" + +msgid "replaygain album gain" +msgstr "hlasitost přehrávání alba" + +msgid "album gain in db" +msgstr "Zesílení alba v db" + +msgid "replaygain album peak" +msgstr "špičková hlasitost přehrávání alba" + +msgid "peak of the album" +msgstr "Špičkové zesílení alba" + +msgid "replaygain reference level" +msgstr "referenční úroveň hlasitosti" + +msgid "reference level of track and album gain values" +msgstr "Hodnota referenční úrovně zesílení stopy a alba" + +msgid "language code" +msgstr "kód jazyka" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "Kód jazyka pro tento proud, ve shodě s ISO-639-1 nebo ISO-639-2" + +msgid "language name" +msgstr "název jazyka" + +msgid "freeform name of the language this stream is in" +msgstr "název jazyka (ve volném tvaru), ve kterém je tento proud" + +msgid "image" +msgstr "obrázek" + +msgid "image related to this stream" +msgstr "Obrázek související s tímto proudem" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "obrázek s náhledem" + +msgid "preview image related to this stream" +msgstr "Obrázek s náhledem související s tímto proudem" + +msgid "attachment" +msgstr "příloha" + +msgid "file attached to this stream" +msgstr "Soubor připojený k tomuto proudu" + +msgid "beats per minute" +msgstr "tempo" + +msgid "number of beats per minute in audio" +msgstr "Tempo (v počtech úderů za minutu) zvuku" + +msgid "keywords" +msgstr "klíčová slova" + +msgid "comma separated keywords describing the content" +msgstr "Čárkami oddělovaná klíčová slova popisující obsah" + +msgid "geo location name" +msgstr "název místa" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"Popisné místo v člověkem čitelné podobě, kde bylo médium nahráno nebo " +"vytvořeno" + +msgid "geo location latitude" +msgstr "zeměpisná šířka místa" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"Zeměpisná šířka místa, kde bylo médium nahráno nebo vytvořeno, ve stupních " +"podle WGS84 (nula na rovníku, záporné hodnoty pro jižní polokouli)" + +msgid "geo location longitude" +msgstr "zeměpisná délka místa" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"Zeměpisná délka místa, kde bylo médium nahráno nebo vytvořeno, ve stupních " +"podle WGS84 (nula na hlavním poledníku v Greenwichi, záporné hodnoty pro " +"západní polokouli)" + +msgid "geo location elevation" +msgstr "zeměpisná výška místa" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"Zeměpisná výška místa, kde bylo médium nahráno nebo vytvořeno, v metrech " +"podle WGS84 (nula je průměrná hladina moře)" + +msgid "geo location country" +msgstr "země" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "Anglický název země, kde bylo médium nahráno nebo vytvořeno" + +msgid "geo location city" +msgstr "město" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "Anglický název města, kde bylo médium nahráno nebo vytvořeno" + +msgid "geo location sublocation" +msgstr "upřesnění místa" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "Místo v rámci města, kde bylo médium nahráno nebo vytvořeno" + +msgid "geo location horizontal error" +msgstr "vodorovná chyba místa" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" +"Předpokládaná chyba v udání polohy místa ve vodorovném směru (v metrech)" + +msgid "geo location movement speed" +msgstr "rychlost pohybu" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"Rychlost pohybu zachytávacího zařízení, které mění svoji polohu (v m/s)" + +msgid "geo location movement direction" +msgstr "směr pohybu" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"Určuje směr pohybu zařízení provádějícího zachytávání média. Je prezentováno " +"jako stupně v podobě desetinného čísla, kdy 0 značí zeměpisný sever a jde se " +"po směru hodinových ručiček" + +msgid "geo location capture direction" +msgstr "směr zachytávání" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"Určuje směr, kterým je zařízení nasměrováno během zachytávání média. Je " +"prezentováno jako stupně v podobě desetinného čísla, kdy 0 značí zeměpisný " +"sever a jde se po směru hodinových ručiček" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "název pořadu" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Název pořadu (televizního, podcastového apod.), ze kterého médium pochází" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "pořad pro účely řazení" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Název pořadu (televizního, podcastového apod.), ze kterého médium pochází; " +"pro účely řazení" + +msgid "episode number" +msgstr "číslo epizody" + +msgid "The episode number in the season the media is part of" +msgstr "Číslo epizody v rámci řady, které je médium součástí" + +msgid "season number" +msgstr "číslo řady" + +msgid "The season number of the show the media is part of" +msgstr "Číslo řady v rámci pořadu, jehož je médium součástí" + +msgid "lyrics" +msgstr "text" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Text k médiu, obvykle text hudební skladby" + +msgid "composer sortname" +msgstr "skladatel pro účely řazení" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "Osoba či osoby, které záznam složily; pro účely řazení" + +msgid "grouping" +msgstr "seskupování" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Skupiny vztahující se k médiu, které je rozloženo do více stop, třeba části " +"koncertu. Jde o vyšší úroveň členění než jsou stopy, ale nižší než je album" + +msgid "user rating" +msgstr "uživatelské hodnocení" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Hodnocení přidělené uživatelem. Čím vyšší hodnocení, tím se uživateli médium " +"víc líbí" + +msgid "device manufacturer" +msgstr "výrobce zařízení" + +msgid "Manufacturer of the device used to create this media" +msgstr "Výrobce zařízení použitého k vytvoření tohoto média" + +msgid "device model" +msgstr "model zařízení" + +msgid "Model of the device used to create this media" +msgstr "Model zařízení použitého k vytvoření tohoto média" + +msgid "application name" +msgstr "název aplikace" + +msgid "Application used to create the media" +msgstr "Aplikace použitá k vytvoření média" + +msgid "application data" +msgstr "data aplikace" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Libovolná aplikační data, která jsou serializována do média" + +msgid "image orientation" +msgstr "natočení obrázku" + +msgid "How the image should be rotated or flipped before display" +msgstr "Jak by měl být obrázek před zobrazením otočen nebo překlopen" + +msgid "publisher" +msgstr "vydavatel" + +msgid "Name of the label or publisher" +msgstr "Název vydavatelství nebo vydavatel" + +msgid "interpreted-by" +msgstr "ztvárnil" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informace o lidech stojících za mixováním a dalším podobným zpracováním" + +msgid "midi-base-note" +msgstr "základní nota MIDI" + +msgid "Midi note number of the audio track." +msgstr "Číslo noty MIDI pro zvukovou stopu." + +msgid "private-data" +msgstr "soukromá data" + +msgid "Private data" +msgstr "Soukromá data" + +msgid ", " +msgstr "; " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Nebyla nalezena žádná adresa URI ovladače pro protokol %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Schéma URI „%s“ není podporováno" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "CHYBA: od elementu %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Dodatečné ladicí informace:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "připojení nemá žádný zdroj [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "připojení nemá žádný cíl [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "v elementu „%2$s“ není žádná vlastnost „%1$s“" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nelze nastavit vlastnost „%s“ v elementu „%s“ na „%s“" + +msgid "Delayed linking failed." +msgstr "Odložené propojení selhalo." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nelze připojit element „%s“ k elementu „%s“, %s nezvládá schopnost %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"nelze připojit element „%s“ k elementu „%s“, žádný element nezvládá " +"schopnost %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nelze připojit element „%s“ k elementu „%s“ se schopností %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nelze připojit element „%s“ k elementu „%s“" + +#, c-format +msgid "no element \"%s\"" +msgstr "element „%s“ neexistuje" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "neočekávaný odkaz „%s“ – ignoruje se" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "neočekávaný odkaz přípojky „%s“ – ignoruje se" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nelze zpracovat schopnosti „%s“" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "neexistuje žádný cílový element pro adresu URI „%s“" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "neexistuje žádný zdrojový element pro adresu URI „%s“" + +msgid "syntax error" +msgstr "syntaktická chyba" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "zadán prázdný zásobník „%s“, to není dovoleno" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "zásobník „%s“, rozbaluje se element" + +msgid "empty pipeline not allowed" +msgstr "prázdná roura není povolena" + +msgid "A lot of buffers are being dropped." +msgstr "Většina vyrovnávacích pamětí je vyřazena." + +msgid "Internal data flow problem." +msgstr "Interní problém toku dat." + +msgid "Internal data flow error." +msgstr "Interní chyba toku dat." + +msgid "Internal clock error." +msgstr "Interní chyba hodin." + +msgid "Failed to map buffer." +msgstr "Selhalo namapování vyrovnávací paměti." + +msgid "Filter caps" +msgstr "Filtrovat schopnosti" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Omezit povolené schopnosti (NULL znamená VŠECHNY). Nastavení této vlastnosti " +"přebírá odkaz na zadaný objekt GstCaps." + +msgid "Caps Change Mode" +msgstr "Režim změny schopností" + +msgid "Filter caps change behaviour" +msgstr "Filtrovat chování změny schopností" + +msgid "No Temp directory specified." +msgstr "Není určena složka pro dočasné soubory." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nelze vytvořit dočasný soubor „%s“." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nelze otevřít soubor „%s“ pro čtení." + +msgid "Error while writing to download file." +msgstr "Chyba při zápisu do stahovaného souboru." + +msgid "No file name specified for writing." +msgstr "Není zadán název souboru pro zápis." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nelze otevřít soubor „%s“ pro zápis." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Chyba při zavírání souboru „%s“." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Chyba při posunu v souboru „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Chyba při zápisu do souboru „%s“." + +msgid "No file name specified for reading." +msgstr "Není zadán název souboru pro čtení." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nelze získat informace o „%s“." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s“ je složka." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Soubor „%s“ je soket." + +msgid "Failed after iterations as requested." +msgstr "Selhání po iteracích podle požadavku." + +msgid "caps" +msgstr "schopnosti" + +msgid "detected capabilities in stream" +msgstr "detekované schopnosti v proudu" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "vynutit schopnosti" + +msgid "force caps without doing a typefind" +msgstr "vynutit schopnosti bez hledání typu" + +msgid "Stream doesn't contain enough data." +msgstr "Proud neobsahuje dostatek dat." + +msgid "Stream contains no data." +msgstr "Proud neobsahuje žádná data." + +msgid "Implemented Interfaces:\n" +msgstr "Implementovaná rozhraní:\n" + +msgid "readable" +msgstr "lze číst" + +msgid "writable" +msgstr "lze zapisovat" + +msgid "deprecated" +msgstr "zavržené" + +msgid "controllable" +msgstr "lze ovládat" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "lze změnit ve stavu PRÁZDNÉ, PŘIPRAVENO, POZASTAVENO nebo PŘEHRÁVÁ" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "lze měnit jen ve stavu PRÁZDNÉ, PŘIPRAVENO nebo POZASTAVENO" + +msgid "changeable only in NULL or READY state" +msgstr "lze měnit jen ve stavu PRÁZDNÉ nebo PŘIPRAVENO" + +msgid "Blacklisted files:" +msgstr "Soubory na černé listině:" + +msgid "Total count: " +msgstr "Celkový počet: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d soubor na černé listině" +msgstr[1] "%d soubory na černé listině" +msgstr[2] "%d souborů na černé listině" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d zásuvný modul" +msgstr[1] "%d zásuvné moduly" +msgstr[2] "%d zásuvných modulů" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d záznam na černé listině" +msgstr[1] "%d záznamy na černé listině" +msgstr[2] "%d záznamů na černé listině" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funkce" +msgstr[1] "%d funkce" +msgstr[2] "%d funkcí" + +msgid "Print all elements" +msgstr "Vypsat všechny elementy" + +msgid "Print list of blacklisted files" +msgstr "Vypsat seznam souborů na černé listině" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Vypsat strojem zpracovatelný seznam funkcí, které poskytuje zadaný nebo " +"všechny zásuvné moduly.\n" +" Užitečné spolu s externími mechanismy " +"pro automatickou instalaci zásuvných modulů" + +msgid "List the plugin contents" +msgstr "Vypsat obsah zásuvných modulů" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Seznam typů elementů (nazývaných také třídy) oddělený lomítky („/“), který " +"se má vypsat (neseřazený)" + +msgid "Check if the specified element or plugin exists" +msgstr "Zkontrolovat, zda zadaný element nebo zásuvný modul existuje" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Při kontrole existence elementu nebo zásuvného modulu rovněž zkontrolovat, " +"zda je jeho verze stejná nebo novější než zadaná" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Vypsat podporovaná schémata URI, včetně elementů, které implementují" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nelze načíst soubor se zásuvným modulem: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Element nebo zásuvný modul „%s“ neexistuje\n" + +msgid "Index statistics" +msgstr "Přehledové statistiky" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Obdržena zpráva čís. %u od elementu „%s“ (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Obdržena zpráva čís. %u od přípojky „%s:%s“ (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Obdržena zpráva čís. %u od objektu „%s“ (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Obdržena zpráva čís. %u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Obdržen konec proudu od elementu „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" +"NALEZEN ŠTÍTEK: nalezen elementem „%s“.\n" +"\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "NALEZEN ŠTÍTEK: nalezen přípojkou „%s:%s“.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "NALEZEN ŠTÍTEK: nalezen objektem „%s“.\n" + +msgid "FOUND TAG\n" +msgstr "NALEZEN ŠTÍTEK\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" +"NALEZENA TABULKA S OBSAHEM: nalezena elementem „%s“.\n" +"\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "NALEZENA TABULKA S OBSAHEM: nalezena objektem „%s“.\n" + +msgid "FOUND TOC\n" +msgstr "NALEZENA TABULKA S OBSAHEM\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACE:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "VAROVÁNÍ: od elementu %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" +"Video vložené před začátek, čeká se na dokončení ulokládání do vyrovnávací " +"paměti…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Video vložené před začátek, čeká se na dokončení průběhu…\n" + +msgid "buffering..." +msgstr "ukládá se do vyrovnávací paměti…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Ukládání do vyrovnávací paměti hotovo, nastavuje se roura na PŘEHRÁVÁ…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Ukládá se do vyrovnávací paměti, nastavuje se roura na POZASTAVENA…\n" + +msgid "Redistribute latency...\n" +msgstr "Šíří se zpoždění…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Nastavuje se stav na %s na základě požadavku od %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Přerušení: Zastavuje se roura…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Průběh: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Schází element: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Obdržen kontext od elementu „%s“: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Vypsat štítky (známé také jako metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "Vypsat tabulku s obsahem (kapitoly nebo vydání)" + +msgid "Output status information and property notifications" +msgstr "Vypsat informace o stavu a upozornění na vlastnosti" + +msgid "Do not print any progress information" +msgstr "Nevypisovat žádné informace o průběhu" + +msgid "Output messages" +msgstr "Zprávy výstupu" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Když je zapnutý podrobný výpis, nevypisovat stavové informace pro zadanou " +"vlastnost (může být uvedeno vícekrát)" + +msgid "PROPERTY-NAME" +msgstr "NÁZEV-VLASTNOSTI" + +msgid "Do not install a fault handler" +msgstr "Neinstalovat obsluhu výjimek" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Vynucuje se zakončení proudu (EOS) před vypnutím roury" + +msgid "Gather and print index statistics" +msgstr "Sesbírat a vypsat přehledové statistiky" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "CHYBA: nelze sestavit rouru: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "CHYBA: nelze sestavit rouru.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "VAROVÁNÍ: chybná roura: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "CHYBA: element „pipeline“ nebyl nalezen.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Nastavuje se rouru na POZASTAVENA…\n" + +# On strike? +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "CHYBA: Roura se nechce pozastavit.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Roura žije a nepotřebuje PŘEDVINUTÍ…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Roura se PŘEDVINUJE…\n" + +# On strike? +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "CHYBA: roura se nechce předvinout.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Roura je PŘEDVINUTA…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Nastavuje se roura na PŘEHRÁVÁNÍ…\n" + +# On strike? +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "CHYBA: roura nechce přehrávat.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Zakončení proudu (EOS) při vypnutí povoleno -- Vynucuje se zakončení proudu " +"v rouře\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" +"Zakončení proudu (EOS) při vypnutí povoleno -- Čeká se na značku EOS po " +"výskytu chyby\n" + +msgid "Waiting for EOS...\n" +msgstr "Čeká se na konec proudu (EOS)…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Obdržen konec proudu (EOS) – zastavuje se roura…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Přerušení při čekání na konec proudu – zastavuje se roura…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Nastala chyba při čekání na konec proudu (EOS)\n" + +msgid "Execution ended after %" +msgstr "Provádění skončilo po %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Nastavuje se roura na PŘIPRAVENA…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Nastavuje se roura na PRÁZDNÁ…\n" + +msgid "Freeing pipeline ...\n" +msgstr "Uvolňuje se roura…\n" diff --git a/po/da.gmo b/po/da.gmo new file mode 100644 index 0000000..f4e3f8d Binary files /dev/null and b/po/da.gmo differ diff --git a/po/da.po b/po/da.po new file mode 100644 index 0000000..9c0a402 --- /dev/null +++ b/po/da.po @@ -0,0 +1,1355 @@ +# translation of gstreamer to Danish +# Copyright (C) 2017 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Mogens Jaeger , 2007, 2010, 2013, 2014. +# Joe Hansen , 2015, 2016, 2017. +# +# conductor -> dirigent (https://lists.freedesktop.org/archives/gstreamer-commits/2016-February/092542.html) +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-21 13:26+0200\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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.5\n" + +msgid "Print the GStreamer version" +msgstr "Udskriv GStreamer-versionsnummer" + +msgid "Make all warnings fatal" +msgstr "Gør alle advarsler fatale" + +msgid "Print available debug categories and exit" +msgstr "Udskriv tilgængelige fejlsøgningskategorier og afslut" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Standard fejlsøgningsniveau fra 1 (kun fejl) til 9 (alt) eller 0 for ingen " +"uddata" + +msgid "LEVEL" +msgstr "NIVEAU" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Kommasepareret liste med kategori_navn:niveaupar til at indstille specifikke " +"niveauer for de individuelle kategorier. Eksempel: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTE" + +msgid "Disable colored debugging output" +msgstr "Deaktiver brug af farver ved fejlsøgnings uddata" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Ændrer farvelægningstilstand af debug-log. Mulige tilstande: til fra, " +"deaktiveret, auto, unix" + +msgid "Disable debugging" +msgstr "Deaktiver fejlsøgning" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Aktiver udførlig diagnostik ved indlæsning af moduler" + +msgid "Colon-separated paths containing plugins" +msgstr "Kolon-separerede stier der indeholder moduler" + +msgid "PATHS" +msgstr "SØGESTIER" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Kommasepareret liste af moduler der skal indlæses på forhånd ud over dem der " +"er gemt i listen med miljøvariabler GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "MODULER" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Deaktiver indfangning af segmentfejl under indlæsning af moduler" + +msgid "Disable updating the registry" +msgstr "Deaktiver opdatering af registratur" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Deaktiver forgrening af hjælpeproces under skanning af registratur" + +msgid "GStreamer Options" +msgstr "GStreamer indstillinger" + +msgid "Show GStreamer Options" +msgstr "Vis GStreamer-indstillinger" + +msgid "Unknown option" +msgstr "Ukendt indstilling" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer opdagede en generel fejl i kernebiblioteket." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer-udviklerne har endnu ikke nået at tildele denne fejl en fejlkode." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Intern GStreamer-fejl: kode ikke implementeret." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer fejl: tilstandsskift fejlede, og det mislykkedes nogle processer " +"at sende en ordentlig fejlmeddelelse med begrundelse for fejlen." + +msgid "Internal GStreamer error: pad problem." +msgstr "Intern GStreamer fejl: kontaktproblem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Intern GStreamer fejl: problem med tråd." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer fejl: forhandlingsproblem." + +msgid "Internal GStreamer error: event problem." +msgstr "Intern GStreamer fejl: hændelsesproblem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Intern GStreamer fejl: søgeproblem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Intern GStreamer fejl: kapabilitetsproblem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Intern GStreamer fejl: mærkatproblem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Din GStreamer-installation mangler et modul." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer fejl: tidsproblem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Denne tilføjelse prøver at bruge GStreamer-funktionalitet, der er blevet " +"fravalgt." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer opdagede en fejl i det generelle hjælpebibliotek." + +msgid "Could not initialize supporting library." +msgstr "Kunne ikke initiere hjælpebiblioteket." + +msgid "Could not close supporting library." +msgstr "Kunne ikke lukke hjælpebiblioteket." + +msgid "Could not configure supporting library." +msgstr "Kunne ikke konfigurere hjælpebiblioteket." + +msgid "Encoding error." +msgstr "Kodningsfejl." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer opdagede en generel ressourcefejl." + +msgid "Resource not found." +msgstr "Ressource ikke fundet." + +msgid "Resource busy or not available." +msgstr "Ressource optaget eller ikke til rådighed." + +msgid "Could not open resource for reading." +msgstr "Kunne ikke åbne ressource for læsning." + +msgid "Could not open resource for writing." +msgstr "Kunne ikke åbne ressource for skrivning." + +msgid "Could not open resource for reading and writing." +msgstr "Kunne ikke åbne ressource for læsning og skrivning." + +msgid "Could not close resource." +msgstr "Kunne ikke lukke ressource." + +msgid "Could not read from resource." +msgstr "Kunne ikke læse fra ressource." + +msgid "Could not write to resource." +msgstr "Kunne ikke skrive til ressource." + +msgid "Could not perform seek on resource." +msgstr "Kunne ikke udføre søgning på ressource." + +msgid "Could not synchronize on resource." +msgstr "Kunne ikke synkronisere på ressource." + +msgid "Could not get/set settings from/on resource." +msgstr "Kunne ikke hente/sætte indstillinger fra/på ressource." + +msgid "No space left on the resource." +msgstr "Der er ikke mere ledig plads på ressourcen." + +msgid "Not authorized to access resource." +msgstr "Ikke autoriseret til at tilgå ressourcen." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer opdagede en generel fejl i mediestrømmen." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementet har ikke implementeret håndtering af denne mediestrøm. Send en " +"fejlrapport." + +msgid "Could not determine type of stream." +msgstr "Kunne ikke bestemme mediestrømtype." + +msgid "The stream is of a different type than handled by this element." +msgstr "Mediestrømmen er en anden type end den, dette element kan håndtere." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Der er ikke noget kodeformat tilstede, der kan håndtere en mediestrøm af " +"denne type." + +msgid "Could not decode stream." +msgstr "Kunne ikke afkode mediestrømmen." + +msgid "Could not encode stream." +msgstr "Kunne ikke indkode mediestrømmen." + +msgid "Could not demultiplex stream." +msgstr "Kunne ikke afmultiplekse mediestrømmen." + +msgid "Could not multiplex stream." +msgstr "Kunne ikke multiplekse mediestrømmen." + +msgid "The stream is in the wrong format." +msgstr "Mediestrømmen er i et forkert format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Mediestrømmen er kodet og afkodning er ikke understøttet." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Mediestrømmen er kodet og kan ikke afkodes fordi der ikke er givet en " +"passende nøgle." + +#, c-format +msgid "No error message for domain %s." +msgstr "Ingen fejlmeddelelse for domæne %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Ingen standard fejlmeddelelse for domæne %s og kode %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Valgt tid kan ikke bruges i rørledningen." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Kunne ikke skrive registraturcache til %s: %s" + +msgid "title" +msgstr "titel" + +msgid "commonly used title" +msgstr "almindeligt brugt titel" + +msgid "title sortname" +msgstr "sorteringsstreng for titel" + +msgid "commonly used title for sorting purposes" +msgstr "almindeligt brugt titel til sorteringsbrug" + +msgid "artist" +msgstr "kunstner" + +msgid "person(s) responsible for the recording" +msgstr "personer ansvarlige for optagelsen" + +msgid "artist sortname" +msgstr "sorteringsstreng for kunstner" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "person, der er ansvarlig for optagelsen, til sorteringsbrug" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album der indeholder disse data" + +msgid "album sortname" +msgstr "sorteringsstreng for album" + +msgid "album containing this data for sorting purposes" +msgstr "album der indeholder disse data, til sorteringsbrug" + +msgid "album artist" +msgstr "albumkunstner" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Kunstneren for hele albummet, som det skal vises" + +msgid "album artist sortname" +msgstr "sorteringsstreng for albumkunstner" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Kunstneren for hele albummet, til sorteringsbrug" + +msgid "date" +msgstr "dato" + +msgid "date the data was created (as a GDate structure)" +msgstr "dato for oprettelse af data (som i en Gregoriansk datostruktur)" + +msgid "datetime" +msgstr "dato og tid" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "dato og tid for oprettelse af data (som en GstDate Time-struktur)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre disse data tilhører" + +msgid "comment" +msgstr "kommentar" + +msgid "free text commenting the data" +msgstr "fri kommentartekst til dataene" + +msgid "extended comment" +msgstr "udvidet kommentar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"fri kommentartekst til dataene i taste=værdi eller taste[en]=kommentar form" + +msgid "track number" +msgstr "spornummer" + +msgid "track number inside a collection" +msgstr "spornummer inden for en samling" + +msgid "track count" +msgstr "sportælling" + +msgid "count of tracks inside collection this track belongs to" +msgstr "tælling af spor inden for den samling dette spor tilhører" + +msgid "disc number" +msgstr "skivenummer" + +msgid "disc number inside a collection" +msgstr "skivenummer inden for en samling" + +msgid "disc count" +msgstr "skivetælling" + +msgid "count of discs inside collection this disc belongs to" +msgstr "tælling af skiver indenfor den samling denne skive tilhører" + +msgid "location" +msgstr "sted" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Mediets oprindelse som en URI (adressen, hvor den originale fil eller strøm " +"er)" + +msgid "homepage" +msgstr "hjemmeside" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Mediets hjemmeside (dvs. hjemmeside for kunstner eller film)" + +msgid "description" +msgstr "beskrivelse" + +msgid "short text describing the content of the data" +msgstr "kort tekst der beskriver indholdet i dataene" + +msgid "version" +msgstr "version" + +msgid "version of this data" +msgstr "version af disse data" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - se http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisation" + +msgid "copyright" +msgstr "ophavsret" + +msgid "copyright notice of the data" +msgstr "ophavsretsnotits for dataene" + +msgid "copyright uri" +msgstr "URI med ophavsret" + +msgid "URI to the copyright notice of the data" +msgstr "URI til ophavsretsnotits for dataene" + +msgid "encoded by" +msgstr "indkodet af" + +msgid "name of the encoding person or organization" +msgstr "navn på indkodende person eller organisation" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "kontaktinformation" + +msgid "license" +msgstr "licens" + +msgid "license of data" +msgstr "licens for data" + +msgid "license uri" +msgstr "URI med licens" + +msgid "URI to the license of the data" +msgstr "URI til licens for data" + +msgid "performer" +msgstr "optrædende" + +msgid "person(s) performing" +msgstr "personer der optræder" + +msgid "composer" +msgstr "komponist" + +msgid "person(s) who composed the recording" +msgstr "person(er) der komponerede optagelsen" + +msgid "conductor" +msgstr "dirigent" + +# Jeg tror "refinement" refererer til at de skelner bedre mellem hvem +# der dirigerer og opfører. F.eks. står der oftest navne på dirigent +# samt solister i koncerter, og/eller de vigtigste sangere (opera osv.) +# Måske man kan erstatte det med -angivelse eller noget andet indirekte. Ideer? +msgid "conductor/performer refinement" +msgstr "dirigent/opfører-angivelse" + +msgid "duration" +msgstr "varighed" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "længde i GStreamer-tidsenheder (nanosekunder)" + +msgid "codec" +msgstr "kodeformat" + +msgid "codec the data is stored in" +msgstr "det kodeformat dataene er gemt i" + +msgid "video codec" +msgstr "kodningsformat for billeder" + +msgid "codec the video data is stored in" +msgstr "det kodeformat videodataene er gemt i" + +msgid "audio codec" +msgstr "kodningsformat for lyd" + +msgid "codec the audio data is stored in" +msgstr "det lydkodeformat dataene er gemt i" + +msgid "subtitle codec" +msgstr "kodningsformat for undertekster" + +msgid "codec the subtitle data is stored in" +msgstr "det kodeformat, underteksterne er gemt i" + +msgid "container format" +msgstr "beholderformat" + +msgid "container format the data is stored in" +msgstr "det beholderformat dataene er gemt i" + +msgid "bitrate" +msgstr "bithastighed" + +msgid "exact or average bitrate in bits/s" +msgstr "præcis eller gennemsnitlig bithastighed i bit/sekund" + +msgid "nominal bitrate" +msgstr "faktisk bithastighed" + +msgid "nominal bitrate in bits/s" +msgstr "faktisk bithastighed i bit/sekund" + +msgid "minimum bitrate" +msgstr "minimal bithastighed" + +msgid "minimum bitrate in bits/s" +msgstr "minimal bithastighed i bit/sekund" + +msgid "maximum bitrate" +msgstr "maksimal bithastighed" + +msgid "maximum bitrate in bits/s" +msgstr "maksimal bithastighed i bit/sekund" + +msgid "encoder" +msgstr "indkoder" + +msgid "encoder used to encode this stream" +msgstr "indkoder der bruges til denne mediestrøm" + +msgid "encoder version" +msgstr "indkoder version" + +msgid "version of the encoder used to encode this stream" +msgstr "koderversion brugt til indkodning af denne mediestrøm" + +msgid "serial" +msgstr "serie" + +msgid "serial number of track" +msgstr "serienummer på spor" + +msgid "replaygain track gain" +msgstr "genspilningsforstærkning sporforstærkning" + +msgid "track gain in db" +msgstr "sporforstærkning i dB" + +msgid "replaygain track peak" +msgstr "genspilningsforstærkning spor maksimum" + +msgid "peak of the track" +msgstr "sporets maksimum" + +msgid "replaygain album gain" +msgstr "genspilningsforstærkning albumforstærkning" + +msgid "album gain in db" +msgstr "albumforstærkning i dB" + +msgid "replaygain album peak" +msgstr "genspilningsforstærkning album maksimum" + +msgid "peak of the album" +msgstr "albummets maksimum" + +msgid "replaygain reference level" +msgstr "genspilningsforstærkning referenceniveau" + +msgid "reference level of track and album gain values" +msgstr "referenceniveau for spor og albums forstærkningsværdier" + +msgid "language code" +msgstr "sprogkode" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" +"sprogkode for denne mediestrøm, i overensstemmelse med ISO-639-1 eller " +"ISO-639-2" + +msgid "language name" +msgstr "sprognavn" + +msgid "freeform name of the language this stream is in" +msgstr "friform navn på det sprog denne mediestrøm er i" + +msgid "image" +msgstr "billede" + +msgid "image related to this stream" +msgstr "billede relateret til denne mediestrøm" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "forhåndsvis billede" + +msgid "preview image related to this stream" +msgstr "forhåndsvis billede relateret til denne mediestrøm" + +msgid "attachment" +msgstr "vedhæftning" + +msgid "file attached to this stream" +msgstr "fil vedhæftet denne mediestrøm" + +msgid "beats per minute" +msgstr "slag pr. minut" + +msgid "number of beats per minute in audio" +msgstr "antal slag pr. minut ved audio" + +msgid "keywords" +msgstr "nøgleord" + +msgid "comma separated keywords describing the content" +msgstr "kommaseparerede nøgleord der beskriver indholdet" + +msgid "geo location name" +msgstr "geografisk stednavn" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"læsbar stedbeskrivelse af hvor mediet er blevet optaget eller produceret" + +msgid "geo location latitude" +msgstr "geografisk breddegrad" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"geografisk breddegrad hvor mediet er blevet optaget eller produceret, i " +"grader efter WGS84 (ækvator er nul, og sydlige breddegrader er negative)" + +msgid "geo location longitude" +msgstr "geografisk længdegrad" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"geografisk længdegrad hvor mediet er blevet optaget eller produceret, i " +"grader efter WGS84 (Greenwich/UK er nul, og vestlige længdegrader er " +"negative)" + +msgid "geo location elevation" +msgstr "geografisk højde" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"geografisk højde hvor mediet er blevet optaget eller produceret, i meter " +"efter WGS84 (gennemsnitlig vandstand er nul)" + +msgid "geo location country" +msgstr "geografisk placering land" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "land (dansk navn) hvor mediet er blevet optaget eller produceret" + +msgid "geo location city" +msgstr "geografisk by" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "by (dansk navn) hvor mediet er blevet optaget eller produceret" + +msgid "geo location sublocation" +msgstr "geografisk underinddeling" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"en stedangivelse indenfor en by hvor mediet er blevet optaget eller " +"produceret (f.eks. nabolaget)" + +msgid "geo location horizontal error" +msgstr "geografisk placering horisontalfejl" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "forventet fejl i den horisontale positionsangivelse (i meter)" + +msgid "geo location movement speed" +msgstr "geografisk bevægelseshastighed" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "bevægelseshastighed af det optagende udstyr under optagelsen i m/s" + +msgid "geo location movement direction" +msgstr "geografisk bevægelsesretning" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"angiver optageretningen for udstyret der optog mediet. Det angives med " +"kommatal, hvor 0 er geografisk nord, og kommatallet øges med urets retning" + +msgid "geo location capture direction" +msgstr "geografisk optagelsesretning" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"angiver optageretningen for udstyret der optog mediet. Det angives med " +"kommatal, hvor 0 er geografisk nord, og kommatallet øges med urets retning" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "udsendelsens navn" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Navnet på serien tv- eller podcastudsendelsen mediet stammer fra" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "sorteringsstreng for udsendelsen" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Navnet på serien tv- eller podcastudsendelsen mediet stammer fra, til " +"sorteringsbrug" + +msgid "episode number" +msgstr "episodenummer" + +msgid "The episode number in the season the media is part of" +msgstr "Episodenumme i den årgang mediet stammer fra" + +msgid "season number" +msgstr "sæsonnummer" + +msgid "The season number of the show the media is part of" +msgstr "Sæsonnummeret som udsendelsen i mediet stammer fra" + +msgid "lyrics" +msgstr "sangtekst" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Sangteksten i mediet, almindeligt brugt for sange" + +msgid "composer sortname" +msgstr "sorteringsstreng for komponist" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "person(er) der komponerede optagelsen, til sorteringsbrug" + +msgid "grouping" +msgstr "gruppering" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupperelateret medie der spænder over flere numre, som f.eks. de " +"forskellige satser i en koncert. Det har højere niveau end et spor, og " +"lavere end et album" + +msgid "user rating" +msgstr "brugervurdering" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Vurdering tildelt af en bruger. Jo højere rangering, desto bedre kan " +"brugeren lide mediet" + +msgid "device manufacturer" +msgstr "fremstiller af udstyret" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fremstiller af udstyret der er brugt til at oprette dette medie" + +msgid "device model" +msgstr "udstyrets model" + +msgid "Model of the device used to create this media" +msgstr "Model af det udstyr der er brugt til at fremstille mediet" + +msgid "application name" +msgstr "programnavn" + +msgid "Application used to create the media" +msgstr "Program brugt til at oprette mediet" + +msgid "application data" +msgstr "programdata" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Vilkårlige programdata der skal gemmes i mediet" + +msgid "image orientation" +msgstr "billedets orientering" + +msgid "How the image should be rotated or flipped before display" +msgstr "Hvordan et billede skal roteres eller vendes før visning" + +msgid "publisher" +msgstr "udgiver" + +msgid "Name of the label or publisher" +msgstr "Mærke eller udgiver navn" + +msgid "interpreted-by" +msgstr "fortolket-af" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Information om personerne bag et remix og lignende fortolkninger" + +msgid "midi-base-note" +msgstr "midi-base-node" + +msgid "Midi note number of the audio track." +msgstr "Midi-nodenummer på lydsporet." + +msgid "private-data" +msgstr "private-data" + +msgid "Private data" +msgstr "Private data" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Ingen URI fortolker fundet til %s protokollen" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI skemaet '%s' er ikke understøttet" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FEJL: fra element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Yderligere fejlsøgningsinformation:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "Henvisningen har ingen kilde [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "Henvisningen har ingen destination [kilde=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "ingen egenskab \"%s\" for element \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "kunne ikke sætte egenskab \"%s\" for element \"%s\" til \"%s\"" + +msgid "Delayed linking failed." +msgstr "Forsinket oprettelse af forbindelse mislykkedes." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "kunne ikke lænke %s til %s, %s kan ikke håndtere store bogstaver %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"kunne ikke lænke %s til %s, ingen af elementerne kan håndtere store " +"bogstaver %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "kunne ikke lænke %s til %s med store bogstaver %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "kunne ikke lænke %s til %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "intet element \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "uventet reference \"%s\" - ignorerer" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "uventet pad-reference \"%s\" - ignorerer" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kunne ikke tolke kapabiliteten \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "intet udgangselement for URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "intet kildeelement for URI \"%s\"" + +msgid "syntax error" +msgstr "syntaksfejl" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "specificeret tomt lager \"%s\", er ikke tilladt" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "intet lager \"%s\", udpakker elementer" + +msgid "empty pipeline not allowed" +msgstr "tom rørledning ikke tilladt" + +msgid "A lot of buffers are being dropped." +msgstr "En masse af bufferens indhold smides væk." + +msgid "Internal data flow problem." +msgstr "Intern datastrømsproblem." + +msgid "Internal data flow error." +msgstr "Intern datastrømsfejl." + +msgid "Internal clock error." +msgstr "Fejl i internt ur." + +# Ingen idé om hvad de mener med map her, men "behandling" eller +# muligvis kortlægge kunne også dække. Men det kan sagtens ske at +# oversætte virker også... +msgid "Failed to map buffer." +msgstr "Fejlede ved behandling af buffer." + +msgid "Filter caps" +msgstr "Filterkapabilitet" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Begræns den mulige tilladte kapabilitet (NUL betyder ALT). Sættes denne " +"egenskab gives en reference til det leverede GstCaps objekt." + +msgid "Caps Change Mode" +msgstr "Caps-ændringstilstand" + +msgid "Filter caps change behaviour" +msgstr "Filtrer caps-ændringsopførsel" + +msgid "No Temp directory specified." +msgstr "Der er ikke angivet en mappe til midlertidige filer." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Kunne ikke oprette den midlertidige fil \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Kunne ikke åbne filen \"%s\" for læsning." + +msgid "Error while writing to download file." +msgstr "Fejl under skrivning til downloadfilen." + +msgid "No file name specified for writing." +msgstr "Intet filnavn specificeret for skrivning." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Kunne ikke åbne filen \"%s\" for skrivning." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fejl ved lukning af filen \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fejl under søgning i filen \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fejl under skrivning til filen \"%s\"." + +msgid "No file name specified for reading." +msgstr "Intet filnavn specificeret for læsning." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Kunne ikke hente info til \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" er et katalog." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Filen \"%s\" er en sokkel." + +msgid "Failed after iterations as requested." +msgstr "Fejlede efter iterationer som forespurgt." + +msgid "caps" +msgstr "kapabiliteter" + +msgid "detected capabilities in stream" +msgstr "konstateret kapabilitet i mediestrøm" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "gennemtving kapabiliteter" + +# typefind - oversættes med ????? +msgid "force caps without doing a typefind" +msgstr "gennemtving kapabiliteter uden at gennemføre en typefind" + +msgid "Stream doesn't contain enough data." +msgstr "Strøm indeholder ikke nok data." + +msgid "Stream contains no data." +msgstr "Mediestrøm indeholder ingen data." + +msgid "Implemented Interfaces:\n" +msgstr "Implementerede grænseflader:\n" + +msgid "readable" +msgstr "læselig" + +msgid "writable" +msgstr "som kan skrives" + +msgid "deprecated" +msgstr "forældet" + +msgid "controllable" +msgstr "kontrollerbar" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "kan ændres i tilstandene NULL, READY, PAUSED eller PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "kan kun ændres i tilstandene NULL, READY eller PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "kan kun ændres i tilstandene NULL eller READY" + +msgid "Blacklisted files:" +msgstr "Sortlistede filer:" + +msgid "Total count: " +msgstr "Total optælling: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d sortlistet fil" +msgstr[1] "%d sortlistede filer" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugin" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d sortlistet indgang" +msgstr[1] "%d sortlistede indgange" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d egenskab" +msgstr[1] "%d egenskaber" + +msgid "Print all elements" +msgstr "Udskriv alle elementer" + +msgid "Print list of blacklisted files" +msgstr "Udskriv sortlistede filer" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Udskriv en liste over egenskaber, som det angivne udvidelsemodul eller alle " +"udvidelsesmoduler tilbyder, i et format der kan fortolkes af andre " +"programmer.\n" +" Bruges i forbindelse med automatisk " +"installation af udvidelsesmoduler." + +msgid "List the plugin contents" +msgstr "Oplist udvidelsesmodulets indhold" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"En skråstregsadskilt (»/«) liste af elementtyper (også kendt som klass) der " +"skal vises. (usorteret)" + +msgid "Check if the specified element or plugin exists" +msgstr "Kontroller om det angivne element eller plugin eksisterer" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Ved kontrol af om et element eller et plugin eksisterer, kontroller da også " +"om versionen i det mindste er den specificerede version" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Vis hvilke URI-skemaer der understøttes, sammen med de elementer, der " +"implementerer dem." + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Kunne ikke indlæse pluginfilen: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Et sådant element eller plugin findes ikke '%s'\n" + +msgid "Index statistics" +msgstr "Indeks statistikker" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Modtog beskeden #%u fra elementet \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Modtog beskeden #%u fra enheden \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Modtog beskeden #%u fra objektet \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Modtog beskeden #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Modtog medieslut fra element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "FUNDET MÆRKAT : fundet af element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "FUNDET MÆRKAT : fundet af enheden \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "FUNDET MÆRKAT : fundet af objektet \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "FUNDET MÆRKAT\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "FUNDET TOC : fundet af element \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "FUNDET TOC : fundet af objektet \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "FUNDET TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ADVARSEL: fra element %s: %s\n" + +# Ingen anelse +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Prerolled, venter på at bufferingen slutter...\n" + +# Ingen anelse +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Prerolled, venter på at fremdrift afslutter...\n" + +msgid "buffering..." +msgstr "indlæser i buffer..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Buffering færdig, sætter rørledning til PLAYING ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Indlæser i buffer, sætter rørledning til PAUSED ...\n" + +msgid "Redistribute latency...\n" +msgstr "Omlægger ventetid...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Sætter tilstand til %s som krævet af %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Afbrydelse: Stopper rørledning...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Fremdrift: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Manglende element: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Fik kontekst fra element '%s': %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Uddatamærkater (også kendt som metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "Uddata TOC (kapitler og versioner)" + +msgid "Output status information and property notifications" +msgstr "Uddata statusinformation og egenskabsmeddelelser" + +msgid "Do not print any progress information" +msgstr "Udskriv ikke information om fremskridt" + +msgid "Output messages" +msgstr "Uddatameddelelser" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Vis ikke statusinformation for den specificerede egenskab hvis uddybende " +"uddata er aktiveret (kan bruges flere gange)" + +msgid "PROPERTY-NAME" +msgstr "EGENSKABSNAVN" + +msgid "Do not install a fault handler" +msgstr "Installer ikke en fejlhåndterer" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Gennemtving medieslut på kilder før nedlukning af rørledning" + +msgid "Gather and print index statistics" +msgstr "Saml og udskriv indeks statistikker" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FEJL: rørledningen kunne ikke dannes: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FEJL: rørledningen kunne ikke dannes.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ADVARSEL: forkert rørledning: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FEJL: elementet 'rørledning' blev ikke fundet.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "PAUSERER rørledning ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FEJL: rørledning ønsker ikke at pausere.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Rørledningen kører, og behøver ikke at blive PREROLL'ed ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Rørledningen PREROLL'er ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FEJL: rørledning ønsker ikke at preroll.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Rørledningen er PREROLL'ed ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Rørledning sættes til AFSPIL ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FEJL: rørledning ønsker ikke at spille.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Medieslut ved nedlukning aktiveret -- Gennemtving medieslut på rørledningen\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS ved nedlukning aktiveret -- venter på EOS efter Fejl\n" + +msgid "Waiting for EOS...\n" +msgstr "Venter på medieslut...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Medieslut modtaget - stopper rørledning...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Afbrydelse afventende EOS - stopper rørledning...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Der opstod en fejl mens der ventedes på medieslut\n" + +msgid "Execution ended after %" +msgstr "Udførsel afsluttet efter %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Rørledning sættes til KLAR ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Rørledning sættes til NUL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Rørledning frigøres ...\n" + +#~ msgid "bin" +#~ msgstr "lager" + +#~ msgid "Internal data stream error." +#~ msgstr "Intern datastrømsfejl." diff --git a/po/de.gmo b/po/de.gmo new file mode 100644 index 0000000..3ea5e19 Binary files /dev/null and b/po/de.gmo differ diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..a3dd8f5 --- /dev/null +++ b/po/de.po @@ -0,0 +1,1505 @@ +# German translation for gstreamer 1.7.90 +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# +# Roland Illig , 2004. +# Christian Kirbach , 2009, 2010, 2011, 2012, 2013, 2015, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-25 16:25+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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +msgid "Print the GStreamer version" +msgstr "Die Version von GStreamer ausgeben" + +msgid "Make all warnings fatal" +msgstr "Alle Warnungen wie Fehler behandeln" + +msgid "Print available debug categories and exit" +msgstr "Verfügbare Fehlerdiagnosekategorien ausgeben und Programm beenden" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Vorgegebene Fehlerdiagnosestufe von 1 (nur Fehler) bis 9 (Alles) oder 0 für " +"keine Ausgabe" + +msgid "LEVEL" +msgstr "STUFE" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Durch Kommata getrennte Liste von Paaren »Kategorie_Name:Level«, um " +"bestimmten Kategorien eigene Stufen zuzuordnen. Beispiel: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTE" + +msgid "Disable colored debugging output" +msgstr "Farbige Fehlerdiagnoseausgabe deaktivieren" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Den Farbmodus des Fehlerdiagnose-Protokolls ändern. Mögliche Modi: off " +"(aus), on (an), disable (deaktiviert), auto und unix" + +msgid "Disable debugging" +msgstr "Fehlerdiagnose deaktivieren" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Ausführliche Meldungen beim Laden von Plugins aktivieren" + +msgid "Colon-separated paths containing plugins" +msgstr "Durch Doppelpunkte getrennte Pfade zu den Plugins" + +msgid "PATHS" +msgstr "PFADE" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Durch Kommata getrennte Liste von Plugins, die zusätzlich zu den Plugins in " +"der Umgebungsvariable GST_PLUGIN_PATH geladen werden" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Verfolgen von Speicherzugriffsfehlern beim Laden von Plugins deaktivieren" + +msgid "Disable updating the registry" +msgstr "Aktualisieren der Registry deaktivieren" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Die Erstellung eines Hilfsprozesses beim Einlesen der Registry deaktivieren" + +msgid "GStreamer Options" +msgstr "Optionen von GStreamer" + +msgid "Show GStreamer Options" +msgstr "Die Optionen von GStreamer anzeigen" + +msgid "Unknown option" +msgstr "Unbekannte Option" + +msgid "GStreamer encountered a general core library error." +msgstr "" +"GStreamer hat einen allgemeinen Fehler in einer Kernbibliothek festgestellt." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Die Entwickler von GStreamer waren zu faul, diesem Fehler eine Nummer zu " +"geben." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Interner GStreamer-Fehler: Code nicht implementiert." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer-Fehler: Zustandswechsel schlug fehl und einige Elemente gaben " +"keine richtige Fehlernachricht mit einer Ursachenbegründung." + +msgid "Internal GStreamer error: pad problem." +msgstr "Interner GStreamer-Fehler: Padding-Problem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Interner GStreamer-Fehler: Thread-Problem." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer-Fehler: Verhandlungsproblem." + +msgid "Internal GStreamer error: event problem." +msgstr "Interner GStreamer-Fehler: Ereignisproblem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Interner GStreamer-Fehler: Suchlauf-Problem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Interner GStreamer-Fehler: Fähigkeitsproblem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Interner GStreamer-Fehler: Kennzeichnungsproblem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Ihrer Installation von GStreamer fehlt ein Plugin." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer-Fehler: Zeitproblem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Diese Anwendung versucht Funktionalität von GStreamer zu verwenden, die " +"deaktiviert worden ist." + +msgid "GStreamer encountered a general supporting library error." +msgstr "" +"Internet GStreamer-Fehler: Problem mit der Unterstützungsbibliothek. Bitte " +"schicken Sie einen Fehlerbericht." + +msgid "Could not initialize supporting library." +msgstr "Die Unterstützungsbibliothek konnte nicht initialisiert werden." + +msgid "Could not close supporting library." +msgstr "Die Unterstützungsbibliothek konnte nicht geschlossen werden." + +msgid "Could not configure supporting library." +msgstr "Die Unterstützungsbibliothek konnte nicht konfiguriert werden." + +msgid "Encoding error." +msgstr "Fehler bei der Kodierung." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer hat einen allgemeinen Ressourcenfehler festgestellt." + +msgid "Resource not found." +msgstr "Ressource nicht gefunden." + +msgid "Resource busy or not available." +msgstr "Ressource in Benutzung oder nicht verfügbar." + +msgid "Could not open resource for reading." +msgstr "Die Ressource konnte nicht zum Lesen geöffnet werden." + +msgid "Could not open resource for writing." +msgstr "Die Ressource konnte nicht zum Schreiben geöffnet werden." + +msgid "Could not open resource for reading and writing." +msgstr "Die Ressource konnte nicht zum Lesen und Schreiben geöffnet werden." + +msgid "Could not close resource." +msgstr "Die Ressource konnte nicht geschlossen werden." + +msgid "Could not read from resource." +msgstr "Aus der Ressource konnte nicht gelesen werden." + +msgid "Could not write to resource." +msgstr "In die Ressource konnte nicht geschrieben werden." + +msgid "Could not perform seek on resource." +msgstr "In der Ressource konnte kein Suchlauf ausgeführt werden." + +msgid "Could not synchronize on resource." +msgstr "Die Ressource konnte nicht abgeglichen werden." + +msgid "Could not get/set settings from/on resource." +msgstr "" +"Die Einstellungen konnten nicht aus der Ressource gelesen oder in die " +"Ressource geschrieben werden." + +msgid "No space left on the resource." +msgstr "Kein Platz in der Ressource übrig." + +msgid "Not authorized to access resource." +msgstr "Keine Berechtigung zum Zugriff auf die Ressource." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer hat einen allgemeinen Datenstromfehler festgestellt." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Das Element kann diesen Datenstrom nicht verarbeiten. Bitte schicken Sie " +"einen Fehlerbericht." + +msgid "Could not determine type of stream." +msgstr "Die Art des Datenstroms konnte nicht ermittelt werden." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Der Datenstrom ist von einer anderen Art als der von diesem Element " +"verarbeitete." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Es ist kein Codec verfügbar, der diese Art von Datenströmen verarbeiten kann." + +msgid "Could not decode stream." +msgstr "Der Datenstrom konnte nicht dekodiert werden." + +msgid "Could not encode stream." +msgstr "Der Datenstrom konnte nicht kodiert werden." + +msgid "Could not demultiplex stream." +msgstr "Der Datenstrom konnte nicht demultiplext werden." + +msgid "Could not multiplex stream." +msgstr "Der Datenstrom konnte nicht multiplext werden." + +msgid "The stream is in the wrong format." +msgstr "Der Datenstrom hat das falsche Format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" +"Der Datenstrom ist verschlüsselt, aber Entschlüsselung wird nicht " +"unterstützt." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Der Datenstrom ist verschlüsselt, kann aber nicht entschlüsselt werden, weil " +"kein passender Schlüssel vorhanden ist." + +#, c-format +msgid "No error message for domain %s." +msgstr "Keine Fehlermeldung für den Bereich %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Keine Standardfehlermeldung für den Bereich %s und Fehlercode %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" +"Der ausgewählte Referenztakt kann nicht in der Pipeline verwendet werden." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Fehler beim Schreiben des Zwischenspeichers der Registry nach %s: %s" + +msgid "title" +msgstr "Titel" + +msgid "commonly used title" +msgstr "Üblicher Titel" + +msgid "title sortname" +msgstr "Sortiername des Titels" + +msgid "commonly used title for sorting purposes" +msgstr "Üblicher Titel zu Sortierzwecken" + +msgid "artist" +msgstr "Künstler" + +msgid "person(s) responsible for the recording" +msgstr "Für die Aufnahme verantwortliche Person(en)" + +msgid "artist sortname" +msgstr "Sortiername des Künstlers" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "Für die Aufnahme verantwortliche Person(en) zu Sortierzwecken" + +msgid "album" +msgstr "Album" + +msgid "album containing this data" +msgstr "Album, das diese Daten enthält" + +msgid "album sortname" +msgstr "Sortiername des Albums" + +msgid "album containing this data for sorting purposes" +msgstr "Album, das diese Daten enthält, zu Sortierzwecken" + +msgid "album artist" +msgstr "Künstler des Albums" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Der Künstler des gesamten Albums, so wie er angezeigt werden soll" + +msgid "album artist sortname" +msgstr "Sortiername des Albenkünstlers" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Der Künstler des gesamten Albums, so wie er einsortiert werden soll" + +msgid "date" +msgstr "Datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "Datum, an dem die Daten erzeugt wurden (als GDate-Struktur)" + +msgid "datetime" +msgstr "DatumUhrzeit" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"Datum und Uhrzeit, an denen die Daten erzeugt wurden (als GstDateTime-" +"Struktur)" + +msgid "genre" +msgstr "Genre" + +msgid "genre this data belongs to" +msgstr "Genre, zu dem diese Daten gehören" + +msgid "comment" +msgstr "Kommentar" + +msgid "free text commenting the data" +msgstr "Ein freier Text, der die Daten beschreibt" + +msgid "extended comment" +msgstr "Erweiterter Kommentar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"Ein beliebiger Text, der die Daten beschreibt, in der Form »Schlüssel=Wert« " +"oder »Schlüssel[de]=Kommentar«" + +msgid "track number" +msgstr "Titelnummer" + +msgid "track number inside a collection" +msgstr "Titelnummer innerhalb der Sammlung" + +msgid "track count" +msgstr "Anzahl der Titel" + +msgid "count of tracks inside collection this track belongs to" +msgstr "Anzahl der Titel in der Sammlung, zu der dieses Stück gehört" + +msgid "disc number" +msgstr "Nummer der Platte" + +msgid "disc number inside a collection" +msgstr "Nummer der Platte innerhalb der Sammlung" + +msgid "disc count" +msgstr "Anzahl der Platten" + +msgid "count of discs inside collection this disc belongs to" +msgstr "Anzahl der Platten innerhalb der Sammlung, zu der diese Platte gehört" + +msgid "location" +msgstr "Ort" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Ursprung des Mediums als URI (Ort, wo das Original der Datei oder des " +"Datenstroms bereit steht)" + +msgid "homepage" +msgstr "Internetseite" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Internetseite dieses Mediums (z.B. Künstler oder Filmseite)" + +msgid "description" +msgstr "Beschreibung" + +msgid "short text describing the content of the data" +msgstr "Eine kurze Beschreibung des Inhalts" + +msgid "version" +msgstr "Version" + +msgid "version of this data" +msgstr "Version dieser Daten" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - siehe http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "Organisation" + +msgid "copyright" +msgstr "Copyright" + +msgid "copyright notice of the data" +msgstr "Copyrightangabe der Daten" + +msgid "copyright uri" +msgstr "Copyright-URI" + +msgid "URI to the copyright notice of the data" +msgstr "URI zu der Copyrightangabe der Daten" + +msgid "encoded by" +msgstr "codiert durch" + +msgid "name of the encoding person or organization" +msgstr "Der Name der codierenden Person oder Organisation" + +msgid "contact" +msgstr "Kontakt" + +msgid "contact information" +msgstr "Kontaktinformation" + +msgid "license" +msgstr "Lizenz" + +msgid "license of data" +msgstr "Lizenz der Daten" + +msgid "license uri" +msgstr "Lizenz-URI" + +msgid "URI to the license of the data" +msgstr "URI zur Lizenz der Daten" + +msgid "performer" +msgstr "Darsteller" + +msgid "person(s) performing" +msgstr "Die das Stück aufführende Person(en)" + +msgid "composer" +msgstr "Komponist" + +msgid "person(s) who composed the recording" +msgstr "Für die Aufnahme verantwortliche Person(en)" + +msgid "conductor" +msgstr "Dirigent" + +msgid "conductor/performer refinement" +msgstr "Detaillierung Dirigent/Darsteller" + +msgid "duration" +msgstr "Dauer" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "Länge des Stücks in GStreamer-Zeiteinheiten (Nanosekunden)" + +msgid "codec" +msgstr "Codec" + +msgid "codec the data is stored in" +msgstr "Datenformat, in dem die Daten gespeichert sind" + +msgid "video codec" +msgstr "Video-Codec" + +msgid "codec the video data is stored in" +msgstr "Datenformat, in dem die Videodaten gespeichert sind" + +msgid "audio codec" +msgstr "Audio-Codec" + +msgid "codec the audio data is stored in" +msgstr "Datenformat, in dem die Audiodaten gespeichert sind" + +msgid "subtitle codec" +msgstr "Untertitel-Codec" + +msgid "codec the subtitle data is stored in" +msgstr "Datenformat, in dem der Untertitel gespeichert sind" + +# Hier ist ein Containerformat wie AVI oder MPEG gemeint. +msgid "container format" +msgstr "Containerformat" + +msgid "container format the data is stored in" +msgstr "Containerformat, in dem die Daten gespeichert sind" + +msgid "bitrate" +msgstr "Bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "Genaue oder durchschnittliche Bitrate in Bits/Sekunde" + +msgid "nominal bitrate" +msgstr "Normale Bitrate" + +msgid "nominal bitrate in bits/s" +msgstr "Bei variabler Bitrate eine mittlere Bitrate in Bits/Sekunde" + +msgid "minimum bitrate" +msgstr "Minimale Bitrate" + +msgid "minimum bitrate in bits/s" +msgstr "Minimale Bitrate in Bits/Sekunde" + +msgid "maximum bitrate" +msgstr "Maximale Bitrate" + +msgid "maximum bitrate in bits/s" +msgstr "Maximale Bitrate in Bits/Sekunde" + +msgid "encoder" +msgstr "Codierer" + +msgid "encoder used to encode this stream" +msgstr "Codierer für diesen Datenstrom" + +msgid "encoder version" +msgstr "Version des Codierers" + +msgid "version of the encoder used to encode this stream" +msgstr "Version des Codierers für diesen Datenstrom" + +msgid "serial" +msgstr "Seriennummer" + +msgid "serial number of track" +msgstr "Seriennummer des Titels" + +# http://www.audiohq.de/index.php?showtopic=23#Referenzlautstaerke +msgid "replaygain track gain" +msgstr "Lautstärkeanpassung des Titelpegels" + +msgid "track gain in db" +msgstr "Pegelanpassung des Titels in dB" + +msgid "replaygain track peak" +msgstr "Lautstärkeanpassung des Spitzenpegels" + +msgid "peak of the track" +msgstr "Spitzenpegel des Titels" + +msgid "replaygain album gain" +msgstr "Lautstärkeanpassung des Albenpegels" + +msgid "album gain in db" +msgstr "Pegelanpassung des Albums in dB" + +msgid "replaygain album peak" +msgstr "Lautstärkeanpassung des Albenspitzenpegels" + +msgid "peak of the album" +msgstr "Spitzenpegel des Albums" + +msgid "replaygain reference level" +msgstr "Referenzpegel der Lautstärkeanpassung" + +msgid "reference level of track and album gain values" +msgstr "Referenzpegel für die Pegelanpassungen von Titel und Album" + +msgid "language code" +msgstr "Sprachcode" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "Sprachcode für diesen Strom nach ISO-639-1 oder ISO-639-2" + +msgid "language name" +msgstr "Sprachname" + +msgid "freeform name of the language this stream is in" +msgstr "Name der Sprache, in welcher der Datenstrom ist" + +msgid "image" +msgstr "Bild" + +msgid "image related to this stream" +msgstr "Bild für diesen Datenstrom" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "Vorschaubild" + +msgid "preview image related to this stream" +msgstr "Vorschaubild für diesen Datenstrom" + +msgid "attachment" +msgstr "Anhang" + +msgid "file attached to this stream" +msgstr "An diesen Datenstrom angehangene Datei" + +msgid "beats per minute" +msgstr "Schläge pro Minute" + +msgid "number of beats per minute in audio" +msgstr "Anzahl der Schläge pro Minute im Hörstück" + +msgid "keywords" +msgstr "Schlagworte" + +msgid "comma separated keywords describing the content" +msgstr "Durch Komma getrennte Schlüsselwörter, die den Inhalt beschreiben" + +msgid "geo location name" +msgstr "geologischer Ort" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"Lesbare Ortsbeschreibung, wo das Medium aufgezeichnet oder produziert wurde" + +msgid "geo location latitude" +msgstr "geografischer Breitengrad" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"geografischer Breitengrad des Ortes in Grad nach WGS84 (Null am Äquator, " +"negative Werte für die südlichen Breitengrade), an dem das Medium " +"aufgezeichnet oder produziert wurde" + +msgid "geo location longitude" +msgstr "geografischer Längengrad" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"geografischer Längengrad des Ortes in Grad nach WGS84 (Null für den " +"Hauptmeridian durch Greenwich/Großbritannien, negative Werte für die " +"westlichen Längengrade)" + +msgid "geo location elevation" +msgstr "geografische Höhe" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"geografische Höhe des Ortes in Metern nach WGS84 (Höhe Null entspricht dem " +"Meeresspiegel)" + +msgid "geo location country" +msgstr "geografisches Land" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"Das Land (englischer Name), in dem das Medium aufgezeichnet oder produziert " +"wurde" + +msgid "geo location city" +msgstr "geografische Stadt" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"Die Stadt (englischer Name), in der das Medium aufgezeichnet oder produziert " +"wurde" + +msgid "geo location sublocation" +msgstr "geografischer Ortsteil" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"ein Ort innerhalb einer Stadt, an dem das Medium aufgezeichnet oder " +"produziert wurde (z.B. der Stadtteil)" + +msgid "geo location horizontal error" +msgstr "Geografischer horizontaler Fehler" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "Erwarteter Fehler der horizontalen Positionsmessung (in Meter)" + +msgid "geo location movement speed" +msgstr "Geografische Bewegungsgeschwindigkeit" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"Bewegungsgeschwindigkeit des Aufzeichnungsgeräts während der Aufzeichnung " +"mit m/s" + +msgid "geo location movement direction" +msgstr "Geografische Bewegungsrichtung" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"Zeigt die Bewegungsrichtung des Aufzeichnungsgeräts während der Aufzeichnung " +"eines Mediums an. Die Darstellung erfolgt in Grad als Fließkommazahl. 0 " +"entspricht dem geografischen Norden und die Zahl wächst im Uhrzeigersinn" + +msgid "geo location capture direction" +msgstr "Geografische Aufzeichnungsrichtung" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"Zeigt die Richtung des Geräts während der Aufzeichnung eines Mediums an. Die " +"Darstellung erfolgt in Grad als Fließkommazahl. 0 entspricht dem " +"geografischen Norden und die Zahl wächst im Uhrzeigersinn" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "Name zeigen" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Name des TV/Podcast/der Serie, von dem das Medium stammt" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "Sortiername zeigen" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Name des TV/Podcast/der Serie, von dem das Medium stammt, zum Sortieren" + +msgid "episode number" +msgstr "Nummer der Folge" + +msgid "The episode number in the season the media is part of" +msgstr "Die Nummer der Folge in der Serie, von der das Medium ein Teil ist" + +msgid "season number" +msgstr "Nummer der Serie" + +msgid "The season number of the show the media is part of" +msgstr "Die Nummer der Serie der Sendung, von der das Medium ein Teil ist" + +msgid "lyrics" +msgstr "Liedtext" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Der Liedtext des Mediums, gewöhnlich für Lieder verwendet" + +msgid "composer sortname" +msgstr "Sortiername des Komponisten" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "Für die Aufnahme verantwortliche Person(en), für Sortierzwecke" + +msgid "grouping" +msgstr "Gruppieren" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Gruppenbezogenes Medium, das mehrere Titel umfasst, ähnlich der " +"verschiedenen Stücke eines Konzertes. Es ist eine Ebene höher als ein Titel, " +"aber niedriger als ein Album" + +msgid "user rating" +msgstr "Benutzerbewertung" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Bewertet durch einen Benutzer. Je höher die Bewertung, desto beliebter ist " +"das Medium beim Benutzer" + +msgid "device manufacturer" +msgstr "Gerätehersteller" + +msgid "Manufacturer of the device used to create this media" +msgstr "Der Hersteller des Geräts zur Erstellung dieses Mediums" + +msgid "device model" +msgstr "Gerätemodell" + +msgid "Model of the device used to create this media" +msgstr "Das Modell des Geräts zur Erstellung dieses Mediums" + +msgid "application name" +msgstr "Anwendungsname" + +msgid "Application used to create the media" +msgstr "Die zur Erstellung dieses Mediums verwendete Anwendung" + +msgid "application data" +msgstr "Anwendungsdaten" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Beliebige Anwendungsdaten zur Serialisierung in das Medium" + +msgid "image orientation" +msgstr "Bildorientierung" + +msgid "How the image should be rotated or flipped before display" +msgstr "Wie das Bild vor der Darstellung gedreht oder gespiegelt werden soll" + +msgid "publisher" +msgstr "Herausgeber" + +msgid "Name of the label or publisher" +msgstr "Name des Labels oder des Herausgebers" + +msgid "interpreted-by" +msgstr "interpreted-by" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informationen über die Personen hinter einem Remix und ähnliche " +"Interpretationen" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Midi-Notenzahl der Tonspur." + +msgid "private-data" +msgstr "Private-Daten" + +msgid "Private data" +msgstr "Private Daten" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Es wurde kein Adress-Handler für das %s-Protokoll gefunden" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Das Adressenschema »%s« wird nicht unterstützt" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FEHLER: Von Element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Zusätzliche Fehlerdiagnoseinformation:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "Verknüpfung hat keine Quelle [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "Verknüpfung hat kein Ziel [sink=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "Keine Eigenschaft »%s« im Element »%s«" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" +"Die Eigenschaft »%s« im Element »%s« konnte nicht auf »%s« gesetzt werden" + +msgid "Delayed linking failed." +msgstr "Verzögertes Verknüpfen ist fehlgeschlagen." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" +"%s konnte nicht mit %s verknüpft werden. %s kann nicht mit Großbuchstaben %s " +"umgehen" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"%s konnte nicht mit %s verknüpft werden. Keines der Elemente kann mit " +"Großbuchstaben %s umgehen" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "%s konnte nicht mit %s verknüpft werden mit den Großbuchstaben %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "%s konnte nicht mit %s verknüpft werden" + +#, c-format +msgid "no element \"%s\"" +msgstr "Kein Element »%s«" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "unerwartete Referenz »%s« - wird ignoriert" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "unerwartete pad-Referenz »%s« - wird ignoriert" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "Die Fähigkeiten von »%s« konnten nicht ausgelesen werden" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "Kein Zielelement für URI »%s«" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "Kein Quellelement für URI »%s«" + +msgid "syntax error" +msgstr "Syntaxfehler" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "Leeren Behälter »%s« angegeben -- nicht erlaubt" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "Kein Behälter »%s« - Elemente werden entpackt" + +msgid "empty pipeline not allowed" +msgstr "Leere Leitung ist nicht erlaubt" + +msgid "A lot of buffers are being dropped." +msgstr "Es werden viele Puffer verworfen." + +msgid "Internal data flow problem." +msgstr "Internes Problem im Datenfluss." + +msgid "Internal data flow error." +msgstr "Interner Fehler im Datenfluss." + +msgid "Internal clock error." +msgstr "Interner Zeitfehler" + +msgid "Failed to map buffer." +msgstr "Pufferzuweisung schlug fehl." + +msgid "Filter caps" +msgstr "Filterfähigkeiten" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Beschränkt die möglichen Filterfähigkeiten (NULL bedeutet ALLE). Setzen " +"dieser Eigenschaft referenziert ein hinzugefügtes GstCaps-Objekt." + +msgid "Caps Change Mode" +msgstr "Änderungsmodus der Fähigkeiten" + +msgid "Filter caps change behaviour" +msgstr "Änderungsmodus der Filterfähigkeiten" + +msgid "No Temp directory specified." +msgstr "Kein temporärer Ordner angegeben." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Die temporäre Datei »%s« konnte nicht angelegt werden." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Die Datei »%s« konnte nicht zum Lesen geöffnet werden." + +msgid "Error while writing to download file." +msgstr "Fehler beim Schreiben in die Download-Datei." + +msgid "No file name specified for writing." +msgstr "Kein Dateiname zum Schreiben angegeben." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Datei »%s« konnte nicht zum Schreiben geöffnet werden." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fehler beim Schließen der Datei »%s«." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fehler beim Durchsuchen der Daten »%s«." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fehler beim Schreiben der Daten »%s«." + +msgid "No file name specified for reading." +msgstr "Kein Dateiname zum Lesen angegeben." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Informationen zu »%s« konnten nicht gelesen werden." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "»%s« ist ein Ordner." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Die Datei »%s« ist ein Socket." + +msgid "Failed after iterations as requested." +msgstr "Nach dem Durchlaufen fehlgeschlagen. Wie gewünscht." + +msgid "caps" +msgstr "Fähigkeiten" + +msgid "detected capabilities in stream" +msgstr "Erkannte Fähigkeiten im Datenstrom" + +msgid "minimum" +msgstr "Minimum" + +msgid "force caps" +msgstr "Fähigkeiten erzwingen" + +msgid "force caps without doing a typefind" +msgstr "Fähigkeiten ohne Typensuche erzwingen" + +msgid "Stream doesn't contain enough data." +msgstr "Der Datenstrom enthält nicht genug Daten." + +msgid "Stream contains no data." +msgstr "Der Datenstrom enthält keine Daten." + +msgid "Implemented Interfaces:\n" +msgstr "Implementierte Schnittstellen:\n" + +msgid "readable" +msgstr "lesbar" + +msgid "writable" +msgstr "schreibbar" + +msgid "deprecated" +msgstr "veraltet" + +msgid "controllable" +msgstr "regelbar" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "änderbar in den Status NULL, BEREIT, PAUSIERT oder ABSPIELEN" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "änderbar nur in den Status NULL, BEREIT oder PAUSIERT" + +msgid "changeable only in NULL or READY state" +msgstr "änderbar nur in den Status NULL oder BEREIT" + +msgid "Blacklisted files:" +msgstr "Dateien auf der schwarzen Liste:" + +msgid "Total count: " +msgstr "Gesamtzahl: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d Datei auf der schwarzen Liste" +msgstr[1] "%d Dateien auf der schwarzen Liste" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d Plugin" +msgstr[1] "%d Plugins" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d Eintrag in der schwarzen Liste" +msgstr[1] "%d Einträge in der schwarzen Liste" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d Merkmal" +msgstr[1] "%d Merkmale" + +msgid "Print all elements" +msgstr "Alle Elemente ausgeben" + +msgid "Print list of blacklisted files" +msgstr "Dateien in der schwarzen Liste ausgeben" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Eine maschinenlesbare Liste der Merkmale, die das angegebene oder alle " +"Plugins bereit stellen.\n" +" Nützlich in Verbindung mit externen " +"Mechanismen zur automatischen Installation von Plugins" + +msgid "List the plugin contents" +msgstr "Die Inhalte des Plugins auflisten" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Eine mit Schrägstrichen »/« getrennte Liste von Elementtypen (auch bekannt " +"als »klass«), die (unsortiert) aufgelistet werden soll." + +msgid "Check if the specified element or plugin exists" +msgstr "Prüfen Sie, ob das angegebene Element oder Plugin vorhanden ist" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Kontrollieren Sie beim Prüfen, ob ein Element oder Plugin vorhanden ist, " +"ebenfalls, ob die Version mindestens der angegebenen entspricht." + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Unterstützte URI-Schemata mit den Elementen ausgeben, die sie implementieren" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Die Plugin-Datei konnte nicht geladen werden: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Kein solches Element oder Plugin »%s«\n" + +msgid "Index statistics" +msgstr "Index-Statistiken" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Nachricht #%u wurde von Element »%s« (%s) erhalten: " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Nachricht #%u wurde von Padding »%s:%s« (%s) erhalten: " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Nachricht #%u wurde von Objekt »%s« (%s) erhalten: " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Nachricht #%u (%s) wurde erhalten: " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "EOS wurde von Element »%s« erhalten.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "KENNZEICHEN GEFUNDEN: Gefunden von Element »%s«.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "KENNZEICHEN GEFUNDEN: Gefunden von Padding »%s:%s«.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "KENNZEICHEN GEFUNDEN: Gefunden von Objekt »%s«.\n" + +msgid "FOUND TAG\n" +msgstr "KENNZEICHEN GEFUNDEN\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TOC GEFUNDEN: Gefunden durch Element »%s«.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TOC GEFUNDEN: Gefunden durch Objekt »%s«.\n" + +msgid "FOUND TOC\n" +msgstr "TOC GEFUNDEN\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "WARNUNG: Von Element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Vorgelaufen, auf Ende des Zwischenspeicherns warten …\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Vorgelaufen, auf Ende des Zwischenspeicherns warten …\n" + +msgid "buffering..." +msgstr "Zwischenspeichern läuft …" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Zwischenspeichern abgeschlossen, Leitung wird auf ABSPIELEN gesetzt …\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" +"Zwischenspeichern, Leitung wird auf PAUSIERT gesetzt …\n" +"\n" + +msgid "Redistribute latency...\n" +msgstr "Verzögerung neu verteilen …\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Status wird auf %s gesetzt wie von %s gewünscht...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrupt: Leitung wird gestoppt ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Fortschritt: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Fehlendes Element »%s«\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Kontext von Element »%s« erhalten: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Kennzeichen (auch bekannt als Metadaten) ausgeben" + +msgid "Output TOC (chapters and editions)" +msgstr "TOC ausgeben (Kapitel und Editionen)" + +msgid "Output status information and property notifications" +msgstr "Zustandsinformation und Eigenschaftsmitteilungen ausgeben" + +msgid "Do not print any progress information" +msgstr "Keine Fortschrittsinformationen ausgeben" + +msgid "Output messages" +msgstr "Ausgabenachrichten" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Keine Statusinformationen für die angegebene Eigenschaft ausgeben, wenn " +"ausführliche Ausgabe eingeschaltet ist (kann mehrfach verwendet werden)" + +msgid "PROPERTY-NAME" +msgstr "EIGENSCHAFT-NAME" + +msgid "Do not install a fault handler" +msgstr "Keine Routine zum Abfangen von Fehlern installieren" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "EOS auf Quelle vor dem Beenden der Leitung erzwingen" + +msgid "Gather and print index statistics" +msgstr "Index-Statistiken sammeln und ausgeben" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FEHLER: Leitung konnte nicht konstruiert werden: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FEHLER: Leitung konnte nicht konstruiert werden.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "WARNUNG: Fehlerhafte Leitung: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FEHLER: Das Element »Leitung« wurde nicht gefunden.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Leitung wird auf PAUSIERT gesetzt ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FEHLER: Leitung möchte nicht pausiert werden.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Leitung ist aktiv und erfordert keinen VORLAUF …\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Leitung läuft vor …\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FEHLER: Leitung läuft nicht vor.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Leitung ist vorgelaufen …\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Leitung wird auf ABSPIELEN gesetzt ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FEHLER: Leitung spielt nicht ab.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"EOS bei Beenden ist eingeschaltet -- EOS wird auf die Leitung erzwungen\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS bei Beenden ist eingeschaltet -- warten auf EOS nach dem Fehler\n" + +msgid "Waiting for EOS...\n" +msgstr "Auf EOS wird gewartet …\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS erhalten - Leitung wird angehalten …\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrupt beim Warten auf EOS - Leitung wird gestoppt ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Ein Fehler ist beim Warten auf EOS aufgetreten\n" + +msgid "Execution ended after %" +msgstr "Ausführung beendet nach %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Leitung wird auf BEREIT gesetzt ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Leitung wird auf NULL gesetzt ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Leitung wird geleert ...\n" + +#~ msgid "bin" +#~ msgstr "Behälter" + +#~ msgid "Internal data stream error." +#~ msgstr "Interner Fehler im Datenstrom." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Zustandsinformation der Art ART nicht ausgeben" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "ART1,ART2,..." + +#~ msgid "link without source element" +#~ msgstr "Verknüpfung ohne Quellelement" + +#~ msgid "link without sink element" +#~ msgstr "Verknüpfung ohne Zielelement" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "Kein Element, um URI »%s« zu verbinden" + +#~ msgid "maximum" +#~ msgstr "Maximum" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Aufruf: gst-xmllaunch [ element.eigenschaft=wert ...]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "FEHLER: Auslesen der XML-Datei »%s« fehlgeschlagen.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "FEHLER: Kein Hauptleitungselement in Datei »%s«.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "WARNUNG: Zur Zeit wird nur ein Hauptelement unterstützt.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "FEHLER: Das Befehlszeilenargument »%d« konnte nicht ausgelesen werden: " +#~ "%s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "WARNUNG: Element namens »%s« nicht gefunden.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "XML-Repräsentation der Leitung in DATEI speichern und beenden" + +#~ msgid "FILE" +#~ msgstr "DATEI" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Keine Routinen für SIGUSR1 und SIGUSR2 installieren" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "" +#~ "Speicherzuordnungsverfolgung ausgeben (falls zur Kompilierzeit aktiviert)" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Fehler beim erneuten Einlesen der Registry %s : %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Fehler beim erneuten Einlesen der Registry %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Interner GStreamer-Fehler: Zustandswechsel fehlgeschlagen." + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Fehler beim Schreiben in den Dateideskriptor »%d«." + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "Der Dateideskriptor »%d« ist nicht gültig." + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Beschleunigte CPU-Befehle deaktivieren" + +#~ msgid "SCHEDULER" +#~ msgstr "SCHEDULER" + +#~ msgid "Registry to use" +#~ msgstr "Zu benutzende Registry" + +#~ msgid "REGISTRY" +#~ msgstr "REGISTRY" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "Pfadliste zum Laden von Plugins (Durch »%s« getrennt)" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Zu benutzender Scheduler (Standard: »%s«)" + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "" +#~ "Internet GStreamer-Fehler: Schedulerproblem. Bitte schicken Sie einen " +#~ "Fehlerbericht." + +#~ msgid "original location of file as a URI" +#~ msgstr "Originalort der Datei als URI" + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "" +#~ "Es gibt kein Element, das den MIME-Typ »%s« dieses Datenstroms " +#~ "verarbeiten kann." + +#~ msgid "" +#~ "could not convert \"%s\" so that it fits property \"%s\" in element \"%s\"" +#~ msgstr "" +#~ "Konnte »%s« nicht so konvertieren, dass es zur Eigenschaft »%s« im " +#~ "Element »%s« passt" + +#~ msgid "Show plugin details" +#~ msgstr "Plugindetails anzeigen" + +#~ msgid "Show scheduler details" +#~ msgstr "Schedulerdetails anzeigen" + +#~ msgid " iterations (sum %" +#~ msgstr " Iterationen (Summe %" + +#~ msgid " ns, average %" +#~ msgstr " Nanosekunden, durchschnittlich %" + +#~ msgid " ns, min %" +#~ msgstr " Nanosekunden, minimal %" + +#~ msgid " ns, max %" +#~ msgstr " Nanosekunden, maximal %" + +#~ msgid " ns).\n" +#~ msgstr " Nanosekunden.\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Anzahl, wie oft die Leitung durchlaufen wird" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Versuche trotzdem zu laufen.\n" diff --git a/po/el.gmo b/po/el.gmo new file mode 100644 index 0000000..5f060ea Binary files /dev/null and b/po/el.gmo differ diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..8e50ee3 --- /dev/null +++ b/po/el.po @@ -0,0 +1,1410 @@ +# Greek translation for gstreamer. +# Copyright (C) 2010 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Michael Kotsarinis , 2010 +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-11-29 11:14+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 "Print the GStreamer version" +msgstr "Εμφάνιση της έκδοσης του GStreamer" + +msgid "Make all warnings fatal" +msgstr "Να γίνουν όλες οι προειδοποιήσεις κρίσιμες" + +msgid "Print available debug categories and exit" +msgstr "Εμφάνιση διαθέσιμων κατηγοριών σφαλμάτων και έξοδος" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Προεπιλεγμένο επίπεδο αποσφαλμάτωσης από 1 (μόνο λάθος) έως 5 (οτιδήποτε) ή " +"0 για καθόλου αποτέλεσμα" + +msgid "LEVEL" +msgstr "LEVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Λίστα διαχωρισμένη με κόμματα των ζευγαριών όνομα κατηγορίας:επίπεδο " +"(category_name:level) για καθορισμό συγκεκριμένων επιπέδων για καθεμιά " +"κατηγορία. Παράδειγμα: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LIST" + +msgid "Disable colored debugging output" +msgstr "Απενεργοποίηση έγχρωμων αποτελεσμάτων αποσφαλμάτωσης" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Απενεργοποίηση αποσφαλμάτωσης" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Ενεργοποίηση αναλυτικών διαγνωστικών φόρτωσης πρόσθετου" + +msgid "Colon-separated paths containing plugins" +msgstr "Διαχωρισμένες με άνω-κάτω τελεία διαδρομές που περιέχουν πρόσθετα" + +msgid "PATHS" +msgstr "PATHS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Διαχωρισμένη με κόμμα λίστα προσθέτων για προφόρτωση επιπλέον της λίστας που " +"είναι αποθηκευμένη στη μεταβλητή περιβάλλοντος GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Απενεργοποίηση παγίδευσης σφαλμάτων διαχωρισμού κατά τη φόρτωση προσθέτου" + +msgid "Disable updating the registry" +msgstr "Απενεργοποίηση ενημέρωσης του μητρώου" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Απενεργοποίηση εκκίνησης βοηθητικής διεργασίας κατά τη σάρωση του μητρώου" + +msgid "GStreamer Options" +msgstr "Επιλογές του GStreamer" + +msgid "Show GStreamer Options" +msgstr "Εμφάνιση επιλογών του GStreamer" + +msgid "Unknown option" +msgstr "Άγνωστη επιλογή" + +msgid "GStreamer encountered a general core library error." +msgstr "Το GStreamer αντιμετώπισε ένα γενικό σφάλμα βασικής βιβλιοθήκης." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Οι προγραμματιστές του GStreamer τεμπέλιασαν και δεν αντιστοίχισαν κωδικό " +"σφάλματος στο σφάλμα αυτό." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Εσωτερικό σφάλμα GStreamer: ο κώδικας δεν υλοποιήθηκε." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Σφάλμα GStreamer: αποτυχία αλλαγής κατάστασης και κάποιο στοιχείο απέτυχε να " +"αναρτήσει σωστό μήνυμα σφάλματος με την αιτία της αποτυχίας." + +msgid "Internal GStreamer error: pad problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα pad." + +msgid "Internal GStreamer error: thread problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα νήματος." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα συνεννόησης." + +msgid "Internal GStreamer error: event problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα γεγονότος." + +msgid "Internal GStreamer error: seek problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα αναζήτησης." + +msgid "Internal GStreamer error: caps problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα δυνατοτήτων." + +msgid "Internal GStreamer error: tag problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα ετικέτας." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Από την εγκατάστασή σας του GStreamer λείπει ένα πρόσθετο." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Εσωτερικό σφάλμα GStreamer: πρόβλημα ρολογιού." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Αυτή η εφαρμογή προσπαθεί να χρησιμοποιήσει λειτουργία του GStreamer που " +"έχει απενεργοποιηθεί." + +msgid "GStreamer encountered a general supporting library error." +msgstr "Το GStreamer συνάντησε ένα γενικό σφάλμα βιβλιοθήκης υποστήριξης." + +msgid "Could not initialize supporting library." +msgstr "Αδυναμία αρχικοποίησης υποστηρικτικής βιβλιοθήκης." + +msgid "Could not close supporting library." +msgstr "Αδυναμία κλεισίματος υποστηρικτικής βιβλιοθήκης." + +msgid "Could not configure supporting library." +msgstr "Αδυναμία διαμόρφωσης υποστηρικτικής βιβλιοθήκης." + +msgid "Encoding error." +msgstr "Σφάλμα κωδικοποίησης." + +msgid "GStreamer encountered a general resource error." +msgstr "Το GStreamer συνάντησε ένα γενικό σφάλμα πόρων." + +msgid "Resource not found." +msgstr "Δεν βρέθηκε ο πόρος." + +msgid "Resource busy or not available." +msgstr "Ο πόρος είναι απασχολημένος ή μη διαθέσιμος." + +msgid "Could not open resource for reading." +msgstr "Αδυναμία ανοίγματος πόρου για ανάγνωση." + +msgid "Could not open resource for writing." +msgstr "Αδυναμία ανοίγματος πόρου για εγγραφή." + +msgid "Could not open resource for reading and writing." +msgstr "Αδυναμία ανοίγματος πόρου για ανάγνωση και εγγραφή." + +msgid "Could not close resource." +msgstr "Αδυναμία κλεισίματος πόρου." + +msgid "Could not read from resource." +msgstr "Αδυναμία ανάγνωσης από τον πόρο." + +msgid "Could not write to resource." +msgstr "Αδυναμία εγγραφής στον πόρο." + +msgid "Could not perform seek on resource." +msgstr "Αδυναμία εκτέλεσης αναζήτησης στον πόρο." + +msgid "Could not synchronize on resource." +msgstr "Αδυναμία συγχρονισμού με τον πόρο." + +msgid "Could not get/set settings from/on resource." +msgstr "Αδυναμία λήψης/ορισμού ρυθμίσεων από τον/στον πόρο." + +msgid "No space left on the resource." +msgstr "Δεν έχει μείνει χώρος στον πόρο." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Δεν έχει μείνει χώρος στον πόρο." + +msgid "GStreamer encountered a general stream error." +msgstr "Το GStreamer συνάντησε ένα γενικό σφάλμα ροής." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Το στοιχείο δεν υλοποιεί χειρισμό αυτή της ροής. Παρακαλούμε αναφέρετε το " +"σφάλμα." + +msgid "Could not determine type of stream." +msgstr "Αδυναμία καθορισμού του τύπου της ροής." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Η ροή είναι διαφορετικού τύπου από αυτόν που χειρίζεται αυτό το στοιχείο." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Δεν υπάρχει παρών κωδικοποιητής που να μπορεί να χειριστεί τον τύπο της ροής." + +msgid "Could not decode stream." +msgstr "Αδυναμία αποκωδικοποίησης ροής." + +msgid "Could not encode stream." +msgstr "Αδυναμία κωδικοποίησης ροής." + +msgid "Could not demultiplex stream." +msgstr "Αδυναμία από-πολύπλεξης ροής." + +msgid "Could not multiplex stream." +msgstr "Αδυναμία πολύπλεξης ροής." + +msgid "The stream is in the wrong format." +msgstr "Η ροή είναι λανθασμένης μορφής." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Η ροή είναι κρυπτογραφημένη και δεν υποστηρίζεται αποκρυπτογράφηση." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Η ροή είναι κρυπτογραφημένη και δεν μπορεί να αποκρυπτογραφηθεί επειδή δεν " +"έχει δοθεί κατάλληλος κωδικός." + +#, c-format +msgid "No error message for domain %s." +msgstr "Δεν υπάρχει μήνυμα σφάλματος για τον τομέα %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" +"Δεν υπάρχει τυποποιημένο μήνυμα σφάλματος για τον τομέα %s και τον κώδικα %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Το επιλεγμένο ρολόι δεν μπορεί να χρησιμοποιηθεί στη διασωλήνωση." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "τίτλος" + +msgid "commonly used title" +msgstr "ο τίτλος που συνήθως χρησιμοποιείται" + +msgid "title sortname" +msgstr "όνομα ταξινόμησης τίτλου" + +msgid "commonly used title for sorting purposes" +msgstr "ο συνήθης τίτλος για σκοπούς ταξινόμησης" + +msgid "artist" +msgstr "καλλιτέχνης" + +msgid "person(s) responsible for the recording" +msgstr "πρόσωπο(α) υπεύθυνο για την ηχογράφηση" + +msgid "artist sortname" +msgstr "όνομα ταξινόμησης καλλιτέχνη" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "πρόσωπο(α) υπεύθυνο για την εγγραφή για σκοπούς ταξινόμησης" + +msgid "album" +msgstr "δίσκος" + +msgid "album containing this data" +msgstr "δίσκος που περιέχει αυτά τα δεδομένα" + +msgid "album sortname" +msgstr "όνομα ταξινόμησης δίσκου" + +msgid "album containing this data for sorting purposes" +msgstr "δίσκος που περιέχει αυτά τα δεδομένα για σκοπούς ταξινόμησης" + +msgid "album artist" +msgstr "καλλιτέχνης δίσκου" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Ο καλλιτέχνης ολόκληρου του δίσκου, όπως θα πρέπει να εμφανίζεται" + +msgid "album artist sortname" +msgstr "όνομα ταξινόμησης καλλιτέχνη δίσκου" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Ο καλλιτέχνης ολόκληρου του δίσκου, όπως θα πρέπει να ταξινομείται." + +msgid "date" +msgstr "ημερομηνία" + +msgid "date the data was created (as a GDate structure)" +msgstr "ημερομηνία δημιουργίας των δεδομένων (ως μια δομή GDate)" + +msgid "datetime" +msgstr "datetime" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "ημερομηνία και ώρα δημιουρίας των δεδομένων (δομημένες ως GstDateTime)" + +msgid "genre" +msgstr "είδος" + +msgid "genre this data belongs to" +msgstr "είδος που ανήκουν αυτά τα δεδομένα" + +msgid "comment" +msgstr "σχόλιο" + +msgid "free text commenting the data" +msgstr "ελεύθερο κείμενο σχολιασμού των δεδομένων" + +msgid "extended comment" +msgstr "εκτεταμένο σχόλιο" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"ελεύθερο κείμενο σχολιασμού των δεδομένων της μορφής key=value ή " +"key[en]=comment" + +msgid "track number" +msgstr "αριθμός κομματιού" + +msgid "track number inside a collection" +msgstr "αριθμός κομματιών μέσα σε μια συλλογή" + +msgid "track count" +msgstr "καταμέτρηση κομματιών" + +msgid "count of tracks inside collection this track belongs to" +msgstr "" +"η καταμέτρηση των κομματιών μέσα στη συλλογή στην οποία ανήκει αυτό το " +"κομμάτι" + +msgid "disc number" +msgstr "αριθμός δίσκου" + +msgid "disc number inside a collection" +msgstr "αριθμός δίσκου μέσα σε μια συλλογή" + +msgid "disc count" +msgstr "καταμέτρηση δίσκων" + +msgid "count of discs inside collection this disc belongs to" +msgstr "η καταμέτρηση των δίσκων μέσα στη συλλογή που ανήκει αυτός ο δίσκος" + +msgid "location" +msgstr "τοποθεσία" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Προέλευση του μέσου ως URI (τοποθεσία, όπου φιλοξενείται το πρωτότυπο του " +"αρχείου ή της ροής)" + +msgid "homepage" +msgstr "αρχική σελίδα" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Η αρχική σελίδα για αυτό το μέσο (π.χ. η αρχική σελίδα της ταινίας ή του " +"καλλιτέχνη)" + +msgid "description" +msgstr "περιγραφή" + +msgid "short text describing the content of the data" +msgstr "σύντομο κείμενο που περιγράφει το περιεχόμενο των δεδομένων" + +msgid "version" +msgstr "έκδοση" + +msgid "version of this data" +msgstr "έκδοση αυτών των δεδομένων" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - βλέπε http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "οργανισμός" + +msgid "copyright" +msgstr "πνευματικά δικαιώματα" + +msgid "copyright notice of the data" +msgstr "σημείωμα πνευματικών δικαιωμάτων των δεδομενων" + +msgid "copyright uri" +msgstr "uri πνευματικών δικαιωμάτων" + +msgid "URI to the copyright notice of the data" +msgstr "URI για το σημείωμα πνευματικών δικαιωμάτων των δεδομένων" + +#, fuzzy +msgid "encoded by" +msgstr "κωδικοποιητής" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "επικοινωνία" + +msgid "contact information" +msgstr "πληροφορίες επικοινωνίας" + +msgid "license" +msgstr "άδεια" + +msgid "license of data" +msgstr "άδεια των δεδομένων" + +msgid "license uri" +msgstr "uri άδειας" + +msgid "URI to the license of the data" +msgstr "URI της άδειας των δεδομένων" + +msgid "performer" +msgstr "εκτελεστής" + +msgid "person(s) performing" +msgstr "πρόσωπο(α) που παίζει" + +msgid "composer" +msgstr "συνθέτης" + +msgid "person(s) who composed the recording" +msgstr "πρόσωπο(α) που συνέθεσε την ηχογράφηση." + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "διάρκεια" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "μήκος σε μονάδες χρόνου του GStreamer (nanoseconds)" + +msgid "codec" +msgstr "κωδικοποιητής" + +msgid "codec the data is stored in" +msgstr "η κωδικοποίηση αποθήκευσης των δεδομένων" + +msgid "video codec" +msgstr "κωδικοποιητής βίντεο" + +msgid "codec the video data is stored in" +msgstr "κωδικοποιητής βίντεο της αποθήκευσης των δεδομένων" + +msgid "audio codec" +msgstr "κωδικοποιητής ήχου" + +msgid "codec the audio data is stored in" +msgstr "κωδικοποιητής αποθήκευσης των ηχητικών δεδομένων" + +msgid "subtitle codec" +msgstr "κωδικοποιητής υποτίτλων" + +msgid "codec the subtitle data is stored in" +msgstr "κωδικοποιητής αποθήκευσης των υποτίτλων" + +msgid "container format" +msgstr "τύπος περιέκτη" + +msgid "container format the data is stored in" +msgstr "ο τύπος του περιέκτη στον οποίο αποθηκεύονται τα δεδομένα" + +msgid "bitrate" +msgstr "ρυθμός μετάδοσης" + +msgid "exact or average bitrate in bits/s" +msgstr "ακριβής ή μέσος ρυθμός σε bits/s" + +msgid "nominal bitrate" +msgstr "ονομαστικός ρυθμός" + +msgid "nominal bitrate in bits/s" +msgstr "ονομαστικός ρυθμός σε bits/s" + +msgid "minimum bitrate" +msgstr "ελάχιστος ρυθμός" + +msgid "minimum bitrate in bits/s" +msgstr "ελάχιστος ρυθμός σε bits/s" + +msgid "maximum bitrate" +msgstr "μέγιστος ρυθμός" + +msgid "maximum bitrate in bits/s" +msgstr "μέγιστος ρυθμός σε bits/s" + +msgid "encoder" +msgstr "κωδικοποιητής" + +msgid "encoder used to encode this stream" +msgstr "κωδικοποιητής που χρησιμοποιήθηκε για την κωδικοποίηση αυτής της ροής" + +msgid "encoder version" +msgstr "έκδοση κωδικοποιητή" + +msgid "version of the encoder used to encode this stream" +msgstr "" +"έκδοση του κωδικοποιητή που χρησιμοποιήθηκε για την κωδικοποίηση αυτής της " +"ροής" + +msgid "serial" +msgstr "σειριακός" + +msgid "serial number of track" +msgstr "σειριακός αριθμός του κομματιού" + +msgid "replaygain track gain" +msgstr "κέρδος κομματιού replaygain" + +msgid "track gain in db" +msgstr "κέρδος κομματιού σε db" + +msgid "replaygain track peak" +msgstr "κορυφή κομματιού replaygain" + +msgid "peak of the track" +msgstr "κορύφωση του κομματιού" + +msgid "replaygain album gain" +msgstr "κέρδος δίσκου replaygain" + +msgid "album gain in db" +msgstr "κέρδος δίσκου σε db" + +msgid "replaygain album peak" +msgstr "κορυφή δίσκου replaygain" + +msgid "peak of the album" +msgstr "κορύφωση του δίσκου" + +msgid "replaygain reference level" +msgstr "επίπεδο αναφοράς replaygain" + +msgid "reference level of track and album gain values" +msgstr "επίπεδο αναφοράς των τιμών κέρδους κομματιού και δίσκου" + +msgid "language code" +msgstr "κωδικός γλώσσας" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "κωδικός γλώσσας γι' αυτή τη ροή, συμμορφούμενος με το ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "κωδικός γλώσσας" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "εικόνα" + +msgid "image related to this stream" +msgstr "εικόνα που σχετίζεται με αυτή τη ροή" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "εικόνα προεπισκόπησης" + +msgid "preview image related to this stream" +msgstr "εικόνα προεπισκόπησης που σχετίζεται με αυτή τη ροή" + +msgid "attachment" +msgstr "συνημμένο" + +msgid "file attached to this stream" +msgstr "αρχείο συνημμένο σε αυτή τη ροή" + +msgid "beats per minute" +msgstr "χτύποι ανά λεπτό" + +msgid "number of beats per minute in audio" +msgstr "αριθμός των χτύπων ανά λεπτό στον ήχο" + +msgid "keywords" +msgstr "λέξεις κλειδιά" + +msgid "comma separated keywords describing the content" +msgstr "" +"λέξεις κλειδιά διαχωρισμένες με κόμματα, που περιγράφουν το περιεχόμενο" + +msgid "geo location name" +msgstr "όνομα γεωγραφικού εντοπισμού" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "ανθρώπινα κατανοητή περιγραφή τοποθεσίας εγγραφής ή παραγωγής" + +msgid "geo location latitude" +msgstr "γεωγραφικός εντοπισμός πλάτους" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"γεωγραφικό πλάτος της τοποθεσίας, όπου εγγράφηκε ή παρήχθη το μέσο, σε " +"μοίρες σύμφωνα με το WGS84 (μηδέν στον ισημερινό, αρνητικές τιμές για πλάτη " +"στο νότιο ημισφαίριο)" + +msgid "geo location longitude" +msgstr "γεωγραφικός εντοπισμός μήκους" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"γεωγραφικό μήκος της τοποθεσίας, όπου εγγράφηκε ή παρήχθη το μέσο, σε μοίρες " +"σύμφωνα με το WGS84 (μηδέν στον πρώτο μεσημβρινό στο Greenwich/UK, αρνητικές " +"τιμές για μήκη στο δυτικό ημισφαίριο)" + +msgid "geo location elevation" +msgstr "γεωγραφικός εντοπισμός υψομέτρου" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"υψόμετρο της τοποθεσίας, όπου εγγράφηκε ή παρήχθη το μέσο, σε μέτρα σύμφωνα " +"με το WGS84 (μηδέν στο επίπεδο της θάλασσας)" + +msgid "geo location country" +msgstr "γεωγραφικός εντοπισμός χώρας" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "χώρα (αγγλικό όνομα) όπου έχει εγγραφεί ή παραχθεί το μέσο" + +msgid "geo location city" +msgstr "γεωγραφικός εντοπισμός πόλης" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "πόλη (αγγλικό όνομα) όπου το μέσο εγγράφηκε ή παρήχθη" + +msgid "geo location sublocation" +msgstr "γεωγραφικός εντοπισμός υποτοποθεσίας" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"τοποθεσία μέσα σε μια πόλη όπου το μέσο παρήχθη ή δημιουργήθηκε (π.χ. η " +"γειτονιά)" + +msgid "geo location horizontal error" +msgstr "γεωγραφικός εντοπισμός οριζόντιου σφάλματος" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "αναμενόμενο σφάλμα των μετρήσεων οριζόντιας τοποθέτησης (σε μέτρα)" + +msgid "geo location movement speed" +msgstr "γεωγραφικός εντοπισμός ταχύτητας κίνησης " + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"ταχύτητα κίνησης της συσκευής σύλληψης κατά τη διάρκεια εγγραφής σε m/s" + +msgid "geo location movement direction" +msgstr "γεωγραφικός εντοπισμός διεύθυνσης κίνησης " + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"υποδεικνύει την κατεύθυνση κίνησης της συσκευής που συλλαμβάνει ένα μέσο. " +"Αναγράφεται ως μοίρες με δεκαδικά, το 0 δείχνει το γεωγραφικό βορρά και " +"αυξάνει δεξιόστροφα" + +msgid "geo location capture direction" +msgstr "γεωγραφικός εντοπισμός κατεύθυνσης σύλληψης" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"υποδεικνύει την κατεύθυνση που δείχνει η συσκευή κατά τη σύλληψη ενός μέσου. " +"Αναγράφεται σε μοίρες με δεκαδικά, το 0 υποδεικνύει το γεωγραφικό βορρά και " +"αυξάνει δεξιόστροφα" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "όνομα εκπομπής" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Όνομα της τηλεοπτικής/φορητής (podcast)/σειράς εκπομπής από την οποία είναι " +"το μέσο" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "όνομα ταξινόμησης εκπομπής" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Όνομα της τηλεοπτικής/φορητής (podcast)/σειράς εκπομπής από την οποία είναι " +"το μέσο, για σκοπούς ταξινόμησης" + +msgid "episode number" +msgstr "αριθμός επεισοδίου" + +msgid "The episode number in the season the media is part of" +msgstr "Ο αριθμός επεισοδίου του κύκλου στο οποίο ανήκει το μέσο" + +msgid "season number" +msgstr "αριθμός κύκλου" + +msgid "The season number of the show the media is part of" +msgstr "Ο αριθμός κύκλου της εκπομπής στην οποία ανήκει το μέσο" + +msgid "lyrics" +msgstr "στίχοι" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Οι στίχοι του μέσου, συνήθως χρησιμοποιείται για τραγούδια" + +msgid "composer sortname" +msgstr "όνομα ταξινόμησης συνθέτη" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "πρόσωπο(α) που συνέθεσε την ηχογράφηση, για σκοπούς ταξινόμησης" + +msgid "grouping" +msgstr "ομαδοποίηση" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Ομαδοποιεί σχετιζόμενα μέσα που καλύπτουν πολλαπλά κομμάτια, όπως τα " +"διαφορετικά μέρη ενός κονσέρτου. Είναι υψηλότερο επίπεδο από το κομμάτι αλλά " +"χαμηλότερο από το δίσκο" + +msgid "user rating" +msgstr "βαθμολογία χρήστη" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Η βαθμολογία που απονεμήθηκε από ένα χρήστη. Όσο υψηλότερη, τόσο περισσότερο " +"αρέσει στο χρήστη το μέσο" + +msgid "device manufacturer" +msgstr "κατασκευαστής συσκευής" + +msgid "Manufacturer of the device used to create this media" +msgstr "" +"Κατασκευαστής της συσκευής που χρησιμοποιήθηκε για τη δημιουργία αυτού του " +"μέσου" + +msgid "device model" +msgstr "μοντέλο συσκευής" + +msgid "Model of the device used to create this media" +msgstr "Μοντέλο της συσκευής που χρησιμοποιήθηκε για τη δημιουργία του μέσου" + +msgid "application name" +msgstr "όνομα εφαρμογής" + +msgid "Application used to create the media" +msgstr "Η εφαρμογή που χρησιμοποιήθηκε για τη δημιουργία του μέσου" + +msgid "application data" +msgstr "δεδομένα εφαρμογής" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Αυθαίρετα δεδομένα εφαρμογής να ενσωματωθούν σειριακά στο μέσο" + +msgid "image orientation" +msgstr "προσανατολισμός εικόνας" + +msgid "How the image should be rotated or flipped before display" +msgstr "" +"Πως θα πρέπει να περιστραφεί ή καθρεφτιστεί η εικόνα πριν την εμφάνισή της" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERROR: από στοιχείο %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Επιπλέον πληροφορίες αποσφαλμάτωσης:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "δεν υπάρχει ιδιότητα «%s» στο στοιχείο «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "αδυναμία ορισμού ιδιότητας «%s» στο στοιχείο «%s» σε «%s»" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "αδυναμία σύνδεσης %s σε %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "αδυναμία σύνδεσης στοιχείου προορισμού για το URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "αδυναμία σύνδεσης %s σε %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "αδυναμία σύνδεσης %s σε %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "δεν υπάρχει στοιχείο «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "αδυναμία ανάλυσης δυνατοτήτων «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "δεν υπάρχει στοιχείο προορισμού για το URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "δεν υπάρχει στοιχείο προέλευσης για το URI «%s»" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "ο καθορισμένος άδειος περιέκτης «%s», δεν επιτρέπεται" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "δεν υπάρχει περιέκτης «%s», παράβλεψη" + +msgid "empty pipeline not allowed" +msgstr "δεν επιτρέπεται κενή διασωλήνωση" + +msgid "A lot of buffers are being dropped." +msgstr "Πολλές ενδιάμεσες αποθηκεύσεις απορρίπτονται." + +msgid "Internal data flow problem." +msgstr "Εσωτερικό πρόβλημα ροής δεδομένων." + +msgid "Internal data flow error." +msgstr "Εσωτερικό σφάλμα ροής δεδομένων." + +msgid "Internal clock error." +msgstr "Σφάλμα εσωτερικού ρολογιού." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Φιλτράρισμα δυνατοτήτων" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Περιορισμός των πιθανών επιτρεπόμενων δυνατοτήτων (NULL σημαίνει ANY). Η " +"ρύθμιση αυτής της ιδιότητας απαιτεί μια αναφορά στο παρεχόμενο αντικείμενο " +"GstCaps." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Δεν ορίσθηκε προσωρινός κατάλογος (Temp)." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Αδυναμία δημιουργίας προσωρινού αρχείου (temp) «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Αδυναμία ανοίγματος αρχείου «%s» για ανάγνωση." + +msgid "Error while writing to download file." +msgstr "Σφάλμα κατά την εγγραφή στο αρχείο μεταφόρτωσης." + +msgid "No file name specified for writing." +msgstr "Δεν έχει καθορισθεί όνομα αρχείου για εγγραφή." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Αδυναμία ανοίγματος αρχείου «%s» για εγγραφή." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Σφάλμα κλεισίματος αρχείου «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Σφάλμα κατά την αναζήτηση στο αρχείο «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Σφάλμα κατά την εγγραφή στο αρχείο «%s»." + +msgid "No file name specified for reading." +msgstr "Δεν καθορίσθηκε όνομα αρχείου για ανάγνωση." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Αδυναμία λήψης πληροφοριών για «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "Το «%s» είναι κατάλογος." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Το αρχείο «%s» είναι μια υποδοχή." + +msgid "Failed after iterations as requested." +msgstr "Αποτυχία κατόπιν επαναλήψεων ως ζητήθηκε." + +msgid "caps" +msgstr "δυνατότητες" + +msgid "detected capabilities in stream" +msgstr "ανιχνεύθηκαν δυνατότητες στη ροή" + +msgid "minimum" +msgstr "ελάχιστο" + +msgid "force caps" +msgstr "επιβολή δυνατοτήτων" + +msgid "force caps without doing a typefind" +msgstr "επιβολή δυνατοτήτων χωρίς εκτέλεση typefind" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Η ροή δεν περιέχει δεδομένα." + +msgid "Stream contains no data." +msgstr "Η ροή δεν περιέχει δεδομένα." + +msgid "Implemented Interfaces:\n" +msgstr "Υλοποιημένες διεπαφές:\n" + +msgid "readable" +msgstr "αναγνώσιμο" + +msgid "writable" +msgstr "εγγράψιμο" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "ελεγχόμενο" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "μπορεί να αλλάξει σε κατάσταση NULL, READY, PAUSED ή PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "μπορεί να αλλάξει μόνο σε κατάσταση NULL, READY ή PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "μπορεί να αλλάξει μόνο σε κατάσταση NULL ή READY" + +msgid "Blacklisted files:" +msgstr "Αρχεία στη μαύρη λίστα:" + +msgid "Total count: " +msgstr "Συνολική καταμέτρηση:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d αρχείο στη μαύρη λίστα" +msgstr[1] "%d αρχεία στη μαύρη λίστα" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d πρόσθετο" +msgstr[1] "%d πρόσθετα" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d καταχώρηση στη μαύρη λίστα" +msgstr[1] "%d καταχωρήσεις στη μαύρη λίστα" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d χαρακτηριστικό" +msgstr[1] "%d χαρακτηριστικά" + +msgid "Print all elements" +msgstr "Εμφάνιση όλων των στοιχείων" + +msgid "Print list of blacklisted files" +msgstr "Εμφάνιση λίστας των αρχείων στη μαύρη λίστα" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Εμφάνιση μιας λίστας που μπορεί να αναλυθεί από υπολογιστή με τα " +"χαρακτηριστικά που παρέχει το επιλεγμένο πρόσθετο ή όλα τα πρόσθετα.\n" +" Χρήσιμο σε συνδυασμό με εξωτερικούς " +"μηχανισμούς αυτόματης εγκατάστασης προσθέτων" + +msgid "List the plugin contents" +msgstr "Απαρίθμηση των περιεχομένων του προσθέτου" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Εμφάνιση υποστηριζόμενων μορφών URI, με τα στοιχεία που τις υλοποιούν" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Αδυναμία φόρτωσης αρχείου προσθέτου: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Δεν υπάρχει τέτοιο στοιχείο ή πρόσθετο '%s'\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Ελήφθη το μήνυμα #%u από το στοιχείο «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Ελήφθη το μήνυμα #%u από το pad «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Ελήφθη το μήνυμα #%u από το αντικείμενο «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Ελήφθη το μήνυμα #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Ελήφθη EOS από το στοιχείο «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "FOUND TAG : εύρεση κατά στοιχείο «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "FOUND TAG : εύρεση κατά pad «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "FOUND TAG : εύρεση κατά αντικείμενο «%s».\n" + +msgid "FOUND TAG\n" +msgstr "FOUND TAG\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "FOUND TAG : εύρεση κατά στοιχείο «%s».\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "FOUND TAG : εύρεση κατά αντικείμενο «%s».\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "FOUND TAG\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "WARNING: από το στοιχείο %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Προτυλιγμένο, αναμονή για ολοκλήρωση η αποθήκευση ροής…\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Προτυλιγμένο, αναμονή για ολοκλήρωση η αποθήκευση ροής…\n" + +msgid "buffering..." +msgstr "προσωρινή αποθήκευση…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Αποθήκευση ολοκληρώθηκε, ορισμός διασωλήνωσης σε PLAYING …\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Αποθήκευση, ορισμός διασωλήνωσης σε PAUSED …\n" + +msgid "Redistribute latency...\n" +msgstr "Καθυστέρηση αναδιανομής…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Ορισμός κατάστασης σε %s όπως ζητήθηκε από %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Διακοπή: Τερματισμός διασωλήνωσης…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "δεν υπάρχει στοιχείο «%s»" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "WARNING: από το στοιχείο %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Ετικέτες εξόδου (επίσης γνωστές ως μεταδεδομένα)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Πληροφορίες κατάστασης εξόδου και ειδοποιήσεις ιδιοτήτων" + +msgid "Do not print any progress information" +msgstr "Να μην εμφανισθεί καμμία πληροφορία προόδου" + +msgid "Output messages" +msgstr "Μηνύματα εξόδου" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Να μην εγκατασταθεί χειριστής σφαλμάτων" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Εξαναγκασμός του EOS στις πηγές πριν το κλείσιμο της διασωλήνωσης" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERROR: αδυναμία κατασκευής διασωλήνωσης: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERROR: αδυναμία κατασκευής διασωλήνωσης.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "WARNING: εσφαλμένη διασωλήνωση: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERROR: το στοιχείο 'διασωλήνωση' δεν βρέθηκε.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Ορισμός διασωλήνωσης σε PAUSED …\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROR: Η διασωλήνωση δεν θέλει να παύσει.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Η διασωλήνωση είναι ενεργή και δεν χρειάζεται PREROLL … \n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Η διασωλήνωση είναι σε PREROLLING …\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERROR: η διασωλήνωση δεν θέλει να προτυλιχθεί.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Η διασωλήνωση είναι PREROLLED …\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Ορισμός διασωλήνωσης σε PLAYING …\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERROR: η διασωλήνωση δεν θέλει να αναπαραχθεί.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Ενεργοποίηση του EOS κατά τον τερματισμό -- Επιβολή του EOS στη διασωλήνωση\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" +"Ενεργοποίηση του EOS κατά τον τερματισμό -- Επιβολή του EOS στη διασωλήνωση\n" + +msgid "Waiting for EOS...\n" +msgstr "Αναμονή για EOS…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Λήψη EOS - διακοπή διασωλήνωσης…\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Διακοπή: Τερματισμός διασωλήνωσης…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Προέκυψε σφάλμα κατά την αναμονή για EOS\n" + +msgid "Execution ended after %" +msgstr "Η εκτέλεση τελείωσε μετά %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Ορισμός διασωλήνωσης σε READY …\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Ορισμός διασωλήνωσης σε NULL …\n" + +msgid "Freeing pipeline ...\n" +msgstr "Αποδέσμευση της διασωλήνωσης …\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Εσωτερικό σφάλμα ροής δεδομένων." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Να μην εξάγεται πληροφορία κατάστασης εξόδου του TYPE" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYPE1,TYPE2,…" + +#~ msgid "link without source element" +#~ msgstr "σύνδεση χωρίς στοιχείο προέλευσης" + +#~ msgid "link without sink element" +#~ msgstr "σύνδεση χωρίς στοιχείο προορισμού" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "δεν υπάρχει στοιχείο για τη σύνδεση του URI «%s» σε" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "" +#~ "Εμφάνιση ίχνους αντιστοίχισης (αν είναι ενεργοποιημένο κατά τη " +#~ "μεταγλώττιση κώδικα)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Χρήση: gst-xmllaunch [ element.property=value ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROR: αποτυχία ανάλυσης αρχείου xml '%s'.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERROR: δεν υπάρχει στοιχείο διασωλήνωσης στο ανώτερο επίπεδο στο αρχείο " +#~ "'%s'.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "WARNING: μόνο ένα στοιχείο σε ανώτερο επίπεδο υποστηρίζεται αυτή τη " +#~ "στιγμή.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "ERROR: αδυναμία ανάλυσης ορίσματος γραμμής εντολής %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "WARNING: το στοιχείο με το όνομα '%s' δεν βρέθηκε.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Αποθήκευση xml αναπαράστασης της διασωλήνωσης στο FILE και έξοδος" + +#~ msgid "FILE" +#~ msgstr "FILE" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Να μην εγκατασταθούν χειριστές σημάτων για SIGUSR1 και SIGUSR2" diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 0000000..fedb6a0 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 0000000..a9647fc --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/en_GB.gmo b/po/en_GB.gmo new file mode 100644 index 0000000..b168be6 Binary files /dev/null and b/po/en_GB.gmo differ diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..259fc36 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,1456 @@ +# Translation of gstreamer messages to English (British). +# Copyright (C) 2004 Free Software Foundation, Inc. +# Gareth Owen , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.8.1\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2004-04-26 10:36-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 "Print the GStreamer version" +msgstr "Print the GStreamer version" + +msgid "Make all warnings fatal" +msgstr "Make all warnings fatal" + +msgid "Print available debug categories and exit" +msgstr "Print available debug categories and exit" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Default debug level from 1 (only error) to 5 (anything) or 0 for no output" + +msgid "LEVEL" +msgstr "LEVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LIST" + +msgid "Disable colored debugging output" +msgstr "Disable coloured debugging output" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Disable debugging" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Enable verbose plugin loading diagnostics" + +msgid "Colon-separated paths containing plugins" +msgstr "" + +msgid "PATHS" +msgstr "PATHS" + +#, fuzzy +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Disable trapping of segmentation faults during plugin loading" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "" + +#, fuzzy +msgid "Show GStreamer Options" +msgstr "Print the GStreamer version" + +msgid "Unknown option" +msgstr "" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer encountered a general core library error." + +#, fuzzy +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer developers were too lazy to assign an error code to this error. " +"Please file a bug." + +#, fuzzy +msgid "Internal GStreamer error: code not implemented." +msgstr "Internal GStreamer error: code not implemented. File a bug." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +#, fuzzy +msgid "Internal GStreamer error: pad problem." +msgstr "Internal GStreamer error: pad problem. File a bug." + +#, fuzzy +msgid "Internal GStreamer error: thread problem." +msgstr "Internal GStreamer error: thread problem. File a bug." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Internal GStreamer error: negotiation problem. File a bug." + +#, fuzzy +msgid "Internal GStreamer error: event problem." +msgstr "Internal GStreamer error: event problem. File a bug." + +#, fuzzy +msgid "Internal GStreamer error: seek problem." +msgstr "Internal GStreamer error: seek problem. File a bug." + +#, fuzzy +msgid "Internal GStreamer error: caps problem." +msgstr "Internal GStreamer error: caps problem. File a bug." + +#, fuzzy +msgid "Internal GStreamer error: tag problem." +msgstr "Internal GStreamer error: tag problem. File a bug." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Internal GStreamer error: seek problem. File a bug." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer encountered a general supporting library error." + +msgid "Could not initialize supporting library." +msgstr "Could not initialise supporting library." + +msgid "Could not close supporting library." +msgstr "Could not close supporting library." + +#, fuzzy +msgid "Could not configure supporting library." +msgstr "Could not close supporting library." + +msgid "Encoding error." +msgstr "" + +#, fuzzy +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer encountered a general core library error." + +msgid "Resource not found." +msgstr "Resource not found." + +msgid "Resource busy or not available." +msgstr "Resource busy or not available." + +msgid "Could not open resource for reading." +msgstr "Could not open resource for reading." + +msgid "Could not open resource for writing." +msgstr "Could not open resource for writing." + +msgid "Could not open resource for reading and writing." +msgstr "Could not open resource for reading and writing." + +msgid "Could not close resource." +msgstr "Could not close resource." + +msgid "Could not read from resource." +msgstr "Could not read from resource." + +msgid "Could not write to resource." +msgstr "Could not write to resource." + +msgid "Could not perform seek on resource." +msgstr "Could not perform seek on resource." + +msgid "Could not synchronize on resource." +msgstr "Could not synchronise on resource." + +msgid "Could not get/set settings from/on resource." +msgstr "Could not get/set settings from/on resource." + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Could not write to resource." + +#, fuzzy +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer encountered a general core library error." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Element doesn't implement handling of this stream. Please file a bug." + +msgid "Could not determine type of stream." +msgstr "Could not determine type of stream." + +msgid "The stream is of a different type than handled by this element." +msgstr "The stream is of a different type than handled by this element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "There is no codec present that can handle the stream's type." + +msgid "Could not decode stream." +msgstr "Could not decode stream." + +msgid "Could not encode stream." +msgstr "Could not encode stream." + +msgid "Could not demultiplex stream." +msgstr "Could not demultiplex stream." + +msgid "Could not multiplex stream." +msgstr "Could not multiplex stream." + +#, fuzzy +msgid "The stream is in the wrong format." +msgstr "Stream is of the wrong format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "No error message for domain %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "No standard error message for domain %s and code %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "title" + +msgid "commonly used title" +msgstr "commonly used title" + +msgid "title sortname" +msgstr "" + +#, fuzzy +msgid "commonly used title for sorting purposes" +msgstr "commonly used title" + +msgid "artist" +msgstr "artist" + +msgid "person(s) responsible for the recording" +msgstr "person(s) responsible for the recording" + +msgid "artist sortname" +msgstr "" + +#, fuzzy +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "person(s) responsible for the recording" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album containing this data" + +msgid "album sortname" +msgstr "" + +#, fuzzy +msgid "album containing this data for sorting purposes" +msgstr "album containing this data" + +#, fuzzy +msgid "album artist" +msgstr "artist" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "date" + +#, fuzzy +msgid "date the data was created (as a GDate structure)" +msgstr "date the data was created (in Julian calendar days)" + +#, fuzzy +msgid "datetime" +msgstr "date" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "date the data was created (in Julian calendar days)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre this data belongs to" + +msgid "comment" +msgstr "comment" + +msgid "free text commenting the data" +msgstr "free text commenting the data" + +#, fuzzy +msgid "extended comment" +msgstr "comment" + +#, fuzzy +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "free text commenting the data" + +msgid "track number" +msgstr "track number" + +msgid "track number inside a collection" +msgstr "track number inside a collection" + +msgid "track count" +msgstr "track count" + +msgid "count of tracks inside collection this track belongs to" +msgstr "count of tracks inside collection this track belongs to" + +msgid "disc number" +msgstr "disc number" + +msgid "disc number inside a collection" +msgstr "disc number inside a collection" + +msgid "disc count" +msgstr "disc count" + +msgid "count of discs inside collection this disc belongs to" +msgstr "count of discs inside collection this disc belongs to" + +msgid "location" +msgstr "location" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "description" + +msgid "short text describing the content of the data" +msgstr "short text describing the content of the data" + +msgid "version" +msgstr "version" + +msgid "version of this data" +msgstr "version of this data" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - see http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisation" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "copyright notice of the data" + +#, fuzzy +msgid "copyright uri" +msgstr "copyright" + +#, fuzzy +msgid "URI to the copyright notice of the data" +msgstr "copyright notice of the data" + +#, fuzzy +msgid "encoded by" +msgstr "encoder" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "contact" + +msgid "contact information" +msgstr "contact information" + +msgid "license" +msgstr "licence" + +msgid "license of data" +msgstr "licence of data" + +#, fuzzy +msgid "license uri" +msgstr "licence" + +#, fuzzy +msgid "URI to the license of the data" +msgstr "licence of data" + +msgid "performer" +msgstr "performer" + +msgid "person(s) performing" +msgstr "person(s) performing" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "person(s) responsible for the recording" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "duration" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "length in GStreamer time units (nanoseconds)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec the data is stored in" + +msgid "video codec" +msgstr "video codec" + +msgid "codec the video data is stored in" +msgstr "codec the video data is stored in" + +msgid "audio codec" +msgstr "audio codec" + +msgid "codec the audio data is stored in" +msgstr "codec the audio data is stored in" + +#, fuzzy +msgid "subtitle codec" +msgstr "video codec" + +#, fuzzy +msgid "codec the subtitle data is stored in" +msgstr "codec the video data is stored in" + +#, fuzzy +msgid "container format" +msgstr "contact information" + +#, fuzzy +msgid "container format the data is stored in" +msgstr "codec the data is stored in" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "exact or average bitrate in bits/s" + +msgid "nominal bitrate" +msgstr "nominal bitrate" + +msgid "nominal bitrate in bits/s" +msgstr "nominal bitrate in bits/s" + +msgid "minimum bitrate" +msgstr "minimum bitrate" + +msgid "minimum bitrate in bits/s" +msgstr "minimum bitrate in bits/s" + +msgid "maximum bitrate" +msgstr "maximum bitrate" + +msgid "maximum bitrate in bits/s" +msgstr "maximum bitrate in bits/s" + +msgid "encoder" +msgstr "encoder" + +msgid "encoder used to encode this stream" +msgstr "encoder used to encode this stream" + +msgid "encoder version" +msgstr "encoder version" + +msgid "version of the encoder used to encode this stream" +msgstr "version of the encoder used to encode this stream" + +msgid "serial" +msgstr "serial" + +msgid "serial number of track" +msgstr "serial number of track" + +msgid "replaygain track gain" +msgstr "replaygain track gain" + +msgid "track gain in db" +msgstr "track gain in db" + +msgid "replaygain track peak" +msgstr "replaygain track peak" + +msgid "peak of the track" +msgstr "peak of the track" + +msgid "replaygain album gain" +msgstr "replaygain album gain" + +msgid "album gain in db" +msgstr "album gain in db" + +msgid "replaygain album peak" +msgstr "replaygain album peak" + +msgid "peak of the album" +msgstr "peak of the album" + +#, fuzzy +msgid "replaygain reference level" +msgstr "replaygain track peak" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +msgid "language name" +msgstr "" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +#, fuzzy +msgid "image related to this stream" +msgstr "encoder used to encode this stream" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +#, fuzzy +msgid "file attached to this stream" +msgstr "encoder used to encode this stream" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +#, fuzzy +msgid "comma separated keywords describing the content" +msgstr "short text describing the content of the data" + +#, fuzzy +msgid "geo location name" +msgstr "location" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +#, fuzzy +msgid "geo location country" +msgstr "location" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location city" +msgstr "location" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location sublocation" +msgstr "location" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "location" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "location" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "location" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "location" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#, fuzzy +msgid "episode number" +msgstr "disc number" + +msgid "The episode number in the season the media is part of" +msgstr "" + +#, fuzzy +msgid "season number" +msgstr "disc number" + +msgid "The season number of the show the media is part of" +msgstr "" + +#, fuzzy +msgid "lyrics" +msgstr "licence" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "person(s) responsible for the recording" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +#, fuzzy +msgid "user rating" +msgstr "duration" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "version of the encoder used to encode this stream" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "version of the encoder used to encode this stream" + +#, fuzzy +msgid "application name" +msgstr "location" + +#, fuzzy +msgid "Application used to create the media" +msgstr "version of the encoder used to encode this stream" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERROR: from element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Additional debug info:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "no property \"%s\" in element \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "could not set property \"%s\" in element \"%s\" to \"%s\"" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "could not link %s to %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "could not link sink element for URI \"%s\"" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "could not link %s to %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "could not link %s to %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "no element \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "could not parse caps \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "no sink element for URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "no source element for URI \"%s\"" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "specified empty bin \"%s\", not allowed" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "no bin \"%s\", skipping" + +msgid "empty pipeline not allowed" +msgstr "empty pipeline not allowed" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, fuzzy, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Could not get/set settings from/on resource." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Could not open file \"%s\" for reading." + +#, fuzzy +msgid "Error while writing to download file." +msgstr "Error while writing to file \"%s\"." + +msgid "No file name specified for writing." +msgstr "No file name specified for writing." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Could not open file \"%s\" for writing." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Error closing file \"%s\"." + +#, fuzzy, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Error while writing to file \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Error while writing to file \"%s\"." + +msgid "No file name specified for reading." +msgstr "No file name specified for reading." + +#, fuzzy, c-format +msgid "Could not get info on \"%s\"." +msgstr "Could not get/set settings from/on resource." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "" + +#, fuzzy, c-format +msgid "File \"%s\" is a socket." +msgstr "File \"%s\" isn't a regular file." + +msgid "Failed after iterations as requested." +msgstr "Failed after iterations as requested." + +msgid "caps" +msgstr "caps" + +msgid "detected capabilities in stream" +msgstr "detected capabilities in stream" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "album containing this data" + +#, fuzzy +msgid "Stream contains no data." +msgstr "album containing this data" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +#, fuzzy +msgid "writable" +msgstr "title" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +#, fuzzy +msgid "Total count: " +msgstr "track count" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +#, fuzzy +msgid "Print all elements" +msgstr "no element \"%s\"" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, fuzzy, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Could not open file \"%s\" for writing." + +#, fuzzy, c-format +msgid "No such element or plugin '%s'\n" +msgstr "no source element for URI \"%s\"" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, fuzzy, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "ERROR: from element %s: %s\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "FOUND TAG : found by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "FOUND TAG : found by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "FOUND TAG : found by element \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "FOUND TAG : found by element \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "FOUND TAG : found by element \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, fuzzy, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ERROR: from element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "no element \"%s\"" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ERROR: from element %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Output tags (also known as metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Output status information and property notifications" + +#, fuzzy +msgid "Do not print any progress information" +msgstr "Do not output status information of TYPE" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Do not install a fault handler" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERROR: pipeline could not be constructed: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERROR: pipeline could not be constructed.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "WARNING: erroneous pipeline: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERROR: the 'pipeline' element wasn't found.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROR: pipeline doesn't want to play.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERROR: pipeline doesn't want to play.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERROR: pipeline doesn't want to play.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "Execution ended after %" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +#, fuzzy +msgid "Freeing pipeline ...\n" +msgstr "RUNNING pipeline ...\n" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Do not output status information of TYPE" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYPE1,TYPE2,..." + +#~ msgid "link without source element" +#~ msgstr "link without source element" + +#~ msgid "link without sink element" +#~ msgstr "link without sink element" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "no element to link URI \"%s\" to" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Print alloc trace (if enabled at compile time)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Usage: gst-xmllaunch [ element.property=value ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROR: parsing of xml file '%s' failed.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "ERROR: no toplevel pipeline element in file '%s'.\n" + +#, fuzzy +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "WARNING: only one toplevel element is supported at this time." + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "ERROR: could not parse command line argument %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "WARNING: element named '%s' not found.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Save xml representation of pipeline to FILE and exit" + +#~ msgid "FILE" +#~ msgstr "FILE" + +#, fuzzy +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Do not install a fault handler" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Disable accelerated CPU instructions" + +#~ msgid "SCHEDULER" +#~ msgstr "SCHEDULER" + +#~ msgid "Registry to use" +#~ msgstr "Registry to use" + +#~ msgid "REGISTRY" +#~ msgstr "REGISTRY" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "path list for loading plugins (separated by '%s')" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Scheduler to use (default is '%s')" + +#~ msgid "Internal GStreamer error: state change failed. File a bug." +#~ msgstr "Internal GStreamer error: state change failed. File a bug." + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "Internal GStreamer error: scheduler problem. File a bug." + +#~ msgid "original location of file as a URI" +#~ msgstr "original location of file as a URI" + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "There is no element present to handle the stream's mime type %s." + +#~ msgid "" +#~ "could not convert \"%s\" so that it fits property \"%s\" in element \"%s\"" +#~ msgstr "" +#~ "could not convert \"%s\" so that it fits property \"%s\" in element \"%s\"" + +#~ msgid "Show plugin details" +#~ msgstr "Show plugin details" + +#~ msgid "Show scheduler details" +#~ msgstr "Show scheduler details" + +#~ msgid " iterations (sum %" +#~ msgstr " iterations (sum %" + +#~ msgid " ns, average %" +#~ msgstr " ns, average %" + +#~ msgid " ns, min %" +#~ msgstr " ns, min %" + +#~ msgid " ns, max %" +#~ msgstr " ns, max %" + +#~ msgid " ns).\n" +#~ msgstr " ns).\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Number of times to iterate pipeline" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Trying to run anyway.\n" + +#~ msgid "')" +#~ msgstr "')" + +#~ msgid "' is the default)" +#~ msgstr "' is the default)" diff --git a/po/eo.gmo b/po/eo.gmo new file mode 100644 index 0000000..744991c Binary files /dev/null and b/po/eo.gmo differ diff --git a/po/eo.po b/po/eo.po new file mode 100644 index 0000000..29e37cd --- /dev/null +++ b/po/eo.po @@ -0,0 +1,1279 @@ +# Esperanto translation for gstreamer. +# Copyright (C) 2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Kristjan SCHMIDT , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2011-06-04 21:11+0100\n" +"Last-Translator: Kristjan SCHMIDT \n" +"Language-Team: Esperanto \n" +"Language: eo\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 "Print the GStreamer version" +msgstr "Eligi la version de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Igi ĉiujn avertojn fatalaj" + +msgid "Print available debug categories and exit" +msgstr "Eligi disponeblaj sencimig-koategorioj kaj eliri" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" + +msgid "LEVEL" +msgstr "NIVELO" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" + +msgid "LIST" +msgstr "LISTO" + +msgid "Disable colored debugging output" +msgstr "" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Elŝalti sencimigon" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" + +msgid "Colon-separated paths containing plugins" +msgstr "" + +msgid "PATHS" +msgstr "VOJOJ" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +msgid "PLUGINS" +msgstr "KROMPROGRAMOJ" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "Opcioj de GStreamer" + +msgid "Show GStreamer Options" +msgstr "Montri la opcijon de GStreamer" + +msgid "Unknown option" +msgstr "Nekonata opcio" + +msgid "GStreamer encountered a general core library error." +msgstr "" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +msgid "Internal GStreamer error: code not implemented." +msgstr "" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "" + +msgid "Internal GStreamer error: thread problem." +msgstr "" + +msgid "GStreamer error: negotiation problem." +msgstr "" + +msgid "Internal GStreamer error: event problem." +msgstr "" + +msgid "Internal GStreamer error: seek problem." +msgstr "" + +msgid "Internal GStreamer error: caps problem." +msgstr "" + +msgid "Internal GStreamer error: tag problem." +msgstr "" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +msgid "GStreamer error: clock problem." +msgstr "" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "" + +msgid "Could not initialize supporting library." +msgstr "" + +msgid "Could not close supporting library." +msgstr "" + +msgid "Could not configure supporting library." +msgstr "" + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "" + +msgid "Resource not found." +msgstr "Ne trovis risurcon." + +msgid "Resource busy or not available." +msgstr "Risurco estas okupite aŭ ne disponeble." + +msgid "Could not open resource for reading." +msgstr "Ne eblas melfermi la risurcon por legado." + +msgid "Could not open resource for writing." +msgstr "Ne eblas melfermi la risurcon por skribado." + +msgid "Could not open resource for reading and writing." +msgstr "Ne eblas melfermi la risurcon por legado kaj skribado." + +msgid "Could not close resource." +msgstr "Ne eblas fermi la risurcon." + +msgid "Could not read from resource." +msgstr "Ne eblas legi de la risurco." + +msgid "Could not write to resource." +msgstr "Ne eblas skribi al la risurco." + +msgid "Could not perform seek on resource." +msgstr "" + +msgid "Could not synchronize on resource." +msgstr "" + +msgid "Could not get/set settings from/on resource." +msgstr "" + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Ne eblas skribi al la risurco." + +msgid "GStreamer encountered a general stream error." +msgstr "" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" + +msgid "Could not determine type of stream." +msgstr "" + +msgid "The stream is of a different type than handled by this element." +msgstr "" + +msgid "There is no codec present that can handle the stream's type." +msgstr "" + +msgid "Could not decode stream." +msgstr "" + +msgid "Could not encode stream." +msgstr "" + +msgid "Could not demultiplex stream." +msgstr "" + +msgid "Could not multiplex stream." +msgstr "" + +msgid "The stream is in the wrong format." +msgstr "" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "titolo" + +msgid "commonly used title" +msgstr "" + +msgid "title sortname" +msgstr "" + +msgid "commonly used title for sorting purposes" +msgstr "" + +msgid "artist" +msgstr "artisto" + +msgid "person(s) responsible for the recording" +msgstr "" + +msgid "artist sortname" +msgstr "" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" + +msgid "album" +msgstr "albumo" + +msgid "album containing this data" +msgstr "" + +msgid "album sortname" +msgstr "" + +msgid "album containing this data for sorting purposes" +msgstr "" + +msgid "album artist" +msgstr "album-artisto" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "dato" + +msgid "date the data was created (as a GDate structure)" +msgstr "" + +msgid "datetime" +msgstr "datohoro" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" + +msgid "genre" +msgstr "ĝenro" + +msgid "genre this data belongs to" +msgstr "" + +msgid "comment" +msgstr "komento" + +msgid "free text commenting the data" +msgstr "" + +msgid "extended comment" +msgstr "" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" + +msgid "track number" +msgstr "" + +msgid "track number inside a collection" +msgstr "" + +msgid "track count" +msgstr "" + +msgid "count of tracks inside collection this track belongs to" +msgstr "" + +msgid "disc number" +msgstr "disk-numero" + +msgid "disc number inside a collection" +msgstr "" + +msgid "disc count" +msgstr "disk-nombro" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" + +msgid "location" +msgstr "loko" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "hejmpaĝo" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "priskribo" + +msgid "short text describing the content of the data" +msgstr "" + +msgid "version" +msgstr "versio" + +msgid "version of this data" +msgstr "versi de tiu datumo" + +msgid "ISRC" +msgstr "" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" + +msgid "organization" +msgstr "" + +msgid "copyright" +msgstr "kopirajto" + +msgid "copyright notice of the data" +msgstr "" + +msgid "copyright uri" +msgstr "" + +msgid "URI to the copyright notice of the data" +msgstr "" + +msgid "encoded by" +msgstr "" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "kontakto" + +msgid "contact information" +msgstr "" + +msgid "license" +msgstr "permesilo" + +msgid "license of data" +msgstr "permesilo de la datumoj" + +msgid "license uri" +msgstr "" + +msgid "URI to the license of the data" +msgstr "" + +msgid "performer" +msgstr "" + +msgid "person(s) performing" +msgstr "" + +msgid "composer" +msgstr "komponisto" + +msgid "person(s) who composed the recording" +msgstr "" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "daŭro" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "" + +msgid "codec" +msgstr "kodeko" + +msgid "codec the data is stored in" +msgstr "" + +msgid "video codec" +msgstr "video-kodeko" + +msgid "codec the video data is stored in" +msgstr "" + +msgid "audio codec" +msgstr "son-kodeko" + +msgid "codec the audio data is stored in" +msgstr "" + +msgid "subtitle codec" +msgstr "subtekst-kodeko" + +msgid "codec the subtitle data is stored in" +msgstr "" + +msgid "container format" +msgstr "" + +msgid "container format the data is stored in" +msgstr "" + +msgid "bitrate" +msgstr "bitrapido" + +msgid "exact or average bitrate in bits/s" +msgstr "" + +msgid "nominal bitrate" +msgstr "" + +msgid "nominal bitrate in bits/s" +msgstr "" + +msgid "minimum bitrate" +msgstr "" + +msgid "minimum bitrate in bits/s" +msgstr "" + +msgid "maximum bitrate" +msgstr "" + +msgid "maximum bitrate in bits/s" +msgstr "" + +msgid "encoder" +msgstr "" + +msgid "encoder used to encode this stream" +msgstr "" + +msgid "encoder version" +msgstr "" + +msgid "version of the encoder used to encode this stream" +msgstr "" + +msgid "serial" +msgstr "" + +msgid "serial number of track" +msgstr "" + +msgid "replaygain track gain" +msgstr "" + +msgid "track gain in db" +msgstr "" + +msgid "replaygain track peak" +msgstr "" + +msgid "peak of the track" +msgstr "" + +msgid "replaygain album gain" +msgstr "" + +msgid "album gain in db" +msgstr "" + +msgid "replaygain album peak" +msgstr "" + +msgid "peak of the album" +msgstr "" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "Lingvokodo" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +#, fuzzy +msgid "language name" +msgstr "Lingvokodo" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "bildo" + +msgid "image related to this stream" +msgstr "" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "kunsendaĵo" + +msgid "file attached to this stream" +msgstr "" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +msgid "comma separated keywords describing the content" +msgstr "" + +msgid "geo location name" +msgstr "" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +msgid "geo location country" +msgstr "" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location city" +msgstr "" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location sublocation" +msgstr "" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +msgid "geo location horizontal error" +msgstr "" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +msgid "geo location movement direction" +msgstr "" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +msgid "geo location capture direction" +msgstr "" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "montri nomon" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +msgid "episode number" +msgstr "" + +msgid "The episode number in the season the media is part of" +msgstr "" + +msgid "season number" +msgstr "" + +msgid "The season number of the show the media is part of" +msgstr "" + +msgid "lyrics" +msgstr "lirikoj" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" + +msgid "grouping" +msgstr "grupado" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +msgid "user rating" +msgstr "" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +msgid "Manufacturer of the device used to create this media" +msgstr "" + +msgid "device model" +msgstr "" + +msgid "Model of the device used to create this media" +msgstr "" + +msgid "application name" +msgstr "" + +msgid "Application used to create the media" +msgstr "" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +msgid "Delayed linking failed." +msgstr "" + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s" +msgstr "" + +#, c-format +msgid "no element \"%s\"" +msgstr "neniu elemento \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "" + +msgid "empty pipeline not allowed" +msgstr "" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "" + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "" + +msgid "Error while writing to download file." +msgstr "" + +msgid "No file name specified for writing." +msgstr "" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Ne eblis malfermi la dosieron \"%s\" por skribi." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Eraro dum fermado de la dosiero \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Eraro dum skribo al la dosiero \"%s\"." + +msgid "No file name specified for reading." +msgstr "" + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" estas dosierujo." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "" + +msgid "Failed after iterations as requested." +msgstr "" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "" + +msgid "minimum" +msgstr "minimumo" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +msgid "Stream doesn't contain enough data." +msgstr "" + +msgid "Stream contains no data." +msgstr "" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "legeble" + +msgid "writable" +msgstr "skribeble" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "regeble" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +msgid "Total count: " +msgstr "" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d kromprogramo" +msgstr[1] "%d kromprogramoj" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d trajto" +msgstr[1] "%d trajtoj" + +msgid "Print all elements" +msgstr "Eligi ĉiujn elementojn" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TAG\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVERTO: de elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "bufrado..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "neniu elemento \"%s\"" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "AVERTO: de elemento %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "" + +msgid "Do not print any progress information" +msgstr "" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +msgid "Freeing pipeline ...\n" +msgstr "" + +#~ msgid "Internal data stream error." +#~ msgstr "Interna datumflu-eraro." + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPO1,TIPO2,..." + +#~ msgid "FILE" +#~ msgstr "DOSIERO" diff --git a/po/es.gmo b/po/es.gmo new file mode 100644 index 0000000..90bf2e0 Binary files /dev/null and b/po/es.gmo differ diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..0299690 --- /dev/null +++ b/po/es.po @@ -0,0 +1,1423 @@ +# translation of gstreamer-0.10.32.2.po to Español +# spanish translation for gstreamer +# This file is put in the public domain. +# Jorge González , 2009, 2010, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2011-10-02 15:45+0200\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 "Print the GStreamer version" +msgstr "Imprimir la versión de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Hacer todas las advertencias fatales" + +msgid "Print available debug categories and exit" +msgstr "Imprimir categorías de depuración disponibles y salir" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Nivel de depuración predeterminado desde 1 (sólo error) hasta 5 (todo) o 0 " +"sin salida" + +msgid "LEVEL" +msgstr "NIVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Lista de pares categoría_nombre:nivel separados por comas para establecer " +"niveles específicos para las categorías individuales. Ejemplo: " +"GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Desactivar la coloración de la salida depurada" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Desactivar depuración" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Activar la salida detallada del diagnóstico de carga de complementos" + +msgid "Colon-separated paths containing plugins" +msgstr "Rutas separadas por punto y coma conteniendo los complementos" + +msgid "PATHS" +msgstr "RUTAS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Lista de complementos para pregarcar separados por comas además de la lista " +"almacenada en la variable de entorno GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "COMPLEMENTOS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Desactivar la captura de fallos de segmentación durante la carga de " +"complementos" + +msgid "Disable updating the registry" +msgstr "Desactivar la actualización del registro" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Desactivar el lanzamiento de un proceso de ayuda al escanear el registro" + +msgid "GStreamer Options" +msgstr "Opciones de GStreamer" + +msgid "Show GStreamer Options" +msgstr "Mostrar las opciones de GStreamer" + +msgid "Unknown option" +msgstr "Opción desconocida" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer encontró un error general en el núcleo de la biblioteca." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Los desarrolladores de GStreamer fueron demasiado vagos para añadir un " +"código de error a este error." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Error interno de GStreamer: código no implementado" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Error de GStreamer: falló el cambio de estado y algún elemento falló al " +"publicar el error de mensaje correspondiente con el motivo del fallo." + +msgid "Internal GStreamer error: pad problem." +msgstr " " + +msgid "Internal GStreamer error: thread problem." +msgstr "Error interno de GStreamer: problema con las hebras." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Error interno de GStreamer: problema con la negociación." + +msgid "Internal GStreamer error: event problem." +msgstr "Error interno de GStreamer: problema con los eventos." + +msgid "Internal GStreamer error: seek problem." +msgstr "Error interno de GStreamer: problema con la búsqueda." + +msgid "Internal GStreamer error: caps problem." +msgstr "Error interno de GStreamer: problema con las capacidades." + +msgid "Internal GStreamer error: tag problem." +msgstr "Error interno de GStreamer: problema con las etiquetas." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "A la instalación de GStreamer le falta un complemento." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Error interno de GStreamer: problema con el reloj." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Esta aplicación está tratando de usar una funcionalidad de GStreamer que se " +"ha deshabilitado." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer encontró un error de soporte general en la biblioteca." + +msgid "Could not initialize supporting library." +msgstr "No se pudo inicializar la biblioteca de soporte." + +msgid "Could not close supporting library." +msgstr "No se pudo cerrar la biblioteca de soporte." + +msgid "Could not configure supporting library." +msgstr "No se pudo configurar la biblioteca de soporte." + +msgid "Encoding error." +msgstr "Error de codificación." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer encontró un error general de recurso." + +msgid "Resource not found." +msgstr "Recurso no encontrado." + +msgid "Resource busy or not available." +msgstr "El recurso está ocupado o no disponible." + +msgid "Could not open resource for reading." +msgstr "No se pudo abrir el recurso para su lectura." + +msgid "Could not open resource for writing." +msgstr "No se pudo abrir el recurso para su escritura." + +msgid "Could not open resource for reading and writing." +msgstr "No se pudo abrir el recurso para su lectura y escritura." + +msgid "Could not close resource." +msgstr "No se pudo cerrar el recurso." + +msgid "Could not read from resource." +msgstr "No se pudo leer del recurso." + +msgid "Could not write to resource." +msgstr "No se pudo escribir en el recurso." + +msgid "Could not perform seek on resource." +msgstr "No se pudo realizar una búsqueda en el recurso." + +msgid "Could not synchronize on resource." +msgstr "No se pudo sincronizar el recurso." + +msgid "Could not get/set settings from/on resource." +msgstr "No se pudieron obtener/establecer los ajustes de/en el recurso." + +msgid "No space left on the resource." +msgstr "No queda espacio disponible en el recurso." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "No queda espacio disponible en el recurso." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer encontró un error general de flujo." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"El elemento no implementa un manejador de este flujo. Por favor, rellene un " +"informe de error." + +msgid "Could not determine type of stream." +msgstr "No se pudo determinar el tipo de flujo." + +msgid "The stream is of a different type than handled by this element." +msgstr "El flujo es de un tipo diferente que el manejado por este elemento." + +msgid "There is no codec present that can handle the stream's type." +msgstr "No hay un códec disponible que pueda manejar el tipo del flujo." + +msgid "Could not decode stream." +msgstr "No se pudo decodificar el flujo." + +msgid "Could not encode stream." +msgstr "No se pudo codificar el flujo." + +msgid "Could not demultiplex stream." +msgstr "No se pudo demultiplexar el flujo." + +msgid "Could not multiplex stream." +msgstr "No se pudo multiplexar el flujo." + +msgid "The stream is in the wrong format." +msgstr "El flujo está en el formato incorrecto." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "El flujo está cifrado y el descifrado no está soportado." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"El flujo está cifrado y no se puede descifrar porque no se ha proporcionado " +"una clave adecuada." + +#, c-format +msgid "No error message for domain %s." +msgstr "No hay un mensaje de error para el dominio %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "No hay un mensaje de error estándar para el dominio %s y código %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "El reloj seleccionado no se puede usar en la segmentación." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Error al escribir la caché de registro a %s: %s" + +msgid "title" +msgstr "título" + +msgid "commonly used title" +msgstr "título usado comúnmente" + +msgid "title sortname" +msgstr "nombre de ordenación del título" + +msgid "commonly used title for sorting purposes" +msgstr "título usado comúnmente para propósitos de ordenamiento" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "persona(s) responsables de la grabación" + +msgid "artist sortname" +msgstr "nombre de ordenación del artista" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" +"persona(s) responsable(s) de la grabación para propósitos de ordenamiento" + +msgid "album" +msgstr "álbum" + +msgid "album containing this data" +msgstr "el álbum que contiene estos datos" + +msgid "album sortname" +msgstr "nombre de ordenación del álbum" + +msgid "album containing this data for sorting purposes" +msgstr "el álbum que contiene estos datos para propósitos de ordenamiento" + +msgid "album artist" +msgstr "artista del álbum" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "El artista del álbum entero, como se debería mostrar" + +msgid "album artist sortname" +msgstr "nombre de ordenación del artista del álbum" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "El artista del álbum entero, como se debería ordenar" + +msgid "date" +msgstr "fecha" + +msgid "date the data was created (as a GDate structure)" +msgstr "fecha en la que se crearon los datos (como estructura GDate)" + +msgid "datetime" +msgstr "fecha y hora" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"fecha y hora en la que se crearon los datos (como estructura GstDateTime)" + +msgid "genre" +msgstr "género" + +msgid "genre this data belongs to" +msgstr "género al que pertenecen estos datos" + +msgid "comment" +msgstr "comentario" + +msgid "free text commenting the data" +msgstr "comentario de texto sobre los datos" + +msgid "extended comment" +msgstr "comentario extendido" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"texto libre comentando los datos como key=valor o key[es]=formulario de " +"comentario" + +msgid "track number" +msgstr "número de pista" + +msgid "track number inside a collection" +msgstr "número de pista en una colección" + +msgid "track count" +msgstr "número de pista" + +msgid "count of tracks inside collection this track belongs to" +msgstr "número de pistas en la colección a la que pertenece la pista" + +msgid "disc number" +msgstr "número de disco" + +msgid "disc number inside a collection" +msgstr "número del disco dentro de una colección" + +msgid "disc count" +msgstr "número de discos" + +msgid "count of discs inside collection this disc belongs to" +msgstr "número de discos en la colección a la que pertenece el disco" + +msgid "location" +msgstr "ubicación" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Origen del medio como un URI (ubicación, donde está alojado el archivo o " +"flujo original)" + +msgid "homepage" +msgstr "página principal" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Página principal para este soporte (ej. página principal del artista o " +"película)" + +msgid "description" +msgstr "descripción" + +msgid "short text describing the content of the data" +msgstr "texto corto describiendo el contenido de los datos" + +msgid "version" +msgstr "versión" + +msgid "version of this data" +msgstr "versión de estos datos" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code; consulte http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organización" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "nota de derechos de autor de los datos" + +msgid "copyright uri" +msgstr "URI a los derechos de autor" + +msgid "URI to the copyright notice of the data" +msgstr "URI a la nota de derechos de autor de los datos" + +msgid "encoded by" +msgstr "codificado por" + +msgid "name of the encoding person or organization" +msgstr "Nombre de la persona u organización que lo codificó" + +msgid "contact" +msgstr "contacto" + +msgid "contact information" +msgstr "información de contacto" + +msgid "license" +msgstr "licencia" + +msgid "license of data" +msgstr "licencia de los datos" + +msgid "license uri" +msgstr "URI a la licencia" + +msgid "URI to the license of the data" +msgstr "URI a la licencia de los datos" + +msgid "performer" +msgstr "intérprete" + +msgid "person(s) performing" +msgstr "persona(s) interpretando" + +msgid "composer" +msgstr "compositor" + +msgid "person(s) who composed the recording" +msgstr "persona(s) que compusieron la grabación" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "duracio" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "duración en unidades de tiempo GStreamer (nanosegundos)" + +msgid "codec" +msgstr "cídec" + +msgid "codec the data is stored in" +msgstr "códec en el que están almacenados los datos" + +msgid "video codec" +msgstr "códec de vídeo" + +msgid "codec the video data is stored in" +msgstr "códec en el que están almacenados los datos del vídeo" + +msgid "audio codec" +msgstr "códec de sonido" + +msgid "codec the audio data is stored in" +msgstr "códec en el que están almacenados los datos del sonido" + +msgid "subtitle codec" +msgstr "códec del subtítulo" + +msgid "codec the subtitle data is stored in" +msgstr "códec en el que están almacenados los datos del subtítulo" + +msgid "container format" +msgstr "formato del contenedor" + +msgid "container format the data is stored in" +msgstr "formato del contenedor en el que están almacenados los datos" + +msgid "bitrate" +msgstr "tasa de bits" + +msgid "exact or average bitrate in bits/s" +msgstr "tasa de bits exacta o media en bits/s" + +msgid "nominal bitrate" +msgstr "tasa de bits nominal" + +msgid "nominal bitrate in bits/s" +msgstr "tasa de bits nominal en bits/s" + +msgid "minimum bitrate" +msgstr "mínima tasa de bits" + +msgid "minimum bitrate in bits/s" +msgstr "mínima tasa de bits en bits/s" + +msgid "maximum bitrate" +msgstr "máxima tasa de bits" + +msgid "maximum bitrate in bits/s" +msgstr "máxima tasa de bits en bits/s" + +msgid "encoder" +msgstr "codificador" + +msgid "encoder used to encode this stream" +msgstr "codificador usado para codificar este flujo" + +msgid "encoder version" +msgstr "versión del codificador" + +msgid "version of the encoder used to encode this stream" +msgstr "versión del codificador usado para codificar este flujo" + +msgid "serial" +msgstr "serie" + +msgid "serial number of track" +msgstr "número de serie de la pista" + +msgid "replaygain track gain" +msgstr "reproduciendo ganancia de la pista" + +msgid "track gain in db" +msgstr "ganancia de la pista en dB" + +msgid "replaygain track peak" +msgstr "reproduciendo pico de la pista" + +msgid "peak of the track" +msgstr "pico de la pista" + +msgid "replaygain album gain" +msgstr "reproduciendo ganancia del álbum" + +msgid "album gain in db" +msgstr "ganancia del álbum en dB" + +msgid "replaygain album peak" +msgstr "reproduciendo el pico del álbum" + +msgid "peak of the album" +msgstr "pico del álbum" + +msgid "replaygain reference level" +msgstr "nivel de referencia de la ganancia" + +msgid "reference level of track and album gain values" +msgstr "valor del nivel de referencia de ganancia de la pista y del álbum" + +msgid "language code" +msgstr "código de idioma" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "código de idioma para este flujo, ajustándose a ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "código de idioma" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "imagen" + +msgid "image related to this stream" +msgstr "imagen relacionada con este flujo" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "previsualizar imagen" + +msgid "preview image related to this stream" +msgstr "previsualizar la imagen relacionada con este flujo" + +msgid "attachment" +msgstr "adjunto" + +msgid "file attached to this stream" +msgstr "archivo adjunto a este flujo" + +msgid "beats per minute" +msgstr "golpes por minuto (bpm)" + +msgid "number of beats per minute in audio" +msgstr "número de golpes por minuto (bpm) en el sonido" + +msgid "keywords" +msgstr "palabras clave" + +msgid "comma separated keywords describing the content" +msgstr "palabras clave separadas por comas describiendo el contenido" + +msgid "geo location name" +msgstr "nombre de la geoubicación" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"descripción de la ubicación entendible por humanos de dónde se ha grabado o " +"producido el medio" + +msgid "geo location latitude" +msgstr "latitud de la geolocalización" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitud geográfica donde se ha grabado o producido el medio, en grados de " +"acuerdo con WGS84 (cero es el ecuador, valores negativos para latitudes " +"meridionales)" + +msgid "geo location longitude" +msgstr "longitud de la geolocalización" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitud geográfica donde se ha grabado o producido el medio, en grados de " +"acuerdo con WGS84 (cero es el primer meridiano en Greenwich/GB, valores " +"negativos para longitudes occidentales)" + +msgid "geo location elevation" +msgstr "elevación de la geolocalización" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"elevación geográfica donde se ha grabado o producido el medio, en metros de " +"acuerdo con WGS84 (cero es el nivel medio del mar)" + +msgid "geo location country" +msgstr "país de la geolocalización" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "país (nombre en inglés) donde se ha grabado o producido el medio" + +msgid "geo location city" +msgstr "ciudad de la geolocalización" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "ciudad (nombre en inglés) donde se ha grabado o producido el medio" + +msgid "geo location sublocation" +msgstr "sububicación de la geolocalización" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"una ubicación en una ciudad donde se ha producido o creado el medio (ej. el " +"barrio)" + +msgid "geo location horizontal error" +msgstr "error horizontal de geolocalización" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" +"error esperado de las medidas de posicionamiento horizontal (en metros)" + +msgid "geo location movement speed" +msgstr "velocidad de movimiento de la geolocalización" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"velocidad de movimiento del dispositivo de captura mientras realiza la " +"captura, en m/s" + +msgid "geo location movement direction" +msgstr "dirección de movimiento de la geolocalización" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica la dirección de movimiento del dispositivo que realiza la captura de " +"un medio. Se representa en grados o en una representación en coma flotante, " +"0 significa el norte geográfico y aumenta de forma horaria." + +msgid "geo location capture direction" +msgstr "dirección de captura de la geolocalización" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica la dirección a la que apunta el dispositivo que realiza la captura de " +"un medio. Se representa en grados o en una representación en coma flotante, " +"0 significa el norte geográfico y aumenta de forma horaria." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nombre del programa" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nombre del programa/podcast/serie" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nombre de ordenación del programa" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Nombre del programa/podcast/serie, para propósitos de ordenación" + +msgid "episode number" +msgstr "número de episodio" + +msgid "The episode number in the season the media is part of" +msgstr "El número de episodio en la temporada " + +msgid "season number" +msgstr "número de temporada" + +msgid "The season number of the show the media is part of" +msgstr "El número de temporada del programa" + +msgid "lyrics" +msgstr "letras" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Las letras del archivo multimedia, generalmente usado para canciones" + +msgid "composer sortname" +msgstr "nombre corto del compositor" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" +"persona(s) que compusieron la grabación, para propósitos de ordenamiento" + +msgid "grouping" +msgstr "agrupación" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Agrupa temas relacionados que se expanden varias pistas, como las diferentes " +"partes de un concierto. Es un nivel más alto que el de una pista, pero más " +"bajo que el de un álbum." + +msgid "user rating" +msgstr "puntuación de usuario" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Puntuación atribuida por un usuario. Cuanto mayor sea la puntuación más le " +"gustará al usuario." + +msgid "device manufacturer" +msgstr "fabricante del dispositivo" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricante del dispositivo usado para crear este medio" + +msgid "device model" +msgstr "modelo del dispositivo" + +msgid "Model of the device used to create this media" +msgstr "Modelo del dispositivo usado para crear este medio" + +msgid "application name" +msgstr "nombre de la aplicación" + +msgid "Application used to create the media" +msgstr "Aplicación usada para crear el medio" + +msgid "application data" +msgstr "datos de la aplicación" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Datos arbitrarios de la aplicación para serializarlos en el medio" + +msgid "image orientation" +msgstr "orientación de la imagen" + +msgid "How the image should be rotated or flipped before display" +msgstr "Cómo se debería rotar o voltear la imagen antes de mostrarla" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERROR: del elemento %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Información adicional de depuración:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "no hay una propiedad «%s» en el elemento «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "no se pudo establecer la propiedad «%s» en el elemento «%s» a «%s»" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "no se pudo enlazar %s a %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "no se pudo enlazar el elemento sumidero para el URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "no se pudo enlazar %s a %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "no se pudo enlazar %s a %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "no hay un elemento «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "no se pudieron analizar las capacidades «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "no existe el elemento sumidero para el URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "no existe un elemento origen para el URI «%s»" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "el binario especificado «%s» está vacío, no está permitido" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "no existe el binario «%s», omitiendo" + +msgid "empty pipeline not allowed" +msgstr "no se permite un conducto vacío" + +msgid "A lot of buffers are being dropped." +msgstr "Se están desechando muchos búferes." + +msgid "Internal data flow problem." +msgstr "Problema en el flujo de datos interno." + +msgid "Internal data flow error." +msgstr "Error en el flujo de datos interno." + +msgid "Internal clock error." +msgstr "Error en el reloj interno." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Filtro de capacidades" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restringir las posibles capacidades permitidas (NULL significa CUALQUIERA). " +"Al establecer esta propiedad se obtiene una referencia del objeto GstCaps " +"proporcionado." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "No se especificó un directorio temporal." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "No se pudo crear el archivo temporal «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "No se pudo abrir el archivo «%s» para leer." + +msgid "Error while writing to download file." +msgstr "Error al escribir para descargar el archivo." + +msgid "No file name specified for writing." +msgstr "No se especificó un nombre de archivo para escritura." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "No se pudo abrir «%s» para escribir." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Error al cerrar el archivo «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Error al buscar en el archivo «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Error al escribir al archivo «%s»." + +msgid "No file name specified for reading." +msgstr "No se especificó un nombre de archivo para la lectura." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "No se pudo obtener la información de «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» es un directorio." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "El archivo «%s» es un socket." + +msgid "Failed after iterations as requested." +msgstr "Falló después de las iteraciones, como se pidió." + +msgid "caps" +msgstr "capacidades" + +msgid "detected capabilities in stream" +msgstr "capacidades detectadas en el flujo" + +msgid "minimum" +msgstr "mínimo" + +msgid "force caps" +msgstr "forzar las capacidades" + +msgid "force caps without doing a typefind" +msgstr "forzar las capacidades sin hacer un «typefind»" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "El flujo no contiene datos." + +msgid "Stream contains no data." +msgstr "El flujo no contiene datos." + +msgid "Implemented Interfaces:\n" +msgstr "Interfaces implementados:\n" + +msgid "readable" +msgstr "legible" + +msgid "writable" +msgstr "escribible" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "controlable" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "intercambiable entre los estados NULL, READY, PAUSED o PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "intercambiable sólo entre los estados NULL, READY o PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "intercambiable sólo entre los estados NULL o READY" + +msgid "Blacklisted files:" +msgstr "Archivos en la lista negra:" + +msgid "Total count: " +msgstr "Conteo total:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d archivo en la lista negra" +msgstr[1] "%d archivos en la lista negra" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d complemento" +msgstr[1] "%d complementos" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entrada en la lista negra" +msgstr[1] "%d entradas en la lista negra" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d característica" +msgstr[1] "%d características" + +msgid "Print all elements" +msgstr "Imprimir todos los elementos" + +msgid "Print list of blacklisted files" +msgstr "Imprimir lista de los archivos en la lista negra" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Imprimir una lista de características analizables por una máquina que el " +"complemento especificado proporciona.\n" +" Útil junto con mecanismos de " +"instalación externa automática de complementos." + +msgid "List the plugin contents" +msgstr "Listar el contenido del complemento" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Imprimir los esquemas URI soportados, con los elementos que los implementan" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "No se pudo cargar el archivo de complemento: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "No existe el elemento o complemento «%s»\n" + +msgid "Index statistics" +msgstr "índice de las estadísticas" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Se obtuvo el mensaje nº %u del elemento «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Se obtuvo el mensaje nº %u de la celda «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Se recibió el mensaje nº %u del objeto «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Se obtuvo el mensaje nº %u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Se recibió un EOS del elemento «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada por el elemento «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada por la celda «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada por el objeto «%s».\n" + +msgid "FOUND TAG\n" +msgstr "ETIQUETA ENCONTRADA\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada por el elemento «%s».\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada por el objeto «%s».\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "ETIQUETA ENCONTRADA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACIÓN:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ADVERTENCIA: del elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Preparado, esperando a llenar el búfer para terminar…\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Preparado, esperando a llenar el búfer para terminar…\n" + +msgid "buffering..." +msgstr "almacenando en el búfer…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Se terminó de almacenar en el búfer, estableciendo la segmentación para " +"REPRODUCIR…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "almacenando en el búfer, estableciendo la segmentación a PAUSA…\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribuir latencia…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Estableciendo el estado a %s según lo solicitó %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrumpir: parando el conducto …\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "no hay un elemento «%s»" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ADVERTENCIA: del elemento %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Etiquetas de salida (también conocidos como metadatos)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Información de estado de la salida y notificaciones de las propiedades" + +msgid "Do not print any progress information" +msgstr "No mostrar ninguna información de progreso" + +msgid "Output messages" +msgstr "Mensajes de salida" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "No instalar un manejador predeterminado" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forzar EOS en las fuentes antes de cerrar la tubería" + +msgid "Gather and print index statistics" +msgstr "Obtener y mostrar el índice de las estadísticas" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERROR: no se pudo construir el conducto:%s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERROR: no se pudo construir el conducto.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ADVERTENCIA: conducto erróneo: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERROR: el elemento «conducto» no se encontró.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Estableciendo el conducto a PAUSA …\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROR: El conducto no quiere pausarse.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "El conducto está vivo y no necesita PREPARARSE …\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "El conducto está PREPARÁNDOSE …\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERROR: el conducto no quiere prepararse.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "El conducto está PREPARADO …\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Estableciendo el conducto a REPRODUCIENDO …\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERROR: el conducto no quiere reproducir.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS al apagar activado; Forzando EOS en la tubería\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS al apagar activado; Forzando EOS en la tubería\n" + +msgid "Waiting for EOS...\n" +msgstr "Esperando a EOS…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS recibido: parando el conducto …\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrumpir: parando el conducto …\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Ocurrió un error al esperar a EOS\n" + +msgid "Execution ended after %" +msgstr "La ejecución finalizó después de %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Estableciando el conducto a PREPARADO …\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Estableciendo el conducto a NULL …\n" + +msgid "Freeing pipeline ...\n" +msgstr "Liberando la tubería…\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Error interno de flujo de datos." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "No sacar la salida de la información de estado del TIPO" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPO1,TIPO2,…" + +#~ msgid "link without source element" +#~ msgstr "enlace sin elemento origen" + +#~ msgid "link without sink element" +#~ msgstr "enlace sin elemento sumidero" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "no existe un elemento con el que enlazar el URI «%s»" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Imprimir la traza de asignaciones (si se activó al compilar)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Uso: gst-xmllaunch [ propiedad.del.elemento=valor … ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROR: falló el análisis del archivo xml «%s».\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERROR: no existe el elemento de nivel superior de la segmentación en el " +#~ "archivo «%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "ADVERTENCIA: en este momento sólo se soporta un elemento de nivel " +#~ "superior.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERROR: no se pudo analizar el argumento %d de la línea de comandos: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "ADVERTENCIA: no se encontró el elemento llamado «%s».\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Guardar la representación xml del conducto a un ARCHIVO y salir" + +#~ msgid "FILE" +#~ msgstr "ARCHIVO" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "No instalar los manejadores de señales para SIGUSR1 y SIGUSR2" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Error al volver a escanear el registro %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Error al volver a escanear el registro %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Error interno de GStreamer: falló el cambio de estado." + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Error al escribir el descriptor del archivo «%d»." + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "El descriptor del archivo «%d» no es válido." + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "LIBERANDO el conducto ...\n" + +#~ msgid "original location of file as a URI" +#~ msgstr "ubicación original del archivo como URI" diff --git a/po/eu.gmo b/po/eu.gmo new file mode 100644 index 0000000..714dfbc Binary files /dev/null and b/po/eu.gmo differ diff --git a/po/eu.po b/po/eu.po new file mode 100644 index 0000000..3db0fad --- /dev/null +++ b/po/eu.po @@ -0,0 +1,1399 @@ +# translation of gstreamer.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 gstreamer package. +# +# Iñaki Larrañaga Murgoitio , 2009, 2010. +# Mikel Olasagasti Uranga , 2009, 2010. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-0.10.26.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-03-25 13:10+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" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: KBabel 1.11.4\n" + +msgid "Print the GStreamer version" +msgstr "Erakutsi GStreamer-en bertsioa" + +msgid "Make all warnings fatal" +msgstr "Bihurtu abisu guztiak errore larri" + +msgid "Print available debug categories and exit" +msgstr "Erakutsi arazte-kategoria erabilgarriak, eta irten" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Arazte-maila lehenetsia, 1etik (soilik erroreak) 5era (dena), edo 0 " +"(irteerarik ez)" + +msgid "LEVEL" +msgstr "MAILA" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Kategoria bakoitzari maila jakin bat ezartzeko, erabili komaz bereizitako " +"kategoriaren_izena:maila pareen zerrenda. Adibidea: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "ZERRENDA" + +msgid "Disable colored debugging output" +msgstr "Desgaitu koloreak arazketako irteeretan" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Desgaitu arazketa" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Gaitu pluginen kargatze-diagnostiko xehatua" + +msgid "Colon-separated paths containing plugins" +msgstr "Pluginak dituzten bide-izenak, bi punturekin bereizita" + +msgid "PATHS" +msgstr "BIDE-IZENAK" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Aurrez kargatzeko pluginen zerrenda komaz bereizita, GST_PLUGIN_PATH " +"ingurumen-aldagaian gordetako zerrendaz gain" + +msgid "PLUGINS" +msgstr "PLUGINAK" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Desgaitu segmentazio-hutsegiteen tranpak pluginak kargatzen diren bitartean" + +msgid "Disable updating the registry" +msgstr "Desgaitu erregistroa eguneratzea" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Desgaitu prozesu laguntzailea abiaraztea erregistroa eskaneatzen den " +"bitartean" + +msgid "GStreamer Options" +msgstr "GStreamer-en aukerak" + +msgid "Show GStreamer Options" +msgstr "Erakutsi GStreamer-en aukerak" + +msgid "Unknown option" +msgstr "Aukera ezezaguna" + +msgid "GStreamer encountered a general core library error." +msgstr "Nukleo-liburutegiaren errore orokorra topatu du GStreamer-ek" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer-en garatzaileak alferregiak ziren errore honi errore-kode bat " +"esleitzeko." + +msgid "Internal GStreamer error: code not implemented." +msgstr "GStreamer-en barne-errorea: kodea ez dago inplementatua." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer-en barne-errorea: egoeraren aldaketak huts egin du eta elementu " +"batzuk huts egin dute dagokion hutsegitearen berri ematen duen errorearen " +"mezua igortzean." + +msgid "Internal GStreamer error: pad problem." +msgstr "GStreamer-en barne-errorea: betegarri-arazoa." + +msgid "Internal GStreamer error: thread problem." +msgstr "GStreamer-en barne-errorea: hari-arazoa." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer-en barne-errorea: negoziazio-arazoa." + +msgid "Internal GStreamer error: event problem." +msgstr "GStreamer-en barne-errorea: gertaera-arazoa." + +msgid "Internal GStreamer error: seek problem." +msgstr "GStreamer-en barne-errorea: bilaketa-arazoa." + +msgid "Internal GStreamer error: caps problem." +msgstr "GStreamer-en barne-errorea: ahalmen-arazoa." + +msgid "Internal GStreamer error: tag problem." +msgstr "GStreamer-en barne-errorea: etiketa-arazoa." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "GStreamer-en instalazioari plugin bat falta zaio." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "GStreamer-en barne-errorea: erloju-arazoa." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"GStreamer-en funtzionalitate desgaitu bat erabiltzen saiatzen ari da " +"aplikazio hau." + +msgid "GStreamer encountered a general supporting library error." +msgstr "Euskarri-liburutegiaren errore orokorra topatu du GStreamer-ek." + +msgid "Could not initialize supporting library." +msgstr "Ezin izan da euskarri-liburutegia hasieratu." + +msgid "Could not close supporting library." +msgstr "Ezin izan da euskarri-liburutegia itxi." + +msgid "Could not configure supporting library." +msgstr "Ezin izan da euskarri-liburutegia konfiguratu." + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "Baliabide-errore orokorra topatu du GStreamer-ek." + +msgid "Resource not found." +msgstr "Ez da baliabidea aurkitu." + +msgid "Resource busy or not available." +msgstr "Baliabidea lanpetua dago edo ez dago erabilgarri." + +msgid "Could not open resource for reading." +msgstr "Ezin izan da baliabidea ireki irakurtzeko." + +msgid "Could not open resource for writing." +msgstr "Ezin izan da baliabidea ireki idazteko." + +msgid "Could not open resource for reading and writing." +msgstr "Ezin izan da baliabidea ireki irakurtzeko eta idazteko." + +msgid "Could not close resource." +msgstr "Ezin izan da baliabidea itxi." + +msgid "Could not read from resource." +msgstr "Ezin izan da baliabidea irakurri." + +msgid "Could not write to resource." +msgstr "Ezin izan da baliabidean idatzi." + +msgid "Could not perform seek on resource." +msgstr "Ezin izan da bilaketa egin baliabidean." + +msgid "Could not synchronize on resource." +msgstr "Ezin izan da baliabidean sinkronizatu." + +msgid "Could not get/set settings from/on resource." +msgstr "Ezin izan dira ezarpenak eskuratu/ezarri baliabidetik/baliabidean." + +msgid "No space left on the resource." +msgstr "Ez da lekurik geratzen baliabidean." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Ez da lekurik geratzen baliabidean." + +msgid "GStreamer encountered a general stream error." +msgstr "Korronte-errore orokorra topatu du GStreamer-ek." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementuak ez du korronte horren maneiatzailerik inplementatzen. Egin " +"errorearen txostena." + +msgid "Could not determine type of stream." +msgstr "Ezin izan da korronte mota zehaztu." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Korronte hori ez da elementu honek maneiatzen dituen korronteen mota berekoa." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Ez dago korronte mota hori maneia dezakeen kodek erabilgarririk." + +msgid "Could not decode stream." +msgstr "Ezin izan da korrontea deskodetu." + +msgid "Could not encode stream." +msgstr "Ezin izan da korrontea kodetu." + +msgid "Could not demultiplex stream." +msgstr "Ezin izan da korrontea demultiplexatu." + +msgid "Could not multiplex stream." +msgstr "Ezin izan da korrontea multiplexatu." + +msgid "The stream is in the wrong format." +msgstr "Korrontearen formatua ez da zuzena." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Korrontea enkriptatuta dago eta desenkriptatzea ez dago onartuta." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Korrontea enkriptatuta dago eta ezin da desenkriptatu, ez baita gako " +"egokirik eman." + +#, c-format +msgid "No error message for domain %s." +msgstr "Ez dago errore-mezurik %s domeinuarentzat." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Ez dago errore-mezu estandarrik %s domeinua eta %d kodea dutenentzat." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Hautatutako erlojua ezin da kanalizazioan erabili." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "izenburua" + +msgid "commonly used title" +msgstr "normalean erabiltzen den izenburua" + +msgid "title sortname" +msgstr "tituluarekiko ordenatu" + +msgid "commonly used title for sorting purposes" +msgstr "tituluaren arabera ordenatzea" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "grabazioaren arduraduna(k)" + +msgid "artist sortname" +msgstr "artistarekiko ordenatu" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "grabazioaren arduradunekiko ordenatzea" + +msgid "album" +msgstr "albuma" + +msgid "album containing this data" +msgstr "datu hauek dituen albuma" + +msgid "album sortname" +msgstr "albumarekiko ordenatu" + +msgid "album containing this data for sorting purposes" +msgstr "datu hauek dituen albumarekiko ordenatzeko" + +msgid "album artist" +msgstr "albuma artista" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Album osoko artista, bistaratu beharko litzatekeen bezala" + +msgid "album artist sortname" +msgstr "albuma artistarekiko ordenatu" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Album osoko artistaren arabera ordenatzea" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "datuak (GDate egitura gisa) sortu zireneko data" + +#, fuzzy +msgid "datetime" +msgstr "data" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "datuak (GDate egitura gisa) sortu zireneko data" + +msgid "genre" +msgstr "generoa" + +msgid "genre this data belongs to" +msgstr "datu horiek zer generotakoak diren" + +msgid "comment" +msgstr "iruzkina" + +msgid "free text commenting the data" +msgstr "datuei buruzko iruzkina (testu librea)" + +msgid "extended comment" +msgstr "iruzkin hedatua" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"datuen iruzkina duen testu librea, gakoa=balioa edo key[en]=iruzkina formakoa" + +msgid "track number" +msgstr "pista-zenbakia" + +msgid "track number inside a collection" +msgstr "pista-zenbakia, bilduma batean" + +msgid "track count" +msgstr "pista-kopurua" + +msgid "count of tracks inside collection this track belongs to" +msgstr "pista-kopurua, pista hori daukan bilduman" + +msgid "disc number" +msgstr "disko-zenbakia" + +msgid "disc number inside a collection" +msgstr "disko-zenbakia, bilduma batean" + +msgid "disc count" +msgstr "disko-kopurua" + +msgid "count of discs inside collection this disc belongs to" +msgstr "disko-kopurua, disko hori daukan bilduman" + +msgid "location" +msgstr "kokalekua" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Multimediaren jatorria URI gisa (jatorriko fitxategia edo korrontea dagoen " +"kokalekua)" + +msgid "homepage" +msgstr "orrialde nagusia" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Multimedia honen orrialde nagusia (adib. artistaren edo filmaren webgunea)" + +msgid "description" +msgstr "deskribapena" + +msgid "short text describing the content of the data" +msgstr "datuen edukia deskribatzen duen testu laburra" + +msgid "version" +msgstr "bertsioa" + +msgid "version of this data" +msgstr "datu horien bertsioa" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Nazioarteko estandarrean oinarritutako grabatze-kodea (ISRC) - ikus http://" +"www.ifpi.org/isrc/" + +msgid "organization" +msgstr "erakundea" + +msgid "copyright" +msgstr "copyrighta" + +msgid "copyright notice of the data" +msgstr "datuen egile-eskubideei buruzko informazioa" + +msgid "copyright uri" +msgstr "copyrightaren URIa" + +msgid "URI to the copyright notice of the data" +msgstr "datuen egile-eskubideei buruzko informazioa atzitzeko URIa" + +#, fuzzy +msgid "encoded by" +msgstr "kodetzailea" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "kontaktua" + +msgid "contact information" +msgstr "kontaktuari buruzko informazioa" + +msgid "license" +msgstr "lizentzia" + +msgid "license of data" +msgstr "datuen lizentzia" + +msgid "license uri" +msgstr "lizentziaren URIa" + +msgid "URI to the license of the data" +msgstr "datuen lizentzia atzitzeko URIa" + +msgid "performer" +msgstr "interpretea" + +msgid "person(s) performing" +msgstr "interpretatzen ari d(ir)ena(k)" + +msgid "composer" +msgstr "konpositorea" + +msgid "person(s) who composed the recording" +msgstr "grabazioa konposatu zuen arduraduna" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "iraupena" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "iraupena GStreamer-en denbora-unitateetan (nanosegundoak)" + +msgid "codec" +msgstr "kodeka" + +msgid "codec the data is stored in" +msgstr "datuak zer kodeketan gordeak dauden" + +msgid "video codec" +msgstr "bideo-kodeka" + +msgid "codec the video data is stored in" +msgstr "bideo-datuak zer kodeketan gordeak dauden" + +msgid "audio codec" +msgstr "audio-kodeka" + +msgid "codec the audio data is stored in" +msgstr "audio-datuak zer kodeketan gordeak dauden" + +msgid "subtitle codec" +msgstr "azpitituluaren kodeka" + +msgid "codec the subtitle data is stored in" +msgstr "azpitituluak zer kodeketan gordeak dauden" + +msgid "container format" +msgstr "ontziaren formatua" + +msgid "container format the data is stored in" +msgstr "datuak zein ontzi formatuan gordeak dauden" + +msgid "bitrate" +msgstr "bit-emaria" + +msgid "exact or average bitrate in bits/s" +msgstr "bit-emari zehatza edo batez bestekoa (bit/s)" + +msgid "nominal bitrate" +msgstr "bit-emari izendatua" + +msgid "nominal bitrate in bits/s" +msgstr "bit-emari izendatua (bit/s)" + +msgid "minimum bitrate" +msgstr "gutxieneko bit-emaria" + +msgid "minimum bitrate in bits/s" +msgstr "gutxieneko bit-emari izendatua (bit/s)" + +msgid "maximum bitrate" +msgstr "gehienezko bit-emaria" + +msgid "maximum bitrate in bits/s" +msgstr "gehienezko bit-emaria (bit/s)" + +msgid "encoder" +msgstr "kodetzailea" + +msgid "encoder used to encode this stream" +msgstr "korronte hau kodetzeko erabili den kodetzailea" + +msgid "encoder version" +msgstr "kodetzailearen bertsioa" + +msgid "version of the encoder used to encode this stream" +msgstr "korronte hau kodetzeko erabili den kodetzailearen bertsioa" + +msgid "serial" +msgstr "seriekoa" + +msgid "serial number of track" +msgstr "pistaren serie-zenbakia" + +msgid "replaygain track gain" +msgstr "replaygain pista-irabazia" + +msgid "track gain in db" +msgstr "pista-irabazia (db)" + +msgid "replaygain track peak" +msgstr "replaygain pista-gailurra" + +msgid "peak of the track" +msgstr "pistaren gailurra" + +msgid "replaygain album gain" +msgstr "replaygain album-irabazia" + +msgid "album gain in db" +msgstr "album-irabazia (db)" + +msgid "replaygain album peak" +msgstr "replaygain album-gailurra" + +msgid "peak of the album" +msgstr "albumaren gailurra" + +msgid "replaygain reference level" +msgstr "replaygain erreferentzia-maila" + +msgid "reference level of track and album gain values" +msgstr "pistaren eta albumaren irabazi-balioen erreferentzia-maila" + +msgid "language code" +msgstr "hizkuntza-kodea" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "korronte honen hizkuntza-kodea, ISO-639-1en arabera" + +#, fuzzy +msgid "language name" +msgstr "hizkuntza-kodea" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "irudia" + +msgid "image related to this stream" +msgstr "korronte honi lotutako irudia" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "aurrebista-irudia" + +msgid "preview image related to this stream" +msgstr "korronte honi lotutako aurrebista-irudia" + +msgid "attachment" +msgstr "eranskina" + +msgid "file attached to this stream" +msgstr "korronte honi erantsitako fitxategia" + +msgid "beats per minute" +msgstr "golpe minutuko" + +msgid "number of beats per minute in audio" +msgstr "minutuko golpe kopurua, audioan" + +msgid "keywords" +msgstr "gako-hitzak" + +msgid "comma separated keywords describing the content" +msgstr "edukia deskribatzen duten komaz bereiztutako gako-hitzak" + +msgid "geo location name" +msgstr "geolokalizazioaren izena" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"multimedia grabatu edo ekoiztu den kokalekuaren azalpena gizakiok irakurtzeko" + +msgid "geo location latitude" +msgstr "geolokalizazioaren latitudea" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"multimedia grabatu edo ekoiztu den lekuaren geolokalizazioaren latitudea " +"gradutan WGS84 estandarraren arabera (zero ekuatorea da, balio negatiboak " +"hegoaldeko latitudeak dira)" + +msgid "geo location longitude" +msgstr "geolokalizazioaren longitudea" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"multimedia grabatu edo ekoiztu den lekuaren geolokalizazioaren longitudea " +"gradutan WGS84 estandarraren arabera (zero meridiano nagusia da Britainia " +"Handiko Greenwich-en, balio negatiboak mendebaldeko longitudeak dira)" + +msgid "geo location elevation" +msgstr "geolokalizazioaren altitudea" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"multimedia grabatu edo ekoiztu den lekuaren geolokalizazioaren altitudea " +"metrotan WGS84 estandarraren arabera (zero batez besteko itsasoaren maila da)" + +msgid "geo location country" +msgstr "geolokalizazioaren estatua" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "muldimedia grabatu edo ekoiztu den estatua (ingelesezko izena)" + +msgid "geo location city" +msgstr "geolokalizazioaren herria" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "muldimedia grabatu edo ekoiztu den herria (ingelesezko izena)" + +msgid "geo location sublocation" +msgstr "geolokalizazioaren azpikokalekua" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "muldimedia grabatu edo ekoiztu den herriko kokaleku bat (adib, auzoa)" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "geolokalizazioaren izena" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "geolokalizazioaren longitudea" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "geolokalizazioaren altitudea" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "geolokalizazioaren altitudea" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "ikuskizunaren izena" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Tb/podcast/serieen ikuskizunaren izena" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "ikuskizunaren ordenatze-izena" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Tb/podcast/serieen ikuskizunaren izena, ordenatzeko helburuarekin" + +msgid "episode number" +msgstr "pasartearen zenbakia" + +msgid "The episode number in the season the media is part of" +msgstr "Denboraldiko pasartearen zenbakia" + +msgid "season number" +msgstr "denboraldiaren zenbakia" + +msgid "The season number of the show the media is part of" +msgstr "Ikuskizunaren denboraldiaren zenbakia" + +msgid "lyrics" +msgstr "lirika" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Multimediaren lirika, batik bat abestietan erabilita" + +msgid "composer sortname" +msgstr "konpositorearen ordenatze-izena" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "grabazioaren konposatu zuten pertsonak, ordenatzeko helburuarekin" + +msgid "grouping" +msgstr "taldekatzea" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Zerikusia dituzten pistak elkartzen ditu, kontzertu bateko zati desberdinak " +"bezala. Pista bat baino gehiago da, baina ez da iristen album baten tamainara" + +msgid "user rating" +msgstr "erabiltzailearen balorazioa" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Erabiltzaile batek emandako balorazioa. Puntuazioa zenbat eta altuagoa izan, " +"are eta gehiago atsegin zaio erabiltzaileari multimedia hau" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "korronte hau kodetzeko erabili den kodetzailearen bertsioa" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "korronte hau kodetzeko erabili den kodetzailearen bertsioa" + +#, fuzzy +msgid "application name" +msgstr "geolokalizazioaren izena" + +#, fuzzy +msgid "Application used to create the media" +msgstr "korronte hau kodetzeko erabili den kodetzailearen bertsioa" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERROREA: %s elementuarena: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Arazketa-informazio gehigarria:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "ez dago \"%s\" propietaterik \"%s\" elementuan" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" +"ezin izan da ezarri \"%2$s\" elementuko \"%1$s\" propietatea honela: \"%3$s\"" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "ezin izan da %s estekatu hona: %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "ezin izan da kolektore-elementua estekatu \"%s\" URIarentzat" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "ezin izan da %s estekatu hona: %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "ezin izan da %s estekatu hona: %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "ez dago \"%s\" elementua" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "ezin izan da \"%s\" edukiera analizatu" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "ez da kolektore-elementurik ezarri \"%s\" URIarentzat" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "ez da iturburu-elementurik ezarri \"%s\" URIarentzat" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "\"%s\" zehaztutako ontzi hutsa, ez da onartzen" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "ez dago \"%s\" ontzirik, saltatzen" + +msgid "empty pipeline not allowed" +msgstr "ez dira onartzen kanalizazio hutsak" + +msgid "A lot of buffers are being dropped." +msgstr "Buffer asko jaregiten ari dira." + +msgid "Internal data flow problem." +msgstr "Datu-fluxuaren barne-arazoa." + +msgid "Internal data flow error." +msgstr "Datu-fluxuaren barne-errorea." + +msgid "Internal clock error." +msgstr "Erlojuaren barne-errorea." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Iragazpen-ahalmena" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Mugatu onar daitezkeen ahalmenak (NULLek EDOZER adierazten du). Propietate " +"hori ezartzen bada, emandako GstCaps objektuaren erreferentzia hartzen du." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Ez da aldi baterako direktoriorik zehaztu." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Ezin izan da \"%s\" aldi baterako fitxategia sortu." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Ezin izan da \"%s\" fitxategia ireki irakurtzeko." + +#, fuzzy +msgid "Error while writing to download file." +msgstr "Errorea gertatu da \"%s\" fitxategian idaztean." + +msgid "No file name specified for writing." +msgstr "Ez da fitxategi-izenik zehaztu idazteko." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Ezin izan da \"%s\" fitxategia ireki idazteko." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Errorea gertatu da \"%s\" fitxategia ixtean." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Errorea gertatu da \"%s\" fitxategian bilaketa egitean." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Errorea gertatu da \"%s\" fitxategian idaztean." + +msgid "No file name specified for reading." +msgstr "Ez da fitxategi-izenik zehaztu irakurtzeko." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Ezin izan da \"%s\"(e)ko informazioa eskuratu." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" direktorioa da." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "\"%s\" fitxategia socket-a da." + +msgid "Failed after iterations as requested." +msgstr "Huts egin du eskatutako iterazioak egin ondoren." + +msgid "caps" +msgstr "ahalmenak" + +msgid "detected capabilities in stream" +msgstr "ahalmenak detektatu dira korrontean" + +msgid "minimum" +msgstr "gutxienekoa" + +msgid "force caps" +msgstr "derrigortu gaitasunak" + +msgid "force caps without doing a typefind" +msgstr "derrigortu gaitasunak motaren bilaketa landu gabe" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Korronteak ez du daturik." + +msgid "Stream contains no data." +msgstr "Korronteak ez du daturik." + +msgid "Implemented Interfaces:\n" +msgstr "Inplementatutako interfazeak:\n" + +msgid "readable" +msgstr "irakur daitekeena" + +msgid "writable" +msgstr "idatz daitekeena" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "kontrola daitekeena" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "Zerrenda beltzeko fitxategiak:" + +msgid "Total count: " +msgstr "Kopuru osoa: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "zerrenda beltzeko fitxategi %d" +msgstr[1] "zerrenda beltzeko %d fitxategi" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugin" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "zerrenda beltzeko sarrera %d" +msgstr[1] "zerrenda beltzeko %d sarrera" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d eginbide" +msgstr[1] "%d eginbide" + +msgid "Print all elements" +msgstr "Inprimatu elementu guztiak" + +msgid "Print list of blacklisted files" +msgstr "Erakutsi zerrenda beltzeko fitxategien zerrenda" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Erakutsi zehaztutako pluginaren eginbide-zerrenda, makina batek analizatzeko " +"modukoa.\n" +" Baliagarria da kanpoko pluginak " +"automatikoki instalatzeko mekanismoen konexioetan" + +msgid "List the plugin contents" +msgstr "Zerrendatu pluginen edukiak" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Erakutsi onartutako URI eskemak, haiek inplementatzen dituzten elementuekin" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Ezin izan da plugin fitxategia kargatu: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "'%s' elementua edo plugina ez da existitzen\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "\"%2$s\" (%3$s) elementuaren %1$u. mezua jaso da: " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "\"%2$s:%3$s\" (%4$s) plataformaren %1$u. mezua jaso da: " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "\"%2$s\" (%3$s) objektuaren %1$u. mezua jaso da: " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "%u. (%s) mezua jaso da: " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "\"%s\" elementuaren EOS bat jaso da.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETIKETA AURKITU DA: \"%s\" elementuak aurkitu du.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ETIKETA AURKITU DA: \"%s:%s\" plataformak aurkitu du.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETIKETA AURKITU DA: \"%s\" objektuak aurkitu du.\n" + +msgid "FOUND TAG\n" +msgstr "ETIKETA AURKITU DA\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ETIKETA AURKITU DA: \"%s\" elementuak aurkitu du.\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ETIKETA AURKITU DA: \"%s\" objektuak aurkitu du.\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "ETIKETA AURKITU DA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMAZIOA:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ABISUA, %s elementuarena: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Prestatu da; bufferreratzen bukatu zain...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Prestatu da; bufferreratzen bukatu zain...\n" + +msgid "buffering..." +msgstr "bufferreratzen..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Bufferreratu da; kanalizazioaren ezarpena ERREPRODUZITZEA gisa jartzen... \n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Bufferreratzen; kanalizazioa PAUSARAZIA gisa ezartzen... \n" + +msgid "Redistribute latency...\n" +msgstr "Latentzia birbanatzen...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Egoera %s(e)ra ezartzen %s(e)k eskatu bezala...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Eten: Kanalizazioa gelditzen... \n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "ez dago \"%s\" elementua" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ABISUA, %s elementuarena: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Erakutsi etiketak (metadatu gisa ere ezagutzen direnak)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Erakutsi egoerari buruzko informazioa eta propietateen jakinarazpenak" + +msgid "Do not print any progress information" +msgstr "Ez erakutsi inolako jarraipenen informaziorik" + +msgid "Output messages" +msgstr "Erakutsi mezuak" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Ez instalatu akats-maneiatzailerik" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Derrigortu EOS iturburuetan kanalizazioa itzali aurretik" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERROREA: ezin izan da kanalizazioa eraiki: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERROREA: ezin izan da kanalizazioa eraiki.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ABISUA, kanalizazio akastuna: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERROREA: ezin izan da 'kanalizazio' elementua aurkitu.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Kanalizazioa PAUSARAZIA gisa ezartzen... \n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROREA: ezin da kanalizazioa pausarazi.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Kanalizazioa aktibo dago eta ez du PRESTATU beharrik...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Kanalizazioa PRESTATZEN ari da... \n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERROREA: ezin da kanalizazioa prestatu.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Kanalizazioa PRESTATUA dago... \n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Kanalizazioa ERREPRODUZITZEA gisa ezartzen... \n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERROREA: ezin da kanalizazioa erreproduzitu.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS itzaltzean gaituta -- EOS derrigortzen kanalizazioan\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS itzaltzean gaituta -- EOS derrigortzen kanalizazioan\n" + +msgid "Waiting for EOS...\n" +msgstr "EOSren zain...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOSa jasota - kanalizazioa gelditzen...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Eten: Kanalizazioa gelditzen... \n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Errorea gertatu da EOSren zain egotean\n" + +msgid "Execution ended after %" +msgstr "Erreprodukzioa amaitu egin da %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Kanalizazioa PREST gisa ezartzen... \n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Kanalizazioa NULUA gisa ezartzen... \n" + +msgid "Freeing pipeline ...\n" +msgstr "Kanalizazioa askatzen...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Datu-korrontearen barne-errorea." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Ez erakutsi MOTA hauetako egoera-informazioa:" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "1.MOTA, 2.MOTA..." + +#~ msgid "link without source element" +#~ msgstr "iturburu-elementurik gabeko esteka" + +#~ msgid "link without sink element" +#~ msgstr "kolektore-elementurik gabeko esteka" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "ez dago elementurik \"%s\" URIa hona estekatzeko:" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Inprimatu esleipenen segimendua (konpilatzean gaitu bada)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Erabilera: gst-xmllaunch [ elementua." +#~ "propietatea=balioa... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERROREA: huts egin du '%s' xml fitxategia analizatzean.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERROREA: ez dago goi-mailako kanalizazio-elementurik '%s' fitxategian.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "KONTUZ: goi-mailako elementu bat bakarra onartzen da oraingoan.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERROREA: ezin izan da komando-lerroko %d. argumentua analizatu: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "KONTUZ: ez da aurkitu '%s' izeneko elementua.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Gorde kanalizazioen xml adierazpena FITXATEGIan eta irten" + +#~ msgid "FILE" +#~ msgstr "FITXATEGIA" + +#, fuzzy +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Ez instalatu akats-maneiatzailerik" diff --git a/po/fi.gmo b/po/fi.gmo new file mode 100644 index 0000000..3741aa4 Binary files /dev/null and b/po/fi.gmo differ diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 0000000..1f869e6 --- /dev/null +++ b/po/fi.po @@ -0,0 +1,1472 @@ +# Finnish translations for gstreamer package. +# Copyright (C) 2005, 2007-2008 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Tommi Vainikainen , 2005, 2007-2010. +# +# Words: +# +# bin (a container element) = säiliö +# sink = nielu +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-11-17 23:10+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 "Print the GStreamer version" +msgstr "Näytä GStreamerin versio" + +msgid "Make all warnings fatal" +msgstr "Tee kaikista varoituksista vakavia" + +msgid "Print available debug categories and exit" +msgstr "Tulosta saatavilla olevat vianetsintäluokat ja poistu" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Oletusvianetsintätaso väliltä 1:stä (vain virheet) 5:een (kaikki) tai 0 ei " +"tulostetta" + +msgid "LEVEL" +msgstr "TASO" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Pilkuin eroteltu luettelo luokkanimi:taso-pareista, joilla asetetaan tietyt " +"tasot yksittäisille luokille. Esimerkki: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LUETTELO" + +msgid "Disable colored debugging output" +msgstr "Ei väritettyjä vianetsintätietoja" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Ei vianetsintää" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Käytä monisanaista liitännäisten latausdiagnostiikka" + +msgid "Colon-separated paths containing plugins" +msgstr "Kaksoispistein erotellut polut liitännäisiin" + +msgid "PATHS" +msgstr "POLUT" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Pilkuin eroteltu luettelo liitännäisistä, jotka esiladataan " +"ympäristömuuttujassa GST_PLUGIN_PATH lueteltujen lisäksi" + +msgid "PLUGINS" +msgstr "LIITÄNNÄISET" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Ei muistialueen ylityksen tarkkailua liitännäisten latauksen aikana" + +msgid "Disable updating the registry" +msgstr "Älä päivitä rekisteriä" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Älä käynnistä apuprosessia rekisterin skannauksessa" + +msgid "GStreamer Options" +msgstr "GStreamerin valitsimet" + +msgid "Show GStreamer Options" +msgstr "Näytä GStreamerin valitsimet" + +msgid "Unknown option" +msgstr "Tuntematon valitsin" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer kohtasi virheen yleisessä ydinkirjastossa." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer-kehittäjät olivat liian laiskoja antaakseen tälle virheelle omaa " +"virhekoodia." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Sisäinen GStreamer-virhe: koodia ei toteutettu." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Gstreamer-virhe: tilasiirtymä epäonnistui ja jokin elementti ei onnistunut " +"ilmoittamaan kunnollista virheilmoitusta epäonnistumisen syyksi." + +msgid "Internal GStreamer error: pad problem." +msgstr "Sisäinen GStreamer-virhe: täyteongelma." + +msgid "Internal GStreamer error: thread problem." +msgstr "Sisäinen GStreamer-virhe: säieongelma." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Sisäinen GStreamer-virhe: neuvotteluongelma." + +msgid "Internal GStreamer error: event problem." +msgstr "Sisäinen GStreamer-virhe: tapahtumaongelma." + +msgid "Internal GStreamer error: seek problem." +msgstr "Sisäinen GStreamer-virhe: kelausongelma." + +msgid "Internal GStreamer error: caps problem." +msgstr "Sisäinen GStreamer-virhe: täyteongelma." + +msgid "Internal GStreamer error: tag problem." +msgstr "Sisäinen GStreamer-virhe: merkintäongelma." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "GStreamer-asennuksesta puuttuu liitännäinen." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Sisäinen GStreamer-virhe: kello-ongelma." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Tämä sovellus yrittää käyttää sellaista GStreamerin toiminnallisuutta, joka " +"on poissa käytöstä." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer kohtasi virheen yleisessä tukikirjastossa." + +msgid "Could not initialize supporting library." +msgstr "Tukikirjastoa ei voitu alustaa." + +msgid "Could not close supporting library." +msgstr "Tukikirjastoa ei voitu sulkea." + +msgid "Could not configure supporting library." +msgstr "Tukikirjastoa ei voitu konfiguroida." + +msgid "Encoding error." +msgstr "Koodausvirhe." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer kohtasi yleisen resurssivirheen." + +msgid "Resource not found." +msgstr "Resurssia ei löytynyt." + +msgid "Resource busy or not available." +msgstr "Resurssi on varattu tai ei saatavilla." + +msgid "Could not open resource for reading." +msgstr "Resurssia ei voitu avata lukemista varten." + +msgid "Could not open resource for writing." +msgstr "Resurssia ei voitu avata kirjoittamista varten." + +msgid "Could not open resource for reading and writing." +msgstr "Resurssia ei voitu avata lukemista ja kirjoittamista varten." + +msgid "Could not close resource." +msgstr "Resurssia ei voitu sulkea." + +msgid "Could not read from resource." +msgstr "Resurssista ei voitu lukea." + +msgid "Could not write to resource." +msgstr "Resurssiin ei voitu kirjoittaa." + +msgid "Could not perform seek on resource." +msgstr "Resurssia ei voitu kelata." + +msgid "Could not synchronize on resource." +msgstr "Resurssia ei voitu synkronisoida." + +msgid "Could not get/set settings from/on resource." +msgstr "Resurssin asetuksia ei saatu/voitu asettaa." + +msgid "No space left on the resource." +msgstr "Resurssilla ei ole tilaa jäljellä." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Resurssilla ei ole tilaa jäljellä." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer kohtasi yleisen tietovirtavirheen." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Elementti ei toteuta tämän tietovirran käsittelyä. Tee vikailmoitus." + +msgid "Could not determine type of stream." +msgstr "Tietovirran tyyppiä ei voitu määrittää." + +msgid "The stream is of a different type than handled by this element." +msgstr "Tietovirta on eri tyyppiä kuin mitä tämä elementti käsittelee." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Saatavilla ei ole koodekkia, joka osaa käsitellä tämän tyyppistä tietovirtaa." + +msgid "Could not decode stream." +msgstr "Tietovirtaa ei voitu purkaa." + +msgid "Could not encode stream." +msgstr "Tietovirtaa ei voitu koodata." + +msgid "Could not demultiplex stream." +msgstr "Tietovirran kanavointia ei voitu purkaa." + +msgid "Could not multiplex stream." +msgstr "Tietovirtaa ei voitu kanavoida." + +msgid "The stream is in the wrong format." +msgstr "Virta on väärässä muodossa." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Virta on salattu ja salauksen purkua ei tueta." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Virta on salattu ja salausta ei voida purkaa, koska sopivaa avainta ei ole " +"annettu." + +#, c-format +msgid "No error message for domain %s." +msgstr "Virheviestiä alueelle %s ei ole." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Standardia virheviestiä alueelle %s ja koodille %d ei ole." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Valittua kelloa ei voi käyttää liukuhihnassa." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Virhe kirjoitettaessa rekisterivälimuistia kohteeseen %s: %s" + +msgid "title" +msgstr "nimi" + +msgid "commonly used title" +msgstr "yleensä käytetty nimi" + +msgid "title sortname" +msgstr "nimi lajitteluun" + +msgid "commonly used title for sorting purposes" +msgstr "yleensä käytetty nimi lajittelua varten" + +msgid "artist" +msgstr "esittäjä" + +msgid "person(s) responsible for the recording" +msgstr "nauhoituksesta vastuussa oleva(t) henkilö(t)" + +msgid "artist sortname" +msgstr "esittäjä lajitteluun" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "nauhoituksesta vastuussa oleva(t) henkilö(t) lajittelua varten" + +msgid "album" +msgstr "levy" + +msgid "album containing this data" +msgstr "levy, joka sisältää tämän datan" + +msgid "album sortname" +msgstr "levy lajitteluun" + +msgid "album containing this data for sorting purposes" +msgstr "levy, joka sisältää tämän datan, lajittelua varten" + +msgid "album artist" +msgstr "levyn esittäjä" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Koko levyn esittäjä sellaisena kuin se tulisi näyttää" + +msgid "album artist sortname" +msgstr "levyn esittäjä lajitteluun" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Koko levyn esittäjä sellaisena kuin sitä tulisi käyttää lajitteluun" + +msgid "date" +msgstr "päiväys" + +msgid "date the data was created (as a GDate structure)" +msgstr "päiväys, jolloin data luotiin (GDate-muodossa)" + +msgid "datetime" +msgstr "päiväysaika" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "päiväys ja aika, jolloin data luotiin (GstDateTime-muodossa)" + +msgid "genre" +msgstr "laji" + +msgid "genre this data belongs to" +msgstr "laji, johon tämä data kuuluu" + +msgid "comment" +msgstr "kommentti" + +msgid "free text commenting the data" +msgstr "vapaa kommenttiteksti datalle" + +msgid "extended comment" +msgstr "laajennettu kommentti" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"vapaa kommenttiteksti datalle muodossa avain=arvo tai avain[fi]=kommentti" + +msgid "track number" +msgstr "raidan numero" + +msgid "track number inside a collection" +msgstr "raidan numero kokoelman sisällä" + +msgid "track count" +msgstr "raitojen määrä" + +msgid "count of tracks inside collection this track belongs to" +msgstr "tähän kokoelmaan kuuluvien raitojen lukumäärä" + +msgid "disc number" +msgstr "levynumero" + +msgid "disc number inside a collection" +msgstr "levynumero kokoelman sisällä" + +msgid "disc count" +msgstr "levymäärä" + +msgid "count of discs inside collection this disc belongs to" +msgstr "tämän levyn kokoelmaan kuuluvien levyjen lukumäärä" + +msgid "location" +msgstr "sijainti" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Median alkuperä URI-muodossa (sijainti, jossa alkuperäinen tiedosto tai " +"virta on tarjolla)" + +msgid "homepage" +msgstr "kotisivu" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Tämän median kotisivu (eism. artistin tai elokuvan kotisivu)" + +msgid "description" +msgstr "kuvaus" + +msgid "short text describing the content of the data" +msgstr "lyhyt teksti, joka kuvaa datan sisältöä" + +msgid "version" +msgstr "versio" + +msgid "version of this data" +msgstr "tämän datan versio" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Kansainvälinen standardoitu äänitekoodi ISRC - katso http://www.ifpi.org/" +"isrc/" + +msgid "organization" +msgstr "organisaatio" + +msgid "copyright" +msgstr "tekijänoikeus" + +msgid "copyright notice of the data" +msgstr "huomautus datan tekijänoikeuksista" + +msgid "copyright uri" +msgstr "tekijänoikeus-uri" + +msgid "URI to the copyright notice of the data" +msgstr "URI huomautukseen datan tekijänoikeuksista" + +#, fuzzy +msgid "encoded by" +msgstr "koodain" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "yhteystiedot" + +msgid "contact information" +msgstr "yhteystiedot" + +msgid "license" +msgstr "lisenssi" + +msgid "license of data" +msgstr "datan lisenssi" + +msgid "license uri" +msgstr "lisenssin uri" + +msgid "URI to the license of the data" +msgstr "URI datan lisenssiin" + +msgid "performer" +msgstr "esittäjä" + +msgid "person(s) performing" +msgstr "esittämässä oleva(t) henkilö(t)" + +msgid "composer" +msgstr "säveltäjä" + +msgid "person(s) who composed the recording" +msgstr "sävellyksestä vastuussa oleva(t) henkilö(t)" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "kesto" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "pituus GStreamerin aikayksikköinä (nanosekuntia)" + +msgid "codec" +msgstr "koodekki" + +msgid "codec the data is stored in" +msgstr "koodekki, jolla data on tallennettu" + +msgid "video codec" +msgstr "videokoodekki" + +msgid "codec the video data is stored in" +msgstr "koodekki, jolla videodata on tallennettu" + +msgid "audio codec" +msgstr "äänikoodekki" + +msgid "codec the audio data is stored in" +msgstr "koodekki, jolla äänidata on tallennettu" + +msgid "subtitle codec" +msgstr "tekstityskoodekki" + +msgid "codec the subtitle data is stored in" +msgstr "koodekki, jolla tekstitystiedot on tallennettu" + +msgid "container format" +msgstr "säilöntämuoto" + +msgid "container format the data is stored in" +msgstr "säilöntämuoto, jolla data on tallennettu" + +msgid "bitrate" +msgstr "bittinopeus" + +msgid "exact or average bitrate in bits/s" +msgstr "tarkka tai keskimääräinen bittinopeus [bittiä/s]" + +msgid "nominal bitrate" +msgstr "nimellinen bittinopeus" + +msgid "nominal bitrate in bits/s" +msgstr "nimellinen bittinopeus [bittiä/s]" + +msgid "minimum bitrate" +msgstr "vähimmäisbittinopeus" + +msgid "minimum bitrate in bits/s" +msgstr "vähimmäisbittinopeus [bittiä/s]" + +msgid "maximum bitrate" +msgstr "enimmäisbittinopeus" + +msgid "maximum bitrate in bits/s" +msgstr "enimmäisbittinopeus [bittiä/s]" + +msgid "encoder" +msgstr "koodain" + +msgid "encoder used to encode this stream" +msgstr "koodain, joka koodaa tämän virran" + +msgid "encoder version" +msgstr "koodaimen versio" + +msgid "version of the encoder used to encode this stream" +msgstr "tämän virran koodaamiseen käytetyn koodaimen versio" + +msgid "serial" +msgstr "sarjanumero" + +msgid "serial number of track" +msgstr "raidan sarjanumero" + +msgid "replaygain track gain" +msgstr "raidan replaygain-vahvistus" + +msgid "track gain in db" +msgstr "raidan vahvistus desibeleissä" + +msgid "replaygain track peak" +msgstr "raidan replaygain-huippu" + +msgid "peak of the track" +msgstr "raidan huippu" + +msgid "replaygain album gain" +msgstr "levyn replaygain-vahvistus" + +msgid "album gain in db" +msgstr "levyn vahvistus desibeleissä" + +msgid "replaygain album peak" +msgstr "levyn replaygain-huippu" + +msgid "peak of the album" +msgstr "levyn huippu" + +msgid "replaygain reference level" +msgstr "raidan replaygain-viitetaso" + +msgid "reference level of track and album gain values" +msgstr "viitetaso raidan ja albumin gain-arvoille" + +msgid "language code" +msgstr "kielikoodi" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "tämän virran kielikoodi ISO-639-1-standardin mukaisesti" + +#, fuzzy +msgid "language name" +msgstr "kielikoodi" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "kuva" + +msgid "image related to this stream" +msgstr "kuva, joka liittyy tähän virtaan" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "esikatselukuva" + +msgid "preview image related to this stream" +msgstr "esikatselukuva, joka liittyy tähän virtaan" + +msgid "attachment" +msgstr "liite" + +msgid "file attached to this stream" +msgstr "tiedosto, joka on liitetty tähän virtaan" + +msgid "beats per minute" +msgstr "tahtia per minuutti" + +msgid "number of beats per minute in audio" +msgstr "tahtien määrä per minuutti äänessä" + +msgid "keywords" +msgstr "avainsanat" + +msgid "comma separated keywords describing the content" +msgstr "pilkuilla erotellut avainsanat,jotka kuvaavat sisältöä" + +msgid "geo location name" +msgstr "maantietellisen sijainnin nimi" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"ihmisluettava kuvaus sijainnista tai paikasta, jossa media on nauhoitettu " +"tai tuotettu" + +msgid "geo location latitude" +msgstr "maantieteellisen sijainnin leveyspiiri" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"maantieteellinen leveyspiiri, jossa media on nauhoitettu tai tuotettu " +"asteina WGS84-koordinaatistossa (nolla on päiväntasaaja, negatiiviset arvot " +"ovat eteläisiä leveyspiirejä)" + +msgid "geo location longitude" +msgstr "maantieteellisen sijainnin pituuspiiri" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"maantieteellinen pituuspiiri, jossa media on nauhoitettu tai tuotettu " +"asteina WGS84-koordinaatistossa (nolla on nollameridiaani Greenwichissä " +"Yhdistyneessä kuningaskunnassa, negatiiviset arvot ovat läntisiä " +"pituuspiirejä)" + +msgid "geo location elevation" +msgstr "maantieteellisen sijainnin korkeustaso" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"maantietellinen korkeustaso, jossa media on nauhoitettu tai tuotettu " +"metreinä WGS84-koordinaateista (nolla on keskimääräinen merenpinta)" + +msgid "geo location country" +msgstr "maantieteellisen sijainnin maa" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "maa (englanninkielinen nimi), jossa media on nauhoitettu tai tuotettu" + +msgid "geo location city" +msgstr "maantieteellisen sijainnin kaupunki" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"kaupunki (englanninkielinen nimi), jossa media on nauhoitettu tai tuotettu" + +msgid "geo location sublocation" +msgstr "maantieteellisen sijainnin alisijainti" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "sijainti kaupungin sisällä, jossa media on nauhoitettu tai tuotettu" + +msgid "geo location horizontal error" +msgstr "maantietellisen sijainnin virhe vaakasuorassa" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "odotettu virhe paikannuksen vaakasuorassa mittauksessa (metreinä)" + +msgid "geo location movement speed" +msgstr "maantieteellisen sijainnin liikenopeus" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "nauhoittavan laitteen liikenopeus nauhoitettaessa yksikössä m/s" + +msgid "geo location movement direction" +msgstr "maantieteellisen sijainnin liikesuunta" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"ilmoittaa mediaa nauhoittavan laitteen liikesuunnan. Esitetään asteina\n" +"liukulukumuodossa, jossa 0 tarkoittaa maantieteellistä pohjoista ja\n" +"asteet kasvavat myötäpäivään" + +msgid "geo location capture direction" +msgstr "maantieteellisen sijainnin kuvaussuunta" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"ilmoittaa suunnan, johon mediaa nauhoittava laite osoittaa nauhoitettaessa. " +"Esitetään asteina liukulukumuodossa, jossa 0 tarkoittaa maantieteellistä " +"pohjoista ja asteet kasvavat myötäpäivään" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "ohjelman nimi" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "TV/podcast/sarjan ohjelman nimi, josta tämä media on lähtöisin" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "ohjelman lajittelunimi" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Lajitteluun käytettävä TV/podcast/sarjan ohjelman nimi, josta tämä media on " +"lähtöisin" + +msgid "episode number" +msgstr "episodin numero" + +msgid "The episode number in the season the media is part of" +msgstr "Episodin numero kaudella, johon tämä media kuuluu" + +msgid "season number" +msgstr "Kauden numero" + +msgid "The season number of the show the media is part of" +msgstr "Kauden numero ohjelmalle, johon tämä media kuuluu" + +msgid "lyrics" +msgstr "sanoitukset" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Median sanoitukset, yleensä käytössä lauluille" + +msgid "composer sortname" +msgstr "säveltäjän lajittelunimi" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "sävellyksestä vastuussa oleva(t) henkilö(t) lajittelua varten" + +msgid "grouping" +msgstr "ryhmittely" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Ryhmittelee toisiinsa liittyvät media, jotka koostuvat useammasta raidasta, " +"kuten konsertin eri osat. Tämä on korkeamman tason kuin raita, mutta " +"matalamman tason kuin levy" + +msgid "user rating" +msgstr "käyttäjän arvio" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Arvio käyttäjältä. Mitä suurempi sijoitus, sitä enemmän käyttäjä pitää tästä " +"mediasta" + +msgid "device manufacturer" +msgstr "laitevalmistaja" + +msgid "Manufacturer of the device used to create this media" +msgstr "Tämän median luomiseen käytetyn laitteen valmistaja" + +msgid "device model" +msgstr "laitemalli" + +msgid "Model of the device used to create this media" +msgstr "Tämän median luomiseen käytetyn laitteen malli" + +msgid "application name" +msgstr "sovelluksen nimi" + +msgid "Application used to create the media" +msgstr "Tämän median luomiseen käytetty sovellus" + +msgid "application data" +msgstr "sovellusdata" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Mielivaltainen sovellusdata joka serialisoidaan mediaan" + +msgid "image orientation" +msgstr "kuvasuunta" + +msgid "How the image should be rotated or flipped before display" +msgstr "Kuinka kuva tulisi pyöräyttää tai kääntää ympäri ennen näyttämistä" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "VIRHE: elementiltä %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Lisätietoja vianetsintään:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "ominaisuutta ”%s” ei ole elementissä ”%s”" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "elementin ”%2$s” ominaisuutta ”%1$s” ei voitu asettaa arvoon ”%3$s”" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "elementtiä %s ei voitu linkittää elementtiin %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "nieluelementtiä ei voitu linkittää URIlle ”%s”" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "elementtiä %s ei voitu linkittää elementtiin %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "elementtiä %s ei voitu linkittää elementtiin %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "ei elementtiä ”%s”" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kykyjä ”%s” ei voitu jäsentää" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "ei nieluelementtiä URIlle ”%s”" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "ei lähde-elementtiä URI:lle ”%s”" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "määritetty tyhjä säiliö ”%s”, ei sallittu" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "ei säiliötä ”%s”, ohitetaan" + +msgid "empty pipeline not allowed" +msgstr "tyhjää liukuhihnaa ei sallita" + +msgid "A lot of buffers are being dropped." +msgstr "Useita puskureita putoilee." + +msgid "Internal data flow problem." +msgstr "Sisäinen tiedon virtausongelma." + +msgid "Internal data flow error." +msgstr "Sisäinen tiedon virtausvirhe." + +msgid "Internal clock error." +msgstr "Sisäinen kellovirhe." + +#, fuzzy +msgid "Failed to map buffer." +msgstr "Kuvan koodaus epäonnistui." + +msgid "Filter caps" +msgstr "Kykysuodatus" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Rajoita mahdollisia sallittuja kykyjä (NULL tarkoittaa mitä tahansa). Tämän " +"ominaisuuden asettaminen ottaa kahvan annettuun GstCaps-olioon." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Tilapäishakemistoa ei ole määritetty." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Ei voitu luoda tilapäistiedostoa ”%s”." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Tiedostoa ”%s” ei voitu avata lukemista varten." + +msgid "Error while writing to download file." +msgstr "Virhe kirjoitettaessa lataustiedostoon." + +msgid "No file name specified for writing." +msgstr "Kirjoitusta varten ei määritetty tiedostonimeä." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Tiedostoa ”%s” ei voitu avata kirjoittamista varten." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Virhe suljettaessa tiedostoa ”%s”." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Virhe kelattaessa tiedostoa ”%s”." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Virhe kirjoitettaessa tiedostoon ”%s”." + +msgid "No file name specified for reading." +msgstr "Lukemista varten ei ole määritetty tiedostonimeä." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Ei saatu tietoja kohteesta ”%s”." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "”%s” on hakemisto." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Tiedosto ”%s” on pistoke." + +msgid "Failed after iterations as requested." +msgstr "Epäonnistui, kuten pyydettiin, yritysten jälkeen." + +msgid "caps" +msgstr "kyvyt" + +msgid "detected capabilities in stream" +msgstr "tunnistettu kyvyt virrassa" + +msgid "minimum" +msgstr "vähintään" + +msgid "force caps" +msgstr "pakota kyvyt" + +msgid "force caps without doing a typefind" +msgstr "pakota kyvyt ilman tyyppihakua" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Virta on tyhjä." + +msgid "Stream contains no data." +msgstr "Virta on tyhjä." + +msgid "Implemented Interfaces:\n" +msgstr "Toteutetut rajapinnat:\n" + +msgid "readable" +msgstr "luettavissa" + +msgid "writable" +msgstr "kirjoitettavissa" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "ohjattavissa" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "vaihdettavissa TYHJÄ-, VALMIS-, TAUOLLA- tai SOI-tiloissa" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "vaihdettavissa vain TYHJÄ-, VALMIS- tai TAUOLLA-tiloissa" + +msgid "changeable only in NULL or READY state" +msgstr "vaihdettavissa vain TYHJÄ- tai VALMIS--tiloissa" + +msgid "Blacklisted files:" +msgstr "Mustalistatut tiedostot:" + +msgid "Total count: " +msgstr "Yhteismäärä: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d mustalistattu tiedosto" +msgstr[1] "%d mustalistattua tiedostoa" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d liitännäinen" +msgstr[1] "%d liitännäistä" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d mustalistaustietue" +msgstr[1] "%d mustalistaustietuetta" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d ominaisuus" +msgstr[1] "%d ominaisuutta" + +msgid "Print all elements" +msgstr "Tulosta kaikki elementit" + +msgid "Print list of blacklisted files" +msgstr "Tulista luettelo tiedostoista mustalla listalla" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Tulosta koneluettava luettelo ominaisuuksista, jotka annettu liitännäinen " +"tarjoaa.\n" +" Hyödyllinen ulkoisten automaattisten " +"liitännäisten asennusmekanismien yhteydessä" + +msgid "List the plugin contents" +msgstr "Luettele liitännäisen sisältö" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Tulosta tuetut URI-skeemat sekä ne toteuttavat elementit" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Ei voitu ladata liitännäistiedostoa: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Ei tällaista elementtiä tai liitännäistä ”%s”\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Saatiin viesti #%u elementiltä ”%s” (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Saatiin viesti #%u täytteeltä ”%s:%s” (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Saatiin viesti #%u oliolta ”%s” (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Saatiin viesti #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Saatiin EOS (virran loppu) elementiltä ”%s”.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "LÖYTYI MERKINTÄ: sen löysi elementti ”%s”.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "LÖYTYI MERKINTÄ: sen löysi täyte ”%s:%s”.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "LÖYTYI MERKINTÄ: sen löysi olio ”%s”.\n" + +msgid "FOUND TAG\n" +msgstr "LÖYTI MERKINTÄ\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "LÖYTYI MERKINTÄ: sen löysi elementti ”%s”.\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "LÖYTYI MERKINTÄ: sen löysi olio ”%s”.\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "LÖYTI MERKINTÄ\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "VAROITUS: elementiltä %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Esipyöritetty, odotetaan puskuroinnin päättymistä...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Esipyöritetty, odotetaan puskuroinnin päättymistä...\n" + +msgid "buffering..." +msgstr "puskuroidaan..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Puskurointi tehty, asetetaan liukuhihna tilaan SOI...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Puskuroidaan, asetetaan liukuhihna tilaan TAUOLLA...\n" + +msgid "Redistribute latency...\n" +msgstr "Uudelleenjaa latenssi...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Asetetaan tilaan %s kuten %s pyysi...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Keskeytys: Pysäytetään liukuhihna ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "ei elementtiä ”%s”" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "VAROITUS: elementiltä %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Tulostemerkinnät (tunnetaan myös metadatana)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Tulostetilatiedot ja ominaisuushuomiot" + +msgid "Do not print any progress information" +msgstr "Älä tulosta mitään edistymistietoa" + +msgid "Output messages" +msgstr "Tulosteviestit" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Älä asenna virheenkäsittelintä" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Pakota virran-loppu lähteille ennen liukuhihan sammuttamista" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "VIRHE: liukuhihnaa ei voitu rakentaa: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "VIRHE: liukuhihnaa ei voitu rakentaa.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "VAROITUS: virheellinen liukuhihna: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "VIRHE: ”liukuhihna”-elementtiä ei löytynyt.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Asetetaan liukuhihna tilaan TAUOLLA...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "VIRHE: Liukuhihna ei halua mennä tauolle.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Liukuhihna on käynnissä eikä sitä tarvitse ESIRULLATA...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Liukuhihna ESIRULLAUTUU...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "VIRHE: Liukuhihna ei halua esirullautua.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Liukuhihna on ESIRULLATTU...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Asetetaan liukuhihna tilaan SOI...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "VIRHE: Liukuhihna ei halua toistaa.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Virran-loppu sammutettaessa käytössä -- pakotetaan virran-loppu " +"liukuhihnalle\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" +"Virran-loppu sammutettaessa käytössä -- pakotetaan virran-loppu " +"liukuhihnalle\n" + +msgid "Waiting for EOS...\n" +msgstr "Odotetaan virran loppua...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Virran-loppu vastaanotettu - pysäytetään liukuhihna...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Keskeytys: Pysäytetään liukuhihna ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Tapahtui virhe odotettaessa virran-loppua\n" + +msgid "Execution ended after %" +msgstr "Suoritus päättyi jälkeen %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Asetetaan liukuhihna tilaan VALMIS...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Asetetaan liukuhihna tilaan TYHJÄ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Vapautetaan liukuhihna...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Sisäinen tietovirtavirhe." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Älä tulosta tilatietoa TYYPPI" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYYPPI1,TYYPPI2,..." + +#~ msgid "link without source element" +#~ msgstr "linkki ilman lähde-elementtiä" + +#~ msgid "link without sink element" +#~ msgstr "linkki ilman nieluelementtiä" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "ei elementtiä, jota linkittää URIin ”%s”" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Tulosta varausjälki (jos valittu käännöksen yhteydessä)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Käyttö: gst-xmllaunch [ elementti.ominaisuus=arvo ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "VIRHE: XML-tiedoston ”%s” jäsentäminen epäonnistui.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "VIRHE: päätason liukuhihnaelementtiä ei ole tiedostossa ”%s”.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "VAROITUS: vain yhtä päätason elementtiä tuetaan tällä kertaa.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "VIRHE: ei voitu jäsentää komentoriviargumenttia %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "VAROITUS: elementtiä nimeltä ”%s” ei löytynyt.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Tallenna liukuhihnan XML-esitys TIEDOSTOon ja poistu" + +#~ msgid "FILE" +#~ msgstr "TIEDOSTO" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Älä asenna SIGUSR1- ja SIGUSR2-signaalinkäsittelijöitä" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Virhe uudelleenskannatessa rekisteriä %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Virhe uudelleenskannatessa rekisteriä %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Sisäinen GStreamer-virhe: tilasiirtymä epäonnistui." + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "VAPAUTETAAN liukuhihna...\n" + +#~ msgid "original location of file as a URI" +#~ msgstr "tiedoston alkuperäinen sijainti URI:na" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Ei kiihdytettyjä suoritinkäskyjä" + +#~ msgid "SCHEDULER" +#~ msgstr "VUOROTIN" + +#~ msgid "Registry to use" +#~ msgstr "Käytettävä rekisteri" + +#~ msgid "REGISTRY" +#~ msgstr "REKISTERI" + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "Sisäinen GStreamer-virhe: vuorotinongelma. Tee vikailmoitus." + +#~ msgid "Internal GStreamer error: capabilities problem. File a bug." +#~ msgstr "Sisäinen GStreamer-virhe: kykyongelma. Tee vikailmoitus." + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "" +#~ "Käytettävissä ei ole elementtiä, joka käsittelisi tietovirran MIME-tyypin " +#~ "%s." + +#~ msgid "stream type" +#~ msgstr "tietovirran tyyppi" + +#~ msgid "" +#~ "Execution ended after %s iterations (sum %s ns, average %s ns, min %s ns, " +#~ "max %s ns).\n" +#~ msgstr "" +#~ "Suoritus päättyi %s läpikäynnin jälkeen (summa %s ns, keskiarvo %s ns, " +#~ "alin %s ns, ylin %s ns).\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Kuinka monta kertaa liukuhihna käydään läpi" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Yritetään suorittaa joka tapauksessa.\n" + +#~ msgid "Added plugin %s with %d feature.\n" +#~ msgid_plural "Added plugin %s with %d features.\n" +#~ msgstr[0] "Lisätty liitännäinen %s, jolla on %d ominaisuus.\n" +#~ msgstr[1] "Lisätty liitännäinen %s, jolla on %d ominaisuutta.\n" + +#~ msgid "Added path %s to %s \n" +#~ msgstr "Lisätty polku %s rekisteriin %s \n" + +#~ msgid "Rebuilding %s (%s) ...\n" +#~ msgstr "Uudelleenrakennetaan %s (%s) ...\n" + +#~ msgid "Trying to load %s ...\n" +#~ msgstr "Yritetään ladata %s ...\n" + +#~ msgid "Error loading %s\n" +#~ msgstr "Virhe ladattaessa %s\n" + +#~ msgid "Loaded %d plugins with %d feature.\n" +#~ msgid_plural "Loaded %d plugins with %d features.\n" +#~ msgstr[0] "Ladattu %d liitännäistä, joilla on %d ominaisuus.\n" +#~ msgstr[1] "Ladattu %d liitännäistä, joilla on %d ominaisuutta.\n" + +#~ msgid "print version information and exit" +#~ msgstr "tulosta versiotiedot ja poistu" diff --git a/po/fr.gmo b/po/fr.gmo new file mode 100644 index 0000000..ceeb025 Binary files /dev/null and b/po/fr.gmo differ diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..cbdfb69 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,1350 @@ +# Translation of GStreamer to French +# Copyright (C) 2003-2012 GStreamer core team +# This file is distributed under the same license as the gstreamer package. +# +# Thomas Vander Stichele , 2004. +# Claude Paroz , 2008-2012. +# Stéphane Aulery , 2015, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 22:33+0200\n" +"Last-Translator: Stéphane Aulery \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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" + +msgid "Print the GStreamer version" +msgstr "Affiche la version de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Rend tous les avertissements bloquants" + +msgid "Print available debug categories and exit" +msgstr "Affiche les catégories de débogage disponibles et quitte" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Niveau de débogage par défaut, de 1 (erreurs uniquement) à 9 (tout) ou 0 " +"pour aucune sortie" + +msgid "LEVEL" +msgstr "NIVEAU" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Liste séparée par des virgules de paires nom_catégorie:niveau définissant " +"des niveaux spécifiques pour chaque catégorie. Exemple : GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTE" + +msgid "Disable colored debugging output" +msgstr "Désactive la couleur dans la sortie de débogage" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Modification du mode de coloration du journal de debug. Modes disponibles : " +"off, on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "Désactive le débogage" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Active le diagnostic détaillé du chargement des greffons" + +msgid "Colon-separated paths containing plugins" +msgstr "Chemins contenant des greffons, séparés par des deux-points" + +msgid "PATHS" +msgstr "CHEMINS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Liste de greffons à précharger, séparée par des virgules, en plus de la " +"liste contenue dans la variable d’environnement GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "GREFFONS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Désactive la détection des erreurs de segmentation pendant le chargement des " +"greffons" + +msgid "Disable updating the registry" +msgstr "Désactive la mise à jour du registre" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Désactive le lancement d’un processus annexe lors de l’analyse du registre" + +msgid "GStreamer Options" +msgstr "Options de GStreamer" + +msgid "Show GStreamer Options" +msgstr "Afficher les options de GStreamer" + +msgid "Unknown option" +msgstr "Option inconnue" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer a rencontré une erreur générale de bibliothèque centrale." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Les développeurs de GStreamer sont trop fainéants pour associer un code " +"d’erreur à cette erreur." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Erreur interne de GStreamer : code non implémenté." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Erreur GStreamer : échec de changement d’état et un élément n’a pas pu " +"signaler un message d’erreur correct contenant la raison de l’échec." + +msgid "Internal GStreamer error: pad problem." +msgstr "Erreur interne de GStreamer : problème de connecteur." + +msgid "Internal GStreamer error: thread problem." +msgstr "Erreur interne de GStreamer : problème de thread." + +msgid "GStreamer error: negotiation problem." +msgstr "Erreur GStreamer : problème de négociation." + +msgid "Internal GStreamer error: event problem." +msgstr "Erreur interne de GStreamer : problème d’événement." + +msgid "Internal GStreamer error: seek problem." +msgstr "Erreur interne de Gstreamer : problème de recherche." + +msgid "Internal GStreamer error: caps problem." +msgstr "Erreur interne de Gstreamer : problème de caps." + +msgid "Internal GStreamer error: tag problem." +msgstr "Erreur interne de Gstreamer : problème de balise." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Il manque un greffon dans votre installation de GStreamer." + +msgid "GStreamer error: clock problem." +msgstr "Erreur Gstreamer : problème d’horloge." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Cette application tente d’utiliser une fonctionnalité de GStreamer qui a été " +"désactivée." + +msgid "GStreamer encountered a general supporting library error." +msgstr "" +"GStreamer a rencontré une erreur générale de bibliothèque de prise en charge." + +msgid "Could not initialize supporting library." +msgstr "Impossible d’initialiser la bibliothèque de prise en charge." + +msgid "Could not close supporting library." +msgstr "Impossible de fermer la bibliothèque de prise en charge." + +msgid "Could not configure supporting library." +msgstr "Impossible de configurer la bibliothèque de prise en charge." + +msgid "Encoding error." +msgstr "Erreur de codage." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer a rencontré une erreur générale de ressource." + +msgid "Resource not found." +msgstr "Ressource introuvable." + +msgid "Resource busy or not available." +msgstr "Ressource occupée ou non disponible." + +msgid "Could not open resource for reading." +msgstr "Impossible d’ouvrir la ressource en lecture." + +msgid "Could not open resource for writing." +msgstr "Impossible d’ouvrir la ressource en écriture." + +msgid "Could not open resource for reading and writing." +msgstr "Impossible d’ouvrir la ressource en lecture et écriture." + +msgid "Could not close resource." +msgstr "Impossible de fermer la ressource." + +msgid "Could not read from resource." +msgstr "Impossible de lire à partir de la ressource." + +msgid "Could not write to resource." +msgstr "Impossible d’écrire dans la ressource." + +msgid "Could not perform seek on resource." +msgstr "Impossible de rechercher dans la ressource." + +msgid "Could not synchronize on resource." +msgstr "Impossible de synchroniser dans la ressource." + +msgid "Could not get/set settings from/on resource." +msgstr "Impossible d’obtenir ou de définir un paramètre de ressource." + +msgid "No space left on the resource." +msgstr "Espace libre insuffisant dans la ressource." + +msgid "Not authorized to access resource." +msgstr "Accès à la ressource interdit." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer a rencontré une erreur générale de flux." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "L’élément ne gère pas ce flux. Veuillez signaler le problème." + +msgid "Could not determine type of stream." +msgstr "Impossible de déterminer le type du flux." + +msgid "The stream is of a different type than handled by this element." +msgstr "Le type du flux est différent de celui qui est géré par cet élément." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Aucun codec disponible pour gérer le type du flux." + +msgid "Could not decode stream." +msgstr "Impossible de décoder le flux." + +msgid "Could not encode stream." +msgstr "Impossible de coder le flux." + +msgid "Could not demultiplex stream." +msgstr "Impossible de démultiplexer le flux." + +msgid "Could not multiplex stream." +msgstr "Impossible de multiplexer le flux." + +msgid "The stream is in the wrong format." +msgstr "Le format du flux n’est pas correct." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Le flux est chiffré et le déchiffrement n’est pas pris en charge." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Le flux est chiffré et il ne peut être déchiffré car aucune clef valable n’a " +"été fournie." + +#, c-format +msgid "No error message for domain %s." +msgstr "Aucun message d’erreur pour le domaine %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Aucun message d’erreur standard pour le domaine %s et le code %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "L’horloge sélectionnée ne peut pas être utilisée dans le pipeline." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Erreur d’écriture du cache de registre à %s : %s" + +msgid "title" +msgstr "titre" + +msgid "commonly used title" +msgstr "titre utilisé habituellement" + +msgid "title sortname" +msgstr "titre pour le tri" + +msgid "commonly used title for sorting purposes" +msgstr "titre utilisé habituellement dans un but de tri" + +msgid "artist" +msgstr "artiste" + +msgid "person(s) responsible for the recording" +msgstr "personne(s) responsable(s) de l’enregistrement" + +msgid "artist sortname" +msgstr "nom d’artiste pour le tri" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "personne(s) responsable(s) de l’enregistrement, dans un but de tri" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album contenant ces données" + +msgid "album sortname" +msgstr "nom d’album pour le tri" + +msgid "album containing this data for sorting purposes" +msgstr "album contenant ces données, dans un but de tri" + +msgid "album artist" +msgstr "artiste de l’album" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "L’artiste de l’album entier, tel qu’il devrait s’afficher" + +msgid "album artist sortname" +msgstr "nom d’artiste de l’album pour le tri" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "L’artiste de l’album entier, adapté pour le tri" + +msgid "date" +msgstr "date" + +msgid "date the data was created (as a GDate structure)" +msgstr "date de création des données (sous forme de structure GDate)" + +msgid "datetime" +msgstr "date et heure" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"date et heure de création des données (sous forme de structure GstDateTime)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre auquel ces données appartiennent" + +msgid "comment" +msgstr "commentaire" + +msgid "free text commenting the data" +msgstr "texte libre décrivant les données" + +msgid "extended comment" +msgstr "commentaire étendu" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"texte libre décrivant les données sous la forme clé=valeur ou " +"clé[en]=commentaire" + +msgid "track number" +msgstr "numéro de piste" + +msgid "track number inside a collection" +msgstr "numéro de piste au sein d’une collection" + +msgid "track count" +msgstr "nombre de pistes" + +msgid "count of tracks inside collection this track belongs to" +msgstr "nombre de pistes dans la collection dont ces données font partie" + +msgid "disc number" +msgstr "numéro de disque" + +msgid "disc number inside a collection" +msgstr "numéro de disque au sein d’une collection" + +msgid "disc count" +msgstr "nombre de disques" + +msgid "count of discs inside collection this disc belongs to" +msgstr "nombre de disques dans la collection dont ces données font partie" + +msgid "location" +msgstr "emplacement" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Origine du média sous forme d’URI (emplacement de l’hébergement d’origine du " +"fichier ou du flux)" + +msgid "homepage" +msgstr "site Web" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Site Web de ce média (par ex. site de l’artiste ou du film)" + +msgid "description" +msgstr "description" + +msgid "short text describing the content of the data" +msgstr "texte court décrivant le contenu des données" + +msgid "version" +msgstr "version" + +msgid "version of this data" +msgstr "version de ces données" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - voir http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisation" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "information sur le copyright des données" + +msgid "copyright uri" +msgstr "URI du copyright" + +msgid "URI to the copyright notice of the data" +msgstr "URI vers l’information de copyright des données" + +msgid "encoded by" +msgstr "codé par" + +msgid "name of the encoding person or organization" +msgstr "nom de la personne ou de l’organisation qui a effectué le codage" + +msgid "contact" +msgstr "contact" + +msgid "contact information" +msgstr "informations sur le contact" + +msgid "license" +msgstr "licence" + +msgid "license of data" +msgstr "licence des données" + +msgid "license uri" +msgstr "URI de la licence" + +msgid "URI to the license of the data" +msgstr "URI vers la licence des données" + +msgid "performer" +msgstr "interprète" + +msgid "person(s) performing" +msgstr "personne(s) qui interprète(nt)" + +msgid "composer" +msgstr "compositeur" + +msgid "person(s) who composed the recording" +msgstr "personne(s) qui a/ont composé l’enregistrement" + +msgid "conductor" +msgstr "réalisateur" + +msgid "conductor/performer refinement" +msgstr "détails sur le réalisateur / interprète" + +msgid "duration" +msgstr "durée" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "longueur en unité de temps GStreamer (nanosecondes)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec de stockage des données" + +msgid "video codec" +msgstr "codec vidéo" + +msgid "codec the video data is stored in" +msgstr "codec de stockage des données vidéo" + +msgid "audio codec" +msgstr "codec audio" + +msgid "codec the audio data is stored in" +msgstr "codec de stockage des données audio" + +msgid "subtitle codec" +msgstr "codec des sous-titres" + +msgid "codec the subtitle data is stored in" +msgstr "codec de stockage des sous-titres" + +msgid "container format" +msgstr "format du conteneur" + +msgid "container format the data is stored in" +msgstr "format du conteneur dans lequel sont stockées les données" + +msgid "bitrate" +msgstr "débit" + +msgid "exact or average bitrate in bits/s" +msgstr "débit exact ou moyen en bits par seconde" + +msgid "nominal bitrate" +msgstr "débit nominal" + +msgid "nominal bitrate in bits/s" +msgstr "débit nominal en bits par seconde" + +msgid "minimum bitrate" +msgstr "débit minimum" + +msgid "minimum bitrate in bits/s" +msgstr "débit minimum en bits par seconde" + +msgid "maximum bitrate" +msgstr "débit maximum" + +msgid "maximum bitrate in bits/s" +msgstr "débit maximum en bits par seconde" + +msgid "encoder" +msgstr "codeur" + +msgid "encoder used to encode this stream" +msgstr "codeur utilisé pour le codage du flux" + +msgid "encoder version" +msgstr "version du codeur" + +msgid "version of the encoder used to encode this stream" +msgstr "version du codeur utilisé pour le codage du flux" + +msgid "serial" +msgstr "numéro de série" + +msgid "serial number of track" +msgstr "numéro de série de la piste" + +msgid "replaygain track gain" +msgstr "gain de piste replaygain" + +msgid "track gain in db" +msgstr "gain de la piste en décibels" + +msgid "replaygain track peak" +msgstr "crête de piste replaygain" + +msgid "peak of the track" +msgstr "crête de la piste" + +msgid "replaygain album gain" +msgstr "gain d’album replaygain" + +msgid "album gain in db" +msgstr "gain de l’album en décibels" + +msgid "replaygain album peak" +msgstr "crête d’album replaygain" + +msgid "peak of the album" +msgstr "crête de l’album" + +msgid "replaygain reference level" +msgstr "niveau de référence replaygain" + +msgid "reference level of track and album gain values" +msgstr "niveau de référence des valeurs de gain de piste et d’album" + +msgid "language code" +msgstr "code linguistique" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "code linguistique du flux, selon la norme ISO-639-1 ou ISO-639-2" + +msgid "language name" +msgstr "nom de la langue" + +msgid "freeform name of the language this stream is in" +msgstr "nom explicite de la langue de ce flux" + +msgid "image" +msgstr "image" + +msgid "image related to this stream" +msgstr "image liée à ce flux" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "image d’aperçu" + +msgid "preview image related to this stream" +msgstr "image d’aperçu liée à ce flux" + +msgid "attachment" +msgstr "pièce jointe" + +msgid "file attached to this stream" +msgstr "fichier joint à ce flux" + +msgid "beats per minute" +msgstr "pulsations par minute" + +msgid "number of beats per minute in audio" +msgstr "nombre de pulsations par minute de la piste audio" + +msgid "keywords" +msgstr "mots-clés" + +msgid "comma separated keywords describing the content" +msgstr "mots-clés décrivant le contenu, séparés par des virgules" + +msgid "geo location name" +msgstr "nom d’emplacement géographique" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"description intelligible de l’endroit où le média a été enregistré ou produit" + +msgid "geo location latitude" +msgstr "latitude de l’emplacement" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitude de l’endroit géographique où le média a été enregistré ou produit, " +"en degrés, conformément à WGS84 (zéro à l’équateur, valeurs négatives dans " +"l’hémisphère sud)" + +msgid "geo location longitude" +msgstr "longitude de l’emplacement" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitude de l’endroit géographique où le média a été enregistré ou produit, " +"en degrés, conformément à WGS84 (zéro au premier méridien de Greenwich (GB), " +"valeurs négatives pour les longitudes vers l’ouest)" + +msgid "geo location elevation" +msgstr "altitude de l’emplacement" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"altitude de l’endroit géographique où le média a été enregistré ou produit, " +"en mètres, conformément à WGS84 (zéro au niveau moyen de la mer)" + +msgid "geo location country" +msgstr "pays de l’emplacement" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "pays (nom anglais) où le média a été enregistré ou produit" + +msgid "geo location city" +msgstr "ville de l’emplacement" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "ville (nom anglais) où le média a été enregistré ou produit" + +msgid "geo location sublocation" +msgstr "zone locale de l’emplacement" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"un endroit de la localité où le média a été enregistré ou produit (par ex. " +"le voisinage)" + +msgid "geo location horizontal error" +msgstr "erreur horizontale de l’emplacement" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "erreur probable des mesures de position horizontale (en mètres)" + +msgid "geo location movement speed" +msgstr "vitesse de déplacement géolocalisé" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"vitesse du mouvement (en m/s) du périphérique de capture durant la capture" + +msgid "geo location movement direction" +msgstr "direction du déplacement géolocalisé" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indique la direction du déplacement du périphérique effectuant la capture " +"d’un média. Elle est indiquée en degrés, par un nombre à virgules. 0 indique " +"le nord géographique et le nombre augmente dans le sens horaire" + +msgid "geo location capture direction" +msgstr "direction de la capture géolocalisée" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indique la direction du périphérique au moment de la capture d’un média. " +"Elle est indiquée en degrés, par un nombre à virgules. 0 indique le nord " +"géographique et le nombre augmente dans le sens horaire" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nom d’émission" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nom de l’émission TV, du podcast ou de la série d’où provient le média" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nom d’émission pour le tri" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Nom de l’émission TV, du podcast ou de la série d’où provient le média, dans " +"l’optique du tri" + +msgid "episode number" +msgstr "numéro d’épisode" + +msgid "The episode number in the season the media is part of" +msgstr "Le numéro d’épisode de la série dont fait partie le média" + +msgid "season number" +msgstr "numéro de saison" + +msgid "The season number of the show the media is part of" +msgstr "Le numéro de la saison de l’émission dont fait partie le média" + +msgid "lyrics" +msgstr "paroles" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Les paroles du média, utilisé surtout pour les chansons" + +msgid "composer sortname" +msgstr "nom du compositeur pour le tri" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "personne(s) qui ont composé l’enregistrement, dans un but de tri" + +msgid "grouping" +msgstr "regroupement" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Unité de groupe pour des médias qui contiennent plusieurs pistes, comme les " +"différents morceaux d’un concerto. De plus haut niveau que la piste, mais de " +"plus bas niveau que l’album" + +msgid "user rating" +msgstr "évaluation par l’utilisateur" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Note attribuée par une personne. Plus la note est élevée, plus la personne " +"apprécie ce média" + +msgid "device manufacturer" +msgstr "fabricant du périphérique" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricant du périphérique utilisé pour créer ce média" + +msgid "device model" +msgstr "modèle du périphérique" + +msgid "Model of the device used to create this media" +msgstr "Modèle du périphérique utilisé pour créer ce média" + +msgid "application name" +msgstr "nom de l’application" + +msgid "Application used to create the media" +msgstr "Application utilisée pour créer ce média" + +msgid "application data" +msgstr "données applicatives" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Données arbitraires de l’application à sérialiser dans le média" + +msgid "image orientation" +msgstr "orientation de l’image" + +msgid "How the image should be rotated or flipped before display" +msgstr "" +"Indique la manière de pivoter ou de retourner l’image avant de l’afficher" + +msgid "publisher" +msgstr "éditeur" + +msgid "Name of the label or publisher" +msgstr "Nom de l’étiquette ou de l’éditeur" + +msgid "interpreted-by" +msgstr "interprété-par" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Information sur les personnes qui ont fait un remix et interprétations " +"similaires" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Numèro de note Midi d’une piste audio." + +msgid "private-data" +msgstr "données-privées" + +msgid "Private data" +msgstr "Données privées" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Aucun gestionnaire d’URI trouvé pour le protocole %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "schèma URI « %s » non pris en charge" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERREUR : de l’élément %s : %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Information de débogage supplémentaire :\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "lien sans source [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "lien sans sink [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "pas de propriété « %s » dans l’élément « %s »" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "impossible de définir la propriété « %s » de l’élément « %s » à « %s »" + +msgid "Delayed linking failed." +msgstr "Échec du chargement dynamique différé." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "impossible de connecter %s à %s, %s n’accepte pas les majuscules %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"impossible de connecter %s à %s, aucun élément n’accepte les majuscules %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "impossible de connecter %s à %s avec les majuscules %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "impossible de connecter %s à %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "pas d’élément « %s »" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "référence « %s » inattendue - ignoré" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "pad-référence « %s » inattendue - ignoré" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "impossible d’analyser le caps « %s »" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "pas d’élément d’entrée pour l’URI « %s »" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "pas d’élément source pour l’URI « %s »" + +msgid "syntax error" +msgstr "erreur de syntaxe" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "conteneur « %s » vide, non autorisé" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "pas de conteneur « %s », dépaquetage des éléments" + +msgid "empty pipeline not allowed" +msgstr "pipeline vide non autorisé" + +msgid "A lot of buffers are being dropped." +msgstr "De nombreux tampons sont éliminés." + +msgid "Internal data flow problem." +msgstr "Problème interne de flux de données." + +msgid "Internal data flow error." +msgstr "Erreur interne de flux de données." + +msgid "Internal clock error." +msgstr "Erreur d’horloge interne." + +msgid "Failed to map buffer." +msgstr "Impossible de mapper les buffer." + +msgid "Filter caps" +msgstr "Capacités de filtrage" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restreint les capacités possibles autorisées (NULL signifie ANY). La " +"définition de cette propriété nécessite une référence à l’objet GSTCaps " +"fourni." + +msgid "Caps Change Mode" +msgstr "Mode majuscule activé" + +msgid "Filter caps change behaviour" +msgstr "Filtre de comportement de modification des majuscules" + +msgid "No Temp directory specified." +msgstr "Aucun répertoire temporaire indiqué." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Impossible de créer le fichier temporaire « %s »." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Impossible d’ouvrir le fichier « %s » en lecture." + +msgid "Error while writing to download file." +msgstr "Erreur d’écriture dans le fichier de téléchargement." + +msgid "No file name specified for writing." +msgstr "Aucun nom de fichier indiqué pour l’écriture." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Impossible d’ouvrir le fichier « %s » en écriture." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Erreur lors de la fermeture du fichier « %s »." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Erreur de positionnement dans le fichier « %s »." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Erreur d’écriture dans le fichier « %s »." + +msgid "No file name specified for reading." +msgstr "Aucun nom de fichier indiqué pour la lecture." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Impossible d’obtenir des infos sur « %s »." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "« %s » est un répertoire." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Le fichier « %s » est un connecteur." + +msgid "Failed after iterations as requested." +msgstr "Échec suite aux itérations demandées." + +msgid "caps" +msgstr "capacités" + +msgid "detected capabilities in stream" +msgstr "capacités détectées dans le flux" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "forcer les capacités" + +msgid "force caps without doing a typefind" +msgstr "force les capacités sans faire de recherche de type" + +msgid "Stream doesn't contain enough data." +msgstr "Le flux ne contient pas assez de données." + +msgid "Stream contains no data." +msgstr "Le flux ne contient aucune donnée." + +msgid "Implemented Interfaces:\n" +msgstr "Interfaces implémentées :\n" + +msgid "readable" +msgstr "accès en lecture" + +msgid "writable" +msgstr "accès en écriture" + +msgid "deprecated" +msgstr "obsolète" + +msgid "controllable" +msgstr "contrôlable" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "modifiable en l’état NULL, READY, PAUSED ou PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "modifiable uniquement en l’état NULL, READY ou PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "modifiable uniquement en l’état NULL ou READY" + +msgid "Blacklisted files:" +msgstr "Fichiers sur liste noire :" + +msgid "Total count: " +msgstr "Nombre total :" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d fichier sur liste noire" +msgstr[1] "%d fichiers sur liste noire" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d greffon" +msgstr[1] "%d greffons" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d élément de liste noire" +msgstr[1] "%d éléments de liste noire" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d fonctionnalité" +msgstr[1] "%d fonctionnalités" + +msgid "Print all elements" +msgstr "Affiche tous les éléments" + +msgid "Print list of blacklisted files" +msgstr "Affiche une liste des fichiers sur liste noire" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Affiche sous forme machine une liste de fonctionnalités offertes par le " +"greffon indiqué ou tous les greffons.\n" +" Utile en lien avec des mécanismes " +"externes d’installation automatique de greffons" + +msgid "List the plugin contents" +msgstr "Énumère le contenu du greffon" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Une liste de types d’éléments séparés par des barres oblique '/' (nommée " +"aussi klass) vers une liste (non ordonnée)." + +msgid "Check if the specified element or plugin exists" +msgstr "Vérifie si l’élément ou le greffon indiqué existe" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Lors de la vérification de l’existence d’un élément ou d’un greffon, vérifie " +"aussi que sa version est au minimum la version indiquée" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Affiche les types d’URI pris en charge, avec les éléments qui les " +"implémentent" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Impossible de charger le fichier de greffon : %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Aucun élément ou greffon « %s »\n" + +msgid "Index statistics" +msgstr "Statistiques d’index" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Message n° %u reçu de l’élément « %s » (%s) : " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Message n° %u reçu du connecteur « %s:%s » (%s) : " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Message n° %u reçu de l’objet « %s » (%s) : " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Message n°%u reçu (%s) : " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "EOS reçu de l’élément « %s ».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "BALISE TROUVÉE : découverte par l’élément « %s ».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "BALISE TROUVÉE : découverte par le connecteur « %s:%s ».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "BALISE TROUVÉE : découverte par l’objet « %s ».\n" + +msgid "FOUND TAG\n" +msgstr "BALISE TROUVÉE\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TDM TROUVÉE : découverte par l’élément « %s ».\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TDM TROUVÉE : découverte par l’objet « %s ».\n" + +msgid "FOUND TOC\n" +msgstr "TDM TROUVÉE\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO :\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVERTISSEMENT : de l’élément %s : %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Préparation terminée, attente de la fin de remplissage du tampon…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Préparation terminée, attente de la fin du traitement…\n" + +msgid "buffering..." +msgstr "mise en mémoire tampon…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Mémoire tampon pleine, définition du pipeline à PLAYING…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Remplissage du tampon, définition du pipeline à PAUSED…\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribution de latence…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Définition de l’état à %s comme demandé par %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interruption : arrêt du pipeline…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Progression : (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Élément manquant : %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Contexte de l’élément « %s » : %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Affiche les balises (aussi connues sous le nom de métadonnées)" + +msgid "Output TOC (chapters and editions)" +msgstr "Affiche la table des matières (chapitres et éditions)" + +msgid "Output status information and property notifications" +msgstr "Affiche des informations d’état et des notifications de propriétés" + +msgid "Do not print any progress information" +msgstr "N’affiche pas d’informations de progression" + +msgid "Output messages" +msgstr "Affiche des messages" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Ne pas afficher les informations de la propriété spécifiée si le mode " +"verbeux est activé (peut être utilisé plusieurs fois)" + +msgid "PROPERTY-NAME" +msgstr "NOM-PROPRIÉTÉ" + +msgid "Do not install a fault handler" +msgstr "N’installe pas de gestionnaire de dysfonctionnement" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Force l’EOS sur les sources avant de fermer le pipeline" + +msgid "Gather and print index statistics" +msgstr "Rassemble et affiche les statistiques d’index" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERREUR : le pipeline n’a pas pu être construit : %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERREUR : le pipeline n’a pas pu être construit.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "AVERTISSEMENT : pipeline erroné : %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERREUR : l’élément « pipeline » est introuvable.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Définition du pipeline à PAUSED...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERREUR : le pipeline refuse de se mettre en pause.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Le pipeline est actif et n’a pas besoin de phase PREROLL…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Le pipeline est en phase de PREROLL…\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERREUR : le pipeline refuse de passer en phase de préparation.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Le pipeline a terminé la phase PREROLL…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Passage du pipeline à la phase PLAYING…\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERREUR : le pipeline refuse de passer en mode actif.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS à la fermeture est activé -- EOS forcé sur le pipeline\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS à la fermeture est activé -- attente d’EOS après erreur\n" + +msgid "Waiting for EOS...\n" +msgstr "Attente d’EOS.\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS reçu - arrêt du pipeline…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interruption lors de l’attende d’EOS - arrêt du pipeline…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Une erreur s’est produite lors de l’attente de l’EOS\n" + +msgid "Execution ended after %" +msgstr "L’exécution s’est terminée après %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Définition du pipeline à READY (prêt)…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Définition du pipeline à NULL…\n" + +msgid "Freeing pipeline ...\n" +msgstr "Libération du pipeline…\n" + +#~ msgid "bin" +#~ msgstr "bin" + +#~ msgid "Internal data stream error." +#~ msgstr "Erreur interne de flux de données." diff --git a/po/fur.gmo b/po/fur.gmo new file mode 100644 index 0000000..1db305c Binary files /dev/null and b/po/fur.gmo differ diff --git a/po/fur.po b/po/fur.po new file mode 100644 index 0000000..486d8ff --- /dev/null +++ b/po/fur.po @@ -0,0 +1,1296 @@ +# Friulian translation for gstreamer package of GStreamer project. +# This file is put in the public domain. +# Fabio Tomat , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.10.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-03-19 15:41+0100\n" +"Last-Translator: Fabio Tomat \n" +"Language-Team: Friulian \n" +"Language: fur\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.12\n" + +msgid "Print the GStreamer version" +msgstr "Stampe la version di GStreamer" + +msgid "Make all warnings fatal" +msgstr "Fâs deventâ ducj i avertiments fatâi" + +msgid "Print available debug categories and exit" +msgstr "" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" + +msgid "LEVEL" +msgstr "NIVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" + +msgid "LIST" +msgstr "LISTE" + +msgid "Disable colored debugging output" +msgstr "" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" + +msgid "Colon-separated paths containing plugins" +msgstr "" + +msgid "PATHS" +msgstr "PERCORS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +msgid "PLUGINS" +msgstr "PLUGIN" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "Opzions GStreamer" + +msgid "Show GStreamer Options" +msgstr "Mostre lis opzions di GSstreamer" + +msgid "Unknown option" +msgstr "Opzion no cognossude" + +msgid "GStreamer encountered a general core library error." +msgstr "" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +msgid "Internal GStreamer error: code not implemented." +msgstr "" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "" + +msgid "Internal GStreamer error: thread problem." +msgstr "" + +msgid "GStreamer error: negotiation problem." +msgstr "" + +msgid "Internal GStreamer error: event problem." +msgstr "" + +msgid "Internal GStreamer error: seek problem." +msgstr "" + +msgid "Internal GStreamer error: caps problem." +msgstr "" + +msgid "Internal GStreamer error: tag problem." +msgstr "" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +msgid "GStreamer error: clock problem." +msgstr "" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "" + +msgid "Could not initialize supporting library." +msgstr "" + +msgid "Could not close supporting library." +msgstr "" + +msgid "Could not configure supporting library." +msgstr "" + +msgid "Encoding error." +msgstr "Erôr di codifiche." + +msgid "GStreamer encountered a general resource error." +msgstr "" + +msgid "Resource not found." +msgstr "Risorse no cjatade." + +msgid "Resource busy or not available." +msgstr "Risorse ocupade o no disponibile." + +msgid "Could not open resource for reading." +msgstr "Impussibil vierzi la risorse pe leture." + +msgid "Could not open resource for writing." +msgstr "Impussibil vierzi la risorse pe scriture." + +msgid "Could not open resource for reading and writing." +msgstr "Impussibil vierzi la risorse pe leture e scriture." + +msgid "Could not close resource." +msgstr "Impussibil sierâ la risorse." + +msgid "Could not read from resource." +msgstr "Impussibil lei de risorse." + +msgid "Could not write to resource." +msgstr "Impussibil scrivi te risorse." + +msgid "Could not perform seek on resource." +msgstr "Impussibil fâ une ricercje su pe risorse." + +msgid "Could not synchronize on resource." +msgstr "Impussibil sincronizâ su pe risorse." + +msgid "Could not get/set settings from/on resource." +msgstr "Impussibil vê/stabilî impostazions de/su pe risorse." + +msgid "No space left on the resource." +msgstr "No spazi disponibil su pe risorse." + +msgid "Not authorized to access resource." +msgstr "No autorizât a acedi ae risorse." + +msgid "GStreamer encountered a general stream error." +msgstr "" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" + +msgid "Could not determine type of stream." +msgstr "Impussibil determinâ il gjenar di flus." + +msgid "The stream is of a different type than handled by this element." +msgstr "" + +msgid "There is no codec present that can handle the stream's type." +msgstr "" + +msgid "Could not decode stream." +msgstr "Impussibil decodificâ il flus." + +msgid "Could not encode stream." +msgstr "Impussibil codificâ il flus." + +msgid "Could not demultiplex stream." +msgstr "" + +msgid "Could not multiplex stream." +msgstr "" + +msgid "The stream is in the wrong format." +msgstr "Il flus al è tal formât sbaliât." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Il flus al è cifrât e il decifrâ nol è supuartât." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Il flus al è cifrât e nol pues jessi decifrât parcè che no je stade furnide " +"nissune clâf adate." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nissun messaç di erôr pal domini %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nissun messaç di erôr standard pal domini %s e codiç %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Erôr tal scrivi la cache di regjistri su %s: %s" + +msgid "title" +msgstr "titul" + +msgid "commonly used title" +msgstr "titul doprât di solit" + +msgid "title sortname" +msgstr "non ordenament titul" + +msgid "commonly used title for sorting purposes" +msgstr "il titul doprât di solit par motîfs di ordenament" + +msgid "artist" +msgstr "artist" + +msgid "person(s) responsible for the recording" +msgstr "persone(-is) responsabile pe regjistrazion" + +msgid "artist sortname" +msgstr "non ordenament artist" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persone(-is) responsabile pe regjistrazion par motîfs di ordenament" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album che al conten chescj dâts" + +msgid "album sortname" +msgstr "non ordenament album" + +msgid "album containing this data for sorting purposes" +msgstr "album che al conten chescj dâts par motîfs di ordenament" + +msgid "album artist" +msgstr "artist album" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "L'artist dal album intîr, come che al à di jessi mostrât" + +msgid "album artist sortname" +msgstr "non ordenament artist album" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "L'artist dal album intîr, come che al à di jessi ordenât" + +msgid "date" +msgstr "date" + +msgid "date the data was created (as a GDate structure)" +msgstr "date di cuant che i dâts a son stâts creâts (come struture GDate)" + +msgid "datetime" +msgstr "date/ore" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"date e ore di cuant che i dâts a son stâts creâts (come struture GsDateTime)" + +msgid "genre" +msgstr "gjenar" + +msgid "genre this data belongs to" +msgstr "il gjenar di apartignince di chescj dâts" + +msgid "comment" +msgstr "coment" + +msgid "free text commenting the data" +msgstr "" + +msgid "extended comment" +msgstr "" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" + +msgid "track number" +msgstr "numar dal toc" + +msgid "track number inside a collection" +msgstr "numar dal toc dentri une colezion" + +msgid "track count" +msgstr "totâl tocs" + +msgid "count of tracks inside collection this track belongs to" +msgstr "il totâl dai tocs dentri de colezion dulà che chest toc al aparten" + +msgid "disc number" +msgstr "numar disc" + +msgid "disc number inside a collection" +msgstr "numar disc dentri une colezion" + +msgid "disc count" +msgstr "totâl discs" + +msgid "count of discs inside collection this disc belongs to" +msgstr "il totâl dai discs dentri de colezion dulà che chest disc al aparten" + +msgid "location" +msgstr "posizion" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Origjin dal contignût multimediâl come URI (posizion dulà che il file " +"origjinâl o il flus a son ospitâts)" + +msgid "homepage" +msgstr "sît web" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"sît web par chest contignût multimediâl (p.e. il sît web dal artist o dal " +"film)" + +msgid "description" +msgstr "descrizion" + +msgid "short text describing the content of the data" +msgstr "un curt test che al descrîf il contignût dai dâts" + +msgid "version" +msgstr "version" + +msgid "version of this data" +msgstr "version di chescj dâts" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Codiç di Regjistrazion Standard Internazionâl - viôt http://www.ifpi.org/" +"isrc/" + +msgid "organization" +msgstr "organizazion" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "l'avîs sul copyright dai dâts" + +msgid "copyright uri" +msgstr "uri copyright" + +msgid "URI to the copyright notice of the data" +msgstr "il URI dal avîs sul copyright dai dâts" + +msgid "encoded by" +msgstr "codificât di" + +msgid "name of the encoding person or organization" +msgstr "non de persone o organizazion che a codifiche" + +msgid "contact" +msgstr "contat" + +msgid "contact information" +msgstr "informazion contat" + +msgid "license" +msgstr "licence" + +msgid "license of data" +msgstr "licence dai dâts" + +msgid "license uri" +msgstr "uri licence" + +msgid "URI to the license of the data" +msgstr "URI de licence dai dâts" + +msgid "performer" +msgstr "esecutôr" + +msgid "person(s) performing" +msgstr "persone(-is) che a àn interpretât" + +msgid "composer" +msgstr "compositôr" + +msgid "person(s) who composed the recording" +msgstr "persone(-is) che e à componût la regjistrazion" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "durade" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "lungjece in unitâts di timp di GStreamer (nanoseconts)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec doprât par memorizâ i dâts" + +msgid "video codec" +msgstr "codec video" + +msgid "codec the video data is stored in" +msgstr "codec doprât par memorizâ i dâts video" + +msgid "audio codec" +msgstr "codec audio" + +msgid "codec the audio data is stored in" +msgstr "codec doprât par memorizâ i dâts audio" + +msgid "subtitle codec" +msgstr "codec sottitui" + +msgid "codec the subtitle data is stored in" +msgstr "codec doprât par memorizâ i sottitui" + +msgid "container format" +msgstr "formât contignidôr" + +msgid "container format the data is stored in" +msgstr "formât dal contignidôr doprât par memorizâ i dâts" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "il bitrate esat o medi in bit/s" + +msgid "nominal bitrate" +msgstr "bitrate nominâl" + +msgid "nominal bitrate in bits/s" +msgstr "bitrate nominâl in bit/s" + +msgid "minimum bitrate" +msgstr "bitrate minim" + +msgid "minimum bitrate in bits/s" +msgstr "bitrate minim in bit/s" + +msgid "maximum bitrate" +msgstr "bitrate massim" + +msgid "maximum bitrate in bits/s" +msgstr "bitrate massim in bit/s" + +msgid "encoder" +msgstr "" + +msgid "encoder used to encode this stream" +msgstr "" + +msgid "encoder version" +msgstr "" + +msgid "version of the encoder used to encode this stream" +msgstr "" + +msgid "serial" +msgstr "seriâl" + +msgid "serial number of track" +msgstr "numar seriâl dal toc" + +msgid "replaygain track gain" +msgstr "" + +msgid "track gain in db" +msgstr "vuadagn toc in db" + +msgid "replaygain track peak" +msgstr "" + +msgid "peak of the track" +msgstr "pic dal toc" + +msgid "replaygain album gain" +msgstr "" + +msgid "album gain in db" +msgstr "vuadagn album in db" + +msgid "replaygain album peak" +msgstr "" + +msgid "peak of the album" +msgstr "pic dal album" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "codiç lenghe" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "il codiç di lenghe par chest flus, conformi ae ISO-639-1 o ISO-639-2" + +msgid "language name" +msgstr "non lenghe" + +msgid "freeform name of the language this stream is in" +msgstr "non in forme libare di cheste lenghe che chest flus e sta doprant" + +msgid "image" +msgstr "imagjin" + +msgid "image related to this stream" +msgstr "imagjin relative a chest flus" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "imagjin anteprime" + +msgid "preview image related to this stream" +msgstr "imagjin di anteprime relative a chest flus" + +msgid "attachment" +msgstr "zonte" + +msgid "file attached to this stream" +msgstr "file alegât a chest flus" + +msgid "beats per minute" +msgstr "batudis al minût" + +msgid "number of beats per minute in audio" +msgstr "numar di batudis par minût tal audio" + +msgid "keywords" +msgstr "peraulis clâf" + +msgid "comma separated keywords describing the content" +msgstr "peraulis clâf separadis di virgule che a descrivin il contest" + +msgid "geo location name" +msgstr "non posizion gjeog." + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "latitudin posizion gjeog." + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"la posizion de latitudin gjeog. di dulà che il contignût multimediâl al è " +"stât regjistrât o prodot in grâts in acuardi cul WGS84 (zero al ecuatôr, " +"valôrs negatîfs pes latitudins meridionâls)" + +msgid "geo location longitude" +msgstr "longjitudin posizion gjeog." + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"posizion de longjitudin gjeog. di dulà che il contignût multimediâl al è " +"stât regjistrât o prodot, in grât in acuardi cul WGS84 (zero al prin " +"meridian a Greenwich/UK, valôrs negatîfs pes longjitudins ocidentâls)" + +msgid "geo location elevation" +msgstr "altece posizion gjeog." + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"la altece gjeog. di dulà che il contignût multimediâl al è stât regjistrât o " +"prodot in metris, in acuardi cun WGS84 (zero al è il nivel medi dal mâr)" + +msgid "geo location country" +msgstr "paîs posizion gjeog." + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"paîs (non inglês) di dulà che il contignût multimediâl al è stât regjistrât " +"o prodot" + +msgid "geo location city" +msgstr "citât posizion gjeog." + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"citât (non inglês) di dulà che il contignût multimediâl al è stât regjistrât " +"o prodot" + +msgid "geo location sublocation" +msgstr "" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +msgid "geo location horizontal error" +msgstr "" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +msgid "geo location movement direction" +msgstr "" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +msgid "geo location capture direction" +msgstr "" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "mostre non" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "mostre non ordenament" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +msgid "episode number" +msgstr "numar episodi" + +msgid "The episode number in the season the media is part of" +msgstr "" +"Il numar di episodi inte stagjon dulà che al fâs part il contignût " +"multimediâl" + +msgid "season number" +msgstr "numar stagjon" + +msgid "The season number of the show the media is part of" +msgstr "" +"Il numar di stagjon dal spetacul dulà che al fâs part il contignût " +"multimediâl" + +msgid "lyrics" +msgstr "" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "non ordenament compositôr" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" +"persone(-is) che e à componût la regjistrazion, par motîfs di ordenament" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +msgid "user rating" +msgstr "valutazion utent" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Valutazion dade di un utent. Plui alt al è il nivel, plui al utent i plâs " +"chest contignût multimediâl" + +msgid "device manufacturer" +msgstr "produtôr dispositîf" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricant dal dispositîf doprât par creâ chest contignût multimediâl" + +msgid "device model" +msgstr "model dispositîf" + +msgid "Model of the device used to create this media" +msgstr "Model dal dispositîf doprât par creâ chest contignût multimediâl" + +msgid "application name" +msgstr "non aplicazion" + +msgid "Application used to create the media" +msgstr "Aplicazion doprade par creâ chest contignût multimediâl" + +msgid "application data" +msgstr "dâts aplicazion" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "orientament imagjin" + +msgid "How the image should be rotated or flipped before display" +msgstr "" +"Ce mût che la imagjin e varès di jessi voltade o ribaltade prime di mostrâle" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +msgid "Delayed linking failed." +msgstr "" + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "" + +#, c-format +msgid "could not link %s to %s" +msgstr "" + +#, c-format +msgid "no element \"%s\"" +msgstr "" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "" + +msgid "syntax error" +msgstr "erôr di sintassi" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "" + +msgid "empty pipeline not allowed" +msgstr "" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Nissune cartele temporanie specificade." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Impussibil creâ il file temporani \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Impussibil vierzi il file \"%s\" pe leture." + +msgid "Error while writing to download file." +msgstr "" + +msgid "No file name specified for writing." +msgstr "Nissun non di file specificât pe scriture." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Impussibil vierzi il file \"%s\" pe scriture." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Erôr tal sierâ il file \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Erôr tal cirî tal file \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Erôr tal scrivi sul file \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nissun non di file specificât pe leture." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" e je une cartele." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Il file \"%s\" al è un socket." + +msgid "Failed after iterations as requested." +msgstr "" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "" + +msgid "minimum" +msgstr "" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +msgid "Stream doesn't contain enough data." +msgstr "Il flus nol conten vonde dâts." + +msgid "Stream contains no data." +msgstr "Il flus nol conten dâts." + +msgid "Implemented Interfaces:\n" +msgstr "Interfacis implementadis:\n" + +msgid "readable" +msgstr "" + +msgid "writable" +msgstr "" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "File te liste nere:" + +msgid "Total count: " +msgstr "Conte totâl: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d file in liste nere" +msgstr[1] "%d file in liste nere" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugin" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d vôs te liste nere" +msgstr[1] "%d vôs te liste nere" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funzionalitât" +msgstr[1] "%d funzionalitâts" + +msgid "Print all elements" +msgstr "Stampe ducj i elements" + +msgid "Print list of blacklisted files" +msgstr "Stampe la liste dai file metûts in liste nere" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Impussibil cjariâ file di plugin: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TAG\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Progrès: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Element mancjant: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "" + +msgid "Output tags (also known as metadata)" +msgstr "" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "" + +msgid "Do not print any progress information" +msgstr "No stâ stampâ nissune informazion di progrès" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +msgid "Freeing pipeline ...\n" +msgstr "" diff --git a/po/gl.gmo b/po/gl.gmo new file mode 100644 index 0000000..09f07f7 Binary files /dev/null and b/po/gl.gmo differ diff --git a/po/gl.po b/po/gl.po new file mode 100644 index 0000000..00165d7 --- /dev/null +++ b/po/gl.po @@ -0,0 +1,1389 @@ +# Galician translations for gstreamer package. +# This file is put in the public domain. +# Francisco Diéguez , 2011. +# Fran Dieguez , 2012. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.0.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2012-12-15 03:29+0200\n" +"Last-Translator: Fran Dieguez \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-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +msgid "Print the GStreamer version" +msgstr "Imprimir a versión de GStreamer" + +msgid "Make all warnings fatal" +msgstr "Facer todas as advertencias fatais" + +msgid "Print available debug categories and exit" +msgstr "Imprimir as categorías de depuración dispoñíbeis e saír" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Nivel de depuración por omisión desde 1 (só erro) até 5 (todo) ou 0 sen saída" + +msgid "LEVEL" +msgstr "NIVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Lista de pares nome_categoría:nivel separados por comas para estabelecer " +"niveis específicos para as categorías individuais. Exemplo: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Desactivar a coloración da saída depurada" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Desactivar depuración" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Activar a saída detallada do diagnóstico de carga de engadidos" + +msgid "Colon-separated paths containing plugins" +msgstr "Rutas separadas por punto e coma contendo os engadidos" + +msgid "PATHS" +msgstr "RUTAS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Lista de engadidos para precargar separados por comas ademais da lista " +"almacenada na variábel de contorno GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "COMPLEMENTOS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Desactivar a captura de fallos de segmentación durante a carga de engadidos" + +msgid "Disable updating the registry" +msgstr "Desactivar a actualización do rexistro" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Desactivar o lanzamento dun proceso de axuda ao escanear o rexistro" + +msgid "GStreamer Options" +msgstr "Opcións de GStreamer" + +msgid "Show GStreamer Options" +msgstr "Mostrar as opcións de GStreamer" + +msgid "Unknown option" +msgstr "Opción descoñecida" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer encontrou un erro xeral no núcleo da biblioteca." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Os desenvolvedores de GStreamer foron demasiado vagos para engadir un código " +"de erro a este erro." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Erro interno de GStreamer: código non implementado." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Produciuse un erro de GStreamer: produciuse un fallo durante o cambio de " +"estado e algún elemento fracasou ao publicar a mensaxe de erro " +"correspondente co motivo do fallo." + +msgid "Internal GStreamer error: pad problem." +msgstr "Erro interno de GStreamer: problema de desprazamento." + +msgid "Internal GStreamer error: thread problem." +msgstr "Erro interno de GStreamer: problema cos fíos" + +msgid "GStreamer error: negotiation problem." +msgstr "Erro de GStreamer: problema de negociación." + +msgid "Internal GStreamer error: event problem." +msgstr "Erro interno de GStreamer: problema cos eventos." + +msgid "Internal GStreamer error: seek problem." +msgstr "Erro interno de GStreamer: problema coa busca." + +msgid "Internal GStreamer error: caps problem." +msgstr "Erro interno de GStreamer: probema coas capacidades." + +msgid "Internal GStreamer error: tag problem." +msgstr "Erro interno de GStreamer: problema coas etiquetas." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Á súa instalación de GStreamer fáltalle un engadido." + +msgid "GStreamer error: clock problem." +msgstr "Erro de GStreamer: problema de reloxo." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Este aplicativo está tentando usar unha funcionalidade de GStreamer que foi " +"deshabilitada." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer atopou un erro de compatibilidade xeral na biblioteca." + +msgid "Could not initialize supporting library." +msgstr "Nonon foi posíbel iniciar a biblioteca de compatibilidade." + +msgid "Could not close supporting library." +msgstr "Non foi posíbel pehar a biblioteca de asistencia." + +msgid "Could not configure supporting library." +msgstr "Non foi posíbel configurar a biblioteca de asistencia." + +msgid "Encoding error." +msgstr "Erro de codificación." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer encontrou un erro xeral de recurso." + +msgid "Resource not found." +msgstr "Recurso non encontrado." + +msgid "Resource busy or not available." +msgstr "O recurso está ocupado ou non dispoñíbel." + +msgid "Could not open resource for reading." +msgstr "Non foi posíbel abrir o recurso para a súa lectura." + +msgid "Could not open resource for writing." +msgstr "Non foi posíbel abrir o recurso para a súa escritura." + +msgid "Could not open resource for reading and writing." +msgstr "Non foi posíbel abrir o recurso para a súa lectura ou escritura." + +msgid "Could not close resource." +msgstr "Non foi posíbel pechar o recurso." + +msgid "Could not read from resource." +msgstr "Non foi posíbel ler desde o recurso." + +msgid "Could not write to resource." +msgstr "Non foi posíbel escribir no recurso." + +msgid "Could not perform seek on resource." +msgstr "Non foi posíbel realizar unha busca no recurso." + +msgid "Could not synchronize on resource." +msgstr "Non foi posíbel sincronizar o recurso." + +msgid "Could not get/set settings from/on resource." +msgstr "Non foi posíbel obter/estabelecer a configuración de/en o recurso." + +msgid "No space left on the resource." +msgstr "Non queda espacio dispoñíbel no recurso." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Non queda espacio dispoñíbel no recurso." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer encontrou un erro xeral de fluxo." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"O elemento non implementa un manexador deste fluxo. Por favor, complete o " +"informe e erro." + +msgid "Could not determine type of stream." +msgstr "Non foi posíbel determinar o tipo de fluxo." + +msgid "The stream is of a different type than handled by this element." +msgstr "O fluxo é dun tipo diferente que o manexado por este elemento." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Non hai un códec dispoñíbel que poida manexar este tipo de fluxo." + +msgid "Could not decode stream." +msgstr "Non foi posíbel descodificar o fluxo." + +msgid "Could not encode stream." +msgstr "Non foi posíbel codificar o fluxo." + +msgid "Could not demultiplex stream." +msgstr "Non foi posíbel demultiplexar o fluxo." + +msgid "Could not multiplex stream." +msgstr "Non foi posíbel multiplexar o fluxo." + +msgid "The stream is in the wrong format." +msgstr "O fluxo está no formato incorrecto." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "O fluxo está cifrado e o descrifrado non é posíbel." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"O fluxo está cifrado e non é posíbel descifralo porque non se forneceu a " +"chave axeitada." + +#, c-format +msgid "No error message for domain %s." +msgstr "Non hai unha mensaxe de erro para o dominio %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Non hai unha mensaxe de erro estándar par ao dominio %s e código %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Non é posíbel usar o reloxo seleccionado na canalización." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "título" + +msgid "commonly used title" +msgstr "título usado de forma común" + +msgid "title sortname" +msgstr "nome de ordenación do título" + +msgid "commonly used title for sorting purposes" +msgstr "título usado comunmente para propósitos de ordenamento" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "persoa(s) responsábel(eis) da gravación" + +msgid "artist sortname" +msgstr "nome de ordenación do artista" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persoa(s) responsábel(eis) da gravación para propósitos de ordenamento" + +msgid "album" +msgstr "álbume" + +msgid "album containing this data" +msgstr "o álbum que conten estes datos" + +msgid "album sortname" +msgstr "nome de ordenación do álbume" + +msgid "album containing this data for sorting purposes" +msgstr "o álbum que conten estes datos para propósitos de ordenamento" + +msgid "album artist" +msgstr "artista do álbume" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "O artista do álbum enteiro, como se debería mostrar" + +msgid "album artist sortname" +msgstr "nome de ordenación do artista do álbume" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "O artista do álbum enteiro, como se debería ordenar" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data na que se crearon os datos (como estrutura GDate)" + +msgid "datetime" +msgstr "data e hora" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data e hora na que se crearon os datos (como estrutura GstDateTime)" + +msgid "genre" +msgstr "xénero" + +msgid "genre this data belongs to" +msgstr "xénero ao que pertencen estes datos" + +msgid "comment" +msgstr "comentario" + +msgid "free text commenting the data" +msgstr "comentario de texto sobre os datos" + +msgid "extended comment" +msgstr "comentario estendido" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"texto libre comentando os datos como key=valor ou key[gl]=formulario de " +"comentario" + +msgid "track number" +msgstr "número de pista" + +msgid "track number inside a collection" +msgstr "número de pista nunha colección" + +msgid "track count" +msgstr "número de pistas" + +msgid "count of tracks inside collection this track belongs to" +msgstr "número de pistas na colección á que pertence a pista" + +msgid "disc number" +msgstr "número de disco" + +msgid "disc number inside a collection" +msgstr "número do disco dentro dunha colección" + +msgid "disc count" +msgstr "número de discos" + +msgid "count of discs inside collection this disc belongs to" +msgstr "número de discos na colección á que pertence o disco" + +msgid "location" +msgstr "localización" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Orixe do medio como un URI (localización, onde está aloxado o ficheiro ou " +"fluxo orixinal)" + +msgid "homepage" +msgstr "sitio web" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Páxina principal para este medio (p.ex. páxina principal do artista ou filme)" + +msgid "description" +msgstr "descrición" + +msgid "short text describing the content of the data" +msgstr "texto curto describindo o contido dos datos" + +msgid "version" +msgstr "versión" + +msgid "version of this data" +msgstr "versión destes datos" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code; consulte http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organización" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "nota de dereitos de autoría dos datos" + +msgid "copyright uri" +msgstr "URI aos dereitos de autor" + +msgid "URI to the copyright notice of the data" +msgstr "URI á nota de dereitos de autoría dos datos" + +msgid "encoded by" +msgstr "codificado por" + +msgid "name of the encoding person or organization" +msgstr "nome da persoa ou organización codificadora" + +msgid "contact" +msgstr "contacto" + +msgid "contact information" +msgstr "información de contacto" + +msgid "license" +msgstr "licenza" + +msgid "license of data" +msgstr "licenza dos datos" + +msgid "license uri" +msgstr "URI á licenza" + +msgid "URI to the license of the data" +msgstr "URI á licenza dos datos" + +msgid "performer" +msgstr "intérprete" + +msgid "person(s) performing" +msgstr "persoa(s) interpretando" + +msgid "composer" +msgstr "compositor" + +msgid "person(s) who composed the recording" +msgstr "persoa(s) que compuxeron a gravación" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "duración" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "duración en unidades de tempo GStreamer (nanosegundos)" + +msgid "codec" +msgstr "códec" + +msgid "codec the data is stored in" +msgstr "códec no que se almacenan os datos" + +msgid "video codec" +msgstr "códec de vídeo" + +msgid "codec the video data is stored in" +msgstr "códec no que se almacenan os datos do vídeo" + +msgid "audio codec" +msgstr "códec de son" + +msgid "codec the audio data is stored in" +msgstr "códec no que se almacenan os datos do son" + +msgid "subtitle codec" +msgstr "códec do subtitulo" + +msgid "codec the subtitle data is stored in" +msgstr "códec no que se almacenan os datos dos subtítulos" + +msgid "container format" +msgstr "formato do contedor" + +msgid "container format the data is stored in" +msgstr "formato do contedor no que se almacenan os datos" + +msgid "bitrate" +msgstr "taxa de bits" + +msgid "exact or average bitrate in bits/s" +msgstr "taxa de bits exacta ou promedio en bits/s" + +msgid "nominal bitrate" +msgstr "taxa de bits nominal" + +msgid "nominal bitrate in bits/s" +msgstr "taxa de bits nominal en bits/s" + +msgid "minimum bitrate" +msgstr "taxa de bits mínima" + +msgid "minimum bitrate in bits/s" +msgstr "taxa mínima de bits en bits/s" + +msgid "maximum bitrate" +msgstr "taxa de bits máxima" + +msgid "maximum bitrate in bits/s" +msgstr "taxa máxima de bits en bits/s" + +msgid "encoder" +msgstr "codificador" + +msgid "encoder used to encode this stream" +msgstr "codificador usado para codificar este fluxo" + +msgid "encoder version" +msgstr "versión do codificador" + +msgid "version of the encoder used to encode this stream" +msgstr "versión do codificador usado para codificar este fluxo" + +msgid "serial" +msgstr "serie" + +msgid "serial number of track" +msgstr "número de serie da pista" + +msgid "replaygain track gain" +msgstr "ganancia da pista (ReplayGain)" + +msgid "track gain in db" +msgstr "ganancia da pista en dB" + +msgid "replaygain track peak" +msgstr "pico da pista (ReplayGain)" + +msgid "peak of the track" +msgstr "pico da pista" + +msgid "replaygain album gain" +msgstr "ganancia do álbum (ReplayGain)" + +msgid "album gain in db" +msgstr "ganancia do álbum en dB" + +msgid "replaygain album peak" +msgstr "pico do álbum (ReplayGain)" + +msgid "peak of the album" +msgstr "pico do álbum" + +msgid "replaygain reference level" +msgstr "nivel de referencia (ReplayGain)" + +msgid "reference level of track and album gain values" +msgstr "valor do nivel de referencia da ganancia da pista e do álbum" + +msgid "language code" +msgstr "código de idioma" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "código de idioma para este fluxo, axustándose a ISO-639-1 ou ISO-639-2" + +msgid "language name" +msgstr "nome do idioma" + +msgid "freeform name of the language this stream is in" +msgstr "nome freeform do idioma no que está este fluxo" + +msgid "image" +msgstr "imaxe" + +msgid "image related to this stream" +msgstr "imaxe relacionada con este fluxo" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "previsualizar imaxe" + +msgid "preview image related to this stream" +msgstr "vista previa da imaxe relacionada con este fluxo" + +msgid "attachment" +msgstr "anexo" + +msgid "file attached to this stream" +msgstr "ficheiro anexo a este fluxo" + +msgid "beats per minute" +msgstr "golpes por minuto (bpm)" + +msgid "number of beats per minute in audio" +msgstr "número de golpes por minuto (bpm) no son" + +msgid "keywords" +msgstr "palabras chave" + +msgid "comma separated keywords describing the content" +msgstr "palabras clave separadas por comas describindo o contido" + +msgid "geo location name" +msgstr "nome da xeolocalización" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"descrición da localización entendíbel por humanos de onde foi gravado ou " +"producido o medio" + +msgid "geo location latitude" +msgstr "latitude da xeolocalización" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitude xeográfica onde foi gravado ou producido o medio, en graos conforme " +"a WGS84 (cero é o ecuador, valores negativos para latitudes meridionais)" + +msgid "geo location longitude" +msgstr "lonxitude da xeolocalización" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"lonxitude xeográfica onde foi gravado ou producido o medio, en graos " +"conforme a WGS84 (cero é o primeiro meridiano en Greenwich/GB, valores " +"negativos para lonxitudes occidentais)" + +msgid "geo location elevation" +msgstr "elevación da xeolocalización" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"elevación xeográfica onde foi gravado ou producido o medio, en graos " +"conforme a WGS84 (cero é o nivel medio do mar)" + +msgid "geo location country" +msgstr "país da xeolocalización" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "país (nome en inglés) onde foi gravado ou producido o medio" + +msgid "geo location city" +msgstr "cidade da xeolocalización" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "cidade (nome en inglés) onde foi gravado ou producido o medio" + +msgid "geo location sublocation" +msgstr "sublocalización da xeolocalización" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"unha localización nunha cidade onde foi gravado ou producido o medio (p.ex. " +"o barrio)" + +msgid "geo location horizontal error" +msgstr "erro horizontal de xeolocalización" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "erro esperado das medidas de posicionamento horizontal (en metros)" + +msgid "geo location movement speed" +msgstr "velocidade de movemento da xeolocalización" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"velocidade de movemento do dispositivo de captura mentres realiza a captura, " +"en m/s" + +msgid "geo location movement direction" +msgstr "dirección de movemento da xeolocalización" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica a dirección do movemento do dispositivo que realiza a captura dun " +"medio. Representase en graos ou nunha representación en coma flotante, 0 " +"corresponde ao norte xeográfico e incrementa de forma horaria." + +msgid "geo location capture direction" +msgstr "dirección de captura da xeolocalización" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica a dirección na que apunta o dispositivo que realiza a captura dun " +"medio. Representase en graos ou nunha representación en coma flotante, 0 " +"corresponde ao norte xeográfico e incrementa de forma horaria." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nome do programa" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nome do programa/podcast/serie" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nome de ordenación do programa" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Nome do programa/podcast/serie, para propósitos de ordenación" + +msgid "episode number" +msgstr "número de episodio" + +msgid "The episode number in the season the media is part of" +msgstr "O número do capítulo na tempada" + +msgid "season number" +msgstr "número de tempada" + +msgid "The season number of the show the media is part of" +msgstr "O número de tempada do programa" + +msgid "lyrics" +msgstr "letras" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "As letras do ficheiro multimedia, xeralmente usado para cancións" + +msgid "composer sortname" +msgstr "nome curto do compositor" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "pesoa(s) que compuxeron a gravación, para propósitos de ordenamento" + +msgid "grouping" +msgstr "agrupación" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Agrupa temas relacionados que se expanden varias pistas, como as diferentes " +"partes dun concerto. É un nivel máis alto que o dunha pista, pero máis baixo " +"que o dun álbum." + +msgid "user rating" +msgstr "puntuación do usuario" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Puntuación atribuída por un usuario. Canto maior sexa a puntuación mais lle " +"gustará ao usuario." + +msgid "device manufacturer" +msgstr "fabricante do dispositivo" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricante do dispositivo usado para crear este medio" + +msgid "device model" +msgstr "modelo do dispositivo" + +msgid "Model of the device used to create this media" +msgstr "Modelo do dispositivo usado para crear este medio" + +msgid "application name" +msgstr "nome do aplicativo" + +msgid "Application used to create the media" +msgstr "Aplicativo usado para crear o medio" + +msgid "application data" +msgstr "datos do aplicativo" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Datos arbitrarios do aplicativo para serializalos no medio" + +msgid "image orientation" +msgstr "orientación da imaxe" + +msgid "How the image should be rotated or flipped before display" +msgstr "Como se debería rotar ou voltear a imaxe antes de mostrala" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERRO: do elemento %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Información adicional de depuración:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "non hai unha propiedade «%s» no elemento «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "non foi posíbel estabelecer a propiedade «%s» no elemento «%s» a «%s»" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "non foi posíbel ligar %s a %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "non foi posíbel ligar o elemento sumidoiro para o URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "non foi posíbel ligar %s a %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "non foi posíbel ligar %s a %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "non hai un elemento «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "non foi posíbel analizar as capacidades «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "non existe o elemento sumidoiro para o URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "non existe un elemento orixe para o URI «%s»" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "o binario especificado «%s» está baleiro, non está permitido" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "non existe o binario «%s», omitindo" + +msgid "empty pipeline not allowed" +msgstr "non se permite unha canalización baleira" + +msgid "A lot of buffers are being dropped." +msgstr "Estanse a desbotar moitos búferes." + +msgid "Internal data flow problem." +msgstr "Hai un problema no fluxo interno de datos." + +msgid "Internal data flow error." +msgstr "Produciuse un erro no fluxo interno de datos." + +msgid "Internal clock error." +msgstr "Produciuse un erro no reloxo interno." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Filtro de capacidades" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restrinxir as posíbeis capacidades permitidas (NULL significa CALQUERA). Ao " +"estabelecer esta propiedade obtense unha referencia do obxecto GstCaps " +"fornecido." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Non se especificou un directorio temporal." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Non foi posíbel crear o ficheiro temporal «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Non foi posíbel abrir o ficheiro «%s» para ler." + +msgid "Error while writing to download file." +msgstr "Produciuse un erro de escritura ao descargar o ficheiro." + +msgid "No file name specified for writing." +msgstr "Non se especificou un nome de ficheiro para escritura." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Non foi posíbel abrir «%s» para escribir." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Produciuse un erro ao pechar o ficheiro «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Produciuse un erro ao buscar no ficheiro «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Produciuse un erro ao escribir no ficheiro «%s»." + +msgid "No file name specified for reading." +msgstr "Non se especificou un nome de ficheiro para a lectura." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Non foi posíbel obter a información de «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» é un directorio." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "O ficheiro «%s» é un socket." + +msgid "Failed after iterations as requested." +msgstr "Produciuse un fallo despois das iteracións que se solicitaron." + +msgid "caps" +msgstr "capacidades" + +msgid "detected capabilities in stream" +msgstr "capacidades detectadas no fluxo" + +msgid "minimum" +msgstr "mínimo" + +msgid "force caps" +msgstr "forzar as capacidades" + +msgid "force caps without doing a typefind" +msgstr "forzar as capacidades sen facer un «typefind»" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "O fluxo non contén datos." + +msgid "Stream contains no data." +msgstr "O fluxo non contén datos." + +msgid "Implemented Interfaces:\n" +msgstr "Interfaces implementadas:\n" + +msgid "readable" +msgstr "lexíbel" + +msgid "writable" +msgstr "escribíbel" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "controlábel" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "intercambiábel entre os estados NULL, READY, PAUSED ou PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "intercambiábel só entre os estados NULL, READY ou PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "intercambiábel só entre os estados NULL ou READY" + +msgid "Blacklisted files:" +msgstr "Ficheiros na lista negra:" + +msgid "Total count: " +msgstr "Contía total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d ficheiro na lista negra" +msgstr[1] "%d ficheiros na lista negra" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d engadido" +msgstr[1] "%d engadidos" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entrada na lista negra" +msgstr[1] "%d entradas na lista negra" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d característica" +msgstr[1] "%d características" + +msgid "Print all elements" +msgstr "Imprimir todos os elementos" + +msgid "Print list of blacklisted files" +msgstr "Imprimir lista dos ficheiros na lista negra" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Imprimir unha lista de características analizábeis por unha máquina do " +"engadido especificado ou fornecer todos os engadidos.\n" +" Útil xunto con mecanismos de " +"instalación externa automática de engadidos." + +msgid "List the plugin contents" +msgstr "Listar o contido do engadido" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "Comprobar se o elemento ou engadido especificado existe" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Ao comprobar se un elemento ou engadido existe, tamén comprobar se a súa " +"versión é cando menos a versión especificada" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Imprimir os esquemas URI admitidos, cos elementos que os implementan" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Non foi posíbel cargar o ficheiro do engadido: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Non existe o elemento ou engadido «%s»\n" + +msgid "Index statistics" +msgstr "Estatísticas do índice" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Obtívose a mensaxe nº %u do elemento «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Obtívose a mensaxe nº %u da cela «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Obtívose a mensaxe nº %u do obxecto «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Obtívose a mensaxe num. %u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Obtívose un EOS do elemento «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ATOPADA ETIQUETA : atopada polo elemento «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ATOPADA ETIQUETA : atopada pola cela «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETIQUETA ENCONTRADA : encontrada polo obxecto «%s».\n" + +msgid "FOUND TAG\n" +msgstr "ETIQUETA ENCONTRADA\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TOC ATOPADO : atopado polo elemento «%s».\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TOC ATOPADO : encontrado polo obxecto «%s».\n" + +msgid "FOUND TOC\n" +msgstr "TOC ATOPADO\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACIÓN:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVISO: do elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Preparado, agardando a encher o búfer para rematar…\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Preparado, agardando a encher o búfer para rematar…\n" + +msgid "buffering..." +msgstr "almacenando no búfer…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Rematouse de almacenar no búfer, estabelecendo a canalización para " +"REPRODUCIR...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Almacenando no búfer, estabelecendo a canalización a PAUSADA...\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribuír latencia...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Estabelecendo o estado a %s segundo foi solicitado por %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interromper: parando a canalización …\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Elemento que falta: «%s»\n" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "AVISO: do elemento %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Etiquetas de saída (tamén coñecido como metadatos)" + +msgid "Output TOC (chapters and editions)" +msgstr "TOC de saída (capítulos e edicións)" + +msgid "Output status information and property notifications" +msgstr "Información do estado da saída e notificacións das propiedades" + +msgid "Do not print any progress information" +msgstr "Non mostrar ningunha información de progreso" + +msgid "Output messages" +msgstr "Mensaxes de saída" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Non instalar un manexador predeterminado" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forzar EOS nas orixes antes de pechar a canalización" + +msgid "Gather and print index statistics" +msgstr "Obter e imprimir as estatísticas do índice" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERRO: non foi posíbel construír a canalización: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERRO: non foi posíbel construír a canalización.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "AVISO: canalización errónea: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERRO: o elemento «canalización» non foi atopado.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Estabelecendo a tubería a PAUSA...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERROR: A tubería non quere pausarse.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "A tubería está viva e non necesita PREPARARSE...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "A tubería está PREPARÁNDOSE...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERRO: a tubería non quere prepararse.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "A tubería está PREPARADA...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Estabelecendo a tubería a REPRODUCINDO.\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERRO: a tubería non quere reproducirse.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS ao apagar activado; Forzando EOS na tubería\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS ao apagar activado; -- agardando polo EOS despois de erro\n" + +msgid "Waiting for EOS...\n" +msgstr "Agardando pola EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS recibido: detendo a tubería...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interromper ao agardar polo EOS - detendo a canalización…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Produciuse un erro ao esperar a EOS\n" + +msgid "Execution ended after %" +msgstr "A execución rematou despois de %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Estabelecendo a tubería a PREPARADO...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Estabelecendo a tubería a NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Liberando a tubería...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Produciuse un erro no fluxo interno de datos." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Non sacar a saída da información de estado do TIPO" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPO1,TIPO2,…" + +#~ msgid "link without source element" +#~ msgstr "ligazón sen elemento orixe" + +#~ msgid "link without sink element" +#~ msgstr "ligazón sen elemento sumidoiro" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "non existe un elemento co que ligar o URI «%s»" + +#~ msgid "maximum" +#~ msgstr "máximo" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Uso: gst-xmllaunch [ propiedade.do.elemento=valor … ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERRO: non foi posíbel analizar o ficheiro xml «%s».\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERRO: non existe o elemento de nivel superior da canalización no ficheiro " +#~ "«%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "AVISO: neste momento só se admite un elemento de nivel superior.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERRO: non foi posíbel analizar o argumento %d da liña de ordes: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "AVISO: non se atopou o elemento nomeado «%s».\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Gardar a representación xml da canalización a un FICHEIRO e saír" + +#~ msgid "FILE" +#~ msgstr "FICHEIRO" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Non instalar os manexadores de sinais para SIGUSR1 e SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Imprimir a traza de asignacións (se foi activada ao compilar)" diff --git a/po/gstreamer-1.0.pot b/po/gstreamer-1.0.pot new file mode 100644 index 0000000..060259f --- /dev/null +++ b/po/gstreamer-1.0.pot @@ -0,0 +1,1645 @@ +# SOME DESCRIPTIVE TITLE. +# This file is put in the public domain. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.14.1\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: gst/gst.c:250 +msgid "Print the GStreamer version" +msgstr "" + +#: gst/gst.c:252 +msgid "Make all warnings fatal" +msgstr "" + +#: gst/gst.c:256 +msgid "Print available debug categories and exit" +msgstr "" + +#: gst/gst.c:260 +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" + +#: gst/gst.c:262 +msgid "LEVEL" +msgstr "" + +#: gst/gst.c:264 +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" + +#: gst/gst.c:267 +msgid "LIST" +msgstr "" + +#: gst/gst.c:269 +msgid "Disable colored debugging output" +msgstr "" + +#: gst/gst.c:273 +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +#: gst/gst.c:277 +msgid "Disable debugging" +msgstr "" + +#: gst/gst.c:281 +msgid "Enable verbose plugin loading diagnostics" +msgstr "" + +#: gst/gst.c:285 +msgid "Colon-separated paths containing plugins" +msgstr "" + +#: gst/gst.c:285 +msgid "PATHS" +msgstr "" + +#: gst/gst.c:288 +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +#: gst/gst.c:290 +msgid "PLUGINS" +msgstr "" + +#: gst/gst.c:293 +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" + +#: gst/gst.c:298 +msgid "Disable updating the registry" +msgstr "" + +#: gst/gst.c:303 +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +#: gst/gst.c:308 +msgid "GStreamer Options" +msgstr "" + +#: gst/gst.c:309 +msgid "Show GStreamer Options" +msgstr "" + +#: gst/gst.c:1012 +msgid "Unknown option" +msgstr "" + +#: gst/gsterror.c:130 +msgid "GStreamer encountered a general core library error." +msgstr "" + +#: gst/gsterror.c:132 gst/gsterror.c:174 gst/gsterror.c:198 gst/gsterror.c:240 +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +#: gst/gsterror.c:135 +msgid "Internal GStreamer error: code not implemented." +msgstr "" + +#: gst/gsterror.c:137 +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +#: gst/gsterror.c:140 +msgid "Internal GStreamer error: pad problem." +msgstr "" + +#: gst/gsterror.c:142 +msgid "Internal GStreamer error: thread problem." +msgstr "" + +#: gst/gsterror.c:144 +msgid "GStreamer error: negotiation problem." +msgstr "" + +#: gst/gsterror.c:146 +msgid "Internal GStreamer error: event problem." +msgstr "" + +#: gst/gsterror.c:148 +msgid "Internal GStreamer error: seek problem." +msgstr "" + +#: gst/gsterror.c:150 +msgid "Internal GStreamer error: caps problem." +msgstr "" + +#: gst/gsterror.c:152 +msgid "Internal GStreamer error: tag problem." +msgstr "" + +#: gst/gsterror.c:154 +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +#: gst/gsterror.c:156 +msgid "GStreamer error: clock problem." +msgstr "" + +#: gst/gsterror.c:158 +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +#: gst/gsterror.c:172 +msgid "GStreamer encountered a general supporting library error." +msgstr "" + +#: gst/gsterror.c:177 +msgid "Could not initialize supporting library." +msgstr "" + +#: gst/gsterror.c:179 +msgid "Could not close supporting library." +msgstr "" + +#: gst/gsterror.c:181 +msgid "Could not configure supporting library." +msgstr "" + +#: gst/gsterror.c:183 +msgid "Encoding error." +msgstr "" + +#: gst/gsterror.c:196 +msgid "GStreamer encountered a general resource error." +msgstr "" + +#: gst/gsterror.c:201 +msgid "Resource not found." +msgstr "" + +#: gst/gsterror.c:203 +msgid "Resource busy or not available." +msgstr "" + +#: gst/gsterror.c:205 +msgid "Could not open resource for reading." +msgstr "" + +#: gst/gsterror.c:207 +msgid "Could not open resource for writing." +msgstr "" + +#: gst/gsterror.c:209 +msgid "Could not open resource for reading and writing." +msgstr "" + +#: gst/gsterror.c:211 +msgid "Could not close resource." +msgstr "" + +#: gst/gsterror.c:213 +msgid "Could not read from resource." +msgstr "" + +#: gst/gsterror.c:215 +msgid "Could not write to resource." +msgstr "" + +#: gst/gsterror.c:217 +msgid "Could not perform seek on resource." +msgstr "" + +#: gst/gsterror.c:219 +msgid "Could not synchronize on resource." +msgstr "" + +#: gst/gsterror.c:221 +msgid "Could not get/set settings from/on resource." +msgstr "" + +#: gst/gsterror.c:223 +msgid "No space left on the resource." +msgstr "" + +#: gst/gsterror.c:225 +msgid "Not authorized to access resource." +msgstr "" + +#: gst/gsterror.c:238 +msgid "GStreamer encountered a general stream error." +msgstr "" + +#: gst/gsterror.c:243 +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" + +#: gst/gsterror.c:246 +msgid "Could not determine type of stream." +msgstr "" + +#: gst/gsterror.c:248 +msgid "The stream is of a different type than handled by this element." +msgstr "" + +#: gst/gsterror.c:251 +msgid "There is no codec present that can handle the stream's type." +msgstr "" + +#: gst/gsterror.c:253 +msgid "Could not decode stream." +msgstr "" + +#: gst/gsterror.c:255 +msgid "Could not encode stream." +msgstr "" + +#: gst/gsterror.c:257 +msgid "Could not demultiplex stream." +msgstr "" + +#: gst/gsterror.c:259 +msgid "Could not multiplex stream." +msgstr "" + +#: gst/gsterror.c:261 +msgid "The stream is in the wrong format." +msgstr "" + +#: gst/gsterror.c:263 +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +#: gst/gsterror.c:265 +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#: gst/gsterror.c:305 +#, c-format +msgid "No error message for domain %s." +msgstr "" + +#: gst/gsterror.c:313 +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" + +#: gst/gstpipeline.c:566 +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#: gst/gstregistry.c:1698 +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +#: gst/gsttaglist.c:108 +msgid "title" +msgstr "" + +#: gst/gsttaglist.c:108 +msgid "commonly used title" +msgstr "" + +#: gst/gsttaglist.c:111 +msgid "title sortname" +msgstr "" + +#: gst/gsttaglist.c:111 +msgid "commonly used title for sorting purposes" +msgstr "" + +#: gst/gsttaglist.c:114 +msgid "artist" +msgstr "" + +#: gst/gsttaglist.c:115 +msgid "person(s) responsible for the recording" +msgstr "" + +#: gst/gsttaglist.c:119 +msgid "artist sortname" +msgstr "" + +#: gst/gsttaglist.c:120 +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" + +#: gst/gsttaglist.c:123 +msgid "album" +msgstr "" + +#: gst/gsttaglist.c:124 +msgid "album containing this data" +msgstr "" + +#: gst/gsttaglist.c:127 +msgid "album sortname" +msgstr "" + +#: gst/gsttaglist.c:128 +msgid "album containing this data for sorting purposes" +msgstr "" + +#: gst/gsttaglist.c:131 +msgid "album artist" +msgstr "" + +#: gst/gsttaglist.c:132 +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +#: gst/gsttaglist.c:136 +msgid "album artist sortname" +msgstr "" + +#: gst/gsttaglist.c:137 +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +#: gst/gsttaglist.c:139 +msgid "date" +msgstr "" + +#: gst/gsttaglist.c:139 +msgid "date the data was created (as a GDate structure)" +msgstr "" + +#: gst/gsttaglist.c:141 +msgid "datetime" +msgstr "" + +#: gst/gsttaglist.c:142 +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" + +#: gst/gsttaglist.c:146 +msgid "genre" +msgstr "" + +#: gst/gsttaglist.c:147 +msgid "genre this data belongs to" +msgstr "" + +#: gst/gsttaglist.c:150 +msgid "comment" +msgstr "" + +#: gst/gsttaglist.c:151 +msgid "free text commenting the data" +msgstr "" + +#: gst/gsttaglist.c:154 +msgid "extended comment" +msgstr "" + +#: gst/gsttaglist.c:155 +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" + +#: gst/gsttaglist.c:159 +msgid "track number" +msgstr "" + +#: gst/gsttaglist.c:160 +msgid "track number inside a collection" +msgstr "" + +#: gst/gsttaglist.c:163 +msgid "track count" +msgstr "" + +#: gst/gsttaglist.c:164 +msgid "count of tracks inside collection this track belongs to" +msgstr "" + +#: gst/gsttaglist.c:168 +msgid "disc number" +msgstr "" + +#: gst/gsttaglist.c:169 +msgid "disc number inside a collection" +msgstr "" + +#: gst/gsttaglist.c:172 +msgid "disc count" +msgstr "" + +#: gst/gsttaglist.c:173 +msgid "count of discs inside collection this disc belongs to" +msgstr "" + +#: gst/gsttaglist.c:177 +msgid "location" +msgstr "" + +#: gst/gsttaglist.c:177 +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +#: gst/gsttaglist.c:182 +msgid "homepage" +msgstr "" + +#: gst/gsttaglist.c:183 +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +#: gst/gsttaglist.c:186 +msgid "description" +msgstr "" + +#: gst/gsttaglist.c:187 +msgid "short text describing the content of the data" +msgstr "" + +#: gst/gsttaglist.c:190 +msgid "version" +msgstr "" + +#: gst/gsttaglist.c:190 +msgid "version of this data" +msgstr "" + +#: gst/gsttaglist.c:192 +msgid "ISRC" +msgstr "" + +#: gst/gsttaglist.c:194 +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" + +#: gst/gsttaglist.c:198 +msgid "organization" +msgstr "" + +#: gst/gsttaglist.c:201 +msgid "copyright" +msgstr "" + +#: gst/gsttaglist.c:201 +msgid "copyright notice of the data" +msgstr "" + +#: gst/gsttaglist.c:203 +msgid "copyright uri" +msgstr "" + +#: gst/gsttaglist.c:204 +msgid "URI to the copyright notice of the data" +msgstr "" + +#: gst/gsttaglist.c:206 +msgid "encoded by" +msgstr "" + +#: gst/gsttaglist.c:206 +msgid "name of the encoding person or organization" +msgstr "" + +#: gst/gsttaglist.c:210 +msgid "contact" +msgstr "" + +#: gst/gsttaglist.c:210 +msgid "contact information" +msgstr "" + +#: gst/gsttaglist.c:212 +msgid "license" +msgstr "" + +#: gst/gsttaglist.c:212 +msgid "license of data" +msgstr "" + +#: gst/gsttaglist.c:214 +msgid "license uri" +msgstr "" + +#: gst/gsttaglist.c:215 +msgid "URI to the license of the data" +msgstr "" + +#: gst/gsttaglist.c:218 +msgid "performer" +msgstr "" + +#: gst/gsttaglist.c:219 +msgid "person(s) performing" +msgstr "" + +#: gst/gsttaglist.c:222 +msgid "composer" +msgstr "" + +#: gst/gsttaglist.c:223 +msgid "person(s) who composed the recording" +msgstr "" + +#: gst/gsttaglist.c:227 +msgid "conductor" +msgstr "" + +#: gst/gsttaglist.c:228 +msgid "conductor/performer refinement" +msgstr "" + +#: gst/gsttaglist.c:231 +msgid "duration" +msgstr "" + +#: gst/gsttaglist.c:231 +msgid "length in GStreamer time units (nanoseconds)" +msgstr "" + +#: gst/gsttaglist.c:234 +msgid "codec" +msgstr "" + +#: gst/gsttaglist.c:235 +msgid "codec the data is stored in" +msgstr "" + +#: gst/gsttaglist.c:238 +msgid "video codec" +msgstr "" + +#: gst/gsttaglist.c:238 +msgid "codec the video data is stored in" +msgstr "" + +#: gst/gsttaglist.c:241 +msgid "audio codec" +msgstr "" + +#: gst/gsttaglist.c:241 +msgid "codec the audio data is stored in" +msgstr "" + +#: gst/gsttaglist.c:244 +msgid "subtitle codec" +msgstr "" + +#: gst/gsttaglist.c:244 +msgid "codec the subtitle data is stored in" +msgstr "" + +#: gst/gsttaglist.c:246 +msgid "container format" +msgstr "" + +#: gst/gsttaglist.c:247 +msgid "container format the data is stored in" +msgstr "" + +#: gst/gsttaglist.c:249 +msgid "bitrate" +msgstr "" + +#: gst/gsttaglist.c:249 +msgid "exact or average bitrate in bits/s" +msgstr "" + +#: gst/gsttaglist.c:251 +msgid "nominal bitrate" +msgstr "" + +#: gst/gsttaglist.c:251 +msgid "nominal bitrate in bits/s" +msgstr "" + +#: gst/gsttaglist.c:253 +msgid "minimum bitrate" +msgstr "" + +#: gst/gsttaglist.c:253 +msgid "minimum bitrate in bits/s" +msgstr "" + +#: gst/gsttaglist.c:255 +msgid "maximum bitrate" +msgstr "" + +#: gst/gsttaglist.c:255 +msgid "maximum bitrate in bits/s" +msgstr "" + +#: gst/gsttaglist.c:258 +msgid "encoder" +msgstr "" + +#: gst/gsttaglist.c:258 +msgid "encoder used to encode this stream" +msgstr "" + +#: gst/gsttaglist.c:261 +msgid "encoder version" +msgstr "" + +#: gst/gsttaglist.c:262 +msgid "version of the encoder used to encode this stream" +msgstr "" + +#: gst/gsttaglist.c:264 +msgid "serial" +msgstr "" + +#: gst/gsttaglist.c:264 +msgid "serial number of track" +msgstr "" + +#: gst/gsttaglist.c:266 +msgid "replaygain track gain" +msgstr "" + +#: gst/gsttaglist.c:266 +msgid "track gain in db" +msgstr "" + +#: gst/gsttaglist.c:268 +msgid "replaygain track peak" +msgstr "" + +#: gst/gsttaglist.c:268 +msgid "peak of the track" +msgstr "" + +#: gst/gsttaglist.c:270 +msgid "replaygain album gain" +msgstr "" + +#: gst/gsttaglist.c:270 +msgid "album gain in db" +msgstr "" + +#: gst/gsttaglist.c:272 +msgid "replaygain album peak" +msgstr "" + +#: gst/gsttaglist.c:272 +msgid "peak of the album" +msgstr "" + +#: gst/gsttaglist.c:274 +msgid "replaygain reference level" +msgstr "" + +#: gst/gsttaglist.c:275 +msgid "reference level of track and album gain values" +msgstr "" + +#: gst/gsttaglist.c:277 +msgid "language code" +msgstr "" + +#: gst/gsttaglist.c:278 +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +#: gst/gsttaglist.c:281 +msgid "language name" +msgstr "" + +#: gst/gsttaglist.c:282 +msgid "freeform name of the language this stream is in" +msgstr "" + +#: gst/gsttaglist.c:284 +msgid "image" +msgstr "" + +#: gst/gsttaglist.c:284 +msgid "image related to this stream" +msgstr "" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +#: gst/gsttaglist.c:288 +msgid "preview image" +msgstr "" + +#: gst/gsttaglist.c:288 +msgid "preview image related to this stream" +msgstr "" + +#: gst/gsttaglist.c:290 +msgid "attachment" +msgstr "" + +#: gst/gsttaglist.c:290 +msgid "file attached to this stream" +msgstr "" + +#: gst/gsttaglist.c:293 +msgid "beats per minute" +msgstr "" + +#: gst/gsttaglist.c:294 +msgid "number of beats per minute in audio" +msgstr "" + +#: gst/gsttaglist.c:296 +msgid "keywords" +msgstr "" + +#: gst/gsttaglist.c:296 +msgid "comma separated keywords describing the content" +msgstr "" + +#: gst/gsttaglist.c:299 +msgid "geo location name" +msgstr "" + +#: gst/gsttaglist.c:300 +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +#: gst/gsttaglist.c:303 +msgid "geo location latitude" +msgstr "" + +#: gst/gsttaglist.c:304 +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +#: gst/gsttaglist.c:308 +msgid "geo location longitude" +msgstr "" + +#: gst/gsttaglist.c:309 +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +#: gst/gsttaglist.c:313 +msgid "geo location elevation" +msgstr "" + +#: gst/gsttaglist.c:314 +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +#: gst/gsttaglist.c:317 +msgid "geo location country" +msgstr "" + +#: gst/gsttaglist.c:318 +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#: gst/gsttaglist.c:321 +msgid "geo location city" +msgstr "" + +#: gst/gsttaglist.c:322 +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +#: gst/gsttaglist.c:325 +msgid "geo location sublocation" +msgstr "" + +#: gst/gsttaglist.c:326 +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +#: gst/gsttaglist.c:329 +msgid "geo location horizontal error" +msgstr "" + +#: gst/gsttaglist.c:330 +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#: gst/gsttaglist.c:333 +msgid "geo location movement speed" +msgstr "" + +#: gst/gsttaglist.c:334 +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#: gst/gsttaglist.c:337 +msgid "geo location movement direction" +msgstr "" + +#: gst/gsttaglist.c:338 +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#: gst/gsttaglist.c:343 +msgid "geo location capture direction" +msgstr "" + +#: gst/gsttaglist.c:344 +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +#: gst/gsttaglist.c:350 +msgid "show name" +msgstr "" + +#: gst/gsttaglist.c:351 +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +#: gst/gsttaglist.c:356 +msgid "show sortname" +msgstr "" + +#: gst/gsttaglist.c:357 +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#: gst/gsttaglist.c:360 +msgid "episode number" +msgstr "" + +#: gst/gsttaglist.c:361 +msgid "The episode number in the season the media is part of" +msgstr "" + +#: gst/gsttaglist.c:364 +msgid "season number" +msgstr "" + +#: gst/gsttaglist.c:365 +msgid "The season number of the show the media is part of" +msgstr "" + +#: gst/gsttaglist.c:368 +msgid "lyrics" +msgstr "" + +#: gst/gsttaglist.c:368 +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +#: gst/gsttaglist.c:371 +msgid "composer sortname" +msgstr "" + +#: gst/gsttaglist.c:372 +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" + +#: gst/gsttaglist.c:374 +msgid "grouping" +msgstr "" + +#: gst/gsttaglist.c:375 +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +#: gst/gsttaglist.c:379 +msgid "user rating" +msgstr "" + +#: gst/gsttaglist.c:380 +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +#: gst/gsttaglist.c:383 +msgid "device manufacturer" +msgstr "" + +#: gst/gsttaglist.c:384 +msgid "Manufacturer of the device used to create this media" +msgstr "" + +#: gst/gsttaglist.c:386 +msgid "device model" +msgstr "" + +#: gst/gsttaglist.c:387 +msgid "Model of the device used to create this media" +msgstr "" + +#: gst/gsttaglist.c:389 +msgid "application name" +msgstr "" + +#: gst/gsttaglist.c:390 +msgid "Application used to create the media" +msgstr "" + +#: gst/gsttaglist.c:392 +msgid "application data" +msgstr "" + +#: gst/gsttaglist.c:393 +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +#: gst/gsttaglist.c:395 +msgid "image orientation" +msgstr "" + +#: gst/gsttaglist.c:396 +msgid "How the image should be rotated or flipped before display" +msgstr "" + +#: gst/gsttaglist.c:399 +msgid "publisher" +msgstr "" + +#: gst/gsttaglist.c:400 +msgid "Name of the label or publisher" +msgstr "" + +#: gst/gsttaglist.c:403 +msgid "interpreted-by" +msgstr "" + +#: gst/gsttaglist.c:404 +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +#: gst/gsttaglist.c:408 +msgid "midi-base-note" +msgstr "" + +#: gst/gsttaglist.c:408 +msgid "Midi note number of the audio track." +msgstr "" + +#: gst/gsttaglist.c:411 +msgid "private-data" +msgstr "" + +#: gst/gsttaglist.c:411 +msgid "Private data" +msgstr "" + +#: gst/gsttaglist.c:451 +msgid ", " +msgstr "" + +#: gst/gsturi.c:648 +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#: gst/gsturi.c:823 +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#: gst/gstutils.c:2626 tools/gst-launch.c:325 +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#: gst/gstutils.c:2628 tools/gst-launch.c:327 tools/gst-launch.c:697 +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" + +#: gst/parse/grammar.y:216 +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#: gst/parse/grammar.y:221 +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#: gst/parse/grammar.y:413 +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:454 +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:507 +msgid "Delayed linking failed." +msgstr "" + +#: gst/parse/grammar.y:719 gst/parse/grammar.y:724 +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" + +#: gst/parse/grammar.y:729 +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#: gst/parse/grammar.y:733 +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "" + +#: gst/parse/grammar.y:739 +#, c-format +msgid "could not link %s to %s" +msgstr "" + +#: gst/parse/grammar.y:816 +#, c-format +msgid "no element \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:877 +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#: gst/parse/grammar.y:883 +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#: gst/parse/grammar.y:915 gst/parse/grammar.y:924 +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:952 +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:971 +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "" + +#: gst/parse/grammar.y:1061 +msgid "syntax error" +msgstr "" + +#: gst/parse/grammar.y:1084 +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#: gst/parse/grammar.y:1094 +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "" + +#: gst/parse/grammar.y:1125 +msgid "empty pipeline not allowed" +msgstr "" + +#: libs/gst/base/gstbasesink.c:2901 +msgid "A lot of buffers are being dropped." +msgstr "" + +#: libs/gst/base/gstbasesink.c:3393 +msgid "Internal data flow problem." +msgstr "" + +#: libs/gst/base/gstbasesink.c:4119 libs/gst/base/gstbasesrc.c:2693 +msgid "Internal data flow error." +msgstr "" + +#: libs/gst/base/gstbasesrc.c:2623 +msgid "Internal clock error." +msgstr "" + +#: libs/gst/base/gstbasesrc.c:2651 plugins/elements/gstdownloadbuffer.c:842 +#: plugins/elements/gstdownloadbuffer.c:1265 +msgid "Failed to map buffer." +msgstr "" + +#: plugins/elements/gstcapsfilter.c:128 +msgid "Filter caps" +msgstr "" + +#: plugins/elements/gstcapsfilter.c:129 +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +#: plugins/elements/gstcapsfilter.c:136 +msgid "Caps Change Mode" +msgstr "" + +#: plugins/elements/gstcapsfilter.c:137 +msgid "Filter caps change behaviour" +msgstr "" + +#: plugins/elements/gstdownloadbuffer.c:927 plugins/elements/gstqueue2.c:1707 +msgid "No Temp directory specified." +msgstr "" + +#: plugins/elements/gstdownloadbuffer.c:933 plugins/elements/gstqueue2.c:1713 +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "" + +#: plugins/elements/gstdownloadbuffer.c:941 plugins/elements/gstfilesrc.c:537 +#: plugins/elements/gstqueue2.c:1721 +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "" + +#: plugins/elements/gstdownloadbuffer.c:1274 plugins/elements/gstqueue2.c:2141 +msgid "Error while writing to download file." +msgstr "" + +#: plugins/elements/gstfilesink.c:424 +msgid "No file name specified for writing." +msgstr "" + +#: plugins/elements/gstfilesink.c:430 +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "" + +#: plugins/elements/gstfilesink.c:442 +#, c-format +msgid "Error closing file \"%s\"." +msgstr "" + +#: plugins/elements/gstfilesink.c:611 +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "" + +#: plugins/elements/gstfilesink.c:619 plugins/elements/gstfilesink.c:696 +#: plugins/elements/gstfilesink.c:731 +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "" + +#: plugins/elements/gstfilesrc.c:525 +msgid "No file name specified for reading." +msgstr "" + +#: plugins/elements/gstfilesrc.c:546 +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "" + +#: plugins/elements/gstfilesrc.c:552 +#, c-format +msgid "\"%s\" is a directory." +msgstr "" + +#: plugins/elements/gstfilesrc.c:558 +#, c-format +msgid "File \"%s\" is a socket." +msgstr "" + +#: plugins/elements/gstidentity.c:699 +msgid "Failed after iterations as requested." +msgstr "" + +#: plugins/elements/gsttypefindelement.c:253 +msgid "caps" +msgstr "" + +#: plugins/elements/gsttypefindelement.c:254 +msgid "detected capabilities in stream" +msgstr "" + +#: plugins/elements/gsttypefindelement.c:257 +msgid "minimum" +msgstr "" + +#: plugins/elements/gsttypefindelement.c:262 +msgid "force caps" +msgstr "" + +#: plugins/elements/gsttypefindelement.c:263 +msgid "force caps without doing a typefind" +msgstr "" + +#: plugins/elements/gsttypefindelement.c:990 +#: plugins/elements/gsttypefindelement.c:1012 +msgid "Stream doesn't contain enough data." +msgstr "" + +#: plugins/elements/gsttypefindelement.c:1132 +msgid "Stream contains no data." +msgstr "" + +#: tools/gst-inspect.c:217 +msgid "Implemented Interfaces:\n" +msgstr "" + +#: tools/gst-inspect.c:318 +msgid "readable" +msgstr "" + +#: tools/gst-inspect.c:322 +msgid "writable" +msgstr "" + +#: tools/gst-inspect.c:326 +msgid "deprecated" +msgstr "" + +#: tools/gst-inspect.c:330 +msgid "controllable" +msgstr "" + +#: tools/gst-inspect.c:334 +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +#: tools/gst-inspect.c:336 +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +#: tools/gst-inspect.c:338 +msgid "changeable only in NULL or READY state" +msgstr "" + +#: tools/gst-inspect.c:968 +msgid "Blacklisted files:" +msgstr "" + +#: tools/gst-inspect.c:980 tools/gst-inspect.c:1108 +msgid "Total count: " +msgstr "" + +#: tools/gst-inspect.c:981 +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#: tools/gst-inspect.c:1109 +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#: tools/gst-inspect.c:1112 +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#: tools/gst-inspect.c:1117 +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +#: tools/gst-inspect.c:1690 +msgid "Print all elements" +msgstr "" + +#: tools/gst-inspect.c:1692 +msgid "Print list of blacklisted files" +msgstr "" + +#: tools/gst-inspect.c:1694 +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +#: tools/gst-inspect.c:1699 +msgid "List the plugin contents" +msgstr "" + +#: tools/gst-inspect.c:1701 +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +#: tools/gst-inspect.c:1704 +msgid "Check if the specified element or plugin exists" +msgstr "" + +#: tools/gst-inspect.c:1707 +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +#: tools/gst-inspect.c:1711 +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#: tools/gst-inspect.c:1847 +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "" + +#: tools/gst-inspect.c:1852 +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +#: tools/gst-launch.c:252 +msgid "Index statistics" +msgstr "" + +#: tools/gst-launch.c:578 +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#: tools/gst-launch.c:582 +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#: tools/gst-launch.c:586 +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#: tools/gst-launch.c:590 +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#: tools/gst-launch.c:622 +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#: tools/gst-launch.c:631 +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#: tools/gst-launch.c:634 +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#: tools/gst-launch.c:637 +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +#: tools/gst-launch.c:640 +msgid "FOUND TAG\n" +msgstr "" + +#: tools/gst-launch.c:655 +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#: tools/gst-launch.c:658 +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +#: tools/gst-launch.c:661 +msgid "FOUND TOC\n" +msgstr "" + +#: tools/gst-launch.c:678 +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#: tools/gst-launch.c:695 +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "" + +#: tools/gst-launch.c:730 +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +#: tools/gst-launch.c:734 +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +#: tools/gst-launch.c:746 +msgid "buffering..." +msgstr "" + +#: tools/gst-launch.c:757 +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +#: tools/gst-launch.c:765 +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +#: tools/gst-launch.c:774 +msgid "Redistribute latency...\n" +msgstr "" + +#: tools/gst-launch.c:785 +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +#: tools/gst-launch.c:801 +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#: tools/gst-launch.c:830 +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#: tools/gst-launch.c:843 +#, c-format +msgid "Missing element: %s\n" +msgstr "" + +#: tools/gst-launch.c:857 +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "" + +#: tools/gst-launch.c:991 +msgid "Output tags (also known as metadata)" +msgstr "" + +#: tools/gst-launch.c:993 +msgid "Output TOC (chapters and editions)" +msgstr "" + +#: tools/gst-launch.c:995 +msgid "Output status information and property notifications" +msgstr "" + +#: tools/gst-launch.c:997 +msgid "Do not print any progress information" +msgstr "" + +#: tools/gst-launch.c:999 +msgid "Output messages" +msgstr "" + +#: tools/gst-launch.c:1001 +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +#: tools/gst-launch.c:1003 +msgid "PROPERTY-NAME" +msgstr "" + +#: tools/gst-launch.c:1005 +msgid "Do not install a fault handler" +msgstr "" + +#: tools/gst-launch.c:1007 +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +#: tools/gst-launch.c:1010 +msgid "Gather and print index statistics" +msgstr "" + +#: tools/gst-launch.c:1077 +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "" + +#: tools/gst-launch.c:1081 +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "" + +#: tools/gst-launch.c:1085 +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +#: tools/gst-launch.c:1101 +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "" + +#: tools/gst-launch.c:1132 tools/gst-launch.c:1233 +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +#: tools/gst-launch.c:1137 +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +#: tools/gst-launch.c:1142 +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +#: tools/gst-launch.c:1146 +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +#: tools/gst-launch.c:1149 tools/gst-launch.c:1163 +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +#: tools/gst-launch.c:1156 +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +#: tools/gst-launch.c:1169 +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +#: tools/gst-launch.c:1176 +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +#: tools/gst-launch.c:1195 +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +#: tools/gst-launch.c:1199 +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +#: tools/gst-launch.c:1202 +msgid "Waiting for EOS...\n" +msgstr "" + +#: tools/gst-launch.c:1209 +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +#: tools/gst-launch.c:1213 +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +#: tools/gst-launch.c:1218 +msgid "An error happened while waiting for EOS\n" +msgstr "" + +#: tools/gst-launch.c:1229 +msgid "Execution ended after %" +msgstr "" + +#: tools/gst-launch.c:1245 +msgid "Setting pipeline to READY ...\n" +msgstr "" + +#: tools/gst-launch.c:1257 +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +#: tools/gst-launch.c:1261 +msgid "Freeing pipeline ...\n" +msgstr "" diff --git a/po/hr.gmo b/po/hr.gmo new file mode 100644 index 0000000..7a03005 Binary files /dev/null and b/po/hr.gmo differ diff --git a/po/hr.po b/po/hr.po new file mode 100644 index 0000000..3ccd3b3 --- /dev/null +++ b/po/hr.po @@ -0,0 +1,1426 @@ +# Translation of gstreamer to Croatian. +# This file is put in the public domain. +# +# +# GStreamer Application Development Manual +# https://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html +# +# Tomislav Krznar , 2012. +# Božidar Putanec , 2016, 2017, 2018. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2018-04-17 15:13-0800\n" +"Last-Translator: Božidar Putanec \n" +"Language-Team: Croatian \n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Bugs: Report translation errors to the Language-Team address.\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" +"X-Generator: Lokalize 2.0\n" + +msgid "Print the GStreamer version" +msgstr "ispiše GStreamer inačicu" + +msgid "Make all warnings fatal" +msgstr "učini sva upozorenja fatalnim" + +msgid "Print available debug categories and exit" +msgstr "ispis dostupnih kategorija debugiranja" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"zadana RAZINA debugiranja od 1\n" +" (samo greške) do 9 (sve) ili 0 " +"(ništa)" + +msgid "LEVEL" +msgstr "RAZINA" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"zarezom odvojeni POPIS parova\n" +" category_name:level\n" +" za postavljanje specifičnih razina\n" +" za pojedinačne kategorije.\n" +" Primjer: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "POPIS" + +msgid "Disable colored debugging output" +msgstr "neobojeni ispis debugiranja" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"mijenja način bojenja debug-dnevnika\n" +" mogući načini su:\n" +" off, on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "onemogući debugiranje" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" +"opširna dijagnostika tijekom\n" +" učitavanja plugina" + +msgid "Colon-separated paths containing plugins" +msgstr "" +"dvotočkom odvojene STAZE (paths)\n" +" koje sadrže plugine" + +msgid "PATHS" +msgstr "STAZE" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"zarezima odvojeni popis dodatnih PLUGINA\n" +" za učitati pored onih navedenih u\n" +" varijabli okoline GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"onemogući hvatanje segmentacijskih\n" +" grešaka tijekom učitavanja plugina" + +msgid "Disable updating the registry" +msgstr "onemogući ažuriranje registra" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"onemogući stvaranje pomoćnog procesa\n" +" tijekom čitanja registra" + +msgid "GStreamer Options" +msgstr "GStreamer opcije" + +msgid "Show GStreamer Options" +msgstr "pokaže opcije za GStreamer" + +msgid "Unknown option" +msgstr "Nepoznata opcija" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer je primio opću grešku u osnovnoj biblioteci." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "Stvaraoci GStreamer-a bili su lijeni da dodijele kȏd toj grešci." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Interna GStreamer greška: kȏd nije implementirani." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer greška: nije uspjela promjena stanja i neki element nije uspio " +"poslati pravilnu poruku o grešci s razlogom za neuspjeh." + +# 1. https://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html +# 2. pad (u elektronskoj glazbi) > A category of synthsizer patches which produce a soft, pleasing sound. +# 3. Pads are element's input and output, where you can connect other elements +msgid "Internal GStreamer error: pad problem." +msgstr "Interna GStreamer greška: pad-problem." + +# Rač.: nezavisni skup naredbi koji se samostalno izvršavaju u programu +msgid "Internal GStreamer error: thread problem." +msgstr "Interna GStreamer greška: dretva-problem." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer greška: problem dogovaranja (za povezivanje elemenata)." + +msgid "Internal GStreamer error: event problem." +msgstr "Interna GStreamer greška: problem s događajem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Interna GStreamer greška: problem u traženju." + +msgid "Internal GStreamer error: caps problem." +msgstr "Interna GStreamer greška: Caps-problem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Interna GStreamer greška: tag-problem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Vašoj GStreamer instalaciji nedostaje plugin." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer greška: problem sa satom (vrijeme, sinkronizacija)." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Aplikacija pokušava koristiti GStreamer funkciju koja je bila onemogućena." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer je primio opću grešku u pomoćnoj biblioteci." + +msgid "Could not initialize supporting library." +msgstr "Pomoćnu biblioteku nije moguće inicijalizirati." + +msgid "Could not close supporting library." +msgstr "Pomoćnu biblioteku nije moguće zatvoriti." + +msgid "Could not configure supporting library." +msgstr "Pomoćnu biblioteku nije moguće konfigurirati." + +msgid "Encoding error." +msgstr "Greška u kodiranju." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer je naišao na opću grešku resursa." + +msgid "Resource not found." +msgstr "Resurs nije pronađen." + +msgid "Resource busy or not available." +msgstr "Resurs je zauzeti ili je nedostupni." + +msgid "Could not open resource for reading." +msgstr "Resurs nije moguće otvoriti za čitanje." + +msgid "Could not open resource for writing." +msgstr "Resurs nije moguće otvoriti za pisanje." + +msgid "Could not open resource for reading and writing." +msgstr "Resurs nije moguće otvoriti za čitanje i pisanje." + +msgid "Could not close resource." +msgstr "Nije moguće zatvoriti resurs." + +msgid "Could not read from resource." +msgstr "Nije moguće čitati iz resursa." + +msgid "Could not write to resource." +msgstr "Nije moguće pisati u resurs." + +msgid "Could not perform seek on resource." +msgstr "Nije moguće pretraživati u resursu." + +msgid "Could not synchronize on resource." +msgstr "Nije moguće sinkronizirati se s resursom." + +msgid "Could not get/set settings from/on resource." +msgstr "Nije moguće dobiti ili promijeniti postavke resursa." + +msgid "No space left on the resource." +msgstr "Nema više prostora na resursu." + +msgid "Not authorized to access resource." +msgstr "Nije dopušteno pristupiti resursu." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer je naišao na opću grešku strujanja (stream error)." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Element ne može rukovati s ovakvim strujanjem. Molimo, prijavite kao grešku." + +msgid "Could not determine type of stream." +msgstr "Nije moguće odrediti vrstu ovog strujanja." + +msgid "The stream is of a different type than handled by this element." +msgstr "Strujanje je vrste kojom ovaj element ne može rukovati." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Nema kodeka koji može rukovati s ovom vrstom strujanja." + +msgid "Could not decode stream." +msgstr "Nije moguće dekodirati strujanje." + +msgid "Could not encode stream." +msgstr "Nije moguće kodirati strujanje." + +msgid "Could not demultiplex stream." +msgstr "Nije moguće demultipleksirati strujanje." + +msgid "Could not multiplex stream." +msgstr "Nije moguće multipleksirati strujanje." + +msgid "The stream is in the wrong format." +msgstr "Strujanje je u krivom formatu." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Strujanje je šifrirano a dešifriranje nije podržano." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Strujanje je šifrirano i ne može se dešifrirati jer nije dobiven prikladni " +"ključ." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nema poruke o grešci za domenu %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nema standardne poruke o grešci za domenu %s i kȏd %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Odabrani sat se ne može koristiti u cjevovodu." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Greška pri zapisivanju u predmemoriju registra u %s: %s" + +msgid "title" +msgstr "naslov" + +msgid "commonly used title" +msgstr "uobičajeni naslov" + +msgid "title sortname" +msgstr "naslov za sortiranje" + +msgid "commonly used title for sorting purposes" +msgstr "uobičajeni naslov za sortiranje" + +msgid "artist" +msgstr "izvođač" + +msgid "person(s) responsible for the recording" +msgstr "osobe odgovorne za snimanje" + +msgid "artist sortname" +msgstr "umjetnik za sortiranje" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "osobe odgovorne za snimanje za sortiranje" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album koji sadrži ove podatke" + +msgid "album sortname" +msgstr "album za sortiranje" + +msgid "album containing this data for sorting purposes" +msgstr "album koji sadrži ove podatke za sortiranje" + +msgid "album artist" +msgstr "izvođač albuma" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Izvođač cijelog albuma prikazan kako treba" + +msgid "album artist sortname" +msgstr "izvođač albuma za sortiranje" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Izvođač cijelog albuma za sortiranje" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "datum stvaranja podataka (u obliku GDate strukture)" + +msgid "datetime" +msgstr "datum-vrijeme" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "datum i vrijeme stvaranja podataka (u obliku GstDateTime strukture)" + +msgid "genre" +msgstr "žanr" + +msgid "genre this data belongs to" +msgstr "žanr kojem pripadaju podaci" + +msgid "comment" +msgstr "komentar" + +msgid "free text commenting the data" +msgstr "slobodan tekst koji opisuje podatke" + +msgid "extended comment" +msgstr "prošireni komentar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"slobodan tekst koji opisuje podatke u obliku ključ=vrijednost ili " +"ključ[hr]=komentar" + +msgid "track number" +msgstr "redni broj zapisa" + +msgid "track number inside a collection" +msgstr "redni broj zapisa u kolekciji" + +msgid "track count" +msgstr "ukupni broj zapisa" + +msgid "count of tracks inside collection this track belongs to" +msgstr "ukupni broj zapisa u kolekciji kojoj pripada ova pjesma" + +msgid "disc number" +msgstr "redni broj diska" + +msgid "disc number inside a collection" +msgstr "redni broj diska u kolekciji" + +msgid "disc count" +msgstr "ukupni broj diskova" + +msgid "count of discs inside collection this disc belongs to" +msgstr "ukupni broj diskova u kolekciji kojoj pripada ovaj disk" + +msgid "location" +msgstr "mjesto" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Podrijetlo medija kao URI (mjesto gdje se nalazi originalna datoteka ili " +"originalni izvor strujanja)" + +msgid "homepage" +msgstr "početna stranica" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Početna stranica ovog medija (npr. početna stranica izvođača ili filma)" + +msgid "description" +msgstr "opis" + +msgid "short text describing the content of the data" +msgstr "sažetak koji opisuje sadržaj podataka" + +msgid "version" +msgstr "inačica" + +msgid "version of this data" +msgstr "inačica ovih podataka" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - pogledajte http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organizacija" + +msgid "copyright" +msgstr "autorska prava" + +msgid "copyright notice of the data" +msgstr "napomena o autorskim pravima podataka" + +msgid "copyright uri" +msgstr "copyright URI" + +msgid "URI to the copyright notice of the data" +msgstr "URI adresa s napomenom o autorskim pravima na podatke" + +msgid "encoded by" +msgstr "kodirao" + +msgid "name of the encoding person or organization" +msgstr "ime osobe ili organizacije koja je kodirala" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "informacije o kontaktu" + +msgid "license" +msgstr "licencija" + +msgid "license of data" +msgstr "licencija za podatke" + +msgid "license uri" +msgstr "URI licencija" + +msgid "URI to the license of the data" +msgstr "URI adresa za licenciju podataka" + +msgid "performer" +msgstr "izvođač" + +msgid "person(s) performing" +msgstr "osoba (ili osobe) koja izvodi" + +msgid "composer" +msgstr "skladatelj" + +msgid "person(s) who composed the recording" +msgstr "osoba (ili osobe) koja je skladala snimku" + +msgid "conductor" +msgstr "dirigent" + +msgid "conductor/performer refinement" +msgstr "dirigent/izvođač detaljnije" + +msgid "duration" +msgstr "trajanje" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "dužina u GStreamer vremenskim jedinicama (nanosekunde)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "kodek u kojem su spremljeni podaci" + +msgid "video codec" +msgstr "video kodek" + +msgid "codec the video data is stored in" +msgstr "kodek u kojem su spremljeni video podaci" + +msgid "audio codec" +msgstr "audio kodek" + +msgid "codec the audio data is stored in" +msgstr "kodek u kojem su spremljeni audio podaci" + +msgid "subtitle codec" +msgstr "kodek titlova" + +msgid "codec the subtitle data is stored in" +msgstr "kodek u kojem su spremljeni podaci o titlovima" + +msgid "container format" +msgstr "format kontejnera" + +msgid "container format the data is stored in" +msgstr "format kontejnera u kojem su spremljeni podaci" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "točna ili prosječna brzina u bitovima po sekundi" + +msgid "nominal bitrate" +msgstr "nominalna brzina" + +msgid "nominal bitrate in bits/s" +msgstr "nominalna brzina u bitovima po sekundi" + +msgid "minimum bitrate" +msgstr "najmanja brzina" + +msgid "minimum bitrate in bits/s" +msgstr "najmanja brzina u bitovima po sekundi" + +msgid "maximum bitrate" +msgstr "najveća brzina" + +msgid "maximum bitrate in bits/s" +msgstr "najveća brzina u bitovima po sekundi" + +msgid "encoder" +msgstr "koder" + +msgid "encoder used to encode this stream" +msgstr "koder upotrebljeni za kodiranje ovog strujanja" + +msgid "encoder version" +msgstr "inačica kodera" + +msgid "version of the encoder used to encode this stream" +msgstr "inačica kodera korištenoga za kodiranje ovog strujanja" + +msgid "serial" +msgstr "serijski broj" + +msgid "serial number of track" +msgstr "serijski broj zapisa" + +# https://en.wikipedia.org/wiki/ReplayGain +# http://www.audiohq.de/index.php?showtopic=23#Referenzlautstaerke +msgid "replaygain track gain" +msgstr "prilagodba glasnoće pjesme" + +msgid "track gain in db" +msgstr "razina glasnoće zapisa u decibelima" + +msgid "replaygain track peak" +msgstr "prilagodba vršne glasnoće pjesme" + +msgid "peak of the track" +msgstr "vršna razina glasnoće pjesme" + +msgid "replaygain album gain" +msgstr "prilagodba glasnoće albuma" + +msgid "album gain in db" +msgstr "razina glasnoće albuma u decibelima" + +msgid "replaygain album peak" +msgstr "prilagodba vršne glasnoće albuma" + +msgid "peak of the album" +msgstr "vršna razina glasnoće albuma" + +msgid "replaygain reference level" +msgstr "prilagodba referentne glasnoće" + +msgid "reference level of track and album gain values" +msgstr "referentna razina za prilagodbu glasnoće zapisa i albuma" + +msgid "language code" +msgstr "jezični kȏd" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "jezični kȏd za ovo strujanje, u skladu s ISO-639-1 ili ISO-639-2" + +msgid "language name" +msgstr "ime jezika" + +msgid "freeform name of the language this stream is in" +msgstr "uobičajeno ime jezika u kojem je ovo strujanje" + +msgid "image" +msgstr "slika" + +msgid "image related to this stream" +msgstr "slika povezana s ovim strujanjem" + +# thumbnail +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "pregledna slika" + +msgid "preview image related to this stream" +msgstr "pregledna slika povezana s ovom strujom" + +msgid "attachment" +msgstr "privitak" + +msgid "file attached to this stream" +msgstr "datoteka pripojena ovom strujanju" + +msgid "beats per minute" +msgstr "otkucaja u minuti (tempo)" + +msgid "number of beats per minute in audio" +msgstr "broj otkucaja u minuti (tempo) zvučnog zapisa" + +msgid "keywords" +msgstr "ključne riječi" + +msgid "comma separated keywords describing the content" +msgstr "zarezima odvojene ključne riječi koje opisuju sadržaj" + +# https://en.wikipedia.org/wiki/Geolocation +msgid "geo location name" +msgstr "geografsko ime mjesta" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "čitljiv opis mjesta gdje je medij snimljeni ili proizvedeni" + +msgid "geo location latitude" +msgstr "geografska širina" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"geografska širina mjesta gdje je medij snimljeni ili proizvedeni, u " +"stupnjevima prema WGS84 (nula na ekvatoru, negativne vrijednosti za južne " +"širine)" + +msgid "geo location longitude" +msgstr "geografska dužina" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"geografska dužina mjesta gdje je medij snimljeni ili proizvedeni, u " +"stupnjevima prema WGS84 (nula na nultom meridijanu Greenwich/UK, negativne " +"vrijednosti za zapadne dužine)" + +msgid "geo location elevation" +msgstr "geografska visina" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"nadmorska visina mjesta gdje je medij snimljeni ili proizvedeni, u metrima " +"prema WGS84 (nula je prosječna razina mora)" + +msgid "geo location country" +msgstr "geografski položaj države" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "država (englesko ime) gdje je medij snimljeni ili proizvedeni" + +msgid "geo location city" +msgstr "geografski položaj grada" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "grad (englesko ime) gdje je medij snimljeni ili proizvedeni" + +msgid "geo location sublocation" +msgstr "geografski položaj djela grada" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"mjesto u gradu gdje je medij snimljeni ili proizvedeni (npr. gradska četvrt)" + +msgid "geo location horizontal error" +msgstr "greška vodoravne geografske lokacije" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "očekivana greška u mjerenju vodoravnog položaja (u metrima)" + +msgid "geo location movement speed" +msgstr "geografska brzina kretanja" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "brzina kretanja uređaja za snimanje pri snimanju, u m/s" + +msgid "geo location movement direction" +msgstr "geografski smjer kretanja" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"označava smjer kretanja uređaja koji snima medij. Prikazan je u stupnjevima " +"u prikazu s decimalnim zarezom, 0 označava zemljopisni sjever i povećava se " +"u smjeru kazaljke na satu" + +msgid "geo location capture direction" +msgstr "geografski smjer snimanja" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"označava usmjerenje uređaja koji snima medij. Prikazan je u stupnjevima u " +"prikazu s decimalnim zarezom, 0 označava zemljopisni sjever i povećava se u " +"smjeru kazaljke na satu" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "ime emisije" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Ime serije ili tv/podcast emisije iz koje je medij" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "ime emisije za sortiranje" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Ime serije ili tv/podcast emisije iz koje je medij za sortiranje" + +msgid "episode number" +msgstr "redni broj epizode" + +msgid "The episode number in the season the media is part of" +msgstr "Redni broj epizode u sezoni iz koje je medij" + +msgid "season number" +msgstr "redni broj sezone" + +msgid "The season number of the show the media is part of" +msgstr "Redni broj sezone emisije iz koje je medij" + +msgid "lyrics" +msgstr "tekstovi" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Tekstovi medija, koristi se obično za pjesme" + +msgid "composer sortname" +msgstr "skladatelj za sortiranje" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "osoba (ili osobe) koja je skladala snimku za sortiranje" + +msgid "grouping" +msgstr "grupiranje" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupira povezane medije koji se protežu kroz više zapisa, kao npr. različiti " +"stavci koncerta. To je viša razina od zapisa, ali niža od albuma" + +msgid "user rating" +msgstr "ocjena korisnika" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Ocjena koju je dodijelio korisnik. Što je veća, korisniku se više sviđa medij" + +msgid "device manufacturer" +msgstr "proizvođač uređaja" + +msgid "Manufacturer of the device used to create this media" +msgstr "Proizvođač uređaja kojim je napravljen medij" + +msgid "device model" +msgstr "model uređaja" + +msgid "Model of the device used to create this media" +msgstr "Model uređaja korišteni za izradu medija" + +msgid "application name" +msgstr "ime aplikacije" + +msgid "Application used to create the media" +msgstr "Aplikacija korištena za izradu medija" + +msgid "application data" +msgstr "podaci o aplikaciji" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Proizvoljni podaci o aplikaciji koji su serijalizirani u medij" + +msgid "image orientation" +msgstr "orijentacija slike" + +msgid "How the image should be rotated or flipped before display" +msgstr "Kako se slika treba rotirati ili preokrenuti prije prikaza" + +msgid "publisher" +msgstr "izdavač" + +msgid "Name of the label or publisher" +msgstr "Ime studija ili izdavača" + +msgid "interpreted-by" +msgstr "obradio" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Informacije o ljudima koji su radili na remiksu i sličnim obradama" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Broj note MIDI na audio zapisu." + +msgid "private-data" +msgstr "privatni-podaci" + +msgid "Private data" +msgstr "Privatni podaci" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Za protokol %s nije pronađen URI rukovatelj" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI shema „%s“ nije podržana" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "GREŠKA: iz elementa %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Dodatne informacije za debugiranje:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "veza nema source [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "veza nema sink [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nema svojstva „%s“ u elementu „%s“" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nije moguće postaviti svojstvo „%s“ u elementu „%s“ sa „%s“" + +msgid "Delayed linking failed." +msgstr "Odgođeno povezivanje nije uspjelo." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nije moguće povezati %s na %s, %s ne može rukovati s Caps %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"nije moguće povezati %s na %s, nijedan element ne može rukovati s Caps %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nije moguće povezati %s na %s s Caps %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nije moguće povezati %s sa %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nema elementa „%s“" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "neočekivana referencija „%s“ - ignorira se" + +# pad (u elektronskoj glazbi) > A category of synthsizer patches which produce a soft, pleasing sound. +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "neočekivan pad-reference „%s“ - ignorira se" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nije moguće iščitati Caps „%s“" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "nema sink-elementa za adresu URI „%s“" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "nema source-elementa za adresu URI „%s“" + +msgid "syntax error" +msgstr "greška u sintaksi" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "specificirani je prazni spremnik „%s“; to nije dopušteno" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nema spremnika „%s“, elementi se otpakiravaju" + +msgid "empty pipeline not allowed" +msgstr "prazan cjevovod nije dopušten" + +msgid "A lot of buffers are being dropped." +msgstr "Puno međuspremnika je odbačeno." + +msgid "Internal data flow problem." +msgstr "Problem unutrašnjeg protoka podataka." + +msgid "Internal data flow error." +msgstr "Interna greška protoka podataka." + +msgid "Internal clock error." +msgstr "Interni problem sa satom." + +msgid "Failed to map buffer." +msgstr "Nije uspjelo mapirati međuspremnik." + +msgid "Filter caps" +msgstr "Caps filtar" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Ograniči dopuštene mogućnosti (NULL znači ANY). Postavljanje ovog svojstva " +"prosljeđuje referenciju na navedeni GstCaps objektu." + +msgid "Caps Change Mode" +msgstr "Način Caps promjena" + +msgid "Filter caps change behaviour" +msgstr "Filtar-Caps mijenja ponašanje" + +msgid "No Temp directory specified." +msgstr "Nijedan privremeni direktorij nije specificiran." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Privremenu datoteku „%s“ nije moguće kreirati." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Datoteku „%s“ nije moguće otvoriti za čitanje." + +msgid "Error while writing to download file." +msgstr "Greška pri pisanju u preuzetu datoteku." + +msgid "No file name specified for writing." +msgstr "Nije specificirana datoteka za pisanje." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Datoteku „%s“ nije moguće otvoriti za pisanje." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Greška zatvaranja datoteke „%s“." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Greška pri traganju u datoteci „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Greška pri pisanju u datoteku „%s“." + +msgid "No file name specified for reading." +msgstr "Nije specificirana datoteka za čitanje." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Ne mogu se dobiti podaci o „%s“." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s“ je direktorij." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Datoteka „%s“ je utičnica (pristupna točka, socket)." + +msgid "Failed after iterations as requested." +msgstr "Neuspjeh nakon iteracija po zahtjevu." + +msgid "caps" +msgstr "Caps" + +msgid "detected capabilities in stream" +msgstr "otkrivene su Caps strujanja" + +msgid "minimum" +msgstr "najmanje" + +msgid "force caps" +msgstr "prisili Caps" + +msgid "force caps without doing a typefind" +msgstr "prisili Caps bez upotrebe „typefind“" + +msgid "Stream doesn't contain enough data." +msgstr "Strujanje ne sadrži dovoljno podataka." + +msgid "Stream contains no data." +msgstr "Strujanje ne sadrži podatke." + +msgid "Implemented Interfaces:\n" +msgstr "Implementirana sučelja:\n" + +msgid "readable" +msgstr "čitljivo" + +msgid "writable" +msgstr "zapisivo" + +msgid "deprecated" +msgstr "zastarjelo" + +msgid "controllable" +msgstr "upravljivo" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "promjenjivo u stanja NULL, READY, PAUSED ili PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "promjenjivo samo u stanja NULL, READY ili PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "promjenjivo samo u stanja NULL ili READY" + +msgid "Blacklisted files:" +msgstr "Datoteke na crnoj listi:" + +msgid "Total count: " +msgstr "Ukupni broj: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d datoteka na crnoj listi" +msgstr[1] "%d datoteke na crnoj listi" +msgstr[2] "%d datoteka na crnoj listi" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugina" +msgstr[2] "%d plugina" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d stavka na crnoj listi" +msgstr[1] "%d stavke na crnoj listi" +msgstr[2] "%d stavki na crnoj listi" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d značajka" +msgstr[1] "%d značajke" +msgstr[2] "%d značajki" + +msgid "Print all elements" +msgstr "ispiše sve elemente" + +msgid "Print list of blacklisted files" +msgstr "ispiše popis datoteka na crnoj listi" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"ispiše popis značajki navedenoga plugina\n" +" ili svih plugina; korisno u vezi s\n" +" vanjskim automatskim mehanizmima\n" +" za instalaciju plugina" + +msgid "List the plugin contents" +msgstr "ispiše sadržaj plugina" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"izlista kosim crtama („/“) odvojeni popis\n" +" vrsta elemenata (poznati kao " +"„klass“)\n" +" (neuređeni)" + +msgid "Check if the specified element or plugin exists" +msgstr "" +"provjeri da li postoji specificirani\n" +" element ili plugin" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"pri provjeri da li postoji element ili\n" +" plugin, također provjeri da " +"njihova\n" +" inačica nije niža od specificirane" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"ispiše podržane URI sheme s elementima\n" +" koji ih implementiraju" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nije moguće učitati plugin datoteku: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nema takvog elementa ili plugina „%s“\n" + +msgid "Index statistics" +msgstr "Statistike indeksa" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Primljena je poruka #%u od elementa „%s“ (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Primljena je poruka #%u od pad „%s:%s“ (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Primljena je poruka #%u od objekta „%s“ (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Primljena je poruka #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Dobiven je EOS od elementa „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "PRONAĐEN TAG : pronađen elementom „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "PRONAĐEN TAG : pronađen s pad „%s:%s“.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "PRONAĐEN TAG : pronađen objektom „%s“.\n" + +msgid "FOUND TAG\n" +msgstr "PRONAĐEN TAG\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "PRONAĐEN TOC : pronađen elementom „%s“.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "PRONAĐEN TOC : pronađen objektom „%s“.\n" + +msgid "FOUND TOC\n" +msgstr "PRONAĐEN TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACIJE:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "UPOZORENJE: od elementa %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Pripremljeno, čeka se završetak punjenja međuspremnika...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Pripremljeno, čeka se završetak progresa...\n" + +msgid "buffering..." +msgstr "punjenje međuspremnika..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Gotovo je spremanje u međuspremnik, postavlja se cjevovod u PLAYING ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Punjenje međuspremnika, postavljam cjevovod u PAUSED ...\n" + +msgid "Redistribute latency...\n" +msgstr "Preraspodjela latencije...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Postavljam stanje u %s kao što traži %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Prekid: Zaustavlja se cjevovod ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Progres: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Nedostaje element %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Dobiven je kontekst od elementa „%s“: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "izlazni tagovi (znani i kao „metapodaci“)" + +msgid "Output TOC (chapters and editions)" +msgstr "ispiše TOC (sadržaj: poglavlja i izdanja)" + +msgid "Output status information and property notifications" +msgstr "" +"ispiše informacije o statusu\n" +" i obavijesti o svojstvima" + +msgid "Do not print any progress information" +msgstr "ne ispisuje informacije o progresu" + +msgid "Output messages" +msgstr "izlazne poruke" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"ne ispiše status za svojstvo IME-SVOJSTVA\n" +" iako je aktivna opcija\n" +" za opširno ispisivanje" + +msgid "PROPERTY-NAME" +msgstr "IME-SVOJSTVA" + +msgid "Do not install a fault handler" +msgstr "ne instalira rutinu za obradu greški" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" +"prisili EOS na sources prije\n" +" zatvaranja cjevovoda" + +msgid "Gather and print index statistics" +msgstr "Prikupiti i ispisati statistike indeksa" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "GREŠKA: Cjevovod se ne može konstruirati: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "GREŠKA: Cjevovod se ne može konstruirati.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "UPOZORENJE: cjevovod je sklon greškama: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "GREŠKA: „cjevovodni“ element nije pronađen.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Cjevovod se postavlja u stanje PAUSED ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "GREŠKA: Cjevovod ne želi pauzirati.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Cjevovod je živ i ne treba PREROLL (pripravu)...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Cjevovod se priprema (PREROLLING)....\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "GREŠKA: cjevovod se ne želi pripremiti (preroll).\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Cjevovod je pripremljen (PREROLLED) ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Cjevovod je postavljen u stanje PLAYING ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "GREŠKA: cjevovod ne želi reproducirati (play).\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS pri zatvaranju omogućen -- EOS se prinuđuje na cjevovod\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS pri zatvaranju omogućen -- čekanje na EOS nakon greške\n" + +msgid "Waiting for EOS...\n" +msgstr "Čekanje na EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS primljen - zaustavljanje cjevovoda...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "U prekidu dok se čeka na EOS - zaustavlja se cjevovod...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Dogodila se greška pri čekanju na EOS\n" + +msgid "Execution ended after %" +msgstr "Izvršavanje je završilo nakon %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Cjevovod se postavlja u stanje READY ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Cjevovod se postavlja u stanje NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Cjevovod se prazni...\n" + +#~ msgid "bin" +#~ msgstr "spremnik" + +#~ msgid "Internal data stream error." +#~ msgstr "Interna greška protoka (stream) podataka." + +#~ msgid "link without source element" +#~ msgstr "veza bez izvornog elementa" + +#~ msgid "link without sink element" +#~ msgstr "veza bez prijamnog elementa" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "nema elementa na koji će se povezati URI „%s”" + +#~ msgid "maximum" +#~ msgstr "najviše" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Uporaba: gst-xmllaunch [ element." +#~ "svojstvo=vrijednost ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "GREŠKA: analiza xml datoteke „%s” nije uspjela.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "GREŠKA: ne postoji vršni element cjevovoda u datoteci „%s”.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "UPOZORENJE: trenutno je podržan samo jedan vršni element.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "GREŠKA: ne mogu analizirati argument naredbenog retka %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "UPOZORENJE: element „%s” nije pronađen.\n" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Ne ispisuj informacije navedene VRSTE o izlaznom stanju" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "VRSTA1,VRSTA2,..." + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Spremi xml prikaz cjevovoda u DATOTEKU i izađi" + +#~ msgid "FILE" +#~ msgstr "DATOTEKA" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Nemoj instalirati rukovatelj signala za SIGUSR1 i SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Ispiši alloc praćenje (ako je omogućeno pri kompajliranju)" diff --git a/po/hu.gmo b/po/hu.gmo new file mode 100644 index 0000000..1093a1f Binary files /dev/null and b/po/hu.gmo differ diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..2d916bc --- /dev/null +++ b/po/hu.po @@ -0,0 +1,1333 @@ +# Hungarian translation for gstreamer +# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2012, 2014, 2015, 2016, 2017 Canonical Ltd, and Rosetta Contributors +# This file is distributed under the same license as the gstreamer package. +# +# Gabor Kelemen , 2006, 2007, 2008, 2009, 2010, 2012, 2016. +# Balázs Úr , 2014, 2015, 2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 20:17+0200\n" +"Last-Translator: Balázs Úr \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-Bugs: Report translation errors to the Language-Team address.\n" +"X-Generator: Lokalize 1.2\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Print the GStreamer version" +msgstr "A GStreamer verziójának kiírása" + +msgid "Make all warnings fatal" +msgstr "Minden figyelmeztetés végzetes legyen" + +msgid "Print available debug categories and exit" +msgstr "Az elérhető hibakeresési kategóriák kiírása és kilépés" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Alapértelmezett hibakeresési szint 1 (csak hibák) és 9 (bármi) között, vagy " +"0 esetén nincs kimenet" + +msgid "LEVEL" +msgstr "SZINT" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"A kategórianév:szint párok vesszőkkel elválasztott listája adott szintek " +"beállításához az egyes kategóriákhoz. Például: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Színes hibakeresési kimenet letiltása" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Megváltoztatja a hibakeresési napló színezési módját. Lehetséges módok: off, " +"on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "Hibakeresés letiltása" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Részletes bővítménybetöltési diagnosztika engedélyezése" + +msgid "Colon-separated paths containing plugins" +msgstr "Bővítményeket tartalmazó útvonalak vesszőkkel elválasztott listája" + +msgid "PATHS" +msgstr "ÚTVONALAK" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"A GST_PLUGIN_PATH környezeti változóban megadott listán kívül előre " +"betöltendő bővítmények vesszővel elválasztott listája." + +msgid "PLUGINS" +msgstr "BŐVÍTMÉNYEK" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Szegmentálási hibák elfogásának letiltása a bővítménybetöltés során" + +msgid "Disable updating the registry" +msgstr "A nyilvántartás frissítésének letiltása" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Segédfolyamat indításának letiltása a nyilvántartás elemzése közben" + +msgid "GStreamer Options" +msgstr "GStreamer beállításai" + +msgid "Show GStreamer Options" +msgstr "A GStreamer beállításainak megjelenítése" + +msgid "Unknown option" +msgstr "Ismeretlen beállítás" + +msgid "GStreamer encountered a general core library error." +msgstr "A GStreamer általános magkönyvtárhibát tapasztalt." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"A GStreamer fejlesztők túl lusták voltak hibakódot rendelni ehhez a hibához." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Belső GStreamer hiba: a kód nincs megvalósítva." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer hiba: az állapotváltás meghiúsult és néhány elem nem volt képes " +"megfelelő hibaüzenetet küldeni a hiba okáról." + +msgid "Internal GStreamer error: pad problem." +msgstr "Belső GStreamer hiba: kitöltési probléma." + +msgid "Internal GStreamer error: thread problem." +msgstr "Belső GStreamer hiba: szálprobléma." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer hiba: megállapodási probléma." + +msgid "Internal GStreamer error: event problem." +msgstr "Belső GStreamer hiba: eseményprobléma." + +msgid "Internal GStreamer error: seek problem." +msgstr "Belső GStreamer hiba: pozicionálási probléma." + +msgid "Internal GStreamer error: caps problem." +msgstr "Belső GStreamer hiba: képességprobléma." + +msgid "Internal GStreamer error: tag problem." +msgstr "Belső GStreamer hiba: címkeprobléma." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "A GStreamer telepítésből hiányzik egy bővítmény." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer hiba: óraprobléma." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "Az alkalmazás letiltott GStreamer funkciókat próbál meg használni." + +msgid "GStreamer encountered a general supporting library error." +msgstr "A GStreamer általános támogató programkönyvtárhibát észlelt." + +msgid "Could not initialize supporting library." +msgstr "Nem sikerült inicializálni a támogató programkönyvtárat." + +msgid "Could not close supporting library." +msgstr "Nem zárható be a támogató programkönyvtár." + +msgid "Could not configure supporting library." +msgstr "Nem állítható be a támogató programkönyvtár." + +msgid "Encoding error." +msgstr "Kódolási hiba." + +msgid "GStreamer encountered a general resource error." +msgstr "A GStreamer általános erőforráshibát észlelt." + +msgid "Resource not found." +msgstr "Az erőforrás nem található." + +msgid "Resource busy or not available." +msgstr "Az erőforrás foglalt vagy nem érhető el." + +msgid "Could not open resource for reading." +msgstr "Az erőforrás nem nyitható meg olvasásra." + +msgid "Could not open resource for writing." +msgstr "Az erőforrás nem nyitható meg írásra." + +msgid "Could not open resource for reading and writing." +msgstr "Az erőforrás nem nyitható meg olvasásra és írásra." + +msgid "Could not close resource." +msgstr "Az erőforrás nem zárható le." + +msgid "Could not read from resource." +msgstr "Nem lehet olvasni az erőforrásból." + +msgid "Could not write to resource." +msgstr "Nem lehet írni az erőforrásba." + +msgid "Could not perform seek on resource." +msgstr "Nem végezhető pozicionálás az erőforráson." + +msgid "Could not synchronize on resource." +msgstr "Nem lehet szinkronizálni az erőforráson." + +msgid "Could not get/set settings from/on resource." +msgstr "Nem lehet lekérni/beállítani az erőforrás beállításait." + +msgid "No space left on the resource." +msgstr "Nincs több hely az erőforráson." + +msgid "Not authorized to access resource." +msgstr "Nincs jogosultsága az erőforrás eléréséhez." + +msgid "GStreamer encountered a general stream error." +msgstr "A GStreamer általános adatfolyamhibát észlelt." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Az elem nem valósítja meg az adatfolyam kezelését. Küldjön be egy " +"hibajelentést." + +msgid "Could not determine type of stream." +msgstr "Nem állapítható meg az adatfolyam típusa." + +msgid "The stream is of a different type than handled by this element." +msgstr "Az adatfolyam típusa eltér az elem által kezelttől." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Nincs jelen az adatfolyam típusát kezelni képes kodek." + +msgid "Could not decode stream." +msgstr "Nem fejthető vissza az adatfolyam." + +msgid "Could not encode stream." +msgstr "Az adatfolyam nem kódolható." + +msgid "Could not demultiplex stream." +msgstr "Nem választható szét az adatfolyam." + +msgid "Could not multiplex stream." +msgstr "Nem egyesíthető az adatfolyam." + +msgid "The stream is in the wrong format." +msgstr "Az adatfolyam formátuma rossz." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Az adatfolyam titkosított és a visszafejtés nem támogatott." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Az adatfolyam titkosított és nem fejthető vissza, mivel nem került megadásra " +"megfelelő kulcs." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nincs hibaüzenet a következő tartományhoz: %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" +"Nincs szabványos hibaüzenet a következő tartományhoz: %s és kódhoz: %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "A kijelölt óra nem használható adatcsatornában." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Hiba a regisztrációs gyorsítótár írásakor ebbe: %s: %s" + +msgid "title" +msgstr "cím" + +msgid "commonly used title" +msgstr "általánosan használt cím" + +msgid "title sortname" +msgstr "cím rendezési neve" + +msgid "commonly used title for sorting purposes" +msgstr "általánosan, rendezési céllal használt cím" + +msgid "artist" +msgstr "előadó" + +msgid "person(s) responsible for the recording" +msgstr "a felvételért felelős személyek" + +msgid "artist sortname" +msgstr "előadó rendezési neve" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "a felvételért felelős személyek, rendezési céllal" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "az adatokat tartalmazó album" + +msgid "album sortname" +msgstr "album rendezési neve" + +msgid "album containing this data for sorting purposes" +msgstr "az adatokat tartalmazó album, rendezési céllal" + +msgid "album artist" +msgstr "albumelőadó" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "A teljes album előadója, megjelenítendő formában" + +msgid "album artist sortname" +msgstr "albumelőadó rendezési neve" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "A teljes album előadója, rendezéshez használható formában" + +msgid "date" +msgstr "dátum" + +msgid "date the data was created (as a GDate structure)" +msgstr "az adatok létrehozási dátuma (GDate struktúraként)" + +msgid "datetime" +msgstr "dátumidő" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "az adatok létrehozási dátuma és ideje (GstDateTime struktúraként)" + +msgid "genre" +msgstr "műfaj" + +msgid "genre this data belongs to" +msgstr "a stílus, amelyhez az adatok tartoznak" + +msgid "comment" +msgstr "megjegyzés" + +msgid "free text commenting the data" +msgstr "az adatokhoz tartozó szabad szöveges megjegyzés" + +msgid "extended comment" +msgstr "kiterjesztett megjegyzés" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"az adatokhoz fűzött szabad szöveges megjegyzés kulcs=érték vagy " +"kulcs[hu]=megjegyzés formában" + +msgid "track number" +msgstr "dalsorszám" + +msgid "track number inside a collection" +msgstr "dalsorszám egy gyűjteményen belül" + +msgid "track count" +msgstr "dalszám" + +msgid "count of tracks inside collection this track belongs to" +msgstr "dalok mennyisége azon gyűjteményen belül, amelyhez ez a dal tartozik" + +msgid "disc number" +msgstr "lemezszám" + +msgid "disc number inside a collection" +msgstr "lemezszám egy gyűjteményen belül" + +msgid "disc count" +msgstr "lemezek mennyisége" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" +"lemezek mennyisége azon gyűjteményen belül, amelyhez ez a lemez tartozik" + +msgid "location" +msgstr "hely" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"A média eredete URI címként (az a hely, ahol az eredeti fájl vagy műsor " +"megtalálható)" + +msgid "homepage" +msgstr "honlap" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "A média honlapja (előadó vagy film honlapja)" + +msgid "description" +msgstr "leírás" + +msgid "short text describing the content of the data" +msgstr "az adatokat leíró rövid szöveg" + +msgid "version" +msgstr "verzió" + +msgid "version of this data" +msgstr "az adatok verziószáma" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code – lásd: http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "szervezet" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "az adatok copyright megjegyzése" + +msgid "copyright uri" +msgstr "védjegy uri" + +msgid "URI to the copyright notice of the data" +msgstr "Az adatok védjegymegjegyzésének URI címe" + +msgid "encoded by" +msgstr "kódolta" + +msgid "name of the encoding person or organization" +msgstr "a kódoló személy vagy szervezet" + +msgid "contact" +msgstr "névjegy" + +msgid "contact information" +msgstr "kapcsolatinformációk" + +msgid "license" +msgstr "licenc" + +msgid "license of data" +msgstr "az adatok licence" + +msgid "license uri" +msgstr "licenc uri" + +msgid "URI to the license of the data" +msgstr "Az adatok licencének URI címe" + +msgid "performer" +msgstr "előadó" + +msgid "person(s) performing" +msgstr "az előadó(k)" + +msgid "composer" +msgstr "zeneszerző" + +msgid "person(s) who composed the recording" +msgstr "a felvétel szerzői" + +msgid "conductor" +msgstr "vezényel" + +msgid "conductor/performer refinement" +msgstr "vezényel/előadó finomítása" + +msgid "duration" +msgstr "időtartam" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "hossz GStreamer időegységekben (nanomásodperc)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "az adatok tárolására használt kodek" + +msgid "video codec" +msgstr "videokodek" + +msgid "codec the video data is stored in" +msgstr "a videoadatok tárolására használt kodek" + +msgid "audio codec" +msgstr "hangkodek" + +msgid "codec the audio data is stored in" +msgstr "a hangadatok tárolására használt kodek" + +msgid "subtitle codec" +msgstr "feliratkodek" + +msgid "codec the subtitle data is stored in" +msgstr "a feliratadatok tárolására használt kodek" + +msgid "container format" +msgstr "tárolóformátum" + +msgid "container format the data is stored in" +msgstr "az adatok tárolására használt tárolóformátum" + +msgid "bitrate" +msgstr "bitsebesség" + +msgid "exact or average bitrate in bits/s" +msgstr "pontos vagy átlagos bitsebesség bit/mp-ben" + +msgid "nominal bitrate" +msgstr "névleges bitsebesség" + +msgid "nominal bitrate in bits/s" +msgstr "névleges bitsebesség bit/mp-ben" + +msgid "minimum bitrate" +msgstr "minimális bitsebesség" + +msgid "minimum bitrate in bits/s" +msgstr "minimális bitsebesség bit/mp-ben" + +msgid "maximum bitrate" +msgstr "maximális bitsebesség" + +msgid "maximum bitrate in bits/s" +msgstr "maximális bitsebesség bit/mp-ben" + +msgid "encoder" +msgstr "kódoló" + +msgid "encoder used to encode this stream" +msgstr "az adatfolyam kódolására használt kódoló" + +msgid "encoder version" +msgstr "kódoló verziószáma" + +msgid "version of the encoder used to encode this stream" +msgstr "az adatfolyam kódolására használt kódoló verziószáma" + +msgid "serial" +msgstr "soros" + +msgid "serial number of track" +msgstr "a dal sorszáma" + +msgid "replaygain track gain" +msgstr "visszajátszási hangerő: dal hangosítása" + +msgid "track gain in db" +msgstr "dal hangosítása dB-ben" + +msgid "replaygain track peak" +msgstr "visszajátszási hangerő: dal hangerejének csúcsértéke" + +msgid "peak of the track" +msgstr "a dal hangerejének csúcsértéke" + +msgid "replaygain album gain" +msgstr "visszajátszási hangerő: album hangosítása" + +msgid "album gain in db" +msgstr "album hangosítása dB-ben" + +msgid "replaygain album peak" +msgstr "visszajátszási hangerő: album hangerejének csúcsértéke" + +msgid "peak of the album" +msgstr "az album hangerejének csúcsértéke" + +msgid "replaygain reference level" +msgstr "visszajátszási hangerő referenciaszintje" + +msgid "reference level of track and album gain values" +msgstr "szám és album hangosításának referenciaszintje" + +msgid "language code" +msgstr "nyelvi kód" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" +"az adatfolyam ISO-639-1 vagy ISO-639-2 szabványnak megfelelő nyelvi kódja" + +msgid "language name" +msgstr "nyelvi kód" + +msgid "freeform name of the language this stream is in" +msgstr "az adatfolyam nyelvének szabad formátumú neve" + +msgid "image" +msgstr "kép" + +msgid "image related to this stream" +msgstr "az adatfolyamhoz kapcsolódó kép" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "előnézeti kép" + +msgid "preview image related to this stream" +msgstr "az adatfolyamhoz kapcsolódó előnézeti kép" + +msgid "attachment" +msgstr "melléklet" + +msgid "file attached to this stream" +msgstr "az adatfolyamhoz mellékelt fájl" + +msgid "beats per minute" +msgstr "percenkénti ütések száma" + +msgid "number of beats per minute in audio" +msgstr "percenkénti ütések száma a hangban" + +msgid "keywords" +msgstr "kulcsszavak" + +msgid "comma separated keywords describing the content" +msgstr "a tartalmat leíró, vesszővel elválasztott kulcsszavak" + +msgid "geo location name" +msgstr "földrajzi hely neve" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"emberek által olvasható leíró jellegű hely, ahol a média felvételre vagy " +"előállításra került" + +msgid "geo location latitude" +msgstr "földrajzi hely szélessége" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"azon hely földrajzi szélessége, ahol a média felvételre vagy előállításra " +"került fokokban, a WGS84-nek megfelelően (nulla az egyenlítőnél, negatív " +"értékek déli szélességeken)" + +msgid "geo location longitude" +msgstr "földrajzi hely hosszúsága" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"azon hely földrajzi hosszúsága, ahol a média felvételre vagy előállításra " +"került fokokban, a WGS84-nek megfelelően (nulla a kezdő délkörnél " +"Greenwichben, negatív értékek nyugati hosszúságokon)" + +msgid "geo location elevation" +msgstr "földrajzi hely magassága" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"azon hely földrajzi magassága, ahol a média felvételre vagy előállításra " +"került méterben, a WGS84-nek megfelelően (nulla az átlagos tengerszinten)" + +msgid "geo location country" +msgstr "földrajzi hely országa" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "ország (angol név), ahol a média felvételre vagy előállításra került" + +msgid "geo location city" +msgstr "földrajzi hely városa" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "város (angol név), ahol a média felvételre vagy előállításra került" + +msgid "geo location sublocation" +msgstr "földrajzi hely részhelye" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"a városon belüli hely, ahol a média előállításra vagy létrehozásra került " +"(például környék)" + +msgid "geo location horizontal error" +msgstr "földrajzi hely vízszintes hibája" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "a vízszintes pozicionálási értékek várt hibája (méterben)" + +msgid "geo location movement speed" +msgstr "földrajzi hely mozgási sebessége" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "a felvevőeszköz mozgási sebessége a felvétel készítésekor, m/s-ban" + +msgid "geo location movement direction" +msgstr "földrajzi hely mozgási iránya" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"a média felvételét végző eszköz mozgási irányát jelzi. lebegőpontosan " +"ábrázolt fokok képviselik, a 0 a földrajzi északot jelzi és az óra járásának " +"irányába nő." + +msgid "geo location capture direction" +msgstr "földrajzi hely felvételi iránya" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"a média felvételét végző eszköz irányát jelzi. lebegőpontosan ábrázolt fokok " +"képviselik, a 0 a földrajzi északot jelzi és az óra járásának irányába nő." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "műsornév" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "A tv/podcast/sorozat műsor neve, amelyből a média származik" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "műsor rendezési neve" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"A tv/podcast/sorozat műsor neve, amelyből a média származik, rendezési célra" + +msgid "episode number" +msgstr "epizódszám" + +msgid "The episode number in the season the media is part of" +msgstr "Azon évadon belüli epizód száma, amelynek ez a média része" + +msgid "season number" +msgstr "évadszám" + +msgid "The season number of the show the media is part of" +msgstr "Azon műsor évadszáma, amelynek ez a média része" + +msgid "lyrics" +msgstr "dalszöveg" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "A média dalszövege" + +msgid "composer sortname" +msgstr "szerző rendezési neve" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "a felvételt szerző személyek, rendezési céllal" + +msgid "grouping" +msgstr "csoportosítás" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Több számot átfogó média csoportosítása, például egy koncert különböző " +"darabjai. Magasabb szintű a számnál, de alacsonyabb az albumnál" + +msgid "user rating" +msgstr "felhasználói értékelés" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Felhasználó által társított értékelés. Minél magasabb, annál jobban kedveli " +"a felhasználó a médiát" + +msgid "device manufacturer" +msgstr "eszköz gyártója" + +msgid "Manufacturer of the device used to create this media" +msgstr "A média előállításához használt eszköz gyártója" + +msgid "device model" +msgstr "eszközmodell" + +msgid "Model of the device used to create this media" +msgstr "A média létrehozására használt eszközmodell" + +msgid "application name" +msgstr "alkalmazás neve" + +msgid "Application used to create the media" +msgstr "A média létrehozására használt alkalmazás" + +msgid "application data" +msgstr "alkalmazásadatok" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Tetszőleges, a médiába mentendő alkalmazásadatok" + +msgid "image orientation" +msgstr "kép tájolása" + +msgid "How the image should be rotated or flipped before display" +msgstr "A kép hogyan forgatandó vagy tükrözendő megjelenítés előtt" + +msgid "publisher" +msgstr "kiadó" + +msgid "Name of the label or publisher" +msgstr "A címke vagy kiadó neve" + +msgid "interpreted-by" +msgstr "feldolgozta" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Információ a remix mögött lévő személyekről és hasonló feldolgozások" + +msgid "midi-base-note" +msgstr "midi-alapú-hangjegy" + +msgid "Midi note number of the audio track." +msgstr "A hangsáv midi hangjegy száma." + +msgid "private-data" +msgstr "privát-adatok" + +msgid "Private data" +msgstr "Privát adatok" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Nem található URI-kezelő a(z) %s protokollhoz" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "A(z) „%s” URI-séma nem támogatott" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "HIBA: a következő elemtől: %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"További hibakeresési információk:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "a hivatkozásnak nincs forrása [nyelő=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "a hivatkozásnak nincs nyelője [forrás=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nincs „%s” tulajdonság a(z) „%s” elemben" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nem állítható be a(z) „%2$s” elem „%1$s” tulajdonsága „%3$s” értékre" + +msgid "Delayed linking failed." +msgstr "A késleltetett linkelés meghiúsult." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" +"%s nem linkelhető a következőre: %s, a(z) %s nem tudja kezelni a következő " +"képességeket: %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"%s nem linkelhető a következőre: %s, egyik elem sem tudja kezelni a " +"következő képességeket: %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "%s nem linkelhető a következőre: %s ezekkel a képességekkel: %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "%s nem linkelhető a következőre: %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nincs „%s” elem" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "nem várt „%s” hivatkozás - mellőzés" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "nem várt „%s” kitöltési hivatkozás - mellőzés" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "a(z) „%s” képesség nem elemezhető" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "nincs nyelőelem a következő URI címhez: „%s”" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "nincs forráselem a következő URI címhez: „%s”" + +msgid "syntax error" +msgstr "szintaktikai hiba" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "a megadott üres „%s” tároló nem engedélyezett" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nincs „%s” tároló, elemek kicsomagolása" + +msgid "empty pipeline not allowed" +msgstr "üres adatcsatorna nem engedélyezett" + +msgid "A lot of buffers are being dropped." +msgstr "Rengetek puffer kerül eldobásra." + +msgid "Internal data flow problem." +msgstr "Belső adatfolyam-probléma." + +msgid "Internal data flow error." +msgstr "Belső adatfolyam-hiba." + +msgid "Internal clock error." +msgstr "Belső órahiba." + +msgid "Failed to map buffer." +msgstr "Nem sikerült a puffer leképezése." + +msgid "Filter caps" +msgstr "Képességek szűrése" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Az engedélyezhető képességek korlátozása (a NULL, ANY-t jelent). Ezen " +"tulajdonság beállítása a biztosított GstCaps objektumra hivatkozik." + +msgid "Caps Change Mode" +msgstr "Képességek változtatása mód" + +msgid "Filter caps change behaviour" +msgstr "Képességek változtatása viselkedés szűrése" + +msgid "No Temp directory specified." +msgstr "Nincs megadva ideiglenes könyvtár." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nem hozható létre a következő ideiglenes fájl: „%s”." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nem nyitható meg a(z) „%s” fájl olvasásra." + +msgid "Error while writing to download file." +msgstr "Hiba a letöltési fájl írása közben." + +msgid "No file name specified for writing." +msgstr "Nincs fájlnév megadva az íráshoz." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nem lehet írásra megnyitni a(z) „%s” fájlt." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Hiba a(z) „%s” fájl bezárása közben." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Hiba a következő fájlban való tekerés közben: „%s”." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Hiba a(z) „%s” fájl írása közben." + +msgid "No file name specified for reading." +msgstr "Nincs megadva fájlnév az olvasáshoz." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nem kérhetők le információk a következőkről: „%s”." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s” egy könyvtár." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "A(z) „%s” fájl egy foglalat." + +msgid "Failed after iterations as requested." +msgstr "Ismétlések után kérésére meghiúsult." + +msgid "caps" +msgstr "képességek" + +msgid "detected capabilities in stream" +msgstr "az adatfolyamban észlelt képességek" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "nagybetűk kényszerítése" + +msgid "force caps without doing a typefind" +msgstr "nagybetűk kényszerítése betűkeresés nélkül" + +msgid "Stream doesn't contain enough data." +msgstr "Az adatfolyam nem tartalmaz elég adatot." + +msgid "Stream contains no data." +msgstr "Az adatfolyam nem tartalmaz adatokat." + +msgid "Implemented Interfaces:\n" +msgstr "Megvalósított felületek:\n" + +msgid "readable" +msgstr "olvasható" + +msgid "writable" +msgstr "írható" + +msgid "deprecated" +msgstr "elavult" + +msgid "controllable" +msgstr "vezérelhető" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "módosítható a NULL, KÉSZ, SZÜNETEL vagy LEJÁTSZÁS állapotban" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "csak a NULL, KÉSZ vagy SZÜNETEL állapotban módosítható" + +msgid "changeable only in NULL or READY state" +msgstr "csak a NULL vagy KÉSZ állapotban módosítható" + +msgid "Blacklisted files:" +msgstr "Feketelistás fájlok:" + +msgid "Total count: " +msgstr "Teljes szám: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d feketelistás fájl" +msgstr[1] "%d feketelistás fájl" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d bővítmény" +msgstr[1] "%d bővítmény" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d feketelista-bejegyzés" +msgstr[1] "%d feketelista-bejegyzés" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d szolgáltatás" +msgstr[1] "%d szolgáltatás" + +msgid "Print all elements" +msgstr "Az összes elem kiírása" + +msgid "Print list of blacklisted files" +msgstr "Feketelistás fájlok listájának kiírása" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"A megadott bővítmény által biztosított szolgáltatások gépileg feldolgozható " +"listájának kiírása.\n" +"Külső bővítménytelepítési módszerekkel együtt hasznos." + +msgid "List the plugin contents" +msgstr "A bővítmény tartalmának felsorolása" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"A felsorolandó elemek típusainak perjellel („/”) elválasztott listája (klass " +"néven is ismert). (nem sorrendezett)" + +msgid "Check if the specified element or plugin exists" +msgstr "Ellenőrizze, hogy a megadott elem vagy bővítmény létezik-e" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Elem vagy bővítmény létezésének ellenőrzésekor azt is ellenőrizze, hogy a " +"verziója legalább a megadott-e" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Támogatott URI sémák kiírása, az azokat megvalósító elemmel" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nem tölthető be a bővítményfájl: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nincs ilyen elem vagy bővítmény: „%s”\n" + +msgid "Index statistics" +msgstr "Indexstatisztika" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "%u számú üzenet érkezett a következő elemtől: „%s” (%s)." + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "%u számú üzenet érkezett a(z) „%s:%s” (%s) kitöltőtől: " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "%u számú üzenet érkezett a(z) „%s” (%s) objektumtól: " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "%u számú üzenet (%s) érkezett:" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "EOS érkezett a következő elemtől: „%s”.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "CÍMKE MEGTALÁLVA: a(z) „%s” elem által.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "CÍMKE MEGTALÁLVA: a(z) „%s:%s” kitöltő által.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "CÍMKE MEGTALÁLVA: a(z) „%s” objektum által.\n" + +msgid "FOUND TAG\n" +msgstr "CÍMKE MEGTALÁLVA\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TARTALOMJEGYZÉK MEGTALÁLVA: a(z) „%s” elem által.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TARTALOMJEGYZÉK MEGTALÁLVA: a(z) „%s” objektum által.\n" + +msgid "FOUND TOC\n" +msgstr "TARTALOMJEGYZÉK MEGTALÁLVA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMÁCIÓ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "FIGYELMEZTETÉS: a következő elemtől: %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Előzetesen betöltve, várakozás a pufferelés befejeződésére…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Előzetesen betöltve, várakozás a folyamat befejeződésére…\n" + +msgid "buffering..." +msgstr "pufferelés…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "A pufferelés kész, adatcsatorna beállítása LEJÁTSZÁSRA…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Pufferelés, az adatcsatorna beállítása SZÜNETELTETETT állapotúra…\n" + +msgid "Redistribute latency...\n" +msgstr "Késleltetés újraelosztása…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Állapot beállítása erre: %s, %s kérésének megfelelően…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Megszakítás: Adatcsatorna leállítása…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Folyamat: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Hiányzó elem: „%s”\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Környezet lekérése a(z) „%s” elemtől: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Kimeneti címkék (metaadatok)" + +msgid "Output TOC (chapters and editions)" +msgstr "TARTALOMJEGYZÉK (fejezetek és változatok) kiírása" + +msgid "Output status information and property notifications" +msgstr "Kimeneti állapotinformációk és tulajdonság-értesítések" + +msgid "Do not print any progress information" +msgstr "Ne írjon ki előrehaladás-információkat" + +msgid "Output messages" +msgstr "Kimeneti üzenetek" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Ne írja ki az állapotinformációkat a megadott tulajdonságnál, ha a részletes " +"kimenet engedélyezve van (többször is használható)" + +msgid "PROPERTY-NAME" +msgstr "TULAJDONSÁGNÉV" + +msgid "Do not install a fault handler" +msgstr "Ne telepítsen hibakezelőt" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "EOS kényszerítése a forrásokra az adatcsatorna leállítása előtt" + +msgid "Gather and print index statistics" +msgstr "Indexstatisztikák gyűjtése és kiírása" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "HIBA: az adatcsatorna nem építhető fel: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "HIBA: az adatcsatorna nem építhető fel.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "FIGYELMEZTETÉS: hibás adatcsatorna: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "HIBA: az „adatcsatorna” elem nem található.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Adatcsatorna beállítása SZÜNETELTETETT állapotúra…\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "HIBA: az adatcsatorna nem akar megállni.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Az adatcsatorna él és nem szükséges ELINDÍTANI…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Az adatcsatorna INDÍTÁSA…\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "HIBA: az adatcsatorna nem akar elindulni.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Az adatcsatorna ELINDÍTVA…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Adatcsatorna beállítása LEJÁTSZÁSRA…\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "HIBA: az adatcsatorna nem akar lejátszani.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Leállításkor EOS engedélyezve – EOS kényszerítése az adatcsatornára\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Leállításkor EOS engedélyezve – várakozás EOS-ra hiba után\n" + +msgid "Waiting for EOS...\n" +msgstr "Várakozás EOS-ra…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS érkezett – adatcsatorna leállítása…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Megszakítás az EOS-ra várakozás közben – adatcsatorna leállítása…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Hiba történt az EOS-ra várakozáskor\n" + +msgid "Execution ended after %" +msgstr "A végrehajtás befejeződött %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Az adatcsatorna beállítása KÉSZ állapotra…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Az adatcsatorna beállítása NULL értékre…\n" + +msgid "Freeing pipeline ...\n" +msgstr "Adatcsatorna felszabadítása…\n" diff --git a/po/id.gmo b/po/id.gmo new file mode 100644 index 0000000..288e89c Binary files /dev/null and b/po/id.gmo differ diff --git a/po/id.po b/po/id.po new file mode 100644 index 0000000..ddcc761 --- /dev/null +++ b/po/id.po @@ -0,0 +1,1349 @@ +# Indonesian translations for gstreamer package. +# This file is put in the public domain. +# Andika Triwidada , 2013. +# Andhika Padmawan , 2010-2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.10.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2016-11-14 20:59+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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Print the GStreamer version" +msgstr "Cetak versi GStreamer" + +msgid "Make all warnings fatal" +msgstr "Buat semua peringatan fatal" + +msgid "Print available debug categories and exit" +msgstr "Cetak kategori awakutu yang tersedia lalu keluar" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Level awakutu standar dari 1 (hanya galat) ke 9 (apapun) atau 0 untuk tak " +"ada keluaran" + +msgid "LEVEL" +msgstr "LEVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Senarai dipisahkan koma dari category_name:level dipasangkan untuk mengatur " +"level spesifik untuk kategori individual. Misalnya: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "SENARAI" + +msgid "Disable colored debugging output" +msgstr "Nonaktifkan keluaran awakutu berwarna" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Mengubah mode pewarnaan dari log awakutu. Mode yang mungkin: off (mati), on " +"(nyala), disable (dinonaktifkan), auto (otomatis), unix" + +msgid "Disable debugging" +msgstr "Nonaktifkan awakutu" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Mengaktifkan plugin verbose ketika memuat diagnosis" + +msgid "Colon-separated paths containing plugins" +msgstr "Alamat dipisahkan tanda titik dua berisi plugin" + +msgid "PATHS" +msgstr "ALAMAT" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Senarai plugin dipisahkan oleh koma untuk pramuat sebagai tambahan dari " +"senarai yang disimpan di lingkungan variabel GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGIN" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Nonaktifkan penjebak galat segmentasi selama memuat plugin" + +msgid "Disable updating the registry" +msgstr "Nonaktifkan pemutakhiran registry" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Nonaktifkan memaksa penolong proses ketika memindai registry" + +msgid "GStreamer Options" +msgstr "Opsi GStreamer" + +msgid "Show GStreamer Options" +msgstr "Tampilkan Opsi GStreamer" + +msgid "Unknown option" +msgstr "Opsi tak diketahui" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer menghadapi galat umum pustaka inti." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Pengembang GStreamer terlalu malas untuk menulis kode galat untuk galat ini." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Galat GStreamer internal: kode belum diimplementasikan." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Galat GStreamer: gagal mengubah kondisi dan beberapa elemen gagal untuk " +"mengirim pesan galat yang benar dengan alasan bagi kegagalan." + +msgid "Internal GStreamer error: pad problem." +msgstr "Galat GStreamer internal: masalah landasan." + +msgid "Internal GStreamer error: thread problem." +msgstr "Galat GStreamer internal: masalah benang." + +msgid "GStreamer error: negotiation problem." +msgstr "Galat GStreamer: masalah negosiasi." + +msgid "Internal GStreamer error: event problem." +msgstr "Galat GStreamer internal: masalah event." + +msgid "Internal GStreamer error: seek problem." +msgstr "Galat GStreamer internal: masalah pencarian." + +msgid "Internal GStreamer error: caps problem." +msgstr "Galat GStreamer internal: masalah huruf." + +msgid "Internal GStreamer error: tag problem." +msgstr "Galat GStreamer internal: masalah tag." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Instalasi GStreamer anda kehilangan plug-in." + +msgid "GStreamer error: clock problem." +msgstr "Galat GStreamer: masalah jam." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Aplikasi ini mencoba untuk menggunakan fungsionalitas GStreamer yang telah " +"dinonaktifkan." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer menghadapi galat umum pustaka pendukung." + +msgid "Could not initialize supporting library." +msgstr "Tak dapat menginisialisasi pustaka pendukung." + +msgid "Could not close supporting library." +msgstr "Tak dapat menutup pustaka pendukung." + +msgid "Could not configure supporting library." +msgstr "Tak dapat mengatur pustaka pendukung." + +msgid "Encoding error." +msgstr "Galat penyandian." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer menghadapi galat umum sumber daya." + +msgid "Resource not found." +msgstr "Sumber daya tak ditemukan." + +msgid "Resource busy or not available." +msgstr "Sumber daya sibuk atau tak tersedia." + +msgid "Could not open resource for reading." +msgstr "Tak dapat membuka sumber daya untuk dibaca." + +msgid "Could not open resource for writing." +msgstr "Tak dapat membuka sumber daya untuk ditulis." + +msgid "Could not open resource for reading and writing." +msgstr "Tak dapat membuka sumber daya untuk dibaca dan ditulis." + +msgid "Could not close resource." +msgstr "Tak dapat menutup sumber daya." + +msgid "Could not read from resource." +msgstr "Tak dapat membaca dari sumber daya." + +msgid "Could not write to resource." +msgstr "Tak dapat menulis ke sumber daya." + +msgid "Could not perform seek on resource." +msgstr "Tak dapat melakukan pencarian di sumber daya." + +msgid "Could not synchronize on resource." +msgstr "Tak dapat sinkronisasi di sumber daya." + +msgid "Could not get/set settings from/on resource." +msgstr "Tak bisa mendapatkan/mengatur pengaturan dari/di sumber daya." + +msgid "No space left on the resource." +msgstr "Tak ada ruang tersisa di sumber daya." + +msgid "Not authorized to access resource." +msgstr "Tak diizinkan untuk mengakses sumber daya." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer menghadapai galat arus umum." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elemen tidak mengimplementasikan penanganan untuk arus ini. Silakan laporkan " +"kutu." + +msgid "Could not determine type of stream." +msgstr "Tak dapat menentukan tipe arus." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Arus berasal dari tipe yang berbeda dari yang ditangani oleh elemen ini." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Tidak ada codec saat ini yang dapat menangani tipe arus." + +msgid "Could not decode stream." +msgstr "Tak dapat mengawasandi arus." + +msgid "Could not encode stream." +msgstr "Tak dapat menyandi arus." + +msgid "Could not demultiplex stream." +msgstr "Tak dapat menyatukan arus." + +msgid "Could not multiplex stream." +msgstr "Tak dapat memperbanyak arus." + +msgid "The stream is in the wrong format." +msgstr "Arus berada dalam format yang salah." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Arus terenkripsi dan dekripsi tidak didukung." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Arus terenkripsi dan tak dapat didekripsi karena tidak ada kunci yang " +"disediakan." + +#, c-format +msgid "No error message for domain %s." +msgstr "Tak ada pesan galat untuk domain %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Tak ada pesan galat standar untuk domain %s dan kode %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Jam terpilih tak dapat digunakan dalam baris pipa." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Galat menulis tembolok registry ke %s: %s" + +msgid "title" +msgstr "judul" + +msgid "commonly used title" +msgstr "judul yang umum digunakan" + +msgid "title sortname" +msgstr "nama singkat judul" + +msgid "commonly used title for sorting purposes" +msgstr "judul yang umum digunakan untuk kepentingan pengurutan" + +msgid "artist" +msgstr "artis" + +msgid "person(s) responsible for the recording" +msgstr "orang yang bertanggungjawab terhadap rekaman" + +msgid "artist sortname" +msgstr "nama singkat artis" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" +"orang yang bertanggungjawab terhadap rekaman untuk kepentingan pengurutan" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album yang berisi data ini" + +msgid "album sortname" +msgstr "nama singkat album" + +msgid "album containing this data for sorting purposes" +msgstr "album yang berisi data ini untuk kepentingan pengurutan" + +msgid "album artist" +msgstr "album artis" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Artis untuk semua album, seperti yang seharusnya ditampilkan" + +msgid "album artist sortname" +msgstr "album artis nama urut" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Artis untuk semua album, seperti yang seharusnya diurutkan" + +msgid "date" +msgstr "tanggal" + +msgid "date the data was created (as a GDate structure)" +msgstr "tanggal data dibuat (menurut struktur GDate)" + +msgid "datetime" +msgstr "tanggalwaktu" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "tanggal dan waktu data dibuat (menurut struktur GDateTime)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre asal data ini" + +msgid "comment" +msgstr "komentar" + +msgid "free text commenting the data" +msgstr "teks bebas untuk mengomentari data" + +msgid "extended comment" +msgstr "komentar diperpanjang" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"teks bebas untuk mengomentari data dalam bentuk kunci=nilai atau " +"kunci[en]=komentar" + +msgid "track number" +msgstr "nomor jalur" + +msgid "track number inside a collection" +msgstr "nomor jalur di dalam koleksi" + +msgid "track count" +msgstr "hitungan jalur" + +msgid "count of tracks inside collection this track belongs to" +msgstr "hitungan jalur di dalam koleksi asal jalur ini" + +msgid "disc number" +msgstr "nomor cakram" + +msgid "disc number inside a collection" +msgstr "nomor cakram di dalam koleksi" + +msgid "disc count" +msgstr "hitungan cakram" + +msgid "count of discs inside collection this disc belongs to" +msgstr "hitungan cakram di dalam koleksi asal cakram ini" + +msgid "location" +msgstr "lokasi" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Asal media dalam bentuk URI (lokasi, dimana berkas asal atau arus " +"ditempatkan)" + +msgid "homepage" +msgstr "laman" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Laman untuk media ini (misalnya laman artis atau film)" + +msgid "description" +msgstr "keterangan" + +msgid "short text describing the content of the data" +msgstr "teks pendek yang menerangkan isi data" + +msgid "version" +msgstr "versi" + +msgid "version of this data" +msgstr "versi data ini" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - lihat http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisasi" + +msgid "copyright" +msgstr "hak cipta" + +msgid "copyright notice of the data" +msgstr "keterangan hak cipta data" + +msgid "copyright uri" +msgstr "uri hak cipta" + +msgid "URI to the copyright notice of the data" +msgstr "URI ke keterangan hak cipta data" + +msgid "encoded by" +msgstr "disandikan oleh" + +msgid "name of the encoding person or organization" +msgstr "nama penyandian orang atau organisasi" + +msgid "contact" +msgstr "kontak" + +msgid "contact information" +msgstr "informasi kontak" + +msgid "license" +msgstr "lisensi" + +msgid "license of data" +msgstr "lisensi data" + +msgid "license uri" +msgstr "uri lisensi" + +msgid "URI to the license of the data" +msgstr "URI ke lisensi data" + +msgid "performer" +msgstr "penampil" + +msgid "person(s) performing" +msgstr "orang yang tampil" + +msgid "composer" +msgstr "penyusun" + +msgid "person(s) who composed the recording" +msgstr "orang yang menyusun perekaman" + +msgid "conductor" +msgstr "konduktor" + +msgid "conductor/performer refinement" +msgstr "pemurnian konduktor/penampil" + +msgid "duration" +msgstr "durasi" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "panjang dalam unit waktu GStreamer (nanodetik)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec data tersimpan" + +msgid "video codec" +msgstr "codec video" + +msgid "codec the video data is stored in" +msgstr "codec data video tersimpan" + +msgid "audio codec" +msgstr "codec audio" + +msgid "codec the audio data is stored in" +msgstr "codec data audio tersimpan" + +msgid "subtitle codec" +msgstr "codec subjudul" + +msgid "codec the subtitle data is stored in" +msgstr "codec data subjudul tersimpan di" + +msgid "container format" +msgstr "format pembatasan" + +msgid "container format the data is stored in" +msgstr "format pembatasan data tersimpan" + +msgid "bitrate" +msgstr "bitrasi" + +msgid "exact or average bitrate in bits/s" +msgstr "bitrasi tepat atau rata-rata dalam bita/detik" + +msgid "nominal bitrate" +msgstr "bitrasi normal" + +msgid "nominal bitrate in bits/s" +msgstr "bitrasi nominal dalam bita/detik" + +msgid "minimum bitrate" +msgstr "bitrasi minimum" + +msgid "minimum bitrate in bits/s" +msgstr "bitrasi minimum dalam bita/detik" + +msgid "maximum bitrate" +msgstr "bitrasi maksimum" + +msgid "maximum bitrate in bits/s" +msgstr "bitrasi maksimum dalam bita/detik" + +msgid "encoder" +msgstr "penyandi" + +msgid "encoder used to encode this stream" +msgstr "penyandi yang digunakan untuk menyandi arus ini" + +msgid "encoder version" +msgstr "versi penyandi" + +msgid "version of the encoder used to encode this stream" +msgstr "versi penyandi yang digunakan untuk menyandi arus ini" + +msgid "serial" +msgstr "seri" + +msgid "serial number of track" +msgstr "nomor seri jalur" + +msgid "replaygain track gain" +msgstr "peraihan jalur peraihan putar ulang" + +msgid "track gain in db" +msgstr "peraihan jalur dalam db" + +msgid "replaygain track peak" +msgstr "puncak peraihan putar ulang jalur" + +msgid "peak of the track" +msgstr "puncak jalur" + +msgid "replaygain album gain" +msgstr "peraihan album peraihan putar ulang" + +msgid "album gain in db" +msgstr "peraihan album dalam db" + +msgid "replaygain album peak" +msgstr "puncak peraihan putar ulang album" + +msgid "peak of the album" +msgstr "puncak album" + +msgid "replaygain reference level" +msgstr "level referensi peraihan putar ulang" + +msgid "reference level of track and album gain values" +msgstr "level referensi nilai peraihan jalur dan album" + +msgid "language code" +msgstr "kode bahasa" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "kode bahasa arus ini, menganut ke ISO-639-1 atau ISO-639-2" + +msgid "language name" +msgstr "nama bahasa" + +msgid "freeform name of the language this stream is in" +msgstr "nama bebas dari bahasa tempat arus ini berada" + +msgid "image" +msgstr "gambar" + +msgid "image related to this stream" +msgstr "gambar yang berhubungan dengan arus ini" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "gambar pratayang" + +msgid "preview image related to this stream" +msgstr "gambar pratayang yang berhubungan dengan arus ini" + +msgid "attachment" +msgstr "lampiran" + +msgid "file attached to this stream" +msgstr "berkas yang dilampirkan dalam arus ini" + +msgid "beats per minute" +msgstr "denyut per menit" + +msgid "number of beats per minute in audio" +msgstr "jumlah denyut per menit dalam audio" + +msgid "keywords" +msgstr "kata kunci" + +msgid "comma separated keywords describing the content" +msgstr "kata kunci yang dipisahkan koma menerangkan isi data" + +msgid "geo location name" +msgstr "nama lokasi geografis" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"lokasi deskriptif dapat dibaca manusia dimana media telah direkam atau " +"dihasilkan" + +msgid "geo location latitude" +msgstr "lintang lokasi geografis" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"lokasi lintang geografis tempat media direkam atau dihasilkan dalam derajat " +"menurut WGS84 (nol pada khatulistiwa, nilai negatif untuk lintang selatan)" + +msgid "geo location longitude" +msgstr "bujur lokasi geografis" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"lokasi bujur geografis tempat media direkam atau dihasilkan dalam derajat " +"menurut WGS84 (nol pada meridian utama di Greenwich/UK, nilai negatif untuk " +"bujur timur)" + +msgid "geo location elevation" +msgstr "ketinggian lokasi geografis" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"ketinggian geografis tempat media direkam atau dihasilkan dalam meter " +"menurut WGS84 (nol adalah permukaan laut rata-rata)" + +msgid "geo location country" +msgstr "negara lokasi geografis" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"negara (dalam bahasa Inggris) tempat media telah direkam atau dihasilkan" + +msgid "geo location city" +msgstr "kota lokasi geografis" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "kota (dalam bahasa Inggris) tempat media telah direkam atau dihasilkan" + +msgid "geo location sublocation" +msgstr "sublokasi lokasi geografis" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"lokasi di dalam kota tempat media dihasilkan atau dibuat (mis. lingkungan)" + +msgid "geo location horizontal error" +msgstr "galat horizontal lokasi geografis" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "galat yang diharapkan dari pengukuran posisi horizontal (dalam meter)" + +msgid "geo location movement speed" +msgstr "kecepatan gerak lokasi geografis" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"kecepatan gerak divais penangkap ketika melakukan penangkapan dalam m/d" + +msgid "geo location movement direction" +msgstr "arah gerak lokasi geografis" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"mengindikasikan arah gerak divais yang melakukan penangkapan media. Arah " +"direpresentasikan sebagai derajat dalam representasi titik mengambang, 0 " +"berarti utara geografis, dan meningkat searah jarum jam" + +msgid "geo location capture direction" +msgstr "arah penangkapan lokasi geografis" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"mengindikasikan arah divais menunjuk ketika menangkap media. Arah " +"direpresentasikan sebagai derajat dalam representasi titik mengambang, 0 " +"berarti utara geografis, dan meningkat searah jarum jam" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "tampilkan nama" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Nama dari acara tv/podcast/serial media berasal" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "tampilkan nama singkat" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Nama dari acara tv/podcast/serial media berasal, untuk tujuan pengurutan" + +msgid "episode number" +msgstr "jumlah episode" + +msgid "The episode number in the season the media is part of" +msgstr "Jumlah episode dalam semusim tempat media menjadi bagiannya" + +msgid "season number" +msgstr "jumlah musim" + +msgid "The season number of the show the media is part of" +msgstr "Jumlah musim dari acara tempat media menjadi bagiannya" + +msgid "lyrics" +msgstr "lirik" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Lirik dari media, umumnya digunakan untuk lagu" + +msgid "composer sortname" +msgstr "nama singkat komposer" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "orang yang mengomposisi rekaman, untuk kepentingan pengurutan" + +msgid "grouping" +msgstr "pengelompokkan" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grup terkait media yang meliputi banyak jalur, seperti bagian yang berbeda " +"dari sebuah konser. Ini adalah level yang lebih tinggi dari jalur, tapi " +"lebih rendah dari album" + +msgid "user rating" +msgstr "peringkat pengguna" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Peringkat diatribusi oleh pengguna. Makin tinggi peringkat, makin suka " +"pengguna terhadap media ini" + +msgid "device manufacturer" +msgstr "manufaktur divais" + +msgid "Manufacturer of the device used to create this media" +msgstr "Manufaktur divais yang digunakan untuk menangkap media" + +msgid "device model" +msgstr "model divais" + +msgid "Model of the device used to create this media" +msgstr "Model divais yang digunakan untuk membuat media ini" + +msgid "application name" +msgstr "nama aplikasi" + +msgid "Application used to create the media" +msgstr "Aplikasi yang digunakan untuk membuat media" + +msgid "application data" +msgstr "data aplikasi" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Data aplikasi wajib yang akan diurutkan dalam media" + +msgid "image orientation" +msgstr "orientasi gambar" + +msgid "How the image should be rotated or flipped before display" +msgstr "Bagaimana gambar harus diputar atau dibalik sebelum ditampilkan" + +msgid "publisher" +msgstr "penerbit" + +msgid "Name of the label or publisher" +msgstr "Nama label atau penerbit" + +msgid "interpreted-by" +msgstr "diinterpretasi-oleh" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informasi tentang orang di belakang suatu remix dan interpretasi yang serupa" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Nomor catatan midi dari jalur audio." + +msgid "private-data" +msgstr "data-privat" + +msgid "Private data" +msgstr "Data privat" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Tak ditemukan penangan URI bagi protokol %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Skema URI '%s' tak didukung" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "GALAT: dari elemen %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Info awakutu tambahan:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "tautan tidak mempunyai sumber [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "tautan mempunyai buangan [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "tak ada properti \"%s\" di elemen \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "tak dapat mengatur properti \"%s\" di elemen \"%s\" ke \"%s\"" + +msgid "Delayed linking failed." +msgstr "Jeda penautan gagal." + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "tak dapat menautkan %s ke %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "tak dapat menautkan elemen buang untuk URI \"%s\"" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "tak dapat menautkan %s ke %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "tak dapat menautkan %s ke %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "tak ada elemen \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "referensi tak diharapkan \"%s\" - mengabaikan" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "referensi pad tak diharapkan \"%s\" - mengabaikan" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "tak dapat menguraikan huruf \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "tak ada elemen buang untuk URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "tak ada elemen sumber untuk URI \"%s\"" + +msgid "syntax error" +msgstr "galat sintaksis" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "menentukan kotak sampah kosong \"%s\", tak diizinkan" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "tak ada tempat sampah \"%s\", membongkar elemen" + +msgid "empty pipeline not allowed" +msgstr "baris pipa kosong tak diizinkan" + +msgid "A lot of buffers are being dropped." +msgstr "Banyak penyangga yang didrop." + +msgid "Internal data flow problem." +msgstr "Masalah aliran data internal." + +msgid "Internal data flow error." +msgstr "Galat aliran data internal." + +msgid "Internal clock error." +msgstr "Galat jam internal." + +msgid "Failed to map buffer." +msgstr "Gagal memetakan penyangga." + +msgid "Filter caps" +msgstr "Filter huruf" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Larang kemampuan yang mungkin diizinkan (KOSONG berarti APAPUN). Pengaturan " +"properti ini bersumber pada objek GstCaps yang disediakan." + +msgid "Caps Change Mode" +msgstr "Mode Ubah Huruf" + +msgid "Filter caps change behaviour" +msgstr "Filter perilaku ubah huruf" + +msgid "No Temp directory specified." +msgstr "Tak ada direktori Temp yang ditentukan." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Tak bisa membuat berkas temp \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Tak dapat membuka berkas \"%s\" untuk dibaca." + +msgid "Error while writing to download file." +msgstr "Galat ketika menulis ke berkas unduhan." + +msgid "No file name specified for writing." +msgstr "Tak ada nama berkas yang ditentukan untuk ditulis." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Tak dapat membuka berkas \"%s\" untuk ditulis." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Galat menulis berkas \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Galat ketika mencari di berkas \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Galat ketika menulis ke berkas \"%s\"." + +msgid "No file name specified for reading." +msgstr "Tak ada nama yang ditentukan untuk dibaca." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Tak bisa mendapatkan info di \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" adalah direktori." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Berkas \"%s\" adalah soket." + +msgid "Failed after iterations as requested." +msgstr "Gagal setelah pengulangan seperti yang diminta." + +msgid "caps" +msgstr "huruf" + +msgid "detected capabilities in stream" +msgstr "mendeteksi kemampuan dalam arus" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "paksa huruf" + +msgid "force caps without doing a typefind" +msgstr "paksa huruf tanpa melakukan pencarian tipe" + +msgid "Stream doesn't contain enough data." +msgstr "Arus tidak berisi cukup data." + +msgid "Stream contains no data." +msgstr "Arus tidak berisi data." + +msgid "Implemented Interfaces:\n" +msgstr "Antarmuka Terimplementasi:\n" + +msgid "readable" +msgstr "dapat dibaca" + +msgid "writable" +msgstr "dapat ditulis" + +msgid "deprecated" +msgstr "usang" + +msgid "controllable" +msgstr "dapat dikendalikan" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "dapat diubah dalam kondisi NULL, READY, PAUSED atau PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "hanya dapat diubah dalam kondisi NULL, READY, atau PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "hanya dapat diubah dalam kondisi NULL atau READY" + +msgid "Blacklisted files:" +msgstr "Berkas yang dilarang:" + +msgid "Total count: " +msgstr "Jumlah total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d berkas terlarang" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entri terlarang" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d fitur" + +msgid "Print all elements" +msgstr "Cetak semua elemen" + +msgid "Print list of blacklisted files" +msgstr "Cetak senarai dari berkas yang dilarang" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Cetak senarai dapat dibaca mesin dari fitur plugin yang ditentukan atau " +"semua plugin yang disediakan.\n" +" Berguna dalam koneksi dengan plugin " +"otomatis eksternal dalam mekanisme instalasi" + +msgid "List the plugin contents" +msgstr "Tampilkan isi plugin" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "Klik bila elemen atau plugin yang dinyatakan ada" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Ketika memeriksa apakah suatu elemen atau plugin ada, juga periksa versinya " +"paling tidak adalah versi yang dinyatakan" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Cetak skema URI yang didukung, dengan elemen yang mengimplementasikannya" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Tak dapat membuat berkas plugin: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Tak ada elemen atau plugin '%s'\n" + +msgid "Index statistics" +msgstr "Statistik indeks" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Mendapat pesan #%u dari elemen \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Mendapat pesan #%u dari bantalan \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Mendapat pesan #%u dari objek \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Mendapat Pesan #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Mendapat EOS dari elemen \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "MENEMUKAN TAG : ditemukan oleh elemen \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "MENEMUKAN TAG : ditemukan oleh bantalan \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "MENEMUKAN TAG : ditemukan oleh objek \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "MENEMUKAN TAG\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "MENEMUKAN TOC : ditemukan oleh elemen \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "MENEMUKAN TOC : ditemukan oleh objek \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "MENEMUKAN TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "PERINGATAN: dari elemen %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Pragulung, menunggu hingga penyangga selesai...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Pragulung, menunggu kemajuan selesai...\n" + +msgid "buffering..." +msgstr "menyangga..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Selesai menyangga, mengatur baris pipa ke MEMUTAR ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Menyangga, mengatur baris pipa ke JEDA ...\n" + +msgid "Redistribute latency...\n" +msgstr "Mendistribusikan ulang latency...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Mengatur tingkat ke %s seperti diminta oleh %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interupsi: Menghentikan baris pipa ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Kemajuan: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Elemen kurang: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Mendapat konteks dari elemen '%s': %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Tag keluaran (juga dikenal sebagai metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "TOC keluaran (bab dan edisi)" + +msgid "Output status information and property notifications" +msgstr "Informasi status keluaran dan pemberitahuan properti" + +msgid "Do not print any progress information" +msgstr "Jangan cetak informasi proses" + +msgid "Output messages" +msgstr "Pesan keluaran" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Jangan keluarkan informasi status untuk properti yang ditentukan jika " +"keluaran lengkap diaktifkan (dapat digunakan berkali-kali)" + +msgid "PROPERTY-NAME" +msgstr "NAMA-PROPERTI" + +msgid "Do not install a fault handler" +msgstr "Jangan instal penanganan galat" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Paksa EOS pada sumber sebelum mematikan pemipaan" + +msgid "Gather and print index statistics" +msgstr "Kumpulkan dan cetak statistik indeks" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "GALAT: baris pipa tak dapat dibangun: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "GALAT: baris pipa tak dapat dibangun.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "PERINGATAN: baris pipa berisi galat: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "GALAT: elemen 'baris pipa' tak ditemukan.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Mengatur baris pipa ke JEDA ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "GALAT: Baris pipa tak ingin dijedakan.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Baris pipa telah hidup dan tak membutuhkan PRAGULUNG ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Baris pipa PRAGULUNG ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "GALAT: baris pipa tak ingin dipragulung.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Baris pipa telah PRAGULUNG ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Mengatur baris pipa ke PUTAR ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "GALAT: baris pipa tidak ingin diputar.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS pada matikan diaktifkan -- Paksa EOS pada pemipaan\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS pada matikan diaktifkan -- menunggu EOS setelah Galat\n" + +msgid "Waiting for EOS...\n" +msgstr "Menunggu untuk EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS diterima - menghentikan baris pipa...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interupsi saat menunggu EOS - menghentikan baris pipa...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Galat terjadi ketika menunggu EOS\n" + +msgid "Execution ended after %" +msgstr "Eksekusi berakhir setelah %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Mengatur baris pipa ke SIAP ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Mengatur baris pipa ke KOSONG ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Membebaskan baris pipa ...\n" + +#~ msgid "bin" +#~ msgstr "tempat sampah" + +#~ msgid "Internal data stream error." +#~ msgstr "Galat arus data internal." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Jangan keluarkan informasi status dari TIPE" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPE1, TIPE2,..." + +#~ msgid "link without source element" +#~ msgstr "taut tanpa elemen sumber" + +#~ msgid "link without sink element" +#~ msgstr "taut tanpa elemen buang" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "tak ada elemen ke taut URI \"%s\"" diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 0000000..b26de01 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/it.gmo b/po/it.gmo new file mode 100644 index 0000000..a509630 Binary files /dev/null and b/po/it.gmo differ diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..c68a62f --- /dev/null +++ b/po/it.po @@ -0,0 +1,1578 @@ +# Italian translation for gstreamer 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 gstreamer package. +# +# Alcune note (essenzialmente una traduzione) dopo una lettura non troppo +# approfondita del manuale di GStreamer +# +# Tenete presente che, da un punto di vista dello sviluppatore, GStreamer +# è pesantemente influenzato dalla struttura di GLib, ed in particolare +# dei GObject, per cui le varie funzioni di libreria operano con il +# criterio della programmazione orientata agli oggetti. +# +# Per chi mi capisce, e tagliando via elementi qui non essenziali +# +# GObject +# GstObject +# GstPad +# GstElement +# GstBin +# GstPipeline +# GstThread +# +# +# --- Elements --- +# +# Un elemento è il blocco costruttivo di base per una "media pipeline". +# Tutti i differenti elementi di alto livello usati sono derivati da +# GstElement. Gli elementi sono "black boxes" con un numero di differenti +# aspetti. Uno di questi aspetti è la presenza di "pads", o punti di +# collegamento (link points). This terminology arises from soldering; pads +# are where wires can be attached. +# +# Tipi di elemento: +# * source - genera i dati da usare in una pipeline, ad es. leggendo +# da qualcosa (disco, rete, canale scheda audio...). Hanno solo un +# source pad +# * filter/codec - hanno dei pad di input ed output. Operano sui +# dati che ricevono nel sink pad e producono dati sul loro source +# pad. Un demuxer appartiene a questa categoria (1 in, 2 out) +# * sink - punto d'uscita di una pipeline, accettano dati senza +# produrne altri. Implementazioni di elementi sink sono la +# scrittura su file, la riproduzione audio o video. +# +# --- Pads --- +# +# Sono l'interfaccia di un elemento verso il mondo esterno. Permettono di +# esporre il tipo specifico di media che l'elemento può gestire. +# +# I pad possono essere source e sink: ciò dipende dal punto di vista +# dell'elemento cui appartengono +# +# Tipi di pad: +# * dinamici - l'elemento crea un pad se necessario, esempio: mpeg +# multiplexer crea pad a seconda dei differenti stream elementari +# rilevati nello stream mpeg +# * requested - pad creato on demand +# +# --- Capabilities --- +# +# Usate per descrivere i tipi di dati che possono "attraversare" il pad. +# Sono allegate al pad stesso. Capabilities sta per "capability chain" +# +# [Salto le parti complicate] Le capabilities sono usate per +# l'autoplugging (automatically finding plugins for a set of capabilities) +# ed il rilevamento di compatibilità (tra due pad collegati - "caps +# negotiation") +# +# --- Link --- +# +# Dati tre elementi (source, filter, sink) posso collegare in modo +# opportuno i relativi pad, creando una catena. Vedi allegato. +# +# --- Bins --- +# +# Un bin è un elemento contenitore. È possibile aggiungere elementi ad un +# bin, così come è possibile aggiungerlo ad un altro bin. +# +# Consente di combinare un gruppo di elementi collegati in un elemento +# logico. A questo punto non serve + ragionare in termini dei singoli +# elementi, ma del bin. +# +# Una pipeline è un elemento bin, un contenitore generico che consente la +# schedulazione degli elementi contenuti. Il "toplevel bin" deve essere +# una pipeline. +# +# Anche un thread è un elemento bin, che consente l'esecuzione separata. +# +# --- Buffers --- +# +# Contengono i dati che scorrono (flow) attraverso una pipeline. +# Tipicamente gli elementi source creano un nuovo buffer. +# +# --- Element states --- +# +# * NULL - predefinito, l'elemento è creato e non sta facendo +# alcunché +# * READY - pronto a fare qualcosa +# * PAUSED - in pausa +# * PLAYING - sta facendo qualcosa +# +# Si passa da NULL a PLAYING attraverso i due stati intermedi. +# +# ---------------------------------------- +# Luca Ferretti , 2004, 2005, 2006, 2007, 2008, 2009, 2010. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-10-25 10:03+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" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +# --gst-version +msgid "Print the GStreamer version" +msgstr "Stampa la versione di GStreamer" + +# --gst-fatal-warnings +msgid "Make all warnings fatal" +msgstr "Rende tutti i warning critici" + +# --gst-debug-help +msgid "Print available debug categories and exit" +msgstr "Stampa le categorie di debug disponibili ed esce" + +# --gst-debug-level=LIVELLO +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Livello di debug predefinito da 1 (solo errori) a 5 (tutto), oppure 0 per " +"nessun output" + +msgid "LEVEL" +msgstr "LIVELLO" + +# --gst-debug=ELENCO +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Elenco di coppie \"nome_categoria=livello\" separate da virgole per " +"impostare i livelli specifici per ogni singola categoria. Esempio: " +"GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "ELENCO" + +# --gst-debug-no-color +msgid "Disable colored debugging output" +msgstr "Disabilita output di debug colorato" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +# --gst-debug-disable +msgid "Disable debugging" +msgstr "Disabilita debug" + +# --gst-plugin-spew +msgid "Enable verbose plugin loading diagnostics" +msgstr "Abilita diagnostica prolissa del caricamento plugin" + +# --gst-plugin-path=PERCORSI +msgid "Colon-separated paths containing plugins" +msgstr "Percorsi che contengono i plugin separati da due punti (:)" + +msgid "PATHS" +msgstr "PERCORSI" + +# --gst-plugin-load=PLUGIN +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Elenco separato da virgole dei plugin da pre-caricare in aggiunta all'elenco " +"memorizzato nella variabile d'ambiente GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGIN" + +# --gst-disable-segtrap +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Disabilita il trapping dei segfault durante il caricamento dei plugin" + +# --gst-disable-registry-update +msgid "Disable updating the registry" +msgstr "Disabilita l'aggiornamento del registro" + +# --gst-disable-registry-fork +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Disabilita la generazione di un processo helper durante la scansione del " +"registro" + +# intestazione categoria opzioni precendenti +msgid "GStreamer Options" +msgstr "Opzioni di GStreamer" + +# --help-gst +msgid "Show GStreamer Options" +msgstr "Mostra le opzioni di GStreamer" + +msgid "Unknown option" +msgstr "Opzione sconosciuta" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer ha incontrato un errore generico delle librerie di base." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Gli sviluppatori di GStreamer sono stati troppo pigri per assegnare un " +"codice d'errore a questo errore." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Errore interno di GStreamer: codice non implementato." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Errore di GStreamer: cambio di stato non riuscito, alcuni elementi non sono " +"riusciti a pubblicare un appropriato messaggio di errore con il motivo del " +"fallimento." + +msgid "Internal GStreamer error: pad problem." +msgstr "Errore interno di GStreamer: problema di pad." + +msgid "Internal GStreamer error: thread problem." +msgstr "Errore interno di GStreamer: problema di thread." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Errore interno di GStreamer: problema di negoziazione." + +msgid "Internal GStreamer error: event problem." +msgstr "Errore interno di GStreamer: problema di evento." + +msgid "Internal GStreamer error: seek problem." +msgstr "Errore interno di GStreamer: problema di posizionamento." + +msgid "Internal GStreamer error: caps problem." +msgstr "Errore interno di GStreamer: problema di caps." + +msgid "Internal GStreamer error: tag problem." +msgstr "Errore interno di GStreamer: problema di tag." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Nell'installazione di GStreamer in uso manca un plugin." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Errore interno di GStreamer: problema di clock." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Questa applicazione sta tentando di usare una funzionalità di GStreamer che " +"è stata disabilitata." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer ha incontrato un errore generico nelle librerie di supporto." + +msgid "Could not initialize supporting library." +msgstr "Impossibile inizializzare la libreria di supporto." + +msgid "Could not close supporting library." +msgstr "Impossibile chiudere la libreria di supporto." + +msgid "Could not configure supporting library." +msgstr "Impossibile configurare la libreria di supporto." + +msgid "Encoding error." +msgstr "Errore nel codificare." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer ha incontrato un errore generico di risorse." + +msgid "Resource not found." +msgstr "Risorsa non trovata." + +msgid "Resource busy or not available." +msgstr "Risorsa occupata o non disponibile." + +msgid "Could not open resource for reading." +msgstr "Impossibile aprire la risorsa in lettura." + +msgid "Could not open resource for writing." +msgstr "Impossibile aprire la risorsa in scrittura." + +msgid "Could not open resource for reading and writing." +msgstr "Impossibile aprire la risorsa in lettura e scrittura." + +msgid "Could not close resource." +msgstr "Impossibile chiudere la risorsa." + +msgid "Could not read from resource." +msgstr "Impossibile leggere dalla risorsa." + +msgid "Could not write to resource." +msgstr "Impossibile scrivere sulla risorsa." + +msgid "Could not perform seek on resource." +msgstr "Impossibile effettuare un posizionamento sulla risorsa." + +msgid "Could not synchronize on resource." +msgstr "Impossibile sincronizzarsi sulla risorsa." + +msgid "Could not get/set settings from/on resource." +msgstr "Impossibile ottenere/regolare le impostazioni della risorsa." + +msgid "No space left on the resource." +msgstr "Niente spazio sulla risorsa." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Niente spazio sulla risorsa." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer ha incontrato un errore generico di stream." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"L'elemento non implementa la gestione di questo stream. Se possibile " +"segnalare il bug." + +msgid "Could not determine type of stream." +msgstr "Impossibile determinare il tipo di stream." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Lo stream è di un tipo differente da quello gestito da questo elemento." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Non è presente alcun codec che possa gestire questo tipo di stream." + +msgid "Could not decode stream." +msgstr "Impossibile decodificare lo stream." + +msgid "Could not encode stream." +msgstr "Impossibile fare l'encoding dello stream." + +msgid "Could not demultiplex stream." +msgstr "Impossibile de-multiplare lo stream." + +msgid "Could not multiplex stream." +msgstr "Impossibile multiplare lo stream." + +msgid "The stream is in the wrong format." +msgstr "Lo stream è nel formato errato." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Questo stream è cifrato e non è supportata la decodifica." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Questo stream è cifrato e non può essere decodificato perché non è stata " +"fornita alcuna chiave adatta." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nessun messaggio d'errore per il dominio %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nessun messaggio d'errore standard per il dominio %s e il codice %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Il clock selezionato non può essere usato nella pipeline." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Errore nello scrivere la cache di registro su %s: %s" + +# questo e i successivi sono nome + descrizione delle proprietà +# dei tag ID3 (o simili); le descrizioni per omogeneità iniziano +# tutte con la lettera minuscola +msgid "title" +msgstr "titolo" + +msgid "commonly used title" +msgstr "il titolo usato comunemente" + +msgid "title sortname" +msgstr "nome ordinamento titolo" + +msgid "commonly used title for sorting purposes" +msgstr "il titolo usato comunemente a scopo di ordinamento" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "la o le persone responsabili della registrazione" + +msgid "artist sortname" +msgstr "nome ordinamento artista" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" +"la o le persone responsabili della registrazione a scopo di ordinamento" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "l'album che contiene questi dati" + +msgid "album sortname" +msgstr "nome ordinamento album" + +msgid "album containing this data for sorting purposes" +msgstr "l'album che contiene questi dati a scopo di ordinamento" + +msgid "album artist" +msgstr "artista album" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "l'artista dell'intero album, così come dovrebbe essere mostrato" + +msgid "album artist sortname" +msgstr "nome ordinamento artista album" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "l'artista dell'intero album, così come dovrebbe essere ordinato" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "la data in cui i dati sono stati creati (come struttura GDate)" + +msgid "datetime" +msgstr "data/ora" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"la data e l'ora in cui i dati sono stati creati (come struttura GstDateTime)" + +msgid "genre" +msgstr "genere" + +msgid "genre this data belongs to" +msgstr "il genere a cui appartengono questi dati" + +msgid "comment" +msgstr "commento" + +msgid "free text commenting the data" +msgstr "del testo libero a commento dei dati" + +msgid "extended comment" +msgstr "commento esteso" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"del testo libero a commento dei dati nella forma chiave=valore o " +"chiave[it]=commento" + +msgid "track number" +msgstr "numero di traccia" + +msgid "track number inside a collection" +msgstr "il numero della traccia all'interno di una collezione" + +msgid "track count" +msgstr "totale tracce" + +msgid "count of tracks inside collection this track belongs to" +msgstr "" +"il totale delle tracce all'interno della collezione a cui questa traccia " +"appartiene" + +msgid "disc number" +msgstr "numero del disco" + +msgid "disc number inside a collection" +msgstr "il numero del disco all'interno di una collezione" + +msgid "disc count" +msgstr "totale dischi" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" +"il totale dei dischi all'interno della collezione a cui questo disco " +"appartiene" + +msgid "location" +msgstr "posizione" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"l'origine del contenuto multimediale come URI (posizione in cui il file o " +"stream originale è ospitato)" + +msgid "homepage" +msgstr "sito web" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"sito web per questo contenuto multimediale (cioè il sito web dell'artista o " +"del film)" + +msgid "description" +msgstr "descrizione" + +msgid "short text describing the content of the data" +msgstr "un breve testo che descrive il contenuto dei dati" + +msgid "version" +msgstr "versione" + +msgid "version of this data" +msgstr "la versione di questi dati" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - consultare http://www.ifpi.org/isrc" + +msgid "organization" +msgstr "organizzazione" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "l'avviso sul copyright dei dati" + +msgid "copyright uri" +msgstr "uri copyright" + +msgid "URI to the copyright notice of the data" +msgstr "l'URI all'avviso sul copyright dei dati" + +#, fuzzy +msgid "encoded by" +msgstr "encoder" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "contatto" + +msgid "contact information" +msgstr "le informazioni sul contatto" + +msgid "license" +msgstr "licenza" + +msgid "license of data" +msgstr "la licenza dei dati" + +msgid "license uri" +msgstr "uri licenza" + +msgid "URI to the license of the data" +msgstr "l'URI alla licenza dei dati" + +msgid "performer" +msgstr "interprete" + +msgid "person(s) performing" +msgstr "la o le persone che hanno interpretato" + +msgid "composer" +msgstr "compositore" + +msgid "person(s) who composed the recording" +msgstr "la o le persone che hanno composto della registrazione" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "durata" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "la lunghezza in unità di tempo di GStreamer (nanosecondi)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "il codec con cui di dati sono memorizzati" + +msgid "video codec" +msgstr "codec video" + +msgid "codec the video data is stored in" +msgstr "il codec con cui i dati video sono memorizzati" + +msgid "audio codec" +msgstr "codec audio" + +msgid "codec the audio data is stored in" +msgstr "il codec con cui i dati audio sono memorizzati" + +msgid "subtitle codec" +msgstr "codec sottotitoli" + +msgid "codec the subtitle data is stored in" +msgstr "il codec con cui i dati dei sottotitoli sono memorizzati" + +msgid "container format" +msgstr "formato contenitore" + +msgid "container format the data is stored in" +msgstr "il formato contenitore con cui i dati sono memorizzati" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "il bitrate esatto o medio in bit/s" + +msgid "nominal bitrate" +msgstr "bitrate nominale" + +msgid "nominal bitrate in bits/s" +msgstr "il bitrate nominale in bit/s" + +msgid "minimum bitrate" +msgstr "bitrate minimo" + +msgid "minimum bitrate in bits/s" +msgstr "il bitrate minimo in bit/s" + +msgid "maximum bitrate" +msgstr "bitrate massimo" + +msgid "maximum bitrate in bits/s" +msgstr "il bitrate massimo in bit/s" + +msgid "encoder" +msgstr "encoder" + +msgid "encoder used to encode this stream" +msgstr "l'encoder usato per codificare questo stream" + +msgid "encoder version" +msgstr "versione encoder" + +msgid "version of the encoder used to encode this stream" +msgstr "la versione dell'encoder usato per codificare questo stream" + +msgid "serial" +msgstr "seriale" + +msgid "serial number of track" +msgstr "il numero seriale della traccia" + +msgid "replaygain track gain" +msgstr "guadagno traccia replaygain" + +msgid "track gain in db" +msgstr "il guadagno della traccia in dB" + +msgid "replaygain track peak" +msgstr "picco traccia replaygain" + +msgid "peak of the track" +msgstr "il picco della traccia" + +msgid "replaygain album gain" +msgstr "guadagno album replaygain" + +msgid "album gain in db" +msgstr "il guadagno dell'album in dB" + +msgid "replaygain album peak" +msgstr "picco album replaygain" + +msgid "peak of the album" +msgstr "il picco dell'album" + +msgid "replaygain reference level" +msgstr "livello riferimento replaygain" + +msgid "reference level of track and album gain values" +msgstr "" +"il livello di riferimento dei valori di guadagno della traccia e dell'album" + +msgid "language code" +msgstr "codice lingua" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "il codice della lingua per questo stream, conforme a ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "codice lingua" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "immagine" + +msgid "image related to this stream" +msgstr "l'immagine relazionata a questo stream" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "immagine anteprima" + +msgid "preview image related to this stream" +msgstr "l'immagine di anteprima relazionata a questo stream" + +msgid "attachment" +msgstr "allegato" + +msgid "file attached to this stream" +msgstr "il file allegato a questo stream" + +# cfr http://it.wikipedia.org/wiki/Battiti_per_minuto +msgid "beats per minute" +msgstr "battiti per minuto" + +msgid "number of beats per minute in audio" +msgstr "il numero di battiti al minuto nell'audio" + +msgid "keywords" +msgstr "parole chiave" + +msgid "comma separated keywords describing the content" +msgstr "le parole chiave separate da virgole che descrivono il contesto" + +msgid "geo location name" +msgstr "nome località geog." + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"la descrizione comprensibile della località in cui il contenuto multimediale " +"è stato registrato o prodotto" + +msgid "geo location latitude" +msgstr "latitudine località geog." + +# http://it.wikipedia.org/wiki/WGS84 +# World Geodetic System 1984 +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"la latitudine geografica della località in cui il contenuto multimediale è " +"stato registrato o prodotto, espresso in gradi secondo lo standard WGS84 " +"(zero all'equatore, valori negativi per le latitudini a sud)" + +msgid "geo location longitude" +msgstr "longitudine località geog." + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"la longitudine geografica della località in cui il contenuto multimediale è " +"stato registrato o prodotto, in gradi secondo lo standard WGS84 (zero al " +"primo meridiano su Greenwich/UK, valori negativi per le longitudini a ovest)" + +msgid "geo location elevation" +msgstr "elevazione località geog." + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"l'elevazione geografica della località in cui il contenuto multimediale è " +"stato registrato o prodotto, in metri secondo lo standard WGS84 (zero è il " +"livello medio del mare)" + +msgid "geo location country" +msgstr "nazione località geog." + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"nazione (nome inglese) in cui il contenuto multimediale è stato registrato o " +"prodotto" + +msgid "geo location city" +msgstr "città località geog." + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"città (nome inglese) in cui il contenuto multimediale è stato registrato o " +"prodotto" + +msgid "geo location sublocation" +msgstr "sub-località località geog." + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"una località all'interno di una città in cui il contenuto multimediale è " +"stato registrato o prodotto (p.e. il quartiere)" + +msgid "geo location horizontal error" +msgstr "errore orizzontale località geog." + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "errore atteso delle misure di posizionamento orizzontale (in metri)" + +msgid "geo location movement speed" +msgstr "velocità movimento località geog." + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"la velocità di movimento del dispositivo di acquisizione durante " +"l'acquisizione stessa in m/s" + +msgid "geo location movement direction" +msgstr "direzione movimento località geog." + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica la direzione di movimento del dispositivo nell'eseguire " +"l'acquisizione di un contenuto multimediale; è rappresentato come gradi in " +"notazione floating point, con 0 che indica il nord geografico e incrementi " +"in sento orario" + +msgid "geo location capture direction" +msgstr "direzione di acquisizione località geog." + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica la direzione del dispositivo nell'eseguire l'acquisizione di un " +"contenuto multimediale; è rappresentato come gradi in notazione floating " +"point, con 0 che indica il nord geografico e incrementi in sento orario" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nome dello show" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"il nome dello show tv/podcast/serie da cui proviene il contenuto multimediale" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nome ordinamento dello show" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"il nome dello show tv/podcast/serie da cui proviene il contenuto " +"multimediale, a scopo di ordinamento" + +msgid "episode number" +msgstr "numero di episodio" + +msgid "The episode number in the season the media is part of" +msgstr "" +"il numero di episodio nella stagione di cui fa parte il contenuto " +"multimediale" + +msgid "season number" +msgstr "numero di stagione" + +msgid "The season number of the show the media is part of" +msgstr "" +"il numero di stagione dello show di cui fa parte il contenuto multimediale" + +msgid "lyrics" +msgstr "testo" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "il testo del contenuto multimediale, tipicamente usato per le canzoni" + +msgid "composer sortname" +msgstr "nome ordinamento compositore" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" +"la o le persone che hanno composto la registrazione, a scopo di ordinamento" + +msgid "grouping" +msgstr "raggruppamento" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"raggruppa elementi multimediali correlati che si dividono su diverse tracce, " +"come le diverse parti di un concerto; è un livello superiore rispetto alla " +"traccia, ma inferiore rispetto all'album" + +msgid "user rating" +msgstr "giudizio utente" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"giudizio attribuito da un utente; maggiore è il livello, più all'utente " +"piace questo contenuto multimediale" + +msgid "device manufacturer" +msgstr "produttore dispositivo" + +msgid "Manufacturer of the device used to create this media" +msgstr "" +"il produttore del dispositivo usato per creare questo contenuto multimediale" + +msgid "device model" +msgstr "modello dispositivo" + +msgid "Model of the device used to create this media" +msgstr "" +"il modello del dispositivo usato per creare questo contenuto multimediale" + +msgid "application name" +msgstr "nome applicazione" + +msgid "Application used to create the media" +msgstr "l'applicazione usata per creare il contenuto multimediale" + +msgid "application data" +msgstr "dati applicazione" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" +"i dati arbitrari dell'applicazione da serializzare all'interno del contenuto " +"multimediale" + +msgid "image orientation" +msgstr "orientamento immagine" + +msgid "How the image should be rotated or flipped before display" +msgstr "come ruotare o capovolgere l'immagine prima di mostrarla" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERRORE: dall'elemento %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Informazioni di debug aggiuntive:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nessuna proprietà «%s» nell'elemento «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "impossibile impostare la proprietà «%s» nell'elemento «%s» a «%s»" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "impossibile collegare %s a %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "impossibile collegare l'elemento sink per l'URI «%s»" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "impossibile collegare %s a %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "impossibile collegare %s a %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nessun elemento «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "impossibile analizzare i caps «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "elemento sink mancante per l'URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "elemento sorgente mancante per l'URI «%s»" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "specificato il bin vuoto «%s», non consentito" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nessun bin «%s», omesso" + +msgid "empty pipeline not allowed" +msgstr "pipeline vuota non consentito" + +msgid "A lot of buffers are being dropped." +msgstr "Stanno per essere scartati molti buffer." + +msgid "Internal data flow problem." +msgstr "Problema interno nel flusso di dati." + +msgid "Internal data flow error." +msgstr "Errore interno nel flusso di dati." + +msgid "Internal clock error." +msgstr "Errore interno di clock." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Caps di filtro" + +# * sul perché lasciato capabilities, vedi intro +# * possible allowed --> ammesse (e basta) +# * ANY tradotto, ma non so se è parola chiave, dovrei controllare. +# +# --Luca +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Pone limitazioni sulle capabilities ammesse (NULL significa QUALSIASI). " +"Impostando questa proprietà si prende un riferimento all'oggetto GstCaps " +"fornito." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Nessuna directory temporanea specificata." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Impossibile creare il file temporaneo «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Impossibile aprire il file «%s» in lettura." + +msgid "Error while writing to download file." +msgstr "Errore durante la scritta sul file di scaricamento." + +msgid "No file name specified for writing." +msgstr "Nessun nome di file specificato per la scrittura." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Impossibile aprire il file «%s» in scrittura." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Errore nel chiudere il file «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Errore durante il posizionamento sul file «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Errore durante la scrittura sul file «%s»." + +msgid "No file name specified for reading." +msgstr "Nessun nome di file specificato per la lettura." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Impossibile ottenere informazioni su «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» è una directory." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Il file «%s» è un socket." + +msgid "Failed after iterations as requested." +msgstr "Fallito dopo le iterazioni come richiesto." + +msgid "caps" +msgstr "caps" + +msgid "detected capabilities in stream" +msgstr "rilevate capabilites nello stream" + +msgid "minimum" +msgstr "minimo" + +msgid "force caps" +msgstr "forza i caps" + +msgid "force caps without doing a typefind" +msgstr "forza i caps senza eseguire un typefind" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Lo stream non contiene dati." + +msgid "Stream contains no data." +msgstr "Lo stream non contiene dati." + +msgid "Implemented Interfaces:\n" +msgstr "Interfacce implementate:\n" + +msgid "readable" +msgstr "leggibile" + +msgid "writable" +msgstr "scrivibile" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "controllabile" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "può passare allo stato NULL, READY, PAUSED o PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "può passare solo allo stato NULL, READY o PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "può passare solo allo stato NULL o READY" + +msgid "Blacklisted files:" +msgstr "File nella blacklist:" + +# Esempio: +# Total count: 23 plugins, 34 feature +msgid "Total count: " +msgstr "In totale: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d file nella blacklist" +msgstr[1] "%d file nella blacklist" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugin" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d voce nella blacklist" +msgstr[1] "%d voci nella blacklist" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funzionalità" +msgstr[1] "%d funzionalità" + +# -a, --print-all +msgid "Print all elements" +msgstr "Stampa tutti gli elementi" + +# -b, --print-blacklist +msgid "Print list of blacklisted files" +msgstr "Stampa l'elenco dei file nella blacklist" + +# --print-plugin-auto-install-info +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Stampa un elenco machine-parsable di funzionalità fornite dal plugin " +"specificato o da tutti i plugin.\n" +" Utile nelle connessioni con " +"meccanismi esterni di installazione automatica dei plugin." + +# Esempio: +# $ gst-inspect-0.10 --plugin +# video4linux: v4lsrc: Video (video4linux/raw) Source +# queue2: queue2: Queue +# gio: giostreamsrc: GIO stream source +# gio: giostreamsink: GIO stream sink +# gio: giosrc: GIO source +# gio: giosink: GIO sink +# volume: volume: Volume +msgid "List the plugin contents" +msgstr "Elenca il contenuto dei plugin" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +# -u, --uri-handlers +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Stampa gli schemi URI supportati, con gli elementi che li implementano" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Impossibile caricare il file di plugin: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Elemento o plugin «%s» inesistente\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Ottenuto messaggio #%u dall'elemento \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Ottenuto messaggio #%u dal pad \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Ottenuto messaggio #%u dall'oggetto \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Ottenuto messaggio #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Ottenuto EOS dall'elemento «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "TAG TROVATO : trovato dall'elemento \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "TAG TROVATO : trovato dal pad \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "TAG TROVATO : trovato dall'oggetto \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "TAG TROVATO\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TAG TROVATO : trovato dall'elemento \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TAG TROVATO : trovato dall'oggetto \"%s\".\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "TAG TROVATO\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMAZIONE:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ATTENZIONE: dall'elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Preroll eseguito, in attesa del riempimento buffer per completare...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Preroll eseguito, in attesa del riempimento buffer per completare...\n" + +msgid "buffering..." +msgstr "riempimento buffer..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Riempimento buffer completato, impostazione della pipeline a PLAYING ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Riempimento buffer, impostazione della pipeline a PAUSED ...\n" + +msgid "Redistribute latency...\n" +msgstr "Ridistribuzione latenza...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Impostazione dello stato a %s come richiesto da %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrotto: arresto della pipeline ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "nessun elemento «%s»" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ATTENZIONE: dall'elemento %s: %s\n" + +# -t, --tags +msgid "Output tags (also known as metadata)" +msgstr "Stampa i tag (anche noti come metadati)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +# -v, --verbose +msgid "Output status information and property notifications" +msgstr "Stampa informazioni di stato e notifiche delle proprietà" + +# -q, --quiet +msgid "Do not print any progress information" +msgstr "Non stampa alcuna informazione di avanzamento" + +# -m, --messages +msgid "Output messages" +msgstr "Stampa i messaggi" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +# -f, --no-fault +msgid "Do not install a fault handler" +msgstr "Non installa un gestore di fault" + +# -e, --eos-on-shutdown +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forza EOS sulle sorgenti prima di arrestare la pipeline" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERRORE: impossibile costruire la pipeline: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERRORE: impossibile costruire la pipeline.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ATTENZIONE: pipeline errata: %s.\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERRORE: l'elemento «pipeline» non è stato trovato.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Impostazione della pipeline a PAUSED ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERRORE: la pipeline non vuole mettersi in pausa.\n" + +# Sinks are special elements in GStreamer. This is because sink elements have to take care of preroll, which is the process that takes care that elements going into the GST_STATE_PAUSED state will have buffers ready after the state change. The result of this is that such elements can start processing data immediately after going into the GST_STATE_PLAYING state, without requiring to take some time to initialize outputs or set up decoders; all that is done already before the state-change to GST_STATE_PAUSED successfully completes. +# +# Preroll, however, is a complex process that would require the same code in many elements. Therefore, sink elements can derive from the GstBaseSink base-class, which does preroll and a few other utility functions automatically. The derived class only needs to implement a bunch of virtual functions and will work automatically. +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "La pipeline è viva e non necessita il PREROLL ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "La pipeline è in PREROLLING ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERRORE: la pipeline non vuole fare il preroll.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "La pipeline è in PREROLLED ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Impostazione della pipeline a PLAYING ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERRORE: la pipeline non vuole riprodurre.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS all'arresto abilitato -- Forzato EOS sulla pipeline\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS all'arresto abilitato -- Forzato EOS sulla pipeline\n" + +msgid "Waiting for EOS...\n" +msgstr "In attesa di EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Ricevuto EOS - arresto della pipeline...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrotto: arresto della pipeline ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Si è verificato un errore durante l'attesa di EOS\n" + +# secondo me quel % è un errore... magari dovrebbe +# essere %d o %s, a meno che non costruscano il messagio +# in qualche modo esoterico... +msgid "Execution ended after %" +msgstr "Esecuzione terminata dopo %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Impostazione della pipeline a READY ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Impostazione della pipeline a NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Esecuzione di free sulla pipeline...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Errore interno nello stream di dati." + +# -X, --exclude=TIPO1,TIPO2,... +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Non stampa le informazioni di stato per TIPO" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPO1,TIPO2,..." + +#~ msgid "link without source element" +#~ msgstr "collegamento senza elemento sorgente" + +#~ msgid "link without sink element" +#~ msgstr "collegamento senza elemento sink" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "elemento mancante per collegare l'URI «%s» a" + +# -T, --trace +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Stampa traccia di alloc (se abilitato in compilazione)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Uso: gst-xmllaunch [ ELEMENTO.PROPRIETA=VALORE ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERRORE: analisi del file xml «%s» non riuscita.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "ERRORE: nessun elemento pipeline toplevel nel file «%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "ATTENZIONE: al momento è supportato sono un elemento toplevel.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERRORE: impossibile analizzare l'argomento %d della riga di comando: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "ATTENZIONE: elemento con nome «%s» non trovato.\n" + +# -o, --output=FILE +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Salva su FILE una rappresentazione xml della pipeline ed esce" + +#~ msgid "FILE" +#~ msgstr "FILE" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Non installa i gestori di segnale per SIGUSR1 e SIGUSR2" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Errore nel ri-scansionare il registro %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Errore nel ri-scansionare il registro %s" diff --git a/po/ja.gmo b/po/ja.gmo new file mode 100644 index 0000000..5827dc2 Binary files /dev/null and b/po/ja.gmo differ diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000..38ef895 --- /dev/null +++ b/po/ja.po @@ -0,0 +1,1345 @@ +# Japanese translation file for gstreamer +# This file is put in the public domain. +# +# Makoto Kato , 2008, 2013. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.0.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2013-08-20 14:56+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=2; plural=(n != 1);\n" + +msgid "Print the GStreamer version" +msgstr "GStreamer バージョンを表示する" + +msgid "Make all warnings fatal" +msgstr "" + +msgid "Print available debug categories and exit" +msgstr "利用可能なデバッグカテゴリを表示して終了する" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" + +msgid "LEVEL" +msgstr "LEVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" + +msgid "LIST" +msgstr "LIST" + +msgid "Disable colored debugging output" +msgstr "デバッグ出力のカラー出力を無効にする" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "デバッグを無効にする" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" + +msgid "Colon-separated paths containing plugins" +msgstr "プラグインを含むコロン (:) で区切られたパス" + +msgid "PATHS" +msgstr "PATHS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"プラグインのロード中に発生したセグメンテーション違反のトラップを無効にする" + +msgid "Disable updating the registry" +msgstr "レジストリのアップデートを無効にする" + +#, fuzzy +msgid "Disable spawning a helper process while scanning the registry" +msgstr "レジストリをスキャンする際に fork() を使わない" + +msgid "GStreamer Options" +msgstr "GStreamer オプション" + +msgid "Show GStreamer Options" +msgstr "GStreamer オプションを表示する" + +msgid "Unknown option" +msgstr "不明なオプション" + +msgid "GStreamer encountered a general core library error." +msgstr "" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" + +msgid "Internal GStreamer error: code not implemented." +msgstr "GStreamer 内部エラー: コードが実装されていません" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +msgid "Internal GStreamer error: pad problem." +msgstr "GStreamer 内部エラー: パッドの問題" + +msgid "Internal GStreamer error: thread problem." +msgstr "GStreamer 内部エラー: スレッドの問題" + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer エラー: ネゴシエーションの問題" + +msgid "Internal GStreamer error: event problem." +msgstr "GStreamer 内部エラー: イベントの問題" + +msgid "Internal GStreamer error: seek problem." +msgstr "GStreamer 内部エラー: シークの問題" + +msgid "Internal GStreamer error: caps problem." +msgstr "" + +msgid "Internal GStreamer error: tag problem." +msgstr "GStreamer 内部エラー: タグの問題" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "GStreamer はプラグインを見つけることができません" + +msgid "GStreamer error: clock problem." +msgstr "GStreamer エラー: クロックの問題" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"このアプリケーションはGStreamer で無効にしている機能を使用しようとしています" + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer上で一般的なサポートライブラリエラーが起きました" + +msgid "Could not initialize supporting library." +msgstr "サポートライブラリを初期化できません" + +msgid "Could not close supporting library." +msgstr "サポートライブラリをクローズできません" + +msgid "Could not configure supporting library." +msgstr "サポートライブラリを構成できません" + +msgid "Encoding error." +msgstr "エンコーディングエラー" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer 上で一般的なリソースエラーが起きました" + +msgid "Resource not found." +msgstr "リソースが見つかりません" + +msgid "Resource busy or not available." +msgstr "リソースがビジーか利用可能ではありません" + +msgid "Could not open resource for reading." +msgstr "読み込み用にリソースを開くことができません" + +msgid "Could not open resource for writing." +msgstr "書き込み用にリソースを開くことができません" + +msgid "Could not open resource for reading and writing." +msgstr "読み書き用にリソースを開くことができません" + +msgid "Could not close resource." +msgstr "リソースをクローズできません" + +msgid "Could not read from resource." +msgstr "リソースから読み込むことができません" + +msgid "Could not write to resource." +msgstr "リソースを書き込むことができません" + +msgid "Could not perform seek on resource." +msgstr "リソース上でリークができません" + +msgid "Could not synchronize on resource." +msgstr "リソースを同期できません" + +msgid "Could not get/set settings from/on resource." +msgstr "リソース上またはリソースから設定を取得・変更ができません" + +msgid "No space left on the resource." +msgstr "リソースに空きがありません" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "リソースに空きがありません" + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer 上で一般的なストリームエラーが起きました" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"エレメントはこのストリームのための処理を実装していません。バグを登録してくだ" +"さい" + +msgid "Could not determine type of stream." +msgstr "ストリームの種類を判別できません" + +msgid "The stream is of a different type than handled by this element." +msgstr "" + +msgid "There is no codec present that can handle the stream's type." +msgstr "このストリームを処理することができるコーデックがありません" + +msgid "Could not decode stream." +msgstr "ストリームをデコードできません" + +msgid "Could not encode stream." +msgstr "ストリームをエンコードできません" + +msgid "Could not demultiplex stream." +msgstr "出力ストリームを取り出せません" + +msgid "Could not multiplex stream." +msgstr "ストリームを多重化できません" + +msgid "The stream is in the wrong format." +msgstr "ストリームのフォーマットが正しくありません" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "ストリームは暗号化をサポートしていません" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "ストリームは暗号化されていますが適したキーがないため復元できません" + +#, c-format +msgid "No error message for domain %s." +msgstr "" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "" + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "%s へのレジストリキャッシュの書き込み中にエラーが発生しました: %s" + +msgid "title" +msgstr "タイトル" + +msgid "commonly used title" +msgstr "共通につかわれるタイトル" + +msgid "title sortname" +msgstr "タイトルのソート名" + +msgid "commonly used title for sorting purposes" +msgstr "" + +msgid "artist" +msgstr "アーティスト" + +msgid "person(s) responsible for the recording" +msgstr "" + +msgid "artist sortname" +msgstr "アーティストのソート名" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "" + +msgid "album" +msgstr "アルバム" + +msgid "album containing this data" +msgstr "" + +msgid "album sortname" +msgstr "アルバムのソート名" + +msgid "album containing this data for sorting purposes" +msgstr "" + +#, fuzzy +msgid "album artist" +msgstr "アーティスト" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +#, fuzzy +msgid "album artist sortname" +msgstr "アーティストのソート名" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "日付" + +msgid "date the data was created (as a GDate structure)" +msgstr "データが作成された日付 (GData 構造体として)" + +#, fuzzy +msgid "datetime" +msgstr "日付" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "データが作成された日付 (GstDateTime 構造体として)" + +msgid "genre" +msgstr "ジャンル" + +msgid "genre this data belongs to" +msgstr "このデータが属しているジャンル" + +msgid "comment" +msgstr "コメント" + +msgid "free text commenting the data" +msgstr "" + +msgid "extended comment" +msgstr "" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" + +msgid "track number" +msgstr "トラック番号" + +msgid "track number inside a collection" +msgstr "コレクション内のトラック番号" + +msgid "track count" +msgstr "トラック数" + +msgid "count of tracks inside collection this track belongs to" +msgstr "" + +msgid "disc number" +msgstr "ディスク番号" + +msgid "disc number inside a collection" +msgstr "コレクション内のディスク番号" + +msgid "disc count" +msgstr "ディスク枚数" + +msgid "count of discs inside collection this disc belongs to" +msgstr "" + +msgid "location" +msgstr "場所" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "詳細" + +msgid "short text describing the content of the data" +msgstr "" + +msgid "version" +msgstr "バージョン" + +msgid "version of this data" +msgstr "このデータのバージョン" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - http://www.ifpi.org/isrc/ を参照して" +"ください" + +msgid "organization" +msgstr "組織" + +msgid "copyright" +msgstr "" + +msgid "copyright notice of the data" +msgstr "" + +msgid "copyright uri" +msgstr "" + +msgid "URI to the copyright notice of the data" +msgstr "" + +#, fuzzy +msgid "encoded by" +msgstr "エンコーダー" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "コンタクト" + +msgid "contact information" +msgstr "コンタクト情報" + +msgid "license" +msgstr "ライセンス" + +msgid "license of data" +msgstr "データのライセンス" + +msgid "license uri" +msgstr "ライセンス uri" + +msgid "URI to the license of the data" +msgstr "デーtのライセンスへの URI" + +msgid "performer" +msgstr "演奏者" + +msgid "person(s) performing" +msgstr "" + +msgid "composer" +msgstr "作曲者" + +msgid "person(s) who composed the recording" +msgstr "" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "演奏時間" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "GStreamer 時間単位 (nanoseconds) での長さ" + +msgid "codec" +msgstr "コーデック" + +msgid "codec the data is stored in" +msgstr "" + +msgid "video codec" +msgstr "動画コーデック" + +msgid "codec the video data is stored in" +msgstr "" + +msgid "audio codec" +msgstr "音声コーデック" + +msgid "codec the audio data is stored in" +msgstr "" + +msgid "subtitle codec" +msgstr "字幕コーデック" + +msgid "codec the subtitle data is stored in" +msgstr "字幕データが保存されているコーデック" + +msgid "container format" +msgstr "コンテナ形式" + +msgid "container format the data is stored in" +msgstr "" + +msgid "bitrate" +msgstr "ビットレート" + +msgid "exact or average bitrate in bits/s" +msgstr "" + +msgid "nominal bitrate" +msgstr "公称ビットレート" + +msgid "nominal bitrate in bits/s" +msgstr "公称ビットレート (bits/秒)" + +msgid "minimum bitrate" +msgstr "最小ビットレート" + +msgid "minimum bitrate in bits/s" +msgstr "最小ビットレート (bits/秒)" + +msgid "maximum bitrate" +msgstr "最大ビットレート" + +msgid "maximum bitrate in bits/s" +msgstr "最大ビットレート (bits/秒)" + +msgid "encoder" +msgstr "エンコーダー" + +msgid "encoder used to encode this stream" +msgstr "このストリームをエンコードするのに使ったエンコーダー" + +msgid "encoder version" +msgstr "エンコーダーバージョン" + +msgid "version of the encoder used to encode this stream" +msgstr "このストリームをエンコードするのに使ったエンコーダーのバージョン" + +msgid "serial" +msgstr "シリアル" + +msgid "serial number of track" +msgstr "トラックのシリアル番号" + +msgid "replaygain track gain" +msgstr "" + +msgid "track gain in db" +msgstr "" + +msgid "replaygain track peak" +msgstr "" + +msgid "peak of the track" +msgstr "トラックのピーク" + +msgid "replaygain album gain" +msgstr "" + +msgid "album gain in db" +msgstr "" + +msgid "replaygain album peak" +msgstr "" + +msgid "peak of the album" +msgstr "アルバムのピーク" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "言語コード" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "このストリームの ISO-639-1 または ISO-639-2 で書かれた言語コード" + +msgid "language name" +msgstr "言語名" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "画像" + +msgid "image related to this stream" +msgstr "このストリームに関連した画像" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "プレビュー画像" + +msgid "preview image related to this stream" +msgstr "このストリームに関連したプレビュー画像" + +msgid "attachment" +msgstr "添付" + +msgid "file attached to this stream" +msgstr "このストリームに添付されたファイル" + +msgid "beats per minute" +msgstr "BPM" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "キーワード" + +msgid "comma separated keywords describing the content" +msgstr "" + +msgid "geo location name" +msgstr "" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +msgid "geo location country" +msgstr "" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location city" +msgstr "場所" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +msgid "geo location sublocation" +msgstr "" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +msgid "geo location horizontal error" +msgstr "" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +msgid "geo location movement direction" +msgstr "" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +msgid "geo location capture direction" +msgstr "" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +#, fuzzy +msgid "show sortname" +msgstr "アーティストのソート名" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +msgid "episode number" +msgstr "エピソード番号" + +msgid "The episode number in the season the media is part of" +msgstr "" + +msgid "season number" +msgstr "シーズン番号" + +msgid "The season number of the show the media is part of" +msgstr "" + +msgid "lyrics" +msgstr "歌詞" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "作曲者のソート名" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +msgid "user rating" +msgstr "" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "デバイス製造元" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "このストリームをエンコードするのに使ったエンコーダーのバージョン" + +msgid "device model" +msgstr "デバイスモデル" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "このストリームをエンコードするのに使ったエンコーダーのバージョン" + +msgid "application name" +msgstr "アプリケーション名" + +msgid "Application used to create the media" +msgstr "" + +msgid "application data" +msgstr "アプリケーションデータ" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"追加のデバッグ情報:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "プロパティ \"%s\" がエレメント \"%s\" にありません" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "%s を %s へリンクできません" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "%s を %s へリンクできません" + +#, c-format +msgid "could not link %s to %s" +msgstr "%s を %s へリンクできません" + +#, c-format +msgid "no element \"%s\"" +msgstr "エレメント \"%s\" がありません" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "URI \"%s\" のソースエレメントがありません" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "プロパティ \"%s\" がエレメント \"%s\" にありません" + +msgid "empty pipeline not allowed" +msgstr "空のパイプラインは許可されません" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "内部データフローエラー" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "一時ファイル \"%s\" を作成できません" + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "読み込み用にファイル \"%s\" を開くことができません" + +msgid "Error while writing to download file." +msgstr "ファイルの書き込み中にエラーが発生しました" + +msgid "No file name specified for writing." +msgstr "書き込み用のファイル名が指定されていません" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "書き込み用にファイル \"%s\" を開くことができません" + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "ファイル \"%s\" のクローズ時にエラーが発生しました" + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "ファイル \"%s\" のシーク中にエラーが発生しました" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "ファイル \"%s\" の書き込み中にエラーが発生しました" + +msgid "No file name specified for reading." +msgstr "読み込み用のファイル名が指定されていません" + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "\"%s\" 上の情報を取得できません" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "ファイル \"%s\" はディレクトリです" + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "ファイル \"%s\" はソケットです" + +msgid "Failed after iterations as requested." +msgstr "" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "ストリーム内のケイパビリティを検出しました" + +msgid "minimum" +msgstr "最小値" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "ストリームでデータが含まれていません" + +msgid "Stream contains no data." +msgstr "ストリームでデータが含まれていません" + +msgid "Implemented Interfaces:\n" +msgstr "実装されているインターフェイス:\n" + +msgid "readable" +msgstr "読み込み可能" + +msgid "writable" +msgstr "書き込み可能" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "コントロール可能" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +msgid "Total count: " +msgstr "合計数: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +msgid "Print all elements" +msgstr "すべてのエレメントを表示する" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "プラグインファイルをロードできませんでした: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TAG\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "" + +msgid "FOUND TOC\n" +msgstr "FOUND TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"情報:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "バッファリング中..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"バッファリングが完了しましたので、パイプラインを再生中 (PLAYING) にしま" +"す...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "バッファリング中なので、パイプラインを一時停止 (PAUSED) にします...\n" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "割り込み: パイプラインを停止しています...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, c-format +msgid "Missing element: %s\n" +msgstr "エレメントが見つかりません: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "" + +msgid "Output tags (also known as metadata)" +msgstr "タグ (メタデータ) を出力する" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "" + +#, fuzzy +msgid "Do not print any progress information" +msgstr "TYPE のステータス情報を出力しない" + +msgid "Output messages" +msgstr "出力メッセージ" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "フォールトハンドラをインストールしない" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "エラー: パイプラインを構築することができません: %s\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "エラー: パイプラインを構築することができません\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "エラー: 'pipeline' エレメントが見つかりませんでした\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "パイプラインを一時停止 (PAUSED) にしています...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "パイプラインを再生中 (PLAYING) にしています...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +#, fuzzy +msgid "EOS received - stopping pipeline...\n" +msgstr "割り込み: パイプラインを停止しています...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "割り込み: パイプラインを停止しています...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +#, fuzzy +msgid "Freeing pipeline ...\n" +msgstr "パイプラインを解放 (FREEING) しています...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "内部データストリームエラー" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "TYPE のステータス情報を出力しない" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYPE1,TYPE2,..." + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "レジストリ %s の再スキャン中にエラーが発生しました: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "レジストリ %s の再スキャン中にエラーが発生しました" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "GStreamer 内部エラー: 状態変更に失敗しました" + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "ファイルディスクリプタ \"%d\" への書き込み中にエラーが発生しました" + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "ファイルディスクリプタ \"%d\" が正しくありません" + +#~ msgid "maximum" +#~ msgstr "最大値" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "使い方: gst-xmllaunch [ element.property=value ...]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "エラー: xml ファイル '%s' の解析に失敗しました\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "エラー: ファイル '%s' にトップレベルのパイプラインエレメントがありません\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time." +#~ msgstr "警告: トップレベルのエレメントは一つのみサポートしています" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "エラー: コマンドライン引数 %d を解析できません: %s\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "警告: エレメント名 '%s' が見つかりません\n" + +#~ msgid "FILE" +#~ msgstr "FILE" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "alloc トレースを表示する (コンパイル時に有効にする必要があります)" diff --git a/po/lt.gmo b/po/lt.gmo new file mode 100644 index 0000000..e956f11 Binary files /dev/null and b/po/lt.gmo differ diff --git a/po/lt.po b/po/lt.po new file mode 100644 index 0000000..80c3144 --- /dev/null +++ b/po/lt.po @@ -0,0 +1,1393 @@ +# Lithuanian translation for gstreamer. +# Copyright (C) 2010 Free Software Foundation +# This file is distributed under the same license as the gstreamer package. +# Aurimas Černius , 2010. +# Žygimantas Beručka , 2010. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.29.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-07-16 00:50+0300\n" +"Last-Translator: Žygimantas Beručka \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" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Virtaal 0.6.1\n" + +msgid "Print the GStreamer version" +msgstr "Išvesti GStreamer versiją" + +msgid "Make all warnings fatal" +msgstr "Padaryti visus įspėjimus lemtingais" + +msgid "Print available debug categories and exit" +msgstr "Išvesti prieinamas derinimo kategorijas ir išeiti" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Numatytasis derinimo lygis nuo 1 (tik klaidos) iki 5 (bet kas) arba 0 – " +"jokios išvesties" + +msgid "LEVEL" +msgstr "LYGIS" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Kableliais skiriamas category_name:level porų sąrašas, nustatantis " +"konkrečius lygius paskiroms kategorijoms. Pavyzdys: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "SĄRAŠAS" + +msgid "Disable colored debugging output" +msgstr "Išjungti spalvotą derinimo išvestį" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Išjungti derinimą" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Įjungti informatyvią įskiepių įkėlimo diagnostiką" + +msgid "Colon-separated paths containing plugins" +msgstr "Dvitaškiais skiriami keliai, kur yra įskiepių" + +msgid "PATHS" +msgstr "KELIAI" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Kableliais skiriamas sąrašas įskiepių, įkeltinų papildomai prie " +"GST_PLUGIN_PATH aplinkos kintamajame saugomo sąrašo" + +msgid "PLUGINS" +msgstr "ĮSKIEPIAI" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Išjungti segmentavimo klaidų gaudymą įskiepių įkėlimo metu" + +msgid "Disable updating the registry" +msgstr "Išjungti registro atnaujinimą" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Išjungti pagalbinio proceso paleidimą skenuojant registrą" + +msgid "GStreamer Options" +msgstr "GStreamer parinktys" + +msgid "Show GStreamer Options" +msgstr "Rodyti GStreamer parinktis" + +msgid "Unknown option" +msgstr "Nežinoma parinktis" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer susidūrė su bendrąją pagrindinės bibliotekos klaida." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "GStreamer kūrėjai nepasivargino priskirti šiai klaidai klaidos kodo." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Vidinė GStreamer klaida: kodas nerealizuotas." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer klaida: nepavyko pakeisti būsenos ir kažkuriam elementui nepavyko " +"išvesti tinkamo klaidos pranešimo su nesėkmės priežastimi." + +msgid "Internal GStreamer error: pad problem." +msgstr "Vidinė GStreamer klaida: pagrindo klaida." + +msgid "Internal GStreamer error: thread problem." +msgstr "Vidinė GStreamer klaida: gijos problema." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Vidinė GStreamer klaida: derybų problema." + +msgid "Internal GStreamer error: event problem." +msgstr "Vidinė GStreamer klaida: įvykio problema." + +msgid "Internal GStreamer error: seek problem." +msgstr "Vidinė GStreamer klaida: ieškojimo klaida." + +msgid "Internal GStreamer error: caps problem." +msgstr "Vidinė GStreamer klaida: galimybių problema." + +msgid "Internal GStreamer error: tag problem." +msgstr "Vidinė GStreamer klaida: žymos problema." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Jūsų įdiegtame GStreamer trūksta įskiepio." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Vidinė GStreamer klaida: laikrodžio problema." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "Ši programa bando naudoti GStreamer funkcijas, kurios buvo išjungtos." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer aptiko bendrąją palaikančiosios bibliotekos klaidą." + +msgid "Could not initialize supporting library." +msgstr "Nepavyko inicializuoti palaikančiosios bibliotekos." + +msgid "Could not close supporting library." +msgstr "Nepavyko užverti palaikančiosios bibliotekos." + +msgid "Could not configure supporting library." +msgstr "Nepavyko sukonfigūruoti palaikančiosios bibliotekos." + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer aptiko bendrąją ištekliaus klaidą." + +msgid "Resource not found." +msgstr "Išteklius nerastas." + +msgid "Resource busy or not available." +msgstr "Išteklius užimtas arba neprieinamas." + +msgid "Could not open resource for reading." +msgstr "Nepavyko atverti ištekliaus skaitymui." + +msgid "Could not open resource for writing." +msgstr "Nepavyko atverti ištekliaus rašymui." + +msgid "Could not open resource for reading and writing." +msgstr "Nepavyko atverti ištekliaus skaitymui ir rašymui." + +msgid "Could not close resource." +msgstr "Nepavyko užverti ištekliaus." + +msgid "Could not read from resource." +msgstr "Nepavyko skaityti iš ištekliaus." + +msgid "Could not write to resource." +msgstr "Nepavyko rašyti į išteklių." + +msgid "Could not perform seek on resource." +msgstr "Nepavyko atlikti paieškos ištekliuje." + +msgid "Could not synchronize on resource." +msgstr "Nepavyko sinchronizuoti su ištekliumi." + +msgid "Could not get/set settings from/on resource." +msgstr "Nepavyko gauti/nustatyti ištekliaus parametrų." + +msgid "No space left on the resource." +msgstr "Ištekliuje nebėra vietos." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Ištekliuje nebėra vietos." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer aptiko bendrąją srauto klaidą." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementas nesukuria srauto apdorojimo galimybės. Praneškite apie klaidą." + +msgid "Could not determine type of stream." +msgstr "Nepavyko aptikti srauto tipo." + +msgid "The stream is of a different type than handled by this element." +msgstr "Srautas yra kitokio tipo negu šis elementas gali apdoroti." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Nėra kodeko, galinčio apdoroti šio tipo srautą." + +msgid "Could not decode stream." +msgstr "Nepavyko dekoduoti srauto." + +msgid "Could not encode stream." +msgstr "Nepavyko koduoti srauto." + +msgid "Could not demultiplex stream." +msgstr "Nepavyko išretinti srauto." + +msgid "Could not multiplex stream." +msgstr "Nepavyko sutankinti srauto." + +msgid "The stream is in the wrong format." +msgstr "Srautas yra neteisingo formato." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Srautas yra šifruotas, o iššifravimo galimybė nepalaikoma." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Srautas yra šifruotas ir negali būti iššifruotas, kadangi nebuvo pateiktas " +"tinkamas raktas." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nėra klaidos pranešimo sričiai %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nėra standartinio klaidos pranešimo sričiai %s ir kodui %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Pasirinktas laikrodis negali būti naudojamas konvejeryje." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "pavadinimas" + +msgid "commonly used title" +msgstr "bendrai naudojamas pavadinimas" + +msgid "title sortname" +msgstr "pavadinimo rikiuojamas pavadinimas" + +msgid "commonly used title for sorting purposes" +msgstr "bendrai naudojamas pavadinimas rikiavimo reikmėms" + +msgid "artist" +msgstr "atlikėjas" + +msgid "person(s) responsible for the recording" +msgstr "asmuo (-enys), atsakingi už įrašą" + +msgid "artist sortname" +msgstr "atlikėjo rikiuojamas pavadinimas" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "asmuo (-enys), atsakingi už įrašą rikiavimo reikmėms" + +msgid "album" +msgstr "albumas" + +msgid "album containing this data" +msgstr "albumas su šiais duomenimis" + +msgid "album sortname" +msgstr "albumo rikiuojamas pavadinimas" + +msgid "album containing this data for sorting purposes" +msgstr "albumas su šiais duomenimis rikiavimo reikmėms" + +msgid "album artist" +msgstr "albumo atlikėjas" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Viso albumo atlikėjas, koks turi būti rodomas" + +msgid "album artist sortname" +msgstr "albumo atlikėjo rikiuojamas pavadinimas" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Viso albumo atlikėjas, koks turėtų būti rikiuojamas" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data, kada duomenys buvo sukurti (kaip GDate struktūra)" + +#, fuzzy +msgid "datetime" +msgstr "data" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data, kada duomenys buvo sukurti (kaip GDate struktūra)" + +msgid "genre" +msgstr "žanras" + +msgid "genre this data belongs to" +msgstr "žanras, kuriam priskiriami šie duomenys" + +msgid "comment" +msgstr "komentaras" + +msgid "free text commenting the data" +msgstr "laisvas tekstas, apibūdinantis duomenis" + +msgid "extended comment" +msgstr "išplėstinis komentaras" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"laisvas tekstas, apibūdinantis duomenis raktas=reikšmė arba " +"raktas[en]=komentaras forma" + +msgid "track number" +msgstr "takelio numeris" + +msgid "track number inside a collection" +msgstr "takelio numeris kolekcijoje" + +msgid "track count" +msgstr "takelių skaičius" + +msgid "count of tracks inside collection this track belongs to" +msgstr "takelių skaičius kolekcijoje, kuriai priklauso šis takelis" + +msgid "disc number" +msgstr "disko numeris" + +msgid "disc number inside a collection" +msgstr "disko numeris kolekcijoje" + +msgid "disc count" +msgstr "diskų skaičius" + +msgid "count of discs inside collection this disc belongs to" +msgstr "diskų skaičius kolekcijoje, kuriai priklauso šis diskas" + +msgid "location" +msgstr "vieta" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Medijos šaltinis kaip URI (vieta, kur patalpintas originalus failas arba " +"srautas)" + +msgid "homepage" +msgstr "svetainė" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Šios medijos namų svetainė (t. y. atlikėjo arba filmo svetainė)" + +msgid "description" +msgstr "aprašymas" + +msgid "short text describing the content of the data" +msgstr "trumpas tekstas, aprašantis duomenų turinį" + +msgid "version" +msgstr "versija" + +msgid "version of this data" +msgstr "šių duomenų versija" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Tarptautinis standartinis įrašų kodas – žiūrėkite http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organizacija" + +msgid "copyright" +msgstr "autoriaus teisės" + +msgid "copyright notice of the data" +msgstr "pranešimas apie duomenų autoriaus teises" + +msgid "copyright uri" +msgstr "autoriaus teisių uri" + +msgid "URI to the copyright notice of the data" +msgstr "URI, kur yra pranešimas apie duomenų autoriaus teises" + +#, fuzzy +msgid "encoded by" +msgstr "enkoderis" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "kontaktai" + +msgid "contact information" +msgstr "kontaktinė informacija" + +msgid "license" +msgstr "licencija" + +msgid "license of data" +msgstr "duomenų licencija" + +msgid "license uri" +msgstr "licencijos uri" + +msgid "URI to the license of the data" +msgstr "URI, kur yra duomenų licencija" + +msgid "performer" +msgstr "atlikėjas" + +msgid "person(s) performing" +msgstr "atliekantis (-ys) asmuo (-enys)" + +msgid "composer" +msgstr "kompozitorius" + +msgid "person(s) who composed the recording" +msgstr "asmuo (-enys), kuris (-ie) sukūrė įrašą" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "trukmė" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "trukmė GStreamer laiko vienetais (nanosekundėmis)" + +msgid "codec" +msgstr "kodekas" + +msgid "codec the data is stored in" +msgstr "kodekas, kuriame laikomi duomenys" + +msgid "video codec" +msgstr "vaizdo kodekas" + +msgid "codec the video data is stored in" +msgstr "vaizdo kodekas, kuriame laikomi duomenys" + +msgid "audio codec" +msgstr "garso kodekas" + +msgid "codec the audio data is stored in" +msgstr "garso kodekas, kuriame laikomi duomenys" + +msgid "subtitle codec" +msgstr "subtitrų kodekas" + +msgid "codec the subtitle data is stored in" +msgstr "kodekas, kuriame laikomi subtitrų duomenys" + +msgid "container format" +msgstr "konteinerio formatas" + +msgid "container format the data is stored in" +msgstr "konteinerio formatas, kuriame laikomi duomenys" + +msgid "bitrate" +msgstr "pralaidumas" + +msgid "exact or average bitrate in bits/s" +msgstr "tikslus arba vidutinis pralaidumas bitais per sekundę" + +msgid "nominal bitrate" +msgstr "nominalus pralaidumas" + +msgid "nominal bitrate in bits/s" +msgstr "nominalus pralaidumas bitais per sekundę" + +msgid "minimum bitrate" +msgstr "mažiausias pralaidumas" + +msgid "minimum bitrate in bits/s" +msgstr "mažiausias pralaidumas bitais per sekundę" + +msgid "maximum bitrate" +msgstr "didžiausias pralaidumas" + +msgid "maximum bitrate in bits/s" +msgstr "didžiausias pralaidumas bitais per sekundę" + +msgid "encoder" +msgstr "enkoderis" + +msgid "encoder used to encode this stream" +msgstr "enkoderis, naudotas šiam srautui koduoti" + +msgid "encoder version" +msgstr "enkoderio versija" + +msgid "version of the encoder used to encode this stream" +msgstr "enkoderio, naudoto šiam srautui koduoti, versija" + +msgid "serial" +msgstr "serija" + +msgid "serial number of track" +msgstr "takelio serijos numeris" + +msgid "replaygain track gain" +msgstr "replaygain takelio stiprinimas" + +msgid "track gain in db" +msgstr "takelio stiprinimas decibelais" + +msgid "replaygain track peak" +msgstr "replaygain takelio viršūnė" + +msgid "peak of the track" +msgstr "takelio viršūnė" + +msgid "replaygain album gain" +msgstr "replaygain albumo stiprinimas" + +msgid "album gain in db" +msgstr "albumo stiprinimas decibelais" + +msgid "replaygain album peak" +msgstr "replaygain albumo viršūnė" + +msgid "peak of the album" +msgstr "albumo viršūnė" + +msgid "replaygain reference level" +msgstr "replaygain santykinis lygis" + +msgid "reference level of track and album gain values" +msgstr "takelio ir albumo stiprinimo reikšmių santykinis lygis" + +msgid "language code" +msgstr "kalbos kodas" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "šio srauto kalbos kodas, atitinkantis ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "kalbos kodas" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "paveikslėlis" + +msgid "image related to this stream" +msgstr "paveikslėlis, susietas su srautu" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "peržiūros paveikslėlis" + +msgid "preview image related to this stream" +msgstr "peržiūros paveikslėlis, susijęs su srautu" + +msgid "attachment" +msgstr "priedas" + +msgid "file attached to this stream" +msgstr "failas, pridėtas prie srauto" + +msgid "beats per minute" +msgstr "taktų per minutę" + +msgid "number of beats per minute in audio" +msgstr "taktų skaičius per minutę garso įraše" + +msgid "keywords" +msgstr "raktažodžiai" + +msgid "comma separated keywords describing the content" +msgstr "kableliais skiriami raktažodžiai, aprašantys turinį" + +msgid "geo location name" +msgstr "geografinės vietos pavadinimas" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "aiškus vietovės, kurioje medija buvo įrašyta arba sukurta, aprašymas" + +msgid "geo location latitude" +msgstr "geografinės vietos platuma" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"vietovės platuma, kur medija buvo įrašyta arba sukurta, laipsniais pagal " +"WGS85 (nulis ties pusiauju, neigiamos reikšmės – pietinėms platumoms)" + +msgid "geo location longitude" +msgstr "geografinės vietos ilguma" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"vietovės ilguma, kur medija buvo įrašyta arba sukurta, laipsniais pagal " +"WGS84 (nulis ties pirmuoju meridianu Grinviče/JK, neigiamos reikšmės – " +"rytinėms ilgumoms)" + +msgid "geo location elevation" +msgstr "geografinės vietos aukštuma" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"aukštuma, kur medija buvo įrašyta arba sukurta, metrais pagal WGS84 (nulis – " +"vidutinis jūros lygis)" + +msgid "geo location country" +msgstr "geografinė vietos šalis" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"šalis (angliškas pavadinimas), kurioje medija buvo įrašyta arba sukurta" + +msgid "geo location city" +msgstr "geografinės vietos miestas" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"miestas (angliškas pavadinimas), kuriame medija buvo įrašyta arba sukurta" + +msgid "geo location sublocation" +msgstr "geografinės vietos sublokacija" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"vietove mieste, kuriame medija buvo pagaminta arba sukurta, (pvz., " +"kaimynystė)" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "geografinės vietos pavadinimas" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "geografinės vietos judėjimo greitis" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "įrašančio prietaiso judėjimo greitis m/s įrašinėjant" + +msgid "geo location movement direction" +msgstr "geografinės vietos judėjimo kryptis" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"nurodo mediją įrašančio prietaiso judėjimo kryptį. Ji nurodoma laipsniais " +"slankaus kablelio pavidalu, „0“ reiškia šiaurę, reikšmė didėja pagal " +"laikrodžio rodyklę" + +msgid "geo location capture direction" +msgstr "geografinės vietos įrašymo kryptis" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"nurodo kryptį, kuria nukreiptas mediją įrašantis įrenginys. Pateikiama " +"laipsniais slankaus kablelio pavidalu, „0“ reiškia geografinę šiaurę, " +"reikšmė didėja pagal laikrodžio rodyklę" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "laidos pavadinimas" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Tv / tinklalaidės / serialo, iš kurio yra medija, laidos pavadinimas" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "laidos rikiuojamas pavadinimas" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Tv / tinklalaidės / serialo, iš kurio yra medija, laidos pavadinimas " +"rikiavimo reikmėms" + +msgid "episode number" +msgstr "epizodo numeris" + +msgid "The episode number in the season the media is part of" +msgstr "Sezono, kuriam priklauso medija, epizodo numeris" + +msgid "season number" +msgstr "sezono numeris" + +msgid "The season number of the show the media is part of" +msgstr "Laidos sezono, kuriam priklauso medija, numeris" + +msgid "lyrics" +msgstr "žodžiai" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Medijos žodžiai, dažniausiai naudojama dainoms" + +msgid "composer sortname" +msgstr "kompozitoriaus rikiuojamas vardas" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "asmens (-enų), kuris (-ie) sukūrė įrašą, vardas rikiavimo reikmėms" + +msgid "grouping" +msgstr "grupavimas" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupuoja susijusias medijas, susidedančias iš daugelio takelių, pvz., " +"skirtingas koncerto dalis. Tai aukštesnis lygmuo nei takelis, bet žemesnis " +"nei albumas" + +msgid "user rating" +msgstr "naudotojo įvertinimas" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Naudotojo nurodytas įvertinimas. Kuo geresnis įvertinimas, tuo labiau " +"naudotojas mėgsta šią mediją" + +msgid "device manufacturer" +msgstr "įrenginio gamintojas" + +msgid "Manufacturer of the device used to create this media" +msgstr "Įrenginio, naudoto šiai medijai sukurti, gamintojas" + +msgid "device model" +msgstr "įrenginio modelis" + +msgid "Model of the device used to create this media" +msgstr "Įrenginio, naudoto šiai medijai sukurti, modelis" + +#, fuzzy +msgid "application name" +msgstr "geografinės vietos pavadinimas" + +#, fuzzy +msgid "Application used to create the media" +msgstr "Įrenginio, naudoto šiai medijai sukurti, modelis" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "paveikslėlio orientacija" + +msgid "How the image should be rotated or flipped before display" +msgstr "Kaip paveikslėlis turėtų būti pasuktas arba apverstas prieš parodymą" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "KLAIDA: iš elemento %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Papildoma derinimo informacija:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nenurodyta savybė „%s“ elemente „%s“" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nepavyko nustatyti savybės „%s“ elemente „%s“ į „%s“" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nepavyko susieti %s su %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "nepavyko susieti išvesties elemento URI „%s“" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nepavyko susieti %s su %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nepavyko susieti %s su %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nėra elemento „%s“" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nepavyko perskaityti galimybių „%s“" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "nėra išvesties elemento URI „%s“" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "nėra šaltinio elemento URI „%s“" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "nurodytas tuščias dėklas „%s“, neleidžiama" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nėra dėklo „%s“, praleidžiama" + +msgid "empty pipeline not allowed" +msgstr "tuščias konvejeris neleidžiamas" + +msgid "A lot of buffers are being dropped." +msgstr "Atlaisvinama daug buferių." + +msgid "Internal data flow problem." +msgstr "Vidinė duomenų tėkmės problema." + +msgid "Internal data flow error." +msgstr "Vidinė duomenų tėkmės klaida." + +msgid "Internal clock error." +msgstr "Vidinė laikrodžio klaida." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Filtruoti galimybes" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Riboti galimas leidžiamas galimybes (NULL – BET KOKIAS). Nustatant šią " +"savybę nurodoma į pateiktą GstCaps objektą." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Nenurodytas laikinas katalogas." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nepavyko sukurti laikino failo „%s“." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nepavyko atverti failo „%s“ skaitymui." + +msgid "Error while writing to download file." +msgstr "Klaida rašant į atsiuntimo failą." + +msgid "No file name specified for writing." +msgstr "Nenurodytas failo pavadinimas rašymui." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nepavyko atverti failo „%s“ rašymui." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Klaida užveriant failą „%s“." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Klaida ieškant faile „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Klaida rašant į failą „%s“." + +msgid "No file name specified for reading." +msgstr "Nenurodytas failo pavadinimas skaitymui." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nepavyko gauti duomenų apie „%s“." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s“ yra katalogas." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Failas „%s“ yra lizdas." + +msgid "Failed after iterations as requested." +msgstr "Nesėkmė po iteracijų kaip ir reikalauta." + +msgid "caps" +msgstr "galimybės" + +msgid "detected capabilities in stream" +msgstr "aptiktos galimybės sraute" + +msgid "minimum" +msgstr "mažiausios" + +msgid "force caps" +msgstr "reikalauti galimybių" + +msgid "force caps without doing a typefind" +msgstr "priverstinai naudoti galimybes neatliekant tipo paieškos" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Sraute nėra duomenų." + +msgid "Stream contains no data." +msgstr "Sraute nėra duomenų." + +msgid "Implemented Interfaces:\n" +msgstr "Realizuotos sąsajos:\n" + +msgid "readable" +msgstr "skaitomas" + +msgid "writable" +msgstr "rašomas" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "valdomas" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "Failai juodajame sąraše:" + +msgid "Total count: " +msgstr "Bendras skaičius:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d failas juodajame sąraše" +msgstr[1] "%d failai juodajame sąraše" +msgstr[2] "%d failų juodajame sąraše" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d įskiepis" +msgstr[1] "%d įskiepiai" +msgstr[2] "%d įskiepių" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d juodojo sąrašo įrašas" +msgstr[1] "%d juodojo sąrašo įrašai" +msgstr[2] "%d juodojo sąrašo įrašų" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funkcija" +msgstr[1] "%d funkcijos" +msgstr[2] "%d funkcijų" + +msgid "Print all elements" +msgstr "Išvesti visus elementus" + +msgid "Print list of blacklisted files" +msgstr "Išvesti failus juodajame sąraše" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Išspausdinti mašininiu būdu perskaitomą sąrašą funkcijų, kurias suteikia " +"nurodytasis arba visi įskiepiai.\n" +" Naudinga naudojant su išoriniais " +"automatiniais įskiepių diegimo mechanizmais" + +msgid "List the plugin contents" +msgstr "Parodyti įskiepio turinį" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Išvesti palaikomas URI schemas su jas sukuriančiais elementais" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nepavyko įkelti įskiepio failo: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nėra tokio elemento arba įskiepio „%s“\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Gautas pranešimas #%u iš elemento „%s“ (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Gautas pranešimas #%u iš pagrindo „%s:%s“ (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Gautas pranešimas #%u iš objekto „%s“ (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Gautas pranešimas #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Gautas EOS iš elemento „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "RASTA ŽYMA : rasta elemento „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "RASTA ŽYMA : rasta pagrindo „%s:%s“.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "RASTA ŽYMA : rasta objekto „%s“.\n" + +msgid "FOUND TAG\n" +msgstr "RASTA ŽYMA\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "RASTA ŽYMA : rasta elemento „%s“.\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "RASTA ŽYMA : rasta objekto „%s“.\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "RASTA ŽYMA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACIJA:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ĮSPĖJIMAS: iš elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Paruošta, laukiama kol bus sukurtas buferis...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Paruošta, laukiama kol bus sukurtas buferis...\n" + +msgid "buffering..." +msgstr "kuriamas buferis..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Buferis sukurtas, konvejeris nustatomas GROJIMUI...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Kuriamas buferis, konvejeris nustatomas į PRISTABDYTĄ...\n" + +msgid "Redistribute latency...\n" +msgstr "Perskirstyti gaišties laiką...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Nustatoma būsena į %s, kaip prašė %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Pertraukimas: stabdomas konvejeris...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "nėra elemento „%s“" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "ĮSPĖJIMAS: iš elemento %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Išvesti žymas (dar žinomas kaip metaduomenys)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Išvesti būsenos informaciją ir savybių pranešimus" + +msgid "Do not print any progress information" +msgstr "Neišvesti jokios informacijos apie pažangą" + +msgid "Output messages" +msgstr "Išvesti pranešimus" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Neįdiegti klaidų apdorojimo posistemės" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Priverstinai naudoti EOS šaltiniuose prie išjungiant konvejerį" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "KLAIDA: nepavyko sukurti konvejerio: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "KLAIDA: nepavyko sukurti konvejerio.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ĮSPĖJIMAS: klaidingas konvejeris: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "KLAIDA: „pipeline“ elementas nerastas.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Nustatomas konvejeris į PRISTABDYTĄ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "KLAIDA: konvejeris nesileidžia pristabdomas.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Konvejeris aktyvus ir nereikalauja PARUOŠIMO...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Konvejeris RUOŠIAMAS...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "KLAIDA: konvejeris nesileidžia paruošiamas.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Konvejeris PARUOŠTAS...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Nustatomas konvejeris į GROJAMA...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "KLAIDA: konvejeris nepradeda groti.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Įjungtas EOS išjungiant – priverstinai naudojama EOS konvejeryje\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Įjungtas EOS išjungiant – priverstinai naudojama EOS konvejeryje\n" + +msgid "Waiting for EOS...\n" +msgstr "Laukiama EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS gautas – stabdomas konvejeris...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Pertraukimas: stabdomas konvejeris...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Įvyko klaida laukiant EOS\n" + +msgid "Execution ended after %" +msgstr "Vykdymas baigėsi po %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Nustatomas konvejeris į PARUOŠTA...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Nustatomas konvejeris į NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Atlaisvinamas konvejeris...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Vidinė duomenų srauto klaida." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Neišvesti šio TIPO būsenos informacijos" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPAS1,TIPAS2,..." + +#~ msgid "link without source element" +#~ msgstr "saitas be šaltinio elemento" + +#~ msgid "link without sink element" +#~ msgstr "saitas be išvesties elemento" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "nėra elemento, su kuriuo susieti URI „%s“" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Išvesti alloc sekimą (jei įjungta kompiliavimo metu)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Naudojimas: gst-xmllaunch [ elementas.savybė=reikšmė ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "KLAIDA: nepavyko perskaityti xml failo „%s“.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "KLAIDA: nėra aukščiausio lygmens konvejerio elemento faile „%s“.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "ĮSPĖJIMAS: šiuo metu palaikomas tik vienas aukščiausio lygmens " +#~ "elementas.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "KLAIDA: nepavyko apdoroti komandinės eilutės argumento %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "ĮSPĖJIMAS: nerastas elementas „%s“.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Įrašyti konvejerio xml atitikmenį į FAILĄ ir išeiti" + +#~ msgid "FILE" +#~ msgstr "FAILAS" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "" +#~ "Neįdiegti signalų apdorojimo posistemės signalams SIGUSR1 ir SIGUSR2" diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..5e9a3d8 --- /dev/null +++ b/po/meson.build @@ -0,0 +1,3 @@ +i18n = import('i18n') + +i18n.gettext('gstreamer-1.0', preset: 'glib') diff --git a/po/nb.gmo b/po/nb.gmo new file mode 100644 index 0000000..58de8f9 Binary files /dev/null and b/po/nb.gmo differ diff --git a/po/nb.po b/po/nb.po new file mode 100644 index 0000000..c86c401 --- /dev/null +++ b/po/nb.po @@ -0,0 +1,1346 @@ +# Norwegian bokmaal translation of gstreamer. +# This file is put in the public domain. +# +# Kjartan Maraas , 2004-2010. +# Johnny A. Solbu , 2015-2017 +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-23 22:59+0200\n" +"Last-Translator: Johnny A. Solbu \n" +"Language-Team: Norwegian Bokmaal \n" +"Language: nb_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.7.1\n" + +msgid "Print the GStreamer version" +msgstr "Skriv ut versjonsnummer for GStreamer" + +msgid "Make all warnings fatal" +msgstr "La alle advarsler være fatale" + +msgid "Print available debug categories and exit" +msgstr "Skriv ut tilgjengelige feilsøkingskategorier og avslutt" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Standard feilsøkingsnivå fra 1 (kun feil) til 9 (noe) eller 0 for ingen " +"utdata" + +msgid "LEVEL" +msgstr "NIVÅ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Kommaseparert liste over kategori_navn:nivåpar for å sette spesifikke nivåer " +"for de enkelte kategoriene. Eksempel: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTE" + +msgid "Disable colored debugging output" +msgstr "Deaktiver farget feilsøkingsinformasjon" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Endrer fargemodus for feilsøking logg. Mulige moduser: av, på, deaktiver, " +"auto, unix" + +msgid "Disable debugging" +msgstr "Slå av feilsøking" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Aktiver utførlig diagnostikk ved lasting av programtillegg" + +msgid "Colon-separated paths containing plugins" +msgstr "Kolon-separerte stier som inneholder programtillegg" + +msgid "PATHS" +msgstr "STIER" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Kommaseparert liste av programtillegg til å forhåndslaste i tillegg til " +"listen som er lagret i miljøvariabelen GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "TILLEGG" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Deaktiver fangst av segmenteringsfeil under programtillegglasting" + +msgid "Disable updating the registry" +msgstr "Deaktiver oppdatering av registeret" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Deaktiver forgrening av hjelperprosess under scanning av registeret" + +msgid "GStreamer Options" +msgstr "GStreamer-flagg" + +msgid "Show GStreamer Options" +msgstr "Vis flagg for GStreamer" + +msgid "Unknown option" +msgstr "Ukjent flagg" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer møtte en generell kjernebiblioteksfeil." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamerutviklerne var for lat til å tildele denne feilen en feilkode ." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Intern GStreamerfeil: kode ikke implementert." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamerfeil: statusendring mislyktes og noen element mislyktes i å legge " +"inn en skikkelig feilmelding med årsaken til svikten." + +msgid "Internal GStreamer error: pad problem." +msgstr "Intern GStreamerfeil: utfyllingsproblem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Intern GStreamerfeil: trådproblem." + +msgid "GStreamer error: negotiation problem." +msgstr "Intern GStreamerfeil: forhandlingsproblem." + +msgid "Internal GStreamer error: event problem." +msgstr "Intern GStreamerfeil: hendelsesproblem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Intern GStreamerfeil: søkeproblem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Intern GStreamerfeil: caps-problem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Intern GStreamerfeil: taggproblem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "GStreamerinstallasjonen din mangler et programtillegg." + +msgid "GStreamer error: clock problem." +msgstr "Intern GStreamerfeil: klokkeproblem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Dette programmet prøver å bruke GStreamerfunksjonalitet som har blitt " +"deaktivert." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer har møtt et generelt støttebiblioteksfeil." + +msgid "Could not initialize supporting library." +msgstr "Kunne ikke initiere støttebibliotek." + +msgid "Could not close supporting library." +msgstr "Kunne ikke lukke støttebibliotek." + +msgid "Could not configure supporting library." +msgstr "Kunne ikke konfigurere støttebibliotek." + +msgid "Encoding error." +msgstr "Feil i koding." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer har møtt en generelt resursfeil." + +msgid "Resource not found." +msgstr "Ressursen ble ikke funnet." + +msgid "Resource busy or not available." +msgstr "Ressursen er opptatt eller ikke tilgjengelig." + +msgid "Could not open resource for reading." +msgstr "Kunne ikke åpne ressurs for lesing." + +msgid "Could not open resource for writing." +msgstr "Kunne ikke åpne ressurs for skriving." + +msgid "Could not open resource for reading and writing." +msgstr "Kunne ikke åpne ressurs for lesing og skriving." + +msgid "Could not close resource." +msgstr "Kunne ikke luke ressurs." + +msgid "Could not read from resource." +msgstr "Kunne ikke lese fra ressurs." + +msgid "Could not write to resource." +msgstr "Kunne ikke skrive til ressurs." + +msgid "Could not perform seek on resource." +msgstr "Kunne ikke søke i ressurs." + +msgid "Could not synchronize on resource." +msgstr "Kunne ikke synkronisere på ressurs." + +msgid "Could not get/set settings from/on resource." +msgstr "Kunne ikke hente/sette innstillinger fra/på ressurs." + +msgid "No space left on the resource." +msgstr "Ingen plass igjen på ressursen." + +msgid "Not authorized to access resource." +msgstr "Ikke autorisert til å få tilgang til ressursen." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer har møtt en generelt strømmefeil." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Element implementerer ikke håndtering av denne strømmen. Send inn en " +"feilrapport." + +msgid "Could not determine type of stream." +msgstr "Kunne ikke bestemme type strøm." + +msgid "The stream is of a different type than handled by this element." +msgstr "Strømmen er av en annen type enn det som håndteres av dette elementet." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Det er ingen kodek til stede som kan håndtere strømmens type." + +msgid "Could not decode stream." +msgstr "Kunne ikke dekode strøm." + +msgid "Could not encode stream." +msgstr "Kunne ikke kode strøm." + +msgid "Could not demultiplex stream." +msgstr "Kunne ikke bryte opp strøm." + +msgid "Could not multiplex stream." +msgstr "Kunne ikke sette sammen strøm." + +msgid "The stream is in the wrong format." +msgstr "Strømmen er i feil format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Strømmen er kryptert og dekryptering er ikke støttet." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Strømmen er kryptert og kan ikke dekrypteres fordi ingen passende nøkkel er " +"oppgitt." + +#, c-format +msgid "No error message for domain %s." +msgstr "Ingen feilmelding for domene %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Ingen standard feilmelding for domene %s og kode %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Valgt klokke kan ikke brukes i røret." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Kunne ikke skrive registerbuffer til %s: %s" + +msgid "title" +msgstr "tittel" + +msgid "commonly used title" +msgstr "ofte brukt tittel" + +msgid "title sortname" +msgstr "tittelsorteringsstreng" + +msgid "commonly used title for sorting purposes" +msgstr "ofte brukt tittel for sorteringsformål" + +msgid "artist" +msgstr "artist" + +msgid "person(s) responsible for the recording" +msgstr "person(er) som er ansvarlige for opptaket" + +msgid "artist sortname" +msgstr "sorteringsnavn for artist" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "person(er) som er ansvarlige for opptaket - til sortering" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album som inneholder disse dataene" + +msgid "album sortname" +msgstr "albumsorteringsstreng" + +msgid "album containing this data for sorting purposes" +msgstr "album som inneholder disse dataene for sorteringsformål" + +msgid "album artist" +msgstr "albumartist" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Artisten av hele albumet, som det burde bli vist" + +msgid "album artist sortname" +msgstr "album-, artistsorteringsstreng" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Artisten av hele albumet, som det burde bli sortert" + +msgid "date" +msgstr "dato" + +msgid "date the data was created (as a GDate structure)" +msgstr "dato for oppretting av dataene (som en GDate-struktur)" + +msgid "datetime" +msgstr "datotid" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"dato og klokkeslett dataene ble opprettet (som et GstDateTime-struktur)" + +msgid "genre" +msgstr "sjanger" + +msgid "genre this data belongs to" +msgstr "sjanger disse dataene tilhører" + +msgid "comment" +msgstr "kommentar" + +msgid "free text commenting the data" +msgstr "fritekstkommentar som beskriver dataene" + +msgid "extended comment" +msgstr "utvidet kommentar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "fritekstkommentar som beskriver dataene" + +msgid "track number" +msgstr "spornummer" + +msgid "track number inside a collection" +msgstr "spornummer i en samling" + +msgid "track count" +msgstr "antall spor" + +msgid "count of tracks inside collection this track belongs to" +msgstr "telling av sporene inne i samlingen dette sporet tilhører" + +msgid "disc number" +msgstr "platenummer" + +msgid "disc number inside a collection" +msgstr "disknummer inne i en samling" + +msgid "disc count" +msgstr "disktelling" + +msgid "count of discs inside collection this disc belongs to" +msgstr "telling av diskene i samlingen denne disken tilhører" + +msgid "location" +msgstr "plassering" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Opprinnelsen til mediet som en URI (plassering, hvor den originale fil eller " +"strøm ligger)" + +msgid "homepage" +msgstr "hjemmeside" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Hjemmesiden til dette mediet (dvs. hjemmesiden til artisten eller filmen)" + +msgid "description" +msgstr "beskrivelse" + +msgid "short text describing the content of the data" +msgstr "kort tekst som beskriver datainnholdet" + +msgid "version" +msgstr "versjon" + +msgid "version of this data" +msgstr "versjon for data" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - se http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisasjon" + +msgid "copyright" +msgstr "opphavsrett" + +msgid "copyright notice of the data" +msgstr "melding om opphavsrett for data" + +msgid "copyright uri" +msgstr "lenke til informasjon om opphavsrett" + +msgid "URI to the copyright notice of the data" +msgstr "Lenke til melding om opphavsrett for data" + +msgid "encoded by" +msgstr "kodet av" + +msgid "name of the encoding person or organization" +msgstr "Navnet på personen eller organisasjonen som kodet" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "kontaktinformasjon" + +msgid "license" +msgstr "lisens" + +msgid "license of data" +msgstr "lisens for data" + +msgid "license uri" +msgstr "lenke til lisens" + +msgid "URI to the license of the data" +msgstr "Lenke til lisensen for dataene" + +msgid "performer" +msgstr "utøver" + +msgid "person(s) performing" +msgstr "personer som spiller" + +msgid "composer" +msgstr "komponist" + +msgid "person(s) who composed the recording" +msgstr "person(er) som er komponerte opptaket" + +msgid "conductor" +msgstr "dirigent" + +msgid "conductor/performer refinement" +msgstr "dirigent/utøver-raffinering" + +msgid "duration" +msgstr "varighet" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "lengde i GStreamer tidsenheter (nanosekunder)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "kodek dataene er lagret i" + +msgid "video codec" +msgstr "videokodek" + +msgid "codec the video data is stored in" +msgstr "kodek videodataene er lagret i" + +msgid "audio codec" +msgstr "lydkodek" + +msgid "codec the audio data is stored in" +msgstr "kodek lyddataene er lagret i" + +msgid "subtitle codec" +msgstr "undertekstkodek" + +msgid "codec the subtitle data is stored in" +msgstr "kodek undertekstdataene er lagret i" + +msgid "container format" +msgstr "beholderformat" + +msgid "container format the data is stored in" +msgstr "beholderformatet dataene er lagret i" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "eksakt eller gjennomsnittlig bitrate i bits/s" + +msgid "nominal bitrate" +msgstr "nominell bitrate" + +msgid "nominal bitrate in bits/s" +msgstr "nominell bitrate i bits/s" + +msgid "minimum bitrate" +msgstr "minste bitrate" + +msgid "minimum bitrate in bits/s" +msgstr "minste bitrate i bits/s" + +msgid "maximum bitrate" +msgstr "maksimal bitrate" + +msgid "maximum bitrate in bits/s" +msgstr "maksimal bitrate i bits/s" + +msgid "encoder" +msgstr "koder" + +msgid "encoder used to encode this stream" +msgstr "omkoder som skal brukes til å kode denne strømmen" + +msgid "encoder version" +msgstr "versjon av koder" + +msgid "version of the encoder used to encode this stream" +msgstr "versjon av omkoderen som brukes til å kode denne strømmen" + +msgid "serial" +msgstr "serienummer" + +msgid "serial number of track" +msgstr "serienummer for spor" + +msgid "replaygain track gain" +msgstr "avspillingsforsterkning sporforsterkning" + +msgid "track gain in db" +msgstr "sporforsterkning i db" + +msgid "replaygain track peak" +msgstr "avspillingsforsterkning sportmaksimum" + +msgid "peak of the track" +msgstr "sporets maksimum" + +msgid "replaygain album gain" +msgstr "avspillingsforsterkning albumforsterkning" + +msgid "album gain in db" +msgstr "albumforsterkning i db" + +msgid "replaygain album peak" +msgstr "avspillingsforsterkning albummaksimum" + +msgid "peak of the album" +msgstr "albumets maksimum" + +msgid "replaygain reference level" +msgstr "avspillingsforsterkning referansenivå" + +msgid "reference level of track and album gain values" +msgstr "referansenivå for spor- og albumforsterkningsverdier" + +msgid "language code" +msgstr "språkkode" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "språkkoden for denne strømmen, i samsvar med ISO-639-1 eller ISO-639-2" + +msgid "language name" +msgstr "språknavn" + +msgid "freeform name of the language this stream is in" +msgstr "friformnavnet på språket denne strømmen er i" + +msgid "image" +msgstr "bilde" + +msgid "image related to this stream" +msgstr "bilde relatert til denne strømmen" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "forhåndsvis bilde" + +msgid "preview image related to this stream" +msgstr "forhåndsvis bilde relatert til denne strømmen" + +msgid "attachment" +msgstr "vedlegg" + +msgid "file attached to this stream" +msgstr "fil vedlagt denne strømmen" + +msgid "beats per minute" +msgstr "slag i minuttet" + +msgid "number of beats per minute in audio" +msgstr "antall slag i minuttet i lyd" + +msgid "keywords" +msgstr "nøkkelord" + +msgid "comma separated keywords describing the content" +msgstr "kommaseparerte nøkkelord som beskriver innholdet" + +msgid "geo location name" +msgstr "geografisk stedsnavn" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"lesbar beskrivende plassering av hvor mediene har blitt innspilt eller " +"produsert" + +msgid "geo location latitude" +msgstr "geografisk breddegrad" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"geografisk breddegradplassering hvor mediene har vært innspilt eller " +"produsert i grader i henhold til WGS84 (null ved ekvator, negative verdier " +"for sydlige breddegrader)" + +msgid "geo location longitude" +msgstr "geografisk lengdegrad" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"geografisk lengdegradplassering hvor mediene har vært innspilt eller " +"produsert i grader i henhold til WGS84 (null ved nullmeridianen i " +"Greenwich / UK, negative verdier for vestlige lengdegrader)" + +msgid "geo location elevation" +msgstr "geografisk høyde" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"geografisk høyde i meter der mediene er innspilt eller produsert, i henhold " +"til WGS84 (null er gjennomsnittlig havnivå)" + +msgid "geo location country" +msgstr "geografisk nasjon" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "land (engelsk navn) der mediene er innspilt eller produsert" + +msgid "geo location city" +msgstr "geografisk by" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "by (engelsk navn) der mediene er innspilt eller produsert" + +msgid "geo location sublocation" +msgstr "geografisk underlokasjon" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"et sted i en by hvor mediene har blitt produsert eller laget (f.eks " +"nabolaget)" + +msgid "geo location horizontal error" +msgstr "geografisk plassering horisontalfeil" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "forventet feil i den horisontale posisjoneringsmål (i meter)" + +msgid "geo location movement speed" +msgstr "geografisk bevegelseshastighet" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "bevegelseshastigheten til opptaksenheten mens du utfører opptak i m/s" + +msgid "geo location movement direction" +msgstr "geografisk bevegelsesretning" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indikerer bevegelsesretningen av innretningen som utfører opptak av et " +"medium. Det er representert som grader i flyttall-representasjon, 0 betyr " +"geografisk nord og øker med klokken" + +msgid "geo location capture direction" +msgstr "geografisk opptaksretning" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indikerer i hvilken retning enheten peker når du tar opp et medie. Det er " +"representert som grader i flyttall-representasjon, 0 betyr geografisk nord " +"og øker med klokken" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "navn på program" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Navnet på serien tv- eller podcasten mediet stammer fra" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "serie-sorteringsnavn" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Navnet på serien tv- eller podcasten mediet stammer fra, for sorteringsformål" + +msgid "episode number" +msgstr "episodenummer" + +msgid "The episode number in the season the media is part of" +msgstr "Episodenummeret i sesongen mediet er en del av" + +msgid "season number" +msgstr "sesongnummer" + +msgid "The season number of the show the media is part of" +msgstr "Sesongnummeret i serien mediet er en del av" + +msgid "lyrics" +msgstr "tekster" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Teksten til mediene, vanligvis brukt for sanger" + +msgid "composer sortname" +msgstr "komponist-sorteringsnavn" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "person(er) som komponert opptaket, for sorteringsformål" + +msgid "grouping" +msgstr "gruppering" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupperelaterte media som går over flere spor, som de forskjellige delene av " +"en konsert. Det er et høyere nivå enn et spor, men lavere enn et album" + +msgid "user rating" +msgstr "brukerrangering" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Rating tilskrevet av en bruker. Jo høyere rang, jo mer liker brukeren dette " +"mediet" + +msgid "device manufacturer" +msgstr "enhetsprodusent" + +msgid "Manufacturer of the device used to create this media" +msgstr "Produsenten av enheten som brukes til å lage dette mediet" + +msgid "device model" +msgstr "enhetsmodell" + +msgid "Model of the device used to create this media" +msgstr "Modell av enheten som brukes til å lage dette mediet" + +msgid "application name" +msgstr "Programnavn" + +msgid "Application used to create the media" +msgstr "Program brukt til å lage mediet" + +msgid "application data" +msgstr "Programdata" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Vilkårlige programdata som skal serialiseres i mediet" + +msgid "image orientation" +msgstr "bildeorientering" + +msgid "How the image should be rotated or flipped before display" +msgstr "Hvordan bildet skal roteres eller snus før visning" + +msgid "publisher" +msgstr "utgiver" + +msgid "Name of the label or publisher" +msgstr "Navnet på forlaget eller utgiveren" + +msgid "interpreted-by" +msgstr "tolket av" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Informasjon om menneskene bak en remiks og lignende tolkninger" + +msgid "midi-base-note" +msgstr "midi-base-node" + +msgid "Midi note number of the audio track." +msgstr "Midi-nodenummer på lydsporet." + +msgid "private-data" +msgstr "private-data" + +msgid "Private data" +msgstr "Private data" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Ingen URI-behandler for %s protokollen funnet" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI-ordningen «%s» støttes ikke" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FEIL: fra element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Tilleggsinformasjon for feilsøking:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "link har ingen slik kilde [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "link har ingen slik sink [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "ingen egenskap «%s» i element «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "kunne ikke sette egenskapen «%s» i elementet «%s» til «%s»" + +msgid "Delayed linking failed." +msgstr "Forsinket linking feilet." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "kunne ikke lenke %s til %s, %s kan ikke håndtere store bokstaver %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"kunne ikke linke %s til %s, ingen av elementene kan håndtere store bokstaver " +"%s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "kunne ikke lenke %s til %s med store bokstaver %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "kunne ikke lenke %s til %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "ingen element «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "uventet referanse «%s» – ignorerer" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "uventet pad-referanse «%s» – ignorerer" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kunne ikke analysere capskunne ikke analysere caps «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "ingen sink-element for URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "ingen kilde-element for URI «%s»" + +msgid "syntax error" +msgstr "Syntaksfeil" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "spesifisert tomt lager «%s», ikke tillat" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "intet lager «%s», pakker ut elementer" + +msgid "empty pipeline not allowed" +msgstr "Tom rørledning ikke tillatt" + +msgid "A lot of buffers are being dropped." +msgstr "Mange av buffere blir droppet." + +msgid "Internal data flow problem." +msgstr "Intern dataflytproblem." + +msgid "Internal data flow error." +msgstr "Intern feil med dataflyt." + +msgid "Internal clock error." +msgstr "Feil i intern klokke" + +msgid "Failed to map buffer." +msgstr "Klarte ikke å kartlegge buffer." + +msgid "Filter caps" +msgstr "Filtrer caps" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Begrense mulige tillatt evner (NULL betyr ALT). Innstilling av denne " +"egenskapen tar en referanse til det medfølgende GstCaps-objektet." + +msgid "Caps Change Mode" +msgstr "Caps-endringstilstand" + +msgid "Filter caps change behaviour" +msgstr "Filter caps-endringsatferd" + +msgid "No Temp directory specified." +msgstr "Inten temp-mappe spesifisert." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Kunne ikke lage midlertidig fil «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Kunne ikke åpne fil «%s» for lesing." + +msgid "Error while writing to download file." +msgstr "Feil ved skriving til nedastingsfilen." + +msgid "No file name specified for writing." +msgstr "Ingen filnavn oppgitt for skriving." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Kunne ikke åpne fil «%s» for skriving." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Feil ved lukking av fil «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Feil ved søking i fil «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Feil ved skriving til fil «%s»." + +msgid "No file name specified for reading." +msgstr "Ingen filnavn oppgitt for lesing." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Kunne ikke hente informasjon om «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» er en katalog." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Fil «%s» er en plugg." + +msgid "Failed after iterations as requested." +msgstr "Mislyktes etter iterasjoner som forespurt." + +msgid "caps" +msgstr "caps" + +msgid "detected capabilities in stream" +msgstr "oppdaget evner i strøm" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "tving caps" + +msgid "force caps without doing a typefind" +msgstr "tving caps uten å foreta typefind" + +msgid "Stream doesn't contain enough data." +msgstr "Strømmen inneholder ikke nok data." + +msgid "Stream contains no data." +msgstr "Strømmen inneholder ikke data." + +msgid "Implemented Interfaces:\n" +msgstr "Implementerte grensesnitt:\n" + +msgid "readable" +msgstr "lesbar" + +msgid "writable" +msgstr "skrivbar" + +msgid "deprecated" +msgstr "foreldet" + +msgid "controllable" +msgstr "kontrollerbar" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "kan bare endres i NULL-, KLAR-, PAUSE- eller SPILLER-tilstand" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "kan bare endres i NULL-, KLAR- eller PAUSE-tilstand" + +msgid "changeable only in NULL or READY state" +msgstr "kan bare endres i NULL-, eller KLAR-tilstand" + +msgid "Blacklisted files:" +msgstr "Svartelistede filer:" + +msgid "Total count: " +msgstr "Totalt antall: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d sortelistet fil" +msgstr[1] "%d sortelistede filer" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d programtillegg" +msgstr[1] "%d programtillegg" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d sortelisteoppføring" +msgstr[1] "%d sortelisteoppføringer" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funksjon" +msgstr[1] "%d funksjoner" + +msgid "Print all elements" +msgstr "Skriv ut alle elementene" + +msgid "Print list of blacklisted files" +msgstr "Skriv ut liste med sortelistede filer" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Skriv ut en maskin-analyseres liste over funksjoner det angitte " +"programtillegget eller alle programtillegg gir.\n" +" Nyttig i forbindelse med eksterne " +"automatiske installasjonsmekanismer for programtillegg" + +msgid "List the plugin contents" +msgstr "List innhold i programtillegg" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"En skråstrekseparert («/») liste av typer av elementer (også kjent som " +"klasse) til listen. (Uordnet)" + +msgid "Check if the specified element or plugin exists" +msgstr "Sjekk om det spesifiserte elementet eller programtillegg eksisterer" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Ved sjekking om et element eller programtillegg eksisterer, sjekk også at " +"dens versjon er minst den angitte versjonen" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Skrive ut støttede URI-schemes, med elementer som implementerer dem" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Kunne ikke laste programtilleggsfil: «%s»\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Ingen slik element eller programtillegg '%s'\n" + +msgid "Index statistics" +msgstr "Indeksstatistikk" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Fikk melding #%u fra element «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Fikk melding #%u fra pad «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Fikk melding #%u fra objekt «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Fikk melding #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Fikk EOS fra element «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "FANT TAG : funnet av element «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "FANT TAG : funnet av pad «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "FANT TAG : funnet av objekt «%s».\n" + +msgid "FOUND TAG\n" +msgstr "FANT TAGG\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "FANT TOC : funnet av element «%s».\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "FANT TOC : funnet av objekt «%s».\n" + +msgid "FOUND TOC\n" +msgstr "FANT TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ADVARSEL: fra element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Forbereder, venter på at buffering fullfører ...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Forbereder, venter på at fremdriften fullfører ...\n" + +msgid "buffering..." +msgstr "bufrer ..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Ferdig med bufring, setter rørledning til SPILLER\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Bufrer, setter rørledning til PAUSE ...\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribuer ventetid ...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Setter status til %s som foresåurt av %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Avbrudd: Stopper rørledning ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Fremdrift: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Mangler element: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Fikk sammenheng fra element «%s»: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "skriv ut tagger (også kjent som metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "Skriv ut TOC (kapitler og utgaver)" + +msgid "Output status information and property notifications" +msgstr "Skriv ut statusinformasjon og egenskapsvarslinger" + +msgid "Do not print any progress information" +msgstr "Ikke skriv ut fremdriftsinformasjon" + +msgid "Output messages" +msgstr "Utdatameldinger" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Ikke gi ut statusinformasjon for den angitte egenskapen hvis verbose-utgang " +"er aktivert (kan brukes flere ganger)" + +msgid "PROPERTY-NAME" +msgstr "EGENSKAPSNAVN" + +msgid "Do not install a fault handler" +msgstr "ikke installer feilhåndterer" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Tvinge EOS på kilder før rørledningen stenges" + +msgid "Gather and print index statistics" +msgstr "Samle og skriv ut indeksstatistikk" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FEIL: rørledningen kunne ikke bygges: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FEIL: rørledningen kunne ikke bygges.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ADVARSEL: feilaktig rørledning: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FEIL: elementet «rørledning» ble ike funnet.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Setter rørledning til PAUSE\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FEIL: rørledningen vil ikke pause\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Rørledningen er live og trenger ikke forberedelse\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Rørledningen forbereder ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FEIL: rørledningen vil ikke forberede.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Rørledning er forberedt ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Setter rørledning til SPILLER ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FEIL: rørledningen vil ikke spille.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS ved avslutning aktivert - Tvinger EOS på rørledningen\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS ved avslutning aktivert - venter på AOS etter feil\n" + +msgid "Waiting for EOS...\n" +msgstr "Venter på EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS mottatt - stopper rørledning...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Avbryt mens du venter på EOS - stopper rørledning...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "En feil oppsto ved venting på EOS\n" + +msgid "Execution ended after %" +msgstr "Kjøring endte etter %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Setter rørledning til KLAR ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Setter rørledning til NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Frigjør rør ...\n" + +#~ msgid "bin" +#~ msgstr "bin" + +#~ msgid "Internal data stream error." +#~ msgstr "Intern datastrøm-feil." + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYPE1,TYPE2,..." + +#~ msgid "maximum" +#~ msgstr "maksimum" + +#~ msgid "FILE" +#~ msgstr "FIL" diff --git a/po/nl.gmo b/po/nl.gmo new file mode 100644 index 0000000..4bc6944 Binary files /dev/null and b/po/nl.gmo differ diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..e9af328 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,1402 @@ +# translation of gstreamer.po to Dutch +# Dutch translation of gstreamer +# Copyright (C) 2003-2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# +# Thomas Vander Stichele , 2004. +# Taco Witte , 2006. +# Freek de Kruijf , 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-10-24 22:53+0100\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-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 2.0\n" + +msgid "Print the GStreamer version" +msgstr "Toon de GStreamer versie" + +msgid "Make all warnings fatal" +msgstr "Alle waarschuwingen fataal maken" + +msgid "Print available debug categories and exit" +msgstr "Beschikbare debug-categorieën weergeven en afsluiten" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Standaard debug-niveau van 1 (alleen fouten) tot 9 (alles) of 0 voor geen " +"uitvoer" + +msgid "LEVEL" +msgstr "NIVEAU" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Komma-gescheiden lijst van categorie_naam:niveau paren om specifieke " +"niveau's in te stellen voor de individuele categorieën. Voorbeeld: " +"GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LIJST" + +msgid "Disable colored debugging output" +msgstr "Kleuren uit zetten in debug-uitvoer" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Wijzig de modus van kleuring van de debug-log. Mogelijke modi: off, on, " +"disable, auto, unix" + +msgid "Disable debugging" +msgstr "Debugging uit zetten" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Uitgebreide diagnostiek voor het laden van plugins aan zetten" + +msgid "Colon-separated paths containing plugins" +msgstr "Dubbele punt-gescheiden lijst met paden met plugins" + +msgid "PATHS" +msgstr "PADEN" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Komma-gescheiden lijst van plugins om voor te laden naast de lijst " +"opgeslagen in omgevingsvariable GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Het opvangen van segmentatiefouten uit zetten tijdens laden van plugins" + +msgid "Disable updating the registry" +msgstr "Zet het het bijwerken van de registry uit" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Zet het starten van een hulpprogramma uit tijdens het doorlopen van de " +"registry" + +msgid "GStreamer Options" +msgstr "GStreamer-opties" + +msgid "Show GStreamer Options" +msgstr "Toon de GStreamer-opties" + +msgid "Unknown option" +msgstr "Onbekende optie" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer kreeg een algemene fout van de kernbibliotheek." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer ontwikkelaars waren te lui om een foutcode toe te wijzen aan deze " +"fout." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Interne GStreamer-fout: code niet geïmplementeerd." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer-fout: statuswijziging is mislukt en een element heeft geen goede " +"foutmelding afgegeven met een reden voor het mislukken." + +msgid "Internal GStreamer error: pad problem." +msgstr "Interne GStreamer-fout: padprobleem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Interne GStreamer-fout: threadprobleem." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer-fout: onderhandelingsprobleem." + +msgid "Internal GStreamer error: event problem." +msgstr "Interne GStreamer-fout: gebeurtenisprobleem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Interne GStreamer-fout: zoekprobleem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Interne GStreamer-fout: mogelijkheden-probleem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Interne GStreamer-fout: tagprobleem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Er ontbreekt een plugin in uw GStreamer installatie." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer-fout: klokprobleem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Deze apllicatie probeert een functie van GStreamer te gebruiken die is " +"uitgezet." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer kreeg een algemene fout van een ondersteunende bibliotheek." + +msgid "Could not initialize supporting library." +msgstr "Kan ondersteunende bibliotheek niet initialiseren." + +msgid "Could not close supporting library." +msgstr "Kan ondersteunende bibliotheek niet sluiten." + +msgid "Could not configure supporting library." +msgstr "Kan ondersteunende bibliotheek niet configureren." + +msgid "Encoding error." +msgstr "Coderingsfout." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer kwam een algemene fout tegen met systeembronnen." + +msgid "Resource not found." +msgstr "Bron niet gevonden." + +msgid "Resource busy or not available." +msgstr "Bron bezet of niet beschikbaar." + +msgid "Could not open resource for reading." +msgstr "Kan bron niet openen om te lezen." + +msgid "Could not open resource for writing." +msgstr "Kan bron niet openen om te schrijven." + +msgid "Could not open resource for reading and writing." +msgstr "Kan bron niet openen om te lezen en schrijven." + +msgid "Could not close resource." +msgstr "Kan bron niet sluiten." + +msgid "Could not read from resource." +msgstr "Kan niet lezen van bron." + +msgid "Could not write to resource." +msgstr "Kan niet schrijven naar bron." + +msgid "Could not perform seek on resource." +msgstr "Kan de bron niet spoelen." + +msgid "Could not synchronize on resource." +msgstr "Kan niet synchroniseren op de bron." + +msgid "Could not get/set settings from/on resource." +msgstr "Kan geen instellingen lezen/schrijven van/naar bron." + +msgid "No space left on the resource." +msgstr "Er is geen ruimte meer in de bron." + +msgid "Not authorized to access resource." +msgstr "Niet geautoriseerd voor toegang tot hulpbron." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer kwam een algemene stroomfout tegen." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Element ondersteunt deze stroom niet. Stuur een foutrapport." + +msgid "Could not determine type of stream." +msgstr "Kan de soort van de stroom niet herkennen." + +msgid "The stream is of a different type than handled by this element." +msgstr "De stroom is van een andere soort dan dit element kan verwerken." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Er is geen codec aanwezig die deze soort stroom kan verwerken." + +msgid "Could not decode stream." +msgstr "Kan de stroom niet decoderen." + +msgid "Could not encode stream." +msgstr "Kan de stroom niet coderen." + +msgid "Could not demultiplex stream." +msgstr "Kan de stroom niet demultiplexen." + +msgid "Could not multiplex stream." +msgstr "Kan de stroom niet multiplexen." + +msgid "The stream is in the wrong format." +msgstr "De stroom is van het verkeerde formaat." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "De stroom is vercijferd en ontcijfering wordt niet ondersteund." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"De stroom is vercijferd en kan niet worden ontcijferd omdat er geen " +"geschikte sleutel aangeleverd is." + +#, c-format +msgid "No error message for domain %s." +msgstr "Geen foutboodschap voor domein %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Geen standaard foutboodschap voor domein %s en code %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Geselecteerde klok kan niet gebruikt worden in de pijplijn." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Fout bij schrijven van registry-cache naar %s: %s" + +msgid "title" +msgstr "titel" + +msgid "commonly used title" +msgstr "vaak gebruikte titel" + +msgid "title sortname" +msgstr "titel voor het sorteren" + +msgid "commonly used title for sorting purposes" +msgstr "vaak gebruikte titel voor het sorteren" + +msgid "artist" +msgstr "artiest" + +msgid "person(s) responsible for the recording" +msgstr "perso(o)n(en) die de opname gemaakt hebben" + +msgid "artist sortname" +msgstr "naam artiest voor sorteren" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "perso(o)n(en) die de opname gemaakt hebben gebruikt voor sorteren" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album waarop dit stuk staat" + +msgid "album sortname" +msgstr "naam album voor sorteren" + +msgid "album containing this data for sorting purposes" +msgstr "album waarop dit stuk staat voor sorteren" + +msgid "album artist" +msgstr "albumartiest" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "De artiest van het gehele album, zoals dat zou moeten worden getoond" + +msgid "album artist sortname" +msgstr "naam artiest voor sorteren" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" +"De artiest van het gehele album, zoals dat zou moeten worden gebruikt voor " +"sorteren" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "datum waarop het stuk gemaakt is (als GDate-structuur)" + +msgid "datetime" +msgstr "datum-tijd" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"datum en tijd waarop de gegevens zijn gemaakt (als een GstDateTime-structuur)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre van het stuk" + +msgid "comment" +msgstr "commentaar" + +msgid "free text commenting the data" +msgstr "vrij te kiezen commentaartekst die het stuk beschrijft" + +msgid "extended comment" +msgstr "uitgebreid commentaar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"vrij te kiezen commentaartekst bij gegevens in de vorm key=waarde of " +"key[en]=commentaar " + +msgid "track number" +msgstr "nummer" + +msgid "track number inside a collection" +msgstr "nummer van het stuk in een verzameling" + +msgid "track count" +msgstr "aantal nummers" + +msgid "count of tracks inside collection this track belongs to" +msgstr "aantal nummers in de verzameling waarbij dit stuk hoort" + +msgid "disc number" +msgstr "schijfnummer" + +msgid "disc number inside a collection" +msgstr "nummer van de schijf in een verzameling" + +msgid "disc count" +msgstr "aantal schijven" + +msgid "count of discs inside collection this disc belongs to" +msgstr "aantal schijven in de verzameling waartoe deze schijf behoort" + +msgid "location" +msgstr "lokatie" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"oorsprong van het medium als een URI (locatie, waar de oorsprong van het " +"bestand of stroom wordt gehost)" + +msgid "homepage" +msgstr "webpagina" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Webpagina voor dit medium (bijv. artiest of film-webpagina)" + +msgid "description" +msgstr "omschrijving" + +msgid "short text describing the content of the data" +msgstr "korte tekst die de inhoud van het stuk omschrijft" + +msgid "version" +msgstr "versie" + +msgid "version of this data" +msgstr "versie van dit stuk" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "Internationale Standaard Opname Code - zie http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisatie" + +msgid "copyright" +msgstr "auteursrecht" + +msgid "copyright notice of the data" +msgstr "auteursrechtvermelding van het stuk" + +msgid "copyright uri" +msgstr "auteursrecht-uri" + +msgid "URI to the copyright notice of the data" +msgstr "URI naar de auteursrechtvermelding van de gegevens" + +msgid "encoded by" +msgstr "gecodeerd door" + +msgid "name of the encoding person or organization" +msgstr "naam van de coderende persoon of organisatie" + +msgid "contact" +msgstr "contact" + +msgid "contact information" +msgstr "contactinformatie" + +msgid "license" +msgstr "licentie" + +msgid "license of data" +msgstr "licentie van het stuk" + +msgid "license uri" +msgstr "licentie-uri" + +msgid "URI to the license of the data" +msgstr "URI naar de licentie van de gegevens" + +msgid "performer" +msgstr "uitvoerder" + +msgid "person(s) performing" +msgstr "perso(o)n(en) die het stuk uitvoeren" + +msgid "composer" +msgstr "componist" + +msgid "person(s) who composed the recording" +msgstr "perso(o)n(en) die de opname gecomponeerd hebben" + +msgid "conductor" +msgstr "dirigent" + +msgid "conductor/performer refinement" +msgstr "dirigent/verfijning van uitvoerder" + +msgid "duration" +msgstr "duur" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "lengte in GStreamer tijdseenheden (nanoseconden)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec waarin het stuk is opgeslagen" + +msgid "video codec" +msgstr "video codec" + +msgid "codec the video data is stored in" +msgstr "codec waarin het stuk is opgeslagen" + +msgid "audio codec" +msgstr "audio codec" + +msgid "codec the audio data is stored in" +msgstr "codec waarin de audiogegevens is opgeslagen" + +msgid "subtitle codec" +msgstr "codec voor ondertiteling" + +msgid "codec the subtitle data is stored in" +msgstr "codec waarin de ondertiteling is opgeslagen" + +msgid "container format" +msgstr "containerindeling" + +msgid "container format the data is stored in" +msgstr "containerindeling waarin de gegevens zijn opgeslagen" + +msgid "bitrate" +msgstr "bitsnelheid" + +msgid "exact or average bitrate in bits/s" +msgstr "exacte of gemiddelde bitsnelheid in bits/s" + +msgid "nominal bitrate" +msgstr "nominale bitsnelheid" + +msgid "nominal bitrate in bits/s" +msgstr "nominale bitsnelheid in bits per seconde" + +msgid "minimum bitrate" +msgstr "minimum bitsnelheid" + +msgid "minimum bitrate in bits/s" +msgstr "minimum bitsnelheid in bits per seconde" + +msgid "maximum bitrate" +msgstr "maximum bitsnelheid" + +msgid "maximum bitrate in bits/s" +msgstr "maximum bitsnelheid in bits per seconde" + +msgid "encoder" +msgstr "encoder" + +msgid "encoder used to encode this stream" +msgstr "encoder gebruikt om deze stroom te coderen" + +msgid "encoder version" +msgstr "encoder versie" + +msgid "version of the encoder used to encode this stream" +msgstr "versie van de encoder gebruikt om deze stroom te coderen" + +msgid "serial" +msgstr "volgnummer" + +msgid "serial number of track" +msgstr "volgnummer van dit nummer" + +msgid "replaygain track gain" +msgstr "aangepaste-geluidssterkte nummer" + +msgid "track gain in db" +msgstr "versterking van nummer in db" + +msgid "replaygain track peak" +msgstr "aangepaste-geluidssterkte piek van nummer" + +msgid "peak of the track" +msgstr "piek van het nummer" + +msgid "replaygain album gain" +msgstr "aangepaste-geluidssterkte album" + +msgid "album gain in db" +msgstr "versterking album in db" + +msgid "replaygain album peak" +msgstr "aangepaste-geluidssterkte piek van album" + +msgid "peak of the album" +msgstr "piek van het album" + +msgid "replaygain reference level" +msgstr "referentieniveau van aangepaste-geluidssterkte van nummer" + +msgid "reference level of track and album gain values" +msgstr "referentieniveau van de waarde van tarck- en albumgeluidsterkte" + +msgid "language code" +msgstr "taalcode" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "taalcode van deze stream, conform ISO-639-1 of ISO-639-2" + +msgid "language name" +msgstr "naam van taal" + +msgid "freeform name of the language this stream is in" +msgstr "naam van de taal in vrije vorm van deze stream" + +msgid "image" +msgstr "afbeelding" + +msgid "image related to this stream" +msgstr "afbeelding behorende bij deze stroom" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "voorbeeldafbeelding" + +msgid "preview image related to this stream" +msgstr "voorbeeldafbeelding behorende bij deze stroom" + +msgid "attachment" +msgstr "bijlage" + +msgid "file attached to this stream" +msgstr "bestand behorende bij deze stroom" + +msgid "beats per minute" +msgstr "slagen per minuut" + +msgid "number of beats per minute in audio" +msgstr "aantal slagen per minuut in audio" + +msgid "keywords" +msgstr "trefwoorden" + +msgid "comma separated keywords describing the content" +msgstr "komma gescheiden trefwoorden die de inhoud omschrijven" + +msgid "geo location name" +msgstr "naam geografische locatie" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"leesbare beschrijving van de locatie waar het medium is opgenomen of " +"geproduceerd" + +msgid "geo location latitude" +msgstr "lengtegraad van de geografische locatie" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"lengtegraad van de geografische locatie van waar het medium is opgenomen of " +"geproduceerd in graden volgens WGS84 (nul op de evenaar, negatieve waarden " +"voor zuidelijke lengtegraden)" + +msgid "geo location longitude" +msgstr "breedtegraad van de geografische locatie" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"breedtegraad van de geografische locatie van waar het medium is opgenomen of " +"geproduceerd in graden volgens WGS84 (nul op primaire meridiaan, negatieve " +"waarden voor westelijke breedtegraden)" + +msgid "geo location elevation" +msgstr "hoogte van de geografische locatie" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"hoogte van de geografische locatie van waar het medium is opgenomen of " +"geproduceerd in meters volgens WGS84 (nul op gemiddeld zeeniveau)" + +msgid "geo location country" +msgstr "geografische locatie van het land" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "land (Engelse naam) waar het medium is opgenomen of geproduceerd" + +msgid "geo location city" +msgstr "geografische locatie van de stad" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "stad (Engelse naam) waar het medium is opgenomen of geproduceerd" + +msgid "geo location sublocation" +msgstr "geografische locatie van de sublocatie" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"een locatie in een stad waar het medium is geproduceerd of gemaakt (bijv. de " +"buurt)" + +msgid "geo location horizontal error" +msgstr "fout in horizontale geo-locatie" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "verwachte fout van de horizontale positioneringsafmetingen (in meters)" + +msgid "geo location movement speed" +msgstr "verplaatsingssnelheid op de geografische locatie" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "verplaatsingssnelheid van het opnameapparaat tijdens de opname in m/s" + +msgid "geo location movement direction" +msgstr "bewegingsrichting op de geografische locatie" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"geeft de bewegingsrichting aan van het apparaat dat de opname op het medium " +"doet. Het wordt weergegeven in graden in drijvendekommavorm, 0 betekent het " +"geografische noorden en neem rechtsom toe" + +msgid "geo location capture direction" +msgstr "opnamerichting op de geografische locatie" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"geeft de richting aan waarnaar het apparaat wijst dat de opname op het " +"medium doet. Het wordt weergegeven in graden in drijvendekommavorm, 0 " +"betekent het geografische noorden en neem rechtsom toe" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "naam tonen" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Mediumnaam van de show van de tv/podcast/serie" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "naam voor sorteren" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Mediumnaam van de show van de tv/podcast/serie, voor sorteren" + +msgid "episode number" +msgstr "episodenummer" + +msgid "The episode number in the season the media is part of" +msgstr "Het episodenummer in het seizoen waar het medium deel van is" + +msgid "season number" +msgstr "seizoennummer" + +msgid "The season number of the show the media is part of" +msgstr "Het nummer van het seizoen van de show waar het medium deel van is" + +msgid "lyrics" +msgstr "liedtekst" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "De liedtekst van het medium, gewoonlijk voor songs gebruikt" + +msgid "composer sortname" +msgstr "componist voor sorteren" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" +"perso(o)n(en) die de opname gecomponeerd he(eft)bben, gebruikt voor sorteren" + +msgid "grouping" +msgstr "groepering" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Groepen gerelateerde media die meerdere tracks omvatten, zoals de " +"verschillende delen van een concert. Het is een hoger niveau dan een track, " +"maat lager dan een album" + +msgid "user rating" +msgstr "waardering van gebruiker" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Waardering toegekend door een gebruiker. Hoe hoger de waardering, hoe meer " +"de gebruiker dit medium waardeert" + +msgid "device manufacturer" +msgstr "apparaatfabrikant" + +msgid "Manufacturer of the device used to create this media" +msgstr "" +"Fabrikant van het apparaat dat gebruikt wordt om dit medium aan te maken" + +msgid "device model" +msgstr "apparaatmodel" + +msgid "Model of the device used to create this media" +msgstr "Model van het apparaat dat gebruikt wordt om dit medium aan te maken" + +msgid "application name" +msgstr "toepassingsnaam" + +msgid "Application used to create the media" +msgstr "Gebruikte toepassing om het medium aan te maken" + +msgid "application data" +msgstr "toepassingsgegevens" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" +"Willekeurige toepassingsgegevens die geserialiseerd moeten worden op het " +"medium" + +msgid "image orientation" +msgstr "oriëntatie van de afbeelding" + +msgid "How the image should be rotated or flipped before display" +msgstr "Hoe de afbeelding geroteerd moet worden of gespiegeld bij tonen" + +msgid "publisher" +msgstr "uitgever" + +msgid "Name of the label or publisher" +msgstr "Naam of label van de uitgever" + +msgid "interpreted-by" +msgstr "geïnterpreteerd-door" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informatie over de mensen achter een remix en soortgelijke interpretaties" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Midi notitienummer van de geluidstrack" + +msgid "private-data" +msgstr "privégegevens" + +msgid "Private data" +msgstr "Privégegevens" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Geen behandelaar van de URI voor het protocol %s gevonden" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI-schema '%s' niet ondersteund" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FOUT: van element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Extra debug-informatie:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "link heeft geen bron [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "link heeft geen sink [bron=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "geen eigenschap \"%s\" in element \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "kon eigenschap \"%s\" in element \"%s\" niet op \"%s\" instellen" + +msgid "Delayed linking failed." +msgstr "Vertraagd koppelen is mislukt." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "kon %s niet koppelen naar %s, %s kan geen hoofdletters %s behandelen" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"kon %s niet koppelen naar %s, geen van beide kan hoofdletters %s behandelen" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "kon %s niet koppelen naar %s met hoofdletters %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "kon %s niet verbinden met %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "geen element \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "onverwachte referentie \"%s\" - wordt genegeerd" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "onverwachte pad-referentie \"%s\" - wordt genegeerd" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kon mogelijkheden \"%s\" niet verwerken" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "geen doelelement voor URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "geen bronelement voor URI \"%s\"" + +msgid "syntax error" +msgstr "syntaxisfout" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "lege ton \"%s\" opgegeven, niet toegelaten" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "geen bin \"%s\", elementen uitpakken" + +msgid "empty pipeline not allowed" +msgstr "lege pijplijn niet toegelaten" + +msgid "A lot of buffers are being dropped." +msgstr "Er worden veel buffers gedropt." + +msgid "Internal data flow problem." +msgstr "Intern probleem met gegevensdoorvoer." + +msgid "Internal data flow error." +msgstr "Interne fout met gegevensdoorvoer." + +msgid "Internal clock error." +msgstr "Interne fout met de klok." + +msgid "Failed to map buffer." +msgstr "Mappen van buffer is mislukt." + +msgid "Filter caps" +msgstr "Filteropzetstukken" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Beperk het aantal toegestane mogelijkheden (NUL betekent alle). Het " +"instellen van deze eigenschap vereist een referentie naar het gegeven " +"GstCaps-object." + +msgid "Caps Change Mode" +msgstr "Modus hoofd- kleine letters veranderen" + +msgid "Filter caps change behaviour" +msgstr "Gedrag van hoofd- kleine letters veranderen filteren" + +msgid "No Temp directory specified." +msgstr "Geen tijdelijke map opgegeven." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Kon geen tijdelijk bestand \"%s\" aanmaken." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Kan bestand \"%s\" niet openen om te lezen." + +msgid "Error while writing to download file." +msgstr "Fout bij het schrijven om bestand te downloaden." + +msgid "No file name specified for writing." +msgstr "Geen bestandsnaam gegeven om te schrijven." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Kan bestand \"%s\" niet openen om te schrijven." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fout bij het sluiten van bestand \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fout bij een seek in bestand \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fout bij het schrijven naar bestand \"%s\"." + +msgid "No file name specified for reading." +msgstr "Geen bestandsnaam gegeven om te lezen." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Kan geen info over \"%s\" krijgen." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" is een map." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Bestand \"%s\" is een socket." + +msgid "Failed after iterations as requested." +msgstr "Mislukt na iteraties zoals gevraagd." + +msgid "caps" +msgstr "mogelijkheden" + +msgid "detected capabilities in stream" +msgstr "gedetecteerde mogelijkheden in stroom" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "forceer mogelijkheden" + +msgid "force caps without doing a typefind" +msgstr "forceer mogelijkheden zonder een \"typefind\" te doen" + +msgid "Stream doesn't contain enough data." +msgstr "Stream bevat niet genoeg gegevens." + +msgid "Stream contains no data." +msgstr "Stroom zonder gegevens." + +msgid "Implemented Interfaces:\n" +msgstr "Geïmplementeerde interfaces:\n" + +msgid "readable" +msgstr "leesbaar" + +msgid "writable" +msgstr "schrijfbaar" + +msgid "deprecated" +msgstr "verouderd" + +msgid "controllable" +msgstr "controleerbaar" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "te veranderen in NUL, GEREED-, GEPAUZEERD- of SPEEL-status" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "te veranderen in NUL, GEREED- of GEPAUZEERD-status" + +msgid "changeable only in NULL or READY state" +msgstr "alleen te veranderen in NUL of GEREED-status" + +msgid "Blacklisted files:" +msgstr "Bestanden op de zwarte lijst:" + +msgid "Total count: " +msgstr "Totaal aantal: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d bestand op de zwarte lijst" +msgstr[1] "%d bestanden op de zwarte lijst" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plugin" +msgstr[1] "%d plugins" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d item op de zwarte lijst" +msgstr[1] "%d items op de zwarte lijst" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d mogelijkheid" +msgstr[1] "%d mogelijkheden" + +msgid "Print all elements" +msgstr "Alle elementen weergeven" + +msgid "Print list of blacklisted files" +msgstr "Druk de lijst met bestanden op de zwarte lijst af" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Toon een door een machine te ontleden lijst van mogelijkheden die de " +"gespecificeerde plugin of alle plugins aanbieden.\n" +" Bruikbaar in verband met externe " +"automatische plugin-installatiemechanismen" + +msgid "List the plugin contents" +msgstr "Toon de inhoud van de plugin" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Een met schuine strepen ('/') gescheiden lijst met typen elementen (ook " +"bekend als klasse) om een lijst te maken. (ongeordend)" + +msgid "Check if the specified element or plugin exists" +msgstr "Controleer of het gespecificeerde element of plug-in bestaat" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Bij het controleren of het gespecificeerde element of plug-in bestaat, " +"controleer ook dat zijn versie minstens de gespecificeerde versie is" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Toon de ondersteunde URI-schema's met de elementen die deze implementeren" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Kan plugin-bestand \"%s\" niet laden\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Geen element of plugin '%s'\n" + +msgid "Index statistics" +msgstr "Indexstatistieken" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Bericht #%u ontvangen uit element \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Bericht #%u ontvangen uit pad \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Bericht #%u ontvangen uit object \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Bericht #%u (%s) ontvangen: " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Einde-stroom ontvangen van element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "TAG GEVONDEN : gevonden door element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "TAG GEVONDEN : gevonden door pad \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "TAG GEVONDEN : gevonden door object \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "TAG GEVONDEN\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "INH GEVONDEN : gevonden door element \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "INH GEVONDEN : gevonden door object \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "INH GEVONDEN\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "WAARSCHUWING: van element %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Voorbereid, wacht op gereedkomen van de buffering...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Voorbereid, wacht op voortgang om te beëindigen...\n" + +msgid "buffering..." +msgstr "in buffer opslaan..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Buffering is gereed, pijplijn gezet op AFSPELEN ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Wordt gebufferd, pijplijn gezet op PAUZE ...\n" + +msgid "Redistribute latency...\n" +msgstr "Herverdeel de vertraging...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Stel de status in op %s zoals verzocht door %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrupt: Pijplijn ingesteld op gestopt ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Voortgang: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "ontbrekend element: \"%s\"\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Context verkregen van element '%s': %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Tags (ook bekend als metadata) weergeven" + +msgid "Output TOC (chapters and editions)" +msgstr "INH uitvoeren (hoofdstukken en uitgaven)" + +msgid "Output status information and property notifications" +msgstr "Statusinformatie en eigenschapswaarschuwingen weergeven" + +msgid "Do not print any progress information" +msgstr "Geen voortgangsinformatie afdrukken" + +msgid "Output messages" +msgstr "Uitvoer" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Statusinformatie voor de gespecificeerde eigenschap niet uitvoeren als " +"verbose-uitvoer is ingeschakeld (kan meerdere keren worden gebruikt)" + +msgid "PROPERTY-NAME" +msgstr "NAAM-EIGENSCHAP" + +msgid "Do not install a fault handler" +msgstr "Geen foutafhandelaar installeren" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forceer een EOS op de bron bij het afsluiten van de pijplijn" + +msgid "Gather and print index statistics" +msgstr "Verzamel en print indexstatistieken" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FOUT: pijplijn kon niet gemaakt worden: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FOUT: pijplijn kon niet gemaakt worden.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "WAARSCHUWING: foutieve pijplijn: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FOUT: het 'pijplijn' element werd niet gevonden.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Pijplijn gezet op gepauzeerd ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FOUT: pijplijn wil niet pauzeren.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Pijplijn klaar en heeft PREROLL niet nodig...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Pijplijn is bezig met PREROLL ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FOUT: pijplijn wil niet PREROLL uitvoeren.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Pijplijn klaar met PREROLL ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Pijplijn gezet op afspelen ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FOUT: pijplijn wil niet afspelen.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS bij afsluiten ingeschakeld -- Forceer een EOS op de pijplijn\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS bij afsluiten ingeschakeld -- wacht op EOS na fout\n" + +msgid "Waiting for EOS...\n" +msgstr "Wacht op EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS ontvangen - pijplijn wordt gestopt...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Interrupt bij wachten op EOS - pijplijn wordt gestopt...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Er trad een fout op bij het wachten op EOS\n" + +msgid "Execution ended after %" +msgstr "Uitvoering beëindigd na %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Pijplijn gezet op gereed ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Pijplijn gezet op NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Pijplijn wordt vrijgemaakt ...\n" + +#~ msgid "bin" +#~ msgstr "bin" + +#~ msgid "Internal data stream error." +#~ msgstr "Interne fout in gegevensstroom." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Statusinformatie van soort SOORT niet weergeven" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "SOORT1,SOORT2,..." + +#~ msgid "link without source element" +#~ msgstr "verbinding zonder bronelement" + +#~ msgid "link without sink element" +#~ msgstr "verbinding zonder doelelement" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "geen element om URI \"%s\" mee te verbinden" + +#~ msgid "maximum" +#~ msgstr "maximum" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Gebruik: gst-xmllaunch [ element.eigenschap=waarde ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "FOUT: verwerken van xml-bestand '%s' mislukt.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "FOUT: geen bovenste pijplijn-element gevonden in file '%s'.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "WAARSCHUWING: slechts één element op het hoogste niveau ondersteund op " +#~ "dit moment.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "FOUT: kon argument %d op opdrachtregel niet verwerken: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "WAARSCHUWING: element met naam '%s' niet gevonden.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "XML-representatie van pijplijn in BESTAND opslaan en afsluiten" + +#~ msgid "FILE" +#~ msgstr "BESTAND" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Geen signaalafhandelaars installeren voor SIGUSR1 en SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Toewijzingsspoor weergeven (indien aangezet tijdens compileren)" diff --git a/po/pl.gmo b/po/pl.gmo new file mode 100644 index 0000000..aadf448 Binary files /dev/null and b/po/pl.gmo differ diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..4267ec7 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,1341 @@ +# Polish translation for gstreamer. +# This file is distributed under the same license as the gstreamer package. +# Jakub Bogusz , 2007-2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-08 18:54+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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +msgid "Print the GStreamer version" +msgstr "Wypisanie wersji GStreamera" + +msgid "Make all warnings fatal" +msgstr "Uczynienie wszystkich ostrzeżeń krytycznymi" + +msgid "Print available debug categories and exit" +msgstr "Wypisanie dostępnych kategorii diagnostyki i zakończenie" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Domyślny poziom diagnostyki od 1 (tylko błędy) do 9 (wszystko) lub 0 dla " +"braku wyjścia" + +msgid "LEVEL" +msgstr "POZIOM" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Rozdzielona przecinkami lista par nazwa_kategorii:poziom dla uzyskania " +"określonych poziomów dla poszczególnych kategorii. Przykład: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Wyłączenie kolorowanego wyjścia diagnostycznego" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Zmiana trybu kolorowania logu diagnostycznego. Możliwe tryby: off, on, " +"disable, auto, unix" + +msgid "Disable debugging" +msgstr "Wyłączenie diagnostyki" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Włączenie szczegółowej diagnostyki wczytywania wtyczek" + +msgid "Colon-separated paths containing plugins" +msgstr "Rozdzielone przecinkami ścieżki zawierające wtyczki" + +msgid "PATHS" +msgstr "ŚCIEŻKI" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Rozdzielona przecinkami lista wtyczek do wczesnego wczytania obok listy " +"zapisanej w zmiennej środowiskowej GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "WTYCZKI" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Wyłączenie przechwytywania błędów ochrony pamięci przy wczytywaniu wtyczek" + +msgid "Disable updating the registry" +msgstr "Wyłączenie uaktualniania rejestru" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Wyłączenie uruchamiania procesu pomocniczego przy przeszukiwaniu rejestru" + +msgid "GStreamer Options" +msgstr "Opcje GStreamera" + +msgid "Show GStreamer Options" +msgstr "Pokazanie opcji GStreamera" + +msgid "Unknown option" +msgstr "Nieznana opcja" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer napotkał ogólny błąd głównej biblioteki." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Programiści GStreamera byli zbyt leniwi, aby przypisać temu błędowi kod." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Błąd wewnętrzny GStreamera: kod nie zaimplementowany." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Błąd GStreamera: zmiana stanu nie powiodła się, a któryś element nie " +"przesłał właściwego komunikatu błędu." + +msgid "Internal GStreamer error: pad problem." +msgstr "Błąd wewnętrzny GStreamera: problem z wyrównaniem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Błąd wewnętrzny GStreamera: problem z wątkami." + +msgid "GStreamer error: negotiation problem." +msgstr "Błąd GStreamera: problem z negocjacją." + +msgid "Internal GStreamer error: event problem." +msgstr "Błąd wewnętrzny GStreamera: problem ze zdarzeniami." + +msgid "Internal GStreamer error: seek problem." +msgstr "Błąd wewnętrzny GStreamera: problem z przemieszczaniem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Błąd wewnętrzny GStreamera: problem z możliwościami." + +msgid "Internal GStreamer error: tag problem." +msgstr "Błąd wewnętrzny GStreamera: problem ze znacznikami." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "W tej instalacji GStreamera brakuje wtyczki." + +msgid "GStreamer error: clock problem." +msgstr "Błąd GStreamera: problem z zegarem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Ta aplikacja próbuje użyć funkcjonalności GStreamera, która została " +"wyłączona." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer napotkał ogólny błąd biblioteki wspierającej." + +msgid "Could not initialize supporting library." +msgstr "Nie udało się zainicjować biblioteki wspierającej." + +msgid "Could not close supporting library." +msgstr "Nie udało się zamknąć biblioteki wspierającej." + +msgid "Could not configure supporting library." +msgstr "Nie udało się skonfigurować biblioteki wspierającej." + +msgid "Encoding error." +msgstr "Błąd kodowania." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer napotkał ogólny błąd zasobów." + +msgid "Resource not found." +msgstr "Nie znaleziono zasobu." + +msgid "Resource busy or not available." +msgstr "Zasób zajęty lub niedostępny." + +msgid "Could not open resource for reading." +msgstr "Nie udało się otworzyć zasobu do odczytu." + +msgid "Could not open resource for writing." +msgstr "Nie udało się otworzyć zasobu do zapisu." + +msgid "Could not open resource for reading and writing." +msgstr "Nie udało się otworzyć zasobu do odczytu i zapisu." + +msgid "Could not close resource." +msgstr "Nie udało się zamknąć zasobu." + +msgid "Could not read from resource." +msgstr "Nie udał się odczyt z zasobu." + +msgid "Could not write to resource." +msgstr "Nie udał się zapis do zasobu." + +msgid "Could not perform seek on resource." +msgstr "Nie udało się przemieszczenie w zasobie." + +msgid "Could not synchronize on resource." +msgstr "Nie udało się zsynchronizować zasobu." + +msgid "Could not get/set settings from/on resource." +msgstr "Nie udało się pobrać/ustawić ustawień zasobu." + +msgid "No space left on the resource." +msgstr "Brak wolnego miejsca w zasobie." + +msgid "Not authorized to access resource." +msgstr "Brak autoryzacji dostępu do zasobu." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer napotkał ogólny błąd strumieni." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Element nie obsługuje tego strumienia. Proszę zgłosić błąd." + +msgid "Could not determine type of stream." +msgstr "Nie udało się określić rodzaju strumienia." + +msgid "The stream is of a different type than handled by this element." +msgstr "Strumień jest innego rodzaju niż obsługiwane przez ten element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Brak kodeka potrafiącego obsłużyć ten rodzaj strumienia." + +msgid "Could not decode stream." +msgstr "Nie udało się zdekodować strumienia." + +msgid "Could not encode stream." +msgstr "Nie udało się zakodować strumienia." + +msgid "Could not demultiplex stream." +msgstr "Nie udało się rozpleść strumienia." + +msgid "Could not multiplex stream." +msgstr "Nie udało się spleść strumienia." + +msgid "The stream is in the wrong format." +msgstr "Strumień ma niewłaściwy format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Strumień jest zaszyfrowany, a odszyfrowywanie nie jest obsługiwane." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Strumień jest zaszyfrowany i nie może być odszyfrowany z powodu braku " +"pasującego klucza." + +#, c-format +msgid "No error message for domain %s." +msgstr "Brak komunikatu błędu dla domeny %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Brak standardowego komunikatu o błędzie dla domeny %s i kodu %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Wybrany zegar nie może być używany w potoku." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Błąd zapisu pamięci podręcznej rejestru do %s: %s" + +msgid "title" +msgstr "tytuł" + +msgid "commonly used title" +msgstr "powszechnie używany tytuł" + +msgid "title sortname" +msgstr "tytuł do sortowania" + +msgid "commonly used title for sorting purposes" +msgstr "powszechnie używany tytuł na potrzeby sortowania" + +msgid "artist" +msgstr "artysta" + +msgid "person(s) responsible for the recording" +msgstr "osoba lub osoby odpowiedzialne za nagranie" + +msgid "artist sortname" +msgstr "artysta do sortowania" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "osoba lub osoby odpowiedzialne za nagranie - na potrzeby sortowania" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album zawierający te dane" + +msgid "album sortname" +msgstr "album do sortowania" + +msgid "album containing this data for sorting purposes" +msgstr "album zawierający te dane - na potrzeby sortowania" + +msgid "album artist" +msgstr "artysta dla albumu" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Artysta dla całego albumu w postaci do wyświetlania" + +msgid "album artist sortname" +msgstr "artysta do sortowania" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Artysta dla całego albumu w postaci do sortowania" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data utworzenia tych danych (jako struktura GDate)" + +msgid "datetime" +msgstr "data/czas" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data i czas utworzenia tych danych (jako struktura GstDateTime)" + +msgid "genre" +msgstr "gatunek" + +msgid "genre this data belongs to" +msgstr "gatunek do którego należą te dane" + +msgid "comment" +msgstr "komentarz" + +msgid "free text commenting the data" +msgstr "dowolny tekst komentujący te dane" + +msgid "extended comment" +msgstr "rozszerzony komentarz" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"dowolny tekst komentujący dane w postaci klucz=wartość lub " +"klucz[język]=komentarz" + +msgid "track number" +msgstr "numer ścieżki" + +msgid "track number inside a collection" +msgstr "numer ścieżki wewnątrz zbioru" + +msgid "track count" +msgstr "liczba ścieżek" + +msgid "count of tracks inside collection this track belongs to" +msgstr "liczba ścieżek wewnątrz zbioru obejmujących tę ścieżkę" + +msgid "disc number" +msgstr "numer płyty" + +msgid "disc number inside a collection" +msgstr "numer płyty wewnątrz kolekcji" + +msgid "disc count" +msgstr "liczba płyt" + +msgid "count of discs inside collection this disc belongs to" +msgstr "liczba płyt wewnątrz kolekcji obejmujących tę ścieżkę" + +msgid "location" +msgstr "położenie" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Pochodzenie utworu jako URI (położenie, gdzie trzymany jest oryginał pliku " +"lub strumienia)" + +msgid "homepage" +msgstr "strona domowa" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Strona domowa tego utworu (artysty lub filmu)" + +msgid "description" +msgstr "opis" + +msgid "short text describing the content of the data" +msgstr "krótki tekst opisujący treść danych" + +msgid "version" +msgstr "wersja" + +msgid "version of this data" +msgstr "wersja tych danych" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Intenational Standard Recording Code (międzynarodowy kod nagrania) - p. " +"http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organizacja" + +msgid "copyright" +msgstr "prawa autorskie" + +msgid "copyright notice of the data" +msgstr "informacja o prawach autorskich do tych danych" + +msgid "copyright uri" +msgstr "URI praw autorskich" + +msgid "URI to the copyright notice of the data" +msgstr "URI do informacji o prawach autorskich do tych danych" + +msgid "encoded by" +msgstr "kodujący" + +msgid "name of the encoding person or organization" +msgstr "nazwa osoby lub organizacji kodującej nagranie" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "informacje kontaktowe" + +msgid "license" +msgstr "licencja" + +msgid "license of data" +msgstr "licencja danych" + +msgid "license uri" +msgstr "URI licencji" + +msgid "URI to the license of the data" +msgstr "URI do licencji danych" + +msgid "performer" +msgstr "wykonawca" + +msgid "person(s) performing" +msgstr "osoba lub osoby wykonujące" + +msgid "composer" +msgstr "kompozytor" + +msgid "person(s) who composed the recording" +msgstr "osoba lub osoby, które skomponowały to nagranie" + +msgid "conductor" +msgstr "dyrygent" + +msgid "conductor/performer refinement" +msgstr "wyszczególnienie dyrygenta/wykonawcy" + +msgid "duration" +msgstr "czas trwania" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "długość w jednostkach czasu GStreamera (nanosekundach)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "kodek użyty do zapisu danych" + +msgid "video codec" +msgstr "kodek obrazu" + +msgid "codec the video data is stored in" +msgstr "kodek użyty do zapisu danych obrazu" + +msgid "audio codec" +msgstr "kodek dźwięku" + +msgid "codec the audio data is stored in" +msgstr "kodek użyty do zapisu danych dźwięku" + +msgid "subtitle codec" +msgstr "kodek napisów" + +msgid "codec the subtitle data is stored in" +msgstr "kodek użyty do zapisu danych napisów" + +msgid "container format" +msgstr "format kontenera" + +msgid "container format the data is stored in" +msgstr "format kontenera użytego do zapisu danych" + +msgid "bitrate" +msgstr "prędkość bitowa" + +msgid "exact or average bitrate in bits/s" +msgstr "dokładna lub średnia prędkość w bitach na sekundę" + +msgid "nominal bitrate" +msgstr "nominalna prędkość bitowa" + +msgid "nominal bitrate in bits/s" +msgstr "nominalna prędkość w bitach na sekundę" + +msgid "minimum bitrate" +msgstr "minimalna prędkość bitowa" + +msgid "minimum bitrate in bits/s" +msgstr "minimalna prędkość w bitach na sekundę" + +msgid "maximum bitrate" +msgstr "maksymalna prędkość bitowa" + +msgid "maximum bitrate in bits/s" +msgstr "maksymalna prędkość w bitach na sekundę" + +msgid "encoder" +msgstr "koder" + +msgid "encoder used to encode this stream" +msgstr "koder użyty do zakodowania tego strumienia" + +msgid "encoder version" +msgstr "wersja kodera" + +msgid "version of the encoder used to encode this stream" +msgstr "wersja kodera użyta do zakodowania tego strumienia" + +msgid "serial" +msgstr "numer seryjny" + +msgid "serial number of track" +msgstr "numer seryjny ścieżki" + +msgid "replaygain track gain" +msgstr "osiągi odtwarzania ścieżki" + +msgid "track gain in db" +msgstr "osiągi ścieżki w db" + +msgid "replaygain track peak" +msgstr "szczyt odtwarzania ścieżki" + +msgid "peak of the track" +msgstr "szczyt ścieżki" + +msgid "replaygain album gain" +msgstr "osiągi odtwarzania albumu" + +msgid "album gain in db" +msgstr "osiągi albumu w db" + +msgid "replaygain album peak" +msgstr "szczyt odtwarzania albumu" + +msgid "peak of the album" +msgstr "szczyt albumu" + +msgid "replaygain reference level" +msgstr "poziom odniesienia osiągów" + +msgid "reference level of track and album gain values" +msgstr "poziom odniesienia wartości osiągów ścieżki i albumu" + +msgid "language code" +msgstr "kod języka" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "kod języka dla tego strumienia, zgodny z ISO-639-1 lub ISO-639-2" + +msgid "language name" +msgstr "nazwa języka" + +msgid "freeform name of the language this stream is in" +msgstr "tekstowa nazwa języka, w jakim jest ten strumień" + +msgid "image" +msgstr "obrazek" + +msgid "image related to this stream" +msgstr "obrazek związany z tym strumieniem" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "podgląd obrazka" + +msgid "preview image related to this stream" +msgstr "podgląd obrazka związanego z tym strumieniem" + +msgid "attachment" +msgstr "załącznik" + +msgid "file attached to this stream" +msgstr "plik załączony do tego strumienia" + +msgid "beats per minute" +msgstr "uderzenia na minutę" + +msgid "number of beats per minute in audio" +msgstr "liczba uderzeń na minutę w dźwięku" + +msgid "keywords" +msgstr "słowa kluczowe" + +msgid "comma separated keywords describing the content" +msgstr "oddzielone przecinkami słowa kluczowe opisujące treść" + +msgid "geo location name" +msgstr "nazwa położenia geograficznego" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"czytelny dla człowieka opis miejsca, gdzie utwór został nagrany lub " +"wyprodukowany" + +msgid "geo location latitude" +msgstr "szerokość geograficzna" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"szerokość geograficzna miejsca, gdzie utwór został nagrany lub wyprodukowany " +"wyrażona w stopniach zgodnie z WSG84 (0 dla równika, wartości ujemne dla " +"szerokości południowych)" + +msgid "geo location longitude" +msgstr "długość geograficzna" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"długość geograficzna miejsca, gdzie utwór został nagrany lub wyprodukowany " +"wyrażona w stopniach zgodnie z WSG84 (0 dla pierwszego południka w Greenwich/" +"UK, wartości ujemne dla długości zachodnich)" + +msgid "geo location elevation" +msgstr "wysokość n.p.m." + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"wysokość miejsca, gdzie utwór został nagrany lub wyprodukowany wyrażona w " +"metrach zgodnie z WSG84 (0 to średni poziom morza)" + +msgid "geo location country" +msgstr "kraj lokalizacji" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"kraj (nazwa angielska), w którym utwór został nagrany lub wyprodukowany" + +msgid "geo location city" +msgstr "miasto lokalizacji" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"miejscowość (nazwa angielska), w której utwór został nagrany lub " +"wyprodukowany" + +msgid "geo location sublocation" +msgstr "część miejscowości lokalizacji" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"miejsce wewnątrz miejscowości, w którym utwór został nagrany lub " +"wyprodukowany (np. dzielnica)" + +msgid "geo location horizontal error" +msgstr "błąd poziomego położenia geograficznego" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "spodziewany błąd oszacowania położenia poziomego (w metrach)" + +msgid "geo location movement speed" +msgstr "prędkość zmiany położenia geograficznego" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "prędkość ruchu urządzenia nagrywającego w trakcie nagrania (m/s)" + +msgid "geo location movement direction" +msgstr "kierunek zmiany położenia geograficznego" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"określenie kierunku ruchu urządzenia nagrywającego w stopniach (w notacji " +"zmiennoprzecinkowej); 0 oznacza geograficzną północ, rośnie zgodnie z ruchem " +"wskazówek zegara" + +msgid "geo location capture direction" +msgstr "kierunek geograficzny urządzenia nagrywającego" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"określenie kierunku, w jakim było skierowane urządzenie nagrywające w " +"trakcie nagrania - w stopniach, w notacji zmiennoprzecinkowej; 0 oznacza " +"geograficzną północ, rośnie zgodnie z ruchem wskazówek zegara" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nazwa widowiska" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Nazwa widowiska telewizyjnego/podcastu/serialu, z którego pochodzi utwór" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "nazwa widowiska do sortowania" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Nazwa widowiska telewizyjnego/podcastu/serialu na potrzeby sortowania" + +msgid "episode number" +msgstr "numer odcinka" + +msgid "The episode number in the season the media is part of" +msgstr "Numer odcinka w sezonie, z którego pochodzi utwór" + +msgid "season number" +msgstr "numer sezonu" + +msgid "The season number of the show the media is part of" +msgstr "Numer sezonu widowiska, z którego pochodzi utwór" + +msgid "lyrics" +msgstr "tekst" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Tekst utworu, używany najczęściej dla piosenek" + +msgid "composer sortname" +msgstr "nazwa kompozytora do sortowania" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "osoba lub osoby, które skomponowały nagranie - na potrzeby sortowania" + +msgid "grouping" +msgstr "grupowanie" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupowanie powiązanych utworów rozciągające się na wiele ścieżek, jak różne " +"części koncertu; jest to poziom wyższy niż ścieżka, a niższy niż album" + +msgid "user rating" +msgstr "ocena użytkownika" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Ocena przypisana przez użytkownika. Im wyższa, tym bardziej użytkownik lubi " +"utwór" + +msgid "device manufacturer" +msgstr "producent urządzenia" + +msgid "Manufacturer of the device used to create this media" +msgstr "Producent urządzenia użytego do utworzenia tego nagrania" + +msgid "device model" +msgstr "model urządzenia" + +msgid "Model of the device used to create this media" +msgstr "Model urządzenia użytego do utworzenia tego nagrania" + +msgid "application name" +msgstr "nazwa aplikacji" + +msgid "Application used to create the media" +msgstr "Aplikacja użyta do utworzenia tego nagrania" + +msgid "application data" +msgstr "dane aplikacji" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Dowolne dane aplikacji zserializowane w nagraniu" + +msgid "image orientation" +msgstr "orientacja obrazu" + +msgid "How the image should be rotated or flipped before display" +msgstr "" +"W jaki sposób obraz powinien być obrócony lub odbity przed wyświetleniem" + +msgid "publisher" +msgstr "wydawca" + +msgid "Name of the label or publisher" +msgstr "Nazwa wytwórni lub wydawcy" + +msgid "interpreted-by" +msgstr "interpretacja" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informacja o osobach odpowiedzialnych za remix lub podobne interpretacje" + +msgid "midi-base-note" +msgstr "dźwięk-podstawowy-midi" + +msgid "Midi note number of the audio track." +msgstr "Numer dźwięku MIDI ścieżki dźwiękowej." + +msgid "private-data" +msgstr "dane-prywatne" + +msgid "Private data" +msgstr "Dane prywatne" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Nie znaleziono sposobu obsługi URI dla protokołu %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Schemat URI '%s' nie jest obsługiwany" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "BŁĄD: od elementu %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Dodatkowe informacje diagnostyczne:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "dowiązanie nie ma źródła [cel=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "dowiązanie nie ma celu [źródło=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "brak właściwości \"%s\" w elemencie \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nie udało się ustawić właściwości \"%s\" w elemencie \"%s\" na \"%s\"" + +msgid "Delayed linking failed." +msgstr "Opóźnione dowiązanie nie powiodło się." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nie udało się dowiązać %s do %s, %s nie może obsłużyć możliwości %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"nie udało się dowiązać %s do %s, żaden element nie obsługuje możliwości %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nie udało się dowiązać %s do %s z możliwościami %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nie udało się dowiązać %s do %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "brak elementu \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "nieoczekiwane odniesienie \"%s\" - zignorowano" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "nieoczekiwane odniesienie dopełniające \"%s\" - zignorowano" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nie udało się przeanalizować możliwości \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "brak elementu osadzającego dla URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "brak elementu źródłowego dla URI \"%s\"" + +msgid "syntax error" +msgstr "błąd składni" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "podano pusty kontener \"%s\", nie jest to dozwolone" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "brak kontenera \"%s\", rozpakowywanie elementów" + +msgid "empty pipeline not allowed" +msgstr "pusty potok nie jest dozwolony" + +msgid "A lot of buffers are being dropped." +msgstr "Wiele buforów zostało zgubionych." + +msgid "Internal data flow problem." +msgstr "Wewnętrzny problem przepływu danych." + +msgid "Internal data flow error." +msgstr "Wewnętrzny błąd przepływu danych." + +msgid "Internal clock error." +msgstr "Wewnętrzny błąd zegara." + +msgid "Failed to map buffer." +msgstr "Nie udało się odwzorować bufora." + +msgid "Filter caps" +msgstr "Filtrowanie możliwości" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Ograniczenie możliwych dozwolonych możliwości (NULL oznacza WSZYSTKIE). " +"Ustawienie tej właściwości odwołuje się do przekazanego obiektu GstCaps." + +msgid "Caps Change Mode" +msgstr "Tryb zmiany możliwości" + +msgid "Filter caps change behaviour" +msgstr "Filtrowanie zachowania zmiany możliwości" + +msgid "No Temp directory specified." +msgstr "Nie podano katalogu tymczasowego." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nie udało się utworzyć pliku tymczasowego \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nie udało się otworzyć pliku \"%s\" do odczytu." + +msgid "Error while writing to download file." +msgstr "Błąd podczas zapisu do ściąganego pluku." + +msgid "No file name specified for writing." +msgstr "Nie podano nazwy pliku do zapisu." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nie udało się otworzyć pliku \"%s\" do zapisu." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Błąd podczas zamykania pliku \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Błąd podczas przemieszczania w pliku \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Błąd podczas zapisu do pliku \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nie podano nazwy pliku do odczytu." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nie udało się uzyskać informacji o \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" jest katalogiem." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Plik \"%s\" jest gniazdem." + +msgid "Failed after iterations as requested." +msgstr "Niepowodzenie po iteracjach jak żądano." + +msgid "caps" +msgstr "możliwości" + +msgid "detected capabilities in stream" +msgstr "wykryte możliwości w strumieniu" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "wymuszenie możliwości" + +msgid "force caps without doing a typefind" +msgstr "wymuszenie możliwości bez sprawdzania" + +msgid "Stream doesn't contain enough data." +msgstr "Strumień nie zawiera wystarczająco dużo danych." + +msgid "Stream contains no data." +msgstr "Strumień nie zawiera danych." + +msgid "Implemented Interfaces:\n" +msgstr "Zaimplementowane interfejsy:\n" + +msgid "readable" +msgstr "odczyt" + +msgid "writable" +msgstr "zapis" + +msgid "deprecated" +msgstr "przestarzałe" + +msgid "controllable" +msgstr "sterowanie" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "możliwa zmiana w stanie NULL, GOTOWOŚĆ, PAUZOWANIE lub ODTWARZANIE" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "możliwa zmiana tylko w stanie NULL, GOTOWOŚĆ lub PAUZOWANIE" + +msgid "changeable only in NULL or READY state" +msgstr "możliwa zmiana tylko w stanie NULL lub GOTOWOŚĆ" + +msgid "Blacklisted files:" +msgstr "Pliki wykluczone:" + +msgid "Total count: " +msgstr "Całkowita liczba: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d plik wykluczony" +msgstr[1] "%d pliki wykluczone" +msgstr[2] "%d plików wykluczonych" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d wtyczka" +msgstr[1] "%d wtyczki" +msgstr[2] "%d wtyczek" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d wpis wykluczony" +msgstr[1] "%d wpisy wykluczone" +msgstr[2] "%d wpisów wykluczonych" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d cecha" +msgstr[1] "%d cechy" +msgstr[2] "%d cech" + +msgid "Print all elements" +msgstr "Wypisanie wszystkich elementów" + +msgid "Print list of blacklisted files" +msgstr "Wypisanie listy plików wykluczonych" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Wypisanie nadającej się do przetworzenia przez maszynę listy cech " +"dostarczanych przez określoną wtyczkę.\n" +" Przydatne w połączeniu z zewnętrznymi " +"automatycznymi mechanizmami instalacji wtyczek" + +msgid "List the plugin contents" +msgstr "Wypisanie zawartości wtyczek" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Lista rozdzielonych ukośnikami ('/') typów elementów (znanych jako klass) do " +"wypisania (nie uporządkowana)." + +msgid "Check if the specified element or plugin exists" +msgstr "Sprawdzenie, czy podany element lub wtyczka istnieje" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Przy sprawdzaniu istnienia elementu lub wtyczki, sprawdzanie także czy " +"wersja jest co najmniej podaną" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Wypisanie obsługiwanych schematów URI wraz z implementującymi je elementami" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nie udało się wczytać pliku wtyczki: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nie ma takiego elementu lub wtyczki '%s'\n" + +msgid "Index statistics" +msgstr "Statystyki indeksu" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Odebrano komunikat #%u od elementu \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Odebrano komunikat #%u od pola \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Odebrano komunikat #%u od obiektu \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Odebrano komunikat #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Otrzymano EOS od elementu \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ZNACZNIK : znaleziony przez element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ZNACZNIK : znaleziony przez pole \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ZNACZNIK : znaleziony przez obiekt \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "ZNACZNIK\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "SPIS TREŚCI : znaleziony przez element \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "SPIS TREŚCI : znaleziony przez obiekt \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "SPIS TREŚCI\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMACJA:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "UWAGA: od elementu %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Przewinięto, czekanie na zakończenie buforowania...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Przewinięto, czekanie na zakończenie postępu...\n" + +msgid "buffering..." +msgstr "buforowanie..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Buforowanie zakończone, ustawianie potoku na ODTWARZANIE...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Buforowanie, ustawianie potoku na PAUZOWANIE...\n" + +msgid "Redistribute latency...\n" +msgstr "Rozprzestrzenianie opóźnień...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Ustawianie stanu na %s zgodnie z wymaganiem %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Przerwanie: Zatrzymywanie potoku...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Postęp: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Brak elementu: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Otrzymano kontekst od elementu '%s': %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Wypisanie znaczników (znanych także jako metadane)" + +msgid "Output TOC (chapters and editions)" +msgstr "Wypisanie spisu treści (rozdziałów i wydań)" + +msgid "Output status information and property notifications" +msgstr "Wypisywanie informacji o stanie i powiadomień właściwości" + +msgid "Do not print any progress information" +msgstr "Nie wypisywanie żadnej informacji o postępie" + +msgid "Output messages" +msgstr "Wypisywanie komunikatów" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Bez wypisywania informacji o stanie określonej własności, jeśli szczegółowe " +"wyjście jest włączone (może być użyte wielokrotnie)" + +msgid "PROPERTY-NAME" +msgstr "NAZWA-WŁASNOŚCI" + +msgid "Do not install a fault handler" +msgstr "Nie instalowanie obsługi błędów" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Wymuszanie EOS na źródłach przed zamknięciem potoku" + +msgid "Gather and print index statistics" +msgstr "Zebranie i wypisanie statystyk indeksu" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "BŁĄD: nie udało się skonstruować potoku: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "BŁĄD: nie udało się skonstruować potoku.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "UWAGA: błędny potok: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "BŁĄD: nie znaleziono elementu 'pipeline'.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Ustawianie potoku na PAUZOWANIE...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "BŁĄD: potok odmawia pauzowania.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Potok jest na żywo i nie wymaga PRZEWINIĘCIA...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Potok jest PRZEWIJANY...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "BŁĄD: potok odmawia przewinięcia.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Potok jest PRZEWINIĘTY...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Ustawianie potoku na ODTWARZANIE...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "BŁĄD: potok odmawia odtwarzania.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Włączony EOS przy wyłączaniu - wymuszanie EOS w potoku\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Włączony EOS przy wyłączaniu - oczekiwanie na EOS po błędzie\n" + +msgid "Waiting for EOS...\n" +msgstr "Oczekiwanie na EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Otrzymano EOS - zatrzymywanie potoku...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Przerwanie podczas oczekiwania na EOS - zatrzymywanie potoku...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Wystąpił błąd w trakcie oczekiwania na EOS\n" + +msgid "Execution ended after %" +msgstr "Wykonywanie zakończone po %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Ustawianie potoku na GOTOWOŚĆ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Ustawianie potoku na NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Zwalnianie potoku...\n" diff --git a/po/pt_BR.gmo b/po/pt_BR.gmo new file mode 100644 index 0000000..5295d42 Binary files /dev/null and b/po/pt_BR.gmo differ diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..20ab918 --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,1420 @@ +# Brazilian Portuguese translation of GStreamer. +# Copyright (C) 2008-2016 Free Software Foundation, Inc. +# This file is distributed under the same license as the GStreamer package. +# Fabrício Godoy , 2008-2016. +# +# pipeline -> fila de processamento +# sink -> consumidor +# flow -> fluxo +# stream -> fluxo +# preroll -> preparar +# clock -> temporizador +# sources + sinks = pad +# element + element + ... = bin +# description of media formats = caps +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-1.7.90\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2016-05-06 18:23-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 "Print the GStreamer version" +msgstr "Exibir a versão do GStreamer" + +msgid "Make all warnings fatal" +msgstr "Tratar todos avisos como fatais" + +msgid "Print available debug categories and exit" +msgstr "Exibir as categorias de depuração disponíveis e sair" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Níveis de depuração predefinidos de 1 (apenas erros) até 9 (tudo) ou 0 para " +"nenhuma saída" + +msgid "LEVEL" +msgstr "NÍVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Lista de \"categoria_nome:nível\" separados por vírgulas, para definir " +"níveis específicos para as categorias individuais. Exemplo: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Desabilitar saída de depuração colorida" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Altera o modo de cor do log de depuração. Modos possíveis: off (desligado), " +"on (ligado), disable (desabilitado), auto (automático) e unix" + +msgid "Disable debugging" +msgstr "Desabilitar depuração" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Habilitar diagnótico detalhado do carregamento do plug-in" + +msgid "Colon-separated paths containing plugins" +msgstr "Caminhos, separados por dois-pontos, de plug-ins" + +msgid "PATHS" +msgstr "CAMINHOS" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Lista, separada por vírgulas, de plug-ins para pré-carregar além da lista " +"armazenada na variável de ambiente GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUG-INS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Desabilitar intercepção das falhas de segmentação durante o carregamento do " +"plug-in" + +msgid "Disable updating the registry" +msgstr "Desabilitar atualização do registro" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Desabilitar a criação de um processo auxiliar durante a análise do registro" + +msgid "GStreamer Options" +msgstr "Opções do GStreamer" + +msgid "Show GStreamer Options" +msgstr "Exibir opções do GStreamer" + +msgid "Unknown option" +msgstr "Opção desconhecida" + +msgid "GStreamer encountered a general core library error." +msgstr "O GStreamer encontrou um erro geral na biblioteca principal." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Os desenvolvedores do GStreamer são muito preguiçosos para definir um código " +"de erro para esse erro." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Erro interno no GStreamer: código não implementado." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Erro no GStreamer: falha ao alterar estado e algum elemento falhou ao enviar " +"uma mensagem de erro apropriada com a razão da falha." + +msgid "Internal GStreamer error: pad problem." +msgstr "Erro interno no GStreamer: problema no Pad." + +msgid "Internal GStreamer error: thread problem." +msgstr "Erro interno no GStreamer: problema no segmento (thread)." + +msgid "GStreamer error: negotiation problem." +msgstr "Erro no GStreamer: problema de negociação." + +msgid "Internal GStreamer error: event problem." +msgstr "Erro interno no GStreamer: problema no evento." + +msgid "Internal GStreamer error: seek problem." +msgstr "Erro interno no GStreamer: problema na busca." + +msgid "Internal GStreamer error: caps problem." +msgstr "Erro interno no GStreamer: problema no Caps." + +msgid "Internal GStreamer error: tag problem." +msgstr "Erro interno no GStreamer: problema na etiqueta." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Sua instalação do GStreamer está com um plug-in faltando." + +msgid "GStreamer error: clock problem." +msgstr "Erro no GStreamer: problema no temporizador." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Este aplicativo está tentando usar uma funcionalidade do GStreamer que foi " +"desabilitada." + +msgid "GStreamer encountered a general supporting library error." +msgstr "O GStreamer encontrou um erro geral na biblioteca de suporte." + +msgid "Could not initialize supporting library." +msgstr "Não foi possível iniciar a biblioteca de suporte." + +msgid "Could not close supporting library." +msgstr "Não foi possível fechar a biblioteca de suporte." + +msgid "Could not configure supporting library." +msgstr "Não foi possível configurar a biblioteca de suporte." + +msgid "Encoding error." +msgstr "Erro de codificação." + +msgid "GStreamer encountered a general resource error." +msgstr "O GStreamer encontrou um erro geral nos recursos." + +msgid "Resource not found." +msgstr "Recurso não encontrado." + +msgid "Resource busy or not available." +msgstr "O recurso está ocupado ou não disponível." + +msgid "Could not open resource for reading." +msgstr "Não foi possível abrir o recurso para leitura." + +msgid "Could not open resource for writing." +msgstr "Não foi possível abrir o recurso para escrita." + +msgid "Could not open resource for reading and writing." +msgstr "Não foi possível abrir o recurso para leitura e escrita." + +msgid "Could not close resource." +msgstr "Não foi possível fechar o recurso." + +msgid "Could not read from resource." +msgstr "Não foi possível ler do recurso." + +msgid "Could not write to resource." +msgstr "Não foi possível escrever no recurso." + +msgid "Could not perform seek on resource." +msgstr "Não foi possível realizar uma busca no recurso." + +msgid "Could not synchronize on resource." +msgstr "Não foi possível sincronizar no recurso." + +msgid "Could not get/set settings from/on resource." +msgstr "Não foi possível obter/definir configurações para/do recurso." + +msgid "No space left on the resource." +msgstr "Não foi deixado espaço no recurso." + +msgid "Not authorized to access resource." +msgstr "O acesso ao recurso não foi autorizado." + +msgid "GStreamer encountered a general stream error." +msgstr "O GStreamer encontrou um erro geral no fluxo." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"O elemento não implementa a manipulação desse fluxo. Por favor, relate o " +"erro." + +msgid "Could not determine type of stream." +msgstr "Não foi possível determinar o tipo do fluxo." + +msgid "The stream is of a different type than handled by this element." +msgstr "O fluxo é de um tipo diferente do que o manipulado por esse elemento." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Não há um CODEC presente que possa manipular esse tipo de fluxo." + +msgid "Could not decode stream." +msgstr "Não foi possível decodificar o fluxo." + +msgid "Could not encode stream." +msgstr "Não foi possível codificar o fluxo." + +msgid "Could not demultiplex stream." +msgstr "Não foi possível demultiplexar o fluxo." + +msgid "Could not multiplex stream." +msgstr "Não foi possível multiplexar o fluxo." + +msgid "The stream is in the wrong format." +msgstr "Esse fluxo está com um formato errado." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "O fluxo está criptografado e não há suporte a descriptografação." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"O fluxo está criptografado e não pôde ser descriptografado porque nenhuma " +"chave apropriada foi fornecida." + +#, c-format +msgid "No error message for domain %s." +msgstr "Nenhuma mensagem de erro para o domínio %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Nenhuma mensagem de erro predefinida para o domínio %s e código %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" +"O temporizador selecionado não pôde ser usado na fila de processamento." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Erro ao escrever o cache de registro em %s: %s" + +msgid "title" +msgstr "título" + +msgid "commonly used title" +msgstr "título normalmente usado" + +msgid "title sortname" +msgstr "título para ordenação" + +msgid "commonly used title for sorting purposes" +msgstr "título normalmente usado, para ordenação" + +msgid "artist" +msgstr "artista" + +msgid "person(s) responsible for the recording" +msgstr "pessoa(s) responsável(is) pela gravação" + +msgid "artist sortname" +msgstr "artista para ordenação" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "pessoa(s) responsável(is) pela gravação, para ordenação" + +msgid "album" +msgstr "álbum" + +msgid "album containing this data" +msgstr "álbum contendo esses dados" + +msgid "album sortname" +msgstr "álbum para ordenação" + +msgid "album containing this data for sorting purposes" +msgstr "álbum contendo esses dados, para ordenação" + +msgid "album artist" +msgstr "artista do álbum" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "O artista de todo álbum, como ele deveria ser exibido" + +msgid "album artist sortname" +msgstr "artista do álbum para ordenação" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "O artista de todo álbum, como ele deveria ser ordenado" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data que os dados foram criados (estrutura GDate)" + +msgid "datetime" +msgstr "data hora" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data e hora que os dados foram criados (estrutura GstDateTime)" + +msgid "genre" +msgstr "gênero" + +msgid "genre this data belongs to" +msgstr "gênero que este dado pertence" + +msgid "comment" +msgstr "comentário" + +msgid "free text commenting the data" +msgstr "texto livre comentando os dados" + +msgid "extended comment" +msgstr "comentário prolongado" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"texto livre comentando os dados, usando o formato chave=valor ou " +"chave[pt_BR]=comentário" + +msgid "track number" +msgstr "número da faixa" + +msgid "track number inside a collection" +msgstr "número da faixa dentro da coleção" + +msgid "track count" +msgstr "número de faixas" + +msgid "count of tracks inside collection this track belongs to" +msgstr "número de faixas dentro da coleção que esta faixa pertence" + +msgid "disc number" +msgstr "número do disco" + +msgid "disc number inside a collection" +msgstr "número do disco dentro da coleção" + +msgid "disc count" +msgstr "número de discos" + +msgid "count of discs inside collection this disc belongs to" +msgstr "número de discos dentro da coleção que este disco pertence" + +msgid "location" +msgstr "local" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"A origem da mídia como um URI (localização onde o arquivo ou fluxo original " +"está hospedado)" + +msgid "homepage" +msgstr "página inicial" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Página inicial desta mídia (página inicial do artista ou filme)" + +msgid "description" +msgstr "descrição" + +msgid "short text describing the content of the data" +msgstr "texto pequeno descrevendo o conteúdo dos dados" + +msgid "version" +msgstr "versão" + +msgid "version of this data" +msgstr "versão destes dados" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Código de Gravação Padrão Internacional (ISRC) - consulte http://www.ifpi." +"org/isrc/" + +msgid "organization" +msgstr "organização" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "informação de copyright dos dados" + +msgid "copyright uri" +msgstr "URI do copyright" + +msgid "URI to the copyright notice of the data" +msgstr "URI para a informação de copyright dos dados" + +msgid "encoded by" +msgstr "codificado por" + +msgid "name of the encoding person or organization" +msgstr "nome da pessoa ou organização que codificou o arquivo" + +msgid "contact" +msgstr "contato" + +msgid "contact information" +msgstr "informação de contato" + +msgid "license" +msgstr "licença" + +msgid "license of data" +msgstr "licença dos dados" + +msgid "license uri" +msgstr "URI da licença" + +msgid "URI to the license of the data" +msgstr "URI para a licença dos dados" + +msgid "performer" +msgstr "participação" + +msgid "person(s) performing" +msgstr "pessoa(s) participante(s)" + +msgid "composer" +msgstr "compositor" + +msgid "person(s) who composed the recording" +msgstr "pessoa(s) que compôs(useram) a gravação" + +msgid "conductor" +msgstr "maestro" + +msgid "conductor/performer refinement" +msgstr "maestro/músico de afinação" + +msgid "duration" +msgstr "duração" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "comprimento em unidades de tempo do GStreamer (nanosegundos)" + +msgid "codec" +msgstr "CODEC" + +msgid "codec the data is stored in" +msgstr "CODEC usado nos dados" + +msgid "video codec" +msgstr "CODEC de vídeo" + +msgid "codec the video data is stored in" +msgstr "CODEC de vídeo usado nos dados" + +msgid "audio codec" +msgstr "CODEC de áudio" + +msgid "codec the audio data is stored in" +msgstr "CODEC de áudio usado nos dados" + +msgid "subtitle codec" +msgstr "CODEC de legenda" + +msgid "codec the subtitle data is stored in" +msgstr "CODEC de legenda usado nos dados" + +msgid "container format" +msgstr "formato do contêiner" + +msgid "container format the data is stored in" +msgstr "formato do contêiner usado para os dados" + +msgid "bitrate" +msgstr "taxa de bits" + +msgid "exact or average bitrate in bits/s" +msgstr "taxa de bits exata ou média, em bits/s" + +msgid "nominal bitrate" +msgstr "taxa de bits nominal" + +msgid "nominal bitrate in bits/s" +msgstr "taxa de bits nominal, em bits/s" + +msgid "minimum bitrate" +msgstr "taxa de bits mínima" + +msgid "minimum bitrate in bits/s" +msgstr "taxa de bits mínima, em bits/s" + +msgid "maximum bitrate" +msgstr "taxa de bits máxima" + +msgid "maximum bitrate in bits/s" +msgstr "taxa de bits máxima, em bits/s" + +msgid "encoder" +msgstr "codificador" + +msgid "encoder used to encode this stream" +msgstr "codificador usado pelo fluxo" + +msgid "encoder version" +msgstr "versão do codificador" + +msgid "version of the encoder used to encode this stream" +msgstr "versão do codificador usado pelo fluxo" + +msgid "serial" +msgstr "série" + +msgid "serial number of track" +msgstr "número de série da faixa" + +msgid "replaygain track gain" +msgstr "ganho da faixa (ReplayGain)" + +msgid "track gain in db" +msgstr "ganho da faixa em decibéis" + +msgid "replaygain track peak" +msgstr "pico da faixa (ReplayGain)" + +msgid "peak of the track" +msgstr "pico da faixa" + +msgid "replaygain album gain" +msgstr "ganho do álbum (ReplayGain)" + +msgid "album gain in db" +msgstr "ganho do álbum em decibéis" + +msgid "replaygain album peak" +msgstr "pico do álbum (ReplayGain)" + +msgid "peak of the album" +msgstr "pico do álbum" + +msgid "replaygain reference level" +msgstr "nível de referência (ReplayGain)" + +msgid "reference level of track and album gain values" +msgstr "nível de referência dos valores de ganho da faixa e do álbum" + +msgid "language code" +msgstr "código da língua" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "código da língua deste fluxo, conforme o ISO-639-1 ou ISO-639-2" + +msgid "language name" +msgstr "nome do idioma" + +msgid "freeform name of the language this stream is in" +msgstr "nome, em formato livre, do idioma do fluxo" + +msgid "image" +msgstr "imagem" + +msgid "image related to this stream" +msgstr "imagem relacionada a este fluxo" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "miniatura" + +msgid "preview image related to this stream" +msgstr "miniatura relacionada a este fluxo" + +msgid "attachment" +msgstr "anexo" + +msgid "file attached to this stream" +msgstr "arquivo anexado a este fluxo" + +msgid "beats per minute" +msgstr "batidas por minuto" + +msgid "number of beats per minute in audio" +msgstr "número de batidas por minuto no áudio" + +msgid "keywords" +msgstr "palavras-chave" + +msgid "comma separated keywords describing the content" +msgstr "palavras-chave separadas por vírgula descrevendo o conteúdo" + +msgid "geo location name" +msgstr "nome da localização geográfica" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"descrição legível da localização de onde a mídia foi gravada ou produzida" + +msgid "geo location latitude" +msgstr "latitude da localização geográfica" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitude da localização geográfica de onde a mídia foi gravada ou produzida " +"em graus de acordo com WGS84 (zero corresponde ao equador e valores " +"negativos a latitudes ao sul)" + +msgid "geo location longitude" +msgstr "longitude da localização geográfica" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitude da localização geográfica de onde a mídia foi gravada ou produzida " +"em graus de acordo com WGS84 (zero corresponde ao meridiano de Greenwich/UK " +"e valores negativos a latitudes ao oeste)" + +msgid "geo location elevation" +msgstr "elevação da localização geográfica" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"elevação geográfica de onde a mídia foi gravada ou produzida em metros de " +"acordo com WGS84 (zero é a média do nível do mar)" + +msgid "geo location country" +msgstr "localização geográfica do país" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "país, em inglês, onde a mídia foi gravada ou produzida" + +msgid "geo location city" +msgstr "localização geográfica da cidade" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "cidade, em inglês, onde a mídia foi gravada ou produzida" + +msgid "geo location sublocation" +msgstr "sublocalização geográfica" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"localização numa cidade onde a mídia foi produzida ou criada (ex: bairro)" + +msgid "geo location horizontal error" +msgstr "desvio horizontal da localização geográfica" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "desvio esperado nas medidas de posicionamento horizontal (em metros)" + +msgid "geo location movement speed" +msgstr "velocidade de movimento na localização geográfica" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"velocidade de movimento do dispositivo de captura ao realizar a captura, em " +"m/s" + +msgid "geo location movement direction" +msgstr "direção de movimento na localização geográfica" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica a direção de movimento do dispositivo ao realizar a captura de uma " +"mídia. É representado como graus em representação fracionária, 0 indica " +"Norte e incrementa-se no sentido do relógio" + +msgid "geo location capture direction" +msgstr "direção de captura na localização geográfica" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica a direção que o dispositivo estava apontando quando capturava uma " +"mídia. É representado como graus em representação fracionária, 0 indica " +"Norte e incrementa-se no sentido do relógio" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nome do programa" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Nome do programa de TV, do podcast ou da série de onde a mídia tem origem" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "programa para ordenação" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Nome do programa de TV, do podcast ou da série de onde a mídia tem origem, " +"para ordenação" + +msgid "episode number" +msgstr "número do episódio" + +msgid "The episode number in the season the media is part of" +msgstr "O número do episódio da temporada que a mídia faz parte" + +msgid "season number" +msgstr "número da temporada" + +msgid "The season number of the show the media is part of" +msgstr "O número da temporada da série que a mídia faz parte" + +msgid "lyrics" +msgstr "letras de música" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "As letras de música da mídia" + +msgid "composer sortname" +msgstr "compositor para ordenação" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "pessoa(s) que compôs a gravação, para ordenação" + +msgid "grouping" +msgstr "parte" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Partes da mídia que se extende em várias faixas, como diferentes partes de " +"um concerto. Tem um nível acima da faixa, mas abaixo do álbum" + +msgid "user rating" +msgstr "avaliação do usuário" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Avaliação atribuída pelo usuário. Quanto melhor a avaliação, mais o usuário " +"gosta da mídia" + +msgid "device manufacturer" +msgstr "fabricante do dispositivo" + +msgid "Manufacturer of the device used to create this media" +msgstr "Fabricante do dispositivo usado para criar esta mídia" + +msgid "device model" +msgstr "modelo do dispositivo" + +msgid "Model of the device used to create this media" +msgstr "Modelo do dispositivo usado para criar esta mídia" + +msgid "application name" +msgstr "nome do aplicativo" + +msgid "Application used to create the media" +msgstr "Aplicativo usado para criar a mídia" + +msgid "application data" +msgstr "Dados do aplicativo" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Dados arbitrários do aplicativo para ser serializado na mídia" + +msgid "image orientation" +msgstr "orientação de imagem" + +msgid "How the image should be rotated or flipped before display" +msgstr "Como a imagem deveria ser rotacionada ou invertida antes da exibição" + +msgid "publisher" +msgstr "editora" + +msgid "Name of the label or publisher" +msgstr "Nome da gravadora ou editora" + +msgid "interpreted-by" +msgstr "interpretado por" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" +"Informações sobre a pessoa detrás de um remix ou interpretações similares" + +msgid "midi-base-note" +msgstr "nota-base-midi" + +msgid "Midi note number of the audio track." +msgstr "Número MIDI da nota da trilha de áudio." + +msgid "private-data" +msgstr "dados-privados" + +msgid "Private data" +msgstr "Dados privados" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Nenhum manipulador URI para o protocolo %s foi encontrado" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Não há suporte para o esquema URI \"%s\"" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ERRO: do elemento %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Informação adicional de depuração:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "não há elemento fonte no link [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "não há consumidor no link [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nenhuma propriedade \"%s\" no elemento \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" +"não foi possível definir a propriedade \"%s\" no elemento \"%s\" para o " +"valor \"%s\"" + +msgid "Delayed linking failed." +msgstr "Falha no vínculo postergado." + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "não foi possível vincular %s em %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "não foi possível vincular o elemento consumidor para o URI \"%s\"" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "não foi possível vincular %s em %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "não foi possível vincular %s em %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "nenhum elemento \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "referência inesperada \"%s\" - ignorando" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "referência ao Pad inesperada \"%s\" - ignorando" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "não foi possível analisar o Caps \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "nenhum elemento consumidor para o URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "nenhum elemento fonte para o URI \"%s\"" + +msgid "syntax error" +msgstr "erro de sintaxe" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "o Bin \"%s\" está vazio, operação não permitida" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "nenhum Bin \"%s\", descarregando elementos" + +msgid "empty pipeline not allowed" +msgstr "não é permitido que a fila de processamento seja vazia" + +msgid "A lot of buffers are being dropped." +msgstr "Uma grande quantidade de buffers está sendo descartada." + +msgid "Internal data flow problem." +msgstr "Problema interno no fluxo de dados." + +msgid "Internal data flow error." +msgstr "Erro interno no fluxo de dados." + +msgid "Internal clock error." +msgstr "Erro interno no temporizador." + +msgid "Failed to map buffer." +msgstr "Falha ao mapear o buffer." + +msgid "Filter caps" +msgstr "Filtro Caps" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restrinja as possíveis capacidades permitidas (NULL = ANY). Definindo essa " +"propriedade é levada uma referência ao objeto GstCaps fornecido." + +msgid "Caps Change Mode" +msgstr "Modo de Alteração do Caps" + +msgid "Filter caps change behaviour" +msgstr "Comportamento de alteração do filtro Caps" + +msgid "No Temp directory specified." +msgstr "Nenhum diretório temporário especificado." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Não foi possível criar o arquivo temporário \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Não foi possível abrir o arquivo \"%s\" para leitura." + +msgid "Error while writing to download file." +msgstr "Erro ao escrever no arquivo baixado." + +msgid "No file name specified for writing." +msgstr "Nenhum nome de arquivo especificado para escrita." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Não foi possível abrir o arquivo \"%s\" para escrita." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Erro ao fechar o arquivo \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Erro ao buscar no arquivo \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Erro ao escrever no arquivo \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nenhum nome de arquivo especificado para leitura." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Não foi possível obter informações em \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" é um diretório." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "O arquivo \"%s\" é um soquete." + +msgid "Failed after iterations as requested." +msgstr "Falha após as interações requeridas." + +msgid "caps" +msgstr "Caps" + +msgid "detected capabilities in stream" +msgstr "capacidades detectadas no fluxo" + +msgid "minimum" +msgstr "mínimo" + +msgid "force caps" +msgstr "forçar Caps" + +msgid "force caps without doing a typefind" +msgstr "forçar Caps sem usar o typefind" + +msgid "Stream doesn't contain enough data." +msgstr "O fluxo não contém dados suficientes." + +msgid "Stream contains no data." +msgstr "O fluxo não contém dados." + +msgid "Implemented Interfaces:\n" +msgstr "Interfaces implementadas:\n" + +msgid "readable" +msgstr "legível" + +msgid "writable" +msgstr "gravável" + +msgid "deprecated" +msgstr "obsoleto" + +msgid "controllable" +msgstr "controlável" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "estado alterável para NULO, PRONTO, PAUSADO ou REPRODUZINDO" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "estado alterável apenas para NULO, PRONTO ou PAUSADO" + +msgid "changeable only in NULL or READY state" +msgstr "estado alterável apenas para NULO ou PRONTO" + +msgid "Blacklisted files:" +msgstr "Arquivos colocados na lista negra:" + +msgid "Total count: " +msgstr "Contagem total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d arquivo na lista negra" +msgstr[1] "%d arquivos na lista negra" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d plug-in" +msgstr[1] "%d plug-ins" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d entrada na lista negra" +msgstr[1] "%d entradas na lista negra" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d recurso" +msgstr[1] "%d recursos" + +msgid "Print all elements" +msgstr "Exibir todos elementos" + +msgid "Print list of blacklisted files" +msgstr "Exibir lista dos arquivos na lista negra" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Exibir uma lista, legível para máquina, de recursos que o plug-in " +"especificado ou todos os plug-ins fornecem.\n" +" Útil na conexão com mecanismos " +"externos de instalação automática de plug-ins" + +msgid "List the plugin contents" +msgstr "Listar o conteúdo do plugin" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "Verificar se o elemento ou plug-in especificado existe" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Ao verificar se um elemento ou plug-in existe, também verificar se a versão " +"é no mínimo a especificada" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Exibir esquemas URI com suporte, com os elementos que os implementam" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Não foi possível carregar o arquivo do plug-in: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Nenhum elemento ou plug-in \"%s\"\n" + +msgid "Index statistics" +msgstr "Tabela de estatísticas" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Obtida a mensagem #%u do elemento \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Obtida a mensagem #%u do Pad \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Obtida a mensagem #%u do objeto \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Obtida a mensagem #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Obtido o final do fluxo do elemento \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETIQ. ENCONTR. : encontrada pelo elemento \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ETIQ. ENCONTR. : encontrada pelo Pad \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETIQ. ENCONTR. : encontrada pelo objeto \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "ETIQUETA ENCONTRADA\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TOC ENCONTR. : encontrada pelo elemento \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TOC ENCONTR. : encontrada pelo objeto \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "TOC ENCONTRADA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMAÇÃO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVISO: do elemento %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Preparado, esperando o preenchimento do buffer para finalizar...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Preparado, esperando o progresso para finalizar...\n" + +msgid "buffering..." +msgstr "preenchendo buffer..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Preenchimento do buffer completo, definindo a fila de processamento para " +"REPRODUZIR...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" +"Preenchendo buffer, definindo a fila de processamento para PAUSADO...\n" + +msgid "Redistribute latency...\n" +msgstr "Redistribuição de latência...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Definindo estado de %s como requerido por %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Interrupção: Parando a fila de processamento...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Progresso: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Elemento faltando: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Contexto obtido do elemento \"%s\": %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Exibir etiquetas (metadados)" + +msgid "Output TOC (chapters and editions)" +msgstr "Exibir TOC (capítulos e edições)" + +msgid "Output status information and property notifications" +msgstr "Exibir informações de estado e notificações de propriedade" + +msgid "Do not print any progress information" +msgstr "Não imprimir nenhuma informação de progresso" + +msgid "Output messages" +msgstr "Exibir mensagens" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Não exibir informações de status para a propriedade especificada se o modo " +"detalhado de saída estiver ativado (pode ser usado várias vezes)" + +msgid "PROPERTY-NAME" +msgstr "NOME-PROPRIEDADE" + +msgid "Do not install a fault handler" +msgstr "Não instale um manipulador de falhas" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" +"Forçar finalização do fluxo nos elementos fonte antes de desligar a fila de " +"processamento" + +msgid "Gather and print index statistics" +msgstr "Reunir e imprimir a tabela de estatísticas" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ERRO: não foi possível construir a fila de processamento: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ERRO: não foi possível construir a fila de processamento.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "AVISO: fila de processamento com erros: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ERRO: o elemento de \"fila de processamento\" não foi encontrado.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Definindo a fila de processamento para PAUSADO...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ERRO: A fila do processamento não quer pausar.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" +"A fila de processamento está executando e não necessita de PREPARAÇÃO...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "A fila de processamento está PREPARANDO...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ERRO: a fila de processamento não quer preparar.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "A fila de processamento foi PREPARADA...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Definindo a fila de processamento para REPRODUZINDO...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ERRO: a fila de processamento não quer reproduzir.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Finalizar fluxo ao sair habilitado -- Forçando finalização do fluxo na fila " +"de processamento\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" +"Finalizar fluxo ao sair habilitado -- esperando o fim do fluxo após erro\n" + +msgid "Waiting for EOS...\n" +msgstr "Esperando pelo final do fluxo...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Final do fluxo encontrado - parando a fila de processamento...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" +"Interrupção recebida enquanto a finalização do fluxo estava sendo aguardada " +"- parando a fila de processamento...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Um erro ocorreu ao esperar pelo final do fluxo\n" + +msgid "Execution ended after %" +msgstr "Execução finalizada depois de %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Definindo a fila de processamento para PRONTO...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Definindo a fila de processamento para NULO...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Liberando a fila de processamento...\n" + +#~ msgid "bin" +#~ msgstr "Bin" + +#~ msgid "Internal data stream error." +#~ msgstr "Erro interno no fluxo de dados." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Não é possível obter informações do estado de saída do TIPO" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIPO1,TIPO2,..." + +#~ msgid "link without source element" +#~ msgstr "vínculo sem o elemento fonte" + +#~ msgid "link without sink element" +#~ msgstr "vínculo sem o elemento consumidor" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "nenhum elemento para vincular o URI \"%s\" para" + +#~ msgid "maximum" +#~ msgstr "máximo" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Uso: gst-xmllaunch [ elemento.propriedade=valor ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ERRO: a validação do arquivo xml \"%s\" falhou.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "ERRO: nenhum elemento de nível superior na fila de processamento do " +#~ "arquivo \"%s\".\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "AVISO: atualmente há suporte apenas a um elemento de nível superior.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ERRO: não foi possível validar o argumento %d da linha de comando: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "AVISO: o elemento com o nome \"%s\" não foi encontrado.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "" +#~ "Salvar representação da fila de processamento como xml para o ARQUIVO e " +#~ "sair" + +#~ msgid "FILE" +#~ msgstr "ARQUIVO" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Não fixar manipuladores de sinal para SIGUSR1 e SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Exibir trilha de alocação (se habilitado na compilação)" diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 0000000..0122c46 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 0000000..2436c49 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/ro.gmo b/po/ro.gmo new file mode 100644 index 0000000..f960a9a Binary files /dev/null and b/po/ro.gmo differ diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 0000000..a794eaf --- /dev/null +++ b/po/ro.po @@ -0,0 +1,1414 @@ +# Romanian translation for gstreamer +# This file is distributed under the same license as the gstreamer package. +# Lucian Adrian Grijincu , 2010. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.10.29.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2010-08-16 01:10+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" +"X-Generator: Virtaal 0.6.1\n" + +msgid "Print the GStreamer version" +msgstr "Afișează versiunea GStreamer" + +msgid "Make all warnings fatal" +msgstr "Setează toate avertizările ca fiind fatale" + +msgid "Print available debug categories and exit" +msgstr "Afișează categoriile de depanare disponibile și ieși" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Nivelul standard de depanare de la 1 (numai erorile) la 5 (orice) sau 0 fără " +"afișare" + +msgid "LEVEL" +msgstr "NIVEL" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Lista separată de virgule cu perechile nume_categorie:nivel pentru a seta " +"nivelul specific pentru fiecare categorie. Exemplu: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTĂ" + +msgid "Disable colored debugging output" +msgstr "Dezactivează afișarea în culori pentru depanare" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Dezactivează depanarea" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "" +"Activează diagnosticele detaliate pentru încărcarea modulelor de extensie" + +msgid "Colon-separated paths containing plugins" +msgstr "Căile către module de extensie, separate prin două puncte (:)" + +msgid "PATHS" +msgstr "CĂI" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Lista modulelor de preîncărcat, separate prin virgulă, în plus față de lista " +"stocată în variabila de mediu GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "MODULE" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Dezactivează capturarea erorilor de segmentare în timpul încărcării modulelor" + +msgid "Disable updating the registry" +msgstr "Dezactivează actualizarea registrului" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Dezactivează lansarea de procese ajutătoare în timpul scanării registrului" + +msgid "GStreamer Options" +msgstr "Opțiuni GStreamer" + +msgid "Show GStreamer Options" +msgstr "Arată opțiunile GStreamer" + +msgid "Unknown option" +msgstr "Opțiune necunoscută" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer a întâlnit o eroare generală într-o bibliotecă principală." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Dezvoltatorii programului GStreamer au fost prea leneși pentru a atribui un " +"cod acestei erori." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Eroare internă GStreamer: cod neimplementat." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Eroare GStreamer: schimbarea de stare nu a reușit și un element nu pentru a " +"posta un mesaj de eroare corespunzător cu motivul eșecului." + +msgid "Internal GStreamer error: pad problem." +msgstr "Eroare internă GStreamer: problemă de „pad”." + +msgid "Internal GStreamer error: thread problem." +msgstr "Eroare internă GStreamer: problemă cu firele de execuție." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Eroare internă GStreamer: problemă de negociere." + +msgid "Internal GStreamer error: event problem." +msgstr "Eroare internă GStreamer: problemă legată de un eveniment." + +msgid "Internal GStreamer error: seek problem." +msgstr "Eroare internă GStreamer: problemă de derulare." + +msgid "Internal GStreamer error: caps problem." +msgstr "Eroare internă GStreamer: problemă de majuscule." + +msgid "Internal GStreamer error: tag problem." +msgstr "Eroare internă Gstreamer: problemă de etichetă." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Lipsește un modul din instalarea programului GStreamer." + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Eroare internă GStreamer: problemă de ceas." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Această aplicație încearcă să folosească o funcție a programului GStreamer " +"care a fost dezactivată." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer a întâlnit o eroare generală într-o bibliotecă suport." + +msgid "Could not initialize supporting library." +msgstr "Nu se poate inițializa biblioteca suport." + +msgid "Could not close supporting library." +msgstr "Nu se poate închide biblioteca suport." + +msgid "Could not configure supporting library." +msgstr "Nu se poate configura biblioteca suport." + +msgid "Encoding error." +msgstr "" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer a întâlnit o eroare generală de resurse." + +msgid "Resource not found." +msgstr "Resursă negăsită." + +msgid "Resource busy or not available." +msgstr "Resursă ocupată sau nedisponibilă." + +msgid "Could not open resource for reading." +msgstr "Nu se poate deschide resursa pentru citire." + +msgid "Could not open resource for writing." +msgstr "Nu se poate deschide resursa pentru scriere." + +msgid "Could not open resource for reading and writing." +msgstr "Nu se poate deschide resursa pentru citire și scriere." + +msgid "Could not close resource." +msgstr "Nu se poate închide resursa." + +msgid "Could not read from resource." +msgstr "Nu se poate citi din resursă." + +msgid "Could not write to resource." +msgstr "Nu se poate scrie în resursă." + +msgid "Could not perform seek on resource." +msgstr "Nu se poate derula în resursă." + +msgid "Could not synchronize on resource." +msgstr "Nu se poate sincroniza resursa." + +msgid "Could not get/set settings from/on resource." +msgstr "Nu s-au putut obține/defini configurările din/în resursă." + +msgid "No space left on the resource." +msgstr "Nu mai există spațiu liber pe resursă." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Nu mai există spațiu liber pe resursă." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer a întâlnit o eroare generală de flux." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementul nu implementează gestionarea acestui flux. Trimiteți o sesizare de " +"defecțiune." + +msgid "Could not determine type of stream." +msgstr "Nu se poate determina tipul fluxului." + +msgid "The stream is of a different type than handled by this element." +msgstr "Fluxul este de un tip diferit de cel gestionat de acest element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Nu există niciun codec care să poată gestiona acest tip de flux." + +msgid "Could not decode stream." +msgstr "Nu se poate decoda fluxul." + +msgid "Could not encode stream." +msgstr "Nu se poate coda fluxul." + +msgid "Could not demultiplex stream." +msgstr "Nu se poate demultiplexa fluxul." + +msgid "Could not multiplex stream." +msgstr "Nu se poate multiplexa fluxul." + +msgid "The stream is in the wrong format." +msgstr "Fluxul este într-un format greșit." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Fluxul este criptat și decriptarea nu este suportată." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Fluxul este criptat și nu poate fi decriptat deoarece nu s-a oferit o cheie " +"potrivită." + +#, c-format +msgid "No error message for domain %s." +msgstr "Niciun mesaj de eroare pentru domeniul %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Niciun mesaj standard de eroare pentru domeniul %s și codul %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Ceasul selectat nu poate fi utilizat în linia de asamblare." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "titlu" + +msgid "commonly used title" +msgstr "titlu folosit în mod obișnuit" + +msgid "title sortname" +msgstr "nume de sortare al titlului" + +msgid "commonly used title for sorting purposes" +msgstr "titlu folosit în mod obișnuit în scop de sortare" + +msgid "artist" +msgstr "artist" + +msgid "person(s) responsible for the recording" +msgstr "persoana responsabilă pentru înregistrare" + +msgid "artist sortname" +msgstr "nume de sortare al artistului" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "persoana responsabilă pentru înregistrarea în scop de sortare" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album care conține aceste date" + +msgid "album sortname" +msgstr "numele de sortare al albumului" + +msgid "album containing this data for sorting purposes" +msgstr "album care conține aceste date în scop de sortare" + +msgid "album artist" +msgstr "artist album" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Artistul albumului întreg, așa cum ar trebui să fie afișat" + +msgid "album artist sortname" +msgstr "nume de sortare al artistului albumului" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Artistul al albumului întreg, așa cum ar trebui să fie sortat" + +msgid "date" +msgstr "data" + +msgid "date the data was created (as a GDate structure)" +msgstr "data la care au fost create aceste date (ca structură GDate)" + +#, fuzzy +msgid "datetime" +msgstr "data" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data la care au fost create aceste date (ca structură GDate)" + +msgid "genre" +msgstr "gen" + +msgid "genre this data belongs to" +msgstr "genul căruia îi aparțin aceste date" + +msgid "comment" +msgstr "comentariu" + +msgid "free text commenting the data" +msgstr "comentariu liber pentru date" + +msgid "extended comment" +msgstr "comentariu extins" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"text liber care comentează datele în key=valoare sau key[en]=comentariu de la" + +msgid "track number" +msgstr "număr piesă" + +msgid "track number inside a collection" +msgstr "numărul piesei în cadrul unei colecții" + +msgid "track count" +msgstr "număr piesă" + +msgid "count of tracks inside collection this track belongs to" +msgstr "numărul pieselor în colecția din care face parte această piesă" + +msgid "disc number" +msgstr "număr disc" + +msgid "disc number inside a collection" +msgstr "număr disc în cadrul unei colecții" + +msgid "disc count" +msgstr "numărul discurilor" + +msgid "count of discs inside collection this disc belongs to" +msgstr "numărul discurilor în colecția din care face parte acest disc" + +msgid "location" +msgstr "locație" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Originea fișierului media ca un URI (locație unde este stocată versiunea " +"originală a fișierului sau fluxului)" + +msgid "homepage" +msgstr "pagina de pornire" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Pagina de pornire pentru acest fișier media (adică pagina de pornire a " +"artistului sau a filmului)" + +msgid "description" +msgstr "descriere" + +msgid "short text describing the content of the data" +msgstr "text scurt care descrie conținutul acestor date" + +msgid "version" +msgstr "versiune" + +msgid "version of this data" +msgstr "versiunea acestor date" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Codul Internațional Standardizat de Înregistrări - vezi http://www.ifpi.org/" +"isrc/" + +msgid "organization" +msgstr "organizație" + +msgid "copyright" +msgstr "drepturi de autor" + +msgid "copyright notice of the data" +msgstr "notiță asupra drepturilor de autor pentru aceste date" + +msgid "copyright uri" +msgstr "uri pentru drepturile de autor" + +msgid "URI to the copyright notice of the data" +msgstr "URI către notița asupra drepturilor de autor pentru aceste date (URI)" + +#, fuzzy +msgid "encoded by" +msgstr "codor" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "contact" + +msgid "contact information" +msgstr "informații de contact" + +msgid "license" +msgstr "licență" + +msgid "license of data" +msgstr "licența datelor" + +msgid "license uri" +msgstr "uri licență" + +msgid "URI to the license of the data" +msgstr "URI pentru licența acestor date" + +msgid "performer" +msgstr "interpret" + +msgid "person(s) performing" +msgstr "persoana care interpretează" + +msgid "composer" +msgstr "compozitor" + +msgid "person(s) who composed the recording" +msgstr "persoana care a compus înregistrarea" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "durata" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "durata în unitățile de timp ale programului GStreamer (nanosecunde)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codecul cu care au fost stocate datele" + +msgid "video codec" +msgstr "codec video" + +msgid "codec the video data is stored in" +msgstr "codecul cu care au fost stocate datele video" + +msgid "audio codec" +msgstr "codec audio" + +msgid "codec the audio data is stored in" +msgstr "codec cu care au fost stocate datele audio" + +msgid "subtitle codec" +msgstr "codec subtitrare" + +msgid "codec the subtitle data is stored in" +msgstr "codec cu care au fost stocate datele subtitrării" + +msgid "container format" +msgstr "format container" + +msgid "container format the data is stored in" +msgstr "formatul containerului în care sunt stocate datele" + +msgid "bitrate" +msgstr "rata de biți" + +msgid "exact or average bitrate in bits/s" +msgstr "rata de biți exactă sau medie, în biți/s" + +msgid "nominal bitrate" +msgstr "rata de biți nominală" + +msgid "nominal bitrate in bits/s" +msgstr "rata de biți nominală în biți/s" + +msgid "minimum bitrate" +msgstr "rata de biți minimă" + +msgid "minimum bitrate in bits/s" +msgstr "rata de biți minimă în biți/s" + +msgid "maximum bitrate" +msgstr "rata de biți maximă" + +msgid "maximum bitrate in bits/s" +msgstr "rata de biți maximă în biți/s" + +msgid "encoder" +msgstr "codor" + +msgid "encoder used to encode this stream" +msgstr "codorul folosit pentru a coda acest flux" + +msgid "encoder version" +msgstr "versiunea codorului" + +msgid "version of the encoder used to encode this stream" +msgstr "versiunea codorului folosit pentru a coda acest flux" + +msgid "serial" +msgstr "serial" + +msgid "serial number of track" +msgstr "numărul serial al pistei" + +msgid "replaygain track gain" +msgstr "câștigul replaygain al pistei" + +msgid "track gain in db" +msgstr "câștigul în db al pistei" + +msgid "replaygain track peak" +msgstr "vârful replaygain al pistei" + +msgid "peak of the track" +msgstr "vârful pistei" + +msgid "replaygain album gain" +msgstr "câștigul replaygain al albumului" + +msgid "album gain in db" +msgstr "câștigul în db al albumului" + +msgid "replaygain album peak" +msgstr "vârful replaygain al albumului" + +msgid "peak of the album" +msgstr "vârful albumului" + +msgid "replaygain reference level" +msgstr "nivelul de referință replaygain" + +msgid "reference level of track and album gain values" +msgstr "nivelul de referință al valorilor câștigului pentru pistă și album" + +msgid "language code" +msgstr "cod limbă" + +#, fuzzy +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "codul de limbă al acestui flux, conform ISO-639-1" + +#, fuzzy +msgid "language name" +msgstr "cod limbă" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "imagine" + +msgid "image related to this stream" +msgstr "imagine în legătură cu acest flux" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "previzualizare imagine" + +msgid "preview image related to this stream" +msgstr "previzualizarea imaginii în legătură cu acest flux" + +msgid "attachment" +msgstr "atașament" + +msgid "file attached to this stream" +msgstr "fișier atașat la acest flux" + +msgid "beats per minute" +msgstr "bătăi pe minut" + +msgid "number of beats per minute in audio" +msgstr "numărul de bătăi pe minut în partea audio" + +msgid "keywords" +msgstr "cuvinte cheie" + +msgid "comma separated keywords describing the content" +msgstr "cuvinte cheie separate prin virgulă, care descriu conținutul" + +msgid "geo location name" +msgstr "nume geo-locație" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"nume lizibil descriptiv al locației unde a fost înregistrat sau produs acest " +"fișier media" + +msgid "geo location latitude" +msgstr "latitudine geo-locație" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitudinea geo-locației unde a fost înregistrat sau produs acest fișier " +"media conform WGS84 (zero la ecuator, valori negative pentru latitudini " +"sudice)" + +msgid "geo location longitude" +msgstr "longitudine geo-locație" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitudine geo-locației unde a fost înregistrat sau produs acest fișier " +"media în grade conform WGS84 (zero la primul meridian din Greenwich/Marea " +"Britanie, valori negative pentru longitudini vestice)" + +msgid "geo location elevation" +msgstr "altitudine geo-locație" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"altitudinea geo-locației unde a fost înregistrat sau produs acest fișier " +"media conform WGS84 (zero la ecuator, valori negative pentru latitudini " +"sudice) (zero este nivelul mediu al mării)" + +msgid "geo location country" +msgstr "țară geo-locație" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"țara (nume în limba engleză) unde a fost înregistrat sau produs acest fișier " +"media" + +msgid "geo location city" +msgstr "oraș geo-locație" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"oraș (nume în limba engleză) unde a fost înregistrat sau produs acest fișier " +"media" + +msgid "geo location sublocation" +msgstr "sublocație geo-locație" + +#, fuzzy +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"locație în orașul unde a fost înregistrat sau produs acest fișier media (de " +"ex. cartierul)" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "nume geo-locație" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +msgid "geo location movement speed" +msgstr "viteza de circulație a geo-locației" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"viteza de circulație a dispozitivului de capturare în timp ce desfășurau " +"activitățile de captare în m/s" + +msgid "geo location movement direction" +msgstr "direcția de circulație a geo-locației" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indica direcția de mișcare a aparatului de captare cu care a fost " +"înregistrat fișierul media. Acesta este reprezentat ca de grade în virgulă " +"mobilă, 0 înseamnă nord geografic și crește în sensul acelor de ceasornic" + +msgid "geo location capture direction" +msgstr "direcția de captare a geo-locației" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indica direcția în care arăta aparatul de captare cu care a fost înregistrat " +"fișierul media. Acesta este reprezentat ca de grade în virgulă mobilă, 0 " +"înseamnă nord geografic și crește în sensul acelor de ceasornic" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "nume show" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" +"Numele unui show tv/podcast/serial din care acest fișier media face parte" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "arată numele de sortare" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Numele unui show tv/podcast/serial din care acest fișier media face parte, " +"pentru sortare" + +msgid "episode number" +msgstr "număr episod" + +msgid "The episode number in the season the media is part of" +msgstr "Numărul episodului din care acest fișier media face parte" + +msgid "season number" +msgstr "numărul sezon" + +msgid "The season number of the show the media is part of" +msgstr "Numărul sezonului din care acest fișier media face parte" + +msgid "lyrics" +msgstr "versuri" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Versurile fișierului media, frecvent utilizate pentru cântece" + +msgid "composer sortname" +msgstr "nume sortare compozitor" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "persoana care a compus înregistrarea, în scop de sortare" + +msgid "grouping" +msgstr "grupare" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupează media înrudite care se întind pe mai multe piste, ca de ex. " +"diferitele piese ale unui concert. Este un nivel de organizare mai ridicat " +"decât al unei piese, dar mai coborât decât al unui album" + +msgid "user rating" +msgstr "evaluare utilizator" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Evaluarea atribuită de un utilizator. Cu cât este mai mare evaluarea, cu " +"atât mai mult i-a plăcut acelui utilizator" + +msgid "device manufacturer" +msgstr "producătorul dispozitivului" + +msgid "Manufacturer of the device used to create this media" +msgstr "Producătorul dispozitivului utilizat pentru a crea acest fișier media" + +msgid "device model" +msgstr "model dispozitiv" + +msgid "Model of the device used to create this media" +msgstr "Modelul dispozitivului utilizat pentru a crea acest fișier media" + +#, fuzzy +msgid "application name" +msgstr "nume geo-locație" + +#, fuzzy +msgid "Application used to create the media" +msgstr "Modelul dispozitivului utilizat pentru a crea acest fișier media" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "orientare imagine" + +msgid "How the image should be rotated or flipped before display" +msgstr "Cum ar trebui rotită sau întoarsă imaginea înainte de afișare" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "EROARE: de la elementul %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Informații suplimentare pentru depanare:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "nicio proprietate „%s” în elementul „%s”" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" +"nu se poate stabili proprietatea „%s” în elementul „%s” la valoarea „%s”" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nu se poate lega %s la %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "nu se poate lega elementul derivat pentru URI „%s”" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nu se poate lega %s la %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nu se poate lega %s la %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "niciun element „%s”" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nu se pot analiza majusculele „%s”" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "niciun element derivat pentru URI „%s”" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "niciun element sursă pentru URI „%s”" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "containerul gol „%s” specificat, nu este permis" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "niciun container „%s”, se omite" + +msgid "empty pipeline not allowed" +msgstr "linia de asamblare vidă nu este permisă" + +msgid "A lot of buffers are being dropped." +msgstr "Multe zone de memorie tampon sunt abandonate." + +msgid "Internal data flow problem." +msgstr "Problemă internă de flux al datelor." + +msgid "Internal data flow error." +msgstr "Eroare internă de flux al datelor." + +msgid "Internal clock error." +msgstr "Eroare internă de ceas." + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "Filtrare majuscule" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Restricționează capacitățile permise (NULL înseamnă ORICE). Definirea " +"acestei proprietăți preia o referință către obiectul GstCaps furnizat." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Niciun director temporar specificat." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nu am putut crea fișierul temporar „%s”." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nu se poate deschide fișierul „%s” pentru citire." + +msgid "Error while writing to download file." +msgstr "Eroare la scrierea în fișierul descărcat." + +msgid "No file name specified for writing." +msgstr "Niciun nume de fișier specificat pentru scriere." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nu s-a putut deschide fișierul „%s” pentru scriere." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Eroare la închiderea fișierului „%s”." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Eroare în timpul derulării în fișierul „%s”." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Eroare la scrierea fișierului „%s\"." + +msgid "No file name specified for reading." +msgstr "Niciun nume de fișier specificat pentru citire." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nu se pot obține informații despre „%s”." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s” este un director." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Fișierul „%s” este un socket." + +msgid "Failed after iterations as requested." +msgstr "Eșec după numărul de iterații care a fost cerut." + +msgid "caps" +msgstr "majuscule" + +msgid "detected capabilities in stream" +msgstr "capabilități detectate în flux" + +msgid "minimum" +msgstr "minim" + +msgid "force caps" +msgstr "forțează caps" + +msgid "force caps without doing a typefind" +msgstr "forțează caps fără a efectua un typefind" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Fluxul nu conține date." + +msgid "Stream contains no data." +msgstr "Fluxul nu conține date." + +msgid "Implemented Interfaces:\n" +msgstr "Interfețe implementate:\n" + +msgid "readable" +msgstr "se poate citi" + +msgid "writable" +msgstr "se poate scrie" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "se poate controla" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "Fișierele de pe lista neagră:" + +msgid "Total count: " +msgstr "Număr total: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d fișier pe lista neagră" +msgstr[1] "%d fișiere pe lista neagră" +msgstr[2] "%d de fișiere pe lista neagră" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d modul" +msgstr[1] "%d module" +msgstr[2] "%d de module" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d intrare pe lista neagră" +msgstr[1] "%d intrări pe lista neagră" +msgstr[2] "%d de intrări pe lista neagră" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d caracteristică" +msgstr[1] "%d caracteristici" +msgstr[2] "%d de caracteristici" + +msgid "Print all elements" +msgstr "Tipărește toate elementele" + +msgid "Print list of blacklisted files" +msgstr "Tipărește lista de fișiere de pe lista neagră" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Tipărește o listă prelucrabilă de o mașină a caracteristicilor furnizate de " +"modulul de extensie specificat sau de toate modulele.\n" +" Util în conexiunile către mecanisme " +"externe de instalare automată de module de extensie" + +msgid "List the plugin contents" +msgstr "Listează conținutul modulului de extensie" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Tipărește schemele URI suportate, cu elementele pe care le implementează" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nu se poate încărca fișierul modul: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Niciun astfel de element sau modul „%s”\n" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Primit mesajul #%u, de la elementul „%s” (%s):" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Primit mesajul #%u, de la pad-ul „%s:%s” (%s):" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Primit mesajul #%u, de la obiectul „%s” (%s):" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Primit mesajul #%u (%s):" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Primire EOS de la elementul „%s”.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "MARCAJ GĂSIT: găsit de către elementul „%s”.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "MARCAJ GĂSIT : găsit de către pad „%s:%s”.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "MARCAJ GĂSIT : găsit de către obiectul „%s”.\n" + +msgid "FOUND TAG\n" +msgstr "MARCAJ GĂSIT\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "MARCAJ GĂSIT: găsit de către elementul „%s”.\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "MARCAJ GĂSIT : găsit de către obiectul „%s”.\n" + +#, fuzzy +msgid "FOUND TOC\n" +msgstr "MARCAJ GĂSIT\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFORMAȚII:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "AVERTISMENT: de la elementul %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Preîncărcare, se așteaptă terminarea umplerii memoriei tampon...\n" + +#, fuzzy +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Preîncărcare, se așteaptă terminarea umplerii memoriei tampon...\n" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Preîncărcare completă, se setează liniei de asamblare pe REDARE ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Preîncărcare, se setează linia de asamblare pe PAUZĂ ...\n" + +msgid "Redistribute latency...\n" +msgstr "Se redistribuie latența...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Se definește starea la %s după cum a fost cerut de %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Întrerupere: Se oprește linia de asamblare ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "niciun element „%s”" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "AVERTISMENT: de la elementul %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Marcaje de ieșire (cunoscute și ca „metadata”)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Informații asupra stării de ieșire și notificări proprietăți" + +msgid "Do not print any progress information" +msgstr "Nu tipări niciun fel de informații de progres" + +msgid "Output messages" +msgstr "Mesaje de ieșire" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Nu instala un gestionar de erori" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Forțează EOS pe surse înainte de a închide linia de asamblare" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "EROARE: linia de asamblare nu a putut fi construită: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "EROARE: linia de asamblare nu a putut fi construită.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "AVERTISMENT: linia de asamblare conține erori: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "EROARE: elementul „pipeline” (linie de asamblare) nu a fost găsit.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Se setează linia de asamblare pe PAUZĂ ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "EROARE: Linia de asamblare nu vrea să fie pusă pe pauză.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Linia de asamblare este „live” și nu necesită PREÎNCĂRCARE ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Linia de asamblare este PREÎNCĂRCATĂ ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "EROARE: linia de asamblare nu vrea să se preîncarce.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Linia de asamblare se PREÎNCARCĂ ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Se setează linia de asamblare pe REDARE ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "EROARE: linia de asamblare nu vrea să redea.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS la închidere activat -- Se forțează EOS pe linia de asamblare\n" + +#, fuzzy +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS la închidere activat -- Se forțează EOS pe linia de asamblare\n" + +msgid "Waiting for EOS...\n" +msgstr "Se așteaptă EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS primit - se oprește linia de asamblare...\n" + +#, fuzzy +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Întrerupere: Se oprește linia de asamblare ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "A apărut o eroare în timp ce se aștepta EOS\n" + +msgid "Execution ended after %" +msgstr "Execuție terminată după %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Se setează linia de asamblare pe PREGĂTIT ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Se setează linia de asamblare pe NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Se eliberează linia de asamblare...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Eroare internă a fluxului de date." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Nu scoate informații despre stările de TIPUL" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TIP1,TIP2,..." + +#~ msgid "link without source element" +#~ msgstr "legătură fără un element sursă" + +#~ msgid "link without sink element" +#~ msgstr "legătură fără un element derivat" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "niciun element pentru a lega URI „%s” la" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Afișează căile de alocare (dacă s-a activat la momentul compilării)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Utilizare: gst-xmllaunch [ element.property=valoare ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "EROARE: prelucrarea fișierului xml „%s” a eșuat.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "" +#~ "EROARE: niciun element de prim nivel al liniei de asamblare în fișierul " +#~ "„%s”.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "AVERTISMENT: doar un element de nivel de vârf este suportat în acest " +#~ "moment.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "EROARE: nu se poate analiza argumetul %d al liniei de comandă: %s\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "AVERTISMENT: elementul cu numele „%s” nu a fost găsit.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "" +#~ "Salvarea unei reprezentări xml a liniei de asamblare în FIȘIER și ieșire" + +#~ msgid "FILE" +#~ msgstr "FIȘIER" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Nu instala rutine de tratare a semnalului pentru SIGUSR1 și SIGUSR2" diff --git a/po/ru.gmo b/po/ru.gmo new file mode 100644 index 0000000..9ab8e0a Binary files /dev/null and b/po/ru.gmo differ diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..10a7a55 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,1458 @@ +# Translation of gstreamer messages to Russian +# This file is put in the public domain. +# +# Peter Astakhov , 2005. +# Артём Попов , 2009. +# Pavel Maryanov , 2009. +# Yuri Kozlov , 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 05:48+0300\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-Bugs: Report translation errors to the Language-Team address.\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" +"X-Generator: Lokalize 2.0\n" + +msgid "Print the GStreamer version" +msgstr "Вывести версию GStreamer" + +msgid "Make all warnings fatal" +msgstr "Сделать все предупреждения фатальными" + +msgid "Print available debug categories and exit" +msgstr "Вывести доступные категории отладки и выйти" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Уровень отладки по умолчанию: от 1 (только ошибки) до 9 (всё), или 0 (ничего " +"не печатать)" + +msgid "LEVEL" +msgstr "УРОВЕНЬ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Список пар, разделённых запятыми, в формате «имя_категории:уровень» для " +"установки уровней отдельных категорий. Пример: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "СПИСОК" + +msgid "Disable colored debugging output" +msgstr "Отключить цветовую разметку при выводе отладочных сообщений" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Изменить цветовой режим отладочного вывода. Возможные режимы: off, on, " +"disable, auto, unix" + +msgid "Disable debugging" +msgstr "Отключить отладку" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Выводить дополнительную информацию при загрузке модулей" + +msgid "Colon-separated paths containing plugins" +msgstr "Список путей поиска модулей, разделённых двоеточиями" + +msgid "PATHS" +msgstr "ПУТИ" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Список модулей (разделяемых запятыми) для предварительной загрузки, " +"дополняющий список, который содержится в переменной среды GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "МОДУЛИ" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Отключить перехват ошибок сегментации памяти во время загрузки модулей" + +msgid "Disable updating the registry" +msgstr "Отключить обновление реестра" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Отключить создание вспомогательного процесса, пока происходит сканирование " +"реестра" + +msgid "GStreamer Options" +msgstr "Параметры GStreamer" + +msgid "Show GStreamer Options" +msgstr "Показать параметры GStreamer" + +msgid "Unknown option" +msgstr "Неизвестный параметр" + +msgid "GStreamer encountered a general core library error." +msgstr "Обнаружена ошибка в библиотеке ядра GStreamer." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Разработчики GStreamer были слишком ленивыми, чтобы добавить код обработки " +"для этой ошибки." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Внутренняя ошибка GStreamer: функция не реализована." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Ошибка GStreamer: не удалось изменить состояние и некоторым элементам не " +"удалось поместить правильное сообщение о причиной ошибки." + +msgid "Internal GStreamer error: pad problem." +msgstr "Внутренняя ошибка GStreamer: проблема с контактным гнездом." + +msgid "Internal GStreamer error: thread problem." +msgstr "Внутренняя ошибка GStreamer: проблема с нитями." + +msgid "GStreamer error: negotiation problem." +msgstr "Ошибка GStreamer: проблема связки элементов." + +msgid "Internal GStreamer error: event problem." +msgstr "Внутренняя ошибка GStreamer: проблема с событиями." + +msgid "Internal GStreamer error: seek problem." +msgstr "Внутренняя ошибка GStreamer: ошибка позиционирования." + +msgid "Internal GStreamer error: caps problem." +msgstr "Внутренняя ошибка GStreamer: проблема с возможностями." + +msgid "Internal GStreamer error: tag problem." +msgstr "Внутренняя ошибка GStreamer: проблема с тегами." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "В вашей установке GStreamer отсутствует модуль." + +msgid "GStreamer error: clock problem." +msgstr "Ошибка GStreamer: проблема синхронизации." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Приложение пытается использовать функцию GStreamer, которая была выключена." + +msgid "GStreamer encountered a general supporting library error." +msgstr "Обнаружена ошибка в дополнительной библиотеке GStreamer." + +msgid "Could not initialize supporting library." +msgstr "Не удалось инициализировать дополнительную библиотеку." + +msgid "Could not close supporting library." +msgstr "Не удалось закрыть дополнительную библиотеку." + +msgid "Could not configure supporting library." +msgstr "Не удалось настроить дополнительную библиотеку." + +msgid "Encoding error." +msgstr "Ошибка при кодировании." + +msgid "GStreamer encountered a general resource error." +msgstr "Обнаружена общая ошибка ресурса GStreamer." + +msgid "Resource not found." +msgstr "Ресурс не найден." + +msgid "Resource busy or not available." +msgstr "Ресурс занят или недоступен." + +msgid "Could not open resource for reading." +msgstr "Не удалось открыть ресурс для чтения." + +msgid "Could not open resource for writing." +msgstr "Не удалось открыть ресурс для записи." + +msgid "Could not open resource for reading and writing." +msgstr "Не удалось открыть ресурс для чтения и записи." + +msgid "Could not close resource." +msgstr "Не удалось закрыть ресурс." + +msgid "Could not read from resource." +msgstr "Не удалось прочитать из ресурса." + +msgid "Could not write to resource." +msgstr "Не удалось записать в ресурс." + +msgid "Could not perform seek on resource." +msgstr "Не удалось произвести позиционирование в ресурсе." + +msgid "Could not synchronize on resource." +msgstr "Не удалось произвести синхронизацию для ресурса." + +msgid "Could not get/set settings from/on resource." +msgstr "Не удалось получить/установить параметры ресурса." + +msgid "No space left on the resource." +msgstr "В ресурсе нет свободного места." + +msgid "Not authorized to access resource." +msgstr "Неправомочный доступ к ресурсу." + +msgid "GStreamer encountered a general stream error." +msgstr "Обнаружена общая ошибка потока GStreamer." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"В элементе не реализована обработка этого потока. Пожалуйста, сообщите об " +"ошибке." + +msgid "Could not determine type of stream." +msgstr "Не удалось определить тип потока." + +msgid "The stream is of a different type than handled by this element." +msgstr "Тип потока отличается от обрабатываемого этим элементом." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Нет кодека для обработки данного типа потока." + +msgid "Could not decode stream." +msgstr "Не удалось декодировать поток." + +msgid "Could not encode stream." +msgstr "Не удалось закодировать поток." + +msgid "Could not demultiplex stream." +msgstr "Не удалось демультиплексировать поток." + +msgid "Could not multiplex stream." +msgstr "Не удалось мультиплексировать поток." + +msgid "The stream is in the wrong format." +msgstr "Поток имеет неверный формат." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Поток зашифрован и его расшифровка не поддерживается." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Поток зашифрован и не может быть расшифрован, потому что не предоставлен " +"подходящий ключ." + +#, c-format +msgid "No error message for domain %s." +msgstr "Нет сообщения об ошибке для домена %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Нет стандартного сообщения об ошибке для домена %s и кода %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Выбранные часы не могут быть использованы в конвейере." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Ошибка записи кэша реестра в %s: %s" + +msgid "title" +msgstr "название" + +msgid "commonly used title" +msgstr "обычно используемое название" + +msgid "title sortname" +msgstr "название (для сортировки)" + +msgid "commonly used title for sorting purposes" +msgstr "обычно используемое название (для сортировки)" + +msgid "artist" +msgstr "исполнитель" + +msgid "person(s) responsible for the recording" +msgstr "лицо/лица, ответственные за запись" + +msgid "artist sortname" +msgstr "исполнитель (для сортировки)" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "лицо/лица, ответственные за запись (для сортировки)" + +msgid "album" +msgstr "альбом" + +msgid "album containing this data" +msgstr "альбом, содержащий эти данные" + +msgid "album sortname" +msgstr "альбом (для сортировки)" + +msgid "album containing this data for sorting purposes" +msgstr "альбом, содержащий эти данные (для сортировки)" + +msgid "album artist" +msgstr "исполнитель альбома" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Исполнитель всего альбома, который должен отображаться" + +msgid "album artist sortname" +msgstr "исполнитель альбома (для сортировки)" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Исполнитель всего альбома, по которому нужно выполнять сортировку" + +msgid "date" +msgstr "дата" + +msgid "date the data was created (as a GDate structure)" +msgstr "дата создания этих данных (как структура GDate)" + +msgid "datetime" +msgstr "дата-время" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "дата и время создания этих данных (как структура GstDateTime)" + +msgid "genre" +msgstr "жанр" + +msgid "genre this data belongs to" +msgstr "жанр, к которому относятся эти данные" + +msgid "comment" +msgstr "комментарий" + +msgid "free text commenting the data" +msgstr "комментарий к этим данным в свободной форме" + +msgid "extended comment" +msgstr "дополнительный комментарий" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"комментарий к этим данным в свободной форме в виде ключ=значение или " +"ключ[en]=значение" + +msgid "track number" +msgstr "номер дорожки" + +msgid "track number inside a collection" +msgstr "номер дорожки внутри коллекции" + +msgid "track count" +msgstr "количество дорожек" + +msgid "count of tracks inside collection this track belongs to" +msgstr "количество дорожек внутри коллекции, к которой принадлежит эта дорожка" + +msgid "disc number" +msgstr "номер диска" + +msgid "disc number inside a collection" +msgstr "номер диска в коллекции" + +msgid "disc count" +msgstr "количество дисков" + +msgid "count of discs inside collection this disc belongs to" +msgstr "количество дисков в коллекции, к которой принадлежит этот диск" + +msgid "location" +msgstr "местоположение" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Источник данных в виде URI (адрес размещения оригинального файла или потока)" + +msgid "homepage" +msgstr "домашняя страница" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Домашняя страница этого носителя (т.е. страница исполнителя или фильма)" + +msgid "description" +msgstr "описание" + +msgid "short text describing the content of the data" +msgstr "короткое описание содержимого данных" + +msgid "version" +msgstr "версия" + +msgid "version of this data" +msgstr "версия этих данных" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code — см. http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "организация" + +msgid "copyright" +msgstr "авторские права" + +msgid "copyright notice of the data" +msgstr "уведомление об авторских правах на эти данные" + +msgid "copyright uri" +msgstr "URI авторских прав" + +msgid "URI to the copyright notice of the data" +msgstr "URI уведомления об авторских правах" + +msgid "encoded by" +msgstr "Кодирование выполнено" + +msgid "name of the encoding person or organization" +msgstr "Имя человека или название организации, выполнявшей кодировку" + +msgid "contact" +msgstr "контакт" + +msgid "contact information" +msgstr "контактная информация" + +msgid "license" +msgstr "лицензия" + +msgid "license of data" +msgstr "лицензия на эти данные" + +msgid "license uri" +msgstr "URI лицензии" + +msgid "URI to the license of the data" +msgstr "URI лицензии на эти данные" + +msgid "performer" +msgstr "исполнитель" + +msgid "person(s) performing" +msgstr "лицо/лица, исполняющие композицию" + +msgid "composer" +msgstr "композитор" + +msgid "person(s) who composed the recording" +msgstr "лицо/лица, написавшие композицию" + +msgid "conductor" +msgstr "дирижёр" + +msgid "conductor/performer refinement" +msgstr "дирижёр/в обработке" + +msgid "duration" +msgstr "длительность" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "длительность в единицах GStreamer (в наносекундах)" + +msgid "codec" +msgstr "кодек" + +msgid "codec the data is stored in" +msgstr "кодек, в котором сохранены данные" + +msgid "video codec" +msgstr "видео-кодек" + +msgid "codec the video data is stored in" +msgstr "кодек, в котором сохранены видео-данные" + +msgid "audio codec" +msgstr "аудио-кодек" + +msgid "codec the audio data is stored in" +msgstr "кодек, в котором сохранены аудио-данные" + +msgid "subtitle codec" +msgstr "кодек субтитров" + +msgid "codec the subtitle data is stored in" +msgstr "кодек, в котором хранятся субтитры" + +msgid "container format" +msgstr "формат контейнера" + +msgid "container format the data is stored in" +msgstr "формат контейнера, в котором хранятся данные" + +msgid "bitrate" +msgstr "битрейт" + +msgid "exact or average bitrate in bits/s" +msgstr "точный или средний битрейт (бит/с)" + +msgid "nominal bitrate" +msgstr "номинальный битрейт" + +msgid "nominal bitrate in bits/s" +msgstr "номинальный битрейт (бит/с)" + +msgid "minimum bitrate" +msgstr "минимальный битрейт" + +msgid "minimum bitrate in bits/s" +msgstr "минимальный битрейт (бит/с)" + +msgid "maximum bitrate" +msgstr "максимальный битрейт" + +msgid "maximum bitrate in bits/s" +msgstr "максимальный битрейт (бит/с)" + +msgid "encoder" +msgstr "кодировщик" + +msgid "encoder used to encode this stream" +msgstr "кодировщик, используемый для кодирования потока" + +msgid "encoder version" +msgstr "версия кодировщика" + +msgid "version of the encoder used to encode this stream" +msgstr "версия кодировщика, используемого для кодирования потока" + +msgid "serial" +msgstr "серийный номер" + +msgid "serial number of track" +msgstr "серийный номер дорожки" + +msgid "replaygain track gain" +msgstr "уровень ReplayGain для дорожки" + +msgid "track gain in db" +msgstr "уровень усиления дорожки в дБ" + +msgid "replaygain track peak" +msgstr "пик ReplayGain для дорожки" + +msgid "peak of the track" +msgstr "пиковое значение сигнала для дорожки" + +msgid "replaygain album gain" +msgstr "уровень ReplayGain для альбома" + +msgid "album gain in db" +msgstr "уровень усиления альбома в дБ" + +msgid "replaygain album peak" +msgstr "пик ReplayGain для альбома" + +msgid "peak of the album" +msgstr "пиковое значение сигнала для альбома" + +msgid "replaygain reference level" +msgstr "эталонный уровень ReplayGain" + +msgid "reference level of track and album gain values" +msgstr "эталонный уровень для корректировки громкости дорожки и альбома" + +msgid "language code" +msgstr "код языка" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "код языка для этого потока согласно ISO-639-1 или ISO-639-2" + +msgid "language name" +msgstr "название языка" + +msgid "freeform name of the language this stream is in" +msgstr "название языка в произвольном формате этого потока в" + +msgid "image" +msgstr "изображение" + +msgid "image related to this stream" +msgstr "изображение, связанное с этим потоком" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "изображение для предпросмотра" + +msgid "preview image related to this stream" +msgstr "изображение для предпросмотра, связанное с этим потоком" + +msgid "attachment" +msgstr "вложение" + +msgid "file attached to this stream" +msgstr "файл, вложенный в этот поток" + +msgid "beats per minute" +msgstr "ударов в минуту" + +msgid "number of beats per minute in audio" +msgstr "число ударов в минуту для аудио" + +msgid "keywords" +msgstr "ключевые слова" + +msgid "comma separated keywords describing the content" +msgstr "разделяемые запятыми ключевые слова, описывающие содержимое" + +msgid "geo location name" +msgstr "геогр. местоположение" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"описательное название местности, в которой производилась запись или " +"производство данных" + +msgid "geo location latitude" +msgstr "геогр. широта" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"географическая широта местности, в которой производилась запись или " +"производство данных, в градусах в системе координат WGS84 (0 на экваторе, " +"отрицательные значения для южных широт)" + +msgid "geo location longitude" +msgstr "геогр. долгота" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"географическая долгота местности, в которой производилась запись или " +"производство данных, в градусах в системе координат WGS84 (0 на Гринвичском " +"меридиане, отрицательные значения для западных долгот)" + +msgid "geo location elevation" +msgstr "геогр. высота" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"географическая высота местности, в которой производилась запись или " +"производство данных, в метрах согласно системе координат WGS84 (0 на среднем " +"уровне моря)" + +msgid "geo location country" +msgstr "страна" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"страна (на английском), в которой производилась запись или производство " +"данных" + +msgid "geo location city" +msgstr "город" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"город (на английском), в котором производилась запись или производство данных" + +msgid "geo location sublocation" +msgstr "доп. к местоположению" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"место в городе, в котором производилась запись или производство данных " +"(например, район)" + +msgid "geo location horizontal error" +msgstr "ошибка в геогр. местоположении" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "ожидаемая ошибка определения геогр. местоположения (в метрах)" + +msgid "geo location movement speed" +msgstr "скорость движения" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "скорость движения устройства съёмки в при выполнении съёмки в м/c" + +msgid "geo location movement direction" +msgstr "направление движения" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"направление движения устройства съёмки. Задаётся в градусах числом с " +"плавающей точкой, 0 означает географический север и дальше по часовой стрелке" + +msgid "geo location capture direction" +msgstr "направление съёмки" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"направление, куда указывало устройство съёмки. Задаётся в градусах числом с " +"плавающей точкой, 0 означает географический север и дальше по часовой стрелке" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "название передачи" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Название тв/подкаста/передачи на носителе" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "короткое название передачи" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Название тв/подкаста/передачи на носителе (для сортировки)" + +msgid "episode number" +msgstr "номер эпизода" + +msgid "The episode number in the season the media is part of" +msgstr "Номер эпизода в сезоне на носителе" + +msgid "season number" +msgstr "номер сезона" + +msgid "The season number of the show the media is part of" +msgstr "Номер сезона на носителе" + +msgid "lyrics" +msgstr "стихи" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Стихи песен на носителе" + +msgid "composer sortname" +msgstr "автор (для сортировки)" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "лицо/лица, ответственные за запись (для сортировки)" + +msgid "grouping" +msgstr "группировка" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Группы носителей с несколькими дорожками, например, различные части " +"концерта. Это больше чем дорожка, но меньше чем альбом" + +msgid "user rating" +msgstr "пользовательская оценка" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Оценка, данная пользователем. Чем выше оценка, тем большему числу " +"пользователей понравился носитель" + +msgid "device manufacturer" +msgstr "производитель устройства" + +msgid "Manufacturer of the device used to create this media" +msgstr "Производитель устройства, на котором создан носитель" + +msgid "device model" +msgstr "модель устройства" + +msgid "Model of the device used to create this media" +msgstr "Модель устройства, на котором создан носитель" + +msgid "application name" +msgstr "имя приложения" + +msgid "Application used to create the media" +msgstr "Приложение с помощью которого создан носитель" + +msgid "application data" +msgstr "данные приложения" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Произвольные данные приложения для преобразования в данные носителя" + +msgid "image orientation" +msgstr "ориентация изображения" + +msgid "How the image should be rotated or flipped before display" +msgstr "Влияет на вращение или поворот изображения перед показом" + +msgid "publisher" +msgstr "издатель" + +msgid "Name of the label or publisher" +msgstr "Название студии или издателя" + +msgid "interpreted-by" +msgstr "в обработке" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Информация о людях, которые сделали ремикс или подобные обработки" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Номер ноты midi на аудио дорожке." + +msgid "private-data" +msgstr "private-data" + +msgid "Private data" +msgstr "Частная информация" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Для протокола «%s» не найден URI обработчика" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Схема URI «%s» не поддерживается" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ОШИБКА: из элемента %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Дополнительная отладочная информация:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "соединение без источника [приёмник=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "соединение без приёмника [источник=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "свойство «%s» не найдено для элемента «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "не удалось установить свойство «%s» элемента «%s» в значение «%s»" + +msgid "Delayed linking failed." +msgstr "Ошибка при отложенной компоновке." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "не удалось соединить %s и %s, %s не поддерживает возможности %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"не удалось соединить %s и %s, ни один из них не поддерживает возможности %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "не удалось соединить %s и %s с возможностями %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "не удалось соединить %s и %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "элемент «%s» не найден" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "неожиданная ссылка «%s» — игнорируется" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "неожиданная ссылка на контактное гнездо «%s» — игнорируется" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "не удалось обработать возможности «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "нет элемента-приёмника для URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "нет элемента-источника для URI «%s»" + +msgid "syntax error" +msgstr "синтаксическая ошибка" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "указанный пустой контейнер «%s» недопустим" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "не найден контейнер «%s», распаковка элементов" + +msgid "empty pipeline not allowed" +msgstr "пустой конвейер недопустим" + +msgid "A lot of buffers are being dropped." +msgstr "Многое из буфера было отброшено." + +msgid "Internal data flow problem." +msgstr "Внутренняя проблема передачи данных." + +msgid "Internal data flow error." +msgstr "Внутренняя ошибка передачи данных." + +msgid "Internal clock error." +msgstr "Внутренняя ошибка синхронизации." + +msgid "Failed to map buffer." +msgstr "Ошибка при отображении (map) буфера." + +msgid "Filter caps" +msgstr "Фильтровать возможности" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Ограничить разрешённые возможности (NULL равносильно ANY). Установка этого " +"свойства увеличивает количество ссылок для предоставленного объекта GstCaps." + +msgid "Caps Change Mode" +msgstr "Режим изменения возможностей" + +msgid "Filter caps change behaviour" +msgstr "Фильтровать поведение изменения возможностей" + +msgid "No Temp directory specified." +msgstr "Не задана временный (Temp) каталог." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Не удалось создать временный файл «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Не удалось открыть файл «%s» для чтения." + +msgid "Error while writing to download file." +msgstr "Ошибка записи загружаемого файла." + +msgid "No file name specified for writing." +msgstr "Не указано имя файла для записи." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Не удалось открыть для записи файл «%s»." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Ошибка закрытия файла «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Ошибка позиционирования в файле «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Ошибка записи в файл «%s»." + +msgid "No file name specified for reading." +msgstr "Не указано имя файла для чтения." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Не удалось получить сведения для «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» является каталогом." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Файл «%s» является сокетом." + +msgid "Failed after iterations as requested." +msgstr "Сбой после итераций, согласно запросу." + +msgid "caps" +msgstr "возможности" + +msgid "detected capabilities in stream" +msgstr "обнаруженные возможности потока" + +msgid "minimum" +msgstr "минимум" + +msgid "force caps" +msgstr "форсировать возможности" + +msgid "force caps without doing a typefind" +msgstr "форсировать возможности без выполнения typefind" + +msgid "Stream doesn't contain enough data." +msgstr "Поток содержит недостаточно данных." + +msgid "Stream contains no data." +msgstr "Поток не содержит данных." + +msgid "Implemented Interfaces:\n" +msgstr "Реализованные интерфейсы:\n" + +msgid "readable" +msgstr "считываемый" + +msgid "writable" +msgstr "записываемый" + +msgid "deprecated" +msgstr "устаревший" + +msgid "controllable" +msgstr "контролируемый" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "может быть равно состоянию NULL, READY, PAUSED или PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "может быть равно только состоянию NULL, READY или PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "может быть равно только состоянию NULL или READY" + +msgid "Blacklisted files:" +msgstr "Файлы из чёрного списка:" + +msgid "Total count: " +msgstr "Общее количество: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d файл в чёрном списке" +msgstr[1] "%d файла в чёрном списке" +msgstr[2] "%d файлов в чёрном списке" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d модуль" +msgstr[1] "%d модуля" +msgstr[2] "%d модулей" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d элемент в чёрном списке" +msgstr[1] "%d элемента в чёрном списке" +msgstr[2] "%d элементов в чёрном списке" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d функция" +msgstr[1] "%d функции" +msgstr[2] "%d функций" + +msgid "Print all elements" +msgstr "Вывести все элементы" + +msgid "Print list of blacklisted files" +msgstr "Вывести файлы из чёрного списка" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Вывести машинно-читаемый список функций, предоставляемых указанным модулем " +"или модулями.\n" +" Полезно для подключения внешних " +"механизмов автоматической установки модулей" + +msgid "List the plugin contents" +msgstr "Вывести содержимое модуля" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Список типов элементов (называемых klass), разделяемых «/» (без сортировки)." + +msgid "Check if the specified element or plugin exists" +msgstr "Проверьте, что указанный элемент или модуль существует" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"При проверке существования элемента или модуля также проверьте, чтобы его " +"версия была не старее указанной" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Вывести поддерживаемые схемы URI для элементов, которые их используют" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Не удалось загрузить файл модуля: «%s»\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Модуль или элемент «%s» не найден\n" + +msgid "Index statistics" +msgstr "Индексная статистика" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Получено сообщение #%u от элемента «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Получено сообщение #%u от контактного гнезда «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Получено сообщение #%u от объекта «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Получено сообщение #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Получен маркер EOS («конец потока») от элемента «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "НАЙДЕН ТЕГ: найден элементом «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "НАЙДЕН ТЕГ: найден контактным гнездом «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "НАЙДЕН ТЕГ: найден объектом «%s».\n" + +msgid "FOUND TAG\n" +msgstr "НАЙДЕН ТЕГ\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "НАЙДЕН TOC: найден элементом «%s».\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "НАЙДЕН TOC: найден объектом «%s».\n" + +msgid "FOUND TOC\n" +msgstr "НАЙДЕН TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"ИНФОРМАЦИЯ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: от элемента %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Конвейер подготовлен, ожидается завершение буферизации…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Время предпуска, ожидается завершение процесса…\n" + +msgid "buffering..." +msgstr "буферизация…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Буферизация завершена, конвейер переведён в состояние PLAYING…\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Идёт буферизация, конвейер переведён в состояние PAUSED…\n" + +msgid "Redistribute latency...\n" +msgstr "Перераспределение латентности…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Устанавливается состояние %s, запрошенное %s…\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Прерывание: Остановка конвейера…\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Ход выполнения: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Элемент отсутствует: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Получен контекст из элемента «%s»: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Выводить теги (метаданные)" + +msgid "Output TOC (chapters and editions)" +msgstr "Выводить TOC (главы и редакции)" + +msgid "Output status information and property notifications" +msgstr "Выводить информацию о состоянии и уведомления о свойствах" + +msgid "Do not print any progress information" +msgstr "Не выводить информацию о ходе выполнения" + +msgid "Output messages" +msgstr "Выводить сообщения" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Не выводить информацию о состоянии для указанного свойства, если включена " +"детализация вывода (можно указывать несколько раз)" + +msgid "PROPERTY-NAME" +msgstr "ИМЯ-СВОЙСТВА" + +msgid "Do not install a fault handler" +msgstr "Не устанавливать обработчик ошибок" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Выдать EOS в источники перед закрытием конвейера" + +msgid "Gather and print index statistics" +msgstr "Собрать и вывести индексную статистику" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ОШИБКА: не удалось собрать конвейер: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ОШИБКА: не удалось собрать конвейер.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: ошибочный конвейер: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ОШИБКА: не найден элемент «pipeline».\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Установка конвейера в состояние PAUSED…\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ОШИБКА: Конвейер не хочет становиться на паузу.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Конвейер работает и не требует состояния PREROLL…\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Подготовка конвейера (PREROLL)…\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ОШИБКА: конвейер не хочет подготавливаться (PREROLL).\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Конвейер подготовлен (PREROLLED)…\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Установка конвейера в состояние PLAYING…\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ОШИБКА: конвейер не хочет воспроизводить.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Включён EOS при закрытии — Выдача EOS в конвейер\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Включён EOS при закрытии — ожидание EOS после ошибки\n" + +msgid "Waiting for EOS...\n" +msgstr "Ожидание EOS…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Получен EOS — остановка конвейера…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Прерывание во время ожидания EOS — остановка конвейера…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Во время ожидания EOS произошла ошибка\n" + +msgid "Execution ended after %" +msgstr "Выполнение окончено после %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Установка конвейера в состояние READY…\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Установка конвейера в состояние NULL…\n" + +msgid "Freeing pipeline ...\n" +msgstr "Освобождение конвейера…\n" + +#~ msgid "bin" +#~ msgstr "контейнер" + +#~ msgid "Internal data stream error." +#~ msgstr "Внутренняя ошибка потока данных." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Не выводить информацию о состоянии ТИПА" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "ТИП1, ТИП2,…" + +#~ msgid "link without source element" +#~ msgstr "попытка соединения без элемента-источника" + +#~ msgid "link without sink element" +#~ msgstr "попытка соединения без элемента-приёмника" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "нет элемента, который можно было бы присоединить к URI «%s»" + +#~ msgid "maximum" +#~ msgstr "максимум" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Использование: gst-xmllaunch <файл.xml> [ элемент.свойство=значение...]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ОШИБКА: ошибка разбора xml-файла «%s».\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "ОШИБКА: в файле «%s» отсутствует главный элемент конвейера.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "ПРЕДУПРЕЖДЕНИЕ: в данный момент поддерживается только один главный " +#~ "элемент.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "ОШИБКА: ошибка обработки аргумента командной строки %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: элемент с именем «%s» не найден.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Сохранить конвейер в XML-файл и выйти" + +#~ msgid "FILE" +#~ msgstr "ФАЙЛ" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Не устанавливать обработчики сигналов SIGUSR1 и SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Вывести трассировку выделения памяти (если включено при сборке)" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Ошибка повторного сканирования реестра %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Ошибка повторного сканирования реестра %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Внутренняя ошибка GStreamer: не удалось сменить состояние." + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Ошибка записи в дескриптор файла «%d»." + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "Дескриптор файла «%d» недействителен." + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "Освобождение конвейера...\n" + +#~ msgid "original location of file as a URI" +#~ msgstr "оригинальное расположение файла в виде URI" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Отключить специфические команды процессора" + +#~ msgid "SCHEDULER" +#~ msgstr "ПЛАНИРОВЩИК" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "список путей для загрузки расширений (разделенных '%s')" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Планировщик для использования (по умолчанию - '%s')" + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "" +#~ "Внутренняя ошибка GStreamer: проблема с планировщиком. Отправьте " +#~ "сообщение об ошибке." + +#~ msgid "" +#~ "Execution ended after %s iterations (sum %s ns, average %s ns, min %s ns, " +#~ "max %s ns).\n" +#~ msgstr "" +#~ "Выполнение завершилось после %s итераций (всего %s ns, среднее %s ns, " +#~ "минимум %s ns, максимум %s ns).\n" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Все равно пытаюсь запустить.\n" + +#~ msgid "Added plugin %s with %d %s.\n" +#~ msgstr "Добавлено расширение %s с %d %s.\n" + +#~ msgid "Added path %s to %s \n" +#~ msgstr "Добавлен путь %s к %s \n" + +#~ msgid "Trying to load %s ...\n" +#~ msgstr "Пытаюсь загрузить %s ...\n" + +#~ msgid "Error loading %s\n" +#~ msgstr "Ошибка загрузки %s\n" + +#~ msgid "Loaded %d plugins with %d %s.\n" +#~ msgstr "Загружено %d расширений с %d %s.\n" diff --git a/po/rw.gmo b/po/rw.gmo new file mode 100644 index 0000000..b277f7f Binary files /dev/null and b/po/rw.gmo differ diff --git a/po/rw.po b/po/rw.po new file mode 100644 index 0000000..2bc1ec8 --- /dev/null +++ b/po/rw.po @@ -0,0 +1,1640 @@ +# Kinyarwanda translations for gstreamer package. +# Copyright (C) 2005 Free Software Foundation, Inc. +# Steve Murphy , 2005. +# Steve performed initial rough translation from compendium built from translations provided by the following translators: +# Philibert Ndandali , 2005. +# Viateur MUGENZI , 2005. +# Noëlla Mupole , 2005. +# Carole Karema , 2005. +# JEAN BAPTISTE NGENDAHAYO , 2005. +# Augustin KIBERWA , 2005. +# Donatien NSENGIYUMVA , 2005. +# Antoine Bigirimana , 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.8.8\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2005-04-04 10:55-0700\n" +"Last-Translator: Steven Michael Murphy \n" +"Language-Team: Kinyarwanda \n" +"Language: rw\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" + +#, fuzzy +msgid "Print the GStreamer version" +msgstr "i Verisiyo" + +#, fuzzy +msgid "Make all warnings fatal" +msgstr "Byose Iburira" + +#, fuzzy +msgid "Print available debug categories and exit" +msgstr "Bihari Kosora amakosa Ibyiciro Na Gusohoka" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Kosora amakosa urwego Bivuye 1. Ikosa Kuri 5 Cyangwa 0 kugirango Oya " +"Ibisohoka" + +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.WriterObject.Table.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.WriterObject.Frame.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.WriterObject.Graphic.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Calc.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Draw.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Chart.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Image.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Formula.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.Impress.Settings.Level.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Insert.Caption.OfficeObject.OLEMisc.Settings.Level.text +#, fuzzy +msgid "LEVEL" +msgstr "urwego" + +#, fuzzy +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Urutonde Bya Izina ry'icyiciro urwego Kuri Gushyiraho Intera kugirango i " +"Ibyiciro Urugero 5 3." + +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....DefaultFont.List.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....DefaultFontCJK.List.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....DefaultFontCTL.List.text +#, fuzzy +msgid "LIST" +msgstr "Urutonde" + +#, fuzzy +msgid "Disable colored debugging output" +msgstr "Ibisohoka" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "" + +#, fuzzy +msgid "Enable verbose plugin loading diagnostics" +msgstr "Itangira..." + +msgid "Colon-separated paths containing plugins" +msgstr "" + +# offmgr/source\offapp\dialog\treeopt.src:RID_OFADLG_OPTIONS_TREE_PAGES.SID_GENERAL_OPTIONS.8.text +#, fuzzy +msgid "PATHS" +msgstr "Inzira" + +#, fuzzy +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "Urutonde Bya Kuri in Guteranya+ Kuri i Urutonde in IMPINDURAGACIRO" + +msgid "PLUGINS" +msgstr "" + +#, fuzzy +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Bya Itangira..." + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "" + +#, fuzzy +msgid "Show GStreamer Options" +msgstr "i Verisiyo" + +msgid "Unknown option" +msgstr "" + +#, fuzzy +msgid "GStreamer encountered a general core library error." +msgstr "a Rusange Isomero Ikosa" + +#, fuzzy +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "Kuri Kugenera... Ikosa ITEGEKONGENGA Kuri iyi Ikosa IDOSIYE a" + +#, fuzzy +msgid "Internal GStreamer error: code not implemented." +msgstr "Ikosa ITEGEKONGENGA OYA Idosiye a" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +#, fuzzy +msgid "Internal GStreamer error: pad problem." +msgstr "Ikosa Idosiye a" + +#, fuzzy +msgid "Internal GStreamer error: thread problem." +msgstr "Ikosa Urudodo Idosiye a" + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Ikosa Idosiye a" + +#, fuzzy +msgid "Internal GStreamer error: event problem." +msgstr "Ikosa Icyabaye Idosiye a" + +#, fuzzy +msgid "Internal GStreamer error: seek problem." +msgstr "Ikosa Idosiye a" + +#, fuzzy +msgid "Internal GStreamer error: caps problem." +msgstr "Ikosa Inyuguti nkuru Idosiye a" + +#, fuzzy +msgid "Internal GStreamer error: tag problem." +msgstr "Ikosa Itagi: Idosiye a" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Ikosa Idosiye a" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +#, fuzzy +msgid "GStreamer encountered a general supporting library error." +msgstr "a Rusange Isomero Ikosa" + +#, fuzzy +msgid "Could not initialize supporting library." +msgstr "OYA gutangiza Isomero" + +#, fuzzy +msgid "Could not close supporting library." +msgstr "OYA Gufunga Isomero" + +#, fuzzy +msgid "Could not configure supporting library." +msgstr "OYA Gufunga Isomero" + +msgid "Encoding error." +msgstr "" + +#, fuzzy +msgid "GStreamer encountered a general resource error." +msgstr "a Rusange Isomero Ikosa" + +#, fuzzy +msgid "Resource not found." +msgstr "OYA Byabonetse" + +#, fuzzy +msgid "Resource busy or not available." +msgstr "Irahuze Cyangwa OYA Bihari" + +#, fuzzy +msgid "Could not open resource for reading." +msgstr "OYA Gufungura kugirango" + +#, fuzzy +msgid "Could not open resource for writing." +msgstr "OYA Gufungura kugirango" + +#, fuzzy +msgid "Could not open resource for reading and writing." +msgstr "OYA Gufungura kugirango Na" + +#, fuzzy +msgid "Could not close resource." +msgstr "OYA Gufunga" + +#, fuzzy +msgid "Could not read from resource." +msgstr "OYA Gusoma Bivuye" + +#, fuzzy +msgid "Could not write to resource." +msgstr "OYA Kwandika Kuri" + +#, fuzzy +msgid "Could not perform seek on resource." +msgstr "OYA ku" + +#, fuzzy +msgid "Could not synchronize on resource." +msgstr "OYA Kuringaniza ku" + +#, fuzzy +msgid "Could not get/set settings from/on resource." +msgstr "OYA Kubona Gushyiraho Amagenamiterere Bivuye ku" + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "OYA Kwandika Kuri" + +#, fuzzy +msgid "GStreamer encountered a general stream error." +msgstr "a Rusange Isomero Ikosa" + +#, fuzzy +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Bya iyi IDOSIYE a" + +#, fuzzy +msgid "Could not determine type of stream." +msgstr "OYA Ubwoko Bya" + +#, fuzzy +msgid "The stream is of a different type than handled by this element." +msgstr "ni Bya a Ubwoko ku iyi Ikigize:" + +#, fuzzy +msgid "There is no codec present that can handle the stream's type." +msgstr "ni Oya i Ubwoko" + +#, fuzzy +msgid "Could not decode stream." +msgstr "OYA" + +#, fuzzy +msgid "Could not encode stream." +msgstr "OYA" + +#, fuzzy +msgid "Could not demultiplex stream." +msgstr "OYA" + +#, fuzzy +msgid "Could not multiplex stream." +msgstr "OYA" + +#, fuzzy +msgid "The stream is in the wrong format." +msgstr "ni Bya i Imiterere" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, fuzzy, c-format +msgid "No error message for domain %s." +msgstr "Ikosa Ubutumwa kugirango Urwego" + +#, fuzzy, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Bisanzwe Ikosa Ubutumwa kugirango Urwego Na ITEGEKONGENGA" + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "umutwe" + +#, fuzzy +msgid "commonly used title" +msgstr "Umutwe" + +msgid "title sortname" +msgstr "" + +#, fuzzy +msgid "commonly used title for sorting purposes" +msgstr "Umutwe" + +#, fuzzy +msgid "artist" +msgstr "Umuhanzi" + +#, fuzzy +msgid "person(s) responsible for the recording" +msgstr "S Nshingwabikorwa kugirango i" + +msgid "artist sortname" +msgstr "" + +#, fuzzy +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "S Nshingwabikorwa kugirango i" + +msgid "album" +msgstr "" + +#, fuzzy +msgid "album containing this data" +msgstr "iyi Ibyatanzwe" + +msgid "album sortname" +msgstr "" + +#, fuzzy +msgid "album containing this data for sorting purposes" +msgstr "iyi Ibyatanzwe" + +#, fuzzy +msgid "album artist" +msgstr "Umuhanzi" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "Itariki" + +#, fuzzy +msgid "date the data was created (as a GDate structure)" +msgstr "Itariki i Ibyatanzwe Byaremwe in Kalindari Iminsi" + +#, fuzzy +msgid "datetime" +msgstr "Itariki" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "Itariki i Ibyatanzwe Byaremwe in Kalindari Iminsi" + +msgid "genre" +msgstr "" + +#, fuzzy +msgid "genre this data belongs to" +msgstr "iyi Ibyatanzwe Kuri" + +# padmin/source\padialog.src:RID_TXT_TESTPAGE_COMMENT.text +#, fuzzy +msgid "comment" +msgstr "Icyo wongeraho" + +#, fuzzy +msgid "free text commenting the data" +msgstr "Kigenga Umwandiko i Ibyatanzwe" + +# padmin/source\padialog.src:RID_TXT_TESTPAGE_COMMENT.text +#, fuzzy +msgid "extended comment" +msgstr "Icyo wongeraho" + +#, fuzzy +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "Kigenga Umwandiko i Ibyatanzwe" + +#, fuzzy +msgid "track number" +msgstr "Umubare" + +#, fuzzy +msgid "track number inside a collection" +msgstr "Umubare Mo Imbere a" + +#, fuzzy +msgid "track count" +msgstr "IBARA" + +#, fuzzy +msgid "count of tracks inside collection this track belongs to" +msgstr "IBARA Bya Mo Imbere iyi Kuri" + +#, fuzzy +msgid "disc number" +msgstr "DISIKI Umubare" + +#, fuzzy +msgid "disc number inside a collection" +msgstr "DISIKI Umubare Mo Imbere a" + +#, fuzzy +msgid "disc count" +msgstr "DISIKI IBARA" + +#, fuzzy +msgid "count of discs inside collection this disc belongs to" +msgstr "IBARA Bya Mo Imbere iyi DISIKI Kuri" + +msgid "location" +msgstr "Inturo" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "Isobanuramiterere" + +#, fuzzy +msgid "short text describing the content of the data" +msgstr "Umwandiko i Ibikubiyemo Bya i Ibyatanzwe" + +# goodies/source\filter.vcl\eps\dlgeps.src:DLG_EXPORT_EPS.GRP_VERSION.text +#, fuzzy +msgid "version" +msgstr "Verisiyo" + +#, fuzzy +msgid "version of this data" +msgstr "Verisiyo Bya iyi Ibyatanzwe" + +msgid "ISRC" +msgstr "" + +#, fuzzy +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "HTTP www org" + +#, fuzzy +msgid "organization" +msgstr "Ihuzagahunda" + +#, fuzzy +msgid "copyright" +msgstr "Uburenganzira bw'umuhimbyi" + +#, fuzzy +msgid "copyright notice of the data" +msgstr "Uburenganzira bw'umuhimbyi Bya i Ibyatanzwe" + +#, fuzzy +msgid "copyright uri" +msgstr "Uburenganzira bw'umuhimbyi" + +#, fuzzy +msgid "URI to the copyright notice of the data" +msgstr "Uburenganzira bw'umuhimbyi Bya i Ibyatanzwe" + +msgid "encoded by" +msgstr "" + +msgid "name of the encoding person or organization" +msgstr "" + +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla Communicator client code, released +# March 31, 1998. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998-1999 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +# Box Headings +#, fuzzy +msgid "contact" +msgstr "Umuntu" + +#, fuzzy +msgid "contact information" +msgstr "Umuntu Ibisobanuro" + +msgid "license" +msgstr "" + +#, fuzzy +msgid "license of data" +msgstr "Bya Ibyatanzwe" + +#, fuzzy +msgid "license uri" +msgstr "Bya Ibyatanzwe" + +#, fuzzy +msgid "URI to the license of the data" +msgstr "Bya Ibyatanzwe" + +msgid "performer" +msgstr "" + +#, fuzzy +msgid "person(s) performing" +msgstr "S" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "S Nshingwabikorwa kugirango i" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....AgendaType.Duration.text +#, fuzzy +msgid "duration" +msgstr "Igihe- ngombwa" + +#, fuzzy +msgid "length in GStreamer time units (nanoseconds)" +msgstr "Uburebure in Igihe" + +msgid "codec" +msgstr "" + +#, fuzzy +msgid "codec the data is stored in" +msgstr "i Ibyatanzwe ni in" + +#, fuzzy +msgid "video codec" +msgstr "Videwo..." + +#, fuzzy +msgid "codec the video data is stored in" +msgstr "i Videwo... Ibyatanzwe ni in" + +msgid "audio codec" +msgstr "" + +#, fuzzy +msgid "codec the audio data is stored in" +msgstr "i Ibyatanzwe ni in" + +#, fuzzy +msgid "subtitle codec" +msgstr "Videwo..." + +#, fuzzy +msgid "codec the subtitle data is stored in" +msgstr "i Videwo... Ibyatanzwe ni in" + +#, fuzzy +msgid "container format" +msgstr "Umuntu Ibisobanuro" + +#, fuzzy +msgid "container format the data is stored in" +msgstr "i Ibyatanzwe ni in" + +msgid "bitrate" +msgstr "" + +#, fuzzy +msgid "exact or average bitrate in bits/s" +msgstr "NYACYO Cyangwa Impuzandengo in S" + +#, fuzzy +msgid "nominal bitrate" +msgstr "SHINGIRO" + +#, fuzzy +msgid "nominal bitrate in bits/s" +msgstr "SHINGIRO in S" + +#, fuzzy +msgid "minimum bitrate" +msgstr "Gito" + +#, fuzzy +msgid "minimum bitrate in bits/s" +msgstr "Gito in S" + +#, fuzzy +msgid "maximum bitrate" +msgstr "Kinini" + +#, fuzzy +msgid "maximum bitrate in bits/s" +msgstr "Kinini in S" + +msgid "encoder" +msgstr "" + +#, fuzzy +msgid "encoder used to encode this stream" +msgstr "Kuri iyi" + +#, fuzzy +msgid "encoder version" +msgstr "Verisiyo" + +#, fuzzy +msgid "version of the encoder used to encode this stream" +msgstr "Verisiyo Bya i Kuri iyi" + +msgid "serial" +msgstr "" + +#, fuzzy +msgid "serial number of track" +msgstr "Umubare Bya" + +msgid "replaygain track gain" +msgstr "" + +#, fuzzy +msgid "track gain in db" +msgstr "in DB" + +msgid "replaygain track peak" +msgstr "" + +#, fuzzy +msgid "peak of the track" +msgstr "Bya i" + +msgid "replaygain album gain" +msgstr "" + +#, fuzzy +msgid "album gain in db" +msgstr "in DB" + +msgid "replaygain album peak" +msgstr "" + +#, fuzzy +msgid "peak of the album" +msgstr "Bya i" + +msgid "replaygain reference level" +msgstr "" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +msgid "language name" +msgstr "" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +#, fuzzy +msgid "image related to this stream" +msgstr "Kuri iyi" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +#, fuzzy +msgid "file attached to this stream" +msgstr "Kuri iyi" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +#, fuzzy +msgid "comma separated keywords describing the content" +msgstr "Umwandiko i Ibikubiyemo Bya i Ibyatanzwe" + +#, fuzzy +msgid "geo location name" +msgstr "Inturo" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +#, fuzzy +msgid "geo location country" +msgstr "Inturo" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location city" +msgstr "Inturo" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location sublocation" +msgstr "Inturo" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "Inturo" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "Inturo" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "Inturo" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "Inturo" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#, fuzzy +msgid "episode number" +msgstr "DISIKI Umubare" + +msgid "The episode number in the season the media is part of" +msgstr "" + +#, fuzzy +msgid "season number" +msgstr "DISIKI Umubare" + +msgid "The season number of the show the media is part of" +msgstr "" + +msgid "lyrics" +msgstr "" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "S Nshingwabikorwa kugirango i" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....AgendaType.Duration.text +#, fuzzy +msgid "user rating" +msgstr "Igihe- ngombwa" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "Verisiyo Bya i Kuri iyi" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "Verisiyo Bya i Kuri iyi" + +#, fuzzy +msgid "application name" +msgstr "Inturo" + +#, fuzzy +msgid "Application used to create the media" +msgstr "Verisiyo Bya i Kuri iyi" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, fuzzy, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "Kosora amakosa Ibisobanuro" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, fuzzy, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "Oya indangakintu in Ikigize:" + +#, fuzzy, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "OYA Gushyiraho indangakintu in Ikigize: Kuri" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "OYA Ihuza Kuri" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "OYA Ihuza Ikigize: kugirango" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "OYA Ihuza Kuri" + +#, fuzzy, c-format +msgid "could not link %s to %s" +msgstr "OYA Ihuza Kuri" + +#, fuzzy, c-format +msgid "no element \"%s\"" +msgstr "Oya Ikigize:" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, fuzzy, c-format +msgid "could not parse caps \"%s\"" +msgstr "OYA Inyuguti nkuru" + +#, fuzzy, c-format +msgid "no sink element for URI \"%s\"" +msgstr "Oya Ikigize: kugirango" + +#, fuzzy, c-format +msgid "no source element for URI \"%s\"" +msgstr "Oya Inkomoko Ikigize: kugirango" + +msgid "syntax error" +msgstr "" + +#, fuzzy, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "ubusa OYA" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "Oya Gusimbuka: %s%s" + +#, fuzzy +msgid "empty pipeline not allowed" +msgstr "ubusa OYA" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, fuzzy, c-format +msgid "Could not create temp file \"%s\"." +msgstr "OYA Kubona Gushyiraho Amagenamiterere Bivuye ku" + +#, fuzzy, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "OYA Gufungura IDOSIYE kugirango" + +#, fuzzy +msgid "Error while writing to download file." +msgstr "Kuri IDOSIYE" + +#, fuzzy +msgid "No file name specified for writing." +msgstr "IDOSIYE Izina: kugirango" + +#, fuzzy, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "OYA Gufungura IDOSIYE kugirango" + +#, fuzzy, c-format +msgid "Error closing file \"%s\"." +msgstr "IDOSIYE" + +#, fuzzy, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Kuri IDOSIYE" + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Kuri IDOSIYE" + +#, fuzzy +msgid "No file name specified for reading." +msgstr "IDOSIYE Izina: kugirango" + +#, fuzzy, c-format +msgid "Could not get info on \"%s\"." +msgstr "OYA Kubona Gushyiraho Amagenamiterere Bivuye ku" + +#, fuzzy, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\"ni a bushyinguro" + +#, fuzzy, c-format +msgid "File \"%s\" is a socket." +msgstr "Idosiye ni a" + +#, fuzzy +msgid "Failed after iterations as requested." +msgstr "Nyuma Amasubiramo Nka" + +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Revision.TextDisplay.Insert.Attribute..5.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Revision.TextDisplay.Delete.Attribute..4.text +# #-#-#-#-# officecfg.pot (PACKAGE VERSION) #-#-#-#-# +# officecfg/registry\schema\org\openoffice\Office\Writer.xcs:....Revision.TextDisplay.ChangedAttribute.Attribute..5.text +#, fuzzy +msgid "caps" +msgstr "Inyuguti nkuru" + +#, fuzzy +msgid "detected capabilities in stream" +msgstr "in" + +# officecfg/registry\schema\org\openoffice\Office\Calc.xcs:....Layout.Other.StatusbarFunction..5.text +#, fuzzy +msgid "minimum" +msgstr "Gito" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "iyi Ibyatanzwe" + +#, fuzzy +msgid "Stream contains no data." +msgstr "iyi Ibyatanzwe" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +#, fuzzy +msgid "writable" +msgstr "umutwe" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +#, fuzzy +msgid "Total count: " +msgstr "IBARA" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "" +msgstr[1] "" + +#, fuzzy +msgid "Print all elements" +msgstr "Byose Ibintu" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, fuzzy, c-format +msgid "Could not load plugin file: %s\n" +msgstr "OYA Gufungura IDOSIYE kugirango" + +#, fuzzy, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Oya Inkomoko Ikigize: kugirango" + +msgid "Index statistics" +msgstr "" + +#, fuzzy, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "Got message #%u (%s): " +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Bivuye Ikigize:" + +#, fuzzy, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "Byabonetse ku Ikigize:" + +#, fuzzy, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "Byabonetse ku Ikigize:" + +#, fuzzy, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "Byabonetse ku Ikigize:" + +msgid "FOUND TAG\n" +msgstr "" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "Byabonetse ku Ikigize:" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "Byabonetse ku Ikigize:" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, fuzzy, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "Bivuye Ikigize:" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "Oya Ikigize:" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Bivuye Ikigize:" + +#, fuzzy +msgid "Output tags (also known as metadata)" +msgstr "Nka" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +#, fuzzy +msgid "Output status information and property notifications" +msgstr "Imimerere Ibisobanuro Na indangakintu Ibimenyetso" + +#, fuzzy +msgid "Do not print any progress information" +msgstr "OYA Ibisohoka Imimerere Ibisobanuro Bya" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +#, fuzzy +msgid "Do not install a fault handler" +msgstr "OYA Kwinjiza porogaramu a" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, fuzzy, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "OYA" + +#, fuzzy +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "OYA" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "" + +#, fuzzy +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "i Ikigize: Byabonetse" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "Kuri Gukina" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "Kuri Gukina" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "Kuri Gukina" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +msgid "Freeing pipeline ...\n" +msgstr "" + +#, fuzzy +#~ msgid "Do not output status information of TYPE" +#~ msgstr "OYA Ibisohoka Imimerere Ibisobanuro Bya" + +#, fuzzy +#~ msgid "link without source element" +#~ msgstr "Ihuza Inkomoko Ikigize:" + +#, fuzzy +#~ msgid "link without sink element" +#~ msgstr "Ihuza Ikigize:" + +#, fuzzy +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "Oya Ikigize: Kuri Ihuza Kuri" + +#, fuzzy +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "NIBA Bikora ku Gukusanya Igihe" + +#, fuzzy +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "IDOSIYE xml Ikigize: indangakintu Agaciro" + +#, fuzzy +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "Bya xml IDOSIYE Byanze" + +#, fuzzy +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "Oya Ikigize: in IDOSIYE" + +#, fuzzy +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "Ikigize: ni ku iyi Igihe" + +#, fuzzy +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "OYA Komandi: Umurongo" + +#, fuzzy +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "Ikigize: OYA Byabonetse" + +#, fuzzy +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Kubika xml Bya Kuri Na Gusohoka" + +#~ msgid "FILE" +#~ msgstr "IDOSIYE" + +#, fuzzy +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "OYA Kwinjiza porogaramu a" + +#, fuzzy +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Kuri IDOSIYE" + +#, fuzzy +#~ msgid "Error while seeking in file \"%d\"." +#~ msgstr "Kuri IDOSIYE" + +#, fuzzy +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Ikosa Leta Guhindura>> Byanze Idosiye a" + +#, fuzzy +#~ msgid "original location of file as a URI" +#~ msgstr "Umwimerere Ahantu Bya IDOSIYE Nka a" + +#, fuzzy +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Amabwiriza" + +#, fuzzy +#~ msgid "Registry to use" +#~ msgstr "Kuri Gukoresha" + +#, fuzzy +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "Inzira Urutonde kugirango Itangira... ku" + +#, fuzzy +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Kuri Gukoresha Mburabuzi ni" + +#, fuzzy +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "Ikosa Idosiye a" + +#, fuzzy +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "ni Oya Ikigize: Kuri i Ubwoko" + +#, fuzzy +#~ msgid "" +#~ "Execution ended after %s iterations (sum %s ns, average %s ns, min %s ns, " +#~ "max %s ns).\n" +#~ msgstr "Nyuma Amasubiramo Igiteranyo Impuzandengo GITO KININI" + +#, fuzzy +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Bya Times Kuri" + +#, fuzzy +#~ msgid " Trying to run anyway.\n" +#~ msgstr "Kuri Gukoresha" + +#, fuzzy +#~ msgid "Added plugin %s with %d %s.\n" +#~ msgstr "Na:" + +#, fuzzy +#~ msgid "Added path %s to %s \n" +#~ msgstr "Inzira Kuri" + +#, fuzzy +#~ msgid "Trying to load %s ...\n" +#~ msgstr "Kuri Ibirimo" + +#, fuzzy +#~ msgid "Error loading %s\n" +#~ msgstr "Itangira..." + +#, fuzzy +#~ msgid "Loaded %d plugins with %d %s.\n" +#~ msgstr "Na:" diff --git a/po/sk.gmo b/po/sk.gmo new file mode 100644 index 0000000..a950dc4 Binary files /dev/null and b/po/sk.gmo differ diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 0000000..4d4cdc4 --- /dev/null +++ b/po/sk.po @@ -0,0 +1,1417 @@ +# translation of sk.po to Slovak +# Slovak translation of gstreamer. +# Copyright (C) 2004, 2005 gstreamer's COPYRIGHT HOLDER +# This file is put in the public domain. +# +# Peter Tuhársky , 2007, 2008, 2009, 2010, 2014, 2016. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.7.90\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2016-05-20 11:32+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%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 1.6.10\n" + +msgid "Print the GStreamer version" +msgstr "Vypísať verziu GStreamer" + +msgid "Make all warnings fatal" +msgstr "Chápať všetky varovania ako závažné" + +msgid "Print available debug categories and exit" +msgstr "Vypísať dostupné ladiace kategórie a skončiť" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Predvolená úroveň ladenia od 1 (len chyby) po 9 (všetko) alebo 0 (bez " +"výstupu)" + +msgid "LEVEL" +msgstr "ÚROVEŇ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Čiarkami oddelený zoznam dvojíc názov_kategórie:úroveň pre nastavenie " +"špecifických úrovní pre jednotlivé kategórie. Príklad: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "ZOZNAM" + +msgid "Disable colored debugging output" +msgstr "Zakázať farebný ladiaci výstup" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Zmení farebný režim ladiaceho výstupu. Dostupné režimy: zapnutý, vypnutý, " +"zakázaný, automatický, unix" + +msgid "Disable debugging" +msgstr "Zakázať ladenie" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Povoliť podrobnú diagnostiku načítavania zásuvných modulov" + +msgid "Colon-separated paths containing plugins" +msgstr "Dvojbodkou oddelené cesty, ktoré obsahujú zásuvné moduly" + +msgid "PATHS" +msgstr "CESTY" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Čiarkami oddelený zoznam zásuvných modulov, ktoré sa majú prednačítať popri " +"zozname, ktorý je uložený v premennej prostredia GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "ZÁSUVNÉ MODULY" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Zakázať zachytávanie chýb segmentácie počas načítania zásuvného modulu" + +msgid "Disable updating the registry" +msgstr "Zakázať aktualizáciu registrov" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Zakázať vytváranie pomocných procesov počas skenovania registrov" + +msgid "GStreamer Options" +msgstr "Možnosti pre GStreamer" + +msgid "Show GStreamer Options" +msgstr "Zobraziť možnosti pre GStreamer" + +msgid "Unknown option" +msgstr "Neznáma možnosť" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer narazil na všeobecnú chybu hlavnej knižnice." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Vývojári GStreamer boli príliš leniví na to, aby tejto chybe priradili kód." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Vnútorná chyba GStreamer: kód nebol implementovaný." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Chyba GStreamer: zlyhala zmena stavu a niektorý prvok nedokázal poslať " +"patričné hlásenie o chybe s dôvodom zlyhania." + +msgid "Internal GStreamer error: pad problem." +msgstr "Vnútorná chyba GStreamer: problém pri vyplňovaní." + +msgid "Internal GStreamer error: thread problem." +msgstr "Vnútorná chyba GStreamer: problém s vláknami." + +msgid "GStreamer error: negotiation problem." +msgstr "Vnútorná chyba GStreamer: problém pri vyjednávaní." + +msgid "Internal GStreamer error: event problem." +msgstr "Vnútorná chyba GStreamer: problém s udalosťami." + +msgid "Internal GStreamer error: seek problem." +msgstr "Vnútorná chyba GStreamer: problém s nastavením pozície." + +msgid "Internal GStreamer error: caps problem." +msgstr "Vnútorná chyba GStreamer: problém schopností." + +msgid "Internal GStreamer error: tag problem." +msgstr "Vnútorná chyba GStreamer: problém so značkami." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Vašej inštalácii GStreamer chýba nejaký zásuvný modul." + +msgid "GStreamer error: clock problem." +msgstr "Vnútorná chyba GStreamer: problém s časovaním." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Táto aplikácia sa pokúša použiť takú funkcionalitu GStreamer, ktorá je " +"vypnutá." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer narazil na všeobecnú chybu podpornej knižnice." + +msgid "Could not initialize supporting library." +msgstr "Nepodarilo sa inicializovať podpornú knižnicu." + +msgid "Could not close supporting library." +msgstr "Nepodarilo sa zatvoriť podpornú knižnicu." + +msgid "Could not configure supporting library." +msgstr "Nepodarilo sa nastaviť podpornú knižnicu." + +msgid "Encoding error." +msgstr "Chyba pri kódovaní." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer narazil na všeobecnú chybu zdrojov." + +msgid "Resource not found." +msgstr "Zdroj sa nenašiel." + +msgid "Resource busy or not available." +msgstr "Zdroj sa používa alebo nie je k dispozícii." + +msgid "Could not open resource for reading." +msgstr "Nepodarilo sa otvoriť zdroj na čítanie." + +msgid "Could not open resource for writing." +msgstr "Nepodarilo sa otvoriť zdroj na zápis." + +msgid "Could not open resource for reading and writing." +msgstr "Nepodarilo sa otvoriť zdroj na čítanie a zápis." + +msgid "Could not close resource." +msgstr "Nepodarilo sa zatvoriť zdroj." + +msgid "Could not read from resource." +msgstr "Nepodarilo sa čítať zo zdroja." + +msgid "Could not write to resource." +msgstr "Nepodarilo sa zapisovať na zdroj." + +msgid "Could not perform seek on resource." +msgstr "Nepodarilo sa nastaviť pozíciu na zdroji." + +msgid "Could not synchronize on resource." +msgstr "Nepodarilo sa synchronizovať so zdrojom." + +msgid "Could not get/set settings from/on resource." +msgstr "Nepodarilo sa získať/upraviť nastavenia zdroja." + +msgid "No space left on the resource." +msgstr "Na zdroji už nezostalo miesto." + +msgid "Not authorized to access resource." +msgstr "Nedostatočné práva na prístup k tomuto zdroju." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer narazil na všeobecnú chybu prúdu údajov." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Prvok neimplementuje obsluhu tohoto prúdu údajov. Ohláste prosím tuto chybu." + +msgid "Could not determine type of stream." +msgstr "Nepodarilo sa zistiť typ prúdu údajov." + +msgid "The stream is of a different type than handled by this element." +msgstr "" +"Tento prúd údajov je odlišného typu, než je schopný obslúžiť tento prvok." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Nie je k dispozícii žiadny kodek, ktorý by dokázal obslúžiť tento typ prúdu " +"údajov." + +msgid "Could not decode stream." +msgstr "Nepodarilo sa dekódovať prúd údajov." + +msgid "Could not encode stream." +msgstr "Nepodarilo sa zakódovať prúd údajov." + +msgid "Could not demultiplex stream." +msgstr "Nepodarilo sa demultiplexovať prúd údajov." + +msgid "Could not multiplex stream." +msgstr "Nepodarilo sa multiplexovať prúd údajov." + +msgid "The stream is in the wrong format." +msgstr "Tento prúd údajov je v nesprávnom formáte." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Tento prúd údajov je šifrovaný a dešifrovanie nie je podporované" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Tento prúd údajov je šifrovaný a nedá sa dešifrovať, pretože nie je k " +"dispozícii vhodný kľúč." + +#, c-format +msgid "No error message for domain %s." +msgstr "Žiadna chybová správa pre doménu %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Žiadna štandardná chybová správa pre doménu %s a kód %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Vybraný časovač sa nedá použiť v rúre." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Chyba pri zápise vyrovnávacej pamäte registrov do %s: %s" + +msgid "title" +msgstr "názov" + +msgid "commonly used title" +msgstr "často používaný názov" + +msgid "title sortname" +msgstr "názov/triedenie" + +msgid "commonly used title for sorting purposes" +msgstr "často používaný názov, na účely triedenia" + +msgid "artist" +msgstr "umelec" + +msgid "person(s) responsible for the recording" +msgstr "osoby zodpovedné za nahrávku" + +msgid "artist sortname" +msgstr "umelec/triedenie" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "osoby zodpovedné za nahrávku, na účely triedenia" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album obsahujúci tieto údaje" + +msgid "album sortname" +msgstr "album/triedenie" + +msgid "album containing this data for sorting purposes" +msgstr "album obsahujúci tieto údaje, na účely triedenia" + +msgid "album artist" +msgstr "umelec albumu" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Umelec celého albumu, ako sa má zobraziť" + +msgid "album artist sortname" +msgstr "meno umelca albumu pre triedenie" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Umelec celého albumu, ako sa má zoradiť" + +msgid "date" +msgstr "dátum" + +msgid "date the data was created (as a GDate structure)" +msgstr "dátum, kedy boli tieto údaje vytvorené (ako štruktúra GDate)" + +msgid "datetime" +msgstr "dátum a čas" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "" +"dátum a čas, kedy boli tieto údaje vytvorené (ako štruktúra GstDateTime)" + +msgid "genre" +msgstr "žáner" + +msgid "genre this data belongs to" +msgstr "žáner, do ktorého patria tieto údaje" + +msgid "comment" +msgstr "poznámka" + +msgid "free text commenting the data" +msgstr "voľný text komentujúci údaje" + +msgid "extended comment" +msgstr "rozšírená poznámka" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"vyčistiť text poznámky ku údajom vo formáte key=value alebo key[en]=comment " + +msgid "track number" +msgstr "číslo stopy" + +msgid "track number inside a collection" +msgstr "číslo stopy v rámci zbierky" + +msgid "track count" +msgstr "počet stôp" + +msgid "count of tracks inside collection this track belongs to" +msgstr "počet stôp v zbierke, do ktorej patrí táto stopa" + +msgid "disc number" +msgstr "číslo disku" + +msgid "disc number inside a collection" +msgstr "číslo disku v rámci zbierky" + +msgid "disc count" +msgstr "počet diskov" + +msgid "count of discs inside collection this disc belongs to" +msgstr "počet diskov v rámci zbierky, do ktorej tento disk patrí" + +msgid "location" +msgstr "umiestnenie" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Zdroj média, ako napríklad URI (miesto, kde je uložený originál tohto súboru " +"alebo prúdu údajov)" + +msgid "homepage" +msgstr "domovská stránka" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Domovská stránka tohto média (napr. umelca, alebo filmu)" + +msgid "description" +msgstr "popis" + +msgid "short text describing the content of the data" +msgstr "krátky text popisujúci obsah údajov" + +msgid "version" +msgstr "verzia" + +msgid "version of this data" +msgstr "verzia týchto údajov" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - viz http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organizácia" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "poznámka o autorských právach k údajom" + +msgid "copyright uri" +msgstr "uri pre copyright" + +msgid "URI to the copyright notice of the data" +msgstr "URI pre poznámku o autorských právach údajov" + +msgid "encoded by" +msgstr "kodér" + +msgid "name of the encoding person or organization" +msgstr "meno kódujúcej osoby alebo organizácie" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "kontaktné informácie" + +msgid "license" +msgstr "licencia" + +msgid "license of data" +msgstr "licencia údajov" + +msgid "license uri" +msgstr "URI licencie" + +msgid "URI to the license of the data" +msgstr "URI ku licencii týchto údajov" + +msgid "performer" +msgstr "interpret" + +msgid "person(s) performing" +msgstr "vystupujúce osoby " + +msgid "composer" +msgstr "skladateľ" + +msgid "person(s) who composed the recording" +msgstr "osoby zodpovedné za skladbu nahrávky" + +msgid "conductor" +msgstr "dirigent" + +msgid "conductor/performer refinement" +msgstr "upresnenie dirigenta/interpreta" + +msgid "duration" +msgstr "trvanie" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "dĺžka v jednotkách času GStreamer (nanosekundách)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "kodek, v ktorom sú údaje uložené" + +msgid "video codec" +msgstr "video kodek" + +msgid "codec the video data is stored in" +msgstr "kodek, v ktorom sú video údaje uložené" + +msgid "audio codec" +msgstr "zvukový kodek" + +msgid "codec the audio data is stored in" +msgstr "kodek, v ktorom sú zvukové údaje uložené" + +msgid "subtitle codec" +msgstr "kodek pre titulky" + +msgid "codec the subtitle data is stored in" +msgstr "kodek pre titulky sa nachádza v" + +msgid "container format" +msgstr "formát kontajneru" + +msgid "container format the data is stored in" +msgstr "formát kontajneru, v ktorom sú uložené dáta" + +msgid "bitrate" +msgstr "Bitová rýchlosť" + +msgid "exact or average bitrate in bits/s" +msgstr "presná alebo priemerná bitová rýchlosť v bitoch/s" + +msgid "nominal bitrate" +msgstr "nominálna bitová rýchlosť" + +msgid "nominal bitrate in bits/s" +msgstr "nominálna bitová rýchlosť v bitoch/s" + +msgid "minimum bitrate" +msgstr "minimálna bitová rýchlosť" + +msgid "minimum bitrate in bits/s" +msgstr "minimálna bitová rýchlosť v bitoch/s" + +msgid "maximum bitrate" +msgstr "maximálna bitová rýchlosť" + +msgid "maximum bitrate in bits/s" +msgstr "maximálna bitová rýchlosť v bitoch/s" + +msgid "encoder" +msgstr "kodér" + +msgid "encoder used to encode this stream" +msgstr "kodér používaný pre kódovanie tohoto prúdu údajov" + +msgid "encoder version" +msgstr "verzia kodéru" + +msgid "version of the encoder used to encode this stream" +msgstr "verzia kodéru používaného pre kódovanie tohto prúdu" + +msgid "serial" +msgstr "sériové" + +msgid "serial number of track" +msgstr "sériové číslo stopy" + +msgid "replaygain track gain" +msgstr "prehrávací zisk stopy" + +msgid "track gain in db" +msgstr "zisk stopy v db" + +msgid "replaygain track peak" +msgstr "špička prehrávacieho zisku stopy" + +msgid "peak of the track" +msgstr "špička stopy" + +msgid "replaygain album gain" +msgstr "prehrávací zisk albumu" + +msgid "album gain in db" +msgstr "zisk albumu v db" + +msgid "replaygain album peak" +msgstr "špička prehrávacieho zisku albumu" + +msgid "peak of the album" +msgstr "špička albumu" + +msgid "replaygain reference level" +msgstr "referenčná úroveň prehrávacieho zisku stopy" + +msgid "reference level of track and album gain values" +msgstr "Referenčná úroveň zisku pre stopu a pre album" + +msgid "language code" +msgstr "jazykový kód" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" +"Jazykový kód pre tento prúd údajov, v súlade s ISO-639-1 alebo ISO-639-2" + +msgid "language name" +msgstr "názov jazyku" + +msgid "freeform name of the language this stream is in" +msgstr "názov reči tohto prúdu údajov" + +msgid "image" +msgstr "obrázok" + +msgid "image related to this stream" +msgstr "obrázok zodpovedajúci k tomuto prúdu údajov" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "ukážka obrázku" + +msgid "preview image related to this stream" +msgstr "ukážka obrázku zodpovedajúca tomuto prúdu údajov" + +msgid "attachment" +msgstr "príloha" + +msgid "file attached to this stream" +msgstr "súbor pripojený ku tomuto prúdu údajov" + +msgid "beats per minute" +msgstr "úderov za minútu" + +msgid "number of beats per minute in audio" +msgstr "počet úderov za minútu, vo zvuku" + +msgid "keywords" +msgstr "kľúčové slová" + +msgid "comma separated keywords describing the content" +msgstr "kľúčové slová, opisujúce obsah, oddelené čiarkou" + +msgid "geo location name" +msgstr "zemepisná poloha - názov" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"opis miesta, v ľudskej reči, kde boli tieto médiá nahraté alebo produkované" + +msgid "geo location latitude" +msgstr "zemepisná šírka" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"zemepisná šírka miesta, kde boli tieto médiá nahraté alebo produkované, v " +"stupňoch podľa WGS84 (0 pre rovník, záporné hodnoty pre južné šírky)" + +msgid "geo location longitude" +msgstr "zemepisná dĺžka" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"zemepisná dĺžka miesta, kde boli tieto médiá nahraté alebo produkované, v " +"stupňoch podľa WGS84 (0 pre nultý poludník v Greenwich/UK, záporné hodnoty " +"pre západné dĺžky)" + +msgid "geo location elevation" +msgstr "nadmorská výška" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"zemepisná nadmorská výška miesta, kde boli tieto médiá nahraté alebo " +"produkované, v metroch podľa WGS84 (0 je priemerná hladina mora)" + +msgid "geo location country" +msgstr "zemepisná poloha - krajina" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "krajina (v angličtine), kde bolo toto médium nahraté alebo produkované" + +msgid "geo location city" +msgstr "zemepisná poloha - mesto" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "mesto (v angličtine), kde bolo toto médium nahraté alebo produkované" + +msgid "geo location sublocation" +msgstr "zemepisná poloha - upresnenie" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"umiestnenie v rámci mesta, kde bolo toto médium vyprodukované alebo " +"vytvorené (napr. v susedstve)" + +msgid "geo location horizontal error" +msgstr "geografická poloha - vodorovná odchýlka" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "očakávaná odchýlka vodorovného umiestnenia (v metroch)" + +msgid "geo location movement speed" +msgstr "zemepisná poloha - rýchlosť pohybu" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "rýchlosť pohybu zachytávajúceho zariadenia počas zachytávania v m/s" + +msgid "geo location movement direction" +msgstr "zemepisná poloha - smer pohybu" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"ukazuje smer pohybu zariadenia, ktoré vykonávalo zachytávanie média. Je " +"reprezentovaný ako stupne v neceločíselnej reprezentácii, 0 znamená " +"geografický sever, a zvyšuje sa v smere hodinových ručičiek" + +msgid "geo location capture direction" +msgstr "zemepisná poloha - smer zachytávania" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"ukazuje smer, kam zariadenie smerovalo počas zachytávania média. Je " +"reprezentovaný ako stupne v neceločíselnej reprezentácii, 0 znamená " +"geografický sever, a zvyšuje sa v smere hodinových ručičiek" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "názov šou" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Názov tv/podcast/seriálovej šou z ktorého pochádza toto médium" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "názov šou pre triedenie" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Názov tv/podcast/seriálovej šou z ktorého pochádza toto médium, pre účely " +"triedenia" + +msgid "episode number" +msgstr "číslo epizódy" + +msgid "The episode number in the season the media is part of" +msgstr "Číslo epizódy v tomto období, ktorého súčasťou je toto médium" + +msgid "season number" +msgstr "číslo obdobia" + +msgid "The season number of the show the media is part of" +msgstr "Číslo obdobia tejto šou, ktorej súčasťou je toto médium" + +msgid "lyrics" +msgstr "text" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Text tohto média, zvyčajne sa používa pri piesňach" + +msgid "composer sortname" +msgstr "meno skladateľa pre triedenie" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "osoby zodpovedné za nahrávku, na účely triedenia" + +msgid "grouping" +msgstr "zoskupovanie" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Zoskupí súvisiace médiá, ktoré zaberajú viacero stôp, ako napríklad rôzne " +"časti koncertu. Toto je vyššia úroveň než stopa, ale nižšia než album." + +msgid "user rating" +msgstr "hodnotenie používateľa" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Hodnotenie podľa používateľa. Čím vyššie, tým viac sa toto médium páči." + +msgid "device manufacturer" +msgstr "výrobca zariadenia" + +msgid "Manufacturer of the device used to create this media" +msgstr "Výrobca zariadenia použitého na vytvorenie tohto média" + +msgid "device model" +msgstr "model zariadenia" + +msgid "Model of the device used to create this media" +msgstr "Model zariadenia použitého na vytvorenie tohto média" + +msgid "application name" +msgstr "názov aplikácie" + +msgid "Application used to create the media" +msgstr "Aplikácia použitá pri tvorbe tohto média" + +msgid "application data" +msgstr "dáta aplikácie" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Ľubovoľné údaje aplikácie, ktoré sa majú serializovať do média" + +msgid "image orientation" +msgstr "orientácia obrázku" + +msgid "How the image should be rotated or flipped before display" +msgstr "Ako má byť obrázok otočený alebo prevrátený pred jeho zobrazením" + +msgid "publisher" +msgstr "vydavateľ" + +msgid "Name of the label or publisher" +msgstr "Meno titulu alebo vydavateľa" + +msgid "interpreted-by" +msgstr "interpret" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Informácie o ľuďoch v pozadí remixovania a podobných interpretácií" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "súkromné-dáta" + +msgid "Private data" +msgstr "Súkromné dáta" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Nenašla sa obsluha URI pre protokol %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI schéma '%s' nie je podporovaná" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "CHYBA: od prvku %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Prídavné ladiace informácie:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "odkaz nemá zdroj [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "odkaz nemá sink [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "neexistuje vlastnosť \"%s\" v prvku \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "nepodarilo sa nastaviť vlastnosť \"%s\" v prvku \"%s\" na \"%s\"" + +msgid "Delayed linking failed." +msgstr "Oneskorené odkazovanie zlyhalo." + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "nepodarilo sa pripojiť %s ku %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "nepodarilo sa pripojiť prvok sink pre URI \"%s\"" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "nepodarilo sa pripojiť %s ku %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "nepodarilo sa pripojiť %s ku %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "prvok \"%s\" neexistuje" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "nečakaný odkaz \"%s\" - ignorujem" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "nepodarilo sa analyzovať schopnosti \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "neexistuje prvok sink pre URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "neexistuje zdrojový prvok pre URI \"%s\"" + +msgid "syntax error" +msgstr "chyba syntaxe" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "bol zadaný prázdny zásobník \"%s\", čo nie je dovolené" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "neexistuje zásobník \"%s\", rozbaľujem prvky" + +msgid "empty pipeline not allowed" +msgstr "prázdna rúra sa nepripúšťa" + +msgid "A lot of buffers are being dropped." +msgstr "Veľa vyrovnávacej pamäte sa zahadzuje." + +msgid "Internal data flow problem." +msgstr "Vnútorný problém v toku údajov." + +msgid "Internal data flow error." +msgstr "Vnútorná chyba toku údajov." + +msgid "Internal clock error." +msgstr "Vnútorná chyba časovača." + +msgid "Failed to map buffer." +msgstr "Zlyhalo vytváranie vyrovnávacej pamäte." + +msgid "Filter caps" +msgstr "Filtrovať schopnosti" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Obmedziť možné povolené schopnosti (NULOVÉ znamená ĽUBOVOĽNÉ). Nastavenie " +"tejto vlastnosti berie referenciu na zadaný objekt GstCaps." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Nebol určený dočasný priečinok (Temp)." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Nepodarilo sa získať informácie o \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Nepodarilo sa otvoriť súbor \"%s\" pre čítanie." + +msgid "Error while writing to download file." +msgstr "Chyba pri zápise do sťahovaného súboru." + +msgid "No file name specified for writing." +msgstr "Nebol určený názov súboru pre zápis." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Nepodarilo sa otvoriť súbor \"%s\" pre zápis." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Chyba pri zatváraní súboru \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Chyba pri nastavovaní pozície v súbore \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Chyba pri zápise do súboru \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nebol určený názov súboru pre čítanie." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Nepodarilo sa získať informácie o \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" je adresár." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Súbor \"%s\" je zásuvka." + +msgid "Failed after iterations as requested." +msgstr "Zlyhanie po vykonaní požadovaných iterácií." + +msgid "caps" +msgstr "schopnosti" + +msgid "detected capabilities in stream" +msgstr "zistené schopnosti v prúde údajov" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "vynútiť veľké písmená" + +msgid "force caps without doing a typefind" +msgstr "vynútiť veľké písmená bez kontroly" + +msgid "Stream doesn't contain enough data." +msgstr "Prúd neobsahuje dostatok údajov." + +msgid "Stream contains no data." +msgstr "Prúd neobsahuje údaje." + +msgid "Implemented Interfaces:\n" +msgstr "Implementované rozhrania:\n" + +msgid "readable" +msgstr "čitateľné" + +msgid "writable" +msgstr "zapisovateľné" + +msgid "deprecated" +msgstr "zastaralé" + +msgid "controllable" +msgstr "ovládateľné" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "meniteľné v stave NULOVÝ, PRIPRAVENÝ, POZASTAVENÝ alebo HRAJÚCI" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "meniteľné v iba stave NULOVÝ, PRIPRAVENÝ alebo POZASTAVENÝ" + +msgid "changeable only in NULL or READY state" +msgstr "meniteľné iba v stave NULOVÝ alebo PRIPRAVENÝ" + +msgid "Blacklisted files:" +msgstr "Zakázané súbory:" + +msgid "Total count: " +msgstr "Celkový počet:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d zakázaný súbor" +msgstr[1] "%d zakázané súbory" +msgstr[2] "%d zakázaných súborov" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d zásuvný modul" +msgstr[1] "%d zásuvné moduly" +msgstr[2] "%d zásuvných modulov" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d zakázaná položka" +msgstr[1] "%d zakázané položky" +msgstr[2] "%d zakázaných položiek" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funkcia" +msgstr[1] "%d funkcie" +msgstr[2] "%d funkcií" + +msgid "Print all elements" +msgstr "Vypísať všetky prvky" + +msgid "Print list of blacklisted files" +msgstr "Vytlačiť zoznam zakázaných súborov" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Vypísať taký zoznam možností tohto zásuvného modulu, ktorý sa dá spracovať " +"automaticky.\n" +" Je to užitočné v spojitosti s " +"vonkajšími automatickými mechanizmami inštalácie zásuvných modulov" + +msgid "List the plugin contents" +msgstr "Vypísať zoznam zásuvných modulov" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "Skontrolovať, či existuje vybraný prvok alebo zásuvný modul" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Pri kontrole, či existuje daný prvok alebo zásuvný modul, skontrolovať aj či " +"je jeho verzia aspoň na určenej úrovni" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Zobraziť podporované URI schémy, spolu s prvkami ktoré ich implementujú" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Nepodarilo sa načítať súbor zásuvného modulu: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Takýto prvok alebo zásuvný modul neexistuje '%s'\n" + +msgid "Index statistics" +msgstr "Štatistika indexu" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Dostal som správu #%u od prvku \"%s\" (%s):" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Dostal som správu #%u od padu \"%s:%s\" (%s):" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Dostal som správu #%u od objektu \"%s\" (%s):" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Dostal som správu #%u (%s):" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Dostal som EOS od prvku \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "NAŠLA SA ZNAČKA : našiel ju prvok \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "NAŠLA SA ZNAČKA : našiel ju pad \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "NAŠLA SA ZNAČKA : našiel ju objekt \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "NAŠLA SA ZNAČKA\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "NAŠLA SA TABUĽKA : našiel ju prvok \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "NAŠLA SA TABUĽKA : našiel ju objekt \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "NAŠLA SA TABUĽKA\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "VAROVANIE: z prvku %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Predčítané, čakám na dokončenie napĺňania vyrovnávacej pamäte...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Predčítané, čakám na dokončenie...\n" + +msgid "buffering..." +msgstr "Ukladám do vyrovnávacej pamäte..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Vyrovnávacia pamäť je naplnená, nastavujem rúru na HRAJÚCU ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Napĺňa sa vyrovnávacia pamäť, nastavujem rúru na POZASTAVENÚ ...\n" + +msgid "Redistribute latency...\n" +msgstr "Predistribuovať latenciu...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Nastavujem stav na %s ako požaduje %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Prerušenie: Zastavujem rúru ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Priebeh: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Chýba prvok %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Získal som kontext z prvku '%s': %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Vypísať značky (známe tiež ako metadáta)" + +msgid "Output TOC (chapters and editions)" +msgstr "Výstupná tabuľka obsahu (kapitoly a vydania)" + +msgid "Output status information and property notifications" +msgstr "Vypísať informácie o stave a upozornenia o vlastnostiach" + +msgid "Do not print any progress information" +msgstr "Nevypisovať informácie o stave" + +msgid "Output messages" +msgstr "Vypísať správy" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Neposkytnúť do výstupu informácie o vybranom vlastníctve ak je povolený " +"podrobný výstup )dá sa použiť niekoľkokrát)" + +msgid "PROPERTY-NAME" +msgstr "Meno vlastníctva" + +msgid "Do not install a fault handler" +msgstr "Neinštalovať obsluhu výnimiek" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Vynútiť EOS na zdrojoch pred vypnutím rúry" + +msgid "Gather and print index statistics" +msgstr "Zozbierať a zobraziť štatistiku indexu" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "CHYBA: nepodarilo sa vytvoriť rúru: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "CHYBA: nepodarilo sa vytvoriť rúru.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "VAROVANIE: chybná rúra: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "CHYBA: prvok 'rúra' sa nenašiel.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Nastavujem rúru na POZASTAVENÚ ...\n" + +# On strike? +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "CHYBA: Rúra sa nechce pozastaviť.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Rúra je živá a nepotrebuje PREROLL ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Rúra je v stave PREROLLING ...\n" + +# On strike? +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "CHYBA: rúra nechce prerollovať.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Rúra je v stave PREROLLED ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Nastavujem rúru na HRAJÚCU ...\n" + +# On strike? +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "CHYBA: Rúra nechce hrať.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS pri vypnutí je povolený -- Vynucujem EOS pre rúru\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS pri vypnutí je povolený -- čakám na EOS po chybe\n" + +msgid "Waiting for EOS...\n" +msgstr "Čakám na EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Prijatý EOS - zastavujem rúru ...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Prerušenie počas čakania na EOS - zastavujem rúru ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Počas čakania na EOS nastala chyba\n" + +msgid "Execution ended after %" +msgstr "Vykonávanie skončilo po %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Nastavujem rúru na PRIPRAVENÚ ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Nastavujem rúru na NULOVÚ ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Uvoľňujem rúru ...\n" + +#~ msgid "bin" +#~ msgstr "zásobník" + +#~ msgid "Internal data stream error." +#~ msgstr "Vnútorná chyba prúdu údajov." + +#~ msgid "link without source element" +#~ msgstr "pripojenie bez zdrojového prvku" + +#~ msgid "link without sink element" +#~ msgstr "odkaz bez prvku sink" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "neexistuje prvok, ku ktorému sa má pripojiť URI \"%s\"" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Nevypisovať informácie o stave TYPU" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYP1,TYP2,..." + +#~ msgid "maximum" +#~ msgstr "maximum" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Použitie: gst-xmllaunch [ prvk.vlastnosť=hodnota ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "CHYBA: zlyhala analýza xml súboru '%s'.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "CHYBA: v súbore '%s' chýba prvok rúry najvyššej úrovne.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "VAROVANIE: v súčasnosti je podporovaný iba jeden prvok najvyššej úrovne.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "CHYBA: nepodarilo sa analyzovať argument príkazového riadku %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "VAROVANIE: prvok s názvom '%s' sa nenašiel.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Uložiť reprezentáciu rúry v xml do SÚBORU a skončiť" + +#~ msgid "FILE" +#~ msgstr "SÚBOR" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Neinštalovať obsluhu signálov SIGUSR1 a SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Vypisovať stopu alokácie (ak je to povolené pri kompilácii)" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Chyba pri opätovnom skenovaní registrov %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Chyba pri opätovnom skenovaní registrov %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "" +#~ "Vnútorná chyba GStreamer: nepodarilo sa zmeniť stav. Ohláste prosím túto " +#~ "chybu." + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Chyba pri zápise do popisovača súboru \"%d\"." + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "Popisovač súboru \"%d\" nie je platný." + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "UVOĽŇUJEM rúru ...\n" + +#~ msgid "original location of file as a URI" +#~ msgstr "pôvodné umiestnenie súboru ako URI" diff --git a/po/sl.gmo b/po/sl.gmo new file mode 100644 index 0000000..07bbb7c Binary files /dev/null and b/po/sl.gmo differ diff --git a/po/sl.po b/po/sl.po new file mode 100644 index 0000000..55bca69 --- /dev/null +++ b/po/sl.po @@ -0,0 +1,1355 @@ +# Slovenian translation for gstreamer. +# This file is distributed under the same license as the gstreamer package. +# Copyright (C) 2005 - 2014 Free Software Foundation, Inc. +# +# Matej Urbančič , 2010 - 2011. +# Martin Srebotnjak , 2011. +# Klemen Košir , 2011 - 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-1.2.1\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2014-04-09 22:38+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-Generator: Poedit 1.6.4\n" + +msgid "Print the GStreamer version" +msgstr "Izpiše različico programa GStreamer" + +msgid "Make all warnings fatal" +msgstr "Izpiši vsa opozorila kot usodna" + +msgid "Print available debug categories and exit" +msgstr "Izpiše razpoložljive kategorije razhroščevanja in se konča" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Privzeta raven razhroščevanja od 1 (le napake) do 9 (karkoli). Vrednost 0 " +"pomeni brez izpisa." + +msgid "LEVEL" +msgstr "RAVEN" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Z vejico ločen seznam parov ime_kategorije:raven za določevanje posebnih " +"ravni posameznih kategorij. Primer: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "SEZNAM" + +msgid "Disable colored debugging output" +msgstr "Onemogoči obarvani razhroščevalni izpis" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Spremeni način barvanja dnevnika razhroščevanja. Razpoložljive možnosti so: " +"off, on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "Onemogoči razhroščevanje" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Omogoči podrobno diagnostiko nalaganja vstavkov" + +msgid "Colon-separated paths containing plugins" +msgstr "Z vejico ločen seznam poti do vstavkov" + +msgid "PATHS" +msgstr "POTI" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Z vejico ločen seznam vstavkov za uporabo ob seznamu, ki je shranjen v " +"okoljski spremenljivki GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "VSTAVKI" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Onemogoči ujemanje napak členjenja med nalaganjem vstavkov" + +msgid "Disable updating the registry" +msgstr "Onemogoči posodabljanje vpisnika" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Onemogoči ustvarjanje pomožnih procesov med pregledovanjem vpisnika" + +msgid "GStreamer Options" +msgstr "Možnosti GStreamer" + +msgid "Show GStreamer Options" +msgstr "Pokaži možnosti GStreamer" + +msgid "Unknown option" +msgstr "Neznana možnost" + +msgid "GStreamer encountered a general core library error." +msgstr "V programu GStreamer je prišlo do splošne napake jedrne knjižnice." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "Za to napako ni določene kode napake." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Notranja napaka GStreamer: zahtevana zmožnost ni podprta." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Napaka: sprememinjanje stanja je spodletelo in ni pravega sporočila vzroka " +"za to vrsto napake." + +msgid "Internal GStreamer error: pad problem." +msgstr "Notranja napaka GStreamer: težave pladnja." + +msgid "Internal GStreamer error: thread problem." +msgstr "Notranja napaka GStreamer: težave z nitenjem." + +msgid "GStreamer error: negotiation problem." +msgstr "Napaka GStreamer: težave s pogajanjem." + +msgid "Internal GStreamer error: event problem." +msgstr "Notranja napaka GStreamer: težave z dogodkom." + +msgid "Internal GStreamer error: seek problem." +msgstr "Notranja napaka GStreamer: težave z iskanjem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Notranja napaka GStreamer: težave z velikimi črkami." + +msgid "Internal GStreamer error: tag problem." +msgstr "Notranja napaka GStreamer: težave z oznako." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Namestitvi GStreamer manjka vstavek." + +msgid "GStreamer error: clock problem." +msgstr "Napaka GStreamer: težave z uro." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "Program poskuša uporabiti funkcijo GStreamer, ki je onemogočena." + +msgid "GStreamer encountered a general supporting library error." +msgstr "V programu GStreamer je prišlo do splošne napake podporne knjižnice." + +msgid "Could not initialize supporting library." +msgstr "Podporne knjižnice ni mogoče začeti." + +msgid "Could not close supporting library." +msgstr "Podporne knjižnice ni mogoče zapreti." + +msgid "Could not configure supporting library." +msgstr "Podporne knjižnice ni mogoče nastaviti." + +msgid "Encoding error." +msgstr "Napaka kodiranja." + +msgid "GStreamer encountered a general resource error." +msgstr "V programu GStreamer je prišlo do splošne napake vira." + +msgid "Resource not found." +msgstr "Vira ni mogoče najti." + +msgid "Resource busy or not available." +msgstr "Vir je zaposlen ali pa ni na voljo." + +msgid "Could not open resource for reading." +msgstr "Vira ni mogoče odpreti za branje." + +msgid "Could not open resource for writing." +msgstr "Vira ni mogoče odpreti za pisanje." + +msgid "Could not open resource for reading and writing." +msgstr "Vira ni mogoče odpreti za branje in pisanje." + +msgid "Could not close resource." +msgstr "Vira ni mogoče zapreti." + +msgid "Could not read from resource." +msgstr "Vira ni mogoče prebrati." + +msgid "Could not write to resource." +msgstr "Vira ni mogoče zapisati." + +msgid "Could not perform seek on resource." +msgstr "Na viru ni mogoče izvesti iskanja." + +msgid "Could not synchronize on resource." +msgstr "Z virom se ni mogoče uskladiti." + +msgid "Could not get/set settings from/on resource." +msgstr "Nastavitev vira ni mogoče pridobiti ali določiti." + +msgid "No space left on the resource." +msgstr "Na viru ni prostora." + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "Na viru ni prostora." + +msgid "GStreamer encountered a general stream error." +msgstr "V programu GStreamer je prišlo do splošne napake pretakanja." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Predmet ne podpira obravnavanja tega pretoka. Prosimo, pošljite poročilo o " +"napaki." + +msgid "Could not determine type of stream." +msgstr "Vrste pretoka ni mogoče določiti." + +msgid "The stream is of a different type than handled by this element." +msgstr "Pretok se razlikuje od vrste, ki jo obravnava predmet." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Za obravnavanje tega pretoka ni ustreznega kodeka." + +msgid "Could not decode stream." +msgstr "Pretoka ni mogoče odkodirati." + +msgid "Could not encode stream." +msgstr "Pretoka ni mogoče kodirati." + +msgid "Could not demultiplex stream." +msgstr "Pretoka ni mogoče odviti." + +msgid "Could not multiplex stream." +msgstr "Pretoka ni mogoče zviti." + +msgid "The stream is in the wrong format." +msgstr "Pretok je v napačnem zapisu." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Pretok je šifriran, odšifriranje pa ni podprto." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Pretok je šifriran in ga ni mogoče odšifrirati, ker ni podanega ustreznega " +"ključa." + +#, c-format +msgid "No error message for domain %s." +msgstr "Sporočilo napake za domeno %s ne obstaja." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Splošno sporočilo napake za domeno %s in kodo %d ne obstaja." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Izbrane ure ni mogoče uporabiti v cevovodu." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Med zapisovanjem predpomnilnika vpisnika v %s je prišlo do napake: %s" + +msgid "title" +msgstr "naslov" + +msgid "commonly used title" +msgstr "običajno uporabljen naslov" + +msgid "title sortname" +msgstr "razvrščevalno ime naslova" + +msgid "commonly used title for sorting purposes" +msgstr "splošno uporabljen naslov za razvrščanje" + +msgid "artist" +msgstr "izvajalec" + +msgid "person(s) responsible for the recording" +msgstr "osebe, zadolžene za snemanje" + +msgid "artist sortname" +msgstr "razvrščevalno ime izvajalca" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "osebe, odgovorne za posnetek, za potrebe razvrščanja" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album, ki vsebuje te podatke" + +msgid "album sortname" +msgstr "razvrščevalno ime albuma" + +msgid "album containing this data for sorting purposes" +msgstr "album, ki vsebuje te podatke, za potrebe razvrščanja" + +msgid "album artist" +msgstr "izvajalec albuma" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "izvajalec celotnega albuma; zapisan, kot mora biti prikazan" + +msgid "album artist sortname" +msgstr "razvrščevalno ime izvajalca albuma" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "izvajalec celotnega albuma, zapisan za razvrščanje" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "datum ustvaritve podatkov (kot zgradba GDate)" + +msgid "datetime" +msgstr "datumčas" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "datum in čas ustvaritve podatkov (kot zgradba GDateTime)" + +msgid "genre" +msgstr "zvrst" + +msgid "genre this data belongs to" +msgstr "zvrst, ki vsebuje te podatke" + +msgid "comment" +msgstr "opomba" + +msgid "free text commenting the data" +msgstr "prosto besedilo za opombe podatkov" + +msgid "extended comment" +msgstr "razširjena opomba" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"prosto besedilo za zapisovanje opomb podatkov v obliki ključ=vrednost ali " +"ključ[en]=opomba" + +msgid "track number" +msgstr "številka skladbe" + +msgid "track number inside a collection" +msgstr "številka skladbe v zbirki" + +msgid "track count" +msgstr "število skladb" + +msgid "count of tracks inside collection this track belongs to" +msgstr "skupno število skladb znotraj zbirke, ki ji skladba pripada" + +msgid "disc number" +msgstr "številka diska" + +msgid "disc number inside a collection" +msgstr "številka diska v zbirki" + +msgid "disc count" +msgstr "število diskov" + +msgid "count of discs inside collection this disc belongs to" +msgstr "skupno število diskov znotraj zbirke, ki ji disk pripada" + +msgid "location" +msgstr "mesto" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"izvor medija kot naslov URI (mesto, kjer je shranjen izvirnik datoteke ali " +"pretoka)" + +msgid "homepage" +msgstr "spletna stran" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "spletna stran medija (izvajalca, filma ali skupine)" + +msgid "description" +msgstr "opis" + +msgid "short text describing the content of the data" +msgstr "kratko besedilo, ki opisuje vsebino podatkov" + +msgid "version" +msgstr "različica" + +msgid "version of this data" +msgstr "različica podatkov" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code (http://www.ifpi.org/content/" +"section_resources/isrc.html)" + +msgid "organization" +msgstr "ustanova" + +msgid "copyright" +msgstr "avtorske pravice" + +msgid "copyright notice of the data" +msgstr "opozorilo avtorskih pravic podatkov" + +msgid "copyright uri" +msgstr "naslov URI avtorskih pravic" + +msgid "URI to the copyright notice of the data" +msgstr "naslov URI do obvestila avtorstva podatkov" + +msgid "encoded by" +msgstr "kodiral" + +msgid "name of the encoding person or organization" +msgstr "ime osebe ali organizacije, ki je opravila kodiranje" + +msgid "contact" +msgstr "stik" + +msgid "contact information" +msgstr "podatki o stiku" + +msgid "license" +msgstr "dovoljenje" + +msgid "license of data" +msgstr "dovoljenje podatkov" + +msgid "license uri" +msgstr "naslov URI dovoljenja" + +msgid "URI to the license of the data" +msgstr "naslov URI dovoljenja podatkov" + +msgid "performer" +msgstr "izvajalec" + +msgid "person(s) performing" +msgstr "osebe, ki so izvajalci posnetka" + +msgid "composer" +msgstr "skladatelj" + +msgid "person(s) who composed the recording" +msgstr "oseba, ki je skladatelj posnetka" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "trajanje" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "dolžina enot časa GStreamer (nanosekunde)" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "kodek, v katerem so shranjeni podatki" + +msgid "video codec" +msgstr "video kodek" + +msgid "codec the video data is stored in" +msgstr "kodek, v katerem so shranjeni video podatki" + +msgid "audio codec" +msgstr "zvočni kodek" + +msgid "codec the audio data is stored in" +msgstr "kodek, v katerem je shranjen zvok" + +msgid "subtitle codec" +msgstr "kodek podnapisov" + +msgid "codec the subtitle data is stored in" +msgstr "kodek, v katerem so shranjeni podnapisi" + +msgid "container format" +msgstr "zapis zabojnika" + +msgid "container format the data is stored in" +msgstr "zabojnik, v katerem so shranjeni podatki" + +msgid "bitrate" +msgstr "bitna hitrost" + +msgid "exact or average bitrate in bits/s" +msgstr "natančna ali povprečna bitna hitrost v bitih/s" + +msgid "nominal bitrate" +msgstr "nazivna bitna hitrost" + +msgid "nominal bitrate in bits/s" +msgstr "nazivna bitna hitrost v bitih/s" + +msgid "minimum bitrate" +msgstr "najmanjša bitna hitrost" + +msgid "minimum bitrate in bits/s" +msgstr "najmanjša bitna hitrost v bitih/s" + +msgid "maximum bitrate" +msgstr "največja bitna hitrost" + +msgid "maximum bitrate in bits/s" +msgstr "največja bitna hitrost v bitih/s" + +msgid "encoder" +msgstr "kodirnik" + +msgid "encoder used to encode this stream" +msgstr "kodirnik, uporabljen za kodiranje pretoka" + +msgid "encoder version" +msgstr "različica kodirnika" + +msgid "version of the encoder used to encode this stream" +msgstr "različica kodirnika, uporabljenega za kodiranje pretoka" + +msgid "serial" +msgstr "zaporedna številka" + +msgid "serial number of track" +msgstr "zaporedna številka skladbe" + +msgid "replaygain track gain" +msgstr "ojačitev sledi ReplayGain" + +msgid "track gain in db" +msgstr "pridobitev sledi v dB" + +msgid "replaygain track peak" +msgstr "vrh sledi ReplayGain" + +msgid "peak of the track" +msgstr "ojačanje vrha sledi" + +msgid "replaygain album gain" +msgstr "ojačitev albuma ReplayGain" + +msgid "album gain in db" +msgstr "pridobitev albuma v dB" + +msgid "replaygain album peak" +msgstr "vrha albuma ReplayGain" + +msgid "peak of the album" +msgstr "ojačanje vrha albuma" + +msgid "replaygain reference level" +msgstr "sklicna raven ReplayGain" + +msgid "reference level of track and album gain values" +msgstr "sklicna raven vrednosti pridobitve sledi in albuma" + +msgid "language code" +msgstr "jezikovna koda" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "koda jezika pretoka v skladu z ISO-639-1 ali ISO-639-2" + +msgid "language name" +msgstr "ime jezika" + +msgid "freeform name of the language this stream is in" +msgstr "prosto ime jezika tega pretoka" + +msgid "image" +msgstr "slika" + +msgid "image related to this stream" +msgstr "slika, povezana s pretokom" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "predogledna slika" + +msgid "preview image related to this stream" +msgstr "predogledna slika, povezana s pretokom" + +msgid "attachment" +msgstr "priloga" + +msgid "file attached to this stream" +msgstr "datoteka, priložena pretoku" + +msgid "beats per minute" +msgstr "udarci na minuto" + +msgid "number of beats per minute in audio" +msgstr "število udarcev na minuto v zvočnem posnetku" + +msgid "keywords" +msgstr "ključne besede" + +msgid "comma separated keywords describing the content" +msgstr "z vejico ločene ključne besede, ki opisujejo vsebino" + +msgid "geo location name" +msgstr "ime zemljepisnega mesta" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"človeku berljiv opis mesta, kjer je bil bil posnetek posnet ali izdelan" + +msgid "geo location latitude" +msgstr "zemljepisna širina mesta" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"zemljepisna širina, kjer je bil bil posnetek posnet ali izdelan v stopinjah " +"glede na WGS84 (vrednost 0 je določena z ekvatorjem, negativne vrednosti so " +"določene za južne zemljepisne širine)" + +msgid "geo location longitude" +msgstr "zemljepisna dolžina mesta" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"zemljepisna dolžina, kjer je bil bil posnetek posnet ali izdelan v stopinjah " +"glede na WGS84 (vrednost 0 je določena z glavnim, greenwiškim/ničelnim " +"poldnevnikom, negativne vrednosti so določene za zahodne zemljepisne dolžine)" + +msgid "geo location elevation" +msgstr "nadmorska višina mesta" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"nadmorska višina, kjer je bil bil posnetek posnet ali izdelan v metrih glede " +"na WGS84 (vrednost 0 je povprečna višina morske gladine)" + +msgid "geo location country" +msgstr "država zemljepisne lege" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "država (angleška različica), kjer je bil posnetek posnet ali izdelan" + +msgid "geo location city" +msgstr "mesto zemljepisne lege" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "mesto (angleška različica), kjer je bil posnetek posnet ali izdelan" + +msgid "geo location sublocation" +msgstr "področje zemljepisne lege" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"okraj znotraj mesta, kjer je bil posnetek posnet ali izdelan (na primer: " +"soseščina)" + +msgid "geo location horizontal error" +msgstr "vodoravna napaka zemljepisnega mesta" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "pričakovana napaka vodoravno umeščevalnih mer (v metrih)" + +msgid "geo location movement speed" +msgstr "zemljepisna hitrost gibanja" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "hitrost gibanja naprave zajemanja med izvajanjem zajemanja v m/s" + +msgid "geo location movement direction" +msgstr "zemljepisna smer gibanja" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"določa smer gibanja naprave, s katero je bil zajet posnetek. Določen je v " +"stopinjah v zapisu s plavajočo vejico. Vrednost 0 določa zemljepisni sever " +"in se povečuje v smeri urinega kazalca" + +msgid "geo location capture direction" +msgstr "zemljepisna smer zajemanja" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"določa smer usmerjenosti naprave, s katero je bil zajet posnetek. Določen je " +"v stopinjah v zapisu s plavajočo vejico. Vrednost 0 določa zemljepisni sever " +"in se povečuje v smeri urinega kazalca" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "pokaži ime" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Ime TV/nanizanke/oddaje, ki ji posnetek pripada" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "pokaži razvrščevalno ime" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Ime TV/nanizanke/oddaje, ki ji posnetek pripada, za potrebe razvrščanja" + +msgid "episode number" +msgstr "epizoda" + +msgid "The episode number in the season the media is part of" +msgstr "Številka epizode v sezoni, ki ji posnetek pripada" + +msgid "season number" +msgstr "sezona" + +msgid "The season number of the show the media is part of" +msgstr "Številka sezone oddaje, ki ji posnetek pripada" + +msgid "lyrics" +msgstr "besedilo" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Besedilo posnetka, običajno uporabljeno za skladbe" + +msgid "composer sortname" +msgstr "razvrščevalno ime skladatelja" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "osebe, ki so sodelovale pri snemanju, za potrebe razvrščanja" + +msgid "grouping" +msgstr "združevanje" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Vsebina, ki sega čez več posnetkov, podobno kot stavki simfonije. Je višje " +"ravni kot posnetek, vendar nižje kot album." + +msgid "user rating" +msgstr "ocena uporabnika" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Ocena, ki jo prispeva uporabnik. Višja kot je, bolj je uporabniku všeč." + +msgid "device manufacturer" +msgstr "proizvajalec naprave" + +msgid "Manufacturer of the device used to create this media" +msgstr "Proizvajalec naprave, s katero je bil ustvarjena datoteka" + +msgid "device model" +msgstr "model naprave" + +msgid "Model of the device used to create this media" +msgstr "Model naprave, s katero je bil ustvarjena datoteka" + +msgid "application name" +msgstr "ime programa" + +msgid "Application used to create the media" +msgstr "Program, uporabljen za izdelavo posnetka" + +msgid "application data" +msgstr "programski podatki" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" +"Poljubni podatki programa, ki bodo postavljeni v vrsto predstavne vsebine" + +msgid "image orientation" +msgstr "usmerjenost slike" + +msgid "How the image should be rotated or flipped before display" +msgstr "Kako naj bo slika zavrti ali zrcali pred prikazom" + +msgid "publisher" +msgstr "založba" + +msgid "Name of the label or publisher" +msgstr "Ime založbe" + +msgid "interpreted-by" +msgstr "avtorji-predelave" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Podatki o avtorjih predelav in drugih različic" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Ročnika URI za protokol %s ni mogoče najti" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Shema URI \"%s\" ni podprta" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "NAPAKA: predmet %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Dodatni podatki razhroščevanja:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "lastnost \"%s\" v predmetu \"%s\" ne obstaja" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "" +"lastnosti \"%s\" v predmetu \"%s\" ni mogoče nastaviti na vrednost \"%s\"" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "%s in %s ni mogoče povezati" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "predmeta korita za naslov URI \"%s\" ni mogoče povezati" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "%s in %s ni mogoče povezati" + +#, c-format +msgid "could not link %s to %s" +msgstr "%s in %s ni mogoče povezati" + +#, c-format +msgid "no element \"%s\"" +msgstr "predmet \"%s\" ne obstaja" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "velikih črk \"%s\" ni mogoče razčleniti" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "predmet ponora za naslov URI \"%s\" ne obstaja" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "izvorni predmet za naslov URI \"%s\" ne obstaja" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "določena je prazna dvojiška datoteka \"%s\", kar ni dovoljeno" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "dvojiška datoteka \"%s\" ne obstaja, zato bo dejanje izpuščeno" + +msgid "empty pipeline not allowed" +msgstr "cevovod brez vsebine ni dovoljen" + +msgid "A lot of buffers are being dropped." +msgstr "Veliko medpomnilnikov se prazni." + +msgid "Internal data flow problem." +msgstr "Notranja težava toka podatkov." + +msgid "Internal data flow error." +msgstr "Notranja napaka toka podatkov." + +msgid "Internal clock error." +msgstr "Notranja napaka ure." + +msgid "Failed to map buffer." +msgstr "Medpomnilnika ni mogoče preslikati." + +msgid "Filter caps" +msgstr "Filtriraj velikost črk" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Omeji možne dovoljene zmožnosti (NULL pomeni ANY, vse). S tem naslavljate " +"priloženi predmet GstCaps." + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "Začasna mapa ni določena." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Začasne datoteke \"%s\" ni mogoče ustvariti." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Datoteke \"%s\" ni mogoče odpreti za branje." + +msgid "Error while writing to download file." +msgstr "Napaka med zapisovanjem v prejeto datoteko." + +msgid "No file name specified for writing." +msgstr "Ime datoteke za pisanje ni določeno." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Datoteke \"%s\" ni mogoče odpreti za pisanje." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Napaka med zapiranjem datoteke \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Napaka med iskanjem v datoteki \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Napaka med pisanjem v datoteko \"%s\"." + +msgid "No file name specified for reading." +msgstr "Ime datoteke za branje ni določeno." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Podatkov o \"%s\" ni mogče pridobiti." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" je mapa." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Datoteka \"%s\" je vtič." + +msgid "Failed after iterations as requested." +msgstr "Po več ponovitvah je bilo (po zahtevi) opravilo neuspešno prekinjeno." + +msgid "caps" +msgstr "velike črke" + +msgid "detected capabilities in stream" +msgstr "zaznane so zmožnosti pretoka" + +msgid "minimum" +msgstr "najmanj" + +msgid "force caps" +msgstr "vsili velike črke" + +msgid "force caps without doing a typefind" +msgstr "vsili velike črke brez potrjevanja pisave" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "Pretok ne vsebuje podatkov." + +msgid "Stream contains no data." +msgstr "Pretok ne vsebuje podatkov." + +msgid "Implemented Interfaces:\n" +msgstr "Vgrajeni vmesniki:\n" + +msgid "readable" +msgstr "berljivo" + +msgid "writable" +msgstr "zapisljivo" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "nadzorljivo" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "spremenljivo le v stanjih NULL, READY, PAUSED in PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "spremenljivo le v stanjih NULL, READY in PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "spremenljivo le v stanjih NULL in READY" + +msgid "Blacklisted files:" +msgstr "Datoteke na črnem seznamu:" + +msgid "Total count: " +msgstr "Skupno: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d datotek na črnem seznamu" +msgstr[1] "%d datoteka na črnem seznamu" +msgstr[2] "%d datoteki na črnem seznamu" +msgstr[3] "%d datoteke na črnem seznamu" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d vstavkov" +msgstr[1] "%d vstavek" +msgstr[2] "%d vstavka" +msgstr[3] "%d vstavki" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d vnosov na črnem seznamu" +msgstr[1] "%d vnos na črnem seznamu" +msgstr[2] "%d vnosa na črnem seznamu" +msgstr[3] "%d vnosi na črnem seznamu" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d zmožnosti" +msgstr[1] "%d zmožnost" +msgstr[2] "%d zmožnosti" +msgstr[3] "%d zmožnosti" + +msgid "Print all elements" +msgstr "Izpiši vse predmete" + +msgid "Print list of blacklisted files" +msgstr "Izpiši seznam datotek na črnem seznamu" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Izpiši strojno razčlenjen seznam možnosti navedenega vstavka ali vseh " +"vstavkov.\n" +" Uporabno v povezavi z zunanjimi " +"mehanizmi za samodejno namestitev vstavkov" + +msgid "List the plugin contents" +msgstr "Izpiši seznam vsebine vstavkov" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "Preveri, če podan predmet ali vstavek že obstaja" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Med preverjanjem, če predmet ali vstavek že obstaja, preveri, če je ustrezna " +"tudi različica" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Izpiši podprte sheme URI s predmeti, ki jih vstavljajo" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Datoteke vstavka ni mogoče naložiti: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Predmet ali datoteka \"%s\" ne obstaja\n" + +msgid "Index statistics" +msgstr "Statistika kazala" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Prejeto sporočilo #%u od predmeta \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Prejeto sporočilo #%u od pladnja \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Prejeto sporočilo #%u od predmeta \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Prejeto sporočilo #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Prejet EOS predmeta \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "NAJDENA OZNAKA : najdeno s predmetom \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "NAJDENA OZNAKA : najdeno s pladnjem \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "NAJDENA OZNAKA : najdeno s predmetom \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "NAJDENA OZNAKA\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "NAJDENO KAZALO : najdeno s predmetom \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "NAJDENO KAZALO : najdeno s predmetom \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "NAJDENO KAZALO\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"PODATKI:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "OPOZORILO: predmet %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Pripravljeno, čakanje na zaključek polnjenja medpomnilnika ...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Pripravljeno, čakanje na zaključek opravila ...\n" + +msgid "buffering..." +msgstr "polnjenje medpomnilnika ..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Polnjenje medpomnilnika je končano, nastavljanje cevovoda na PLAYING ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Polnjenje medpomnilnika, nastavljanje cevovoda na PAUSED ...\n" + +msgid "Redistribute latency...\n" +msgstr "Prerazporejanje pritajenosti ...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Nastavljanje stanja na %s, kot to zahteva %s ...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Prekinitev: zaustavljanje cevovoda ... \n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Napredek: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Manjkajoči element: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Vsebina je bila pridobljena iz elementa \"%s\": %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Izhodne oznake (znane tudi kot metapodatki)" + +msgid "Output TOC (chapters and editions)" +msgstr "Izpiši kazalo (poglavja)" + +msgid "Output status information and property notifications" +msgstr "Izhodni podatki o stanju in obvestila o lastnostih" + +msgid "Do not print any progress information" +msgstr "Ne izpiši podrobnosti napredka" + +msgid "Output messages" +msgstr "Izhodna sporočila" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Na namesti ročnika napak" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Viru vsili EOS pred zaustavitvijo cevovoda" + +msgid "Gather and print index statistics" +msgstr "Zberi in natisni statistiko kazala" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "NAPAKA: cevovoda ni mogoče izgraditi: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "NAPAKA: cevovoda ni mogoče izgraditi.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "OPOZORILO: cevovod z napakami: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "NAPAKA: predmeta \"cevovoda\" ni mogoče najti.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Nastavljanje cevovoda na PAUSED ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "NAPAKA: cevovoda ni mogoče postaviti v mirovanje.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Cevovod je živ in ga ni potrebno pripraviti ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Cevovod se pripravlja ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "NAPAKA: cevovoda ni mogoče pripraviti.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Cevovod je pripravljen ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Nastavljanje cevovoda na PLAYING ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "NAPAKA: vsebine cevovoda ni mogoče predvajati.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS ob izklopu je omogočen -- vsiljen EOS vsebine cevovoda\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS ob izklopu je omogočen -- čakanje na EOS, ki sledi napaki\n" + +msgid "Waiting for EOS...\n" +msgstr "Čakanje na EOS ...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Prejet EOS - zaustavljanje cevovoda ...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Prekinitev med čakanjem na EOS. Zaustavljanje cevovoda ...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Med čakanjem na EOS je prišlo do napake\n" + +msgid "Execution ended after %" +msgstr "Izvajanje je bilo prekinjeno po %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Nastavljanje cevovoda na READY ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Nastavljanje cevovoda na NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Sproščanje cevovoda ...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "Notranja napaka pretoka podatkov." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Ne izpiši podrobnosti stanja VRSTE" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "VRSTA1, VRSTA2 ..." + +#~ msgid "link without source element" +#~ msgstr "povezava brez predmeta vira" + +#~ msgid "link without sink element" +#~ msgstr "povezava brez predmeta ponora" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "ni predmeta za povezovanje naslova \"%s\" na" diff --git a/po/sq.gmo b/po/sq.gmo new file mode 100644 index 0000000..373bec2 Binary files /dev/null and b/po/sq.gmo differ diff --git a/po/sq.po b/po/sq.po new file mode 100644 index 0000000..302ea1d --- /dev/null +++ b/po/sq.po @@ -0,0 +1,1466 @@ +# Përkthimi i mesazheve të gstreamer në shqip. +# Copyright (C) 2004 Free Software Foundation, Inc. +# Laurent Dhima , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 0.8.4\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2004-08-07 23:46+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" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Print the GStreamer version" +msgstr "Printo versionin e GStreamer" + +msgid "Make all warnings fatal" +msgstr "Bëj që të gjithë paralajmërimet të jenë fatale" + +msgid "Print available debug categories and exit" +msgstr "Printo kategoritë e debug në dispozicion dhe dil" + +#, fuzzy +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Niveli i prezgjedhur i debug nga 1 (vetëm gabimi) në 5 (gjithçka) ose 0 për " +"jo output" + +msgid "LEVEL" +msgstr "NIVELI" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Lista e category_name, ndarë me presje:etiketë çifte për të përcaktuar " +"etiketa specifike për kategoritë individuale. Shembull: GST_AUTOPLUG:5," +"GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTË" + +msgid "Disable colored debugging output" +msgstr "Ç'aktivo output shumëngjyrësh të debug" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" + +msgid "Disable debugging" +msgstr "Ç'aktivo debug" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Aktivo kërkesën e plugin të ngarkimit të diagnostikimeve" + +msgid "Colon-separated paths containing plugins" +msgstr "" + +msgid "PATHS" +msgstr "POZICIONET" + +#, fuzzy +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Lista e plugin, të ndarë me presje, që duhen parangarkuar në plotësim të " +"listës së regjistruar tek e ndryshueshmja e ambientit GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PLUGINS" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Ç'aktivo regjistrimin e dështimeve të segmentuara gjatë ngarkimit të plugin" + +msgid "Disable updating the registry" +msgstr "" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" + +msgid "GStreamer Options" +msgstr "" + +#, fuzzy +msgid "Show GStreamer Options" +msgstr "Printo versionin e GStreamer" + +msgid "Unknown option" +msgstr "" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer ndeshi në një gabim të përgjithshëm të librarisë bazë." + +#, fuzzy +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Zhvilluesit e GStreamer ishin tepër të lodhur për t'i caktuar një kod gabimi " +"këtij difekti. Ju lutem dërgoni një raport." + +#, fuzzy +msgid "Internal GStreamer error: code not implemented." +msgstr "Gabim i brendshëm i GStreamer: kodi mungon. Raporto bug." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" + +#, fuzzy +msgid "Internal GStreamer error: pad problem." +msgstr "Gabim i brendshëm i GStreamer: problem me shtegun. Raporto bug." + +#, fuzzy +msgid "Internal GStreamer error: thread problem." +msgstr "Gabim i brendshëm i GStreamer: problem i thread. Raporto bug." + +#, fuzzy +msgid "GStreamer error: negotiation problem." +msgstr "Gabim i brendshëm i GStreamer: problem negocimi. Raporto bug." + +#, fuzzy +msgid "Internal GStreamer error: event problem." +msgstr "Gabim i brendshëm i GStreamer: problem ndodhie. Raporto bug." + +#, fuzzy +msgid "Internal GStreamer error: seek problem." +msgstr "Gabim i brendshëm i GStreamer: problem kërkimi. Raporto bug." + +#, fuzzy +msgid "Internal GStreamer error: caps problem." +msgstr "Gabim i brendshëm i GStreamer: problem drejtimi. Raporto bug." + +#, fuzzy +msgid "Internal GStreamer error: tag problem." +msgstr "Gabim i brendshëm i GStreamer: problem me tag. Raporto bug." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "" + +#, fuzzy +msgid "GStreamer error: clock problem." +msgstr "Gabim i brendshëm i GStreamer: problem kërkimi. Raporto bug." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer ndeshi në një gabim librarie të suportit të përgjithshëm." + +msgid "Could not initialize supporting library." +msgstr "E pamundur nisja e librarisë mbështetëse." + +msgid "Could not close supporting library." +msgstr "E pamundur mbyllja e librarisë mbështetëse." + +#, fuzzy +msgid "Could not configure supporting library." +msgstr "E pamundur mbyllja e librarisë mbështetëse." + +msgid "Encoding error." +msgstr "" + +#, fuzzy +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer ndeshi në një gabim të përgjithshëm të librarisë bazë." + +msgid "Resource not found." +msgstr "Burimi nuk u gjet." + +msgid "Resource busy or not available." +msgstr "Burimi është i zënë ose jo në dispozicion." + +msgid "Could not open resource for reading." +msgstr "E pamundur hapja e burimit për lexim." + +msgid "Could not open resource for writing." +msgstr "E pamundur hapja e burimit për shkrim." + +msgid "Could not open resource for reading and writing." +msgstr "E pamundur hapja e burimit për lexim dhe shkrim." + +msgid "Could not close resource." +msgstr "E pamundur mbyllja e burimit." + +msgid "Could not read from resource." +msgstr "I pamundur leximi nga burimi." + +msgid "Could not write to resource." +msgstr "I pamundur hkrimi në burim." + +msgid "Could not perform seek on resource." +msgstr "E pamundur kryerja e kërkimit në burim." + +msgid "Could not synchronize on resource." +msgstr "Sinkronizim i pamundur në burim." + +msgid "Could not get/set settings from/on resource." +msgstr "E pamundur marrja/vendosja e rregullimeve nga/në burim." + +msgid "No space left on the resource." +msgstr "" + +#, fuzzy +msgid "Not authorized to access resource." +msgstr "I pamundur hkrimi në burim." + +#, fuzzy +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer ndeshi në një gabim të përgjithshëm të librarisë bazë." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementi nuk suporton trajtimin e kësaj vazhde. Ju lutem raporto një bug." + +msgid "Could not determine type of stream." +msgstr "I pamundur përcaktimi i llojit të vazhdës." + +msgid "The stream is of a different type than handled by this element." +msgstr "Vazhda është e një lloji të ndryshëm nga të trajtuarit nga ky element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Asnjë kodues/dekodues në dispozicion për të trajtuar llojin e vazhdës." + +msgid "Could not decode stream." +msgstr "I pamundur dekodifikimi i vazhdës." + +msgid "Could not encode stream." +msgstr "I pamundur kodifikimi i vazhdës." + +msgid "Could not demultiplex stream." +msgstr "I pamundur demultipleksimi i stream." + +msgid "Could not multiplex stream." +msgstr "I pamundur multipleksimi i vazhdës." + +#, fuzzy +msgid "The stream is in the wrong format." +msgstr "Vazhda është në një format të gabuar." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" + +#, c-format +msgid "No error message for domain %s." +msgstr "Asnjë mesazh gabimi për domain %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Asnjë mesazh gabimi standart për domain %s dhe kodin %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "" + +msgid "title" +msgstr "titulli" + +msgid "commonly used title" +msgstr "titulli i përdorur zakonisht" + +msgid "title sortname" +msgstr "" + +#, fuzzy +msgid "commonly used title for sorting purposes" +msgstr "titulli i përdorur zakonisht" + +msgid "artist" +msgstr "artisti" + +msgid "person(s) responsible for the recording" +msgstr "personi(at) përgjegjës për regjistrimin" + +msgid "artist sortname" +msgstr "" + +#, fuzzy +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "personi(at) përgjegjës për regjistrimin" + +msgid "album" +msgstr "albumi" + +msgid "album containing this data" +msgstr "albumi që përmban këtë të dhënë" + +msgid "album sortname" +msgstr "" + +#, fuzzy +msgid "album containing this data for sorting purposes" +msgstr "albumi që përmban këtë të dhënë" + +#, fuzzy +msgid "album artist" +msgstr "artisti" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "" + +msgid "album artist sortname" +msgstr "" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "" + +msgid "date" +msgstr "data" + +#, fuzzy +msgid "date the data was created (as a GDate structure)" +msgstr "data e krijimit të së dhënës (në ditë të kalendarit Julian)" + +#, fuzzy +msgid "datetime" +msgstr "data" + +#, fuzzy +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "data e krijimit të së dhënës (në ditë të kalendarit Julian)" + +msgid "genre" +msgstr "lloji" + +msgid "genre this data belongs to" +msgstr "lloji së cilit i takon e dhëna" + +msgid "comment" +msgstr "komenti" + +msgid "free text commenting the data" +msgstr "tekst i lirë komentues i së dhënës" + +#, fuzzy +msgid "extended comment" +msgstr "komenti" + +#, fuzzy +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "tekst i lirë komentues i së dhënës" + +msgid "track number" +msgstr "numri i pistës" + +msgid "track number inside a collection" +msgstr "numri i pjesës në brendësi të një koleksioni" + +msgid "track count" +msgstr "numërimi i pjesës" + +msgid "count of tracks inside collection this track belongs to" +msgstr "numurimi i pjesëve në brendësi të koleksionit të cilit i përket pjesa" + +msgid "disc number" +msgstr "numri i diskut" + +msgid "disc number inside a collection" +msgstr "numri i diskut në brendësi të një koleksioni" + +msgid "disc count" +msgstr "numurimi i diskut" + +msgid "count of discs inside collection this disc belongs to" +msgstr "numurimi i disqeve në brendësi të koleksionit të cilit i përket disku" + +msgid "location" +msgstr "pozicioni" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" + +msgid "homepage" +msgstr "" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" + +msgid "description" +msgstr "përshkrimi" + +msgid "short text describing the content of the data" +msgstr "teks i shkurtër përshkrues i përmbajtjes së së dhënës" + +msgid "version" +msgstr "versioni" + +msgid "version of this data" +msgstr "versioni i kësaj të dhëne" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"International Standard Recording Code - shiko http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organizata" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "shënime mbi të drejtat e së dhënës" + +#, fuzzy +msgid "copyright uri" +msgstr "copyright" + +#, fuzzy +msgid "URI to the copyright notice of the data" +msgstr "shënime mbi të drejtat e së dhënës" + +#, fuzzy +msgid "encoded by" +msgstr "kodifikuesi" + +msgid "name of the encoding person or organization" +msgstr "" + +msgid "contact" +msgstr "kontakti" + +msgid "contact information" +msgstr "informacione në lidhje me kontaktin" + +msgid "license" +msgstr "liçenca" + +msgid "license of data" +msgstr "liçenca e së dhënës" + +#, fuzzy +msgid "license uri" +msgstr "liçenca" + +#, fuzzy +msgid "URI to the license of the data" +msgstr "liçenca e së dhënës" + +msgid "performer" +msgstr "interpretuesi" + +msgid "person(s) performing" +msgstr "personi(at) interpretues" + +msgid "composer" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording" +msgstr "personi(at) përgjegjës për regjistrimin" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "kohëzgjatja" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "gjatësia në njësi kohore të GStreamer (nanosekonda)" + +msgid "codec" +msgstr "codec" + +msgid "codec the data is stored in" +msgstr "codec ku janë regjistruar të dhënat" + +msgid "video codec" +msgstr "video codec" + +msgid "codec the video data is stored in" +msgstr "codec ku janë regjistruar të dhënat video" + +msgid "audio codec" +msgstr "audio codec" + +msgid "codec the audio data is stored in" +msgstr "codec ku janë regjistruar të dhënat audio" + +#, fuzzy +msgid "subtitle codec" +msgstr "video codec" + +#, fuzzy +msgid "codec the subtitle data is stored in" +msgstr "codec ku janë regjistruar të dhënat video" + +#, fuzzy +msgid "container format" +msgstr "informacione në lidhje me kontaktin" + +#, fuzzy +msgid "container format the data is stored in" +msgstr "codec ku janë regjistruar të dhënat" + +msgid "bitrate" +msgstr "bitrate" + +msgid "exact or average bitrate in bits/s" +msgstr "bitrate preçize ose mesatare në bits/s" + +msgid "nominal bitrate" +msgstr "bitrate nominale" + +msgid "nominal bitrate in bits/s" +msgstr "bitrate nominale në bits/s" + +msgid "minimum bitrate" +msgstr "bitrate minimum" + +msgid "minimum bitrate in bits/s" +msgstr "bitrate minimum në bits/s" + +msgid "maximum bitrate" +msgstr "bitrate maksimum" + +msgid "maximum bitrate in bits/s" +msgstr "bitrate maksimum në bits/s" + +msgid "encoder" +msgstr "kodifikuesi" + +msgid "encoder used to encode this stream" +msgstr "kodifikuesi i përdorur për të kodifikuar këtë fluks" + +msgid "encoder version" +msgstr "versioni i kodifikuesit" + +msgid "version of the encoder used to encode this stream" +msgstr "versioni i kodifikuesit të përdorur për të kodifikuar këtë fluks" + +msgid "serial" +msgstr "seria" + +msgid "serial number of track" +msgstr "numri serisë së pjesës" + +msgid "replaygain track gain" +msgstr "ecuria i pjesës në replygain" + +msgid "track gain in db" +msgstr "rritja e pjesës në db" + +msgid "replaygain track peak" +msgstr "maksimumi i pjesës në replygain" + +msgid "peak of the track" +msgstr "skaji i pistës" + +msgid "replaygain album gain" +msgstr "replaygain album gain" + +msgid "album gain in db" +msgstr "gain i albumit në db" + +msgid "replaygain album peak" +msgstr "replaygain album peak" + +msgid "peak of the album" +msgstr "kulmi i albumit" + +#, fuzzy +msgid "replaygain reference level" +msgstr "maksimumi i pjesës në replygain" + +msgid "reference level of track and album gain values" +msgstr "" + +msgid "language code" +msgstr "" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" + +msgid "language name" +msgstr "" + +msgid "freeform name of the language this stream is in" +msgstr "" + +msgid "image" +msgstr "" + +#, fuzzy +msgid "image related to this stream" +msgstr "kodifikuesi i përdorur për të kodifikuar këtë fluks" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "" + +msgid "preview image related to this stream" +msgstr "" + +msgid "attachment" +msgstr "" + +#, fuzzy +msgid "file attached to this stream" +msgstr "kodifikuesi i përdorur për të kodifikuar këtë fluks" + +msgid "beats per minute" +msgstr "" + +msgid "number of beats per minute in audio" +msgstr "" + +msgid "keywords" +msgstr "" + +#, fuzzy +msgid "comma separated keywords describing the content" +msgstr "teks i shkurtër përshkrues i përmbajtjes së së dhënës" + +#, fuzzy +msgid "geo location name" +msgstr "pozicioni" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" + +msgid "geo location latitude" +msgstr "" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" + +msgid "geo location longitude" +msgstr "" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" + +msgid "geo location elevation" +msgstr "" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" + +#, fuzzy +msgid "geo location country" +msgstr "pozicioni" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location city" +msgstr "pozicioni" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" + +#, fuzzy +msgid "geo location sublocation" +msgstr "pozicioni" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" + +#, fuzzy +msgid "geo location horizontal error" +msgstr "pozicioni" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "" + +#, fuzzy +msgid "geo location movement speed" +msgstr "pozicioni" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" + +#, fuzzy +msgid "geo location movement direction" +msgstr "pozicioni" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" + +#, fuzzy +msgid "geo location capture direction" +msgstr "pozicioni" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" + +#, fuzzy +msgid "episode number" +msgstr "numri i diskut" + +msgid "The episode number in the season the media is part of" +msgstr "" + +#, fuzzy +msgid "season number" +msgstr "numri i diskut" + +msgid "The season number of the show the media is part of" +msgstr "" + +#, fuzzy +msgid "lyrics" +msgstr "liçenca" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "" + +msgid "composer sortname" +msgstr "" + +#, fuzzy +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "personi(at) përgjegjës për regjistrimin" + +msgid "grouping" +msgstr "" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" + +#, fuzzy +msgid "user rating" +msgstr "kohëzgjatja" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" + +msgid "device manufacturer" +msgstr "" + +#, fuzzy +msgid "Manufacturer of the device used to create this media" +msgstr "versioni i kodifikuesit të përdorur për të kodifikuar këtë fluks" + +msgid "device model" +msgstr "" + +#, fuzzy +msgid "Model of the device used to create this media" +msgstr "versioni i kodifikuesit të përdorur për të kodifikuar këtë fluks" + +#, fuzzy +msgid "application name" +msgstr "pozicioni" + +#, fuzzy +msgid "Application used to create the media" +msgstr "versioni i kodifikuesit të përdorur për të kodifikuar këtë fluks" + +msgid "application data" +msgstr "" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" + +msgid "image orientation" +msgstr "" + +msgid "How the image should be rotated or flipped before display" +msgstr "" + +msgid "publisher" +msgstr "" + +msgid "Name of the label or publisher" +msgstr "" + +msgid "interpreted-by" +msgstr "" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "" + +msgid "midi-base-note" +msgstr "" + +msgid "Midi note number of the audio track." +msgstr "" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "GABIM: nga elementi %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Informacione shtesë të debug:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "asnjë pronësi \"%s\" tek elementi \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "e pamundur vendosja e pronësisë \"%s\" tek elementi \"%s\" në \"%s" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "e pamundur lidhja e %s me %s" + +#, fuzzy, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "e pamundur lidhja e elementit sink për URI \"%s\"" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "e pamundur lidhja e %s me %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "e pamundur lidhja e %s me %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "asnjë element \"%s\"" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "i pamundur analizimi i caps \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "asnjë element shpërndarës për URI \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "asnjë element burues për URI \"%s\"" + +msgid "syntax error" +msgstr "" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "u specifikua bin bosh \"%s\", nuk lejohet" + +#, fuzzy, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "asnjë bin \"%s\", u kapërcye" + +msgid "empty pipeline not allowed" +msgstr "nuk lejohet konduktori bosh" + +msgid "A lot of buffers are being dropped." +msgstr "" + +msgid "Internal data flow problem." +msgstr "" + +msgid "Internal data flow error." +msgstr "" + +msgid "Internal clock error." +msgstr "" + +msgid "Failed to map buffer." +msgstr "" + +msgid "Filter caps" +msgstr "" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "" + +#, fuzzy, c-format +msgid "Could not create temp file \"%s\"." +msgstr "E pamundur marrja/vendosja e rregullimeve nga/në burim." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "E pamundur hapja e file \"%s\" për lexim." + +#, fuzzy +msgid "Error while writing to download file." +msgstr "Gabim gjatë shkrimit tek file \"%s\"." + +msgid "No file name specified for writing." +msgstr "Nuk është përcaktuar asnjë emër file për tu shkruar." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "E pamundur hapja e file \"%s\" në shkrim." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Gabim gjatë mbylljes së file \"%s\"." + +#, fuzzy, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Gabim gjatë shkrimit tek file \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Gabim gjatë shkrimit tek file \"%s\"." + +msgid "No file name specified for reading." +msgstr "Nuk është përcaktuar asnjë emër file për tu lexuar." + +#, fuzzy, c-format +msgid "Could not get info on \"%s\"." +msgstr "E pamundur marrja/vendosja e rregullimeve nga/në burim." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" është një directory." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "File \"%s\" është një socket." + +msgid "Failed after iterations as requested." +msgstr "Dështoi mbas përsëritjeve sikurse të kërkuara." + +msgid "caps" +msgstr "mbrojtëse" + +msgid "detected capabilities in stream" +msgstr "u zbuluan mundësi në fluks" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "" + +msgid "force caps without doing a typefind" +msgstr "" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "albumi që përmban këtë të dhënë" + +#, fuzzy +msgid "Stream contains no data." +msgstr "albumi që përmban këtë të dhënë" + +msgid "Implemented Interfaces:\n" +msgstr "" + +msgid "readable" +msgstr "" + +#, fuzzy +msgid "writable" +msgstr "titulli" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "" + +msgid "changeable only in NULL or READY state" +msgstr "" + +msgid "Blacklisted files:" +msgstr "" + +#, fuzzy +msgid "Total count: " +msgstr "numërimi i pjesës" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "" +msgstr[1] "" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "" +msgstr[1] "" + +#, fuzzy, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "karakteristika" +msgstr[1] "karakteristikat" + +msgid "Print all elements" +msgstr "Printo të gjithë elementët" + +msgid "Print list of blacklisted files" +msgstr "" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" + +msgid "List the plugin contents" +msgstr "" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" + +#, fuzzy, c-format +msgid "Could not load plugin file: %s\n" +msgstr "E pamundur hapja e file \"%s\" në shkrim." + +#, fuzzy, c-format +msgid "No such element or plugin '%s'\n" +msgstr "asnjë element burues për URI \"%s\"" + +msgid "Index statistics" +msgstr "" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "" + +#, fuzzy, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "GABIM: nga elementi %s: %s\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "NDRYSHIM I GJETUR : u gjet nga elementi \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "NDRYSHIM I GJETUR : u gjet nga elementi \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "NDRYSHIM I GJETUR : u gjet nga elementi \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "" + +#, fuzzy, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "NDRYSHIM I GJETUR : u gjet nga elementi \"%s\".\n" + +#, fuzzy, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "NDRYSHIM I GJETUR : u gjet nga elementi \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" + +#, fuzzy, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "GABIM: nga elementi %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" + +msgid "buffering..." +msgstr "" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "" + +msgid "Redistribute latency...\n" +msgstr "" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "" + +#, fuzzy, c-format +msgid "Missing element: %s\n" +msgstr "asnjë element \"%s\"" + +#, fuzzy, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "GABIM: nga elementi %s: %s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Tags e output (njohur gjithashtu si metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "" + +msgid "Output status information and property notifications" +msgstr "Njoftime të informacioneve dhe pronësisë së kondicionit të daljes" + +#, fuzzy +msgid "Do not print any progress information" +msgstr "Mos jep informacionin e gjendjes së LLOJIT" + +msgid "Output messages" +msgstr "" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "Mos instalo një ushqyes të dëmtuar" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "" + +msgid "Gather and print index statistics" +msgstr "" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "GABIM: i pamundur ndërtimi i pipeline: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "GABIM: i pamundur ndërtimi i pipeline.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "KUJDES: pipline e gabuar: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "GABIM: elementi 'konduktor' nuk u gjet.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "GABIM: pipeline nuk dëshiron të luajë.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "" + +#, fuzzy +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "GABIM: pipeline nuk dëshiron të luajë.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "GABIM: pipeline nuk dëshiron të luajë.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "" + +msgid "Waiting for EOS...\n" +msgstr "" + +msgid "EOS received - stopping pipeline...\n" +msgstr "" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" + +msgid "An error happened while waiting for EOS\n" +msgstr "" + +msgid "Execution ended after %" +msgstr "Ekzekutimi përfundoi mbas %" + +msgid "Setting pipeline to READY ...\n" +msgstr "" + +msgid "Setting pipeline to NULL ...\n" +msgstr "" + +#, fuzzy +msgid "Freeing pipeline ...\n" +msgstr "DUKE ZBATUAR pipeline ...\n" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Mos jep informacionin e gjendjes së LLOJIT" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "LLOJI1,LLOJI2,..." + +#~ msgid "link without source element" +#~ msgstr "lidhje ma element burues" + +#~ msgid "link without sink element" +#~ msgstr "lidhje pa elementin sink" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "asnjë element për të lidhur URI \"%s\" me" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "Printo shenjat e alloc (nëse aktivuar në kohën e kompilimit)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Përdorimi: gst-xmllaunch [ element.property=vlera ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "GABIM: analizimi i file xml '%s' dështoi.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "GABIM: asnjë element i pipline të toplevel tek file '%s'.\n" + +#, fuzzy +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "KUJDES: vetëm një element toplevel suportohet aktualisht." + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "GABIM: i pamundur analizimi i argumentit %d të rreshtit të komandës: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "KUJDES: elementi me emrin '%s' nuk u gjet.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Ruaj prezantimin xml të pipeline tek FILE dhe dil" + +#~ msgid "FILE" +#~ msgstr "FILE" + +#, fuzzy +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Mos instalo një ushqyes të dëmtuar" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Ç'aktivo instruksionet e përshpejtimit të CPU" + +#~ msgid "SCHEDULER" +#~ msgstr "PLANIFIKUES" + +#~ msgid "Registry to use" +#~ msgstr "Regjistri që duhet përdorur" + +#~ msgid "REGISTRY" +#~ msgstr "REGJISTRI" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "pozicioni i listës për ngarkimin e plugins (ndarë me '%s')" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "Planifikuesi që duhet përdorur (i prezgjedhuri është '%s')" + +#~ msgid "Internal GStreamer error: state change failed. File a bug." +#~ msgstr "" +#~ "Gabim i brendshëm i GStreamer: ndryshimi i gjendjes dështoi. Raporto bug." + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "Gabim i brendshëm i GStreamer: problem planifikimi. Raporto bug." + +#~ msgid "original location of file as a URI" +#~ msgstr "vendodhja orgjinale e file si një URI" + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "" +#~ "Nuk ekziston asnjë element për të trajtuar llojin mime %s të fluksit." + +#~ msgid " iterations (sum %" +#~ msgstr " përsëritjet (shuma %" + +#~ msgid " ns, average %" +#~ msgstr " ns, mesatarja %" + +#~ msgid " ns, min %" +#~ msgstr " ns, min %" + +#~ msgid " ns, max %" +#~ msgstr " ns, max %" + +#~ msgid " ns).\n" +#~ msgstr " ns).\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Numri i herëve të përsëritjes së kanalit" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Duke u përpjekur të zbatohet sidoqoftë.\n" + +#~ msgid "Added plugin %s with %d %s.\n" +#~ msgstr "U shtua plugin %s me %d %s.\n" + +#~ msgid "Added path %s to %s \n" +#~ msgstr "U shtua pozicioni %s tek %s \n" + +#~ msgid "Rebuilding %s (%s) ...\n" +#~ msgstr "Duke rindërtuar %s (%s) ...\n" + +#~ msgid "Trying to load %s ...\n" +#~ msgstr "Duke u përpjekur të ngarkoj %s ...\n" + +#~ msgid "Error loading %s\n" +#~ msgstr "Gabim gjatë ngarkimit të %s\n" + +#~ msgid "Loaded %d plugins with %d %s.\n" +#~ msgstr "U ngarkuan %d plugins me %d %s.\n" diff --git a/po/sr.gmo b/po/sr.gmo new file mode 100644 index 0000000..49ce34b Binary files /dev/null and b/po/sr.gmo differ diff --git a/po/sr.po b/po/sr.po new file mode 100644 index 0000000..1a8033d --- /dev/null +++ b/po/sr.po @@ -0,0 +1,1364 @@ +# Serbian translation of gstreamer +# Copyright © 2014 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Danilo Segan , 2004-2005. +# Мирослав Николић , 2011—2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer-1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-07 12:42+0200\n" +"Last-Translator: Мирослав Николић \n" +"Language-Team: Serbian <(nothing)>\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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"X-Project-Style: gnome\n" + +msgid "Print the GStreamer version" +msgstr "Исписује издање Гстримера" + +msgid "Make all warnings fatal" +msgstr "Чини сва упозорења кобним" + +msgid "Print available debug categories and exit" +msgstr "Исписује доступне категорије за уклањање грешака и излази" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Основни ниво за уклањање грешака од 1 (само грешке) до 9 (све) или 0 (без " +"излаза)" + +msgid "LEVEL" +msgstr "НИВО" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Зарезом одвојен списак парова назив_категорије:ниво за постављање нарочитих " +"нивоа за појединачне категорије. Пример: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "СПИСАК" + +msgid "Disable colored debugging output" +msgstr "Искључује обојени излаз за уклањање грешака" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Мења режим бојења дневника за уклањање грешака. Могући режими су: off, on, " +"disable, auto, unix" + +msgid "Disable debugging" +msgstr "Искључује уклањање грешака" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Укључује опширну дијагностику учитавања прикључка" + +msgid "Colon-separated paths containing plugins" +msgstr "Двотачком раздвојене путање које садрже прикључке" + +msgid "PATHS" +msgstr "ПУТАЊЕ" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Зарезом раздвојен списак прикључака који ће бити унапред учитани као додатак " +"списку који се чува у променљивој окружења GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "ПРИКЉУЧЦИ" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Искључује пресретање погрешних приступа меморији приликом учитавања прикључка" + +msgid "Disable updating the registry" +msgstr "Искључује ажурирање регистра" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Искључује израђање помоћниковог процеса приликом претраживања регистра" + +msgid "GStreamer Options" +msgstr "Опције Гстримера" + +msgid "Show GStreamer Options" +msgstr "Приказује опције Гстримера" + +msgid "Unknown option" +msgstr "Непозната опција" + +msgid "GStreamer encountered a general core library error." +msgstr "Гстример је наишао на општу грешку у основној библиотеци." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Програмери Гстримера су били сувише лењи да доделе неки кôд за ову грешку." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Унутрашња грешка Гстримера: кôд није примењен. " + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Грешка Гстримера: промена стања није успела и неки елемент није успео да " +"огласи сопствену поруку грешке са разлогом неуспеха." + +msgid "Internal GStreamer error: pad problem." +msgstr "Унутрашња грешка Гстримера: неприлика са попуном." + +msgid "Internal GStreamer error: thread problem." +msgstr "Унутрашња грешка Гстримера: неприлика са нитима." + +msgid "GStreamer error: negotiation problem." +msgstr "грешка Гстримера: неприлика у преговарању." + +msgid "Internal GStreamer error: event problem." +msgstr "Унутрашња грешка Гстримера: неприлика са догађајем." + +msgid "Internal GStreamer error: seek problem." +msgstr "Унутрашња грешка Гстримера: неприлика са тражењем." + +# bug: is "caps" short for "capabilities"? if so, it should be spelled completely +msgid "Internal GStreamer error: caps problem." +msgstr "Унутрашња грешка Гстримера: неприлика са могућностима." + +msgid "Internal GStreamer error: tag problem." +msgstr "Унутрашња грешка Гстримера: неприлика са ознаком." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Вашој инсталацији Гстримера недостаје прикључак." + +msgid "GStreamer error: clock problem." +msgstr "Грешка Гстримера: неприлика са сатом." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Овај програм покушава да користи функционалност Гстримера која је искључена." + +msgid "GStreamer encountered a general supporting library error." +msgstr "Гстример је наишао на општу грешку у библиотеци подршке." + +msgid "Could not initialize supporting library." +msgstr "Не могу да покренем библиотеку подршке." + +msgid "Could not close supporting library." +msgstr "Не могу да затворим библиотеку подршке." + +msgid "Could not configure supporting library." +msgstr "Не могу да подесим библиотеку подршке." + +msgid "Encoding error." +msgstr "Грешка кодирања." + +msgid "GStreamer encountered a general resource error." +msgstr "Гстример је наишао на општу грешку изворишта." + +msgid "Resource not found." +msgstr "Извориште није нађено." + +msgid "Resource busy or not available." +msgstr "Извориште је заузето или недоступно." + +msgid "Could not open resource for reading." +msgstr "Не могу да отворим извориште ради читања." + +msgid "Could not open resource for writing." +msgstr "Не могу да отворим извориште ради уписа." + +msgid "Could not open resource for reading and writing." +msgstr "Не могу да отворим извориште ради читања и писања." + +msgid "Could not close resource." +msgstr "Не могу да затворим извориште." + +msgid "Could not read from resource." +msgstr "Не могу да читам из изворишта." + +msgid "Could not write to resource." +msgstr "Не могу да упишем у извориште." + +msgid "Could not perform seek on resource." +msgstr "Не могу да извршим постављање на изворишту." + +msgid "Could not synchronize on resource." +msgstr "Не могу да ускладим са извориштем." + +msgid "Could not get/set settings from/on resource." +msgstr "Не могу да добавим/поставим подешавања из/у извориште." + +msgid "No space left on the resource." +msgstr "Није преостало простора у изворишту." + +msgid "Not authorized to access resource." +msgstr "Нисам овлашћен да приступим изворишту." + +msgid "GStreamer encountered a general stream error." +msgstr "Гстример је наишао на општу грешку тока." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Елемент не обезбеђује баратање овим током. Пријавите грешку." + +msgid "Could not determine type of stream." +msgstr "Не могу да одредим врсту тока." + +msgid "The stream is of a different type than handled by this element." +msgstr "Ток је врсте различите од оне којим барата овај елемент." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Није присутно кодирање које може да барата током ове врсте." + +msgid "Could not decode stream." +msgstr "Не могу да декодирам ток." + +msgid "Could not encode stream." +msgstr "Не могу да кодирам ток." + +# несигурно +msgid "Could not demultiplex stream." +msgstr "Не могу да разградим ток." + +# несигурно +msgid "Could not multiplex stream." +msgstr "Не могу да изградим ток." + +msgid "The stream is in the wrong format." +msgstr "Ток је у погрешном запису." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Ток је шифрован али дешифровање није подржано." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Ток је шифрован и не може бити дешифрован зато што није придодат " +"одговарајући кључ." + +#, c-format +msgid "No error message for domain %s." +msgstr "Нема поруке о грешци за домен %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Нема уобичајене поруке о грешци за домен %s и код %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Изабрани сат не може бити коришћен у спојци низа." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Грешка записивања оставе регистра у %s: %s" + +msgid "title" +msgstr "наслов" + +msgid "commonly used title" +msgstr "уобичајено коришћен наслов" + +msgid "title sortname" +msgstr "назив наслова при ређању" + +msgid "commonly used title for sorting purposes" +msgstr "уобичајено коришћен наслов за сврхе ређања" + +msgid "artist" +msgstr "извођач" + +msgid "person(s) responsible for the recording" +msgstr "особе одговорне за снимање" + +msgid "artist sortname" +msgstr "име извођача при ређању" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "особе одговорне за снимање за сврхе ређања" + +msgid "album" +msgstr "албум" + +msgid "album containing this data" +msgstr "албум који садржи ове податке" + +msgid "album sortname" +msgstr "назив албума при ређању" + +msgid "album containing this data for sorting purposes" +msgstr "албум који садржи ове податке за сврхе ређања" + +msgid "album artist" +msgstr "извођач албума" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Извођач читавог албума, онако како треба бити приказан" + +msgid "album artist sortname" +msgstr "име извођача албума при ређању" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Извођач читавог албума, онако како треба бити поређан" + +msgid "date" +msgstr "датум" + +msgid "date the data was created (as a GDate structure)" +msgstr "датум стварања података (као број Јулијанског дана)" + +msgid "datetime" +msgstr "датум и време" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "датум и време стварања података (као број Јулијанског дана)" + +msgid "genre" +msgstr "жанр" + +msgid "genre this data belongs to" +msgstr "жанр којем ови подаци припадају" + +msgid "comment" +msgstr "напомена" + +msgid "free text commenting the data" +msgstr "слободан текст о овим подацима" + +msgid "extended comment" +msgstr "додатна напомена" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"слободан текст о овим подацима у облику кључ=вредност или кључ[en]=напомена" + +# можда „нумере“ уместо „песме“, пошто можемо имати и видео снимке +msgid "track number" +msgstr "број нумере" + +msgid "track number inside a collection" +msgstr "број нумере у збирци" + +msgid "track count" +msgstr "укупно нумера" + +msgid "count of tracks inside collection this track belongs to" +msgstr "укупно нумера у збирци којој припада ова нумера" + +msgid "disc number" +msgstr "број диска" + +msgid "disc number inside a collection" +msgstr "број диска у збирци" + +msgid "disc count" +msgstr "укупно дискова" + +msgid "count of discs inside collection this disc belongs to" +msgstr "укупно дискова у збирци којој припада овај диск" + +msgid "location" +msgstr "положај" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Порекло медија дато као адреса (место, где се налази оригинална датотека или " +"ток)" + +msgid "homepage" +msgstr "матична страница" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Матична страница за овај медиј (нпр. матична страница извођача или филма)" + +msgid "description" +msgstr "опис" + +msgid "short text describing the content of the data" +msgstr "кратак текст који описује садржај података" + +# +msgid "version" +msgstr "издање" + +msgid "version of this data" +msgstr "издање ових података" + +msgid "ISRC" +msgstr "МСКС" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Међународни стандардни код за снимање — погледајте „http://www.ifpi.org/" +"isrc/“" + +msgid "organization" +msgstr "организација" + +msgid "copyright" +msgstr "ауторска права" + +msgid "copyright notice of the data" +msgstr "порука о ауторским правима за податке" + +msgid "copyright uri" +msgstr "адреса ауторских права" + +msgid "URI to the copyright notice of the data" +msgstr "адреса до поруке о ауторским правима за податке" + +msgid "encoded by" +msgstr "кодирао" + +msgid "name of the encoding person or organization" +msgstr "име особе или назив организације кодирања" + +msgid "contact" +msgstr "контакт" + +msgid "contact information" +msgstr "подаци за ступање у везу" + +msgid "license" +msgstr "дозвола" + +msgid "license of data" +msgstr "дозвола за употребу података" + +msgid "license uri" +msgstr "адреса дозволе" + +msgid "URI to the license of the data" +msgstr "адреса до дозволе за употребу података" + +msgid "performer" +msgstr "извођач" + +msgid "person(s) performing" +msgstr "особе које изводе" + +msgid "composer" +msgstr "састављач" + +msgid "person(s) who composed the recording" +msgstr "особе које су саставиле снимак" + +msgid "conductor" +msgstr "диригент" + +msgid "conductor/performer refinement" +msgstr "диригент/појашњење извођача" + +msgid "duration" +msgstr "трајање" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "дужина у временским јединицама Гстримера (наносекундама)" + +msgid "codec" +msgstr "кодек" + +msgid "codec the data is stored in" +msgstr "кодек у коме су подаци сачувани" + +msgid "video codec" +msgstr "видео кодек" + +msgid "codec the video data is stored in" +msgstr "кодек у коме су видео подаци сачувани" + +msgid "audio codec" +msgstr "звучни кодек" + +msgid "codec the audio data is stored in" +msgstr "кодек у коме су звучни подаци сачувани" + +msgid "subtitle codec" +msgstr "кодек превода" + +msgid "codec the subtitle data is stored in" +msgstr "кодек у коме су подаци превода сачувани" + +msgid "container format" +msgstr "облик садржаоца" + +msgid "container format the data is stored in" +msgstr "облик садржаоца у коме су подаци сачувани" + +msgid "bitrate" +msgstr "брзина битова" + +msgid "exact or average bitrate in bits/s" +msgstr "тачна или просечна брзина битова у битовима по секунди" + +msgid "nominal bitrate" +msgstr "наведена брзина битова" + +msgid "nominal bitrate in bits/s" +msgstr "наведена брзина битова у битовима по секунди" + +msgid "minimum bitrate" +msgstr "најмања брзина битова" + +msgid "minimum bitrate in bits/s" +msgstr "најмања брзина битова у битовима по секунди" + +msgid "maximum bitrate" +msgstr "највећа брзина битова" + +msgid "maximum bitrate in bits/s" +msgstr "највећа брзина битова у битовима по секунди" + +msgid "encoder" +msgstr "кодер" + +msgid "encoder used to encode this stream" +msgstr "кодер коришћен за кодирање овог тока" + +msgid "encoder version" +msgstr "издање кодера" + +msgid "version of the encoder used to encode this stream" +msgstr "издање кодера коришћеног за кодирање овог тока" + +msgid "serial" +msgstr "серија" + +msgid "serial number of track" +msgstr "серијски број нумере" + +# bug: this is something strange +msgid "replaygain track gain" +msgstr "појачање нумере појачања пуштања" + +msgid "track gain in db" +msgstr "појачање песме у децибелима" + +msgid "replaygain track peak" +msgstr "врхунац нумере појачања пуштања" + +msgid "peak of the track" +msgstr "врхунац нумере" + +msgid "replaygain album gain" +msgstr "појачање албума појачања пуштања" + +msgid "album gain in db" +msgstr "појачање албума у децибелима" + +msgid "replaygain album peak" +msgstr "врхунац албума појачања пуштања" + +msgid "peak of the album" +msgstr "врхунац албума" + +msgid "replaygain reference level" +msgstr "ниво подсетника појачања пуштања" + +msgid "reference level of track and album gain values" +msgstr "подсетни ниво вредности појачања нумере и албума" + +msgid "language code" +msgstr "шифра језика" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "шифра језика за овај ток, према стандарду ИСО-639-1 или ИСО-639-2" + +msgid "language name" +msgstr "назив језика" + +msgid "freeform name of the language this stream is in" +msgstr "слободан облик назива језика на коме је овај ток" + +msgid "image" +msgstr "слика" + +msgid "image related to this stream" +msgstr "слика која се односи на овај ток" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "слика прегледа" + +msgid "preview image related to this stream" +msgstr "слика прегледа која се односи на овај ток" + +msgid "attachment" +msgstr "прилог" + +msgid "file attached to this stream" +msgstr "датотека приложена уз овај ток" + +msgid "beats per minute" +msgstr "тактова у минуту" + +msgid "number of beats per minute in audio" +msgstr "број тактова у минуту у звуку" + +msgid "keywords" +msgstr "кључне речи" + +msgid "comma separated keywords describing the content" +msgstr "зарезом одвојене кључне речи које описују садржај" + +msgid "geo location name" +msgstr "назив географског места" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "људима читљиво описно место где је медиј снимљен или произведен" + +msgid "geo location latitude" +msgstr "латитуда гео положаја" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"географска ширина места у коме је медиј снимљен или произведен у степенима " +"према стандарду „WGS84“ (нула на екватору, негативне вредности за јужне " +"ширине)" + +msgid "geo location longitude" +msgstr "лонгитуда гео положаја" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"географска дужина места у коме је медиј снимљен или произведен у степенима " +"према стандарду „WGS84“ (нула на првом меридијану у Гринвичу/Велика " +"Британија, негативне вредности за западне дужине)" + +msgid "geo location elevation" +msgstr "издигнуће гео положаја" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"надморска висина места у коме је медиј снимљен или произведен у метрима " +"према стандарду „WGS84“ (нула је просечни ниво мора)" + +msgid "geo location country" +msgstr "земља гео положаја" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "земља (енглески назив) у којој је медиј снимљен или произведен" + +msgid "geo location city" +msgstr "град гео положаја" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "град (енглески назив) у коме је медиј снимљен или произведен" + +msgid "geo location sublocation" +msgstr "потположај гео положаја" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"место унутар града у коме је медиј произведен или створен (нпр. суседство)" + +msgid "geo location horizontal error" +msgstr "водоравна грешка гео положаја" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "очекивана грешка мерења водоравног позиционирања (у метрима)" + +msgid "geo location movement speed" +msgstr "брзина кретања гео положаја" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"брзина кретања уређаја за снимање приликом извршавања снимања у метрима у " +"секунди" + +msgid "geo location movement direction" +msgstr "усмерење кретања гео положаја" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"означава усмерење кретања уређаја приликом снимања медија. Представља се у " +"степенима са покретним зарезом, 0 значи северни пол, и повећава се у смеру " +"казаљке на сату." + +msgid "geo location capture direction" +msgstr "усмерење снимања гео положаја" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"означава усмерење на које уређај указује приликом снимања медија. Представља " +"се у степенима са покретним зарезом, 0 значи северни пол, и повећава се у " +"смеру казаљке на сату." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "назив програма" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Назив програма телевизије/подемисије/серије из ког је медиј" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "назив програма при ређању" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Назив програма телевизије/подемисије/серије из ког је медиј, за сврхе ређања" + +msgid "episode number" +msgstr "број епизоде" + +msgid "The episode number in the season the media is part of" +msgstr "Број епизоде сезоне којој припада медиј" + +msgid "season number" +msgstr "број сезоне" + +msgid "The season number of the show the media is part of" +msgstr "Број сезоне програма којој припада медиј" + +msgid "lyrics" +msgstr "стихови" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Стихови медија, обично коришћени за песме" + +msgid "composer sortname" +msgstr "назив састављача при ређању" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "особе које су саставиле снимање, за сврхе ређања" + +msgid "grouping" +msgstr "груписање" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Групише одговарајуће медије који обухватају више нумера, као различите " +"делове концерта. То је виши ниво од нумере, али нижи од албума." + +msgid "user rating" +msgstr "оцене корисника" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Оцене које су доделили корисници. Виши ли је пласман, то се већем броју " +"корисника свиђа овај медиј." + +msgid "device manufacturer" +msgstr "произвођач уређаја" + +msgid "Manufacturer of the device used to create this media" +msgstr "Произвођач уређаја који је коришћен за стварање овог медија" + +msgid "device model" +msgstr "модел уређаја" + +msgid "Model of the device used to create this media" +msgstr "Модел уређаја који је коришћен за стварање овог медија" + +msgid "application name" +msgstr "назив апликације" + +msgid "Application used to create the media" +msgstr "Апликација која је коришћена за стварање медија" + +msgid "application data" +msgstr "подаци апликације" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Произвољни подаци апликације који ће бити запаковани у медиј" + +msgid "image orientation" +msgstr "усмерење слике" + +msgid "How the image should be rotated or flipped before display" +msgstr "Како би слика требала да буде окренута или изврнута пре приказивања" + +msgid "publisher" +msgstr "издавач" + +msgid "Name of the label or publisher" +msgstr "Назив натписа или издавача" + +msgid "interpreted-by" +msgstr "извођач" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Подаци о људима који су урадили ремикс и сличне изведбе" + +msgid "midi-base-note" +msgstr "миди-основна-нота" + +msgid "Midi note number of the audio track." +msgstr "Број миди ноте звучне нумере." + +msgid "private-data" +msgstr "приватни подаци" + +msgid "Private data" +msgstr "Приватни подаци" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Нисам пронашао руковаоца путањом за протокол %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Шема путање „%s“ није подржана" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ГРЕШКА: из елемента %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Додатни подаци за исправљање грешака:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "веза нема извора [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "веза нема усклађивање [source=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "нема особине „%s“ у елементу „%s“" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "не могу да поставим особину „%s“ у елементу „%s“ на „%s“" + +msgid "Delayed linking failed." +msgstr "Одложено повезивање није успело." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "" +"не могу да вежем „%s“ са „%s“, „%s“ не може да ради са могућностима „%s“" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"не могу да вежем „%s“ са „%s“, ниједан елемент не може да ради са " +"могућностима „%s“" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "не могу да вежем „%s“ са „%s“ са могућностима „%s“" + +#, c-format +msgid "could not link %s to %s" +msgstr "не могу да вежем %s са %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "нема елемента „%s“" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "неочекивана упута „%s“ — занемарујем" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "неочекивана упута-попуне „%s“ — занемарујем" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "не могу да обрадим могућности „%s“" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "нема елемента усклађивања за адресу „%s“" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "нема изворног елемента за адресу „%s“" + +msgid "syntax error" +msgstr "грешка синтаксе" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "наведена је празна канта „%s“, ово није дозвољено" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "нема канте „%s“, распакујем елементе" + +msgid "empty pipeline not allowed" +msgstr "није допуштена празна спојка низа" + +msgid "A lot of buffers are being dropped." +msgstr "Много помоћне меморије је одбачено." + +msgid "Internal data flow problem." +msgstr "Унутрaшњи проблем протока података." + +msgid "Internal data flow error." +msgstr "Унутрaшња грешка протока података." + +msgid "Internal clock error." +msgstr "Унутрашња грешка сата." + +msgid "Failed to map buffer." +msgstr "Нисам успео да мапирам међумеморију." + +msgid "Filter caps" +msgstr "Издваја могућности" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Умањује могуће допуштене могућности (НИШТА значи БИЛО КОЈА). Постављање овог " +"својства поставља као орјентир придодати објекат Гст могућности." + +msgid "Caps Change Mode" +msgstr "Режим промене могућности" + +msgid "Filter caps change behaviour" +msgstr "Издваја понашање промене могућности" + +msgid "No Temp directory specified." +msgstr "Није наведен привремени директоријум." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Не могу да створим привремену датотеку „%s“." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Не могу да отворим датотеку „%s“ ради читања." + +msgid "Error while writing to download file." +msgstr "Грешка при упису у датотеку преузимања." + +msgid "No file name specified for writing." +msgstr "Није наведен назив датотеке за упис." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Не могу да отворим датотеку „%s“ ради уписа." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Грешка при затварању датотеке „%s“." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Грешка приликом премотавања у датотеци „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Грешка при упису у датотеку „%s“." + +msgid "No file name specified for reading." +msgstr "Није наведен назив датотеке за читање." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Не могу да добавим податке на „%s“." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "„%s“ је директоријум." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Датотека „%s“ је прикључница." + +msgid "Failed after iterations as requested." +msgstr "Неуспех након траженог броја покушаја." + +# bug: this should be full word +msgid "caps" +msgstr "могућности" + +msgid "detected capabilities in stream" +msgstr "откривене могућности у току" + +msgid "minimum" +msgstr "најмање" + +msgid "force caps" +msgstr "приморај могућности" + +msgid "force caps without doing a typefind" +msgstr "приморај могућности без обављања претраге уписа" + +msgid "Stream doesn't contain enough data." +msgstr "Овај ток не садржи довољно података." + +msgid "Stream contains no data." +msgstr "Овај ток не садржи податке." + +msgid "Implemented Interfaces:\n" +msgstr "Примењени уређаји:\n" + +msgid "readable" +msgstr "читљив" + +msgid "writable" +msgstr "уписив" + +msgid "deprecated" +msgstr "застарело" + +msgid "controllable" +msgstr "управљив" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "измењив у стање НИШТА, СПРЕМАН, ПАУЗИРАН или ПУШТАМ" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "измењив само у стање НИШТА, СПРЕМАН или ПАУЗИРАН" + +msgid "changeable only in NULL or READY state" +msgstr "измењив само у стање НИШТА или СПРЕМАН" + +msgid "Blacklisted files:" +msgstr "Забрањене датотеке:" + +msgid "Total count: " +msgstr "Укупан број:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d забрањена датотека" +msgstr[1] "%d забрањене датотеке" +msgstr[2] "%d забрањених датотека" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d прикључак" +msgstr[1] "%d прикључка" +msgstr[2] "%d прикључака" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d забрањена ставка" +msgstr[1] "%d забрањене ставке" +msgstr[2] "%d забрањених ставки" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d одлика" +msgstr[1] "%d одлике" +msgstr[2] "%d одлика" + +msgid "Print all elements" +msgstr "Исписује све елементе" + +msgid "Print list of blacklisted files" +msgstr "Штампа списак забрањених даттека" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Штампа машинама обрадив списак одлика које наведени прикључак или прикључци " +"обезбеђују.\n" +" Корисно у везама са спољним " +"самосталним механизмом инсталирања прикључка." + +msgid "List the plugin contents" +msgstr "Наводи садржај прикључка" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Косе црте (/) раздвајају списак врсти елемената (познати као класе) на " +"списак. (неразврстано)" + +msgid "Check if the specified element or plugin exists" +msgstr "Проверава да ли постоји наведени елемент или прикључак" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Када проверава да ли постоји елемент или прикључак, такође проверава да ли " +"је његово издање барем оно наведено" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Штампа подржане шеме адреса, са елементима који их примењују." + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Не могу да учитам датотеку прикључка: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Нема таквог елемента или прикључка „%s“\n" + +msgid "Index statistics" +msgstr "Статистике пописа" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Добих поруку #%u од елемента „%s“ (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Добих поруку #%u од попуне „%s:%s“ (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Добих поруку #%u од објекта „%s“ (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Добих поруку #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Добих ЕОС од елемента „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "НАЂОХ ОЗНАКУ : нађена је елементом „%s“.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "НАЂОХ ОЗНАКУ : нађена је попуном „%s:%s“.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "НАЂОХ ОЗНАКУ : нађена је објектом „%s“.\n" + +msgid "FOUND TAG\n" +msgstr "НАЂОХ ОЗНАКУ\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "НАЂОХ ТАС : нађена је елементом „%s“.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "НАЂОХ ТАС : нађена је објектом „%s“.\n" + +msgid "FOUND TOC\n" +msgstr "НАЂОХ ТАС\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"ПОДАЦИ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "УПОЗОРЕЊЕ: из елемента %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Припремљено, чекам да заврши смештање у међумеморију…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Припремљено, чекам на напредовање да заврши…\n" + +msgid "buffering..." +msgstr "смештам у међумеморију..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Обавио сам смештање у међумеморију, постављам спојку низа на ПУШТАМ ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Смештам у међумеморију, постављам спојку низа на ПАУЗИРАН ...\n" + +msgid "Redistribute latency...\n" +msgstr "Расподељујем кашњење...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Постављам стање на %s као што је затражио %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Прекид: Заустављам спојку низа ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Напредовање: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Недостаје елемент: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Добих садржај из елемента „%s“: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Излазне ознаке (такође познате и као метаподаци)" + +msgid "Output TOC (chapters and editions)" +msgstr "Излазна табела садржаја (поглавља и издања)" + +msgid "Output status information and property notifications" +msgstr "Исписује податке о стању и обавештења о особинама" + +msgid "Do not print any progress information" +msgstr "Не исписује податке о напредовању" + +msgid "Output messages" +msgstr "Излазне поруке" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Не исписује податке стања за наведено својство ако је укључен опширан излаз " +"(може да се користи више пута)" + +msgid "PROPERTY-NAME" +msgstr "СВОЈСТВО-НАЗИВ" + +msgid "Do not install a fault handler" +msgstr "Неће инсталирати руковаоца грешкама" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Приморај ЕОС на извору пре гашења спојке низа" + +msgid "Gather and print index statistics" +msgstr "Прикупи и штампај статистике регистра" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ГРЕШКА: не могу да саставим спојку низа: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ГРЕШКА: не могу да саставим спојку низа.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "УПОЗОРЕЊЕ: неисправна спојка низа: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ГРЕШКА: елемент „спојка низа“ није нађен.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Постављам спојку низа на ПАУЗИРАН ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ГРЕШКА: Спојка низа не жели да иде на паузу.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Спојка низа је жива и не треба јој ПРИПРЕМА ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Спојка низа врши ПРИПРЕМУ ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "ГРЕШКА: спојка низа не жели да припреми.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Спојка низа је ПРИПРЕМЉЕНА ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Постављам спојку низа на ПУШТАМ ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ГРЕШКА: спојка низа не жели да пусти.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "ЕОС је укључен приликом гашења —— Присиљавам ЕОС на спојци низа\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "ЕОС је укључен гашењем —— чекам на ЕОС након грешке\n" + +msgid "Waiting for EOS...\n" +msgstr "Чекам на ЕОС...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "ЕОС је примљен — заустављам спојку низа…\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Прекид за време чекања на ЕОС — заустављам спојку низа...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Дошло је до грешке док сам чекао на ЕОС\n" + +msgid "Execution ended after %" +msgstr "Извршење је окончано након %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Постављам спојку низа на СПРЕМАН ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Постављам спојку низа на НИШТА ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Ослобађам спојку низа...\n" + +#~ msgid "bin" +#~ msgstr "канта" + +#~ msgid "Internal data stream error." +#~ msgstr "Унутрашња грешка тока података." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Не исписује податке о стању за ВРСТУ" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "ВРСТА1,ВРСТА2,..." + +#~ msgid "link without source element" +#~ msgstr "веза без изворног елемента" + +#~ msgid "link without sink element" +#~ msgstr "веза без елемента усклађивања" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "нема елемента за везивање адресе „%s“" diff --git a/po/stamp-po b/po/stamp-po new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/po/stamp-po @@ -0,0 +1 @@ +timestamp diff --git a/po/sv.gmo b/po/sv.gmo new file mode 100644 index 0000000..272b221 Binary files /dev/null and b/po/sv.gmo differ diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 0000000..392fd5e --- /dev/null +++ b/po/sv.po @@ -0,0 +1,1350 @@ +# Swedish messages for gstreamer. +# Copyright © 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2016, 2017 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Christian Rose , 2004, 2005. +# Daniel Nylander , 2007, 2008, 2009, 2010, 2011. +# Sebastian Rasmussen , 2014, 2015, 2016, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-21 18:45+0800\n" +"Last-Translator: Sebastian Rasmussen \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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.11\n" + +msgid "Print the GStreamer version" +msgstr "Skriv ut GStreamer-versionen" + +msgid "Make all warnings fatal" +msgstr "Gör alla varningar ödesdigra" + +msgid "Print available debug categories and exit" +msgstr "Skriv ut tillgängliga felsökningskategorier och avsluta" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Standardfelsökningsnivå från 1 (endast fel) till 9 (allting) eller 0 för " +"ingen utmatning" + +msgid "LEVEL" +msgstr "NIVÅ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Kommaseparerad lista med kategorinamn:nivå-par för att ställa in specifika " +"nivåer för de enskilda kategorierna. Exempel: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LISTA" + +msgid "Disable colored debugging output" +msgstr "Inaktivera färglagd felsökningsutmatning" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Ändrar färgläggning av felsökningsutskrifter. Möjliga alternativ: off, on, " +"disable, auto, unix" + +msgid "Disable debugging" +msgstr "Inaktivera felsökning" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Aktivera utförlig diagnostik vid inläsning av insticksmoduler" + +msgid "Colon-separated paths containing plugins" +msgstr "Kolonseparerade sökvägar som innehåller insticksmoduler" + +msgid "PATHS" +msgstr "SÖKVÄGAR" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Kommaseparerad lista med insticksmoduler att förhandsinläsa utöver listan " +"som lagras i miljövariabeln GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "INSTICKSMODULER" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "" +"Inaktivera fångst av segmenteringsfel under inläsning av insticksmoduler" + +msgid "Disable updating the registry" +msgstr "Inaktivera uppdatering av registret" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Inaktivera start av en hjälpprocess vid avsökning av registret" + +msgid "GStreamer Options" +msgstr "GStreamer-alternativ" + +msgid "Show GStreamer Options" +msgstr "Visa GStreamer-alternativ" + +msgid "Unknown option" +msgstr "Okänt alternativ" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer stötte på ett allmänt fel i kärnbibliotek." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Utvecklarna av GStreamer var för lata för att tilldela detta fel ett " +"felnummer." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Internt GStreamer-fel: koden inte implementerad." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer-fel: tillståndsändring misslyckades och några element misslyckades " +"med att skicka ett korrekt felmeddelande med anledningen till felet." + +msgid "Internal GStreamer error: pad problem." +msgstr "Internt GStreamer-fel: kontaktproblem." + +msgid "Internal GStreamer error: thread problem." +msgstr "Internt GStreamer-fel: trådproblem." + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer-fel: förhandlingsproblem." + +msgid "Internal GStreamer error: event problem." +msgstr "Internt GStreamer-fel: händelseproblem." + +msgid "Internal GStreamer error: seek problem." +msgstr "Internt GStreamer-fel: spolningsproblem." + +msgid "Internal GStreamer error: caps problem." +msgstr "Internt GStreamer-fel: förmågeproblem." + +msgid "Internal GStreamer error: tag problem." +msgstr "Internt GStreamer-fel: taggproblem." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Din GStreamer-installation saknar en insticksmodul." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer-fel: klockproblem." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Det här programmet försöker använda GStreamer-funktionalitet som har " +"inaktiverats." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer stötte på ett allmänt fel i stödbibliotek." + +msgid "Could not initialize supporting library." +msgstr "Kunde inte initiera stödbibliotek." + +msgid "Could not close supporting library." +msgstr "Kunde inte stänga stödbibliotek." + +msgid "Could not configure supporting library." +msgstr "Kunde inte konfigurera stödbibliotek." + +msgid "Encoding error." +msgstr "Kodningsfel." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer stötte på ett allmänt resursfel." + +msgid "Resource not found." +msgstr "Resursen kunde inte hittas." + +msgid "Resource busy or not available." +msgstr "Resursen upptagen eller inte tillgänglig." + +msgid "Could not open resource for reading." +msgstr "Kunde inte öppna resursen för läsning." + +msgid "Could not open resource for writing." +msgstr "Kunde inte öppna resursen för skrivning." + +msgid "Could not open resource for reading and writing." +msgstr "Kunde inte öppna resursen för läsning och skrivning." + +msgid "Could not close resource." +msgstr "Kunde inte stänga resursen." + +msgid "Could not read from resource." +msgstr "Kunde inte läsa från resursen." + +msgid "Could not write to resource." +msgstr "Kunde inte skriva till resursen." + +msgid "Could not perform seek on resource." +msgstr "Kunde inte utföra spolning på resursen." + +msgid "Could not synchronize on resource." +msgstr "Kunde inte synkronisera på resursen." + +msgid "Could not get/set settings from/on resource." +msgstr "Kunde inte hämta/ställa in inställningar från/på resursen." + +msgid "No space left on the resource." +msgstr "Inget ledigt utrymme på resursen." + +msgid "Not authorized to access resource." +msgstr "Har ej befogenhet att använda resursen." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer stötte på ett allmänt strömfel." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Elementet stöder inte hantering av denna ström. Skicka gärna in en " +"felrapport." + +msgid "Could not determine type of stream." +msgstr "Kunde inte fastställa typen av ström." + +msgid "The stream is of a different type than handled by this element." +msgstr "Strömmen är av en annan typ än den som hanteras av detta element." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Det finns ingen omkodare som kan hantera denna strömtyp." + +msgid "Could not decode stream." +msgstr "Kunde inte avkoda ström." + +msgid "Could not encode stream." +msgstr "Kunde inte koda ström." + +msgid "Could not demultiplex stream." +msgstr "Kunde inte avmultiplexera ström." + +msgid "Could not multiplex stream." +msgstr "Kunde inte multiplexera ström." + +msgid "The stream is in the wrong format." +msgstr "Strömmen är av fel format." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Strömmen är krypterad och dekryptering stöds inte." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Strömmen är krypterad och kan inte dekrypteras därför att det inte finns en " +"lämplig nyckel." + +#, c-format +msgid "No error message for domain %s." +msgstr "Inget felmeddelande för domänen %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Inget standardfelmeddelande för domänen %s och koden %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Vald klocka kan inte användas i rörledning." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Fel vid skrivning av registercache till %s: %s" + +msgid "title" +msgstr "titel" + +msgid "commonly used title" +msgstr "vanligtvis använd titel" + +msgid "title sortname" +msgstr "sorteringsnamn för titel" + +msgid "commonly used title for sorting purposes" +msgstr "vanligen använd titel för sorteringsändamål" + +msgid "artist" +msgstr "artist" + +msgid "person(s) responsible for the recording" +msgstr "person(er) som ansvarar för inspelningen" + +msgid "artist sortname" +msgstr "sorteringsnamn för artist" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "person(er) som ansvarar för inspelningen för sorteringsändamål" + +msgid "album" +msgstr "album" + +msgid "album containing this data" +msgstr "album som innehåller dessa data" + +msgid "album sortname" +msgstr "sorteringsnamn för album" + +msgid "album containing this data for sorting purposes" +msgstr "album som innehåller dessa data för sorteringsändamål" + +msgid "album artist" +msgstr "albumartist" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Artisten för hela albumet, som det ska visas" + +msgid "album artist sortname" +msgstr "sorteringsnamn för albumartist" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Artisten för hela albumet, som det ska sorteras" + +msgid "date" +msgstr "datum" + +msgid "date the data was created (as a GDate structure)" +msgstr "datum då dessa data skapades (som en GDate-struktur)" + +msgid "datetime" +msgstr "datumtid" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "datum och tid då dessa data skapades (som en GstDateTime-struktur)" + +msgid "genre" +msgstr "genre" + +msgid "genre this data belongs to" +msgstr "genre som dessa data tillhör" + +msgid "comment" +msgstr "kommentar" + +msgid "free text commenting the data" +msgstr "fri text som kommenterar dessa data" + +msgid "extended comment" +msgstr "utökad kommentar" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"fri text som kommenterar dessa data i formatet key=värde eller " +"key[sv]=kommentar" + +msgid "track number" +msgstr "spårnummer" + +msgid "track number inside a collection" +msgstr "spårnummer inuti en samling" + +msgid "track count" +msgstr "spårantal" + +msgid "count of tracks inside collection this track belongs to" +msgstr "antal spår inuti den samling som detta spår tillhör" + +msgid "disc number" +msgstr "skivnummer" + +msgid "disc number inside a collection" +msgstr "skivnummer inuti en samling" + +msgid "disc count" +msgstr "skivantal" + +msgid "count of discs inside collection this disc belongs to" +msgstr "antal skivor inuti den samling som denna skiva tillhör" + +msgid "location" +msgstr "plats" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Ursprunget för mediet som en URI (plats där den ursprungliga filen eller " +"strömmen finns)" + +msgid "homepage" +msgstr "webbsida" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Webbsida för detta media (alltså webbsidan för artisten eller filmen)" + +msgid "description" +msgstr "beskrivning" + +msgid "short text describing the content of the data" +msgstr "kort text som beskriver innehållet av dessa data" + +msgid "version" +msgstr "version" + +msgid "version of this data" +msgstr "version av dessa data" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - se http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "organisation" + +msgid "copyright" +msgstr "copyright" + +msgid "copyright notice of the data" +msgstr "copyrightnotis för dessa data" + +msgid "copyright uri" +msgstr "Uri till copyrightnotis" + +msgid "URI to the copyright notice of the data" +msgstr "Uri till copyrightnotis för datat" + +msgid "encoded by" +msgstr "kodat av" + +msgid "name of the encoding person or organization" +msgstr "namn på den person eller organisation som kodat" + +msgid "contact" +msgstr "kontakt" + +msgid "contact information" +msgstr "kontaktinformation" + +msgid "license" +msgstr "licens" + +msgid "license of data" +msgstr "licens för data" + +msgid "license uri" +msgstr "Uri för licensinformation" + +msgid "URI to the license of the data" +msgstr "Uri till licens för datat" + +msgid "performer" +msgstr "aktör" + +msgid "person(s) performing" +msgstr "person(er) som agerar" + +msgid "composer" +msgstr "kompositör" + +msgid "person(s) who composed the recording" +msgstr "person(er) som komponerade inspelningen" + +msgid "conductor" +msgstr "konduktör" + +msgid "conductor/performer refinement" +msgstr "konduktör/artist förfining" + +msgid "duration" +msgstr "varaktighet" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "längd i GStreamer-tidsenheter (nanosekunder)" + +msgid "codec" +msgstr "komprimeringsmetod" + +msgid "codec the data is stored in" +msgstr "komprimeringsmetod som dessa data lagras med" + +msgid "video codec" +msgstr "videokomprimeringsmetod" + +msgid "codec the video data is stored in" +msgstr "komprimeringsmetod som dessa videodata lagras med" + +msgid "audio codec" +msgstr "ljudkomprimeringsmetod" + +msgid "codec the audio data is stored in" +msgstr "komprimeringsmetod som dessa ljuddata lagras med" + +msgid "subtitle codec" +msgstr "omkodare för undertext" + +msgid "codec the subtitle data is stored in" +msgstr "omkodare som undertextdata lagrats med" + +msgid "container format" +msgstr "behållarformat" + +msgid "container format the data is stored in" +msgstr "behållarformatet som dessa data lagras med" + +msgid "bitrate" +msgstr "bitfrekvens" + +msgid "exact or average bitrate in bits/s" +msgstr "exakt bitfrekvens eller genomsnittlig bitfrekvens i bitar/s" + +msgid "nominal bitrate" +msgstr "nominell bitfrekvens" + +msgid "nominal bitrate in bits/s" +msgstr "nominell bitfrekvens i bitar/s" + +msgid "minimum bitrate" +msgstr "minsta bitfrekvens" + +msgid "minimum bitrate in bits/s" +msgstr "minsta bitfrekvens i bitar/s" + +msgid "maximum bitrate" +msgstr "högsta bitfrekvens" + +msgid "maximum bitrate in bits/s" +msgstr "högsta bitfrekvens i bitar/s" + +msgid "encoder" +msgstr "kodare" + +msgid "encoder used to encode this stream" +msgstr "kodare som använts för att koda denna ström" + +msgid "encoder version" +msgstr "kodarversion" + +msgid "version of the encoder used to encode this stream" +msgstr "version av kodaren som använts för att koda denna ström" + +msgid "serial" +msgstr "serienummer" + +msgid "serial number of track" +msgstr "serienummer för spår" + +msgid "replaygain track gain" +msgstr "uppspelningsförstärkning spårförstärkning" + +msgid "track gain in db" +msgstr "spårförstärkning i db" + +msgid "replaygain track peak" +msgstr "uppspelningsförstärkning spårtopp" + +msgid "peak of the track" +msgstr "toppen för spåret" + +msgid "replaygain album gain" +msgstr "uppspelningsförstärkning albumförstärkning" + +msgid "album gain in db" +msgstr "albumförstärkning i db" + +msgid "replaygain album peak" +msgstr "uppspelningsförstärkning albumtopp" + +msgid "peak of the album" +msgstr "toppen för albumet" + +msgid "replaygain reference level" +msgstr "referensnivå för uppspelningsförstärkning" + +msgid "reference level of track and album gain values" +msgstr "referensnivå för förstärkningsvärden för spår och album" + +msgid "language code" +msgstr "språkkod" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "språkkod för denna ström, enligt ISO-639-1 eller ISO-639-2" + +msgid "language name" +msgstr "språknamn" + +msgid "freeform name of the language this stream is in" +msgstr "namn på det språk som denna ström använder" + +msgid "image" +msgstr "bild" + +msgid "image related to this stream" +msgstr "bild relaterad till den här strömmen" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "förhandsvisningsbild" + +msgid "preview image related to this stream" +msgstr "förhandsvisningsbild relaterad till den här strömmen" + +msgid "attachment" +msgstr "bilaga" + +msgid "file attached to this stream" +msgstr "fil bifogad till den här strömmen" + +msgid "beats per minute" +msgstr "slag per minut" + +msgid "number of beats per minute in audio" +msgstr "antalet slag per minut i ljudet" + +msgid "keywords" +msgstr "nyckelord" + +msgid "comma separated keywords describing the content" +msgstr "kommaseparerade nyckelord som beskriver innehållet" + +msgid "geo location name" +msgstr "geografiskt platsnamn" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"mänskligt läslig beskrivande plats för var mediet har spelats in eller " +"producerats" + +msgid "geo location latitude" +msgstr "latitud för geografisk plats" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"latitud i grader för geografisk plats där mediet har spelats in eller " +"producerats enligt WGS84 (noll för ekvatorn, negativa värden för sydliga " +"latituder)" + +msgid "geo location longitude" +msgstr "longitud för geografisk plats" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"longitud i grader för geografisk plats där mediet har spelats in eller " +"producerats enligt WGS84 (noll för meridianlinjen i Greenwich, " +"Storbritannien, negativa värden för västliga longituder)" + +msgid "geo location elevation" +msgstr "höjd för geografisk plats" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"höjd i meter för geografisk plats där mediet har spelats in eller " +"producerats enligt WGS84 (noll för genomsnittlig havsnivå)" + +msgid "geo location country" +msgstr "land för geografisk plats" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "land (engelskt namn) där mediet har spelats in eller producerats" + +msgid "geo location city" +msgstr "stad för geografisk plats" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "stad (engelskt namn) där mediet har spelats in eller producerats" + +msgid "geo location sublocation" +msgstr "specifik plats för geografisk plats" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"en plats inom en stad där mediet har producerats eller skapats (t.ex. " +"närområde)" + +msgid "geo location horizontal error" +msgstr "fel i horisontell geografisk plats" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "förväntat fel i horisontell positioneringsmätning (i meter)" + +msgid "geo location movement speed" +msgstr "förflyttningshastighet för geografisk plats" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "förflyttningshastighet för fångstenheten när mediet skapas (i meter/s)" + +msgid "geo location movement direction" +msgstr "förflyttningsriktning för geografisk plats" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"indikerar riktningen som enheten förflyttas när mediet skapas. Det " +"representeras som grader i flyttalsrepresentation, 0 betyder geografiskt " +"nordlig riktning och ökar medsols" + +msgid "geo location capture direction" +msgstr "fångstriktning för geografisk plats" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"indikerar riktningen som enheten pekar mot när mediet skapas. Det " +"representeras som grader i flyttalsrepresentation, 0 betyder geografiskt " +"nordlig riktning och ökar medsols" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "visningsnamn" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Namn på TV-program/poddsändning/serie som mediet kommer från" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "visa sorteringsnamn" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Namn på TV-program/poddsändning/serie som mediet kommer från, för " +"sorteringsändamål" + +msgid "episode number" +msgstr "avsnittsnummer" + +msgid "The episode number in the season the media is part of" +msgstr "Avsnittsnumret i säsongen som mediet är en del av" + +msgid "season number" +msgstr "säsongsnummer" + +msgid "The season number of the show the media is part of" +msgstr "Säsongsnumret för programmet som mediet är en del av" + +msgid "lyrics" +msgstr "låttexter" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Låttexter för mediet, används oftast för låtar" + +msgid "composer sortname" +msgstr "sorteringsnamn för kompositör" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "person(er) som komponerade inspelningen, för sorteringsändamål" + +msgid "grouping" +msgstr "gruppering" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grupprelaterade media som spänner över flera spår, såsom olika delar av en " +"konsert. Det är en högre nivå än ett spår, men lägre än ett album" + +msgid "user rating" +msgstr "användarbetyg" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Betyg angivit av en användare. Desto högre rankning, desto mer gillar " +"användaren detta media" + +msgid "device manufacturer" +msgstr "enhetstillverkare" + +msgid "Manufacturer of the device used to create this media" +msgstr "Tillverkare av enheten som använts för att skapa detta media" + +msgid "device model" +msgstr "enhetsmodell" + +msgid "Model of the device used to create this media" +msgstr "Modell av enheten som använts för att skapa detta media" + +msgid "application name" +msgstr "programnamn" + +msgid "Application used to create the media" +msgstr "Programmet som använts för att skapa detta media" + +msgid "application data" +msgstr "programdata" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Godtycklig programdata att serialisera inuti detta media" + +msgid "image orientation" +msgstr "bildorientering" + +msgid "How the image should be rotated or flipped before display" +msgstr "Hur bilden ska roteras eller vändas före visning" + +msgid "publisher" +msgstr "utgivare" + +msgid "Name of the label or publisher" +msgstr "Namn på förlag eller utgivare" + +msgid "interpreted-by" +msgstr "tolkad av" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Information om människorna bakom en remix eller liknande tolkning" + +msgid "midi-base-note" +msgstr "midi-bas-not" + +msgid "Midi note number of the audio track." +msgstr "Midi-not-nummer för ljudspåret." + +msgid "private-data" +msgstr "privat-data" + +msgid "Private data" +msgstr "Privat data" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Ingen uri-hanterare hittades för %s-protokollet" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Uri-schema \"%s\" saknar stöd" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "FEL: från element %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Ytterligare felsökningsinformation:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "länk har ingen källa [utgång=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "länk har ingen utgång [källa=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "ingen \"%s\"-egenskap i elementet \"%s\"" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "kunde inte ställa in egenskapen \"%s\" i elementet \"%s\" till \"%s\"" + +msgid "Delayed linking failed." +msgstr "Fördröjd länkning misslyckades." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "kunde inte länka %s med %s, %s kan inte hantera förmågorna %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"kunde inte länka %s med %s, ingetdera element kan hantera förmågorna %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "kunde inte länka %s med %s med förmågor %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "kunde inte länka %s med %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "inget \"%s\"-element" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "oväntad referens \"%s\" - ignorerar" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "oväntad kontakt-referens \"%s\" - ignorerar" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "kunde inte tolka förmågorna \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "inget utgångselement för URI:n \"%s\"" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "inget källelement för URI:n \"%s\"" + +msgid "syntax error" +msgstr "syntaxfel" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "angav tom korg \"%s\", inte tillåtet" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "ingen korg \"%s\", packar upp element" + +msgid "empty pipeline not allowed" +msgstr "tom rörledning är inte tillåtet" + +msgid "A lot of buffers are being dropped." +msgstr "Förkastar en stor mängd buffertar." + +msgid "Internal data flow problem." +msgstr "Internt dataflödesproblem." + +msgid "Internal data flow error." +msgstr "Internt fel i dataflöde." + +msgid "Internal clock error." +msgstr "Internt klockfel." + +msgid "Failed to map buffer." +msgstr "Misslyckades med att mappa buffert." + +msgid "Filter caps" +msgstr "Filtrera förmågor" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Begränsa de möjliga tillåtna förmågorna (NULL betyder ANY). Inställning av " +"egenskapen tar en referens till det angivna GstCaps-objektet." + +msgid "Caps Change Mode" +msgstr "Ändringsläge för förmågor" + +msgid "Filter caps change behaviour" +msgstr "Ändringsläge för filterförmågor" + +msgid "No Temp directory specified." +msgstr "Ingen temporärkatalog angiven." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Kunde inte skapa temporärfilen \"%s\"." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Kunde inte öppna filen \"%s\" för läsning." + +msgid "Error while writing to download file." +msgstr "Fel vid skrivning till hämtningsfilen." + +msgid "No file name specified for writing." +msgstr "Inget filnamn angivet för skrivning." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Kunde inte öppna filen \"%s\" för skrivning." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Fel vid stängning av filen \"%s\"." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Fel vid sökning i filen \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fel vid skrivning till filen \"%s\"." + +msgid "No file name specified for reading." +msgstr "Inget filnamn angivet för läsning." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Kunde inte få information om \"%s\"." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" är en katalog." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Filen \"%s\" är ett uttag." + +msgid "Failed after iterations as requested." +msgstr "Misslyckades efter iterationer som begärt." + +msgid "caps" +msgstr "förmågor" + +msgid "detected capabilities in stream" +msgstr "detekterade förmågor i strömmen" + +msgid "minimum" +msgstr "minimum" + +msgid "force caps" +msgstr "tvinga förmågor" + +msgid "force caps without doing a typefind" +msgstr "tvinga förmågor utan att göra en typefind" + +msgid "Stream doesn't contain enough data." +msgstr "Strömmen innehåller inte tillräckligt med data." + +msgid "Stream contains no data." +msgstr "Strömmen innehåller inget data." + +msgid "Implemented Interfaces:\n" +msgstr "Implementerade gränssnitt:\n" + +msgid "readable" +msgstr "läsbar" + +msgid "writable" +msgstr "skrivbar" + +msgid "deprecated" +msgstr "föråldrad" + +msgid "controllable" +msgstr "kontrollerbar" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "ändringsbart i tillstånden NULL, READY, PAUSED eller PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "ändringsbart endast i tillstånden NULL, READY eller PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "ändringsbart endast i tillstånden NULL eller READY" + +msgid "Blacklisted files:" +msgstr "Svartlistade filer:" + +msgid "Total count: " +msgstr "Totalt antal: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d svartlistad fil" +msgstr[1] "%d svartlistade filer" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d insticksmodul" +msgstr[1] "%d insticksmoduler" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d svartlistad post" +msgstr[1] "%d svartlistade poster" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d funktion" +msgstr[1] "%d funktioner" + +msgid "Print all elements" +msgstr "Skriv ut alla element" + +msgid "Print list of blacklisted files" +msgstr "Skriv ut lista över svartlistade filer" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Skriv ut en maskintolkningsbar lista över funktioner som den angivna " +"insticksmodulen\n" +" eller alla insticksmoduler " +"tillhandahåller. Användbart\n" +" tillsammans med externa mekanismer " +"för automatisk installation av insticksmoduler" + +msgid "List the plugin contents" +msgstr "Lista insticksmodulens innehåll" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"En snedstreckseparerad lista (”/”) av typer av element (också känd som en " +"klass) att lista. (oordnad)" + +msgid "Check if the specified element or plugin exists" +msgstr "Kontrollera om det angivna elementet eller insticksmodulen existerar" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"När existensen av ett element eller insticksmodul kontrolleras, kontrollera " +"även att dess version åtminstone är den angivna" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "" +"Skriv ut uri-scheman som stöds, tillsammans med elementen som implementerar " +"dem" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Kunde inte läsa in fil för insticksmodul: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Inget sådant element eller insticksmodul \"%s\"\n" + +msgid "Index statistics" +msgstr "Indexstatistik" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Fick meddelande #%u från elementet \"%s\" (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Fick meddelande #%u från kontakten (pad) \"%s:%s\" (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Fick meddelande #%u från objektet \"%s\" (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Fick meddelande #%u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Fick EOS från element \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "HITTADE TAGG : hittat av elementet \"%s\".\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "HITTADE TAGG : hittat av kontakten \"%s:%s\".\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "HITTADE TAGG : hittat av objektet \"%s\".\n" + +msgid "FOUND TAG\n" +msgstr "HITTADE TAGG\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "HITTADE INNEHÅLL : hittat av elementet \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "HITTADE INNEHÅLL : hittat av objektet \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "HITTADE INNEHÅLL\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"INFO:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "VARNING: från elementet %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Förinläst, väntar på att buffringen ska bli färdig...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Förinläst, väntar på att förloppet ska avslutas...\n" + +msgid "buffering..." +msgstr "buffrar..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Färdig med buffringen, ställer in rörledningen till PLAYING...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Buffrar, ställer in rörledningen till PAUSED...\n" + +msgid "Redistribute latency...\n" +msgstr "Fördröjning för vidaresändning...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Ställer in tillståndet till %s enligt begäran från %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Avbrott: Stoppar rörledningen ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Förlopp: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Element saknas: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Fick kontext från elementet \"%s\": %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Mata ut taggar (även känt som metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "Skriv ut INNEHÅLL (kapitel och utgåvor)" + +msgid "Output status information and property notifications" +msgstr "Skriv ut statusinformation och egenskapsnotifieringar" + +msgid "Do not print any progress information" +msgstr "Skriv inte ut någon förloppsinformation" + +msgid "Output messages" +msgstr "Mata ut meddelanden" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Mata inte ut statusinformation för den angivna egenskapen om utförlig " +"diagnostik är aktiverad (kan användas flera gånger)" + +msgid "PROPERTY-NAME" +msgstr "EGENSKAPSNAMN" + +msgid "Do not install a fault handler" +msgstr "Installera inte en felhanterare" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Tvinga EOS på källor innan rörledningen stängs av" + +msgid "Gather and print index statistics" +msgstr "Samla och skriv ut indexstatistik" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "FEL: rörledningen kunde inte konstrueras: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "FEL: rörledningen kunde inte konstrueras.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "VARNING: felaktig rörledning: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "FEL: \"pipeline\"-elementet hittades inte.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Ställer in rörledningen till PAUSED...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "FEL: Rörledningen vill inte göra paus.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Rörledningen lever och behöver inte PREROLL ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Rörledningen utför PREROLL...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "FEL: rörledningen vill inte utföra preroll.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Rörledningen har utfört PREROLL...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Ställer in rörledningen till PLAYING...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "FEL: rörledningen vill inte spela.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "EOS vid avstängning aktiverad -- Tvingar EOS på rörledningen\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS vid avstängning aktiverad -- Väntar på EOS efter fel\n" + +msgid "Waiting for EOS...\n" +msgstr "Väntar på EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS togs emot - stoppar rörledning...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Avbrott medan EOS väntades på: Stoppar rörledningen...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Ett fel inträffade vid väntan på EOS\n" + +msgid "Execution ended after %" +msgstr "Körning avslutades efter %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Ställer in rörledningen till READY...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Ställer in rörledningen till NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Frigör rörledning ...\n" + +#~ msgid "bin" +#~ msgstr "korg" + +#~ msgid "Internal data stream error." +#~ msgstr "Internt fel i dataström." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Mata inte ut statusinformation av TYP" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYP1,TYP2,..." diff --git a/po/tr.gmo b/po/tr.gmo new file mode 100644 index 0000000..95e484e Binary files /dev/null and b/po/tr.gmo differ diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 0000000..6e396dc --- /dev/null +++ b/po/tr.po @@ -0,0 +1,1448 @@ +# translation of GStreamer to Turkish +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Baris Cicek , 2004, 2015. +# Mehmet Kececi , 2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 11:51+0300\n" +"Last-Translator: Mehmet Kececi \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" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.1\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"X-Project-Style: gnome\n" + +msgid "Print the GStreamer version" +msgstr "GStreamer sürünümü yazdır" + +msgid "Make all warnings fatal" +msgstr "Tüm uyarıları ölümcül yap" + +msgid "Print available debug categories and exit" +msgstr "Geçerli hata ayıklama sınıflarını yazdır ve çık" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Öntanımlı hata ayıklama seviyesi 1'den (sadece hatalar) 9'a (her şey) ya da " +"çıktı olmaması için 0" + +msgid "LEVEL" +msgstr "SEVİYE" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Ayrı sınıfların belirli seviyeleri için sınıf_ismi:seviye çiftlerinin virgül " +"ile ayrılmış listesi. Örnek: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "LİSTE" + +msgid "Disable colored debugging output" +msgstr "Renkli hata ayıklama çıktısını kapat" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Hata ayıklama günlüklerini renklendirme kipini değiştirir. Olası kipler: " +"kapalı, açık, devredışı, otomatik, unix" + +msgid "Disable debugging" +msgstr "Hata ayıklamayı kapat" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Ayrıntılı eklenti yükleme detaylarını etkinleştir" + +msgid "Colon-separated paths containing plugins" +msgstr "Eklentileri içeren iki nokta üst üste ile ayrılmış yollar" + +msgid "PATHS" +msgstr "YOLLAR" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Çevre değişkeni GST_PLUGIN_PATH içinde saklanan listeye ek olarak önceden " +"yüklenecek virgün ile ayrılmış eklenti listesi" + +msgid "PLUGINS" +msgstr "EKLENTİLER" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Eklenti yüklenirken kesimleme hatalarını yakalamayı kapat" + +msgid "Disable updating the registry" +msgstr "Kayıt defteri güncellemeyi devre dışı bırak" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Kayıt defteri taranırken yardımcı bir işlem oluşturmayı devre dışı bırak" + +msgid "GStreamer Options" +msgstr "GStreamer Seçenekleri" + +msgid "Show GStreamer Options" +msgstr "GStreamer Seçeneklerini Göster" + +msgid "Unknown option" +msgstr "Bilinmeyen seçenek" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer genel temel kütüphane hatası ile karşılaştı." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"GStreamer geliştiricileri bu hata için bir hata kodu atamaya üşenmişler." + +msgid "Internal GStreamer error: code not implemented." +msgstr "İç GStreamer hatası: kod tamamlanmamış." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer hatası: durum değişikliği başarısız oldu ve bazı öge başarısızlık " +"nedeni ile ilgili uygun bir hata iletisi göndermede başarısız oldu." + +msgid "Internal GStreamer error: pad problem." +msgstr "Dahili GStreamer hatası: dolgu problemi." + +msgid "Internal GStreamer error: thread problem." +msgstr "İç GStreamer hatası: iş parçacığı sorunu." + +msgid "GStreamer error: negotiation problem." +msgstr "İç GStreamer hatası: uzlaşma sorunu." + +msgid "Internal GStreamer error: event problem." +msgstr "İç GStreamer hatası: olay sorunu." + +msgid "Internal GStreamer error: seek problem." +msgstr "İç GStreamer hatası: arama sorunu." + +msgid "Internal GStreamer error: caps problem." +msgstr "İç GStreamer hatası: kapasite sorunu." + +msgid "Internal GStreamer error: tag problem." +msgstr "İç GStreamer hatası: etiket sorunu." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "GStreamer kurulumunuzda bir eklenti eksik." + +msgid "GStreamer error: clock problem." +msgstr "GStreamer hatası: saat sorunu." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Bu uygulama devre dışı bırakılmış GStreamer işlevini kullanmayı deniyor." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer genel kütüphane destekleme hatası ile karşılaştı." + +msgid "Could not initialize supporting library." +msgstr "Destekleyici kütüphane başlatılamadı." + +msgid "Could not close supporting library." +msgstr "Destekleyici kütüphane kapatılamadı." + +msgid "Could not configure supporting library." +msgstr "Desteklenen kütüphane yapılandırılamadı." + +msgid "Encoding error." +msgstr "Kodlama hatası." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer genel bir kaynak hatası ile karşılaştı." + +msgid "Resource not found." +msgstr "Kaynak bulunamadı." + +msgid "Resource busy or not available." +msgstr "Kaynak meşgul veya ulaşılabilir değil." + +msgid "Could not open resource for reading." +msgstr "Okuma için kaynak açılamadı." + +msgid "Could not open resource for writing." +msgstr "Yazma için kaynak açılamadı." + +msgid "Could not open resource for reading and writing." +msgstr "Okuma ve yazma için kaynak açılamadı." + +msgid "Could not close resource." +msgstr "Kaynak kapatılamadı." + +msgid "Could not read from resource." +msgstr "Kaynaktan okunamadı." + +msgid "Could not write to resource." +msgstr "Kaynağa yazılamadı." + +msgid "Could not perform seek on resource." +msgstr "Kaynak üzerinde atlama yapılamadı." + +msgid "Could not synchronize on resource." +msgstr "Kaynak eşzamanlandırılamadı." + +msgid "Could not get/set settings from/on resource." +msgstr "Kaynağa değerler atanamadı ya da alınamadı." + +msgid "No space left on the resource." +msgstr "Kaynakta boş alan kalmadı." + +msgid "Not authorized to access resource." +msgstr "Kaynağa erişmek için yetkili değil." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer genel bir akış hatası ile karşılaştı." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"Öğe bu akımın işlemesini gerçekleştiremiyor. Lütfen hata bildiriminde " +"bulunun." + +msgid "Could not determine type of stream." +msgstr "Akım türü belirlenemedi." + +msgid "The stream is of a different type than handled by this element." +msgstr "Akım bu öğe tarafından işlenen türden farklı bir türde." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Akım türünü işleyebilecek kodek bulunmuyor." + +msgid "Could not decode stream." +msgstr "Akım çözümlenemedi." + +msgid "Could not encode stream." +msgstr "Akım kodlanamadı." + +msgid "Could not demultiplex stream." +msgstr "Akım çoklaması geriye alınamadı." + +msgid "Could not multiplex stream." +msgstr "Akım çoklandırılamadı." + +msgid "The stream is in the wrong format." +msgstr "Akış yanlış biçimdedir." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Akış şifrelidir ve şifre açma desteklenmiyor." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Akış şifrelidir ve şifresi açılamaz çünkü uygun anahtar temin edilmemiştir." + +#, c-format +msgid "No error message for domain %s." +msgstr "%s etki alanı için hiç hata iletisi yok." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "%s etki alanı ve %d kodu için standart hata iletisi yok." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Seçilen saat ardışık düzende kulanılamıyor." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "%s konumuna kayıt defteri önbelleğini yazmada hata: %s" + +msgid "title" +msgstr "başlık" + +msgid "commonly used title" +msgstr "yaygın olarak kullanılan başlık" + +msgid "title sortname" +msgstr "sıralamaadı başlığı" + +msgid "commonly used title for sorting purposes" +msgstr "amaçları sıralamak için yaygın olarak kullanılan başlık" + +msgid "artist" +msgstr "sanatçı" + +msgid "person(s) responsible for the recording" +msgstr "kayıttan sorumlu olan kişi ya da kişiler" + +msgid "artist sortname" +msgstr "sanatçı sıralamadı" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "sıralama amaçlı kayıttan sorumlu kişi(ler)" + +msgid "album" +msgstr "albüm" + +msgid "album containing this data" +msgstr "bu bilgiyi içeren albüm" + +msgid "album sortname" +msgstr "albüm sıralama adı" + +msgid "album containing this data for sorting purposes" +msgstr "sıralama amaçlı bu verileri içeren albüm" + +msgid "album artist" +msgstr "albüm sanatçısı" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Gerektiği gibi gösterilen tüm albümlerin sanatçıları" + +msgid "album artist sortname" +msgstr "albüm sanatçıları sıralamaadı" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Gerektiği gibi sıralanan tüm albümlerin sanatçıları" + +msgid "date" +msgstr "tarih" + +msgid "date the data was created (as a GDate structure)" +msgstr "tarih verisi oluşturuldu (bir GDate yapısı olarak)" + +msgid "datetime" +msgstr "tarihsaat" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "tarih ve saat verisi oluşturuldu (bir GstDateTime yapısı olarak)" + +msgid "genre" +msgstr "tür" + +msgid "genre this data belongs to" +msgstr "bu verinin ait olduğu tür" + +msgid "comment" +msgstr "yorum" + +msgid "free text commenting the data" +msgstr "veriyi yorumlayan serbest metin" + +msgid "extended comment" +msgstr "genişletilmiş yorum" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "anahtar=deger ya da anahtar[en]=yorum biçimindeki metin yorumlama" + +msgid "track number" +msgstr "parça numarası" + +msgid "track number inside a collection" +msgstr "kolleksiyon içindeki parça numarası" + +msgid "track count" +msgstr "parça sayısı" + +msgid "count of tracks inside collection this track belongs to" +msgstr "bu parçanın ait olduğu kolleksiyonun parça sayısı" + +msgid "disc number" +msgstr "disk numarası" + +msgid "disc number inside a collection" +msgstr "kolleksiyon içindeki disk numarası" + +msgid "disc count" +msgstr "disk sayısı" + +msgid "count of discs inside collection this disc belongs to" +msgstr "bu diskin ait olduğu kolleksiyondaki disklerin sayısı" + +msgid "location" +msgstr "konum" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"URI olarak ortam kaynağı (dosyanın özgün konumu ya da akışın barındırıldığı " +"konum)" + +msgid "homepage" +msgstr "anasayfa" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Bu ortamın anasayfası (yani sanatçı ya da film anasayfası)" + +msgid "description" +msgstr "tanım" + +msgid "short text describing the content of the data" +msgstr "verinin içeriğini tanımlayan kısa metin" + +msgid "version" +msgstr "sürüm" + +msgid "version of this data" +msgstr "bu verinin sürümü" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Uluslararası Standart Kayıt Kodu - http://www.ifpi.org/isrc/ adresine bakın" + +msgid "organization" +msgstr "kurum" + +msgid "copyright" +msgstr "telif hakkı" + +msgid "copyright notice of the data" +msgstr "verinin telif hakkı notu" + +msgid "copyright uri" +msgstr "telif hakkı uri" + +msgid "URI to the copyright notice of the data" +msgstr "Verinin telif hakkı bildirimi için URI" + +msgid "encoded by" +msgstr "kodlayan" + +msgid "name of the encoding person or organization" +msgstr "kodlayan kişi ya da organizasyonun adı" + +msgid "contact" +msgstr "iletişim" + +msgid "contact information" +msgstr "iletişim bilgisi" + +msgid "license" +msgstr "lisans" + +msgid "license of data" +msgstr "verinin lisansı" + +msgid "license uri" +msgstr "lisans uri" + +msgid "URI to the license of the data" +msgstr "Verinin lisansı için URI" + +msgid "performer" +msgstr "icra eden" + +msgid "person(s) performing" +msgstr "icra eden kişi" + +msgid "composer" +msgstr "düzenleyici" + +msgid "person(s) who composed the recording" +msgstr "kayıt oluşturan kişi(ler)" + +msgid "conductor" +msgstr "kondüktör" + +msgid "conductor/performer refinement" +msgstr "kondüktör/performans iyileştirmesi" + +msgid "duration" +msgstr "süre" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "GStreamer zaman birimi (nano saniye) olarak uzunluk" + +msgid "codec" +msgstr "kodek" + +msgid "codec the data is stored in" +msgstr "verinin saklandığı kodek" + +msgid "video codec" +msgstr "video kodeki" + +msgid "codec the video data is stored in" +msgstr "videonun saklandığı kodek" + +msgid "audio codec" +msgstr "ses kodeki" + +msgid "codec the audio data is stored in" +msgstr "ses verisinin saklandığı kodek" + +msgid "subtitle codec" +msgstr "altyazı kodlayıcı-kod çözücüsü" + +msgid "codec the subtitle data is stored in" +msgstr "altyazı verisinin saklandığı kodlayıcı-kod çözücü" + +msgid "container format" +msgstr "kap biçimi" + +msgid "container format the data is stored in" +msgstr "verilerin saklandığı kap biçemi" + +msgid "bitrate" +msgstr "örnekleme hızı" + +msgid "exact or average bitrate in bits/s" +msgstr "bit/s olarak ortalama veya kesin örnekleme hızı" + +msgid "nominal bitrate" +msgstr "nominal örnekleme hızı" + +msgid "nominal bitrate in bits/s" +msgstr "bit/s olarak nominal örnekleme hızı" + +msgid "minimum bitrate" +msgstr "asgari örnekleme hızı" + +msgid "minimum bitrate in bits/s" +msgstr "bit/s olarak asgari örnekleme hızı" + +msgid "maximum bitrate" +msgstr "azami örnekleme hızı" + +msgid "maximum bitrate in bits/s" +msgstr "bit/s olarak azami örnekleme hızı" + +msgid "encoder" +msgstr "kodlayıcı" + +msgid "encoder used to encode this stream" +msgstr "bu akımı kodlarken kullanılacak kodlayıcı" + +msgid "encoder version" +msgstr "kodlayıcı sürümü" + +msgid "version of the encoder used to encode this stream" +msgstr "bu akımı kodlarken kullanılan kodlayıcının sürümü" + +msgid "serial" +msgstr "seri numarası" + +msgid "serial number of track" +msgstr "parçanın seri numarası" + +msgid "replaygain track gain" +msgstr "tekrarkazanç parça kazancı" + +msgid "track gain in db" +msgstr "db olarak parça kazancı" + +msgid "replaygain track peak" +msgstr "tekrarkazanç parça üst sınırı" + +msgid "peak of the track" +msgstr "parçanın üst sınırı" + +msgid "replaygain album gain" +msgstr "tekrarkazanç albüm kazancı" + +msgid "album gain in db" +msgstr "db olarak albüm kazancı" + +msgid "replaygain album peak" +msgstr "tekrarkazanç albüm üst sınırı" + +msgid "peak of the album" +msgstr "albüm üst sınırı" + +msgid "replaygain reference level" +msgstr "yeniden kazanç kaynak seviyesi" + +msgid "reference level of track and album gain values" +msgstr "şarkı ve albüm kazanç değerlerinin kaynak seviyesi" + +msgid "language code" +msgstr "dil kodu" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "bu akış için ISO-639-1 ya da ISO-639-2 standartlarına uygun dil kodu" + +msgid "language name" +msgstr "dil adı" + +msgid "freeform name of the language this stream is in" +msgstr "bu akıştaki dilin serbest biçem adı" + +msgid "image" +msgstr "görüntü" + +msgid "image related to this stream" +msgstr "bu akış ile ilişkili görüntü" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "görüntüyü önizle" + +msgid "preview image related to this stream" +msgstr "bu akış ile ilişkili görüntüyü önizle" + +msgid "attachment" +msgstr "ek" + +msgid "file attached to this stream" +msgstr "bu akışa dosya eklendi" + +msgid "beats per minute" +msgstr "dakikadaki vuruş" + +msgid "number of beats per minute in audio" +msgstr "seste dakikadaki vuruş sayısı" + +msgid "keywords" +msgstr "anahtar sözcükler" + +msgid "comma separated keywords describing the content" +msgstr "içeriği tanımlayan virgülle ayrılmış anahtar sözcükler" + +msgid "geo location name" +msgstr "coğrafi konum adı" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "ortamın kaydedildiği ya da üretildiği okunabilir açıklayıcı konum" + +msgid "geo location latitude" +msgstr "coğrafi konum enlemi" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"WGS84 yerlem derecesinde (ekvatorda sıfır, güney enlemler için negatif " +"değerler) üretilen ya da kaydedilen ortamın coğrafik enlem konumu" + +msgid "geo location longitude" +msgstr "coğrafi konum boylamı" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"WGS84 yerlem derecesinde (Greenwich/UK baş meridyeninde sıfır, batı " +"boylamları için negatif değerler) üretilen ya da kaydedilen ortamın coğrafik " +"boylam konumu" + +msgid "geo location elevation" +msgstr "coğrafi konum yüksekliği" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"WGS84 yerlem ölçüsünde (ortalama deniz seviyesi sıfırdır) üretilen ya da " +"kaydedilen ortamın coğrafik yüksekliği" + +msgid "geo location country" +msgstr "ülke coğrafi konumu" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "ortamın üretildiği ya da kaydedildiği ülke (ingilizce adı)" + +msgid "geo location city" +msgstr "şehir coğrafi konumu" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "ortamın kaydedildiği ya da üretildiği şehir (ingilizce adı)" + +msgid "geo location sublocation" +msgstr "bölge coğrafi konumu" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"ortamın üretildiği ya da oluşturulduğu şehirdeki bir konum (örneğin semt)" + +msgid "geo location horizontal error" +msgstr "coğrafi yatay konum hatası" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "yatay konumlandırma ölçümlerinde beklenen hata (metre cinsinden)" + +msgid "geo location movement speed" +msgstr "coğrafi konum hareket hızı" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "yakalama aygıtının m/s cinsinden yakalama yaparken ki hareket hızı" + +msgid "geo location movement direction" +msgstr "coğrafi konum hareket doğrultusu" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"Bir medyada yakalama yapan aygıtın haraket yönünü belirtir. Kayan noktalı " +"sayı olarak, derece biçiminde gösterilir, 0 çoğrafik kuzeydir ve saat " +"yönünde belirtilir" + +msgid "geo location capture direction" +msgstr "coğrafi konum yakalama açıklaması" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"Bir medya yakalanırken işaret edilen aygıtın yönünü belirtir. Kayan noktalı " +"sayı olarak, derece biçiminde gösterilir, 0 çoğrafik kuzeydir ve saat " +"yönünde belirtilir" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "adı göster" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Ortamın tv/podcast/serie den birisinin adı" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "sıralamaadını göster" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "Ortamın tv/podcast/serie den birisinin adı, sıralama için" + +msgid "episode number" +msgstr "bölüm numarası" + +msgid "The episode number in the season the media is part of" +msgstr "Ortamın parçası olduğu sezonun bölüm numarası" + +msgid "season number" +msgstr "oturum numarası" + +msgid "The season number of the show the media is part of" +msgstr "Ortamın parçası olduğu sezon numarası" + +msgid "lyrics" +msgstr "şarkı sözleri" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Ortamın şarkı sözleri, genellikle şarkılar için kullanılır" + +msgid "composer sortname" +msgstr "besteci sıralama adı" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "sıralama amaçlı kayıt oluşturan kişi(ler)" + +msgid "grouping" +msgstr "gruplandırma" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Grup ilgili ortam çoklu şarkılar içerir, bir konçertonun farklı parçaları " +"gibi. Bu şarkıdan daha üst seviyedir ancak albümden alt seviyedir" + +msgid "user rating" +msgstr "kullanıcı değerlendirmesi" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Kullanıcı tarafından verilmiş puanlama. En yüksek puanlama, bir çok " +"kullanıcı bu ortamı beğenmiş" + +msgid "device manufacturer" +msgstr "aygıt üreticisi" + +msgid "Manufacturer of the device used to create this media" +msgstr "Bu ortamı oluşturmak için kullanılan aygıt üreticisi" + +msgid "device model" +msgstr "aygıt modeli" + +msgid "Model of the device used to create this media" +msgstr "Bu ortamı oluşturmak için kullanılan aygıtın modeli" + +msgid "application name" +msgstr "uygulama adı" + +msgid "Application used to create the media" +msgstr "Bu ortamı oluşturmak için kullanılan uygulama" + +msgid "application data" +msgstr "uygulama verileri" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Ortamda serileştirilecek gelişigüzel uygulama verileri" + +msgid "image orientation" +msgstr "görüntü yönü" + +msgid "How the image should be rotated or flipped before display" +msgstr "Görüntü gösterilmeden önce nasıl döndürülmelidir ya da çevirilmelidir" + +msgid "publisher" +msgstr "yayımcı" + +msgid "Name of the label or publisher" +msgstr "Marka ya da yayımcının adı" + +msgid "interpreted-by" +msgstr "tarafından-yorumlanmış" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Yeniden düzenleme ve benzer yorumların arkasındaki kişi hakkında bilgi" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Ses kaydının midi notu numarası." + +msgid "private-data" +msgstr "özel-veri" + +msgid "Private data" +msgstr "Özel veri" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "%s protokolü için URI işleyicisi bulunamadı" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "URI şema '%s' desteklenmez" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "HATA: %s öğesinden: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Ek hata ayıklama bilgisi:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "bağlantı kaynağı yok [alıcı=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "bağlantı alış noktası yok [kaynak=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "\"%s\" öğesinde \"%s\" özelliği yok" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "\"%s\" öğesindeki \"%s\" özelliğine \"%s\" değeri atanamadı" + +msgid "Delayed linking failed." +msgstr "Gecikmeli bağlama başarısız oldu." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "%s i %s e bağlanamadı, %s başlıklar işlenemiyor %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "%s i %s e bağlanamadı, hiçbir başlık başlık öğesi işlenemiyor %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "%s, %s e %s başlıklar ile bağlanamadı" + +#, c-format +msgid "could not link %s to %s" +msgstr "%s, %s'a bağlanamadı" + +#, c-format +msgid "no element \"%s\"" +msgstr "\"%s\" öğesi yok" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "beklenmeyen kaynak \"%s\" - yoksayılıyor" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "beklenmedik dolgu-kaynağı \"%s\" - yoksayılıyor" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "\"%s\" kabiliyetleri ayrıştırılamadı" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "\"%s\" URI'si için 'sink' öğesi yok" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "\"%s\" URI'si için kaynak öğesi yok" + +msgid "syntax error" +msgstr "söz dizim hatası" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "belirtilen boş ikili \"%s\", izin verilmedi" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "\"%s\" ikilisi yok, öge açılamıyor" + +msgid "empty pipeline not allowed" +msgstr "boş boruhattına izin verilmiyor" + +msgid "A lot of buffers are being dropped." +msgstr "Tampon belleklerin bir çoğu bırakılıyor." + +msgid "Internal data flow problem." +msgstr "İç veri akış sorunu." + +msgid "Internal data flow error." +msgstr "İç veri akış hatası." + +msgid "Internal clock error." +msgstr "İç saat hatası." + +msgid "Failed to map buffer." +msgstr "Tampon eşleştirme başarısız." + +msgid "Filter caps" +msgstr "Büyük harfleri süz" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"İzin verilen yetenekleri kısıtla (NULL HİÇ anlamına gelir). Bu özelliklerin " +"ayarlanması verilen GstCaps nesnesini kaynak olarak alır." + +msgid "Caps Change Mode" +msgstr "Başlıklar Modunu Değiştir" + +msgid "Filter caps change behaviour" +msgstr "Büyük harf değişiklik davranışını filtrele" + +msgid "No Temp directory specified." +msgstr "Geçici dizin belirtilmedi." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Geçici dosya \"%s\" oluşturulamadı." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "\"%s\" dosyası okuma için açılamadı." + +msgid "Error while writing to download file." +msgstr "Dosya indirmek için yazarken hata." + +msgid "No file name specified for writing." +msgstr "Yazım için hiç bir dosya adı belirtilmedi." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "\"%s\" dosyası yazım için açılamadı." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "\"%s\" kapatılırken hata." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "\"%s\" dosyasında arama yaparken hata." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "\"%s\" dosyası yazılırken hata." + +msgid "No file name specified for reading." +msgstr "Okuma için hiç bir dosya adı belirtilmedi." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "\"%s\" ögesinden bilgi alınamadı." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "\"%s\" bir dizindir." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Dosya \"%s\" bir sokettir." + +msgid "Failed after iterations as requested." +msgstr "İstenildiği gibi tekrarlama başarısız oldu." + +msgid "caps" +msgstr "kabiliyetler" + +msgid "detected capabilities in stream" +msgstr "akımda tesbit edilen kabiliyetler" + +msgid "minimum" +msgstr "asgari" + +msgid "force caps" +msgstr "kapasiteyi zorla" + +msgid "force caps without doing a typefind" +msgstr "bir tür tanımlaması yapmadan kapasiteyi zorla" + +msgid "Stream doesn't contain enough data." +msgstr "Akışı yeterli veri içermiyor." + +msgid "Stream contains no data." +msgstr "Akış hiçbir veri içermiyor." + +msgid "Implemented Interfaces:\n" +msgstr "Gerçeklenmiş Arayüzler:\n" + +msgid "readable" +msgstr "okunabilir" + +msgid "writable" +msgstr "yazılabilir" + +msgid "deprecated" +msgstr "kullanım dışı" + +msgid "controllable" +msgstr "yöneltilebilir" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "BOŞ, HAZIR, DURDURULMUŞ ya da YÜRÜTÜLÜYOR durumlarına değiştirilebilir" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "sadece NULL, READY ya da PAUSED olarak değiştirilebilir" + +msgid "changeable only in NULL or READY state" +msgstr "sadece NULL ya da READY olarak değiştirilebilir" + +msgid "Blacklisted files:" +msgstr "Kara listeye alınan dosyalar:" + +msgid "Total count: " +msgstr "Toplam sayı: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d kara listeye alınan dosya" +msgstr[1] "%d kara listeye alınan dosya" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d eklentisi" +msgstr[1] "%d eklentisi" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d kara liste girdisi" +msgstr[1] "%d kara liste girdisi" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d özelliği" +msgstr[1] "%d özelliği" + +msgid "Print all elements" +msgstr "Bütün ögeleri yazdır" + +msgid "Print list of blacklisted files" +msgstr "Kara listeye alınmış dosyaların listesini yazdır" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Belirtilen eklenti ya da sağlanan bütün eklentilerin özelliklerinin makine-" +"çözümlenebilir bir listesini yazdır.\n" +" Harici otomatik eklenti kurulum " +"tekniği ile bağlantıda faydalı" + +msgid "List the plugin contents" +msgstr "Eklenti içeriklerini listele" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Bir eğik çizgi ('/') öğelernin türlerini listelemek için (klass olarak da " +"bilinen) listelerine ayrılmış. (sıralı değil)" + +msgid "Check if the specified element or plugin exists" +msgstr "Belirtilen öge ya da eklentinin var olup olmadığını kontrol et" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Bir öge ya da eklentinin var olup olmadığını kontrol ettiğinizde ayrıca " +"onların belirtilen en son versiyonda olup olmadıklarını da kontrol edin" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Desteklenen URI şemalarını onlara uygulanan ögelerle yazdır" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Eklenti dosyası yüklenemedi: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Böyle bir öge ya da '%s' eklentisi yok\n" + +msgid "Index statistics" +msgstr "Dizin istatistikleri" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "#%u iletisi \"%s\" ögesinden alındı (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "#%u iletisi dolgu \"%s:%s\" (%s) üzerinden alındı: " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "#%u iletisi \"%s\" nesnesinden alındı (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "İleti #%u alındı (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "\"%s\" ögesinden gelen EOS.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ETİKET BULUNDU : \"%s\" öğesi tarafından bulundu.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ETİKET BULUNDU : \"%s:%s\" dolgusu tarafından bulundu.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ETİKET BULUNDU : \"%s\" nesnesi tarafından bulundu.\n" + +msgid "FOUND TAG\n" +msgstr "ETİKET BULUNDU\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "İÇİNDEKİLER BULUNDU : \"%s\" ögesi tarafından bulundu.\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "İÇİNDEKİLER BULUNDU : \"%s\" nesnesi tarafından bulundu.\n" + +msgid "FOUND TOC\n" +msgstr "İÇİNDEKİLER BULUNDU\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"BİLGİ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "UYARI: %s ögesinden: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Kullanım öncesi, önbelleğe alma işleminin bitmesi bekleniyor...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Kullanım öncesi, ilerlemenin bitmesi için bekleniyor...\n" + +msgid "buffering..." +msgstr "tamponlanıyor..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "" +"Önbelleğe alma işlemi, YÜRÜTÜLÜYOR durumu için ardışık düzen ayarlamaları " +"yapıldı ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Tamponlama, DURAKLAT olarak ayarlanıyor ...\n" + +msgid "Redistribute latency...\n" +msgstr "Yeniden dağıtım gecikmesi...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Durum %s olarak ayarlanıyor, %s tarafından istenmiş...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Kesme: Boru hattı durduruluyor ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "İlerleme: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Eksik öge: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Ögeden '%s' içerik alındı: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Çıktı etiketleri (metadata olarak da bilinir)" + +msgid "Output TOC (chapters and editions)" +msgstr "İçindekiler Çıktısı (bölümler ve sürümleri)" + +msgid "Output status information and property notifications" +msgstr "Çıktı durum bilgisi ve özellik uyarıları" + +msgid "Do not print any progress information" +msgstr "Herhangi bir ilerleme bilgisi yazdırmayın" + +msgid "Output messages" +msgstr "Çıktı iletileri" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Ayrıntılı çıktı etkinse, durum bilgilerini belirtilen özellik için çıkış " +"değil (birden çok kez kullanılabilir)" + +msgid "PROPERTY-NAME" +msgstr "ÖZELLİK-ADI" + +msgid "Do not install a fault handler" +msgstr "Hatalı işleticiyi kurma" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Boru hattı kapatılmadan önce kaynaklarda EOS zorla" + +msgid "Gather and print index statistics" +msgstr "Dizin istatistiklerini topla ve yazdır" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "HATA: boruhattı oluşturulamadı: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "HATA: boruhattı oluşturulamadı.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "UYARI: hatalı boruhattı: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "HATA: 'pipeline' öğesi bulunamadı.\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "DURDURULDU durumu için ardışık düzen ayarlamaları ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "HATA: Ardışık düzen durdurmayı istemez.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Boru hattı çalışıyor ve PREROLL ihtiyacı yok ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Boru hattı PREROLLING yapıyor ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "HATA: boru hattı kullanım öncesi yapmak istemiyor.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Boru hattı PREROLLED ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Boru hattı PLAYING olarak ayarlanıyor ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "HATA: boruhattı çalmak istemiyor.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Kapanmada EOS etkin - Boru hattında EOS zorlanıyor\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Kapanmada EOS etkin -- Hatadan sonra EOS için bekleniyor\n" + +msgid "Waiting for EOS...\n" +msgstr "EOS için bekleniyor...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "EOS alındı - boru hattı durduruluyor...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "EOS için beklenirken kesme - boru hattı durduruluyor...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Akış sonu için beklerken bir hata oldu\n" + +msgid "Execution ended after %" +msgstr "Çalıştırma % sonrası bitti" + +msgid "Setting pipeline to READY ...\n" +msgstr "Boru hattı READY olarak ayarlanıyor ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Boru hattı NULL olarak ayarlanıyor ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Boru hattı boşaltılıyor ...\n" + +#~ msgid "bin" +#~ msgstr "bin" + +#~ msgid "Internal data stream error." +#~ msgstr "İç veri akışı hatası." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "TÜRÜN durum bilgisini gösterme" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TÜR1,TÜR2,..." + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "Hızlandırılmış CPU işlemlerini kapat" + +#~ msgid "path list for loading plugins (separated by '" +#~ msgstr "eklenti yüklemek için yol listesi (' ile ayırılmış" + +#~ msgid "')" +#~ msgstr "')" + +#~ msgid "Scheduler to use ('" +#~ msgstr "Kullanılacak zamanlandırıcı ('" + +#~ msgid "' is the default)" +#~ msgstr "' ön tanımlı olanı)" + +#~ msgid "SCHEDULER" +#~ msgstr "ZAMANLANDIRICI" + +#~ msgid "Registry to use" +#~ msgstr "Kullanılacak kayıt" + +#~ msgid "REGISTRY" +#~ msgstr "KAYIT" + +#~ msgid "Internal GStreamer error: state change failed. File a bug." +#~ msgstr "" +#~ "Dahili GStreamer hatası: durum değiştirilemedi. Hata bildiriminde " +#~ "bulunun." + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "" +#~ "Dahili GStreamer hatası: zamanlandırıcı sorunu. Hata bildiriminde " +#~ "bulunun." + +#~ msgid "original location of file as a URI" +#~ msgstr "dosyanın URI olarak özgün konumu" + +#~ msgid "There is no element present to handle the stream's mime type %s." +#~ msgstr "Akımın %s mime türünü işleyebilecek hiç bir öğe yok." + +#~ msgid "maximum" +#~ msgstr "azami" + +#~ msgid "" +#~ "could not convert \"%s\" so that it fits property \"%s\" in element \"%s\"" +#~ msgstr "" +#~ "\"%1$s\", \"%3$s\" öğesindeki \"%2$s\" özelliğinine uyacak şekilde " +#~ "dönüştürülemedi" + +#~ msgid "link without source element" +#~ msgstr "kaynak öğesi olmayan bağ" + +#~ msgid "link without sink element" +#~ msgstr "'sink' öğesi olmayan bağ" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "\"%s\" URI'sini belirtilene bağlayacak öğe yok:" + +#~ msgid "Show plugin details" +#~ msgstr "Eklenti detaylarını göster" + +#~ msgid "Show scheduler details" +#~ msgstr "Zamanlandırıcı detaylarını göster" + +#~ msgid " iterations (sum %" +#~ msgstr " tekrarlar (toplam %" + +#~ msgid " ns, average %" +#~ msgstr " ns, ortalama %" + +#~ msgid " ns, min %" +#~ msgstr " ns, dak %" + +#~ msgid " ns, max %" +#~ msgstr " ns, en fazla %" + +#~ msgid " ns).\n" +#~ msgstr " ns) \n" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "Kullanım: gst-xmllaunch [ öğe.özellik=değer ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "HATA: xml dosyası '%s' ayrıştırması başarısız.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "HATA: '%s' dosyasında üst seviye öğesi bulunamadı.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time." +#~ msgstr "UYARI: Şu anda sadece bir tane üst seviye öğesi destekleniyor." + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "HATA: komut satırı argümanı %d ayrıştırılamadı: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "UYARI: '%s' isimli öğe bulunamadı.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Boruhattının xml belirtimini DOSYA'ya kaydet ve çık" + +#~ msgid "FILE" +#~ msgstr "DOSYA" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "'alloc' takibini yazdır (derleme sırasında etkinleştirilmişse)" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "Boruhattının kaç defa tekrarlanacağı" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " Gene de çalıştırma deneniyor.\n" diff --git a/po/uk.gmo b/po/uk.gmo new file mode 100644 index 0000000..993f45e Binary files /dev/null and b/po/uk.gmo differ diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 0000000..44a99f0 --- /dev/null +++ b/po/uk.po @@ -0,0 +1,1422 @@ +# Ukrainian translation to gstreamer. +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# +# Maxim V. Dziumanenko , 2004-2007. +# Yuri Chornoivan , 2011, 2012, 2013, 2014, 2015, 2016, 2017. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-04 22:17+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" +"X-Bugs: Report translation errors to the Language-Team address.\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" +"X-Generator: Lokalize 1.5\n" + +msgid "Print the GStreamer version" +msgstr "Показати дані щодо версії GStreamer" + +msgid "Make all warnings fatal" +msgstr "Вважати всі попередження помилками" + +msgid "Print available debug categories and exit" +msgstr "Вивести наявні категорії діагностики і завершити роботу" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Типовий рівень діагностики від 1 (лише помилки) до 9 (усе), або 0 — без " +"діагностики" + +msgid "LEVEL" +msgstr "РІВЕНЬ" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Перелік розділених комою пар «назва_категорії:рівень» для встановлення " +"певних рівнів окремим категоріям. Приклад: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "СПИСОК" + +msgid "Disable colored debugging output" +msgstr "Вимкнути оформлення кольором діагностичних повідомлень" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Змінити режим розфарбовування повідомлень діагностичного журналу. Можливі " +"режими: off, on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "Вимкнути діагностику" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Вимкнути докладну діагностику завантаження модулів" + +msgid "Colon-separated paths containing plugins" +msgstr "Список розділених крапкою з комою шляхів, які містять модулі" + +msgid "PATHS" +msgstr "ШЛЯХИ" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Перелік розділених комою назв модулів, що попередньо завантажуються, " +"додатково до переліку, який зберігається у змінній оточення GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "МОДУЛІ" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Вимкнути перехоплення помилок сегментації при завантаженні модулів" + +msgid "Disable updating the registry" +msgstr "Вимкнути оновлення реєстру" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "Вимкнути створення допоміжного процесу під час сканування реєстру" + +msgid "GStreamer Options" +msgstr "Параметри GStreamer" + +msgid "Show GStreamer Options" +msgstr "Показати параметри GStreamer" + +msgid "Unknown option" +msgstr "Невідомий параметр" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer перехопив загальну помилку основної бібліотеки." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "Розробники GStreamer не призначили код для цієї помилки." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Внутрішня помилка GStreamer: код не реалізовано." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Помилка GStreamer: не вдалося змінити стан, деяким елементам не вдалося " +"вивести належне повідомлення про помилку з причиною помилки." + +msgid "Internal GStreamer error: pad problem." +msgstr "Внутрішня помилка GStreamer: проблема наповнення." + +msgid "Internal GStreamer error: thread problem." +msgstr "Внутрішня помилка GStreamer: помилка потоку виконання." + +msgid "GStreamer error: negotiation problem." +msgstr "Помилка GStreamer: помилка встановлення зв'язку." + +msgid "Internal GStreamer error: event problem." +msgstr "Внутрішня помилка GStreamer: помилка події." + +msgid "Internal GStreamer error: seek problem." +msgstr "Внутрішня помилка GStreamer: помилка встановлення позиції." + +msgid "Internal GStreamer error: caps problem." +msgstr "Внутрішня помилка GStreamer: проблема можливостей." + +msgid "Internal GStreamer error: tag problem." +msgstr "Внутрішня помилка GStreamer: помилка у мітці." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "У вашій збірці GStreamer відсутній модуль." + +msgid "GStreamer error: clock problem." +msgstr "Помилка GStreamer: помилка годинника." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "" +"Програма намагається використовувати вимкнену функціональність GStreamer." + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer перехопив загальну помилку основної бібліотеки підтримки." + +msgid "Could not initialize supporting library." +msgstr "Не вдалося ініціалізувати бібліотеку підтримки." + +msgid "Could not close supporting library." +msgstr "Не вдалося закрити бібліотеку підтримки." + +msgid "Could not configure supporting library." +msgstr "Не вдалося налаштувати бібліотеку підтримки." + +msgid "Encoding error." +msgstr "Помилка кодування." + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer перехопив загальну помилку ресурсу." + +msgid "Resource not found." +msgstr "Ресурсу не знайдено." + +msgid "Resource busy or not available." +msgstr "Ресурс зайнятий або недоступний." + +msgid "Could not open resource for reading." +msgstr "Не вдалося відкрити ресурс для читання." + +msgid "Could not open resource for writing." +msgstr "Не вдалося відкрити ресурс для запису." + +msgid "Could not open resource for reading and writing." +msgstr "Не вдалося відкрити ресурс для читання чи запису." + +msgid "Could not close resource." +msgstr "Не вдалося закрити ресурс." + +msgid "Could not read from resource." +msgstr "Не вдалося прочитати з ресурсу." + +msgid "Could not write to resource." +msgstr "Не вдалося записати у ресурс." + +msgid "Could not perform seek on resource." +msgstr "Не вдалося виконати встановлення позиції у ресурсі." + +msgid "Could not synchronize on resource." +msgstr "Не вдалося синхронізуватись з ресурсом." + +msgid "Could not get/set settings from/on resource." +msgstr "" +"Не вдалося отримати параметри з ресурсу або встановити параметри у ресурсі." + +msgid "No space left on the resource." +msgstr "На ресурсі не залишилось місця." + +msgid "Not authorized to access resource." +msgstr "Не уповноважено на доступ до ресурсу." + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer перехопив загальну помилку потоку." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "" +"У елементі не реалізовано перехоплення цього потоку. Сповістіть про помилку." + +msgid "Could not determine type of stream." +msgstr "Не вдалося визначити тип потоку." + +msgid "The stream is of a different type than handled by this element." +msgstr "Потік іншого типу ніж тип, який обробляє цей елемент." + +msgid "There is no codec present that can handle the stream's type." +msgstr "Немає кодека, який здатен обробляти цей тип потоку." + +msgid "Could not decode stream." +msgstr "Не вдалося розкодувати потік." + +msgid "Could not encode stream." +msgstr "Не вдалося закодувати потік." + +msgid "Could not demultiplex stream." +msgstr "Не вдалося демультиплексувати потік." + +msgid "Could not multiplex stream." +msgstr "Не вдалося мультиплексувати потік." + +msgid "The stream is in the wrong format." +msgstr "Потік у некоректному форматі." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Дані потоку зашифровано, дешифрування не підтримується." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Дані потоку зашифровано, їх не можна дешифрувати, оскільки не надано " +"відповідного ключа дешифрування." + +#, c-format +msgid "No error message for domain %s." +msgstr "Немає повідомлення про помилку для домену %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Немає стандартного повідомлення про помилку для домену %s та коду %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Обраний годинник не може використовуватись у конвеєрі." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Помилка при записі кешу реєстру у %s: %s" + +msgid "title" +msgstr "назва" + +msgid "commonly used title" +msgstr "загальновживана назва" + +msgid "title sortname" +msgstr "назва (для впорядкування)" + +msgid "commonly used title for sorting purposes" +msgstr "загальновживана назва (для впорядкування)" + +msgid "artist" +msgstr "виконавець" + +msgid "person(s) responsible for the recording" +msgstr "особа, відповідальна за запис" + +msgid "artist sortname" +msgstr "виконавець (для впорядкування)" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "особа або особи, відповідальні за запис (для впорядкування)" + +msgid "album" +msgstr "альбом" + +msgid "album containing this data" +msgstr "альбом, що містить ці дані" + +msgid "album sortname" +msgstr "альбом (для впорядкування)" + +msgid "album containing this data for sorting purposes" +msgstr "альбом, який містить ці дані (для впорядкування)" + +msgid "album artist" +msgstr "виконавець альбому" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Виконавець всього альбому у форматі показу запису" + +msgid "album artist sortname" +msgstr "виконавець альбому (для впорядкування)" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Виконавець всього альбому у форматі впорядкування" + +msgid "date" +msgstr "дата" + +msgid "date the data was created (as a GDate structure)" +msgstr "дата створення (у форматі структури GDate)" + +msgid "datetime" +msgstr "дата-час" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "дата і час створення даних (у форматі структури GstDateTime)" + +msgid "genre" +msgstr "жанр" + +msgid "genre this data belongs to" +msgstr "жанр цих даних" + +msgid "comment" +msgstr "коментар" + +msgid "free text commenting the data" +msgstr "довільний текст з описом даних" + +msgid "extended comment" +msgstr "розширений коментар" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"довільний текст з описом даних у формі ключ=значення чи ключ[en]=коментар" + +msgid "track number" +msgstr "номер композиції" + +msgid "track number inside a collection" +msgstr "номер композиції у збірці" + +msgid "track count" +msgstr "кількість композицій" + +msgid "count of tracks inside collection this track belongs to" +msgstr "кількість композицій у збірці, до якої належить ця композиція" + +msgid "disc number" +msgstr "номер диска" + +msgid "disc number inside a collection" +msgstr "номер диска у збірці" + +msgid "disc count" +msgstr "кількість дисків" + +msgid "count of discs inside collection this disc belongs to" +msgstr "кількість дисків у збірці, до якої належить цей диск" + +msgid "location" +msgstr "адреса" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Джерело даних як адреса (місце, де розташовано початкові дані файла або " +"адреса поширення потоку)" + +msgid "homepage" +msgstr "домашня сторінка" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "" +"Домашня сторінка цього носія даних (домашня сторінка виконавця або фільму)" + +msgid "description" +msgstr "опис" + +msgid "short text describing the content of the data" +msgstr "короткий текст з описом вмісту даних" + +msgid "version" +msgstr "версія" + +msgid "version of this data" +msgstr "версія цих даних" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Інтернаціональний стандартний код запису (ISRC) — дивіться http://www.ifpi." +"org/isrc/" + +msgid "organization" +msgstr "організація" + +msgid "copyright" +msgstr "авторські права" + +msgid "copyright notice of the data" +msgstr "примітка щодо авторських прав на дані" + +msgid "copyright uri" +msgstr "uri авторських прав" + +msgid "URI to the copyright notice of the data" +msgstr "URI примітки про авторські права даних" + +msgid "encoded by" +msgstr "автор кодування" + +msgid "name of the encoding person or organization" +msgstr "ім’я людини або назва установи, якою було виконано кодування" + +msgid "contact" +msgstr "контакти" + +msgid "contact information" +msgstr "контактна інформація" + +msgid "license" +msgstr "ліцензія" + +msgid "license of data" +msgstr "ліцензія даних" + +msgid "license uri" +msgstr "uri ліцензії" + +msgid "URI to the license of the data" +msgstr "URI ліцензії даних" + +msgid "performer" +msgstr "виконавець" + +msgid "person(s) performing" +msgstr "особа(и), що виконала" + +msgid "composer" +msgstr "композитор" + +msgid "person(s) who composed the recording" +msgstr "особа чи особи, якими було створено музику запису" + +msgid "conductor" +msgstr "диригент" + +msgid "conductor/performer refinement" +msgstr "диригент або покращувач виконання" + +msgid "duration" +msgstr "тривалість" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "тривалість у одиницях виміру GStreamer (наносекунди)" + +msgid "codec" +msgstr "кодек" + +msgid "codec the data is stored in" +msgstr "кодек, яким закодовано дані" + +msgid "video codec" +msgstr "відеокодек" + +msgid "codec the video data is stored in" +msgstr "кодек, яким закодовано відеодані" + +msgid "audio codec" +msgstr "аудіокодек" + +msgid "codec the audio data is stored in" +msgstr "кодек, яким закодовані звукові дані" + +msgid "subtitle codec" +msgstr "кодек субтитрів" + +msgid "codec the subtitle data is stored in" +msgstr "кодек, у якому зберігаються субтитри" + +msgid "container format" +msgstr "формат контейнера" + +msgid "container format the data is stored in" +msgstr "формат контейнера, у якому зберігаються дані" + +msgid "bitrate" +msgstr "щільність потоку бітів" + +msgid "exact or average bitrate in bits/s" +msgstr "точна або приблизна щільність потоку бітів у біт/с" + +msgid "nominal bitrate" +msgstr "номінальна щільність потоку бітів" + +msgid "nominal bitrate in bits/s" +msgstr "номінальна щільність потоку бітів у біт/с" + +msgid "minimum bitrate" +msgstr "мінімальна щільність потоку бітів" + +msgid "minimum bitrate in bits/s" +msgstr "мінімальна щільність потоку бітів у біт/с" + +msgid "maximum bitrate" +msgstr "максимальна щільність потоку бітів" + +msgid "maximum bitrate in bits/s" +msgstr "максимальна щільність потоку бітів у біт/с" + +msgid "encoder" +msgstr "кодувальник" + +msgid "encoder used to encode this stream" +msgstr "кодувальник, який використовувався для кодування цих даних" + +msgid "encoder version" +msgstr "версія кодувальника" + +msgid "version of the encoder used to encode this stream" +msgstr "версія кодувальника, який використовувався для кодування цих даних" + +msgid "serial" +msgstr "номер" + +msgid "serial number of track" +msgstr "послідовний номер композиції" + +msgid "replaygain track gain" +msgstr "рівень відтворення композиції" + +msgid "track gain in db" +msgstr "рівень композиції, у дБ" + +msgid "replaygain track peak" +msgstr "пік відтворення композиції" + +msgid "peak of the track" +msgstr "пік композиції" + +msgid "replaygain album gain" +msgstr "рівень відтворення альбому" + +msgid "album gain in db" +msgstr "рівень альбому, у дБ" + +msgid "replaygain album peak" +msgstr "пік відтворення альбому" + +msgid "peak of the album" +msgstr "пік альбому" + +msgid "replaygain reference level" +msgstr "опорний рівень гучності відтворення" + +msgid "reference level of track and album gain values" +msgstr "опорні рівні гучності композиції чи альбому" + +msgid "language code" +msgstr "код мови" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "код мови для потоку, код має відповідати ISO-639-1 або ISO-639-2" + +msgid "language name" +msgstr "назва мови" + +msgid "freeform name of the language this stream is in" +msgstr "назва мови цього потоку звукових даних у довільній формі" + +msgid "image" +msgstr "зображення" + +msgid "image related to this stream" +msgstr "зображення, що стосується цього потоку" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "попередній перегляд зображення" + +msgid "preview image related to this stream" +msgstr "попередній перегляд зображення, пов’язаного з цим потоком" + +msgid "attachment" +msgstr "долучення" + +msgid "file attached to this stream" +msgstr "файл, долучений до цього потоку" + +msgid "beats per minute" +msgstr "тактів за хвилину" + +msgid "number of beats per minute in audio" +msgstr "кількість тактів звуку за хвилину" + +msgid "keywords" +msgstr "ключові слова" + +msgid "comma separated keywords describing the content" +msgstr "відокремлені комами ключові слова, що описують дані" + +msgid "geo location name" +msgstr "географічна назва" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"зручний для читання описова назва місцевості, у якій було записано або " +"створено дані" + +msgid "geo location latitude" +msgstr "географічна широта" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"географічна широта місцевості, де було записано або створено дані у градусах " +"відповідно до WGS84 (нуль — екватор, від’ємні значення відповідають " +"південній широті)" + +msgid "geo location longitude" +msgstr "географічна довгота" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"географічна довгота місцевості, де було записано або створено дані у " +"градусах відповідно до WGS84 (нуль — нульовий меридіан Гринвіча, від’ємні " +"значення відповідають західній довготі)" + +msgid "geo location elevation" +msgstr "географічна висота" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"висота над рівнем моря, де було записано або створено дані у метрах " +"відповідно до WGS84 (нуль відповідає рівню моря)" + +msgid "geo location country" +msgstr "країна" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "країна (англійською), у якій було записано або створено дані" + +msgid "geo location city" +msgstr "місто" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "місто (англійською), у якому було записано або створено дані" + +msgid "geo location sublocation" +msgstr "додаткові дані розташування" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"місце у місті, де виконувалася зйомка або було створено дані (наприклад, " +"район)" + +msgid "geo location horizontal error" +msgstr "похибка у даних гор. розташування" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "очікувана похибка у вимірюванні горизонтальних координат (у метрах)" + +msgid "geo location movement speed" +msgstr "географічна швидкість пересування" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "швидкість руху пристрою для знімання під час виконання зйомки у м/с" + +msgid "geo location movement direction" +msgstr "географічний напрямок пересування" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"напрямок руху пристрою, яким виконувалося знімання даних. Визначається у " +"градусах з використанням десяткових дробів, 0 відповідає географічній " +"півночі, відлік ведеться за годинниковою стрілкою." + +msgid "geo location capture direction" +msgstr "географічний напрямок зйомки" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"напрямок, у якому було спрямовано об’єктив пристрою, яким виконувалося " +"знімання даних. Визначається у градусах з використанням десяткових дробів, 0 " +"відповідає географічній півночі, відлік ведеться за годинниковою стрілкою." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "назва передачі" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Назва телепрограми/трансляції/серіалу звідки взято дані" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "назва передачі (для впорядкування)" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Назва телепрограми/трансляції/серіалу звідки взято дані (для впорядкування)" + +msgid "episode number" +msgstr "номер серії" + +msgid "The episode number in the season the media is part of" +msgstr "Номер серії у сезоні, частиною якого є дані" + +msgid "season number" +msgstr "номер сезону" + +msgid "The season number of the show the media is part of" +msgstr "Номер сезону, частиною якого є дані" + +msgid "lyrics" +msgstr "текст" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Текст, що супроводжує дані, типово — текст пісні" + +msgid "composer sortname" +msgstr "композитор (для впорядкування)" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "" +"особа (чи особи), якою виконувалося компонування запису (для впорядкування)" + +msgid "grouping" +msgstr "групування" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Групує пов’язані дані, які складаються з декількох композицій, наприклад, " +"різні частини концерту. Має вищий рівень за окрему композицію, але нижчий за " +"рівень альбому." + +msgid "user rating" +msgstr "оцінка користувачем" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Оцінка, визначена користувачем. Більшим значенням відповідає вища оцінка." + +msgid "device manufacturer" +msgstr "виробник пристрою" + +msgid "Manufacturer of the device used to create this media" +msgstr "Виробник пристрою, використаного для створення цих даних" + +msgid "device model" +msgstr "модель пристрою" + +msgid "Model of the device used to create this media" +msgstr "Модель пристрою, використаного для створення цих даних" + +msgid "application name" +msgstr "назва програми" + +msgid "Application used to create the media" +msgstr "Програма, за допомогою якої записано дані" + +msgid "application data" +msgstr "дані програми" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "Довільні дані програми, якими підписано дані" + +msgid "image orientation" +msgstr "орієнтація зображення" + +msgid "How the image should be rotated or flipped before display" +msgstr "Визначає обертання та віддзеркалення зображення перед показом" + +msgid "publisher" +msgstr "поширювач" + +msgid "Name of the label or publisher" +msgstr "Назва лейбла або поширювача" + +msgid "interpreted-by" +msgstr "інтерпретація" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Дані щодо тих, ким було виконано ремікс або подібну інтерпретацію" + +msgid "midi-base-note" +msgstr "базова-нота-midi" + +msgid "Midi note number of the audio track." +msgstr "Номер ноти MIDI звукової доріжки." + +msgid "private-data" +msgstr "конфіденційні-дані" + +msgid "Private data" +msgstr "Конфіденційні дані" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Не знайдено обробника адрес для протоколу %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Підтримки схеми адреси «%s» не передбачено" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "ПОМИЛКА: у елементі %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Додаткова діагностична інформація:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "у посилання немає джерела [приймач=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "у посилання немає приймача [джерело=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "немає властивості «%s» у елементі «%s»" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "не вдалося встановити властивість «%s» у елементі «%s» у значення «%s»" + +msgid "Delayed linking failed." +msgstr "Спроба відкладеного компонування зазнала невдачі." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "не вдалося прив'язати %s до %s, %s не може обробити можливості %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"не вдалося прив'язати %s до %s, жоден елемент не може обробити можливості %s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "не вдалося прив'язати %s до %s із можливостями %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "не вдалося прив'язати %s до %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "немає елемента «%s»" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "неочікуване посилання «%s» — ігноруємо" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "неочікуване посилання-підкладка «%s» — ігноруємо" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "не вдалося розібрати можливості «%s»" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "немає елемента-споживача для URI «%s»" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "відсутній елемент-джерело для URI «%s»" + +msgid "syntax error" +msgstr "синтаксична помилка" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "вказано порожній контейнер «%s», не допускається" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "немає фрагмента «%s», розпаковуємо елементи" + +msgid "empty pipeline not allowed" +msgstr "не можна використовувати порожній канал" + +msgid "A lot of buffers are being dropped." +msgstr "Викинуто багато буферів." + +msgid "Internal data flow problem." +msgstr "Помилка внутрішнього перенесення даних." + +msgid "Internal data flow error." +msgstr "Помилка внутрішнього перенесення даних." + +msgid "Internal clock error." +msgstr "Помилка внутрішньої синхронізації." + +msgid "Failed to map buffer." +msgstr "Не вдалося отримати місце під буфер." + +msgid "Filter caps" +msgstr "Фільтр можливостей" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Обмежити допустимі можливості (NULL означає ANY). Встановлення цієї " +"властивості призводить до посилання на поставлений об'єкт GstCaps." + +msgid "Caps Change Mode" +msgstr "Режим зміни можливостей" + +msgid "Filter caps change behaviour" +msgstr "Зміна поведінки можливостей фільтрування" + +msgid "No Temp directory specified." +msgstr "Не вказано каталог тимчасових даних." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Не вдалося створити тимчасовий файл даних «%s»." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Не вдалося відкрити файл «%s» для читання." + +msgid "Error while writing to download file." +msgstr "Помилка під час запису до файла отриманих даних." + +msgid "No file name specified for writing." +msgstr "Не вказано назви файла для запису." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Не вдалося відкрити файл «%s» для запису." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Помилка закривання файла «%s»." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Помилка при встановленні позиції у файлі «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Помилка при записуванні до файла «%s»." + +msgid "No file name specified for reading." +msgstr "Не вказано назву файла для читання." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Не вдалося отримати інформацію щодо «%s»." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "«%s» є каталогом." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Файл «%s» є сокетом." + +msgid "Failed after iterations as requested." +msgstr "Помилка після ітерацій у запитаному порядку." + +msgid "caps" +msgstr "можливості" + +msgid "detected capabilities in stream" +msgstr "у потоці знайдено можливості" + +msgid "minimum" +msgstr "мінімум" + +msgid "force caps" +msgstr "примусово визначені можливості" + +msgid "force caps without doing a typefind" +msgstr "примусово визначити можливості без виконання typefind" + +msgid "Stream doesn't contain enough data." +msgstr "У потоці міститься недостатньо даних." + +msgid "Stream contains no data." +msgstr "Потік не містить даних." + +msgid "Implemented Interfaces:\n" +msgstr "Реалізовані інтерфейси:\n" + +msgid "readable" +msgstr "читання" + +msgid "writable" +msgstr "запис" + +msgid "deprecated" +msgstr "застаріле" + +msgid "controllable" +msgstr "контроль" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "можна змінювати у станах NULL, READY, PAUSED та PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "можна змінювати лише у станах NULL, READY і PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "можна змінювати лише у станах NULL і READY" + +msgid "Blacklisted files:" +msgstr "Заблоковані файли:" + +msgid "Total count: " +msgstr "Загальна кількість:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d заблокований файл" +msgstr[1] "%d заблокованих файли" +msgstr[2] "%d заблокованих файлів" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d модуль" +msgstr[1] "%d модулі" +msgstr[2] "%d модулів" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d заблокований запис" +msgstr[1] "%d заблокованих записи" +msgstr[2] "%d заблокованих записів" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d функція" +msgstr[1] "%d функції" +msgstr[2] "%d функцій" + +msgid "Print all elements" +msgstr "Вивести усі елементи" + +msgid "Print list of blacklisted files" +msgstr "Показати список заблокованих файлів" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"Вивести придатний для обробки комп’ютером список можливостей, роботу яких " +"забезпечує модуль або всі модулі.\n" +" Використовується разом з зовнішніми " +"механізмами автоматичного встановлення модулів" + +msgid "List the plugin contents" +msgstr "Показати вміст модуля" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Список типів елементів (також відомих як класи), відокремлених похилими " +"рисками («/»). (неупорядкований)" + +msgid "Check if the specified element or plugin exists" +msgstr "Перевірити, чи існує вказаний елемент або додаток" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Під час перевірки існування елемента або додатка також перевірити, чи є його " +"версія новішою за вказану або рівною їй" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "Показати підтримувані схеми адрес з елементами, які їх реалізують" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Не вдалося завантажити файл модулю %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Немає елемента елемента або модуля «%s»\n" + +msgid "Index statistics" +msgstr "Статистичні дані покажчика" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Отримано повідомлення %u від елемента «%s» (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Отримано повідомлення %u від гнізда «%s:%s» (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Отримано повідомлення %u від об’єкта «%s» (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Отримано повідомлення %u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Отримано ознаку кінця рядка від елементу «%s».\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "ЗНАЙДЕНО ТЕГ : знайдено у елементі «%s».\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "ЗНАЙДЕНО МІТКУ : знайдено у елементі «%s:%s».\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "ЗНАЙДЕНО МІТКУ : знайдено об’єктом «%s».\n" + +msgid "FOUND TAG\n" +msgstr "ЗНАЙДЕНО МІТКУ\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "ЗНАЙДЕНО ЗМІСТ : знайдено елементом «%s».\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "ЗНАЙДЕНО ЗМІСТУ: знайдено об’єктом «%s».\n" + +msgid "FOUND TOC\n" +msgstr "ЗНАЙДЕНО ЗМІСТ\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"ІНФОРМАЦІЯ:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "ПОПЕРЕДЖЕННЯ: у елементі %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "" +"Виконано випереджальне просування даних, очікуємо на завершення " +"буферизації...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "" +"Виконано випереджальне просування даних, очікуємо на завершення обробки...\n" + +msgid "buffering..." +msgstr "буферизація..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Буферизацію завершено, канал переводиться у стан ВІДТВОРЕННЯ ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Буферизація, канал переводиться у стан ПРИЗУПИНЕНО ...\n" + +msgid "Redistribute latency...\n" +msgstr "Перерозподіл затримки...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Встановлення стану %s, потрібно для %s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Переривання: зупинка каналу...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Поступ: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Не вистачає елемента: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Отримано контекст з елемента «%s»: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Вивести мітки (також відомі як метадані)" + +msgid "Output TOC (chapters and editions)" +msgstr "Виведений зміст (розділи та редакції)" + +msgid "Output status information and property notifications" +msgstr "Вивести інформацію про стан та сповіщення щодо властивостей" + +msgid "Do not print any progress information" +msgstr "Не показувати даних щодо поступу" + +msgid "Output messages" +msgstr "Виведено повідомлення" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Не виводити дані щодо стану для вказаної властивості, якщо увімкнено " +"докладне виведення (можна використовувати декілька разів)" + +msgid "PROPERTY-NAME" +msgstr "НАЗВА-ВЛАСТИВОСТІ" + +msgid "Do not install a fault handler" +msgstr "Не встановлювати обробник збоїв" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Примусово надіслати EOS до джерел до завершення роботи каналу" + +msgid "Gather and print index statistics" +msgstr "Зібрати та показати статистичні дані покажчика" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "ПОМИЛКА: канал не може бути сконструйований: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "ПОМИЛКА: канал не може бути сконструйований.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "ПОПЕРЕДЖЕННЯ: помилковий канал: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "ПОМИЛКА: не знайдений елемент \"pipeline\".\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Канал переводиться у стан PAUSED...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "ПОМИЛКА: канал не може призупинитись.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Конвеєр активний та не потребує випереджального просування даних...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Канал у стані приготування до випереджального просування даних...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "" +"ПОМИЛКА: канал не може перейти у стан випереджального просування даних.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Канал у стані випереджального просування даних...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Канал переводиться у стан ВІДТВОРЕННЯ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "ПОМИЛКА: канал не може почати відтворення.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "Увімкнено EOS при завершенні - Примусове виведення EOS до каналу\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "Увімкнено EOS при завершенні - очікуємо на EOS після помилки\n" + +msgid "Waiting for EOS...\n" +msgstr "Очікування на EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Отримано EOS - завершення роботи каналу...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "" +"Переривання під час очікування на EOS - перериваємо роботу каналу " +"передавання даних...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Під час очікування на EOS сталася помилка\n" + +msgid "Execution ended after %" +msgstr "Виконання завершено після %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Канал переводиться у стан ГОТОВИЙ ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Канал переводиться у стан NULL ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "Спорожнення каналу...\n" + +#~ msgid "bin" +#~ msgstr "фрагмент" + +#~ msgid "Internal data stream error." +#~ msgstr "Помилка внутрішнього потоку даних." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Не виводити інформацію про стан типу ТИП" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "ТИП1,ТИП2,..." + +#~ msgid "link without source element" +#~ msgstr "зв'язок без елемента-джерела" + +#~ msgid "link without sink element" +#~ msgstr "зв'язок без елемента-споживача" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "немає елемента для зв'язку URI «%s» до" + +#~ msgid "maximum" +#~ msgstr "максимум" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Використання: gst-xmllaunch [ елемент." +#~ "властивість=значення ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "ПОМИЛКА: помилка при аналізі xml файлу «%s».\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "ПОМИЛКА: немає верхнього елемента каналу у файлі «%s».\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "" +#~ "ПОПЕРЕДЖЕННЯ: наразі підтримується лише один елемент найвищого рівня.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "" +#~ "ПОМИЛКА: не вдалося проаналізувати аргумент командного рядка %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "ПОПЕРЕДЖЕННЯ: елемент з назвою «%s» не існує.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Зберегти xml представлення каналу у файл ФАЙЛ та завершитись" + +#~ msgid "FILE" +#~ msgstr "ФАЙЛ" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Не встановлювати обробники сигналів для SIGUSR1 і SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "" +#~ "Вивести трасування розподілу пам’яті (якщо ввімкнено при компіляції)" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "Помилка при повторному скануванні реєстру модулів %s: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "Помилка при повторному скануванні реєстру %s" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "Внутрішня помилка GStreamer: помилка зміни стану." + +#~ msgid "original location of file as a URI" +#~ msgstr "оригінальне розташування файлу у вигляді URI" + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "Помилка при записуванні у дескриптор файлу \"%d\"." + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "Дескриптор файлу \"%d\" некоректний." + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "канал ЗВІЛЬНЕННЯ...\n" diff --git a/po/vi.gmo b/po/vi.gmo new file mode 100644 index 0000000..0335d45 Binary files /dev/null and b/po/vi.gmo differ diff --git a/po/vi.po b/po/vi.po new file mode 100644 index 0000000..81eaaba --- /dev/null +++ b/po/vi.po @@ -0,0 +1,1394 @@ +# Vietnamese Translation for GStreamer. +# Bản dịch tiếng Việt dành cho GStreamer. +# Copyright © 2016 Free Software Foundation, Inc. +# This file is distributed under the same license as the gstreamer package. +# Clytie Siddall , 2005-2010. +# Trần Ngọc Quân , 2012-2014, 2015, 2016, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 06:45+0700\n" +"Last-Translator: Trần Ngọc Quân \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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Language-Team-Website: \n" +"X-Generator: Gtranslator 2.91.7\n" + +msgid "Print the GStreamer version" +msgstr "Hiển thị phiên bản của GStreamer" + +msgid "Make all warnings fatal" +msgstr "Đặt mọi cảnh báo là nghiêm trọng" + +msgid "Print available debug categories and exit" +msgstr "Hiển thị tất cả các loại gỡ lỗi sẵn có rồi thoát" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"Mức gỡ lỗi mặc định từ 1 (chỉ lỗi) đến 9 (mọi thứ) hay 0 (không xuất gì)" + +msgid "LEVEL" +msgstr "MỨC" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"Danh sách định giới bằng dấu phẩy của đôi “tên_loại:cấp” để đặt cấp rõ ràng " +"cho mỗi loại. Thí dụ: GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "DANH_SÁCH" + +msgid "Disable colored debugging output" +msgstr "Tắt xuất dữ liệu gỡ lỗi với màu" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "" +"Đổi chế độ màu của nhật ký gỡ lỗi. Các chế độ có thể là: off, on, disable, " +"auto, unix" + +msgid "Disable debugging" +msgstr "Tắt gỡ lỗi" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "Bật chẩn đoán chi tiết việc nạp phần bổ sung" + +msgid "Colon-separated paths containing plugins" +msgstr "Các đường dẫn định giới bằng dấu hai chấm mà chứa phần bổ sung" + +msgid "PATHS" +msgstr "ĐƯỜNG_DẪN" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"Danh sách định giới bằng dấu phẩy chứa các phần bổ sung cần nạp trước, thêm " +"vào danh sách được cất giữ trong biến môi trường GST_PLUGIN_PATH" + +msgid "PLUGINS" +msgstr "PHẦN_BỔ_SUNG" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "Tắt chức năng bắt lỗi phân đoạn trong khi nạp phần bổ sung" + +msgid "Disable updating the registry" +msgstr "Tắt khả năng cập nhật bộ đăng ký" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "" +"Tắt khả năng tạo và thực hiện tiến trình bổ trợ trong khi quét bộ đăng ký" + +msgid "GStreamer Options" +msgstr "Tùy chọn GStreamer" + +msgid "Show GStreamer Options" +msgstr "Hiện Tùy chọn GStreamer" + +msgid "Unknown option" +msgstr "Tùy chọn lạ" + +msgid "GStreamer encountered a general core library error." +msgstr "Trình GStreamer mới gặp một lỗi thư viện lõi chung." + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "" +"Những nhà phát triển GStreamer đã quá lười mà chưa gán mã lỗi cho lỗi này." + +msgid "Internal GStreamer error: code not implemented." +msgstr "Lỗi nội bộ GStreamer: chưa viết mã cho chức năng này." + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Lỗi GStreamer: không thay đổi được tình trạng, và một phần tử nào đó không " +"gửi được thông điệp lỗi đúng chứa lý do của lỗi này." + +msgid "Internal GStreamer error: pad problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề đệm." + +msgid "Internal GStreamer error: thread problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề về tuyến trình." + +msgid "GStreamer error: negotiation problem." +msgstr "Lỗi GStreamer: vấn đề thỏa thuận." + +msgid "Internal GStreamer error: event problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề sự kiện." + +msgid "Internal GStreamer error: seek problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề di chuyển vị trí đọc." + +msgid "Internal GStreamer error: caps problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề caps." + +msgid "Internal GStreamer error: tag problem." +msgstr "Lỗi nội bộ GStreamer: vấn đề thẻ." + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "Bản cài đặt GStreamer của bạn còn thiếu một bổ sung." + +msgid "GStreamer error: clock problem." +msgstr "Lỗi GStreamer: vấn đề đồng hồ." + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "Ứng dụng này đang thử sử dụng chức năng GStreamer bị tắt." + +msgid "GStreamer encountered a general supporting library error." +msgstr "Trình GStreamer mới gặp một lỗi thư viện hỗ trợ chung." + +msgid "Could not initialize supporting library." +msgstr "Không thể khởi động thư viện hỗ trợ." + +msgid "Could not close supporting library." +msgstr "Không thể đóng thư viện hỗ trợ." + +msgid "Could not configure supporting library." +msgstr "Không thể cấu hình thư viện hỗ trợ." + +msgid "Encoding error." +msgstr "Lỗi giải mã." + +msgid "GStreamer encountered a general resource error." +msgstr "Trình GStreamer mới gặp một lỗi tài nguyên chung." + +msgid "Resource not found." +msgstr "Không tìm thấy tài nguyên." + +msgid "Resource busy or not available." +msgstr "Tài nguyên đang bận hay chưa sẵn sàng." + +msgid "Could not open resource for reading." +msgstr "Không thể mở tài nguyên để đọc." + +msgid "Could not open resource for writing." +msgstr "Không thể mở tài nguyên để ghi." + +msgid "Could not open resource for reading and writing." +msgstr "Không thể mở tài nguyên để đọc và ghi." + +msgid "Could not close resource." +msgstr "Không thể đóng tài nguyên." + +msgid "Could not read from resource." +msgstr "Không thể đọc từ tài nguyên." + +msgid "Could not write to resource." +msgstr "Không thể ghi vào tài nguyên." + +msgid "Could not perform seek on resource." +msgstr "Không thể thi hành việc di chuyển vị trí đọc trên tài nguyên." + +msgid "Could not synchronize on resource." +msgstr "Không thể đồng bộ trên tài nguyên." + +msgid "Could not get/set settings from/on resource." +msgstr "Không thể lấy/đặt cài đặt từ/trên tài nguyên." + +msgid "No space left on the resource." +msgstr "Không còn không gian trống trên tài nguyên đó." + +msgid "Not authorized to access resource." +msgstr "Không đủ thẩm quyền truy cập trên tài nguyên." + +msgid "GStreamer encountered a general stream error." +msgstr "Trình GStreamer mới gặp một lỗi luồng chung." + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "phần tử không thi hành khả năng quản lý luồng này. Hãy thông báo lỗi." + +msgid "Could not determine type of stream." +msgstr "Không thể quyết định kiểu luồng dữ liệu." + +msgid "The stream is of a different type than handled by this element." +msgstr "Luồng dữ liệu đó khác kiểu với luồng mà phần tử này xử lý được." + +msgid "There is no codec present that can handle the stream's type." +msgstr "" +"Hiện thời không có phần mã hóa/giải mã (codec) xử lý được luồng kiểu đó." + +msgid "Could not decode stream." +msgstr "Không thể giải mã luồng dữ liệu." + +msgid "Could not encode stream." +msgstr "Không thể mã hóa luồng dữ liệu." + +msgid "Could not demultiplex stream." +msgstr "Không thể tách kênh luồng dữ liệu." + +msgid "Could not multiplex stream." +msgstr "Không thể phối hợp luồng để truyền thông qua một kênh riêng lẻ." + +msgid "The stream is in the wrong format." +msgstr "Luồng dữ liệu có định dạng sai." + +msgid "The stream is encrypted and decryption is not supported." +msgstr "Luồng dữ liệu bị mã hóa và không hỗ trợ chức năng giải mã." + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "" +"Luồng dữ liệu bị mã hóa và không thể giải mã vì chưa cung cấp khóa thích hợp." + +#, c-format +msgid "No error message for domain %s." +msgstr "Không có thông điệp lỗi cho miền %s." + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "Không có thông điệp chuẩn cho miền %s và mã %d." + +msgid "Selected clock cannot be used in pipeline." +msgstr "Đồng hồ đã chọn không thể dùng trong đường ống." + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "Lỗi ghi đăng ký bộ nhớ tạm vào %s: %s" + +msgid "title" +msgstr "tựa đề" + +msgid "commonly used title" +msgstr "tựa đề thường dùng" + +msgid "title sortname" +msgstr "tên sắp" + +msgid "commonly used title for sorting purposes" +msgstr "thường dùng cho mục đích sắp xếp" + +msgid "artist" +msgstr "nghệ sĩ" + +msgid "person(s) responsible for the recording" +msgstr "người thu nhạc này" + +msgid "artist sortname" +msgstr "tên nghệ sĩ dạng viết tắt" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "(các) người chịu trách nhiệm về bản thu, cho mục đích sắp xếp" + +msgid "album" +msgstr "tập nhạc" + +msgid "album containing this data" +msgstr "tập nhạc chứa dữ liệu này" + +msgid "album sortname" +msgstr "tên sắp xếp tập nhạc" + +msgid "album containing this data for sorting purposes" +msgstr "tập nhạc chứa dữ liệu này, cho mục đích sắp xếp" + +msgid "album artist" +msgstr "nghệ sĩ tập" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "Nghệ sĩ của toàn bộ tập nhạc, như hiển thị đúng" + +msgid "album artist sortname" +msgstr "tên sắp nghệ sĩ tập nhạc" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "Nghệ sĩ của toàn bộ tập nhạc, theo thứ tự đúng" + +msgid "date" +msgstr "ngày" + +msgid "date the data was created (as a GDate structure)" +msgstr "ngày tạo dữ liệu này (dạng cấu trúc GDate)" + +msgid "datetime" +msgstr "ngày-giờ" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "ngày và giờ mà dữ liệu được tạo (dạng cấu trúc GstDateTime)" + +msgid "genre" +msgstr "thể loại" + +msgid "genre this data belongs to" +msgstr "thể loại của dữ liệu này" + +msgid "comment" +msgstr "ghi chú" + +msgid "free text commenting the data" +msgstr "ý kiến của bạn về nhạc này" + +msgid "extended comment" +msgstr "ghi chú kéo dài" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "" +"văn bản tự do đặt ghi chú về dữ liệu dưới dạng key=value (khóa=giá trị) hay " +"key[en]=comment (khóa[en]=ghi chú)" + +msgid "track number" +msgstr "số rãnh" + +msgid "track number inside a collection" +msgstr "số thứ tự rãnh ở trong bộ sưu tập" + +msgid "track count" +msgstr "số lượng rãnh" + +msgid "count of tracks inside collection this track belongs to" +msgstr "số đếm rãnh ở trong bộ sưu tập" + +msgid "disc number" +msgstr "số đĩa" + +msgid "disc number inside a collection" +msgstr "số thứ tự đĩa ở trong bộ sưu tập" + +msgid "disc count" +msgstr "số đĩa" + +msgid "count of discs inside collection this disc belongs to" +msgstr "số lượng đĩa ở trong bộ sưu tập" + +msgid "location" +msgstr "địa điểm" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "" +"Nguồn của nhạc/phim dưới dạng một địa chỉ URI (địa chỉ gốc của tập tin hay " +"luồng)" + +msgid "homepage" +msgstr "trang chủ" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "Trang chủ của nghệ sĩ hay phim" + +msgid "description" +msgstr "mô tả" + +msgid "short text describing the content of the data" +msgstr "bài tóm tắt diễn tả nội dung của dữ liệu này" + +msgid "version" +msgstr "phiên bản" + +msgid "version of this data" +msgstr "phiên bản của dữ liệu này" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "" +"Luật thu âm Tiêu chuẩn Quốc tế (International Standard Recording Code) — xem " +"" + +msgid "organization" +msgstr "tổ chức" + +msgid "copyright" +msgstr "tác quyền" + +msgid "copyright notice of the data" +msgstr "thông báo tác quyền của dữ liệu này" + +msgid "copyright uri" +msgstr "URI tác quyền" + +msgid "URI to the copyright notice of the data" +msgstr "địa chỉ URI đến thông báo tác quyền của dữ liệu này" + +msgid "encoded by" +msgstr "má hóa bởi" + +msgid "name of the encoding person or organization" +msgstr "tên của người hay tổ chức đã mã hóa tập tin" + +msgid "contact" +msgstr "liên lạc" + +msgid "contact information" +msgstr "thông tin liên lạc" + +msgid "license" +msgstr "giấy phép" + +msgid "license of data" +msgstr "giấy phép của dữ liệu" + +msgid "license uri" +msgstr "URI giấy phép" + +msgid "URI to the license of the data" +msgstr "địa chỉ URI đến giấy phép của dữ liệu này" + +msgid "performer" +msgstr "người biểu diễn" + +msgid "person(s) performing" +msgstr "người biểu diễn nhạc/ảnh này" + +msgid "composer" +msgstr "người soạn" + +msgid "person(s) who composed the recording" +msgstr "(những) người đã soạn bản thu này" + +msgid "conductor" +msgstr "người chỉ huy" + +msgid "conductor/performer refinement" +msgstr "thanh lọc người chỉ huy / biểu diễn" + +msgid "duration" +msgstr "thời lượng" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "thời gian bằng đơn vị thời gian kiểu GStreamer (phần tỷ giây: ns)" + +msgid "codec" +msgstr "mã hóa" + +msgid "codec the data is stored in" +msgstr "cách mã hóa/giải mà dữ liệu này" + +msgid "video codec" +msgstr "codec của phim" + +msgid "codec the video data is stored in" +msgstr "cách mã hóa/giải mã dữ liệu ảnh động này" + +msgid "audio codec" +msgstr "codec âm thanh" + +msgid "codec the audio data is stored in" +msgstr "cách mã hóa/giải mã dữ liệu âm thanh này" + +msgid "subtitle codec" +msgstr "codec phụ đề" + +msgid "codec the subtitle data is stored in" +msgstr "codec theo đó dữ liệu phụ đề được mã hóa" + +msgid "container format" +msgstr "định dạng chứa" + +msgid "container format the data is stored in" +msgstr "định dạng chứa dữ liệu được cất giữ" + +msgid "bitrate" +msgstr "tốc độ bít" + +msgid "exact or average bitrate in bits/s" +msgstr "" +"số bít dữ liệu trong mỗi giây phát, chính xác hay trung bình, theo bít/giây" + +msgid "nominal bitrate" +msgstr "tốc độ bít không đáng kể" + +msgid "nominal bitrate in bits/s" +msgstr "số bít dữ liệu trong mỗi giây phát, không đáng kể, theo bít/giây" + +msgid "minimum bitrate" +msgstr "tốc độ bít tối thiểu" + +msgid "minimum bitrate in bits/s" +msgstr "số bít dữ liệu trong mỗi giây phát, tối thiểu, theo bít/giây" + +msgid "maximum bitrate" +msgstr "tốc độ bít tối đa" + +msgid "maximum bitrate in bits/s" +msgstr "số bít dữ liệu trong mỗi giây được phát, tối đa, theo bít/giây" + +msgid "encoder" +msgstr "mã hóa" + +msgid "encoder used to encode this stream" +msgstr "bộ mã hóa được dùng để mã hóa luồng này" + +msgid "encoder version" +msgstr "phiên bản bộ giải mã" + +msgid "version of the encoder used to encode this stream" +msgstr "phiên bản của bộ mã hóa được dùng để mã hóa luồng này" + +msgid "serial" +msgstr "số sê-ri" + +msgid "serial number of track" +msgstr "số sê-ri của rãnh" + +msgid "replaygain track gain" +msgstr "nhớ âm lượng rãnh" + +msgid "track gain in db" +msgstr "tăng hay giảm âm lượng của rãnh tính theo đề-xi-ben" + +msgid "replaygain track peak" +msgstr "nhớ âm lượng tối đa rãnh" + +msgid "peak of the track" +msgstr "âm lượng tối đa bạn muốn cho rãnh này" + +msgid "replaygain album gain" +msgstr "nhớ âm lượng tập nhạc/ảnh" + +msgid "album gain in db" +msgstr "tăng hay giảm âm lượng của tập nhạc/ảnh tính theo đề-xi-ben" + +msgid "replaygain album peak" +msgstr "nhớ âm lượng tối đa tập nhạc/ảnh" + +msgid "peak of the album" +msgstr "âm lượng tối đa bạn muốn cho tập nhạc/ảnh này" + +msgid "replaygain reference level" +msgstr "lớp chỉ dẫn khuếch đại phát lại" + +msgid "reference level of track and album gain values" +msgstr "lớp chỉ dẫn các giá trị khuếch đại của rãnh và tập nhạc" + +msgid "language code" +msgstr "mã ngôn ngữ" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "" +"mã ngôn ngữ cho luồng dữ liệu này, tùy theo tiêu chuẩn ISO-639-1 hoặc " +"ISO-639-2" + +msgid "language name" +msgstr "Tên ngôn ngữ" + +msgid "freeform name of the language this stream is in" +msgstr "tên dạng tự do của ngôn ngữ luồng dữ liệu này là trong" + +msgid "image" +msgstr "ảnh" + +msgid "image related to this stream" +msgstr "ảnh liên quan đến luồng này" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "ảnh xem thử" + +msgid "preview image related to this stream" +msgstr "ảnh xem thử liên quan đến luồng dữ liệu này" + +msgid "attachment" +msgstr "đính kèm" + +msgid "file attached to this stream" +msgstr "tập tin đính kèm luồng này" + +msgid "beats per minute" +msgstr "tiếng nhịp đập mỗi phút" + +msgid "number of beats per minute in audio" +msgstr "số tiếng nhịp trong mỗi phút âm thanh" + +msgid "keywords" +msgstr "từ khóa" + +msgid "comma separated keywords describing the content" +msgstr "các từ khóa định giới bằng dấu phẩy, diễn tả nội dung" + +msgid "geo location name" +msgstr "tên định vị địa lý" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "" +"vị trí miêu tả cho người đọc được của nơi ở đó nhạc/phím đã được thu hay tạo" + +msgid "geo location latitude" +msgstr "vĩ độ định vị địa lý" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"vĩ độ định vị địa lý ở đó nhạc/phím đã được thu hay tạo, theo độ tùy theo " +"WGS84 (xích đạo là số không, độ vĩ Nam có số âm)" + +msgid "geo location longitude" +msgstr "độ kinh định vị địa lý" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"kinh độ định vị địa lý ở đó nhạc/phím đã được thu hay tạo, theo độ tùy theo " +"WGS84 (kinh tuyến gốc ở Quốc Anh là số không, độ kinh Tây có số âm)" + +msgid "geo location elevation" +msgstr "độ cao định vị địa lý" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"độ cao định vị địa lý ở đó nhạc/phím đã được thu hay tạo, theo mét tùy theo " +"WSG84 (mặt biển trung bình là số không)" + +msgid "geo location country" +msgstr "vị trí địa lý của quốc gia" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "" +"quốc gia (tên tiếng Anh, v.d. “Vietnam”) ở đó nhạc/phim đã được quay/thu" + +msgid "geo location city" +msgstr "vị trí địa lý của thành phố" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "" +"thành phố (tên tiếng Anh, v.d. “Hanoi”) ở đó nhạc/phím đã được quay/thu" + +msgid "geo location sublocation" +msgstr "vị trí phụ địa lý" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "" +"một vùng bên trong thành phố ở đó dữ liệu đa phương tiện đã được tạo hay sản " +"xuất (v.d. hàng xóm)" + +msgid "geo location horizontal error" +msgstr "lỗi vị trí đường chân trời theo Trái Đất" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "chờ đợi một lỗi của đo lường vị trí đường nằm ngang (tính bằng mét)" + +msgid "geo location movement speed" +msgstr "tốc độ di chuyển theo vị trí đại lý" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "" +"tốc độ di chuyển của thiết bị bắt trong khi thực hiện việc bắt theo miligiây" + +msgid "geo location movement direction" +msgstr "hướng di chuyển theo vị trí đại lý" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"ngụ ý hướng di chuyển của thiết bị đang bắt phương tiện. Giá trị này được " +"đại diện bằng độ theo dấu phẩy động: 0 là Bắc đại lý, và giá trị tăng theo " +"chiều kim đồng hồ." + +msgid "geo location capture direction" +msgstr "hướng bắt theo vị trí đại lý" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"cho biết rằng hướng thiết bị đang chỉ khi bắt phương tiện. Giá trị này được " +"đại diện bằng độ theo dấu phẩy động: 0 là cực Bắc, và giá trị tăng theo " +"chiều kim đồng hồ." + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "hiện tên" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "Tên của buổi biểu diễn TV/podcast/bộ là gốc của phương tiện này" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "hiện tên ngắn" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "" +"Tên của cuộc biểu diễn TV/podcast/bộ là gốc của phương tiện này, cho mục " +"đích sắp xếp" + +msgid "episode number" +msgstr "số tình tiết" + +msgid "The episode number in the season the media is part of" +msgstr "Số thứ tự tình tiết trong mùa cung cấp phương tiện này" + +msgid "season number" +msgstr "số mùa" + +msgid "The season number of the show the media is part of" +msgstr "Số thứ tự mùa trong cuộc biểu diễn cung cấp phương tiện này" + +msgid "lyrics" +msgstr "lời nhạc" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "Lời nhạc của phương tiện, thường dùng cho bài hát" + +msgid "composer sortname" +msgstr "tên sắp nhạc sĩ" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "(những) người đã soạn bản thu, dành cho mục đích sắp xếp" + +msgid "grouping" +msgstr "nhóm lại" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"Nhóm lại các phương tiện liên quan mà chiếm giữ nhiều rãnh khác nhau (v.d. " +"các phần khác nhau của một côngxectô). Cấp này cao hơn rãnh còn thấp hơn tập " +"nhạc." + +msgid "user rating" +msgstr "đánh giá do người dùng" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "" +"Đánh giá bởi người dùng. Càng cao điểm càng nhiều người dùng thích nhạc/phim " +"này" + +msgid "device manufacturer" +msgstr "nhà chế tạo thiết bị" + +msgid "Manufacturer of the device used to create this media" +msgstr "Nhà chế tạo của thiết bị được dùng để tạo phương tiện này" + +msgid "device model" +msgstr "mẫu thiết bị" + +msgid "Model of the device used to create this media" +msgstr "Mô hình của thiết bị được dùng để tạo phương tiện này" + +msgid "application name" +msgstr "tên ứng dụng" + +msgid "Application used to create the media" +msgstr "Ứng dụng sử dụng để tạo đa phương tiện" + +msgid "application data" +msgstr "dữ liệu ứng dụng" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "" +"Dữ liệu ứng dụng tùy ý để được xếp thứ tự vào trong đa phương tiện (media)" + +msgid "image orientation" +msgstr "hướng ảnh" + +msgid "How the image should be rotated or flipped before display" +msgstr "Hướng mà ảnh nên được quay hoặc lật trước khi hiển thị" + +msgid "publisher" +msgstr "nhà xuất bản" + +msgid "Name of the label or publisher" +msgstr "Tên của nhãn hay nhà xuất bản" + +msgid "interpreted-by" +msgstr "phiên-dịch-bởi" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "Thông tin về người đứng sau phối và biên tập lại" + +msgid "midi-base-note" +msgstr "midi-base-note" + +msgid "Midi note number of the audio track." +msgstr "Số ghi chú midi của rãnh âm thanh." + +msgid "private-data" +msgstr "dữ-liệu-riêng" + +msgid "Private data" +msgstr "Dữ liệu riêng" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "Không tìm thấy bộ tiếp hợp với URI dành cho giao thức %s" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "Không hỗ trợ lược đồ URI “%s”" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "LỖI: từ phần tử %s: %s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"Thông tin gỡ lỗi thêm:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "liên kết không có nguồn [sink=%s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "liên kết không có sink [nguồn=%s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "không có thuộc tính “%s” trong phần tử “%s”" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "không thể đặt thuộc tính “%s” trong phần tử “%s” thành “%s”" + +msgid "Delayed linking failed." +msgstr "Gặp lỗi khi liên kết trễ." + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "không thể liên kết %s đến %s, %s không thể xử lý caps %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" +"không thể liên kết %s đến %s, mà cũng không có phần tử nào xó thể xử lý caps " +"%s" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "không thể liên kết %s đến %s với caps %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "không thể liên kết %s đến %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "không có phần tử “%s”" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "gặp tham chiếu không cần \"%s\" nên bỏ qua" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "gặp tham chiếu đệm không cần \"%s\" nên bỏ qua" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "không thể phân tách caps “%s”" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "" +"không có phần tử quản lý việc phân phối dữ liệu vào đệm khác nhau, cho địa " +"điểm “%s”" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "không có phần tử nguồn cho URI “%s”" + +msgid "syntax error" +msgstr "lỗi cú pháp" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "không cho phép nhị phân trống được ghi rõ “%s”" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "không có nhị phân “%s”, đang giải nén các phần tử" + +msgid "empty pipeline not allowed" +msgstr "không cho phép đường ống trống" + +msgid "A lot of buffers are being dropped." +msgstr "Nhiều bộ đệm bị bỏ." + +msgid "Internal data flow problem." +msgstr "Vấn đề luồng dữ liệu nội bộ." + +msgid "Internal data flow error." +msgstr "Lỗi luồng dữ liệu nội bộ." + +msgid "Internal clock error." +msgstr "Lỗi đồng hồ nội bộ." + +msgid "Failed to map buffer." +msgstr "Gặp lỗi khi ánh xạ bộ nhớ đệm." + +msgid "Filter caps" +msgstr "Lọc tối đa" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"Hạn chế các khả năng có thể cho phép (NULL [vô giá trị] cho phép tất cả). " +"Đặt thuộc tính này thì chấp nhận tham chiếu đến đối tượng GstCaps đã cung " +"cấp." + +msgid "Caps Change Mode" +msgstr "Thay đổi chế độ Caps" + +msgid "Filter caps change behaviour" +msgstr "Bộ lọc caps thay đổi cách ứng xử" + +msgid "No Temp directory specified." +msgstr "Chưa xác định thư mục tạm thời." + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "Không thể tạo tập tin tạm thời “%s”." + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "Không thể mở tập tin “%s” để đọc." + +msgid "Error while writing to download file." +msgstr "Gặp lỗi khi ghi vào tập tin tải về." + +msgid "No file name specified for writing." +msgstr "Chưa ghi rõ tên tập tin để ghi vào." + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "Không thể mở tập tin “%s” để ghi." + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "Gặp lỗi khi đóng tập tin “%s”." + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "Gặp lỗi khi di chuyển vị trí đọc trong tập tin “%s”." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Gặp lỗi khi ghi vào tập tin “%s”." + +msgid "No file name specified for reading." +msgstr "Chưa ghi rõ tên tập tin để đọc." + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "Không thể lấy thông tin về “%s”." + +#, c-format +msgid "\"%s\" is a directory." +msgstr "“%s” là thư mục." + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "Tập tin “%s” là ổ cắm mạng." + +msgid "Failed after iterations as requested." +msgstr "Lỗi sau số lần lặp lại được chọn." + +msgid "caps" +msgstr "khả năng" + +msgid "detected capabilities in stream" +msgstr "đã phát hiện khả năng trong luồng" + +msgid "minimum" +msgstr "tối thiểu" + +msgid "force caps" +msgstr "buộc khả năng" + +msgid "force caps without doing a typefind" +msgstr "buộc các khả năng mà không tìm kiểu" + +msgid "Stream doesn't contain enough data." +msgstr "Luồng không chứa đủ dữ liệu." + +msgid "Stream contains no data." +msgstr "Luồng không chứa dữ liệu." + +msgid "Implemented Interfaces:\n" +msgstr "Giao diện đã thực hiện:\n" + +msgid "readable" +msgstr "được đọc" + +msgid "writable" +msgstr "được ghi" + +msgid "deprecated" +msgstr "đã lạc hậu" + +msgid "controllable" +msgstr "điều khiển được" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "có thể thay đổi được trong trạng thái NULL, READY, PAUSED hay PLAYING" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "chỉ có thể thay đổi trong trạng thái NULL, READY hay PAUSED" + +msgid "changeable only in NULL or READY state" +msgstr "chỉ có thể thay đổi trong trạng thái NULL hay READY" + +msgid "Blacklisted files:" +msgstr "Tập tin bị cấm:" + +msgid "Total count: " +msgstr "Số lượng tổng cộng: " + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d tập tin bị cấm" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d phần bổ sung" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d mục tin bị cấm" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d tính năng" + +msgid "Print all elements" +msgstr "In ra mọi phần tử" + +msgid "Print list of blacklisted files" +msgstr "In danh sách các tập tin bị cấm" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"In ra danh sách cho máy phân tích được chứa các tính năng của phần bổ sung " +"đã ghi rõ hoặc mọi phần bổ sung.\n" +" Có ích khi dùng cơ chế tự động bên " +"ngoài mà cài đặt phần bổ sung." + +msgid "List the plugin contents" +msgstr "Liệt kê nội dung phần bổ sung" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"Một danh sách các kiểu của phần tử được ngăn cách bằng dấu xổ chéo (“/”) " +"(thường được gọi là klass) để liệt kê. (không được đăng ký)" + +msgid "Check if the specified element or plugin exists" +msgstr "Kiểm tra xem một phần tử hay phần bổ xung đã cho có tồn tại hay không" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "" +"Kiểm tra xem một phần tử hay phần bổ xung đã cho có tồn tại hay không, đồng " +"thời cũng kiểm tra cả phiên bản tối thiểu có thể hoạt động được" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "In ra các lược đồ URI được hỗ trợ, với những phần tử thực hiện chúng." + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "Không thể nạp tập tin phần bổ sung: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "Không có phần tử hay phần bổ sung như vậy “%s”\n" + +msgid "Index statistics" +msgstr "Thống kê chỉ mục" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "Nhận được thông điệp số %u từ phần tử “%s” (%s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "Nhận được thông điệp số %u từ đệm “%s:%s” (%s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "Nhận được thông điệp số %u từ đối tượng “%s” (%s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "Nhận được thông điệp số %u (%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "Mới nhận kết thúc luồng (EOS) từ phần tử “%s”.\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "THẺ ĐÃ TÌM : được tìm bởi phần tử “%s”.\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "THẺ ĐÃ TÌM : được tìm bởi đệm “%s:%s”.\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "THẺ ĐÃ TÌM : được tìm bởi đối tượng “%s”.\n" + +msgid "FOUND TAG\n" +msgstr "THẺ ĐÃ TÌM\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "TOC ĐÃ TÌM : được tìm bởi phần tử \"%s\".\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "TOC ĐÃ TÌM : được tìm bởi đối tượng \"%s\".\n" + +msgid "FOUND TOC\n" +msgstr "TOC TÌM THẤY\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"THÔNG TIN:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "CẢNH BÁO: từ phần tử %s: %s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "Cuộn sẵn, đợi chuyển hoán đệm xong…\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "Cuộn sẵn, đợi tiến trình hoàn tất…\n" + +msgid "buffering..." +msgstr "đang chuyển hoán đệm…" + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "Hoàn tất chuyển hoán đệm nên đặt đường ống thành ĐANG PHÁT …\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "Đang chuyển hoán đệm nên đặt đường ống thành BỊ TẠM DỪNG …\n" + +msgid "Redistribute latency...\n" +msgstr "Phân phối lại độ trễ…\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "Đang đặt tình trạng thành %s như yêu cầu bởi %s….\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "Ngắt: đang ngừng chạy đường ống …\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "Tiến trình: (%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "Thiếu phần tử: %s\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "Đã nhận nội dung từ phần tử “%s”: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "Xuất các thẻ (cũng được biết là siêu dữ liệu)" + +msgid "Output TOC (chapters and editions)" +msgstr "Xuất TOC (các chương và phiên bản)" + +msgid "Output status information and property notifications" +msgstr "Xuất thông tin trạng thái và thông báo tài sản" + +msgid "Do not print any progress information" +msgstr "Không in ra thông tin nào về tiến hành" + +msgid "Output messages" +msgstr "Thông điệp xuất" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" +"Đừng xuất thông tinh trạng thái cho thuộc tính đã cho nếu bật kết xuất chi " +"tiết (có thể sử dụng nhiều lần)" + +msgid "PROPERTY-NAME" +msgstr "TÊN-THUỘC-TÍNH" + +msgid "Do not install a fault handler" +msgstr "Không cài đặt bộ quản lý lỗi" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "Ép buộc kết thúc luồng trên các nguồn trước khi đóng đường ống" + +msgid "Gather and print index statistics" +msgstr "Tập hợp lại và in ra thống kê chỉ mục" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "LỖI: không thể xây dựng đường ống: %s.\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "LỖI: không thể xây dựng đường ống.\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "CẢNH BÁO: đường ống có lỗi: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "LỖI: không tìm thấy phần tử “đường ống” (pipeline).\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "Đang đặt đường ống thành BỊ TẠM DỪNG …\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "LỖI: đường ống không tạm dừng được.\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Đường ống đang sống và không cần TIỀN CUỘN …\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Đường ống ĐANG TIỀN CUỘN …\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "LỖI: đường ống không tiền cuộn được.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Đường ống ĐÃ TIỀN CUỘN …\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "Đang đặt đường ống thành ĐANG PHÁT …\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "LỖI: đường ống không phát được.\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "" +"Kết thúc luồng khi tắt phần mềm vẫn còn hoạt động thì đang ép buộc kết thúc " +"luồng trên đường ống\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "EOS khi tắt máy được bật -- chờ sau Lỗi EOS\n" + +msgid "Waiting for EOS...\n" +msgstr "Đang đợi kết thúc luồng…\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "Nhận được tín hiệu kết thúc luồng: đang ngừng chạy đường ống …\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "Ngắt trong khi chờ EOS - đang dừng đường ống lại…\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "Gặp lỗi trong khi đợi kết thúc luồng\n" + +msgid "Execution ended after %" +msgstr "Thực hiện xong sau %" + +msgid "Setting pipeline to READY ...\n" +msgstr "Đang đặt đường ống thành SẴN_SÀNG …\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "Đang đặt đường ống thành VÔ_GIÁ_TRỊ …\n" + +msgid "Freeing pipeline ...\n" +msgstr "Đang giải phóng đường ống …\n" + +#~ msgid "bin" +#~ msgstr "nhị phân" + +#~ msgid "Internal data stream error." +#~ msgstr "Lỗi luồng dữ liệu nội bộ." + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "Không xuất thông tin trạng thái KIỂU" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "KIỂU1,KIỂU2,…" + +#~ msgid "link without source element" +#~ msgstr "liên kết không có phần tử nguồn" + +#~ msgid "link without sink element" +#~ msgstr "" +#~ "liên kết không có phần tử quản lý việc phân phối dữ liệu vào đệm khác nhau" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "không có phần tử đến đó cần liên kết URI “%s”" + +#~ msgid "maximum" +#~ msgstr "tối đa" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "" +#~ "Cách sử dụng: gst-xmllaunch [ yếu_tố.tài_sản=giá_trị …]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "LỖI: lỗi phân tách tập tin xml “%s”.\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "LỖI: không có phần tử đường ống cấp đầu trong tập tin “%s”.\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "CẢNH BÁO: hiện thời hỗ trợ chỉ một phần tử cấp đầu.\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "LỖI: không thể phân tách đối số dòng lệnh %d: %s.\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "CẢNH BÁO: không tìm thấy phần tử tên “%s”.\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "Lưu đường ống dạng XML vào TẬP_TIN rồi thoát" + +#~ msgid "FILE" +#~ msgstr "TẬP_TIN" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "Đừng cài đặt bộ quản lý tín hiệu cho SIGUSR1 và SIGUSR2" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "In ra vết cấp phát (nếu được bật khi biên dich)" diff --git a/po/zh_CN.gmo b/po/zh_CN.gmo new file mode 100644 index 0000000..7b799cf Binary files /dev/null and b/po/zh_CN.gmo differ diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 0000000..d9e6b12 --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,1364 @@ +# Chinese (simplified) translation about gstreamer. +# This file is put in the public domain. +# Funda Wang , 2005. +# Ji ZhengYu , 2008, 2009. +# Tianze Wang , 2015. +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.12.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2017-05-05 22:53+0800\n" +"Last-Translator: Tianze Wang \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" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 2.0.1\n" + +msgid "Print the GStreamer version" +msgstr "打印 GStreamer 版本" + +msgid "Make all warnings fatal" +msgstr "将所有的警告也当作严重问题" + +msgid "Print available debug categories and exit" +msgstr "打印可用的调试类别并退出" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "默认调试级别,从 1(仅有错误)到 9(所有内容),0代表无输出" + +msgid "LEVEL" +msgstr "级别" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"逗号分隔的“类别名称:级别”列表用来为每个类别设置指定的调试级别。如:" +"GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "列表" + +msgid "Disable colored debugging output" +msgstr "禁止彩色的调试信息输出" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "改变调试日志的颜色模式。可能的模式有:off、on、disable、auto和unix" + +msgid "Disable debugging" +msgstr "禁止调试" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "开启详细的插件载入分析" + +msgid "Colon-separated paths containing plugins" +msgstr "冒号分隔的包含插件的路径" + +msgid "PATHS" +msgstr "路径" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"逗号分隔的预载入的插件列表,而且此列表被保存于环境变量 GST_PLUGIN_PATH 中" + +msgid "PLUGINS" +msgstr "插件" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "禁止跟踪装入插件时的段严重错误" + +msgid "Disable updating the registry" +msgstr "禁止更新寄存器" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "扫描寄存器时禁止启动帮助进程" + +msgid "GStreamer Options" +msgstr "GStreamer 选项" + +msgid "Show GStreamer Options" +msgstr "显示 GStreamer 选项" + +msgid "Unknown option" +msgstr "未知选项" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer 遇到了常规核心库错误。" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "GStreamer 开发者未对此错误指派错误代码。" + +msgid "Internal GStreamer error: code not implemented." +msgstr "GStreamer 内部错误:代码未实现。" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"Gstreamer 错误:改变状态时失败,并且一些组件无法提供有关错误原因的信息。" + +msgid "Internal GStreamer error: pad problem." +msgstr "GStreamer 内部错误: 填充问题。" + +msgid "Internal GStreamer error: thread problem." +msgstr "GStreamer 内部错误:线程问题。" + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer 错误: 协商问题。" + +msgid "Internal GStreamer error: event problem." +msgstr "GStreamer 内部错误:事件问题。" + +msgid "Internal GStreamer error: seek problem." +msgstr "GStreamer 内部错误:搜索问题。" + +msgid "Internal GStreamer error: caps problem." +msgstr "GStreamer 内部错误: 分析器问题。" + +msgid "Internal GStreamer error: tag problem." +msgstr "GStreamer 内部错误:标签问题。" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "您的 GStreamer 安装缺少插件。" + +msgid "GStreamer error: clock problem." +msgstr "GStreamer 错误:时钟错误。" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "此程序正尝试使用已被禁用的 GStreamer 功能。" + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer 遇到了常规支持库错误。" + +msgid "Could not initialize supporting library." +msgstr "无法初始化支持库。" + +msgid "Could not close supporting library." +msgstr "无法关闭支持库。" + +msgid "Could not configure supporting library." +msgstr "无法配置支持库。" + +msgid "Encoding error." +msgstr "编码错误。" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer 遇到了常规资源错误。" + +msgid "Resource not found." +msgstr "资源未找到。" + +msgid "Resource busy or not available." +msgstr "资源忙或不可用。" + +msgid "Could not open resource for reading." +msgstr "无法打开资源读取。" + +msgid "Could not open resource for writing." +msgstr "无法打开资源写入。" + +msgid "Could not open resource for reading and writing." +msgstr "无法打开资源读取和写入。" + +msgid "Could not close resource." +msgstr "无法关闭资源。" + +msgid "Could not read from resource." +msgstr "无法从资源阅读。" + +msgid "Could not write to resource." +msgstr "无法写入资源。" + +msgid "Could not perform seek on resource." +msgstr "无法在资源上执行搜索。" + +msgid "Could not synchronize on resource." +msgstr "无法在资源上同步。" + +msgid "Could not get/set settings from/on resource." +msgstr "无法从资源获得设置或在资源上设定设置。" + +msgid "No space left on the resource." +msgstr "资源上无剩余空间。" + +msgid "Not authorized to access resource." +msgstr "无权访问资源。" + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer 遇到了常规流错误。" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "组件未实现对此流的处理。请提交错误报告。" + +msgid "Could not determine type of stream." +msgstr "无法确定流类型。" + +msgid "The stream is of a different type than handled by this element." +msgstr "此流的类型与此组件可处理的类型不符。" + +msgid "There is no codec present that can handle the stream's type." +msgstr "没有可处理此流类型的编解码器。" + +msgid "Could not decode stream." +msgstr "无法解码流。" + +msgid "Could not encode stream." +msgstr "无法编码流。" + +msgid "Could not demultiplex stream." +msgstr "无法解码多工传送的流。" + +msgid "Could not multiplex stream." +msgstr "无法编码多工传送的流。" + +msgid "The stream is in the wrong format." +msgstr "此流的格式错误。" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "此为加密流且不支持解密。" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "此为加密流,而且由于未提供合适的密钥因此无法解密。" + +#, c-format +msgid "No error message for domain %s." +msgstr "域 %s 无错误信息。" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "域 %s 和代码 %d 中无标准错误信息。" + +msgid "Selected clock cannot be used in pipeline." +msgstr "选中的时钟序列无法用在管道中。" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "寄存器缓存写入 %s 时出错: %s" + +msgid "title" +msgstr "标题" + +msgid "commonly used title" +msgstr "公用标题" + +msgid "title sortname" +msgstr "排序后的标题名" + +msgid "commonly used title for sorting purposes" +msgstr "用于排序的公用标题" + +msgid "artist" +msgstr "艺术家" + +msgid "person(s) responsible for the recording" +msgstr "负责录制的个人" + +msgid "artist sortname" +msgstr "排序后的艺术家" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "用于排序的负责录制的人名" + +msgid "album" +msgstr "专辑" + +msgid "album containing this data" +msgstr "包含此数据的专辑" + +msgid "album sortname" +msgstr "排序后的专辑名" + +msgid "album containing this data for sorting purposes" +msgstr "用于排序的专辑名" + +msgid "album artist" +msgstr "艺术家列表" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "用于显示的整张专辑的艺术家" + +msgid "album artist sortname" +msgstr "排序后的艺术家名" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "用于排序的整张专辑的艺术家名" + +msgid "date" +msgstr "日期" + +msgid "date the data was created (as a GDate structure)" +msgstr "创建数据的日期(为 GDate 结构)" + +msgid "datetime" +msgstr "日期和时间" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "创建数据的日期和时间为 GDate 结构)" + +msgid "genre" +msgstr "流派" + +msgid "genre this data belongs to" +msgstr "此数据所属的流派" + +msgid "comment" +msgstr "注释" + +msgid "free text commenting the data" +msgstr "注释数据的任意文本" + +msgid "extended comment" +msgstr "更多注释" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "以“关键词=值或 key[en]=注释”这种形式注释数据的任意文本" + +msgid "track number" +msgstr "音轨编号" + +msgid "track number inside a collection" +msgstr "收藏集中的音轨编号" + +msgid "track count" +msgstr "音轨数" + +msgid "count of tracks inside collection this track belongs to" +msgstr "此音轨所属的收藏集中的音轨数" + +msgid "disc number" +msgstr "碟片编号" + +msgid "disc number inside a collection" +msgstr "收藏集中的碟片编号" + +msgid "disc count" +msgstr "碟片数" + +msgid "count of discs inside collection this disc belongs to" +msgstr "此碟所属的收藏集中的碟片数" + +msgid "location" +msgstr "位置" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "媒体来源作为 URI 地址(原始文件或流所在的位置)" + +msgid "homepage" +msgstr "主页" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "此媒体的主页(艺术家或电影等)" + +msgid "description" +msgstr "描述" + +msgid "short text describing the content of the data" +msgstr "描述数据内容的简要文本" + +msgid "version" +msgstr "版本" + +msgid "version of this data" +msgstr "此数据的版本" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "International Standard Recording Code - see http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "组织" + +msgid "copyright" +msgstr "版权" + +msgid "copyright notice of the data" +msgstr "数据的版权警告" + +msgid "copyright uri" +msgstr "版权 uri" + +msgid "URI to the copyright notice of the data" +msgstr "数据的版权警告 URI" + +msgid "encoded by" +msgstr "编码者为" + +msgid "name of the encoding person or organization" +msgstr "进行编码的人或组织" + +msgid "contact" +msgstr "联系人" + +msgid "contact information" +msgstr "联系人信息" + +msgid "license" +msgstr "许可证" + +msgid "license of data" +msgstr "数据许可证" + +msgid "license uri" +msgstr "许可证 uri" + +msgid "URI to the license of the data" +msgstr "数据许可证的 URI" + +msgid "performer" +msgstr "演奏者" + +msgid "person(s) performing" +msgstr "演奏者" + +msgid "composer" +msgstr "作曲人" + +msgid "person(s) who composed the recording" +msgstr "负责录制的人" + +msgid "conductor" +msgstr "指挥" + +msgid "conductor/performer refinement" +msgstr "现场指挥/演奏者" + +msgid "duration" +msgstr "时期" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "GStreamer 时间单位的长度(纳秒)" + +msgid "codec" +msgstr "编码" + +msgid "codec the data is stored in" +msgstr "数据以...编码存储" + +msgid "video codec" +msgstr "视频编码" + +msgid "codec the video data is stored in" +msgstr "视频数据以...编码存储" + +msgid "audio codec" +msgstr "音频编码" + +msgid "codec the audio data is stored in" +msgstr "音频数据以...编码存储" + +msgid "subtitle codec" +msgstr "字幕编码" + +msgid "codec the subtitle data is stored in" +msgstr "字幕编码数据保存在" + +msgid "container format" +msgstr "容器格式" + +msgid "container format the data is stored in" +msgstr "用于储存数据的容器格式" + +msgid "bitrate" +msgstr "比特率" + +msgid "exact or average bitrate in bits/s" +msgstr "精确或平均比特率(比特/秒)" + +msgid "nominal bitrate" +msgstr "名义比特率" + +msgid "nominal bitrate in bits/s" +msgstr "名义比特率(比特/秒)" + +msgid "minimum bitrate" +msgstr "最小比特率" + +msgid "minimum bitrate in bits/s" +msgstr "最小比特率(比特/秒)" + +msgid "maximum bitrate" +msgstr "最大比特率" + +msgid "maximum bitrate in bits/s" +msgstr "最大比特率(比特/秒)" + +msgid "encoder" +msgstr "编码器" + +msgid "encoder used to encode this stream" +msgstr "用于编码此流的编码器" + +msgid "encoder version" +msgstr "编码器版本" + +msgid "version of the encoder used to encode this stream" +msgstr "用于编码此流的编码器版本" + +msgid "serial" +msgstr "序列号" + +msgid "serial number of track" +msgstr "音轨的序列号" + +msgid "replaygain track gain" +msgstr "重放增益音轨增益" + +msgid "track gain in db" +msgstr "音轨增益(db)" + +msgid "replaygain track peak" +msgstr "重放增益音轨峰值" + +msgid "peak of the track" +msgstr "音轨峰值" + +msgid "replaygain album gain" +msgstr "重放增益专辑增益" + +msgid "album gain in db" +msgstr "专辑增益(db)" + +msgid "replaygain album peak" +msgstr "回放增益专辑峰值" + +msgid "peak of the album" +msgstr "专辑峰值" + +msgid "replaygain reference level" +msgstr "回放增益参考级别" + +msgid "reference level of track and album gain values" +msgstr "音轨和专辑增益的参考级别值" + +msgid "language code" +msgstr "语言代码" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "此流的语言代码(依照 ISO-639-1 或 ISO-639-2 规范)" + +msgid "language name" +msgstr "语言名称" + +msgid "freeform name of the language this stream is in" +msgstr "此流的语言名称(freeform格式)" + +msgid "image" +msgstr "图像" + +msgid "image related to this stream" +msgstr "有关此流的图像" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "上一图像" + +msgid "preview image related to this stream" +msgstr "有关此流的上一图像" + +msgid "attachment" +msgstr "附加信息" + +msgid "file attached to this stream" +msgstr "有关此流的文件" + +msgid "beats per minute" +msgstr "每分钟节拍数" + +msgid "number of beats per minute in audio" +msgstr "音频中的每分钟节拍数" + +msgid "keywords" +msgstr "简要文本" + +msgid "comma separated keywords describing the content" +msgstr "逗号分隔的描述数据内容的简要文本" + +msgid "geo location name" +msgstr "地理位置名称" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "有关此媒体在何处录制或生产的可读信息" + +msgid "geo location latitude" +msgstr "地理纬度" + +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "" +"根据 WGS84(赤道为 0 度,南半球为负值)标准确定的地理纬度值(有关此媒体在哪里" +"录制或产生的)" + +msgid "geo location longitude" +msgstr "地理经度" + +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "" +"根据 WGS84(英国格林威治本初子午线上为 0 度,西半球为负值)标准确定的地理经度" +"值(有关此媒体在哪里录制或产生的)" + +msgid "geo location elevation" +msgstr "地理海拔" + +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "" +"根据 WGS84(平均海平面为 0 米)标准确定的地理海拔高度(有关此媒体在哪里录制或" +"产生的)" + +msgid "geo location country" +msgstr "地理位置(国家)" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "媒体录制或制作地所在国家(的英语名)" + +msgid "geo location city" +msgstr "地理位置(城市)" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "媒体录制或制作地所在城市(的英语名)" + +msgid "geo location sublocation" +msgstr "地理区域(区)" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "媒体录制或制作地所在城市的区(的英语名),如“the neighborhood”" + +msgid "geo location horizontal error" +msgstr "地理位置(水平误差)" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "预期的水平定位测量误差(单位为米)" + +msgid "geo location movement speed" +msgstr "地理位置(移动速度)" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "进行捕捉时捕捉设备的移动速度,单位:米每秒" + +msgid "geo location movement direction" +msgstr "地理位置(移动方向)" + +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "" +"进行捕捉时捕捉设备的移动方向。它由角度的浮点值表示,0为地理北极,且按顺时针方" +"向增大" + +msgid "geo location capture direction" +msgstr "地理位置(捕获方向)" + +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "" +"进行捕捉时捕捉设备的朝向。它由角度的浮点值表示,0为地理北极,且按顺时针方向增" +"大" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "显示名称" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "tv/podcast/series 的名称,此名称代表媒体来自何处" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "显示排序名" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "tv/podcast/series 名称代表此媒体来自何处(排名显示)" + +msgid "episode number" +msgstr "年代" + +msgid "The episode number in the season the media is part of" +msgstr "媒体是一季中的第几场景" + +msgid "season number" +msgstr "季号" + +msgid "The season number of the show the media is part of" +msgstr "媒体是第几季" + +msgid "lyrics" +msgstr "歌词" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "媒体歌词,通常用于歌曲" + +msgid "composer sortname" +msgstr "排序后的作曲者" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "用于排序的负责制作的人名" + +msgid "grouping" +msgstr "媒体组" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"媒体组横跨多个音轨,就好像是一场音乐会的不同时段。这个概念范围比音轨高,但小" +"于专辑" + +msgid "user rating" +msgstr "用户评级" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "由用户提供的评级。评级越高,意味着有越多的用户喜欢这一媒体" + +msgid "device manufacturer" +msgstr "设备商" + +msgid "Manufacturer of the device used to create this media" +msgstr "用于创建此媒体的设备的生产厂家" + +msgid "device model" +msgstr "设备模式" + +msgid "Model of the device used to create this media" +msgstr "用于创建此媒体的设备的模式" + +msgid "application name" +msgstr "应用程序名称" + +msgid "Application used to create the media" +msgstr "用于创建此媒体的应用程序" + +msgid "application data" +msgstr "应用程序数据" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "被序列化后写入到媒体中的应用程序数据" + +msgid "image orientation" +msgstr "图像方向" + +msgid "How the image should be rotated or flipped before display" +msgstr "指示应如何旋转或翻转该图像后再显示它" + +msgid "publisher" +msgstr "出版者" + +msgid "Name of the label or publisher" +msgstr "标签或出版商的名称" + +msgid "interpreted-by" +msgstr "解说者为" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "混音(或类似解说)作者的信息" + +msgid "midi-base-note" +msgstr "基于midi的注解" + +msgid "Midi note number of the audio track." +msgstr "音频轨的midi注解编号" + +msgid "private-data" +msgstr "私有数据" + +msgid "Private data" +msgstr "专有用途的数据" + +msgid ", " +msgstr ", " + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "未找到用于 %s 协议的URI处理器" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "不支持URI方案“%s”" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "错误:来自组件 %s:%s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"额外的调试信息:\n" +"%s\n" + +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "链接没有源 [汇为 %s@%p]" + +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "链接没有汇 [源为 %s@%p]" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "组件“%2$s”中找不到属性“%1$s”" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "无法设置组件“%2$s”中的属性“%1$s”为“%3$s”" + +msgid "Delayed linking failed." +msgstr "延迟链接失败。" + +#, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "无法将 %s 链接到 %s,%s 无法处理分析器 %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "无法将 %s 链接到 %s,没有可以处理分析器 %s 的元素" + +#, c-format +msgid "could not link %s to %s with caps %s" +msgstr "无法将带有分析器 %3$s 的 %1$s 链接到 %2$s" + +#, c-format +msgid "could not link %s to %s" +msgstr "无法将 %s 链接到 %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "无组件“%s”" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "未预期的引用“%s” - 忽略" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "未预期的填充引用“%s” - 忽略" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "无法解析分析器“%s”" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "URI“%s”上无消音组件" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "URI“%s”无源组件" + +msgid "syntax error" +msgstr "语法错误" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "不允许指定空储仓“%s”" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "找不到用于解包组件的储仓“%s”" + +msgid "empty pipeline not allowed" +msgstr "不允许空管道" + +msgid "A lot of buffers are being dropped." +msgstr "许多缓冲被丢弃。" + +msgid "Internal data flow problem." +msgstr "内部数据流问题。" + +msgid "Internal data flow error." +msgstr "内部数据流错误。" + +msgid "Internal clock error." +msgstr "内部时钟错误。" + +msgid "Failed to map buffer." +msgstr "映射缓冲失败。" + +msgid "Filter caps" +msgstr "过滤分析器" + +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "" +"限制所允许的功能 (NULL 表示无限制)。此属性可以为所提供的 GstCaps 对象设置一个" +"关联应用。" + +msgid "Caps Change Mode" +msgstr "分析器变更模式" + +msgid "Filter caps change behaviour" +msgstr "过滤分析器变更行为" + +msgid "No Temp directory specified." +msgstr "未指定临时目录。" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "无法创建临时文件“%s”。" + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "无法打开文件“%s”读取。" + +msgid "Error while writing to download file." +msgstr "写入下载文件时出错。" + +msgid "No file name specified for writing." +msgstr "未指定写入的文件名。" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "无法打开文件“%s”写入。" + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "关闭文件“%s”出错。" + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "在文件“%s”搜寻时出错。" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "写入文件“%s”时出错。" + +msgid "No file name specified for reading." +msgstr "未指定读取的文件名。" + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "无法在“%s”上获得信息。" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "“%s”不是目录。" + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "文件“%s”是套接字。" + +msgid "Failed after iterations as requested." +msgstr "在完成所要求的迭代操作后出错。" + +msgid "caps" +msgstr "分析器" + +msgid "detected capabilities in stream" +msgstr "流中探测到的信息" + +msgid "minimum" +msgstr "最小" + +msgid "force caps" +msgstr "强制分析" + +msgid "force caps without doing a typefind" +msgstr "不做类型查找的强制分析" + +msgid "Stream doesn't contain enough data." +msgstr "流中没有足够数据。" + +msgid "Stream contains no data." +msgstr "流中不含数据" + +msgid "Implemented Interfaces:\n" +msgstr "实现的接口:\n" + +msgid "readable" +msgstr "可读" + +msgid "writable" +msgstr "可写" + +msgid "deprecated" +msgstr "已废弃" + +msgid "controllable" +msgstr "可控制" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "可以在NULL、READY、PAUSED或PLAYING状态下改变" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "只能在NULL、READY或PAUSED状态下改变" + +msgid "changeable only in NULL or READY state" +msgstr "只能在NULL、或READY状态下改变" + +msgid "Blacklisted files:" +msgstr "文件黑名单:" + +msgid "Total count: " +msgstr "总数:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d 个黑名单文件" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d 个插件" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d 个黑名单记录" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d 个特性" + +msgid "Print all elements" +msgstr "打印全部组件" + +msgid "Print list of blacklisted files" +msgstr "显示黑名单文件列表" + +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"打印机器可解析的指定(或所有)插件提供的特性列表。\n" +" 可以用于与外部自动插件安装机制的连接" + +msgid "List the plugin contents" +msgstr "列出插件信息" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" +"斜杠(“/”)用于将一系列元素类型(也叫做 klass)分割成(未排序的)类型列表。" + +msgid "Check if the specified element or plugin exists" +msgstr "检查指定的组件或插件是否存在" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "当检查组件或插件是否存在时,也检测它们的版本是否大于等于指定版本" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "打印所支持的 URI 样式及它们的关联组件" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "无法载入插件文件: %s\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "没有那样的组件或插件‘%s’\n" + +msgid "Index statistics" +msgstr "索引统计" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "从组件“%2$s”获得消息 #%1$u(%3$s): " + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "从填充“%2$s:%3$s”获得消息 #%1$u(%4$s): " + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "从对象“%2$s”获得消息 #%1$u(%3$s): " + +#, c-format +msgid "Got message #%u (%s): " +msgstr "获得消息 #%u(%s): " + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "收到来自组件“%s”的 EOS 信号。\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "找到标识 :由组件“%s”找到。\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "找到标识 :由填充“%s:%s”找到。\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "找到标识 :由对象“%s”找到。\n" + +msgid "FOUND TAG\n" +msgstr "找到标识\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "找到TOC :由组件“%s”找到。\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "找到TOC :由对象“%s”找到。\n" + +msgid "FOUND TOC\n" +msgstr "找到TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"信息:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "警告:来自组件 %s:%s\n" + +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "已加载预告片,等待缓冲完成...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "已加载预告片,等待处理完成...\n" + +msgid "buffering..." +msgstr "正在缓冲..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "缓冲完成,设置播放管道 ...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "正在缓冲,设置暂停管道 ...\n" + +msgid "Redistribute latency...\n" +msgstr "重新分配延迟时间...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "%2$s 发起请求时状态设置为 %1$s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "中断: 中止管道 ...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "进度:(%s)%s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "缺少组件:“%s”\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "从组件“%s”获取上下文:%s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "输出标识(也可认为是元数据)" + +msgid "Output TOC (chapters and editions)" +msgstr "输出TOC(章节和版本)" + +msgid "Output status information and property notifications" +msgstr "输出状态信息和属性通知" + +msgid "Do not print any progress information" +msgstr "不打印任何进度信息" + +msgid "Output messages" +msgstr "输出信息" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "如果启用了详细输出模式,不输出指定属性的状态信息(可以多次使用)" + +msgid "PROPERTY-NAME" +msgstr "属性名" + +msgid "Do not install a fault handler" +msgstr "不安装错误的处理程序" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "关闭管道前强制对源发出 EOS 信号" + +msgid "Gather and print index statistics" +msgstr "收集并显示索引统计" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "错误: 无法创建管道: %s。\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "错误: 无法创建管道。\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "警告: 错误管道: %s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "错误: 未找到‘管道’组件。\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "设置暂停管道 ...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "错误: 管道不想暂停。\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "管道正在使用且不需要 PREROLL ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "管道正在 PREROLLING ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "错误: 管道不需要 preroll.\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "管道被 PREROLLED ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "设置播放管道 ...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "错误: 管道不想播放。\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "允许关闭时发出 EOS 信号 —— 强制对管道发出 EOS 信号\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "允许关闭时发出 EOS 信号 —— 发生错误后等待EOS信号\n" + +msgid "Waiting for EOS...\n" +msgstr "等待 EOS 信号...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "收到 EOS 信号 - 中止管道 ...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "等待EOS信号时被中断 - 正在中止管道...\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "等待 EOS 信号时出现一个错误\n" + +msgid "Execution ended after %" +msgstr "在 % 后运行终止" + +msgid "Setting pipeline to READY ...\n" +msgstr "设置备用管道 ...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "设置 NULL 管道 ...\n" + +msgid "Freeing pipeline ...\n" +msgstr "释放管道资源 ...\n" + +#~ msgid "bin" +#~ msgstr "储仓" + +#~ msgid "Internal data stream error." +#~ msgstr "内部数据流错误。" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "不输出类型的状态信息" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "类型1,类型2,..." + +#~ msgid "link without source element" +#~ msgstr "不带源组件的链接" + +#~ msgid "link without sink element" +#~ msgstr "不带消音组件的链接" + +#~ msgid "no element to link URI \"%s\" to" +#~ msgstr "无组件让 URI“%s”来连接" + +#~ msgid "maximum" +#~ msgstr "最大" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "用法: gst-xmllaunch [ element.property=value ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "错误: xml 文件‘%s’解析失败。\n" + +#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n" +#~ msgstr "错误: 文件‘%s’中没有顶级管道组件。\n" + +#~ msgid "WARNING: only one toplevel element is supported at this time.\n" +#~ msgstr "警告: 此时仅支持一个一级组件。\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "错误: 无法解析命令行参数 %d: %s。\n" + +#~ msgid "WARNING: element named '%s' not found.\n" +#~ msgstr "警告: 组件名‘%s’未找到。\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "保存管道的 xml 描述符至文件并退出" + +#~ msgid "FILE" +#~ msgstr "文件" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "打印分配记录(如果在编译时开启的话)" + +#~ msgid "Error re-scanning registry %s: %s" +#~ msgstr "重新扫描寄存器 %s 时出错: %s" + +#~ msgid "Error re-scanning registry %s" +#~ msgstr "重新扫描寄存器 %s 时出错" + +#~ msgid "Internal GStreamer error: state change failed." +#~ msgstr "GStreamer 内部错误:状态更改失败。" + +#~ msgid "Error while writing to file descriptor \"%d\"." +#~ msgstr "写入文件描述符“%d”时出错。" + +#~ msgid "File descriptor \"%d\" is not valid." +#~ msgstr "文件描述符“%d”无效。" + +#~ msgid "FREEING pipeline ...\n" +#~ msgstr "正在释放管道 ...\n" + +#~ msgid "original location of file as a URI" +#~ msgstr "文件原始位置作为 URI 地址" + +#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2" +#~ msgstr "不设置 SIGUSR1 和 SIGUSR2 信号的处理器" diff --git a/po/zh_TW.gmo b/po/zh_TW.gmo new file mode 100644 index 0000000..1f59949 Binary files /dev/null and b/po/zh_TW.gmo differ diff --git a/po/zh_TW.po b/po/zh_TW.po new file mode 100644 index 0000000..3ce24fa --- /dev/null +++ b/po/zh_TW.po @@ -0,0 +1,1386 @@ +# traditional Chinese translation of gstreamer. +# This file is put in the public domain. +# Abel Cheung , 2005. +# Wen Liao , 2014 +# Terms sync-up: +# plugin: 外掛程式 +# log: 日誌 +# registry: 登錄資料 +# thread: 執行緒 +# seek: 跳播 (通常多媒體播放中seek不是字面上的搜尋,而是跳到媒體任意地方,因此 +# 使用搜尋,尋找並不夠精確) +# stream: 資料串流 +# multiplex: 多工串接 +# demultiplex: 解多工分接 +# key: 金鑰 +# replaygain: 回放增益,用在確保playlist內所有音軌不會音量不同 +# http://zh.wikipedia.org/zh-tw/%E5%9B%9E%E6%94%BE%E5%A2%9E%E7%9B%8A +# problem: 大部分翻成錯誤 +# reference: 參照(應該有更好的名詞) +# 保留原名: +# 1. GStreamer專用元件: element, pad, caps, clock, pipeline, bin, 某些link +# 2. 專有名詞: codec, container, beat, URI, URI scheme, TOC +# 3. 疑似專有名詞:domain +# 4. GStreamer內部狀態 +# 5. metadata +msgid "" +msgstr "" +"Project-Id-Version: gstreamer 1.3.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2018-05-17 13:17+0100\n" +"PO-Revision-Date: 2014-06-08 00:22+0800\n" +"Last-Translator: Wen Liao \n" +"Language-Team: Chinese (traditional) \n" +"Language: zh_TW\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" + +msgid "Print the GStreamer version" +msgstr "顯示 GStreamer 版本" + +msgid "Make all warnings fatal" +msgstr "將所有警告視為嚴重錯誤" + +msgid "Print available debug categories and exit" +msgstr "顯示可以偵錯的類別,並結束" + +msgid "" +"Default debug level from 1 (only error) to 9 (anything) or 0 for no output" +msgstr "" +"將預設偵錯等級設定為 1 (只顯示錯誤) 至 9 (任何訊息),或者用 0 表示不顯示訊息" + +msgid "LEVEL" +msgstr "" + +msgid "" +"Comma-separated list of category_name:level pairs to set specific levels for " +"the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3" +msgstr "" +"以逗號分隔列表中的內容,內容的格式為「分類:等級」,以此方式指定各個分類的等" +"級。例如:GST_AUTOPLUG:5,GST_ELEMENT_*:3" + +msgid "LIST" +msgstr "" + +msgid "Disable colored debugging output" +msgstr "偵錯結果不顯示顏色" + +msgid "" +"Changes coloring mode of the debug log. Possible modes: off, on, disable, " +"auto, unix" +msgstr "更改偵錯日誌配色模式,支援配色模式為:off, on, disable, auto, unix" + +msgid "Disable debugging" +msgstr "關閉偵錯功能" + +msgid "Enable verbose plugin loading diagnostics" +msgstr "載入外掛時顯示詳細訊息" + +msgid "Colon-separated paths containing plugins" +msgstr "以分號分隔的路徑中有包含外掛程式" + +msgid "PATHS" +msgstr "路徑" + +msgid "" +"Comma-separated list of plugins to preload in addition to the list stored in " +"environment variable GST_PLUGIN_PATH" +msgstr "" +"除了有輸入環境變數 GST_PLUGIN_PATH 的外掛程式之外,所有以逗號分隔的外掛程式清" +"單都會被預載" + +msgid "PLUGINS" +msgstr "外掛程式" + +msgid "Disable trapping of segmentation faults during plugin loading" +msgstr "載入外掛程式時不攔截程式區段碼錯誤" + +msgid "Disable updating the registry" +msgstr "停止更新登錄資料" + +msgid "Disable spawning a helper process while scanning the registry" +msgstr "掃描登錄資料時不產生協助處理資料的行程" + +msgid "GStreamer Options" +msgstr "GStreamer 選項" + +msgid "Show GStreamer Options" +msgstr "顯示 GStreamer 選項" + +msgid "Unknown option" +msgstr "未知的選項" + +msgid "GStreamer encountered a general core library error." +msgstr "GStreamer 主要函式庫發生一般性的錯誤。" + +msgid "" +"GStreamer developers were too lazy to assign an error code to this error." +msgstr "GStreamer 開發人員尚未定義這類錯誤的錯誤代碼。" + +msgid "Internal GStreamer error: code not implemented." +msgstr "GStreamer 內部錯誤:未實作的功能。" + +msgid "" +"GStreamer error: state change failed and some element failed to post a " +"proper error message with the reason for the failure." +msgstr "" +"GStreamer錯誤: 狀態切換失敗,同時部份element在該次失敗中無法顯示相關錯誤訊息" + +msgid "Internal GStreamer error: pad problem." +msgstr "GStreamer 內部錯誤:pad錯誤。" + +msgid "Internal GStreamer error: thread problem." +msgstr "GStreamer 內部錯誤:執行緒錯誤。" + +msgid "GStreamer error: negotiation problem." +msgstr "GStreamer 內部錯誤:溝通協定錯誤。" + +msgid "Internal GStreamer error: event problem." +msgstr "GStreamer 內部錯誤:事件錯誤。" + +msgid "Internal GStreamer error: seek problem." +msgstr "GStreamer 內部錯誤:跳播錯誤。" + +msgid "Internal GStreamer error: caps problem." +msgstr "GStreamer 內部錯誤:caps錯誤。" + +msgid "Internal GStreamer error: tag problem." +msgstr "GStreamer 內部錯誤:標籤錯誤。" + +msgid "Your GStreamer installation is missing a plug-in." +msgstr "您的GStreamer缺少外掛程式。" + +msgid "GStreamer error: clock problem." +msgstr "GStreamer 內部錯誤:時脈錯誤。" + +msgid "" +"This application is trying to use GStreamer functionality that has been " +"disabled." +msgstr "應用程式嘗試使用已被關閉的選項內的功能" + +msgid "GStreamer encountered a general supporting library error." +msgstr "GStreamer 輔助函式庫發生一般性的錯誤。" + +msgid "Could not initialize supporting library." +msgstr "無法初始化支援函式庫。" + +# (abel) close library? 該解釋清楚才是。 +msgid "Could not close supporting library." +msgstr "無法關閉支援函式庫。" + +msgid "Could not configure supporting library." +msgstr "無法設定支援函式庫組態。" + +msgid "Encoding error." +msgstr "編碼錯誤。" + +msgid "GStreamer encountered a general resource error." +msgstr "GStreamer 遭遇一般性的資源錯誤。" + +msgid "Resource not found." +msgstr "找不到資源。" + +msgid "Resource busy or not available." +msgstr "資源使用中,或者無法存取。" + +msgid "Could not open resource for reading." +msgstr "無法開啟讀取用的資源" + +msgid "Could not open resource for writing." +msgstr "無法開啟寫入用的資源。" + +msgid "Could not open resource for reading and writing." +msgstr "無法開啟讀取和寫入用的資源。" + +msgid "Could not close resource." +msgstr "無法關閉資源。" + +msgid "Could not read from resource." +msgstr "無法從資源中讀取資料。" + +msgid "Could not write to resource." +msgstr "無法寫入資料到資源內。" + +msgid "Could not perform seek on resource." +msgstr "該資源內無法跳播。" + +msgid "Could not synchronize on resource." +msgstr "無法和資源同步。" + +msgid "Could not get/set settings from/on resource." +msgstr "無法從資源取得或設定組態設定。" + +msgid "No space left on the resource." +msgstr "資源已經沒有剩餘空間。" + +msgid "Not authorized to access resource." +msgstr "未經授權無法存取資源。" + +msgid "GStreamer encountered a general stream error." +msgstr "GStreamer 遭遇一般性的資料串流錯誤。" + +msgid "Element doesn't implement handling of this stream. Please file a bug." +msgstr "Element 沒有實作處理該資料串流,請回報錯誤。" + +msgid "Could not determine type of stream." +msgstr "無法決定資料串流的類型。" + +msgid "The stream is of a different type than handled by this element." +msgstr "該資料串流和element能處理的型態不一致。" + +msgid "There is no codec present that can handle the stream's type." +msgstr "沒有能夠處理該資料串流的codec。" + +msgid "Could not decode stream." +msgstr "無法將資料串流進行解碼。" + +msgid "Could not encode stream." +msgstr "無法將資料串流進行編碼。" + +msgid "Could not demultiplex stream." +msgstr "無法將資料串流解多工分接。" + +msgid "Could not multiplex stream." +msgstr "無法將資料串流多工串接。" + +msgid "The stream is in the wrong format." +msgstr "資料串流格式錯誤。" + +msgid "The stream is encrypted and decryption is not supported." +msgstr "資料串流已加密,但是目前不支援解密。" + +msgid "" +"The stream is encrypted and can't be decrypted because no suitable key has " +"been supplied." +msgstr "資料串流已加密,但是沒有適當的金鑰因而無法解密。" + +# Wen, 怪怪的?Domain意義不明。 +#, c-format +msgid "No error message for domain %s." +msgstr "domain %s沒有可用的錯誤訊息。" + +#, c-format +msgid "No standard error message for domain %s and code %d." +msgstr "domain %s 以及代碼 %d沒有標準的錯誤訊息。" + +msgid "Selected clock cannot be used in pipeline." +msgstr "在pipeline中無法使用選擇的clock。" + +#, c-format +msgid "Error writing registry cache to %s: %s" +msgstr "寫入登錄資料快取到%s時發生錯誤:%s" + +msgid "title" +msgstr "標題" + +msgid "commonly used title" +msgstr "通用標題" + +msgid "title sortname" +msgstr "排序後的標題" + +msgid "commonly used title for sorting purposes" +msgstr "排序用的通用標題" + +msgid "artist" +msgstr "作者" + +msgid "person(s) responsible for the recording" +msgstr "錄製人" + +msgid "artist sortname" +msgstr "排序後的作者" + +msgid "person(s) responsible for the recording for sorting purposes" +msgstr "排序後的錄製人" + +msgid "album" +msgstr "專輯" + +msgid "album containing this data" +msgstr "這些樂曲所屬的專輯" + +msgid "album sortname" +msgstr "排序後的專輯" + +# 從gsttaglist.c猜測這個是前面訊息的詳細版本 +msgid "album containing this data for sorting purposes" +msgstr "排序後包含這些資料的專輯" + +msgid "album artist" +msgstr "專輯作者" + +msgid "The artist of the entire album, as it should be displayed" +msgstr "整張專輯的作者" + +msgid "album artist sortname" +msgstr "排序後的專輯作者" + +msgid "The artist of the entire album, as it should be sorted" +msgstr "排序後的整張專輯作者" + +msgid "date" +msgstr "日期" + +msgid "date the data was created (as a GDate structure)" +msgstr "媒體資料製作日期" + +msgid "datetime" +msgstr "日期時間" + +msgid "date and time the data was created (as a GstDateTime structure)" +msgstr "媒體資料製作日期" + +msgid "genre" +msgstr "媒體類型" + +msgid "genre this data belongs to" +msgstr "媒體類型" + +msgid "comment" +msgstr "註解" + +msgid "free text commenting the data" +msgstr "媒體註解的內容" + +msgid "extended comment" +msgstr "延伸註解" + +msgid "free text commenting the data in key=value or key[en]=comment form" +msgstr "使用關鍵字=值或是關鍵字[en]=註解格式表示媒體註解的內容" + +msgid "track number" +msgstr "音軌編號" + +msgid "track number inside a collection" +msgstr "蒐集資料內的音軌編號" + +msgid "track count" +msgstr "音軌總數" + +msgid "count of tracks inside collection this track belongs to" +msgstr "目前音軌所屬的蒐集資料音軌總數" + +msgid "disc number" +msgstr "碟片編號" + +msgid "disc number inside a collection" +msgstr "蒐集資料中的碟片編號" + +msgid "disc count" +msgstr "碟片總數" + +msgid "count of discs inside collection this disc belongs to" +msgstr "目前碟片編號所數的蒐集資料碟片總數" + +msgid "location" +msgstr "位置" + +msgid "" +"Origin of media as a URI (location, where the original of the file or stream " +"is hosted)" +msgstr "媒體的URI(檔案或是資料串流的位置)" + +msgid "homepage" +msgstr "首頁" + +msgid "Homepage for this media (i.e. artist or movie homepage)" +msgstr "該媒體的首頁(如作者或是電影首頁)" + +msgid "description" +msgstr "描述" + +msgid "short text describing the content of the data" +msgstr "一段有關媒體內容的簡短說明文字" + +msgid "version" +msgstr "版本" + +msgid "version of this data" +msgstr "媒體檔案版本" + +msgid "ISRC" +msgstr "ISRC" + +msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/" +msgstr "國際標準錄音錄影資料代碼 - 請參考: http://www.ifpi.org/isrc/" + +msgid "organization" +msgstr "組織" + +msgid "copyright" +msgstr "版權" + +msgid "copyright notice of the data" +msgstr "資料的版權通知" + +msgid "copyright uri" +msgstr "版權URI" + +msgid "URI to the copyright notice of the data" +msgstr "資料的版權通知URI" + +msgid "encoded by" +msgstr "編碼者" + +msgid "name of the encoding person or organization" +msgstr "編碼者或是編碼組織名稱" + +msgid "contact" +msgstr "連絡" + +msgid "contact information" +msgstr "連絡資訊" + +msgid "license" +msgstr "條款" + +msgid "license of data" +msgstr "資料的條款" + +msgid "license uri" +msgstr "條款uri" + +msgid "URI to the license of the data" +msgstr "資料的條款URI" + +msgid "performer" +msgstr "演出者" + +msgid "person(s) performing" +msgstr "演出者" + +msgid "composer" +msgstr "作曲者" + +msgid "person(s) who composed the recording" +msgstr "作曲者" + +msgid "conductor" +msgstr "" + +msgid "conductor/performer refinement" +msgstr "" + +msgid "duration" +msgstr "時間長度" + +msgid "length in GStreamer time units (nanoseconds)" +msgstr "GStreamer 時間單位(奈秒)長度" + +msgid "codec" +msgstr "" + +# Wen, 怪怪的 +# 從gsttaglist.c猜測這個是前面訊息的詳細版本 +msgid "codec the data is stored in" +msgstr "處理資料用的codec" + +msgid "video codec" +msgstr "影片codec" + +# Wen, 怪怪的 +# 從gsttaglist.c猜測這個是前面訊息的詳細版本 +msgid "codec the video data is stored in" +msgstr "處理影片資料用的codec" + +msgid "audio codec" +msgstr "聲音codec" + +msgid "codec the audio data is stored in" +msgstr "處理聲音資料用的codec" + +msgid "subtitle codec" +msgstr "字幕codec" + +msgid "codec the subtitle data is stored in" +msgstr "處理字幕資料的codec" + +msgid "container format" +msgstr "container 格式" + +msgid "container format the data is stored in" +msgstr "處理資料的container模式" + +msgid "bitrate" +msgstr "位元率" + +msgid "exact or average bitrate in bits/s" +msgstr "準確的或平均的位元率 (bit/s)" + +msgid "nominal bitrate" +msgstr "" + +msgid "nominal bitrate in bits/s" +msgstr "" + +msgid "minimum bitrate" +msgstr "最低位元率" + +msgid "minimum bitrate in bits/s" +msgstr "最低位元率 (bit/s)" + +msgid "maximum bitrate" +msgstr "最高位元率" + +msgid "maximum bitrate in bits/s" +msgstr "最高位元率 (bit/s)" + +msgid "encoder" +msgstr "編碼器" + +msgid "encoder used to encode this stream" +msgstr "該資料串流使用的編碼器" + +msgid "encoder version" +msgstr "編碼器版本" + +msgid "version of the encoder used to encode this stream" +msgstr "該資料串流使用的編碼器版本" + +msgid "serial" +msgstr "流水號" + +msgid "serial number of track" +msgstr "音軌的流水號" + +msgid "replaygain track gain" +msgstr "回放增益音軌增益" + +msgid "track gain in db" +msgstr "音軌增益(db)" + +msgid "replaygain track peak" +msgstr "回放增益音軌峰值" + +msgid "peak of the track" +msgstr "音軌峰值" + +msgid "replaygain album gain" +msgstr "回放增益專輯增益" + +msgid "album gain in db" +msgstr "專輯增益(db)" + +msgid "replaygain album peak" +msgstr "回放增益專輯峰值" + +msgid "peak of the album" +msgstr "專輯峰值" + +msgid "replaygain reference level" +msgstr "回放增益參考level" + +msgid "reference level of track and album gain values" +msgstr "音軌以及增益值的參考level" + +msgid "language code" +msgstr "語言編碼" + +msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2" +msgstr "該資料串流的語言編碼,和ISO-639或ISO-639-2相容" + +msgid "language name" +msgstr "語言名稱" + +msgid "freeform name of the language this stream is in" +msgstr "該資料串流使用的語言" + +msgid "image" +msgstr "影像" + +msgid "image related to this stream" +msgstr "和該資料串流有關的影像" + +#. TRANSLATORS: 'preview image' = image that shows a preview of the full image +msgid "preview image" +msgstr "影像預覽" + +msgid "preview image related to this stream" +msgstr "和該資料串流有關的影像預覽" + +msgid "attachment" +msgstr "附件" + +msgid "file attached to this stream" +msgstr "該資料串流所附的檔案" + +msgid "beats per minute" +msgstr "每分鐘beat數" + +msgid "number of beats per minute in audio" +msgstr "聲音中每分鐘beat數" + +msgid "keywords" +msgstr "關鍵字" + +msgid "comma separated keywords describing the content" +msgstr "用來敘述媒體內容的關鍵字,關鍵字之間以逗號分開" + +msgid "geo location name" +msgstr "地理位置名稱" + +msgid "" +"human readable descriptive location of where the media has been recorded or " +"produced" +msgstr "人類可讀的媒體錄製地點資訊。" + +msgid "geo location latitude" +msgstr "地理緯度位置" + +# Wen, 省略規格描述部份 +msgid "" +"geo latitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the equator, negative values for " +"southern latitudes)" +msgstr "媒體錄製地點緯度" + +msgid "geo location longitude" +msgstr "地理經度位置" + +# Wen, 省略規格描述部份 +msgid "" +"geo longitude location of where the media has been recorded or produced in " +"degrees according to WGS84 (zero at the prime meridian in Greenwich/UK, " +"negative values for western longitudes)" +msgstr "媒體錄製地點經度" + +msgid "geo location elevation" +msgstr "地理位置海拔" + +# Wen, 省略規格描述部份 +msgid "" +"geo elevation of where the media has been recorded or produced in meters " +"according to WGS84 (zero is average sea level)" +msgstr "媒體錄製地點海拔" + +msgid "geo location country" +msgstr "地理位置國家" + +msgid "country (english name) where the media has been recorded or produced" +msgstr "媒體錄製的國家(英文名)" + +msgid "geo location city" +msgstr "地理位置城市" + +msgid "city (english name) where the media has been recorded or produced" +msgstr "以英文表示的媒體錄製城市" + +msgid "geo location sublocation" +msgstr "地理位置城市內區域" + +msgid "" +"a location within a city where the media has been produced or created (e.g. " +"the neighborhood)" +msgstr "媒體錄製城市內區域" + +msgid "geo location horizontal error" +msgstr "地理位置水平誤差" + +msgid "expected error of the horizontal positioning measures (in meters)" +msgstr "預期的水平誤差(以公尺為單位)" + +msgid "geo location movement speed" +msgstr "地理位址移動速度" + +msgid "" +"movement speed of the capturing device while performing the capture in m/s" +msgstr "錄製設備操作時的移動速度(m/s)" + +msgid "geo location movement direction" +msgstr "地理位址移動方向" + +# Wen, 省略規格描述部份 +msgid "" +"indicates the movement direction of the device performing the capture of a " +"media. It is represented as degrees in floating point representation, 0 " +"means the geographic north, and increases clockwise" +msgstr "錄製設備操作時的移動方向" + +msgid "geo location capture direction" +msgstr "地理位址錄製設備方向" + +# Wen, 省略規格描述部份 +msgid "" +"indicates the direction the device is pointing to when capturing a media. " +"It is represented as degrees in floating point representation, 0 means the " +"geographic north, and increases clockwise" +msgstr "錄製設備操作時的方向" + +#. TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here +msgid "show name" +msgstr "顯示名稱" + +msgid "Name of the tv/podcast/series show the media is from" +msgstr "tv/podcast/影集中媒體的名稱" + +#. TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here +msgid "show sortname" +msgstr "顯示排序後名稱" + +msgid "" +"Name of the tv/podcast/series show the media is from, for sorting purposes" +msgstr "排序後的tv/podcast/影集中媒體的名稱" + +msgid "episode number" +msgstr "集數編號" + +msgid "The episode number in the season the media is part of" +msgstr "該季中媒體集數編號" + +msgid "season number" +msgstr "季數編號" + +msgid "The season number of the show the media is part of" +msgstr "媒體的季數編號" + +msgid "lyrics" +msgstr "歌詞" + +msgid "The lyrics of the media, commonly used for songs" +msgstr "歌曲歌詞" + +msgid "composer sortname" +msgstr "排序後的編曲者" + +msgid "person(s) who composed the recording, for sorting purposes" +msgstr "排序後的編曲者" + +msgid "grouping" +msgstr "群組" + +msgid "" +"Groups related media that spans multiple tracks, like the different pieces " +"of a concerto. It is a higher level than a track, but lower than an album" +msgstr "" +"將有關聯的不同的音軌設成群組,例如一場演唱會切成不同段落。比單一音軌高階,但" +"是比專輯低階" + +msgid "user rating" +msgstr "使用者評價" + +msgid "" +"Rating attributed by a user. The higher the rank, the more the user likes " +"this media" +msgstr "使用者評價,分數愈高表示愈受歡迎" + +msgid "device manufacturer" +msgstr "設備製造商" + +msgid "Manufacturer of the device used to create this media" +msgstr "錄製媒體設備的製造商" + +msgid "device model" +msgstr "設備型號" + +msgid "Model of the device used to create this media" +msgstr "錄製媒體設備的型號" + +msgid "application name" +msgstr "應用程式名稱" + +msgid "Application used to create the media" +msgstr "產生媒體使用的應用程式" + +msgid "application data" +msgstr "應用程式資料" + +msgid "Arbitrary application data to be serialized into the media" +msgstr "任意的應用程式資料,最後會被串列化後放入媒體" + +msgid "image orientation" +msgstr "影像方向" + +msgid "How the image should be rotated or flipped before display" +msgstr "用來協助判斷影像播放時應該旋轉或是翻面" + +msgid "publisher" +msgstr "出版者" + +msgid "Name of the label or publisher" +msgstr "標簽或出版商名稱" + +msgid "interpreted-by" +msgstr "詮釋者" + +msgid "Information about the people behind a remix and similar interpretations" +msgstr "重新混音或是重新詮釋的作者" + +# Wen, 怪怪的 +msgid "midi-base-note" +msgstr "Midi簡譜" + +# Wen, 怪怪的 +msgid "Midi note number of the audio track." +msgstr "音軌Midi簡譜" + +msgid "private-data" +msgstr "" + +msgid "Private data" +msgstr "" + +msgid ", " +msgstr "" + +#, c-format +msgid "No URI handler for the %s protocol found" +msgstr "找不到%s的URI處理程式" + +#, c-format +msgid "URI scheme '%s' not supported" +msgstr "不支援URI scheme:'%s'" + +#, c-format +msgid "ERROR: from element %s: %s\n" +msgstr "錯誤:來自 %s element:%s\n" + +#, c-format +msgid "" +"Additional debug info:\n" +"%s\n" +msgstr "" +"額外偵錯資訊:\n" +"%s\n" + +# Wen, 不翻譯,幾乎都是專有名詞 +#, c-format +msgid "link has no source [sink=%s@%p]" +msgstr "" + +# Wen, 不翻譯,幾乎都是專有名詞 +#, c-format +msgid "link has no sink [source=%s@%p]" +msgstr "" + +#, c-format +msgid "no property \"%s\" in element \"%s\"" +msgstr "“%2$s” 元件沒有 “%1$s” 屬性" + +#, c-format +msgid "could not set property \"%s\" in element \"%s\" to \"%s\"" +msgstr "無法將 “%2$s” element的 “%1$s” 屬性設定為 “%3$s”" + +msgid "Delayed linking failed." +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s, %s can't handle caps %s" +msgstr "無法連接 %s 和 %s" + +#, c-format +msgid "could not link %s to %s, neither element can handle caps %s" +msgstr "" + +#, fuzzy, c-format +msgid "could not link %s to %s with caps %s" +msgstr "無法連接 %s 和 %s" + +#, c-format +msgid "could not link %s to %s" +msgstr "無法連接 %s 和 %s" + +#, c-format +msgid "no element \"%s\"" +msgstr "“%s” element不存在" + +#, c-format +msgid "unexpected reference \"%s\" - ignoring" +msgstr "忽略非預期的參照: \"%s\"" + +#, c-format +msgid "unexpected pad-reference \"%s\" - ignoring" +msgstr "忽略非預期的pad參照: \"%s\"" + +#, c-format +msgid "could not parse caps \"%s\"" +msgstr "無法分析caps \"%s\"" + +#, c-format +msgid "no sink element for URI \"%s\"" +msgstr "URI “%s” 沒有可用的sink element" + +#, c-format +msgid "no source element for URI \"%s\"" +msgstr "URI “%s” 沒有可用的source element" + +msgid "syntax error" +msgstr "語法錯誤" + +#, c-format +msgid "specified empty bin \"%s\", not allowed" +msgstr "不允許指定空的bin: \"%s\"" + +#, c-format +msgid "no bin \"%s\", unpacking elements" +msgstr "bin \"%s\"不存在,解開elements" + +msgid "empty pipeline not allowed" +msgstr "不允許空的pipeline" + +msgid "A lot of buffers are being dropped." +msgstr "正在拋棄大量的緩衝區" + +msgid "Internal data flow problem." +msgstr "內部資料流程錯誤" + +msgid "Internal data flow error." +msgstr "內部資料流程錯誤" + +msgid "Internal clock error." +msgstr "內部clock錯誤" + +msgid "Failed to map buffer." +msgstr "對應緩衝區失敗" + +msgid "Filter caps" +msgstr "過濾caps" + +# Wen, 怪怪的 +msgid "" +"Restrict the possible allowed capabilities (NULL means ANY). Setting this " +"property takes a reference to the supplied GstCaps object." +msgstr "限制允許的capabilities (NULL表示不限制),打開該屬性將會參照GstCaps物件" + +msgid "Caps Change Mode" +msgstr "" + +msgid "Filter caps change behaviour" +msgstr "" + +msgid "No Temp directory specified." +msgstr "未指定暫存目錄" + +#, c-format +msgid "Could not create temp file \"%s\"." +msgstr "無法產生暫存檔案\"%s\"" + +#, c-format +msgid "Could not open file \"%s\" for reading." +msgstr "無法開啟檔案 “%s” 來讀取內容。" + +msgid "Error while writing to download file." +msgstr "下載並寫入內容至檔案時發生錯誤。" + +msgid "No file name specified for writing." +msgstr "未指定準備寫入的檔案名稱。" + +#, c-format +msgid "Could not open file \"%s\" for writing." +msgstr "無法開啟 “%s” 檔案來寫入內容。" + +#, c-format +msgid "Error closing file \"%s\"." +msgstr "關閉檔案 “%s” 時發生錯誤。" + +#, c-format +msgid "Error while seeking in file \"%s\"." +msgstr "對檔案 “%s” 定位時發生錯誤。" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "當寫入內容至檔案 “%s” 時發生錯誤。" + +msgid "No file name specified for reading." +msgstr "未指定要讀取的檔案名稱。" + +#, c-format +msgid "Could not get info on \"%s\"." +msgstr "無法從 %s 取得資料" + +#, c-format +msgid "\"%s\" is a directory." +msgstr "“%s” 是一個目錄。" + +#, c-format +msgid "File \"%s\" is a socket." +msgstr "“%s” 是一個 socket。" + +# Wen, 怪怪的 +msgid "Failed after iterations as requested." +msgstr "重複送出請求後發生失敗" + +msgid "caps" +msgstr "" + +msgid "detected capabilities in stream" +msgstr "已從資料串流中偵測到capabilities" + +msgid "minimum" +msgstr "最低" + +msgid "force caps" +msgstr "強迫caps" + +msgid "force caps without doing a typefind" +msgstr "不尋找型態,直些強迫caps" + +#, fuzzy +msgid "Stream doesn't contain enough data." +msgstr "資料串流中沒有資料" + +msgid "Stream contains no data." +msgstr "資料串流中沒有資料" + +msgid "Implemented Interfaces:\n" +msgstr "實作介面:\n" + +msgid "readable" +msgstr "可讀" + +msgid "writable" +msgstr "可寫" + +msgid "deprecated" +msgstr "" + +msgid "controllable" +msgstr "可控制" + +msgid "changeable in NULL, READY, PAUSED or PLAYING state" +msgstr "可以切換到NULL, READY, PAUSED 或PLAYING狀態" + +msgid "changeable only in NULL, READY or PAUSED state" +msgstr "只能切換到NULL, READY, 或PAUSED狀態" + +msgid "changeable only in NULL or READY state" +msgstr "只能切換到NULL 或 READY狀態" + +msgid "Blacklisted files:" +msgstr "黑名單檔案" + +msgid "Total count: " +msgstr "總數量:" + +#, c-format +msgid "%d blacklisted file" +msgid_plural "%d blacklisted files" +msgstr[0] "%d個黑名單檔案" + +#, c-format +msgid "%d plugin" +msgid_plural "%d plugins" +msgstr[0] "%d 個外掛程式" + +#, c-format +msgid "%d blacklist entry" +msgid_plural "%d blacklist entries" +msgstr[0] "%d筆黑名單紀錄" + +#, c-format +msgid "%d feature" +msgid_plural "%d features" +msgstr[0] "%d 個功能" + +msgid "Print all elements" +msgstr "顯示所有elements" + +msgid "Print list of blacklisted files" +msgstr "顯示所有黑名單檔案" + +# Wen, 怪怪的 +msgid "" +"Print a machine-parsable list of features the specified plugin or all " +"plugins provide.\n" +" Useful in connection with external " +"automatic plugin installation mechanisms" +msgstr "" +"從指定外掛程式或是所有外掛程式印出電腦可以分析的功能列表。\n" +" 對於連結並安裝外部自動外掛程式有用" + +msgid "List the plugin contents" +msgstr "列出外掛程式內容" + +msgid "" +"A slashes ('/') separated list of types of elements (also known as klass) to " +"list. (unordered)" +msgstr "" + +msgid "Check if the specified element or plugin exists" +msgstr "檢查指定的element或是外掛程式是否存在" + +msgid "" +"When checking if an element or plugin exists, also check that its version is " +"at least the version specified" +msgstr "檢查指定的element或是外掛程式是否存在時順便檢查是否為最新版本" + +msgid "Print supported URI schemes, with the elements that implement them" +msgstr "印出支援的URI schemes以及有實作它的elements" + +#, c-format +msgid "Could not load plugin file: %s\n" +msgstr "無法再入外掛程式檔案: “%s”\n" + +#, c-format +msgid "No such element or plugin '%s'\n" +msgstr "找不到element或外掛程式'%s'\n" + +msgid "Index statistics" +msgstr "索引統計" + +#, c-format +msgid "Got message #%u from element \"%s\" (%s): " +msgstr "從element \"%2$s\"(%3$s) 中得到訊息#%1$u:" + +#, c-format +msgid "Got message #%u from pad \"%s:%s\" (%s): " +msgstr "從pad \"%4$s\"(%2$s:%3$s) 中得到訊息#%1$u:" + +#, c-format +msgid "Got message #%u from object \"%s\" (%s): " +msgstr "從物件 \"%2$s\"(%3$s) 中得到訊息#%1$u:" + +#, c-format +msgid "Got message #%u (%s): " +msgstr "收到訊息 #%u (%s):" + +#, c-format +msgid "Got EOS from element \"%s\".\n" +msgstr "從element \"%s\" 中得到EOS通知\n" + +#, c-format +msgid "FOUND TAG : found by element \"%s\".\n" +msgstr "找到標籤 : 由element \"%s\"找到。\n" + +#, c-format +msgid "FOUND TAG : found by pad \"%s:%s\".\n" +msgstr "找到標籤 : 由pad \"%s:%s\"找到。\n" + +#, c-format +msgid "FOUND TAG : found by object \"%s\".\n" +msgstr "找到標籤 : 由從物件 \"%s\"找到。\n" + +msgid "FOUND TAG\n" +msgstr "找到標籤\n" + +#, c-format +msgid "FOUND TOC : found by element \"%s\".\n" +msgstr "找到 TOC : 從element \"%s\"。\n" + +#, c-format +msgid "FOUND TOC : found by object \"%s\".\n" +msgstr "找到 TOC : 從物件 \"%s\"。\n" + +msgid "FOUND TOC\n" +msgstr "找到TOC\n" + +#, c-format +msgid "" +"INFO:\n" +"%s\n" +msgstr "" +"資訊:\n" +"%s\n" + +#, c-format +msgid "WARNING: from element %s: %s\n" +msgstr "警告:來自element %s :%s\n" + +# Wen, 怪怪的, 如何精確區分preroll和buffer? +msgid "Prerolled, waiting for buffering to finish...\n" +msgstr "緩衝中,等待緩衝完成...\n" + +msgid "Prerolled, waiting for progress to finish...\n" +msgstr "緩衝中,等待完成進度...\n" + +msgid "buffering..." +msgstr "緩衝中..." + +msgid "Done buffering, setting pipeline to PLAYING ...\n" +msgstr "緩衝完成,將pipeline狀態設成PLAYING...\n" + +msgid "Buffering, setting pipeline to PAUSED ...\n" +msgstr "緩衝完成,將pipeline狀態設成PAUSE...\n" + +msgid "Redistribute latency...\n" +msgstr "重新分配延遲時間...\n" + +#, c-format +msgid "Setting state to %s as requested by %s...\n" +msgstr "由%2$s要求,將狀態設成%1$s...\n" + +msgid "Interrupt: Stopping pipeline ...\n" +msgstr "中斷:停止pipeline...\n" + +#, c-format +msgid "Progress: (%s) %s\n" +msgstr "進度:(%s) %s\n" + +#, c-format +msgid "Missing element: %s\n" +msgstr "“%s” element不存在\n" + +#, c-format +msgid "Got context from element '%s': %s=%s\n" +msgstr "從element '%s' 取得內容: %s=%s\n" + +msgid "Output tags (also known as metadata)" +msgstr "輸出標籤 (即metadata)" + +msgid "Output TOC (chapters and editions)" +msgstr "輸出TOC (章節以及版本)" + +msgid "Output status information and property notifications" +msgstr "輸出狀態資訊以及屬性通知" + +msgid "Do not print any progress information" +msgstr "不顯示任何進度資訊" + +msgid "Output messages" +msgstr "輸出訊息" + +msgid "" +"Do not output status information for the specified property if verbose " +"output is enabled (can be used multiple times)" +msgstr "" + +msgid "PROPERTY-NAME" +msgstr "" + +msgid "Do not install a fault handler" +msgstr "不安裝錯誤處理程式" + +msgid "Force EOS on sources before shutting the pipeline down" +msgstr "在關閉pipeline前強迫source EOS" + +msgid "Gather and print index statistics" +msgstr "收集並列印索引統計" + +#, c-format +msgid "ERROR: pipeline could not be constructed: %s.\n" +msgstr "錯誤:無法建立pipeline:%s。\n" + +msgid "ERROR: pipeline could not be constructed.\n" +msgstr "錯誤:無法建立pipeline。\n" + +#, c-format +msgid "WARNING: erroneous pipeline: %s\n" +msgstr "警告:pipeline錯誤:%s\n" + +msgid "ERROR: the 'pipeline' element wasn't found.\n" +msgstr "錯誤:找不到 ‘pipeline’ element。\n" + +msgid "Setting pipeline to PAUSED ...\n" +msgstr "將pipeline狀態設為PAUSED...\n" + +msgid "ERROR: Pipeline doesn't want to pause.\n" +msgstr "錯誤:Pipeline 不想要暫停。\n" + +msgid "Pipeline is live and does not need PREROLL ...\n" +msgstr "Pipepline可以正常運動,不需要緩衝 ...\n" + +msgid "Pipeline is PREROLLING ...\n" +msgstr "Pipeline正在緩衝 ...\n" + +msgid "ERROR: pipeline doesn't want to preroll.\n" +msgstr "錯誤:Pipeline 不想要緩衝。\n" + +msgid "Pipeline is PREROLLED ...\n" +msgstr "Pipleline已經緩衝完畢 ...\n" + +msgid "Setting pipeline to PLAYING ...\n" +msgstr "將pipeline狀態設為PLAYING...\n" + +msgid "ERROR: pipeline doesn't want to play.\n" +msgstr "錯誤:Pipeline 不想要播放。\n" + +msgid "EOS on shutdown enabled -- Forcing EOS on the pipeline\n" +msgstr "關閉時送出EOS已設定 -- 強迫Pipeline EOS\n" + +msgid "EOS on shutdown enabled -- waiting for EOS after Error\n" +msgstr "關閉時送出EOS已設定 -- 產生錯誤後等待EOS\n" + +msgid "Waiting for EOS...\n" +msgstr "等待EOS...\n" + +msgid "EOS received - stopping pipeline...\n" +msgstr "收到EOS - 停止pipeline...\n" + +msgid "Interrupt while waiting for EOS - stopping pipeline...\n" +msgstr "等待EOS時發生中斷 - 停止pipeline\n" + +msgid "An error happened while waiting for EOS\n" +msgstr "等待EOS時發生錯誤\n" + +msgid "Execution ended after %" +msgstr "在 % 之後執行結束" + +msgid "Setting pipeline to READY ...\n" +msgstr "將pipeline狀態設為READY...\n" + +msgid "Setting pipeline to NULL ...\n" +msgstr "將pipeline狀態設為NULL...\n" + +msgid "Freeing pipeline ...\n" +msgstr "釋放pipeline ...\n" + +#~ msgid "Internal data stream error." +#~ msgstr "內部資料串流錯誤" + +#~ msgid "Do not output status information of TYPE" +#~ msgstr "不顯示和 TYPE 有關的狀態資訊" + +#~ msgid "TYPE1,TYPE2,..." +#~ msgstr "TYPE1,TYPE2,..." + +#~ msgid "link without source element" +#~ msgstr "管線中沒有來源元件" + +#~ msgid "link without sink element" +#~ msgstr "管線中沒有輸出元件" + +#~ msgid "Print alloc trace (if enabled at compile time)" +#~ msgstr "印出 alloc 追蹤訊息 (如果編譯程式時有啟用這項功能)" + +#~ msgid "Usage: gst-xmllaunch [ element.property=value ... ]\n" +#~ msgstr "用法:gst-xmllaunch [ element.property=value ... ]\n" + +#~ msgid "ERROR: parse of xml file '%s' failed.\n" +#~ msgstr "錯誤:無法解析 XML 檔案 ‘%s’ 的內容。\n" + +#~ msgid "ERROR: could not parse command line argument %d: %s.\n" +#~ msgstr "錯誤:無法解析指令的第 %d 個參數:%s。\n" + +#~ msgid "Save xml representation of pipeline to FILE and exit" +#~ msgstr "將代表管線的架構儲存至<檔案>,然後結束" + +#~ msgid "FILE" +#~ msgstr "檔案" + +#~ msgid "Disable accelerated CPU instructions" +#~ msgstr "關閉 CPU 優化功能" + +#~ msgid "SCHEDULER" +#~ msgstr "SCHEDULER" + +#~ msgid "REGISTRY" +#~ msgstr "REGISTRY" + +#~ msgid "path list for loading plugins (separated by '%s')" +#~ msgstr "搜尋外掛時的路徑清單,以‘%s’分隔" + +#~ msgid "Scheduler to use (default is '%s')" +#~ msgstr "準備使用的排程器 (預設為 ‘%s’)" + +#~ msgid "Internal GStreamer error: state change failed. File a bug." +#~ msgstr "GStreamer 內部錯誤:無法更改狀態。請匯報錯誤。" + +#~ msgid "Internal GStreamer error: scheduler problem. File a bug." +#~ msgstr "GStreamer 內部錯誤:排程器發生問題。請匯報錯誤。" + +#~ msgid "original location of file as a URI" +#~ msgstr "URI 形式的檔案位置" + +#~ msgid "" +#~ "Execution ended after %s iterations (sum %s ns, average %s ns, min %s ns, " +#~ "max %s ns).\n" +#~ msgstr "" +#~ "%s 個迴圈後執行完畢 (總共 %s ns,平均 %s ns,最少 %s ns,最多 %s ns)\n" + +#~ msgid "Number of times to iterate pipeline" +#~ msgstr "管線執行次數" + +#~ msgid " Trying to run anyway.\n" +#~ msgstr " 嘗試強制執行。\n" diff --git a/scripts/gst-uninstalled b/scripts/gst-uninstalled new file mode 100755 index 0000000..2108c3c --- /dev/null +++ b/scripts/gst-uninstalled @@ -0,0 +1,260 @@ +#!/bin/bash -i +# +# this script is in git as gstreamer/scripts/gst-uninstalled +# +# It will set up the environment to use and develop gstreamer and projects +# that use gstreamer with an uninstalled git checkout of gstreamer and the +# plugin modules. +# +# It will set up LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PKG_CONFIG_PATH, +# GST_PLUGIN_PATH, GST_PLUGIN_SYSTEM_PATH, GST_REGISTRY, MANPATH, PYTHONPATH +# to prefer the uninstalled versions but also contain the installed ones. +# The only exception to this is, that no system installed plugins will be +# used but only the uninstalled ones. +# +# This script assumes that the relevant modules are checked out one by one +# under a given tree specified below in MYGST. +# +# Symlink this script in a directory in your path (for example $HOME/bin). You +# must name the symlink gst-something, where something is the subdirectory +# of MYGST that contains your gstreamer module checkouts. +# +# e.g.: +# - mkdir $HOME/gst/head +# - ln -sf gst-uninstalled $HOME/bin/gst-head +# - checkout copies of gstreamer modules in $HOME/gst/head +# - gst-head + +# This script is run -i so that PS1 doesn't get cleared + +if [ -z $GST_UNINSTALLED_ROOT ]; +then + # Change this variable to the location of your gstreamer git checkouts + MYGST=$HOME/gst + + # + # Everything below this line shouldn't be edited! + # + + # extract version from $0 + # if this script is called "gst-head" then version will be "head" + VERSION=`echo $0 | sed s/.*gst-//g` + + # base path under which dirs are installed + GST=$MYGST/$VERSION +else + # Alternatively, you can set the GST_UNINSTALLED_ROOT environment variable to the + # location of your checkout and call this script directly. + # + # Ex: GST_UNINSTALLED_ROOT=$HOME/checkout/location gst-uninstalled + + GST=$GST_UNINSTALLED_ROOT +fi + +GST_PREFIX=$GST/prefix +if test ! -e $GST; then + echo "$GST does not exist !" + exit +fi + +# set up a bunch of paths +PATH="\ +$GST/gstreamer/tools:\ +$GST/gst-plugins-base/tools:\ +$GST/gst-player/src:\ +$GST/gst-editor/src:\ +$GST/gstreamer-sharp/tools:\ +$GST/orc/tools:\ +$GST_PREFIX/bin:\ +$PATH" + +# /some/path: makes the dynamic linker look in . too, so avoid this +LD_LIBRARY_PATH=$GST_PREFIX/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} +DYLD_LIBRARY_PATH=$GST_PREFIX/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH} +GI_TYPELIB_PATH=$GST_PREFIX/share/gir-1.0${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH} + +# ORC +LD_LIBRARY_PATH=$GST/orc/orc/.libs:$GST/orc/orc-test/.libs:$LD_LIBRARY_PATH +DYLD_LIBRARY_PATH=$GST/orc/orc/.libs:$GST/orc/orc-test/.libs:$DYLD_LIBRARY_PATH + +# GStreamer rtsp server library +LD_LIBRARY_PATH=$GST/gst-rtsp-server/gst/rtsp-server/.libs:$LD_LIBRARY_PATH +DYLD_LIBRARY_PATH=$GST/gst-rtsp-server/gst/rtsp-server/.libs:$DYLD_LIBRARY_PATH +GI_TYPELIB_PATH=$GST/gst-rtsp-server/gst/rtsp-server:$GI_TYPELIB_PATH + +# GStreamer Editing Services library +LD_LIBRARY_PATH=$GST/gst-editing-services/ges/.libs:$LD_LIBRARY_PATH +DYLD_LIBRARY_PATH=$GST/gst-editing-services/ges/.libs:$DYLD_LIBRARY_PATH +GI_TYPELIB_PATH=$GST/gst-editing-services/ges:$GI_TYPELIB_PATH +PATH=$GST/gst-editing-services/tools:$PATH + +# GStreamer plugins vaapi libraries +LD_LIBRARY_PATH=$GST/gstreamer-vaapi/gst-libs/gst/vaapi/.libs:$LD_LIBRARY_PATH +DYLD_LIBRARY_PATH=$GST/gstreamer-vaapi/gst-libs/gst/vaapi/.libs:$DYLD_LIBRARY_PATH + +# GStreamer plugins base libraries +for path in allocators app audio fft gl pbutils riff rtp rtsp sdp tag utils video +do + LD_LIBRARY_PATH=$GST/gst-plugins-base/gst-libs/gst/$path/.libs:$LD_LIBRARY_PATH + DYLD_LIBRARY_PATH=$GST/gst-plugins-base/gst-libs/gst/$path/.libs:$DYLD_LIBRARY_PATH + GI_TYPELIB_PATH=$GST/gst-plugins-base/gst-libs/gst/$path:$GI_TYPELIB_PATH +done + +# GStreamer plugins bad libraries +for path in adaptivedemux audio basecamerabinsrc codecparsers insertbin interfaces mpegts opencv player uridownloader video wayland webrtc +do + LD_LIBRARY_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path/.libs:$LD_LIBRARY_PATH + DYLD_LIBRARY_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path/.libs:$DYLD_LIBRARY_PATH + GI_TYPELIB_PATH=$GST/gst-plugins-bad/gst-libs/gst/$path:$GI_TYPELIB_PATH +done +export GST_HAAR_CASCADES_PATH=$GST/gst-plugins-bad/ext/opencv/ + +# GStreamer core libraries +for path in base check controller net +do + LD_LIBRARY_PATH=$GST/gstreamer/libs/gst/$path/.libs:$LD_LIBRARY_PATH + DYLD_LIBRARY_PATH=$GST/gstreamer/libs/gst/$path/.libs:$DYLD_LIBRARY_PATH + GI_TYPELIB_PATH=$GST/gstreamer/libs/gst/$path:$GI_TYPELIB_PATH +done +LD_LIBRARY_PATH=$GST/gstreamer/gst/.libs:$LD_LIBRARY_PATH +DYLD_LIBRARY_PATH=$GST/gstreamer/gst/.libs:$DYLD_LIBRARY_PATH +GI_TYPELIB_PATH=$GST/gstreamer/gst:$GI_TYPELIB_PATH +export LD_LIBRARY_PATH +export DYLD_LIBRARY_PATH +export GI_TYPELIB_PATH + +export PKG_CONFIG_PATH="\ +$GST_PREFIX/lib/pkgconfig\ +:$GST/gstreamer/pkgconfig\ +:$GST/gst-plugins-base/pkgconfig\ +:$GST/gst-plugins-good/pkgconfig\ +:$GST/gst-plugins-ugly/pkgconfig\ +:$GST/gst-plugins-bad/pkgconfig\ +:$GST/gst-libav/pkgconfig\ +:$GST/gst-ffmpeg/pkgconfig\ +:$GST/gst-python/pkgconfig\ +:$GST/gst-rtsp-server/pkgconfig\ +:$GST/gst-editing-services/pkgconfig\ +:$GST/gstreamer-sharp/pkgconfig\ +:$GST/gstreamer-vaapi/pkgconfig\ +:$GST/orc\ +:$GST/farsight2\ +:$GST/libnice/nice\ +${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" + +export GST_PLUGIN_PATH="\ +$GST/gstreamer/plugins\ +:$GST/gst-plugins-base/ext\ +:$GST/gst-plugins-base/gst\ +:$GST/gst-plugins-base/sys\ +:$GST/gst-plugins-good/ext\ +:$GST/gst-plugins-good/gst\ +:$GST/gst-plugins-good/sys\ +:$GST/gst-plugins-ugly/ext\ +:$GST/gst-plugins-ugly/gst\ +:$GST/gst-plugins-ugly/sys\ +:$GST/gst-plugins-bad/ext\ +:$GST/gst-plugins-bad/gst\ +:$GST/gst-plugins-bad/sys\ +:$GST/gst-libav/ext/\ +:$GST/gst-ffmpeg/ext/\ +:$GST/gst-omx/omx/.libs\ +:$GST/clutter-gst/clutter-gst/.libs\ +:$GST/gstreamer-vaapi/gst/vaapi/.libs\ +:$GST/plugins\ +:$GST/farsight2/gst\ +:$GST/farsight2/transmitters\ +:$GST/libnice/gst\ +:$GST/gst-rpicamsrc/src/.libs\ +:$GST/gst-rtsp-server/gst/rtsp-sink/.libs\ +:$GST/gst-editing-services/plugins/nle/.libs\ +${GST_PLUGIN_PATH:+:$GST_PLUGIN_PATH}" + +export GST_PRESET_PATH="\ +$GST/gst-plugins-good/gst/equalizer/\ +:$GST/gst-plugins-good/gst/equalizer\ +:$GST/gst-plugins-good/ext/vpx/\ +:$GST/gst-plugins-ugly/ext/x264\ +:$GST/gst-plugins-ugly/ext/amrnb\ +:$GST/gst-plugins-bad/gst/freeverb\ +:$GST/gst-plugins-bad/ext/voamrwbenc\ +${GST_PRESET_PATH:+:$GST_PRESET_PATH}" + +# don't use any system-installed plug-ins at all +export GST_PLUGIN_SYSTEM_PATH= +# set our registry somewhere else so we don't mess up the registry generated +# by an installed copy +rm -f $GST/gstreamer/registry.xml 2>/dev/null +export GST_REGISTRY=$GST/gstreamer/registry.dat +# Point at the uninstalled plugin scanner +export GST_PLUGIN_SCANNER=$GST/gstreamer/libs/gst/helpers/gst-plugin-scanner +# Point at the uninstalled PTP helper +export GST_PTP_HELPER=$GST/gstreamer/libs/gst/helpers/.libs/gst-ptp-helper + +# once MANPATH is set, it needs at least an "empty"component to keep pulling +# in the system-configured man paths from man.config +# this still doesn't make it work for the uninstalled case, since man goes +# look for a man directory "nearby" instead of the directory I'm telling it to +export MANPATH=$GST/gstreamer/tools:$GST_PREFIX/share/man:$GST/gst-editing-services/docs/man/:$MANPATH +if [ -z "$PYTHON" ]; then PYTHON="python3"; fi +pythonver=`$PYTHON -c "import sys; print (sys.version[:3])"` +pythonsites=`$PYTHON -c "import site; print(':'.join(site.getsitepackages()))"` +export PYTHONPATH="${PYTHONPATH}:${pythonsites}:${GST}/gst-python" + +# clutter-gst +export PKG_CONFIG_PATH=$GST/clutter-gst:$PKG_CONFIG_PATH +export LD_LIBRARY_PATH=$GST/clutter-gst/clutter-gst/.libs:$LD_LIBRARY_PATH +export DYLD_LIBRARY_PATH=$GST/clutter-gst/clutter-gst/.libs:$DYLD_LIBRARY_PATH + +# totem-pl-parser +export PKG_CONFIG_PATH=$GST/totem-pl-parser:$PKG_CONFIG_PATH +export LD_LIBRARY_PATH=$GST/totem-pl-parser/plparse/.libs:$LD_LIBRARY_PATH +export DYLD_LIBRARY_PATH=$GST/totem-pl-parser/plparse/.libs:$DYLD_LIBRARY_PATH + +# totem +export PATH=$GST/totem/src:$PATH + +# gstreamer-sharp +export MONO_PATH=$GST/gstreamer-sharp/gstreamer-sharp:$MONO_PATH +export LD_LIBRARY_PATH=$GST/gstreamer-sharp/gstreamer-sharp/glue/.libs:$LD_LIBRARY_PATH +export DYLD_LIBRARY_PATH=$GST/gstreamer-sharp/gstreamer-sharp/glue/.libs:$DYLD_LIBRARY_PATH + +# gst-devtools/validate +export PATH=$GST/gst-devtools/validate/tools:$PATH +export PKG_CONFIG_PATH=$GST/gst-devtools/validate/pkgconfig:$PKG_CONFIG_PATH +export GST_VALIDATE_SCENARIOS_PATH=$GST/gst-devtools/validate/data/scenarios:$GST_VALIDATE_SCENARIOS_PATH +export GST_VALIDATE_APPS_DIR=$GST_VALIDATE_APPS_DIR:$GST/gst-editing-services/tests/validate/ +export GST_VALIDATE_PLUGIN_PATH=$GST_VALIDATE_PLUGIN_PATH:$GST/gst-devtools/validate/plugins/ +export GIO_EXTRA_MODULES=$GST/prefix/lib/gio/modules:$GIO_EXTRA_MODULES + +if [ -d "$GST/gst-libav" -a -d "$GST/gst-ffmpeg" ]; then + echo + echo "=====================================================================" + echo " You have both an uninstalled gst-ffmpeg checkout and a gst-libav" + echo " checkout. You need to remove one of those. You should remove" + echo + echo " $GST/gst-ffmpeg" + echo + echo " since gst-libav replaces gst-ffmpeg." + echo "=====================================================================" + echo +fi + +# if we got a command, run it, else start a shell +if test ! -z "$1"; +then + $@ + exit $? +fi + +# set up prompt to help us remember we're in a subshell, cd to +# the gstreamer base dir and start $SHELL +cd $GST +shell=$SHELL +if test "x$SHELL" = "x/bin/bash" +then + # debian/ubuntu resets our PS1. bastards. + shell="$SHELL --noprofile" +fi +PS1="[gst-$VERSION] $PS1" $shell + diff --git a/stamp.h.in b/stamp.h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/stamp.h.in @@ -0,0 +1 @@ +timestamp diff --git a/test-driver b/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# 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. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..9fe291c --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,45 @@ +EXTRA_DIST = README + +# Build misc unless both --disable-examples and --disable-benchmarks were passed + +if BUILD_BENCHMARKS +SUBDIRS_BENCHMARKS = benchmarks +SUBDIRS_MISC = misc +else +SUBDIRS_BENCHMARKS = +endif + +if BUILD_TESTS +## SUBDIRS_TESTS = tests testsuite +## FIXME: write tests from scratch +SUBDIRS_TESTS = +if HAVE_CHECK +SUBDIRS_CHECK = check +else +SUBDIRS_CHECK = +endif +else +SUBDIRS_TESTS = +SUBDIRS_CHECK = +endif + +if BUILD_EXAMPLES +SUBDIRS_EXAMPLES = examples +SUBDIRS_MISC = misc +else +SUBDIRS_EXAMPLES = +endif + +SUBDIRS = \ + $(SUBDIRS_BENCHMARKS) \ + $(SUBDIRS_CHECK) \ + $(SUBDIRS_MISC) \ + $(SUBDIRS_TESTS) \ + $(SUBDIRS_EXAMPLES) + +# These are all the possible subdirs +DIST_SUBDIRS = \ + benchmarks \ + check \ + examples \ + misc diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..ee4ed6a --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,839 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = README +@BUILD_BENCHMARKS_FALSE@SUBDIRS_BENCHMARKS = + +# Build misc unless both --disable-examples and --disable-benchmarks were passed +@BUILD_BENCHMARKS_TRUE@SUBDIRS_BENCHMARKS = benchmarks +@BUILD_BENCHMARKS_TRUE@SUBDIRS_MISC = misc +@BUILD_EXAMPLES_TRUE@SUBDIRS_MISC = misc +@BUILD_TESTS_FALSE@SUBDIRS_TESTS = +@BUILD_TESTS_TRUE@SUBDIRS_TESTS = +@BUILD_TESTS_FALSE@SUBDIRS_CHECK = +@BUILD_TESTS_TRUE@@HAVE_CHECK_FALSE@SUBDIRS_CHECK = +@BUILD_TESTS_TRUE@@HAVE_CHECK_TRUE@SUBDIRS_CHECK = check +@BUILD_EXAMPLES_FALSE@SUBDIRS_EXAMPLES = +@BUILD_EXAMPLES_TRUE@SUBDIRS_EXAMPLES = examples +SUBDIRS = \ + $(SUBDIRS_BENCHMARKS) \ + $(SUBDIRS_CHECK) \ + $(SUBDIRS_MISC) \ + $(SUBDIRS_TESTS) \ + $(SUBDIRS_EXAMPLES) + + +# These are all the possible subdirs +DIST_SUBDIRS = \ + benchmarks \ + check \ + examples \ + misc + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..7dad473 --- /dev/null +++ b/tests/README @@ -0,0 +1,12 @@ +This directory contains regression tests, functionality tests, examples, +benchmarks, ... + +benchmarks/ + benchmarks to profile pieces of GStreamer +check/ + unit tests using the check library, non-interactive +examples/ + small examples demonstrating the use of various features +misc/ + prototypes, random bits, ... + diff --git a/tests/benchmarks/Makefile.am b/tests/benchmarks/Makefile.am new file mode 100644 index 0000000..3d769f5 --- /dev/null +++ b/tests/benchmarks/Makefile.am @@ -0,0 +1,25 @@ +if !GST_DISABLE_GST_DEBUG +TRACER_BENCH = tracerserialize +else +TRACER_BENCH = +endif + +noinst_PROGRAMS = \ + caps \ + capsnego \ + complexity \ + controller \ + init \ + mass-elements \ + gstpollstress \ + gstpoolstress \ + gstclockstress \ + gstbufferstress \ + $(TRACER_BENCH) + +LDADD = $(GST_OBJ_LIBS) +AM_CFLAGS = $(GST_OBJ_CFLAGS) + +controller_CFLAGS = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs +controller_LDADD = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la $(LDADD) + diff --git a/tests/benchmarks/Makefile.in b/tests/benchmarks/Makefile.in new file mode 100644 index 0000000..0bc0678 --- /dev/null +++ b/tests/benchmarks/Makefile.in @@ -0,0 +1,905 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = caps$(EXEEXT) capsnego$(EXEEXT) complexity$(EXEEXT) \ + controller$(EXEEXT) init$(EXEEXT) mass-elements$(EXEEXT) \ + gstpollstress$(EXEEXT) gstpoolstress$(EXEEXT) \ + gstclockstress$(EXEEXT) gstbufferstress$(EXEEXT) \ + $(am__EXEEXT_1) +subdir = tests/benchmarks +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@GST_DISABLE_GST_DEBUG_FALSE@am__EXEEXT_1 = tracerserialize$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +caps_SOURCES = caps.c +caps_OBJECTS = caps.$(OBJEXT) +caps_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +caps_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +capsnego_SOURCES = capsnego.c +capsnego_OBJECTS = capsnego.$(OBJEXT) +capsnego_LDADD = $(LDADD) +capsnego_DEPENDENCIES = $(am__DEPENDENCIES_1) +complexity_SOURCES = complexity.c +complexity_OBJECTS = complexity.$(OBJEXT) +complexity_LDADD = $(LDADD) +complexity_DEPENDENCIES = $(am__DEPENDENCIES_1) +controller_SOURCES = controller.c +controller_OBJECTS = controller-controller.$(OBJEXT) +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +controller_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_2) +controller_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(controller_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +gstbufferstress_SOURCES = gstbufferstress.c +gstbufferstress_OBJECTS = gstbufferstress.$(OBJEXT) +gstbufferstress_LDADD = $(LDADD) +gstbufferstress_DEPENDENCIES = $(am__DEPENDENCIES_1) +gstclockstress_SOURCES = gstclockstress.c +gstclockstress_OBJECTS = gstclockstress.$(OBJEXT) +gstclockstress_LDADD = $(LDADD) +gstclockstress_DEPENDENCIES = $(am__DEPENDENCIES_1) +gstpollstress_SOURCES = gstpollstress.c +gstpollstress_OBJECTS = gstpollstress.$(OBJEXT) +gstpollstress_LDADD = $(LDADD) +gstpollstress_DEPENDENCIES = $(am__DEPENDENCIES_1) +gstpoolstress_SOURCES = gstpoolstress.c +gstpoolstress_OBJECTS = gstpoolstress.$(OBJEXT) +gstpoolstress_LDADD = $(LDADD) +gstpoolstress_DEPENDENCIES = $(am__DEPENDENCIES_1) +init_SOURCES = init.c +init_OBJECTS = init.$(OBJEXT) +init_LDADD = $(LDADD) +init_DEPENDENCIES = $(am__DEPENDENCIES_1) +mass_elements_SOURCES = mass-elements.c +mass_elements_OBJECTS = mass-elements.$(OBJEXT) +mass_elements_LDADD = $(LDADD) +mass_elements_DEPENDENCIES = $(am__DEPENDENCIES_1) +tracerserialize_SOURCES = tracerserialize.c +tracerserialize_OBJECTS = tracerserialize.$(OBJEXT) +tracerserialize_LDADD = $(LDADD) +tracerserialize_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = caps.c capsnego.c complexity.c controller.c \ + gstbufferstress.c gstclockstress.c gstpollstress.c \ + gstpoolstress.c init.c mass-elements.c tracerserialize.c +DIST_SOURCES = caps.c capsnego.c complexity.c controller.c \ + gstbufferstress.c gstclockstress.c gstpollstress.c \ + gstpoolstress.c init.c mass-elements.c tracerserialize.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@GST_DISABLE_GST_DEBUG_FALSE@TRACER_BENCH = tracerserialize +@GST_DISABLE_GST_DEBUG_TRUE@TRACER_BENCH = +LDADD = $(GST_OBJ_LIBS) +AM_CFLAGS = $(GST_OBJ_CFLAGS) +controller_CFLAGS = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs +controller_LDADD = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la $(LDADD) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/benchmarks/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/benchmarks/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +caps$(EXEEXT): $(caps_OBJECTS) $(caps_DEPENDENCIES) $(EXTRA_caps_DEPENDENCIES) + @rm -f caps$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(caps_OBJECTS) $(caps_LDADD) $(LIBS) + +capsnego$(EXEEXT): $(capsnego_OBJECTS) $(capsnego_DEPENDENCIES) $(EXTRA_capsnego_DEPENDENCIES) + @rm -f capsnego$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(capsnego_OBJECTS) $(capsnego_LDADD) $(LIBS) + +complexity$(EXEEXT): $(complexity_OBJECTS) $(complexity_DEPENDENCIES) $(EXTRA_complexity_DEPENDENCIES) + @rm -f complexity$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(complexity_OBJECTS) $(complexity_LDADD) $(LIBS) + +controller$(EXEEXT): $(controller_OBJECTS) $(controller_DEPENDENCIES) $(EXTRA_controller_DEPENDENCIES) + @rm -f controller$(EXEEXT) + $(AM_V_CCLD)$(controller_LINK) $(controller_OBJECTS) $(controller_LDADD) $(LIBS) + +gstbufferstress$(EXEEXT): $(gstbufferstress_OBJECTS) $(gstbufferstress_DEPENDENCIES) $(EXTRA_gstbufferstress_DEPENDENCIES) + @rm -f gstbufferstress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gstbufferstress_OBJECTS) $(gstbufferstress_LDADD) $(LIBS) + +gstclockstress$(EXEEXT): $(gstclockstress_OBJECTS) $(gstclockstress_DEPENDENCIES) $(EXTRA_gstclockstress_DEPENDENCIES) + @rm -f gstclockstress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gstclockstress_OBJECTS) $(gstclockstress_LDADD) $(LIBS) + +gstpollstress$(EXEEXT): $(gstpollstress_OBJECTS) $(gstpollstress_DEPENDENCIES) $(EXTRA_gstpollstress_DEPENDENCIES) + @rm -f gstpollstress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gstpollstress_OBJECTS) $(gstpollstress_LDADD) $(LIBS) + +gstpoolstress$(EXEEXT): $(gstpoolstress_OBJECTS) $(gstpoolstress_DEPENDENCIES) $(EXTRA_gstpoolstress_DEPENDENCIES) + @rm -f gstpoolstress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gstpoolstress_OBJECTS) $(gstpoolstress_LDADD) $(LIBS) + +init$(EXEEXT): $(init_OBJECTS) $(init_DEPENDENCIES) $(EXTRA_init_DEPENDENCIES) + @rm -f init$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(init_OBJECTS) $(init_LDADD) $(LIBS) + +mass-elements$(EXEEXT): $(mass_elements_OBJECTS) $(mass_elements_DEPENDENCIES) $(EXTRA_mass_elements_DEPENDENCIES) + @rm -f mass-elements$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mass_elements_OBJECTS) $(mass_elements_LDADD) $(LIBS) + +tracerserialize$(EXEEXT): $(tracerserialize_OBJECTS) $(tracerserialize_DEPENDENCIES) $(EXTRA_tracerserialize_DEPENDENCIES) + @rm -f tracerserialize$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tracerserialize_OBJECTS) $(tracerserialize_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caps.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/capsnego.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/complexity.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller-controller.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstbufferstress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstclockstress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstpollstress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstpoolstress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mass-elements.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tracerserialize.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +controller-controller.o: controller.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_CFLAGS) $(CFLAGS) -MT controller-controller.o -MD -MP -MF $(DEPDIR)/controller-controller.Tpo -c -o controller-controller.o `test -f 'controller.c' || echo '$(srcdir)/'`controller.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/controller-controller.Tpo $(DEPDIR)/controller-controller.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='controller.c' object='controller-controller.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_CFLAGS) $(CFLAGS) -c -o controller-controller.o `test -f 'controller.c' || echo '$(srcdir)/'`controller.c + +controller-controller.obj: controller.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_CFLAGS) $(CFLAGS) -MT controller-controller.obj -MD -MP -MF $(DEPDIR)/controller-controller.Tpo -c -o controller-controller.obj `if test -f 'controller.c'; then $(CYGPATH_W) 'controller.c'; else $(CYGPATH_W) '$(srcdir)/controller.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/controller-controller.Tpo $(DEPDIR)/controller-controller.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='controller.c' object='controller-controller.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_CFLAGS) $(CFLAGS) -c -o controller-controller.obj `if test -f 'controller.c'; then $(CYGPATH_W) 'controller.c'; else $(CYGPATH_W) '$(srcdir)/controller.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/benchmarks/caps.c b/tests/benchmarks/caps.c new file mode 100644 index 0000000..d5c2101 --- /dev/null +++ b/tests/benchmarks/caps.c @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * caps.c: benchmark for caps creation and destruction + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include + + +#define NUM_CAPS 10000 + +#define AUDIO_FORMATS_ALL " { S8, U8, " \ + "S16LE, S16BE, U16LE, U16BE, " \ + "S24_32LE, S24_32BE, U24_32LE, U24_32BE, " \ + "S32LE, S32BE, U32LE, U32BE, " \ + "S24LE, S24BE, U24LE, U24BE, " \ + "S20LE, S20BE, U20LE, U20BE, " \ + "S18LE, S18BE, U18LE, U18BE, " \ + "F32LE, F32BE, F64LE, F64BE }" + +#define GST_AUDIO_INT_PAD_TEMPLATE_CAPS \ + "audio/x-raw, " \ + "format = (string) " AUDIO_FORMATS_ALL ", " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ]" + + +gint +main (gint argc, gchar * argv[]) +{ + GstCaps **capses; + GstCaps *protocaps; + GstClockTime start, end; + gint i; + + gst_init (&argc, &argv); + + protocaps = gst_caps_from_string (GST_AUDIO_INT_PAD_TEMPLATE_CAPS); + + start = gst_util_get_timestamp (); + capses = g_new (GstCaps *, NUM_CAPS); + for (i = 0; i < NUM_CAPS; i++) + capses[i] = gst_caps_copy (protocaps); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - creating %d caps\n", + GST_TIME_ARGS (end - start), i); + + start = gst_util_get_timestamp (); + for (i = 0; i < NUM_CAPS; i++) + gst_caps_unref (capses[i]); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - destroying %d caps\n", + GST_TIME_ARGS (end - start), i); + + g_free (capses); + gst_caps_unref (protocaps); + + return 0; +} diff --git a/tests/benchmarks/capsnego.c b/tests/benchmarks/capsnego.c new file mode 100644 index 0000000..5a7a390 --- /dev/null +++ b/tests/benchmarks/capsnego.c @@ -0,0 +1,269 @@ +/* GStreamer + * Copyright (C) 2010 Stefan Kost + * + * capsnego.c: benchmark for caps negotiation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* This benchmark recursively builds a pipeline and measures the time to go + * from READY to PAUSED state. + * + * The graph size and type can be controlled with a few command line options: + * + * -d depth: is the depth of the tree + * -c children: is the number of branches on each level + * -f : can be "audio" or "video" and is controlling the kind of + * elements that are used. + */ + +#include +#include +#include + +enum +{ + FLAVOUR_AUDIO = 0, + FLAVOUR_VIDEO, + NUM_FLAVOURS +}; + +enum +{ + ELEM_SRC = 0, + ELEM_MIX, + ELEM_PROC, + ELEM_CONV, + NUM_ELEM +}; + +static const gchar *factories[NUM_FLAVOURS][NUM_ELEM] = { + {"audiotestsrc", "adder", "volume", "audioconvert"}, + {"videotestsrc", "videomixer", "videoscale", "videoconvert"} +}; + +static const gchar *sink_pads[NUM_FLAVOURS][NUM_ELEM] = { + {NULL, "sink_%u", NULL, NULL}, + {NULL, "sink_%u", NULL, NULL} +}; + + +static gboolean +create_node (GstBin * bin, GstElement * sink, const gchar * sinkpadname, + GstElement ** new_sink, gint children, gint flavour) +{ + GstElement *mix, *proc, *conv; + + if (children >= 1) { + mix = gst_element_factory_make (factories[flavour][ELEM_MIX], NULL); + if (!mix) { + GST_WARNING ("need element '%s'", factories[flavour][ELEM_MIX]); + return FALSE; + } + } else { + mix = gst_element_factory_make ("identity", NULL); + } + proc = gst_element_factory_make (factories[flavour][ELEM_PROC], NULL); + if (!proc) { + GST_WARNING ("need element '%s'", factories[flavour][ELEM_PROC]); + return FALSE; + } + conv = gst_element_factory_make (factories[flavour][ELEM_CONV], NULL); + if (!conv) { + GST_WARNING ("need element '%s'", factories[flavour][ELEM_CONV]); + return FALSE; + } + gst_bin_add_many (bin, mix, proc, conv, NULL); + if (!gst_element_link_pads_full (mix, "src", proc, "sink", + GST_PAD_LINK_CHECK_NOTHING) + || !gst_element_link_pads_full (proc, "src", conv, "sink", + GST_PAD_LINK_CHECK_NOTHING) + || !gst_element_link_pads_full (conv, "src", sink, sinkpadname, + GST_PAD_LINK_CHECK_NOTHING)) { + GST_WARNING ("can't link elements"); + return FALSE; + } + *new_sink = mix; + return TRUE; +} + +static gboolean +create_nodes (GstBin * bin, GstElement * sink, gint depth, gint children, + gint flavour) +{ + GstElement *new_sink, *src; + gint i; + + for (i = 0; i < children; i++) { + if (depth > 0) { + if (!create_node (bin, sink, sink_pads[flavour][ELEM_MIX], &new_sink, + children, flavour)) { + return FALSE; + } + if (!create_nodes (bin, new_sink, depth - 1, children, flavour)) { + return FALSE; + } + } else { + src = gst_element_factory_make (factories[flavour][ELEM_SRC], NULL); + if (!src) { + GST_WARNING ("need element '%s'", factories[flavour][ELEM_SRC]); + return FALSE; + } + gst_bin_add (bin, src); + if (!gst_element_link_pads_full (src, "src", sink, + sink_pads[flavour][ELEM_MIX], GST_PAD_LINK_CHECK_NOTHING)) { + GST_WARNING ("can't link elements"); + return FALSE; + } + } + } + return TRUE; +} + +static void +event_loop (GstElement * bin) +{ + GstBus *bus; + GstMessage *msg = NULL; + gboolean running = TRUE; + + bus = gst_element_get_bus (bin); + + while (running) { + msg = gst_bus_poll (bus, + GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING, -1); + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ASYNC_DONE: + running = FALSE; + break; + case GST_MESSAGE_WARNING:{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_warning (msg, &err, &dbg); + GST_WARNING_OBJECT (GST_MESSAGE_SRC (msg), "%s (%s)", err->message, + (dbg ? dbg : "no details")); + g_clear_error (&err); + g_free (dbg); + break; + } + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_error (msg, &err, &dbg); + GST_ERROR_OBJECT (GST_MESSAGE_SRC (msg), "%s (%s)", err->message, + (dbg ? dbg : "no details")); + g_clear_error (&err); + g_free (dbg); + running = FALSE; + break; + } + default: + break; + } + gst_message_unref (msg); + } + gst_object_unref (bus); +} + +gint +main (gint argc, gchar * argv[]) +{ + /* default parameters */ + gchar *flavour_str = g_strdup("audio"); + gint flavour = FLAVOUR_AUDIO; + gint children = 3; + gint depth = 4; + gint loops = 50; + + GOptionContext *ctx; + GOptionEntry options[] = { + {"children", 'c', 0, G_OPTION_ARG_INT, &children, + "Number of children (branches on each level) (default: 3)", NULL}, + {"depth", 'd', 0, G_OPTION_ARG_INT, &depth, + "Depth of pipeline hierarchy tree (default: 4)", NULL}, + {"flavour", 'f', 0, G_OPTION_ARG_STRING, &flavour_str, + "Flavour (video|audio) controlling the kind of elements used " + "(default: audio)", NULL}, + {"loops", 'l', 0, G_OPTION_ARG_INT, &loops, + "How many loops to run (default: 50)", NULL}, + {NULL} + }; + GError *err = NULL; + GstBin *bin; + GstClockTime start, end; + GstElement *sink, *new_sink; + gint i; + + g_set_prgname ("capsnego"); + + /* check command line options */ + ctx = g_option_context_new (""); + 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)); + g_clear_error (&err); + g_option_context_free (ctx); + return 1; + } + g_option_context_free (ctx); + + if (strcmp (flavour_str, "video") == 0) + flavour = FLAVOUR_VIDEO; + + /* build pipeline */ + g_print ("building %s pipeline with depth = %d and children = %d\n", + flavour_str, depth, children); + g_free (flavour_str); + + start = gst_util_get_timestamp (); + bin = GST_BIN (gst_pipeline_new ("pipeline")); + sink = gst_element_factory_make ("fakesink", NULL); + gst_bin_add (bin, sink); + if (!create_node (bin, sink, "sink", &new_sink, children, flavour)) { + goto Error; + } + if (!create_nodes (bin, new_sink, depth, children, flavour)) { + goto Error; + } + end = gst_util_get_timestamp (); + /* num-threads = num-sources = pow (children, depth) */ + g_print ("%" GST_TIME_FORMAT " built pipeline with %d elements\n", + GST_TIME_ARGS (end - start), GST_BIN_NUMCHILDREN (bin)); + + /* measure */ + g_print ("starting pipeline\n"); + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + GST_DEBUG_BIN_TO_DOT_FILE (bin, GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE, "capsnego"); + + start = gst_util_get_timestamp (); + for (i = 0; i < loops; ++i) { + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + event_loop (GST_ELEMENT (bin)); + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + } + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " reached PAUSED state (%d loop iterations)\n", + GST_TIME_ARGS (end - start), loops); + /* clean up */ +Error: + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + gst_object_unref (bin); + return 0; +} diff --git a/tests/benchmarks/complexity.c b/tests/benchmarks/complexity.c new file mode 100644 index 0000000..2cf1dc8 --- /dev/null +++ b/tests/benchmarks/complexity.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2004 Benjamin Otte + * Copyright (C) 2005 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#define BUFFER_COUNT (1000) + +gint +main (gint argc, gchar * argv[]) +{ + GstMessage *msg; + GstElement *pipeline, *src, *e; + GSList *saved_src_list, *src_list, *new_src_list; + guint complexity_order, n_elements, i, j, max_this_level; + GstClockTime start, end; + + gst_init (&argc, &argv); + + if (argc != 3) { + g_print ("Usage: %s COMPLEXITY_ORDER N_ELEMENTS\n", argv[0]); + return 1; + } + + complexity_order = atoi (argv[1]); + n_elements = atoi (argv[2]); + + start = gst_util_get_timestamp (); + + pipeline = gst_element_factory_make ("pipeline", NULL); + g_assert (pipeline); + + e = gst_element_factory_make ("fakesrc", NULL); + g_object_set (e, "num-buffers", BUFFER_COUNT, NULL); + g_object_set (e, "silent", TRUE, NULL); + gst_bin_add (GST_BIN (pipeline), e); + src_list = saved_src_list = g_slist_append (NULL, e); + + new_src_list = NULL; + + max_this_level = 1; + for (i = 0, j = 0; i < n_elements; i++, j++) { + if (j >= max_this_level) { + g_slist_free (saved_src_list); + saved_src_list = g_slist_reverse (new_src_list); + new_src_list = NULL; + j = 0; + max_this_level *= complexity_order; + } + + if (!src_list) { + src_list = saved_src_list; + } + + src = (GstElement *) src_list->data; + src_list = src_list->next; + + if (i + max_this_level < n_elements) { + e = gst_element_factory_make ("tee", NULL); + } else { + e = gst_element_factory_make ("fakesink", NULL); + g_object_set (e, "async", FALSE, NULL); + } + g_object_set (e, "silent", TRUE, NULL); + new_src_list = g_slist_prepend (new_src_list, e); + + gst_bin_add (GST_BIN (pipeline), e); + if (!gst_element_link (src, e)) + g_assert_not_reached (); + } + + g_slist_free (saved_src_list); + g_slist_free (new_src_list); + + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - creating and linking %u elements\n", + GST_TIME_ARGS (end - start), i); + + start = gst_util_get_timestamp (); + if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) + g_assert_not_reached (); + if (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) + g_assert_not_reached (); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to playing\n", + GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + msg = gst_bus_poll (gst_element_get_bus (pipeline), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + end = gst_util_get_timestamp (); + gst_message_unref (msg); + g_print ("%" GST_TIME_FORMAT " - putting %d buffers through\n", + GST_TIME_ARGS (end - start), BUFFER_COUNT); + + start = gst_util_get_timestamp (); + if (gst_element_set_state (pipeline, + GST_STATE_NULL) != GST_STATE_CHANGE_SUCCESS) + g_assert_not_reached (); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to NULL\n", + GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + g_object_unref (pipeline); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n", + GST_TIME_ARGS (end - start)); + + return 0; +} diff --git a/tests/benchmarks/controller.c b/tests/benchmarks/controller.c new file mode 100644 index 0000000..13012ec --- /dev/null +++ b/tests/benchmarks/controller.c @@ -0,0 +1,189 @@ +/* GStreamer + * Copyright (C) 2009 Stefan Kost + * + * controller.c: benchmark for interpolation control-source + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include + +/* a song in buzztard can easily reach 30000 here */ +#define NUM_CP 15000 +#define BLOCK_SIZE 64 + +static void +event_loop (GstElement * pipe) +{ + GstBus *bus; + GstMessage *message = NULL; + gboolean running = TRUE; + + bus = gst_element_get_bus (GST_ELEMENT (pipe)); + + while (running) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); + + g_assert (message != NULL); + + switch (message->type) { + case GST_MESSAGE_EOS: + running = FALSE; + 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); + running = FALSE; + break; + } + default: + break; + } + gst_message_unref (message); + } + gst_object_unref (bus); +} + +gint +main (gint argc, gchar * argv[]) +{ + gint res = 1; + gint i, j; + GstElement *src, *sink; + GstElement *bin; + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstClockTime bt, ct; + GstClockTimeDiff elapsed; + GstClockTime tick; + + gst_init (&argc, &argv); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("audiotestsrc", "gen_audio"); + if (!src) { + GST_WARNING ("need audiotestsrc from gst-plugins-base"); + goto Error; + } + sink = gst_element_factory_make ("fakesink", "swallow_audio"); + + gst_bin_add_many (GST_BIN (bin), src, sink, NULL); + if (!gst_element_link (src, sink)) { + GST_WARNING ("can't link elements"); + goto Error; + } + + g_object_set (G_OBJECT (src), "wave", 7, /* sine table - we don't want to benchmark the fpu */ + "num-buffers", NUM_CP, "samplesperbuffer", BLOCK_SIZE, NULL); + + tick = BLOCK_SIZE * GST_SECOND / 44100; + + /* create and configure control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + gst_object_add_control_binding (GST_OBJECT (src), + gst_direct_control_binding_new (GST_OBJECT (src), "freq", cs)); + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values, we set them in a linear order as we would when loading + * a stored project + */ + bt = gst_util_get_timestamp (); + + for (i = 0; i < NUM_CP; i++) { + gst_timed_value_control_source_set (tvcs, i * tick, + g_random_double_range (50.0, 3000.0)); + } + + ct = gst_util_get_timestamp (); + elapsed = GST_CLOCK_DIFF (bt, ct); + printf ("linear insert of control-points: %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (elapsed)); + + + /* set extra control values, we set them in arbitrary order to simulate + * the user editing a project from the ui + */ + bt = gst_util_get_timestamp (); + + for (i = 0; i < 100; i++) { + j = g_random_int_range (0, NUM_CP - 1); + gst_timed_value_control_source_set (tvcs, j * tick, + g_random_double_range (50.0, 3000.0)); + } + + ct = gst_util_get_timestamp (); + elapsed = GST_CLOCK_DIFF (bt, ct); + printf ("random insert of control-points: %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (elapsed)); + + { + GstClockTime sample_duration = + gst_util_uint64_scale_int (1, GST_SECOND, 44100); + gdouble *values = g_new0 (gdouble, BLOCK_SIZE * NUM_CP); + + bt = gst_util_get_timestamp (); + gst_control_source_get_value_array (cs, 0, sample_duration, + BLOCK_SIZE * NUM_CP, values); + ct = gst_util_get_timestamp (); + g_free (values); + elapsed = GST_CLOCK_DIFF (bt, ct); + printf ("linear array for control-points: %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (elapsed)); + } + + /* play, this test sequential reads */ + bt = gst_util_get_timestamp (); + + if (gst_element_set_state (bin, GST_STATE_PLAYING)) { + /* wait for EOS */ + event_loop (bin); + gst_element_set_state (bin, GST_STATE_NULL); + } + + ct = gst_util_get_timestamp (); + elapsed = GST_CLOCK_DIFF (bt, ct); + printf ("linear read of control-points : %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (elapsed)); + + /* cleanup */ + gst_object_unref (cs); + gst_object_unref (bin); + res = 0; +Error: + return res; +} diff --git a/tests/benchmarks/gstbufferstress.c b/tests/benchmarks/gstbufferstress.c new file mode 100644 index 0000000..c9a4ac1 --- /dev/null +++ b/tests/benchmarks/gstbufferstress.c @@ -0,0 +1,129 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "gst/glib-compat-private.h" + +#define MAX_THREADS 1000 + +static guint64 nbbuffers; +static GMutex mutex; + + +static void * +run_test (void *user_data) +{ + gint threadid = GPOINTER_TO_INT (user_data); + guint64 nb; + GstBuffer *buf; + GstClockTime start, end; + + g_mutex_lock (&mutex); + g_mutex_unlock (&mutex); + + start = gst_util_get_timestamp (); + + g_assert (nbbuffers > 0); + + for (nb = nbbuffers; nb; nb--) { + buf = gst_buffer_new (); + gst_buffer_unref (buf); + } + + end = gst_util_get_timestamp (); + g_print ("total %" GST_TIME_FORMAT " - average %" GST_TIME_FORMAT + " - Thread %d\n", GST_TIME_ARGS (end - start), + GST_TIME_ARGS ((end - start) / nbbuffers), threadid); + + + g_thread_exit (NULL); + return NULL; +} + +gint +main (gint argc, gchar * argv[]) +{ + GThread *threads[MAX_THREADS]; + gint num_threads; + gint t; + GstBuffer *tmp; + GstClockTime start, end; + + gst_init (&argc, &argv); + g_mutex_init (&mutex); + + if (argc != 3) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + num_threads = atoi (argv[1]); + nbbuffers = atoi (argv[2]); + + if (num_threads <= 0 || num_threads > MAX_THREADS) { + g_print ("number of threads must be between 0 and %d\n", MAX_THREADS); + exit (-2); + } + + if (nbbuffers <= 0) { + g_print ("number of buffers must be greater than 0\n"); + exit (-3); + } + + g_mutex_lock (&mutex); + /* Let's just make sure the GstBufferClass is loaded ... */ + tmp = gst_buffer_new (); + + printf ("main(): Creating %d threads.\n", num_threads); + for (t = 0; t < num_threads; t++) { + GError *error = NULL; + + threads[t] = g_thread_try_new ("bufferstresstest", run_test, + GINT_TO_POINTER (t), &error); + + if (error) { + printf ("ERROR: g_thread_try_new() %s\n", error->message); + g_clear_error (&error); + exit (-1); + } + } + + /* Signal all threads to start */ + start = gst_util_get_timestamp (); + g_mutex_unlock (&mutex); + + for (t = 0; t < num_threads; t++) { + if (threads[t]) + g_thread_join (threads[t]); + } + + end = gst_util_get_timestamp (); + g_print ("*** total %" GST_TIME_FORMAT " - average %" GST_TIME_FORMAT + " - Done creating %" G_GUINT64_FORMAT " buffers\n", + GST_TIME_ARGS (end - start), + GST_TIME_ARGS ((end - start) / (num_threads * nbbuffers)), + num_threads * nbbuffers); + + + gst_buffer_unref (tmp); + + return 0; +} diff --git a/tests/benchmarks/gstclockstress.c b/tests/benchmarks/gstclockstress.c new file mode 100644 index 0000000..0d30900 --- /dev/null +++ b/tests/benchmarks/gstclockstress.c @@ -0,0 +1,100 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#define MAX_THREADS 100 + +static gboolean running = TRUE; +static gint count = 0; + +static void * +run_test (void *user_data) +{ + gint prev; + GstClock *sysclock = GST_CLOCK_CAST (user_data); + + while (running) { + gst_clock_get_time (sysclock); + prev = g_atomic_int_add (&count, 1); + if (prev == G_MAXINT) + g_warning ("overflow"); + } + g_thread_exit (NULL); + return NULL; +} + +gint +main (gint argc, gchar * argv[]) +{ + GThread *threads[MAX_THREADS]; + gint num_threads; + gint t; + GstClock *sysclock; + + gst_init (&argc, &argv); + + if (argc != 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + num_threads = atoi (argv[1]); + + if (num_threads <= 0 || num_threads > MAX_THREADS) { + g_print ("number of threads must be between 0 and %d\n", MAX_THREADS); + exit (-2); + } + + sysclock = gst_system_clock_obtain (); + + for (t = 0; t < num_threads; t++) { + GError *error = NULL; + + threads[t] = g_thread_try_new ("clockstresstest", run_test, + sysclock, &error); + + if (error) { + printf ("ERROR: g_thread_try_new() %s\n", error->message); + g_clear_error (&error); + exit (-1); + } + } + printf ("main(): Created %d threads.\n", t); + + /* run for 5 seconds */ + g_usleep (G_USEC_PER_SEC * 5); + + printf ("main(): Stopping threads...\n"); + + running = FALSE; + + for (t = 0; t < num_threads; t++) { + g_thread_join (threads[t]); + } + + g_print ("performed %d get_time operations\n", count); + + gst_object_unref (sysclock); + + return 0; +} diff --git a/tests/benchmarks/gstpollstress.c b/tests/benchmarks/gstpollstress.c new file mode 100644 index 0000000..fcfed15 --- /dev/null +++ b/tests/benchmarks/gstpollstress.c @@ -0,0 +1,181 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "gst/glib-compat-private.h" + +static GstPoll *set; +static GList *fds = NULL; +static GMutex fdlock; +static GTimer *timer; + +#define MAX_THREADS 100 + +static void +mess_some_more (void) +{ + GList *walk; + gint random; + gint removed = 0; + + g_mutex_lock (&fdlock); + + for (walk = fds; walk;) { + GstPollFD *fd = (GstPollFD *) walk->data; + + walk = g_list_next (walk); + + random = (gint) (10.0 * rand () / (RAND_MAX + 1.0)); + switch (random) { + case 0: + { + /* + GstPollFD *newfd = g_new0 (GstPollFD, 1); + + gst_poll_add_fd (set, newfd); + fds = g_list_prepend (fds, newfd); + */ + break; + } + case 1: + if ((gint) (10.0 * rand () / (RAND_MAX + 1.0)) < 2) { + gst_poll_remove_fd (set, fd); + fds = g_list_remove (fds, fd); + g_free (fd); + removed++; + } + break; + + case 2: + gst_poll_fd_ctl_write (set, fd, TRUE); + break; + case 3: + gst_poll_fd_ctl_write (set, fd, FALSE); + break; + case 4: + gst_poll_fd_ctl_read (set, fd, TRUE); + break; + case 5: + gst_poll_fd_ctl_read (set, fd, FALSE); + break; + + case 6: + gst_poll_fd_has_closed (set, fd); + break; + case 7: + gst_poll_fd_has_error (set, fd); + break; + case 8: + gst_poll_fd_can_read (set, fd); + break; + case 9: + gst_poll_fd_can_write (set, fd); + break; + default: + g_assert_not_reached (); + break; + } + } + if (g_list_length (fds) < 900) { + random = removed + (gint) (2.0 * rand () / (RAND_MAX + 1.0)); + while (random) { + GstPollFD *newfd = g_new0 (GstPollFD, 1); + + gst_poll_add_fd (set, newfd); + fds = g_list_prepend (fds, newfd); + random--; + } + } + + g_mutex_unlock (&fdlock); +} + +static void * +run_test (void *threadid) +{ + gint id = GPOINTER_TO_INT (threadid); + + while (TRUE) { + if (id == 0) { + gint res = gst_poll_wait (set, 10); + + if (res < 0) { + g_print ("error %d %s\n", errno, g_strerror (errno)); + } + } else { + mess_some_more (); + if (g_timer_elapsed (timer, NULL) > 0.5) { + g_mutex_lock (&fdlock); + g_print ("active fds :%u\n", g_list_length (fds)); + g_timer_start (timer); + g_mutex_unlock (&fdlock); + } + g_usleep (1); + } + } + + return NULL; +} + +gint +main (gint argc, gchar * argv[]) +{ + GThread *threads[MAX_THREADS]; + gint num_threads; + gint t; + + gst_init (&argc, &argv); + + g_mutex_init (&fdlock); + timer = g_timer_new (); + + if (argc != 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + num_threads = atoi (argv[1]); + + set = gst_poll_new (TRUE); + + for (t = 0; t < num_threads; t++) { + GError *error = NULL; + + threads[t] = g_thread_try_new ("pollstresstest", run_test, + GINT_TO_POINTER (t), &error); + + if (error) { + printf ("ERROR: g_thread_try_new() %s\n", error->message); + g_clear_error (&error); + exit (-1); + } + } + printf ("main(): Created %d threads.\n", t); + + for (t = 0; t < num_threads; t++) { + g_thread_join (threads[t]); + } + + gst_poll_free (set); + + return 0; +} diff --git a/tests/benchmarks/gstpoolstress.c b/tests/benchmarks/gstpoolstress.c new file mode 100644 index 0000000..dc615c0 --- /dev/null +++ b/tests/benchmarks/gstpoolstress.c @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) <2013> 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "gst/glib-compat-private.h" + +#define BUFFER_SIZE (1400) + +gint +main (gint argc, gchar * argv[]) +{ + gint i; + GstBuffer *tmp; + GstBufferPool *pool; + GstClockTime start, end; + GstClockTimeDiff dur1, dur2; + guint64 nbuffers; + GstStructure *conf; + + gst_init (&argc, &argv); + + if (argc != 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + nbuffers = atoi (argv[1]); + + if (nbuffers <= 0) { + g_print ("number of buffers must be greater than 0\n"); + exit (-3); + } + + /* Let's just make sure the GstBufferClass is loaded ... */ + tmp = gst_buffer_new (); + gst_buffer_unref (tmp); + + pool = gst_buffer_pool_new (); + + conf = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (conf, NULL, BUFFER_SIZE, 0, 0); + gst_buffer_pool_set_config (pool, conf); + + gst_buffer_pool_set_active (pool, TRUE); + + /* allocate buffers directly */ + start = gst_util_get_timestamp (); + for (i = 0; i < nbuffers; i++) { + tmp = gst_buffer_new_allocate (NULL, BUFFER_SIZE, NULL); + gst_buffer_unref (tmp); + } + end = gst_util_get_timestamp (); + dur1 = GST_CLOCK_DIFF (start, end); + g_print ("*** total %" GST_TIME_FORMAT " - average %" GST_TIME_FORMAT + " - Done creating %" G_GUINT64_FORMAT " fresh buffers\n", + GST_TIME_ARGS (dur1), GST_TIME_ARGS (dur1 / nbuffers), nbuffers); + + /* allocate buffers from the pool */ + start = gst_util_get_timestamp (); + for (i = 0; i < nbuffers; i++) { + gst_buffer_pool_acquire_buffer (pool, &tmp, NULL); + gst_buffer_unref (tmp); + } + end = gst_util_get_timestamp (); + dur2 = GST_CLOCK_DIFF (start, end); + g_print ("*** total %" GST_TIME_FORMAT " - average %" GST_TIME_FORMAT + " - Done creating %" G_GUINT64_FORMAT " pooled buffers\n", + GST_TIME_ARGS (dur2), GST_TIME_ARGS (dur2 / nbuffers), nbuffers); + + g_print ("*** speedup %6.4lf\n", ((gdouble) dur1 / (gdouble) dur2)); + + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + + return 0; +} diff --git a/tests/benchmarks/init.c b/tests/benchmarks/init.c new file mode 100644 index 0000000..3126a2c --- /dev/null +++ b/tests/benchmarks/init.c @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) 2006 Stefan Kost + * + * init.c: benchmark gst 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include + +gint +main (gint argc, gchar * argv[]) +{ + gst_init (&argc, &argv); + + return 0; +} diff --git a/tests/benchmarks/mass-elements.c b/tests/benchmarks/mass-elements.c new file mode 100644 index 0000000..cfe6c85 --- /dev/null +++ b/tests/benchmarks/mass-elements.c @@ -0,0 +1,118 @@ +/* + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#define IDENTITY_COUNT (1000) +#define BUFFER_COUNT (1000) +#define SRC_ELEMENT "fakesrc" +#define SINK_ELEMENT "fakesink" + + +gint +main (gint argc, gchar * argv[]) +{ + GstMessage *msg; + GstElement *pipeline, *src, *sink, *current, *last; + guint i, buffers = BUFFER_COUNT, identities = IDENTITY_COUNT; + GstClockTime start, end; + const gchar *src_name = SRC_ELEMENT, *sink_name = SINK_ELEMENT; + + gst_init (&argc, &argv); + + if (argc > 1) + identities = atoi (argv[1]); + if (argc > 2) + buffers = atoi (argv[2]); + if (argc > 3) + src_name = argv[3]; + if (argc > 4) + sink_name = argv[4]; + + g_print + ("*** benchmarking this pipeline: %s num-buffers=%u ! %u * identity ! %s\n", + src_name, buffers, identities, sink_name); + start = gst_util_get_timestamp (); + pipeline = gst_element_factory_make ("pipeline", NULL); + g_assert (pipeline); + src = gst_element_factory_make (src_name, NULL); + if (!src) { + g_print ("no element named \"%s\" found, aborting...\n", src_name); + return 1; + } + g_object_set (src, "num-buffers", buffers, NULL); + sink = gst_element_factory_make (sink_name, NULL); + if (!sink) { + g_print ("no element named \"%s\" found, aborting...\n", sink_name); + return 1; + } + last = src; + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + for (i = 0; i < identities; i++) { + current = gst_element_factory_make ("identity", NULL); + g_assert (current); + /* shut this element up (no g_strdup_printf please) */ + g_object_set (current, "silent", TRUE, NULL); + gst_bin_add (GST_BIN (pipeline), current); + if (!gst_element_link (last, current)) + g_assert_not_reached (); + last = current; + } + if (!gst_element_link (last, sink)) + g_assert_not_reached (); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - creating %u identity elements\n", + GST_TIME_ARGS (end - start), identities); + + start = gst_util_get_timestamp (); + if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) + g_assert_not_reached (); + if (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) + g_assert_not_reached (); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to playing\n", + GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + msg = gst_bus_poll (gst_element_get_bus (pipeline), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + end = gst_util_get_timestamp (); + gst_message_unref (msg); + g_print ("%" GST_TIME_FORMAT " - putting %u buffers through\n", + GST_TIME_ARGS (end - start), buffers); + + start = gst_util_get_timestamp (); + if (gst_element_set_state (pipeline, + GST_STATE_NULL) != GST_STATE_CHANGE_SUCCESS) + g_assert_not_reached (); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to NULL\n", + GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + g_object_unref (pipeline); + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n", + GST_TIME_ARGS (end - start)); + + return 0; +} diff --git a/tests/benchmarks/meson.build b/tests/benchmarks/meson.build new file mode 100644 index 0000000..0ed4808 --- /dev/null +++ b/tests/benchmarks/meson.build @@ -0,0 +1,20 @@ +benchmarks = [ + 'caps', + 'capsnego', + 'complexity', + 'controller', + 'init', + 'mass-elements', + 'gstpollstress', + 'gstpoolstress', + 'gstclockstress', + 'gstbufferstress', +] + +foreach b : benchmarks + executable(b, '@0@.c'.format(b), + c_args : gst_c_args, + link_with : [printf_lib], + dependencies : [gobject_dep, gmodule_dep, glib_dep, gst_dep, gst_controller_dep], + ) +endforeach diff --git a/tests/benchmarks/tracerserialize.c b/tests/benchmarks/tracerserialize.c new file mode 100644 index 0000000..168d177 --- /dev/null +++ b/tests/benchmarks/tracerserialize.c @@ -0,0 +1,119 @@ +/* GStreamer + * Copyright (C) 2016 Stefan Sauer + * + * tracerserialize.c: benchmark for log serialisation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITcreating %d capsNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* to check the sizes run: + * + * GST_DEBUG="default:7" GST_DEBUG_FILE=trace.log ./tracerserialize + * + * grep "log_gst_structure" trace.log >tracerserialize.gststructure.log + * grep "log_g_variant" trace.log >tracerserialize.gvariant.log + * + */ + +#include + +#define NUM_LOOPS 100000 + +static void +log_gst_structure (const gchar * name, const gchar * first, ...) +{ + va_list var_args; + GstStructure *s; + gchar *l; + + va_start (var_args, first); + s = gst_structure_new_valist (name, first, var_args); + l = gst_structure_to_string (s); + GST_TRACE ("%s", l); + g_free (l); + gst_structure_free (s); + va_end (var_args); +} + +static void +log_gst_structure_tmpl (const gchar * format, ...) +{ + va_list var_args; + + va_start (var_args, format); + if (G_LIKELY (GST_LEVEL_TRACE <= _gst_debug_min)) { + gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_TRACE, __FILE__, + GST_FUNCTION, __LINE__, NULL, format, var_args); + } + va_end (var_args); +} + +static void +log_g_variant (const gchar * format, ...) +{ + va_list var_args; + GVariant *v; + gchar *l; + + va_start (var_args, format); + v = g_variant_new_va (format, NULL, &var_args); + l = g_variant_print (v, FALSE); + GST_TRACE ("%s", l); + g_free (l); + g_variant_unref (v); + va_end (var_args); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstClockTime start, end; + gint i; + + gst_init (&argc, &argv); + + start = gst_util_get_timestamp (); + for (i = 0; i < NUM_LOOPS; i++) { + log_gst_structure ("name", + "ts", G_TYPE_UINT64, (guint64) 0, + "index", G_TYPE_UINT, 10, + "test", G_TYPE_STRING, "hallo", + "bool", G_TYPE_BOOLEAN, TRUE, + "flag", GST_TYPE_PAD_DIRECTION, GST_PAD_SRC, NULL); + } + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT ": GstStructure\n", GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + for (i = 0; i < NUM_LOOPS; i++) { + log_gst_structure_tmpl ("name, ts=(guint64)%" G_GUINT64_FORMAT + ", index=(uint)%u, test=(string)%s, bool=(boolean)%s, flag=(GstPadDirection)%d;", + (guint64) 0, 10, "hallo", (TRUE ? "true" : "false"), GST_PAD_SRC); + } + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT ": GstStructure template\n", + GST_TIME_ARGS (end - start)); + + start = gst_util_get_timestamp (); + for (i = 0; i < NUM_LOOPS; i++) { + log_g_variant ("(stusbu)", "name", (guint64) 0, 10, "hallo", TRUE, + GST_PAD_SRC); + } + end = gst_util_get_timestamp (); + g_print ("%" GST_TIME_FORMAT ": GVariant\n", GST_TIME_ARGS (end - start)); + + return 0; +} diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am new file mode 100644 index 0000000..13b916d --- /dev/null +++ b/tests/check/Makefile.am @@ -0,0 +1,312 @@ +include $(top_srcdir)/common/check.mak + +CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg + +GST_TOOLS_DIR = $(top_builddir)/tools + +REGISTRY_ENVIRONMENT = \ + GST_REGISTRY=$(CHECK_REGISTRY) + +AM_TESTS_ENVIRONMENT += \ + GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \ + $(REGISTRY_ENVIRONMENT) \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner \ + GST_PLUGIN_SYSTEM_PATH_1_0= \ + GST_PLUGIN_PATH_1_0=$(top_builddir)/plugins + +plugindir = $(libdir)/gstreamer-@GST_API_VERSION@ + +# override to _not_ install the test plugins +install-pluginLTLIBRARIES: + +# the core dumps of some machines have PIDs appended, test registry and +# profiling data +CLEANFILES = core core.* test-registry.* *.gcno *.gcda + +SUPPRESSIONS = $(top_srcdir)/common/gst.supp + +clean-local: clean-local-check + +# These tests don't even build any longer: +# gst/gstindex.c + +if GST_DISABLE_PARSE +PARSE_CHECKS = pipelines/parse-disabled +else +PARSE_CHECKS = pipelines/simple-launch-lines pipelines/cleanup pipelines/parse-launch +endif + +# Do not run the abi test in case any option which causes the API to change has +# been used +if !GST_DISABLE_REGISTRY +ABI_CHECKS = gst/gstabi +endif + +if !GST_DISABLE_GST_DEBUG +PRINTF_CHECKS = gst/gstprintf +else +PRINTF_CHECKS = +endif + +LIBSABI_CHECKS = libs/libsabi + +if HAVE_CXX +CXX_CHECKS = gst/gstcpp libs/gstlibscpp +else +CXX_CHECKS = +endif + +# if it's calling gst_element_factory_make(), it will probably not work without +# a registry +if GST_DISABLE_REGISTRY +REGISTRY_CHECKS = +else +REGISTRY_CHECKS = \ + gst/gst \ + gst/gstbin \ + gst/gstchildproxy \ + gst/gstcontext \ + gst/gstcontroller \ + gst/gstelement \ + gst/gstelementfactory \ + gst/gstevent \ + gst/gstghostpad \ + gst/gstplugin \ + gst/gstpreset \ + gst/gstprotection \ + gst/gstquery \ + gst/gstregistry \ + gst/gsturi \ + gst/gstutils \ + generic/sinks \ + elements/capsfilter \ + elements/concat \ + elements/dataurisrc \ + elements/fakesink \ + elements/fakesrc \ + elements/fdsrc \ + elements/filesink \ + elements/filesrc \ + elements/funnel \ + elements/identity \ + elements/multiqueue \ + elements/selector \ + elements/tee \ + elements/queue \ + elements/queue2 \ + elements/valve \ + elements/streamiddemux \ + libs/baseparse \ + libs/basesrc \ + libs/basesink \ + libs/sparsefile \ + libs/controller \ + libs/queuearray \ + libs/typefindhelper \ + pipelines/seek \ + pipelines/stress \ + pipelines/queue-error +endif + +check_PROGRAMS = \ + $(ABI_CHECKS) \ + gst/gstatomicqueue \ + gst/gstbuffer \ + gst/gstbufferlist \ + gst/gstbufferpool \ + gst/gstmeta \ + gst/gstmemory \ + gst/gstbus \ + gst/gstcaps \ + gst/gstcapsfeatures \ + $(CXX_CHECKS) \ + gst/gstdatetime \ + gst/gstdeinit \ + gst/gstdevice \ + gst/gstinfo \ + gst/gstiterator \ + gst/gstmessage \ + gst/gstminiobject \ + gst/gstobject \ + gst/gstpad \ + gst/gstparamspecs \ + gst/gstpipeline \ + gst/gstpoll \ + gst/gstprotection \ + $(PRINTF_CHECKS) \ + gst/gstpromise \ + gst/gstsegment \ + gst/gstsystemclock \ + gst/gstclock \ + gst/gststream \ + gst/gststructure \ + gst/gsttag \ + gst/gsttracerrecord \ + gst/gsttagsetter \ + gst/gsttask \ + gst/gsttoc \ + gst/gsttocsetter \ + gst/gstvalue \ + generic/states \ + $(PARSE_CHECKS) \ + $(REGISTRY_CHECKS) \ + $(LIBSABI_CHECKS) \ + libs/adapter \ + libs/aggregator \ + libs/bitreader \ + libs/bytereader \ + libs/bytewriter \ + libs/bitreader-noinline \ + libs/bytereader-noinline \ + libs/bytewriter-noinline \ + libs/flowcombiner \ + libs/sparsefile \ + libs/collectpads \ + libs/gstharness \ + libs/gstnetclientclock \ + libs/gstnettimeprovider \ + libs/gsttestclock \ + libs/transform1 \ + libs/transform2 \ + tools/gstinspect + +# failing tests +noinst_PROGRAMS = + +# elements to ignore for the state tests +# STATE_IGNORE_ELEMENTS = + +TESTS = $(check_PROGRAMS) + +noinst_HEADERS = \ + gst/capslist.h \ + gst/struct_arm.h \ + gst/struct_i386.h \ + gst/struct_i386w.h \ + gst/struct_hppa.h \ + gst/struct_ppc32.h \ + gst/struct_ppc64.h \ + gst/struct_sparc.h \ + gst/struct_x86_64.h \ + gst/struct_x86_64w.h \ + libs/struct_arm.h \ + libs/struct_i386.h \ + libs/struct_hppa.h \ + libs/struct_ppc32.h \ + libs/struct_ppc64.h \ + libs/struct_sparc.h \ + libs/struct_x86_64.h + +EXTRA_DIST = \ + libs/test_transform.c + +AM_CFLAGS = $(PTHREAD_CFLAGS) $(GST_OBJ_CFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \ + -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\"" +AM_CXXFLAGS = $(GST_OBJ_CXXFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \ + -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\"" +LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +gst_gstcpp_SOURCES = gst/gstcpp.cc + +libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc + +gst_gsttracerrecord_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API + +gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS) + +gst_gstprintf_LDADD = \ + $(top_builddir)/gst/printf/libgstprintf.la \ + $(LDADD) + +elements_fdsrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \ + -DTESTFILE=\"$(top_srcdir)/configure.ac\" +elements_filesrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \ + -DTESTFILE=\"$(top_srcdir)/configure.ac\" + +libs_controller_LDADD = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(LDADD) +libs_gstnetclientclock_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(LDADD) +libs_gstnettimeprovider_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GIO_LIBS) $(LDADD) + +# valgrind testing +# these just need valgrind fixing, period +VALGRIND_TO_FIX = \ + gst/gstinfo \ + gst/gsttracerrecord \ + tools/gstinspect + +VALGRIND_IGNORE = \ + pipelines/stress + +# these need fixing because the threads cause segfaults under valgrind +TESTS_THREADED = \ + gst/gstminiobject \ + gst/gstobject + +VALGRIND_TESTS_DISABLE = \ + $(TESTS_THREADED) \ + $(VALGRIND_IGNORE) \ + $(VALGRIND_TO_FIX) + +# indexers does not get tested yet +COVERAGE_DIRS = \ + gst \ + libs/gst/base \ + libs/gst/controller \ + libs/gst/check \ + libs/gst/net \ + plugins/elements +COVERAGE_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov)) +COVERAGE_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_FILES)) +COVERAGE_OUT_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov.out)) +COVERAGE_OUT_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_OUT_FILES)) + +debug: + echo $(COVERAGE_FILES) + echo $(COVERAGE_FILES_REL) + +.PHONY: coverage +if GST_GCOV_ENABLED +# we rebuild a registry and do gst-inspect so that all the get/set codepaths +# are also covered +coverage: + for file in `find $(top_builddir) -name '*.gcda'`; do rm $$file; done + -rm $(CHECK_REGISTRY) + echo "Inspecting all elements" + for e in `$(GST_INSPECT) | head -n -2 | cut -d: -f2`; do $(GST_INSPECT) $$e > /dev/null 2>&1; done + make check + make coverage-report +else +coverage: + echo "You need to configure with --enable-gcov to get coverage data" + exit 1 +endif + +coverage-report: + rm -r coverage + for dir in $(COVERAGE_DIRS); do \ + mkdir -p coverage/$$dir; \ + make -C $(top_builddir)/$$dir gcov; \ + done + for dir in $(COVERAGE_DIRS); do \ + files="`ls $(top_builddir)/$$dir/*.gcov.out 2> /dev/null`"; \ + if test ! -z "$$files"; then \ + perl $(top_srcdir)/common/coverage/coverage-report.pl \ + $(top_builddir)/$$dir/*.gcov.out > \ + coverage/$$dir/index.xml; \ + xsltproc $(top_srcdir)/common/coverage/coverage-report.xsl \ + coverage/$$dir/index.xml > coverage/$$dir/index.html; \ + fi; \ + done + for file in $(COVERAGE_FILES_REL); do \ + echo Generating coverage/$$file.html; \ + perl $(top_srcdir)/common/coverage/coverage-report-entry.pl \ + $(top_builddir)/$$file > coverage/$$file.html; \ + done diff --git a/tests/check/Makefile.in b/tests/check/Makefile.in new file mode 100644 index 0000000..bbe83df --- /dev/null +++ b/tests/check/Makefile.in @@ -0,0 +1,4033 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +check_PROGRAMS = $(am__EXEEXT_1) gst/gstatomicqueue$(EXEEXT) \ + gst/gstbuffer$(EXEEXT) gst/gstbufferlist$(EXEEXT) \ + gst/gstbufferpool$(EXEEXT) gst/gstmeta$(EXEEXT) \ + gst/gstmemory$(EXEEXT) gst/gstbus$(EXEEXT) \ + gst/gstcaps$(EXEEXT) gst/gstcapsfeatures$(EXEEXT) \ + $(am__EXEEXT_2) gst/gstdatetime$(EXEEXT) \ + gst/gstdeinit$(EXEEXT) gst/gstdevice$(EXEEXT) \ + gst/gstinfo$(EXEEXT) gst/gstiterator$(EXEEXT) \ + gst/gstmessage$(EXEEXT) gst/gstminiobject$(EXEEXT) \ + gst/gstobject$(EXEEXT) gst/gstpad$(EXEEXT) \ + gst/gstparamspecs$(EXEEXT) gst/gstpipeline$(EXEEXT) \ + gst/gstpoll$(EXEEXT) gst/gstprotection$(EXEEXT) \ + $(am__EXEEXT_3) gst/gstpromise$(EXEEXT) \ + gst/gstsegment$(EXEEXT) gst/gstsystemclock$(EXEEXT) \ + gst/gstclock$(EXEEXT) gst/gststream$(EXEEXT) \ + gst/gststructure$(EXEEXT) gst/gsttag$(EXEEXT) \ + gst/gsttracerrecord$(EXEEXT) gst/gsttagsetter$(EXEEXT) \ + gst/gsttask$(EXEEXT) gst/gsttoc$(EXEEXT) \ + gst/gsttocsetter$(EXEEXT) gst/gstvalue$(EXEEXT) \ + generic/states$(EXEEXT) $(am__EXEEXT_4) $(am__EXEEXT_5) \ + $(am__EXEEXT_6) libs/adapter$(EXEEXT) libs/aggregator$(EXEEXT) \ + libs/bitreader$(EXEEXT) libs/bytereader$(EXEEXT) \ + libs/bytewriter$(EXEEXT) libs/bitreader-noinline$(EXEEXT) \ + libs/bytereader-noinline$(EXEEXT) \ + libs/bytewriter-noinline$(EXEEXT) libs/flowcombiner$(EXEEXT) \ + libs/sparsefile$(EXEEXT) libs/collectpads$(EXEEXT) \ + libs/gstharness$(EXEEXT) libs/gstnetclientclock$(EXEEXT) \ + libs/gstnettimeprovider$(EXEEXT) libs/gsttestclock$(EXEEXT) \ + libs/transform1$(EXEEXT) libs/transform2$(EXEEXT) \ + tools/gstinspect$(EXEEXT) +noinst_PROGRAMS = +subdir = tests/check +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@GST_DISABLE_REGISTRY_FALSE@am__EXEEXT_1 = gst/gstabi$(EXEEXT) +@HAVE_CXX_TRUE@am__EXEEXT_2 = gst/gstcpp$(EXEEXT) \ +@HAVE_CXX_TRUE@ libs/gstlibscpp$(EXEEXT) +@GST_DISABLE_GST_DEBUG_FALSE@am__EXEEXT_3 = gst/gstprintf$(EXEEXT) +@GST_DISABLE_PARSE_FALSE@am__EXEEXT_4 = pipelines/simple-launch-lines$(EXEEXT) \ +@GST_DISABLE_PARSE_FALSE@ pipelines/cleanup$(EXEEXT) \ +@GST_DISABLE_PARSE_FALSE@ pipelines/parse-launch$(EXEEXT) +@GST_DISABLE_PARSE_TRUE@am__EXEEXT_4 = \ +@GST_DISABLE_PARSE_TRUE@ pipelines/parse-disabled$(EXEEXT) +@GST_DISABLE_REGISTRY_FALSE@am__EXEEXT_5 = gst/gst$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstbin$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstchildproxy$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstcontext$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstcontroller$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstelement$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstelementfactory$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstevent$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstghostpad$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstplugin$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstpreset$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstprotection$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstquery$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstregistry$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gsturi$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstutils$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ generic/sinks$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/capsfilter$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/concat$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/dataurisrc$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fakesink$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fakesrc$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fdsrc$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/filesink$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/filesrc$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/funnel$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/identity$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/multiqueue$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/selector$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/tee$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/queue$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/queue2$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/valve$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ elements/streamiddemux$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/baseparse$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/basesrc$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/basesink$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/sparsefile$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/controller$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/queuearray$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ libs/typefindhelper$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/seek$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/stress$(EXEEXT) \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/queue-error$(EXEEXT) +am__EXEEXT_6 = libs/libsabi$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +elements_capsfilter_SOURCES = elements/capsfilter.c +am__dirstamp = $(am__leading_dot)dirstamp +elements_capsfilter_OBJECTS = elements/capsfilter.$(OBJEXT) +elements_capsfilter_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +elements_capsfilter_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +elements_concat_SOURCES = elements/concat.c +elements_concat_OBJECTS = elements/concat.$(OBJEXT) +elements_concat_LDADD = $(LDADD) +elements_concat_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_dataurisrc_SOURCES = elements/dataurisrc.c +elements_dataurisrc_OBJECTS = elements/dataurisrc.$(OBJEXT) +elements_dataurisrc_LDADD = $(LDADD) +elements_dataurisrc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_fakesink_SOURCES = elements/fakesink.c +elements_fakesink_OBJECTS = elements/fakesink.$(OBJEXT) +elements_fakesink_LDADD = $(LDADD) +elements_fakesink_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_fakesrc_SOURCES = elements/fakesrc.c +elements_fakesrc_OBJECTS = elements/fakesrc.$(OBJEXT) +elements_fakesrc_LDADD = $(LDADD) +elements_fakesrc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_fdsrc_SOURCES = elements/fdsrc.c +elements_fdsrc_OBJECTS = elements/elements_fdsrc-fdsrc.$(OBJEXT) +elements_fdsrc_LDADD = $(LDADD) +elements_fdsrc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_fdsrc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(elements_fdsrc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +elements_filesink_SOURCES = elements/filesink.c +elements_filesink_OBJECTS = elements/filesink.$(OBJEXT) +elements_filesink_LDADD = $(LDADD) +elements_filesink_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_filesrc_SOURCES = elements/filesrc.c +elements_filesrc_OBJECTS = \ + elements/elements_filesrc-filesrc.$(OBJEXT) +elements_filesrc_LDADD = $(LDADD) +elements_filesrc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_filesrc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(elements_filesrc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +elements_funnel_SOURCES = elements/funnel.c +elements_funnel_OBJECTS = elements/funnel.$(OBJEXT) +elements_funnel_LDADD = $(LDADD) +elements_funnel_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_identity_SOURCES = elements/identity.c +elements_identity_OBJECTS = elements/identity.$(OBJEXT) +elements_identity_LDADD = $(LDADD) +elements_identity_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_multiqueue_SOURCES = elements/multiqueue.c +elements_multiqueue_OBJECTS = elements/multiqueue.$(OBJEXT) +elements_multiqueue_LDADD = $(LDADD) +elements_multiqueue_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_queue_SOURCES = elements/queue.c +elements_queue_OBJECTS = elements/queue.$(OBJEXT) +elements_queue_LDADD = $(LDADD) +elements_queue_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_queue2_SOURCES = elements/queue2.c +elements_queue2_OBJECTS = elements/queue2.$(OBJEXT) +elements_queue2_LDADD = $(LDADD) +elements_queue2_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_selector_SOURCES = elements/selector.c +elements_selector_OBJECTS = elements/selector.$(OBJEXT) +elements_selector_LDADD = $(LDADD) +elements_selector_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_streamiddemux_SOURCES = elements/streamiddemux.c +elements_streamiddemux_OBJECTS = elements/streamiddemux.$(OBJEXT) +elements_streamiddemux_LDADD = $(LDADD) +elements_streamiddemux_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_tee_SOURCES = elements/tee.c +elements_tee_OBJECTS = elements/tee.$(OBJEXT) +elements_tee_LDADD = $(LDADD) +elements_tee_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +elements_valve_SOURCES = elements/valve.c +elements_valve_OBJECTS = elements/valve.$(OBJEXT) +elements_valve_LDADD = $(LDADD) +elements_valve_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +generic_sinks_SOURCES = generic/sinks.c +generic_sinks_OBJECTS = generic/sinks.$(OBJEXT) +generic_sinks_LDADD = $(LDADD) +generic_sinks_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +generic_states_SOURCES = generic/states.c +generic_states_OBJECTS = generic/states.$(OBJEXT) +generic_states_LDADD = $(LDADD) +generic_states_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gst_SOURCES = gst/gst.c +gst_gst_OBJECTS = gst/gst.$(OBJEXT) +gst_gst_LDADD = $(LDADD) +gst_gst_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstabi_SOURCES = gst/gstabi.c +gst_gstabi_OBJECTS = gst/gstabi.$(OBJEXT) +gst_gstabi_LDADD = $(LDADD) +gst_gstabi_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstatomicqueue_SOURCES = gst/gstatomicqueue.c +gst_gstatomicqueue_OBJECTS = gst/gstatomicqueue.$(OBJEXT) +gst_gstatomicqueue_LDADD = $(LDADD) +gst_gstatomicqueue_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstbin_SOURCES = gst/gstbin.c +gst_gstbin_OBJECTS = gst/gstbin.$(OBJEXT) +gst_gstbin_LDADD = $(LDADD) +gst_gstbin_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstbuffer_SOURCES = gst/gstbuffer.c +gst_gstbuffer_OBJECTS = gst/gstbuffer.$(OBJEXT) +gst_gstbuffer_LDADD = $(LDADD) +gst_gstbuffer_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstbufferlist_SOURCES = gst/gstbufferlist.c +gst_gstbufferlist_OBJECTS = gst/gstbufferlist.$(OBJEXT) +gst_gstbufferlist_LDADD = $(LDADD) +gst_gstbufferlist_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstbufferpool_SOURCES = gst/gstbufferpool.c +gst_gstbufferpool_OBJECTS = gst/gstbufferpool.$(OBJEXT) +gst_gstbufferpool_LDADD = $(LDADD) +gst_gstbufferpool_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstbus_SOURCES = gst/gstbus.c +gst_gstbus_OBJECTS = gst/gstbus.$(OBJEXT) +gst_gstbus_LDADD = $(LDADD) +gst_gstbus_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstcaps_SOURCES = gst/gstcaps.c +gst_gstcaps_OBJECTS = gst/gstcaps.$(OBJEXT) +gst_gstcaps_LDADD = $(LDADD) +gst_gstcaps_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstcapsfeatures_SOURCES = gst/gstcapsfeatures.c +gst_gstcapsfeatures_OBJECTS = gst/gstcapsfeatures.$(OBJEXT) +gst_gstcapsfeatures_LDADD = $(LDADD) +gst_gstcapsfeatures_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstchildproxy_SOURCES = gst/gstchildproxy.c +gst_gstchildproxy_OBJECTS = gst/gstchildproxy.$(OBJEXT) +gst_gstchildproxy_LDADD = $(LDADD) +gst_gstchildproxy_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstclock_SOURCES = gst/gstclock.c +gst_gstclock_OBJECTS = gst/gstclock.$(OBJEXT) +gst_gstclock_LDADD = $(LDADD) +gst_gstclock_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstcontext_SOURCES = gst/gstcontext.c +gst_gstcontext_OBJECTS = gst/gstcontext.$(OBJEXT) +gst_gstcontext_LDADD = $(LDADD) +gst_gstcontext_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstcontroller_SOURCES = gst/gstcontroller.c +gst_gstcontroller_OBJECTS = gst/gstcontroller.$(OBJEXT) +gst_gstcontroller_LDADD = $(LDADD) +gst_gstcontroller_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +am_gst_gstcpp_OBJECTS = gst/gstcpp.$(OBJEXT) +gst_gstcpp_OBJECTS = $(am_gst_gstcpp_OBJECTS) +gst_gstcpp_LDADD = $(LDADD) +gst_gstcpp_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstdatetime_SOURCES = gst/gstdatetime.c +gst_gstdatetime_OBJECTS = gst/gstdatetime.$(OBJEXT) +gst_gstdatetime_LDADD = $(LDADD) +gst_gstdatetime_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstdeinit_SOURCES = gst/gstdeinit.c +gst_gstdeinit_OBJECTS = gst/gstdeinit.$(OBJEXT) +gst_gstdeinit_LDADD = $(LDADD) +gst_gstdeinit_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstdevice_SOURCES = gst/gstdevice.c +gst_gstdevice_OBJECTS = gst/gstdevice.$(OBJEXT) +gst_gstdevice_LDADD = $(LDADD) +gst_gstdevice_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstelement_SOURCES = gst/gstelement.c +gst_gstelement_OBJECTS = gst/gstelement.$(OBJEXT) +gst_gstelement_LDADD = $(LDADD) +gst_gstelement_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstelementfactory_SOURCES = gst/gstelementfactory.c +gst_gstelementfactory_OBJECTS = gst/gstelementfactory.$(OBJEXT) +gst_gstelementfactory_LDADD = $(LDADD) +gst_gstelementfactory_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstevent_SOURCES = gst/gstevent.c +gst_gstevent_OBJECTS = gst/gstevent.$(OBJEXT) +gst_gstevent_LDADD = $(LDADD) +gst_gstevent_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstghostpad_SOURCES = gst/gstghostpad.c +gst_gstghostpad_OBJECTS = gst/gstghostpad.$(OBJEXT) +gst_gstghostpad_LDADD = $(LDADD) +gst_gstghostpad_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstinfo_SOURCES = gst/gstinfo.c +gst_gstinfo_OBJECTS = gst/gstinfo.$(OBJEXT) +gst_gstinfo_LDADD = $(LDADD) +gst_gstinfo_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstiterator_SOURCES = gst/gstiterator.c +gst_gstiterator_OBJECTS = gst/gstiterator.$(OBJEXT) +gst_gstiterator_LDADD = $(LDADD) +gst_gstiterator_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstmemory_SOURCES = gst/gstmemory.c +gst_gstmemory_OBJECTS = gst/gstmemory.$(OBJEXT) +gst_gstmemory_LDADD = $(LDADD) +gst_gstmemory_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstmessage_SOURCES = gst/gstmessage.c +gst_gstmessage_OBJECTS = gst/gstmessage.$(OBJEXT) +gst_gstmessage_LDADD = $(LDADD) +gst_gstmessage_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstmeta_SOURCES = gst/gstmeta.c +gst_gstmeta_OBJECTS = gst/gstmeta.$(OBJEXT) +gst_gstmeta_LDADD = $(LDADD) +gst_gstmeta_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstminiobject_SOURCES = gst/gstminiobject.c +gst_gstminiobject_OBJECTS = gst/gstminiobject.$(OBJEXT) +gst_gstminiobject_LDADD = $(LDADD) +gst_gstminiobject_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstobject_SOURCES = gst/gstobject.c +gst_gstobject_OBJECTS = gst/gstobject.$(OBJEXT) +gst_gstobject_LDADD = $(LDADD) +gst_gstobject_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstpad_SOURCES = gst/gstpad.c +gst_gstpad_OBJECTS = gst/gstpad.$(OBJEXT) +gst_gstpad_LDADD = $(LDADD) +gst_gstpad_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstparamspecs_SOURCES = gst/gstparamspecs.c +gst_gstparamspecs_OBJECTS = gst/gstparamspecs.$(OBJEXT) +gst_gstparamspecs_LDADD = $(LDADD) +gst_gstparamspecs_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstpipeline_SOURCES = gst/gstpipeline.c +gst_gstpipeline_OBJECTS = gst/gstpipeline.$(OBJEXT) +gst_gstpipeline_LDADD = $(LDADD) +gst_gstpipeline_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstplugin_SOURCES = gst/gstplugin.c +gst_gstplugin_OBJECTS = gst/gstplugin.$(OBJEXT) +gst_gstplugin_LDADD = $(LDADD) +gst_gstplugin_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstpoll_SOURCES = gst/gstpoll.c +gst_gstpoll_OBJECTS = gst/gstpoll.$(OBJEXT) +gst_gstpoll_LDADD = $(LDADD) +gst_gstpoll_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstpreset_SOURCES = gst/gstpreset.c +gst_gstpreset_OBJECTS = gst/gstpreset.$(OBJEXT) +gst_gstpreset_LDADD = $(LDADD) +gst_gstpreset_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstprintf_SOURCES = gst/gstprintf.c +gst_gstprintf_OBJECTS = gst/gstprintf.$(OBJEXT) +am__DEPENDENCIES_2 = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstprintf_DEPENDENCIES = \ + $(top_builddir)/gst/printf/libgstprintf.la \ + $(am__DEPENDENCIES_2) +gst_gstpromise_SOURCES = gst/gstpromise.c +gst_gstpromise_OBJECTS = gst/gstpromise.$(OBJEXT) +gst_gstpromise_LDADD = $(LDADD) +gst_gstpromise_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstprotection_SOURCES = gst/gstprotection.c +gst_gstprotection_OBJECTS = gst/gstprotection.$(OBJEXT) +gst_gstprotection_LDADD = $(LDADD) +gst_gstprotection_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstquery_SOURCES = gst/gstquery.c +gst_gstquery_OBJECTS = gst/gstquery.$(OBJEXT) +gst_gstquery_LDADD = $(LDADD) +gst_gstquery_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstregistry_SOURCES = gst/gstregistry.c +gst_gstregistry_OBJECTS = gst/gstregistry.$(OBJEXT) +gst_gstregistry_LDADD = $(LDADD) +gst_gstregistry_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstsegment_SOURCES = gst/gstsegment.c +gst_gstsegment_OBJECTS = gst/gstsegment.$(OBJEXT) +gst_gstsegment_LDADD = $(LDADD) +gst_gstsegment_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gststream_SOURCES = gst/gststream.c +gst_gststream_OBJECTS = gst/gststream.$(OBJEXT) +gst_gststream_LDADD = $(LDADD) +gst_gststream_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gststructure_SOURCES = gst/gststructure.c +gst_gststructure_OBJECTS = gst/gststructure.$(OBJEXT) +gst_gststructure_LDADD = $(LDADD) +gst_gststructure_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstsystemclock_SOURCES = gst/gstsystemclock.c +gst_gstsystemclock_OBJECTS = gst/gstsystemclock.$(OBJEXT) +gst_gstsystemclock_LDADD = $(LDADD) +gst_gstsystemclock_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttag_SOURCES = gst/gsttag.c +gst_gsttag_OBJECTS = gst/gsttag.$(OBJEXT) +gst_gsttag_LDADD = $(LDADD) +gst_gsttag_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttagsetter_SOURCES = gst/gsttagsetter.c +gst_gsttagsetter_OBJECTS = gst/gsttagsetter.$(OBJEXT) +gst_gsttagsetter_LDADD = $(LDADD) +gst_gsttagsetter_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttask_SOURCES = gst/gsttask.c +gst_gsttask_OBJECTS = gst/gsttask.$(OBJEXT) +gst_gsttask_LDADD = $(LDADD) +gst_gsttask_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttoc_SOURCES = gst/gsttoc.c +gst_gsttoc_OBJECTS = gst/gsttoc.$(OBJEXT) +gst_gsttoc_LDADD = $(LDADD) +gst_gsttoc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttocsetter_SOURCES = gst/gsttocsetter.c +gst_gsttocsetter_OBJECTS = gst/gsttocsetter.$(OBJEXT) +gst_gsttocsetter_LDADD = $(LDADD) +gst_gsttocsetter_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttracerrecord_SOURCES = gst/gsttracerrecord.c +gst_gsttracerrecord_OBJECTS = \ + gst/gst_gsttracerrecord-gsttracerrecord.$(OBJEXT) +gst_gsttracerrecord_LDADD = $(LDADD) +gst_gsttracerrecord_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gsttracerrecord_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_gsttracerrecord_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +gst_gsturi_SOURCES = gst/gsturi.c +gst_gsturi_OBJECTS = gst/gsturi.$(OBJEXT) +gst_gsturi_LDADD = $(LDADD) +gst_gsturi_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +gst_gstutils_SOURCES = gst/gstutils.c +gst_gstutils_OBJECTS = gst/gstutils.$(OBJEXT) +gst_gstutils_DEPENDENCIES = $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +gst_gstvalue_SOURCES = gst/gstvalue.c +gst_gstvalue_OBJECTS = gst/gstvalue.$(OBJEXT) +gst_gstvalue_LDADD = $(LDADD) +gst_gstvalue_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_adapter_SOURCES = libs/adapter.c +libs_adapter_OBJECTS = libs/adapter.$(OBJEXT) +libs_adapter_LDADD = $(LDADD) +libs_adapter_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_aggregator_SOURCES = libs/aggregator.c +libs_aggregator_OBJECTS = libs/aggregator.$(OBJEXT) +libs_aggregator_LDADD = $(LDADD) +libs_aggregator_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_baseparse_SOURCES = libs/baseparse.c +libs_baseparse_OBJECTS = libs/baseparse.$(OBJEXT) +libs_baseparse_LDADD = $(LDADD) +libs_baseparse_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_basesink_SOURCES = libs/basesink.c +libs_basesink_OBJECTS = libs/basesink.$(OBJEXT) +libs_basesink_LDADD = $(LDADD) +libs_basesink_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_basesrc_SOURCES = libs/basesrc.c +libs_basesrc_OBJECTS = libs/basesrc.$(OBJEXT) +libs_basesrc_LDADD = $(LDADD) +libs_basesrc_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bitreader_SOURCES = libs/bitreader.c +libs_bitreader_OBJECTS = libs/bitreader.$(OBJEXT) +libs_bitreader_LDADD = $(LDADD) +libs_bitreader_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bitreader_noinline_SOURCES = libs/bitreader-noinline.c +libs_bitreader_noinline_OBJECTS = libs/bitreader-noinline.$(OBJEXT) +libs_bitreader_noinline_LDADD = $(LDADD) +libs_bitreader_noinline_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bytereader_SOURCES = libs/bytereader.c +libs_bytereader_OBJECTS = libs/bytereader.$(OBJEXT) +libs_bytereader_LDADD = $(LDADD) +libs_bytereader_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bytereader_noinline_SOURCES = libs/bytereader-noinline.c +libs_bytereader_noinline_OBJECTS = libs/bytereader-noinline.$(OBJEXT) +libs_bytereader_noinline_LDADD = $(LDADD) +libs_bytereader_noinline_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bytewriter_SOURCES = libs/bytewriter.c +libs_bytewriter_OBJECTS = libs/bytewriter.$(OBJEXT) +libs_bytewriter_LDADD = $(LDADD) +libs_bytewriter_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_bytewriter_noinline_SOURCES = libs/bytewriter-noinline.c +libs_bytewriter_noinline_OBJECTS = libs/bytewriter-noinline.$(OBJEXT) +libs_bytewriter_noinline_LDADD = $(LDADD) +libs_bytewriter_noinline_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_collectpads_SOURCES = libs/collectpads.c +libs_collectpads_OBJECTS = libs/collectpads.$(OBJEXT) +libs_collectpads_LDADD = $(LDADD) +libs_collectpads_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_controller_SOURCES = libs/controller.c +libs_controller_OBJECTS = libs/controller.$(OBJEXT) +libs_controller_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_2) +libs_flowcombiner_SOURCES = libs/flowcombiner.c +libs_flowcombiner_OBJECTS = libs/flowcombiner.$(OBJEXT) +libs_flowcombiner_LDADD = $(LDADD) +libs_flowcombiner_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_gstharness_SOURCES = libs/gstharness.c +libs_gstharness_OBJECTS = libs/gstharness.$(OBJEXT) +libs_gstharness_LDADD = $(LDADD) +libs_gstharness_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +am_libs_gstlibscpp_OBJECTS = libs/gstlibscpp.$(OBJEXT) +libs_gstlibscpp_OBJECTS = $(am_libs_gstlibscpp_OBJECTS) +libs_gstlibscpp_LDADD = $(LDADD) +libs_gstlibscpp_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_gstnetclientclock_SOURCES = libs/gstnetclientclock.c +libs_gstnetclientclock_OBJECTS = libs/gstnetclientclock.$(OBJEXT) +libs_gstnetclientclock_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_2) +libs_gstnettimeprovider_SOURCES = libs/gstnettimeprovider.c +libs_gstnettimeprovider_OBJECTS = libs/gstnettimeprovider.$(OBJEXT) +libs_gstnettimeprovider_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +libs_gsttestclock_SOURCES = libs/gsttestclock.c +libs_gsttestclock_OBJECTS = libs/gsttestclock.$(OBJEXT) +libs_gsttestclock_LDADD = $(LDADD) +libs_gsttestclock_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_libsabi_SOURCES = libs/libsabi.c +libs_libsabi_OBJECTS = libs/libsabi.$(OBJEXT) +libs_libsabi_LDADD = $(LDADD) +libs_libsabi_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_queuearray_SOURCES = libs/queuearray.c +libs_queuearray_OBJECTS = libs/queuearray.$(OBJEXT) +libs_queuearray_LDADD = $(LDADD) +libs_queuearray_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_sparsefile_SOURCES = libs/sparsefile.c +libs_sparsefile_OBJECTS = libs/sparsefile.$(OBJEXT) +libs_sparsefile_LDADD = $(LDADD) +libs_sparsefile_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_transform1_SOURCES = libs/transform1.c +libs_transform1_OBJECTS = libs/transform1.$(OBJEXT) +libs_transform1_LDADD = $(LDADD) +libs_transform1_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_transform2_SOURCES = libs/transform2.c +libs_transform2_OBJECTS = libs/transform2.$(OBJEXT) +libs_transform2_LDADD = $(LDADD) +libs_transform2_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +libs_typefindhelper_SOURCES = libs/typefindhelper.c +libs_typefindhelper_OBJECTS = libs/typefindhelper.$(OBJEXT) +libs_typefindhelper_LDADD = $(LDADD) +libs_typefindhelper_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_cleanup_SOURCES = pipelines/cleanup.c +pipelines_cleanup_OBJECTS = pipelines/cleanup.$(OBJEXT) +pipelines_cleanup_LDADD = $(LDADD) +pipelines_cleanup_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_parse_disabled_SOURCES = pipelines/parse-disabled.c +pipelines_parse_disabled_OBJECTS = pipelines/parse-disabled.$(OBJEXT) +pipelines_parse_disabled_LDADD = $(LDADD) +pipelines_parse_disabled_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_parse_launch_SOURCES = pipelines/parse-launch.c +pipelines_parse_launch_OBJECTS = pipelines/parse-launch.$(OBJEXT) +pipelines_parse_launch_LDADD = $(LDADD) +pipelines_parse_launch_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_queue_error_SOURCES = pipelines/queue-error.c +pipelines_queue_error_OBJECTS = pipelines/queue-error.$(OBJEXT) +pipelines_queue_error_LDADD = $(LDADD) +pipelines_queue_error_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_seek_SOURCES = pipelines/seek.c +pipelines_seek_OBJECTS = pipelines/seek.$(OBJEXT) +pipelines_seek_LDADD = $(LDADD) +pipelines_seek_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_simple_launch_lines_SOURCES = \ + pipelines/simple-launch-lines.c +pipelines_simple_launch_lines_OBJECTS = \ + pipelines/simple-launch-lines.$(OBJEXT) +pipelines_simple_launch_lines_LDADD = $(LDADD) +pipelines_simple_launch_lines_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +pipelines_stress_SOURCES = pipelines/stress.c +pipelines_stress_OBJECTS = pipelines/stress.$(OBJEXT) +pipelines_stress_LDADD = $(LDADD) +pipelines_stress_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +tools_gstinspect_SOURCES = tools/gstinspect.c +tools_gstinspect_OBJECTS = tools/gstinspect.$(OBJEXT) +tools_gstinspect_LDADD = $(LDADD) +tools_gstinspect_DEPENDENCIES = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = elements/capsfilter.c elements/concat.c \ + elements/dataurisrc.c elements/fakesink.c elements/fakesrc.c \ + elements/fdsrc.c elements/filesink.c elements/filesrc.c \ + elements/funnel.c elements/identity.c elements/multiqueue.c \ + elements/queue.c elements/queue2.c elements/selector.c \ + elements/streamiddemux.c elements/tee.c elements/valve.c \ + generic/sinks.c generic/states.c gst/gst.c gst/gstabi.c \ + gst/gstatomicqueue.c gst/gstbin.c gst/gstbuffer.c \ + gst/gstbufferlist.c gst/gstbufferpool.c gst/gstbus.c \ + gst/gstcaps.c gst/gstcapsfeatures.c gst/gstchildproxy.c \ + gst/gstclock.c gst/gstcontext.c gst/gstcontroller.c \ + $(gst_gstcpp_SOURCES) gst/gstdatetime.c gst/gstdeinit.c \ + gst/gstdevice.c gst/gstelement.c gst/gstelementfactory.c \ + gst/gstevent.c gst/gstghostpad.c gst/gstinfo.c \ + gst/gstiterator.c gst/gstmemory.c gst/gstmessage.c \ + gst/gstmeta.c gst/gstminiobject.c gst/gstobject.c gst/gstpad.c \ + gst/gstparamspecs.c gst/gstpipeline.c gst/gstplugin.c \ + gst/gstpoll.c gst/gstpreset.c gst/gstprintf.c gst/gstpromise.c \ + gst/gstprotection.c gst/gstquery.c gst/gstregistry.c \ + gst/gstsegment.c gst/gststream.c gst/gststructure.c \ + gst/gstsystemclock.c gst/gsttag.c gst/gsttagsetter.c \ + gst/gsttask.c gst/gsttoc.c gst/gsttocsetter.c \ + gst/gsttracerrecord.c gst/gsturi.c gst/gstutils.c \ + gst/gstvalue.c libs/adapter.c libs/aggregator.c \ + libs/baseparse.c libs/basesink.c libs/basesrc.c \ + libs/bitreader.c libs/bitreader-noinline.c libs/bytereader.c \ + libs/bytereader-noinline.c libs/bytewriter.c \ + libs/bytewriter-noinline.c libs/collectpads.c \ + libs/controller.c libs/flowcombiner.c libs/gstharness.c \ + $(libs_gstlibscpp_SOURCES) libs/gstnetclientclock.c \ + libs/gstnettimeprovider.c libs/gsttestclock.c libs/libsabi.c \ + libs/queuearray.c libs/sparsefile.c libs/transform1.c \ + libs/transform2.c libs/typefindhelper.c pipelines/cleanup.c \ + pipelines/parse-disabled.c pipelines/parse-launch.c \ + pipelines/queue-error.c pipelines/seek.c \ + pipelines/simple-launch-lines.c pipelines/stress.c \ + tools/gstinspect.c +DIST_SOURCES = elements/capsfilter.c elements/concat.c \ + elements/dataurisrc.c elements/fakesink.c elements/fakesrc.c \ + elements/fdsrc.c elements/filesink.c elements/filesrc.c \ + elements/funnel.c elements/identity.c elements/multiqueue.c \ + elements/queue.c elements/queue2.c elements/selector.c \ + elements/streamiddemux.c elements/tee.c elements/valve.c \ + generic/sinks.c generic/states.c gst/gst.c gst/gstabi.c \ + gst/gstatomicqueue.c gst/gstbin.c gst/gstbuffer.c \ + gst/gstbufferlist.c gst/gstbufferpool.c gst/gstbus.c \ + gst/gstcaps.c gst/gstcapsfeatures.c gst/gstchildproxy.c \ + gst/gstclock.c gst/gstcontext.c gst/gstcontroller.c \ + $(gst_gstcpp_SOURCES) gst/gstdatetime.c gst/gstdeinit.c \ + gst/gstdevice.c gst/gstelement.c gst/gstelementfactory.c \ + gst/gstevent.c gst/gstghostpad.c gst/gstinfo.c \ + gst/gstiterator.c gst/gstmemory.c gst/gstmessage.c \ + gst/gstmeta.c gst/gstminiobject.c gst/gstobject.c gst/gstpad.c \ + gst/gstparamspecs.c gst/gstpipeline.c gst/gstplugin.c \ + gst/gstpoll.c gst/gstpreset.c gst/gstprintf.c gst/gstpromise.c \ + gst/gstprotection.c gst/gstquery.c gst/gstregistry.c \ + gst/gstsegment.c gst/gststream.c gst/gststructure.c \ + gst/gstsystemclock.c gst/gsttag.c gst/gsttagsetter.c \ + gst/gsttask.c gst/gsttoc.c gst/gsttocsetter.c \ + gst/gsttracerrecord.c gst/gsturi.c gst/gstutils.c \ + gst/gstvalue.c libs/adapter.c libs/aggregator.c \ + libs/baseparse.c libs/basesink.c libs/basesrc.c \ + libs/bitreader.c libs/bitreader-noinline.c libs/bytereader.c \ + libs/bytereader-noinline.c libs/bytewriter.c \ + libs/bytewriter-noinline.c libs/collectpads.c \ + libs/controller.c libs/flowcombiner.c libs/gstharness.c \ + $(libs_gstlibscpp_SOURCES) libs/gstnetclientclock.c \ + libs/gstnettimeprovider.c libs/gsttestclock.c libs/libsabi.c \ + libs/queuearray.c libs/sparsefile.c libs/transform1.c \ + libs/transform2.c libs/typefindhelper.c pipelines/cleanup.c \ + pipelines/parse-disabled.c pipelines/parse-launch.c \ + pipelines/queue-error.c pipelines/seek.c \ + pipelines/simple-launch-lines.c pipelines/stress.c \ + tools/gstinspect.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common/check.mak \ + $(top_srcdir)/depcomp $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = $(libdir)/gstreamer-@GST_API_VERSION@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_TESTS_ENVIRONMENT = CK_DEFAULT_TIMEOUT=20 \ + GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \ + $(REGISTRY_ENVIRONMENT) \ + GST_PLUGIN_SCANNER_1_0=$(top_builddir)/libs/gst/helpers/gst-plugin-scanner \ + GST_PLUGIN_SYSTEM_PATH_1_0= \ + GST_PLUGIN_PATH_1_0=$(top_builddir)/plugins + +# inspect every plugin feature +GST_INSPECT = $(GST_TOOLS_DIR)/gst-inspect-$(GST_API_VERSION) +CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg +GST_TOOLS_DIR = $(top_builddir)/tools +REGISTRY_ENVIRONMENT = \ + GST_REGISTRY=$(CHECK_REGISTRY) + + +# the core dumps of some machines have PIDs appended, test registry and +# profiling data +CLEANFILES = core core.* test-registry.* *.gcno *.gcda +SUPPRESSIONS = $(top_srcdir)/common/gst.supp +@GST_DISABLE_PARSE_FALSE@PARSE_CHECKS = pipelines/simple-launch-lines pipelines/cleanup pipelines/parse-launch + +# These tests don't even build any longer: +# gst/gstindex.c +@GST_DISABLE_PARSE_TRUE@PARSE_CHECKS = pipelines/parse-disabled + +# Do not run the abi test in case any option which causes the API to change has +# been used +@GST_DISABLE_REGISTRY_FALSE@ABI_CHECKS = gst/gstabi +@GST_DISABLE_GST_DEBUG_FALSE@PRINTF_CHECKS = gst/gstprintf +@GST_DISABLE_GST_DEBUG_TRUE@PRINTF_CHECKS = +LIBSABI_CHECKS = libs/libsabi +@HAVE_CXX_FALSE@CXX_CHECKS = +@HAVE_CXX_TRUE@CXX_CHECKS = gst/gstcpp libs/gstlibscpp +@GST_DISABLE_REGISTRY_FALSE@REGISTRY_CHECKS = \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gst \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstbin \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstchildproxy \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstcontext \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstcontroller \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstelement \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstelementfactory \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstevent \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstghostpad \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstplugin \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstpreset \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstprotection \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstquery \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstregistry \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gsturi \ +@GST_DISABLE_REGISTRY_FALSE@ gst/gstutils \ +@GST_DISABLE_REGISTRY_FALSE@ generic/sinks \ +@GST_DISABLE_REGISTRY_FALSE@ elements/capsfilter \ +@GST_DISABLE_REGISTRY_FALSE@ elements/concat \ +@GST_DISABLE_REGISTRY_FALSE@ elements/dataurisrc \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fakesink \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fakesrc \ +@GST_DISABLE_REGISTRY_FALSE@ elements/fdsrc \ +@GST_DISABLE_REGISTRY_FALSE@ elements/filesink \ +@GST_DISABLE_REGISTRY_FALSE@ elements/filesrc \ +@GST_DISABLE_REGISTRY_FALSE@ elements/funnel \ +@GST_DISABLE_REGISTRY_FALSE@ elements/identity \ +@GST_DISABLE_REGISTRY_FALSE@ elements/multiqueue \ +@GST_DISABLE_REGISTRY_FALSE@ elements/selector \ +@GST_DISABLE_REGISTRY_FALSE@ elements/tee \ +@GST_DISABLE_REGISTRY_FALSE@ elements/queue \ +@GST_DISABLE_REGISTRY_FALSE@ elements/queue2 \ +@GST_DISABLE_REGISTRY_FALSE@ elements/valve \ +@GST_DISABLE_REGISTRY_FALSE@ elements/streamiddemux \ +@GST_DISABLE_REGISTRY_FALSE@ libs/baseparse \ +@GST_DISABLE_REGISTRY_FALSE@ libs/basesrc \ +@GST_DISABLE_REGISTRY_FALSE@ libs/basesink \ +@GST_DISABLE_REGISTRY_FALSE@ libs/sparsefile \ +@GST_DISABLE_REGISTRY_FALSE@ libs/controller \ +@GST_DISABLE_REGISTRY_FALSE@ libs/queuearray \ +@GST_DISABLE_REGISTRY_FALSE@ libs/typefindhelper \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/seek \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/stress \ +@GST_DISABLE_REGISTRY_FALSE@ pipelines/queue-error + + +# if it's calling gst_element_factory_make(), it will probably not work without +# a registry +@GST_DISABLE_REGISTRY_TRUE@REGISTRY_CHECKS = + +# elements to ignore for the state tests +# STATE_IGNORE_ELEMENTS = +TESTS = $(check_PROGRAMS) +noinst_HEADERS = \ + gst/capslist.h \ + gst/struct_arm.h \ + gst/struct_i386.h \ + gst/struct_i386w.h \ + gst/struct_hppa.h \ + gst/struct_ppc32.h \ + gst/struct_ppc64.h \ + gst/struct_sparc.h \ + gst/struct_x86_64.h \ + gst/struct_x86_64w.h \ + libs/struct_arm.h \ + libs/struct_i386.h \ + libs/struct_hppa.h \ + libs/struct_ppc32.h \ + libs/struct_ppc64.h \ + libs/struct_sparc.h \ + libs/struct_x86_64.h + +EXTRA_DIST = \ + libs/test_transform.c + +AM_CFLAGS = $(PTHREAD_CFLAGS) $(GST_OBJ_CFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \ + -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\"" + +AM_CXXFLAGS = $(GST_OBJ_CXXFLAGS) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS \ + -DGST_CHECK_TEST_ENVIRONMENT_BEACON="\"GST_STATE_IGNORE_ELEMENTS\"" + +LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_API_VERSION@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +gst_gstcpp_SOURCES = gst/gstcpp.cc +libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc +gst_gsttracerrecord_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API +gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS) +gst_gstprintf_LDADD = \ + $(top_builddir)/gst/printf/libgstprintf.la \ + $(LDADD) + +elements_fdsrc_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) \ + -DTESTFILE=\"$(top_srcdir)/configure.ac\" + +elements_filesrc_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) \ + -DTESTFILE=\"$(top_srcdir)/configure.ac\" + +libs_controller_LDADD = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(LDADD) + +libs_gstnetclientclock_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(LDADD) + +libs_gstnettimeprovider_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GIO_LIBS) $(LDADD) + + +# valgrind testing +# these just need valgrind fixing, period +VALGRIND_TO_FIX = \ + gst/gstinfo \ + gst/gsttracerrecord \ + tools/gstinspect + +VALGRIND_IGNORE = \ + pipelines/stress + + +# these need fixing because the threads cause segfaults under valgrind +TESTS_THREADED = \ + gst/gstminiobject \ + gst/gstobject + +VALGRIND_TESTS_DISABLE = \ + $(TESTS_THREADED) \ + $(VALGRIND_IGNORE) \ + $(VALGRIND_TO_FIX) + + +# indexers does not get tested yet +COVERAGE_DIRS = \ + gst \ + libs/gst/base \ + libs/gst/controller \ + libs/gst/check \ + libs/gst/net \ + plugins/elements + +COVERAGE_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov)) +COVERAGE_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_FILES)) +COVERAGE_OUT_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov.out)) +COVERAGE_OUT_FILES_REL = $(subst $(top_builddir)/,,$(COVERAGE_OUT_FILES)) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/check.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/check/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/check/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/check.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +elements/$(am__dirstamp): + @$(MKDIR_P) elements + @: > elements/$(am__dirstamp) +elements/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) elements/$(DEPDIR) + @: > elements/$(DEPDIR)/$(am__dirstamp) +elements/capsfilter.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/capsfilter$(EXEEXT): $(elements_capsfilter_OBJECTS) $(elements_capsfilter_DEPENDENCIES) $(EXTRA_elements_capsfilter_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/capsfilter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_capsfilter_OBJECTS) $(elements_capsfilter_LDADD) $(LIBS) +elements/concat.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/concat$(EXEEXT): $(elements_concat_OBJECTS) $(elements_concat_DEPENDENCIES) $(EXTRA_elements_concat_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/concat$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_concat_OBJECTS) $(elements_concat_LDADD) $(LIBS) +elements/dataurisrc.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/dataurisrc$(EXEEXT): $(elements_dataurisrc_OBJECTS) $(elements_dataurisrc_DEPENDENCIES) $(EXTRA_elements_dataurisrc_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/dataurisrc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_dataurisrc_OBJECTS) $(elements_dataurisrc_LDADD) $(LIBS) +elements/fakesink.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/fakesink$(EXEEXT): $(elements_fakesink_OBJECTS) $(elements_fakesink_DEPENDENCIES) $(EXTRA_elements_fakesink_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/fakesink$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_fakesink_OBJECTS) $(elements_fakesink_LDADD) $(LIBS) +elements/fakesrc.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/fakesrc$(EXEEXT): $(elements_fakesrc_OBJECTS) $(elements_fakesrc_DEPENDENCIES) $(EXTRA_elements_fakesrc_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/fakesrc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_fakesrc_OBJECTS) $(elements_fakesrc_LDADD) $(LIBS) +elements/elements_fdsrc-fdsrc.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/fdsrc$(EXEEXT): $(elements_fdsrc_OBJECTS) $(elements_fdsrc_DEPENDENCIES) $(EXTRA_elements_fdsrc_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/fdsrc$(EXEEXT) + $(AM_V_CCLD)$(elements_fdsrc_LINK) $(elements_fdsrc_OBJECTS) $(elements_fdsrc_LDADD) $(LIBS) +elements/filesink.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/filesink$(EXEEXT): $(elements_filesink_OBJECTS) $(elements_filesink_DEPENDENCIES) $(EXTRA_elements_filesink_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/filesink$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_filesink_OBJECTS) $(elements_filesink_LDADD) $(LIBS) +elements/elements_filesrc-filesrc.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/filesrc$(EXEEXT): $(elements_filesrc_OBJECTS) $(elements_filesrc_DEPENDENCIES) $(EXTRA_elements_filesrc_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/filesrc$(EXEEXT) + $(AM_V_CCLD)$(elements_filesrc_LINK) $(elements_filesrc_OBJECTS) $(elements_filesrc_LDADD) $(LIBS) +elements/funnel.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/funnel$(EXEEXT): $(elements_funnel_OBJECTS) $(elements_funnel_DEPENDENCIES) $(EXTRA_elements_funnel_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/funnel$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_funnel_OBJECTS) $(elements_funnel_LDADD) $(LIBS) +elements/identity.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/identity$(EXEEXT): $(elements_identity_OBJECTS) $(elements_identity_DEPENDENCIES) $(EXTRA_elements_identity_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/identity$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_identity_OBJECTS) $(elements_identity_LDADD) $(LIBS) +elements/multiqueue.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/multiqueue$(EXEEXT): $(elements_multiqueue_OBJECTS) $(elements_multiqueue_DEPENDENCIES) $(EXTRA_elements_multiqueue_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/multiqueue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_multiqueue_OBJECTS) $(elements_multiqueue_LDADD) $(LIBS) +elements/queue.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/queue$(EXEEXT): $(elements_queue_OBJECTS) $(elements_queue_DEPENDENCIES) $(EXTRA_elements_queue_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/queue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_queue_OBJECTS) $(elements_queue_LDADD) $(LIBS) +elements/queue2.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/queue2$(EXEEXT): $(elements_queue2_OBJECTS) $(elements_queue2_DEPENDENCIES) $(EXTRA_elements_queue2_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/queue2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_queue2_OBJECTS) $(elements_queue2_LDADD) $(LIBS) +elements/selector.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/selector$(EXEEXT): $(elements_selector_OBJECTS) $(elements_selector_DEPENDENCIES) $(EXTRA_elements_selector_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/selector$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_selector_OBJECTS) $(elements_selector_LDADD) $(LIBS) +elements/streamiddemux.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/streamiddemux$(EXEEXT): $(elements_streamiddemux_OBJECTS) $(elements_streamiddemux_DEPENDENCIES) $(EXTRA_elements_streamiddemux_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/streamiddemux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_streamiddemux_OBJECTS) $(elements_streamiddemux_LDADD) $(LIBS) +elements/tee.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/tee$(EXEEXT): $(elements_tee_OBJECTS) $(elements_tee_DEPENDENCIES) $(EXTRA_elements_tee_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/tee$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_tee_OBJECTS) $(elements_tee_LDADD) $(LIBS) +elements/valve.$(OBJEXT): elements/$(am__dirstamp) \ + elements/$(DEPDIR)/$(am__dirstamp) + +elements/valve$(EXEEXT): $(elements_valve_OBJECTS) $(elements_valve_DEPENDENCIES) $(EXTRA_elements_valve_DEPENDENCIES) elements/$(am__dirstamp) + @rm -f elements/valve$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elements_valve_OBJECTS) $(elements_valve_LDADD) $(LIBS) +generic/$(am__dirstamp): + @$(MKDIR_P) generic + @: > generic/$(am__dirstamp) +generic/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) generic/$(DEPDIR) + @: > generic/$(DEPDIR)/$(am__dirstamp) +generic/sinks.$(OBJEXT): generic/$(am__dirstamp) \ + generic/$(DEPDIR)/$(am__dirstamp) + +generic/sinks$(EXEEXT): $(generic_sinks_OBJECTS) $(generic_sinks_DEPENDENCIES) $(EXTRA_generic_sinks_DEPENDENCIES) generic/$(am__dirstamp) + @rm -f generic/sinks$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(generic_sinks_OBJECTS) $(generic_sinks_LDADD) $(LIBS) +generic/states.$(OBJEXT): generic/$(am__dirstamp) \ + generic/$(DEPDIR)/$(am__dirstamp) + +generic/states$(EXEEXT): $(generic_states_OBJECTS) $(generic_states_DEPENDENCIES) $(EXTRA_generic_states_DEPENDENCIES) generic/$(am__dirstamp) + @rm -f generic/states$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(generic_states_OBJECTS) $(generic_states_LDADD) $(LIBS) +gst/$(am__dirstamp): + @$(MKDIR_P) gst + @: > gst/$(am__dirstamp) +gst/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) gst/$(DEPDIR) + @: > gst/$(DEPDIR)/$(am__dirstamp) +gst/gst.$(OBJEXT): gst/$(am__dirstamp) gst/$(DEPDIR)/$(am__dirstamp) + +gst/gst$(EXEEXT): $(gst_gst_OBJECTS) $(gst_gst_DEPENDENCIES) $(EXTRA_gst_gst_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gst$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gst_OBJECTS) $(gst_gst_LDADD) $(LIBS) +gst/gstabi.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstabi$(EXEEXT): $(gst_gstabi_OBJECTS) $(gst_gstabi_DEPENDENCIES) $(EXTRA_gst_gstabi_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstabi$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstabi_OBJECTS) $(gst_gstabi_LDADD) $(LIBS) +gst/gstatomicqueue.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstatomicqueue$(EXEEXT): $(gst_gstatomicqueue_OBJECTS) $(gst_gstatomicqueue_DEPENDENCIES) $(EXTRA_gst_gstatomicqueue_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstatomicqueue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstatomicqueue_OBJECTS) $(gst_gstatomicqueue_LDADD) $(LIBS) +gst/gstbin.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstbin$(EXEEXT): $(gst_gstbin_OBJECTS) $(gst_gstbin_DEPENDENCIES) $(EXTRA_gst_gstbin_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstbin$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstbin_OBJECTS) $(gst_gstbin_LDADD) $(LIBS) +gst/gstbuffer.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstbuffer$(EXEEXT): $(gst_gstbuffer_OBJECTS) $(gst_gstbuffer_DEPENDENCIES) $(EXTRA_gst_gstbuffer_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstbuffer$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstbuffer_OBJECTS) $(gst_gstbuffer_LDADD) $(LIBS) +gst/gstbufferlist.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstbufferlist$(EXEEXT): $(gst_gstbufferlist_OBJECTS) $(gst_gstbufferlist_DEPENDENCIES) $(EXTRA_gst_gstbufferlist_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstbufferlist$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstbufferlist_OBJECTS) $(gst_gstbufferlist_LDADD) $(LIBS) +gst/gstbufferpool.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstbufferpool$(EXEEXT): $(gst_gstbufferpool_OBJECTS) $(gst_gstbufferpool_DEPENDENCIES) $(EXTRA_gst_gstbufferpool_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstbufferpool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstbufferpool_OBJECTS) $(gst_gstbufferpool_LDADD) $(LIBS) +gst/gstbus.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstbus$(EXEEXT): $(gst_gstbus_OBJECTS) $(gst_gstbus_DEPENDENCIES) $(EXTRA_gst_gstbus_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstbus$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstbus_OBJECTS) $(gst_gstbus_LDADD) $(LIBS) +gst/gstcaps.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstcaps$(EXEEXT): $(gst_gstcaps_OBJECTS) $(gst_gstcaps_DEPENDENCIES) $(EXTRA_gst_gstcaps_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstcaps$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstcaps_OBJECTS) $(gst_gstcaps_LDADD) $(LIBS) +gst/gstcapsfeatures.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstcapsfeatures$(EXEEXT): $(gst_gstcapsfeatures_OBJECTS) $(gst_gstcapsfeatures_DEPENDENCIES) $(EXTRA_gst_gstcapsfeatures_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstcapsfeatures$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstcapsfeatures_OBJECTS) $(gst_gstcapsfeatures_LDADD) $(LIBS) +gst/gstchildproxy.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstchildproxy$(EXEEXT): $(gst_gstchildproxy_OBJECTS) $(gst_gstchildproxy_DEPENDENCIES) $(EXTRA_gst_gstchildproxy_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstchildproxy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstchildproxy_OBJECTS) $(gst_gstchildproxy_LDADD) $(LIBS) +gst/gstclock.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstclock$(EXEEXT): $(gst_gstclock_OBJECTS) $(gst_gstclock_DEPENDENCIES) $(EXTRA_gst_gstclock_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstclock$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstclock_OBJECTS) $(gst_gstclock_LDADD) $(LIBS) +gst/gstcontext.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstcontext$(EXEEXT): $(gst_gstcontext_OBJECTS) $(gst_gstcontext_DEPENDENCIES) $(EXTRA_gst_gstcontext_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstcontext$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstcontext_OBJECTS) $(gst_gstcontext_LDADD) $(LIBS) +gst/gstcontroller.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstcontroller$(EXEEXT): $(gst_gstcontroller_OBJECTS) $(gst_gstcontroller_DEPENDENCIES) $(EXTRA_gst_gstcontroller_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstcontroller$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstcontroller_OBJECTS) $(gst_gstcontroller_LDADD) $(LIBS) +gst/gstcpp.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstcpp$(EXEEXT): $(gst_gstcpp_OBJECTS) $(gst_gstcpp_DEPENDENCIES) $(EXTRA_gst_gstcpp_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstcpp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(gst_gstcpp_OBJECTS) $(gst_gstcpp_LDADD) $(LIBS) +gst/gstdatetime.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstdatetime$(EXEEXT): $(gst_gstdatetime_OBJECTS) $(gst_gstdatetime_DEPENDENCIES) $(EXTRA_gst_gstdatetime_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstdatetime$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstdatetime_OBJECTS) $(gst_gstdatetime_LDADD) $(LIBS) +gst/gstdeinit.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstdeinit$(EXEEXT): $(gst_gstdeinit_OBJECTS) $(gst_gstdeinit_DEPENDENCIES) $(EXTRA_gst_gstdeinit_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstdeinit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstdeinit_OBJECTS) $(gst_gstdeinit_LDADD) $(LIBS) +gst/gstdevice.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstdevice$(EXEEXT): $(gst_gstdevice_OBJECTS) $(gst_gstdevice_DEPENDENCIES) $(EXTRA_gst_gstdevice_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstdevice$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstdevice_OBJECTS) $(gst_gstdevice_LDADD) $(LIBS) +gst/gstelement.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstelement$(EXEEXT): $(gst_gstelement_OBJECTS) $(gst_gstelement_DEPENDENCIES) $(EXTRA_gst_gstelement_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstelement$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstelement_OBJECTS) $(gst_gstelement_LDADD) $(LIBS) +gst/gstelementfactory.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstelementfactory$(EXEEXT): $(gst_gstelementfactory_OBJECTS) $(gst_gstelementfactory_DEPENDENCIES) $(EXTRA_gst_gstelementfactory_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstelementfactory$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstelementfactory_OBJECTS) $(gst_gstelementfactory_LDADD) $(LIBS) +gst/gstevent.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstevent$(EXEEXT): $(gst_gstevent_OBJECTS) $(gst_gstevent_DEPENDENCIES) $(EXTRA_gst_gstevent_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstevent$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstevent_OBJECTS) $(gst_gstevent_LDADD) $(LIBS) +gst/gstghostpad.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstghostpad$(EXEEXT): $(gst_gstghostpad_OBJECTS) $(gst_gstghostpad_DEPENDENCIES) $(EXTRA_gst_gstghostpad_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstghostpad$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstghostpad_OBJECTS) $(gst_gstghostpad_LDADD) $(LIBS) +gst/gstinfo.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstinfo$(EXEEXT): $(gst_gstinfo_OBJECTS) $(gst_gstinfo_DEPENDENCIES) $(EXTRA_gst_gstinfo_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstinfo$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstinfo_OBJECTS) $(gst_gstinfo_LDADD) $(LIBS) +gst/gstiterator.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstiterator$(EXEEXT): $(gst_gstiterator_OBJECTS) $(gst_gstiterator_DEPENDENCIES) $(EXTRA_gst_gstiterator_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstiterator$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstiterator_OBJECTS) $(gst_gstiterator_LDADD) $(LIBS) +gst/gstmemory.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstmemory$(EXEEXT): $(gst_gstmemory_OBJECTS) $(gst_gstmemory_DEPENDENCIES) $(EXTRA_gst_gstmemory_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstmemory$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstmemory_OBJECTS) $(gst_gstmemory_LDADD) $(LIBS) +gst/gstmessage.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstmessage$(EXEEXT): $(gst_gstmessage_OBJECTS) $(gst_gstmessage_DEPENDENCIES) $(EXTRA_gst_gstmessage_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstmessage$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstmessage_OBJECTS) $(gst_gstmessage_LDADD) $(LIBS) +gst/gstmeta.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstmeta$(EXEEXT): $(gst_gstmeta_OBJECTS) $(gst_gstmeta_DEPENDENCIES) $(EXTRA_gst_gstmeta_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstmeta$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstmeta_OBJECTS) $(gst_gstmeta_LDADD) $(LIBS) +gst/gstminiobject.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstminiobject$(EXEEXT): $(gst_gstminiobject_OBJECTS) $(gst_gstminiobject_DEPENDENCIES) $(EXTRA_gst_gstminiobject_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstminiobject$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstminiobject_OBJECTS) $(gst_gstminiobject_LDADD) $(LIBS) +gst/gstobject.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstobject$(EXEEXT): $(gst_gstobject_OBJECTS) $(gst_gstobject_DEPENDENCIES) $(EXTRA_gst_gstobject_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstobject$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstobject_OBJECTS) $(gst_gstobject_LDADD) $(LIBS) +gst/gstpad.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstpad$(EXEEXT): $(gst_gstpad_OBJECTS) $(gst_gstpad_DEPENDENCIES) $(EXTRA_gst_gstpad_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstpad$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstpad_OBJECTS) $(gst_gstpad_LDADD) $(LIBS) +gst/gstparamspecs.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstparamspecs$(EXEEXT): $(gst_gstparamspecs_OBJECTS) $(gst_gstparamspecs_DEPENDENCIES) $(EXTRA_gst_gstparamspecs_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstparamspecs$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstparamspecs_OBJECTS) $(gst_gstparamspecs_LDADD) $(LIBS) +gst/gstpipeline.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstpipeline$(EXEEXT): $(gst_gstpipeline_OBJECTS) $(gst_gstpipeline_DEPENDENCIES) $(EXTRA_gst_gstpipeline_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstpipeline$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstpipeline_OBJECTS) $(gst_gstpipeline_LDADD) $(LIBS) +gst/gstplugin.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstplugin$(EXEEXT): $(gst_gstplugin_OBJECTS) $(gst_gstplugin_DEPENDENCIES) $(EXTRA_gst_gstplugin_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstplugin$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstplugin_OBJECTS) $(gst_gstplugin_LDADD) $(LIBS) +gst/gstpoll.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstpoll$(EXEEXT): $(gst_gstpoll_OBJECTS) $(gst_gstpoll_DEPENDENCIES) $(EXTRA_gst_gstpoll_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstpoll$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstpoll_OBJECTS) $(gst_gstpoll_LDADD) $(LIBS) +gst/gstpreset.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstpreset$(EXEEXT): $(gst_gstpreset_OBJECTS) $(gst_gstpreset_DEPENDENCIES) $(EXTRA_gst_gstpreset_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstpreset$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstpreset_OBJECTS) $(gst_gstpreset_LDADD) $(LIBS) +gst/gstprintf.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstprintf$(EXEEXT): $(gst_gstprintf_OBJECTS) $(gst_gstprintf_DEPENDENCIES) $(EXTRA_gst_gstprintf_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstprintf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstprintf_OBJECTS) $(gst_gstprintf_LDADD) $(LIBS) +gst/gstpromise.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstpromise$(EXEEXT): $(gst_gstpromise_OBJECTS) $(gst_gstpromise_DEPENDENCIES) $(EXTRA_gst_gstpromise_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstpromise$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstpromise_OBJECTS) $(gst_gstpromise_LDADD) $(LIBS) +gst/gstprotection.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstprotection$(EXEEXT): $(gst_gstprotection_OBJECTS) $(gst_gstprotection_DEPENDENCIES) $(EXTRA_gst_gstprotection_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstprotection$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstprotection_OBJECTS) $(gst_gstprotection_LDADD) $(LIBS) +gst/gstquery.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstquery$(EXEEXT): $(gst_gstquery_OBJECTS) $(gst_gstquery_DEPENDENCIES) $(EXTRA_gst_gstquery_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstquery$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstquery_OBJECTS) $(gst_gstquery_LDADD) $(LIBS) +gst/gstregistry.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstregistry$(EXEEXT): $(gst_gstregistry_OBJECTS) $(gst_gstregistry_DEPENDENCIES) $(EXTRA_gst_gstregistry_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstregistry$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstregistry_OBJECTS) $(gst_gstregistry_LDADD) $(LIBS) +gst/gstsegment.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstsegment$(EXEEXT): $(gst_gstsegment_OBJECTS) $(gst_gstsegment_DEPENDENCIES) $(EXTRA_gst_gstsegment_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstsegment$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstsegment_OBJECTS) $(gst_gstsegment_LDADD) $(LIBS) +gst/gststream.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gststream$(EXEEXT): $(gst_gststream_OBJECTS) $(gst_gststream_DEPENDENCIES) $(EXTRA_gst_gststream_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gststream$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gststream_OBJECTS) $(gst_gststream_LDADD) $(LIBS) +gst/gststructure.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gststructure$(EXEEXT): $(gst_gststructure_OBJECTS) $(gst_gststructure_DEPENDENCIES) $(EXTRA_gst_gststructure_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gststructure$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gststructure_OBJECTS) $(gst_gststructure_LDADD) $(LIBS) +gst/gstsystemclock.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstsystemclock$(EXEEXT): $(gst_gstsystemclock_OBJECTS) $(gst_gstsystemclock_DEPENDENCIES) $(EXTRA_gst_gstsystemclock_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstsystemclock$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstsystemclock_OBJECTS) $(gst_gstsystemclock_LDADD) $(LIBS) +gst/gsttag.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttag$(EXEEXT): $(gst_gsttag_OBJECTS) $(gst_gsttag_DEPENDENCIES) $(EXTRA_gst_gsttag_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttag$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsttag_OBJECTS) $(gst_gsttag_LDADD) $(LIBS) +gst/gsttagsetter.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttagsetter$(EXEEXT): $(gst_gsttagsetter_OBJECTS) $(gst_gsttagsetter_DEPENDENCIES) $(EXTRA_gst_gsttagsetter_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttagsetter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsttagsetter_OBJECTS) $(gst_gsttagsetter_LDADD) $(LIBS) +gst/gsttask.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttask$(EXEEXT): $(gst_gsttask_OBJECTS) $(gst_gsttask_DEPENDENCIES) $(EXTRA_gst_gsttask_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttask$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsttask_OBJECTS) $(gst_gsttask_LDADD) $(LIBS) +gst/gsttoc.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttoc$(EXEEXT): $(gst_gsttoc_OBJECTS) $(gst_gsttoc_DEPENDENCIES) $(EXTRA_gst_gsttoc_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttoc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsttoc_OBJECTS) $(gst_gsttoc_LDADD) $(LIBS) +gst/gsttocsetter.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttocsetter$(EXEEXT): $(gst_gsttocsetter_OBJECTS) $(gst_gsttocsetter_DEPENDENCIES) $(EXTRA_gst_gsttocsetter_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttocsetter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsttocsetter_OBJECTS) $(gst_gsttocsetter_LDADD) $(LIBS) +gst/gst_gsttracerrecord-gsttracerrecord.$(OBJEXT): \ + gst/$(am__dirstamp) gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsttracerrecord$(EXEEXT): $(gst_gsttracerrecord_OBJECTS) $(gst_gsttracerrecord_DEPENDENCIES) $(EXTRA_gst_gsttracerrecord_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsttracerrecord$(EXEEXT) + $(AM_V_CCLD)$(gst_gsttracerrecord_LINK) $(gst_gsttracerrecord_OBJECTS) $(gst_gsttracerrecord_LDADD) $(LIBS) +gst/gsturi.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gsturi$(EXEEXT): $(gst_gsturi_OBJECTS) $(gst_gsturi_DEPENDENCIES) $(EXTRA_gst_gsturi_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gsturi$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gsturi_OBJECTS) $(gst_gsturi_LDADD) $(LIBS) +gst/gstutils.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstutils$(EXEEXT): $(gst_gstutils_OBJECTS) $(gst_gstutils_DEPENDENCIES) $(EXTRA_gst_gstutils_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstutils$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstutils_OBJECTS) $(gst_gstutils_LDADD) $(LIBS) +gst/gstvalue.$(OBJEXT): gst/$(am__dirstamp) \ + gst/$(DEPDIR)/$(am__dirstamp) + +gst/gstvalue$(EXEEXT): $(gst_gstvalue_OBJECTS) $(gst_gstvalue_DEPENDENCIES) $(EXTRA_gst_gstvalue_DEPENDENCIES) gst/$(am__dirstamp) + @rm -f gst/gstvalue$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gst_gstvalue_OBJECTS) $(gst_gstvalue_LDADD) $(LIBS) +libs/$(am__dirstamp): + @$(MKDIR_P) libs + @: > libs/$(am__dirstamp) +libs/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libs/$(DEPDIR) + @: > libs/$(DEPDIR)/$(am__dirstamp) +libs/adapter.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/adapter$(EXEEXT): $(libs_adapter_OBJECTS) $(libs_adapter_DEPENDENCIES) $(EXTRA_libs_adapter_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/adapter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_adapter_OBJECTS) $(libs_adapter_LDADD) $(LIBS) +libs/aggregator.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/aggregator$(EXEEXT): $(libs_aggregator_OBJECTS) $(libs_aggregator_DEPENDENCIES) $(EXTRA_libs_aggregator_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/aggregator$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_aggregator_OBJECTS) $(libs_aggregator_LDADD) $(LIBS) +libs/baseparse.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/baseparse$(EXEEXT): $(libs_baseparse_OBJECTS) $(libs_baseparse_DEPENDENCIES) $(EXTRA_libs_baseparse_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/baseparse$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_baseparse_OBJECTS) $(libs_baseparse_LDADD) $(LIBS) +libs/basesink.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/basesink$(EXEEXT): $(libs_basesink_OBJECTS) $(libs_basesink_DEPENDENCIES) $(EXTRA_libs_basesink_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/basesink$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_basesink_OBJECTS) $(libs_basesink_LDADD) $(LIBS) +libs/basesrc.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/basesrc$(EXEEXT): $(libs_basesrc_OBJECTS) $(libs_basesrc_DEPENDENCIES) $(EXTRA_libs_basesrc_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/basesrc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_basesrc_OBJECTS) $(libs_basesrc_LDADD) $(LIBS) +libs/bitreader.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bitreader$(EXEEXT): $(libs_bitreader_OBJECTS) $(libs_bitreader_DEPENDENCIES) $(EXTRA_libs_bitreader_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bitreader$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bitreader_OBJECTS) $(libs_bitreader_LDADD) $(LIBS) +libs/bitreader-noinline.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bitreader-noinline$(EXEEXT): $(libs_bitreader_noinline_OBJECTS) $(libs_bitreader_noinline_DEPENDENCIES) $(EXTRA_libs_bitreader_noinline_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bitreader-noinline$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bitreader_noinline_OBJECTS) $(libs_bitreader_noinline_LDADD) $(LIBS) +libs/bytereader.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bytereader$(EXEEXT): $(libs_bytereader_OBJECTS) $(libs_bytereader_DEPENDENCIES) $(EXTRA_libs_bytereader_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bytereader$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bytereader_OBJECTS) $(libs_bytereader_LDADD) $(LIBS) +libs/bytereader-noinline.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bytereader-noinline$(EXEEXT): $(libs_bytereader_noinline_OBJECTS) $(libs_bytereader_noinline_DEPENDENCIES) $(EXTRA_libs_bytereader_noinline_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bytereader-noinline$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bytereader_noinline_OBJECTS) $(libs_bytereader_noinline_LDADD) $(LIBS) +libs/bytewriter.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bytewriter$(EXEEXT): $(libs_bytewriter_OBJECTS) $(libs_bytewriter_DEPENDENCIES) $(EXTRA_libs_bytewriter_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bytewriter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bytewriter_OBJECTS) $(libs_bytewriter_LDADD) $(LIBS) +libs/bytewriter-noinline.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/bytewriter-noinline$(EXEEXT): $(libs_bytewriter_noinline_OBJECTS) $(libs_bytewriter_noinline_DEPENDENCIES) $(EXTRA_libs_bytewriter_noinline_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/bytewriter-noinline$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_bytewriter_noinline_OBJECTS) $(libs_bytewriter_noinline_LDADD) $(LIBS) +libs/collectpads.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/collectpads$(EXEEXT): $(libs_collectpads_OBJECTS) $(libs_collectpads_DEPENDENCIES) $(EXTRA_libs_collectpads_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/collectpads$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_collectpads_OBJECTS) $(libs_collectpads_LDADD) $(LIBS) +libs/controller.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/controller$(EXEEXT): $(libs_controller_OBJECTS) $(libs_controller_DEPENDENCIES) $(EXTRA_libs_controller_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/controller$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_controller_OBJECTS) $(libs_controller_LDADD) $(LIBS) +libs/flowcombiner.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/flowcombiner$(EXEEXT): $(libs_flowcombiner_OBJECTS) $(libs_flowcombiner_DEPENDENCIES) $(EXTRA_libs_flowcombiner_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/flowcombiner$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_flowcombiner_OBJECTS) $(libs_flowcombiner_LDADD) $(LIBS) +libs/gstharness.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/gstharness$(EXEEXT): $(libs_gstharness_OBJECTS) $(libs_gstharness_DEPENDENCIES) $(EXTRA_libs_gstharness_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/gstharness$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_gstharness_OBJECTS) $(libs_gstharness_LDADD) $(LIBS) +libs/gstlibscpp.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/gstlibscpp$(EXEEXT): $(libs_gstlibscpp_OBJECTS) $(libs_gstlibscpp_DEPENDENCIES) $(EXTRA_libs_gstlibscpp_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/gstlibscpp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(libs_gstlibscpp_OBJECTS) $(libs_gstlibscpp_LDADD) $(LIBS) +libs/gstnetclientclock.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/gstnetclientclock$(EXEEXT): $(libs_gstnetclientclock_OBJECTS) $(libs_gstnetclientclock_DEPENDENCIES) $(EXTRA_libs_gstnetclientclock_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/gstnetclientclock$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_gstnetclientclock_OBJECTS) $(libs_gstnetclientclock_LDADD) $(LIBS) +libs/gstnettimeprovider.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/gstnettimeprovider$(EXEEXT): $(libs_gstnettimeprovider_OBJECTS) $(libs_gstnettimeprovider_DEPENDENCIES) $(EXTRA_libs_gstnettimeprovider_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/gstnettimeprovider$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_gstnettimeprovider_OBJECTS) $(libs_gstnettimeprovider_LDADD) $(LIBS) +libs/gsttestclock.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/gsttestclock$(EXEEXT): $(libs_gsttestclock_OBJECTS) $(libs_gsttestclock_DEPENDENCIES) $(EXTRA_libs_gsttestclock_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/gsttestclock$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_gsttestclock_OBJECTS) $(libs_gsttestclock_LDADD) $(LIBS) +libs/libsabi.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/libsabi$(EXEEXT): $(libs_libsabi_OBJECTS) $(libs_libsabi_DEPENDENCIES) $(EXTRA_libs_libsabi_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/libsabi$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_libsabi_OBJECTS) $(libs_libsabi_LDADD) $(LIBS) +libs/queuearray.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/queuearray$(EXEEXT): $(libs_queuearray_OBJECTS) $(libs_queuearray_DEPENDENCIES) $(EXTRA_libs_queuearray_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/queuearray$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_queuearray_OBJECTS) $(libs_queuearray_LDADD) $(LIBS) +libs/sparsefile.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/sparsefile$(EXEEXT): $(libs_sparsefile_OBJECTS) $(libs_sparsefile_DEPENDENCIES) $(EXTRA_libs_sparsefile_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/sparsefile$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_sparsefile_OBJECTS) $(libs_sparsefile_LDADD) $(LIBS) +libs/transform1.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/transform1$(EXEEXT): $(libs_transform1_OBJECTS) $(libs_transform1_DEPENDENCIES) $(EXTRA_libs_transform1_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/transform1$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_transform1_OBJECTS) $(libs_transform1_LDADD) $(LIBS) +libs/transform2.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/transform2$(EXEEXT): $(libs_transform2_OBJECTS) $(libs_transform2_DEPENDENCIES) $(EXTRA_libs_transform2_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/transform2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_transform2_OBJECTS) $(libs_transform2_LDADD) $(LIBS) +libs/typefindhelper.$(OBJEXT): libs/$(am__dirstamp) \ + libs/$(DEPDIR)/$(am__dirstamp) + +libs/typefindhelper$(EXEEXT): $(libs_typefindhelper_OBJECTS) $(libs_typefindhelper_DEPENDENCIES) $(EXTRA_libs_typefindhelper_DEPENDENCIES) libs/$(am__dirstamp) + @rm -f libs/typefindhelper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(libs_typefindhelper_OBJECTS) $(libs_typefindhelper_LDADD) $(LIBS) +pipelines/$(am__dirstamp): + @$(MKDIR_P) pipelines + @: > pipelines/$(am__dirstamp) +pipelines/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) pipelines/$(DEPDIR) + @: > pipelines/$(DEPDIR)/$(am__dirstamp) +pipelines/cleanup.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/cleanup$(EXEEXT): $(pipelines_cleanup_OBJECTS) $(pipelines_cleanup_DEPENDENCIES) $(EXTRA_pipelines_cleanup_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/cleanup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_cleanup_OBJECTS) $(pipelines_cleanup_LDADD) $(LIBS) +pipelines/parse-disabled.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/parse-disabled$(EXEEXT): $(pipelines_parse_disabled_OBJECTS) $(pipelines_parse_disabled_DEPENDENCIES) $(EXTRA_pipelines_parse_disabled_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/parse-disabled$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_parse_disabled_OBJECTS) $(pipelines_parse_disabled_LDADD) $(LIBS) +pipelines/parse-launch.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/parse-launch$(EXEEXT): $(pipelines_parse_launch_OBJECTS) $(pipelines_parse_launch_DEPENDENCIES) $(EXTRA_pipelines_parse_launch_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/parse-launch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_parse_launch_OBJECTS) $(pipelines_parse_launch_LDADD) $(LIBS) +pipelines/queue-error.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/queue-error$(EXEEXT): $(pipelines_queue_error_OBJECTS) $(pipelines_queue_error_DEPENDENCIES) $(EXTRA_pipelines_queue_error_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/queue-error$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_queue_error_OBJECTS) $(pipelines_queue_error_LDADD) $(LIBS) +pipelines/seek.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/seek$(EXEEXT): $(pipelines_seek_OBJECTS) $(pipelines_seek_DEPENDENCIES) $(EXTRA_pipelines_seek_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/seek$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_seek_OBJECTS) $(pipelines_seek_LDADD) $(LIBS) +pipelines/simple-launch-lines.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/simple-launch-lines$(EXEEXT): $(pipelines_simple_launch_lines_OBJECTS) $(pipelines_simple_launch_lines_DEPENDENCIES) $(EXTRA_pipelines_simple_launch_lines_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/simple-launch-lines$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_simple_launch_lines_OBJECTS) $(pipelines_simple_launch_lines_LDADD) $(LIBS) +pipelines/stress.$(OBJEXT): pipelines/$(am__dirstamp) \ + pipelines/$(DEPDIR)/$(am__dirstamp) + +pipelines/stress$(EXEEXT): $(pipelines_stress_OBJECTS) $(pipelines_stress_DEPENDENCIES) $(EXTRA_pipelines_stress_DEPENDENCIES) pipelines/$(am__dirstamp) + @rm -f pipelines/stress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelines_stress_OBJECTS) $(pipelines_stress_LDADD) $(LIBS) +tools/$(am__dirstamp): + @$(MKDIR_P) tools + @: > tools/$(am__dirstamp) +tools/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tools/$(DEPDIR) + @: > tools/$(DEPDIR)/$(am__dirstamp) +tools/gstinspect.$(OBJEXT): tools/$(am__dirstamp) \ + tools/$(DEPDIR)/$(am__dirstamp) + +tools/gstinspect$(EXEEXT): $(tools_gstinspect_OBJECTS) $(tools_gstinspect_DEPENDENCIES) $(EXTRA_tools_gstinspect_DEPENDENCIES) tools/$(am__dirstamp) + @rm -f tools/gstinspect$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tools_gstinspect_OBJECTS) $(tools_gstinspect_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f elements/*.$(OBJEXT) + -rm -f generic/*.$(OBJEXT) + -rm -f gst/*.$(OBJEXT) + -rm -f libs/*.$(OBJEXT) + -rm -f pipelines/*.$(OBJEXT) + -rm -f tools/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/capsfilter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/concat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/dataurisrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/elements_fdsrc-fdsrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/elements_filesrc-filesrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/fakesink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/fakesrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/filesink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/funnel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/identity.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/multiqueue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/queue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/queue2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/selector.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/streamiddemux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/tee.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@elements/$(DEPDIR)/valve.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/sinks.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/states.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gst.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstabi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstatomicqueue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstbin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstbuffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstbufferlist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstbufferpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstbus.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstcaps.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstcapsfeatures.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstchildproxy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstcontext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstcontroller.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstcpp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstdatetime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstdeinit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstdevice.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstelement.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstelementfactory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstevent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstghostpad.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstiterator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstmemory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstmessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstmeta.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstminiobject.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstobject.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstpad.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstparamspecs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstpipeline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstplugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstpoll.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstpreset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstpromise.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstprotection.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstquery.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstregistry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstsegment.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gststream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gststructure.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstsystemclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsttag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsttagsetter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsttask.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsttoc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsttocsetter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gsturi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstutils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gst/$(DEPDIR)/gstvalue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/adapter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/aggregator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/baseparse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/basesink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/basesrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bitreader-noinline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bitreader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bytereader-noinline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bytereader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bytewriter-noinline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/bytewriter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/collectpads.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/controller.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/flowcombiner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/gstharness.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/gstlibscpp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/gstnetclientclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/gstnettimeprovider.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/gsttestclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/libsabi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/queuearray.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/sparsefile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/transform1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/transform2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libs/$(DEPDIR)/typefindhelper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/cleanup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/parse-disabled.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/parse-launch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/queue-error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/seek.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/simple-launch-lines.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pipelines/$(DEPDIR)/stress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/gstinspect.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +elements/elements_fdsrc-fdsrc.o: elements/fdsrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_fdsrc_CFLAGS) $(CFLAGS) -MT elements/elements_fdsrc-fdsrc.o -MD -MP -MF elements/$(DEPDIR)/elements_fdsrc-fdsrc.Tpo -c -o elements/elements_fdsrc-fdsrc.o `test -f 'elements/fdsrc.c' || echo '$(srcdir)/'`elements/fdsrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) elements/$(DEPDIR)/elements_fdsrc-fdsrc.Tpo elements/$(DEPDIR)/elements_fdsrc-fdsrc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elements/fdsrc.c' object='elements/elements_fdsrc-fdsrc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_fdsrc_CFLAGS) $(CFLAGS) -c -o elements/elements_fdsrc-fdsrc.o `test -f 'elements/fdsrc.c' || echo '$(srcdir)/'`elements/fdsrc.c + +elements/elements_fdsrc-fdsrc.obj: elements/fdsrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_fdsrc_CFLAGS) $(CFLAGS) -MT elements/elements_fdsrc-fdsrc.obj -MD -MP -MF elements/$(DEPDIR)/elements_fdsrc-fdsrc.Tpo -c -o elements/elements_fdsrc-fdsrc.obj `if test -f 'elements/fdsrc.c'; then $(CYGPATH_W) 'elements/fdsrc.c'; else $(CYGPATH_W) '$(srcdir)/elements/fdsrc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) elements/$(DEPDIR)/elements_fdsrc-fdsrc.Tpo elements/$(DEPDIR)/elements_fdsrc-fdsrc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elements/fdsrc.c' object='elements/elements_fdsrc-fdsrc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_fdsrc_CFLAGS) $(CFLAGS) -c -o elements/elements_fdsrc-fdsrc.obj `if test -f 'elements/fdsrc.c'; then $(CYGPATH_W) 'elements/fdsrc.c'; else $(CYGPATH_W) '$(srcdir)/elements/fdsrc.c'; fi` + +elements/elements_filesrc-filesrc.o: elements/filesrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_filesrc_CFLAGS) $(CFLAGS) -MT elements/elements_filesrc-filesrc.o -MD -MP -MF elements/$(DEPDIR)/elements_filesrc-filesrc.Tpo -c -o elements/elements_filesrc-filesrc.o `test -f 'elements/filesrc.c' || echo '$(srcdir)/'`elements/filesrc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) elements/$(DEPDIR)/elements_filesrc-filesrc.Tpo elements/$(DEPDIR)/elements_filesrc-filesrc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elements/filesrc.c' object='elements/elements_filesrc-filesrc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_filesrc_CFLAGS) $(CFLAGS) -c -o elements/elements_filesrc-filesrc.o `test -f 'elements/filesrc.c' || echo '$(srcdir)/'`elements/filesrc.c + +elements/elements_filesrc-filesrc.obj: elements/filesrc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_filesrc_CFLAGS) $(CFLAGS) -MT elements/elements_filesrc-filesrc.obj -MD -MP -MF elements/$(DEPDIR)/elements_filesrc-filesrc.Tpo -c -o elements/elements_filesrc-filesrc.obj `if test -f 'elements/filesrc.c'; then $(CYGPATH_W) 'elements/filesrc.c'; else $(CYGPATH_W) '$(srcdir)/elements/filesrc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) elements/$(DEPDIR)/elements_filesrc-filesrc.Tpo elements/$(DEPDIR)/elements_filesrc-filesrc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elements/filesrc.c' object='elements/elements_filesrc-filesrc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(elements_filesrc_CFLAGS) $(CFLAGS) -c -o elements/elements_filesrc-filesrc.obj `if test -f 'elements/filesrc.c'; then $(CYGPATH_W) 'elements/filesrc.c'; else $(CYGPATH_W) '$(srcdir)/elements/filesrc.c'; fi` + +gst/gst_gsttracerrecord-gsttracerrecord.o: gst/gsttracerrecord.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_gsttracerrecord_CFLAGS) $(CFLAGS) -MT gst/gst_gsttracerrecord-gsttracerrecord.o -MD -MP -MF gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Tpo -c -o gst/gst_gsttracerrecord-gsttracerrecord.o `test -f 'gst/gsttracerrecord.c' || echo '$(srcdir)/'`gst/gsttracerrecord.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Tpo gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst/gsttracerrecord.c' object='gst/gst_gsttracerrecord-gsttracerrecord.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_gsttracerrecord_CFLAGS) $(CFLAGS) -c -o gst/gst_gsttracerrecord-gsttracerrecord.o `test -f 'gst/gsttracerrecord.c' || echo '$(srcdir)/'`gst/gsttracerrecord.c + +gst/gst_gsttracerrecord-gsttracerrecord.obj: gst/gsttracerrecord.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_gsttracerrecord_CFLAGS) $(CFLAGS) -MT gst/gst_gsttracerrecord-gsttracerrecord.obj -MD -MP -MF gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Tpo -c -o gst/gst_gsttracerrecord-gsttracerrecord.obj `if test -f 'gst/gsttracerrecord.c'; then $(CYGPATH_W) 'gst/gsttracerrecord.c'; else $(CYGPATH_W) '$(srcdir)/gst/gsttracerrecord.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Tpo gst/$(DEPDIR)/gst_gsttracerrecord-gsttracerrecord.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst/gsttracerrecord.c' object='gst/gst_gsttracerrecord-gsttracerrecord.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_gsttracerrecord_CFLAGS) $(CFLAGS) -c -o gst/gst_gsttracerrecord-gsttracerrecord.obj `if test -f 'gst/gsttracerrecord.c'; then $(CYGPATH_W) 'gst/gsttracerrecord.c'; else $(CYGPATH_W) '$(srcdir)/gst/gsttracerrecord.c'; fi` + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf elements/.libs elements/_libs + -rm -rf generic/.libs generic/_libs + -rm -rf gst/.libs gst/_libs + -rm -rf libs/.libs libs/_libs + -rm -rf pipelines/.libs pipelines/_libs + -rm -rf tools/.libs tools/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +gst/gstabi.log: gst/gstabi$(EXEEXT) + @p='gst/gstabi$(EXEEXT)'; \ + b='gst/gstabi'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstatomicqueue.log: gst/gstatomicqueue$(EXEEXT) + @p='gst/gstatomicqueue$(EXEEXT)'; \ + b='gst/gstatomicqueue'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstbuffer.log: gst/gstbuffer$(EXEEXT) + @p='gst/gstbuffer$(EXEEXT)'; \ + b='gst/gstbuffer'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstbufferlist.log: gst/gstbufferlist$(EXEEXT) + @p='gst/gstbufferlist$(EXEEXT)'; \ + b='gst/gstbufferlist'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstbufferpool.log: gst/gstbufferpool$(EXEEXT) + @p='gst/gstbufferpool$(EXEEXT)'; \ + b='gst/gstbufferpool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstmeta.log: gst/gstmeta$(EXEEXT) + @p='gst/gstmeta$(EXEEXT)'; \ + b='gst/gstmeta'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstmemory.log: gst/gstmemory$(EXEEXT) + @p='gst/gstmemory$(EXEEXT)'; \ + b='gst/gstmemory'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstbus.log: gst/gstbus$(EXEEXT) + @p='gst/gstbus$(EXEEXT)'; \ + b='gst/gstbus'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstcaps.log: gst/gstcaps$(EXEEXT) + @p='gst/gstcaps$(EXEEXT)'; \ + b='gst/gstcaps'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstcapsfeatures.log: gst/gstcapsfeatures$(EXEEXT) + @p='gst/gstcapsfeatures$(EXEEXT)'; \ + b='gst/gstcapsfeatures'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstcpp.log: gst/gstcpp$(EXEEXT) + @p='gst/gstcpp$(EXEEXT)'; \ + b='gst/gstcpp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/gstlibscpp.log: libs/gstlibscpp$(EXEEXT) + @p='libs/gstlibscpp$(EXEEXT)'; \ + b='libs/gstlibscpp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstdatetime.log: gst/gstdatetime$(EXEEXT) + @p='gst/gstdatetime$(EXEEXT)'; \ + b='gst/gstdatetime'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstdeinit.log: gst/gstdeinit$(EXEEXT) + @p='gst/gstdeinit$(EXEEXT)'; \ + b='gst/gstdeinit'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstdevice.log: gst/gstdevice$(EXEEXT) + @p='gst/gstdevice$(EXEEXT)'; \ + b='gst/gstdevice'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstinfo.log: gst/gstinfo$(EXEEXT) + @p='gst/gstinfo$(EXEEXT)'; \ + b='gst/gstinfo'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstiterator.log: gst/gstiterator$(EXEEXT) + @p='gst/gstiterator$(EXEEXT)'; \ + b='gst/gstiterator'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstmessage.log: gst/gstmessage$(EXEEXT) + @p='gst/gstmessage$(EXEEXT)'; \ + b='gst/gstmessage'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstminiobject.log: gst/gstminiobject$(EXEEXT) + @p='gst/gstminiobject$(EXEEXT)'; \ + b='gst/gstminiobject'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstobject.log: gst/gstobject$(EXEEXT) + @p='gst/gstobject$(EXEEXT)'; \ + b='gst/gstobject'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstpad.log: gst/gstpad$(EXEEXT) + @p='gst/gstpad$(EXEEXT)'; \ + b='gst/gstpad'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstparamspecs.log: gst/gstparamspecs$(EXEEXT) + @p='gst/gstparamspecs$(EXEEXT)'; \ + b='gst/gstparamspecs'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstpipeline.log: gst/gstpipeline$(EXEEXT) + @p='gst/gstpipeline$(EXEEXT)'; \ + b='gst/gstpipeline'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstpoll.log: gst/gstpoll$(EXEEXT) + @p='gst/gstpoll$(EXEEXT)'; \ + b='gst/gstpoll'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstprotection.log: gst/gstprotection$(EXEEXT) + @p='gst/gstprotection$(EXEEXT)'; \ + b='gst/gstprotection'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstprintf.log: gst/gstprintf$(EXEEXT) + @p='gst/gstprintf$(EXEEXT)'; \ + b='gst/gstprintf'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstpromise.log: gst/gstpromise$(EXEEXT) + @p='gst/gstpromise$(EXEEXT)'; \ + b='gst/gstpromise'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstsegment.log: gst/gstsegment$(EXEEXT) + @p='gst/gstsegment$(EXEEXT)'; \ + b='gst/gstsegment'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstsystemclock.log: gst/gstsystemclock$(EXEEXT) + @p='gst/gstsystemclock$(EXEEXT)'; \ + b='gst/gstsystemclock'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstclock.log: gst/gstclock$(EXEEXT) + @p='gst/gstclock$(EXEEXT)'; \ + b='gst/gstclock'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gststream.log: gst/gststream$(EXEEXT) + @p='gst/gststream$(EXEEXT)'; \ + b='gst/gststream'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gststructure.log: gst/gststructure$(EXEEXT) + @p='gst/gststructure$(EXEEXT)'; \ + b='gst/gststructure'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttag.log: gst/gsttag$(EXEEXT) + @p='gst/gsttag$(EXEEXT)'; \ + b='gst/gsttag'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttracerrecord.log: gst/gsttracerrecord$(EXEEXT) + @p='gst/gsttracerrecord$(EXEEXT)'; \ + b='gst/gsttracerrecord'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttagsetter.log: gst/gsttagsetter$(EXEEXT) + @p='gst/gsttagsetter$(EXEEXT)'; \ + b='gst/gsttagsetter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttask.log: gst/gsttask$(EXEEXT) + @p='gst/gsttask$(EXEEXT)'; \ + b='gst/gsttask'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttoc.log: gst/gsttoc$(EXEEXT) + @p='gst/gsttoc$(EXEEXT)'; \ + b='gst/gsttoc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsttocsetter.log: gst/gsttocsetter$(EXEEXT) + @p='gst/gsttocsetter$(EXEEXT)'; \ + b='gst/gsttocsetter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstvalue.log: gst/gstvalue$(EXEEXT) + @p='gst/gstvalue$(EXEEXT)'; \ + b='gst/gstvalue'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +generic/states.log: generic/states$(EXEEXT) + @p='generic/states$(EXEEXT)'; \ + b='generic/states'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/simple-launch-lines.log: pipelines/simple-launch-lines$(EXEEXT) + @p='pipelines/simple-launch-lines$(EXEEXT)'; \ + b='pipelines/simple-launch-lines'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/cleanup.log: pipelines/cleanup$(EXEEXT) + @p='pipelines/cleanup$(EXEEXT)'; \ + b='pipelines/cleanup'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/parse-launch.log: pipelines/parse-launch$(EXEEXT) + @p='pipelines/parse-launch$(EXEEXT)'; \ + b='pipelines/parse-launch'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/parse-disabled.log: pipelines/parse-disabled$(EXEEXT) + @p='pipelines/parse-disabled$(EXEEXT)'; \ + b='pipelines/parse-disabled'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gst.log: gst/gst$(EXEEXT) + @p='gst/gst$(EXEEXT)'; \ + b='gst/gst'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstbin.log: gst/gstbin$(EXEEXT) + @p='gst/gstbin$(EXEEXT)'; \ + b='gst/gstbin'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstchildproxy.log: gst/gstchildproxy$(EXEEXT) + @p='gst/gstchildproxy$(EXEEXT)'; \ + b='gst/gstchildproxy'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstcontext.log: gst/gstcontext$(EXEEXT) + @p='gst/gstcontext$(EXEEXT)'; \ + b='gst/gstcontext'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstcontroller.log: gst/gstcontroller$(EXEEXT) + @p='gst/gstcontroller$(EXEEXT)'; \ + b='gst/gstcontroller'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstelement.log: gst/gstelement$(EXEEXT) + @p='gst/gstelement$(EXEEXT)'; \ + b='gst/gstelement'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstelementfactory.log: gst/gstelementfactory$(EXEEXT) + @p='gst/gstelementfactory$(EXEEXT)'; \ + b='gst/gstelementfactory'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstevent.log: gst/gstevent$(EXEEXT) + @p='gst/gstevent$(EXEEXT)'; \ + b='gst/gstevent'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstghostpad.log: gst/gstghostpad$(EXEEXT) + @p='gst/gstghostpad$(EXEEXT)'; \ + b='gst/gstghostpad'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstplugin.log: gst/gstplugin$(EXEEXT) + @p='gst/gstplugin$(EXEEXT)'; \ + b='gst/gstplugin'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstpreset.log: gst/gstpreset$(EXEEXT) + @p='gst/gstpreset$(EXEEXT)'; \ + b='gst/gstpreset'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstquery.log: gst/gstquery$(EXEEXT) + @p='gst/gstquery$(EXEEXT)'; \ + b='gst/gstquery'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstregistry.log: gst/gstregistry$(EXEEXT) + @p='gst/gstregistry$(EXEEXT)'; \ + b='gst/gstregistry'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gsturi.log: gst/gsturi$(EXEEXT) + @p='gst/gsturi$(EXEEXT)'; \ + b='gst/gsturi'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +gst/gstutils.log: gst/gstutils$(EXEEXT) + @p='gst/gstutils$(EXEEXT)'; \ + b='gst/gstutils'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +generic/sinks.log: generic/sinks$(EXEEXT) + @p='generic/sinks$(EXEEXT)'; \ + b='generic/sinks'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/capsfilter.log: elements/capsfilter$(EXEEXT) + @p='elements/capsfilter$(EXEEXT)'; \ + b='elements/capsfilter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/concat.log: elements/concat$(EXEEXT) + @p='elements/concat$(EXEEXT)'; \ + b='elements/concat'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/dataurisrc.log: elements/dataurisrc$(EXEEXT) + @p='elements/dataurisrc$(EXEEXT)'; \ + b='elements/dataurisrc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/fakesink.log: elements/fakesink$(EXEEXT) + @p='elements/fakesink$(EXEEXT)'; \ + b='elements/fakesink'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/fakesrc.log: elements/fakesrc$(EXEEXT) + @p='elements/fakesrc$(EXEEXT)'; \ + b='elements/fakesrc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/fdsrc.log: elements/fdsrc$(EXEEXT) + @p='elements/fdsrc$(EXEEXT)'; \ + b='elements/fdsrc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/filesink.log: elements/filesink$(EXEEXT) + @p='elements/filesink$(EXEEXT)'; \ + b='elements/filesink'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/filesrc.log: elements/filesrc$(EXEEXT) + @p='elements/filesrc$(EXEEXT)'; \ + b='elements/filesrc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/funnel.log: elements/funnel$(EXEEXT) + @p='elements/funnel$(EXEEXT)'; \ + b='elements/funnel'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/identity.log: elements/identity$(EXEEXT) + @p='elements/identity$(EXEEXT)'; \ + b='elements/identity'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/multiqueue.log: elements/multiqueue$(EXEEXT) + @p='elements/multiqueue$(EXEEXT)'; \ + b='elements/multiqueue'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/selector.log: elements/selector$(EXEEXT) + @p='elements/selector$(EXEEXT)'; \ + b='elements/selector'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/tee.log: elements/tee$(EXEEXT) + @p='elements/tee$(EXEEXT)'; \ + b='elements/tee'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/queue.log: elements/queue$(EXEEXT) + @p='elements/queue$(EXEEXT)'; \ + b='elements/queue'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/queue2.log: elements/queue2$(EXEEXT) + @p='elements/queue2$(EXEEXT)'; \ + b='elements/queue2'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/valve.log: elements/valve$(EXEEXT) + @p='elements/valve$(EXEEXT)'; \ + b='elements/valve'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +elements/streamiddemux.log: elements/streamiddemux$(EXEEXT) + @p='elements/streamiddemux$(EXEEXT)'; \ + b='elements/streamiddemux'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/baseparse.log: libs/baseparse$(EXEEXT) + @p='libs/baseparse$(EXEEXT)'; \ + b='libs/baseparse'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/basesrc.log: libs/basesrc$(EXEEXT) + @p='libs/basesrc$(EXEEXT)'; \ + b='libs/basesrc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/basesink.log: libs/basesink$(EXEEXT) + @p='libs/basesink$(EXEEXT)'; \ + b='libs/basesink'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/sparsefile.log: libs/sparsefile$(EXEEXT) + @p='libs/sparsefile$(EXEEXT)'; \ + b='libs/sparsefile'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/controller.log: libs/controller$(EXEEXT) + @p='libs/controller$(EXEEXT)'; \ + b='libs/controller'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/queuearray.log: libs/queuearray$(EXEEXT) + @p='libs/queuearray$(EXEEXT)'; \ + b='libs/queuearray'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/typefindhelper.log: libs/typefindhelper$(EXEEXT) + @p='libs/typefindhelper$(EXEEXT)'; \ + b='libs/typefindhelper'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/seek.log: pipelines/seek$(EXEEXT) + @p='pipelines/seek$(EXEEXT)'; \ + b='pipelines/seek'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/stress.log: pipelines/stress$(EXEEXT) + @p='pipelines/stress$(EXEEXT)'; \ + b='pipelines/stress'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelines/queue-error.log: pipelines/queue-error$(EXEEXT) + @p='pipelines/queue-error$(EXEEXT)'; \ + b='pipelines/queue-error'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/libsabi.log: libs/libsabi$(EXEEXT) + @p='libs/libsabi$(EXEEXT)'; \ + b='libs/libsabi'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/adapter.log: libs/adapter$(EXEEXT) + @p='libs/adapter$(EXEEXT)'; \ + b='libs/adapter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/aggregator.log: libs/aggregator$(EXEEXT) + @p='libs/aggregator$(EXEEXT)'; \ + b='libs/aggregator'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bitreader.log: libs/bitreader$(EXEEXT) + @p='libs/bitreader$(EXEEXT)'; \ + b='libs/bitreader'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bytereader.log: libs/bytereader$(EXEEXT) + @p='libs/bytereader$(EXEEXT)'; \ + b='libs/bytereader'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bytewriter.log: libs/bytewriter$(EXEEXT) + @p='libs/bytewriter$(EXEEXT)'; \ + b='libs/bytewriter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bitreader-noinline.log: libs/bitreader-noinline$(EXEEXT) + @p='libs/bitreader-noinline$(EXEEXT)'; \ + b='libs/bitreader-noinline'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bytereader-noinline.log: libs/bytereader-noinline$(EXEEXT) + @p='libs/bytereader-noinline$(EXEEXT)'; \ + b='libs/bytereader-noinline'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/bytewriter-noinline.log: libs/bytewriter-noinline$(EXEEXT) + @p='libs/bytewriter-noinline$(EXEEXT)'; \ + b='libs/bytewriter-noinline'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/flowcombiner.log: libs/flowcombiner$(EXEEXT) + @p='libs/flowcombiner$(EXEEXT)'; \ + b='libs/flowcombiner'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/collectpads.log: libs/collectpads$(EXEEXT) + @p='libs/collectpads$(EXEEXT)'; \ + b='libs/collectpads'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/gstharness.log: libs/gstharness$(EXEEXT) + @p='libs/gstharness$(EXEEXT)'; \ + b='libs/gstharness'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/gstnetclientclock.log: libs/gstnetclientclock$(EXEEXT) + @p='libs/gstnetclientclock$(EXEEXT)'; \ + b='libs/gstnetclientclock'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/gstnettimeprovider.log: libs/gstnettimeprovider$(EXEEXT) + @p='libs/gstnettimeprovider$(EXEEXT)'; \ + b='libs/gstnettimeprovider'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/gsttestclock.log: libs/gsttestclock$(EXEEXT) + @p='libs/gsttestclock$(EXEEXT)'; \ + b='libs/gsttestclock'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/transform1.log: libs/transform1$(EXEEXT) + @p='libs/transform1$(EXEEXT)'; \ + b='libs/transform1'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +libs/transform2.log: libs/transform2$(EXEEXT) + @p='libs/transform2$(EXEEXT)'; \ + b='libs/transform2'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tools/gstinspect.log: tools/gstinspect$(EXEEXT) + @p='tools/gstinspect$(EXEEXT)'; \ + b='tools/gstinspect'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f elements/$(DEPDIR)/$(am__dirstamp) + -rm -f elements/$(am__dirstamp) + -rm -f generic/$(DEPDIR)/$(am__dirstamp) + -rm -f generic/$(am__dirstamp) + -rm -f gst/$(DEPDIR)/$(am__dirstamp) + -rm -f gst/$(am__dirstamp) + -rm -f libs/$(DEPDIR)/$(am__dirstamp) + -rm -f libs/$(am__dirstamp) + -rm -f pipelines/$(DEPDIR)/$(am__dirstamp) + -rm -f pipelines/$(am__dirstamp) + -rm -f tools/$(DEPDIR)/$(am__dirstamp) + -rm -f tools/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf elements/$(DEPDIR) generic/$(DEPDIR) gst/$(DEPDIR) libs/$(DEPDIR) pipelines/$(DEPDIR) tools/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf elements/$(DEPDIR) generic/$(DEPDIR) gst/$(DEPDIR) libs/$(DEPDIR) pipelines/$(DEPDIR) tools/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# keep target around, since it's referenced in the modules' Makefiles +clean-local-check: + @echo + +# hangs spectacularly on some machines, so let's not do this by default yet +@HAVE_VALGRIND_TRUE@check-valgrind: +@HAVE_VALGRIND_TRUE@ $(MAKE) valgrind +@HAVE_VALGRIND_FALSE@check-valgrind: +@HAVE_VALGRIND_FALSE@ @true + +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: % + @$(AM_TESTS_ENVIRONMENT) \ + $* || \ + $(AM_TESTS_ENVIRONMENT) \ + GST_DEBUG=$$GST_DEBUG,*:2 \ + $* + +# just like 'check', but don't run it again if it fails (useful for debugging) +%.check-norepeat: % + @$(AM_TESTS_ENVIRONMENT) \ + $* + +# run any given test in a loop +%.torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(AM_TESTS_ENVIRONMENT) \ + $*; done + +# run any given test in an infinite loop +%.forever: % + @while true; do \ + $(AM_TESTS_ENVIRONMENT) \ + $* || break; done + +# valgrind any given test by running make test.valgrind +%.valgrind: % + @valgrind_log=$(subst /,-,$*-valgrind.log); \ + $(AM_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 \ + --show-possibly-lost=no \ + --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: % + @$(AM_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 \ + --show-possibly-lost=no \ + --leak-resolution=high --num-callers=20 \ + --gen-suppressions=all \ + ./$* 2>&1 | tee suppressions.log + +# valgrind torture any given test +%.valgrind-torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) $*.valgrind || \ + (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 + +# 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: % + @$(AM_TESTS_ENVIRONMENT) \ + CK_FORK=no \ + $(LIBTOOL) --mode=execute \ + gdb $(GDB_ARGS) $* + +%.gdb-forever: % + @while $(MAKE) GDB_ARGS="-ex run -ex quit" $*.gdb ; do \ + sleep 1; done + +%.lcov-reset: + $(MAKE) $*.lcov-run + $(MAKE) $*.lcov-report + +%.lcov: % + $(MAKE) $*.lcov-reset + +@GST_GCOV_ENABLED_TRUE@%.lcov-clean: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) -C $(top_builddir) lcov-clean + +@GST_GCOV_ENABLED_TRUE@%.lcov-run: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) $*.lcov-clean +@GST_GCOV_ENABLED_TRUE@ $(MAKE) $*.check + +@GST_GCOV_ENABLED_TRUE@%.lcov-report: +@GST_GCOV_ENABLED_TRUE@ $(MAKE) -C $(top_builddir) lcov-report +@GST_GCOV_ENABLED_FALSE@%.lcov-run: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +@GST_GCOV_ENABLED_FALSE@%.lcov-report: +@GST_GCOV_ENABLED_FALSE@ echo "Need to reconfigure with --enable-gcov" + +# torture tests +torture: $(TESTS) + -rm test-registry.* + @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.* + @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; valgrind_targets=""; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + valgrind_targets="$$valgrind_targets $$t.valgrind"; \ + done; \ + if ! $(MAKE) $$valgrind_targets ; then \ + echo "Some tests had leaks or errors under valgrind"; \ + false; \ + fi + +# valgrind all tests until failure +valgrind-forever: $(TESTS) + -rm test-registry.* + @echo "Forever valgrinding tests ..." + @while true; do \ + $(MAKE) valgrind || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind torture all tests +valgrind-torture: $(TESTS) + -rm test-registry.* + @echo "Torturing and valgrinding tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) valgrind || \ + (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 + +# 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: + @echo "Inspecting features ..." + @for e in `$(AM_TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 \ + | cut -d: -f2`; \ + do echo Inspecting $$e; \ + $(GST_INSPECT) $$e > /dev/null 2>&1; done + +# build all tests +build-checks: $(TESTS) + +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, repeat with GST_DEBUG=*:2 if it fails" + @echo "make (dir)/(test).check-norepeat -- run the given check once, but don't run it again if it fails" + @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-forever -- valgrind all tests forever" + @echo "make valgrind-torture -- valgrind all tests $(LOOPS) times" + @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-torture -- valgrind the given test $(LOOPS) times" + @echo "make (dir)/(test).valgrind.gen-suppressions -- generate suppressions" + @echo " and save to suppressions.log" + @echo "make inspect -- inspect all plugin features" + @echo "make build-checks -- build all checks (but don't run them)" + @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 + +# override to _not_ install the test plugins +install-pluginLTLIBRARIES: + +clean-local: clean-local-check + +debug: + echo $(COVERAGE_FILES) + echo $(COVERAGE_FILES_REL) + +.PHONY: coverage +# we rebuild a registry and do gst-inspect so that all the get/set codepaths +# are also covered +@GST_GCOV_ENABLED_TRUE@coverage: +@GST_GCOV_ENABLED_TRUE@ for file in `find $(top_builddir) -name '*.gcda'`; do rm $$file; done +@GST_GCOV_ENABLED_TRUE@ -rm $(CHECK_REGISTRY) +@GST_GCOV_ENABLED_TRUE@ echo "Inspecting all elements" +@GST_GCOV_ENABLED_TRUE@ for e in `$(GST_INSPECT) | head -n -2 | cut -d: -f2`; do $(GST_INSPECT) $$e > /dev/null 2>&1; done +@GST_GCOV_ENABLED_TRUE@ make check +@GST_GCOV_ENABLED_TRUE@ make coverage-report +@GST_GCOV_ENABLED_FALSE@coverage: +@GST_GCOV_ENABLED_FALSE@ echo "You need to configure with --enable-gcov to get coverage data" +@GST_GCOV_ENABLED_FALSE@ exit 1 + +coverage-report: + rm -r coverage + for dir in $(COVERAGE_DIRS); do \ + mkdir -p coverage/$$dir; \ + make -C $(top_builddir)/$$dir gcov; \ + done + for dir in $(COVERAGE_DIRS); do \ + files="`ls $(top_builddir)/$$dir/*.gcov.out 2> /dev/null`"; \ + if test ! -z "$$files"; then \ + perl $(top_srcdir)/common/coverage/coverage-report.pl \ + $(top_builddir)/$$dir/*.gcov.out > \ + coverage/$$dir/index.xml; \ + xsltproc $(top_srcdir)/common/coverage/coverage-report.xsl \ + coverage/$$dir/index.xml > coverage/$$dir/index.html; \ + fi; \ + done + for file in $(COVERAGE_FILES_REL); do \ + echo Generating coverage/$$file.html; \ + perl $(top_srcdir)/common/coverage/coverage-report-entry.pl \ + $(top_builddir)/$$file > coverage/$$file.html; \ + done + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/check/elements/capsfilter.c b/tests/check/elements/capsfilter.c new file mode 100644 index 0000000..b5c0a7b --- /dev/null +++ b/tests/check/elements/capsfilter.c @@ -0,0 +1,493 @@ +/* GStreamer unit test for capsfilter + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define CAPS_TEMPLATE_STRING \ + "audio/x-raw, " \ + "channels = (int) [ 1, 2], " \ + "rate = (int) [ 1, MAX ]" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CAPS_TEMPLATE_STRING) + ); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CAPS_TEMPLATE_STRING) + ); + +static GstStaticPadTemplate any_sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate any_srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GList *events = NULL; + +static gboolean +test_pad_eventfunc (GstPad * pad, GstObject * parent, GstEvent * event) +{ + events = g_list_append (events, event); + return TRUE; +} + +GST_START_TEST (test_unfixed_downstream_caps) +{ + GstElement *pipe, *src, *filter; + GstCaps *filter_caps; + GstPad *mysinkpad; + GstMessage *msg; + + pipe = gst_check_setup_element ("pipeline"); + + src = gst_check_setup_element ("fakesrc"); + g_object_set (src, "sizetype", 2, "sizemax", 1024, "num-buffers", 1, NULL); + + filter = gst_check_setup_element ("capsfilter"); + filter_caps = gst_caps_from_string ("audio/x-raw, rate=(int)44100"); + fail_unless (filter_caps != NULL); + g_object_set (filter, "caps", filter_caps, NULL); + + gst_bin_add_many (GST_BIN (pipe), src, filter, NULL); + fail_unless (gst_element_link (src, filter)); + + mysinkpad = gst_check_setup_sink_pad (filter, &sinktemplate); + gst_pad_set_active (mysinkpad, TRUE); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + /* wait for error on bus */ + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR, + "Expected ERROR message, got EOS message"); + gst_message_unref (msg); + + /* We don't expect any output buffers unless the check fails */ + fail_unless (buffers == NULL); + + /* cleanup */ + GST_DEBUG ("cleanup"); + + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (filter); + gst_check_teardown_element (pipe); + gst_caps_unref (filter_caps); +} + +GST_END_TEST; + +GST_START_TEST (test_caps_property) +{ + GstElement *filter; + GstCaps *filter_caps, *caps; + const gchar *caps_str; + + filter = gst_check_setup_element ("capsfilter"); + + /* verify that the set caps are actually set */ + caps_str = "audio/x-raw, rate=(int)44100, channels=(int)1"; + + filter_caps = gst_caps_from_string (caps_str); + fail_unless (GST_IS_CAPS (filter_caps)); + g_object_set (filter, "caps", filter_caps, NULL); + + g_object_get (filter, "caps", &caps, NULL); + fail_unless (gst_caps_is_equal (caps, filter_caps)); + gst_caps_unref (caps); + gst_caps_unref (filter_caps); + + /* verify that new caps set replace the old ones */ + caps_str = "video/x-raw, width=(int)320, height=(int)240"; + + filter_caps = gst_caps_from_string (caps_str); + fail_unless (GST_IS_CAPS (filter_caps)); + g_object_set (filter, "caps", filter_caps, NULL); + + g_object_get (filter, "caps", &caps, NULL); + fail_unless (gst_caps_is_equal (caps, filter_caps)); + gst_caps_unref (caps); + gst_caps_unref (filter_caps); + + /* make sure that NULL caps is interpreted as ANY */ + g_object_set (filter, "caps", NULL, NULL); + + g_object_get (filter, "caps", &filter_caps, NULL); + fail_unless (gst_caps_is_any (filter_caps)); + gst_caps_unref (filter_caps); + + gst_object_unref (filter); +} + +GST_END_TEST; + +GST_START_TEST (test_caps_query) +{ + GstElement *filter; + GstCaps *filter_caps; + const gchar *caps_str; + GstQuery *query; + GstCaps *caps; + + filter = gst_check_setup_element ("capsfilter"); + + /* set some caps, do a caps query with a filter resulting in no + * intersecting caps */ + caps_str = "audio/x-raw, rate=(int)44100, channels=(int)1"; + + filter_caps = gst_caps_from_string (caps_str); + fail_unless (GST_IS_CAPS (filter_caps)); + g_object_set (filter, "caps", filter_caps, NULL); + gst_caps_unref (filter_caps); + + caps_str = "video/x-raw, width=(int)320, height=(int)240"; + filter_caps = gst_caps_from_string (caps_str); + query = gst_query_new_caps (filter_caps); + gst_caps_unref (filter_caps); + fail_unless (gst_element_query (filter, query)); + gst_query_parse_caps_result (query, &caps); + fail_unless (gst_caps_is_empty (caps)); + gst_query_unref (query); + + gst_object_unref (filter); +} + +GST_END_TEST; + +GST_START_TEST (test_accept_caps_query) +{ + GstElement *filter; + GstCaps *filter_caps; + const gchar *caps_str; + GstQuery *query; + gboolean accepted; + GstPad *sinkpad; + GstPad *srcpad; + + filter = gst_check_setup_element ("capsfilter"); + + /* set some caps on (both pads of) the capsfilter */ + caps_str = "audio/x-raw, rate=(int)44100, channels=(int)1"; + + filter_caps = gst_caps_from_string (caps_str); + fail_unless (GST_IS_CAPS (filter_caps)); + g_object_set (filter, "caps", filter_caps, NULL); + gst_caps_unref (filter_caps); + + sinkpad = gst_element_get_static_pad (filter, "sink"); + + /* check that the set caps are acceptable on the sinkpad */ + caps_str = "audio/x-raw, rate=(int)44100, channels=(int)1"; + filter_caps = gst_caps_from_string (caps_str); + query = gst_query_new_accept_caps (filter_caps); + gst_caps_unref (filter_caps); + fail_unless (gst_pad_query (sinkpad, query)); + gst_query_parse_accept_caps_result (query, &accepted); + fail_unless (accepted); + gst_query_unref (query); + + /* and that unrelated caps are not acceptable */ + caps_str = "video/x-raw, width=(int)320, height=(int)240"; + filter_caps = gst_caps_from_string (caps_str); + query = gst_query_new_accept_caps (filter_caps); + gst_caps_unref (filter_caps); + fail_unless (gst_pad_query (sinkpad, query)); + gst_query_parse_accept_caps_result (query, &accepted); + fail_unless (!accepted); + gst_query_unref (query); + + gst_object_unref (sinkpad); + + /* now do the same for the src pad (which has the same caps) */ + srcpad = gst_element_get_static_pad (filter, "src"); + + caps_str = "audio/x-raw, rate=(int)44100, channels=(int)1"; + filter_caps = gst_caps_from_string (caps_str); + query = gst_query_new_accept_caps (filter_caps); + gst_caps_unref (filter_caps); + fail_unless (gst_pad_query (srcpad, query)); + gst_query_parse_accept_caps_result (query, &accepted); + fail_unless (accepted); + gst_query_unref (query); + + caps_str = "video/x-raw, width=(int)320, height=(int)240"; + filter_caps = gst_caps_from_string (caps_str); + query = gst_query_new_accept_caps (filter_caps); + gst_caps_unref (filter_caps); + fail_unless (gst_pad_query (srcpad, query)); + gst_query_parse_accept_caps_result (query, &accepted); + fail_unless (!accepted); + gst_query_unref (query); + + gst_object_unref (srcpad); + + gst_object_unref (filter); +} + +GST_END_TEST; + +GST_START_TEST (test_push_pending_events) +{ + GstElement *filter; + GstPad *mysinkpad; + GstPad *mysrcpad; + GstSegment segment; + GstTagList *tags; + GstBuffer *buffer; + GstEvent *event; + GstCaps *caps; + + filter = gst_check_setup_element ("capsfilter"); + mysinkpad = gst_check_setup_sink_pad (filter, &sinktemplate); + gst_pad_set_event_function (mysinkpad, test_pad_eventfunc); + gst_pad_set_active (mysinkpad, TRUE); + mysrcpad = gst_check_setup_src_pad (filter, &srctemplate); + gst_pad_set_active (mysrcpad, TRUE); + + fail_unless_equals_int (gst_element_set_state (filter, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + /* push the stream start */ + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_stream_start ("test-stream"))); + fail_unless (g_list_length (events) == 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* the tag should get trapped as we haven't pushed a caps yet */ + tags = gst_tag_list_new (GST_TAG_COMMENT, "testcomment", NULL); + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_tag (gst_tag_list_ref (tags)))); + fail_unless (g_list_length (events) == 0); + + /* push a caps */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)44100"); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + gst_caps_unref (caps); + fail_unless (g_list_length (events) == 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* push a segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + fail_unless (g_list_length (events) == 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* push a buffer, the tag should now be pushed downstream */ + buffer = gst_buffer_new_wrapped (g_malloc0 (1024), 1024); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + fail_unless (g_list_length (events) == 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* We don't expect any output buffers unless the check fails */ + fail_unless (g_list_length (buffers) == 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* cleanup */ + GST_DEBUG ("cleanup"); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (filter); + gst_check_teardown_sink_pad (filter); + gst_check_teardown_element (filter); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +GST_START_TEST (test_caps_change_mode_delayed) +{ + GstElement *filter; + GstPad *mysinkpad; + GstPad *mysrcpad; + GstSegment segment; + GstEvent *event; + GstCaps *caps; + + filter = gst_check_setup_element ("capsfilter"); + mysinkpad = gst_check_setup_sink_pad (filter, &any_sinktemplate); + gst_pad_set_event_function (mysinkpad, test_pad_eventfunc); + gst_pad_set_active (mysinkpad, TRUE); + mysrcpad = gst_check_setup_src_pad (filter, &any_srctemplate); + gst_pad_set_active (mysrcpad, TRUE); + + g_object_set (filter, "caps-change-mode", 1, NULL); + + fail_unless_equals_int (gst_element_set_state (filter, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + /* push the stream start */ + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_stream_start ("test-stream"))); + fail_unless_equals_int (g_list_length (events), 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* push a caps */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)44100"); + g_object_set (filter, "caps", caps, NULL); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + gst_caps_unref (caps); + fail_unless_equals_int (g_list_length (events), 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* push a segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + fail_unless_equals_int (g_list_length (events), 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* push a buffer */ + fail_unless_equals_int (gst_pad_push (mysrcpad, + gst_buffer_new_wrapped (g_malloc0 (1024), 1024)), GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* Set new incompatible caps */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)48000"); + g_object_set (filter, "caps", caps, NULL); + + /* push a buffer without updating the caps */ + fail_unless_equals_int (gst_pad_push (mysrcpad, + gst_buffer_new_wrapped (g_malloc0 (1024), 1024)), GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* No caps event here, we're still at the old caps */ + fail_unless (g_list_length (events) == 0); + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + gst_caps_unref (caps); + fail_unless_equals_int (g_list_length (events), 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + /* Push a new buffer, now we have the new caps */ + fail_unless_equals_int (gst_pad_push (mysrcpad, + gst_buffer_new_wrapped (g_malloc0 (1024), 1024)), GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* Set back old caps */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)44100"); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + /* push a buffer without updating the caps */ + fail_unless_equals_int (gst_pad_push (mysrcpad, + gst_buffer_new_wrapped (g_malloc0 (1024), 1024)), GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* Now set new caps again but the old caps are currently pushed */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)48000"); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + /* Race condition simulation here! */ + caps = gst_caps_from_string ("audio/x-raw, " + "channels=(int)2, " "rate = (int)44100"); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + gst_caps_unref (caps); + fail_unless_equals_int (g_list_length (events), 1); + event = events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + g_list_free_full (events, (GDestroyNotify) gst_event_unref); + events = NULL; + + fail_unless_equals_int (gst_pad_push (mysrcpad, + gst_buffer_new_wrapped (g_malloc0 (1024), 1024)), GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + /* cleanup */ + GST_DEBUG ("cleanup"); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (filter); + gst_check_teardown_sink_pad (filter); + gst_check_teardown_element (filter); +} + +GST_END_TEST; + +static Suite * +capsfilter_suite (void) +{ + Suite *s = suite_create ("capsfilter"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_unfixed_downstream_caps); + tcase_add_test (tc_chain, test_caps_property); + tcase_add_test (tc_chain, test_caps_query); + tcase_add_test (tc_chain, test_accept_caps_query); + tcase_add_test (tc_chain, test_push_pending_events); + tcase_add_test (tc_chain, test_caps_change_mode_delayed); + + return s; +} + +GST_CHECK_MAIN (capsfilter) diff --git a/tests/check/elements/concat.c b/tests/check/elements/concat.c new file mode 100644 index 0000000..43054dc --- /dev/null +++ b/tests/check/elements/concat.c @@ -0,0 +1,308 @@ +/* GStreamer unit tests for concat + * + * Copyright (C) 2014 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define N_BUFFERS 10 +static gboolean got_eos; +static guint buffer_count; +static GstSegment current_segment; +static guint64 current_bytes; + +static GstFlowReturn +output_chain_time (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstClockTime timestamp; + guint8 b; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + fail_unless_equals_int64 (timestamp, + (buffer_count % N_BUFFERS) * 25 * GST_MSECOND); + timestamp = + gst_segment_to_stream_time (¤t_segment, GST_FORMAT_TIME, timestamp); + fail_unless_equals_int64 (timestamp, + (buffer_count % N_BUFFERS) * 25 * GST_MSECOND); + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + timestamp = + gst_segment_to_running_time (¤t_segment, GST_FORMAT_TIME, + timestamp); + fail_unless_equals_int64 (timestamp, buffer_count * 25 * GST_MSECOND); + + gst_buffer_extract (buffer, 0, &b, 1); + fail_unless_equals_int (b, buffer_count % N_BUFFERS); + + buffer_count++; + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +static gboolean +output_event_time (GstPad * pad, GstObject * parent, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED); + break; + case GST_EVENT_SEGMENT: + gst_event_copy_segment (event, ¤t_segment); + break; + case GST_EVENT_EOS: + got_eos = TRUE; + break; + default: + break; + } + + gst_event_unref (event); + return TRUE; +} + +static gpointer +push_buffers_time (gpointer data) +{ + GstSegment segment; + GstPad *pad = data; + gint i; + GstClockTime timestamp = 0; + + gst_pad_send_event (pad, gst_event_new_stream_start ("test")); + gst_segment_init (&segment, GST_FORMAT_TIME); + gst_pad_send_event (pad, gst_event_new_segment (&segment)); + + for (i = 0; i < N_BUFFERS; i++) { + GstBuffer *buf = gst_buffer_new_and_alloc (1000); + + gst_buffer_memset (buf, 0, i, 1); + + GST_BUFFER_TIMESTAMP (buf) = timestamp; + timestamp += 25 * GST_MSECOND; + GST_BUFFER_DURATION (buf) = timestamp - GST_BUFFER_TIMESTAMP (buf); + + fail_unless (gst_pad_chain (pad, buf) == GST_FLOW_OK); + } + gst_pad_send_event (pad, gst_event_new_eos ()); + + return NULL; +} + +GST_START_TEST (test_concat_simple_time) +{ + GstElement *concat; + GstPad *sink1, *sink2, *sink3, *src, *output_sink; + GThread *thread1, *thread2, *thread3; + + got_eos = FALSE; + buffer_count = 0; + gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED); + + concat = gst_element_factory_make ("concat", NULL); + fail_unless (concat != NULL); + + sink1 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink1 != NULL); + + sink2 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink2 != NULL); + + sink3 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink3 != NULL); + + src = gst_element_get_static_pad (concat, "src"); + output_sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (output_sink != NULL); + fail_unless (gst_pad_link (src, output_sink) == GST_PAD_LINK_OK); + + gst_pad_set_chain_function (output_sink, output_chain_time); + gst_pad_set_event_function (output_sink, output_event_time); + + gst_pad_set_active (output_sink, TRUE); + fail_unless (gst_element_set_state (concat, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + thread1 = g_thread_new ("thread1", (GThreadFunc) push_buffers_time, sink1); + thread2 = g_thread_new ("thread2", (GThreadFunc) push_buffers_time, sink2); + thread3 = g_thread_new ("thread3", (GThreadFunc) push_buffers_time, sink3); + + g_thread_join (thread1); + g_thread_join (thread2); + g_thread_join (thread3); + + fail_unless (got_eos); + fail_unless_equals_int (buffer_count, 3 * N_BUFFERS); + + gst_element_set_state (concat, GST_STATE_NULL); + gst_pad_unlink (src, output_sink); + gst_object_unref (src); + gst_element_release_request_pad (concat, sink1); + gst_object_unref (sink1); + gst_element_release_request_pad (concat, sink2); + gst_object_unref (sink2); + gst_element_release_request_pad (concat, sink3); + gst_object_unref (sink3); + gst_pad_set_active (output_sink, FALSE); + gst_object_unref (output_sink); + gst_object_unref (concat); +} + +GST_END_TEST; + +static GstFlowReturn +output_chain_bytes (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + guint8 b; + + fail_unless (current_bytes >= current_segment.start); + fail_unless_equals_int64 (current_segment.start, + (buffer_count / N_BUFFERS) * 1000 * N_BUFFERS); + + gst_buffer_extract (buffer, 0, &b, 1); + fail_unless_equals_int (b, buffer_count % N_BUFFERS); + + current_bytes += gst_buffer_get_size (buffer), buffer_count++; + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +static gboolean +output_event_bytes (GstPad * pad, GstObject * parent, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED); + break; + case GST_EVENT_SEGMENT: + gst_event_copy_segment (event, ¤t_segment); + break; + case GST_EVENT_EOS: + got_eos = TRUE; + break; + default: + break; + } + + gst_event_unref (event); + return TRUE; +} + +static gpointer +push_buffers_bytes (gpointer data) +{ + GstSegment segment; + GstPad *pad = data; + gint i; + + gst_pad_send_event (pad, gst_event_new_stream_start ("test")); + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_send_event (pad, gst_event_new_segment (&segment)); + + for (i = 0; i < N_BUFFERS; i++) { + GstBuffer *buf = gst_buffer_new_and_alloc (1000); + gst_buffer_memset (buf, 0, i, 1); + + fail_unless (gst_pad_chain (pad, buf) == GST_FLOW_OK); + } + gst_pad_send_event (pad, gst_event_new_eos ()); + + return NULL; +} + +GST_START_TEST (test_concat_simple_bytes) +{ + GstElement *concat; + GstPad *sink1, *sink2, *sink3, *src, *output_sink; + GThread *thread1, *thread2, *thread3; + + got_eos = FALSE; + buffer_count = 0; + current_bytes = 0; + gst_segment_init (¤t_segment, GST_FORMAT_UNDEFINED); + + concat = gst_element_factory_make ("concat", NULL); + fail_unless (concat != NULL); + + sink1 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink1 != NULL); + + sink2 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink2 != NULL); + + sink3 = gst_element_get_request_pad (concat, "sink_%u"); + fail_unless (sink3 != NULL); + + src = gst_element_get_static_pad (concat, "src"); + output_sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (output_sink != NULL); + fail_unless (gst_pad_link (src, output_sink) == GST_PAD_LINK_OK); + + gst_pad_set_chain_function (output_sink, output_chain_bytes); + gst_pad_set_event_function (output_sink, output_event_bytes); + + gst_pad_set_active (output_sink, TRUE); + fail_unless (gst_element_set_state (concat, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + thread1 = g_thread_new ("thread1", (GThreadFunc) push_buffers_bytes, sink1); + thread2 = g_thread_new ("thread2", (GThreadFunc) push_buffers_bytes, sink2); + thread3 = g_thread_new ("thread3", (GThreadFunc) push_buffers_bytes, sink3); + + g_thread_join (thread1); + g_thread_join (thread2); + g_thread_join (thread3); + + fail_unless (got_eos); + fail_unless_equals_int (buffer_count, 3 * N_BUFFERS); + fail_unless_equals_int64 (current_bytes, 3 * N_BUFFERS * 1000); + + gst_element_set_state (concat, GST_STATE_NULL); + gst_pad_unlink (src, output_sink); + gst_object_unref (src); + gst_element_release_request_pad (concat, sink1); + gst_object_unref (sink1); + gst_element_release_request_pad (concat, sink2); + gst_object_unref (sink2); + gst_element_release_request_pad (concat, sink3); + gst_object_unref (sink3); + gst_pad_set_active (output_sink, FALSE); + gst_object_unref (output_sink); + gst_object_unref (concat); +} + +GST_END_TEST; + +static Suite * +concat_suite (void) +{ + Suite *s = suite_create ("concat"); + TCase *tc_chain; + + tc_chain = tcase_create ("concat"); + tcase_add_test (tc_chain, test_concat_simple_time); + tcase_add_test (tc_chain, test_concat_simple_bytes); + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (concat); diff --git a/tests/check/elements/dataurisrc.c b/tests/check/elements/dataurisrc.c new file mode 100644 index 0000000..decbe61 --- /dev/null +++ b/tests/check/elements/dataurisrc.c @@ -0,0 +1,538 @@ +/* GStreamer unit test for dataurisrc + * + * Copyright (C) 2010, 2016 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* sine wave encoded in ogg/vorbis, created with: + * gst-launch-1.0 audiotestsrc num-buffers=110 ! audioconvert ! \ + * audio/x-raw,channels=1 ! vorbisenc ! oggmux ! \ + * filesink location=sine.ogg + * and then encoded to base64 */ +const gchar data_uri[] = "data:audio/ogg;base64," + "T2dnUwACAAAAAAAAAACVWbd7AAAAAHgH02kBHgF2b3JiaXMAAAAAAUSsAAAAAAAAgDgBAAAAAAC4" + "AU9nZ1MAAAAAAAAAAAAAlVm3ewEAAADrU8FRDkv///////////////+BA3ZvcmJpcx0AAABYaXBo" + "Lk9yZyBsaWJWb3JiaXMgSSAyMDA5MDcwOQEAAAAaAAAAREVTQ1JJUFRJT049YXVkaW90ZXN0IHdh" + "dmUBBXZvcmJpcyJCQ1YBAEAAACRzGCpGpXMWhBAaQlAZ4xxCzmvsGUJMEYIcMkxbyyVzkCGkoEKI" + "WyiB0JBVAABAAACHQXgUhIpBCCGEJT1YkoMnPQghhIg5eBSEaUEIIYQQQgghhBBCCCGERTlokoMn" + "QQgdhOMwOAyD5Tj4HIRFOVgQgydB6CCED0K4moOsOQghhCQ1SFCDBjnoHITCLCiKgsQwuBaEBDUo" + "jILkMMjUgwtCiJqDSTX4GoRnQXgWhGlBCCGEJEFIkIMGQcgYhEZBWJKDBjm4FITLQagahCo5CB+E" + "IDRkFQCQAACgoiiKoigKEBqyCgDIAAAQQFEUx3EcyZEcybEcCwgNWQUAAAEACAAAoEiKpEiO5EiS" + "JFmSJVmSJVmS5omqLMuyLMuyLMsyEBqyCgBIAABQUQxFcRQHCA1ZBQBkAAAIoDiKpViKpWiK54iO" + "CISGrAIAgAAABAAAEDRDUzxHlETPVFXXtm3btm3btm3btm3btm1blmUZCA1ZBQBAAAAQ0mlmqQaI" + "MAMZBkJDVgEACAAAgBGKMMSA0JBVAABAAACAGEoOogmtOd+c46BZDppKsTkdnEi1eZKbirk555xz" + "zsnmnDHOOeecopxZDJoJrTnnnMSgWQqaCa0555wnsXnQmiqtOeeccc7pYJwRxjnnnCateZCajbU5" + "55wFrWmOmkuxOeecSLl5UptLtTnnnHPOOeecc84555zqxekcnBPOOeecqL25lpvQxTnnnE/G6d6c" + "EM4555xzzjnnnHPOOeecIDRkFQAABABAEIaNYdwpCNLnaCBGEWIaMulB9+gwCRqDnELq0ehopJQ6" + "CCWVcVJKJwgNWQUAAAIAQAghhRRSSCGFFFJIIYUUYoghhhhyyimnoIJKKqmooowyyyyzzDLLLLPM" + "Ouyssw47DDHEEEMrrcRSU2011lhr7jnnmoO0VlprrbVSSimllFIKQkNWAQAgAAAEQgYZZJBRSCGF" + "FGKIKaeccgoqqIDQkFUAACAAgAAAAABP8hzRER3RER3RER3RER3R8RzPESVREiVREi3TMjXTU0VV" + "dWXXlnVZt31b2IVd933d933d+HVhWJZlWZZlWZZlWZZlWZZlWZYgNGQVAAACAAAghBBCSCGFFFJI" + "KcYYc8w56CSUEAgNWQUAAAIACAAAAHAUR3EcyZEcSbIkS9IkzdIsT/M0TxM9URRF0zRV0RVdUTdt" + "UTZl0zVdUzZdVVZtV5ZtW7Z125dl2/d93/d93/d93/d93/d9XQdCQ1YBABIAADqSIymSIimS4ziO" + "JElAaMgqAEAGAEAAAIriKI7jOJIkSZIlaZJneZaomZrpmZ4qqkBoyCoAABAAQAAAAAAAAIqmeIqp" + "eIqoeI7oiJJomZaoqZoryqbsuq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq4LhIas" + "AgAkAAB0JEdyJEdSJEVSJEdygNCQVQCADACAAAAcwzEkRXIsy9I0T/M0TxM90RM901NFV3SB0JBV" + "AAAgAIAAAAAAAAAMybAUy9EcTRIl1VItVVMt1VJF1VNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" + "VVVVVVVVVVVN0zRNEwgNWQkAAAEA0FpzzK2XjkHorJfIKKSg10455qTXzCiCnOcQMWOYx1IxQwzG" + "lkGElAVCQ1YEAFEAAIAxyDHEHHLOSeokRc45Kh2lxjlHqaPUUUqxplo7SqW2VGvjnKPUUcoopVpL" + "qx2lVGuqsQAAgAAHAIAAC6HQkBUBQBQAAIEMUgophZRizinnkFLKOeYcYoo5p5xjzjkonZTKOSed" + "kxIppZxjzinnnJTOSeack9JJKAAAIMABACDAQig0ZEUAECcA4HAcTZM0TRQlTRNFTxRd1xNF1ZU0" + "zTQ1UVRVTRRN1VRVWRZNVZYlTTNNTRRVUxNFVRVVU5ZNVbVlzzRt2VRV3RZV1bZlW/Z9V5Z13TNN" + "2RZV1bZNVbV1V5Z1XbZt3Zc0zTQ1UVRVTRRV11RV2zZV1bY1UXRdUVVlWVRVWXZdWddVV9Z9TRRV" + "1VNN2RVVVZZV2dVlVZZ1X3RV3VZd2ddVWdZ929aFX9Z9wqiqum7Krq6rsqz7si77uu3rlEnTTFMT" + "RVXVRFFVTVe1bVN1bVsTRdcVVdWWRVN1ZVWWfV91ZdnXRNF1RVWVZVFVZVmVZV13ZVe3RVXVbVV2" + "fd90XV2XdV1YZlv3hdN1dV2VZd9XZVn3ZV3H1nXf90zTtk3X1XXTVXXf1nXlmW3b+EVV1XVVloVf" + "lWXf14XheW7dF55RVXXdlF1fV2VZF25fN9q+bjyvbWPbPrKvIwxHvrAsXds2ur5NmHXd6BtD4TeG" + "NNO0bdNVdd10XV+Xdd1o67pQVFVdV2XZ91VX9n1b94Xh9n3fGFXX91VZFobVlp1h932l7guVVbaF" + "39Z155htXVh+4+j8vjJ0dVto67qxzL6uPLtxdIY+AgAABhwAAAJMKAOFhqwIAOIEABiEnENMQYgU" + "gxBCSCmEkFLEGITMOSkZc1JCKamFUlKLGIOQOSYlc05KKKGlUEpLoYTWQimxhVJabK3VmlqLNYTS" + "WiiltVBKi6mlGltrNUaMQcick5I5J6WU0loopbXMOSqdg5Q6CCmllFosKcVYOSclg45KByGlkkpM" + "JaUYQyqxlZRiLCnF2FpsucWYcyilxZJKbCWlWFtMObYYc44Yg5A5JyVzTkoopbVSUmuVc1I6CCll" + "DkoqKcVYSkoxc05KByGlDkJKJaUYU0qxhVJiKynVWEpqscWYc0sx1lBSiyWlGEtKMbYYc26x5dZB" + "aC2kEmMoJcYWY66ttRpDKbGVlGIsKdUWY629xZhzKCXGkkqNJaVYW425xhhzTrHlmlqsucXYa225" + "9Zpz0Km1WlNMubYYc465BVlz7r2D0FoopcVQSoyttVpbjDmHUmIrKdVYSoq1xZhza7H2UEqMJaVY" + "S0o1thhrjjX2mlqrtcWYa2qx5ppz7zHm2FNrNbcYa06x5Vpz7r3m1mMBAAADDgAAASaUgUJDVgIA" + "UQAABCFKMQahQYgx56Q0CDHmnJSKMecgpFIx5hyEUjLnIJSSUuYchFJSCqWkklJroZRSUmqtAACA" + "AgcAgAAbNCUWByg0ZCUAkAoAYHAcy/I8UTRV2XYsyfNE0TRV1bYdy/I8UTRNVbVty/NE0TRV1XV1" + "3fI8UTRVVXVdXfdEUTVV1XVlWfc9UTRVVXVdWfZ901RV1XVlWbaFXzRVV3VdWZZl31hd1XVlWbZ1" + "WxhW1XVdWZZtWzeGW9d13feFYTk6t27ruu/7wvE7xwAA8AQHAKACG1ZHOCkaCyw0ZCUAkAEAQBiD" + "kEFIIYMQUkghpRBSSgkAABhwAAAIMKEMFBqyEgCIAgAACJFSSimNlFJKKaWRUkoppZQSQgghhBBC" + "CCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQggFAPhPOAD4P9igKbE4QKEhKwGAcAAAwBilmHIMOgkp" + "NYw5BqGUlFJqrWGMMQilpNRaS5VzEEpJqbXYYqycg1BSSq3FGmMHIaXWWqyx1po7CCmlFmusOdgc" + "Smktxlhzzr33kFJrMdZac++9l9ZirDXn3IMQwrQUY6659uB77ym2WmvNPfgghFCx1Vpz8EEIIYSL" + "Mffcg/A9CCFcjDnnHoTwwQdhAAB3gwMARIKNM6wknRWOBhcashIACAkAIBBiijHnnIMQQgiRUow5" + "5xyEEEIoJVKKMeecgw5CCCVkjDnnHIQQQiillIwx55yDEEIJpZSSOecchBBCKKWUUjLnoIMQQgml" + "lFJK5xyEEEIIpZRSSumggxBCCaWUUkopIYQQQgmllFJKKSWEEEIJpZRSSimlhBBKKKWUUkoppZQQ" + "QimllFJKKaWUEkIopZRSSimllJJCKaWUUkoppZRSUiillFJKKaWUUkoJpZRSSimllJRSSQUAABw4" + "AAAEGEEnGVUWYaMJFx6AQkNWAgBAAAAUxFZTiZ1BzDFnqSEIMaipQkophjFDyiCmKVMKIYUhc4oh" + "AqHFVkvFAAAAEAQACAgJADBAUDADAAwOED4HQSdAcLQBAAhCZIZINCwEhweVABExFQAkJijkAkCF" + "xUXaxQV0GeCCLu46EEIQghDE4gAKSMDBCTc88YYn3OAEnaJSBwEAAAAAcAAADwAAxwUQEdEcRobG" + "BkeHxwdISAAAAAAAyADABwDAIQJERDSHkaGxwdHh8QESEgAAAAAAAAAAAAQEBAAAAAAAAgAAAAQE" + "T2dnUwAAwFIAAAAAAACVWbd7AgAAAPtNZ2oXKxQ4JiYlJSUmJSYmJSUlJiUmJiYmJSWM64s3q+wD" + "MAQAnICN1ydV8tWC8lN5Kk/lqTyVp/JUuqu7uqu7KgjDMEwAnO2rVb0qWHw+DQAAAAAAIC5HDwU6" + "yj7C62/u4teEkwiA2gAAAAAAAAAAAAAAbL8fuP/EQFh6odjwP2uvvNHgH/d6FLjkcubZXtUAAJ7K" + "3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8H7XAwAAcm8vpwcAnsreqjfJ7RahwY4/FUwHAAAAAAAA" + "AAAAAADw/l0AAIB2r4kzAgCeyt4qNyntFqHBzv0KpgNQAAAAAAAAAAAAAODQowQAgPjtOQoAnsre" + "KjfJ/RYF7NyvYDoAAAAAAAAAAAAAAIBf3wMAgL2/NDECAJ7K3qo3Ke0WpcHOrQKmAxAAAAAAAAAA" + "AAAAIJoFAACIm3ZUAQCeyt4qN8ntFqnBjj8VTAcAAAAAAAAAAAAAAPDj9wAAgEnDb5MBAJ7K3io3" + "ye0WGuz4U8F0AAoAAAAAAAAAAAAAXG8xAQAgv8G5vgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAA" + "APB1FwkAAIPev/QBAJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX29hAADAwMuzPgIAnsreKjcp" + "7RYa7PhTwHQAAgAAAAAAAAAAAACcv6UAAIDcBE+qAJ7K3io3yf0WAez4W8F0AAAAAAAAAAAAAAAA" + "P34XAABMFj2SAgCeyt6qNyntFqnBzv0KpgNQAAAAAAAAAAAAACCrSwAAkGUXUwAAnsreKjfJ/RYF" + "7PhTwXQAAAAAAAAAAAAAAAC/fhYAYGHvr03cAACeyt4qNyntFhrs+FPAdAACAAAAAAAAAAAAANz3" + "OAAAIHrqAhUAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw/l0BAEC7xG4ZAACeyt6qN8ntFhrs" + "+FvAdAAAAAAAAAAAAAAAAO9vQQIAQP7YG9MBAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8Ny1" + "BACAmsF9ngAAnsreKjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw6+0AAMCi1mdeAACeyt7yNyntFgHs" + "3K9gOgABAAAAAAAAAAAAAFpnCgAAMI98WgAAnsre8jfJ7RYN7NyaYDoAAAAAAAAAAAAAAIA/fgMA" + "wLKxf1wEAE9nZ1MAAMCqAAAAAAAAlVm3ewMAAAD+9Ox8FiQlJSYmJSUlJSUmJSYlJSUmJiYmJSSe" + "yt4qNyntFqHBzv0KpgNQAAAAAAAAAAAAAKB9ZgkAAE6GCACeyt6qN8ntFqnBjj8VTAcAAAAAAAAA" + "AAAAAPD1lgEAwODweu8AnsreqjfJ7RYa7PhbwHQAAAAAAAAAAAAAAADPXQoAAKje6sUrAJ7K3qo3" + "ye0WocGOPxVMBwAAAAAAAAAAAAAAcN31AACA3K760gIAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAA" + "AADw/l0AAID2OV7SAgCeyt7yNyl1i1Bg5/4E0wEoAAAAAAAAAAAAAHDoQQIAQJxOjwQAnsreKjfJ" + "7Ratwc6tAqYDAAAAAAAAAAAAAAD46wcAgMDlal8mAJ7K3io3Ke0WqcHO/QKmAxAAAAAAAAAAAAAA" + "oN/DAACAaKfrAACeyt4qN8ntFqnBzv0KpgMAAAAAAAAAAAAAAPjxHQAAMJn8dhoAnsreqjfJ7RYa" + "7PhbwHQAAAAAAAAAAAAAAADXW0oAAMj7OMMnAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8HVX" + "CQAAtYu2eQMAnsreqjfJ7RYa7PhbwHQAAAAAAAAAAAAAAABfnwAAAAZN1vcBAJ7K3io3Ke0WocHO" + "/QqmAxAAAAAAAAAAAAAA4PzMAwAAzP8cqQIAnsreKjfJ/RYJ7PhTwHQAAAAAAAAAAAAAAAA/fhcA" + "AEx+XGYSAJ7K3qo3Ke0WpcHOrQqmA1AAAAAAAAAAAAAAIKtLAACQ841WAACeyt4qN8n9Fgns+FPB" + "dAAAAAAAAAAAAAAAAL9+FgAALDa84wEAnsreKjfJ7RaxwY6/FUwHIAAAAAAAAAAAAADA/V0LAACo" + "7vGKCgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPD+XQMAANplf5IRAJ7K3qo3ye0WGuz4W8B0" + "AAAAAAAAAAAAAAAA799lAgBAu9mnGQAAnsreKjcp7RYa7PhTwXQACgAAAAAAAAAAAAC83OUEAIDa" + "7i8rAACeyt4qN8n9FgHs+FvBdAAAAAAAAAAAAAAAAL9+BgAALNa/7Q4Ansreqjcp7Rapwc79CqYD" + "EAAAAAAAAAAAAAAgmgUAAIj5x6gAT2dnUwAAwAIBAAAAAACVWbd7BAAAAFDbxx4WJSUmJiYlJSUl" + "JiUmJSUlJSUlJiUmJZ7K3io3yf0WBezcr2A6AAAAAAAAAAAAAACAH78DAAA2flSWLwCeyt4qNynt" + "Fhrs+FPAdAAKAAAAAAAAAAAAALTPLAEAwPnmCAUAnsreqjfJ7RapwY4/FUwHAAAAAAAAAAAAAADw" + "9ZYBAMCg6Xo+AgCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAF93KQAAoHrhht4BAJ7K3qo3ye0W" + "ocGOPxVMBwAAAAAAAAAAAAAAcL3FAACAnA8zUwEAnsreKjfJ7RYa7PhTwHQAAAAAAAAAAAAAAAA/" + "PhkAAEymvJMWAJ7K3vI3Ke0WAezcr2A6AAUAAAAAAAAAAAAADj1IAACI5x0vAQCeyt4qN8n9Fg3s" + "3CpgOgAAAAAAAAAAAAAAgL9+AAAI7K317QAAnsreKjcp7Rahwc79CqYDEAAAAAAAAAAAAACg3+MA" + "AIAobSQBAJ7K3qo3ye0WqcGOPxVMBwAAAAAAAAAAAAAA8P5JAQBA+2yvaQAAnsreqjfJ7RYa7Phb" + "wHQAAAAAAAAAAAAAAADXW5AAAJDfzWAaAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8NxVAgBA" + "7TavXgAAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw9QkAAGBwWIM3AJ7K3vI3KXWLUGDn/gTT" + "AQgAAAAAAAAAAAAA0DpTAACAWUZ6AQCeyt4qN8ntFq3Bzq0CpgMAAAAAAAAAAAAAAPjjtwAALCfy" + "Y8UAnsre8jcp7RYB7NyvYDoABQAAAAAAAAAAAADaPU0AAHCOeIYEAJ7K3io3ye0WqcHO/QqmAwAA" + "AAAAAAAAAAAA+PX2AABgUftTrwCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAM9dDgAAqBrY7xkA" + "nsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADwftcDAAByx9yUHgCeyt6qN8ntFhrs+FvAdAAAAAAA" + "AAAAAAAAAO/fJQAAaJfcNSMAnsreKjcp7Rahwc79CqYDUAAAAAAAAAAAAADgpUcJAADxk+crAACe" + "yt4qN8n9Fgns+FPAdAAAAAAAAAAAAAAAAL9+BgAALP7S1BAAT2dnUwAAwFoBAAAAAACVWbd7BQAA" + "ABLEbSgWJSUmJiYlJSUlJSYmJiYlJSUlJSYlJZ7K3lo3Kf0WbcDOrQqmAxAAAAAAAAAAAAAAIKof" + "AAAgmhXTAACeyt4qN8n9Fgns+FPAdAAAAAAAAAAAAAAAAD9+BwAATJ7eWzIAnsreKjfJ7RaxwY6/" + "BUwHoAAAAAAAAAAAAADAzVtMAADIj/+UAgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPD1iRIA" + "AAZeX/ABAJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX2cZAAAw6O0LHwEAnsreKjfJ7RYa7PhT" + "wXQAAgAAAAAAAAAAAABcbykAACC3/nlJAJ7K3io3yf0WAez4U8F0AAAAAAAAAAAAAAAAP34vAACY" + "dPsqBQCeyt6qNyntFqXBzq0CpgNQAAAAAAAAAAAAACCrSwAAkDfupAAAnsreKjfJ/RYF7NyvYDoA" + "AAAAAAAAAAAAAIBfPwEAgL2/NnUBAJ7K3io3Ke0WGuz4U8B0AAIAAAAAAAAAAAAA9HscAAAQvTNb" + "BQCeyt6qN8ntFqnBjj8VTAcAAAAAAAAAAAAAAPD+SQEAQLvnvAwAAJ7K3qo3ye0WGuz4W8B0AAAA" + "AAAAAAAAAAAA729BAgBA/p0l6QAAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw3LUEAIBai6M9" + "AQCeyt6qN8ntFqHBjj8FTAcAAAAAAAAAAAAAAPDr7QAAwOLZvXkBAJ7K3vI3Ke0WAezcr2A6AAEA" + "AAAAAAAAAAAAWmcKAAAwmy4gAACeyt4qN8ntFq3Bzq0KpgMAAAAAAAAAAAAAAPjjFwAAy8Yf7gEA" + "nsreKjcp7Rahwc79CqYDUAAAAAAAAAAAAACgfWYJAABOmg4BAJ7K3qo3ye0WqcGOPxVMBwAAAAAA" + "AAAAAAAA8PX2AABgcENGrwCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAM9dDgAAqK6f0SsAnsre" + "qjfJ7RahwY4/FUwHAAAAAAAAAAAAAABw3fUAAIDck43SAgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAA" + "AAAAAPD+XQAAgPZO7fQAnsreKjcp7Rapwc79CqYDUAAAAAAAAAAAAADg0KMEAIB4XVMAAE9nZ1MA" + "AMCyAQAAAAAAlVm3ewYAAADDE4GEFiUkJSUmJSYlJSYlJiYmJiQlJSUlJiaeyt4qN8ntFqXBzv0K" + "pgMAAAAAAAAAAAAAAPj1PQAA2PtTwgQAnsre8jcp7RYB7NyfYDoAAQAAAAAAAAAAAAD6TQEAAOLr" + "jwUAnsreKjfJ7Rapwc79CqYDAAAAAAAAAAAAAAD48R0AADCp/OETAJ7K3qo3ye0WGuz4W8B0AAAA" + "AAAAAAAAAAAA11tKAADIZzylAwCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPB1VwkAAEPzP+kN" + "AJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX28hAAAY+LzBBwCeyt4qNyntFqHBzv0KpgMQAAAA" + "AAAAAAAAAOD8zAMAAMzb/qMCAJ7K3io3yf0WCez4U8B0AAAAAAAAAAAAAAAAP34XAABMPpBLAgCe" + "yt7aN6nzFmXCzv0CpgNQAAAAAAAAAAAAACCrlwAAIL2kaAEAnsreKjfJ/RYF7PhTwXQAAAAAAAAA" + "AAAAAAC/fhYAYGHvK6M8AACeyt4qN8ntFhrs+FPAdAACAAAAAAAAAAAAANzftQAAgOqC/6sAnsre" + "qjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw/l0DAADaeh7ICACeyt6qN8ntFhrs+FvAdAAAAAAAAAAA" + "AAAAAO9vngAA0B7vmekAAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8Ny1BACAWt+vaAEAnsre" + "KjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw67sDAIBF3989AQCeyt7yNyntFgHs3K9gOgABAAAAAAAA" + "AAAAAKIRAAAgvnymAACeyt7yN8ntFgXs3C9gOgAAAAAAAAAAAAAAgD9+AwAANpqv+gEAnsreKjcp" + "7RYa7PhTwHQACgAAAAAAAAAAAAC0zywBAMC5cJgAAJ7K3qo3ye0WqcGOPxVMBwAAAAAAAAAAAAAA" + "8PWWAQDAYK0R7wCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAF93KQAAoPpNq1cAnsreqjfJ7Rah" + "wY4/FUwHAAAAAAAAAAAAAABwvcUAAIBcX6VTAQCeyt6qN8ntFqHBjj8FTAcAAAAAAAAAAAAAAPDj" + "uwAAAJM3TJgWAE9nZ1MAAMC2AQAAAAAAlVm3ewcAAAChMbyhATK+ur7krvf7iNcT84QFpAwAAAAA" + "AAAAAAAAAEAnELfPda81yNy2bdpbCkUt8amvXMHuAE9nZ1MABAC4AQAAAAAAlVm3ewgAAAA8WkRh" + "AWZeiL1v7LSgX1wHDrB3NhI3k3sSnaKJAAAAAAAAQOJJS94nzV+3/3r/2Ho5ub5tHN70XSuPfdZZ" + "C/9eZOtqZc5Zfl8wP5ZenOT3hbWPpZeE6jzjkdY3f+GXCblaF41qKouT/N7UyQA="; + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static gboolean have_eos; +static GCond eos_cond; +static GMutex event_mutex; + +static guchar *data; +static gsize data_size; + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + + g_mutex_lock (&event_mutex); + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + have_eos = TRUE; + GST_DEBUG ("signal EOS"); + g_cond_broadcast (&eos_cond); + } + g_mutex_unlock (&event_mutex); + + gst_event_unref (event); + + return res; +} + +static GstElement * +setup_dataurisrc (void) +{ + GstElement *dataurisrc; + + g_cond_init (&eos_cond); + g_mutex_init (&event_mutex); + have_eos = FALSE; + + dataurisrc = gst_check_setup_element ("dataurisrc"); + mysinkpad = gst_check_setup_sink_pad (dataurisrc, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + + return dataurisrc; +} + +static void +cleanup_dataurisrc (GstElement * dataurisrc) +{ + gst_check_drop_buffers (); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (dataurisrc); + gst_check_teardown_element (dataurisrc); + + g_cond_clear (&eos_cond); + g_mutex_clear (&event_mutex); +} + +GST_START_TEST (test_dataurisrc_pull) +{ + GstFlowReturn flow; + GstBuffer *buf1, *buf2; + GstElement *src; + GstQuery *seeking_query; + GstPad *src_pad; + gboolean seekable = FALSE; + gint64 start = -1, stop = -1; + + data = g_base64_decode (data_uri + 22, &data_size); + fail_unless (data != NULL); + + src = setup_dataurisrc (); + + g_object_set (src, "uri", data_uri, NULL); + + fail_unless_equals_int (gst_element_set_state (src, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + + /* get the source pad */ + src_pad = gst_element_get_static_pad (src, "src"); + fail_unless (src_pad != NULL); + + /* activate the pad in pull mode */ + fail_unless (gst_pad_activate_mode (src_pad, GST_PAD_MODE_PULL, TRUE)); + + /* now start playing */ + fail_unless_equals_int (gst_element_set_state (src, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + /* Check that dataurisrc is seekable */ + seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES); + fail_unless (gst_element_query (src, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, &start, &stop); + fail_unless (seekable == TRUE); + fail_unless_equals_int64 (start, 0); + fail_unless_equals_int64 (stop, data_size); + gst_query_unref (seeking_query); + + seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES); + fail_unless (gst_pad_query (src_pad, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, &start, &stop); + fail_unless (seekable == TRUE); + fail_unless_equals_int64 (start, 0); + fail_unless_equals_int64 (stop, data_size); + gst_query_unref (seeking_query); + + seeking_query = gst_query_new_seeking (GST_FORMAT_TIME); + fail_unless (gst_pad_query (src_pad, seeking_query) == FALSE); + gst_query_unref (seeking_query); + + /* do some pulls */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, 0, 100, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), 100); + fail_unless (gst_buffer_memcmp (buf1, 0, data, 100) == 0); + + buf2 = NULL; + flow = gst_pad_get_range (src_pad, 0, 50, &buf2); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf2 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf2), 50); + fail_unless (gst_buffer_memcmp (buf2, 0, data, 50) == 0); + gst_buffer_unref (buf2); + gst_buffer_unref (buf1); + + /* read next 50 bytes */ + buf2 = NULL; + flow = gst_pad_get_range (src_pad, 50, 50, &buf2); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf2 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf2), 50); + fail_unless (gst_buffer_memcmp (buf2, 0, data + 50, 50) == 0); + gst_buffer_unref (buf2); + + buf1 = NULL; + flow = gst_pad_get_range (src_pad, 1, 100, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), 100); + fail_unless (gst_buffer_memcmp (buf1, 0, data + 1, 100) == 0); + gst_buffer_unref (buf1); + + buf1 = NULL; + flow = gst_pad_get_range (src_pad, 0, 999999, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), data_size); + fail_unless (gst_buffer_memcmp (buf1, 0, data, data_size) == 0); + gst_buffer_unref (buf1); + + buf1 = NULL; + flow = gst_pad_get_range (src_pad, 50, 999999, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), data_size - 50); + fail_unless (gst_buffer_memcmp (buf1, 0, data + 50, data_size - 50) == 0); + gst_buffer_unref (buf1); + + /* read 10 bytes at end-10 should give exactly 10 bytes */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size - 10, 10, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), 10); + gst_buffer_unref (buf1); + + /* read 20 bytes at end-10 should give exactly 10 bytes */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size - 10, 20, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), 10); + gst_buffer_unref (buf1); + + /* read 0 bytes at end-1 should return 0 bytes */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size - 1, 0, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf1), 0); + gst_buffer_unref (buf1); + + /* read 10 bytes at end-1 should return 1 byte */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, stop - 1, 10, &buf1); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_unless (buf1 != NULL); + fail_unless (gst_buffer_get_size (buf1) == 1); + gst_buffer_unref (buf1); + + /* read 0 bytes at end should EOS */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size, 0, &buf1); + fail_unless_equals_int (flow, GST_FLOW_EOS); + + /* read 10 bytes after end should EOS */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size, 10, &buf1); + fail_unless_equals_int (flow, GST_FLOW_EOS); + + /* read 0 bytes after end should EOS */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size + 10, 0, &buf1); + fail_unless_equals_int (flow, GST_FLOW_EOS); + + /* read 10 bytes after end should EOS too */ + buf1 = NULL; + flow = gst_pad_get_range (src_pad, data_size + 10, 10, &buf1); + fail_unless_equals_int (flow, GST_FLOW_EOS); + + fail_unless_equals_int (gst_element_set_state (src, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (src_pad); + cleanup_dataurisrc (src); + g_free (data); +} + +GST_END_TEST; + +static GstBuffer * +dataurisrc_wait_for_eos_and_get_data_buffer (void) +{ + GstBuffer *buf; + + g_mutex_lock (&event_mutex); + while (!have_eos) + g_cond_wait (&eos_cond, &event_mutex); + g_mutex_unlock (&event_mutex); + + buf = gst_buffer_new (); + while (buffers != NULL) { + buf = gst_buffer_append (buf, buffers->data); + buffers = g_list_delete_link (buffers, buffers); + } + + return buf; +} + +GST_START_TEST (test_dataurisrc_push) +{ + GstElement *src; + GstBuffer *buf; + + data = g_base64_decode (data_uri + 22, &data_size); + fail_unless (data != NULL); + + src = setup_dataurisrc (); + + g_object_set (src, "uri", data_uri, NULL); + + fail_unless_equals_int (gst_element_set_state (src, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + /* Everything */ + buf = dataurisrc_wait_for_eos_and_get_data_buffer (); + fail_unless_equals_int (gst_buffer_get_size (buf), data_size); + fail_unless (gst_buffer_memcmp (buf, 0, data, data_size) == 0); + gst_buffer_unref (buf); + + /* 500 - 1000 */ + have_eos = FALSE; + gst_pad_push_event (mysinkpad, + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 500, GST_SEEK_TYPE_SET, 1000)); + + buf = dataurisrc_wait_for_eos_and_get_data_buffer (); + fail_unless_equals_int (gst_buffer_get_size (buf), 500); + fail_unless (gst_buffer_memcmp (buf, 0, data + 500, 500) == 0); + gst_buffer_unref (buf); + + /* only start changed, stop kept the same (ie. 1000), so 1000-1000 now */ + have_eos = FALSE; + gst_pad_push_event (mysinkpad, + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 1000, GST_SEEK_TYPE_NONE, -1)); + + buf = dataurisrc_wait_for_eos_and_get_data_buffer (); + fail_unless_equals_int (gst_buffer_get_size (buf), 0); + gst_buffer_unref (buf); + + /* 1000-end */ + have_eos = FALSE; + gst_pad_push_event (mysinkpad, + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 1000, GST_SEEK_TYPE_SET, -1)); + + buf = dataurisrc_wait_for_eos_and_get_data_buffer (); + fail_unless_equals_int (gst_buffer_get_size (buf), data_size - 1000); + fail_unless (gst_buffer_memcmp (buf, 0, data + 1000, data_size - 1000) == 0); + gst_buffer_unref (buf); + + fail_unless_equals_int (gst_element_set_state (src, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + cleanup_dataurisrc (src); + g_free (data); +} + +GST_END_TEST; + +GST_START_TEST (test_dataurisrc_uri_iface) +{ + const gchar *const *protocols; + GstElement *src; + gchar *uri = NULL; + + src = gst_element_factory_make ("dataurisrc", NULL); + fail_unless (gst_uri_handler_get_uri (GST_URI_HANDLER (src)) == NULL); + fail_unless_equals_int (gst_uri_handler_get_uri_type (GST_URI_HANDLER (src)), + GST_URI_SRC); + protocols = gst_uri_handler_get_protocols (GST_URI_HANDLER (src)); + fail_unless (protocols != NULL && *protocols != NULL); +#if GLIB_CHECK_VERSION (2, 44, 0) + fail_unless (g_strv_contains (protocols, "data")); +#endif + fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (src), "file:///foo", + NULL)); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src), data_uri, NULL)); + g_object_get (src, "uri", &uri, NULL); + fail_unless_equals_string (uri, data_uri); + g_free (uri); + uri = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless (uri, data_uri); + g_free (uri); + gst_object_unref (src); +} + +GST_END_TEST; + +GST_START_TEST (test_dataurisrc_from_uri) +{ + GstElement *src, *sink; + + sink = gst_element_make_from_uri (GST_URI_SINK, data_uri, NULL, NULL); + fail_unless (sink == NULL); + + src = gst_element_make_from_uri (GST_URI_SRC, data_uri, NULL, NULL); + fail_unless (src != NULL); + gst_object_unref (src); +} + +GST_END_TEST; + +static Suite * +dataurisrc_suite (void) +{ + Suite *s = suite_create ("dataurisrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_dataurisrc_pull); + tcase_add_test (tc_chain, test_dataurisrc_push); + tcase_add_test (tc_chain, test_dataurisrc_uri_iface); + tcase_add_test (tc_chain, test_dataurisrc_from_uri); + + return s; +} + +GST_CHECK_MAIN (dataurisrc); diff --git a/tests/check/elements/fakesink.c b/tests/check/elements/fakesink.c new file mode 100644 index 0000000..352031a --- /dev/null +++ b/tests/check/elements/fakesink.c @@ -0,0 +1,1200 @@ +/* GStreamer + * + * unit test for fakesink + * + * Copyright (C) <2005> Thomas Vander Stichele + * <2007> Wim Taymans + * <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +typedef struct +{ + GstPad *pad; + GstBuffer *buffer; + GThread *thread; + GstFlowReturn ret; +} ChainData; + +static gpointer +chain_async_buffer (gpointer data) +{ + ChainData *chain_data = (ChainData *) data; + + chain_data->ret = gst_pad_chain (chain_data->pad, chain_data->buffer); + + return chain_data; +} + +static ChainData * +chain_async (GstPad * pad, GstBuffer * buffer) +{ + GThread *thread; + ChainData *chain_data; + GError *error = NULL; + + chain_data = g_new (ChainData, 1); + chain_data->pad = pad; + chain_data->buffer = buffer; + chain_data->ret = GST_FLOW_ERROR; + + thread = + g_thread_try_new ("gst-check", chain_async_buffer, chain_data, &error); + if (error != NULL) { + g_warning ("could not create thread reason: %s", error->message); + g_free (chain_data); + return NULL; + } + chain_data->thread = thread; + + return chain_data; +} + +static GstFlowReturn +chain_async_return (ChainData * data) +{ + GstFlowReturn ret; + + g_thread_join (data->thread); + ret = data->ret; + g_free (data); + + return ret; +} + +GST_START_TEST (test_clipping) +{ + GstElement *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + + /* create sink */ + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* make element ready to accept data */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* send segment */ + { + GstEvent *event; + GstSegment segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 1 * GST_SECOND; + segment.stop = 5 * GST_SECOND; + segment.time = 1 * GST_SECOND; + + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* new segment should not have finished preroll */ + ret = gst_element_get_state (sink, NULL, NULL, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* send buffer that should be dropped */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 0; + GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND; + + GST_DEBUG ("sending buffer to be dropped"); + fret = gst_pad_chain (sinkpad, buffer); + fail_if (fret != GST_FLOW_OK); + } + /* dropped buffer should not have finished preroll */ + ret = gst_element_get_state (sink, NULL, NULL, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* send buffer that should be dropped */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND; + + GST_DEBUG ("sending buffer to be dropped"); + fret = gst_pad_chain (sinkpad, buffer); + fail_if (fret != GST_FLOW_OK); + } + /* dropped buffer should not have finished preroll */ + ret = gst_element_get_state (sink, NULL, NULL, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* send buffer that should block and finish preroll */ + { + GstBuffer *buffer; + GstFlowReturn fret; + ChainData *data; + GstState current, pending; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND; + + GST_DEBUG ("sending buffer to finish preroll"); + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + /* state should now eventually change to PAUSED */ + ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_PAUSED); + fail_unless (pending == GST_STATE_VOID_PENDING); + + /* playing should render the buffer */ + ret = gst_element_set_state (sink, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* and we should get a success return value */ + fret = chain_async_return (data); + fail_if (fret != GST_FLOW_OK); + } + + /* send some buffer that will be dropped or clipped, this can + * only be observed in the debug log. */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 6 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_MSECOND; + + /* should be dropped */ + GST_DEBUG ("sending buffer to drop"); + fret = gst_pad_chain (sinkpad, buffer); + fail_if (fret != GST_FLOW_OK); + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 0 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND; + + /* should be clipped */ + GST_DEBUG ("sending buffer to clip"); + fret = gst_pad_chain (sinkpad, buffer); + fail_if (fret != GST_FLOW_OK); + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 2 * GST_SECOND; + + /* should be clipped */ + GST_DEBUG ("sending buffer to clip"); + fret = gst_pad_chain (sinkpad, buffer); + fail_if (fret != GST_FLOW_OK); + } + + gst_element_set_state (sink, GST_STATE_NULL); + gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (sinkpad); + gst_object_unref (sink); +} + +GST_END_TEST; + +static gint num_preroll = 0; + +static void +preroll_count (GstElement * sink) +{ + num_preroll++; + GST_DEBUG ("got preroll handoff %d", num_preroll); +} + +GST_START_TEST (test_preroll_sync) +{ + GstElement *pipeline, *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + + /* create sink */ + pipeline = gst_pipeline_new ("pipeline"); + fail_if (pipeline == NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "preroll-handoff", G_CALLBACK (preroll_count), NULL); + + fail_unless (num_preroll == 0); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* make pipeline and element ready to accept data */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* send segment */ + { + GstEvent *event; + GstSegment segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 0 * GST_SECOND; + segment.stop = 102 * GST_SECOND; + segment.time = 0 * GST_SECOND; + + event = gst_event_new_segment (&segment); + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* send buffer that should block and finish preroll */ + { + GstBuffer *buffer; + GstFlowReturn fret; + ChainData *data; + GstState current, pending; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer to finish preroll"); + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + /* state should now eventually change to PAUSED */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_PAUSED); + fail_unless (pending == GST_STATE_VOID_PENDING); + + fail_unless (num_preroll == 1); + + /* playing should render the buffer */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* and we should get a success return value */ + fret = chain_async_return (data); + fail_if (fret != GST_FLOW_OK); + + /* now we are playing no new preroll was done */ + fail_unless (num_preroll == 1); + + buffer = gst_buffer_new (); + /* far in the future to make sure we block */ + GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND; + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + g_usleep (1000000); + + /* pause again. Since the buffer has a humongous timestamp we likely + * interrupt the clock_wait and we should preroll on this buffer again */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_PAUSED); + fail_unless (pending == GST_STATE_VOID_PENDING); + + fail_unless (num_preroll == 2); + + /* shutdown */ + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* should be wrong state now */ + fret = chain_async_return (data); + fail_if (fret != GST_FLOW_FLUSHING); + } + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* after EOS, we refuse everything */ +GST_START_TEST (test_eos) +{ + GstElement *pipeline, *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + GstMessage *message; + GstBus *bus; + + /* create sink */ + pipeline = gst_pipeline_new ("pipeline"); + fail_if (pipeline == NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE_CAST (pipeline)); + fail_if (bus == NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* make pipeline and element ready to accept data */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* send EOS, this should work fine */ + { + GstEvent *eos; + gboolean eret; + + GST_DEBUG ("sending EOS"); + eos = gst_event_new_eos (); + + eret = gst_pad_send_event (sinkpad, eos); + fail_if (eret == FALSE); + } + + /* wait for preroll */ + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + /* EOS should be on the bus at some point */ + while (TRUE) { + GstMessageType type; + + /* blocking wait for messages */ + message = gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE); + type = GST_MESSAGE_TYPE (message); + gst_message_unref (message); + + GST_DEBUG ("got message %s", gst_message_type_get_name (type)); + + if (type == GST_MESSAGE_EOS) + break; + } + gst_object_unref (bus); + + /* send another EOS, this should fail */ + { + GstEvent *eos; + gboolean eret; + + GST_DEBUG ("sending second EOS"); + eos = gst_event_new_eos (); + + eret = gst_pad_send_event (sinkpad, eos); + fail_if (eret == TRUE); + } + + /* send segment, this should fail */ + { + GstEvent *event; + GstSegment segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 0 * GST_SECOND; + segment.stop = 2 * GST_SECOND; + segment.time = 0 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == TRUE); + } + + /* send buffer that should fail after EOS */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* buffer after EOS is not EOS */ + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_EOS); + } + + /* flush, EOS state is flushed again. */ + { + GstEvent *event; + gboolean eret; + + GST_DEBUG ("sending FLUSH_START"); + event = gst_event_new_flush_start (); + eret = gst_pad_send_event (sinkpad, event); + fail_unless (eret == TRUE); + + GST_DEBUG ("sending FLUSH_STOP"); + event = gst_event_new_flush_stop (TRUE); + eret = gst_pad_send_event (sinkpad, event); + fail_unless (eret == TRUE); + } + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* send segment, this should now work again */ + { + GstEvent *event; + GstSegment segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 0 * GST_SECOND; + segment.stop = 2 * GST_SECOND; + segment.time = 0 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_unless (eret == TRUE); + } + + /* send buffer that should work and block */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_OK); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* test EOS triggered by the element */ +GST_START_TEST (test_eos2) +{ + GstElement *pipeline, *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + + /* create sink */ + pipeline = gst_pipeline_new ("pipeline"); + fail_if (pipeline == NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* make pipeline and element ready to accept data */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* send segment, this should work */ + { + GstEvent *event; + GstSegment segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 0 * GST_SECOND; + segment.stop = 2 * GST_SECOND; + segment.time = 0 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* send buffer that should return EOS */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* this buffer will generate EOS */ + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_EOS); + } + + /* send buffer that should return EOS */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_EOS); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* test position reporting before, during and after flush + * in PAUSED and PLAYING */ +GST_START_TEST (test_position) +{ + GstElement *pipeline, *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + gboolean qret; + gint64 qcur; + GstBuffer *buffer; + GstFlowReturn fret; + ChainData *data; + GstEvent *event; + gboolean eret; + gint i; + + /* create sink */ + pipeline = gst_pipeline_new ("pipeline"); + fail_if (pipeline == NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (sink), "num-buffers", 2, NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* do position query, this should fail, we have nothing received yet */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* do position query, this should fail, we have nothing received yet */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + /* make pipeline and element ready to accept data */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* do position query, this should fail, we have nothing received yet */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* send segment, this should work */ + { + GstSegment segment; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 1 * GST_SECOND; + segment.stop = 3 * GST_SECOND; + segment.time = 1 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* FIXME, do position query, this should succeed with the time value from the + * segment. */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 1 * GST_SECOND); + + /* send buffer that we will flush out */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* this buffer causes the sink to preroll */ + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + /* wait for preroll */ + ret = gst_element_get_state (pipeline, NULL, NULL, -1); + + /* do position query, this should succeed with the time value from the + * segment. */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 1 * GST_SECOND); + + /* start flushing, no timing is affected yet */ + { + GST_DEBUG ("sending flush_start"); + event = gst_event_new_flush_start (); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* preroll buffer is flushed out */ + fret = chain_async_return (data); + fail_unless (fret == GST_FLOW_FLUSHING); + + /* do position query, this should succeed with the time value from the + * segment before the flush. */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 1 * GST_SECOND); + + /* stop flushing, timing is affected now */ + { + GST_DEBUG ("sending flush_stop"); + event = gst_event_new_flush_stop (TRUE); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* do position query, this should fail, the segment is flushed */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + /* send segment, this should work */ + { + GstSegment segment; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 2 * GST_SECOND; + segment.stop = 4 * GST_SECOND; + segment.time = 1 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* send buffer that should return OK */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* this buffer causes the sink to preroll */ + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + /* wait for preroll */ + ret = gst_element_get_state (pipeline, NULL, NULL, -1); + + /* do position query, this should succeed with the time value from the + * segment. */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 1 * GST_SECOND); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* position now is increasing but never exceeds the boundaries of the segment */ + for (i = 0; i < 5; i++) { + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur)); + fail_unless (qret == TRUE); + fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND); + g_usleep (1000 * 250); + } + + /* preroll buffer is rendered, we expect one more buffer after this one */ + fret = chain_async_return (data); + fail_unless (fret == GST_FLOW_OK); + + /* after rendering the position must be bigger then the stream_time of the + * buffer */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND); + + /* start flushing in PLAYING */ + { + GST_DEBUG ("sending flush_start"); + event = gst_event_new_flush_start (); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* this should now just report the last stream time */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND); + + { + GST_DEBUG ("sending flush_stop"); + event = gst_event_new_flush_stop (TRUE); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* do position query, this should fail, the segment is flushed */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + /* send segment, this should work */ + { + GstSegment segment; + + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 2 * GST_SECOND; + segment.stop = 4 * GST_SECOND; + segment.time = 1 * GST_SECOND; + event = gst_event_new_segment (&segment); + + eret = gst_pad_send_event (sinkpad, event); + fail_if (eret == FALSE); + } + + /* send buffer that should return EOS */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* this buffer causes the sink to preroll */ + data = chain_async (sinkpad, buffer); + fail_if (data == NULL); + + /* wait for preroll */ + ret = gst_element_get_state (pipeline, NULL, NULL, -1); + + /* preroll buffer is rendered, we expect no more buffer after this one */ + fret = chain_async_return (data); + fail_unless (fret == GST_FLOW_EOS); + + /* do position query, this should succeed with the stream time of the buffer + * against the clock. Since the buffer is synced against the clock, the time + * should be at least the stream time of the buffer. */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND); + + /* wait 2 more seconds, enough to test if the position was clipped correctly + * against the segment */ + g_usleep (2 * G_USEC_PER_SEC); + + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 3 * GST_SECOND); + + GST_DEBUG ("going to PAUSED"); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* we report the time of the last start of the buffer. This is slightly + * incorrect, we should report the exact time when we paused but there is no + * record of that anywhere */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == TRUE); + fail_unless (qcur == 3 * GST_SECOND); + + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* fails again because we are in the wrong state */ + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur); + fail_unless (qret == FALSE); + + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* like fakesrc, but also pushes an OOB event after each buffer */ +typedef GstPushSrc OOBSource; +typedef GstPushSrcClass OOBSourceClass; + +GType oob_source_get_type (void); +G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC); + +static GstFlowReturn +oob_source_create (GstPushSrc * src, GstBuffer ** p_buf) +{ + *p_buf = gst_buffer_new (); + + gst_pad_push_event (GST_BASE_SRC_PAD (src), + gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, NULL)); + + return GST_FLOW_OK; +} + +static void +oob_source_class_init (OOBSourceClass * klass) +{ + static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + + gst_element_class_add_static_pad_template (element_class, &sinktemplate); + + pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create); +} + +static void +oob_source_init (OOBSource * src) +{ + /* nothing to do */ +} + +#define NOTIFY_RACE_NUM_PIPELINES 10 + +typedef struct +{ + GstElement *src; + GstElement *queue; + GstElement *sink; + GstElement *pipe; +} NotifyRacePipeline; + +static void +test_notify_race_setup_pipeline (NotifyRacePipeline * p) +{ + GST_DEBUG ("Creating pipeline"); + p->pipe = gst_pipeline_new ("pipeline"); + p->src = g_object_new (oob_source_get_type (), NULL); + + p->queue = gst_element_factory_make ("queue", NULL); + g_object_set (p->queue, "max-size-buffers", 2, NULL); + + p->sink = gst_element_factory_make ("fakesink", NULL); + gst_bin_add (GST_BIN (p->pipe), p->src); + gst_bin_add (GST_BIN (p->pipe), p->queue); + gst_bin_add (GST_BIN (p->pipe), p->sink); + gst_element_link_many (p->src, p->queue, p->sink, NULL); + + GST_DEBUG ("Setting pipeline to PAUSED.."); + fail_unless_equals_int (gst_element_set_state (p->pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + GST_DEBUG ("Waiting for pipeline to preroll.."); + fail_unless_equals_int (gst_element_get_state (p->pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + GST_DEBUG ("Ready to party!"); +} + +static void +test_notify_race_cleanup_pipeline (NotifyRacePipeline * p) +{ + gst_element_set_state (p->pipe, GST_STATE_NULL); + gst_object_unref (p->pipe); + memset (p, 0, sizeof (NotifyRacePipeline)); +} + +/* we create N pipelines to make sure the notify race isn't per-class, but + * only per instance */ +GST_START_TEST (test_notify_race) +{ + NotifyRacePipeline pipelines[NOTIFY_RACE_NUM_PIPELINES]; + int i; + + for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) { + GST_DEBUG ("Setting up pipeline %d", i); + test_notify_race_setup_pipeline (&pipelines[i]); + } + + for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) { + GST_DEBUG ("Starting pipeline %d", i); + gst_element_set_state (pipelines[i].pipe, GST_STATE_PLAYING); + } + + g_usleep (2 * G_USEC_PER_SEC); + + for (i = 0; i < G_N_ELEMENTS (pipelines); ++i) { + GST_DEBUG ("Cleaning up pipeline %d", i); + test_notify_race_cleanup_pipeline (&pipelines[i]); + } +} + +GST_END_TEST; + +static void +last_message_cb (GObject * obj, GParamSpec * pspec, gpointer user_data) +{ + gint *p_counter = user_data; + gchar *s, *end, *last_msg = NULL; + guint64 offset, count; + + g_object_get (obj, "last-message", &last_msg, NULL); + fail_unless (last_msg != NULL); + + if (!strstr (last_msg, "chain")) + goto skip; + + GST_LOG_OBJECT (obj, "%s", last_msg); + + s = strstr (last_msg, "offset: "); + fail_unless (s != NULL); + + s += strlen ("offset: "); + + offset = g_ascii_strtoull (s, &end, 10); + fail_unless (offset < G_MAXUINT64); + fail_if (end == s); + + count = *p_counter; + + fail_unless_equals_int (count, offset); + + *p_counter = count + 1; + +skip: + + g_free (last_msg); +} + +#define NUM_BUFFERS 500 + +GST_START_TEST (test_last_message_notify) +{ + GstElement *pipe, *src, *tee, *q1, *q2, *sink1, *sink2; + gint counter1 = 0; + gint counter2 = 0; + GstMessage *m; + + pipe = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", NULL); + gst_util_set_object_arg (G_OBJECT (src), "sizetype", "fixed"); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizemax", 1, NULL); + + tee = gst_element_factory_make ("tee", NULL); + + q1 = gst_element_factory_make ("queue", NULL); + sink1 = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink1, "silent", FALSE, NULL); + + q2 = gst_element_factory_make ("queue", NULL); + sink2 = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink2, "silent", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipe), src, tee, q1, q2, sink1, sink2, NULL); + fail_unless (gst_element_link_many (src, tee, NULL)); + fail_unless (gst_element_link_many (tee, q1, sink1, NULL)); + fail_unless (gst_element_link_many (tee, q2, sink2, NULL)); + + g_signal_connect (sink1, "notify::last-message", + G_CALLBACK (last_message_cb), &counter1); + g_signal_connect (sink2, "notify::last-message", + G_CALLBACK (last_message_cb), &counter2); + + GST_DEBUG ("Setting pipeline to PLAYING"); + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS); + gst_message_unref (m); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + fail_unless_equals_int (counter1, NUM_BUFFERS); + fail_unless_equals_int (counter2, NUM_BUFFERS); + + gst_object_unref (pipe); +} + +GST_END_TEST; + +static void +deep_notify_last_message_cb (GstObject * obj, GstObject * prop_obj, + GParamSpec * pspec, gpointer user_data) +{ + gint *counter_array = user_data; + gint *p_counter; + gchar *s, *end, *last_msg = NULL; + guint64 offset, count; + + if (strcmp (GST_OBJECT_NAME (prop_obj), "fakesink0") == 0) + p_counter = counter_array; + else if (strcmp (GST_OBJECT_NAME (prop_obj), "fakesink1") == 0) + p_counter = counter_array + 1; + else + g_assert_not_reached (); + + g_object_get (prop_obj, "last-message", &last_msg, NULL); + fail_unless (last_msg != NULL); + + if (!strstr (last_msg, "chain")) + goto skip; + + GST_LOG_OBJECT (prop_obj, "%s", last_msg); + + s = strstr (last_msg, "offset: "); + fail_unless (s != NULL); + + s += strlen ("offset: "); + + offset = g_ascii_strtoull (s, &end, 10); + fail_unless (offset < G_MAXUINT64); + fail_if (end == s); + + count = *p_counter; + +// fail_unless_equals_int (count, offset); + + *p_counter = count + 1; + +skip: + + g_free (last_msg); +} + +GST_START_TEST (test_last_message_deep_notify) +{ + GstElement *pipe, *src, *tee, *q1, *q2, *sink1, *sink2; + gint counter[2] = { 0, 0 }; + GstMessage *m; + + pipe = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", NULL); + gst_util_set_object_arg (G_OBJECT (src), "sizetype", "fixed"); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizemax", 1, NULL); + + tee = gst_element_factory_make ("tee", NULL); + + q1 = gst_element_factory_make ("queue", NULL); + sink1 = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink1, "silent", FALSE, NULL); + + q2 = gst_element_factory_make ("queue", NULL); + sink2 = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink2, "silent", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipe), src, tee, q1, q2, sink1, sink2, NULL); + fail_unless (gst_element_link_many (src, tee, NULL)); + fail_unless (gst_element_link_many (tee, q1, sink1, NULL)); + fail_unless (gst_element_link_many (tee, q2, sink2, NULL)); + + g_signal_connect (pipe, "deep-notify::last-message", + G_CALLBACK (deep_notify_last_message_cb), counter); + + GST_DEBUG ("Setting pipeline to PLAYING"); + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + m = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, GST_MESSAGE_EOS); + gst_message_unref (m); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + GST_ERROR ("sink1: %d, sink2: %d, total: %d", counter[0], counter[1], + counter[0] + counter[1]); + + fail_unless_equals_int (counter[0], NUM_BUFFERS); + fail_unless_equals_int (counter[1], NUM_BUFFERS); +} + +GST_END_TEST; + +static Suite * +fakesink_suite (void) +{ + Suite *s = suite_create ("fakesink"); + TCase *tc_chain = tcase_create ("general"); + + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_clipping); + tcase_add_test (tc_chain, test_preroll_sync); + tcase_add_test (tc_chain, test_eos); + tcase_add_test (tc_chain, test_eos2); + tcase_add_test (tc_chain, test_position); + tcase_add_test (tc_chain, test_notify_race); + tcase_add_test (tc_chain, test_last_message_notify); + tcase_skip_broken_test (tc_chain, test_last_message_deep_notify); + + return s; +} + +GST_CHECK_MAIN (fakesink); diff --git a/tests/check/elements/fakesrc.c b/tests/check/elements/fakesrc.c new file mode 100644 index 0000000..8de2c7c --- /dev/null +++ b/tests/check/elements/fakesrc.c @@ -0,0 +1,336 @@ +/* GStreamer + * + * unit test for fakesrc + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static gboolean have_eos = FALSE; + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + have_eos = TRUE; + } + gst_event_unref (event); + return TRUE; +} + +static GstElement * +setup_fakesrc (void) +{ + GstElement *fakesrc; + + GST_DEBUG ("setup_fakesrc"); + fakesrc = gst_check_setup_element ("fakesrc"); + mysinkpad = gst_check_setup_sink_pad (fakesrc, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + have_eos = FALSE; + return fakesrc; +} + +static void +cleanup_fakesrc (GstElement * fakesrc) +{ + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (fakesrc); + gst_check_teardown_element (fakesrc); +} + +GST_START_TEST (test_num_buffers) +{ + GstElement *src; + + src = setup_fakesrc (); + g_object_set (G_OBJECT (src), "num-buffers", 3, NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + while (!have_eos) { + g_usleep (1000); + } + + fail_unless_equals_int (g_list_length (buffers), 3); + gst_check_drop_buffers (); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fakesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_sizetype_empty) +{ + GstElement *src; + GList *l; + + src = setup_fakesrc (); + + g_object_set (G_OBJECT (src), "sizetype", 1, NULL); + g_object_set (G_OBJECT (src), "num-buffers", 100, NULL); + + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + while (!have_eos) { + g_usleep (1000); + } + + fail_unless_equals_int (g_list_length (buffers), 100); + l = buffers; + while (l) { + GstBuffer *buf = l->data; + + fail_unless (gst_buffer_get_size (buf) == 0); + l = l->next; + } + gst_check_drop_buffers (); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fakesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_sizetype_fixed) +{ + GstElement *src; + GList *l; + + src = setup_fakesrc (); + + g_object_set (G_OBJECT (src), "sizetype", 2, NULL); + g_object_set (G_OBJECT (src), "sizemax", 8192, NULL); + g_object_set (G_OBJECT (src), "num-buffers", 100, NULL); + + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + while (!have_eos) { + g_usleep (1000); + } + + fail_unless (g_list_length (buffers) == 100); + l = buffers; + while (l) { + GstBuffer *buf = l->data; + + fail_unless (gst_buffer_get_size (buf) == 8192); + l = l->next; + } + gst_check_drop_buffers (); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fakesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_sizetype_random) +{ + GstElement *src; + GList *l; + + src = setup_fakesrc (); + + g_object_set (G_OBJECT (src), "sizetype", 3, NULL); + g_object_set (G_OBJECT (src), "sizemin", 4096, NULL); + g_object_set (G_OBJECT (src), "sizemax", 8192, NULL); + g_object_set (G_OBJECT (src), "num-buffers", 100, NULL); + + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + while (!have_eos) { + g_usleep (1000); + } + + fail_unless (g_list_length (buffers) == 100); + l = buffers; + while (l) { + GstBuffer *buf = l->data; + + fail_if (gst_buffer_get_size (buf) > 8192); + fail_if (gst_buffer_get_size (buf) < 4096); + l = l->next; + } + gst_check_drop_buffers (); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fakesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_no_preroll) +{ + GstElement *src; + GstStateChangeReturn ret; + + src = setup_fakesrc (); + + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + + ret = gst_element_set_state (src, GST_STATE_PAUSED); + + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "error going to paused the first time"); + + ret = gst_element_set_state (src, GST_STATE_PAUSED); + + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "error going to paused the second time"); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fakesrc (src); +} + +GST_END_TEST; + +static void +handoff_cb (GstElement * element, GstBuffer * buf, GstPad * pad, + gint * p_counter) +{ + *p_counter += 1; + GST_LOG ("counter = %d", *p_counter); +} + +GST_START_TEST (test_reuse_push) +{ + GstElement *src, *sep, *sink, *pipeline; + GstBus *bus; + gint counter, repeat = 3, num_buffers = 10; + + pipeline = gst_pipeline_new ("pipeline"); + fail_unless (pipeline != NULL, "Failed to create pipeline!"); + + bus = gst_element_get_bus (pipeline); + + src = gst_element_factory_make ("fakesrc", "fakesrc"); + fail_unless (src != NULL, "Failed to create 'fakesrc' element!"); + + sep = gst_element_factory_make ("queue", "queue"); + fail_unless (sep != NULL, "Failed to create 'queue' element"); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL, "Failed to create 'fakesink' element!"); + + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), &counter); + + gst_bin_add_many (GST_BIN (pipeline), src, sep, sink, NULL); + + fail_unless (gst_element_link (src, sep)); + fail_unless (gst_element_link (sep, sink)); + + g_object_set (src, "num-buffers", num_buffers, NULL); + + do { + GstStateChangeReturn state_ret; + GstMessage *msg; + + GST_INFO ("====================== round %d ======================", repeat); + + counter = 0; + + state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (state_ret != GST_STATE_CHANGE_FAILURE); + + if (state_ret == GST_STATE_CHANGE_ASYNC) { + GST_LOG ("waiting for pipeline to reach PAUSED state"); + state_ret = gst_element_get_state (pipeline, NULL, NULL, -1); + fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS); + } + + GST_LOG ("PAUSED, let's read all of it"); + + state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (state_ret != GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS, -1); + fail_unless (msg != NULL, "Expected EOS message on bus!"); + + gst_message_unref (msg); + + if (num_buffers >= 0) { + fail_unless_equals_int (counter, num_buffers); + } + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + --repeat; + } while (repeat > 0); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +fakesrc_suite (void) +{ + Suite *s = suite_create ("fakesrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_num_buffers); + tcase_add_test (tc_chain, test_sizetype_empty); + tcase_add_test (tc_chain, test_sizetype_fixed); + tcase_add_test (tc_chain, test_sizetype_random); + tcase_add_test (tc_chain, test_no_preroll); + tcase_add_test (tc_chain, test_reuse_push); + + return s; +} + +GST_CHECK_MAIN (fakesrc); diff --git a/tests/check/elements/fdsrc.c b/tests/check/elements/fdsrc.c new file mode 100644 index 0000000..8e1c421 --- /dev/null +++ b/tests/check/elements/fdsrc.c @@ -0,0 +1,219 @@ +/* GStreamer + * + * unit test for fdsrc + * + * Copyright (C) <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include + +#include + +static gboolean have_eos = FALSE; + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + have_eos = TRUE; + } + + gst_event_unref (event); + return TRUE; +} + +static GstElement * +setup_fdsrc (void) +{ + GstElement *fdsrc; + + GST_DEBUG ("setup_fdsrc"); + fdsrc = gst_check_setup_element ("fdsrc"); + mysinkpad = gst_check_setup_sink_pad (fdsrc, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + return fdsrc; +} + +static void +cleanup_fdsrc (GstElement * fdsrc) +{ + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (fdsrc); + gst_check_teardown_element (fdsrc); +} + +GST_START_TEST (test_num_buffers) +{ + GstElement *src; + gint pipe_fd[2]; + gchar data[4096]; + +#ifndef G_OS_WIN32 + fail_if (pipe (pipe_fd) < 0); +#else + fail_if (_pipe (pipe_fd, 2048, _O_BINARY) < 0); +#endif + + src = setup_fdsrc (); + g_object_set (G_OBJECT (src), "num-buffers", 3, NULL); + g_object_set (G_OBJECT (src), "fd", pipe_fd[0], NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + +#if defined (G_OS_UNIX) && defined (O_NONBLOCK) + { + int flags; + + flags = fcntl (pipe_fd[1], F_GETFL, 0); + fcntl (pipe_fd[1], F_SETFL, flags | O_NONBLOCK); + } +#endif + + memset (data, 0, 4096); + while (!have_eos) { + int ret = write (pipe_fd[1], data, 4096); + fail_if (ret < 0 && errno != EAGAIN); + g_usleep (100); + } + + fail_unless (g_list_length (buffers) == 3); + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fdsrc (src); + close (pipe_fd[0]); + close (pipe_fd[1]); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); +} + +GST_END_TEST; + +GST_START_TEST (test_nonseeking) +{ + GstElement *src; + GstQuery *seeking_query; + gint pipe_fd[2]; + gchar data[4096]; + gboolean seekable; + +#ifndef G_OS_WIN32 + fail_if (pipe (pipe_fd) < 0); +#else + fail_if (_pipe (pipe_fd, 2048, _O_BINARY) < 0); +#endif + + src = setup_fdsrc (); + g_object_set (G_OBJECT (src), "num-buffers", 3, NULL); + g_object_set (G_OBJECT (src), "fd", pipe_fd[0], NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + memset (data, 0, 4096); + fail_if (write (pipe_fd[1], data, 4096) < 0); + + /* Test that fdsrc is non-seekable with a pipe */ + fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) + != NULL); + fail_unless (gst_element_query (src, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL); + fail_unless (seekable == FALSE); + gst_query_unref (seeking_query); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fdsrc (src); + close (pipe_fd[0]); + close (pipe_fd[1]); +} + +GST_END_TEST; + +GST_START_TEST (test_seeking) +{ + GstElement *src; + gint in_fd; + GstQuery *seeking_query; + gboolean seekable; + +#ifndef TESTFILE +#error TESTFILE not defined +#endif + fail_if ((in_fd = open (TESTFILE, O_RDONLY)) < 0); + src = setup_fdsrc (); + + g_object_set (G_OBJECT (src), "fd", in_fd, NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + /* Test that fdsrc is seekable with a file fd */ + fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) + != NULL); + fail_unless (gst_element_query (src, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL); + fail_unless (seekable == TRUE); + gst_query_unref (seeking_query); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_fdsrc (src); + close (in_fd); +} + +GST_END_TEST; + +static Suite * +fdsrc_suite (void) +{ + Suite *s = suite_create ("fdsrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_num_buffers); + tcase_add_test (tc_chain, test_nonseeking); + tcase_add_test (tc_chain, test_seeking); + + return s; +} + +GST_CHECK_MAIN (fdsrc); diff --git a/tests/check/elements/filesink.c b/tests/check/elements/filesink.c new file mode 100644 index 0000000..430085f --- /dev/null +++ b/tests/check/elements/filesink.c @@ -0,0 +1,488 @@ +/* GStreamer unit test for the filesink 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#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_filesink (void) +{ + GstElement *filesink; + + GST_DEBUG ("setup_filesink"); + filesink = gst_check_setup_element ("filesink"); + mysrcpad = gst_check_setup_src_pad (filesink, &srctemplate); + gst_pad_set_active (mysrcpad, TRUE); + return filesink; +} + +static void +cleanup_filesink (GstElement * filesink) +{ + gst_pad_set_active (mysrcpad, FALSE); + gst_check_teardown_src_pad (filesink); + gst_check_teardown_element (filesink); +} + +#if 0 +/* this queries via the element vfunc, which is currently not implemented */ +#define CHECK_QUERY_POSITION(filesink,format,position) \ + G_STMT_START { \ + gint64 pos; \ + fail_unless (gst_element_query_position (filesink, format, &pos)); \ + fail_unless_equals_int (pos, position); \ + } G_STMT_END +#else +#define CHECK_QUERY_POSITION(filesink,format,position) \ + G_STMT_START { \ + GstPad *pad; \ + gint64 pos; \ + pad = gst_element_get_static_pad (filesink, "sink"); \ + fail_unless (gst_pad_query_position (pad, format, &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); \ + GstMapInfo info; \ + guint i; \ + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); \ + for (i = 0; i < num_bytes; ++i) \ + ((guint8 *)info.data)[i] = (g_rand_int (rand) >> 24) & 0xff; \ + gst_buffer_unmap (buf, &info); \ + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \ + g_rand_free (rand); \ + } G_STMT_END + +/* Push Buffer with num_mem_blocks memory block each of size num_bytes*/ +#define PUSH_BUFFER_WITH_MULTIPLE_MEM_BLOCKS(num_mem_blocks, num_bytes) \ + G_STMT_START { \ + GstBuffer *buf = gst_buffer_new(); \ + guint i; \ + for (i = 0; i < num_mem_blocks; ++i){ \ + GstMapInfo info; \ + GstMemory* mem_block = gst_allocator_alloc(NULL,num_bytes,NULL); \ + GRand *rand = g_rand_new_with_seed (num_bytes); \ + guint j; \ + fail_unless (gst_memory_map (mem_block, &info, GST_MAP_WRITE)); \ + for (j = 0; j < num_bytes; ++j) \ + ((guint8 *)info.data)[j] = (g_rand_int (rand) >> 24) & 0xff; \ + gst_memory_unmap (mem_block, &info); \ + gst_buffer_append_memory(buf,mem_block); \ + g_rand_free (rand); \ + } \ + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \ + } G_STMT_END + +/* Push Buffer List with num_buffers buffers each containing num_mem_blocks + * memory blocks of size num_bytes */ +#define PUSH_BUFFER_LIST_WITH_MULTI_MEM_BLOCKS_BUFFERS(num_buffers, num_mem_blocks, num_bytes) \ + G_STMT_START { \ + guint i; \ + GstBufferList* buf_list = gst_buffer_list_new(); \ + for(i = 0; i < num_buffers; ++i){ \ + GstBuffer *buf = gst_buffer_new(); \ + guint j; \ + for (j = 0; j < num_mem_blocks; ++j){ \ + GstMapInfo info; \ + GstMemory* mem_block = gst_allocator_alloc(NULL,num_bytes,NULL); \ + GRand *rand = g_rand_new_with_seed (num_bytes); \ + guint k; \ + fail_unless (gst_memory_map (mem_block, &info, GST_MAP_WRITE)); \ + for (k = 0; k < num_bytes; ++k) \ + ((guint8 *)info.data)[k] = (g_rand_int (rand) >> 24) & 0xff; \ + gst_memory_unmap (mem_block, &info); \ + gst_buffer_append_memory(buf,mem_block); \ + g_rand_free (rand); \ + } \ + gst_buffer_list_add(buf_list,buf); \ + } \ + fail_unless_equals_int (gst_pad_push_list (mysrcpad, buf_list), GST_FLOW_OK); \ + } G_STMT_END + +/* Push buffer_list containing num_buffers number of buffers with size + * num_bytes bytes + * Example: PUSH_BUFFER_LIST(2,10) will push the buffer list containing + * 2 buffers with size 10 bytes each */ +#define PUSH_BUFFER_LIST(num_buffers, num_bytes) \ + G_STMT_START { \ + guint i; \ + GstBufferList* buf_list = gst_buffer_list_new(); \ + for(i = 0; i < num_buffers; ++i){ \ + GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes); \ + GRand *rand = g_rand_new_with_seed (num_bytes); \ + GstMapInfo info; \ + guint j; \ + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); \ + for (j = 0; j < num_bytes; ++j) \ + ((guint8 *)info.data)[j] = (g_rand_int (rand) >> 24) & 0xff; \ + gst_buffer_unmap (buf, &info); \ + gst_buffer_list_add(buf_list,buf); \ + g_rand_free (rand); \ + } \ + fail_unless_equals_int (gst_pad_push_list (mysrcpad, buf_list), GST_FLOW_OK); \ + } G_STMT_END + +#define CHECK_WRITTEN_BYTES(offset,written,file_size) \ + G_STMT_START { \ + 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, file_size); \ + { \ + /* we wrote bytes at position 0 */ \ + GRand *rand = g_rand_new_with_seed (written); \ + guint i; \ + for (i = 0; i < written; ++i) { \ + guint8 byte_written = *(((guint8 *) data) + offset + i); \ + \ + fail_unless_equals_int (byte_written, g_rand_int (rand) >> 24); \ + } \ + g_rand_free (rand); \ + } \ + g_free (data); \ + } G_STMT_END + +static gchar * +create_temporary_file (void) +{ + const gchar *tmpdir; + gchar *tmp_fn; + gint fd; + + tmpdir = g_get_tmp_dir (); + if (tmpdir == NULL) + return NULL; + + /* this is just silly, but gcc warns if we try to use tpmnam() */ + tmp_fn = g_build_filename (tmpdir, "gstreamer-filesink-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 NULL; + } + /* don't want the file, just a filename (hence silly, see above) */ + g_close (fd, NULL); + g_remove (tmp_fn); + + return tmp_fn; +} + +/* TODO: we don't check that the data is actually written to the right + * position after a seek */ +GST_START_TEST (test_seeking) +{ + GstElement *filesink; + gchar *tmp_fn; + GstSegment segment; + + tmp_fn = create_temporary_file (); + if (tmp_fn == NULL) + return; + filesink = setup_filesink (); + + GST_LOG ("using temp file '%s'", tmp_fn); + g_object_set (filesink, "location", tmp_fn, NULL); + + fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + +#if 0 + /* Test that filesink is seekable with a file fd */ + /* filesink 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 (filesink, 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_stream_start ("test"))); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0); + + /* push buffer with size 0 and NULL data */ + PUSH_BYTES (0); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0); + + PUSH_BYTES (1); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 1); + + PUSH_BYTES (99); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 100); + + PUSH_BYTES (8800); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8900); + + /* Push buffer list with 2 buffers each of size 50 bytes */ + PUSH_BUFFER_LIST (2, 50); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 9000); + /* Push buffer list with 3 buffers each of size 10 bytes */ + PUSH_BUFFER_LIST (3, 10); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 9030); + /* Check bytes written using push buffer list */ + CHECK_WRITTEN_BYTES (8900, 50, 9030); + CHECK_WRITTEN_BYTES (8950, 50, 9030); + CHECK_WRITTEN_BYTES (9000, 10, 9030); + CHECK_WRITTEN_BYTES (9010, 10, 9030); + CHECK_WRITTEN_BYTES (9020, 10, 9030); + + /* Push buffer with 2 memory blocks each of size 20 bytes */ + PUSH_BUFFER_WITH_MULTIPLE_MEM_BLOCKS (2, 20); + CHECK_WRITTEN_BYTES (9030, 20, 9070); + CHECK_WRITTEN_BYTES (9050, 20, 9070); + + /* Push buffer list with 2 buffers each containing 2 memory blocks each of size 20 bytes */ + PUSH_BUFFER_LIST_WITH_MULTI_MEM_BLOCKS_BUFFERS (2, 2, 20); + CHECK_WRITTEN_BYTES (9070, 20, 9150); + CHECK_WRITTEN_BYTES (9090, 20, 9150); + CHECK_WRITTEN_BYTES (9110, 20, 9150); + CHECK_WRITTEN_BYTES (9130, 20, 9150); + + segment.start = 8800; + if (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))) { + GST_LOG ("seek ok"); + /* make sure that new position is reported immediately */ + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8800); + PUSH_BYTES (1); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8801); + PUSH_BYTES (9256); + CHECK_QUERY_POSITION (filesink, 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 (filesink, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + /* cleanup */ + cleanup_filesink (filesink); + + CHECK_WRITTEN_BYTES (8801, 9256, 18057); + + /* remove file */ + g_remove (tmp_fn); + g_free (tmp_fn); +} + +GST_END_TEST; + +GST_START_TEST (test_flush) +{ + GstElement *filesink; + gchar *tmp_fn; + GstSegment segment; + + tmp_fn = create_temporary_file (); + if (tmp_fn == NULL) + return; + filesink = setup_filesink (); + + GST_LOG ("using temp file '%s'", tmp_fn); + g_object_set (filesink, "location", tmp_fn, NULL); + + fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_stream_start ("test"))); + + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0); + + PUSH_BYTES (8); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8); + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ())); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE))); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0); + + PUSH_BYTES (4); + CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 4); + + cleanup_filesink (filesink); + + CHECK_WRITTEN_BYTES (0, 4, 4); + + g_remove (tmp_fn); + g_free (tmp_fn); +} + +GST_END_TEST; + +GST_START_TEST (test_coverage) +{ + GstElement *filesink; + gchar *location; + GstBus *bus; + GstMessage *message; + + filesink = setup_filesink (); + bus = gst_bus_new (); + + gst_element_set_bus (filesink, bus); + + g_object_set (filesink, "location", "/i/do/not/exist", NULL); + g_object_get (filesink, "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + + fail_unless_equals_int (gst_element_set_state (filesink, 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 (filesink, "location", NULL, NULL); + g_object_get (filesink, "location", &location, NULL); + fail_if (location); + + /* cleanup */ + gst_element_set_bus (filesink, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_filesink (filesink); +} + +GST_END_TEST; + +GST_START_TEST (test_uri_interface) +{ + GstElement *filesink; + gchar *location; + GstBus *bus; + + filesink = setup_filesink (); + bus = gst_bus_new (); + + gst_element_set_bus (filesink, bus); + + g_object_set (G_OBJECT (filesink), "location", "/i/do/not/exist", NULL); + g_object_get (G_OBJECT (filesink), "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + + location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink)); + fail_unless_equals_string (location, "file:///i/do/not/exist"); + g_free (location); + + /* should accept file:///foo/bar URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink), + "file:///foo/bar", NULL)); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink)); + fail_unless_equals_string (location, "file:///foo/bar"); + g_free (location); + g_object_get (G_OBJECT (filesink), "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 (filesink), + "file://localhost/foo/baz", NULL)); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink)); + fail_unless_equals_string (location, "file:///foo/baz"); + g_free (location); + g_object_get (G_OBJECT (filesink), "location", &location, NULL); + fail_unless_equals_string (location, "/foo/baz"); + g_free (location); + + /* should escape non-uri characters for the URI but not for the location */ + g_object_set (G_OBJECT (filesink), "location", "/foo/b?r", NULL); + g_object_get (G_OBJECT (filesink), "location", &location, NULL); + fail_unless_equals_string (location, "/foo/b?r"); + g_free (location); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink)); + fail_unless_equals_string (location, "file:///foo/b%3Fr"); + g_free (location); + + g_object_set (G_OBJECT (filesink), "location", "\".donotexist", NULL); + g_object_get (G_OBJECT (filesink), "location", &location, NULL); + fail_unless_equals_string (location, "\".donotexist"); + g_free (location); + + /* should fail with other hostnames */ + fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink), + "file://hostname/foo/foo", NULL)); + + /* cleanup */ + gst_element_set_bus (filesink, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_filesink (filesink); +} + +GST_END_TEST; + +static Suite * +filesink_suite (void) +{ + Suite *s = suite_create ("filesink"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_coverage); + tcase_add_test (tc_chain, test_uri_interface); + tcase_add_test (tc_chain, test_seeking); + tcase_add_test (tc_chain, test_flush); + + return s; +} + +GST_CHECK_MAIN (filesink); diff --git a/tests/check/elements/filesrc.c b/tests/check/elements/filesrc.c new file mode 100644 index 0000000..e081685 --- /dev/null +++ b/tests/check/elements/filesrc.c @@ -0,0 +1,564 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static gboolean have_eos = FALSE; +static GCond eos_cond; +static GMutex event_mutex; + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean res = TRUE; + + g_mutex_lock (&event_mutex); + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + have_eos = TRUE; + GST_DEBUG ("signal EOS"); + g_cond_broadcast (&eos_cond); + } + g_mutex_unlock (&event_mutex); + + gst_event_unref (event); + + return res; +} + +static void +wait_eos (void) +{ + g_mutex_lock (&event_mutex); + GST_DEBUG ("waiting for EOS"); + while (!have_eos) { + g_cond_wait (&eos_cond, &event_mutex); + } + GST_DEBUG ("received EOS"); + g_mutex_unlock (&event_mutex); +} + +static GstElement * +setup_filesrc (void) +{ + GstElement *filesrc; + + g_cond_init (&eos_cond); + g_mutex_init (&event_mutex); + + GST_DEBUG ("setup_filesrc"); + filesrc = gst_check_setup_element ("filesrc"); + mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + + return filesrc; +} + +static void +cleanup_filesrc (GstElement * filesrc) +{ + gst_check_drop_buffers (); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (filesrc); + gst_check_teardown_element (filesrc); + + g_mutex_clear (&event_mutex); + g_cond_clear (&eos_cond); +} + +GST_START_TEST (test_seeking) +{ + GstElement *src; + GstQuery *seeking_query; + gboolean seekable; + +#ifndef TESTFILE +#error TESTFILE not defined +#endif + src = setup_filesrc (); + + g_object_set (G_OBJECT (src), "location", TESTFILE, NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + /* Test that filesrc is seekable with a file fd */ + fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) + != NULL); + fail_unless (gst_element_query (src, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL); + fail_unless (seekable == TRUE); + gst_query_unref (seeking_query); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_filesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_reverse) +{ + GstElement *src; + +#ifndef TESTFILE +#error TESTFILE not defined +#endif + src = setup_filesrc (); + + g_object_set (G_OBJECT (src), "location", TESTFILE, NULL); + /* we're going to perform the seek in ready */ + fail_unless (gst_element_set_state (src, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, + "could not set to ready"); + + /* reverse seek from end to start */ + gst_element_seek (src, -1.0, GST_FORMAT_BYTES, 0, GST_SEEK_TYPE_SET, 100, + GST_SEEK_TYPE_SET, -1); + + fail_unless (gst_element_set_state (src, + GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + /* wait for EOS */ + wait_eos (); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + cleanup_filesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_pull) +{ + GstElement *src; + GstQuery *seeking_query; + gboolean res, seekable; + gint64 start, stop; + GstPad *pad; + GstFlowReturn ret; + GstBuffer *buffer1, *buffer2; + GstMapInfo info1, info2; + + src = setup_filesrc (); + + g_object_set (G_OBJECT (src), "location", TESTFILE, NULL); + fail_unless (gst_element_set_state (src, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, + "could not set to ready"); + + /* get the source pad */ + pad = gst_element_get_static_pad (src, "src"); + fail_unless (pad != NULL); + + /* activate the pad in pull mode */ + res = gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); + fail_unless (res == TRUE); + + /* not start playing */ + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + /* Test that filesrc is seekable with a file fd */ + fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) + != NULL); + fail_unless (gst_element_query (src, seeking_query) == TRUE); + + /* get the seeking capabilities */ + gst_query_parse_seeking (seeking_query, NULL, &seekable, &start, &stop); + fail_unless (seekable == TRUE); + fail_unless (start == 0); + fail_unless (start != -1); + gst_query_unref (seeking_query); + + /* do some pulls */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, 0, 100, &buffer1); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer1 != NULL); + fail_unless (gst_buffer_get_size (buffer1) == 100); + + buffer2 = NULL; + ret = gst_pad_get_range (pad, 0, 50, &buffer2); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer2 != NULL); + fail_unless (gst_buffer_get_size (buffer2) == 50); + + /* this should be the same */ + fail_unless (gst_buffer_map (buffer1, &info1, GST_MAP_READ)); + fail_unless (gst_buffer_map (buffer2, &info2, GST_MAP_READ)); + fail_unless (memcmp (info1.data, info2.data, 50) == 0); + gst_buffer_unmap (buffer2, &info2); + + gst_buffer_unref (buffer2); + + /* read next 50 bytes */ + buffer2 = NULL; + ret = gst_pad_get_range (pad, 50, 50, &buffer2); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer2 != NULL); + fail_unless (gst_buffer_get_size (buffer2) == 50); + + /* compare with previously read data */ + fail_unless (gst_buffer_map (buffer2, &info2, GST_MAP_READ)); + fail_unless (memcmp ((guint8 *) info1.data + 50, info2.data, 50) == 0); + gst_buffer_unmap (buffer2, &info2); + + gst_buffer_unmap (buffer1, &info1); + gst_buffer_unref (buffer1); + gst_buffer_unref (buffer2); + + /* read 10 bytes at end-10 should give exactly 10 bytes */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop - 10, 10, &buffer1); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer1 != NULL); + fail_unless (gst_buffer_get_size (buffer1) == 10); + gst_buffer_unref (buffer1); + + /* read 20 bytes at end-10 should give exactly 10 bytes */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop - 10, 20, &buffer1); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer1 != NULL); + fail_unless (gst_buffer_get_size (buffer1) == 10); + gst_buffer_unref (buffer1); + + /* read 0 bytes at end-1 should return 0 bytes */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop - 1, 0, &buffer1); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer1 != NULL); + fail_unless (gst_buffer_get_size (buffer1) == 0); + gst_buffer_unref (buffer1); + + /* read 10 bytes at end-1 should return 1 byte */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop - 1, 10, &buffer1); + fail_unless (ret == GST_FLOW_OK); + fail_unless (buffer1 != NULL); + fail_unless (gst_buffer_get_size (buffer1) == 1); + gst_buffer_unref (buffer1); + + /* read 0 bytes at end should EOS */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop, 0, &buffer1); + fail_unless (ret == GST_FLOW_EOS); + + /* read 10 bytes before end should EOS */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop, 10, &buffer1); + fail_unless (ret == GST_FLOW_EOS); + + /* read 0 bytes after end should EOS */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop + 10, 0, &buffer1); + fail_unless (ret == GST_FLOW_EOS); + + /* read 10 bytes after end should EOS too */ + buffer1 = NULL; + ret = gst_pad_get_range (pad, stop + 10, 10, &buffer1); + fail_unless (ret == GST_FLOW_EOS); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + gst_object_unref (pad); + cleanup_filesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_coverage) +{ + GstElement *src; + gchar *location; + GstBus *bus; + GstMessage *message; + + src = setup_filesrc (); + bus = gst_bus_new (); + + gst_element_set_bus (src, bus); + + g_object_set (G_OBJECT (src), "location", "/i/do/not/exist", NULL); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE, + "could set to playing with wrong location"); + + /* a state change and an error */ + fail_if ((message = gst_bus_pop (bus)) == NULL); + gst_message_unref (message); + fail_if ((message = gst_bus_pop (bus)) == NULL); + fail_unless_message_error (message, RESOURCE, NOT_FOUND); + gst_message_unref (message); + + g_object_set (G_OBJECT (src), "location", NULL, NULL); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_if (location); + + /* cleanup */ + gst_element_set_bus (src, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_filesrc (src); +} + +GST_END_TEST; + +GST_START_TEST (test_uri_interface) +{ + GstElement *src; + gchar *location; + GstBus *bus; + GstPad *pad; + + src = setup_filesrc (); + bus = gst_bus_new (); + + gst_element_set_bus (src, bus); + + g_object_set (G_OBJECT (src), "location", NULL, NULL); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless (location == NULL); + + g_object_set (G_OBJECT (src), "location", "/i/do/not/exist", NULL); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + + location = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless_equals_string (location, "file:///i/do/not/exist"); + g_free (location); + +#define DSEP G_DIR_SEPARATOR_S + + /* should accept file:///foo/bar URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src), + "file:///foo/bar", NULL)); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless_equals_string (location, "file:///foo/bar"); + g_free (location); + location = NULL; + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, DSEP "foo" DSEP "bar"); + g_free (location); + +#ifdef G_OS_WIN32 + /* should accept file:///c:/foo/bar.txt URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src), + "file:///c:/foo/bar", NULL)); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless_equals_string (location, "file:///c:/foo/bar"); + g_free (location); + location = NULL; + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, "c:" DSEP "foo" DSEP "bar"); + g_free (location); +#endif + + /* should accept file://localhost/foo/bar URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src), + "file://localhost/foo/baz", NULL)); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless_equals_string (location, "file:///foo/baz"); + g_free (location); + location = NULL; + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, DSEP "foo" DSEP "baz"); + g_free (location); + +#undef DSEP + + /* should escape non-uri characters for the URI but not for the location */ + g_object_set (G_OBJECT (src), "location", "/foo/b?r", NULL); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, "/foo/b?r"); + g_free (location); + location = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + fail_unless_equals_string (location, "file:///foo/b%3Fr"); + g_free (location); + + /* should fail with other hostnames */ + fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (src), + "file://hostname/foo/foo", NULL)); + + g_object_set (G_OBJECT (src), "location", TESTFILE, NULL); + + pad = gst_element_get_static_pad (src, "src"); + fail_unless (pad != NULL); + fail_unless (gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)); + gst_object_unref (pad); + + fail_unless (gst_element_set_state (src, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + ASSERT_WARNING (g_object_set (G_OBJECT (src), "location", "/wrong", NULL)); + g_object_get (G_OBJECT (src), "location", &location, NULL); + fail_unless_equals_string (location, TESTFILE); + g_free (location); + + fail_unless (gst_element_set_state (src, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup */ + gst_element_set_bus (src, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_filesrc (src); +} + +GST_END_TEST; + +#ifdef G_OS_UNIX +static void +check_uri_for_uri (GstElement * e, const gchar * in_uri, const gchar * uri) +{ + GstQuery *query; + gchar *query_uri = NULL; + + gst_uri_handler_set_uri (GST_URI_HANDLER (e), in_uri, NULL); + + query = gst_query_new_uri (); + fail_unless (gst_element_query (e, query)); + gst_query_parse_uri (query, &query_uri); + gst_query_unref (query); + + if (uri != NULL) { + fail_unless_equals_string (query_uri, uri); + } else { + gchar *fn; + + fail_unless (gst_uri_is_valid (query_uri)); + fn = g_filename_from_uri (query_uri, NULL, NULL); + fail_unless (g_path_is_absolute (fn)); + fail_unless (fn != NULL); + g_free (fn); + } + + g_free (query_uri); +} + +static void +check_uri_for_location (GstElement * e, const gchar * location, + const gchar * uri) +{ + GstQuery *query; + gchar *query_uri = NULL; + + g_object_set (e, "location", location, NULL); + query = gst_query_new_uri (); + fail_unless (gst_element_query (e, query)); + gst_query_parse_uri (query, &query_uri); + gst_query_unref (query); + + if (uri != NULL) { + fail_unless_equals_string (query_uri, uri); + } else { + gchar *fn; + + fail_unless (gst_uri_is_valid (query_uri)); + fn = g_filename_from_uri (query_uri, NULL, NULL); + fail_unless (g_path_is_absolute (fn)); + fail_unless (fn != NULL); + g_free (fn); + } + + g_free (query_uri); +} +#endif + +GST_START_TEST (test_uri_query) +{ + GstElement *src; + + src = setup_filesrc (); + +#ifdef G_OS_UNIX + { + GST_INFO ("*nix"); + check_uri_for_location (src, "/i/do/not/exist", "file:///i/do/not/exist"); + check_uri_for_location (src, "/i/do/not/../exist", "file:///i/do/exist"); + check_uri_for_location (src, "/i/do/not/.././exist", "file:///i/do/exist"); + check_uri_for_location (src, "/i/./do/not/../exist", "file:///i/do/exist"); + check_uri_for_location (src, "/i/do/./not/../exist", "file:///i/do/exist"); + check_uri_for_location (src, "/i/do/not/./../exist", "file:///i/do/exist"); + check_uri_for_location (src, "/i/./do/./././././exist", + "file:///i/do/exist"); + check_uri_for_location (src, "/i/do/not/../../exist", "file:///i/exist"); + check_uri_for_location (src, "/i/../not/../exist", "file:///exist"); + /* hard to test relative URIs, just make sure it returns an URI of sorts */ + check_uri_for_location (src, "foo", NULL); + check_uri_for_location (src, "foo/../bar", NULL); + check_uri_for_location (src, "./foo", NULL); + check_uri_for_location (src, "../foo", NULL); + check_uri_for_location (src, "foo/./bar", NULL); + /* make sure non-ASCII characters are escaped properly (U+00F6 here) */ + check_uri_for_location (src, "/i/./d\303\266/not/../exist", + "file:///i/d%C3%B6/exist"); + /* let's see what happens if we set a malformed URI with ISO-8859-1 chars, + * i.e. one that the input characters haven't been escaped properly. We + * should get back a properly escaped URI */ + check_uri_for_uri (src, "file:///M\366t\366r", "file:///M%F6t%F6r"); + } +#endif + + cleanup_filesrc (src); +} + +GST_END_TEST; + +static Suite * +filesrc_suite (void) +{ + Suite *s = suite_create ("filesrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_seeking); + tcase_add_test (tc_chain, test_reverse); + tcase_add_test (tc_chain, test_pull); + tcase_add_test (tc_chain, test_coverage); + tcase_add_test (tc_chain, test_uri_interface); + tcase_add_test (tc_chain, test_uri_query); + + return s; +} + +GST_CHECK_MAIN (filesrc); diff --git a/tests/check/elements/funnel.c b/tests/check/elements/funnel.c new file mode 100644 index 0000000..af56d54 --- /dev/null +++ b/tests/check/elements/funnel.c @@ -0,0 +1,427 @@ +/* GStreamer unit tests for the funnel + * + * Copyright (C) 2008 Collabora, Nokia + * @author: Olivier Crete + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +struct TestData +{ + GstElement *funnel; + GstPad *funnelsrc, *funnelsink11, *funnelsink22; + GstPad *mysink, *mysrc1, *mysrc2; + GstCaps *mycaps; +}; + +static void +setup_test_objects (struct TestData *td, GstPadChainFunction chain_func) +{ + td->mycaps = gst_caps_new_empty_simple ("test/test"); + + td->funnel = gst_element_factory_make ("funnel", NULL); + + td->funnelsrc = gst_element_get_static_pad (td->funnel, "src"); + fail_unless (td->funnelsrc != NULL); + + td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink_11"); + fail_unless (td->funnelsink11 != NULL); + fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink_11")); + + td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink_22"); + fail_unless (td->funnelsink22 != NULL); + fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink_22")); + + fail_unless (gst_element_set_state (td->funnel, GST_STATE_PLAYING) == + GST_STATE_CHANGE_SUCCESS); + + td->mysink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (td->mysink, chain_func); + gst_pad_set_active (td->mysink, TRUE); + + td->mysrc1 = gst_pad_new ("src1", GST_PAD_SRC); + gst_pad_set_active (td->mysrc1, TRUE); + gst_check_setup_events_with_stream_id (td->mysrc1, td->funnel, td->mycaps, + GST_FORMAT_BYTES, "test1"); + + td->mysrc2 = gst_pad_new ("src2", GST_PAD_SRC); + gst_pad_set_active (td->mysrc2, TRUE); + gst_check_setup_events_with_stream_id (td->mysrc2, td->funnel, td->mycaps, + GST_FORMAT_BYTES, "test2"); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->funnelsrc, + td->mysink))); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc1, + td->funnelsink11))); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc2, + td->funnelsink22))); + +} + +static void +release_test_objects (struct TestData *td) +{ + gst_pad_set_active (td->mysink, FALSE); + gst_pad_set_active (td->mysrc1, FALSE); + gst_pad_set_active (td->mysrc1, FALSE); + + gst_object_unref (td->mysink); + gst_object_unref (td->mysrc1); + gst_object_unref (td->mysrc2); + + fail_unless (gst_element_set_state (td->funnel, GST_STATE_NULL) == + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (td->funnelsrc); + gst_element_release_request_pad (td->funnel, td->funnelsink11); + gst_object_unref (td->funnelsink11); + gst_element_release_request_pad (td->funnel, td->funnelsink22); + gst_object_unref (td->funnelsink22); + + gst_caps_unref (td->mycaps); + gst_object_unref (td->funnel); +} + +static gint bufcount = 0; +static gint alloccount = 0; + +static GstFlowReturn +chain_ok (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + bufcount++; + + gst_buffer_unref (buffer); + + return GST_FLOW_OK; +} + +GST_START_TEST (test_funnel_simple) +{ + struct TestData td; + + setup_test_objects (&td, chain_ok); + + bufcount = 0; + alloccount = 0; + + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_OK); + + fail_unless (bufcount == 2); + + release_test_objects (&td); +} + +GST_END_TEST; + +guint num_eos = 0; + +static gboolean +eos_event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) + ++num_eos; + + return gst_pad_event_default (pad, parent, event); +} + +GST_START_TEST (test_funnel_eos) +{ + struct TestData td; + GstSegment segment; + + setup_test_objects (&td, chain_ok); + + num_eos = 0; + bufcount = 0; + + gst_pad_set_event_function (td.mysink, eos_event_func); + + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_OK); + + fail_unless (bufcount == 2); + + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_eos ())); + fail_unless (num_eos == 0); + + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_EOS); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_OK); + + fail_unless (bufcount == 3); + + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_eos ())); + fail_unless (num_eos == 1); + + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_EOS); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_EOS); + + fail_unless (bufcount == 3); + + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_flush_start ())); + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_flush_stop (TRUE))); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (td.mysrc1, gst_event_new_segment (&segment)); + gst_pad_push_event (td.mysrc2, gst_event_new_segment (&segment)); + + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_EOS); + + fail_unless (bufcount == 4); + + fail_unless (gst_pad_unlink (td.mysrc1, td.funnelsink11)); + gst_element_release_request_pad (td.funnel, td.funnelsink11); + gst_object_unref (td.funnelsink11); + fail_unless (num_eos == 2); + + td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11"); + fail_unless (td.funnelsink11 != NULL); + fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11")); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc1, + td.funnelsink11))); + + /* This will fail because everything is EOS already */ + fail_if (gst_pad_push_event (td.mysrc1, gst_event_new_eos ())); + fail_unless (num_eos == 2); + + fail_unless (gst_pad_unlink (td.mysrc1, td.funnelsink11)); + gst_element_release_request_pad (td.funnel, td.funnelsink11); + gst_object_unref (td.funnelsink11); + fail_unless (num_eos == 2); + + /* send only eos to check, it handles empty streams */ + td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11"); + fail_unless (td.funnelsink11 != NULL); + fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11")); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc1, + td.funnelsink11))); + + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_flush_start ())); + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_flush_stop (TRUE))); + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_flush_start ())); + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_flush_stop (TRUE))); + + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_eos ())); + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_eos ())); + fail_unless (num_eos == 3); + + fail_unless (gst_pad_unlink (td.mysrc1, td.funnelsink11)); + gst_element_release_request_pad (td.funnel, td.funnelsink11); + gst_object_unref (td.funnelsink11); + fail_unless (num_eos == 3); + + td.funnelsink11 = gst_element_get_request_pad (td.funnel, "sink_11"); + fail_unless (td.funnelsink11 != NULL); + fail_unless (!strcmp (GST_OBJECT_NAME (td.funnelsink11), "sink_11")); + + release_test_objects (&td); +} + +GST_END_TEST; + +guint nb_stream_start_event = 0; +guint nb_caps_event = 0; +guint nb_segment_event = 0; +guint nb_gap_event = 0; + +static GstPadProbeReturn +event_counter (GstObject * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); + + fail_unless (event != NULL); + fail_unless (GST_IS_EVENT (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + ++nb_stream_start_event; + break; + case GST_EVENT_CAPS: + ++nb_caps_event; + break; + case GST_EVENT_SEGMENT: + ++nb_segment_event; + break; + case GST_EVENT_GAP: + ++nb_gap_event; + break; + default: + break; + } + + return GST_PAD_PROBE_OK; +} + +/* + * Push GAP events into funnel to forward sticky events. + * Funnel element shoud also treat GAP events likes buffers. + * For example, funnel can be used for internal subtitle with streamiddemux. + * +--------------------------------------------------------------------------+ + * | playbin +--------------------------------+ | + * | +--------------+ +----------------+ | +------------+ playsink | | + * | | uridecodebin | | input-selector | | | video-sink | | | + * | | | +----------------+ | +------------+ | | + * | | | | | | + * | | | +----------------+ | +------------+ | | + * | | | | input-selector | | | audio-sink | | | + * | | | +----------------+ | +------------+ | | + * | | | | | | + * | | | +----------------+ | +---------------+ +----------+ | | + * | | | | funnel | | | streamiddemux | | appsink0 | | | + * | +--------------+ +----------------+ | +---------------+ +----------+ | | + * | | +----------+ | | + * | | | appsinkn | | | + * | | +----------+ | | + * | +--------------------------------+ | + * +--------------------------------------------------------------------------+ + * If no data was received in funnel and then sticky events can be pending continuously. + * And streamiddemux only receive gap events continuously. + * Thus, pipeline can not be constructed completely. + * For support it, need to handle GAP events likes buffers. + */ +GST_START_TEST (test_funnel_gap_event) +{ + struct TestData td; + guint probe = 0; + + setup_test_objects (&td, chain_ok); + + nb_stream_start_event = 0; + nb_caps_event = 0; + nb_segment_event = 0; + nb_gap_event = 0; + bufcount = 0; + + probe = gst_pad_add_probe (td.mysink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + (GstPadProbeCallback) event_counter, NULL, NULL); + + /* push a gap event to srcpad1 to push sticky events */ + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_gap (0, + GST_SECOND))); + + fail_unless (nb_stream_start_event == 1); + fail_unless (nb_caps_event == 1); + fail_unless (nb_segment_event == 1); + fail_unless (nb_gap_event == 1); + + /* push a gap event to srcpad2 to push sticky events */ + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_gap (0, + GST_SECOND))); + + fail_unless (nb_stream_start_event == 2); + fail_unless (nb_caps_event == 2); + fail_unless (nb_segment_event == 2); + fail_unless (nb_gap_event == 2); + + /* push a gap event to srcpad2 */ + fail_unless (gst_pad_push_event (td.mysrc2, gst_event_new_gap (0, + GST_SECOND))); + + fail_unless (nb_stream_start_event == 2); + fail_unless (nb_caps_event == 2); + fail_unless (nb_segment_event == 2); + fail_unless (nb_gap_event == 3); + + /* push a gap event to srcpad1 */ + fail_unless (gst_pad_push_event (td.mysrc1, gst_event_new_gap (0, + GST_SECOND))); + + fail_unless (nb_stream_start_event == 3); + fail_unless (nb_caps_event == 3); + fail_unless (nb_segment_event == 3); + fail_unless (nb_gap_event == 4); + + /* push buffer */ + fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_OK); + + fail_unless (nb_stream_start_event == 4); + fail_unless (nb_caps_event == 4); + fail_unless (nb_segment_event == 4); + fail_unless (nb_gap_event == 4); + fail_unless (bufcount == 2); + + gst_pad_remove_probe (td.mysink, probe); + + release_test_objects (&td); +} + +GST_END_TEST; + +GST_START_TEST (test_funnel_stress) +{ + GstHarness *h0 = gst_harness_new_with_padnames ("funnel", "sink_0", "src"); + GstHarness *h1 = gst_harness_new_with_element (h0->element, "sink_1", NULL); + GstHarnessThread *req, *push0, *push1; + GstPadTemplate *templ = + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (h0->element), + "sink_%u"); + GstCaps *caps = gst_caps_from_string ("testcaps"); + GstBuffer *buf = gst_buffer_new (); + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + req = gst_harness_stress_requestpad_start (h0, templ, NULL, NULL, TRUE); + push0 = gst_harness_stress_push_buffer_start (h0, caps, &segment, buf); + push1 = gst_harness_stress_push_buffer_start (h1, caps, &segment, buf); + + gst_caps_unref (caps); + gst_buffer_unref (buf); + + /* test-length */ + g_usleep (G_USEC_PER_SEC * 1); + + gst_harness_stress_thread_stop (push1); + gst_harness_stress_thread_stop (push0); + gst_harness_stress_thread_stop (req); + + gst_harness_teardown (h1); + gst_harness_teardown (h0); +} + +GST_END_TEST; + + +static Suite * +funnel_suite (void) +{ + Suite *s = suite_create ("funnel"); + TCase *tc_chain; + + tc_chain = tcase_create ("funnel simple"); + tcase_add_test (tc_chain, test_funnel_simple); + tcase_add_test (tc_chain, test_funnel_eos); + tcase_add_test (tc_chain, test_funnel_gap_event); + tcase_add_test (tc_chain, test_funnel_stress); + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (funnel); diff --git a/tests/check/elements/identity.c b/tests/check/elements/identity.c new file mode 100644 index 0000000..63f2f0b --- /dev/null +++ b/tests/check/elements/identity.c @@ -0,0 +1,202 @@ +/* GStreamer + * + * unit test for identity + * + * Copyright (C) <2005> Thomas Vander Stichele + * Copyright (C) <2015> Havard Graff + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_one_buffer) +{ + GstHarness *h = gst_harness_new ("identity"); + GstBuffer *buffer_in; + GstBuffer *buffer_out; + + gst_harness_set_src_caps_str (h, "mycaps"); + + buffer_in = gst_buffer_new_and_alloc (4); + ASSERT_BUFFER_REFCOUNT (buffer_in, "buffer", 1); + + gst_buffer_fill (buffer_in, 0, "data", 4); + + /* pushing gives away my reference ... */ + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer_in)); + + /* ... but it should end up being collected on GstHarness queue */ + fail_unless_equals_int (1, gst_harness_buffers_in_queue (h)); + buffer_out = gst_harness_pull (h); + + fail_unless (buffer_in == buffer_out); + ASSERT_BUFFER_REFCOUNT (buffer_out, "buffer", 1); + + /* cleanup */ + gst_buffer_unref (buffer_out); + gst_harness_teardown (h); +} + +GST_END_TEST; + +static void +handoff_func (GstElement * identity, GstBuffer * buf, GstBuffer ** ret) +{ + (void) identity; + *ret = buf; +} + +GST_START_TEST (test_signal_handoffs) +{ + GstHarness *h = gst_harness_new ("identity"); + GstBuffer *buffer_in; + GstBuffer *buffer_signaled = NULL; + gst_harness_set_src_caps_str (h, "mycaps"); + + /* connect to the handoff signal */ + g_signal_connect (h->element, "handoff", + G_CALLBACK (handoff_func), &buffer_signaled); + + /* first, turn off signal-handoffs */ + g_object_set (h->element, "signal-handoffs", FALSE, NULL); + + /* then push a buffer */ + buffer_in = gst_buffer_new_and_alloc (4); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer_in)); + + /* verify that we got no buffer signaled */ + fail_unless (buffer_signaled == NULL); + + /* now turn on signal-handoffs */ + g_object_set (h->element, "signal-handoffs", TRUE, NULL); + + /* then push another buffer */ + buffer_in = gst_buffer_new_and_alloc (4); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer_in)); + + /* verify the buffer signaled is equal to the one pushed in */ + fail_unless (buffer_signaled == buffer_in); + ASSERT_BUFFER_REFCOUNT (buffer_signaled, "buffer", 1); + + /* cleanup */ + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_sync_on_timestamp) +{ + /* the reason to use the queue in front of the identity element + is to effectively make gst_harness_push asynchronous, not locking + up the test, waiting for gst_clock_id_wait */ + GstHarness *h = gst_harness_new_parse ("queue ! identity sync=1"); + GstBuffer *buf; + GstClock *clock; + GstClockTime timestamp = 123456789; + + /* use testclock */ + gst_harness_use_testclock (h); + gst_harness_set_src_caps_str (h, "mycaps"); + + /* make a buffer and set the timestamp */ + buf = gst_buffer_new (); + GST_BUFFER_PTS (buf) = timestamp; + + /* push the buffer, and verify it does *not* make it through */ + gst_harness_push (h, buf); + fail_unless_equals_int (0, gst_harness_buffers_in_queue (h)); + + /* verify the identity element has registered exactly one GstClockID */ + fail_unless (gst_harness_wait_for_clock_id_waits (h, 1, 42)); + + /* crank the clock and pull the buffer */ + gst_harness_crank_single_clock_wait (h); + buf = gst_harness_pull (h); + + /* verify that the buffer has the right timestamp, and that the time on + the clock is equal to the timestamp */ + fail_unless_equals_int64 (timestamp, GST_BUFFER_PTS (buf)); + clock = gst_element_get_clock (h->element); + fail_unless_equals_int64 (timestamp, gst_clock_get_time (clock)); + + /* cleanup */ + gst_object_unref (clock); + gst_buffer_unref (buf); + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_stopping_element_unschedules_sync) +{ + /* the reason to use the queue in front of the identity element + is to effectively make gst_harness_push asynchronous, not locking + up the test, waiting for gst_clock_id_wait */ + GstHarness *h = gst_harness_new_parse ("queue ! identity sync=1"); + GstBuffer *buf; + GstClockTime timestamp = 123456789; + + /* use testclock */ + gst_harness_use_testclock (h); + gst_harness_set_src_caps_str (h, "mycaps"); + + /* make a buffer and set the timestamp */ + buf = gst_buffer_new (); + GST_BUFFER_PTS (buf) = timestamp; + + /* push the buffer, and verify it does *not* make it through */ + gst_harness_push (h, buf); + fail_unless_equals_int (0, gst_harness_buffers_in_queue (h)); + + /* verify the identity element has registered exactly one GstClockID */ + fail_unless (gst_harness_wait_for_clock_id_waits (h, 1, 42)); + + /* setting identity to READY should unschedule the sync */ + gst_element_set_state (h->element, GST_STATE_READY); + + /* verify the identity element no longer waits on the clock */ + fail_unless (gst_harness_wait_for_clock_id_waits (h, 0, 42)); + + /* and that the waiting buffer was dropped */ + fail_unless_equals_int (0, gst_harness_buffers_received (h)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +static Suite * +identity_suite (void) +{ + Suite *s = suite_create ("identity"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_one_buffer); + tcase_add_test (tc_chain, test_signal_handoffs); + tcase_add_test (tc_chain, test_sync_on_timestamp); + tcase_add_test (tc_chain, test_stopping_element_unschedules_sync); + + + return s; +} + +GST_CHECK_MAIN (identity); diff --git a/tests/check/elements/multiqueue.c b/tests/check/elements/multiqueue.c new file mode 100644 index 0000000..6ec638a --- /dev/null +++ b/tests/check/elements/multiqueue.c @@ -0,0 +1,1699 @@ +/* GStreamer unit tests for multiqueue + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GMutex _check_lock; + +static GstElement * +setup_multiqueue (GstElement * pipe, GstElement * inputs[], + GstElement * outputs[], guint num) +{ + GstElement *mq; + guint i; + + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL, "failed to create 'multiqueue' element"); + + gst_bin_add (GST_BIN (pipe), mq); + + for (i = 0; i < num; ++i) { + GstPad *sinkpad = NULL; + GstPad *srcpad = NULL; + + /* create multiqueue sink (and source) pad */ + sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (sinkpad != NULL, + "failed to create multiqueue request pad #%u", i); + + /* link input element N to the N-th multiqueue sink pad we just created */ + if (inputs != NULL && inputs[i] != NULL) { + gst_bin_add (GST_BIN (pipe), inputs[i]); + + srcpad = gst_element_get_static_pad (inputs[i], "src"); + fail_unless (srcpad != NULL, "failed to find src pad for input #%u", i); + + fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); + + gst_object_unref (srcpad); + srcpad = NULL; + } + gst_object_unref (sinkpad); + sinkpad = NULL; + + /* link output element N to the N-th multiqueue src pad */ + if (outputs != NULL && outputs[i] != NULL) { + gchar padname[10]; + + /* only the sink pads are by request, the source pads are sometimes pads, + * so this should return NULL */ + srcpad = gst_element_get_request_pad (mq, "src_%u"); + fail_unless (srcpad == NULL); + + g_snprintf (padname, sizeof (padname), "src_%u", i); + srcpad = gst_element_get_static_pad (mq, padname); + fail_unless (srcpad != NULL, "failed to get multiqueue src pad #%u", i); + fail_unless (GST_PAD_IS_SRC (srcpad), + "%s:%s is not a source pad?!", GST_DEBUG_PAD_NAME (srcpad)); + + gst_bin_add (GST_BIN (pipe), outputs[i]); + + sinkpad = gst_element_get_static_pad (outputs[i], "sink"); + fail_unless (sinkpad != NULL, "failed to find sink pad of output #%u", i); + fail_unless (GST_PAD_IS_SINK (sinkpad)); + + fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + } + } + + return mq; +} + +GST_START_TEST (test_simple_pipeline) +{ + GstElement *pipe; + GstElement *inputs[1]; + GstElement *outputs[1]; + GstMessage *msg; + + pipe = gst_pipeline_new ("pipeline"); + + inputs[0] = gst_element_factory_make ("fakesrc", NULL); + fail_unless (inputs[0] != NULL, "failed to create 'fakesrc' element"); + g_object_set (inputs[0], "num-buffers", 256, NULL); + + outputs[0] = gst_element_factory_make ("fakesink", NULL); + fail_unless (outputs[0] != NULL, "failed to create 'fakesink' element"); + + setup_multiqueue (pipe, inputs, outputs, 1); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected EOS message, got ERROR message"); + gst_message_unref (msg); + + GST_LOG ("Got EOS, cleaning up"); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_simple_shutdown_while_running) +{ + GstElement *pipe; + GstElement *inputs[1]; + GstElement *outputs[1]; + GstMessage *msg; + + pipe = gst_pipeline_new ("pipeline"); + + inputs[0] = gst_element_factory_make ("fakesrc", NULL); + fail_unless (inputs[0] != NULL, "failed to create 'fakesrc' element"); + + outputs[0] = gst_element_factory_make ("fakesink", NULL); + fail_unless (outputs[0] != NULL, "failed to create 'fakesink' element"); + + setup_multiqueue (pipe, inputs, outputs, 1); + + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* wait until pipeline is up and running */ + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE, -1); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, "Got ERROR message"); + gst_message_unref (msg); + + GST_LOG ("pipeline is running now"); + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* wait a bit to accumulate some buffers in the queue (while it's blocking + * in the sink) */ + msg = + gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, GST_SECOND / 4); + if (msg) + g_error ("Got ERROR message"); + + /* now shut down only the sink, so the queue gets a wrong-state flow return */ + gst_element_set_state (outputs[0], GST_STATE_NULL); + msg = + gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, GST_SECOND / 2); + if (msg) + g_error ("Got ERROR message"); + + GST_LOG ("Cleaning up"); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_simple_create_destroy) +{ + GstElement *mq; + + mq = gst_element_factory_make ("multiqueue", NULL); + gst_object_unref (mq); +} + +GST_END_TEST; + +GST_START_TEST (test_request_pads) +{ + GstElement *mq; + GstPad *sink1, *sink2; + + mq = gst_element_factory_make ("multiqueue", NULL); + + sink1 = gst_element_get_request_pad (mq, "foo_%u"); + fail_unless (sink1 == NULL, + "Expected NULL pad, as there is no request pad template for 'foo_%%u'"); + + sink1 = gst_element_get_request_pad (mq, "src_%u"); + fail_unless (sink1 == NULL, + "Expected NULL pad, as there is no request pad template for 'src_%%u'"); + + sink1 = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (sink1 != NULL); + fail_unless (GST_IS_PAD (sink1)); + fail_unless (GST_PAD_IS_SINK (sink1)); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1)); + + sink2 = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (sink2 != NULL); + fail_unless (GST_IS_PAD (sink2)); + fail_unless (GST_PAD_IS_SINK (sink2)); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink2)); + + fail_unless (sink1 != sink2); + + GST_LOG ("Cleaning up"); + gst_object_unref (sink1); + gst_object_unref (sink2); + gst_object_unref (mq); +} + +GST_END_TEST; + +static GstPad * +mq_sinkpad_to_srcpad (GstElement * mq, GstPad * sink) +{ + GstPad *srcpad = NULL; + + gchar *mq_sinkpad_name; + gchar *mq_srcpad_name; + + mq_sinkpad_name = gst_pad_get_name (sink); + fail_unless (g_str_has_prefix (mq_sinkpad_name, "sink")); + mq_srcpad_name = g_strdup_printf ("src_%s", mq_sinkpad_name + 5); + srcpad = gst_element_get_static_pad (mq, mq_srcpad_name); + fail_unless (srcpad != NULL); + + g_free (mq_sinkpad_name); + g_free (mq_srcpad_name); + + return srcpad; +} + +GST_START_TEST (test_request_pads_named) +{ + GstElement *mq; + GstPad *sink1, *sink2, *sink3, *sink4; + + mq = gst_element_factory_make ("multiqueue", NULL); + + sink1 = gst_element_get_request_pad (mq, "sink_1"); + fail_unless (sink1 != NULL); + fail_unless (GST_IS_PAD (sink1)); + fail_unless (GST_PAD_IS_SINK (sink1)); + fail_unless_equals_string (GST_PAD_NAME (sink1), "sink_1"); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1)); + + sink3 = gst_element_get_request_pad (mq, "sink_3"); + fail_unless (sink3 != NULL); + fail_unless (GST_IS_PAD (sink3)); + fail_unless (GST_PAD_IS_SINK (sink3)); + fail_unless_equals_string (GST_PAD_NAME (sink3), "sink_3"); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink3)); + + sink2 = gst_element_get_request_pad (mq, "sink_2"); + fail_unless (sink2 != NULL); + fail_unless (GST_IS_PAD (sink2)); + fail_unless (GST_PAD_IS_SINK (sink2)); + fail_unless_equals_string (GST_PAD_NAME (sink2), "sink_2"); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink2)); + + /* This gets us the first unused id, sink0 */ + sink4 = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (sink4 != NULL); + fail_unless (GST_IS_PAD (sink4)); + fail_unless (GST_PAD_IS_SINK (sink4)); + fail_unless_equals_string (GST_PAD_NAME (sink4), "sink_0"); + GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink4)); + + GST_LOG ("Cleaning up"); + gst_object_unref (sink1); + gst_object_unref (sink2); + gst_object_unref (sink3); + gst_object_unref (sink4); + gst_object_unref (mq); +} + +GST_END_TEST; + +static gboolean +mq_dummypad_query (GstPad * sinkpad, GstObject * parent, GstQuery * query) +{ + gboolean res = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstCaps *filter, *caps; + + gst_query_parse_caps (query, &filter); + caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + break; + } + default: + res = gst_pad_query_default (sinkpad, parent, query); + break; + } + return res; +} + +struct PadData +{ + GstPad *input_pad; + GstPad *out_pad; + guint8 pad_num; + guint32 *max_linked_id_ptr; + guint32 *eos_count_ptr; + gboolean is_linked; + gboolean first_buf; + gint n_linked; + + GMutex *mutex; + GCond *cond; + + /* used by initial_events_nodelay */ + gint event_count; +}; + +static GstFlowReturn +mq_dummypad_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf) +{ + guint32 cur_id; + struct PadData *pad_data; + GstMapInfo info; + + pad_data = gst_pad_get_element_private (sinkpad); + + g_mutex_lock (&_check_lock); + fail_if (pad_data == NULL); + /* Read an ID from the first 4 bytes of the buffer data and check it's + * what we expect */ + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + fail_unless (info.size >= 4); + g_mutex_unlock (&_check_lock); + cur_id = GST_READ_UINT32_BE (info.data); + gst_buffer_unmap (buf, &info); + + g_mutex_lock (pad_data->mutex); + + /* For not-linked pads, ensure that we're not running ahead of the 'linked' + * pads. The first buffer is allowed to get ahead, because otherwise things can't + * always pre-roll correctly */ + if (pad_data->max_linked_id_ptr) { + if (!pad_data->is_linked) { + /* If there are no linked pads, we can't track a max_id for them :) */ + if (pad_data->n_linked > 0 && !pad_data->first_buf) { + g_mutex_lock (&_check_lock); + fail_unless (cur_id <= *(pad_data->max_linked_id_ptr) + 1, + "Got buffer %u on pad %u before buffer %u was seen on a " + "linked pad (max: %u)", cur_id, pad_data->pad_num, cur_id - 1, + *(pad_data->max_linked_id_ptr)); + g_mutex_unlock (&_check_lock); + } + } else { + /* Update the max_id value */ + if (cur_id > *(pad_data->max_linked_id_ptr)) + *(pad_data->max_linked_id_ptr) = cur_id; + } + } + pad_data->first_buf = FALSE; + + g_mutex_unlock (pad_data->mutex); + + /* Unref the buffer */ + gst_buffer_unref (buf); + + /* Return OK or not-linked as indicated */ + return pad_data->is_linked ? GST_FLOW_OK : GST_FLOW_NOT_LINKED; +} + +static gboolean +mq_dummypad_event (GstPad * sinkpad, GstObject * parent, GstEvent * event) +{ + struct PadData *pad_data; + + pad_data = gst_pad_get_element_private (sinkpad); + g_mutex_lock (&_check_lock); + fail_if (pad_data == NULL); + g_mutex_unlock (&_check_lock); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + g_mutex_lock (pad_data->mutex); + + /* Accumulate that we've seen the EOS and signal the main thread */ + if (pad_data->eos_count_ptr) + *(pad_data->eos_count_ptr) += 1; + + GST_DEBUG ("EOS on pad %u", pad_data->pad_num); + + g_cond_broadcast (pad_data->cond); + g_mutex_unlock (pad_data->mutex); + } + + gst_event_unref (event); + return TRUE; +} + +static void +construct_n_pads (GstElement * mq, struct PadData *pad_data, gint n_pads, + gint n_linked) +{ + gint i; + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + /* Construct NPADS dummy output pads. The first 'n_linked' return FLOW_OK, the rest + * return NOT_LINKED. The not-linked ones check the expected ordering of + * output buffers */ + for (i = 0; i < n_pads; i++) { + GstPad *mq_srcpad, *mq_sinkpad, *inpad, *outpad; + gchar *name; + + name = g_strdup_printf ("dummysrc%d", i); + inpad = gst_pad_new (name, GST_PAD_SRC); + g_free (name); + gst_pad_set_query_function (inpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inpad, TRUE); + + gst_pad_push_event (inpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inpad, gst_event_new_segment (&segment)); + + mq_srcpad = mq_sinkpad_to_srcpad (mq, mq_sinkpad); + + name = g_strdup_printf ("dummysink%d", i); + outpad = gst_pad_new (name, GST_PAD_SINK); + g_free (name); + gst_pad_set_chain_function (outpad, mq_dummypad_chain); + gst_pad_set_event_function (outpad, mq_dummypad_event); + gst_pad_set_query_function (outpad, mq_dummypad_query); + + pad_data[i].pad_num = i; + pad_data[i].input_pad = inpad; + pad_data[i].out_pad = outpad; + pad_data[i].max_linked_id_ptr = NULL; + pad_data[i].eos_count_ptr = NULL; + pad_data[i].is_linked = (i < n_linked ? TRUE : FALSE); + pad_data[i].n_linked = n_linked; + pad_data[i].cond = NULL; + pad_data[i].mutex = NULL; + pad_data[i].first_buf = TRUE; + gst_pad_set_element_private (outpad, pad_data + i); + + fail_unless (gst_pad_link (mq_srcpad, outpad) == GST_PAD_LINK_OK); + gst_pad_set_active (outpad, TRUE); + + gst_object_unref (mq_sinkpad); + gst_object_unref (mq_srcpad); + } +} + +static void +push_n_buffers (struct PadData *pad_data, gint num_buffers, + const guint8 * pad_pattern, guint pattern_size) +{ + gint i; + + for (i = 0; i < num_buffers; i++) { + guint8 cur_pad; + GstBuffer *buf; + GstFlowReturn ret; + GstMapInfo info; + + cur_pad = pad_pattern[i % pattern_size]; + + buf = gst_buffer_new_and_alloc (4); + g_mutex_lock (&_check_lock); + fail_if (buf == NULL); + g_mutex_unlock (&_check_lock); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + GST_WRITE_UINT32_BE (info.data, i + 1); + gst_buffer_unmap (buf, &info); + GST_BUFFER_TIMESTAMP (buf) = (i + 1) * GST_SECOND; + + ret = gst_pad_push (pad_data[cur_pad].input_pad, buf); + g_mutex_lock (&_check_lock); + if (pad_data[cur_pad].is_linked) { + fail_unless (ret == GST_FLOW_OK, + "Push on pad %d returned %d when FLOW_OK was expected", cur_pad, ret); + } else { + /* Expect OK initially, then NOT_LINKED when the srcpad starts pushing */ + fail_unless (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED, + "Push on pad %d returned %d when FLOW_OK or NOT_LINKED was expected", + cur_pad, ret); + } + g_mutex_unlock (&_check_lock); + } +} + +static void +run_output_order_test (gint n_linked) +{ + /* This test creates a multiqueue with 2 linked output, and 3 outputs that + * return 'not-linked' when data is pushed, then verifies that all buffers + * are received on not-linked pads only after earlier buffers on the + * 'linked' pads are made */ + GstElement *pipe; + GstElement *mq; + struct PadData pad_data[5]; + guint32 max_linked_id; + guint32 eos_seen; + GMutex mutex; + GCond cond; + gint i; + const gint NPADS = 5; + const gint NBUFFERS = 1000; + + g_mutex_init (&mutex); + g_cond_init (&cond); + + pipe = gst_bin_new ("testbin"); + + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + /* No limits */ + g_object_set (mq, + "max-size-bytes", (guint) 0, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, "extra-size-time", (guint64) 0, NULL); + + construct_n_pads (mq, pad_data, NPADS, n_linked); + for (i = 0; i < NPADS; i++) { + pad_data[i].max_linked_id_ptr = &max_linked_id; + /* Only look for EOS on the linked pads */ + pad_data[i].eos_count_ptr = (i < n_linked) ? &eos_seen : NULL; + pad_data[i].cond = &cond; + pad_data[i].mutex = &mutex; + } + + /* Run the test. Push 1000 buffers through the multiqueue in a pattern */ + max_linked_id = 0; + eos_seen = 0; + gst_element_set_state (pipe, GST_STATE_PLAYING); + + { + const guint8 pad_pattern[] = + { 0, 0, 0, 0, 1, 1, 2, 1, 0, 2, 3, 2, 3, 1, 4 }; + const guint n = sizeof (pad_pattern) / sizeof (guint8); + push_n_buffers (pad_data, NBUFFERS, pad_pattern, n); + } + + for (i = 0; i < NPADS; i++) { + gst_pad_push_event (pad_data[i].input_pad, gst_event_new_eos ()); + } + + /* Wait while the buffers are processed */ + g_mutex_lock (&mutex); + /* We wait until EOS has been pushed on all linked pads */ + while (eos_seen < n_linked) { + g_cond_wait (&cond, &mutex); + } + g_mutex_unlock (&mutex); + + /* Clean up */ + for (i = 0; i < NPADS; i++) { + GstPad *mq_input = gst_pad_get_peer (pad_data[i].input_pad); + + gst_pad_unlink (pad_data[i].input_pad, mq_input); + gst_element_release_request_pad (mq, mq_input); + gst_object_unref (mq_input); + gst_object_unref (pad_data[i].input_pad); + gst_object_unref (pad_data[i].out_pad); + } + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + g_cond_clear (&cond); + g_mutex_clear (&mutex); +} + +GST_START_TEST (test_output_order) +{ + run_output_order_test (2); + run_output_order_test (0); +} + +GST_END_TEST; + +GST_START_TEST (test_not_linked_eos) +{ + /* This test creates a multiqueue with 1 linked output and 1 not-linked + * pad. It pushes a few buffers through each, then EOS on the linked + * pad and waits until that arrives. After that, it pushes some more + * buffers on the not-linked pad and then EOS and checks that those + * are all output */ + GstElement *pipe; + GstElement *mq; + struct PadData pad_data[2]; + guint32 eos_seen; + GMutex mutex; + GCond cond; + gint i; + const gint NPADS = 2; + const gint NBUFFERS = 20; + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + g_mutex_init (&mutex); + g_cond_init (&cond); + + pipe = gst_bin_new ("testbin"); + + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + /* No limits */ + g_object_set (mq, + "max-size-bytes", (guint) 0, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, "extra-size-time", (guint64) 0, NULL); + + /* Construct NPADS dummy output pads. The first 1 returns FLOW_OK, the rest + * return NOT_LINKED. */ + construct_n_pads (mq, pad_data, NPADS, 1); + for (i = 0; i < NPADS; i++) { + /* Only look for EOS on the linked pads */ + pad_data[i].eos_count_ptr = &eos_seen; + pad_data[i].cond = &cond; + pad_data[i].mutex = &mutex; + } + + /* Run the test. Push 20 buffers through the multiqueue in a pattern */ + eos_seen = 0; + gst_element_set_state (pipe, GST_STATE_PLAYING); + + { + const guint8 pad_pattern[] = { 0, 1 }; + const guint n = sizeof (pad_pattern) / sizeof (guint8); + push_n_buffers (pad_data, NBUFFERS, pad_pattern, n); + } + + /* Make the linked pad go EOS */ + gst_pad_push_event (pad_data[0].input_pad, gst_event_new_eos ()); + + g_mutex_lock (&mutex); + /* Wait until EOS has been seen on the linked pad */ + while (eos_seen == 0) + g_cond_wait (&cond, &mutex); + g_mutex_unlock (&mutex); + + /* Now push some more buffers to the not-linked pad */ + { + const guint8 pad_pattern[] = { 1, 1 }; + const guint n = sizeof (pad_pattern) / sizeof (guint8); + push_n_buffers (pad_data, NBUFFERS, pad_pattern, n); + } + /* And EOS on the not-linked pad */ + gst_pad_push_event (pad_data[1].input_pad, gst_event_new_eos ()); + + g_mutex_lock (&mutex); + while (eos_seen < NPADS) + g_cond_wait (&cond, &mutex); + g_mutex_unlock (&mutex); + + /* Clean up */ + for (i = 0; i < NPADS; i++) { + GstPad *mq_input = gst_pad_get_peer (pad_data[i].input_pad); + + gst_pad_unlink (pad_data[i].input_pad, mq_input); + gst_element_release_request_pad (mq, mq_input); + gst_object_unref (mq_input); + gst_object_unref (pad_data[i].input_pad); + gst_object_unref (pad_data[i].out_pad); + } + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + g_cond_clear (&cond); + g_mutex_clear (&mutex); +} + +GST_END_TEST; + +GST_START_TEST (test_sparse_stream) +{ + /* This test creates a multiqueue with 2 streams. One receives + * a constant flow of buffers, the other only gets one buffer, and then + * new-segment events, and returns not-linked. The multiqueue should not fill. + */ + GstElement *pipe; + GstElement *mq; + GstPad *inputpads[2]; + GstPad *sinkpads[2]; + GstEvent *event; + struct PadData pad_data[2]; + guint32 eos_seen, max_linked_id; + GMutex mutex; + GCond cond; + gint i; + const gint NBUFFERS = 100; + GstSegment segment; + + g_mutex_init (&mutex); + g_cond_init (&cond); + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + /* 1 second limit */ + g_object_set (mq, + "max-size-bytes", (guint) 0, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) GST_SECOND, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, "extra-size-time", (guint64) 0, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + /* Construct 2 dummy output pads. */ + for (i = 0; i < 2; i++) { + GstPad *mq_srcpad, *mq_sinkpad; + gchar *name; + + name = g_strdup_printf ("dummysrc%d", i); + inputpads[i] = gst_pad_new (name, GST_PAD_SRC); + g_free (name); + gst_pad_set_query_function (inputpads[i], mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpads[i], TRUE); + + gst_pad_push_event (inputpads[i], gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpads[i], gst_event_new_segment (&segment)); + + mq_srcpad = mq_sinkpad_to_srcpad (mq, mq_sinkpad); + + name = g_strdup_printf ("dummysink%d", i); + sinkpads[i] = gst_pad_new (name, GST_PAD_SINK); + g_free (name); + gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain); + gst_pad_set_event_function (sinkpads[i], mq_dummypad_event); + gst_pad_set_query_function (sinkpads[i], mq_dummypad_query); + + pad_data[i].pad_num = i; + pad_data[i].max_linked_id_ptr = &max_linked_id; + if (i == 0) + pad_data[i].eos_count_ptr = &eos_seen; + else + pad_data[i].eos_count_ptr = NULL; + pad_data[i].is_linked = (i == 0) ? TRUE : FALSE; + pad_data[i].n_linked = 1; + pad_data[i].cond = &cond; + pad_data[i].mutex = &mutex; + pad_data[i].first_buf = TRUE; + gst_pad_set_element_private (sinkpads[i], pad_data + i); + + fail_unless (gst_pad_link (mq_srcpad, sinkpads[i]) == GST_PAD_LINK_OK); + gst_pad_set_active (sinkpads[i], TRUE); + + gst_object_unref (mq_sinkpad); + gst_object_unref (mq_srcpad); + } + + /* Run the test. Push 100 buffers through the multiqueue */ + max_linked_id = 0; + eos_seen = 0; + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + for (i = 0; i < NBUFFERS; i++) { + GstBuffer *buf; + GstFlowReturn ret; + GstClockTime ts; + GstMapInfo info; + + ts = gst_util_uint64_scale_int (GST_SECOND, i, 10); + + buf = gst_buffer_new_and_alloc (4); + g_mutex_lock (&_check_lock); + fail_if (buf == NULL); + g_mutex_unlock (&_check_lock); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + GST_WRITE_UINT32_BE (info.data, i + 1); + gst_buffer_unmap (buf, &info); + + GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (GST_SECOND, i, 10); + + /* If i == 0, also push the buffer to the 2nd pad */ + if (i == 0) + ret = gst_pad_push (inputpads[1], gst_buffer_ref (buf)); + + ret = gst_pad_push (inputpads[0], buf); + g_mutex_lock (&_check_lock); + fail_unless (ret == GST_FLOW_OK, + "Push on pad %d returned %d when FLOW_OK was expected", 0, ret); + g_mutex_unlock (&_check_lock); + + /* Push a new segment update on the 2nd pad */ + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = ts; + segment.time = ts; + event = gst_event_new_segment (&segment); + gst_pad_push_event (inputpads[1], event); + } + + event = gst_event_new_eos (); + gst_pad_push_event (inputpads[0], gst_event_ref (event)); + gst_pad_push_event (inputpads[1], event); + + /* Wait while the buffers are processed */ + g_mutex_lock (&mutex); + /* We wait until EOS has been pushed on pad 1 */ + while (eos_seen < 1) { + g_cond_wait (&cond, &mutex); + } + g_mutex_unlock (&mutex); + + /* Clean up */ + for (i = 0; i < 2; i++) { + GstPad *mq_input = gst_pad_get_peer (inputpads[i]); + + gst_pad_unlink (inputpads[i], mq_input); + gst_element_release_request_pad (mq, mq_input); + gst_object_unref (mq_input); + gst_object_unref (inputpads[i]); + + gst_object_unref (sinkpads[i]); + } + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + g_cond_clear (&cond); + g_mutex_clear (&mutex); +} + +GST_END_TEST; + +static gpointer +pad_push_datablock_thread (gpointer data) +{ + GstPad *pad = data; + GstBuffer *buf; + + buf = gst_buffer_new_allocate (NULL, 80 * 1000, NULL); + gst_pad_push (pad, buf); + + return NULL; +} + +static GstPadProbeReturn +block_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + return GST_PAD_PROBE_OK; +} + +static void +check_for_buffering_msg (GstElement * pipeline, gint expected_perc) +{ + gint buf_perc; + GstMessage *msg; + + GST_LOG ("waiting for %d%% buffering message", expected_perc); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), + GST_MESSAGE_BUFFERING | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected BUFFERING message, got ERROR message"); + + gst_message_parse_buffering (msg, &buf_perc); + fail_unless (buf_perc == expected_perc, + "Got incorrect percentage: %d%% expected: %d%%", buf_perc, expected_perc); + + gst_message_unref (msg); +} + +GST_START_TEST (test_initial_fill_above_high_threshold) +{ + /* This test checks what happens if the first buffer that enters + * the queue immediately fills it above the high-threshold. */ + GstElement *pipe; + GstElement *mq, *fakesink; + GstPad *inputpad; + GstPad *mq_sinkpad; + GstPad *sinkpad; + GstSegment segment; + GThread *thread; + + + /* Setup test pipeline with one multiqueue and one fakesink */ + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + /* Block fakesink sinkpad flow to ensure the queue isn't emptied + * by the prerolling sink */ + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK, block_probe, NULL, + NULL); + gst_object_unref (sinkpad); + + /* Set size limit to 1000000 byte, low threshold to 1%, high + * threshold to 5%, to make sure that even just one data push + * will exceed both thresholds.*/ + g_object_set (mq, + "use-buffering", (gboolean) TRUE, + "max-size-bytes", (guint) 1000 * 1000, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, + "extra-size-time", (guint64) 0, + "low-percent", (gint) 1, "high-percent", (gint) 5, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (mq_sinkpad); + + fail_unless (gst_element_link (mq, fakesink)); + + /* Start pipeline in paused state to ensure the sink remains + * in preroll mode and blocks */ + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* Feed data. queue will be filled to 8% (because it pushes 80000 bytes), + * which is above both the low- and the high-threshold. This should + * produce a 100% buffering message. */ + thread = g_thread_new ("push1", pad_push_datablock_thread, inputpad); + g_thread_join (thread); + check_for_buffering_msg (pipe, 100); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_watermark_and_fill_level) +{ + /* This test checks the behavior of the fill level and + * the low/high watermarks. It also checks if the + * low/high-percent and low/high-watermark properties + * are coupled together properly. */ + GstElement *pipe; + GstElement *mq, *fakesink; + GstPad *inputpad; + GstPad *mq_sinkpad; + GstPad *sinkpad; + GstSegment segment; + GThread *thread; + gint low_perc, high_perc; + + + /* Setup test pipeline with one multiqueue and one fakesink */ + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + /* Block fakesink sinkpad flow to ensure the queue isn't emptied + * by the prerolling sink */ + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK, block_probe, NULL, + NULL); + gst_object_unref (sinkpad); + + g_object_set (mq, + "use-buffering", (gboolean) TRUE, + "max-size-bytes", (guint) 1000 * 1000, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, + "extra-size-time", (guint64) 0, + "low-watermark", (gdouble) 0.01, "high-watermark", (gdouble) 0.10, NULL); + + g_object_get (mq, "low-percent", &low_perc, "high-percent", &high_perc, NULL); + + /* Check that low/high-watermark and low/high-percent are + * coupled properly. (low/high-percent are deprecated and + * exist for backwards compatibility.) */ + fail_unless_equals_int (low_perc, 1); + fail_unless_equals_int (high_perc, 10); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (mq_sinkpad); + + fail_unless (gst_element_link (mq, fakesink)); + + /* Start pipeline in paused state to ensure the sink remains + * in preroll mode and blocks */ + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* Feed data. queue will be filled to 8% (because it pushes 80000 bytes), + * which is below the high-threshold, provoking a buffering message. */ + thread = g_thread_new ("push1", pad_push_datablock_thread, inputpad); + g_thread_join (thread); + + /* Check for the buffering message; it should indicate 80% fill level + * (Note that the percentage from the message is normalized) */ + check_for_buffering_msg (pipe, 80); + + /* Increase the buffer size and lower the watermarks to test + * if <1% watermarks are supported. */ + g_object_set (mq, + "max-size-bytes", (guint) 20 * 1000 * 1000, + "low-watermark", (gdouble) 0.0001, "high-watermark", (gdouble) 0.005, + NULL); + /* First buffering message is posted after the max-size-bytes limit + * is set to 20000000 bytes & the low-watermark is set. Since the + * multiqueue contains 80000 bytes, and the high watermark still is + * 0.1 at this point, and the buffer level 80000 / 20000000 = 0.004 is + * normalized by 0.1: 0.004 / 0.1 => buffering percentage 4%. */ + check_for_buffering_msg (pipe, 4); + /* Second buffering message is posted after the high-watermark limit + * is set to 0.005. This time, the buffer level is normalized this way: + * 0.004 / 0.005 => buffering percentage 80%. */ + check_for_buffering_msg (pipe, 80); + + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_high_threshold_change) +{ + /* This test checks what happens if the high threshold is changed to a + * value below the current buffer fill level. Expected behavior is for + * multiqueue to emit a 100% buffering message in that case. */ + GstElement *pipe; + GstElement *mq, *fakesink; + GstPad *inputpad; + GstPad *mq_sinkpad; + GstPad *sinkpad; + GstSegment segment; + GThread *thread; + + + /* Setup test pipeline with one multiqueue and one fakesink */ + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + /* Block fakesink sinkpad flow to ensure the queue isn't emptied + * by the prerolling sink */ + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK, block_probe, NULL, + NULL); + gst_object_unref (sinkpad); + + g_object_set (mq, + "use-buffering", (gboolean) TRUE, + "max-size-bytes", (guint) 1000 * 1000, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, + "extra-size-time", (guint64) 0, + "low-percent", (gint) 1, "high-percent", (gint) 99, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (mq_sinkpad); + + fail_unless (gst_element_link (mq, fakesink)); + + /* Start pipeline in paused state to ensure the sink remains + * in preroll mode and blocks */ + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* Feed data. queue will be filled to 8% (because it pushes 80000 bytes), + * which is below the high-threshold, provoking a buffering message. */ + thread = g_thread_new ("push1", pad_push_datablock_thread, inputpad); + g_thread_join (thread); + + /* Check for the buffering message; it should indicate 8% fill level + * (Note that the percentage from the message is normalized, but since + * the high threshold is at 99%, it should still apply) */ + check_for_buffering_msg (pipe, 8); + + /* Set high threshold to half of what it was before. This means that the + * relative fill level doubles. As a result, this should trigger a buffering + * message with a percentage of 16%. */ + g_object_set (mq, "high-percent", (gint) 50, NULL); + check_for_buffering_msg (pipe, 16); + + /* Set high threshold to a value that lies below the current fill level. + * This should trigger a 100% buffering message immediately, even without + * pushing in extra data. */ + g_object_set (mq, "high-percent", (gint) 5, NULL); + check_for_buffering_msg (pipe, 100); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_low_threshold_change) +{ + /* This tests what happens if the queue isn't currently buffering and the + * low-threshold is raised above the current fill level. */ + GstElement *pipe; + GstElement *mq, *fakesink; + GstPad *inputpad; + GstPad *mq_sinkpad; + GstPad *sinkpad; + GstSegment segment; + GThread *thread; + + + /* Setup test pipeline with one multiqueue and one fakesink */ + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + /* Block fakesink sinkpad flow to ensure the queue isn't emptied + * by the prerolling sink */ + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK, block_probe, NULL, + NULL); + gst_object_unref (sinkpad); + + /* Enable buffering and set the low/high thresholds to 1%/5%. This ensures + * that after pushing one data block, the high threshold is reached, and + * buffering ceases. */ + g_object_set (mq, + "use-buffering", (gboolean) TRUE, + "max-size-bytes", (guint) 1000 * 1000, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, + "extra-size-time", (guint64) 0, + "low-percent", (gint) 1, "high-percent", (gint) 5, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (mq_sinkpad); + + fail_unless (gst_element_link (mq, fakesink)); + + /* Start pipeline in paused state to ensure the sink remains + * in preroll mode and blocks */ + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* Feed data. queue will be filled to 8% (because it pushes 80000 bytes), + * which is above the high-threshold, ensuring that the queue disables + * its buffering mode internally. */ + thread = g_thread_new ("push1", pad_push_datablock_thread, inputpad); + g_thread_join (thread); + + /* Check for the buffering message; it should indicate 100% relative fill + * level (Note that the percentage from the message is normalized) */ + check_for_buffering_msg (pipe, 100); + + /* Set low threshold to a 10%, which is above the current fill level of 8%. + * As a result, the queue must re-enable its buffering mode, and post the + * current relative fill level of 40% (since high-percent is also set to 20% + * and 8%/20% = 40%). */ + g_object_set (mq, "high-percent", (gint) 20, "low-percent", (gint) 10, NULL); + check_for_buffering_msg (pipe, 40); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static gpointer +pad_push_thread (gpointer data) +{ + GstPad *pad = data; + GstBuffer *buf; + + buf = gst_buffer_new (); + gst_pad_push (pad, buf); + + return NULL; +} + +GST_START_TEST (test_limit_changes) +{ + /* This test creates a multiqueue with 1 stream. The limit of the queue + * is two buffers, we check if we block once this is reached. Then we + * change the limit to three buffers and check if this is waking up + * the queue and we get the third buffer. + */ + GstElement *pipe; + GstElement *mq, *fakesink; + GstPad *inputpad; + GstPad *mq_sinkpad; + GstSegment segment; + GThread *thread; + + pipe = gst_pipeline_new ("testbin"); + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + g_object_set (mq, + "max-size-bytes", (guint) 0, + "max-size-buffers", (guint) 2, + "max-size-time", (guint64) 0, + "extra-size-bytes", (guint) 0, + "extra-size-buffers", (guint) 0, "extra-size-time", (guint64) 0, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, mq_dummypad_query); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (mq_sinkpad); + + fail_unless (gst_element_link (mq, fakesink)); + + gst_element_set_state (pipe, GST_STATE_PAUSED); + + thread = g_thread_new ("push1", pad_push_thread, inputpad); + g_thread_join (thread); + thread = g_thread_new ("push2", pad_push_thread, inputpad); + g_thread_join (thread); + thread = g_thread_new ("push3", pad_push_thread, inputpad); + g_thread_join (thread); + thread = g_thread_new ("push4", pad_push_thread, inputpad); + + /* Wait until we are actually blocking... we unfortunately can't + * know that without sleeping */ + g_usleep (G_USEC_PER_SEC); + g_object_set (mq, "max-size-buffers", (guint) 3, NULL); + g_thread_join (thread); + + g_object_set (mq, "max-size-buffers", (guint) 4, NULL); + thread = g_thread_new ("push5", pad_push_thread, inputpad); + g_thread_join (thread); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static GMutex block_mutex; +static GCond block_cond; +static gint unblock_count; +static gboolean expect_overrun; + +static GstFlowReturn +pad_chain_block (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + g_mutex_lock (&block_mutex); + while (unblock_count == 0) { + g_cond_wait (&block_cond, &block_mutex); + } + if (unblock_count > 0) { + unblock_count--; + } + g_mutex_unlock (&block_mutex); + + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +static gboolean +pad_event_always_ok (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gst_event_unref (event); + return TRUE; +} + +static void +mq_overrun (GstElement * mq, gpointer udata) +{ + fail_unless (expect_overrun); + + /* unblock always so we don't get stuck */ + g_mutex_lock (&block_mutex); + unblock_count = 2; /* let the PTS=0 and PTS=none go */ + g_cond_signal (&block_cond); + g_mutex_unlock (&block_mutex); +} + +GST_START_TEST (test_buffering_with_none_pts) +{ + /* + * This test creates a multiqueue where source pushing blocks so we can check + * how its buffering level is reacting to GST_CLOCK_TIME_NONE buffers + * mixed with properly timestamped buffers. + * + * Sequence of pushing: + * pts=0 + * pts=none + * pts=1 (it gets full now) + * pts=none (overrun expected) + */ + GstElement *mq; + GstPad *inputpad; + GstPad *outputpad; + GstPad *mq_sinkpad; + GstPad *mq_srcpad; + GstSegment segment; + GstBuffer *buffer; + + g_mutex_init (&block_mutex); + g_cond_init (&block_cond); + unblock_count = 0; + expect_overrun = FALSE; + + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + + g_object_set (mq, + "max-size-bytes", (guint) 0, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) GST_SECOND, NULL); + g_signal_connect (mq, "overrun", (GCallback) mq_overrun, NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + outputpad = gst_pad_new ("dummysink", GST_PAD_SINK); + gst_pad_set_chain_function (outputpad, pad_chain_block); + gst_pad_set_event_function (outputpad, pad_event_always_ok); + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + mq_srcpad = gst_element_get_static_pad (mq, "src_0"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + fail_unless (gst_pad_link (mq_srcpad, outputpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + gst_pad_set_active (outputpad, TRUE); + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_element_set_state (mq, GST_STATE_PAUSED); + + /* push a buffer with PTS = 0 */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = 0; + fail_unless (gst_pad_push (inputpad, buffer) == GST_FLOW_OK); + + /* push a buffer with PTS = NONE */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; + fail_unless (gst_pad_push (inputpad, buffer) == GST_FLOW_OK); + + /* push a buffer with PTS = 1s, so we have 1s of data in multiqueue, we are + * full */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = GST_SECOND; + fail_unless (gst_pad_push (inputpad, buffer) == GST_FLOW_OK); + + /* push a buffer with PTS = NONE, the queue is full so it should overrun */ + expect_overrun = TRUE; + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; + fail_unless (gst_pad_push (inputpad, buffer) == GST_FLOW_OK); + + g_mutex_lock (&block_mutex); + unblock_count = -1; + g_cond_signal (&block_cond); + g_mutex_unlock (&block_mutex); + + gst_element_set_state (mq, GST_STATE_NULL); + gst_object_unref (inputpad); + gst_object_unref (outputpad); + gst_object_unref (mq_sinkpad); + gst_object_unref (mq_srcpad); + gst_object_unref (mq); + g_mutex_clear (&block_mutex); + g_cond_clear (&block_cond); +} + +GST_END_TEST; + +static gboolean +event_func_signal (GstPad * sinkpad, GstObject * parent, GstEvent * event) +{ + struct PadData *pad_data; + + GST_LOG_OBJECT (sinkpad, "%s event", GST_EVENT_TYPE_NAME (event)); + + pad_data = gst_pad_get_element_private (sinkpad); + + g_mutex_lock (pad_data->mutex); + ++pad_data->event_count; + g_cond_broadcast (pad_data->cond); + g_mutex_unlock (pad_data->mutex); + + gst_event_unref (event); + return TRUE; +} + +GST_START_TEST (test_initial_events_nodelay) +{ + struct PadData pad_data = { 0, }; + GstElement *pipe; + GstElement *mq; + GstPad *inputpad; + GstPad *sinkpad; + GstSegment segment; + GstCaps *caps; + GMutex mutex; + GCond cond; + + g_mutex_init (&mutex); + g_cond_init (&cond); + + pipe = gst_pipeline_new ("testbin"); + + mq = gst_element_factory_make ("multiqueue", NULL); + fail_unless (mq != NULL); + gst_bin_add (GST_BIN (pipe), mq); + + { + GstPad *mq_srcpad, *mq_sinkpad; + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + + mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); + fail_unless (mq_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, mq_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + mq_srcpad = mq_sinkpad_to_srcpad (mq, mq_sinkpad); + + sinkpad = gst_pad_new ("dummysink", GST_PAD_SINK); + gst_pad_set_event_function (sinkpad, event_func_signal); + + pad_data.event_count = 0; + pad_data.cond = &cond; + pad_data.mutex = &mutex; + gst_pad_set_element_private (sinkpad, &pad_data); + + fail_unless (gst_pad_link (mq_srcpad, sinkpad) == GST_PAD_LINK_OK); + gst_pad_set_active (sinkpad, TRUE); + + gst_object_unref (mq_sinkpad); + gst_object_unref (mq_srcpad); + } + + /* Run the test: push events through multiqueue */ + gst_element_set_state (pipe, GST_STATE_PLAYING); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_pad_push_event (inputpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + gst_segment_init (&segment, GST_FORMAT_TIME); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + g_mutex_lock (&mutex); + while (pad_data.event_count < 3) { + GST_LOG ("%d events so far, waiting for more", pad_data.event_count); + g_cond_wait (&cond, &mutex); + } + g_mutex_unlock (&mutex); + + /* Clean up */ + { + GstPad *mq_input = gst_pad_get_peer (inputpad); + + gst_pad_unlink (inputpad, mq_input); + gst_element_release_request_pad (mq, mq_input); + gst_object_unref (mq_input); + gst_object_unref (inputpad); + + gst_object_unref (sinkpad); + } + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + g_cond_clear (&cond); + g_mutex_clear (&mutex); +} + +GST_END_TEST; + +static void +check_for_stream_status_msg (GstElement * pipeline, GstElement * multiqueue, + GstStreamStatusType expected_type) +{ + GEnumClass *klass; + const gchar *expected_nick, *nick; + GstMessage *msg; + GstStreamStatusType type; + GstElement *owner; + + klass = g_type_class_ref (GST_TYPE_STREAM_STATUS_TYPE); + expected_nick = g_enum_get_value (klass, expected_type)->value_nick; + + GST_LOG ("waiting for stream-status %s message", expected_nick); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected stream-status message, got error message"); + + gst_message_parse_stream_status (msg, &type, &owner); + nick = g_enum_get_value (klass, type)->value_nick; + fail_unless (owner == multiqueue, + "Got incorrect owner: %" GST_PTR_FORMAT " expected: %" GST_PTR_FORMAT, + owner, multiqueue); + fail_unless (type == expected_type, + "Got incorrect type: %s expected: %s", nick, expected_nick); + + gst_message_unref (msg); + g_type_class_unref (klass); +} + +GST_START_TEST (test_stream_status_messages) +{ + GstElement *pipe, *mq; + GstPad *pad; + + pipe = gst_pipeline_new ("pipeline"); + mq = gst_element_factory_make ("multiqueue", NULL); + + gst_bin_add (GST_BIN (pipe), mq); + + pad = gst_element_get_request_pad (mq, "sink_%u"); + gst_object_unref (pad); + + gst_element_set_state (pipe, GST_STATE_PAUSED); + + check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_CREATE); + check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_ENTER); + + pad = gst_element_get_request_pad (mq, "sink_%u"); + gst_object_unref (pad); + + check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_CREATE); + check_for_stream_status_msg (pipe, mq, GST_STREAM_STATUS_TYPE_ENTER); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static Suite * +multiqueue_suite (void) +{ + Suite *s = suite_create ("multiqueue"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_simple_create_destroy); + tcase_add_test (tc_chain, test_simple_pipeline); + tcase_add_test (tc_chain, test_simple_shutdown_while_running); + + tcase_add_test (tc_chain, test_request_pads); + tcase_add_test (tc_chain, test_request_pads_named); + + /* Disabled, The test (and not multiqueue itself) is racy. + * See https://bugzilla.gnome.org/show_bug.cgi?id=708661 */ + tcase_skip_broken_test (tc_chain, test_output_order); + + tcase_add_test (tc_chain, test_not_linked_eos); + + tcase_add_test (tc_chain, test_sparse_stream); + tcase_add_test (tc_chain, test_initial_fill_above_high_threshold); + tcase_add_test (tc_chain, test_watermark_and_fill_level); + tcase_add_test (tc_chain, test_high_threshold_change); + tcase_add_test (tc_chain, test_low_threshold_change); + tcase_add_test (tc_chain, test_limit_changes); + + tcase_add_test (tc_chain, test_buffering_with_none_pts); + tcase_add_test (tc_chain, test_initial_events_nodelay); + + tcase_add_test (tc_chain, test_stream_status_messages); + + return s; +} + +GST_CHECK_MAIN (multiqueue) diff --git a/tests/check/elements/queue.c b/tests/check/elements/queue.c new file mode 100644 index 0000000..a41ef64 --- /dev/null +++ b/tests/check/elements/queue.c @@ -0,0 +1,1211 @@ +/* GStreamer + * + * unit test for queue + * + * Copyright (C) <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define UNDERRUN_LOCK() (g_mutex_lock (&underrun_mutex)) +#define UNDERRUN_UNLOCK() (g_mutex_unlock (&underrun_mutex)) +#define UNDERRUN_SIGNAL() (g_cond_signal (&underrun_cond)) +#define UNDERRUN_WAIT() (g_cond_wait (&underrun_cond, &underrun_mutex)) + +static GstElement *queue; + +/* 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; +static GstPad *mysinkpad; +static GstPad *qsrcpad; +static gulong probe_id; + +static gint overrun_count; + +static GMutex underrun_mutex; +static GCond underrun_cond; +static gint underrun_count; + +static GMutex events_lock; +static GCond events_cond; +static gint events_count; +static GList *events; + +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 void +queue_overrun (GstElement * queue, gpointer user_data) +{ + overrun_count++; + GST_DEBUG ("queue overrun %d", overrun_count); +} + +static void +queue_underrun (GstElement * queue, gpointer user_data) +{ + UNDERRUN_LOCK (); + underrun_count++; + GST_DEBUG ("queue underrun %d", underrun_count); + UNDERRUN_SIGNAL (); + UNDERRUN_UNLOCK (); +} + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GST_DEBUG ("%s event", GST_EVENT_TYPE_NAME (event)); + + g_mutex_lock (&events_lock); + + events = g_list_append (events, event); + ++events_count; + + g_cond_broadcast (&events_cond); + g_mutex_unlock (&events_lock); + + return TRUE; +} + +static void +block_src (void) +{ + qsrcpad = gst_element_get_static_pad (queue, "src"); + probe_id = gst_pad_add_probe (qsrcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + NULL, NULL, NULL); +} + +static void +unblock_src (void) +{ + gst_pad_remove_probe (qsrcpad, probe_id); + gst_object_unref (qsrcpad); +} + +static void +setup (void) +{ + GST_DEBUG ("setup_queue"); + + queue = gst_check_setup_element ("queue"); + g_signal_connect (queue, "underrun", G_CALLBACK (queue_underrun), NULL); + + mysrcpad = gst_check_setup_src_pad (queue, &srctemplate); + gst_pad_set_active (mysrcpad, TRUE); + + mysinkpad = NULL; + + overrun_count = 0; + + underrun_count = 0; + + + g_mutex_init (&events_lock); + g_cond_init (&events_cond); + events_count = 0; + events = NULL; +} + +static void +cleanup (void) +{ + GST_DEBUG ("cleanup_queue"); + + gst_check_drop_buffers (); + + while (events != NULL) { + gst_event_unref (GST_EVENT (events->data)); + events = g_list_delete_link (events, events); + } + events_count = 0; + g_mutex_clear (&events_lock); + g_cond_clear (&events_cond); + + if (mysinkpad != NULL) { + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (queue); + } + + gst_pad_set_active (mysrcpad, FALSE); + gst_check_teardown_src_pad (queue); + + gst_check_teardown_element (queue); + queue = NULL; +} + +/* setup the sinkpad on a playing queue element. gst_check_setup_sink_pad() + * does not work in this case since it does not activate the pad before linking + * it. */ +static GstPad * +setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl) +{ + GstPad *srcpad; + GstPad *sinkpad; + + sinkpad = gst_pad_new_from_static_template (tmpl, "sink"); + fail_if (sinkpad == NULL); + srcpad = gst_element_get_static_pad (element, "src"); + fail_if (srcpad == NULL); + gst_pad_set_chain_function (sinkpad, gst_check_chain_func); + gst_pad_set_event_function (sinkpad, event_func); + gst_pad_set_active (sinkpad, TRUE); + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK); + gst_object_unref (srcpad); + + return sinkpad; +} + +/* set queue size to 2 buffers + * pull 1 buffer + * check over/underuns + */ +GST_START_TEST (test_non_leaky_underrun) +{ + g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL); + mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate); + gst_pad_set_active (mysinkpad, TRUE); + + GST_DEBUG ("starting"); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +static void +queue_overrun_link_and_activate (GstElement * queue, gpointer user_data) +{ + GST_DEBUG ("queue overrun"); + overrun_count++; + + /* link the src pad of the queue to make it dequeue buffers */ + mysinkpad = setup_sink_pad (queue, &sinktemplate); + + unblock_src (); +} + +/* set queue size to 2 buffers + * push 2 buffers + * check over/underuns + * push 1 more buffer + * check over/underuns again + */ +GST_START_TEST (test_non_leaky_overrun) +{ + GstBuffer *buffer1; + GstBuffer *buffer2; + GstBuffer *buffer3; + GstBuffer *buffer; + GstSegment segment; + + g_signal_connect (queue, "overrun", + G_CALLBACK (queue_overrun_link_and_activate), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL); + + block_src (); + + GST_DEBUG ("starting"); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + fail_unless (underrun_count == 1); + fail_unless (overrun_count == 0); + + buffer1 = gst_buffer_new_and_alloc (4); + /* pushing gives away my reference */ + gst_pad_push (mysrcpad, buffer1); + + GST_DEBUG ("added 1st"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer2 = gst_buffer_new_and_alloc (4); + gst_pad_push (mysrcpad, buffer2); + + GST_DEBUG ("added 2nd"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer3 = gst_buffer_new_and_alloc (4); + /* the next call to gst_pad_push will emit the overrun signal. The signal + * handler queue_overrun_link_and_activate() (above) increases overrun_count, + * activates and links mysinkpad. The queue task then dequeues a buffer and + * gst_pad_push() will return. */ + gst_pad_push (mysrcpad, buffer3); + + GST_DEBUG ("added 3rd"); + fail_unless (overrun_count == 1); + + /* lock the check_mutex to block the first buffer pushed to mysinkpad */ + g_mutex_lock (&check_mutex); + /* now let the queue push all buffers */ + while (g_list_length (buffers) < 3) { + g_cond_wait (&check_cond, &check_mutex); + } + g_mutex_unlock (&check_mutex); + + fail_unless (overrun_count == 1); + /* make sure we get the underrun signal before we check underrun_count */ + UNDERRUN_LOCK (); + while (underrun_count < 2) { + UNDERRUN_WAIT (); + } + /* we can't check the underrun_count here safely because when adding the 3rd + * buffer, the queue lock is released to emit the overrun signal and the + * downstream part can then push and empty the queue and signal an additional + * underrun */ + /* fail_unless_equals_int (underrun_count, 2); */ + UNDERRUN_UNLOCK (); + + buffer = g_list_nth (buffers, 0)->data; + fail_unless (buffer == buffer1); + + buffer = g_list_nth (buffers, 1)->data; + fail_unless (buffer == buffer2); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +/* set queue size to 2 buffers + * push 2 buffers + * check over/underuns + * push 1 more buffer + * check over/underuns again + * check which buffer was leaked + */ +GST_START_TEST (test_leaky_upstream) +{ + GstBuffer *buffer1; + GstBuffer *buffer2; + GstBuffer *buffer3; + GstBuffer *buffer; + GstSegment segment; + + g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 1, NULL); + + GST_DEBUG ("starting"); + + block_src (); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer1 = gst_buffer_new_and_alloc (4); + /* pushing gives away my reference */ + gst_pad_push (mysrcpad, buffer1); + + GST_DEBUG ("added 1st"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer2 = gst_buffer_new_and_alloc (4); + gst_pad_push (mysrcpad, buffer2); + + GST_DEBUG ("added 2nd"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer3 = gst_buffer_new_and_alloc (4); + /* buffer4 will be leaked, keep a ref so refcount can be checked below */ + gst_buffer_ref (buffer3); + gst_pad_push (mysrcpad, buffer3); + + GST_DEBUG ("added 3nd"); + /* it still triggers overrun when leaking */ + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 1); + + /* wait for underrun and check that we got buffer1 and buffer2 only */ + UNDERRUN_LOCK (); + mysinkpad = setup_sink_pad (queue, &sinktemplate); + unblock_src (); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 2); + + fail_unless (g_list_length (buffers) == 2); + + buffer = g_list_nth (buffers, 0)->data; + fail_unless (buffer == buffer1); + + buffer = g_list_nth (buffers, 1)->data; + fail_unless (buffer == buffer2); + + ASSERT_BUFFER_REFCOUNT (buffer3, "buffer", 1); + gst_buffer_unref (buffer3); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +/* set queue size to 2 buffers + * push 2 buffers + * check over/underuns + * push 1 more buffer + * check over/underuns again + * check which buffer was leaked + */ +GST_START_TEST (test_leaky_downstream) +{ + GstBuffer *buffer1; + GstBuffer *buffer2; + GstBuffer *buffer3; + GstBuffer *buffer; + GstSegment segment; + + g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 2, "leaky", 2, NULL); + + GST_DEBUG ("starting"); + + block_src (); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer1 = gst_buffer_new_and_alloc (4); + /* pushing gives away one reference */ + /* buffer1 will be leaked, keep a ref so refcount can be checked below */ + gst_buffer_ref (buffer1); + gst_pad_push (mysrcpad, buffer1); + + GST_DEBUG ("added 1st"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer2 = gst_buffer_new_and_alloc (4); + gst_pad_push (mysrcpad, buffer2); + + GST_DEBUG ("added 2nd"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 1); + + buffer3 = gst_buffer_new_and_alloc (4); + gst_pad_push (mysrcpad, buffer3); + + GST_DEBUG ("added 3rd"); + /* it still triggers overrun when leaking */ + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 1); + + /* wait for underrun and check that we got buffer1 and buffer2 only */ + UNDERRUN_LOCK (); + mysinkpad = setup_sink_pad (queue, &sinktemplate); + unblock_src (); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 2); + + fail_unless (g_list_length (buffers) == 2); + + ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1); + gst_buffer_unref (buffer1); + + buffer = g_list_nth (buffers, 0)->data; + fail_unless (buffer == buffer2); + + buffer = g_list_nth (buffers, 1)->data; + fail_unless (buffer == buffer3); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +/* set queue size to 6 buffers and 7 seconds + * push 7 buffers with and without duration + * check current-level-time + */ +GST_START_TEST (test_time_level) +{ + GstBuffer *buffer = NULL; + GstClockTime time; + GstSegment segment; + + g_signal_connect (queue, "overrun", + G_CALLBACK (queue_overrun_link_and_activate), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 6, NULL); + g_object_set (G_OBJECT (queue), "max-size-time", 7 * GST_SECOND, NULL); + + GST_DEBUG ("starting"); + + block_src (); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + /* push buffer without duration */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND; + /* pushing gives away my reference */ + gst_pad_push (mysrcpad, buffer); + + /* level should be 1 seconds because buffer has no duration and starts at 1 + * SECOND (sparse stream). */ + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != GST_SECOND); + + /* second push should set the level to 2 second */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 2 * GST_SECOND); + + /* third push should set the level to 4 seconds, the 1 second diff with the + * previous buffer (without duration) and the 1 second duration of this + * buffer. */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 4 * GST_SECOND); + + /* fourth push should set the level to 6 seconds, the 2 second diff with the + * previous buffer, same duration. */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 6 * GST_SECOND); + + /* fifth push should not adjust the level, the timestamp and duration are the + * same, meaning the previous buffer did not really have a duration. */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 6 * GST_SECOND); + + /* sixth push should adjust the level with 1 second, we now know the + * previous buffer actually had a duration of 2 SECONDS */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 7 * GST_SECOND; + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 7 * GST_SECOND); + + /* eighth push should cause overrun */ + fail_unless (overrun_count == 0); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 8 * GST_SECOND; + /* the next call to gst_pad_push will emit the overrun signal. The signal + * handler queue_overrun_link_and_activate() (above) increases overrun_count, + * activates and links mysinkpad. The queue task then dequeues a buffer and + * gst_pad_push() will return. */ + gst_pad_push (mysrcpad, buffer); + + fail_unless (overrun_count == 1); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +GST_START_TEST (test_time_level_task_not_started) +{ + GstEvent *event; + GstClockTime time; + GstSegment segment; + + GST_DEBUG ("starting"); + + block_src (); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 1 * GST_SECOND; + segment.stop = 5 * GST_SECOND; + segment.time = 0; + segment.position = 1 * GST_SECOND; + + event = gst_event_new_segment (&segment); + gst_pad_push_event (mysrcpad, event); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_if (time != 0 * GST_SECOND); + + segment.base = 4 * GST_SECOND; + event = gst_event_new_segment (&segment); + gst_pad_push_event (mysrcpad, event); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + GST_DEBUG ("time now %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); + fail_if (time != 4 * GST_SECOND); + + unblock_src (); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +GST_START_TEST (test_sticky_not_linked) +{ + GstEvent *event; + GstSegment segment; + gboolean ret; + GstFlowReturn flow_ret; + + GST_DEBUG ("starting"); + + g_object_set (queue, "max-size-buffers", 1, NULL); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 1 * GST_SECOND; + segment.stop = 5 * GST_SECOND; + segment.time = 0; + segment.position = 1 * GST_SECOND; + + event = gst_event_new_segment (&segment); + ret = gst_pad_push_event (mysrcpad, event); + fail_unless (ret == TRUE); + + /* the first few buffers can return OK as they are queued and gst_queue_loop + * is woken up, tries to push and sets ->srcresult to NOT_LINKED + */ + flow_ret = GST_FLOW_OK; + while (flow_ret != GST_FLOW_NOT_LINKED) + flow_ret = gst_pad_push (mysrcpad, gst_buffer_new ()); + + /* send a new sticky event so that it will be pushed on the next gst_pad_push + */ + event = gst_event_new_segment (&segment); + ret = gst_pad_push_event (mysrcpad, event); + fail_unless (ret == TRUE); + + /* make sure that gst_queue_sink_event doesn't return FALSE if the queue is + * unlinked, as that would make gst_pad_push return ERROR + */ + flow_ret = gst_pad_push (mysrcpad, gst_buffer_new ()); + fail_unless_equals_int (flow_ret, GST_FLOW_NOT_LINKED); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +#if 0 +static gboolean +event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate, + GstFormat format, gint64 start, gint64 stop, gint64 position) +{ + gboolean ns_update; + gdouble ns_rate, ns_arate; + GstFormat ns_format; + gint64 ns_start; + gint64 ns_stop; + gint64 ns_position; + + if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT) { + return FALSE; + } + + gst_event_parse_new_segment (event, &ns_update, &ns_rate, &ns_arate, + &ns_format, &ns_start, &ns_stop, &ns_position); + + GST_DEBUG ("update %d, rate %lf, format %s, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT, ns_update, + ns_rate, gst_format_get_name (ns_format), GST_TIME_ARGS (ns_start), + GST_TIME_ARGS (ns_stop), GST_TIME_ARGS (ns_position)); + + return (ns_update == update && ns_rate == rate && ns_format == format && + ns_start == start && ns_stop == stop && ns_position == position); +} + +GST_START_TEST (test_newsegment) +{ + GstEvent *event; + GstBuffer *buffer1; + GstBuffer *buffer2; + GstBuffer *buffer; + + g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 1, "max-size-time", + (guint64) 0, "leaky", 2, NULL); + + GST_DEBUG ("starting"); + + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 0); + + event = gst_event_new_new_segment (FALSE, 2.0, 1.0, GST_FORMAT_TIME, 0, + 2 * GST_SECOND, 0); + gst_pad_push_event (mysrcpad, event); + + GST_DEBUG ("added 1st newsegment"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 0); + + event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0, + 3 * GST_SECOND, 0); + gst_pad_push_event (mysrcpad, event); + + GST_DEBUG ("added 2nd newsegment"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 0); + + event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME, + 4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND); + gst_pad_push_event (mysrcpad, event); + + GST_DEBUG ("added 3rd newsegment"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 0); + + buffer1 = gst_buffer_new_and_alloc (4); + /* buffer1 will be leaked, keep a ref so refcount can be checked below */ + gst_buffer_ref (buffer1); + /* pushing gives away one reference */ + gst_pad_push (mysrcpad, buffer1); + + GST_DEBUG ("added 1st buffer"); + fail_unless (overrun_count == 0); + fail_unless (underrun_count == 0); + + buffer2 = gst_buffer_new_and_alloc (4); + /* next push will cause overrun and leak all newsegment events and buffer1 */ + gst_pad_push (mysrcpad, buffer2); + + GST_DEBUG ("added 2nd buffer"); + /* it still triggers overrun when leaking */ + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 0); + + /* wait for underrun and check that we got one accumulated newsegment event, + * one real newsegment event and buffer2 only */ + UNDERRUN_LOCK (); + mysinkpad = setup_sink_pad (queue, &sinktemplate); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + fail_unless (overrun_count == 1); + fail_unless (underrun_count == 1); + + fail_unless (g_list_length (events) == 2); + + event = g_list_nth (events, 0)->data; + fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME, 0, + 4 * GST_SECOND, 0)); + + event = g_list_nth (events, 1)->data; + fail_unless (event_equals_newsegment (event, FALSE, 1.0, GST_FORMAT_TIME, + 4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND)); + + fail_unless (g_list_length (buffers) == 1); + + ASSERT_BUFFER_REFCOUNT (buffer1, "buffer", 1); + gst_buffer_unref (buffer1); + + buffer = g_list_nth (buffers, 0)->data; + fail_unless (buffer == buffer2); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; +#endif + +static gpointer +thread_func (gpointer data) +{ + int i = 0; + for (i = 0; i < 100; i++) { + GstCaps *caps; + GstQuery *query; + gboolean ok; + caps = gst_caps_new_any (); + query = gst_query_new_allocation (caps, FALSE); + ok = gst_pad_peer_query (mysrcpad, query); + gst_query_unref (query); + gst_caps_unref (caps); + query = NULL; + caps = NULL; + + if (!ok) + break; + } + + return NULL; +} + +static gboolean query_func (GstPad * pad, GstObject * parent, GstQuery * query); + +static gboolean +query_func (GstPad * pad, GstObject * parent, GstQuery * query) +{ + + g_usleep (1000); + return TRUE; +} + +GST_START_TEST (test_queries_while_flushing) +{ + GstEvent *event; + GThread *thread; + int i; + + mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate); + gst_pad_set_query_function (mysinkpad, query_func); + gst_pad_set_active (mysinkpad, TRUE); + + /* hard to reproduce, so just run it a few times in a row */ + for (i = 0; i < 500; ++i) { + GST_DEBUG ("starting"); + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + thread = g_thread_new ("deactivating thread", thread_func, NULL); + g_usleep (1000); + + event = gst_event_new_flush_start (); + gst_pad_push_event (mysrcpad, event); + + g_thread_join (thread); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, + "could not set to null"); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_serialized_query_with_threshold) +{ + GstQuery *query; + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + + g_object_set (queue, "min-threshold-buffers", 10, NULL); + + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + gst_pad_push (mysrcpad, gst_buffer_new ()); + + query = gst_query_new_drain (); + gst_pad_peer_query (mysrcpad, query); + gst_query_unref (query); + + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + + +static gpointer +push_event_thread_func (gpointer data) +{ + GstEvent *event; + + event = GST_EVENT (data); + + GST_DEBUG ("pushing event %p on pad %p", event, mysrcpad); + gst_pad_push_event (mysrcpad, event); + + return NULL; +} + +GST_START_TEST (test_state_change_when_flushing) +{ + GstEvent *event; + GThread *thread; + + mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate); + gst_pad_set_active (mysinkpad, TRUE); + + fail_unless (gst_element_set_state (queue, GST_STATE_PAUSED) == + GST_STATE_CHANGE_SUCCESS); + + event = gst_event_new_flush_start (); + gst_pad_push_event (mysrcpad, event); + + event = gst_event_new_flush_stop (TRUE); + thread = g_thread_new ("send event", push_event_thread_func, event); + + GST_DEBUG ("changing state to READY"); + fail_unless (gst_element_set_state (queue, GST_STATE_READY) == + GST_STATE_CHANGE_SUCCESS); + GST_DEBUG ("state changed"); + + g_thread_join (thread); + + fail_unless (gst_element_set_state (queue, GST_STATE_NULL) == + GST_STATE_CHANGE_SUCCESS); +} + +GST_END_TEST; + +GST_START_TEST (test_time_level_buffer_list) +{ + GstBuffer *buffer = NULL; + GstBufferList *buffer_list = NULL; + GstClockTime time; + guint buffers; + GstSegment segment; + + g_signal_connect (queue, "overrun", + G_CALLBACK (queue_overrun_link_and_activate), NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 11, NULL); + g_object_set (G_OBJECT (queue), "max-size-time", + G_GUINT64_CONSTANT (7000) * GST_MSECOND, NULL); + + GST_DEBUG ("starting"); + + block_src (); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + + /* push buffer without duration */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 1000 * GST_MSECOND; + /* pushing gives away my reference */ + gst_pad_push (mysrcpad, buffer); + + /* level should be 1 seconds because buffer has no duration and starts at 1 + * SECOND (sparse stream). */ + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 1000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 1); + + /* second push should set the level to 2 second */ + buffer_list = gst_buffer_list_new (); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 1500 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 2000 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + gst_pad_push_list (mysrcpad, buffer_list); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 2000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 3); + + /* third push should set the level to 4 seconds, the 1 second diff with the + * previous buffer (without duration) and the 1 second duration of this + * buffer. */ + buffer_list = gst_buffer_list_new (); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 3000 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 500 * GST_MSECOND; + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_buffer_list_add (buffer_list, buffer); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 3500 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 500 * GST_MSECOND; + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_buffer_list_add (buffer_list, buffer); + gst_pad_push_list (mysrcpad, buffer_list); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 4000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 5); + + /* fourth push should set the level to 6 seconds, the 2 second diff with the + * previous buffer, same duration. */ + buffer_list = gst_buffer_list_new (); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5000 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 1000 * GST_MSECOND; + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_buffer_list_add (buffer_list, buffer); + gst_pad_push_list (mysrcpad, buffer_list); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 6000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 6); + + /* fifth push should not adjust the level, the timestamp and duration are the + * same, meaning the previous buffer did not really have a duration. */ + buffer_list = gst_buffer_list_new (); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5000 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5250 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5500 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 5750 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_list_add (buffer_list, buffer); + gst_pad_push_list (mysrcpad, buffer_list); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 6000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 10); + + /* sixth push should adjust the level with 1 second, we now know the + * previous buffer actually had a duration of 2 SECONDS */ + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 7000 * GST_MSECOND; + gst_pad_push (mysrcpad, buffer); + + g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL); + fail_unless_equals_uint64 (time, 7000 * GST_MSECOND); + g_object_get (G_OBJECT (queue), "current-level-buffers", &buffers, NULL); + fail_unless_equals_int (buffers, 11); + + /* eighth push should cause overrun */ + fail_unless (overrun_count == 0); + buffer_list = gst_buffer_list_new (); + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (buffer) = 8000 * GST_MSECOND; + /* the next call to gst_pad_push will emit the overrun signal. The signal + * handler queue_overrun_link_and_activate() (above) increases overrun_count, + * activates and links mysinkpad. The queue task then dequeues a buffer and + * gst_pad_push() will return. */ + gst_buffer_list_add (buffer_list, buffer); + gst_pad_push_list (mysrcpad, buffer_list); + + fail_unless (overrun_count == 1); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + +GST_START_TEST (test_initial_events_nodelay) +{ + GstSegment segment; + GstEvent *event; + GstCaps *caps; + gboolean ret; + + mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate); + gst_pad_set_event_function (mysinkpad, event_func); + gst_pad_set_active (mysinkpad, TRUE); + + GST_DEBUG ("starting"); + + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + ret = gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + fail_unless (ret == TRUE); + + gst_segment_init (&segment, GST_FORMAT_TIME); + ret = gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); + fail_unless (ret == TRUE); + + g_mutex_lock (&events_lock); + while (events_count < 3) { + g_cond_wait (&events_cond, &events_lock); + } + g_mutex_unlock (&events_lock); + + fail_unless_equals_int (g_list_length (events), 3); + event = g_list_nth_data (events, 0); + fail_unless_equals_int (GST_EVENT_TYPE (event), GST_EVENT_STREAM_START); + event = g_list_nth_data (events, 1); + fail_unless_equals_int (GST_EVENT_TYPE (event), GST_EVENT_CAPS); + event = g_list_nth_data (events, 2); + fail_unless_equals_int (GST_EVENT_TYPE (event), GST_EVENT_SEGMENT); + + gst_element_set_state (queue, GST_STATE_NULL); +} + +GST_END_TEST; + +static Suite * +queue_suite (void) +{ + Suite *s = suite_create ("queue"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_checked_fixture (tc_chain, setup, cleanup); + tcase_add_test (tc_chain, test_non_leaky_underrun); + tcase_add_test (tc_chain, test_non_leaky_overrun); + tcase_add_test (tc_chain, test_leaky_upstream); + tcase_add_test (tc_chain, test_leaky_downstream); + tcase_add_test (tc_chain, test_time_level); + tcase_add_test (tc_chain, test_time_level_task_not_started); + tcase_add_test (tc_chain, test_queries_while_flushing); + tcase_add_test (tc_chain, test_serialized_query_with_threshold); + tcase_add_test (tc_chain, test_state_change_when_flushing); +#if 0 + tcase_add_test (tc_chain, test_newsegment); +#endif + tcase_add_test (tc_chain, test_sticky_not_linked); + tcase_add_test (tc_chain, test_time_level_buffer_list); + tcase_add_test (tc_chain, test_initial_events_nodelay); + + return s; +} + +GST_CHECK_MAIN (queue); diff --git a/tests/check/elements/queue2.c b/tests/check/elements/queue2.c new file mode 100644 index 0000000..5707d1c --- /dev/null +++ b/tests/check/elements/queue2.c @@ -0,0 +1,567 @@ +/* GStreamer unit tests for queue2 + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstElement * +setup_queue2 (GstElement * pipe, GstElement * input, GstElement * output) +{ + GstElement *queue2; + GstPad *sinkpad, *srcpad; + + queue2 = gst_element_factory_make ("queue2", NULL); + fail_unless (queue2 != NULL, "failed to create 'queue2' element"); + + gst_bin_add (GST_BIN (pipe), queue2); + gst_bin_add (GST_BIN (pipe), input); + gst_bin_add (GST_BIN (pipe), output); + + sinkpad = gst_element_get_static_pad (queue2, "sink"); + fail_unless (sinkpad != NULL, "failed to get queue2 sink pad"); + + srcpad = gst_element_get_static_pad (input, "src"); + fail_unless (srcpad != NULL, "failed to find src pad for input element"); + + fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + srcpad = gst_element_get_static_pad (queue2, "src"); + fail_unless (srcpad != NULL); + + sinkpad = gst_element_get_static_pad (output, "sink"); + fail_unless (sinkpad != NULL, "failed to find sink pad of output element"); + + fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad)); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + return queue2; +} + +GST_START_TEST (test_simple_pipeline) +{ + GstElement *pipe, *input, *output; + GstMessage *msg; + + pipe = gst_pipeline_new ("pipeline"); + + input = gst_element_factory_make ("fakesrc", NULL); + fail_unless (input != NULL, "failed to create 'fakesrc' element"); + g_object_set (input, "num-buffers", 256, "sizetype", 3, NULL); + + output = gst_element_factory_make ("fakesink", NULL); + fail_unless (output != NULL, "failed to create 'fakesink' element"); + + setup_queue2 (pipe, input, output); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected EOS message, got ERROR message"); + gst_message_unref (msg); + + GST_LOG ("Got EOS, cleaning up"); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +GST_START_TEST (test_simple_pipeline_ringbuffer) +{ + GstElement *pipe, *queue2, *input, *output; + GstMessage *msg; + + pipe = gst_pipeline_new ("pipeline"); + + input = gst_element_factory_make ("fakesrc", NULL); + fail_unless (input != NULL, "failed to create 'fakesrc' element"); + g_object_set (input, "num-buffers", 256, "sizetype", 3, NULL); + + output = gst_element_factory_make ("fakesink", NULL); + fail_unless (output != NULL, "failed to create 'fakesink' element"); + + queue2 = setup_queue2 (pipe, input, output); + g_object_set (queue2, "ring-buffer-max-size", (guint64) 1024 * 50, NULL); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected EOS message, got ERROR message"); + gst_message_unref (msg); + + GST_LOG ("Got EOS, cleaning up"); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static void +do_test_simple_shutdown_while_running (guint64 ring_buffer_max_size) +{ + GstElement *pipe, *q2; + GstElement *input; + GstElement *output; + GstMessage *msg; + + pipe = gst_pipeline_new ("pipeline"); + + input = gst_element_factory_make ("fakesrc", NULL); + fail_unless (input != NULL, "failed to create 'fakesrc' element"); + g_object_set (input, "format", GST_FORMAT_TIME, "sizetype", 2, + "sizemax", 10, NULL); + + output = gst_element_factory_make ("fakesink", NULL); + fail_unless (output != NULL, "failed to create 'fakesink' element"); + + q2 = setup_queue2 (pipe, input, output); + + if (ring_buffer_max_size > 0) { + g_object_set (q2, "ring-buffer-max-size", ring_buffer_max_size, + "temp-template", NULL, NULL); + } + + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* wait until pipeline is up and running */ + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE, -1); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, "Got ERROR message"); + gst_message_unref (msg); + + GST_LOG ("pipeline is running now"); + gst_element_set_state (pipe, GST_STATE_PLAYING); + g_usleep (G_USEC_PER_SEC / 20); + + /* now shut down only the sink, so the queue gets a wrong-state flow return */ + gst_element_set_state (output, GST_STATE_NULL); + GST_LOG ("Cleaning up"); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_START_TEST (test_simple_shutdown_while_running) +{ + int i; + + /* run a couple of iterations, gives higher chance of different code paths + * being executed at time the flush is detected (esp. useful to make sure + * things are cleaned up properly when running under valgrind) */ + for (i = 0; i < 10; ++i) { + do_test_simple_shutdown_while_running (0); + } +} + +GST_END_TEST; + +GST_START_TEST (test_simple_shutdown_while_running_ringbuffer) +{ + int i; + + /* run a couple of iterations, gives higher chance of different code paths + * being executed at time the flush is detected (esp. useful to make sure + * things are cleaned up properly when running under valgrind) */ + for (i = 0; i < 10; ++i) { + do_test_simple_shutdown_while_running (1024 * 1024); + } +} + +GST_END_TEST; + +GST_START_TEST (test_simple_create_destroy) +{ + GstElement *queue2; + + queue2 = gst_element_factory_make ("queue2", NULL); + gst_object_unref (queue2); +} + +GST_END_TEST; + +static gboolean +queue2_dummypad_query (GstPad * sinkpad, GstObject * parent, GstQuery * query) +{ + gboolean res = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstCaps *filter, *caps; + + gst_query_parse_caps (query, &filter); + caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + break; + } + default: + res = gst_pad_query_default (sinkpad, parent, query); + break; + } + return res; +} + +static gpointer +pad_push_datablock_thread (gpointer data) +{ + GstPad *pad = data; + GstBuffer *buf; + + buf = gst_buffer_new_allocate (NULL, 80 * 1000, NULL); + gst_pad_push (pad, buf); + + return NULL; +} + +static GstPadProbeReturn +block_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + return GST_PAD_PROBE_OK; +} + +#define CHECK_FOR_BUFFERING_MSG(PIPELINE, EXPECTED_PERC) \ + G_STMT_START { \ + gint buf_perc; \ + GstMessage *msg; \ + GST_LOG ("waiting for %d%% buffering message", (EXPECTED_PERC)); \ + msg = gst_bus_poll (GST_ELEMENT_BUS (PIPELINE), \ + GST_MESSAGE_BUFFERING | GST_MESSAGE_ERROR, -1); \ + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, \ + "Expected BUFFERING message, got ERROR message"); \ + gst_message_parse_buffering (msg, &buf_perc); \ + gst_message_unref (msg); \ + fail_unless (buf_perc == (EXPECTED_PERC), \ + "Got incorrect percentage: %d%% expected: %d%%", buf_perc, \ + (EXPECTED_PERC)); \ + } G_STMT_END + +GST_START_TEST (test_watermark_and_fill_level) +{ + /* This test checks the behavior of the fill level and + * the low/high watermarks. It also checks if the + * low/high-percent and low/high-watermark properties + * are coupled together properly. */ + + GstElement *pipe; + GstElement *queue2, *fakesink; + GstPad *inputpad; + GstPad *queue2_sinkpad; + GstPad *sinkpad; + GstSegment segment; + GThread *thread; + gint low_perc, high_perc; + + + /* Setup test pipeline with one multiqueue and one fakesink */ + + pipe = gst_pipeline_new ("pipeline"); + queue2 = gst_element_factory_make ("queue2", NULL); + fail_unless (queue2 != NULL); + gst_bin_add (GST_BIN (pipe), queue2); + + fakesink = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink != NULL); + gst_bin_add (GST_BIN (pipe), fakesink); + + /* Block fakesink sinkpad flow to ensure the queue isn't emptied + * by the prerolling sink */ + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BLOCK, block_probe, NULL, + NULL); + gst_object_unref (sinkpad); + + g_object_set (queue2, + "use-buffering", (gboolean) TRUE, + "max-size-bytes", (guint) 1000 * 1000, + "max-size-buffers", (guint) 0, + "max-size-time", (guint64) 0, + "low-watermark", (gdouble) 0.01, "high-watermark", (gdouble) 0.10, NULL); + + g_object_get (queue2, "low-percent", &low_perc, + "high-percent", &high_perc, NULL); + + /* Check that low/high-watermark and low/high-percent are + * coupled properly. (low/high-percent are deprecated and + * exist for backwards compatibility.) */ + fail_unless_equals_int (low_perc, 1); + fail_unless_equals_int (high_perc, 10); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + inputpad = gst_pad_new ("dummysrc", GST_PAD_SRC); + gst_pad_set_query_function (inputpad, queue2_dummypad_query); + + queue2_sinkpad = gst_element_get_static_pad (queue2, "sink"); + fail_unless (queue2_sinkpad != NULL); + fail_unless (gst_pad_link (inputpad, queue2_sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (inputpad, TRUE); + + gst_pad_push_event (inputpad, gst_event_new_stream_start ("test")); + gst_pad_push_event (inputpad, gst_event_new_segment (&segment)); + + gst_object_unref (queue2_sinkpad); + + fail_unless (gst_element_link (queue2, fakesink)); + + /* Start pipeline in paused state to ensure the sink remains + * in preroll mode and blocks */ + gst_element_set_state (pipe, GST_STATE_PAUSED); + + /* When the use-buffering property is set to TRUE, a buffering + * message is posted. Since the queue is empty at that point, + * the buffering message contains a value of 0%. */ + CHECK_FOR_BUFFERING_MSG (pipe, 0); + + /* Feed data. queue will be filled to 80% (because it pushes 80000 bytes), + * which is below the high-threshold, provoking a buffering message. */ + thread = g_thread_new ("push1", pad_push_datablock_thread, inputpad); + g_thread_join (thread); + + /* Check for the buffering message; it should indicate 80% fill level + * (Note that the percentage from the message is normalized) */ + CHECK_FOR_BUFFERING_MSG (pipe, 80); + + /* Increase the buffer size and lower the watermarks to test + * if <1% watermarks are supported. */ + g_object_set (queue2, + "max-size-bytes", (guint) 20 * 1000 * 1000, + "low-watermark", (gdouble) 0.0001, "high-watermark", (gdouble) 0.005, + NULL); + + /* First buffering message is posted after the max-size-bytes limit + * is set to 20000000 bytes & the low-watermark is set. Since the + * queue contains 80000 bytes, and the high watermark still is + * 0.1 at this point, and the buffer level 80000 / 20000000 = 0.004 is + * normalized by 0.1: 0.004 / 0.1 => buffering percentage 4%. */ + CHECK_FOR_BUFFERING_MSG (pipe, 4); + /* Second buffering message is posted after the high-watermark limit + * is set to 0.005. This time, the buffer level is normalized this way: + * 0.004 / 0.005 => buffering percentage 80%. */ + CHECK_FOR_BUFFERING_MSG (pipe, 80); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + gst_object_unref (inputpad); +} + +GST_END_TEST; + +static gpointer +push_buffer (GstPad * sinkpad) +{ + GstBuffer *buffer; + + buffer = gst_buffer_new_and_alloc (1 * 1024); + + gst_pad_chain (sinkpad, buffer); + + return NULL; +} + +GST_START_TEST (test_filled_read) +{ + GstElement *queue2; + GstBuffer *buffer; + GstPad *sinkpad, *srcpad; + GThread *thread; + GstSegment segment; + + queue2 = gst_element_factory_make ("queue2", NULL); + sinkpad = gst_element_get_static_pad (queue2, "sink"); + srcpad = gst_element_get_static_pad (queue2, "src"); + + g_object_set (queue2, "ring-buffer-max-size", (guint64) 5 * 1024, + "use-buffering", FALSE, + "max-size-buffers", (guint) 0, "max-size-time", (guint64) 0, + "max-size-bytes", (guint) 4 * 1024, NULL); + + gst_pad_activate_mode (srcpad, GST_PAD_MODE_PULL, TRUE); + gst_element_set_state (queue2, GST_STATE_PLAYING); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)); + + /* fill up the buffer */ + buffer = gst_buffer_new_and_alloc (4 * 1024); + fail_unless (gst_pad_chain (sinkpad, buffer) == GST_FLOW_OK); + + thread = + g_thread_try_new ("gst-check", (GThreadFunc) push_buffer, sinkpad, NULL); + fail_unless (thread != NULL); + + buffer = NULL; + fail_unless (gst_pad_get_range (srcpad, 1024, 4 * 1024, + &buffer) == GST_FLOW_OK); + + fail_unless (gst_buffer_get_size (buffer) == 4 * 1024); + gst_buffer_unref (buffer); + + gst_element_set_state (queue2, GST_STATE_NULL); + + g_thread_join (thread); + + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_object_unref (queue2); +} + +GST_END_TEST; + + +static GstPadProbeReturn +block_callback (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_percent_overflow) +{ + GstElement *queue2; + GstBuffer *buffer; + GstPad *sinkpad, *srcpad; + gulong block_probe; + guint64 i; + guint64 current_level_time; + GstSegment segment; + + queue2 = gst_element_factory_make ("queue2", NULL); + sinkpad = gst_element_get_static_pad (queue2, "sink"); + srcpad = gst_element_get_static_pad (queue2, "src"); + + block_probe = gst_pad_add_probe (srcpad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, + block_callback, NULL, NULL); + + g_object_set (queue2, "use-buffering", TRUE, + "use-rate-estimate", FALSE, + "max-size-buffers", 0, + "max-size-time", 2 * GST_SECOND, "max-size-bytes", 0, NULL); + + gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); + gst_element_set_state (queue2, GST_STATE_PAUSED); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 0; + segment.time = 0; + segment.position = 0; + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)); + + /* push 2 seconds of data with valid but excessively high timestamps */ + for (i = 0; i < 20; i++) { + buffer = gst_buffer_new_and_alloc (1024); + GST_BUFFER_PTS (buffer) = + G_GUINT64_CONSTANT (18446744071709551616) + i * (GST_SECOND / 10); + GST_BUFFER_DTS (buffer) = + G_GUINT64_CONSTANT (18446744071709551616) + i * (GST_SECOND / 10); + GST_BUFFER_DURATION (buffer) = (GST_SECOND / 10); + fail_unless (gst_pad_chain (sinkpad, buffer) == GST_FLOW_OK); + } + + g_object_get (queue2, "current-level-time", ¤t_level_time, NULL); + + gst_pad_remove_probe (srcpad, block_probe); + + gst_element_set_state (queue2, GST_STATE_NULL); + + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_object_unref (queue2); +} + +GST_END_TEST; + +GST_START_TEST (test_small_ring_buffer) +{ + GstElement *pipeline; + GstElement *queue2; + const gchar *desc; + GstBus *bus; + GstMessage *msg; + + /* buffer too small to seek used to crash, test for regression */ + desc = "fakesrc sizetype=2 sizemax=4096 num-buffers=100 datarate=1000 ! " + "queue2 ring-buffer-max-size=1000 name=q2 ! fakesink sync=true"; + + pipeline = gst_parse_launch (desc, NULL); + fail_if (pipeline == NULL); + + queue2 = gst_bin_get_by_name (GST_BIN (pipeline), "q2"); + fail_if (queue2 == NULL); + + /* bring the pipeline to PLAYING, then start switching */ + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + /* Wait for the pipeline to hit playing */ + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + /* now wait for completion or error */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, + "Expected EOS message, got ERROR message"); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (queue2); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +queue2_suite (void) +{ + Suite *s = suite_create ("queue2"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_simple_create_destroy); + tcase_add_test (tc_chain, test_simple_pipeline); + tcase_add_test (tc_chain, test_simple_pipeline_ringbuffer); + tcase_add_test (tc_chain, test_simple_shutdown_while_running); + tcase_add_test (tc_chain, test_simple_shutdown_while_running_ringbuffer); + tcase_add_test (tc_chain, test_watermark_and_fill_level); + tcase_add_test (tc_chain, test_filled_read); + tcase_add_test (tc_chain, test_percent_overflow); + tcase_add_test (tc_chain, test_small_ring_buffer); + + return s; +} + +GST_CHECK_MAIN (queue2) diff --git a/tests/check/elements/selector.c b/tests/check/elements/selector.c new file mode 100644 index 0000000..ac4f3ec --- /dev/null +++ b/tests/check/elements/selector.c @@ -0,0 +1,854 @@ +/* GStreamer + * + * Unit test for selector plugin + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define NUM_SELECTOR_PADS 4 +#define NUM_INPUT_BUFFERS 4 // buffers to send per each selector pad + +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); + +/* Data probe cb to drop everything but count buffers and events */ +static GstPadProbeReturn +probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gint count = 0; + const gchar *count_type = NULL; + GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info); + + GST_LOG_OBJECT (pad, "got data"); + + if (GST_IS_BUFFER (obj)) { + count_type = "buffer_count"; + } else if (GST_IS_EVENT (obj)) { + count_type = "event_count"; + } else { + g_assert_not_reached (); + } + + /* increment and store count */ + count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), count_type)); + count++; + g_object_set_data (G_OBJECT (pad), count_type, GINT_TO_POINTER (count)); + + /* drop every buffer */ + return GST_IS_BUFFER (obj) ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_PASS; +} + +/* Create and link output pad: selector:src%d ! output_pad */ +static GstPad * +setup_output_pad (GstElement * element, GstStaticPadTemplate * tmpl) +{ + GstPad *srcpad = NULL, *output_pad = NULL; + gulong probe_id = 0; + + if (tmpl == NULL) + tmpl = &sinktemplate; + + /* create output_pad */ + output_pad = gst_pad_new_from_static_template (tmpl, "sink"); + fail_if (output_pad == NULL, "Could not create a output_pad"); + + /* add probe */ + probe_id = + gst_pad_add_probe (output_pad, GST_PAD_PROBE_TYPE_DATA_BOTH, + (GstPadProbeCallback) probe_cb, NULL, NULL); + g_object_set_data (G_OBJECT (output_pad), "probe_id", + GINT_TO_POINTER (probe_id)); + + /* request src pad */ + srcpad = gst_element_get_request_pad (element, "src_%u"); + fail_if (srcpad == NULL, "Could not get source pad from %s", + GST_ELEMENT_NAME (element)); + + /* link pads and activate */ + fail_unless (gst_pad_link (srcpad, output_pad) == GST_PAD_LINK_OK, + "Could not link %s source and output pad", GST_ELEMENT_NAME (element)); + + gst_pad_set_active (output_pad, TRUE); + + GST_DEBUG_OBJECT (output_pad, "set up %" GST_PTR_FORMAT " ! %" GST_PTR_FORMAT, + srcpad, output_pad); + + gst_object_unref (srcpad); + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); + + return output_pad; +} + +/* Clean up output/input pad and respective selector request pad */ +static void +cleanup_pad (GstPad * pad, GstElement * element) +{ + GstPad *selpad = NULL; + guint probe_id = 0; + + fail_if (pad == NULL, "pad doesn't exist"); + + /* remove probe if necessary */ + probe_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "probe_id")); + if (probe_id) + gst_pad_remove_probe (pad, probe_id); + + /* unlink */ + selpad = gst_pad_get_peer (pad); + if (GST_PAD_DIRECTION (selpad) == GST_PAD_SRC) { + gst_pad_unlink (selpad, pad); + } else { + gst_pad_unlink (pad, selpad); + } + + GST_DEBUG_OBJECT (pad, "clean up %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, + selpad, pad); + + /* cleanup the pad */ + gst_pad_set_active (pad, FALSE); + ASSERT_OBJECT_REFCOUNT (pad, "pad", 1); + gst_object_unref (pad); + + /* cleanup selector pad, reffed by this function (_get_peer) and creator */ + gst_element_release_request_pad (element, selpad); + gst_object_unref (selpad); +} + +/* Duplicate and push given buffer many times to all input_pads */ +static void +push_input_buffers (GList * input_pads, GstBuffer * buf, gint num_buffers) +{ + GstBuffer *buf_in = NULL; + GList *l = input_pads; + GstPad *input_pad; + gint i = 0; + + while (l != NULL) { + input_pad = l->data; + GST_DEBUG_OBJECT (input_pad, "pushing %d buffers to %" GST_PTR_FORMAT, + num_buffers, input_pad); + for (i = 0; i < num_buffers; i++) { + buf_in = gst_buffer_copy (buf); + fail_unless (gst_pad_push (input_pad, buf_in) == GST_FLOW_OK, + "pushing buffer failed"); + } + l = g_list_next (l); + } +} + +/* Check that received buffers count match to expected buffers */ +static void +count_output_buffers (GList * output_pads, gint expected_buffers) +{ + gint count = 0; + GList *l = output_pads; + GstPad *output_pad = NULL; + + while (l != NULL) { + output_pad = l->data; + count = + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (output_pad), + "buffer_count")); + GST_DEBUG_OBJECT (output_pad, "received %d buffers", count); + fail_unless (count == expected_buffers, + "received/expected buffer count doesn't match %d/%d", count, + expected_buffers); + count = + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (output_pad), + "event_count")); + GST_DEBUG_OBJECT (output_pad, "received %d events", count); + l = g_list_next (l); + } +} + +/* Set selector active pad */ +static void +selector_set_active_pad (GstElement * elem, GstPad * selpad) +{ + gchar *padname = NULL; + + if (selpad) { + padname = gst_pad_get_name (selpad); + } + + g_object_set (G_OBJECT (elem), "active-pad", selpad, NULL); + GST_DEBUG_OBJECT (elem, "activated selector pad: %s", GST_STR_NULL (padname)); + g_free (padname); +} + +static void +push_newsegment_events (GList * input_pads) +{ + GstSegment seg; + GList *l; + + seg.flags = GST_SEGMENT_FLAG_NONE; + seg.rate = seg.applied_rate = 1.0; + seg.format = GST_FORMAT_BYTES; + seg.base = 0; + seg.start = 0; + seg.stop = -1; + seg.time = 0; + seg.position = 0; + seg.duration = -1; + + for (l = input_pads; l; l = l->next) { + GstPad *pad = l->data; + + gst_pad_push_event (pad, gst_event_new_stream_start ("test")); + gst_pad_push_event (pad, gst_event_new_segment (&seg)); + } +} + +/* Push buffers and switch for each selector pad */ +static void +push_switched_buffers (GList * input_pads, + GstElement * elem, GList * peer_pads, gint num_buffers) +{ + GstBuffer *buf = NULL; + GList *l = peer_pads; + GstPad *selpad = NULL; + + /* setup dummy buffer */ + buf = gst_buffer_new_and_alloc (1); + + while (l != NULL) { + /* set selector pad */ + selpad = gst_pad_get_peer (GST_PAD (l->data)); + selector_set_active_pad (elem, selpad); + if (selpad) { + gst_object_unref (selpad); + } + /* push buffers */ + push_input_buffers (input_pads, buf, num_buffers); + /* switch to next selector pad */ + l = g_list_next (l); + } + + /* cleanup buffer */ + gst_buffer_unref (buf); +} + +/* Create output-selector with given number of src pads and switch + given number of input buffers to each src pad. + */ +static void +run_output_selector_buffer_count (gint num_output_pads, + gint num_buffers_per_output) +{ + /* setup input_pad ! selector ! output_pads */ + gint i = 0; + GList *output_pads = NULL, *input_pads = NULL; + GstElement *sel = gst_check_setup_element ("output-selector"); + GstPad *input_pad = gst_check_setup_src_pad (sel, &srctemplate); + + input_pads = g_list_append (input_pads, input_pad); + gst_pad_set_active (input_pad, TRUE); + for (i = 0; i < num_output_pads; i++) { + output_pads = g_list_append (output_pads, setup_output_pad (sel, NULL)); + } + + /* run the test */ + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + push_newsegment_events (input_pads); + push_switched_buffers (input_pads, sel, output_pads, num_buffers_per_output); + count_output_buffers (output_pads, num_buffers_per_output); + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* cleanup input_pad, selector and output_pads */ + gst_pad_set_active (input_pad, FALSE); + gst_check_teardown_src_pad (sel); + g_list_foreach (output_pads, (GFunc) cleanup_pad, sel); + g_list_free (output_pads); + g_list_free (input_pads); + gst_check_teardown_element (sel); +} + +/* Create and link input pad: input_pad ! selector:sink%d */ +static GstPad * +setup_input_pad (GstElement * element) +{ + GstPad *sinkpad = NULL, *input_pad = NULL; + + /* create input_pad */ + input_pad = gst_pad_new_from_static_template (&srctemplate, "src"); + fail_if (input_pad == NULL, "Could not create a input_pad"); + + /* request sink pad */ + sinkpad = gst_element_get_request_pad (element, "sink_%u"); + fail_if (sinkpad == NULL, "Could not get sink pad from %s", + GST_ELEMENT_NAME (element)); + + /* link pads and activate */ + fail_unless (gst_pad_link (input_pad, sinkpad) == GST_PAD_LINK_OK, + "Could not link input_pad and %s sink", GST_ELEMENT_NAME (element)); + + gst_pad_set_active (input_pad, TRUE); + + GST_DEBUG_OBJECT (input_pad, "set up %" GST_PTR_FORMAT " ! %" GST_PTR_FORMAT, + input_pad, sinkpad); + + gst_object_unref (sinkpad); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1); + + return input_pad; +} + +/* Create input-selector with given number of sink pads and switch + given number of input buffers to each sink pad. + */ +static void +run_input_selector_buffer_count (gint num_input_pads, + gint num_buffers_per_input) +{ + /* set up input_pads ! selector ! output_pad */ + gint i = 0, probe_id = 0; + GList *input_pads = NULL, *output_pads = NULL; + GstElement *sel = gst_check_setup_element ("input-selector"); + GstPad *output_pad = gst_check_setup_sink_pad (sel, &sinktemplate); + + output_pads = g_list_append (output_pads, output_pad); + gst_pad_set_active (output_pad, TRUE); + for (i = 0; i < num_input_pads; i++) { + input_pads = g_list_append (input_pads, setup_input_pad (sel)); + } + /* add probe */ + probe_id = + gst_pad_add_probe (output_pad, GST_PAD_PROBE_TYPE_DATA_BOTH, + (GstPadProbeCallback) probe_cb, NULL, NULL); + g_object_set_data (G_OBJECT (output_pad), "probe_id", + GINT_TO_POINTER (probe_id)); + + /* run the test */ + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + push_newsegment_events (input_pads); + push_switched_buffers (input_pads, sel, input_pads, num_buffers_per_input); + count_output_buffers (output_pads, (num_input_pads * num_buffers_per_input)); + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + /* clean up */ + gst_pad_remove_probe (output_pad, probe_id); + gst_pad_set_active (output_pad, FALSE); + gst_check_teardown_sink_pad (sel); + GST_DEBUG ("setting selector pad to NULL"); + selector_set_active_pad (sel, NULL); // unref input-selector active pad + g_list_foreach (input_pads, (GFunc) cleanup_pad, sel); + g_list_free (input_pads); + g_list_free (output_pads); + gst_check_teardown_element (sel); +} + +/* Push buffers to input pad and check the + amount of buffers arrived to output pads */ +GST_START_TEST (test_output_selector_buffer_count) +{ + gint i, j; + + for (i = 0; i < NUM_SELECTOR_PADS; i++) { + for (j = 0; j < NUM_INPUT_BUFFERS; j++) { + run_output_selector_buffer_count (i, j); + } + } +} + +GST_END_TEST; + +/* Push buffers to input pads and check the + amount of buffers arrived to output pad */ +GST_START_TEST (test_input_selector_buffer_count) +{ + gint i, j; + + for (i = 0; i < NUM_SELECTOR_PADS; i++) { + for (j = 0; j < NUM_INPUT_BUFFERS; j++) { + run_input_selector_buffer_count (i, j); + } + } +} + +GST_END_TEST; + +static GstElement *selector; +static GstPad *output_pad; +static GstPad *stream1_pad; +static GstPad *stream2_pad; + +static gboolean eos_received; +static gulong eos_probe; +static GMutex eos_probe_lock; +static GCond eos_probe_cond; + +enum InputSelectorResult +{ + INPUT_SELECTOR_FORWARD, + INPUT_SELECTOR_DROP +}; + +static GstPadProbeReturn +eos_pushed_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata) +{ + g_mutex_lock (&eos_probe_lock); + if (GST_EVENT_TYPE (info->data) == GST_EVENT_EOS) { + eos_received = TRUE; + g_cond_broadcast (&eos_probe_cond); + } + g_mutex_unlock (&eos_probe_lock); + + return GST_PAD_PROBE_OK; +} + +static void +setup_input_selector_with_2_streams (gint active_stream) +{ + eos_received = FALSE; + g_mutex_init (&eos_probe_lock); + g_cond_init (&eos_probe_cond); + + selector = gst_check_setup_element ("input-selector"); + output_pad = gst_check_setup_sink_pad (selector, &sinktemplate); + + gst_pad_set_active (output_pad, TRUE); + stream1_pad = setup_input_pad (selector); + stream2_pad = setup_input_pad (selector); + + if (active_stream == 1) { + g_object_set (selector, "active-pad", GST_PAD_PEER (stream1_pad), NULL); + } else { + g_object_set (selector, "active-pad", GST_PAD_PEER (stream2_pad), NULL); + } + + eos_probe = + gst_pad_add_probe (output_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + eos_pushed_probe, NULL, NULL); + + fail_unless (gst_element_set_state (selector, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + gst_check_setup_events_with_stream_id (stream1_pad, selector, NULL, + GST_FORMAT_TIME, "stream-1-id"); + gst_check_setup_events_with_stream_id (stream2_pad, selector, NULL, + GST_FORMAT_TIME, "stream-2-id"); +} + +static void +teardown_input_selector_with_2_streams (void) +{ + fail_unless (gst_element_set_state (selector, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_pad_remove_probe (output_pad, eos_probe); + + gst_pad_set_active (output_pad, FALSE); + gst_check_teardown_sink_pad (selector); + gst_check_teardown_element (selector); + gst_object_unref (stream1_pad); + gst_object_unref (stream2_pad); + + g_mutex_clear (&eos_probe_lock); + g_cond_clear (&eos_probe_cond); +} + +static void +input_selector_push_buffer (gint stream, enum InputSelectorResult res) +{ + GstBuffer *buf; + GstPad *pad = stream == 1 ? stream1_pad : stream2_pad; + + buf = gst_buffer_new (); + fail_unless (buffers == NULL); + fail_unless (gst_pad_push (pad, buf) == GST_FLOW_OK); + + if (res == INPUT_SELECTOR_DROP) { + fail_unless (buffers == NULL); + } else { + fail_unless (buffers != NULL); + fail_unless (buffers->data == buf); + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + } +} + +static gpointer +input_selector_do_push_eos (GstPad * pad) +{ + gst_pad_push_event (pad, gst_event_new_eos ()); + return NULL; +} + +static void +input_selector_check_eos (gint present) +{ + GstEvent *eos; + + eos = gst_pad_get_sticky_event (output_pad, GST_EVENT_EOS, 0); + if (present) { + fail_unless (eos != NULL); + gst_event_unref (eos); + } else { + fail_unless (eos == NULL); + } +} + +static void +input_selector_push_eos (gint stream, gboolean active) +{ + GstPad *pad = stream == 1 ? stream1_pad : stream2_pad; + + if (active) { + fail_unless (gst_pad_push_event (pad, gst_event_new_eos ())); + } else { + /* The non-active pads will block when receving eos, so we need to do it + * from a separate thread. This makes this test racy, but it should only + * cause false positives, not false negatives */ + GThread *t = g_thread_new ("selector-test-push-eos", + (GThreadFunc) input_selector_do_push_eos, pad); + + /* Sleep half a second to allow the other thread to execute, this is not + * a definitive solution but there is no way to know when the + * EOS has reached input-selector and blocked there, so this is just + * to reduce the possibility of this test being racy (false positives) + */ + g_usleep (0.5 * G_USEC_PER_SEC); + g_thread_unref (t); + } + + input_selector_check_eos (active); +} + +GST_START_TEST (test_input_selector_empty_stream) +{ + setup_input_selector_with_2_streams (2); + + /* stream1 is the empty stream, stream2 has data */ + + /* empty stream is just an EOS and it should not be forwarded */ + input_selector_push_eos (1, FALSE); + + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_eos (2, TRUE); + + teardown_input_selector_with_2_streams (); +} + +GST_END_TEST; + + +GST_START_TEST (test_input_selector_shorter_stream) +{ + setup_input_selector_with_2_streams (2); + + /* stream1 is shorter than stream2 */ + + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (1, INPUT_SELECTOR_DROP); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + + /* EOS from inactive stream should not go through */ + input_selector_push_eos (1, FALSE); + + /* buffers from active stream can still flow */ + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + + /* EOS from active stream should go through */ + input_selector_push_eos (2, TRUE); + + teardown_input_selector_with_2_streams (); +} + +GST_END_TEST; + + +GST_START_TEST (test_input_selector_switch_to_eos_stream) +{ + setup_input_selector_with_2_streams (2); + + /* stream1 receives eos before stream2 and then we switch to it */ + + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (1, INPUT_SELECTOR_DROP); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (1, INPUT_SELECTOR_DROP); + + /* EOS from inactive stream should not go through */ + input_selector_push_eos (1, FALSE); + + /* buffers from active stream can still flow */ + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + input_selector_push_buffer (2, INPUT_SELECTOR_FORWARD); + + /* now switch to stream1 */ + g_object_set (selector, "active-pad", GST_PAD_PEER (stream1_pad), NULL); + + /* wait for eos (it runs from a separate thread) */ + g_mutex_lock (&eos_probe_lock); + while (!eos_received) { + g_cond_wait (&eos_probe_cond, &eos_probe_lock); + } + g_mutex_unlock (&eos_probe_lock); + + teardown_input_selector_with_2_streams (); +} + +GST_END_TEST; + + +GST_START_TEST (test_output_selector_no_srcpad_negotiation) +{ + GstElement *sel; + GstCaps *caps; + GstPad *pad; + gint i; + + sel = gst_element_factory_make ("output-selector", NULL); + fail_unless (sel != NULL); + + pad = gst_element_get_static_pad (sel, "sink"); + fail_unless (pad != NULL); + + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (i = 0; i <= 2; i++) { + + /* regardless of pad-negotiation-mode, getcaps should return ANY and + * setcaps should accept any caps when there are no srcpads */ + g_object_set (sel, "pad-negotiation-mode", i, NULL); + + caps = gst_pad_query_caps (pad, NULL); + fail_unless (gst_caps_is_any (caps)); + + gst_caps_unref (caps); + + caps = gst_caps_new_empty_simple ("mymedia/mycaps"); + fail_unless (gst_pad_set_caps (pad, caps)); + gst_caps_unref (caps); + } + + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + gst_object_unref (pad); + gst_object_unref (sel); +} + +GST_END_TEST; + + +GstElement *sel; +GstPad *input_pad; +GList *output_pads = NULL; /* list of sinkpads linked to output-selector */ +#define OUTPUT_SELECTOR_NUM_PADS 2 + +static GstStaticPadTemplate sinktmpl_nego_a = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("format/abc; format/xyz")); +static GstStaticPadTemplate sinktmpl_nego_b = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("format/abc")); + +static void +setup_output_selector (void) +{ + sel = gst_check_setup_element ("output-selector"); + input_pad = gst_check_setup_src_pad (sel, &srctemplate); + gst_pad_set_active (input_pad, TRUE); + + output_pads = g_list_append (output_pads, setup_output_pad (sel, + &sinktmpl_nego_a)); + output_pads = g_list_append (output_pads, setup_output_pad (sel, + &sinktmpl_nego_b)); +} + +static void +teardown_output_selector (void) +{ + gst_pad_set_active (input_pad, FALSE); + gst_object_unref (input_pad); + gst_check_teardown_src_pad (sel); + g_list_foreach (output_pads, (GFunc) cleanup_pad, sel); + g_list_free (output_pads); + gst_check_teardown_element (sel); + output_pads = NULL; +} + +GST_START_TEST (test_output_selector_getcaps_none) +{ + GList *walker; + + /* set pad negotiation mode to none */ + g_object_set (sel, "pad-negotiation-mode", 0, NULL); + + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (walker = output_pads; walker; walker = g_list_next (walker)) { + GstCaps *caps; + GstPad *pad; + + pad = gst_pad_get_peer ((GstPad *) walker->data); + + g_object_set (sel, "active-pad", pad, NULL); + + caps = gst_pad_peer_query_caps (input_pad, NULL); + + /* in 'none' mode, the getcaps returns the template, which is ANY */ + g_assert (gst_caps_is_any (caps)); + gst_caps_unref (caps); + gst_object_unref (pad); + } + + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + +} + +GST_END_TEST; + + +GST_START_TEST (test_output_selector_getcaps_all) +{ + GList *walker; + GstCaps *expected; + + /* set pad negotiation mode to 'all' */ + g_object_set (sel, "pad-negotiation-mode", 1, NULL); + + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + /* in 'all' mode, the intersection of the srcpad caps should be returned on + * the sinkpad's getcaps */ + expected = gst_caps_new_empty_simple ("format/abc"); + + for (walker = output_pads; walker; walker = g_list_next (walker)) { + GstCaps *caps; + GstPad *pad; + + pad = gst_pad_get_peer ((GstPad *) walker->data); + + g_object_set (sel, "active-pad", pad, NULL); + + caps = gst_pad_peer_query_caps (input_pad, NULL); + + g_assert (gst_caps_is_equal (caps, expected)); + gst_caps_unref (caps); + gst_object_unref (pad); + } + gst_caps_unref (expected); + + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + +} + +GST_END_TEST; + + +GST_START_TEST (test_output_selector_getcaps_active) +{ + GList *walker; + GstCaps *expected; + + /* set pad negotiation mode to 'active' */ + g_object_set (sel, "pad-negotiation-mode", 2, NULL); + + fail_unless (gst_element_set_state (sel, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (walker = output_pads; walker; walker = g_list_next (walker)) { + GstCaps *caps; + GstPad *pad; + GstPadTemplate *templ; + + pad = gst_pad_get_peer ((GstPad *) walker->data); + + g_object_set (sel, "active-pad", pad, NULL); + + /* in 'active' mode, the active srcpad peer's caps should be returned on + * the sinkpad's getcaps */ + + templ = gst_pad_get_pad_template ((GstPad *) walker->data); + expected = gst_pad_template_get_caps (templ); + caps = gst_pad_peer_query_caps (input_pad, NULL); + + g_assert (gst_caps_is_equal (caps, expected)); + gst_caps_unref (caps); + gst_caps_unref (expected); + gst_object_unref (templ); + gst_object_unref (pad); + } + + fail_unless (gst_element_set_state (sel, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + +} + +GST_END_TEST; + + +static Suite * +selector_suite (void) +{ + Suite *s = suite_create ("selector"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_output_selector_buffer_count); + tcase_add_test (tc_chain, test_input_selector_buffer_count); + tcase_add_test (tc_chain, test_input_selector_empty_stream); + tcase_add_test (tc_chain, test_input_selector_shorter_stream); + tcase_add_test (tc_chain, test_input_selector_switch_to_eos_stream); + tcase_add_test (tc_chain, test_output_selector_no_srcpad_negotiation); + + tc_chain = tcase_create ("output-selector-negotiation"); + tcase_add_checked_fixture (tc_chain, setup_output_selector, + teardown_output_selector); + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_output_selector_getcaps_none); + tcase_add_test (tc_chain, test_output_selector_getcaps_all); + tcase_add_test (tc_chain, test_output_selector_getcaps_active); + + return s; +} + +GST_CHECK_MAIN (selector); diff --git a/tests/check/elements/streamiddemux.c b/tests/check/elements/streamiddemux.c new file mode 100644 index 0000000..25bb969 --- /dev/null +++ b/tests/check/elements/streamiddemux.c @@ -0,0 +1,517 @@ +/* GStreamer unit tests for the streamiddemux + * + * Copyright 2013 LGE Corporation. + * @author: Hoonhee Lee + * @author: Jeongseok Kim + * @author: Wonchul Lee + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#define NUM_SUBSTREAMS 100 +#define NUM_BUFFER 1000 + +static GstPad *active_srcpad; + +struct TestData +{ + GstElement *demux; + GstPad *mysrc, *mysink[NUM_SUBSTREAMS]; + GstPad *demuxsink, *demuxsrc[NUM_SUBSTREAMS]; + gint srcpad_cnt; + GstCaps *mycaps; + GstCaps *caps[NUM_SUBSTREAMS]; + GstSegment segment[NUM_SUBSTREAMS]; + gchar *stream_ids[NUM_SUBSTREAMS]; +}; + +static void +set_active_srcpad (struct TestData *td) +{ + if (active_srcpad) + gst_object_unref (active_srcpad); + + g_object_get (td->demux, "active-pad", &active_srcpad, NULL); +} + +static void +release_test_objects (struct TestData *td) +{ + fail_unless (gst_element_set_state (td->demux, GST_STATE_NULL) == + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (td->demuxsink); + + gst_caps_unref (td->mycaps); + + if (active_srcpad) { + gst_object_unref (active_srcpad); + active_srcpad = NULL; + } + gst_object_unref (td->demux); +} + +static void +src_pad_added_cb (GstElement * demux, GstPad * pad, struct TestData *td) +{ + if (td->srcpad_cnt < NUM_SUBSTREAMS) { + td->demuxsrc[td->srcpad_cnt] = pad; + fail_unless (gst_pad_link (pad, + td->mysink[td->srcpad_cnt++]) == GST_PAD_LINK_OK); + } +} + +static void +setup_test_objects (struct TestData *td) +{ + td->mycaps = gst_caps_new_empty_simple ("test/test"); + td->srcpad_cnt = 0; + + td->demux = gst_element_factory_make ("streamiddemux", NULL); + fail_unless (td->demux != NULL); + g_signal_connect (td->demux, "pad-added", G_CALLBACK (src_pad_added_cb), td); + td->demuxsink = gst_element_get_static_pad (td->demux, "sink"); + fail_unless (td->demuxsink != NULL); + + fail_unless (gst_element_set_state (td->demux, GST_STATE_PLAYING) == + GST_STATE_CHANGE_SUCCESS); +} + +static GstFlowReturn +chain_ok (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstPad *peer_pad = NULL; + gchar *pad_stream_id, *active_srcpad_stream_id; + + peer_pad = gst_pad_get_peer (active_srcpad); + pad_stream_id = gst_pad_get_stream_id (pad); + active_srcpad_stream_id = gst_pad_get_stream_id (active_srcpad); + fail_unless (pad == peer_pad); + fail_unless (g_strcmp0 (pad_stream_id, active_srcpad_stream_id) == 0); + + g_free (pad_stream_id); + g_free (active_srcpad_stream_id); + gst_object_unref (peer_pad); + gst_buffer_unref (buffer); + + return GST_FLOW_OK; +} + +GST_START_TEST (test_simple_create_destroy) +{ + GstElement *demux; + + demux = gst_element_factory_make ("streamiddemux", NULL); + gst_object_unref (demux); +} + +GST_END_TEST; + +GST_START_TEST (test_streamiddemux_with_stream_start) +{ + struct TestData td; + + setup_test_objects (&td); + + GST_DEBUG ("Creating mysink"); + td.mysink[0] = gst_pad_new ("mysink0", GST_PAD_SINK); + gst_pad_set_active (td.mysink[0], TRUE); + + GST_DEBUG ("Creating mysrc"); + td.mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc, td.demuxsink))); + gst_pad_set_active (td.mysrc, TRUE); + + GST_DEBUG ("Pushing stream-start event"); + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_stream_start ("test0"))); + + g_object_get (td.demux, "active-pad", &active_srcpad, NULL); + fail_unless (active_srcpad != NULL, "Failed to generate a srcpad"); + fail_unless (td.srcpad_cnt == 1, "pad-added signal has not emmited"); + + GST_DEBUG ("Releasing mysink and mysrc"); + gst_pad_set_active (td.mysink[0], FALSE); + gst_pad_set_active (td.mysrc, FALSE); + + gst_object_unref (td.mysink[0]); + gst_object_unref (td.mysrc); + + GST_DEBUG ("Releasing streamiddemux"); + release_test_objects (&td); +} + +GST_END_TEST; + +GST_START_TEST (test_streamiddemux_without_stream_start) +{ + struct TestData td; + GstSegment segment; + + setup_test_objects (&td); + + GST_DEBUG ("Creating mysink"); + td.mysink[0] = gst_pad_new ("mysink0", GST_PAD_SINK); + gst_pad_set_active (td.mysink[0], TRUE); + + GST_DEBUG ("Creating mysrc"); + td.mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc, td.demuxsink))); + gst_pad_set_active (td.mysrc, TRUE); + + GST_DEBUG ("Pushing caps and segment event without stream-start"); + fail_unless (gst_pad_push_event (td.mysrc, gst_event_new_caps (td.mycaps))); + gst_segment_init (&segment, GST_FORMAT_BYTES); + fail_unless (gst_pad_push_event (td.mysrc, gst_event_new_segment (&segment))); + + g_object_get (td.demux, "active-pad", &active_srcpad, NULL); + fail_unless (active_srcpad == NULL, "srcpad has created unexpectedly"); + fail_unless (td.srcpad_cnt == 0, "pad-added signal is emmited unexpectedly"); + + GST_DEBUG ("Releasing mysink and mysrc"); + gst_pad_set_active (td.mysink[0], FALSE); + gst_pad_set_active (td.mysrc, FALSE); + + gst_object_unref (td.mysink[0]); + gst_object_unref (td.mysrc); + + GST_DEBUG ("Releasing streamiddemux"); + release_test_objects (&td); +} + +GST_END_TEST; + +GST_START_TEST (test_streamiddemux_simple) +{ + struct TestData td; + + setup_test_objects (&td); + + GST_DEBUG ("Creating mysink"); + td.mysink[0] = gst_pad_new ("mysink0", GST_PAD_SINK); + td.mysink[0]->chaindata = &td; + gst_pad_set_chain_function (td.mysink[0], chain_ok); + gst_pad_set_active (td.mysink[0], TRUE); + + td.mysink[1] = gst_pad_new ("mysink1", GST_PAD_SINK); + td.mysink[1]->chaindata = &td; + gst_pad_set_chain_function (td.mysink[1], chain_ok); + gst_pad_set_active (td.mysink[1], TRUE); + + GST_DEBUG ("Creating mysrc"); + td.mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc, td.demuxsink))); + gst_pad_set_active (td.mysrc, TRUE); + + GST_DEBUG ("Pushing stream-start, caps and segment event"); + gst_check_setup_events_with_stream_id (td.mysrc, td.demux, td.mycaps, + GST_FORMAT_BYTES, "test0"); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + gst_check_setup_events_with_stream_id (td.mysrc, td.demux, td.mycaps, + GST_FORMAT_BYTES, "test1"); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + GST_DEBUG ("Pushing buffer"); + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_stream_start ("test0"))); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_stream_start ("test1"))); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + GST_DEBUG ("Releasing mysink and mysrc"); + gst_pad_set_active (td.mysink[0], FALSE); + gst_pad_set_active (td.mysink[1], FALSE); + gst_pad_set_active (td.mysrc, FALSE); + + gst_object_unref (td.mysink[0]); + gst_object_unref (td.mysink[1]); + gst_object_unref (td.mysrc); + + GST_DEBUG ("Releasing streamiddemux"); + release_test_objects (&td); +} + +GST_END_TEST; + +GList *expected[NUM_SUBSTREAMS]; + +static gboolean +sink_event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GList **expected = GST_PAD_ELEMENT_PRIVATE (pad), *l; + GstEvent *exp; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS:{ + GstCaps *recvcaps, *expectcaps; + + l = g_list_first (*expected); + exp = GST_EVENT (l->data); + + gst_event_parse_caps (event, &recvcaps); + gst_event_parse_caps (exp, &expectcaps); + + fail_unless (gst_caps_is_equal (recvcaps, expectcaps)); + break; + } + case GST_EVENT_SEGMENT:{ + const GstSegment *recvseg, *expectseg; + + l = g_list_last (*expected); + exp = GST_EVENT (l->data); + + gst_event_parse_segment (event, &recvseg); + gst_event_parse_segment (exp, &expectseg); + + fail_unless_equals_uint64 (recvseg->position, expectseg->position); + break; + } + default: + break; + } + + return gst_pad_event_default (pad, parent, event); +} + +GST_START_TEST (test_streamiddemux_num_buffers) +{ + struct TestData td; + gint buffer_cnt = 0; + gint stream_cnt = 0; + GstEvent *event; + + setup_test_objects (&td); + + GST_DEBUG ("Creating mysink"); + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gchar *name; + name = g_strdup_printf ("mysink%d", stream_cnt); + td.mysink[stream_cnt] = gst_pad_new (name, GST_PAD_SINK); + g_free (name); + gst_pad_set_chain_function (td.mysink[stream_cnt], chain_ok); + gst_pad_set_event_function (td.mysink[stream_cnt], sink_event_func); + gst_pad_set_active (td.mysink[stream_cnt], TRUE); + GST_PAD_ELEMENT_PRIVATE (td.mysink[stream_cnt]) = &expected[stream_cnt]; + } + + GST_DEBUG ("Creating mysrc"); + td.mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc, td.demuxsink))); + gst_pad_set_active (td.mysrc, TRUE); + + GST_DEBUG ("Creating caps"); + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gchar *caps_name; + caps_name = g_strdup_printf ("test/test%d", stream_cnt); + td.caps[stream_cnt] = gst_caps_new_empty_simple (caps_name); + + g_free (caps_name); + } + + GST_DEBUG ("Creating segment"); + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gst_segment_init (&td.segment[stream_cnt], GST_FORMAT_BYTES); + td.segment[stream_cnt].position = stream_cnt * GST_SECOND; + } + + GST_DEBUG ("Pushing stream-start, caps and segment event"); + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gchar *name; + name = g_strdup_printf ("test%d", stream_cnt); + + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_stream_start (name))); + + event = gst_event_new_caps (td.caps[stream_cnt]); + expected[stream_cnt] = + g_list_append (expected[stream_cnt], gst_event_ref (event)); + fail_unless (gst_pad_push_event (td.mysrc, event)); + + event = gst_event_new_segment (&td.segment[stream_cnt]); + expected[stream_cnt] = + g_list_append (expected[stream_cnt], gst_event_ref (event)); + fail_unless (gst_pad_push_event (td.mysrc, event)); + + g_free (name); + set_active_srcpad (&td); + + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + } + + GST_DEBUG ("Pushing buffers to random srcpad"); + for (buffer_cnt = 0; buffer_cnt < NUM_BUFFER; ++buffer_cnt) { + gchar *name; + gint active_stream = rand () % NUM_SUBSTREAMS; + name = g_strdup_printf ("test%d", active_stream); + + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_stream_start (name))); + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_caps (td.caps[active_stream]))); + fail_unless (gst_pad_push_event (td.mysrc, + gst_event_new_segment (&td.segment[active_stream]))); + + g_free (name); + set_active_srcpad (&td); + + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + } + + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) + gst_caps_unref (td.caps[stream_cnt]); + + GST_DEBUG ("Releasing mysink and mysrc"); + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gst_pad_set_active (td.mysink[stream_cnt], FALSE); + } + gst_pad_set_active (td.mysrc, FALSE); + + for (stream_cnt = 0; stream_cnt < NUM_SUBSTREAMS; ++stream_cnt) { + gst_object_unref (td.mysink[stream_cnt]); + + g_list_free_full (expected[stream_cnt], (GDestroyNotify) gst_event_unref); + } + gst_object_unref (td.mysrc); + + GST_DEBUG ("Releasing streamiddemux"); + release_test_objects (&td); +} + +GST_END_TEST; + +guint num_eos = 0; +guint num_flush_start = 0; +guint num_flush_stop = 0; + +static gboolean +event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_STREAM_START: + ++num_flush_start; + break; + case GST_EVENT_FLUSH_STOP: + ++num_flush_stop; + break; + case GST_EVENT_EOS: + ++num_eos; + break; + default: + break; + } + + return gst_pad_event_default (pad, parent, event); +} + +GST_START_TEST (test_streamiddemux_eos) +{ + struct TestData td; + + setup_test_objects (&td); + + num_eos = 0; + + GST_DEBUG ("Creating mysink"); + td.mysink[0] = gst_pad_new ("mysink0", GST_PAD_SINK); + gst_pad_set_chain_function (td.mysink[0], chain_ok); + gst_pad_set_event_function (td.mysink[0], event_func); + gst_pad_set_active (td.mysink[0], TRUE); + + td.mysink[1] = gst_pad_new ("mysink1", GST_PAD_SINK); + gst_pad_set_chain_function (td.mysink[1], chain_ok); + gst_pad_set_event_function (td.mysink[1], event_func); + gst_pad_set_active (td.mysink[1], TRUE); + + GST_DEBUG ("Creating mysrc"); + td.mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td.mysrc, td.demuxsink))); + gst_pad_set_active (td.mysrc, TRUE); + + GST_DEBUG ("Pushing stream-start, caps and segment event"); + gst_check_setup_events_with_stream_id (td.mysrc, td.demux, td.mycaps, + GST_FORMAT_BYTES, "test0"); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + gst_check_setup_events_with_stream_id (td.mysrc, td.demux, td.mycaps, + GST_FORMAT_BYTES, "test1"); + set_active_srcpad (&td); + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_OK); + + GST_DEBUG ("Pushing flush event"); + fail_unless (gst_pad_push_event (td.mysrc, gst_event_new_flush_start ())); + fail_unless (num_flush_start == 2, + "Failed to send flush-start event to all pads internally linked"); + fail_unless (gst_pad_push_event (td.mysrc, gst_event_new_flush_stop (TRUE))); + fail_unless (num_flush_stop == 2, + "Failed to send flush-stop event to all pads internally linked"); + + GST_DEBUG ("Pushing eos event"); + fail_unless (gst_pad_push_event (td.mysrc, gst_event_new_eos ())); + fail_unless (num_eos == 2, + "Failed to send eos event to all pads internally linked"); + + fail_unless (gst_pad_push (td.mysrc, gst_buffer_new ()) == GST_FLOW_EOS); + + GST_DEBUG ("Releasing mysink and mysrc"); + gst_pad_set_active (td.mysink[0], FALSE); + gst_pad_set_active (td.mysink[1], FALSE); + gst_pad_set_active (td.mysrc, FALSE); + + gst_object_unref (td.mysink[0]); + gst_object_unref (td.mysink[1]); + gst_object_unref (td.mysrc); + + GST_DEBUG ("Releasing streamiddemux"); + release_test_objects (&td); +} + +GST_END_TEST; + +static Suite * +streamiddemux_suite (void) +{ + Suite *s = suite_create ("streamiddemux"); + TCase *tc_chain; + + tc_chain = tcase_create ("streamiddemux simple"); + tcase_add_test (tc_chain, test_simple_create_destroy); + tcase_add_test (tc_chain, test_streamiddemux_with_stream_start); + tcase_add_test (tc_chain, test_streamiddemux_without_stream_start); + tcase_add_test (tc_chain, test_streamiddemux_simple); + tcase_add_test (tc_chain, test_streamiddemux_num_buffers); + tcase_add_test (tc_chain, test_streamiddemux_eos); + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (streamiddemux); diff --git a/tests/check/elements/tee.c b/tests/check/elements/tee.c new file mode 100644 index 0000000..acee40c --- /dev/null +++ b/tests/check/elements/tee.c @@ -0,0 +1,969 @@ +/* GStreamer + * + * unit test for tee + * + * Copyright (C) <2007> Wim Taymans + * Copyright (C) <2008> Ole André Vadla Ravnås + * Copyright (C) <2008> Christian Berentsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static void +handoff (GstElement * fakesink, GstBuffer * buf, GstPad * pad, guint * count) +{ + *count = *count + 1; +} + +/* construct fakesrc num-buffers=3 ! tee name=t ! queue ! fakesink t. ! queue ! + * fakesink. Each fakesink should exactly receive 3 buffers. + */ +GST_START_TEST (test_num_buffers) +{ +#define NUM_SUBSTREAMS 15 +#define NUM_BUFFERS 3 + GstElement *pipeline, *src, *tee; + GstElement *queues[NUM_SUBSTREAMS]; + GstElement *sinks[NUM_SUBSTREAMS]; + GstPad *req_pads[NUM_SUBSTREAMS]; + guint counts[NUM_SUBSTREAMS]; + GstBus *bus; + GstMessage *msg; + gint i; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("fakesrc"); + g_object_set (src, "num-buffers", NUM_BUFFERS, NULL); + tee = gst_check_setup_element ("tee"); + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), tee)); + fail_unless (gst_element_link (src, tee)); + + for (i = 0; i < NUM_SUBSTREAMS; ++i) { + GstPad *qpad; + gchar name[32]; + + counts[i] = 0; + + queues[i] = gst_check_setup_element ("queue"); + g_snprintf (name, 32, "queue%d", i); + gst_object_set_name (GST_OBJECT (queues[i]), name); + fail_unless (gst_bin_add (GST_BIN (pipeline), queues[i])); + + sinks[i] = gst_check_setup_element ("fakesink"); + g_snprintf (name, 32, "sink%d", i); + gst_object_set_name (GST_OBJECT (sinks[i]), name); + fail_unless (gst_bin_add (GST_BIN (pipeline), sinks[i])); + fail_unless (gst_element_link (queues[i], sinks[i])); + g_object_set (sinks[i], "signal-handoffs", TRUE, NULL); + g_signal_connect (sinks[i], "handoff", (GCallback) handoff, &counts[i]); + + req_pads[i] = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (req_pads[i] != NULL); + + qpad = gst_element_get_static_pad (queues[i], "sink"); + fail_unless_equals_int (gst_pad_link (req_pads[i], qpad), GST_PAD_LINK_OK); + gst_object_unref (qpad); + } + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + for (i = 0; i < NUM_SUBSTREAMS; ++i) { + fail_unless_equals_int (counts[i], NUM_BUFFERS); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + + for (i = 0; i < NUM_SUBSTREAMS; ++i) { + gst_element_release_request_pad (tee, req_pads[i]); + gst_object_unref (req_pads[i]); + } + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* we use fakesrc ! tee ! fakesink and then randomly request/release and link + * some pads from tee. This should happily run without any errors. */ +GST_START_TEST (test_stress) +{ + GstElement *pipeline; + GstElement *tee; + const gchar *desc; + GstBus *bus; + GstMessage *msg; + gint i; + + /* Pump 1000 buffers (10 bytes each) per second through tee for 5 secs */ + desc = "fakesrc datarate=10000 sizemin=10 sizemax=10 num-buffers=5000 ! " + "video/x-raw,framerate=25/1 ! tee name=t ! " + "queue max-size-buffers=2 ! fakesink sync=true"; + + pipeline = gst_parse_launch (desc, NULL); + fail_if (pipeline == NULL); + + tee = gst_bin_get_by_name (GST_BIN (pipeline), "t"); + fail_if (tee == NULL); + + /* bring the pipeline to PLAYING, then start switching */ + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + /* Wait for the pipeline to hit playing so that parse_launch can do the + * initial link, otherwise we perform linking from multiple threads and cause + * trouble */ + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + for (i = 0; i < 50000; i++) { + GstPad *pad; + + pad = gst_element_get_request_pad (tee, "src_%u"); + gst_element_release_request_pad (tee, pad); + gst_object_unref (pad); + + if ((msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, 0))) + break; + } + + /* now wait for completion or error */ + if (msg == NULL) + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (tee); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +typedef struct +{ + GstElement *tee; + GstCaps *caps; + GstPad *start_srcpad; + GstPad *tee_sinkpad; + GstPad *tee_srcpad; + GstPad *final_sinkpad; + GThread *app_thread; + gint countdown; + gboolean app_thread_prepped; + gboolean bufferalloc_blocked; +} BufferAllocHarness; + +static void +buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown) +{ + h->app_thread = NULL; + + h->tee = gst_check_setup_element ("tee"); + fail_if (h->tee == NULL); + + h->countdown = countdown; + + fail_unless_equals_int (gst_element_set_state (h->tee, GST_STATE_PLAYING), + TRUE); + + h->caps = gst_caps_new_empty_simple ("video/x-raw"); + + h->start_srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_if (h->start_srcpad == NULL); + fail_unless (gst_pad_set_active (h->start_srcpad, TRUE) == TRUE); + fail_unless (gst_pad_set_caps (h->start_srcpad, h->caps) == TRUE); + + h->tee_sinkpad = gst_element_get_static_pad (h->tee, "sink"); + fail_if (h->tee_sinkpad == NULL); + + h->tee_srcpad = gst_element_get_request_pad (h->tee, "src_%u"); + fail_if (h->tee_srcpad == NULL); + + h->final_sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (h->final_sinkpad == NULL); + fail_unless (gst_pad_set_active (h->final_sinkpad, TRUE) == TRUE); + fail_unless (gst_pad_set_caps (h->final_sinkpad, h->caps) == TRUE); + g_object_set_qdata (G_OBJECT (h->final_sinkpad), + g_quark_from_static_string ("buffer-alloc-harness"), h); + + fail_unless_equals_int (gst_pad_link (h->start_srcpad, h->tee_sinkpad), + GST_PAD_LINK_OK); + fail_unless_equals_int (gst_pad_link (h->tee_srcpad, h->final_sinkpad), + GST_PAD_LINK_OK); +} + +static void +buffer_alloc_harness_teardown (BufferAllocHarness * h) +{ + if (h->app_thread) + g_thread_join (h->app_thread); + + gst_pad_set_active (h->final_sinkpad, FALSE); + gst_object_unref (h->final_sinkpad); + gst_object_unref (h->tee_srcpad); + gst_object_unref (h->tee_sinkpad); + gst_pad_set_active (h->start_srcpad, FALSE); + gst_object_unref (h->start_srcpad); + gst_caps_unref (h->caps); + gst_check_teardown_element (h->tee); +} + +#if 0 +static gpointer +app_thread_func (gpointer data) +{ + BufferAllocHarness *h = data; + + /* Signal that we are about to call release_request_pad(). */ + g_mutex_lock (&check_mutex); + h->app_thread_prepped = TRUE; + g_cond_signal (&check_cond); + g_mutex_unlock (&check_mutex); + + /* Simulate that the app releases the pad while the streaming thread is in + * buffer_alloc below. */ + gst_element_release_request_pad (h->tee, h->tee_srcpad); + + /* Signal the bufferalloc function below if it's still waiting. */ + g_mutex_lock (&check_mutex); + h->bufferalloc_blocked = FALSE; + g_cond_signal (&check_cond); + g_mutex_unlock (&check_mutex); + + return NULL; +} +#endif + +#if 0 +static GstFlowReturn +final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buf) +{ + BufferAllocHarness *h; + GTimeVal deadline; + + h = g_object_get_qdata (G_OBJECT (pad), + g_quark_from_static_string ("buffer-alloc-harness")); + g_assert (h != NULL); + + if (--(h->countdown) == 0) { + /* Time to make the app release the pad. */ + h->app_thread_prepped = FALSE; + h->bufferalloc_blocked = TRUE; + + h->app_thread = g_thread_try_new ("gst-check", app_thread_func, h, NULL); + fail_if (h->app_thread == NULL); + + /* Wait for the app thread to get ready to call release_request_pad(). */ + g_mutex_lock (&check_mutex); + while (!h->app_thread_prepped) + g_cond_wait (&check_cond, &check_mutex); + g_mutex_unlock (&check_mutex); + + /* Now wait for it to do that within a second, to avoid deadlocking + * in the event of future changes to the locking semantics. */ + g_mutex_lock (&check_mutex); + g_get_current_time (&deadline); + deadline.tv_sec += 1; + while (h->bufferalloc_blocked) { + if (!g_cond_timed_wait (&check_cond, &check_mutex, &deadline)) + break; + } + g_mutex_unlock (&check_mutex); + } + + *buf = gst_buffer_new_and_alloc (size); + gst_buffer_set_caps (*buf, caps); + + return GST_FLOW_OK; +} +#endif + +/* Simulate an app releasing the pad while the first alloc_buffer() is in + * progress. */ +GST_START_TEST (test_release_while_buffer_alloc) +{ + BufferAllocHarness h; + + buffer_alloc_harness_setup (&h, 1); + + buffer_alloc_harness_teardown (&h); +} + +GST_END_TEST; + +/* Simulate an app releasing the pad while the second alloc_buffer() is in + * progress. */ +GST_START_TEST (test_release_while_second_buffer_alloc) +{ + BufferAllocHarness h; + + buffer_alloc_harness_setup (&h, 2); + + buffer_alloc_harness_teardown (&h); +} + +GST_END_TEST; + +/* Check the internal pads of tee */ +GST_START_TEST (test_internal_links) +{ + GstElement *tee; + GstPad *sinkpad, *srcpad1, *srcpad2; + GstIterator *it; + GstIteratorResult res; + GValue val1 = { 0, } + , val2 = { + 0,}; + + tee = gst_check_setup_element ("tee"); + + sinkpad = gst_element_get_static_pad (tee, "sink"); + fail_unless (sinkpad != NULL); + it = gst_pad_iterate_internal_links (sinkpad); + fail_unless (it != NULL); + + /* iterator should not return anything */ + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_DONE); + fail_unless (g_value_get_object (&val1) == NULL); + + srcpad1 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (srcpad1 != NULL); + + /* iterator should resync */ + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_RESYNC); + fail_unless (g_value_get_object (&val1) == NULL); + gst_iterator_resync (it); + + /* we should get something now */ + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == srcpad1); + + g_value_reset (&val1); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_DONE); + fail_unless (g_value_get_object (&val1) == NULL); + + srcpad2 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (srcpad2 != NULL); + + /* iterator should resync */ + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_RESYNC); + fail_unless (g_value_get_object (&val1) == NULL); + gst_iterator_resync (it); + + /* we should get one of the 2 pads now */ + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == srcpad1 + || GST_PAD_CAST (g_value_get_object (&val1)) == srcpad2); + + /* and the other */ + res = gst_iterator_next (it, &val2); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GST_PAD_CAST (g_value_get_object (&val2)) == srcpad1 + || GST_PAD_CAST (g_value_get_object (&val2)) == srcpad2); + fail_unless (g_value_get_object (&val1) != g_value_get_object (&val2)); + g_value_reset (&val1); + g_value_reset (&val2); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_DONE); + fail_unless (g_value_get_object (&val1) == NULL); + + gst_iterator_free (it); + + /* get an iterator for the other direction */ + it = gst_pad_iterate_internal_links (srcpad1); + fail_unless (it != NULL); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == sinkpad); + g_value_reset (&val1); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_DONE); + gst_iterator_free (it); + + it = gst_pad_iterate_internal_links (srcpad2); + fail_unless (it != NULL); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == sinkpad); + g_value_reset (&val1); + + res = gst_iterator_next (it, &val1); + fail_unless (res == GST_ITERATOR_DONE); + + g_value_unset (&val1); + g_value_unset (&val2); + gst_iterator_free (it); + gst_object_unref (srcpad1); + gst_object_unref (srcpad2); + gst_object_unref (sinkpad); + gst_object_unref (tee); +} + +GST_END_TEST; + +static GstFlowReturn +_fake_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +static GstFlowReturn +_fake_chain_error (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; +} + +GST_START_TEST (test_flow_aggregation) +{ + GstPad *mysrc, *mysink1, *mysink2; + GstPad *teesink, *teesrc1, *teesrc2; + GstElement *tee; + GstBuffer *buffer; + GstSegment segment; + GstCaps *caps; + + caps = gst_caps_new_empty_simple ("test/test"); + + tee = gst_element_factory_make ("tee", NULL); + fail_unless (tee != NULL); + teesink = gst_element_get_static_pad (tee, "sink"); + fail_unless (teesink != NULL); + teesrc1 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (teesrc1 != NULL); + teesrc2 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (teesrc2 != NULL); + + GST_DEBUG ("Creating mysink1"); + mysink1 = gst_pad_new ("mysink1", GST_PAD_SINK); + gst_pad_set_chain_function (mysink1, _fake_chain); + gst_pad_set_active (mysink1, TRUE); + + GST_DEBUG ("Creating mysink2"); + mysink2 = gst_pad_new ("mysink2", GST_PAD_SINK); + gst_pad_set_chain_function (mysink2, _fake_chain); + gst_pad_set_active (mysink2, TRUE); + + GST_DEBUG ("Creating mysrc"); + mysrc = gst_pad_new ("mysrc", GST_PAD_SRC); + gst_pad_set_active (mysrc, TRUE); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mysrc, gst_event_new_stream_start ("test")); + gst_pad_set_caps (mysrc, caps); + gst_pad_push_event (mysrc, gst_event_new_segment (&segment)); + + fail_unless (gst_pad_link (mysrc, teesink) == GST_PAD_LINK_OK); + fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK); + fail_unless (gst_pad_link (teesrc2, mysink2) == GST_PAD_LINK_OK); + + fail_unless (gst_element_set_state (tee, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new (); +#if 0 + gst_buffer_set_caps (buffer, caps); +#endif + + GST_DEBUG ("Try to push a buffer"); + /* First check if everything works in normal state */ + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + /* One pad being in wrong state must result in wrong state */ + GST_DEBUG ("Trying to push with mysink2 disabled"); + gst_pad_set_active (mysink2, FALSE); + fail_unless (gst_pad_push (mysrc, + gst_buffer_ref (buffer)) == GST_FLOW_FLUSHING); + + GST_DEBUG ("Trying to push with mysink2 disabled"); + gst_pad_set_active (mysink1, FALSE); + gst_pad_set_active (mysink2, TRUE); + fail_unless (gst_pad_push (mysrc, + gst_buffer_ref (buffer)) == GST_FLOW_FLUSHING); + + GST_DEBUG ("Trying to push with mysink2 and mysink1 disabled"); + gst_pad_set_active (mysink2, FALSE); + fail_unless (gst_pad_push (mysrc, + gst_buffer_ref (buffer)) == GST_FLOW_FLUSHING); + + /* Test if everything still works in normal state */ + GST_DEBUG ("Reactivate both pads and try pushing"); + gst_pad_set_active (mysink1, TRUE); + gst_pad_set_active (mysink2, TRUE); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + /* One unlinked pad must return OK, two unlinked pads must return NOT_LINKED */ + GST_DEBUG ("Pushing with mysink1 unlinked"); + fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + GST_DEBUG ("Pushing with mysink2 unlinked"); + fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK); + fail_unless (gst_pad_unlink (teesrc2, mysink2) == TRUE); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + GST_DEBUG ("Pushing with mysink1 AND mysink2 unlinked"); + fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE); + fail_unless (gst_pad_push (mysrc, + gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED); + + /* Test if everything still works in normal state */ + GST_DEBUG ("Relink both pads and try pushing"); + fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK); + fail_unless (gst_pad_link (teesrc2, mysink2) == GST_PAD_LINK_OK); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + /* One pad returning ERROR should result in ERROR */ + GST_DEBUG ("Pushing with mysink1 returning GST_FLOW_ERROR"); + gst_pad_set_chain_function (mysink1, _fake_chain_error); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR); + + GST_DEBUG ("Pushing with mysink2 returning GST_FLOW_ERROR"); + gst_pad_set_chain_function (mysink1, _fake_chain); + gst_pad_set_chain_function (mysink2, _fake_chain_error); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR); + + GST_DEBUG ("Pushing with mysink1 AND mysink2 returning GST_FLOW_ERROR"); + gst_pad_set_chain_function (mysink1, _fake_chain_error); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR); + + /* And now everything still needs to work */ + GST_DEBUG ("Try pushing with everything ok"); + gst_pad_set_chain_function (mysink1, _fake_chain); + gst_pad_set_chain_function (mysink2, _fake_chain); + fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + fail_unless (gst_element_set_state (tee, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (gst_pad_unlink (mysrc, teesink) == TRUE); + fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE); + fail_unless (gst_pad_unlink (teesrc2, mysink2) == TRUE); + + + gst_object_unref (teesink); + gst_object_unref (teesrc1); + gst_object_unref (teesrc2); + gst_element_release_request_pad (tee, teesrc1); + gst_element_release_request_pad (tee, teesrc2); + gst_object_unref (tee); + + gst_object_unref (mysink1); + gst_object_unref (mysink2); + gst_object_unref (mysrc); + gst_caps_unref (caps); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_request_pads) +{ + GstElement *tee; + GstPad *srcpad1, *srcpad2, *srcpad3, *srcpad4; + + tee = gst_check_setup_element ("tee"); + + srcpad1 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (srcpad1 != NULL); + fail_unless_equals_string (GST_OBJECT_NAME (srcpad1), "src_0"); + srcpad2 = gst_element_get_request_pad (tee, "src_100"); + fail_unless (srcpad2 != NULL); + fail_unless_equals_string (GST_OBJECT_NAME (srcpad2), "src_100"); + srcpad3 = gst_element_get_request_pad (tee, "src_10"); + fail_unless (srcpad3 != NULL); + fail_unless_equals_string (GST_OBJECT_NAME (srcpad3), "src_10"); + srcpad4 = gst_element_get_request_pad (tee, "src_%u"); + fail_unless (srcpad4 != NULL); + + gst_object_unref (srcpad1); + gst_object_unref (srcpad2); + gst_object_unref (srcpad3); + gst_object_unref (srcpad4); + gst_object_unref (tee); +} + +GST_END_TEST; + +GST_START_TEST (test_allow_not_linked) +{ + GstElement *tee; + GstPad *src1, *src2; + GstBuffer *buffer; + GstPad *srcpad; + GstCaps *caps; + GstSegment segment; + + static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + caps = gst_caps_new_empty_simple ("test/test"); + + tee = gst_check_setup_element ("tee"); + fail_unless (tee); + g_object_set (tee, "allow-not-linked", TRUE, NULL); + + srcpad = gst_check_setup_src_pad (tee, &srctemplate); + gst_pad_set_active (srcpad, TRUE); + + gst_pad_push_event (srcpad, gst_event_new_stream_start ("test")); + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (srcpad, gst_event_new_stream_start ("test")); + gst_pad_set_caps (srcpad, caps); + gst_caps_unref (caps); + gst_pad_push_event (srcpad, gst_event_new_segment (&segment)); + + fail_unless (gst_element_set_state (tee, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new (); + fail_unless (buffer); + + fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + src1 = gst_element_get_request_pad (tee, "src_%u"); + + fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + src2 = gst_element_get_request_pad (tee, "src_%u"); + + fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK); + + g_object_set (tee, "allow-not-linked", FALSE, NULL); + + fail_unless (gst_pad_push (srcpad, + gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED); + + gst_element_release_request_pad (tee, src1); + + fail_unless (gst_pad_push (srcpad, + gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED); + + gst_element_release_request_pad (tee, src2); + g_object_unref (src1); + g_object_unref (src2); + + fail_unless (gst_pad_push (srcpad, + gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED); + + gst_pad_set_active (srcpad, FALSE); + gst_check_teardown_src_pad (tee); + gst_check_teardown_element (tee); + + fail_if (buffer->mini_object.refcount != 1); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +static gboolean +allocation_query_empty (GstPad * pad, GstObject * parent, GstQuery * query) +{ + if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) + return gst_pad_query_default (pad, parent, query); + + return TRUE; +} + +static gboolean +allocation_query1 (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstAllocationParams param = { 0, 15, 1, 1 }; + + if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) + return gst_pad_query_default (pad, parent, query); + + gst_query_add_allocation_pool (query, NULL, 128, 2, 10); + gst_query_add_allocation_param (query, NULL, ¶m); + gst_query_add_allocation_meta (query, GST_PARENT_BUFFER_META_API_TYPE, NULL); + gst_query_add_allocation_meta (query, GST_REFERENCE_TIMESTAMP_META_API_TYPE, + NULL); + gst_query_add_allocation_meta (query, GST_PROTECTION_META_API_TYPE, NULL); + + return TRUE; +} + +static gboolean +allocation_query2 (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstAllocationParams param = { 0, 7, 2, 1 }; + + if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) + return gst_pad_query_default (pad, parent, query); + + gst_query_add_allocation_pool (query, NULL, 129, 1, 15); + gst_query_add_allocation_param (query, NULL, ¶m); + gst_query_add_allocation_meta (query, GST_PARENT_BUFFER_META_API_TYPE, NULL); + gst_query_add_allocation_meta (query, GST_REFERENCE_TIMESTAMP_META_API_TYPE, + NULL); + gst_query_add_allocation_meta (query, GST_PROTECTION_META_API_TYPE, NULL); + + return TRUE; +} + +static gboolean +allocation_query3 (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstStructure *s; + GstAllocationParams param = { 0, 7, 1, 2 }; + + if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) + return gst_pad_query_default (pad, parent, query); + + gst_query_add_allocation_pool (query, NULL, 130, 1, 20); + gst_query_add_allocation_param (query, NULL, ¶m); + gst_query_add_allocation_meta (query, GST_PARENT_BUFFER_META_API_TYPE, NULL); + s = gst_structure_new_empty ("test/test"); + gst_query_add_allocation_meta (query, GST_PROTECTION_META_API_TYPE, s); + gst_structure_free (s); + + return TRUE; +} + +static gboolean +allocation_query_fail (GstPad * pad, GstObject * parent, GstQuery * query) +{ + if (GST_QUERY_TYPE (query) != GST_QUERY_ALLOCATION) + return gst_pad_query_default (pad, parent, query); + + return FALSE; +} + +static void +add_sink_pad_and_setup_query_func (GstElement * tee, + GstPadQueryFunction query_func) +{ + GstPad *sink; + static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + sink = gst_check_setup_sink_pad_by_name (tee, &sinktemplate, "src_%u"); + fail_unless (sink != NULL); + gst_pad_set_query_function (sink, query_func); +} + +GST_START_TEST (test_allocation_query_aggregation) +{ + GstElement *tee; + GstPad *sinkpad; + GstCaps *caps; + GstQuery *query; + guint size, min, max; + GstAllocationParams param; + + tee = gst_check_setup_element ("tee"); + fail_unless (tee); + + sinkpad = gst_element_get_static_pad (tee, "sink"); + add_sink_pad_and_setup_query_func (tee, allocation_query1); + add_sink_pad_and_setup_query_func (tee, allocation_query2); + add_sink_pad_and_setup_query_func (tee, allocation_query3); + + caps = gst_caps_new_empty_simple ("test/test"); + query = gst_query_new_allocation (caps, TRUE); + fail_unless (gst_pad_query (sinkpad, query)); + + ck_assert_int_eq (gst_query_get_n_allocation_pools (query), 1); + gst_query_parse_nth_allocation_pool (query, 0, NULL, &size, &min, &max); + fail_unless (size == 130); + /* The tee will allocate one more buffer when multiplexing */ + fail_unless (min == 2 + 1); + fail_unless (max == 0); + + fail_unless (gst_query_get_n_allocation_params (query), 1); + gst_query_parse_nth_allocation_param (query, 0, NULL, ¶m); + fail_unless (param.align == 15); + fail_unless (param.prefix == 2); + fail_unless (param.padding == 2); + + fail_unless (gst_query_get_n_allocation_metas (query), 1); + fail_unless (gst_query_parse_nth_allocation_meta (query, 0, NULL) == + GST_PARENT_BUFFER_META_API_TYPE); + + gst_caps_unref (caps); + gst_query_unref (query); + gst_check_teardown_pad_by_name (tee, "src_0"); + gst_check_teardown_pad_by_name (tee, "src_1"); + gst_check_teardown_pad_by_name (tee, "src_2"); + gst_object_unref (sinkpad); + gst_check_teardown_element (tee); +} + +GST_END_TEST; + + +GST_START_TEST (test_allocation_query_allow_not_linked) +{ + GstElement *tee; + GstPad *sinkpad, *srcpad; + GstCaps *caps; + GstQuery *query; + + tee = gst_check_setup_element ("tee"); + fail_unless (tee); + + sinkpad = gst_element_get_static_pad (tee, "sink"); + add_sink_pad_and_setup_query_func (tee, allocation_query1); + add_sink_pad_and_setup_query_func (tee, allocation_query2); + add_sink_pad_and_setup_query_func (tee, allocation_query3); + /* This unlinked pad is what will make a difference between having + * allow-not-linked set or not */ + srcpad = gst_element_get_request_pad (tee, "src_%u"); + caps = gst_caps_new_empty_simple ("test/test"); + + /* Without allow-not-linked the query should fail */ + query = gst_query_new_allocation (caps, TRUE); + fail_if (gst_pad_query (sinkpad, query)); + + /* While with allow-not-linked it should succeed (ignoring that pad) */ + g_object_set (tee, "allow-not-linked", TRUE, NULL); + gst_query_unref (query); + query = gst_query_new_allocation (caps, TRUE); + fail_unless (gst_pad_query (sinkpad, query)); + + gst_caps_unref (caps); + gst_query_unref (query); + gst_check_teardown_pad_by_name (tee, "src_0"); + gst_check_teardown_pad_by_name (tee, "src_1"); + gst_check_teardown_pad_by_name (tee, "src_2"); + gst_element_release_request_pad (tee, srcpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + gst_check_teardown_element (tee); +} + +GST_END_TEST; + + +GST_START_TEST (test_allocation_query_failure) +{ + GstElement *tee; + GstPad *sinkpad; + GstCaps *caps; + GstQuery *query; + + tee = gst_check_setup_element ("tee"); + fail_unless (tee); + g_object_set (tee, "allow-not-linked", TRUE, NULL); + + sinkpad = gst_element_get_static_pad (tee, "sink"); + add_sink_pad_and_setup_query_func (tee, allocation_query1); + add_sink_pad_and_setup_query_func (tee, allocation_query2); + add_sink_pad_and_setup_query_func (tee, allocation_query_fail); + + caps = gst_caps_new_empty_simple ("test/test"); + query = gst_query_new_allocation (caps, TRUE); + fail_if (gst_pad_query (sinkpad, query)); + + gst_caps_unref (caps); + gst_query_unref (query); + gst_check_teardown_pad_by_name (tee, "src_0"); + gst_check_teardown_pad_by_name (tee, "src_1"); + gst_check_teardown_pad_by_name (tee, "src_2"); + gst_object_unref (sinkpad); + gst_check_teardown_element (tee); +} + +GST_END_TEST; + + +GST_START_TEST (test_allocation_query_empty) +{ + GstElement *tee; + GstPad *sinkpad; + GstCaps *caps; + GstQuery *query; + + tee = gst_check_setup_element ("tee"); + fail_unless (tee); + + sinkpad = gst_element_get_static_pad (tee, "sink"); + add_sink_pad_and_setup_query_func (tee, allocation_query_empty); + + caps = gst_caps_new_empty_simple ("test/test"); + + query = gst_query_new_allocation (caps, TRUE); + fail_unless (gst_pad_query (sinkpad, query)); + + ck_assert_int_eq (gst_query_get_n_allocation_pools (query), 0); + ck_assert_int_eq (gst_query_get_n_allocation_params (query), 0); + + gst_caps_unref (caps); + gst_query_unref (query); + gst_check_teardown_pad_by_name (tee, "src_0"); + gst_object_unref (sinkpad); + gst_check_teardown_element (tee); +} + +GST_END_TEST; + + +static Suite * +tee_suite (void) +{ + Suite *s = suite_create ("tee"); + TCase *tc_chain = tcase_create ("general"); + + /* Set the timeout to a much larger time - 3 minutes */ + tcase_set_timeout (tc_chain, 180); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_num_buffers); + tcase_add_test (tc_chain, test_stress); + tcase_add_test (tc_chain, test_release_while_buffer_alloc); + tcase_add_test (tc_chain, test_release_while_second_buffer_alloc); + tcase_add_test (tc_chain, test_internal_links); + tcase_add_test (tc_chain, test_flow_aggregation); + tcase_add_test (tc_chain, test_request_pads); + tcase_add_test (tc_chain, test_allow_not_linked); + tcase_add_test (tc_chain, test_allocation_query_aggregation); + tcase_add_test (tc_chain, test_allocation_query_allow_not_linked); + tcase_add_test (tc_chain, test_allocation_query_failure); + tcase_add_test (tc_chain, test_allocation_query_empty); + + return s; +} + +GST_CHECK_MAIN (tee); diff --git a/tests/check/elements/valve.c b/tests/check/elements/valve.c new file mode 100644 index 0000000..e6d7f37 --- /dev/null +++ b/tests/check/elements/valve.c @@ -0,0 +1,101 @@ +/* GStreamer + * + * unit test for the valve element + * + * Copyright 2009 Collabora Ltd. + * @author: Olivier Crete + * Copyright 2009 Nokia Corp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +GST_START_TEST (test_valve_basic) +{ + GstHarness *h = gst_harness_new ("valve"); + + gst_harness_set_src_caps_str (h, "mycaps"); + + /* when not dropping, we don't drop buffers.... */ + g_object_set (h->element, "drop", FALSE, NULL); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, gst_buffer_new ())); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, gst_buffer_new ())); + fail_unless_equals_int (2, gst_harness_buffers_received (h)); + + /* when dropping, the buffers don't make it through */ + g_object_set (h->element, "drop", TRUE, NULL); + fail_unless_equals_int (3, gst_harness_events_received (h)); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, gst_buffer_new ())); + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, gst_buffer_new ())); + fail_unless_equals_int (2, gst_harness_buffers_received (h)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_valve_upstream_events_dont_send_sticky) +{ + GstHarness *h = gst_harness_new ("valve"); + + /* set to drop */ + g_object_set (h->element, "drop", TRUE, NULL); + + /* set caps to trigger sticky-events being pushed to valve */ + gst_harness_set_src_caps_str (h, "mycaps"); + + /* verify no events have made it through yet */ + fail_unless_equals_int (0, gst_harness_events_received (h)); + + /* stop dropping */ + g_object_set (h->element, "drop", FALSE, NULL); + + /* send an upstream event and verify that no + downstream events was pushed as a result of this */ + gst_harness_push_upstream_event (h, gst_event_new_reconfigure ()); + fail_unless_equals_int (0, gst_harness_events_received (h)); + + /* push a buffer, and verify this pushes the sticky events */ + fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, gst_buffer_new ())); + fail_unless_equals_int (3, gst_harness_events_received (h)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +static Suite * +valve_suite (void) +{ + Suite *s = suite_create ("valve"); + TCase *tc_chain; + + tc_chain = tcase_create ("valve_basic"); + tcase_add_test (tc_chain, test_valve_basic); + tcase_add_test (tc_chain, test_valve_upstream_events_dont_send_sticky); + + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (valve) diff --git a/tests/check/generic/sinks.c b/tests/check/generic/sinks.c new file mode 100644 index 0000000..0a0e95d --- /dev/null +++ b/tests/check/generic/sinks.c @@ -0,0 +1,1414 @@ +/* GStreamer + * + * unit test for sinks + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static void +pop_state_change_message (GstBus * bus, GstElement * src, GstState old, + GstState new, GstState pending) +{ + GstMessage *message = NULL; + GstState _old, _new, _pending; + + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); + fail_unless (message != NULL, + "Expected state change message, but got nothing"); + + gst_message_parse_state_changed (message, &_old, &_new, &_pending); + + fail_unless (GST_MESSAGE_SRC (message) == (GstObject *) src, + "Unexpected state change order"); + fail_unless (old == _old, "Unexpected old state"); + fail_unless (new == _new, "Unexpected new state"); + fail_unless (pending == _pending, "Unexpected pending state"); + + gst_message_unref (message); +} + +/* a sink should go ASYNC to PAUSE. forcing PLAYING is possible */ +GST_START_TEST (test_sink) +{ + GstElement *sink; + GstStateChangeReturn ret; + GstState current, pending; + + sink = gst_element_factory_make ("fakesink", "sink"); + + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return"); + + ret = gst_element_set_state (sink, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no forced async state change"); + + ret = gst_element_get_state (sink, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async"); + fail_unless (current == GST_STATE_READY, "bad current state"); + fail_unless (pending == GST_STATE_PLAYING, "bad pending state"); + + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async going back to paused"); + + ret = gst_element_set_state (sink, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to ready"); + + ret = gst_element_set_state (sink, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null"); + + gst_object_unref (sink); +} + +GST_END_TEST +/* a sink should go ASYNC to PAUSE and PLAYING, when linking a src, it + * should complete the state change. */ +GST_START_TEST (test_sink_completion) +{ + GstElement *sink, *src; + GstStateChangeReturn ret; + GstState current, pending; + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + ret = gst_element_set_state (sink, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return"); + + ret = gst_element_get_state (sink, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async"); + fail_unless (current == GST_STATE_READY, "bad current state"); + fail_unless (pending == GST_STATE_PLAYING, "bad pending state"); + + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "datarate", 200, "sizetype", 2, NULL); + gst_element_link (src, sink); + + ret = gst_element_set_state (src, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + + /* now wait for final state */ + ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to change state"); + fail_unless (current == GST_STATE_PLAYING, "bad current state"); + fail_unless (pending == GST_STATE_VOID_PENDING, "bad pending state"); + + ret = gst_element_set_state (sink, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null"); + + ret = gst_element_set_state (src, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null"); + + gst_object_unref (sink); + gst_object_unref (src); +} + +GST_END_TEST +/* a sink should go ASYNC to PAUSE. PAUSE should complete when + * prerolled. */ +GST_START_TEST (test_src_sink) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return"); + ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot start play"); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline"); + + gst_object_unref (pipeline); + +} + +GST_END_TEST +/* a pipeline with live source should return NO_PREROLL in + * PAUSE. When removing the live source it should return ASYNC + * from the sink */ +GST_START_TEST (test_livesrc_remove) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_object_ref (src); + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no no_preroll state return"); + + ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + gst_bin_remove (GST_BIN (pipeline), src); + + ret = gst_element_set_state (src, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null"); + gst_object_unref (src); + + ret = gst_element_get_state (pipeline, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_PAUSED, "not paused"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null"); + gst_object_unref (pipeline); +} + +GST_END_TEST +/* the sink should go ASYNC to PAUSE. The live source should go + * NO_PREROLL to PAUSE. the pipeline returns NO_PREROLL. An + * attempt to go to PLAYING will return ASYNC. polling state + * completion should return SUCCESS when the sink is gone to + * PLAYING. */ +GST_START_TEST (test_livesrc_sink) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + GstBus *bus; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + bus = gst_element_get_bus (pipeline); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no no_preroll state return"); + + pop_state_change_message (bus, sink, GST_STATE_NULL, GST_STATE_READY, + GST_STATE_VOID_PENDING); + pop_state_change_message (bus, src, GST_STATE_NULL, GST_STATE_READY, + GST_STATE_VOID_PENDING); + pop_state_change_message (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, + GST_STATE_PAUSED); + + /* this order only holds true for live sources because they do not push + buffers in PAUSED */ + pop_state_change_message (bus, src, GST_STATE_READY, GST_STATE_PAUSED, + GST_STATE_VOID_PENDING); + pop_state_change_message (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED, + GST_STATE_VOID_PENDING); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no no_preroll state return the second time"); + + ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + /* don't block here */ + ret = gst_element_get_state (sink, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async"); + fail_unless (current == GST_STATE_READY, "not ready"); + fail_unless (pending == GST_STATE_PAUSED, "not paused"); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async"); + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + /* now we have four messages on the bus: src from paused to playing, sink from + ready to paused and paused to playing, and pipeline from paused to playing. + the pipeline message should be last, and the sink messages should go in + order, but the src message can be interleaved with the sink one. */ + { + GstMessage *m; + GstState old, new, pending; + gint n_src = 1, n_sink = 2; + + while (n_src + n_sink > 0) { + m = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); + fail_unless (m != NULL, "expected state change message"); + gst_message_parse_state_changed (m, &old, &new, &pending); + if (GST_MESSAGE_SRC (m) == (GstObject *) src) { + fail_unless (n_src == 1, "already got one message from the src"); + n_src--; + fail_unless (old == GST_STATE_PAUSED, "unexpected old"); + fail_unless (new == GST_STATE_PLAYING, "unexpected new (got %d)", new); + fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending"); + } else if (GST_MESSAGE_SRC (m) == (GstObject *) sink) { + if (n_sink == 2) { + fail_unless (old == GST_STATE_READY, "unexpected old"); + fail_unless (new == GST_STATE_PAUSED, "unexpected new"); + fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending"); + } else if (n_sink == 1) { + fail_unless (old == GST_STATE_PAUSED, "unexpected old"); + fail_unless (new == GST_STATE_PLAYING, "unexpected new"); + fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending"); + } else { + g_assert_not_reached (); + } + n_sink--; + } else { + g_critical + ("Unexpected state change message src %s (%d src %d sink pending)", + GST_OBJECT_NAME (GST_MESSAGE_SRC (m)), n_src, n_sink); + } + gst_message_unref (m); + } + } + + pop_state_change_message (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING, + GST_STATE_VOID_PENDING); + + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* The sink should go ASYNC to PLAYING. The source should go + * to PLAYING with SUCCESS. The pipeline returns ASYNC. */ +GST_START_TEST (test_livesrc2_sink) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return"); + + ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + /* and back down */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no no_preroll state return"); + + ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not paused"); + + /* sink state is not known.. it might be prerolled or not */ + + /* and to READY */ + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + + ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success"); + fail_unless (current == GST_STATE_READY, "not ready"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not ready"); + + ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success"); + fail_unless (current == GST_STATE_READY, "not ready"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not ready"); + + /* And destroy. Must be NULL */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_livesrc3_sink) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return"); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not playing"); + + /* and back down */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_locked_sink) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + /* we don't link the elements */ + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + /* the sink is now async going from ready to paused */ + ret = gst_element_get_state (sink, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async"); + fail_unless (current == GST_STATE_READY, "not ready"); + fail_unless (pending == GST_STATE_PAUSED, "not paused"); + + /* lock the sink */ + gst_element_set_locked_state (sink, TRUE); + + /* move to PlAYING, the sink should remain ASYNC. The pipeline + * returns ASYNC */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* back to PAUSED, we should get NO_PREROLL again */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* unlock the sink */ + gst_element_set_locked_state (sink, FALSE); + + /* and now everything back down */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return"); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_unlinked_live) +{ + GstElement *sink, *src, *lsrc, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + lsrc = gst_element_factory_make ("fakesrc", "lsrc"); + g_object_set (G_OBJECT (lsrc), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), lsrc); + gst_bin_add (GST_BIN (pipeline), sink); + + /* link non live source to sink */ + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + /* we don't link the srcpad of the live source, it will not contribute to the + * NO_PREROLL. */ + + /* set state to PAUSED, this should return NO_PREROLL because there is a live + * source. since the only sink in this pipeline is linked to a non-live + * source, it will preroll eventually. */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* wait till the sink is prerolled */ + ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have playing"); + + /* the pipeline should still return NO_PREROLL */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have playing"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_delayed_async) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + /* add source, don't add sink yet */ + gst_bin_add (GST_BIN (pipeline), src); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* add sink now and set to PAUSED */ + gst_bin_add (GST_BIN (pipeline), sink); + + /* This will make the bin notice an ASYNC element. */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* we should still be NO_PREROLL now although there is an async element in the + * pipeline. */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + /* link live source to sink */ + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* we should get SUCCESS now */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PLAYING, "not PLAYING"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_added_async) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + /* add source, don't add sink yet */ + gst_bin_add (GST_BIN (pipeline), src); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* set sink to PAUSED without adding it to the pipeline */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* add sink now, pipeline should notice the async element */ + gst_bin_add (GST_BIN (pipeline), sink); + + /* we should still be NO_PREROLL now although there is an async element in the + * pipeline. */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + /* link live source to sink */ + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* we should get SUCCESS now */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PLAYING, "not PLAYING"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_added_async2) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + sink = gst_element_factory_make ("fakesink", "sink"); + + /* add source, don't add sink yet */ + gst_bin_add (GST_BIN (pipeline), src); + /* need to lock state here or the pipeline might go in error */ + gst_element_set_locked_state (src, TRUE); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return"); + + /* set sink to PAUSED without adding it to the pipeline */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* add sink now, pipeline should notice the async element */ + gst_bin_add (GST_BIN (pipeline), sink); + + /* we should be ASYNC now because there is an async element in the + * pipeline. */ + ret = gst_element_get_state (pipeline, ¤t, &pending, 0); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_PAUSED, "not paused"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_add_live) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + /* add sink, don't add sourc3 yet */ + gst_bin_add (GST_BIN (pipeline), sink); + + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* set source to PAUSED without adding it to the pipeline */ + ret = gst_element_set_state (src, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* add source now, pipeline should notice the NO_PREROLL element */ + gst_bin_add (GST_BIN (pipeline), src); + + /* we should be NO_PREROLL now because there is a NO_PREROLL element in the + * pipeline. */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GMutex blocked_lock; +static GCond blocked_cond; + +static GstPadProbeReturn +pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + g_mutex_lock (&blocked_lock); + GST_DEBUG ("srcpad blocked: %d, sending signal", info->type); + g_cond_signal (&blocked_cond); + g_mutex_unlock (&blocked_lock); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_add_live2) +{ + GstElement *sink, *src, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + gulong id; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + /* add sink, don't add source yet */ + gst_bin_add (GST_BIN (pipeline), sink); + + /* set the pipeline to PLAYING. This will return ASYNC on READY->PAUSED */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + g_mutex_lock (&blocked_lock); + + GST_DEBUG ("blocking srcpad"); + /* block source pad */ + srcpad = gst_element_get_static_pad (src, "src"); + id = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + pad_blocked_cb, NULL, NULL); + + /* set source to PAUSED without adding it to the pipeline */ + ret = gst_element_set_state (src, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + + /* add source now, pipeline should notice the NO_PREROLL element. This + * should trigger as commit of the ASYNC pipeline and make it continue + * to PLAYING. We blocked the source pad so that we don't get an unlinked + * error. */ + gst_bin_add (GST_BIN (pipeline), src); + + /* wait for pad blocked, this means the source is now PLAYING. */ + g_cond_wait (&blocked_cond, &blocked_lock); + g_mutex_unlock (&blocked_lock); + + GST_DEBUG ("linking pads"); + + /* link to sink */ + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + GST_DEBUG ("unblocking srcpad"); + + /* and unblock */ + gst_pad_remove_probe (srcpad, id); + + GST_DEBUG ("getting state"); + + /* we should be SUCCESS now and PLAYING */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + fail_unless (current == GST_STATE_PLAYING, "not PLAYING"); + fail_unless (pending == GST_STATE_VOID_PENDING, "have pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS"); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_bin_live) +{ + GstElement *sink, *src, *pipeline, *bin; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + bin = gst_bin_new ("bin"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (bin), src); + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (pipeline), bin); + + srcpad = gst_element_get_static_pad (src, "src"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + /* PAUSED returns NO_PREROLL because of the live source */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending"); + + /* when going to PLAYING, the sink should go to PLAYING ASYNC */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC"); + + /* now wait for PLAYING to complete */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline"); + + gst_object_unref (pipeline); +} + +GST_END_TEST static gpointer +send_eos (GstPad * sinkpad) +{ + gboolean ret; + + ret = gst_pad_send_event (sinkpad, gst_event_new_eos ()); + + return GINT_TO_POINTER (ret); +} + +/* push a buffer with a very long duration in a fakesink, then push an EOS + * event. fakesink should emit EOS after the duration of the buffer expired. + * Going to PAUSED, however should not return ASYNC while processing the + * buffer. */ +GST_START_TEST (test_fake_eos) +{ + GstElement *sink, *pipeline; + GstBuffer *buffer; + GstStateChangeReturn ret; + GstPad *sinkpad; + GstFlowReturn res; + GThread *thread; + GstSegment segment; + + pipeline = gst_pipeline_new ("pipeline"); + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + + gst_bin_add (GST_BIN_CAST (pipeline), sink); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)); + + /* push buffer of 100 seconds, since it has a timestamp of 0, it should be + * rendered immediately and the chain function should return immediately */ + buffer = gst_buffer_new_and_alloc (10); + GST_BUFFER_TIMESTAMP (buffer) = 0; + GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND; + res = gst_pad_chain (sinkpad, buffer); + fail_unless (res == GST_FLOW_OK, "no OK flow return"); + + /* wait for preroll, this should happen really soon. */ + ret = gst_element_get_state (pipeline, NULL, NULL, -1); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return"); + + /* push EOS, this will block for up to 100 seconds, until the previous + * buffer has finished. We therefore push it in another thread so we can do + * something else while it blocks. */ + thread = + g_thread_try_new ("gst-check", (GThreadFunc) send_eos, sinkpad, NULL); + fail_if (thread == NULL, "no thread"); + + /* wait a while so that the thread manages to start and push the EOS */ + g_usleep (G_USEC_PER_SEC); + + /* this should cancel rendering of the EOS event and should return SUCCESS + * because the sink is now prerolled on the EOS. */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return"); + + /* we can unref the sinkpad now, we're done with it */ + gst_object_unref (sinkpad); + + /* wait for a second, use the debug log to see that basesink does not discard + * the EOS */ + g_usleep (G_USEC_PER_SEC); + + /* go back to PLAYING, which means waiting some more in EOS, check debug log + * to see this happen. */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return"); + g_usleep (G_USEC_PER_SEC); + + /* teardown and cleanup */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return"); + + /* we can join now */ + g_thread_join (thread); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* this variable is updated in the same thread, first it is set by the + * handoff-preroll signal, then it is checked when the ASYNC_DONE is posted on + * the bus */ +static gboolean have_preroll = FALSE; + +static void +async_done_handoff (GstElement * element, GstBuffer * buf, GstPad * pad, + GstElement * sink) +{ + GST_DEBUG ("we have the preroll buffer"); + have_preroll = TRUE; +} + +/* when we get the ASYNC_DONE, query the position */ +static GstBusSyncReply +async_done_func (GstBus * bus, GstMessage * msg, GstElement * sink) +{ + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) { + gint64 position; + + GST_DEBUG ("we have ASYNC_DONE now"); + fail_unless (have_preroll == TRUE, "no preroll buffer received"); + + /* get the position now */ + gst_element_query_position (sink, GST_FORMAT_TIME, &position); + + GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + } + + /* we must unref the message if we return DROP */ + gst_message_unref (msg); + + /* we can drop the message, nothing is listening for it. */ + return GST_BUS_DROP; +} + +static void +send_buffer (GstPad * sinkpad) +{ + GstBuffer *buffer; + GstFlowReturn ret; + + /* push a second buffer */ + GST_DEBUG ("pushing last buffer"); + buffer = gst_buffer_new_and_alloc (10); + GST_BUFFER_TIMESTAMP (buffer) = 200 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND; + + /* this function will initially block */ + ret = gst_pad_chain (sinkpad, buffer); + fail_unless (ret == GST_FLOW_OK, "no OK flow return"); +} + +/* when we get the ASYNC_DONE message from a sink, we want the sink to be able + * to report the duration and position. The sink should also have called the + * render method. */ +GST_START_TEST (test_async_done) +{ + GstElement *sink; + GstEvent *event; + GstStateChangeReturn ret; + GstPad *sinkpad; + gboolean res; + GstBus *bus; + GThread *thread; + gint64 position; + gboolean qret; + GstSegment segment; + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL); + + g_signal_connect (sink, "preroll-handoff", (GCallback) async_done_handoff, + sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* set bus on element synchronously listen for ASYNC_DONE */ + bus = gst_bus_new (); + gst_element_set_bus (sink, bus); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_func, sink, + NULL); + + gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test")); + + /* make newsegment, this sets the position to 10sec when the buffer prerolls */ + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.time = 10 * GST_SECOND; + + event = gst_event_new_segment (&segment); + res = gst_pad_send_event (sinkpad, event); + fail_unless (res == TRUE); + + /* We have not yet received any buffers so we are still in the READY state, + * the position is therefore still not queryable. */ + position = -1; + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position); + fail_unless (qret == TRUE, "position wrong"); + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + + /* last buffer, blocks because preroll queue is filled. Start the push in a + * new thread so that we can check the position */ + GST_DEBUG ("starting thread"); + thread = + g_thread_try_new ("gst-check", (GThreadFunc) send_buffer, sinkpad, NULL); + fail_if (thread == NULL, "no thread"); + + GST_DEBUG ("waiting 1 second"); + g_usleep (G_USEC_PER_SEC); + GST_DEBUG ("waiting done"); + + /* check if position is still 10 seconds. This is racy because the above + * thread might not yet have started the push, because of the above sleep, + * this is very unlikely, though. */ + gst_element_query_position (sink, GST_FORMAT_TIME, &position); + GST_DEBUG ("second buffer position %" GST_TIME_FORMAT, + GST_TIME_ARGS (position)); + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + + /* now we go to playing. This should unlock and stop the above thread. */ + GST_DEBUG ("going to PLAYING"); + ret = gst_element_set_state (sink, GST_STATE_PLAYING); + + /* join the thread. At this point we know the sink processed the last buffer + * and the position should now be 210 seconds; the time of the last buffer we + * pushed. The element has no clock or base-time so it only reports the + * last seen timestamp of the buffer, it does not know how much of the buffer + * is consumed. */ + GST_DEBUG ("joining thread"); + g_thread_join (thread); + + gst_element_query_position (sink, GST_FORMAT_TIME, &position); + GST_DEBUG ("last buffer position %" GST_TIME_FORMAT, + GST_TIME_ARGS (position)); + fail_unless (position == 210 * GST_SECOND, "position is wrong"); + + gst_object_unref (sinkpad); + + gst_element_set_state (sink, GST_STATE_NULL); + gst_object_unref (sink); + gst_object_unref (bus); +} + +GST_END_TEST; + +/* when we get the ASYNC_DONE, query the position */ +static GstBusSyncReply +async_done_eos_func (GstBus * bus, GstMessage * msg, GstElement * sink) +{ + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) { + gint64 position; + + GST_DEBUG ("we have ASYNC_DONE now"); + + /* get the position now */ + gst_element_query_position (sink, GST_FORMAT_TIME, &position); + + GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + } + /* we must unref the message if we return DROP */ + gst_message_unref (msg); + /* we can drop the message, nothing is listening for it. */ + return GST_BUS_DROP; +} + +/* when we get the ASYNC_DONE message from a sink, we want the sink to be able + * to report the duration and position. The sink should also have called the + * render method. */ +GST_START_TEST (test_async_done_eos) +{ + GstElement *sink; + GstEvent *event; + GstStateChangeReturn ret; + GstPad *sinkpad; + gboolean res; + GstBus *bus; + gboolean qret; + GstSegment segment; + gint64 position; + GThread *thread; + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return"); + + /* set bus on element synchronously listen for ASYNC_DONE */ + bus = gst_bus_new (); + gst_element_set_bus (sink, bus); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_eos_func, sink, + NULL); + + /* make newsegment, this sets the position to 10sec when the buffer prerolls */ + GST_DEBUG ("sending segment"); + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.time = 10 * GST_SECOND; + event = gst_event_new_segment (&segment); + res = gst_pad_send_event (sinkpad, event); + fail_unless (res == TRUE); + + /* We have not yet received any buffers so we are still in the READY state, + * the position is therefore still not queryable. */ + position = -1; + qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position); + fail_unless (qret == TRUE, "position wrong"); + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + + /* Since we are paused and the preroll queue has a length of 1, this function + * will return immediately. The EOS will complete the preroll and the + * position should now be 10 seconds. */ + GST_DEBUG ("pushing EOS"); + GST_DEBUG ("starting thread"); + thread = + g_thread_try_new ("gst-check", (GThreadFunc) send_eos, sinkpad, NULL); + fail_if (thread == NULL, "no thread"); + + /* wait for preroll */ + gst_element_get_state (sink, NULL, NULL, -1); + + /* check if position is still 10 seconds */ + gst_element_query_position (sink, GST_FORMAT_TIME, &position); + GST_DEBUG ("EOS position %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + fail_unless (position == 10 * GST_SECOND, "position is wrong"); + + gst_element_set_state (sink, GST_STATE_NULL); + g_thread_join (thread); + + gst_object_unref (sinkpad); + gst_object_unref (sink); + gst_object_unref (bus); +} + +GST_END_TEST; + +static GMutex preroll_lock; +static GCond preroll_cond; + +static void +test_async_false_seek_preroll (GstElement * elem, GstBuffer * buf, + GstPad * pad, gpointer data) +{ + g_mutex_lock (&preroll_lock); + GST_DEBUG ("Got preroll buffer %p", buf); + g_cond_signal (&preroll_cond); + g_mutex_unlock (&preroll_lock); +} + +static void +test_async_false_seek_handoff (GstElement * elem, GstBuffer * buf, + GstPad * pad, gpointer data) +{ + /* should never be reached, we never go to PLAYING */ + GST_DEBUG ("Got handoff buffer %p", buf); + fail_unless (FALSE); +} + +GST_START_TEST (test_async_false_seek) +{ + GstElement *pipeline, *source, *sink; + + /* Create gstreamer elements */ + pipeline = gst_pipeline_new ("test-pipeline"); + source = gst_element_factory_make ("fakesrc", "file-source"); + sink = gst_element_factory_make ("fakesink", "audio-output"); + + g_object_set (G_OBJECT (sink), "async", FALSE, NULL); + g_object_set (G_OBJECT (sink), "num-buffers", 10, NULL); + g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL); + + g_signal_connect (sink, "handoff", G_CALLBACK (test_async_false_seek_handoff), + NULL); + g_signal_connect (sink, "preroll-handoff", + G_CALLBACK (test_async_false_seek_preroll), NULL); + + /* we add all elements into the pipeline */ + gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); + + /* we link the elements together */ + gst_element_link (source, sink); + + GST_DEBUG ("Now pausing"); + g_mutex_lock (&preroll_lock); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* wait for preroll */ + GST_DEBUG ("wait for preroll"); + g_cond_wait (&preroll_cond, &preroll_lock); + g_mutex_unlock (&preroll_lock); + + g_mutex_lock (&preroll_lock); + GST_DEBUG ("Seeking"); + fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1)); + + GST_DEBUG ("wait for new preroll"); + /* this either prerolls or fails */ + g_cond_wait (&preroll_cond, &preroll_lock); + g_mutex_unlock (&preroll_lock); + + GST_DEBUG ("bring pipe to state NULL"); + gst_element_set_state (pipeline, GST_STATE_NULL); + + GST_DEBUG ("Deleting pipeline"); + gst_object_unref (GST_OBJECT (pipeline)); +} + +GST_END_TEST; + +static GMutex handoff_lock; +static GCond handoff_cond; + +static void +test_async_false_seek_in_playing_handoff (GstElement * elem, GstBuffer * buf, + GstPad * pad, gpointer data) +{ + g_mutex_lock (&handoff_lock); + GST_DEBUG ("Got handoff buffer %p", buf); + g_cond_signal (&handoff_cond); + g_mutex_unlock (&handoff_lock); +} + +GST_START_TEST (test_async_false_seek_in_playing) +{ + GstElement *pipeline, *source, *sink; + + /* Create gstreamer elements */ + pipeline = gst_pipeline_new ("test-pipeline"); + source = gst_element_factory_make ("fakesrc", "fake-source"); + sink = gst_element_factory_make ("fakesink", "fake-output"); + + g_object_set (G_OBJECT (sink), "async", FALSE, NULL); + g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL); + + g_signal_connect (sink, "handoff", + G_CALLBACK (test_async_false_seek_in_playing_handoff), NULL); + + /* we add all elements into the pipeline */ + gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); + + /* we link the elements together */ + gst_element_link (source, sink); + + GST_DEBUG ("Now playing"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_mutex_lock (&handoff_lock); + GST_DEBUG ("wait for handoff buffer"); + g_cond_wait (&handoff_cond, &handoff_lock); + g_mutex_unlock (&handoff_lock); + + GST_DEBUG ("Seeking"); + fail_unless (gst_element_seek (source, 1.0, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1)); + + g_mutex_lock (&handoff_lock); + GST_DEBUG ("wait for handoff buffer"); + g_cond_wait (&handoff_cond, &handoff_lock); + g_mutex_unlock (&handoff_lock); + + GST_DEBUG ("bring pipe to state NULL"); + gst_element_set_state (pipeline, GST_STATE_NULL); + + GST_DEBUG ("Deleting pipeline"); + gst_object_unref (GST_OBJECT (pipeline)); +} + +GST_END_TEST; + +/* test: try changing state of sinks */ +static Suite * +gst_sinks_suite (void) +{ + Suite *s = suite_create ("Sinks"); + TCase *tc_chain = tcase_create ("general"); + guint timeout = 10; + + /* time out after 10s, not the default 3, we need this for the last test. + * We need a longer timeout when running under valgrind though. */ + if (g_getenv ("CK_DEFAULT_TIMEOUT") != NULL) + timeout = MAX (10, atoi (g_getenv ("CK_DEFAULT_TIMEOUT"))); + tcase_set_timeout (tc_chain, timeout); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_sink); + tcase_add_test (tc_chain, test_sink_completion); + tcase_add_test (tc_chain, test_src_sink); + tcase_add_test (tc_chain, test_livesrc_remove); + tcase_add_test (tc_chain, test_livesrc_sink); + tcase_add_test (tc_chain, test_livesrc2_sink); + tcase_add_test (tc_chain, test_livesrc3_sink); + tcase_add_test (tc_chain, test_locked_sink); + tcase_add_test (tc_chain, test_unlinked_live); + tcase_add_test (tc_chain, test_delayed_async); + tcase_add_test (tc_chain, test_added_async); + tcase_add_test (tc_chain, test_added_async2); + tcase_add_test (tc_chain, test_add_live); + tcase_add_test (tc_chain, test_add_live2); + tcase_add_test (tc_chain, test_bin_live); + tcase_add_test (tc_chain, test_fake_eos); + tcase_add_test (tc_chain, test_async_done); + tcase_add_test (tc_chain, test_async_done_eos); + tcase_add_test (tc_chain, test_async_false_seek); + tcase_add_test (tc_chain, test_async_false_seek_in_playing); + + return s; +} + +GST_CHECK_MAIN (gst_sinks); diff --git a/tests/check/generic/states.c b/tests/check/generic/states.c new file mode 100644 index 0000000..7f95686 --- /dev/null +++ b/tests/check/generic/states.c @@ -0,0 +1,284 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#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"); + fail_unless (STATE_IGNORE_ELEMENTS != NULL, "Test environment not set up!"); + if (!g_getenv ("GST_NO_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 ()); + + 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 (), + gst_plugin_get_name (plugin)); + + for (f = features; f; f = f->next) { + GstPluginFeature *feature = f->data; + const gchar *name; + gboolean ignore = FALSE; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + continue; + + name = GST_OBJECT_NAME (feature); + + 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, 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 gboolean +element_state_is (GstElement * e, GstState s) +{ + GstStateChangeReturn ret; + GstState state; + + ret = gst_element_get_state (e, &state, NULL, GST_CLOCK_TIME_NONE); + return (ret == GST_STATE_CHANGE_SUCCESS && state == s); +} + +GST_START_TEST (test_state_changes_up_failure) +{ + GstElement *bin; + GstElement *mid[3]; + int n; + + /* we want at least one before and one after */ + g_assert (G_N_ELEMENTS (mid) >= 3); + + /* make a bin */ + bin = gst_element_factory_make ("bin", NULL); + + /* add children */ + for (n = 0; n < G_N_ELEMENTS (mid); ++n) { + const char *element = n != 1 ? "identity" : "fakesink"; + mid[n] = gst_element_factory_make (element, NULL); + gst_bin_add (GST_BIN (bin), mid[n]); + if (n == 1) + g_object_set (mid[n], "async", FALSE, NULL); + } + + /* This one should work */ + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_NULL)); + gst_element_set_state (bin, GST_STATE_READY); + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_READY)); + gst_element_set_state (bin, GST_STATE_NULL); + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_NULL)); + + /* make the middle element fail to switch up */ + g_object_set (mid[1], "state-error", 1 /* null-to-ready */ , NULL); + + /* This one should not */ + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_NULL)); + gst_element_set_state (bin, GST_STATE_READY); + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_NULL)); + gst_element_set_state (bin, GST_STATE_NULL); + for (n = 0; n < G_N_ELEMENTS (mid); ++n) + fail_unless (element_state_is (mid[n], GST_STATE_NULL)); + + /* cleanup */ + gst_object_unref (bin); +} + +GST_END_TEST; + + +static Suite * +states_suite (void) +{ + Suite *s = suite_create ("states_core"); + 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); + tcase_add_test (tc_chain, test_state_changes_up_failure); + + return s; +} + +GST_CHECK_MAIN (states); diff --git a/tests/check/gst/capslist.h b/tests/check/gst/capslist.h new file mode 100644 index 0000000..0991fa8 --- /dev/null +++ b/tests/check/gst/capslist.h @@ -0,0 +1,38 @@ +#include + +/* defines an array of strings named caps_list, that contains a list of caps for + general tests. So if you don't know what caps to use to write a test, just + include this file */ + +static const gchar *caps_list[] = { + "audio/x-adpcm, layout=(string)quicktime; audio/x-adpcm, layout=(string)quicktime; audio/x-adpcm, layout=(string)wav; audio/x-adpcm, layout=(string)wav; audio/x-adpcm, layout=(string)dk3; audio/x-adpcm, layout=(string)dk3; audio/x-adpcm, layout=(string)dk4; audio/x-adpcm, layout=(string)dk4; audio/x-adpcm, layout=(string)westwood; audio/x-adpcm, layout=(string)westwood; audio/x-adpcm, layout=(string)smjpeg; audio/x-adpcm, layout=(string)smjpeg; audio/x-adpcm, layout=(string)microsoft; audio/x-adpcm, layout=(string)microsoft; audio/x-adpcm, layout=(string)4xm; audio/x-adpcm, layout=(string)4xm; audio/x-adpcm, layout=(string)xa; audio/x-adpcm, layout=(string)xa; audio/x-adpcm, layout=(string)adx; audio/x-adpcm, layout=(string)adx; audio/x-adpcm, layout=(string)ea; audio/x-adpcm, layout=(string)ea; audio/x-adpcm, layout=(string)g726; audio/x-adpcm, layout=(string)g726", + "video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)I420; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)YUY2; video/x-raw, format=(string)RGB, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw, format=(string)BGR, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)Y42B; video/x-raw, format=(string)BGRx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)YUV9; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)Y41B; video/x-raw, format=(string)RGB16 ,width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw, format=(string)RGB15, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]", + "video/x-raw, format=(string){ YUY2, I420 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-jpeg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)[ 3, 5 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-3ivx, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)[ 41, 43 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)1, systemstream=(boolean)false, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int){ 576, 480 }; video/x-huffyuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]", + "video/x-raw, format=(string){ YUY2, I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], divxversion=(int)[ 3, 5 ]; video/x-xvid, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-3ivx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], msmpegversion=(int)[ 41, 43 ]; video/mpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], mpegversion=(int)1, systemstream=(boolean)false; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, width=(int)720, height=(int){ 576, 480 }, systemstream=(boolean)false; video/x-huffyuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]", + "video/x-raw, format=(string)BGRx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw, format=(string)RGBx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]", + "video/x-raw, format=(string)BGRx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]", + "video/x-raw, format=(string){ I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]", + "video/x-raw, format=(string) xBGR, framerate = (double) [ 0, max ]", + "video/x-raw, format=(string) RGBx, framerate = (double) [ 0, max ]", + "video/x-raw,\\ format=(string) { RGBA, RGBx, BGRx, BGRA, xRGB, xBGR, ARGB, ABGR }", + /* Test fraction type */ + "test/gst-fraction, fraction = (fraction) 1/8", + "test/gst-fraction, fraction = (fraction) MIN", + "test/gst-fraction, fraction = (fraction) MAX", + /* Test fraction range */ + "test/gst-fraction-range, fraction = (fraction) [ 1/4, 1/3 ]", + "test/gst-fraction-range, fraction = (fraction) [ MIN, MAX ]", + "test/gst-fraction-range, fraction = (fraction) [ 1/MAX, MAX ]", + /* Test lists of fractions and fraction ranges */ + "test/gst-fraction-range, fraction = (fraction) { [ 1/4, 1/3 ], 1/8 }", + "test/gst-fraction-range, fraction = (fraction) { [ 1/4, 1/3 ], [ 1/8, 2/8 ] }", + /* FlagSet */ + "test/gst-flags,thingy=1f394:00ff8ff", + "test/gst-flags,thingy=101ffff1f394:fff00ff00ff8ff", + /* Some random checks */ + "video/x-raw, format = (string) { I420, Y42B, Y444 }, framerate = (fraction) [1/MAX, MAX], width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]", + + "ANY", + "EMPTY" +}; + diff --git a/tests/check/gst/gst.c b/tests/check/gst/gst.c new file mode 100644 index 0000000..fc82763 --- /dev/null +++ b/tests/check/gst/gst.c @@ -0,0 +1,116 @@ +/* GStreamer + * Copyright (C) <2005> Thomas Vander Stichele + * + * gst.c: Unit test for gst.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_init) +{ + /* don't segfault with NULL, NULL */ + gst_init (NULL, NULL); + /* allow calling twice. well, actually, thrice. */ + gst_init (NULL, NULL); +} + +GST_END_TEST; + +GST_START_TEST (test_deinit) +{ + gst_init (NULL, NULL); + + gst_deinit (); +} + +GST_END_TEST; + +GST_START_TEST (test_deinit_sysclock) +{ + GstClock *clock; + + gst_init (NULL, NULL); + + clock = gst_system_clock_obtain (); + gst_object_unref (clock); + + gst_deinit (); +} + +GST_END_TEST; + +/* tests if we can create an element from a compiled-in plugin */ +GST_START_TEST (test_new_pipeline) +{ + GstElement *pipeline; + + pipeline = gst_pipeline_new ("pipeline"); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* tests if we can load an element from a plugin */ +GST_START_TEST (test_new_fakesrc) +{ + GstElement *element; + + element = gst_element_factory_make ("fakesrc", NULL); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_version) +{ + guint major, minor, micro, nano; + gchar *version; + + gst_version (&major, &minor, µ, &nano); + assert_equals_int (major, GST_VERSION_MAJOR); + + version = gst_version_string (); + fail_if (version == NULL); + g_free (version); +} + +GST_END_TEST; + +static Suite * +gst_suite (void) +{ + Suite *s = suite_create ("Gst"); + TCase *tc_chain = tcase_create ("gst tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_init); + tcase_add_test (tc_chain, test_new_pipeline); + tcase_add_test (tc_chain, test_new_fakesrc); + tcase_add_test (tc_chain, test_version); + /* run these last so the others don't fail if CK_FORK=no is being used */ + tcase_add_test (tc_chain, test_deinit_sysclock); + tcase_add_test (tc_chain, test_deinit); + + return s; +} + +GST_CHECK_MAIN (gst); diff --git a/tests/check/gst/gstabi.c b/tests/check/gst/gstabi.c new file mode 100644 index 0000000..6f13b12 --- /dev/null +++ b/tests/check/gst/gstabi.c @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstabi.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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifdef HAVE_CPU_I386 +#ifndef G_OS_WIN32 +#include "struct_i386.h" +#else +#include "struct_i386w.h" +#endif +#define HAVE_ABI_SIZES TRUE +#else +#ifdef __powerpc64__ +#include "struct_ppc64.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef __powerpc__ +#include "struct_ppc32.h" +#define HAVE_ABI_SIZES TRUE +#else +#ifdef HAVE_CPU_X86_64 +#ifndef G_OS_WIN32 +#include "struct_x86_64.h" +#else +#include "struct_x86_64w.h" +#endif +#define HAVE_ABI_SIZES TRUE +#else +#ifdef HAVE_CPU_HPPA +#include "struct_hppa.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef HAVE_CPU_SPARC +#include "struct_sparc.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef HAVE_CPU_ARM +#include "struct_arm.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 +#endif +#endif +#endif +#endif +#endif + +GST_START_TEST (test_ABI) +{ + gst_check_abi_list (list, HAVE_ABI_SIZES); +} + +GST_END_TEST; + +static Suite * +gstabi_suite (void) +{ + Suite *s = suite_create ("GstABI"); + 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 (gstabi); diff --git a/tests/check/gst/gstatomicqueue.c b/tests/check/gst/gstatomicqueue.c new file mode 100644 index 0000000..a516421 --- /dev/null +++ b/tests/check/gst/gstatomicqueue.c @@ -0,0 +1,49 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +GST_START_TEST (test_create_free) +{ + GstAtomicQueue *aq; + + aq = gst_atomic_queue_new (20); + gst_atomic_queue_unref (aq); +} + +GST_END_TEST; + +static Suite * +gst_atomic_queue_suite (void) +{ + Suite *s = suite_create ("GstAtomicQueue"); + TCase *tc_chain = tcase_create ("GstAtomicQueue tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_create_free); + + return s; +} + +GST_CHECK_MAIN (gst_atomic_queue); diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c new file mode 100644 index 0000000..21e6043 --- /dev/null +++ b/tests/check/gst/gstbin.c @@ -0,0 +1,1823 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * Copyright (C) 2005 Thomas Vander Stichele + * + * gstbin.c: Unit test for GstBin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static void +pop_async_done (GstBus * bus) +{ + GstMessage *message; + + GST_DEBUG ("popping async-done message"); + message = gst_bus_poll (bus, GST_MESSAGE_ASYNC_DONE, -1); + + fail_unless (message && GST_MESSAGE_TYPE (message) + == GST_MESSAGE_ASYNC_DONE, "did not get GST_MESSAGE_ASYNC_DONE"); + + gst_message_unref (message); + GST_DEBUG ("popped message"); +} + +static void +pop_messages (GstBus * bus, int count) +{ + GstMessage *message; + + int i; + + GST_DEBUG ("popping %d messages", count); + for (i = 0; i < count; ++i) { + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1); + + fail_unless (message && GST_MESSAGE_TYPE (message) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + gst_message_unref (message); + } + GST_DEBUG ("popped %d messages", count); +} + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static gpointer +push_one_eos (GstPad * pad) +{ + GST_DEBUG_OBJECT (pad, "Pushing EOS event"); + gst_pad_push_event (pad, gst_event_new_eos ()); + + return NULL; +} + +static gpointer +push_one_stream_start (GstPad * pad) +{ + GST_DEBUG_OBJECT (pad, "Pushing STREAM_START event"); + gst_pad_push_event (pad, gst_event_new_stream_start ("test")); + + return NULL; +} + +GST_START_TEST (test_interface) +{ + GstBin *bin, *bin2; + GstElement *filesrc; + GstIterator *it; + GValue item = { 0, }; + + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL, "Could not create bin"); + + filesrc = gst_element_factory_make ("filesrc", NULL); + fail_unless (filesrc != NULL, "Could not create filesrc"); + fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler"); + gst_bin_add (bin, filesrc); + + fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc); + gst_object_unref (filesrc); + + it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER); + fail_unless (it != NULL); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + gst_bin_add_many (bin, + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), NULL); + it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER); + fail_unless (it != NULL); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + bin2 = bin; + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL); + gst_bin_add_many (bin, + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), + GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL); + it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL)); + gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL)); + it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + g_value_unset (&item); + gst_iterator_free (it); + + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_eos) +{ + GstBus *bus; + GstElement *pipeline, *sink1, *sink2; + GstMessage *message; + GstPad *pad1, *pad2; + GThread *thread1, *thread2; + + pipeline = gst_pipeline_new ("test_eos"); + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + + sink1 = gst_element_factory_make ("fakesink", "sink1"); + sink2 = gst_element_factory_make ("fakesink", "sink2"); + + gst_bin_add_many (GST_BIN (pipeline), sink1, sink2, NULL); + + pad1 = gst_check_setup_src_pad_by_name (sink1, &srctemplate, "sink"); + pad2 = gst_check_setup_src_pad_by_name (sink2, &srctemplate, "sink"); + + gst_pad_set_active (pad1, TRUE); + gst_pad_set_active (pad2, TRUE); + + fail_if (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE); + + /* Send one EOS to sink1 */ + thread1 = g_thread_new ("thread1", (GThreadFunc) push_one_eos, pad1); + + /* Make sure the EOS message is not sent */ + message = + gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, 2 * GST_SECOND); + fail_if (message != NULL); + + /* Send one EOS to sink2 */ + thread2 = g_thread_new ("thread2", (GThreadFunc) push_one_eos, pad2); + + /* Make sure the EOS message is sent then */ + message = gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, -1); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS); + gst_message_unref (message); + + /* Cleanup */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_pad_set_active (pad1, FALSE); + gst_pad_set_active (pad2, FALSE); + gst_check_teardown_src_pad (sink1); + gst_check_teardown_src_pad (sink2); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_stream_start) +{ + GstBus *bus; + GstElement *pipeline, *sink1, *sink2; + GstMessage *message; + GstPad *pad1, *pad2; + GThread *thread1, *thread2; + + pipeline = gst_pipeline_new ("test_stream_start"); + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + + sink1 = gst_element_factory_make ("fakesink", "sink1"); + sink2 = gst_element_factory_make ("fakesink", "sink2"); + + gst_bin_add_many (GST_BIN (pipeline), sink1, sink2, NULL); + + pad1 = gst_check_setup_src_pad_by_name (sink1, &srctemplate, "sink"); + pad2 = gst_check_setup_src_pad_by_name (sink2, &srctemplate, "sink"); + + gst_pad_set_active (pad1, TRUE); + gst_pad_set_active (pad2, TRUE); + + fail_if (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE); + + /* Send one STREAM_START to sink1 */ + thread1 = g_thread_new ("thread1", (GThreadFunc) push_one_stream_start, pad1); + + /* Make sure the STREAM_START message is not sent */ + message = + gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_STREAM_START, + 2 * GST_SECOND); + fail_if (message != NULL); + + /* Send one STREAM_START to sink2 */ + thread2 = g_thread_new ("thread2", (GThreadFunc) push_one_stream_start, pad2); + + /* Make sure the STREAM_START message is sent then */ + message = + gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_STREAM_START, -1); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START); + gst_message_unref (message); + + /* Cleanup */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_pad_set_active (pad1, FALSE); + gst_pad_set_active (pad2, FALSE); + gst_check_teardown_src_pad (sink1); + gst_check_teardown_src_pad (sink2); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_message_state_changed) +{ + GstBin *bin; + GstBus *bus; + GstMessage *message; + GstStateChangeReturn ret; + + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL, "Could not create bin"); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 1); + + bus = g_object_new (gst_bus_get_type (), NULL); + gst_object_ref_sink (bus); + gst_element_set_bus (GST_ELEMENT_CAST (bin), bus); + + /* change state, spawning a message, causing an incref on the bin */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (bin, "bin", 2); + + /* get and unref the message, causing a decref on the bin */ + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1); + + fail_unless (message && GST_MESSAGE_TYPE (message) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + gst_message_unref (message); + + ASSERT_OBJECT_REFCOUNT (bin, "bin", 1); + + gst_bus_set_flushing (bus, TRUE); + + /* clean up */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_message_state_changed_child) +{ + GstBin *bin; + GstElement *src; + GstBus *bus; + GstMessage *message; + GstStateChangeReturn ret; + + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL, "Could not create bin"); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 1); + + bus = g_object_new (gst_bus_get_type (), NULL); + gst_object_ref_sink (bus); + gst_element_set_bus (GST_ELEMENT_CAST (bin), bus); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + gst_bin_add (bin, src); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + /* change state, spawning two messages: + * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc + * - second for bin, causing an incref on the bin */ + GST_DEBUG ("setting bin to READY"); + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 2); + + /* get and unref the message, causing a decref on the src */ + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1); + fail_unless (message && GST_MESSAGE_TYPE (message) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + fail_unless (message->src == GST_OBJECT (src)); + gst_message_unref (message); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 2); + + /* get and unref message 2, causing a decref on the bin */ + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1); + fail_unless (message && GST_MESSAGE_TYPE (message) + == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED"); + + fail_unless (message->src == GST_OBJECT (bin)); + gst_message_unref (message); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (bin, "bin", 1); + + gst_bus_set_flushing (bus, TRUE); + + /* clean up */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_message_state_changed_children) +{ + GstPipeline *pipeline; + GstElement *src, *sink; + GstBus *bus; + GstStateChangeReturn ret; + GstState current, pending; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + /* need to silence the element as the deep_notify refcounts the + * parents while running */ + g_object_set (G_OBJECT (src), "silent", TRUE, NULL); + gst_bin_add (GST_BIN (pipeline), src); + + sink = gst_element_factory_make ("fakesink", NULL); + /* need to silence the element as the deep_notify refcounts the + * parents while running */ + g_object_set (G_OBJECT (sink), "silent", TRUE, NULL); + fail_if (sink == NULL, "Could not create fakesink"); + gst_bin_add (GST_BIN (pipeline), sink); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + + bus = gst_pipeline_get_bus (pipeline); + + /* change state to READY, spawning three messages */ + GST_DEBUG ("setting pipeline to READY"); + ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* each object is referenced by a message */ + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 2); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2); + + pop_messages (bus, 3); + fail_if (gst_bus_have_pending (bus), "unexpected pending messages"); + + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* change state to PAUSED, spawning four messages */ + /* STATE_CHANGED (NULL => READY) + * STREAM_START + * ASYNC_DONE + * STATE_CHANGED (READY => PAUSED) + */ + GST_DEBUG ("setting pipeline to PAUSED"); + ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + ret = + gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_PAUSED); + fail_unless (pending == GST_STATE_VOID_PENDING); + + /* wait for async thread to settle down */ + GST_DEBUG ("waiting for refcount"); + while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 4) + THREAD_SWITCH (); + GST_DEBUG ("refcount <= 4 now"); + + /* each object is referenced by a message; + * base_src is blocked in the push and has an extra refcount. + * base_sink_chain has taken a refcount on the sink, and is blocked on + * preroll + * The stream-status messages holds 2 more refs to the element */ + ASSERT_OBJECT_REFCOUNT (src, "src", 4); + /* refcount can be 4 if the bin is still processing the async_done message of + * the sink. */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3); + /* 3 or 4 is valid, because the pipeline might still be posting + * its state_change message */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline", 3, 4); + + pop_messages (bus, 3); + pop_async_done (bus); + fail_if ((gst_bus_pop (bus)) != NULL); + + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 2); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* change state to PLAYING, spawning three messages */ + GST_DEBUG ("setting pipeline to PLAYING"); + ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + ret = + gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_PLAYING); + fail_unless (pending == GST_STATE_VOID_PENDING); + + /* each object is referenced by one message + * src might have an extra reference if it's still pushing + * sink might have an extra reference if it's still blocked on preroll + * pipeline posted a new-clock message too. */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3); + ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 4); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); + + pop_messages (bus, 3); + fail_if ((gst_bus_pop (bus)) != NULL); + + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + /* src might have an extra reference if it's still pushing */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2); + /* sink might have an extra reference if it's still blocked on preroll */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 3); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* go back to READY, spawning six messages */ + GST_DEBUG ("setting pipeline to READY"); + ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* each object is referenced by two messages, the source also has the + * stream-status message referencing it */ + ASSERT_OBJECT_REFCOUNT (src, "src", 4); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 3); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); + + pop_messages (bus, 6); + fail_if ((gst_bus_pop (bus)) != NULL); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* setting pipeline to NULL flushes the bus automatically */ + ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + /* clean up */ + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_watch_for_state_change) +{ + GstElement *src, *sink, *bin; + GstBus *bus; + GstStateChangeReturn ret; + + bin = gst_element_factory_make ("bin", NULL); + fail_unless (bin != NULL, "Could not create bin"); + + bus = g_object_new (gst_bus_get_type (), NULL); + gst_object_ref_sink (bus); + gst_element_set_bus (GST_ELEMENT_CAST (bin), bus); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (bin), src); + + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + /* change state, spawning two times three messages */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + ret = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + pop_messages (bus, 6); + pop_async_done (bus); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + pop_messages (bus, 3); + + /* this one might return either SUCCESS or ASYNC, likely SUCCESS */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE); + + pop_messages (bus, 3); + if (ret == GST_STATE_CHANGE_ASYNC) + pop_async_done (bus); + + fail_unless (gst_bus_have_pending (bus) == FALSE, + "Unexpected messages on bus"); + + gst_bus_set_flushing (bus, TRUE); + + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* clean up */ + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_state_change_error_message) +{ + GstElement *src, *sink, *bin; + GstBus *bus; + GstStateChangeReturn ret; + + bin = gst_element_factory_make ("bin", NULL); + fail_unless (bin != NULL, "Could not create bin"); + + bus = g_object_new (gst_bus_get_type (), NULL); + gst_object_ref_sink (bus); + gst_element_set_bus (GST_ELEMENT_CAST (bin), bus); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + /* add but don't link elements */ + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (bin), src); + + /* change state, this should succeed */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* now wait, the streaming thread will error because the source is not + * linked. */ + ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_FAILURE); + + gst_bus_set_flushing (bus, TRUE); + + /* setting bin to NULL flushes the bus automatically */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* clean up */ + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + + +/* adding an element with linked pads to a bin unlinks the + * pads */ +GST_START_TEST (test_add_linked) +{ + GstElement *src, *sink; + GstPad *srcpad, *sinkpad; + GstElement *pipeline; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless (sinkpad != NULL); + + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK); + + /* pads are linked now */ + fail_unless (gst_pad_is_linked (srcpad)); + fail_unless (gst_pad_is_linked (sinkpad)); + + /* adding element to bin voids hierarchy so pads are unlinked */ + gst_bin_add (GST_BIN (pipeline), src); + + /* check if pads really are unlinked */ + fail_unless (!gst_pad_is_linked (srcpad)); + fail_unless (!gst_pad_is_linked (sinkpad)); + + /* cannot link pads in wrong hierarchy */ + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY); + + /* adding other element to bin as well */ + gst_bin_add (GST_BIN (pipeline), sink); + + /* now we can link again */ + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK); + + /* check if pads really are linked */ + fail_unless (gst_pad_is_linked (srcpad)); + fail_unless (gst_pad_is_linked (sinkpad)); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* adding ourself should fail */ +GST_START_TEST (test_add_self) +{ + GstElement *bin; + + bin = gst_bin_new (NULL); + fail_unless (bin != NULL, "Could not create bin"); + + ASSERT_CRITICAL (gst_bin_add (GST_BIN (bin), bin)); + + gst_object_unref (bin); +} + +GST_END_TEST; + + +/* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */ + +#define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num) \ + { \ + GstMessage *msg; \ + GstState old = 0, new = 0, pending = 0; \ + msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); \ + fail_if (msg == NULL, "No state change message within 1 second (#" \ + G_STRINGIFY (num) ")"); \ + gst_message_parse_state_changed (msg, &old, &new, &pending); \ + fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element) \ + " should have changed state next (#" G_STRINGIFY (num) ")"); \ + fail_if (old != old_state || new != new_state, "state change is not " \ + G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state)); \ + gst_message_unref (msg); \ + } + +GST_START_TEST (test_children_state_change_order_flagged_sink) +{ + GstElement *src, *identity, *sink, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstBus *bus; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL, "Pipeline has no bus?!"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + g_object_set (src, "num-buffers", 5, NULL); + + identity = gst_element_factory_make ("identity", NULL); + fail_if (identity == NULL, "Could not create identity"); + + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL); + + fail_unless (gst_element_link (src, identity) == TRUE); + fail_unless (gst_element_link (identity, sink) == TRUE); + + /* (1) Test state change with fakesink being a regular sink */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_if (ret != GST_STATE_CHANGE_ASYNC, + "State change to PLAYING did not return ASYNC"); + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed"); + fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed"); + fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed"); + + /* NULL => READY */ + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102); + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103); + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104); + + /* READY => PAUSED */ + /* because of pre-rolling, sink will return ASYNC on state + * change and change state later when it has a buffer */ + GST_DEBUG ("popping READY -> PAUSED messages"); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED, + 105); +#if 0 + /* From here on, all bets are off. Usually the source changes state next, + * but it might just as well be that the first buffer produced by the + * source reaches the sink before the source has finished its state change, + * in which case the sink will commit its new state before the source ... */ + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106); + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107); +#else + + pop_messages (bus, 2); /* pop remaining ready => paused messages off the bus */ + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED, + 108); + pop_async_done (bus); +#endif + /* PAUSED => PLAYING */ + GST_DEBUG ("popping PAUSED -> PLAYING messages"); + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING, + 110); + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111); + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING, + 112); + + /* don't set to NULL that will set the bus flushing and kill our messages */ + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed"); + ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed"); + + /* TODO: do we need to check downwards state change order as well? */ + pop_messages (bus, 4); /* pop playing => paused messages off the bus */ + pop_messages (bus, 4); /* pop paused => ready messages off the bus */ + + while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1) + THREAD_SWITCH (); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed"); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + + +GST_START_TEST (test_children_state_change_order_semi_sink) +{ + GstElement *src, *identity, *sink, *pipeline; + GstStateChangeReturn ret; + GstState current, pending; + GstBus *bus; + + /* (2) Now again, but check other code path where we don't have + * a proper sink correctly flagged as such, but a 'semi-sink' */ + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL, "Pipeline has no bus?!"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + + identity = gst_element_factory_make ("identity", NULL); + fail_if (identity == NULL, "Could not create identity"); + + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL); + + fail_unless (gst_element_link (src, identity) == TRUE); + fail_unless (gst_element_link (identity, sink) == TRUE); + + /* this is not very nice but should work just fine in this case. */ + GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_FLAG_SINK); /* <======== */ + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC"); + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed"); + fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed"); + fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed"); + + /* NULL => READY */ + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202); + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203); + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204); + + /* READY => PAUSED */ + /* because of pre-rolling, sink will return ASYNC on state + * change and change state later when it has a buffer */ + GST_DEBUG ("popping READY -> PAUSED messages"); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED, + 205); +#if 0 + /* From here on, all bets are off. Usually the source changes state next, + * but it might just as well be that the first buffer produced by the + * source reaches the sink before the source has finished its state change, + * in which case the sink will commit its new state before the source ... */ + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206); + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207); +#else + pop_messages (bus, 2); /* pop remaining ready => paused messages off the bus */ + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED, + 208); + pop_async_done (bus); + + /* PAUSED => PLAYING */ + GST_DEBUG ("popping PAUSED -> PLAYING messages"); + ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209); + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING, + 210); + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211); + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING, + 212); +#endif + + /* don't set to NULL that will set the bus flushing and kill our messages */ + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed"); + + /* TODO: do we need to check downwards state change order as well? */ + pop_messages (bus, 4); /* pop playing => paused messages off the bus */ + pop_messages (bus, 4); /* pop paused => ready messages off the bus */ + + GST_DEBUG ("waiting for pipeline to reach refcount 1"); + while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1) + THREAD_SWITCH (); + + GST_DEBUG ("checking refcount"); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed"); + + GST_DEBUG ("checking refcount"); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + GST_DEBUG ("cleanup"); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_children_state_change_order_two_sink) +{ + GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline; + GstStateChangeReturn ret; + GstBus *bus; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL, "Pipeline has no bus?!"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + + tee = gst_element_factory_make ("tee", NULL); + fail_if (tee == NULL, "Could not create tee"); + + identity = gst_element_factory_make ("identity", NULL); + fail_if (identity == NULL, "Could not create identity"); + + sink1 = gst_element_factory_make ("fakesink", NULL); + fail_if (sink1 == NULL, "Could not create fakesink1"); + + sink2 = gst_element_factory_make ("fakesink", NULL); + fail_if (sink2 == NULL, "Could not create fakesink2"); + + gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL); + + fail_unless (gst_element_link (src, tee) == TRUE); + fail_unless (gst_element_link (tee, identity) == TRUE); + fail_unless (gst_element_link (identity, sink1) == TRUE); + fail_unless (gst_element_link (tee, sink2) == TRUE); + + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed"); + + /* NULL => READY */ + { + GstMessage *msg; + GstState old = 0, new = 0, pending = 0; + GstObject *first, *second; + + msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); + fail_if (msg == NULL, "No state change message within 1 second (#201)"); + + gst_message_parse_state_changed (msg, &old, &new, &pending); + first = gst_object_ref (msg->src); + + fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2), + "sink1 or sink2 should have changed state next #(202)"); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); + fail_if (msg == NULL, "No state change message within 1 second (#201)"); + + gst_message_parse_state_changed (msg, &old, &new, &pending); + second = gst_object_ref (msg->src); + + fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2), + "sink1 or sink2 should have changed state next #(202)"); + gst_message_unref (msg); + + fail_if (second == first, "got state change from same object"); + + gst_object_unref (first); + gst_object_unref (second); + } + ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203); + ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204); + ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205); + ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (tee, "tee", 1); + ASSERT_OBJECT_REFCOUNT (identity, "identity", 1); + ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1); + ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed"); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (tee, "tee", 1); + ASSERT_OBJECT_REFCOUNT (identity, "identity", 1); + ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1); + ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_iterate_sorted) +{ + GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline, *bin; + GstIterator *it; + GValue elem = { 0, }; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bin = gst_bin_new (NULL); + fail_unless (bin != NULL, "Could not create bin"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + + tee = gst_element_factory_make ("tee", NULL); + fail_if (tee == NULL, "Could not create tee"); + + sink1 = gst_element_factory_make ("fakesink", NULL); + fail_if (sink1 == NULL, "Could not create fakesink1"); + + gst_bin_add_many (GST_BIN (bin), src, tee, sink1, NULL); + + fail_unless (gst_element_link (src, tee) == TRUE); + fail_unless (gst_element_link (tee, sink1) == TRUE); + + identity = gst_element_factory_make ("identity", NULL); + fail_if (identity == NULL, "Could not create identity"); + + sink2 = gst_element_factory_make ("fakesink", NULL); + fail_if (sink2 == NULL, "Could not create fakesink2"); + + gst_bin_add_many (GST_BIN (pipeline), bin, identity, sink2, NULL); + + fail_unless (gst_element_link (tee, identity) == TRUE); + fail_unless (gst_element_link (identity, sink2) == TRUE); + + it = gst_bin_iterate_sorted (GST_BIN (pipeline)); + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) sink2); + g_value_reset (&elem); + + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) identity); + g_value_reset (&elem); + + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) bin); + g_value_reset (&elem); + + g_value_unset (&elem); + gst_iterator_free (it); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_iterate_sorted_unlinked) +{ + GstElement *pipeline, *src, *sink, *identity; + GstIterator *it; + GValue elem = { 0, }; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink1"); + + identity = gst_element_factory_make ("identity", NULL); + fail_if (identity == NULL, "Could not create identity"); + + gst_bin_add_many (GST_BIN (pipeline), sink, identity, src, NULL); + + /* If elements aren't linked, we should end up with: + * * sink elements always first + * * source elements always last + * * any other elements in between + */ + + it = gst_bin_iterate_sorted (GST_BIN (pipeline)); + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) sink); + g_value_reset (&elem); + + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) identity); + g_value_reset (&elem); + + fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&elem) == (gpointer) src); + g_value_reset (&elem); + + g_value_unset (&elem); + gst_iterator_free (it); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static void +test_link_structure_change_state_changed_sync_cb (GstBus * bus, + GstMessage * message, gpointer data) +{ + GstPipeline *pipeline = GST_PIPELINE (data); + GstElement *src, *identity, *sink; + GstState old, snew, pending; + + sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); + fail_unless (sink != NULL, "Could not get sink"); + + gst_message_parse_state_changed (message, &old, &snew, &pending); + if (message->src != GST_OBJECT (sink) || snew != GST_STATE_READY) { + gst_object_unref (sink); + return; + } + + src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); + fail_unless (src != NULL, "Could not get src"); + + identity = gst_bin_get_by_name (GST_BIN (pipeline), "identity"); + fail_unless (identity != NULL, "Could not get identity"); + + /* link src to identity, the pipeline should detect the new link and + * resync the state change */ + fail_unless (gst_element_link (src, identity) == TRUE); + + gst_object_unref (src); + gst_object_unref (identity); + gst_object_unref (sink); +} + +GST_START_TEST (test_link_structure_change) +{ + GstElement *src, *identity, *sink, *pipeline; + GstBus *bus; + GstState state; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + fail_unless (bus != NULL, "Could not get bus"); + + /* use the sync signal handler to link elements while the pipeline is still + * doing the state change */ + gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline, NULL); + g_object_connect (bus, "signal::sync-message::state-changed", + G_CALLBACK (test_link_structure_change_state_changed_sync_cb), pipeline, + NULL); + + src = gst_element_factory_make ("fakesrc", "src"); + fail_if (src == NULL, "Could not create fakesrc"); + + identity = gst_element_factory_make ("identity", "identity"); + fail_if (identity == NULL, "Could not create identity"); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL, "Could not create fakesink1"); + + gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL); + + gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + /* the state change will be done on src only if the pipeline correctly resyncs + * after that fakesrc has been linked to identity */ + gst_element_get_state (src, &state, NULL, 0); + fail_unless_equals_int (state, GST_STATE_READY); + + /* clean up */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstBusSyncReply +sync_handler_remove_sink (GstBus * bus, GstMessage * message, gpointer data) +{ + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) { + GstElement *child; + + child = gst_bin_get_by_name (GST_BIN (data), "fakesink"); + fail_unless (child != NULL, "Could not find fakesink"); + + gst_bin_remove (GST_BIN (data), child); + gst_object_unref (child); + } + return GST_BUS_PASS; +} + +GST_START_TEST (test_state_failure_remove) +{ + GstElement *src, *sink, *pipeline; + GstBus *bus; + GstStateChangeReturn ret; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", "fakesrc"); + fail_unless (src != NULL, "Could not create fakesrc"); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL, "Could not create fakesink"); + + g_object_set (sink, "state-error", 1, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + gst_element_link (src, sink); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + fail_unless (bus != NULL, "Could not get bus"); + + gst_bus_set_sync_handler (bus, sync_handler_remove_sink, pipeline, NULL); + + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, + "did not get state change success"); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_many_bins) +{ + GstStateChangeReturn ret; + GstElement *src, *sink, *pipeline, *last_bin = NULL; + gint i; + +#define NUM_BINS 2000 + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", "fakesrc"); + fail_unless (src != NULL, "Could not create fakesrc"); + g_object_set (src, "num-buffers", 3, NULL); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL, "Could not create fakesink"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + + for (i = 0; i < NUM_BINS; ++i) { + GstElement *bin, *identity; + GstPad *srcpad, *sinkpad; + + bin = gst_bin_new (NULL); + fail_unless (bin != NULL, "Could not create bin %d", i); + identity = gst_element_factory_make ("identity", "identity"); + fail_unless (identity != NULL, "Could not create identity %d", i); + g_object_set (identity, "silent", TRUE, NULL); + gst_bin_add (GST_BIN (bin), identity); + sinkpad = gst_element_get_static_pad (identity, "sink"); + srcpad = gst_element_get_static_pad (identity, "src"); + gst_element_add_pad (bin, gst_ghost_pad_new ("sink", sinkpad)); + gst_element_add_pad (bin, gst_ghost_pad_new ("src", srcpad)); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + + gst_bin_add (GST_BIN (pipeline), bin); + + if (last_bin == NULL) { + srcpad = gst_element_get_static_pad (src, "src"); + } else { + srcpad = gst_element_get_static_pad (last_bin, "src"); + } + sinkpad = gst_element_get_static_pad (bin, "sink"); + gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + + + last_bin = bin; + + /* insert some queues to limit the number of function calls in a row */ + if ((i % 100) == 0) { + GstElement *q = gst_element_factory_make ("queue", NULL); + + GST_LOG ("bin #%d, inserting queue", i); + gst_bin_add (GST_BIN (pipeline), q); + fail_unless (gst_element_link (last_bin, q)); + last_bin = q; + } + } + + fail_unless (gst_element_link (last_bin, sink)); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC); + + for (i = 0; i < 15; ++i) { + GST_INFO ("waiting for preroll ..."); + ret = gst_element_get_state (pipeline, NULL, NULL, GST_SECOND); + if (ret != GST_STATE_CHANGE_ASYNC) + break; + } + fail_unless_equals_int (ret, GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstPadProbeReturn +fakesrc_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, void *arg) +{ + GstPipeline *pipeline = (GstPipeline *) arg; + GstElement *src, *sink; + + src = gst_bin_get_by_name (GST_BIN (pipeline), "fakesrc"); + fail_unless (src != NULL, "Could not get fakesrc"); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL, "Could not create fakesink"); + + g_object_set (sink, "state-error", 1, NULL); + gst_bin_add (GST_BIN (pipeline), sink); + + gst_element_link (src, sink); + gst_element_sync_state_with_parent (sink); + gst_object_unref (src); + + return GST_PAD_PROBE_REMOVE; +} + +GST_START_TEST (test_state_failure_unref) +{ + GstElement *src, *pipeline; + GstPad *srcpad; + GstBus *bus; + GstStateChangeReturn ret; + GstMessage *msg; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", "fakesrc"); + fail_unless (src != NULL, "Could not create fakesrc"); + + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL, "Could not get fakesrc srcpad"); + + gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + fakesrc_pad_blocked_cb, pipeline, NULL); + gst_object_unref (srcpad); + + gst_bin_add (GST_BIN (pipeline), src); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + fail_unless (bus != NULL, "Could not get bus"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* Wait for an error message from our fakesink (added from the + pad block callback). */ + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, GST_SECOND); + fail_if (msg == NULL, "No error message within 1 second"); + gst_message_unref (msg); + + /* Check that after this failure, we can still stop, and then unref, the + pipeline. This should always be possible. */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed"); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static void +on_sync_bus_error (GstBus * bus, GstMessage * msg) +{ + fail_if (msg != NULL); +} + +GST_START_TEST (test_state_change_skip) +{ + GstElement *sink, *pipeline; + GstStateChangeReturn ret; + GstBus *bus; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + fail_unless (bus != NULL, "Could not get bus"); + + /* no errors */ + gst_bus_enable_sync_message_emission (bus); + g_signal_connect (bus, "sync-message::error", (GCallback) on_sync_bus_error, + NULL); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL, "Could not create fakesink"); + gst_element_set_state (sink, GST_STATE_PAUSED); + + g_object_set (sink, "state-error", 5, NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_object_set (sink, "state-error", 0, NULL); + + /* Check that after this failure, we can still stop, and then unref, the + pipeline. This should always be possible. */ + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed"); + + gst_object_unref (pipeline); + gst_object_unref (bus); +} + +GST_END_TEST; + +GST_START_TEST (test_duration_is_max) +{ + GstElement *bin, *src[3], *sink[3]; + GstStateChangeReturn state_res; + GstFormat format = GST_FORMAT_BYTES; + gboolean res; + gint64 duration; + GstBus *bus; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + + /* 3 sources, an adder and a fakesink */ + src[0] = gst_element_factory_make ("fakesrc", NULL); + src[1] = gst_element_factory_make ("fakesrc", NULL); + src[2] = gst_element_factory_make ("fakesrc", NULL); + sink[0] = gst_element_factory_make ("fakesink", NULL); + sink[1] = gst_element_factory_make ("fakesink", NULL); + sink[2] = gst_element_factory_make ("fakesink", NULL); + gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], sink[0], sink[1], + sink[2], NULL); + + gst_element_link (src[0], sink[0]); + gst_element_link (src[1], sink[1]); + gst_element_link (src[2], sink[2]); + + /* irks, duration is reset on basesrc */ + state_res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + /* set durations on src */ + GST_BASE_SRC (src[0])->segment.duration = 1000; + GST_BASE_SRC (src[1])->segment.duration = 3000; + GST_BASE_SRC (src[2])->segment.duration = 2000; + + /* set to playing */ + state_res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + state_res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration); + fail_unless (res, NULL); + + ck_assert_int_eq (duration, 3000); + + bus = gst_element_get_bus (bin); + gst_bus_set_flushing (bus, TRUE); + gst_object_unref (bus); + + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_duration_unknown_overrides) +{ + GstElement *bin, *src[3], *sink[3]; + GstStateChangeReturn state_res; + GstFormat format = GST_FORMAT_BYTES; + gboolean res; + gint64 duration; + GstBus *bus; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + + /* 3 sources, an adder and a fakesink */ + src[0] = gst_element_factory_make ("fakesrc", NULL); + src[1] = gst_element_factory_make ("fakesrc", NULL); + src[2] = gst_element_factory_make ("fakesrc", NULL); + sink[0] = gst_element_factory_make ("fakesink", NULL); + sink[1] = gst_element_factory_make ("fakesink", NULL); + sink[2] = gst_element_factory_make ("fakesink", NULL); + gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], sink[0], sink[1], + sink[2], NULL); + + gst_element_link (src[0], sink[0]); + gst_element_link (src[1], sink[1]); + gst_element_link (src[2], sink[2]); + + /* irks, duration is reset on basesrc */ + state_res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + /* set durations on src */ + GST_BASE_SRC (src[0])->segment.duration = GST_CLOCK_TIME_NONE; + GST_BASE_SRC (src[1])->segment.duration = 3000; + GST_BASE_SRC (src[2])->segment.duration = 2000; + + /* set to playing */ + state_res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + state_res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration); + fail_unless (res, NULL); + + ck_assert_int_eq (duration, GST_CLOCK_TIME_NONE); + + bus = gst_element_get_bus (bin); + gst_bus_set_flushing (bus, TRUE); + gst_object_unref (bus); + + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bin); +} + +GST_END_TEST; + +static gboolean +element_in_list (GList ** list, GstElement * element) +{ + GList *l = g_list_find (*list, element); + + if (l == NULL) + return FALSE; + + *list = g_list_delete_link (*list, l); + return TRUE; +} + +#define element_was_added(e) element_in_list(&added,e) +#define element_was_removed(e) element_in_list(&removed,e) + +static void +add_cb (GstBin * pipeline, GstBin * bin, GstElement * element, GList ** list) +{ + fail_unless (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (bin)); + + *list = g_list_prepend (*list, element); +} + +static void +remove_cb (GstBin * pipeline, GstBin * bin, GstElement * element, GList ** list) +{ + *list = g_list_prepend (*list, element); +} + +GST_START_TEST (test_deep_added_removed) +{ + GstElement *pipe, *e, *bin0, *bin1; + gulong id_removed, id_added; + GList *removed = NULL; + GList *added = NULL; + + pipe = gst_pipeline_new (NULL); + + id_added = g_signal_connect (pipe, "deep-element-added", + G_CALLBACK (add_cb), &added); + id_removed = g_signal_connect (pipe, "deep-element-removed", + G_CALLBACK (remove_cb), &removed); + + /* simple add/remove */ + e = gst_element_factory_make ("identity", NULL); + gst_bin_add (GST_BIN (pipe), e); + fail_unless (element_was_added (e)); + gst_bin_remove (GST_BIN (pipe), e); + fail_unless (element_was_removed (e)); + + /* let's try with a deeper hierarchy, construct it from top-level down */ + bin0 = gst_bin_new (NULL); + gst_bin_add (GST_BIN (pipe), bin0); + bin1 = gst_bin_new (NULL); + gst_bin_add (GST_BIN (bin0), bin1); + e = gst_element_factory_make ("identity", NULL); + gst_bin_add (GST_BIN (bin1), e); + fail_unless (element_was_added (bin0)); + fail_unless (element_was_added (bin1)); + fail_unless (element_was_added (e)); + fail_unless (added == NULL); + fail_unless (removed == NULL); + + gst_object_ref (e); /* keep e alive */ + gst_bin_remove (GST_BIN (bin1), e); + fail_unless (element_was_removed (e)); + fail_unless (added == NULL); + fail_unless (removed == NULL); + + /* now add existing bin hierarchy to pipeline (first remove it so we can re-add it) */ + gst_object_ref (bin0); /* keep bin0 alive */ + gst_bin_remove (GST_BIN (pipe), bin0); + fail_unless (element_was_removed (bin0)); + fail_unless (element_was_removed (bin1)); + fail_unless (added == NULL); + fail_unless (removed == NULL); + + /* re-adding element to removed bin should not trigger our callbacks */ + gst_bin_add (GST_BIN (bin1), e); + fail_unless (added == NULL); + fail_unless (removed == NULL); + + gst_bin_add (GST_BIN (pipe), bin0); + fail_unless (element_was_added (bin0)); + fail_unless (element_was_added (bin1)); + fail_unless (element_was_added (e)); + fail_unless (added == NULL); + fail_unless (removed == NULL); + gst_object_unref (bin0); + gst_object_unref (e); + + /* disconnect signals, unref will trigger remove callbacks otherwise */ + g_signal_handler_disconnect (pipe, id_added); + g_signal_handler_disconnect (pipe, id_removed); + + gst_object_unref (pipe); +} + +GST_END_TEST; + +#define _GST_CHECK_BIN_SUPPRESSED_FLAGS(element_flags, suppressed_flags, \ + expected_flags) \ +G_STMT_START { \ + GstBin *bin = GST_BIN (gst_bin_new ("test-bin")); \ + GstElement *element = gst_element_factory_make ("identity", "test-i"); \ + GstElementFlags natural_flags = GST_OBJECT_FLAGS (bin); \ + GST_OBJECT_FLAG_SET (element, element_flags); \ + gst_bin_set_suppressed_flags (bin, suppressed_flags); \ + gst_bin_add (bin, element); \ + fail_unless ((natural_flags | GST_OBJECT_FLAGS (bin)) \ + == expected_flags); \ + gst_object_unref (bin); \ +} G_STMT_END + +GST_START_TEST (test_suppressed_flags) +{ + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE, + 0, GST_ELEMENT_FLAG_SOURCE); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE, + GST_ELEMENT_FLAG_SOURCE, 0); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE, + GST_ELEMENT_FLAG_SINK, GST_ELEMENT_FLAG_SOURCE); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE | + GST_ELEMENT_FLAG_PROVIDE_CLOCK, + GST_ELEMENT_FLAG_PROVIDE_CLOCK, GST_ELEMENT_FLAG_SOURCE); + + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK, + 0, GST_ELEMENT_FLAG_SINK); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK, + GST_ELEMENT_FLAG_SINK, 0); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK, + GST_ELEMENT_FLAG_SOURCE, GST_ELEMENT_FLAG_SINK); + + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK, + 0, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK, + GST_ELEMENT_FLAG_PROVIDE_CLOCK, 0); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK, + GST_ELEMENT_FLAG_REQUIRE_CLOCK, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK, + 0, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK, + GST_ELEMENT_FLAG_REQUIRE_CLOCK, 0); + _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK, + GST_ELEMENT_FLAG_PROVIDE_CLOCK, GST_ELEMENT_FLAG_REQUIRE_CLOCK); +} + +GST_END_TEST; + + +#define _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL(suppressed_flags) \ +G_STMT_START { \ + GstBin *bin = GST_BIN (gst_bin_new ("test-bin")); \ + GstElement *element = gst_element_factory_make ("identity", "test-i"); \ + GST_OBJECT_FLAG_SET (bin, suppressed_flags); \ + gst_bin_set_suppressed_flags (bin, suppressed_flags); \ + GST_OBJECT_FLAG_SET (element, suppressed_flags); \ + fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \ + == suppressed_flags); \ + gst_bin_add (bin, element); \ + fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \ + == suppressed_flags); \ + gst_bin_remove (bin, element); \ + fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \ + == suppressed_flags); \ + gst_object_unref (bin); \ +} G_STMT_END + +GST_START_TEST (test_suppressed_flags_when_removing) +{ + _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_SOURCE); + _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_SINK); + _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_REQUIRE_CLOCK); + _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_PROVIDE_CLOCK); +} + +GST_END_TEST; + +static Suite * +gst_bin_suite (void) +{ + Suite *s = suite_create ("GstBin"); + TCase *tc_chain = tcase_create ("bin tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_interface); + tcase_add_test (tc_chain, test_eos); + tcase_add_test (tc_chain, test_stream_start); + tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink); + tcase_add_test (tc_chain, test_children_state_change_order_semi_sink); + tcase_add_test (tc_chain, test_children_state_change_order_two_sink); + tcase_add_test (tc_chain, test_message_state_changed); + tcase_add_test (tc_chain, test_message_state_changed_child); + tcase_add_test (tc_chain, test_message_state_changed_children); + tcase_add_test (tc_chain, test_watch_for_state_change); + tcase_add_test (tc_chain, test_state_change_error_message); + tcase_add_test (tc_chain, test_add_linked); + tcase_add_test (tc_chain, test_add_self); + tcase_add_test (tc_chain, test_iterate_sorted); + tcase_add_test (tc_chain, test_iterate_sorted_unlinked); + tcase_add_test (tc_chain, test_link_structure_change); + tcase_add_test (tc_chain, test_state_failure_remove); + tcase_add_test (tc_chain, test_state_failure_unref); + tcase_add_test (tc_chain, test_state_change_skip); + tcase_add_test (tc_chain, test_duration_is_max); + tcase_add_test (tc_chain, test_duration_unknown_overrides); + tcase_add_test (tc_chain, test_deep_added_removed); + tcase_add_test (tc_chain, test_suppressed_flags); + tcase_add_test (tc_chain, test_suppressed_flags_when_removing); + + /* fails on OSX build bot for some reason, and is a bit silly anyway */ + if (0) + tcase_add_test (tc_chain, test_many_bins); + + return s; +} + +GST_CHECK_MAIN (gst_bin); diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c new file mode 100644 index 0000000..4121b70 --- /dev/null +++ b/tests/check/gst/gstbuffer.c @@ -0,0 +1,918 @@ +/* GStreamer + * + * unit test for GstBuffer + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +GST_START_TEST (test_subbuffer) +{ + GstBuffer *buffer, *sub; + GstMapInfo info, sinfo; + + buffer = gst_buffer_new_and_alloc (4); + + /* check sizes, buffer starts out empty */ + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + fail_unless (info.size == 4, "buffer has wrong size"); + fail_unless (info.maxsize >= 4, "buffer has wrong size"); + memset (info.data, 0, 4); + gst_buffer_unmap (buffer, &info); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + /* set some metadata */ + GST_BUFFER_TIMESTAMP (buffer) = 1; + GST_BUFFER_DURATION (buffer) = 2; + GST_BUFFER_OFFSET (buffer) = 3; + GST_BUFFER_OFFSET_END (buffer) = 4; + + sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 2); + fail_if (sub == NULL, "copy region of buffer returned NULL"); + + fail_unless (gst_buffer_map (sub, &sinfo, GST_MAP_READ)); + fail_unless (sinfo.size == 2, "subbuffer has wrong size"); + fail_unless (memcmp (info.data + 1, sinfo.data, 2) == 0, + "subbuffer contains the wrong data"); + ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1); + fail_unless (GST_BUFFER_TIMESTAMP (sub) == -1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_DURATION (sub) == -1, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET (sub) == -1, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == -1, + "subbuffer has wrong offset end"); + gst_buffer_unmap (sub, &sinfo); + gst_buffer_unref (sub); + + /* create a subbuffer of size 0 */ + sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 0); + fail_if (sub == NULL, "copy_region of buffer returned NULL"); + fail_unless (gst_buffer_map (sub, &sinfo, GST_MAP_READ)); + fail_unless (sinfo.size == 0, "subbuffer has wrong size"); + ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1); + gst_buffer_unmap (sub, &sinfo); + gst_buffer_unref (sub); + + /* test if metadata is coppied, not a complete buffer copy so only the + * timestamp and offset fields are copied. */ + sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 1); + fail_if (sub == NULL, "copy_region of buffer returned NULL"); + fail_unless (gst_buffer_get_size (sub) == 1, "subbuffer has wrong size"); + fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_OFFSET (sub) == 3, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_DURATION (sub) == -1, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == -1, + "subbuffer has wrong offset end"); + gst_buffer_unref (sub); + + /* test if metadata is coppied, a complete buffer is copied so all the timing + * fields should be copied. */ + sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 4); + fail_if (sub == NULL, "copy_region of buffer returned NULL"); + fail_unless (gst_buffer_get_size (sub) == 4, "subbuffer has wrong size"); + fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_DURATION (sub) == 2, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET (sub) == 3, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == 4, + "subbuffer has wrong offset end"); + + /* clean up */ + gst_buffer_unref (sub); + + gst_buffer_unmap (buffer, &info); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_span) +{ + GstBuffer *buffer, *sub1, *sub2, *span; + GstMapInfo info; + + buffer = gst_buffer_new_and_alloc (4); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + memcpy (info.data, "data", 4); + gst_buffer_unmap (buffer, &info); + + ASSERT_CRITICAL (gst_buffer_append (NULL, NULL)); + ASSERT_CRITICAL (gst_buffer_append (buffer, NULL)); + ASSERT_CRITICAL (gst_buffer_append (NULL, buffer)); + + sub1 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 2); + fail_if (sub1 == NULL, "copy_region of buffer returned NULL"); + + sub2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 2, 2); + fail_if (sub2 == NULL, "copy_region of buffer returned NULL"); + + ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1); + ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1); + ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1); + + /* span will create a new subbuffer from the parent */ + gst_buffer_ref (sub1); + gst_buffer_ref (sub2); + span = gst_buffer_append (sub1, sub2); + fail_unless (gst_buffer_map (span, &info, GST_MAP_READ)); + fail_unless (info.size == 4, "spanned buffer is wrong size"); + ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1); + ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1); + ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1); + ASSERT_BUFFER_REFCOUNT (span, "span", 1); + fail_unless (memcmp (info.data, "data", 4) == 0, + "spanned buffer contains the wrong data"); + gst_buffer_unmap (span, &info); + gst_buffer_unref (span); + ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1); + + /* span from non-contiguous buffers will create new buffers */ + gst_buffer_ref (sub1); + gst_buffer_ref (sub2); + span = gst_buffer_append (sub2, sub1); + fail_unless (gst_buffer_map (span, &info, GST_MAP_READ)); + fail_unless (info.size == 4, "spanned buffer is wrong size"); + ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1); + ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1); + ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1); + ASSERT_BUFFER_REFCOUNT (span, "span", 1); + fail_unless (memcmp (info.data, "tada", 4) == 0, + "spanned buffer contains the wrong data"); + gst_buffer_unmap (span, &info); + gst_buffer_unref (span); + ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1); + + /* clean up */ + gst_buffer_unref (sub1); + gst_buffer_unref (sub2); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + + +static const char ro_memory[] = "abcdefghijklmnopqrstuvwxyz"; + +static GstBuffer * +create_read_only_buffer (void) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + + /* assign some read-only data to the new buffer */ + gst_buffer_insert_memory (buf, -1, + gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, + (gpointer) ro_memory, sizeof (ro_memory), + 0, sizeof (ro_memory), NULL, NULL)); + + return buf; +} + +GST_START_TEST (test_make_writable) +{ + GstBuffer *buf, *buf2; + GstMapInfo info; + + /* create read-only buffer and make it writable */ + buf = create_read_only_buffer (); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + info.data[4] = 'a'; + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); + + /* alloc'ed buffer with refcount 1 should be writable */ + buf = gst_buffer_new_and_alloc (32); + buf2 = gst_buffer_make_writable (buf); + fail_unless (buf == buf2, + "_make_writable() should have returned same buffer"); + gst_buffer_unref (buf2); + + /* alloc'ed buffer with refcount >1 should be copied */ + buf = gst_buffer_new_and_alloc (32); + gst_buffer_ref (buf); + buf2 = gst_buffer_make_writable (buf); + fail_unless (buf != buf2, "_make_writable() should have returned a copy!"); + gst_buffer_unref (buf2); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_subbuffer_make_writable) +{ + GstBuffer *buf, *sub_buf; + GstMapInfo info; + + /* create sub-buffer of read-only buffer and make it writable */ + buf = create_read_only_buffer (); + + sub_buf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, 0, 8); + + fail_unless (gst_buffer_map (sub_buf, &info, GST_MAP_WRITE)); + fail_if (info.data == NULL); + info.data[4] = 'a'; + gst_buffer_unmap (sub_buf, &info); + gst_buffer_unref (sub_buf); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_metadata_writable) +{ + GstBuffer *buffer, *sub1; + + buffer = gst_buffer_new_and_alloc (4); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* Buffer with refcount 1 should have writable metadata */ + fail_unless (gst_buffer_is_writable (buffer) == TRUE); + + /* Check that a buffer with refcount 2 does not have writable metadata */ + gst_buffer_ref (buffer); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 2); + fail_unless (gst_buffer_is_writable (buffer) == FALSE); + + /* Check that make_metadata_writable produces a new sub-buffer with + * writable metadata. */ + sub1 = gst_buffer_make_writable (buffer); + fail_if (sub1 == buffer); + fail_unless (gst_buffer_is_writable (sub1) == TRUE); + + /* Check that make_metadata_writable() maintains the buffer flags */ + fail_unless (GST_BUFFER_FLAG_IS_SET (sub1, GST_BUFFER_FLAG_DISCONT)); + fail_unless (GST_BUFFER_FLAG_IS_SET (sub1, GST_BUFFER_FLAG_DELTA_UNIT)); + + /* Unset flags on writable buffer, then make sure they're still + * set on the original buffer */ + GST_BUFFER_FLAG_UNSET (sub1, GST_BUFFER_FLAG_DISCONT); + GST_BUFFER_FLAG_UNSET (sub1, GST_BUFFER_FLAG_DELTA_UNIT); + fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)); + fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)); + + /* Drop the subbuffer and check that the metadata is now writable again */ + ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1); + gst_buffer_unref (sub1); + fail_unless (gst_buffer_is_writable (buffer) == TRUE); + + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_memcmp) +{ + GstBuffer *buffer; + char buf[3] = { 0, 0, 0 }; + + buffer = gst_buffer_new_and_alloc (2); + gst_buffer_memset (buffer, 0, 0, 2); + + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 2) == 0); + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 1) == 0); + fail_unless (gst_buffer_memcmp (buffer, 1, buf, 1) == 0); + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 3) != 0); + fail_unless (gst_buffer_memcmp (buffer, 2, buf, 1) != 0); + fail_unless (gst_buffer_memcmp (buffer, 4, buf, 1) != 0); + + gst_buffer_memset (buffer, 0, 0x20, 2); + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 2) != 0); + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 1) != 0); + fail_unless (gst_buffer_memcmp (buffer, 1, buf, 1) != 0); + fail_unless (gst_buffer_memcmp (buffer, 0, buf, 3) != 0); + fail_unless (gst_buffer_memcmp (buffer, 2, buf, 1) != 0); + + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_copy) +{ + GstBuffer *buffer, *copy; + GstMapInfo info, sinfo; + + buffer = gst_buffer_new_and_alloc (4); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + + copy = gst_buffer_copy (buffer); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + ASSERT_BUFFER_REFCOUNT (copy, "copy", 1); + /* buffers are copied and must point to different memory */ + fail_if (buffer == copy); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_unless (gst_buffer_map (copy, &sinfo, GST_MAP_READ)); + + /* NOTE that data is refcounted */ + fail_unless (info.size == sinfo.size); + /* GstBuffer was copied but the underlying GstMemory should be the same */ + fail_unless (info.data == sinfo.data); + + gst_buffer_unmap (copy, &sinfo); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); + + /* a 0-sized buffer has NULL data as per docs */ + buffer = gst_buffer_new_and_alloc (0); + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_unless (info.data == NULL); + gst_buffer_unmap (buffer, &info); + + /* copying a 0-sized buffer should not crash and also set + * the data member NULL. */ + copy = gst_buffer_copy (buffer); + fail_unless (gst_buffer_map (copy, &info, GST_MAP_READ)); + fail_unless (info.data == NULL); + gst_buffer_unmap (copy, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); + + /* check if copy is an independent copy when written to */ + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_memset (buffer, 0, 0, 4); + copy = gst_buffer_copy (buffer); + fail_unless (gst_buffer_is_writable (copy)); + gst_buffer_memset (copy, 0, 0x80, 4); + gst_buffer_map (buffer, &info, GST_MAP_READ); + fail_if (gst_buffer_memcmp (copy, 0, info.data, info.size) == 0); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); + + /* copy should still be independent if copied when mapped */ + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_memset (buffer, 0, 0, 4); + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + copy = gst_buffer_copy (buffer); + fail_unless (gst_buffer_is_writable (copy)); + gst_buffer_memset (copy, 0, 0x80, 4); + gst_buffer_unmap (buffer, &info); + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_if (gst_buffer_memcmp (copy, 0, info.data, info.size) == 0); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); + + /* check if a writable clone of a buffer is independent when written to */ + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_memset (buffer, 0, 0, 4); + copy = gst_buffer_ref (buffer); + copy = gst_buffer_make_writable (copy); + fail_unless (gst_buffer_is_writable (copy)); + gst_buffer_memset (copy, 0, 0x80, 4); + gst_buffer_map (buffer, &info, GST_MAP_READ); + fail_if (gst_buffer_memcmp (copy, 0, info.data, info.size) == 0); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_copy_deep) +{ + GstBuffer *buffer, *copy; + GstMapInfo info, sinfo; + + buffer = gst_buffer_new_and_alloc (4); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + + copy = gst_buffer_copy_deep (buffer); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + ASSERT_BUFFER_REFCOUNT (copy, "copy", 1); + /* buffers are copied and must point to different memory */ + fail_if (buffer == copy); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_unless (gst_buffer_map (copy, &sinfo, GST_MAP_READ)); + + /* NOTE that data is refcounted */ + fail_unless (info.size == sinfo.size); + /* copy_deep() forces new GstMemory to be used */ + fail_unless (info.data != sinfo.data); + + gst_buffer_unmap (copy, &sinfo); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (copy); + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_try_new_and_alloc) +{ + GstBuffer *buf; + GstMapInfo info; + + /* special case: alloc of 0 bytes results in new buffer with NULL data */ + buf = gst_buffer_new_and_alloc (0); + fail_unless (buf != NULL); + fail_unless (GST_IS_BUFFER (buf)); + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + fail_unless (info.data == NULL); + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); + + /* normal alloc should still work */ + buf = gst_buffer_new_and_alloc (640 * 480 * 4); + fail_unless (buf != NULL); + fail_unless (GST_IS_BUFFER (buf)); + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + fail_unless (info.data != NULL); + fail_unless (info.size == (640 * 480 * 4)); + info.data[640 * 479 * 4 + 479] = 0xff; + gst_buffer_unmap (buf, &info); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_size) +{ + GstBuffer *buf; + GstMemory *mem; + gsize maxalloc, maxalloc2, maxalloc3, maxalloc4; + gsize size, maxsize, offset; + + /* one memory block */ + buf = gst_buffer_new_allocate (NULL, 100, NULL); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + mem = gst_buffer_get_memory (buf, 0); + gst_memory_resize (mem, 10, 70); + gst_memory_unref (mem); + + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 70); + fail_unless (offset == 10); + fail_unless (maxsize == maxalloc); + + /* new memory */ + mem = gst_allocator_alloc (NULL, 100, NULL); + size = gst_memory_get_sizes (mem, &offset, &maxalloc2); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc2 >= 100); + + gst_memory_resize (mem, 20, 60); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 60); + fail_unless (offset == 20); + fail_unless (maxsize == maxalloc2); + + /* append */ + gst_buffer_insert_memory (buf, -1, mem); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 130); + fail_unless (offset == 10); + /* the maxsize is the size of the first buffer plus the remaining size in the + * second buffer */ + fail_unless (maxalloc == 80 + (maxalloc2 - 20)); + + /* appending an empty block */ + mem = gst_allocator_alloc (NULL, 100, NULL); + size = gst_memory_get_sizes (mem, &offset, &maxalloc3); + gst_memory_resize (mem, 0, 0); + gst_buffer_insert_memory (buf, -1, mem); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 130); + fail_unless (offset == 10); + /* the maxsize is the size of the first buffer plus the remaining size in the + * second buffer and the last empty buffer*/ + fail_unless (maxalloc == 80 + (maxalloc2 - 20) + maxalloc3); + + /* prepending an empty block */ + mem = gst_allocator_alloc (NULL, 100, NULL); + size = gst_memory_get_sizes (mem, &offset, &maxalloc4); + gst_memory_resize (mem, 0, 0); + gst_buffer_insert_memory (buf, 0, mem); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 130); + /* empty buffer maxsize can be used as offset */ + fail_unless (offset == 10 + maxalloc4); + /* the maxsize is the size of the first buffer plus the remaining size in the + * second buffer and the last empty buffer*/ + fail_unless (maxalloc == 80 + (maxalloc2 - 20) + maxalloc3 + maxalloc4); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_resize) +{ + GstBuffer *buf; + gsize maxalloc; + gsize size, maxsize, offset; + + /* one memory block */ + buf = gst_buffer_new_allocate (NULL, 100, NULL); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + ASSERT_CRITICAL (gst_buffer_resize (buf, 200, 50)); + ASSERT_CRITICAL (gst_buffer_resize (buf, 0, 150)); + ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc)); + ASSERT_CRITICAL (gst_buffer_resize (buf, maxalloc, 1)); + + /* this does nothing */ + gst_buffer_resize (buf, 0, 100); + + /* nothing should have changed */ + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 0, 50); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 50); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 0, 100); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 1, 99); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxsize == maxalloc); + + ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc - 1)); + + gst_buffer_resize (buf, 0, 99); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, -1, 100); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + ASSERT_CRITICAL (gst_buffer_resize (buf, -1, 100)); + + gst_buffer_resize (buf, 50, 40); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 40); + fail_unless (offset == 50); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, -50, 100); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 0, 0); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 0); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 0, 100); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_resize (buf, 0, 100); + size = gst_buffer_get_sizes (buf, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_map) +{ + GstBuffer *buf; + GstMapInfo map, map2; + gsize maxalloc; + gsize size, offset; + + buf = gst_buffer_new (); + gst_buffer_insert_memory (buf, -1, gst_allocator_alloc (NULL, 50, NULL)); + gst_buffer_insert_memory (buf, -1, gst_allocator_alloc (NULL, 50, NULL)); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + fail_unless (gst_buffer_n_memory (buf) == 2); + + /* make readonly */ + gst_buffer_ref (buf); + /* map should merge */ + gst_buffer_map (buf, &map, GST_MAP_READ); + /* merged memory is not stored */ + fail_unless (gst_buffer_n_memory (buf) == 2); + gst_buffer_unmap (buf, &map); + + fail_unless (gst_buffer_n_memory (buf) == 2); + + /* can't map write on readonly buffer */ + ASSERT_CRITICAL (gst_buffer_map (buf, &map, GST_MAP_WRITE)); + /* make writable again */ + gst_buffer_unref (buf); + + /* should merge and store */ + gst_buffer_map (buf, &map, GST_MAP_READ); + fail_unless (gst_buffer_n_memory (buf) == 1); + gst_buffer_unmap (buf, &map); + + gst_buffer_map (buf, &map, GST_MAP_WRITE); + gst_buffer_unmap (buf, &map); + + /* mapping same kind should be ok using same memory */ + gst_buffer_map (buf, &map, GST_MAP_WRITE); + fail_unless (gst_buffer_map (buf, &map2, GST_MAP_WRITE)); + fail_unless (map.memory == map2.memory); + gst_buffer_unmap (buf, &map2); + gst_buffer_unmap (buf, &map); + + /* ... but different kind should give temporary memory */ + gst_buffer_map (buf, &map, GST_MAP_WRITE); + fail_unless (gst_buffer_map (buf, &map2, GST_MAP_READ)); + fail_if (map.memory == map2.memory); + gst_buffer_unmap (buf, &map2); + gst_buffer_unmap (buf, &map); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_map_range) +{ + GstBuffer *buf; + GstMapInfo map; + gsize maxalloc; + gsize size, offset; + + buf = gst_buffer_new (); + gst_buffer_insert_memory (buf, -1, gst_allocator_alloc (NULL, 50, NULL)); + gst_buffer_insert_memory (buf, -1, gst_allocator_alloc (NULL, 50, NULL)); + gst_buffer_insert_memory (buf, -1, gst_allocator_alloc (NULL, 50, NULL)); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 150); + fail_unless (offset == 0); + fail_unless (maxalloc >= 150); + fail_unless (gst_buffer_n_memory (buf) == 3); + + gst_buffer_ref (buf); + /* map should merge */ + gst_buffer_map_range (buf, 1, 2, &map, GST_MAP_READ); + /* merged memory is not stored */ + fail_unless (gst_buffer_n_memory (buf) == 3); + fail_unless (map.size == 100); + gst_buffer_unmap (buf, &map); + + fail_unless (gst_buffer_n_memory (buf) == 3); + + gst_buffer_unref (buf); + + /* map should merge */ + gst_buffer_map_range (buf, 1, 2, &map, GST_MAP_READ); + /* merged memory is stored */ + fail_unless (gst_buffer_n_memory (buf) == 2); + fail_unless (map.size == 100); + gst_buffer_unmap (buf, &map); + + fail_unless (gst_buffer_n_memory (buf) == 2); + + /* should merge and store */ + gst_buffer_map (buf, &map, GST_MAP_READ); + fail_unless (gst_buffer_n_memory (buf) == 1); + gst_buffer_unmap (buf, &map); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_find) +{ + GstBuffer *buf; + gsize maxalloc; + gsize size, offset; + guint idx, length; + + buf = gst_buffer_new (); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 10, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 15, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL)); + + size = gst_buffer_get_sizes (buf, &offset, &maxalloc); + fail_unless (size == 25); + fail_unless (offset >= 0); + fail_unless (maxalloc >= 25); + fail_unless (gst_buffer_n_memory (buf) == 4); + + fail_unless (gst_buffer_find_memory (buf, 0, 5, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 1); + fail_unless (offset == 0); + + fail_unless (gst_buffer_find_memory (buf, 0, 10, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 1); + fail_unless (offset == 0); + + fail_unless (gst_buffer_find_memory (buf, 5, 4, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 1); + fail_unless (offset == 5); + + fail_unless (gst_buffer_find_memory (buf, 5, 5, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 1); + fail_unless (offset == 5); + + fail_unless (gst_buffer_find_memory (buf, 5, 6, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 2); + fail_unless (offset == 5); + + fail_unless (gst_buffer_find_memory (buf, 10, 6, &idx, &length, &offset)); + fail_unless (idx == 2); + fail_unless (length == 1); + fail_unless (offset == 0); + + fail_unless (gst_buffer_find_memory (buf, 10, 15, &idx, &length, &offset)); + fail_unless (idx == 2); + fail_unless (length == 1); + fail_unless (offset == 0); + + fail_unless (gst_buffer_find_memory (buf, 11, 14, &idx, &length, &offset)); + fail_unless (idx == 2); + fail_unless (length == 1); + fail_unless (offset == 1); + + fail_unless (gst_buffer_find_memory (buf, 0, 25, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 2); + fail_unless (offset == 0); + + fail_unless (gst_buffer_find_memory (buf, 24, 0, &idx, &length, &offset)); + fail_unless (idx == 2); + fail_unless (length == 1); + fail_unless (offset == 14); + + fail_if (gst_buffer_find_memory (buf, 11, 15, &idx, &length, &offset)); + fail_if (gst_buffer_find_memory (buf, 0, 26, &idx, &length, &offset)); + fail_if (gst_buffer_find_memory (buf, 25, 0, &idx, &length, &offset)); + + fail_unless (gst_buffer_find_memory (buf, 1, -1, &idx, &length, &offset)); + fail_unless (idx == 1); + fail_unless (length == 3); + fail_unless (offset == 1); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_fill) +{ + GstBuffer *buf; + guint8 data[1024], data2[25]; + gint i; + + buf = gst_buffer_new (); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 10, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 15, NULL)); + gst_buffer_append_memory (buf, gst_allocator_alloc (NULL, 0, NULL)); + + for (i = 0; i < G_N_ELEMENTS (data); ++i) + data[i] = i & 0xff; + + /* a NULL src pointer should be ok if the src length is 0 bytes */ + fail_unless_equals_int (gst_buffer_fill (buf, 0, NULL, 0), 0); + fail_unless_equals_int (gst_buffer_fill (buf, 20, NULL, 0), 0); + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 0), 0); + + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 1), 1); + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 11), 11); + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 15), 15); + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 25), 25); + fail_unless_equals_int (gst_buffer_fill (buf, 0, data, 26), 25); + fail_unless_equals_int (gst_buffer_fill (buf, 1, data, 26), 24); + fail_unless_equals_int (gst_buffer_fill (buf, 10, data, 100), 15); + fail_unless_equals_int (gst_buffer_fill (buf, 11, data, 100), 14); + fail_unless_equals_int (gst_buffer_fill (buf, 25, data, 100), 0); + + fail_unless_equals_int (gst_buffer_fill (buf, 0, data + 10, 25), 25); + fail_unless_equals_int (gst_buffer_extract (buf, 0, data2, 25), 25); + fail_unless (memcmp (data2, data + 10, 25) == 0); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_parent_buffer_meta) +{ + GstBuffer *buf, *parent; + GstParentBufferMeta *meta; + + buf = gst_buffer_new (); + parent = gst_buffer_new (); + + gst_buffer_add_parent_buffer_meta (buf, parent); + meta = gst_buffer_get_parent_buffer_meta (buf); + fail_unless (meta); + fail_unless (parent == meta->buffer); + + gst_buffer_unref (buf); + gst_buffer_unref (parent); +} + +GST_END_TEST; + + +static Suite * +gst_buffer_suite (void) +{ + Suite *s = suite_create ("GstBuffer"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_subbuffer); + tcase_add_test (tc_chain, test_subbuffer_make_writable); + tcase_add_test (tc_chain, test_make_writable); + tcase_add_test (tc_chain, test_span); + tcase_add_test (tc_chain, test_metadata_writable); + tcase_add_test (tc_chain, test_memcmp); + tcase_add_test (tc_chain, test_copy); + tcase_add_test (tc_chain, test_copy_deep); + tcase_add_test (tc_chain, test_try_new_and_alloc); + tcase_add_test (tc_chain, test_size); + tcase_add_test (tc_chain, test_resize); + tcase_add_test (tc_chain, test_map); + tcase_add_test (tc_chain, test_map_range); + tcase_add_test (tc_chain, test_find); + tcase_add_test (tc_chain, test_fill); + tcase_add_test (tc_chain, test_parent_buffer_meta); + + return s; +} + +GST_CHECK_MAIN (gst_buffer); diff --git a/tests/check/gst/gstbufferlist.c b/tests/check/gst/gstbufferlist.c new file mode 100644 index 0000000..2ac3323 --- /dev/null +++ b/tests/check/gst/gstbufferlist.c @@ -0,0 +1,508 @@ +/* GStreamer + * + * unit test for GstBufferList + * + * Copyright (C) 2009 Axis Communications + * @author Jonas Holmberg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +static GstBufferList *list; + +static void +setup (void) +{ + list = gst_buffer_list_new (); +} + +static void +cleanup (void) +{ + gst_buffer_list_unref (list); + list = NULL; +} + +GST_START_TEST (test_add_and_iterate) +{ + GstBuffer *buf1; + GstBuffer *buf2; + + /* buffer list is initially empty */ + fail_unless (gst_buffer_list_length (list) == 0); + + ASSERT_CRITICAL (gst_buffer_list_insert (list, 0, NULL)); + ASSERT_CRITICAL (gst_buffer_list_insert (NULL, 0, NULL)); + + buf1 = gst_buffer_new (); + + /* add a group of 2 buffers */ + fail_unless (gst_buffer_list_length (list) == 0); + ASSERT_CRITICAL (gst_buffer_list_insert (list, -1, NULL)); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1); + gst_buffer_list_add (list, buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1); /* list takes ownership */ + fail_unless (gst_buffer_list_length (list) == 1); + buf2 = gst_buffer_new (); + gst_buffer_list_add (list, buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1); + fail_unless (gst_buffer_list_length (list) == 2); +} + +GST_END_TEST; + +GST_START_TEST (test_remove) +{ + GstBuffer *buf; + + /* buffer list is initially empty */ + fail_unless (gst_buffer_list_length (list) == 0); + + buf = gst_buffer_new (); + + /* add our own ref so it stays alive after removal from the list */ + buf = gst_buffer_ref (buf); + + /* add a buffer */ + fail_unless (gst_buffer_list_length (list) == 0); + ASSERT_CRITICAL (gst_buffer_list_insert (list, -1, NULL)); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 2); + gst_buffer_list_add (list, buf); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 2); /* list takes ownership */ + fail_unless (gst_buffer_list_length (list) == 1); + gst_buffer_list_remove (list, 0, 1); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); + gst_buffer_unref (buf); + fail_unless (gst_buffer_list_length (list) == 0); +} + +GST_END_TEST; + +GST_START_TEST (test_make_writable) +{ + GstBufferList *wlist; + GstBuffer *buf1; + GstBuffer *buf2; + GstBuffer *buf3; + GstBuffer *buf; + + /* add buffers to list */ + buf1 = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_list_add (list, buf1); + + buf2 = gst_buffer_new_allocate (NULL, 2, NULL); + buf3 = gst_buffer_new_allocate (NULL, 3, NULL); + gst_buffer_list_add (list, gst_buffer_append (buf2, buf3)); + + /* making it writable with refcount 1 returns the same list */ + wlist = gst_buffer_list_make_writable (list); + fail_unless (wlist == list); + fail_unless_equals_int (gst_buffer_list_length (list), 2); + buf = gst_buffer_list_get (list, 0); + fail_unless (buf == buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1); + fail_unless_equals_int (gst_buffer_get_size (buf), 1); + buf = gst_buffer_list_get (list, 1); + fail_unless (buf == buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1); + fail_unless_equals_int (gst_buffer_n_memory (buf), 2); + + /* making it writable with refcount 2 returns a copy of the list with + * increased refcount on the buffers in the list */ + gst_buffer_list_ref (list); + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (list), 2); + wlist = gst_buffer_list_make_writable (list); + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (list), 1); + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (wlist), 1); + fail_unless (wlist != list); + /* check list */ + fail_unless_equals_int (gst_buffer_list_length (list), 2); + buf = gst_buffer_list_get (list, 0); + fail_unless (buf == buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2); + fail_unless_equals_int (gst_buffer_get_size (buf), 1); + buf = gst_buffer_list_get (list, 1); + fail_unless (buf == buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2); + fail_unless_equals_int (gst_buffer_n_memory (buf), 2); + /* check wlist */ + fail_unless_equals_int (gst_buffer_list_length (wlist), 2); + buf = gst_buffer_list_get (wlist, 0); + fail_unless (buf == buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2); + fail_unless_equals_int (gst_buffer_get_size (buf), 1); + buf = gst_buffer_list_get (wlist, 1); + fail_unless (buf == buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2); + fail_unless_equals_int (gst_buffer_n_memory (buf), 2); + gst_buffer_list_unref (wlist); + /* list will be unrefed in cleanup hook */ +} + +GST_END_TEST; + +GST_START_TEST (test_copy) +{ + GstBufferList *list_copy; + GstBuffer *buf1; + GstBuffer *buf2; + GstBuffer *buf3; + GstBuffer *buf; + + /* add buffers to the list */ + buf1 = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_list_add (list, buf1); + + buf2 = gst_buffer_new_allocate (NULL, 2, NULL); + buf3 = gst_buffer_new_allocate (NULL, 3, NULL); + gst_buffer_list_add (list, gst_buffer_append (buf2, buf3)); + + /* make a copy */ + list_copy = gst_buffer_list_copy (list); + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list) == 1); + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list_copy) == 1); + fail_unless (list_copy != list); + fail_unless_equals_int (gst_buffer_list_length (list_copy), 2); + buf = gst_buffer_list_get (list_copy, 0); + fail_unless (buf == buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2); + fail_unless_equals_int (gst_buffer_get_size (buf1), 1); + buf = gst_buffer_list_get (list_copy, 1); + fail_unless (buf == buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2); + fail_unless_equals_int (gst_buffer_get_size (buf2), 5); + fail_unless_equals_int (gst_buffer_n_memory (buf2), 2); + + gst_buffer_list_unref (list_copy); +} + +GST_END_TEST; + +GST_START_TEST (test_copy_deep) +{ + GstBufferList *list_copy; + GstMapInfo info, sinfo; + GstBuffer *buf1; + GstBuffer *buf2; + GstBuffer *buf_copy; + + /* add buffers to the list */ + buf1 = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_list_add (list, buf1); + + buf2 = gst_buffer_new_allocate (NULL, 2, NULL); + gst_buffer_list_add (list, buf2); + + /* make a copy */ + list_copy = gst_buffer_list_copy_deep (list); + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list) == 1); + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list_copy) == 1); + fail_unless (list_copy != list); + fail_unless_equals_int (gst_buffer_list_length (list_copy), 2); + + buf_copy = gst_buffer_list_get (list_copy, 0); + /* each buffer in the list is copied and must point to different memory */ + fail_unless (buf_copy != buf1); + ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1); + fail_unless_equals_int (gst_buffer_get_size (buf1), 1); + + buf_copy = gst_buffer_list_get (list_copy, 1); + fail_unless (buf_copy != buf2); + ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1); + fail_unless_equals_int (gst_buffer_get_size (buf2), 2); + + fail_unless (gst_buffer_map (buf2, &info, GST_MAP_READ)); + fail_unless (gst_buffer_map (buf_copy, &sinfo, GST_MAP_READ)); + + /* NOTE that data is refcounted */ + fail_unless (info.size == sinfo.size); + /* copy_deep() forces new GstMemory to be used */ + fail_unless (info.data != sinfo.data); + + gst_buffer_unmap (buf_copy, &sinfo); + gst_buffer_unmap (buf2, &info); + + gst_buffer_list_unref (list_copy); +} + +GST_END_TEST; + +typedef struct +{ + GstBuffer *buf[2]; + guint iter; +} ForeachData; + +static gboolean +foreach_func1 (GstBuffer ** buffer, guint idx, ForeachData * data) +{ + fail_unless (buffer != NULL); + fail_unless (GST_IS_BUFFER (*buffer)); + fail_unless (*buffer == data->buf[idx]); + + data->iter++; + + return TRUE; +} + +static gboolean +foreach_func3 (GstBuffer ** buffer, guint idx, ForeachData * data) +{ + fail_unless (idx == 0); + fail_unless (buffer != NULL); + fail_unless (GST_IS_BUFFER (*buffer)); + fail_unless (*buffer == data->buf[idx]); + + data->iter++; + + return FALSE; +} + +static gboolean +foreach_func4 (GstBuffer ** buffer, guint idx, ForeachData * data) +{ + fail_unless (idx == 0); + fail_unless (buffer != NULL); + fail_unless (GST_IS_BUFFER (*buffer)); + fail_unless (*buffer == data->buf[data->iter]); + + /* remove first */ + if (*buffer == data->buf[0]) { + gst_buffer_unref (*buffer); + *buffer = NULL; + } + + data->iter++; + + return TRUE; +} + +static gboolean +foreach_func5 (GstBuffer ** buffer, guint idx, ForeachData * data) +{ + fail_unless (buffer != NULL); + fail_unless (GST_IS_BUFFER (*buffer)); + + data->iter++; + + return TRUE; +} + +GST_START_TEST (test_foreach) +{ + GstBuffer *buf2, *buf3; + ForeachData data; + + /* add buffers to the list */ + data.buf[0] = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_list_add (list, data.buf[0]); + + buf2 = gst_buffer_new_allocate (NULL, 2, NULL); + buf3 = gst_buffer_new_allocate (NULL, 3, NULL); + data.buf[1] = gst_buffer_append (buf2, buf3); + gst_buffer_list_add (list, data.buf[1]); + + fail_unless (gst_buffer_list_get (list, 0) == data.buf[0]); + fail_unless (gst_buffer_list_get (list, 1) == data.buf[1]); + + /* iterate everything */ + data.iter = 0; + gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func1, &data); + fail_unless (data.iter == 2); + + /* iterate only the first buffer */ + data.iter = 0; + gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func3, &data); + fail_unless (data.iter == 1); + + /* remove the first buffer */ + data.iter = 0; + gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func4, &data); + fail_unless (data.iter == 2); + + fail_unless (gst_buffer_list_get (list, 0) == data.buf[1]); + fail_unless_equals_int (gst_buffer_list_length (list), 1); + + /* iterate everything, just one more buffer now */ + data.iter = 0; + gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func5, &data); + fail_unless (data.iter == 1); +} + +GST_END_TEST; + +/* make sure everything is fine if we exceed the pre-allocated size */ +GST_START_TEST (test_expand_and_remove) +{ + GArray *arr; + GstBuffer *buf; + guint i, idx, num, counter = 0; + + gst_buffer_list_unref (list); + + arr = g_array_new (FALSE, FALSE, sizeof (guint)); + + list = gst_buffer_list_new_sized (1); + + for (i = 0; i < 250; ++i) { + num = ++counter; + buf = gst_buffer_new_allocate (NULL, num, NULL); + gst_buffer_list_add (list, buf); + g_array_append_val (arr, num); + } + + for (i = 0; i < 250; ++i) { + num = ++counter; + buf = gst_buffer_new_allocate (NULL, num, NULL); + idx = g_random_int_range (0, gst_buffer_list_length (list)); + gst_buffer_list_insert (list, idx, buf); + g_array_insert_val (arr, idx, num); + } + + /* make sure the list looks like it should */ + fail_unless_equals_int (arr->len, gst_buffer_list_length (list)); + for (i = 0; i < arr->len; ++i) { + buf = gst_buffer_list_get (list, i); + num = gst_buffer_get_size (buf); + fail_unless_equals_int (num, g_array_index (arr, guint, i)); + } + + for (i = 0; i < 44; ++i) { + num = g_random_int_range (1, 5); + idx = g_random_int_range (0, gst_buffer_list_length (list) - num); + gst_buffer_list_remove (list, idx, num); + g_array_remove_range (arr, idx, num); + } + + /* make sure the list still looks like it should */ + fail_unless_equals_int (arr->len, gst_buffer_list_length (list)); + for (i = 0; i < arr->len; ++i) { + buf = gst_buffer_list_get (list, i); + num = gst_buffer_get_size (buf); + fail_unless_equals_int (num, g_array_index (arr, guint, i)); + } + + for (i = 0; i < 500; ++i) { + num = ++counter; + buf = gst_buffer_new_allocate (NULL, num, NULL); + gst_buffer_list_add (list, buf); + g_array_append_val (arr, num); + } + + for (i = 0; i < 500; ++i) { + num = ++counter; + buf = gst_buffer_new_allocate (NULL, num, NULL); + idx = g_random_int_range (0, gst_buffer_list_length (list)); + gst_buffer_list_insert (list, idx, buf); + g_array_insert_val (arr, idx, num); + } + + /* make sure the list still looks like it should */ + fail_unless_equals_int (arr->len, gst_buffer_list_length (list)); + for (i = 0; i < arr->len; ++i) { + buf = gst_buffer_list_get (list, i); + num = gst_buffer_get_size (buf); + fail_unless_equals_int (num, g_array_index (arr, guint, i)); + } + + g_array_unref (arr); +} + +GST_END_TEST; + +GST_START_TEST (test_get_writable) +{ + GstBuffer *buf, *writable_buf; + + /* buffer list is initially empty */ + fail_unless (gst_buffer_list_length (list) == 0); + + /* Add 2 buffers */ + buf = gst_buffer_new (); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); + gst_buffer_list_add (list, buf); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); /* list takes ownership */ + fail_unless (gst_buffer_list_length (list) == 1); + fail_unless (buf == gst_buffer_list_get_writable (list, 0)); + fail_unless (buf == gst_buffer_list_get (list, 0)); + + /* extra ref to make buffer no longer writable */ + gst_buffer_ref (buf); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 2); + fail_unless (buf == gst_buffer_list_get (list, 0)); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 2); + + /* should make a copy to make it writable */ + writable_buf = gst_buffer_list_get_writable (list, 0); + fail_if (buf == writable_buf); + ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); + ASSERT_BUFFER_REFCOUNT (writable_buf, "writable_buf", 1); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_calc_size) +{ + gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup ("Hello"), 5)); + gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup (", "), 2)); + gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup ("world!"), 6)); + + fail_unless_equals_int (5 + 2 + 6, gst_buffer_list_calculate_size (list)); +} + +GST_END_TEST; + +GST_START_TEST (test_new_sized_0) +{ + GstBufferList *b = gst_buffer_list_new_sized (0); + + gst_buffer_list_unref (b); +} + +GST_END_TEST; + +static Suite * +gst_buffer_list_suite (void) +{ + Suite *s = suite_create ("GstBufferList"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_checked_fixture (tc_chain, setup, cleanup); + tcase_add_test (tc_chain, test_add_and_iterate); + tcase_add_test (tc_chain, test_remove); + tcase_add_test (tc_chain, test_make_writable); + tcase_add_test (tc_chain, test_copy); + tcase_add_test (tc_chain, test_copy_deep); + tcase_add_test (tc_chain, test_foreach); + tcase_add_test (tc_chain, test_expand_and_remove); + tcase_add_test (tc_chain, test_get_writable); + tcase_add_test (tc_chain, test_calc_size); + tcase_add_test (tc_chain, test_new_sized_0); + + return s; +} + +GST_CHECK_MAIN (gst_buffer_list); diff --git a/tests/check/gst/gstbufferpool.c b/tests/check/gst/gstbufferpool.c new file mode 100644 index 0000000..8b9b0b3 --- /dev/null +++ b/tests/check/gst/gstbufferpool.c @@ -0,0 +1,328 @@ +/* GStreamer + * Copyright (C) 2014 Stefan Sauer + * + * gstbufferpool.c: Unit test for GstBufferPool + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstBufferPool * +create_pool (guint size, guint min_buf, guint max_buf) +{ + GstBufferPool *pool = gst_buffer_pool_new (); + GstStructure *conf = gst_buffer_pool_get_config (pool); + GstCaps *caps = gst_caps_new_empty_simple ("test/data"); + + gst_buffer_pool_config_set_params (conf, caps, size, min_buf, max_buf); + gst_buffer_pool_set_config (pool, conf); + gst_caps_unref (caps); + + return pool; +} + +static void +buffer_destroy_notify (gpointer ptr) +{ + gint *counter = ptr; + + GST_DEBUG ("buffer destroyed"); + + *counter += 1; +} + +/* Track when a buffer is destroyed. The counter will be increased if the + * buffer is finalized (but not if it was re-surrected in dispose and put + * back into the buffer pool. */ +static void +buffer_track_destroy (GstBuffer * buf, gint * counter) +{ + gst_mini_object_set_qdata (GST_MINI_OBJECT (buf), + g_quark_from_static_string ("TestTracker"), + counter, buffer_destroy_notify); +} + +GST_START_TEST (test_new_buffer_from_empty_pool) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstBuffer *buf = NULL; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + fail_if (buf == NULL, "acquiring buffer returned NULL"); + + gst_buffer_unref (buf); + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); +} + +GST_END_TEST; + + +GST_START_TEST (test_buffer_is_recycled) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstBuffer *buf = NULL, *prev; + gint dcount = 0; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + prev = buf; + buffer_track_destroy (buf, &dcount); + gst_buffer_unref (buf); + + /* buffer should not have been freed, but have been recycled */ + fail_unless (dcount == 0); + + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + fail_unless (buf == prev, "got a fresh buffer instead of previous"); + + gst_buffer_unref (buf); + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + + /* buffer should now be gone */ + fail_unless (dcount == 1); +} + +GST_END_TEST; + + +GST_START_TEST (test_buffer_out_of_order_reuse) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstBuffer *buf1 = NULL, *buf2 = NULL, *prev; + gint dcount1 = 0, dcount2 = 0; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_acquire_buffer (pool, &buf1, NULL); + buffer_track_destroy (buf1, &dcount1); + gst_buffer_pool_acquire_buffer (pool, &buf2, NULL); + buffer_track_destroy (buf2, &dcount2); + prev = buf2; + gst_buffer_unref (buf2); + + /* buffer should not have been freed, but have been recycled */ + fail_unless (dcount2 == 0); + + gst_buffer_pool_acquire_buffer (pool, &buf2, NULL); + fail_unless (buf2 == prev, "got a fresh buffer instead of previous"); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + + fail_unless (dcount1 == 1); + fail_unless (dcount2 == 1); +} + +GST_END_TEST; + + +GST_START_TEST (test_pool_config_buffer_size) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstBuffer *buf = NULL; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + ck_assert_int_eq (gst_buffer_get_size (buf), 10); + + gst_buffer_unref (buf); + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); +} + +GST_END_TEST; + + +GST_START_TEST (test_inactive_pool_returns_flushing) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstFlowReturn ret; + GstBuffer *buf = NULL; + + ret = gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + ck_assert_int_eq (ret, GST_FLOW_FLUSHING); + + gst_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_modify_discard) +{ + + GstBufferPool *pool = create_pool (10, 0, 0); + GstBuffer *buf = NULL, *prev; + GstMemory *mem; + gint dcount = 0; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + fail_unless (buf != NULL); + prev = buf; + buffer_track_destroy (buf, &dcount); + /* remove all memory, pool should not reuse this buffer */ + gst_buffer_remove_all_memory (buf); + gst_buffer_unref (buf); + + /* buffer should've been destroyed instead of going back into pool */ + fail_unless_equals_int (dcount, 1); + + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + prev = buf; + buffer_track_destroy (buf, &dcount); + /* do resize, pool should not reuse this buffer */ + gst_buffer_resize (buf, 5, 2); + gst_buffer_unref (buf); + + /* buffer should've been destroyed instead of going back into pool */ + fail_unless_equals_int (dcount, 2); + + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + prev = buf; + buffer_track_destroy (buf, &dcount); + /* keep ref to memory, not exclusive so pool should reuse this buffer */ + mem = gst_buffer_get_memory (buf, 0); + gst_buffer_unref (buf); + gst_memory_unref (mem); + + /* buffer should not have been destroyed and gone back into pool */ + fail_unless_equals_int (dcount, 2); + + gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + fail_unless (buf == prev, "got a fresh buffer instead of previous"); + /* we're already did track_destroy on this buf, so no need to do it again */ + mem = gst_buffer_get_memory (buf, 0); + /* exclusive lock so pool should not reuse this buffer */ + gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE); + gst_buffer_unref (buf); + gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unref (mem); + + /* buffer should have been destroyed and not gone back into pool because + * of the exclusive lock */ + fail_unless_equals_int (dcount, 3); + + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_activation_and_config) +{ + GstBufferPool *pool = gst_buffer_pool_new (); + GstStructure *config = gst_buffer_pool_get_config (pool); + GstCaps *caps = gst_caps_new_empty_simple ("test/data"); + + /* unconfigured pool cannot be activated */ + fail_if (gst_buffer_pool_set_active (pool, TRUE)); + + gst_buffer_pool_config_set_params (config, caps, 10, 10, 0); + fail_unless (gst_buffer_pool_set_config (pool, config)); + fail_unless (gst_buffer_pool_set_active (pool, TRUE)); + + /* setting the same config on an active pool is ok */ + config = gst_buffer_pool_get_config (pool); + fail_unless (gst_buffer_pool_set_config (pool, config)); + + /* setting a different config on active pool should fail */ + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, 12, 10, 0); + fail_if (gst_buffer_pool_set_config (pool, config)); + fail_unless (gst_buffer_pool_is_active (pool)); + + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_pool_config_validate) +{ + GstBufferPool *pool = create_pool (5, 4, 30); + GstStructure *config = gst_buffer_pool_get_config (pool); + GstCaps *caps = gst_caps_new_empty_simple ("test/data"); + + fail_unless (gst_buffer_pool_config_validate_params (config, caps, 5, 4, 0)); + fail_unless (gst_buffer_pool_config_validate_params (config, caps, 5, 2, 0)); + fail_unless (gst_buffer_pool_config_validate_params (config, caps, 4, 4, 0)); + fail_if (gst_buffer_pool_config_validate_params (config, caps, 5, 6, 0)); + + gst_caps_unref (caps); + caps = gst_caps_new_empty_simple ("test/data2"); + fail_if (gst_buffer_pool_config_validate_params (config, caps, 5, 4, 0)); + + gst_caps_unref (caps); + gst_structure_free (config); + gst_object_unref (pool); +} + +GST_END_TEST; + +GST_START_TEST (test_flushing_pool_returns_flushing) +{ + GstBufferPool *pool = create_pool (10, 0, 0); + GstFlowReturn ret; + GstBuffer *buf = NULL; + + gst_buffer_pool_set_active (pool, TRUE); + gst_buffer_pool_set_flushing (pool, TRUE); + + ret = gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + ck_assert_int_eq (ret, GST_FLOW_FLUSHING); + + gst_buffer_pool_set_flushing (pool, FALSE); + ret = gst_buffer_pool_acquire_buffer (pool, &buf, NULL); + ck_assert_int_eq (ret, GST_FLOW_OK); + + gst_buffer_unref (buf); + gst_object_unref (pool); +} + +GST_END_TEST; + +static Suite * +gst_buffer_pool_suite (void) +{ + Suite *s = suite_create ("GstBufferPool"); + TCase *tc_chain = tcase_create ("buffer_pool tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_new_buffer_from_empty_pool); + tcase_add_test (tc_chain, test_buffer_is_recycled); + tcase_add_test (tc_chain, test_buffer_out_of_order_reuse); + tcase_add_test (tc_chain, test_pool_config_buffer_size); + tcase_add_test (tc_chain, test_inactive_pool_returns_flushing); + tcase_add_test (tc_chain, test_buffer_modify_discard); + tcase_add_test (tc_chain, test_pool_activation_and_config); + tcase_add_test (tc_chain, test_pool_config_validate); + tcase_add_test (tc_chain, test_flushing_pool_returns_flushing); + + return s; +} + +GST_CHECK_MAIN (gst_buffer_pool); diff --git a/tests/check/gst/gstbus.c b/tests/check/gst/gstbus.c new file mode 100644 index 0000000..f8d6cb0 --- /dev/null +++ b/tests/check/gst/gstbus.c @@ -0,0 +1,839 @@ +/* GStreamer message bus unit tests + * Copyright (C) 2005 Andy Wingo + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstBus *test_bus = NULL; +static GMainLoop *main_loop; + +static GType foo_device_get_type (void); + +#define NUM_MESSAGES 1000 +#define NUM_THREADS 10 + +static gpointer +pound_bus_with_messages (gpointer data) +{ + gint thread_id = GPOINTER_TO_INT (data); + gint i; + + for (i = 0; i < NUM_MESSAGES; i++) { + GstMessage *m; + GstStructure *s; + + s = gst_structure_new ("test_message", + "thread_id", G_TYPE_INT, thread_id, "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + } + return NULL; +} + +static void +pull_messages (void) +{ + GstMessage *m; + const GstStructure *s; + guint message_ids[NUM_THREADS]; + gint i; + + for (i = 0; i < NUM_THREADS; i++) + message_ids[i] = 0; + + while (1) { + gint _t, _i; + + m = gst_bus_pop (test_bus); + if (!m) + break; + g_return_if_fail (GST_MESSAGE_TYPE (m) == GST_MESSAGE_APPLICATION); + + s = gst_message_get_structure (m); + if (!gst_structure_get_int (s, "thread_id", &_t)) + g_critical ("Invalid message"); + if (!gst_structure_get_int (s, "msg_id", &_i)) + g_critical ("Invalid message"); + + g_return_if_fail (_t < NUM_THREADS); + g_return_if_fail (_i == message_ids[_t]++); + + gst_message_unref (m); + } + + for (i = 0; i < NUM_THREADS; i++) + g_return_if_fail (message_ids[i] == NUM_MESSAGES); +} + +GST_START_TEST (test_hammer_bus) +{ + GThread *threads[NUM_THREADS]; + gint i; + + test_bus = gst_bus_new (); + + for (i = 0; i < NUM_THREADS; i++) + threads[i] = g_thread_try_new ("gst-check", pound_bus_with_messages, + GINT_TO_POINTER (i), NULL); + + for (i = 0; i < NUM_THREADS; i++) + g_thread_join (threads[i]); + + pull_messages (); + + gst_object_unref ((GstObject *) test_bus); +} + +GST_END_TEST; + +static gboolean +message_func_eos (GstBus * bus, GstMessage * message, guint * p_counter) +{ + const GstStructure *s; + gint i; + + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS, FALSE); + + GST_DEBUG ("got EOS message"); + + s = gst_message_get_structure (message); + if (!gst_structure_get_int (s, "msg_id", &i)) + g_critical ("Invalid message"); + + if (p_counter != NULL) + *p_counter += 1; + + return i != 9; +} + +static gboolean +message_func_app (GstBus * bus, GstMessage * message, guint * p_counter) +{ + const GstStructure *s; + gint i; + + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_APPLICATION, + FALSE); + + GST_DEBUG ("got APP message"); + + s = gst_message_get_structure (message); + if (!gst_structure_get_int (s, "msg_id", &i)) + g_critical ("Invalid message"); + + if (p_counter != NULL) + *p_counter += 1; + + return i != 9; +} + +static gboolean +send_messages (gpointer data) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 10; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_custom (GST_MESSAGE_EOS, NULL, s); + gst_bus_post (test_bus, m); + } + + return FALSE; +} + +/* test if adding a signal watch for different message types calls the + * respective callbacks. */ +GST_START_TEST (test_watch) +{ + guint num_eos = 0; + guint num_app = 0; + guint id; + + test_bus = gst_bus_new (); + + main_loop = g_main_loop_new (NULL, FALSE); + + id = gst_bus_add_watch (test_bus, gst_bus_async_signal_func, NULL); + fail_if (id == 0); + g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos, + &num_eos); + g_signal_connect (test_bus, "message::application", + (GCallback) message_func_app, &num_app); + + g_idle_add ((GSourceFunc) send_messages, NULL); + while (g_main_context_pending (NULL)) + g_main_context_iteration (NULL, FALSE); + + fail_unless_equals_int (num_eos, 10); + fail_unless_equals_int (num_app, 10); + + fail_unless (gst_bus_remove_watch (test_bus)); + g_main_loop_unref (main_loop); + + gst_object_unref ((GstObject *) test_bus); +} + +GST_END_TEST; + +/* test if adding a signal watch for different message types calls the + * respective callbacks. */ +GST_START_TEST (test_watch_with_custom_context) +{ + GMainContext *ctx; + GSource *source; + guint num_eos = 0; + guint num_app = 0; + guint id; + + test_bus = gst_bus_new (); + + ctx = g_main_context_new (); + main_loop = g_main_loop_new (ctx, FALSE); + + source = gst_bus_create_watch (test_bus); + g_source_set_callback (source, (GSourceFunc) gst_bus_async_signal_func, NULL, + NULL); + id = g_source_attach (source, ctx); + g_source_unref (source); + fail_if (id == 0); + + g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos, + &num_eos); + g_signal_connect (test_bus, "message::application", + (GCallback) message_func_app, &num_app); + + source = g_idle_source_new (); + g_source_set_callback (source, (GSourceFunc) send_messages, NULL, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + while (g_main_context_pending (ctx)) + g_main_context_iteration (ctx, FALSE); + + fail_unless_equals_int (num_eos, 10); + fail_unless_equals_int (num_app, 10); + + if ((source = g_main_context_find_source_by_id (ctx, id))) + g_source_destroy (source); + g_main_loop_unref (main_loop); + g_main_context_unref (ctx); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +/* test if adding a signal watch for different message types calls the + * respective callbacks. */ +GST_START_TEST (test_add_watch_with_custom_context) +{ + GMainContext *ctx; + GSource *source; + guint num_eos = 0; + guint num_app = 0; + + test_bus = gst_bus_new (); + + ctx = g_main_context_new (); + main_loop = g_main_loop_new (ctx, FALSE); + + g_main_context_push_thread_default (ctx); + gst_bus_add_signal_watch (test_bus); + g_main_context_pop_thread_default (ctx); + + g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos, + &num_eos); + g_signal_connect (test_bus, "message::application", + (GCallback) message_func_app, &num_app); + + source = g_idle_source_new (); + g_source_set_callback (source, (GSourceFunc) send_messages, NULL, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + while (g_main_context_pending (ctx)) + g_main_context_iteration (ctx, FALSE); + + fail_unless_equals_int (num_eos, 10); + fail_unless_equals_int (num_app, 10); + + g_main_loop_unref (main_loop); + g_main_context_unref (ctx); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +static gboolean +dummy_bus_func (GstBus * bus, GstMessage * msg, gpointer user_data) +{ + return TRUE; +} + +GST_START_TEST (test_remove_watch) +{ + test_bus = gst_bus_new (); + + /* removing a non-existing watch should fail */ + fail_if (gst_bus_remove_watch (test_bus)); + + gst_bus_add_watch (test_bus, dummy_bus_func, NULL); + + fail_unless (gst_bus_remove_watch (test_bus)); + + /* now it should fail to remove the watch again */ + fail_if (gst_bus_remove_watch (test_bus)); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +static gint messages_seen; + +static void +message_func (GstBus * bus, GstMessage * message, gpointer data) +{ + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_APPLICATION); + + messages_seen++; +} + +static void +send_5app_1el_1err_2app_1eos_messages (guint interval_usecs) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 5; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + GST_LOG ("posting application message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 1; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_element (NULL, s); + GST_LOG ("posting element message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 1; i++) { + m = gst_message_new_error (NULL, NULL, "debug string"); + GST_LOG ("posting error message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 2; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + GST_LOG ("posting application message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 1; i++) { + m = gst_message_new_eos (NULL); + GST_LOG ("posting EOS message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } +} + +static void +send_extended_messages (guint interval_usecs) +{ + GstMessage *msg; + GstDevice *device; + + device = g_object_new (foo_device_get_type (), NULL); + + msg = gst_message_new_device_added (NULL, device); + GST_LOG ("posting device-added message"); + gst_bus_post (test_bus, msg); + g_usleep (interval_usecs); + + msg = gst_message_new_device_removed (NULL, device); + GST_LOG ("posting device-removed message"); + gst_bus_post (test_bus, msg); + g_usleep (interval_usecs); + + gst_object_unref (device); +} + + +static void +send_10_app_messages (void) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 10; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + } +} + +/* test that you get the same messages from a poll as from signal watches. */ +GST_START_TEST (test_watch_with_poll) +{ + guint i; + + test_bus = gst_bus_new (); + messages_seen = 0; + + gst_bus_add_signal_watch (test_bus); + g_signal_connect (test_bus, "message", (GCallback) message_func, NULL); + + send_10_app_messages (); + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_poll (test_bus, GST_MESSAGE_APPLICATION, + GST_CLOCK_TIME_NONE)); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + fail_unless (messages_seen == 10, "signal handler didn't get 10 messages"); + + gst_bus_remove_signal_watch (test_bus); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +/* test that you get the messages with pop. */ +GST_START_TEST (test_timed_pop) +{ + guint i; + + test_bus = gst_bus_new (); + + send_10_app_messages (); + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_timed_pop (test_bus, GST_CLOCK_TIME_NONE)); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +typedef struct +{ + GstDevice device; +} FooDevice; +typedef struct +{ + GstDeviceClass device_klass; +} FooDeviceClass; + +G_DEFINE_TYPE (FooDevice, foo_device, GST_TYPE_DEVICE); + +static void +foo_device_class_init (FooDeviceClass * klass) +{ + /* nothing to do here */ +} + +static void +foo_device_init (FooDevice * device) +{ + /* nothing to do here */ +} + +/* test that you get the messages with pop_filtered */ +GST_START_TEST (test_timed_pop_filtered) +{ + GstMessage *msg; + guint i; + + test_bus = gst_bus_new (); + + send_10_app_messages (); + for (i = 0; i < 10; i++) { + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_ANY); + fail_unless (msg != NULL); + gst_message_unref (msg); + } + + /* should flush all messages on the bus with types not matching */ + send_10_app_messages (); + msg = gst_bus_timed_pop_filtered (test_bus, 0, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg == NULL); + msg = gst_bus_timed_pop_filtered (test_bus, GST_SECOND / 2, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg == NULL); + /* there should be nothing on the bus now */ + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_ANY); + fail_unless (msg == NULL); + + send_5app_1el_1err_2app_1eos_messages (0); + msg = gst_bus_timed_pop_filtered (test_bus, 0, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + gst_message_unref (msg); + fail_unless (gst_bus_have_pending (test_bus), "expected messages on bus"); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_ERROR); + fail_unless (msg == NULL); + + gst_object_unref (test_bus); + + /* Test extended messages */ + GST_DEBUG + ("Checking extended messages received from gst_bus_timed_pop_filtered"); + test_bus = gst_bus_new (); + + send_5app_1el_1err_2app_1eos_messages (0); + send_extended_messages (0); + send_5app_1el_1err_2app_1eos_messages (0); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_EXTENDED); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_DEVICE_ADDED); + gst_message_unref (msg); + + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_EXTENDED); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_DEVICE_REMOVED); + gst_message_unref (msg); + gst_object_unref (test_bus); + + /* Now check extended messages don't appear when we don't ask for them */ + GST_DEBUG + ("Checking extended messages *not* received from gst_bus_timed_pop_filtered when not wanted"); + test_bus = gst_bus_new (); + + send_extended_messages (0); + send_5app_1el_1err_2app_1eos_messages (0); + + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + gst_message_unref (msg); + + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_EOS); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS); + gst_message_unref (msg); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +static gpointer +post_delayed_thread (gpointer data) +{ + THREAD_START (); + send_5app_1el_1err_2app_1eos_messages (1 * G_USEC_PER_SEC); + return NULL; +} + +/* test that you get the messages with pop_filtered if there's a timeout*/ +GST_START_TEST (test_timed_pop_filtered_with_timeout) +{ + GstMessage *msg; + + MAIN_INIT (); + + test_bus = gst_bus_new (); + + MAIN_START_THREAD_FUNCTIONS (1, post_delayed_thread, NULL); + + MAIN_SYNCHRONIZE (); + + msg = gst_bus_timed_pop_filtered (test_bus, 2 * GST_SECOND, + GST_MESSAGE_ERROR); + fail_unless (msg == NULL, "Got unexpected %s message", + (msg) ? GST_MESSAGE_TYPE_NAME (msg) : ""); + msg = gst_bus_timed_pop_filtered (test_bus, (3 + 1 + 1 + 1) * GST_SECOND, + GST_MESSAGE_ERROR | GST_MESSAGE_ELEMENT); + fail_unless (msg != NULL, "expected element message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL, "expected application message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL, "expected application message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_SECOND / 4, + GST_MESSAGE_TAG | GST_MESSAGE_ERROR); + fail_unless (msg == NULL, "Got unexpected %s message", + (msg) ? GST_MESSAGE_TYPE_NAME (msg) : ""); + + MAIN_STOP_THREADS (); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +/* test that you get the messages with pop from another thread. */ +static gpointer +pop_thread (gpointer data) +{ + GstBus *bus = GST_BUS_CAST (data); + guint i; + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE)); + + return NULL; +} + +GST_START_TEST (test_timed_pop_thread) +{ + GThread *thread; + GError *error = NULL; + + test_bus = gst_bus_new (); + + thread = g_thread_try_new ("gst-chek", pop_thread, test_bus, &error); + fail_if (error != NULL); + + send_10_app_messages (); + + g_thread_join (thread); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + + /* try to pop a message without timeout. */ + fail_if (gst_bus_timed_pop (test_bus, 0) != NULL); + + /* with a small timeout */ + fail_if (gst_bus_timed_pop (test_bus, 1000) != NULL); + + gst_object_unref (test_bus); +} + +GST_END_TEST; + +static gboolean +cb_bus_call (GstBus * bus, GstMessage * msg, gpointer data) +{ + GMainLoop *loop = data; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + { + GST_INFO ("End-of-stream"); + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_ERROR: + { + GError *err = NULL; + + gst_message_parse_error (msg, &err, NULL); + g_error ("Error: %s", err->message); + g_error_free (err); + + g_main_loop_quit (loop); + break; + } + default: + { + GST_LOG ("BUS MESSAGE: type=%s", GST_MESSAGE_TYPE_NAME (msg)); + break; + } + } + + return TRUE; +} + +GST_START_TEST (test_custom_main_context) +{ + GMainContext *ctx; + GMainLoop *loop; + GstElement *pipeline; + GstElement *src; + GstElement *sink; + GSource *source; + GstBus *bus; + + ctx = g_main_context_new (); + loop = g_main_loop_new (ctx, FALSE); + + pipeline = gst_pipeline_new (NULL); + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", 2000, NULL); + + sink = gst_element_factory_make ("fakesink", NULL); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (src, sink)); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + source = gst_bus_create_watch (bus); + g_source_attach (source, ctx); + g_source_set_callback (source, (GSourceFunc) cb_bus_call, loop, NULL); + g_source_unref (source); + gst_object_unref (bus); + + GST_INFO ("starting pipeline"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + GST_INFO ("running event loop, ctx=%p", ctx); + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + /* clean up */ + if (ctx) + g_main_context_unref (ctx); + g_main_loop_unref (loop); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstBusSyncReply +test_async_sync_handler (GstBus * bus, GstMessage * msg, gpointer user_data) +{ + GArray *timestamps = user_data; + gint64 ts = g_get_monotonic_time () * 1000; /* microsecs -> nanosecs */ + + g_array_append_val (timestamps, ts); + GST_INFO ("[msg %p] %" GST_PTR_FORMAT, msg, msg); + + return GST_BUS_ASYNC; +} + +static gpointer +post_10_app_messages_thread (gpointer data) +{ + THREAD_START (); + send_10_app_messages (); + return NULL; +} + +/* Test GST_BUS_ASYNC actually causes the thread posting the message to + * block until the message has been freed. We spawn a thread to post ten + * messages. We install a bus sync handler to get the timestamp of each + * message as it is being posted, and to return GST_BUS_ASYNC. In the main + * thread we sleep a bit after we pop off a message and before we free it. + * The posting thread should be blocked while the main thread sleeps, so + * we expect the interval as the messages are posted to be roughly the same + * as the sleep time in the main thread. g_usleep() is not super-precise, so + * we allow for some slack there, we just want to check that the posting + * thread was blocked at all really. */ +GST_START_TEST (test_async_message) +{ + GArray *timestamps; + guint i; + + MAIN_INIT (); + + timestamps = g_array_sized_new (FALSE, FALSE, sizeof (gint64), 10); + + test_bus = gst_bus_new (); + + gst_bus_set_sync_handler (test_bus, test_async_sync_handler, timestamps, + NULL); + + MAIN_START_THREAD_FUNCTIONS (1, post_10_app_messages_thread, NULL); + + MAIN_SYNCHRONIZE (); + + for (i = 0; i < 10; i++) { + GstMessage *msg; + + GST_LOG ("(%d) waiting for message..", i); + msg = gst_bus_timed_pop (test_bus, GST_CLOCK_TIME_NONE); + GST_LOG ("(%d) got message, sleeping a bit", i); + g_usleep (60 * GST_MSECOND / (GST_SECOND / G_USEC_PER_SEC)); + GST_LOG ("(%d) about to free message", i); + gst_message_unref (msg); + } + + for (i = 1; i < 10; i++) { + gint64 prev_ts = g_array_index (timestamps, gint64, i - 1); + gint64 ts = g_array_index (timestamps, gint64, i); + gint64 diff = ts - prev_ts; + + fail_unless (prev_ts < ts); + fail_unless (diff >= 20 * GST_MSECOND, "interval between messages being " + "posted was just %" G_GINT64_FORMAT "ms", diff / GST_MSECOND); + } + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + + MAIN_STOP_THREADS (); + + gst_object_unref (test_bus); + + g_array_unref (timestamps); +} + +GST_END_TEST; + +static Suite * +gst_bus_suite (void) +{ + Suite *s = suite_create ("GstBus"); + TCase *tc_chain = tcase_create ("stresstest"); + + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_hammer_bus); + tcase_add_test (tc_chain, test_watch); + tcase_add_test (tc_chain, test_watch_with_poll); + tcase_add_test (tc_chain, test_watch_with_custom_context); + tcase_add_test (tc_chain, test_add_watch_with_custom_context); + tcase_add_test (tc_chain, test_remove_watch); + tcase_add_test (tc_chain, test_timed_pop); + tcase_add_test (tc_chain, test_timed_pop_thread); + tcase_add_test (tc_chain, test_timed_pop_filtered); + tcase_add_test (tc_chain, test_timed_pop_filtered_with_timeout); + tcase_add_test (tc_chain, test_custom_main_context); + tcase_add_test (tc_chain, test_async_message); + return s; +} + +GST_CHECK_MAIN (gst_bus); diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c new file mode 100644 index 0000000..a85a033 --- /dev/null +++ b/tests/check/gst/gstcaps.c @@ -0,0 +1,1429 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * Copyright (C) <2005> Thomas Vander Stichele + * + * gstcaps.c: Unit test for GstCaps + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "capslist.h" + +GST_START_TEST (test_from_string) +{ + GstCaps *caps; + GstCaps *caps2; + gchar *to_str; + int i; + + for (i = 0; i < G_N_ELEMENTS (caps_list); i++) { + caps = gst_caps_from_string (caps_list[i]); + fail_if (caps == NULL, + "Could not create caps from string %s\n", caps_list[i]); + to_str = gst_caps_to_string (caps); + fail_if (to_str == NULL, + "Could not convert caps back to string %s\n", caps_list[i]); + caps2 = gst_caps_from_string (to_str); + fail_if (caps2 == NULL, "Could not create caps from string %s\n", to_str); + + fail_unless (gst_caps_is_equal (caps, caps)); + fail_unless (gst_caps_is_equal (caps, caps2)); + + gst_caps_unref (caps); + gst_caps_unref (caps2); + g_free (to_str); + } +} + +GST_END_TEST; + +GST_START_TEST (test_double_append) +{ + GstStructure *s1; + GstCaps *c1; + + c1 = gst_caps_new_any (); + s1 = gst_structure_from_string ("audio/x-raw,rate=44100", NULL); + gst_caps_append_structure (c1, s1); + ASSERT_CRITICAL (gst_caps_append_structure (c1, s1)); + + gst_caps_unref (c1); +} + +GST_END_TEST; + +GST_START_TEST (test_mutability) +{ + GstStructure *s1; + GstCaps *c1; + gint ret; + + c1 = gst_caps_new_any (); + s1 = gst_structure_from_string ("audio/x-raw,rate=44100", NULL); + gst_structure_set (s1, "rate", G_TYPE_INT, 48000, NULL); + gst_caps_append_structure (c1, s1); + gst_structure_set (s1, "rate", G_TYPE_INT, 22500, NULL); + gst_caps_ref (c1); + ASSERT_CRITICAL (gst_structure_set (s1, "rate", G_TYPE_INT, 11250, NULL)); + fail_unless (gst_structure_get_int (s1, "rate", &ret)); + fail_unless (ret == 22500); + ASSERT_CRITICAL (gst_caps_set_simple (c1, "rate", G_TYPE_INT, 11250, NULL)); + fail_unless (gst_structure_get_int (s1, "rate", &ret)); + fail_unless (ret == 22500); + gst_caps_unref (c1); + gst_structure_set (s1, "rate", G_TYPE_INT, 11250, NULL); + fail_unless (gst_structure_get_int (s1, "rate", &ret)); + fail_unless (ret == 11250); + gst_caps_set_simple (c1, "rate", G_TYPE_INT, 1, NULL); + fail_unless (gst_structure_get_int (s1, "rate", &ret)); + fail_unless (ret == 1); + gst_caps_unref (c1); +} + +GST_END_TEST; + +GST_START_TEST (test_static_caps) +{ + static GstStaticCaps scaps = GST_STATIC_CAPS ("audio/x-raw,rate=44100"); + GstCaps *caps1; + GstCaps *caps2; + static GstStaticCaps sany = GST_STATIC_CAPS_ANY; + static GstStaticCaps snone = GST_STATIC_CAPS_NONE; + + /* caps creation */ + caps1 = gst_static_caps_get (&scaps); + fail_unless (caps1 != NULL); + /* 1 refcount core, one from us */ + fail_unless (GST_CAPS_REFCOUNT (caps1) == 2); + + /* caps should be the same */ + caps2 = gst_static_caps_get (&scaps); + fail_unless (caps2 != NULL); + /* 1 refcount core, two from us */ + fail_unless (GST_CAPS_REFCOUNT (caps1) == 3); + /* caps must be equal */ + fail_unless (caps1 == caps2); + + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + caps1 = gst_static_caps_get (&sany); + fail_unless (gst_caps_is_equal (caps1, GST_CAPS_ANY)); + caps2 = gst_static_caps_get (&snone); + fail_unless (gst_caps_is_equal (caps2, GST_CAPS_NONE)); + fail_if (gst_caps_is_equal (caps1, caps2)); + gst_caps_unref (caps1); + gst_caps_unref (caps2); +} + +GST_END_TEST; + +static const gchar non_simple_caps_string[] = + "video/x-raw, format=(string)I420, framerate=(fraction)[ 1/100, 100 ], " + "width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw, " + "format=(string)YUY2, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " + "height=(int)[ 16, 4096 ]; video/x-raw, format=(string)RGB8_PALETTED, " + "framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " + "height=(int)[ 16, 4096 ]; video/x-raw, " + "format=(string){ I420, YUY2, YV12 }, width=(int)[ 16, 4096 ], " + "height=(int)[ 16, 4096 ], framerate=(fraction)[ 1/100, 100 ]"; + +static gboolean +check_string_list (const GValue * format_value) +{ + const GValue *string_value; + gboolean got_rgb8 = FALSE; + gboolean got_yv12 = FALSE; + gboolean got_i420 = FALSE; + gboolean got_yuy2 = FALSE; + const gchar *string; + + string_value = gst_value_list_get_value (format_value, 0); + fail_unless (string_value != NULL); + fail_unless (G_VALUE_HOLDS_STRING (string_value)); + string = g_value_get_string (string_value); + fail_unless (string != NULL); + got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED")); + got_i420 = got_i420 || (g_str_equal (string, "I420")); + got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2")); + got_yv12 = got_yv12 || (g_str_equal (string, "YV12")); + + string_value = gst_value_list_get_value (format_value, 1); + fail_unless (string_value != NULL); + fail_unless (G_VALUE_HOLDS_STRING (string_value)); + string = g_value_get_string (string_value); + fail_unless (string != NULL); + got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED")); + got_i420 = got_i420 || (g_str_equal (string, "I420")); + got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2")); + got_yv12 = got_yv12 || (g_str_equal (string, "YV12")); + + string_value = gst_value_list_get_value (format_value, 2); + fail_unless (string_value != NULL); + fail_unless (G_VALUE_HOLDS_STRING (string_value)); + string = g_value_get_string (string_value); + fail_unless (string != NULL); + got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED")); + got_i420 = got_i420 || (g_str_equal (string, "I420")); + got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2")); + got_yv12 = got_yv12 || (g_str_equal (string, "YV12")); + + string_value = gst_value_list_get_value (format_value, 3); + fail_unless (string_value != NULL); + fail_unless (G_VALUE_HOLDS_STRING (string_value)); + string = g_value_get_string (string_value); + fail_unless (string != NULL); + got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED")); + got_i420 = got_i420 || (g_str_equal (string, "I420")); + got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2")); + got_yv12 = got_yv12 || (g_str_equal (string, "YV12")); + + return (got_rgb8 && got_i420 && got_yuy2 && got_yv12); +} + +GST_START_TEST (test_simplify) +{ + GstStructure *s1; + GstCaps *caps; + + caps = gst_caps_from_string (non_simple_caps_string); + fail_unless (caps != NULL, + "gst_caps_from_string (non_simple_caps_string) failed"); + + caps = gst_caps_simplify (caps); + fail_unless (caps != NULL, "gst_caps_simplify() should have worked"); + + /* check simplified caps, should be: + * + * video/x-raw, format=(string){ RGB8_PALETTED, YV12, YUY2, I420 }, + * width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], + * framerate=(fraction)[ 1/100, 100 ] + */ + GST_DEBUG ("simplyfied %" GST_PTR_FORMAT, caps); + fail_unless (gst_caps_get_size (caps) == 1); + s1 = gst_caps_get_structure (caps, 0); + fail_unless (s1 != NULL); + + fail_unless (gst_structure_has_name (s1, "video/x-raw")); + { + const GValue *framerate_value; + const GValue *format_value; + const GValue *width_value; + const GValue *height_value; + const GValue *val_fps; + GValue test_fps = { 0, }; + gint min_width, max_width; + gint min_height, max_height; + + format_value = gst_structure_get_value (s1, "format"); + fail_unless (format_value != NULL); + fail_unless (GST_VALUE_HOLDS_LIST (format_value)); + fail_unless (gst_value_list_get_size (format_value) == 4); + fail_unless (check_string_list (format_value) == TRUE); + + g_value_init (&test_fps, GST_TYPE_FRACTION); + framerate_value = gst_structure_get_value (s1, "framerate"); + fail_unless (framerate_value != NULL); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value)); + + val_fps = gst_value_get_fraction_range_min (framerate_value); + gst_value_set_fraction (&test_fps, 1, 100); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + val_fps = gst_value_get_fraction_range_max (framerate_value); + gst_value_set_fraction (&test_fps, 100, 1); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + g_value_unset (&test_fps); + + width_value = gst_structure_get_value (s1, "width"); + fail_unless (width_value != NULL); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (width_value)); + min_width = gst_value_get_int_range_min (width_value); + max_width = gst_value_get_int_range_max (width_value); + fail_unless (min_width == 16 && max_width == 4096); + + height_value = gst_structure_get_value (s1, "height"); + fail_unless (height_value != NULL); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (height_value)); + min_height = gst_value_get_int_range_min (height_value); + max_height = gst_value_get_int_range_max (height_value); + fail_unless (min_height == 16 && max_height == 4096); + } + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_truncate) +{ + GstCaps *caps; + + caps = gst_caps_from_string (non_simple_caps_string); + fail_unless (caps != NULL, + "gst_caps_from_string (non_simple_caps_string) failed"); + fail_unless_equals_int (gst_caps_get_size (caps), 4); + caps = gst_caps_truncate (caps); + fail_unless_equals_int (gst_caps_get_size (caps), 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_subset) +{ + GstCaps *c1, *c2; + + c1 = gst_caps_from_string ("video/x-raw; video/x-raw"); + c2 = gst_caps_from_string ("video/x-raw, format=(string)YUY2"); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_if (gst_caps_is_subset (c1, c2)); + gst_caps_unref (c1); + gst_caps_unref (c2); + + c1 = gst_caps_from_string + ("audio/x-raw, channels=(int)[ 1, 2 ], rate=(int)44100"); + c2 = gst_caps_from_string ("audio/x-raw, channels=(int)1, rate=(int)44100"); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_if (gst_caps_is_subset (c1, c2)); + gst_caps_unref (c1); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("audio/x-raw, channels=(int) {1}"); + c2 = gst_caps_from_string ("audio/x-raw, channels=(int)1"); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_equal (c1, c2)); + gst_caps_unref (c1); + gst_caps_unref (c2); + + c1 = gst_caps_from_string + ("audio/x-raw, rate=(int)44100, channels=(int)3, format=(string)U16_LE"); + c2 = gst_caps_from_string + ("audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], format=(string){ S16_LE, U16_LE }"); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_if (gst_caps_is_subset (c2, c1)); + gst_caps_unref (c1); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("video/x-h264, parsed=(boolean)true"); + c2 = gst_caps_from_string + ("video/x-h264, stream-format=(string)byte-stream, alignment=(string)nal"); + fail_if (gst_caps_is_subset (c2, c1)); + fail_if (gst_caps_is_subset (c1, c2)); + fail_if (gst_caps_is_equal (c1, c2)); + gst_caps_unref (c1); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_subset_duplication) +{ + GstCaps *c1, *c2; + + c1 = gst_caps_from_string ("audio/x-raw, format=(string)F32LE"); + c2 = gst_caps_from_string ("audio/x-raw, format=(string)F32LE"); + + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + + gst_caps_unref (c2); + c2 = gst_caps_from_string ("audio/x-raw, format=(string){ F32LE }"); + + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + + gst_caps_unref (c2); + c2 = gst_caps_from_string ("audio/x-raw, format=(string){ F32LE, F32LE }"); + + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + + gst_caps_unref (c2); + c2 = gst_caps_from_string + ("audio/x-raw, format=(string){ F32LE, F32LE, F32LE }"); + + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + + gst_caps_unref (c1); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_merge_fundamental) +{ + GstCaps *c1, *c2; + + /* ANY + specific = ANY */ + c1 = gst_caps_from_string ("audio/x-raw,rate=44100"); + c2 = gst_caps_new_any (); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 0, NULL); + fail_unless (gst_caps_is_any (c2), NULL); + gst_caps_unref (c2); + + /* specific + ANY = ANY */ + c2 = gst_caps_from_string ("audio/x-raw,rate=44100"); + c1 = gst_caps_new_any (); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 0, NULL); + fail_unless (gst_caps_is_any (c2), NULL); + gst_caps_unref (c2); + + /* EMPTY + specific = specific */ + c1 = gst_caps_from_string ("audio/x-raw,rate=44100"); + c2 = gst_caps_new_empty (); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + fail_if (gst_caps_is_empty (c2), NULL); + gst_caps_unref (c2); + + /* specific + EMPTY = specific */ + c2 = gst_caps_from_string ("audio/x-raw,rate=44100"); + c1 = gst_caps_new_empty (); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + fail_if (gst_caps_is_empty (c2), NULL); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_merge_same) +{ + GstCaps *c1, *c2, *test; + + /* this is the same */ + c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1"); + c2 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (test); + gst_caps_unref (c2); + + /* and so is this */ + c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1"); + c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA"); + c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AABB"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AABB"); + c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AA"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA"); + c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AA"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + gst_caps_unref (c2); + + c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA"); + c2 = gst_caps_from_string ("video/x-bar, data=(buffer)AA"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_merge_subset) +{ + GstCaps *c1, *c2, *test; + + /* the 2nd is already covered */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=1"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,2]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* here it is not */ + c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* second one was already contained in the first one */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,3]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,3]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* second one was already contained in the first one */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* second one was already contained in the first one */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[2,4]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* second one was already contained in the first one */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[2,3]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* these caps cannot be merged */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[2,3]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[1,4]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = + gst_caps_from_string + ("audio/x-raw,channels=[2,3];audio/x-raw,channels=[1,4]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* these caps cannot be merged */ + c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]"); + c1 = gst_caps_from_string ("audio/x-raw,channels=[1,3]"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = + gst_caps_from_string + ("audio/x-raw,channels=[1,2];audio/x-raw,channels=[1,3]"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}"); + c1 = gst_caps_from_string ("audio/x-raw,channels={1,2,3,4}"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = gst_caps_from_string ("audio/x-raw,channels={1,2};" + "audio/x-raw,channels={1,2,3,4}"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}"); + c1 = gst_caps_from_string ("audio/x-raw,channels={1,3}"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = gst_caps_from_string ("audio/x-raw,channels={1,2};" + "audio/x-raw,channels={1,3}"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + c2 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/2, 5/1 }"); + c1 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/1, 5/1 }"); + test = gst_caps_copy (c1); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_is_subset (test, c2)); + gst_caps_unref (test); + gst_caps_unref (c2); + + c2 = gst_caps_from_string ("audio/x-raw"); + c1 = gst_caps_from_string ("audio/x-raw,channels=1"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 1, NULL); + test = gst_caps_from_string ("audio/x-raw"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); + + c2 = gst_caps_from_string ("audio/x-raw,channels=1"); + c1 = gst_caps_from_string ("audio/x-raw"); + c2 = gst_caps_merge (c2, c1); + GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2); + fail_unless (gst_caps_get_size (c2) == 2, NULL); + test = gst_caps_from_string ("audio/x-raw,channels=1; audio/x-raw"); + fail_unless (gst_caps_is_equal (c2, test)); + gst_caps_unref (c2); + gst_caps_unref (test); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect) +{ + GstStructure *s; + GstCaps *c1, *c2, *ci1, *ci2; + + /* field not specified = any value possible, so the intersection + * should keep fields which are only part of one set of caps */ + c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20"); + c1 = gst_caps_from_string ("video/x-raw,format=(string)I420"); + + ci1 = gst_caps_intersect (c2, c1); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1); + fail_unless (gst_caps_get_size (ci1) == 1, NULL); + s = gst_caps_get_structure (ci1, 0); + fail_unless (gst_structure_has_name (s, "video/x-raw")); + fail_unless (gst_structure_get_value (s, "format") != NULL); + fail_unless (gst_structure_get_value (s, "width") != NULL); + + /* with changed order */ + ci2 = gst_caps_intersect (c1, c2); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2); + fail_unless (gst_caps_get_size (ci2) == 1, NULL); + s = gst_caps_get_structure (ci2, 0); + fail_unless (gst_structure_has_name (s, "video/x-raw")); + fail_unless (gst_structure_get_value (s, "format") != NULL); + fail_unless (gst_structure_get_value (s, "width") != NULL); + + fail_unless (gst_caps_is_equal (ci1, ci2)); + + gst_caps_unref (ci1); + gst_caps_unref (ci2); + + gst_caps_unref (c1); + gst_caps_unref (c2); + + /* ========== */ + + c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20"); + c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=30"); + + ci1 = gst_caps_intersect (c2, c1); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1); + fail_unless (gst_caps_is_empty (ci1), NULL); + + /* with changed order */ + ci2 = gst_caps_intersect (c1, c2); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2); + fail_unless (gst_caps_is_empty (ci2), NULL); + + fail_unless (gst_caps_is_equal (ci1, ci2)); + + gst_caps_unref (ci1); + gst_caps_unref (ci2); + + gst_caps_unref (c1); + gst_caps_unref (c2); + + /* ========== */ + + c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20"); + c1 = gst_caps_from_string ("video/x-raw2,format=(string)I420,width=20"); + + ci1 = gst_caps_intersect (c2, c1); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1); + fail_unless (gst_caps_is_empty (ci1), NULL); + + /* with changed order */ + ci2 = gst_caps_intersect (c1, c2); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2); + fail_unless (gst_caps_is_empty (ci2), NULL); + + fail_unless (gst_caps_is_equal (ci1, ci2)); + + gst_caps_unref (ci1); + gst_caps_unref (ci2); + + gst_caps_unref (c1); + gst_caps_unref (c2); + + /* ========== */ + + c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20"); + c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,height=30"); + + ci1 = gst_caps_intersect (c2, c1); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1); + fail_unless (gst_caps_get_size (ci1) == 1, NULL); + s = gst_caps_get_structure (ci1, 0); + fail_unless (gst_structure_has_name (s, "video/x-raw")); + fail_unless (gst_structure_get_value (s, "format") != NULL); + fail_unless (gst_structure_get_value (s, "width") != NULL); + fail_unless (gst_structure_get_value (s, "height") != NULL); + + /* with changed order */ + ci2 = gst_caps_intersect (c1, c2); + GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2); + fail_unless (gst_caps_get_size (ci2) == 1, NULL); + s = gst_caps_get_structure (ci2, 0); + fail_unless (gst_structure_has_name (s, "video/x-raw")); + fail_unless (gst_structure_get_value (s, "format") != NULL); + fail_unless (gst_structure_get_value (s, "height") != NULL); + fail_unless (gst_structure_get_value (s, "width") != NULL); + + fail_unless (gst_caps_is_equal (ci1, ci2)); + + gst_caps_unref (ci1); + gst_caps_unref (ci2); + + gst_caps_unref (c1); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect2) +{ + GstCaps *caps1, *caps2, *icaps; + + /* tests array subtraction */ + caps1 = gst_caps_from_string ("audio/x-raw, " + "channel-positions=(int)< " + "{ 1, 2, 3, 4, 5, 6 }, " + "{ 1, 2, 3, 4, 5, 6 }, " + "{ 1, 2, 3, 4, 5, 6 }, " + "{ 1, 2, 3, 4, 5, 6 }, " + "{ 1, 2, 3, 4, 5, 6 }, " "{ 1, 2, 3, 4, 5, 6 }>"); + caps2 = gst_caps_from_string ("audio/x-raw, " + "channel-positions=(int)< 1, 2, 3, 4, 5, 6 >"); + icaps = gst_caps_intersect (caps1, caps2); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, caps2)); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + gst_caps_unref (icaps); + + /* ===== */ + + caps1 = gst_caps_from_string ("some/type, foo=(int)< { 1, 2 }, { 3, 4} >"); + caps2 = gst_caps_from_string ("some/type, foo=(int)< 1, 3 >"); + icaps = gst_caps_intersect (caps1, caps2); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, caps2)); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + gst_caps_unref (icaps); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect_list_duplicate) +{ + GstCaps *caps1, *caps2, *icaps; + + /* make sure we don't take too long to intersect these.. */ + caps1 = gst_caps_from_string ("video/x-raw, format=(string)YV12; " + "video/x-raw, format=(string)I420; video/x-raw, format=(string)YUY2; " + "video/x-raw, format=(string)UYVY; " + "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx," + " xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } } } } }, BGRA, ARGB, { ABGR, ABGR, " + "{ ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } } } }, " + "RGB, BGR, Y41B, Y42B, YVYU, Y444 }; " + "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, " + "xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } } } } }, BGRA, ARGB, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } } } }, " + "RGB, BGR, Y41B, Y42B, YVYU, Y444, NV12, NV21 }; " + "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, " + "BGRx, xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, " + "{ RGBA, RGBA, { RGBA, RGBA } } } }, BGRA, ARGB, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, " + "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, " + "RGB, BGR, Y41B, Y42B, YVYU, Y444, NV12, NV21 }"); + + caps2 = gst_caps_copy (caps1); + + icaps = gst_caps_intersect (caps1, caps2); + + gst_caps_unref (caps1); + gst_caps_unref (caps2); + gst_caps_unref (icaps); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect_zigzag) +{ + GstCaps *caps1, *caps2, *icaps, *result; + + /* tests if caps order is maintained */ + caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D"); + caps2 = gst_caps_from_string ("format/D; format/A; format/B; format/C"); + + icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG); + result = gst_caps_from_string ("format/B; format/A; format/D; format/C"); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, result)); + gst_caps_unref (icaps); + gst_caps_unref (result); + + icaps = gst_caps_intersect_full (caps2, caps1, GST_CAPS_INTERSECT_FIRST); + result = gst_caps_from_string ("format/A; format/B; format/D; format/C"); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, result)); + gst_caps_unref (icaps); + gst_caps_unref (result); + + gst_caps_unref (caps1); + gst_caps_unref (caps2); +} + +GST_END_TEST; + + +GST_START_TEST (test_intersect_first) +{ + GstCaps *caps1, *caps2, *icaps, *result; + + /* tests if caps order is maintained */ + caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D"); + caps2 = gst_caps_from_string ("format/C; format/D; format/A"); + icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_FIRST); + result = gst_caps_from_string ("format/A; format/C; format/D"); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, result)); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + gst_caps_unref (icaps); + gst_caps_unref (result); +} + +GST_END_TEST; + + +GST_START_TEST (test_intersect_first2) +{ + GstCaps *caps1, *caps2, *icaps, *result; + + /* tests if caps order is maintained */ + caps1 = gst_caps_from_string ("format/A; format/B; format/C; format/D"); + caps2 = gst_caps_from_string ("format/D; format/A; format/B; format/C"); + + icaps = gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_FIRST); + result = gst_caps_from_string ("format/A; format/B; format/C; format/D"); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, result)); + gst_caps_unref (icaps); + gst_caps_unref (result); + + icaps = gst_caps_intersect_full (caps2, caps1, GST_CAPS_INTERSECT_FIRST); + result = gst_caps_from_string ("format/D; format/A; format/B; format/C"); + GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps); + fail_if (gst_caps_is_empty (icaps)); + fail_unless (gst_caps_is_equal (icaps, result)); + gst_caps_unref (icaps); + gst_caps_unref (result); + + gst_caps_unref (caps1); + gst_caps_unref (caps2); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect_duplication) +{ + GstCaps *c1, *c2, *test; + + c1 = gst_caps_from_string + ("audio/x-raw, format=(string)S16_LE, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]"); + c2 = gst_caps_from_string + ("audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]; audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ]; audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ]"); + + test = gst_caps_intersect_full (c1, c2, GST_CAPS_INTERSECT_FIRST); + fail_unless_equals_int (gst_caps_get_size (test), 1); + fail_unless (gst_caps_is_equal (c1, test)); + gst_caps_unref (c1); + gst_caps_unref (c2); + gst_caps_unref (test); +} + +GST_END_TEST; + +GST_START_TEST (test_intersect_flagset) +{ + GstCaps *c1, *c2, *test; + GType test_flagset_type; + GstSeekFlags test_flags, test_mask; + gchar *test_string; + + /* Test that matching bits inside the mask intersect, + * and bits outside the mask don't matter */ + c1 = gst_caps_from_string ("test/x-caps,field=ffd81d:fffff0"); + c2 = gst_caps_from_string ("test/x-caps,field=0fd81f:0ffff0"); + + test = gst_caps_intersect_full (c1, c2, GST_CAPS_INTERSECT_FIRST); + fail_unless_equals_int (gst_caps_get_size (test), 1); + fail_unless (gst_caps_is_equal (c1, test)); + gst_caps_unref (c1); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* Test that non-matching bits in the mask don't intersect */ + c1 = gst_caps_from_string ("test/x-caps,field=ff001d:0ffff0"); + c2 = gst_caps_from_string ("test/x-caps,field=0fd81f:0ffff0"); + + test = gst_caps_intersect_full (c1, c2, GST_CAPS_INTERSECT_FIRST); + fail_unless (gst_caps_is_empty (test)); + gst_caps_unref (c1); + gst_caps_unref (c2); + gst_caps_unref (test); + + /* Check custom flags type serialisation and de-serialisation */ + test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS); + fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET)); + + test_flags = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE | + GST_SEEK_FLAG_TRICKMODE_KEY_UNITS; + test_mask = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE | + GST_SEEK_FLAG_TRICKMODE_NO_AUDIO; + + c1 = gst_caps_new_simple ("test/x-caps", "field", test_flagset_type, + test_flags, test_mask, NULL); + + test_string = gst_caps_to_string (c1); + fail_if (test_string == NULL); + + GST_DEBUG ("Serialised caps to %s", test_string); + c2 = gst_caps_from_string (test_string); + g_free (test_string); + + fail_unless (gst_caps_is_equal (c1, c2), "Caps %s != %s", + gst_caps_to_string (c1), gst_caps_to_string (c2)); + + gst_caps_unref (c1); + gst_caps_unref (c2); +} + +GST_END_TEST; + +GST_START_TEST (test_union) +{ + GstCaps *c1, *c2, *test, *expect; + + /* Test that matching bits inside the masks union OK, */ + c1 = gst_caps_from_string ("test/x-caps,field=ffd81d:0ffff0"); + c2 = gst_caps_from_string ("test/x-caps,field=0fd81f:0ffff0"); + + test = gst_caps_merge (c1, c2); + test = gst_caps_simplify (test); + /* c1, c2 now invalid */ + fail_unless_equals_int (gst_caps_get_size (test), 1); + gst_caps_unref (test); + + /* Test that non-intersecting sets of masked bits are OK */ + c1 = gst_caps_from_string ("test/x-caps,field=ff001d:0ffff0"); + c2 = gst_caps_from_string ("test/x-caps,field=4fd81f:f00000"); + expect = gst_caps_from_string ("test/x-caps,field=4f001d:fffff0"); + test = gst_caps_simplify (gst_caps_merge (c1, c2)); + /* c1, c2 now invalid */ + GST_LOG ("Expected caps %" GST_PTR_FORMAT " got %" GST_PTR_FORMAT "\n", + expect, test); + fail_unless (gst_caps_is_equal (test, expect)); + gst_caps_unref (test); + gst_caps_unref (expect); + + /* Test that partially-intersecting sets of masked bits that match are OK */ + c1 = gst_caps_from_string ("test/x-caps,field=ff001d:0ffff0"); + c2 = gst_caps_from_string ("test/x-caps,field=4fd81f:ff0000"); + expect = gst_caps_from_string ("test/x-caps,field=4f001d:fffff0"); + test = gst_caps_simplify (gst_caps_merge (c1, c2)); + /* c1, c2 now invalid */ + GST_LOG ("Expected caps %" GST_PTR_FORMAT " got %" GST_PTR_FORMAT "\n", + expect, test); + fail_unless (gst_caps_is_equal (test, expect)); + gst_caps_unref (test); + gst_caps_unref (expect); +} + +GST_END_TEST; + +static gboolean +_caps_is_fixed_foreach (GQuark field_id, const GValue * value, gpointer unused) +{ + return gst_value_is_fixed (value); +} + + +GST_START_TEST (test_normalize) +{ + GstCaps *in, *norm, *out; + guint i; + + in = gst_caps_from_string ("some/type, foo=(int){ 1 , 2 }"); + out = gst_caps_from_string ("some/type, foo=(int) 1; some/type, foo=(int) 2"); + norm = gst_caps_normalize (in); + fail_if (gst_caps_is_empty (norm)); + fail_unless (gst_caps_is_equal (norm, out)); + for (i = 0; i < gst_caps_get_size (norm); i++) { + GstStructure *st = gst_caps_get_structure (norm, i); + /* Make sure all fields of all structures are fixed */ + fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL)); + } + + gst_caps_unref (out); + gst_caps_unref (norm); + + in = gst_caps_from_string + ("some/type, foo=(int){ 1 , 2 }, bar=(int){ 3, 4 }"); + out = + gst_caps_from_string + ("some/type, foo=(int) 1, bar=(int) 3; some/type, foo=(int) 2, bar=(int) 3;" + "some/type, foo=(int) 1, bar=(int) 4; some/type, foo=(int) 2, bar=(int) 4;"); + norm = gst_caps_normalize (in); + fail_if (gst_caps_is_empty (norm)); + fail_unless (gst_caps_is_equal (norm, out)); + for (i = 0; i < gst_caps_get_size (norm); i++) { + GstStructure *st = gst_caps_get_structure (norm, i); + /* Make sure all fields of all structures are fixed */ + fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL)); + } + + gst_caps_unref (out); + gst_caps_unref (norm); + + in = gst_caps_from_string + ("some/type, foo=(string){ 1 , 2 }, bar=(string) { 3 }"); + out = + gst_caps_from_string + ("some/type, foo=(string) 1, bar=(string) 3; some/type, foo=(string) 2, bar=(string) 3"); + norm = gst_caps_normalize (in); + fail_if (gst_caps_is_empty (norm)); + fail_unless (gst_caps_is_equal (norm, out)); + for (i = 0; i < gst_caps_get_size (norm); i++) { + GstStructure *st = gst_caps_get_structure (norm, i); + /* Make sure all fields of all structures are fixed */ + fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL)); + } + + gst_caps_unref (out); + gst_caps_unref (norm); +} + +GST_END_TEST; + +GST_START_TEST (test_broken) +{ + GstCaps *c1; + + /* NULL is not valid for media_type */ + ASSERT_CRITICAL (c1 = + gst_caps_new_simple (NULL, "field", G_TYPE_INT, 1, NULL)); + fail_if (c1); + +#ifndef G_DISABLE_CHECKS + /* such a name is not valid, see gst_structure_validate_name() */ + ASSERT_CRITICAL (c1 = + gst_caps_new_simple ("1#@abc", "field", G_TYPE_INT, 1, NULL)); + fail_if (c1); +#endif +} + +GST_END_TEST; + +GST_START_TEST (test_features) +{ + GstCaps *c1, *c2, *c3; + GstStructure *s1, *s2; + GstCapsFeatures *f1, *f2; + gchar *str1; + static GstStaticCaps scaps = + GST_STATIC_CAPS + ("video/x-raw(memory:EGLImage), width=320, height=[ 240, 260 ]"); + + c1 = gst_caps_new_empty (); + fail_unless (c1 != NULL); + s1 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height", + GST_TYPE_INT_RANGE, 240, 260, NULL); + fail_unless (s1 != NULL); + f1 = gst_caps_features_new ("memory:EGLImage", NULL); + fail_unless (f1 != NULL); + + gst_caps_append_structure_full (c1, s1, f1); + s2 = gst_caps_get_structure (c1, 0); + fail_unless (s1 == s2); + f2 = gst_caps_get_features (c1, 0); + fail_unless (f1 == f2); + + str1 = gst_caps_to_string (c1); + fail_unless (str1 != NULL); + c2 = gst_caps_from_string (str1); + fail_unless (c2 != NULL); + g_free (str1); + + fail_unless (gst_caps_is_equal (c1, c2)); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_unless (gst_caps_can_intersect (c1, c2)); + + gst_caps_unref (c2); + + c2 = gst_caps_new_empty (); + fail_unless (c2 != NULL); + s2 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height", + GST_TYPE_INT_RANGE, 240, 260, NULL); + fail_unless (s2 != NULL); + f2 = gst_caps_features_new ("memory:VASurface", "meta:VAMeta", NULL); + fail_unless (f2 != NULL); + gst_caps_append_structure_full (c2, s2, f2); + + fail_if (gst_caps_is_equal (c1, c2)); + fail_if (gst_caps_is_subset (c1, c2)); + fail_if (gst_caps_is_subset (c2, c1)); + fail_if (gst_caps_can_intersect (c1, c2)); + + str1 = gst_caps_to_string (c2); + fail_unless (str1 != NULL); + c3 = gst_caps_from_string (str1); + fail_unless (c3 != NULL); + g_free (str1); + + fail_unless (gst_caps_is_equal (c2, c3)); + fail_unless (gst_caps_is_subset (c2, c3)); + fail_unless (gst_caps_is_subset (c3, c2)); + fail_unless (gst_caps_can_intersect (c2, c3)); + + f1 = gst_caps_get_features (c3, 0); + fail_unless (f1 != NULL); + fail_if (f1 == f2); + gst_caps_features_contains (f1, "memory:VASurface"); + gst_caps_features_remove (f1, "memory:VASurface"); + fail_if (gst_caps_is_equal (c2, c3)); + fail_if (gst_caps_is_subset (c2, c3)); + fail_if (gst_caps_is_subset (c3, c2)); + fail_if (gst_caps_can_intersect (c2, c3)); + + gst_caps_unref (c3); + gst_caps_unref (c2); + + c2 = gst_static_caps_get (&scaps); + fail_unless (c2 != NULL); + fail_unless (gst_caps_is_equal (c1, c2)); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_unless (gst_caps_is_subset (c2, c1)); + fail_unless (gst_caps_can_intersect (c1, c2)); + gst_caps_unref (c2); + + c2 = gst_caps_from_string + ("video/x-raw(ANY), width=320, height=[ 240, 260 ]"); + fail_unless (c2 != NULL); + fail_if (gst_caps_is_equal (c1, c2)); + fail_unless (gst_caps_is_subset (c1, c2)); + fail_if (gst_caps_is_subset (c2, c1)); + fail_unless (gst_caps_can_intersect (c1, c2)); + + c3 = gst_caps_intersect (c1, c2); + fail_unless (gst_caps_is_equal (c3, c1)); + + gst_caps_unref (c3); + gst_caps_unref (c2); + gst_caps_unref (c1); + + c1 = gst_caps_from_string ("video/x-raw"); + c2 = gst_caps_from_string ("video/x-raw"); + + f1 = gst_caps_get_features (c1, 0); + gst_caps_features_add (f1, "memory:VASurface"); + + fail_unless (gst_caps_features_is_equal (f1, gst_caps_get_features (c1, 0))); + fail_if (gst_caps_can_intersect (c1, c2)); + + f2 = gst_caps_get_features (c2, 0); + fail_unless (gst_caps_features_is_equal + (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, f2)); + + gst_caps_unref (c2); + gst_caps_unref (c1); + + c1 = gst_caps_from_string ("video/x-raw"); + f1 = gst_caps_get_features (c1, 0); + f2 = gst_caps_features_new ("memory:dmabuf", NULL); + gst_caps_set_features (c1, 0, f2); + + gst_caps_unref (c1); +} + +GST_END_TEST; + +GST_START_TEST (test_special_caps) +{ + GstCaps *caps; + + caps = gst_caps_new_any (); + fail_unless (gst_caps_is_any (caps)); + fail_unless (gst_caps_is_any (caps) == TRUE); + fail_if (gst_caps_is_empty (caps)); + fail_unless (gst_caps_is_empty (caps) == FALSE); + gst_caps_unref (caps); + + caps = gst_caps_new_empty (); + fail_if (gst_caps_is_any (caps)); + fail_unless (gst_caps_is_any (caps) == FALSE); + fail_unless (gst_caps_is_empty (caps)); + fail_unless (gst_caps_is_empty (caps) == TRUE); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static gboolean +foreach_append_function (GstCapsFeatures * features, GstStructure * structure, + gpointer user_data) +{ + GstCaps *caps = user_data; + + gst_caps_append_structure_full (caps, gst_structure_copy (structure), + features ? gst_caps_features_copy (features) : NULL); + + return TRUE; +} + +GST_START_TEST (test_foreach) +{ + GstCaps *caps, *caps2; + + caps = + gst_caps_from_string + ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264"); + caps2 = gst_caps_new_empty (); + fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2)); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + caps = gst_caps_new_empty (); + caps2 = gst_caps_new_empty (); + fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2)); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); +} + +GST_END_TEST; + +static gboolean +map_function (GstCapsFeatures * features, GstStructure * structure, + gpointer user_data) +{ + /* Remove caps features if there are any, otherwise add some dummy */ + if (gst_caps_features_contains (features, "foo:bar")) { + gst_caps_features_remove (features, "foo:bar"); + } else { + gst_caps_features_add (features, "foo:bar"); + gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); + } + + /* Set some dummy integer in the structure */ + gst_structure_set (structure, "foo", G_TYPE_INT, 123, NULL); + + return TRUE; +} + +GST_START_TEST (test_map_in_place) +{ + GstCaps *caps, *caps2; + + caps = + gst_caps_from_string + ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264"); + caps2 = + gst_caps_from_string + ("video/x-raw(foo:bar), foo=(int)123, format=I420; video/x-raw, foo=(int)123; video/x-h264(foo:bar), foo=(int)123"); + fail_unless (gst_caps_map_in_place (caps, map_function, NULL)); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + caps = gst_caps_new_empty (); + caps2 = gst_caps_new_empty (); + fail_unless (gst_caps_map_in_place (caps, map_function, NULL)); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); +} + +GST_END_TEST; + +static gboolean +filter_map_function (GstCapsFeatures * features, GstStructure * structure, + gpointer user_data) +{ + if (!gst_structure_has_name (structure, "video/x-raw")) + return FALSE; + + if (!gst_caps_features_contains (features, "foo:bar")) + return FALSE; + + /* Set some dummy integer in the structure */ + gst_structure_set (structure, "foo", G_TYPE_INT, 123, NULL); + + return TRUE; +} + +GST_START_TEST (test_filter_and_map_in_place) +{ + GstCaps *caps, *caps2; + + caps = + gst_caps_from_string + ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264"); + caps2 = gst_caps_from_string ("video/x-raw(foo:bar), foo=(int)123"); + gst_caps_filter_and_map_in_place (caps, filter_map_function, NULL); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + caps = gst_caps_from_string ("video/x-raw, format=I420; video/x-h264"); + caps2 = gst_caps_new_empty (); + gst_caps_filter_and_map_in_place (caps, filter_map_function, NULL); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + caps = gst_caps_new_empty (); + caps2 = gst_caps_new_empty (); + gst_caps_filter_and_map_in_place (caps, filter_map_function, NULL); + fail_unless (gst_caps_is_strictly_equal (caps, caps2)); + gst_caps_unref (caps); + gst_caps_unref (caps2); +} + +GST_END_TEST; + +static Suite * +gst_caps_suite (void) +{ + Suite *s = suite_create ("GstCaps"); + TCase *tc_chain = tcase_create ("operations"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_from_string); + tcase_add_test (tc_chain, test_double_append); + tcase_add_test (tc_chain, test_mutability); + tcase_add_test (tc_chain, test_static_caps); + tcase_add_test (tc_chain, test_simplify); + tcase_add_test (tc_chain, test_truncate); + tcase_add_test (tc_chain, test_subset); + tcase_add_test (tc_chain, test_subset_duplication); + tcase_add_test (tc_chain, test_merge_fundamental); + tcase_add_test (tc_chain, test_merge_same); + tcase_add_test (tc_chain, test_merge_subset); + tcase_add_test (tc_chain, test_intersect); + tcase_add_test (tc_chain, test_intersect2); + tcase_add_test (tc_chain, test_intersect_list_duplicate); + tcase_add_test (tc_chain, test_intersect_zigzag); + tcase_add_test (tc_chain, test_intersect_first); + tcase_add_test (tc_chain, test_intersect_first2); + tcase_add_test (tc_chain, test_intersect_duplication); + tcase_add_test (tc_chain, test_intersect_flagset); + tcase_add_test (tc_chain, test_union); + tcase_add_test (tc_chain, test_normalize); + tcase_add_test (tc_chain, test_broken); + tcase_add_test (tc_chain, test_features); + tcase_add_test (tc_chain, test_special_caps); + tcase_add_test (tc_chain, test_foreach); + tcase_add_test (tc_chain, test_map_in_place); + tcase_add_test (tc_chain, test_filter_and_map_in_place); + + return s; +} + +GST_CHECK_MAIN (gst_caps); diff --git a/tests/check/gst/gstcapsfeatures.c b/tests/check/gst/gstcapsfeatures.c new file mode 100644 index 0000000..9af126f --- /dev/null +++ b/tests/check/gst/gstcapsfeatures.c @@ -0,0 +1,114 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: Sebastian Dröge + * + * gstcapsfeatures.c: Unit test for GstCapsFeatures + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_basic_operations) +{ + GstCapsFeatures *a, *b; + + a = gst_caps_features_new ("m:abc", "m:def", "m:ghi", NULL); + fail_unless (a != NULL); + b = gst_caps_features_copy (a); + fail_unless (b != NULL); + fail_unless (gst_caps_features_is_equal (a, b)); + fail_if (gst_caps_features_is_equal (a, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)); + fail_unless_equals_int (gst_caps_features_get_size (a), 3); + fail_unless_equals_string (gst_caps_features_get_nth (a, 1), "m:def"); + gst_caps_features_add (b, "m:jkl"); + fail_if (gst_caps_features_is_equal (a, b)); + fail_unless_equals_int (gst_caps_features_get_size (b), 4); + fail_unless_equals_string (gst_caps_features_get_nth (b, 3), "m:jkl"); + gst_caps_features_add (b, "m:jkl"); + fail_unless_equals_int (gst_caps_features_get_size (b), 4); + + gst_caps_features_remove (b, "m:jkl"); + fail_unless (gst_caps_features_is_equal (a, b)); + gst_caps_features_remove (b, "m:abc"); + gst_caps_features_add (b, "m:abc"); + fail_unless (gst_caps_features_is_equal (a, b)); + gst_caps_features_remove (b, "m:abc"); + gst_caps_features_remove (b, "m:def"); + gst_caps_features_remove (b, "m:ghi"); + fail_unless (gst_caps_features_is_equal (b, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)); + gst_caps_features_add (b, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); + + gst_caps_features_free (a); + gst_caps_features_free (b); +} + +GST_END_TEST; + +GST_START_TEST (test_from_to_string) +{ + GstCapsFeatures *a, *b; + gchar *str; + + a = gst_caps_features_new ("m:abc", "m:def", "m:ghi", NULL); + fail_unless (a != NULL); + str = gst_caps_features_to_string (a); + fail_unless (str != NULL); + fail_unless_equals_string (str, "m:abc, m:def, m:ghi"); + b = gst_caps_features_from_string (str); + fail_unless (b != NULL); + fail_unless (gst_caps_features_is_equal (a, b)); + gst_caps_features_free (a); + gst_caps_features_free (b); + g_free (str); + + a = gst_caps_features_new_any (); + fail_unless (a != NULL); + fail_unless (gst_caps_features_is_any (a)); + str = gst_caps_features_to_string (a); + fail_unless (str != NULL); + fail_unless_equals_string (str, "ANY"); + b = gst_caps_features_from_string (str); + fail_unless (b != NULL); + fail_unless (gst_caps_features_is_equal (a, b)); + fail_unless (gst_caps_features_is_any (b)); + gst_caps_features_free (a); + gst_caps_features_free (b); + g_free (str); +} + +GST_END_TEST; + +static Suite * +gst_capsfeatures_suite (void) +{ + Suite *s = suite_create ("GstCapsFeatures"); + TCase *tc_chain = tcase_create ("operations"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_basic_operations); + tcase_add_test (tc_chain, test_from_to_string); + + return s; +} + +GST_CHECK_MAIN (gst_capsfeatures); diff --git a/tests/check/gst/gstchildproxy.c b/tests/check/gst/gstchildproxy.c new file mode 100644 index 0000000..47ce459 --- /dev/null +++ b/tests/check/gst/gstchildproxy.c @@ -0,0 +1,82 @@ +/* GStreamer + * Copyright (C) 2009 Stefan Kost + * + * gstchildproxy.c: Unit test for GstChildProxy 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_START_TEST (test_get) +{ + GstElement *pipeline; + gchar *name; + + pipeline = gst_pipeline_new ("foo"); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + gst_child_proxy_get (GST_CHILD_PROXY (pipeline), "name", &name, NULL); + fail_if (g_strcmp0 ("foo", name)); + g_free (name); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_child_get) +{ + GstElement *pipeline, *elem; + gchar *name; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + elem = gst_element_factory_make ("fakesrc", "src"); + fail_if (elem == NULL, "Could not create fakesrc"); + + gst_bin_add (GST_BIN (pipeline), elem); + + gst_child_proxy_get (GST_CHILD_PROXY (pipeline), "src::name", &name, NULL); + fail_if (g_strcmp0 ("src", name)); + g_free (name); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + + +static Suite * +gst_child_proxy_suite (void) +{ + Suite *s = suite_create ("GstChildProxy"); + TCase *tc_chain = tcase_create ("child proxy tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_get); + tcase_add_test (tc_chain, test_child_get); + + return s; +} + +GST_CHECK_MAIN (gst_child_proxy); diff --git a/tests/check/gst/gstclock.c b/tests/check/gst/gstclock.c new file mode 100644 index 0000000..92446a5 --- /dev/null +++ b/tests/check/gst/gstclock.c @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) 2010 Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +typedef struct +{ + GstClock parent; +} TestClock; + +typedef struct +{ + GstClockClass parent_class; +} TestClockClass; + +#define TYPE_TEST_CLOCK (test_clock_get_type ()) +#define TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TEST_CLOCK, TestClock)) +#define TEST_CLOCK_CAST(obj) ((TestClock *)(obj)) +#define IS_TEST_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TEST_CLOCK)) +#define TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TEST_CLOCK, TestClockClass)) +#define IS_TEST_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TEST_CLOCK)) +#define TEST_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TEST_CLOCK, TestClockClass)) + + +GType test_clock_get_type (void); +G_DEFINE_TYPE (TestClock, test_clock, GST_TYPE_CLOCK); + +static GstClockReturn +fake_wait_async (GstClock * clock, GstClockEntry * entry) +{ + return GST_CLOCK_OK; +} + +static void +test_clock_class_init (TestClockClass * klass) +{ + GstClockClass *clock_class; + + clock_class = GST_CLOCK_CLASS (klass); + + clock_class->wait_async = fake_wait_async; +} + +static void +test_clock_init (TestClock * clock) +{ +} + + +static void +weak_notify (gpointer data, GObject * object) +{ + *(gboolean *) data = FALSE; +} + +GST_START_TEST (test_set_master_refcount) +{ + GstClock *master, *slave; + gboolean master_alive = TRUE; + + /* create master and slave */ + master = g_object_new (TYPE_TEST_CLOCK, "name", "TestClockMaster", NULL); + gst_object_ref_sink (master); + slave = g_object_new (TYPE_TEST_CLOCK, "name", "TestClockSlave", NULL); + gst_object_ref_sink (slave); + GST_OBJECT_FLAG_SET (slave, GST_CLOCK_FLAG_CAN_SET_MASTER); + + fail_unless_equals_int (GST_OBJECT_REFCOUNT (master), 1); + fail_unless_equals_int (GST_OBJECT_REFCOUNT (slave), 1); + + g_object_weak_ref (G_OBJECT (master), weak_notify, &master_alive); + fail_unless_equals_int (GST_OBJECT_REFCOUNT (master), 1); + + gst_clock_set_master (slave, master); + /* slave stores master in slave->master */ + fail_unless_equals_int (GST_OBJECT_REFCOUNT (master), 2); + /* master stores a ref to slave in master->clockid */ + fail_unless_equals_int (GST_OBJECT_REFCOUNT (slave), 2); + + /* discard our ref */ + gst_object_unref (master); + + /* master should still be reffed inside slave */ + fail_unless_equals_int (GST_OBJECT_REFCOUNT (master), 1); + fail_unless (master_alive); + + /* drop the last ref to mater */ + gst_clock_set_master (slave, NULL); + + fail_if (master_alive); + fail_unless_equals_int (GST_OBJECT_REFCOUNT (slave), 1); + + gst_object_unref (slave); +} + +GST_END_TEST; + +static Suite * +gst_clock_suite (void) +{ + Suite *s = suite_create ("GstClock"); + TCase *tc_chain = tcase_create ("clock"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_set_master_refcount); + + return s; +} + +GST_CHECK_MAIN (gst_clock); diff --git a/tests/check/gst/gstcontext.c b/tests/check/gst/gstcontext.c new file mode 100644 index 0000000..88441ae --- /dev/null +++ b/tests/check/gst/gstcontext.c @@ -0,0 +1,455 @@ +/* GStreamer + * Copyright (C) 2013 Collabora Ltd. + * Author: Sebastian Dröge + * Copyright (C) 2013 Sebastian Dröge + * + * gstcontext.c: Unit test for GstContext + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_START_TEST (test_basic) +{ + GstContext *c1, *c2; + GstStructure *s1; + const GstStructure *s2; + + c1 = gst_context_new ("test", FALSE); + fail_unless (c1 != NULL); + fail_unless (GST_IS_CONTEXT (c1)); + s1 = gst_context_writable_structure (c1); + fail_unless (s1 != NULL); + gst_structure_set (s1, "foobar", G_TYPE_INT, 1, NULL); + + c2 = gst_context_copy (c1); + fail_unless (c2 != NULL); + fail_unless (GST_IS_CONTEXT (c2)); + fail_unless (strcmp (gst_context_get_context_type (c1), + gst_context_get_context_type (c2)) == 0); + s2 = gst_context_get_structure (c2); + fail_unless (s2 != NULL); + fail_unless (gst_structure_is_equal (s1, s2)); + + gst_context_unref (c1); + gst_context_unref (c2); +} + +GST_END_TEST; + +typedef struct +{ + GstElement parent; + gboolean set_before_ready; + gboolean set_from_need_context; + gboolean create_self; + + gboolean have_foobar; +} GstContextElement; + +typedef struct +{ + GstElementClass parent_class; +} GstContextElementClass; + +GType gst_context_element_get_type (void); + +G_DEFINE_TYPE (GstContextElement, gst_context_element, GST_TYPE_ELEMENT); + +static void +gst_context_element_set_context (GstElement * element, GstContext * context) +{ + if (strcmp (gst_context_get_context_type (context), "foobar") == 0) + ((GstContextElement *) element)->have_foobar = TRUE; + + GST_ELEMENT_CLASS (gst_context_element_parent_class)->set_context (element, + context); +} + +static GstStateChangeReturn +gst_context_element_change_state (GstElement * element, + GstStateChange transition) +{ + GstContextElement *celement = (GstContextElement *) element; + + if (transition == GST_STATE_CHANGE_NULL_TO_READY) { + GstContext *context; + GstMessage *msg; + gboolean have_foobar = celement->have_foobar; + + if (celement->set_before_ready && !have_foobar) + return GST_STATE_CHANGE_FAILURE; + else if (celement->set_before_ready) + goto chain_up; + + if (celement->set_from_need_context && have_foobar) + return GST_STATE_CHANGE_FAILURE; + + if (!have_foobar) { + /* Here we would first query downstream for a context but we have no pads */ + msg = gst_message_new_need_context (GST_OBJECT (element), "foobar"); + gst_element_post_message (element, msg); + + have_foobar = celement->have_foobar; + } + + if (celement->set_from_need_context && !have_foobar) + return GST_STATE_CHANGE_FAILURE; + else if (celement->set_from_need_context) + goto chain_up; + + if (celement->create_self && have_foobar) + return GST_STATE_CHANGE_FAILURE; + + if (!have_foobar) { + context = gst_context_new ("foobar", FALSE); + gst_element_set_context (element, context); + msg = + gst_message_new_have_context (GST_OBJECT (element), + gst_context_ref (context)); + gst_element_post_message (element, msg); + gst_context_unref (context); + } + } + +chain_up: + return + GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state + (element, transition); +} + +static void +gst_context_element_class_init (GstContextElementClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gstelement_class->set_context = gst_context_element_set_context; + gstelement_class->change_state = gst_context_element_change_state; +} + +static void +gst_context_element_init (GstContextElement * self) +{ + +} + +GST_START_TEST (test_element_set_before_ready) +{ + GstBus *bus; + GstElement *element; + GstContext *context; + GstMessage *msg; + + element = g_object_new (gst_context_element_get_type (), NULL); + bus = gst_bus_new (); + gst_element_set_bus (element, bus); + + ((GstContextElement *) element)->set_before_ready = TRUE; + + fail_if (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + fail_if (gst_bus_pop (bus) != NULL); + + context = gst_context_new ("foobar", FALSE); + gst_element_set_context (element, context); + fail_unless (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_STATE_CHANGED)) != NULL); + gst_message_unref (msg); + fail_if (gst_bus_pop (bus) != NULL); + + fail_unless (((GstContextElement *) element)->have_foobar); + + gst_context_unref (context); + + gst_element_set_bus (element, NULL); + fail_unless (gst_element_set_state (element, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (element); +} + +GST_END_TEST; + +static GstBusSyncReply +sync_handler (GstBus * bus, GstMessage * message, gpointer user_data) +{ + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT) { + const gchar *type; + GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message)); + GstContext *context; + + fail_unless (gst_message_parse_context_type (message, &type)); + fail_unless_equals_string (type, "foobar"); + context = gst_context_new ("foobar", FALSE); + gst_element_set_context (element, context); + gst_context_unref (context); + } + + return GST_BUS_PASS; +} + +GST_START_TEST (test_element_set_from_need_context) +{ + GstBus *bus; + GstElement *element; + GstMessage *msg; + + element = g_object_new (gst_context_element_get_type (), NULL); + bus = gst_bus_new (); + gst_bus_set_sync_handler (bus, sync_handler, NULL, NULL); + gst_element_set_bus (element, bus); + + ((GstContextElement *) element)->set_from_need_context = TRUE; + + fail_unless (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_NEED_CONTEXT)) != NULL); + gst_message_unref (msg); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_STATE_CHANGED)) != NULL); + gst_message_unref (msg); + fail_if (gst_bus_pop (bus) != NULL); + + fail_unless (((GstContextElement *) element)->have_foobar); + + gst_element_set_bus (element, NULL); + fail_unless (gst_element_set_state (element, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_element_create_self) +{ + GstBus *bus; + GstElement *element; + GstContext *context; + GstMessage *msg; + + element = g_object_new (gst_context_element_get_type (), NULL); + bus = gst_bus_new (); + gst_element_set_bus (element, bus); + + ((GstContextElement *) element)->create_self = TRUE; + + fail_unless (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_NEED_CONTEXT)) != NULL); + gst_message_unref (msg); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_HAVE_CONTEXT)) != NULL); + gst_message_parse_have_context (msg, &context); + fail_unless (GST_IS_CONTEXT (context)); + fail_unless_equals_string (gst_context_get_context_type (context), "foobar"); + gst_context_unref (context); + gst_message_unref (msg); + fail_unless ((msg = + gst_bus_pop_filtered (bus, GST_MESSAGE_STATE_CHANGED)) != NULL); + gst_message_unref (msg); + fail_if (gst_bus_pop (bus) != NULL); + + fail_unless (((GstContextElement *) element)->have_foobar); + + gst_element_set_bus (element, NULL); + fail_unless (gst_element_set_state (element, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_element_bin_caching) +{ + GstBus *bus; + GstElement *bin; + GstElement *element, *element2; + + bin = gst_bin_new (NULL); + element = g_object_new (gst_context_element_get_type (), NULL); + element2 = g_object_new (gst_context_element_get_type (), NULL); + gst_bin_add_many (GST_BIN (bin), element, element2, NULL); + + /* FIXME: This assumes (as currently is true) the GstBin activates + * the last added element first if none of them is a sink or has pads + */ + ((GstContextElement *) element2)->create_self = TRUE; + ((GstContextElement *) element)->set_from_need_context = TRUE; + + bus = gst_bus_new (); + gst_element_set_bus (bin, bus); + + fail_unless (gst_element_set_state (bin, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (((GstContextElement *) element)->have_foobar); + fail_unless (((GstContextElement *) element2)->have_foobar); + + gst_element_set_bus (bin, NULL); + fail_unless (gst_element_set_state (bin, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_add_element_to_bin) +{ + GstBus *bus; + GstElement *bin; + GstElement *element; + GList *contexts, *contexts2, *l; + + /* Start with an element not inside a bin requesting a context. Add the + * element to a bin and check the context propagation. */ + element = g_object_new (gst_context_element_get_type (), NULL); + + ((GstContextElement *) element)->create_self = TRUE; + + fail_unless (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (((GstContextElement *) element)->have_foobar); + + bin = gst_bin_new (NULL); + + bus = gst_bus_new (); + gst_element_set_bus (bin, bus); + + fail_unless (gst_element_set_state (bin, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + + gst_bin_add (GST_BIN (bin), element); + + /* check the contexts are the same */ + contexts = gst_element_get_contexts (element); + contexts2 = gst_element_get_contexts (bin); + for (l = contexts; l; l = l->next) + fail_unless (g_list_find (contexts2, l->data)); + g_list_free_full (contexts, (GDestroyNotify) gst_context_unref); + g_list_free_full (contexts2, (GDestroyNotify) gst_context_unref); + + gst_element_set_bus (bin, NULL); + fail_unless (gst_element_set_state (bin, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_add_element_to_bin_collision) +{ + GstBus *bus; + GstElement *bin; + GstElement *element, *element2; + GList *contexts, *contexts2, *l; + + /* Start with a bin containing an element that requests a context and then add + * another element to the bin that has already requested the same context. */ + + bin = gst_bin_new (NULL); + element = g_object_new (gst_context_element_get_type (), NULL); + gst_bin_add (GST_BIN (bin), element); + + ((GstContextElement *) element)->create_self = TRUE; + + bus = gst_bus_new (); + gst_element_set_bus (bin, bus); + + fail_unless (gst_element_set_state (bin, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (((GstContextElement *) element)->have_foobar); + + /* propagate a context without a parent bin */ + element2 = g_object_new (gst_context_element_get_type (), NULL); + ((GstContextElement *) element2)->create_self = TRUE; + + fail_unless (gst_element_set_state (element2, + GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (((GstContextElement *) element2)->have_foobar); + + ((GstContextElement *) element)->have_foobar = FALSE; + ((GstContextElement *) element2)->have_foobar = FALSE; + + /* add element to bin should result in the propagation of contexts to the + * added element */ + gst_bin_add (GST_BIN (bin), element2); + + fail_unless (((GstContextElement *) element)->have_foobar == FALSE); + fail_unless (((GstContextElement *) element2)->have_foobar); + + /* check the contexts are the same */ + contexts = gst_element_get_contexts (element); + contexts2 = gst_element_get_contexts (element2); + for (l = contexts; l; l = l->next) + fail_unless (g_list_find (contexts2, l->data)); + g_list_free_full (contexts, (GDestroyNotify) gst_context_unref); + contexts = gst_element_get_contexts (bin); + for (l = contexts; l; l = l->next) + fail_unless (g_list_find (contexts2, l->data)); + g_list_free_full (contexts, (GDestroyNotify) gst_context_unref); + g_list_free_full (contexts2, (GDestroyNotify) gst_context_unref); + + gst_element_set_bus (bin, NULL); + fail_unless (gst_element_set_state (bin, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +static Suite * +gst_context_suite (void) +{ + Suite *s = suite_create ("GstContext"); + TCase *tc_chain = tcase_create ("context tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_basic); + tcase_add_test (tc_chain, test_element_set_before_ready); + tcase_add_test (tc_chain, test_element_set_from_need_context); + tcase_add_test (tc_chain, test_element_create_self); + tcase_add_test (tc_chain, test_element_bin_caching); + tcase_add_test (tc_chain, test_add_element_to_bin); + tcase_add_test (tc_chain, test_add_element_to_bin_collision); + + return s; +} + +GST_CHECK_MAIN (gst_context); diff --git a/tests/check/gst/gstcontroller.c b/tests/check/gst/gstcontroller.c new file mode 100644 index 0000000..9d81c5d --- /dev/null +++ b/tests/check/gst/gstcontroller.c @@ -0,0 +1,730 @@ +/* GStreamer + * + * unit test for the controller library + * + * Copyright (C) <2005> Stefan Kost + * Copyright (C) <2006-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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* local test element */ + +enum +{ + PROP_INT = 1, + PROP_FLOAT, + PROP_DOUBLE, + PROP_BOOLEAN, + PROP_READONLY, + PROP_STATIC, + PROP_CONSTRUCTONLY, + PROP_COUNT +}; + +#define GST_TYPE_TEST_OBJ (gst_test_obj_get_type ()) +#define GST_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj)) +#define GST_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass)) +#define GST_IS_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ)) +#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ)) +#define GST_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass)) + +typedef struct _GstTestObj GstTestObj; +typedef struct _GstTestObjClass GstTestObjClass; + +struct _GstTestObj +{ + GstElement parent; + gint val_int; + gfloat val_float; + gdouble val_double; + gboolean val_boolean; +}; +struct _GstTestObjClass +{ + GstElementClass parent_class; +}; + +static GType gst_test_obj_get_type (void); + +static void +gst_test_obj_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + g_value_set_int (value, self->val_int); + break; + case PROP_FLOAT: + g_value_set_float (value, self->val_float); + break; + case PROP_DOUBLE: + g_value_set_double (value, self->val_double); + break; + case PROP_BOOLEAN: + g_value_set_boolean (value, self->val_boolean); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + self->val_int = g_value_get_int (value); + GST_DEBUG ("test value int=%d", self->val_int); + break; + case PROP_FLOAT: + self->val_float = g_value_get_float (value); + GST_DEBUG ("test value float=%f", self->val_float); + break; + case PROP_DOUBLE: + self->val_double = g_value_get_double (value); + GST_DEBUG ("test value double=%lf", self->val_double); + break; + case PROP_BOOLEAN: + self->val_boolean = g_value_get_boolean (value); + GST_DEBUG ("test value boolean=%d", self->val_boolean); + break; + case PROP_CONSTRUCTONLY: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_class_init (GstTestObjClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_test_obj_set_property; + gobject_class->get_property = gst_test_obj_get_property; + + g_object_class_install_property (gobject_class, PROP_INT, + g_param_spec_int ("int", + "int prop", + "int number parameter", + 0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_FLOAT, + g_param_spec_float ("float", + "float prop", + "float number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_DOUBLE, + g_param_spec_double ("double", + "double prop", + "double number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_BOOLEAN, + g_param_spec_boolean ("boolean", + "boolean prop", + "boolean parameter", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_READONLY, + g_param_spec_int ("readonly", + "readonly prop", + "readonly parameter", + 0, G_MAXINT, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_STATIC, + g_param_spec_int ("static", + "static prop", + "static parameter", 0, G_MAXINT, 0, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_CONSTRUCTONLY, + g_param_spec_int ("construct-only", + "construct-only prop", + "construct-only parameter", + 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + gst_element_class_set_metadata (element_class, + "test object for unit tests", + "Test", "Use in unit tests", "Stefan Sauer "); +} + +static GType +gst_test_obj_get_type (void) +{ + static volatile gsize test_obj_type = 0; + + if (g_once_init_enter (&test_obj_type)) { + GType type; + static const GTypeInfo info = { + (guint16) sizeof (GstTestObjClass), + NULL, // base_init + NULL, // base_finalize + (GClassInitFunc) gst_test_obj_class_init, // class_init + NULL, // class_finalize + NULL, // class_data + (guint16) sizeof (GstTestObj), + 0, // n_preallocs + NULL, // instance_init + NULL // value_table + }; + type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0); + g_once_init_leave (&test_obj_type, type); + } + return test_obj_type; +} + +/* test control source */ + +#define GST_TYPE_TEST_CONTROL_SOURCE (gst_test_control_source_get_type ()) +#define GST_TEST_CONTROL_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSource)) +#define GST_TEST_CONTROL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass)) +#define GST_IS_TEST_CONTROL_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_SOURCE)) +#define GST_IS_TEST_CONTROL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_SOURCE)) +#define GST_TEST_CONTROL_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass)) + +typedef struct _GstTestControlSource GstTestControlSource; +typedef struct _GstTestControlSourceClass GstTestControlSourceClass; + +struct _GstTestControlSource +{ + GstControlSource parent; + + gdouble value; +}; +struct _GstTestControlSourceClass +{ + GstControlSourceClass parent_class; +}; + +static GType gst_test_control_source_get_type (void); + +static GstTestControlSource * +gst_test_control_source_new (void) +{ + GstTestControlSource *csource = + g_object_new (GST_TYPE_TEST_CONTROL_SOURCE, NULL); + + /* Clear floating flag */ + gst_object_ref_sink (csource); + + return csource; +} + +static gboolean +gst_test_control_source_get (GstTestControlSource * self, + GstClockTime timestamp, gdouble * value) +{ + *value = self->value; + return TRUE; +} + +static gboolean +gst_test_control_source_get_value_array (GstTestControlSource * self, + GstClockTime timestamp, GstClockTime interval, guint n_values, + gdouble * values) +{ + guint i; + + for (i = 0; i < n_values; i++) { + *values = self->value; + values++; + } + return TRUE; +} + +static void +gst_test_control_source_init (GstTestControlSource * self) +{ + GstControlSource *cs = (GstControlSource *) self; + + cs->get_value = (GstControlSourceGetValue) gst_test_control_source_get; + cs->get_value_array = (GstControlSourceGetValueArray) + gst_test_control_source_get_value_array; + self->value = 0.0; +} + +static GType +gst_test_control_source_get_type (void) +{ + static volatile gsize test_countrol_source_type = 0; + + if (g_once_init_enter (&test_countrol_source_type)) { + GType type; + static const GTypeInfo info = { + (guint16) sizeof (GstTestControlSourceClass), + NULL, // base_init + NULL, // base_finalize + NULL, // class_init + NULL, // class_finalize + NULL, // class_data + (guint16) sizeof (GstTestControlSource), + 0, // n_preallocs + (GInstanceInitFunc) gst_test_control_source_init, // instance_init + NULL // value_table + }; + type = + g_type_register_static (GST_TYPE_CONTROL_SOURCE, "GstTestControlSource", + &info, 0); + g_once_init_leave (&test_countrol_source_type, type); + } + return test_countrol_source_type; +} + +/* test control binding */ + +enum +{ + PROP_CS = 1, +}; + +#define GST_TYPE_TEST_CONTROL_BINDING (gst_test_control_binding_get_type ()) +#define GST_TEST_CONTROL_BINDING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBinding)) +#define GST_TEST_CONTROL_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass)) +#define GST_IS_TEST_CONTROL_BINDING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_BINDING)) +#define GST_IS_TEST_CONTROL_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_BINDING)) +#define GST_TEST_CONTROL_BINDING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass)) + +typedef struct _GstTestControlBinding GstTestControlBinding; +typedef struct _GstTestControlBindingClass GstTestControlBindingClass; + +struct _GstTestControlBinding +{ + GstControlBinding parent; + + GstControlSource *cs; +}; +struct _GstTestControlBindingClass +{ + GstControlBindingClass parent_class; +}; + +static GType gst_test_control_binding_get_type (void); +static GstControlBindingClass *gst_test_control_binding_parent_class = NULL; + +static GstControlBinding * +gst_test_control_binding_new (GstObject * object, const gchar * property_name, + GstControlSource * cs) +{ + GstTestControlBinding *self; + self = (GstTestControlBinding *) g_object_new (GST_TYPE_TEST_CONTROL_BINDING, + "object", object, "name", property_name, NULL); + + self->cs = gst_object_ref (cs); + + return (GstControlBinding *) self; +} + +static void +gst_test_control_binding_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec) +{ + GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (object); + + switch (property_id) { + case PROP_CS: + g_value_set_object (value, self->cs); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_control_binding_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec) +{ + GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (object); + + switch (property_id) { + case PROP_CS: + self->cs = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_control_binding_finalize (GObject * obj) +{ + GstTestControlBinding *self = GST_TEST_CONTROL_BINDING (obj); + + gst_object_unref (self->cs); + + G_OBJECT_CLASS (gst_test_control_binding_parent_class)->finalize (obj); +} + +static void +gst_test_control_binding_class_init (gpointer klass, gpointer class_data) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gst_test_control_binding_parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_test_control_binding_set_property; + gobject_class->get_property = gst_test_control_binding_get_property; + gobject_class->finalize = gst_test_control_binding_finalize; + + g_object_class_install_property (gobject_class, PROP_CS, + g_param_spec_object ("control-source", "ControlSource", + "The control source", + GST_TYPE_CONTROL_SOURCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static GType +gst_test_control_binding_get_type (void) +{ + static volatile gsize test_countrol_binding_type = 0; + + if (g_once_init_enter (&test_countrol_binding_type)) { + GType type; + static const GTypeInfo info = { + (guint16) sizeof (GstTestControlBindingClass), + NULL, // base_init + NULL, // base_finalize + gst_test_control_binding_class_init, // class_init + NULL, // class_finalize + NULL, // class_data + (guint16) sizeof (GstTestControlBinding), + 0, // n_preallocs + NULL, // instance_init + NULL // value_table + }; + type = + g_type_register_static (GST_TYPE_CONTROL_BINDING, + "GstTestControlBinding", &info, 0); + g_once_init_leave (&test_countrol_binding_type, type); + } + return test_countrol_binding_type; +} + + +static void +setup (void) +{ + gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ); +} + +static void +teardown (void) +{ +} + + +/* TESTS */ + +/* tests for an element with no controlled params */ +GST_START_TEST (controller_new_fail1) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should not exist */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "_schrompf_", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests for readonly params */ +GST_START_TEST (controller_new_fail2) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should exist and but is readonly */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "readonly", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests for static params */ +GST_START_TEST (controller_new_fail3) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should exist and but is not controlable */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "static", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests for construct-only params */ +GST_START_TEST (controller_new_fail4) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should exist and but is construct-only */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "construct-only", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + + +/* tests for an element with controlled params */ +GST_START_TEST (controller_new_okay1) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should exist and should be controllable */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "int", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests for an element with several controlled params */ +GST_START_TEST (controller_new_okay2) +{ + GstElement *elem; + GstTestControlSource *cs1, *cs2; + GstControlBinding *cb1, *cb2; + + elem = gst_element_factory_make ("testobj", NULL); + cs1 = gst_test_control_source_new (); + cs2 = gst_test_control_source_new (); + + /* these properties should exist and should be controllable */ + cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int", + GST_CONTROL_SOURCE (cs1)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL); + + cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "boolean", + GST_CONTROL_SOURCE (cs2)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL); + + gst_object_unref (cb1); + gst_object_unref (cb2); + gst_object_unref (cs1); + gst_object_unref (cs2); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* controlling a param twice should be handled */ +GST_START_TEST (controller_param_twice) +{ + GstElement *elem; + GstTestControlSource *cs; + GstControlBinding *cb; + gboolean res; + + elem = gst_element_factory_make ("testobj", NULL); + cs = gst_test_control_source_new (); + + /* that property should exist and should be controllable */ + cb = gst_test_control_binding_new (GST_OBJECT (elem), "int", + GST_CONTROL_SOURCE (cs)); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL); + cb = gst_object_ref (cb); + + res = gst_object_add_control_binding (GST_OBJECT (elem), cb); + fail_unless (res, NULL); + + /* setting it again will just unset the old and set it again + * this might cause some trouble with binding the control source again + */ + res = gst_object_add_control_binding (GST_OBJECT (elem), cb); + fail_unless (res, NULL); + + /* it should have been added now, let remove it */ + res = gst_object_remove_control_binding (GST_OBJECT (elem), cb); + fail_unless (res, NULL); + + /* removing it again should not work */ + res = gst_object_remove_control_binding (GST_OBJECT (elem), cb); + fail_unless (!res, NULL); + + gst_object_unref (cb); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests if we can run controller methods against any GObject */ +GST_START_TEST (controller_any_gobject) +{ + GstElement *elem; + gboolean res; + + elem = gst_element_factory_make ("bin", "test_elem"); + + /* that element is not controllable */ + res = gst_object_sync_values (GST_OBJECT (elem), 0LL); + /* Syncing should still succeed as there's nothing to sync */ + fail_unless (res == TRUE, NULL); + + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests if we cleanup properly */ +GST_START_TEST (controller_controlsource_refcounts) +{ + GstElement *elem; + GstControlBinding *cb, *test_cb; + GstControlSource *cs, *test_cs; + + elem = gst_element_factory_make ("testobj", NULL); + + cs = (GstControlSource *) gst_test_control_source_new (); + fail_unless (cs != NULL, NULL); + + fail_unless_equals_int (G_OBJECT (cs)->ref_count, 1); + + cb = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL); + fail_unless_equals_int (G_OBJECT (cs)->ref_count, 2); + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), cb)); + + test_cb = gst_object_get_control_binding (GST_OBJECT (elem), "int"); + fail_unless (test_cb != NULL, NULL); + + g_object_get (test_cb, "control-source", &test_cs, NULL); + fail_unless (test_cs != NULL, NULL); + fail_unless (test_cs == cs); + fail_unless_equals_int (G_OBJECT (cs)->ref_count, 3); + gst_object_unref (test_cs); + gst_object_unref (test_cb); + gst_object_unref (cs); + + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests if we can bind a control source twice */ +GST_START_TEST (controller_bind_twice) +{ + GstElement *elem; + GstControlSource *cs; + GstControlBinding *cb1, *cb2; + + elem = gst_element_factory_make ("testobj", NULL); + + cs = (GstControlSource *) gst_test_control_source_new (); + fail_unless (cs != NULL, NULL); + + cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL); + cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "double", cs); + fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL); + + gst_object_unref (cb1); + gst_object_unref (cb2); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + + +static Suite * +gst_controller_suite (void) +{ + Suite *s = suite_create ("Controller"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_checked_fixture (tc, setup, teardown); + tcase_add_test (tc, controller_new_fail1); + tcase_add_test (tc, controller_new_fail2); + tcase_add_test (tc, controller_new_fail3); + tcase_add_test (tc, controller_new_fail4); + tcase_add_test (tc, controller_new_okay1); + tcase_add_test (tc, controller_new_okay2); + tcase_add_test (tc, controller_param_twice); + tcase_add_test (tc, controller_any_gobject); + tcase_add_test (tc, controller_controlsource_refcounts); + tcase_add_test (tc, controller_bind_twice); + + return s; +} + +GST_CHECK_MAIN (gst_controller); diff --git a/tests/check/gst/gstcpp.cc b/tests/check/gst/gstcpp.cc new file mode 100644 index 0000000..eb58be2 --- /dev/null +++ b/tests/check/gst/gstcpp.cc @@ -0,0 +1,49 @@ +/* GStreamer C++ compiler include compatibility test + * Copyright (C) 2016 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_init_macros) +{ + GstMapInfo map = GST_MAP_INFO_INIT; + GstPollFD poll_fd = GST_POLL_FD_INIT; + + fail_unless_equals_int (map.size, 0); + fail_unless_equals_int (poll_fd.fd, -1); +} + +GST_END_TEST; + +static Suite * +gst_cpp_suite (void) +{ + Suite *s = suite_create ("GstC++"); + TCase *tc_chain = tcase_create ("gst C++ tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_init_macros); + + return s; +} + +GST_CHECK_MAIN (gst_cpp); diff --git a/tests/check/gst/gstdatetime.c b/tests/check/gst/gstdatetime.c new file mode 100644 index 0000000..7bbc5bd --- /dev/null +++ b/tests/check/gst/gstdatetime.c @@ -0,0 +1,790 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * Copyright (C) 2010 Christian Hergert + * + * gstdatetime.c: Unit tests for GstDateTime + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define assert_almost_equals_int(a, b) \ +G_STMT_START { \ + int first = a; \ + int second = b; \ + fail_unless(ABS (first - second) <= 1, \ + "'" #a "' (%d) is not almost equal to '" #b"' (%d)", first, second); \ +} G_STMT_END; + +GST_START_TEST (test_GstDateTime_now) +{ + GstDateTime *dt; + time_t t; + struct tm tm; + + memset (&tm, 0, sizeof (tm)); + t = time (NULL); +#ifdef HAVE_LOCALTIME_R + localtime_r (&t, &tm); +#else + memcpy (&tm, localtime (&t), sizeof (struct tm)); +#endif + dt = gst_date_time_new_now_local_time (); + assert_equals_int (gst_date_time_get_year (dt), 1900 + tm.tm_year); + assert_equals_int (gst_date_time_get_month (dt), 1 + tm.tm_mon); + assert_equals_int (gst_date_time_get_day (dt), tm.tm_mday); + assert_equals_int (gst_date_time_get_hour (dt), tm.tm_hour); + assert_equals_int (gst_date_time_get_minute (dt), tm.tm_min); + assert_almost_equals_int (gst_date_time_get_second (dt), tm.tm_sec); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_new_from_unix_epoch_local_time) +{ + GstDateTime *dt; + struct tm tm; + time_t t; + + memset (&tm, 0, sizeof (tm)); + t = time (NULL); +#ifdef HAVE_LOCALTIME_R + localtime_r (&t, &tm); +#else + memcpy (&tm, localtime (&t), sizeof (struct tm)); +#endif + dt = gst_date_time_new_from_unix_epoch_local_time (t); + assert_equals_int (gst_date_time_get_year (dt), 1900 + tm.tm_year); + assert_equals_int (gst_date_time_get_month (dt), 1 + tm.tm_mon); + assert_equals_int (gst_date_time_get_day (dt), tm.tm_mday); + assert_equals_int (gst_date_time_get_hour (dt), tm.tm_hour); + assert_equals_int (gst_date_time_get_minute (dt), tm.tm_min); + assert_equals_int (gst_date_time_get_second (dt), tm.tm_sec); + gst_date_time_unref (dt); + + memset (&tm, 0, sizeof (tm)); + tm.tm_year = 70; + tm.tm_mday = 1; + tm.tm_mon = 0; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + t = mktime (&tm); + dt = gst_date_time_new_from_unix_epoch_local_time (t); + assert_equals_int (gst_date_time_get_year (dt), 1970); + assert_equals_int (gst_date_time_get_month (dt), 1); + assert_equals_int (gst_date_time_get_day (dt), 1); + assert_equals_int (gst_date_time_get_hour (dt), 0); + assert_equals_int (gst_date_time_get_minute (dt), 0); + assert_equals_int (gst_date_time_get_second (dt), 0); + gst_date_time_unref (dt); +} + +GST_END_TEST; + + +GST_START_TEST (test_GstDateTime_new_from_unix_epoch_utc) +{ + GstDateTime *dt; + struct tm tm; + time_t t; + + memset (&tm, 0, sizeof (tm)); + t = time (NULL); +#ifdef HAVE_GMTIME_R + gmtime_r (&t, &tm); +#else + memcpy (&tm, gmtime (&t), sizeof (struct tm)); +#endif + dt = gst_date_time_new_from_unix_epoch_utc (t); + assert_equals_int (gst_date_time_get_year (dt), 1900 + tm.tm_year); + assert_equals_int (gst_date_time_get_month (dt), 1 + tm.tm_mon); + assert_equals_int (gst_date_time_get_day (dt), tm.tm_mday); + assert_equals_int (gst_date_time_get_hour (dt), tm.tm_hour); + assert_equals_int (gst_date_time_get_minute (dt), tm.tm_min); + assert_equals_int (gst_date_time_get_second (dt), tm.tm_sec); + assert_equals_int (gst_date_time_get_time_zone_offset (dt), 0); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_dmy) +{ + GstDateTime *dt; + time_t t; + struct tm tt; + + t = time (NULL); +#ifdef HAVE_LOCALTIME_R + localtime_r (&t, &tt); +#else + memcpy (&tt, localtime (&t), sizeof (struct tm)); +#endif + dt = gst_date_time_new_from_unix_epoch_local_time (t); + assert_equals_int (gst_date_time_get_year (dt), tt.tm_year + 1900); + assert_equals_int (gst_date_time_get_month (dt), tt.tm_mon + 1); + assert_equals_int (gst_date_time_get_day (dt), tt.tm_mday); + + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_hour) +{ + GstDateTime *dt; + + dt = gst_date_time_new (0, 2009, 10, 19, 15, 13, 11); + assert_equals_int (15, gst_date_time_get_hour (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0, 100, 10, 19, 1, 0, 0); + assert_equals_int (1, gst_date_time_get_hour (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0, 100, 10, 19, 0, 0, 0); + assert_equals_int (0, gst_date_time_get_hour (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0, 100, 10, 1, 23, 59, 59); + assert_equals_int (23, gst_date_time_get_hour (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_microsecond) +{ + GTimeVal tv; + GstDateTime *dt; + + g_get_current_time (&tv); + dt = gst_date_time_new (0, 2010, 7, 15, 11, 12, + 13 + (tv.tv_usec / 1000000.0)); + assert_almost_equals_int (tv.tv_usec, gst_date_time_get_microsecond (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_minute) +{ + GstDateTime *dt; + + dt = gst_date_time_new (0, 2009, 12, 1, 1, 31, 0); + assert_equals_int (31, gst_date_time_get_minute (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_second) +{ + GstDateTime *dt; + + dt = gst_date_time_new (0, 2009, 12, 1, 1, 31, 44); + assert_equals_int (44, gst_date_time_get_second (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_new_full) +{ + GstDateTime *dt; + + dt = gst_date_time_new (0, 2009, 12, 11, 12, 11, 10.001234); + assert_equals_int (2009, gst_date_time_get_year (dt)); + assert_equals_int (12, gst_date_time_get_month (dt)); + assert_equals_int (11, gst_date_time_get_day (dt)); + assert_equals_int (12, gst_date_time_get_hour (dt)); + assert_equals_int (11, gst_date_time_get_minute (dt)); + assert_equals_int (10, gst_date_time_get_second (dt)); + assert_equals_int (1234, gst_date_time_get_microsecond (dt)); + assert_equals_float (0, gst_date_time_get_time_zone_offset (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (2.5, 2010, 3, 29, 12, 13, 16.5); + assert_equals_int (2010, gst_date_time_get_year (dt)); + assert_equals_int (3, gst_date_time_get_month (dt)); + assert_equals_int (29, gst_date_time_get_day (dt)); + assert_equals_int (12, gst_date_time_get_hour (dt)); + assert_equals_int (13, gst_date_time_get_minute (dt)); + assert_equals_int (16, gst_date_time_get_second (dt)); + assert_equals_int (500000, gst_date_time_get_microsecond (dt)); + assert_equals_float (2.5, gst_date_time_get_time_zone_offset (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_utc_now) +{ + GstDateTime *dt; + time_t t; + struct tm tm; + + t = time (NULL); +#ifdef HAVE_GMTIME_R + gmtime_r (&t, &tm); +#else + memcpy (&tm, gmtime (&t), sizeof (struct tm)); +#endif + dt = gst_date_time_new_now_utc (); + assert_equals_int (tm.tm_year + 1900, gst_date_time_get_year (dt)); + assert_equals_int (tm.tm_mon + 1, gst_date_time_get_month (dt)); + assert_equals_int (tm.tm_mday, gst_date_time_get_day (dt)); + assert_equals_int (tm.tm_hour, gst_date_time_get_hour (dt)); + assert_equals_int (tm.tm_min, gst_date_time_get_minute (dt)); + assert_almost_equals_int (tm.tm_sec, gst_date_time_get_second (dt)); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_get_utc_offset) +{ + struct tm tm; + time_t t; + + t = time (NULL); + memset (&tm, 0, sizeof (tm)); +#ifdef HAVE_LOCALTIME_R + localtime_r (&t, &tm); +#else + memcpy (&tm, localtime (&t), sizeof (struct tm)); +#endif + +#ifdef HAVE_TM_GMTOFF + { + GstDateTime *dt; + gfloat ts; + + dt = gst_date_time_new_now_local_time (); + ts = gst_date_time_get_time_zone_offset (dt); + assert_equals_int (ts, tm.tm_gmtoff / 3600.0); + gst_date_time_unref (dt); + } +#endif +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_partial_fields) +{ + GstDateTime *dt; + + ASSERT_CRITICAL (gst_date_time_new (0.0, -1, -1, -1, -1, -1, -1)); + ASSERT_CRITICAL (gst_date_time_new (0.0, 2012, 7, 18, 9, -1, -1)); + + dt = gst_date_time_new (0.0, 2012, -1, -1, -1, -1, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless_equals_int (gst_date_time_get_year (dt), 2012); + fail_if (gst_date_time_has_month (dt)); + ASSERT_CRITICAL (gst_date_time_get_month (dt)); + fail_if (gst_date_time_has_day (dt)); + ASSERT_CRITICAL (gst_date_time_get_day (dt)); + fail_if (gst_date_time_has_time (dt)); + ASSERT_CRITICAL (gst_date_time_get_hour (dt)); + ASSERT_CRITICAL (gst_date_time_get_minute (dt)); + fail_if (gst_date_time_has_second (dt)); + ASSERT_CRITICAL (gst_date_time_get_second (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0.0, 2012, 7, -1, -1, -1, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless_equals_int (gst_date_time_get_year (dt), 2012); + fail_unless (gst_date_time_has_month (dt)); + fail_unless_equals_int (gst_date_time_get_month (dt), 7); + fail_if (gst_date_time_has_day (dt)); + ASSERT_CRITICAL (gst_date_time_get_day (dt)); + fail_if (gst_date_time_has_time (dt)); + ASSERT_CRITICAL (gst_date_time_get_hour (dt)); + ASSERT_CRITICAL (gst_date_time_get_minute (dt)); + fail_if (gst_date_time_has_second (dt)); + ASSERT_CRITICAL (gst_date_time_get_second (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0.0, 2012, 7, 1, -1, -1, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless_equals_int (gst_date_time_get_month (dt), 7); + fail_unless (gst_date_time_has_day (dt)); + fail_unless_equals_int (gst_date_time_get_day (dt), 1); + fail_if (gst_date_time_has_time (dt)); + fail_if (gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0.0, 2012, 7, 1, 18, 20, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless_equals_int (gst_date_time_get_year (dt), 2012); + fail_unless (gst_date_time_has_month (dt)); + fail_unless_equals_int (gst_date_time_get_month (dt), 7); + fail_unless (gst_date_time_has_day (dt)); + fail_unless_equals_int (gst_date_time_get_day (dt), 1); + fail_unless (gst_date_time_has_time (dt)); + fail_unless_equals_int (gst_date_time_get_hour (dt), 18); + fail_unless_equals_int (gst_date_time_get_minute (dt), 20); + fail_if (gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new (0.0, 2012, 7, 1, 18, 20, 25.0443); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (gst_date_time_has_second (dt)); + fail_unless_equals_int (gst_date_time_get_second (dt), 25); + /* fail_unless_equals_int (gst_date_time_get_microsecond (dt), 443); */ + gst_date_time_unref (dt); +} + +GST_END_TEST; + +static gboolean +date_times_are_equal (GstDateTime * d1, GstDateTime * d2) +{ + GValue val1 = G_VALUE_INIT; + GValue val2 = G_VALUE_INIT; + int ret; + + g_value_init (&val1, GST_TYPE_DATE_TIME); + g_value_set_boxed (&val1, d1); + g_value_init (&val2, GST_TYPE_DATE_TIME); + g_value_set_boxed (&val2, d2); + ret = gst_value_compare (&val1, &val2); + g_value_unset (&val2); + g_value_unset (&val1); + + return ret == GST_VALUE_EQUAL; +} + +GST_START_TEST (test_GstDateTime_iso8601) +{ + GstDateTime *dt, *dt2; + gchar *str, *str2; + GDateTime *gdt, *gdt2; + + dt = gst_date_time_new_now_utc (); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_int (strlen (str), strlen ("2012-06-26T22:46:43Z")); + fail_unless (g_str_has_suffix (str, "Z")); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (gst_date_time_get_hour (dt) == gst_date_time_get_hour (dt2)); + fail_unless (gst_date_time_get_minute (dt) == gst_date_time_get_minute (dt2)); + fail_unless (gst_date_time_get_second (dt) == gst_date_time_get_second (dt2)); + /* This will succeed because we're not comparing microseconds when + * checking for equality */ + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- year only ---- */ + + dt = gst_date_time_new_y (2010); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (!gst_date_time_has_month (dt)); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + fail_unless (!gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- year and month ---- */ + + dt = gst_date_time_new_ym (2010, 10); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + fail_unless (!gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- year and month ---- */ + + dt = gst_date_time_new_ymd (2010, 10, 30); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + fail_unless (!gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10-30"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- date and time, but no seconds ---- */ + + dt = gst_date_time_new (-4.5, 2010, 10, 30, 15, 50, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (!gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10-30T15:50-0430"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (gst_date_time_get_hour (dt) == gst_date_time_get_hour (dt2)); + fail_unless (gst_date_time_get_minute (dt) == gst_date_time_get_minute (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- date and time, but no seconds (UTC) ---- */ + + dt = gst_date_time_new (0, 2010, 10, 30, 15, 50, -1); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (!gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10-30T15:50Z"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (gst_date_time_get_hour (dt) == gst_date_time_get_hour (dt2)); + fail_unless (gst_date_time_get_minute (dt) == gst_date_time_get_minute (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- date and time, with seconds ---- */ + + dt = gst_date_time_new (-4.5, 2010, 10, 30, 15, 50, 0); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10-30T15:50:00-0430"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (gst_date_time_get_hour (dt) == gst_date_time_get_hour (dt2)); + fail_unless (gst_date_time_get_minute (dt) == gst_date_time_get_minute (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- date and time, with seconds (UTC) ---- */ + + dt = gst_date_time_new (0, 2010, 10, 30, 15, 50, 0); + fail_unless (gst_date_time_has_year (dt)); + fail_unless (gst_date_time_has_month (dt)); + fail_unless (gst_date_time_has_day (dt)); + fail_unless (gst_date_time_has_time (dt)); + fail_unless (gst_date_time_has_second (dt)); + str = gst_date_time_to_iso8601_string (dt); + fail_unless (str != NULL); + fail_unless_equals_string (str, "2010-10-30T15:50:00Z"); + dt2 = gst_date_time_new_from_iso8601_string (str); + fail_unless (gst_date_time_get_year (dt) == gst_date_time_get_year (dt2)); + fail_unless (gst_date_time_get_month (dt) == gst_date_time_get_month (dt2)); + fail_unless (gst_date_time_get_day (dt) == gst_date_time_get_day (dt2)); + fail_unless (gst_date_time_get_hour (dt) == gst_date_time_get_hour (dt2)); + fail_unless (gst_date_time_get_minute (dt) == gst_date_time_get_minute (dt2)); + fail_unless (date_times_are_equal (dt, dt2)); + str2 = gst_date_time_to_iso8601_string (dt2); + fail_unless_equals_string (str, str2); + g_free (str2); + gst_date_time_unref (dt2); + g_free (str); + gst_date_time_unref (dt); + + /* ---- date and time, but without the 'T' and without timezone */ + dt = gst_date_time_new_from_iso8601_string ("2010-10-30 15:50"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (gst_date_time_get_month (dt) == 10); + fail_unless (gst_date_time_get_day (dt) == 30); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (!gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + /* ---- date and time+secs, but without the 'T' and without timezone */ + dt = gst_date_time_new_from_iso8601_string ("2010-10-30 15:50:33"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (gst_date_time_get_month (dt) == 10); + fail_unless (gst_date_time_get_day (dt) == 30); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (gst_date_time_get_second (dt) == 33); + gst_date_time_unref (dt); + + /* ---- dates with 00s */ + dt = gst_date_time_new_from_iso8601_string ("2010-10-00"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (gst_date_time_get_month (dt) == 10); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("2010-00-00"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (!gst_date_time_has_month (dt)); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("2010-00-30"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (!gst_date_time_has_month (dt)); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + gst_date_time_unref (dt); + + /* completely invalid */ + dt = gst_date_time_new_from_iso8601_string ("0000-00-00"); + fail_unless (dt == NULL); + + /* partially invalid - here we'll just extract the year */ + dt = gst_date_time_new_from_iso8601_string ("2010/05/30"); + fail_unless (gst_date_time_get_year (dt) == 2010); + fail_unless (!gst_date_time_has_month (dt)); + fail_unless (!gst_date_time_has_day (dt)); + fail_unless (!gst_date_time_has_time (dt)); + gst_date_time_unref (dt); + + + /* only time provided - we assume today's date */ + gdt = g_date_time_new_now_utc (); + + dt = gst_date_time_new_from_iso8601_string ("15:50:33"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (gst_date_time_get_second (dt) == 33); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("15:50:33Z"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (gst_date_time_get_second (dt) == 33); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("15:50"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (!gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("15:50Z"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (!gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + gdt2 = g_date_time_add_minutes (gdt, -270); + g_date_time_unref (gdt); + + dt = gst_date_time_new_from_iso8601_string ("15:50:33-0430"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt2)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt2)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt2)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (gst_date_time_get_second (dt) == 33); + gst_date_time_unref (dt); + + dt = gst_date_time_new_from_iso8601_string ("15:50-0430"); + fail_unless (gst_date_time_get_year (dt) == g_date_time_get_year (gdt2)); + fail_unless (gst_date_time_get_month (dt) == g_date_time_get_month (gdt2)); + fail_unless (gst_date_time_get_day (dt) == + g_date_time_get_day_of_month (gdt2)); + fail_unless (gst_date_time_get_hour (dt) == 15); + fail_unless (gst_date_time_get_minute (dt) == 50); + fail_unless (!gst_date_time_has_second (dt)); + gst_date_time_unref (dt); + + /* some bogus ones, make copy to detect out of bound read in valgrind/asan */ + { + gchar *s = g_strdup ("0002000000T00000:00+0"); + dt = gst_date_time_new_from_iso8601_string (s); + gst_date_time_unref (dt); + g_free (s); + } + + g_date_time_unref (gdt2); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_to_g_date_time) +{ + GDateTime *gdt1; + GDateTime *gdt2; + GstDateTime *dt; + + gdt1 = g_date_time_new_now_utc (); + g_date_time_ref (gdt1); /* keep it alive for compare below */ + dt = gst_date_time_new_from_g_date_time (gdt1); + gdt2 = gst_date_time_to_g_date_time (dt); + + fail_unless (g_date_time_compare (gdt1, gdt2) == 0); + + g_date_time_unref (gdt1); + g_date_time_unref (gdt2); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +GST_START_TEST (test_GstDateTime_new_from_g_date_time) +{ + GDateTime *gdt; + GstDateTime *dt; + + gdt = g_date_time_new_now_utc (); + g_date_time_ref (gdt); /* keep it alive for compare below */ + dt = gst_date_time_new_from_g_date_time (gdt); + + assert_equals_int (gst_date_time_get_year (dt), g_date_time_get_year (gdt)); + assert_equals_int (gst_date_time_get_month (dt), g_date_time_get_month (gdt)); + assert_equals_int (gst_date_time_get_day (dt), + g_date_time_get_day_of_month (gdt)); + assert_equals_int (gst_date_time_get_hour (dt), g_date_time_get_hour (gdt)); + assert_equals_int (gst_date_time_get_minute (dt), + g_date_time_get_minute (gdt)); + assert_equals_int (gst_date_time_get_second (dt), + g_date_time_get_second (gdt)); + assert_equals_int (gst_date_time_get_microsecond (dt), + g_date_time_get_microsecond (gdt)); + + g_date_time_unref (gdt); + gst_date_time_unref (dt); +} + +GST_END_TEST; + +static Suite * +gst_date_time_suite (void) +{ + Suite *s = suite_create ("GstDateTime"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_GstDateTime_get_dmy); + tcase_add_test (tc_chain, test_GstDateTime_get_hour); + tcase_add_test (tc_chain, test_GstDateTime_get_microsecond); + tcase_add_test (tc_chain, test_GstDateTime_get_minute); + tcase_add_test (tc_chain, test_GstDateTime_get_second); + tcase_add_test (tc_chain, test_GstDateTime_get_utc_offset); + tcase_add_test (tc_chain, test_GstDateTime_new_from_unix_epoch_local_time); + tcase_add_test (tc_chain, test_GstDateTime_new_from_unix_epoch_utc); + tcase_add_test (tc_chain, test_GstDateTime_new_full); + tcase_add_test (tc_chain, test_GstDateTime_now); + tcase_add_test (tc_chain, test_GstDateTime_utc_now); + tcase_add_test (tc_chain, test_GstDateTime_partial_fields); + tcase_add_test (tc_chain, test_GstDateTime_iso8601); + tcase_add_test (tc_chain, test_GstDateTime_to_g_date_time); + tcase_add_test (tc_chain, test_GstDateTime_new_from_g_date_time); + + return s; +} + +GST_CHECK_MAIN (gst_date_time) diff --git a/tests/check/gst/gstdeinit.c b/tests/check/gst/gstdeinit.c new file mode 100644 index 0000000..b551e85 --- /dev/null +++ b/tests/check/gst/gstdeinit.c @@ -0,0 +1,37 @@ +/* GStreamer + * Copyright (C) 2017 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +int +main (int argc, char **argv) +{ + char *arr[] = { (char *) "gstdeinit", (char *) "--gst-debug" }; + char **a = arr; + int n = 2; + + /* This will fail because --gst-debug requires a parameter */ + gst_init_check (&n, &a, NULL); + + gst_deinit (); + return 0; +} diff --git a/tests/check/gst/gstdevice.c b/tests/check/gst/gstdevice.c new file mode 100644 index 0000000..c59d43b --- /dev/null +++ b/tests/check/gst/gstdevice.c @@ -0,0 +1,561 @@ +/* GStreamer + * Copyright (C) 2014 Collabora + * Author: Olivier Crete + * + * gstdevice.c: Unit test for GstDevice + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +typedef struct _GstTestDevice +{ + GstDevice parent; +} GstTestDevice; + +typedef struct _GstTestDeviceClass +{ + GstDeviceClass parent_class; +} GstTestDeviceClass; + +GType gst_test_device_get_type (void); + + +G_DEFINE_TYPE (GstTestDevice, gst_test_device, GST_TYPE_DEVICE) + + static GstElement *gst_test_device_create_element (GstDevice * device, + const gchar * name) +{ + return gst_bin_new (name); +} + +static gboolean +gst_test_device_reconfigure_element (GstDevice * device, GstElement * element) +{ + if (!strcmp (GST_ELEMENT_NAME (element), "reconfigurable")) + return TRUE; + else + return FALSE; +} + +static void +gst_test_device_class_init (GstTestDeviceClass * klass) +{ + GstDeviceClass *dclass = GST_DEVICE_CLASS (klass); + + dclass->create_element = gst_test_device_create_element; + dclass->reconfigure_element = gst_test_device_reconfigure_element; +} + +static void +gst_test_device_init (GstTestDevice * self) +{ +} + +#define DEVICE_CLASS "Test0/Test1/Test2/Test3/Test4/TestDev" +#define DISPLAY_NAME "Test device" + +static GstDevice * +test_device_new (void) +{ + GstCaps *caps = gst_caps_new_empty_simple ("video/test"); + GstDevice *device = g_object_new (gst_test_device_get_type (), "caps", caps, + "display-name", DISPLAY_NAME, "device-class", DEVICE_CLASS, NULL); + + gst_caps_unref (caps); + + return device; +} + +GST_START_TEST (test_device) +{ + GstDevice *device = test_device_new (); + GstCaps *caps; + gchar *display_name; + gchar *device_class; + GstCaps *compare_caps = gst_caps_new_empty_simple ("video/test"); + GstElement *element; + + caps = gst_device_get_caps (device); + display_name = gst_device_get_display_name (device); + device_class = gst_device_get_device_class (device); + + fail_unless_equals_string (DISPLAY_NAME, display_name); + fail_unless_equals_string (DEVICE_CLASS, device_class); + gst_check_caps_equal (caps, compare_caps); + + g_free (display_name); + g_free (device_class); + gst_caps_unref (caps); + + fail_unless (gst_device_has_classes (device, "Test1")); + fail_unless (gst_device_has_classes (device, "Test2/Test1")); + + element = gst_device_create_element (device, "reconfigurable"); + fail_unless (GST_IS_BIN (element)); + + fail_unless (gst_device_reconfigure_element (device, element)); + + gst_element_set_name (element, "no-no"); + + fail_unless (!gst_device_reconfigure_element (device, element)); + + gst_object_unref (element); + + gst_caps_unref (compare_caps); + gst_object_unref (device); +} + +GST_END_TEST; + + +typedef struct _GstTestDeviceProvider +{ + GstDeviceProvider parent; + +} GstTestDeviceProvider; + +typedef struct _GstTestDeviceProviderClass +{ + GstDeviceProviderClass parent_class; +} GstTestDeviceProviderClass; + +GType gst_test_device_provider_get_type (void); + + +G_DEFINE_TYPE (GstTestDeviceProvider, gst_test_device_provider, + GST_TYPE_DEVICE_PROVIDER) + + + static GList *devices = NULL; + + static GList *gst_test_device_provider_probe (GstDeviceProvider * provider) +{ + GList *devs; + + devs = g_list_copy (devices); + g_list_foreach (devs, (GFunc) gst_object_ref, NULL); + + return devs; +} + +static void +gst_test_device_provider_class_init (GstTestDeviceProviderClass * klass) +{ + GstDeviceProviderClass *dpclass = GST_DEVICE_PROVIDER_CLASS (klass); + + dpclass->probe = gst_test_device_provider_probe; + + gst_device_provider_class_set_static_metadata (dpclass, + "Test Device Provider", "Test0/Test1/Test2/Test3/TestProvider", + "List but does NOT monitor test devices", + "Olivier Crete "); +} + +static void +gst_test_device_provider_init (GstTestDeviceProvider * self) +{ +} + +static void +register_test_device_provider (void) +{ + gst_device_provider_register (NULL, "testdeviceprovider", 1, + gst_test_device_provider_get_type ()); +} + +GST_START_TEST (test_device_provider_factory) +{ + GstDeviceProvider *dp, *dp2; + GList *factories; + GstDeviceProviderFactory *f; + + register_test_device_provider (); + + factories = gst_device_provider_factory_list_get_device_providers (1); + + fail_unless (factories != NULL); + + f = gst_device_provider_factory_find ("testdeviceprovider"); + fail_unless (f != NULL); + + gst_plugin_feature_list_free (factories); + + fail_unless (gst_device_provider_factory_has_classes (f, "Test2")); + fail_unless (gst_device_provider_factory_has_classes (f, "Test2/Test0")); + fail_unless (!gst_device_provider_factory_has_classes (f, + "Test2/TestN/Test0")); + fail_unless (!gst_device_provider_factory_has_classes (f, "TestN")); + fail_unless (!gst_device_provider_factory_has_classes (f, "Test")); + + dp = gst_device_provider_factory_get (f); + + gst_object_unref (f); + + dp2 = gst_device_provider_factory_get_by_name ("testdeviceprovider"); + + fail_unless_equals_pointer (dp, dp2); + + gst_object_unref (dp); + gst_object_unref (dp2); + + dp2 = gst_device_provider_factory_get_by_name ("testdeviceprovider"); + fail_unless_equals_pointer (dp, dp2); + gst_object_unref (dp2); +} + +GST_END_TEST; + +GST_START_TEST (test_device_provider) +{ + GstDeviceProvider *dp; + GList *devs; + GstBus *bus; + + register_test_device_provider (); + + dp = gst_device_provider_factory_get_by_name ("testdeviceprovider"); + + fail_unless (gst_device_provider_get_devices (dp) == NULL); + + devices = g_list_append (NULL, test_device_new ()); + + devs = gst_device_provider_get_devices (dp); + fail_unless (g_list_length (devs) == 1); + fail_unless_equals_pointer (devs->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + fail_if (gst_device_provider_can_monitor (dp)); + fail_if (gst_device_provider_start (dp)); + + bus = gst_device_provider_get_bus (dp); + fail_unless (GST_IS_BUS (bus)); + gst_object_unref (bus); + + g_list_free_full (devices, (GDestroyNotify) gst_object_unref); + gst_object_unref (dp); +} + +GST_END_TEST; + +typedef struct _GstTestDeviceProviderMonitor +{ + GstDeviceProvider parent; + +} GstTestDeviceProviderMonitor; + +typedef struct _GstTestDeviceProviderMonitorClass +{ + GstDeviceProviderClass parent_class; +} GstTestDeviceProviderMonitorClass; + +GType gst_test_device_provider_monitor_get_type (void); + + +G_DEFINE_TYPE (GstTestDeviceProviderMonitor, gst_test_device_provider_monitor, + GST_TYPE_DEVICE_PROVIDER) + + + static gboolean + gst_test_device_provider_monitor_start (GstDeviceProvider * monitor) +{ + return TRUE; +} + +static void +gst_test_device_provider_monitor_class_init (GstTestDeviceProviderMonitorClass * + klass) +{ + GstDeviceProviderClass *dpclass = GST_DEVICE_PROVIDER_CLASS (klass); + + dpclass->probe = gst_test_device_provider_probe; + dpclass->start = gst_test_device_provider_monitor_start; + + gst_device_provider_class_set_static_metadata (dpclass, + "Test Device Provider Monitor", + "Test0/Test1/Test2/Test4/TestProviderMonitor", + "List and monitors Test devices", + "Olivier Crete "); +} + +static void +gst_test_device_provider_monitor_init (GstTestDeviceProviderMonitor * self) +{ +} + +static void +register_test_device_provider_monitor (void) +{ + gst_device_provider_register (NULL, "testdeviceprovidermonitor", 2, + gst_test_device_provider_monitor_get_type ()); +} + + +GST_START_TEST (test_device_provider_monitor) +{ + GstDeviceProvider *dp; + GList *devs; + GstBus *bus; + GstDevice *mydev; + GstDevice *dev; + GstMessage *msg; + + register_test_device_provider_monitor (); + + devices = g_list_append (NULL, test_device_new ()); + + dp = gst_device_provider_factory_get_by_name ("testdeviceprovidermonitor"); + + bus = gst_device_provider_get_bus (dp); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + fail_unless (gst_device_provider_can_monitor (dp)); + fail_unless (gst_device_provider_start (dp)); + + fail_unless (gst_device_provider_get_devices (dp) == NULL); + + devs = gst_device_provider_get_devices (dp); + fail_unless (devs == NULL); + + mydev = test_device_new (); + fail_unless (g_object_is_floating (mydev)); + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 1); + + gst_device_provider_device_add (dp, mydev); + fail_unless (!g_object_is_floating (mydev)); + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 2); + + devs = gst_device_provider_get_devices (dp); + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 3); + + fail_unless_equals_int (g_list_length (devs), 1); + fail_unless_equals_pointer (devs->data, mydev); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 2); + + msg = gst_bus_pop (bus); + fail_unless (msg != NULL); + + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_DEVICE_ADDED); + + gst_message_parse_device_added (msg, &dev); + fail_unless_equals_pointer (dev, mydev); + gst_object_unref (dev); + gst_message_unref (msg); + + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 1); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + gst_device_provider_device_remove (dp, mydev); + devs = gst_device_provider_get_devices (dp); + fail_unless (devs == NULL); + + msg = gst_bus_pop (bus); + fail_unless (msg != NULL); + + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_DEVICE_REMOVED); + + gst_message_parse_device_removed (msg, &dev); + fail_unless_equals_pointer (dev, mydev); + ASSERT_OBJECT_REFCOUNT (mydev, "dev", 2); + gst_object_unref (dev); + gst_message_unref (msg); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + gst_device_provider_stop (dp); + gst_object_unref (bus); + ASSERT_OBJECT_REFCOUNT (dp, "monitor", 2); + gst_object_unref (dp); + + /* Is singleton, so system keeps a ref */ + ASSERT_OBJECT_REFCOUNT (dp, "monitor", 1); + + g_list_free_full (devices, (GDestroyNotify) gst_object_unref); +} + +GST_END_TEST; + + +GST_START_TEST (test_device_monitor) +{ + GstDeviceProvider *dp, *dp2; + GstDeviceMonitor *mon; + GList *devs; + guint id, id2; + GstDevice *mydev; + GstMessage *msg; + GstBus *bus; + GstDevice *dev; + + register_test_device_provider (); + register_test_device_provider_monitor (); + + dp = gst_device_provider_factory_get_by_name ("testdeviceprovider"); + dp2 = gst_device_provider_factory_get_by_name ("testdeviceprovidermonitor"); + + mon = gst_device_monitor_new (); + + devices = g_list_append (NULL, test_device_new ()); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (devs == NULL); + + id = gst_device_monitor_add_filter (mon, "TestProvider", NULL); + fail_unless (id > 0); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (devs == NULL); + + fail_unless (gst_device_monitor_add_filter (mon, "TestDevice", NULL) == 0); + ASSERT_CRITICAL (gst_device_monitor_remove_filter (mon, 0)); + + fail_unless (gst_device_monitor_remove_filter (mon, id)); + + id = gst_device_monitor_add_filter (mon, "Test3", NULL); + fail_unless (id > 0); + devs = gst_device_monitor_get_devices (mon); + fail_unless (g_list_length (devs) == 1); + fail_unless_equals_pointer (devs->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + id2 = gst_device_monitor_add_filter (mon, "Test1", NULL); + fail_unless (id2 > 0); + devs = gst_device_monitor_get_devices (mon); + fail_unless (g_list_length (devs) == 2); + fail_unless_equals_pointer (devs->data, devices->data); + fail_unless_equals_pointer (devs->next->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + fail_unless (gst_device_monitor_remove_filter (mon, id)); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (g_list_length (devs) == 2); + fail_unless_equals_pointer (devs->data, devices->data); + fail_unless_equals_pointer (devs->next->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + + fail_unless (gst_device_monitor_start (mon)); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (g_list_length (devs) == 1); + fail_unless_equals_pointer (devs->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + gst_device_monitor_stop (mon); + + fail_unless (gst_device_monitor_remove_filter (mon, id2)); + + id = gst_device_monitor_add_filter (mon, "Test4", NULL); + fail_unless (id > 0); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (g_list_length (devs) == 1); + fail_unless_equals_pointer (devs->data, devices->data); + g_list_free_full (devs, (GDestroyNotify) gst_object_unref); + + fail_unless (gst_device_monitor_start (mon)); + + devs = gst_device_monitor_get_devices (mon); + fail_unless (devs == NULL); + + bus = gst_device_monitor_get_bus (mon); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + mydev = test_device_new (); + gst_device_provider_device_add (dp2, mydev); + + msg = gst_bus_pop (bus); + fail_unless (msg != NULL); + + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_DEVICE_ADDED); + + gst_message_parse_device_added (msg, &dev); + fail_unless_equals_pointer (dev, mydev); + gst_object_unref (dev); + gst_message_unref (msg); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + gst_device_provider_device_remove (dp2, mydev); + devs = gst_device_monitor_get_devices (mon); + fail_unless (devs == NULL); + + msg = gst_bus_pop (bus); + fail_unless (msg != NULL); + + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_DEVICE_REMOVED); + + gst_message_parse_device_removed (msg, &dev); + fail_unless_equals_pointer (dev, mydev); + gst_object_unref (dev); + gst_message_unref (msg); + + msg = gst_bus_pop (bus); + fail_unless (msg == NULL); + + + gst_device_monitor_stop (mon); + + gst_object_unref (bus); + gst_object_unref (mon); + + gst_object_unref (dp); + gst_object_unref (dp2); + g_list_free_full (devices, (GDestroyNotify) gst_object_unref); + + /* should work fine without any filters */ + mon = gst_device_monitor_new (); + fail_unless (gst_device_monitor_start (mon)); + gst_device_monitor_stop (mon); + gst_object_unref (mon); +} + +GST_END_TEST; + + +static Suite * +gst_device_suite (void) +{ + Suite *s = suite_create ("GstDevice"); + TCase *tc_chain = tcase_create ("device tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_device); + tcase_add_test (tc_chain, test_device_provider_factory); + tcase_add_test (tc_chain, test_device_provider); + tcase_add_test (tc_chain, test_device_provider_monitor); + tcase_add_test (tc_chain, test_device_monitor); + + return s; +} + +GST_CHECK_MAIN (gst_device); diff --git a/tests/check/gst/gstelement.c b/tests/check/gst/gstelement.c new file mode 100644 index 0000000..fa63ee6 --- /dev/null +++ b/tests/check/gst/gstelement.c @@ -0,0 +1,930 @@ +/* GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * + * gstelement.c: Unit test for GstElement + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_add_remove_pad) +{ + GstElement *e; + GstPad *p; + + /* getting an existing element class is cheating, but easier */ + e = gst_element_factory_make ("fakesrc", "source"); + + /* create a new floating pad with refcount 1 */ + p = gst_pad_new ("source", GST_PAD_SRC); + ASSERT_OBJECT_REFCOUNT (p, "pad", 1); + /* ref it for ourselves */ + gst_object_ref (p); + ASSERT_OBJECT_REFCOUNT (p, "pad", 2); + /* adding it sinks the pad -> not floating, same refcount */ + gst_element_add_pad (e, p); + ASSERT_OBJECT_REFCOUNT (p, "pad", 2); + + /* removing it reduces the refcount */ + gst_element_remove_pad (e, p); + ASSERT_OBJECT_REFCOUNT (p, "pad", 1); + + /* clean up our own reference */ + gst_object_unref (p); + gst_object_unref (e); +} + +GST_END_TEST; + +GST_START_TEST (test_add_pad_unref_element) +{ + GstElement *e; + GstPad *p; + + /* getting an existing element class is cheating, but easier */ + e = gst_element_factory_make ("fakesrc", "source"); + + /* create a new floating pad with refcount 1 */ + p = gst_pad_new ("source", GST_PAD_SRC); + ASSERT_OBJECT_REFCOUNT (p, "pad", 1); + /* ref it for ourselves */ + gst_object_ref (p); + ASSERT_OBJECT_REFCOUNT (p, "pad", 2); + /* adding it sinks the pad -> not floating, same refcount */ + gst_element_add_pad (e, p); + ASSERT_OBJECT_REFCOUNT (p, "pad", 2); + + /* unreffing the element should clean it up */ + gst_object_unref (GST_OBJECT (e)); + + ASSERT_OBJECT_REFCOUNT (p, "pad", 1); + + /* clean up our own reference */ + gst_object_unref (p); +} + +GST_END_TEST; + +GST_START_TEST (test_error_no_bus) +{ + GstElement *e; + GstBus *bus; + + e = gst_element_factory_make ("fakesrc", "source"); + + /* get the bus, should be NULL */ + bus = gst_element_get_bus (e); + fail_if (bus != NULL); + + /* I don't want errors shown */ + gst_debug_set_default_threshold (GST_LEVEL_NONE); + + GST_ELEMENT_ERROR (e, RESOURCE, OPEN_READ, ("I could not read"), ("debug")); + + gst_object_unref (e); +} + +GST_END_TEST; + +/* link and run two elements without putting them in a pipeline */ +GST_START_TEST (test_link) +{ + GstElement *src, *sink; + + src = gst_element_factory_make ("fakesrc", "source"); + sink = gst_element_factory_make ("fakesink", "sink"); + + fail_unless (gst_element_link_pads (src, "src", sink, "sink")); + + /* do sink to source state change */ + gst_element_set_state (sink, GST_STATE_PAUSED); + gst_element_set_state (src, GST_STATE_PAUSED); + + /* wait for preroll */ + gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE); + + /* play some more */ + gst_element_set_state (sink, GST_STATE_PLAYING); + gst_element_set_state (src, GST_STATE_PLAYING); + + g_usleep (G_USEC_PER_SEC); + + /* and stop */ + gst_element_set_state (sink, GST_STATE_PAUSED); + gst_element_set_state (src, GST_STATE_PAUSED); + + /* wait for preroll */ + gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE); + + gst_element_set_state (sink, GST_STATE_NULL); + gst_element_set_state (src, GST_STATE_NULL); + + gst_element_get_state (sink, NULL, NULL, GST_CLOCK_TIME_NONE); + g_usleep (G_USEC_PER_SEC / 2); + + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + gst_element_unlink_pads (src, "src", sink, "sink"); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +/* linking two elements without pads should fail */ +GST_START_TEST (test_link_no_pads) +{ + GstElement *src, *sink; + + src = gst_bin_new ("src"); + sink = gst_bin_new ("sink"); + + fail_if (gst_element_link (src, sink)); + + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +typedef struct _GstTestElement +{ + GstElement parent; + +} GstTestElement; + +typedef struct _GstTestElementClass +{ + GstElementClass parent; + +} GstTestElementClass; + +static void +gst_test_element_class_init (GstTestElementClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstPadTemplate *templ; + + gst_element_class_set_metadata (element_class, "Test element", + "Element", "Does nothing", "Foo Bar "); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 0); + + fail_unless (gst_element_class_get_pad_template (element_class, + "test") == NULL); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY)); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 1); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test")) != NULL); + fail_unless (gst_caps_is_any (templ->caps)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("test2", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_CAPS_ANY)); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 2); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test2")) != NULL); + fail_unless (gst_caps_is_any (templ->caps)); + + /* Add "test" again, with NONE caps this time */ + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_CAPS_NONE)); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 2); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test")) != NULL); + fail_unless (gst_caps_is_empty (templ->caps)); +} + +static GType +gst_test_element_get_type (void) +{ + static GType gst_test_element_type = G_TYPE_NONE; + + if (gst_test_element_type == G_TYPE_NONE) { + static const GTypeInfo gst_test_element_info = { + sizeof (GstTestElementClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_test_element_class_init, + NULL, + NULL, + sizeof (GstTestElement), + 0, + NULL, /* instance_init */ + NULL + }; + + gst_test_element_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstTestElement", &gst_test_element_info, 0); + } + return gst_test_element_type; +} + +typedef struct _GstTestElement2 +{ + GstTestElement parent; + +} GstTestElement2; + +typedef struct _GstTestElement2Class +{ + GstTestElementClass parent; + +} GstTestElement2Class; + +static void +gst_test_element2_class_init (GstTestElement2Class * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstPadTemplate *templ; + + gst_element_class_set_metadata (element_class, "Test element 2", + "Element", "Does nothing", "Foo Bar "); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 2); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test")) != NULL); + fail_unless (gst_caps_is_empty (templ->caps)); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test2")) != NULL); + fail_unless (gst_caps_is_any (templ->caps)); + + /* Add "test" pad with ANY caps, should have "test" pad with EMPTY caps before */ + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY)); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 2); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test")) != NULL); + fail_unless (gst_caps_is_any (templ->caps)); + + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("test4", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_CAPS_ANY)); + + fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list + (element_class)), 3); + + fail_unless ((templ = + gst_element_class_get_pad_template (element_class, "test4")) != NULL); + fail_unless (gst_caps_is_any (templ->caps)); +} + +static GType +gst_test_element2_get_type (void) +{ + static GType gst_test_element2_type = G_TYPE_NONE; + + if (gst_test_element2_type == G_TYPE_NONE) { + static const GTypeInfo gst_test_element2_info = { + sizeof (GstTestElement2Class), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_test_element2_class_init, + NULL, + NULL, + sizeof (GstTestElement2), + 0, + NULL, /* instance_init */ + NULL + }; + + gst_test_element2_type = + g_type_register_static (gst_test_element_get_type (), "GstTestElement2", + &gst_test_element2_info, 0); + } + return gst_test_element2_type; +} + + +GST_START_TEST (test_pad_templates) +{ + GstTestElement *test; + GstTestElement2 *test2; + + test = g_object_new (gst_test_element_get_type (), NULL); + test2 = g_object_new (gst_test_element2_get_type (), NULL); + + g_object_unref (test); + g_object_unref (test2); +} + +GST_END_TEST; + +/* need to return the message here because object, property name and value + * are only valid as long as we keep the message alive */ +static GstMessage * +bus_wait_for_notify_message (GstBus * bus, GstElement ** obj, + const gchar ** prop_name, const GValue ** val) +{ + GstMessage *msg; + + do { + msg = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_ANY); + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_PROPERTY_NOTIFY) + break; + gst_message_unref (msg); + } while (TRUE); + + gst_message_parse_property_notify (msg, (GstObject **) obj, prop_name, val); + return msg; +} + +GST_START_TEST (test_property_notify_message) +{ + GstElement *pipeline, *identity; + gulong watch_id0, watch_id1, watch_id2, deep_watch_id1, deep_watch_id2; + GstBus *bus; + + pipeline = gst_pipeline_new (NULL); + identity = gst_element_factory_make ("identity", NULL); + gst_bin_add (GST_BIN (pipeline), identity); + + bus = GST_ELEMENT_BUS (pipeline); + + /* need to set state to READY, otherwise bus will be flushing and discard + * our messages */ + gst_element_set_state (pipeline, GST_STATE_READY); + + watch_id0 = gst_element_add_property_notify_watch (identity, NULL, FALSE); + + watch_id1 = gst_element_add_property_notify_watch (identity, "sync", FALSE); + + watch_id2 = gst_element_add_property_notify_watch (identity, "silent", TRUE); + + deep_watch_id1 = + gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE); + + deep_watch_id2 = + gst_element_add_property_deep_notify_watch (pipeline, "silent", FALSE); + + /* Now test property changes and if we get the messages we expect. We rely + * on the signals being fired in the order that they were set up here. */ + { + const GValue *val; + const gchar *name; + GstMessage *msg; + GstElement *obj; + + /* A - This should be picked up by... */ + g_object_set (identity, "dump", TRUE, NULL); + /* 1) the catch-all notify on the element (no value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless (obj == identity); + fail_unless_equals_string (name, "dump"); + fail_unless (val == NULL); + gst_message_unref (msg); + /* 2) the catch-all deep-notify on the pipeline (with value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless_equals_string (name, "dump"); + fail_unless (obj == identity); + fail_unless (G_VALUE_HOLDS_BOOLEAN (val)); + fail_unless_equals_int (g_value_get_boolean (val), TRUE); + gst_message_unref (msg); + + /* B - This should be picked up by... */ + g_object_set (identity, "sync", TRUE, NULL); + /* 1) the catch-all notify on the element (no value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless (obj == identity); + fail_unless_equals_string (name, "sync"); + fail_unless (val == NULL); + gst_message_unref (msg); + /* 2) the "sync" notify on the element (no value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless (obj == identity); + fail_unless_equals_string (name, "sync"); + fail_unless (val == NULL); + gst_message_unref (msg); + /* 3) the catch-all deep-notify on the pipeline (with value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless_equals_string (name, "sync"); + fail_unless (obj == identity); + fail_unless (G_VALUE_HOLDS_BOOLEAN (val)); + fail_unless_equals_int (g_value_get_boolean (val), TRUE); + gst_message_unref (msg); + + /* C - This should be picked up by... */ + g_object_set (identity, "silent", FALSE, NULL); + /* 1) the catch-all notify on the element (no value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless (obj == identity); + fail_unless_equals_string (name, "silent"); + fail_unless (val == NULL); + gst_message_unref (msg); + /* 2) the "silent" notify on the element (with value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless (obj == identity); + fail_unless_equals_string (name, "silent"); + fail_unless (val != NULL); + fail_unless (G_VALUE_HOLDS_BOOLEAN (val)); + fail_unless_equals_int (g_value_get_boolean (val), FALSE); + gst_message_unref (msg); + /* 3) the catch-all deep-notify on the pipeline (with value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless_equals_string (name, "silent"); + fail_unless (obj == identity); + fail_unless (G_VALUE_HOLDS_BOOLEAN (val)); + fail_unless_equals_int (g_value_get_boolean (val), FALSE); + gst_message_unref (msg); + /* 4) the "silent" deep-notify on the pipeline (without value) */ + msg = bus_wait_for_notify_message (bus, &obj, &name, &val); + fail_unless_equals_string (name, "silent"); + fail_unless (obj == identity); + fail_unless (val == NULL); + gst_message_unref (msg); + } + + gst_element_remove_property_notify_watch (identity, watch_id0); + gst_element_remove_property_notify_watch (identity, watch_id1); + gst_element_remove_property_notify_watch (identity, watch_id2); + gst_element_remove_property_notify_watch (pipeline, deep_watch_id1); + gst_element_remove_property_notify_watch (pipeline, deep_watch_id2); + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +typedef struct _GstTestElement3 +{ + GstElement parent; + +} GstTestElement3; + +typedef struct _GstTestElement3Class +{ + GstElementClass parent; + +} GstTestElement3Class; + +static GstPad * +gst_test_element3_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstPad *pad; + gchar *str; + gchar *pad_name; + gint n_conversion = 0; + static gint i = 0; + + str = templ->name_template; + while ((str = strchr (str, '%'))) { + n_conversion++; + str++; + } + + if (strcmp (templ->name_template, "src_%ublah_blah%ublah") == 0) + pad_name = g_strdup_printf ("src_%ublah_blah_%ublah", i, i + 1); + else if (n_conversion == 1) { + pad_name = g_strdup_printf ("src_%u", i); + } else if (n_conversion == 2) { + pad_name = g_strdup_printf ("src_%u_%u", i, i + 1); + } else if (n_conversion == 3) { + pad_name = g_strdup_printf ("src_%u_%u_%u", i, i + 1, i + 2); + } else { + pad_name = g_strdup (name); + } + + pad = gst_pad_new_from_template (templ, pad_name); + + gst_element_add_pad (element, pad); + + i++; + g_free (pad_name); + + return pad; +} + +static void +gst_test_element3_release_pad (GstElement * element, GstPad * pad) +{ + gst_element_remove_pad (element, pad); +} + +static void +gst_test_element3_init (GstTestElement3 * test) +{ + GstPadTemplate *pad_template; + GstPad *sinkpad; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (test), "sink"); + g_return_if_fail (pad_template != NULL); + sinkpad = gst_pad_new_from_template (pad_template, "sink"); + + gst_element_add_pad (GST_ELEMENT (test), sinkpad); +} + +static void +gst_test_element3_class_init (GstTestElement3Class * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_metadata (element_class, "Test element 3", + "Element", "For testing request pad template", "Foo Bar "); + + element_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_test_element3_request_new_pad); + element_class->release_pad = + GST_DEBUG_FUNCPTR (gst_test_element3_release_pad); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%u", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%u_%u", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%u_%u_%u", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%ublah_blah%ublah", GST_PAD_SRC, + GST_PAD_REQUEST, GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%d", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%d_%d", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%d_%d_%d", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%s", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src_%u_%s", GST_PAD_SRC, GST_PAD_REQUEST, + GST_CAPS_ANY)); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_CAPS_ANY)); +} + +static GType +gst_test_element3_get_type (void) +{ + static GType gst_test_element3_type = G_TYPE_NONE; + + if (gst_test_element3_type == G_TYPE_NONE) { + static const GTypeInfo gst_test_element3_info = { + sizeof (GstTestElement3Class), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_test_element3_class_init, + NULL, + NULL, + sizeof (GstTestElement3), + 0, + (GInstanceInitFunc) gst_test_element3_init, + NULL + }; + + gst_test_element3_type = + g_type_register_static (gst_element_get_type (), "GstTestElement3", + &gst_test_element3_info, 0); + } + return gst_test_element3_type; +} + +static gboolean +gst_test_element3_plugin_init (GstPlugin * plugin) +{ + gst_element_register (plugin, "test3", GST_RANK_NONE, + gst_test_element3_get_type ()); + return TRUE; +} + +GST_START_TEST (test_request_pad_templates) +{ + GstTestElement3 *test; + GstElement *pipeline, *sink; + GstPad *pad; + GHashTable *padnames; + GHashTableIter iter; + gpointer key, value; + const gchar *pad_name, *templ_name; + GSList *padname_blacklists = NULL, *item; + GError *err = NULL; + + padnames = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (padnames, (gpointer) "src_0", (gpointer) "src_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u", (gpointer) "src_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_%u", + (gpointer) "src_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_0_%u", (gpointer) "src_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_0", (gpointer) "src_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_0_1", (gpointer) "src_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_%u_%u", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_0_%u_%u", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_0_1_%u", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_0_1_2", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_0_%u", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_0_1", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%u_%u_0", + (gpointer) "src_%u_%u_%u"); + g_hash_table_insert (padnames, (gpointer) "src_%ublah_blah%ublah", + (gpointer) "src_%ublah_blah%ublah"); + g_hash_table_insert (padnames, (gpointer) "src_%d", (gpointer) "src_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%d_%d", + (gpointer) "src_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_1_%d", (gpointer) "src_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%d_%d_%d", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_1_2_%d", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_1_%d_2", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%d_2_1", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%d_%d_1", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%d_1_%d", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_1_%d_%d", + (gpointer) "src_%d_%d_%d"); + g_hash_table_insert (padnames, (gpointer) "src_%s", (gpointer) "src_%s"); + g_hash_table_insert (padnames, (gpointer) "src_%u_%s", + (gpointer) "src_%u_%s"); + + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%u%u"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%u_%d"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%u_%u_"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%u_%s_%s"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%s_%u"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%s_%s"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%s_%s_%s"); + padname_blacklists = + g_slist_append (padname_blacklists, (gpointer) "src_%s_blah"); + + test = g_object_new (gst_test_element3_get_type (), NULL); + + /* check available request pad names */ + g_hash_table_iter_init (&iter, padnames); + while (g_hash_table_iter_next (&iter, &key, &value)) { + pad_name = (const gchar *) key; + templ_name = (const gchar *) value; + + pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name); + fail_unless (pad != NULL); + gst_element_release_request_pad (GST_ELEMENT (test), pad); + gst_object_unref (pad); + + pad = gst_element_request_pad (GST_ELEMENT (test), + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (test), + templ_name), pad_name, NULL); + fail_unless (pad != NULL); + gst_element_release_request_pad (GST_ELEMENT (test), pad); + gst_object_unref (pad); + } + + item = padname_blacklists; + + /* check invalid request pad name */ + while (item) { + pad_name = (const gchar *) (item->data); + item = g_slist_next (item); + pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name); + fail_unless (pad == NULL); + } + + /* check it working with some APIs + * gst_element_link/link_pads */ + sink = gst_element_factory_make ("fakesink", "sink"); + + fail_unless (gst_element_link (GST_ELEMENT (test), sink)); + gst_element_unlink (GST_ELEMENT (test), sink); + + fail_unless (gst_element_link_pads (GST_ELEMENT (test), "src_%u_%u", sink, + "sink")); + gst_element_unlink (GST_ELEMENT (test), sink); + + g_object_unref (test); + g_object_unref (sink); + + /* gst_parse_launch */ + gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "test3", + "request pad template test", + gst_test_element3_plugin_init, + VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); + + pipeline = + gst_parse_launch ("fakesrc ! test3 name=t ! fakesink t. ! fakesink", + &err); + fail_unless (pipeline && err == NULL); + + if (err) { + g_error_free (err); + } + g_slist_free (padname_blacklists); + g_hash_table_unref (padnames); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static gboolean run_foreach_thread; + +/* thread function that just adds/removes pads while main thread iterates pads */ +static gpointer +thread_add_remove_pads (GstElement * e) +{ + GPtrArray *pads; + guint n, c = 0; + + pads = g_ptr_array_new (); + + THREAD_START (); + + while (g_atomic_int_get (&run_foreach_thread)) { + GstPad *p; + gchar name[16]; + + /* add a new pad */ + g_snprintf (name, 16, "pad_%u", c++); + p = gst_pad_new (name, g_random_boolean ()? GST_PAD_SRC : GST_PAD_SINK); + g_ptr_array_add (pads, p); + gst_element_add_pad (e, p); + + THREAD_SWITCH (); + + /* and remove a random pad */ + if (g_random_boolean () || pads->len > 100) { + n = g_random_int_range (0, pads->len); + p = g_ptr_array_remove_index (pads, n); + gst_element_remove_pad (e, p); + } + + THREAD_SWITCH (); + } + + g_ptr_array_free (pads, TRUE); + return NULL; +} + +typedef struct +{ + GQuark q; + GstPadDirection dir; /* GST_PAD_UNKNOWN = both are allowed */ + gboolean func_called; +} PadChecks; + +static gboolean +pad_foreach_func (GstElement * e, GstPad * pad, gpointer user_data) +{ + PadChecks *checks = user_data; + + /* check we haven't visited this pad already */ + fail_if (g_object_get_qdata (G_OBJECT (pad), checks->q) != NULL); + + g_object_set_qdata (G_OBJECT (pad), checks->q, GINT_TO_POINTER (1)); + + if (checks->dir != GST_PAD_UNKNOWN) { + fail_unless_equals_int (checks->dir, GST_PAD_DIRECTION (pad)); + } + checks->func_called = TRUE; + return TRUE; +} + +GST_START_TEST (test_foreach_pad) +{ + PadChecks checks = { 0, GST_PAD_UNKNOWN, FALSE }; + GstElement *e; + gint i; + + e = gst_bin_new ("testbin"); + + /* function should not be called if there are no pads! */ + gst_element_foreach_pad (e, pad_foreach_func, &checks); + fail_if (checks.func_called); + + g_atomic_int_set (&run_foreach_thread, TRUE); + + MAIN_INIT (); + MAIN_START_THREAD_FUNCTION (0, thread_add_remove_pads, e); + MAIN_SYNCHRONIZE (); + + for (i = 0; i < 10000; ++i) { + gchar num[32]; + + g_snprintf (num, 32, "foreach-test-%u", i); + + checks.q = g_quark_from_string (num); + checks.func_called = FALSE; + if (g_random_boolean ()) { + checks.dir = GST_PAD_UNKNOWN; + gst_element_foreach_pad (e, pad_foreach_func, &checks); + } else if (g_random_boolean ()) { + checks.dir = GST_PAD_SRC; + gst_element_foreach_src_pad (e, pad_foreach_func, &checks); + } else { + checks.dir = GST_PAD_SINK; + gst_element_foreach_sink_pad (e, pad_foreach_func, &checks); + } + + THREAD_SWITCH (); + } + + g_atomic_int_set (&run_foreach_thread, FALSE); + + MAIN_STOP_THREADS (); + + /* function should be called if there are pads */ + checks.q = g_quark_from_string ("fini"); + checks.dir = GST_PAD_UNKNOWN; + checks.func_called = FALSE; + gst_element_foreach_pad (e, pad_foreach_func, &checks); + fail_if (e->numpads > 0 && !checks.func_called); + + gst_object_unref (e); +} + +GST_END_TEST; + +static Suite * +gst_element_suite (void) +{ + Suite *s = suite_create ("GstElement"); + TCase *tc_chain = tcase_create ("element tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_add_remove_pad); + tcase_add_test (tc_chain, test_add_pad_unref_element); + tcase_add_test (tc_chain, test_error_no_bus); + tcase_add_test (tc_chain, test_link); + tcase_add_test (tc_chain, test_link_no_pads); + tcase_add_test (tc_chain, test_pad_templates); + tcase_add_test (tc_chain, test_property_notify_message); + tcase_add_test (tc_chain, test_request_pad_templates); + tcase_add_test (tc_chain, test_foreach_pad); + + return s; +} + +GST_CHECK_MAIN (gst_element); diff --git a/tests/check/gst/gstelementfactory.c b/tests/check/gst/gstelementfactory.c new file mode 100644 index 0000000..294ebf1 --- /dev/null +++ b/tests/check/gst/gstelementfactory.c @@ -0,0 +1,183 @@ +/* GStreamer + * Copyright (C) 2011 Stefan Kost + * + * gstelementfactory.c: Unit test for GstElementFactory + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "../../gst/gst_private.h" + +#include + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw, " "channels = (int) [ 1, 6 ]") + ); +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw, " "channels = (int) [ 1, 6 ]") + ); + +static void +setup_pad_template (GstElementFactory * factory, GstStaticPadTemplate * tmpl) +{ + GstStaticPadTemplate *template; + + template = g_slice_dup (GstStaticPadTemplate, tmpl); + factory->staticpadtemplates = g_list_append (factory->staticpadtemplates, + template); + factory->numpadtemplates++; +} + +static GstElementFactory * +setup_factory (void) +{ + GstPluginFeature *feature; + GstElementFactory *factory; + + feature = g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL); + gst_plugin_feature_set_name (feature, "test"); + + factory = GST_ELEMENT_FACTORY_CAST (feature); +#if 0 + gst_element_class_set_metadata (factory, "test", "test", "test", "test"); +#endif + + setup_pad_template (factory, &sink_template); + setup_pad_template (factory, &src_template); + + return factory; +} + +/* create a basic factory */ +GST_START_TEST (test_create) +{ + GstElementFactory *factory; + + factory = setup_factory (); + fail_if (factory == NULL); + + g_object_unref (factory); +} + +GST_END_TEST; + +/* test if the factory can accept some caps */ +GST_START_TEST (test_can_sink_any_caps) +{ + GstElementFactory *factory; + GstCaps *caps; + gboolean res; + + factory = setup_factory (); + fail_if (factory == NULL); + + caps = gst_caps_new_empty_simple ("audio/x-raw"); + fail_if (caps == NULL); + res = gst_element_factory_can_sink_any_caps (factory, caps); + fail_if (!res); + gst_caps_unref (caps); + + g_object_unref (factory); +} + +GST_END_TEST; + +/* test if the factory is compatible with some caps */ +GST_START_TEST (test_can_sink_all_caps) +{ + GstElementFactory *factory; + GstCaps *caps; + gboolean res; + + factory = setup_factory (); + fail_if (factory == NULL); + + caps = gst_caps_new_empty_simple ("audio/x-raw"); + fail_if (caps == NULL); + res = gst_element_factory_can_sink_all_caps (factory, caps); + fail_if (res); + gst_caps_unref (caps); + + g_object_unref (factory); +} + +GST_END_TEST; + +/* check if the elementfactory of a class is filled (see #131079) */ +GST_START_TEST (test_class) +{ + GstElementClass *klass; + GstElementFactory *factory, *tmp; + GType type; + + GST_DEBUG ("finding factory for queue"); + factory = gst_element_factory_find ("queue"); + fail_if (factory == NULL); + + /* it may already be loaded if check is being run with CK_FORK=no */ + if (!GST_PLUGIN_FEATURE (factory)->loaded) { + GST_DEBUG ("getting the type"); + /* feature is not loaded, should return 0 as the type */ + type = gst_element_factory_get_element_type (factory); + fail_if (type != 0); + } + + GST_DEBUG ("now loading the plugin"); + tmp = + GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + fail_if (tmp == NULL); + + gst_object_unref (factory); + factory = tmp; + + /* feature is now loaded */ + type = gst_element_factory_get_element_type (factory); + fail_if (type == 0); + + klass = g_type_class_ref (factory->type); + fail_if (klass == NULL); + + GST_DEBUG ("checking the element factory class field"); + /* and elementfactory is filled in */ + fail_if (klass->elementfactory == NULL); + fail_if (klass->elementfactory != factory); + + gst_object_unref (factory); +} + +GST_END_TEST; + + +static Suite * +gst_element_factory_suite (void) +{ + Suite *s = suite_create ("GstElementFactory"); + TCase *tc_chain = tcase_create ("element-factory tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_class); + tcase_add_test (tc_chain, test_create); + tcase_add_test (tc_chain, test_can_sink_any_caps); + tcase_add_test (tc_chain, test_can_sink_all_caps); + + return s; +} + +GST_CHECK_MAIN (gst_element_factory); diff --git a/tests/check/gst/gstevent.c b/tests/check/gst/gstevent.c new file mode 100644 index 0000000..d124c91 --- /dev/null +++ b/tests/check/gst/gstevent.c @@ -0,0 +1,715 @@ +/* GStreamer + * Copyright (C) 2005 Jan Schmidt + * + * gstevent.c: Unit test for event 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_START_TEST (create_events) +{ + GstEvent *event, *event2; + GstStructure *structure; + + /* FLUSH_START */ + { + event = gst_event_new_flush_start (); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_if (GST_EVENT_IS_SERIALIZED (event)); + gst_event_unref (event); + } + /* FLUSH_STOP */ + { + gboolean reset_time; + + event = gst_event_new_flush_stop (TRUE); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + + gst_event_parse_flush_stop (event, &reset_time); + fail_unless (reset_time == TRUE); + gst_event_unref (event); + } + + /* SELECT_STREAMS */ + { + GList *streams = NULL; + GList *res = NULL; + GList *tmp; + streams = g_list_append (streams, (gpointer) "stream1"); + streams = g_list_append (streams, (gpointer) "stream2"); + event = gst_event_new_select_streams (streams); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SELECT_STREAMS); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + + gst_event_parse_select_streams (event, &res); + fail_if (res == NULL); + fail_unless_equals_int (g_list_length (res), 2); + tmp = res; + fail_unless_equals_string (tmp->data, "stream1"); + tmp = tmp->next; + fail_unless_equals_string (tmp->data, "stream2"); + + gst_event_unref (event); + + g_list_free (streams); + g_list_free_full (res, g_free); + } + + /* STREAM_GROUP_DONE */ + { + guint group_id = 0; + + event = gst_event_new_stream_group_done (0x42); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + gst_event_parse_stream_group_done (event, &group_id); + fail_unless (group_id == 0x42); + gst_event_unref (event); + } + + /* EOS */ + { + event = gst_event_new_eos (); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + gst_event_unref (event); + } + /* GAP */ + { + GstClockTime ts = 0, dur = 0; + + ASSERT_CRITICAL (gst_event_new_gap (GST_CLOCK_TIME_NONE, GST_SECOND)); + + event = gst_event_new_gap (90 * GST_SECOND, GST_SECOND); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_GAP); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + gst_event_parse_gap (event, &ts, NULL); + fail_unless_equals_int64 (ts, 90 * GST_SECOND); + gst_event_parse_gap (event, &ts, &dur); + fail_unless_equals_int64 (dur, GST_SECOND); + gst_event_unref (event); + } + /* SEGMENT */ + { + GstSegment segment, parsed; + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.rate = 0.5; + segment.applied_rate = 1.0; + segment.start = 1; + segment.stop = G_MAXINT64; + segment.time = 0xdeadbeef; + + event = gst_event_new_segment (&segment); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + + gst_event_copy_segment (event, &parsed); + fail_unless (parsed.rate == 0.5); + fail_unless (parsed.applied_rate == 1.0); + fail_unless (parsed.format == GST_FORMAT_TIME); + fail_unless (parsed.start == 1); + fail_unless (parsed.stop == G_MAXINT64); + fail_unless (parsed.time == 0xdeadbeef); + + gst_event_unref (event); + } + + /* TAGS */ + { + GstTagList *taglist = gst_tag_list_new_empty (); + GstTagList *tl2 = NULL; + + event = gst_event_new_tag (taglist); + fail_if (taglist == NULL); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + + gst_event_parse_tag (event, &tl2); + fail_unless (taglist == tl2); + gst_event_unref (event); + } + + /* QOS */ + { + GstQOSType t1 = GST_QOS_TYPE_THROTTLE, t2; + gdouble p1 = 1.0, p2; + GstClockTimeDiff ctd1 = G_GINT64_CONSTANT (10), ctd2; + GstClockTime ct1 = G_GUINT64_CONSTANT (20), ct2; + + event = gst_event_new_qos (t1, p1, ctd1, ct1); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_QOS); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_if (GST_EVENT_IS_DOWNSTREAM (event)); + fail_if (GST_EVENT_IS_SERIALIZED (event)); + + gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2); + fail_unless (p1 == p2); + fail_unless (ctd1 == ctd2); + fail_unless (ct1 == ct2); + gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2); + fail_unless (t2 == GST_QOS_TYPE_THROTTLE); + fail_unless (p1 == p2); + fail_unless (ctd1 == ctd2); + fail_unless (ct1 == ct2); + gst_event_unref (event); + + ctd1 = G_GINT64_CONSTANT (-10); + event = gst_event_new_qos (t1, p1, ctd1, ct1); + gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2); + fail_unless (t2 == GST_QOS_TYPE_THROTTLE); + gst_event_unref (event); + + event = gst_event_new_qos (t1, p1, ctd1, ct1); + gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2); + fail_unless (t2 == GST_QOS_TYPE_THROTTLE); + fail_unless (p1 == p2); + fail_unless (ctd1 == ctd2); + fail_unless (ct1 == ct2); + gst_event_unref (event); + } + + /* SEEK */ + { + gdouble rate; + GstFormat format; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + + event = gst_event_new_seek (0.5, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, + GST_SEEK_TYPE_SET, 1, GST_SEEK_TYPE_NONE, 0xdeadbeef); + + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEEK); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_if (GST_EVENT_IS_DOWNSTREAM (event)); + fail_if (GST_EVENT_IS_SERIALIZED (event)); + + gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, + &stop_type, &stop); + fail_unless (rate == 0.5); + fail_unless (format == GST_FORMAT_BYTES); + fail_unless (flags == (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE)); + fail_unless (start_type == GST_SEEK_TYPE_SET); + fail_unless (start == 1); + fail_unless (stop_type == GST_SEEK_TYPE_NONE); + fail_unless (stop == 0xdeadbeef); + + gst_event_unref (event); + } + + /* STREAM_START */ + { + GstStreamFlags flags = ~GST_STREAM_FLAG_NONE; + + event = gst_event_new_stream_start ("7f4b2f0/audio_02"); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + fail_if (GST_EVENT_IS_UPSTREAM (event)); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + gst_event_parse_stream_flags (event, &flags); + fail_unless_equals_int (flags, GST_STREAM_FLAG_NONE); + gst_event_set_stream_flags (event, GST_STREAM_FLAG_SPARSE); + gst_event_parse_stream_flags (event, &flags); + fail_unless_equals_int (flags, GST_STREAM_FLAG_SPARSE); + gst_event_ref (event); + ASSERT_CRITICAL (gst_event_set_stream_flags (event, GST_STREAM_FLAG_NONE)); + gst_event_unref (event); + gst_event_unref (event); + } + + /* STREAM_COLLECTION */ + { + GstStreamCollection *collection, *res = NULL; + GstStream *stream1, *stream2; + GstCaps *caps1, *caps2; + + /* Create a collection of two streams */ + caps1 = gst_caps_from_string ("some/caps"); + caps2 = gst_caps_from_string ("some/other-string"); + + stream1 = gst_stream_new ("stream-1", caps1, GST_STREAM_TYPE_AUDIO, 0); + stream2 = gst_stream_new ("stream-2", caps2, GST_STREAM_TYPE_VIDEO, 0); + + collection = gst_stream_collection_new ("something"); + fail_unless (gst_stream_collection_add_stream (collection, stream1)); + fail_unless (gst_stream_collection_add_stream (collection, stream2)); + + event = gst_event_new_stream_collection (collection); + fail_unless (event != NULL); + + gst_event_parse_stream_collection (event, &res); + fail_unless (res != NULL); + fail_unless (res == collection); + + gst_event_unref (event); + gst_object_unref (res); + gst_object_unref (collection); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + } + + /* NAVIGATION */ + { + structure = gst_structure_new ("application/x-gst-navigation", "event", + G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, "mon", NULL); + fail_if (structure == NULL); + event = gst_event_new_navigation (structure); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_if (GST_EVENT_IS_DOWNSTREAM (event)); + fail_if (GST_EVENT_IS_SERIALIZED (event)); + + fail_unless (gst_event_get_structure (event) == structure); + gst_event_unref (event); + } + + /* Protection */ + { + GstBuffer *data; + GstMemory *mem; + const gchar *parsed_origin; + const gchar *parsed_id; + GstBuffer *parsed_data; + const gchar clearkey_sys_id[] = "78f32170-d883-11e0-9572-0800200c9a66"; + gsize offset; + + data = gst_buffer_new (); + mem = gst_allocator_alloc (NULL, 40, NULL); + gst_buffer_insert_memory (data, -1, mem); + for (offset = 0; offset < 40; offset += 4) { + gst_buffer_fill (data, offset, "pssi", 4); + } + ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 1); + event = gst_event_new_protection (clearkey_sys_id, data, "test"); + fail_if (event == NULL); + ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 2); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_PROTECTION); + fail_unless (GST_EVENT_IS_DOWNSTREAM (event)); + fail_unless (GST_EVENT_IS_SERIALIZED (event)); + gst_event_parse_protection (event, &parsed_id, &parsed_data, + &parsed_origin); + fail_if (parsed_id == NULL); + fail_unless (g_strcmp0 (clearkey_sys_id, parsed_id) == 0); + fail_if (parsed_data == NULL); + fail_if (parsed_data != data); + ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 2); + fail_if (parsed_origin == NULL); + fail_unless (g_strcmp0 ("test", parsed_origin) == 0); + gst_event_unref (event); + ASSERT_MINI_OBJECT_REFCOUNT (data, "data", 1); + gst_buffer_unref (data); + } + + /* Custom event types */ + { + structure = gst_structure_new_empty ("application/x-custom"); + fail_if (structure == NULL); + event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure); + fail_if (event == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM); + fail_unless (GST_EVENT_IS_UPSTREAM (event)); + fail_if (GST_EVENT_IS_DOWNSTREAM (event)); + fail_if (GST_EVENT_IS_SERIALIZED (event)); + fail_unless (gst_event_get_structure (event) == structure); + fail_unless (gst_event_has_name (event, "application/x-custom")); + gst_event_unref (event); + + /* Decided not to test the other custom enum types, as they + * only differ by the value of the enum passed to gst_event_new_custom + */ + } + + /* Event copying */ + { + structure = gst_structure_new_empty ("application/x-custom"); + fail_if (structure == NULL); + event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure); + + fail_if (event == NULL); + event2 = gst_event_copy (event); + fail_if (event2 == NULL); + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (event2)); + fail_unless (gst_event_has_name (event, "application/x-custom")); + + /* The structure should have been duplicated */ + fail_if (gst_event_get_structure (event) == + gst_event_get_structure (event2)); + + gst_event_unref (event); + gst_event_unref (event2); + } + + /* Make events writable */ + { + structure = gst_structure_new_empty ("application/x-custom"); + fail_if (structure == NULL); + event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure); + /* ref the event so that it becomes non-writable */ + gst_event_ref (event); + gst_event_ref (event); + /* this should fail if the structure isn't writable */ + ASSERT_CRITICAL (gst_structure_remove_all_fields ((GstStructure *) + gst_event_get_structure (event))); + fail_unless (gst_event_has_name (event, "application/x-custom")); + + /* now make writable */ + event2 = + GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event))); + fail_unless (event != event2); + /* this fail if the structure isn't writable */ + gst_structure_remove_all_fields ((GstStructure *) + gst_event_get_structure (event2)); + fail_unless (gst_event_has_name (event2, "application/x-custom")); + + gst_event_unref (event); + gst_event_unref (event); + gst_event_unref (event2); + } +} + +GST_END_TEST; + +static GTimeVal sent_event_time; +static GstEvent *got_event_before_q, *got_event_after_q; +static GTimeVal got_event_time; + +static GstPadProbeReturn +event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); + gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data); + + GST_DEBUG ("event probe called %p", data); + + fail_unless (GST_IS_EVENT (data)); + + if (before_q) { + switch (GST_EVENT_TYPE (GST_EVENT (data))) { + case GST_EVENT_CUSTOM_UPSTREAM: + case GST_EVENT_CUSTOM_BOTH: + case GST_EVENT_CUSTOM_BOTH_OOB: + if (got_event_before_q != NULL) + break; + gst_event_ref ((GstEvent *) data); + g_get_current_time (&got_event_time); + got_event_before_q = GST_EVENT (data); + break; + default: + break; + } + } else { + switch (GST_EVENT_TYPE (GST_EVENT (data))) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + case GST_EVENT_CUSTOM_BOTH: + case GST_EVENT_CUSTOM_BOTH_OOB: + if (got_event_after_q != NULL) + break; + gst_event_ref ((GstEvent *) data); + g_get_current_time (&got_event_time); + got_event_after_q = GST_EVENT (data); + break; + default: + break; + } + } + + return GST_PAD_PROBE_OK; +} + + +typedef struct +{ + GMutex lock; + GCond cond; + gboolean signaled; +} SignalData; + +static void +signal_data_init (SignalData * data) +{ + GST_DEBUG ("init %p", data); + g_mutex_init (&data->lock); + g_cond_init (&data->cond); + data->signaled = FALSE; +} + +static void +signal_data_cleanup (SignalData * data) +{ + GST_DEBUG ("free %p", data); + g_mutex_clear (&data->lock); + g_cond_clear (&data->cond); +} + +static void +signal_data_signal (SignalData * data) +{ + g_mutex_lock (&data->lock); + data->signaled = TRUE; + g_cond_broadcast (&data->cond); + GST_DEBUG ("signaling %p", data); + g_mutex_unlock (&data->lock); +} + +static void +signal_data_wait (SignalData * data) +{ + g_mutex_lock (&data->lock); + GST_DEBUG ("signal wait %p", data); + while (!data->signaled) + g_cond_wait (&data->cond, &data->lock); + GST_DEBUG ("signal wait done %p", data); + g_mutex_unlock (&data->lock); +} + +static GstPadProbeReturn +signal_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + SignalData *data = (SignalData *) user_data; + + GST_DEBUG ("signal called %p", data); + signal_data_signal (data); + GST_DEBUG ("signal done %p", data); + + return GST_PAD_PROBE_OK; +} + +static void test_event + (GstBin * pipeline, GstEventType type, GstPad * pad, + gboolean expect_before_q, GstPad * fake_srcpad) +{ + GstEvent *event; + GstPad *peer; + gint i; + SignalData data; + gulong id; + + got_event_before_q = got_event_after_q = NULL; + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, + GST_CLOCK_TIME_NONE); + + GST_DEBUG ("test event called"); + + event = gst_event_new_custom (type, + gst_structure_new_empty ("application/x-custom")); + g_get_current_time (&sent_event_time); + got_event_time.tv_sec = 0; + got_event_time.tv_usec = 0; + + signal_data_init (&data); + + /* We block the pad so the stream lock is released and we can send the event */ + id = gst_pad_add_probe (fake_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + signal_blocked, &data, NULL); + fail_unless (id != 0); + + signal_data_wait (&data); + + /* We send on the peer pad, since the pad is blocked */ + GST_DEBUG ("sending event %p", event); + fail_unless ((peer = gst_pad_get_peer (pad)) != NULL); + gst_pad_send_event (peer, event); + gst_object_unref (peer); + + gst_pad_remove_probe (fake_srcpad, id); + + if (expect_before_q) { + /* Wait up to 5 seconds for the event to appear */ + for (i = 0; i < 500; i++) { + g_usleep (G_USEC_PER_SEC / 100); + if (got_event_before_q != NULL) + break; + } + fail_if (got_event_before_q == NULL, + "Expected event failed to appear upstream of the queue " + "within 5 seconds"); + fail_unless (GST_EVENT_TYPE (got_event_before_q) == type); + } else { + /* Wait up to 10 seconds for the event to appear */ + for (i = 0; i < 1000; i++) { + g_usleep (G_USEC_PER_SEC / 100); + if (got_event_after_q != NULL) + break; + } + fail_if (got_event_after_q == NULL, + "Expected event failed to appear after the queue within 10 seconds"); + fail_unless (GST_EVENT_TYPE (got_event_after_q) == type); + } + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, + GST_CLOCK_TIME_NONE); + + if (got_event_before_q) + gst_event_unref (got_event_before_q); + if (got_event_after_q) + gst_event_unref (got_event_after_q); + + got_event_before_q = got_event_after_q = NULL; + + signal_data_cleanup (&data); +} + +static gint64 +timediff (GTimeVal * end, GTimeVal * start) +{ + return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC + + (end->tv_usec - start->tv_usec); +} + +GST_START_TEST (send_custom_events) +{ + /* Run some tests on custom events. Checking for serialisation and whatnot. + * pipeline is fakesrc ! queue ! fakesink */ + GstBin *pipeline; + GstElement *fakesrc, *fakesink, *queue; + GstPad *srcpad, *sinkpad; + + fail_if ((pipeline = (GstBin *) gst_pipeline_new ("testpipe")) == NULL); + fail_if ((fakesrc = gst_element_factory_make ("fakesrc", NULL)) == NULL); + fail_if ((fakesink = gst_element_factory_make ("fakesink", NULL)) == NULL); + fail_if ((queue = gst_element_factory_make ("queue", NULL)) == NULL); + + gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL); + fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL)); + + g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL); + + /* Send 100 buffers per sec */ + g_object_set (G_OBJECT (fakesrc), "silent", TRUE, "datarate", 100, + "sizemax", 1, "sizetype", 2, NULL); + g_object_set (G_OBJECT (queue), "max-size-buffers", 0, "max-size-time", + (guint64) GST_SECOND, "max-size-bytes", 0, NULL); + g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL); + + /* add pad-probes to faksrc.src and fakesink.sink */ + fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL); + gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + event_probe, GINT_TO_POINTER (TRUE), NULL); + + fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL); + gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + event_probe, GINT_TO_POINTER (FALSE), NULL); + + /* Upstream events */ + test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) < G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_UP took too long to reach source: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) < G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_BOTH took too long to reach source: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) < G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + /* Out of band downstream events */ + test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) < G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) < G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + /* In-band downstream events are expected to take at least 1 second + * to traverse the queue */ + test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) >= G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad); + fail_unless (timediff (&got_event_time, + &sent_event_time) >= G_USEC_PER_SEC / 2, + "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %" + G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time)); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, + GST_CLOCK_TIME_NONE); + + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +gst_event_suite (void) +{ + Suite *s = suite_create ("GstEvent"); + TCase *tc_chain = tcase_create ("events"); + + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, create_events); + tcase_add_test (tc_chain, send_custom_events); + return s; +} + +GST_CHECK_MAIN (gst_event); diff --git a/tests/check/gst/gstghostpad.c b/tests/check/gst/gstghostpad.c new file mode 100644 index 0000000..087d034 --- /dev/null +++ b/tests/check/gst/gstghostpad.c @@ -0,0 +1,1441 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstghostpad.c: Unit test for GstGhostPad + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* test if removing a bin also cleans up the ghostpads + */ +GST_START_TEST (test_remove1) +{ + GstElement *b1, *b2, *src, *sink; + GstPad *srcpad, *sinkpad; + GstPadLinkReturn ret; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (b2, "bin", 1); + + fail_unless (gst_bin_add (GST_BIN (b2), sink)); + fail_unless (gst_bin_add (GST_BIN (b1), src)); + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (b2, "bin", 1); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (b2, "bin", 1); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad)); + gst_object_unref (sinkpad); + + srcpad = gst_element_get_static_pad (src, "src"); + /* get the ghostpad */ + sinkpad = gst_element_get_static_pad (b2, "sink"); + + ret = gst_pad_link (srcpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_OK); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + /* now remove the bin with the ghostpad, b2 is disposed now. */ + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + ASSERT_OBJECT_REFCOUNT (b2, "bin", 1); + gst_bin_remove (GST_BIN (b1), b2); + + srcpad = gst_element_get_static_pad (src, "src"); + /* pad cannot be linked now */ + fail_if (gst_pad_is_linked (srcpad)); + gst_object_unref (srcpad); + + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + gst_object_unref (b1); +} + +GST_END_TEST; + +/* test if removing a bin also cleans up the ghostpads + */ +GST_START_TEST (test_remove2) +{ + GstElement *b1, *b2, *src, *sink; + GstPad *srcpad, *sinkpad; + GstPadLinkReturn ret; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + fail_unless (gst_bin_add (GST_BIN (b2), sink)); + fail_unless (gst_bin_add (GST_BIN (b1), src)); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad)); + gst_object_unref (sinkpad); + + srcpad = gst_element_get_static_pad (src, "src"); + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2); /* since we got one */ + /* get the ghostpad */ + sinkpad = gst_element_get_static_pad (b2, "sink"); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); /* since we got one */ + + GST_DEBUG ("linking srcpad and sinkpad"); + ret = gst_pad_link (srcpad, sinkpad); + GST_DEBUG ("linked srcpad and sinkpad"); + fail_unless (ret == GST_PAD_LINK_OK); + /* Refcount should be unchanged, targets are now decuced using peer pad */ + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + /* now remove the sink from the bin */ + gst_bin_remove (GST_BIN (b2), sink); + + srcpad = gst_element_get_static_pad (src, "src"); + /* pad is still linked to ghostpad */ + fail_if (!gst_pad_is_linked (srcpad)); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2); + gst_object_unref (srcpad); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1); + + /* cleanup */ + /* now unlink the pads */ + gst_pad_unlink (srcpad, sinkpad); + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); /* we dropped our ref */ + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (b2, "bin", 1); + /* remove b2 from b1 */ + gst_bin_remove (GST_BIN (b1), b2); + + /* flush the message, dropping the b1 refcount to 1 */ + gst_element_set_state (b1, GST_STATE_READY); + gst_element_set_state (b1, GST_STATE_NULL); + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + gst_object_unref (b1); +} + +GST_END_TEST; + + + +/* test if a ghost pad without a target can be linked and + * unlinked. An untargeted ghostpad has a default ANY caps unless there + * is a padtemplate that says something else. + */ +GST_START_TEST (test_ghost_pads_notarget) +{ + GstElement *b1, *b2, *sink; + GstPad *srcpad, *sinkpad, *peer; + GstPadLinkReturn ret; + gboolean bret; + GstBus *bus; + GstCaps *caps; + + b1 = gst_element_factory_make ("pipeline", NULL); + + /* make sure all messages are discarded */ + bus = gst_pipeline_get_bus (GST_PIPELINE (b1)); + gst_bus_set_flushing (bus, TRUE); + gst_object_unref (bus); + + b2 = gst_element_factory_make ("bin", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + fail_unless (gst_bin_add (GST_BIN (b1), sink)); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + + srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless (sinkpad != NULL); + + ret = gst_pad_link (srcpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_OK); + + /* check if the peers are ok */ + peer = gst_pad_get_peer (srcpad); + fail_unless (peer == sinkpad); + gst_object_unref (peer); + + peer = gst_pad_get_peer (sinkpad); + fail_unless (peer == srcpad); + gst_object_unref (peer); + + /* check caps, untargetted pad should return ANY or the padtemplate caps + * when it was created from a template */ + caps = gst_pad_query_caps (srcpad, NULL); + fail_unless (gst_caps_is_any (caps)); + gst_caps_unref (caps); + + /* unlink */ + bret = gst_pad_unlink (srcpad, sinkpad); + fail_unless (bret == TRUE); + + /* cleanup */ + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + gst_object_unref (b1); +} + +GST_END_TEST; + +/* Test that removing the target of a ghostpad properly sets the target of the + * ghostpad to NULL */ +GST_START_TEST (test_remove_target) +{ + GstElement *b1, *b2, *src, *sink; + GstPad *sinkpad, *ghost, *target; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + fail_unless (gst_bin_add (GST_BIN (b2), sink)); + fail_unless (gst_bin_add (GST_BIN (b1), src)); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad)); + + ghost = gst_element_get_static_pad (b2, "sink"); + + target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost)); + fail_unless (target == sinkpad); + gst_object_unref (target); + gst_object_unref (sinkpad); + + gst_bin_remove (GST_BIN (b2), sink); + + target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost)); + fail_unless (target == NULL); + + gst_object_unref (b1); + gst_object_unref (ghost); +} + +GST_END_TEST; + + +/* test if linking fails over different bins using a pipeline + * like this: + * + * fakesrc num_buffers=10 ! ( fakesink ) + * + */ +GST_START_TEST (test_link) +{ + GstElement *b1, *b2, *src, *sink; + GstPad *srcpad, *sinkpad, *gpad, *ppad, *tmp; + GstPadLinkReturn ret; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + fail_unless (gst_bin_add (GST_BIN (b2), sink)); + fail_unless (gst_bin_add (GST_BIN (b1), src)); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless (sinkpad != NULL); + + /* linking in different hierarchies should fail */ + ret = gst_pad_link (srcpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_WRONG_HIERARCHY); + + /* now setup a ghostpad */ + gpad = gst_ghost_pad_new ("sink", sinkpad); + + /* Check if the internal pads are set correctly */ + ppad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad))); + fail_unless (ppad == GST_PAD_PEER (sinkpad)); + tmp = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (ppad))); + fail_unless (tmp == gpad); + gst_object_unref (tmp); + gst_object_unref (ppad); + gst_object_unref (sinkpad); + /* need to ref as _add_pad takes ownership */ + gst_object_ref (gpad); + gst_element_add_pad (b2, gpad); + + /* our new sinkpad */ + sinkpad = gpad; + + /* and linking should work now */ + ret = gst_pad_link (srcpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_OK); + + /* flush the message, dropping the b1 refcount to 1 */ + gst_element_set_state (b1, GST_STATE_READY); + gst_element_set_state (b1, GST_STATE_NULL); + ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + gst_object_unref (b1); +} + +GST_END_TEST; + +/* test if ghostpads are created automagically when using + * gst_element_link_pads. + * + * fakesrc num_buffers=10 ! ( identity ) ! fakesink + */ +GST_START_TEST (test_ghost_pads) +{ + GstElement *b1, *b2, *src, *i1, *sink; + GstPad *gsink, *gsrc, *gisrc, *gisink, *isink, *isrc, *fsrc, *fsink; + GstStateChangeReturn ret; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", (int) 10, NULL); + i1 = gst_element_factory_make ("identity", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + fail_unless (gst_bin_add (GST_BIN (b2), i1)); + fail_unless (gst_bin_add (GST_BIN (b1), src)); + fail_unless (gst_bin_add (GST_BIN (b1), b2)); + fail_unless (gst_bin_add (GST_BIN (b1), sink)); + fail_unless (gst_element_link_pads (src, NULL, i1, NULL)); + fail_unless (gst_element_link_pads (i1, NULL, sink, NULL)); + GST_OBJECT_LOCK (b2); + fail_unless (b2->numsinkpads == 1); + fail_unless (GST_IS_GHOST_PAD (b2->sinkpads->data)); + fail_unless (b2->numsrcpads == 1); + fail_unless (GST_IS_GHOST_PAD (b2->srcpads->data)); + GST_OBJECT_UNLOCK (b2); + + fsrc = gst_element_get_static_pad (src, "src"); + fail_unless (fsrc != NULL); + gsink = GST_PAD (gst_object_ref (b2->sinkpads->data)); + fail_unless (gsink != NULL); + gsrc = GST_PAD (gst_object_ref (b2->srcpads->data)); + fail_unless (gsrc != NULL); + fsink = gst_element_get_static_pad (sink, "sink"); + fail_unless (fsink != NULL); + + isink = gst_element_get_static_pad (i1, "sink"); + fail_unless (isink != NULL); + isrc = gst_element_get_static_pad (i1, "src"); + fail_unless (isrc != NULL); + gisrc = gst_pad_get_peer (isink); + fail_unless (gisrc != NULL); + gisink = gst_pad_get_peer (isrc); + fail_unless (gisink != NULL); + + /* all objects above have one refcount owned by us as well */ + + ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (gsrc, "gsrc", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 2); /* parent */ + + ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (isink, "isink", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* parent */ + ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2); /* parent */ + + ret = gst_element_set_state (b1, GST_STATE_PLAYING); + ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + ret = gst_element_set_state (b1, GST_STATE_NULL); + ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (b1); + /* unreffing the bin will unref all elements, which will unlink and unparent + * all pads */ + + /* wait for thread to settle down */ + while (GST_OBJECT_REFCOUNT_VALUE (fsrc) > 1) + THREAD_SWITCH (); + + ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1); + ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1); + ASSERT_OBJECT_REFCOUNT (gsrc, "gsink", 1); + ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1); + + ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* gsink */ + ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); /* gsink */ + ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */ + ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); /* gsrc */ + + gst_object_unref (gsink); + ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); + ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1); + ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1); + gst_object_unref (gisrc); + ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1); + + gst_object_unref (gsrc); + ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); + ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1); + ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1); + gst_object_unref (gisink); + ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1); + + gst_object_unref (fsrc); + gst_object_unref (isrc); + gst_object_unref (isink); + gst_object_unref (fsink); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_bin) +{ + GstBin *pipeline; + GstBin *srcbin; + GstBin *sinkbin; + GstElement *src; + GstElement *sink; + GstPad *srcpad, *srcghost, *target; + GstPad *sinkpad, *sinkghost; + + pipeline = GST_BIN (gst_pipeline_new ("pipe")); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + srcbin = GST_BIN (gst_bin_new ("srcbin")); + gst_bin_add (pipeline, GST_ELEMENT (srcbin)); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + sinkbin = GST_BIN (gst_bin_new ("sinkbin")); + gst_bin_add (pipeline, GST_ELEMENT (sinkbin)); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + src = gst_element_factory_make ("fakesrc", "src"); + gst_bin_add (srcbin, src); + srcpad = gst_element_get_static_pad (src, "src"); + srcghost = gst_ghost_pad_new ("src", srcpad); + gst_object_unref (srcpad); + gst_element_add_pad (GST_ELEMENT (srcbin), srcghost); + + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add (sinkbin, sink); + sinkpad = gst_element_get_static_pad (sink, "sink"); + sinkghost = gst_ghost_pad_new ("sink", sinkpad); + gst_object_unref (sinkpad); + gst_element_add_pad (GST_ELEMENT (sinkbin), sinkghost); + + gst_element_link (GST_ELEMENT (srcbin), GST_ELEMENT (sinkbin)); + + fail_unless (GST_PAD_PEER (srcghost) != NULL); + fail_unless (GST_PAD_PEER (sinkghost) != NULL); + target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcghost)); + fail_unless (GST_PAD_PEER (target) != NULL); + gst_object_unref (target); + target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkghost)); + fail_unless (GST_PAD_PEER (target) != NULL); + gst_object_unref (target); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +typedef struct +{ + GMutex mutex; + GCond cond; +} BlockData; + +static GstPadProbeReturn +block_callback (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + BlockData *block_data = (BlockData *) user_data; + + g_mutex_lock (&block_data->mutex); + GST_DEBUG ("blocked\n"); + g_cond_signal (&block_data->cond); + g_mutex_unlock (&block_data->mutex); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_ghost_pads_block) +{ + GstBin *pipeline; + GstBin *srcbin; + GstElement *src; + GstPad *srcpad; + GstPad *srcghost; + BlockData block_data; + + pipeline = GST_BIN (gst_pipeline_new ("pipeline")); + + srcbin = GST_BIN (gst_bin_new ("srcbin")); + gst_bin_add (pipeline, GST_ELEMENT (srcbin)); + + src = gst_element_factory_make ("fakesrc", "src"); + gst_bin_add (srcbin, src); + srcpad = gst_element_get_static_pad (src, "src"); + srcghost = gst_ghost_pad_new ("src", srcpad); + gst_element_add_pad (GST_ELEMENT (srcbin), srcghost); + gst_object_unref (srcpad); + + g_mutex_init (&block_data.mutex); + g_cond_init (&block_data.cond); + + g_mutex_lock (&block_data.mutex); + gst_pad_add_probe (srcghost, GST_PAD_PROBE_TYPE_BLOCK, block_callback, + &block_data, NULL); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + /* and wait now */ + g_cond_wait (&block_data.cond, &block_data.mutex); + g_mutex_unlock (&block_data.mutex); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + + g_mutex_clear (&block_data.mutex); + g_cond_clear (&block_data.cond); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_probes) +{ + GstBin *pipeline; + GstBin *srcbin; + GstElement *src; + GstPad *srcpad; + GstPad *srcghost; + BlockData block_data; + + pipeline = GST_BIN (gst_pipeline_new ("pipeline")); + + srcbin = GST_BIN (gst_bin_new ("srcbin")); + gst_bin_add (pipeline, GST_ELEMENT (srcbin)); + + src = gst_element_factory_make ("fakesrc", "src"); + gst_bin_add (srcbin, src); + srcpad = gst_element_get_static_pad (src, "src"); + srcghost = gst_ghost_pad_new ("src", srcpad); + gst_element_add_pad (GST_ELEMENT (srcbin), srcghost); + gst_object_unref (srcpad); + + g_mutex_init (&block_data.mutex); + g_cond_init (&block_data.cond); + + g_mutex_lock (&block_data.mutex); + gst_pad_add_probe (srcghost, GST_PAD_PROBE_TYPE_BLOCK, block_callback, + &block_data, NULL); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + /* and wait now */ + g_cond_wait (&block_data.cond, &block_data.mutex); + g_mutex_unlock (&block_data.mutex); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + + g_mutex_clear (&block_data.mutex); + g_cond_clear (&block_data.cond); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_new_from_template) +{ + GstPad *sinkpad, *ghostpad; + GstPadTemplate *padtempl, *ghosttempl; + GstCaps *padcaps, *ghostcaps, *newcaps; + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + ghostcaps = gst_caps_from_string ("some/caps;some/other-caps"); + fail_unless (ghostcaps != NULL); + + padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK, + GST_PAD_ALWAYS, padcaps); + fail_unless (padtempl != NULL); + ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK, + GST_PAD_ALWAYS, ghostcaps); + + sinkpad = gst_pad_new_from_template (padtempl, "sinkpad"); + fail_unless (sinkpad != NULL); + + ghostpad = gst_ghost_pad_new_from_template ("ghostpad", sinkpad, ghosttempl); + fail_unless (ghostpad != NULL); + + /* check template is properly set */ + fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl); + + /* check ghostpad caps are from the sinkpad */ + newcaps = gst_pad_query_caps (ghostpad, NULL); + fail_unless (newcaps != NULL); + fail_unless (gst_caps_is_equal (newcaps, padcaps)); + gst_caps_unref (newcaps); + gst_caps_unref (padcaps); + gst_caps_unref (ghostcaps); + + gst_object_unref (sinkpad); + gst_object_unref (ghostpad); + + gst_object_unref (padtempl); + gst_object_unref (ghosttempl); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_new_no_target_from_template) +{ + GstPad *sinkpad, *ghostpad; + GstPadTemplate *padtempl, *ghosttempl; + GstCaps *padcaps, *ghostcaps, *newcaps; + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + ghostcaps = gst_caps_from_string ("some/caps;some/other-caps"); + fail_unless (ghostcaps != NULL); + + padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK, + GST_PAD_ALWAYS, padcaps); + fail_unless (padtempl != NULL); + ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK, + GST_PAD_ALWAYS, ghostcaps); + + sinkpad = gst_pad_new_from_template (padtempl, "sinkpad"); + fail_unless (sinkpad != NULL); + + ghostpad = gst_ghost_pad_new_no_target_from_template ("ghostpad", ghosttempl); + fail_unless (ghostpad != NULL); + + /* check template is properly set */ + fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl); + + /* check ghostpad caps are from the ghostpad template */ + newcaps = gst_pad_query_caps (ghostpad, NULL); + fail_unless (newcaps != NULL); + fail_unless (gst_caps_is_equal (newcaps, ghostcaps)); + gst_caps_unref (newcaps); + + fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad)); + + /* check ghostpad caps are now from the target pad */ + newcaps = gst_pad_query_caps (ghostpad, NULL); + fail_unless (newcaps != NULL); + fail_unless (gst_caps_is_equal (newcaps, padcaps)); + gst_caps_unref (newcaps); + + gst_object_unref (sinkpad); + gst_object_unref (ghostpad); + + gst_object_unref (padtempl); + gst_object_unref (ghosttempl); + + gst_caps_unref (padcaps); + gst_caps_unref (ghostcaps); +} + +GST_END_TEST; + +static void +ghost_notify_caps (GObject * object, GParamSpec * pspec, gpointer * user_data) +{ + GST_DEBUG ("caps notify called"); + (*(gint *) user_data)++; +} + +GST_START_TEST (test_ghost_pads_forward_setcaps) +{ + GstCaps *templ_caps, *caps1, *caps2; + GstPadTemplate *src_template, *sink_template; + GstPad *src, *ghost, *sink; + gint notify_counter = 0; + + templ_caps = gst_caps_from_string ("meh; muh"); + src_template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, templ_caps); + gst_caps_unref (templ_caps); + + templ_caps = gst_caps_from_string ("muh; meh"); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, templ_caps); + gst_caps_unref (templ_caps); + + src = gst_pad_new_from_template (src_template, "src"); + sink = gst_pad_new_from_template (sink_template, "sink"); + + /* ghost source pad, setting caps on the source influences the caps of the + * ghostpad. */ + ghost = gst_ghost_pad_new ("ghostsrc", src); + g_signal_connect (ghost, "notify::caps", + G_CALLBACK (ghost_notify_caps), ¬ify_counter); + fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK); + + /* Activate pads for caps forwarding/setting to work */ + gst_pad_set_active (src, TRUE); + gst_pad_set_active (ghost, TRUE); + + caps1 = gst_caps_from_string ("meh"); + fail_unless (gst_pad_set_caps (src, caps1)); + caps2 = gst_pad_get_current_caps (ghost); + fail_unless (gst_caps_is_equal (caps1, caps2)); + fail_unless_equals_int (notify_counter, 1); + + gst_object_unref (ghost); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + /* source 2, setting the caps on the ghostpad does not influence the caps of + * the target */ + notify_counter = 0; + ghost = gst_ghost_pad_new ("ghostsrc", src); + g_signal_connect (ghost, "notify::caps", + G_CALLBACK (ghost_notify_caps), ¬ify_counter); + fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK); + + gst_pad_set_active (ghost, TRUE); + gst_pad_set_active (sink, TRUE); + + caps1 = gst_caps_from_string ("meh"); + fail_unless (gst_pad_set_caps (ghost, caps1)); +#if 0 + caps2 = gst_pad_get_current_caps (src); + fail_unless (caps2 == NULL); +#endif + fail_unless_equals_int (notify_counter, 1); + + gst_object_unref (ghost); + gst_caps_unref (caps1); + + + /* ghost sink pad. Setting caps on the ghostpad will also set those caps on + * the target pad. */ + notify_counter = 0; + ghost = gst_ghost_pad_new ("ghostsink", sink); + g_signal_connect (ghost, "notify::caps", + G_CALLBACK (ghost_notify_caps), ¬ify_counter); + fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK); + + gst_pad_set_active (src, TRUE); + gst_pad_set_active (ghost, TRUE); + + caps1 = gst_caps_from_string ("muh"); + fail_unless (gst_pad_set_caps (ghost, caps1)); + caps2 = gst_pad_get_current_caps (sink); + fail_unless (gst_caps_is_equal (caps1, caps2)); + fail_unless_equals_int (notify_counter, 1); + + gst_object_unref (ghost); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + /* clear caps on pads */ + gst_pad_set_active (src, FALSE); + gst_pad_set_active (src, TRUE); + gst_pad_set_active (sink, FALSE); + gst_pad_set_active (sink, TRUE); + + /* sink pad 2, setting caps just on the target pad should not influence the caps + * on the ghostpad. */ + notify_counter = 0; + ghost = gst_ghost_pad_new ("ghostsink", sink); + fail_unless (gst_pad_get_current_caps (ghost) == NULL); + g_signal_connect (ghost, "notify::caps", + G_CALLBACK (ghost_notify_caps), ¬ify_counter); + fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK); + + gst_pad_set_active (ghost, TRUE); + + caps1 = gst_caps_from_string ("muh"); + fail_unless (gst_pad_set_caps (sink, caps1)); + caps2 = gst_pad_get_current_caps (ghost); + fail_unless (caps2 == NULL); + fail_unless_equals_int (notify_counter, 0); + + gst_object_unref (ghost); + gst_caps_unref (caps1); + + gst_object_unref (src); + gst_object_unref (sink); + gst_object_unref (src_template); + gst_object_unref (sink_template); +} + +GST_END_TEST; + +static gint linked_count1; +static gint unlinked_count1; +static gint linked_count2; +static gint unlinked_count2; + +static GstPadLinkReturn +pad_linked1 (GstPad * pad, GstObject * parent, GstPad * peer) +{ + linked_count1++; + + return GST_PAD_LINK_OK; +} + +static void +pad_unlinked1 (GstPad * pad, GstObject * parent) +{ + unlinked_count1++; +} + +static GstPadLinkReturn +pad_linked2 (GstPad * pad, GstObject * parent, GstPad * peer) +{ + linked_count2++; + + return GST_PAD_LINK_OK; +} + +static void +pad_unlinked2 (GstPad * pad, GstObject * parent) +{ + unlinked_count2++; +} + +GST_START_TEST (test_ghost_pads_sink_link_unlink) +{ + GstCaps *padcaps; + GstPad *srcpad, *sinkpad, *ghostpad; + GstPadTemplate *srctempl, *sinktempl; + GstPadLinkReturn ret; + gboolean res; + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC, + GST_PAD_ALWAYS, padcaps); + gst_caps_unref (padcaps); + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK, + GST_PAD_ALWAYS, padcaps); + gst_caps_unref (padcaps); + + srcpad = gst_pad_new_from_template (srctempl, "src"); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new_from_template (sinktempl, "sink"); + fail_unless (sinkpad != NULL); + + /* set up link/unlink functions for the pad */ + linked_count1 = unlinked_count1 = 0; + gst_pad_set_link_function (sinkpad, pad_linked1); + gst_pad_set_unlink_function (sinkpad, pad_unlinked1); + linked_count2 = unlinked_count2 = 0; + gst_pad_set_link_function (srcpad, pad_linked2); + gst_pad_set_unlink_function (srcpad, pad_unlinked2); + + /* this should trigger a link from the internal pad to the sinkpad */ + ghostpad = gst_ghost_pad_new ("ghostpad", sinkpad); + fail_unless (ghostpad != NULL); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 0); + fail_unless (unlinked_count2 == 0); + + /* this should not trigger anything because we are not directly + * linking/unlinking the sink pad. */ + ret = gst_pad_link (srcpad, ghostpad); + fail_unless (ret == GST_PAD_LINK_OK); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 0); + + res = gst_pad_unlink (srcpad, ghostpad); + fail_unless (res == TRUE); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + /* this should trigger the unlink */ + res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL); + fail_unless (res == TRUE); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 1); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + gst_object_unref (ghostpad); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_object_unref (srctempl); + gst_object_unref (sinktempl); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_src_link_unlink) +{ + GstCaps *padcaps; + GstPad *srcpad, *sinkpad, *ghostpad, *dummy; + GstPadTemplate *srctempl, *sinktempl; + GstPadLinkReturn ret; + gboolean res; + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC, + GST_PAD_ALWAYS, padcaps); + gst_caps_unref (padcaps); + + padcaps = gst_caps_from_string ("some/caps"); + fail_unless (padcaps != NULL); + sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK, + GST_PAD_ALWAYS, padcaps); + gst_caps_unref (padcaps); + + srcpad = gst_pad_new_from_template (srctempl, "src"); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new_from_template (sinktempl, "sink"); + fail_unless (sinkpad != NULL); + + /* set up link/unlink functions for the pad */ + linked_count1 = unlinked_count1 = 0; + gst_pad_set_link_function (srcpad, pad_linked1); + gst_pad_set_unlink_function (srcpad, pad_unlinked1); + linked_count2 = unlinked_count2 = 0; + gst_pad_set_link_function (sinkpad, pad_linked2); + gst_pad_set_unlink_function (sinkpad, pad_unlinked2); + + /* this should trigger a link from the internal pad to the srcpad */ + ghostpad = gst_ghost_pad_new ("ghostpad", srcpad); + fail_unless (ghostpad != NULL); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 0); + fail_unless (unlinked_count2 == 0); + + /* this should fail with a critial */ + ASSERT_CRITICAL (dummy = gst_ghost_pad_new ("ghostpad", srcpad)); + fail_unless (dummy == NULL); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 0); + fail_unless (unlinked_count2 == 0); + + /* this should not trigger anything because we are not directly + * linking/unlinking the src pad. */ + ret = gst_pad_link (ghostpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_OK); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 0); + + /* this link should fail because we are already linked. Let's make sure the + * link functions are not called */ + ret = gst_pad_link (ghostpad, sinkpad); + fail_unless (ret == GST_PAD_LINK_WAS_LINKED); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 0); + + res = gst_pad_unlink (ghostpad, sinkpad); + fail_unless (res == TRUE); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + res = gst_pad_unlink (ghostpad, sinkpad); + fail_unless (res == FALSE); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 0); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + /* this should trigger the unlink function */ + res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL); + fail_unless (res == TRUE); + fail_unless (linked_count1 == 1); + fail_unless (unlinked_count1 == 1); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + /* and this the link function again */ + res = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), srcpad); + fail_unless (res == TRUE); + fail_unless (linked_count1 == 2); + fail_unless (unlinked_count1 == 1); + fail_unless (linked_count2 == 1); + fail_unless (unlinked_count2 == 1); + + gst_object_unref (ghostpad); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_object_unref (srctempl); + gst_object_unref (sinktempl); +} + +GST_END_TEST; + +GST_START_TEST (test_ghost_pads_change_when_linked) +{ + GstElement *b1, *b2, *src, *fmt, *sink1, *sink2; + GstPad *sinkpad, *ghostpad; + GstCaps *caps; + + b1 = gst_element_factory_make ("pipeline", NULL); + b2 = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + fmt = gst_element_factory_make ("capsfilter", NULL); + sink1 = gst_element_factory_make ("fakesink", NULL); + sink2 = gst_element_factory_make ("fakesink", NULL); + + gst_bin_add (GST_BIN (b2), sink1); + gst_bin_add (GST_BIN (b2), sink2); + gst_bin_add (GST_BIN (b1), src); + gst_bin_add (GST_BIN (b1), fmt); + gst_bin_add (GST_BIN (b1), b2); + + caps = gst_caps_from_string ("audio/x-raw, format=S16LE, channels=1"); + g_object_set (fmt, "caps", caps, NULL); + gst_caps_unref (caps); + + /* create the ghostpad as a sink-pad for bin 2 */ + ghostpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK); + gst_element_add_pad (b2, ghostpad); + + sinkpad = gst_element_get_static_pad (sink1, "sink"); + fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad)); + gst_object_unref (sinkpad); + + fail_unless (gst_element_link_many (src, fmt, b2, NULL)); + + /* set different target after ghostpad is linked */ + sinkpad = gst_element_get_static_pad (sink2, "sink"); + fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad)); + gst_object_unref (sinkpad); + + /* clean up */ + gst_object_unref (b1); +} + +GST_END_TEST; + +/* test that setting a ghostpad proxy pad as ghostpad target automatically set + * both ghostpad targets. + * + * fakesrc ! ( ) ! fakesink + */ + +GST_START_TEST (test_ghost_pads_internal_link) +{ + GstElement *pipeline, *src, *bin, *sink; + GstPad *sinkpad, *srcpad, *target; + GstProxyPad *proxypad; + + pipeline = gst_element_factory_make ("pipeline", NULL); + bin = gst_element_factory_make ("bin", NULL); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), bin); + gst_bin_add (GST_BIN (pipeline), sink); + + /* create the sink ghostpad */ + sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK); + proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (sinkpad)); + gst_element_add_pad (bin, sinkpad); + + /* create the src ghostpad and link it to sink proxypad */ + srcpad = gst_ghost_pad_new ("src", GST_PAD (proxypad)); + gst_object_unref (proxypad); + gst_element_add_pad (bin, srcpad); + + fail_unless (gst_element_link_many (src, bin, sink, NULL)); + + /* Check that both targets are set, and point to each other */ + target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkpad)); + fail_if (target == NULL); + proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (srcpad)); + fail_unless (target == GST_PAD (proxypad)); + gst_object_unref (target); + gst_object_unref (proxypad); + + target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad)); + fail_if (target == NULL); + proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (sinkpad)); + fail_unless (target == GST_PAD (proxypad)); + gst_object_unref (target); + gst_object_unref (proxypad); + + /* clean up */ + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* Test that remove a ghostpad that has something flowing through it does not + * crash the program + */ + +GstElement *bin; +GstPad *ghostsink; +GstPad *ghostsrc; + +static GstPadProbeReturn +remove_ghostpad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + gst_pad_set_active (ghostsrc, FALSE); + gst_pad_set_active (ghostsink, FALSE); + gst_element_remove_pad (bin, ghostsrc); + gst_element_remove_pad (bin, ghostsink); + + return GST_PAD_PROBE_DROP; +} + +GST_START_TEST (test_ghost_pads_remove_while_playing) +{ + GstPad *sinkpad; + GstPad *srcpad; + GstSegment segment; + + bin = gst_bin_new (NULL); + gst_element_set_state (bin, GST_STATE_PLAYING); + + ghostsrc = gst_ghost_pad_new_no_target ("ghostsrc", GST_PAD_SRC); + sinkpad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (ghostsrc))); + ghostsink = gst_ghost_pad_new ("ghostsink", sinkpad); + gst_object_unref (sinkpad); + gst_pad_set_active (ghostsrc, TRUE); + gst_pad_set_active (ghostsink, TRUE); + gst_element_add_pad (bin, ghostsrc); + gst_element_add_pad (bin, ghostsink); + + srcpad = gst_pad_new ("srcpad", GST_PAD_SRC); + gst_pad_set_active (srcpad, TRUE); + gst_pad_link (srcpad, ghostsink); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_segment (&segment)) == TRUE); + + gst_pad_add_probe (ghostsrc, GST_PAD_PROBE_TYPE_BUFFER, + remove_ghostpad_probe_cb, NULL, NULL); + + g_assert (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK); + + gst_pad_set_active (srcpad, FALSE); + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bin); + gst_object_unref (srcpad); +} + +GST_END_TEST; + + +GST_START_TEST (test_activate_src) +{ + GstHarness *h; + GstElement *b; + GstElement *src; + GstPad *srcpad; + + b = gst_bin_new (NULL); + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "sync", TRUE, NULL); + gst_bin_add (GST_BIN (b), src); + + srcpad = gst_element_get_static_pad (src, "src"); + gst_element_add_pad (b, gst_ghost_pad_new ("src", srcpad)); + gst_object_unref (srcpad); + + h = gst_harness_new_with_element (b, NULL, "src"); + gst_harness_play (h); + + gst_harness_crank_single_clock_wait (h); + gst_buffer_unref (gst_harness_pull (h)); + + gst_object_unref (b); + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_activate_sink_and_src) +{ + GstHarness *h; + GstElement *b; + GstElement *element; + GstPad *sinkpad; + GstPad *srcpad; + + b = gst_bin_new (NULL); + element = gst_element_factory_make ("identity", NULL); + gst_bin_add (GST_BIN (b), element); + + sinkpad = gst_element_get_static_pad (element, "sink"); + gst_element_add_pad (b, gst_ghost_pad_new ("sink", sinkpad)); + gst_object_unref (sinkpad); + + srcpad = gst_element_get_static_pad (element, "src"); + gst_element_add_pad (b, gst_ghost_pad_new ("src", srcpad)); + gst_object_unref (srcpad); + + h = gst_harness_new_with_element (b, "sink", "src"); + gst_harness_set_src_caps_str (h, "mycaps"); + + gst_harness_push (h, gst_buffer_new ()); + gst_buffer_unref (gst_harness_pull (h)); + + gst_object_unref (b); + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_activate_src_pull_mode) +{ + GstElement *b; + GstElement *src; + GstPad *srcpad; + GstPad *internalpad; + GstPad *ghost; + + b = gst_bin_new (NULL); + src = gst_element_factory_make ("fakesrc", NULL); + gst_bin_add (GST_BIN (b), src); + + srcpad = gst_element_get_static_pad (src, "src"); + ghost = gst_ghost_pad_new ("src", srcpad); + gst_element_add_pad (b, ghost); + + internalpad = (GstPad *) gst_proxy_pad_get_internal ((GstProxyPad *) ghost); + + fail_if (GST_PAD_IS_ACTIVE (ghost)); + fail_if (GST_PAD_IS_ACTIVE (internalpad)); + fail_if (GST_PAD_IS_ACTIVE (srcpad)); + fail_unless (gst_pad_activate_mode (ghost, GST_PAD_MODE_PULL, TRUE)); + fail_unless (GST_PAD_IS_ACTIVE (ghost)); + fail_unless (GST_PAD_IS_ACTIVE (internalpad)); + fail_unless (GST_PAD_IS_ACTIVE (srcpad)); + + gst_object_unref (internalpad); + gst_object_unref (srcpad); + gst_object_unref (b); +} + +GST_END_TEST; + +GST_START_TEST (test_activate_sink_switch_mode) +{ + GstElement *pipeline; + GstElement *b, *src, *identity; + GstPad *srcpad, *sinkpad, *internalpad, *ghost; + + pipeline = gst_pipeline_new (NULL); + b = gst_bin_new (NULL); + gst_bin_add (GST_BIN (pipeline), b); + src = gst_element_factory_make ("fakesrc", NULL); + gst_bin_add (GST_BIN (pipeline), src); + identity = gst_element_factory_make ("identity", NULL); + gst_bin_add (GST_BIN (b), identity); + + sinkpad = gst_element_get_static_pad (identity, "sink"); + ghost = gst_ghost_pad_new ("sink", sinkpad); + gst_element_add_pad (b, ghost); + srcpad = gst_element_get_static_pad (src, "src"); + gst_pad_link (srcpad, ghost); + + internalpad = (GstPad *) gst_proxy_pad_get_internal ((GstProxyPad *) ghost); + + /* We start with no active pads */ + fail_if (GST_PAD_IS_ACTIVE (ghost)); + fail_if (GST_PAD_IS_ACTIVE (internalpad)); + fail_if (GST_PAD_IS_ACTIVE (sinkpad)); + fail_if (GST_PAD_IS_ACTIVE (srcpad)); + + GST_DEBUG ("Activating pads in push mode"); + /* Let's first try to activate everything in push-mode, for this we need + * to go on every exposed pad */ + fail_unless (gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE)); + fail_unless (gst_pad_activate_mode (ghost, GST_PAD_MODE_PUSH, TRUE)); + fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE)); + + GST_DEBUG ("Checking pads are all activated properly"); + /* Let's check all pads are now active, including internal ones */ + fail_unless (GST_PAD_MODE (ghost) == GST_PAD_MODE_PUSH); + fail_unless (GST_PAD_MODE (internalpad) == GST_PAD_MODE_PUSH); + fail_unless (GST_PAD_MODE (srcpad) == GST_PAD_MODE_PUSH); + fail_unless (GST_PAD_MODE (sinkpad) == GST_PAD_MODE_PUSH); + + /* Now simulate a scheduling reconfiguration (PUSH=>PULL) */ + fail_unless (gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE)); + + /* All pads should have switched modes */ + fail_unless (GST_PAD_MODE (ghost) == GST_PAD_MODE_PULL); + fail_unless (GST_PAD_MODE (srcpad) == GST_PAD_MODE_PULL); + fail_unless (GST_PAD_MODE (sinkpad) == GST_PAD_MODE_PULL); + fail_unless (GST_PAD_MODE (internalpad) == GST_PAD_MODE_PULL); + + gst_object_unref (internalpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static gboolean thread_running; + +static gpointer +send_query_to_pad_func (GstPad * pad) +{ + GstQuery *query = gst_query_new_latency (); + + while (thread_running) { + gst_pad_peer_query (pad, query); + g_thread_yield (); + } + + gst_query_unref (query); + return NULL; +} + +GST_START_TEST (test_stress_upstream_queries_while_tearing_down) +{ + GThread *query_thread; + gint i; + GstPad *pad = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_active (pad, TRUE); + + thread_running = TRUE; + query_thread = g_thread_new ("queries", + (GThreadFunc) send_query_to_pad_func, pad); + + for (i = 0; i < 1000; i++) { + GstPad *ghostpad = gst_ghost_pad_new ("ghost-sink", pad); + gst_pad_set_active (ghostpad, TRUE); + + g_thread_yield (); + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL); + gst_pad_set_active (pad, FALSE); + gst_object_unref (ghostpad); + } + + thread_running = FALSE; + g_thread_join (query_thread); + + gst_object_unref (pad); +} + +GST_END_TEST; + +GST_START_TEST (test_deactivate_already_deactive_with_no_parent) +{ + /* This simulates the behavior where a ghostpad is released while + * deactivating (for instance because of a state change). + * gst_pad_activate_mode() may be be called from + * gst_ghost_pad_internal_activate_push_default() on a pad that is already + * deactivate and unparented. The call chain is really like somethink like + * this: + * gst_pad_activate_mode(ghostpad) + * -> ... + * -> gst_pad_activate_mode(proxypad) + * -> ... + * -> gst_pad_activate_mode(ghostpad) + */ + GstElement *bin = gst_bin_new ("testbin"); + GstPad *pad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC); + gst_object_ref (pad); + + /* We need to add/remove pad because that will update the pad's flags */ + fail_unless (gst_element_add_pad (bin, pad)); + fail_unless (gst_element_remove_pad (bin, pad)); + + /* Setting a pad that's already deactive to deactive should not fail. */ + fail_if (gst_pad_is_active (pad)); + fail_unless (gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, FALSE)); + + gst_object_unref (bin); + gst_object_unref (pad); +} + +GST_END_TEST; + +static Suite * +gst_ghost_pad_suite (void) +{ + Suite *s = suite_create ("GstGhostPad"); + + TCase *tc_chain = tcase_create ("ghost pad tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_remove1); + tcase_add_test (tc_chain, test_remove2); + tcase_add_test (tc_chain, test_remove_target); + tcase_add_test (tc_chain, test_link); + tcase_add_test (tc_chain, test_ghost_pads); + tcase_add_test (tc_chain, test_ghost_pads_bin); + tcase_add_test (tc_chain, test_ghost_pads_notarget); + tcase_add_test (tc_chain, test_ghost_pads_block); + tcase_add_test (tc_chain, test_ghost_pads_probes); + tcase_add_test (tc_chain, test_ghost_pads_new_from_template); + tcase_add_test (tc_chain, test_ghost_pads_new_no_target_from_template); + tcase_add_test (tc_chain, test_ghost_pads_forward_setcaps); + tcase_add_test (tc_chain, test_ghost_pads_sink_link_unlink); + tcase_add_test (tc_chain, test_ghost_pads_src_link_unlink); + tcase_add_test (tc_chain, test_ghost_pads_change_when_linked); + tcase_add_test (tc_chain, test_ghost_pads_internal_link); + tcase_add_test (tc_chain, test_ghost_pads_remove_while_playing); + + tcase_add_test (tc_chain, test_activate_src); + tcase_add_test (tc_chain, test_activate_sink_and_src); + tcase_add_test (tc_chain, test_activate_src_pull_mode); + tcase_add_test (tc_chain, test_activate_sink_switch_mode); + tcase_add_test (tc_chain, test_deactivate_already_deactive_with_no_parent); + tcase_add_test (tc_chain, test_stress_upstream_queries_while_tearing_down); + + return s; +} + +GST_CHECK_MAIN (gst_ghost_pad); diff --git a/tests/check/gst/gstinfo.c b/tests/check/gst/gstinfo.c new file mode 100644 index 0000000..78f8b5a --- /dev/null +++ b/tests/check/gst/gstinfo.c @@ -0,0 +1,516 @@ +/* GStreamer + * + * Unit tests for GstInfo + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#ifndef GST_DISABLE_GST_DEBUG + +static GList *messages; /* NULL */ +static gboolean save_messages; /* FALSE */ + +static void +printf_extension_log_func (GstDebugCategory * category, + GstDebugLevel level, const gchar * file, const gchar * function, + gint line, GObject * object, GstDebugMessage * message, gpointer unused) +{ + const gchar *dbg_msg; + + dbg_msg = gst_debug_message_get (message); + fail_unless (dbg_msg != NULL); + + if (save_messages && g_str_equal (category->name, "check")) + messages = g_list_append (messages, g_strdup (dbg_msg)); + + /* g_print ("%s\n", dbg_msg); */ + + /* quick hack to still get stuff to show if GST_DEBUG is set */ + if (g_getenv ("GST_DEBUG")) { + gst_debug_log_default (category, level, file, function, line, object, + message, unused); + } +} + +/* check our GST_PTR_FORMAT printf extension stuff */ +GST_START_TEST (info_ptr_format_printf_extension) +{ + /* set up our own log function to make sure the code in gstinfo is actually + * executed without GST_DEBUG being set or it being output to stdout */ + gst_debug_remove_log_function (gst_debug_log_default); + gst_debug_add_log_function (printf_extension_log_func, NULL, NULL); + + gst_debug_set_default_threshold (GST_LEVEL_LOG); + + /* NULL object */ + GST_LOG ("NULL: %" GST_PTR_FORMAT, (gpointer) NULL); + + /* structure */ + { + GstStructure *s; + + s = gst_structure_new ("foo/bar", "number", G_TYPE_INT, 1, + "string", G_TYPE_STRING, "s", "float-number", G_TYPE_DOUBLE, + (gdouble) 424242.42, NULL); + + GST_LOG ("STRUCTURE: %" GST_PTR_FORMAT, s); + gst_structure_free (s); + } + + /* message */ + { + GstMessage *msg; + + msg = gst_message_new_element (NULL, + gst_structure_new ("redirect", "new-location", G_TYPE_STRING, + "http://foobar.com/r0x0r.ogg", "minimum-bitrate", G_TYPE_INT, + 56000, NULL)); + + GST_LOG ("MESSAGE: %" GST_PTR_FORMAT, msg); + gst_message_unref (msg); + } + + /* buffer and buffer list */ + { + GstBufferList *list; + GstBuffer *buf; + + buf = gst_buffer_new_allocate (NULL, 42, NULL); + GST_BUFFER_PTS (buf) = 5 * GST_SECOND; + GST_BUFFER_DURATION (buf) = GST_SECOND; + GST_LOG ("BUFFER: %" GST_PTR_FORMAT, buf); + + list = gst_buffer_list_new (); + gst_buffer_list_add (list, buf); + buf = gst_buffer_new_allocate (NULL, 58, NULL); + gst_buffer_list_add (list, buf); + GST_LOG ("BUFFERLIST: %" GST_PTR_FORMAT, list); + gst_buffer_list_unref (list); + } + +#if 0 + /* TODO: GObject */ + { + GST_LOG ("GOBJECT: %" GST_PTR_FORMAT, obj); + } + + /* TODO: GstObject */ + { + GST_LOG ("GSTOBJECT: %" GST_PTR_FORMAT, obj); + } + + /* TODO: GstPad */ + { + GST_LOG ("PAD: %" GST_PTR_FORMAT, pad); + } + + /* TODO: GstCaps */ + { + GST_LOG ("PAD: %" GST_PTR_FORMAT, pad); + } +#endif + + /* clean up */ + gst_debug_set_default_threshold (GST_LEVEL_NONE); + gst_debug_add_log_function (gst_debug_log_default, NULL, NULL); + gst_debug_remove_log_function (printf_extension_log_func); +} + +GST_END_TEST; + +/* check our GST_SEGMENT_FORMAT printf extension stuff */ +GST_START_TEST (info_segment_format_printf_extension) +{ + /* set up our own log function to make sure the code in gstinfo is actually + * executed without GST_DEBUG being set or it being output to stdout */ + gst_debug_remove_log_function (gst_debug_log_default); + gst_debug_add_log_function (printf_extension_log_func, NULL, NULL); + + gst_debug_set_default_threshold (GST_LEVEL_LOG); + + /* TIME segment */ + { + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.rate = 1.0; + segment.applied_rate = 2.0; + segment.start = 0; + segment.stop = 5 * 60 * GST_SECOND; + segment.time = 0; + + segment.position = 2 * GST_SECOND; + segment.duration = 90 * 60 * GST_SECOND; + + GST_LOG ("TIME: %" GST_SEGMENT_FORMAT, &segment); + } + + /* BYTE segment */ + { + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + segment.rate = 1.0; + segment.applied_rate = 1.0; + segment.start = 0; + segment.stop = 9999999; + segment.time = 0; + + GST_LOG ("BYTE: %" GST_SEGMENT_FORMAT, &segment); + } + + /* UNKNOWN format segment (format numbers are consecutive from 0) */ + { + GstSegment segment; + + gst_segment_init (&segment, 98765432); + + segment.rate = 1.0; + segment.applied_rate = 1.0; + segment.start = 0; + segment.stop = 987654321; + segment.time = 0; + + GST_LOG ("UNKNOWN: %" GST_SEGMENT_FORMAT, &segment); + } + + /* UNDEFINED format segment */ + { + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_UNDEFINED); + + GST_LOG ("UNDEFINED: %" GST_SEGMENT_FORMAT, &segment); + } + + /* NULL segment */ + GST_LOG ("NULL: %" GST_SEGMENT_FORMAT, (GstSegment *) NULL); + + /* clean up */ + gst_debug_set_default_threshold (GST_LEVEL_NONE); + gst_debug_add_log_function (gst_debug_log_default, NULL, NULL); + gst_debug_remove_log_function (printf_extension_log_func); +} + +GST_END_TEST; + +GST_START_TEST (info_log_handler) +{ + guint removed; + + removed = gst_debug_remove_log_function (gst_debug_log_default); + fail_unless (removed == 1); +} + +GST_END_TEST; + +GST_START_TEST (info_dump_mem) +{ + GstDebugCategory *cat = NULL; + GstElement *e; + + const guint8 data[] = { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, + 0x71, 0x74, 0x20, 0x20, 0x20, 0x05, 0x03, 0x00, 0x71, 0x74, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xef, 0xe1, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x6c, + 0x6d, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xd1, 0x00, 0x1d, + 0xbf, 0xd1, 0x00, 0x1e, 0x00, 0x00, 0x0b, 0xb5, 0x00, 0x04, 0x59, 0xc5, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, '%', 's', '%', 's' + }; + + e = gst_pipeline_new ("pipeline"); + GST_DEBUG_CATEGORY_INIT (cat, "dumpcat", 0, "data dump debug category"); + GST_MEMDUMP ("quicktime header", data, sizeof (data)); + GST_MEMDUMP (NULL, data, sizeof (data)); + GST_CAT_MEMDUMP (cat, "quicktime header", data, sizeof (data)); + GST_MEMDUMP_OBJECT (e, "object stuff", data, sizeof (data)); + GST_CAT_MEMDUMP_OBJECT (cat, e, "object/cat stuff", data, sizeof (data)); + gst_object_unref (e); +} + +GST_END_TEST; + +GST_START_TEST (info_fixme) +{ + GstDebugCategory *cat = NULL; + GstElement *e; + + e = gst_pipeline_new ("pipeline"); + GST_DEBUG_CATEGORY_INIT (cat, "fixcat", 0, "FIXME debug category"); + GST_FIXME ("fix %s thing", "this"); + GST_FIXME_OBJECT (e, "fix %s object", "this"); + GST_CAT_FIXME (cat, "fix some%s in this category", "thing"); + GST_CAT_FIXME_OBJECT (cat, e, "fix some%s in this cat and object", "thing"); + gst_object_unref (e); +} + +GST_END_TEST; + +/* need this indirection so the compiler doesn't check the printf format + * like it would if we used GST_INFO directly (it would complain) */ +static void +call_GST_INFO (const gchar * format, ...) +{ + va_list var_args; + + va_start (var_args, format); + gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_INFO, __FILE__, GST_FUNCTION, + __LINE__, NULL, format, var_args); + va_end (var_args); +} + +GST_START_TEST (info_old_printf_extensions) +{ + GstSegment segment; + GstCaps *caps; + gchar *str; + + /* set up our own log function to make sure the code in gstinfo is actually + * executed without GST_DEBUG being set or it being output to stdout */ + gst_debug_remove_log_function (gst_debug_log_default); + gst_debug_add_log_function (printf_extension_log_func, NULL, NULL); + + gst_debug_set_default_threshold (GST_LEVEL_LOG); + + save_messages = TRUE; + + fail_unless (messages == NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + caps = gst_caps_new_simple ("foo/bar", "width", G_TYPE_INT, 4096, + "framerate", GST_TYPE_FRACTION, 50, 1, "format", G_TYPE_STRING, "ARGB", + NULL); + call_GST_INFO ("Segment %Q, caps are %P", &segment, caps); + gst_caps_unref (caps); + + fail_unless_equals_int (g_list_length (messages), 1); + str = (gchar *) messages->data; + fail_unless (str != NULL); + + GST_INFO ("str = '%s'", str); + + fail_unless (strstr (str, "time") != NULL); + fail_unless (strstr (str, "start=0:00:00.000000000") != NULL); + fail_unless (strstr (str, "stop=99:99:99.999999999") != NULL); + fail_unless (strstr (str, "applied_rate=1.000000") != NULL); + + fail_unless (strstr (str, " caps are ") != NULL); + fail_unless (strstr (str, "foo/bar") != NULL); + fail_unless (strstr (str, "width=(int)4096") != NULL); + fail_unless (strstr (str, "framerate=(fraction)50/1") != NULL); + fail_unless (strstr (str, "ARGB") != NULL); + + /* clean up */ + gst_debug_set_default_threshold (GST_LEVEL_NONE); + gst_debug_add_log_function (gst_debug_log_default, NULL, NULL); + gst_debug_remove_log_function (printf_extension_log_func); + save_messages = FALSE; + g_list_free_full (messages, (GDestroyNotify) g_free); + messages = NULL; +} + +GST_END_TEST; + +GST_START_TEST (info_register_same_debug_category_twice) +{ + GstDebugCategory *cat1 = NULL, *cat2 = NULL; + + GST_DEBUG_CATEGORY_INIT (cat1, "dupli-cat", 0, "Going once"); + GST_DEBUG_CATEGORY_INIT (cat2, "dupli-cat", 0, "Going twice"); + + fail_unless_equals_pointer (cat1, cat2); + + fail_unless_equals_string (gst_debug_category_get_name (cat1), "dupli-cat"); + fail_unless_equals_string (gst_debug_category_get_description (cat1), + "Going once"); +} + +GST_END_TEST; + +GST_START_TEST (info_set_and_unset_single) +{ + GstDebugLevel orig = gst_debug_get_default_threshold (); + GstDebugLevel cat1, cat2; + GstDebugCategory *states; + + GST_DEBUG_CATEGORY_GET (states, "GST_STATES"); + fail_unless (states != NULL); + + gst_debug_set_default_threshold (GST_LEVEL_WARNING); + + gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG); + cat1 = gst_debug_category_get_threshold (states); + gst_debug_unset_threshold_for_name ("GST_STATES"); + cat2 = gst_debug_category_get_threshold (states); + + gst_debug_set_default_threshold (orig); + fail_unless (cat1 = GST_LEVEL_DEBUG); + fail_unless (cat2 = GST_LEVEL_WARNING); +} + +GST_END_TEST; + +GST_START_TEST (info_set_and_unset_multiple) +{ + GstDebugLevel orig = gst_debug_get_default_threshold (); + GstDebugLevel cat1, cat2, cat3; + GstDebugCategory *states; + GstDebugCategory *caps; + + GST_DEBUG_CATEGORY_GET (states, "GST_STATES"); + GST_DEBUG_CATEGORY_GET (caps, "GST_CAPS"); + fail_unless (states != NULL); + fail_unless (caps != NULL); + + gst_debug_set_default_threshold (GST_LEVEL_WARNING); + + gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG); + gst_debug_set_threshold_for_name ("GST_CAPS", GST_LEVEL_DEBUG); + cat1 = gst_debug_category_get_threshold (states); + gst_debug_unset_threshold_for_name ("GST_STATES"); + gst_debug_unset_threshold_for_name ("GST_CAPS"); + cat2 = gst_debug_category_get_threshold (states); + cat3 = gst_debug_category_get_threshold (caps); + + gst_debug_set_default_threshold (orig); + + fail_unless (cat1 = GST_LEVEL_DEBUG); + fail_unless (cat2 = GST_LEVEL_WARNING); + fail_unless (cat3 = GST_LEVEL_WARNING); +} + +GST_END_TEST; +#endif + +GST_START_TEST (info_fourcc) +{ + gchar *res; + const gchar *cmp; + + cmp = "abcd"; + res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x64636261)); + fail_unless_equals_string (res, cmp); + g_free (res); + + cmp = ".bcd"; + res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x646362a9)); + fail_unless_equals_string (res, cmp); + g_free (res); +} + +GST_END_TEST; + +/* Here we're testing adding debug categories after gst_init() and making + * sure that this doesn't incur exponential costs. Previously this would + * reparse the debug string and re-add the parsed category/levels to the + * list, thus doubling the list to pattern match a category against for + * every category added. And we would also re-evaluate all existing categories + * against that list. This test makes sure the overhead of registering debug + * categories late is very small. This test would time out before the fix. */ +GST_START_TEST (info_post_gst_init_category_registration) +{ + GstDebugCategory *cats[10000] = { NULL, }; + guint i; + + /* Note: before the fixes this wouldn't work to trigger the problem because + * only a pattern set via GST_DEBUG before gst_init would be picked up + * (another bug) */ + gst_debug_set_threshold_from_string ("*a*b:6,*b*0:6,*c:3,d*:2,xyz*:9,ax:1", + TRUE); + + fail_unless_equals_int (GST_LEVEL_DEFAULT, + gst_debug_get_default_threshold ()); + + for (i = 0; i < G_N_ELEMENTS (cats); ++i) { + gchar *name = g_strdup_printf ("%s-%x", (i % 2 == 0) ? "cat" : "dog", i); + GST_DEBUG_CATEGORY_INIT (cats[i], name, 0, "none"); + g_free (name); + } + + /* These checks will only work if no one else set anything externally */ + if (g_getenv ("GST_DEBUG") == NULL) { + /* none */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[0]), + GST_LEVEL_DEFAULT); + /* d*:2 */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[1]), + GST_LEVEL_WARNING); + /* none */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[2]), + GST_LEVEL_DEFAULT); + /* d*:2 */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[3]), + GST_LEVEL_WARNING); + /* *c:3 */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xc]), + GST_LEVEL_FIXME); + /* *c:3 */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[0x4c]), + GST_LEVEL_FIXME); + /* *a*b:6 and d*:2, but d*:2 takes priority here as cat name is "dog-a1b" + * and order matters: items listed later override earlier ones. */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xa1b]), + GST_LEVEL_WARNING); + /* *a*0:6 */ + fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xb10]), + GST_LEVEL_LOG); + } + + for (i = 0; i < G_N_ELEMENTS (cats); ++i) + gst_debug_category_free (cats[i]); +} + +GST_END_TEST; + +static Suite * +gst_info_suite (void) +{ + Suite *s = suite_create ("GstInfo"); + TCase *tc_chain = tcase_create ("info"); + + tcase_set_timeout (tc_chain, 30); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, info_fourcc); +#ifndef GST_DISABLE_GST_DEBUG + tcase_add_test (tc_chain, info_segment_format_printf_extension); + tcase_add_test (tc_chain, info_ptr_format_printf_extension); + tcase_add_test (tc_chain, info_log_handler); + tcase_add_test (tc_chain, info_dump_mem); + tcase_add_test (tc_chain, info_fixme); + tcase_add_test (tc_chain, info_old_printf_extensions); + tcase_add_test (tc_chain, info_register_same_debug_category_twice); + tcase_add_test (tc_chain, info_set_and_unset_single); + tcase_add_test (tc_chain, info_set_and_unset_multiple); + tcase_add_test (tc_chain, info_post_gst_init_category_registration); +#endif + + return s; +} + +GST_CHECK_MAIN (gst_info); diff --git a/tests/check/gst/gstiterator.c b/tests/check/gst/gstiterator.c new file mode 100644 index 0000000..9e989f8 --- /dev/null +++ b/tests/check/gst/gstiterator.c @@ -0,0 +1,447 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * gstiterator.c: Unit test for iterators + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +static GList * +make_list_of_ints (gint n) +{ + GList *ret = NULL; + gint i; + + for (i = 0; i < n; i++) + ret = g_list_prepend (ret, GINT_TO_POINTER (i)); + + return g_list_reverse (ret); +} + +#define NUM_ELEMENTS 10 + +GST_START_TEST (test_manual_iteration) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter; + GstIteratorResult res; + GValue item = { 0, }; + gint i = 0; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + + fail_unless (iter != NULL); + + while (1) { + res = gst_iterator_next (iter, &item); + if (i < NUM_ELEMENTS) { + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == i); + g_value_reset (&item); + i++; + continue; + } else { + fail_unless (res == GST_ITERATOR_DONE); + break; + } + } + /* clean up */ + g_value_unset (&item); + gst_iterator_free (iter); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +GST_START_TEST (test_resync) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter; + GstIteratorResult res; + GValue item = { 0, }; + gint i = 0; + gboolean hacked_list = FALSE; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + + fail_unless (iter != NULL); + + while (1) { + res = gst_iterator_next (iter, &item); + if (i < NUM_ELEMENTS / 2) { + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == i); + g_value_reset (&item); + i++; + continue; + } else if (!hacked_list) { + /* here's where we test resync */ + fail_unless (res == GST_ITERATOR_OK); + g_value_reset (&item); + l = g_list_prepend (l, GINT_TO_POINTER (-1)); + cookie++; + hacked_list = TRUE; + continue; + } else { + fail_unless (res == GST_ITERATOR_RESYNC); + gst_iterator_resync (iter); + res = gst_iterator_next (iter, &item); + fail_unless (res == GST_ITERATOR_OK); + fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == -1); + g_value_reset (&item); + break; + } + } + + /* clean up */ + g_value_unset (&item); + gst_iterator_free (iter); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +static gboolean +add_fold_func (const GValue * item, GValue * ret, gpointer user_data) +{ + g_value_set_int (ret, + g_value_get_int (ret) + GPOINTER_TO_INT (g_value_get_pointer (item))); + return TRUE; +} + +GST_START_TEST (test_fold) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter; + GstIteratorResult res; + gint i, expected; + GValue ret = { 0, }; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + fail_unless (iter != NULL); + + expected = 0; + for (i = 0; i < NUM_ELEMENTS; i++) + expected += i; + + g_value_init (&ret, G_TYPE_INT); + g_value_set_int (&ret, 0); + + res = gst_iterator_fold (iter, add_fold_func, &ret, NULL); + + fail_unless (res == GST_ITERATOR_DONE); + fail_unless (g_value_get_int (&ret) == expected); + + /* clean up */ + gst_iterator_free (iter); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +GST_START_TEST (test_single) +{ + GstIterator *it; + GstStructure *s = gst_structure_new_empty ("test"); + GValue v = { 0, }; + GstStructure *i; + + g_value_init (&v, GST_TYPE_STRUCTURE); + g_value_set_boxed (&v, s); + it = gst_iterator_new_single (GST_TYPE_STRUCTURE, &v); + g_value_reset (&v); + + fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_OK); + i = g_value_get_boxed (&v); + fail_unless (strcmp (gst_structure_get_name (s), + gst_structure_get_name (i)) == 0); + i = NULL; + g_value_reset (&v); + + fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_DONE); + fail_unless (g_value_get_boxed (&v) == NULL); + + gst_iterator_free (it); + gst_structure_free (s); + + it = gst_iterator_new_single (GST_TYPE_STRUCTURE, NULL); + + fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_DONE); + fail_unless (g_value_get_boxed (&v) == NULL); + + g_value_reset (&v); + + gst_iterator_free (it); +} + +GST_END_TEST; + +static gint +filter2_cb (gconstpointer a, gconstpointer b) +{ + const GValue *va = a; + gint ia; + + ia = GPOINTER_TO_INT (g_value_get_pointer (va)); + + return ia % 2; +} + +GST_START_TEST (test_filter) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter, *filter; + GstIteratorResult res; + GValue item = { 0, }; + gint expected = 0, value; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + fail_unless (iter != NULL); + + filter = gst_iterator_filter (iter, filter2_cb, NULL); + + while (1) { + res = gst_iterator_next (filter, &item); + if (res == GST_ITERATOR_DONE) + break; + fail_unless (res == GST_ITERATOR_OK); + value = GPOINTER_TO_INT (g_value_get_pointer (&item)); + fail_unless_equals_int (value, expected); + expected += 2; + } + + /* clean up */ + g_value_unset (&item); + gst_iterator_free (filter); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +static gint +filter2_lock_cb (gconstpointer a, gconstpointer b) +{ + const GValue *va = a; + const GValue *vb = b; + gint ia; + GMutex *m; + + ia = GPOINTER_TO_INT (g_value_get_pointer (va)); + + m = g_value_get_pointer (vb); + g_mutex_lock (m); + g_mutex_unlock (m); + + return ia % 2; +} + +GST_START_TEST (test_filter_locking) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter, *filter; + GstIteratorResult res; + GValue item = { 0, }; + GValue user_data = { 0, }; + gint expected = 0, value; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + fail_unless (iter != NULL); + + g_value_init (&user_data, G_TYPE_POINTER); + g_value_set_pointer (&user_data, &m); + + filter = gst_iterator_filter (iter, filter2_lock_cb, &user_data); + + while (1) { + res = gst_iterator_next (filter, &item); + if (res == GST_ITERATOR_DONE) + break; + fail_unless (res == GST_ITERATOR_OK); + value = GPOINTER_TO_INT (g_value_get_pointer (&item)); + fail_unless_equals_int (value, expected); + expected += 2; + } + + /* clean up */ + g_value_unset (&item); + g_value_unset (&user_data); + gst_iterator_free (filter); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +static gint +filter4_cb (gconstpointer a, gconstpointer b) +{ + const GValue *va = a; + gint ia; + + ia = GPOINTER_TO_INT (g_value_get_pointer (va)); + + return ia % 4; +} + +GST_START_TEST (test_filter_of_filter) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter, *filter, *filter2; + GstIteratorResult res; + GValue item = { 0, }; + gint expected = 0, value; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + fail_unless (iter != NULL); + + filter = gst_iterator_filter (iter, filter2_cb, NULL); + filter2 = gst_iterator_filter (filter, filter4_cb, NULL); + + while (1) { + res = gst_iterator_next (filter2, &item); + if (res == GST_ITERATOR_DONE) + break; + fail_unless (res == GST_ITERATOR_OK); + value = GPOINTER_TO_INT (g_value_get_pointer (&item)); + fail_unless_equals_int (value, expected); + expected += 4; + } + + /* clean up */ + g_value_unset (&item); + gst_iterator_free (filter2); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +static gint +filter4_lock_cb (gconstpointer a, gconstpointer b) +{ + const GValue *va = a; + const GValue *vb = b; + gint ia; + GMutex *m; + + ia = GPOINTER_TO_INT (g_value_get_pointer (va)); + + m = g_value_get_pointer (vb); + g_mutex_lock (m); + g_mutex_unlock (m); + + return ia % 4; +} + +GST_START_TEST (test_filter_of_filter_locking) +{ + GList *l; + guint32 cookie = 0; + GMutex m; + GstIterator *iter, *filter, *filter2; + GstIteratorResult res; + GValue item = { 0, }; + GValue user_data = { 0, }; + gint expected = 0, value; + + l = make_list_of_ints (NUM_ELEMENTS); + g_mutex_init (&m); + iter = gst_iterator_new_list (G_TYPE_POINTER, &m, &cookie, &l, NULL, NULL); + fail_unless (iter != NULL); + + g_value_init (&user_data, G_TYPE_POINTER); + g_value_set_pointer (&user_data, &m); + + filter = gst_iterator_filter (iter, filter2_lock_cb, &user_data); + filter2 = gst_iterator_filter (filter, filter4_lock_cb, &user_data); + + while (1) { + res = gst_iterator_next (filter2, &item); + if (res == GST_ITERATOR_DONE) + break; + fail_unless (res == GST_ITERATOR_OK); + value = GPOINTER_TO_INT (g_value_get_pointer (&item)); + fail_unless_equals_int (value, expected); + expected += 4; + } + + /* clean up */ + g_value_unset (&item); + g_value_unset (&user_data); + gst_iterator_free (filter2); + g_mutex_clear (&m); + g_list_free (l); +} + +GST_END_TEST; + +static Suite * +gst_iterator_suite (void) +{ + Suite *s = suite_create ("GstIterator"); + TCase *tc_chain = tcase_create ("correctness"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_manual_iteration); + tcase_add_test (tc_chain, test_resync); + tcase_add_test (tc_chain, test_fold); + tcase_add_test (tc_chain, test_single); + tcase_add_test (tc_chain, test_filter); + tcase_add_test (tc_chain, test_filter_locking); + tcase_add_test (tc_chain, test_filter_of_filter); + tcase_add_test (tc_chain, test_filter_of_filter_locking); + return s; +} + +GST_CHECK_MAIN (gst_iterator); diff --git a/tests/check/gst/gstmemory.c b/tests/check/gst/gstmemory.c new file mode 100644 index 0000000..9bd6c00 --- /dev/null +++ b/tests/check/gst/gstmemory.c @@ -0,0 +1,767 @@ +/* GStreamer + * + * unit test for GstMemory + * + * Copyright (C) <2012> 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +GST_START_TEST (test_submemory) +{ + GstMemory *memory, *sub; + GstMapInfo info, sinfo; + + memory = gst_allocator_alloc (NULL, 4, NULL); + + /* check sizes, memory starts out empty */ + fail_unless (gst_memory_map (memory, &info, GST_MAP_WRITE)); + fail_unless (info.size == 4, "memory has wrong size"); + fail_unless (info.maxsize >= 4, "memory has wrong size"); + memset (info.data, 0, 4); + gst_memory_unmap (memory, &info); + + fail_unless (gst_memory_map (memory, &info, GST_MAP_READ)); + + sub = gst_memory_share (memory, 1, 2); + fail_if (sub == NULL, "share of memory returned NULL"); + + fail_unless (gst_memory_map (sub, &sinfo, GST_MAP_READ)); + fail_unless (sinfo.size == 2, "submemory has wrong size"); + fail_unless (memcmp (info.data + 1, sinfo.data, 2) == 0, + "submemory contains the wrong data"); + ASSERT_MINI_OBJECT_REFCOUNT (sub, "submemory", 1); + gst_memory_unmap (sub, &sinfo); + gst_memory_unref (sub); + + /* create a submemory of size 0 */ + sub = gst_memory_share (memory, 1, 0); + fail_if (sub == NULL, "share memory returned NULL"); + fail_unless (gst_memory_map (sub, &sinfo, GST_MAP_READ)); + fail_unless (sinfo.size == 0, "submemory has wrong size"); + fail_unless (memcmp (info.data + 1, sinfo.data, 0) == 0, + "submemory contains the wrong data"); + ASSERT_MINI_OBJECT_REFCOUNT (sub, "submemory", 1); + gst_memory_unmap (sub, &sinfo); + gst_memory_unref (sub); + + /* test if metadata is coppied, not a complete memory copy so only the + * timestamp and offset fields are copied. */ + sub = gst_memory_share (memory, 0, 1); + fail_if (sub == NULL, "share of memory returned NULL"); + fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 1, + "submemory has wrong size"); + gst_memory_unref (sub); + + /* test if metadata is coppied, a complete memory is copied so all the timing + * fields should be copied. */ + sub = gst_memory_share (memory, 0, 4); + fail_if (sub == NULL, "share of memory returned NULL"); + fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 4, + "submemory has wrong size"); + + /* clean up */ + gst_memory_unref (sub); + + gst_memory_unmap (memory, &info); + + /* test write map + share failure */ + fail_unless (gst_memory_map (memory, &info, GST_MAP_WRITE)); + sub = gst_memory_share (memory, 0, 4); + fail_unless (sub == NULL, "share with a write map succeeded"); + + gst_memory_unmap (memory, &info); + gst_memory_unref (memory); +} + +GST_END_TEST; + +GST_START_TEST (test_is_span) +{ + GstMemory *memory, *sub1, *sub2; + + memory = gst_allocator_alloc (NULL, 4, NULL); + + sub1 = gst_memory_share (memory, 0, 2); + fail_if (sub1 == NULL, "share of memory returned NULL"); + + sub2 = gst_memory_share (memory, 2, 2); + fail_if (sub2 == NULL, "share of memory returned NULL"); + + fail_if (gst_memory_is_span (memory, sub2, NULL) == TRUE, + "a parent memory can't be span"); + + fail_if (gst_memory_is_span (sub1, memory, NULL) == TRUE, + "a parent memory can't be span"); + + fail_if (gst_memory_is_span (sub1, sub2, NULL) == FALSE, + "two submemorys next to each other should be span"); + + /* clean up */ + gst_memory_unref (sub1); + gst_memory_unref (sub2); + gst_memory_unref (memory); +} + +GST_END_TEST; + +static const char ro_memory[] = "abcdefghijklmnopqrstuvwxyz"; + +static GstMemory * +create_read_only_memory (void) +{ + GstMemory *mem; + + /* assign some read-only data to the new memory */ + mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, + (gpointer) ro_memory, sizeof (ro_memory), 0, sizeof (ro_memory), NULL, + NULL); + fail_unless (GST_MEMORY_IS_READONLY (mem)); + + return mem; +} + +GST_START_TEST (test_writable) +{ + GstMemory *mem, *mem2; + GstMapInfo info; + + /* create read-only memory and try to write */ + mem = create_read_only_memory (); + + fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE)); + + /* Make sure mapping anxd unmapping it doesn't change it's locking state */ + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + gst_memory_unmap (mem, &info); + + fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE)); + + mem2 = gst_memory_copy (mem, 0, -1); + fail_unless (GST_MEMORY_IS_READONLY (mem)); + fail_if (GST_MEMORY_IS_READONLY (mem2)); + + fail_unless (gst_memory_map (mem2, &info, GST_MAP_WRITE)); + info.data[4] = 'a'; + gst_memory_unmap (mem2, &info); + + gst_memory_ref (mem2); + fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE)); + gst_memory_unref (mem2); + + fail_unless (gst_memory_map (mem2, &info, GST_MAP_WRITE)); + info.data[4] = 'a'; + gst_memory_unmap (mem2, &info); + gst_memory_unref (mem2); + + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_submemory_writable) +{ + GstMemory *mem, *sub_mem; + GstMapInfo info; + + /* create sub-memory of read-only memory and try to write */ + mem = create_read_only_memory (); + + sub_mem = gst_memory_share (mem, 0, 8); + fail_unless (GST_MEMORY_IS_READONLY (sub_mem)); + + fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE)); + fail_if (gst_memory_map (sub_mem, &info, GST_MAP_WRITE)); + + gst_memory_unref (sub_mem); + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_copy) +{ + GstMemory *memory, *copy; + GstMapInfo info, sinfo; + + memory = gst_allocator_alloc (NULL, 4, NULL); + ASSERT_MINI_OBJECT_REFCOUNT (memory, "memory", 1); + + copy = gst_memory_copy (memory, 0, -1); + ASSERT_MINI_OBJECT_REFCOUNT (memory, "memory", 1); + ASSERT_MINI_OBJECT_REFCOUNT (copy, "copy", 1); + /* memorys are copied and must point to different memory */ + fail_if (memory == copy); + + fail_unless (gst_memory_map (memory, &info, GST_MAP_READ)); + fail_unless (gst_memory_map (copy, &sinfo, GST_MAP_READ)); + + /* NOTE that data is refcounted */ + fail_unless (info.size == sinfo.size); + + gst_memory_unmap (copy, &sinfo); + gst_memory_unmap (memory, &info); + + gst_memory_unref (copy); + gst_memory_unref (memory); + + memory = gst_allocator_alloc (NULL, 0, NULL); + fail_unless (gst_memory_map (memory, &info, GST_MAP_READ)); + fail_unless (info.size == 0); + gst_memory_unmap (memory, &info); + + /* copying a 0-sized memory should not crash */ + copy = gst_memory_copy (memory, 0, -1); + fail_unless (gst_memory_map (copy, &info, GST_MAP_READ)); + fail_unless (info.size == 0); + gst_memory_unmap (copy, &info); + + gst_memory_unref (copy); + gst_memory_unref (memory); +} + +GST_END_TEST; + +GST_START_TEST (test_try_new_and_alloc) +{ + GstMemory *mem; + GstMapInfo info; + gsize size; + + mem = gst_allocator_alloc (NULL, 0, NULL); + fail_unless (mem != NULL); + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_unless (info.size == 0); + gst_memory_unmap (mem, &info); + gst_memory_unref (mem); + + /* normal alloc should still work */ + size = 640 * 480 * 4; + mem = gst_allocator_alloc (NULL, size, NULL); + fail_unless (mem != NULL); + fail_unless (gst_memory_map (mem, &info, GST_MAP_WRITE)); + fail_unless (info.data != NULL); + fail_unless (info.size == (640 * 480 * 4)); + info.data[640 * 479 * 4 + 479] = 0xff; + gst_memory_unmap (mem, &info); + + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_resize) +{ + GstMemory *mem; + gsize maxalloc; + gsize size, maxsize, offset; + + /* one memory block */ + mem = gst_allocator_alloc (NULL, 100, NULL); + + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + ASSERT_CRITICAL (gst_memory_resize (mem, 200, 50)); + ASSERT_CRITICAL (gst_memory_resize (mem, 0, 150)); + ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc)); + ASSERT_CRITICAL (gst_memory_resize (mem, maxalloc, 1)); + + /* this does nothing */ + gst_memory_resize (mem, 0, 100); + + /* nothing should have changed */ + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 0, 50); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 50); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 0, 100); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 1, 99); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxsize == maxalloc); + + ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc - 1)); + + gst_memory_resize (mem, 0, 99); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, -1, 100); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + /* can't set offset below 0 */ + ASSERT_CRITICAL (gst_memory_resize (mem, -1, 100)); + + gst_memory_resize (mem, 50, 40); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 40); + fail_unless (offset == 50); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, -50, 100); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 0, 0); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 0); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 0, 100); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_resize (mem, 0, 100); + size = gst_memory_get_sizes (mem, &offset, &maxsize); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxsize == maxalloc); + + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_map) +{ + GstMemory *mem; + GstMapInfo info; + gsize maxalloc; + gsize size, offset; + + /* one memory block */ + mem = gst_allocator_alloc (NULL, 100, NULL); + + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + /* see if simply mapping works */ + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 100); + fail_unless (info.maxsize == maxalloc); + + gst_memory_unmap (mem, &info); + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_map_nested) +{ + GstMemory *mem; + GstMapInfo info1, info2; + + mem = gst_allocator_alloc (NULL, 100, NULL); + + /* nested mapping */ + fail_unless (gst_memory_map (mem, &info1, GST_MAP_READ)); + fail_unless (info1.data != NULL); + fail_unless (info1.size == 100); + + fail_unless (gst_memory_map (mem, &info2, GST_MAP_READ)); + fail_unless (info2.data == info1.data); + fail_unless (info2.size == 100); + + /* unmap */ + gst_memory_unmap (mem, &info2); + gst_memory_unmap (mem, &info1); + + fail_unless (gst_memory_map (mem, &info1, GST_MAP_READ)); + /* not allowed */ + fail_if (gst_memory_map (mem, &info2, GST_MAP_WRITE)); + fail_if (gst_memory_map (mem, &info2, GST_MAP_READWRITE)); + fail_unless (gst_memory_map (mem, &info2, GST_MAP_READ)); + gst_memory_unmap (mem, &info2); + gst_memory_unmap (mem, &info1); + + fail_unless (gst_memory_map (mem, &info1, GST_MAP_WRITE)); + /* not allowed */ + fail_if (gst_memory_map (mem, &info2, GST_MAP_READ)); + fail_if (gst_memory_map (mem, &info2, GST_MAP_READWRITE)); + fail_unless (gst_memory_map (mem, &info2, GST_MAP_WRITE)); + gst_memory_unmap (mem, &info1); + gst_memory_unmap (mem, &info2); + /* nothing was mapped */ + ASSERT_CRITICAL (gst_memory_unmap (mem, &info2)); + + fail_unless (gst_memory_map (mem, &info1, GST_MAP_READWRITE)); + fail_unless (gst_memory_map (mem, &info2, GST_MAP_READ)); + gst_memory_unmap (mem, &info2); + fail_unless (gst_memory_map (mem, &info2, GST_MAP_WRITE)); + gst_memory_unmap (mem, &info2); + gst_memory_unmap (mem, &info1); + /* nothing was mapped */ + ASSERT_CRITICAL (gst_memory_unmap (mem, &info1)); + + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_map_resize) +{ + GstMemory *mem; + GstMapInfo info; + gsize size, maxalloc, offset; + + mem = gst_allocator_alloc (NULL, 100, NULL); + + /* do mapping */ + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 100); + + /* resize the buffer */ + gst_memory_resize (mem, 1, info.size - 1); + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxalloc >= 100); + gst_memory_unmap (mem, &info); + + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 99); + fail_unless (offset == 1); + fail_unless (maxalloc >= 100); + + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 99); + fail_unless (info.maxsize >= 100); + gst_memory_unmap (mem, &info); + + /* and larger */ + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + gst_memory_resize (mem, -1, 100); + gst_memory_unmap (mem, &info); + + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + gst_memory_unmap (mem, &info); + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_alloc_params) +{ + GstMemory *mem; + GstMapInfo info; + gsize size, offset, maxalloc; + GstAllocationParams params; + guint8 arr[10]; + + memset (arr, 0, 10); + + gst_allocation_params_init (¶ms); + params.padding = 10; + params.prefix = 10; + params.flags = GST_MEMORY_FLAG_ZERO_PREFIXED | GST_MEMORY_FLAG_ZERO_PADDED; + mem = gst_allocator_alloc (NULL, 100, ¶ms); + + /*Checking size and offset */ + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 10); + fail_unless (maxalloc >= 120); + + fail_unless (GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_ZERO_PREFIXED)); + fail_unless (GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_ZERO_PADDED)); + + fail_unless (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 100); + + /*Checking prefix */ + fail_unless (memcmp (info.data - 10, arr, 10) == 0); + + /*Checking padding */ + fail_unless (memcmp (info.data + 100, arr, 10) == 0); + + + gst_memory_unmap (mem, &info); + gst_memory_unref (mem); +} + +GST_END_TEST; + +GST_START_TEST (test_lock) +{ + GstMemory *mem; + + mem = gst_allocator_alloc (NULL, 10, NULL); + fail_unless (mem != NULL); + + /* test exclusivity */ + fail_unless (gst_memory_lock (mem, + GST_LOCK_FLAG_WRITE | GST_LOCK_FLAG_EXCLUSIVE)); + fail_if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)); + fail_unless (gst_memory_lock (mem, GST_LOCK_FLAG_WRITE)); + gst_memory_unlock (mem, GST_LOCK_FLAG_WRITE | GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unlock (mem, GST_LOCK_FLAG_WRITE); + + /* no lock here */ + + fail_unless (gst_memory_lock (mem, + GST_LOCK_FLAG_READ | GST_LOCK_FLAG_EXCLUSIVE)); + fail_unless (gst_memory_lock (mem, + GST_LOCK_FLAG_READ | GST_LOCK_FLAG_EXCLUSIVE)); + gst_memory_unlock (mem, GST_LOCK_FLAG_READ | GST_LOCK_FLAG_EXCLUSIVE); + gst_memory_unlock (mem, GST_LOCK_FLAG_READ | GST_LOCK_FLAG_EXCLUSIVE); + + /* no lock here */ + + fail_unless (gst_memory_lock (mem, + GST_LOCK_FLAG_READWRITE | GST_LOCK_FLAG_EXCLUSIVE)); + fail_unless (gst_memory_lock (mem, GST_LOCK_FLAG_READ)); + fail_if (gst_memory_lock (mem, GST_LOCK_FLAG_READ | GST_LOCK_FLAG_EXCLUSIVE)); + fail_if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)); + fail_unless (gst_memory_lock (mem, GST_LOCK_FLAG_WRITE)); + gst_memory_unlock (mem, GST_LOCK_FLAG_WRITE); + gst_memory_unlock (mem, GST_LOCK_FLAG_READ); + gst_memory_unlock (mem, GST_LOCK_FLAG_READWRITE | GST_LOCK_FLAG_EXCLUSIVE); + + gst_memory_unref (mem); +} + +GST_END_TEST; + +typedef struct +{ + GstMemory mem; + gpointer data; +} MyOpaqueMemory; + +static GstMemory * +_my_opaque_alloc (GstAllocator * allocator, gsize size, + GstAllocationParams * params) +{ + MyOpaqueMemory *mem = g_slice_new (MyOpaqueMemory); + gsize maxsize = size + params->prefix + params->padding; + + gst_memory_init (GST_MEMORY_CAST (mem), params->flags, allocator, NULL, + maxsize, params->align, params->prefix, size); + + mem->data = g_malloc (maxsize); + + return (GstMemory *) mem; +} + +static void +_my_opaque_free (GstAllocator * allocator, GstMemory * mem) +{ + MyOpaqueMemory *mmem = (MyOpaqueMemory *) mem; + + g_free (mmem->data); + g_slice_free (MyOpaqueMemory, mmem); +} + +static gpointer +_my_opaque_mem_map (MyOpaqueMemory * mem, gsize maxsize, GstMapFlags flags) +{ + /* the subclass is reponsible for logging any error, by design choice and for + * testing purpose MyOpaqueMemory never logs any trace */ + return NULL; +} + +static gboolean +_my_opaque_mem_unmap (MyOpaqueMemory * mem) +{ + return FALSE; +} + +static MyOpaqueMemory * +_my_opaque_mem_share (MyOpaqueMemory * mem, gssize offset, gsize size) +{ + return NULL; +} + +typedef struct +{ + GstAllocator parent; +} MyOpaqueMemoryAllocator; + +typedef struct +{ + GstAllocatorClass parent_class; +} MyOpaqueMemoryAllocatorClass; + +GType my_opaque_memory_allocator_get_type (void); +G_DEFINE_TYPE (MyOpaqueMemoryAllocator, my_opaque_memory_allocator, + GST_TYPE_ALLOCATOR); + +static void +my_opaque_memory_allocator_class_init (MyOpaqueMemoryAllocatorClass * klass) +{ + GstAllocatorClass *allocator_class; + + allocator_class = (GstAllocatorClass *) klass; + + allocator_class->alloc = _my_opaque_alloc; + allocator_class->free = _my_opaque_free; +} + +static void +my_opaque_memory_allocator_init (MyOpaqueMemoryAllocator * allocator) +{ + GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + + alloc->mem_type = "MyOpaqueMemory"; + alloc->mem_map = (GstMemoryMapFunction) _my_opaque_mem_map; + alloc->mem_unmap = (GstMemoryUnmapFunction) _my_opaque_mem_unmap; + alloc->mem_share = (GstMemoryShareFunction) _my_opaque_mem_share; +} + +static void +my_opaque_memory_init (void) +{ + GstAllocator *allocator; + + allocator = g_object_new (my_opaque_memory_allocator_get_type (), NULL); + + gst_allocator_register ("MyOpaqueMemory", allocator); +} + +static void +_custom_log_func (GstDebugCategory * category, + GstDebugLevel level, const gchar * file, const gchar * function, + gint line, GObject * object, GstDebugMessage * message, gpointer unused) +{ + const gchar *dbg_msg = gst_debug_message_get (message); + fail_unless (dbg_msg == NULL); +} + +#ifndef GST_DISABLE_GST_DEBUG +GST_START_TEST (test_no_error_and_no_warning_on_map_failure) +{ + GstAllocator *alloc; + GstMemory *mem; + GstMapInfo info; + gsize maxalloc; + gsize size, offset; + GstDebugLevel prev_debug_threshold; + gboolean prev_debug_is_active; + + my_opaque_memory_init (); + alloc = gst_allocator_find ("MyOpaqueMemory"); + mem = gst_allocator_alloc (alloc, 100, NULL); + + size = gst_memory_get_sizes (mem, &offset, &maxalloc); + fail_unless (size == 100); + fail_unless (offset == 0); + fail_unless (maxalloc >= 100); + + /* Prepare custom logging to capture any GST_ERROR and GST_WARNING. */ + prev_debug_threshold = gst_debug_get_default_threshold (); + prev_debug_is_active = gst_debug_is_active (); + gst_debug_set_active (TRUE); + fail_unless (gst_debug_is_active ()); + gst_debug_set_default_threshold (GST_LEVEL_WARNING); + fail_unless (gst_debug_get_default_threshold () == GST_LEVEL_WARNING); + gst_debug_remove_log_function (gst_debug_log_default); + gst_debug_add_log_function (_custom_log_func, NULL, NULL); + + /* Ensure that the map does not log any error on failure. It has to fail + * because the custom opaque memory here is desgined to not be mappable. */ + fail_if (gst_memory_map (mem, &info, GST_MAP_READ)); + fail_if (info.data != NULL); + fail_if (info.size != 0); + fail_if (info.maxsize != 0); + + fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE)); + fail_if (info.data != NULL); + fail_if (info.size != 0); + fail_if (info.maxsize != 0); + + gst_memory_unref (mem); + gst_object_unref (alloc); + + /* Restore previous logging state. */ + gst_debug_set_default_threshold (prev_debug_threshold); + gst_debug_add_log_function (gst_debug_log_default, NULL, NULL); + gst_debug_remove_log_function (_custom_log_func); + gst_debug_set_active (prev_debug_is_active); +} + +GST_END_TEST; +#endif /* !GST_DISABLE_GST_DEBUG */ + +static Suite * +gst_memory_suite (void) +{ + Suite *s = suite_create ("GstMemory"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_submemory); + tcase_add_test (tc_chain, test_submemory_writable); + tcase_add_test (tc_chain, test_writable); + tcase_add_test (tc_chain, test_is_span); + tcase_add_test (tc_chain, test_copy); + tcase_add_test (tc_chain, test_try_new_and_alloc); + tcase_add_test (tc_chain, test_resize); + tcase_add_test (tc_chain, test_map); + tcase_add_test (tc_chain, test_map_nested); + tcase_add_test (tc_chain, test_map_resize); + tcase_add_test (tc_chain, test_alloc_params); + tcase_add_test (tc_chain, test_lock); +#ifndef GST_DISABLE_GST_DEBUG + tcase_add_test (tc_chain, test_no_error_and_no_warning_on_map_failure); +#endif + + return s; +} + +GST_CHECK_MAIN (gst_memory); diff --git a/tests/check/gst/gstmessage.c b/tests/check/gst/gstmessage.c new file mode 100644 index 0000000..1f5b250 --- /dev/null +++ b/tests/check/gst/gstmessage.c @@ -0,0 +1,631 @@ +/* GStreamer + * + * unit test for GstMessage + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GQuark domain; + +GST_START_TEST (test_parsing) +{ + GstMessage *message; + + domain = g_quark_from_static_string ("test"); + + /* GST_MESSAGE_EOS */ + { + GstStructure *s; + + message = gst_message_new_eos (NULL); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* Add an extra field */ + s = gst_message_writable_structure (message); + fail_if (s == NULL); + gst_structure_set (s, "eos-extra-field", G_TYPE_BOOLEAN, TRUE, NULL); + + gst_message_unref (message); + } + /* GST_MESSAGE_ERROR */ + { + GError *error = NULL; + gchar *debug; + + error = g_error_new (domain, 10, "test error"); + fail_if (error == NULL); + message = gst_message_new_error (NULL, error, "error string"); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + g_error_free (error); + error = NULL; + debug = NULL; + + gst_message_parse_error (message, NULL, NULL); + + gst_message_parse_error (message, &error, &debug); + fail_if (error == NULL); + fail_if (debug == NULL); + fail_unless (strcmp (error->message, "test error") == 0); + fail_unless (error->domain == domain); + fail_unless (error->code == 10); + fail_unless (strcmp (debug, "error string") == 0); + + gst_message_unref (message); + g_error_free (error); + g_free (debug); + } + /* GST_MESSAGE_ERROR with details */ + { + GError *error = NULL; + gchar *debug; + GstStructure *d; + const GstStructure *dc; + + error = g_error_new (domain, 10, "test error"); + fail_if (error == NULL); + d = gst_structure_new ("title", "test-field", G_TYPE_STRING, + "test-contents", NULL); + message = + gst_message_new_error_with_details (NULL, error, "error string", d); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + g_error_free (error); + error = NULL; + debug = NULL; + + gst_message_parse_error (message, NULL, NULL); + + gst_message_parse_error (message, &error, &debug); + fail_if (error == NULL); + fail_if (debug == NULL); + fail_unless (strcmp (error->message, "test error") == 0); + fail_unless (error->domain == domain); + fail_unless (error->code == 10); + fail_unless (strcmp (debug, "error string") == 0); + gst_message_parse_error_details (message, &dc); + fail_unless (dc != NULL); + fail_unless (gst_structure_has_field_typed (dc, "test-field", + G_TYPE_STRING)); + fail_unless (gst_structure_get_string (dc, "test-field"), "test-contents"); + + gst_message_unref (message); + g_error_free (error); + g_free (debug); + } + /* GST_MESSAGE_WARNING */ + { + GError *warning = NULL; + gchar *debug; + + warning = g_error_new (domain, 10, "test warning"); + fail_if (warning == NULL); + message = gst_message_new_warning (NULL, warning, "warning string"); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + g_error_free (warning); + warning = NULL; + debug = NULL; + + gst_message_parse_warning (message, NULL, NULL); + + gst_message_parse_warning (message, &warning, &debug); + fail_if (warning == NULL); + fail_if (debug == NULL); + fail_unless (strcmp (warning->message, "test warning") == 0); + fail_unless (warning->domain == domain); + fail_unless (warning->code == 10); + fail_unless (strcmp (debug, "warning string") == 0); + + gst_message_unref (message); + g_error_free (warning); + g_free (debug); + } + /* GST_MESSAGE_INFO */ + { + GError *info = NULL; + gchar *debug; + + info = g_error_new (domain, 10, "test info"); + fail_if (info == NULL); + message = gst_message_new_info (NULL, info, "info string"); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + g_error_free (info); + info = NULL; + debug = NULL; + + gst_message_parse_info (message, NULL, NULL); + + gst_message_parse_info (message, &info, &debug); + fail_if (info == NULL); + fail_if (debug == NULL); + fail_unless (strcmp (info->message, "test info") == 0); + fail_unless (info->domain == domain); + fail_unless (info->code == 10); + fail_unless (strcmp (debug, "info string") == 0); + + gst_message_unref (message); + g_error_free (info); + g_free (debug); + } + /* GST_MESSAGE_TAG */ + { + GstTagList *tag; + + /* FIXME, do some more tag adding */ + tag = gst_tag_list_new_empty (); + fail_if (tag == NULL); + message = gst_message_new_tag (NULL, tag); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + tag = NULL; + gst_message_parse_tag (message, &tag); + fail_if (tag == NULL); + /* FIXME, check the actual tags */ + gst_message_unref (message); + gst_tag_list_unref (tag); + } + /* GST_MESSAGE_BUFFERING */ + { + } + /* GST_MESSAGE_STATE_CHANGED */ + { + GstState oldstate, newstate, pending; + + oldstate = GST_STATE_PAUSED; + newstate = GST_STATE_PLAYING; + pending = GST_STATE_VOID_PENDING; + + message = gst_message_new_state_changed (NULL, oldstate, newstate, pending); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* set some wrong values to check if the parse method overwrites them + * with the good values */ + oldstate = GST_STATE_READY; + newstate = GST_STATE_READY; + pending = GST_STATE_READY; + gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); + fail_unless (oldstate == GST_STATE_PAUSED); + fail_unless (newstate == GST_STATE_PLAYING); + fail_unless (pending == GST_STATE_VOID_PENDING); + + gst_message_unref (message); + } + /* GST_MESSAGE_STEP_DONE */ + { + } + /* GST_MESSAGE_NEW_CLOCK */ + { + } + /* GST_MESSAGE_STRUCTURE_CHANGE */ + { + } + /* GST_MESSAGE_STREAM_STATUS */ + { + } + /* GST_MESSAGE_APPLICATION */ + { + GstStructure *structure; + const GstStructure *struc; + gint some_int; + gdouble a_double; + + structure = gst_structure_new ("test_struct", + "some_int", G_TYPE_INT, 10, + "a_double", G_TYPE_DOUBLE, (gdouble) 1.8, NULL); + fail_if (structure == NULL); + message = gst_message_new_application (NULL, structure); + fail_if (message == NULL); + struc = gst_message_get_structure (message); + fail_if (struc == NULL); + fail_unless (gst_structure_get_int (struc, "some_int", &some_int)); + fail_unless (gst_structure_get_double (struc, "a_double", &a_double)); + fail_unless (some_int == 10); + fail_unless (a_double == 1.8); + + gst_message_unref (message); + } + + /* + void gst_message_parse_tag (GstMessage *message, GstTagList **tag_list); + void gst_message_parse_state_changed (GstMessage *message, GstState *old_state, + GstState *new_state); + void gst_message_parse_error (GstMessage *message, GError **gerror, gchar **debug); + void gst_message_parse_warning (GstMessage *message, GError **gerror, gchar **debug); + */ + + /* GST_MESSAGE_STREAM_STATUS */ + { + GstStreamStatusType type; + GstTask *task, *task2; + GValue value = { 0 }; + const GValue *val; + + message = + gst_message_new_stream_status (NULL, GST_STREAM_STATUS_TYPE_ENTER, + NULL); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* set some wrong values to check if the parse method overwrites them + * with the good values */ + type = GST_STREAM_STATUS_TYPE_START; + gst_message_parse_stream_status (message, &type, NULL); + fail_unless (type == GST_STREAM_STATUS_TYPE_ENTER); + + /* create a task with some dummy function, we're not actually going to run + * the task here */ + task = gst_task_new ((GstTaskFunction) gst_object_unref, NULL, NULL); + + ASSERT_OBJECT_REFCOUNT (task, "task", 1); + + /* set the task */ + g_value_init (&value, GST_TYPE_TASK); + g_value_set_object (&value, task); + + ASSERT_OBJECT_REFCOUNT (task, "task", 2); + + gst_message_set_stream_status_object (message, &value); + ASSERT_OBJECT_REFCOUNT (task, "task", 3); + g_value_unset (&value); + ASSERT_OBJECT_REFCOUNT (task, "task", 2); + gst_object_unref (task); + ASSERT_OBJECT_REFCOUNT (task, "task", 1); + + /* get the object back, no refcount is changed */ + val = gst_message_get_stream_status_object (message); + ASSERT_OBJECT_REFCOUNT (task, "task", 1); + + task2 = g_value_get_object (val); + + fail_unless (GST_IS_TASK (task2)); + fail_unless (task2 == task); + + ASSERT_OBJECT_REFCOUNT (task, "task", 1); + ASSERT_OBJECT_REFCOUNT (task2, "task", 1); + + gst_message_unref (message); + } + + /* GST_MESSAGE_REQUEST_STATE */ + { + GstState state; + + state = GST_STATE_PAUSED; + + message = gst_message_new_request_state (NULL, state); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REQUEST_STATE); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* set some wrong values to check if the parse method overwrites them + * with the good values */ + state = GST_STATE_READY; + gst_message_parse_request_state (message, &state); + fail_unless (state == GST_STATE_PAUSED); + + gst_message_unref (message); + } + /* GST_MESSAGE_QOS */ + { + gboolean live; + GstClockTime running_time; + GstClockTime stream_time; + GstClockTime timestamp, duration; + gint64 jitter; + gdouble proportion; + gint quality; + GstFormat format; + guint64 processed; + guint64 dropped; + + running_time = 1 * GST_SECOND; + stream_time = 2 * GST_SECOND; + timestamp = 3 * GST_SECOND; + duration = 4 * GST_SECOND; + + message = + gst_message_new_qos (NULL, TRUE, running_time, stream_time, timestamp, + duration); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* check defaults */ + gst_message_parse_qos_values (message, &jitter, &proportion, &quality); + fail_unless (jitter == 0); + fail_unless (proportion == 1.0); + fail_unless (quality == 1000000); + + gst_message_parse_qos_stats (message, &format, &processed, &dropped); + fail_unless (format == GST_FORMAT_UNDEFINED); + fail_unless (processed == -1); + fail_unless (dropped == -1); + + /* set some wrong values to check if the parse method overwrites them + * with the good values */ + running_time = stream_time = timestamp = duration = 5 * GST_SECOND; + live = FALSE; + gst_message_parse_qos (message, &live, &running_time, &stream_time, + ×tamp, &duration); + fail_unless (live == TRUE); + fail_unless (running_time == 1 * GST_SECOND); + fail_unless (stream_time == 2 * GST_SECOND); + fail_unless (timestamp == 3 * GST_SECOND); + fail_unless (duration == 4 * GST_SECOND); + + /* change some values */ + gst_message_set_qos_values (message, -10, 2.0, 5000); + gst_message_parse_qos_values (message, &jitter, &proportion, &quality); + fail_unless (jitter == -10); + fail_unless (proportion == 2.0); + fail_unless (quality == 5000); + + gst_message_set_qos_stats (message, GST_FORMAT_DEFAULT, 1030, 65); + gst_message_parse_qos_stats (message, &format, &processed, &dropped); + fail_unless (format == GST_FORMAT_DEFAULT); + fail_unless (processed == 1030); + fail_unless (dropped == 65); + + gst_message_unref (message); + } + /* GST_MESSAGE_PROGRESS */ + { + GstProgressType type; + gchar *category, *text; + + message = + gst_message_new_progress (NULL, GST_PROGRESS_TYPE_START, "connecting", + "Connecting to youtbue.com"); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROGRESS); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* set some wrong values to check if the parse method overwrites them + * with the good values */ + type = GST_PROGRESS_TYPE_ERROR; + gst_message_parse_progress (message, &type, &category, &text); + fail_unless (type == GST_PROGRESS_TYPE_START); + fail_unless (!strcmp (category, "connecting")); + fail_unless (!strcmp (text, "Connecting to youtbue.com")); + g_free (category); + g_free (text); + + gst_message_unref (message); + } + /* GST_MESSAGE_STREAM_COLLECTION */ + { + GstMessage *message; + GstStreamCollection *collection, *res = NULL; + GstStream *stream1, *stream2; + GstCaps *caps1, *caps2; + + /* Create a collection of two streams */ + caps1 = gst_caps_from_string ("some/caps"); + caps2 = gst_caps_from_string ("some/other-string"); + + stream1 = gst_stream_new ("stream-1", caps1, GST_STREAM_TYPE_AUDIO, 0); + stream2 = gst_stream_new ("stream-2", caps2, GST_STREAM_TYPE_VIDEO, 0); + + collection = gst_stream_collection_new ("something"); + fail_unless (gst_stream_collection_add_stream (collection, stream1)); + fail_unless (gst_stream_collection_add_stream (collection, stream2)); + + message = gst_message_new_stream_collection (NULL, collection); + fail_unless (message != NULL); + + gst_message_parse_stream_collection (message, &res); + fail_unless (res != NULL); + + gst_message_unref (message); + gst_object_unref (res); + gst_object_unref (collection); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + } + /* GST_MESSAGE_STREAMS_SELECTED */ + { + GstMessage *message; + GstStreamCollection *collection, *res = NULL; + GstStream *stream1, *stream2, *stream3; + GstCaps *caps1, *caps2; + + /* Create a collection of two streams */ + caps1 = gst_caps_from_string ("some/caps"); + caps2 = gst_caps_from_string ("some/other-string"); + + stream1 = gst_stream_new ("stream-1", caps1, GST_STREAM_TYPE_AUDIO, 0); + stream2 = gst_stream_new ("stream-2", caps2, GST_STREAM_TYPE_VIDEO, 0); + + collection = gst_stream_collection_new ("something"); + fail_unless (gst_stream_collection_add_stream (collection, stream1)); + fail_unless (gst_stream_collection_add_stream (collection, stream2)); + + message = gst_message_new_streams_selected (NULL, collection); + fail_unless (message != NULL); + + gst_message_parse_streams_selected (message, &res); + fail_unless (res != NULL); + + fail_unless (gst_message_streams_selected_get_size (message) == 0); + gst_object_unref (res); + gst_message_unref (message); + + /* Once again, this time with a stream in it */ + message = gst_message_new_streams_selected (NULL, collection); + fail_unless (message != NULL); + + gst_message_streams_selected_add (message, stream1); + + gst_message_parse_streams_selected (message, &res); + fail_unless (res != NULL); + + /* There is only one stream ! */ + fail_unless (gst_message_streams_selected_get_size (message) == 1); + + stream3 = gst_message_streams_selected_get_stream (message, 0); + fail_unless (stream3 != NULL); + gst_object_unref (stream3); + + /* Shoul fail */ + ASSERT_CRITICAL (gst_message_streams_selected_get_stream (message, 1)); + + gst_object_unref (res); + gst_message_unref (message); + + gst_object_unref (collection); + gst_caps_unref (caps1); + gst_caps_unref (caps2); + } + /* GST_MESSAGE_REDIRECT */ + { + const gchar *parsed_location; + GstTagList *parsed_tag_list; + const GstStructure *parsed_structure; + const gchar *test_location = "some-location"; + const gchar *test_struct_name = "test-struct"; + const gchar *test_value_name = "foo"; + const gint test_value = 12345; + const guint test_bitrate = 120000; + gint value; + guint bitrate; + GstTagList *test_tag_list; + GstStructure *test_structure; + + test_structure = + gst_structure_new (test_struct_name, test_value_name, G_TYPE_INT, + test_value, NULL); + + /* Create a test tag list. It is ref'd before adding an entry to be able + * to test that new_redirect takes ownership */ + test_tag_list = gst_tag_list_new (GST_TAG_BITRATE, test_bitrate, NULL); + + /* Create the message and add the first entry, which only has a location + * and a tag list */ + gst_tag_list_ref (test_tag_list); + message = + gst_message_new_redirect (NULL, test_location, test_tag_list, NULL); + fail_if (message == NULL); + fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT); + fail_unless (GST_MESSAGE_SRC (message) == NULL); + + /* Add the second entry, which only has a location and a structure */ + gst_message_add_redirect_entry (message, test_location, NULL, + gst_structure_copy (test_structure)); + + /* Add the third entry, which has a location, a taglist, and a structure */ + gst_tag_list_ref (test_tag_list); + gst_message_add_redirect_entry (message, test_location, test_tag_list, + gst_structure_copy (test_structure)); + + fail_unless (gst_message_get_num_redirect_entries (message) == 3); + + /* Check that the location of the first entry is correct and that the + * structure pointer is set to NULL */ + parsed_location = NULL; + parsed_tag_list = NULL; + parsed_structure = (const GstStructure *) 0x1; + gst_message_parse_redirect_entry (message, 0, &parsed_location, + &parsed_tag_list, &parsed_structure); + fail_unless (parsed_location != NULL); + fail_unless (parsed_tag_list != NULL); + fail_unless (parsed_structure == NULL); + fail_unless (!strcmp (parsed_location, test_location)); + fail_unless (gst_tag_list_get_uint (parsed_tag_list, GST_TAG_BITRATE, + &bitrate) && (bitrate == test_bitrate)); + + /* Check that the structure of the second entry is correct and that the + * tag list pointer is set to NULL */ + parsed_location = NULL; + parsed_tag_list = (GstTagList *) 0x1; + parsed_structure = NULL; + gst_message_parse_redirect_entry (message, 1, &parsed_location, + &parsed_tag_list, &parsed_structure); + fail_unless (parsed_location != NULL); + fail_unless (parsed_tag_list == NULL); + fail_unless (parsed_structure != NULL); + fail_unless (!strcmp (parsed_location, test_location)); + fail_unless (!strcmp (gst_structure_get_name (parsed_structure), + test_struct_name)); + fail_unless (gst_structure_get_int (parsed_structure, test_value_name, + &value) && (value == test_value)); + + /* Check that the location, tag list, and structure pointers of the + * third entry are correct */ + parsed_location = NULL; + parsed_tag_list = NULL; + parsed_structure = NULL; + gst_message_parse_redirect_entry (message, 2, &parsed_location, + &parsed_tag_list, &parsed_structure); + fail_unless (parsed_location != NULL); + fail_unless (parsed_tag_list != NULL); + fail_unless (parsed_structure != NULL); + fail_unless (!strcmp (parsed_location, test_location)); + fail_unless (!strcmp (gst_structure_get_name (parsed_structure), + test_struct_name)); + fail_unless (gst_tag_list_get_uint (parsed_tag_list, GST_TAG_BITRATE, + &bitrate) && (bitrate == test_bitrate)); + fail_unless (gst_structure_get_int (parsed_structure, test_value_name, + &value) && (value == test_value)); + + gst_message_unref (message); + + /* Since the message takes ownership over the tag list, its refcount + * must have been decreased after each added entry */ + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (test_tag_list), 1); + + gst_structure_free (test_structure); + gst_tag_list_unref (test_tag_list); + } +} + +GST_END_TEST; + +static Suite * +gst_message_suite (void) +{ + Suite *s = suite_create ("GstMessage"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_parsing); + + return s; +} + +GST_CHECK_MAIN (gst_message); diff --git a/tests/check/gst/gstmeta.c b/tests/check/gst/gstmeta.c new file mode 100644 index 0000000..65cf835 --- /dev/null +++ b/tests/check/gst/gstmeta.c @@ -0,0 +1,481 @@ +/* GStreamer + * + * unit test for GstMeta + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +/* test metadata for PTS/DTS and duration */ +typedef struct +{ + GstMeta meta; + + GstClockTime pts; + GstClockTime dts; + GstClockTime duration; + GstClockTime clock_rate; +} GstMetaTest; + +static GType gst_meta_test_api_get_type (void); +#define GST_META_TEST_API_TYPE (gst_meta_test_api_get_type()) + +static const GstMetaInfo *gst_meta_test_get_info (void); +#define GST_META_TEST_INFO (gst_meta_test_get_info()) + +#define GST_META_TEST_GET(buf) ((GstMetaTest *)gst_buffer_get_meta(buf,GST_META_TEST_API_TYPE)) +#define GST_META_TEST_ADD(buf) ((GstMetaTest *)gst_buffer_add_meta(buf,GST_META_TEST_INFO,NULL)) + +typedef struct +{ + GstMeta meta; +} GstMetaFoo; + +static GType gst_meta_foo_api_get_type (void); +#define GST_META_FOO_API_TYPE (gst_meta_foo_api_get_type()) + +static const GstMetaInfo *gst_meta_foo_get_info (void); +#define GST_META_FOO_INFO (gst_meta_foo_get_info()) + +#define GST_META_FOO_GET(buf) ((GstMetaFoo *)gst_buffer_get_meta(buf,GST_META_FOO_API_TYPE)) +#define GST_META_FOO_ADD(buf) ((GstMetaFoo *)gst_buffer_add_meta(buf,GST_META_FOO_INFO,NULL)) + +#if 0 +/* unused currently. This is a user function to fill the metadata with default + * values. We don't call this from the init function because the user is mostly + * likely going to override the values immediately after */ +static void +gst_meta_test_init (GstMetaTest * meta) +{ + meta->pts = GST_CLOCK_TIME_NONE; + meta->dts = GST_CLOCK_TIME_NONE; + meta->duration = GST_CLOCK_TIME_NONE; + meta->clock_rate = GST_SECOND; +} +#endif + +static gboolean +test_init_func (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GST_DEBUG ("init called on buffer %p, meta %p", buffer, meta); + /* nothing to init really, the init function is mostly for allocating + * additional memory or doing special setup as part of adding the metadata to + * the buffer*/ + return TRUE; +} + +static void +test_free_func (GstMeta * meta, GstBuffer * buffer) +{ + GST_DEBUG ("free called on buffer %p, meta %p", buffer, meta); + /* nothing to free really */ +} + +static gboolean +test_transform_func (GstBuffer * transbuf, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstMetaTest *test, *tmeta = (GstMetaTest *) meta; + + GST_DEBUG ("transform %s called from buffer %p to %p, meta %p", + g_quark_to_string (type), buffer, transbuf, meta); + + if (GST_META_TRANSFORM_IS_COPY (type)) { + GstMetaTransformCopy *copy_data = data; + + test = GST_META_TEST_ADD (transbuf); + + if (copy_data->offset == 0) { + /* same offset, copy timestamps */ + test->pts = tmeta->pts; + test->dts = tmeta->dts; + if (!copy_data->region) { + fail_unless (gst_buffer_get_size (buffer) == copy_data->size); + /* same size, copy duration */ + test->duration = tmeta->duration; + } else { + fail_unless (gst_buffer_get_size (buffer) > copy_data->size); + /* else clear */ + test->duration = GST_CLOCK_TIME_NONE; + } + } else { + fail_unless (copy_data->region == TRUE); + test->pts = -1; + test->dts = -1; + test->duration = -1; + } + test->clock_rate = tmeta->clock_rate; + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + +static GType +gst_meta_test_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { "timing", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstMetaTestAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +static gboolean +foo_init_func (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GST_DEBUG ("init called on buffer %p, foo meta %p", buffer, meta); + return TRUE; +} + +static void +foo_free_func (GstMeta * meta, GstBuffer * buffer) +{ + GST_DEBUG ("free called on buffer %p, foo meta %p", buffer, meta); +} + + +static const GstMetaInfo * +gst_meta_test_get_info (void) +{ + static const GstMetaInfo *meta_test_info = NULL; + + if (g_once_init_enter (&meta_test_info)) { + const GstMetaInfo *mi = gst_meta_register (GST_META_TEST_API_TYPE, + "GstMetaTest", + sizeof (GstMetaTest), + test_init_func, test_free_func, test_transform_func); + g_once_init_leave (&meta_test_info, mi); + } + return meta_test_info; +} + +static gboolean +foo_transform_func (GstBuffer * transbuf, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GST_DEBUG ("transform %s called from buffer %p to %p, meta %p", + g_quark_to_string (type), buffer, transbuf, meta); + + if (GST_META_TRANSFORM_IS_COPY (type)) { + GST_META_FOO_ADD (transbuf); + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + +static GType +gst_meta_foo_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstMetaFooAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +static const GstMetaInfo * +gst_meta_foo_get_info (void) +{ + static const GstMetaInfo *meta_foo_info = NULL; + + if (g_once_init_enter (&meta_foo_info)) { + const GstMetaInfo *mi = gst_meta_register (GST_META_FOO_API_TYPE, + "GstMetaFoo", + sizeof (GstMetaFoo), + foo_init_func, foo_free_func, foo_transform_func); + g_once_init_leave (&meta_foo_info, mi); + } + return meta_foo_info; +} + +GST_START_TEST (test_meta_test) +{ + GstBuffer *buffer, *copy, *subbuf; + GstMetaTest *meta; + GstMapInfo info; + + buffer = gst_buffer_new_and_alloc (4); + fail_if (buffer == NULL); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + fail_if (info.data == NULL); + memset (info.data, 0, 4); + gst_buffer_unmap (buffer, &info); + + /* add some metadata */ + meta = GST_META_TEST_ADD (buffer); + fail_if (meta == NULL); + /* fill some values */ + meta->pts = 1000; + meta->dts = 2000; + meta->duration = 1000; + meta->clock_rate = 1000; + + /* copy of the buffer */ + copy = gst_buffer_copy (buffer); + /* get metadata of the buffer */ + meta = GST_META_TEST_GET (copy); + fail_if (meta == NULL); + fail_if (meta->pts != 1000); + fail_if (meta->dts != 2000); + fail_if (meta->duration != 1000); + fail_if (meta->clock_rate != 1000); + gst_buffer_unref (copy); + + /* make subbuffer */ + subbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 1); + /* get metadata of the buffer */ + meta = GST_META_TEST_GET (subbuf); + fail_if (meta == NULL); + fail_if (meta->pts != 1000); + fail_if (meta->dts != 2000); + fail_if (meta->duration != -1); + fail_if (meta->clock_rate != 1000); + gst_buffer_unref (subbuf); + + /* make another subbuffer */ + subbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 3); + /* get metadata of the buffer */ + meta = GST_META_TEST_GET (subbuf); + fail_if (meta == NULL); + fail_if (meta->pts != -1); + fail_if (meta->dts != -1); + fail_if (meta->duration != -1); + fail_if (meta->clock_rate != 1000); + gst_buffer_unref (subbuf); + + /* clean up */ + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +static gboolean +foreach_meta (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) +{ + /* try to remove */ + *meta = NULL; + return TRUE; +} + +GST_START_TEST (test_meta_locked) +{ + GstBuffer *buffer; + GstMetaTest *meta; + + buffer = gst_buffer_new_and_alloc (4); + fail_if (buffer == NULL); + + /* add some metadata */ + meta = GST_META_TEST_ADD (buffer); + fail_if (meta == NULL); + GST_META_FLAG_SET (meta, GST_META_FLAG_LOCKED); + + ASSERT_CRITICAL (gst_buffer_remove_meta (buffer, (GstMeta *) meta)); + ASSERT_CRITICAL (gst_buffer_foreach_meta (buffer, foreach_meta, NULL)); + + GST_META_FLAG_UNSET (meta, GST_META_FLAG_LOCKED); + + gst_buffer_remove_meta (buffer, (GstMeta *) meta); + + /* clean up */ + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +static gboolean +foreach_meta_remove_one (GstBuffer * buffer, GstMeta ** meta, + gpointer to_remove) +{ + if (*meta == to_remove) { + *meta = NULL; + } + + return TRUE; +} + +static gint +count_buffer_meta (GstBuffer * buffer) +{ + gint ret = 0; + gpointer state = NULL; + + while (gst_buffer_iterate_meta (buffer, &state)) + ret++; + + return ret; +} + +GST_START_TEST (test_meta_foreach_remove_one) +{ + GstBuffer *buffer; + GstMetaTest *meta1, *meta2, *meta3; + + buffer = gst_buffer_new_and_alloc (4); + fail_if (buffer == NULL); + + /* add some metadata */ + meta1 = GST_META_TEST_ADD (buffer); + fail_if (meta1 == NULL); + meta2 = GST_META_TEST_ADD (buffer); + fail_if (meta2 == NULL); + meta3 = GST_META_TEST_ADD (buffer); + fail_if (meta3 == NULL); + + fail_unless_equals_int (count_buffer_meta (buffer), 3); + + gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta1); + + fail_unless_equals_int (count_buffer_meta (buffer), 2); + + /* clean up */ + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +GST_START_TEST (test_meta_iterate) +{ + GstBuffer *buffer; + GstMeta *m1, *m2, *m3, *m_found; + GList *metas; + gpointer state; + + /* buffer with single meta */ + buffer = gst_buffer_new_and_alloc (4); + m1 = (GstMeta *) GST_META_TEST_ADD (buffer); + fail_unless (m1 != NULL); + + state = NULL; + fail_unless (gst_buffer_iterate_meta (buffer, &state) != NULL); + fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL); + + state = NULL; + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_TEST_API_TYPE) != NULL); + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_TEST_API_TYPE) == NULL); + + state = NULL; + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_FOO_API_TYPE) == NULL); + + state = NULL; + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_TEST_API_TYPE) != NULL); + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_TEST_API_TYPE) == NULL); + + /* buffer with multiple metas */ + m2 = (GstMeta *) GST_META_FOO_ADD (buffer); + fail_unless (m2 != NULL); + m3 = (GstMeta *) GST_META_TEST_ADD (buffer); + fail_unless (m3 != NULL); + + /* create a list with metas, we don't know what order buffer_iterate has */ + metas = g_list_prepend (g_list_prepend (g_list_prepend (NULL, m1), m2), m3); + + state = NULL; + m_found = gst_buffer_iterate_meta (buffer, &state); + fail_unless (m_found != NULL); + metas = g_list_remove (metas, m_found); + m_found = gst_buffer_iterate_meta (buffer, &state); + fail_unless (m_found != NULL); + metas = g_list_remove (metas, m_found); + m_found = gst_buffer_iterate_meta (buffer, &state); + fail_unless (m_found != NULL); + metas = g_list_remove (metas, m_found); + + /* should only have 3 metas, so the 4th time we should get NULL back */ + fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL); + + /* list should be empty now, we should have seen each meta once */ + fail_unless (metas == NULL); + + /* same test as above with iterate_filtered */ + + /* create a list with metas, we don't know what order buffer_iterate has */ + metas = g_list_prepend (g_list_prepend (g_list_prepend (NULL, m1), m2), m3); + + state = NULL; + m_found = + gst_buffer_iterate_meta_filtered (buffer, &state, GST_META_TEST_API_TYPE); + fail_unless (m_found != NULL); + metas = g_list_remove (metas, m_found); + m_found = + gst_buffer_iterate_meta_filtered (buffer, &state, GST_META_TEST_API_TYPE); + fail_unless (m_found != NULL); + metas = g_list_remove (metas, m_found); + + /* should only have 2 Test metas, so now we should get NULL back */ + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_TEST_API_TYPE) == NULL); + + /* but there should also still be a Foo meta */ + fail_unless_equals_int (g_list_length (metas), 1); + fail_unless (metas->data == m2); + metas = g_list_remove (metas, m2); + + state = NULL; + m_found = + gst_buffer_iterate_meta_filtered (buffer, &state, GST_META_FOO_API_TYPE); + fail_unless (m_found == m2); + + /* only have 1 Foo meta, so now we should get NULL back */ + fail_unless (gst_buffer_iterate_meta_filtered (buffer, &state, + GST_META_FOO_API_TYPE) == NULL); + + gst_buffer_unref (buffer); + + +} + +GST_END_TEST; + +static Suite * +gst_buffermeta_suite (void) +{ + Suite *s = suite_create ("GstMeta"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_meta_test); + tcase_add_test (tc_chain, test_meta_locked); + tcase_add_test (tc_chain, test_meta_foreach_remove_one); + tcase_add_test (tc_chain, test_meta_iterate); + + return s; +} + +GST_CHECK_MAIN (gst_buffermeta); diff --git a/tests/check/gst/gstminiobject.c b/tests/check/gst/gstminiobject.c new file mode 100644 index 0000000..e2cc14e --- /dev/null +++ b/tests/check/gst/gstminiobject.c @@ -0,0 +1,485 @@ +/* GStreamer + * + * unit test for GstMiniObject + * + * Copyright (C) <2005> Thomas Vander Stichele + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_START_TEST (test_copy) +{ + GstBuffer *buffer, *copy; + + buffer = gst_buffer_new_and_alloc (4); + + copy = GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CAST (buffer))); + + fail_if (copy == NULL, "Copy of buffer returned NULL"); + fail_unless (gst_buffer_get_size (copy) == 4, + "Copy of buffer has different size"); + + gst_buffer_unref (buffer); + gst_buffer_unref (copy); +} + +GST_END_TEST; + +GST_START_TEST (test_is_writable) +{ + GstBuffer *buffer; + GstMiniObject *mobj; + + buffer = gst_buffer_new_and_alloc (4); + mobj = GST_MINI_OBJECT_CAST (buffer); + + fail_unless (gst_mini_object_is_writable (mobj), + "A buffer with one ref should be writable"); + + fail_if (gst_mini_object_ref (mobj) == NULL, "Could not ref the mobj"); + + fail_if (gst_mini_object_is_writable (mobj), + "A buffer with two refs should not be writable"); + + gst_buffer_unref (buffer); + gst_mini_object_unref (mobj); +} + +GST_END_TEST; + +GST_START_TEST (test_make_writable) +{ + GstBuffer *buffer; + GstMiniObject *mobj, *mobj2, *mobj3; + + buffer = gst_buffer_new_and_alloc (4); + mobj = GST_MINI_OBJECT_CAST (buffer); + + mobj2 = gst_mini_object_make_writable (mobj); + fail_unless (GST_IS_BUFFER (mobj2), "make_writable did not return a buffer"); + fail_unless (mobj == mobj2, + "make_writable returned a copy for a buffer with refcount 1"); + + mobj2 = gst_mini_object_ref (mobj); + mobj3 = gst_mini_object_make_writable (mobj); + fail_unless (GST_IS_BUFFER (mobj3), "make_writable did not return a buffer"); + fail_if (mobj == mobj3, + "make_writable returned same object for a buffer with refcount > 1"); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (mobj) == 1, + "refcount of original mobj object should be back to 1"); + + mobj2 = gst_mini_object_make_writable (mobj); + fail_unless (GST_IS_BUFFER (mobj2), "make_writable did not return a buffer"); + fail_unless (mobj == mobj2, + "make_writable returned a copy for a buffer with refcount 1"); + + gst_buffer_unref (buffer); + gst_mini_object_unref (mobj3); +} + +GST_END_TEST; + +static gint num_threads = 10; +static gint refs_per_thread = 10000; + +/* test thread-safe refcounting of GstMiniObject */ +static void +thread_ref (GstMiniObject * mobj) +{ + int j; + + THREAD_START (); + + for (j = 0; j < refs_per_thread; ++j) { + gst_mini_object_ref (mobj); + + if (j % num_threads == 0) + THREAD_SWITCH (); + } + GST_DEBUG ("thread stopped"); +} + +GST_START_TEST (test_ref_threaded) +{ + GstBuffer *buffer; + GstMiniObject *mobj; + gint expected; + + buffer = gst_buffer_new_and_alloc (4); + + mobj = GST_MINI_OBJECT_CAST (buffer); + + MAIN_START_THREADS (num_threads, thread_ref, mobj); + + MAIN_STOP_THREADS (); + + expected = num_threads * refs_per_thread + 1; + ASSERT_MINI_OBJECT_REFCOUNT (mobj, "miniobject", expected); + + while (expected-- != 0) + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +static void +thread_unref (GstMiniObject * mobj) +{ + int j; + + THREAD_START (); + + for (j = 0; j < refs_per_thread; ++j) { + gst_mini_object_unref (mobj); + + if (j % num_threads == 0) + THREAD_SWITCH (); + } +} + +GST_START_TEST (test_unref_threaded) +{ + GstBuffer *buffer; + GstMiniObject *mobj; + int i; + + buffer = gst_buffer_new_and_alloc (4); + + mobj = GST_MINI_OBJECT (buffer); + + for (i = 0; i < num_threads * refs_per_thread; ++i) + gst_mini_object_ref (mobj); + + MAIN_START_THREADS (num_threads, thread_unref, mobj); + + MAIN_STOP_THREADS (); + + ASSERT_MINI_OBJECT_REFCOUNT (mobj, "miniobject", 1); + + /* final unref */ + gst_mini_object_unref (mobj); +} + +GST_END_TEST; + +/* ======== weak ref test ======== */ + +static gboolean weak_ref_notify_succeeded = FALSE; + +static void +on_weak_ref_notify (gpointer data, GstMiniObject * where_object_was) +{ + weak_ref_notify_succeeded = TRUE; +} + +GST_START_TEST (test_weak_ref) +{ + GstBuffer *buffer; + + buffer = gst_buffer_new_and_alloc (4); + + gst_mini_object_weak_ref (GST_MINI_OBJECT (buffer), on_weak_ref_notify, + &buffer); + + gst_buffer_unref (buffer); + + fail_unless (weak_ref_notify_succeeded, + "No weak reference notification took place."); +} + +GST_END_TEST; + +#if 0 +/* ======== recycle test ======== */ + +static gint recycle_buffer_count = 10; + +typedef struct _MyBufferPool MyBufferPool; + +struct _MyBufferPool +{ + GSList *buffers; + + volatile gboolean is_closed; +}; + +static void my_recycle_buffer_destroy (MyRecycleBuffer * buf); + +static MyBufferPool * +my_buffer_pool_new (void) +{ + return g_new0 (MyBufferPool, 1); +} + +static void +my_buffer_pool_free (MyBufferPool * self) +{ + while (self->buffers != NULL) { + my_recycle_buffer_destroy (self->buffers->data); + self->buffers = g_slist_delete_link (self->buffers, self->buffers); + } + + g_free (self); +} + +static void +my_buffer_pool_add (MyBufferPool * self, GstBuffer * buf) +{ + g_mutex_lock (mutex); + self->buffers = g_slist_prepend (self->buffers, gst_buffer_ref (buf)); + g_mutex_unlock (mutex); +} + +static GstBuffer * +my_buffer_pool_drain_one (MyBufferPool * self) +{ + GstBuffer *buf = NULL; + + g_mutex_lock (mutex); + if (self->buffers != NULL) { + buf = self->buffers->data; + self->buffers = g_slist_delete_link (self->buffers, self->buffers); + } + g_mutex_unlock (mutex); + + return buf; +} + +static void +my_recycle_buffer_finalize (GstMiniObject * mini_object) +{ + GstBuffer *self = GST_BUFFER_CAST (mini_object); + + if (self->pool != NULL) { + my_buffer_pool_add (self->pool, GST_BUFFER_CAST (self)); + g_usleep (G_USEC_PER_SEC / 100); + } else { + GST_MINI_OBJECT_CLASS (my_recycle_buffer_parent_class)->finalize + (mini_object); + } +} + +static GstBuffer * +my_recycle_buffer_new (MyBufferPool * pool) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + + //buf->pool = pool; + + return GST_BUFFER_CAST (buf); +} + +static void +my_recycle_buffer_destroy (MyRecycleBuffer * buf) +{ + buf->pool = NULL; + gst_buffer_unref (GST_BUFFER_CAST (buf)); +} + +static void +thread_buffer_producer (MyBufferPool * pool) +{ + int j; + + THREAD_START (); + + for (j = 0; j < recycle_buffer_count; ++j) { + GstBuffer *buf = my_recycle_buffer_new (pool); + gst_buffer_unref (buf); + } + + pool->is_closed = TRUE; +} + +static void +thread_buffer_consumer (MyBufferPool * pool) +{ + THREAD_START (); + + do { + GstBuffer *buf; + + buf = my_buffer_pool_drain_one (pool); + if (buf != NULL) + my_recycle_buffer_destroy (MY_RECYCLE_BUFFER_CAST (buf)); + + THREAD_SWITCH (); + } + while (!pool->is_closed); +} + +GST_START_TEST (test_recycle_threaded) +{ + MyBufferPool *pool; + + pool = my_buffer_pool_new (); + + MAIN_START_THREADS (1, thread_buffer_producer, pool); + MAIN_START_THREADS (1, thread_buffer_consumer, pool); + + MAIN_STOP_THREADS (); + + my_buffer_pool_free (pool); +} + +GST_END_TEST; +#endif + +/* ======== value collection test ======== */ +typedef struct _MyFoo +{ + GObject object; +} MyFoo; + +typedef struct _MyFooClass +{ + GObjectClass gobject_class; +} MyFooClass; + +enum +{ + PROP_BUFFER = 1 +}; + +GType my_foo_get_type (void); +G_DEFINE_TYPE (MyFoo, my_foo, G_TYPE_OBJECT); + +static void +my_foo_init (MyFoo * foo) +{ +} + +static void +my_foo_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBuffer *new_buf; + + g_assert (prop_id == PROP_BUFFER); + + new_buf = gst_buffer_new_and_alloc (1024); + g_value_set_boxed (value, GST_MINI_OBJECT (new_buf)); + gst_buffer_unref (new_buf); +} + +static void +my_foo_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstMiniObject *mini_obj; + + g_assert (prop_id == PROP_BUFFER); + + mini_obj = g_value_get_boxed (value); + g_assert (GST_IS_BUFFER (mini_obj)); + +#if 0 + /* gst_value_dup_mini_object() does not exist yet */ + mini_obj = gst_value_dup_mini_object (value); + g_assert (GST_IS_MINI_OBJECT (mini_obj)); + g_assert (GST_IS_BUFFER (mini_obj)); + gst_mini_object_unref (mini_obj); +#endif +} + + +static void +my_foo_class_init (MyFooClass * klass) +{ + GObjectClass *gobject_klass = G_OBJECT_CLASS (klass); + + gobject_klass->get_property = my_foo_get_property; + gobject_klass->set_property = my_foo_set_property; + + g_object_class_install_property (gobject_klass, PROP_BUFFER, + g_param_spec_boxed ("buffer", "Buffer", + "a newly created GstBuffer", GST_TYPE_BUFFER, G_PARAM_READWRITE)); +} + +GST_START_TEST (test_value_collection) +{ + GstBuffer *buf = NULL; + MyFoo *foo; + + foo = (MyFoo *) g_object_new (my_foo_get_type (), NULL); + + /* test g_object_get() refcounting */ + g_object_get (foo, "buffer", &buf, NULL); + g_assert (GST_IS_BUFFER (buf)); + g_assert (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1); + gst_buffer_unref (buf); + + /* test g_object_set() refcounting */ + buf = gst_buffer_new_and_alloc (1024); + g_object_set (foo, "buffer", buf, NULL); + g_assert (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1); + gst_buffer_unref (buf); + + g_object_unref (foo); +} + +GST_END_TEST; + + +GST_START_TEST (test_dup_null_mini_object) +{ + GValue value = { 0, }; + GstMiniObject *mo; + + g_value_init (&value, GST_TYPE_BUFFER); + + g_value_set_boxed (&value, NULL); + + mo = GST_MINI_OBJECT_CAST (g_value_dup_boxed (&value)); + g_assert (mo == NULL); + + g_value_unset (&value); +} + +GST_END_TEST; + +static Suite * +gst_mini_object_suite (void) +{ + Suite *s = suite_create ("GstMiniObject"); + TCase *tc_chain = tcase_create ("general"); + + /* turn off timeout */ + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_copy); + tcase_add_test (tc_chain, test_is_writable); + tcase_add_test (tc_chain, test_make_writable); + tcase_add_test (tc_chain, test_ref_threaded); + tcase_add_test (tc_chain, test_unref_threaded); + tcase_add_test (tc_chain, test_weak_ref); + //tcase_add_test (tc_chain, test_recycle_threaded); + tcase_add_test (tc_chain, test_value_collection); + tcase_add_test (tc_chain, test_dup_null_mini_object); + return s; +} + +GST_CHECK_MAIN (gst_mini_object); diff --git a/tests/check/gst/gstobject.c b/tests/check/gst/gstobject.c new file mode 100644 index 0000000..96ad284 --- /dev/null +++ b/tests/check/gst/gstobject.c @@ -0,0 +1,644 @@ +/* GStreamer + * + * unit test for GstObject + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* + Create a fake subclass + */ +typedef struct _GstFakeObjectClass GstFakeObjectClass; +typedef struct _GstFakeObject GstFakeObject; + +struct _GstFakeObject +{ + GstObject object; +}; + +struct _GstFakeObjectClass +{ + GstObjectClass parent_class; +}; + +//static GstObjectClass *parent_class = NULL; +//static guint gst_fake_object_signals[LAST_SIGNAL] = { 0 }; + +static GType +gst_fake_object_get_type (void) +{ + static volatile gsize fake_object_type = 0; + + if (g_once_init_enter (&fake_object_type)) { + GType type; + static const GTypeInfo fake_object_info = { + sizeof (GstFakeObjectClass), + NULL, //gst_fake_object_base_class_init, + NULL, //gst_fake_object_base_class_finalize, + NULL, //(GClassInitFunc) gst_fake_object_class_init, + NULL, + NULL, + sizeof (GstFakeObject), + 0, + NULL, //(GInstanceInitFunc) gst_fake_object_init, + NULL + }; + + type = g_type_register_static (GST_TYPE_OBJECT, + "GstFakeObject", &fake_object_info, 0); + g_once_init_leave (&fake_object_type, type); + } + return fake_object_type; +} + +/* g_object_new on GstFakeObject should succeed */ +GST_START_TEST (test_fake_object_new) +{ + GstObject *object; + + object = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object == NULL, "Failed to create instance of GstFakeObject"); + fail_unless (GST_IS_OBJECT (object), + "GstFakeObject instance is not a GstObject"); + gst_object_unref (object); +} + +GST_END_TEST; + +static void +notify_name (GObject * object, GParamSpec * pspec, gint * out_count) +{ + *out_count += 1; +} + +/* GstFakeObject name tests */ +GST_START_TEST (test_fake_object_initial_name) +{ + GstObject *object; + gchar *name; + + object = g_object_new (gst_fake_object_get_type (), NULL); + + name = gst_object_get_name (object); + fail_if (name == NULL, "Newly created object has no name"); + fail_if (strncmp (name, "fakeobject", 10) != 0, + "Random name %s does not start with 'fakeobject'", name); + g_free (name); + + gst_object_unref (object); +} + +GST_END_TEST; + + +GST_START_TEST (test_fake_object_reset_name) +{ + GstObject *object; + gchar *name; + gint count = 0; + + object = g_object_new (gst_fake_object_get_type (), NULL); + g_signal_connect (object, "notify::name", G_CALLBACK (notify_name), &count); + + /* give a random name by setting with NULL; + * GstFakeObject class -> fakeobject%d */ + fail_unless (gst_object_set_name (object, NULL), "Could not set name"); + name = gst_object_get_name (object); + fail_if (name == NULL, "Random name was not assigned"); + fail_if (strncmp (name, "fakeobject", 10) != 0, + "Random name %s does not start with 'fakeobject'", name); + g_free (name); + fail_unless (count == 1, "Name change was not notified"); + + gst_object_unref (object); +} + +GST_END_TEST; + + +GST_START_TEST (test_fake_object_set_name_via_property) +{ + GstObject *object; + gchar *name; + gint count = 0; + + object = g_object_new (gst_fake_object_get_type (), NULL); + g_signal_connect (object, "notify::name", G_CALLBACK (notify_name), &count); + + /* also test the property code path */ + g_object_set (object, "name", "fake", NULL); + name = gst_object_get_name (object); + fail_if (name == NULL, "Failed to get name of GstFakeObject"); + fail_if (strcmp (name, "fake") != 0, "Name of GstFakeObject is not 'fake'"); + g_free (name); + fail_if (count > 1, "Name change was notified multiple time"); + fail_unless (count == 1, "Name change was not notified"); + + gst_object_unref (object); +} + +GST_END_TEST; + + +GST_START_TEST (test_fake_object_get_name_returns_copy) +{ + GstObject *object; + gchar *name1, *name2; + + object = g_object_new (gst_fake_object_get_type (), NULL); + + /* change the gotten name to see that it's a copy and not the original */ + name1 = gst_object_get_name (object); + name1[0] = 'm'; + name2 = gst_object_get_name (object); + fail_if (strncmp (name2, "fakeobject", 10) != 0, + "Copy of object name affected actual object name"); + g_free (name1); + g_free (name2); + + gst_object_unref (object); +} + +GST_END_TEST; + + +GST_START_TEST (test_fake_object_set_name_when_parented) +{ + GstObject *object, *parent; + + object = g_object_new (gst_fake_object_get_type (), NULL); + + /* add a parent and ensure name cannot be changed */ + parent = g_object_new (gst_fake_object_get_type (), NULL); + gst_object_set_parent (object, parent); + fail_if (gst_object_set_name (object, "broken"), + "Could set name on parented object"); + + gst_object_unparent (object); + gst_object_unref (parent); +} + +GST_END_TEST; + +/* thread function for threaded name change test */ +static gpointer +thread_name_object (GstObject * object) +{ + gchar *thread_id = g_strdup_printf ("%p", g_thread_self ()); + + THREAD_START (); + + /* give main thread a head start */ + g_usleep (100000); + + /* write our name repeatedly */ + g_message ("THREAD %s: starting loop", thread_id); + while (THREAD_TEST_RUNNING ()) { + gst_object_set_name (object, thread_id); + /* a minimal sleep invokes a thread switch */ + THREAD_SWITCH (); + } + + /* thread is done, so let's return */ + g_message ("THREAD %s: set name", thread_id); + g_free (thread_id); + + return NULL; +} + +#if 0 +GST_START_TEST (test_fake_object_name_threaded_wrong) +{ + GstObject *object; + gchar *name; + gint i; + gboolean expected_failure = FALSE; + + g_message ("\nTEST: set/get without lock"); + + object = g_object_new (gst_fake_object_get_type (), NULL); + gst_object_set_name (object, "main"); + + MAIN_START_THREADS (5, thread_name_object, object); + + /* start looping and set/get name repeatedly */ + for (i = 0; i < 1000; ++i) { + gst_object_set_name (object, "main"); + THREAD_SWITCH (); + name = gst_object_get_name (object); + if (strcmp (name, "main") != 0) { + g_message ("MAIN: expected failure during run %d", i); + expected_failure = TRUE; + g_free (name); + break; + } + g_free (name); + } + MAIN_STOP_THREADS (); + + gst_object_unref (object); + + fail_unless (expected_failure, "name did not get changed"); +} + +GST_END_TEST; +#endif + +/* + * main thread sets and gets name directly on struct inside the object lock + * succeed because lock is held during set/get, and threads are locked out + */ +GST_START_TEST (test_fake_object_name_threaded_right) +{ + GstObject *object; + gchar *name; + gint i; + + g_message ("\nTEST: set/get inside lock"); + + object = g_object_new (gst_fake_object_get_type (), NULL); + gst_object_set_name (object, "main"); + + MAIN_START_THREADS (5, thread_name_object, object); + + /* start looping and set/get name repeatedly */ + for (i = 0; i < 1000; ++i) { + GST_OBJECT_LOCK (object); + g_free (GST_OBJECT_NAME (object)); + GST_OBJECT_NAME (object) = g_strdup ("main"); + THREAD_SWITCH (); + name = g_strdup (GST_OBJECT_NAME (object)); + GST_OBJECT_UNLOCK (object); + + fail_unless (strcmp (name, "main") == 0, + "Name got changed while lock held during run %d", i); + g_free (name); + } + MAIN_STOP_THREADS (); + gst_object_unref (object); +} + +GST_END_TEST; +/* + * main thread creates lots of objects + * child threads sets default names on objects + * then main thread checks uniqueness of object names + */ + +static GList *object_list = NULL; +static gint num_objects = 1000; +static gint num_threads = 5; + +/* thread function for threaded default name change test */ +static gpointer +thread_name_object_default (int *i) +{ + int j; + + THREAD_START (); + + for (j = *i; j < num_objects; j += num_threads) { + GstObject *o = GST_OBJECT (g_list_nth_data (object_list, j)); + + /* g_message ("THREAD %p: setting default name on object %d", + g_thread_self (), j); */ + gst_object_set_name (o, NULL); + THREAD_SWITCH (); + } + + /* thread is done, so let's return */ + g_message ("THREAD %p: set name", g_thread_self ()); + g_free (i); + + return NULL; +} + +static gint +gst_object_name_compare (GstObject * o, GstObject * p) +{ + gint result; + + GST_OBJECT_LOCK (o); + GST_OBJECT_LOCK (p); + + if (o->name == NULL && p->name == NULL) { + result = 0; + } else if (o->name == NULL) { + result = -1; + } else if (p->name == NULL) { + result = 1; + } else { + result = strcmp (o->name, p->name); + } + + GST_OBJECT_UNLOCK (p); + GST_OBJECT_UNLOCK (o); + + return result; +} + +GST_START_TEST (test_fake_object_name_threaded_unique) +{ + GstObject *object; + gint i; + gint *ip; + gchar *name1, *name2; + GList *l; + + g_message ("\nTEST: uniqueness of default names"); + + for (i = 0; i < num_objects; ++i) { + object = g_object_new (gst_fake_object_get_type (), NULL); + object_list = g_list_append (object_list, object); + } + + MAIN_INIT (); + + mark_point (); + for (i = 0; i < num_threads; ++i) { + ip = g_new (gint, 1); + *ip = i; + MAIN_START_THREAD_FUNCTION (i, thread_name_object_default, ip); + } + + mark_point (); + MAIN_SYNCHRONIZE (); + mark_point (); + MAIN_STOP_THREADS (); + + /* sort GList based on object name */ + /* FIXME: sort and test */ + object_list = + g_list_sort (object_list, (GCompareFunc) gst_object_name_compare); + + name1 = gst_object_get_name (GST_OBJECT (object_list->data)); + for (l = object_list->next; l->next; l = l->next) { + g_message ("object with name %s", name1); + name2 = gst_object_get_name (GST_OBJECT (l->data)); + fail_if (strcmp (name1, name2) == 0, "Two objects with name %s", name2); + g_free (name1); + name1 = name2; + } + g_free (name1); + + /* free stuff */ + g_list_foreach (object_list, (GFunc) g_object_unref, NULL); +} + +GST_END_TEST; + +/* parentage test on GstFakeObject */ +GST_START_TEST (test_fake_object_parentage) +{ + GstObject *object1, *object2; + GstObject *parent; + gboolean result; + + /* create new object */ + object1 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object1 == NULL, "Failed to create instance of GstFakeObject"); + fail_unless (GST_IS_OBJECT (object1), + "GstFakeObject instance is not a GstObject"); + fail_unless (g_object_is_floating (object1), + "GstFakeObject instance is not floating"); + + /* check the parent */ + parent = gst_object_get_parent (object1); + fail_if (parent != NULL, "GstFakeObject has parent"); + /* try to set a NULL parent, this should give a warning */ + ASSERT_CRITICAL (result = gst_object_set_parent (object1, NULL)); + fail_if (result, "GstFakeObject accepted NULL parent"); + /* try to set itself as parent, we expect a warning here */ + ASSERT_CRITICAL (result = gst_object_set_parent (object1, object1)); + fail_if (result, "GstFakeObject accepted itself as parent"); + + /* _has_parent always returns FALSE if there is no parent */ + fail_if (gst_object_has_as_parent (object1, NULL)); + fail_if (gst_object_has_as_parent (NULL, object1)); + fail_if (gst_object_has_as_parent (object1, object1)); + + /* should still be floating */ + fail_unless (g_object_is_floating (object1), + "GstFakeObject instance is not floating"); + + /* create another object */ + object2 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object2 == NULL, + "Failed to create another instance of GstFakeObject"); + fail_unless (GST_IS_OBJECT (object2), + "second GstFakeObject instance is not a GstObject"); + fail_unless (g_object_is_floating (object1), + "GstFakeObject instance is not floating"); + + result = gst_object_has_as_parent (object1, object2); + fail_if (result, "GstFakeObject has a parent"); + + /* try to set other object as parent */ + result = gst_object_set_parent (object1, object2); + fail_unless (result, "GstFakeObject could not accept other object as parent"); + + /* should not be floating anymore */ + fail_if (g_object_is_floating (object1), + "GstFakeObject instance is still floating"); + /* parent should still be floating */ + fail_unless (g_object_is_floating (object2), + "GstFakeObject instance is not floating"); + + /* check the parent */ + fail_unless (gst_object_has_as_parent (object1, object2)); + + /* any other combination is invalid */ + fail_if (gst_object_has_as_parent (object2, object1)); + fail_if (gst_object_has_as_parent (object1, NULL)); + fail_if (gst_object_has_as_parent (object2, NULL)); + fail_if (gst_object_has_as_parent (NULL, object1)); + fail_if (gst_object_has_as_parent (NULL, object2)); + fail_if (gst_object_has_as_parent (object1, object1)); + fail_if (gst_object_has_as_parent (object2, object2)); + + /* try to set other object as parent again */ + result = gst_object_set_parent (object1, object2); + fail_if (result, "GstFakeObject could set parent twice"); + + /* ref before unparenting */ + gst_object_ref (object1); + /* clear parent of object */ + gst_object_unparent (object1); + + /* check the parent */ + parent = gst_object_get_parent (object1); + fail_if (parent != NULL, "GstFakeObject has parent"); + + /* object should not be floating */ + fail_if (g_object_is_floating (object1), + "GstFakeObject instance is floating again"); + + gst_object_unref (object1); + gst_object_unref (object2); +} + +GST_END_TEST; + +/* parentage test dispose on GstFakeObject, since our testcase + * does not handle the parent relation completely, the parent does + * not hold a ref to the child, we cannot dispose the parent to + * dipose the child as well. This test needs to be run with DEBUG + * info to check if the finalize methods are called correctly. */ +GST_START_TEST (test_fake_object_parentage_dispose) +{ + GstObject *object1, *object2; + gboolean result; + + object1 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object1 == NULL, "Failed to create instance of GstFakeObject"); + + object2 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object2 == NULL, "Failed to create instance of GstFakeObject"); + + /* try to set other object as parent */ + result = gst_object_set_parent (object1, object2); + fail_unless (result, "GstFakeObject could not accept other object as parent"); + + /* clear parent of object */ + gst_object_unparent (object1); + + /* now dispose parent */ + gst_object_unref (object2); +} + +GST_END_TEST; + +GST_START_TEST (test_fake_object_has_as_ancestor) +{ + GstObject *object1, *object2, *object3, *object4; + gboolean result; + + object1 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object1 == NULL, "Failed to create instance of GstFakeObject"); + + object2 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object2 == NULL, "Failed to create instance of GstFakeObject"); + + object3 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object3 == NULL, "Failed to create instance of GstFakeObject"); + + object4 = g_object_new (gst_fake_object_get_type (), NULL); + fail_if (object4 == NULL, "Failed to create instance of GstFakeObject"); + + /* try to set other object as parent */ + result = gst_object_set_parent (object1, object3); + fail_unless (result, "GstFakeObject could not accept other object as parent"); + result = gst_object_set_parent (object2, object3); + fail_unless (result, "GstFakeObject could not accept other object as parent"); + result = gst_object_set_parent (object3, object4); + fail_unless (result, "GstFakeObject could not accept other object as parent"); + + /* Hierarchy: + * object4 + * `- object3 + * |- object2 + * `- object1 + */ + + /* An object isn't its own parent, but it is its own ancestor */ + fail_if (gst_object_has_as_parent (object1, object1)); + fail_unless (gst_object_has_as_ancestor (object1, object1)); + + fail_if (gst_object_has_as_parent (object4, object4)); + fail_unless (gst_object_has_as_ancestor (object4, object4)); + + /* direct parents */ + fail_unless (gst_object_has_as_parent (object1, object3)); + fail_unless (gst_object_has_as_ancestor (object1, object3)); + + fail_unless (gst_object_has_as_parent (object2, object3)); + fail_unless (gst_object_has_as_ancestor (object2, object3)); + + fail_unless (gst_object_has_as_parent (object3, object4)); + fail_unless (gst_object_has_as_ancestor (object3, object4)); + + /* grandparents */ + fail_if (gst_object_has_as_parent (object1, object4)); + fail_unless (gst_object_has_as_ancestor (object1, object4)); + + fail_if (gst_object_has_as_parent (object2, object4)); + fail_unless (gst_object_has_as_ancestor (object2, object4)); + + /* not ancestors */ + fail_if (gst_object_has_as_parent (object1, object2)); + fail_if (gst_object_has_as_ancestor (object1, object2)); + + fail_if (gst_object_has_as_parent (object3, object1)); + fail_if (gst_object_has_as_ancestor (object3, object1)); + + fail_if (gst_object_has_as_parent (object4, object1)); + fail_if (gst_object_has_as_ancestor (object4, object1)); + + fail_if (gst_object_has_as_parent (object4, object3)); + fail_if (gst_object_has_as_ancestor (object4, object3)); + + /* unparent everything */ + gst_object_unparent (object3); + gst_object_unparent (object2); + gst_object_unparent (object1); + + /* now dispose objects */ + gst_object_unref (object4); +} + +GST_END_TEST; + +/* test: try renaming a parented object, make sure it fails */ + +static Suite * +gst_object_suite (void) +{ + Suite *s = suite_create ("GstObject"); + TCase *tc_chain = tcase_create ("general"); + + /* turn off timeout */ + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_fake_object_new); + tcase_add_test (tc_chain, test_fake_object_initial_name); + tcase_add_test (tc_chain, test_fake_object_reset_name); + tcase_add_test (tc_chain, test_fake_object_set_name_via_property); + tcase_add_test (tc_chain, test_fake_object_get_name_returns_copy); + tcase_add_test (tc_chain, test_fake_object_set_name_when_parented); +#if 0 + tcase_add_test (tc_chain, test_fake_object_name_threaded_wrong); +#endif + tcase_add_test (tc_chain, test_fake_object_name_threaded_right); + tcase_add_test (tc_chain, test_fake_object_name_threaded_unique); + tcase_add_test (tc_chain, test_fake_object_parentage); + tcase_add_test (tc_chain, test_fake_object_parentage_dispose); + + tcase_add_test (tc_chain, test_fake_object_has_as_ancestor); + //tcase_add_checked_fixture (tc_chain, setup, teardown); + + return s; +} + +GST_CHECK_MAIN (gst_object); diff --git a/tests/check/gst/gstpad.c b/tests/check/gst/gstpad.c new file mode 100644 index 0000000..b9def0f --- /dev/null +++ b/tests/check/gst/gstpad.c @@ -0,0 +1,3349 @@ +/* GStreamer + * Copyright (C) <2005> Thomas Vander Stichele + * + * gstpad.c: Unit test for GstPad + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstSegment dummy_segment; + +GST_START_TEST (test_link) +{ + GstPad *src, *sink; + GstPadTemplate *srct; + + GstPadLinkReturn ret; + gchar *name; + + src = gst_pad_new ("source", GST_PAD_SRC); + fail_if (src == NULL); + ASSERT_OBJECT_REFCOUNT (src, "source pad", 1); + + name = gst_pad_get_name (src); + fail_unless (strcmp (name, "source") == 0); + ASSERT_OBJECT_REFCOUNT (src, "source pad", 1); + g_free (name); + + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + + /* linking without templates or caps should work */ + ret = gst_pad_link (src, sink); + ASSERT_OBJECT_REFCOUNT (src, "source pad", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink pad", 1); + fail_unless (ret == GST_PAD_LINK_OK); + + ASSERT_CRITICAL (gst_pad_get_pad_template (NULL)); + + srct = gst_pad_get_pad_template (src); + fail_unless (srct == NULL); + ASSERT_OBJECT_REFCOUNT (src, "source pad", 1); + + /* clean up */ + ASSERT_OBJECT_REFCOUNT (src, "source pad", 1); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +/* threaded link/unlink */ +/* use globals */ +static GstPad *src, *sink; + +static void +thread_link_unlink (gpointer data) +{ + THREAD_START (); + + while (THREAD_TEST_RUNNING ()) { + gst_pad_link (src, sink); + gst_pad_unlink (src, sink); + THREAD_SWITCH (); + } +} + +GST_START_TEST (test_link_unlink_threaded) +{ + GstCaps *caps; + int i; + + src = gst_pad_new ("source", GST_PAD_SRC); + fail_if (src == NULL); + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + + caps = gst_caps_from_string ("foo/bar"); + gst_pad_set_active (src, TRUE); + gst_pad_set_caps (src, caps); + gst_pad_set_active (sink, TRUE); + gst_pad_set_caps (sink, caps); + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + + MAIN_START_THREADS (5, thread_link_unlink, NULL); + for (i = 0; i < 1000; ++i) { + gst_pad_is_linked (src); + gst_pad_is_linked (sink); + THREAD_SWITCH (); + } + MAIN_STOP_THREADS (); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + gst_caps_unref (caps); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +GST_START_TEST (test_refcount) +{ + GstPad *src, *sink; + GstCaps *caps; + GstPadLinkReturn plr; + + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + + caps = gst_caps_from_string ("foo/bar"); + /* one for me */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + /* can't set caps on flushing sinkpad */ + fail_if (gst_pad_set_caps (src, caps) == TRUE); + fail_if (gst_pad_set_caps (sink, caps) == TRUE); + /* one for me and one for each set_caps */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + gst_pad_set_active (src, TRUE); + fail_unless (gst_pad_set_caps (src, caps) == TRUE); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + gst_pad_set_active (sink, TRUE); + fail_unless (gst_pad_set_caps (sink, caps) == TRUE); + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + /* src caps added to pending caps on sink */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + + gst_pad_unlink (src, sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + + /* cleanup */ + gst_object_unref (src); + gst_object_unref (sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_get_allowed_caps) +{ + GstPad *src, *sink; + GstCaps *caps, *gotcaps; + GstBuffer *buffer; + GstPadLinkReturn plr; + + ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL)); + + buffer = gst_buffer_new (); + ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer)); + gst_buffer_unref (buffer); + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + caps = gst_pad_get_allowed_caps (src); + fail_unless (caps == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_active (src, TRUE); + /* source pad is active and will accept the caps event */ + fail_unless (gst_pad_set_caps (src, caps) == TRUE); + /* sink pad is not active and will refuse the caps event */ + fail_if (gst_pad_set_caps (sink, caps) == TRUE); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + gst_pad_set_active (sink, TRUE); + /* sink pad is now active and will accept the caps event */ + fail_unless (gst_pad_set_caps (sink, caps) == TRUE); + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + + gotcaps = gst_pad_get_allowed_caps (src); + fail_if (gotcaps == NULL); + fail_unless (gst_caps_is_equal (gotcaps, caps)); + + ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 4); + gst_caps_unref (gotcaps); + + gst_pad_unlink (src, sink); + + /* cleanup */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 3); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + + gst_object_unref (src); + gst_object_unref (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static GstCaps *event_caps = NULL; + +static gboolean +sticky_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GstCaps *caps; + + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS + || GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START + || GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + return TRUE; + } + + /* Ensure we get here just once: */ + fail_unless (event_caps == NULL); + + /* The event must arrive before any buffer: */ + fail_unless_equals_int (g_list_length (buffers), 0); + + gst_event_parse_caps (event, &caps); + event_caps = gst_caps_ref (caps); + + gst_event_unref (event); + + return TRUE; +} + +/* Tests whether caps get properly forwarded when pads + are initially unlinked */ +GST_START_TEST (test_sticky_caps_unlinked) +{ + GstCaps *caps; + GstPadTemplate *src_template, *sink_template; + GstPad *src, *sink; + GstEvent *event; + + caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}"); + src_template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, caps); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, caps); + gst_caps_unref (caps); + + src = gst_pad_new_from_template (src_template, "src"); + fail_if (src == NULL); + sink = gst_pad_new_from_template (sink_template, "sink"); + fail_if (sink == NULL); + gst_pad_set_event_function (sink, sticky_event); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + gst_object_unref (src_template); + gst_object_unref (sink_template); + + gst_pad_set_active (src, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + + caps = gst_caps_from_string ("foo/bar, dummy=(int)1"); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + event = gst_event_new_caps (caps); + fail_unless (gst_pad_push_event (src, event) == TRUE); + fail_unless (event_caps == NULL); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* Linking and activating will not forward the sticky event yet... */ + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink))); + gst_pad_set_active (sink, TRUE); + fail_unless (event_caps == NULL); + + /* ...but the first buffer will: */ + fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (event_caps == caps); + fail_unless_equals_int (g_list_length (buffers), 1); + + gst_check_drop_buffers (); + + gst_caps_replace (&caps, NULL); + gst_caps_replace (&event_caps, NULL); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static gboolean +check_if_caps_is_accepted (GstPad * sink, const gchar * str) +{ + GstCaps *caps; + gboolean ret; + + caps = gst_caps_from_string (str); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + ret = gst_pad_query_accept_caps (sink, caps); + gst_caps_unref (caps); + + return ret; +} + +static gboolean +sink_query_caps (GstPad * pad, GstObject * object, GstQuery * q) +{ + gboolean ret; + GstCaps *caps; + + switch (GST_QUERY_TYPE (q)) { + case GST_QUERY_CAPS: + ret = TRUE; + caps = + gst_caps_from_string ("foo/bar, dummy=(int)1," + " query-only-field=(int)1"); + gst_query_set_caps_result (q, caps); + gst_caps_unref (caps); + default: + ret = gst_pad_query_default (pad, object, q); + break; + } + + return ret; +} + +/* Tests whether acceptcaps default handler works properly + with all 4 possible flag combinations */ +GST_START_TEST (test_default_accept_caps) +{ + GstCaps *caps; + GstPadTemplate *sink_template; + GstPad *sink; + + caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}"); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, caps); + gst_caps_unref (caps); + + sink = gst_pad_new_from_template (sink_template, "sink"); + fail_if (sink == NULL); + gst_pad_set_query_function (sink, sink_query_caps); + + gst_object_unref (sink_template); + + gst_pad_set_active (sink, TRUE); + + /* 1. Check with caps query, subset check */ + GST_PAD_UNSET_ACCEPT_INTERSECT (sink); + GST_PAD_UNSET_ACCEPT_TEMPLATE (sink); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)3")); + fail_unless (check_if_caps_is_accepted (sink, + "foo/bar, dummy=(int)1, query-only-field=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, extra-field=(int)1")); + + /* 2. Check with caps query, intersect check */ + GST_PAD_SET_ACCEPT_INTERSECT (sink); + GST_PAD_UNSET_ACCEPT_TEMPLATE (sink); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)3")); + fail_unless (check_if_caps_is_accepted (sink, + "foo/bar, dummy=(int)1, query-only-field=(int)1")); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, extra-field=(int)1")); + + /* 3. Check with template caps, subset check */ + GST_PAD_UNSET_ACCEPT_INTERSECT (sink); + GST_PAD_SET_ACCEPT_TEMPLATE (sink); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)3")); + fail_unless (check_if_caps_is_accepted (sink, + "foo/bar, dummy=(int)1, query-only-field=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, extra-field=(int)1")); + + /* 3. Check with template caps, intersect check */ + GST_PAD_SET_ACCEPT_INTERSECT (sink); + GST_PAD_SET_ACCEPT_TEMPLATE (sink); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)1")); + fail_if (check_if_caps_is_accepted (sink, "foo/bar, dummy=(int)3")); + fail_unless (check_if_caps_is_accepted (sink, + "foo/bar, dummy=(int)1, query-only-field=(int)1")); + fail_unless (check_if_caps_is_accepted (sink, "foo/bar, extra-field=(int)1")); + + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + gst_object_unref (sink); +} + +GST_END_TEST; + +/* Same as test_sticky_caps_unlinked except that the source pad + * has a template of ANY and we will attempt to push + * incompatible caps */ +GST_START_TEST (test_sticky_caps_unlinked_incompatible) +{ + GstCaps *caps, *failcaps; + GstPadTemplate *src_template, *sink_template; + GstPad *src, *sink; + GstEvent *event; + + /* Source pad has ANY caps + * Sink pad has foobar caps + * We will push the pony express caps (which should fail) + */ + caps = gst_caps_new_any (); + src_template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, caps); + gst_caps_unref (caps); + caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}"); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, caps); + gst_caps_unref (caps); + + src = gst_pad_new_from_template (src_template, "src"); + fail_if (src == NULL); + sink = gst_pad_new_from_template (sink_template, "sink"); + fail_if (sink == NULL); + gst_pad_set_event_function (sink, sticky_event); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + gst_object_unref (src_template); + gst_object_unref (sink_template); + + gst_pad_set_active (src, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + + failcaps = gst_caps_from_string ("pony/express, failure=(boolean)true"); + ASSERT_CAPS_REFCOUNT (failcaps, "caps", 1); + + event = gst_event_new_caps (failcaps); + gst_caps_unref (failcaps); + /* The pad isn't linked yet, and anything matches the source pad template + * (which is ANY) */ + fail_unless (gst_pad_push_event (src, event) == TRUE); + fail_unless (event_caps == NULL); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* Linking and activating will not forward the sticky event yet... */ + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink))); + gst_pad_set_active (sink, TRUE); + fail_unless (event_caps == NULL); + + /* ...but the first buffer will and should FAIL since the caps + * are not compatible */ + fail_unless (gst_pad_push (src, + gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED); + /* We shouldn't have received the caps event since it's incompatible */ + fail_unless (event_caps == NULL); + /* We shouldn't have received any buffers since caps are incompatible */ + fail_unless_equals_int (g_list_length (buffers), 0); + + gst_check_drop_buffers (); + + gst_caps_replace (&event_caps, NULL); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +/* Like test_sticky_caps_unlinked, but link before caps: */ + +GST_START_TEST (test_sticky_caps_flushing) +{ + GstCaps *caps; + GstPadTemplate *src_template, *sink_template; + GstPad *src, *sink; + GstEvent *event; + + caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}"); + src_template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, caps); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, caps); + gst_caps_unref (caps); + + src = gst_pad_new_from_template (src_template, "src"); + fail_if (src == NULL); + sink = gst_pad_new_from_template (sink_template, "sink"); + fail_if (sink == NULL); + gst_pad_set_event_function (sink, sticky_event); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + gst_object_unref (src_template); + gst_object_unref (sink_template); + + fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink))); + + caps = gst_caps_from_string ("foo/bar, dummy=(int)1"); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + event = gst_event_new_caps (caps); + + gst_pad_set_active (src, TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + /* The caps event gets accepted by the source pad (and stored) */ + fail_unless (gst_pad_push_event (src, event) == TRUE); + /* But wasn't forwarded since the sink pad is flushing (not activated) */ + fail_unless (event_caps == NULL); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* Activating will not forward the sticky event yet... */ + gst_pad_set_active (sink, TRUE); + fail_unless (event_caps == NULL); + + /* ...but the first buffer will: */ + fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (event_caps == caps); + fail_unless_equals_int (g_list_length (buffers), 1); + + gst_check_drop_buffers (); + + gst_caps_replace (&caps, NULL); + gst_caps_replace (&event_caps, NULL); + + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static gboolean +name_is_valid (const gchar * name, GstPadPresence presence) +{ + GstPadTemplate *new; + GstCaps *any = gst_caps_new_any (); + + new = gst_pad_template_new (name, GST_PAD_SRC, presence, any); + gst_caps_unref (any); + if (new) { + gst_object_unref (GST_OBJECT (new)); + return TRUE; + } + return FALSE; +} + +GST_START_TEST (test_name_is_valid) +{ + gboolean result = FALSE; + + fail_unless (name_is_valid ("src", GST_PAD_ALWAYS)); + ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS)); + ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS)); + fail_if (result); + + fail_unless (name_is_valid ("src", GST_PAD_REQUEST)); + ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST)); + ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST)); + ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST)); + fail_unless (name_is_valid ("src%dsrc", GST_PAD_REQUEST)); + + fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES)); + fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES)); +} + +GST_END_TEST; + +static GstPadProbeReturn +_probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata) +{ + GstPadProbeReturn ret = (GstPadProbeReturn) GPOINTER_TO_INT (userdata); + + /* If we are handling the data, we unref it */ + if (ret == GST_PAD_PROBE_HANDLED + && !(GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_QUERY_BOTH)) { + GST_DEBUG_OBJECT (pad, "Unreffing data"); + gst_mini_object_unref (info->data); + } + return ret; +} + +static GstPadProbeReturn +_handled_probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata) +{ + GstFlowReturn customflow = (GstFlowReturn) GPOINTER_TO_INT (userdata); + + /* We are handling the data, we unref it */ + if (!(GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_QUERY_BOTH)) + gst_mini_object_unref (info->data); + GST_PAD_PROBE_INFO_FLOW_RETURN (info) = customflow; + + return GST_PAD_PROBE_HANDLED; +} + + + +GST_START_TEST (test_events_query_unlinked) +{ + GstPad *src; + GstCaps *caps; + gulong id; + GstQuery *query; + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + caps = gst_pad_get_allowed_caps (src); + fail_unless (caps == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + gst_pad_set_active (src, TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + gst_pad_set_caps (src, caps); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + /* Doing a query on an unlinked pad will return FALSE */ + query = gst_query_new_duration (GST_FORMAT_TIME); + fail_unless (gst_pad_peer_query (src, query) == FALSE); + ASSERT_MINI_OBJECT_REFCOUNT (query, "query", 1); + gst_query_unref (query); + + /* Add a probe that returns _DROP will make the event push return TRUE + * even if not linked */ + GST_DEBUG ("event/query DROP"); + id = gst_pad_add_probe (src, + GST_PAD_PROBE_TYPE_EVENT_BOTH | GST_PAD_PROBE_TYPE_QUERY_BOTH, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_DROP), NULL); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + /* Queries should stil fail */ + query = gst_query_new_duration (GST_FORMAT_TIME); + fail_unless (gst_pad_peer_query (src, query) == FALSE); + ASSERT_MINI_OBJECT_REFCOUNT (query, "query", 1); + gst_query_unref (query); + gst_pad_remove_probe (src, id); + + /* Add a probe that returns _HANDLED will make the event push return TRUE + * even if not linked */ + GST_DEBUG ("event/query HANDLED"); + id = gst_pad_add_probe (src, + GST_PAD_PROBE_TYPE_EVENT_BOTH | GST_PAD_PROBE_TYPE_QUERY_BOTH, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_HANDLED), NULL); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* Queries will succeed */ + query = gst_query_new_duration (GST_FORMAT_TIME); + fail_unless (gst_pad_peer_query (src, query) == TRUE); + ASSERT_MINI_OBJECT_REFCOUNT (query, "query", 1); + gst_query_unref (query); + gst_pad_remove_probe (src, id); + + /* cleanup */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + gst_object_unref (src); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_push_unlinked) +{ + GstPad *src; + GstCaps *caps; + GstBuffer *buffer; + gulong id; + GstFlowReturn fl; + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + caps = gst_pad_get_allowed_caps (src); + fail_unless (caps == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + /* pushing on an inactive pad will return wrong state */ + GST_DEBUG ("push buffer inactive"); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_FLUSHING); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + + gst_pad_set_active (src, TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + GST_DEBUG ("push caps event inactive"); + gst_pad_set_caps (src, caps); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* pushing on an unlinked pad will drop the buffer */ + GST_DEBUG ("push buffer unlinked"); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + + /* adding a probe that returns _DROP will drop the buffer without trying + * to chain */ + GST_DEBUG ("push buffer drop"); + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_DROP), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + /* adding a probe that returns _HANDLED will drop the buffer without trying + * to chain */ + GST_DEBUG ("push buffer handled"); + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_HANDLED), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + /* adding a probe that returns _OK will still chain the buffer, + * and hence drop because pad is unlinked */ + GST_DEBUG ("push buffer ok"); + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_OK), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + GST_DEBUG ("push buffer handled and custom return"); + for (fl = GST_FLOW_NOT_SUPPORTED; fl <= GST_FLOW_OK; fl += 1) { + GST_DEBUG ("Testing with %s", gst_flow_get_name (fl)); + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _handled_probe_handler, GINT_TO_POINTER (fl), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == fl); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + } + + + /* cleanup */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + + gst_object_unref (src); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_push_linked) +{ + GstPad *src, *sink; + GstPadLinkReturn plr; + GstCaps *caps; + GstBuffer *buffer; + gulong id; + + /* setup */ + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + + caps = gst_caps_from_string ("foo/bar"); + /* one for me */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + gst_pad_set_active (src, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + + gst_pad_set_caps (src, caps); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + gst_pad_set_active (sink, TRUE); + /* one for me and one for each set_caps */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + buffer = gst_buffer_new (); + + /* test */ + /* pushing on a linked pad will drop the ref to the buffer */ + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2); + gst_buffer_unref (buffer); + fail_unless_equals_int (g_list_length (buffers), 1); + buffer = GST_BUFFER (buffers->data); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + g_list_free (buffers); + buffers = NULL; + + /* adding a probe that returns _DROP will drop the buffer without trying + * to chain */ + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_DROP), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* adding a probe that returns _OK will still chain the buffer */ + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_OK), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + gst_pad_remove_probe (src, id); + + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2); + gst_buffer_unref (buffer); + fail_unless_equals_int (g_list_length (buffers), 1); + buffer = GST_BUFFER (buffers->data); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + g_list_free (buffers); + buffers = NULL; + + /* adding a probe that returns _HANDLED will not chain the buffer */ + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + _probe_handler, GINT_TO_POINTER (GST_PAD_PROBE_HANDLED), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK); + gst_pad_remove_probe (src, id); + + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + gst_buffer_unref (buffer); + fail_unless_equals_int (g_list_length (buffers), 0); + g_list_free (buffers); + buffers = NULL; + + /* teardown */ + gst_check_drop_buffers (); + gst_pad_unlink (src, sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + gst_object_unref (src); + gst_object_unref (sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_push_linked_flushing) +{ + GstPad *src, *sink; + GstCaps *caps; + GstPadLinkReturn plr; + GstBuffer *buffer; + gulong id; + + /* setup */ + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + caps = gst_pad_get_allowed_caps (src); + fail_unless (caps == NULL); + caps = gst_pad_get_allowed_caps (sink); + fail_unless (caps == NULL); + + caps = gst_caps_from_string ("foo/bar"); + /* one for me */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + + gst_pad_set_active (src, TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + gst_pad_set_caps (src, caps); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + /* need to activate to make it accept the caps */ + gst_pad_set_active (sink, TRUE); + /* one for me and one for each set_caps */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + + /* not activating the pads here, which keeps them flushing */ + gst_pad_set_active (src, FALSE); + gst_pad_set_active (sink, FALSE); + + /* pushing on a flushing pad will drop the buffer */ + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_FLUSHING); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + gst_buffer_unref (buffer); + + gst_pad_set_active (src, TRUE); + gst_pad_set_active (sink, FALSE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + gst_pad_set_caps (src, caps); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + /* adding a probe that returns _DROP will drop the buffer without trying + * to chain */ + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler, + GINT_TO_POINTER (GST_PAD_PROBE_DROP), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_FLUSHING); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + /* adding a probe that returns _OK will still chain the buffer, + * and hence drop because pad is flushing */ + id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler, + GINT_TO_POINTER (GST_PAD_PROBE_OK), NULL); + buffer = gst_buffer_new (); + gst_buffer_ref (buffer); + fail_unless (gst_pad_push (src, buffer) == GST_FLOW_FLUSHING); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + gst_buffer_unref (buffer); + gst_pad_remove_probe (src, id); + + /* cleanup */ + gst_check_drop_buffers (); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + gst_pad_link (src, sink); + gst_object_unref (src); + gst_object_unref (sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static GstBuffer * +buffer_from_string (const gchar * str) +{ + guint size; + GstBuffer *buf; + + size = strlen (str); + buf = gst_buffer_new_and_alloc (size); + + gst_buffer_fill (buf, 0, str, size); + + return buf; +} + +static gboolean +buffer_compare (GstBuffer * buf, const gchar * str, gsize size) +{ + gboolean res; + GstMapInfo info; + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + res = memcmp (info.data, str, size) == 0; + GST_MEMDUMP ("buffer data", info.data, size); + GST_MEMDUMP ("compare data", (guint8 *) str, size); + GST_DEBUG ("buffers match: %s", res ? "yes" : "no"); + gst_buffer_unmap (buf, &info); + + return res; +} + +GST_START_TEST (test_push_buffer_list_compat) +{ + GstPad *src, *sink; + GstPadLinkReturn plr; + GstCaps *caps; + GstBufferList *list; + GstBuffer *buffer; + + /* setup */ + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + gst_pad_set_chain_function (sink, gst_check_chain_func); + /* leave chainlistfunc unset */ + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + gst_pad_set_active (src, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + + gst_pad_set_caps (src, caps); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + gst_pad_set_active (sink, TRUE); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + + list = gst_buffer_list_new (); + + /* test */ + /* adding to a buffer list will drop the ref to the buffer */ + gst_buffer_list_add (list, buffer_from_string ("ListGroup")); + gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup")); + + fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 2); + buffer = GST_BUFFER (buffers->data); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + fail_unless (buffer_compare (buffer, "ListGroup", 9)); + gst_buffer_unref (buffer); + buffers = g_list_delete_link (buffers, buffers); + buffer = GST_BUFFER (buffers->data); + ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1); + fail_unless (buffer_compare (buffer, "AnotherListGroup", 16)); + gst_buffer_unref (buffer); + buffers = g_list_delete_link (buffers, buffers); + fail_unless (buffers == NULL); + + /* teardown */ + gst_check_drop_buffers (); + gst_pad_unlink (src, sink); + gst_object_unref (src); + gst_object_unref (sink); + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_flowreturn) +{ + GstFlowReturn ret; + GQuark quark; + + /* test some of the macros */ + ret = GST_FLOW_EOS; + fail_if (strcmp (gst_flow_get_name (ret), "eos")); + quark = gst_flow_to_quark (ret); + fail_if (strcmp (g_quark_to_string (quark), "eos")); + + /* custom returns */ + ret = GST_FLOW_CUSTOM_SUCCESS; + fail_if (strcmp (gst_flow_get_name (ret), "custom-success")); + quark = gst_flow_to_quark (ret); + fail_if (strcmp (g_quark_to_string (quark), "custom-success")); + + ret = GST_FLOW_CUSTOM_ERROR; + fail_if (strcmp (gst_flow_get_name (ret), "custom-error")); + quark = gst_flow_to_quark (ret); + fail_if (strcmp (g_quark_to_string (quark), "custom-error")); + + /* custom returns clamping */ + ret = GST_FLOW_CUSTOM_SUCCESS + 2; + fail_if (strcmp (gst_flow_get_name (ret), "custom-success")); + quark = gst_flow_to_quark (ret); + fail_if (strcmp (g_quark_to_string (quark), "custom-success")); + + ret = GST_FLOW_CUSTOM_ERROR - 2; + fail_if (strcmp (gst_flow_get_name (ret), "custom-error")); + quark = gst_flow_to_quark (ret); + fail_if (strcmp (g_quark_to_string (quark), "custom-error")); + + /* unknown values */ + ret = GST_FLOW_CUSTOM_ERROR + 2; + fail_if (strcmp (gst_flow_get_name (ret), "unknown")); + quark = gst_flow_to_quark (ret); + fail_unless (quark == 0); +} + +GST_END_TEST; + +GST_START_TEST (test_push_negotiation) +{ + GstPad *src, *sink; + GstPadLinkReturn plr; + GstCaps *srccaps = + gst_caps_from_string ("audio/x-raw,width={16,32},depth={16,32}"); + GstCaps *sinkcaps = + gst_caps_from_string ("audio/x-raw,width=32,depth={16,32}"); + GstPadTemplate *src_template; + GstPadTemplate *sink_template; + GstCaps *caps; + + /* setup */ + src_template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, srccaps); + sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, sinkcaps); + gst_caps_unref (srccaps); + gst_caps_unref (sinkcaps); + + sink = gst_pad_new_from_template (sink_template, "sink"); + fail_if (sink == NULL); + gst_pad_set_chain_function (sink, gst_check_chain_func); + + src = gst_pad_new_from_template (src_template, "src"); + fail_if (src == NULL); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + + /* activate pads */ + gst_pad_set_active (src, TRUE); + gst_pad_set_active (sink, TRUE); + + caps = gst_caps_from_string ("audio/x-raw,width=16,depth=16"); + + /* Should fail if src pad caps are incompatible with sink pad caps */ + gst_pad_set_caps (src, caps); + fail_unless (gst_pad_set_caps (sink, caps) == FALSE); + + /* teardown */ + gst_check_drop_buffers (); + gst_pad_unlink (src, sink); + gst_object_unref (src); + gst_object_unref (sink); + gst_caps_unref (caps); + gst_object_unref (sink_template); + gst_object_unref (src_template); +} + +GST_END_TEST; + +/* see that an unref also unlinks the pads */ +GST_START_TEST (test_src_unref_unlink) +{ + GstPad *src, *sink; + GstCaps *caps; + GstPadLinkReturn plr; + + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + gst_pad_set_active (src, TRUE); + gst_pad_set_caps (src, caps); + gst_pad_set_active (sink, TRUE); + gst_pad_set_caps (sink, caps); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + + /* unref the srcpad */ + gst_object_unref (src); + + /* sink should be unlinked now */ + fail_if (gst_pad_is_linked (sink)); + + /* cleanup */ + gst_object_unref (sink); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* see that an unref also unlinks the pads */ +GST_START_TEST (test_sink_unref_unlink) +{ + GstPad *src, *sink; + GstCaps *caps; + GstPadLinkReturn plr; + + sink = gst_pad_new ("sink", GST_PAD_SINK); + fail_if (sink == NULL); + + src = gst_pad_new ("src", GST_PAD_SRC); + fail_if (src == NULL); + + caps = gst_caps_from_string ("foo/bar"); + + gst_pad_set_active (src, TRUE); + gst_pad_set_caps (src, caps); + gst_pad_set_active (sink, TRUE); + gst_pad_set_caps (sink, caps); + + plr = gst_pad_link (src, sink); + fail_unless (GST_PAD_LINK_SUCCESSFUL (plr)); + + /* unref the sinkpad */ + gst_object_unref (sink); + + /* src should be unlinked now */ + fail_if (gst_pad_is_linked (src)); + + /* cleanup */ + gst_object_unref (src); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static gulong id; + +static GstPadProbeReturn +block_async_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gboolean *bool_user_data = (gboolean *) user_data; + + fail_unless ((info->type & GST_PAD_PROBE_TYPE_BLOCK) != 0); + + /* here we should have blocked == 0 unblocked == 0 */ + fail_unless (bool_user_data[0] == FALSE); + fail_unless (bool_user_data[1] == FALSE); + + bool_user_data[0] = TRUE; + + gst_pad_remove_probe (pad, id); + bool_user_data[1] = TRUE; + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_block_async) +{ + GstPad *pad; + /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's + * unblocked */ + gboolean data[2] = { FALSE, FALSE }; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + + gst_pad_set_active (pad, TRUE); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_cb, &data, + NULL); + + fail_unless (data[0] == FALSE); + fail_unless (data[1] == FALSE); + gst_pad_push (pad, gst_buffer_new ()); + + gst_object_unref (pad); +} + +GST_END_TEST; + +static GstPadProbeReturn +block_async_cb_return_ok (GstPad * pad, GstPadProbeInfo * info, + gpointer user_data) +{ + return GST_PAD_PROBE_OK; +} + +static gpointer +push_buffer_async (GstPad * pad) +{ + return GINT_TO_POINTER (gst_pad_push (pad, gst_buffer_new ())); +} + +static void +test_pad_blocking_with_type (GstPadProbeType type) +{ + GstPad *pad; + GThread *thread; + GstFlowReturn ret; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + + gst_pad_set_active (pad, TRUE); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + id = gst_pad_add_probe (pad, type, block_async_cb_return_ok, NULL, NULL); + + thread = g_thread_try_new ("gst-check", (GThreadFunc) push_buffer_async, + pad, NULL); + + /* wait for the block */ + while (!gst_pad_is_blocking (pad)) { + g_usleep (10000); + } + + /* stop with flushing */ + gst_pad_push_event (pad, gst_event_new_flush_start ()); + + /* get return value from push */ + ret = GPOINTER_TO_INT (g_thread_join (thread)); + /* unflush now */ + gst_pad_push_event (pad, gst_event_new_flush_stop (FALSE)); + /* must be wrong state */ + fail_unless (ret == GST_FLOW_FLUSHING); + + gst_object_unref (pad); +} + +GST_START_TEST (test_pad_blocking_with_probe_type_block) +{ + test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCK); +} + +GST_END_TEST; + +GST_START_TEST (test_pad_blocking_with_probe_type_blocking) +{ + test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCKING); +} + +GST_END_TEST; + +static gboolean idle_probe_running; + +static GstFlowReturn +idletest_sink_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + if (idle_probe_running) + fail ("Should not be reached"); + gst_buffer_unref (buf); + return GST_FLOW_OK; +} + +static GstPadProbeReturn +idle_probe_wait (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + /* it is ok to have a probe called multiple times but it is not + * acceptable in our scenario */ + fail_if (idle_probe_running); + + idle_probe_running = TRUE; + while (idle_probe_running) { + g_usleep (10000); + } + + return GST_PAD_PROBE_REMOVE; +} + +static gpointer +add_idle_probe_async (GstPad * pad) +{ + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE, idle_probe_wait, NULL, NULL); + + return NULL; +} + +GST_START_TEST (test_pad_blocking_with_probe_type_idle) +{ + GstPad *srcpad, *sinkpad; + GThread *idle_thread, *thread; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + + gst_pad_set_chain_function (sinkpad, idletest_sink_pad_chain); + + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK); + + gst_pad_set_active (sinkpad, TRUE); + gst_pad_set_active (srcpad, TRUE); + + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + idle_probe_running = FALSE; + idle_thread = + g_thread_try_new ("gst-check", (GThreadFunc) add_idle_probe_async, srcpad, + NULL); + + /* wait for the idle function to signal it is being called */ + while (!idle_probe_running) { + g_usleep (10000); + } + + thread = g_thread_try_new ("gst-check", (GThreadFunc) push_buffer_async, + srcpad, NULL); + + while (!gst_pad_is_blocking (srcpad)) { + g_usleep (10000); + } + + idle_probe_running = FALSE; + + g_thread_join (idle_thread); + g_thread_join (thread); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +static gboolean pull_probe_called; +static gboolean pull_probe_called_with_bad_type; +static gboolean pull_probe_called_with_bad_data; + +static GstPadProbeReturn +probe_pull_buffer_cb_check_buffer_return_ok (GstPad * pad, + GstPadProbeInfo * info, gpointer user_data) +{ + if (info->type & GST_PAD_PROBE_TYPE_BUFFER) { + if (GST_IS_BUFFER (info->data)) + pull_probe_called = TRUE; + else + pull_probe_called_with_bad_data = TRUE; + } else { + /* shouldn't be called */ + pull_probe_called_with_bad_type = TRUE; + } + return GST_PAD_PROBE_OK; +} + +static GstFlowReturn +test_probe_pull_getrange (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) +{ + *buf = gst_buffer_new (); + return GST_FLOW_OK; +} + +static gboolean +test_probe_pull_activate_pull (GstPad * pad, GstObject * object) +{ + return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); +} + +static gpointer +pull_range_async (GstPad * pad) +{ + GstBuffer *buf = NULL; + GstFlowReturn res = gst_pad_pull_range (pad, 0, 100, &buf); + if (buf) + gst_buffer_unref (buf); + return GINT_TO_POINTER (res); +} + +GST_START_TEST (test_pad_probe_pull) +{ + GstPad *srcpad, *sinkpad; + GThread *thread; + GstFlowReturn ret; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + + gst_pad_set_getrange_function (srcpad, test_probe_pull_getrange); + gst_pad_set_activate_function (sinkpad, test_probe_pull_activate_pull); + gst_pad_link (srcpad, sinkpad); + + gst_pad_set_active (sinkpad, TRUE); + gst_pad_set_active (srcpad, TRUE); + + id = gst_pad_add_probe (sinkpad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_PULL, + block_async_cb_return_ok, NULL, NULL); + + thread = g_thread_try_new ("gst-check", (GThreadFunc) pull_range_async, + sinkpad, NULL); + + /* wait for the block */ + while (!gst_pad_is_blocking (sinkpad)) { + g_usleep (10000); + } + + /* stop with flushing */ + gst_pad_push_event (srcpad, gst_event_new_flush_start ()); + + /* get return value from push */ + ret = GPOINTER_TO_INT (g_thread_join (thread)); + /* unflush now */ + gst_pad_push_event (srcpad, gst_event_new_flush_stop (FALSE)); + /* must be wrong state */ + fail_unless (ret == GST_FLOW_FLUSHING); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +static gboolean idle_probe_called; +static gboolean get_range_wait; +static gboolean getrange_waiting; + +static GstPadProbeReturn +idle_cb_return_ok (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + idle_probe_called = TRUE; + return GST_PAD_PROBE_OK; +} + +static GstFlowReturn +test_probe_pull_getrange_wait (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) +{ + getrange_waiting = TRUE; + + *buf = gst_buffer_new (); + while (get_range_wait) { + g_usleep (10000); + } + + getrange_waiting = FALSE; + return GST_FLOW_OK; +} + +GST_START_TEST (test_pad_probe_pull_idle) +{ + GstPad *srcpad, *sinkpad; + GThread *thread; + GstFlowReturn ret; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + + gst_pad_set_getrange_function (srcpad, test_probe_pull_getrange_wait); + gst_pad_set_activate_function (sinkpad, test_probe_pull_activate_pull); + gst_pad_link (srcpad, sinkpad); + + gst_pad_set_active (sinkpad, TRUE); + gst_pad_set_active (srcpad, TRUE); + + idle_probe_called = FALSE; + get_range_wait = TRUE; + thread = g_thread_try_new ("gst-check", (GThreadFunc) pull_range_async, + sinkpad, NULL); + + /* wait for the block */ + while (!getrange_waiting) { + g_usleep (10000); + } + + id = gst_pad_add_probe (sinkpad, + GST_PAD_PROBE_TYPE_IDLE | GST_PAD_PROBE_TYPE_PULL, + idle_cb_return_ok, NULL, NULL); + + fail_if (idle_probe_called); + + get_range_wait = FALSE; + while (getrange_waiting) { + g_usleep (10000); + } + while (!idle_probe_called) { + g_usleep (10000); + } + + ret = GPOINTER_TO_INT (g_thread_join (thread)); + fail_unless (ret == GST_FLOW_OK); + gst_pad_set_active (srcpad, FALSE); + gst_pad_set_active (sinkpad, FALSE); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + + +GST_START_TEST (test_pad_probe_pull_buffer) +{ + GstPad *srcpad, *sinkpad; + GThread *thread; + GstFlowReturn ret; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + + gst_pad_set_getrange_function (srcpad, test_probe_pull_getrange); + gst_pad_set_activate_function (sinkpad, test_probe_pull_activate_pull); + gst_pad_link (srcpad, sinkpad); + + gst_pad_set_active (sinkpad, TRUE); + gst_pad_set_active (srcpad, TRUE); + + id = gst_pad_add_probe (sinkpad, + GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PULL, + probe_pull_buffer_cb_check_buffer_return_ok, NULL, NULL); + + pull_probe_called = FALSE; + pull_probe_called_with_bad_type = FALSE; + pull_probe_called_with_bad_data = FALSE; + + thread = g_thread_try_new ("gst-check", (GThreadFunc) pull_range_async, + sinkpad, NULL); + + /* wait for the block */ + while (!pull_probe_called && !pull_probe_called_with_bad_data + && !pull_probe_called_with_bad_type) { + g_usleep (10000); + } + + fail_unless (pull_probe_called); + fail_if (pull_probe_called_with_bad_data); + fail_if (pull_probe_called_with_bad_type); + + /* get return value from push */ + ret = GPOINTER_TO_INT (g_thread_join (thread)); + fail_unless (ret == GST_FLOW_OK); + + gst_pad_set_active (sinkpad, FALSE); + gst_pad_set_active (srcpad, FALSE); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +static gboolean pad_probe_remove_notifiy_called = FALSE; + +static GstPadProbeReturn +probe_remove_self_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gst_pad_remove_probe (pad, info->id); + + fail_unless (pad->num_probes == 0); + fail_unless (pad->num_blocked == 0); + + return GST_PAD_PROBE_REMOVE; +} + +static void +probe_remove_notify_cb (gpointer data) +{ + fail_unless (pad_probe_remove_notifiy_called == FALSE); + pad_probe_remove_notifiy_called = TRUE; +} + +GST_START_TEST (test_pad_probe_remove) +{ + GstPad *pad; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + + gst_pad_set_active (pad, TRUE); + fail_unless (pad->num_probes == 0); + fail_unless (pad->num_blocked == 0); + gst_pad_add_probe (pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + probe_remove_self_cb, NULL, probe_remove_notify_cb); + fail_unless (pad->num_probes == 1); + fail_unless (pad->num_blocked == 1); + + pad_probe_remove_notifiy_called = FALSE; + gst_pad_push_event (pad, gst_event_new_stream_start ("asda")); + + fail_unless (pad->num_probes == 0); + fail_unless (pad->num_blocked == 0); + + gst_object_unref (pad); +} + +GST_END_TEST; + +typedef struct +{ + gulong probe_id; + GstPad *probe_pad; + GThread *thread; +} BlockReplaceProbeHelper; + +static gpointer +unblock_probe_thread (gpointer user_data) +{ + BlockReplaceProbeHelper *helper = user_data; + + GST_INFO_OBJECT (helper->probe_pad, "removing probe to unblock pad"); + gst_pad_remove_probe (helper->probe_pad, helper->probe_id); + return NULL; +} + +static GstPadProbeReturn +block_and_replace_buffer_probe_cb (GstPad * pad, GstPadProbeInfo * info, + gpointer user_data) +{ + BlockReplaceProbeHelper *helper = user_data; + + GST_INFO_OBJECT (pad, "about to block pad, replacing buffer"); + + /* we want to block, but also drop this buffer */ + gst_buffer_unref (GST_BUFFER (info->data)); + info->data = NULL; + + helper->thread = + g_thread_new ("gst-pad-test-thread", unblock_probe_thread, helper); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_pad_probe_block_and_drop_buffer) +{ + BlockReplaceProbeHelper helper; + GstFlowReturn flow; + GstPad *src, *sink; + + src = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_active (src, TRUE); + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (sink, gst_check_chain_func); + gst_pad_set_active (sink, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + fail_unless_equals_int (gst_pad_link (src, sink), GST_PAD_LINK_OK); + + helper.probe_id = gst_pad_add_probe (src, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, + block_and_replace_buffer_probe_cb, &helper, NULL); + helper.probe_pad = src; + + /* push a buffer so the events are propagated downstream */ + flow = gst_pad_push (src, gst_buffer_new ()); + + g_thread_join (helper.thread); + + fail_unless_equals_int (flow, GST_FLOW_OK); + + /* no buffer should have made it through to the sink pad, and especially + * not a NULL pointer buffer */ + fail_if (buffers && buffers->data == NULL); + fail_unless (buffers == NULL); + + gst_check_drop_buffers (); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static GstPadProbeReturn +probe_block_a (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +probe_block_b (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gboolean *probe_b_called = user_data; + + *probe_b_called = TRUE; + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +probe_block_c (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gboolean *probe_c_called = user_data; + + *probe_c_called = TRUE; + + return GST_PAD_PROBE_REMOVE; +} + +GST_START_TEST (test_pad_probe_block_add_remove) +{ + GstPad *pad; + GThread *thread; + gulong probe_a, probe_b; + gboolean probe_b_called = FALSE; + gboolean probe_c_called = FALSE; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + + gst_pad_set_active (pad, TRUE); + fail_unless (pad->num_probes == 0); + fail_unless (pad->num_blocked == 0); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + probe_a = gst_pad_add_probe (pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, + probe_block_a, NULL, NULL); + + fail_unless (pad->num_probes == 1); + fail_unless (pad->num_blocked == 1); + + thread = g_thread_try_new ("gst-check", (GThreadFunc) push_buffer_async, + pad, NULL); + + /* wait for the block */ + while (!gst_pad_is_blocking (pad)) { + g_usleep (10000); + } + + probe_b = gst_pad_add_probe (pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, + probe_block_b, &probe_b_called, NULL); + + gst_pad_remove_probe (pad, probe_a); + + /* wait for the callback */ + while (!probe_b_called) { + g_usleep (10000); + } + + /* wait for the block */ + while (!gst_pad_is_blocking (pad)) { + g_usleep (10000); + } + + gst_pad_add_probe (pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, + probe_block_c, &probe_c_called, NULL); + + gst_pad_remove_probe (pad, probe_b); + + /* wait for the callback */ + while (!probe_c_called) { + g_usleep (10000); + } + + /* wait for the unblock */ + while (gst_pad_is_blocking (pad)) { + g_usleep (10000); + } + + gst_object_unref (pad); + + g_thread_join (thread); +} + +GST_END_TEST; + +static gboolean src_flush_start_probe_called = FALSE; +static gboolean src_flush_stop_probe_called = FALSE; +static gboolean sink_flush_start_probe_called = FALSE; +static gboolean sink_flush_stop_probe_called = FALSE; + +static GstPadProbeReturn +flush_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstEvent *event; + + if (!(GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_EVENT_FLUSH)) + goto out; + + event = gst_pad_probe_info_get_event (info); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) + src_flush_start_probe_called = TRUE; + else + sink_flush_start_probe_called = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) + src_flush_stop_probe_called = TRUE; + else + sink_flush_stop_probe_called = TRUE; + break; + default: + break; + } + +out: + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_pad_probe_flush_events) +{ + GstPad *src, *sink; + + src = gst_pad_new ("src", GST_PAD_SRC); + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (sink, gst_check_chain_func); + gst_pad_set_active (src, TRUE); + gst_pad_set_active (sink, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + fail_unless (gst_pad_link (src, sink) == GST_PAD_LINK_OK); + + gst_pad_add_probe (src, + GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | + GST_PAD_PROBE_TYPE_EVENT_FLUSH, flush_probe_cb, NULL, NULL); + gst_pad_add_probe (sink, + GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | + GST_PAD_PROBE_TYPE_EVENT_FLUSH, flush_probe_cb, NULL, NULL); + + gst_pad_push_event (src, gst_event_new_flush_start ()); + gst_pad_push_event (src, gst_event_new_flush_stop (TRUE)); + + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + /* push a buffer so the events are propagated downstream */ + gst_pad_push (src, gst_buffer_new ()); + + fail_unless (src_flush_start_probe_called); + fail_unless (src_flush_stop_probe_called); + fail_unless (sink_flush_start_probe_called); + fail_unless (sink_flush_stop_probe_called); + + gst_check_drop_buffers (); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static gboolean probe_was_called; + +static GstPadProbeReturn +flush_events_only_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + GST_LOG_OBJECT (pad, "%" GST_PTR_FORMAT, GST_PAD_PROBE_INFO_DATA (info)); + + probe_was_called = TRUE; + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_pad_probe_flush_events_only) +{ + GstPad *src, *sink; + + src = gst_pad_new ("src", GST_PAD_SRC); + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (sink, gst_check_chain_func); + gst_pad_set_active (src, TRUE); + gst_pad_set_active (sink, TRUE); + + fail_unless (gst_pad_link (src, sink) == GST_PAD_LINK_OK); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + + gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_EVENT_FLUSH, + flush_events_only_probe, NULL, NULL); + + probe_was_called = FALSE; + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + fail_if (probe_was_called); + + fail_unless_equals_int (gst_pad_push (src, gst_buffer_new ()), GST_FLOW_OK); + fail_if (probe_was_called); + + gst_pad_push_event (src, gst_event_new_flush_start ()); + fail_unless (probe_was_called); + + probe_was_called = FALSE; + gst_pad_push_event (src, gst_event_new_flush_stop (TRUE)); + fail_unless (probe_was_called); + + gst_check_drop_buffers (); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +#define NUM_PROBES 4 +static guint count; + +static GstPadProbeReturn +order_others_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + *(guint *) (user_data) = ++count; + + return GST_PAD_PROBE_REMOVE; +} + +GST_START_TEST (test_pad_probe_call_order) +{ + GstFlowReturn flow; + GstPad *src, *sink; + guint counters[NUM_PROBES]; + guint i; + + src = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_active (src, TRUE); + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (sink, gst_check_chain_func); + gst_pad_set_active (sink, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + fail_unless_equals_int (gst_pad_link (src, sink), GST_PAD_LINK_OK); + + for (i = 0; i < NUM_PROBES; i++) { + gst_pad_add_probe (src, + GST_PAD_PROBE_TYPE_BUFFER, order_others_probe_cb, &(counters[i]), NULL); + } + + /* push a buffer so the events are propagated downstream */ + flow = gst_pad_push (src, gst_buffer_new ()); + fail_unless_equals_int (flow, GST_FLOW_OK); + + for (i = 0; i < NUM_PROBES; i++) { + fail_unless (counters[i] == i + 1); + } + + gst_check_drop_buffers (); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static GstPadProbeReturn +buffers_probe_handled (GstPad * pad, GstPadProbeInfo * info, gpointer gp) +{ + if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER) { + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); + + GST_DEBUG_OBJECT (pad, "buffer: %" GST_PTR_FORMAT ", refcount: %d", + buffer, (GST_MINI_OBJECT (buffer))->refcount); + gst_buffer_unref (buffer); + } + + return GST_PAD_PROBE_HANDLED; +} + +static GstPadProbeReturn +buffers_probe_drop (GstPad * pad, GstPadProbeInfo * info, gboolean * called) +{ + if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER) { + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); + + GST_DEBUG_OBJECT (pad, "buffer: %" GST_PTR_FORMAT ", refcount: %d", + buffer, (GST_MINI_OBJECT (buffer))->refcount); + *called = TRUE; + } + + return GST_PAD_PROBE_DROP; +} + +GST_START_TEST (test_pad_probe_handled_and_drop) +{ + GstFlowReturn flow; + GstPad *src, *sink; + gboolean called; + + src = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_active (src, TRUE); + sink = gst_pad_new ("sink", GST_PAD_SINK); + gst_pad_set_chain_function (sink, gst_check_chain_func); + gst_pad_set_active (sink, TRUE); + + fail_unless (gst_pad_push_event (src, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (src, + gst_event_new_segment (&dummy_segment)) == TRUE); + + fail_unless_equals_int (gst_pad_link (src, sink), GST_PAD_LINK_OK); + + gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + (GstPadProbeCallback) buffers_probe_handled, NULL, NULL); + gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, + (GstPadProbeCallback) buffers_probe_drop, &called, NULL); + + called = FALSE; + flow = gst_pad_push (src, gst_buffer_new ()); + fail_unless_equals_int (flow, GST_FLOW_OK); + fail_if (called); + + /* no buffer should have made it through to the sink pad, and especially + * not a NULL pointer buffer */ + fail_if (buffers && buffers->data == NULL); + fail_unless (buffers == NULL); + + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static gboolean got_notify; + +static void +caps_notify (GstPad * pad, GParamSpec * spec, gpointer data) +{ + got_notify = TRUE; +} + +static void +test_queue_src_caps_notify (gboolean link_queue) +{ + GstElement *queue; + GstPad *src, *sink, *another_pad; + GstCaps *caps; + + queue = gst_element_factory_make ("queue", NULL); + fail_unless (queue != NULL); + + src = gst_element_get_static_pad (queue, "src"); + fail_unless (src != NULL); + + sink = gst_element_get_static_pad (queue, "sink"); + fail_unless (sink != NULL); + + if (link_queue) { + another_pad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (another_pad != NULL); + gst_pad_set_active (another_pad, TRUE); + + gst_pad_link_full (src, another_pad, GST_PAD_LINK_CHECK_NOTHING); + } else { + another_pad = NULL; + } + + gst_element_set_state (queue, GST_STATE_PLAYING); + + got_notify = FALSE; + + g_signal_connect (src, "notify::caps", G_CALLBACK (caps_notify), NULL); + + caps = gst_caps_from_string ("caps"); + gst_pad_send_event (sink, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + while (got_notify == FALSE) + g_usleep (10000); + + gst_element_set_state (queue, GST_STATE_NULL); + + gst_object_unref (src); + gst_object_unref (sink); + gst_object_unref (queue); + if (another_pad) { + gst_object_unref (another_pad); + } +} + +GST_START_TEST (test_queue_src_caps_notify_linked) +{ + test_queue_src_caps_notify (TRUE); +} + +GST_END_TEST +GST_START_TEST (test_queue_src_caps_notify_not_linked) +{ + /* This test will fail because queue doesn't set the caps + on src pad unless it is linked */ + test_queue_src_caps_notify (FALSE); +} + +GST_END_TEST; + +#if 0 +static void +block_async_second (GstPad * pad, gboolean blocked, gpointer user_data) +{ + gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL); +} + +static void +block_async_first (GstPad * pad, gboolean blocked, gpointer user_data) +{ + static int n_calls = 0; + gboolean *bool_user_data = (gboolean *) user_data; + + if (++n_calls > 1) + /* we expect this callback to be called only once */ + g_warn_if_reached (); + + *bool_user_data = blocked; + + /* replace block_async_first with block_async_second so next time the pad is + * blocked the latter should be called */ + gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL); + + /* unblock temporarily, in the next push block_async_second should be called + */ + gst_pad_push_event (pad, gst_event_new_flush_start ()); +} + +GST_START_TEST (test_block_async_replace_callback) +{ + GstPad *pad; + gboolean blocked; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + gst_pad_set_active (pad, TRUE); + + gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL); + blocked = FALSE; + + gst_pad_push (pad, gst_buffer_new ()); + fail_unless (blocked == TRUE); + /* block_async_first flushes to unblock */ + gst_pad_push_event (pad, gst_event_new_flush_stop ()); + + /* push again, this time block_async_second should be called */ + gst_pad_push (pad, gst_buffer_new ()); + fail_unless (blocked == TRUE); + + gst_object_unref (pad); +} + +GST_END_TEST; +#endif + +static void +block_async_full_destroy (gpointer user_data) +{ + gint *state = (gint *) user_data; + + fail_unless (*state < 2); + + GST_DEBUG ("setting state to 2"); + *state = 2; +} + +static GstPadProbeReturn +block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + *(gint *) user_data = (gint) TRUE; + + gst_pad_push_event (pad, gst_event_new_flush_start ()); + GST_DEBUG ("setting state to 1"); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_block_async_full_destroy) +{ + GstPad *pad; + /* 0 = unblocked, 1 = blocked, 2 = destroyed */ + gint state = 0; + gulong id; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + gst_pad_set_active (pad, TRUE); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb, + &state, block_async_full_destroy); + fail_unless (state == 0); + + gst_pad_push (pad, gst_buffer_new ()); + /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily + */ + fail_unless (state == 1); + gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE)); + + /* unblock callback is called */ + gst_pad_remove_probe (pad, id); + fail_unless (state == 2); + + gst_object_unref (pad); +} + +GST_END_TEST; + +GST_START_TEST (test_block_async_full_destroy_dispose) +{ + GstPad *pad; + /* 0 = unblocked, 1 = blocked, 2 = destroyed */ + gint state = 0; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + gst_pad_set_active (pad, TRUE); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb, + &state, block_async_full_destroy); + + gst_pad_push (pad, gst_buffer_new ()); + /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily + */ + fail_unless_equals_int (state, 1); + gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE)); + + /* gst_BLOCK calls the destroy_notify function if necessary */ + gst_object_unref (pad); + + fail_unless_equals_int (state, 2); +} + +GST_END_TEST; + + +#if 0 +static void +unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data) +{ + gboolean *bool_user_data = (gboolean *) user_data; + + /* here we should have blocked == 1 unblocked == 0 */ + + fail_unless (blocked == FALSE); + + fail_unless (bool_user_data[0] == TRUE); + fail_unless (bool_user_data[1] == TRUE); + fail_unless (bool_user_data[2] == FALSE); + + bool_user_data[2] = TRUE; +} +#endif + + +#if 0 +static void +unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data) +{ + g_warn_if_reached (); +} +#endif + +static GstPadProbeReturn +block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info, + gpointer user_data) +{ + gboolean *bool_user_data = (gboolean *) user_data; + + GST_DEBUG ("second probe called"); + + fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK); + + fail_unless (bool_user_data[0] == TRUE); + fail_unless (bool_user_data[1] == FALSE); + fail_unless (bool_user_data[2] == FALSE); + + bool_user_data[1] = TRUE; + + GST_DEBUG ("removing second probe with id %lu", id); + gst_pad_remove_probe (pad, id); + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info, + gpointer user_data) +{ + static int n_calls = 0; + gboolean *bool_user_data = (gboolean *) user_data; + + fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK); + + GST_DEBUG ("first probe called"); + + if (++n_calls > 1) + /* we expect this callback to be called only once */ + g_warn_if_reached (); + + *bool_user_data = TRUE; + + fail_unless (bool_user_data[0] == TRUE); + fail_unless (bool_user_data[1] == FALSE); + fail_unless (bool_user_data[2] == FALSE); + + GST_DEBUG ("removing first probe with id %lu", id); + gst_pad_remove_probe (pad, id); + + GST_DEBUG ("adding second probe"); + /* replace block_async_first with block_async_second so next time the pad is + * blocked the latter should be called */ + id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, + block_async_second_no_flush, user_data, NULL); + GST_DEBUG ("added probe with id %lu", id); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_block_async_replace_callback_no_flush) +{ + GstPad *pad; + gboolean bool_user_data[3] = { FALSE, FALSE, FALSE }; + + pad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (pad != NULL); + gst_pad_set_active (pad, TRUE); + + fail_unless (gst_pad_push_event (pad, + gst_event_new_stream_start ("test")) == TRUE); + fail_unless (gst_pad_push_event (pad, + gst_event_new_segment (&dummy_segment)) == TRUE); + + GST_DEBUG ("adding probe"); + id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, + block_async_first_no_flush, bool_user_data, NULL); + GST_DEBUG ("added probe with id %lu", id); + fail_if (id == 0); + + GST_DEBUG ("pushing buffer"); + gst_pad_push (pad, gst_buffer_new ()); + fail_unless (bool_user_data[0] == TRUE); + fail_unless (bool_user_data[1] == TRUE); + fail_unless (bool_user_data[2] == FALSE); + + gst_object_unref (pad); +} + +GST_END_TEST; + +static gint sticky_count; + +static gboolean +test_sticky_events_handler (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GST_DEBUG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event); + + switch (sticky_count) { + case 0: + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + break; + case 1: + { + GstCaps *caps; + GstStructure *s; + + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS); + + gst_event_parse_caps (event, &caps); + fail_unless (gst_caps_get_size (caps) == 1); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_has_name (s, "foo/baz")); + break; + } + case 2: + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + break; + default: + fail_unless (FALSE); + break; + } + + gst_event_unref (event); + sticky_count++; + + return TRUE; +} + +static GstFlowReturn +test_sticky_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +GST_START_TEST (test_sticky_events) +{ + GstPad *srcpad, *sinkpad; + GstCaps *caps; + GstSegment seg; + gchar *id; + + /* make unlinked srcpad */ + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + gst_pad_set_active (srcpad, TRUE); + + /* test stream-start */ + fail_unless (gst_pad_get_stream_id (srcpad) == NULL); + + /* push an event, it should be sticky on the srcpad */ + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_stream_start ("test")) == TRUE); + + /* let's see if it stuck */ + id = gst_pad_get_stream_id (srcpad); + fail_unless_equals_string (id, "test"); + g_free (id); + + /* make a caps event */ + caps = gst_caps_new_empty_simple ("foo/bar"); + gst_pad_push_event (srcpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + /* make segment event */ + gst_segment_init (&seg, GST_FORMAT_TIME); + gst_pad_push_event (srcpad, gst_event_new_segment (&seg)); + + /* now make a sinkpad */ + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + sticky_count = 0; + gst_pad_set_event_function (sinkpad, test_sticky_events_handler); + gst_pad_set_chain_function (sinkpad, test_sticky_chain); + fail_unless (sticky_count == 0); + gst_pad_set_active (sinkpad, TRUE); + + /* link the pads */ + gst_pad_link (srcpad, sinkpad); + /* should not trigger events */ + fail_unless (sticky_count == 0); + + /* caps replaces old caps event at position 2, the pushes all + * pending events */ + caps = gst_caps_new_empty_simple ("foo/baz"); + gst_pad_push_event (srcpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + /* should have triggered 2 events, the segment event is still pending */ + fail_unless_equals_int (sticky_count, 2); + + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK); + + /* should have triggered 3 events */ + fail_unless_equals_int (sticky_count, 3); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +static GstFlowReturn next_return; + +static GstFlowReturn +test_lastflow_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + gst_buffer_unref (buffer); + return next_return; +} + +GST_START_TEST (test_last_flow_return_push) +{ + GstPad *srcpad, *sinkpad; + GstSegment seg; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + gst_pad_set_chain_function (sinkpad, test_lastflow_chain); + gst_pad_link (srcpad, sinkpad); + + /* initial value is flushing */ + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_FLUSHING); + + /* when active it goes to ok */ + gst_pad_set_active (srcpad, TRUE); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK); + gst_pad_set_active (sinkpad, TRUE); + + /* startup events */ + gst_pad_push_event (srcpad, gst_event_new_stream_start ("test")); + gst_segment_init (&seg, GST_FORMAT_TIME); + gst_pad_push_event (srcpad, gst_event_new_segment (&seg)); + + + /* push Ok */ + next_return = GST_FLOW_OK; + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK); + + /* push not-linked */ + next_return = GST_FLOW_NOT_LINKED; + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED); + + /* push not-linked */ + next_return = GST_FLOW_NOT_NEGOTIATED; + fail_unless (gst_pad_push (srcpad, + gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED); + fail_unless (gst_pad_get_last_flow_return (srcpad) == + GST_FLOW_NOT_NEGOTIATED); + + /* push error */ + next_return = GST_FLOW_ERROR; + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_ERROR); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_ERROR); + + /* back to ok */ + next_return = GST_FLOW_OK; + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_OK); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_OK); + + /* unlinked push */ + gst_pad_unlink (srcpad, sinkpad); + fail_unless (gst_pad_push (srcpad, gst_buffer_new ()) == GST_FLOW_NOT_LINKED); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_NOT_LINKED); + + gst_pad_link (srcpad, sinkpad); + fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ())); + fail_unless (gst_pad_get_last_flow_return (srcpad) == GST_FLOW_EOS); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +static GstFlowReturn +test_lastflow_getrange (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) +{ + if (next_return == GST_FLOW_OK) + *buf = gst_buffer_new (); + else + *buf = NULL; + return next_return; +} + +static gboolean +test_lastflow_activate_pull_func (GstPad * pad, GstObject * object) +{ + return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); +} + +GST_START_TEST (test_last_flow_return_pull) +{ + GstPad *srcpad, *sinkpad; + GstBuffer *buf = NULL; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + gst_pad_set_getrange_function (srcpad, test_lastflow_getrange); + gst_pad_set_activate_function (sinkpad, test_lastflow_activate_pull_func); + gst_pad_link (srcpad, sinkpad); + + /* initial value is flushing */ + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_FLUSHING); + + /* when active it goes to ok */ + gst_pad_set_active (sinkpad, TRUE); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK); + gst_pad_set_active (srcpad, TRUE); + + /* pull Ok */ + next_return = GST_FLOW_OK; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK); + gst_buffer_unref (buf); + buf = NULL; + + /* pull not-linked */ + next_return = GST_FLOW_NOT_LINKED; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED); + + /* pull error */ + next_return = GST_FLOW_ERROR; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_ERROR); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_ERROR); + + /* pull not-nego */ + next_return = GST_FLOW_NOT_NEGOTIATED; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, + &buf) == GST_FLOW_NOT_NEGOTIATED); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == + GST_FLOW_NOT_NEGOTIATED); + + /* pull ok again */ + next_return = GST_FLOW_OK; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_OK); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_OK); + gst_buffer_unref (buf); + buf = NULL; + + /* unlinked pads */ + gst_pad_unlink (srcpad, sinkpad); + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_NOT_LINKED); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_NOT_LINKED); + + /* eos */ + gst_pad_link (srcpad, sinkpad); + next_return = GST_FLOW_EOS; + fail_unless (gst_pad_pull_range (sinkpad, 0, 1, &buf) == GST_FLOW_EOS); + fail_unless (gst_pad_get_last_flow_return (sinkpad) == GST_FLOW_EOS); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +GST_START_TEST (test_flush_stop_inactive) +{ + GstPad *sinkpad, *srcpad; + + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + fail_unless (sinkpad != NULL); + + /* new pads are inactive and flushing */ + fail_if (GST_PAD_IS_ACTIVE (sinkpad)); + fail_unless (GST_PAD_IS_FLUSHING (sinkpad)); + + /* this should fail, pad is inactive */ + fail_if (gst_pad_send_event (sinkpad, gst_event_new_flush_stop (FALSE))); + + /* nothing should have changed */ + fail_if (GST_PAD_IS_ACTIVE (sinkpad)); + fail_unless (GST_PAD_IS_FLUSHING (sinkpad)); + + gst_pad_set_active (sinkpad, TRUE); + + /* pad is now active an not flushing anymore */ + fail_unless (GST_PAD_IS_ACTIVE (sinkpad)); + fail_if (GST_PAD_IS_FLUSHING (sinkpad)); + + /* do flush, does not deactivate the pad */ + fail_unless (gst_pad_send_event (sinkpad, gst_event_new_flush_start ())); + fail_unless (GST_PAD_IS_ACTIVE (sinkpad)); + fail_unless (GST_PAD_IS_FLUSHING (sinkpad)); + + fail_unless (gst_pad_send_event (sinkpad, gst_event_new_flush_stop (FALSE))); + fail_unless (GST_PAD_IS_ACTIVE (sinkpad)); + fail_if (GST_PAD_IS_FLUSHING (sinkpad)); + + gst_pad_set_active (sinkpad, FALSE); + fail_if (GST_PAD_IS_ACTIVE (sinkpad)); + fail_unless (GST_PAD_IS_FLUSHING (sinkpad)); + + gst_object_unref (sinkpad); + + /* we should not be able to push on an inactive srcpad */ + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + + fail_if (GST_PAD_IS_ACTIVE (srcpad)); + fail_unless (GST_PAD_IS_FLUSHING (srcpad)); + + fail_if (gst_pad_push_event (srcpad, gst_event_new_flush_stop (FALSE))); + + /* should still be inactive and flushing */ + fail_if (GST_PAD_IS_ACTIVE (srcpad)); + fail_unless (GST_PAD_IS_FLUSHING (srcpad)); + + gst_pad_set_active (srcpad, TRUE); + + /* pad is now active an not flushing anymore */ + fail_unless (GST_PAD_IS_ACTIVE (srcpad)); + fail_if (GST_PAD_IS_FLUSHING (srcpad)); + + /* do flush, does not deactivate the pad */ + fail_if (gst_pad_push_event (srcpad, gst_event_new_flush_start ())); + fail_unless (GST_PAD_IS_ACTIVE (srcpad)); + fail_unless (GST_PAD_IS_FLUSHING (srcpad)); + + fail_if (gst_pad_push_event (srcpad, gst_event_new_flush_stop (FALSE))); + fail_unless (GST_PAD_IS_ACTIVE (srcpad)); + fail_if (GST_PAD_IS_FLUSHING (srcpad)); + + gst_pad_set_active (srcpad, FALSE); + fail_if (GST_PAD_IS_ACTIVE (srcpad)); + fail_unless (GST_PAD_IS_FLUSHING (srcpad)); + + gst_object_unref (srcpad); +} + +GST_END_TEST; + +/* For proxy caps flag tests */ + +typedef struct _GstProxyTestElement GstProxyTestElement; +typedef struct _GstProxyTestElementClass GstProxyTestElementClass; + +struct _GstProxyTestElement +{ + GstElement element; +}; + +struct _GstProxyTestElementClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_proxytestelement_get_type (void); + +static GstStaticPadTemplate proxytestelement_peer_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("test/proxy, option=(int)1")); + +static GstStaticPadTemplate proxytestelement_peer_incompatible_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("test/proxy-incompatible")); + +static GstStaticPadTemplate proxytestelement_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("test/proxy")); + +static GstStaticPadTemplate proxytestelement_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +G_DEFINE_TYPE (GstProxyTestElement, gst_proxytestelement, GST_TYPE_ELEMENT); + +static void +gst_proxytestelement_class_init (GstProxyTestElementClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_static_metadata (gstelement_class, + "Proxy Test Element", "Test", "Proxy test element", + "Thiago Santos "); + + gst_element_class_add_static_pad_template (gstelement_class, + &proxytestelement_sink_template); +} + +static void +gst_proxytestelement_init (GstProxyTestElement * element) +{ + GstPad *sinkpad; + sinkpad = + gst_pad_new_from_static_template (&proxytestelement_sink_template, + "sink"); + GST_PAD_SET_PROXY_CAPS (sinkpad); + gst_element_add_pad (GST_ELEMENT_CAST (element), sinkpad); +} + +GST_START_TEST (test_proxy_accept_caps_no_proxy) +{ + GstElement *element; + GstPad *sinkpad; + GstCaps *caps; + + gst_element_register (NULL, "proxytestelement", GST_RANK_NONE, + gst_proxytestelement_get_type ()); + element = gst_element_factory_make ("proxytestelement", NULL); + sinkpad = gst_element_get_static_pad (element, "sink"); + + gst_element_set_state (element, GST_STATE_PLAYING); + + caps = gst_caps_from_string ("test/proxy"); + fail_unless (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + caps = gst_caps_from_string ("test/bad"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + gst_object_unref (sinkpad); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); +} + +GST_END_TEST; + + +GST_START_TEST (test_proxy_accept_caps_with_proxy) +{ + GstElement *element; + GstPad *sinkpad, *srcpad; + GstPad *peerpad; + GstCaps *caps; + + gst_element_register (NULL, "proxytestelement", GST_RANK_NONE, + gst_proxytestelement_get_type ()); + element = gst_element_factory_make ("proxytestelement", NULL); + + srcpad = + gst_pad_new_from_static_template (&proxytestelement_src_template, "src"); + gst_element_add_pad (GST_ELEMENT_CAST (element), srcpad); + + sinkpad = gst_element_get_static_pad (element, "sink"); + srcpad = gst_element_get_static_pad (element, "src"); + + peerpad = + gst_pad_new_from_static_template (&proxytestelement_peer_template, + "sink"); + fail_unless (gst_pad_link (srcpad, peerpad) == GST_PAD_LINK_OK); + gst_pad_set_active (peerpad, TRUE); + + gst_element_set_state (element, GST_STATE_PLAYING); + + caps = gst_caps_from_string ("test/bad"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + caps = gst_caps_from_string ("test/proxy, option=(int)1"); + fail_unless (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + caps = gst_caps_from_string ("test/proxy, option=(int)2"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_pad_set_active (peerpad, FALSE); + gst_object_unref (peerpad); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_proxy_accept_caps_with_incompatible_proxy) +{ + GstElement *element; + GstPad *sinkpad, *srcpad; + GstPad *peerpad; + GstCaps *caps; + + gst_element_register (NULL, "proxytestelement", GST_RANK_NONE, + gst_proxytestelement_get_type ()); + element = gst_element_factory_make ("proxytestelement", NULL); + + srcpad = + gst_pad_new_from_static_template (&proxytestelement_src_template, "src"); + gst_element_add_pad (GST_ELEMENT_CAST (element), srcpad); + + sinkpad = gst_element_get_static_pad (element, "sink"); + srcpad = gst_element_get_static_pad (element, "src"); + + peerpad = + gst_pad_new_from_static_template + (&proxytestelement_peer_incompatible_template, "sink"); + fail_unless (gst_pad_link (srcpad, peerpad) == GST_PAD_LINK_OK); + + gst_element_set_state (element, GST_STATE_PLAYING); + + caps = gst_caps_from_string ("test/bad"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + caps = gst_caps_from_string ("test/proxy"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + caps = gst_caps_from_string ("test/proxy-incompatible"); + fail_if (gst_pad_query_accept_caps (sinkpad, caps)); + gst_caps_unref (caps); + + gst_object_unref (sinkpad); + gst_object_unref (srcpad); + gst_pad_set_active (peerpad, FALSE); + gst_object_unref (peerpad); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); +} + +GST_END_TEST; + +static GstSegment sink_segment; +static gint sink_segment_counter; + +static gboolean +segment_event_func (GstPad * pad, GstObject * parent, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEGMENT: + gst_event_copy_segment (event, &sink_segment); + sink_segment_counter++; + break; + default: + break; + } + + gst_event_unref (event); + return TRUE; +} + +static void +test_pad_offset (gboolean on_srcpad) +{ + GstPad *srcpad, *sinkpad, *offset_pad; + GstSegment segment; + GstBuffer *buffer; + GstQuery *query; + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + fail_unless (srcpad != NULL); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + + offset_pad = on_srcpad ? srcpad : sinkpad; + + gst_segment_init (&sink_segment, GST_FORMAT_UNDEFINED); + sink_segment_counter = 0; + gst_pad_set_chain_function (sinkpad, gst_check_chain_func); + gst_pad_set_event_function (sinkpad, segment_event_func); + + fail_unless (sinkpad != NULL); + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK); + fail_unless (gst_pad_set_active (sinkpad, TRUE)); + fail_unless (gst_pad_set_active (srcpad, TRUE)); + + /* Set an offset of 5s, meaning: + * segment position 0 gives running time 5s, stream time 0s + * segment start of 0 should stay 0 + */ + gst_pad_set_offset (offset_pad, 5 * GST_SECOND); + + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_stream_start ("test")) == TRUE); + /* We should have no segment event yet */ + fail_if (sink_segment.format != GST_FORMAT_UNDEFINED); + fail_unless_equals_int (sink_segment_counter, 0); + + /* Send segment event, expect it to arrive with a modified start running time */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_segment (&segment)) == TRUE); + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 1); + + /* Send a buffer and check if all timestamps are as expected, and especially + * if the buffer timestamp was not changed */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = 0 * GST_SECOND; + fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + buffer = buffers->data; + buffers = g_list_delete_link (buffers, buffers); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 0 * GST_SECOND); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0 * GST_SECOND); + gst_buffer_unref (buffer); + + fail_unless_equals_int (sink_segment_counter, 1); + + /* Set a negative offset of -5s, meaning: + * segment position 5s gives running time 0s, stream time 5s + * segment start would have a negative running time! + */ + gst_pad_set_offset (offset_pad, -5 * GST_SECOND); + + /* Segment should still be the same as before */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 1); + + /* Send segment event, expect it to arrive with a modified start running time */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_segment (&segment)) == TRUE); + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start + 5 * GST_SECOND), + 0 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start + 5 * GST_SECOND), + 5 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 2); + + /* Send a buffer and check if all timestamps are as expected, and especially + * if the buffer timestamp was not changed */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = 5 * GST_SECOND; + fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + buffer = buffers->data; + buffers = g_list_delete_link (buffers, buffers); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 0 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 5 * GST_SECOND); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 5 * GST_SECOND); + gst_buffer_unref (buffer); + + fail_unless_equals_int (sink_segment_counter, 2); + + /* Set offset to 5s again, same situation as above but don't send a new + * segment event. The segment should be adjusted *before* the buffer comes + * out of the srcpad */ + gst_pad_set_offset (offset_pad, 5 * GST_SECOND); + + /* Segment should still be the same as before */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start + 5 * GST_SECOND), + 0 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start + 5 * GST_SECOND), + 5 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 2); + + /* Send a buffer and check if a new segment event was sent and all buffer + * timestamps are as expected */ + buffer = gst_buffer_new (); + GST_BUFFER_PTS (buffer) = 0 * GST_SECOND; + fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK); + + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 3); + + fail_unless_equals_int (g_list_length (buffers), 1); + buffer = buffers->data; + buffers = g_list_delete_link (buffers, buffers); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, GST_BUFFER_PTS (buffer)), 0 * GST_SECOND); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0 * GST_SECOND); + gst_buffer_unref (buffer); + + fail_unless_equals_int (sink_segment_counter, 3); + + /* Set offset to 10s and send another sticky event. In between a new + * segment event should've been sent */ + gst_pad_set_offset (offset_pad, 10 * GST_SECOND); + + /* Segment should still be the same as before */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 5 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + fail_unless_equals_int (sink_segment_counter, 3); + + fail_unless (gst_pad_push_event (srcpad, + gst_event_new_tag (gst_tag_list_new_empty ())) == TRUE); + + /* Segment should be updated */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 10 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 4); + + /* Set offset to 15s and do a serialized query. In between a new + * segment event should've been sent */ + gst_pad_set_offset (offset_pad, 15 * GST_SECOND); + + /* Segment should still be the same as before */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 10 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + fail_unless_equals_int (sink_segment_counter, 4); + + query = gst_query_new_drain (); + gst_pad_peer_query (srcpad, query); + gst_query_unref (query); + + /* Segment should be updated */ + fail_if (sink_segment.format == GST_FORMAT_UNDEFINED); + fail_unless_equals_uint64 (gst_segment_to_running_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 15 * GST_SECOND); + fail_unless_equals_uint64 (gst_segment_to_stream_time (&sink_segment, + GST_FORMAT_TIME, sink_segment.start), 0 * GST_SECOND); + fail_unless_equals_uint64 (sink_segment.start, 0 * GST_SECOND); + + fail_unless_equals_int (sink_segment_counter, 5); + + gst_check_drop_buffers (); + + fail_unless (gst_pad_set_active (sinkpad, FALSE)); + fail_unless (gst_pad_set_active (srcpad, FALSE)); + gst_object_unref (sinkpad); + gst_object_unref (srcpad); +} + +GST_START_TEST (test_pad_offset_src) +{ + test_pad_offset (TRUE); +} + +GST_END_TEST; + +static Suite * +gst_pad_suite (void) +{ + Suite *s = suite_create ("GstPad"); + TCase *tc_chain = tcase_create ("general"); + + /* turn off timeout */ + tcase_set_timeout (tc_chain, 60); + + gst_segment_init (&dummy_segment, GST_FORMAT_BYTES); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_link); + tcase_add_test (tc_chain, test_refcount); + tcase_add_test (tc_chain, test_get_allowed_caps); + tcase_add_test (tc_chain, test_sticky_caps_unlinked); + tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible); + tcase_add_test (tc_chain, test_sticky_caps_flushing); + tcase_add_test (tc_chain, test_default_accept_caps); + tcase_add_test (tc_chain, test_link_unlink_threaded); + tcase_add_test (tc_chain, test_name_is_valid); + tcase_add_test (tc_chain, test_push_unlinked); + tcase_add_test (tc_chain, test_push_linked); + tcase_add_test (tc_chain, test_push_linked_flushing); + tcase_add_test (tc_chain, test_push_buffer_list_compat); + tcase_add_test (tc_chain, test_flowreturn); + tcase_add_test (tc_chain, test_push_negotiation); + tcase_add_test (tc_chain, test_src_unref_unlink); + tcase_add_test (tc_chain, test_sink_unref_unlink); + tcase_add_test (tc_chain, test_block_async); + tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block); + tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking); + tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_idle); + tcase_add_test (tc_chain, test_pad_probe_pull); + tcase_add_test (tc_chain, test_pad_probe_pull_idle); + tcase_add_test (tc_chain, test_pad_probe_pull_buffer); + tcase_add_test (tc_chain, test_pad_probe_remove); + tcase_add_test (tc_chain, test_pad_probe_block_add_remove); + tcase_add_test (tc_chain, test_pad_probe_block_and_drop_buffer); + tcase_add_test (tc_chain, test_pad_probe_flush_events); + tcase_add_test (tc_chain, test_pad_probe_flush_events_only); + tcase_add_test (tc_chain, test_pad_probe_call_order); + tcase_add_test (tc_chain, test_pad_probe_handled_and_drop); + tcase_add_test (tc_chain, test_events_query_unlinked); + tcase_add_test (tc_chain, test_queue_src_caps_notify_linked); + tcase_add_test (tc_chain, test_queue_src_caps_notify_not_linked); +#if 0 + tcase_add_test (tc_chain, test_block_async_replace_callback); +#endif + tcase_add_test (tc_chain, test_block_async_full_destroy); + tcase_add_test (tc_chain, test_block_async_full_destroy_dispose); + tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush); + tcase_add_test (tc_chain, test_sticky_events); + tcase_add_test (tc_chain, test_last_flow_return_push); + tcase_add_test (tc_chain, test_last_flow_return_pull); + tcase_add_test (tc_chain, test_flush_stop_inactive); + tcase_add_test (tc_chain, test_proxy_accept_caps_no_proxy); + tcase_add_test (tc_chain, test_proxy_accept_caps_with_proxy); + tcase_add_test (tc_chain, test_proxy_accept_caps_with_incompatible_proxy); + tcase_add_test (tc_chain, test_pad_offset_src); + + return s; +} + +GST_CHECK_MAIN (gst_pad); diff --git a/tests/check/gst/gstparamspecs.c b/tests/check/gst/gstparamspecs.c new file mode 100644 index 0000000..696c62b --- /dev/null +++ b/tests/check/gst/gstparamspecs.c @@ -0,0 +1,132 @@ +/* GStreamer GstParamSpec unit tests + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +/* some minimal dummy object */ +#define GST_TYPE_DUMMY_OBJ gst_dummy_obj_get_type() + +typedef struct +{ + GstElement parent; + guint num, denom; +} GstDummyObj; + +typedef GstElementClass GstDummyObjClass; + +GType gst_dummy_obj_get_type (void); +G_DEFINE_TYPE (GstDummyObj, gst_dummy_obj, GST_TYPE_ELEMENT); + +static void +gst_dummy_obj_get_property (GObject * obj, guint prop_id, GValue * val, + GParamSpec * pspec); +static void +gst_dummy_obj_set_property (GObject * obj, guint prop_id, const GValue * val, + GParamSpec * pspec); + +static void +gst_dummy_obj_class_init (GstDummyObjClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gst_dummy_obj_get_property; + gobject_class->set_property = gst_dummy_obj_set_property; + + ASSERT_CRITICAL ( + /* default value is out of bounds, should print a warning */ + g_object_class_install_property (gobject_class, 1, + gst_param_spec_fraction ("ratio", "ratio", "ratio", 0, 1, 2, 1, + 16, 4, G_PARAM_READWRITE)); + ); + + /* should be within bounds */ + g_object_class_install_property (gobject_class, 2, + gst_param_spec_fraction ("other-ratio", "other ratio", "other ratio", + 0, 1, 2, 1, 16, 9, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, 3, + g_param_spec_boolean ("foo", "foo", "foo", TRUE, G_PARAM_READWRITE)); +} + +static void +gst_dummy_obj_init (GstDummyObj * obj) +{ + /* nothing to do there */ +} + +static void +gst_dummy_obj_set_property (GObject * obj, guint prop_id, const GValue * val, + GParamSpec * pspec) +{ + GstDummyObj *dobj = (GstDummyObj *) obj; + + fail_unless_equals_int (prop_id, 2); + dobj->num = gst_value_get_fraction_numerator (val); + dobj->denom = gst_value_get_fraction_denominator (val); +} + +static void +gst_dummy_obj_get_property (GObject * obj, guint prop_id, GValue * val, + GParamSpec * pspec) +{ + GstDummyObj *dobj = (GstDummyObj *) obj; + + fail_unless_equals_int (prop_id, 2); + gst_value_set_fraction (val, dobj->num, dobj->denom); +} + +GST_START_TEST (test_param_spec_fraction) +{ + GObject *obj; + GValue val = { 0, }; + gint n = 0, d = 0; + + obj = g_object_new (GST_TYPE_DUMMY_OBJ, "other-ratio", 15, 8, NULL); + + g_value_init (&val, GST_TYPE_FRACTION); + g_object_get_property (G_OBJECT (obj), "other-ratio", &val); + fail_unless_equals_int (gst_value_get_fraction_numerator (&val), 15); + fail_unless_equals_int (gst_value_get_fraction_denominator (&val), 8); + g_value_unset (&val); + + g_object_get (obj, "other-ratio", &n, &d, NULL); + fail_unless_equals_int (n, 15); + fail_unless_equals_int (d, 8); + + g_object_unref (obj); +} + +GST_END_TEST static Suite * +gst_param_spec_suite (void) +{ + Suite *s = suite_create ("GstParamSpec"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_param_spec_fraction); + + return s; +} + +GST_CHECK_MAIN (gst_param_spec); diff --git a/tests/check/gst/gstpipeline.c b/tests/check/gst/gstpipeline.c new file mode 100644 index 0000000..6a317f0 --- /dev/null +++ b/tests/check/gst/gstpipeline.c @@ -0,0 +1,688 @@ +/* GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * + * gstpipeline.c: Unit test for GstPipeline + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define WAIT_TIME (300 * GST_MSECOND) + +/* an empty pipeline can go to PLAYING in one go */ +GST_START_TEST (test_async_state_change_empty) +{ + GstPipeline *pipeline; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_async_state_change_fake_ready) +{ + GstPipeline *pipeline; + GstElement *src, *sink; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + + fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_READY), GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_async_state_change_fake) +{ + GstPipeline *pipeline; + GstElement *src, *sink; + GstBus *bus; + gboolean done = FALSE; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + + bus = gst_pipeline_get_bus (pipeline); + + fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *message; + GstState old, new, pending; + + message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1); + if (message) { + gst_message_parse_state_changed (message, &old, &new, &pending); + GST_DEBUG_OBJECT (message->src, "state change from %d to %d", old, new); + if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING) + done = TRUE; + gst_message_unref (message); + } + } + + fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline), + GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS); + + /* here we don't get the state change messages, because of auto-flush in + * the bus */ + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_get_bus) +{ + GstPipeline *pipeline; + GstBus *bus; + + pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); + fail_unless (pipeline != NULL, "Could not create pipeline"); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + bus = gst_pipeline_get_bus (pipeline); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1); + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + + /* bindings don't like the floating flag to be set here */ + fail_if (g_object_is_floating (bus)); + + gst_object_unref (pipeline); + + ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1); + gst_object_unref (bus); +} + +GST_END_TEST; + +static GMainLoop *loop = NULL; + +static gboolean +message_received (GstBus * bus, GstMessage * message, gpointer data) +{ + GstElement *pipeline = GST_ELEMENT (data); + GstMessageType type = message->type; + + GST_DEBUG ("message received"); + switch (type) { + case GST_MESSAGE_STATE_CHANGED: + { + GstState old, new, pending; + + GST_DEBUG ("state change message received"); + gst_message_parse_state_changed (message, &old, &new, &pending); + GST_DEBUG ("new state %d", new); + if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING) { + GST_DEBUG ("quitting main loop"); + g_main_loop_quit (loop); + } + } + break; + case GST_MESSAGE_ERROR: + { + g_print ("error\n"); + } + break; + default: + break; + } + + return TRUE; +} + +GST_START_TEST (test_bus) +{ + GstElement *pipeline; + GstElement *src, *sink; + GstBus *bus; + guint id; + GstState current; + GstStateChangeReturn ret; + + pipeline = gst_pipeline_new (NULL); + fail_unless (pipeline != NULL, "Could not create pipeline"); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_unless (src != NULL); + sink = gst_element_factory_make ("fakesink", NULL); + fail_unless (sink != NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + fail_unless (gst_element_link (src, sink)); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1); + ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); + + id = gst_bus_add_watch (bus, message_received, pipeline); + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after add_watch", 1); + ASSERT_OBJECT_REFCOUNT (bus, "bus after add_watch", 3); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + loop = g_main_loop_new (NULL, FALSE); + GST_DEBUG ("going into main loop"); + g_main_loop_run (loop); + GST_DEBUG ("left main loop"); + + /* PLAYING now */ + + ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline after gone to playing", 1, + 3); + + /* cleanup */ + GST_DEBUG ("cleanup"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + ret = gst_element_get_state (pipeline, ¤t, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + fail_unless (current == GST_STATE_NULL, "state is not NULL but %d", current); + + ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline at start of cleanup", 1); + ASSERT_OBJECT_REFCOUNT (bus, "bus at start of cleanup", 3); + + fail_unless (g_source_remove (id)); + ASSERT_OBJECT_REFCOUNT (bus, "bus after removing source", 2); + + GST_DEBUG ("unreffing pipeline"); + gst_object_unref (pipeline); + + ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1); + gst_object_unref (bus); +} + +GST_END_TEST; + +static GMutex probe_lock; +static GCond probe_cond; + +static GstPadProbeReturn +sink_pad_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstClockTime *first_timestamp = user_data; + GstBuffer *buffer; + + fail_unless ((GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER)); + + buffer = GST_BUFFER (info->data); + + GST_LOG_OBJECT (pad, "buffer with timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + + fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE, + "testing if buffer timestamps are right, but got CLOCK_TIME_NONE"); + + if (*first_timestamp == GST_CLOCK_TIME_NONE) { + *first_timestamp = GST_BUFFER_TIMESTAMP (buffer); + } + + g_mutex_lock (&probe_lock); + g_cond_signal (&probe_cond); + g_mutex_unlock (&probe_lock); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_base_time) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstPad *sink; + GstClockTime observed, lower, upper, base, stream; + GstClock *clock; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements"); + + g_object_set (fakesrc, "is-live", (gboolean) TRUE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + sink = gst_element_get_static_pad (fakesink, "sink"); + gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_BUFFER, sink_pad_probe, + &observed, NULL); + + fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED) + == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline"); + + clock = gst_system_clock_obtain (); + fail_unless (clock && GST_IS_CLOCK (clock), "i want a clock dammit"); + gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock); + + fail_unless (gst_element_get_start_time (pipeline) == 0, + "stream time doesn't start off at 0"); + + /* test the first: that base time is being distributed correctly, timestamps + are correct relative to the running clock and base time */ + { + lower = gst_clock_get_time (clock); + + observed = GST_CLOCK_TIME_NONE; + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_SUCCESS, "failed state change"); + + g_mutex_lock (&probe_lock); + while (observed == GST_CLOCK_TIME_NONE) + g_cond_wait (&probe_cond, &probe_lock); + g_mutex_unlock (&probe_lock); + + /* now something a little more than lower was distributed as the base time, + * and the buffer was timestamped between 0 and upper-base + */ + + base = gst_element_get_base_time (pipeline); + fail_if (base == GST_CLOCK_TIME_NONE); + + /* set stream time */ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* pulling upper here makes sure that the pipeline's new stream time has + already been computed */ + upper = gst_clock_get_time (clock); + + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_NO_PREROLL, "failed state change"); + + fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded"); + + fail_unless (base >= lower, "early base time: %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (lower)); + fail_unless (upper >= base, "bogus base time: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (upper)); + + stream = gst_element_get_start_time (pipeline); + + fail_unless (stream > 0, "bogus new stream time: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, GST_TIME_ARGS (stream), GST_TIME_ARGS (0)); + fail_unless (stream <= upper, + "bogus new stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream), GST_TIME_ARGS (upper)); + + fail_unless (observed <= stream, "timestamps outrun stream time: %" + GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (stream)); + fail_unless (observed != GST_CLOCK_TIME_NONE, "early timestamp: %" + GST_TIME_FORMAT " < %" GST_TIME_FORMAT, GST_TIME_ARGS (observed), + GST_TIME_ARGS (lower - base)); + fail_unless (observed <= upper - base, + "late timestamp: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base)); + } + + /* test the second: that the base time is redistributed when we go to PLAYING + again */ + { + GstClockID clock_id; + GstClockTime oldbase = base, oldstream = stream; + + /* let some time pass */ + clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME); + fail_unless (gst_clock_id_wait (clock_id, NULL) == GST_CLOCK_OK, + "unexpected clock_id_wait return"); + gst_clock_id_unref (clock_id); + + lower = gst_clock_get_time (clock); + fail_if (lower == GST_CLOCK_TIME_NONE); + + observed = GST_CLOCK_TIME_NONE; + + fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_SUCCESS, "failed state change"); + + g_mutex_lock (&probe_lock); + while (observed == GST_CLOCK_TIME_NONE) + g_cond_wait (&probe_cond, &probe_lock); + g_mutex_unlock (&probe_lock); + + /* now the base time should have advanced by more than WAIT_TIME compared + * to what it was. The buffer will be timestamped between the last stream + * time and upper minus base. + */ + + base = gst_element_get_base_time (pipeline); + fail_if (base == GST_CLOCK_TIME_NONE); + + /* set stream time */ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* new stream time already set */ + upper = gst_clock_get_time (clock); + + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_NO_PREROLL, "failed state change"); + + fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded"); + + stream = gst_element_get_start_time (pipeline); + + fail_unless (base >= oldbase + WAIT_TIME, "base time not reset"); + fail_unless (upper >= base + stream, "bogus base time: %" + GST_TIME_FORMAT " > %" GST_TIME_FORMAT, GST_TIME_ARGS (base), + GST_TIME_ARGS (upper)); + + fail_unless (lower >= base); + fail_unless (observed >= lower - base, "early timestamp: %" + GST_TIME_FORMAT " < %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base)); + fail_unless (observed <= upper - base, "late timestamp: %" + GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base)); + fail_unless (stream - oldstream <= upper - lower, + "insufficient stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper)); + } + + /* test the third: that if I set CLOCK_TIME_NONE as the stream time, that the + base time is not changed */ + { + GstClockID clock_id; + GstClockTime oldbase = base, oldobserved = observed; + GstClockReturn ret; + + /* let some time pass */ + clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME); + ret = gst_clock_id_wait (clock_id, NULL); + fail_unless (ret == GST_CLOCK_OK, + "unexpected clock_id_wait return %d", ret); + gst_clock_id_unref (clock_id); + + lower = gst_clock_get_time (clock); + + observed = GST_CLOCK_TIME_NONE; + + fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?"); + + /* bling */ + gst_element_set_start_time (pipeline, GST_CLOCK_TIME_NONE); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_SUCCESS, "failed state change"); + + g_mutex_lock (&probe_lock); + while (observed == GST_CLOCK_TIME_NONE) + g_cond_wait (&probe_cond, &probe_lock); + g_mutex_unlock (&probe_lock); + + /* now the base time should be the same as it was, and the timestamp should + * be more than WAIT_TIME past what it was. + */ + + base = gst_element_get_base_time (pipeline); + + /* set stream time */ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* new stream time already set */ + upper = gst_clock_get_time (clock); + + fail_unless (gst_element_get_state (pipeline, NULL, NULL, + GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_NO_PREROLL, "failed state change"); + + fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded"); + + fail_unless (gst_element_get_start_time (pipeline) + == GST_CLOCK_TIME_NONE, "stream time was reset"); + + fail_unless (base == oldbase, "base time was reset"); + + fail_unless (observed >= lower - base, "early timestamp: %" + GST_TIME_FORMAT " < %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base)); + fail_unless (observed <= upper - base, "late timestamp: %" + GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base)); + fail_unless (observed - oldobserved >= WAIT_TIME, + "insufficient tstamp delta: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (oldobserved)); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (sink); + gst_object_unref (clock); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static gpointer +pipeline_thread (gpointer data) +{ + GstElement *pipeline, *src, *sink; + + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", 20, NULL); + sink = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink, "sync", TRUE, NULL); + pipeline = gst_pipeline_new (NULL); + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), sink); + gst_element_link (src, sink); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + g_usleep (G_USEC_PER_SEC / 10); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return NULL; +} + +GST_START_TEST (test_concurrent_create) +{ + GThread *threads[30]; + int i; + + for (i = 0; i < G_N_ELEMENTS (threads); ++i) { + threads[i] = g_thread_try_new ("gst-check", pipeline_thread, NULL, NULL); + } + for (i = 0; i < G_N_ELEMENTS (threads); ++i) { + if (threads[i]) + g_thread_join (threads[i]); + } +} + +GST_END_TEST; + +GST_START_TEST (test_pipeline_in_pipeline) +{ + GstElement *pipeline, *bin, *fakesrc, *fakesink; + GstMessage *msg; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + bin = gst_element_factory_make ("pipeline", "pipeline-as-bin"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + fail_unless (pipeline && bin && fakesrc && fakesink); + + g_object_set (fakesrc, "num-buffers", 100, NULL); + + gst_bin_add (GST_BIN (pipeline), bin); + gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + 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_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_pipeline_reset_start_time) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstState state; + GstClock *clock; + GstClockID id; + gint64 position; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + /* no more than 100 buffers per second */ + g_object_set (fakesrc, "do-timestamp", TRUE, "format", GST_FORMAT_TIME, + "sizetype", 2, "sizemax", 4096, "datarate", 4096 * 100, NULL); + + g_object_set (fakesink, "sync", TRUE, NULL); + + fail_unless (pipeline && fakesrc && fakesink); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + fail_unless (gst_element_get_start_time (fakesink) == 0); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (state, GST_STATE_PLAYING); + + /* We just started and never paused, start time must be 0 */ + fail_unless (gst_element_get_start_time (fakesink) == 0); + + clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline)); + fail_unless (clock != NULL); + id = gst_clock_new_single_shot_id (clock, + gst_element_get_base_time (pipeline) + 55 * GST_MSECOND); + gst_clock_id_wait (id, NULL); + gst_clock_id_unref (id); + gst_object_unref (clock); + + /* We waited 50ms, so the position should be now >= 50ms */ + fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME, + &position)); + fail_unless (position >= 50 * GST_MSECOND, + "Pipeline position is not at least 50millisecond (reported %" + G_GUINT64_FORMAT " nanoseconds)", position); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (state, GST_STATE_PAUSED); + + /* And now after pausing the start time should be bigger than the last + * position */ + fail_unless (gst_element_get_start_time (fakesink) >= 50 * GST_MSECOND); + fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME, + &position)); + fail_unless (position >= 50 * GST_MSECOND); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + + /* When going back to ready the start time should be reset everywhere */ + fail_unless (gst_element_get_start_time (fakesink) == 0); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (state, GST_STATE_PAUSED); + + /* And the start time should still be set to 0 when we go to paused for the + * first time. Same goes for the position */ + fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME, + &position)); + fail_unless (position < 50 * GST_MSECOND); + + fail_unless (gst_element_get_start_time (fakesink) == 0); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +gst_pipeline_suite (void) +{ + Suite *s = suite_create ("GstPipeline"); + TCase *tc_chain = tcase_create ("pipeline tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_async_state_change_empty); + tcase_add_test (tc_chain, test_async_state_change_fake_ready); + tcase_add_test (tc_chain, test_async_state_change_fake); + tcase_add_test (tc_chain, test_get_bus); + tcase_add_test (tc_chain, test_bus); + tcase_add_test (tc_chain, test_base_time); + tcase_add_test (tc_chain, test_concurrent_create); + tcase_add_test (tc_chain, test_pipeline_in_pipeline); + tcase_add_test (tc_chain, test_pipeline_reset_start_time); + + return s; +} + +GST_CHECK_MAIN (gst_pipeline); diff --git a/tests/check/gst/gstplugin.c b/tests/check/gst/gstplugin.c new file mode 100644 index 0000000..4550bca --- /dev/null +++ b/tests/check/gst/gstplugin.c @@ -0,0 +1,333 @@ +/* GStreamer + * + * unit test for GstPlugin + * + * Copyright 2004 Thomas Vander Stichele + * Copyright 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +static gboolean +register_check_elements (GstPlugin * plugin) +{ + return TRUE; +} + +GST_START_TEST (test_register_static) +{ + GstPlugin *plugin; + + fail_unless (gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, "more-elements", "more-elements", + register_check_elements, VERSION, GST_LICENSE, PACKAGE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)); + + plugin = g_object_new (GST_TYPE_PLUGIN, NULL); + + gst_object_unref (plugin); +} + +GST_END_TEST; + +GST_START_TEST (test_registry) +{ + GList *list, *g; + GstRegistry *registry; + + registry = gst_registry_get (); + + list = gst_registry_get_plugin_list (registry); + for (g = list; g; g = g->next) { + GstPlugin *plugin = GST_PLUGIN (g->data); + + /* one for the registry, one for the list */ + GST_DEBUG ("Plugin refcount %d %s", GST_OBJECT_REFCOUNT_VALUE (plugin), + gst_plugin_get_name (plugin)); + ASSERT_OBJECT_REFCOUNT (plugin, "plugin in registry", 2); + + gst_object_unref (plugin); + } + g_list_free (list); + + list = gst_registry_feature_filter (registry, NULL, FALSE, NULL); + for (g = list; g; g = g->next) { + GstPluginFeature *feature = GST_PLUGIN_FEATURE (g->data); + + /* one for the registry, one for the list */ + GST_DEBUG ("Feature refcount %d %s", GST_OBJECT_REFCOUNT_VALUE (feature), + GST_OBJECT_NAME (feature)); + gst_object_unref (feature); + } + g_list_free (list); +} + +GST_END_TEST; + +GST_START_TEST (test_load_coreelements) +{ + GstPlugin *unloaded_plugin; + GstPlugin *loaded_plugin; + + unloaded_plugin = gst_registry_find_plugin (gst_registry_get (), + "coreelements"); + fail_if (unloaded_plugin == NULL, "Failed to find coreelements plugin"); + fail_if (GST_OBJECT_REFCOUNT_VALUE (unloaded_plugin) != 2, + "Refcount of unloaded plugin in registry initially should be 2"); + GST_DEBUG ("refcount %d", GST_OBJECT_REFCOUNT_VALUE (unloaded_plugin)); + + loaded_plugin = gst_plugin_load (unloaded_plugin); + fail_if (loaded_plugin == NULL, "Failed to load plugin"); + + if (loaded_plugin != unloaded_plugin) { + fail_if (GST_OBJECT_REFCOUNT_VALUE (loaded_plugin) != 2, + "Refcount of loaded plugin in registry should be 2"); + GST_DEBUG ("refcount %d", GST_OBJECT_REFCOUNT_VALUE (loaded_plugin)); + fail_if (GST_OBJECT_REFCOUNT_VALUE (unloaded_plugin) != 1, + "Refcount of replaced plugin should be 1"); + GST_DEBUG ("refcount %d", GST_OBJECT_REFCOUNT_VALUE (unloaded_plugin)); + } + + gst_object_unref (unloaded_plugin); + gst_object_unref (loaded_plugin); +} + +GST_END_TEST; + +GST_START_TEST (test_registry_get_plugin_list) +{ + GList *list; + GstPlugin *plugin; + + plugin = gst_registry_find_plugin (gst_registry_get (), "coreelements"); + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 2, + "Refcount of plugin in registry should be 2"); + + list = gst_registry_get_plugin_list (gst_registry_get ()); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 3, + "Refcount of plugin in registry+list should be 3"); + + gst_plugin_list_free (list); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 2, + "Refcount of plugin in after list free should be 2"); + + gst_object_unref (plugin); +} + +GST_END_TEST; + +GST_START_TEST (test_find_plugin) +{ + GstPlugin *plugin; + + plugin = gst_registry_find_plugin (gst_registry_get (), "coreelements"); + fail_if (plugin == NULL, "Failed to find coreelements plugin"); + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 2); + + fail_unless_equals_string (gst_plugin_get_version (plugin), VERSION); + fail_unless_equals_string (gst_plugin_get_license (plugin), "LGPL"); + fail_unless_equals_string (gst_plugin_get_source (plugin), "gstreamer"); + fail_unless_equals_string (gst_plugin_get_package (plugin), GST_PACKAGE_NAME); + fail_unless_equals_string (gst_plugin_get_origin (plugin), + GST_PACKAGE_ORIGIN); + + gst_object_unref (plugin); +} + +GST_END_TEST; + + +GST_START_TEST (test_find_feature) +{ + GstPluginFeature *feature; + GstPlugin *plugin; + + feature = gst_registry_find_feature (gst_registry_get (), + "identity", GST_TYPE_ELEMENT_FACTORY); + fail_if (feature == NULL, "Failed to find identity element factory"); + + plugin = gst_plugin_feature_get_plugin (feature); + fail_unless (plugin != NULL); + fail_unless_equals_string (gst_plugin_get_name (plugin), "coreelements"); + gst_object_unref (plugin); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (feature) != 2, + "Refcount of feature should be 2"); + GST_DEBUG ("refcount %d", GST_OBJECT_REFCOUNT_VALUE (feature)); + + gst_object_unref (feature); +} + +GST_END_TEST; + +GST_START_TEST (test_find_element) +{ + GstElementFactory *element_factory; + + element_factory = gst_element_factory_find ("identity"); + fail_if (element_factory == NULL, "Failed to find identity element factory"); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (element_factory) != 2, + "Refcount of plugin in registry+feature should be 2"); + + gst_object_unref (element_factory); +} + +GST_END_TEST; + +#if 0 +guint8 * +peek (gpointer data, gint64 offset, guint size) +{ + return NULL; +} + +void +suggest (gpointer data, guint probability, const GstCaps * caps) +{ + +} + +GST_START_TEST (test_typefind) +{ + GstPlugin *plugin; + GstPluginFeature *feature; + GstTypeFind typefind = { + peek, + suggest, + NULL, + NULL, + GST_PADDING_INIT + }; + + plugin = gst_default_registry_find_plugin ("typefindfunctions"); + fail_if (plugin == NULL, "Failed to find typefind functions"); + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 2, + "Refcount of plugin in registry should be 2"); + fail_if (gst_plugin_is_loaded (plugin), "Expected plugin to be unloaded"); + + feature = gst_registry_find_feature (gst_registry_get (), + "audio/x-au", GST_TYPE_TYPE_FIND_FACTORY); + fail_if (feature == NULL, "Failed to find audio/x-aw typefind factory"); + fail_if (feature->plugin != plugin, + "Expected identity to be from coreelements plugin"); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 3, + "Refcount of plugin in registry+feature should be 3"); + + gst_type_find_factory_call_function (GST_TYPE_FIND_FACTORY (feature), + &typefind); + + gst_object_unref (feature->plugin); + + fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 1, + "Refcount of plugin in after list free should be 1"); + + gst_object_unref (plugin); +} + +GST_END_TEST; +#endif + +#define gst_default_registry_check_feature_version(name,a,b,c) \ + gst_registry_check_feature_version(gst_registry_get(),(name),(a),(b),(c)) + +GST_START_TEST (test_version_checks) +{ + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO) == FALSE, + "Unexpected version check result"); + + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR + 1, GST_VERSION_MINOR, GST_VERSION_MICRO) == TRUE, + "Unexpected version check result"); + + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR + 1, GST_VERSION_MICRO) == TRUE, + "Unexpected version check result"); + + /* If the nano is set, then we expect that X.Y.Z-1.x >= X.Y.Z, so that a + * devel plugin is valid against an upcoming release */ + if (GST_VERSION_NANO > 0) { + fail_unless (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO + 1) == + TRUE, "Unexpected version check result"); + } else { + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO + 1) == + TRUE, "Unexpected version check result"); + } + + if (GST_VERSION_MAJOR > 0) { + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR - 1, GST_VERSION_MINOR, + GST_VERSION_MICRO) == FALSE, "Unexpected version check result"); + } + + if (GST_VERSION_MINOR > 0) { + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR - 1, + GST_VERSION_MICRO) == FALSE, "Unexpected version check result"); + } + + if (GST_VERSION_MICRO > 0) { + fail_if (gst_default_registry_check_feature_version ("identity", + GST_VERSION_MAJOR, GST_VERSION_MINOR, + GST_VERSION_MICRO - 1) == FALSE, "Unexpected version check result"); + } + + fail_if (gst_default_registry_check_feature_version ("entityid", + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO) == TRUE, + "Unexpected version check result"); +} + +GST_END_TEST; + +static Suite * +gst_plugin_suite (void) +{ + Suite *s = suite_create ("GstPlugin"); + TCase *tc_chain = tcase_create ("general"); + + /* turn off timeout */ + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); +#ifdef GST_GNUC_CONSTRUCTOR_DEFINED + tcase_add_test (tc_chain, test_old_register_static); +#endif + tcase_add_test (tc_chain, test_register_static); + tcase_add_test (tc_chain, test_registry); + tcase_add_test (tc_chain, test_load_coreelements); + tcase_add_test (tc_chain, test_registry_get_plugin_list); + tcase_add_test (tc_chain, test_find_plugin); + tcase_add_test (tc_chain, test_find_feature); + tcase_add_test (tc_chain, test_find_element); + tcase_add_test (tc_chain, test_version_checks); + //tcase_add_test (tc_chain, test_typefind); + + return s; +} + +GST_CHECK_MAIN (gst_plugin); diff --git a/tests/check/gst/gstpoll.c b/tests/check/gst/gstpoll.c new file mode 100644 index 0000000..78e73ef --- /dev/null +++ b/tests/check/gst/gstpoll.c @@ -0,0 +1,354 @@ +/* GStreamer + * + * unit test for GstPoll + * + * Copyright (C) <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef G_OS_WIN32 +#include +#include +#else +#include +#include +#endif + +GST_START_TEST (test_poll_wait) +{ + GstPoll *set; + GstPollFD rfd = GST_POLL_FD_INIT; + GstPollFD wfd = GST_POLL_FD_INIT; + gint socks[2]; + guchar c = 'A'; + + set = gst_poll_new (FALSE); + fail_if (set == NULL, "Failed to create a GstPoll"); + +#ifdef G_OS_WIN32 + fail_if (_pipe (socks, 4096, _O_BINARY) < 0, "Could not create a pipe"); +#else + fail_if (socketpair (PF_UNIX, SOCK_STREAM, 0, socks) < 0, + "Could not create a pipe"); +#endif + rfd.fd = socks[0]; + wfd.fd = socks[1]; + + fail_unless (gst_poll_add_fd (set, &rfd), "Could not add read descriptor"); + fail_unless (gst_poll_fd_ctl_read (set, &rfd, TRUE), + "Could not mark the descriptor as readable"); + + fail_unless (write (wfd.fd, &c, 1) == 1, "write() failed"); + + fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 1, + "One descriptor should be available"); + fail_unless (gst_poll_fd_can_read (set, &rfd), + "Read descriptor should be readable"); + fail_if (gst_poll_fd_can_write (set, &rfd), + "Read descriptor should not be writeable"); + + fail_unless (gst_poll_add_fd (set, &wfd), "Could not add write descriptor"); + fail_unless (gst_poll_fd_ctl_write (set, &wfd, TRUE), + "Could not mark the descriptor as writeable"); + + fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 2, + "Two descriptors should be available"); + fail_unless (gst_poll_fd_can_read (set, &rfd), + "Read descriptor should be readable"); + fail_if (gst_poll_fd_can_write (set, &rfd), + "Read descriptor should not be writeable"); + fail_if (gst_poll_fd_can_read (set, &wfd), + "Write descriptor should not be readable"); + fail_unless (gst_poll_fd_can_write (set, &wfd), + "Write descriptor should be writeable"); + + fail_unless (read (rfd.fd, &c, 1) == 1, "read() failed"); + + fail_unless (gst_poll_wait (set, GST_CLOCK_TIME_NONE) == 1, + "One descriptor should be available"); + fail_if (gst_poll_fd_can_read (set, &rfd), + "Read descriptor should not be readable"); + fail_if (gst_poll_fd_can_write (set, &rfd), + "Read descriptor should not be writeable"); + fail_if (gst_poll_fd_can_read (set, &wfd), + "Write descriptor should not be readable"); + fail_unless (gst_poll_fd_can_write (set, &wfd), + "Write descriptor should be writeable"); + + gst_poll_free (set); + close (socks[0]); + close (socks[1]); +} + +GST_END_TEST; + +GST_START_TEST (test_poll_basic) +{ + GstPoll *set; + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = 1; + + set = gst_poll_new (FALSE); + fail_if (set == NULL, "Failed to create a GstPoll"); + + fail_unless (gst_poll_add_fd (set, &fd), "Could not add descriptor"); + fail_unless (gst_poll_fd_ctl_write (set, &fd, TRUE), + "Could not mark the descriptor as writeable"); + fail_unless (gst_poll_fd_ctl_read (set, &fd, TRUE), + "Could not mark the descriptor as readable"); + fail_if (gst_poll_fd_has_closed (set, &fd), + "Descriptor should not be closed"); + fail_if (gst_poll_fd_has_error (set, &fd), + "Descriptor should not have an error"); + fail_if (gst_poll_fd_can_write (set, &fd), + "Descriptor should not be writeable"); + fail_if (gst_poll_fd_can_read (set, &fd), + "Descriptor should not be readable"); + fail_unless (gst_poll_remove_fd (set, &fd), "Could not remove descriptor"); + + fail_if (gst_poll_remove_fd (set, &fd), + "Could remove already removed descriptor"); + + fail_unless (gst_poll_wait (set, 50 * GST_MSECOND) == 0, + "Waiting did not timeout"); + + gst_poll_free (set); + + set = gst_poll_new (TRUE); + fail_if (set == NULL, "Failed to create a GstPoll"); + gst_poll_set_flushing (set, TRUE); + gst_poll_free (set); +} + +GST_END_TEST; + +static gpointer +delayed_stop (gpointer data) +{ + GstPoll *set = data; + + THREAD_START (); + + g_usleep (500000); + + gst_poll_set_flushing (set, TRUE); + + return NULL; +} + +GST_START_TEST (test_poll_wait_stop) +{ + GstPoll *set; + + set = gst_poll_new (TRUE); + fail_if (set == NULL, "Failed to create a GstPoll"); + + MAIN_START_THREADS (1, delayed_stop, set); + + fail_unless (gst_poll_wait (set, GST_SECOND) != 0, "Waiting timed out"); + + MAIN_STOP_THREADS (); + + gst_poll_free (set); +} + +GST_END_TEST; + +static gpointer +delayed_restart (gpointer data) +{ + GstPoll *set = data; + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = 1; + + THREAD_START (); + + g_usleep (500000); + + gst_poll_add_fd (set, &fd); + gst_poll_fd_ctl_write (set, &fd, TRUE); + gst_poll_restart (set); + + return NULL; +} + +GST_START_TEST (test_poll_wait_restart) +{ + GstPoll *set; + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = 1; + + set = gst_poll_new (TRUE); + fail_if (set == NULL, "Failed to create a GstPoll"); + + MAIN_START_THREADS (1, delayed_restart, set); + + fail_unless (gst_poll_wait (set, GST_SECOND) > 0, "Waiting was interrupted"); + fail_unless (gst_poll_fd_can_write (set, &fd), + "Write descriptor should be writeable"); + + MAIN_STOP_THREADS (); + + gst_poll_free (set); +} + +GST_END_TEST; + +static gpointer +delayed_flush (gpointer data) +{ + GstPoll *set = data; + + THREAD_START (); + + g_usleep (500000); + gst_poll_set_flushing (set, TRUE); + + return NULL; +} + +GST_START_TEST (test_poll_wait_flush) +{ + GstPoll *set; + + set = gst_poll_new (TRUE); + fail_if (set == NULL, "Failed to create a GstPoll"); + + gst_poll_set_flushing (set, TRUE); + fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY, + "Waiting was not flushed"); + fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY, + "Waiting was not flushed"); + + gst_poll_set_flushing (set, FALSE); + fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout"); + + MAIN_START_THREADS (1, delayed_flush, set); + + fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY, + "Waiting was not flushed"); + fail_unless (gst_poll_wait (set, GST_SECOND) == -1 && errno == EBUSY, + "Waiting was not flushed"); + + gst_poll_set_flushing (set, FALSE); + fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout"); + + MAIN_STOP_THREADS (); + + gst_poll_free (set); +} + +GST_END_TEST; + +static gpointer +delayed_control (gpointer data) +{ + GstPoll *set = data; + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = 1; + + THREAD_START (); + + g_usleep (500000); + + gst_poll_add_fd (set, &fd); + gst_poll_fd_ctl_write (set, &fd, TRUE); + gst_poll_restart (set); + + g_mutex_lock (&mutex); + THREAD_SYNCHRONIZE (); + + g_usleep (500000); + + gst_poll_add_fd (set, &fd); + gst_poll_fd_ctl_write (set, &fd, TRUE); + gst_poll_restart (set); + + return NULL; +} + +GST_START_TEST (test_poll_controllable) +{ + GstPoll *set; + GstPollFD fd = GST_POLL_FD_INIT; + + fd.fd = 1; + + set = gst_poll_new (FALSE); + fail_if (set == NULL, "Failed to create a GstPoll"); + + MAIN_START_THREADS (1, delayed_control, set); + + fail_unless (gst_poll_wait (set, GST_SECOND) == 0, "Waiting did not timeout"); + + fail_unless (gst_poll_remove_fd (set, &fd), "Could not remove descriptor"); + fail_unless (gst_poll_set_controllable (set, TRUE), + "Could not make the set controllable"); + + MAIN_SYNCHRONIZE (); + + fail_unless (gst_poll_wait (set, GST_SECOND) > 0, "Waiting was interrupted"); + fail_unless (gst_poll_fd_can_write (set, &fd), + "Write descriptor should be writeable"); + + MAIN_STOP_THREADS (); + + gst_poll_free (set); +} + +GST_END_TEST; + +static Suite * +gst_poll_suite (void) +{ + Suite *s = suite_create ("GstPoll"); + TCase *tc_chain = tcase_create ("general"); + + /* turn off timeout */ + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); + +#ifndef G_OS_WIN32 + tcase_add_test (tc_chain, test_poll_basic); + tcase_add_test (tc_chain, test_poll_wait); + tcase_add_test (tc_chain, test_poll_wait_stop); + tcase_add_test (tc_chain, test_poll_wait_restart); + tcase_add_test (tc_chain, test_poll_wait_flush); + tcase_add_test (tc_chain, test_poll_controllable); +#else + tcase_skip_broken_test (tc_chain, test_poll_basic); + tcase_skip_broken_test (tc_chain, test_poll_wait); + tcase_skip_broken_test (tc_chain, test_poll_wait_stop); + tcase_skip_broken_test (tc_chain, test_poll_wait_restart); + tcase_skip_broken_test (tc_chain, test_poll_wait_flush); + tcase_skip_broken_test (tc_chain, test_poll_controllable); +#endif + + return s; +} + +GST_CHECK_MAIN (gst_poll); diff --git a/tests/check/gst/gstpreset.c b/tests/check/gst/gstpreset.c new file mode 100644 index 0000000..dfa0c4e --- /dev/null +++ b/tests/check/gst/gstpreset.c @@ -0,0 +1,311 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation and its subsidary(-ies) + * contact: + * + * gstpreset.c: Unit test for GstPreset + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +static GType gst_preset_test_get_type (void); + +#define GST_TYPE_PRESET_TEST (gst_preset_test_get_type ()) +#define GST_PRESET_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PRESET_TEST, GstPresetTest)) +#define GST_PRESET_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PRESET_TEST, GstPresetTestClass)) +#define GST_IS_PRESET_TEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PRESET_TEST)) +#define GST_IS_PRESET_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PRESET_TEST)) +#define GST_PRESET_TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PRESET_TEST, GstPresetTestClass)) +#define GST_PRESET_TEST_NAME "preset-test" + +enum +{ + PROP_TEST = 1, +}; + +typedef struct _GstPresetTest +{ + GstElement parent; + + gint test; +} GstPresetTest; + +typedef struct _GstPresetTestClass +{ + GstElementClass parent_class; +} GstPresetTestClass; + +static void +gst_preset_test_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstPresetTest *self = GST_PRESET_TEST (object); + + switch (property_id) { + case PROP_TEST: + g_value_set_int (value, self->test); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_preset_test_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstPresetTest *self = GST_PRESET_TEST (object); + + switch (property_id) { + case PROP_TEST: + self->test = g_value_get_int (value); + break; + } +} + +static void +gst_preset_test_class_init (GObjectClass * klass) +{ + klass->set_property = gst_preset_test_set_property; + klass->get_property = gst_preset_test_get_property; + + g_object_class_install_property (klass, PROP_TEST, + g_param_spec_int ("test", + "test prop", + "test parameter for preset test", + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE)); +} + +static void +gst_preset_test_base_init (GstPresetTestClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_metadata (element_class, + "Element for unit tests", + "Testing", "Use in unit tests", "Stefan Kost "); +} + +static GType +gst_preset_test_get_type (void) +{ + static volatile gsize preset_test_type = 0; + + if (g_once_init_enter (&preset_test_type)) { + GType type; + const GTypeInfo info = { + sizeof (GstPresetTestClass), + (GBaseInitFunc) gst_preset_test_base_init, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_preset_test_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GstPresetTest), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL /* value_table */ + }; + const GInterfaceInfo preset_interface_info = { + NULL, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + type = g_type_register_static (GST_TYPE_ELEMENT, "GstPresetTest", &info, 0); + g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_interface_info); + g_once_init_leave (&preset_test_type, type); + } + return preset_test_type; +} + +static gboolean +gst_preset_test_plugin_init (GstPlugin * plugin) +{ + gst_element_register (plugin, GST_PRESET_TEST_NAME, GST_RANK_NONE, + GST_TYPE_PRESET_TEST); + return TRUE; +} + + +GST_START_TEST (test_check) +{ + GstElement *elem; + + elem = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + fail_unless (GST_IS_PRESET (elem)); + + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (test_load) +{ + GstElement *elem; + gboolean res; + + elem = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + res = gst_preset_load_preset (GST_PRESET (elem), "does-not-exist"); + fail_unless (!res); + + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (test_add) +{ + GstElement *elem; + gboolean res; + gint val; + + elem = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + g_object_set (elem, "test", 5, NULL); + + res = gst_preset_save_preset (GST_PRESET (elem), "test"); + fail_unless (res); + + res = gst_preset_load_preset (GST_PRESET (elem), "test"); + fail_unless (res); + g_object_get (elem, "test", &val, NULL); + fail_unless (val == 5); + + gst_object_unref (elem); +} + +GST_END_TEST; + + +GST_START_TEST (test_del) +{ + GstElement *elem; + gboolean res; + + elem = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + res = gst_preset_save_preset (GST_PRESET (elem), "test"); + fail_unless (res); + + res = gst_preset_delete_preset (GST_PRESET (elem), "test"); + fail_unless (res); + + res = gst_preset_load_preset (GST_PRESET (elem), "test"); + fail_unless (!res); + + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (test_two_instances) +{ + GstElement *elem1, *elem2; + gboolean res; + gint val; + + elem1 = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + g_object_set (elem1, "test", 5, NULL); + + res = gst_preset_save_preset (GST_PRESET (elem1), "test"); + fail_unless (res); + + elem2 = gst_element_factory_make (GST_PRESET_TEST_NAME, NULL); + res = gst_preset_load_preset (GST_PRESET (elem2), "test"); + fail_unless (res); + g_object_get (elem2, "test", &val, NULL); + fail_unless (val == 5); + + gst_object_unref (elem1); + gst_object_unref (elem2); +} + +GST_END_TEST; + + +static void +remove_preset_file (void) +{ + gchar *preset_file_name; + + preset_file_name = g_build_filename (g_get_user_data_dir (), + "gstreamer-" GST_API_VERSION, "presets", "GstPresetTest.prs", NULL); + g_unlink (preset_file_name); + g_free (preset_file_name); +} + +static void +test_setup (void) +{ + remove_preset_file (); + gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "gst-test", + "preset test plugin", + gst_preset_test_plugin_init, + VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); +} + +static void +test_teardown (void) +{ + remove_preset_file (); +} + + +static Suite * +gst_preset_suite (void) +{ + Suite *s = suite_create ("GstPreset"); + TCase *tc = tcase_create ("preset"); + gchar *gst_dir; + gboolean can_write = FALSE; + + /* check if we can create presets */ + gst_dir = g_build_filename (g_get_user_data_dir (), + "gstreamer-" GST_API_VERSION, NULL); + +#ifdef G_OS_WIN32 + can_write = FALSE; /* FIXME: test properly using win32 API */ +#else + can_write = (g_access (gst_dir, R_OK | W_OK | X_OK) == 0); +#endif + + g_free (gst_dir); + + suite_add_tcase (s, tc); + tcase_add_test (tc, test_check); + tcase_add_test (tc, test_load); + if (can_write) { + tcase_add_test (tc, test_add); + tcase_add_test (tc, test_del); + tcase_add_test (tc, test_two_instances); + } + tcase_add_unchecked_fixture (tc, test_setup, test_teardown); + + return s; +} + +GST_CHECK_MAIN (gst_preset); diff --git a/tests/check/gst/gstprintf.c b/tests/check/gst/gstprintf.c new file mode 100644 index 0000000..3e01df0 --- /dev/null +++ b/tests/check/gst/gstprintf.c @@ -0,0 +1,151 @@ +/* GStreamer unit tests for the custom printf + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#ifdef GST_DISABLE_GST_DEBUG +#error "Something wrong with the build system setup" +#endif + +#include "gst/printf/printf.h" +/* +#include "gst/printf/printf-extension.h" +*/ + +static char * +test_printf (const char *format, ...) +{ + va_list varargs; + char *str = NULL; + int len; + + va_start (varargs, format); + len = __gst_vasprintf (&str, format, varargs); + va_end (varargs); + + if (len <= 0) + return NULL; + + GST_INFO ("[%s]", str); + return str; +} + +GST_START_TEST (printf_I32_I64) +{ + guint64 v64 = 0xf1e2d3c4b5a6978f; + guint32 v32 = 0xf1e2d3cf; + guint vu = 0xf1e2d3cf; + gchar *str; + + /* standard int/uint */ + str = test_printf ("x = %x", vu); + fail_unless_equals_string (str, "x = f1e2d3cf"); + g_free (str); + str = test_printf ("u = %u", vu); + fail_unless_equals_string (str, "u = 4058174415"); + g_free (str); + str = test_printf ("d = %d", vu); + fail_unless_equals_string (str, "d = -236792881"); + g_free (str); + + /* 32 bit GLib */ + str = test_printf ("32-bit x value = %" G_GINT32_MODIFIER "x", v32); + fail_unless_equals_string (str, "32-bit x value = f1e2d3cf"); + g_free (str); + str = test_printf ("32-bit u value = %" G_GUINT32_FORMAT, v32); + fail_unless_equals_string (str, "32-bit u value = 4058174415"); + g_free (str); + str = test_printf ("32-bit d value = %" G_GINT32_FORMAT, v32); + fail_unless_equals_string (str, "32-bit d value = -236792881"); + g_free (str); + + /* 64 bit Glib */ + str = test_printf ("64-bit x value = %" G_GINT64_MODIFIER "x", v64); + fail_unless_equals_string (str, "64-bit x value = f1e2d3c4b5a6978f"); + g_free (str); + str = test_printf ("64-bit u value = %" G_GUINT64_FORMAT, v64); + fail_unless_equals_string (str, "64-bit u value = 17429726349691885455"); + g_free (str); + str = test_printf ("64-bit d value = %" G_GINT64_FORMAT, v64); + fail_unless_equals_string (str, "64-bit d value = -1017017724017666161"); + g_free (str); + + /* 32 bit Windows */ + str = test_printf ("I32x value = %I32x", v32); + fail_unless_equals_string (str, "I32x value = f1e2d3cf"); + g_free (str); + str = test_printf ("I32u value = %I32u", v32); + fail_unless_equals_string (str, "I32u value = 4058174415"); + g_free (str); + str = test_printf ("I32d value = %I32d", v32); + fail_unless_equals_string (str, "I32d value = -236792881"); + g_free (str); + + /* needs testing first */ +#if 0 +#ifdef G_OS_WIN32 + /* 64 bit Windows */ + str = test_printf ("I64x value = %I64x", v64); + fail_unless_equals_string (str, "I64x value = f1e2d3c4b5a6978f"); + g_free (str); + str = test_printf ("I64u value = %I64u", v64); + fail_unless_equals_string (str, "I64u value = 17429726349691885455"); + g_free (str); + str = test_printf ("I64d value = %I64d", v64); + fail_unless_equals_string (str, "I64d value = -1017017724017666161"); + g_free (str); +#endif +#endif +} + +GST_END_TEST; + +GST_START_TEST (printf_percent) +{ + gchar *str; + + /* standard int/uint */ + str = test_printf ("%u%%", 99); + fail_unless_equals_string (str, "99%"); + g_free (str); +} + +GST_END_TEST; + +static Suite * +gst_printf_suite (void) +{ + Suite *s = suite_create ("GstPrintf"); + TCase *tc_chain = tcase_create ("gstprintf"); + + tcase_set_timeout (tc_chain, 30); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, printf_I32_I64); + tcase_add_test (tc_chain, printf_percent); + + return s; +} + +GST_CHECK_MAIN (gst_printf); diff --git a/tests/check/gst/gstpromise.c b/tests/check/gst/gstpromise.c new file mode 100644 index 0000000..7653399 --- /dev/null +++ b/tests/check/gst/gstpromise.c @@ -0,0 +1,639 @@ +/* GStreamer + * + * unit test for GstPromise + * + * Copyright (C) 2017 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +struct event_queue +{ + GMutex lock; + GCond cond; + GThread *thread; + GMainContext *main_context; + GMainLoop *main_loop; + gpointer user_data; +}; + +static gboolean +_unlock_thread (GMutex * lock) +{ + g_mutex_unlock (lock); + return G_SOURCE_REMOVE; +} + +static gpointer +_promise_thread (struct event_queue *q) +{ + g_mutex_lock (&q->lock); + q->main_context = g_main_context_new (); + q->main_loop = g_main_loop_new (q->main_context, FALSE); + + g_cond_broadcast (&q->cond); + g_main_context_invoke (q->main_context, (GSourceFunc) _unlock_thread, + &q->lock); + + g_main_loop_run (q->main_loop); + + g_mutex_lock (&q->lock); + g_main_context_unref (q->main_context); + q->main_context = NULL; + g_main_loop_unref (q->main_loop); + q->main_loop = NULL; + g_cond_broadcast (&q->cond); + g_mutex_unlock (&q->lock); + + return NULL; +} + +static void +event_queue_start (struct event_queue *q) +{ + g_mutex_lock (&q->lock); + q->thread = g_thread_new ("promise-thread", (GThreadFunc) _promise_thread, q); + + while (!q->main_loop) + g_cond_wait (&q->cond, &q->lock); + g_mutex_unlock (&q->lock); +} + +static void +event_queue_stop (struct event_queue *q) +{ + g_mutex_lock (&q->lock); + if (q->main_loop) + g_main_loop_quit (q->main_loop); + g_mutex_unlock (&q->lock); +} + +static void +event_queue_stop_wait (struct event_queue *q) +{ + g_mutex_lock (&q->lock); + while (q->main_loop) { + g_main_loop_quit (q->main_loop); + g_cond_wait (&q->cond, &q->lock); + } + g_mutex_unlock (&q->lock); + + g_thread_unref (q->thread); +} + +static struct event_queue * +event_queue_new (void) +{ + struct event_queue *q = g_new0 (struct event_queue, 1); + + GST_LOG ("starting event queue %p", q); + + g_mutex_init (&q->lock); + g_cond_init (&q->cond); + event_queue_start (q); + + return q; +} + +static void +event_queue_free (struct event_queue *q) +{ + event_queue_stop_wait (q); + + g_mutex_clear (&q->lock); + g_cond_clear (&q->cond); + + GST_LOG ("stopped event queue %p", q); + + g_free (q); +} + +static void +_enqueue_task (struct event_queue *q, GSourceFunc func, gpointer data, + GDestroyNotify notify) +{ + GSource *source; + + source = g_idle_source_new (); + g_source_set_priority (source, G_PRIORITY_DEFAULT); + g_source_set_callback (source, (GSourceFunc) func, data, notify); + g_source_attach (source, q->main_context); + g_source_unref (source); +} + +GST_START_TEST (test_reply) +{ + GstPromise *r; + + r = gst_promise_new (); + + gst_promise_reply (r, NULL); + fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_REPLIED); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_data) +{ + GstPromise *r; + GstStructure *s; + const GstStructure *ret; + + r = gst_promise_new (); + + s = gst_structure_new ("promise", "test", G_TYPE_INT, 1, NULL); + gst_promise_reply (r, s); + fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_REPLIED); + ret = gst_promise_get_reply (r); + fail_unless (gst_structure_is_equal (ret, s)); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_immutable) +{ + GstPromise *r; + GstStructure *s, *ret; + + r = gst_promise_new (); + + s = gst_structure_new ("promise", "test", G_TYPE_INT, 1, NULL); + gst_promise_reply (r, s); + ret = (GstStructure *) gst_promise_get_reply (r); + + /* immutable result must not be able to modify the reply */ + ASSERT_CRITICAL (gst_structure_set (ret, "foo", G_TYPE_STRING, "bar", NULL)); + fail_unless (gst_structure_get_string (ret, "foo") == NULL); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_interrupt) +{ + GstPromise *r; + + r = gst_promise_new (); + + gst_promise_interrupt (r); + fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_INTERRUPTED); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_expire) +{ + GstPromise *r; + + r = gst_promise_new (); + + gst_promise_expire (r); + fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_EXPIRED); + + gst_promise_unref (r); +} + +GST_END_TEST; + +struct change_data +{ + int change_count; + GstPromiseResult result; +}; + +static void +on_change (GstPromise * promise, gpointer user_data) +{ + struct change_data *res = user_data; + + res->result = gst_promise_wait (promise); + res->change_count += 1; +} + +GST_START_TEST (test_change_func) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_reply (r, NULL); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_expire) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_reply (r, NULL); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_discard) +{ + GstPromise *r; + + /* NULL promise => discard reply */ + r = NULL; + + /* no-op, we don't want a reply */ + gst_promise_reply (r, NULL); + + if (r) + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_interrupt) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_reply (r, NULL); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + gst_promise_interrupt (r); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_reply_reply) +{ + GstPromise *r; + GstStructure *s; + struct change_data data = { 0, }; + const GstStructure *ret; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + s = gst_structure_new ("promise", "test", G_TYPE_INT, 1, NULL); + gst_promise_reply (r, s); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + ASSERT_CRITICAL (gst_promise_reply (r, NULL)); + fail_unless (gst_promise_wait (r) == GST_PROMISE_RESULT_REPLIED); + ret = gst_promise_get_reply (r); + fail_unless (gst_structure_is_equal (ret, s)); + fail_unless (data.result == GST_PROMISE_RESULT_REPLIED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_interrupt_expire) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_interrupt (r); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_interrupt_reply) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_interrupt (r); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + gst_promise_reply (r, NULL); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_interrupt_interrupt) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_interrupt (r); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + ASSERT_CRITICAL (gst_promise_interrupt (r)); + fail_unless (data.result == GST_PROMISE_RESULT_INTERRUPTED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_expire_expire) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_expire_interrupt) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + ASSERT_CRITICAL (gst_promise_interrupt (r)); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +GST_START_TEST (test_expire_reply) +{ + GstPromise *r; + struct change_data data = { 0, }; + + r = gst_promise_new_with_change_func (on_change, &data, NULL); + gst_promise_expire (r); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + ASSERT_CRITICAL (gst_promise_reply (r, NULL)); + fail_unless (data.result == GST_PROMISE_RESULT_EXPIRED); + fail_unless (data.change_count == 1); + + gst_promise_unref (r); +} + +GST_END_TEST; + +struct stress_item +{ + struct event_queue *q; + GstPromise *promise; + GstPromiseResult result; +}; + +static void +stress_reply (struct stress_item *item) +{ + switch (item->result) { + case GST_PROMISE_RESULT_REPLIED: + gst_promise_reply (item->promise, NULL); + break; + case GST_PROMISE_RESULT_INTERRUPTED: + gst_promise_interrupt (item->promise); + break; + case GST_PROMISE_RESULT_EXPIRED: + gst_promise_expire (item->promise); + break; + default: + g_assert_not_reached (); + } +} + +struct stress_queues +{ + GAsyncQueue *push_queue; + GAsyncQueue *wait_queue; + guint64 push_count; +}; + +static gboolean +_push_random_promise (struct event_queue *q) +{ + struct stress_queues *s_q = q->user_data; + struct stress_item *item; + + item = g_new0 (struct stress_item, 1); + item->promise = gst_promise_new (); + while (item->result == GST_PROMISE_RESULT_PENDING) + item->result = g_random_int () % 4; + + g_async_queue_push (s_q->wait_queue, item); + g_async_queue_push (s_q->push_queue, item); + + s_q->push_count++; + + return G_SOURCE_CONTINUE; +} + +static void +_push_stop_promise (struct event_queue *q) +{ + struct stress_queues *s_q = q->user_data; + gpointer item = GINT_TO_POINTER (1); + + g_async_queue_push (s_q->wait_queue, item); + g_async_queue_push (s_q->push_queue, item); +} + +static gboolean +_pop_promise (struct event_queue *q) +{ + struct stress_queues *s_q = q->user_data; + struct stress_item *item; + + item = g_async_queue_pop (s_q->push_queue); + + if (item == (void *) 1) + return G_SOURCE_REMOVE; + + stress_reply (item); + + return G_SOURCE_CONTINUE; +} + +static gboolean +_wait_promise (struct event_queue *q) +{ + struct stress_queues *s_q = q->user_data; + struct stress_item *item; + + item = g_async_queue_pop (s_q->wait_queue); + + if (item == (void *) 1) + return G_SOURCE_REMOVE; + + fail_unless (gst_promise_wait (item->promise) == item->result); + + gst_promise_unref (item->promise); + g_free (item); + + return G_SOURCE_CONTINUE; +} + +GST_START_TEST (test_stress) +{ +#define N_QUEUES 3 + struct event_queue *pushers[N_QUEUES]; + struct event_queue *poppers[N_QUEUES]; + struct event_queue *waiters[N_QUEUES]; + struct stress_queues s_q = { 0, }; + int i; + + s_q.push_queue = g_async_queue_new (); + s_q.wait_queue = g_async_queue_new (); + + for (i = 0; i < N_QUEUES; i++) { + pushers[i] = event_queue_new (); + pushers[i]->user_data = &s_q; + _enqueue_task (pushers[i], (GSourceFunc) _push_random_promise, pushers[i], + NULL); + waiters[i] = event_queue_new (); + waiters[i]->user_data = &s_q; + _enqueue_task (waiters[i], (GSourceFunc) _wait_promise, waiters[i], NULL); + poppers[i] = event_queue_new (); + poppers[i]->user_data = &s_q; + _enqueue_task (poppers[i], (GSourceFunc) _pop_promise, poppers[i], NULL); + } + + GST_INFO ("all set up, waiting."); + g_usleep (100000); + GST_INFO ("wait done, cleaning up the test."); + + { + struct stress_item *item; + int push_size; + + for (i = 0; i < N_QUEUES; i++) { + event_queue_stop (pushers[i]); + event_queue_stop (poppers[i]); + event_queue_stop (waiters[i]); + _push_stop_promise (pushers[i]); + } + + for (i = 0; i < N_QUEUES; i++) { + event_queue_free (pushers[i]); + event_queue_free (poppers[i]); + } + + push_size = g_async_queue_length (s_q.push_queue); + + /* push through all the promises so all the waits will complete */ + while ((item = g_async_queue_try_pop (s_q.push_queue))) { + if (item == (void *) 1) + continue; + stress_reply (item); + } + + for (i = 0; i < N_QUEUES; i++) + event_queue_free (waiters[i]); + + GST_INFO ("pushed %" G_GUINT64_FORMAT ", %d leftover in push queue, " + "%d leftover in wait queue", s_q.push_count, push_size, + g_async_queue_length (s_q.wait_queue)); + + while ((item = g_async_queue_try_pop (s_q.wait_queue))) { + if (item == (void *) 1) + continue; + + fail_unless (gst_promise_wait (item->promise) == item->result); + + gst_promise_unref (item->promise); + g_free (item); + } + } + + g_async_queue_unref (s_q.push_queue); + g_async_queue_unref (s_q.wait_queue); +} + +GST_END_TEST; + +static Suite * +gst_promise_suite (void) +{ + Suite *s = suite_create ("GstPromise"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_reply); + tcase_add_test (tc_chain, test_reply_data); + tcase_add_test (tc_chain, test_reply_immutable); + tcase_add_test (tc_chain, test_interrupt); + tcase_add_test (tc_chain, test_expire); + tcase_add_test (tc_chain, test_change_func); + tcase_add_test (tc_chain, test_reply_expire); + tcase_add_test (tc_chain, test_reply_discard); + tcase_add_test (tc_chain, test_reply_interrupt); + tcase_add_test (tc_chain, test_reply_reply); + tcase_add_test (tc_chain, test_interrupt_reply); + tcase_add_test (tc_chain, test_interrupt_expire); + tcase_add_test (tc_chain, test_interrupt_interrupt); + tcase_add_test (tc_chain, test_expire_expire); + tcase_add_test (tc_chain, test_expire_interrupt); + tcase_add_test (tc_chain, test_expire_reply); + tcase_add_test (tc_chain, test_stress); + + return s; +} + +GST_CHECK_MAIN (gst_promise); diff --git a/tests/check/gst/gstprotection.c b/tests/check/gst/gstprotection.c new file mode 100644 index 0000000..1669c81 --- /dev/null +++ b/tests/check/gst/gstprotection.c @@ -0,0 +1,294 @@ +/* GStreamer + * + * Unit tests for protection library. + * + * Copyright (C) <2015> YouView TV Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifndef GST_PACKAGE_NAME +#define GST_PACKAGE_NAME "gstreamer" +#endif + +#ifndef GST_PACKAGE_ORIGIN +#define GST_PACKAGE_ORIGIN "https://developer.gnome.org/gstreamer/" +#endif + +static GType gst_protection_test_get_type (void); + +#define GST_TYPE_PROTECTION_TEST (gst_protection_test_get_type ()) +#define GST_PROTECTION_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROTECTION_TEST, GstProtectionTest)) +#define GST_PROTECTION_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROTECTION_TEST, GstProtectionTestClass)) +#define GST_IS_PROTECTION_TEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROTECTION_TEST)) +#define GST_IS_PROTECTION_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROTECTION_TEST)) +#define GST_PROTECTION_TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PROTECTION_TEST, GstProtectionTestClass)) +#define GST_PROTECTION_TEST_NAME "protection-test" + +#define CLEARKEY_SYSTEM_ID "78f32170-d883-11e0-9572-0800200c9a66" + +typedef struct _GstProtectionTest +{ + GstElement parent; + + gint test; +} GstProtectionTest; + +typedef struct _GstProtectionTestClass +{ + GstElementClass parent_class; +} GstProtectionTestClass; + +typedef struct _PluginInitContext +{ + const gchar *name; + guint rank; + GType type; +} PluginInitContext; + +static GstStaticPadTemplate gst_decrypt_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS + ("application/x-cenc, original-media-type=(string)video/x-h264, " + GST_PROTECTION_SYSTEM_ID_CAPS_FIELD "=(string)" CLEARKEY_SYSTEM_ID) + ); + +static void +gst_protection_test_class_init (GObjectClass * klass) +{ +} + +static void +gst_protection_test_base_init (GstProtectionTestClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_static_pad_template (element_class, + &gst_decrypt_sink_template); + + gst_element_class_set_metadata (element_class, + "Decryptor element for unit tests", + GST_ELEMENT_FACTORY_KLASS_DECRYPTOR, + "Use in unit tests", "Alex Ashley "); +} + +static GType +gst_protection_test_get_type (void) +{ + static volatile gsize protection_test_type = 0; + + if (g_once_init_enter (&protection_test_type)) { + GType type; + const GTypeInfo info = { + sizeof (GstProtectionTestClass), + (GBaseInitFunc) gst_protection_test_base_init, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_protection_test_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GstProtectionTest), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL /* value_table */ + }; + type = + g_type_register_static (GST_TYPE_ELEMENT, "GstProtectionTest", &info, + 0); + g_once_init_leave (&protection_test_type, type); + } + return protection_test_type; +} + +static gboolean +protection_plugin_init_func (GstPlugin * plugin, gpointer user_data) +{ + PluginInitContext *context = (PluginInitContext *) user_data; + gboolean ret; + + ret = + gst_element_register (plugin, context->name, context->rank, + context->type); + return ret; +} + +static gboolean +protection_create_plugin (GstRegistry * registry, const gchar * name, + GType type) +{ + gboolean ret; + PluginInitContext context; + + context.name = name; + context.rank = GST_RANK_MARGINAL; + context.type = type; + ret = gst_plugin_register_static_full (GST_VERSION_MAJOR, /* version */ + GST_VERSION_MINOR, /* version */ + name, /* name */ + "Protection unit test", /* description */ + protection_plugin_init_func, /* init function */ + "0.0.0", /* version string */ + GST_LICENSE_UNKNOWN, /* license */ + __FILE__, /* source */ + GST_PACKAGE_NAME, /* package */ + GST_PACKAGE_ORIGIN, /* origin */ + &context /* user_data */ + ); + return ret; +} + +static void +test_setup (void) +{ + GstRegistry *registry; + + registry = gst_registry_get (); + protection_create_plugin (registry, GST_PROTECTION_TEST_NAME, + GST_TYPE_PROTECTION_TEST); +} + +static void +test_teardown (void) +{ +} + + +GST_START_TEST (test_decryptor_element_class) +{ + GstElement *elem; + const gchar *selected_id; + const gchar *sys_ids[] = { + CLEARKEY_SYSTEM_ID, + "69f908af-4816-46ea-910c-cd5dcccb0a3a", + "5e629af5-38da-4063-8977-97ffbd9902d4", + NULL + }; + +#ifdef DEBUG_PLUGINS + GList *list, *walk; + + list = gst_registry_get_plugin_list (gst_registry_get ()); + for (walk = list; walk; walk = g_list_next (walk)) { + GstPlugin *plugin = (GstPlugin *) walk->data; + g_print ("Element %s\n", gst_plugin_get_name (plugin)); + } +#endif + + elem = gst_element_factory_make (GST_PROTECTION_TEST_NAME, NULL); + fail_unless (GST_IS_ELEMENT (elem)); + + selected_id = gst_protection_select_system (sys_ids); + fail_if (selected_id == NULL); + + selected_id = gst_protection_select_system (&sys_ids[1]); + fail_unless (selected_id == NULL); + + selected_id = gst_protection_select_system (&sys_ids[3]); + fail_unless (selected_id == NULL); + + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (test_protection_metadata) +{ + GstBuffer *buf = NULL; + GstBuffer *iv, *kid; + GstBuffer *fetched_iv = NULL, *fetched_key_id = NULL; + GstStructure *meta_info; + GstProtectionMeta *meta = NULL; + const GstMetaInfo *info = NULL; + const GValue *value; + + /* Check correct type info is returned */ + info = gst_protection_meta_get_info (); + fail_unless (info != NULL); + fail_unless (info->api == GST_PROTECTION_META_API_TYPE); + + iv = gst_buffer_new_allocate (NULL, 16, NULL); + gst_buffer_memset (iv, 0, 'i', 16); + ASSERT_MINI_OBJECT_REFCOUNT (iv, "iv", 1); + kid = gst_buffer_new_allocate (NULL, 16, NULL); + gst_buffer_memset (kid, 0, 'k', 16); + ASSERT_MINI_OBJECT_REFCOUNT (kid, "kid", 1); + meta_info = gst_structure_new ("application/x-cenc", + "encrypted", G_TYPE_BOOLEAN, TRUE, + "iv", GST_TYPE_BUFFER, iv, + "iv_size", G_TYPE_UINT, 16, "kid", GST_TYPE_BUFFER, kid, NULL); + ASSERT_MINI_OBJECT_REFCOUNT (kid, "kid", 2); + ASSERT_MINI_OBJECT_REFCOUNT (iv, "iv", 2); + + buf = gst_buffer_new_allocate (NULL, 1024, NULL); + /* Test attaching protection metadata to buffer */ + meta = gst_buffer_add_protection_meta (buf, meta_info); + fail_unless (meta != NULL); + /* gst_buffer_new_allocate takes ownership of info GstStructure */ + ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1); + + /* Test detaching protection metadata from buffer, and check that + * contained data is correct */ + meta = NULL; + meta = gst_buffer_get_protection_meta (buf); + fail_unless (meta != NULL); + ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1); + value = gst_structure_get_value (meta->info, "iv"); + fail_unless (value != NULL); + fetched_iv = gst_value_get_buffer (value); + fail_unless (fetched_iv != NULL); + fail_unless (gst_buffer_get_size (fetched_iv) == 16); + value = gst_structure_get_value (meta->info, "kid"); + fail_unless (value != NULL); + fetched_key_id = gst_value_get_buffer (value); + fail_unless (fetched_key_id != NULL); + fail_unless (gst_buffer_get_size (fetched_key_id) == 16); + + gst_buffer_remove_meta (buf, (GstMeta *) meta); + + /* Check that refcounts are decremented after metadata is freed */ + ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1); + ASSERT_MINI_OBJECT_REFCOUNT (iv, "IV", 1); + ASSERT_MINI_OBJECT_REFCOUNT (kid, "KID", 1); + + gst_buffer_unref (buf); + gst_buffer_unref (iv); + gst_buffer_unref (kid); +} + +GST_END_TEST; + +static Suite * +protection_suite (void) +{ + Suite *s = suite_create ("protection library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_decryptor_element_class); + tcase_add_test (tc_chain, test_protection_metadata); + tcase_add_unchecked_fixture (tc_chain, test_setup, test_teardown); + + return s; +} + +GST_CHECK_MAIN (protection); diff --git a/tests/check/gst/gstquery.c b/tests/check/gst/gstquery.c new file mode 100644 index 0000000..547c622 --- /dev/null +++ b/tests/check/gst/gstquery.c @@ -0,0 +1,296 @@ +/* GStreamer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_START_TEST (create_queries) +{ + GstQuery *query; + + /* POSITION */ + { + GstFormat format; + gint64 position; + + query = gst_query_new_position (GST_FORMAT_TIME); + fail_if (query == NULL); + fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_POSITION); + + gst_query_parse_position (query, &format, NULL); + fail_if (format != GST_FORMAT_TIME); + + gst_query_set_position (query, GST_FORMAT_TIME, 0xdeadbeaf); + + gst_query_parse_position (query, &format, &position); + fail_if (format != GST_FORMAT_TIME); + fail_if (position != 0xdeadbeaf); + + gst_query_unref (query); + } + /* DURATION */ + { + GstFormat format; + gint64 duration; + + query = gst_query_new_duration (GST_FORMAT_TIME); + fail_if (query == NULL); + fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_DURATION); + + gst_query_parse_duration (query, &format, NULL); + fail_if (format != GST_FORMAT_TIME); + + gst_query_set_duration (query, GST_FORMAT_TIME, 0xdeadbeaf); + + gst_query_parse_duration (query, &format, &duration); + fail_if (format != GST_FORMAT_TIME); + fail_if (duration != 0xdeadbeaf); + + gst_query_unref (query); + } + /* BUFFERING RANGES */ + { + gint64 start, stop; + + query = gst_query_new_buffering (GST_FORMAT_PERCENT); + fail_if (query == NULL); + fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING); + + fail_unless (gst_query_add_buffering_range (query, 0, 20)); + fail_unless (gst_query_add_buffering_range (query, 25, 30)); + + /* check incoherent range insertion */ + fail_if (gst_query_add_buffering_range (query, 10, 15)); + fail_if (gst_query_add_buffering_range (query, 50, 40)); + + fail_unless (gst_query_get_n_buffering_ranges (query) == 2); + + fail_unless (gst_query_parse_nth_buffering_range (query, 0, &start, &stop)); + fail_unless (start == 0); + fail_unless (stop == 20); + + fail_unless (gst_query_parse_nth_buffering_range (query, 1, &start, &stop)); + fail_unless (start == 25); + fail_unless (stop == 30); + + gst_query_unref (query); + } + { + /* FIXME make tests for: + * + * LATENCY + * JITTER + * RATE + * SEEKING + * SEGMENT + * CONVERT + */ + } + /* SEGMENT */ + { + gdouble rate; + GstFormat format; + gint64 start, stop; + + format = GST_FORMAT_BYTES; + query = gst_query_new_segment (format); + + fail_if (query == NULL); + fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT); + + gst_query_parse_segment (query, &rate, &format, &start, &stop); + + /* see if empty gives undefined formats */ + fail_if (rate != 0.0); + fail_if (format != GST_FORMAT_BYTES); + fail_if (start != -1); + fail_if (stop != -1); + + /* change all values */ + gst_query_set_segment (query, 2.0, GST_FORMAT_TIME, 1 * GST_SECOND, + 3 * GST_SECOND); + + gst_query_parse_segment (query, &rate, &format, &start, &stop); + + /* see if the values were changed */ + fail_if (rate != 2.0); + fail_if (format != GST_FORMAT_TIME); + fail_if (start != 1 * GST_SECOND); + fail_if (stop != 3 * GST_SECOND); + + gst_query_unref (query); + } + + /* FORMATS */ + { + guint size; + GstFormat format; + + query = gst_query_new_formats (); + fail_if (query == NULL); + fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS); + + /* empty */ + gst_query_parse_n_formats (query, &size); + fail_if (size != 0); + + /* see if empty gives undefined formats */ + gst_query_parse_nth_format (query, 0, &format); + fail_if (format != GST_FORMAT_UNDEFINED); + gst_query_parse_nth_format (query, 1, &format); + fail_if (format != GST_FORMAT_UNDEFINED); + + /* set 2 formats */ + gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES); + + gst_query_parse_n_formats (query, &size); + fail_if (size != 2); + + format = GST_FORMAT_UNDEFINED; + + gst_query_parse_nth_format (query, 0, &format); + fail_if (format != GST_FORMAT_TIME); + gst_query_parse_nth_format (query, 1, &format); + fail_if (format != GST_FORMAT_BYTES); + + /* out of bounds, should return UNDEFINED */ + gst_query_parse_nth_format (query, 2, &format); + fail_if (format != GST_FORMAT_UNDEFINED); + + /* overwrite with 3 formats */ + gst_query_set_formats (query, 3, GST_FORMAT_TIME, GST_FORMAT_BYTES, + GST_FORMAT_PERCENT); + + gst_query_parse_n_formats (query, &size); + fail_if (size != 3); + + gst_query_parse_nth_format (query, 2, &format); + fail_if (format != GST_FORMAT_PERCENT); + + /* create one from an array */ + { + static GstFormat formats[] = { + GST_FORMAT_TIME, + GST_FORMAT_BYTES, + GST_FORMAT_PERCENT + }; + gst_query_set_formatsv (query, 3, formats); + + gst_query_parse_n_formats (query, &size); + fail_if (size != 3); + + gst_query_parse_nth_format (query, 0, &format); + fail_if (format != GST_FORMAT_TIME); + gst_query_parse_nth_format (query, 2, &format); + fail_if (format != GST_FORMAT_PERCENT); + } + gst_query_unref (query); + } +} + +GST_END_TEST; + +GST_START_TEST (test_queries) +{ + GstBin *bin; + GstElement *src, *sink; + GstStateChangeReturn ret; + GstPad *pad; + GstQuery *dur, *pos; + + fail_unless ((bin = (GstBin *) gst_pipeline_new (NULL)) != NULL, + "Could not create pipeline"); + fail_unless ((src = gst_element_factory_make ("fakesrc", NULL)) != NULL, + "Could not create fakesrc"); + g_object_set (src, "datarate", 200, "sizetype", 2, NULL); + + fail_unless ((sink = gst_element_factory_make ("fakesink", NULL)) != NULL, + "Could not create fakesink"); + g_object_set (sink, "sync", TRUE, NULL); + fail_unless ((dur = gst_query_new_duration (GST_FORMAT_BYTES)) != NULL, + "Could not prepare duration query"); + fail_unless ((pos = gst_query_new_position (GST_FORMAT_BYTES)) != NULL, + "Could not prepare position query"); + + fail_unless (gst_bin_add (bin, src), "Could not add src to bin"); + fail_unless (gst_bin_add (bin, sink), "Could not add sink to bin"); + fail_unless (gst_element_link (src, sink), "could not link src and sink"); + + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); + fail_if (ret == GST_STATE_CHANGE_FAILURE, "Failed to set pipeline PLAYING"); + if (ret == GST_STATE_CHANGE_ASYNC) + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE); + + /* Query the bin */ + fail_unless (gst_element_query (GST_ELEMENT (bin), pos), + "Could not query pipeline position"); + fail_unless (gst_element_query (GST_ELEMENT (bin), dur), + "Could not query pipeline duration"); + + /* Query elements */ + fail_unless (gst_element_query (GST_ELEMENT (src), pos), + "Could not query position of fakesrc"); + fail_unless (gst_element_query (GST_ELEMENT (src), pos), + "Could not query duration of fakesrc"); + + fail_unless (gst_element_query (GST_ELEMENT (sink), pos), + "Could not query position of fakesink"); + fail_unless (gst_element_query (GST_ELEMENT (sink), pos), + "Could not query duration of fakesink"); + + /* Query pads */ + fail_unless ((pad = gst_element_get_static_pad (src, "src")) != NULL, + "Could not get source pad of fakesrc"); + fail_unless (gst_pad_query (pad, pos), + "Could not query position of fakesrc src pad"); + fail_unless (gst_pad_query (pad, dur), + "Could not query duration of fakesrc src pad"); + gst_object_unref (pad); + + /* We don't query the sink pad of fakesink, it doesn't + * handle downstream queries atm, but it might later, who knows? */ + + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_if (ret == GST_STATE_CHANGE_FAILURE, "Failed to set pipeline NULL"); + if (ret == GST_STATE_CHANGE_ASYNC) + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE); + + gst_query_unref (dur); + gst_query_unref (pos); + gst_object_unref (bin); +} + +GST_END_TEST; + +static Suite * +gst_query_suite (void) +{ + Suite *s = suite_create ("GstQuery"); + TCase *tc_chain = tcase_create ("queries"); + + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, create_queries); + tcase_add_test (tc_chain, test_queries); + return s; +} + +GST_CHECK_MAIN (gst_query); diff --git a/tests/check/gst/gstregistry.c b/tests/check/gst/gstregistry.c new file mode 100644 index 0000000..1a7ec91 --- /dev/null +++ b/tests/check/gst/gstregistry.c @@ -0,0 +1,219 @@ +/* GStreamer unit tests for the plugin registry + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +static gint +plugin_name_cmp (GstPlugin * a, GstPlugin * b) +{ + const gchar *name_a = gst_plugin_get_name (a); + const gchar *name_b = gst_plugin_get_name (b); + + return strcmp (name_a, name_b); +} + +static gint +plugin_ptr_cmp (GstPlugin * a, GstPlugin * b) +{ + return (a == b) ? 0 : 1; +} + +static void +print_plugin (const gchar * marker, GstRegistry * registry, GstPlugin * plugin) +{ + const gchar *name; + GList *features, *f; + + name = gst_plugin_get_name (plugin); + + GST_DEBUG ("%s: plugin %p %d %s file: %s", marker, plugin, + GST_OBJECT_REFCOUNT (plugin), name, + GST_STR_NULL (gst_plugin_get_filename (plugin))); + + features = gst_registry_get_feature_list_by_plugin (registry, name); + for (f = features; f != NULL; f = f->next) { + GstPluginFeature *feature; + + feature = GST_PLUGIN_FEATURE (f->data); + + GST_LOG ("%s: feature: %p %s", marker, feature, + GST_OBJECT_NAME (feature)); + } + gst_plugin_feature_list_free (features); +} + +GST_START_TEST (test_registry_update) +{ + GstPluginFeature *old_identity, *new_identity; + GstPluginFeature *old_pipeline, *new_pipeline; + GstRegistry *registry; + GList *plugins_before, *plugins_after, *l; + + registry = gst_registry_get (); + fail_unless (registry != NULL); + ASSERT_OBJECT_REFCOUNT (registry, "default registry", 1); + + /* refcount should still be 1 the second time */ + registry = gst_registry_get (); + fail_unless (registry != NULL); + ASSERT_OBJECT_REFCOUNT (registry, "default registry", 1); + + old_identity = gst_registry_lookup_feature (registry, "identity"); + fail_unless (old_identity != NULL, "Can't find plugin feature 'identity'"); + + old_pipeline = gst_registry_lookup_feature (registry, "pipeline"); + fail_unless (old_pipeline != NULL, "Can't find plugin feature 'pipeline'"); + + /* plugins should have a refcount of 2: the registry holds one reference, + * and the other one is ours for the list */ + plugins_before = gst_registry_get_plugin_list (registry); + for (l = plugins_before; l; l = l->next) { + GstPlugin *plugin; + + plugin = GST_PLUGIN (l->data); + + print_plugin ("before1", registry, plugin); + + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 2); + } + + GST_LOG (" ----- calling gst_update_registry -----"); + + fail_unless (gst_update_registry () != FALSE, "registry update failed"); + + GST_LOG (" ----- registry updated -----"); + + /* static plugins should have the same refcount as before (ie. 2), whereas + * file-based plugins *may* have been replaced by a newly-created object + * if the on-disk file changed (and was not yet loaded). There should be + * only one reference left for those, and that's ours */ + for (l = plugins_before; l; l = l->next) { + GstPlugin *plugin; + + plugin = GST_PLUGIN (l->data); + + print_plugin ("before2", registry, plugin); + + if (gst_plugin_get_filename (plugin)) { + /* file-based plugin. */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (plugin, "plugin", 1, 2); + } else { + /* static plugin */ + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 2); + } + } + + GST_LOG (" -----------------------------------"); + + plugins_after = gst_registry_get_plugin_list (registry); + for (l = plugins_after; l; l = l->next) { + GstPlugin *plugin = GST_PLUGIN (l->data); + + print_plugin ("after ", registry, plugin); + + /* file-based plugins should have a refcount of 2 (one for the registry, + * one for us for the list) or 3 (one for the registry, one for the before + * list, one for the after list), static plugins should have one of 3 + * (one for the registry, one for the new list and one for the old list). + * This implicitly also makes sure that all static plugins are the same + * objects as they were before. Non-static ones may or may not have been + * replaced by new objects */ + if (gst_plugin_get_filename (plugin)) { + if (g_list_find_custom (plugins_before, plugin, + (GCompareFunc) plugin_ptr_cmp) != NULL) { + /* Same plugin existed in the before list. Refcount must be 3 */ + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 3); + } else { + /* This plugin is newly created, so should only exist in the after list + * and the registry: Refcount must be 2 */ + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 2); + } + } else { + ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 3); + } + } + + /* check that we still have all plugins in the new list that we had before */ + for (l = plugins_after; l; l = l->next) { + GstPlugin *plugin; + + plugin = GST_PLUGIN (l->data); + + fail_unless (g_list_find_custom (plugins_before, plugin, + (GCompareFunc) plugin_name_cmp) != NULL, + "Plugin %s is in new list but not in old one?!", + gst_plugin_get_name (plugin)); + } + for (l = plugins_before; l; l = l->next) { + GstPlugin *plugin; + + plugin = GST_PLUGIN (l->data); + fail_unless (g_list_find_custom (plugins_after, plugin, + (GCompareFunc) plugin_name_cmp) != NULL, + "Plugin %s is in old list but not in new one?!", + gst_plugin_get_name (plugin)); + } + + new_identity = gst_registry_lookup_feature (registry, "identity"); + fail_unless (new_identity != NULL, "Can't find plugin feature 'identity'"); + fail_unless (old_identity == new_identity, "Old and new 'identity' feature " + "objects should be the same, but are different objects"); + + /* One ref each for: the registry, old_identity, new_identity */ + ASSERT_OBJECT_REFCOUNT (old_identity, "old identity feature after update", 3); + + new_pipeline = gst_registry_lookup_feature (registry, "pipeline"); + fail_unless (new_pipeline != NULL, "Can't find plugin feature 'pipeline'"); + fail_unless (old_pipeline == new_pipeline, "Old and new 'pipeline' feature " + "objects should be the same, but are different objects"); + + gst_plugin_list_free (plugins_before); + plugins_before = NULL; + gst_plugin_list_free (plugins_after); + plugins_after = NULL; + registry = NULL; + + gst_object_unref (old_identity); + gst_object_unref (new_identity); + gst_object_unref (old_pipeline); + gst_object_unref (new_pipeline); +} + +GST_END_TEST; + +static Suite * +registry_suite (void) +{ + Suite *s = suite_create ("registry"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_registry_update); + + return s; +} + +GST_CHECK_MAIN (registry); diff --git a/tests/check/gst/gstsegment.c b/tests/check/gst/gstsegment.c new file mode 100644 index 0000000..bba31ce --- /dev/null +++ b/tests/check/gst/gstsegment.c @@ -0,0 +1,1065 @@ +/* GStreamer + * Copyright (C) 2005 Jan Schmidt + * 2009 Wim Taymans + * + * gstsegment.c: Unit test for segments + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define check_times(segment, position, stream_time, running_time) G_STMT_START { \ + guint64 st, rt, pos; \ + \ + st = gst_segment_to_stream_time ((segment), (segment)->format, (position)); \ + rt = gst_segment_to_running_time ((segment), (segment)->format, (position)); \ + GST_DEBUG ("position %" G_GUINT64_FORMAT ", st %" G_GUINT64_FORMAT ", rt %" \ + G_GUINT64_FORMAT, (guint64) (position), (guint64) (stream_time), (guint64) (running_time)); \ + \ + fail_unless_equals_int64 (st, (stream_time)); \ + fail_unless_equals_int64 (rt, (running_time)); \ + if ((stream_time) != -1) { \ + pos = gst_segment_position_from_stream_time ((segment), (segment)->format, st); \ + fail_unless_equals_int64 (pos, (position)); \ + } \ + \ + if ((running_time) != -1) { \ + pos = gst_segment_position_from_running_time ((segment), (segment)->format, rt); \ + fail_unless_equals_int64 (pos, (position)); \ + } \ +} G_STMT_END; + +/* mess with the segment structure in the bytes format */ +GST_START_TEST (segment_seek_nosize) +{ + GstSegment segment; + gboolean res; + guint64 cstart, cstop; + gboolean update; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + /* configure segment to start 100 */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update); + fail_unless_equals_uint64 (segment.start, 100); + fail_unless_equals_uint64 (segment.position, 100); + fail_unless_equals_uint64 (segment.stop, -1); + fail_unless (update == TRUE); + /* appended after current position 0 */ + check_times (&segment, 100, 100, 0); + + /* do some clipping on the open range */ + /* completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop); + fail_unless (res == FALSE); + + /* touching lower bound, still outside of the segment */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* inside, touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 100, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* special case, 0 duration and outside segment */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 90, 90, &cstart, &cstop); + fail_unless (res == FALSE); + + /* special case, 0 duration and touching lower bound, i.e. inside segment */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 100, 100, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 100); + + /* special case, 0 duration and inside the segment */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 120, 120, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 120); + fail_unless_equals_uint64 (cstop, 120); + + /* completely inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 150, 200, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, 200); + + /* invalid start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start outside, we don't know the stop */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_int64 (cstop, -1); + + /* start on lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_int64 (cstop, -1); + + /* start inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_int64 (cstop, -1); + + /* move to 150, this is a running_time of 50 */ + segment.position = 150; + check_times (&segment, 150, 150, 50); + + /* add 100 to start, set stop to 300 */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update); + fail_unless_equals_uint64 (segment.start, 200); + fail_unless_equals_uint64 (segment.position, 200); + fail_unless_equals_uint64 (segment.stop, 300); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless (update == TRUE); + check_times (&segment, 200, 200, 50); + check_times (&segment, 250, 250, 100); + + update = FALSE; + /* add 100 to start (to 300), set stop to 200, this is not allowed. + * nothing should be updated in the segment. A g_warning is + * emitted. */ + ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update)); + fail_unless_equals_uint64 (segment.start, 200); + fail_unless_equals_uint64 (segment.position, 200); + fail_unless_equals_uint64 (segment.stop, 300); + fail_unless_equals_uint64 (segment.base, 50); + /* update didn't change */ + fail_unless (update == FALSE); + check_times (&segment, 200, 200, 50); + check_times (&segment, 250, 250, 100); + + update = TRUE; + /* seek relative to end, should not do anything since size is + * unknown. */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update); + fail_unless_equals_uint64 (segment.start, 200); + fail_unless_equals_uint64 (segment.position, 200); + fail_unless_equals_uint64 (segment.stop, 300); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless (update == FALSE); + check_times (&segment, 250, 250, 100); + + /* completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop); + fail_unless (res == FALSE); + + /* touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 200, &cstart, &cstop); + fail_unless (res == FALSE); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 250, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 250); + + /* inside, touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 200, 250, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 250); + + /* completely inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 250, 290, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 250); + fail_unless_equals_uint64 (cstop, 290); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 250, 350, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 250); + fail_unless_equals_uint64 (cstop, 300); + + /* invalid start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 300); + + /* start on lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 300); + + /* start inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 250); + fail_unless_equals_uint64 (cstop, 300); + + /* start outside on boundary */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 300, -1, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 350, -1, &cstart, &cstop); + fail_unless (res == FALSE); +} + +GST_END_TEST; + +/* mess with the segment structure in the bytes format */ +GST_START_TEST (segment_seek_size) +{ + GstSegment segment; + gboolean res; + guint64 cstart, cstop; + gboolean update; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + segment.duration = 200; + + /* configure segment to start 100 */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update); + fail_unless_equals_uint64 (segment.start, 100); + fail_unless_equals_uint64 (segment.position, 100); + fail_unless_equals_int64 (segment.stop, -1); + fail_unless (update == TRUE); + check_times (&segment, 100, 100, 0); + + /* do some clipping on the open range */ + /* completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop); + fail_unless (res == FALSE); + + /* touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* inside, touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 100, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* completely inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 150, 200, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, 200); + + /* invalid start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_int64 (cstop, -1); + + /* start on lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, -1); + + /* start inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, -1); + + /* add 100 to start, set stop to 300, stop clips to 200 */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update); + fail_unless_equals_uint64 (segment.start, 200); + fail_unless_equals_uint64 (segment.position, 200); + fail_unless_equals_uint64 (segment.stop, 200); + check_times (&segment, 200, 200, 0); + + /* add 100 to start (to 300), set stop to 200, this clips start + * to duration */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update); + fail_unless_equals_uint64 (segment.start, 200); + fail_unless_equals_uint64 (segment.position, 200); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless (update == FALSE); + check_times (&segment, 200, 200, 0); + + /* special case, segment's start and stop are identical */ + /* completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* completely outside also */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 250, 300, &cstart, &cstop); + fail_unless (res == FALSE); + + /* stop at boundary point. it's outside because stop is exclusive */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 100, 200, &cstart, &cstop); + fail_unless (res == FALSE); + + /* touching boundary point. it's inside because start at segment start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 200, 300, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 200); + + /* completely inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 200, 200, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 200); + + /* exclusively cover boundary point */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 150, 250, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 200); + + /* invalid start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 200, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 200); + + /* start on boundary point */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 200, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 200); + fail_unless_equals_uint64 (cstop, 200); + + /* start completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop); + fail_unless (res == FALSE); + + /* seek relative to end */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update); + fail_unless_equals_uint64 (segment.start, 100); + fail_unless_equals_uint64 (segment.position, 100); + fail_unless_equals_uint64 (segment.stop, 180); + fail_unless (update == TRUE); + check_times (&segment, 150, 150, 50); + + /* completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop); + fail_unless (res == FALSE); + + /* touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* inside, touching lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 100, 150, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 150); + + /* completely inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 150, 170, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, 170); + + /* partially inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, + 150, 250, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, 180); + + /* invalid start */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 180); + + /* start on lower bound */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 100, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 100); + fail_unless_equals_uint64 (cstop, 180); + + /* start inside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 150, -1, &cstart, &cstop); + fail_unless (res == TRUE); + fail_unless_equals_uint64 (cstart, 150); + fail_unless_equals_uint64 (cstop, 180); + + /* start outside on boundary */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 180, -1, &cstart, &cstop); + fail_unless (res == FALSE); + + /* start completely outside */ + res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 250, -1, &cstart, &cstop); + fail_unless (res == FALSE); +} + +GST_END_TEST; + +GST_START_TEST (segment_seek_reverse) +{ + GstSegment segment; + gboolean update; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + segment.duration = 200; + + /* configure segment to stop 100 */ + gst_segment_do_seek (&segment, -1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 100); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 100); + fail_unless (update == TRUE); + check_times (&segment, 100, 100, 0); + check_times (&segment, 50, 50, 50); + check_times (&segment, 0, 0, 100); + + /* update */ + gst_segment_do_seek (&segment, -1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update); + fail_unless_equals_uint64 (segment.start, 10); + fail_unless_equals_uint64 (segment.stop, 80); + fail_unless_equals_uint64 (segment.time, 10); + fail_unless_equals_uint64 (segment.position, 80); + fail_unless (update == TRUE); + check_times (&segment, 80, 80, 0); + check_times (&segment, 40, 40, 40); + check_times (&segment, 10, 10, 70); + + gst_segment_do_seek (&segment, -1.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update); + fail_unless_equals_uint64 (segment.start, 20); + fail_unless_equals_uint64 (segment.stop, 80); + fail_unless_equals_uint64 (segment.time, 20); + fail_unless_equals_uint64 (segment.position, 80); + fail_unless (update == FALSE); + check_times (&segment, 80, 80, 0); + check_times (&segment, 20, 20, 60); +} + +GST_END_TEST; + +/* mess with the segment structure in the bytes format */ +GST_START_TEST (segment_seek_rate) +{ + GstSegment segment; + gboolean update; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + + /* configure segment to rate 2.0 */ + gst_segment_do_seek (&segment, 2.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update); + fail_unless (segment.format == GST_FORMAT_BYTES); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.position, 0); + fail_unless_equals_int64 (segment.stop, -1); + fail_unless_equals_float (segment.rate, 2.0); + fail_unless (update == FALSE); + check_times (&segment, 50, 50, 25); + + /* set a real stop position, this must happen in bytes */ + gst_segment_do_seek (&segment, 3.0, + GST_FORMAT_BYTES, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update); + fail_unless (segment.format == GST_FORMAT_BYTES); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 100); + fail_unless_equals_float (segment.rate, 3.0); + /* no seek should happen, we just updated the stop position in forward + * playback mode.*/ + fail_unless (update == FALSE); + check_times (&segment, 60, 60, 20); + + /* set some duration, stop -1 END seeks will now work with the + * duration, if the formats match */ + segment.duration = 200; + + /* seek to end with 0 should set the stop to the duration */ + gst_segment_do_seek (&segment, 2.0, + GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.duration, 200); + + /* subtract 100 from the end */ + gst_segment_do_seek (&segment, 2.0, + GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update); + fail_unless_equals_uint64 (segment.stop, 100); + fail_unless_equals_uint64 (segment.duration, 200); + + /* add 100 to the duration, this should be clamped to the duration */ + gst_segment_do_seek (&segment, 2.0, + GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.duration, 200); +} + +GST_END_TEST; + +GST_START_TEST (segment_copy) +{ + GstSegment *copy; + GstSegment segment = { 0.0, }; + + /* this is a boxed type copy function, we support copying NULL */ + fail_unless (gst_segment_copy (NULL) == NULL); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.rate = -1.0; + segment.applied_rate = 1.0; + segment.start = 0; + segment.stop = 200; + segment.time = 0; + + copy = gst_segment_copy (&segment); + fail_unless (copy != NULL); + /* we inited the struct on the stack to zeroes, so direct comparison should + * be ok here despite the padding field and regardless of implementation */ + fail_unless (memcmp (copy, &segment, sizeof (GstSegment)) == 0); + gst_segment_free (copy); +} + +GST_END_TEST; + +/* mess with the segment structure in the bytes format */ +GST_START_TEST (segment_seek_noupdate) +{ + GstSegment segment; + gboolean update; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 0; + segment.position = 50; + segment.stop = 200; + segment.time = 0; + + /* doesn't change anything */ + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_TIME, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update); + fail_unless (update == FALSE); + fail_unless (segment.format == GST_FORMAT_TIME); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless_equals_uint64 (segment.offset, 50); + + gst_segment_do_seek (&segment, 2.0, + GST_FORMAT_TIME, + GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update); + fail_unless (update == FALSE); + fail_unless (segment.format == GST_FORMAT_TIME); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless_equals_uint64 (segment.offset, 50); + + gst_segment_do_seek (&segment, 1.0, + GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update); + fail_unless (update == FALSE); + fail_unless (segment.format == GST_FORMAT_TIME); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 50); +} + +GST_END_TEST; + +GST_START_TEST (segment_offset) +{ + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 0; + segment.position = 50; + segment.stop = 200; + segment.time = 0; + + check_times (&segment, 20, 20, 20); + check_times (&segment, 220, -1, -1); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + 0) == TRUE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 20, 20, 20); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + 100) == TRUE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 100); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 20, 20, 120); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -50) == TRUE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 20, 20, 70); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -100) == TRUE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 50); + check_times (&segment, 20, 20, -1); + check_times (&segment, 200, 200, 150); + + /* can go negative */ + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -151) == FALSE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 50); + check_times (&segment, 100, 100, 50); + check_times (&segment, 200, 200, 150); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -150) == TRUE); + fail_unless_equals_uint64 (segment.start, 0); + fail_unless_equals_uint64 (segment.stop, 200); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 200); + check_times (&segment, 200, 200, 0); + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 20; + segment.position = 50; + segment.stop = 220; + segment.time = 0; + + check_times (&segment, 40, 20, 20); + check_times (&segment, 240, -1, -1); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + 0) == TRUE); + fail_unless_equals_uint64 (segment.start, 20); + fail_unless_equals_uint64 (segment.stop, 220); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 40, 20, 20); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + 100) == TRUE); + fail_unless_equals_uint64 (segment.start, 20); + fail_unless_equals_uint64 (segment.stop, 220); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 100); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 40, 20, 120); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -50) == TRUE); + fail_unless_equals_uint64 (segment.start, 20); + fail_unless_equals_uint64 (segment.stop, 220); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 50); + fail_unless_equals_uint64 (segment.offset, 0); + check_times (&segment, 40, 20, 70); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -100) == TRUE); + fail_unless_equals_uint64 (segment.start, 20); + fail_unless_equals_uint64 (segment.stop, 220); + fail_unless_equals_uint64 (segment.time, 0); + fail_unless_equals_uint64 (segment.position, 50); + fail_unless_equals_uint64 (segment.base, 0); + fail_unless_equals_uint64 (segment.offset, 50); + check_times (&segment, 40, 20, -1); + check_times (&segment, 220, 200, 150); +} + +GST_END_TEST; + +GST_START_TEST (segment_full) +{ + GstSegment segment; + guint64 rt, pos; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 50; + segment.position = 150; + segment.stop = 200; + segment.time = 0; + + check_times (&segment, 100, 50, 50); + check_times (&segment, 220, -1, -1); + + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, + 50, &rt) == 1); + fail_unless (rt == 0); + fail_unless (gst_segment_position_from_running_time_full (&segment, + GST_FORMAT_TIME, rt, &pos) == 1); + fail_unless (pos == 50); + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, + 200, &rt) == 1); + fail_unless (rt == 150); + fail_unless (gst_segment_position_from_running_time_full (&segment, + GST_FORMAT_TIME, rt, &pos) == 1); + fail_unless (pos == 200); + fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 40, 40, NULL, + NULL)); + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 40, + &rt) == -1); + fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 49, 49, NULL, + NULL)); + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 49, + &rt) == -1); + fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 201, 201, NULL, + NULL)); + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 201, + &rt) == 1); + fail_unless (gst_segment_position_from_running_time_full (&segment, + GST_FORMAT_TIME, rt, &pos) == 1); + fail_unless (pos == 201); + + fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME, + -50) == TRUE); + fail_unless (segment.offset == 50); + + fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, + 50, &rt) == -1); + GST_DEBUG ("%" G_GUINT64_FORMAT, rt); + fail_unless (rt == 50); + + segment.start = 50; + segment.stop = 300; + segment.position = 150; + segment.time = 0; + segment.offset = 0; + gst_segment_set_running_time (&segment, GST_FORMAT_TIME, 100); + fail_unless_equals_int (segment.base, 100); + fail_unless (gst_segment_position_from_running_time_full (&segment, + GST_FORMAT_TIME, 70, &pos) == -1); + fail_unless (gst_segment_position_from_running_time_full (&segment, + GST_FORMAT_TIME, 140, &pos) == 1); + fail_unless_equals_int (pos, 190); +} + +GST_END_TEST; + +GST_START_TEST (segment_stream_time_full) +{ + GstSegment segment; + guint64 st, pos; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 50; + segment.stop = 200; + segment.time = 30; + segment.position = 0; + + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 0, &st) == -1); + fail_unless_equals_int (st, 20); + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 20, &st) == 1); + fail_unless_equals_int (st, 0); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 0, &pos) == 1); + fail_unless_equals_int (pos, 20); + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 10, &st) == -1); + fail_unless_equals_int (st, 10); + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 40, &st) == 1); + fail_unless_equals_int (st, 20); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, st, &pos) == 1); + fail_unless_equals_int (pos, 40); + segment.time = 100; + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 40, &pos) == -1); + fail_unless_equals_int (pos, 10); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 60, &pos) == 1); + fail_unless_equals_int (pos, 10); + + segment.start = 50; + segment.position = 150; + segment.stop = 200; + segment.time = 0; + segment.applied_rate = -1; + segment.rate = -1; + + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 0, &st) == 1); + fail_unless_equals_int (st, 200); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 200, &pos) == 1); + fail_unless_equals_int (pos, 0); + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 250, &st) == -1); + fail_unless_equals_int (st, 50); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 200, &pos) == 1); + fail_unless_equals_int (pos, 0); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 250, &pos) == -1); + fail_unless_equals_int (pos, 50); + + segment.time = 70; + fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME, + 250, &st) == 1); + fail_unless_equals_int (st, 20); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 50, &pos) == 1); + fail_unless_equals_int (pos, 220); + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 90, &pos) == 1); + fail_unless_equals_int (pos, 180); + + segment.stop = 60; + fail_unless (gst_segment_position_from_stream_time_full (&segment, + GST_FORMAT_TIME, 5, &pos) == 1); + fail_unless_equals_int (pos, 125); +} + +GST_END_TEST; + +GST_START_TEST (segment_negative_rate) +{ + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 50; + segment.position = 150; + segment.stop = 200; + segment.time = 0; + segment.applied_rate = -1; + segment.rate = -1; + + /* somewhere in the middle */ + check_times (&segment, 100, 100, 100); + /* after stop */ + check_times (&segment, 220, -1, -1); + /* before start */ + check_times (&segment, 10, -1, -1); + /* at segment start */ + check_times (&segment, 50, 150, 150); + /* another place in the middle */ + check_times (&segment, 150, 50, 50); + /* at segment stop */ + check_times (&segment, 200, 0, 0); + + segment.time = 100; + segment.base = 100; + /* somewhere in the middle */ + check_times (&segment, 100, 200, 200); + /* at segment start */ + check_times (&segment, 50, 250, 250); + /* another place in the middle */ + check_times (&segment, 150, 150, 150); + /* at segment stop */ + check_times (&segment, 200, 100, 100); +} + +GST_END_TEST; + +GST_START_TEST (segment_negative_applied_rate) +{ + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + segment.start = 50; + segment.position = 150; + segment.stop = 200; + segment.time = 0; + segment.applied_rate = -1; + segment.rate = 1; + + /* somewhere in the middle */ + check_times (&segment, 100, 100, 50); + /* after stop */ + check_times (&segment, 220, -1, -1); + /* before start */ + check_times (&segment, 10, -1, -1); + /* at segment start */ + check_times (&segment, 50, 150, 0); + /* another place in the middle */ + check_times (&segment, 150, 50, 100); + /* at segment stop */ + check_times (&segment, 200, 0, 150); + + segment.time = 100; + segment.base = 100; + /* somewhere in the middle */ + check_times (&segment, 100, 200, 150); + /* at segment start */ + check_times (&segment, 50, 250, 100); + /* another place in the middle */ + check_times (&segment, 150, 150, 200); + /* at segment stop */ + check_times (&segment, 200, 100, 250); +} + +GST_END_TEST; + +static Suite * +gst_segment_suite (void) +{ + Suite *s = suite_create ("GstSegment"); + TCase *tc_chain = tcase_create ("segments"); + + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, segment_seek_nosize); + tcase_add_test (tc_chain, segment_seek_size); + tcase_add_test (tc_chain, segment_seek_reverse); + tcase_add_test (tc_chain, segment_seek_rate); + tcase_add_test (tc_chain, segment_copy); + tcase_add_test (tc_chain, segment_seek_noupdate); + tcase_add_test (tc_chain, segment_offset); + tcase_add_test (tc_chain, segment_full); + tcase_add_test (tc_chain, segment_negative_rate); + tcase_add_test (tc_chain, segment_negative_applied_rate); + tcase_add_test (tc_chain, segment_stream_time_full); + + return s; +} + +GST_CHECK_MAIN (gst_segment); diff --git a/tests/check/gst/gststream.c b/tests/check/gst/gststream.c new file mode 100644 index 0000000..4ff15d0 --- /dev/null +++ b/tests/check/gst/gststream.c @@ -0,0 +1,227 @@ +/* GStreamer + * Copyright (C) <2015> Edward Hervey + * + * gststructure.c: Unit tests for GstStream and GstStreamCollection + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_stream_creation) +{ + GstStream *stream; + GstCaps *caps; + GstCaps *caps2; + GstTagList *tags, *tags2; + + caps = gst_caps_from_string ("some/caps"); + stream = gst_stream_new ("stream-id", caps, GST_STREAM_TYPE_AUDIO, 0); + fail_unless (stream != NULL); + + fail_unless_equals_string (gst_stream_get_stream_id (stream), "stream-id"); + caps2 = gst_stream_get_caps (stream); + fail_unless (gst_caps_is_equal (caps, caps2)); + gst_caps_unref (caps2); + + fail_unless (gst_stream_get_stream_type (stream) == GST_STREAM_TYPE_AUDIO); + + gst_caps_unref (caps); + + tags = gst_tag_list_new (GST_TAG_ALBUM, "test-album", NULL); + g_object_set (stream, "tags", tags, NULL); + tags2 = gst_stream_get_tags (stream); + fail_unless (gst_tag_list_is_equal (tags, tags2)); + gst_tag_list_unref (tags); + gst_tag_list_unref (tags2); + + gst_object_unref (stream); +} + +GST_END_TEST; + +GST_START_TEST (test_stream_event) +{ + GstEvent *event; + GstStream *stream, *stream2 = NULL; + GstCaps *caps; + GstCaps *caps2; + + event = gst_event_new_stream_start ("here/we/go"); + /* By default a stream-start event has no stream */ + gst_event_parse_stream (event, &stream2); + fail_if (stream2 != NULL); + + /* Create and set stream on event */ + caps = gst_caps_from_string ("some/caps"); + stream = gst_stream_new ("here/we/go", caps, GST_STREAM_TYPE_AUDIO, 0); + fail_unless (stream != NULL); + gst_event_set_stream (event, stream); + + /* Parse and check it's the same */ + gst_event_parse_stream (event, &stream2); + fail_unless (stream2 != NULL); + fail_unless_equals_string (gst_stream_get_stream_id (stream2), "here/we/go"); + caps2 = gst_stream_get_caps (stream); + fail_unless (gst_caps_is_equal (caps, caps2)); + fail_unless (gst_stream_get_stream_type (stream) == GST_STREAM_TYPE_AUDIO); + gst_caps_unref (caps2); + + gst_event_unref (event); + gst_caps_unref (caps); + gst_object_unref (stream); + gst_object_unref (stream2); +} + +GST_END_TEST; + +struct NotifyStats +{ + guint collection_notify; + guint collection_notify_caps; + guint collection_notify_tags; + guint collection_notify_type; + guint collection_notify_flags; + + guint stream_notify; + guint stream_notify_caps; + guint stream_notify_tags; + guint stream_notify_type; + guint stream_notify_flags; + + guint stream2_notify; + guint stream2_notify_caps; + guint stream2_notify_tags; + guint stream2_notify_type; + guint stream2_notify_flags; +}; + +static void +stream_notify_cb (GstStreamCollection * collection, GstStream * stream, + GParamSpec * pspec, guint * val) +{ + GST_LOG ("Got stream-notify from %" GST_PTR_FORMAT " for %s from %" + GST_PTR_FORMAT, stream, pspec->name, collection); + (*val)++; +} + +static void +notify_cb (GstStream * stream, GParamSpec * pspec, guint * val) +{ + GST_LOG ("Got notify from %" GST_PTR_FORMAT " for %s", stream, pspec->name); + (*val)++; +} + +GST_START_TEST (test_notifies) +{ + GstStreamCollection *collection; + GstStream *stream, *stream2 = NULL; + GstCaps *caps; + struct NotifyStats stats = { 0, }; + GstTagList *tags; + + collection = gst_stream_collection_new ("check-collection"); + g_signal_connect (collection, "stream-notify", (GCallback) stream_notify_cb, + &stats.collection_notify); + g_signal_connect (collection, "stream-notify::stream-type", + (GCallback) stream_notify_cb, &stats.collection_notify_type); + g_signal_connect (collection, "stream-notify::stream-flags", + (GCallback) stream_notify_cb, &stats.collection_notify_flags); + g_signal_connect (collection, "stream-notify::caps", + (GCallback) stream_notify_cb, &stats.collection_notify_caps); + g_signal_connect (collection, "stream-notify::tags", + (GCallback) stream_notify_cb, &stats.collection_notify_tags); + + caps = gst_caps_from_string ("some/audio-caps"); + stream = gst_stream_new ("here/we/go", caps, GST_STREAM_TYPE_AUDIO, 0); + gst_caps_unref (caps); + g_signal_connect (stream, "notify", (GCallback) notify_cb, + &stats.stream_notify); + g_signal_connect (stream, "notify::stream-type", (GCallback) notify_cb, + &stats.stream_notify_type); + g_signal_connect (stream, "notify::stream-flags", (GCallback) notify_cb, + &stats.stream_notify_flags); + g_signal_connect (stream, "notify::caps", (GCallback) notify_cb, + &stats.stream_notify_caps); + g_signal_connect (stream, "notify::tags", (GCallback) notify_cb, + &stats.stream_notify_tags); + gst_stream_collection_add_stream (collection, stream); + + caps = gst_caps_from_string ("some/video-caps"); + stream2 = gst_stream_new ("here/we/go/again", caps, GST_STREAM_TYPE_VIDEO, 0); + gst_caps_unref (caps); + g_signal_connect (stream2, "notify", (GCallback) notify_cb, + &stats.stream2_notify); + g_signal_connect (stream2, "notify::stream-type", (GCallback) notify_cb, + &stats.stream2_notify_type); + g_signal_connect (stream2, "notify::stream-flags", (GCallback) notify_cb, + &stats.stream2_notify_flags); + g_signal_connect (stream2, "notify::caps", (GCallback) notify_cb, + &stats.stream2_notify_caps); + g_signal_connect (stream2, "notify::tags", (GCallback) notify_cb, + &stats.stream2_notify_tags); + gst_stream_collection_add_stream (collection, stream2); + + caps = gst_caps_from_string ("some/new-video-caps"); + gst_stream_set_caps (stream2, caps); + gst_caps_unref (caps); + + fail_unless (stats.collection_notify == 1); + fail_unless (stats.collection_notify_caps == 1); + fail_unless (stats.stream_notify == 0); + fail_unless (stats.stream_notify_caps == 0); + fail_unless (stats.stream_notify_tags == 0); + fail_unless (stats.stream2_notify == 1); + fail_unless (stats.stream2_notify_caps == 1); + fail_unless (stats.stream2_notify_tags == 0); + + tags = gst_tag_list_new (GST_TAG_ALBUM, "test-album", NULL); + gst_stream_set_tags (stream, tags); + gst_tag_list_unref (tags); + + fail_unless (stats.collection_notify == 2); + fail_unless (stats.collection_notify_caps == 1); + fail_unless (stats.collection_notify_tags == 1); + fail_unless (stats.stream_notify == 1); + fail_unless (stats.stream_notify_caps == 0); + fail_unless (stats.stream_notify_tags == 1); + fail_unless (stats.stream2_notify == 1); + fail_unless (stats.stream2_notify_caps == 1); + fail_unless (stats.stream2_notify_tags == 0); + + gst_object_unref (collection); +} + +GST_END_TEST; + +static Suite * +gst_streams_suite (void) +{ + Suite *s = suite_create ("GstStream"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_stream_creation); + tcase_add_test (tc_chain, test_stream_event); + tcase_add_test (tc_chain, test_notifies); + return s; +} + +GST_CHECK_MAIN (gst_streams); diff --git a/tests/check/gst/gststructure.c b/tests/check/gst/gststructure.c new file mode 100644 index 0000000..cce6665 --- /dev/null +++ b/tests/check/gst/gststructure.c @@ -0,0 +1,908 @@ +/* GStreamer + * Copyright (C) <2005> Thomas Vander Stichele + * + * gststructure.c: Unit tests for GstStructure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + + +GST_START_TEST (test_from_string_int) +{ + const char *strings[] = { + "video/x-raw, width = (int) 123456", + "video/x-raw, stride = (int) -123456", + "video/x-raw, red_mask = (int) 0xFFFF", + "video/x-raw, red_mask = (int) 0x0000FFFF", + "video/x-raw, red_mask = (int) 0x7FFFFFFF", + "video/x-raw, red_mask = (int) 0x80000000", + "video/x-raw, red_mask = (int) 0xFF000000", + /* result from + * gst-launch ... ! "video/x-raw, red_mask=(int)0xFF000000" ! ... */ + "video/x-raw,\\ red_mask=(int)0xFF000000", + }; + gint results[] = { + 123456, + -123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + (gint) 0x80000000, + (gint) 0xFF000000, + (gint) 0xFF000000, + }; + GstStructure *structure; + int i; + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + const char *s; + const gchar *name; + gint value; + + s = strings[i]; + + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + name = gst_structure_nth_field_name (structure, 0); + fail_unless (gst_structure_get_int (structure, name, &value)); + fail_unless (value == results[i], + "Value %d is not the expected result %d for string %s", + value, results[i], s); + + /* cleanup */ + gst_structure_free (structure); + } +} + +GST_END_TEST; + +GST_START_TEST (test_from_string_uint) +{ + const char *strings[] = { + "taglist, bar = (uint) 123456", + "taglist, bar = (uint) 0xFFFF", + "taglist, bar = (uint) 0x0000FFFF", + "taglist, bar = (uint) 0x7FFFFFFF", + "taglist, bar = (uint) 0x80000000", + "taglist, bar = (uint) 0xFF000000" + }; + guint results[] = { + 123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + 0x80000000, + 0xFF000000, + }; + GstStructure *structure; + int i; + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + const char *s; + const gchar *name; + guint value; + + s = strings[i]; + + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + name = gst_structure_nth_field_name (structure, 0); + fail_unless (gst_structure_get_uint (structure, name, &value)); + fail_unless (value == results[i], + "Value %u is not the expected result %u for string %s", + value, results[i], s); + + /* cleanup */ + gst_structure_free (structure); + } +} + +GST_END_TEST; + +/* Test type conversions from string */ +GST_START_TEST (test_from_string) +{ + GstStructure *structure; + const gchar *s; + const GValue *val; + + s = "test-string,value=1"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (G_VALUE_HOLDS_INT (val)); + gst_structure_free (structure); + + s = "test-string,value=1.0"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (G_VALUE_HOLDS_DOUBLE (val)); + gst_structure_free (structure); + + s = "test-string,value=1/1"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (GST_VALUE_HOLDS_FRACTION (val)); + gst_structure_free (structure); + + s = "test-string,value=bar"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (G_VALUE_HOLDS_STRING (val)); + gst_structure_free (structure); + + s = "test-string,value=true"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (G_VALUE_HOLDS_BOOLEAN (val)); + fail_unless_equals_int (g_value_get_boolean (val), TRUE); + gst_structure_free (structure); + + /* Tests for flagset deserialisation */ + s = "foobar,value=0010:ffff"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (GST_VALUE_HOLDS_FLAG_SET (val)); + gst_structure_free (structure); + + /* In the presence of the hex values, the strings don't matter as long as they + * have the right form */ + s = "foobar,value=0010:ffff:+random+other/not-the-other"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL); + fail_unless (GST_VALUE_HOLDS_FLAG_SET (val)); + gst_structure_free (structure); + + /* Test that a timecode string is deserialised as a string, not a flagset: + * https://bugzilla.gnome.org/show_bug.cgi?id=779755 */ + s = "foobar,timecode=00:01:00:00"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + fail_unless ((val = gst_structure_get_value (structure, "timecode")) != NULL); + fail_unless (G_VALUE_HOLDS_STRING (val)); + gst_structure_free (structure); + + s = "0.10:decoder-video/mpeg, abc=(boolean)false"; + ASSERT_CRITICAL (structure = gst_structure_from_string (s, NULL)); + fail_unless (structure == NULL, "Could not get structure from string %s", s); + + /* make sure we bail out correctly in case of an error or if parsing fails */ + s = "***foo***, abc=(boolean)false"; + structure = gst_structure_from_string (s, NULL); + fail_unless (structure == NULL); + + /* assert that we get a warning if the structure wasn't entirely consumed, but + * we didn't provide an end pointer */ + s = "foo/bar; other random data"; + ASSERT_WARNING (structure = gst_structure_from_string (s, NULL)); + fail_if (structure == NULL, "Could not get structure from string %s", s); + gst_structure_free (structure); + + /* make sure we handle \ as last character in various things, run with valgrind */ + s = "foo,test=\"foobar\\"; + structure = gst_structure_from_string (s, NULL); + fail_unless (structure == NULL); + s = "\\"; + structure = gst_structure_from_string (s, NULL); + fail_unless (structure == NULL); + s = "foobar,test\\"; + structure = gst_structure_from_string (s, NULL); + fail_unless (structure == NULL); + s = "foobar,test=(string)foo\\"; + structure = gst_structure_from_string (s, NULL); + fail_unless (structure == NULL); +} + +GST_END_TEST; + + +GST_START_TEST (test_to_string) +{ + GstStructure *st1; + + ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo\nwith-newline")); + fail_unless (st1 == NULL); + + ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo with whitespace")); + fail_unless (st1 == NULL); + ASSERT_CRITICAL (st1 = gst_structure_new_empty ("1st")); + fail_unless (st1 == NULL); +} + +GST_END_TEST; + + +GST_START_TEST (test_to_from_string) +{ + GstStructure *st1, *st2; + gchar *str; + + /* test escaping/unescaping */ + st1 = gst_structure_new ("FooBar-123/0_1", "num", G_TYPE_INT, 9173, + "string", G_TYPE_STRING, "Something Like Face/Off", NULL); + str = gst_structure_to_string (st1); + st2 = gst_structure_from_string (str, NULL); + g_free (str); + + fail_unless (st2 != NULL); + fail_unless (gst_structure_is_equal (st1, st2), + "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT + "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2); + + gst_structure_free (st1); + gst_structure_free (st2); + + /* Test NULL strings */ + st1 = gst_structure_new ("test", "mynullstr", G_TYPE_STRING, NULL, NULL); + fail_unless (st1 != NULL); + str = gst_structure_to_string (st1); + fail_unless (strcmp (str, "test, mynullstr=(string)NULL;") == 0, + "Failed to serialize to right string: %s", str); + + st2 = gst_structure_from_string (str, NULL); + fail_unless (st2 != NULL); + g_free (str); + + fail_unless (gst_structure_is_equal (st1, st2), + "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT + "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2); + + gst_structure_free (st1); + gst_structure_free (st2); +} + +GST_END_TEST; + +/* Added to make sure taglists are properly serialized/deserialized after bug + * https://bugzilla.gnome.org/show_bug.cgi?id=733131 */ +GST_START_TEST (test_to_from_string_tag_event) +{ + GstEvent *tagevent; + GstTagList *taglist; + GstStructure *st1, *st2; + gchar *str; + + /* empty taglist */ + taglist = gst_tag_list_new_empty (); + tagevent = gst_event_new_tag (taglist); + + st1 = (GstStructure *) gst_event_get_structure (tagevent); + str = gst_structure_to_string (st1); + fail_unless (str != NULL); + + st2 = gst_structure_new_from_string (str); + fail_unless (st2 != NULL); + fail_unless (gst_structure_is_equal (st1, st2)); + gst_event_unref (tagevent); + gst_structure_free (st2); + g_free (str); + + /* taglist with data */ + taglist = gst_tag_list_new ("title", "TEST TITLE", NULL); + tagevent = gst_event_new_tag (taglist); + + st1 = (GstStructure *) gst_event_get_structure (tagevent); + str = gst_structure_to_string (st1); + fail_unless (str != NULL); + + st2 = gst_structure_new_from_string (str); + fail_unless (st2 != NULL); + fail_unless (gst_structure_is_equal (st1, st2)); + gst_event_unref (tagevent); + gst_structure_free (st2); + g_free (str); +} + +GST_END_TEST; + +GST_START_TEST (test_complete_structure) +{ + GstStructure *structure; + const gchar *s; + + s = "GstEventSeek, rate=(double)1, format=(GstFormat)GST_FORMAT_TIME, flags=(GstSeekFlags)GST_SEEK_FLAG_NONE, start_type=(GstSeekType)GST_SEEK_TYPE_SET, start=(gint64)1000000000, stop_type=(GstSeekType)GST_SEEK_TYPE_NONE, stop=(gint64)0"; + structure = gst_structure_from_string (s, NULL); + fail_if (structure == NULL, "Could not get structure from string %s", s); + /* FIXME: TODO: add checks for correct serialization of members ? */ + gst_structure_free (structure); +} + +GST_END_TEST; + +GST_START_TEST (test_string_properties) +{ + GstStructure *st1, *st2; + gchar *str; + + /* test escaping/unescaping */ + st1 = gst_structure_new ("RandomStructure", "prop1", G_TYPE_STRING, "foo", + "prop2", G_TYPE_STRING, "", "prop3", G_TYPE_STRING, NULL, + "prop4", G_TYPE_STRING, "NULL", NULL); + str = gst_structure_to_string (st1); + st2 = gst_structure_from_string (str, NULL); + g_free (str); + + fail_unless (st2 != NULL); + fail_unless (gst_structure_is_equal (st1, st2), + "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT + "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2); + + gst_structure_free (st1); + gst_structure_free (st2); +} + +GST_END_TEST; + +GST_START_TEST (test_structure_new) +{ + GstStructure *s; + GError *e; + GQuark domain; + gboolean bool; + gint num, den; + GstClockTime clocktime; + guint64 uint64; + + s = gst_structure_new ("name", + "key", G_TYPE_STRING, "value", + "bool", G_TYPE_BOOLEAN, TRUE, + "fraction", GST_TYPE_FRACTION, 1, 5, + "clocktime", GST_TYPE_CLOCK_TIME, GST_CLOCK_TIME_NONE, + "uint64", G_TYPE_UINT64, (guint64) 1234, NULL); + + fail_unless (gst_structure_get_field_type (s, "unknown") == G_TYPE_INVALID); + /* test setting a different name */ + gst_structure_set_name (s, "newname"); + fail_unless (strcmp (gst_structure_get_string (s, "key"), "value") == 0); + fail_unless (gst_structure_has_field (s, "key")); + fail_unless_equals_int (gst_structure_n_fields (s), 5); + /* test removing a field */ + gst_structure_remove_field (s, "key"); + fail_if (gst_structure_get_string (s, "key")); + fail_if (gst_structure_has_field (s, "key")); + fail_unless_equals_int (gst_structure_n_fields (s), 4); + + fail_unless (gst_structure_get_boolean (s, "bool", &bool)); + fail_unless (bool); + + fail_unless (gst_structure_get_fraction (s, "fraction", &num, &den)); + fail_unless_equals_int (num, 1); + fail_unless_equals_int (den, 5); + + fail_unless (gst_structure_get_clock_time (s, "clocktime", &clocktime)); + fail_unless_equals_uint64 (clocktime, GST_CLOCK_TIME_NONE); + + fail_unless (gst_structure_get_uint64 (s, "uint64", &uint64)); + fail_unless_equals_uint64 (uint64, 1234); + + gst_structure_free (s); + + domain = g_quark_from_static_string ("test"); + e = g_error_new (domain, 0, "a test error"); + s = gst_structure_new ("name", "key", G_TYPE_ERROR, e, NULL); + g_error_free (e); + gst_structure_free (s); + + ASSERT_CRITICAL (gst_structure_free (gst_structure_new_empty + ("0.10:decoder-video/mpeg"))); + + /* make sure we bail out correctly in case of an error or if parsing fails */ + ASSERT_CRITICAL (s = gst_structure_new ("^joo\nba\ndoo^", + "abc", G_TYPE_BOOLEAN, FALSE, NULL)); + fail_unless (s == NULL); +} + +GST_END_TEST; + +GST_START_TEST (test_fixate) +{ + GstStructure *s; + + s = gst_structure_new ("name", + "int", G_TYPE_INT, 5, + "intrange", GST_TYPE_INT_RANGE, 5, 10, + "intrange2", GST_TYPE_INT_RANGE, 5, 10, NULL); + + fail_if (gst_structure_fixate_field_nearest_int (s, "int", 5)); + fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange", 5)); + fail_if (gst_structure_fixate_field_nearest_int (s, "intrange", 5)); + fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange2", 15)); + fail_if (gst_structure_fixate_field_nearest_int (s, "intrange2", 15)); + gst_structure_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_fixate_frac_list) +{ + GstStructure *s, *s2; + GValue list = { 0 }; + GValue frac = { 0 }; + gchar *str; + gint num, denom; + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&frac, GST_TYPE_FRACTION); + + gst_value_set_fraction (&frac, 30, 1); + gst_value_list_append_value (&list, &frac); + gst_value_set_fraction (&frac, 15, 1); + gst_value_list_append_value (&list, &frac); + gst_value_set_fraction (&frac, 10, 1); + gst_value_list_append_value (&list, &frac); + + s = gst_structure_new_empty ("name"); + gst_structure_set_value (s, "frac", &list); + g_value_unset (&frac); + g_value_unset (&list); + + str = gst_structure_to_string (s); + GST_DEBUG ("list %s", str); + g_free (str); + + /* take copy */ + s2 = gst_structure_copy (s); + + /* fixate to the nearest fraction, this should give 15/1 */ + fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1)); + + fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom)); + fail_unless (num == 15); + fail_unless (denom == 1); + + gst_structure_free (s); + s = s2; + + /* fixate to the nearest fraction, this should give 30/1 */ + fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", G_MAXINT, + 1)); + + fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom)); + fail_unless (num == 30); + fail_unless (denom == 1); + gst_structure_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_is_subset_equal_array_list) +{ + GstStructure *s1, *s2; + + s1 = gst_structure_from_string ("test/test, channels=(int){ 1, 2 }", NULL); + fail_if (s1 == NULL); + s2 = gst_structure_from_string ("test/test, channels=(int)[ 1, 2 ]", NULL); + fail_if (s2 == NULL); + + fail_unless (gst_structure_is_subset (s1, s2)); + + gst_structure_free (s1); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_is_subset_different_name) +{ + GstStructure *s1, *s2; + + s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL); + fail_if (s1 == NULL); + s2 = gst_structure_from_string ("test/baz, channels=(int)1", NULL); + fail_if (s2 == NULL); + + fail_unless (!gst_structure_is_subset (s1, s2)); + + gst_structure_free (s1); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_is_subset_superset_missing_fields) +{ + GstStructure *s1, *s2; + + /* a missing field is equivalent to any value */ + s1 = gst_structure_from_string ("test/test, channels=(int)1, rate=(int)1", + NULL); + fail_if (s1 == NULL); + s2 = gst_structure_from_string ("test/test, channels=(int)1", NULL); + fail_if (s2 == NULL); + + fail_unless (gst_structure_is_subset (s1, s2)); + + gst_structure_free (s1); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_is_subset_superset_extra_fields) +{ + GstStructure *s1, *s2; + + /* a missing field is equivalent to any value */ + s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL); + fail_if (s1 == NULL); + s2 = gst_structure_from_string ("test/test, channels=(int)1, rate=(int)1", + NULL); + fail_if (s2 == NULL); + + fail_unless (!gst_structure_is_subset (s1, s2)); + + gst_structure_free (s1); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_is_subset_superset_extra_values) +{ + GstStructure *s1, *s2; + + s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL); + fail_if (s1 == NULL); + s2 = gst_structure_from_string ("test/test, channels=(int)[ 1, 2 ]", NULL); + fail_if (s2 == NULL); + + fail_unless (gst_structure_is_subset (s1, s2)); + + gst_structure_free (s1); + gst_structure_free (s2); +} + +GST_END_TEST; + + +GST_START_TEST (test_structure_nested) +{ + GstStructure *sp, *sc1, *sc2; + gchar *str; + + sc1 = gst_structure_new ("Camera", + "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL); + fail_unless (sc1 != NULL); + + sc2 = gst_structure_new ("Image-Data", + "Orientation", G_TYPE_STRING, "top-left", + "Comment", G_TYPE_STRING, "super photo", NULL); + fail_unless (sc2 != NULL); + + sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1, + "Image Data", GST_TYPE_STRUCTURE, sc2, NULL); + fail_unless (sp != NULL); + + fail_unless (gst_structure_n_fields (sp) == 2); + + fail_unless (gst_structure_has_field_typed (sp, "Camera", + GST_TYPE_STRUCTURE)); + + str = gst_structure_to_string (sp); + fail_unless (str != NULL); + + GST_DEBUG ("serialized to '%s'", str); + + fail_unless (g_str_equal (str, + "Exif" + ", Camera=(structure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\"" + ", Image Data=(structure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";")); + + g_free (str); + str = NULL; + + gst_structure_free (sc1); + gst_structure_free (sc2); + gst_structure_free (sp); +} + +GST_END_TEST; + +GST_START_TEST (test_structure_nested_from_and_to_string) +{ + GstStructure *s; + const gchar *str1; + gchar *str2, *end = NULL; + + str1 = "main" + ", main-sub1=(structure)\"type-b\\,\\ machine-type\\=\\(int\\)0\\;\"" + ", main-sub2=(structure)\"type-a\\,\\ plugin-filename\\=\\(string\\)\\\"/home/user/lib/lib\\\\\\ with\\\\\\ spaces.dll\\\"\\,\\ machine-type\\=\\(int\\)1\\;\"" + ", main-sub3=(structure)\"type-b\\,\\ plugin-filename\\=\\(string\\)/home/user/lib/lib_no_spaces.so\\,\\ machine-type\\=\\(int\\)1\\;\"" + ";"; + + s = gst_structure_from_string (str1, &end); + fail_unless (s != NULL); + + GST_DEBUG ("not parsed part : %s", end); + fail_unless (*end == '\0'); + + fail_unless (gst_structure_n_fields (s) == 3); + + fail_unless (gst_structure_has_field_typed (s, "main-sub1", + GST_TYPE_STRUCTURE)); + + str2 = gst_structure_to_string (s); + fail_unless (str2 != NULL); + + fail_unless (g_str_equal (str1, str2)); + + g_free (str2); + + gst_structure_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_vararg_getters) +{ + GstStructure *s; + GstBuffer *buf, *buf2; + gboolean ret; + GstCaps *caps, *caps2; + GstMapInfo info; + gdouble d; + gint64 i64; + gchar *c; + gint i, num, denom; + guint8 *data; + + buf = gst_buffer_new_and_alloc (3); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + data = info.data; + data[0] = 0xf0; + data[1] = 0x66; + data[2] = 0x0d; + gst_buffer_unmap (buf, &info); + + caps = gst_caps_new_empty_simple ("video/x-foo"); + + s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string", + G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps", + GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99), + "double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14, + NULL); + + /* first the plain one */ + ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string", + G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf", + GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int", + G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL); + + fail_unless (ret); + fail_unless_equals_string (c, "Hello World!"); + fail_unless_equals_int (i, 12345678); + fail_unless_equals_float (d, G_MAXDOUBLE); + fail_unless_equals_int (num, 39); + fail_unless_equals_int (denom, 14); + fail_unless (i64 == -99); + fail_unless (caps == caps2); + fail_unless (buf == buf2); + + /* expected failures */ + ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL)); + fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double", + G_TYPE_FLOAT, &d, NULL)); + fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble", + G_TYPE_DOUBLE, &d, NULL)); + + g_free (c); + c = NULL; + gst_caps_unref (caps2); + caps2 = NULL; + gst_buffer_unref (buf2); + buf2 = NULL; + + /* and now the _id variant */ + ret = gst_structure_id_get (s, g_quark_from_static_string ("double"), + G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING, + &c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2, + g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2, + g_quark_from_static_string ("int"), G_TYPE_INT, &i, + g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL); + + fail_unless (ret); + fail_unless_equals_string (c, "Hello World!"); + fail_unless_equals_int (i, 12345678); + fail_unless_equals_float (d, G_MAXDOUBLE); + fail_unless (i64 == -99); + fail_unless (caps == caps2); + fail_unless (buf == buf2); + + /* expected failures */ + ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL)); + fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"), + G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT, + &d, NULL)); + fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"), + G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE, + &d, NULL)); + + g_free (c); + gst_caps_unref (caps2); + gst_buffer_unref (buf2); + + /* finally make sure NULL as return location is handled gracefully */ + ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string", + G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf", + GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION, + NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL); + + ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL, + &denom, NULL)); + ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num, + NULL, NULL)); + + /* clean up */ + gst_caps_unref (caps); + gst_buffer_unref (buf); + gst_structure_free (s); +} + +GST_END_TEST; + +static gboolean +foreach_func (GQuark field_id, const GValue * value, gpointer user_data) +{ + gint *sum = user_data; + gint v = 0; + + if (G_VALUE_HOLDS_INT (value)) + v = g_value_get_int (value); + *sum += v; + + return TRUE; +} + +GST_START_TEST (test_foreach) +{ + GstStructure *s; + gint sum = 0; + + s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3, + NULL); + fail_unless (gst_structure_foreach (s, foreach_func, &sum)); + fail_unless_equals_int (sum, 4); + gst_structure_free (s); + +} + +GST_END_TEST; + +static gboolean +map_func (GQuark field_id, GValue * value, gpointer user_data) +{ + if (G_VALUE_HOLDS_INT (value)) + g_value_set_int (value, 123); + + return TRUE; +} + +GST_START_TEST (test_map_in_place) +{ + GstStructure *s, *s2; + + s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3, + NULL); + s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 123, "bla", G_TYPE_INT, + 123, NULL); + fail_unless (gst_structure_map_in_place (s, map_func, NULL)); + fail_unless (gst_structure_is_equal (s, s2)); + gst_structure_free (s); + gst_structure_free (s2); + +} + +GST_END_TEST; + +static gboolean +filter_map_func (GQuark field_id, GValue * value, gpointer user_data) +{ + if (strcmp (g_quark_to_string (field_id), "bla") == 0) + return FALSE; + + if (G_VALUE_HOLDS_INT (value)) + g_value_set_int (value, 2); + + return TRUE; +} + +GST_START_TEST (test_filter_and_map_in_place) +{ + GstStructure *s, *s2; + + s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3, + NULL); + s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 2, NULL); + gst_structure_filter_and_map_in_place (s, filter_map_func, NULL); + fail_unless (gst_structure_is_equal (s, s2)); + gst_structure_free (s); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_flagset) +{ + GstStructure *s; + GType test_flagset_type; + guint test_flags = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_SNAP_AFTER; + guint test_mask = GST_FLAG_SET_MASK_EXACT; + guint out_flags, out_mask; + + test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS); + fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET)); + + /* Check that we can retrieve a non-standard flagset from the structure */ + s = gst_structure_new ("test-struct", "test-flagset", test_flagset_type, + test_flags, test_mask, NULL); + fail_unless (gst_structure_get_flagset (s, "test-flagset", &out_flags, + &out_mask)); + + fail_unless (out_flags == test_flags); + fail_unless (out_mask == test_mask); + gst_structure_free (s); +} + +GST_END_TEST; + +static Suite * +gst_structure_suite (void) +{ + Suite *s = suite_create ("GstStructure"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_from_string_int); + tcase_add_test (tc_chain, test_from_string_uint); + tcase_add_test (tc_chain, test_from_string); + tcase_add_test (tc_chain, test_to_string); + tcase_add_test (tc_chain, test_to_from_string); + tcase_add_test (tc_chain, test_to_from_string_tag_event); + tcase_add_test (tc_chain, test_string_properties); + tcase_add_test (tc_chain, test_complete_structure); + tcase_add_test (tc_chain, test_structure_new); + tcase_add_test (tc_chain, test_fixate); + tcase_add_test (tc_chain, test_fixate_frac_list); + tcase_add_test (tc_chain, test_is_subset_equal_array_list); + tcase_add_test (tc_chain, test_is_subset_different_name); + tcase_add_test (tc_chain, test_is_subset_superset_missing_fields); + tcase_add_test (tc_chain, test_is_subset_superset_extra_fields); + tcase_add_test (tc_chain, test_is_subset_superset_extra_values); + tcase_add_test (tc_chain, test_structure_nested); + tcase_add_test (tc_chain, test_structure_nested_from_and_to_string); + tcase_add_test (tc_chain, test_vararg_getters); + tcase_add_test (tc_chain, test_foreach); + tcase_add_test (tc_chain, test_map_in_place); + tcase_add_test (tc_chain, test_filter_and_map_in_place); + tcase_add_test (tc_chain, test_flagset); + return s; +} + +GST_CHECK_MAIN (gst_structure); diff --git a/tests/check/gst/gstsystemclock.c b/tests/check/gst/gstsystemclock.c new file mode 100644 index 0000000..59b3af1 --- /dev/null +++ b/tests/check/gst/gstsystemclock.c @@ -0,0 +1,940 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstsystemclock.c: Unit test for GstSystemClock + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GMutex af_lock; +static GCond af_cond; + +/* see if the defines make sense */ +GST_START_TEST (test_range) +{ + GstClockTime time, time2; + + time = GST_SECOND; + fail_unless (time == G_GUINT64_CONSTANT (1000000000)); + + time2 = time / 1000; + fail_unless (time2 == 1000000); + fail_unless (time2 == GST_MSECOND); + fail_unless (time2 == GST_TIME_AS_USECONDS (time)); + + time2 = time / 1000000; + fail_unless (time2 == 1000); + fail_unless (time2 == GST_USECOND); + fail_unless (time2 == GST_TIME_AS_MSECONDS (time)); +} + +GST_END_TEST; + +GST_START_TEST (test_signedness) +{ + GstClockTime time[] = { 0, 1, G_MAXUINT64 / GST_SECOND }; + GstClockTimeDiff diff[] = + { 0, 1, -1, G_MAXINT64 / GST_SECOND, G_MININT64 / GST_SECOND }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (time); i++) { + fail_if (time[i] != (time[i] * GST_SECOND / GST_SECOND)); + } + for (i = 0; i < G_N_ELEMENTS (diff); i++) { + fail_if (diff[i] != (diff[i] * GST_SECOND / GST_SECOND)); + } +} + +GST_END_TEST; + +#define TIME_UNIT (GST_SECOND / 5) +static void +gst_clock_debug (GstClock * clock) +{ + GstClockTime time; + + time = gst_clock_get_time (clock); + GST_DEBUG ("Clock info: time %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); +} + +static gboolean +ok_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + GST_LOG ("unlocked async id %p", id); + return FALSE; +} + +static gboolean +error_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + GST_WARNING ("unlocked unscheduled async id %p, this is wrong", id); + fail_if (TRUE); + + return FALSE; +} + +GMutex store_lock; + +static gboolean +store_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + GList **list = user_data; + + GST_DEBUG ("unlocked async id %p", id); + g_mutex_lock (&store_lock); + *list = g_list_append (*list, id); + g_mutex_unlock (&store_lock); + return FALSE; +} + +static gboolean +notify_callback (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + gboolean *ret = (gboolean *) user_data; + + if (ret != NULL) + *ret = TRUE; + + return FALSE; +} + +GST_START_TEST (test_set_default) +{ + GstClock *clock, *static_clock; + + /* obtain the default system clock, which keeps a static ref and bumps the + * refcount before returning */ + static_clock = gst_system_clock_obtain (); + fail_unless (static_clock != NULL, "Could not create default system clock"); + g_assert_cmpint (GST_OBJECT_REFCOUNT (static_clock), ==, 2); + + /* set a new default clock to a different instance which should replace the + * static clock with this one, and unref the static clock */ + clock = g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "TestClock", NULL); + gst_object_ref_sink (clock); + gst_system_clock_set_default (clock); + g_assert_cmpint (GST_OBJECT_REFCOUNT (static_clock), ==, 1); + g_object_unref (static_clock); + static_clock = gst_system_clock_obtain (); + fail_unless (static_clock == clock); + g_assert_cmpint (GST_OBJECT_REFCOUNT (clock), ==, 3); + g_object_unref (static_clock); + + /* Reset the default clock to the static one */ + gst_system_clock_set_default (NULL); + static_clock = gst_system_clock_obtain (); + fail_unless (static_clock != clock); + g_assert_cmpint (GST_OBJECT_REFCOUNT (clock), ==, 1); + g_assert_cmpint (GST_OBJECT_REFCOUNT (static_clock), ==, 2); + g_object_unref (clock); + g_object_unref (static_clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot) +{ + GstClock *clock; + GstClockID id, id2; + GstClockTime base; + GstClockReturn result; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + id = gst_clock_new_single_shot_id (clock, base + TIME_UNIT); + fail_unless (id != NULL, "Could not create single shot id"); + + GST_DEBUG ("waiting one time unit"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK (result=%d)", + result); + fail_unless (gst_clock_get_time (clock) > (base + TIME_UNIT), + "target time has not been reached"); + + GST_DEBUG ("waiting in the past"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + fail_unless (result == GST_CLOCK_EARLY, + "Waiting did not return EARLY(result=%d)", result); + gst_clock_id_unref (id); + + id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT); + GST_DEBUG ("waiting one second async id %p", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + gst_clock_id_unschedule (id); + gst_clock_id_unref (id); + + id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT); + GST_DEBUG ("waiting one second async, with cancel on id %p", id); + result = gst_clock_id_wait_async (id, error_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + GST_DEBUG ("cancel id %p after half a time unit", id); + gst_clock_id_unschedule (id); + gst_clock_id_unref (id); + GST_DEBUG ("canceled id %p", id); + + GST_DEBUG ("waiting multiple one second async, with cancel"); + id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT); + id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT); + GST_DEBUG ("waiting id %p", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + + GST_DEBUG ("waiting id %p", id2); + result = gst_clock_id_wait_async (id2, error_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + GST_DEBUG ("cancel id %p after half a time unit", id2); + gst_clock_id_unschedule (id2); + GST_DEBUG ("canceled id %p", id2); + gst_clock_id_unref (id2); + + /* wait for the entry to time out */ + g_usleep (TIME_UNIT / 1000 * 5); + fail_unless (((GstClockEntry *) id)->status == GST_CLOCK_OK, + "Waiting did not finish"); + gst_clock_id_unref (id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_periodic_shot) +{ + GstClock *clock; + GstClockID id, id2; + GstClockTime base; + GstClockReturn result; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + /* signal every half a time unit */ + id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2); + fail_unless (id != NULL, "Could not create periodic id"); + + GST_DEBUG ("waiting one time unit"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + + GST_DEBUG ("waiting for the next"); + result = gst_clock_id_wait (id, NULL); + gst_clock_debug (clock); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + + GST_DEBUG ("waiting for the next async %p", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + + GST_DEBUG ("waiting some more for the next async %p", id); + result = gst_clock_id_wait_async (id, ok_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + + id2 = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2); + fail_unless (id2 != NULL, "Could not create second periodic id"); + + GST_DEBUG ("waiting some more for another async %p", id2); + result = gst_clock_id_wait_async (id2, ok_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + + GST_DEBUG ("unschedule %p", id); + gst_clock_id_unschedule (id); + + /* entry cannot be used again */ + result = gst_clock_id_wait_async (id, error_callback, NULL, NULL); + fail_unless (result == GST_CLOCK_UNSCHEDULED, + "Waiting did not return UNSCHEDULED"); + result = gst_clock_id_wait (id, NULL); + fail_unless (result == GST_CLOCK_UNSCHEDULED, + "Waiting did not return UNSCHEDULED"); + g_usleep (TIME_UNIT / (2 * 1000)); + + /* clean up */ + gst_clock_id_unref (id); + gst_clock_id_unschedule (id2); + gst_clock_id_unref (id2); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_async_order) +{ + GstClock *clock; + GstClockID id1, id2; + GList *cb_list = NULL, *next; + GstClockTime base; + GstClockReturn result; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + id1 = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT); + id2 = gst_clock_new_single_shot_id (clock, base + 1 * TIME_UNIT); + result = gst_clock_id_wait_async (id1, store_callback, &cb_list, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / (2 * 1000)); + result = gst_clock_id_wait_async (id2, store_callback, &cb_list, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + g_usleep (TIME_UNIT / 1000); + /* at this point at least one of the timers should have timed out */ + g_mutex_lock (&store_lock); + fail_unless (cb_list != NULL, "expected notification"); + fail_unless (cb_list->data == id2, + "Expected notification for id2 to come first"); + g_mutex_unlock (&store_lock); + g_usleep (TIME_UNIT / 1000); + g_mutex_lock (&store_lock); + /* now both should have timed out */ + next = g_list_next (cb_list); + fail_unless (next != NULL, "expected second notification"); + fail_unless (next->data == id1, "Missing notification for id1"); + g_mutex_unlock (&store_lock); + + gst_clock_id_unref (id1); + gst_clock_id_unref (id2); + g_list_free (cb_list); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_async_order_stress_test) +{ +#define ALARM_COUNT 20 + GstClock *clock; + GstClockID id[ALARM_COUNT]; + GList *cb_list = NULL, *cb_list_it; + GstClockTime base; + GstClockReturn result; + unsigned int i; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + /* keep inserting at the beginning of the list. + * We expect the alarm thread to keep detecting the new entries and to + * switch to wait on the first entry on the list + */ + for (i = ALARM_COUNT; i > 0; --i) { + id[i - 1] = gst_clock_new_single_shot_id (clock, base + i * TIME_UNIT); + result = + gst_clock_id_wait_async (id[i - 1], store_callback, &cb_list, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + } + + g_usleep (TIME_UNIT * (ALARM_COUNT + 1) / 1000); + /* at this point all the timers should have timed out */ + g_mutex_lock (&store_lock); + fail_unless (cb_list != NULL, "expected notification"); + cb_list_it = cb_list; + /* alarms must trigger in order. + * Will fail if alarm thread did not properly switch to wait on first entry + * from the list + */ + for (i = 0; i < ALARM_COUNT; ++i) { + fail_unless (cb_list_it != NULL, "No notification received for id[%d]", i); + fail_unless (cb_list_it->data == id[i], + "Expected notification for id[%d]", i); + cb_list_it = g_list_next (cb_list_it); + } + g_mutex_unlock (&store_lock); + + for (i = 0; i < ALARM_COUNT; ++i) + gst_clock_id_unref (id[i]); + g_list_free (cb_list); + + gst_object_unref (clock); +} + +GST_END_TEST; + +struct test_async_sync_interaction_data +{ + GMutex lock; + + GstClockID sync_id; + GstClockID sync_id2; + + GstClockID async_id; + GstClockID async_id2; + GstClockID async_id3; +}; + +static gboolean +test_async_sync_interaction_cb (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + struct test_async_sync_interaction_data *td = + (struct test_async_sync_interaction_data *) (user_data); + + g_mutex_lock (&td->lock); + /* The first async callback is ignored */ + if (id == td->async_id) + goto out; + + if (id != td->async_id2 && id != td->async_id3) + goto out; + + /* Unschedule the sync callback */ + if (id == td->async_id3) { + gst_clock_id_unschedule (td->sync_id); + gst_clock_id_unschedule (td->async_id2); + } +out: + g_mutex_unlock (&td->lock); + return FALSE; +} + +GST_START_TEST (test_async_sync_interaction) +{ + /* This test schedules an async callback, then before it completes, schedules + * an earlier async callback, and quickly unschedules the first, and inserts + * a THIRD even earlier async callback. It then attempts to wait on a + * sync clock ID. While that's sleeping, the 3rd async callback should fire + * and unschedule it. This tests for problems with unscheduling async and + * sync callbacks on the system clock. */ + GstClock *clock; + GstClockReturn result; + GstClockTime base; + GstClockTimeDiff jitter; + struct test_async_sync_interaction_data td; + int i; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + g_mutex_init (&td.lock); + + for (i = 0; i < 50; i++) { + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + g_mutex_lock (&td.lock); + td.async_id = gst_clock_new_single_shot_id (clock, base + 40 * GST_MSECOND); + td.async_id2 = + gst_clock_new_single_shot_id (clock, base + 30 * GST_MSECOND); + td.async_id3 = + gst_clock_new_single_shot_id (clock, base + 20 * GST_MSECOND); + td.sync_id2 = gst_clock_new_single_shot_id (clock, base + 10 * GST_MSECOND); + td.sync_id = gst_clock_new_single_shot_id (clock, base + 50 * GST_MSECOND); + g_mutex_unlock (&td.lock); + + result = gst_clock_id_wait_async (td.async_id, + test_async_sync_interaction_cb, &td, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + + /* Wait 10ms, then unschedule async_id and schedule async_id2 */ + result = gst_clock_id_wait (td.sync_id2, &jitter); + fail_unless (result == GST_CLOCK_OK || result == GST_CLOCK_EARLY, + "Waiting did not return OK or EARLY"); + /* async_id2 is earlier than async_id - should become head of the queue */ + result = gst_clock_id_wait_async (td.async_id2, + test_async_sync_interaction_cb, &td, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + gst_clock_id_unschedule (td.async_id); + + /* async_id3 is earlier than async_id2 - should become head of the queue */ + result = gst_clock_id_wait_async (td.async_id3, + test_async_sync_interaction_cb, &td, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + + /* While this is sleeping, the async3 id should fire and unschedule it */ + result = gst_clock_id_wait (td.sync_id, &jitter); + fail_unless (result == GST_CLOCK_UNSCHEDULED || result == GST_CLOCK_EARLY, + "Waiting did not return UNSCHEDULED (was %d)", result); + + gst_clock_id_unschedule (td.async_id3); + g_mutex_lock (&td.lock); + + gst_clock_id_unref (td.sync_id); + gst_clock_id_unref (td.sync_id2); + gst_clock_id_unref (td.async_id); + gst_clock_id_unref (td.async_id2); + gst_clock_id_unref (td.async_id3); + g_mutex_unlock (&td.lock); + } + + g_mutex_clear (&td.lock); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_periodic_multi) +{ + GstClock *clock; + GstClockID clock_id; + GstClockID clock_id_async; + GstClockTime base; + GstClockReturn result; + gboolean got_callback = FALSE; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create instance of GstSystemClock"); + + gst_clock_debug (clock); + base = gst_clock_get_time (clock); + + clock_id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT); + gst_clock_id_wait (clock_id, NULL); + fail_unless (gst_clock_get_time (clock) >= base + TIME_UNIT); + fail_unless (gst_clock_get_time (clock) < base + 2 * TIME_UNIT); + + /* now perform a concurrent wait and wait_async */ + + clock_id_async = + gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT); + result = + gst_clock_id_wait_async (clock_id_async, notify_callback, &got_callback, + NULL); + fail_unless (result == GST_CLOCK_OK, "Async waiting did not return OK"); + + result = gst_clock_id_wait (clock_id, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + fail_unless (gst_clock_get_time (clock) >= base + 2 * TIME_UNIT); + /* give the async thread some time to call our callback: */ + g_usleep (TIME_UNIT / (10 * 1000)); + fail_unless (got_callback == TRUE, "got no async callback (1)"); + fail_unless (gst_clock_get_time (clock) < base + 3 * TIME_UNIT); + got_callback = FALSE; + + result = gst_clock_id_wait (clock_id, NULL); + fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK"); + fail_unless (gst_clock_get_time (clock) >= base + 3 * TIME_UNIT); + /* give the async thread some time to call our callback: */ + g_usleep (TIME_UNIT / (10 * 1000)); + fail_unless (got_callback == TRUE, "got no async callback (2)"); + fail_unless (gst_clock_get_time (clock) < base + 4 * TIME_UNIT); + + /* clean up */ + gst_clock_id_unref (clock_id); + gst_clock_id_unschedule (clock_id_async); + gst_clock_id_unref (clock_id_async); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_diff) +{ + GstClockTime time1[] = { 0, (GstClockTime) - 1, 0, 1, 2 * GST_SECOND, + (GstClockTime) - GST_SECOND, (GstClockTime) - GST_SECOND + }; + GstClockTime time2[] = + { 0, 1, 1, 0, 1 * GST_SECOND, (GstClockTime) - GST_SECOND, GST_SECOND }; + GstClockTimeDiff d[] = { 0, 2, 1, -1, -GST_SECOND, 0, 2 * GST_SECOND }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (d); i++) { + fail_if (d[i] != GST_CLOCK_DIFF (time1[i], time2[i])); + } +} + +GST_END_TEST; + +/* test if a blocking wait, unblocked by an async entry continues to be + * scheduled */ +typedef struct +{ + GstClock *clock; + GstClockID id; + GstClockTimeDiff jitter; + GstClockReturn ret; +} MixedInfo; + +static gpointer +mixed_thread (MixedInfo * info) +{ + info->ret = gst_clock_id_wait (info->id, &info->jitter); + return NULL; +} + +static gboolean +mixed_async_cb (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data) +{ + return TRUE; +} + +GST_START_TEST (test_mixed) +{ + GThread *thread; + GError *error = NULL; + MixedInfo info; + GstClockTime base; + GstClockID id; + + info.clock = gst_system_clock_obtain (); + fail_unless (info.clock != NULL, + "Could not create instance of GstSystemClock"); + + /* get current time of the clock as base time */ + base = gst_clock_get_time (info.clock); + + /* create entry to wait for 1 second */ + info.id = gst_clock_new_single_shot_id (info.clock, base + GST_SECOND); + + /* make and start an entry that is scheduled every 10ms */ + id = gst_clock_new_periodic_id (info.clock, base, 10 * GST_MSECOND); + + /* start waiting for the entry */ + thread = + g_thread_try_new ("gst-check", (GThreadFunc) mixed_thread, &info, &error); + fail_unless (error == NULL, "error creating thread"); + fail_unless (thread != NULL, "Could not create thread"); + + /* wait half a second so we are sure to be in the thread */ + g_usleep (G_USEC_PER_SEC / 2); + + /* start scheduling the entry */ + gst_clock_id_wait_async (id, mixed_async_cb, NULL, NULL); + + /* wait for thread to finish */ + g_thread_join (thread); + /* entry must have timed out correctly */ + fail_unless (info.ret == GST_CLOCK_OK, "clock return was %d", info.ret); + + gst_clock_id_unschedule (id); + gst_clock_id_unref (id); + gst_clock_id_unref (info.id); + gst_object_unref (info.clock); +} + +GST_END_TEST; + +static gboolean +test_async_full_slave_callback (GstClock * master, GstClockTime time, + GstClockID id, GstClock * clock) +{ + GstClockTime stime, mtime; + gdouble r_squared; + + /* notify the test case that we started */ + GST_INFO ("callback started"); + g_mutex_lock (&af_lock); + g_cond_signal (&af_cond); + + /* wait for the test case to unref "clock" and signal */ + GST_INFO ("waiting for test case to signal"); + g_cond_wait (&af_cond, &af_lock); + + stime = gst_clock_get_internal_time (clock); + mtime = gst_clock_get_time (master); + + gst_clock_add_observation (clock, stime, mtime, &r_squared); + + g_cond_signal (&af_cond); + g_mutex_unlock (&af_lock); + GST_INFO ("callback finished"); + + return TRUE; +} + +GST_START_TEST (test_async_full) +{ + GstClock *master, *slave; + GstClockID *clockid; + + /* create master and slave */ + master = + g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "TestClockMaster", NULL); + gst_object_ref_sink (master); + slave = g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "TestClockMaster", NULL); + gst_object_ref_sink (slave); + GST_OBJECT_FLAG_SET (slave, GST_CLOCK_FLAG_CAN_SET_MASTER); + g_object_set (slave, "timeout", 50 * GST_MSECOND, NULL); + + fail_unless (GST_OBJECT_REFCOUNT (master) == 1); + fail_unless (GST_OBJECT_REFCOUNT (slave) == 1); + + /* register a periodic shot on the master to calibrate the slave */ + g_mutex_lock (&af_lock); + clockid = gst_clock_new_periodic_id (master, + gst_clock_get_time (master), gst_clock_get_timeout (slave)); + gst_clock_id_wait_async (clockid, + (GstClockCallback) test_async_full_slave_callback, + gst_object_ref (slave), (GDestroyNotify) gst_object_unref); + + /* wait for the shot to be fired and test_async_full_slave_callback to be + * called */ + GST_INFO ("waiting for the slave callback to start"); + g_cond_wait (&af_cond, &af_lock); + GST_INFO ("slave callback running, unreffing slave"); + + /* unref the slave clock while the slave_callback is running. This should be + * safe since the master clock now stores a ref to the slave */ + gst_object_unref (slave); + + /* unref the clock entry. This should be safe as well since the clock thread + * refs the entry before executing it */ + gst_clock_id_unschedule (clockid); + gst_clock_id_unref (clockid); + + /* signal and wait for the callback to complete */ + g_cond_signal (&af_cond); + + GST_INFO ("waiting for callback to finish"); + g_cond_wait (&af_cond, &af_lock); + GST_INFO ("callback finished"); + g_mutex_unlock (&af_lock); + + gst_object_unref (master); +} + +GST_END_TEST; + +GST_START_TEST (test_resolution) +{ + GstClock *clock; + GstClockTime now_t, prev_t, resolution; + int i; + + now_t = prev_t = GST_CLOCK_TIME_NONE; + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "Could not create default system clock"); + resolution = gst_clock_get_resolution (clock); + fail_unless (resolution != GST_CLOCK_TIME_NONE); + + for (i = 0; i < 100000; ++i) { + now_t = gst_clock_get_internal_time (clock); + fail_unless (now_t != GST_CLOCK_TIME_NONE); + if (prev_t != GST_CLOCK_TIME_NONE) { + GstClockTime diff; + fail_unless (now_t >= prev_t); + diff = now_t - prev_t; + fail_unless (diff == 0 || diff >= resolution); + } + prev_t = now_t; + g_thread_yield (); + } + g_object_unref (clock); + clock = NULL; +} + +GST_END_TEST; + +typedef struct +{ + GThread *thread_wait; + GThread *thread_unschedule; + GMutex lock; + gboolean running; + GstClockID id; + gboolean unschedule; + gint32 time_offset_min; + gint32 time_offset_max; + gboolean dont_unschedule_positive_offset; +} WaitUnscheduleData; + +static gpointer +single_shot_wait_thread_func (gpointer data) +{ + WaitUnscheduleData *d = data; + GstClock *clock = gst_system_clock_obtain (); + + while (d->running) { + GstClockTime now; + gint offset; + GstClockID id; + + now = gst_clock_get_time (clock); + offset = g_random_int_range (d->time_offset_min, d->time_offset_max); + + g_mutex_lock (&d->lock); + d->unschedule = d->dont_unschedule_positive_offset ? offset < 0 : TRUE; + id = d->id = + gst_clock_new_single_shot_id (clock, now + (GstClockTime) offset); + g_mutex_unlock (&d->lock); + + fail_unless (id != NULL, "Could not create single shot id"); + + gst_clock_id_wait (id, NULL); + + g_mutex_lock (&d->lock); + gst_clock_id_unref (id); + d->id = NULL; + g_mutex_unlock (&d->lock); + } + + g_object_unref (clock); + + return NULL; +} + +static gpointer +unschedule_thread_func (gpointer data) +{ + WaitUnscheduleData *d = data; + + while (d->running) { + g_mutex_lock (&d->lock); + if (d->id && d->unschedule) { + g_thread_yield (); + gst_clock_id_unschedule (d->id); + } + g_mutex_unlock (&d->lock); + g_thread_yield (); + } + + return NULL; +} + +GST_START_TEST (test_stress_cleanup_unschedule) +{ + WaitUnscheduleData *data; + gint i, num; + + num = g_get_num_processors () * 6; + data = g_newa (WaitUnscheduleData, num); + + for (i = 0; i < num; i++) { + WaitUnscheduleData *d = &data[i]; + + /* Don't unschedule waits with positive offsets in order to trigger + * gst_system_clock_wait_wakeup() */ + d->dont_unschedule_positive_offset = TRUE; + /* Overweight of negative offsets in order to trigger GST_CLOCK_EARLY more + * frequently */ + d->time_offset_min = -GST_MSECOND; + d->time_offset_max = GST_MSECOND / 10; + + /* Initialize test */ + d->id = NULL; + d->running = TRUE; + g_mutex_init (&d->lock); + d->thread_wait = g_thread_new ("wait", single_shot_wait_thread_func, d); + d->thread_unschedule = g_thread_new ("unschedule", unschedule_thread_func, + d); + } + + /* Test duration */ + g_usleep (G_USEC_PER_SEC); + + /* Stop and free test data */ + for (i = 0; i < num; i++) { + WaitUnscheduleData *d = &data[i]; + d->running = FALSE; + g_thread_join (d->thread_wait); + g_thread_join (d->thread_unschedule); + g_mutex_clear (&d->lock); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_stress_reschedule) +{ + WaitUnscheduleData *data; + gint i, num; + + num = g_get_num_processors () * 6; + data = g_newa (WaitUnscheduleData, num); + + for (i = 0; i < num; i++) { + WaitUnscheduleData *d = &data[i]; + + /* Try to unschedule all waits */ + d->dont_unschedule_positive_offset = FALSE; + /* Small positive offsets in order to have both negative and positive + * diffs when a reschedule is needed. */ + d->time_offset_min = 0; + d->time_offset_max = GST_MSECOND; + + d->id = NULL; + d->running = TRUE; + g_mutex_init (&d->lock); + d->thread_wait = g_thread_new ("wait", single_shot_wait_thread_func, d); + d->thread_unschedule = g_thread_new ("unschedule", unschedule_thread_func, + d); + } + + /* Test duration */ + g_usleep (G_USEC_PER_SEC); + + /* Stop and free test data */ + for (i = 0; i < num; i++) { + WaitUnscheduleData *d = &data[i]; + d->running = FALSE; + g_thread_join (d->thread_wait); + g_thread_join (d->thread_unschedule); + g_mutex_clear (&d->lock); + } +} + +GST_END_TEST; + + +static Suite * +gst_systemclock_suite (void) +{ + Suite *s = suite_create ("GstSystemClock"); + TCase *tc_chain = tcase_create ("waiting"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_range); + tcase_add_test (tc_chain, test_signedness); + tcase_add_test (tc_chain, test_single_shot); + tcase_add_test (tc_chain, test_periodic_shot); + tcase_add_test (tc_chain, test_periodic_multi); + tcase_add_test (tc_chain, test_async_order); + tcase_add_test (tc_chain, test_async_order_stress_test); + tcase_add_test (tc_chain, test_async_sync_interaction); + tcase_add_test (tc_chain, test_diff); + tcase_add_test (tc_chain, test_mixed); + tcase_add_test (tc_chain, test_async_full); + tcase_add_test (tc_chain, test_set_default); + tcase_add_test (tc_chain, test_resolution); + tcase_add_test (tc_chain, test_stress_cleanup_unschedule); + tcase_add_test (tc_chain, test_stress_reschedule); + + return s; +} + +GST_CHECK_MAIN (gst_systemclock); diff --git a/tests/check/gst/gsttag.c b/tests/check/gst/gsttag.c new file mode 100644 index 0000000..d330cb3 --- /dev/null +++ b/tests/check/gst/gsttag.c @@ -0,0 +1,658 @@ +/* + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +/* multiple artists are possible (unfixed) */ +#define UTAG GST_TAG_ARTIST +#define UNFIXED1 "Britney Spears" +#define UNFIXED2 "Evanescence" +#define UNFIXED3 "AC/DC" +#define UNFIXED4 "The Prodigy" + +/* license is fixed */ +#define FTAG GST_TAG_LICENSE +#define FIXED1 "Lesser General Public License" +#define FIXED2 "Microsoft End User License Agreement" +#define FIXED3 "Mozilla Public License" +#define FIXED4 "Public Domain" + +/* checks that a tag contains the given values and not more values */ +static void +check_tags (const GstTagList * list, const gchar * tag, const gchar * value, + ...) +{ + va_list args; + gchar *str; + guint i = 0; + + va_start (args, value); + while (value != NULL) { + fail_unless (gst_tag_list_get_string_index (list, tag, i, &str)); + fail_unless (strcmp (value, str) == 0); + g_free (str); + + value = va_arg (args, gchar *); + i++; + } + fail_unless (i == gst_tag_list_get_tag_size (list, tag)); + va_end (args); +} + +static void +check_tags_empty (const GstTagList * list) +{ + GST_DEBUG ("taglist: %" GST_PTR_FORMAT, list); + fail_unless ((list == NULL) || (gst_tag_list_is_empty (list))); +} + +#define NEW_LIST_FIXED(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = gst_tag_list_new_empty (); \ + gst_tag_list_add (list, mode, FTAG, FIXED1, FTAG, FIXED2, \ + FTAG, FIXED3, FTAG, FIXED4, NULL); \ + mark_point(); \ +} G_STMT_END; + +#define NEW_LIST_UNFIXED(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = gst_tag_list_new_empty (); \ + gst_tag_list_add (list, mode, UTAG, UNFIXED1, UTAG, UNFIXED2, \ + UTAG, UNFIXED3, UTAG, UNFIXED4, NULL); \ + mark_point(); \ +} G_STMT_END; + +#define NEW_LISTS_FIXED(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = gst_tag_list_new_empty (); \ + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, FTAG, FIXED1, \ + FTAG, FIXED2, NULL); \ + if (list2) gst_tag_list_unref (list2); \ + list2 = gst_tag_list_new_empty (); \ + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, FTAG, FIXED3, \ + FTAG, FIXED4, NULL); \ + if (merge) gst_tag_list_unref (merge); \ + merge = gst_tag_list_merge (list, list2, mode); \ + mark_point(); \ +} G_STMT_END; + +#define NEW_LISTS_UNFIXED(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = gst_tag_list_new_empty (); \ + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, UTAG, UNFIXED1, \ + UTAG, UNFIXED2, NULL); \ + if (list2) gst_tag_list_unref (list2); \ + list2 = gst_tag_list_new_empty (); \ + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, UTAG, UNFIXED3,\ + UTAG, UNFIXED4, NULL); \ + if (merge) gst_tag_list_unref (merge); \ + merge = gst_tag_list_merge (list, list2, mode); \ + mark_point(); \ +} G_STMT_END; + +#define NEW_LISTS_EMPTY1(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = NULL; \ + if (list2) gst_tag_list_unref (list2); \ + list2 = gst_tag_list_new_empty (); \ + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, FTAG, FIXED3, \ + FTAG, FIXED4, NULL); \ + if (merge) gst_tag_list_unref (merge); \ + merge = gst_tag_list_merge (list, list2, mode); \ + mark_point(); \ +} G_STMT_END; + +#define NEW_LISTS_EMPTY2(mode) \ +G_STMT_START { \ + if (list) gst_tag_list_unref (list); \ + list = gst_tag_list_new_empty (); \ + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, FTAG, FIXED1, \ + FTAG, FIXED2, NULL); \ + if (list2) gst_tag_list_unref (list2); \ + list2 = NULL; \ + if (merge) gst_tag_list_unref (merge); \ + merge = gst_tag_list_merge (list, list2, mode); \ + mark_point(); \ +} G_STMT_END; + + +GST_START_TEST (test_basics) +{ + /* make sure the assumptions work */ + fail_unless (gst_tag_is_fixed (FTAG)); + fail_unless (!gst_tag_is_fixed (UTAG)); + /* we check string here only */ + fail_unless (gst_tag_get_type (FTAG) == G_TYPE_STRING); + fail_unless (gst_tag_get_type (UTAG) == G_TYPE_STRING); +} + +GST_END_TEST +GST_START_TEST (test_add) +{ + GstTagList *list = NULL; + + /* check additions */ + /* unfixed */ + NEW_LIST_UNFIXED (GST_TAG_MERGE_REPLACE_ALL); + check_tags (list, UTAG, UNFIXED4, NULL); + NEW_LIST_UNFIXED (GST_TAG_MERGE_REPLACE); + check_tags (list, UTAG, UNFIXED4, NULL); + NEW_LIST_UNFIXED (GST_TAG_MERGE_PREPEND); + check_tags (list, UTAG, UNFIXED4, UNFIXED3, UNFIXED2, UNFIXED1, NULL); + NEW_LIST_UNFIXED (GST_TAG_MERGE_APPEND); + check_tags (list, UTAG, UNFIXED1, UNFIXED2, UNFIXED3, UNFIXED4, NULL); + NEW_LIST_UNFIXED (GST_TAG_MERGE_KEEP); + check_tags (list, UTAG, UNFIXED1, NULL); + NEW_LIST_UNFIXED (GST_TAG_MERGE_KEEP_ALL); + check_tags (list, UTAG, NULL); + + /* fixed */ + NEW_LIST_FIXED (GST_TAG_MERGE_REPLACE_ALL); + check_tags (list, FTAG, FIXED4, NULL); + NEW_LIST_FIXED (GST_TAG_MERGE_REPLACE); + check_tags (list, FTAG, FIXED4, NULL); + NEW_LIST_FIXED (GST_TAG_MERGE_PREPEND); + check_tags (list, FTAG, FIXED4, NULL); + NEW_LIST_FIXED (GST_TAG_MERGE_APPEND); + check_tags (list, FTAG, FIXED1, NULL); + NEW_LIST_FIXED (GST_TAG_MERGE_KEEP); + check_tags (list, FTAG, FIXED1, NULL); + NEW_LIST_FIXED (GST_TAG_MERGE_KEEP_ALL); + check_tags (list, FTAG, NULL); + + /* clean up */ + if (list) + gst_tag_list_unref (list); +} + +GST_END_TEST +GST_START_TEST (test_merge) +{ + GstTagList *list = NULL, *list2 = NULL, *merge = NULL; + + /* check merging */ + /* unfixed */ + GST_DEBUG ("unfixed"); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_REPLACE_ALL); + check_tags (merge, UTAG, UNFIXED3, UNFIXED4, NULL); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_REPLACE); + check_tags (merge, UTAG, UNFIXED3, UNFIXED4, NULL); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_PREPEND); + check_tags (merge, UTAG, UNFIXED3, UNFIXED4, UNFIXED1, UNFIXED2, NULL); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_APPEND); + check_tags (merge, UTAG, UNFIXED1, UNFIXED2, UNFIXED3, UNFIXED4, NULL); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_KEEP); + check_tags (merge, UTAG, UNFIXED1, UNFIXED2, NULL); + NEW_LISTS_UNFIXED (GST_TAG_MERGE_KEEP_ALL); + check_tags (merge, UTAG, UNFIXED1, UNFIXED2, NULL); + + /* fixed */ + GST_DEBUG ("fixed"); + NEW_LISTS_FIXED (GST_TAG_MERGE_REPLACE_ALL); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_FIXED (GST_TAG_MERGE_REPLACE); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_FIXED (GST_TAG_MERGE_PREPEND); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_FIXED (GST_TAG_MERGE_APPEND); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_FIXED (GST_TAG_MERGE_KEEP); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_FIXED (GST_TAG_MERGE_KEEP_ALL); + check_tags (merge, FTAG, FIXED1, NULL); + + /* first list empty */ + GST_DEBUG ("first empty"); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_REPLACE_ALL); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_REPLACE); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_PREPEND); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_APPEND); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_KEEP); + check_tags (merge, FTAG, FIXED3, NULL); + NEW_LISTS_EMPTY1 (GST_TAG_MERGE_KEEP_ALL); + check_tags_empty (merge); + + /* second list empty */ + GST_DEBUG ("second empty"); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_REPLACE_ALL); + check_tags_empty (merge); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_REPLACE); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_PREPEND); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_APPEND); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_KEEP); + check_tags (merge, FTAG, FIXED1, NULL); + NEW_LISTS_EMPTY2 (GST_TAG_MERGE_KEEP_ALL); + check_tags (merge, FTAG, FIXED1, NULL); + + /* clean up */ + if (list) + gst_tag_list_unref (list); + if (list2) + gst_tag_list_unref (list2); + if (merge) + gst_tag_list_unref (merge); +} + +GST_END_TEST +GST_START_TEST (test_date_tags) +{ + GstTagList *tag_list, *tag_list2; + GDate *date, *date2; + gchar *str; + + date = g_date_new_dmy (14, 10, 2005); + tag_list = gst_tag_list_new_empty (); + gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_DATE, date, NULL); + + str = gst_tag_list_to_string (tag_list); + fail_if (str == NULL); + fail_if (strstr (str, "2005-10-14") == NULL); + + tag_list2 = gst_tag_list_new_from_string (str); + fail_if (tag_list2 == NULL); + fail_if (!gst_tag_list_get_date (tag_list2, GST_TAG_DATE, &date2)); + fail_unless (gst_tag_list_is_equal (tag_list2, tag_list)); + gst_tag_list_unref (tag_list2); + g_free (str); + + fail_if (g_date_compare (date, date2) != 0); + fail_if (g_date_get_day (date) != 14); + fail_if (g_date_get_month (date) != 10); + fail_if (g_date_get_year (date) != 2005); + fail_if (g_date_get_day (date2) != 14); + fail_if (g_date_get_month (date2) != 10); + fail_if (g_date_get_year (date2) != 2005); + g_date_free (date2); + + gst_tag_list_unref (tag_list); + g_date_free (date); +} + +GST_END_TEST; + +GST_START_TEST (test_type) +{ + GstTagList *taglist; + + taglist = gst_tag_list_new_empty (); + fail_unless (GST_IS_TAG_LIST (taglist)); + gst_tag_list_unref (taglist); + + /* this should be fine */ + fail_if (GST_IS_TAG_LIST (NULL)); + + /* check gst_tag_list_is_empty */ + ASSERT_CRITICAL (gst_tag_list_is_empty (NULL)); + taglist = gst_tag_list_new_empty (); + fail_unless (gst_tag_list_is_empty (taglist)); + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "JD", NULL); + fail_if (gst_tag_list_is_empty (taglist)); + gst_tag_list_unref (taglist); +} + +GST_END_TEST; + +GST_START_TEST (test_set_non_utf8_string) +{ + GstTagList *taglist; + guint8 foobar[2] = { 0xff, 0x00 }; /* not UTF-8 */ + + taglist = gst_tag_list_new_empty (); + fail_unless (taglist != NULL); + + ASSERT_WARNING (gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, + GST_TAG_ARTIST, (gchar *) foobar, NULL)); + + /* That string field with a non-UTF8 string should not have been added */ + fail_unless (gst_tag_list_is_empty (taglist)); + + gst_tag_list_unref (taglist); +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_tags) +{ + GstTagList *tags; + GstBuffer *buf1, *buf2; + GstSample *s1, *s2; + + tags = gst_tag_list_new_empty (); + + buf1 = gst_buffer_new_and_alloc (222); + s1 = gst_sample_new (buf1, NULL, NULL, NULL); + gst_buffer_unref (buf1); + + buf2 = gst_buffer_new_and_alloc (100); + s2 = gst_sample_new (buf2, NULL, NULL, NULL); + gst_buffer_unref (buf2); + + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, s1, + GST_TAG_PREVIEW_IMAGE, s2, NULL); + + gst_sample_unref (s1); + gst_sample_unref (s2); + s1 = s2 = NULL; + + fail_if (!gst_tag_list_get_sample (tags, GST_TAG_IMAGE, &s1)); + fail_unless (gst_sample_get_buffer (s1) == buf1); + gst_sample_unref (s1); + + fail_if (!gst_tag_list_get_sample (tags, GST_TAG_PREVIEW_IMAGE, &s2)); + fail_unless (gst_sample_get_buffer (s2) == buf2); + gst_sample_unref (s2); + + fail_if (gst_tag_list_get_sample_index (tags, GST_TAG_IMAGE, 1, &s1)); + fail_if (gst_tag_list_get_sample_index (tags, GST_TAG_IMAGE, 2, &s1)); + fail_if (gst_tag_list_get_sample_index (tags, GST_TAG_PREVIEW_IMAGE, 1, &s1)); + fail_if (gst_tag_list_get_sample_index (tags, GST_TAG_PREVIEW_IMAGE, 2, &s1)); + + fail_if (!gst_tag_list_get_sample_index (tags, GST_TAG_IMAGE, 0, &s1)); + fail_if (!gst_tag_list_get_sample_index (tags, GST_TAG_PREVIEW_IMAGE, 0, + &s2)); + buf1 = gst_sample_get_buffer (s1); + fail_unless_equals_int (gst_buffer_get_size (buf1), 222); + buf2 = gst_sample_get_buffer (s2); + fail_unless_equals_int (gst_buffer_get_size (buf2), 100); + + gst_sample_unref (s1); + gst_sample_unref (s2); + + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +GST_START_TEST (test_empty_tags) +{ + GstTagList *tags; + + /* only get g_warnings() with git */ + if (GST_VERSION_NANO != 1) + return; + + tags = gst_tag_list_new_empty (); + ASSERT_WARNING (gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, + GST_TAG_ARTIST, NULL, NULL)); + ASSERT_WARNING (gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, + GST_TAG_ARTIST, "", NULL)); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "xyz", NULL); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +GST_START_TEST (test_new_full) +{ + GstTagList *tags; + gchar *artist, *title; + gdouble track_gain; + guint track_num; + + tags = gst_tag_list_new (GST_TAG_ARTIST, "Arty Ist", + GST_TAG_TRACK_NUMBER, 9, GST_TAG_TRACK_GAIN, 4.242, GST_TAG_TITLE, + "Title!", NULL); + + fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &artist)); + fail_unless_equals_string (artist, "Arty Ist"); + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &title)); + fail_unless_equals_string (title, "Title!"); + fail_unless (gst_tag_list_get_uint (tags, GST_TAG_TRACK_NUMBER, &track_num)); + fail_unless_equals_int (track_num, 9); + fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_GAIN, &track_gain)); + fail_unless_equals_float (track_gain, 4.242); + fail_unless (tags != NULL); + + gst_tag_list_unref (tags); + g_free (artist); + g_free (title); +} + +GST_END_TEST; + +GST_START_TEST (test_merge_strings_with_comma) +{ + GstTagList *tags; + gchar *artists = NULL; + + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL); + gst_tag_list_get_string (tags, GST_TAG_ARTIST, &artists); + fail_unless (artists != NULL); + /* can't check for exact string since the comma separator is i18n-ed */ + fail_unless (strstr (artists, "Foo") != NULL); + fail_unless (strstr (artists, "Bar") != NULL); + fail_unless (strstr (artists, "Yay") != NULL); + g_free (artists); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +GST_START_TEST (test_equal) +{ + GstTagList *tags, *tags2; + GstSample *sample1, *sample2, *sample11; + GstBuffer *buf; + + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL); + + tags2 = gst_tag_list_new_empty (); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL); + fail_unless (gst_tag_list_is_equal (tags2, tags)); + + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_REFERENCE_LEVEL, + 9.87654321, NULL); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_REFERENCE_LEVEL, + 9.87654320, NULL); + /* want these two double values to be equal despite minor differences */ + fail_unless (gst_tag_list_is_equal (tags2, tags)); + + /* want this to be unequal though, difference too large */ + gst_tag_list_add (tags2, GST_TAG_MERGE_REPLACE, GST_TAG_REFERENCE_LEVEL, + 9.87654310, NULL); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + + gst_tag_list_unref (tags); + gst_tag_list_unref (tags2); + + /* samples */ + buf = gst_buffer_new_wrapped (g_strdup ("test 1-2-3"), 10); + sample1 = gst_sample_new (buf, NULL, NULL, NULL); + gst_buffer_unref (buf); + + buf = gst_buffer_new_wrapped (g_strdup ("test 1-2-3"), 10); + sample11 = gst_sample_new (buf, NULL, NULL, NULL); + gst_buffer_unref (buf); + + buf = gst_buffer_new_wrapped (g_strdup ("test 2-3-4-5"), 12); + sample2 = gst_sample_new (buf, NULL, NULL, NULL); + gst_buffer_unref (buf); + + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, sample1, NULL); + + tags2 = gst_tag_list_new_empty (); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + + /* sample sample, should be very equal now */ + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, sample1, NULL); + fail_unless (gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_unref (tags2); + + /* same buffer content, but different buffer instances, still rather equal */ + tags2 = gst_tag_list_new_empty (); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, sample11, NULL); + fail_unless (gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_unref (tags2); + + /* different buffer content, should not be equal */ + tags2 = gst_tag_list_new_empty (); + gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, sample2, NULL); + fail_unless (!gst_tag_list_is_equal (tags2, tags)); + gst_tag_list_unref (tags2); + + gst_tag_list_unref (tags); + + gst_sample_unref (sample1); + gst_sample_unref (sample11); + gst_sample_unref (sample2); +} + +GST_END_TEST; + +GST_START_TEST (test_writability) +{ + GstTagList *tags, *wtags; + + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL); + + /* take ref, should no longer be writable */ + gst_tag_list_ref (tags); + ASSERT_CRITICAL (gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, + GST_TAG_ARTIST, "Bar", NULL)); + + wtags = gst_tag_list_make_writable (tags); + /* should be ok now */ + gst_tag_list_add (wtags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL); + gst_tag_list_unref (wtags); + + /* this too, since we dropped the second ref in make_writable */ + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +/* this tests GstSample serialisation/deserialisation, esp. with multiple + * samples in a tag list */ +GST_START_TEST (test_serialization) +{ + GstTagList *tags, *tags2; + GstBuffer *b1, *b2; + GstSample *s1, *s2; + GstCaps *c2; + gchar *s; + + b1 = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_memset (b1, 0, 0xb3, -1); + s1 = gst_sample_new (b1, NULL, NULL, NULL); + gst_buffer_unref (b1); + + b2 = gst_buffer_new_allocate (NULL, 8, NULL); + gst_buffer_memset (b2, 0, 0x2f, -1); + c2 = gst_caps_new_empty_simple ("foo/bar"); + s2 = gst_sample_new (b2, c2, NULL, NULL); + gst_buffer_unref (b2); + gst_caps_unref (c2); + c2 = NULL; + + tags = gst_tag_list_new (GST_TAG_ATTACHMENT, s1, NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT, s2, NULL); + GST_INFO ("tags: %" GST_PTR_FORMAT, tags); + + s = gst_tag_list_to_string (tags); + GST_INFO ("taglist -> string: %s", s); + tags2 = gst_tag_list_new_from_string (s); + GST_INFO ("string -> taglist: %" GST_PTR_FORMAT, tags2); + fail_unless (gst_tag_list_is_equal (tags, tags2)); + gst_tag_list_unref (tags2); + g_free (s); + + gst_sample_unref (s1); + gst_sample_unref (s2); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + +GST_START_TEST (test_empty_taglist_serialization) +{ + GstTagList *taglist, *taglist2; + gchar *str; + + taglist = gst_tag_list_new_empty (); + str = gst_tag_list_to_string (taglist); + taglist2 = gst_tag_list_new_from_string (str); + fail_if (taglist2 == NULL); + fail_unless (gst_tag_list_is_equal (taglist, taglist2)); + + gst_tag_list_unref (taglist); + gst_tag_list_unref (taglist2); + g_free (str); +} + +GST_END_TEST; + + +static Suite * +gst_tag_suite (void) +{ + Suite *s = suite_create ("GstTag"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_basics); + tcase_add_test (tc_chain, test_add); + tcase_add_test (tc_chain, test_merge); + tcase_add_test (tc_chain, test_merge_strings_with_comma); + tcase_add_test (tc_chain, test_date_tags); + tcase_add_test (tc_chain, test_type); + tcase_add_test (tc_chain, test_set_non_utf8_string); + tcase_add_test (tc_chain, test_buffer_tags); + tcase_add_test (tc_chain, test_empty_tags); + tcase_add_test (tc_chain, test_new_full); + tcase_add_test (tc_chain, test_equal); + tcase_add_test (tc_chain, test_writability); + tcase_add_test (tc_chain, test_serialization); + tcase_add_test (tc_chain, test_empty_taglist_serialization); + + return s; +} + +GST_CHECK_MAIN (gst_tag); diff --git a/tests/check/gst/gsttagsetter.c b/tests/check/gst/gsttagsetter.c new file mode 100644 index 0000000..10f68fe --- /dev/null +++ b/tests/check/gst/gsttagsetter.c @@ -0,0 +1,340 @@ +/* GStreamer GstTagSetter interface unit tests + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +/* some minimal GstTagSetter object */ +#define GST_TYPE_DUMMY_ENC gst_dummy_enc_get_type() + +typedef GstElement GstDummyEnc; +typedef GstElementClass GstDummyEncClass; + +GType gst_dummy_enc_get_type (void); +G_DEFINE_TYPE_WITH_CODE (GstDummyEnc, gst_dummy_enc, + GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL)); + +static void +gst_dummy_enc_class_init (GstDummyEncClass * klass) +{ +} + +static void +gst_dummy_enc_init (GstDummyEnc * enc) +{ +} + +static void +tag_list_foreach (const GstTagList * taglist, const gchar * tag, guint * p_num) +{ + guint tag_size; + + tag_size = gst_tag_list_get_tag_size (taglist, tag); + GST_LOG ("%u+%u tag = %s", *p_num, tag_size, tag); + *p_num += tag_size; +} + +static guint +tag_setter_list_length (GstTagSetter * setter) +{ + guint len = 0; + + if (gst_tag_setter_get_tag_list (setter) == NULL) + return 0; + + gst_tag_list_foreach (gst_tag_setter_get_tag_list (setter), + (GstTagForeachFunc) tag_list_foreach, &len); + return len; +} + +static guint +tag_list_length (const GstTagList * tag_list) +{ + guint len = 0; + + if (tag_list == NULL) + return 0; + + gst_tag_list_foreach (tag_list, (GstTagForeachFunc) tag_list_foreach, &len); + return len; +} + +#define assert_tag_setter_list_length(setter,len) \ + fail_unless_equals_int (tag_setter_list_length(setter), len); + +GST_START_TEST (test_merge) +{ + GstTagSetter *setter; + GstTagList *list1, *list2; + GstElement *enc; + + enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL); + fail_unless (enc != NULL); + + setter = GST_TAG_SETTER (enc); + + list1 = gst_tag_list_new_empty (); + gst_tag_list_add (list1, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "artist1", + NULL); + gst_tag_setter_merge_tags (setter, list1, GST_TAG_MERGE_APPEND); + assert_tag_setter_list_length (setter, 1); + + list2 = gst_tag_list_new_empty (); + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "artist2", + GST_TAG_TITLE, "title1", NULL); + gst_tag_setter_merge_tags (setter, list2, GST_TAG_MERGE_APPEND); + assert_tag_setter_list_length (setter, 3); + + gst_tag_setter_merge_tags (setter, list2, GST_TAG_MERGE_REPLACE_ALL); + assert_tag_setter_list_length (setter, 2); + + gst_tag_setter_merge_tags (setter, list1, GST_TAG_MERGE_REPLACE_ALL); + assert_tag_setter_list_length (setter, 1); + + gst_tag_setter_add_tags (setter, GST_TAG_MERGE_APPEND, GST_TAG_ALBUM, "xyz", + NULL); + assert_tag_setter_list_length (setter, 2); + + gst_tag_list_unref (list2); + gst_tag_list_unref (list1); + + g_object_unref (enc); +} + +GST_END_TEST +GST_START_TEST (test_merge_modes) +{ + GstTagMergeMode mode; + + for (mode = GST_TAG_MERGE_REPLACE_ALL; mode < GST_TAG_MERGE_COUNT; mode++) { + gint i; + + for (i = 0; i < 4; i++) { + GstElement *enc; + GstTagSetter *setter; + GstTagList *list1, *list2, *merged; + + enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL); + fail_unless (enc != NULL); + + setter = GST_TAG_SETTER (enc); + list1 = gst_tag_list_new_empty (); + list2 = gst_tag_list_new_empty (); + + /* i = 0: - - + * i = 1: list1 - + * i = 2: - list2 + * i = 3: list1 list2 */ + + if (i % 2 == 1) { + gst_tag_list_add (list1, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, + "artist1", NULL); + } + if (i > 1) { + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, + "artist2", NULL); + } + + gst_tag_setter_merge_tags (setter, list1, GST_TAG_MERGE_APPEND); + gst_tag_setter_merge_tags (setter, list2, mode); + + merged = gst_tag_list_merge (list1, list2, mode); + + fail_unless_equals_int (tag_list_length (gst_tag_setter_get_tag_list + (setter)), tag_list_length (merged)); + + gst_tag_list_unref (list1); + gst_tag_list_unref (list2); + gst_tag_list_unref (merged); + gst_object_unref (enc); + } + } +} + +GST_END_TEST +GST_START_TEST (test_merge_modes_skip_empty) +{ + GstTagMergeMode mode; + + for (mode = GST_TAG_MERGE_REPLACE_ALL; mode < GST_TAG_MERGE_COUNT; mode++) { + gint i; + + for (i = 0; i < 2; i++) { + GstElement *enc; + GstTagSetter *setter; + GstTagList *list1, *list2, *merged; + + enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL); + fail_unless (enc != NULL); + + setter = GST_TAG_SETTER (enc); + list1 = gst_tag_list_new_empty (); + list2 = gst_tag_list_new_empty (); + + if (i == 1) { + gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, + "artist2", NULL); + } + + gst_tag_setter_merge_tags (setter, list2, mode); + + merged = gst_tag_list_merge (list1, list2, mode); + + fail_unless_equals_int (tag_list_length (gst_tag_setter_get_tag_list + (setter)), tag_list_length (merged)); + + gst_tag_list_unref (list1); + gst_tag_list_unref (list2); + gst_tag_list_unref (merged); + gst_object_unref (enc); + } + } +} + +GST_END_TEST static int spin_and_wait = 1; +static int threads_running = 0; + +#define THREADS_TEST_SECONDS 1.5 + +static gpointer +test_threads_thread_func1 (gpointer data) +{ + GstTagSetter *setter = GST_TAG_SETTER (data); + GTimer *timer; + + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) { + gst_tag_setter_add_tags (setter, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, + "some artist", GST_TAG_TITLE, "some title", GST_TAG_TRACK_NUMBER, 6, + NULL); + } + + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +static gpointer +test_threads_thread_func2 (gpointer data) +{ + GstTagSetter *setter = GST_TAG_SETTER (data); + GTimer *timer; + + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) { + gst_tag_setter_add_tags (setter, GST_TAG_MERGE_PREPEND, GST_TAG_CODEC, + "MP42", GST_TAG_COMMENT, "deep insights go here", GST_TAG_TRACK_COUNT, + 10, NULL); + } + + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +static gpointer +test_threads_thread_func3 (gpointer data) +{ + GstTagSetter *setter = GST_TAG_SETTER (data); + GTimer *timer; + + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) { + gst_tag_setter_reset_tags (setter); + } + + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +GST_START_TEST (test_threads) +{ + GstTagSetter *setter; + GThread *threads[3]; + + setter = GST_TAG_SETTER (g_object_new (GST_TYPE_DUMMY_ENC, NULL)); + + spin_and_wait = TRUE; + threads[0] = g_thread_try_new ("gst-check", test_threads_thread_func1, + setter, NULL); + threads[1] = g_thread_try_new ("gst-check", test_threads_thread_func2, + setter, NULL); + threads[2] = g_thread_try_new ("gst-check", test_threads_thread_func3, + setter, NULL); + + while (g_atomic_int_get (&threads_running) < 3) + g_usleep (10); + + g_atomic_int_set (&spin_and_wait, FALSE); + + g_thread_join (threads[0]); + g_thread_join (threads[1]); + g_thread_join (threads[2]); + + g_object_unref (G_OBJECT (setter)); +} + +GST_END_TEST static Suite * +gst_tag_setter_suite (void) +{ + Suite *s = suite_create ("GstTagSetter"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_merge); + tcase_add_test (tc_chain, test_merge_modes); + tcase_add_test (tc_chain, test_merge_modes_skip_empty); + tcase_add_test (tc_chain, test_threads); + + return s; +} + +GST_CHECK_MAIN (gst_tag_setter); diff --git a/tests/check/gst/gsttask.c b/tests/check/gst/gsttask.c new file mode 100644 index 0000000..e18a508 --- /dev/null +++ b/tests/check/gst/gsttask.c @@ -0,0 +1,272 @@ +/* GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * + * gsttask.c: Unit test for GstTask + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GMutex task_lock; +static GCond task_cond; + +static GRecMutex task_mutex; + +#define TEST_RACE_ITERATIONS 1000 + +static void +task_signal_pause_func (void *data) +{ + GstTask **t = data; + + g_mutex_lock (&task_lock); + GST_DEBUG ("signal"); + g_cond_signal (&task_cond); + + gst_task_pause (*t); + g_mutex_unlock (&task_lock); +} + +GST_START_TEST (test_pause_stop_race) +{ + guint it = TEST_RACE_ITERATIONS; + GstTask *t; + gboolean ret; + + t = gst_task_new (task_signal_pause_func, &t, NULL); + fail_if (t == NULL); + + g_rec_mutex_init (&task_mutex); + gst_task_set_lock (t, &task_mutex); + + g_cond_init (&task_cond); + g_mutex_init (&task_lock); + + while (it-- > 0) { + g_mutex_lock (&task_lock); + GST_DEBUG ("starting"); + ret = gst_task_start (t); + fail_unless (ret == TRUE); + /* wait for it to spin up */ + GST_DEBUG ("waiting"); + g_cond_wait (&task_cond, &task_lock); + GST_DEBUG ("done waiting"); + g_mutex_unlock (&task_lock); + + GST_DEBUG ("starting"); + ret = gst_task_stop (t); + fail_unless (ret == TRUE); + + GST_DEBUG ("joining"); + ret = gst_task_join (t); + fail_unless (ret == TRUE); + } + + g_cond_clear (&task_cond); + g_mutex_clear (&task_lock); + + gst_object_unref (t); +} + +GST_END_TEST; + +static void +task_func2 (void *data) +{ + gboolean ret; + GstTask *t = *((GstTask **) data); + + g_mutex_lock (&task_lock); + GST_DEBUG ("signal"); + g_cond_signal (&task_cond); + g_mutex_unlock (&task_lock); + + ASSERT_WARNING (ret = gst_task_join (t)); + fail_unless (ret == FALSE); +} + +GST_START_TEST (test_join) +{ + GstTask *t; + gboolean ret; + + t = gst_task_new (task_func2, &t, NULL); + fail_if (t == NULL); + + g_rec_mutex_init (&task_mutex); + gst_task_set_lock (t, &task_mutex); + + g_cond_init (&task_cond); + g_mutex_init (&task_lock); + + g_mutex_lock (&task_lock); + GST_DEBUG ("starting"); + ret = gst_task_start (t); + fail_unless (ret == TRUE); + /* wait for it to spin up */ + GST_DEBUG ("waiting"); + g_cond_wait (&task_cond, &task_lock); + GST_DEBUG ("done waiting"); + g_mutex_unlock (&task_lock); + + GST_DEBUG ("joining"); + ret = gst_task_join (t); + fail_unless (ret == TRUE); + + gst_task_cleanup_all (); + + gst_object_unref (t); +} + +GST_END_TEST; + +static void +task_func (void *data) +{ + g_mutex_lock (&task_lock); + GST_DEBUG ("signal"); + g_cond_signal (&task_cond); + g_mutex_unlock (&task_lock); +} + +GST_START_TEST (test_lock_start) +{ + GstTask *t; + gboolean ret; + + t = gst_task_new (task_func, NULL, NULL); + fail_if (t == NULL); + + g_rec_mutex_init (&task_mutex); + gst_task_set_lock (t, &task_mutex); + + g_cond_init (&task_cond); + g_mutex_init (&task_lock); + + g_mutex_lock (&task_lock); + GST_DEBUG ("starting"); + ret = gst_task_start (t); + fail_unless (ret == TRUE); + /* wait for it to spin up */ + GST_DEBUG ("waiting"); + g_cond_wait (&task_cond, &task_lock); + GST_DEBUG ("done waiting"); + g_mutex_unlock (&task_lock); + + /* cannot set mutex now */ + ASSERT_WARNING (gst_task_set_lock (t, &task_mutex)); + + GST_DEBUG ("joining"); + ret = gst_task_join (t); + fail_unless (ret == TRUE); + + gst_task_cleanup_all (); + + gst_object_unref (t); +} + +GST_END_TEST; + +GST_START_TEST (test_lock) +{ + GstTask *t; + gboolean ret; + + t = gst_task_new (task_func, NULL, NULL); + fail_if (t == NULL); + + g_rec_mutex_init (&task_mutex); + gst_task_set_lock (t, &task_mutex); + + GST_DEBUG ("pause"); + ret = gst_task_pause (t); + fail_unless (ret == TRUE); + + g_usleep (1 * G_USEC_PER_SEC / 2); + + GST_DEBUG ("joining"); + ret = gst_task_join (t); + fail_unless (ret == TRUE); + + g_usleep (1 * G_USEC_PER_SEC / 2); + + gst_object_unref (t); +} + +GST_END_TEST; + +GST_START_TEST (test_no_lock) +{ + GstTask *t; + gboolean ret; + + t = gst_task_new (task_func, NULL, NULL); + fail_if (t == NULL); + + /* stop should be possible without lock */ + gst_task_stop (t); + + /* pause should give a warning */ + ASSERT_WARNING (ret = gst_task_pause (t)); + fail_unless (ret == FALSE); + + /* start should give a warning */ + ASSERT_WARNING (ret = gst_task_start (t)); + fail_unless (ret == FALSE); + + /* stop should be possible without lock */ + gst_task_stop (t); + + gst_object_unref (t); +} + +GST_END_TEST; + +GST_START_TEST (test_create) +{ + GstTask *t; + + t = gst_task_new (task_func, NULL, NULL); + fail_if (t == NULL); + + gst_object_unref (t); +} + +GST_END_TEST; + + +static Suite * +gst_task_suite (void) +{ + Suite *s = suite_create ("GstTask"); + TCase *tc_chain = tcase_create ("task tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_create); + tcase_add_test (tc_chain, test_no_lock); + tcase_add_test (tc_chain, test_lock); + tcase_add_test (tc_chain, test_lock_start); + tcase_add_test (tc_chain, test_join); + tcase_add_test (tc_chain, test_pause_stop_race); + + return s; +} + +GST_CHECK_MAIN (gst_task); diff --git a/tests/check/gst/gsttoc.c b/tests/check/gst/gsttoc.c new file mode 100644 index 0000000..4abe3ad --- /dev/null +++ b/tests/check/gst/gsttoc.c @@ -0,0 +1,323 @@ +/* GStreamer + * + * unit test for GstToc + * + * Copyright (C) 2010, 2012 Alexander Saprykin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* ------- TOC ------- + * / \ + * edition1 edition2 + * | | + * -chapter1 -chapter3 + * -chapter2 | + * -subchapter1 + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define ENTRY_ED1 "/edition1" +#define ENTRY_ED2 "/edition2" +#define ENTRY_ED3 "test-edition" + +#define ENTRY_CH1 "/edition1/chapter1" +#define ENTRY_CH2 "/edition1/chapter2" +#define ENTRY_CH3 "/edition2/chapter3" +#define ENTRY_CH4 "/test-chapter" + +#define ENTRY_SUB1 "/edition2/chapter3/subchapter1" + +#define ENTRY_TAG "EntryTag" +#define TOC_TAG "TocTag" + +#define TEST_UID "129537542" + +static void +CHECK_TOC_ENTRY (GstTocEntry * entry_c, GstTocEntryType type_c, + const gchar * uid_c) +{ + GstTagList *tags; + gchar *tag_c; + + fail_unless_equals_string (gst_toc_entry_get_uid (entry_c), uid_c); + fail_unless (gst_toc_entry_get_entry_type (entry_c) == type_c); + + tags = gst_toc_entry_get_tags (entry_c); + fail_unless (tags != NULL); + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_c)); + fail_unless_equals_string (tag_c, ENTRY_TAG); + g_free (tag_c); +} + +static void +CHECK_TOC (GstToc * toc_t) +{ + GstTocEntry *entry_t, *subentry_t; + GstTagList *tags; + GList *entries, *subentries, *subsubentries; + gchar *tag_t; + + /* dump TOC */ + gst_toc_dump (toc_t); + + /* check TOC */ + tags = gst_toc_get_tags (toc_t); + fail_unless (tags != NULL); + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_t)); + fail_unless_equals_string (tag_t, TOC_TAG); + g_free (tag_t); + + entries = gst_toc_get_entries (toc_t); + fail_unless_equals_int (g_list_length (entries), 2); + + /* check edition1 */ + entry_t = g_list_nth_data (entries, 0); + fail_if (entry_t == NULL); + subentries = gst_toc_entry_get_sub_entries (entry_t); + fail_unless_equals_int (g_list_length (subentries), 2); + CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + /* check chapter1 */ + subentry_t = g_list_nth_data (subentries, 0); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1); + /* check chapter2 */ + subentry_t = g_list_nth_data (subentries, 1); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2); + + /* check edition2 */ + entry_t = g_list_nth_data (entries, 1); + fail_if (entry_t == NULL); + CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2); + subentries = gst_toc_entry_get_sub_entries (entry_t); + fail_unless_equals_int (g_list_length (subentries), 1); + /* check chapter3 */ + subentry_t = g_list_nth_data (subentries, 0); + fail_if (subentry_t == NULL); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 1); + /* check subchapter1 */ + subentry_t = g_list_nth_data (subsubentries, 0); + fail_if (subentry_t == NULL); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); +} + +/* This whole test is a bit pointless now that we just stuff a ref of + * the original TOC into the message/query/event */ +GST_START_TEST (test_serializing) +{ + GstToc *toc, *test_toc = NULL; + GstTocEntry *ed, *ch, *subch; + GstTagList *tags; + GstEvent *event; + GstMessage *message; + gboolean updated; + gchar *uid; + gint64 start = -1, stop = -1; + + toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL); + fail_unless_equals_int (gst_toc_get_scope (toc), GST_TOC_SCOPE_GLOBAL); + fail_if (toc == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, TOC_TAG, NULL); + gst_toc_set_tags (toc, tags); + + /* create edition1 */ + ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + fail_if (ed == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ed, tags); + + CHECK_TOC_ENTRY (ed, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + + /* append chapter1 to edition1 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1); + fail_if (ch == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + CHECK_TOC_ENTRY (ch, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1); + + gst_toc_entry_append_sub_entry (ed, ch); + fail_unless_equals_int (g_list_length (gst_toc_entry_get_sub_entries (ed)), + 1); + + /* append chapter2 to edition1 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2); + fail_if (ch == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + CHECK_TOC_ENTRY (ch, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2); + + gst_toc_entry_append_sub_entry (ed, ch); + fail_unless_equals_int (g_list_length (gst_toc_entry_get_sub_entries (ed)), + 2); + + /* append edition1 to the TOC */ + gst_toc_append_entry (toc, ed); + fail_unless_equals_int (g_list_length (gst_toc_get_entries (toc)), 1); + + /* test gst_toc_entry_find() */ + ed = NULL; + ed = gst_toc_find_entry (toc, ENTRY_ED1); + + fail_if (ed == NULL); + + CHECK_TOC_ENTRY (ed, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + + /* test info GstStructure */ + gst_toc_entry_set_start_stop_times (ch, 100, 1000); + fail_if (!gst_toc_entry_get_start_stop_times (ch, &start, &stop)); + fail_unless (start == 100); + fail_unless (stop == 1000); + + /* create edition2 */ + ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2); + fail_if (ed == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ed, tags); + + CHECK_TOC_ENTRY (ed, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2); + + /* create chapter3 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3); + fail_if (ch == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + CHECK_TOC_ENTRY (ch, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3); + + /* create subchapter1 */ + subch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1); + fail_if (subch == NULL); + tags = gst_tag_list_new (GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (subch, tags); + + CHECK_TOC_ENTRY (subch, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1); + + /* append subchapter1 to chapter3 */ + gst_toc_entry_append_sub_entry (ch, subch); + fail_unless_equals_int (g_list_length (gst_toc_entry_get_sub_entries (ch)), + 1); + + /* append chapter3 to edition2 */ + gst_toc_entry_append_sub_entry (ed, ch); + fail_unless_equals_int (g_list_length (gst_toc_entry_get_sub_entries (ed)), + 1); + + /* finally append edition2 to the TOC */ + gst_toc_append_entry (toc, ed); + fail_unless_equals_int (g_list_length (gst_toc_get_entries (toc)), 2); + + GST_INFO ("check original TOC"); + CHECK_TOC (toc); + + /* test gst_toc_copy() */ + test_toc = gst_toc_copy (toc); + fail_if (test_toc == NULL); + GST_INFO ("check TOC copy"); + CHECK_TOC (test_toc); + gst_toc_unref (test_toc); + test_toc = NULL; + + /* check TOC event handling */ + event = gst_event_new_toc (toc, TRUE); + fail_if (event == NULL); + fail_unless (event->type == GST_EVENT_TOC); + ASSERT_MINI_OBJECT_REFCOUNT (GST_MINI_OBJECT (event), "GstEvent", 1); + + gst_event_parse_toc (event, &test_toc, &updated); + fail_unless (updated == TRUE); + fail_if (test_toc == NULL); + GST_INFO ("check TOC parsed from event"); + CHECK_TOC (test_toc); + gst_toc_unref (test_toc); + gst_event_unref (event); + updated = FALSE; + test_toc = NULL; + + /* check TOC message handling */ + message = gst_message_new_toc (NULL, toc, TRUE); + fail_if (message == NULL); + fail_unless (message->type == GST_MESSAGE_TOC); + ASSERT_MINI_OBJECT_REFCOUNT (GST_MINI_OBJECT (message), "GstMessage", 1); + + gst_message_parse_toc (message, &test_toc, &updated); + fail_unless (updated == TRUE); + fail_if (test_toc == NULL); + CHECK_TOC (test_toc); + gst_toc_unref (test_toc); + gst_message_unref (message); + test_toc = NULL; + + /* check TOC select event handling */ + event = gst_event_new_toc_select (TEST_UID); + fail_if (event == NULL); + fail_unless (event->type == GST_EVENT_TOC_SELECT); + ASSERT_MINI_OBJECT_REFCOUNT (GST_MINI_OBJECT (event), "GstEvent", 1); + + gst_event_parse_toc_select (event, &uid); + fail_unless_equals_string (uid, TEST_UID); + gst_event_unref (event); + g_free (uid); + + /* FIXME: toc validation / verification should probably be done on the fly + * while creating it, and not when putting the toc in events or messages ? */ +#if 0 + /* that's wrong code, we should fail */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH4); + toc->entries = g_list_prepend (toc->entries, ch); + ASSERT_CRITICAL (message = gst_message_new_toc (NULL, toc, TRUE)); + + /* and yet another one */ + toc->entries = g_list_remove (toc->entries, ch); + gst_toc_entry_unref (ch); + ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED3); + ch = (GstTocEntry *) (toc->entries->data); + ch->subentries = g_list_prepend (ch->subentries, ed); + ASSERT_WARNING (message = gst_message_new_toc (NULL, toc, TRUE)); +#endif + + gst_toc_unref (toc); +} + +GST_END_TEST; + +static Suite * +gst_toc_suite (void) +{ + Suite *s = suite_create ("GstToc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_serializing); + + return s; +} + +GST_CHECK_MAIN (gst_toc); diff --git a/tests/check/gst/gsttocsetter.c b/tests/check/gst/gsttocsetter.c new file mode 100644 index 0000000..f15e198 --- /dev/null +++ b/tests/check/gst/gsttocsetter.c @@ -0,0 +1,388 @@ +/* GStreamer GstTocSetter interface unit tests + * Copyright (C) 2010, 2012 Alexander Saprykin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define ENTRY_ED1 "/edition1" +#define ENTRY_ED2 "/edition2" +#define ENTRY_ED3 "test-edition" + +#define ENTRY_CH1 "/edition1/chapter1" +#define ENTRY_CH2 "/edition1/chapter2" +#define ENTRY_CH3 "/edition2/chapter3" +#define ENTRY_CH4 "/test-chapter" + +#define ENTRY_SUB1 "/edition2/chapter3/subchapter1" + +#define ENTRY_TAG "EntryTag" +#define TOC_TAG "TocTag" + +static void +CHECK_TOC_ENTRY (GstTocEntry * entry_c, GstTocEntryType type_c, + const gchar * uid_c) +{ + GstTagList *tags; + gchar *tag_c; + + fail_unless_equals_string (gst_toc_entry_get_uid (entry_c), uid_c); + fail_unless (gst_toc_entry_get_entry_type (entry_c) == type_c); + + tags = gst_toc_entry_get_tags (entry_c); + fail_unless (tags != NULL); + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_c)); + fail_unless_equals_string (tag_c, ENTRY_TAG); + g_free (tag_c); +} + +static void +CHECK_TOC (GstToc * toc_t) +{ + GstTocEntry *entry_t, *subentry_t; + GstTagList *tags; + GList *entries, *subentries, *subsubentries; + gchar *tag_t; + + /* dump TOC */ + gst_toc_dump (toc_t); + + /* check TOC */ + tags = gst_toc_get_tags (toc_t); + fail_unless (tags != NULL); + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_t)); + fail_unless_equals_string (tag_t, TOC_TAG); + g_free (tag_t); + + entries = gst_toc_get_entries (toc_t); + fail_unless_equals_int (g_list_length (entries), 2); + /* check edition1 */ + entry_t = g_list_nth_data (entries, 0); + fail_if (entry_t == NULL); + subentries = gst_toc_entry_get_sub_entries (entry_t); + fail_unless_equals_int (g_list_length (subentries), 2); + CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + /* check chapter1 */ + subentry_t = g_list_nth_data (subentries, 0); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1); + /* check chapter2 */ + subentry_t = g_list_nth_data (subentries, 1); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2); + /* check edition2 */ + entry_t = g_list_nth_data (entries, 1); + fail_if (entry_t == NULL); + subentries = gst_toc_entry_get_sub_entries (entry_t); + fail_unless_equals_int (g_list_length (subentries), 1); + CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2); + /* check chapter3 */ + subentry_t = g_list_nth_data (subentries, 0); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 1); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3); + /* check subchapter1 */ + subentry_t = g_list_nth_data (subsubentries, 0); + fail_if (subentry_t == NULL); + subsubentries = gst_toc_entry_get_sub_entries (subentry_t); + fail_unless_equals_int (g_list_length (subsubentries), 0); + CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1); +} + +/* some minimal GstTocSetter object */ +#define GST_TYPE_DUMMY_ENC gst_dummy_enc_get_type() + +typedef GstElement GstDummyEnc; +typedef GstElementClass GstDummyEncClass; + +GType gst_dummy_enc_get_type (void); +G_DEFINE_TYPE_WITH_CODE (GstDummyEnc, gst_dummy_enc, + GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_TOC_SETTER, NULL)); + +static void +gst_dummy_enc_class_init (GstDummyEncClass * klass) +{ +} + +static void +gst_dummy_enc_init (GstDummyEnc * enc) +{ +} + +static GstToc * +create_toc (void) +{ + GstToc *toc; + GstTocEntry *ed, *ch, *subch; + GstTagList *tags; + + toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, TOC_TAG, NULL); + gst_toc_set_tags (toc, tags); + + /* create edition1 */ + ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ed, tags); + + /* append chapter1 to edition1 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + gst_toc_entry_append_sub_entry (ed, ch); + + /* append chapter2 to edition1 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + gst_toc_entry_append_sub_entry (ed, ch); + + /* append edition1 to the TOC */ + gst_toc_append_entry (toc, ed); + + /* create edition2 */ + ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ed, tags); + + /* create chapter3 */ + ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (ch, tags); + + /* create subchapter1 */ + subch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1); + tags = gst_tag_list_new_empty (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL); + gst_toc_entry_set_tags (subch, tags); + + /* append subchapter1 to chapter3 */ + gst_toc_entry_append_sub_entry (ch, subch); + + /* append chapter3 to edition2 */ + gst_toc_entry_append_sub_entry (ed, ch); + + /* finally append edition2 to the TOC */ + gst_toc_append_entry (toc, ed); + + return toc; +} + +GST_START_TEST (test_set) +{ + GstToc *toc; +#if 0 + GstTocEntry *entry, *ed; +#endif + GstTocSetter *setter; + GstElement *enc; + + enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL); + fail_unless (enc != NULL); + + setter = GST_TOC_SETTER (enc); + + toc = create_toc (); + fail_unless (toc != NULL); + + gst_toc_setter_set_toc (setter, toc); + + gst_toc_unref (toc); + toc = gst_toc_setter_get_toc (setter); + + CHECK_TOC (toc); + +#if 0 + /* test entry adding into the root TOC */ + entry = g_list_last (toc->entries)->data; + toc->entries = g_list_remove (toc->entries, entry); + + gst_toc_setter_set_toc (setter, toc); + gst_toc_setter_add_toc_entry (setter, "0", entry); + + gst_toc_unref (toc); + gst_toc_entry_unref (entry); + toc = gst_toc_setter_get_toc (setter); + + CHECK_TOC (toc); +#endif + +#if 0 + /* test entry adding into the arbitrary entry */ + entry = gst_toc_find_entry (toc, ENTRY_CH2); + fail_if (entry == NULL); + + ed = toc->entries->data; + ed->subentries = g_list_remove (ed->subentries, entry); + + gst_toc_setter_add_toc_entry (setter, ed->uid, entry); + + CHECK_TOC (toc); +#endif + + gst_toc_unref (toc); + gst_toc_setter_reset (setter); + toc = gst_toc_setter_get_toc (setter); + + fail_unless (toc == NULL); + + g_object_unref (enc); +} + +GST_END_TEST static int spin_and_wait = 1; +static int threads_running = 0; + +#define THREADS_TEST_SECONDS 1.5 + +static gpointer +test_threads_thread_func1 (gpointer data) +{ + GstToc *toc; + GstTocSetter *setter = GST_TOC_SETTER (data); + GTimer *timer; + + toc = create_toc (); + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) + gst_toc_setter_set_toc (setter, toc); + + gst_toc_unref (toc); + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +static gpointer +test_threads_thread_func2 (gpointer data) +{ + GstToc *toc; + GstTocSetter *setter = GST_TOC_SETTER (data); + GTimer *timer; + + toc = create_toc (); + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) + gst_toc_setter_set_toc (setter, toc); + + gst_toc_unref (toc); + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +static gpointer +test_threads_thread_func3 (gpointer data) +{ + GstTocSetter *setter = GST_TOC_SETTER (data); + GTimer *timer; + + timer = g_timer_new (); + + g_atomic_int_inc (&threads_running); + while (g_atomic_int_get (&spin_and_wait)) + g_usleep (0); + + GST_INFO ("Go!"); + g_timer_start (timer); + + while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) { + gst_toc_setter_reset (setter); + } + + g_timer_destroy (timer); + GST_INFO ("Done"); + + return NULL; +} + +GST_START_TEST (test_threads) +{ + GstTocSetter *setter; + GThread *threads[3]; + + setter = GST_TOC_SETTER (g_object_new (GST_TYPE_DUMMY_ENC, NULL)); + + spin_and_wait = TRUE; + threads[0] = g_thread_try_new ("gst-check", test_threads_thread_func1, + setter, NULL); + threads[1] = g_thread_try_new ("gst-check", test_threads_thread_func2, + setter, NULL); + threads[2] = g_thread_try_new ("gst-check", test_threads_thread_func3, + setter, NULL); + + while (g_atomic_int_get (&threads_running) < 3) + g_usleep (10); + + g_atomic_int_set (&spin_and_wait, FALSE); + + g_thread_join (threads[0]); + g_thread_join (threads[1]); + g_thread_join (threads[2]); + + g_object_unref (G_OBJECT (setter)); +} + +GST_END_TEST static Suite * +gst_toc_setter_suite (void) +{ + Suite *s = suite_create ("GstTocSetter"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_set); + tcase_add_test (tc_chain, test_threads); + + return s; +} + +GST_CHECK_MAIN (gst_toc_setter); diff --git a/tests/check/gst/gsttracerrecord.c b/tests/check/gst/gsttracerrecord.c new file mode 100644 index 0000000..6dd629a --- /dev/null +++ b/tests/check/gst/gsttracerrecord.c @@ -0,0 +1,172 @@ +/* GStreamer + * + * Unit tests for GstTracerRecord + * + * Copyright (C) 2016 Stefan Sauer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static GList *messages; /* NULL */ +static gboolean save_messages; /* FALSE */ + +static void +tracer_log_func (GstDebugCategory * category, + GstDebugLevel level, const gchar * file, const gchar * function, + gint line, GObject * object, GstDebugMessage * message, gpointer unused) +{ + const gchar *dbg_msg; + + if (!save_messages || level != GST_LEVEL_TRACE || + !g_str_equal (category->name, "GST_TRACER")) { + return; + } + + dbg_msg = gst_debug_message_get (message); + fail_unless (dbg_msg != NULL); + + messages = g_list_append (messages, g_strdup (dbg_msg)); +} + +static void +setup (void) +{ + gst_debug_remove_log_function (gst_debug_log_default); + gst_debug_add_log_function (tracer_log_func, NULL, NULL); + gst_debug_set_threshold_for_name ("GST_TRACER", GST_LEVEL_TRACE); + messages = NULL; + save_messages = FALSE; +} + +static void +cleanup (void) +{ + save_messages = FALSE; + gst_debug_set_threshold_for_name ("GST_TRACER", GST_LEVEL_NONE); + gst_debug_add_log_function (gst_debug_log_default, NULL, NULL); + gst_debug_remove_log_function (tracer_log_func); + g_list_free_full (messages, (GDestroyNotify) g_free); + messages = NULL; +} + + +GST_START_TEST (serialize_message_logging) +{ + GstTracerRecord *tr; + gchar *str; + + /* *INDENT-OFF* */ + tr = gst_tracer_record_new ("test.class", + "string", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + NULL), + NULL); + /* *INDENT-ON* */ + + save_messages = TRUE; + gst_tracer_record_log (tr, "test"); + save_messages = FALSE; + + fail_unless_equals_int (g_list_length (messages), 1); + str = (gchar *) messages->data; + fail_unless (str != NULL); + + g_object_unref (tr); +} + +GST_END_TEST; + + +GST_START_TEST (serialize_static_record) +{ + GstTracerRecord *tr; + GstStructure *s; + gchar *str; + gchar *str_val; + gint int_val; + gboolean bool_val; + GstPadDirection enum_val; + + /* *INDENT-OFF* */ + tr = gst_tracer_record_new ("test.class", + "string", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_STRING, + NULL), + "int", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_INT, + NULL), + "bool", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, G_TYPE_BOOLEAN, + NULL), + "enum", GST_TYPE_STRUCTURE, gst_structure_new ("value", + "type", G_TYPE_GTYPE, GST_TYPE_PAD_DIRECTION, + NULL), + NULL); + /* *INDENT-ON* */ + + save_messages = TRUE; + gst_tracer_record_log (tr, "test", 1, TRUE, GST_PAD_SRC); + save_messages = FALSE; + + str = (gchar *) messages->data; + GST_INFO ("serialized to '%s'", str); + + s = gst_structure_from_string (str, NULL); + fail_unless (s != NULL); + + fail_unless_equals_string (gst_structure_get_name (s), "test"); + + fail_unless (gst_structure_get (s, + "string", G_TYPE_STRING, &str_val, + "int", G_TYPE_INT, &int_val, + "bool", G_TYPE_BOOLEAN, &bool_val, + "enum", GST_TYPE_PAD_DIRECTION, &enum_val, NULL)); + fail_unless_equals_int (int_val, 1); + fail_unless_equals_string (str_val, "test"); + fail_unless_equals_int (bool_val, TRUE); + fail_unless_equals_int (enum_val, GST_PAD_SRC); + g_free (str_val); + + gst_structure_free (s); + g_object_unref (tr); +} + +GST_END_TEST; + + +static Suite * +gst_tracer_record_suite (void) +{ + Suite *s = suite_create ("GstTracerRecord"); + TCase *tc_chain = tcase_create ("record"); + + suite_add_tcase (s, tc_chain); + tcase_add_checked_fixture (tc_chain, setup, cleanup); + tcase_add_test (tc_chain, serialize_message_logging); + tcase_add_test (tc_chain, serialize_static_record); + + /* FIXME: add more tests, e.g. enums, pointer types and optional fields */ + + return s; +} + +GST_CHECK_MAIN (gst_tracer_record); diff --git a/tests/check/gst/gsturi.c b/tests/check/gst/gsturi.c new file mode 100644 index 0000000..ee623db --- /dev/null +++ b/tests/check/gst/gsturi.c @@ -0,0 +1,1128 @@ +/* GStreamer unit tests for GstURI + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef GST_REMOVE_DEPRECATED +#undef GST_DISABLE_DEPRECATED +#endif + +#include + +GST_START_TEST (test_protocol_case) +{ + GstElement *element; + GError *err = NULL; + + element = gst_element_make_from_uri (GST_URI_SRC, "file:///foo/bar", NULL, + &err); + + /* no element? probably no registry, bail out */ + if (element == NULL && err->code == GST_URI_ERROR_UNSUPPORTED_PROTOCOL) { + g_error_free (err); + return; + } + + gst_object_unref (element); + element = gst_element_make_from_uri (GST_URI_SRC, "FILE:///foo/bar", NULL, + NULL); + fail_unless (element != NULL, + "Got source for 'file://' URI but not for 'FILE://' URI"); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_uri_get_location) +{ + gchar *l; + + /* URI with no location should return empty string */ + l = gst_uri_get_location ("dvd://"); + fail_unless (l != NULL); + fail_unless_equals_string (l, ""); + g_free (l); + + /* URI with hostname */ + l = gst_uri_get_location ("smb://supercomputer/path/to/file"); + fail_unless (l != NULL); + fail_unless_equals_string (l, "supercomputer/path/to/file"); + g_free (l); + + /* URI */ + l = gst_uri_get_location ("file:///path/to/file"); + fail_unless (l != NULL); + fail_unless_equals_string (l, "/path/to/file"); + g_free (l); + + /* unescaping */ + l = gst_uri_get_location ("file:///path/to/some%20file"); + fail_unless (l != NULL); + fail_unless_equals_string (l, "/path/to/some file"); + g_free (l); +} + +GST_END_TEST; + +#ifndef GST_REMOVE_DEPRECATED +GST_START_TEST (test_gst_uri_construct) +{ + gchar *l; + + /* URI with no protocol or empty protocol should return empty string */ + ASSERT_CRITICAL (l = gst_uri_construct (NULL, "/path/to/file")); + fail_unless (l == NULL); + ASSERT_CRITICAL (l = gst_uri_construct ("", "/path/to/file")); + fail_unless (l == NULL); + + /* URI with no location should return empty string */ + ASSERT_CRITICAL (l = gst_uri_construct ("protocol", NULL)); + fail_unless (l == NULL); + + /* check the protocol for validity */ + l = gst_uri_construct ("protocol1234567890+-.", "somefile"); + fail_unless (l != NULL); + fail_unless_equals_string (l, "protocol1234567890+-.://somefile"); + g_free (l); + + /* check the location for correct handling */ + l = gst_uri_construct ("aprotocol", + "/path+ to/some/file%d?akey=aval&key2=val2"); + fail_unless (l != NULL); + fail_unless_equals_string (l, + "aprotocol:///path%2B%20to/some/file%25d?akey=aval&key2=val2"); + g_free (l); +} + +GST_END_TEST; +#endif + +#ifdef G_OS_WIN32 + +GST_START_TEST (test_win32_uri) +{ + gchar *uri, *l; + + uri = g_strdup ("file:///c:/my%20music/foo.ogg"); + l = gst_uri_get_location (uri); + fail_unless (l != NULL); + /* fail_unless_equals_string will screw up here in the failure case + * because the string constant will be appended to the printf format + * message string and contains a '%', that's why we use fail_unless here */ + fail_unless (g_str_equal (l, "c:/my music/foo.ogg"), + "wrong location '%s' returned for URI '%s'", l, uri); + g_free (l); + g_free (uri); + + /* make sure the other variant with two slashes before the C: (which was + * needed before because of a bug in _get_location()) still works */ + uri = g_strdup ("file://c:/my%20music/foo.ogg"); + l = gst_uri_get_location (uri); + fail_unless (l != NULL); + /* fail_unless_equals_string will screw up here in the failure case + * because the string constant will be appended to the printf format + * message string and contains a '%', that's why we use fail_unless here */ + fail_unless (g_str_equal (l, "c:/my music/foo.ogg"), + "wrong location '%s' returned for URI '%s'", l, uri); + g_free (l); + g_free (uri); +} + +GST_END_TEST; + +#endif /* G_OS_WIN32 */ + +GST_START_TEST (test_uri_misc) +{ + /* require at least two characters for the protocol */ + fail_if (gst_uri_is_valid ("B:\\foo.txt")); + fail_if (gst_uri_is_valid ("B:/foo.txt")); + fail_if (gst_uri_is_valid ("B://foo.txt")); + fail_if (gst_uri_is_valid ("B:foo.txt")); + + fail_unless (gst_uri_is_valid ("fd://0")); + fail_unless (gst_uri_is_valid ("AB:\\foo.txt")); + fail_unless (gst_uri_is_valid ("AB:/foo.txt")); + fail_unless (gst_uri_is_valid ("AB://foo.txt")); + fail_unless (gst_uri_is_valid ("AB:foo.txt")); + + fail_unless (gst_uri_is_valid ("ABC:/foo.txt")); + fail_unless (gst_uri_is_valid ("ABC://foo.txt")); + fail_unless (gst_uri_is_valid ("ABC:foo.txt")); + + fail_unless (gst_uri_is_valid ("ABCD:/foo.txt")); + fail_unless (gst_uri_is_valid ("ABCD://foo.txt")); + fail_unless (gst_uri_is_valid ("ABCD:foo.txt")); +} + +GST_END_TEST; + +GST_START_TEST (test_element_make_from_uri) +{ + GstElement *element; + GError *err = NULL; + + element = gst_element_make_from_uri (GST_URI_SRC, "foo://", NULL, NULL); + fail_unless (element == NULL); + + element = gst_element_make_from_uri (GST_URI_SRC, "foo://", NULL, &err); + fail_unless (element == NULL); + fail_unless (err != NULL); + fail_unless (err->code == GST_URI_ERROR_UNSUPPORTED_PROTOCOL); + g_error_free (err); + err = NULL; + + if (gst_registry_check_feature_version (gst_registry_get (), "filesrc", + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO)) { + element = gst_element_make_from_uri (GST_URI_SRC, "file://host/foo", NULL, + &err); + fail_unless (element == NULL); + fail_unless (err != NULL); + fail_unless (err->code == GST_URI_ERROR_BAD_URI); + g_error_free (err); + err = NULL; + } +} + +GST_END_TEST; + +/* Taken from the GNet unit test and extended with other URIs: + * https://git.gnome.org/browse/archive/gnet/plain/tests/check/gnet/gneturi.c + */ +struct QueryValue +{ + const gchar *key; + const gchar *value; +}; + +struct URITest +{ + const gchar *str; + struct + { + const gchar *scheme; + const gchar *userinfo; + const gchar *host; + gint port; + const gchar *path; + /* needs to be updated if more than 10 */ + struct QueryValue query[10]; + const gchar *fragment; + } uri; +}; + +static const struct URITest tests[] = { + /* VALID URIS. PARSING AND PRINTING OF THESE SHOULD NOT CHANGE */ + + /* scheme/path */ + {"scheme:", + {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}}, + + {"scheme:path", + {"scheme", NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, + + {"path", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, + + {"/path", + {NULL, NULL, NULL, GST_URI_NO_PORT, "/path", {{NULL, NULL}}, NULL}}, + + /* hostname/port */ + {"scheme://hostname/path", + {"scheme", NULL, "hostname", GST_URI_NO_PORT, "/path", {{NULL, NULL}}, + NULL}}, + + {"scheme://hostname:123/path", + {"scheme", NULL, "hostname", 123, "/path", {{NULL, NULL}}, NULL}}, + + /* ipv6 hostname/port */ + {"scheme://[01:23:45:67:89:ab:cd:ef]/path", + {"scheme", NULL, "01:23:45:67:89:ab:cd:ef", GST_URI_NO_PORT, "/path", + {{NULL, NULL}}, NULL}}, + + {"scheme://[01:23:45:67:89:ab:cd:ef]:123/path", + {"scheme", NULL, "01:23:45:67:89:ab:cd:ef", 123, "/path", {{NULL, + NULL}}, NULL}}, + + /* query/fragment */ + {"path?query", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, + NULL}}, NULL}}, + {"path?query=value", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", "value"}, {NULL, + NULL}}, NULL}}, + + {"path?query#fragment", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, + NULL}}, "fragment"}}, + + {"path?query=value#fragment", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", "value"}, {NULL, + NULL}}, "fragment"}}, + + {"scheme:path?query#fragment", + {"scheme", NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, + NULL}}, "fragment"}}, + + /* full */ + {"scheme://hostname:123/path?query#fragment", + {"scheme", NULL, "hostname", 123, "/path", {{"query", NULL}, {NULL, + NULL}}, "fragment"}}, + + {"scheme://hostname:123/path?query=value#fragment", + {"scheme", NULL, "hostname", 123, "/path", {{"query", "value"}, {NULL, + NULL}}, "fragment"}}, + + {"scheme://hostname:123?query", + {"scheme", NULL, "hostname", 123, NULL, {{"query", NULL}, {NULL, + NULL}}, NULL}}, + + {"scheme://hostname:123?query=value", + {"scheme", NULL, "hostname", 123, NULL, {{"query", "value"}, {NULL, + NULL}}, NULL}}, + + {"scheme://hostname:123?query#fragment", + {"scheme", NULL, "hostname", 123, NULL, {{"query", NULL}, {NULL, + NULL}}, "fragment"}}, + + {"scheme://hostname:123?query=value#fragment", + {"scheme", NULL, "hostname", 123, NULL, {{"query", "value"}, {NULL, + NULL}}, "fragment"}}, + + /* user/pass */ + {"scheme://userinfo@hostname", + {"scheme", "userinfo", "hostname", GST_URI_NO_PORT, NULL, {{NULL, + NULL}}, NULL}}, + + {"scheme://userinfo@hostname:123/path?query#fragment", + {"scheme", "userinfo", "hostname", 123, "/path", {{"query", NULL}, + {NULL, NULL}}, "fragment"}}, + + {"scheme://user:pass@hostname", + {"scheme", "user:pass", "hostname", GST_URI_NO_PORT, NULL, {{NULL, + NULL}}, NULL}}, + + {"scheme://user:pass@hostname:123/path?query#fragment", + {"scheme", "user:pass", "hostname", 123, "/path", {{"query", NULL}, + {NULL, NULL}}, "fragment"}}, + + /* FUNNY URIS. PARSING AND PRINTING OF THESE MAY CHANGE */ + + {"scheme:hostname:123/path?query#fragment", + {"scheme", NULL, NULL, GST_URI_NO_PORT, "hostname:123/path", {{"query", + NULL}, {NULL, NULL}}, "fragment"}}, + + {"scheme://:pass@hostname:123/path?query#fragment", + {"scheme", ":pass", "hostname", 123, "/path", {{"query", NULL}, {NULL, + NULL}}, "fragment"}}, + + /* Skip initial white space */ + {" \f\n\r\t\vscheme:", + {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}}, + + {" \f\n\r\t\vpath", + {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, + + /* file URI */ + {"file://host/home/joe/foo.txt", + {"file", NULL, "host", GST_URI_NO_PORT, "/home/joe/foo.txt", {{NULL, + NULL}}, NULL}}, + {"file:///home/joe/foo.txt", + {"file", NULL, NULL, GST_URI_NO_PORT, "/home/joe/foo.txt", {{NULL, + NULL}}, NULL}}, +}; + +static const gchar *unparsable_uri_tests[] = { + /* Path not started correctly */ + "scheme://hostname:123path?query#fragment", + + /* Brackets that don't close */ + "scheme://[01:23:45:67:89:ab:cd:ef:123/path", + + /* IPv6 hostname without brackets */ + "scheme://01:23:45:67:89:ab:cd:ef:123/path", +}; + +GST_START_TEST (test_url_parsing) +{ + GstUri *uri; + GList *list; + gchar *tmp_str; + guint i, j; + + for (i = 0; i < G_N_ELEMENTS (tests); i++) { + GST_DEBUG ("Testing URI '%s'", tests[i].str); + + uri = gst_uri_from_string (tests[i].str); + fail_unless (uri != NULL); + fail_unless_equals_string (gst_uri_get_scheme (uri), tests[i].uri.scheme); + fail_unless_equals_string (gst_uri_get_userinfo (uri), + tests[i].uri.userinfo); + fail_unless_equals_string (gst_uri_get_host (uri), tests[i].uri.host); + fail_unless_equals_int (gst_uri_get_port (uri), tests[i].uri.port); + tmp_str = gst_uri_get_path (uri); + fail_unless_equals_string (tmp_str, tests[i].uri.path); + g_free (tmp_str); + + for (j = 0; j < 10; j++) { + if (!tests[i].uri.query[j].key) + break; + + if (tests[i].uri.query[j].value) { + fail_unless_equals_string (gst_uri_get_query_value (uri, + tests[i].uri.query[j].key), tests[i].uri.query[j].value); + } else { + fail_unless (gst_uri_query_has_key (uri, tests[i].uri.query[j].key)); + } + } + list = gst_uri_get_query_keys (uri); + fail_unless_equals_int (j, g_list_length (list)); + g_list_free (list); + gst_uri_unref (uri); + } + + for (i = 0; i < G_N_ELEMENTS (unparsable_uri_tests); i++) { + GST_DEBUG ("Testing unparsable URI '%s'", unparsable_uri_tests[i]); + + uri = gst_uri_from_string (unparsable_uri_tests[i]); + fail_unless (uri == NULL); + } +} + +GST_END_TEST; + +static const struct URITest url_presenting_tests[] = { + /* check all URI elements present */ + {.uri = {"scheme", "user:pass", "host", 1234, "/path/to/dir", + {{"query", NULL}, {"key", "value"}}, "fragment"}, + .str = + "scheme://user:pass@host:1234/path/to/dir?query&key=value#fragment"}, + + /* IPv6 literal should render in square brackets */ + {.uri = {"scheme", "user:pass", "12:34:56:78:9a:bc:de:f0", 1234, + "/path/to/dir", {{"query", "value"}}, "fragment"}, + .str = + "scheme://user:pass@[12:34:56:78:9a:bc:de:f0]:1234/path/to/dir?query=value#fragment"}, +}; + +GST_START_TEST (test_url_presenting) +{ + GstUri *uri; + gchar *result; + guint i, j; + + for (i = 0; i < G_N_ELEMENTS (url_presenting_tests); i++) { + uri = gst_uri_new (url_presenting_tests[i].uri.scheme, + url_presenting_tests[i].uri.userinfo, + url_presenting_tests[i].uri.host, + url_presenting_tests[i].uri.port, + url_presenting_tests[i].uri.path, + NULL, url_presenting_tests[i].uri.fragment); + fail_unless (uri != NULL); + for (j = 0; j < 10; j++) { + if (!url_presenting_tests[i].uri.query[j].key) + break; + + fail_unless (gst_uri_set_query_value (uri, + url_presenting_tests[i].uri.query[j].key, + url_presenting_tests[i].uri.query[j].value)); + } + + result = gst_uri_to_string (uri); + fail_unless_equals_string (result, url_presenting_tests[i].str); + g_free (result); + gst_uri_unref (uri); + } +} + +GST_END_TEST; + +GST_START_TEST (test_url_normalization) +{ + GstUri *url; + gchar *tmp_str; + + url = + gst_uri_from_string + ("ScHeMe://User:P%61ss@HOST.%63om:1234/path/./from/../to%7d/item%2dobj?qu%65ry=something#fr%61gment"); + fail_unless (gst_uri_normalize (url)); + fail_unless_equals_string (gst_uri_get_scheme (url), "scheme"); + fail_unless_equals_string (gst_uri_get_userinfo (url), "User:Pass"); + fail_unless_equals_string (gst_uri_get_host (url), "host.com"); + tmp_str = gst_uri_get_path (url); + fail_unless_equals_string (tmp_str, "/path/to}/item-obj"); + g_free (tmp_str); + fail_unless (gst_uri_query_has_key (url, "query")); + fail_unless_equals_string (gst_uri_get_query_value (url, "query"), + "something"); + fail_unless_equals_string (gst_uri_get_fragment (url), "fragment"); + gst_uri_unref (url); +} + +GST_END_TEST; + +GST_START_TEST (test_url_joining) +{ + GstUri *base, *rel, *joined; + gchar *l; + + base = + gst_uri_from_string + ("http://example.com/path/to/dir/filename.html#fragment"); + + /* test change of fragment only */ + rel = gst_uri_from_string ("#new_frag"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/filename.html#new_frag"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test addition of new query string */ + rel = gst_uri_from_string ("?key=val"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/filename.html?key=val"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test new base filename */ + rel = gst_uri_from_string ("new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test relative file same directory */ + rel = gst_uri_from_string ("./new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test relative file parent directory */ + rel = gst_uri_from_string ("../new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/path/to/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test relative file grandparent directory */ + rel = gst_uri_from_string ("../../new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/path/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test relative file root directory */ + rel = gst_uri_from_string ("../../../new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test relative file beyond root directory */ + rel = gst_uri_from_string ("../../../../new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test add subdirectory */ + rel = gst_uri_from_string ("subdir/new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/subdir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test change directory */ + rel = gst_uri_from_string ("../subdir/new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/subdir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + gst_uri_unref (base); + + /* change base for path ending in directory */ + base = gst_uri_from_string ("http://example.com/path/to/dir/"); + + /* test adding file to directory */ + rel = gst_uri_from_string ("new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test adding file to directory using relative path */ + rel = gst_uri_from_string ("./new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, + "http://example.com/path/to/dir/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test filename in parent directory */ + rel = gst_uri_from_string ("../new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/path/to/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test path ending in '../' */ + rel = gst_uri_from_string ("one/two/../"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/path/to/dir/one/"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test path ending in '..' Result should be the same as when ending in '../' */ + rel = gst_uri_from_string ("one/two/.."); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "http://example.com/path/to/dir/one/"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + /* test replace with absolute */ + rel = gst_uri_from_string ("https://ssl.example.com/new_filename.xml"); + joined = gst_uri_join (base, rel); + l = gst_uri_to_string (joined); + fail_unless_equals_string (l, "https://ssl.example.com/new_filename.xml"); + g_free (l); + gst_uri_unref (joined); + gst_uri_unref (rel); + + gst_uri_unref (base); +} + +GST_END_TEST; + +GST_START_TEST (test_url_equality) +{ + GstUri *url1, *url2; + + url1 = + gst_uri_from_string + ("ScHeMe://User:Pass@HOST.com:1234/path/./from/../to%7d/item%2dobj?query=something#fragment"); + + /* equal */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (gst_uri_equal (url1, url2)); + fail_unless (gst_uri_equal (url2, url1)); + gst_uri_unref (url2); + + /* different fragment */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/item-obj?query=something#different-fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different query */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/item-obj?query=different-something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different path */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/different-item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different port */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:4321/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different host */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@different-host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different userinfo */ + url2 = + gst_uri_from_string + ("scheme://Different-User:Pass@host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different scheme */ + url2 = + gst_uri_from_string + ("different+scheme://User:Pass@host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no scheme) */ + url2 = + gst_uri_from_string + ("//User:Pass@host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no userinfo) */ + url2 = + gst_uri_from_string + ("scheme://host.com:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no host) */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@:1234/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no port) */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com/path/to%7D/item-obj?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no path) */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234?query=something#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no query) */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/item-obj#fragment"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* different (no fragment) */ + url2 = + gst_uri_from_string + ("scheme://User:Pass@host.com:1234/path/to%7D/item-obj?query=something"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + /* compare two NULL uris */ + fail_unless (gst_uri_equal (NULL, NULL)); + + /* compare same object */ + fail_unless (gst_uri_equal (url1, url1)); + + /* compare one NULL and one non-NULL uri */ + fail_unless (!gst_uri_equal (url1, NULL)); + fail_unless (!gst_uri_equal (NULL, url1)); + + gst_uri_unref (url1); +} + +GST_END_TEST; + +GST_START_TEST (test_url_constructors) +{ + GstUri *url1, *url2; + gchar *tmp_str; + GHashTable *tmp_table; + + url1 = + gst_uri_new ("scheme", "userinfo", "hostname", 1234, "/path/to/file", + "query", "fragment"); + fail_unless_equals_string (gst_uri_get_scheme (url1), "scheme"); + fail_unless_equals_string (gst_uri_get_userinfo (url1), "userinfo"); + fail_unless_equals_string (gst_uri_get_host (url1), "hostname"); + fail_unless (gst_uri_get_port (url1) == 1234); + tmp_str = gst_uri_get_path (url1); + fail_unless_equals_string (tmp_str, "/path/to/file"); + g_free (tmp_str); + tmp_table = gst_uri_get_query_table (url1); + fail_unless (g_hash_table_size (tmp_table) == 1); + fail_unless (g_hash_table_contains (tmp_table, "query")); + fail_unless (g_hash_table_lookup (tmp_table, "query") == NULL); + g_hash_table_unref (tmp_table); + fail_unless_equals_string (gst_uri_get_fragment (url1), "fragment"); + tmp_str = gst_uri_to_string (url1); + fail_unless_equals_string (tmp_str, + "scheme://userinfo@hostname:1234/path/to/file?query#fragment"); + g_free (tmp_str); + + url2 = + gst_uri_new_with_base (url1, NULL, NULL, NULL, GST_URI_NO_PORT, + "new_file", NULL, NULL); + fail_unless_equals_string (gst_uri_get_scheme (url2), "scheme"); + fail_unless_equals_string (gst_uri_get_userinfo (url2), "userinfo"); + fail_unless_equals_string (gst_uri_get_host (url2), "hostname"); + fail_unless (gst_uri_get_port (url2) == 1234); + tmp_str = gst_uri_get_path (url2); + fail_unless_equals_string (tmp_str, "/path/to/new_file"); + g_free (tmp_str); + fail_unless (gst_uri_get_query_table (url2) == NULL); + fail_unless (gst_uri_get_fragment (url2) == NULL); + tmp_str = gst_uri_to_string (url2); + fail_unless_equals_string (tmp_str, + "scheme://userinfo@hostname:1234/path/to/new_file"); + g_free (tmp_str); + gst_uri_unref (url2); + + url2 = gst_uri_from_string_with_base (url1, "/a/new/path/to/file"); + fail_unless_equals_string (gst_uri_get_scheme (url2), "scheme"); + fail_unless_equals_string (gst_uri_get_userinfo (url2), "userinfo"); + fail_unless_equals_string (gst_uri_get_host (url2), "hostname"); + fail_unless (gst_uri_get_port (url2) == 1234); + tmp_str = gst_uri_get_path (url2); + fail_unless_equals_string (tmp_str, "/a/new/path/to/file"); + g_free (tmp_str); + fail_unless (gst_uri_get_query_table (url2) == NULL); + fail_unless (gst_uri_get_fragment (url2) == NULL); + tmp_str = gst_uri_to_string (url2); + fail_unless_equals_string (tmp_str, + "scheme://userinfo@hostname:1234/a/new/path/to/file"); + g_free (tmp_str); + gst_uri_unref (url2); + + url2 = gst_uri_from_string_with_base (url1, "http://foobar.com/bla"); + fail_unless_equals_string (gst_uri_get_scheme (url2), "http"); + fail_unless_equals_string (gst_uri_get_host (url2), "foobar.com"); + fail_unless (gst_uri_get_port (url2) == 0); + tmp_str = gst_uri_get_path (url2); + fail_unless_equals_string (tmp_str, "/bla"); + g_free (tmp_str); + fail_unless (gst_uri_get_query_table (url2) == NULL); + fail_unless (gst_uri_get_fragment (url2) == NULL); + tmp_str = gst_uri_to_string (url2); + fail_unless_equals_string (tmp_str, "http://foobar.com/bla"); + g_free (tmp_str); + gst_uri_unref (url2); + + url2 = gst_uri_copy (url1); + fail_unless (gst_uri_equal (url1, url2)); + gst_uri_set_query_value (url2, "key", "value"); + fail_unless (!gst_uri_equal (url1, url2)); + gst_uri_unref (url2); + + gst_uri_unref (url1); +} + +GST_END_TEST; + +GST_START_TEST (test_url_get_set) +{ + GstUri *url; + gchar *tmp_str; + GList *tmp_list; + + url = gst_uri_from_string ("scheme://hostname/path/to/file?query#fragment"); + + fail_unless (gst_uri_set_scheme (url, "new+scheme")); + fail_unless_equals_string (gst_uri_get_scheme (url), "new+scheme"); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "new+scheme://hostname/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (gst_uri_set_scheme (url, NULL)); + fail_unless (gst_uri_get_scheme (url) == NULL); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, "//hostname/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_scheme (NULL, "fail")); + fail_unless (gst_uri_set_scheme (NULL, NULL)); + + fail_unless (gst_uri_set_userinfo (url, "username:password")); + fail_unless_equals_string (gst_uri_get_userinfo (url), "username:password"); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//username:password@hostname/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (gst_uri_set_userinfo (url, NULL)); + fail_unless (gst_uri_get_userinfo (url) == NULL); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, "//hostname/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_userinfo (NULL, "fail")); + fail_unless (gst_uri_set_userinfo (NULL, NULL)); + + fail_unless (gst_uri_set_host (url, NULL)); + fail_unless (gst_uri_get_host (url) == NULL); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, "/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (gst_uri_set_host (url, "example.com")); + fail_unless_equals_string (gst_uri_get_host (url), "example.com"); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_host (NULL, "fail")); + fail_unless (gst_uri_set_host (NULL, NULL)); + + fail_unless (gst_uri_set_port (url, 12345)); + fail_unless (gst_uri_get_port (url) == 12345); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com:12345/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (gst_uri_set_port (url, GST_URI_NO_PORT)); + fail_unless (gst_uri_get_port (url) == GST_URI_NO_PORT); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_port (NULL, 1234)); + fail_unless (gst_uri_set_port (NULL, GST_URI_NO_PORT)); + + fail_unless (gst_uri_append_path_segment (url, "here")); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/here?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_append_path_segment (NULL, "fail")); + fail_unless (gst_uri_append_path_segment (NULL, NULL)); + + fail_unless (gst_uri_append_path (url, "../there")); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/here/../there?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_append_path (NULL, "fail")); + fail_unless (gst_uri_append_path (NULL, NULL)); + + gst_uri_normalize (url); + + tmp_list = gst_uri_get_path_segments (url); + fail_unless (tmp_list != NULL); + tmp_list = g_list_append (tmp_list, g_strdup ("segment")); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there?query#fragment"); + g_free (tmp_str); + fail_unless (gst_uri_set_path_segments (url, tmp_list)); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query#fragment"); + g_free (tmp_str); + + tmp_list = g_list_append (NULL, g_strdup ("test")); + fail_unless (!gst_uri_set_path_segments (NULL, tmp_list)); + fail_unless (gst_uri_set_path_segments (NULL, NULL)); + + fail_unless (gst_uri_set_query_value (url, "key", "value")); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query&key=value#fragment"); + g_free (tmp_str); + + fail_unless (gst_uri_set_query_value (url, "key", NULL)); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query&key#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_query_value (NULL, "key", "value")); + + fail_unless (gst_uri_remove_query_key (url, "key")); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query#fragment"); + g_free (tmp_str); + + fail_unless (!gst_uri_remove_query_key (url, "key")); + fail_unless (!gst_uri_remove_query_key (NULL, "key")); + + fail_unless (gst_uri_set_fragment (url, NULL)); + fail_unless (gst_uri_get_fragment (url) == NULL); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query"); + g_free (tmp_str); + + fail_unless (gst_uri_set_fragment (url, "tag")); + fail_unless_equals_string (gst_uri_get_fragment (url), "tag"); + tmp_str = gst_uri_to_string (url); + fail_unless_equals_string (tmp_str, + "//example.com/path/to/file/there/segment?query#tag"); + g_free (tmp_str); + + fail_unless (!gst_uri_set_fragment (NULL, "can't set if no URI")); + fail_unless (gst_uri_set_fragment (NULL, NULL)); + + gst_uri_unref (url); +} + +GST_END_TEST; + +GST_START_TEST (test_url_get_media_fragment_table) +{ + GstUri *url; + gchar *val; + GHashTable *table; + + /* Examples at https://www.w3.org/TR/media-frags/#processing-media-fragment-uri */ + + /* TEST "t=1" */ + url = gst_uri_from_string ("http://foo/var/file#t=1"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("1", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* NOTE: Media Fragments URI 1.0 (W3C) is saying that + * "Multiple occurrences of the same dimension: only the last valid occurrence + * of a dimension (e.g. t=10 in #t=2&t=10) is interpreted and all previous + * occurrences (valid or invalid) SHOULD be ignored by the user agent" + */ + /* TEST "t=1&t=2" */ + url = gst_uri_from_string ("http://foo/var/file#t=1&t=2"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("2", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "a=b=c" */ + url = gst_uri_from_string ("http://foo/var/file#a=b=c"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "a", NULL, + (gpointer) & val)); + fail_unless_equals_string ("b=c", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "a&b=c" */ + url = gst_uri_from_string ("http://foo/var/file#a&b=c"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 2); + fail_unless (g_hash_table_lookup_extended (table, "a", NULL, + (gpointer) & val)); + fail_unless (val == NULL); + fail_unless (g_hash_table_lookup_extended (table, "b", NULL, + (gpointer) & val)); + fail_unless_equals_string ("c", val); + g_hash_table_unref (table); + gst_uri_unref (url); + + /* TEST "%74=%6ept%3A%310" */ + url = gst_uri_from_string ("http://foo/var/file#%74=%6ept%3A%310"); + table = gst_uri_get_media_fragment_table (url); + fail_unless (table); + fail_unless (g_hash_table_size (table) == 1); + fail_unless (g_hash_table_lookup_extended (table, "t", NULL, + (gpointer) & val)); + fail_unless_equals_string ("npt:10", val); + g_hash_table_unref (table); + gst_uri_unref (url); +} + +GST_END_TEST; + +static Suite * +gst_uri_suite (void) +{ + Suite *s = suite_create ("GstURI"); + TCase *tc_chain = tcase_create ("uri"); + + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_protocol_case); + tcase_add_test (tc_chain, test_uri_get_location); +#ifndef GST_REMOVE_DEPRECATED + tcase_add_test (tc_chain, test_gst_uri_construct); +#endif + tcase_add_test (tc_chain, test_uri_misc); + tcase_add_test (tc_chain, test_element_make_from_uri); +#ifdef G_OS_WIN32 + tcase_add_test (tc_chain, test_win32_uri); +#endif + tcase_add_test (tc_chain, test_url_parsing); + tcase_add_test (tc_chain, test_url_presenting); + tcase_add_test (tc_chain, test_url_normalization); + tcase_add_test (tc_chain, test_url_joining); + tcase_add_test (tc_chain, test_url_equality); + tcase_add_test (tc_chain, test_url_constructors); + tcase_add_test (tc_chain, test_url_get_set); + tcase_add_test (tc_chain, test_url_get_media_fragment_table); + + return s; +} + +GST_CHECK_MAIN (gst_uri); diff --git a/tests/check/gst/gstutils.c b/tests/check/gst/gstutils.c new file mode 100644 index 0000000..18ba199 --- /dev/null +++ b/tests/check/gst/gstutils.c @@ -0,0 +1,2000 @@ +/* GStreamer + * Copyright (C) <2005> Thomas Vander Stichele + * Copyright (C) <2006> Tim-Philipp Müller + * + * gstutils.c: Unit test for functions in gstutils + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define SPECIAL_POINTER(x) ((void*)(19283847+(x))) + +static int n_data_probes = 0; +static int n_buffer_probes = 0; +static int n_event_probes = 0; + +static GstPadProbeReturn +probe_do_nothing (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info); + GST_DEBUG_OBJECT (pad, "is buffer:%d", GST_IS_BUFFER (obj)); + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +data_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info); + n_data_probes++; + GST_DEBUG_OBJECT (pad, "data probe %d", n_data_probes); + g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj)); + g_assert (data == SPECIAL_POINTER (0)); + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info); + n_buffer_probes++; + GST_DEBUG_OBJECT (pad, "buffer probe %d", n_buffer_probes); + g_assert (GST_IS_BUFFER (obj)); + g_assert (data == SPECIAL_POINTER (1)); + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info); + n_event_probes++; + GST_DEBUG_OBJECT (pad, "event probe %d [%s]", + n_event_probes, GST_EVENT_TYPE_NAME (obj)); + g_assert (GST_IS_EVENT (obj)); + g_assert (data == SPECIAL_POINTER (2)); + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_buffer_probe_n_times) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstBus *bus; + GstMessage *message; + GstPad *pad; + + pipeline = gst_element_factory_make ("pipeline", NULL); + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + g_object_set (fakesrc, "num-buffers", (int) 10, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + pad = gst_element_get_static_pad (fakesink, "sink"); + + /* add the probes we need for the test */ + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, data_probe, + SPECIAL_POINTER (0), NULL); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, buffer_probe, + SPECIAL_POINTER (1), NULL); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, event_probe, + SPECIAL_POINTER (2), NULL); + + /* add some string probes just to test that the data is free'd + * properly as it should be */ + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, probe_do_nothing, + g_strdup ("data probe string"), (GDestroyNotify) g_free); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, probe_do_nothing, + g_strdup ("buffer probe string"), (GDestroyNotify) g_free); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, probe_do_nothing, + g_strdup ("event probe string"), (GDestroyNotify) g_free); + + gst_object_unref (pad); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + bus = gst_element_get_bus (pipeline); + message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1); + gst_message_unref (message); + gst_object_unref (bus); + + g_assert (n_buffer_probes == 10); /* one for every buffer */ + g_assert (n_event_probes == 4); /* stream-start, new segment, latency and eos */ + g_assert (n_data_probes == 14); /* duh */ + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + /* make sure nothing was sent in addition to the above when shutting down */ + g_assert (n_buffer_probes == 10); /* one for every buffer */ + g_assert (n_event_probes == 4); /* stream-start, new segment, latency and eos */ + g_assert (n_data_probes == 14); /* duh */ +} GST_END_TEST; + +static int n_data_probes_once = 0; +static int n_buffer_probes_once = 0; +static int n_event_probes_once = 0; + +static GstPadProbeReturn +data_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data) +{ + GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info); + + n_data_probes_once++; + g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj)); + + gst_pad_remove_probe (pad, *data); + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +buffer_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data) +{ + GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info); + + n_buffer_probes_once++; + g_assert (GST_IS_BUFFER (obj)); + + gst_pad_remove_probe (pad, *data); + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn +event_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data) +{ + GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info); + + n_event_probes_once++; + g_assert (GST_IS_EVENT (obj)); + + gst_pad_remove_probe (pad, *data); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_buffer_probe_once) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstBus *bus; + GstMessage *message; + GstPad *pad; + guint id1, id2, id3; + + pipeline = gst_element_factory_make ("pipeline", NULL); + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + g_object_set (fakesrc, "num-buffers", (int) 10, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + pad = gst_element_get_static_pad (fakesink, "sink"); + id1 = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, + (GstPadProbeCallback) data_probe_once, &id1, NULL); + id2 = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, + (GstPadProbeCallback) buffer_probe_once, &id2, NULL); + id3 = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) event_probe_once, &id3, NULL); + gst_object_unref (pad); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + bus = gst_element_get_bus (pipeline); + message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1); + gst_message_unref (message); + gst_object_unref (bus); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + g_assert (n_buffer_probes_once == 1); /* can we hit it and quit? */ + g_assert (n_event_probes_once == 1); /* i said, can we hit it and quit? */ + g_assert (n_data_probes_once == 1); /* let's hit it and quit!!! */ +} GST_END_TEST; + +GST_START_TEST (test_math_scale) +{ + fail_if (gst_util_uint64_scale_int (1, 1, 1) != 1); + + fail_if (gst_util_uint64_scale_int (10, 10, 1) != 100); + fail_if (gst_util_uint64_scale_int (10, 10, 2) != 50); + + fail_if (gst_util_uint64_scale_int (0, 10, 2) != 0); + fail_if (gst_util_uint64_scale_int (0, 0, 2) != 0); + + fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL); + fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL); + + fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL); + fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL); + + /* not quite overflow */ + fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10, + 10) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32, + G_MAXINT32) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 100, G_MAXINT32, + G_MAXINT32) != G_MAXUINT64 - 100); + + /* overflow */ + fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64); + fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32, + 1) != G_MAXUINT64); + +} GST_END_TEST; + +GST_START_TEST (test_math_scale_round) +{ + fail_if (gst_util_uint64_scale_int_round (2, 1, 2) != 1); + fail_if (gst_util_uint64_scale_int_round (3, 1, 2) != 2); + fail_if (gst_util_uint64_scale_int_round (4, 1, 2) != 2); + + fail_if (gst_util_uint64_scale_int_round (200, 100, 20000) != 1); + fail_if (gst_util_uint64_scale_int_round (299, 100, 20000) != 1); + fail_if (gst_util_uint64_scale_int_round (300, 100, 20000) != 2); + fail_if (gst_util_uint64_scale_int_round (301, 100, 20000) != 2); + fail_if (gst_util_uint64_scale_int_round (400, 100, 20000) != 2); +} GST_END_TEST; + +GST_START_TEST (test_math_scale_ceil) +{ + fail_if (gst_util_uint64_scale_int_ceil (2, 1, 2) != 1); + fail_if (gst_util_uint64_scale_int_ceil (3, 1, 2) != 2); + fail_if (gst_util_uint64_scale_int_ceil (4, 1, 2) != 2); + + fail_if (gst_util_uint64_scale_int_ceil (200, 100, 20000) != 1); + fail_if (gst_util_uint64_scale_int_ceil (299, 100, 20000) != 2); + fail_if (gst_util_uint64_scale_int_ceil (300, 100, 20000) != 2); + fail_if (gst_util_uint64_scale_int_ceil (301, 100, 20000) != 2); + fail_if (gst_util_uint64_scale_int_ceil (400, 100, 20000) != 2); +} GST_END_TEST; + +GST_START_TEST (test_math_scale_uint64) +{ + fail_if (gst_util_uint64_scale (1, 1, 1) != 1); + + fail_if (gst_util_uint64_scale (10, 10, 1) != 100); + fail_if (gst_util_uint64_scale (10, 10, 2) != 50); + + fail_if (gst_util_uint64_scale (0, 10, 2) != 0); + fail_if (gst_util_uint64_scale (0, 0, 2) != 0); + + fail_if (gst_util_uint64_scale (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL); + fail_if (gst_util_uint64_scale (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL); + + fail_if (gst_util_uint64_scale (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL); + fail_if (gst_util_uint64_scale (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL); + + /* not quite overflow */ + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 10) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT32, + G_MAXUINT32) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 100, G_MAXUINT32, + G_MAXUINT32) != G_MAXUINT64 - 100); + + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 10) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT64, + G_MAXUINT64) != G_MAXUINT64 - 1); + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 100, G_MAXUINT64, + G_MAXUINT64) != G_MAXUINT64 - 100); + + /* overflow */ + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64); + fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT64, + 1) != G_MAXUINT64); + +} GST_END_TEST; + +GST_START_TEST (test_math_scale_random) +{ + guint64 val, num, denom, res; + GRand *rand; + gint i; + + rand = g_rand_new (); + + i = 100000; + while (i--) { + guint64 check, diff; + + val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand); + num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand); + denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand); + + res = gst_util_uint64_scale (val, num, denom); + check = gst_gdouble_to_guint64 (gst_guint64_to_gdouble (val) * + gst_guint64_to_gdouble (num) / gst_guint64_to_gdouble (denom)); + + if (res < G_MAXUINT64 && check < G_MAXUINT64) { + if (res > check) + diff = res - check; + else + diff = check - res; + + /* some arbitrary value, really.. someone do the proper math to get + * the upper bound */ + if (diff > 20000) + fail_if (diff > 20000); + } + } + g_rand_free (rand); + +} + +GST_END_TEST; + +GST_START_TEST (test_guint64_to_gdouble) +{ + guint64 from[] = { 0, 1, 100, 10000, (guint64) (1) << 63, + ((guint64) (1) << 63) + 1, + ((guint64) (1) << 63) + (G_GINT64_CONSTANT (1) << 62) + }; + gdouble to[] = { 0., 1., 100., 10000., 9223372036854775808., + 9223372036854775809., 13835058055282163712. + }; + gdouble tolerance[] = { 0., 0., 0., 0., 0., 1., 1. }; + gint i; + gdouble result; + gdouble delta; + + for (i = 0; i < G_N_ELEMENTS (from); ++i) { + result = gst_util_guint64_to_gdouble (from[i]); + delta = ABS (to[i] - result); + fail_unless (delta <= tolerance[i], + "Could not convert %d: %" G_GUINT64_FORMAT + " -> %f, got %f instead, delta of %e with tolerance of %e", + i, from[i], to[i], result, delta, tolerance[i]); + } +} + +GST_END_TEST; + +GST_START_TEST (test_gdouble_to_guint64) +{ + gdouble from[] = { 0., 1., 100., 10000., 9223372036854775808., + 9223372036854775809., 13835058055282163712. + }; + guint64 to[] = { 0, 1, 100, 10000, (guint64) (1) << 63, + ((guint64) (1) << 63) + 1, + ((guint64) (1) << 63) + (G_GINT64_CONSTANT (1) << 62) + }; + guint64 tolerance[] = { 0, 0, 0, 0, 0, 1, 1 }; + gint i; + gdouble result; + guint64 delta; + + for (i = 0; i < G_N_ELEMENTS (from); ++i) { + result = gst_util_gdouble_to_guint64 (from[i]); + delta = ABS (to[i] - result); + fail_unless (delta <= tolerance[i], + "Could not convert %f: %" G_GUINT64_FORMAT + " -> %d, got %d instead, delta of %e with tolerance of %e", + i, from[i], to[i], result, delta, tolerance[i]); + } +} + +GST_END_TEST; + +#ifndef GST_DISABLE_PARSE +GST_START_TEST (test_parse_bin_from_description) +{ + struct + { + const gchar *bin_desc; + const gchar *pad_names; + } bin_tests[] = { + { + "identity", "identity0/sink,identity0/src"}, { + "identity ! identity ! identity", "identity1/sink,identity3/src"}, { + "identity ! fakesink", "identity4/sink"}, { + "fakesrc ! identity", "identity5/src"}, { + "fakesrc ! fakesink", ""} + }; + gint i; + + for (i = 0; i < G_N_ELEMENTS (bin_tests); ++i) { + GstElement *bin, *parent; + GString *s; + GstPad *ghost_pad, *target_pad; + GError *err = NULL; + + bin = gst_parse_bin_from_description (bin_tests[i].bin_desc, TRUE, &err); + if (err) { + g_error ("ERROR in gst_parse_bin_from_description (%s): %s", + bin_tests[i].bin_desc, err->message); + } + g_assert (bin != NULL); + + s = g_string_new (""); + if ((ghost_pad = gst_element_get_static_pad (bin, "sink"))) { + g_assert (GST_IS_GHOST_PAD (ghost_pad)); + + target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad)); + g_assert (target_pad != NULL); + g_assert (GST_IS_PAD (target_pad)); + + parent = gst_pad_get_parent_element (target_pad); + g_assert (parent != NULL); + + g_string_append_printf (s, "%s/sink", GST_ELEMENT_NAME (parent)); + + gst_object_unref (parent); + gst_object_unref (target_pad); + gst_object_unref (ghost_pad); + } + + if ((ghost_pad = gst_element_get_static_pad (bin, "src"))) { + g_assert (GST_IS_GHOST_PAD (ghost_pad)); + + target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad)); + g_assert (target_pad != NULL); + g_assert (GST_IS_PAD (target_pad)); + + parent = gst_pad_get_parent_element (target_pad); + g_assert (parent != NULL); + + if (s->len > 0) { + g_string_append (s, ","); + } + + g_string_append_printf (s, "%s/src", GST_ELEMENT_NAME (parent)); + + gst_object_unref (parent); + gst_object_unref (target_pad); + gst_object_unref (ghost_pad); + } + + if (strcmp (s->str, bin_tests[i].pad_names) != 0) { + g_error ("FAILED: expected '%s', got '%s' for bin '%s'", + bin_tests[i].pad_names, s->str, bin_tests[i].bin_desc); + } + g_string_free (s, TRUE); + + gst_object_unref (bin); + } +} + +GST_END_TEST; +#endif + +GST_START_TEST (test_element_found_tags) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstTagList *list; + GstBus *bus; + GstMessage *message; + GstPad *srcpad; + + pipeline = gst_element_factory_make ("pipeline", NULL); + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + list = gst_tag_list_new_empty (); + + g_object_set (fakesrc, "num-buffers", (int) 10, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + srcpad = gst_element_get_static_pad (fakesrc, "src"); + gst_pad_push_event (srcpad, gst_event_new_tag (list)); + gst_object_unref (srcpad); + + bus = gst_element_get_bus (pipeline); + message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1); + gst_message_unref (message); + gst_object_unref (bus); + + /* FIXME: maybe also check if the fakesink receives the message */ + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_element_unlink) +{ + GstElement *src, *sink; + + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + fail_unless (gst_element_link (src, sink) != FALSE); + gst_element_unlink (src, sink); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +GST_START_TEST (test_set_value_from_string) +{ + GValue val = { 0, }; + + /* g_return_if_fail */ + ASSERT_CRITICAL (gst_util_set_value_from_string (NULL, "xyz")); + + g_value_init (&val, G_TYPE_STRING); + ASSERT_CRITICAL (gst_util_set_value_from_string (&val, NULL)); + g_value_unset (&val); + + /* string => string */ + g_value_init (&val, G_TYPE_STRING); + gst_util_set_value_from_string (&val, "Y00"); + fail_unless (g_value_get_string (&val) != NULL); + fail_unless_equals_string (g_value_get_string (&val), "Y00"); + g_value_unset (&val); + + /* string => int */ + g_value_init (&val, G_TYPE_INT); + gst_util_set_value_from_string (&val, "987654321"); + fail_unless (g_value_get_int (&val) == 987654321); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_INT); + ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz")); + g_value_unset (&val); + + /* string => uint */ + g_value_init (&val, G_TYPE_UINT); + gst_util_set_value_from_string (&val, "987654321"); + fail_unless (g_value_get_uint (&val) == 987654321); + g_value_unset (&val); + + /* CHECKME: is this really desired behaviour? (tpm) */ + g_value_init (&val, G_TYPE_UINT); + gst_util_set_value_from_string (&val, "-999"); + fail_unless (g_value_get_uint (&val) == ((guint) 0 - (guint) 999)); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_UINT); + ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz")); + g_value_unset (&val); + + /* string => long */ + g_value_init (&val, G_TYPE_LONG); + gst_util_set_value_from_string (&val, "987654321"); + fail_unless (g_value_get_long (&val) == 987654321); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_LONG); + ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz")); + g_value_unset (&val); + + /* string => ulong */ + g_value_init (&val, G_TYPE_ULONG); + gst_util_set_value_from_string (&val, "987654321"); + fail_unless (g_value_get_ulong (&val) == 987654321); + g_value_unset (&val); + + /* CHECKME: is this really desired behaviour? (tpm) */ + g_value_init (&val, G_TYPE_ULONG); + gst_util_set_value_from_string (&val, "-999"); + fail_unless (g_value_get_ulong (&val) == ((gulong) 0 - (gulong) 999)); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_ULONG); + ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz")); + g_value_unset (&val); + + /* string => boolean */ + g_value_init (&val, G_TYPE_BOOLEAN); + gst_util_set_value_from_string (&val, "true"); + fail_unless_equals_int (g_value_get_boolean (&val), TRUE); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_BOOLEAN); + gst_util_set_value_from_string (&val, "TRUE"); + fail_unless_equals_int (g_value_get_boolean (&val), TRUE); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_BOOLEAN); + gst_util_set_value_from_string (&val, "false"); + fail_unless_equals_int (g_value_get_boolean (&val), FALSE); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_BOOLEAN); + gst_util_set_value_from_string (&val, "FALSE"); + fail_unless_equals_int (g_value_get_boolean (&val), FALSE); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_BOOLEAN); + gst_util_set_value_from_string (&val, "bleh"); + fail_unless_equals_int (g_value_get_boolean (&val), FALSE); + g_value_unset (&val); + +#if 0 + /* string => float (yay, localisation issues involved) */ + g_value_init (&val, G_TYPE_FLOAT); + gst_util_set_value_from_string (&val, "987.654"); + fail_unless (g_value_get_float (&val) >= 987.653 && + g_value_get_float (&val) <= 987.655); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_FLOAT); + gst_util_set_value_from_string (&val, "987,654"); + fail_unless (g_value_get_float (&val) >= 987.653 && + g_value_get_float (&val) <= 987.655); + g_value_unset (&val); + + /* string => double (yay, localisation issues involved) */ + g_value_init (&val, G_TYPE_DOUBLE); + gst_util_set_value_from_string (&val, "987.654"); + fail_unless (g_value_get_double (&val) >= 987.653 && + g_value_get_double (&val) <= 987.655); + g_value_unset (&val); + + g_value_init (&val, G_TYPE_DOUBLE); + gst_util_set_value_from_string (&val, "987,654"); + fail_unless (g_value_get_double (&val) >= 987.653 && + g_value_get_double (&val) <= 987.655); + g_value_unset (&val); +#endif +} + +GST_END_TEST; + +static gint +_binary_search_compare (guint32 * a, guint32 * b) +{ + return *a - *b; +} + +GST_START_TEST (test_binary_search) +{ + guint32 data[257]; + guint32 *match; + guint32 search_element = 121 * 2; + guint i; + + for (i = 0; i < 257; i++) + data[i] = (i + 1) * 2; + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 120); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 120); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 120); + + search_element = 0; + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT, + &search_element, NULL); + fail_unless (match == NULL); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 0); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE, + &search_element, NULL); + fail_unless (match == NULL); + + search_element = 1000; + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT, + &search_element, NULL); + fail_unless (match == NULL); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER, + &search_element, NULL); + fail_unless (match == NULL); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 256); + + search_element = 121 * 2 - 1; + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT, + &search_element, NULL); + fail_unless (match == NULL); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 120); + + match = + (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32), + (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE, + &search_element, NULL); + fail_unless (match != NULL); + fail_unless_equals_int (match - data, 119); + +} + +GST_END_TEST; + +#ifdef HAVE_GSL +#ifdef HAVE_GMP + +#include +#include + +static guint64 +randguint64 (gsl_rng * rng, guint64 n) +{ + union + { + guint64 x; + struct + { + guint16 a, b, c, d; + } parts; + } x; + x.parts.a = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.b = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.c = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.d = gsl_rng_uniform_int (rng, 1 << 16); + return x.x % n; +} + + +enum round_t +{ + ROUND_TONEAREST = 0, + ROUND_UP, + ROUND_DOWN +}; + +static void +gmp_set_uint64 (mpz_t mp, guint64 x) +{ + mpz_t two_32, tmp; + + mpz_init (two_32); + mpz_init (tmp); + + mpz_ui_pow_ui (two_32, 2, 32); + mpz_set_ui (mp, (unsigned long) ((x >> 32) & G_MAXUINT32)); + mpz_mul (tmp, mp, two_32); + mpz_add_ui (mp, tmp, (unsigned long) (x & G_MAXUINT32)); + mpz_clear (two_32); + mpz_clear (tmp); +} + +static guint64 +gmp_get_uint64 (mpz_t mp) +{ + mpz_t two_64, two_32, tmp; + guint64 ret; + + mpz_init (two_64); + mpz_init (two_32); + mpz_init (tmp); + + mpz_ui_pow_ui (two_64, 2, 64); + mpz_ui_pow_ui (two_32, 2, 32); + if (mpz_cmp (tmp, two_64) >= 0) + return G_MAXUINT64; + mpz_clear (two_64); + + mpz_tdiv_q (tmp, mp, two_32); + ret = mpz_get_ui (tmp); + ret <<= 32; + ret |= mpz_get_ui (mp); + mpz_clear (two_32); + mpz_clear (tmp); + + return ret; +} + +static guint64 +gmp_scale (guint64 x, guint64 a, guint64 b, enum round_t mode) +{ + mpz_t mp1, mp2, mp3; + if (!b) + /* overflow */ + return G_MAXUINT64; + mpz_init (mp1); + mpz_init (mp2); + mpz_init (mp3); + + gmp_set_uint64 (mp1, x); + gmp_set_uint64 (mp3, a); + mpz_mul (mp2, mp1, mp3); + switch (mode) { + case ROUND_TONEAREST: + gmp_set_uint64 (mp1, b); + mpz_tdiv_q_ui (mp3, mp1, 2); + mpz_add (mp1, mp2, mp3); + mpz_set (mp2, mp1); + break; + case ROUND_UP: + gmp_set_uint64 (mp1, b); + mpz_sub_ui (mp3, mp1, 1); + mpz_add (mp1, mp2, mp3); + mpz_set (mp2, mp1); + break; + case ROUND_DOWN: + break; + } + gmp_set_uint64 (mp3, b); + mpz_tdiv_q (mp1, mp2, mp3); + x = gmp_get_uint64 (mp1); + mpz_clear (mp1); + mpz_clear (mp2); + mpz_clear (mp3); + return x; +} + +static void +_gmp_test_scale (gsl_rng * rng) +{ + guint64 bygst, bygmp; + guint64 a = randguint64 (rng, gsl_rng_uniform_int (rng, + 2) ? G_MAXUINT64 : G_MAXUINT32); + guint64 b = randguint64 (rng, gsl_rng_uniform_int (rng, 2) ? G_MAXUINT64 - 1 : G_MAXUINT32 - 1) + 1; /* 0 not allowed */ + guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN)); + enum round_t mode = gsl_rng_uniform_int (rng, 3); + const char *func; + + bygmp = gmp_scale (val, a, b, mode); + switch (mode) { + case ROUND_TONEAREST: + bygst = gst_util_uint64_scale_round (val, a, b); + func = "gst_util_uint64_scale_round"; + break; + case ROUND_UP: + bygst = gst_util_uint64_scale_ceil (val, a, b); + func = "gst_util_uint64_scale_ceil"; + break; + case ROUND_DOWN: + bygst = gst_util_uint64_scale (val, a, b); + func = "gst_util_uint64_scale"; + break; + default: + g_assert_not_reached (); + break; + } + fail_unless (bygst == bygmp, + "error: %s(): %" G_GUINT64_FORMAT " * %" G_GUINT64_FORMAT " / %" + G_GUINT64_FORMAT " = %" G_GUINT64_FORMAT ", correct = %" G_GUINT64_FORMAT + "\n", func, val, a, b, bygst, bygmp); +} + +static void +_gmp_test_scale_int (gsl_rng * rng) +{ + guint64 bygst, bygmp; + gint32 a = randguint64 (rng, G_MAXINT32); + gint32 b = randguint64 (rng, G_MAXINT32 - 1) + 1; /* 0 not allowed */ + guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN)); + enum round_t mode = gsl_rng_uniform_int (rng, 3); + const char *func; + + bygmp = gmp_scale (val, a, b, mode); + switch (mode) { + case ROUND_TONEAREST: + bygst = gst_util_uint64_scale_int_round (val, a, b); + func = "gst_util_uint64_scale_int_round"; + break; + case ROUND_UP: + bygst = gst_util_uint64_scale_int_ceil (val, a, b); + func = "gst_util_uint64_scale_int_ceil"; + break; + case ROUND_DOWN: + bygst = gst_util_uint64_scale_int (val, a, b); + func = "gst_util_uint64_scale_int"; + break; + default: + g_assert_not_reached (); + break; + } + fail_unless (bygst == bygmp, + "error: %s(): %" G_GUINT64_FORMAT " * %d / %d = %" G_GUINT64_FORMAT + ", correct = %" G_GUINT64_FORMAT "\n", func, val, a, b, bygst, bygmp); +} + +#define GMP_TEST_RUNS 100000 + +GST_START_TEST (test_math_scale_gmp) +{ + gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937); + gint n; + + for (n = 0; n < GMP_TEST_RUNS; n++) + _gmp_test_scale (rng); + + gsl_rng_free (rng); +} + +GST_END_TEST; + +GST_START_TEST (test_math_scale_gmp_int) +{ + gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937); + gint n; + + for (n = 0; n < GMP_TEST_RUNS; n++) + _gmp_test_scale_int (rng); + + gsl_rng_free (rng); +} + +GST_END_TEST; + +#endif +#endif + +GST_START_TEST (test_pad_proxy_query_caps_aggregation) +{ + GstElement *tee, *sink1, *sink2; + GstCaps *caps; + GstPad *tee_src1, *tee_src2, *tee_sink, *sink1_sink, *sink2_sink; + + tee = gst_element_factory_make ("tee", "tee"); + + sink1 = gst_element_factory_make ("fakesink", "sink1"); + tee_src1 = gst_element_get_request_pad (tee, "src_%u"); + sink1_sink = gst_element_get_static_pad (sink1, "sink"); + fail_unless_equals_int (gst_pad_link (tee_src1, sink1_sink), GST_PAD_LINK_OK); + + sink2 = gst_element_factory_make ("fakesink", "sink2"); + tee_src2 = gst_element_get_request_pad (tee, "src_%u"); + sink2_sink = gst_element_get_static_pad (sink2, "sink"); + fail_unless_equals_int (gst_pad_link (tee_src2, sink2_sink), GST_PAD_LINK_OK); + + tee_sink = gst_element_get_static_pad (tee, "sink"); + + gst_element_set_state (sink1, GST_STATE_PAUSED); + gst_element_set_state (sink2, GST_STATE_PAUSED); + gst_element_set_state (tee, GST_STATE_PAUSED); + + /* by default, ANY caps should intersect to ANY */ + caps = gst_pad_query_caps (tee_sink, NULL); + GST_INFO ("got caps: %" GST_PTR_FORMAT, caps); + fail_unless (caps != NULL); + fail_unless (gst_caps_is_any (caps)); + gst_caps_unref (caps); + + /* these don't intersect we should get empty caps */ + caps = gst_caps_new_empty_simple ("foo/bar"); + fail_unless (gst_pad_set_caps (sink1_sink, caps)); + gst_pad_use_fixed_caps (sink1_sink); + gst_caps_unref (caps); + + caps = gst_caps_new_empty_simple ("bar/ter"); + fail_unless (gst_pad_set_caps (sink2_sink, caps)); + gst_pad_use_fixed_caps (sink2_sink); + gst_caps_unref (caps); + + caps = gst_pad_query_caps (tee_sink, NULL); + GST_INFO ("got caps: %" GST_PTR_FORMAT, caps); + fail_unless (caps != NULL); + fail_unless (gst_caps_is_empty (caps)); + gst_caps_unref (caps); + + /* test intersection */ + caps = gst_caps_new_simple ("foo/bar", "barversion", G_TYPE_INT, 1, NULL); + GST_OBJECT_FLAG_UNSET (sink2_sink, GST_PAD_FLAG_FIXED_CAPS); + fail_unless (gst_pad_set_caps (sink2_sink, caps)); + gst_pad_use_fixed_caps (sink2_sink); + gst_caps_unref (caps); + + caps = gst_pad_query_caps (tee_sink, NULL); + GST_INFO ("got caps: %" GST_PTR_FORMAT, caps); + fail_unless (caps != NULL); + fail_if (gst_caps_is_empty (caps)); + { + GstStructure *s = gst_caps_get_structure (caps, 0); + + fail_unless_equals_string (gst_structure_get_name (s), "foo/bar"); + fail_unless (gst_structure_has_field_typed (s, "barversion", G_TYPE_INT)); + } + gst_caps_unref (caps); + + gst_element_set_state (sink1, GST_STATE_NULL); + gst_element_set_state (sink2, GST_STATE_NULL); + gst_element_set_state (tee, GST_STATE_NULL); + + /* clean up */ + gst_element_release_request_pad (tee, tee_src1); + gst_object_unref (tee_src1); + gst_element_release_request_pad (tee, tee_src2); + gst_object_unref (tee_src2); + gst_object_unref (tee_sink); + gst_object_unref (tee); + gst_object_unref (sink1_sink); + gst_object_unref (sink1); + gst_object_unref (sink2_sink); + gst_object_unref (sink2); +} + +GST_END_TEST; + +GST_START_TEST (test_greatest_common_divisor) +{ + fail_if (gst_util_greatest_common_divisor (1, 1) != 1); + fail_if (gst_util_greatest_common_divisor (2, 3) != 1); + fail_if (gst_util_greatest_common_divisor (3, 5) != 1); + fail_if (gst_util_greatest_common_divisor (-1, 1) != 1); + fail_if (gst_util_greatest_common_divisor (-2, 3) != 1); + fail_if (gst_util_greatest_common_divisor (-3, 5) != 1); + fail_if (gst_util_greatest_common_divisor (-1, -1) != 1); + fail_if (gst_util_greatest_common_divisor (-2, -3) != 1); + fail_if (gst_util_greatest_common_divisor (-3, -5) != 1); + fail_if (gst_util_greatest_common_divisor (1, -1) != 1); + fail_if (gst_util_greatest_common_divisor (2, -3) != 1); + fail_if (gst_util_greatest_common_divisor (3, -5) != 1); + fail_if (gst_util_greatest_common_divisor (2, 2) != 2); + fail_if (gst_util_greatest_common_divisor (2, 4) != 2); + fail_if (gst_util_greatest_common_divisor (1001, 11) != 11); + +} + +GST_END_TEST; + +GST_START_TEST (test_read_macros) +{ + guint8 carray[] = "ABCDEFGH"; /* 0x41 ... 0x48 */ + guint32 uarray[2]; + guint8 *cpointer; + + memcpy (uarray, carray, 8); + cpointer = carray; + + /* 16 bit */ + /* First try the standard pointer variants */ + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer), 0x4142); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 1), 0x4243); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 2), 0x4344); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 3), 0x4445); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 4), 0x4546); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 5), 0x4647); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer + 6), 0x4748); + + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer), 0x4241); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 1), 0x4342); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 2), 0x4443); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 3), 0x4544); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 4), 0x4645); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 5), 0x4746); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (cpointer + 6), 0x4847); + + /* On an array of guint8 */ + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray), 0x4142); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 1), 0x4243); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 2), 0x4344); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 3), 0x4445); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 4), 0x4546); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 5), 0x4647); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (carray + 6), 0x4748); + + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray), 0x4241); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 1), 0x4342); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 2), 0x4443); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 3), 0x4544); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 4), 0x4645); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 5), 0x4746); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (carray + 6), 0x4847); + + /* On an array of guint32 */ + fail_unless_equals_int_hex (GST_READ_UINT16_BE (uarray), 0x4142); + fail_unless_equals_int_hex (GST_READ_UINT16_BE (uarray + 1), 0x4546); + + fail_unless_equals_int_hex (GST_READ_UINT16_LE (uarray), 0x4241); + fail_unless_equals_int_hex (GST_READ_UINT16_LE (uarray + 1), 0x4645); + + + /* 24bit */ + /* First try the standard pointer variants */ + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer), 0x414243); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer + 1), 0x424344); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer + 2), 0x434445); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer + 3), 0x444546); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer + 4), 0x454647); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (cpointer + 5), 0x464748); + + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer), 0x434241); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer + 1), 0x444342); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer + 2), 0x454443); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer + 3), 0x464544); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer + 4), 0x474645); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (cpointer + 5), 0x484746); + + /* On an array of guint8 */ + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray), 0x414243); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray + 1), 0x424344); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray + 2), 0x434445); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray + 3), 0x444546); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray + 4), 0x454647); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (carray + 5), 0x464748); + + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray), 0x434241); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray + 1), 0x444342); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray + 2), 0x454443); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray + 3), 0x464544); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray + 4), 0x474645); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (carray + 5), 0x484746); + + /* On an array of guint32 */ + fail_unless_equals_int_hex (GST_READ_UINT24_BE (uarray), 0x414243); + fail_unless_equals_int_hex (GST_READ_UINT24_BE (uarray + 1), 0x454647); + + fail_unless_equals_int_hex (GST_READ_UINT24_LE (uarray), 0x434241); + fail_unless_equals_int_hex (GST_READ_UINT24_LE (uarray + 1), 0x474645); + + + /* 32bit */ + /* First try the standard pointer variants */ + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer), 0x41424344); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer + 1), 0x42434445); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer + 2), 0x43444546); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer + 3), 0x44454647); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer + 4), 0x45464748); + + fail_unless_equals_int_hex (GST_READ_UINT32_LE (cpointer), 0x44434241); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (cpointer + 1), 0x45444342); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (cpointer + 2), 0x46454443); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (cpointer + 3), 0x47464544); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (cpointer + 4), 0x48474645); + + /* On an array of guint8 */ + fail_unless_equals_int_hex (GST_READ_UINT32_BE (carray), 0x41424344); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (carray + 1), 0x42434445); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (carray + 2), 0x43444546); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (carray + 3), 0x44454647); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (carray + 4), 0x45464748); + + fail_unless_equals_int_hex (GST_READ_UINT32_LE (carray), 0x44434241); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (carray + 1), 0x45444342); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (carray + 2), 0x46454443); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (carray + 3), 0x47464544); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (carray + 4), 0x48474645); + + /* On an array of guint32 */ + fail_unless_equals_int_hex (GST_READ_UINT32_BE (uarray), 0x41424344); + fail_unless_equals_int_hex (GST_READ_UINT32_BE (uarray + 1), 0x45464748); + + fail_unless_equals_int_hex (GST_READ_UINT32_LE (uarray), 0x44434241); + fail_unless_equals_int_hex (GST_READ_UINT32_LE (uarray + 1), 0x48474645); + + + /* 64bit */ + fail_unless_equals_int64_hex (GST_READ_UINT64_BE (cpointer), + 0x4142434445464748); + fail_unless_equals_int64_hex (GST_READ_UINT64_LE (cpointer), + 0x4847464544434241); + + fail_unless_equals_int64_hex (GST_READ_UINT64_BE (carray), + 0x4142434445464748); + fail_unless_equals_int64_hex (GST_READ_UINT64_LE (carray), + 0x4847464544434241); + + fail_unless_equals_int64_hex (GST_READ_UINT64_BE (uarray), + 0x4142434445464748); + fail_unless_equals_int64_hex (GST_READ_UINT64_LE (uarray), + 0x4847464544434241); + + /* make sure the data argument is not duplicated inside the macro + * with possibly unexpected side-effects */ + cpointer = carray; + fail_unless_equals_int (GST_READ_UINT8 (cpointer++), 'A'); + fail_unless (cpointer == carray + 1); + + cpointer = carray; + fail_unless_equals_int_hex (GST_READ_UINT16_BE (cpointer++), 0x4142); + fail_unless (cpointer == carray + 1); + + cpointer = carray; + fail_unless_equals_int_hex (GST_READ_UINT32_BE (cpointer++), 0x41424344); + fail_unless (cpointer == carray + 1); + + cpointer = carray; + fail_unless_equals_int64_hex (GST_READ_UINT64_BE (cpointer++), + 0x4142434445464748); + fail_unless (cpointer == carray + 1); +} + +GST_END_TEST; + +GST_START_TEST (test_write_macros) +{ + guint8 carray[8]; + guint8 *cpointer; + + /* make sure the data argument is not duplicated inside the macro + * with possibly unexpected side-effects */ + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT8 (cpointer++, 'A'); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'A'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT16_BE (cpointer++, 0x4142); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'A'); + fail_unless_equals_int (carray[1], 'B'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT32_BE (cpointer++, 0x41424344); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'A'); + fail_unless_equals_int (carray[3], 'D'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT64_BE (cpointer++, 0x4142434445464748); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'A'); + fail_unless_equals_int (carray[7], 'H'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT16_LE (cpointer++, 0x4142); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'B'); + fail_unless_equals_int (carray[1], 'A'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT32_LE (cpointer++, 0x41424344); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'D'); + fail_unless_equals_int (carray[3], 'A'); + + memset (carray, 0, sizeof (carray)); + cpointer = carray; + GST_WRITE_UINT64_LE (cpointer++, 0x4142434445464748); + fail_unless_equals_pointer (cpointer, carray + 1); + fail_unless_equals_int (carray[0], 'H'); + fail_unless_equals_int (carray[7], 'A'); +} + +GST_END_TEST; + +static void +count_request_pad (const GValue * item, gpointer user_data) +{ + GstPad *pad = GST_PAD (g_value_get_object (item)); + guint *count = (guint *) user_data; + + if (GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) == GST_PAD_REQUEST) + (*count)++; +} + +static guint +request_pads (GstElement * element) +{ + GstIterator *iter; + guint pads = 0; + + iter = gst_element_iterate_pads (element); + fail_unless (gst_iterator_foreach (iter, count_request_pad, &pads) == + GST_ITERATOR_DONE); + gst_iterator_free (iter); + + return pads; +} + +static GstPadLinkReturn +refuse_to_link (GstPad * pad, GstObject * parent, GstPad * peer) +{ + return GST_PAD_LINK_REFUSED; +} + +typedef struct _GstFakeReqSink GstFakeReqSink; +typedef struct _GstFakeReqSinkClass GstFakeReqSinkClass; + +struct _GstFakeReqSink +{ + GstElement element; +}; + +struct _GstFakeReqSinkClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_fakereqsink_get_type (void); + +static GstStaticPadTemplate fakereqsink_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +G_DEFINE_TYPE (GstFakeReqSink, gst_fakereqsink, GST_TYPE_ELEMENT); + +static GstPad * +gst_fakereqsink_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name, const GstCaps * caps) +{ + GstPad *pad; + pad = gst_pad_new_from_static_template (&fakereqsink_sink_template, name); + gst_pad_set_link_function (pad, refuse_to_link); + gst_element_add_pad (GST_ELEMENT_CAST (element), pad); + return pad; +} + +static void +gst_fakereqsink_release_pad (GstElement * element, GstPad * pad) +{ + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (element, pad); +} + +static void +gst_fakereqsink_class_init (GstFakeReqSinkClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_static_metadata (gstelement_class, + "Fake Request Sink", "Sink", "Fake sink with request pads", + "Sebastian Rasmussen "); + + gst_element_class_add_static_pad_template (gstelement_class, + &fakereqsink_sink_template); + + gstelement_class->request_new_pad = gst_fakereqsink_request_new_pad; + gstelement_class->release_pad = gst_fakereqsink_release_pad; +} + +static void +gst_fakereqsink_init (GstFakeReqSink * fakereqsink) +{ +} + +static void +test_link (const gchar * expectation, const gchar * srcname, + const gchar * srcpad, const gchar * srcstate, const gchar * sinkname, + const gchar * sinkpad, const gchar * sinkstate) +{ + GstElement *src, *sink, *othersrc, *othersink; + guint src_pads, sink_pads; + + if (g_strcmp0 (srcname, "requestsrc") == 0) + src = gst_element_factory_make ("tee", NULL); + else if (g_strcmp0 (srcname, "requestsink") == 0) + src = gst_element_factory_make ("funnel", NULL); + else if (g_strcmp0 (srcname, "staticsrc") == 0) + src = gst_element_factory_make ("fakesrc", NULL); + else if (g_strcmp0 (srcname, "staticsink") == 0) + src = gst_element_factory_make ("fakesink", NULL); + else + g_assert_not_reached (); + + if (g_strcmp0 (sinkname, "requestsink") == 0) + sink = gst_element_factory_make ("funnel", NULL); + else if (g_strcmp0 (sinkname, "requestsrc") == 0) + sink = gst_element_factory_make ("tee", NULL); + else if (g_strcmp0 (sinkname, "staticsink") == 0) + sink = gst_element_factory_make ("fakesink", NULL); + else if (g_strcmp0 (sinkname, "staticsrc") == 0) + sink = gst_element_factory_make ("fakesrc", NULL); + else if (g_strcmp0 (sinkname, "fakerequestsink") == 0) + sink = gst_element_factory_make ("fakereqsink", NULL); + else + g_assert_not_reached (); + + othersrc = gst_element_factory_make ("fakesrc", NULL); + othersink = gst_element_factory_make ("fakesink", NULL); + + if (g_strcmp0 (srcstate, "linked") == 0) + fail_unless (gst_element_link_pads (src, srcpad, othersink, NULL)); + if (g_strcmp0 (sinkstate, "linked") == 0) + fail_unless (gst_element_link_pads (othersrc, NULL, sink, sinkpad)); + if (g_strcmp0 (srcstate, "unlinkable") == 0) { + GstPad *pad = gst_element_get_static_pad (src, srcpad ? srcpad : "src"); + gst_pad_set_link_function (pad, refuse_to_link); + gst_object_unref (pad); + } + if (g_strcmp0 (sinkstate, "unlinkable") == 0) { + GstPad *pad = gst_element_get_static_pad (sink, sinkpad ? sinkpad : "sink"); + gst_pad_set_link_function (pad, refuse_to_link); + gst_object_unref (pad); + } + + src_pads = request_pads (src); + sink_pads = request_pads (sink); + if (g_strcmp0 (expectation, "OK") == 0) { + fail_unless (gst_element_link_pads (src, srcpad, sink, sinkpad)); + if (g_str_has_prefix (srcname, "request")) { + fail_unless_equals_int (request_pads (src), src_pads + 1); + } else { + fail_unless_equals_int (request_pads (src), src_pads); + } + if (g_str_has_prefix (sinkname, "request")) { + fail_unless_equals_int (request_pads (sink), sink_pads + 1); + } else { + fail_unless_equals_int (request_pads (sink), sink_pads); + } + } else { + fail_if (gst_element_link_pads (src, srcpad, sink, sinkpad)); + fail_unless_equals_int (request_pads (src), src_pads); + fail_unless_equals_int (request_pads (sink), sink_pads); + } + + gst_object_unref (othersrc); + gst_object_unref (othersink); + + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_START_TEST (test_element_link) +{ + /* Successful cases */ + + gst_element_register (NULL, "fakereqsink", GST_RANK_NONE, + gst_fakereqsink_get_type ()); + + test_link ("OK", "staticsrc", "src", "", "staticsink", "sink", ""); + test_link ("OK", "staticsrc", "src", "", "requestsink", "sink_0", ""); + test_link ("OK", "staticsrc", "src", "", "staticsink", NULL, ""); + test_link ("OK", "staticsrc", "src", "", "requestsink", NULL, ""); + test_link ("OK", "requestsrc", "src_0", "", "staticsink", "sink", ""); + test_link ("OK", "requestsrc", "src_0", "", "requestsink", "sink_0", ""); + test_link ("OK", "requestsrc", "src_0", "", "staticsink", NULL, ""); + test_link ("OK", "requestsrc", "src_0", "", "requestsink", NULL, ""); + test_link ("OK", "staticsrc", NULL, "", "staticsink", "sink", ""); + test_link ("OK", "staticsrc", NULL, "", "requestsink", "sink_0", ""); + test_link ("OK", "staticsrc", NULL, "", "staticsink", NULL, ""); + test_link ("OK", "staticsrc", NULL, "", "requestsink", NULL, ""); + test_link ("OK", "requestsrc", NULL, "", "staticsink", "sink", ""); + test_link ("OK", "requestsrc", NULL, "", "requestsink", "sink_0", ""); + test_link ("OK", "requestsrc", NULL, "", "staticsink", NULL, ""); + test_link ("OK", "requestsrc", NULL, "", "requestsink", NULL, ""); + + /* Failure cases */ + + test_link ("NOK", "staticsrc", "missing", "", "staticsink", "sink", ""); + test_link ("NOK", "staticsink", "sink", "", "staticsink", "sink", ""); + test_link ("NOK", "staticsrc", "src", "linked", "staticsink", "sink", ""); + test_link ("NOK", "staticsrc", "src", "", "staticsink", "missing", ""); + test_link ("NOK", "staticsrc", "src", "", "staticsrc", "src", ""); + test_link ("NOK", "staticsrc", "src", "", "staticsink", "sink", "linked"); + test_link ("NOK", "staticsrc", "src", "", "staticsink", "sink", "unlinkable"); + test_link ("NOK", "staticsrc", NULL, "", "staticsink", "sink", "unlinkable"); + test_link ("NOK", "staticsrc", NULL, "", "staticsink", NULL, "unlinkable"); + test_link ("NOK", "requestsrc", "missing", "", "staticsink", "sink", ""); + test_link ("NOK", "requestsink", "sink_0", "", "staticsink", "sink", ""); + test_link ("NOK", "requestsrc", "src_0", "linked", "staticsink", "sink", ""); + test_link ("NOK", "requestsrc", "src_0", "", "staticsink", "missing", ""); + test_link ("NOK", "requestsrc", "src_0", "", "staticsrc", "src", ""); + test_link ("NOK", "requestsrc", "src_0", "", "staticsink", "sink", "linked"); + test_link ("NOK", "requestsrc", "src_0", "", "staticsink", "sink", + "unlinkable"); + test_link ("NOK", "requestsrc", NULL, "", "staticsink", "sink", "unlinkable"); + test_link ("NOK", "requestsrc", NULL, "", "staticsink", NULL, "unlinkable"); + test_link ("NOK", "staticsrc", "missing", "", "requestsink", "sink_0", ""); + test_link ("NOK", "staticsink", "sink", "", "requestsink", "sink_0", ""); + test_link ("NOK", "staticsrc", "src", "linked", "requestsink", "sink_0", ""); + test_link ("NOK", "staticsrc", "src", "", "requestsink", "missing", ""); + test_link ("NOK", "staticsrc", "src", "", "requestsrc", "src_0", ""); + test_link ("NOK", "staticsrc", "src", "", "requestsink", "sink_0", "linked"); + test_link ("NOK", "staticsrc", "src", "unlinkable", "requestsink", + "sink_0", ""); + test_link ("NOK", "staticsrc", NULL, "unlinkable", "requestsink", + "sink_0", ""); + test_link ("NOK", "staticsrc", NULL, "unlinkable", "requestsink", NULL, ""); + test_link ("NOK", "requestsrc", "src_0", "", "staticsink", NULL, + "unlinkable"); + test_link ("NOK", "requestsrc", NULL, "", "fakerequestsink", NULL, ""); +} + +GST_END_TEST; + +typedef struct _GstTestPadReqSink GstTestPadReqSink; +typedef struct _GstTestPadReqSinkClass GstTestPadReqSinkClass; + +struct _GstTestPadReqSink +{ + GstElement element; +}; + +struct _GstTestPadReqSinkClass +{ + GstElementClass parent_class; +}; + +G_GNUC_INTERNAL GType gst_testpadreqsink_get_type (void); + +static GstStaticPadTemplate testpadreqsink_video_template = +GST_STATIC_PAD_TEMPLATE ("video_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("video/x-raw")); + +static GstStaticPadTemplate testpadreqsink_audio_template = +GST_STATIC_PAD_TEMPLATE ("audio_%u", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("audio/x-raw")); + +G_DEFINE_TYPE (GstTestPadReqSink, gst_testpadreqsink, GST_TYPE_ELEMENT); + +static GstPad * +gst_testpadreqsink_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) +{ + GstPad *pad; + pad = gst_pad_new_from_template (templ, name); + gst_pad_set_active (pad, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (element), pad); + return pad; +} + +static void +gst_testpadreqsink_release_pad (GstElement * element, GstPad * pad) +{ + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (element, pad); +} + +static void +gst_testpadreqsink_class_init (GstTestPadReqSinkClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_static_metadata (gstelement_class, + "Test Pad Request Sink", "Sink", "Sink for unit tests with request pads", + "Thiago Santos "); + + gst_element_class_add_static_pad_template (gstelement_class, + &testpadreqsink_video_template); + gst_element_class_add_static_pad_template (gstelement_class, + &testpadreqsink_audio_template); + + gstelement_class->request_new_pad = gst_testpadreqsink_request_new_pad; + gstelement_class->release_pad = gst_testpadreqsink_release_pad; +} + +static void +gst_testpadreqsink_init (GstTestPadReqSink * testpadeqsink) +{ +} + +static GstCaps *padreqsink_query_caps = NULL; + +static gboolean +testpadreqsink_peer_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + if (padreqsink_query_caps) { + gst_query_set_caps_result (query, padreqsink_query_caps); + res = TRUE; + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } + + return res; +} + +static void +check_get_compatible_pad_request (GstElement * element, GstCaps * peer_caps, + GstCaps * filter, gboolean should_get_pad, const gchar * pad_tmpl_name) +{ + GstPad *peer, *requested; + GstPadTemplate *tmpl; + + gst_caps_replace (&padreqsink_query_caps, peer_caps); + peer = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_query_function (peer, testpadreqsink_peer_query); + requested = gst_element_get_compatible_pad (element, peer, filter); + + if (should_get_pad) { + fail_unless (requested != NULL); + if (pad_tmpl_name) { + tmpl = gst_pad_get_pad_template (requested); + fail_unless (strcmp (GST_PAD_TEMPLATE_NAME_TEMPLATE (tmpl), + pad_tmpl_name) == 0); + gst_object_unref (tmpl); + } + gst_element_release_request_pad (element, requested); + gst_object_unref (requested); + } else { + fail_unless (requested == NULL); + } + + if (peer_caps) + gst_caps_unref (peer_caps); + if (filter) + gst_caps_unref (filter); + gst_object_unref (peer); +} + +GST_START_TEST (test_element_get_compatible_pad_request) +{ + GstElement *element; + + gst_element_register (NULL, "testpadreqsink", GST_RANK_NONE, + gst_testpadreqsink_get_type ()); + + element = gst_element_factory_make ("testpadreqsink", NULL); + + /* Try with a peer pad with any caps and no filter, + * returning any pad is ok */ + check_get_compatible_pad_request (element, NULL, NULL, TRUE, NULL); + /* Try with a peer pad with any caps and video as filter */ + check_get_compatible_pad_request (element, NULL, + gst_caps_from_string ("video/x-raw"), TRUE, "video_%u"); + /* Try with a peer pad with any caps and audio as filter */ + check_get_compatible_pad_request (element, NULL, + gst_caps_from_string ("audio/x-raw"), TRUE, "audio_%u"); + /* Try with a peer pad with any caps and fake caps as filter */ + check_get_compatible_pad_request (element, NULL, + gst_caps_from_string ("foo/bar"), FALSE, NULL); + + /* Try with a peer pad with video caps and no caps as filter */ + check_get_compatible_pad_request (element, + gst_caps_from_string ("video/x-raw"), NULL, TRUE, "video_%u"); + /* Try with a peer pad with audio caps and no caps as filter */ + check_get_compatible_pad_request (element, + gst_caps_from_string ("audio/x-raw"), NULL, TRUE, "audio_%u"); + /* Try with a peer pad with video caps and foo caps as filter */ + check_get_compatible_pad_request (element, + gst_caps_from_string ("video/x-raw"), gst_caps_from_string ("foo/bar"), + FALSE, NULL); + + gst_caps_replace (&padreqsink_query_caps, NULL); + gst_object_unref (element); +} + +GST_END_TEST; + +GST_START_TEST (test_element_link_with_ghost_pads) +{ + GstElement *sink_bin, *sink2_bin, *pipeline; + GstElement *src, *tee, *queue, *queue2, *sink, *sink2; + GstMessage *message; + GstBus *bus; + + fail_unless (pipeline = gst_pipeline_new (NULL)); + fail_unless (sink_bin = gst_bin_new (NULL)); + fail_unless (sink2_bin = gst_bin_new (NULL)); + fail_unless (src = gst_element_factory_make ("fakesrc", NULL)); + fail_unless (tee = gst_element_factory_make ("tee", NULL)); + fail_unless (queue = gst_element_factory_make ("queue", NULL)); + fail_unless (sink = gst_element_factory_make ("fakesink", NULL)); + fail_unless (queue2 = gst_element_factory_make ("queue", NULL)); + fail_unless (sink2 = gst_element_factory_make ("fakesink", NULL)); + + gst_bin_add_many (GST_BIN (pipeline), src, tee, queue, sink, sink2_bin, NULL); + fail_unless (gst_element_link_many (src, tee, queue, sink, NULL)); + fail_unless (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_ASYNC); + + /* wait for a buffer to arrive at the sink */ + bus = gst_element_get_bus (pipeline); + message = gst_bus_poll (bus, GST_MESSAGE_ASYNC_DONE, -1); + gst_message_unref (message); + gst_object_unref (bus); + + gst_bin_add_many (GST_BIN (sink_bin), queue2, sink2, NULL); + fail_unless (gst_element_link (queue2, sink2)); + + gst_bin_add (GST_BIN (sink2_bin), sink_bin); + /* The two levels of bins with the outer bin in the running state is + * important, when the second ghost pad is created (from this + * gst_element_link()) in the running bin, we need to activate the + * created ghost pad */ + fail_unless (gst_element_link (tee, queue2)); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static const GstClockTime times1[] = { + 257116899087539, 120632754291904, + 257117935914250, 120633825367344, + 257119448289434, 120635306141271, + 257120493671524, 120636384357825, + 257121550784861, 120637417438878, + 257123042669403, 120638895344150, + 257124089184865, 120639971729651, + 257125545836474, 120641406788243, + 257127030618490, 120642885914220, + 257128033712770, 120643888843907, + 257129081768074, 120644981892002, + 257130145383845, 120646016376867, + 257131532530200, 120647389850987, + 257132578136034, 120648472767247, + 257134102475722, 120649953785315, + 257135142994788, 120651028858556, + 257136585079868, 120652441303624, + 257137618260656, 120653491627112, + 257139108694546, 120654963978184, + 257140644022048, 120656500233068, + 257141685671825, 120657578510655, + 257142741238288, 120658610889805, + 257144243633074, 120660093098060, + 257145287962271, 120661172901525, + 257146740596716, 120662591572179, + 257147757607150, 120663622822179, + 257149263992401, 120665135578527, + 257150303719290, 120666176166905, + 257151355569906, 120667217304601, + 257152430578406, 120668326099768, + 257153490501095, 120669360554111, + 257154512360784, 120670365497960, + 257155530610577, 120671399006259, + 257156562091659, 120672432728185, + 257157945388742, 120673800312414, + 257159287547073, 120675142444983, + 257160324912880, 120676215076817, + 257345408328042, 120861261738196, + 257346412270919, 120862265613926, + 257347420532284, 120863278644933, + 257348431187638, 120864284412754, + 257349439018028, 120865293110265, + 257351796217938, 120867651111973, + 257352803038092, 120868659107578, + 257354152688899, 120870008594883, + 257355157088906, 120871011097327, + 257356162439182, 120872016346348, + 257357167872040, 120873021656407, + 257358182440058, 120874048633945, + 257359198881356, 120875052265538, + 257100756525466, 120616619282139, + 257101789337770, 120617655475988, + 257102816323472, 120618674000157, + 257103822485250, 120619679005039, + 257104840760423, 120620710743321, + 257105859459496, 120621715351476, + 257106886662470, 120622764942539, + 257108387497864, 120624244221106, + 257109428859191, 120625321461096, + 257110485892785, 120626356892003, + 257111869872141, 120627726459874, + 257112915903774, 120628813190830, + 257114329982208, 120630187061682, + 257115376666026, 120631271992101 +}; + + +static const GstClockTime times2[] = { + 291678579009762, 162107345029507, + 291679770464405, 162108597684538, + 291680972924370, 162109745816863, + 291682278949629, 162111000577605, + 291683590706117, 162112357724822, + 291684792322541, 162113613156950, + 291685931362506, 162114760556854, + 291687132156589, 162115909238493, + 291688265012060, 162117120603240, + 291689372183047, 162118126279508, + 291705506022294, 162134329373992, + 291667914301004, 162096795553658, + 291668119537668, 162096949051905, + 291668274671455, 162097049238371, + 291668429435600, 162097256356719, + 291668586128535, 162097355689763, + 291668741306233, 162097565678460, + 291668893789203, 162097661044916, + 291669100256555, 162097865694145, + 291669216417563, 162098069214693, + 291669836394620, 162098677275530, + 291669990447821, 162098792601263, + 291670149426086, 162098916899184, + 291670300232152, 162099114225621, + 291670411261917, 162099236784112, + 291670598483507, 162099402158751, + 291671716582687, 162100558744122, + 291672600759788, 162101499326359, + 291673919988307, 162102751981384, + 291675174441643, 162104005551939, + 291676271562197, 162105105252898, + 291677376345374, 162106195737516 +}; + +static const GstClockTime times3[] = { + 291881924291688, 162223997578228, + 291883318122262, 162224167198360, + 291884786394838, 162224335172501, + 291886004374386, 162224503695531, + 291887224353285, 162224673560021, + 291888472403367, 162224843760361, + 291889727977561, 162225014479362, + 291890989982306, 162225174554558, + 291892247875763, 162225339753039, + 291893502163547, 162225673230987, + 291894711382216, 162225829494101, + 291895961021506, 162225964530832, + 291897251690854, 162226127287981, + 291898508630785, 162226303710406, + 291899740172868, 162226472478047, + 291900998878873, 162226637402085, + 291902334919875, 162226797873245, + 291903572196610, 162226964352963, + 291904727342699, 162227125312525, + 291906071189108, 162228361337153, + 291907308146005, 162229560625638, + 291908351925126, 162230604986650, + 291909396411423, 162231653690543, + 291910453965348, 162232698550995, + 291912096870744, 162233475264947, + 291913234148395, 162233606516855, + 291915448096576, 162233921145559, + 291916707748827, 162234047154298, + 291918737451070, 162234370837425, + 291919896016205, 162234705504337, + 291921098663980, 162234872320397, + 291922315691409, 162235031023366 +}; + +static const GstClockTime times4[] = { + 10, 0, + 20, 20, + 30, 40, + 40, 60, + 50, 80, + 60, 100 +}; + +struct test_entry +{ + gint n; + const GstClockTime *v; + GstClockTime expect_internal; + GstClockTime expect_external; + guint64 expect_num; + guint64 expect_denom; +} times[] = { + { + 32, times1, 257154512360784, 120670380469753, 4052622913376634109, + 4052799313904261962}, { + 64, times1, 257359198881356, 120875054227405, 2011895759027682422, + 2012014931360215503}, { + 32, times2, 291705506022294, 162134297192792, 2319535707505209857, + 2321009753483354451}, { + 32, times3, 291922315691409, 162234934150296, 1370930728180888261, + 4392719527011673456}, { + 6, times4, 60, 100, 2, 1} +}; + +GST_START_TEST (test_regression) +{ + GstClockTime m_num, m_den, internal, external; + gdouble r_squared, rate, expect_rate; + gint i; + + for (i = 0; i < G_N_ELEMENTS (times); i++) { + fail_unless (gst_calculate_linear_regression (times[i].v, NULL, times[i].n, + &m_num, &m_den, &external, &internal, &r_squared)); + + GST_LOG ("xbase %" G_GUINT64_FORMAT " ybase %" G_GUINT64_FORMAT " rate = %" + G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT " = %.10f r_squared %f\n", + internal, external, m_num, m_den, (gdouble) (m_num) / (m_den), + r_squared); + + /* Require high correlation */ + fail_unless (r_squared >= 0.9); + + fail_unless (internal == times[i].expect_internal, + "Regression params %d fail. internal %" G_GUINT64_FORMAT + " != expected %" G_GUINT64_FORMAT, i, internal, + times[i].expect_internal); + /* Rate must be within 1% tolerance */ + expect_rate = ((gdouble) (times[i].expect_num) / times[i].expect_denom); + rate = ((gdouble) (m_num) / m_den); + fail_unless ((expect_rate - rate) >= -0.1 && (expect_rate - rate) <= 0.1, + "Regression params %d fail. Rate out of range. Expected %f, got %f", + i, expect_rate, rate); + fail_unless (external >= times[i].expect_external * 0.99 && + external <= times[i].expect_external * 1.01, + "Regression params %d fail. external %" G_GUINT64_FORMAT + " != expected %" G_GUINT64_FORMAT, i, external, + times[i].expect_external); + } +} + +GST_END_TEST; + +static Suite * +gst_utils_suite (void) +{ + Suite *s = suite_create ("GstUtils"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_buffer_probe_n_times); + tcase_add_test (tc_chain, test_buffer_probe_once); + tcase_add_test (tc_chain, test_math_scale); + tcase_add_test (tc_chain, test_math_scale_round); + tcase_add_test (tc_chain, test_math_scale_ceil); + tcase_add_test (tc_chain, test_math_scale_uint64); + tcase_add_test (tc_chain, test_math_scale_random); +#ifdef HAVE_GSL +#ifdef HAVE_GMP + tcase_add_test (tc_chain, test_math_scale_gmp); + tcase_add_test (tc_chain, test_math_scale_gmp_int); +#endif +#endif + + tcase_add_test (tc_chain, test_guint64_to_gdouble); + tcase_add_test (tc_chain, test_gdouble_to_guint64); +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_parse_bin_from_description); +#endif + tcase_add_test (tc_chain, test_element_found_tags); + tcase_add_test (tc_chain, test_element_link); + tcase_add_test (tc_chain, test_element_link_with_ghost_pads); + tcase_add_test (tc_chain, test_element_unlink); + tcase_add_test (tc_chain, test_element_get_compatible_pad_request); + tcase_add_test (tc_chain, test_set_value_from_string); + tcase_add_test (tc_chain, test_binary_search); + + tcase_add_test (tc_chain, test_pad_proxy_query_caps_aggregation); + tcase_add_test (tc_chain, test_greatest_common_divisor); + + tcase_add_test (tc_chain, test_read_macros); + tcase_add_test (tc_chain, test_write_macros); + tcase_add_test (tc_chain, test_regression); + + return s; +} + +GST_CHECK_MAIN (gst_utils); diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c new file mode 100644 index 0000000..35bd23c --- /dev/null +++ b/tests/check/gst/gstvalue.c @@ -0,0 +1,3485 @@ +/* GStreamer + * Copyright (C) <2004> David Schleef + * Copyright (C) <2005> Thomas Vander Stichele + * + * gstvalue.c: Unit tests for GstValue + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GLIB_DISABLE_DEPRECATION_WARNINGS +#include + + +GST_START_TEST (test_deserialize_buffer) +{ + GValue value = { 0 }; + GstBuffer *buf; + guint8 data[8]; + guint64 val; + + g_value_init (&value, GST_TYPE_BUFFER); + fail_unless (gst_value_deserialize (&value, "1234567890abcdef")); + /* does not increase the refcount */ + buf = GST_BUFFER (g_value_get_boxed (&value)); + ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1); + + /* does not increase the refcount */ + buf = gst_value_get_buffer (&value); + ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1); + + gst_buffer_extract (buf, 0, data, 8); + val = GST_READ_UINT64_BE (data); + fail_unless_equals_uint64 (val, G_GUINT64_CONSTANT (0x1234567890abcdef)); + + /* cleanup */ + g_value_unset (&value); +} + +GST_END_TEST; + +/* create and serialize a buffer */ +GST_START_TEST (test_serialize_buffer) +{ + GValue value = { 0 }; + GstBuffer *buf; + gchar *serialized; + const guint8 buf_data[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }; + gint len; + + len = sizeof (buf_data); + buf = gst_buffer_new_and_alloc (len); + + gst_buffer_fill (buf, 0, (gchar *) buf_data, len); + + ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1); + + /* and assign buffer to mini object */ + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_take_buffer (&value, buf); + ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1); + + /* now serialize it */ + serialized = gst_value_serialize (&value); + GST_DEBUG ("serialized buffer to %s", serialized); + fail_unless (serialized != NULL); + fail_unless_equals_string (serialized, "1234567890abcdef"); + + /* refcount should not change */ + ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1); + + /* cleanup */ + g_free (serialized); + g_value_unset (&value); + + /* take NULL buffer */ + g_value_init (&value, GST_TYPE_BUFFER); + GST_DEBUG ("setting NULL buffer"); + gst_value_take_buffer (&value, NULL); + + /* now serialize it */ + GST_DEBUG ("serializing NULL buffer"); + serialized = gst_value_serialize (&value); + /* should return NULL */ + fail_unless (serialized == NULL); + + g_free (serialized); + g_value_unset (&value); +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gint64) +{ + GValue value = { 0 }; + const char *strings[] = { + "12345678901", + "-12345678901", + "1152921504606846976", + "-1152921504606846976", + }; + gint64 results[] = { + 12345678901LL, + -12345678901LL, + 1152921504606846976LL, + -1152921504606846976LL, + }; + int i; + + g_value_init (&value, G_TYPE_INT64); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_int64 (&value) == results[i], + "resulting value is %" G_GINT64_FORMAT ", not %" G_GINT64_FORMAT + ", for string %s (%d)", g_value_get_int64 (&value), + results[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_guint64) +{ + GValue value = { 0 }; + const char *strings[] = { + "0xffffffffffffffff", + "9223372036854775810", + "-9223372036854775810", + "-1", + "1", + "-0", + }; + guint64 results[] = { + 0xffffffffffffffffULL, + 9223372036854775810ULL, + 9223372036854775806ULL, + (guint64) - 1, + 1, + 0, + }; + int i; + + g_value_init (&value, G_TYPE_UINT64); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_uint64 (&value) == results[i], + "resulting value is %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT + ", for string %s (%d)", g_value_get_uint64 (&value), + results[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_guchar) +{ + GValue value = { 0 }; + const char *strings[] = { + "0xff", + "255", + "-1", + "1", + "-0", + }; + guchar results[] = { + 0xff, + 255, + (guchar) - 1, + 1, + 0, + }; + int i; + + g_value_init (&value, G_TYPE_UCHAR); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_uchar (&value) == results[i], + "resulting value is %u not %u, for string %s (%d)", + g_value_get_uchar (&value), results[i], strings[i], i); + } + + /* test serialisation as well while we're at it */ + { + gchar *str; + GValue value = { 0 }; + g_value_init (&value, G_TYPE_UCHAR); + + g_value_set_uchar (&value, 255); + str = gst_value_serialize (&value); + + fail_unless_equals_string (str, "255"); + g_free (str); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gstfraction) +{ + GValue value = { 0 }; + const char *strings[] = { + "4/5", + "-8/9" + }; + gint64 result_numers[] = { + 4, + -8 + }; + gint64 result_denoms[] = { + 5, + 9 + }; + + int i; + + g_value_init (&value, GST_TYPE_FRACTION); + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (gst_value_get_fraction_numerator (&value) == result_numers[i], + "resulting numerator value is %d, not %d" + ", for string %s (%d)", gst_value_get_fraction_numerator (&value), + result_numers[i], strings[i], i); + fail_unless (gst_value_get_fraction_denominator (&value) == + result_denoms[i], "resulting denominator value is %d, not %d" + ", for string %s (%d)", gst_value_get_fraction_denominator (&value), + result_denoms[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gint) +{ + GValue value = { 0 }; + const char *strings[] = { + "123456", + "-123456", + "0xFFFF", + "0x0000FFFF", + /* a positive long long, serializing to highest possible positive sint */ + "0x7FFFFFFF", + /* a positive long long, serializing to lowest possible negative sint */ + "0x80000000", + /* a negative long long, serializing to lowest possible negative sint */ + "0xFFFFFFFF80000000", + "0xFF000000", + /* a positive long long serializing to -1 */ + "0xFFFFFFFF", + "0xFFFFFFFF", + /* a negative long long serializing to -1 */ + "0xFFFFFFFFFFFFFFFF", + "0xFFFFFFFFFFFFFFFF", + "0xEFFFFFFF", + }; + /* some casts need to be explicit because of unsigned -> signed */ + gint results[] = { + 123456, + -123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + (gint) 0x80000000, + (gint) 0x80000000, + (gint) 0xFF000000, + -1, + (gint) 0xFFFFFFFF, + -1, + (gint) 0xFFFFFFFFFFFFFFFFLL, + (gint) 0xEFFFFFFF, + }; + int i; + + g_value_init (&value, G_TYPE_INT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_int (&value) == results[i], + "resulting value is %d, not %d, for string %s (%d)", + g_value_get_int (&value), results[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gint_failures) +{ + GValue value = { 0 }; + const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ + "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ + "0xF000000000000000", + "0xFFFFFFF000000000", + "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", + }; + int i; + + g_value_init (&value, G_TYPE_INT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_if (gst_value_deserialize (&value, strings[i]), + "deserialized %s (%d), while it should have failed", strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_guint) +{ + GValue value = { 0 }; + const char *strings[] = { + "123456", + "-123456", + "0xFFFF", + "0x0000FFFF", + /* a positive long long, serializing to highest possible positive sint */ + "0x7FFFFFFF", + /* a positive long long, serializing to lowest possible negative sint */ + "0x80000000", + "2147483648", + /* a negative long long, serializing to lowest possible negative sint */ + "0xFFFFFFFF80000000", + /* a value typically used for rgb masks */ + "0xFF000000", + /* a positive long long serializing to highest possible positive uint */ + "0xFFFFFFFF", + "0xFFFFFFFF", + /* a negative long long serializing to highest possible positive uint */ + "0xFFFFFFFFFFFFFFFF", + "0xEFFFFFFF", + }; + guint results[] = { + 123456, + (guint) - 123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + 0x80000000, + (guint) 2147483648LL, + 0x80000000, + 0xFF000000, + 0xFFFFFFFF, + G_MAXUINT, + (guint) 0xFFFFFFFFFFFFFFFFLL, + 0xEFFFFFFF, + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_uint (&value) == results[i], + "resulting value is %d, not %d, for string %s (%d)", + g_value_get_uint (&value), results[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_guint_failures) +{ + GValue value = { 0 }; + const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ +#if 0 +/* FIXME: these values should not be deserializable, since they overflow + * the target format */ + "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ + "0xF000000000000000", + "0xFFFFFFF000000000", + "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", +#endif + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_if (gst_value_deserialize (&value, strings[i]), + "deserialized %s (%d), while it should have failed", strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_flags) +{ + GValue value = { 0 }; + gchar *string; + GstSeekFlags flags[] = { + 0, + GST_SEEK_FLAG_NONE, + GST_SEEK_FLAG_FLUSH, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, + }; + const char *results[] = { + "GST_SEEK_FLAG_NONE", + "GST_SEEK_FLAG_NONE", + "GST_SEEK_FLAG_FLUSH", + "GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE", + }; + int i; + + g_value_init (&value, GST_TYPE_SEEK_FLAGS); + + for (i = 0; i < G_N_ELEMENTS (flags); ++i) { + g_value_set_flags (&value, flags[i]); + string = gst_value_serialize (&value); + fail_if (string == NULL, "could not serialize flags %d", i); + fail_unless (strcmp (string, results[i]) == 0, + "resulting value is %s, not %s, for flags #%d", string, results[i], i); + g_free (string); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_deserialize_flags) +{ + GValue value = { 0 }; + const char *strings[] = { + "", + "0", + "GST_SEEK_FLAG_NONE", + "GST_SEEK_FLAG_FLUSH", + "0xf", + "15", + "GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE", + }; + GstSeekFlags results[] = { + GST_SEEK_FLAG_NONE, + GST_SEEK_FLAG_NONE, + GST_SEEK_FLAG_NONE, + GST_SEEK_FLAG_FLUSH, + 0xf, + 15, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, + }; + int i; + + g_value_init (&value, GST_TYPE_SEEK_FLAGS); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_flags (&value) == results[i], + "resulting value is %d, not %d, for string %s (%d)", + g_value_get_flags (&value), results[i], strings[i], i); + } + + fail_if (gst_value_deserialize (&value, "foo"), + "flag deserializing for bogus value should have failed!"); + fail_if (gst_value_deserialize (&value, "GST_SEEK_FLAG_FLUSH+foo"), + "flag deserializing for bogus value should have failed!"); + fail_if (gst_value_deserialize (&value, + "GST_SEEK_FLAG_FLUSH+foo+GST_SEEK_FLAG_ACCURATE"), + "flag deserializing for bogus value should have failed!"); +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gtype) +{ + GValue value = { 0 }; + const char *strings[] = { + "gchararray", + "gint", + }; + GType results[] = { + G_TYPE_STRING, + G_TYPE_INT, + }; + int i; + + g_value_init (&value, G_TYPE_GTYPE); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_gtype (&value) == results[i], + "resulting value is %" G_GSIZE_FORMAT ", not %" G_GSIZE_FORMAT + ", for string %s (%d)", + g_value_get_gtype (&value), results[i], strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_gtype_failures) +{ + GValue value = { 0 }; + const char *strings[] = { + "-", /* not a gtype */ + }; + int i; + + g_value_init (&value, G_TYPE_GTYPE); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_if (gst_value_deserialize (&value, strings[i]), + "deserialized %s (%d), while it should have failed", strings[i], i); + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_bitmask) +{ + GValue value = { 0 }; + const char *strings[] = { + "0xffffffffffffffff", + "0x1234567890ABCDEF", + }; + guint64 results[] = { + 0xffffffffffffffffULL, + 0x1234567890ABCDEFULL, + }; + int i; + + g_value_init (&value, GST_TYPE_BITMASK); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (gst_value_get_bitmask (&value) == results[i], + "resulting value is 0x%016" G_GINT64_MODIFIER "x, not 0x%016" + G_GINT64_MODIFIER "x, for string %s (%d)", + gst_value_get_bitmask (&value), results[i], strings[i], i); + } +} + +GST_END_TEST; + +static void +check_flagset_mask_serialisation (GValue * value, guint test_flags, + guint test_mask) +{ + gchar *string; + gst_value_set_flagset (value, test_flags, test_mask); + + /* Normalise our test flags against the mask now for easier testing, + * as that's what we expect to get back from the flagset after it + * normalises internally */ + test_flags &= test_mask; + + /* Check the values got stored correctly */ + fail_unless (gst_value_get_flagset_flags (value) == test_flags, + "resulting flags value is 0x%u, not 0x%x", + gst_value_get_flagset_flags (value), test_flags); + fail_unless (gst_value_get_flagset_mask (value) == test_mask, + "resulting mask is 0x%u, not 0x%x", + gst_value_get_flagset_mask (value), test_mask); + + string = gst_value_serialize (value); + fail_if (string == NULL, "could not serialize flagset"); + + GST_DEBUG ("Serialized flagset to: %s", string); + + fail_unless (gst_value_deserialize (value, string), + "could not deserialize %s", string); + + fail_unless (gst_value_get_flagset_flags (value) == test_flags, + "resulting flags value is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_flags (value), test_flags, string); + + fail_unless (gst_value_get_flagset_mask (value) == test_mask, + "resulting mask is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_mask (value), test_mask, string); + + g_free (string); +} + +GST_START_TEST (test_flagset) +{ + GValue value = G_VALUE_INIT; + GValue value2 = G_VALUE_INIT; + GValue dest = G_VALUE_INIT; + gchar *string; + GType test_flagset_type; + guint test_flags, test_mask; + + /* Test serialisation of abstract type */ + g_value_init (&value, GST_TYPE_FLAG_SET); + + test_flags = 0xf1f1; + test_mask = 0xffff; + + gst_value_set_flagset (&value, test_flags, test_mask); + string = gst_value_serialize (&value); + fail_if (string == NULL, "could not serialize flagset"); + + fail_unless (gst_value_deserialize (&value, string), + "could not deserialize %s", string); + + fail_unless (gst_value_get_flagset_flags (&value) == test_flags, + "resulting value is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_flags (&value), test_flags, string); + + fail_unless (gst_value_get_flagset_mask (&value) == test_mask, + "resulting value is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_mask (&value), test_mask, string); + + g_free (string); + g_value_unset (&value); + + /* Check we can't wrap a random non-flags type */ + ASSERT_CRITICAL (gst_flagset_register (GST_TYPE_OBJECT)); + + test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS); + + fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET)); + + g_value_init (&value, test_flagset_type); + + test_flags = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE | + GST_SEEK_FLAG_TRICKMODE_KEY_UNITS; + test_mask = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE | + GST_SEEK_FLAG_TRICKMODE_NO_AUDIO; + + check_flagset_mask_serialisation (&value, test_flags, test_mask); + /* Check serialisation works with the generic 'exact' flag */ + check_flagset_mask_serialisation (&value, test_flags, + GST_FLAG_SET_MASK_EXACT); + + /* Check deserialisation of flagset in 'flags' form, without + * the hex strings at the start */ + test_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE; + test_mask = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE | + GST_SEEK_FLAG_TRICKMODE_NO_AUDIO; + string = g_strdup ("+flush+trickmode/trickmode-no-audio"); + + fail_unless (gst_value_deserialize (&value, string), + "could not deserialize %s", string); + + GST_DEBUG ("Deserialized %s to 0x%x:0x%x", string, + gst_value_get_flagset_flags (&value), + gst_value_get_flagset_mask (&value)); + + fail_unless (gst_value_get_flagset_flags (&value) == test_flags, + "resulting flags value is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_flags (&value), (test_flags & test_mask), string); + + fail_unless (gst_value_get_flagset_mask (&value) == test_mask, + "resulting mask is 0x%u, not 0x%x, for string %s", + gst_value_get_flagset_mask (&value), test_mask, string); + + g_free (string); + g_value_unset (&value); + + /* Test that fixating don't-care fields works, using our + * sub-type flagset for good measure */ + g_value_init (&value, test_flagset_type); + gst_value_set_flagset (&value, test_flags, test_mask); + + fail_unless (gst_value_fixate (&dest, &value)); + fail_unless (gst_value_get_flagset_flags (&dest) == test_flags); + fail_unless (gst_value_get_flagset_mask (&dest) == GST_FLAG_SET_MASK_EXACT); + + g_value_unset (&value); + + /* Intersection tests */ + g_value_init (&value, GST_TYPE_FLAG_SET); + g_value_init (&value2, test_flagset_type); + + /* We want Accurate, but not Snap-Before */ + gst_value_set_flagset (&value, GST_SEEK_FLAG_ACCURATE, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SNAP_BEFORE); + + /* This only cares that things are flushing */ + gst_value_set_flagset (&value2, GST_SEEK_FLAG_FLUSH, GST_SEEK_FLAG_FLUSH); + + test_flags = GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH; + test_mask = + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_BEFORE; + + /* GstFlagSet should always intersect with itself */ + g_value_unset (&dest); + fail_unless (gst_value_can_intersect (&value, &value)); + fail_unless (gst_value_intersect (&dest, &value, &value)); + + /* GstFlagSet subtype should intersect with itself */ + g_value_unset (&dest); + fail_unless (gst_value_can_intersect (&value2, &value2)); + fail_unless (gst_value_intersect (&dest, &value2, &value2)); + + /* Check we can intersect custom flagset subtype with flagset */ + g_value_unset (&dest); + fail_unless (gst_value_can_intersect (&value2, &value)); + fail_unless (gst_value_intersect (&dest, &value2, &value)); + + /* and in the other order */ + g_value_unset (&dest); + fail_unless (gst_value_can_intersect (&value, &value2)); + fail_unless (gst_value_intersect (&dest, &value, &value2)); + + fail_unless (gst_value_get_flagset_flags (&dest) == test_flags, + "resulting flags value is 0x%u, not 0x%x", + gst_value_get_flagset_flags (&dest), test_flags); + + fail_unless (gst_value_get_flagset_mask (&dest) == test_mask, + "resulting mask is 0x%u, not 0x%x", + gst_value_get_flagset_mask (&dest), test_mask); + + gst_value_set_flagset (&value, + GST_SEEK_FLAG_ACCURATE, GST_SEEK_FLAG_ACCURATE); + gst_value_set_flagset (&value2, GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SNAP_BEFORE | GST_SEEK_FLAG_FLUSH); + /* Check that accurate alone is a subset of accurate+!snap_before+flush, + * but not vice-versa */ + fail_unless (gst_value_is_subset (&value, &value2)); + fail_if (gst_value_is_subset (&value2, &value)); + + g_value_unset (&dest); + g_value_unset (&value); + g_value_unset (&value2); +} + +GST_END_TEST; + + +GST_START_TEST (test_string) +{ + const gchar *try[] = { + "Dude", + "Hi, I'm a string", + "tüüüt!", + "\"\"" /* Empty string */ + }; + gchar *tmp; + GValue v = { 0, }; + guint i; + + g_value_init (&v, G_TYPE_STRING); + for (i = 0; i < G_N_ELEMENTS (try); i++) { + g_value_set_string (&v, try[i]); + tmp = gst_value_serialize (&v); + fail_if (tmp == NULL, "couldn't serialize: %s\n", try[i]); + fail_unless (gst_value_deserialize (&v, tmp), + "couldn't deserialize: %s\n", tmp); + g_free (tmp); + + fail_unless (g_str_equal (g_value_get_string (&v), try[i]), + "\nserialized : %s\ndeserialized: %s", try[i], + g_value_get_string (&v)); + } + /* NULL strings should not be serializable */ + g_value_set_string (&v, NULL); + fail_unless (gst_value_serialize (&v) == NULL); + g_value_unset (&v); +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_string) +{ + struct + { + const gchar *from; + const gchar *to; + } tests[] = { + { + "\"foo\"", "foo"}, { + "\"foo\\%\"", "foo%"}, { + "\"0123456789_-+/:.\"", "0123456789_-+/:."}, { + "\"Hello\\ World\"", "Hello World"}, { + "\"Hello\\ World", "\"Hello\\ World"}, { + "\"\\", "\"\\"}, { + "\"\\0", "\"\\0"}, { + "", ""}, /* empty strings */ + { + "\"\"", ""}, /* quoted empty string -> empty string */ + /* Expected FAILURES: */ + { + "\"\\0\"", NULL}, /* unfinished escaped character */ + { + "\"", NULL}, /* solitary quote */ + { + "\" \"", NULL}, /* spaces must be escaped */ +#if 0 + /* FIXME 0.9: this test should fail, but it doesn't */ + { + "tüüt", NULL} /* string with special chars must be escaped */ +#endif + }; + guint i; + GValue v = { 0, }; + + g_value_init (&v, G_TYPE_STRING); + for (i = 0; i < G_N_ELEMENTS (tests); i++) { + if (gst_value_deserialize (&v, tests[i].from)) { + fail_if (tests[i].to == NULL, + "I got %s instead of a failure", g_value_get_string (&v)); + fail_unless (g_str_equal (g_value_get_string (&v), tests[i].to), + "\nwanted: %s\ngot : %s", tests[i].to, g_value_get_string (&v)); + } else { + fail_if (tests[i].to != NULL, "failed, but wanted: %s", tests[i].to); + } + } + g_value_unset (&v); +} + +GST_END_TEST; + +GST_START_TEST (test_value_compare) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue tmp = { 0 }; + GstAllocationParams alloc_params = { 0 }; + + g_value_init (&value1, G_TYPE_INT); + g_value_set_int (&value1, 10); + g_value_init (&value2, G_TYPE_INT); + g_value_set_int (&value2, 20); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + g_value_init (&value1, G_TYPE_DOUBLE); + g_value_set_double (&value1, 10); + g_value_init (&value2, G_TYPE_DOUBLE); + g_value_set_double (&value2, 20); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + g_value_init (&value1, G_TYPE_STRING); + g_value_set_string (&value1, "a"); + g_value_init (&value2, G_TYPE_STRING); + g_value_set_string (&value2, "b"); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + /* Test some NULL string comparisons */ + g_value_set_string (&value2, NULL); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL); + + g_value_unset (&value1); + g_value_unset (&value2); + + /* comparing 2/3 with 3/4 */ + g_value_init (&value1, GST_TYPE_FRACTION); + gst_value_set_fraction (&value1, 2, 3); + g_value_init (&value2, GST_TYPE_FRACTION); + gst_value_set_fraction (&value2, 3, 4); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* comparing -4/5 with 2/-3 */ + g_value_init (&value1, GST_TYPE_FRACTION); + gst_value_set_fraction (&value1, -4, 5); + g_value_init (&value2, GST_TYPE_FRACTION); + gst_value_set_fraction (&value2, 2, -3); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* comparing 10/100 with 200/2000 */ + g_value_init (&value1, GST_TYPE_FRACTION); + gst_value_set_fraction (&value1, 10, 100); + g_value_init (&value2, GST_TYPE_FRACTION); + gst_value_set_fraction (&value2, 200, 2000); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* comparing -4/5 with 2/-3 */ + g_value_init (&value1, GST_TYPE_FRACTION); + gst_value_set_fraction (&value1, -4, 5); + g_value_init (&value2, GST_TYPE_FRACTION); + gst_value_set_fraction (&value2, 2, -3); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* Check that lists are equal regardless of order */ + g_value_init (&value1, GST_TYPE_LIST); + g_value_init (&tmp, G_TYPE_INT); + g_value_set_int (&tmp, 1); + gst_value_list_append_value (&value1, &tmp); + g_value_set_int (&tmp, 2); + gst_value_list_append_value (&value1, &tmp); + g_value_set_int (&tmp, 3); + gst_value_list_append_value (&value1, &tmp); + g_value_set_int (&tmp, 4); + gst_value_list_append_value (&value1, &tmp); + + g_value_init (&value2, GST_TYPE_LIST); + g_value_set_int (&tmp, 4); + gst_value_list_append_value (&value2, &tmp); + g_value_set_int (&tmp, 3); + gst_value_list_append_value (&value2, &tmp); + g_value_set_int (&tmp, 2); + gst_value_list_append_value (&value2, &tmp); + g_value_set_int (&tmp, 1); + gst_value_list_append_value (&value2, &tmp); + + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL, + "value lists with different order were not equal when they should be"); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL, + "value lists with same order were not equal when they should be"); + fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL, + "value lists with same order were not equal when they should be"); + + /* Carry over the lists to this next check: */ + /* Lists with different sizes are unequal */ + g_value_set_int (&tmp, 1); + gst_value_list_append_value (&value2, &tmp); + + fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL, + "Value lists with different size were equal when they shouldn't be"); + + /* Carry over the lists to this next check: */ + /* Lists with same size but list1 contains one more element not in list2 */ + g_value_set_int (&tmp, 5); + gst_value_list_append_value (&value1, &tmp); + + fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL, + "Value lists with different elements were equal when they shouldn't be"); + fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL, + "Value lists with different elements were equal when they shouldn't be"); + + g_value_unset (&value1); + g_value_unset (&value2); + g_value_unset (&tmp); + + /* Arrays are only equal when in the same order */ + g_value_init (&value1, GST_TYPE_ARRAY); + g_value_init (&tmp, G_TYPE_INT); + g_value_set_int (&tmp, 1); + gst_value_array_append_value (&value1, &tmp); + g_value_set_int (&tmp, 2); + gst_value_array_append_value (&value1, &tmp); + g_value_set_int (&tmp, 3); + gst_value_array_append_value (&value1, &tmp); + g_value_set_int (&tmp, 4); + gst_value_array_append_value (&value1, &tmp); + + g_value_init (&value2, GST_TYPE_ARRAY); + g_value_set_int (&tmp, 4); + gst_value_array_append_value (&value2, &tmp); + g_value_set_int (&tmp, 3); + gst_value_array_append_value (&value2, &tmp); + g_value_set_int (&tmp, 2); + gst_value_array_append_value (&value2, &tmp); + g_value_set_int (&tmp, 1); + gst_value_array_append_value (&value2, &tmp); + + fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL, + "Value arrays with different order were equal when they shouldn't be"); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL, + "Identical value arrays were not equal when they should be"); + fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL, + "Identical value arrays were not equal when they should be"); + + /* Carry over the arrays to this next check: */ + /* Arrays with different sizes are unequal */ + g_value_unset (&value2); + g_value_init (&value2, GST_TYPE_ARRAY); + g_value_copy (&value1, &value2); + + g_value_set_int (&tmp, 1); + gst_value_array_append_value (&value2, &tmp); + + fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL, + "Value arrays with different size were equal when they shouldn't be"); + /* order should not matter */ + fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL, + "Value arrays with different size were equal when they shouldn't be"); + + g_value_unset (&value1); + g_value_unset (&value2); + g_value_unset (&tmp); + + g_value_init (&value1, GST_TYPE_BITMASK); + gst_value_set_bitmask (&value1, 0x123); + g_value_init (&value2, GST_TYPE_BITMASK); + gst_value_set_bitmask (&value2, 0x321); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* Check that we can compare objects */ + g_value_init (&value1, GST_TYPE_BIN); + g_value_take_object (&value1, gst_bin_new (NULL)); + g_value_init (&value2, GST_TYPE_BIN); + g_value_take_object (&value2, gst_bin_new (NULL)); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* Check that we can compare allocation params */ + g_value_init (&value1, GST_TYPE_ALLOCATION_PARAMS); + g_value_set_boxed (&value1, &alloc_params); + g_value_init (&value2, GST_TYPE_ALLOCATION_PARAMS); + alloc_params.align = 1; + g_value_set_boxed (&value2, &alloc_params); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED); + fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + + /* Check that we can compare structure */ + { + GstStructure *s = gst_structure_new_empty ("test"); + + g_value_init (&value1, GST_TYPE_STRUCTURE); + g_value_init (&value2, GST_TYPE_STRUCTURE); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL); + + gst_value_set_structure (&value1, s); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED); + gst_value_set_structure (&value2, s); + fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL); + g_value_unset (&value1); + g_value_unset (&value2); + gst_structure_free (s); + } +} + +GST_END_TEST; + +GST_START_TEST (test_value_intersect) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + GValue item = { 0 }; + gboolean ret; + + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 10); + g_value_init (&src2, G_TYPE_INT); + g_value_set_int (&src2, 20); + ret = gst_value_intersect (&dest, &src1, &src2); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + g_value_init (&src1, G_TYPE_STRING); + g_value_set_static_string (&src1, "YUY2"); + g_value_init (&src2, GST_TYPE_LIST); + g_value_init (&item, G_TYPE_STRING); + g_value_set_static_string (&item, "YUY2"); + gst_value_list_append_value (&src2, &item); + g_value_set_static_string (&item, "I420"); + gst_value_list_append_value (&src2, &item); + g_value_set_static_string (&item, "ABCD"); + gst_value_list_append_value (&src2, &item); + + fail_unless (gst_value_intersect (&dest, &src1, &src2)); + fail_unless (G_VALUE_HOLDS_STRING (&dest)); + fail_unless (g_str_equal (g_value_get_string (&dest), "YUY2")); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&dest); +} + +GST_END_TEST; + + +GST_START_TEST (test_value_subtract_int) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + const GValue *tmp; + gboolean ret; + + /* int <-> int + */ + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 10); + g_value_init (&src2, G_TYPE_INT); + g_value_set_int (&src2, 20); + /* subtract as in sets, result is 10 */ + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* same values, yields empty set */ + ret = gst_value_subtract (&dest, &src1, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int <-> int_range + */ + + /* would yield an empty set */ + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 10); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 0, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a list of two ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 0); + fail_unless (gst_value_get_int_range_max (tmp) == 9); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 11); + fail_unless (gst_value_get_int_range_max (tmp) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 10); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 11); + fail_unless (gst_value_get_int_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 2, empty set */ + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 20); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 10); + fail_unless (gst_value_get_int_range_max (&dest) == 19); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 3, valid set */ + g_value_init (&src1, G_TYPE_INT); + g_value_set_int (&src1, 0); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_HOLDS_INT (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* and the other way around, should keep the range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 10); + fail_unless (gst_value_get_int_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int_range <-> int_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* non overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 30, 40); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 10); + fail_unless (gst_value_get_int_range_max (&dest) == 20); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 30); + fail_unless (gst_value_get_int_range_max (&dest) == 40); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 10, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 21); + fail_unless (gst_value_get_int_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 15, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 10); + fail_unless (gst_value_get_int_range_max (&dest) == 14); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + fail_unless (gst_value_get_int_range_min (&dest) == 21); + fail_unless (gst_value_get_int_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole { int_range, int_range } */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 15, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 10); + fail_unless (gst_value_get_int_range_max (tmp) == 14); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 21); + fail_unless (gst_value_get_int_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int, int } */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 11, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE); + fail_unless (g_value_get_int (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE); + fail_unless (g_value_get_int (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int, int_range } */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 11, 28); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE); + fail_unless (g_value_get_int (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 29); + fail_unless (gst_value_get_int_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int_range, int } */ + g_value_init (&src1, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&src2, 12, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int_range_min (tmp) == 10); + fail_unless (gst_value_get_int_range_max (tmp) == 11); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE); + fail_unless (g_value_get_int (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); +} + +GST_END_TEST; + +GST_START_TEST (test_value_subtract_int64) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + const GValue *tmp; + gboolean ret; + + /* int64 <-> int64 + */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, G_TYPE_INT64); + g_value_set_int64 (&src2, 20); + /* subtract as in sets, result is 10 */ + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* same values, yields empty set */ + ret = gst_value_subtract (&dest, &src1, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int64 <-> int64_range + */ + + /* would yield an empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 0, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a list of two ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 0); + fail_unless (gst_value_get_int64_range_max (tmp) == 9); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 11); + fail_unless (gst_value_get_int64_range_max (tmp) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 11); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 2, empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 19); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 3, valid set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 0); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_HOLDS_INT64 (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* and the other way around, should keep the range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int64_range <-> int64_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* non overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 30, 40); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 30); + fail_unless (gst_value_get_int64_range_max (&dest) == 40); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 21); + fail_unless (gst_value_get_int64_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 15, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 14); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + fail_unless (gst_value_get_int64_range_min (&dest) == 21); + fail_unless (gst_value_get_int64_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole { int64_range, int64_range } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 15, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 10); + fail_unless (gst_value_get_int64_range_max (tmp) == 14); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 21); + fail_unless (gst_value_get_int64_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64, int64 } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 11, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64, int64_range } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 11, 28); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 29); + fail_unless (gst_value_get_int64_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64_range, int64 } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 12, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 10); + fail_unless (gst_value_get_int64_range_max (tmp) == 11); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); +} + +GST_END_TEST; + +GST_START_TEST (test_value_subtract_double) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + const GValue *tmp; + gboolean ret; + + /* double <-> double + */ + g_value_init (&src1, G_TYPE_DOUBLE); + g_value_set_double (&src1, 10.0); + g_value_init (&src2, G_TYPE_DOUBLE); + g_value_set_double (&src2, 20.0); + /* subtract as in sets, result is 10 */ + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* same values, yields empty set */ + ret = gst_value_subtract (&dest, &src1, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* double <-> double_range + */ + + /* would yield an empty set */ + g_value_init (&src1, G_TYPE_DOUBLE); + g_value_set_double (&src1, 10.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 0.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, we cannot create open ranges + * so the result is the range again */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 0.0); + fail_unless (gst_value_get_double_range_max (&dest) == 20.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, G_TYPE_DOUBLE); + g_value_set_double (&src1, 10.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should keep same range as + * we don't have open ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 10.0); + fail_unless (gst_value_get_double_range_max (&dest) == 20.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 2, empty set */ + g_value_init (&src1, G_TYPE_DOUBLE); + g_value_set_double (&src1, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should keep same range as + * we don't have open ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 10.0); + fail_unless (gst_value_get_double_range_max (&dest) == 20.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 3, valid set */ + g_value_init (&src1, G_TYPE_DOUBLE); + g_value_set_double (&src1, 0.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_HOLDS_DOUBLE (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* and the other way around, should keep the range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 10.0); + fail_unless (gst_value_get_double_range_max (&dest) == 20.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* double_range <-> double_range + */ + + /* Check equality */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 15.0); + /* They are not equal (higher bound is different */ + fail_if (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL); + g_value_unset (&src1); + /* They are not equal (lower bound is different */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 5.0, 15.0); + fail_if (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL); + g_value_unset (&src1); + /* And finally check equality */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 15.0); + fail_unless (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL); + g_value_unset (&src1); + g_value_unset (&src2); + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* non overlapping ranges */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 30.0, 40.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 10.0); + fail_unless (gst_value_get_double_range_max (&dest) == 20.0); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 30.0); + fail_unless (gst_value_get_double_range_max (&dest) == 40.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 10.0, 30.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 20.0); + fail_unless (gst_value_get_double_range_max (&dest) == 30.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 20.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 15.0, 30.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 10.0); + fail_unless (gst_value_get_double_range_max (&dest) == 15.0); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE); + fail_unless (gst_value_get_double_range_min (&dest) == 20.0); + fail_unless (gst_value_get_double_range_max (&dest) == 30.0); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole { double_range, double_range } */ + g_value_init (&src1, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src1, 10.0, 30.0); + g_value_init (&src2, GST_TYPE_DOUBLE_RANGE); + gst_value_set_double_range (&src2, 15.0, 20.0); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_double_range_min (tmp) == 10.0); + fail_unless (gst_value_get_double_range_max (tmp) == 15.0); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_double_range_min (tmp) == 20.0); + fail_unless (gst_value_get_double_range_max (tmp) == 30.0); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); +} + +GST_END_TEST; + +/* Test arithmetic subtraction of fractions */ +GST_START_TEST (test_value_subtract_fraction) +{ + GValue result = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + + /* Subtract 1/4 from 1/2 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 1, 2); + gst_value_set_fraction (&src2, 1, 4); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 1); + fail_unless (gst_value_get_fraction_denominator (&result) == 4); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); + + /* Subtract 1/12 from 7/8 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 7, 8); + gst_value_set_fraction (&src2, 1, 12); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 19); + fail_unless (gst_value_get_fraction_denominator (&result) == 24); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); + + /* Subtract 12/13 from 4/3 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 4, 3); + gst_value_set_fraction (&src2, 12, 13); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 16); + fail_unless (gst_value_get_fraction_denominator (&result) == 39); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); + + /* Subtract 1/12 from 7/8 */ +} + +GST_END_TEST; + +/* Test set subtraction operations on fraction ranges */ +GST_START_TEST (test_value_subtract_fraction_range) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + GValue cmp = { 0 }; + const GValue *tmp; + gboolean ret; + + /* Value for tests */ + g_value_init (&cmp, GST_TYPE_FRACTION); + + /* fraction <-> fraction + */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION); + gst_value_set_fraction (&src2, 20, 1); + gst_value_set_fraction (&src1, 10, 1); + + /* subtract as in sets, result is 10 */ + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* same values, yields empty set */ + ret = gst_value_subtract (&dest, &src1, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* fraction <-> fraction_range + */ + + /* would yield an empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 0, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, we cannot create open ranges + * so the result is the range again */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 0, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should keep same range as + * we don't have open ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 2, valid set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 0, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* and the other way around, should keep the range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + fail_unless (gst_value_compare (&dest, &src2) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* fraction_range <-> fraction_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 20, 2); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 2, 20, 2); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* non overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 30, 2, 40, 2); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 5, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 30, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 30, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole { double_range, double_range } */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 30, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST); + /* 1st list entry */ + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + /* 2nd list entry */ + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + g_value_unset (&cmp); +} + +GST_END_TEST; + +/* Test set subtraction operations on fraction lists */ +GST_START_TEST (test_value_subtract_fraction_list) +{ + GValue list1 = { 0 }; + GValue list2 = { 0 }; + GValue val1 = { 0 }; + GValue val2 = { 0 }; + GValue tmp = { 0 }; + gboolean ret; + + g_value_init (&list1, GST_TYPE_LIST); + g_value_init (&val1, GST_TYPE_FRACTION); + gst_value_set_fraction (&val1, 15, 2); + gst_value_list_append_value (&list1, &val1); + g_value_init (&tmp, GST_TYPE_FRACTION); + gst_value_set_fraction (&tmp, 5, 1); + gst_value_list_append_value (&list1, &tmp); + g_value_unset (&tmp); + + g_value_init (&list2, GST_TYPE_LIST); + g_value_init (&val2, GST_TYPE_FRACTION); + gst_value_set_fraction (&val2, 15, 1); + gst_value_list_append_value (&list2, &val2); + g_value_init (&tmp, GST_TYPE_FRACTION); + gst_value_set_fraction (&tmp, 5, 1); + gst_value_list_append_value (&list2, &tmp); + g_value_unset (&tmp); + + /* should subtract all common elements */ + ret = gst_value_subtract (&tmp, &list1, &list2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&tmp, &val1) == GST_VALUE_EQUAL); + g_value_unset (&val1); + g_value_unset (&tmp); + + ret = gst_value_subtract (&tmp, &list2, &list1); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&tmp, &val2) == GST_VALUE_EQUAL); + g_value_unset (&val2); + g_value_unset (&tmp); + + g_value_unset (&list1); + g_value_unset (&list2); +} + +GST_END_TEST; + +GST_START_TEST (test_date) +{ + GstStructure *s; + GDate *date, *date2; + gchar *str; + + date = g_date_new_dmy (22, 9, 2005); + + s = gst_structure_new ("media/x-type", "SOME_DATE_TAG", G_TYPE_DATE, + date, NULL); + + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE)); + fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date2)); + fail_unless (date2 != NULL); + fail_unless (g_date_valid (date2)); + fail_unless (g_date_compare (date, date2) == 0); + + g_date_free (date); + g_date_free (date2); + date = NULL; + date2 = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless (g_str_equal (str, + "media/x-type, SOME_DATE_TAG=(date)2005-09-22;")); + + s = gst_structure_from_string (str, NULL); + g_free (str); + str = NULL; + + fail_unless (s != NULL); + fail_unless (gst_structure_has_name (s, "media/x-type")); + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE)); + fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date)); + fail_unless (date != NULL); + fail_unless (g_date_valid (date)); + fail_unless (g_date_get_day (date) == 22); + fail_unless (g_date_get_month (date) == 9); + fail_unless (g_date_get_year (date) == 2005); + g_date_free (date); + date = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless (g_str_equal (str, + "media/x-type, SOME_DATE_TAG=(date)2005-09-22;")); + g_free (str); + str = NULL; +} + +GST_END_TEST; + +static gboolean +date_time_equal (GstDateTime * a, GstDateTime * b) +{ + if (gst_date_time_get_year (a) != gst_date_time_get_year (b) || + gst_date_time_get_month (a) != gst_date_time_get_month (b) || + gst_date_time_get_day (a) != gst_date_time_get_day (b)) + return FALSE; + + if (gst_date_time_get_hour (a) != gst_date_time_get_hour (b) || + gst_date_time_get_minute (a) != gst_date_time_get_minute (b) || + gst_date_time_get_second (a) != gst_date_time_get_second (b) || + gst_date_time_get_microsecond (a) != gst_date_time_get_microsecond (b)) + return FALSE; + + if (gst_date_time_get_time_zone_offset (a) != + gst_date_time_get_time_zone_offset (b)) + return FALSE; + + return TRUE; +} + +GST_START_TEST (test_date_time) +{ + GstStructure *s; + GstDateTime *datetime, *datetime2; + GValue val = { 0, }; + gchar *str; + + /* utc timezone */ + datetime = gst_date_time_new (0, 2010, 6, 23, 7, 40, 10); + + s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME, datetime, NULL); + + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime2)); + fail_unless (datetime2 != NULL); + fail_unless (date_time_equal (datetime, datetime2)); + + gst_date_time_unref (datetime); + gst_date_time_unref (datetime2); + datetime = NULL; + datetime2 = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10Z;"); + + s = gst_structure_from_string (str, NULL); + g_free (str); + str = NULL; + + fail_unless (s != NULL); + fail_unless (gst_structure_has_name (s, "media/x-type")); + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime)); + fail_unless (datetime != NULL); + fail_unless (gst_date_time_get_year (datetime) == 2010); + fail_unless (gst_date_time_get_month (datetime) == 6); + fail_unless (gst_date_time_get_day (datetime) == 23); + fail_unless (gst_date_time_get_hour (datetime) == 7); + fail_unless (gst_date_time_get_minute (datetime) == 40); + fail_unless (gst_date_time_get_second (datetime) == 10); + fail_unless (gst_date_time_get_microsecond (datetime) == 0); + fail_unless (gst_date_time_get_time_zone_offset (datetime) == 0); + gst_date_time_unref (datetime); + datetime = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10Z;"); + g_free (str); + str = NULL; + + /* with timezone */ + datetime = gst_date_time_new (-3.0, 2010, 6, 23, 7, 40, 10.000001); + + s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME, datetime, NULL); + + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime2)); + fail_unless (datetime2 != NULL); + fail_unless (date_time_equal (datetime, datetime2)); + + gst_date_time_unref (datetime); + gst_date_time_unref (datetime2); + datetime = NULL; + datetime2 = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001-0300;"); + + s = gst_structure_from_string (str, NULL); + g_free (str); + str = NULL; + + fail_unless (s != NULL); + fail_unless (gst_structure_has_name (s, "media/x-type")); + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime)); + fail_unless (datetime != NULL); + fail_unless (gst_date_time_get_year (datetime) == 2010); + fail_unless (gst_date_time_get_month (datetime) == 6); + fail_unless (gst_date_time_get_day (datetime) == 23); + fail_unless (gst_date_time_get_hour (datetime) == 7); + fail_unless (gst_date_time_get_minute (datetime) == 40); + fail_unless (gst_date_time_get_second (datetime) == 10); + fail_unless (gst_date_time_get_microsecond (datetime) == 1); + fail_unless (gst_date_time_get_time_zone_offset (datetime) == -3); + gst_date_time_unref (datetime); + datetime = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001-0300;"); + + g_free (str); + str = NULL; + + /* with positive timezone */ + datetime = gst_date_time_new (2.0, 2010, 6, 23, 7, 40, 10.000001); + + s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME, datetime, NULL); + + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime2)); + fail_unless (datetime2 != NULL); + fail_unless (date_time_equal (datetime, datetime2)); + + gst_date_time_unref (datetime); + gst_date_time_unref (datetime2); + datetime = NULL; + datetime2 = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001+0200;"); + + s = gst_structure_from_string (str, NULL); + g_free (str); + str = NULL; + + fail_unless (s != NULL); + fail_unless (gst_structure_has_name (s, "media/x-type")); + fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG", + GST_TYPE_DATE_TIME)); + fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG", + &datetime)); + fail_unless (datetime != NULL); + fail_unless (gst_date_time_get_year (datetime) == 2010); + fail_unless (gst_date_time_get_month (datetime) == 6); + fail_unless (gst_date_time_get_day (datetime) == 23); + fail_unless (gst_date_time_get_hour (datetime) == 7); + fail_unless (gst_date_time_get_minute (datetime) == 40); + fail_unless (gst_date_time_get_second (datetime) == 10); + fail_unless (gst_date_time_get_microsecond (datetime) == 1); + fail_unless (gst_date_time_get_time_zone_offset (datetime) == 2); + gst_date_time_unref (datetime); + datetime = NULL; + + str = gst_structure_to_string (s); + gst_structure_free (s); + s = NULL; + fail_unless_equals_string (str, + "media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001+0200;"); + + g_free (str); + str = NULL; + + /* test partial dates */ + datetime = gst_date_time_new (0.0, 2010, -1, -1, -1, -1, -1.0); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "2010"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (gst_date_time_has_month (datetime)); + fail_if (gst_date_time_has_day (datetime)); + fail_if (gst_date_time_has_time (datetime)); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (0.0, 2010, 9, -1, -1, -1, -1.0); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "2010-09"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (gst_date_time_has_day (datetime)); + fail_if (gst_date_time_has_time (datetime)); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (0.0, 1983, 11, 30, -1, -1, -1.0); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "1983-11-30"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (!gst_date_time_has_day (datetime)); + fail_if (gst_date_time_has_time (datetime)); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (0.0, 1983, 11, 30, 3, 52, -1.0); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "1983-11-30T03:52Z"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (!gst_date_time_has_day (datetime)); + fail_if (!gst_date_time_has_time (datetime)); + fail_if (gst_date_time_has_second (datetime)); + fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), 0.0); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (-4.5, 1983, 11, 30, 3, 52, -1.0); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "1983-11-30T03:52-0430"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (!gst_date_time_has_day (datetime)); + fail_if (!gst_date_time_has_time (datetime)); + fail_if (gst_date_time_has_second (datetime)); + fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), + -4.5); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (4.5, 1983, 11, 30, 14, 52, 9); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "1983-11-30T14:52:09+0430"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (!gst_date_time_has_day (datetime)); + fail_if (!gst_date_time_has_time (datetime)); + fail_if (!gst_date_time_has_second (datetime)); + fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), 4.5); + g_value_unset (&val); + g_free (str); + + datetime = gst_date_time_new (-4.5, 1983, 11, 30, 14, 52, 9.702); + g_value_init (&val, GST_TYPE_DATE_TIME); + g_value_take_boxed (&val, datetime); + str = gst_value_serialize (&val); + g_value_reset (&val); + fail_unless_equals_string (str, "1983-11-30T14:52:09.702-0430"); + fail_unless (gst_value_deserialize (&val, str)); + datetime = g_value_get_boxed (&val); + fail_if (!gst_date_time_has_year (datetime)); + fail_if (!gst_date_time_has_month (datetime)); + fail_if (!gst_date_time_has_day (datetime)); + fail_if (!gst_date_time_has_time (datetime)); + fail_if (!gst_date_time_has_second (datetime)); + fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), + -4.5); + g_value_unset (&val); + g_free (str); +} + +GST_END_TEST; + +GST_START_TEST (test_fraction_range) +{ + GValue range = { 0, }; + GValue start = { 0, }; + GValue end = { 0, }; + GValue src = { 0, }; + GValue dest = { 0, }; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_FRACTION_RANGE); + g_value_init (&range2, GST_TYPE_FRACTION_RANGE); + g_value_init (&start, GST_TYPE_FRACTION); + g_value_init (&end, GST_TYPE_FRACTION); + g_value_init (&src, GST_TYPE_FRACTION); + + gst_value_set_fraction (&src, 1, 2); + + /* Check that a intersection of fraction & range = fraction */ + gst_value_set_fraction (&start, 1, 4); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range, &start, &end); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_fraction (&start, 1, 3); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + + gst_value_set_fraction_range (&range2, &start, &end); + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_fraction (&start, 4, 2); + gst_value_set_fraction (&end, 5, 2); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_deserialize_format_enum) +{ + GstStructure *s, *s2; + GstFormat foobar_fmt; + gchar *str, *str2, *end = NULL; + + /* make sure custom formats are serialised properly as well */ + foobar_fmt = gst_format_register ("foobar", "GST_FORMAT_FOOBAR"); + fail_unless (foobar_fmt != GST_FORMAT_UNDEFINED); + + s = gst_structure_new ("foo/bar", "format1", GST_TYPE_FORMAT, + GST_FORMAT_BYTES, "format2", GST_TYPE_FORMAT, GST_FORMAT_TIME, + "format3", GST_TYPE_FORMAT, GST_FORMAT_DEFAULT, "format4", + GST_TYPE_FORMAT, foobar_fmt, NULL); + + str = gst_structure_to_string (s); + GST_LOG ("Got structure string '%s'", GST_STR_NULL (str)); + fail_unless (str != NULL); + fail_unless (strstr (str, "TIME") != NULL); + fail_unless (strstr (str, "BYTE") != NULL); + fail_unless (strstr (str, "DEFAULT") != NULL); + fail_unless (strstr (str, "FOOBAR") != NULL); + + s2 = gst_structure_from_string (str, &end); + fail_unless (s2 != NULL); + + str2 = gst_structure_to_string (s2); + fail_unless (str2 != NULL); + + fail_unless (g_str_equal (str, str2)); + + g_free (str); + g_free (str2); + gst_structure_free (s); + gst_structure_free (s2); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_deserialize_value_array) +{ + GValue v = G_VALUE_INIT, v2 = G_VALUE_INIT, v3 = G_VALUE_INIT; + gchar *str = NULL; + + g_value_init (&v, GST_TYPE_ARRAY); + g_value_init (&v2, GST_TYPE_ARRAY); + g_value_init (&v3, G_TYPE_DOUBLE); + g_value_set_double (&v3, 1); + gst_value_array_append_value (&v2, &v3); + g_value_unset (&v3); + g_value_init (&v3, G_TYPE_DOUBLE); + g_value_set_double (&v3, 0); + gst_value_array_append_value (&v2, &v3); + g_value_unset (&v3); + gst_value_array_append_value (&v, &v2); + g_value_unset (&v2); + + str = gst_value_serialize (&v); + + g_value_init (&v2, GST_TYPE_ARRAY); + fail_unless (gst_value_deserialize (&v2, str)); + fail_unless (gst_value_compare (&v, &v2) == 0); + + g_value_unset (&v2); + g_value_unset (&v); + g_free (str); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_deserialize_caps) +{ + GValue value = { 0 } + , value2 = { + 0}; + GstCaps *caps, *caps2; + GstCaps *incaps; + gchar *serialized; + + incaps = gst_caps_new_simple ("caps/internal", + "in-field", G_TYPE_INT, 20, "in-field2", + G_TYPE_STRING, "some in ternal field", NULL); + caps = gst_caps_new_simple ("test/caps", + "foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test", + "int-caps", GST_TYPE_CAPS, incaps, NULL); + fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1); + gst_caps_unref (incaps); + + /* and assign caps to gvalue */ + g_value_init (&value, GST_TYPE_CAPS); + g_value_take_boxed (&value, caps); + fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1); + + /* now serialize it */ + serialized = gst_value_serialize (&value); + GST_DEBUG ("serialized caps to %s", serialized); + fail_unless (serialized != NULL); + + /* refcount should not change */ + fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1); + + /* now deserialize again */ + g_value_init (&value2, GST_TYPE_CAPS); + gst_value_deserialize (&value2, serialized); + + caps2 = g_value_get_boxed (&value2); + fail_if (GST_CAPS_REFCOUNT_VALUE (caps2) != 1); + + /* they should be equal */ + fail_unless (gst_caps_is_equal (caps, caps2)); + + /* cleanup */ + g_value_unset (&value); + g_value_unset (&value2); + g_free (serialized); +} + +GST_END_TEST; + +GST_START_TEST (test_int_range) +{ + GValue range = { 0, }; + GValue start = { 0, }; + GValue end = { 0, }; + GValue src = { 0, }; + GValue dest = { 0, }; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_INT_RANGE); + g_value_init (&range2, GST_TYPE_INT_RANGE); + g_value_init (&start, G_TYPE_INT); + g_value_init (&end, G_TYPE_INT); + g_value_init (&src, G_TYPE_INT); + + g_value_set_int (&src, 2); + + /* Check that a intersection of int & range = int */ + gst_value_set_int_range (&range, 1, 5); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_int_range (&range2, 2, 3); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_int_range (&range2, 6, 7); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + gst_value_set_int_range (&range, -7, -6); + fail_unless_equals_int (gst_value_get_int_range_min (&range), -7); + fail_unless_equals_int (gst_value_get_int_range_max (&range), -6); + gst_value_set_int_range (&range, -7, 7); + fail_unless_equals_int (gst_value_get_int_range_min (&range), -7); + fail_unless_equals_int (gst_value_get_int_range_max (&range), 7); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + +GST_START_TEST (test_int64_range) +{ + GValue range = { 0, }; + GValue start = { 0, }; + GValue end = { 0, }; + GValue src = { 0, }; + GValue dest = { 0, }; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_INT64_RANGE); + g_value_init (&range2, GST_TYPE_INT64_RANGE); + g_value_init (&start, G_TYPE_INT64); + g_value_init (&end, G_TYPE_INT64); + g_value_init (&src, G_TYPE_INT64); + + g_value_set_int64 (&src, 2); + + /* Check that a intersection of int64 & range = int64 */ + gst_value_set_int64_range (&range, 1, 5); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT64); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_int64_range (&range2, 2, 3); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_int64_range (&range2, 6, 7); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_int64_range) +{ + int i = 0; + + gint64 int64_ranges[] = { + 0, 5, + 0, G_MAXINT, + 5, G_MAXINT32, + 5, G_MAXINT64, + }; + gint int64_ranges_size = sizeof (int64_ranges) / sizeof (int64_ranges[0]) / 2; + + gchar *int64_range_strings[] = { + g_strdup ("[ 0, 5 ]"), + g_strdup_printf ("[ 0, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT), + g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT32), + g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", G_MAXINT64), + }; + gint int64_range_strings_size = + sizeof (int64_range_strings) / sizeof (int64_range_strings[0]); + + fail_unless (int64_ranges_size == int64_range_strings_size); + + while (i + 1 < (int64_ranges_size * 2)) { + if ((i + 1) % 2) { + gchar *str; + gchar *str2; + GValue value = { 0 }; + const GValue *deserialized_value; + int idx = i / 2; + GstStructure *s; + + g_value_init (&value, GST_TYPE_INT64_RANGE); + + /* check serialization */ + gst_value_set_int64_range (&value, int64_ranges[i], int64_ranges[i + 1]); + str = gst_value_serialize (&value); + fail_unless (strcmp (str, int64_range_strings[idx]) == 0); + g_free (int64_range_strings[idx]); + g_value_unset (&value); + + /* now deserialize again to an int64 range */ + s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE, + int64_ranges[i], int64_ranges[i + 1], NULL); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE); + str2 = gst_value_serialize (deserialized_value); + + fail_unless (gst_value_get_int64_range_min (deserialized_value) == + int64_ranges[i]); + fail_unless (gst_value_get_int64_range_max (deserialized_value) == + int64_ranges[i + 1]); + + gst_structure_free (s); + g_free (str); + g_free (str2); + } + i++; + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_int_range) +{ + GstStructure *s; + gchar *str, *str2; + gchar *end = NULL; + const GValue *deserialized_value; + + /* check a valid int_range deserialization */ + str = g_strdup_printf ("foo/bar, range=[ 1, %d ];", G_MAXINT); + s = gst_structure_from_string (str, &end); + fail_unless (*end == '\0'); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (deserialized_value) == TRUE); + fail_unless (gst_value_get_int_range_min (deserialized_value) == 1); + fail_unless (gst_value_get_int_range_max (deserialized_value) == G_MAXINT); + gst_structure_free (s); + end = NULL; + g_free (str); + + /* check invalid int_range deserialization */ + str = + g_strdup_printf ("foo/bar, range=[ 1, %" G_GINT64_FORMAT " ];", + (gint64) G_MAXINT + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, &end)); + g_free (str); + gst_structure_free (s); + str = + g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %" + G_GINT64_FORMAT " ];", (gint64) G_MAXINT, (gint64) G_MAXINT + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL)); + end = NULL; + g_free (str); + gst_structure_free (s); + + /* check a valid int64_range deserialization. Those ranges need to + * be explicit about their storage type. */ + str = g_strdup_printf ("foo/bar, range=(gint64)[ 1, %d ];", G_MAXINT); + s = gst_structure_from_string (str, &end); + fail_unless (*end == '\0'); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE); + fail_unless (gst_value_get_int64_range_min (deserialized_value) == 1); + fail_unless (gst_value_get_int64_range_max (deserialized_value) == G_MAXINT); + str2 = gst_structure_to_string (s); + fail_unless (strcmp (str, str2) == 0); + gst_structure_free (s); + end = NULL; + g_free (str); + g_free (str2); + + /* check invalid int64_range (starting with a gint) deserialization */ + str = + g_strdup_printf ("foo/bar, range=(gint64)[ 1, %" G_GUINT64_FORMAT " ];", + (guint64) G_MAXINT64 + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, &end)); + fail_unless (*end == '\0'); + gst_structure_free (s); + end = NULL; + g_free (str); + + /* check invalid int64_range deserialization into a int64_range */ + str = + g_strdup_printf ("foo/bar, range=(gint64)[ %" G_GINT64_FORMAT ", %" + G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL)); + g_free (str); + gst_structure_free (s); + + /* check invalid int64_range deserialization into a int_range */ + str = + g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %" + G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1); + s = gst_structure_from_string (str, &end); + fail_unless (s == NULL); + fail_unless (end == NULL); + g_free (str); +} + +GST_END_TEST; + +GST_START_TEST (test_stepped_range_collection) +{ + GstStructure *s; + const GValue *v; + + s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT_RANGE, 8, 12, NULL); + fail_unless (s != NULL); + v = gst_structure_get_value (s, "range"); + fail_unless (v != NULL); + fail_unless (gst_value_get_int_range_min (v) == 8); + fail_unless (gst_value_get_int_range_max (v) == 12); + fail_unless (gst_value_get_int_range_step (v) == 1); + gst_structure_free (s); + + s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE, (gint64) 8, + (gint64) 12, NULL); + fail_unless (s != NULL); + v = gst_structure_get_value (s, "range"); + fail_unless (v != NULL); + fail_unless (gst_value_get_int64_range_min (v) == 8); + fail_unless (gst_value_get_int64_range_max (v) == 12); + fail_unless (gst_value_get_int64_range_step (v) == 1); + gst_structure_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_stepped_int_range_parsing) +{ + gchar *str; + guint n; + gchar *end = NULL; + GstStructure *s; + + static const gchar *good_ranges[] = { + "[0, 1, 1]", + "[-2, 2, 2]", + "[16, 4096, 16]", + }; + + static const gchar *bad_ranges[] = { + "[0, 1, -1]", + "[1, 2, 2]", + "[2, 3, 2]", + "[0, 0, 0]", + }; + + /* check we can parse good ranges */ + for (n = 0; n < G_N_ELEMENTS (good_ranges); ++n) { + str = g_strdup_printf ("foo/bar, range=%s", good_ranges[n]); + s = gst_structure_from_string (str, &end); + fail_unless (s != NULL); + fail_unless (*end == '\0'); + gst_structure_free (s); + g_free (str); + } + + /* check we cannot parse bad ranges */ + for (n = 0; n < G_N_ELEMENTS (bad_ranges); ++n) { + str = g_strdup_printf ("foo/bar, range=%s", bad_ranges[n]); + ASSERT_CRITICAL (s = gst_structure_from_string (str, &end)); + gst_structure_free (s); + g_free (str); + } +} + +GST_END_TEST; + +GST_START_TEST (test_stepped_int_range_ops) +{ + gchar *str1, *str2, *str3; + guint n; + GstStructure *s1, *s2, *s3; + const GValue *v1, *v2, *v3; + + static const struct + { + const gchar *set1; + const gchar *op; + const gchar *set2; + const gchar *result; + } ranges[] = { + { + "[16, 4096, 16]", "inter", "[100, 200, 10]", "160"}, { + "[16, 4096, 16]", "inter", "[100, 200, 100]", NULL}, { + "[16, 4096, 16]", "inter", "[0, 512, 256]", "[256, 512, 256]"}, { + "[16, 32, 16]", "union", "[32, 96, 16]", "[16, 96, 16]"}, { + "[16, 32, 16]", "union", "[48, 96, 16]", "[16, 96, 16]"}, { + "[112, 192, 16]", "union", "[48, 96, 16]", "[48, 192, 16]"}, { + "[16, 32, 16]", "union", "[64, 96, 16]", NULL}, { + "[112, 192, 16]", "union", "[48, 96, 8]", NULL}, { + "[10, 20, 5]", "union", "10", "[10, 20, 5]"}, { + "[10, 20, 5]", "union", "20", "[10, 20, 5]"}, { + "[10, 20, 5]", "union", "15", "[10, 20, 5]"}, { + "[10, 20, 5]", "union", "5", "[5, 20, 5]"}, { + "[10, 20, 5]", "union", "12", NULL}, { + "[10, 20, 5]", "union", "30", NULL}, { + "[10, 20, 5]", "union", "25", "[10, 25, 5]"},}; + + for (n = 0; n < G_N_ELEMENTS (ranges); ++n) { + gchar *end = NULL; + GValue dest = { 0 }; + gboolean ret; + + str1 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set1); + s1 = gst_structure_from_string (str1, &end); + fail_unless (s1 != NULL); + fail_unless (*end == '\0'); + v1 = gst_structure_get_value (s1, "range"); + fail_unless (v1 != NULL); + + str2 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set2); + s2 = gst_structure_from_string (str2, &end); + fail_unless (s2 != NULL); + fail_unless (*end == '\0'); + v2 = gst_structure_get_value (s2, "range"); + fail_unless (v2 != NULL); + + if (!strcmp (ranges[n].op, "inter")) { + ret = gst_value_intersect (&dest, v1, v2); + } else if (!strcmp (ranges[n].op, "union")) { + ret = gst_value_union (&dest, v1, v2); + } else { + fail_unless (FALSE); + ret = FALSE; + } + + if (ranges[n].result) { + fail_unless (ret); + } else { + fail_unless (!ret); + } + + if (ret) { + str3 = g_strdup_printf ("foo/bar, range=%s", ranges[n].result); + s3 = gst_structure_from_string (str3, &end); + fail_unless (s3 != NULL); + fail_unless (*end == '\0'); + v3 = gst_structure_get_value (s3, "range"); + fail_unless (v3 != NULL); + + if (gst_value_compare (&dest, v3) != GST_VALUE_EQUAL) { + GST_ERROR ("%s %s %s yielded %s, expected %s", str1, ranges[n].op, str2, + gst_value_serialize (&dest), gst_value_serialize (v3)); + fail_unless (FALSE); + } + + gst_structure_free (s3); + g_free (str3); + + g_value_unset (&dest); + } + + gst_structure_free (s2); + g_free (str2); + gst_structure_free (s1); + g_free (str1); + } +} + +GST_END_TEST; + +GST_START_TEST (test_structure_basic) +{ + GstStructure *s1, *s2; + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT; + + /* sanity test */ + s1 = gst_structure_from_string ("foo,bar=1", NULL); + g_value_init (&v1, GST_TYPE_STRUCTURE); + gst_value_set_structure (&v1, s1); + fail_unless (gst_structure_is_equal (s1, gst_value_get_structure (&v1))); + + s2 = gst_structure_copy (s1); + g_value_init (&v2, GST_TYPE_STRUCTURE); + gst_value_set_structure (&v2, s2); + + /* can do everything but subtract */ + fail_unless (gst_value_can_compare (&v1, &v2)); + fail_unless (gst_value_can_intersect (&v1, &v2)); + fail_unless (!gst_value_can_subtract (&v1, &v2)); + fail_unless (gst_value_can_union (&v1, &v2)); + + gst_structure_free (s1); + gst_structure_free (s2); + g_value_unset (&v1); + g_value_unset (&v2); +} + +GST_END_TEST; + +GST_START_TEST (test_structure_single_ops) +{ + static const struct + { + const gchar *str1; + gboolean is_fixed; + gboolean can_fixate; + } single_struct[] = { + { + "foo,bar=(int)1", TRUE, TRUE}, { + "foo,bar=(int)[1,2]", FALSE, TRUE},}; + gint i; + + for (i = 0; i < G_N_ELEMENTS (single_struct); i++) { + GstStructure *s1 = gst_structure_from_string (single_struct[i].str1, NULL); + GValue v1 = G_VALUE_INIT; + GValue v2 = G_VALUE_INIT; + + fail_unless (s1 != NULL); + + GST_DEBUG ("checking structure %" GST_PTR_FORMAT, s1); + + g_value_init (&v1, GST_TYPE_STRUCTURE); + gst_value_set_structure (&v1, s1); + + fail_unless (gst_value_is_fixed (&v1) == single_struct[i].is_fixed); + fail_unless (gst_value_fixate (&v2, &v1) == single_struct[i].can_fixate); + if (single_struct[i].can_fixate) + g_value_unset (&v2); + + g_value_unset (&v1); + gst_structure_free (s1); + } +} + +GST_END_TEST; + +GST_START_TEST (test_structure_ops) +{ + struct + { + const gchar *str1; + const gchar *str2; + const gchar *op; + gint ret; + GType str_type; + const gchar *str_result; + } comparisons[] = { + /* *INDENT-OFF* */ + {"foo,bar=(int)1", "foo,bar=(int)1", "compare", GST_VALUE_EQUAL, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)1", "is_subset", TRUE, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"}, + {"foo,bar=(int)1", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"}, + {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL}, + {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "is_subset", FALSE, 0, NULL}, + {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"}, + {"foo,bar=(int)[1,2]", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"}, + {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "compare", GST_VALUE_UNORDERED, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "is_subset", TRUE, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"}, + {"foo,bar=(int)1", "foo,bar=(int)[1,2]", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"}, + {"foo,bar=(int)1", "foo,bar=(int)2", "compare", GST_VALUE_UNORDERED, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)2", "is_subset", FALSE, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)2", "intersect", FALSE, 0, NULL}, + {"foo,bar=(int)1", "foo,bar=(int)2", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"}, + {"foo,bar=(int)1", "baz,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL}, + {"foo,bar=(int)1", "baz,bar=(int)1", "is_subset", FALSE, 0, NULL}, + {"foo,bar=(int)1", "baz,bar=(int)1", "intersect", FALSE, 0, NULL}, +#if 0 + /* deserializing lists is not implemented (but this should still work!) */ + {"foo,bar=(int)1", "baz,bar=(int)1", "union", TRUE, G_TYPE_LIST, "{foo,bar=(int)1;, baz,bar=(int)1;}"}, +#endif + /* *INDENT-ON* */ + }; + gint i; + + for (i = 0; i < G_N_ELEMENTS (comparisons); i++) { + GstStructure *s1 = gst_structure_from_string (comparisons[i].str1, NULL); + GstStructure *s2 = gst_structure_from_string (comparisons[i].str2, NULL); + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT, v3 = G_VALUE_INIT; + + fail_unless (s1 != NULL); + fail_unless (s2 != NULL); + + GST_DEBUG ("checking %s with structure1 %" GST_PTR_FORMAT " structure2 %" + GST_PTR_FORMAT " is %d, %s", comparisons[i].op, s1, s2, + comparisons[i].ret, comparisons[i].str_result); + + g_value_init (&v1, GST_TYPE_STRUCTURE); + gst_value_set_structure (&v1, s1); + g_value_init (&v2, GST_TYPE_STRUCTURE); + gst_value_set_structure (&v2, s2); + + if (g_strcmp0 (comparisons[i].op, "compare") == 0) { + fail_unless (gst_value_compare (&v1, &v2) == comparisons[i].ret); + } else if (g_strcmp0 (comparisons[i].op, "is_subset") == 0) { + fail_unless (gst_value_is_subset (&v1, &v2) == comparisons[i].ret); + } else { + if (g_strcmp0 (comparisons[i].op, "intersect") == 0) { + fail_unless (gst_value_intersect (&v3, &v1, &v2) == comparisons[i].ret); + } else if (g_strcmp0 (comparisons[i].op, "union") == 0) { + fail_unless (gst_value_union (&v3, &v1, &v2) == comparisons[i].ret); + } + if (comparisons[i].ret) { + GValue result = G_VALUE_INIT; + gchar *str; + + str = gst_value_serialize (&v3); + GST_LOG ("result %s", str); + g_free (str); + + g_value_init (&result, comparisons[i].str_type); + fail_unless (gst_value_deserialize (&result, + comparisons[i].str_result)); + fail_unless (gst_value_compare (&result, &v3) == GST_VALUE_EQUAL); + g_value_unset (&v3); + g_value_unset (&result); + } + } + + gst_structure_free (s1); + gst_structure_free (s2); + g_value_unset (&v1); + g_value_unset (&v2); + } +} + +GST_END_TEST; + +static void +setup_test_value_array (GValue * value) +{ + GValueArray *array; + GValue v = G_VALUE_INIT; + + g_value_init (&v, G_TYPE_INT); + g_value_init (value, G_TYPE_VALUE_ARRAY); + + array = g_value_array_new (3); + g_value_set_int (&v, 1); + g_value_array_append (array, &v); + g_value_set_int (&v, 2); + g_value_array_append (array, &v); + g_value_set_int (&v, 3); + g_value_array_append (array, &v); + + g_value_take_boxed (value, array); +} + +static void +test_revert_array_transform (GValue * v1, GValue * v2) +{ + GValueArray *array; + + g_value_reset (v1); + + fail_unless (g_value_transform (v2, v1)); + array = g_value_get_boxed (v1); + fail_unless (array->n_values == 3); + fail_unless (g_value_get_int (g_value_array_get_nth (array, 0)) == 1); + fail_unless (g_value_get_int (g_value_array_get_nth (array, 1)) == 2); + fail_unless (g_value_get_int (g_value_array_get_nth (array, 2)) == 3); +} + +GST_START_TEST (test_transform_array) +{ + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT; + + setup_test_value_array (&v1); + + g_value_init (&v2, GST_TYPE_ARRAY); + + fail_unless (g_value_transform (&v1, &v2)); + fail_unless (gst_value_array_get_size (&v2) == 3); + fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 0)) == 1); + fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 1)) == 2); + fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 2)) == 3); + + test_revert_array_transform (&v1, &v2); + + g_value_unset (&v1); + g_value_unset (&v2); +} + +GST_END_TEST; + +GST_START_TEST (test_transform_list) +{ + GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT; + + setup_test_value_array (&v1); + + g_value_init (&v2, GST_TYPE_LIST); + + fail_unless (g_value_transform (&v1, &v2)); + fail_unless (gst_value_list_get_size (&v2) == 3); + fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 0)) == 1); + fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 1)) == 2); + fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 2)) == 3); + + test_revert_array_transform (&v1, &v2); + + g_value_unset (&v1); + g_value_unset (&v2); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_null_aray) +{ + gchar *serialized; + GValue v = G_VALUE_INIT; + + g_value_init (&v, G_TYPE_VALUE_ARRAY); + + g_value_set_boxed (&v, NULL); + serialized = gst_value_serialize (&v); + fail_unless_equals_string (serialized, "< >"); + g_value_unset (&v); + g_free (serialized); +} + +GST_END_TEST; + +static Suite * +gst_value_suite (void) +{ + Suite *s = suite_create ("GstValue"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_deserialize_buffer); + tcase_add_test (tc_chain, test_serialize_buffer); + tcase_add_test (tc_chain, test_deserialize_gint); + tcase_add_test (tc_chain, test_deserialize_gint_failures); + tcase_add_test (tc_chain, test_deserialize_guint); + tcase_add_test (tc_chain, test_deserialize_guint_failures); + tcase_add_test (tc_chain, test_deserialize_gint64); + tcase_add_test (tc_chain, test_deserialize_guint64); + tcase_add_test (tc_chain, test_deserialize_guchar); + tcase_add_test (tc_chain, test_deserialize_gstfraction); + tcase_add_test (tc_chain, test_deserialize_gtype); + tcase_add_test (tc_chain, test_deserialize_gtype_failures); + tcase_add_test (tc_chain, test_deserialize_bitmask); + tcase_add_test (tc_chain, test_serialize_flags); + tcase_add_test (tc_chain, test_deserialize_flags); + tcase_add_test (tc_chain, test_serialize_deserialize_format_enum); + tcase_add_test (tc_chain, test_serialize_deserialize_value_array); + tcase_add_test (tc_chain, test_string); + tcase_add_test (tc_chain, test_deserialize_string); + tcase_add_test (tc_chain, test_value_compare); + tcase_add_test (tc_chain, test_value_intersect); + tcase_add_test (tc_chain, test_value_subtract_int); + tcase_add_test (tc_chain, test_value_subtract_int64); + tcase_add_test (tc_chain, test_value_subtract_double); + tcase_add_test (tc_chain, test_value_subtract_fraction); + tcase_add_test (tc_chain, test_value_subtract_fraction_range); + tcase_add_test (tc_chain, test_value_subtract_fraction_list); + tcase_add_test (tc_chain, test_date); + tcase_add_test (tc_chain, test_date_time); + tcase_add_test (tc_chain, test_fraction_range); + tcase_add_test (tc_chain, test_serialize_deserialize_caps); + tcase_add_test (tc_chain, test_int_range); + tcase_add_test (tc_chain, test_int64_range); + tcase_add_test (tc_chain, test_serialize_int64_range); + tcase_add_test (tc_chain, test_deserialize_int_range); + tcase_add_test (tc_chain, test_stepped_range_collection); + tcase_add_test (tc_chain, test_stepped_int_range_parsing); + tcase_add_test (tc_chain, test_stepped_int_range_ops); + tcase_add_test (tc_chain, test_flagset); + tcase_add_test (tc_chain, test_structure_basic); + tcase_add_test (tc_chain, test_structure_single_ops); + tcase_add_test (tc_chain, test_structure_ops); + tcase_add_test (tc_chain, test_transform_array); + tcase_add_test (tc_chain, test_transform_list); + tcase_add_test (tc_chain, test_serialize_null_aray); + + return s; +} + +GST_CHECK_MAIN (gst_value); diff --git a/tests/check/gst/struct_arm.h b/tests/check/gst/struct_arm.h new file mode 100644 index 0000000..3f7be8a --- /dev/null +++ b/tests/check/gst/struct_arm.h @@ -0,0 +1,67 @@ + +GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 32}, + {"GstAllocator", sizeof (GstAllocator), 112}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 116}, + {"GstBinClass", sizeof (GstBinClass), 292}, + {"GstBin", sizeof (GstBin), 248}, + {"GstBuffer", sizeof (GstBuffer), 80}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 48}, + {"GstBufferPool", sizeof (GstBufferPool), 88}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 144}, + {"GstBusClass", sizeof (GstBusClass), 116}, + {"GstBus", sizeof (GstBus), 88}, + {"GstCaps", sizeof (GstCaps), 36}, + {"GstClockClass", sizeof (GstClockClass), 132}, + {"GstClockEntry", sizeof (GstClockEntry), 72}, + {"GstClock", sizeof (GstClock), 88}, + {"GstControlBinding", sizeof (GstControlBinding), 96}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 124}, + {"GstControlSource", sizeof (GstControlSource), 88}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 108}, + {"GstDebugCategory", sizeof (GstDebugCategory), 16}, + {"GstElementClass", sizeof (GstElementClass), 248}, + {"GstElement", sizeof (GstElement), 184}, + {"GstEvent", sizeof (GstEvent), 56}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 16}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 136}, + {"GstGhostPad", sizeof (GstGhostPad), 320}, + {"GstIterator", sizeof (GstIterator), 60}, + {"GstMemory", sizeof (GstMemory), 60}, + {"GstMapInfo", sizeof (GstMapInfo), 52}, + {"GstMessage", sizeof (GstMessage), 80}, + {"GstMeta", sizeof (GstMeta), 8}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 12}, + {"GstMiniObject", sizeof (GstMiniObject), 36}, + {"GstObjectClass", sizeof (GstObjectClass), 92}, + {"GstObject", sizeof (GstObject), 64}, + {"GstPadClass", sizeof (GstPadClass), 116}, + {"GstPad", sizeof (GstPad), 304}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 48}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 112}, + {"GstPadTemplate", sizeof (GstPadTemplate), 96}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 64}, + {"GstPipelineClass", sizeof (GstPipelineClass), 308}, + {"GstPipeline", sizeof (GstPipeline), 296}, + {"GstPluginDesc", sizeof (GstPluginDesc), 60}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 120}, + {"GstProxyPad", sizeof (GstProxyPad), 312}, + {"GstQuery", sizeof (GstQuery), 40}, + {"GstRegistryClass", sizeof (GstRegistryClass), 92}, + {"GstRegistry", sizeof (GstRegistry), 72}, + {"GstSegment", sizeof (GstSegment), 104}, + {"GstStaticCaps", sizeof (GstStaticCaps), 24}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 36}, + {"GstStructure", sizeof (GstStructure), 8}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 148}, + {"GstSystemClock", sizeof (GstSystemClock), 112}, + {"GstTagList", sizeof (GstTagList), 36}, + {"GstTaskClass", sizeof (GstTaskClass), 112}, + {"GstTask", sizeof (GstTask), 128}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 124}, + {"GstTaskPool", sizeof (GstTaskPool), 88}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 32}, + {"GstValueTable", sizeof (GstValueTable), 32}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_hppa.h b/tests/check/gst/struct_hppa.h new file mode 100644 index 0000000..2708df0 --- /dev/null +++ b/tests/check/gst/struct_hppa.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 64}, + {"GstAllocator", sizeof (GstAllocator), 176}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 232}, + {"GstBinClass", sizeof (GstBinClass), 576}, + {"GstBin", sizeof (GstBin), 376}, + {"GstBuffer", sizeof (GstBuffer), 112}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 64}, + {"GstBufferPool", sizeof (GstBufferPool), 136}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 288}, + {"GstBusClass", sizeof (GstBusClass), 232}, + {"GstBus", sizeof (GstBus), 128}, + {"GstCaps", sizeof (GstCaps), 64}, + {"GstClockClass", sizeof (GstClockClass), 264}, + {"GstClockEntry", sizeof (GstClockEntry), 112}, + {"GstClock", sizeof (GstClock), 128}, + {"GstControlBinding", sizeof (GstControlBinding), 152}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 248}, + {"GstControlSource", sizeof (GstControlSource), 136}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 216}, + {"GstDebugCategory", sizeof (GstDebugCategory), 24}, + {"GstElementClass", sizeof (GstElementClass), 488}, + {"GstElement", sizeof (GstElement), 264}, + {"GstEvent", sizeof (GstEvent), 88}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 32}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 272}, + {"GstGhostPad", sizeof (GstGhostPad), 536}, + {"GstIterator", sizeof (GstIterator), 120}, + {"GstMemory", sizeof (GstMemory), 112}, + {"GstMapInfo", sizeof (GstMapInfo), 104}, + {"GstMessage", sizeof (GstMessage), 120}, + {"GstMeta", sizeof (GstMeta), 16}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 24}, + {"GstMiniObject", sizeof (GstMiniObject), 64}, + {"GstObjectClass", sizeof (GstObjectClass), 184}, + {"GstObject", sizeof (GstObject), 88}, + {"GstPadClass", sizeof (GstPadClass), 232}, + {"GstPad", sizeof (GstPad), 520}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 72}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 224}, + {"GstPadTemplate", sizeof (GstPadTemplate), 144}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 96}, + {"GstPipelineClass", sizeof (GstPipelineClass), 608}, + {"GstPipeline", sizeof (GstPipeline), 440}, + {"GstPluginDesc", sizeof (GstPluginDesc), 112}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 240}, + {"GstProxyPad", sizeof (GstProxyPad), 528}, + {"GstQuery", sizeof (GstQuery), 72}, + {"GstRegistryClass", sizeof (GstRegistryClass), 184}, + {"GstRegistry", sizeof (GstRegistry), 96}, + {"GstSegment", sizeof (GstSegment), 120}, + {"GstStaticCaps", sizeof (GstStaticCaps), 48}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 64}, + {"GstStructure", sizeof (GstStructure), 16}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 296}, + {"GstSystemClock", sizeof (GstSystemClock), 168}, + {"GstTagList", sizeof (GstTagList), 64,}, + {"GstTaskClass", sizeof (GstTaskClass), 224}, + {"GstTask", sizeof (GstTask), 200}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 248}, + {"GstTaskPool", sizeof (GstTaskPool), 128}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 64}, + {"GstValueTable", sizeof (GstValueTable), 64}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_i386.h b/tests/check/gst/struct_i386.h new file mode 100644 index 0000000..015ee64 --- /dev/null +++ b/tests/check/gst/struct_i386.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 32}, + {"GstAllocator", sizeof (GstAllocator), 100}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 116}, + {"GstBinClass", sizeof (GstBinClass), 292}, + {"GstBin", sizeof (GstBin), 232}, + {"GstBuffer", sizeof (GstBuffer), 80}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 40}, + {"GstBufferPool", sizeof (GstBufferPool), 80}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 144}, + {"GstBusClass", sizeof (GstBusClass), 116}, + {"GstBus", sizeof (GstBus), 76}, + {"GstCaps", sizeof (GstCaps), 36}, + {"GstClockClass", sizeof (GstClockClass), 132}, + {"GstClockEntry", sizeof (GstClockEntry), 68}, + {"GstClock", sizeof (GstClock), 76}, + {"GstControlBinding", sizeof (GstControlBinding), 88}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 124}, + {"GstControlSource", sizeof (GstControlSource), 80}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 108}, + {"GstDebugCategory", sizeof (GstDebugCategory), 16}, + {"GstElementClass", sizeof (GstElementClass), 248}, + {"GstElement", sizeof (GstElement), 172}, + {"GstEvent", sizeof (GstEvent), 52}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 16}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 136}, + {"GstGhostPad", sizeof (GstGhostPad), 296}, + {"GstIterator", sizeof (GstIterator), 60}, + {"GstMemory", sizeof (GstMemory), 60}, + {"GstMapInfo", sizeof (GstMapInfo), 52}, + {"GstMessage", sizeof (GstMessage), 76}, + {"GstMeta", sizeof (GstMeta), 8}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 12}, + {"GstMiniObject", sizeof (GstMiniObject), 36}, + {"GstObjectClass", sizeof (GstObjectClass), 92}, + {"GstObject", sizeof (GstObject), 56}, + {"GstPadClass", sizeof (GstPadClass), 116}, + {"GstPad", sizeof (GstPad), 288}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 40}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 112}, + {"GstPadTemplate", sizeof (GstPadTemplate), 88}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 64}, + {"GstPipelineClass", sizeof (GstPipelineClass), 308}, + {"GstPipeline", sizeof (GstPipeline), 272}, + {"GstPluginDesc", sizeof (GstPluginDesc), 60}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 120}, + {"GstProxyPad", sizeof (GstProxyPad), 292}, + {"GstQuery", sizeof (GstQuery), 40}, + {"GstRegistryClass", sizeof (GstRegistryClass), 92}, + {"GstRegistry", sizeof (GstRegistry), 60}, + {"GstSegment", sizeof (GstSegment), 96}, + {"GstStaticCaps", sizeof (GstStaticCaps), 24}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 36}, + {"GstStructure", sizeof (GstStructure), 8}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 148}, + {"GstSystemClock", sizeof (GstSystemClock), 96}, + {"GstTagList", sizeof (GstTagList), 36}, + {"GstTaskClass", sizeof (GstTaskClass), 112}, + {"GstTask", sizeof (GstTask), 116}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 124}, + {"GstTaskPool", sizeof (GstTaskPool), 76}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 32}, + {"GstValueTable", sizeof (GstValueTable), 32}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_i386w.h b/tests/check/gst/struct_i386w.h new file mode 100644 index 0000000..5d985ac --- /dev/null +++ b/tests/check/gst/struct_i386w.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 32}, + {"GstAllocator", sizeof (GstAllocator), 112}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 116}, + {"GstBinClass", sizeof (GstBinClass), 292}, + {"GstBin", sizeof (GstBin), 248}, + {"GstBuffer", sizeof (GstBuffer), 80}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 48}, + {"GstBufferPool", sizeof (GstBufferPool), 88}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 144}, + {"GstBusClass", sizeof (GstBusClass), 116}, + {"GstBus", sizeof (GstBus), 88}, + {"GstCaps", sizeof (GstCaps), 36}, + {"GstClockClass", sizeof (GstClockClass), 132}, + {"GstClockEntry", sizeof (GstClockEntry), 72}, + {"GstClock", sizeof (GstClock), 88}, + {"GstControlBinding", sizeof (GstControlBinding), 96}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 124}, + {"GstControlSource", sizeof (GstControlSource), 88}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 108}, + {"GstDebugCategory", sizeof (GstDebugCategory), 16}, + {"GstElementClass", sizeof (GstElementClass), 248}, + {"GstElement", sizeof (GstElement), 184}, + {"GstEvent", sizeof (GstEvent), 56}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 16}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 136}, + {"GstGhostPad", sizeof (GstGhostPad), 320}, + {"GstIterator", sizeof (GstIterator), 60}, + {"GstMemory", sizeof (GstMemory), 60}, + {"GstMapInfo", sizeof (GstMapInfo), 52}, + {"GstMessage", sizeof (GstMessage), 80}, + {"GstMeta", sizeof (GstMeta), 8}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 12}, + {"GstMiniObject", sizeof (GstMiniObject), 36}, + {"GstObjectClass", sizeof (GstObjectClass), 92}, + {"GstObject", sizeof (GstObject), 64}, + {"GstPadClass", sizeof (GstPadClass), 116}, + {"GstPad", sizeof (GstPad), 304}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 48}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 112}, + {"GstPadTemplate", sizeof (GstPadTemplate), 96}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 64}, + {"GstPipelineClass", sizeof (GstPipelineClass), 308}, + {"GstPipeline", sizeof (GstPipeline), 296}, + {"GstPluginDesc", sizeof (GstPluginDesc), 60}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 120}, + {"GstProxyPad", sizeof (GstProxyPad), 312}, + {"GstQuery", sizeof (GstQuery), 40}, + {"GstRegistryClass", sizeof (GstRegistryClass), 92}, + {"GstRegistry", sizeof (GstRegistry), 72}, + {"GstSegment", sizeof (GstSegment), 104}, + {"GstStaticCaps", sizeof (GstStaticCaps), 24}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 36}, + {"GstStructure", sizeof (GstStructure), 8}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 148}, + {"GstSystemClock", sizeof (GstSystemClock), 112}, + {"GstTagList", sizeof (GstTagList), 36}, + {"GstTaskClass", sizeof (GstTaskClass), 112}, + {"GstTask", sizeof (GstTask), 128}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 124}, + {"GstTaskPool", sizeof (GstTaskPool), 88}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 32}, + {"GstValueTable", sizeof (GstValueTable), 32}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_ppc32.h b/tests/check/gst/struct_ppc32.h new file mode 100644 index 0000000..5d985ac --- /dev/null +++ b/tests/check/gst/struct_ppc32.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 32}, + {"GstAllocator", sizeof (GstAllocator), 112}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 116}, + {"GstBinClass", sizeof (GstBinClass), 292}, + {"GstBin", sizeof (GstBin), 248}, + {"GstBuffer", sizeof (GstBuffer), 80}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 48}, + {"GstBufferPool", sizeof (GstBufferPool), 88}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 144}, + {"GstBusClass", sizeof (GstBusClass), 116}, + {"GstBus", sizeof (GstBus), 88}, + {"GstCaps", sizeof (GstCaps), 36}, + {"GstClockClass", sizeof (GstClockClass), 132}, + {"GstClockEntry", sizeof (GstClockEntry), 72}, + {"GstClock", sizeof (GstClock), 88}, + {"GstControlBinding", sizeof (GstControlBinding), 96}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 124}, + {"GstControlSource", sizeof (GstControlSource), 88}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 108}, + {"GstDebugCategory", sizeof (GstDebugCategory), 16}, + {"GstElementClass", sizeof (GstElementClass), 248}, + {"GstElement", sizeof (GstElement), 184}, + {"GstEvent", sizeof (GstEvent), 56}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 16}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 136}, + {"GstGhostPad", sizeof (GstGhostPad), 320}, + {"GstIterator", sizeof (GstIterator), 60}, + {"GstMemory", sizeof (GstMemory), 60}, + {"GstMapInfo", sizeof (GstMapInfo), 52}, + {"GstMessage", sizeof (GstMessage), 80}, + {"GstMeta", sizeof (GstMeta), 8}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 12}, + {"GstMiniObject", sizeof (GstMiniObject), 36}, + {"GstObjectClass", sizeof (GstObjectClass), 92}, + {"GstObject", sizeof (GstObject), 64}, + {"GstPadClass", sizeof (GstPadClass), 116}, + {"GstPad", sizeof (GstPad), 304}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 48}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 112}, + {"GstPadTemplate", sizeof (GstPadTemplate), 96}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 64}, + {"GstPipelineClass", sizeof (GstPipelineClass), 308}, + {"GstPipeline", sizeof (GstPipeline), 296}, + {"GstPluginDesc", sizeof (GstPluginDesc), 60}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 120}, + {"GstProxyPad", sizeof (GstProxyPad), 312}, + {"GstQuery", sizeof (GstQuery), 40}, + {"GstRegistryClass", sizeof (GstRegistryClass), 92}, + {"GstRegistry", sizeof (GstRegistry), 72}, + {"GstSegment", sizeof (GstSegment), 104}, + {"GstStaticCaps", sizeof (GstStaticCaps), 24}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 36}, + {"GstStructure", sizeof (GstStructure), 8}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 148}, + {"GstSystemClock", sizeof (GstSystemClock), 112}, + {"GstTagList", sizeof (GstTagList), 36}, + {"GstTaskClass", sizeof (GstTaskClass), 112}, + {"GstTask", sizeof (GstTask), 128}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 124}, + {"GstTaskPool", sizeof (GstTaskPool), 88}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 32}, + {"GstValueTable", sizeof (GstValueTable), 32}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_ppc64.h b/tests/check/gst/struct_ppc64.h new file mode 100644 index 0000000..2708df0 --- /dev/null +++ b/tests/check/gst/struct_ppc64.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 64}, + {"GstAllocator", sizeof (GstAllocator), 176}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 232}, + {"GstBinClass", sizeof (GstBinClass), 576}, + {"GstBin", sizeof (GstBin), 376}, + {"GstBuffer", sizeof (GstBuffer), 112}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 64}, + {"GstBufferPool", sizeof (GstBufferPool), 136}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 288}, + {"GstBusClass", sizeof (GstBusClass), 232}, + {"GstBus", sizeof (GstBus), 128}, + {"GstCaps", sizeof (GstCaps), 64}, + {"GstClockClass", sizeof (GstClockClass), 264}, + {"GstClockEntry", sizeof (GstClockEntry), 112}, + {"GstClock", sizeof (GstClock), 128}, + {"GstControlBinding", sizeof (GstControlBinding), 152}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 248}, + {"GstControlSource", sizeof (GstControlSource), 136}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 216}, + {"GstDebugCategory", sizeof (GstDebugCategory), 24}, + {"GstElementClass", sizeof (GstElementClass), 488}, + {"GstElement", sizeof (GstElement), 264}, + {"GstEvent", sizeof (GstEvent), 88}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 32}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 272}, + {"GstGhostPad", sizeof (GstGhostPad), 536}, + {"GstIterator", sizeof (GstIterator), 120}, + {"GstMemory", sizeof (GstMemory), 112}, + {"GstMapInfo", sizeof (GstMapInfo), 104}, + {"GstMessage", sizeof (GstMessage), 120}, + {"GstMeta", sizeof (GstMeta), 16}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 24}, + {"GstMiniObject", sizeof (GstMiniObject), 64}, + {"GstObjectClass", sizeof (GstObjectClass), 184}, + {"GstObject", sizeof (GstObject), 88}, + {"GstPadClass", sizeof (GstPadClass), 232}, + {"GstPad", sizeof (GstPad), 520}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 72}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 224}, + {"GstPadTemplate", sizeof (GstPadTemplate), 144}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 96}, + {"GstPipelineClass", sizeof (GstPipelineClass), 608}, + {"GstPipeline", sizeof (GstPipeline), 440}, + {"GstPluginDesc", sizeof (GstPluginDesc), 112}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 240}, + {"GstProxyPad", sizeof (GstProxyPad), 528}, + {"GstQuery", sizeof (GstQuery), 72}, + {"GstRegistryClass", sizeof (GstRegistryClass), 184}, + {"GstRegistry", sizeof (GstRegistry), 96}, + {"GstSegment", sizeof (GstSegment), 120}, + {"GstStaticCaps", sizeof (GstStaticCaps), 48}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 64}, + {"GstStructure", sizeof (GstStructure), 16}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 296}, + {"GstSystemClock", sizeof (GstSystemClock), 168}, + {"GstTagList", sizeof (GstTagList), 64,}, + {"GstTaskClass", sizeof (GstTaskClass), 224}, + {"GstTask", sizeof (GstTask), 200}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 248}, + {"GstTaskPool", sizeof (GstTaskPool), 128}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 64}, + {"GstValueTable", sizeof (GstValueTable), 64}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_sparc.h b/tests/check/gst/struct_sparc.h new file mode 100644 index 0000000..2708df0 --- /dev/null +++ b/tests/check/gst/struct_sparc.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 64}, + {"GstAllocator", sizeof (GstAllocator), 176}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 232}, + {"GstBinClass", sizeof (GstBinClass), 576}, + {"GstBin", sizeof (GstBin), 376}, + {"GstBuffer", sizeof (GstBuffer), 112}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 64}, + {"GstBufferPool", sizeof (GstBufferPool), 136}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 288}, + {"GstBusClass", sizeof (GstBusClass), 232}, + {"GstBus", sizeof (GstBus), 128}, + {"GstCaps", sizeof (GstCaps), 64}, + {"GstClockClass", sizeof (GstClockClass), 264}, + {"GstClockEntry", sizeof (GstClockEntry), 112}, + {"GstClock", sizeof (GstClock), 128}, + {"GstControlBinding", sizeof (GstControlBinding), 152}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 248}, + {"GstControlSource", sizeof (GstControlSource), 136}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 216}, + {"GstDebugCategory", sizeof (GstDebugCategory), 24}, + {"GstElementClass", sizeof (GstElementClass), 488}, + {"GstElement", sizeof (GstElement), 264}, + {"GstEvent", sizeof (GstEvent), 88}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 32}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 272}, + {"GstGhostPad", sizeof (GstGhostPad), 536}, + {"GstIterator", sizeof (GstIterator), 120}, + {"GstMemory", sizeof (GstMemory), 112}, + {"GstMapInfo", sizeof (GstMapInfo), 104}, + {"GstMessage", sizeof (GstMessage), 120}, + {"GstMeta", sizeof (GstMeta), 16}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 24}, + {"GstMiniObject", sizeof (GstMiniObject), 64}, + {"GstObjectClass", sizeof (GstObjectClass), 184}, + {"GstObject", sizeof (GstObject), 88}, + {"GstPadClass", sizeof (GstPadClass), 232}, + {"GstPad", sizeof (GstPad), 520}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 72}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 224}, + {"GstPadTemplate", sizeof (GstPadTemplate), 144}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 96}, + {"GstPipelineClass", sizeof (GstPipelineClass), 608}, + {"GstPipeline", sizeof (GstPipeline), 440}, + {"GstPluginDesc", sizeof (GstPluginDesc), 112}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 240}, + {"GstProxyPad", sizeof (GstProxyPad), 528}, + {"GstQuery", sizeof (GstQuery), 72}, + {"GstRegistryClass", sizeof (GstRegistryClass), 184}, + {"GstRegistry", sizeof (GstRegistry), 96}, + {"GstSegment", sizeof (GstSegment), 120}, + {"GstStaticCaps", sizeof (GstStaticCaps), 48}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 64}, + {"GstStructure", sizeof (GstStructure), 16}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 296}, + {"GstSystemClock", sizeof (GstSystemClock), 168}, + {"GstTagList", sizeof (GstTagList), 64,}, + {"GstTaskClass", sizeof (GstTaskClass), 224}, + {"GstTask", sizeof (GstTask), 200}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 248}, + {"GstTaskPool", sizeof (GstTaskPool), 128}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 64}, + {"GstValueTable", sizeof (GstValueTable), 64}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_x86_64.h b/tests/check/gst/struct_x86_64.h new file mode 100644 index 0000000..2708df0 --- /dev/null +++ b/tests/check/gst/struct_x86_64.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 64}, + {"GstAllocator", sizeof (GstAllocator), 176}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 232}, + {"GstBinClass", sizeof (GstBinClass), 576}, + {"GstBin", sizeof (GstBin), 376}, + {"GstBuffer", sizeof (GstBuffer), 112}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 64}, + {"GstBufferPool", sizeof (GstBufferPool), 136}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 288}, + {"GstBusClass", sizeof (GstBusClass), 232}, + {"GstBus", sizeof (GstBus), 128}, + {"GstCaps", sizeof (GstCaps), 64}, + {"GstClockClass", sizeof (GstClockClass), 264}, + {"GstClockEntry", sizeof (GstClockEntry), 112}, + {"GstClock", sizeof (GstClock), 128}, + {"GstControlBinding", sizeof (GstControlBinding), 152}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 248}, + {"GstControlSource", sizeof (GstControlSource), 136}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 216}, + {"GstDebugCategory", sizeof (GstDebugCategory), 24}, + {"GstElementClass", sizeof (GstElementClass), 488}, + {"GstElement", sizeof (GstElement), 264}, + {"GstEvent", sizeof (GstEvent), 88}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 32}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 272}, + {"GstGhostPad", sizeof (GstGhostPad), 536}, + {"GstIterator", sizeof (GstIterator), 120}, + {"GstMemory", sizeof (GstMemory), 112}, + {"GstMapInfo", sizeof (GstMapInfo), 104}, + {"GstMessage", sizeof (GstMessage), 120}, + {"GstMeta", sizeof (GstMeta), 16}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 24}, + {"GstMiniObject", sizeof (GstMiniObject), 64}, + {"GstObjectClass", sizeof (GstObjectClass), 184}, + {"GstObject", sizeof (GstObject), 88}, + {"GstPadClass", sizeof (GstPadClass), 232}, + {"GstPad", sizeof (GstPad), 520}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 72}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 224}, + {"GstPadTemplate", sizeof (GstPadTemplate), 144}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 96}, + {"GstPipelineClass", sizeof (GstPipelineClass), 608}, + {"GstPipeline", sizeof (GstPipeline), 440}, + {"GstPluginDesc", sizeof (GstPluginDesc), 112}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 240}, + {"GstProxyPad", sizeof (GstProxyPad), 528}, + {"GstQuery", sizeof (GstQuery), 72}, + {"GstRegistryClass", sizeof (GstRegistryClass), 184}, + {"GstRegistry", sizeof (GstRegistry), 96}, + {"GstSegment", sizeof (GstSegment), 120}, + {"GstStaticCaps", sizeof (GstStaticCaps), 48}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 64}, + {"GstStructure", sizeof (GstStructure), 16}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 296}, + {"GstSystemClock", sizeof (GstSystemClock), 168}, + {"GstTagList", sizeof (GstTagList), 64,}, + {"GstTaskClass", sizeof (GstTaskClass), 224}, + {"GstTask", sizeof (GstTask), 200}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 248}, + {"GstTaskPool", sizeof (GstTaskPool), 128}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 64}, + {"GstValueTable", sizeof (GstValueTable), 64}, + {NULL, 0, 0} +}; diff --git a/tests/check/gst/struct_x86_64w.h b/tests/check/gst/struct_x86_64w.h new file mode 100644 index 0000000..00c6405 --- /dev/null +++ b/tests/check/gst/struct_x86_64w.h @@ -0,0 +1,66 @@ +static GstCheckABIStruct list[] = { + {"GstAllocationParams", sizeof (GstAllocationParams), 64}, + {"GstAllocator", sizeof (GstAllocator), 176}, + {"GstAllocatorClass", sizeof (GstAllocatorClass), 232}, + {"GstBinClass", sizeof (GstBinClass), 576}, + {"GstBin", sizeof (GstBin), 376}, + {"GstBuffer", sizeof (GstBuffer), 112}, + {"GstBufferPoolAcquireParams", sizeof (GstBufferPoolAcquireParams), 64}, + {"GstBufferPool", sizeof (GstBufferPool), 136}, + {"GstBufferPoolClass", sizeof (GstBufferPoolClass), 288}, + {"GstBusClass", sizeof (GstBusClass), 232}, + {"GstBus", sizeof (GstBus), 128}, + {"GstCaps", sizeof (GstCaps), 64}, + {"GstClockClass", sizeof (GstClockClass), 264}, + {"GstClockEntry", sizeof (GstClockEntry), 112}, + {"GstClock", sizeof (GstClock), 128}, + {"GstControlBinding", sizeof (GstControlBinding), 152}, + {"GstControlBindingClass", sizeof (GstControlBindingClass), 248}, + {"GstControlSource", sizeof (GstControlSource), 136}, + {"GstControlSourceClass", sizeof (GstControlSourceClass), 216}, + {"GstDebugCategory", sizeof (GstDebugCategory), 24}, + {"GstElementClass", sizeof (GstElementClass), 488}, + {"GstElement", sizeof (GstElement), 264}, + {"GstEvent", sizeof (GstEvent), 88}, + {"GstFormatDefinition", sizeof (GstFormatDefinition), 32}, + {"GstGhostPadClass", sizeof (GstGhostPadClass), 272}, + {"GstGhostPad", sizeof (GstGhostPad), 528}, + {"GstIterator", sizeof (GstIterator), 120}, + {"GstMemory", sizeof (GstMemory), 112}, + {"GstMapInfo", sizeof (GstMapInfo), 104}, + {"GstMessage", sizeof (GstMessage), 120}, + {"GstMeta", sizeof (GstMeta), 16}, + {"GstMetaTransformCopy", sizeof (GstMetaTransformCopy), 24}, + {"GstMiniObject", sizeof (GstMiniObject), 64}, + {"GstObjectClass", sizeof (GstObjectClass), 184}, + {"GstObject", sizeof (GstObject), 88}, + {"GstPadClass", sizeof (GstPadClass), 232}, + {"GstPad", sizeof (GstPad), 512}, + {"GstPadProbeInfo", sizeof (GstPadProbeInfo), 64}, + {"GstPadTemplateClass", sizeof (GstPadTemplateClass), 224}, + {"GstPadTemplate", sizeof (GstPadTemplate), 144}, + {"GstParamSpecFraction", sizeof (GstParamSpecFraction), 96}, + {"GstPipelineClass", sizeof (GstPipelineClass), 608}, + {"GstPipeline", sizeof (GstPipeline), 440}, + {"GstPluginDesc", sizeof (GstPluginDesc), 112}, + {"GstProxyPadClass", sizeof (GstProxyPadClass), 240}, + {"GstProxyPad", sizeof (GstProxyPad), 520}, + {"GstQuery", sizeof (GstQuery), 72}, + {"GstRegistryClass", sizeof (GstRegistryClass), 184}, + {"GstRegistry", sizeof (GstRegistry), 96}, + {"GstSegment", sizeof (GstSegment), 120}, + {"GstStaticCaps", sizeof (GstStaticCaps), 48}, + {"GstStaticPadTemplate", sizeof (GstStaticPadTemplate), 64}, + {"GstStructure", sizeof (GstStructure), 16}, + {"GstSystemClockClass", sizeof (GstSystemClockClass), 296}, + {"GstSystemClock", sizeof (GstSystemClock), 168}, + {"GstTagList", sizeof (GstTagList), 64,}, + {"GstTaskClass", sizeof (GstTaskClass), 224}, + {"GstTask", sizeof (GstTask), 200}, + {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 248}, + {"GstTaskPool", sizeof (GstTaskPool), 128}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {"GstTypeFind", sizeof (GstTypeFind), 64}, + {"GstValueTable", sizeof (GstValueTable), 64}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/adapter.c b/tests/check/libs/adapter.c new file mode 100644 index 0000000..cedb966 --- /dev/null +++ b/tests/check/libs/adapter.c @@ -0,0 +1,1479 @@ +/* GStreamer + * + * unit test for adapter + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +/* does some implementation dependent checking that should + * also be optimal + */ + +/* + * Start peeking on an adapter with 1 buffer pushed. + */ +GST_START_TEST (test_peek1) +{ + GstAdapter *adapter; + GstBuffer *buffer; + guint avail; + GstMapInfo info; + const guint8 *data1, *data2, *idata; + + adapter = gst_adapter_new (); + fail_if (adapter == NULL); + + /* push single buffer in adapter */ + buffer = gst_buffer_new_and_alloc (512); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + idata = info.data; + gst_buffer_unmap (buffer, &info); + + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + /* available and available_fast should return the size of the + * buffer */ + avail = gst_adapter_available (adapter); + fail_if (avail != 512); + avail = gst_adapter_available_fast (adapter); + fail_if (avail != 512); + + /* should g_critical with NULL as result */ + ASSERT_CRITICAL (data1 = gst_adapter_map (adapter, 0)); + fail_if (data1 != NULL); + + /* should return NULL as result */ + data1 = gst_adapter_map (adapter, 513); + fail_if (data1 != NULL); + + /* this should work */ + data1 = gst_adapter_map (adapter, 512); + fail_if (data1 == NULL); + /* it should point to the buffer data as well */ + fail_if (data1 != idata); + gst_adapter_unmap (adapter); + + data2 = gst_adapter_map (adapter, 512); + fail_if (data2 == NULL); + /* second peek should return the same pointer */ + fail_if (data2 != data1); + gst_adapter_unmap (adapter); + + /* this should fail since we don't have that many bytes */ + ASSERT_CRITICAL (gst_adapter_flush (adapter, 513)); + + /* this should work fine */ + gst_adapter_flush (adapter, 10); + + /* see if we have 10 bytes less available */ + avail = gst_adapter_available (adapter); + fail_if (avail != 502); + avail = gst_adapter_available_fast (adapter); + fail_if (avail != 502); + + /* should return NULL as result */ + data2 = gst_adapter_map (adapter, 503); + fail_if (data2 != NULL); + + /* should work fine */ + data2 = gst_adapter_map (adapter, 502); + fail_if (data2 == NULL); + /* peek should return the same old pointer + 10 */ + fail_if (data2 != data1 + 10); + fail_if (data2 != (guint8 *) idata + 10); + gst_adapter_unmap (adapter); + + /* flush some more */ + gst_adapter_flush (adapter, 500); + + /* see if we have 2 bytes available */ + avail = gst_adapter_available (adapter); + fail_if (avail != 2); + avail = gst_adapter_available_fast (adapter); + fail_if (avail != 2); + + data2 = gst_adapter_map (adapter, 2); + fail_if (data2 == NULL); + fail_if (data2 != data1 + 510); + fail_if (data2 != (guint8 *) idata + 510); + gst_adapter_unmap (adapter); + + /* flush some more */ + gst_adapter_flush (adapter, 2); + + /* see if we have 0 bytes available */ + avail = gst_adapter_available (adapter); + fail_if (avail != 0); + avail = gst_adapter_available_fast (adapter); + fail_if (avail != 0); + + /* silly clear just for fun */ + gst_adapter_clear (adapter); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Start peeking on an adapter with 2 non-mergeable buffers + * pushed. + */ +GST_START_TEST (test_peek2) +{ +} + +GST_END_TEST; + +/* Start peeking on an adapter with 2 mergeable buffers + * pushed. + */ +GST_START_TEST (test_peek3) +{ +} + +GST_END_TEST; + +/* take data from an adapter with 1 buffer pushed. + */ +GST_START_TEST (test_take1) +{ + GstAdapter *adapter; + GstBuffer *buffer, *buffer2; + guint avail; + GstMapInfo info, info2; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 100); + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + /* take out buffer */ + buffer2 = gst_adapter_take_buffer (adapter, 100); + fail_unless (buffer2 != NULL); + + fail_unless (gst_buffer_map (buffer2, &info2, GST_MAP_READ)); + fail_unless (info2.data != NULL); + fail_unless (info2.size == 100); + + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + + /* the buffer should be the same */ + fail_unless (buffer == buffer2); + fail_unless (info.data == info2.data); + + gst_buffer_unmap (buffer, &info); + gst_buffer_unmap (buffer2, &info2); + + gst_buffer_unref (buffer2); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* take data from an adapter with 2 non-mergeable buffers + * pushed. + */ +GST_START_TEST (test_take2) +{ +} + +GST_END_TEST; + +/* take data from an adapter with 2 mergeable buffers + * pushed. + */ +GST_START_TEST (test_take3) +{ + GstAdapter *adapter; + GstBuffer *buffer, *buffer2; + guint avail; + GstMapInfo info, info2; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + fail_unless (info.data != NULL); + fail_unless (info.size == 100); + gst_buffer_unmap (buffer, &info); + + /* set up and push subbuffers */ + buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 25); + gst_adapter_push (adapter, buffer2); + buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 25, 25); + gst_adapter_push (adapter, buffer2); + buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 50, 25); + gst_adapter_push (adapter, buffer2); + buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 75, 25); + gst_adapter_push (adapter, buffer2); + + gst_buffer_unref (buffer); + + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + /* take out buffer */ + buffer2 = gst_adapter_take_buffer (adapter, 100); + fail_unless (buffer2 != NULL); + fail_unless (gst_buffer_map (buffer2, &info2, GST_MAP_READ)); + fail_unless (info2.data != NULL); + fail_unless (info2.size == 100); + + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + +#if 0 + /* the data should be the same FIXME, implement span in adapter again. */ + fail_unless (info.data == info2.data); +#endif + + gst_buffer_unmap (buffer2, &info2); + gst_buffer_unref (buffer2); + + g_object_unref (adapter); +} + +GST_END_TEST; + +static GstAdapter * +create_and_fill_adapter (void) +{ + GstAdapter *adapter; + gint i, j; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + for (i = 0; i < 10000; i += 4) { + GstBuffer *buf; + GstMapInfo info; + guint8 *ptr; + + buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4); + fail_unless (buf != NULL); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); + ptr = info.data; + + for (j = 0; j < 4; j++) { + GST_WRITE_UINT32_LE (ptr, i + j); + ptr += sizeof (guint32); + } + gst_buffer_unmap (buf, &info); + + gst_adapter_push (adapter, buf); + } + + return adapter; +} + +/* Fill a buffer with a sequence of 32 bit ints and read them back out, + * checking that they're still in the right order */ +GST_START_TEST (test_take_order) +{ + GstAdapter *adapter; + int i = 0; + + adapter = create_and_fill_adapter (); + while (gst_adapter_available (adapter) >= sizeof (guint32)) { + guint8 *data = gst_adapter_take (adapter, sizeof (guint32)); + guint32 val = GST_READ_UINT32_LE (data); + + GST_DEBUG ("val %8u", val); + fail_unless (val == i); + i++; + g_free (data); + } + fail_unless (gst_adapter_available (adapter) == 0, + "Data was left in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Fill a buffer with a sequence of 32 bit ints and read them back out + * using take_buffer, checking that they're still in the right order */ +GST_START_TEST (test_take_buf_order) +{ + GstAdapter *adapter; + int i = 0; + + adapter = create_and_fill_adapter (); + while (gst_adapter_available (adapter) >= sizeof (guint32)) { + GstBuffer *buf = gst_adapter_take_buffer (adapter, sizeof (guint32)); + GstMapInfo info; + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + fail_unless (GST_READ_UINT32_LE (info.data) == i); + gst_buffer_unmap (buf, &info); + + i++; + + gst_buffer_unref (buf); + } + fail_unless (gst_adapter_available (adapter) == 0, + "Data was left in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +GST_START_TEST (test_timestamp) +{ + GstAdapter *adapter; + GstBuffer *buffer; + guint avail; + GstClockTime timestamp; + guint64 dist; + guint8 *data; + const guint8 *cdata; + guint64 offset; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + /* timestamp is now undefined */ + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless (dist == 0); + + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* Offset should be undefined */ + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless (offset == GST_BUFFER_OFFSET_NONE); + fail_unless (dist == 0); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless (offset == GST_CLOCK_TIME_NONE); + + /* 0 bytes since discont */ + dist = gst_adapter_distance_from_discont (adapter); + fail_unless (dist == 0); + + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 50); + + /* still undefined, dist changed, though */ + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless (dist == 50); + + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* Offset still undefined */ + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless (offset == GST_BUFFER_OFFSET_NONE); + fail_unless (dist == 50); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless (offset == GST_CLOCK_TIME_NONE); + + /* 50 bytes since discont */ + dist = gst_adapter_distance_from_discont (adapter); + fail_unless (dist == 50); + + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + + /* timestamp is still undefined */ + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless (dist == 50); + + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* Offset still undefined */ + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless (offset == GST_BUFFER_OFFSET_NONE); + fail_unless (dist == 50); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless (offset == GST_CLOCK_TIME_NONE); + + /* 50 bytes since discont */ + dist = gst_adapter_distance_from_discont (adapter); + fail_unless (dist == 50); + + /* flush out first buffer we are now at the second buffer timestamp */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless (dist == 0); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* 100 bytes since discont */ + dist = gst_adapter_distance_from_discont (adapter); + fail_unless (dist == 100); + + /* move some more, still the same timestamp but further away */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 50); + + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless (dist == 50); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* push a buffer without timestamp in the adapter */ + buffer = gst_buffer_new_and_alloc (100); + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + /* push a buffer with timestamp in the adapter */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 250); + + /* timestamp still as it was before the push */ + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless (dist == 50); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* flush away buffer with the timestamp */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 200); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless (dist == 100); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* move into the second buffer */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless (dist == 150); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* move to third buffer we move to the new timestamp */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless (dist == 0); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* move everything out */ + gst_adapter_flush (adapter, 100); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless (dist == 100); + + /* clear everything */ + gst_adapter_clear (adapter); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless (dist == 0); + + /* timestamp was undefined at discont */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* push an empty buffer with timestamp in the adapter */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless (dist == 0); + + /* timestamp was undefined at discont (clearing the adapter is not + * necessarily a discont) */ + timestamp = gst_adapter_pts_at_discont (adapter); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + + /* push another empty buffer */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless (dist == 0); + + /* push a buffer with timestamp in the adapter */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless (dist == 0); + + gst_adapter_flush (adapter, 1); + avail = gst_adapter_available (adapter); + fail_unless (avail == 99); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 4 * GST_SECOND); + fail_unless (dist == 1); + + /* push an empty buffer with timestamp in the adapter */ + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 99); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 4 * GST_SECOND); + fail_unless (dist == 1); + + /* push buffer without timestamp */ + buffer = gst_buffer_new_and_alloc (100); + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 199); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 4 * GST_SECOND); + fail_unless (dist == 1); + + /* remove first buffer, timestamp of empty buffer is visible */ + buffer = gst_adapter_take_buffer (adapter, 99); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 99); + gst_buffer_unref (buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 5 * GST_SECOND); + fail_unless (dist == 0); + + /* remove empty buffer, timestamp still visible */ + cdata = gst_adapter_map (adapter, 50); + fail_unless (cdata != NULL); + gst_adapter_unmap (adapter); + + data = gst_adapter_take (adapter, 50); + fail_unless (data != NULL); + g_free (data); + avail = gst_adapter_available (adapter); + fail_unless (avail == 50); + timestamp = gst_adapter_prev_pts (adapter, &dist); + fail_unless (timestamp == 5 * GST_SECOND); + fail_unless (dist == 50); + + /* clearing to start a new test */ + gst_adapter_clear (adapter); + + buffer = gst_buffer_new_and_alloc (100); + + /* push the buffer without timestamp in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 100); + + /* timestamp is now undefined */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless_equals_int (dist, 0); + + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 50); + + /* still undefined, dist changed, though */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless_equals_int (dist, 50); + + /* alloc first buffer with timestamp */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 150); + + /* timestamp is still undefined at offset 0 */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless_equals_int (dist, 50); + + /* timestamp is still undefined at offset 50 */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 50, &dist); + fail_unless (timestamp == GST_CLOCK_TIME_NONE); + fail_unless_equals_int (dist, 100); + + /* timestamp is 1 second at offset 51 */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 51, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless_equals_int (dist, 1); + + /* timestamp is still 1 second at offset 100 */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 100, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless_equals_int (dist, 50); + + /* flush out the last 50 bytes of the buffer with undefined timestamp */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 100); + + /* alloc second buffer with timestamp */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 200); + + /* alloc third buffer with timestamp */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND; + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 300); + + /* alloc fourth buffer with timestamp */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND; + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 400); + + timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless_equals_int (dist, 0); + + timestamp = gst_adapter_prev_pts_at_offset (adapter, 100, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless_equals_int (dist, 100); + + timestamp = gst_adapter_prev_pts_at_offset (adapter, 200, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless_equals_int (dist, 100); + + timestamp = gst_adapter_prev_pts_at_offset (adapter, 300, &dist); + fail_unless (timestamp == 3 * GST_SECOND); + fail_unless_equals_int (dist, 100); + + timestamp = gst_adapter_prev_pts_at_offset (adapter, 400, &dist); + fail_unless (timestamp == 4 * GST_SECOND); + fail_unless_equals_int (dist, 100); + + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless_equals_int (avail, 350); + + /* We flushed 50 bytes, we are still on the first buffer */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist); + fail_unless (timestamp == 1 * GST_SECOND); + fail_unless_equals_int (dist, 50); + + /* As we flushed 50 bytes, offset 100 is on the second buffer */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 100, &dist); + fail_unless (timestamp == 2 * GST_SECOND); + fail_unless_equals_int (dist, 50); + + /* Third buffer */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 200, &dist); + fail_unless (timestamp == 3 * GST_SECOND); + fail_unless_equals_int (dist, 50); + + /* Fourth buffer */ + timestamp = gst_adapter_prev_pts_at_offset (adapter, 300, &dist); + fail_unless (timestamp == 4 * GST_SECOND); + fail_unless_equals_int (dist, 50); + + g_object_unref (adapter); +} + +GST_END_TEST; + +GST_START_TEST (test_offset) +{ + GstAdapter *adapter; + GstBuffer *buffer; + guint avail; + guint64 offset; + guint64 dist; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + /* Offset should be undefined */ + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 0); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + fail_unless_equals_int (dist, 0); + + /* Offset is undefined */ + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 50); + + /* Offset still undefined, dist changed though */ + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 50); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + fail_unless_equals_int (dist, 50); + + /* Offset is undefined */ + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + + /* Let's push in a discont buffer with a valid offset */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_OFFSET (buffer) = 10000; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + + /* push in the adapter */ + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + + /* offset is still undefined */ + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 50); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + fail_unless_equals_int (dist, 50); + + /* Offset is undefined */ + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + + /* flush out first buffer we are now at the second buffer offset */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 0); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 10000); + fail_unless_equals_int (dist, 0); + + /* Offset should be defined now */ + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* move some more, we should have an updated offset */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 50); + + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 50); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 10000); + fail_unless_equals_int (dist, 50); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* push a buffer without offset in the adapter (contiguous with the + other) */ + buffer = gst_buffer_new_and_alloc (100); + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + + /* push a buffer with offset in the adapter (but contiguous with the + other), the offset shouldn't be taken into account */ + buffer = gst_buffer_new_and_alloc (100); + GST_BUFFER_OFFSET (buffer) = 50000; + gst_adapter_push (adapter, buffer); + avail = gst_adapter_available (adapter); + fail_unless (avail == 250); + + /* offset still as it was before the push */ + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 50); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 10000); + fail_unless_equals_int (dist, 50); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* flush away buffer with the offset */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 200); + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 100); + /* The previous valid offset seen is now 100 bytes away */ + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 10000); + fail_unless_equals_int (dist, 100); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* move into the second buffer */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 150); + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 150); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 10000); + fail_unless_equals_int (dist, 150); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* move to third buffer, we should still see a continuously increasing + * offset and ignore the non-discont offset */ + gst_adapter_flush (adapter, 50); + avail = gst_adapter_available (adapter); + fail_unless (avail == 100); + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 200); + /* But the prev_offset *does* give us the actual buffer offset value */ + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 50000); + fail_unless_equals_int (dist, 0); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* move everything out, we end up at the last offset */ + gst_adapter_flush (adapter, 100); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 300); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, 50000); + fail_unless_equals_int (dist, 100); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, 10000); + + /* clear everything */ + gst_adapter_clear (adapter); + avail = gst_adapter_available (adapter); + fail_unless (avail == 0); + offset = gst_adapter_distance_from_discont (adapter); + fail_unless_equals_uint64 (offset, 0); + offset = gst_adapter_prev_offset (adapter, &dist); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + fail_unless_equals_int (dist, 0); + + offset = gst_adapter_offset_at_discont (adapter); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET_NONE); + + g_object_unref (adapter); +} + +GST_END_TEST; + +GST_START_TEST (test_scan) +{ + GstAdapter *adapter; + GstBuffer *buffer; + GstMapInfo info; + guint offset; + guint i; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + /* fill with pattern */ + for (i = 0; i < 100; i++) + ((guint8 *) info.data)[i] = i; + gst_buffer_unmap (buffer, &info); + + gst_adapter_push (adapter, buffer); + + /* find first bytes */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 100); + fail_unless (offset == 0); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 0, 100); + fail_unless (offset == 1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 99); + fail_unless (offset == 1); + /* offset is past the pattern start */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 2, 98); + fail_unless (offset == -1); + /* not enough bytes to find the pattern */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x02030405, 2, 3); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x02030405, 2, 4); + fail_unless (offset == 2); + /* size does not include the last scanned byte */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x40414243, 0, 0x41); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x40414243, 0, 0x43); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x40414243, 0, 0x44); + fail_unless (offset == 0x40); + /* past the start */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x40414243, 65, 10); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x40414243, 64, 5); + fail_unless (offset == 64); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x60616263, 65, 35); + fail_unless (offset == 0x60); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x60616263, 0x60, 4); + fail_unless (offset == 0x60); + /* past the start */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x60616263, 0x61, 3); + fail_unless (offset == -1); + + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x60616263, 99, 1); + fail_unless (offset == -1); + + /* add another buffer */ + buffer = gst_buffer_new_and_alloc (100); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_WRITE)); + /* fill with pattern */ + for (i = 0; i < 100; i++) + ((guint8 *) info.data)[i] = i + 100; + gst_buffer_unmap (buffer, &info); + + gst_adapter_push (adapter, buffer); + + /* past the start */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x60616263, 0x61, 6); + fail_unless (offset == -1); + /* this should work */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x61626364, 0x61, 4); + fail_unless (offset == 0x61); + /* not enough data */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x62636465, 0x61, 4); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x62636465, 0x61, 5); + fail_unless (offset == 0x62); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x62636465, 0, 120); + fail_unless (offset == 0x62); + + /* border conditions */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x62636465, 0, 200); + fail_unless (offset == 0x62); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x63646566, 0, 200); + fail_unless (offset == 0x63); + /* we completely searched the first list */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x64656667, 0, 200); + fail_unless (offset == 0x64); + /* skip first buffer */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x64656667, 0x64, + 100); + fail_unless (offset == 0x64); + /* past the start */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x64656667, 0x65, + 10); + fail_unless (offset == -1); + /* not enough data to scan */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x64656667, 0x63, 4); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x64656667, 0x63, 5); + fail_unless (offset == 0x64); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0, 199); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0x62, + 102); + fail_unless (offset == 0xc4); + /* different masks */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0x00ffffff, 0x00656667, 0x64, + 100); + fail_unless (offset == 0x64); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0x000000ff, 0x00000000, 0, 100); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0x000000ff, 0x00000003, 0, 100); + fail_unless (offset == 0); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0x000000ff, 0x00000061, 0x61, + 100); + fail_unless (offset == -1); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xff000000, 0x61000000, 0, 0x62); + fail_unless (offset == -1); + /* does not even exist */ + ASSERT_CRITICAL (offset = + gst_adapter_masked_scan_uint32 (adapter, 0x00ffffff, 0xffffffff, 0x65, + 99)); + fail_unless (offset == -1); + + /* flush some bytes */ + gst_adapter_flush (adapter, 0x20); + + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x20212223, 0, 100); + fail_unless (offset == 0); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x20212223, 0, 4); + fail_unless (offset == 0); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0x62, + 70); + fail_unless (offset == 0xa4); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0, 168); + fail_unless (offset == 0xa4); + + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 164, 4); + fail_unless (offset == 0xa4); + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0x44, + 100); + fail_unless (offset == 0xa4); + /* not enough bytes */ + offset = + gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0xc4c5c6c7, 0x44, + 99); + fail_unless (offset == -1); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Fill a buffer with a sequence of 32 bit ints and read them back out + * using take_buffer, checking that they're still in the right order */ +GST_START_TEST (test_take_list) +{ + GstAdapter *adapter; + int i = 0; + + adapter = create_and_fill_adapter (); + while (gst_adapter_available (adapter) >= sizeof (guint32)) { + GList *list, *walk; + GstBuffer *buf; + gsize left; + GstMapInfo info; + guint8 *ptr; + + list = gst_adapter_take_list (adapter, sizeof (guint32) * 5); + fail_unless (list != NULL); + + for (walk = list; walk; walk = g_list_next (walk)) { + buf = walk->data; + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + + ptr = info.data; + left = info.size; + + while (left > 0) { + fail_unless (GST_READ_UINT32_LE (ptr) == i); + i++; + ptr += sizeof (guint32); + left -= sizeof (guint32); + } + gst_buffer_unmap (buf, &info); + + gst_buffer_unref (buf); + } + g_list_free (list); + } + fail_unless (gst_adapter_available (adapter) == 0, + "Data was left in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Fill a buffer with a sequence of 32 bit ints and read a couple of front + * buffers using get_buffer, checking that they're still in the right order */ +GST_START_TEST (test_get_list) +{ + GstAdapter *adapter; + int i = 0; + gsize size = 0; + GList *list, *walk; + GstBuffer *buf; + gsize left; + GstMapInfo info; + guint8 *ptr; + + adapter = create_and_fill_adapter (); + size = gst_adapter_available (adapter); + + list = gst_adapter_get_list (adapter, sizeof (guint32) * 5); + fail_unless (list != NULL); + + for (walk = list; walk; walk = g_list_next (walk)) { + buf = walk->data; + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + + ptr = info.data; + left = info.size; + + while (left > 0) { + fail_unless (GST_READ_UINT32_LE (ptr) == i); + i++; + ptr += sizeof (guint32); + left -= sizeof (guint32); + } + gst_buffer_unmap (buf, &info); + + gst_buffer_unref (buf); + } + g_list_free (list); + + fail_unless (gst_adapter_available (adapter) == size, + "All data should remain in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Fill a buffer with a sequence of 32 bit ints and read them back out + * using take_buffer, checking that they're still in the right order */ +GST_START_TEST (test_take_buffer_list) +{ + GstAdapter *adapter; + int i = 0; + + adapter = create_and_fill_adapter (); + while (gst_adapter_available (adapter) >= sizeof (guint32)) { + GstBufferList *buffer_list; + GstBuffer *buf; + gsize left; + GstMapInfo info; + guint8 *ptr; + guint n, num; + + buffer_list = gst_adapter_take_buffer_list (adapter, sizeof (guint32) * 5); + fail_unless (buffer_list != NULL); + num = gst_buffer_list_length (buffer_list); + fail_unless (num > 0); + + for (n = 0; n < num; ++n) { + buf = gst_buffer_list_get (buffer_list, n); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + + ptr = info.data; + left = info.size; + + while (left > 0) { + fail_unless (GST_READ_UINT32_LE (ptr) == i); + i++; + ptr += sizeof (guint32); + left -= sizeof (guint32); + } + gst_buffer_unmap (buf, &info); + } + gst_buffer_list_unref (buffer_list); + } + fail_unless (gst_adapter_available (adapter) == 0, + "Data was left in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +/* Fill a buffer with a sequence of 32 bit ints and read a couple of front + * buffers using get_buffer, checking that they're still in the right order */ +GST_START_TEST (test_get_buffer_list) +{ + GstAdapter *adapter; + int i = 0; + gsize size = 0; + GstBufferList *buffer_list; + GstBuffer *buf; + gsize left; + GstMapInfo info; + guint8 *ptr; + guint n, num; + + adapter = create_and_fill_adapter (); + size = gst_adapter_available (adapter); + + buffer_list = gst_adapter_get_buffer_list (adapter, sizeof (guint32) * 5); + fail_unless (buffer_list != NULL); + + num = gst_buffer_list_length (buffer_list); + fail_unless (num > 0); + + for (n = 0; n < num; ++n) { + buf = gst_buffer_list_get (buffer_list, n); + + fail_unless (gst_buffer_map (buf, &info, GST_MAP_READ)); + + ptr = info.data; + left = info.size; + + while (left > 0) { + fail_unless (GST_READ_UINT32_LE (ptr) == i); + i++; + ptr += sizeof (guint32); + left -= sizeof (guint32); + } + gst_buffer_unmap (buf, &info); + } + gst_buffer_list_unref (buffer_list); + + fail_unless (gst_adapter_available (adapter) == size, + "All data should remain in the adapter"); + + g_object_unref (adapter); +} + +GST_END_TEST; + +GST_START_TEST (test_merge) +{ + GstAdapter *adapter; + GstBuffer *buffer; + gint i; + + adapter = gst_adapter_new (); + fail_if (adapter == NULL); + + buffer = gst_buffer_new_and_alloc (10); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + for (i = 0; i < 1000; i++) { + buffer = gst_buffer_new_and_alloc (10); + gst_adapter_push (adapter, buffer); + + fail_unless (gst_adapter_map (adapter, 20) != NULL); + gst_adapter_unmap (adapter); + + gst_adapter_flush (adapter, 10); + } + g_object_unref (adapter); +} + +GST_END_TEST; + +GST_START_TEST (test_take_buffer_fast) +{ + GstAdapter *adapter; + GstBuffer *buffer; + + adapter = gst_adapter_new (); + fail_if (adapter == NULL); + + buffer = gst_buffer_new_and_alloc (5); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + buffer = gst_buffer_new_and_alloc (10); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + buffer = gst_buffer_new_and_alloc (15); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + fail_unless (gst_adapter_available (adapter) == 30); + + buffer = gst_adapter_take_buffer_fast (adapter, 30); + fail_unless (gst_adapter_available (adapter) == 0); + fail_unless (gst_buffer_n_memory (buffer) == 3); + fail_unless (gst_buffer_get_sizes_range (buffer, 0, 1, NULL, NULL) == 5); + fail_unless (gst_buffer_get_sizes_range (buffer, 1, 1, NULL, NULL) == 10); + fail_unless (gst_buffer_get_sizes_range (buffer, 2, 1, NULL, NULL) == 15); + gst_buffer_unref (buffer); + + fail_unless (gst_adapter_available (adapter) == 0); + + buffer = gst_buffer_new_and_alloc (10); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + buffer = gst_buffer_new_and_alloc (20); + fail_if (buffer == NULL); + gst_adapter_push (adapter, buffer); + + gst_adapter_flush (adapter, 2); + fail_unless (gst_adapter_available (adapter) == 28); + + buffer = gst_adapter_take_buffer_fast (adapter, 10); + fail_unless (gst_buffer_n_memory (buffer) == 2); + fail_unless (gst_buffer_get_sizes_range (buffer, 0, 1, NULL, NULL) == 8); + fail_unless (gst_buffer_get_sizes_range (buffer, 1, 1, NULL, NULL) == 2); + fail_unless (gst_adapter_available (adapter) == 18); + gst_buffer_unref (buffer); + + buffer = gst_adapter_take_buffer_fast (adapter, 8); + fail_unless (gst_buffer_n_memory (buffer) == 1); + fail_unless (gst_buffer_get_size (buffer) == 8); + fail_unless (gst_adapter_available (adapter) == 10); + gst_buffer_unref (buffer); + + gst_adapter_clear (adapter); + fail_unless (gst_adapter_available (adapter) == 0); + + g_object_unref (adapter); +} + +GST_END_TEST; + +static Suite * +gst_adapter_suite (void) +{ + Suite *s = suite_create ("adapter"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_peek1); + tcase_add_test (tc_chain, test_peek2); + tcase_add_test (tc_chain, test_peek3); + tcase_add_test (tc_chain, test_take1); + tcase_add_test (tc_chain, test_take2); + tcase_add_test (tc_chain, test_take3); + tcase_add_test (tc_chain, test_take_order); + tcase_add_test (tc_chain, test_take_buf_order); + tcase_add_test (tc_chain, test_timestamp); + tcase_add_test (tc_chain, test_scan); + tcase_add_test (tc_chain, test_take_list); + tcase_add_test (tc_chain, test_get_list); + tcase_add_test (tc_chain, test_take_buffer_list); + tcase_add_test (tc_chain, test_get_buffer_list); + tcase_add_test (tc_chain, test_merge); + tcase_add_test (tc_chain, test_take_buffer_fast); + tcase_add_test (tc_chain, test_offset); + + return s; +} + +GST_CHECK_MAIN (gst_adapter); diff --git a/tests/check/libs/aggregator.c b/tests/check/libs/aggregator.c new file mode 100644 index 0000000..8503a95 --- /dev/null +++ b/tests/check/libs/aggregator.c @@ -0,0 +1,1283 @@ +/* + * aggregator.c - GstAggregator testsuite + * Copyright (C) 2006 Alessandro Decina + * Copyright (C) 2014 Mathieu Duponchelle + * Copyright (C) 2014 Thibault Saunier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +/* dummy aggregator based element */ + +#define GST_TYPE_TEST_AGGREGATOR (gst_test_aggregator_get_type ()) +#define GST_TEST_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_AGGREGATOR, GstTestAggregator)) +#define GST_TEST_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_AGGREGATOR, GstTestAggregatorClass)) +#define GST_TEST_AGGREGATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_AGGREGATOR, GstTestAggregatorClass)) + +#define fail_error_message(msg) \ + G_STMT_START { \ + GError *error; \ + gst_message_parse_error(msg, &error, NULL); \ + fail_unless(FALSE, "Error Message from %s : %s", \ + GST_OBJECT_NAME (GST_MESSAGE_SRC(msg)), error->message); \ + g_error_free (error); \ + } G_STMT_END; + +typedef struct _GstTestAggregator GstTestAggregator; +typedef struct _GstTestAggregatorClass GstTestAggregatorClass; + +static GType gst_test_aggregator_get_type (void); + +#define BUFFER_DURATION 100000000 /* 10 frames per second */ +#define TEST_GAP_PTS 0 +#define TEST_GAP_DURATION (5 * GST_SECOND) + +struct _GstTestAggregator +{ + GstAggregator parent; + + guint64 timestamp; + gboolean gap_expected; +}; + +struct _GstTestAggregatorClass +{ + GstAggregatorClass parent_class; +}; + +static GstFlowReturn +gst_test_aggregator_aggregate (GstAggregator * aggregator, gboolean timeout) +{ + GstIterator *iter; + gboolean all_eos = TRUE; + GstTestAggregator *testagg; + GstBuffer *buf; + + gboolean done_iterating = FALSE; + + testagg = GST_TEST_AGGREGATOR (aggregator); + + iter = gst_element_iterate_sink_pads (GST_ELEMENT (testagg)); + while (!done_iterating) { + GValue value = { 0, }; + GstAggregatorPad *pad; + + switch (gst_iterator_next (iter, &value)) { + case GST_ITERATOR_OK: + pad = g_value_get_object (&value); + + if (gst_aggregator_pad_is_eos (pad) == FALSE) + all_eos = FALSE; + + if (testagg->gap_expected == TRUE) { + buf = gst_aggregator_pad_peek_buffer (pad); + fail_unless (buf); + fail_unless (GST_BUFFER_PTS (buf) == TEST_GAP_PTS); + fail_unless (GST_BUFFER_DURATION (buf) == TEST_GAP_DURATION); + fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)); + fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DROPPABLE)); + gst_buffer_unref (buf); + testagg->gap_expected = FALSE; + } + + gst_aggregator_pad_drop_buffer (pad); + + g_value_reset (&value); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (testagg, "Sinkpads iteration error"); + done_iterating = TRUE; + break; + case GST_ITERATOR_DONE: + done_iterating = TRUE; + break; + } + } + gst_iterator_free (iter); + + if (all_eos == TRUE) { + GST_INFO_OBJECT (testagg, "no data available, must be EOS"); + gst_pad_push_event (aggregator->srcpad, gst_event_new_eos ()); + return GST_FLOW_EOS; + } + + buf = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buf) = testagg->timestamp; + GST_BUFFER_DURATION (buf) = BUFFER_DURATION; + testagg->timestamp += BUFFER_DURATION; + + gst_aggregator_finish_buffer (aggregator, buf); + + /* We just check finish_frame return FLOW_OK */ + return GST_FLOW_OK; +} + +#define gst_test_aggregator_parent_class parent_class +G_DEFINE_TYPE (GstTestAggregator, gst_test_aggregator, GST_TYPE_AGGREGATOR); + +static void +gst_test_aggregator_class_init (GstTestAggregatorClass * klass) +{ + GstElementClass *gstelement_class = (GstElementClass *) klass; + GstAggregatorClass *base_aggregator_class = (GstAggregatorClass *) klass; + + 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_%u", GST_PAD_SINK, GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + + gst_element_class_add_static_pad_template_with_gtype (gstelement_class, + &_src_template, GST_TYPE_AGGREGATOR_PAD); + + gst_element_class_add_static_pad_template_with_gtype (gstelement_class, + &_sink_template, GST_TYPE_AGGREGATOR_PAD); + + gst_element_class_set_static_metadata (gstelement_class, "Aggregator", + "Testing", "Combine N buffers", "Stefan Sauer "); + + base_aggregator_class->aggregate = + GST_DEBUG_FUNCPTR (gst_test_aggregator_aggregate); +} + +static void +gst_test_aggregator_init (GstTestAggregator * self) +{ + GstAggregator *agg = GST_AGGREGATOR (self); + gst_segment_init (&GST_AGGREGATOR_PAD (agg->srcpad)->segment, + GST_FORMAT_TIME); + self->timestamp = 0; + self->gap_expected = FALSE; +} + +static gboolean +gst_test_aggregator_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "testaggregator", GST_RANK_NONE, + GST_TYPE_TEST_AGGREGATOR); +} + +static gboolean +gst_test_aggregator_plugin_register (void) +{ + return gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "testaggregator", + "Combine buffers", + gst_test_aggregator_plugin_init, + VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); +} + +/* test helpers */ + +typedef struct +{ + GQueue *queue; + GstElement *aggregator; + GstPad *sinkpad, *srcpad; + GstFlowReturn expected_result; + + /* ------------------ + * ----------- --------|-- | + * | srcpad | -- | sinkpad | aggregator | + * ----------- --------|-- | + * ------------------ + * This is for 1 Chain, we can have several + */ +} ChainData; + +typedef struct +{ + GMainLoop *ml; + GstPad *srcpad, /* srcpad of the GstAggregator */ + *sinkpad; /* fake sinkpad to which GstAggregator.srcpad is linked */ + guint timeout_id; + GstElement *aggregator; + + /* -----------------| + * | ---------- ----------- + * | aggregator | srcpad | -- | sinkpad | + * | ---------- ----------- + * -----------------| + */ + + gint flush_start_events, flush_stop_events; +} TestData; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void +start_flow (ChainData * chain_data) +{ + GstSegment segment; + GstCaps *caps; + + gst_pad_push_event (chain_data->srcpad, gst_event_new_stream_start ("test")); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_pad_push_event (chain_data->srcpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + gst_segment_init (&segment, GST_FORMAT_TIME); + gst_pad_push_event (chain_data->srcpad, gst_event_new_segment (&segment)); +} + +static gpointer +push_data (gpointer user_data) +{ + ChainData *chain_data = (ChainData *) user_data; + GstTestAggregator *aggregator = (GstTestAggregator *) chain_data->aggregator; + GstPad *sinkpad = chain_data->sinkpad; + GstPad *srcpad = chain_data->srcpad; + gpointer data; + + start_flow (chain_data); + + while ((data = g_queue_pop_head (chain_data->queue))) { + GST_DEBUG_OBJECT (sinkpad, "Pushing %" GST_PTR_FORMAT, data); + + /* switch on the data type and push */ + if (GST_IS_BUFFER (data)) { + GstFlowReturn flow = gst_pad_push (srcpad, GST_BUFFER_CAST (data)); + fail_unless (flow == chain_data->expected_result, + "got flow %s instead of %s on %s:%s", gst_flow_get_name (flow), + gst_flow_get_name (chain_data->expected_result), + GST_DEBUG_PAD_NAME (sinkpad)); + } else if (GST_IS_EVENT (data)) { + switch (GST_EVENT_TYPE (data)) { + case GST_EVENT_GAP: + aggregator->gap_expected = TRUE; + break; + default: + break; + } + fail_unless (gst_pad_push_event (srcpad, GST_EVENT_CAST (data))); + } else if (GST_IS_QUERY (data)) { + /* we don't care whether the query actualy got handled */ + gst_pad_peer_query (srcpad, GST_QUERY_CAST (data)); + gst_query_unref (GST_QUERY_CAST (data)); + } else { + GST_WARNING_OBJECT (sinkpad, "bad queue entry: %" GST_PTR_FORMAT, data); + } + } + GST_DEBUG_OBJECT (sinkpad, "All data from queue sent"); + + return NULL; +} + +static gboolean +_aggregate_timeout (GMainLoop * ml) +{ + g_main_loop_quit (ml); + + fail_unless ("No buffer found on aggregator.srcpad -> TIMEOUT" == NULL); + + return FALSE; +} + +static gboolean +_quit (GMainLoop * ml) +{ + GST_DEBUG ("QUITING ML"); + g_main_loop_quit (ml); + + return G_SOURCE_REMOVE; +} + +static GstPadProbeReturn +_aggregated_cb (GstPad * pad, GstPadProbeInfo * info, GMainLoop * ml) +{ + GST_DEBUG ("Received data %" GST_PTR_FORMAT, info->data); + GST_DEBUG ("Should quit ML"); + g_idle_add ((GSourceFunc) _quit, ml); + + return GST_PAD_PROBE_REMOVE; +} + +static GstPadProbeReturn +_downstream_probe_cb (GstPad * pad, GstPadProbeInfo * info, TestData * test) +{ + GST_DEBUG ("PROBING "); + if (info->type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) { + if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_EVENT (info)) == + GST_EVENT_FLUSH_START) { + + g_atomic_int_inc (&test->flush_start_events); + GST_DEBUG ("==========> FLUSH: %i", test->flush_start_events); + } else if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_EVENT (info)) == + GST_EVENT_FLUSH_STOP) + g_atomic_int_inc (&test->flush_stop_events); + } + return GST_PAD_PROBE_OK; +} + +/* + * Not thread safe, will create a new ChainData which contains + * an activated src pad linked to a requested sink pad of @agg, and + * a newly allocated buffer ready to be pushed. Caller needs to + * clear with _chain_data_clear after. + */ +static void +_chain_data_init (ChainData * data, GstElement * agg, ...) +{ + static gint num_src_pads = 0; + gchar *pad_name = g_strdup_printf ("src%d", num_src_pads); + va_list var_args; + gpointer d; + + num_src_pads += 1; + + data->srcpad = gst_pad_new_from_static_template (&srctemplate, pad_name); + g_free (pad_name); + gst_pad_set_active (data->srcpad, TRUE); + data->aggregator = agg; + data->sinkpad = gst_element_get_request_pad (agg, "sink_%u"); + fail_unless (GST_IS_PAD (data->sinkpad)); + fail_unless (gst_pad_link (data->srcpad, data->sinkpad) == GST_PAD_LINK_OK); + + /* add data items */ + data->queue = g_queue_new (); + va_start (var_args, agg); + while (TRUE) { + if (!(d = va_arg (var_args, gpointer))) + break; + g_queue_push_tail (data->queue, d); + GST_DEBUG_OBJECT (data->sinkpad, "Adding to queue: %" GST_PTR_FORMAT, d); + } + va_end (var_args); +} + +static void +_chain_data_clear (ChainData * chain_data) +{ + gpointer data; + + while ((data = g_queue_pop_head (chain_data->queue))) { + /* switch on the data type and free */ + if (GST_IS_BUFFER (data)) { + gst_buffer_unref (GST_BUFFER_CAST (data)); + } else if (GST_IS_EVENT (data)) { + gst_event_unref (GST_EVENT_CAST (data)); + } else if (GST_IS_QUERY (data)) { + gst_query_unref (GST_QUERY_CAST (data)); + } else { + GST_WARNING_OBJECT (chain_data->sinkpad, "bad queue entry: %" + GST_PTR_FORMAT, data); + } + } + g_queue_free (chain_data->queue); + + if (chain_data->srcpad) + gst_object_unref (chain_data->srcpad); + if (chain_data->sinkpad) + gst_object_unref (chain_data->sinkpad); +} + +static GstFlowReturn +_test_chain (GstPad * pad, GstObject * object, GstBuffer * buffer) +{ + /* accept any buffers */ + gst_buffer_unref (buffer); + return GST_FLOW_OK; +} + +static void +_test_data_init (TestData * test, gboolean needs_flushing) +{ + test->aggregator = gst_element_factory_make ("testaggregator", NULL); + gst_element_set_state (test->aggregator, GST_STATE_PLAYING); + test->ml = g_main_loop_new (NULL, TRUE); + test->srcpad = GST_AGGREGATOR (test->aggregator)->srcpad; + + GST_DEBUG_OBJECT (test->srcpad, "Init test data for srcpad"); + + if (needs_flushing) { + static gint num_sink_pads = 0; + gchar *pad_name = g_strdup_printf ("sink%d", num_sink_pads); + + num_sink_pads += 1; + test->sinkpad = gst_pad_new_from_static_template (&sinktemplate, pad_name); + gst_pad_set_chain_function (test->sinkpad, _test_chain); + gst_pad_set_active (test->sinkpad, TRUE); + g_free (pad_name); + fail_unless (gst_pad_link (test->srcpad, test->sinkpad) == GST_PAD_LINK_OK); + gst_pad_add_probe (test->srcpad, GST_PAD_PROBE_TYPE_EVENT_FLUSH, + (GstPadProbeCallback) _downstream_probe_cb, test, NULL); + } else { + gst_pad_add_probe (test->srcpad, GST_PAD_PROBE_TYPE_BUFFER, + (GstPadProbeCallback) _aggregated_cb, test->ml, NULL); + } + + test->timeout_id = + g_timeout_add (1000, (GSourceFunc) _aggregate_timeout, test->ml); +} + +static void +_test_data_clear (TestData * test) +{ + gst_element_set_state (test->aggregator, GST_STATE_NULL); + gst_object_unref (test->aggregator); + + if (test->sinkpad) + gst_object_unref (test->sinkpad); + + g_main_loop_unref (test->ml); +} + +/* tests */ + +GST_START_TEST (test_aggregate) +{ + GThread *thread1, *thread2; + ChainData data1 = { 0, }; + ChainData data2 = { 0, }; + TestData test = { 0, }; + + _test_data_init (&test, FALSE); + _chain_data_init (&data1, test.aggregator, gst_buffer_new (), NULL); + _chain_data_init (&data2, test.aggregator, gst_buffer_new (), NULL); + + thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL); + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread1); + g_thread_join (thread2); + + _chain_data_clear (&data1); + _chain_data_clear (&data2); + _test_data_clear (&test); +} + +GST_END_TEST; + +GST_START_TEST (test_aggregate_eos) +{ + GThread *thread1, *thread2; + ChainData data1 = { 0, }; + ChainData data2 = { 0, }; + TestData test = { 0, }; + + _test_data_init (&test, FALSE); + _chain_data_init (&data1, test.aggregator, gst_buffer_new (), NULL); + _chain_data_init (&data2, test.aggregator, gst_event_new_eos (), NULL); + + thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL); + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread1); + g_thread_join (thread2); + + _chain_data_clear (&data1); + _chain_data_clear (&data2); + _test_data_clear (&test); +} + +GST_END_TEST; + +GST_START_TEST (test_aggregate_gap) +{ + GThread *thread; + ChainData data = { 0, }; + TestData test = { 0, }; + + _test_data_init (&test, FALSE); + _chain_data_init (&data, test.aggregator, + gst_event_new_gap (TEST_GAP_PTS, TEST_GAP_DURATION), NULL); + + thread = g_thread_try_new ("gst-check", push_data, &data, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread); + + _chain_data_clear (&data); + _test_data_clear (&test); +} + +GST_END_TEST; + +GST_START_TEST (test_aggregate_handle_events) +{ + GThread *thread1, *thread2; + ChainData data1 = { 0, }; + ChainData data2 = { 0, }; + TestData test = { 0, }; + + _test_data_init (&test, FALSE); + _chain_data_init (&data1, test.aggregator, + gst_event_new_tag (gst_tag_list_new_empty ()), gst_buffer_new (), NULL); + _chain_data_init (&data2, test.aggregator, gst_buffer_new (), NULL); + + thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL); + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread1); + g_thread_join (thread2); + + _chain_data_clear (&data1); + _chain_data_clear (&data2); + _test_data_clear (&test); +} + +GST_END_TEST; + +GST_START_TEST (test_aggregate_handle_queries) +{ + GThread *thread1, *thread2; + ChainData data1 = { 0, }; + ChainData data2 = { 0, }; + TestData test = { 0, }; + GstCaps *caps; + + _test_data_init (&test, FALSE); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + _chain_data_init (&data1, test.aggregator, + gst_query_new_allocation (caps, FALSE), gst_buffer_new (), NULL); + gst_caps_unref (caps); + + _chain_data_init (&data2, test.aggregator, gst_buffer_new (), NULL); + + thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL); + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread1); + g_thread_join (thread2); + + _chain_data_clear (&data1); + _chain_data_clear (&data2); + _test_data_clear (&test); +} + +GST_END_TEST; + +#define NUM_BUFFERS 3 +static void +handoff (GstElement * fakesink, GstBuffer * buf, GstPad * pad, guint * count) +{ + *count = *count + 1; + GST_DEBUG ("HANDOFF: %i", *count); +} + +/* Test a linear pipeline using aggregator */ +GST_START_TEST (test_linear_pipeline) +{ + GstBus *bus; + GstMessage *msg; + GstElement *pipeline, *src, *agg, *sink; + gint count = 0; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("fakesrc"); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizetype", 2, "sizemax", 4, + NULL); + agg = gst_check_setup_element ("testaggregator"); + sink = gst_check_setup_element ("fakesink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff, &count); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (src, agg)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + fail_unless_equals_int (count, NUM_BUFFERS); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_two_src_pipeline) +{ + GstBus *bus; + GstMessage *msg; + GstElement *pipeline, *src, *src1, *agg, *sink; + gint count = 0; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizetype", 2, "sizemax", 4, + NULL); + + src1 = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src1, "num-buffers", NUM_BUFFERS + 1, "sizetype", 2, "sizemax", + 4, NULL); + + agg = gst_check_setup_element ("testaggregator"); + sink = gst_check_setup_element ("fakesink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff, &count); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), src1)); + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (src, agg)); + fail_unless (gst_element_link (src1, agg)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + fail_unless_equals_int (count, NUM_BUFFERS + 1); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstPadProbeReturn +_drop_buffer_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + gint wait; + + if (GST_IS_BUFFER (info->data)) { + wait = GPOINTER_TO_INT (user_data); + if (wait > 0) + g_usleep (wait / 1000); + return GST_PAD_PROBE_DROP; + } + + return GST_PAD_PROBE_PASS; +} + +#define TIMEOUT_NUM_BUFFERS 20 +static void +_test_timeout (gint buffer_wait) +{ + GstBus *bus; + GstMessage *msg; + GstElement *pipeline, *src, *src1, *agg, *sink; + GstPad *src1pad; + gint count = 0; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", TIMEOUT_NUM_BUFFERS, "sizetype", 2, + "sizemax", 4, "is-live", TRUE, "datarate", 4000, NULL); + + src1 = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src1, "num-buffers", TIMEOUT_NUM_BUFFERS, "sizetype", 2, + "sizemax", 4, "is-live", TRUE, "datarate", 4000, NULL); + + agg = gst_check_setup_element ("testaggregator"); + g_object_set (agg, "latency", GST_USECOND, NULL); + sink = gst_check_setup_element ("fakesink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff, &count); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), src1)); + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + + src1pad = gst_element_get_static_pad (src1, "src"); + fail_if (src1pad == NULL); + gst_pad_add_probe (src1pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + (GstPadProbeCallback) _drop_buffer_probe_cb, + GINT_TO_POINTER (buffer_wait), NULL); + + fail_unless (gst_element_link (src, agg)); + fail_unless (gst_element_link (src1, agg)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + /* cannot rely on the exact number of buffers as the timeout may produce + * more buffers with the unsynchronized _aggregate() implementation in + * testaggregator */ + fail_if (count < TIMEOUT_NUM_BUFFERS); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (src1pad); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_START_TEST (test_timeout_pipeline) +{ + _test_timeout (0); +} + +GST_END_TEST; + +GST_START_TEST (test_timeout_pipeline_with_wait) +{ + _test_timeout (1000000 /* 1 ms */ ); +} + +GST_END_TEST; + +GST_START_TEST (test_flushing_seek) +{ + GstEvent *event; + GThread *thread1, *thread2; + ChainData data1 = { 0, }; + ChainData data2 = { 0, }; + TestData test = { 0, }; + GstBuffer *buf; + + _test_data_init (&test, TRUE); + + /* Queue a buffer in agg:sink_1. Then do a flushing seek and check that the + * new flushing seek logic is triggered. On the first FLUSH_START call the + * buffers queued in collectpads should get flushed. Only one FLUSH_START and + * one FLUSH_STOP should be forwarded downstream. + */ + _chain_data_init (&data1, test.aggregator, gst_buffer_new (), NULL); + + buf = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buf) = 0; + _chain_data_init (&data2, test.aggregator, buf, NULL); + + gst_segment_init (&GST_AGGREGATOR_PAD (GST_AGGREGATOR (test. + aggregator)->srcpad)->segment, GST_FORMAT_TIME); + + /* now do a successful flushing seek */ + event = gst_event_new_seek (1, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 10 * GST_SECOND); + fail_unless (gst_pad_send_event (test.srcpad, event)); + + /* flushing starts once one of the upstream elements sends the first + * FLUSH_START */ + fail_unless_equals_int (test.flush_start_events, 0); + fail_unless_equals_int (test.flush_stop_events, 0); + + /* send a first FLUSH_START on agg:sink_0, will be sent downstream */ + GST_DEBUG_OBJECT (data2.sinkpad, "send flush_start"); + fail_unless (gst_pad_push_event (data2.srcpad, gst_event_new_flush_start ())); + fail_unless_equals_int (test.flush_start_events, 1); + fail_unless_equals_int (test.flush_stop_events, 0); + + /* expect this buffer to be flushed */ + data2.expected_result = GST_FLOW_FLUSHING; + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + /* this should send not additional flush_start */ + GST_DEBUG_OBJECT (data1.sinkpad, "send flush_start"); + fail_unless (gst_pad_push_event (data1.srcpad, gst_event_new_flush_start ())); + fail_unless_equals_int (test.flush_start_events, 1); + fail_unless_equals_int (test.flush_stop_events, 0); + + /* the first FLUSH_STOP is not forwarded downstream */ + GST_DEBUG_OBJECT (data1.srcpad, "send flush_stop"); + fail_unless (gst_pad_push_event (data1.srcpad, + gst_event_new_flush_stop (TRUE))); + fail_unless_equals_int (test.flush_start_events, 1); + fail_unless_equals_int (test.flush_stop_events, 0); + + /* at this point even the other pad agg:sink_1 should be flushing so thread2 + * should have stopped */ + g_thread_join (thread2); + + /* push a buffer on agg:sink_0 to trigger one collect after flushing to verify + * that flushing completes once all the pads have been flushed */ + thread1 = g_thread_try_new ("gst-check", push_data, &data1, NULL); + + /* flush agg:sink_1 as well. This completes the flushing seek so a FLUSH_STOP is + * sent downstream */ + GST_DEBUG_OBJECT (data2.srcpad, "send flush_stop"); + gst_pad_push_event (data2.srcpad, gst_event_new_flush_stop (TRUE)); + + /* and the last FLUSH_STOP is forwarded downstream */ + fail_unless_equals_int (test.flush_stop_events, 1); + + /* Check collected */ + gst_pad_add_probe (test.srcpad, GST_PAD_PROBE_TYPE_BUFFER, + (GstPadProbeCallback) _aggregated_cb, test.ml, NULL); + + g_queue_push_tail (data2.queue, gst_event_new_eos ()); + thread2 = g_thread_try_new ("gst-check", push_data, &data2, NULL); + + g_main_loop_run (test.ml); + g_source_remove (test.timeout_id); + + fail_unless_equals_int (test.flush_stop_events, 1); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); + + _chain_data_clear (&data1); + _chain_data_clear (&data2); + _test_data_clear (&test); + +} + +GST_END_TEST; + +static void +infinite_seek (guint num_srcs, guint num_seeks, gboolean is_live) +{ + GstBus *bus; + GstMessage *message; + GstElement *pipeline, *src, *agg, *sink; + gint count = 0, i; + gboolean seek_res, carry_on = TRUE; + + pipeline = gst_pipeline_new ("pipeline"); + + agg = gst_check_setup_element ("testaggregator"); + sink = gst_check_setup_element ("fakesink"); + + if (is_live) + g_object_set (agg, "latency", GST_MSECOND, NULL); + + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (agg, sink)); + + for (i = 0; i < num_srcs; i++) { + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "sizetype", 2, "sizemax", 4, + "format", GST_FORMAT_TIME, "datarate", 1000, NULL); + if (is_live) + g_object_set (src, "is-live", TRUE, NULL); + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_element_link (src, agg)); + } + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + while (count < num_seeks && carry_on) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10); + if (message) { + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + { + /* we should check if we really finished here */ + GST_WARNING ("Got an EOS"); + carry_on = FALSE; + break; + } + case GST_MESSAGE_STATE_CHANGED: + { + GstState new; + + if (GST_MESSAGE_SRC (message) == GST_OBJECT (pipeline)) { + gst_message_parse_state_changed (message, NULL, &new, NULL); + + if (new != GST_STATE_PLAYING) + break; + + GST_INFO ("Seeking (num: %i)", count); + seek_res = + gst_element_seek_simple (sink, GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 0); + GST_INFO ("seek result is : %d", seek_res); + fail_unless (seek_res != 0); + count++; + } + + break; + } + case GST_MESSAGE_ERROR: + GST_ERROR ("Error on the bus: %" GST_PTR_FORMAT, message); + carry_on = FALSE; + fail_error_message (message); + break; + default: + break; + } + gst_message_unref (message); + } + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_START_TEST (test_infinite_seek) +{ + infinite_seek (2, 500, FALSE); +} + +GST_END_TEST; + +GST_START_TEST (test_infinite_seek_50_src) +{ + infinite_seek (50, 100, FALSE); +} + +GST_END_TEST; + +GST_START_TEST (test_infinite_seek_50_src_live) +{ + infinite_seek (50, 100, TRUE); +} + +GST_END_TEST; + +typedef struct +{ + GstElement *agg, *src, *pipeline; + GCond *cond; + GMutex *lock; +} RemoveElementData; + +static GstPadProbeReturn +pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, RemoveElementData * data) +{ + GstPad *peer; + + GST_INFO_OBJECT (pad, "Removing pad"); + + peer = gst_pad_get_peer (pad); + gst_pad_unlink (pad, peer); + gst_element_release_request_pad (data->agg, peer); + fail_unless (gst_bin_remove (GST_BIN (data->pipeline), data->src)); + gst_object_unref (peer); + + g_mutex_lock (data->lock); + g_cond_broadcast (data->cond); + g_mutex_unlock (data->lock); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_add_remove) +{ + /* Used to notify that we removed the pad from */ + GCond cond; + GMutex lock; + GstBus *bus; + GstState state; + GstMessage *message; + gboolean carry_on = TRUE; + guint num_iterations = 100; + GstPad *pad; + GstElement *pipeline, *src, *src1 = NULL, *agg, *sink; + gint count = 0; + + g_mutex_init (&lock); + g_cond_init (&cond); + + pipeline = gst_pipeline_new ("pipeline"); + + agg = gst_check_setup_element ("testaggregator"); + sink = gst_check_setup_element ("fakesink"); + + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + while (count < num_iterations) { + + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "num-buffers", 100000, "sizetype", 2, "sizemax", 4, + "format", GST_FORMAT_TIME, "datarate", 1000, NULL); + gst_element_set_locked_state (src, TRUE); + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_element_link (src, agg)); + gst_element_set_locked_state (src, FALSE); + fail_unless (gst_element_sync_state_with_parent (src)); + + if (count == 0) + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* Now make sure the seek happend */ + carry_on = TRUE; + do { + message = gst_bus_timed_pop (bus, -1); + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + { + /* we should check if we really finished here */ + GST_WARNING ("Got an EOS"); + carry_on = FALSE; + break; + } + case GST_MESSAGE_STATE_CHANGED: + { + if (GST_MESSAGE_SRC (message) == GST_OBJECT (pipeline)) { + gst_message_parse_state_changed (message, NULL, &state, NULL); + + if (state == GST_STATE_PLAYING) { + RemoveElementData data; + + carry_on = FALSE; + if (count == 0) { + GST_DEBUG ("First run, not removing any element yet"); + + break; + } + + data.src = gst_object_ref (src1); + data.agg = agg; + data.lock = &lock; + data.cond = &cond; + data.pipeline = pipeline; + pad = gst_element_get_static_pad (data.src, "src"); + + g_mutex_lock (&lock); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + (GstPadProbeCallback) pad_probe_cb, &data, NULL); + GST_INFO ("Waiting for %" GST_PTR_FORMAT " %s", pad, + gst_element_state_get_name (GST_STATE (data.src))); + g_cond_wait (&cond, &lock); + g_mutex_unlock (&lock); + gst_object_unref (pad); + + /* We can not set state from the streaming thread so we + * need to make sure that the source has been removed + * before setting its state to NULL */ + gst_element_set_state (data.src, GST_STATE_NULL); + + gst_object_unref (data.src); + } + } + + break; + } + case GST_MESSAGE_ERROR: + { + GST_ERROR ("Error on the bus: %" GST_PTR_FORMAT, message); + carry_on = FALSE; + fail_error_message (message); + break; + } + default: + break; + } + + gst_message_unref (message); + } while (carry_on); + + GST_INFO ("Seeking"); + fail_unless (gst_element_seek_simple (pipeline, GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 0)); + + count++; + src1 = src; + } + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); + g_mutex_clear (&lock); + g_cond_clear (&cond); +} + +GST_END_TEST; + +GST_START_TEST (test_change_state_intensive) +{ + GstBus *bus; + GstMessage *message; + GstElement *pipeline, *src, *agg, *sink; + gint i, state_i = 0, num_srcs = 3; + gboolean carry_on = TRUE, ready = FALSE; + GstStateChangeReturn state_return; + GstState wanted_state, wanted_states[] = { + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PAUSED, GST_STATE_READY, + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PAUSED, GST_STATE_READY, + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PAUSED, GST_STATE_READY, + GST_STATE_PAUSED, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_READY, + GST_STATE_PAUSED, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_NULL, + GST_STATE_PAUSED, GST_STATE_NULL, GST_STATE_PAUSED, GST_STATE_NULL, + GST_STATE_PAUSED, GST_STATE_NULL, GST_STATE_PAUSED, GST_STATE_NULL, + GST_STATE_PAUSED, GST_STATE_NULL, GST_STATE_PLAYING, GST_STATE_NULL, + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PLAYING, GST_STATE_NULL, + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PLAYING, GST_STATE_NULL, + GST_STATE_PLAYING, GST_STATE_NULL, GST_STATE_PLAYING, GST_STATE_NULL, + }; + + pipeline = gst_pipeline_new ("pipeline"); + + agg = gst_check_setup_element ("testaggregator"); + sink = gst_check_setup_element ("fakesink"); + + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (agg, sink)); + + for (i = 0; i < num_srcs; i++) { + src = gst_element_factory_make ("fakesrc", NULL); + g_object_set (src, "sizetype", 2, "sizemax", 4, NULL); + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_element_link (src, agg)); + } + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + + wanted_state = wanted_states[state_i++]; + state_return = gst_element_set_state (pipeline, wanted_state); + + while (state_i < G_N_ELEMENTS (wanted_states) && carry_on) { + if (state_return == GST_STATE_CHANGE_SUCCESS && ready) { + wanted_state = wanted_states[state_i++]; + fail_unless (gst_element_set_state (pipeline, wanted_state), + GST_STATE_CHANGE_SUCCESS); + GST_INFO ("Wanted state: %s", gst_element_state_get_name (wanted_state)); + } + + message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10); + if (message) { + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + { + /* we should check if we really finished here */ + GST_WARNING ("Got an EOS"); + carry_on = FALSE; + break; + } + case GST_MESSAGE_STATE_CHANGED: + { + GstState new; + + if (GST_MESSAGE_SRC (message) == GST_OBJECT (pipeline)) { + gst_message_parse_state_changed (message, NULL, &new, NULL); + + if (new != wanted_state) { + ready = FALSE; + break; + } + + GST_DEBUG ("State %s reached", + gst_element_state_get_name (wanted_state)); + wanted_state = wanted_states[state_i++]; + GST_DEBUG ("Wanted state: %s", + gst_element_state_get_name (wanted_state)); + state_return = gst_element_set_state (pipeline, wanted_state); + fail_unless (state_return == GST_STATE_CHANGE_SUCCESS || + state_return == GST_STATE_CHANGE_ASYNC); + ready = TRUE; + } + + break; + } + case GST_MESSAGE_ERROR: + GST_ERROR ("Error on the bus: %" GST_PTR_FORMAT, message); + carry_on = FALSE; + break; + default: + break; + } + gst_message_unref (message); + } + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +gst_aggregator_suite (void) +{ + Suite *suite; + TCase *general; + + gst_test_aggregator_plugin_register (); + + suite = suite_create ("GstAggregator"); + + general = tcase_create ("general"); + suite_add_tcase (suite, general); + tcase_add_test (general, test_aggregate); + tcase_add_test (general, test_aggregate_eos); + tcase_add_test (general, test_aggregate_gap); + tcase_add_test (general, test_aggregate_handle_events); + tcase_add_test (general, test_aggregate_handle_queries); + tcase_add_test (general, test_flushing_seek); + tcase_add_test (general, test_infinite_seek); + tcase_add_test (general, test_infinite_seek_50_src); + tcase_add_test (general, test_infinite_seek_50_src_live); + tcase_add_test (general, test_linear_pipeline); + tcase_add_test (general, test_two_src_pipeline); + tcase_add_test (general, test_timeout_pipeline); + tcase_add_test (general, test_timeout_pipeline_with_wait); + tcase_add_test (general, test_add_remove); + tcase_add_test (general, test_change_state_intensive); + + return suite; +} + +GST_CHECK_MAIN (gst_aggregator); diff --git a/tests/check/libs/baseparse.c b/tests/check/libs/baseparse.c new file mode 100644 index 0000000..cbd3b66 --- /dev/null +++ b/tests/check/libs/baseparse.c @@ -0,0 +1,489 @@ +/* GStreamer + * + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * Author: 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +static GstPad *mysrcpad, *mysinkpad; +static GstElement *parsetest; +static GstBus *bus; +static GMainLoop *loop = NULL; +static gboolean have_eos = FALSE; +static gboolean have_data = FALSE; +static gint buffer_count = 0; +static gboolean caps_set = FALSE; + +#define TEST_VIDEO_WIDTH 640 +#define TEST_VIDEO_HEIGHT 480 +#define TEST_VIDEO_FPS_N 30 +#define TEST_VIDEO_FPS_D 1 + +#define GST_PARSER_TESTER_TYPE gst_parser_tester_get_type() +static GType gst_parser_tester_get_type (void); + +typedef struct _GstParserTester GstParserTester; +typedef struct _GstParserTesterClass GstParserTesterClass; + +struct _GstParserTester +{ + GstBaseParse parent; +}; + +struct _GstParserTesterClass +{ + GstBaseParseClass parent_class; +}; + +G_DEFINE_TYPE (GstParserTester, gst_parser_tester, GST_TYPE_BASE_PARSE); + +static gboolean +gst_parser_tester_start (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_parser_tester_stop (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_parser_tester_set_sink_caps (GstBaseParse * parse, GstCaps * caps) +{ + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + return TRUE; +} + +static GstFlowReturn +gst_parser_tester_handle_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, gint * skipsize) +{ + GstFlowReturn ret = GST_FLOW_OK; + + if (caps_set == FALSE) { + GstCaps *caps; + /* push caps */ + caps = + gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT, + TEST_VIDEO_WIDTH, "height", G_TYPE_INT, TEST_VIDEO_HEIGHT, "framerate", + GST_TYPE_FRACTION, TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D, NULL); + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + gst_caps_unref (caps); + caps_set = TRUE; + } + + while (frame->buffer && gst_buffer_get_size (frame->buffer) >= 8) { + GST_BUFFER_DURATION (frame->buffer) = + gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N); + ret = gst_base_parse_finish_frame (parse, frame, 8); + } + return ret; +} + +static void +gst_parser_tester_class_init (GstParserTesterClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass); + + static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-test-custom")); + + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-test-custom")); + + gst_element_class_add_static_pad_template (element_class, &sink_templ); + gst_element_class_add_static_pad_template (element_class, &src_templ); + + gst_element_class_set_metadata (element_class, + "ParserTester", "Parser/Video", "yep", "me"); + + baseparse_class->start = gst_parser_tester_start; + baseparse_class->stop = gst_parser_tester_stop; + baseparse_class->handle_frame = gst_parser_tester_handle_frame; + baseparse_class->set_sink_caps = gst_parser_tester_set_sink_caps; +} + +static void +gst_parser_tester_init (GstParserTester * tester) +{ +} + +static void +setup_parsertester (void) +{ + static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-test-custom") + ); + static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-test-custom") + ); + + parsetest = g_object_new (GST_PARSER_TESTER_TYPE, NULL); + mysrcpad = gst_check_setup_src_pad (parsetest, &srctemplate); + mysinkpad = gst_check_setup_sink_pad (parsetest, &sinktemplate); + bus = gst_bus_new (); + gst_element_set_bus (parsetest, bus); +} + +static void +cleanup_parsertest (void) +{ + /* release the bus first to get rid of all refcounts */ + gst_element_set_bus (parsetest, NULL); + gst_object_unref (bus); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (parsetest); + gst_check_teardown_sink_pad (parsetest); + gst_check_teardown_element (parsetest); +} + +static GstBuffer * +create_test_buffer (guint64 num) +{ + GstBuffer *buffer; + guint64 *data = g_malloc (sizeof (guint64)); + + *data = num; + + buffer = gst_buffer_new_wrapped (data, sizeof (guint64)); + + GST_BUFFER_PTS (buffer) = + gst_util_uint64_scale_round (num, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N); + GST_BUFFER_DURATION (buffer) = + gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N); + + return buffer; +} + +static void +send_startup_events (void) +{ + GstCaps *caps; + + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_stream_start ("randomvalue"))); + + /* push caps */ + caps = + gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT, + TEST_VIDEO_WIDTH, "height", G_TYPE_INT, TEST_VIDEO_HEIGHT, "framerate", + GST_TYPE_FRACTION, TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D, NULL); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + gst_caps_unref (caps); +} + +static void +check_no_error_received (void) +{ + GstMessage *msg; + + msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR); + fail_unless (msg == NULL); + if (msg) + gst_message_unref (msg); +} + +static void +run_parser_playback_test (GList * input, gint expected_output, gdouble rate) +{ + GstBuffer *buffer; + guint64 i; + GList *iter; + GstSegment segment; + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (parsetest, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.rate = rate; + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers, the data is actually a number so we can track them */ + for (iter = input; iter; iter = g_list_next (iter)) { + buffer = iter->data; + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + g_list_free (input); + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + /* check that all buffers were received by our source pad */ + fail_unless (g_list_length (buffers) == expected_output); + i = 0; + for (iter = buffers; iter; iter = g_list_next (iter)) { + GstMapInfo map; + guint64 num; + + buffer = iter->data; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + num = *(guint64 *) map.data; + fail_unless (i == num); + fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i, + GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N)); + fail_unless (GST_BUFFER_DURATION (buffer) == + gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N)); + + gst_buffer_unmap (buffer, &map); + i++; + } + + g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); + buffers = NULL; + + check_no_error_received (); + + cleanup_parsertest (); +} + + +GST_START_TEST (parser_playback) +{ + GList *input = NULL; + gint i; + GstBuffer *buffer; + + setup_parsertester (); + + /* push buffers, the data is actually a number so we can track them */ + for (i = 0; i < 3; i++) { + buffer = create_test_buffer (i); + input = g_list_append (input, buffer); + } + + run_parser_playback_test (input, 3, 1.0); +} + +GST_END_TEST; + + +/* Check https://bugzilla.gnome.org/show_bug.cgi?id=721941 */ +GST_START_TEST (parser_reverse_playback_on_passthrough) +{ + GList *input = NULL; + gint i; + GstBuffer *buffer; + + setup_parsertester (); + + gst_base_parse_set_passthrough (GST_BASE_PARSE (parsetest), TRUE); + + /* push buffers, the data is actually a number so we can track them */ + for (i = 0; i < 6; i++) { + buffer = create_test_buffer (i); + if (i > 0) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + input = g_list_append (input, buffer); + } + GST_BUFFER_FLAG_SET (g_list_nth (input, 3)->data, GST_BUFFER_FLAG_DISCONT); + + run_parser_playback_test (input, 6, -1.0); +} + +GST_END_TEST; + +GST_START_TEST (parser_empty_stream) +{ + setup_parsertester (); + + run_parser_playback_test (NULL, 0, 1.0); +} + +GST_END_TEST; + +static GstFlowReturn +_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstMapInfo map; + guint64 num; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + num = *(guint64 *) map.data; + + fail_unless (buffer_count == num); + fail_unless (GST_BUFFER_PTS (buffer) == + gst_util_uint64_scale_round (buffer_count, GST_SECOND * TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N)); + fail_unless (GST_BUFFER_DURATION (buffer) == + gst_util_uint64_scale_round (GST_SECOND, TEST_VIDEO_FPS_D, + TEST_VIDEO_FPS_N)); + gst_buffer_unmap (buffer, &map); + gst_buffer_unref (buffer); + buffer_count++; + + have_data = TRUE; + return GST_FLOW_OK; +} + +static gboolean +_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + GST_INFO_OBJECT (pad, "got %s event %p: %" GST_PTR_FORMAT, + GST_EVENT_TYPE_NAME (event), event, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + if (loop) { + while (!g_main_loop_is_running (loop)) { + /* nothing */ + }; + } + have_eos = TRUE; + if (loop) + g_main_loop_quit (loop); + break; + default: + break; + } + gst_event_unref (event); + + return TRUE; +} + +static GstFlowReturn +_src_getrange (GstPad * pad, GstObject * parent, guint64 offset, guint length, + GstBuffer ** buffer) +{ + gboolean ret = FALSE; + if (offset >= 80 && have_eos == FALSE) { + ret = gst_element_seek (parsetest, -1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, gst_util_uint64_scale_round (5, + GST_SECOND * TEST_VIDEO_FPS_D, TEST_VIDEO_FPS_N)); + fail_unless (ret == TRUE); + buffer_count = 0; + } + + *buffer = create_test_buffer (offset / 8); + + return GST_FLOW_OK; +} + +static gboolean +_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING:{ + gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); + res = TRUE; + break; + } + default: + GST_DEBUG_OBJECT (pad, "unhandled %s query", GST_QUERY_TYPE_NAME (query)); + break; + } + + return res; +} + +GST_START_TEST (parser_reverse_playback) +{ + have_eos = FALSE; + have_data = FALSE; + loop = g_main_loop_new (NULL, FALSE); + + setup_parsertester (); + gst_pad_set_getrange_function (mysrcpad, _src_getrange); + gst_pad_set_query_function (mysrcpad, _src_query); + gst_pad_set_chain_function (mysinkpad, _sink_chain); + gst_pad_set_event_function (mysinkpad, _sink_event); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (parsetest, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + g_main_loop_run (loop); + fail_unless (have_eos == TRUE); + fail_unless (have_data == TRUE); + + gst_element_set_state (parsetest, GST_STATE_NULL); + + check_no_error_received (); + cleanup_parsertest (); + + g_main_loop_unref (loop); + loop = NULL; +} + +GST_END_TEST; + +static void +baseparse_setup (void) +{ + /* init/reset global state */ + mysrcpad = mysinkpad = NULL; + parsetest = NULL; + bus = NULL; + loop = NULL; + have_eos = have_data = caps_set = FALSE; + buffer_count = 0; +} + +static void +baseparse_teardown (void) +{ +} + +static Suite * +gst_baseparse_suite (void) +{ + Suite *s = suite_create ("GstBaseParse"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_checked_fixture (tc, baseparse_setup, baseparse_teardown); + tcase_add_test (tc, parser_playback); + tcase_add_test (tc, parser_empty_stream); + tcase_add_test (tc, parser_reverse_playback_on_passthrough); + tcase_add_test (tc, parser_reverse_playback); + + return s; +} + +GST_CHECK_MAIN (gst_baseparse); diff --git a/tests/check/libs/basesink.c b/tests/check/libs/basesink.c new file mode 100644 index 0000000..5415d70 --- /dev/null +++ b/tests/check/libs/basesink.c @@ -0,0 +1,301 @@ +/* GStreamer + * + * Copyright (C) 2010 Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +GST_START_TEST (basesink_last_sample_enabled) +{ + GstElement *src, *sink, *pipeline; + GstBus *bus; + GstMessage *msg; + GstSample *last_sample; + + pipeline = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink) == TRUE); + fail_unless (gst_element_link (src, sink) == TRUE); + + bus = gst_element_get_bus (pipeline); + + /* try with enable-last-sample set to TRUE */ + g_object_set (src, "num-buffers", 1, NULL); + fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) + != GST_STATE_CHANGE_FAILURE); + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); + + /* last-sample should be != NULL */ + fail_unless (gst_base_sink_is_last_sample_enabled (GST_BASE_SINK (sink)) + == TRUE); + g_object_get (sink, "last-sample", &last_sample, NULL); + fail_unless (last_sample != NULL); + gst_sample_unref (last_sample); + + /* set enable-last-sample to FALSE now, this should set last-sample to NULL */ + g_object_set (sink, "enable-last-sample", FALSE, NULL); + fail_unless (gst_base_sink_is_last_sample_enabled (GST_BASE_SINK (sink)) + == FALSE); + g_object_get (sink, "last-sample", &last_sample, NULL); + fail_unless (last_sample == NULL); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + GST_INFO ("stopped"); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (basesink_last_sample_disabled) +{ + GstElement *src, *sink, *pipeline; + GstBus *bus; + GstMessage *msg; + GstSample *last_sample; + + pipeline = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink) == TRUE); + fail_unless (gst_element_link (src, sink) == TRUE); + + bus = gst_element_get_bus (pipeline); + + /* set enable-last-sample to FALSE */ + g_object_set (src, "num-buffers", 1, NULL); + gst_base_sink_set_last_sample_enabled (GST_BASE_SINK (sink), FALSE); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); + + /* last-sample should be NULL */ + g_object_get (sink, "last-sample", &last_sample, NULL); + fail_unless (last_sample == NULL); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + GST_INFO ("stopped"); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (basesink_test_gap) +{ + GstElement *sink, *pipeline; + GstPad *pad; + GstBus *bus; + GstMessage *msg; + GstEvent *ev; + GstSegment segment; + + pipeline = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (sink, "sync", TRUE, NULL); + + pad = gst_element_get_static_pad (sink, "sink"); + + fail_unless (gst_bin_add (GST_BIN (pipeline), sink) == TRUE); + + bus = gst_element_get_bus (pipeline); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.stop = 120 * GST_SECOND; + ev = gst_event_new_segment (&segment); + + fail_unless (gst_pad_send_event (pad, ev)); + + ev = gst_event_new_gap (200 * GST_MSECOND, GST_CLOCK_TIME_NONE); + fail_unless (gst_pad_send_event (pad, ev)); + + ev = gst_event_new_eos (); + fail_unless (gst_pad_send_event (pad, ev)); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + GST_INFO ("stopped"); + + gst_object_unref (pad); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static gpointer +send_eos_event (gpointer data) +{ + GstPad *pad = data; + GstEvent *ev; + GstSegment segment; + + ev = gst_event_new_stream_start ("test"); + fail_unless (gst_pad_send_event (pad, ev)); + + gst_segment_init (&segment, GST_FORMAT_TIME); + ev = gst_event_new_segment (&segment); + fail_unless (gst_pad_send_event (pad, ev)); + + ev = gst_event_new_eos (); + gst_pad_send_event (pad, ev); + + return NULL; +} + +GST_START_TEST (basesink_test_eos_after_playing) +{ + GstElement *pipeline, *sink; + GstPad *pad; + GstBus *bus; + GstMessage *msg; + GThread *thread; + gboolean reached_playing = FALSE; + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (sink, "sync", TRUE, NULL); + pipeline = gst_pipeline_new (NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + pad = gst_element_get_static_pad (sink, "sink"); + + bus = gst_element_get_bus (pipeline); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + thread = g_thread_new ("push-thread", send_eos_event, pad); + + while ((msg = gst_bus_timed_pop (bus, -1))) { + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STATE_CHANGED + && GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) { + GstState new_state; + + gst_message_parse_state_changed (msg, NULL, &new_state, NULL); + if (new_state == GST_STATE_PLAYING) + reached_playing = TRUE; + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) { + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) { + fail_unless (reached_playing); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_message_unref (msg); + break; + } + + gst_message_unref (msg); + } + + g_thread_join (thread); + + gst_object_unref (pad); + gst_object_unref (bus); + gst_object_unref (pipeline); + + GST_INFO ("stopped"); +} + +GST_END_TEST; + + +GST_START_TEST (basesink_position_query_handles_segment_offset) +{ + GstElement *pipeline, *sink; + GstPad *pad; + GstEvent *ev; + GstSegment segment; + gint64 position; + + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (sink, "async", FALSE, "sync", TRUE, NULL); + pad = gst_element_get_static_pad (sink, "sink"); + + pipeline = gst_pipeline_new (NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + ev = gst_event_new_stream_start ("test"); + fail_unless (gst_pad_send_event (pad, ev)); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.offset = 15000; + ev = gst_event_new_segment (&segment); + fail_unless (gst_pad_send_event (pad, ev)); + + fail_unless (gst_element_query_position (pipeline, GST_FORMAT_TIME, + &position)); + fail_unless_equals_int (position, 15000); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + gst_object_unref (pad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +gst_basesrc_suite (void) +{ + Suite *s = suite_create ("GstBaseSink"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_test (tc, basesink_last_sample_enabled); + tcase_add_test (tc, basesink_last_sample_disabled); + tcase_add_test (tc, basesink_test_gap); + tcase_add_test (tc, basesink_test_eos_after_playing); + tcase_add_test (tc, basesink_position_query_handles_segment_offset); + + return s; +} + +GST_CHECK_MAIN (gst_basesrc); diff --git a/tests/check/libs/basesrc.c b/tests/check/libs/basesrc.c new file mode 100644 index 0000000..ee360ce --- /dev/null +++ b/tests/check/libs/basesrc.c @@ -0,0 +1,927 @@ +/* GStreamer + * + * some unit tests for GstBaseSrc + * + * Copyright (C) 2006-2017 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +static GstPadProbeReturn +eos_event_counter (GstObject * pad, GstPadProbeInfo * info, guint * p_num_eos) +{ + GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); + + fail_unless (event != NULL); + fail_unless (GST_IS_EVENT (event)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) + *p_num_eos += 1; + + return GST_PAD_PROBE_OK; +} + +/* basesrc_eos_events_push_live_op: + * - make sure source does send an EOS event when operating in push + * mode and being set to READY explicitly (like one might with + * live sources) + */ +GST_START_TEST (basesrc_eos_events_push_live_op) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *srcpad; + guint probe, num_eos = 0; + GstStreamConsistency *consistency; + GstEvent *eos_event; + guint32 eos_event_seqnum; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", TRUE, NULL); + g_object_set (sink, "can-activate-pull", FALSE, NULL); + + g_object_set (src, "can-activate-push", TRUE, NULL); + g_object_set (src, "can-activate-pull", FALSE, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + consistency = gst_consistency_checker_new (srcpad); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + bus = gst_element_get_bus (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* wait a second, then do controlled shutdown */ + g_usleep (GST_USECOND * 1); + + /* shut down pipeline (should send EOS message) ... */ + eos_event = gst_event_new_eos (); + eos_event_seqnum = gst_event_get_seqnum (eos_event); + gst_element_send_event (pipe, eos_event); + + /* ... and wait for the EOS message from the sink */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* should be exactly one EOS event */ + fail_unless (num_eos == 1); + fail_unless (gst_message_get_seqnum (msg) == eos_event_seqnum); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent a second one when going PAUSED => READY */ + fail_unless (num_eos == 1); + + gst_consistency_checker_free (consistency); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + + + +/* basesrc_eos_events_push: + * - make sure source only sends one EOS when operating in push-mode, + * reaching the max number of buffers, and is then shut down. + */ +GST_START_TEST (basesrc_eos_events_push) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *srcpad; + guint probe, num_eos = 0; + GstStreamConsistency *consistency; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", TRUE, NULL); + g_object_set (sink, "can-activate-pull", FALSE, NULL); + + g_object_set (src, "can-activate-push", TRUE, NULL); + g_object_set (src, "can-activate-pull", FALSE, NULL); + g_object_set (src, "num-buffers", 8, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + consistency = gst_consistency_checker_new (srcpad); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + bus = gst_element_get_bus (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* should be exactly one EOS event */ + fail_unless (num_eos == 1); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent a second one when going PAUSED => READY */ + fail_unless (num_eos == 1); + + gst_consistency_checker_free (consistency); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + +/* basesrc_eos_events_pull_live_op: + * - make sure source doesn't send an EOS event when operating in + * pull mode and being set to READY explicitly (like one might with + * live sources) + */ +GST_START_TEST (basesrc_eos_events_pull_live_op) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstPad *srcpad; + guint probe, num_eos = 0; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", FALSE, NULL); + g_object_set (sink, "can-activate-pull", TRUE, NULL); + + g_object_set (src, "can-activate-push", FALSE, NULL); + g_object_set (src, "can-activate-pull", TRUE, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* wait a second, then do controlled shutdown */ + g_usleep (GST_USECOND * 1); + + /* shut down source only ... */ + gst_element_set_state (src, GST_STATE_NULL); + state_ret = gst_element_get_state (src, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + fail_unless (gst_element_set_locked_state (src, TRUE) == TRUE); + + /* source shouldn't have sent any EOS event in pull mode */ + fail_unless (num_eos == 0); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent an EOS when going PAUSED => READY either */ + fail_unless (num_eos == 0); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_object_unref (pipe); +} + +GST_END_TEST; + +/* basesrc_eos_events_pull: + * - makes sure source doesn't send EOS event when reaching the max. + * number of buffers configured in pull-mode + * - make sure source doesn't send EOS event either when being shut down + * (PAUSED => READY state change) after EOSing in pull mode + */ +GST_START_TEST (basesrc_eos_events_pull) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *srcpad; + guint probe, num_eos = 0; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", FALSE, NULL); + g_object_set (sink, "can-activate-pull", TRUE, NULL); + + g_object_set (src, "can-activate-push", FALSE, NULL); + g_object_set (src, "can-activate-pull", TRUE, NULL); + g_object_set (src, "num-buffers", 8, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + bus = gst_element_get_bus (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* source shouldn't have sent any EOS event in pull mode */ + fail_unless (num_eos == 0); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent an EOS when going PAUSED => READY either */ + fail_unless (num_eos == 0); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + + +/* basesrc_eos_events_push_live_eos: + * - make sure the source stops and emits EOS when we send an EOS event to the + * pipeline. + */ +GST_START_TEST (basesrc_eos_events_push_live_eos) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *srcpad; + guint probe, num_eos = 0; + gboolean res; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", TRUE, NULL); + g_object_set (sink, "can-activate-pull", FALSE, NULL); + + g_object_set (src, "can-activate-push", TRUE, NULL); + g_object_set (src, "can-activate-pull", FALSE, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + bus = gst_element_get_bus (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* wait a second, then emit the EOS */ + g_usleep (GST_USECOND * 1); + + /* shut down source only (should send EOS event) ... */ + res = gst_element_send_event (pipe, gst_event_new_eos ()); + fail_unless (res == TRUE); + + /* ... and wait for the EOS message from the sink */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* should be exactly one EOS event */ + fail_unless (num_eos == 1); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent a second one when going PAUSED => READY */ + fail_unless (num_eos == 1); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + +/* basesrc_eos_events_pull_live_eos: + * - make sure the source stops and emits EOS when we send an EOS event to the + * pipeline. + */ +GST_START_TEST (basesrc_eos_events_pull_live_eos) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *srcpad; + guint probe, num_eos = 0; + gboolean res; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + g_object_set (sink, "can-activate-push", FALSE, NULL); + g_object_set (sink, "can-activate-pull", TRUE, NULL); + + g_object_set (src, "can-activate-push", FALSE, NULL); + g_object_set (src, "can-activate-pull", TRUE, NULL); + + /* set up event probe to count EOS events */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad != NULL); + + probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) eos_event_counter, &num_eos, NULL); + + bus = gst_element_get_bus (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* wait a second, then emit the EOS */ + g_usleep (GST_USECOND * 1); + + /* shut down source only (should send EOS event) ... */ + res = gst_element_send_event (pipe, gst_event_new_eos ()); + fail_unless (res == TRUE); + + /* ... and wait for the EOS message from the sink */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* no EOS in pull mode */ + fail_unless (num_eos == 0); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + /* make sure source hasn't sent a second one when going PAUSED => READY */ + fail_unless (num_eos == 0); + + gst_pad_remove_probe (srcpad, probe); + gst_object_unref (srcpad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + + +static GstPadProbeReturn +segment_event_catcher (GstObject * pad, GstPadProbeInfo * info, + gpointer * user_data) +{ + GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); + GstEvent **last_event = (GstEvent **) user_data; + fail_unless (event != NULL); + fail_unless (GST_IS_EVENT (event)); + fail_unless (user_data != NULL); + + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + g_mutex_lock (&check_mutex); + fail_unless (*last_event == NULL); + *last_event = gst_event_copy (event); + g_cond_signal (&check_cond); + g_mutex_unlock (&check_mutex); + } + + return GST_PAD_PROBE_OK; +} + +/* basesrc_seek_events_rate_update: + * - make sure we get expected segment after sending a seek event + */ +GST_START_TEST (basesrc_seek_events_rate_update) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *probe_pad; + guint probe; + GstEvent *seg_event = NULL; + GstEvent *rate_seek; + gboolean event_ret; + const GstSegment *segment; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + bus = gst_element_get_bus (pipe); + + /* set up event probe to catch new segment event */ + probe_pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (probe_pad != NULL); + + probe = gst_pad_add_probe (probe_pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, + (GstPadProbeCallback) segment_event_catcher, &seg_event, NULL); + + /* prepare the seek */ + rate_seek = gst_event_new_seek (0.5, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + + GST_INFO ("going to playing"); + + /* play */ + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* wait for the first segment to be posted, and flush it ... */ + g_mutex_lock (&check_mutex); + while (seg_event == NULL) + g_cond_wait (&check_cond, &check_mutex); + gst_event_unref (seg_event); + seg_event = NULL; + g_mutex_unlock (&check_mutex); + + GST_INFO ("seeking"); + + /* seek */ + event_ret = gst_element_send_event (pipe, rate_seek); + fail_unless (event_ret == TRUE); + + /* wait for the updated segment to be posted, posting EOS make the loop + * thread exit before the updated segment is posted ... */ + g_mutex_lock (&check_mutex); + while (seg_event == NULL) + g_cond_wait (&check_cond, &check_mutex); + g_mutex_unlock (&check_mutex); + + /* shut down pipeline only (should send EOS message) ... */ + gst_element_send_event (pipe, gst_event_new_eos ()); + + /* ... and wait for the EOS message from the sink */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + GST_INFO ("stopped"); + + /* check that we have go the event */ + fail_unless (seg_event != NULL); + + gst_event_parse_segment (seg_event, &segment); + fail_unless (segment->rate == 0.5); + + gst_pad_remove_probe (probe_pad, probe); + gst_object_unref (probe_pad); + gst_message_unref (msg); + gst_event_unref (seg_event); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + + +typedef struct +{ + gboolean seeked; + gint buffer_count; + GList *events; +} LastBufferSeekData; + +static GstPadProbeReturn +seek_on_buffer (GstObject * pad, GstPadProbeInfo * info, gpointer * user_data) +{ + LastBufferSeekData *data = (LastBufferSeekData *) user_data; + + fail_unless (user_data != NULL); + + if (info->type & GST_PAD_PROBE_TYPE_BUFFER) { + data->buffer_count++; + + if (!data->seeked) { + fail_unless (gst_pad_push_event (GST_PAD (pad), + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1))); + data->seeked = TRUE; + } + } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { + data->events = g_list_append (data->events, gst_event_ref (info->data)); + } else { + fail ("Should not be reached"); + } + return GST_PAD_PROBE_OK; +} + +/* basesrc_seek_on_last_buffer: + * - make sure basesrc doesn't go eos if a seek is sent + * after the last buffer push + * + * This is just a test and is a controlled environment. + * For testing purposes sending the seek from the streaming + * thread is ok but doing this in an application might not + * be a good idea. + */ +GST_START_TEST (basesrc_seek_on_last_buffer) +{ + GstStateChangeReturn state_ret; + GstElement *src, *sink, *pipe; + GstMessage *msg; + GstBus *bus; + GstPad *probe_pad; + guint probe; + GstEvent *seek; + LastBufferSeekData seek_data; + + pipe = gst_pipeline_new ("pipeline"); + sink = gst_element_factory_make ("fakesink", "sink"); + src = gst_element_factory_make ("fakesrc", "src"); + + g_assert (pipe != NULL); + g_assert (sink != NULL); + g_assert (src != NULL); + + /* use 'sizemax' buffers to avoid receiving empty buffers */ + g_object_set (src, "sizetype", 2, NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src) == TRUE); + fail_unless (gst_bin_add (GST_BIN (pipe), sink) == TRUE); + + fail_unless (gst_element_link (src, sink) == TRUE); + + bus = gst_element_get_bus (pipe); + + /* set up probe to catch the last buffer and send a seek event */ + probe_pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (probe_pad != NULL); + + seek_data.buffer_count = 0; + seek_data.seeked = FALSE; + seek_data.events = NULL; + + probe = + gst_pad_add_probe (probe_pad, + GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + (GstPadProbeCallback) seek_on_buffer, &seek_data, NULL); + + /* prepare the segment so that it has only one buffer */ + seek = gst_event_new_seek (1, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1); + + gst_element_set_state (pipe, GST_STATE_READY); + fail_unless (gst_element_send_event (src, seek)); + + GST_INFO ("going to playing"); + + /* play */ + gst_element_set_state (pipe, GST_STATE_PLAYING); + state_ret = gst_element_get_state (pipe, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + /* ... and wait for the EOS message from the sink */ + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ERROR); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_element_get_state (pipe, NULL, NULL, -1); + + GST_INFO ("stopped"); + + /* check that we have go the event */ + fail_unless (seek_data.buffer_count == 2); + fail_unless (seek_data.seeked); + + /* events: stream-start -> segment -> segment -> eos */ + fail_unless (g_list_length (seek_data.events) == 4); + { + GstEvent *event; + + event = seek_data.events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START); + gst_event_unref (event); + seek_data.events = g_list_delete_link (seek_data.events, seek_data.events); + + event = seek_data.events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + gst_event_unref (event); + seek_data.events = g_list_delete_link (seek_data.events, seek_data.events); + + event = seek_data.events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); + gst_event_unref (event); + seek_data.events = g_list_delete_link (seek_data.events, seek_data.events); + + event = seek_data.events->data; + fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS); + gst_event_unref (event); + seek_data.events = g_list_delete_link (seek_data.events, seek_data.events); + } + + gst_pad_remove_probe (probe_pad, probe); + gst_object_unref (probe_pad); + gst_message_unref (msg); + gst_object_unref (bus); + gst_object_unref (pipe); +} + +GST_END_TEST; + +typedef GstBaseSrc TestSrc; +typedef GstBaseSrcClass TestSrcClass; + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GType test_src_get_type (void); + +G_DEFINE_TYPE (TestSrc, test_src, GST_TYPE_BASE_SRC); + +static void +test_src_init (TestSrc * src) +{ +} + +static GstFlowReturn +test_src_create (GstBaseSrc * src, guint64 offset, guint size, + GstBuffer ** p_buf) +{ + GstBuffer *buf; + static int num = 0; + + fail_if (*p_buf != NULL); + + buf = gst_buffer_new (); + GST_BUFFER_OFFSET (buf) = num++; + + if (num == 1 || g_random_boolean ()) { + GstBufferList *buflist = gst_buffer_list_new (); + + gst_buffer_list_add (buflist, buf); + + buf = gst_buffer_new (); + GST_BUFFER_OFFSET (buf) = num++; + gst_buffer_list_add (buflist, buf); + gst_base_src_submit_buffer_list (src, buflist); + } else { + *p_buf = buf; + } + + return GST_FLOW_OK; +} + +static void +test_src_class_init (TestSrcClass * klass) +{ + GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + + gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass), + &src_template); + + gstbasesrc_class->create = test_src_create; +} + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#define NUM_BUFFERS 100 +static gboolean done; +static guint expect_offset; + +static GstFlowReturn +chain_____func (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GST_LOG (" buffer # %3u", (guint) GST_BUFFER_OFFSET (buf)); + + fail_unless_equals_int (GST_BUFFER_OFFSET (buf), expect_offset); + ++expect_offset; + + if (GST_BUFFER_OFFSET (buf) > NUM_BUFFERS) { + g_mutex_lock (&check_mutex); + done = TRUE; + g_cond_signal (&check_cond); + g_mutex_unlock (&check_mutex); + } + gst_buffer_unref (buf); + + return GST_FLOW_OK; +} + +static GstFlowReturn +chainlist_func (GstPad * pad, GstObject * parent, GstBufferList * list) +{ + guint i, len; + + len = gst_buffer_list_length (list); + + GST_DEBUG ("buffer list with %u buffers", len); + for (i = 0; i < len; ++i) { + GstBuffer *buf = gst_buffer_list_get (list, i); + GST_LOG (" buffer # %3u", (guint) GST_BUFFER_OFFSET (buf)); + + fail_unless_equals_int (GST_BUFFER_OFFSET (buf), expect_offset); + ++expect_offset; + } + + gst_buffer_list_unref (list); + return GST_FLOW_OK; +} + +GST_START_TEST (basesrc_create_bufferlist) +{ + GstElement *src; + + src = g_object_new (test_src_get_type (), NULL); + + mysinkpad = gst_check_setup_sink_pad (src, &sinktemplate); + gst_pad_set_chain_function (mysinkpad, chain_____func); + gst_pad_set_chain_list_function (mysinkpad, chainlist_func); + gst_pad_set_active (mysinkpad, TRUE); + + done = FALSE; + expect_offset = 0; + + gst_element_set_state (src, GST_STATE_PLAYING); + + g_mutex_lock (&check_mutex); + while (!done) + g_cond_wait (&check_cond, &check_mutex); + g_mutex_unlock (&check_mutex); + + gst_element_set_state (src, GST_STATE_NULL); + + gst_check_teardown_sink_pad (src); + + gst_object_unref (src); +} + +GST_END_TEST; + +static Suite * +gst_basesrc_suite (void) +{ + Suite *s = suite_create ("GstBaseSrc"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_test (tc, basesrc_eos_events_pull); + tcase_add_test (tc, basesrc_eos_events_push); + tcase_add_test (tc, basesrc_eos_events_push_live_op); + tcase_add_test (tc, basesrc_eos_events_pull_live_op); + tcase_add_test (tc, basesrc_eos_events_push_live_eos); + tcase_add_test (tc, basesrc_eos_events_pull_live_eos); + tcase_add_test (tc, basesrc_seek_events_rate_update); + tcase_add_test (tc, basesrc_seek_on_last_buffer); + tcase_add_test (tc, basesrc_create_bufferlist); + + return s; +} + +GST_CHECK_MAIN (gst_basesrc); diff --git a/tests/check/libs/bitreader-noinline.c b/tests/check/libs/bitreader-noinline.c new file mode 100644 index 0000000..107a9a4 --- /dev/null +++ b/tests/check/libs/bitreader-noinline.c @@ -0,0 +1,21 @@ +/* GStreamer unit test for GstBitReader without using inlining + * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#define GST_BIT_READER_DISABLE_INLINES +#include "bitreader.c" diff --git a/tests/check/libs/bitreader.c b/tests/check/libs/bitreader.c new file mode 100644 index 0000000..8910c36 --- /dev/null +++ b/tests/check/libs/bitreader.c @@ -0,0 +1,254 @@ +/* GStreamer + * + * unit test for GstBitReader + * + * Copyright (C) <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifndef fail_unless_equals_int64 +#define fail_unless_equals_int64(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GINT64_FORMAT ") is not equal to '" #b"' (%" \ + G_GINT64_FORMAT ")", first, second); \ +} G_STMT_END; +#endif + +GST_START_TEST (test_initialization) +{ + guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; + GstBuffer *buffer = gst_buffer_new (); + GstBitReader reader = GST_BIT_READER_INIT (data, 4); + GstBitReader *reader2; + guint8 x = 0; + GstMapInfo info; + + gst_buffer_insert_memory (buffer, -1, + gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, data, 4, 0, 4, NULL, + NULL)); + + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + + memset (&reader, 0, sizeof (GstBitReader)); + + gst_bit_reader_init (&reader, data, 4); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + gst_bit_reader_init (&reader, info.data, info.size); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8)); + fail_unless_equals_int (x, 0x02); + gst_buffer_unmap (buffer, &info); + + reader2 = gst_bit_reader_new (data, 4); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x02); + gst_bit_reader_free (reader2); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + reader2 = gst_bit_reader_new (info.data, info.size); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8)); + fail_unless_equals_int (x, 0x02); + gst_bit_reader_free (reader2); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +#define GET_CHECK(reader, dest, bits, nbits, val) { \ + fail_unless (gst_bit_reader_get_bits_uint##bits (reader, &dest, nbits)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, nbits, val) { \ + fail_unless (gst_bit_reader_peek_bits_uint##bits (reader, &dest, nbits)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, nbits) { \ + fail_if (gst_bit_reader_get_bits_uint##bits (reader, &dest, nbits)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, nbits) { \ + fail_if (gst_bit_reader_peek_bits_uint##bits (reader, &dest, nbits)); \ +} + +GST_START_TEST (test_get_bits) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstBitReader reader = GST_BIT_READER_INIT (data, 16); + guint8 a = 0; + guint16 b = 0; + guint32 c = 0; + guint64 d = 0; + + /* 8 bit */ + GET_CHECK (&reader, a, 8, 8, 0x12); + GET_CHECK (&reader, a, 8, 4, 0x03); + GET_CHECK (&reader, a, 8, 4, 0x04); + GET_CHECK (&reader, a, 8, 3, 0x02); + GET_CHECK (&reader, a, 8, 1, 0x01); + GET_CHECK (&reader, a, 8, 2, 0x01); + GET_CHECK (&reader, a, 8, 2, 0x02); + + PEEK_CHECK (&reader, a, 8, 8, 0x78); + PEEK_CHECK (&reader, a, 8, 8, 0x78); + fail_unless (gst_bit_reader_skip (&reader, 8)); + + PEEK_CHECK (&reader, a, 8, 8, 0x90); + GET_CHECK (&reader, a, 8, 1, 0x01); + GET_CHECK (&reader, a, 8, 1, 0x00); + GET_CHECK (&reader, a, 8, 1, 0x00); + GET_CHECK (&reader, a, 8, 1, 0x01); + fail_unless (gst_bit_reader_skip (&reader, 4)); + + fail_unless (gst_bit_reader_skip (&reader, 10 * 8)); + GET_CHECK (&reader, a, 8, 8, 0x21); + GET_CHECK_FAIL (&reader, a, 8, 1); + PEEK_CHECK_FAIL (&reader, a, 8, 1); + + /* 16 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, b, 16, 16, 0x1234); + PEEK_CHECK (&reader, b, 16, 13, 0x0acf); + GET_CHECK (&reader, b, 16, 8, 0x56); + GET_CHECK (&reader, b, 16, 4, 0x07); + GET_CHECK (&reader, b, 16, 2, 0x02); + GET_CHECK (&reader, b, 16, 2, 0x00); + PEEK_CHECK (&reader, b, 16, 8, 0x90); + fail_unless (gst_bit_reader_skip (&reader, 11 * 8)); + GET_CHECK (&reader, b, 16, 8, 0x21); + GET_CHECK_FAIL (&reader, b, 16, 16); + PEEK_CHECK_FAIL (&reader, b, 16, 16); + + /* 32 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, c, 32, 32, 0x12345678); + GET_CHECK (&reader, c, 32, 24, 0x90abcd); + GET_CHECK (&reader, c, 32, 16, 0xeffe); + GET_CHECK (&reader, c, 32, 8, 0xdc); + GET_CHECK (&reader, c, 32, 4, 0x0b); + GET_CHECK (&reader, c, 32, 2, 0x02); + GET_CHECK (&reader, c, 32, 2, 0x02); + PEEK_CHECK (&reader, c, 32, 8, 0x09); + fail_unless (gst_bit_reader_skip (&reader, 3 * 8)); + GET_CHECK (&reader, c, 32, 15, 0x2190); + GET_CHECK (&reader, c, 32, 1, 0x1); + GET_CHECK_FAIL (&reader, c, 32, 1); + + /* 64 bit */ + gst_bit_reader_init (&reader, data, 16); + + GET_CHECK (&reader, d, 64, 64, G_GINT64_CONSTANT (0x1234567890abcdef)); + GET_CHECK (&reader, d, 64, 7, 0xfe >> 1); + GET_CHECK (&reader, d, 64, 1, 0x00); + GET_CHECK (&reader, d, 64, 24, 0xdcba09); + GET_CHECK (&reader, d, 64, 32, 0x87654321); + GET_CHECK_FAIL (&reader, d, 64, 32); +} + +GST_END_TEST; + +#undef GET_CHECK +#undef PEEK_CHECK +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL + +GST_START_TEST (test_position_tracking) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstBitReader reader = GST_BIT_READER_INIT (data, 16); + guint8 a = 0; + + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 0); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8); + + fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &a, 3)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 3); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 3); + + fail_unless (gst_bit_reader_set_pos (&reader, 9)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 9); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 9); + + fail_unless (gst_bit_reader_skip (&reader, 3)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 12); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 12); + + fail_unless (gst_bit_reader_skip_to_byte (&reader)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 16); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 16 * 8 - 16); + + fail_unless (gst_bit_reader_set_pos (&reader, 16 * 8)); + fail_unless_equals_int (gst_bit_reader_get_pos (&reader), 16 * 8); + fail_unless_equals_int (gst_bit_reader_get_remaining (&reader), 0); + + fail_unless (gst_bit_reader_skip (&reader, 0)); + fail_if (gst_bit_reader_skip (&reader, 1)); + fail_unless (gst_bit_reader_skip_to_byte (&reader)); +} + +GST_END_TEST; + +static Suite * +gst_bit_reader_suite (void) +{ + Suite *s = suite_create ("GstBitReader"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_initialization); + tcase_add_test (tc_chain, test_get_bits); + tcase_add_test (tc_chain, test_position_tracking); + + return s; +} + + +GST_CHECK_MAIN (gst_bit_reader); diff --git a/tests/check/libs/bytereader-noinline.c b/tests/check/libs/bytereader-noinline.c new file mode 100644 index 0000000..8200128 --- /dev/null +++ b/tests/check/libs/bytereader-noinline.c @@ -0,0 +1,21 @@ +/* GStreamer unit test for GstByteReader without using inlining + * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#define GST_BYTE_READER_DISABLE_INLINES +#include "bytereader.c" diff --git a/tests/check/libs/bytereader.c b/tests/check/libs/bytereader.c new file mode 100644 index 0000000..24a2971 --- /dev/null +++ b/tests/check/libs/bytereader.c @@ -0,0 +1,846 @@ +/* GStreamer + * + * unit test for GstByteReader + * + * Copyright (C) <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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifndef fail_unless_equals_int64 +#define fail_unless_equals_int64(a, b) \ +G_STMT_START { \ + gint64 first = a; \ + gint64 second = b; \ + fail_unless(first == second, \ + "'" #a "' (%" G_GINT64_FORMAT ") is not equal to '" #b"' (%" \ + G_GINT64_FORMAT ")", first, second); \ +} G_STMT_END; +#endif + +GST_START_TEST (test_initialization) +{ + guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; + GstBuffer *buffer = gst_buffer_new (); + GstByteReader reader = GST_BYTE_READER_INIT (data, 4); + GstByteReader *reader2; + guint8 x = 0; + GstMapInfo info; + + gst_buffer_insert_memory (buffer, -1, + gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, data, 4, 0, 4, NULL, + NULL)); + + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + + memset (&reader, 0, sizeof (GstByteReader)); + + gst_byte_reader_init (&reader, data, 4); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + gst_byte_reader_init (&reader, info.data, info.size); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0x02); + gst_buffer_unmap (buffer, &info); + + reader2 = gst_byte_reader_new (data, 4); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x02); + gst_byte_reader_free (reader2); + + fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ)); + reader2 = gst_byte_reader_new (info.data, info.size); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x01); + fail_unless (gst_byte_reader_get_uint8 (reader2, &x)); + fail_unless_equals_int (x, 0x02); + gst_byte_reader_free (reader2); + gst_buffer_unmap (buffer, &info); + + gst_buffer_unref (buffer); +} + +GST_END_TEST; + +#define GET_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_get_uint8 (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_uint##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define GET_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_get_uint8 (reader, &dest)); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_uint##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_peek_uint8 (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_uint##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_uint64 (dest, val); \ +} + +#define PEEK_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_peek_uint8 (reader, &dest)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_uint##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_uint_le) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a = 0; + guint16 b = 0; + guint32 c = 0; + guint64 d = 0; + + GET_CHECK8 (&reader, a, 0x12); + GET_CHECK (&reader, b, 16, le, 0x5634); + GET_CHECK (&reader, c, 24, le, 0xab9078); + GET_CHECK (&reader, c, 32, le, 0xdcfeefcd); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0xefcdab9078563412)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0x2143658709badcfe)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, le); + GET_CHECK_FAIL (&reader, c, 24, le); + GET_CHECK_FAIL (&reader, c, 32, le); + GET_CHECK_FAIL (&reader, d, 64, le); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, 0x12); + PEEK_CHECK (&reader, b, 16, le, 0x3412); + PEEK_CHECK (&reader, c, 24, le, 0x563412); + PEEK_CHECK (&reader, c, 32, le, 0x78563412); + PEEK_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (0xefcdab9078563412)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, le); + PEEK_CHECK_FAIL (&reader, c, 24, le); + PEEK_CHECK_FAIL (&reader, c, 32, le); + PEEK_CHECK_FAIL (&reader, d, 64, le); +} + +GST_END_TEST; + +GST_START_TEST (test_get_uint_be) +{ + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a = 0; + guint16 b = 0; + guint32 c = 0; + guint64 d = 0; + + GET_CHECK8 (&reader, a, 0x12); + GET_CHECK (&reader, b, 16, be, 0x3456); + GET_CHECK (&reader, c, 24, be, 0x7890ab); + GET_CHECK (&reader, c, 32, be, 0xcdeffedc); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0x1234567890abcdef)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0xfedcba0987654321)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, be); + GET_CHECK_FAIL (&reader, c, 24, be); + GET_CHECK_FAIL (&reader, c, 32, be); + GET_CHECK_FAIL (&reader, d, 64, be); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, 0x12); + PEEK_CHECK (&reader, b, 16, be, 0x1234); + PEEK_CHECK (&reader, c, 24, be, 0x123456); + PEEK_CHECK (&reader, c, 32, be, 0x12345678); + PEEK_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (0x1234567890abcdef)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, be); + PEEK_CHECK_FAIL (&reader, c, 24, be); + PEEK_CHECK_FAIL (&reader, c, 32, be); + PEEK_CHECK_FAIL (&reader, d, 64, be); +} + +GST_END_TEST; + +#undef GET_CHECK8 +#undef GET_CHECK +#undef PEEK_CHECK8 +#undef PEEK_CHECK +#undef GET_CHECK_FAIL8 +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL8 +#undef PEEK_CHECK_FAIL + +#define GET_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_get_int8 (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_int##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define GET_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_get_int8 (reader, &dest)); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_int##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK8(reader, dest, val) { \ + fail_unless (gst_byte_reader_peek_int8 (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_int##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_int64 (dest, val); \ +} + +#define PEEK_CHECK_FAIL8(reader, dest) { \ + fail_if (gst_byte_reader_peek_int8 (reader, &dest)); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_int##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_int_le) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + gint8 a = 0; + gint16 b = 0; + gint32 c = 0; + gint64 d = 0; + + GET_CHECK8 (&reader, a, -1); + GET_CHECK (&reader, b, 16, le, -1); + GET_CHECK (&reader, c, 24, le, -1); + GET_CHECK (&reader, c, 32, le, -1); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + GET_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, le); + GET_CHECK_FAIL (&reader, c, 24, le); + GET_CHECK_FAIL (&reader, c, 32, le); + GET_CHECK_FAIL (&reader, d, 64, le); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, -1); + PEEK_CHECK (&reader, b, 16, le, -1); + PEEK_CHECK (&reader, c, 24, le, -1); + PEEK_CHECK (&reader, c, 32, le, -1); + PEEK_CHECK (&reader, d, 64, le, G_GINT64_CONSTANT (-1)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, le); + PEEK_CHECK_FAIL (&reader, c, 24, le); + PEEK_CHECK_FAIL (&reader, c, 32, le); + PEEK_CHECK_FAIL (&reader, d, 64, le); + +} + +GST_END_TEST; + +GST_START_TEST (test_get_int_be) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + gint8 a = 0; + gint16 b = 0; + gint32 c = 0; + gint64 d = 0; + + GET_CHECK8 (&reader, a, -1); + GET_CHECK (&reader, b, 16, be, -1); + GET_CHECK (&reader, c, 24, be, -1); + GET_CHECK (&reader, c, 32, be, -1); + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + GET_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + + GET_CHECK_FAIL8 (&reader, a); + GET_CHECK_FAIL (&reader, b, 16, be); + GET_CHECK_FAIL (&reader, c, 24, be); + GET_CHECK_FAIL (&reader, c, 32, be); + GET_CHECK_FAIL (&reader, d, 64, be); + + fail_unless (gst_byte_reader_set_pos (&reader, 0)); + + PEEK_CHECK8 (&reader, a, -1); + PEEK_CHECK (&reader, b, 16, be, -1); + PEEK_CHECK (&reader, c, 24, be, -1); + PEEK_CHECK (&reader, c, 32, be, -1); + PEEK_CHECK (&reader, d, 64, be, G_GINT64_CONSTANT (-1)); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + PEEK_CHECK_FAIL8 (&reader, a); + PEEK_CHECK_FAIL (&reader, b, 16, be); + PEEK_CHECK_FAIL (&reader, c, 24, be); + PEEK_CHECK_FAIL (&reader, c, 32, be); + PEEK_CHECK_FAIL (&reader, d, 64, be); + +} + +GST_END_TEST; + +#undef GET_CHECK8 +#undef GET_CHECK +#undef PEEK_CHECK8 +#undef PEEK_CHECK +#undef GET_CHECK_FAIL8 +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL8 +#undef PEEK_CHECK_FAIL + +#define GET_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_get_float##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_float (dest, val); \ +} + +#define GET_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_get_float##bits##_##endianness (reader, &dest)); \ +} + +#define PEEK_CHECK(reader, dest, bits, endianness, val) { \ + fail_unless (gst_byte_reader_peek_float##bits##_##endianness (reader, &dest)); \ + fail_unless_equals_float (dest, val); \ +} + +#define PEEK_CHECK_FAIL(reader, dest, bits, endianness) { \ + fail_if (gst_byte_reader_peek_float##bits##_##endianness (reader, &dest)); \ +} + +GST_START_TEST (test_get_float_le) +{ + guint8 data[] = { + 0x00, 0x00, 0x80, 0x3f, + 0x00, 0x00, 0x80, 0xbf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 24); + gfloat a = 0.0; + gdouble b = 0.0; + + PEEK_CHECK (&reader, a, 32, le, 1.0); + GET_CHECK (&reader, a, 32, le, 1.0); + GET_CHECK (&reader, a, 32, le, -1.0); + PEEK_CHECK (&reader, b, 64, le, 1.0); + GET_CHECK (&reader, b, 64, le, 1.0); + GET_CHECK (&reader, b, 64, le, -1.0); + GET_CHECK_FAIL (&reader, a, 32, le); + GET_CHECK_FAIL (&reader, b, 64, le); + PEEK_CHECK_FAIL (&reader, a, 32, le); + PEEK_CHECK_FAIL (&reader, b, 64, le); +} + +GST_END_TEST; + +GST_START_TEST (test_get_float_be) +{ + guint8 data[] = { + 0x3f, 0x80, 0x00, 0x00, + 0xbf, 0x80, 0x00, 0x00, + 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 24); + gfloat a = 0.0; + gdouble b = 0.0; + + PEEK_CHECK (&reader, a, 32, be, 1.0); + GET_CHECK (&reader, a, 32, be, 1.0); + GET_CHECK (&reader, a, 32, be, -1.0); + PEEK_CHECK (&reader, b, 64, be, 1.0); + GET_CHECK (&reader, b, 64, be, 1.0); + GET_CHECK (&reader, b, 64, be, -1.0); + GET_CHECK_FAIL (&reader, a, 32, be); + GET_CHECK_FAIL (&reader, b, 64, be); + PEEK_CHECK_FAIL (&reader, a, 32, be); + PEEK_CHECK_FAIL (&reader, b, 64, be); +} + +GST_END_TEST; + +#undef GET_CHECK +#undef PEEK_CHECK +#undef GET_CHECK_FAIL +#undef PEEK_CHECK_FAIL + +GST_START_TEST (test_position_tracking) +{ + guint8 data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + GstByteReader reader = GST_BYTE_READER_INIT (data, 16); + guint8 a = 0; + + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 0); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16); + + fail_unless (gst_byte_reader_get_uint8 (&reader, &a)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 1); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 1); + + fail_unless (gst_byte_reader_set_pos (&reader, 8)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 8); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 8); + + fail_unless (gst_byte_reader_skip (&reader, 4)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 12); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16 - 12); + + fail_unless (gst_byte_reader_set_pos (&reader, 16)); + fail_unless_equals_int (gst_byte_reader_get_pos (&reader), 16); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 0); + + fail_unless (gst_byte_reader_skip (&reader, 0)); + fail_if (gst_byte_reader_skip (&reader, 1)); +} + +GST_END_TEST; + +#define do_scan(r,m,p,o,s,x) \ +G_STMT_START { \ + fail_unless_equals_int (gst_byte_reader_masked_scan_uint32 (r,m,p,o,s), x); \ + if (x != -1) { \ + guint32 v, res_v; \ + const guint8 *rdata = NULL; \ + fail_unless (gst_byte_reader_peek_data (r, x + 4, &rdata)); \ + res_v = GST_READ_UINT32_BE (rdata + x); \ + fail_unless_equals_int (gst_byte_reader_masked_scan_uint32_peek (r,m,p,o,s,&v), x); \ + fail_unless_equals_int (v, res_v); \ + } \ +} G_STMT_END; + +GST_START_TEST (test_scan) +{ + GstByteReader reader; + guint8 data[200]; + guint i; + + /* fill half the buffer with a pattern */ + for (i = 0; i < 100; i++) + data[i] = i; + + gst_byte_reader_init (&reader, data, 100); + + /* find first bytes */ + do_scan (&reader, 0xffffffff, 0x00010203, 0, 100, 0); + do_scan (&reader, 0xffffffff, 0x01020304, 0, 100, 1); + do_scan (&reader, 0xffffffff, 0x01020304, 1, 99, 1); + /* offset is past the pattern start */ + do_scan (&reader, 0xffffffff, 0x01020304, 2, 98, -1); + /* not enough bytes to find the pattern */ + do_scan (&reader, 0xffffffff, 0x02030405, 2, 3, -1); + do_scan (&reader, 0xffffffff, 0x02030405, 2, 4, 2); + /* size does not include the last scanned byte */ + do_scan (&reader, 0xffffffff, 0x40414243, 0, 0x41, -1); + do_scan (&reader, 0xffffffff, 0x40414243, 0, 0x43, -1); + do_scan (&reader, 0xffffffff, 0x40414243, 0, 0x44, 0x40); + /* past the start */ + do_scan (&reader, 0xffffffff, 0x40414243, 65, 10, -1); + do_scan (&reader, 0xffffffff, 0x40414243, 64, 5, 64); + do_scan (&reader, 0xffffffff, 0x60616263, 65, 35, 0x60); + do_scan (&reader, 0xffffffff, 0x60616263, 0x60, 4, 0x60); + /* past the start */ + do_scan (&reader, 0xffffffff, 0x60616263, 0x61, 3, -1); + do_scan (&reader, 0xffffffff, 0x60616263, 99, 1, -1); + + /* add more data to the buffer */ + for (i = 100; i < 200; i++) + data[i] = i; + gst_byte_reader_init (&reader, data, 200); + + /* past the start */ + do_scan (&reader, 0xffffffff, 0x60616263, 0x61, 6, -1); + /* this should work */ + do_scan (&reader, 0xffffffff, 0x61626364, 0x61, 4, 0x61); + /* not enough data */ + do_scan (&reader, 0xffffffff, 0x62636465, 0x61, 4, -1); + do_scan (&reader, 0xffffffff, 0x62636465, 0x61, 5, 0x62); + do_scan (&reader, 0xffffffff, 0x62636465, 0, 120, 0x62); + + /* border conditions */ + do_scan (&reader, 0xffffffff, 0x62636465, 0, 200, 0x62); + do_scan (&reader, 0xffffffff, 0x63646566, 0, 200, 0x63); + /* we completely searched the first list */ + do_scan (&reader, 0xffffffff, 0x64656667, 0, 200, 0x64); + /* skip first buffer */ + do_scan (&reader, 0xffffffff, 0x64656667, 0x64, 100, 0x64); + /* past the start */ + do_scan (&reader, 0xffffffff, 0x64656667, 0x65, 10, -1); + /* not enough data to scan */ + do_scan (&reader, 0xffffffff, 0x64656667, 0x63, 4, -1); + do_scan (&reader, 0xffffffff, 0x64656667, 0x63, 5, 0x64); + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0, 199, -1); + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0x62, 102, 0xc4); + /* different masks */ + do_scan (&reader, 0x00ffffff, 0x00656667, 0x64, 100, 0x64); + do_scan (&reader, 0x000000ff, 0x00000000, 0, 100, -1); + do_scan (&reader, 0x000000ff, 0x00000003, 0, 100, 0); + do_scan (&reader, 0x000000ff, 0x00000061, 0x61, 100, -1); + do_scan (&reader, 0xff000000, 0x61000000, 0, 0x62, -1); + /* does not even exist */ + do_scan (&reader, 0x00ffffff, 0xffffffff, 0x65, 99, -1); + + /* flush some bytes */ + fail_unless (gst_byte_reader_skip (&reader, 0x20)); + + do_scan (&reader, 0xffffffff, 0x20212223, 0, 100, 0); + do_scan (&reader, 0xffffffff, 0x20212223, 0, 4, 0); + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0x62, 70, 0xa4); + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0, 168, 0xa4); + + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 164, 4, 0xa4); + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0x44, 100, 0xa4); + + /* not enough bytes */ + do_scan (&reader, 0xffffffff, 0xc4c5c6c7, 0x44, 99, -1); + + /* check special code path that exists for 00 00 01 sync marker */ + { + const guint8 sync_data[] = { 0xA0, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0x00, 0x00, 0x00, 0x01, 0xAF, 0xB0, 0xB1 + }; + guint32 val = 0; + guint8 *m; + gint found; + + /* dup so valgrind can detect out of bounds access more easily */ + m = g_memdup (sync_data, sizeof (sync_data)); + gst_byte_reader_init (&reader, m, sizeof (sync_data)); + + found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00, + 0x00000100, 0, sizeof (sync_data), &val); + fail_unless_equals_int (found, 2); + fail_unless_equals_int (val, 0x000001A5); + + found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00, + 0x00000100, 2, sizeof (sync_data) - 2, &val); + fail_unless_equals_int (found, 2); + fail_unless_equals_int (val, 0x000001A5); + + found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00, + 0x00000100, 3, sizeof (sync_data) - 3, &val); + fail_unless_equals_int (found, 12); + fail_unless_equals_int (val, 0x000001AF); + + found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00, + 0x00000100, 12, sizeof (sync_data) - 12, &val); + fail_unless_equals_int (found, 12); + fail_unless_equals_int (val, 0x000001AF); + + found = gst_byte_reader_masked_scan_uint32_peek (&reader, 0xffffff00, + 0x00000100, 13, sizeof (sync_data) - 13, &val); + fail_unless_equals_int (found, -1); + + g_free (m); + } +} + +GST_END_TEST; + +GST_START_TEST (test_string_funcs) +{ + GstByteReader reader, backup; + const gchar *s8; + guint32 *c32; + guint16 *c16; + gchar *c8; + guint8 data[200], *d = 0; + guint i; + + /* fill half the buffer with a pattern */ + for (i = 0; i < 100; i++) + data[i] = i + 1; + + gst_byte_reader_init (&reader, data, 100); + + /* no NUL terminator, so these should all fail */ + fail_if (gst_byte_reader_get_string (&reader, &s8)); + fail_if (gst_byte_reader_get_string_utf8 (&reader, &s8)); + fail_if (gst_byte_reader_dup_string (&reader, &c8)); + fail_if (gst_byte_reader_dup_string_utf8 (&reader, &c8)); + fail_if (gst_byte_reader_skip_string (&reader)); + fail_if (gst_byte_reader_skip_string_utf8 (&reader)); + fail_if (gst_byte_reader_skip_string_utf16 (&reader)); + fail_if (gst_byte_reader_skip_string_utf32 (&reader)); + fail_if (gst_byte_reader_peek_string (&reader, &s8)); + fail_if (gst_byte_reader_peek_string_utf8 (&reader, &s8)); + fail_if (gst_byte_reader_dup_string_utf16 (&reader, &c16)); + fail_if (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + + /* let's add a single NUL terminator */ + data[80] = '\0'; + backup = reader; + fail_if (gst_byte_reader_skip_string_utf32 (&reader)); + fail_if (gst_byte_reader_skip_string_utf16 (&reader)); + fail_if (gst_byte_reader_dup_string_utf16 (&reader, &c16)); + fail_if (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + fail_unless (gst_byte_reader_skip_string (&reader)); + reader = backup; + fail_unless (gst_byte_reader_skip_string_utf8 (&reader)); + reader = backup; + fail_unless (gst_byte_reader_peek_string (&reader, &s8)); + fail_unless (gst_byte_reader_peek_string_utf8 (&reader, &s8)); + fail_if (gst_byte_reader_dup_string_utf16 (&reader, &c16)); + fail_if (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + + /* let's add another NUL terminator */ + data[81] = '\0'; + reader = backup; + fail_if (gst_byte_reader_skip_string_utf32 (&reader)); + fail_if (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + fail_unless (gst_byte_reader_skip_string_utf16 (&reader)); + reader = backup; + fail_unless (gst_byte_reader_dup_string_utf16 (&reader, &c16)); + g_free (c16); + reader = backup; + fail_unless (gst_byte_reader_skip_string (&reader)); + reader = backup; + fail_unless (gst_byte_reader_skip_string_utf8 (&reader)); + reader = backup; + fail_unless (gst_byte_reader_peek_string (&reader, &s8)); + fail_unless (gst_byte_reader_peek_string_utf8 (&reader, &s8)); + fail_if (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + + /* two more NUL terminators */ + data[79] = '\0'; + data[82] = '\0'; + reader = backup; + /* we're at pos. 80 now, so have only 3 NUL terminators in front of us */ + fail_if (gst_byte_reader_skip_string_utf32 (&reader)); + /* let's rewind */ + gst_byte_reader_init (&reader, data, 100); + backup = reader; + /* oops, 79 is not dividable by 4, so not aligned, so should fail as well! */ + fail_if (gst_byte_reader_skip_string_utf32 (&reader)); + /* let's try that again */ + data[83] = '\0'; + gst_byte_reader_init (&reader, data, 100); + backup = reader; + fail_unless (gst_byte_reader_skip_string_utf16 (&reader)); + reader = backup; + fail_unless (gst_byte_reader_skip_string (&reader)); + reader = backup; + fail_unless (gst_byte_reader_skip_string_utf8 (&reader)); + reader = backup; + fail_unless (gst_byte_reader_peek_string (&reader, &s8)); + fail_unless (gst_byte_reader_peek_string_utf8 (&reader, &s8)); + fail_unless (gst_byte_reader_dup_string_utf16 (&reader, &c16)); + g_free (c16); + reader = backup; + fail_unless (gst_byte_reader_dup_string_utf32 (&reader, &c32)); + g_free (c32); + + /* and again from the start */ + gst_byte_reader_init (&reader, data, 100); + fail_unless (gst_byte_reader_skip_string_utf16 (&reader)); + fail_if (gst_byte_reader_dup_data (&reader, 200, &d)); + fail_if (gst_byte_reader_dup_data (&reader, 100, &d)); + fail_if (gst_byte_reader_dup_data (&reader, 20, &d)); + fail_unless (gst_byte_reader_dup_data (&reader, 10, &d)); + fail_unless_equals_int (d[0], 0); + fail_unless_equals_int (d[1], 0); + fail_unless_equals_int (d[2], 85); + fail_unless_equals_int (d[3], 86); + g_free (d); +} + +GST_END_TEST; + +GST_START_TEST (test_dup_string) +{ + const gchar moredata[] = { 0x99, 0x10, 'f', '0', '0', '!', '\0', 0xff }; + GstByteReader reader; + guint16 num = 0; + guint8 x = 0; + gchar *s; + + gst_byte_reader_init (&reader, (guint8 *) moredata, sizeof (moredata)); + fail_unless (gst_byte_reader_get_uint16_be (&reader, &num)); + fail_unless_equals_int (num, 0x9910); + fail_unless (gst_byte_reader_dup_string (&reader, &s)); + fail_unless_equals_string (s, "f00!"); + fail_unless (gst_byte_reader_get_uint8 (&reader, &x)); + fail_unless_equals_int (x, 0xff); + g_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_sub_reader) +{ + const guint8 memdata[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + GstByteReader reader = GST_BYTE_READER_INIT (memdata, sizeof (memdata)); + GstByteReader sub; + const guint8 *data = NULL, *sub_data = NULL; + guint16 v = 0; + + /* init sub reader */ + fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 17)); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 16)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 16); + fail_unless (gst_byte_reader_peek_data (&reader, 16, &data)); + fail_unless (gst_byte_reader_peek_data (&sub, 16, &sub_data)); + fail_unless (memcmp (data, sub_data, 16) == 0); + + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16); + fail_unless (gst_byte_reader_skip (&reader, 3)); + fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 14)); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 13)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 13); + fail_unless (gst_byte_reader_peek_data (&reader, 13, &data)); + fail_unless (gst_byte_reader_peek_data (&sub, 13, &sub_data)); + fail_unless (memcmp (data, sub_data, 13) == 0); + fail_unless (memcmp (memdata + 3, sub_data, 13) == 0); + + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 13); + fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 3)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 3); + fail_if (gst_byte_reader_peek_data (&sub, 10, &sub_data)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0304); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 1); + + fail_unless (gst_byte_reader_get_uint16_be (&reader, &v)); + fail_unless_equals_int (v, 0x0304); + fail_unless (gst_byte_reader_get_uint16_be (&reader, &v)); + fail_unless_equals_int (v, 0x0506); + fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 9); + + /* get sub reader */ + gst_byte_reader_init (&reader, memdata, sizeof (memdata)); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 17)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 16)); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 1)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 0)); + + gst_byte_reader_init (&reader, memdata, sizeof (memdata)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0001); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 3)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0203); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x04); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 9)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0506); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0708); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x090a); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0b0c); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x0d); + fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 3)); + fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2)); + fail_unless (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_unless_equals_int (v, 0x0e0f); + fail_if (gst_byte_reader_get_uint16_be (&sub, &v)); + fail_if (gst_byte_reader_get_uint16_be (&reader, &v)); +} + +GST_END_TEST; + +static Suite * +gst_byte_reader_suite (void) +{ + Suite *s = suite_create ("GstByteReader"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_initialization); + tcase_add_test (tc_chain, test_get_uint_le); + tcase_add_test (tc_chain, test_get_uint_be); + tcase_add_test (tc_chain, test_get_int_le); + tcase_add_test (tc_chain, test_get_int_be); + tcase_add_test (tc_chain, test_get_float_le); + tcase_add_test (tc_chain, test_get_float_be); + tcase_add_test (tc_chain, test_position_tracking); + tcase_add_test (tc_chain, test_scan); + tcase_add_test (tc_chain, test_string_funcs); + tcase_add_test (tc_chain, test_dup_string); + tcase_add_test (tc_chain, test_sub_reader); + + return s; +} + + +GST_CHECK_MAIN (gst_byte_reader); diff --git a/tests/check/libs/bytewriter-noinline.c b/tests/check/libs/bytewriter-noinline.c new file mode 100644 index 0000000..241d4a0 --- /dev/null +++ b/tests/check/libs/bytewriter-noinline.c @@ -0,0 +1,21 @@ +/* GStreamer unit test for GstByteWriter without using inlining + * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#define GST_BYTE_WRITER_DISABLE_INLINES +#include "bytewriter.c" diff --git a/tests/check/libs/bytewriter.c b/tests/check/libs/bytewriter.c new file mode 100644 index 0000000..89999af --- /dev/null +++ b/tests/check/libs/bytewriter.c @@ -0,0 +1,258 @@ +/* GStreamer + * + * unit test for GstByteWriter + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +GST_START_TEST (test_initialization) +{ + GstByteWriter writer, *writer2; + static guint8 sdata[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + guint8 *data, *tmp; + + gst_byte_writer_init_with_size (&writer, 24, FALSE); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 0); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 0); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), -1); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0); + gst_byte_writer_reset (&writer); + + data = g_memdup (sdata, sizeof (sdata)); + gst_byte_writer_init_with_data (&writer, data, sizeof (sdata), FALSE); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 0); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 0); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), + sizeof (sdata)); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0) + tmp = gst_byte_writer_reset_and_get_data (&writer); + fail_if (tmp == data); + g_free (tmp); + g_free (data); + data = tmp = NULL; + + data = g_memdup (sdata, sizeof (sdata)); + gst_byte_writer_init_with_data (&writer, data, sizeof (sdata), TRUE); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 0); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), sizeof (sdata)); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), + sizeof (sdata)); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), sizeof (sdata)); + tmp = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (tmp != data); + g_free (tmp); + g_free (data); + data = tmp = NULL; + + writer2 = gst_byte_writer_new_with_size (24, FALSE); + data = gst_byte_writer_free_and_get_data (writer2); + fail_unless (data != NULL); + g_free (data); +} + +GST_END_TEST; + +GST_START_TEST (test_write_fixed) +{ + GstByteWriter writer; + guint64 end_data = G_GUINT64_CONSTANT (0xff34567890abcdef); + guint8 *data; + guint8 b = 0; + guint64 l = 0; + + end_data = GUINT64_TO_BE (end_data); + + gst_byte_writer_init_with_size (&writer, 8, TRUE); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), 8); + + fail_unless (gst_byte_writer_put_uint8 (&writer, 0x12)); + fail_unless (gst_byte_writer_put_uint16_be (&writer, 0x3456)); + fail_unless (gst_byte_writer_put_uint16_le (&writer, 0x9078)); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 5); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 5); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), 8 - 5); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0); + fail_if (gst_byte_reader_get_uint8 (GST_BYTE_READER (&writer), &b)); + fail_unless (gst_byte_writer_put_uint24_be (&writer, 0xabcdef)); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 8); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 8); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), 8 - 8); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0); + fail_if (gst_byte_writer_put_uint8 (&writer, 0x12)); + fail_unless (gst_byte_writer_set_pos (&writer, 0)); + fail_unless (gst_byte_reader_peek_uint64_be (GST_BYTE_READER (&writer), &l)); + fail_unless_equals_uint64 (l, G_GUINT64_CONSTANT (0x1234567890abcdef)); + fail_unless (gst_byte_writer_put_uint8 (&writer, 0xff)); + fail_unless (gst_byte_writer_set_pos (&writer, 0)); + fail_unless (gst_byte_reader_get_uint64_be (GST_BYTE_READER (&writer), &l)); + fail_unless_equals_uint64 (l, G_GUINT64_CONSTANT (0xff34567890abcdef)); + fail_if (gst_byte_writer_put_uint64_be (&writer, + G_GUINT64_CONSTANT (0x1234567890abcdef))); + + data = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (data != NULL); + fail_unless (memcmp (&end_data, data, 8) == 0); + g_free (data); +} + +GST_END_TEST; + +GST_START_TEST (test_write_non_fixed) +{ + GstByteWriter writer; + guint64 end_data = G_GUINT64_CONSTANT (0xff34567890abcdef); + guint8 *data; + guint64 l = 0; + + end_data = GUINT64_TO_BE (end_data); + + gst_byte_writer_init_with_size (&writer, 6, FALSE); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), -1); + + fail_unless (gst_byte_writer_put_uint8 (&writer, 0x12)); + fail_unless (gst_byte_writer_put_uint16_be (&writer, 0x3456)); + fail_unless (gst_byte_writer_put_uint16_le (&writer, 0x9078)); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 5); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 5); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), -1); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0); + fail_unless (gst_byte_writer_put_uint24_be (&writer, 0xabcdef)); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 8); + fail_unless_equals_int (gst_byte_writer_get_size (&writer), 8); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), -1); + fail_unless_equals_int (gst_byte_reader_get_remaining (GST_BYTE_READER + (&writer)), 0); + fail_unless (gst_byte_writer_set_pos (&writer, 0)); + fail_unless (gst_byte_reader_peek_uint64_be (GST_BYTE_READER (&writer), &l)); + fail_unless_equals_uint64 (l, G_GUINT64_CONSTANT (0x1234567890abcdef)); + fail_unless (gst_byte_writer_put_uint8 (&writer, 0xff)); + fail_unless (gst_byte_writer_set_pos (&writer, 0)); + fail_unless (gst_byte_reader_get_uint64_be (GST_BYTE_READER (&writer), &l)); + fail_unless_equals_uint64 (l, G_GUINT64_CONSTANT (0xff34567890abcdef)); + fail_unless (gst_byte_writer_set_pos (&writer, 8)); + fail_unless (gst_byte_writer_put_uint64_be (&writer, + G_GUINT64_CONSTANT (0x1234567890abcdef))); + + data = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (data != NULL); + fail_unless (memcmp (&end_data, data, 8) == 0); + end_data = GUINT64_TO_BE (G_GUINT64_CONSTANT (0x1234567890abcdef)); + fail_unless (memcmp (&end_data, data + 8, 8) == 0); + g_free (data); +} + +GST_END_TEST; + +GST_START_TEST (test_from_data) +{ + GstByteWriter writer; + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, + 0x90, 0xab, 0xcd, 0xef + }; + guint8 *data2; + + gst_byte_writer_init_with_data (&writer, data, sizeof (data), TRUE); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), 8); + fail_unless (gst_byte_writer_put_uint8 (&writer, 0xff)); + fail_unless_equals_int (data[0], 0xff); + fail_unless_equals_int (gst_byte_writer_get_remaining (&writer), 7); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), 1); + fail_if (gst_byte_writer_put_uint64_be (&writer, + G_GUINT64_CONSTANT (0x1234567890abcdef))); + data2 = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (data2 != NULL); + fail_if (data2 == data); + fail_unless (memcmp (data, data2, 8) == 0); + g_free (data2); +} + +GST_END_TEST; + +GST_START_TEST (test_put_data_strings) +{ + GstByteWriter writer; + guint8 data[] = { 0x12, 0x34, 0x56, 0x78, + 0x90, 0xab, 0xcd, 0xef + }; + guint8 *data2; + + gst_byte_writer_init (&writer); + fail_unless (gst_byte_writer_put_data (&writer, data, 8)); + fail_unless (gst_byte_writer_put_string (&writer, "somerandomteststring")); + fail_unless_equals_int (gst_byte_writer_get_pos (&writer), + 8 + sizeof ("somerandomteststring")); + + data2 = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (data2 != NULL); + fail_unless (memcmp (data2, data, 8) == 0); + g_free (data2); +} + +GST_END_TEST; + +GST_START_TEST (test_fill) +{ + GstByteWriter writer; + guint8 data[] = { 0x0, 0x0, 0x0, 0x0, 0x5, 0x5 }; + guint8 *data2; + + gst_byte_writer_init (&writer); + fail_unless (gst_byte_writer_fill (&writer, 0, 4)); + fail_unless (gst_byte_writer_fill (&writer, 5, 2)); + + data2 = gst_byte_writer_reset_and_get_data (&writer); + fail_unless (data2 != NULL); + fail_unless (memcmp (data2, data, 6) == 0); + g_free (data2); +} + +GST_END_TEST; +static Suite * +gst_byte_writer_suite (void) +{ + Suite *s = suite_create ("GstByteWriter"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_initialization); + tcase_add_test (tc_chain, test_write_fixed); + tcase_add_test (tc_chain, test_write_non_fixed); + tcase_add_test (tc_chain, test_from_data); + tcase_add_test (tc_chain, test_put_data_strings); + tcase_add_test (tc_chain, test_fill); + + return s; +} + + +GST_CHECK_MAIN (gst_byte_writer); diff --git a/tests/check/libs/collectpads.c b/tests/check/libs/collectpads.c new file mode 100644 index 0000000..53a9d4c --- /dev/null +++ b/tests/check/libs/collectpads.c @@ -0,0 +1,1111 @@ +/* + * collectpads.c - GstCollectPads testsuite + * Copyright (C) 2006 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +/* dummy collectpads based element */ + +#define GST_TYPE_AGGREGATOR (gst_aggregator_get_type ()) +#define GST_AGGREGATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AGGREGATOR, GstAggregator)) +#define GST_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AGGREGATOR, GstAggregatorClass)) +#define GST_AGGREGATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AGGREGATOR, GstAggregatorClass)) + +typedef struct _GstAggregator GstAggregator; +typedef struct _GstAggregatorClass GstAggregatorClass; + +struct _GstAggregator +{ + GstElement parent; + GstCollectPads *collect; + GstPad *srcpad; + GstPad *sinkpad[2]; + gint padcount; + gboolean first; +}; +struct _GstAggregatorClass +{ + GstElementClass parent_class; +}; + +static GType gst_aggregator_get_type (void); + +G_DEFINE_TYPE (GstAggregator, gst_aggregator, GST_TYPE_ELEMENT); + +static GstStaticPadTemplate gst_aggregator_src_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_aggregator_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstFlowReturn +gst_agregator_collected (GstCollectPads * pads, gpointer user_data) +{ + GstAggregator *aggregator = GST_AGGREGATOR (user_data); + GstBuffer *inbuf; + GstCollectData *collect_data = NULL; + guint outsize = 0; + GSList *walk; + + walk = pads->data; + for (walk = pads->data; walk; walk = walk->next) { + GstCollectData *tmp = (GstCollectData *) walk->data; + if (tmp->buffer) { + collect_data = tmp; + break; + } + } + + /* can only happen when no pads to collect or all EOS */ + if (collect_data == NULL) + goto eos; + + outsize = gst_buffer_get_size (collect_data->buffer); + inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize); + if (!inbuf) + goto eos; + + if (aggregator->first) { + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (aggregator->srcpad, + gst_event_new_stream_start ("test")); + gst_pad_push_event (aggregator->srcpad, gst_event_new_segment (&segment)); + aggregator->first = FALSE; + } + + /* just forward the first buffer */ + GST_DEBUG_OBJECT (aggregator, "forward buffer %p", inbuf); + return gst_pad_push (aggregator->srcpad, inbuf); + /* ERRORS */ +eos: + { + GST_DEBUG_OBJECT (aggregator, "no data available, must be EOS"); + gst_pad_push_event (aggregator->srcpad, gst_event_new_eos ()); + return GST_FLOW_EOS; + } +} + +static GstPad * +gst_aggregator_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * unused, const GstCaps * caps) +{ + GstAggregator *aggregator = GST_AGGREGATOR (element); + gchar *name; + GstPad *newpad; + gint padcount; + + if (templ->direction != GST_PAD_SINK) + return NULL; + + /* create new pad */ + padcount = g_atomic_int_add (&aggregator->padcount, 1); + name = g_strdup_printf ("sink_%u", padcount); + newpad = gst_pad_new_from_template (templ, name); + g_free (name); + + gst_collect_pads_add_pad (aggregator->collect, newpad, + sizeof (GstCollectData), NULL, TRUE); + + /* takes ownership of the pad */ + if (!gst_element_add_pad (GST_ELEMENT (aggregator), newpad)) + goto could_not_add; + + GST_DEBUG_OBJECT (aggregator, "added new pad %s", GST_OBJECT_NAME (newpad)); + return newpad; + + /* errors */ +could_not_add: + { + GST_DEBUG_OBJECT (aggregator, "could not add pad"); + gst_collect_pads_remove_pad (aggregator->collect, newpad); + gst_object_unref (newpad); + return NULL; + } +} + +static void +gst_aggregator_release_pad (GstElement * element, GstPad * pad) +{ + GstAggregator *aggregator = GST_AGGREGATOR (element); + + if (aggregator->collect) + gst_collect_pads_remove_pad (aggregator->collect, pad); + gst_element_remove_pad (element, pad); +} + +static GstStateChangeReturn +gst_aggregator_change_state (GstElement * element, GstStateChange transition) +{ + GstAggregator *aggregator = GST_AGGREGATOR (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_collect_pads_start (aggregator->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 (aggregator->collect); + break; + default: + break; + } + + ret = + GST_ELEMENT_CLASS (gst_aggregator_parent_class)->change_state (element, + transition); + + switch (transition) { + default: + break; + } + + return ret; +} + +static void +gst_aggregator_dispose (GObject * object) +{ + GstAggregator *aggregator = GST_AGGREGATOR (object); + + if (aggregator->collect) { + gst_object_unref (aggregator->collect); + aggregator->collect = NULL; + } + + G_OBJECT_CLASS (gst_aggregator_parent_class)->dispose (object); +} + +static void +gst_aggregator_class_init (GstAggregatorClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + gobject_class->dispose = gst_aggregator_dispose; + + gst_element_class_add_static_pad_template (gstelement_class, + &gst_aggregator_src_template); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_aggregator_sink_template); + gst_element_class_set_static_metadata (gstelement_class, "Aggregator", + "Testing", "Combine N buffers", "Stefan Sauer "); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_aggregator_release_pad); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_aggregator_change_state); +} + +static void +gst_aggregator_init (GstAggregator * agregator) +{ + GstPadTemplate *template; + + template = gst_static_pad_template_get (&gst_aggregator_src_template); + agregator->srcpad = gst_pad_new_from_template (template, "src"); + gst_object_unref (template); + + GST_PAD_SET_PROXY_CAPS (agregator->srcpad); + gst_element_add_pad (GST_ELEMENT (agregator), agregator->srcpad); + + /* keep track of the sinkpads requested */ + agregator->collect = gst_collect_pads_new (); + gst_collect_pads_set_function (agregator->collect, + GST_DEBUG_FUNCPTR (gst_agregator_collected), agregator); + + agregator->first = TRUE; +} + +static gboolean +gst_agregator_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "aggregator", GST_RANK_NONE, + GST_TYPE_AGGREGATOR); +} + +static gboolean +gst_agregator_plugin_register (void) +{ + return gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "aggregator", + "Combine buffers", + gst_agregator_plugin_init, + VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); +} + + +#define fail_unless_collected(expected) \ +G_STMT_START { \ + g_mutex_lock (&lock); \ + while (expected == TRUE && collected == FALSE) \ + g_cond_wait (&cond, &lock); \ + fail_unless_equals_int (collected, expected); \ + g_mutex_unlock (&lock); \ +} G_STMT_END; + +typedef struct +{ + char foo; +} BadCollectData; + +typedef struct +{ + GstCollectData data; + GstPad *pad; + GstBuffer *buffer; + GstEvent *event; + GstFlowReturn expected_result; +} TestData; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstCollectPads *collect; +static gboolean collected; +static GstPad *agg_srcpad, *srcpad1, *srcpad2; +static GstPad *sinkpad1, *sinkpad2; +static TestData *data1, *data2; +static GstBuffer *outbuf1, *outbuf2; +static GstElement *agg; +gboolean fail_seek; +gint flush_start_events, flush_stop_events; + +static GMutex lock; +static GCond cond; + +static GstFlowReturn +collected_cb (GstCollectPads * pads, gpointer user_data) +{ + outbuf1 = gst_collect_pads_pop (pads, (GstCollectData *) data1); + outbuf2 = gst_collect_pads_pop (pads, (GstCollectData *) data2); + + g_mutex_lock (&lock); + collected = TRUE; + g_cond_signal (&cond); + g_mutex_unlock (&lock); + + return GST_FLOW_OK; +} + +static GstFlowReturn +handle_buffer_cb (GstCollectPads * pads, GstCollectData * data, + GstBuffer * buf, gpointer user_data) +{ + GST_DEBUG ("collected buffers via callback"); + + outbuf1 = gst_collect_pads_pop (pads, (GstCollectData *) data1); + outbuf2 = gst_collect_pads_pop (pads, (GstCollectData *) data2); + + g_mutex_lock (&lock); + collected = TRUE; + g_cond_signal (&cond); + g_mutex_unlock (&lock); + + return GST_FLOW_OK; +} + +static gpointer +push_buffer (gpointer user_data) +{ + GstFlowReturn flow; + GstCaps *caps; + TestData *test_data = (TestData *) user_data; + GstSegment segment; + + gst_pad_push_event (test_data->pad, gst_event_new_stream_start ("test")); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_pad_push_event (test_data->pad, gst_event_new_caps (caps)); + gst_caps_unref (caps); + + gst_segment_init (&segment, GST_FORMAT_TIME); + gst_pad_push_event (test_data->pad, gst_event_new_segment (&segment)); + + flow = gst_pad_push (test_data->pad, test_data->buffer); + fail_unless (flow == test_data->expected_result, "got flow %s instead of OK", + gst_flow_get_name (flow)); + + return NULL; +} + +static gpointer +push_event (gpointer user_data) +{ + TestData *test_data = (TestData *) user_data; + + fail_unless (gst_pad_push_event (test_data->pad, test_data->event) == TRUE); + + return NULL; +} + +static void +setup_default (void) +{ + collect = gst_collect_pads_new (); + + srcpad1 = gst_pad_new_from_static_template (&srctemplate, "src1"); + srcpad2 = gst_pad_new_from_static_template (&srctemplate, "src2"); + sinkpad1 = gst_pad_new_from_static_template (&sinktemplate, "sink1"); + sinkpad2 = gst_pad_new_from_static_template (&sinktemplate, "sink2"); + fail_unless (gst_pad_link (srcpad1, sinkpad1) == GST_PAD_LINK_OK); + fail_unless (gst_pad_link (srcpad2, sinkpad2) == GST_PAD_LINK_OK); + + gst_pad_set_active (sinkpad1, TRUE); + gst_pad_set_active (sinkpad2, TRUE); + gst_pad_set_active (srcpad1, TRUE); + gst_pad_set_active (srcpad2, TRUE); + + data1 = NULL; + data2 = NULL; + outbuf1 = NULL; + outbuf2 = NULL; + collected = FALSE; +} + +static void +setup (void) +{ + setup_default (); + gst_collect_pads_set_function (collect, collected_cb, NULL); +} + +static void +setup_buffer_cb (void) +{ + setup_default (); + gst_collect_pads_set_buffer_function (collect, handle_buffer_cb, NULL); +} + +static void +teardown (void) +{ + gst_object_unref (srcpad1); + gst_object_unref (srcpad2); + gst_object_unref (sinkpad1); + gst_object_unref (sinkpad2); + gst_object_unref (collect); + srcpad1 = srcpad2 = NULL; + sinkpad1 = sinkpad2 = NULL; + collect = NULL; +} + +GST_START_TEST (test_pad_add_remove) +{ + ASSERT_CRITICAL (gst_collect_pads_add_pad (collect, sinkpad1, + sizeof (BadCollectData), NULL, TRUE)); + + data1 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad1, sizeof (TestData), NULL, TRUE); + fail_unless (data1 != NULL); + + fail_unless (gst_collect_pads_remove_pad (collect, sinkpad2) == FALSE); + fail_unless (gst_collect_pads_remove_pad (collect, sinkpad1) == TRUE); +} + +GST_END_TEST; + +GST_START_TEST (test_collect) +{ + GstBuffer *buf1, *buf2; + GThread *thread1, *thread2; + + data1 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad1, sizeof (TestData), NULL, TRUE); + fail_unless (data1 != NULL); + + data2 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad2, sizeof (TestData), NULL, TRUE); + fail_unless (data2 != NULL); + + buf1 = gst_buffer_new (); + buf2 = gst_buffer_new (); + + /* start collect pads */ + gst_collect_pads_start (collect); + + /* push buffers on the pads */ + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + /* here thread1 is blocked and srcpad1 has a queued buffer */ + fail_unless_collected (FALSE); + + data2->pad = srcpad2; + data2->buffer = buf2; + thread2 = g_thread_try_new ("gst-check", push_buffer, data2, NULL); + + /* now both pads have a buffer */ + fail_unless_collected (TRUE); + + fail_unless (outbuf1 == buf1); + fail_unless (outbuf2 == buf2); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_collect_pads_stop (collect); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); +} + +GST_END_TEST; + + +GST_START_TEST (test_collect_eos) +{ + GstBuffer *buf1; + GThread *thread1, *thread2; + + data1 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad1, sizeof (TestData), NULL, TRUE); + fail_unless (data1 != NULL); + + data2 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad2, sizeof (TestData), NULL, TRUE); + fail_unless (data2 != NULL); + + buf1 = gst_buffer_new (); + + /* start collect pads */ + gst_collect_pads_start (collect); + + /* push a buffer on srcpad1 and EOS on srcpad2 */ + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + /* here thread1 is blocked and srcpad1 has a queued buffer */ + fail_unless_collected (FALSE); + + data2->pad = srcpad2; + data2->event = gst_event_new_eos (); + thread2 = g_thread_try_new ("gst-check", push_event, data2, NULL); + /* now sinkpad1 has a buffer and sinkpad2 has EOS */ + fail_unless_collected (TRUE); + + fail_unless (outbuf1 == buf1); + /* sinkpad2 has EOS so a NULL buffer is returned */ + fail_unless (outbuf2 == NULL); + + /* these will return immediately as when the data is popped the threads are + * unlocked and will terminate */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_collect_pads_stop (collect); + + gst_buffer_unref (buf1); +} + +GST_END_TEST; + +GST_START_TEST (test_collect_twice) +{ + GstBuffer *buf1, *buf2; + GThread *thread1, *thread2; + + data1 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad1, sizeof (TestData), NULL, TRUE); + fail_unless (data1 != NULL); + + data2 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad2, sizeof (TestData), NULL, TRUE); + fail_unless (data2 != NULL); + + GST_INFO ("round 1"); + + buf1 = gst_buffer_new (); + + /* start collect pads */ + gst_collect_pads_start (collect); + + /* queue a buffer */ + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + /* here thread1 is blocked and srcpad1 has a queued buffer */ + fail_unless_collected (FALSE); + + /* push EOS on the other pad */ + data2->pad = srcpad2; + data2->event = gst_event_new_eos (); + thread2 = g_thread_try_new ("gst-check", push_event, data2, NULL); + + /* one of the pads has a buffer, the other has EOS */ + fail_unless_collected (TRUE); + + fail_unless (outbuf1 == buf1); + /* there's nothing to pop from the one which received EOS */ + fail_unless (outbuf2 == NULL); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_collect_pads_stop (collect); + collected = FALSE; + + GST_INFO ("round 2"); + + buf2 = gst_buffer_new (); + + /* clear EOS from pads */ + gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE)); + gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE)); + + /* start collect pads */ + gst_collect_pads_start (collect); + + /* push buffers on the pads */ + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + /* here thread1 is blocked and srcpad1 has a queued buffer */ + fail_unless_collected (FALSE); + + data2->pad = srcpad2; + data2->buffer = buf2; + thread2 = g_thread_try_new ("gst-check", push_buffer, data2, NULL); + + /* now both pads have a buffer */ + fail_unless_collected (TRUE); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_collect_pads_stop (collect); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); + +} + +GST_END_TEST; + + +/* Test the default collected buffer func */ +GST_START_TEST (test_collect_default) +{ + GstBuffer *buf1, *buf2; + GThread *thread1, *thread2; + + data1 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad1, sizeof (TestData), NULL, TRUE); + fail_unless (data1 != NULL); + + data2 = (TestData *) gst_collect_pads_add_pad (collect, + sinkpad2, sizeof (TestData), NULL, TRUE); + fail_unless (data2 != NULL); + + buf1 = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buf1) = 0; + buf2 = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buf2) = GST_SECOND; + + /* start collect pads */ + gst_collect_pads_start (collect); + + /* push buffers on the pads */ + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + /* here thread1 is blocked and srcpad1 has a queued buffer */ + fail_unless_collected (FALSE); + + data2->pad = srcpad2; + data2->buffer = buf2; + thread2 = g_thread_try_new ("gst-check", push_buffer, data2, NULL); + + /* now both pads have a buffer */ + fail_unless_collected (TRUE); + + /* The default callback should have popped the buffer with lower timestamp, + * and this should therefore be NULL: */ + fail_unless (outbuf1 == NULL); + /* While this one should still be pending: */ + fail_unless (outbuf2 == buf2); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); + + gst_collect_pads_stop (collect); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); +} + +GST_END_TEST; + + +#define NUM_BUFFERS 3 +static void +handoff (GstElement * fakesink, GstBuffer * buf, GstPad * pad, guint * count) +{ + *count = *count + 1; +} + +/* Test a linear pipeline using aggregator */ +GST_START_TEST (test_linear_pipeline) +{ + GstElement *pipeline, *src, *agg, *sink; + GstBus *bus; + GstMessage *msg; + gint count = 0; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("fakesrc"); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizetype", 2, "sizemax", 4, + NULL); + agg = gst_check_setup_element ("aggregator"); + sink = gst_check_setup_element ("fakesink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff, &count); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (src, agg)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + fail_unless_equals_int (count, NUM_BUFFERS); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +/* Test a linear pipeline using aggregator */ +GST_START_TEST (test_branched_pipeline) +{ + GstElement *pipeline, *src, *tee, *queue[2], *agg, *sink; + GstBus *bus; + GstMessage *msg; + gint count = 0; + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("fakesrc"); + g_object_set (src, "num-buffers", NUM_BUFFERS, "sizetype", 2, "sizemax", 4, + NULL); + tee = gst_check_setup_element ("tee"); + queue[0] = gst_check_setup_element ("queue"); + gst_object_set_name (GST_OBJECT (queue[0]), "queue0"); + queue[1] = gst_check_setup_element ("queue"); + gst_object_set_name (GST_OBJECT (queue[1]), "queue1"); + agg = gst_check_setup_element ("aggregator"); + sink = gst_check_setup_element ("fakesink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff, &count); + + fail_unless (gst_bin_add (GST_BIN (pipeline), src)); + fail_unless (gst_bin_add (GST_BIN (pipeline), tee)); + fail_unless (gst_bin_add (GST_BIN (pipeline), queue[0])); + fail_unless (gst_bin_add (GST_BIN (pipeline), queue[1])); + fail_unless (gst_bin_add (GST_BIN (pipeline), agg)); + fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); + fail_unless (gst_element_link (src, tee)); + fail_unless (gst_element_link (tee, queue[0])); + fail_unless (gst_element_link (tee, queue[1])); + fail_unless (gst_element_link (queue[0], agg)); + fail_unless (gst_element_link (queue[1], agg)); + fail_unless (gst_element_link (agg, sink)); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS); + gst_message_unref (msg); + + /* we have two branches, but we still only forward buffers from one branch */ + fail_unless_equals_int (count, NUM_BUFFERS * 2); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstPadProbeReturn +downstream_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + if (info->type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) { + if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_EVENT (info)) == + GST_EVENT_FLUSH_START) + g_atomic_int_inc (&flush_start_events); + else if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_EVENT (info)) == + GST_EVENT_FLUSH_STOP) + g_atomic_int_inc (&flush_stop_events); + } else if (info->type & GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM) { + g_mutex_lock (&lock); + collected = TRUE; + g_cond_signal (&cond); + g_mutex_unlock (&lock); + } + + return GST_PAD_PROBE_DROP; +} + +static gboolean +src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + gboolean ret = TRUE; + if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) { + if (g_atomic_int_compare_and_exchange (&fail_seek, TRUE, FALSE) == TRUE) { + ret = FALSE; + } + } + + gst_event_unref (event); + return ret; +} + +static gboolean +agg_src_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + return gst_collect_pads_src_event_default (GST_AGGREGATOR (parent)->collect, + pad, event); +} + +static GstPad * +setup_src_pad (GstElement * element, + GstStaticPadTemplate * tmpl, const char *name) +{ + GstPad *srcpad, *sinkpad; + + srcpad = gst_pad_new_from_static_template (tmpl, "src"); + sinkpad = gst_element_get_request_pad (element, name); + fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK, + "Could not link source and %s sink pads", GST_ELEMENT_NAME (element)); + gst_pad_set_event_function (srcpad, src_event); + gst_pad_set_active (srcpad, TRUE); + gst_object_unref (sinkpad); + + return srcpad; +} + +static void +flush_setup (void) +{ + agg = gst_check_setup_element ("aggregator"); + agg_srcpad = gst_element_get_static_pad (agg, "src"); + srcpad1 = setup_src_pad (agg, &srctemplate, "sink_0"); + srcpad2 = setup_src_pad (agg, &srctemplate, "sink_1"); + gst_pad_add_probe (agg_srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | + GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM | + GST_PAD_PROBE_TYPE_EVENT_FLUSH, downstream_probe_cb, NULL, NULL); + gst_pad_set_event_function (agg_srcpad, agg_src_event); + data1 = g_new0 (TestData, 1); + data2 = g_new0 (TestData, 1); + g_atomic_int_set (&flush_start_events, 0); + g_atomic_int_set (&flush_stop_events, 0); + gst_element_set_state (agg, GST_STATE_PLAYING); + outbuf1 = NULL; + outbuf2 = NULL; + collected = FALSE; +} + +static void +flush_teardown (void) +{ + gst_element_set_state (agg, GST_STATE_NULL); + gst_object_unref (agg); + gst_object_unref (agg_srcpad); + gst_object_unref (srcpad1); + gst_object_unref (srcpad2); + g_free (data1); + g_free (data2); + agg = NULL; + agg_srcpad = NULL; + srcpad1 = srcpad2 = NULL; + data1 = data2 = NULL; +} + +GST_START_TEST (test_flushing_seek_failure) +{ + GstBuffer *buf1, *buf2; + GThread *thread1, *thread2; + GstEvent *event; + + /* Queue a buffer in agg:sink_1. Do a flushing seek and simulate one upstream + * element failing to handle the seek (see src_event()). Check that the + * flushing seek logic doesn't get triggered by checking that the buffer + * queued on agg:sink_1 doesn't get flushed. + */ + + /* queue a buffer in agg:sink_1 */ + buf2 = gst_buffer_new_allocate (NULL, 1, NULL); + GST_BUFFER_TIMESTAMP (buf2) = GST_SECOND; + data2->pad = srcpad2; + data2->buffer = buf2; + thread2 = g_thread_try_new ("gst-check", push_buffer, data2, NULL); + fail_unless_collected (FALSE); + + /* do the seek */ + event = gst_event_new_seek (1, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 10 * GST_SECOND); + g_atomic_int_set (&fail_seek, TRUE); + fail_if (gst_pad_send_event (agg_srcpad, event)); + + /* flush srcpad1 (pretending it's the upstream that didn't fail to seek) */ + fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_start ())); + fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE))); + + /* check that the flush events reached agg:src */ + fail_unless_equals_int (flush_start_events, 1); + fail_unless_equals_int (flush_stop_events, 1); + + /* push a buffer on agg:sink_0. This should trigger a collect since agg:sink_1 + * should not have been flushed at this point */ + buf1 = gst_buffer_new_allocate (NULL, 1, NULL); + GST_BUFFER_TIMESTAMP (buf1) = 0; + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + fail_unless_collected (TRUE); + collected = FALSE; + + /* at this point thread1 must have returned */ + g_thread_join (thread1); + + /* push eos on agg:sink_0 so the buffer queued in agg:sink_1 is collected and + * the pushing thread returns */ + data1->pad = srcpad1; + data1->event = gst_event_new_eos (); + thread1 = g_thread_try_new ("gst-check", push_event, data1, NULL); + fail_unless_collected (TRUE); + + g_thread_join (thread1); + g_thread_join (thread2); +} + +GST_END_TEST; + +GST_START_TEST (test_flushing_seek) +{ + GstBuffer *buf1, *buf2; + GThread *thread1, *thread2; + GstEvent *event; + + /* Queue a buffer in agg:sink_1. Then do a flushing seek and check that the + * new flushing seek logic is triggered. On the first FLUSH_START call the + * buffers queued in collectpads should get flushed. Only one FLUSH_START and + * one FLUSH_STOP should be forwarded downstream. + */ + buf2 = gst_buffer_new_allocate (NULL, 1, NULL); + GST_BUFFER_TIMESTAMP (buf2) = 0; + data2->pad = srcpad2; + data2->buffer = buf2; + /* expect this buffer to be flushed */ + data2->expected_result = GST_FLOW_FLUSHING; + thread2 = g_thread_try_new ("gst-check", push_buffer, data2, NULL); + + /* now do a successful flushing seek */ + event = gst_event_new_seek (1, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 10 * GST_SECOND); + g_atomic_int_set (&fail_seek, FALSE); + fail_unless (gst_pad_send_event (agg_srcpad, event)); + + /* flushing starts once one of the upstream elements sends the first + * FLUSH_START */ + fail_unless_equals_int (flush_start_events, 0); + fail_unless_equals_int (flush_stop_events, 0); + + /* flush ogg:sink_0. This flushs collectpads, calls ::flush() and sends + * FLUSH_START downstream */ + fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_start ())); + fail_unless_equals_int (flush_start_events, 1); + fail_unless_equals_int (flush_stop_events, 0); + /* the first FLUSH_STOP is forwarded downstream */ + fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE))); + fail_unless_equals_int (flush_start_events, 1); + fail_unless_equals_int (flush_stop_events, 1); + /* at this point even the other pad agg:sink_1 should be flushing so thread2 + * should have stopped */ + g_thread_join (thread2); + + /* push a buffer on agg:sink_0 to trigger one collect after flushing to verify + * that flushing completes once all the pads have been flushed */ + buf1 = gst_buffer_new_allocate (NULL, 1, NULL); + GST_BUFFER_TIMESTAMP (buf1) = GST_SECOND; + data1->pad = srcpad1; + data1->buffer = buf1; + thread1 = g_thread_try_new ("gst-check", push_buffer, data1, NULL); + + /* flush agg:sink_1 as well. This completes the flushing seek so a FLUSH_STOP is + * sent downstream */ + gst_pad_push_event (srcpad2, gst_event_new_flush_start ()); + gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE)); + + /* still, only one FLUSH_START and one FLUSH_STOP are forwarded downstream */ + fail_unless_equals_int (flush_start_events, 1); + fail_unless_equals_int (flush_stop_events, 1); + + /* EOS agg:sink_1 so the buffer queued in agg:sink_0 is collected */ + data2->pad = srcpad2; + data2->event = gst_event_new_eos (); + thread2 = g_thread_try_new ("gst-check", push_event, data2, NULL); + fail_unless_collected (TRUE); + + /* these will return immediately as at this point the threads have been + * unlocked and are finished */ + g_thread_join (thread1); + g_thread_join (thread2); +} + +GST_END_TEST; + +GST_START_TEST (test_clip_running_time) +{ + GstBuffer *buf; + GstCollectData data = { 0 }; + + buf = gst_buffer_new (); + data.pad = gst_pad_new ("clip_test", GST_PAD_SRC); + + GST_BUFFER_PTS (buf) = 0; + GST_BUFFER_DTS (buf) = 0; + gst_segment_init (&data.segment, GST_FORMAT_TIME); + + gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL); + + fail_unless (buf != NULL); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0); + fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), 0); + fail_unless_equals_int64 (GST_COLLECT_PADS_DTS (&data), 0); + + GST_BUFFER_PTS (buf) = 1000; + GST_BUFFER_DTS (buf) = 0; + data.segment.start = 1000; + + gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL); + + fail_unless (buf != NULL); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0); + fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), GST_CLOCK_TIME_NONE); + fail_unless_equals_int64 (GST_COLLECT_PADS_DTS (&data), -1000); + + GST_BUFFER_PTS (buf) = 1000; + GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE; + + gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL); + + fail_unless (buf != NULL); + fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), 0); + fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), GST_CLOCK_TIME_NONE); + fail_if (GST_COLLECT_PADS_DTS_IS_VALID (&data)); + + GST_BUFFER_PTS (buf) = 0; + GST_BUFFER_DTS (buf) = 0; + + gst_collect_pads_clip_running_time (NULL, &data, buf, &buf, NULL); + + fail_unless (buf == NULL); + gst_object_unref (data.pad); +} + +GST_END_TEST; + + +static Suite * +gst_collect_pads_suite (void) +{ + Suite *suite; + TCase *general, *buffers, *pipeline, *flush; + + gst_agregator_plugin_register (); + + suite = suite_create ("GstCollectPads"); + + general = tcase_create ("general"); + suite_add_tcase (suite, general); + tcase_add_checked_fixture (general, setup, teardown); + tcase_add_test (general, test_pad_add_remove); + + tcase_add_test (general, test_collect); + tcase_add_test (general, test_collect_eos); + tcase_add_test (general, test_collect_twice); + tcase_add_test (general, test_clip_running_time); + + buffers = tcase_create ("buffers"); + suite_add_tcase (suite, buffers); + tcase_add_checked_fixture (buffers, setup_buffer_cb, teardown); + tcase_add_test (buffers, test_collect_default); + + pipeline = tcase_create ("pipeline"); + suite_add_tcase (suite, pipeline); + tcase_add_test (pipeline, test_linear_pipeline); + tcase_add_test (pipeline, test_branched_pipeline); + + flush = tcase_create ("flush"); + suite_add_tcase (suite, flush); + tcase_add_checked_fixture (flush, flush_setup, flush_teardown); + tcase_add_test (flush, test_flushing_seek_failure); + tcase_add_test (flush, test_flushing_seek); + + return suite; +} + +GST_CHECK_MAIN (gst_collect_pads); diff --git a/tests/check/libs/controller.c b/tests/check/libs/controller.c new file mode 100644 index 0000000..9fdb760 --- /dev/null +++ b/tests/check/libs/controller.c @@ -0,0 +1,1674 @@ +/* GStreamer + * + * unit test for the controller library + * + * Copyright (C) <2005> Stefan Kost + * Copyright (C) <2006-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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +/* enum for text element */ + +#define GST_TYPE_TEST_ENUM (gst_test_enum_get_type ()) + +typedef enum +{ + ENUM_V0 = 0, + ENUM_V10 = 10, + ENUM_V11, + ENUM_V12, + ENUM_V255 = 255 +} GstTestEnum; + +static GType +gst_test_enum_get_type (void) +{ + static gsize gtype = 0; + static const GEnumValue values[] = { + {ENUM_V0, "ENUM_V0", "0"}, + {ENUM_V10, "ENUM_V10", "10"}, + {ENUM_V11, "ENUM_V11", "11"}, + {ENUM_V12, "ENUM_V12", "12"}, + {ENUM_V255, "ENUM_V255", "255"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (>ype)) { + GType tmp = g_enum_register_static ("GstTestEnum", values); + g_once_init_leave (>ype, tmp); + } + + return (GType) gtype; +} + +/* local test element */ + +enum +{ + PROP_INT = 1, + PROP_FLOAT, + PROP_DOUBLE, + PROP_BOOLEAN, + PROP_ENUM, + PROP_READONLY, + PROP_STATIC, + PROP_CONSTRUCTONLY, + PROP_COUNT +}; + +#define GST_TYPE_TEST_OBJ (gst_test_obj_get_type ()) +#define GST_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj)) +#define GST_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass)) +#define GST_IS_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ)) +#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ)) +#define GST_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass)) + +typedef struct _GstTestObj GstTestObj; +typedef struct _GstTestObjClass GstTestObjClass; + +struct _GstTestObj +{ + GstElement parent; + gint val_int; + gfloat val_float; + gdouble val_double; + gboolean val_boolean; + GstTestEnum val_enum; +}; +struct _GstTestObjClass +{ + GstElementClass parent_class; +}; + +static GType gst_test_obj_get_type (void); + +static void +gst_test_obj_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + g_value_set_int (value, self->val_int); + break; + case PROP_FLOAT: + g_value_set_float (value, self->val_float); + break; + case PROP_DOUBLE: + g_value_set_double (value, self->val_double); + break; + case PROP_BOOLEAN: + g_value_set_boolean (value, self->val_boolean); + break; + case PROP_ENUM: + g_value_set_enum (value, self->val_enum); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + self->val_int = g_value_get_int (value); + GST_DEBUG ("test value int=%d", self->val_int); + break; + case PROP_FLOAT: + self->val_float = g_value_get_float (value); + GST_DEBUG ("test value float=%f", self->val_float); + break; + case PROP_DOUBLE: + self->val_double = g_value_get_double (value); + GST_DEBUG ("test value double=%lf", self->val_double); + break; + case PROP_BOOLEAN: + self->val_boolean = g_value_get_boolean (value); + GST_DEBUG ("test value boolean=%d", self->val_boolean); + break; + case PROP_ENUM: + self->val_enum = g_value_get_enum (value); + GST_DEBUG ("test value enum=%d", self->val_enum); + break; + case PROP_CONSTRUCTONLY: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_class_init (GstTestObjClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_test_obj_set_property; + gobject_class->get_property = gst_test_obj_get_property; + + g_object_class_install_property (gobject_class, PROP_INT, + g_param_spec_int ("int", + "int prop", + "int number parameter", + 0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_FLOAT, + g_param_spec_float ("float", + "float prop", + "float number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_DOUBLE, + g_param_spec_double ("double", + "double prop", + "double number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_BOOLEAN, + g_param_spec_boolean ("boolean", + "boolean prop", + "boolean parameter", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_ENUM, + g_param_spec_enum ("enum", + "enum prop", + "enum parameter", + GST_TYPE_TEST_ENUM, ENUM_V0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_READONLY, + g_param_spec_int ("readonly", + "readonly prop", + "readonly parameter", + 0, G_MAXINT, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_STATIC, + g_param_spec_int ("static", + "static prop", + "static parameter", 0, G_MAXINT, 0, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_CONSTRUCTONLY, + g_param_spec_int ("construct-only", + "construct-only prop", + "construct-only parameter", + 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gst_test_obj_base_init (GstTestObjClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_metadata (element_class, + "test object for unit tests", + "Test", "Use in unit tests", "Stefan Sauer "); +} + +static GType +gst_test_obj_get_type (void) +{ + static volatile gsize test_obj_type = 0; + + if (g_once_init_enter (&test_obj_type)) { + GType type; + static const GTypeInfo info = { + (guint16) sizeof (GstTestObjClass), + (GBaseInitFunc) gst_test_obj_base_init, // base_init + NULL, // base_finalize + (GClassInitFunc) gst_test_obj_class_init, // class_init + NULL, // class_finalize + NULL, // class_data + (guint16) sizeof (GstTestObj), + 0, // n_preallocs + NULL, // instance_init + NULL // value_table + }; + type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0); + g_once_init_leave (&test_obj_type, type); + } + return test_obj_type; +} + +static void +setup (void) +{ + gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ); +} + +static void +teardown (void) +{ +} + + +/* TESTS */ + +/* tests if we don't fail on empty interpolation controlsources */ +GST_START_TEST (controller_controlsource_empty1) +{ + GstElement *elem; + GstControlSource *cs; + + elem = gst_element_factory_make ("testobj", NULL); + + cs = gst_interpolation_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* don't fail on empty control point lists */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + + /* unref objects */ + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* tests if we don't fail on interpolation controlsources that are empty again */ +GST_START_TEST (controller_controlsource_empty2) +{ + GstElement *elem; + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + + elem = gst_element_factory_make ("testobj", NULL); + + cs = gst_interpolation_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set control values */ + tvcs = (GstTimedValueControlSource *) cs; + gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0); + + /* ... and unset the value */ + gst_timed_value_control_source_unset (tvcs, 0 * GST_SECOND); + + /* don't fail on empty control point lists */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + + /* unref objects */ + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value handling without interpolation */ +GST_START_TEST (controller_interpolation_none) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + gdouble v; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + + /* check values on control source directly */ + fail_unless (gst_control_source_get_value (cs, 0 * GST_SECOND, &v)); + fail_unless_equals_float (v, 0.0); + fail_unless (gst_control_source_get_value (cs, 1 * GST_SECOND, &v)); + fail_unless_equals_float (v, 0.0); + fail_unless (gst_control_source_get_value (cs, 2 * GST_SECOND, &v)); + fail_unless_equals_float (v, 1.0); + fail_unless (gst_control_source_get_value (cs, 3 * GST_SECOND, &v)); + fail_unless_equals_float (v, 1.0); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value handling with linear interpolation */ +GST_START_TEST (controller_interpolation_linear) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value handling with cubic interpolation */ +GST_START_TEST (controller_interpolation_cubic) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "double", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 0.5)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.2)); + fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 0.8)); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 50.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless (GST_TEST_OBJ (elem)->val_double > 20.0 && + GST_TEST_OBJ (elem)->val_double < 80.0, NULL); + gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 80.0); + gst_object_sync_values (GST_OBJECT (elem), 5 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 80.0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value handling with cubic interpolation */ +GST_START_TEST (controller_interpolation_cubic_too_few_cp) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "double", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL); + + /* set 2 control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.4)); + + /* now pull in values for some timestamps and verify that it used linear + * interpolation as we don't gave enough control points + */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test _unset() */ +GST_START_TEST (controller_interpolation_unset) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.5)); + + /* verify values */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + + /* unset second */ + fail_unless (gst_timed_value_control_source_unset (tvcs, 1 * GST_SECOND)); + + /* verify value again */ + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + + /* unset all values, reset and try to unset again */ + fail_unless (gst_timed_value_control_source_unset (tvcs, 0 * GST_SECOND)); + fail_unless (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND)); + gst_timed_value_control_source_unset_all (tvcs); + fail_if (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND)); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test _unset_all() */ +GST_START_TEST (controller_interpolation_unset_all) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0)); + + /* verify values */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + /* unset all */ + gst_timed_value_control_source_unset_all (tvcs); + GST_TEST_OBJ (elem)->val_int = 0; + + /* verify value again */ + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test retrieval of an array of values with get_value_array() */ +GST_START_TEST (controller_interpolation_linear_absolute_value_array) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + gdouble *raw_values; + GValue *g_values; + gint *values; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new_absolute (GST_OBJECT (elem), "int", + cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 100)); + + /* now pull in raw-values for some timestamps */ + raw_values = g_new (gdouble, 3); + + fail_unless (gst_control_source_get_value_array (cs, + 0, GST_SECOND / 2, 3, raw_values)); + fail_unless_equals_float ((raw_values)[0], 0); + fail_unless_equals_float ((raw_values)[1], 50); + fail_unless_equals_float ((raw_values)[2], 100); + + g_free (raw_values); + + /* now pull in mapped GValues for some timestamps */ + g_values = g_new0 (GValue, 3); + + fail_unless (gst_object_get_g_value_array (GST_OBJECT (elem), "int", + 0, GST_SECOND / 2, 3, g_values)); + fail_unless_equals_int (g_value_get_int (&g_values[0]), 0); + fail_unless_equals_int (g_value_get_int (&g_values[1]), 50); + fail_unless_equals_int (g_value_get_int (&g_values[2]), 100); + + g_free (g_values); + + /* now pull in mapped values for some timestamps */ + values = g_new0 (gint, 3); + + fail_unless (gst_object_get_value_array (GST_OBJECT (elem), "int", + 0, GST_SECOND / 2, 3, values)); + fail_unless_equals_int (values[0], 0); + fail_unless_equals_int (values[1], 50); + fail_unless_equals_int (values[2], 100); + + g_free (values); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test retrieval of an array of values with get_value_array() */ +GST_START_TEST (controller_interpolation_linear_value_array) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + gdouble *raw_values; + GValue *g_values; + gint *values; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0)); + + /* now pull in raw-values for some timestamps */ + raw_values = g_new (gdouble, 3); + + fail_unless (gst_control_source_get_value_array (cs, + 0, GST_SECOND / 2, 3, raw_values)); + fail_unless_equals_float ((raw_values)[0], 0.0); + fail_unless_equals_float ((raw_values)[1], 0.5); + fail_unless_equals_float ((raw_values)[2], 1.0); + + g_free (raw_values); + + /* now pull in mapped GValues for some timestamps */ + g_values = g_new0 (GValue, 3); + + fail_unless (gst_object_get_g_value_array (GST_OBJECT (elem), "int", + 0, GST_SECOND / 2, 3, g_values)); + fail_unless_equals_int (g_value_get_int (&g_values[0]), 0); + fail_unless_equals_int (g_value_get_int (&g_values[1]), 50); + fail_unless_equals_int (g_value_get_int (&g_values[2]), 100); + + g_free (g_values); + + /* now pull in mapped values for some timestamps */ + values = g_new0 (gint, 3); + + fail_unless (gst_object_get_value_array (GST_OBJECT (elem), "int", + 0, GST_SECOND / 2, 3, values)); + fail_unless_equals_int (values[0], 0); + fail_unless_equals_int (values[1], 50); + fail_unless_equals_int (values[2], 100); + + g_free (values); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test if values below minimum and above maximum are clipped */ +GST_START_TEST (controller_interpolation_linear_invalid_values) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "float", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 2.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, -2.0)); + + /* now pull in values for some timestamps and see if clipping works */ + /* 200.0 */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 100.0); + /* 100.0 */ + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 100.0); + /* 50.0 */ + gst_object_sync_values (GST_OBJECT (elem), + 1 * GST_SECOND + 500 * GST_MSECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 50.0); + /* 0.0 */ + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0); + /* -100.0 */ + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0); + /* -200.0 */ + gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (controller_interpolation_linear_default_values) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* Should fail if no value was set yet + * FIXME: will not fail, as interpolation assumes val[0]=default_value if + * nothing else is set. + fail_if (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, &val_int)); + */ + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 3 * GST_SECOND, 1.0)); + + /* now pull in values for some timestamps */ + /* should give the value of the first control point for timestamps before it */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + + /* unset the old ones */ + fail_unless (gst_timed_value_control_source_unset (tvcs, 1 * GST_SECOND)); + fail_unless (gst_timed_value_control_source_unset (tvcs, 3 * GST_SECOND)); + + /* now pull in values for some timestamps */ + /* should now give our value for timestamp 0 */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test gst_controller_set_disabled() with linear interpolation */ +GST_START_TEST (controller_interpolation_linear_disabled) +{ + GstControlSource *cs1, *cs2; + GstTimedValueControlSource *tvcs1, *tvcs2; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs1 = gst_interpolation_control_source_new (); + tvcs1 = (GstTimedValueControlSource *) cs1; + + cs2 = gst_interpolation_control_source_new (); + tvcs2 = (GstTimedValueControlSource *) cs2; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs1))); + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "double", cs2))); + + /* set interpolation mode */ + g_object_set (cs1, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + g_object_set (cs2, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs1, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs1, 2 * GST_SECOND, 1.0)); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs2, 0 * GST_SECOND, 0.2)); + fail_unless (gst_timed_value_control_source_set (tvcs2, 2 * GST_SECOND, 0.4)); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0); + + /* now pull in values for some timestamps, prop double disabled */ + GST_TEST_OBJ (elem)->val_int = 0; + GST_TEST_OBJ (elem)->val_double = 0.0; + gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", TRUE); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + + /* now pull in values for some timestamps, after enabling double again */ + GST_TEST_OBJ (elem)->val_int = 0; + GST_TEST_OBJ (elem)->val_double = 0.0; + gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", FALSE); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0); + + /* now pull in values for some timestamps, after disabling all props */ + GST_TEST_OBJ (elem)->val_int = 0; + GST_TEST_OBJ (elem)->val_double = 0.0; + gst_object_set_control_bindings_disabled (GST_OBJECT (elem), TRUE); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0); + + /* now pull in values for some timestamps, enabling double again */ + GST_TEST_OBJ (elem)->val_int = 0; + GST_TEST_OBJ (elem)->val_double = 0.0; + gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", FALSE); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0); + + /* now pull in values for some timestamps, enabling all */ + GST_TEST_OBJ (elem)->val_int = 0; + GST_TEST_OBJ (elem)->val_double = 0.0; + gst_object_set_control_bindings_disabled (GST_OBJECT (elem), FALSE); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0); + + gst_object_unref (cs1); + gst_object_unref (cs2); + gst_object_unref (elem); +} + +GST_END_TEST; + + +GST_START_TEST (controller_interpolation_set_from_list) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstTimedValue *tval; + GstElement *elem; + GSList *list = NULL; + + /* test that an invalid timestamp throws a warning of some sort */ + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control value */ + tval = g_new0 (GstTimedValue, 1); + tval->timestamp = GST_CLOCK_TIME_NONE; + tval->value = 0.0; + + list = g_slist_append (list, tval); + + fail_if (gst_timed_value_control_source_set_from_list (tvcs, list)); + + /* try again with a valid stamp, should work now */ + tval->timestamp = 0; + fail_unless (gst_timed_value_control_source_set_from_list (tvcs, list)); + + /* allocated GstTimedValue now belongs to the controller, but list not */ + g_free (tval); + g_slist_free (list); + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + + +/* test linear interpolation for ts < first control point */ +GST_START_TEST (controller_interpolation_linear_before_ts0) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 0.0)); + + /* now pull in values for some timestamps after first control point */ + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + /* now pull in values for some timestamps before first control point */ + GST_TEST_OBJ (elem)->val_int = 25; + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test linear interpolation of enums */ +GST_START_TEST (controller_interpolation_linear_enums) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "enum", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 1.0)); + + /* now pull in values going over the enum values */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V0); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V10); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V11); + gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V12); + gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V255); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value counts */ +GST_START_TEST (controller_timed_value_count) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* set interpolation mode */ + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + + fail_unless (gst_timed_value_control_source_get_count (tvcs) == 0); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_get_count (tvcs) == 1); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + fail_unless (gst_timed_value_control_source_get_count (tvcs) == 2); + + /* unset control values */ + fail_unless (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND)); + fail_unless (gst_timed_value_control_source_get_count (tvcs) == 1); + fail_unless (gst_timed_value_control_source_unset (tvcs, 0 * GST_SECOND)); + fail_unless (gst_timed_value_control_source_get_count (tvcs) == 0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + + +/* test lfo control source with sine waveform */ +GST_START_TEST (controller_lfo_sine) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, + "frequency", 1.0, "timeshift", (GstClockTime) 0, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test lfo control source with sine waveform and timeshift */ +GST_START_TEST (controller_lfo_sine_timeshift) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, + "frequency", 1.0, "timeshift", 250 * GST_MSECOND, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test lfo control source with square waveform */ +GST_START_TEST (controller_lfo_square) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, + "frequency", 1.0, "timeshift", (GstClockTime) 0, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test lfo control source with saw waveform */ +GST_START_TEST (controller_lfo_saw) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, + "frequency", 1.0, "timeshift", (GstClockTime) 0, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test lfo control source with reverse saw waveform */ +GST_START_TEST (controller_lfo_rsaw) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, + "frequency", 1.0, "timeshift", (GstClockTime) 0, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test lfo control source with saw waveform */ +GST_START_TEST (controller_lfo_triangle) +{ + GstControlSource *cs; + GstElement *elem; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new lfo control source */ + cs = gst_lfo_control_source_new (); + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + /* configure lfo */ + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, + "frequency", 1.0, "timeshift", (GstClockTime) 0, + "amplitude", 0.5, "offset", 0.5, NULL); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +/* test timed value handling in trigger mode */ +GST_START_TEST (controller_trigger_exact) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + gdouble raw_val; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_trigger_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + fail_if (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val)); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.5)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + + /* now pull in values for some timestamps */ + fail_unless (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val)); + + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + + GST_TEST_OBJ (elem)->val_int = 0; + fail_if (gst_control_source_get_value (cs, 1 * GST_SECOND, &raw_val)); + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + fail_unless (gst_control_source_get_value (cs, 2 * GST_SECOND, &raw_val)); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (controller_trigger_tolerance) +{ + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem; + gdouble raw_val; + + elem = gst_element_factory_make ("testobj", NULL); + + /* new interpolation control source */ + cs = gst_trigger_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), + gst_direct_control_binding_new (GST_OBJECT (elem), "int", cs))); + + g_object_set (cs, "tolerance", G_GINT64_CONSTANT (10), NULL); + + fail_if (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val)); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.5)); + fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0)); + + /* now pull in values for some timestamps */ + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND + 5); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50); + + GST_TEST_OBJ (elem)->val_int = 0; + gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0); + + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND - 5); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND); + fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); +} + +GST_END_TEST; + +GST_START_TEST (controller_proxy) +{ + GstControlBinding *cb, *cb2; + GstControlSource *cs; + GstTimedValueControlSource *tvcs; + GstElement *elem, *elem2; + GstClockTime time; + gint int1, int2; + GValue gval1 = G_VALUE_INIT, gval2 = G_VALUE_INIT; + GValue *val1, *val2; + + elem = gst_element_factory_make ("testobj", NULL); + elem2 = gst_element_factory_make ("testobj", NULL); + + /* proxy control binding from elem to elem2 */ + cb = gst_proxy_control_binding_new (GST_OBJECT (elem), "int", + GST_OBJECT (elem2), "int"); + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), cb)); + + /* test that no proxy does nothing */ + val1 = gst_control_binding_get_value (cb, 0); + fail_unless (val1 == NULL); + fail_if (gst_control_binding_get_value_array (cb, 0, 0, 1, &int1)); + fail_if (gst_control_binding_get_g_value_array (cb, 0, 0, 1, &gval1)); + + /* new interpolation control source */ + cs = gst_trigger_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + cb2 = gst_direct_control_binding_new (GST_OBJECT (elem2), "int", cs); + fail_unless (gst_object_add_control_binding (GST_OBJECT (elem2), cb2)); + + /* set control values */ + fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0)); + fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0)); + + /* now pull in values for some timestamps */ + time = 0 * GST_SECOND; + gst_object_sync_values (GST_OBJECT (elem), time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, 0); + val1 = gst_control_binding_get_value (cb, time); + val2 = gst_control_binding_get_value (cb2, time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (val1)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (val2)); + fail_unless (gst_control_binding_get_value_array (cb, time, 0, 1, &int1)); + fail_unless (gst_control_binding_get_value_array (cb2, time, 0, 1, &int2)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, int1); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, int2); + fail_unless (gst_control_binding_get_g_value_array (cb, time, 0, 1, &gval1)); + fail_unless (gst_control_binding_get_g_value_array (cb2, time, 0, 1, &gval2)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (&gval1)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (&gval2)); + g_value_unset (val1); + g_value_unset (val2); + g_free (val1); + g_free (val2); + g_value_unset (&gval1); + g_value_unset (&gval2); + + time = 1 * GST_SECOND; + gst_object_sync_values (GST_OBJECT (elem), time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, 100); + val1 = gst_control_binding_get_value (cb, time); + val2 = gst_control_binding_get_value (cb2, time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (val1)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (val2)); + fail_unless (gst_control_binding_get_value_array (cb, time, 0, 1, &int1)); + fail_unless (gst_control_binding_get_value_array (cb2, time, 0, 1, &int2)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, int1); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, int2); + fail_unless (gst_control_binding_get_g_value_array (cb, time, 0, 1, &gval1)); + fail_unless (gst_control_binding_get_g_value_array (cb2, time, 0, 1, &gval2)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (&gval1)); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, + g_value_get_int (&gval2)); + g_value_unset (val1); + g_value_unset (val2); + g_free (val1); + g_free (val2); + g_value_unset (&gval1); + g_value_unset (&gval2); + + /* test syncing on the original control binding */ + time = 0 * GST_SECOND; + gst_object_sync_values (GST_OBJECT (elem2), time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, 0); + + time = 1 * GST_SECOND; + gst_object_sync_values (GST_OBJECT (elem2), time); + fail_unless_equals_int (GST_TEST_OBJ (elem2)->val_int, 100); + + gst_object_unref (cs); + gst_object_unref (elem); + gst_object_unref (elem2); +} + +GST_END_TEST; + + +static Suite * +gst_controller_suite (void) +{ + Suite *s = suite_create ("Controller"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_checked_fixture (tc, setup, teardown); + tcase_add_test (tc, controller_controlsource_empty1); + tcase_add_test (tc, controller_controlsource_empty2); + tcase_add_test (tc, controller_interpolation_none); + tcase_add_test (tc, controller_interpolation_linear); + tcase_add_test (tc, controller_interpolation_cubic); + tcase_add_test (tc, controller_interpolation_cubic_too_few_cp); + tcase_add_test (tc, controller_interpolation_unset); + tcase_add_test (tc, controller_interpolation_unset_all); + tcase_add_test (tc, controller_interpolation_linear_absolute_value_array); + tcase_add_test (tc, controller_interpolation_linear_value_array); + tcase_add_test (tc, controller_interpolation_linear_invalid_values); + tcase_add_test (tc, controller_interpolation_linear_default_values); + tcase_add_test (tc, controller_interpolation_linear_disabled); + tcase_add_test (tc, controller_interpolation_set_from_list); + tcase_add_test (tc, controller_interpolation_linear_before_ts0); + tcase_add_test (tc, controller_interpolation_linear_enums); + tcase_add_test (tc, controller_timed_value_count); + tcase_add_test (tc, controller_lfo_sine); + tcase_add_test (tc, controller_lfo_sine_timeshift); + tcase_add_test (tc, controller_lfo_square); + tcase_add_test (tc, controller_lfo_saw); + tcase_add_test (tc, controller_lfo_rsaw); + tcase_add_test (tc, controller_lfo_triangle); + tcase_add_test (tc, controller_trigger_exact); + tcase_add_test (tc, controller_trigger_tolerance); + tcase_add_test (tc, controller_proxy); + + return s; +} + +GST_CHECK_MAIN (gst_controller); diff --git a/tests/check/libs/flowcombiner.c b/tests/check/libs/flowcombiner.c new file mode 100644 index 0000000..6c634c1 --- /dev/null +++ b/tests/check/libs/flowcombiner.c @@ -0,0 +1,248 @@ +/* GStreamer + * + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * Author: Thiago Santos + * + * flowcombiner.c: Unit test for GstFlowCombiner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static GstFlowReturn sink_flowret = GST_FLOW_OK; + +#define CHECK_COMBINED_FLOWS(f1, f2, f3, expected) \ +G_STMT_START { \ + combiner = gst_flow_combiner_new (); \ + gst_flow_combiner_add_pad (combiner, pad1); \ + gst_flow_combiner_add_pad (combiner, pad2); \ + gst_flow_combiner_add_pad (combiner, pad3); \ + sink_flowret = f1; \ + gst_pad_push (pad1, gst_buffer_new ()); \ + gst_flow_combiner_update_flow (combiner, f1); \ + sink_flowret = f2; \ + gst_pad_push (pad2, gst_buffer_new ()); \ + gst_flow_combiner_update_flow (combiner, f2); \ + sink_flowret = f3; \ + gst_pad_push (pad3, gst_buffer_new ()); \ + ret = gst_flow_combiner_update_flow (combiner, f3); \ + gst_flow_combiner_free (combiner); \ + fail_unless_equals_int (ret, expected); \ +} G_STMT_END + +static GstFlowReturn +_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + gst_buffer_unref (buf); + return sink_flowret; +} + +GST_START_TEST (test_combined_flows) +{ + GstFlowReturn ret; + GstFlowCombiner *combiner; + GstPad *pad1, *pad2, *pad3; + GstPad *peer1, *peer2, *peer3; + GstSegment segment; + + pad1 = gst_pad_new ("src1", GST_PAD_SRC); + pad2 = gst_pad_new ("src2", GST_PAD_SRC); + pad3 = gst_pad_new ("src3", GST_PAD_SRC); + + peer1 = gst_pad_new ("sink1", GST_PAD_SINK); + peer2 = gst_pad_new ("sink2", GST_PAD_SINK); + peer3 = gst_pad_new ("sink3", GST_PAD_SINK); + + gst_pad_set_chain_function (peer1, _sink_chain); + gst_pad_set_chain_function (peer2, _sink_chain); + gst_pad_set_chain_function (peer3, _sink_chain); + + gst_pad_link (pad1, peer1); + gst_pad_link (pad2, peer2); + gst_pad_link (pad3, peer3); + + gst_pad_set_active (peer1, TRUE); + gst_pad_set_active (peer2, TRUE); + gst_pad_set_active (peer3, TRUE); + gst_pad_set_active (pad1, TRUE); + gst_pad_set_active (pad2, TRUE); + gst_pad_set_active (pad3, TRUE); + + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (pad1, gst_event_new_stream_start ("p1")); + gst_pad_push_event (pad2, gst_event_new_stream_start ("p2")); + gst_pad_push_event (pad3, gst_event_new_stream_start ("p3")); + gst_pad_push_event (pad1, gst_event_new_segment (&segment)); + gst_pad_push_event (pad2, gst_event_new_segment (&segment)); + gst_pad_push_event (pad3, gst_event_new_segment (&segment)); + + /* ok */ + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_OK); + + /* not linked */ + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_NOT_LINKED, GST_FLOW_OK, + GST_FLOW_OK); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_EOS, GST_FLOW_OK, GST_FLOW_OK); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_NOT_LINKED, GST_FLOW_NOT_LINKED, + GST_FLOW_OK); + CHECK_COMBINED_FLOWS (GST_FLOW_NOT_LINKED, GST_FLOW_NOT_LINKED, + GST_FLOW_NOT_LINKED, GST_FLOW_NOT_LINKED); + + /* errors */ + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_ERROR, GST_FLOW_OK, + GST_FLOW_ERROR); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_CUSTOM_ERROR, GST_FLOW_OK, + GST_FLOW_CUSTOM_ERROR); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_NOT_NEGOTIATED, GST_FLOW_OK, + GST_FLOW_NOT_NEGOTIATED); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_NOT_NEGOTIATED, + GST_FLOW_NOT_NEGOTIATED); + CHECK_COMBINED_FLOWS (GST_FLOW_NOT_LINKED, GST_FLOW_ERROR, GST_FLOW_OK, + GST_FLOW_ERROR); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_ERROR, + GST_FLOW_ERROR); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_CUSTOM_ERROR, + GST_FLOW_CUSTOM_ERROR); + + /* flushing */ + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_OK, GST_FLOW_FLUSHING, + GST_FLOW_FLUSHING); + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_FLUSHING, GST_FLOW_OK, + GST_FLOW_FLUSHING); + CHECK_COMBINED_FLOWS (GST_FLOW_FLUSHING, GST_FLOW_FLUSHING, GST_FLOW_FLUSHING, + GST_FLOW_FLUSHING); + + /* eos */ + CHECK_COMBINED_FLOWS (GST_FLOW_OK, GST_FLOW_NOT_LINKED, GST_FLOW_EOS, + GST_FLOW_OK); + CHECK_COMBINED_FLOWS (GST_FLOW_EOS, GST_FLOW_OK, GST_FLOW_EOS, GST_FLOW_OK); + CHECK_COMBINED_FLOWS (GST_FLOW_EOS, GST_FLOW_EOS, GST_FLOW_EOS, GST_FLOW_EOS); + + /* eos + not-linked */ + CHECK_COMBINED_FLOWS (GST_FLOW_NOT_LINKED, GST_FLOW_EOS, GST_FLOW_EOS, + GST_FLOW_EOS); + CHECK_COMBINED_FLOWS (GST_FLOW_NOT_LINKED, GST_FLOW_NOT_LINKED, GST_FLOW_EOS, + GST_FLOW_EOS); + + gst_object_unref (pad1); + gst_object_unref (pad2); + gst_object_unref (pad3); + gst_object_unref (peer1); + gst_object_unref (peer2); + gst_object_unref (peer3); +} + +GST_END_TEST; + +GST_START_TEST (test_clear) +{ + GstFlowCombiner *combiner; + GstPad *pad; + GstPad *peer; + GstSegment segment; + GstFlowReturn ret; + + combiner = gst_flow_combiner_new (); + + /* add a pad and make it return _FLUSHING */ + pad = gst_pad_new ("src1", GST_PAD_SRC); + peer = gst_pad_new ("sink1", GST_PAD_SINK); + gst_pad_set_chain_function (peer, _sink_chain); + gst_pad_link (pad, peer); + gst_pad_set_active (peer, TRUE); + gst_pad_set_active (pad, TRUE); + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (pad, gst_event_new_stream_start ("test1")); + gst_pad_push_event (pad, gst_event_new_segment (&segment)); + gst_flow_combiner_add_pad (combiner, pad); + sink_flowret = GST_FLOW_FLUSHING; + fail_unless_equals_int (gst_pad_push (pad, gst_buffer_new ()), + GST_FLOW_FLUSHING); + + /* the combined flow is _FLUSHING */ + ret = gst_flow_combiner_update_flow (combiner, GST_FLOW_FLUSHING); + fail_unless_equals_int (ret, GST_FLOW_FLUSHING); + gst_object_unref (pad); + gst_object_unref (peer); + + /* add one more pad and make it return _OK */ + pad = gst_pad_new ("src2", GST_PAD_SRC); + peer = gst_pad_new ("sink2", GST_PAD_SINK); + gst_pad_set_chain_function (peer, _sink_chain); + gst_pad_link (pad, peer); + gst_pad_set_active (peer, TRUE); + gst_pad_set_active (pad, TRUE); + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (pad, gst_event_new_stream_start ("test2")); + gst_pad_push_event (pad, gst_event_new_segment (&segment)); + gst_flow_combiner_add_pad (combiner, pad); + sink_flowret = GST_FLOW_OK; + fail_unless_equals_int (gst_pad_push (pad, gst_buffer_new ()), GST_FLOW_OK); + + /* the combined flow is _FLUSHING because of the first pad */ + ret = gst_flow_combiner_update_flow (combiner, GST_FLOW_OK); + fail_unless_equals_int (ret, GST_FLOW_FLUSHING); + gst_object_unref (pad); + gst_object_unref (peer); + + /* clear the combiner */ + gst_flow_combiner_clear (combiner); + + /* add a pad and make it return _OK */ + pad = gst_pad_new ("src3", GST_PAD_SRC); + peer = gst_pad_new ("sink3", GST_PAD_SINK); + gst_pad_set_chain_function (peer, _sink_chain); + gst_pad_link (pad, peer); + gst_pad_set_active (peer, TRUE); + gst_pad_set_active (pad, TRUE); + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (pad, gst_event_new_stream_start ("test3")); + gst_pad_push_event (pad, gst_event_new_segment (&segment)); + gst_flow_combiner_add_pad (combiner, pad); + sink_flowret = GST_FLOW_OK; + fail_unless_equals_int (gst_pad_push (pad, gst_buffer_new ()), GST_FLOW_OK); + + /* the combined flow is _OK since the other pads have been removed */ + ret = gst_flow_combiner_update_flow (combiner, GST_FLOW_OK); + fail_unless_equals_int (ret, GST_FLOW_OK); + gst_object_unref (pad); + gst_object_unref (peer); + + gst_flow_combiner_free (combiner); +} + +GST_END_TEST; + +static Suite * +flow_combiner_suite (void) +{ + Suite *s = suite_create ("GstFlowCombiner"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_combined_flows); + tcase_add_test (tc_chain, test_clear); + + return s; +} + +GST_CHECK_MAIN (flow_combiner); diff --git a/tests/check/libs/gstharness.c b/tests/check/libs/gstharness.c new file mode 100644 index 0000000..633d538 --- /dev/null +++ b/tests/check/libs/gstharness.c @@ -0,0 +1,269 @@ +/* + * Tests and examples of GstHarness + * + * Copyright (C) 2015 Havard Graff + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 void +create_destroy_element_harness (gpointer data, gpointer user_data) +{ + GstElement *element = user_data; + GstHarness *h = gst_harness_new_with_element (element, NULL, NULL); + gst_harness_teardown (h); +} + +GST_START_TEST (test_harness_element_ref) +{ + GstHarness *h = gst_harness_new ("identity"); + GstHarnessThread *threads[100]; + gint i; + + for (i = 0; i < G_N_ELEMENTS (threads); i++) + threads[i] = gst_harness_stress_custom_start (h, NULL, + create_destroy_element_harness, h->element, 0); + for (i = 0; i < G_N_ELEMENTS (threads); i++) + gst_harness_stress_thread_stop (threads[i]); + + fail_unless_equals_int (G_OBJECT (h->element)->ref_count, 1); + + gst_harness_teardown (h); +} + +GST_END_TEST; + + +GST_START_TEST (test_src_harness) +{ + GstHarness *h = gst_harness_new ("identity"); + + /* add a fakesrc that syncs to the clock and a + capsfilter that adds some caps to it */ + gst_harness_add_src_parse (h, + "fakesrc sync=1 ! capsfilter caps=\"mycaps\"", TRUE); + + /* this cranks the clock and transfers the resulting buffer + from the src-harness into the identity element */ + gst_harness_push_from_src (h); + + /* verify that identity outputs a buffer by pulling and unreffing */ + gst_buffer_unref (gst_harness_pull (h)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_src_harness_no_forwarding) +{ + GstHarness *h = gst_harness_new ("identity"); + + /* turn of forwarding of necessary events */ + gst_harness_set_forwarding (h, FALSE); + + /* add a fakesrc that syncs to the clock and a + capsfilter that adds some caps to it */ + gst_harness_add_src_parse (h, + "fakesrc sync=1 ! capsfilter caps=\"mycaps\"", TRUE); + + /* start the fakesrc to produce the first events */ + gst_harness_play (h->src_harness); + + /* transfer STREAM_START event */ + gst_harness_src_push_event (h); + + /* crank the clock to produce the CAPS and SEGMENT events */ + gst_harness_crank_single_clock_wait (h->src_harness); + + /* transfer CAPS event */ + gst_harness_src_push_event (h); + + /* transfer SEGMENT event */ + gst_harness_src_push_event (h); + + /* now transfer the buffer produced by exploiting + the ability to say 0 cranks but 1 push */ + gst_harness_src_crank_and_push_many (h, 0, 1); + + /* and verify that the identity element outputs it */ + gst_buffer_unref (gst_harness_pull (h)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_add_sink_harness_without_sinkpad) +{ + GstHarness *h = gst_harness_new ("fakesink"); + + gst_harness_add_sink (h, "fakesink"); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +static GstEvent * +create_new_stream_start_event (GstHarness * h, gpointer data) +{ + guint *counter = data; + gchar *stream_id = g_strdup_printf ("streamid/%d", *counter); + GstEvent *event = gst_event_new_stream_start (stream_id); + g_free (stream_id); + (*counter)++; + return event; +} + +static void +push_query (gpointer data, gpointer user_data) +{ + GstHarness *h = user_data; + GstCaps *caps = gst_caps_new_empty_simple ("mycaps"); + GstQuery *query = gst_query_new_allocation (caps, FALSE); + gst_caps_unref (caps); + gst_pad_peer_query (h->srcpad, query); + gst_query_unref (query); +} + +GST_START_TEST (test_forward_event_and_query_to_sink_harness_while_teardown) +{ + GstHarness *h = gst_harness_new ("identity"); + guint counter = 0; + GstHarnessThread *e_thread = gst_harness_stress_push_event_with_cb_start (h, + create_new_stream_start_event, &counter, NULL); + GstHarnessThread *q_thread = gst_harness_stress_custom_start (h, NULL, + push_query, h, 0); + gdouble duration = 1.0; + GTimer *timer = g_timer_new (); + + while (g_timer_elapsed (timer, NULL) < duration) { + gst_harness_add_sink (h, "fakesink"); + g_thread_yield (); + } + + g_timer_destroy (timer); + gst_harness_stress_thread_stop (q_thread); + gst_harness_stress_thread_stop (e_thread); + gst_harness_teardown (h); +} + +GST_END_TEST; + +static GstHarness * +harness_new_and_fill_with_data (void) +{ + GstHarness *h = gst_harness_new_parse ("fakesrc num-buffers=5 " + "filltype=pattern-span sizetype=fixed sizemin=10 sizemax=10"); + gboolean have_eos = FALSE; + + gst_harness_play (h); + + do { + GstEvent *e = gst_harness_pull_event (h); + have_eos = GST_EVENT_TYPE (e) == GST_EVENT_EOS; + gst_event_unref (e); + } while (!have_eos); + + return h; +} + +GST_START_TEST (test_get_all_data) +{ + guint8 expected[50]; + const guint8 *cdata; + GstHarness *h; + GstBuffer *buf; + GBytes *bytes; + guint8 *data; + gsize size; + guint i; + + for (i = 0; i < G_N_ELEMENTS (expected); ++i) + expected[i] = i; + + h = harness_new_and_fill_with_data (); + buf = gst_harness_take_all_data_as_buffer (h); + fail_unless (buf != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf), 5 * 10); + fail_unless (gst_buffer_memcmp (buf, 0, expected, 5 * 10) == 0); + gst_buffer_unref (buf); + /* There should be nothing left now. We should still get a non-NULL buffer */ + buf = gst_harness_take_all_data_as_buffer (h); + fail_unless (buf != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf), 0); + gst_buffer_unref (buf); + gst_harness_teardown (h); + + h = harness_new_and_fill_with_data (); + bytes = gst_harness_take_all_data_as_bytes (h); + fail_unless (bytes != NULL); + cdata = g_bytes_get_data (bytes, &size); + fail_unless_equals_int (size, 5 * 10); + fail_unless (memcmp (cdata, expected, 50) == 0); + g_bytes_unref (bytes); + /* There should be nothing left now. We should still get a non-NULL bytes */ + bytes = gst_harness_take_all_data_as_bytes (h); + fail_unless (bytes != NULL); + cdata = g_bytes_get_data (bytes, &size); + fail_unless (cdata == NULL); + fail_unless_equals_int (size, 0); + g_bytes_unref (bytes); + gst_harness_teardown (h); + + h = harness_new_and_fill_with_data (); + data = gst_harness_take_all_data (h, &size); + fail_unless (data != NULL); + fail_unless_equals_int (size, 5 * 10); + fail_unless (memcmp (data, expected, 50) == 0); + g_free (data); + /* There should be nothing left now. */ + data = gst_harness_take_all_data (h, &size); + fail_unless (data == NULL); + fail_unless_equals_int (size, 0); + gst_harness_teardown (h); +} + +GST_END_TEST; + +static Suite * +gst_harness_suite (void) +{ + Suite *s = suite_create ("GstHarness"); + TCase *tc_chain = tcase_create ("harness"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_harness_element_ref); + tcase_add_test (tc_chain, test_src_harness); + tcase_add_test (tc_chain, test_src_harness_no_forwarding); + tcase_add_test (tc_chain, test_add_sink_harness_without_sinkpad); + + tcase_add_test (tc_chain, + test_forward_event_and_query_to_sink_harness_while_teardown); + tcase_add_test (tc_chain, test_get_all_data); + + return s; +} + +GST_CHECK_MAIN (gst_harness); diff --git a/tests/check/libs/gstlibscpp.cc b/tests/check/libs/gstlibscpp.cc new file mode 100644 index 0000000..bee2588 --- /dev/null +++ b/tests/check/libs/gstlibscpp.cc @@ -0,0 +1,63 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#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; + +GST_START_TEST (test_init_macros) +{ + GstBitReader bit_reader = GST_BIT_READER_INIT (NULL, 0); + GstByteReader byte_reader = GST_BYTE_READER_INIT (NULL, 0); + + fail_unless (bit_reader.data == NULL); + fail_unless (byte_reader.data == 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); + tcase_add_test (tc_chain, test_init_macros); + + return s; +} + +GST_CHECK_MAIN (libscpp); diff --git a/tests/check/libs/gstnetclientclock.c b/tests/check/libs/gstnetclientclock.c new file mode 100644 index 0000000..06ce006 --- /dev/null +++ b/tests/check/libs/gstnetclientclock.c @@ -0,0 +1,136 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * gstnetclientclock.c: Unit test for the network client clock + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_instantiation) +{ + GstClock *client, *local; + + local = gst_system_clock_obtain (); + client = gst_net_client_clock_new (NULL, "127.0.0.1", 1234, GST_SECOND); + fail_unless (local != NULL, "failed to get system clock"); + fail_unless (client != NULL, "failed to get network client clock"); + + /* one for gstreamer, one for us */ + ASSERT_OBJECT_REFCOUNT (local, "system clock", 2); + ASSERT_OBJECT_REFCOUNT (client, "network client clock", 1); + + gst_object_unref (client); + + ASSERT_OBJECT_REFCOUNT (local, "system clock", 2); + + gst_object_unref (local); +} + +GST_END_TEST; + +GST_START_TEST (test_functioning) +{ + GstNetTimeProvider *ntp; + GstClock *client, *server; + GstClockTime basex, basey, rate_num, rate_denom; + GstClockTime servtime, clienttime, diff; + gint port; + gchar sign; + + server = gst_system_clock_obtain (); + fail_unless (server != NULL, "failed to get system clock"); + + /* move the clock ahead 100 seconds */ + gst_clock_get_calibration (server, &basex, &basey, &rate_num, &rate_denom); + basey += 100 * GST_SECOND; + gst_clock_set_calibration (server, basex, basey, rate_num, rate_denom); + + ntp = gst_net_time_provider_new (server, "127.0.0.1", 0); + fail_unless (ntp != NULL, "failed to create network time provider"); + + g_object_get (ntp, "port", &port, NULL); + + client = gst_net_client_clock_new (NULL, "127.0.0.1", port, GST_SECOND); + fail_unless (client != NULL, "failed to get network client clock"); + + g_object_get (client, "port", &port, NULL); + + /* let the clocks synchronize */ + gst_clock_wait_for_sync (GST_CLOCK (client), GST_SECOND); + + servtime = gst_clock_get_time (server); + clienttime = gst_clock_get_time (client); + + if (servtime > clienttime) { + sign = '-'; + diff = servtime - clienttime; + } else { + sign = '+'; + diff = clienttime - servtime; + } + + GST_LOG ("server time: %" GST_TIME_FORMAT, GST_TIME_ARGS (servtime)); + GST_LOG ("client time: %" GST_TIME_FORMAT, GST_TIME_ARGS (clienttime)); + GST_LOG ("diff : %c%" GST_TIME_FORMAT, sign, GST_TIME_ARGS (diff)); + + /* can't in general make a precise assertion here, because this depends on + * system load and a lot of things. however within half a second they should + * at least be within 1/10 of a second of each other... */ + if (diff > 100 * GST_MSECOND) + fail ("clocks not in sync (%" GST_TIME_FORMAT ")", diff); + + /* + g_print ("diff: %" GST_TIME_FORMAT, + GST_TIME_ARGS (servtime > clienttime ? servtime - clienttime + : clienttime - servtime)); + */ + + /* one for gstreamer, one for ntp, one for us */ + ASSERT_OBJECT_REFCOUNT (server, "system clock", 3); + ASSERT_OBJECT_REFCOUNT (client, "network client clock", 1); + + gst_object_unref (ntp); + + ASSERT_OBJECT_REFCOUNT (server, "system clock", 2); + + gst_object_unref (client); + gst_object_unref (server); +} + +GST_END_TEST; + +static Suite * +gst_net_client_clock_suite (void) +{ + Suite *s = suite_create ("GstNetClientClock"); + TCase *tc_chain = tcase_create ("generic tests"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_instantiation); + tcase_add_test (tc_chain, test_functioning); + + return s; +} + +GST_CHECK_MAIN (gst_net_client_clock); diff --git a/tests/check/libs/gstnettimeprovider.c b/tests/check/libs/gstnettimeprovider.c new file mode 100644 index 0000000..ac5e94d --- /dev/null +++ b/tests/check/libs/gstnettimeprovider.c @@ -0,0 +1,123 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * gstnettimeprovider.c: Unit test for the network time provider + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +GST_START_TEST (test_refcounts) +{ + GstNetTimeProvider *ntp; + GstClock *clock; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "failed to get system clock"); + + /* one for gstreamer, one for us */ + ASSERT_OBJECT_REFCOUNT (clock, "system clock", 2); + + ntp = gst_net_time_provider_new (clock, NULL, 0); + fail_unless (ntp != NULL, "failed to create net time provider"); + + /* one for ntp, one for gstreamer, one for us */ + ASSERT_OBJECT_REFCOUNT (clock, "system clock", 3); + /* one for us */ + ASSERT_OBJECT_REFCOUNT (ntp, "net time provider", 1); + + gst_object_unref (ntp); + ASSERT_OBJECT_REFCOUNT (clock, "net time provider", 2); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_functioning) +{ + GstNetTimeProvider *ntp; + GstNetTimePacket *packet; + GstClock *clock; + GstClockTime local; + GSocketAddress *server_addr; + GInetAddress *addr; + GSocket *socket; + gint port = -1; + + clock = gst_system_clock_obtain (); + fail_unless (clock != NULL, "failed to get system clock"); + ntp = gst_net_time_provider_new (clock, "127.0.0.1", 0); + fail_unless (ntp != NULL, "failed to create net time provider"); + + g_object_get (ntp, "port", &port, NULL); + fail_unless (port > 0); + + socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + fail_unless (socket != NULL, "could not create socket"); + + addr = g_inet_address_new_from_string ("127.0.0.1"); + server_addr = g_inet_socket_address_new (addr, port); + g_object_unref (addr); + + packet = gst_net_time_packet_new (NULL); + fail_unless (packet != NULL, "failed to create packet"); + + packet->local_time = local = gst_clock_get_time (clock); + + fail_unless (gst_net_time_packet_send (packet, socket, server_addr, NULL)); + + g_free (packet); + + packet = gst_net_time_packet_receive (socket, NULL, NULL); + + fail_unless (packet != NULL, "failed to receive packet"); + fail_unless (packet->local_time == local, "local time is not the same"); + fail_unless (packet->remote_time > local, "remote time not after local time"); + fail_unless (packet->remote_time < gst_clock_get_time (clock), + "remote time in the future"); + + g_free (packet); + + g_object_unref (socket); + g_object_unref (server_addr); + + gst_object_unref (ntp); + gst_object_unref (clock); +} + +GST_END_TEST; + +static Suite * +gst_net_time_provider_suite (void) +{ + Suite *s = suite_create ("GstNetTimeProvider"); + TCase *tc_chain = tcase_create ("generic tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_refcounts); + tcase_add_test (tc_chain, test_functioning); + + return s; +} + +GST_CHECK_MAIN (gst_net_time_provider); diff --git a/tests/check/libs/gsttestclock.c b/tests/check/libs/gsttestclock.c new file mode 100644 index 0000000..e3b86fd --- /dev/null +++ b/tests/check/libs/gsttestclock.c @@ -0,0 +1,1082 @@ +/* + * Unit test for a deterministic clock for Gstreamer unit tests + * + * Copyright (C) 2008 Ole André Vadla Ravnås + * Copyright (C) 2012 Sebastian Rasmussen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +typedef struct +{ + GstTestClock *test_clock; + GstClockID id; + GstClockTime reference; +} GtuClockWaitContext; + +typedef struct +{ + GstClockID clock_id; + GstClockTimeDiff jitter; +} SyncClockWaitContext; + +#define assert_pending_id(pending_id, id, type, time) \ +G_STMT_START { \ + GstClockEntry *entry = GST_CLOCK_ENTRY (pending_id); \ + g_assert (entry == (id)); \ + g_assert (GST_CLOCK_ENTRY_TYPE (entry) == (type)); \ + g_assert_cmpuint (GST_CLOCK_ENTRY_TIME (entry), ==, (time)); \ +} G_STMT_END + +#define assert_processed_id(processed_id, id, type, time) \ +G_STMT_START { \ + GstClockEntry *entry = GST_CLOCK_ENTRY (processed_id); \ + g_assert (entry == (id)); \ + g_assert (GST_CLOCK_ENTRY_TYPE (entry) == (type)); \ + g_assert_cmpuint (GST_CLOCK_ENTRY_STATUS (entry), ==, (time)); \ +} G_STMT_END + +static gpointer test_wait_pending_single_shot_id_sync_worker (gpointer data); +static gpointer test_wait_pending_single_shot_id_async_worker (gpointer data); +static gpointer test_wait_pending_periodic_id_waiter_thread (gpointer data); +static gboolean test_async_wait_cb (GstClock * clock, GstClockTime time, + GstClockID id, gpointer user_data); + +static GtuClockWaitContext *gst_test_util_wait_for_clock_id_begin (GstTestClock + * clock, GstClockID id, GstClockTimeDiff * jitter); +static GstClockReturn gst_test_util_wait_for_clock_id_end (GtuClockWaitContext * + wait_ctx); +static gboolean +gst_test_util_clock_wait_context_has_completed (GtuClockWaitContext * wait_ctx); + +static gpointer +test_wait_pending_single_shot_id_sync_worker (gpointer data) +{ + SyncClockWaitContext *ctx = data; + + gst_clock_id_wait (ctx->clock_id, &ctx->jitter); + + return NULL; +} + +static gpointer +test_wait_pending_single_shot_id_async_worker (gpointer data) +{ + GstClockID clock_id = data; + + g_usleep (G_USEC_PER_SEC / 10); + gst_clock_id_wait_async (clock_id, test_async_wait_cb, NULL, NULL); + + return NULL; +} + +static gpointer +test_wait_pending_periodic_id_waiter_thread (gpointer data) +{ + GstClockID clock_id = data; + gst_clock_id_wait (clock_id, NULL); + return NULL; +} + +static gboolean +test_async_wait_cb (GstClock * clock, + GstClockTime time, GstClockID id, gpointer user_data) +{ + + gboolean *wait_complete = user_data; + + if (wait_complete != NULL) + *wait_complete = TRUE; + + return TRUE; +} + +static GtuClockWaitContext * +gst_test_util_wait_for_clock_id_begin (GstTestClock * test_clock, GstClockID id, + GstClockTimeDiff * jitter) +{ + GtuClockWaitContext *wait_ctx; + + wait_ctx = g_slice_new (GtuClockWaitContext); + wait_ctx->test_clock = gst_object_ref (test_clock); + wait_ctx->reference = gst_clock_get_time (GST_CLOCK (wait_ctx->test_clock)); + wait_ctx->id = gst_clock_id_ref (id); + + if (jitter) { + GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id); + GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry); + GstClockTime reference = wait_ctx->reference; + + *jitter = GST_CLOCK_DIFF (requested, reference); + } + + if (!gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)) { + GstClockClass *klass = GST_CLOCK_GET_CLASS (wait_ctx->test_clock); + GstClock *clock = GST_CLOCK (wait_ctx->test_clock); + g_assert (klass->wait_async (clock, wait_ctx->id) == GST_CLOCK_OK); + } + + g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)); + g_assert_cmpint (gst_test_clock_peek_id_count (wait_ctx->test_clock), >, 0); + + return wait_ctx; +} + +static GstClockReturn +gst_test_util_wait_for_clock_id_end (GtuClockWaitContext * wait_ctx) +{ + GstClockReturn status = GST_CLOCK_ERROR; + GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id); + + if (G_UNLIKELY (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)) { + status = GST_CLOCK_UNSCHEDULED; + } else { + GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry); + GstClockTimeDiff diff; + + g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)); + + diff = GST_CLOCK_DIFF (requested, wait_ctx->reference); + + if (diff > 0) { + status = GST_CLOCK_EARLY; + } else { + status = GST_CLOCK_OK; + } + + g_atomic_int_set (&GST_CLOCK_ENTRY_STATUS (entry), status); + } + + if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_SINGLE) { + GstClockClass *klass = GST_CLOCK_GET_CLASS (wait_ctx->test_clock); + GstClock *clock = GST_CLOCK (wait_ctx->test_clock); + + klass->unschedule (clock, wait_ctx->id); + g_assert (!gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)); + } else { + GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry); + g_assert (gst_test_clock_has_id (wait_ctx->test_clock, wait_ctx->id)); + } + + gst_clock_id_unref (wait_ctx->id); + gst_object_unref (wait_ctx->test_clock); + g_slice_free (GtuClockWaitContext, wait_ctx); + + return status; +} + +static gboolean +gst_test_util_clock_wait_context_has_completed (GtuClockWaitContext * wait_ctx) +{ + GstClock *clock = GST_CLOCK (wait_ctx->test_clock); + GstClockEntry *entry = GST_CLOCK_ENTRY (wait_ctx->id); + GstClockTime requested = GST_CLOCK_ENTRY_TIME (entry); + GstClockTime now = gst_clock_get_time (clock); + + return requested < now; +} + +GST_START_TEST (test_object_flags) +{ + GstClock *clock = gst_test_clock_new (); + g_assert (GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC)); + g_assert (GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC)); + g_assert (GST_OBJECT_FLAG_IS_SET (clock, + GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC)); + g_assert (GST_OBJECT_FLAG_IS_SET (clock, + GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC)); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_resolution_query) +{ + GstClock *clock = gst_test_clock_new (); + g_assert_cmpuint (gst_clock_get_resolution (clock), ==, 1); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_start_time) +{ + GstClock *clock; + guint64 start_time; + + clock = gst_test_clock_new (); + g_assert_cmpuint (gst_clock_get_time (clock), ==, 0); + g_object_get (clock, "start-time", &start_time, NULL); + g_assert_cmpuint (start_time, ==, 0); + gst_object_unref (clock); + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND); + g_object_get (clock, "start-time", &start_time, NULL); + g_assert_cmpuint (start_time, ==, GST_SECOND); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_set_time) +{ + GstClock *clock = gst_test_clock_new_with_start_time (GST_SECOND); + gst_test_clock_set_time (GST_TEST_CLOCK (clock), GST_SECOND); + g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND); + gst_test_clock_set_time (GST_TEST_CLOCK (clock), GST_SECOND + 1); + g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND + 1); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_advance_time) +{ + GstClock *clock = gst_test_clock_new_with_start_time (GST_SECOND); + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 0); + g_assert_cmpuint (gst_clock_get_time (clock), ==, GST_SECOND); + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 42 * GST_MSECOND); + g_assert_cmpuint (gst_clock_get_time (clock), ==, + GST_SECOND + (42 * GST_MSECOND)); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_wait_synchronous_no_timeout) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GThread *worker_thread; + GstClockID pending_id; + GstClockID processed_id; + SyncClockWaitContext context; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1); + context.clock_id = gst_clock_id_ref (clock_id); + context.jitter = 0; + worker_thread = + g_thread_new ("worker_thread", + test_wait_pending_single_shot_id_sync_worker, &context); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_SECOND - 1); + gst_clock_id_unref (pending_id); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_EARLY); + gst_clock_id_unref (processed_id); + g_thread_join (worker_thread); + g_assert_cmpuint (context.jitter, ==, 1); + gst_clock_id_unref (context.clock_id); + gst_clock_id_unref (clock_id); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND); + context.clock_id = gst_clock_id_ref (clock_id); + context.jitter = 0; + worker_thread = + g_thread_new ("worker_thread", + test_wait_pending_single_shot_id_sync_worker, &context); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, GST_SECOND); + gst_clock_id_unref (pending_id); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + g_thread_join (worker_thread); + g_assert_cmpuint (context.jitter, ==, 0); + gst_clock_id_unref (context.clock_id); + gst_clock_id_unref (clock_id); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND + 1); + context.clock_id = gst_clock_id_ref (clock_id); + context.jitter = 0; + worker_thread = + g_thread_new ("worker_thread", + test_wait_pending_single_shot_id_sync_worker, &context); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_SECOND + 1); + gst_clock_id_unref (pending_id); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + g_assert (processed_id == NULL); + gst_test_clock_advance_time (test_clock, 1); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + g_thread_join (worker_thread); + g_assert_cmpuint (context.jitter, ==, -1); + gst_clock_id_unref (context.clock_id); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_wait_pending_single_shot_id) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GstClockID processed_id; + GThread *worker_thread; + GstClockID pending_id; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND); + gst_clock_id_wait_async (clock_id, test_async_wait_cb, NULL, NULL); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, GST_SECOND); + gst_clock_id_unref (pending_id); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + gst_clock_id_unref (clock_id); + + clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + worker_thread = + g_thread_new ("worker_thread", + test_wait_pending_single_shot_id_async_worker, clock_id); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + 2 * GST_SECOND); + gst_clock_id_unref (pending_id); + g_thread_join (worker_thread); + gst_clock_id_unref (clock_id); + + clock_id = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND); + worker_thread = + g_thread_new ("worker_thread", + test_wait_pending_single_shot_id_async_worker, clock_id); + gst_test_clock_wait_for_next_pending_id (test_clock, NULL); + g_thread_join (worker_thread); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_wait_pending_periodic_id) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GstClockID processed_id; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + clock_id = gst_clock_new_periodic_id (clock, GST_SECOND, GST_MSECOND); + + { + GThread *waiter_thread; + + waiter_thread = + g_thread_new ("waiter_thread", + test_wait_pending_periodic_id_waiter_thread, clock_id); + + gst_test_clock_wait_for_next_pending_id (test_clock, NULL); + gst_test_clock_set_time (test_clock, GST_SECOND); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + + g_thread_join (waiter_thread); + } + + { + guint i; + GThread *waiter_thread; + + for (i = 0; i < 3; i++) { + g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL)); + g_usleep (G_USEC_PER_SEC / 10 / 10); + } + + waiter_thread = + g_thread_new ("waiter_thread", + test_wait_pending_periodic_id_waiter_thread, clock_id); + + gst_test_clock_wait_for_next_pending_id (test_clock, NULL); + gst_clock_id_unschedule (clock_id); + + g_thread_join (waiter_thread); + } + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_past) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GstClockTimeDiff jitter; + GtuClockWaitContext *wait_ctx; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1); + wait_ctx = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_EARLY); + g_assert_cmpint (jitter, ==, 1); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_present) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GstClockTimeDiff jitter; + GtuClockWaitContext *wait_ctx; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND); + wait_ctx = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK); + g_assert_cmpint (jitter, ==, 0); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_future) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GstClockTimeDiff jitter; + GtuClockWaitContext *wait_ctx; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + wait_ctx = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, &jitter); + gst_test_clock_advance_time (test_clock, GST_SECOND); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) == GST_CLOCK_OK); + g_assert_cmpint (jitter, ==, -GST_SECOND); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_unschedule) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + GtuClockWaitContext *wait_ctx; + gboolean wait_complete = FALSE; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND); + gst_clock_id_unschedule (clock_id); + /* any wait should timeout immediately */ + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_UNSCHEDULED); + g_assert (gst_clock_id_wait (clock_id, NULL) == GST_CLOCK_UNSCHEDULED); + gst_clock_id_unref (clock_id); + + clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + wait_ctx = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL); + gst_clock_id_unschedule (clock_id); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx) + == GST_CLOCK_UNSCHEDULED); + gst_clock_id_unref (clock_id); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_ordering) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id_a, clock_id_b; + GtuClockWaitContext *wait_ctx_a, *wait_ctx_b; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id_a = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND); + wait_ctx_a = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_a, NULL); + + gst_test_clock_advance_time (test_clock, GST_SECOND); + + clock_id_b = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + wait_ctx_b = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_b, NULL); + + gst_test_clock_advance_time (test_clock, GST_SECOND); + + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK); + + gst_clock_id_unref (clock_id_b); + gst_clock_id_unref (clock_id_a); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_ordering_parallel) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id_a, clock_id_b; + GtuClockWaitContext *wait_ctx_a, *wait_ctx_b; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id_a = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND); + clock_id_b = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + wait_ctx_a = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_a, + NULL); + wait_ctx_b = gst_test_util_wait_for_clock_id_begin (test_clock, clock_id_b, + NULL); + + g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==, + 2 * GST_SECOND); + gst_test_clock_advance_time (test_clock, GST_SECOND); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_b) == GST_CLOCK_OK); + + g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==, + 3 * GST_SECOND); + gst_test_clock_advance_time (test_clock, GST_SECOND); + g_assert (gst_test_util_wait_for_clock_id_end (wait_ctx_a) == GST_CLOCK_OK); + + gst_clock_id_unref (clock_id_b); + gst_clock_id_unref (clock_id_a); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_sync_simultaneous_no_timeout) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id_a; + GstClockID clock_id_b; + SyncClockWaitContext context_a; + SyncClockWaitContext context_b; + GThread *worker_thread_a; + GThread *worker_thread_b; + GstClockID processed_id; + GstClockID pending_id; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + clock_id_a = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND); + clock_id_b = gst_clock_new_single_shot_id (clock, 6 * GST_SECOND); + + context_a.clock_id = gst_clock_id_ref (clock_id_a); + context_a.jitter = 0; + context_b.clock_id = gst_clock_id_ref (clock_id_b); + context_b.jitter = 0; + + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 0, NULL); + + worker_thread_b = + g_thread_new ("worker_thread_b", + test_wait_pending_single_shot_id_sync_worker, &context_b); + + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 1, NULL); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE, + 6 * GST_SECOND); + gst_clock_id_unref (pending_id); + + worker_thread_a = + g_thread_new ("worker_thread_a", + test_wait_pending_single_shot_id_sync_worker, &context_a); + + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 2, NULL); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id_a, GST_CLOCK_ENTRY_SINGLE, + 5 * GST_SECOND); + gst_clock_id_unref (pending_id); + + g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==, + 5 * GST_SECOND); + gst_test_clock_advance_time (test_clock, 5 * GST_SECOND); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id_a, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 1, NULL); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE, + 6 * GST_SECOND); + gst_clock_id_unref (pending_id); + + g_assert_cmpuint (gst_test_clock_get_next_entry_time (test_clock), ==, + 6 * GST_SECOND); + gst_test_clock_advance_time (test_clock, 6 * GST_SECOND); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + assert_processed_id (processed_id, clock_id_b, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 0, NULL); + + g_thread_join (worker_thread_a); + g_thread_join (worker_thread_b); + + g_assert_cmpuint (context_a.jitter, ==, -4 * GST_SECOND); + g_assert_cmpuint (context_b.jitter, ==, -5 * GST_SECOND); + + gst_clock_id_unref (context_a.clock_id); + gst_clock_id_unref (context_b.clock_id); + + gst_clock_id_unref (clock_id_a); + gst_clock_id_unref (clock_id_b); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_processing_multiple_ids) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id_a; + GstClockID clock_id_b; + SyncClockWaitContext context_a; + SyncClockWaitContext context_b; + GThread *worker_thread_a; + GThread *worker_thread_b; + GList *pending_list = NULL; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + /* register a wait for 5 seconds */ + clock_id_a = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND); + context_a.clock_id = gst_clock_id_ref (clock_id_a); + context_a.jitter = 0; + worker_thread_a = + g_thread_new ("worker_thread_a", + test_wait_pending_single_shot_id_sync_worker, &context_a); + + /* register another wait for 6 seconds */ + clock_id_b = gst_clock_new_single_shot_id (clock, 6 * GST_SECOND); + context_b.clock_id = gst_clock_id_ref (clock_id_b); + context_b.jitter = 0; + worker_thread_b = + g_thread_new ("worker_thread_b", + test_wait_pending_single_shot_id_sync_worker, &context_b); + + /* wait for two waits */ + gst_test_clock_wait_for_multiple_pending_ids (test_clock, 2, &pending_list); + + /* assert they are correct */ + assert_pending_id (pending_list->data, clock_id_a, GST_CLOCK_ENTRY_SINGLE, + 5 * GST_SECOND); + assert_pending_id (pending_list->next->data, clock_id_b, + GST_CLOCK_ENTRY_SINGLE, 6 * GST_SECOND); + + /* verify we are waiting for 6 seconds as the latest time */ + fail_unless_equals_int64 (6 * GST_SECOND, + gst_test_clock_id_list_get_latest_time (pending_list)); + + /* process both ID's at the same time */ + gst_test_clock_process_id_list (test_clock, pending_list); + g_list_free_full (pending_list, (GDestroyNotify) gst_clock_id_unref); + + g_thread_join (worker_thread_a); + g_thread_join (worker_thread_b); + + fail_unless_equals_int64 (-4 * GST_SECOND, context_a.jitter); + fail_unless_equals_int64 (-5 * GST_SECOND, context_b.jitter); + + gst_clock_id_unref (context_a.clock_id); + gst_clock_id_unref (context_b.clock_id); + + gst_clock_id_unref (clock_id_a); + gst_clock_id_unref (clock_id_b); + + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_async_past) +{ + GstClock *clock; + GstClockID clock_id; + GstClockID processed_id; + gboolean wait_complete = FALSE; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND - 1); + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_OK); + g_assert (!wait_complete); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (wait_complete); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_EARLY); + gst_clock_id_unref (processed_id); + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_async_present) +{ + GstClock *clock; + GstClockID clock_id; + GstClockID processed_id; + gboolean wait_complete = FALSE; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + clock_id = gst_clock_new_single_shot_id (clock, GST_SECOND); + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_OK); + g_assert (!wait_complete); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (wait_complete); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_async_future) +{ + GstClock *clock; + GstClockID clock_id; + GstClockID processed_id; + gboolean wait_complete = FALSE; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + clock_id = gst_clock_new_single_shot_id (clock, 2 * GST_SECOND); + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_OK); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (processed_id == NULL); + g_assert (!wait_complete); + g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id)) + == GST_CLOCK_OK); + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), GST_SECOND - 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (processed_id == NULL); + g_assert (!wait_complete); + g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id)) + == GST_CLOCK_OK); + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (wait_complete); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_SINGLE, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + g_assert (GST_CLOCK_ENTRY_STATUS (GST_CLOCK_ENTRY (clock_id)) + == GST_CLOCK_OK); + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_single_shot_async_unschedule) +{ + GstClock *clock; + GstClockID clock_id; + gboolean wait_complete = FALSE; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + + clock_id = gst_clock_new_single_shot_id (clock, 3 * GST_SECOND); + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_OK); + + gst_clock_id_unschedule (clock_id); + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 2 * GST_SECOND); + g_assert (gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)) + == NULL); + g_assert (!wait_complete); + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_periodic_sync) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + guint i; + const GstClockTime interval = 4 * GST_MSECOND; + + clock = gst_test_clock_new (); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_periodic_id (clock, GST_SECOND, interval); + + for (i = 0; i < 3; i++) { + GtuClockWaitContext *wait_ctx; + GstClockID pending_id; + guint j; + + wait_ctx = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL); + + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + assert_pending_id (pending_id, clock_id, GST_CLOCK_ENTRY_PERIODIC, + GST_SECOND + (i * interval)); + gst_clock_id_unref (pending_id); + + for (j = 0; j < 10; j++) { + g_usleep (G_USEC_PER_SEC / 10 / 10); + g_assert (!gst_test_util_clock_wait_context_has_completed (wait_ctx)); + } + + if (i == 0) + gst_test_clock_advance_time (test_clock, GST_SECOND); + else + gst_test_clock_advance_time (test_clock, interval); + + gst_test_util_wait_for_clock_id_end (wait_ctx); + } + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_periodic_async) +{ + GstClock *clock; + GstClockID clock_id; + GstClockID processed_id; + gboolean wait_complete = FALSE; + const GstClockTime interval = 4 * GST_MSECOND; + + clock = gst_test_clock_new (); + clock_id = gst_clock_new_periodic_id (clock, gst_clock_get_time (clock), + interval); + g_assert (gst_clock_id_wait_async (clock_id, test_async_wait_cb, + &wait_complete, NULL) == GST_CLOCK_OK); + + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + + g_assert (wait_complete); + wait_complete = FALSE; + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), interval - 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (processed_id == NULL); + g_assert (!wait_complete); + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + g_assert (wait_complete); + wait_complete = FALSE; + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), interval - 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + g_assert (processed_id == NULL); + g_assert (!wait_complete); + + gst_test_clock_advance_time (GST_TEST_CLOCK (clock), 1); + processed_id = gst_test_clock_process_next_clock_id (GST_TEST_CLOCK (clock)); + assert_processed_id (processed_id, clock_id, GST_CLOCK_ENTRY_PERIODIC, + GST_CLOCK_OK); + gst_clock_id_unref (processed_id); + g_assert (wait_complete); + wait_complete = FALSE; + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_periodic_uniqueness) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + guint i; + const GstClockTime interval = 4 * GST_MSECOND; + + clock = gst_test_clock_new (); + test_clock = GST_TEST_CLOCK (clock); + + clock_id = gst_clock_new_periodic_id (clock, 0, interval); + + for (i = 0; i < 3; i++) { + GtuClockWaitContext *wait_ctx; + guint j; + + wait_ctx = + gst_test_util_wait_for_clock_id_begin (test_clock, clock_id, NULL); + + for (j = 0; j < 10; j++) { + g_usleep (G_USEC_PER_SEC / 10 / 10); + g_assert_cmpuint (gst_test_clock_peek_id_count (test_clock), ==, 1); + } + + gst_test_clock_advance_time (test_clock, interval); + gst_test_util_wait_for_clock_id_end (wait_ctx); + } + + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +GST_START_TEST (test_crank) +{ + GstClock *clock; + GstTestClock *test_clock; + GstClockID clock_id; + SyncClockWaitContext context; + GThread *worker_thread; + + clock = gst_test_clock_new_with_start_time (GST_SECOND); + test_clock = GST_TEST_CLOCK (clock); + + /* register a wait for 5 seconds */ + clock_id = gst_clock_new_single_shot_id (clock, 5 * GST_SECOND); + context.clock_id = gst_clock_id_ref (clock_id); + context.jitter = 0; + worker_thread = + g_thread_new ("worker_thread_a", + test_wait_pending_single_shot_id_sync_worker, &context); + + /* crank */ + gst_test_clock_crank (test_clock); + + /* the clock should have advanced and the wait released */ + g_thread_join (worker_thread); + + /* 4 seconds was spent waiting for the clock */ + fail_unless_equals_int64 (-4 * GST_SECOND, context.jitter); + + /* and the clock is now at 5 seconds */ + fail_unless_equals_int64 (5 * GST_SECOND, gst_clock_get_time (clock)); + + gst_clock_id_unref (context.clock_id); + gst_clock_id_unref (clock_id); + gst_object_unref (clock); +} + +GST_END_TEST; + +static Suite * +gst_test_clock_suite (void) +{ + Suite *s = suite_create ("GstTestClock"); + TCase *tc_chain = tcase_create ("testclock"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_object_flags); + tcase_add_test (tc_chain, test_resolution_query); + tcase_add_test (tc_chain, test_start_time); + tcase_add_test (tc_chain, test_set_time); + tcase_add_test (tc_chain, test_advance_time); + tcase_add_test (tc_chain, test_wait_synchronous_no_timeout); + tcase_add_test (tc_chain, test_wait_pending_single_shot_id); + tcase_add_test (tc_chain, test_wait_pending_periodic_id); + tcase_add_test (tc_chain, test_single_shot_sync_simultaneous_no_timeout); + tcase_add_test (tc_chain, test_processing_multiple_ids); + tcase_add_test (tc_chain, test_single_shot_sync_past); + tcase_add_test (tc_chain, test_single_shot_sync_present); + tcase_add_test (tc_chain, test_single_shot_sync_future); + tcase_add_test (tc_chain, test_single_shot_sync_unschedule); + tcase_add_test (tc_chain, test_single_shot_sync_ordering); + tcase_add_test (tc_chain, test_single_shot_sync_ordering_parallel); + tcase_add_test (tc_chain, test_single_shot_async_past); + tcase_add_test (tc_chain, test_single_shot_async_present); + tcase_add_test (tc_chain, test_single_shot_async_future); + tcase_add_test (tc_chain, test_single_shot_async_unschedule); + tcase_add_test (tc_chain, test_periodic_sync); + tcase_add_test (tc_chain, test_periodic_async); + tcase_add_test (tc_chain, test_periodic_uniqueness); + tcase_add_test (tc_chain, test_crank); + + return s; +} + +GST_CHECK_MAIN (gst_test_clock); diff --git a/tests/check/libs/libsabi.c b/tests/check/libs/libsabi.c new file mode 100644 index 0000000..42ca40f --- /dev/null +++ b/tests/check/libs/libsabi.c @@ -0,0 +1,106 @@ +/* GStreamer + * Copyright (C) 2012 Wim Taymans + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CPU_I386 +#include "struct_i386.h" +#define HAVE_ABI_SIZES TRUE +#else +#ifdef __powerpc64__ +#include "struct_ppc64.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef __powerpc__ +#include "struct_ppc32.h" +#define HAVE_ABI_SIZES TRUE +#else +#ifdef HAVE_CPU_X86_64 +#include "struct_x86_64.h" +#define HAVE_ABI_SIZES TRUE +#else +#ifdef HAVE_CPU_HPPA +#include "struct_hppa.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef HAVE_CPU_SPARC +#include "struct_sparc.h" +#define HAVE_ABI_SIZES FALSE +#else +#ifdef HAVE_CPU_ARM +#include "struct_arm.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 +#endif +#endif +#endif +#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/tests/check/libs/queuearray.c b/tests/check/libs/queuearray.c new file mode 100644 index 0000000..d9f0f00 --- /dev/null +++ b/tests/check/libs/queuearray.c @@ -0,0 +1,338 @@ +/* GStreamer + * + * unit test for GstQueueArray + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +/* Simplest test + * Initial size : 10 + * Add 10, Remove 10 + */ +GST_START_TEST (test_array_1) +{ + GstQueueArray *array; + guint i; + + /* Create an array of initial size 10 */ + array = gst_queue_array_new (10); + + /* push 5 values in */ + for (i = 0; i < 5; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 5); + + /* pull 5 values out */ + for (i = 0; i < 5; i++) { + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_grow) +{ + GstQueueArray *array; + guint i; + + /* Create an array of initial size 10 */ + array = gst_queue_array_new (10); + + /* push 10 values in */ + for (i = 0; i < 10; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 10); + + + /* If we add one value, it will grow */ + gst_queue_array_push_tail (array, GINT_TO_POINTER (10)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 11); + + /* pull the 11 values out */ + for (i = 0; i < 11; i++) { + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_grow_multiple) +{ + GstQueueArray *array; + guint i; + + /* Create an array of initial size 10 */ + array = gst_queue_array_new (10); + + /* push 11 values in */ + for (i = 0; i < 11; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + /* With 11 values, it should have grown once (15) */ + fail_unless_equals_int (gst_queue_array_get_length (array), 11); + + for (i = 11; i < 20; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + /* With 20 total values, it should have grown another time (3 * 15) / 2 = 22) */ + fail_unless_equals_int (gst_queue_array_get_length (array), 20); + /* It did grow beyond initial size */ + + /* pull the 20 values out */ + for (i = 0; i < 20; i++) { + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_grow_middle) +{ + GstQueueArray *array; + guint i; + + /* Create an array of initial size 10 */ + array = gst_queue_array_new (10); + + /* push/pull 5 values to end up in the middle */ + for (i = 0; i < 5; i++) { + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + /* push 10 values in */ + for (i = 0; i < 10; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 10); + + /* If we add one value, it will grow */ + gst_queue_array_push_tail (array, GINT_TO_POINTER (10)); + fail_unless_equals_int (gst_queue_array_get_length (array), 11); + + /* pull the 11 values out */ + for (i = 0; i < 11; i++) { + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_grow_end) +{ + GstQueueArray *array; + guint i; + + /* Create an array of initial size 10 */ + array = gst_queue_array_new (10); + + /* push/pull 9 values to end up at the last position */ + for (i = 0; i < 9; i++) { + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + /* push 10 values in */ + for (i = 0; i < 10; i++) + gst_queue_array_push_tail (array, GINT_TO_POINTER (i)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 10); + + /* If we add one value, it will grow */ + gst_queue_array_push_tail (array, GINT_TO_POINTER (10)); + fail_unless_equals_int (gst_queue_array_get_length (array), 11); + + /* pull the 11 values out */ + for (i = 0; i < 11; i++) { + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_pop_head (array)), + i); + } + + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + gst_queue_array_free (array); +} + +GST_END_TEST; + +static int +compare_pointer_value (gconstpointer a, gconstpointer b) +{ + return (int) ((guintptr) a - (guintptr) b); +} + +GST_START_TEST (test_array_drop2) +{ +#define NUM_QA_ELEMENTS 674 + gboolean in_array[NUM_QA_ELEMENTS] = { FALSE, }; + GstQueueArray *array; + guint i, j, count, idx; + + array = gst_queue_array_new (10); + + for (i = 0; i < NUM_QA_ELEMENTS; i++) { + gpointer element = GUINT_TO_POINTER (i); + + if (g_random_boolean ()) { + gst_queue_array_push_tail (array, element); + in_array[i] = TRUE; + } + } + + for (j = 0, count = 0; j < NUM_QA_ELEMENTS; j++) + count += in_array[j] ? 1 : 0; + fail_unless_equals_int (gst_queue_array_get_length (array), count); + + while (gst_queue_array_get_length (array) > 0) { + for (i = 0; i < NUM_QA_ELEMENTS; i++) { + gpointer dropped; + + if (g_random_boolean () && g_random_boolean () && in_array[i]) { + idx = gst_queue_array_find (array, compare_pointer_value, + GUINT_TO_POINTER (i)); + dropped = gst_queue_array_drop_element (array, idx); + fail_unless_equals_int (i, GPOINTER_TO_INT (dropped)); + in_array[i] = FALSE; + } + } + + for (j = 0, count = 0; j < NUM_QA_ELEMENTS; j++) + count += in_array[j] ? 1 : 0; + fail_unless_equals_int (gst_queue_array_get_length (array), count); + } + + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_grow_from_prealloc1) +{ + GstQueueArray *array; + + array = gst_queue_array_new (1); + gst_queue_array_push_tail (array, NULL); + gst_queue_array_push_tail (array, NULL); + gst_queue_array_free (array); +} + +GST_END_TEST; + +GST_START_TEST (test_array_peek_pop_tail) +{ + const guint array_sizes[] = { 0, 1, 2, 5 }; + guint s; + + for (s = 0; s < G_N_ELEMENTS (array_sizes); ++s) { + GstQueueArray *array; + + GST_INFO ("Testing with initial size %u", array_sizes[s]); + + array = gst_queue_array_new (array_sizes[s]); + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + + fail_unless (gst_queue_array_peek_tail (array) == NULL); + fail_unless (gst_queue_array_pop_tail (array) == NULL); + + gst_queue_array_push_tail (array, GINT_TO_POINTER (42)); + fail_unless_equals_int (gst_queue_array_get_length (array), 1); + fail_unless (gst_queue_array_peek_tail (array) == GINT_TO_POINTER (42)); + fail_unless (gst_queue_array_peek_head (array) == GINT_TO_POINTER (42)); + fail_unless_equals_int (gst_queue_array_get_length (array), 1); + fail_unless (gst_queue_array_pop_tail (array) == GINT_TO_POINTER (42)); + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + + gst_queue_array_push_tail (array, GINT_TO_POINTER (42)); + fail_unless_equals_int (gst_queue_array_get_length (array), 1); + fail_unless (gst_queue_array_pop_head (array) == GINT_TO_POINTER (42)); + fail_unless_equals_int (gst_queue_array_get_length (array), 0); + fail_unless (gst_queue_array_peek_tail (array) == NULL); + fail_unless (gst_queue_array_pop_tail (array) == NULL); + + gst_queue_array_push_tail (array, GINT_TO_POINTER (43)); + gst_queue_array_push_tail (array, GINT_TO_POINTER (44)); + + fail_unless_equals_int (gst_queue_array_get_length (array), 2); + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_peek_head (array)), + 43); + fail_unless_equals_int (GPOINTER_TO_INT (gst_queue_array_peek_tail (array)), + 44); + fail_unless_equals_int (gst_queue_array_get_length (array), 2); + fail_unless (gst_queue_array_pop_tail (array) == GINT_TO_POINTER (44)); + fail_unless_equals_int (gst_queue_array_get_length (array), 1); + fail_unless (gst_queue_array_peek_head (array) == GINT_TO_POINTER (43)); + fail_unless (gst_queue_array_peek_tail (array) == GINT_TO_POINTER (43)); + fail_unless_equals_int (gst_queue_array_get_length (array), 1); + + gst_queue_array_free (array); + } +} + +GST_END_TEST; + +static Suite * +gst_queue_array_suite (void) +{ + Suite *s = suite_create ("GstQueueArray"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_array_1); + tcase_add_test (tc_chain, test_array_grow); + tcase_add_test (tc_chain, test_array_grow_multiple); + tcase_add_test (tc_chain, test_array_grow_middle); + tcase_add_test (tc_chain, test_array_grow_end); + tcase_add_test (tc_chain, test_array_drop2); + tcase_add_test (tc_chain, test_array_grow_from_prealloc1); + tcase_add_test (tc_chain, test_array_peek_pop_tail); + + return s; +} + + +GST_CHECK_MAIN (gst_queue_array); diff --git a/tests/check/libs/sparsefile.c b/tests/check/libs/sparsefile.c new file mode 100644 index 0000000..fd5c81e --- /dev/null +++ b/tests/check/libs/sparsefile.c @@ -0,0 +1,227 @@ +/* GStreamer + * + * unit test for cachefile helper + * + * Copyright (C) 2014 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 + +/* not public API for now */ +#include "../../../plugins/elements/gstsparsefile.c" + +static void +expect_range_before (GstSparseFile * file, gsize offset, gsize start, + gsize stop) +{ + gsize tstart, tstop; + + fail_unless (gst_sparse_file_get_range_before (file, offset, &tstart, + &tstop) == TRUE); + fail_unless (tstart == start); + fail_unless (tstop == stop); +} + +static void +expect_range_after (GstSparseFile * file, gsize offset, gsize start, gsize stop) +{ + gsize tstart, tstop; + + fail_unless (gst_sparse_file_get_range_after (file, offset, &tstart, + &tstop) == TRUE); + fail_unless (tstart == start); + fail_unless (tstop == stop); +} + +static gboolean +expect_write (GstSparseFile * file, gsize offset, gsize count, gsize result, + gsize avail) +{ + GError *error = NULL; + gchar buffer[200] = { 0, }; + gsize res, a; + + res = gst_sparse_file_write (file, offset, buffer, count, &a, &error); + if (res != result) + return FALSE; + if (res == 0) { + if (error == NULL) + return FALSE; + g_clear_error (&error); + } else if (a != avail) + return FALSE; + return TRUE; +} + +static gboolean +expect_read (GstSparseFile * file, gsize offset, gsize count, gsize result, + gsize avail) +{ + GError *error = NULL; + gchar buffer[200]; + gsize res, a; + + res = gst_sparse_file_read (file, offset, buffer, count, &a, &error); + if (res != result) + return FALSE; + if (res == 0) { + if (error == NULL) + return FALSE; + g_clear_error (&error); + } else if (a != avail) + return FALSE; + return TRUE; +} + +GST_START_TEST (test_write_read) +{ + GstSparseFile *file; + gint fd; + gchar *name; + gsize start, stop; + + name = g_strdup ("cachefile-testXXXXXX"); + fd = g_mkstemp (name); + fail_if (fd == -1); + + file = gst_sparse_file_new (); + fail_unless (file != NULL); + fail_unless (gst_sparse_file_set_fd (file, fd)); + fail_unless (gst_sparse_file_n_ranges (file) == 0); + + /* should fail, we didn't write anything yet */ + fail_unless (expect_read (file, 0, 100, 0, 0)); + + /* no ranges, searching for a range should fail */ + fail_unless (gst_sparse_file_n_ranges (file) == 0); + fail_unless (gst_sparse_file_get_range_before (file, 0, &start, + &stop) == FALSE); + fail_unless (gst_sparse_file_get_range_before (file, 10, &start, + &stop) == FALSE); + fail_unless (gst_sparse_file_get_range_after (file, 0, &start, + &stop) == FALSE); + fail_unless (gst_sparse_file_get_range_after (file, 10, &start, + &stop) == FALSE); + + /* now write some data */ + fail_unless (expect_write (file, 0, 100, 100, 0)); + + /* we have 1 range now */ + fail_unless (gst_sparse_file_n_ranges (file) == 1); + expect_range_before (file, 0, 0, 100); + expect_range_after (file, 0, 0, 100); + expect_range_before (file, 100, 0, 100); + expect_range_before (file, 50, 0, 100); + expect_range_before (file, 200, 0, 100); + fail_unless (gst_sparse_file_get_range_after (file, 100, &start, + &stop) == FALSE); + expect_range_after (file, 50, 0, 100); + + /* we can read all data now */ + fail_unless (expect_read (file, 0, 100, 100, 0)); + /* we can read less */ + fail_unless (expect_read (file, 0, 50, 50, 50)); + /* but we can't read more than what is written */ + fail_unless (expect_read (file, 0, 101, 0, 0)); + + g_unlink (name); + gst_sparse_file_free (file); + g_free (name); +} + +GST_END_TEST; + +GST_START_TEST (test_write_merge) +{ + GstSparseFile *file; + gint fd; + gchar *name; + gsize start, stop; + + name = g_strdup ("cachefile-testXXXXXX"); + fd = g_mkstemp (name); + fail_if (fd == -1); + + file = gst_sparse_file_new (); + gst_sparse_file_set_fd (file, fd); + + /* write something at offset 0 */ + fail_unless (expect_write (file, 0, 100, 100, 0)); + /* we have 1 range now */ + fail_unless (gst_sparse_file_n_ranges (file) == 1); + expect_range_before (file, 110, 0, 100); + expect_range_after (file, 50, 0, 100); + fail_unless (gst_sparse_file_get_range_after (file, 100, &start, + &stop) == FALSE); + + /* read should fail */ + fail_unless (expect_read (file, 50, 150, 0, 0)); + + /* write something at offset 150 */ + fail_unless (expect_write (file, 150, 100, 100, 0)); + /* we have 2 ranges now */ + fail_unless (gst_sparse_file_n_ranges (file) == 2); + expect_range_before (file, 110, 0, 100); + expect_range_after (file, 50, 0, 100); + expect_range_after (file, 100, 150, 250); + expect_range_before (file, 150, 150, 250); + + /* read should still fail */ + fail_unless (expect_read (file, 50, 150, 0, 0)); + + /* fill the hole */ + fail_unless (expect_write (file, 100, 50, 50, 100)); + /* we have 1 range now */ + fail_unless (gst_sparse_file_n_ranges (file) == 1); + expect_range_before (file, 110, 0, 250); + expect_range_after (file, 50, 0, 250); + expect_range_after (file, 100, 0, 250); + expect_range_before (file, 150, 0, 250); + fail_unless (gst_sparse_file_get_range_after (file, 250, &start, + &stop) == FALSE); + + /* read work */ + fail_unless (expect_read (file, 50, 150, 150, 50)); + + g_unlink (name); + gst_sparse_file_free (file); + g_free (name); +} + +GST_END_TEST; + +static Suite * +gst_cachefile_suite (void) +{ + Suite *s = suite_create ("cachefile"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_write_read); + tcase_add_test (tc_chain, test_write_merge); + + return s; +} + +GST_CHECK_MAIN (gst_cachefile); diff --git a/tests/check/libs/struct_arm.h b/tests/check/libs/struct_arm.h new file mode 100644 index 0000000..21310de --- /dev/null +++ b/tests/check/libs/struct_arm.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 368}, + {"GstBaseParse", sizeof (GstBaseParse), 392}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 400}, + {"GstBaseSink", sizeof (GstBaseSink), 464}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 404}, + {"GstBaseSrc", sizeof (GstBaseSrc), 448}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 416}, + {"GstBaseTransform", sizeof (GstBaseTransform), 392}, + {"GstBitReader", sizeof (GstBitReader), 32}, + {"GstByteReader", sizeof (GstByteReader), 28}, + {"GstByteWriter", sizeof (GstByteWriter), 56}, + {"GstCollectData", sizeof (GstCollectData), 144}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 108}, + {"GstCollectPads", sizeof (GstCollectPads), 104}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 140}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 160}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 140}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 168}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 140}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 152}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 124}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 120}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 124}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 128}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 140}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 152}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 164}, + {"GstNetClientClock", sizeof (GstNetClientClock), 136}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 108}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 88}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 432}, + {"GstPushSrc", sizeof (GstPushSrc), 464}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_hppa.h b/tests/check/libs/struct_hppa.h new file mode 100644 index 0000000..9cdb923 --- /dev/null +++ b/tests/check/libs/struct_hppa.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 728}, + {"GstBaseParse", sizeof (GstBaseParse), 576}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 792}, + {"GstBaseSink", sizeof (GstBaseSink), 664}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 800}, + {"GstBaseSrc", sizeof (GstBaseSrc), 648}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 816}, + {"GstBaseTransform", sizeof (GstBaseTransform), 576}, + {"GstBitReader", sizeof (GstBitReader), 56}, + {"GstByteReader", sizeof (GstByteReader), 48}, + {"GstByteWriter", sizeof (GstByteWriter), 96}, + {"GstCollectData", sizeof (GstCollectData), 200}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 216}, + {"GstCollectPads", sizeof (GstCollectPads), 152}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 280}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 248}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 280}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 248}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 280}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 240}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 248}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 184}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 248}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 200}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 280}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 240}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 328}, + {"GstNetClientClock", sizeof (GstNetClientClock), 208}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 216}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 128}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 856}, + {"GstPushSrc", sizeof (GstPushSrc), 680}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_i386.h b/tests/check/libs/struct_i386.h new file mode 100644 index 0000000..fd13063 --- /dev/null +++ b/tests/check/libs/struct_i386.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 368}, + {"GstBaseParse", sizeof (GstBaseParse), 364}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 400}, + {"GstBaseSink", sizeof (GstBaseSink), 440}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 404}, + {"GstBaseSrc", sizeof (GstBaseSrc), 424}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 416}, + {"GstBaseTransform", sizeof (GstBaseTransform), 364}, + {"GstBitReader", sizeof (GstBitReader), 32}, + {"GstByteReader", sizeof (GstByteReader), 28}, + {"GstByteWriter", sizeof (GstByteWriter), 56}, + {"GstCollectData", sizeof (GstCollectData), 136}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 108}, + {"GstCollectPads", sizeof (GstCollectPads), 92}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 140}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 144}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 140}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 148}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 140}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 140}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 124}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 108}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 124}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 120}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 140}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 140}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 164}, + {"GstNetClientClock", sizeof (GstNetClientClock), 116}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 108}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 76}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 432}, + {"GstPushSrc", sizeof (GstPushSrc), 440}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_ppc32.h b/tests/check/libs/struct_ppc32.h new file mode 100644 index 0000000..21310de --- /dev/null +++ b/tests/check/libs/struct_ppc32.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 368}, + {"GstBaseParse", sizeof (GstBaseParse), 392}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 400}, + {"GstBaseSink", sizeof (GstBaseSink), 464}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 404}, + {"GstBaseSrc", sizeof (GstBaseSrc), 448}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 416}, + {"GstBaseTransform", sizeof (GstBaseTransform), 392}, + {"GstBitReader", sizeof (GstBitReader), 32}, + {"GstByteReader", sizeof (GstByteReader), 28}, + {"GstByteWriter", sizeof (GstByteWriter), 56}, + {"GstCollectData", sizeof (GstCollectData), 144}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 108}, + {"GstCollectPads", sizeof (GstCollectPads), 104}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 140}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 160}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 140}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 168}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 140}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 152}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 124}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 120}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 124}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 128}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 140}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 152}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 164}, + {"GstNetClientClock", sizeof (GstNetClientClock), 136}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 108}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 88}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 432}, + {"GstPushSrc", sizeof (GstPushSrc), 464}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_ppc64.h b/tests/check/libs/struct_ppc64.h new file mode 100644 index 0000000..9cdb923 --- /dev/null +++ b/tests/check/libs/struct_ppc64.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 728}, + {"GstBaseParse", sizeof (GstBaseParse), 576}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 792}, + {"GstBaseSink", sizeof (GstBaseSink), 664}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 800}, + {"GstBaseSrc", sizeof (GstBaseSrc), 648}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 816}, + {"GstBaseTransform", sizeof (GstBaseTransform), 576}, + {"GstBitReader", sizeof (GstBitReader), 56}, + {"GstByteReader", sizeof (GstByteReader), 48}, + {"GstByteWriter", sizeof (GstByteWriter), 96}, + {"GstCollectData", sizeof (GstCollectData), 200}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 216}, + {"GstCollectPads", sizeof (GstCollectPads), 152}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 280}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 248}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 280}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 248}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 280}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 240}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 248}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 184}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 248}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 200}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 280}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 240}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 328}, + {"GstNetClientClock", sizeof (GstNetClientClock), 208}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 216}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 128}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 856}, + {"GstPushSrc", sizeof (GstPushSrc), 680}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_sparc.h b/tests/check/libs/struct_sparc.h new file mode 100644 index 0000000..9cdb923 --- /dev/null +++ b/tests/check/libs/struct_sparc.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 728}, + {"GstBaseParse", sizeof (GstBaseParse), 576}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 792}, + {"GstBaseSink", sizeof (GstBaseSink), 664}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 800}, + {"GstBaseSrc", sizeof (GstBaseSrc), 648}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 816}, + {"GstBaseTransform", sizeof (GstBaseTransform), 576}, + {"GstBitReader", sizeof (GstBitReader), 56}, + {"GstByteReader", sizeof (GstByteReader), 48}, + {"GstByteWriter", sizeof (GstByteWriter), 96}, + {"GstCollectData", sizeof (GstCollectData), 200}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 216}, + {"GstCollectPads", sizeof (GstCollectPads), 152}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 280}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 248}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 280}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 248}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 280}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 240}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 248}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 184}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 248}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 200}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 280}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 240}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 328}, + {"GstNetClientClock", sizeof (GstNetClientClock), 208}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 216}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 128}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 856}, + {"GstPushSrc", sizeof (GstPushSrc), 680}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/struct_x86_64.h b/tests/check/libs/struct_x86_64.h new file mode 100644 index 0000000..9cdb923 --- /dev/null +++ b/tests/check/libs/struct_x86_64.h @@ -0,0 +1,39 @@ + +GstCheckABIStruct list[] = { + {"GstBaseParseClass", sizeof (GstBaseParseClass), 728}, + {"GstBaseParse", sizeof (GstBaseParse), 576}, + {"GstBaseSinkClass", sizeof (GstBaseSinkClass), 792}, + {"GstBaseSink", sizeof (GstBaseSink), 664}, + {"GstBaseSrcClass", sizeof (GstBaseSrcClass), 800}, + {"GstBaseSrc", sizeof (GstBaseSrc), 648}, + {"GstBaseTransformClass", sizeof (GstBaseTransformClass), 816}, + {"GstBaseTransform", sizeof (GstBaseTransform), 576}, + {"GstBitReader", sizeof (GstBitReader), 56}, + {"GstByteReader", sizeof (GstByteReader), 48}, + {"GstByteWriter", sizeof (GstByteWriter), 96}, + {"GstCollectData", sizeof (GstCollectData), 200}, + {"GstCollectPadsClass", sizeof (GstCollectPadsClass), 216}, + {"GstCollectPads", sizeof (GstCollectPads), 152}, + {"GstARGBControlBindingClass", sizeof (GstARGBControlBindingClass), 280}, + {"GstARGBControlBinding", sizeof (GstARGBControlBinding), 248}, + {"GstDirectControlBindingClass", sizeof (GstDirectControlBindingClass), 280}, + {"GstDirectControlBinding", sizeof (GstDirectControlBinding), 248}, + {"GstInterpolationControlSourceClass", sizeof (GstInterpolationControlSourceClass), 280}, + {"GstInterpolationControlSource", sizeof (GstInterpolationControlSource), 240}, + {"GstLFOControlSourceClass", sizeof (GstLFOControlSourceClass), 248}, + {"GstLFOControlSource", sizeof (GstLFOControlSource), 184}, + {"GstControlPoint", sizeof (GstControlPoint), 80}, + {"GstTimedValueControlSourceClass", sizeof (GstTimedValueControlSourceClass), 248}, + {"GstTimedValueControlSource", sizeof (GstTimedValueControlSource), 200}, + {"GstTriggerControlSourceClass", sizeof (GstTriggerControlSourceClass), 280}, + {"GstTriggerControlSource", sizeof (GstTriggerControlSource), 240}, + {"GstNetClientClockClass", sizeof (GstNetClientClockClass), 328}, + {"GstNetClientClock", sizeof (GstNetClientClock), 208}, + {"GstNetTimePacket", sizeof (GstNetTimePacket), 16}, + {"GstNetTimeProviderClass", sizeof (GstNetTimeProviderClass), 216}, + {"GstNetTimeProvider", sizeof (GstNetTimeProvider), 128}, + {"GstPushSrcClass", sizeof (GstPushSrcClass), 856}, + {"GstPushSrc", sizeof (GstPushSrc), 680}, + {"GstTimedValue", sizeof (GstTimedValue), 16}, + {NULL, 0, 0} +}; diff --git a/tests/check/libs/test_transform.c b/tests/check/libs/test_transform.c new file mode 100644 index 0000000..273104d --- /dev/null +++ b/tests/check/libs/test_transform.c @@ -0,0 +1,285 @@ +/* GStreamer + * + * some unit tests for GstBaseTransform + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +typedef struct +{ + GstPad *srcpad; + GstPad *sinkpad; + GList *events; + GList *buffers; + GstElement *trans; + GstBaseTransformClass *klass; +} TestTransData; + +static GstStaticPadTemplate gst_test_trans_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("foo/x-bar") + ); + +static GstStaticPadTemplate gst_test_trans_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("foo/x-bar") + ); + +typedef struct _GstTestTrans GstTestTrans; +typedef struct _GstTestTransClass GstTestTransClass; + +#define GST_TEST_TRANS(obj) ((GstTestTrans *)(obj)) + +struct _GstTestTrans +{ + GstBaseTransform element; + + TestTransData *data; +}; + +struct _GstTestTransClass +{ + GstBaseTransformClass parent_class; +}; + +static GstFlowReturn (*klass_transform) (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf) = NULL; +static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans, + GstBuffer * buf) = NULL; +static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) = NULL; +static GstCaps *(*klass_transform_caps) (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) = NULL; +static gboolean (*klass_transform_size) (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, gsize size, GstCaps * othercaps, + gsize * othersize) = NULL; +static gboolean klass_passthrough_on_same_caps = FALSE; +GstFlowReturn (*klass_submit_input_buffer) (GstBaseTransform * trans, + gboolean is_discont, GstBuffer * input) = NULL; +GstFlowReturn (*klass_generate_output) (GstBaseTransform * trans, + GstBuffer ** outbuf) = NULL; + +static GstStaticPadTemplate *sink_template = &gst_test_trans_sink_template; +static GstStaticPadTemplate *src_template = &gst_test_trans_src_template; + +static void +gst_test_trans_class_init (GstTestTransClass * klass) +{ + GstElementClass *element_class; + GstBaseTransformClass *trans_class; + + element_class = (GstElementClass *) klass; + trans_class = (GstBaseTransformClass *) klass; + + gst_element_class_set_metadata (element_class, "TestTrans", + "Filter/Test", "Test transform", "Wim Taymans "); + + gst_element_class_add_static_pad_template (element_class, sink_template); + gst_element_class_add_static_pad_template (element_class, src_template); + + GST_INFO ("setting up %s", g_type_name (((GTypeClass *) klass)->g_type)); + + trans_class->passthrough_on_same_caps = klass_passthrough_on_same_caps; + if (klass_transform_ip != NULL) + trans_class->transform_ip = klass_transform_ip; + if (klass_transform != NULL) + trans_class->transform = klass_transform; + if (klass_transform_caps != NULL) + trans_class->transform_caps = klass_transform_caps; + if (klass_transform_size != NULL) + trans_class->transform_size = klass_transform_size; + if (klass_set_caps != NULL) + trans_class->set_caps = klass_set_caps; + if (klass_submit_input_buffer != NULL) + trans_class->submit_input_buffer = klass_submit_input_buffer; + if (klass_generate_output) + trans_class->generate_output = klass_generate_output; +} + +static void +gst_test_trans_init (GstTestTrans * this) +{ +} + +static void +gst_test_trans_set_data (GstTestTrans * this, TestTransData * data) +{ + this->data = data; +} + +static GstFlowReturn +result_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + TestTransData *data; + + data = gst_pad_get_element_private (pad); + + data->buffers = g_list_append (data->buffers, buffer); + + return GST_FLOW_OK; +} + +#if 0 +static GstFlowReturn +result_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, + GstBuffer ** buf) +{ + GstFlowReturn res; + TestTransData *data; + + data = gst_pad_get_element_private (pad); + + *buf = gst_buffer_new_and_alloc (size); + gst_buffer_set_caps (*buf, caps); + res = GST_FLOW_OK; + + return res; +} +#endif + +static TestTransData * +gst_test_trans_new (void) +{ + TestTransData *res; + GstPad *tmp; + GstPadTemplate *templ; + GType type; + + /* we register a new sub-class for every test-run, so the class init + * function is called for every test run and can be set up properly + * even with CK_FORK=no */ + { + static gint counter = 0; + gchar name[100]; + + g_snprintf (name, sizeof (name), "GstTestTrans%d", ++counter); + + type = g_type_register_static_simple (GST_TYPE_BASE_TRANSFORM, name, + sizeof (GstTestTransClass), (GClassInitFunc) gst_test_trans_class_init, + sizeof (GstTestTrans), (GInstanceInitFunc) gst_test_trans_init, 0); + } + + res = g_new0 (TestTransData, 1); + res->trans = g_object_new (type, NULL); + + templ = gst_static_pad_template_get (sink_template); + templ->direction = GST_PAD_SRC; + res->srcpad = gst_pad_new_from_template (templ, "src"); + gst_object_unref (templ); + + templ = gst_static_pad_template_get (src_template); + templ->direction = GST_PAD_SINK; + res->sinkpad = gst_pad_new_from_template (templ, "sink"); + gst_object_unref (templ); + + res->klass = GST_BASE_TRANSFORM_GET_CLASS (res->trans); + + gst_test_trans_set_data (GST_TEST_TRANS (res->trans), res); + gst_pad_set_element_private (res->sinkpad, res); + + gst_pad_set_chain_function (res->sinkpad, result_sink_chain); + + tmp = gst_element_get_static_pad (res->trans, "sink"); + gst_pad_link (res->srcpad, tmp); + gst_object_unref (tmp); + + tmp = gst_element_get_static_pad (res->trans, "src"); + gst_pad_link (tmp, res->sinkpad); + gst_object_unref (tmp); + + gst_pad_set_active (res->sinkpad, TRUE); + gst_element_set_state (res->trans, GST_STATE_PAUSED); + gst_pad_set_active (res->srcpad, TRUE); + + gst_pad_push_event (res->srcpad, gst_event_new_stream_start ("test")); + + return res; +} + +static void +gst_test_trans_free (TestTransData * data) +{ + GstPad *tmp; + + gst_pad_set_active (data->sinkpad, FALSE); + gst_element_set_state (data->trans, GST_STATE_NULL); + gst_pad_set_active (data->srcpad, FALSE); + + tmp = gst_element_get_static_pad (data->trans, "src"); + gst_pad_unlink (tmp, data->sinkpad); + gst_object_unref (tmp); + + tmp = gst_element_get_static_pad (data->trans, "sink"); + gst_pad_link (data->srcpad, tmp); + gst_object_unref (tmp); + + gst_object_unref (data->srcpad); + gst_object_unref (data->sinkpad); + gst_object_unref (data->trans); + + g_free (data); +} + +static GstFlowReturn +gst_test_trans_push (TestTransData * data, GstBuffer * buffer) +{ + GstFlowReturn ret; + + ret = gst_pad_push (data->srcpad, buffer); + + return ret; +} + +static GstBuffer * +gst_test_trans_pop (TestTransData * data) +{ + GstBuffer *ret; + + if (data->buffers) { + ret = data->buffers->data; + data->buffers = g_list_delete_link (data->buffers, data->buffers); + } else { + ret = NULL; + } + return ret; +} + +static gboolean +gst_test_trans_setcaps (TestTransData * data, GstCaps * caps) +{ + return gst_pad_set_caps (data->srcpad, caps); +} + +static gboolean +gst_test_trans_push_segment (TestTransData * data) +{ + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + return gst_pad_push_event (data->srcpad, gst_event_new_segment (&segment)); +} diff --git a/tests/check/libs/transform1.c b/tests/check/libs/transform1.c new file mode 100644 index 0000000..45e6477 --- /dev/null +++ b/tests/check/libs/transform1.c @@ -0,0 +1,933 @@ +/* GStreamer + * + * some unit tests for GstBaseTransform + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "test_transform.c" + +static gboolean set_caps_pt1_called; + +static gboolean +set_caps_pt1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) +{ + GST_DEBUG_OBJECT (trans, "set_caps called"); + + set_caps_pt1_called = TRUE; + + return TRUE; +} + +/* basic passthrough, we don't have any transform functions so we can only + * perform passthrough. We also don't have caps, which is fine */ +GST_START_TEST (basetransform_chain_pt1) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *caps; + + klass_set_caps = set_caps_pt1; + trans = gst_test_trans_new (); + + gst_test_trans_push_segment (trans); + + GST_DEBUG_OBJECT (trans, "buffer without caps, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + + set_caps_pt1_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (set_caps_pt1_called == FALSE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + gst_buffer_unref (buffer); + + GST_DEBUG_OBJECT (trans, "buffer without caps, size 10"); + + buffer = gst_buffer_new_and_alloc (10); + set_caps_pt1_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (set_caps_pt1_called == FALSE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 10); + + gst_buffer_unref (buffer); + + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + set_caps_pt1_called = FALSE; + gst_test_trans_setcaps (trans, caps); + fail_unless (set_caps_pt1_called == TRUE); + gst_caps_unref (caps); + + gst_test_trans_push_segment (trans); + + gst_test_trans_free (trans); + + klass_transform_ip = NULL; + klass_transform = NULL; + klass_transform_caps = NULL; + klass_transform_size = NULL; + klass_set_caps = NULL; + klass_submit_input_buffer = NULL; + klass_generate_output = NULL; +} + +GST_END_TEST; + +static gboolean set_caps_pt2_called; + +static gboolean +set_caps_pt2 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) +{ + GST_DEBUG_OBJECT (trans, "set_caps called"); + + set_caps_pt2_called = TRUE; + + fail_unless (gst_caps_is_equal (incaps, outcaps)); + + return TRUE; +} + +/* basic passthrough, we don't have any transform functions so we can only + * perform passthrough with same caps */ +GST_START_TEST (basetransform_chain_pt2) +{ + TestTransData *trans; + GstBuffer *buffer; + GstCaps *caps; + GstFlowReturn res; + + klass_set_caps = set_caps_pt2; + trans = gst_test_trans_new (); + + /* first buffer */ + set_caps_pt2_called = FALSE; + caps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_test_trans_setcaps (trans, caps); + gst_test_trans_push_segment (trans); + + GST_DEBUG_OBJECT (trans, "buffer with caps, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (set_caps_pt2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + gst_buffer_unref (buffer); + + gst_caps_unref (caps); + + /* second buffer, renegotiates, keeps extra type arg in caps */ + caps = gst_caps_new_simple ("foo/x-bar", "type", G_TYPE_INT, 1, NULL); + set_caps_pt2_called = FALSE; + gst_test_trans_setcaps (trans, caps); + + GST_DEBUG_OBJECT (trans, "buffer with caps, size 10"); + + buffer = gst_buffer_new_and_alloc (10); + + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (set_caps_pt2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 10); + + gst_buffer_unref (buffer); + + gst_caps_unref (caps); + + /* with caps that is a superset */ + caps = gst_caps_new_empty_simple ("foo/x-bar"); + set_caps_pt2_called = FALSE; + gst_test_trans_setcaps (trans, caps); + + GST_DEBUG_OBJECT (trans, "buffer with caps, size 10"); + + buffer = gst_buffer_new_and_alloc (10); + + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (set_caps_pt2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 10); + + gst_buffer_unref (buffer); + + gst_caps_unref (caps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +static gboolean transform_ip_1_called; +static gboolean transform_ip_1_writable; + +static GstFlowReturn +transform_ip_1 (GstBaseTransform * trans, GstBuffer * buf) +{ + GST_DEBUG_OBJECT (trans, "transform called"); + + transform_ip_1_called = TRUE; + transform_ip_1_writable = gst_buffer_is_writable (buf); + + GST_DEBUG_OBJECT (trans, "writable: %d", transform_ip_1_writable); + + return GST_FLOW_OK; +} + +/* basic in-place, check if the _ip function is called, buffer should + * be writable. no setcaps is set */ +GST_START_TEST (basetransform_chain_ip1) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + + klass_transform_ip = transform_ip_1; + trans = gst_test_trans_new (); + + gst_test_trans_push_segment (trans); + + GST_DEBUG_OBJECT (trans, "buffer without caps, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + + transform_ip_1_called = FALSE; + transform_ip_1_writable = TRUE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ip_1_called == TRUE); + fail_unless (transform_ip_1_writable == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + gst_buffer_unref (buffer); + + GST_DEBUG_OBJECT (trans, "buffer without caps extra ref, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + /* take additional ref to make it non-writable */ + gst_buffer_ref (buffer); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2); + + transform_ip_1_called = FALSE; + transform_ip_1_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ip_1_called == TRUE); + /* copy should have been taken with pad-alloc */ + fail_unless (transform_ip_1_writable == TRUE); + /* after push, get rid of the final ref we had */ + gst_buffer_unref (buffer); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + /* with caps buffer */ + GST_DEBUG_OBJECT (trans, "alloc without caps, size 20"); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +static gboolean set_caps_1_called; + +static gboolean +set_caps_1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) +{ + GstCaps *caps; + + GST_DEBUG_OBJECT (trans, "set_caps called"); + + set_caps_1_called = TRUE; + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + + fail_unless (gst_caps_is_equal (incaps, caps)); + fail_unless (gst_caps_is_equal (outcaps, caps)); + + gst_caps_unref (caps); + + return TRUE; +} + +/* basic in-place, check if the _ip function is called, buffer should be + * writable. we also set a setcaps function and see if it's called. */ +GST_START_TEST (basetransform_chain_ip2) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *caps; + + klass_transform_ip = transform_ip_1; + klass_set_caps = set_caps_1; + + trans = gst_test_trans_new (); + + caps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_test_trans_push_segment (trans); + + /* first try to push a buffer without caps, this should fail */ + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer without caps, size 20"); + + transform_ip_1_called = FALSE; + transform_ip_1_writable = FALSE; + set_caps_1_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (transform_ip_1_called == FALSE); + fail_unless (transform_ip_1_writable == FALSE); + fail_unless (set_caps_1_called == FALSE); + + /* try to push a buffer with caps */ + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + set_caps_1_called = FALSE; + gst_test_trans_setcaps (trans, caps); + gst_test_trans_push_segment (trans); + + GST_DEBUG_OBJECT (trans, "buffer with caps, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + + transform_ip_1_called = FALSE; + transform_ip_1_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ip_1_called == TRUE); + fail_unless (transform_ip_1_writable == TRUE); + fail_unless (set_caps_1_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + gst_buffer_unref (buffer); + + GST_DEBUG_OBJECT (trans, "buffer with caps extra ref, size 20"); + + buffer = gst_buffer_new_and_alloc (20); + /* take additional ref to make it non-writable */ + gst_buffer_ref (buffer); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2); + + transform_ip_1_called = FALSE; + transform_ip_1_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ip_1_called == TRUE); + fail_unless (transform_ip_1_writable == TRUE); + /* after push, get rid of the final ref we had */ + gst_buffer_unref (buffer); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + gst_caps_unref (caps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +static GstStaticPadTemplate sink_template_ct1 = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("baz/x-foo") + ); + +static gboolean set_caps_ct1_called; + +static gboolean +set_caps_ct1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) +{ + GstCaps *caps1, *caps2; + + GST_DEBUG_OBJECT (trans, "set_caps called"); + + caps1 = gst_caps_new_empty_simple ("baz/x-foo"); + caps2 = gst_caps_new_empty_simple ("foo/x-bar"); + + fail_unless (gst_caps_is_equal (incaps, caps1)); + fail_unless (gst_caps_is_equal (outcaps, caps2)); + + set_caps_ct1_called = TRUE; + + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + return TRUE; +} + +static gboolean transform_ct1_called; +static gboolean transform_ct1_writable; + +static GstFlowReturn +transform_ct1 (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out) +{ + transform_ct1_called = TRUE; + transform_ct1_writable = gst_buffer_is_writable (out); + + GST_DEBUG_OBJECT (trans, "writable: %d", transform_ct1_writable); + + return GST_FLOW_OK; +} + +static GstCaps * +transform_caps_ct1 (GstBaseTransform * trans, GstPadDirection dir, + GstCaps * caps, GstCaps * filter) +{ + GstCaps *res; + + if (dir == GST_PAD_SINK) { + res = gst_caps_new_empty_simple ("foo/x-bar"); + } else { + res = gst_caps_new_empty_simple ("baz/x-foo"); + } + + if (filter) { + GstCaps *temp = + gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (res); + res = temp; + } + + return res; +} + +static gboolean +transform_size_ct1 (GstBaseTransform * trans, GstPadDirection direction, + GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize) +{ + if (direction == GST_PAD_SINK) { + *othersize = size * 2; + } else { + *othersize = size / 2; + } + + return TRUE; +} + +/* basic copy-transform, check if the transform function is called, + * buffer should be writable. we also set a setcaps function and + * see if it's called. */ +GST_START_TEST (basetransform_chain_ct1) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *incaps, *outcaps; + + sink_template = &sink_template_ct1; + klass_transform = transform_ct1; + klass_set_caps = set_caps_ct1; + klass_transform_caps = transform_caps_ct1; + klass_transform_size = transform_size_ct1; + + trans = gst_test_trans_new (); + + incaps = gst_caps_new_empty_simple ("baz/x-foo"); + outcaps = gst_caps_new_empty_simple ("foo/x-bar"); + gst_test_trans_push_segment (trans); + + /* first try to push a buffer without caps, this should fail */ + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer without caps"); + + transform_ct1_called = FALSE; + transform_ct1_writable = FALSE; + set_caps_ct1_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (transform_ct1_called == FALSE); + fail_unless (transform_ct1_writable == FALSE); + fail_unless (set_caps_ct1_called == FALSE); + + /* try to push a buffer with caps */ + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + set_caps_ct1_called = FALSE; + gst_test_trans_setcaps (trans, incaps); + gst_test_trans_push_segment (trans); + + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + transform_ct1_called = FALSE; + transform_ct1_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct1_called == TRUE); + fail_unless (transform_ct1_writable == TRUE); + fail_unless (set_caps_ct1_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 40); + gst_buffer_unref (buffer); + + buffer = gst_buffer_new_and_alloc (20); + /* take additional ref to make it non-writable */ + gst_buffer_ref (buffer); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + transform_ct1_called = FALSE; + transform_ct1_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct1_called == TRUE); + fail_unless (transform_ct1_writable == TRUE); + /* after push, get rid of the final ref we had */ + gst_buffer_unref (buffer); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 40); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + gst_caps_unref (incaps); + gst_caps_unref (outcaps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +static GstStaticPadTemplate src_template_ct2 = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("baz/x-foo; foo/x-bar") + ); + +static gint set_caps_ct2_case; +static gboolean set_caps_ct2_called; + +static gboolean +set_caps_ct2 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) +{ + GstCaps *caps1, *caps2; + + GST_DEBUG_OBJECT (trans, "set_caps called"); + + caps1 = gst_caps_new_empty_simple ("foo/x-bar"); + + if (set_caps_ct2_case == 1) + caps2 = gst_caps_copy (caps1); + else + caps2 = gst_caps_new_empty_simple ("baz/x-foo"); + + fail_unless (gst_caps_is_equal (incaps, caps1)); + fail_unless (gst_caps_is_equal (outcaps, caps2)); + + set_caps_ct2_called = TRUE; + + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + return TRUE; +} + +static gboolean transform_ct2_called; +static gboolean transform_ct2_writable; + +static GstFlowReturn +transform_ct2 (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out) +{ + transform_ct2_called = TRUE; + transform_ct2_writable = gst_buffer_is_writable (out); + + GST_DEBUG_OBJECT (trans, "writable: %d", transform_ct2_writable); + + return GST_FLOW_OK; +} + +static GstCaps * +transform_caps_ct2 (GstBaseTransform * trans, GstPadDirection dir, + GstCaps * caps, GstCaps * filter) +{ + GstCaps *res; + + if (dir == GST_PAD_SINK) { + /* everything on the sinkpad can be transformed to the output formats */ + if (set_caps_ct2_case == 1) + res = gst_caps_new_empty_simple ("foo/x-bar"); + else + res = gst_caps_new_empty_simple ("baz/x-foo"); + } else { + /* all on the srcpad can be transformed to the format of the sinkpad */ + res = gst_caps_new_empty_simple ("foo/x-bar"); + } + + if (filter) { + GstCaps *temp = + gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (res); + res = temp; + } + + return res; +} + +static gboolean +transform_size_ct2 (GstBaseTransform * trans, GstPadDirection direction, + GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize) +{ + if (gst_caps_is_equal (caps, othercaps)) { + *othersize = size; + } else { + if (direction == GST_PAD_SINK) { + *othersize = size * 2; + } else { + *othersize = size / 2; + } + } + + return TRUE; +} + +/* basic copy-transform, check if the transform function is called, + * buffer should be writable. we also set a setcaps function and + * see if it's called. */ +GST_START_TEST (basetransform_chain_ct2) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *incaps, *outcaps; + + src_template = &src_template_ct2; + klass_transform = transform_ct2; + klass_set_caps = set_caps_ct2; + klass_transform_caps = transform_caps_ct2; + klass_transform_size = transform_size_ct2; + + trans = gst_test_trans_new (); + + incaps = gst_caps_new_empty_simple ("foo/x-bar"); + outcaps = gst_caps_new_empty_simple ("baz/x-foo"); + + gst_test_trans_push_segment (trans); + + /* first try to push a buffer without caps, this should fail */ + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer without caps"); + + transform_ct2_called = FALSE; + transform_ct2_writable = FALSE; + set_caps_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (transform_ct2_called == FALSE); + fail_unless (transform_ct2_writable == FALSE); + fail_unless (set_caps_ct2_called == FALSE); + + + /* try to push a buffer with caps */ + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + set_caps_ct2_case = 1; + set_caps_ct2_called = FALSE; + gst_test_trans_setcaps (trans, incaps); + gst_test_trans_push_segment (trans); + + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + transform_ct2_called = FALSE; + transform_ct2_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == TRUE); + fail_unless (transform_ct2_writable == TRUE); + fail_unless (set_caps_ct2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + gst_buffer_unref (buffer); + + buffer = gst_buffer_new_and_alloc (20); + /* take additional ref to make it non-writable */ + gst_buffer_ref (buffer); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + transform_ct2_called = FALSE; + transform_ct2_writable = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == TRUE); + fail_unless (transform_ct2_writable == TRUE); + /* after push, get rid of the final ref we had */ + gst_buffer_unref (buffer); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + gst_caps_unref (incaps); + gst_caps_unref (outcaps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +/* basic copy-transform, we work in passthrough here. */ +GST_START_TEST (basetransform_chain_ct3) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *incaps, *outcaps; + + src_template = &src_template_ct2; + klass_passthrough_on_same_caps = TRUE; + klass_transform = transform_ct2; + klass_set_caps = set_caps_ct2; + klass_transform_caps = transform_caps_ct2; + klass_transform_size = transform_size_ct2; + + trans = gst_test_trans_new (); + + incaps = gst_caps_new_empty_simple ("foo/x-bar"); + outcaps = gst_caps_new_empty_simple ("baz/x-foo"); + + /* with passthrough caps */ + gst_test_trans_push_segment (trans); + GST_DEBUG_OBJECT (trans, "alloc size 20, with passthrough caps %" + GST_PTR_FORMAT, incaps); + + /* first try to push a buffer without caps, this should fail */ + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer without caps"); + + transform_ct2_called = FALSE; + transform_ct2_writable = FALSE; + set_caps_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (transform_ct2_called == FALSE); + fail_unless (transform_ct2_writable == FALSE); + fail_unless (set_caps_ct2_called == FALSE); + + /* try to push a buffer with caps */ + buffer = gst_buffer_new_and_alloc (20); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + set_caps_ct2_case = 1; + set_caps_ct2_called = FALSE; + gst_test_trans_setcaps (trans, incaps); + gst_test_trans_push_segment (trans); + + transform_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == FALSE); + fail_unless (set_caps_ct2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + gst_buffer_unref (buffer); + + buffer = gst_buffer_new_and_alloc (20); + /* take additional ref to make it non-writable */ + gst_buffer_ref (buffer); + + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + + transform_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == FALSE); + /* after push, get rid of the final ref we had */ + gst_buffer_unref (buffer); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + /* change the return value of the buffer-alloc function */ + GST_DEBUG_OBJECT (trans, "switching transform output"); + + GST_DEBUG_OBJECT (trans, + "buffer with in passthrough with caps %" GST_PTR_FORMAT, incaps); + buffer = gst_buffer_new_and_alloc (10); + + /* don't suggest anything else */ + set_caps_ct2_case = 2; + gst_pad_push_event (trans->sinkpad, gst_event_new_reconfigure ()); + transform_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == TRUE); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + buffer = gst_buffer_new_and_alloc (10); + + /* don't suggest anything else */ + transform_ct2_called = FALSE; + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + fail_unless (transform_ct2_called == TRUE); + /* after push, get rid of the final ref we had */ + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 20); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + gst_caps_unref (incaps); + gst_caps_unref (outcaps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + +static void +transform1_setup (void) +{ + sink_template = &gst_test_trans_sink_template; + src_template = &gst_test_trans_src_template; +} + +static void +transform1_teardown (void) +{ + /* reset global state */ + klass_transform_ip = NULL; + klass_transform = NULL; + klass_transform_caps = NULL; + klass_transform_size = NULL; + klass_set_caps = NULL; + klass_submit_input_buffer = NULL; + klass_generate_output = NULL; +} + +static Suite * +gst_basetransform_suite (void) +{ + Suite *s = suite_create ("GstBaseTransform"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_checked_fixture (tc, transform1_setup, transform1_teardown); + + /* pass through */ + tcase_add_test (tc, basetransform_chain_pt1); + tcase_add_test (tc, basetransform_chain_pt2); + /* in place */ + tcase_add_test (tc, basetransform_chain_ip1); + tcase_add_test (tc, basetransform_chain_ip2); + /* copy transform */ + tcase_add_test (tc, basetransform_chain_ct1); + tcase_add_test (tc, basetransform_chain_ct2); + tcase_add_test (tc, basetransform_chain_ct3); + + return s; +} + +GST_CHECK_MAIN (gst_basetransform); diff --git a/tests/check/libs/transform2.c b/tests/check/libs/transform2.c new file mode 100644 index 0000000..bc1f4d0 --- /dev/null +++ b/tests/check/libs/transform2.c @@ -0,0 +1,165 @@ +/* GStreamer + * + * Unit tests for basetransform collation/separation + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "test_transform.c" + +GstBuffer *buf1, *buf2; + +/* Output buffers are twice the size as input */ +static gboolean +transform_size_collate (GstBaseTransform * trans, GstPadDirection direction, + GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize) +{ + if (direction == GST_PAD_SINK) { + *othersize = size * 2; + } else { + *othersize = size / 2; + } + + return TRUE; +} + +static GstFlowReturn +collate_submit_input_buffer (GstBaseTransform * trans, + gboolean is_discont, GstBuffer * input) +{ + GstBaseTransformClass *tt_parent_class; + GstFlowReturn ret; + + tt_parent_class = + g_type_class_peek_parent (GST_BASE_TRANSFORM_GET_CLASS (trans)); + + ret = tt_parent_class->submit_input_buffer (trans, is_discont, input); + + if (ret != GST_FLOW_OK) + return ret; + + fail_unless (buf1 == NULL || buf2 == NULL); + + if (buf1 == NULL) { + buf1 = trans->queued_buf; + trans->queued_buf = NULL; + } else if (buf2 == NULL) { + buf2 = trans->queued_buf; + trans->queued_buf = NULL; + } + + return ret; +} + +static GstFlowReturn +collate_generate_output (GstBaseTransform * trans, GstBuffer ** outbuf) +{ + /* Not ready to generate output unless we've collected 2 buffers */ + if (buf1 == NULL || buf2 == NULL) + return GST_BASE_TRANSFORM_FLOW_DROPPED; + + fail_unless (buf1 != NULL && buf2 != NULL); + *outbuf = gst_buffer_new_and_alloc (40); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); + buf1 = NULL; + buf2 = NULL; + + return GST_FLOW_OK; +} + +/* Take 2 input buffers, generate 1 output + * buffer with twice the size + */ +GST_START_TEST (basetransform_chain_collate) +{ + TestTransData *trans; + GstBuffer *buffer; + GstFlowReturn res; + GstCaps *incaps, *outcaps; + + src_template = &gst_test_trans_src_template; + klass_passthrough_on_same_caps = FALSE; + klass_transform_size = transform_size_collate; + klass_submit_input_buffer = collate_submit_input_buffer; + klass_generate_output = collate_generate_output; + + trans = gst_test_trans_new (); + + incaps = gst_caps_new_empty_simple ("foo/x-bar"); + outcaps = gst_caps_new_empty_simple ("foo/x-bar"); + + gst_test_trans_push_segment (trans); + + gst_pad_push_event (trans->srcpad, gst_event_new_flush_start ()); + gst_pad_push_event (trans->srcpad, gst_event_new_flush_stop (TRUE)); + + GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps); + gst_test_trans_setcaps (trans, incaps); + gst_test_trans_push_segment (trans); + + buffer = gst_buffer_new_and_alloc (20); + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + + /* We do not expect an output buffer after only pushing one input */ + buffer = gst_test_trans_pop (trans); + fail_unless (buffer == NULL); + + buffer = gst_buffer_new_and_alloc (20); + res = gst_test_trans_push (trans, buffer); + fail_unless (res == GST_FLOW_OK); + + buffer = gst_test_trans_pop (trans); + fail_unless (buffer != NULL); + fail_unless (gst_buffer_get_size (buffer) == 40); + + /* output buffer has refcount 1 */ + fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1); + gst_buffer_unref (buffer); + + gst_caps_unref (incaps); + gst_caps_unref (outcaps); + + gst_test_trans_free (trans); +} + +GST_END_TEST; + + +static Suite * +gst_basetransform_collate_suite (void) +{ + Suite *s = suite_create ("GstBaseTransformCollate"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_test (tc, basetransform_chain_collate); + + return s; +} + +GST_CHECK_MAIN (gst_basetransform_collate); diff --git a/tests/check/libs/typefindhelper.c b/tests/check/libs/typefindhelper.c new file mode 100644 index 0000000..750fc18 --- /dev/null +++ b/tests/check/libs/typefindhelper.c @@ -0,0 +1,123 @@ +/* GStreamer + * + * unit test for typefind helper + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +static const guint8 vorbisid[30] = { 0x01, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01 +}; + +static void foobar_typefind (GstTypeFind * tf, gpointer unused); + +static GstStaticCaps foobar_caps = GST_STATIC_CAPS ("foo/x-bar"); + +#define FOOBAR_CAPS (gst_static_caps_get (&foobar_caps)) + +/* make sure the entire data in the buffer is available for peeking */ +GST_START_TEST (test_buffer_range) +{ + GstStructure *s; + GstBuffer *buf; + GstCaps *caps; + + fail_unless (gst_type_find_register (NULL, "foo/x-bar", + GST_RANK_PRIMARY + 50, foobar_typefind, "foobar", + FOOBAR_CAPS, NULL, NULL)); + + buf = gst_buffer_new (); + fail_unless (buf != NULL); + + gst_buffer_insert_memory (buf, -1, + gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, + (gpointer) vorbisid, 30, 0, 30, NULL, NULL)); + + caps = gst_type_find_helper_for_buffer (NULL, buf, NULL); + fail_unless (caps != NULL); + fail_unless (GST_CAPS_IS_SIMPLE (caps)); + fail_unless (gst_caps_is_fixed (caps)); + + s = gst_caps_get_structure (caps, 0); + fail_unless (s != NULL); + fail_unless (gst_structure_has_name (s, "foo/x-bar")); + + gst_caps_unref (caps); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +static Suite * +gst_typefindhelper_suite (void) +{ + Suite *s = suite_create ("typefindhelper"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_buffer_range); + + return s; +} + +GST_CHECK_MAIN (gst_typefindhelper); + +static void +foobar_typefind (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + + data = gst_type_find_peek (tf, 0, 10); + fail_unless (data != NULL); + fail_unless (memcmp (data, vorbisid, 10) == 0); + + data = gst_type_find_peek (tf, 0, 20); + fail_unless (data != NULL); + fail_unless (memcmp (data, vorbisid, 20) == 0); + + data = gst_type_find_peek (tf, 0, 30); + fail_unless (data != NULL); + fail_unless (memcmp (data, vorbisid, 30) == 0); + + fail_unless (gst_type_find_peek (tf, 0, 31) == NULL); + fail_unless (gst_type_find_peek (tf, 1, 30) == NULL); + fail_unless (gst_type_find_peek (tf, 25, 6) == NULL); + + data = gst_type_find_peek (tf, 1, 29); + fail_unless (data != NULL); + fail_unless (memcmp (data, vorbisid + 1, 29) == 0); + + data = gst_type_find_peek (tf, 25, 4); + fail_unless (data != NULL); + fail_unless (memcmp (data, vorbisid + 25, 4) == 0); + + fail_unless (gst_type_find_peek (tf, -1, 29) == NULL); + fail_unless (gst_type_find_peek (tf, -1, 1) == NULL); + fail_unless (gst_type_find_peek (tf, -1, 0) == NULL); + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FOOBAR_CAPS); +} diff --git a/tests/check/meson.build b/tests/check/meson.build new file mode 100644 index 0000000..f2d9861 --- /dev/null +++ b/tests/check/meson.build @@ -0,0 +1,159 @@ +have_registry = not get_option('disable_registry') +have_debug = true # FIXME +have_parse = true # FIXME + +# tests and condition when to skip the test +core_tests = [ + [ 'gst/gst.c', not have_registry ], + [ 'gst/gstabi.c', not have_registry ], + [ 'gst/gstatomicqueue.c' ], + [ 'gst/gstbuffer.c' ], + [ 'gst/gstbufferlist.c' ], + [ 'gst/gstbufferpool.c' ], + [ 'gst/gstchildproxy.c', not have_registry ], + [ 'gst/gstclock.c' ], + [ 'gst/gstcontext.c' ], + [ 'gst/gstcontroller.c' ], + [ 'gst/gstcaps.c' ], + [ 'gst/gstcapsfeatures.c' ], + [ 'gst/gstdatetime.c' ], + [ 'gst/gstdeinit.c' ], + [ 'gst/gstdevice.c' ], + [ 'gst/gstelement.c', not have_registry ], + [ 'gst/gstelementfactory.c', not have_registry ], + [ 'gst/gstghostpad.c', not have_registry ], + [ 'gst/gstinfo.c' ], + [ 'gst/gstiterator.c' ], + [ 'gst/gstmessage.c' ], + [ 'gst/gstmemory.c' ], + [ 'gst/gstmeta.c' ], + [ 'gst/gstminiobject.c' ], + [ 'gst/gstobject.c' ], + [ 'gst/gstpad.c', not have_registry ], + [ 'gst/gstparamspecs.c' ], + [ 'gst/gstprintf.c', disable_gst_debug, printf_lib], + [ 'gst/gstpipeline.c', not have_registry ], + [ 'gst/gstpoll.c' ], + [ 'gst/gstplugin.c', not have_registry ], + [ 'gst/gstpreset.c' ], + [ 'gst/gstprotection.c' ], + [ 'gst/gstquery.c', not have_registry ], + [ 'gst/gstregistry.c', not have_registry ], + [ 'gst/gstpromise.c'], + [ 'gst/gstsegment.c' ], + [ 'gst/gststream.c' ], + [ 'gst/gststructure.c' ], + [ 'gst/gstsystemclock.c' ], + [ 'gst/gsttag.c' ], + [ 'gst/gsttagsetter.c' ], + [ 'gst/gsttask.c' ], + [ 'gst/gsttoc.c' ], + [ 'gst/gsttocsetter.c' ], + [ 'gst/gsttracerrecord.c', disable_tracer_hooks or disable_gst_debug], + [ 'gst/gsturi.c' ], + [ 'gst/gstutils.c', not have_registry ], + [ 'gst/gstvalue.c' ], + [ 'generic/states.c', not have_registry ], + [ 'libs/adapter.c' ], + [ 'libs/aggregator.c' ], + [ 'libs/baseparse.c' ], + [ 'libs/basesrc.c', not have_registry ], + [ 'libs/basesink.c', not have_registry ], + [ 'libs/bitreader.c' ], + [ 'libs/bytereader.c' ], + [ 'libs/bytewriter.c' ], + [ 'libs/bitreader-noinline.c' ], + [ 'libs/bytereader-noinline.c' ], + [ 'libs/bytewriter-noinline.c' ], + [ 'libs/collectpads.c', not have_registry ], + [ 'libs/controller.c' ], + [ 'libs/flowcombiner.c' ], + [ 'libs/gstharness.c' ], + [ 'libs/gstnetclientclock.c' ], + [ 'libs/gstnettimeprovider.c' ], + [ 'libs/gsttestclock.c' ], + [ 'libs/libsabi.c' ], + [ 'libs/sparsefile.c' ], + [ 'libs/transform1.c' ], + [ 'libs/transform2.c' ], + [ 'libs/typefindhelper.c' ], + [ 'libs/queuearray.c' ], + [ 'elements/capsfilter.c', not have_registry ], + [ 'elements/concat.c', not have_registry ], + [ 'elements/dataurisrc.c', not have_registry ], + [ 'elements/fakesrc.c', not have_registry ], + [ 'elements/fdsrc.c', not have_registry ], + [ 'elements/filesink.c', not have_registry ], + [ 'elements/filesrc.c', not have_registry ], + [ 'elements/funnel.c', not have_registry ], + [ 'elements/identity.c', not have_registry ], + [ 'elements/multiqueue.c', not have_registry ], + [ 'elements/selector.c', not have_registry ], + [ 'elements/streamiddemux.c', not have_registry ], + [ 'elements/tee.c', not have_registry ], + [ 'elements/queue.c', not have_registry ], + [ 'elements/queue2.c', not have_registry ], + [ 'elements/valve.c', not have_registry ], + [ 'pipelines/seek.c', not have_registry ], + [ 'pipelines/queue-error.c', not have_registry ], + [ 'pipelines/parse-disabled.c', have_parse ], + [ 'pipelines/simple-launch-lines.c', not have_parse ], + [ 'pipelines/parse-launch.c', not have_parse ], + [ 'pipelines/cleanup.c', not have_parse ], + [ 'tools/gstinspect.c' ], + # These take quite long, put them at the end + [ 'elements/fakesink.c', not have_registry ], + [ 'gst/gstbin.c', not have_registry ], + [ 'gst/gstbus.c', not have_registry ], + [ 'gst/gstevent.c', not have_registry ], + [ 'pipelines/stress.c', not have_registry ], + [ 'generic/sinks.c', not have_registry ], +] + +# Make sure our headers are C++ clean +if add_languages('cpp', required : false) + core_tests += [ + [ 'gst/gstcpp.cc', not have_registry ], + [ 'libs/gstlibscpp.cc', false ], + ] +endif + +test_defines = [ + '-UG_DISABLE_ASSERT', + '-UG_DISABLE_CAST_CHECKS', + '-DGST_CHECK_TEST_ENVIRONMENT_BEACON="GST_STATE_IGNORE_ELEMENTS"', + '-DTESTFILE="' + meson.current_source_dir() + '/meson.build"', + '-DGST_USE_UNSTABLE_API', + '-DGST_DISABLE_DEPRECATED', +] + +glib_deps = [gio_dep, gobject_dep, gmodule_dep, glib_dep] +gst_deps = [gst_dep, gst_base_dep, gst_check_dep, gst_net_dep, gst_controller_dep] + +foreach t : core_tests + fname = t[0] + test_name = fname.split('.')[0].underscorify() + skip_test = t.get(1, false) + link_with_libs = t.get(2, []) + + if not skip_test + exe = executable(test_name, fname, + c_args : gst_c_args + test_defines, + cpp_args : gst_c_args + test_defines, + include_directories : [configinc], + link_with : link_with_libs, + dependencies : test_deps + glib_deps + gst_deps, + ) + + env = environment() + env.set('GST_PLUGIN_PATH_1_0', meson.build_root()) + env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '') + env.set('GST_STATE_IGNORE_ELEMENTS', '') + env.set('CK_DEFAULT_TIMEOUT', '20') + env.set('GST_REGISTRY', '@0@/@1@.registry'.format(meson.current_build_dir(), test_name)) + env.set('GST_PLUGIN_SCANNER_1_0', gst_scanner_dir + '/gst-plugin-scanner') + env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer') + + test(test_name, exe, env: env, timeout : 3 * 60) + endif +endforeach diff --git a/tests/check/pipelines/cleanup.c b/tests/check/pipelines/cleanup.c new file mode 100644 index 0000000..5ccb50b --- /dev/null +++ b/tests/check/pipelines/cleanup.c @@ -0,0 +1,120 @@ +/* GStreamer + * Copyright (C) <2005> Thomas Vander Stichele + * + * cleanup.c: Unit test for cleanup of 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include + + +static GstElement * +setup_pipeline (const gchar * pipe_descr) +{ + GstElement *pipeline; + + pipeline = gst_parse_launch (pipe_descr, NULL); + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL); + return pipeline; +} + +/* 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 * pipeline, const gchar * descr, + GstMessageType events, GstMessageType tevent) +{ + GstBus *bus; + GstMessageType revent; + + bus = gst_element_get_bus (pipeline); + g_assert (bus); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + while (1) { + GstMessage *message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2); + + 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); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (bus); +} + +GST_START_TEST (test_pipeline_unref) +{ + const gchar *s; + GstElement *pipeline, *src, *sink; + + s = "fakesrc name=src num-buffers=20 ! fakesink name=sink"; + pipeline = setup_pipeline (s); + /* get_by_name takes a ref */ + src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); + fail_if (src == NULL); + sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); + fail_if (sink == NULL); + + run_pipeline (pipeline, s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); + while (GST_OBJECT_REFCOUNT_VALUE (src) > 1) + THREAD_SWITCH (); + ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (sink, "sink", 1); + gst_object_unref (src); + gst_object_unref (sink); +} + +GST_END_TEST; + +static Suite * +cleanup_suite (void) +{ + Suite *s = suite_create ("Pipeline cleanup"); + TCase *tc_chain = tcase_create ("linear"); + + /* time out after 20s, not the default 3 */ + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_pipeline_unref); + return s; +} + +GST_CHECK_MAIN (cleanup); diff --git a/tests/check/pipelines/parse-disabled.c b/tests/check/pipelines/parse-disabled.c new file mode 100644 index 0000000..5ddb0e3 --- /dev/null +++ b/tests/check/pipelines/parse-disabled.c @@ -0,0 +1,72 @@ +/* GStreamer unit test for disabled gst-parse + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +GST_START_TEST (test_parse_launch_errors) +{ + GstElement *pipe; + GError *err; + const gchar *arr[] = { "fakesrc", "fakesink", NULL }; + + err = NULL; + pipe = gst_parse_launch ("fakesrc ! fakesink", &err); + fail_unless (err != NULL, "expected an error, but did not get one"); + fail_unless (pipe == NULL, "got pipeline, but expected NULL"); + fail_unless (err->domain == GST_CORE_ERROR); + fail_unless (err->code == GST_CORE_ERROR_DISABLED); + g_error_free (err); + + err = NULL; + pipe = gst_parse_bin_from_description ("fakesrc ! fakesink", TRUE, &err); + fail_unless (err != NULL, "expected an error, but did not get one"); + fail_unless (pipe == NULL, "got pipeline, but expected NULL"); + fail_unless (err->domain == GST_CORE_ERROR); + fail_unless (err->code == GST_CORE_ERROR_DISABLED); + g_error_free (err); + + err = NULL; + pipe = gst_parse_launchv (arr, &err); + fail_unless (err != NULL, "expected an error, but did not get one"); + fail_unless (pipe == NULL, "got pipeline, but expected NULL"); + fail_unless (err->domain == GST_CORE_ERROR); + fail_unless (err->code == GST_CORE_ERROR_DISABLED); + g_error_free (err); +} + +GST_END_TEST; + +static Suite * +parsedisabled_suite (void) +{ + Suite *s = suite_create ("Parse Launch (Disabled Mode)"); + TCase *tc_chain = tcase_create ("parselaunchdisabled"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_parse_launch_errors); + return s; +} + +GST_CHECK_MAIN (parsedisabled); diff --git a/tests/check/pipelines/parse-launch.c b/tests/check/pipelines/parse-launch.c new file mode 100644 index 0000000..6e91165 --- /dev/null +++ b/tests/check/pipelines/parse-launch.c @@ -0,0 +1,728 @@ +/* GStreamer gst_parse_launch unit tests + * Copyright (C) <2005> Thomas Vander Stichele + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#define GST_TYPE_PARSE_TEST_ELEMENT (gst_parse_test_element_get_type()) +static GType gst_parse_test_element_get_type (void); + +static GstElement * +setup_pipeline (const gchar * pipe_descr) +{ + GstElement *pipeline; + GError *error = NULL; + + GST_DEBUG ("creating [%s] setup_pipeline", pipe_descr); + + pipeline = gst_parse_launch (pipe_descr, &error); + + GST_DEBUG ("created [%s] setup_pipeline", pipe_descr); + + if (error != NULL) { + fail_if (error != NULL, "Error parsing pipeline %s: %s", pipe_descr, + error->message); + g_error_free (error); + } + fail_unless (pipeline != NULL, "Failed to create pipeline %s", pipe_descr); + /* Newly returned object should be floating reffed */ + fail_unless (g_object_is_floating (pipeline)); + g_assert_cmpuint (G_OBJECT (pipeline)->ref_count, ==, 1); + return pipeline; +} + +static void +expected_fail_pipe (const gchar * pipe_descr) +{ + GstElement *pipeline; + GError *error = NULL; + +#ifndef GST_DISABLE_GST_DEBUG + gst_debug_set_default_threshold (GST_LEVEL_NONE); +#endif + + pipeline = gst_parse_launch (pipe_descr, &error); + fail_unless (pipeline == NULL || error != NULL, + "Expected failure pipeline %s: succeeded!", pipe_descr); + g_error_free (error); + + /* We get a pipeline back even when parsing has failed, sometimes! */ + if (pipeline) + gst_object_unref (pipeline); +} + +static void +check_pipeline_runs (GstElement * p) +{ + GstStateChangeReturn ret; + + /* Check that the pipeline changes state to PAUSED and back to NULL */ + ret = gst_element_set_state (p, GST_STATE_PAUSED); + if (ret == GST_STATE_CHANGE_ASYNC) + ret = gst_element_get_state (p, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret != GST_STATE_CHANGE_FAILURE, + "Could not set pipeline to paused"); + + ret = gst_element_set_state (p, GST_STATE_NULL); + if (ret == GST_STATE_CHANGE_ASYNC) + ret = gst_element_get_state (p, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (ret != GST_STATE_CHANGE_FAILURE, + "Could not set pipeline to null"); +} + +static const gchar *test_lines[] = { + "filesrc location=music.mp3 ! identity silent=true ! fakesink silent=true", + "filesrc location=music.ogg ! tee ! identity silent=true ! identity silent=true ! fakesink silent=true", + "filesrc location=http://domain.com/music.mp3 ! identity silent=true ! fakesink silent=true", + "filesrc location=movie.avi ! tee name=demuxer ! ( queue ! identity silent=true ! fakesink silent=true ) ( demuxer. ! queue ! identity silent=true ! fakesink silent=true )", + "fakesrc ! video/x-raw ! fakesink silent=true", + "fakesrc ! video/raw, format=(string)YUY2; video/raw, format=(string)YV12 ! fakesink silent=true", + "fakesrc ! audio/x-raw, width=[16, 32], depth={16, 24, 32}, signed=TRUE ! fakesink silent=true", + "fakesrc ! identity silent=true ! identity silent=true ! identity silent=true ! fakesink silent=true", + "fakesrc name=100 fakesink name=101 silent=true 100. ! 101.", /* linking with named reference on both sides */ + "fakesrc ! 1__dentity ! fakesink silent=true", /* using a freshly registered element type */ + "fakesrc ! tee name=t t.src_12 ! queue ! fakesink t.src_3 ! queue ! fakesink", + "fakesrc name=foo name=fin fin. ! fakesink", /* testing assignments are executed in correct order (left-to-right) */ + "( fakesrc ) ! fakesink", /* ghostPad creation on-the-fly, infix notation link */ + "( fakesrc name=dasrc ) dasrc. ! fakesink", /* ghostPad creation on-the-fly, named link */ +/* "(name=mabin fakesrc) mabin. ! fakesink", FIXME: linking to named bin does not work yet */ +/* "(name=mabin name=yoyo fakesrc) yoyo. ! fakesink", FIXME: linking to named bin does not work yet */ + "deepsrc. ! fakesink fakesrc ! ( identity ! ( identity ! ( identity name=deepsrc ) ) )", /* deep name resolution, multilevel ghostpad creation */ + "fakesrc : fakesink", /* linking all matching pads */ + "fakesrc : video/x-all : fakesink", /* linking all matching pads with filter */ + "fakesrc ! video/x-all : fakesink", /* linking all matching pads with filter */ + "fakesrc : video/x-all ! fakesink", /* linking all matching pads with filter */ + NULL +}; + +GST_START_TEST (test_launch_lines) +{ + GstElement *pipeline; + const gchar **s; + GType type; + GstElementFactory *efac; + + efac = gst_element_factory_find ("identity"); + fail_unless (efac != NULL); + efac = + GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (efac))); + fail_unless (efac != NULL); + type = gst_element_factory_get_element_type (efac); + fail_unless (type != 0); + g_object_unref (efac); + g_object_unref (efac); + fail_unless (gst_element_register (NULL, "1__dentity", GST_RANK_NONE, type)); + + for (s = test_lines; *s != NULL; s++) { + pipeline = setup_pipeline (*s); + gst_object_unref (pipeline); + } +} + +GST_END_TEST; + +#define PIPELINE1 "fakesrc" +#define PIPELINE2 "fakesrc name=donald num-buffers= 27 silent =TruE sizetype = 3 data= Subbuffer\\ data" +#define PIPELINE3 "fakesrc identity silent=true fakesink silent=true" +#define PIPELINE4 "fakesrc num-buffers=4 .src ! identity silent=true !.sink identity silent=true .src ! .sink fakesink silent=true" +#define PIPELINE5 "fakesrc num-buffers=4 name=src identity silent=true name=id1 identity silent=true name = id2 fakesink silent=true name =sink src. ! id1. id1.! id2.sink id2.src!sink.sink" +#define PIPELINE6 "pipeline.(name=\"john\" fakesrc num-buffers=4 ! ( bin. ( queue ! identity silent=true !( queue ! fakesink silent=true )) ))" +#define PIPELINE7 "fakesrc num-buffers=4 ! tee name=tee .src_%u ! queue ! fakesink silent=true tee.src_%u ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src_%u ! foo." +/* aggregator is borked + * #define PIPELINE8 "fakesrc num-buffers=4 ! tee name=tee1 .src0,src1 ! .sink0, sink1 aggregator ! fakesink silent=true" + * */ +#define PIPELINE8 "fakesrc num-buffers=4 ! fakesink silent=true" +#define PIPELINE9 "fakesrc num-buffers=4 ! test. fakesink silent=true name=test" +#define PIPELINE10 "( fakesrc num-buffers=\"4\" ) ! identity silent=true ! fakesink silent=true" +#define PIPELINE11 "fakesink silent=true name = sink identity silent=true name=id ( fakesrc num-buffers=\"4\" ! id. ) id. ! sink." +#define PIPELINE12 "file:///tmp/test.file ! fakesink silent=true" +#define PIPELINE13 "fakesrc ! file:///tmp/test.file" +#define PIPELINE14 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\,x\"" +#define PIPELINE15 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\\"x\\,x\"" + +GST_START_TEST (test_launch_lines2) +{ + GstElement *cur; + gint i; + gboolean b; + gchar *s = NULL; + + /** + * checks: + * - specifying an element works :) + * - if only 1 element is requested, no bin is returned, but the element + */ + cur = setup_pipeline (PIPELINE1); + fail_unless (G_OBJECT_TYPE (cur) == g_type_from_name ("GstFakeSrc"), + "parse_launch did not produce a fakesrc"); + gst_object_unref (cur); + + /** + * checks: + * - properties works + * - string, int, boolean and enums can be properly set + * - first test of escaping strings + */ + cur = setup_pipeline (PIPELINE2); + g_object_get (G_OBJECT (cur), "name", &s, "num-buffers", &i, + "silent", &b, NULL); + fail_if (s == NULL, "name was NULL"); + fail_unless (strcmp (s, "donald") == 0, "fakesrc name was not 'donald'"); + fail_unless (i == 27, "num-buffers was not 27"); + fail_unless (b == TRUE, "silent was not TRUE"); + g_free (s); + + g_object_get (G_OBJECT (cur), "sizetype", &i, NULL); + fail_unless (i == 3, "sizetype != 3"); + + g_object_get (G_OBJECT (cur), "data", &i, NULL); + fail_unless (i == 2, "data != 2"); + gst_object_unref (cur); + + /** + * checks: + * - specifying multiple elements without links works + * - if multiple toplevel elements exist, a pipeline is returned + */ + cur = setup_pipeline (PIPELINE3); + fail_unless (GST_BIN_NUMCHILDREN (cur) == 3, + "Pipeline does not contain 3 children"); + gst_object_unref (cur); + + /** + * checks: + * - test default link "!" + * - test if specifying pads on links works + */ + cur = setup_pipeline (PIPELINE4); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - test if appending the links works, too + * - check if the pipeline constructed works the same as the one before (how?) + */ + cur = setup_pipeline (PIPELINE5); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - test various types of bins + * - test if linking across bins works + * - test if escaping strings works + */ + cur = setup_pipeline (PIPELINE6); + /* FIXME: valgrind finds element later */ + fail_unless (GST_IS_PIPELINE (cur), "Parse did not produce a pipeline"); + g_object_get (G_OBJECT (cur), "name", &s, NULL); + fail_if (s == NULL, "name was NULL"); + fail_unless (strcmp (s, "john") == 0, "Name was not 'john'"); + g_free (s); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - test request pads + */ + cur = setup_pipeline (PIPELINE7); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - multiple pads on 1 link + */ + cur = setup_pipeline (PIPELINE8); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - failed in grammar.y cvs version 1.17 + */ + cur = setup_pipeline (PIPELINE9); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - failed in grammar.y cvs version 1.17 + */ + cur = setup_pipeline (PIPELINE10); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - failed in grammar.y cvs version 1.18 + */ + cur = setup_pipeline (PIPELINE11); + check_pipeline_runs (cur); + gst_object_unref (cur); + + /** + * checks: + * - URI detection works + */ + cur = setup_pipeline (PIPELINE12); + gst_object_unref (cur); + + /** * checks: + * - URI sink detection works + */ + cur = setup_pipeline (PIPELINE13); + gst_object_unref (cur); + + /** + * Checks if characters inside quotes are not escaped. + */ + cur = setup_pipeline (PIPELINE14); + gst_object_unref (cur); + + /** + * Checks if escaped quotes inside quotes are not treated as end string quotes. + * This would make the rest of characters to be escaped incorrectly. + */ + cur = setup_pipeline (PIPELINE15); + gst_object_unref (cur); +} + +GST_END_TEST; + +static const gchar *expected_failures[] = { + /* checks: fails because a=b. is not a valid element reference in parse.l */ + "fakesrc num-buffers=4 name=\"a=b\" a=b. ! fakesink silent=true", + /* checks: Error branch for a non-deserialisable property value */ + "filesrc blocksize=absdff", + /* checks: That broken caps which don't parse can't create a pipeline */ + "fakesrc ! video/raw,format=(antwerp)monkeys ! fakesink silent=true", + /* checks: Empty pipeline is invalid */ + "", + /* checks: Link without sink element failes */ + "fakesrc ! ", + /* checks: Link without src element failes */ + " ! fakesink silent=true", + /* checks: Source URI for which no element exists is a failure */ + "borky://fdaffd ! fakesink silent=true", + /* checks: Sink URI for which no element exists is a failure */ + "fakesrc ! borky://fdaffd", + /* checks: Referencing non-existent source element by name can't link */ + "fakesrc name=src fakesink silent=true name=sink noexiste. ! sink.", + /* checks: Referencing non-existent sink element by name can't link */ + "fakesrc name=src fakesink silent=true name=sink src. ! noexiste.", + /* checks: Can't link 2 elements that only have sink pads */ + "fakesink silent=true ! fakesink silent=true", + /* checks multi-chain link without src element fails. */ + "! identity silent=true ! identity silent=true ! fakesink silent=true", + /* Empty bin not allowed */ + "bin.( )", + /* bin with non-existent element counts as empty, and not allowed */ + "bin.( non_existent_element )", + /* bin with an element, assignments and then a syntax error */ + "( filesrc blocksize=4 location=/dev/null @ )", + /* bin linking with the ! inside the bin and no ! outside */ + "( fakesrc num-buffers=\"4\" ! ) identity silent=true ! fakesink silent=true", + /* bins with linking without ! */ + /* FIXME: one element leaks as reported by valgrind */ + "pipeline.(name=\"john\" fakesrc num-buffers=4 ( bin. ( ! queue ! identity silent=true !( queue ! fakesink silent=true )) ))", + /* non-existent bin-type containing already created elements */ + "coffeebin.( fakesrc ! identity ! fakesink )", + /* non-existent bin-type in pipeline */ + "fakesrc ! coffeebin.( identity ) ! fakesink", + /* unexpected pad references Part I */ + "fakesrc ! .ch0 .ch1 fakesink", + /* unexpected pad references Part II */ + "fakesrc .ch0 .ch1 ! fakesink", + /* unexpected pad references Part III */ + "(fakesrc .ch1) ! fakesink", + /* unexpected full reference, I */ + "(fakesrc name=s s.ch1) ! fakesink", + /* unexpected full reference, II */ + "s.ch1 fakesrc ! fakesink", + /* unexpected full reference, III */ + "fakesrc ! fakesink s.ch1", + /* unlinked src/sink URI */ + "http://eff.org fakesrc ! fakesink", + /* catch assignments evaluated in wrong order */ + "fakesrc name=ss name=st ss. ! fakesink", + /* unbalanced brackets */ + "(", ")", ") (", + /* END: */ + NULL +}; + +GST_START_TEST (expected_to_fail_pipes) +{ + const gchar **s; + + for (s = expected_failures; *s != NULL; s++) { + expected_fail_pipe (*s); + } +} + +GST_END_TEST; + +static const gchar *leaking_failures[] = { + /* checks: Invalid pipeline syntax fails */ + "fakesrc ! identity silent=true ! sgsdfagfd @ gfdgfdsgfsgSF", + /* checks: Attempting to link to a non-existent pad on an element + * created via URI handler should fail */ + "fakesrc ! .foo file:///dev/null", + /* checks: That requesting an element which doesn't exist doesn't work */ + "error-does-not-exist-src", + NULL +}; + +/* These don't seem to leak any longer? */ +GST_START_TEST (leaking_fail_pipes) +{ + const gchar **s; + + for (s = leaking_failures; *s != NULL; s++) { + GST_INFO ("Trying pipe: %s", *s); + expected_fail_pipe (*s); + } +} + +GST_END_TEST; + +/* Helper function to test delayed linking support in parse_launch by creating + * a test element based on bin, which contains a fakesrc and a sometimes + * pad-template, and trying to link to a fakesink. When the bin transitions + * to paused it adds a pad, which should get linked to the fakesink */ +static void +run_delayed_test (const gchar * pipe_str, const gchar * peer, + gboolean expect_link) +{ + GstElement *pipe, *src, *sink; + GstPad *srcpad, *sinkpad, *peerpad = NULL; + + pipe = setup_pipeline (pipe_str); + + src = gst_bin_get_by_name (GST_BIN (pipe), "src"); + fail_if (src == NULL, "Test source element was not created"); + + sink = gst_bin_get_by_name (GST_BIN (pipe), "sink"); + fail_if (sink == NULL, "Test sink element was not created"); + + /* The src should not yet have a src pad */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_unless (srcpad == NULL, "Source element already has a source pad"); + + /* Set the state to PAUSED and wait until the src at least reaches that + * state */ + fail_if (gst_element_set_state (pipe, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE); + + fail_if (gst_element_get_state (src, NULL, NULL, GST_CLOCK_TIME_NONE) == + GST_STATE_CHANGE_FAILURE); + + /* Now, the source element should have a src pad, and if "peer" was passed, + * then the src pad should have gotten linked to the 'sink' pad of that + * peer */ + srcpad = gst_element_get_static_pad (src, "src"); + fail_if (srcpad == NULL, "Source element did not create source pad"); + + peerpad = gst_pad_get_peer (srcpad); + + if (expect_link == TRUE) { + fail_if (peerpad == NULL, "Source element pad did not get linked"); + } else { + fail_if (peerpad != NULL, + "Source element pad got linked but should not have"); + } + if (peerpad != NULL) + gst_object_unref (peerpad); + + if (peer != NULL) { + GstElement *peer_elem = gst_bin_get_by_name (GST_BIN (pipe), peer); + + fail_if (peer_elem == NULL, "Could not retrieve peer %s", peer); + + sinkpad = gst_element_get_static_pad (peer_elem, "sink"); + gst_object_unref (peer_elem); + fail_if (sinkpad == NULL, "Peer element did not have a 'sink' pad"); + + fail_unless (peerpad == sinkpad, + "Source src pad got connected to the wrong peer"); + gst_object_unref (sinkpad); + } + + gst_object_unref (srcpad); + + gst_object_unref (src); + gst_object_unref (sink); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_START_TEST (delayed_link) +{ + fail_unless (gst_element_register (NULL, "parsetestelement", + GST_RANK_NONE, GST_TYPE_PARSE_TEST_ELEMENT)); + + /* This tests the delayed linking support in parse_launch by creating + * a test element based on bin, which contains a fakesrc and a sometimes + * pad-template, and trying to link to a fakesink. When the bin transitions + * to paused it adds a pad, which should get linked to the fakesink */ + run_delayed_test + ("parsetestelement name=src ! fakesink silent=true name=sink", "sink", + TRUE); + /* FIXME: valgrind finds one element */ + + /* Test, but this time specifying both pad names */ + run_delayed_test ("parsetestelement name=src .src ! " + ".sink fakesink silent=true name=sink", "sink", TRUE); + /* FIXME: valgrind finds one element */ + + /* Now try with a caps filter, but not testing that + * the peerpad == sinkpad, because the peer will actually + * be a capsfilter */ + run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! " + "fakesink silent=true name=sink", NULL, TRUE); + + /* Now try with mutually exclusive caps filters that + * will prevent linking, but only once gets around to happening - + * ie, the pipeline should create ok but fail to change state */ + run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! " + "identity silent=true ! application/x-other-caps ! " + "fakesink silent=true name=sink silent=true", NULL, FALSE); +} + +GST_END_TEST; + +typedef struct _GstParseTestElement +{ + GstBin parent; + + GstElement *fakesrc; +} GstParseTestElement; + +typedef struct _GstParseTestElementClass +{ + GstBinClass parent; +} GstParseTestElementClass; + +static GstStaticPadTemplate test_element_pad_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, + GST_PAD_SOMETIMES, GST_STATIC_CAPS ("application/x-test-caps")); +#define gst_parse_test_element_parent_class parent_class +G_DEFINE_TYPE (GstParseTestElement, gst_parse_test_element, GST_TYPE_BIN); + +static GstStateChangeReturn +gst_parse_test_element_change_state (GstElement * element, + GstStateChange transition); + +static void +gst_parse_test_element_class_init (GstParseTestElementClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_static_pad_template (gstelement_class, + &test_element_pad_template); + + gst_element_class_set_metadata (gstelement_class, + "Test element for parse launch tests", "Source", + "Test element for parse launch tests in core", + "GStreamer Devel "); + + gstelement_class->change_state = gst_parse_test_element_change_state; +} + +static void +gst_parse_test_element_init (GstParseTestElement * src) +{ + /* Create a fakesrc and add it to ourselves */ + src->fakesrc = gst_element_factory_make ("fakesrc", NULL); + if (src->fakesrc) + gst_bin_add (GST_BIN (src), src->fakesrc); +} + +static GstStateChangeReturn +gst_parse_test_element_change_state (GstElement * element, + GstStateChange transition) +{ + GstParseTestElement *src = (GstParseTestElement *) element; + + if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) { + /* Add our pad */ + GstPad *pad; + GstPad *ghost; + + if (src->fakesrc == NULL) + return GST_STATE_CHANGE_FAILURE; + + pad = gst_element_get_static_pad (src->fakesrc, "src"); + if (pad == NULL) + return GST_STATE_CHANGE_FAILURE; + + ghost = gst_ghost_pad_new ("src", pad); + fail_if (ghost == NULL, "Failed to create ghost pad"); + /* activate and add */ + gst_pad_set_active (ghost, TRUE); + gst_element_add_pad (GST_ELEMENT (src), ghost); + gst_object_unref (pad); + } + + return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); +} + +GST_START_TEST (test_missing_elements) +{ + GstParseContext *ctx; + GstElement *element; + GError *err = NULL; + gchar **arr; + + /* avoid misleading 'no such element' error debug messages when using cvs */ + if (!g_getenv ("GST_DEBUG")) + gst_debug_set_default_threshold (GST_LEVEL_NONE); + + /* one missing element */ + ctx = gst_parse_context_new (); + element = gst_parse_launch_full ("fakesrc ! coffeesink", ctx, + GST_PARSE_FLAG_FATAL_ERRORS, &err); + fail_unless (err != NULL, "expected error"); + fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT); + fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS"); + arr = gst_parse_context_get_missing_elements (ctx); + fail_unless (arr != NULL, "expected missing elements"); + fail_unless_equals_string (arr[0], "coffeesink"); + fail_unless (arr[1] == NULL); + g_strfreev (arr); + gst_parse_context_free (ctx); + g_error_free (err); + err = NULL; + + /* multiple missing elements */ + ctx = gst_parse_context_new (); + element = gst_parse_launch_full ("fakesrc ! bogusenc ! identity ! goomux ! " + "fakesink", ctx, GST_PARSE_FLAG_FATAL_ERRORS, &err); + fail_unless (err != NULL, "expected error"); + fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT); + fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS"); + arr = gst_parse_context_get_missing_elements (ctx); + fail_unless (arr != NULL, "expected missing elements"); + fail_unless_equals_string (arr[0], "bogusenc"); + fail_unless_equals_string (arr[1], "goomux"); + fail_unless (arr[2] == NULL); + g_strfreev (arr); + gst_parse_context_free (ctx); + g_error_free (err); + err = NULL; + + /* multiple missing elements, different link pattern */ + ctx = gst_parse_context_new (); + element = gst_parse_launch_full ("fakesrc ! bogusenc ! mux.sink " + "blahsrc ! goomux name=mux ! fakesink fakesrc ! goosink", ctx, + GST_PARSE_FLAG_FATAL_ERRORS, &err); + fail_unless (err != NULL, "expected error"); + fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT); + fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS"); + arr = gst_parse_context_get_missing_elements (ctx); + fail_unless (arr != NULL, "expected missing elements"); + fail_unless_equals_string (arr[0], "bogusenc"); + fail_unless_equals_string (arr[1], "blahsrc"); + fail_unless_equals_string (arr[2], "goomux"); + fail_unless_equals_string (arr[3], "goosink"); + fail_unless (arr[4] == NULL); + g_strfreev (arr); + gst_parse_context_free (ctx); + g_error_free (err); + err = NULL; +} + +GST_END_TEST; + +GST_START_TEST (test_flags) +{ + GstElement *element; + GError *err = NULL; + + /* avoid misleading 'no such element' error debug messages when using cvs */ + if (!g_getenv ("GST_DEBUG")) + gst_debug_set_default_threshold (GST_LEVEL_NONE); + + /* default behaviour is to return any already constructed bins/elements */ + element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, 0, &err); + fail_unless (err != NULL, "expected error"); + fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT); + fail_unless (element != NULL, "expected partial pipeline/element"); + g_error_free (err); + err = NULL; + gst_object_unref (element); + + /* test GST_PARSE_FLAG_FATAL_ERRORS */ + element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, + GST_PARSE_FLAG_FATAL_ERRORS, &err); + fail_unless (err != NULL, "expected error"); + fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT); + fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS"); + g_error_free (err); + err = NULL; + + /* test GST_PARSE_FLAG_FATAL_ERRORS without GError */ + element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, + GST_PARSE_FLAG_FATAL_ERRORS, NULL); + fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS"); +} + +GST_END_TEST; + +GST_START_TEST (test_parsing) +{ + GstElement *pipeline; + + /* make sure we don't read beyond the end of the string */ + pipeline = gst_parse_launch_full ("filesrc location=x\\", NULL, 0, NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +parse_suite (void) +{ + Suite *s = suite_create ("Parse Launch syntax"); + TCase *tc_chain = tcase_create ("parselaunch"); + + /* time out after 20s, not the default 3 */ + tcase_set_timeout (tc_chain, 20); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_launch_lines); + tcase_add_test (tc_chain, test_launch_lines2); + tcase_add_test (tc_chain, expected_to_fail_pipes); + tcase_add_test (tc_chain, leaking_fail_pipes); + tcase_add_test (tc_chain, delayed_link); + tcase_add_test (tc_chain, test_flags); + tcase_add_test (tc_chain, test_missing_elements); + tcase_add_test (tc_chain, test_parsing); + return s; +} + +GST_CHECK_MAIN (parse); diff --git a/tests/check/pipelines/queue-error.c b/tests/check/pipelines/queue-error.c new file mode 100644 index 0000000..a8408bd --- /dev/null +++ b/tests/check/pipelines/queue-error.c @@ -0,0 +1,112 @@ +/* GStreamer unit test for queue + * + * Copyright (C) 2007 Tim-Philipp Müller + * Copyright (C) 2009 Mark Nauwelaerts + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include + +static GstPadProbeReturn +modify_caps (GstObject * pad, GstPadProbeInfo * info, gpointer data) +{ + GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); + GstElement *filter = GST_ELEMENT (data); + GstCaps *caps; + + fail_unless (event != NULL); + fail_unless (GST_IS_EVENT (event)); + + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) + return GST_PAD_PROBE_OK; + + /* trigger caps negotiation error */ + caps = gst_caps_new_empty_simple ("video/x-raw"); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + return GST_PAD_PROBE_OK; +} + +GST_START_TEST (test_queue) +{ + GstStateChangeReturn state_ret; + GstMessage *msg; + GstElement *pipeline, *filter, *queue; + GstBus *bus; + GstPad *pad; + guint probe; + gchar *pipe_desc = + g_strdup_printf ("fakesrc num-buffers=1 ! video/x-raw ! " + "queue min-threshold-buffers=2 name=queue ! " + "capsfilter name=nasty ! fakesink"); + + pipeline = gst_parse_launch (pipe_desc, NULL); + fail_unless (pipeline != NULL); + g_free (pipe_desc); + + filter = gst_bin_get_by_name (GST_BIN (pipeline), "nasty"); + fail_unless (filter != NULL); + + /* queue waits for all data and EOS to arrive */ + /* then probe forces downstream element to return negotiation error */ + queue = gst_bin_get_by_name (GST_BIN (pipeline), "queue"); + fail_unless (queue != NULL); + pad = gst_element_get_static_pad (queue, "sink"); + fail_unless (pad != NULL); + probe = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + (GstPadProbeCallback) modify_caps, filter, NULL); + + bus = gst_element_get_bus (pipeline); + + state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (state_ret != GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, 5 * GST_SECOND); + fail_unless (msg != NULL, "timeout waiting for error or eos message"); + + gst_message_unref (msg); + gst_object_unref (bus); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_pad_remove_probe (pad, probe); + gst_object_unref (queue); + gst_object_unref (pad); + gst_object_unref (filter); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +queue_suite (void) +{ + Suite *s = suite_create ("queue"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_queue); + + return s; +} + +GST_CHECK_MAIN (queue) diff --git a/tests/check/pipelines/seek.c b/tests/check/pipelines/seek.c new file mode 100644 index 0000000..28bb884 --- /dev/null +++ b/tests/check/pipelines/seek.c @@ -0,0 +1,570 @@ +/* GStreamer simple seek unit test + * Copyright (C) 2012 Collabora Ltd. + * Author: Tim-Philipp Müller + * Copyright (C) Julien Isorce + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#include + +/* ======================================================================== + * Dummy source, like a stripped down audio test source + * ======================================================================== */ + +#define SAMPLERATE 44100 +#define CHUNKS_PER_SEC 10 + +typedef struct +{ + GstBaseSrc parent; + GstClockTime next_time; +} TimedTestSrc; + +typedef struct +{ + GstBaseSrcClass parent_class; +} TimedTestSrcClass; + +static GstStaticPadTemplate timed_test_src_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("timed/audio")); + +static GType timed_test_src_get_type (void); + +G_DEFINE_TYPE (TimedTestSrc, timed_test_src, GST_TYPE_BASE_SRC); + +static gboolean timed_test_src_is_seekable (GstBaseSrc * basesrc); +static gboolean timed_test_src_do_seek (GstBaseSrc * basesrc, + GstSegment * segment); +static gboolean timed_test_src_start (GstBaseSrc * basesrc); +static gboolean timed_test_src_stop (GstBaseSrc * basesrc); +static GstFlowReturn timed_test_src_create (GstBaseSrc * basesrc, + guint64 offset, guint length, GstBuffer ** buffer); + +static void +timed_test_src_class_init (TimedTestSrcClass * klass) +{ + GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; + + gstbasesrc_class->is_seekable = timed_test_src_is_seekable; + gstbasesrc_class->do_seek = timed_test_src_do_seek; + gstbasesrc_class->start = timed_test_src_start; + gstbasesrc_class->stop = timed_test_src_stop; + gstbasesrc_class->create = timed_test_src_create; + + gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass), + &timed_test_src_src_template); +} + +static void +timed_test_src_init (TimedTestSrc * src) +{ + gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (src), FALSE); +} + +static gboolean +timed_test_src_start (GstBaseSrc * basesrc) +{ + TimedTestSrc *src = (TimedTestSrc *) basesrc; + + src->next_time = 0; + return TRUE; +} + +static gboolean +timed_test_src_stop (GstBaseSrc * basesrc) +{ + return TRUE; +} + +static gboolean +timed_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment) +{ + TimedTestSrc *src = (TimedTestSrc *) basesrc; + + src->next_time = segment->position; + return TRUE; +} + +static gboolean +timed_test_src_is_seekable (GstBaseSrc * basesrc) +{ + return TRUE; +} + +static GstFlowReturn +timed_test_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer ** buf) +{ + TimedTestSrc *src = (TimedTestSrc *) basesrc; + + *buf = gst_buffer_new_and_alloc (SAMPLERATE / CHUNKS_PER_SEC); + GST_BUFFER_TIMESTAMP (*buf) = src->next_time; + GST_BUFFER_DURATION (*buf) = GST_SECOND / CHUNKS_PER_SEC; + src->next_time += GST_BUFFER_DURATION (*buf); + return GST_FLOW_OK; +} + +/* ======================================================================== + * Dummy parser + * ======================================================================== */ + +typedef struct +{ + GstBaseParse parent; + gboolean caps_set; +} DummyParser; + +typedef struct +{ + GstBaseParseClass parent_class; +} DummyParserClass; + +static GType dummy_parser_get_type (void); + +G_DEFINE_TYPE (DummyParser, dummy_parser, GST_TYPE_BASE_PARSE); + +static gboolean +dummy_parser_start (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +dummy_parser_stop (GstBaseParse * parse) +{ + return TRUE; +} + +static GstFlowReturn +dummy_parser_handle_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, gint * skipsize) +{ + if (((DummyParser *) parse)->caps_set == FALSE) { + GstCaps *caps; + /* push caps */ + caps = gst_caps_new_empty_simple ("ANY"); + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + gst_caps_unref (caps); + ((DummyParser *) parse)->caps_set = TRUE; + } + + GST_BUFFER_DURATION (frame->buffer) = GST_SECOND / 10; + + return gst_base_parse_finish_frame (parse, frame, + gst_buffer_get_size (frame->buffer)); +} + +static gboolean +dummy_parser_set_sink_caps (GstBaseParse * parse, GstCaps * caps) +{ + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + return TRUE; +} + +static gboolean +dummy_parser_src_event (GstBaseParse * parse, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + default: + GST_INFO ("src event %s", GST_EVENT_TYPE_NAME (event)); + break; + } + return GST_BASE_PARSE_CLASS (dummy_parser_parent_class)->src_event (parse, + event); +} + +static void +dummy_parser_class_init (DummyParserClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass); + + static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + gst_element_class_add_static_pad_template (element_class, &sink_templ); + gst_element_class_add_static_pad_template (element_class, &src_templ); + + gst_element_class_set_metadata (element_class, + "DummyParser", "Parser/Video", "empty", "empty"); + + baseparse_class->start = GST_DEBUG_FUNCPTR (dummy_parser_start); + baseparse_class->stop = GST_DEBUG_FUNCPTR (dummy_parser_stop); + baseparse_class->handle_frame = GST_DEBUG_FUNCPTR (dummy_parser_handle_frame); + baseparse_class->set_sink_caps = + GST_DEBUG_FUNCPTR (dummy_parser_set_sink_caps); + baseparse_class->src_event = GST_DEBUG_FUNCPTR (dummy_parser_src_event); +} + +static void +dummy_parser_init (DummyParser * parser) +{ + parser->caps_set = FALSE; +} + +/* ======================================================================== */ + +GST_START_TEST (test_seek) +{ + GstMessage *msg; + GstElement *bin, *src1, *sink; + gboolean res; + GstPad *srcpad; + GstBus *bus; + + 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 = g_object_new (timed_test_src_get_type (), "name", "testsrc", NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, sink, NULL); + + res = gst_element_link (src1, sink); + fail_unless (res == TRUE, NULL); + + srcpad = gst_element_get_static_pad (src1, "src"); + gst_object_unref (srcpad); + + 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_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)); + 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); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos"); + gst_message_unref (msg); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + gst_bus_remove_signal_watch (bus); + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + + +/* This test checks that the pipeline does not wait for nothing after + * sending the non-flush seek event. */ +GST_START_TEST (test_loopback_1) +{ + GstMessage *msg; + GstElement *bin, *source, *parser, *sink; + gboolean res; + GstPad *sinkpad; + GstBus *bus; + guint seek_flags; + + GST_INFO + ("construct the test pipeline fakesrc ! testparse ! fakesink sync=1"); + + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + source = gst_element_factory_make ("fakesrc", "source"); + parser = g_object_new (dummy_parser_get_type (), "name", "testparse", NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add_many (GST_BIN (bin), source, parser, sink, NULL); + + res = gst_element_link (source, parser); + fail_unless (res == TRUE, NULL); + res = gst_element_link (parser, sink); + fail_unless (res == TRUE, NULL); + + GST_INFO ("configure elements"); + + g_object_set (G_OBJECT (source), + "format", GST_FORMAT_BYTES, + "can-activate-pull", TRUE, + "can-activate-push", FALSE, + "is-live", FALSE, + "sizemax", 65536, "sizetype", 2 /* FAKE_SRC_SIZETYPE_FIXED */ , + "num-buffers", 35, NULL); + + /* Sync true is required for this test. */ + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + GST_INFO ("set paused state"); + + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + GST_INFO ("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); + + GST_INFO ("paused state reached"); + + fail_unless (GST_BASE_SRC (source)->random_access); + + sinkpad = gst_element_get_static_pad (parser, "sink"); + fail_unless (GST_PAD_MODE (sinkpad) == GST_PAD_MODE_PULL); + gst_object_unref (sinkpad); + + GST_INFO ("flush seek"); + + seek_flags = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT; + + res = gst_element_seek (bin, 1.0, GST_FORMAT_TIME, seek_flags, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + fail_unless (res == TRUE, NULL); + + GST_INFO ("set playing state"); + + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_SEGMENT_DONE | GST_MESSAGE_ERROR); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "segment-done"); + gst_message_unref (msg); + + GST_INFO ("warm-up sequence done"); + + seek_flags &= ~GST_SEEK_FLAG_FLUSH; + fail_if (seek_flags & GST_SEEK_FLAG_FLUSH, NULL); + + GST_INFO ("non-flush seek"); + + res = + gst_element_seek (bin, 1.0, GST_FORMAT_TIME, seek_flags, + GST_SEEK_TYPE_SET, (GstClockTime) 0, GST_SEEK_TYPE_SET, + (GstClockTime) 3 * GST_SECOND); + fail_unless (res == TRUE, NULL); + + GST_INFO ("wait for segment done message"); + + msg = gst_bus_timed_pop_filtered (bus, (GstClockTime) 2 * GST_SECOND, + GST_MESSAGE_SEGMENT_DONE | GST_MESSAGE_ERROR); + /* Make sure the pipeline is not waiting for nothing because the base time is + * screwed up. */ + fail_unless (msg, "no message within the timed window"); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "segment-done"); + gst_message_unref (msg); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + gst_bus_remove_signal_watch (bus); + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +/* This test checks that the pipeline does not play the media instantly + * after sending the non-flush seek event. */ +GST_START_TEST (test_loopback_2) +{ + GstMessage *msg; + GstElement *bin, *source, *parser, *sink; + gboolean res; + GstPad *sinkpad; + GstBus *bus; + guint seek_flags; + gint64 position = GST_CLOCK_TIME_NONE; + gint64 playback_duration = GST_CLOCK_TIME_NONE; + gint64 start_absolute_time = GST_CLOCK_TIME_NONE; + + GST_INFO + ("construct the test pipeline fakesrc ! testparse ! fakesink sync=1"); + + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + source = gst_element_factory_make ("fakesrc", "source"); + parser = g_object_new (dummy_parser_get_type (), "name", "testparse", NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add_many (GST_BIN (bin), source, parser, sink, NULL); + + res = gst_element_link (source, parser); + fail_unless (res == TRUE, NULL); + res = gst_element_link (parser, sink); + fail_unless (res == TRUE, NULL); + + GST_INFO ("configure elements"); + + g_object_set (G_OBJECT (source), + "format", GST_FORMAT_BYTES, + "can-activate-pull", TRUE, + "can-activate-push", FALSE, + "is-live", FALSE, + "sizemax", 65536, "sizetype", 2 /* FAKE_SRC_SIZETYPE_FIXED */ , + NULL); + + /* Sync true is required for this test. */ + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + + GST_INFO ("set paused state"); + + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + GST_INFO ("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); + + GST_INFO ("paused state reached"); + + fail_unless (GST_BASE_SRC (source)->random_access); + + sinkpad = gst_element_get_static_pad (parser, "sink"); + fail_unless (GST_PAD_MODE (sinkpad) == GST_PAD_MODE_PULL); + gst_object_unref (sinkpad); + + GST_INFO ("flush seek"); + + seek_flags = + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT; + + res = gst_element_seek (bin, 1.0, GST_FORMAT_TIME, seek_flags, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + fail_unless (res == TRUE, NULL); + + GST_INFO ("set playing state"); + + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_SEGMENT_DONE | GST_MESSAGE_ERROR); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "segment-done"); + gst_message_unref (msg); + + GST_INFO ("warm-up sequence done"); + + seek_flags &= ~GST_SEEK_FLAG_FLUSH; + fail_if (seek_flags & GST_SEEK_FLAG_FLUSH, NULL); + + GST_INFO ("non-flush seek"); + + start_absolute_time = gst_clock_get_time (GST_ELEMENT_CLOCK (bin)); + + res = + gst_element_seek (bin, 1.0, GST_FORMAT_TIME, seek_flags, + GST_SEEK_TYPE_SET, (GstClockTime) 0, GST_SEEK_TYPE_SET, + (GstClockTime) 2 * GST_SECOND); + fail_unless (res == TRUE, NULL); + + GST_INFO ("wait for segment done message"); + + msg = gst_bus_timed_pop_filtered (bus, (GstClockTime) 2 * GST_SECOND, + GST_MESSAGE_SEGMENT_DONE | GST_MESSAGE_ERROR); + fail_unless (msg, "no message within the timed window"); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "segment-done"); + + gst_message_parse_segment_done (msg, NULL, &position); + gst_message_unref (msg); + + GST_INFO ("final position: %" G_GINT64_FORMAT, position); + + fail_unless (position == 2 * GST_SECOND); + + playback_duration = + GST_CLOCK_DIFF (start_absolute_time, + gst_clock_get_time (GST_ELEMENT_CLOCK (bin))); + + GST_INFO ("test duration: %" G_GINT64_FORMAT, playback_duration); + + fail_unless (playback_duration > GST_SECOND, + "playback duration should be near 2 seconds"); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + gst_bus_remove_signal_watch (bus); + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + +static Suite * +pipelines_seek_suite (void) +{ + Suite *s = suite_create ("pipelines-seek"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_seek); + tcase_add_test (tc_chain, test_loopback_1); + tcase_add_test (tc_chain, test_loopback_2); + + return s; +} + +GST_CHECK_MAIN (pipelines_seek); diff --git a/tests/check/pipelines/simple-launch-lines.c b/tests/check/pipelines/simple-launch-lines.c new file mode 100644 index 0000000..62385b2 --- /dev/null +++ b/tests/check/pipelines/simple-launch-lines.c @@ -0,0 +1,346 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include + + +static GstElement * +setup_pipeline (const gchar * pipe_descr) +{ + GstElement *pipeline; + + pipeline = gst_parse_launch (pipe_descr, NULL); + fail_unless (GST_IS_PIPELINE (pipeline)); + return pipeline; +} + +/* + * run_pipeline: + * @pipe: the pipeline to run + * @desc: the description for use in messages + * @message_types: is a mask of expected message_types + * @tmessage: is the expected terminal message + * + * the poll call will time out after half a second. + */ +static void +run_pipeline (GstElement * pipeline, const gchar * descr, + GstMessageType message_types, GstMessageType tmessage) +{ + GstBus *bus; + GstMessageType rmessage; + GstStateChangeReturn ret; + + fail_if (pipeline == NULL); + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + + GST_DEBUG ("running pipeline %s", descr); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + if (ret != GST_STATE_CHANGE_SUCCESS) { + GST_WARNING ("have failed state change %d", ret); + g_critical ("Couldn't set pipeline to PLAYING"); + goto done; + } + + while (1) { + GstMessage *message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2); + + if (message) { + rmessage = GST_MESSAGE_TYPE (message); + gst_message_unref (message); + } else { + rmessage = GST_MESSAGE_UNKNOWN; + } + + if (rmessage == tmessage) { + break; + } else if (rmessage == GST_MESSAGE_UNKNOWN) { + g_critical ("Unexpected timeout in gst_bus_poll, looking for %d: %s", + tmessage, descr); + break; + } else if (rmessage & message_types) { + continue; + } + g_critical + ("Unexpected message received of type %d, '%s', looking for %d: %s", + rmessage, gst_message_type_get_name (rmessage), tmessage, descr); + } + +done: + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (bus); +} + +GST_START_TEST (test_2_elements) +{ + const gchar *s; + + s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN); + + s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN); + + s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); + + s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); + + s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false"; + ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN)); +} + +GST_END_TEST; + +static void +check_state_change_return (GstElement * pipeline, GstState state, + GstStateChangeReturn immediate, GstStateChangeReturn final) +{ + GstStateChangeReturn ret; + + ret = gst_element_set_state (pipeline, state); + if (ret != immediate) + g_critical ("Unexpected set_state return ->%s: %d != %d", + gst_element_state_get_name (state), ret, immediate); + ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (ret != final) + g_critical ("Unexpected get_state return ->%s: %d != %d", + gst_element_state_get_name (state), ret, final); +} + + +GST_START_TEST (test_state_change_returns) +{ + const gchar *s; + GstElement *pipeline; + + s = "fakesrc can-activate-pull=false ! fakesink"; + pipeline = gst_parse_launch (s, NULL); + fail_unless (GST_IS_PIPELINE (pipeline)); + check_state_change_return (pipeline, GST_STATE_READY, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_PAUSED, GST_STATE_CHANGE_ASYNC, + GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_PLAYING, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + /* can't check PAUSED, it's not deterministic */ + check_state_change_return (pipeline, GST_STATE_READY, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS, + GST_STATE_CHANGE_SUCCESS); + gst_object_unref (pipeline); + + s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true"; + pipeline = gst_parse_launch (s, NULL); + fail_unless (GST_IS_PIPELINE (pipeline)); + check_state_change_return (pipeline, GST_STATE_READY, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_PAUSED, + GST_STATE_CHANGE_ASYNC, GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_PLAYING, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + /* can't check PAUSED, it's not deterministic */ + check_state_change_return (pipeline, GST_STATE_READY, + GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_SUCCESS); + check_state_change_return (pipeline, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS, + GST_STATE_CHANGE_SUCCESS); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +G_GNUC_UNUSED +GST_START_TEST (test_tee) +{ + const gchar *s; + + s = "fakesrc can-activate-push=true ! tee ! fakesink can-activate-push=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN); + + s = "fakesrc can-activate-push=true num-buffers=10 ! tee ! fakesink can-activate-push=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); + + s = "fakesrc can-activate-push=false can-activate-pull=true ! tee ! fakesink can-activate-pull=true"; + ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN)); + + s = "fakesrc can-activate-push=false can-activate-pull=true " + "! tee pull-mode=single ! fakesink can-activate-pull=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN); + + s = "fakesrc can-activate-push=false can-activate-pull=true num-buffers=10 " + "! tee pull-mode=single ! fakesink can-activate-pull=true"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); + + s = "fakesrc can-activate-push=false can-activate-pull=true " + "! tee name=t pull-mode=single ! fakesink can-activate-pull=true " + "t. ! queue ! fakesink can-activate-pull=true can-activate-push=false"; + ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN)); + + s = "fakesrc can-activate-push=false can-activate-pull=true " + "! tee name=t pull-mode=single ! fakesink can-activate-pull=true " + "t. ! queue ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN); + + s = "fakesrc can-activate-push=false can-activate-pull=true num-buffers=10 " + "! tee name=t pull-mode=single ! fakesink can-activate-pull=true " + "t. ! queue ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_START, GST_MESSAGE_EOS); +} + +GST_END_TEST; + +static void +got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused) +{ + gst_element_post_message + (sink, gst_message_new_application (NULL, + gst_structure_new_empty ("foo"))); +} + +GST_START_TEST (test_stop_from_app) +{ + GstElement *fakesrc, *fakesink, *pipeline; + GstBus *bus; + GstStateChangeReturn ret; + GstMessageType rmessage; + GstMessage *message; + + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + pipeline = gst_element_factory_make ("pipeline", NULL); + + fail_unless (fakesrc && fakesink && pipeline); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + fail_unless (gst_element_link (fakesrc, fakesink) != FALSE); + + g_object_set (fakesink, "signal-handoffs", (gboolean) TRUE, NULL); + g_signal_connect (fakesink, "handoff", G_CALLBACK (got_handoff), NULL); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + ret = gst_element_get_state (pipeline, NULL, NULL, 5 * GST_SECOND); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + g_error ("Failed to change state to PAUSED"); + break; + case GST_STATE_CHANGE_ASYNC: + g_error ("Failed to change state to PAUSED within 5 seconds"); + break; + default: + break; + } + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + + /* will time out after half a second */ + message = gst_bus_poll (bus, GST_MESSAGE_APPLICATION, GST_SECOND / 2); + if (message) { + rmessage = GST_MESSAGE_TYPE (message); + gst_message_unref (message); + } else { + rmessage = GST_MESSAGE_UNKNOWN; + } + fail_unless (rmessage == GST_MESSAGE_APPLICATION, + "polled message is not APPLICATION but %s", + gst_message_type_get_name (rmessage)); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (bus); +} + +GST_END_TEST; + +GST_START_TEST (test_typefind_force_sink_caps) +{ + const gchar *s; + + s = "fakesrc can-activate-push=true num-buffers=5 ! " + "typefind force-caps=foo/x-bar ! fakesink can-activate-push=true"; + ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_NEW_CLOCK | GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_STREAM_STATUS | GST_MESSAGE_ASYNC_DONE | + GST_MESSAGE_STREAM_START, GST_MESSAGE_UNKNOWN)); +} + +GST_END_TEST; + +static Suite * +simple_launch_lines_suite (void) +{ + Suite *s = suite_create ("Pipelines"); + TCase *tc_chain = tcase_create ("linear"); + + /* time out after 20s, not the default 3 */ + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_2_elements); + tcase_add_test (tc_chain, test_state_change_returns); + /* tcase_add_test (tc_chain, test_tee); FIXME */ + tcase_add_test (tc_chain, test_stop_from_app); + tcase_add_test (tc_chain, test_typefind_force_sink_caps); + + return s; +} + +GST_CHECK_MAIN (simple_launch_lines); diff --git a/tests/check/pipelines/stress.c b/tests/check/pipelines/stress.c new file mode 100644 index 0000000..7c2d06e --- /dev/null +++ b/tests/check/pipelines/stress.c @@ -0,0 +1,132 @@ +/* GStreamer + * Copyright (C) 2005 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include + +static int playing = 1; +static int quit = 0; + +static gboolean +change_state_timeout (gpointer data) +{ + GstElement *pipeline = (GstElement *) data; + + if (quit) + return FALSE; + + if (playing) { + playing = 0; + gst_element_set_state (pipeline, GST_STATE_NULL); + } else { + playing = 1; + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } + + return TRUE; +} + +static gboolean +quit_timeout (gpointer data) +{ + quit = 1; + return FALSE; +} + +GST_START_TEST (test_stress_preroll) +{ + GstElement *fakesrc, *fakesink; + GstElement *pipeline; + + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + pipeline = gst_element_factory_make ("pipeline", NULL); + + g_return_if_fail (fakesrc && fakesink && pipeline); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_timeout_add (500, &change_state_timeout, pipeline); + g_timeout_add_seconds (10, &quit_timeout, NULL); + + while (!quit) { + g_main_context_iteration (NULL, TRUE); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_stress) +{ + GstElement *fakesrc, *fakesink, *pipeline; + gint i; + + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + pipeline = gst_element_factory_make ("pipeline", NULL); + + g_return_if_fail (fakesrc && fakesink && pipeline); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + i = 100; + while (i--) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_NULL); + } + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +stress_suite (void) +{ + Suite *s = suite_create ("stress"); + TCase *tc_chain = tcase_create ("linear"); + + /* Completely disable timeout for this test */ + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_stress); + tcase_add_test (tc_chain, test_stress_preroll); + + return s; +} + +GST_CHECK_MAIN (stress); diff --git a/tests/check/tools/gstinspect.c b/tests/check/tools/gstinspect.c new file mode 100644 index 0000000..72e23a4 --- /dev/null +++ b/tests/check/tools/gstinspect.c @@ -0,0 +1,128 @@ +/* GStreamer gst-inspect unit test + * Copyright (C) 2012 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* FIXME 2.0: suppress warnings for deprecated API such as GValueArray + * with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#include +#include + +static int gst_inspect_main (int argc, char **argv); + +#define main gst_inspect_main +#include "../../tools/gst-inspect.c" +#undef main + +GST_START_TEST (test_exists) +{ +#define ARGV_LEN (G_N_ELEMENTS (argv) - 1) + + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", "foo", NULL }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", "bin", NULL }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 0); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=" VERSION, "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 0); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.0", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 0); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.0.0", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 0); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.2.0", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 0); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=2.0", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=2.0.0", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.44", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } + { + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.60.4", "bin", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } + { + /* check for plugin should fail like this */ + const gchar *argv[] = { "gst-inspect-1.0", "--exists", + "--atleast-version=1.0", "coreelements", NULL + }; + + fail_unless_equals_int (gst_inspect_main (ARGV_LEN, (gchar **) argv), 1); + } +} + +GST_END_TEST; + +static Suite * +gstabi_suite (void) +{ + Suite *s = suite_create ("gst-inspect"); + TCase *tc_chain = tcase_create ("gst-inspect"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_exists); + return s; +} + +GST_CHECK_MAIN (gstabi); diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am new file mode 100644 index 0000000..ea563c8 --- /dev/null +++ b/tests/examples/Makefile.am @@ -0,0 +1,24 @@ +# adapter test needs sys/times.h and unistd.h +if HAVE_SYS_TIMES_H_AND_UNISTD_H + ADAPTER_TEST_DIR = adapter +else + ADAPTER_TEST_DIR = +endif + +always_dirs = \ + controller \ + helloworld \ + memory \ + netclock \ + ptp \ + stepping \ + streamiddemux \ + streams + +SUBDIRS = \ + $(always_dirs) \ + $(ADAPTER_TEST_DIR) + +DIST_SUBDIRS = $(always_dirs) adapter + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/tests/examples/Makefile.in b/tests/examples/Makefile.in new file mode 100644 index 0000000..4a3416b --- /dev/null +++ b/tests/examples/Makefile.in @@ -0,0 +1,845 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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. +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = tests/examples +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/common/parallel-subdirs.mak +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@HAVE_SYS_TIMES_H_AND_UNISTD_H_FALSE@ADAPTER_TEST_DIR = + +# adapter test needs sys/times.h and unistd.h +@HAVE_SYS_TIMES_H_AND_UNISTD_H_TRUE@ADAPTER_TEST_DIR = adapter +always_dirs = \ + controller \ + helloworld \ + memory \ + netclock \ + ptp \ + stepping \ + streamiddemux \ + streams + +SUBDIRS = \ + $(always_dirs) \ + $(ADAPTER_TEST_DIR) + +DIST_SUBDIRS = $(always_dirs) adapter +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/parallel-subdirs.mak $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/common/parallel-subdirs.mak $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +.PHONY: independent-subdirs $(SUBDIRS) + +independent-subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ + +all-recursive: independent-subdirs + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/adapter/Makefile.am b/tests/examples/adapter/Makefile.am new file mode 100644 index 0000000..cbd2987 --- /dev/null +++ b/tests/examples/adapter/Makefile.am @@ -0,0 +1,4 @@ +noinst_PROGRAMS = adapter_test + +adapter_test_LDADD = $(GST_OBJ_LIBS) $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la +adapter_test_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/adapter/Makefile.in b/tests/examples/adapter/Makefile.in new file mode 100644 index 0000000..4a3f509 --- /dev/null +++ b/tests/examples/adapter/Makefile.in @@ -0,0 +1,801 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = adapter_test$(EXEEXT) +subdir = tests/examples/adapter +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +adapter_test_SOURCES = adapter_test.c +adapter_test_OBJECTS = adapter_test-adapter_test.$(OBJEXT) +am__DEPENDENCIES_1 = +adapter_test_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +adapter_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(adapter_test_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = adapter_test.c +DIST_SOURCES = adapter_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +adapter_test_LDADD = $(GST_OBJ_LIBS) $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la +adapter_test_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/adapter/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/adapter/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +adapter_test$(EXEEXT): $(adapter_test_OBJECTS) $(adapter_test_DEPENDENCIES) $(EXTRA_adapter_test_DEPENDENCIES) + @rm -f adapter_test$(EXEEXT) + $(AM_V_CCLD)$(adapter_test_LINK) $(adapter_test_OBJECTS) $(adapter_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adapter_test-adapter_test.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +adapter_test-adapter_test.o: adapter_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(adapter_test_CFLAGS) $(CFLAGS) -MT adapter_test-adapter_test.o -MD -MP -MF $(DEPDIR)/adapter_test-adapter_test.Tpo -c -o adapter_test-adapter_test.o `test -f 'adapter_test.c' || echo '$(srcdir)/'`adapter_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/adapter_test-adapter_test.Tpo $(DEPDIR)/adapter_test-adapter_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adapter_test.c' object='adapter_test-adapter_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(adapter_test_CFLAGS) $(CFLAGS) -c -o adapter_test-adapter_test.o `test -f 'adapter_test.c' || echo '$(srcdir)/'`adapter_test.c + +adapter_test-adapter_test.obj: adapter_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(adapter_test_CFLAGS) $(CFLAGS) -MT adapter_test-adapter_test.obj -MD -MP -MF $(DEPDIR)/adapter_test-adapter_test.Tpo -c -o adapter_test-adapter_test.obj `if test -f 'adapter_test.c'; then $(CYGPATH_W) 'adapter_test.c'; else $(CYGPATH_W) '$(srcdir)/adapter_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/adapter_test-adapter_test.Tpo $(DEPDIR)/adapter_test-adapter_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adapter_test.c' object='adapter_test-adapter_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(adapter_test_CFLAGS) $(CFLAGS) -c -o adapter_test-adapter_test.obj `if test -f 'adapter_test.c'; then $(CYGPATH_W) 'adapter_test.c'; else $(CYGPATH_W) '$(srcdir)/adapter_test.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/adapter/adapter_test.c b/tests/examples/adapter/adapter_test.c new file mode 100644 index 0000000..489a06f --- /dev/null +++ b/tests/examples/adapter/adapter_test.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include +#include + +struct TestParams +{ + gint tot_size; + gint read_size; + gint write_size; +}; + +/* This test pushes 'n' buffers of 'write size' into an adapter, then reads + * them out in 'read size' sized pieces, using take and then take_buffer, + * and prints the timings */ + +static struct TestParams param_sets[] = { +/* These values put ~256MB in 1MB chunks in an adapter, then reads them out + * in 250kb blocks */ + {256000000, 250000, 1000000}, +/* These values put ~256MB in 1000 byte chunks in an adapter, then reads them + * out in 200 byte blocks */ + {25600000, 200, 1000}, +/* These values put ~256MB in 200 chunks in an adapter, then reads them out + * in 1000 byte blocks */ + {25600000, 1000, 200} +}; + +static const gint n_tests = sizeof (param_sets) / sizeof (struct TestParams); + +static gint ticks_per_sec; + +static void +run_test_take (struct TestParams *params) +{ + /* Create an adapter and feed it data of fixed size, then retrieve it in + * a different size */ + GstAdapter *adapter = gst_adapter_new (); + guint8 *data; + GstBuffer *buf; + int i; + gint ntimes = params->tot_size / params->write_size; + + for (i = 0; i < ntimes; i++) { + buf = gst_buffer_new_and_alloc (params->write_size); + + gst_buffer_memset (buf, 0, 0, params->write_size); + + gst_adapter_push (adapter, buf); + } + + do { + data = gst_adapter_take (adapter, params->read_size); + if (data == NULL) + break; + g_free (data); + } while (TRUE); + + g_object_unref (adapter); +} + +static void +run_test_take_buffer (struct TestParams *params) +{ + /* Create an adapter and feed it data of fixed size, then retrieve it in + * a different size + */ + GstAdapter *adapter = gst_adapter_new (); + GstBuffer *buf; + int i; + gint ntimes = params->tot_size / params->write_size; + + for (i = 0; i < ntimes; i++) { + buf = gst_buffer_new_and_alloc (params->write_size); + + gst_buffer_memset (buf, 0, 0, params->write_size); + + gst_adapter_push (adapter, buf); + } + + do { + buf = gst_adapter_take_buffer (adapter, params->read_size); + if (buf == NULL) + break; + gst_buffer_unref (buf); + } while (TRUE); + + g_object_unref (adapter); +} + +static void +run_tests (struct TestParams *params) +{ + struct tms time_data; + gdouble start; + gdouble dur; + + g_print ("Running on %d bytes, writing %d bytes/buf, reading %d bytes/buf\n", + params->tot_size, params->write_size, params->read_size); + + start = 0.0; + run_test_take (params); + + times (&time_data); + dur = (gdouble) (time_data.tms_utime + time_data.tms_stime) / ticks_per_sec; + g_print ("Time for take test: %g secs\n", dur - start); + + start = dur; + run_test_take_buffer (params); + + times (&time_data); + dur = (gdouble) (time_data.tms_utime + time_data.tms_stime) / ticks_per_sec; + g_print ("Time for TakeBuffer test: %g secs\n", dur - start); + + g_print ("\n"); +} + +int +main (int argc, char **argv) +{ + gint i; + + ticks_per_sec = sysconf (_SC_CLK_TCK); + + gst_init (&argc, &argv); + + for (i = 0; i < n_tests; i++) + run_tests (param_sets + i); + + return 0; +} diff --git a/tests/examples/adapter/meson.build b/tests/examples/adapter/meson.build new file mode 100644 index 0000000..200c5c4 --- /dev/null +++ b/tests/examples/adapter/meson.build @@ -0,0 +1,7 @@ +if cdata.has('HAVE_SYS_TIMES_H') and cdata.has('HAVE_UNISTD_H') + executable('adapter_test', 'adapter_test.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_base_dep], + c_args: gst_c_args, + ) +endif diff --git a/tests/examples/controller/Makefile.am b/tests/examples/controller/Makefile.am new file mode 100644 index 0000000..146416c --- /dev/null +++ b/tests/examples/controller/Makefile.am @@ -0,0 +1,17 @@ +noinst_PROGRAMS = audio-example control-sources text-color-example absolute-example + +AM_CFLAGS = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs + +LDADD = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +if HAVE_GTK +noinst_PROGRAMS += controller-graph + +controller_graph_CFLAGS = $(GST_OBJ_CFLAGS) $(GTK_CFLAGS) +controller_graph_LDADD = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) $(GTK_LIBS) + +endif \ No newline at end of file diff --git a/tests/examples/controller/Makefile.in b/tests/examples/controller/Makefile.in new file mode 100644 index 0000000..ef3ff0c --- /dev/null +++ b/tests/examples/controller/Makefile.in @@ -0,0 +1,857 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = audio-example$(EXEEXT) control-sources$(EXEEXT) \ + text-color-example$(EXEEXT) absolute-example$(EXEEXT) \ + $(am__EXEEXT_1) +@HAVE_GTK_TRUE@am__append_1 = controller-graph +subdir = tests/examples/controller +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_GTK_TRUE@am__EXEEXT_1 = controller-graph$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +absolute_example_SOURCES = absolute-example.c +absolute_example_OBJECTS = absolute-example.$(OBJEXT) +absolute_example_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +absolute_example_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +audio_example_SOURCES = audio-example.c +audio_example_OBJECTS = audio-example.$(OBJEXT) +audio_example_LDADD = $(LDADD) +audio_example_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +control_sources_SOURCES = control-sources.c +control_sources_OBJECTS = control-sources.$(OBJEXT) +control_sources_LDADD = $(LDADD) +control_sources_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +controller_graph_SOURCES = controller-graph.c +controller_graph_OBJECTS = \ + controller_graph-controller-graph.$(OBJEXT) +@HAVE_GTK_TRUE@controller_graph_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ +@HAVE_GTK_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +controller_graph_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(controller_graph_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +text_color_example_SOURCES = text-color-example.c +text_color_example_OBJECTS = text-color-example.$(OBJEXT) +text_color_example_LDADD = $(LDADD) +text_color_example_DEPENDENCIES = $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = absolute-example.c audio-example.c control-sources.c \ + controller-graph.c text-color-example.c +DIST_SOURCES = absolute-example.c audio-example.c control-sources.c \ + controller-graph.c text-color-example.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs +LDADD = \ + $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +@HAVE_GTK_TRUE@controller_graph_CFLAGS = $(GST_OBJ_CFLAGS) $(GTK_CFLAGS) +@HAVE_GTK_TRUE@controller_graph_LDADD = \ +@HAVE_GTK_TRUE@ $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_API_VERSION@.la \ +@HAVE_GTK_TRUE@ $(GST_OBJ_LIBS) $(GTK_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/controller/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/controller/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +absolute-example$(EXEEXT): $(absolute_example_OBJECTS) $(absolute_example_DEPENDENCIES) $(EXTRA_absolute_example_DEPENDENCIES) + @rm -f absolute-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(absolute_example_OBJECTS) $(absolute_example_LDADD) $(LIBS) + +audio-example$(EXEEXT): $(audio_example_OBJECTS) $(audio_example_DEPENDENCIES) $(EXTRA_audio_example_DEPENDENCIES) + @rm -f audio-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(audio_example_OBJECTS) $(audio_example_LDADD) $(LIBS) + +control-sources$(EXEEXT): $(control_sources_OBJECTS) $(control_sources_DEPENDENCIES) $(EXTRA_control_sources_DEPENDENCIES) + @rm -f control-sources$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(control_sources_OBJECTS) $(control_sources_LDADD) $(LIBS) + +controller-graph$(EXEEXT): $(controller_graph_OBJECTS) $(controller_graph_DEPENDENCIES) $(EXTRA_controller_graph_DEPENDENCIES) + @rm -f controller-graph$(EXEEXT) + $(AM_V_CCLD)$(controller_graph_LINK) $(controller_graph_OBJECTS) $(controller_graph_LDADD) $(LIBS) + +text-color-example$(EXEEXT): $(text_color_example_OBJECTS) $(text_color_example_DEPENDENCIES) $(EXTRA_text_color_example_DEPENDENCIES) + @rm -f text-color-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(text_color_example_OBJECTS) $(text_color_example_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/absolute-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audio-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control-sources.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller_graph-controller-graph.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text-color-example.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +controller_graph-controller-graph.o: controller-graph.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_graph_CFLAGS) $(CFLAGS) -MT controller_graph-controller-graph.o -MD -MP -MF $(DEPDIR)/controller_graph-controller-graph.Tpo -c -o controller_graph-controller-graph.o `test -f 'controller-graph.c' || echo '$(srcdir)/'`controller-graph.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/controller_graph-controller-graph.Tpo $(DEPDIR)/controller_graph-controller-graph.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='controller-graph.c' object='controller_graph-controller-graph.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_graph_CFLAGS) $(CFLAGS) -c -o controller_graph-controller-graph.o `test -f 'controller-graph.c' || echo '$(srcdir)/'`controller-graph.c + +controller_graph-controller-graph.obj: controller-graph.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_graph_CFLAGS) $(CFLAGS) -MT controller_graph-controller-graph.obj -MD -MP -MF $(DEPDIR)/controller_graph-controller-graph.Tpo -c -o controller_graph-controller-graph.obj `if test -f 'controller-graph.c'; then $(CYGPATH_W) 'controller-graph.c'; else $(CYGPATH_W) '$(srcdir)/controller-graph.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/controller_graph-controller-graph.Tpo $(DEPDIR)/controller_graph-controller-graph.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='controller-graph.c' object='controller_graph-controller-graph.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(controller_graph_CFLAGS) $(CFLAGS) -c -o controller_graph-controller-graph.obj `if test -f 'controller-graph.c'; then $(CYGPATH_W) 'controller-graph.c'; else $(CYGPATH_W) '$(srcdir)/controller-graph.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/controller/absolute-example.c b/tests/examples/controller/absolute-example.c new file mode 100644 index 0000000..2bce7e7 --- /dev/null +++ b/tests/examples/controller/absolute-example.c @@ -0,0 +1,97 @@ +/* + * text-color-example.c + * + * Builds a pipeline with [videotestsrc ! textoverlay ! ximagesink] and + * moves text + * + * Needs gst-plugins-base installed. + */ + +#include +#include +#include +#include +#include + +gint +main (gint argc, gchar ** argv) +{ + gint res = 1; + GstElement *src, *text, *sink; + GstElement *bin; + GstControlSource *cs; + GstClock *clock; + GstClockID clock_id; + GstClockReturn wait_ret; + + gst_init (&argc, &argv); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + clock = gst_pipeline_get_clock (GST_PIPELINE (bin)); + src = gst_element_factory_make ("videotestsrc", NULL); + if (!src) { + GST_WARNING ("need videotestsrc from gst-plugins-base"); + goto Error; + } + g_object_set (src, "pattern", /* red */ 4, + NULL); + text = gst_element_factory_make ("textoverlay", NULL); + if (!text) { + GST_WARNING ("need textoverlay from gst-plugins-base"); + goto Error; + } + g_object_set (text, + "text", "GStreamer rocks!", + "font-desc", "Sans, 30", + "xpos", 0.0, "wrap-mode", -1, "halignment", /* position */ 4, + "valignment", /* position */ 3, + NULL); + sink = gst_element_factory_make ("ximagesink", NULL); + if (!sink) { + GST_WARNING ("need ximagesink from gst-plugins-base"); + goto Error; + } + + gst_bin_add_many (GST_BIN (bin), src, text, sink, NULL); + if (!gst_element_link_many (src, text, sink, NULL)) { + GST_WARNING ("can't link elements"); + goto Error; + } + + /* setup control sources */ + cs = gst_interpolation_control_source_new (); + gst_object_add_control_binding (GST_OBJECT_CAST (text), + gst_direct_control_binding_new_absolute (GST_OBJECT_CAST (text), "deltax", + cs)); + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + // At second 0 the text will be at 0px on the x-axis + gst_timed_value_control_source_set ((GstTimedValueControlSource *) cs, 0, 0); + // At second 5 the text will be at 1000px on the x-axis + gst_timed_value_control_source_set ((GstTimedValueControlSource *) cs, + GST_SECOND * 5, 1000); + + gst_object_unref (cs); + + /* run for 10 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (10 * GST_SECOND)); + + if (gst_element_set_state (bin, GST_STATE_PLAYING)) { + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_element_set_state (bin, GST_STATE_NULL); + } + + /* cleanup */ + gst_clock_id_unref (clock_id); + gst_object_unref (G_OBJECT (clock)); + gst_object_unref (G_OBJECT (bin)); + res = 0; +Error: + return (res); +} diff --git a/tests/examples/controller/audio-example.c b/tests/examples/controller/audio-example.c new file mode 100644 index 0000000..f57731f --- /dev/null +++ b/tests/examples/controller/audio-example.c @@ -0,0 +1,95 @@ +/* + * audio-example.c + * + * Builds a pipeline with [ audiotestsource ! autoaudiosink ] and sweeps + * frequency and volume. + * + * Needs gst-plugins-base + gst-plugins-good installed. + */ + +#include +#include +#include + +gint +main (gint argc, gchar ** argv) +{ + gint res = 1; + GstElement *src, *sink; + GstElement *bin; + GstControlSource *cs1, *cs2; + GstTimedValueControlSource *tvcs; + GstClock *clock; + GstClockID clock_id; + GstClockReturn wait_ret; + + gst_init (&argc, &argv); + + /* 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; + } + sink = gst_element_factory_make ("autoaudiosink", NULL); + if (!sink) { + GST_WARNING ("need autoaudiosink from gst-plugins-good"); + goto Error; + } + + gst_bin_add_many (GST_BIN (bin), src, sink, NULL); + if (!gst_element_link (src, sink)) { + GST_WARNING ("can't link elements"); + goto Error; + } + + /* setup control sources */ + cs1 = gst_interpolation_control_source_new (); + cs2 = gst_interpolation_control_source_new (); + + gst_object_add_control_binding (GST_OBJECT_CAST (src), + gst_direct_control_binding_new (GST_OBJECT_CAST (src), "volume", cs1)); + gst_object_add_control_binding (GST_OBJECT_CAST (src), + gst_direct_control_binding_new (GST_OBJECT_CAST (src), "freq", cs2)); + + /* set interpolation mode */ + + g_object_set (cs1, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + g_object_set (cs2, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + /* set control values */ + tvcs = (GstTimedValueControlSource *) cs1; + gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0); + gst_timed_value_control_source_set (tvcs, 5 * GST_SECOND, 1.0); + + gst_object_unref (cs1); + + tvcs = (GstTimedValueControlSource *) cs2; + gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 220.0 / 20000.0); + gst_timed_value_control_source_set (tvcs, 3 * GST_SECOND, 3520.0 / 20000.0); + gst_timed_value_control_source_set (tvcs, 6 * GST_SECOND, 440.0 / 20000.0); + + gst_object_unref (cs2); + + /* run for 7 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (7 * GST_SECOND)); + + if (gst_element_set_state (bin, GST_STATE_PLAYING)) { + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_element_set_state (bin, GST_STATE_NULL); + } + + /* cleanup */ + gst_clock_id_unref (clock_id); + gst_object_unref (clock); + gst_object_unref (bin); + res = 0; +Error: + return (res); +} diff --git a/tests/examples/controller/control-sources.c b/tests/examples/controller/control-sources.c new file mode 100644 index 0000000..5322933 --- /dev/null +++ b/tests/examples/controller/control-sources.c @@ -0,0 +1,450 @@ +/* + * control-sources.c + * + * Generates a datafile for various control sources. + * + * Needs gnuplot for plotting. + * plot "ctrl_i1.dat" using 1:2 with points title 'none', "" using 1:3 with points title 'linear', "" using 1:4 with points title 'cubic', "ctrl_i2.dat" using 1:2 with lines title 'none', "" using 1:3 with lines title 'linear', "" using 1:4 with lines title 'cubic' + * plot "ctrl_l1.dat" using 1:2 with points title 'sine', "" using 1:3 with points title 'square', "" using 1:4 with points title 'saw', "" using 1:5 with points title 'revsaw', "" using 1:6 with points title 'triangle', "ctrl_l2.dat" using 1:2 with lines title 'sine', "" using 1:3 with lines title 'square', "" using 1:4 with lines title 'saw', "" using 1:5 with lines title 'revsaw', "" using 1:6 with lines title 'triangle' + * plot "ctrl_cl1.dat" using 1:2 with points title 'sine', "ctrl_cl2.dat" using 1:2 with lines title 'sine' + */ + +#include +#include + +#include +#include +#include +#include + +/* local test element */ + +enum +{ + PROP_INT = 1, + PROP_FLOAT, + PROP_DOUBLE, + PROP_BOOLEAN, + PROP_COUNT +}; + +#define GST_TYPE_TEST_OBJ (gst_test_obj_get_type ()) +#define GST_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj)) +#define GST_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass)) +#define GST_IS_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ)) +#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ)) +#define GST_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass)) + +typedef struct _GstTestObj GstTestObj; +typedef struct _GstTestObjClass GstTestObjClass; + +struct _GstTestObj +{ + GstElement parent; + gint val_int; + gfloat val_float; + gdouble val_double; + gboolean val_boolean; +}; +struct _GstTestObjClass +{ + GstElementClass parent_class; +}; + +static GType gst_test_obj_get_type (void); + +static void +gst_test_obj_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + g_value_set_int (value, self->val_int); + break; + case PROP_FLOAT: + g_value_set_float (value, self->val_float); + break; + case PROP_DOUBLE: + g_value_set_double (value, self->val_double); + break; + case PROP_BOOLEAN: + g_value_set_boolean (value, self->val_boolean); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec) +{ + GstTestObj *self = GST_TEST_OBJ (object); + + switch (property_id) { + case PROP_INT: + self->val_int = g_value_get_int (value); + GST_DEBUG ("test value int=%d", self->val_int); + break; + case PROP_FLOAT: + self->val_float = g_value_get_float (value); + GST_DEBUG ("test value float=%f", self->val_float); + break; + case PROP_DOUBLE: + self->val_double = g_value_get_double (value); + GST_DEBUG ("test value double=%f", self->val_double); + break; + case PROP_BOOLEAN: + self->val_boolean = g_value_get_boolean (value); + GST_DEBUG ("test value boolean=%d", self->val_boolean); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gst_test_obj_class_init (GstTestObjClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_test_obj_set_property; + gobject_class->get_property = gst_test_obj_get_property; + + g_object_class_install_property (gobject_class, PROP_INT, + g_param_spec_int ("int", + "int prop", + "int number parameter", + 0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_FLOAT, + g_param_spec_float ("float", + "float prop", + "float number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_DOUBLE, + g_param_spec_double ("double", + "double prop", + "double number parameter", + 0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_BOOLEAN, + g_param_spec_boolean ("boolean", + "boolean prop", + "boolean parameter", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); +} + +static void +gst_test_obj_base_init (GstTestObjClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_metadata (element_class, + "test object for unit tests", + "Test", "Use in unit tests", "Stefan Sauer "); +} + +static GType +gst_test_obj_get_type (void) +{ + static volatile gsize TEST_OBJ_type = 0; + + if (g_once_init_enter (&TEST_OBJ_type)) { + GType type; + static const GTypeInfo info = { + (guint16) sizeof (GstTestObjClass), + (GBaseInitFunc) gst_test_obj_base_init, // base_init + NULL, // base_finalize + (GClassInitFunc) gst_test_obj_class_init, // class_init + NULL, // class_finalize + NULL, // class_data + (guint16) sizeof (GstTestObj), + 0, // n_preallocs + NULL, // instance_init + NULL // value_table + }; + type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0); + g_once_init_leave (&TEST_OBJ_type, type); + } + return TEST_OBJ_type; +} + +static void +test_interpolation (void) +{ + GstObject *e; + GstTimedValueControlSource *tvcs; + GstControlSource *cs; + gint t, i1, i2, i3; + GValue *v1, *v2, *v3; + gint n_values; + FILE *f; + + e = (GstObject *) gst_element_factory_make ("testobj", NULL); + + cs = gst_interpolation_control_source_new (); + tvcs = (GstTimedValueControlSource *) cs; + + gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int", + cs)); + + gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0); + gst_timed_value_control_source_set (tvcs, 10 * GST_SECOND, 1.0); + gst_timed_value_control_source_set (tvcs, 20 * GST_SECOND, 0.5); + gst_timed_value_control_source_set (tvcs, 30 * GST_SECOND, 0.2); + + /* test single values */ + if (!(f = fopen ("ctrl_i1.dat", "w"))) + exit (-1); + fprintf (f, "# Time None Linear Cubic\n"); + + for (t = 0; t < 40; t++) { + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i1 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i2 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i3 = GST_TEST_OBJ (e)->val_int; + + fprintf (f, "%4.1f %d %d %d\n", (gfloat) t, i1, i2, i3); + } + + fclose (f); + + /* test value arrays */ + if (!(f = fopen ("ctrl_i2.dat", "w"))) + exit (-1); + fprintf (f, "# Time None Linear Cubic\n"); + n_values = 40 * 10; + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL); + v1 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1); + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + v2 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2); + + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL); + v3 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3); + + for (t = 0; t < n_values; t++) { + i1 = g_value_get_int (&v1[t]); + i2 = g_value_get_int (&v2[t]); + i3 = g_value_get_int (&v3[t]); + fprintf (f, "%4.1f %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3); + g_value_unset (&v1[t]); + g_value_unset (&v2[t]); + g_value_unset (&v3[t]); + } + g_free (v1); + g_free (v2); + g_free (v3); + + fclose (f); + + gst_object_unref (cs); + gst_object_unref (e); +} + +static void +test_lfo (void) +{ + GstObject *e; + GstControlSource *cs; + gint t, i1, i2, i3, i4, i5; + GValue *v1, *v2, *v3, *v4, *v5; + gint n_values; + FILE *f; + + e = (GstObject *) gst_element_factory_make ("testobj", NULL); + + cs = gst_lfo_control_source_new (); + + gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int", + cs)); + + g_object_set (cs, + "frequency", (gdouble) 0.05, + "timeshift", (GstClockTime) 0, + "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL); + + /* test single values */ + if (!(f = fopen ("ctrl_l1.dat", "w"))) + exit (-1); + fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n"); + + for (t = 0; t < 40; t++) { + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i1 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i2 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i3 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i4 = GST_TEST_OBJ (e)->val_int; + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL); + gst_object_sync_values (e, t * GST_SECOND); + i5 = GST_TEST_OBJ (e)->val_int; + + fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t, i1, i2, i3, i4, i5); + } + + fclose (f); + + /* test value arrays */ + if (!(f = fopen ("ctrl_l2.dat", "w"))) + exit (-1); + fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n"); + n_values = 40 * 10; + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, NULL); + v1 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1); + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL); + v2 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2); + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, NULL); + v3 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3); + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL); + v4 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v4); + + g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL); + v5 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v5); + + for (t = 0; t < n_values; t++) { + i1 = g_value_get_int (&v1[t]); + i2 = g_value_get_int (&v2[t]); + i3 = g_value_get_int (&v3[t]); + i4 = g_value_get_int (&v4[t]); + i5 = g_value_get_int (&v5[t]); + fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3, i4, + i5); + g_value_unset (&v1[t]); + g_value_unset (&v2[t]); + g_value_unset (&v3[t]); + g_value_unset (&v4[t]); + g_value_unset (&v5[t]); + } + g_free (v1); + g_free (v2); + g_free (v3); + g_free (v4); + g_free (v5); + + fclose (f); + + gst_object_unref (cs); + gst_object_unref (e); +} + +static void +test_chained_lfo (void) +{ + GstObject *e; + GstControlSource *cs1, *cs2; + gint t, i1; + GValue *v1; + gint n_values; + FILE *f; + + e = (GstObject *) gst_element_factory_make ("testobj", NULL); + + cs1 = gst_lfo_control_source_new (); + + gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int", + cs1)); + + g_object_set (cs1, + "waveform", GST_LFO_WAVEFORM_SINE, + "frequency", (gdouble) 0.05, + "timeshift", (GstClockTime) 0, "offset", (gdouble) 0.5, NULL); + + cs2 = gst_lfo_control_source_new (); + + gst_object_add_control_binding ((GstObject *) cs1, + gst_direct_control_binding_new ((GstObject *) cs1, "amplitude", cs2)); + + g_object_set (cs2, + "waveform", GST_LFO_WAVEFORM_SINE, + "frequency", (gdouble) 0.05, + "timeshift", (GstClockTime) 0, + "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL); + + /* test single values */ + if (!(f = fopen ("ctrl_cl1.dat", "w"))) + exit (-1); + fprintf (f, "# Time Sine\n"); + + for (t = 0; t < 40; t++) { + gst_object_sync_values (e, t * GST_SECOND); + i1 = GST_TEST_OBJ (e)->val_int; + + fprintf (f, "%4.1f %d\n", (gfloat) t, i1); + } + + fclose (f); + + /* test value arrays */ + if (!(f = fopen ("ctrl_cl2.dat", "w"))) + exit (-1); + fprintf (f, "# Time Sine\n"); + n_values = 40 * 10; + + v1 = g_new0 (GValue, n_values); + gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1); + + for (t = 0; t < n_values; t++) { + i1 = g_value_get_int (&v1[t]); + fprintf (f, "%4.1f %d\n", (gfloat) t / 10.0, i1); + g_value_unset (&v1[t]); + } + g_free (v1); + + fclose (f); + + gst_object_unref (cs1); + gst_object_unref (cs2); + gst_object_unref (e); +} + +gint +main (gint argc, gchar ** argv) +{ + gst_init (&argc, &argv); + + gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ); + + test_interpolation (); + test_lfo (); + + test_chained_lfo (); + + return 0; +} diff --git a/tests/examples/controller/controller-graph.c b/tests/examples/controller/controller-graph.c new file mode 100644 index 0000000..ef90a27 --- /dev/null +++ b/tests/examples/controller/controller-graph.c @@ -0,0 +1,185 @@ +/* GStreamer + * Copyright (C) <2015> Stefan Sauer + * + * controller-graph: explore interpolation 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include +#include + +GtkWidget *graph; +GstControlSource *cs = NULL; +gdouble yval[] = { 0.0, 0.2, 0.8, 0.1, 0.1, 1.0 }; + +static gboolean +on_graph_draw (GtkWidget * widget, cairo_t * cr, gpointer user_data) +{ + GtkStyleContext *style = gtk_widget_get_style_context (widget); + GtkAllocation alloc; + gint x, y, w, h; + gdouble *data; + guint64 ts, ts_step; + gint i; + GstTimedValueControlSource *tvcs = (GstTimedValueControlSource *) cs; + + gtk_widget_get_allocation (widget, &alloc); + w = alloc.width; + h = alloc.height; + gtk_render_background (style, cr, 0, 0, w, h); + // add some border: + x = 5; + y = 5; + w -= (x + x); + h -= (y + y); + + // build graph + ts = G_GUINT64_CONSTANT (0); + ts_step = w / (G_N_ELEMENTS (yval) - 1); + gst_timed_value_control_source_unset_all (tvcs); + for (i = 0; i < G_N_ELEMENTS (yval); i++) { + gst_timed_value_control_source_set (tvcs, ts, yval[i]); + ts += ts_step; + } + data = g_new (gdouble, w); + gst_control_source_get_value_array (cs, 0, 1, w, data); + + // draw background + cairo_set_source_rgb (cr, 0.5, 0.5, 0.5); + cairo_rectangle (cr, x, y, w, h); + cairo_stroke_preserve (cr); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_fill (cr); + + + // plot graph + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_set_line_width (cr, 1.0); + cairo_move_to (cr, x, y + data[0] * h); + for (i = 1; i < w; i++) { + cairo_line_to (cr, x + i, y + CLAMP (data[i], 0.0, 1.0) * h); + } + cairo_stroke (cr); + + // plot control points + ts = G_GUINT64_CONSTANT (0); + for (i = 0; i < G_N_ELEMENTS (yval); i++) { + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_arc (cr, x + ts, y + yval[i] * h, 3.0, 0.0, 2 * M_PI); + cairo_stroke_preserve (cr); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_fill (cr); + ts += ts_step; + } + + g_free (data); + + return TRUE; +} + +static void +on_mode_changed (GtkComboBox * combo, gpointer user_data) +{ + g_object_set (cs, "mode", gtk_combo_box_get_active (combo), NULL); + gtk_widget_queue_draw (graph); +} + +static void +on_yval_changed (GtkSpinButton * spin, gpointer user_data) +{ + guint ix = GPOINTER_TO_UINT (user_data); + yval[ix] = gtk_spin_button_get_value (spin); + gtk_widget_queue_draw (graph); +} + +int +main (int argc, char **argv) +{ + GtkWidget *window; + GtkWidget *layout, *label, *combo, *box, *spin; + GEnumClass *enum_class; + GEnumValue *enum_value; + gint i; + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + cs = gst_interpolation_control_source_new (); + g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL); + gtk_window_set_default_size (GTK_WINDOW (window), 320, 240); + gtk_window_set_title (GTK_WINDOW (window), + "GstInterpolationControlSource demo"); + + layout = gtk_grid_new (); + + graph = gtk_drawing_area_new (); + gtk_widget_add_events (graph, GDK_POINTER_MOTION_MASK); + g_signal_connect (graph, "draw", G_CALLBACK (on_graph_draw), NULL); + g_object_set (graph, "hexpand", TRUE, "vexpand", TRUE, "margin-bottom", 3, + NULL); + gtk_grid_attach (GTK_GRID (layout), graph, 0, 0, 2, 1); + + // add controls to move the yvals + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + g_object_set (box, "homogeneous", TRUE, "margin-bottom", 3, NULL); + for (i = 0; i < G_N_ELEMENTS (yval); i++) { + spin = gtk_spin_button_new_with_range (0.0, 1.0, 0.05); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), yval[i]); + g_signal_connect (spin, "changed", G_CALLBACK (on_yval_changed), + GUINT_TO_POINTER (i)); + gtk_container_add (GTK_CONTAINER (box), spin); + } + gtk_grid_attach (GTK_GRID (layout), box, 0, 1, 2, 1); + + // combo for interpolation modes + label = gtk_label_new ("interpolation mode"); + gtk_grid_attach (GTK_GRID (layout), label, 0, 2, 1, 1); + + combo = gtk_combo_box_text_new (); + enum_class = g_type_class_ref (GST_TYPE_INTERPOLATION_MODE); + for (i = enum_class->minimum; i <= enum_class->maximum; i++) { + if ((enum_value = g_enum_get_value (enum_class, i))) { + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), + enum_value->value_nick); + } + } + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), + GST_INTERPOLATION_MODE_LINEAR); + g_signal_connect (combo, "changed", G_CALLBACK (on_mode_changed), NULL); + g_object_set (combo, "hexpand", TRUE, "margin-left", 3, NULL); + gtk_grid_attach (GTK_GRID (layout), combo, 1, 2, 1, 1); + + gtk_container_set_border_width (GTK_CONTAINER (window), 6); + gtk_container_add (GTK_CONTAINER (window), layout); + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} diff --git a/tests/examples/controller/meson.build b/tests/examples/controller/meson.build new file mode 100644 index 0000000..da4ee04 --- /dev/null +++ b/tests/examples/controller/meson.build @@ -0,0 +1,23 @@ +progs = [ + 'audio-example', + 'control-sources', + 'text-color-example', + 'absolute-example', +] + +foreach prog : progs + executable(prog, prog + '.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_controller_dep], + c_args: gst_c_args, + ) +endforeach + +gtk_dep = dependency('gtk+-3.0', required : false) +if gtk_dep.found() + executable('controller-graph', 'controller-graph.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_controller_dep, gtk_dep], + c_args: gst_c_args, + ) +endif diff --git a/tests/examples/controller/text-color-example.c b/tests/examples/controller/text-color-example.c new file mode 100644 index 0000000..c9e1119 --- /dev/null +++ b/tests/examples/controller/text-color-example.c @@ -0,0 +1,117 @@ +/* + * text-color-example.c + * + * Builds a pipeline with [videotestsrc ! textoverlay ! ximagesink] and + * modulates color, text and text pos. + * + * Needs gst-plugins-base installed. + */ + +#include +#include +#include +#include +#include + +gint +main (gint argc, gchar ** argv) +{ + gint res = 1; + GstElement *src, *text, *sink; + GstElement *bin; + GstControlSource *cs; + GstControlSource *cs_r, *cs_g, *cs_b; + GstClock *clock; + GstClockID clock_id; + GstClockReturn wait_ret; + + gst_init (&argc, &argv); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + clock = gst_pipeline_get_clock (GST_PIPELINE (bin)); + src = gst_element_factory_make ("videotestsrc", NULL); + if (!src) { + GST_WARNING ("need videotestsrc from gst-plugins-base"); + goto Error; + } + g_object_set (src, "pattern", /* checkers-8 */ 10, + NULL); + text = gst_element_factory_make ("textoverlay", NULL); + if (!text) { + GST_WARNING ("need textoverlay from gst-plugins-base"); + goto Error; + } + g_object_set (text, + "text", "GStreamer rocks!", + "font-desc", "Sans, 30", "halignment", /* position */ 4, + "valignment", /* position */ 3, + NULL); + sink = gst_element_factory_make ("ximagesink", NULL); + if (!sink) { + GST_WARNING ("need ximagesink from gst-plugins-base"); + goto Error; + } + + gst_bin_add_many (GST_BIN (bin), src, text, sink, NULL); + if (!gst_element_link_many (src, text, sink, NULL)) { + GST_WARNING ("can't link elements"); + goto Error; + } + + /* setup control sources */ + cs = gst_lfo_control_source_new (); + g_object_set (cs, + "frequency", (gdouble) 0.11, + "amplitude", (gdouble) 0.2, "offset", (gdouble) 0.5, NULL); + gst_object_add_control_binding (GST_OBJECT_CAST (text), + gst_direct_control_binding_new (GST_OBJECT_CAST (text), "xpos", cs)); + gst_object_unref (cs); + + cs = gst_lfo_control_source_new (); + g_object_set (cs, + "frequency", (gdouble) 0.04, + "amplitude", (gdouble) 0.4, "offset", (gdouble) 0.5, NULL); + gst_object_add_control_binding (GST_OBJECT_CAST (text), + gst_direct_control_binding_new (GST_OBJECT_CAST (text), "ypos", cs)); + gst_object_unref (cs); + + cs_r = gst_lfo_control_source_new (); + g_object_set (cs_r, + "frequency", (gdouble) 0.19, + "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL); + cs_g = gst_lfo_control_source_new (); + g_object_set (cs_g, + "frequency", (gdouble) 0.27, + "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL); + cs_b = gst_lfo_control_source_new (); + g_object_set (cs_b, + "frequency", (gdouble) 0.13, + "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL); + gst_object_add_control_binding (GST_OBJECT_CAST (text), + gst_argb_control_binding_new (GST_OBJECT_CAST (text), "color", NULL, + cs_r, cs_g, cs_b)); + gst_object_unref (cs_r); + gst_object_unref (cs_g); + gst_object_unref (cs_b); + + /* run for 10 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (30 * GST_SECOND)); + + if (gst_element_set_state (bin, GST_STATE_PLAYING)) { + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_element_set_state (bin, GST_STATE_NULL); + } + + /* cleanup */ + gst_clock_id_unref (clock_id); + gst_object_unref (G_OBJECT (clock)); + gst_object_unref (G_OBJECT (bin)); + res = 0; +Error: + return (res); +} diff --git a/tests/examples/helloworld/Makefile.am b/tests/examples/helloworld/Makefile.am new file mode 100644 index 0000000..a7d1bd9 --- /dev/null +++ b/tests/examples/helloworld/Makefile.am @@ -0,0 +1,4 @@ +noinst_PROGRAMS = helloworld + +helloworld_LDADD = $(GST_OBJ_LIBS) +helloworld_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/helloworld/Makefile.in b/tests/examples/helloworld/Makefile.in new file mode 100644 index 0000000..5d8364a --- /dev/null +++ b/tests/examples/helloworld/Makefile.in @@ -0,0 +1,800 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = helloworld$(EXEEXT) +subdir = tests/examples/helloworld +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +helloworld_SOURCES = helloworld.c +helloworld_OBJECTS = helloworld-helloworld.$(OBJEXT) +am__DEPENDENCIES_1 = +helloworld_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +helloworld_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(helloworld_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = helloworld.c +DIST_SOURCES = helloworld.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +helloworld_LDADD = $(GST_OBJ_LIBS) +helloworld_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/helloworld/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/helloworld/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +helloworld$(EXEEXT): $(helloworld_OBJECTS) $(helloworld_DEPENDENCIES) $(EXTRA_helloworld_DEPENDENCIES) + @rm -f helloworld$(EXEEXT) + $(AM_V_CCLD)$(helloworld_LINK) $(helloworld_OBJECTS) $(helloworld_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helloworld-helloworld.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +helloworld-helloworld.o: helloworld.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(helloworld_CFLAGS) $(CFLAGS) -MT helloworld-helloworld.o -MD -MP -MF $(DEPDIR)/helloworld-helloworld.Tpo -c -o helloworld-helloworld.o `test -f 'helloworld.c' || echo '$(srcdir)/'`helloworld.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/helloworld-helloworld.Tpo $(DEPDIR)/helloworld-helloworld.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='helloworld.c' object='helloworld-helloworld.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(helloworld_CFLAGS) $(CFLAGS) -c -o helloworld-helloworld.o `test -f 'helloworld.c' || echo '$(srcdir)/'`helloworld.c + +helloworld-helloworld.obj: helloworld.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(helloworld_CFLAGS) $(CFLAGS) -MT helloworld-helloworld.obj -MD -MP -MF $(DEPDIR)/helloworld-helloworld.Tpo -c -o helloworld-helloworld.obj `if test -f 'helloworld.c'; then $(CYGPATH_W) 'helloworld.c'; else $(CYGPATH_W) '$(srcdir)/helloworld.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/helloworld-helloworld.Tpo $(DEPDIR)/helloworld-helloworld.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='helloworld.c' object='helloworld-helloworld.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(helloworld_CFLAGS) $(CFLAGS) -c -o helloworld-helloworld.obj `if test -f 'helloworld.c'; then $(CYGPATH_W) 'helloworld.c'; else $(CYGPATH_W) '$(srcdir)/helloworld.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/helloworld/helloworld.c b/tests/examples/helloworld/helloworld.c new file mode 100644 index 0000000..2d8ae3f --- /dev/null +++ b/tests/examples/helloworld/helloworld.c @@ -0,0 +1,83 @@ +#include + +static gboolean +bus_call (GstBus * bus, GstMessage * msg, gpointer data) +{ + GMainLoop *loop = (GMainLoop *) data; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS:{ + g_print ("End-of-stream\n"); + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_ERROR:{ + gchar *debug; + GError *err; + + gst_message_parse_error (msg, &err, &debug); + g_printerr ("Debugging info: %s\n", (debug) ? debug : "none"); + g_free (debug); + + g_print ("Error: %s\n", err->message); + g_error_free (err); + + g_main_loop_quit (loop); + + break; + } + default: + break; + } + return TRUE; +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *playbin; + GMainLoop *loop; + GstBus *bus; + guint bus_watch_id; + gchar *uri; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return 1; + } + + playbin = gst_element_factory_make ("playbin", NULL); + if (!playbin) { + g_print ("'playbin' gstreamer plugin missing\n"); + return 1; + } + + /* take the commandline argument and ensure that it is a uri */ + if (gst_uri_is_valid (argv[1])) + uri = g_strdup (argv[1]); + else + uri = gst_filename_to_uri (argv[1], NULL); + g_object_set (playbin, "uri", uri, NULL); + g_free (uri); + + /* create and event loop and feed gstreamer bus mesages to it */ + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (playbin); + bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); + g_object_unref (bus); + + /* start play back and listed to events */ + gst_element_set_state (playbin, GST_STATE_PLAYING); + g_main_loop_run (loop); + + /* cleanup */ + gst_element_set_state (playbin, GST_STATE_NULL); + g_object_unref (playbin); + g_source_remove (bus_watch_id); + g_main_loop_unref (loop); + + return 0; +} diff --git a/tests/examples/helloworld/meson.build b/tests/examples/helloworld/meson.build new file mode 100644 index 0000000..5eea10b --- /dev/null +++ b/tests/examples/helloworld/meson.build @@ -0,0 +1,5 @@ +executable('helloworld', 'helloworld.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/memory/Makefile.am b/tests/examples/memory/Makefile.am new file mode 100644 index 0000000..b0399c0 --- /dev/null +++ b/tests/examples/memory/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS = memory_test + +memory_test_SOURCES = memory_test.c my-memory.c my-memory.h my-vidmem.c my-vidmem.h +memory_test_LDADD = $(GST_OBJ_LIBS) +memory_test_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/memory/Makefile.in b/tests/examples/memory/Makefile.in new file mode 100644 index 0000000..9546545 --- /dev/null +++ b/tests/examples/memory/Makefile.in @@ -0,0 +1,833 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = memory_test$(EXEEXT) +subdir = tests/examples/memory +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_memory_test_OBJECTS = memory_test-memory_test.$(OBJEXT) \ + memory_test-my-memory.$(OBJEXT) \ + memory_test-my-vidmem.$(OBJEXT) +memory_test_OBJECTS = $(am_memory_test_OBJECTS) +am__DEPENDENCIES_1 = +memory_test_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +memory_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(memory_test_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(memory_test_SOURCES) +DIST_SOURCES = $(memory_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +memory_test_SOURCES = memory_test.c my-memory.c my-memory.h my-vidmem.c my-vidmem.h +memory_test_LDADD = $(GST_OBJ_LIBS) +memory_test_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/memory/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/memory/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +memory_test$(EXEEXT): $(memory_test_OBJECTS) $(memory_test_DEPENDENCIES) $(EXTRA_memory_test_DEPENDENCIES) + @rm -f memory_test$(EXEEXT) + $(AM_V_CCLD)$(memory_test_LINK) $(memory_test_OBJECTS) $(memory_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory_test-memory_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory_test-my-memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory_test-my-vidmem.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +memory_test-memory_test.o: memory_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-memory_test.o -MD -MP -MF $(DEPDIR)/memory_test-memory_test.Tpo -c -o memory_test-memory_test.o `test -f 'memory_test.c' || echo '$(srcdir)/'`memory_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-memory_test.Tpo $(DEPDIR)/memory_test-memory_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='memory_test.c' object='memory_test-memory_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-memory_test.o `test -f 'memory_test.c' || echo '$(srcdir)/'`memory_test.c + +memory_test-memory_test.obj: memory_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-memory_test.obj -MD -MP -MF $(DEPDIR)/memory_test-memory_test.Tpo -c -o memory_test-memory_test.obj `if test -f 'memory_test.c'; then $(CYGPATH_W) 'memory_test.c'; else $(CYGPATH_W) '$(srcdir)/memory_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-memory_test.Tpo $(DEPDIR)/memory_test-memory_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='memory_test.c' object='memory_test-memory_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-memory_test.obj `if test -f 'memory_test.c'; then $(CYGPATH_W) 'memory_test.c'; else $(CYGPATH_W) '$(srcdir)/memory_test.c'; fi` + +memory_test-my-memory.o: my-memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-my-memory.o -MD -MP -MF $(DEPDIR)/memory_test-my-memory.Tpo -c -o memory_test-my-memory.o `test -f 'my-memory.c' || echo '$(srcdir)/'`my-memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-my-memory.Tpo $(DEPDIR)/memory_test-my-memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='my-memory.c' object='memory_test-my-memory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-my-memory.o `test -f 'my-memory.c' || echo '$(srcdir)/'`my-memory.c + +memory_test-my-memory.obj: my-memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-my-memory.obj -MD -MP -MF $(DEPDIR)/memory_test-my-memory.Tpo -c -o memory_test-my-memory.obj `if test -f 'my-memory.c'; then $(CYGPATH_W) 'my-memory.c'; else $(CYGPATH_W) '$(srcdir)/my-memory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-my-memory.Tpo $(DEPDIR)/memory_test-my-memory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='my-memory.c' object='memory_test-my-memory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-my-memory.obj `if test -f 'my-memory.c'; then $(CYGPATH_W) 'my-memory.c'; else $(CYGPATH_W) '$(srcdir)/my-memory.c'; fi` + +memory_test-my-vidmem.o: my-vidmem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-my-vidmem.o -MD -MP -MF $(DEPDIR)/memory_test-my-vidmem.Tpo -c -o memory_test-my-vidmem.o `test -f 'my-vidmem.c' || echo '$(srcdir)/'`my-vidmem.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-my-vidmem.Tpo $(DEPDIR)/memory_test-my-vidmem.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='my-vidmem.c' object='memory_test-my-vidmem.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-my-vidmem.o `test -f 'my-vidmem.c' || echo '$(srcdir)/'`my-vidmem.c + +memory_test-my-vidmem.obj: my-vidmem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -MT memory_test-my-vidmem.obj -MD -MP -MF $(DEPDIR)/memory_test-my-vidmem.Tpo -c -o memory_test-my-vidmem.obj `if test -f 'my-vidmem.c'; then $(CYGPATH_W) 'my-vidmem.c'; else $(CYGPATH_W) '$(srcdir)/my-vidmem.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/memory_test-my-vidmem.Tpo $(DEPDIR)/memory_test-my-vidmem.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='my-vidmem.c' object='memory_test-my-vidmem.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_test_CFLAGS) $(CFLAGS) -c -o memory_test-my-vidmem.obj `if test -f 'my-vidmem.c'; then $(CYGPATH_W) 'my-vidmem.c'; else $(CYGPATH_W) '$(srcdir)/my-vidmem.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/memory/memory_test.c b/tests/examples/memory/memory_test.c new file mode 100644 index 0000000..96d9afb --- /dev/null +++ b/tests/examples/memory/memory_test.c @@ -0,0 +1,54 @@ +#include + +#include "my-memory.h" +#include "my-vidmem.h" + +int +main (int argc, char **argv) +{ + GstAllocator *alloc; + GstMemory *mem; + GstAllocationParams params; + GstMapInfo info; + guint f, w, h; + + gst_init (&argc, &argv); + + /* memory using the default API */ + my_memory_init (); + + alloc = gst_allocator_find ("MyMemory"); + + gst_allocation_params_init (¶ms); + mem = gst_allocator_alloc (alloc, 1024, ¶ms); + + gst_memory_map (mem, &info, GST_MAP_READ); + gst_memory_unmap (mem, &info); + + gst_memory_unref (mem); + gst_object_unref (alloc); + + /* allocator with custom alloc API */ + my_vidmem_init (); + + /* we can get the allocator but we can only make objects from it when we know + * the API */ + alloc = gst_allocator_find ("MyVidmem"); + + /* use custom api to alloc */ + mem = my_vidmem_alloc (0, 640, 480); + g_assert (my_is_vidmem (mem)); + + my_vidmem_get_format (mem, &f, &w, &h); + g_assert (f == 0); + g_assert (w == 640); + g_assert (h == 480); + + gst_memory_map (mem, &info, GST_MAP_READ); + gst_memory_unmap (mem, &info); + + gst_memory_unref (mem); + gst_object_unref (alloc); + + return 0; +} diff --git a/tests/examples/memory/meson.build b/tests/examples/memory/meson.build new file mode 100644 index 0000000..edce02a --- /dev/null +++ b/tests/examples/memory/meson.build @@ -0,0 +1,5 @@ +executable('memory_test', 'memory_test.c', 'my-memory.c', 'my-vidmem.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/memory/my-memory.c b/tests/examples/memory/my-memory.c new file mode 100644 index 0000000..2c1b7cb --- /dev/null +++ b/tests/examples/memory/my-memory.c @@ -0,0 +1,159 @@ +/* GStreamer + * Copyright (C) 2012 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "my-memory.h" + +typedef struct +{ + GstMemory mem; + + gpointer data; + +} MyMemory; + + +static GstMemory * +_my_alloc (GstAllocator * allocator, gsize size, GstAllocationParams * params) +{ + MyMemory *mem; + gsize maxsize = size + params->prefix + params->padding; + + GST_DEBUG ("alloc from allocator %p", allocator); + + mem = g_slice_new (MyMemory); + + gst_memory_init (GST_MEMORY_CAST (mem), params->flags, allocator, NULL, + maxsize, params->align, params->prefix, size); + + mem->data = NULL; + + return (GstMemory *) mem; +} + +static void +_my_free (GstAllocator * allocator, GstMemory * mem) +{ + MyMemory *mmem = (MyMemory *) mem; + + g_free (mmem->data); + g_slice_free (MyMemory, mmem); + GST_DEBUG ("%p: freed", mmem); +} + +static gpointer +_my_mem_map (MyMemory * mem, gsize maxsize, GstMapFlags flags) +{ + gpointer res; + + while (TRUE) { + if ((res = g_atomic_pointer_get (&mem->data)) != NULL) + break; + + res = g_malloc (maxsize); + + if (g_atomic_pointer_compare_and_exchange (&mem->data, NULL, res)) + break; + + g_free (res); + } + + GST_DEBUG ("%p: mapped %p", mem, res); + + return res; +} + +static gboolean +_my_mem_unmap (MyMemory * mem) +{ + GST_DEBUG ("%p: unmapped", mem); + return TRUE; +} + +static MyMemory * +_my_mem_share (MyMemory * mem, gssize offset, gsize size) +{ + MyMemory *sub; + GstMemory *parent; + + GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset, + size); + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + if (size == -1) + size = mem->mem.size - offset; + + sub = g_slice_new (MyMemory); + /* the shared memory is always readonly */ + gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | + GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent, + mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size); + + /* install pointer */ + sub->data = _my_mem_map (mem, mem->mem.maxsize, GST_MAP_READ); + + return sub; +} + +typedef struct +{ + GstAllocator parent; +} MyMemoryAllocator; + +typedef struct +{ + GstAllocatorClass parent_class; +} MyMemoryAllocatorClass; + +GType my_memory_allocator_get_type (void); +G_DEFINE_TYPE (MyMemoryAllocator, my_memory_allocator, GST_TYPE_ALLOCATOR); + +static void +my_memory_allocator_class_init (MyMemoryAllocatorClass * klass) +{ + GstAllocatorClass *allocator_class; + + allocator_class = (GstAllocatorClass *) klass; + + allocator_class->alloc = _my_alloc; + allocator_class->free = _my_free; +} + +static void +my_memory_allocator_init (MyMemoryAllocator * allocator) +{ + GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + + alloc->mem_type = "MyMemory"; + alloc->mem_map = (GstMemoryMapFunction) _my_mem_map; + alloc->mem_unmap = (GstMemoryUnmapFunction) _my_mem_unmap; + alloc->mem_share = (GstMemoryShareFunction) _my_mem_share; +} + +void +my_memory_init (void) +{ + GstAllocator *allocator; + + allocator = g_object_new (my_memory_allocator_get_type (), NULL); + + gst_allocator_register ("MyMemory", allocator); +} diff --git a/tests/examples/memory/my-memory.h b/tests/examples/memory/my-memory.h new file mode 100644 index 0000000..3f43e1d --- /dev/null +++ b/tests/examples/memory/my-memory.h @@ -0,0 +1,26 @@ +/* GStreamer + * Copyright (C) 2012 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + + +/* example of an allocator that delays allocation of the memory + * until the memory is mapped */ +void my_memory_init (void); + diff --git a/tests/examples/memory/my-vidmem.c b/tests/examples/memory/my-vidmem.c new file mode 100644 index 0000000..1303a67 --- /dev/null +++ b/tests/examples/memory/my-vidmem.c @@ -0,0 +1,192 @@ +/* GStreamer + * Copyright (C) 2012 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "my-vidmem.h" + +static GstAllocator *_my_allocator; + +typedef struct +{ + GstMemory mem; + + guint format; + guint width; + guint height; + gpointer data; + +} MyVidmem; + + +static GstMemory * +_my_alloc (GstAllocator * allocator, gsize size, GstAllocationParams * params) +{ + g_warning ("Use my_vidmem_alloc() to allocate from this allocator"); + + return NULL; +} + +static void +_my_free (GstAllocator * allocator, GstMemory * mem) +{ + MyVidmem *vmem = (MyVidmem *) mem; + + g_free (vmem->data); + g_slice_free (MyVidmem, vmem); + GST_DEBUG ("%p: freed", vmem); +} + +static gpointer +_my_vidmem_map (MyVidmem * mem, gsize maxsize, GstMapFlags flags) +{ + gpointer res; + + while (TRUE) { + if ((res = g_atomic_pointer_get (&mem->data)) != NULL) + break; + + res = g_malloc (maxsize); + + if (g_atomic_pointer_compare_and_exchange (&mem->data, NULL, res)) + break; + + g_free (res); + } + + GST_DEBUG ("%p: mapped %p", mem, res); + + return res; +} + +static gboolean +_my_vidmem_unmap (MyVidmem * mem) +{ + GST_DEBUG ("%p: unmapped", mem); + return TRUE; +} + +static MyVidmem * +_my_vidmem_share (MyVidmem * mem, gssize offset, gsize size) +{ + MyVidmem *sub; + GstMemory *parent; + + GST_DEBUG ("%p: share %" G_GSSIZE_FORMAT " %" G_GSIZE_FORMAT, mem, offset, + size); + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + if (size == -1) + size = mem->mem.size - offset; + + sub = g_slice_new (MyVidmem); + /* the shared memory is always readonly */ + gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | + GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->mem.allocator, parent, + mem->mem.maxsize, mem->mem.align, mem->mem.offset + offset, size); + + /* install pointer */ + sub->data = _my_vidmem_map (mem, mem->mem.maxsize, GST_MAP_READ); + + return sub; +} + +typedef struct +{ + GstAllocator parent; +} MyVidmemAllocator; + +typedef struct +{ + GstAllocatorClass parent_class; +} MyVidmemAllocatorClass; + +GType my_vidmem_allocator_get_type (void); +G_DEFINE_TYPE (MyVidmemAllocator, my_vidmem_allocator, GST_TYPE_ALLOCATOR); + +static void +my_vidmem_allocator_class_init (MyVidmemAllocatorClass * klass) +{ + GstAllocatorClass *allocator_class; + + allocator_class = (GstAllocatorClass *) klass; + + allocator_class->alloc = _my_alloc; + allocator_class->free = _my_free; +} + +static void +my_vidmem_allocator_init (MyVidmemAllocator * allocator) +{ + GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); + + alloc->mem_type = "MyVidmem"; + alloc->mem_map = (GstMemoryMapFunction) _my_vidmem_map; + alloc->mem_unmap = (GstMemoryUnmapFunction) _my_vidmem_unmap; + alloc->mem_share = (GstMemoryShareFunction) _my_vidmem_share; +} + +void +my_vidmem_init (void) +{ + _my_allocator = g_object_new (my_vidmem_allocator_get_type (), NULL); + + gst_allocator_register ("MyVidmem", gst_object_ref (_my_allocator)); +} + +GstMemory * +my_vidmem_alloc (guint format, guint width, guint height) +{ + MyVidmem *mem; + gsize maxsize; + + GST_DEBUG ("alloc frame format %u %ux%u", format, width, height); + + maxsize = (GST_ROUND_UP_4 (width) * height); + + mem = g_slice_new (MyVidmem); + + gst_memory_init (GST_MEMORY_CAST (mem), 0, _my_allocator, NULL, + maxsize, 31, 0, maxsize); + + mem->format = format; + mem->width = width; + mem->height = height; + mem->data = NULL; + + return (GstMemory *) mem; +} + +gboolean +my_is_vidmem (GstMemory * mem) +{ + return mem->allocator == _my_allocator; +} + +void +my_vidmem_get_format (GstMemory * mem, guint * format, guint * width, + guint * height) +{ + MyVidmem *vmem = (MyVidmem *) mem; + + *format = vmem->format; + *width = vmem->width; + *height = vmem->height; +} diff --git a/tests/examples/memory/my-vidmem.h b/tests/examples/memory/my-vidmem.h new file mode 100644 index 0000000..e11fa5c --- /dev/null +++ b/tests/examples/memory/my-vidmem.h @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) 2012 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +/* example of an allocator that needs a custom alloc function */ +void my_vidmem_init (void); + +GstMemory * my_vidmem_alloc (guint format, guint width, guint height); + +gboolean my_is_vidmem (GstMemory *mem); + +void my_vidmem_get_format (GstMemory *mem, guint *format, + guint *width, guint *height); + diff --git a/tests/examples/meson.build b/tests/examples/meson.build new file mode 100644 index 0000000..d8b795c --- /dev/null +++ b/tests/examples/meson.build @@ -0,0 +1,10 @@ +subdir('adapter') +subdir('controller') +subdir('helloworld') +#subdir('manual') # FIXME +subdir('memory') +subdir('netclock') +subdir('ptp') +subdir('stepping') +subdir('streamiddemux') +subdir('streams') diff --git a/tests/examples/netclock/Makefile.am b/tests/examples/netclock/Makefile.am new file mode 100644 index 0000000..9506997 --- /dev/null +++ b/tests/examples/netclock/Makefile.am @@ -0,0 +1,11 @@ +noinst_PROGRAMS = netclock-server netclock-client + +netclock_server_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) +netclock_server_CFLAGS = $(GST_OBJ_CFLAGS) + +netclock_client_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) +netclock_client_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/netclock/Makefile.in b/tests/examples/netclock/Makefile.in new file mode 100644 index 0000000..b94c926 --- /dev/null +++ b/tests/examples/netclock/Makefile.in @@ -0,0 +1,839 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = netclock-server$(EXEEXT) netclock-client$(EXEEXT) +subdir = tests/examples/netclock +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +netclock_client_SOURCES = netclock-client.c +netclock_client_OBJECTS = netclock_client-netclock-client.$(OBJEXT) +am__DEPENDENCIES_1 = +netclock_client_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +netclock_client_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(netclock_client_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +netclock_server_SOURCES = netclock-server.c +netclock_server_OBJECTS = netclock_server-netclock-server.$(OBJEXT) +netclock_server_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +netclock_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(netclock_server_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = netclock-client.c netclock-server.c +DIST_SOURCES = netclock-client.c netclock-server.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +netclock_server_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +netclock_server_CFLAGS = $(GST_OBJ_CFLAGS) +netclock_client_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +netclock_client_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/netclock/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/netclock/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +netclock-client$(EXEEXT): $(netclock_client_OBJECTS) $(netclock_client_DEPENDENCIES) $(EXTRA_netclock_client_DEPENDENCIES) + @rm -f netclock-client$(EXEEXT) + $(AM_V_CCLD)$(netclock_client_LINK) $(netclock_client_OBJECTS) $(netclock_client_LDADD) $(LIBS) + +netclock-server$(EXEEXT): $(netclock_server_OBJECTS) $(netclock_server_DEPENDENCIES) $(EXTRA_netclock_server_DEPENDENCIES) + @rm -f netclock-server$(EXEEXT) + $(AM_V_CCLD)$(netclock_server_LINK) $(netclock_server_OBJECTS) $(netclock_server_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netclock_client-netclock-client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netclock_server-netclock-server.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +netclock_client-netclock-client.o: netclock-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_client_CFLAGS) $(CFLAGS) -MT netclock_client-netclock-client.o -MD -MP -MF $(DEPDIR)/netclock_client-netclock-client.Tpo -c -o netclock_client-netclock-client.o `test -f 'netclock-client.c' || echo '$(srcdir)/'`netclock-client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_client-netclock-client.Tpo $(DEPDIR)/netclock_client-netclock-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-client.c' object='netclock_client-netclock-client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_client_CFLAGS) $(CFLAGS) -c -o netclock_client-netclock-client.o `test -f 'netclock-client.c' || echo '$(srcdir)/'`netclock-client.c + +netclock_client-netclock-client.obj: netclock-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_client_CFLAGS) $(CFLAGS) -MT netclock_client-netclock-client.obj -MD -MP -MF $(DEPDIR)/netclock_client-netclock-client.Tpo -c -o netclock_client-netclock-client.obj `if test -f 'netclock-client.c'; then $(CYGPATH_W) 'netclock-client.c'; else $(CYGPATH_W) '$(srcdir)/netclock-client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_client-netclock-client.Tpo $(DEPDIR)/netclock_client-netclock-client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-client.c' object='netclock_client-netclock-client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_client_CFLAGS) $(CFLAGS) -c -o netclock_client-netclock-client.obj `if test -f 'netclock-client.c'; then $(CYGPATH_W) 'netclock-client.c'; else $(CYGPATH_W) '$(srcdir)/netclock-client.c'; fi` + +netclock_server-netclock-server.o: netclock-server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_server_CFLAGS) $(CFLAGS) -MT netclock_server-netclock-server.o -MD -MP -MF $(DEPDIR)/netclock_server-netclock-server.Tpo -c -o netclock_server-netclock-server.o `test -f 'netclock-server.c' || echo '$(srcdir)/'`netclock-server.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_server-netclock-server.Tpo $(DEPDIR)/netclock_server-netclock-server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-server.c' object='netclock_server-netclock-server.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_server_CFLAGS) $(CFLAGS) -c -o netclock_server-netclock-server.o `test -f 'netclock-server.c' || echo '$(srcdir)/'`netclock-server.c + +netclock_server-netclock-server.obj: netclock-server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_server_CFLAGS) $(CFLAGS) -MT netclock_server-netclock-server.obj -MD -MP -MF $(DEPDIR)/netclock_server-netclock-server.Tpo -c -o netclock_server-netclock-server.obj `if test -f 'netclock-server.c'; then $(CYGPATH_W) 'netclock-server.c'; else $(CYGPATH_W) '$(srcdir)/netclock-server.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_server-netclock-server.Tpo $(DEPDIR)/netclock_server-netclock-server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-server.c' object='netclock_server-netclock-server.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_server_CFLAGS) $(CFLAGS) -c -o netclock_server-netclock-server.obj `if test -f 'netclock-server.c'; then $(CYGPATH_W) 'netclock-server.c'; else $(CYGPATH_W) '$(srcdir)/netclock-server.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/netclock/meson.build b/tests/examples/netclock/meson.build new file mode 100644 index 0000000..6d9589d --- /dev/null +++ b/tests/examples/netclock/meson.build @@ -0,0 +1,11 @@ +executable('netclock-server', 'netclock-server.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_net_dep], + c_args: gst_c_args, +) + +executable('netclock-client', 'netclock-client.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_net_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/netclock/netclock-client.c b/tests/examples/netclock/netclock-client.c new file mode 100644 index 0000000..2082297 --- /dev/null +++ b/tests/examples/netclock/netclock-client.c @@ -0,0 +1,59 @@ +#include +#include +#include + +static gboolean +handle_bus_message (GstBus * bus, GstMessage * message, GstClock * client_clock) +{ + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) { + const GstStructure *s = gst_message_get_structure (message); + gchar *str; + + if (s == NULL) + return TRUE; + str = gst_structure_to_string (s); + g_print ("%s\n", str); + g_free (str); + } + return TRUE; +} + +gint +main (gint argc, gchar * argv[]) +{ + GMainLoop *loop; + gchar *host; + guint16 port; + GstClock *client_clock; + GstBus *bus; + + gst_init (&argc, &argv); + + if (argc < 3) { + g_print ("Usage: netclock-client \n"); + return 1; + } + + host = argv[1]; + port = atoi (argv[2]); + + client_clock = gst_net_client_clock_new (NULL, host, port, 0); + if (client_clock == NULL) { + g_printerr ("Failed to create network clock client\n"); + return 1; + } + + bus = gst_bus_new (); + gst_bus_add_watch (bus, (GstBusFunc) handle_bus_message, client_clock); + g_object_set (G_OBJECT (client_clock), "bus", bus, NULL); + + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + /* cleanup */ + g_main_loop_unref (loop); + g_object_unref (client_clock); + + return 0; +} diff --git a/tests/examples/netclock/netclock-server.c b/tests/examples/netclock/netclock-server.c new file mode 100644 index 0000000..46513e2 --- /dev/null +++ b/tests/examples/netclock/netclock-server.c @@ -0,0 +1,59 @@ +/* GStreamer + * Copyright (C) 2014 Jan Schmidt + * + * netclock-server.c: Publish a network clock provider + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +gint +main (gint argc, gchar * argv[]) +{ + GMainLoop *loop; + GstClock *clock; + GstNetTimeProvider *net_clock; + int clock_port = 0; + + gst_init (&argc, &argv); + + if (argc > 1) { + clock_port = atoi (argv[1]); + } + + loop = g_main_loop_new (NULL, FALSE); + + clock = gst_system_clock_obtain (); + net_clock = gst_net_time_provider_new (clock, NULL, clock_port); + gst_object_unref (clock); + + g_object_get (net_clock, "port", &clock_port, NULL); + + g_print ("Published network clock on port %u\n", clock_port); + + g_main_loop_run (loop); + + /* cleanup */ + g_main_loop_unref (loop); + + return 0; +} diff --git a/tests/examples/ptp/Makefile.am b/tests/examples/ptp/Makefile.am new file mode 100644 index 0000000..d76b4ad --- /dev/null +++ b/tests/examples/ptp/Makefile.am @@ -0,0 +1,7 @@ +noinst_PROGRAMS = ptp-print-times + +ptp_print_times_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) +ptp_print_times_CFLAGS = $(GST_OBJ_CFLAGS) + diff --git a/tests/examples/ptp/Makefile.in b/tests/examples/ptp/Makefile.in new file mode 100644 index 0000000..532fac4 --- /dev/null +++ b/tests/examples/ptp/Makefile.in @@ -0,0 +1,806 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = ptp-print-times$(EXEEXT) +subdir = tests/examples/ptp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +ptp_print_times_SOURCES = ptp-print-times.c +ptp_print_times_OBJECTS = ptp_print_times-ptp-print-times.$(OBJEXT) +am__DEPENDENCIES_1 = +ptp_print_times_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ptp_print_times_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(ptp_print_times_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = ptp-print-times.c +DIST_SOURCES = ptp-print-times.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ptp_print_times_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) + +ptp_print_times_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/ptp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/ptp/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +ptp-print-times$(EXEEXT): $(ptp_print_times_OBJECTS) $(ptp_print_times_DEPENDENCIES) $(EXTRA_ptp_print_times_DEPENDENCIES) + @rm -f ptp-print-times$(EXEEXT) + $(AM_V_CCLD)$(ptp_print_times_LINK) $(ptp_print_times_OBJECTS) $(ptp_print_times_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptp_print_times-ptp-print-times.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +ptp_print_times-ptp-print-times.o: ptp-print-times.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ptp_print_times_CFLAGS) $(CFLAGS) -MT ptp_print_times-ptp-print-times.o -MD -MP -MF $(DEPDIR)/ptp_print_times-ptp-print-times.Tpo -c -o ptp_print_times-ptp-print-times.o `test -f 'ptp-print-times.c' || echo '$(srcdir)/'`ptp-print-times.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ptp_print_times-ptp-print-times.Tpo $(DEPDIR)/ptp_print_times-ptp-print-times.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ptp-print-times.c' object='ptp_print_times-ptp-print-times.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ptp_print_times_CFLAGS) $(CFLAGS) -c -o ptp_print_times-ptp-print-times.o `test -f 'ptp-print-times.c' || echo '$(srcdir)/'`ptp-print-times.c + +ptp_print_times-ptp-print-times.obj: ptp-print-times.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ptp_print_times_CFLAGS) $(CFLAGS) -MT ptp_print_times-ptp-print-times.obj -MD -MP -MF $(DEPDIR)/ptp_print_times-ptp-print-times.Tpo -c -o ptp_print_times-ptp-print-times.obj `if test -f 'ptp-print-times.c'; then $(CYGPATH_W) 'ptp-print-times.c'; else $(CYGPATH_W) '$(srcdir)/ptp-print-times.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ptp_print_times-ptp-print-times.Tpo $(DEPDIR)/ptp_print_times-ptp-print-times.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ptp-print-times.c' object='ptp_print_times-ptp-print-times.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ptp_print_times_CFLAGS) $(CFLAGS) -c -o ptp_print_times-ptp-print-times.obj `if test -f 'ptp-print-times.c'; then $(CYGPATH_W) 'ptp-print-times.c'; else $(CYGPATH_W) '$(srcdir)/ptp-print-times.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/ptp/meson.build b/tests/examples/ptp/meson.build new file mode 100644 index 0000000..7e89b1e --- /dev/null +++ b/tests/examples/ptp/meson.build @@ -0,0 +1,5 @@ +executable('ptp-print-times', 'ptp-print-times.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, gst_net_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/ptp/ptp-print-times.c b/tests/examples/ptp/ptp-print-times.c new file mode 100644 index 0000000..b7de82a --- /dev/null +++ b/tests/examples/ptp/ptp-print-times.c @@ -0,0 +1,101 @@ +/* GStreamer + * Copyright (C) 2015 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* Create a PTP client clock and print times and statistics. + * + * When running this from a GStreamer build tree, you will have to set + * GST_PTP_HELPER to libs/gst/helpers/.libs/gst-ptp-helper and also + * make sure that it has the right permissions (setuid root or appropriate + * capabilities + * + * You can test this with any PTP compatible clock, e.g. ptpd from here: http://ptpd.sourceforge.net/ + * + * For testing the accuracy, you can use the PTP reflector available from + * http://code.centricular.com/ptp-clock-reflector/ or here + * https://github.com/sdroege/ptp-clock-reflector + */ + +#include +#include + +static gint domain = 0; +static gboolean stats = FALSE; + +static GOptionEntry opt_entries[] = { + {"domain", 'd', 0, G_OPTION_ARG_INT, &domain, + "PTP domain", NULL}, + {"stats", 's', 0, G_OPTION_ARG_NONE, &stats, + "Print PTP statistics", NULL}, + {NULL} +}; + +static gboolean +stats_cb (guint8 d, const GstStructure * stats, gpointer user_data) +{ + if (d == domain) { + gchar *stats_str = gst_structure_to_string (stats); + g_print ("Got stats: %s\n", stats_str); + g_free (stats_str); + } + + return TRUE; +} + +gint +main (gint argc, gchar ** argv) +{ + GOptionContext *opt_ctx; + GstClock *clock; + GError *err = NULL; + + opt_ctx = g_option_context_new ("- GStreamer PTP clock test app"); + g_option_context_add_main_entries (opt_ctx, opt_entries, NULL); + g_option_context_add_group (opt_ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (opt_ctx, &argc, &argv, &err)) + g_error ("Error parsing options: %s", err->message); + g_clear_error (&err); + g_option_context_free (opt_ctx); + + if (!gst_ptp_init (GST_PTP_CLOCK_ID_NONE, NULL)) + g_error ("failed to init ptp"); + + if (stats) + gst_ptp_statistics_callback_add (stats_cb, NULL, NULL); + + clock = gst_ptp_clock_new ("test-clock", domain); + + gst_clock_wait_for_sync (GST_CLOCK (clock), GST_CLOCK_TIME_NONE); + + while (TRUE) { + GstClockTime local, remote; + GstClockTimeDiff diff; + + local = g_get_real_time () * 1000; + remote = gst_clock_get_time (clock); + diff = GST_CLOCK_DIFF (local, remote); + + g_print ("local: %" GST_TIME_FORMAT " ptp: %" GST_TIME_FORMAT " diff: %s%" + GST_TIME_FORMAT "\n", GST_TIME_ARGS (local), GST_TIME_ARGS (remote), + (diff < 0 ? "-" : " "), GST_TIME_ARGS (ABS (diff))); + g_usleep (100000); + } + + return 0; +} diff --git a/tests/examples/stepping/Makefile.am b/tests/examples/stepping/Makefile.am new file mode 100644 index 0000000..2a6fbc1 --- /dev/null +++ b/tests/examples/stepping/Makefile.am @@ -0,0 +1,4 @@ +noinst_PROGRAMS = framestep1 + +framestep1_LDADD = $(GST_OBJ_LIBS) +framestep1_CFLAGS = $(GST_OBJ_CFLAGS) diff --git a/tests/examples/stepping/Makefile.in b/tests/examples/stepping/Makefile.in new file mode 100644 index 0000000..259ee16 --- /dev/null +++ b/tests/examples/stepping/Makefile.in @@ -0,0 +1,800 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = framestep1$(EXEEXT) +subdir = tests/examples/stepping +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +framestep1_SOURCES = framestep1.c +framestep1_OBJECTS = framestep1-framestep1.$(OBJEXT) +am__DEPENDENCIES_1 = +framestep1_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +framestep1_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(framestep1_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = framestep1.c +DIST_SOURCES = framestep1.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +framestep1_LDADD = $(GST_OBJ_LIBS) +framestep1_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/stepping/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/stepping/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +framestep1$(EXEEXT): $(framestep1_OBJECTS) $(framestep1_DEPENDENCIES) $(EXTRA_framestep1_DEPENDENCIES) + @rm -f framestep1$(EXEEXT) + $(AM_V_CCLD)$(framestep1_LINK) $(framestep1_OBJECTS) $(framestep1_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/framestep1-framestep1.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +framestep1-framestep1.o: framestep1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(framestep1_CFLAGS) $(CFLAGS) -MT framestep1-framestep1.o -MD -MP -MF $(DEPDIR)/framestep1-framestep1.Tpo -c -o framestep1-framestep1.o `test -f 'framestep1.c' || echo '$(srcdir)/'`framestep1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/framestep1-framestep1.Tpo $(DEPDIR)/framestep1-framestep1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='framestep1.c' object='framestep1-framestep1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(framestep1_CFLAGS) $(CFLAGS) -c -o framestep1-framestep1.o `test -f 'framestep1.c' || echo '$(srcdir)/'`framestep1.c + +framestep1-framestep1.obj: framestep1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(framestep1_CFLAGS) $(CFLAGS) -MT framestep1-framestep1.obj -MD -MP -MF $(DEPDIR)/framestep1-framestep1.Tpo -c -o framestep1-framestep1.obj `if test -f 'framestep1.c'; then $(CYGPATH_W) 'framestep1.c'; else $(CYGPATH_W) '$(srcdir)/framestep1.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/framestep1-framestep1.Tpo $(DEPDIR)/framestep1-framestep1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='framestep1.c' object='framestep1-framestep1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(framestep1_CFLAGS) $(CFLAGS) -c -o framestep1-framestep1.obj `if test -f 'framestep1.c'; then $(CYGPATH_W) 'framestep1.c'; else $(CYGPATH_W) '$(srcdir)/framestep1.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/stepping/framestep1.c b/tests/examples/stepping/framestep1.c new file mode 100644 index 0000000..69d42b9 --- /dev/null +++ b/tests/examples/stepping/framestep1.c @@ -0,0 +1,169 @@ +#include +#include + +static void +event_loop (GstElement * pipe) +{ + GstBus *bus; + GstMessage *message = NULL; + gboolean running = TRUE; + + bus = gst_element_get_bus (GST_ELEMENT (pipe)); + + while (running) { + message = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_ANY); + + g_assert (message != NULL); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_message ("got EOS"); + running = FALSE; + 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); + running = FALSE; + break; + } + case GST_MESSAGE_STEP_DONE: + { + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush, intermediate; + guint64 duration; + gboolean eos; + + gst_message_parse_step_done (message, &format, &amount, &rate, + &flush, &intermediate, &duration, &eos); + + if (format == GST_FORMAT_DEFAULT) { + g_message ("step done: %" GST_TIME_FORMAT " skipped in %" + G_GUINT64_FORMAT " frames", GST_TIME_ARGS (duration), amount); + } else { + g_message ("step done: %" GST_TIME_FORMAT " skipped", + GST_TIME_ARGS (duration)); + } + break; + } + default: + break; + } + gst_message_unref (message); + } + gst_object_unref (bus); +} + +/* signalled when a new preroll buffer is available */ +static GstFlowReturn +new_preroll (GstElement * appsink, gpointer user_data) +{ + GstBuffer *buffer; + + g_signal_emit_by_name (appsink, "pull-preroll", &buffer); + + g_message ("have new-preroll buffer %p, timestamp %" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + + gst_buffer_unref (buffer); + + return GST_FLOW_OK; +} + +int +main (int argc, char *argv[]) +{ + GstElement *bin, *videotestsrc, *appsink; + gint64 pos; + + gst_init (&argc, &argv); + + /* create a new bin to hold the elements */ + bin = gst_pipeline_new ("pipeline"); + g_assert (bin); + + /* create a fake source */ + videotestsrc = gst_element_factory_make ("videotestsrc", "videotestsrc"); + g_assert (videotestsrc); + g_object_set (videotestsrc, "num-buffers", 10, NULL); + + /* and a fake sink */ + appsink = gst_element_factory_make ("appsink", "appsink"); + g_assert (appsink); + g_object_set (appsink, "emit-signals", TRUE, NULL); + g_object_set (appsink, "sync", TRUE, NULL); + g_signal_connect (appsink, "new-preroll", (GCallback) new_preroll, NULL); + + /* add objects to the main pipeline */ + gst_bin_add (GST_BIN (bin), videotestsrc); + gst_bin_add (GST_BIN (bin), appsink); + + /* link the elements */ + gst_element_link_many (videotestsrc, appsink, NULL); + + /* 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); + + /* step two frames, flush so that new preroll is queued */ + g_message ("stepping three frames"); + if (!gst_element_send_event (bin, + gst_event_new_step (GST_FORMAT_BUFFERS, 2, 1.0, TRUE, FALSE))) + g_warning ("Filed to send STEP event!"); + + /* blocks and returns when we received the step done message */ + event_loop (bin); + + /* wait for step to really complete */ + gst_element_get_state (bin, NULL, NULL, -1); + + gst_element_query_position (bin, GST_FORMAT_TIME, &pos); + g_message ("stepped two frames, now at %" GST_TIME_FORMAT, + GST_TIME_ARGS (pos)); + + /* step 3 frames, flush so that new preroll is queued */ + g_message ("stepping 120 milliseconds "); + if (!gst_element_send_event (bin, + gst_event_new_step (GST_FORMAT_TIME, 120 * GST_MSECOND, 1.0, TRUE, + FALSE))) + g_warning ("Filed to send STEP event!"); + + /* blocks and returns when we received the step done message */ + event_loop (bin); + + /* wait for step to really complete */ + gst_element_get_state (bin, NULL, NULL, -1); + + gst_element_query_position (bin, GST_FORMAT_TIME, &pos); + g_message ("stepped 120ms frames, now at %" GST_TIME_FORMAT, + GST_TIME_ARGS (pos)); + + g_message ("playing until EOS"); + gst_element_set_state (bin, GST_STATE_PLAYING); + /* Run event loop listening for bus messages until EOS or ERROR */ + event_loop (bin); + g_message ("finished"); + + /* stop the bin */ + gst_element_set_state (bin, GST_STATE_NULL); + + exit (0); +} diff --git a/tests/examples/stepping/meson.build b/tests/examples/stepping/meson.build new file mode 100644 index 0000000..e4d4f28 --- /dev/null +++ b/tests/examples/stepping/meson.build @@ -0,0 +1,5 @@ +executable('framestep1', 'framestep1.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/streamiddemux/Makefile.am b/tests/examples/streamiddemux/Makefile.am new file mode 100644 index 0000000..e182d29 --- /dev/null +++ b/tests/examples/streamiddemux/Makefile.am @@ -0,0 +1,6 @@ +noinst_PROGRAMS = streamiddemux-stream + +streamiddemux_stream_SOURCES = streamiddemux-stream.c +streamiddemux_stream_LDADD = $(GST_OBJ_LIBS) +streamiddemux_stream_CFLAGS = $(GST_OBJ_CFLAGS) + diff --git a/tests/examples/streamiddemux/Makefile.in b/tests/examples/streamiddemux/Makefile.in new file mode 100644 index 0000000..349ccfd --- /dev/null +++ b/tests/examples/streamiddemux/Makefile.in @@ -0,0 +1,803 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = streamiddemux-stream$(EXEEXT) +subdir = tests/examples/streamiddemux +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_streamiddemux_stream_OBJECTS = \ + streamiddemux_stream-streamiddemux-stream.$(OBJEXT) +streamiddemux_stream_OBJECTS = $(am_streamiddemux_stream_OBJECTS) +am__DEPENDENCIES_1 = +streamiddemux_stream_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +streamiddemux_stream_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(streamiddemux_stream_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(streamiddemux_stream_SOURCES) +DIST_SOURCES = $(streamiddemux_stream_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +streamiddemux_stream_SOURCES = streamiddemux-stream.c +streamiddemux_stream_LDADD = $(GST_OBJ_LIBS) +streamiddemux_stream_CFLAGS = $(GST_OBJ_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/streamiddemux/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/streamiddemux/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +streamiddemux-stream$(EXEEXT): $(streamiddemux_stream_OBJECTS) $(streamiddemux_stream_DEPENDENCIES) $(EXTRA_streamiddemux_stream_DEPENDENCIES) + @rm -f streamiddemux-stream$(EXEEXT) + $(AM_V_CCLD)$(streamiddemux_stream_LINK) $(streamiddemux_stream_OBJECTS) $(streamiddemux_stream_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +streamiddemux_stream-streamiddemux-stream.o: streamiddemux-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(streamiddemux_stream_CFLAGS) $(CFLAGS) -MT streamiddemux_stream-streamiddemux-stream.o -MD -MP -MF $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Tpo -c -o streamiddemux_stream-streamiddemux-stream.o `test -f 'streamiddemux-stream.c' || echo '$(srcdir)/'`streamiddemux-stream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Tpo $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='streamiddemux-stream.c' object='streamiddemux_stream-streamiddemux-stream.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(streamiddemux_stream_CFLAGS) $(CFLAGS) -c -o streamiddemux_stream-streamiddemux-stream.o `test -f 'streamiddemux-stream.c' || echo '$(srcdir)/'`streamiddemux-stream.c + +streamiddemux_stream-streamiddemux-stream.obj: streamiddemux-stream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(streamiddemux_stream_CFLAGS) $(CFLAGS) -MT streamiddemux_stream-streamiddemux-stream.obj -MD -MP -MF $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Tpo -c -o streamiddemux_stream-streamiddemux-stream.obj `if test -f 'streamiddemux-stream.c'; then $(CYGPATH_W) 'streamiddemux-stream.c'; else $(CYGPATH_W) '$(srcdir)/streamiddemux-stream.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Tpo $(DEPDIR)/streamiddemux_stream-streamiddemux-stream.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='streamiddemux-stream.c' object='streamiddemux_stream-streamiddemux-stream.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(streamiddemux_stream_CFLAGS) $(CFLAGS) -c -o streamiddemux_stream-streamiddemux-stream.obj `if test -f 'streamiddemux-stream.c'; then $(CYGPATH_W) 'streamiddemux-stream.c'; else $(CYGPATH_W) '$(srcdir)/streamiddemux-stream.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/streamiddemux/meson.build b/tests/examples/streamiddemux/meson.build new file mode 100644 index 0000000..88c4823 --- /dev/null +++ b/tests/examples/streamiddemux/meson.build @@ -0,0 +1,5 @@ +executable('streamiddemux-stream', 'streamiddemux-stream.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + c_args: gst_c_args, +) diff --git a/tests/examples/streamiddemux/streamiddemux-stream.c b/tests/examples/streamiddemux/streamiddemux-stream.c new file mode 100644 index 0000000..1ef128b --- /dev/null +++ b/tests/examples/streamiddemux/streamiddemux-stream.c @@ -0,0 +1,241 @@ +#include + +#define NUM_STREAM 13 + +typedef struct _App App; + +struct _App +{ + GstElement *pipeline; + GstElement *audiotestsrc[NUM_STREAM]; + GstElement *audioconvert[NUM_STREAM]; + GstElement *capsfilter[NUM_STREAM]; + GstElement *vorbisenc[NUM_STREAM]; + GstElement *oggmux[NUM_STREAM]; + GstElement *funnel; + GstElement *demux; + GstElement *stream_synchronizer; + GstElement *queue[NUM_STREAM]; + GstElement *filesink[NUM_STREAM]; + + gboolean pad_blocked[NUM_STREAM]; + GstPad *queue_srcpad[NUM_STREAM]; + gulong blocked_id[NUM_STREAM]; +}; + +App s_app; + +gint pad_added_cnt = 0; + +static gboolean +bus_call (GstBus * bus, GstMessage * msg, gpointer data) +{ + GMainLoop *loop = (GMainLoop *) data; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS:{ + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_ERROR:{ + g_main_loop_quit (loop); + break; + } + default: + break; + } + return TRUE; +} + +static void +set_blocked (App * app, gboolean blocked) +{ + gint i = 0; + + for (i = 0; i < NUM_STREAM; i++) { + gst_pad_remove_probe (app->queue_srcpad[i], app->blocked_id[i]); + } +} + +static void +sink_do_reconfigure (App * app) +{ + gint i = 0; + GstPad *filesink_sinkpad[NUM_STREAM]; + GstPad *sync_sinkpad[NUM_STREAM]; + GstPad *sync_srcpad[NUM_STREAM]; + GstIterator *it; + GValue item = G_VALUE_INIT; + + for (i = 0; i < NUM_STREAM; i++) { + sync_sinkpad[i] = + gst_element_get_request_pad (app->stream_synchronizer, "sink_%u"); + it = gst_pad_iterate_internal_links (sync_sinkpad[i]); + g_assert (it); + gst_iterator_next (it, &item); + sync_srcpad[i] = g_value_dup_object (&item); + g_value_unset (&item); + + filesink_sinkpad[i] = gst_element_get_static_pad (app->filesink[i], "sink"); + + gst_pad_link_full (app->queue_srcpad[i], sync_sinkpad[i], + GST_PAD_LINK_CHECK_NOTHING); + gst_pad_link_full (sync_srcpad[i], filesink_sinkpad[i], + GST_PAD_LINK_CHECK_NOTHING); + } + gst_iterator_free (it); + +} + +static GstPadProbeReturn +blocked_cb (GstPad * blockedpad, GstPadProbeInfo * info, gpointer user_data) +{ + App *app = user_data; + gint i = 0; + gboolean all_pads_blocked = TRUE; + + for (i = 0; i < NUM_STREAM; i++) { + if (blockedpad == app->queue_srcpad[i]) + app->pad_blocked[i] = TRUE; + } + + for (i = 0; i < NUM_STREAM; i++) { + if (app->queue_srcpad[i] == FALSE) { + all_pads_blocked = FALSE; + break; + } + } + + if (all_pads_blocked == TRUE) { + sink_do_reconfigure (app); + set_blocked (app, FALSE); + } + + return GST_PAD_PROBE_OK; +} + +static void +src_pad_added_cb (GstElement * demux, GstPad * pad, App * app) +{ + GstPad *queue_sinkpad[NUM_STREAM]; + + queue_sinkpad[pad_added_cnt] = + gst_element_get_static_pad (app->queue[pad_added_cnt], "sink"); + gst_pad_link_full (pad, queue_sinkpad[pad_added_cnt], + GST_PAD_LINK_CHECK_NOTHING); + + app->queue_srcpad[pad_added_cnt] = + gst_element_get_static_pad (app->queue[pad_added_cnt], "src"); + app->blocked_id[pad_added_cnt] = + gst_pad_add_probe (app->queue_srcpad[pad_added_cnt], + GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, blocked_cb, app, NULL); + + pad_added_cnt++; +} + +gint +main (gint argc, gchar * argv[]) +{ + App *app = &s_app; + + GMainLoop *loop = NULL; + GstBus *bus; + guint bus_watch_id; + + GstPad *funnel_sinkpad[NUM_STREAM]; + GstPad *funnel_srcpad; + GstPad *demux_sinkpad; + GstPad *oggmux_srcpad[NUM_STREAM]; + + guint stream_cnt = 0; + GstCaps *caps; + + gst_init (&argc, &argv); + + app->pipeline = gst_pipeline_new ("pipeline"); + + for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) { + app->audiotestsrc[stream_cnt] = + gst_element_factory_make ("audiotestsrc", NULL); + app->audioconvert[stream_cnt] = + gst_element_factory_make ("audioconvert", NULL); + app->capsfilter[stream_cnt] = gst_element_factory_make ("capsfilter", NULL); + app->vorbisenc[stream_cnt] = gst_element_factory_make ("vorbisenc", NULL); + app->oggmux[stream_cnt] = gst_element_factory_make ("oggmux", NULL); + } + + app->funnel = gst_element_factory_make ("funnel", NULL); + app->demux = gst_element_factory_make ("streamiddemux", NULL); + app->stream_synchronizer = + gst_element_factory_make ("streamsynchronizer", NULL); + + caps = gst_caps_from_string ("audio/x-raw,channels=1;"); + + stream_cnt = 0; + + for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) { + app->queue[stream_cnt] = gst_element_factory_make ("queue", NULL); + app->filesink[stream_cnt] = gst_element_factory_make ("filesink", NULL); + + g_object_set (app->audiotestsrc[stream_cnt], "wave", stream_cnt, + "num-buffers", 2000, NULL); + g_object_set (app->capsfilter[stream_cnt], "caps", caps, NULL); + g_object_set (app->filesink[stream_cnt], "location", + g_strdup_printf ("filesink_%d.ogg", stream_cnt), NULL); + } + + stream_cnt = 0; + + g_signal_connect (app->demux, "pad-added", G_CALLBACK (src_pad_added_cb), + app); + + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (app->pipeline); + bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); + g_object_unref (bus); + + for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) { + gst_bin_add_many (GST_BIN (app->pipeline), app->audiotestsrc[stream_cnt], + app->audioconvert[stream_cnt], app->capsfilter[stream_cnt], + app->vorbisenc[stream_cnt], app->oggmux[stream_cnt], + app->queue[stream_cnt], app->filesink[stream_cnt], NULL); + if (stream_cnt == 0) { + gst_bin_add_many (GST_BIN (app->pipeline), app->funnel, app->demux, + app->stream_synchronizer, NULL); + } + } + + stream_cnt = 0; + + for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) { + gst_element_link_many (app->audiotestsrc[stream_cnt], + app->audioconvert[stream_cnt], app->capsfilter[stream_cnt], + app->vorbisenc[stream_cnt], app->oggmux[stream_cnt], NULL); + } + + stream_cnt = 0; + + for (stream_cnt = 0; stream_cnt < NUM_STREAM; stream_cnt++) { + funnel_sinkpad[stream_cnt] = + gst_element_get_request_pad (app->funnel, "sink_%u"); + oggmux_srcpad[stream_cnt] = + gst_element_get_static_pad (app->oggmux[stream_cnt], "src"); + gst_pad_link (oggmux_srcpad[stream_cnt], funnel_sinkpad[stream_cnt]); + } + + funnel_srcpad = gst_element_get_static_pad (app->funnel, "src"); + + demux_sinkpad = gst_element_get_static_pad (app->demux, "sink"); + gst_pad_link (funnel_srcpad, demux_sinkpad); + + gst_element_set_state (app->pipeline, GST_STATE_PLAYING); + g_main_loop_run (loop); + + gst_element_set_state (app->pipeline, GST_STATE_NULL); + g_object_unref (app->pipeline); + g_source_remove (bus_watch_id); + g_main_loop_unref (loop); + + return 0; +} diff --git a/tests/examples/streams/Makefile.am b/tests/examples/streams/Makefile.am new file mode 100644 index 0000000..e1f87ac --- /dev/null +++ b/tests/examples/streams/Makefile.am @@ -0,0 +1,14 @@ +noinst_PROGRAMS = stream-status +if HAVE_PTHREAD +noinst_PROGRAMS += rtpool-test +endif + +stream_status_SOURCES = stream-status.c +stream_status_LDADD = $(GST_OBJ_LIBS) +stream_status_CFLAGS = $(GST_OBJ_CFLAGS) + +rtpool_test_SOURCES = rtpool-test.c testrtpool.h testrtpool.c +rtpool_test_LDADD = $(GST_OBJ_LIBS) $(PTHREAD_LIBS) +rtpool_test_CFLAGS = $(GST_OBJ_CFLAGS) $(PTHREAD_CFLAGS) + +EXTRA_DIST = rtpool-test.c testrtpool.h testrtpool.c diff --git a/tests/examples/streams/Makefile.in b/tests/examples/streams/Makefile.in new file mode 100644 index 0000000..4c46dcf --- /dev/null +++ b/tests/examples/streams/Makefile.in @@ -0,0 +1,848 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = stream-status$(EXEEXT) $(am__EXEEXT_1) +@HAVE_PTHREAD_TRUE@am__append_1 = rtpool-test +subdir = tests/examples/streams +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_PTHREAD_TRUE@am__EXEEXT_1 = rtpool-test$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_rtpool_test_OBJECTS = rtpool_test-rtpool-test.$(OBJEXT) \ + rtpool_test-testrtpool.$(OBJEXT) +rtpool_test_OBJECTS = $(am_rtpool_test_OBJECTS) +am__DEPENDENCIES_1 = +rtpool_test_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +rtpool_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(rtpool_test_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_stream_status_OBJECTS = stream_status-stream-status.$(OBJEXT) +stream_status_OBJECTS = $(am_stream_status_OBJECTS) +stream_status_DEPENDENCIES = $(am__DEPENDENCIES_1) +stream_status_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(stream_status_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(rtpool_test_SOURCES) $(stream_status_SOURCES) +DIST_SOURCES = $(rtpool_test_SOURCES) $(stream_status_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +stream_status_SOURCES = stream-status.c +stream_status_LDADD = $(GST_OBJ_LIBS) +stream_status_CFLAGS = $(GST_OBJ_CFLAGS) +rtpool_test_SOURCES = rtpool-test.c testrtpool.h testrtpool.c +rtpool_test_LDADD = $(GST_OBJ_LIBS) $(PTHREAD_LIBS) +rtpool_test_CFLAGS = $(GST_OBJ_CFLAGS) $(PTHREAD_CFLAGS) +EXTRA_DIST = rtpool-test.c testrtpool.h testrtpool.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/examples/streams/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/examples/streams/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +rtpool-test$(EXEEXT): $(rtpool_test_OBJECTS) $(rtpool_test_DEPENDENCIES) $(EXTRA_rtpool_test_DEPENDENCIES) + @rm -f rtpool-test$(EXEEXT) + $(AM_V_CCLD)$(rtpool_test_LINK) $(rtpool_test_OBJECTS) $(rtpool_test_LDADD) $(LIBS) + +stream-status$(EXEEXT): $(stream_status_OBJECTS) $(stream_status_DEPENDENCIES) $(EXTRA_stream_status_DEPENDENCIES) + @rm -f stream-status$(EXEEXT) + $(AM_V_CCLD)$(stream_status_LINK) $(stream_status_OBJECTS) $(stream_status_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtpool_test-rtpool-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtpool_test-testrtpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_status-stream-status.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +rtpool_test-rtpool-test.o: rtpool-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -MT rtpool_test-rtpool-test.o -MD -MP -MF $(DEPDIR)/rtpool_test-rtpool-test.Tpo -c -o rtpool_test-rtpool-test.o `test -f 'rtpool-test.c' || echo '$(srcdir)/'`rtpool-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rtpool_test-rtpool-test.Tpo $(DEPDIR)/rtpool_test-rtpool-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtpool-test.c' object='rtpool_test-rtpool-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -c -o rtpool_test-rtpool-test.o `test -f 'rtpool-test.c' || echo '$(srcdir)/'`rtpool-test.c + +rtpool_test-rtpool-test.obj: rtpool-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -MT rtpool_test-rtpool-test.obj -MD -MP -MF $(DEPDIR)/rtpool_test-rtpool-test.Tpo -c -o rtpool_test-rtpool-test.obj `if test -f 'rtpool-test.c'; then $(CYGPATH_W) 'rtpool-test.c'; else $(CYGPATH_W) '$(srcdir)/rtpool-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rtpool_test-rtpool-test.Tpo $(DEPDIR)/rtpool_test-rtpool-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rtpool-test.c' object='rtpool_test-rtpool-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -c -o rtpool_test-rtpool-test.obj `if test -f 'rtpool-test.c'; then $(CYGPATH_W) 'rtpool-test.c'; else $(CYGPATH_W) '$(srcdir)/rtpool-test.c'; fi` + +rtpool_test-testrtpool.o: testrtpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -MT rtpool_test-testrtpool.o -MD -MP -MF $(DEPDIR)/rtpool_test-testrtpool.Tpo -c -o rtpool_test-testrtpool.o `test -f 'testrtpool.c' || echo '$(srcdir)/'`testrtpool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rtpool_test-testrtpool.Tpo $(DEPDIR)/rtpool_test-testrtpool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testrtpool.c' object='rtpool_test-testrtpool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -c -o rtpool_test-testrtpool.o `test -f 'testrtpool.c' || echo '$(srcdir)/'`testrtpool.c + +rtpool_test-testrtpool.obj: testrtpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -MT rtpool_test-testrtpool.obj -MD -MP -MF $(DEPDIR)/rtpool_test-testrtpool.Tpo -c -o rtpool_test-testrtpool.obj `if test -f 'testrtpool.c'; then $(CYGPATH_W) 'testrtpool.c'; else $(CYGPATH_W) '$(srcdir)/testrtpool.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rtpool_test-testrtpool.Tpo $(DEPDIR)/rtpool_test-testrtpool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testrtpool.c' object='rtpool_test-testrtpool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rtpool_test_CFLAGS) $(CFLAGS) -c -o rtpool_test-testrtpool.obj `if test -f 'testrtpool.c'; then $(CYGPATH_W) 'testrtpool.c'; else $(CYGPATH_W) '$(srcdir)/testrtpool.c'; fi` + +stream_status-stream-status.o: stream-status.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stream_status_CFLAGS) $(CFLAGS) -MT stream_status-stream-status.o -MD -MP -MF $(DEPDIR)/stream_status-stream-status.Tpo -c -o stream_status-stream-status.o `test -f 'stream-status.c' || echo '$(srcdir)/'`stream-status.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stream_status-stream-status.Tpo $(DEPDIR)/stream_status-stream-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stream-status.c' object='stream_status-stream-status.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stream_status_CFLAGS) $(CFLAGS) -c -o stream_status-stream-status.o `test -f 'stream-status.c' || echo '$(srcdir)/'`stream-status.c + +stream_status-stream-status.obj: stream-status.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stream_status_CFLAGS) $(CFLAGS) -MT stream_status-stream-status.obj -MD -MP -MF $(DEPDIR)/stream_status-stream-status.Tpo -c -o stream_status-stream-status.obj `if test -f 'stream-status.c'; then $(CYGPATH_W) 'stream-status.c'; else $(CYGPATH_W) '$(srcdir)/stream-status.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stream_status-stream-status.Tpo $(DEPDIR)/stream_status-stream-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stream-status.c' object='stream_status-stream-status.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stream_status_CFLAGS) $(CFLAGS) -c -o stream_status-stream-status.obj `if test -f 'stream-status.c'; then $(CYGPATH_W) 'stream-status.c'; else $(CYGPATH_W) '$(srcdir)/stream-status.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/examples/streams/meson.build b/tests/examples/streams/meson.build new file mode 100644 index 0000000..e087f41 --- /dev/null +++ b/tests/examples/streams/meson.build @@ -0,0 +1,15 @@ +executable('stream-status', 'stream-status.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + c_args: gst_c_args, +) + +# we assume that if the header is there it actually found pthreads as thread lib +threads_dep = dependency('threads', required : false) +if threads_dep.found() and cc.has_header('pthread.h') + executable('rtpool-test', 'rtpool-test.c', 'testrtpool.c', + install: false, + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep, threads_dep], + c_args: gst_c_args, + ) +endif diff --git a/tests/examples/streams/rtpool-test.c b/tests/examples/streams/rtpool-test.c new file mode 100644 index 0000000..fe129d2 --- /dev/null +++ b/tests/examples/streams/rtpool-test.c @@ -0,0 +1,173 @@ +#include +#include + +#include "testrtpool.h" + +static GstTaskPool *pool; + +static void +event_loop (GstBus * bus, GstElement * pipe) +{ + GstMessage *message = NULL; + + while (TRUE) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); + + g_assert (message != NULL); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_message ("received EOS"); + gst_message_unref (message); + return; + case GST_MESSAGE_WARNING: + { + GError *gerror; + gchar *debug; + + gst_message_parse_warning (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + gst_message_unref (message); + g_error_free (gerror); + g_free (debug); + return; + } + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + gst_message_unref (message); + g_error_free (gerror); + g_free (debug); + return; + } + default: + gst_message_unref (message); + break; + } + } +} + +static GstBusSyncReply +sync_bus_handler (GstBus * bus, GstMessage * message, GstElement * bin) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_STREAM_STATUS: + { + GstStreamStatusType type; + GstElement *owner; + const GValue *val; + gchar *path; + GstTask *task = NULL; + + g_message ("received STREAM_STATUS"); + gst_message_parse_stream_status (message, &type, &owner); + + val = gst_message_get_stream_status_object (message); + + g_message ("type: %d", type); + path = gst_object_get_path_string (GST_MESSAGE_SRC (message)); + g_message ("source: %s", path); + g_free (path); + path = gst_object_get_path_string (GST_OBJECT (owner)); + g_message ("owner: %s", path); + g_free (path); + + if (G_VALUE_HOLDS_OBJECT (val)) { + g_message ("object: type %s, value %p", G_VALUE_TYPE_NAME (val), + g_value_get_object (val)); + } else if (G_VALUE_HOLDS_POINTER (val)) { + g_message ("object: type %s, value %p", G_VALUE_TYPE_NAME (val), + g_value_get_pointer (val)); + } else if (G_IS_VALUE (val)) { + g_message ("object: type %s", G_VALUE_TYPE_NAME (val)); + } else { + g_message ("object: (null)"); + break; + } + + /* see if we know how to deal with this object */ + if (G_VALUE_TYPE (val) == GST_TYPE_TASK) { + task = g_value_get_object (val); + } + + switch (type) { + case GST_STREAM_STATUS_TYPE_CREATE: + if (task) { + g_message ("created task %p, setting pool", task); + gst_task_set_pool (task, pool); + } + break; + case GST_STREAM_STATUS_TYPE_ENTER: + break; + case GST_STREAM_STATUS_TYPE_LEAVE: + break; + default: + break; + } + break; + } + default: + break; + } + /* pass all messages on the async queue */ + return GST_BUS_PASS; +} + +int +main (int argc, char *argv[]) +{ + GstElement *bin, *alsasrc, *alsasink; + GstBus *bus; + GstStateChangeReturn ret; + + gst_init (&argc, &argv); + + /* create a custom thread pool */ + pool = test_rt_pool_new (); + + /* create a new bin to hold the elements */ + bin = gst_pipeline_new ("pipeline"); + g_assert (bin); + + /* create a source */ + alsasrc = gst_element_factory_make ("alsasrc", "alsasrc"); + g_assert (alsasrc); + g_object_set (alsasrc, "device", "hw:0", NULL); + g_object_set (alsasrc, "latency-time", (gint64) 2000, NULL); + g_object_set (alsasrc, "slave-method", 2, NULL); + + /* and a sink */ + alsasink = gst_element_factory_make ("alsasink", "alsasink"); + g_assert (alsasink); + g_object_set (alsasink, "device", "hw:0", NULL); + g_object_set (alsasink, "latency-time", (gint64) 2000, NULL); + g_object_set (alsasink, "buffer-time", (gint64) 10000, NULL); + + /* add objects to the main pipeline */ + gst_bin_add_many (GST_BIN (bin), alsasrc, alsasink, NULL); + + /* link the elements */ + gst_element_link (alsasrc, alsasink); + + /* get the bus, we need to install a sync handler */ + bus = gst_pipeline_get_bus (GST_PIPELINE (bin)); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) sync_bus_handler, bin, + NULL); + + /* start playing */ + ret = gst_element_set_state (bin, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) + return 0; + + /* Run event loop listening for bus messages until EOS or ERROR */ + event_loop (bus, bin); + + /* stop the bin */ + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bus); + + exit (0); +} diff --git a/tests/examples/streams/stream-status.c b/tests/examples/streams/stream-status.c new file mode 100644 index 0000000..c94823e --- /dev/null +++ b/tests/examples/streams/stream-status.c @@ -0,0 +1,145 @@ +#include +#include + +static void +event_loop (GstBus * bus, GstElement * pipe) +{ + GstMessage *message = NULL; + + while (TRUE) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); + + g_assert (message != NULL); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_message ("received EOS"); + gst_message_unref (message); + return; + case GST_MESSAGE_WARNING:{ + GError *gerror; + gchar *debug; + + gst_message_parse_warning (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + gst_message_unref (message); + g_error_free (gerror); + g_free (debug); + break; + } + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + gst_message_unref (message); + g_error_free (gerror); + g_free (debug); + return; + } + default: + gst_message_unref (message); + break; + } + } +} + +static GstBusSyncReply +sync_bus_handler (GstBus * bus, GstMessage * message, GstElement * bin) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_STREAM_STATUS: + { + GstStreamStatusType type; + GstElement *owner; + const GValue *val; + gchar *path; + GstTask *task = NULL; + + g_message ("received STREAM_STATUS"); + gst_message_parse_stream_status (message, &type, &owner); + + val = gst_message_get_stream_status_object (message); + + g_message ("type: %d", type); + path = gst_object_get_path_string (GST_MESSAGE_SRC (message)); + g_message ("source: %s", path); + g_free (path); + path = gst_object_get_path_string (GST_OBJECT (owner)); + g_message ("owner: %s", path); + g_free (path); + g_message ("object: type %s, value %p", G_VALUE_TYPE_NAME (val), + g_value_get_object (val)); + + /* see if we know how to deal with this object */ + if (G_VALUE_TYPE (val) == GST_TYPE_TASK) { + task = g_value_get_object (val); + } + + switch (type) { + case GST_STREAM_STATUS_TYPE_CREATE: + g_message ("created task %p", task); + break; + case GST_STREAM_STATUS_TYPE_ENTER: + /* g_message ("raising task priority"); */ + /* setpriority (PRIO_PROCESS, 0, -10); */ + break; + case GST_STREAM_STATUS_TYPE_LEAVE: + break; + default: + break; + } + break; + } + default: + break; + } + /* pass all messages on the async queue */ + return GST_BUS_PASS; +} + +int +main (int argc, char *argv[]) +{ + GstElement *bin, *fakesrc, *fakesink; + GstBus *bus; + + gst_init (&argc, &argv); + + /* create a new bin to hold the elements */ + bin = gst_pipeline_new ("pipeline"); + g_assert (bin); + + /* create a source */ + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + g_assert (fakesrc); + g_object_set (fakesrc, "num-buffers", 50, NULL); + + /* and a sink */ + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + g_assert (fakesink); + + /* add objects to the main pipeline */ + gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL); + + /* link the elements */ + gst_element_link (fakesrc, fakesink); + + /* get the bus, we need to install a sync handler */ + bus = gst_pipeline_get_bus (GST_PIPELINE (bin)); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) sync_bus_handler, bin, + NULL); + + /* start playing */ + gst_element_set_state (bin, GST_STATE_PLAYING); + + /* Run event loop listening for bus messages until EOS or ERROR */ + event_loop (bus, bin); + + /* stop the bin */ + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bus); + + exit (0); +} diff --git a/tests/examples/streams/testrtpool.c b/tests/examples/streams/testrtpool.c new file mode 100644 index 0000000..0a29fda --- /dev/null +++ b/tests/examples/streams/testrtpool.c @@ -0,0 +1,135 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include "testrtpool.h" + +static void test_rt_pool_finalize (GObject * object); + +typedef struct +{ + pthread_t thread; +} TestRTId; + +G_DEFINE_TYPE (TestRTPool, test_rt_pool, GST_TYPE_TASK_POOL); + +static void +default_prepare (GstTaskPool * pool, GError ** error) +{ + /* we don't do anything here. We could construct a pool of threads here that + * we could reuse later but we don't */ + g_message ("prepare Realtime pool %p", pool); +} + +static void +default_cleanup (GstTaskPool * pool) +{ + g_message ("cleanup Realtime pool %p", pool); +} + +static gpointer +default_push (GstTaskPool * pool, GstTaskPoolFunction func, gpointer data, + GError ** error) +{ + TestRTId *tid; + gint res; + pthread_attr_t attr; + struct sched_param param; + + g_message ("pushing Realtime pool %p, %p", pool, func); + + tid = g_slice_new0 (TestRTId); + + g_message ("set policy"); + pthread_attr_init (&attr); + if ((res = pthread_attr_setschedpolicy (&attr, SCHED_RR)) != 0) + g_warning ("setschedpolicy: failure: %p", g_strerror (res)); + + g_message ("set prio"); + param.sched_priority = 50; + if ((res = pthread_attr_setschedparam (&attr, ¶m)) != 0) + g_warning ("setschedparam: failure: %p", g_strerror (res)); + + g_message ("set inherit"); + if ((res = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0) + g_warning ("setinheritsched: failure: %p", g_strerror (res)); + + g_message ("create thread"); + res = pthread_create (&tid->thread, &attr, (void *(*)(void *)) func, data); + + if (res != 0) { + g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, + "Error creating thread: %s", g_strerror (res)); + g_slice_free (TestRTId, tid); + tid = NULL; + } + + return tid; +} + +static void +default_join (GstTaskPool * pool, gpointer id) +{ + TestRTId *tid = (TestRTId *) id; + + g_message ("joining Realtime pool %p", pool); + + pthread_join (tid->thread, NULL); + + g_slice_free (TestRTId, tid); +} + +static void +test_rt_pool_class_init (TestRTPoolClass * klass) +{ + GObjectClass *gobject_class; + GstTaskPoolClass *gsttaskpool_class; + + gobject_class = (GObjectClass *) klass; + gsttaskpool_class = (GstTaskPoolClass *) klass; + + gobject_class->finalize = GST_DEBUG_FUNCPTR (test_rt_pool_finalize); + + gsttaskpool_class->prepare = default_prepare; + gsttaskpool_class->cleanup = default_cleanup; + gsttaskpool_class->push = default_push; + gsttaskpool_class->join = default_join; +} + +static void +test_rt_pool_init (TestRTPool * pool) +{ +} + +static void +test_rt_pool_finalize (GObject * object) +{ + G_OBJECT_CLASS (test_rt_pool_parent_class)->finalize (object); +} + +GstTaskPool * +test_rt_pool_new (void) +{ + GstTaskPool *pool; + + pool = g_object_new (TEST_TYPE_RT_POOL, NULL); + + return pool; +} diff --git a/tests/examples/streams/testrtpool.h b/tests/examples/streams/testrtpool.h new file mode 100644 index 0000000..95e62e9 --- /dev/null +++ b/tests/examples/streams/testrtpool.h @@ -0,0 +1,53 @@ +/* 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __TEST_RT_POOL_H__ +#define __TEST_RT_POOL_H__ + +#include + +G_BEGIN_DECLS + +/* --- standard type macros --- */ +#define TEST_TYPE_RT_POOL (test_rt_pool_get_type ()) +#define TEST_RT_POOL(pool) (G_TYPE_CHECK_INSTANCE_CAST ((pool), TEST_TYPE_RT_POOL, TestRTPool)) +#define TEST_IS_RT_POOL(pool) (G_TYPE_CHECK_INSTANCE_TYPE ((pool), TEST_TYPE_RT_POOL)) +#define TEST_RT_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_CAST ((pclass), TEST_TYPE_RT_POOL, TestRTPoolClass)) +#define TEST_IS_RT_POOL_CLASS(pclass) (G_TYPE_CHECK_CLASS_TYPE ((pclass), TEST_TYPE_RT_POOL)) +#define TEST_RT_POOL_GET_CLASS(pool) (G_TYPE_INSTANCE_GET_CLASS ((pool), TEST_TYPE_RT_POOL, TestRTPoolClass)) +#define TEST_RT_POOL_CAST(pool) ((TestRTPool*)(pool)) + +typedef struct _TestRTPool TestRTPool; +typedef struct _TestRTPoolClass TestRTPoolClass; + +struct _TestRTPool { + GstTaskPool object; +}; + +struct _TestRTPoolClass { + GstTaskPoolClass parent_class; +}; + +GType test_rt_pool_get_type (void); + +GstTaskPool * test_rt_pool_new (void); + +G_END_DECLS + +#endif /* __TEST_RT_POOL_H__ */ diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..a53dcf8 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,6 @@ +subdir('benchmarks') +subdir('check') +if not get_option('disable_examples') + subdir('examples') +endif +subdir('misc') diff --git a/tests/misc/Makefile.am b/tests/misc/Makefile.am new file mode 100644 index 0000000..5aaede5 --- /dev/null +++ b/tests/misc/Makefile.am @@ -0,0 +1,12 @@ +EXTRA_DIST = \ + network-clock.scm \ + network-clock-utils.scm \ + plot-data + +noinst_PROGRAMS = netclock-replay + +netclock_replay_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) \ + $(GIO_LIBS) +netclock_replay_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) diff --git a/tests/misc/Makefile.in b/tests/misc/Makefile.in new file mode 100644 index 0000000..a2702a2 --- /dev/null +++ b/tests/misc/Makefile.in @@ -0,0 +1,812 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = netclock-replay$(EXEEXT) +subdir = tests/misc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +netclock_replay_SOURCES = netclock-replay.c +netclock_replay_OBJECTS = netclock_replay-netclock-replay.$(OBJEXT) +am__DEPENDENCIES_1 = +netclock_replay_DEPENDENCIES = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +netclock_replay_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(netclock_replay_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = netclock-replay.c +DIST_SOURCES = netclock-replay.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + network-clock.scm \ + network-clock-utils.scm \ + plot-data + +netclock_replay_LDADD = \ + $(top_builddir)/libs/gst/net/libgstnet-@GST_API_VERSION@.la \ + $(GST_OBJ_LIBS) \ + $(GIO_LIBS) + +netclock_replay_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/misc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tests/misc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +netclock-replay$(EXEEXT): $(netclock_replay_OBJECTS) $(netclock_replay_DEPENDENCIES) $(EXTRA_netclock_replay_DEPENDENCIES) + @rm -f netclock-replay$(EXEEXT) + $(AM_V_CCLD)$(netclock_replay_LINK) $(netclock_replay_OBJECTS) $(netclock_replay_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netclock_replay-netclock-replay.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +netclock_replay-netclock-replay.o: netclock-replay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_replay_CFLAGS) $(CFLAGS) -MT netclock_replay-netclock-replay.o -MD -MP -MF $(DEPDIR)/netclock_replay-netclock-replay.Tpo -c -o netclock_replay-netclock-replay.o `test -f 'netclock-replay.c' || echo '$(srcdir)/'`netclock-replay.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_replay-netclock-replay.Tpo $(DEPDIR)/netclock_replay-netclock-replay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-replay.c' object='netclock_replay-netclock-replay.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_replay_CFLAGS) $(CFLAGS) -c -o netclock_replay-netclock-replay.o `test -f 'netclock-replay.c' || echo '$(srcdir)/'`netclock-replay.c + +netclock_replay-netclock-replay.obj: netclock-replay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_replay_CFLAGS) $(CFLAGS) -MT netclock_replay-netclock-replay.obj -MD -MP -MF $(DEPDIR)/netclock_replay-netclock-replay.Tpo -c -o netclock_replay-netclock-replay.obj `if test -f 'netclock-replay.c'; then $(CYGPATH_W) 'netclock-replay.c'; else $(CYGPATH_W) '$(srcdir)/netclock-replay.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netclock_replay-netclock-replay.Tpo $(DEPDIR)/netclock_replay-netclock-replay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netclock-replay.c' object='netclock_replay-netclock-replay.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netclock_replay_CFLAGS) $(CFLAGS) -c -o netclock_replay-netclock-replay.obj `if test -f 'netclock-replay.c'; then $(CYGPATH_W) 'netclock-replay.c'; else $(CYGPATH_W) '$(srcdir)/netclock-replay.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/misc/meson.build b/tests/misc/meson.build new file mode 100644 index 0000000..eedfdc7 --- /dev/null +++ b/tests/misc/meson.build @@ -0,0 +1,2 @@ +executable('netclock-replay', 'netclock-replay.c', + dependencies : [gio_dep, gst_dep, gst_net_dep]) diff --git a/tests/misc/netclock-replay.c b/tests/misc/netclock-replay.c new file mode 100644 index 0000000..f5dd67d --- /dev/null +++ b/tests/misc/netclock-replay.c @@ -0,0 +1,138 @@ +/* GStreamer + * Copyright (C) 2016 Centricular Ltd. + * Author: Arun Raghavan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* We need the internal netclock estimation function to (re)run the code on + * captured samples, plus its dependencies for the build to succeed. */ +#include "../../libs/gst/net/gstntppacket.c" +#include "../../libs/gst/net/gstnetclientclock.c" +#include "../../libs/gst/net/gstnetutils.c" + +static gchar *input = NULL; +static gboolean debug = FALSE; +static gint rtt_limit = 0; + +static GOptionEntry entries[] = { + {"input", 'i', 0, G_OPTION_ARG_FILENAME, &input, + "Clock reading file containing one local and remote time readings, one " + "per line", + "FILE"}, + {"rtt-limit", 'r', 0, G_OPTION_ARG_INT64, &rtt_limit, + "Round trip time limit on packets (in ms)", "MSEC"}, + {"debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Verbose debug output", NULL}, + {NULL,} +}; + +int +main (int argc, char *argv[]) +{ + GstNetClientInternalClock *clock; + GstBus *bus; + GIOChannel *channel; + GIOStatus status; + GError *error = NULL; + GOptionContext *context; + gchar *line; + int ret = 1; + + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_add_group (context, gst_init_get_option_group ()); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Failed to parse options: %s\n\n", error->message); + g_error_free (error); + return 1; + } + + if (input) { + if (!(channel = g_io_channel_new_file (input, "r", NULL))) { + g_print ("Could not read input file: %s\n", input); + return 1; + } + } else { + if (!(channel = g_io_channel_unix_new (0))) { + g_print ("Could not read stdin"); + return 1; + } + } + + clock = g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, NULL); + bus = gst_bus_new (); + + /* FIXME: Find a way to do this without touching the structure internals */ + if (rtt_limit) + clock->roundtrip_limit = rtt_limit * GST_MSECOND; + clock->busses = g_list_prepend (clock->busses, bus); + + while ((status = g_io_channel_read_line (channel, &line, NULL, NULL, + &error)) == G_IO_STATUS_NORMAL) { + GstClockTime local_1, local_2, remote_1, remote_2; + GstMessage *message; + + if (sscanf (line, "%" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" + G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, &local_1, &remote_1, + &remote_2, &local_2) != 4) { + g_print ("Failed to get local/remote time values from: %s\n", line); + goto done; + } + + if (debug) + g_print ("%s", line); + + gst_net_client_internal_clock_observe_times (clock, local_1, remote_1, + remote_2, local_2); + + g_free (line); + + if ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT))) { + const GstStructure *st; + gchar *str; + + st = gst_message_get_structure (message); + str = gst_structure_to_string (st); + + g_print ("%s\n", str); + + g_free (str); + gst_message_unref (message); + } + } + + if (status == G_IO_CHANNEL_ERROR) { + g_print ("Error reading file: %s\n", error->message); + g_error_free (error); + goto done; + } + + g_io_channel_unref (channel); + g_free (input); + gst_object_unref (bus); + + ret = 0; + +done: + return ret; +} diff --git a/tests/misc/network-clock-utils.scm b/tests/misc/network-clock-utils.scm new file mode 100644 index 0000000..1a71e32 --- /dev/null +++ b/tests/misc/network-clock-utils.scm @@ -0,0 +1,229 @@ +;; GStreamer +;; Copyright (C) 2005 Andy Wingo + +;; 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, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 51 Franklin St, Fifth Floor Fax: +1-617-542-2652 +;; Boston, MA 02110-1301, USA gnu@gnu.org + + +;;; Commentary: +;; +;; Utilities for the network clock simulator. +;; +;;; Code: + + +;; Init the rng. + +(use-modules ((srfi srfi-1) (fold unfold))) + +(define (read-bytes-from-file-as-integer f n) + (with-input-from-file f + (lambda () + (fold (lambda (x seed) (+ x (ash seed 8))) + 0 + (unfold zero? (lambda (n) (char->integer (read-char))) 1- n))))) + +(set! *random-state* (seed->random-state + (read-bytes-from-file-as-integer "/dev/random" 4))) + +;; General utilities. + +(define (iround x) + (if (inexact? x) + (inexact->exact (round x)) + x)) + +(define (filter proc l) + (cond + ((null? l) '()) + ((proc (car l)) (cons (car l) (filter proc (cdr l)))) + (else (filter proc (cdr l))))) + +(define (sum l) + (apply + l)) + +(define (avg . nums) + (/ (sum nums) (length nums))) + +(define (sq x) + (* x x)) + +(define (debug str . args) + (if *debug* + (apply format (current-error-port) str args))) + +(define (print-event kind x y) + (format #t "~a ~a ~a\n" kind x y)) + +;; Linear least squares. +;; +;; See http://mathworld.wolfram.com/LeastSquaresFitting.html +;; returns (values slope intercept r-squared) + +(define (least-squares x y) + (let ((n (length x))) + (let ((xbar (apply avg x)) + (ybar (apply avg y))) + (let ((sxx (- (sum (map sq x)) (* n (sq xbar)))) + (syy (- (sum (map sq y)) (* n (sq ybar)))) + (sxy (- (sum (map * x y)) (* n xbar ybar)))) + (let ((slope (/ sxy sxx))) + (values + slope + (- ybar (* slope xbar)) + (/ (sq sxy) (* sxx syy)))))))) + +;; Streams: lists with lazy cdrs. + +(define-macro (stream-cons kar kdr) + `(cons ,kar (delay ,kdr))) + +(define (stream-cdr stream) + (force (cdr stream))) + +(define (stream-car stream) + (car stream)) + +(define (stream-null? stream) + (null? stream)) + +(define (stream-ref stream n) + (if (zero? n) + (stream-car stream) + (stream-ref (stream-cdr stream) (1- n)))) + +(define (stream->list stream n) + (let lp ((in stream) (out '()) (n n)) + (if (zero? n) + (reverse! out) + (lp (stream-cdr in) (cons (stream-car in) out) (1- n))))) + +(define (stream-skip stream n) + (if (zero? n) + stream + (stream-skip (stream-cdr stream) (1- n)))) + +(define (stream-sample stream n) + (stream-cons (stream-car stream) + (stream-sample (stream-skip stream n) n))) + +(define (stream-map proc . streams) + (stream-cons (apply proc (map stream-car streams)) + (apply stream-map proc (map stream-cdr streams)))) + +(define (arithmetic-series start step) + (stream-cons start (arithmetic-series (+ start step) step))) + +(define (scale-stream stream factor) + (stream-map (lambda (t) (* t factor)) stream)) + +(define (stream-while pred proc . streams) + (if (apply pred (map stream-car streams)) + (begin + (apply proc (map stream-car streams)) + (apply stream-while pred proc (map stream-cdr streams))))) + +(define (stream-of val) + (stream-cons val (stream-of val))) + +(define (periodic-stream val period) + (let ((period (iround (max 1 (* *sample-frequency* period))))) + (let lp ((n 0)) + (if (zero? n) + (stream-cons val (lp period)) + (stream-cons #f (lp (1- n))))))) + + +;; Queues with a maximum length. + +(define (make-q l) + (cons l (last-pair l))) + +(define (q-head q) + (car q)) + +(define (q-tail q) + (car q)) + +(define (q-push q val) + (let ((tail (cons val '()))) + (if (null? (q-tail q)) + (make-q tail) + (let ((l (append! (q-head q) tail))) + (if (> (length (q-head q)) *window-size*) + (make-q (cdr (q-head q))) + q))))) + + +;; Parameters, settable via command line arguments. + +(define %parameters '()) +(define-macro (define-parameter name val) + (let ((str (symbol->string name))) + (or (and (eqv? (string-ref str 0) #\*) + (eqv? (string-ref str (1- (string-length str))) #\*)) + (error "Invalid parameter name" name)) + (let ((param (string->symbol + (substring str 1 (1- (string-length str))))) + (val-sym (gensym))) + `(begin + (define ,name #f) + (let ((,val-sym ,val)) + (set! ,name ,val-sym) + (set! %parameters (cons (cons ',param ,val-sym) + %parameters))))))) +(define (set-parameter! name val) + (define (symbol-append . args) + (string->symbol (apply string-append (map symbol->string args)))) + (or (assq name %parameters) + (error "Unknown parameter" name)) + (module-set! (current-module) (symbol-append '* name '*) val)) + +(define (parse-parameter-arguments args) + (define (usage) + (format #t "Usage: ~a ARG1...\n\n" "network-clock.scm") + (for-each + (lambda (pair) + (format #t "\t--~a=VAL \t(default: ~a)\n" (car pair) (cdr pair))) + %parameters)) + (define (unknown-arg arg) + (with-output-to-port (current-error-port) + (lambda () + (format #t "\nUnknown argument: ~a\n\n" arg) + (usage) + (quit)))) + (define (parse-arguments args) + (let lp ((in args) (out '())) + (cond + ((null? in) + (reverse! out)) + ((not (string=? (substring (car in) 0 2) "--")) + (unknown-arg (car in))) + (else + (let ((divider (or (string-index (car in) #\=) + (unknown-arg (car in))))) + (or (> divider 2) (unknown-arg (car in))) + (let ((param (string->symbol (substring (car in) 2 divider))) + (val (with-input-from-string (substring (car in) (1+ divider)) + read))) + (lp (cdr in) (acons param val out)))))))) + (for-each + (lambda (pair) + (or (false-if-exception + (set-parameter! (car pair) (cdr pair))) + (unknown-arg (format #f "--~a=~a" (car pair) (cdr pair))))) + (parse-arguments args))) diff --git a/tests/misc/network-clock.scm b/tests/misc/network-clock.scm new file mode 100755 index 0000000..cd21bef --- /dev/null +++ b/tests/misc/network-clock.scm @@ -0,0 +1,205 @@ +#!/bin/bash +# -*- scheme -*- +exec guile --debug -l $0 -e main -- "$@" +!# + +;; GStreamer +;; Copyright (C) 2005 Andy Wingo + +;; 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, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 51 Franklin St, Fifth Floor Fax: +1-617-542-2652 +;; Boston, MA 02110-1301, USA gnu@gnu.org + + +;;; Commentary: +;; +;; Network clock simulator. +;; +;; Simulates the attempts of one clock to synchronize with another over +;; the network. Packets are sent out with a local timestamp, and come +;; back with the remote time added on to the packet. The remote time is +;; assumed to have been observed at the local time in between sending +;; the query and receiving the reply. +;; +;; The local clock will attempt to adjust its rate and offset by fitting +;; a line to the last N datapoints on hand, by default 32. A better fit, +;; as measured by the correlation coefficient, will result in a longer +;; time before the next query. Bad fits or a not-yet-full set of data +;; will result in many queries in quick succession. +;; +;; The rate and offset are set directly to the slope and intercept from +;; the linear regression. This results in discontinuities in the local +;; time. As clock times must be monotonically increasing, a jump down in +;; time will result instead in time standing still for a while. Smoothly +;; varying the rate such that no discontinuities are present has not +;; been investigated. +;; +;; Implementation-wise, this simulator processes events and calculates +;; times discretely. Times are represented as streams, also known as +;; lazy lists. This is an almost-pure functional simulator. The thing to +;; remember while reading is that stream-cons does not evaluate its +;; second argument, rather deferring that calculation until stream-cdr +;; is called. In that way all times are actually infinite series. +;; +;; Usage: See network-clock.scm --help. +;; +;;; Code: + + +(use-modules (ice-9 popen)) + + +(load "network-clock-utils.scm") + + +(define (time->samples t) + (iround (* t *sample-frequency*))) + + +(define (schedule-event events e time) + (let lp ((response-time (time->samples time)) + (stream events)) + (if (zero? response-time) + (if (not (stream-car stream)) + (stream-cons e (stream-cdr stream)) + (stream-cons (stream-car stream) (lp 0 (stream-cdr stream)))) + (stream-cons (stream-car stream) (lp (1- response-time) (stream-cdr stream)))))) + +(define (schedule-send-time-query events time) + (schedule-event events (list 'send-time-query) time)) + +(define (schedule-time-query events l) + (schedule-event events (list 'time-query l) + (+ *send-delay* (random *send-jitter*)))) + +(define (schedule-time-response events l r) + (schedule-event events (list 'time-response l r) + (+ *recv-delay* (random *recv-jitter*)))) + +(define (network-time remote-time local-time events m b x y t) + (let ((r (stream-car remote-time)) + (l (stream-car local-time)) + (event (stream-car events)) + (events (stream-cdr events))) + + (define (next events m b x y t) + (stream-cons + (+ (* m l) b) + (network-time + (stream-cdr remote-time) (stream-cdr local-time) events m b x y t))) + + (case (and=> event car) + ((send-time-query) + (cond + ((< (random 1.0) *packet-loss*) + (debug "; dropped time query: ~a\n" l) + (print-event 'packet-lost l (+ (* m l) b)) + (next events m b x y (time->samples *timeout*))) + (else + (debug "; sending time query: ~a\n" l) + (print-event 'packet-sent l (+ (* m l) b)) + (next (schedule-time-query events l) m b x y (time->samples *timeout*))))) + + ((time-query) + (debug "; time query received, replying with ~a\n" r) + (next (schedule-time-response events (cadr event) r) m b x y (and t (1- t)))) + + ((time-response) + (let ((x (q-push x (avg (cadr event) l))) + (y (q-push y (caddr event)))) + (call-with-values + (lambda () (least-squares (q-head x) (q-head y))) + (lambda (m b r-squared) + (define (next-time) + (max + (if (< (length (q-head x)) *window-size*) + 0 + (/ 1 (- 1 (min r-squared 0.99999)) 1000)) + 0.10)) + (debug "; new slope and offset: ~a ~a (~a)\n" m b r-squared) + (print-event 'packet-observed (avg (cadr event) l) (caddr event)) + (print-event 'packet-received l (+ (* m l) b)) + (next (schedule-send-time-query events (next-time)) m b x y #f))))) + + (else + (cond + ((not t) + ;; not waiting for a response + (next events m b x y t)) + ((<= t 0) + ;; we timed out + (next (schedule-send-time-query events 0.0) m b x y 0)) + (else + (next events m b x y (1- t)))))))) + +(define (run-simulation remote-speed local-speed) + (let ((absolute-time (arithmetic-series 0.0 (/ 1.0 *sample-frequency*))) + (event-stream (stream-of #f))) + (let ((remote-time (scale-stream absolute-time remote-speed)) + (local-time (scale-stream absolute-time local-speed))) + (values + absolute-time + remote-time + local-time + (network-time + remote-time + local-time + (schedule-send-time-query event-stream 0.0) + 1.0 + (stream-car local-time) + (make-q (list (stream-car local-time))) + (make-q (list (stream-car remote-time))) + #f))))) + +(define (print-simulation) + (display "Absolute time; Remote time; Local time; Network time\n") + (call-with-values + (lambda () (run-simulation *remote-rate* *local-rate*)) + (lambda streams + (apply + stream-while + (lambda (a r l n) (<= a *total-time*)) + (lambda (a r l n) (format #t "~a ~a ~a ~a\n" a r l n)) + streams)))) + +(define (plot-simulation) + (let ((port (open-output-pipe "./plot-data Network Clock Simulation"))) + (with-output-to-port port + print-simulation) + (close-pipe port))) + + +(define-parameter *sample-frequency* 40) +(define-parameter *send-delay* 0.1) +(define-parameter *recv-delay* 0.1) +(define-parameter *packet-loss* 0.01) +(define-parameter *send-jitter* 0.1) +(define-parameter *recv-jitter* 0.1) +(define-parameter *window-size* 32) +(define-parameter *local-rate* 1.0) +(define-parameter *remote-rate* 1.1) +(define-parameter *total-time* 5.0) +(define-parameter *timeout* 1.0) +(define-parameter *debug* #f) +(define-parameter *with-graph* #t) + + +(define (main args) + (parse-parameter-arguments (cdr args)) + (if *with-graph* + (plot-simulation) + (print-simulation)) + (quit)) diff --git a/tests/misc/plot-data b/tests/misc/plot-data new file mode 100755 index 0000000..6627a66 --- /dev/null +++ b/tests/misc/plot-data @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +from __future__ import division + +import pylab +import optparse +import sys + +def parse_data(l, state): + state['data'].append([float(x) for x in filter(None, l.split(' '))]) + return state + +def parse_event(l, state): + components = filter(None, l.split(' ')) + vals = [float(x) for x in components[1:]] + if not components[0] in state: + state[components[0]] = [vals] + else: + state[components[0]].append(vals) + return state + +def read_line(fd, state): + l = fd.readline() + if not l: + return None + l = l.strip() + if l[0].isdigit(): + return parse_data(l, state) + else: + return parse_event(l, state) + +def read_data(fd): + state = {'data':[], + 'packet-sent':[], + 'packet-lost':[], + 'packet-received':[], + 'packet-observed':[]} + newstate = state + while newstate: + state = newstate + newstate = read_line(fd, state) + return state + +def make_xticks(start, end, numticks): + return range(int(start), int(end), int((start-end)/numticks)) + +def make_plot(title): + l = sys.stdin.readline() + labels = l.strip().split(';') + state = read_data(sys.stdin) + data = state['data'] + lost_packets = state['packet-lost'] + obsv_packets = state['packet-observed'] + sent_packets = state['packet-sent'] + recd_packets = state['packet-received'] + + domain = [x[0] for x in data] + for i in range(1,len(labels)): + pylab.plot(domain, [x[i] for x in data], label=labels[i]) + pylab.plot([x[0] for x in lost_packets], [x[1] for x in lost_packets], + label='Client sent packet, but dropped', marker='x', linestyle=None, ms=8) + pylab.plot([x[0] for x in sent_packets], [x[1] for x in sent_packets], + label='Client sent packet', marker='^', linestyle=None, ms=8) + pylab.plot([x[0] for x in obsv_packets], [x[1] for x in obsv_packets], + label='Remote time observation', marker='D', linestyle=None, ms=8) + pylab.plot([x[0] for x in recd_packets], [x[1] for x in recd_packets], + label='Client received packet', marker='v', linestyle=None, ms=8) + pylab.legend() + pylab.ylabel(r'Clock time (s)') + pylab.xlabel(r'Real time (s)') + pylab.title(title) + pylab.grid(True) + pylab.show() + +def main(args): + parser = optparse.OptionParser() + + title = ' '.join(args[1:]) + make_plot(title) + +main(sys.argv) diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..caa5ab6 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,48 @@ + +bin_PROGRAMS = \ + gst-inspect-@GST_API_VERSION@ \ + gst-stats-@GST_API_VERSION@ \ + gst-typefind-@GST_API_VERSION@ + +gst_inspect_@GST_API_VERSION@_SOURCES = gst-inspect.c tools.h +gst_inspect_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_inspect_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) + +gst_stats_@GST_API_VERSION@_SOURCES = gst-stats.c tools.h +gst_stats_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_stats_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) + +gst_typefind_@GST_API_VERSION@_SOURCES = gst-typefind.c tools.h +gst_typefind_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_typefind_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) + +if !GST_DISABLE_PARSE +bin_PROGRAMS += gst-launch-@GST_API_VERSION@ + +gst_launch_@GST_API_VERSION@_SOURCES = gst-launch.c tools.h +gst_launch_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_launch_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) +endif + +manpages = \ + gst-inspect-@GST_API_VERSION@.1 \ + gst-stats-@GST_API_VERSION@.1 \ + gst-typefind-@GST_API_VERSION@.1 + +if !GST_DISABLE_PARSE +manpages += gst-launch-@GST_API_VERSION@.1 +endif + +man_MANS = $(manpages) + +# developer helper tools, not meant for installation +noinst_SCRIPTS = gst-indent + +noinst_HEADERS = tools.h + +EXTRA_DIST = \ + gst-inspect-@GST_API_VERSION@.1 \ + gst-typefind-@GST_API_VERSION@.1 \ + gst-launch-@GST_API_VERSION@.1 \ + gst-stats-@GST_API_VERSION@.1 \ + $(noinst_SCRIPTS) diff --git a/tools/Makefile.in b/tools/Makefile.in new file mode 100644 index 0000000..b2fa94d --- /dev/null +++ b/tools/Makefile.in @@ -0,0 +1,1048 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = gst-inspect-@GST_API_VERSION@$(EXEEXT) \ + gst-stats-@GST_API_VERSION@$(EXEEXT) \ + gst-typefind-@GST_API_VERSION@$(EXEEXT) $(am__EXEEXT_1) +@GST_DISABLE_PARSE_FALSE@am__append_1 = gst-launch-@GST_API_VERSION@ +@GST_DISABLE_PARSE_FALSE@am__append_2 = gst-launch-@GST_API_VERSION@.1 +subdir = tools +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-libtool.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/ax_pthread.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-function.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-parser.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/introspection.m4 \ + $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@GST_DISABLE_PARSE_FALSE@am__EXEEXT_1 = gst-launch-@GST_API_VERSION@$(EXEEXT) +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +PROGRAMS = $(bin_PROGRAMS) +am_gst_inspect_@GST_API_VERSION@_OBJECTS = \ + gst_inspect_@GST_API_VERSION@-gst-inspect.$(OBJEXT) +gst_inspect_@GST_API_VERSION@_OBJECTS = \ + $(am_gst_inspect_@GST_API_VERSION@_OBJECTS) +am__DEPENDENCIES_1 = +gst_inspect_@GST_API_VERSION@_DEPENDENCIES = $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +gst_inspect_@GST_API_VERSION@_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_inspect_@GST_API_VERSION@_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am__gst_launch_@GST_API_VERSION@_SOURCES_DIST = gst-launch.c tools.h +@GST_DISABLE_PARSE_FALSE@am_gst_launch_@GST_API_VERSION@_OBJECTS = gst_launch_@GST_API_VERSION@-gst-launch.$(OBJEXT) +gst_launch_@GST_API_VERSION@_OBJECTS = \ + $(am_gst_launch_@GST_API_VERSION@_OBJECTS) +@GST_DISABLE_PARSE_FALSE@gst_launch_@GST_API_VERSION@_DEPENDENCIES = \ +@GST_DISABLE_PARSE_FALSE@ $(am__DEPENDENCIES_1) +gst_launch_@GST_API_VERSION@_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_launch_@GST_API_VERSION@_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_gst_stats_@GST_API_VERSION@_OBJECTS = \ + gst_stats_@GST_API_VERSION@-gst-stats.$(OBJEXT) +gst_stats_@GST_API_VERSION@_OBJECTS = \ + $(am_gst_stats_@GST_API_VERSION@_OBJECTS) +gst_stats_@GST_API_VERSION@_DEPENDENCIES = $(am__DEPENDENCIES_1) +gst_stats_@GST_API_VERSION@_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_stats_@GST_API_VERSION@_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_gst_typefind_@GST_API_VERSION@_OBJECTS = \ + gst_typefind_@GST_API_VERSION@-gst-typefind.$(OBJEXT) +gst_typefind_@GST_API_VERSION@_OBJECTS = \ + $(am_gst_typefind_@GST_API_VERSION@_OBJECTS) +gst_typefind_@GST_API_VERSION@_DEPENDENCIES = $(am__DEPENDENCIES_1) +gst_typefind_@GST_API_VERSION@_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gst_typefind_@GST_API_VERSION@_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(gst_inspect_@GST_API_VERSION@_SOURCES) \ + $(gst_launch_@GST_API_VERSION@_SOURCES) \ + $(gst_stats_@GST_API_VERSION@_SOURCES) \ + $(gst_typefind_@GST_API_VERSION@_SOURCES) +DIST_SOURCES = $(gst_inspect_@GST_API_VERSION@_SOURCES) \ + $(am__gst_launch_@GST_API_VERSION@_SOURCES_DIST) \ + $(gst_stats_@GST_API_VERSION@_SOURCES) \ + $(gst_typefind_@GST_API_VERSION@_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH_COMPLETION_CFLAGS = @BASH_COMPLETION_CFLAGS@ +BASH_COMPLETION_DIR = @BASH_COMPLETION_DIR@ +BASH_COMPLETION_LIBS = @BASH_COMPLETION_LIBS@ +BASH_HELPERS_DIR = @BASH_HELPERS_DIR@ +BISON_PATH = @BISON_PATH@ +CAP_LIBS = @CAP_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ +CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ +CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ +CHECK_VERSION = @CHECK_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DW_CFLAGS = @DW_CFLAGS@ +DW_LIBS = @DW_LIBS@ +DW_REQUIRE = @DW_REQUIRE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLEX_PATH = @FLEX_PATH@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSL_LIBS = @GSL_LIBS@ +GSTCONFIG_BUILT_WITH_MSVC = @GSTCONFIG_BUILT_WITH_MSVC@ +GST_AGE = @GST_AGE@ +GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ +GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ +GST_COMPLETION_HELPER_INSTALLED = @GST_COMPLETION_HELPER_INSTALLED@ +GST_CURRENT = @GST_CURRENT@ +GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ +GST_DISABLE_GST_TRACER_HOOKS_DEFINE = @GST_DISABLE_GST_TRACER_HOOKS_DEFINE@ +GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ +GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ +GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ +GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ +GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ +GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBVERSION = @GST_LIBVERSION@ +GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ +GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ +GST_OBJ_LIBS = @GST_OBJ_LIBS@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ +GST_PTP_HELPER_INSTALLED = @GST_PTP_HELPER_INSTALLED@ +GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ +GST_REVISION = @GST_REVISION@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_CAP = @HAVE_CAP@ +HAVE_FORK = @HAVE_FORK@ +HAVE_GMP = @HAVE_GMP@ +HAVE_GSL = @HAVE_GSL@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_INIT = @INTROSPECTION_INIT@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL_PATH = @PERL_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PRINTF_CFLAGS = @PRINTF_CFLAGS@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SETCAP = @SETCAP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +UNWIND_CFLAGS = @UNWIND_CFLAGS@ +UNWIND_LIBS = @UNWIND_LIBS@ +UNWIND_REQUIRE = @UNWIND_REQUIRE@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WIN32_LIBS = @WIN32_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +gst_inspect_@GST_API_VERSION@_SOURCES = gst-inspect.c tools.h +gst_inspect_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_inspect_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) +gst_stats_@GST_API_VERSION@_SOURCES = gst-stats.c tools.h +gst_stats_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_stats_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) +gst_typefind_@GST_API_VERSION@_SOURCES = gst-typefind.c tools.h +gst_typefind_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +gst_typefind_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) +@GST_DISABLE_PARSE_FALSE@gst_launch_@GST_API_VERSION@_SOURCES = gst-launch.c tools.h +@GST_DISABLE_PARSE_FALSE@gst_launch_@GST_API_VERSION@_CFLAGS = $(GST_OBJ_CFLAGS) +@GST_DISABLE_PARSE_FALSE@gst_launch_@GST_API_VERSION@_LDADD = $(GST_OBJ_LIBS) +manpages = gst-inspect-@GST_API_VERSION@.1 \ + gst-stats-@GST_API_VERSION@.1 gst-typefind-@GST_API_VERSION@.1 \ + $(am__append_2) +man_MANS = $(manpages) + +# developer helper tools, not meant for installation +noinst_SCRIPTS = gst-indent +noinst_HEADERS = tools.h +EXTRA_DIST = \ + gst-inspect-@GST_API_VERSION@.1 \ + gst-typefind-@GST_API_VERSION@.1 \ + gst-launch-@GST_API_VERSION@.1 \ + gst-stats-@GST_API_VERSION@.1 \ + $(noinst_SCRIPTS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tools/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +gst-inspect-@GST_API_VERSION@$(EXEEXT): $(gst_inspect_@GST_API_VERSION@_OBJECTS) $(gst_inspect_@GST_API_VERSION@_DEPENDENCIES) $(EXTRA_gst_inspect_@GST_API_VERSION@_DEPENDENCIES) + @rm -f gst-inspect-@GST_API_VERSION@$(EXEEXT) + $(AM_V_CCLD)$(gst_inspect_@GST_API_VERSION@_LINK) $(gst_inspect_@GST_API_VERSION@_OBJECTS) $(gst_inspect_@GST_API_VERSION@_LDADD) $(LIBS) + +gst-launch-@GST_API_VERSION@$(EXEEXT): $(gst_launch_@GST_API_VERSION@_OBJECTS) $(gst_launch_@GST_API_VERSION@_DEPENDENCIES) $(EXTRA_gst_launch_@GST_API_VERSION@_DEPENDENCIES) + @rm -f gst-launch-@GST_API_VERSION@$(EXEEXT) + $(AM_V_CCLD)$(gst_launch_@GST_API_VERSION@_LINK) $(gst_launch_@GST_API_VERSION@_OBJECTS) $(gst_launch_@GST_API_VERSION@_LDADD) $(LIBS) + +gst-stats-@GST_API_VERSION@$(EXEEXT): $(gst_stats_@GST_API_VERSION@_OBJECTS) $(gst_stats_@GST_API_VERSION@_DEPENDENCIES) $(EXTRA_gst_stats_@GST_API_VERSION@_DEPENDENCIES) + @rm -f gst-stats-@GST_API_VERSION@$(EXEEXT) + $(AM_V_CCLD)$(gst_stats_@GST_API_VERSION@_LINK) $(gst_stats_@GST_API_VERSION@_OBJECTS) $(gst_stats_@GST_API_VERSION@_LDADD) $(LIBS) + +gst-typefind-@GST_API_VERSION@$(EXEEXT): $(gst_typefind_@GST_API_VERSION@_OBJECTS) $(gst_typefind_@GST_API_VERSION@_DEPENDENCIES) $(EXTRA_gst_typefind_@GST_API_VERSION@_DEPENDENCIES) + @rm -f gst-typefind-@GST_API_VERSION@$(EXEEXT) + $(AM_V_CCLD)$(gst_typefind_@GST_API_VERSION@_LINK) $(gst_typefind_@GST_API_VERSION@_OBJECTS) $(gst_typefind_@GST_API_VERSION@_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +gst_inspect_@GST_API_VERSION@-gst-inspect.o: gst-inspect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_inspect_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_inspect_@GST_API_VERSION@-gst-inspect.o -MD -MP -MF $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Tpo -c -o gst_inspect_@GST_API_VERSION@-gst-inspect.o `test -f 'gst-inspect.c' || echo '$(srcdir)/'`gst-inspect.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Tpo $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-inspect.c' object='gst_inspect_@GST_API_VERSION@-gst-inspect.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_inspect_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_inspect_@GST_API_VERSION@-gst-inspect.o `test -f 'gst-inspect.c' || echo '$(srcdir)/'`gst-inspect.c + +gst_inspect_@GST_API_VERSION@-gst-inspect.obj: gst-inspect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_inspect_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_inspect_@GST_API_VERSION@-gst-inspect.obj -MD -MP -MF $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Tpo -c -o gst_inspect_@GST_API_VERSION@-gst-inspect.obj `if test -f 'gst-inspect.c'; then $(CYGPATH_W) 'gst-inspect.c'; else $(CYGPATH_W) '$(srcdir)/gst-inspect.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Tpo $(DEPDIR)/gst_inspect_@GST_API_VERSION@-gst-inspect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-inspect.c' object='gst_inspect_@GST_API_VERSION@-gst-inspect.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_inspect_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_inspect_@GST_API_VERSION@-gst-inspect.obj `if test -f 'gst-inspect.c'; then $(CYGPATH_W) 'gst-inspect.c'; else $(CYGPATH_W) '$(srcdir)/gst-inspect.c'; fi` + +gst_launch_@GST_API_VERSION@-gst-launch.o: gst-launch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_launch_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_launch_@GST_API_VERSION@-gst-launch.o -MD -MP -MF $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Tpo -c -o gst_launch_@GST_API_VERSION@-gst-launch.o `test -f 'gst-launch.c' || echo '$(srcdir)/'`gst-launch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Tpo $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-launch.c' object='gst_launch_@GST_API_VERSION@-gst-launch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_launch_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_launch_@GST_API_VERSION@-gst-launch.o `test -f 'gst-launch.c' || echo '$(srcdir)/'`gst-launch.c + +gst_launch_@GST_API_VERSION@-gst-launch.obj: gst-launch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_launch_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_launch_@GST_API_VERSION@-gst-launch.obj -MD -MP -MF $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Tpo -c -o gst_launch_@GST_API_VERSION@-gst-launch.obj `if test -f 'gst-launch.c'; then $(CYGPATH_W) 'gst-launch.c'; else $(CYGPATH_W) '$(srcdir)/gst-launch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Tpo $(DEPDIR)/gst_launch_@GST_API_VERSION@-gst-launch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-launch.c' object='gst_launch_@GST_API_VERSION@-gst-launch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_launch_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_launch_@GST_API_VERSION@-gst-launch.obj `if test -f 'gst-launch.c'; then $(CYGPATH_W) 'gst-launch.c'; else $(CYGPATH_W) '$(srcdir)/gst-launch.c'; fi` + +gst_stats_@GST_API_VERSION@-gst-stats.o: gst-stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_stats_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_stats_@GST_API_VERSION@-gst-stats.o -MD -MP -MF $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Tpo -c -o gst_stats_@GST_API_VERSION@-gst-stats.o `test -f 'gst-stats.c' || echo '$(srcdir)/'`gst-stats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Tpo $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-stats.c' object='gst_stats_@GST_API_VERSION@-gst-stats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_stats_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_stats_@GST_API_VERSION@-gst-stats.o `test -f 'gst-stats.c' || echo '$(srcdir)/'`gst-stats.c + +gst_stats_@GST_API_VERSION@-gst-stats.obj: gst-stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_stats_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_stats_@GST_API_VERSION@-gst-stats.obj -MD -MP -MF $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Tpo -c -o gst_stats_@GST_API_VERSION@-gst-stats.obj `if test -f 'gst-stats.c'; then $(CYGPATH_W) 'gst-stats.c'; else $(CYGPATH_W) '$(srcdir)/gst-stats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Tpo $(DEPDIR)/gst_stats_@GST_API_VERSION@-gst-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-stats.c' object='gst_stats_@GST_API_VERSION@-gst-stats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_stats_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_stats_@GST_API_VERSION@-gst-stats.obj `if test -f 'gst-stats.c'; then $(CYGPATH_W) 'gst-stats.c'; else $(CYGPATH_W) '$(srcdir)/gst-stats.c'; fi` + +gst_typefind_@GST_API_VERSION@-gst-typefind.o: gst-typefind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_typefind_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_typefind_@GST_API_VERSION@-gst-typefind.o -MD -MP -MF $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Tpo -c -o gst_typefind_@GST_API_VERSION@-gst-typefind.o `test -f 'gst-typefind.c' || echo '$(srcdir)/'`gst-typefind.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Tpo $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-typefind.c' object='gst_typefind_@GST_API_VERSION@-gst-typefind.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_typefind_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_typefind_@GST_API_VERSION@-gst-typefind.o `test -f 'gst-typefind.c' || echo '$(srcdir)/'`gst-typefind.c + +gst_typefind_@GST_API_VERSION@-gst-typefind.obj: gst-typefind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_typefind_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -MT gst_typefind_@GST_API_VERSION@-gst-typefind.obj -MD -MP -MF $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Tpo -c -o gst_typefind_@GST_API_VERSION@-gst-typefind.obj `if test -f 'gst-typefind.c'; then $(CYGPATH_W) 'gst-typefind.c'; else $(CYGPATH_W) '$(srcdir)/gst-typefind.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Tpo $(DEPDIR)/gst_typefind_@GST_API_VERSION@-gst-typefind.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gst-typefind.c' object='gst_typefind_@GST_API_VERSION@-gst-typefind.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gst_typefind_@GST_API_VERSION@_CFLAGS) $(CFLAGS) -c -o gst_typefind_@GST_API_VERSION@-gst-typefind.obj `if test -f 'gst-typefind.c'; then $(CYGPATH_W) 'gst-typefind.c'; else $(CYGPATH_W) '$(srcdir)/gst-typefind.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-man1 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-man uninstall-man1 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tools/gst-indent b/tools/gst-indent new file mode 100755 index 0000000..a9b8bfe --- /dev/null +++ b/tools/gst-indent @@ -0,0 +1,45 @@ +#!/bin/sh + +for execname in gnuindent gindent indent; do + version=`$execname --version 2>/dev/null` + if test "x$version" != "x"; then + INDENT=$execname + break + fi +done + +if test -z $INDENT; then + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + exit 1 +fi + +case `$INDENT --version` in + GNU*) + ;; + default) + 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 + +# Run twice. GNU indent isn't idempotent +# when run once +for i in 1 2; do +$INDENT \ + --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 \ + $* || exit $? +done diff --git a/tools/gst-inspect-1.0.1 b/tools/gst-inspect-1.0.1 new file mode 100644 index 0000000..1f16200 --- /dev/null +++ b/tools/gst-inspect-1.0.1 @@ -0,0 +1,81 @@ +.TH GStreamer 1 "December 2005" +.SH "NAME" +gst\-inspect\-1.0 \- print info about a GStreamer plugin or element +.SH "SYNOPSIS" +.B gst\-inspect\-1.0 [OPTION...] [PLUGIN|ELEMENT] +.SH "DESCRIPTION" +.PP +\fIgst\-inspect\-1.0\fP is a tool that prints out information on +available \fIGStreamer\fP plugins, information about a particular +plugin, or information about a particular element. When executed +with no PLUGIN or ELEMENT argument, \fIgst\-inspect\-1.0\fP will print +a list of all plugins and elements together with a summary. +When executed with a PLUGIN or ELEMENT argument, +\fIgst\-inspect\-1.0\fP will print information about that plug-in or +element. +. +.SH "OPTIONS" +.l +\fIgst\-inspect\-1.0\fP accepts the following arguments and options: +.TP 8 +.B PLUGIN +Name of a plugin +.TP 8 +.B ELEMENT +Name of an element +.TP 8 +.B \-\-help +Print help synopsis and available FLAGS +.TP 8 +.B \-\-gst\-info\-mask=FLAGS +\fIGStreamer\fP info flags to set (list with \-\-help) +.TP 8 +.B \-a, \-\-print\-all +Print all plugins and elements +.TP 8 +.B \-b, \-\-print\-blacklist +Print list of blacklisted files +.TP 8 +.B \-\-plugin +List the plugin contents +.TP 8 +.B \-\-types=Element/Types +Allow inspecting only elements that match all the element types filtered +in this slash (\'/\') separated list of element types. Those types correspond to +what is also called \'klass\' which is a string describing the type of +element, like \'Decoder\', \'Audio\', \'Encoder\' etc... This options +implies that only elements will be printed (not typefind functions or +tracers). +.TP 8 +.B \-\-exists +Check if the specified element or plugin exists +.TP 8 +.B \-\-atleast\-version +When checking if an element or plugin exists, also check that its version +is at least the version specified +.TP 8 +.B \-u, \-\-uri\-handlers +Print supported URI schemes, with the elements that implement them +.TP 8 +.B \-\-print\-plugin\-auto\-install\-info +Print a machine-parsable list of features the specified plugin provides. +Useful in connection with external automatic plugin installation mechanisms. +.TP 8 +.B \-\-gst\-debug\-mask=FLAGS +\fIGStreamer\fP debugging flags to set (list with \-\-help) +.TP 8 +.B \-\-gst\-mask=FLAGS +\fIGStreamer\fP info and debugging flags to set (list with \-\-help) +.TP 8 +.B \-\-gst\-plugin\-spew +\fIGStreamer\fP info flags to set +Enable printout of errors while loading \fIGStreamer\fP plugins +.TP 8 +.B \-\-gst\-plugin\-path=PATH +Add directories separated with ':' to the plugin search path +. +.SH "SEE ALSO" +.BR gst\-launch\-1.0 (1), +.BR gst\-typefind\-1.0 (1) +.SH "AUTHOR" +The GStreamer team at http://gstreamer.freedesktop.org/ diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c new file mode 100644 index 0000000..89a1fab --- /dev/null +++ b/tools/gst-inspect.c @@ -0,0 +1,1860 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2004 Thomas Vander Stichele + * + * gst-inspect.c: tool to inspect the GStreamer registry + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* FIXME 2.0: suppress warnings for deprecated API such as GValueArray + * with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#include "tools.h" +#include /* for internal Factories */ + +#include +#include +#include + +static char *_name = NULL; +static int indent = 0; + +static int print_element_info (GstPluginFeature * feature, + gboolean print_names); +static int print_typefind_info (GstPluginFeature * feature, + gboolean print_names); +static int print_tracer_info (GstPluginFeature * feature, gboolean print_names); + +#define push_indent() push_indent_n(1) +#define pop_indent() push_indent_n(-1) +#define pop_indent_n(n) push_indent_n(-n) + +static void +push_indent_n (int n) +{ + g_assert (n > 0 || indent > 0); + indent += n; +} + +/* *INDENT-OFF* */ +G_GNUC_PRINTF (1, 2) +/* *INDENT-ON* */ + +static void +n_print (const char *format, ...) +{ + va_list args; + int i; + + if (_name) + g_print ("%s", _name); + + for (i = 0; i < indent; ++i) + g_print (" "); + + va_start (args, format); + g_vprintf (format, args); + va_end (args); +} + +static gboolean +print_field (GQuark field, const GValue * value, gpointer pfx) +{ + gchar *str = gst_value_serialize (value); + + n_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str); + g_free (str); + return TRUE; +} + +static void +print_caps (const GstCaps * caps, const gchar * pfx) +{ + guint i; + + g_return_if_fail (caps != NULL); + + if (gst_caps_is_any (caps)) { + n_print ("%sANY\n", pfx); + return; + } + if (gst_caps_is_empty (caps)) { + n_print ("%sEMPTY\n", pfx); + return; + } + + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + GstCapsFeatures *features = gst_caps_get_features (caps, i); + + if (features && (gst_caps_features_is_any (features) || + !gst_caps_features_is_equal (features, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) { + gchar *features_string = gst_caps_features_to_string (features); + + n_print ("%s%s(%s)\n", pfx, gst_structure_get_name (structure), + features_string); + g_free (features_string); + } else { + n_print ("%s%s\n", pfx, gst_structure_get_name (structure)); + } + gst_structure_foreach (structure, print_field, (gpointer) pfx); + } +} + +static const char * +get_rank_name (char *s, gint rank) +{ + static const int ranks[4] = { + GST_RANK_NONE, GST_RANK_MARGINAL, GST_RANK_SECONDARY, GST_RANK_PRIMARY + }; + static const char *rank_names[4] = { "none", "marginal", "secondary", + "primary" + }; + int i; + int best_i; + + best_i = 0; + for (i = 0; i < 4; i++) { + if (rank == ranks[i]) + return rank_names[i]; + if (abs (rank - ranks[i]) < abs (rank - ranks[best_i])) { + best_i = i; + } + } + + sprintf (s, "%s %c %d", rank_names[best_i], + (rank - ranks[best_i] > 0) ? '+' : '-', abs (ranks[best_i] - rank)); + + return s; +} + +static void +print_factory_details_info (GstElementFactory * factory) +{ + gchar **keys, **k; + GstRank rank; + char s[20]; + + rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)); + n_print ("Factory Details:\n"); + + push_indent (); + n_print ("%-25s%s (%d)\n", "Rank", get_rank_name (s, rank), rank); + + keys = gst_element_factory_get_metadata_keys (factory); + if (keys != NULL) { + for (k = keys; *k != NULL; ++k) { + const gchar *val; + gchar *key = *k; + + val = gst_element_factory_get_metadata (factory, key); + key[0] = g_ascii_toupper (key[0]); + n_print ("%-25s%s\n", key, val); + } + g_strfreev (keys); + } + pop_indent (); + n_print ("\n"); +} + +static void +print_hierarchy (GType type, gint level, gint * maxlevel) +{ + GType parent; + gint i; + + parent = g_type_parent (type); + + *maxlevel = *maxlevel + 1; + level++; + + if (parent) + print_hierarchy (parent, level, maxlevel); + + if (_name) + g_print ("%s", _name); + + for (i = 1; i < *maxlevel - level; i++) + g_print (" "); + if (*maxlevel - level) + g_print (" +----"); + + g_print ("%s\n", g_type_name (type)); + + if (level == 1) + n_print ("\n"); +} + +static void +print_interfaces (GType type) +{ + guint n_ifaces; + GType *iface, *ifaces = g_type_interfaces (type, &n_ifaces); + + if (ifaces) { + if (n_ifaces) { + n_print (_("Implemented Interfaces:\n")); + push_indent (); + iface = ifaces; + while (*iface) { + n_print ("%s\n", g_type_name (*iface)); + iface++; + } + pop_indent (); + n_print ("\n"); + } + g_free (ifaces); + } +} + +static gchar * +flags_to_string (GFlagsValue * vals, guint flags) +{ + GString *s = NULL; + guint flags_left, i; + + /* first look for an exact match and count the number of values */ + for (i = 0; vals[i].value_name != NULL; ++i) { + if (vals[i].value == flags) + return g_strdup (vals[i].value_nick); + } + + s = g_string_new (NULL); + + /* we assume the values are sorted from lowest to highest value */ + flags_left = flags; + while (i > 0) { + --i; + if (vals[i].value != 0 && (flags_left & vals[i].value) == vals[i].value) { + if (s->len > 0) + g_string_append_c (s, '+'); + g_string_append (s, vals[i].value_nick); + flags_left -= vals[i].value; + if (flags_left == 0) + break; + } + } + + if (s->len == 0) + g_string_assign (s, "(none)"); + + return g_string_free (s, FALSE); +} + +#define KNOWN_PARAM_FLAGS \ + (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY | \ + G_PARAM_LAX_VALIDATION | G_PARAM_STATIC_STRINGS | \ + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_DEPRECATED | \ + GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | \ + GST_PARAM_MUTABLE_PAUSED | GST_PARAM_MUTABLE_READY) + +/* obj will be NULL if we're printing properties of pad template pads */ +static void +print_object_properties_info (GObject * obj, GObjectClass * obj_class, + const gchar * desc) +{ + GParamSpec **property_specs; + guint num_properties, i; + gboolean readable; + gboolean first_flag; + + property_specs = g_object_class_list_properties (obj_class, &num_properties); + n_print ("%s:\n", desc); + + push_indent (); + + for (i = 0; i < num_properties; i++) { + GValue value = { 0, }; + GParamSpec *param = property_specs[i]; + GType owner_type = param->owner_type; + + /* We're printing pad properties */ + if (obj == NULL && (owner_type == G_TYPE_OBJECT + || owner_type == GST_TYPE_OBJECT || owner_type == GST_TYPE_PAD)) + continue; + + readable = FALSE; + + g_value_init (&value, param->value_type); + + n_print ("%-20s: %s\n", g_param_spec_get_name (param), + g_param_spec_get_blurb (param)); + + push_indent_n (11); + + first_flag = TRUE; + n_print ("flags: "); + readable = ! !(param->flags & G_PARAM_READABLE); + if (readable && obj != NULL) { + g_object_get_property (obj, param->name, &value); + } else { + /* if we can't read the property value, assume it's set to the default + * (which might not be entirely true for sub-classes, but that's an + * unlikely corner-case anyway) */ + g_param_value_set_default (param, &value); + } + if (readable) { + g_print ("%s%s", (first_flag) ? "" : ", ", _("readable")); + first_flag = FALSE; + } + if (param->flags & G_PARAM_WRITABLE) { + g_print ("%s%s", (first_flag) ? "" : ", ", _("writable")); + first_flag = FALSE; + } + if (param->flags & G_PARAM_DEPRECATED) { + g_print ("%s%s", (first_flag) ? "" : ", ", _("deprecated")); + first_flag = FALSE; + } + if (param->flags & GST_PARAM_CONTROLLABLE) { + g_print (", %s", _("controllable")); + first_flag = FALSE; + } + if (param->flags & GST_PARAM_MUTABLE_PLAYING) { + g_print (", %s", _("changeable in NULL, READY, PAUSED or PLAYING state")); + } else if (param->flags & GST_PARAM_MUTABLE_PAUSED) { + g_print (", %s", _("changeable only in NULL, READY or PAUSED state")); + } else if (param->flags & GST_PARAM_MUTABLE_READY) { + g_print (", %s", _("changeable only in NULL or READY state")); + } + if (param->flags & ~KNOWN_PARAM_FLAGS) { + g_print ("%s0x%0x", (first_flag) ? "" : ", ", + param->flags & ~KNOWN_PARAM_FLAGS); + } + g_print ("\n"); + + switch (G_VALUE_TYPE (&value)) { + case G_TYPE_STRING: + { + const char *string_val = g_value_get_string (&value); + + n_print ("String. "); + + if (string_val == NULL) + g_print ("Default: null"); + else + g_print ("Default: \"%s\"", string_val); + break; + } + case G_TYPE_BOOLEAN: + { + gboolean bool_val = g_value_get_boolean (&value); + + n_print ("Boolean. Default: %s", bool_val ? "true" : "false"); + break; + } + case G_TYPE_ULONG: + { + GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param); + + n_print ("Unsigned Long. Range: %lu - %lu Default: %lu ", + pulong->minimum, pulong->maximum, g_value_get_ulong (&value)); + + GST_ERROR ("%s: property '%s' of type ulong: consider changing to " + "uint/uint64", G_OBJECT_CLASS_NAME (obj_class), + g_param_spec_get_name (param)); + break; + } + case G_TYPE_LONG: + { + GParamSpecLong *plong = G_PARAM_SPEC_LONG (param); + + n_print ("Long. Range: %ld - %ld Default: %ld ", + plong->minimum, plong->maximum, g_value_get_long (&value)); + + GST_ERROR ("%s: property '%s' of type long: consider changing to " + "int/int64", G_OBJECT_CLASS_NAME (obj_class), + g_param_spec_get_name (param)); + break; + } + case G_TYPE_UINT: + { + GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param); + + n_print ("Unsigned Integer. Range: %u - %u Default: %u ", + puint->minimum, puint->maximum, g_value_get_uint (&value)); + break; + } + case G_TYPE_INT: + { + GParamSpecInt *pint = G_PARAM_SPEC_INT (param); + + n_print ("Integer. Range: %d - %d Default: %d ", + pint->minimum, pint->maximum, g_value_get_int (&value)); + break; + } + case G_TYPE_UINT64: + { + GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param); + + n_print ("Unsigned Integer64. Range: %" G_GUINT64_FORMAT " - " + "%" G_GUINT64_FORMAT " Default: %" G_GUINT64_FORMAT " ", + puint64->minimum, puint64->maximum, g_value_get_uint64 (&value)); + break; + } + case G_TYPE_INT64: + { + GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param); + + n_print ("Integer64. Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT + " Default: %" G_GINT64_FORMAT " ", + pint64->minimum, pint64->maximum, g_value_get_int64 (&value)); + break; + } + case G_TYPE_FLOAT: + { + GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param); + + n_print ("Float. Range: %15.7g - %15.7g Default: %15.7g ", + pfloat->minimum, pfloat->maximum, g_value_get_float (&value)); + break; + } + case G_TYPE_DOUBLE: + { + GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param); + + n_print ("Double. Range: %15.7g - %15.7g Default: %15.7g ", + pdouble->minimum, pdouble->maximum, g_value_get_double (&value)); + break; + } + case G_TYPE_CHAR: + case G_TYPE_UCHAR: + GST_ERROR ("%s: property '%s' of type char: consider changing to " + "int/string", G_OBJECT_CLASS_NAME (obj_class), + g_param_spec_get_name (param)); + /* fall through */ + default: + if (param->value_type == GST_TYPE_CAPS) { + const GstCaps *caps = gst_value_get_caps (&value); + + if (!caps) + n_print ("Caps (NULL)"); + else { + print_caps (caps, " "); + } + } else if (G_IS_PARAM_SPEC_ENUM (param)) { + GEnumValue *values; + guint j = 0; + gint enum_value; + const gchar *value_nick = ""; + + values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values; + enum_value = g_value_get_enum (&value); + + while (values[j].value_name) { + if (values[j].value == enum_value) + value_nick = values[j].value_nick; + j++; + } + + n_print ("Enum \"%s\" Default: %d, \"%s\"", + g_type_name (G_VALUE_TYPE (&value)), enum_value, value_nick); + + j = 0; + while (values[j].value_name) { + g_print ("\n"); + n_print (" (%d): %-16s - %s", + values[j].value, values[j].value_nick, values[j].value_name); + j++; + } + /* g_type_class_unref (ec); */ + } else if (G_IS_PARAM_SPEC_FLAGS (param)) { + GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (param); + GFlagsValue *vals; + gchar *cur; + + vals = pflags->flags_class->values; + + cur = flags_to_string (vals, g_value_get_flags (&value)); + + n_print ("Flags \"%s\" Default: 0x%08x, \"%s\"", + g_type_name (G_VALUE_TYPE (&value)), + g_value_get_flags (&value), cur); + + while (vals[0].value_name) { + g_print ("\n"); + n_print (" (0x%08x): %-16s - %s", + vals[0].value, vals[0].value_nick, vals[0].value_name); + ++vals; + } + + g_free (cur); + } else if (G_IS_PARAM_SPEC_OBJECT (param)) { + n_print ("Object of type \"%s\"", g_type_name (param->value_type)); + } else if (G_IS_PARAM_SPEC_BOXED (param)) { + n_print ("Boxed pointer of type \"%s\"", + g_type_name (param->value_type)); + if (param->value_type == GST_TYPE_STRUCTURE) { + const GstStructure *s = gst_value_get_structure (&value); + if (s) + gst_structure_foreach (s, print_field, + (gpointer) " "); + } + } else if (G_IS_PARAM_SPEC_POINTER (param)) { + if (param->value_type != G_TYPE_POINTER) { + n_print ("Pointer of type \"%s\".", + g_type_name (param->value_type)); + } else { + n_print ("Pointer."); + } + } else if (param->value_type == G_TYPE_VALUE_ARRAY) { + GParamSpecValueArray *pvarray = G_PARAM_SPEC_VALUE_ARRAY (param); + + if (pvarray->element_spec) { + n_print ("Array of GValues of type \"%s\"", + g_type_name (pvarray->element_spec->value_type)); + } else { + n_print ("Array of GValues"); + } + } else if (GST_IS_PARAM_SPEC_FRACTION (param)) { + GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (param); + + n_print ("Fraction. Range: %d/%d - %d/%d Default: %d/%d ", + pfraction->min_num, pfraction->min_den, + pfraction->max_num, pfraction->max_den, + gst_value_get_fraction_numerator (&value), + gst_value_get_fraction_denominator (&value)); + } else if (param->value_type == GST_TYPE_ARRAY) { + GstParamSpecArray *parray = GST_PARAM_SPEC_ARRAY_LIST (param); + + if (parray->element_spec) { + n_print ("GstValueArray of GValues of type \"%s\"", + g_type_name (parray->element_spec->value_type)); + } else { + n_print ("GstValueArray of GValues"); + } + } else { + n_print ("Unknown type %ld \"%s\"", + (glong) param->value_type, g_type_name (param->value_type)); + } + break; + } + if (!readable) + g_print (" Write only\n"); + else + g_print ("\n"); + + pop_indent_n (11); + + g_value_reset (&value); + } + if (num_properties == 0) + n_print ("none\n"); + + pop_indent (); + + g_free (property_specs); +} + +static void +print_element_properties_info (GstElement * element) +{ + g_print ("\n"); + print_object_properties_info (G_OBJECT (element), + G_OBJECT_GET_CLASS (element), "Element Properties"); +} + +static void +print_pad_templates_info (GstElement * element, GstElementFactory * factory) +{ + const GList *pads; + GstStaticPadTemplate *padtemplate; + GstPadTemplate *tmpl; + + n_print ("Pad Templates:\n"); + + push_indent (); + + if (gst_element_factory_get_num_pad_templates (factory) == 0) { + n_print ("none\n"); + goto done; + } + + pads = gst_element_factory_get_static_pad_templates (factory); + while (pads) { + padtemplate = (GstStaticPadTemplate *) (pads->data); + pads = g_list_next (pads); + + if (padtemplate->direction == GST_PAD_SRC) + n_print ("SRC template: '%s'\n", padtemplate->name_template); + else if (padtemplate->direction == GST_PAD_SINK) + n_print ("SINK template: '%s'\n", padtemplate->name_template); + else + n_print ("UNKNOWN template: '%s'\n", padtemplate->name_template); + + push_indent (); + + if (padtemplate->presence == GST_PAD_ALWAYS) + n_print ("Availability: Always\n"); + else if (padtemplate->presence == GST_PAD_SOMETIMES) + n_print ("Availability: Sometimes\n"); + else if (padtemplate->presence == GST_PAD_REQUEST) { + n_print ("Availability: On request\n"); + } else + n_print ("Availability: UNKNOWN\n"); + + if (padtemplate->static_caps.string) { + GstCaps *caps = gst_static_caps_get (&padtemplate->static_caps); + + n_print ("Capabilities:\n"); + + push_indent (); + print_caps (caps, ""); // FIXME + pop_indent (); + + gst_caps_unref (caps); + } + + tmpl = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element), + padtemplate->name_template); + if (tmpl != NULL) { + GType pad_type = GST_PAD_TEMPLATE_GTYPE (tmpl); + + if (pad_type != G_TYPE_NONE && pad_type != GST_TYPE_PAD) { + gpointer pad_klass; + + pad_klass = g_type_class_ref (pad_type); + n_print ("Type: %s\n", g_type_name (pad_type)); + print_object_properties_info (NULL, pad_klass, "Pad Properties"); + g_type_class_unref (pad_klass); + } + } + + pop_indent (); + + if (pads != NULL) + n_print ("\n"); + } + +done: + pop_indent (); +} + +static void +print_clocking_info (GstElement * element) +{ + gboolean requires_clock, provides_clock; + + requires_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK); + provides_clock = + GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK); + + if (!requires_clock && !provides_clock) { + n_print ("\n"); + n_print ("Element has no clocking capabilities.\n"); + return; + } + + n_print ("\n"); + n_print ("Clocking Interaction:\n"); + + push_indent (); + + if (requires_clock) { + n_print ("element requires a clock\n"); + } + + if (provides_clock) { + GstClock *clock; + + clock = gst_element_get_clock (element); + if (clock) { + n_print ("element provides a clock: %s\n", GST_OBJECT_NAME (clock)); + gst_object_unref (clock); + } else + n_print ("element is supposed to provide a clock but returned NULL\n"); + } + + pop_indent (); +} + +static void +print_uri_handler_info (GstElement * element) +{ + if (GST_IS_URI_HANDLER (element)) { + const gchar *const *uri_protocols; + const gchar *uri_type; + + if (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element)) == GST_URI_SRC) + uri_type = "source"; + else if (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element)) == + GST_URI_SINK) + uri_type = "sink"; + else + uri_type = "unknown"; + + uri_protocols = gst_uri_handler_get_protocols (GST_URI_HANDLER (element)); + + n_print ("\n"); + n_print ("URI handling capabilities:\n"); + + push_indent (); + + n_print ("Element can act as %s.\n", uri_type); + + if (uri_protocols && *uri_protocols) { + n_print ("Supported URI protocols:\n"); + push_indent (); + for (; *uri_protocols != NULL; uri_protocols++) + n_print ("%s\n", *uri_protocols); + pop_indent (); + } else { + n_print ("No supported URI protocols\n"); + } + + pop_indent (); + } else { + n_print ("Element has no URI handling capabilities.\n"); + } +} + +static void +print_pad_info (GstElement * element) +{ + const GList *pads; + GstPad *pad; + + n_print ("\n"); + n_print ("Pads:\n"); + + push_indent (); + + if (!element->numpads) { + n_print ("none\n"); + goto done; + } + + pads = element->pads; + while (pads) { + gchar *name; + GstCaps *caps; + + pad = GST_PAD (pads->data); + pads = g_list_next (pads); + + name = gst_pad_get_name (pad); + if (gst_pad_get_direction (pad) == GST_PAD_SRC) + n_print ("SRC: '%s'\n", name); + else if (gst_pad_get_direction (pad) == GST_PAD_SINK) + n_print ("SINK: '%s'\n", name); + else + n_print ("UNKNOWN: '%s'\n", name); + + g_free (name); + + if (pad->padtemplate) { + push_indent (); + n_print ("Pad Template: '%s'\n", pad->padtemplate->name_template); + pop_indent (); + } + + caps = gst_pad_get_current_caps (pad); + if (caps) { + n_print ("Capabilities:\n"); + push_indent (); + print_caps (caps, ""); // FIXME + pop_indent (); + gst_caps_unref (caps); + } + } + +done: + pop_indent (); +} + +static gboolean +has_sometimes_template (GstElement * element) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); + GList *l; + + for (l = klass->padtemplates; l != NULL; l = l->next) { + if (GST_PAD_TEMPLATE (l->data)->presence == GST_PAD_SOMETIMES) + return TRUE; + } + + return FALSE; +} + +static gboolean +gtype_needs_ptr_marker (GType type) +{ + if (type == G_TYPE_POINTER) + return FALSE; + + if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_POINTER || G_TYPE_IS_BOXED (type) + || G_TYPE_IS_OBJECT (type)) + return TRUE; + + return FALSE; +} + +static void +print_signal_info (GstElement * element) +{ + /* Signals/Actions Block */ + guint *signals; + guint nsignals; + gint i = 0, j, k; + GSignalQuery *query = NULL; + GType type; + GSList *found_signals, *l; + + for (k = 0; k < 2; k++) { + found_signals = NULL; + + /* For elements that have sometimes pads, also list a few useful GstElement + * signals. Put these first, so element-specific ones come later. */ + if (k == 0 && has_sometimes_template (element)) { + query = g_new0 (GSignalQuery, 1); + g_signal_query (g_signal_lookup ("pad-added", GST_TYPE_ELEMENT), query); + found_signals = g_slist_append (found_signals, query); + query = g_new0 (GSignalQuery, 1); + g_signal_query (g_signal_lookup ("pad-removed", GST_TYPE_ELEMENT), query); + found_signals = g_slist_append (found_signals, query); + query = g_new0 (GSignalQuery, 1); + g_signal_query (g_signal_lookup ("no-more-pads", GST_TYPE_ELEMENT), + query); + found_signals = g_slist_append (found_signals, query); + } + + for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) { + if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT) + break; + + if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN) + continue; + + signals = g_signal_list_ids (type, &nsignals); + for (i = 0; i < nsignals; i++) { + query = g_new0 (GSignalQuery, 1); + g_signal_query (signals[i], query); + + if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) || + (k == 1 && (query->signal_flags & G_SIGNAL_ACTION))) + found_signals = g_slist_append (found_signals, query); + else + g_free (query); + } + g_free (signals); + signals = NULL; + } + + if (found_signals) { + n_print ("\n"); + if (k == 0) + n_print ("Element Signals:\n"); + else + n_print ("Element Actions:\n"); + } else { + continue; + } + + for (l = found_signals; l; l = l->next) { + gchar *indent; + const gchar *pmark; + int indent_len; + + query = (GSignalQuery *) l->data; + indent_len = strlen (query->signal_name) + + strlen (g_type_name (query->return_type)) + 24; + + if (gtype_needs_ptr_marker (query->return_type)) { + pmark = "* "; + indent_len += 2; + } else { + pmark = ""; + } + + indent = g_new0 (gchar, indent_len + 1); + memset (indent, ' ', indent_len); + + n_print (" \"%s\" : %s %suser_function (%s* object", + query->signal_name, g_type_name (query->return_type), pmark, + g_type_name (type)); + + for (j = 0; j < query->n_params; j++) { + const gchar *type_name, *asterisk; + + type_name = g_type_name (query->param_types[j]); + asterisk = gtype_needs_ptr_marker (query->param_types[j]) ? "*" : ""; + + g_print (",\n"); + n_print ("%s%s%s arg%d", indent, type_name, asterisk, j); + } + + if (k == 0) { + g_print (",\n"); + n_print ("%sgpointer user_data);\n", indent); + } else + g_print (");\n"); + + g_free (indent); + } + + if (found_signals) { + g_slist_foreach (found_signals, (GFunc) g_free, NULL); + g_slist_free (found_signals); + } + } +} + +static void +print_children_info (GstElement * element) +{ + GList *children; + + if (!GST_IS_BIN (element)) + return; + + children = (GList *) GST_BIN (element)->children; + if (children) { + n_print ("\n"); + n_print ("Children:\n"); + } + + while (children) { + n_print (" %s\n", GST_ELEMENT_NAME (GST_ELEMENT (children->data))); + children = g_list_next (children); + } +} + +static void +print_preset_list (GstElement * element) +{ + gchar **presets, **preset; + + if (!GST_IS_PRESET (element)) + return; + + presets = gst_preset_get_preset_names (GST_PRESET (element)); + if (presets && *presets) { + n_print ("\n"); + n_print ("Presets:\n"); + for (preset = presets; *preset; preset++) { + n_print (" \"%s\"\n", *preset); + } + g_strfreev (presets); + } +} + +static void +print_blacklist (void) +{ + GList *plugins, *cur; + gint count = 0; + + g_print ("%s\n", _("Blacklisted files:")); + + plugins = gst_registry_get_plugin_list (gst_registry_get ()); + for (cur = plugins; cur != NULL; cur = g_list_next (cur)) { + GstPlugin *plugin = (GstPlugin *) (cur->data); + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) { + g_print (" %s\n", gst_plugin_get_name (plugin)); + count++; + } + } + + g_print ("\n"); + g_print (_("Total count: ")); + g_print (ngettext ("%d blacklisted file", "%d blacklisted files", count), + count); + g_print ("\n"); + gst_plugin_list_free (plugins); +} + +static void +print_typefind_extensions (const gchar * const *extensions) +{ + guint i = 0; + + while (extensions[i]) { + g_print ("%s%s", i > 0 ? ", " : "", extensions[i]); + i++; + } +} + +static void +print_element_list (gboolean print_all, gchar * ftypes) +{ + int plugincount = 0, featurecount = 0, blacklistcount = 0; + GList *plugins, *orig_plugins; + gchar **types = NULL; + + if (ftypes) { + gint i; + + types = g_strsplit (ftypes, "/", -1); + for (i = 0; types[i]; i++) + *types[i] = g_ascii_toupper (*types[i]); + + } + + orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ()); + while (plugins) { + GList *features, *orig_features; + GstPlugin *plugin; + + plugin = (GstPlugin *) (plugins->data); + plugins = g_list_next (plugins); + plugincount++; + + if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) { + blacklistcount++; + continue; + } + + orig_features = features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + while (features) { + GstPluginFeature *feature; + + if (G_UNLIKELY (features->data == NULL)) + goto next; + feature = GST_PLUGIN_FEATURE (features->data); + featurecount++; + + if (GST_IS_ELEMENT_FACTORY (feature)) { + const gchar *klass; + GstElementFactory *factory; + + factory = GST_ELEMENT_FACTORY (feature); + if (types) { + gint i; + gboolean all_found = TRUE; + + klass = + gst_element_factory_get_metadata (factory, + GST_ELEMENT_METADATA_KLASS); + for (i = 0; types[i]; i++) { + if (!strstr (klass, types[i])) { + all_found = FALSE; + break; + } + } + + if (!all_found) + goto next; + } + if (print_all) + print_element_info (feature, TRUE); + else + g_print ("%s: %s: %s\n", gst_plugin_get_name (plugin), + GST_OBJECT_NAME (factory), + gst_element_factory_get_metadata (factory, + GST_ELEMENT_METADATA_LONGNAME)); + } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { + GstTypeFindFactory *factory; + const gchar *const *extensions; + + if (types) + goto next; + factory = GST_TYPE_FIND_FACTORY (feature); + if (!print_all) + g_print ("%s: %s: ", gst_plugin_get_name (plugin), + gst_plugin_feature_get_name (feature)); + + extensions = gst_type_find_factory_get_extensions (factory); + if (extensions != NULL) { + if (!print_all) { + print_typefind_extensions (extensions); + g_print ("\n"); + } + } else { + if (!print_all) + g_print ("no extensions\n"); + } + } else { + if (types) + goto next; + if (!print_all) + n_print ("%s: %s (%s)\n", gst_plugin_get_name (plugin), + GST_OBJECT_NAME (feature), g_type_name (G_OBJECT_TYPE (feature))); + } + + next: + features = g_list_next (features); + } + + gst_plugin_feature_list_free (orig_features); + } + + gst_plugin_list_free (orig_plugins); + g_strfreev (types); + + g_print ("\n"); + g_print (_("Total count: ")); + g_print (ngettext ("%d plugin", "%d plugins", plugincount), plugincount); + if (blacklistcount) { + g_print (" ("); + g_print (ngettext ("%d blacklist entry", "%d blacklist entries", + blacklistcount), blacklistcount); + g_print (" not shown)"); + } + g_print (", "); + g_print (ngettext ("%d feature", "%d features", featurecount), featurecount); + g_print ("\n"); +} + +static void +print_all_uri_handlers (void) +{ + GList *plugins, *p, *features, *f; + + plugins = gst_registry_get_plugin_list (gst_registry_get ()); + + for (p = plugins; p; p = p->next) { + GstPlugin *plugin = (GstPlugin *) (p->data); + + features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + + for (f = features; f; f = f->next) { + GstPluginFeature *feature = GST_PLUGIN_FEATURE (f->data); + + if (GST_IS_ELEMENT_FACTORY (feature)) { + GstElementFactory *factory; + GstElement *element; + + factory = GST_ELEMENT_FACTORY (gst_plugin_feature_load (feature)); + if (!factory) { + g_print ("element plugin %s couldn't be loaded\n", + gst_plugin_get_name (plugin)); + continue; + } + + element = gst_element_factory_create (factory, NULL); + if (!element) { + g_print ("couldn't construct element for %s for some reason\n", + GST_OBJECT_NAME (factory)); + gst_object_unref (factory); + continue; + } + + if (GST_IS_URI_HANDLER (element)) { + const gchar *const *uri_protocols; + const gchar *dir; + gchar *joined; + + switch (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element))) { + case GST_URI_SRC: + dir = "read"; + break; + case GST_URI_SINK: + dir = "write"; + break; + default: + dir = "unknown"; + break; + } + + uri_protocols = + gst_uri_handler_get_protocols (GST_URI_HANDLER (element)); + joined = g_strjoinv (", ", (gchar **) uri_protocols); + + g_print ("%s (%s, rank %u): %s\n", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), dir, + gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)), + joined); + + g_free (joined); + } + + gst_object_unref (element); + gst_object_unref (factory); + } + } + + gst_plugin_feature_list_free (features); + } + + gst_plugin_list_free (plugins); +} + +static void +print_plugin_info (GstPlugin * plugin) +{ + const gchar *release_date = gst_plugin_get_release_date_string (plugin); + const gchar *filename = gst_plugin_get_filename (plugin); + + n_print ("Plugin Details:\n"); + + push_indent (); + + n_print ("%-25s%s\n", "Name", gst_plugin_get_name (plugin)); + n_print ("%-25s%s\n", "Description", gst_plugin_get_description (plugin)); + n_print ("%-25s%s\n", "Filename", (filename != NULL) ? filename : "(null)"); + n_print ("%-25s%s\n", "Version", gst_plugin_get_version (plugin)); + n_print ("%-25s%s\n", "License", gst_plugin_get_license (plugin)); + n_print ("%-25s%s\n", "Source module", gst_plugin_get_source (plugin)); + + if (release_date != NULL) { + const gchar *tz = "(UTC)"; + gchar *str, *sep; + + /* may be: YYYY-MM-DD or YYYY-MM-DDTHH:MMZ */ + /* YYYY-MM-DDTHH:MMZ => YYYY-MM-DD HH:MM (UTC) */ + str = g_strdup (release_date); + sep = strstr (str, "T"); + if (sep != NULL) { + *sep = ' '; + sep = strstr (sep + 1, "Z"); + if (sep != NULL) + *sep = ' '; + } else { + tz = ""; + } + n_print ("%-25s%s%s\n", "Source release date", str, tz); + g_free (str); + } + n_print ("%-25s%s\n", "Binary package", gst_plugin_get_package (plugin)); + n_print ("%-25s%s\n", "Origin URL", gst_plugin_get_origin (plugin)); + + pop_indent (); + + n_print ("\n"); +} + +static void +print_plugin_features (GstPlugin * plugin) +{ + GList *features, *origlist; + gint num_features = 0; + gint num_elements = 0; + gint num_tracers = 0; + gint num_typefinders = 0; + gint num_devproviders = 0; + gint num_other = 0; + + origlist = features = + gst_registry_get_feature_list_by_plugin (gst_registry_get (), + gst_plugin_get_name (plugin)); + + while (features) { + GstPluginFeature *feature; + + feature = GST_PLUGIN_FEATURE (features->data); + + if (GST_IS_ELEMENT_FACTORY (feature)) { + GstElementFactory *factory; + + factory = GST_ELEMENT_FACTORY (feature); + n_print (" %s: %s\n", GST_OBJECT_NAME (factory), + gst_element_factory_get_metadata (factory, + GST_ELEMENT_METADATA_LONGNAME)); + num_elements++; + } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { + GstTypeFindFactory *factory; + const gchar *const *extensions; + + factory = GST_TYPE_FIND_FACTORY (feature); + extensions = gst_type_find_factory_get_extensions (factory); + if (extensions) { + guint i = 0; + + g_print (" %s: %s: ", gst_plugin_get_name (plugin), + gst_plugin_feature_get_name (feature)); + while (extensions[i]) { + g_print ("%s%s", i > 0 ? ", " : "", extensions[i]); + i++; + } + g_print ("\n"); + } else + g_print (" %s: %s: no extensions\n", gst_plugin_get_name (plugin), + gst_plugin_feature_get_name (feature)); + + num_typefinders++; + } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) { + GstDeviceProviderFactory *factory; + + factory = GST_DEVICE_PROVIDER_FACTORY (feature); + n_print (" %s: %s\n", GST_OBJECT_NAME (factory), + gst_device_provider_factory_get_metadata (factory, + GST_ELEMENT_METADATA_LONGNAME)); + num_devproviders++; + } else if (GST_IS_TRACER_FACTORY (feature)) { + n_print (" %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), + g_type_name (G_OBJECT_TYPE (feature))); + num_tracers++; + } else if (feature) { + n_print (" %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), + g_type_name (G_OBJECT_TYPE (feature))); + num_other++; + } + num_features++; + features = g_list_next (features); + } + + gst_plugin_feature_list_free (origlist); + + n_print ("\n"); + n_print (" %d features:\n", num_features); + if (num_elements > 0) + n_print (" +-- %d elements\n", num_elements); + if (num_typefinders > 0) + n_print (" +-- %d typefinders\n", num_typefinders); + if (num_devproviders > 0) + n_print (" +-- %d device providers\n", num_devproviders); + if (num_tracers > 0) + n_print (" +-- %d tracers\n", num_tracers); + if (num_other > 0) + n_print (" +-- %d other objects\n", num_other); + + n_print ("\n"); +} + +static int +print_feature_info (const gchar * feature_name, gboolean print_all) +{ + GstPluginFeature *feature; + GstRegistry *registry = gst_registry_get (); + int ret; + + if ((feature = gst_registry_find_feature (registry, feature_name, + GST_TYPE_ELEMENT_FACTORY))) { + ret = print_element_info (feature, print_all); + goto handled; + } + if ((feature = gst_registry_find_feature (registry, feature_name, + GST_TYPE_TYPE_FIND_FACTORY))) { + ret = print_typefind_info (feature, print_all); + goto handled; + } + if ((feature = gst_registry_find_feature (registry, feature_name, + GST_TYPE_TRACER_FACTORY))) { + ret = print_tracer_info (feature, print_all); + goto handled; + } + + /* TODO: handle DEVICE_PROVIDER_FACTORY */ + + return -1; + +handled: + gst_object_unref (feature); + return ret; +} + +static int +print_element_info (GstPluginFeature * feature, gboolean print_names) +{ + GstElementFactory *factory; + GstElement *element; + GstPlugin *plugin; + gint maxlevel = 0; + + factory = GST_ELEMENT_FACTORY (gst_plugin_feature_load (feature)); + if (!factory) { + g_print ("element plugin couldn't be loaded\n"); + return -1; + } + + element = gst_element_factory_create (factory, NULL); + if (!element) { + gst_object_unref (factory); + g_print ("couldn't construct element for some reason\n"); + return -1; + } + + if (print_names) + _name = g_strdup_printf ("%s: ", GST_OBJECT_NAME (factory)); + else + _name = NULL; + + print_factory_details_info (factory); + + plugin = gst_plugin_feature_get_plugin (GST_PLUGIN_FEATURE (factory)); + if (plugin) { + print_plugin_info (plugin); + gst_object_unref (plugin); + } + + print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel); + print_interfaces (G_OBJECT_TYPE (element)); + + print_pad_templates_info (element, factory); + print_clocking_info (element); + print_uri_handler_info (element); + print_pad_info (element); + print_element_properties_info (element); + print_signal_info (element); + print_children_info (element); + print_preset_list (element); + + gst_object_unref (element); + gst_object_unref (factory); + g_free (_name); + return 0; +} + +static int +print_typefind_info (GstPluginFeature * feature, gboolean print_names) +{ + GstTypeFindFactory *factory; + GstPlugin *plugin; + GstCaps *caps; + GstRank rank; + char s[20]; + const gchar *const *extensions; + + factory = GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (feature)); + if (!factory) { + g_print ("typefind plugin couldn't be loaded\n"); + return -1; + } + + if (print_names) + _name = g_strdup_printf ("%s: ", GST_OBJECT_NAME (factory)); + else + _name = NULL; + + n_print ("Factory Details:\n"); + rank = gst_plugin_feature_get_rank (feature); + n_print (" %-25s%s (%d)\n", "Rank", get_rank_name (s, rank), rank); + n_print (" %-25s%s\n", "Name", GST_OBJECT_NAME (factory)); + caps = gst_type_find_factory_get_caps (factory); + if (caps) { + gchar *caps_str = gst_caps_to_string (factory->caps); + + n_print (" %-25s%s\n", "Caps", caps_str); + g_free (caps_str); + } + extensions = gst_type_find_factory_get_extensions (factory); + if (extensions) { + n_print (" %-25s", "Extensions"); + print_typefind_extensions (extensions); + n_print ("\n"); + } + n_print ("\n"); + + plugin = gst_plugin_feature_get_plugin (GST_PLUGIN_FEATURE (factory)); + if (plugin) { + print_plugin_info (plugin); + gst_object_unref (plugin); + } + + gst_object_unref (factory); + g_free (_name); + return 0; +} + +static int +print_tracer_info (GstPluginFeature * feature, gboolean print_names) +{ + GstTracerFactory *factory; + GstTracer *tracer; + GstPlugin *plugin; + gint maxlevel = 0; + + factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature)); + if (!factory) { + g_print ("tracer plugin couldn't be loaded\n"); + return -1; + } + + tracer = (GstTracer *) g_object_new (factory->type, NULL); + if (!tracer) { + gst_object_unref (factory); + g_print ("couldn't construct tracer for some reason\n"); + return -1; + } + + if (print_names) + _name = g_strdup_printf ("%s: ", GST_OBJECT_NAME (factory)); + else + _name = NULL; + + n_print ("Factory Details:\n"); + n_print (" %-25s%s\n", "Name", GST_OBJECT_NAME (factory)); + n_print ("\n"); + + plugin = gst_plugin_feature_get_plugin (GST_PLUGIN_FEATURE (factory)); + if (plugin) { + print_plugin_info (plugin); + gst_object_unref (plugin); + } + + print_hierarchy (G_OBJECT_TYPE (tracer), 0, &maxlevel); + print_interfaces (G_OBJECT_TYPE (tracer)); + + /* TODO: list what hooks it registers + * - the data is available in gsttracerutils, we need to iterate the + * _priv_tracers hashtable for each probe and then check the list of hooks + * for each probe whether hook->tracer == tracer :/ + */ + + /* TODO: list what records it emits + * - in class_init tracers can create GstTracerRecord instances + * - those only get logged right now and there is no association with the + * tracer that created them + * - we'd need to add them to GstTracerFactory + * gst_tracer_class_add_record (klass, record); + * - needs work in gstregistrychunks to (de)serialize specs + * - gst_tracer_register() would need to iterate the list of records and + * copy the record->spec into the factory + */ + + gst_object_unref (tracer); + gst_object_unref (factory); + g_free (_name); + return 0; +} + +static void +print_plugin_automatic_install_info_codecs (GstElementFactory * factory) +{ + GstPadDirection direction; + const gchar *type_name; + const gchar *klass; + const GList *static_templates, *l; + GstCaps *caps = NULL; + guint i, num; + + klass = + gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS); + g_return_if_fail (klass != NULL); + + if (strstr (klass, "Demuxer") || + strstr (klass, "Decoder") || + strstr (klass, "Depay") || strstr (klass, "Parser")) { + type_name = "decoder"; + direction = GST_PAD_SINK; + } else if (strstr (klass, "Muxer") || + strstr (klass, "Encoder") || strstr (klass, "Pay")) { + type_name = "encoder"; + direction = GST_PAD_SRC; + } else { + return; + } + + /* decoder/demuxer sink pads should always be static and there should only + * be one, the same applies to encoders/muxers and source pads */ + static_templates = gst_element_factory_get_static_pad_templates (factory); + for (l = static_templates; l != NULL; l = l->next) { + GstStaticPadTemplate *tmpl = NULL; + + tmpl = (GstStaticPadTemplate *) l->data; + if (tmpl->direction == direction) { + caps = gst_static_pad_template_get_caps (tmpl); + break; + } + } + + if (caps == NULL) { + g_printerr ("Couldn't find static pad template for %s '%s'\n", + type_name, GST_OBJECT_NAME (factory)); + return; + } + + caps = gst_caps_make_writable (caps); + num = gst_caps_get_size (caps); + for (i = 0; i < num; ++i) { + GstStructure *s; + gchar *s_str; + + s = gst_caps_get_structure (caps, i); + /* remove fields that are almost always just MIN-MAX of some sort + * in order to make the caps look less messy */ + gst_structure_remove_field (s, "pixel-aspect-ratio"); + gst_structure_remove_field (s, "framerate"); + gst_structure_remove_field (s, "channels"); + gst_structure_remove_field (s, "width"); + gst_structure_remove_field (s, "height"); + gst_structure_remove_field (s, "rate"); + gst_structure_remove_field (s, "depth"); + gst_structure_remove_field (s, "clock-rate"); + s_str = gst_structure_to_string (s); + g_print ("%s-%s\n", type_name, s_str); + g_free (s_str); + } + gst_caps_unref (caps); +} + +static void +print_plugin_automatic_install_info_protocols (GstElementFactory * factory) +{ + const gchar *const *protocols; + + protocols = gst_element_factory_get_uri_protocols (factory); + if (protocols != NULL && *protocols != NULL) { + switch (gst_element_factory_get_uri_type (factory)) { + case GST_URI_SINK: + while (*protocols != NULL) { + g_print ("urisink-%s\n", *protocols); + ++protocols; + } + break; + case GST_URI_SRC: + while (*protocols != NULL) { + g_print ("urisource-%s\n", *protocols); + ++protocols; + } + break; + default: + break; + } + } +} + +static void +print_plugin_automatic_install_info (GstPlugin * plugin) +{ + GList *features, *l; + + /* not interested in typefind factories, only element factories */ + features = gst_registry_get_feature_list (gst_registry_get (), + GST_TYPE_ELEMENT_FACTORY); + + for (l = features; l != NULL; l = l->next) { + GstPluginFeature *feature; + GstPlugin *feature_plugin; + + feature = GST_PLUGIN_FEATURE (l->data); + + /* only interested in the ones that are in the plugin we just loaded */ + feature_plugin = gst_plugin_feature_get_plugin (feature); + if (feature_plugin == plugin) { + GstElementFactory *factory; + + g_print ("element-%s\n", gst_plugin_feature_get_name (feature)); + + factory = GST_ELEMENT_FACTORY (feature); + print_plugin_automatic_install_info_protocols (factory); + print_plugin_automatic_install_info_codecs (factory); + } + if (feature_plugin) + gst_object_unref (feature_plugin); + } + + g_list_foreach (features, (GFunc) gst_object_unref, NULL); + g_list_free (features); +} + +static void +print_all_plugin_automatic_install_info (void) +{ + GList *plugins, *orig_plugins; + + orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ()); + while (plugins) { + GstPlugin *plugin; + + plugin = (GstPlugin *) (plugins->data); + plugins = g_list_next (plugins); + + print_plugin_automatic_install_info (plugin); + } + gst_plugin_list_free (orig_plugins); +} + +int +main (int argc, char *argv[]) +{ + gboolean print_all = FALSE; + gboolean do_print_blacklist = FALSE; + gboolean plugin_name = FALSE; + gboolean print_aii = FALSE; + gboolean uri_handlers = FALSE; + gboolean check_exists = FALSE; + gchar *min_version = NULL; + guint minver_maj = GST_VERSION_MAJOR; + guint minver_min = GST_VERSION_MINOR; + guint minver_micro = 0; + gchar *types = NULL; +#ifndef GST_DISABLE_OPTION_PARSING + GOptionEntry options[] = { + {"print-all", 'a', 0, G_OPTION_ARG_NONE, &print_all, + N_("Print all elements"), NULL}, + {"print-blacklist", 'b', 0, G_OPTION_ARG_NONE, &do_print_blacklist, + N_("Print list of blacklisted files"), NULL}, + {"print-plugin-auto-install-info", '\0', 0, G_OPTION_ARG_NONE, &print_aii, + N_("Print a machine-parsable list of features the specified plugin " + "or all plugins provide.\n " + "Useful in connection with external automatic plugin " + "installation mechanisms"), NULL}, + {"plugin", '\0', 0, G_OPTION_ARG_NONE, &plugin_name, + N_("List the plugin contents"), NULL}, + {"types", 't', 0, G_OPTION_ARG_STRING, &types, + N_("A slashes ('/') separated list of types of elements (also known " + "as klass) to list. (unordered)"), NULL}, + {"exists", '\0', 0, G_OPTION_ARG_NONE, &check_exists, + N_("Check if the specified element or plugin exists"), NULL}, + {"atleast-version", '\0', 0, G_OPTION_ARG_STRING, &min_version, + N_ + ("When checking if an element or plugin exists, also check that its " + "version is at least the version specified"), NULL}, + {"uri-handlers", 'u', 0, G_OPTION_ARG_NONE, &uri_handlers, + N_ + ("Print supported URI schemes, with the elements that implement them"), + NULL}, + GST_TOOLS_GOPTION_VERSION, + {NULL} + }; + GOptionContext *ctx; + GError *err = NULL; +#endif + + setlocale (LC_ALL, ""); + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + /* avoid glib warnings when inspecting deprecated properties */ + g_setenv ("G_ENABLE_DIAGNOSTIC", "0", FALSE); + + g_set_prgname ("gst-inspect-" GST_API_VERSION); + +#ifndef GST_DISABLE_OPTION_PARSING + ctx = g_option_context_new ("[ELEMENT-NAME | PLUGIN-NAME]"); + g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_printerr ("Error initializing: %s\n", err->message); + g_clear_error (&err); + g_option_context_free (ctx); + return -1; + } + g_option_context_free (ctx); +#else + gst_init (&argc, &argv); +#endif + + gst_tools_print_version (); + + if (print_all && argc > 1) { + g_printerr ("-a requires no extra arguments\n"); + return -1; + } + + if (uri_handlers && argc > 1) { + g_printerr ("-u requires no extra arguments\n"); + return -1; + } + + /* --atleast-version implies --exists */ + if (min_version != NULL) { + if (sscanf (min_version, "%u.%u.%u", &minver_maj, &minver_min, + &minver_micro) < 2) { + g_printerr ("Can't parse version '%s' passed to --atleast-version\n", + min_version); + return -1; + } + check_exists = TRUE; + } + + if (check_exists) { + int exit_code; + + if (argc == 1) { + g_printerr ("--exists requires an extra command line argument\n"); + exit_code = -1; + } else { + if (!plugin_name) { + GstPluginFeature *feature; + + feature = gst_registry_lookup_feature (gst_registry_get (), argv[1]); + if (feature != NULL && gst_plugin_feature_check_version (feature, + minver_maj, minver_min, minver_micro)) { + exit_code = 0; + } else { + exit_code = 1; + } + + if (feature) + gst_object_unref (feature); + } else { + /* FIXME: support checking for plugins too */ + g_printerr ("Checking for plugins is not supported yet\n"); + exit_code = -1; + } + } + return exit_code; + } + + /* if no arguments, print out list of elements */ + if (uri_handlers) { + print_all_uri_handlers (); + } else if (argc == 1 || print_all) { + if (do_print_blacklist) + print_blacklist (); + else { + if (print_aii) + print_all_plugin_automatic_install_info (); + else + print_element_list (print_all, types); + } + } else { + /* else we try to get a factory */ + const char *arg = argv[argc - 1]; + int retval = -1; + + if (!plugin_name) { + retval = print_feature_info (arg, print_all); + } + + /* otherwise check if it's a plugin */ + if (retval) { + GstPlugin *plugin = gst_registry_find_plugin (gst_registry_get (), arg); + + /* if there is such a plugin, print out info */ + if (plugin) { + if (print_aii) { + print_plugin_automatic_install_info (plugin); + } else { + print_plugin_info (plugin); + print_plugin_features (plugin); + } + } else { + GError *error = NULL; + + if (g_file_test (arg, G_FILE_TEST_EXISTS)) { + plugin = gst_plugin_load_file (arg, &error); + + if (plugin) { + if (print_aii) { + print_plugin_automatic_install_info (plugin); + } else { + print_plugin_info (plugin); + print_plugin_features (plugin); + } + } else { + g_printerr (_("Could not load plugin file: %s\n"), error->message); + g_clear_error (&error); + return -1; + } + } else { + g_printerr (_("No such element or plugin '%s'\n"), arg); + return -1; + } + } + } + } + + return 0; +} diff --git a/tools/gst-launch-1.0.1 b/tools/gst-launch-1.0.1 new file mode 100644 index 0000000..33a7d14 --- /dev/null +++ b/tools/gst-launch-1.0.1 @@ -0,0 +1,495 @@ +.TH "GStreamer" "1" "May 2007" +.SH "NAME" +gst\-launch\-1.0 \- build and run a GStreamer pipeline +.SH "SYNOPSIS" +\fBgst\-launch\-1.0\fR \fI[OPTION...]\fR PIPELINE\-DESCRIPTION +.SH "DESCRIPTION" +.LP +\fIgst\-launch\-1.0\fP is a tool that builds and runs basic +\fIGStreamer\fP pipelines. + +In simple form, a PIPELINE\-DESCRIPTION is a list of +elements separated by exclamation marks (!). Properties may be appended to +elements, in the form \fIproperty=value\fR. + +For a complete description of possible PIPELINE-DESCRIPTIONS see the section +\fIpipeline description\fR below or consult the GStreamer documentation. + +Please note that \fIgst\-launch\-1.0\fP is primarily a debugging tool for +developers and users. You should not build applications on top of it. For +applications, use the gst_parse_launch() function of the GStreamer API as an +easy way to construct pipelines from pipeline descriptions. +. +.SH "OPTIONS" +.l +\fIgst\-launch\-1.0\fP accepts the following options: +.TP 8 +.B \-\-help +Print help synopsis and available FLAGS +.TP 8 +.B \-v, \-\-verbose +Output status information and property notifications +.TP 8 +.B \-q, \-\-quiet +Do not print any progress information +.TP 8 +.B \-m, \-\-messages +Output messages posted on the pipeline's bus +.TP 8 +.B \-t, \-\-tags +Output tags (also known as metadata) +.TP 8 +.B \-e, \-\-eos\-on\-shutdown +Force an EOS event on sources before shutting the pipeline down. This is +useful to make sure muxers create readable files when a muxing pipeline is +shut down forcefully via Control-C. +.TP 8 +.B \-i, \-\-index +Gather and print index statistics. This is mostly useful for playback or +recording pipelines. +.TP 8 +.B \-f, \-\-no\-fault +Do not install a fault handler +.TP 8 +.B \-T, \-\-trace +Print memory allocation traces. The feature must be enabled at compile time to +work. +.TP 8 + +. +.SH "GSTREAMER OPTIONS" +.l +\fIgst\-launch\-1.0\fP also accepts the following options that are common +to all GStreamer applications: +.TP 8 +.B \-\-gst\-version +Prints the version string of the \fIGStreamer\fP core library. +.TP 8 +.B \-\-gst\-fatal\-warnings +Causes \fIGStreamer\fP to abort if a warning message occurs. This is equivalent +to setting the environment variable G_DEBUG to 'fatal_warnings' (see the +section \fIenvironment variables\fR below for further information). +.TP 8 +.B \-\-gst\-debug=STRING +A comma separated list of category_name:level pairs to specify debugging levels +for each category. Level is in the range 0-9 where 0 will show no messages, and +9 will show all messages. The wildcard * can be used to match category names. +Note that the order of categories and levels is important, wildcards at the +end may override levels set earlier. The log levels are: 1=ERROR, 2=WARNING, +3=FIXME, 4=INFO, 5=DEBUG, 6=LOG, 7=TRACE, 9=MEMDUMP. Since GStreamer 1.2 one +can also use the debug level names, e.g. \-\-gst\-debug=*sink:LOG. A full +description of the various debug levels can be found in the GStreamer core +library API documentation, in the "Running GStreamer Applications" section. + +Use \-\-gst\-debug\-help to show category names + +Example: +GST_CAT:5,GST_ELEMENT_*:3,oggdemux:5 + +.TP 8 +.B \-\-gst\-debug\-level=LEVEL +Sets the threshold for printing debugging messages. A higher level +will print more messages. The useful range is 0-9, with the default +being 0. Level 6 (LOG level) will show all information that is usually +required for debugging purposes. Higher levels are only useful in very +specific cases. See above for the full list of levels. +.TP 8 +.B \-\-gst\-debug\-no\-color +\fIGStreamer\fP normally prints debugging messages so that the +messages are color-coded when printed to a terminal that handles +ANSI escape sequences. Using this option causes \fIGStreamer\fP +to print messages without color. Setting the \fBGST_DEBUG_NO_COLOR\fR +environment variable will achieve the same thing. +.TP 8 +.B \-\-gst\-debug\-color\-mode +\fIGStreamer\fP normally prints debugging messages so that the +messages are color-coded when printed to a terminal that handles +ANSI escape sequences (on *nix), or uses W32 console API to color the +messages printed into a console (on W32). Using this option causes +\fIGStreamer\fP to print messages without color ('off' or 'disable'), +print messages with default colors ('on' or 'auto'), or print messages +using ANSI escape sequences for coloring ('unix'). Setting the +\fBGST_DEBUG_COLOR_MODE\fR environment variable will achieve the same thing. +.TP 8 +.B \-\-gst\-debug\-disable +Disables debugging. +.TP 8 +.B \-\-gst\-debug\-help +Prints a list of available debug categories and their default debugging level. +.TP 8 +.B \-\-gst\-plugin\-spew +\fIGStreamer\fP info flags to set +Enable printout of errors while loading \fIGStreamer\fP plugins +.TP 8 +.B \-\-gst\-plugin\-path=PATH +Add directories separated with ':' to the plugin search path +.TP 8 +.B \-\-gst\-plugin\-load=PLUGINS +Preload plugins specified in a comma-separated list. Another way to specify +plugins to preload is to use the environment variable GST_PLUGIN_PATH + +.SH "PIPELINE DESCRIPTION" + +A pipeline consists \fIelements\fR and \fIlinks\fR. \fIElements\fR can be put +into \fIbins\fR of different sorts. \fIElements\fR, \fIlinks\fR and \fIbins\fR +can be specified in a pipeline description in any order. + +.B Elements + +ELEMENTTYPE \fI[PROPERTY1 ...]\fR + +Creates an element of type ELEMENTTYPE and sets the PROPERTIES. + +.B Properties + +PROPERTY=VALUE ... + +Sets the property to the specified value. You can use \fBgst\-inspect\-1.0\fR(1) to +find out about properties and allowed values of different elements. +.br +Enumeration properties can be set by name, nick or value. + +.B Bins + +\fI[BINTYPE.]\fR ( \fI[PROPERTY1 ...]\fR PIPELINE-DESCRIPTION ) +.br + +Specifies that a bin of type BINTYPE is created and the given properties are +set. Every element between the braces is put into the bin. Please note the dot +that has to be used after the BINTYPE. You will almost never need this +functionality, it is only really useful for applications using the +gst_launch_parse() API with 'bin' as bintype. That way it is possible to build +partial pipelines instead of a full-fledged top-level pipeline. + +.B Links + +\fI[[SRCELEMENT].[PAD1,...]]\fR ! \fI[[SINKELEMENT].[PAD1,...]]\fR +\fI[[SRCELEMENT].[PAD1,...]]\fR ! CAPS ! \fI[[SINKELEMENT].[PAD1,...]]\fR +\fI[[SRCELEMENT].[PAD1,...]]\fR : \fI[[SINKELEMENT].[PAD1,...]]\fR +\fI[[SRCELEMENT].[PAD1,...]]\fR : CAPS : \fI[[SINKELEMENT].[PAD1,...]]\fR + +Links the element with name SRCELEMENT to the element with name SINKELEMENT, +using the caps specified in CAPS as a filter. +Names can be set on elements with the name property. If the name is omitted, the +element that was specified directly in front of or after the link is used. This +works across bins. If a padname is given, the link is done with these pads. If +no pad names are given all possibilities are tried and a matching pad is used. +If multiple padnames are given, both sides must have the same number of pads +specified and multiple links are done in the given order. +.br +So the simplest link is a simple exclamation mark, that links the element to +the left of it to the element right of it. +.br +Linking using the : operator attempts to link all possible pads between +the elements +.br + +.B Caps + +MEDIATYPE \fI[, PROPERTY[, PROPERTY ...]]]\fR \fI[; CAPS[; CAPS ...]]\fR + +Creates a capability with the given media type and optionally with given +properties. The media type can be escaped using " or '. +If you want to chain caps, you can add more caps in the same format afterwards. + +.B Properties + +NAME=\fI[(TYPE)]\fRVALUE +.br +in lists and ranges: \fI[(TYPE)]\fRVALUE + +Sets the requested property in capabilities. The name is an alphanumeric value +and the type can have the following case-insensitive values: +.br +- \fBi\fR or \fBint\fR for integer values or ranges +.br +- \fBf\fR or \fBfloat\fR for float values or ranges +.br +- \fBb\fR, \fBbool\fR or \fBboolean\fR for boolean values +.br +- \fBs\fR, \fBstr\fR or \fBstring\fR for strings +.br +- \fBfraction\fR for fractions (framerate, pixel\-aspect\-ratio) +.br +- \fBl\fR or \fBlist\fR for lists +.br +If no type was given, the following order is tried: integer, float, boolean, +string. +.br +Integer values must be parsable by \fBstrtol()\fP, floats by \fBstrtod()\fP. FOURCC values may +either be integers or strings. Boolean values are (case insensitive) \fIyes\fR, +\fIno\fR, \fItrue\fR or \fIfalse\fR and may like strings be escaped with " or '. +.br +Ranges are in this format: [ VALUE, VALUE ] +.br +Lists use this format: { VALUE \fI[, VALUE ...]\fR } + +.SH "PIPELINE EXAMPLES" + +The examples below assume that you have the correct plug-ins available. +In general, "pulsesink" can be substituted with another audio output +plug-in such as "alsasink" or "osxaudiosink" +Likewise, "xvimagesink" can be substituted with "ximagesink", "glimagesink", +or "osxvideosink". Keep in mind though that different sinks might +accept different formats and even the same sink might accept different formats +on different machines, so you might need to add converter elements like +audioconvert and audioresample (for audio) or videoconvert (for video) +in front of the sink to make things work. + +.B Audio playback + +Play the mp3 music file "music.mp3" using a libmpg123-based plug-in and +output to an Pulseaudio device +.br +.B + gst\-launch\-1.0 filesrc location=music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink + +Play an Ogg Vorbis format file +.br +.B + gst\-launch\-1.0 filesrc location=music.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! pulsesink + +Play an mp3 file or an http stream using GIO +.br +.B + gst\-launch\-1.0 giosrc location=music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! pulsesink +.br +.B + gst\-launch\-1.0 giosrc location=http://domain.com/music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink + +Use GIO to play an mp3 file located on an SMB server +.br +.B + gst\-launch\-1.0 giosrc location=smb://computer/music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink + +.B Format conversion + +Convert an mp3 music file to an Ogg Vorbis file +.br +.B + gst\-launch\-1.0 filesrc location=music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! vorbisenc ! oggmux ! filesink location=music.ogg + +Convert to the FLAC format +.br +.B + gst\-launch\-1.0 filesrc location=music.mp3 ! mpegaudioparse ! mpg123audiodec ! audioconvert ! flacenc ! filesink location=test.flac + +.B Other + +Plays a .WAV file that contains raw audio data (PCM). +.br +.B + gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! audioresample ! pulsesink + +Convert a .WAV file containing raw audio data into an Ogg Vorbis or mp3 file +.br +.B + gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! vorbisenc ! oggmux ! filesink location=music.ogg +.br +.B + gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! lamemp3enc ! filesink location=music.mp3 + +Rips all tracks from compact disc and convert them into a single mp3 file +.br +.B + gst\-launch\-1.0 cdparanoiasrc mode=continuous ! audioconvert ! lamemp3enc ! mpegaudioparse ! id3v2mux ! filesink location=cd.mp3 + +Rips track 5 from the CD and converts it into a single mp3 file +.br +.B + gst\-launch\-1.0 cdparanoiasrc track=5 ! audioconvert ! lamemp3enc ! mpegaudioparse ! id3v2mux ! filesink location=track5.mp3 + +Using \fBgst\-inspect\-1.0\fR(1), it is possible to discover settings like the above +for cdparanoiasrc that will tell it to rip the entire cd or only tracks of it. +Alternatively, you can use an URI and gst\-launch\-1.0 will find an element (such as +cdparanoia) that supports that protocol for you, e.g.: +.B + gst\-launch\-1.0 cdda://5 ! lamemp3enc vbr=new vbr\-quality=6 ! filesink location=track5.mp3 + +Records sound from your audio input and encodes it into an ogg file +.br +.B + gst\-launch\-1.0 pulsesrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=input.ogg + +.B Video + +Display only the video portion of an MPEG-1 video file, outputting to +an X display window +.br +.B + gst\-launch\-1.0 filesrc location=JB_FF9_TheGravityOfLove.mpg ! dvddemux ! mpegvideoparse ! mpeg2dec ! xvimagesink + +Display the video portion of a .vob file (used on DVDs), outputting to +an SDL window +.br +.B + gst\-launch\-1.0 filesrc location=/flflfj.vob ! dvddemux ! mpegvideoparse ! mpeg2dec ! sdlvideosink + +Play both video and audio portions of an MPEG movie +.br +.B + gst\-launch\-1.0 filesrc location=movie.mpg ! dvddemux name=demuxer demuxer. ! queue ! mpegvideoparse ! mpeg2dec ! sdlvideosink demuxer. ! queue ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink + +Play an AVI movie with an external text subtitle stream +.br +.B + gst\-launch\-1.0 filesrc location=movie.mpg ! mpegdemux name=demuxer demuxer. ! queue ! mpegvideoparse ! mpeg2dec ! videoconvert ! sdlvideosink demuxer. ! queue ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink + +This example also shows how to refer to specific pads by name if an element +(here: textoverlay) has multiple sink or source pads. +.br +.B + gst\-launch\-1.0 textoverlay name=overlay ! videoconvert ! videoscale ! autovideosink filesrc location=movie.avi ! decodebin ! videoconvert ! overlay.video_sink filesrc location=movie.srt ! subparse ! overlay.text_sink + +Play an AVI movie with an external text subtitle stream using playbin +.br +.B + gst\-launch\-1.0 playbin uri=file:///path/to/movie.avi suburi=file:///path/to/movie.srt + +.B Network streaming + +Stream video using RTP and network elements. + +This command would be run on the transmitter +.br +.B + gst\-launch\-1.0 v4l2src ! video/x\-raw,width=128,height=96,format=UYVY ! videoconvert ! ffenc_h263 ! video/x\-h263 ! rtph263ppay pt=96 ! udpsink host=192.168.1.1 port=5000 + +Use this command on the receiver +.br +.B + gst\-launch\-1.0 udpsrc port=5000 ! application/x\-rtp, clock\-rate=90000,payload=96 ! rtph263pdepay queue\-delay=0 ! ffdec_h263 ! xvimagesink + +.B Diagnostic + +Generate a null stream and ignore it (and print out details). +.br +.B + gst\-launch\-1.0 \-v fakesrc num\-buffers=16 ! fakesink + +Generate a pure sine tone to test the audio output +.br +.B + gst\-launch\-1.0 audiotestsrc ! audioconvert ! audioresample ! pulsesink + +Generate a familiar test pattern to test the video output +.br +.B + gst\-launch\-1.0 videotestsrc ! xvimagesink +.br +.B + gst\-launch\-1.0 videotestsrc ! ximagesink + +.B Automatic linking + +You can use the decodebin element to automatically select the right elements +to get a working pipeline. + +Play any supported audio format +.br +.B + gst\-launch\-1.0 filesrc location=musicfile ! decodebin ! audioconvert ! audioresample ! pulsesink + +Play any supported video format with video and audio output. Threads are used +automatically. To make this even easier, you can use the playbin element: +.br +.B + gst\-launch\-1.0 filesrc location=videofile ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! pulsesink decoder. ! videoconvert ! xvimagesink +.br +.B + gst\-launch\-1.0 playbin uri=file:///home/joe/foo.avi + + +.B Filtered connections + +These examples show you how to use filtered caps. + +Show a test image and use the YUY2 or YV12 video format for this. +.br +.B + gst\-launch\-1.0 videotestsrc ! 'video/x\-raw,format=YUY2;video/x\-raw,format=YV12' ! xvimagesink + +Record audio and write it to a .wav file. Force usage of signed 16 to 32 bit +samples and a sample rate between 32kHz and 64KHz. +.br +.B + gst\-launch\-1.0 pulsesrc ! 'audio/x\-raw,rate=[32000,64000],format={S16LE,S24LE,S32LE}' ! wavenc ! filesink location=recording.wav + + +.SH "ENVIRONMENT VARIABLES" +.TP +\fBGST_DEBUG\fR +Comma-separated list of debug categories and levels (e.g. +GST_DEBUG=totem:4,typefind:5). '*' is allowed as a wildcard as part of +debug category names (e.g. GST_DEBUG=*sink:6,*audio*:6). Since 1.2.0 it is +also possible to specify the log level by name (1=ERROR, 2=WARN, 3=FIXME, +4=INFO, 5=DEBUG, 6=LOG, 7=TRACE, 9=MEMDUMP) (e.g. GST_DEBUG=*audio*:LOG) +.TP +\fBGST_DEBUG_NO_COLOR\fR +When this environment variable is set, coloured debug output is disabled. +.TP +\fBGST_DEBUG_DUMP_DOT_DIR\fR +When set to a filesystem path, store 'dot' files of pipeline graphs there. +These can then later be converted into an image using the 'dot' utility from +the graphviz set of tools, like this: dot foo.dot \-Tsvg \-o foo.svg (png or jpg +are also possible as output format). There is also a utility called 'xdot' +which allows you to view the .dot file directly without converting it first. +.br +When the pipeline changes state through NULL to PLAYING and back to NULL, a +dot file is generated on each state change. To write a snapshot of the +pipeline state, send a SIGHUP to the process. +.TP +\fBGST_REGISTRY\fR +Path of the plugin registry file. Default is +~/.cache/gstreamer\-1.0/registry\-CPU.bin where CPU is the +machine/cpu type GStreamer was compiled for, e.g. 'i486', 'i686', 'x86\-64', 'ppc', +etc. (check the output of "uname \-i" and "uname \-m" for details). +.TP +\fBGST_REGISTRY_UPDATE\fR +Set to "no" to force GStreamer to assume that no plugins have changed, +been added or been removed. This will make GStreamer skip the initial check +whether a rebuild of the registry cache is required or not. This may be useful +in embedded environments where the installed plugins never change. Do not +use this option in any other setup. +.TP +\fBGST_PLUGIN_PATH\fR +Specifies a list of directories to scan for additional plugins. +These take precedence over the system plugins. +.TP +\fBGST_PLUGIN_SYSTEM_PATH\fR +Specifies a list of plugins that are always loaded by default. If not set, +this defaults to the system-installed path, and the plugins installed in the +user's home directory +.TP +\fBGST_DEBUG_FILE\fR +Set this variable to a file path to redirect all GStreamer debug +messages to this file. If left unset, debug messages with be output +unto the standard error. +.TP +\fBORC_CODE\fR +Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers +such as gdb to create useful backtraces from Orc-generated code. Set +ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code +generator is producing incorrect code. (Quite a few important +GStreamer plugins like videotestsrc, audioconvert or audioresample use Orc). +.TP +\fBG_DEBUG\fR +Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make +GStreamer programs abort when a critical warning such as an assertion failure +occurs. This is useful if you want to find out which part of the code caused +that warning to be triggered and under what circumstances. Simply set G_DEBUG +as mentioned above and run the program in gdb (or let it core dump). Then get +a stack trace in the usual way. +. +.SH FILES +.TP 8 +~/.cache/gstreamer\-1.0/registry\-*.bin +The plugin cache; can be deleted at any time, will be re-created +automatically when it does not exist yet or plugins change. Based on +XDG_CACHE_DIR, so may be in a different location than the one suggested. +. +.SH "SEE ALSO" +.BR gst\-inspect\-1.0 (1), +.BR gst\-launch\-1.0 (1), +.SH "AUTHOR" +The GStreamer team at http://gstreamer.freedesktop.org/ diff --git a/tools/gst-launch.c b/tools/gst-launch.c new file mode 100644 index 0000000..f19b0dc --- /dev/null +++ b/tools/gst-launch.c @@ -0,0 +1,1267 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2004 Thomas Vander Stichele + * + * gst-launch.c: tool to launch GStreamer pipelines from the command line + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef G_OS_UNIX +#include +#include +#elif defined (G_OS_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#endif +#include /* for LC_ALL */ +#include "tools.h" + +extern volatile gboolean glib_on_error_halt; + +#ifdef G_OS_UNIX +static void fault_restore (void); +static void fault_spin (void); +#endif + +/* event_loop return codes */ +typedef enum _EventLoopResult +{ + ELR_NO_ERROR = 0, + ELR_ERROR, + ELR_INTERRUPT +} EventLoopResult; + +static GstElement *pipeline; +static EventLoopResult caught_error = ELR_NO_ERROR; +static gboolean quiet = FALSE; +static gboolean tags = FALSE; +static gboolean toc = FALSE; +static gboolean messages = FALSE; +static gboolean is_live = FALSE; +static gboolean waiting_eos = FALSE; +static gchar **exclude_args = NULL; + +/* convenience macro so we don't have to litter the code with if(!quiet) */ +#define PRINT if(!quiet)g_print + +#ifdef G_OS_UNIX +static void +fault_handler_sighandler (int signum) +{ + fault_restore (); + + /* printf is used instead of g_print(), since it's less likely to + * deadlock */ + switch (signum) { + case SIGSEGV: + fprintf (stderr, "Caught SIGSEGV\n"); + break; + case SIGQUIT: + if (!quiet) + printf ("Caught SIGQUIT\n"); + break; + default: + fprintf (stderr, "signo: %d\n", signum); + break; + } + + fault_spin (); +} + +static void +fault_spin (void) +{ + int spinning = TRUE; + + glib_on_error_halt = FALSE; + g_on_error_stack_trace ("gst-launch-" GST_API_VERSION); + + wait (NULL); + + /* FIXME how do we know if we were run by libtool? */ + fprintf (stderr, + "Spinning. Please run 'gdb gst-launch-" GST_API_VERSION " %d' to " + "continue debugging, Ctrl-C to quit, or Ctrl-\\ to dump core.\n", + (gint) getpid ()); + while (spinning) + g_usleep (1000000); +} + +static void +fault_restore (void) +{ + struct sigaction action; + + memset (&action, 0, sizeof (action)); + action.sa_handler = SIG_DFL; + + sigaction (SIGSEGV, &action, NULL); + sigaction (SIGQUIT, &action, NULL); +} + +static void +fault_setup (void) +{ + struct sigaction action; + + memset (&action, 0, sizeof (action)); + action.sa_handler = fault_handler_sighandler; + + sigaction (SIGSEGV, &action, NULL); + sigaction (SIGQUIT, &action, NULL); +} +#endif /* G_OS_UNIX */ + +#if 0 +typedef struct _GstIndexStats +{ + gint id; + gchar *desc; + + guint num_frames; + guint num_keyframes; + guint num_dltframes; + GstClockTime last_keyframe; + GstClockTime last_dltframe; + GstClockTime min_keyframe_gap; + GstClockTime max_keyframe_gap; + GstClockTime avg_keyframe_gap; +} GstIndexStats; + +static void +entry_added (GstIndex * index, GstIndexEntry * entry, gpointer user_data) +{ + GPtrArray *index_stats = (GPtrArray *) user_data; + GstIndexStats *s; + + switch (entry->type) { + case GST_INDEX_ENTRY_ID: + /* we have a new writer */ + GST_DEBUG_OBJECT (index, "id %d: describes writer %s", entry->id, + GST_INDEX_ID_DESCRIPTION (entry)); + if (entry->id >= index_stats->len) { + g_ptr_array_set_size (index_stats, entry->id + 1); + } + s = g_new (GstIndexStats, 1); + s->id = entry->id; + s->desc = g_strdup (GST_INDEX_ID_DESCRIPTION (entry)); + s->num_frames = s->num_keyframes = s->num_dltframes = 0; + s->last_keyframe = s->last_dltframe = GST_CLOCK_TIME_NONE; + s->min_keyframe_gap = s->max_keyframe_gap = s->avg_keyframe_gap = + GST_CLOCK_TIME_NONE; + g_ptr_array_index (index_stats, entry->id) = s; + break; + case GST_INDEX_ENTRY_FORMAT: + /* have not found any code calling this */ + GST_DEBUG_OBJECT (index, "id %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: + { + gint64 ts; + GstAssocFlags flags = GST_INDEX_ASSOC_FLAGS (entry); + + s = g_ptr_array_index (index_stats, entry->id); + gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts); + + if (flags & GST_ASSOCIATION_FLAG_KEY_UNIT) { + s->num_keyframes++; + + if (GST_CLOCK_TIME_IS_VALID (ts)) { + if (GST_CLOCK_TIME_IS_VALID (s->last_keyframe)) { + GstClockTimeDiff d = GST_CLOCK_DIFF (s->last_keyframe, ts); + + if (G_UNLIKELY (d < 0)) { + GST_WARNING ("received out-of-order keyframe at %" + GST_TIME_FORMAT, GST_TIME_ARGS (ts)); + /* FIXME: does it still make sense to use that for the statistics */ + d = GST_CLOCK_DIFF (ts, s->last_keyframe); + } + + if (GST_CLOCK_TIME_IS_VALID (s->min_keyframe_gap)) { + if (d < s->min_keyframe_gap) + s->min_keyframe_gap = d; + } else { + s->min_keyframe_gap = d; + } + if (GST_CLOCK_TIME_IS_VALID (s->max_keyframe_gap)) { + if (d > s->max_keyframe_gap) + s->max_keyframe_gap = d; + } else { + s->max_keyframe_gap = d; + } + if (GST_CLOCK_TIME_IS_VALID (s->avg_keyframe_gap)) { + s->avg_keyframe_gap = (d + s->num_frames * s->avg_keyframe_gap) / + (s->num_frames + 1); + } else { + s->avg_keyframe_gap = d; + } + } + s->last_keyframe = ts; + } + } + if (flags & GST_ASSOCIATION_FLAG_DELTA_UNIT) { + s->num_dltframes++; + if (GST_CLOCK_TIME_IS_VALID (ts)) { + s->last_dltframe = ts; + } + } + s->num_frames++; + + break; + } + default: + break; + } +} + +/* print statistics from the entry_added callback, free the entries */ +static void +print_index_stats (GPtrArray * index_stats) +{ + gint i; + + if (index_stats->len) { + g_print ("%s:\n", _("Index statistics")); + } + + for (i = 0; i < index_stats->len; i++) { + GstIndexStats *s = g_ptr_array_index (index_stats, i); + if (s) { + g_print ("id %d, %s\n", s->id, s->desc); + if (s->num_frames) { + GstClockTime last_frame = s->last_keyframe; + + if (GST_CLOCK_TIME_IS_VALID (s->last_dltframe)) { + if (!GST_CLOCK_TIME_IS_VALID (last_frame) || + (s->last_dltframe > last_frame)) + last_frame = s->last_dltframe; + } + + if (GST_CLOCK_TIME_IS_VALID (last_frame)) { + g_print (" total time = %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (last_frame)); + } + g_print (" frame/keyframe rate = %u / %u = ", s->num_frames, + s->num_keyframes); + if (s->num_keyframes) + g_print ("%lf\n", s->num_frames / (gdouble) s->num_keyframes); + else + g_print ("-\n"); + if (s->num_keyframes) { + g_print (" min/avg/max keyframe gap = %" GST_TIME_FORMAT ", %" + GST_TIME_FORMAT ", %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (s->min_keyframe_gap), + GST_TIME_ARGS (s->avg_keyframe_gap), + GST_TIME_ARGS (s->max_keyframe_gap)); + } + } else { + g_print (" no stats\n"); + } + + g_free (s->desc); + g_free (s); + } + } +} +#endif + +/* Kids, use the functions from libgstpbutils in gst-plugins-base in your + * own code (we can't do that here because it would introduce a circular + * dependency) */ +static gboolean +gst_is_missing_plugin_message (GstMessage * msg) +{ + if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT + || gst_message_get_structure (msg) == NULL) + return FALSE; + + return gst_structure_has_name (gst_message_get_structure (msg), + "missing-plugin"); +} + +static const gchar * +gst_missing_plugin_message_get_description (GstMessage * msg) +{ + return gst_structure_get_string (gst_message_get_structure (msg), "name"); +} + +static void +print_error_message (GstMessage * msg) +{ + GError *err = NULL; + gchar *name, *debug = NULL; + + name = gst_object_get_path_string (msg->src); + gst_message_parse_error (msg, &err, &debug); + + g_printerr (_("ERROR: from element %s: %s\n"), name, err->message); + if (debug != NULL) + g_printerr (_("Additional debug info:\n%s\n"), debug); + + g_clear_error (&err); + g_free (debug); + g_free (name); +} + +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 = NULL; + + if (gst_tag_get_type (tag) == G_TYPE_STRING) { + if (!gst_tag_list_get_string_index (list, tag, i, &str)) { + g_warning ("Couldn't fetch string for %s tag", tag); + g_assert_not_reached (); + } + } else if (gst_tag_get_type (tag) == GST_TYPE_SAMPLE) { + GstSample *sample = NULL; + + if (gst_tag_list_get_sample_index (list, tag, i, &sample)) { + GstBuffer *img = gst_sample_get_buffer (sample); + GstCaps *caps = gst_sample_get_caps (sample); + + if (img) { + if (caps) { + gchar *caps_str; + + caps_str = gst_caps_to_string (caps); + str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes, " + "type: %s", gst_buffer_get_size (img), caps_str); + g_free (caps_str); + } else { + str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes", + gst_buffer_get_size (img)); + } + } else { + str = g_strdup ("NULL buffer"); + } + } else { + g_warning ("Couldn't fetch sample for %s tag", tag); + g_assert_not_reached (); + } + gst_sample_unref (sample); + } else if (gst_tag_get_type (tag) == GST_TYPE_DATE_TIME) { + GstDateTime *dt = NULL; + + gst_tag_list_get_date_time_index (list, tag, i, &dt); + if (!gst_date_time_has_time (dt)) { + str = gst_date_time_to_iso8601_string (dt); + } else { + gdouble tz_offset = gst_date_time_get_time_zone_offset (dt); + gchar tz_str[32]; + + if (tz_offset != 0.0) { + g_snprintf (tz_str, sizeof (tz_str), "(UTC %s%gh)", + (tz_offset > 0.0) ? "+" : "", tz_offset); + } else { + g_snprintf (tz_str, sizeof (tz_str), "(UTC)"); + } + + str = g_strdup_printf ("%04u-%02u-%02u %02u:%02u:%02u %s", + 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), + tz_str); + } + gst_date_time_unref (dt); + } else { + str = + g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i)); + } + + if (str) { + PRINT ("%16s: %s\n", i == 0 ? gst_tag_get_nick (tag) : "", str); + g_free (str); + } + } +} + +static void +print_tag_foreach (const GstTagList * tags, const gchar * tag, + gpointer user_data) +{ + GValue val = { 0, }; + gchar *str; + gint depth = GPOINTER_TO_INT (user_data); + + if (!gst_tag_list_copy_value (&val, tags, tag)) + return; + + if (G_VALUE_HOLDS_STRING (&val)) + str = g_value_dup_string (&val); + else + str = gst_value_serialize (&val); + + g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str); + g_free (str); + + g_value_unset (&val); +} + +#define MAX_INDENT 40 + +static void +print_toc_entry (gpointer data, gpointer user_data) +{ + GstTocEntry *entry = (GstTocEntry *) data; + const gchar spc[MAX_INDENT + 1] = " "; + guint indent = MIN (GPOINTER_TO_UINT (user_data), MAX_INDENT); + const GstTagList *tags; + GList *subentries; + gint64 start, stop; + + gst_toc_entry_get_start_stop_times (entry, &start, &stop); + + PRINT ("%s%s:", &spc[MAX_INDENT - indent], + gst_toc_entry_type_get_nick (gst_toc_entry_get_entry_type (entry))); + if (GST_CLOCK_TIME_IS_VALID (start)) { + PRINT (" start: %" GST_TIME_FORMAT, GST_TIME_ARGS (start)); + } + if (GST_CLOCK_TIME_IS_VALID (stop)) { + PRINT (" stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (stop)); + } + PRINT ("\n"); + indent += 2; + + /* print tags */ + tags = gst_toc_entry_get_tags (entry); + if (tags) + gst_tag_list_foreach (tags, print_tag_foreach, GUINT_TO_POINTER (indent)); + + /* loop over sub-toc entries */ + subentries = gst_toc_entry_get_sub_entries (entry); + g_list_foreach (subentries, print_toc_entry, GUINT_TO_POINTER (indent)); +} + +#ifdef G_OS_UNIX +static guint signal_watch_hup_id; +#endif +#if defined(G_OS_UNIX) || defined(G_OS_WIN32) +static guint signal_watch_intr_id; +#if defined(G_OS_WIN32) +static GstElement *intr_pipeline; +#endif +#endif + +#if defined(G_OS_UNIX) || defined(G_OS_WIN32) +/* As the interrupt handler is dispatched from GMainContext as a GSourceFunc + * handler, we can react to this by posting a message. */ +static gboolean +intr_handler (gpointer user_data) +{ + GstElement *pipeline = (GstElement *) user_data; + + PRINT ("handling interrupt.\n"); + + /* post an application specific message */ + gst_element_post_message (GST_ELEMENT (pipeline), + gst_message_new_application (GST_OBJECT (pipeline), + gst_structure_new ("GstLaunchInterrupt", + "message", G_TYPE_STRING, "Pipeline interrupted", NULL))); + + /* remove signal handler */ + signal_watch_intr_id = 0; + return G_SOURCE_REMOVE; +} + +#ifdef G_OS_UNIX +static gboolean +hup_handler (gpointer user_data) +{ + GstElement *pipeline = (GstElement *) user_data; + + if (g_getenv ("GST_DEBUG_DUMP_DOT_DIR") != NULL) { + PRINT ("SIGHUP: dumping dot file snapshot ...\n"); + } else { + PRINT ("SIGHUP: not dumping dot file snapshot, GST_DEBUG_DUMP_DOT_DIR " + "environment variable not set.\n"); + } + + /* dump graph on hup */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.snapshot"); + + return G_SOURCE_CONTINUE; +} +#endif + +#if defined(G_OS_WIN32) /* G_OS_UNIX */ +static BOOL WINAPI +w32_intr_handler (DWORD dwCtrlType) +{ + intr_handler ((gpointer) intr_pipeline); + intr_pipeline = NULL; + return TRUE; +} +#endif /* G_OS_WIN32 */ +#endif /* G_OS_UNIX */ + +/* returns ELR_ERROR if there was an error + * or ELR_INTERRUPT if we caught a keyboard interrupt + * or ELR_NO_ERROR otherwise. */ +static EventLoopResult +event_loop (GstElement * pipeline, gboolean blocking, gboolean do_progress, + GstState target_state) +{ + GstBus *bus; + GstMessage *message = NULL; + EventLoopResult res = ELR_NO_ERROR; + gboolean buffering = FALSE, in_progress = FALSE; + gboolean prerolled = target_state != GST_STATE_PAUSED; + + bus = gst_element_get_bus (GST_ELEMENT (pipeline)); + +#ifdef G_OS_UNIX + signal_watch_intr_id = + g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline); + signal_watch_hup_id = + g_unix_signal_add (SIGHUP, (GSourceFunc) hup_handler, pipeline); +#elif defined(G_OS_WIN32) + intr_pipeline = NULL; + if (SetConsoleCtrlHandler (w32_intr_handler, TRUE)) + intr_pipeline = pipeline; +#endif + + while (TRUE) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0); + + /* if the poll timed out, only when !blocking */ + if (message == NULL) + goto exit; + + /* check if we need to dump messages to the console */ + if (messages) { + GstObject *src_obj; + const GstStructure *s; + guint32 seqnum; + + seqnum = gst_message_get_seqnum (message); + + s = gst_message_get_structure (message); + + src_obj = GST_MESSAGE_SRC (message); + + if (GST_IS_ELEMENT (src_obj)) { + PRINT (_("Got message #%u from element \"%s\" (%s): "), + (guint) seqnum, GST_ELEMENT_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else if (GST_IS_PAD (src_obj)) { + PRINT (_("Got message #%u from pad \"%s:%s\" (%s): "), + (guint) seqnum, GST_DEBUG_PAD_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else if (GST_IS_OBJECT (src_obj)) { + PRINT (_("Got message #%u from object \"%s\" (%s): "), + (guint) seqnum, GST_OBJECT_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else { + PRINT (_("Got message #%u (%s): "), (guint) seqnum, + GST_MESSAGE_TYPE_NAME (message)); + } + + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + PRINT ("%s\n", sstr); + g_free (sstr); + } else { + PRINT ("no message details\n"); + } + } + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_NEW_CLOCK: + { + GstClock *clock; + + gst_message_parse_new_clock (message, &clock); + + PRINT ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL")); + break; + } + case GST_MESSAGE_CLOCK_LOST: + PRINT ("Clock lost, selecting a new one\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + break; + case GST_MESSAGE_EOS:{ + waiting_eos = FALSE; + PRINT (_("Got EOS from element \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + goto exit; + } + case GST_MESSAGE_TAG: + if (tags) { + GstTagList *tag_list; + + if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TAG : found by element \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else if (GST_IS_PAD (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TAG : found by pad \"%s:%s\".\n"), + GST_DEBUG_PAD_NAME (GST_MESSAGE_SRC (message))); + } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TAG : found by object \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else { + PRINT (_("FOUND TAG\n")); + } + + gst_message_parse_tag (message, &tag_list); + gst_tag_list_foreach (tag_list, print_tag, NULL); + gst_tag_list_unref (tag_list); + } + break; + case GST_MESSAGE_TOC: + if (toc) { + GstToc *toc; + GList *entries; + gboolean updated; + + if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TOC : found by element \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) { + PRINT (_("FOUND TOC : found by object \"%s\".\n"), + GST_MESSAGE_SRC_NAME (message)); + } else { + PRINT (_("FOUND TOC\n")); + } + + gst_message_parse_toc (message, &toc, &updated); + /* recursively loop over toc entries */ + entries = gst_toc_get_entries (toc); + g_list_foreach (entries, print_toc_entry, GUINT_TO_POINTER (0)); + gst_toc_unref (toc); + } + break; + case GST_MESSAGE_INFO:{ + GError *gerror; + gchar *debug; + gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message)); + + gst_message_parse_info (message, &gerror, &debug); + if (debug) { + PRINT (_("INFO:\n%s\n"), debug); + } + g_clear_error (&gerror); + g_free (debug); + g_free (name); + break; + } + case GST_MESSAGE_WARNING:{ + GError *gerror; + gchar *debug; + gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message)); + + /* dump graph on warning */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning"); + + gst_message_parse_warning (message, &gerror, &debug); + PRINT (_("WARNING: from element %s: %s\n"), name, gerror->message); + if (debug) { + PRINT (_("Additional debug info:\n%s\n"), debug); + } + g_clear_error (&gerror); + g_free (debug); + g_free (name); + break; + } + case GST_MESSAGE_ERROR:{ + /* dump graph on error */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error"); + + print_error_message (message); + + /* we have an error */ + res = ELR_ERROR; + goto exit; + } + case GST_MESSAGE_STATE_CHANGED:{ + GstState old, new, pending; + + /* we only care about pipeline state change messages */ + if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline)) + break; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + /* if we reached the final target state, exit */ + if (target_state == GST_STATE_PAUSED && new == target_state) { + prerolled = TRUE; + /* ignore when we are buffering since then we mess with the states + * ourselves. */ + if (buffering) { + PRINT (_("Prerolled, waiting for buffering to finish...\n")); + break; + } + if (in_progress) { + PRINT (_("Prerolled, waiting for progress to finish...\n")); + break; + } + goto exit; + } + /* else not an interesting message */ + break; + } + case GST_MESSAGE_BUFFERING:{ + gint percent; + + gst_message_parse_buffering (message, &percent); + PRINT ("%s %d%% \r", _("buffering..."), percent); + + /* no state management needed for live pipelines */ + if (is_live) + break; + + if (percent == 100) { + /* a 100% message means buffering is done */ + buffering = FALSE; + /* if the desired state is playing, go back */ + if (target_state == GST_STATE_PLAYING) { + PRINT (_("Done buffering, setting pipeline to PLAYING ...\n")); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } else if (prerolled && !in_progress) + goto exit; + } else { + /* buffering busy */ + if (!buffering && target_state == GST_STATE_PLAYING) { + /* we were not buffering but PLAYING, PAUSE the pipeline. */ + PRINT (_("Buffering, setting pipeline to PAUSED ...\n")); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + buffering = TRUE; + } + break; + } + case GST_MESSAGE_LATENCY: + { + PRINT (_("Redistribute latency...\n")); + gst_bin_recalculate_latency (GST_BIN (pipeline)); + break; + } + case GST_MESSAGE_REQUEST_STATE: + { + GstState state; + gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message)); + + gst_message_parse_request_state (message, &state); + + PRINT (_("Setting state to %s as requested by %s...\n"), + gst_element_state_get_name (state), name); + + gst_element_set_state (pipeline, state); + + g_free (name); + break; + } + case GST_MESSAGE_APPLICATION:{ + const GstStructure *s; + + s = gst_message_get_structure (message); + + if (gst_structure_has_name (s, "GstLaunchInterrupt")) { + /* this application message is posted when we caught an interrupt and + * we need to stop the pipeline. */ + PRINT (_("Interrupt: Stopping pipeline ...\n")); + res = ELR_INTERRUPT; + goto exit; + } + break; + } + case GST_MESSAGE_PROGRESS: + { + GstProgressType type; + gchar *code, *text; + + gst_message_parse_progress (message, &type, &code, &text); + + switch (type) { + case GST_PROGRESS_TYPE_START: + case GST_PROGRESS_TYPE_CONTINUE: + if (do_progress) { + in_progress = TRUE; + blocking = TRUE; + } + break; + case GST_PROGRESS_TYPE_COMPLETE: + case GST_PROGRESS_TYPE_CANCELED: + case GST_PROGRESS_TYPE_ERROR: + in_progress = FALSE; + break; + default: + break; + } + PRINT (_("Progress: (%s) %s\n"), code, text); + g_free (code); + g_free (text); + + if (do_progress && !in_progress && !buffering && prerolled) + goto exit; + break; + } + case GST_MESSAGE_ELEMENT:{ + if (gst_is_missing_plugin_message (message)) { + const gchar *desc; + + desc = gst_missing_plugin_message_get_description (message); + PRINT (_("Missing element: %s\n"), desc ? desc : "(no description)"); + } + break; + } + case GST_MESSAGE_HAVE_CONTEXT:{ + GstContext *context; + const gchar *context_type; + gchar *context_str; + + gst_message_parse_have_context (message, &context); + + context_type = gst_context_get_context_type (context); + context_str = + gst_structure_to_string (gst_context_get_structure (context)); + PRINT (_("Got context from element '%s': %s=%s\n"), + GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)), context_type, + context_str); + g_free (context_str); + gst_context_unref (context); + break; + } + case GST_MESSAGE_PROPERTY_NOTIFY:{ + const GValue *val; + const gchar *name; + GstObject *obj; + gchar *val_str = NULL; + gchar **ex_prop, *obj_name; + + if (quiet) + break; + + gst_message_parse_property_notify (message, &obj, &name, &val); + + /* Let's not print anything for excluded properties... */ + ex_prop = exclude_args; + while (ex_prop != NULL && *ex_prop != NULL) { + if (strcmp (name, *ex_prop) == 0) + break; + ex_prop++; + } + if (ex_prop != NULL && *ex_prop != NULL) + break; + + obj_name = gst_object_get_path_string (GST_OBJECT (obj)); + if (val != NULL) { + if (G_VALUE_HOLDS_STRING (val)) + val_str = g_value_dup_string (val); + else if (G_VALUE_TYPE (val) == GST_TYPE_CAPS) + val_str = gst_caps_to_string (g_value_get_boxed (val)); + else if (G_VALUE_TYPE (val) == GST_TYPE_TAG_LIST) + val_str = gst_tag_list_to_string (g_value_get_boxed (val)); + else if (G_VALUE_TYPE (val) == GST_TYPE_STRUCTURE) + val_str = gst_structure_to_string (g_value_get_boxed (val)); + else + val_str = gst_value_serialize (val); + } else { + val_str = g_strdup ("(no value)"); + } + + g_print ("%s: %s = %s\n", obj_name, name, val_str); + g_free (obj_name); + g_free (val_str); + break; + } + default: + /* just be quiet by default */ + break; + } + if (message) + gst_message_unref (message); + } + g_assert_not_reached (); + +exit: + { + if (message) + gst_message_unref (message); + gst_object_unref (bus); +#ifdef G_OS_UNIX + if (signal_watch_intr_id > 0) + g_source_remove (signal_watch_intr_id); + if (signal_watch_hup_id > 0) + g_source_remove (signal_watch_hup_id); +#elif defined(G_OS_WIN32) + intr_pipeline = NULL; + SetConsoleCtrlHandler (w32_intr_handler, FALSE); +#endif + return res; + } +} + +static GstBusSyncReply +bus_sync_handler (GstBus * bus, GstMessage * message, gpointer data) +{ + GstElement *pipeline = (GstElement *) data; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_STATE_CHANGED: + /* we only care about pipeline state change messages */ + if (GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) { + GstState old, new, pending; + gchar *state_transition_name; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + state_transition_name = g_strdup_printf ("%s_%s", + gst_element_state_get_name (old), gst_element_state_get_name (new)); + + /* dump graph for (some) pipeline state changes */ + { + gchar *dump_name = g_strconcat ("gst-launch.", state_transition_name, + NULL); + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, dump_name); + g_free (dump_name); + } + + /* place a marker into e.g. strace logs */ + { + gchar *access_name = g_strconcat (g_get_tmp_dir (), G_DIR_SEPARATOR_S, + "gst-launch", G_DIR_SEPARATOR_S, state_transition_name, NULL); + g_file_test (access_name, G_FILE_TEST_EXISTS); + g_free (access_name); + } + + g_free (state_transition_name); + } + break; + default: + break; + } + return GST_BUS_PASS; +} + +int +main (int argc, char *argv[]) +{ + /* options */ + gboolean verbose = FALSE; + gboolean no_fault = FALSE; + gboolean eos_on_shutdown = FALSE; +#if 0 + gboolean check_index = FALSE; +#endif + gchar *savefile = NULL; +#ifndef GST_DISABLE_OPTION_PARSING + GOptionEntry options[] = { + {"tags", 't', 0, G_OPTION_ARG_NONE, &tags, + N_("Output tags (also known as metadata)"), NULL}, + {"toc", 'c', 0, G_OPTION_ARG_NONE, &toc, + N_("Output TOC (chapters and editions)"), NULL}, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + N_("Output status information and property notifications"), NULL}, + {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, + N_("Do not print any progress information"), NULL}, + {"messages", 'm', 0, G_OPTION_ARG_NONE, &messages, + N_("Output messages"), NULL}, + {"exclude", 'X', 0, G_OPTION_ARG_STRING_ARRAY, &exclude_args, + N_("Do not output status information for the specified property " + "if verbose output is enabled (can be used multiple times)"), + N_("PROPERTY-NAME")}, + {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault, + N_("Do not install a fault handler"), NULL}, + {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown, + N_("Force EOS on sources before shutting the pipeline down"), NULL}, +#if 0 + {"index", 'i', 0, G_OPTION_ARG_NONE, &check_index, + N_("Gather and print index statistics"), NULL}, +#endif + GST_TOOLS_GOPTION_VERSION, + {NULL} + }; + GOptionContext *ctx; + GError *err = NULL; +#endif +#if 0 + GstIndex *index; + GPtrArray *index_stats = NULL; +#endif + gchar **argvn; + GError *error = NULL; + gulong deep_notify_id = 0; + gint res = 0; + + free (malloc (8)); /* -lefence */ + + setlocale (LC_ALL, ""); + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + g_set_prgname ("gst-launch-" GST_API_VERSION); + /* Ensure XInitThreads() is called if/when needed */ + g_setenv ("GST_GL_XINITTHREADS", "1", TRUE); + +#ifndef GST_DISABLE_OPTION_PARSING + ctx = g_option_context_new ("PIPELINE-DESCRIPTION"); + g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + if (err) + g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message)); + else + g_printerr ("Error initializing: Unknown error!\n"); + g_clear_error (&err); + g_option_context_free (ctx); + exit (1); + } + g_option_context_free (ctx); +#else + gst_init (&argc, &argv); +#endif + + gst_tools_print_version (); + +#ifdef G_OS_UNIX + if (!no_fault) + fault_setup (); +#endif + + /* make a null-terminated version of argv */ + argvn = g_new0 (char *, argc); + memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1)); + { + pipeline = + (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error); + } + g_free (argvn); + + if (!pipeline) { + if (error) { + g_printerr (_("ERROR: pipeline could not be constructed: %s.\n"), + GST_STR_NULL (error->message)); + g_clear_error (&error); + } else { + g_printerr (_("ERROR: pipeline could not be constructed.\n")); + } + return 1; + } else if (error) { + g_printerr (_("WARNING: erroneous pipeline: %s\n"), + GST_STR_NULL (error->message)); + g_clear_error (&error); + return 1; + } + + if (!savefile) { + GstState state, pending; + GstStateChangeReturn ret; + GstBus *bus; + + /* If the top-level object is not a pipeline, place it in a pipeline. */ + if (!GST_IS_PIPELINE (pipeline)) { + GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL); + + if (real_pipeline == NULL) { + g_printerr (_("ERROR: the 'pipeline' element wasn't found.\n")); + return 1; + } + gst_bin_add (GST_BIN (real_pipeline), pipeline); + pipeline = real_pipeline; + } + if (verbose) { + deep_notify_id = + gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE); + } +#if 0 + if (check_index) { + /* gst_index_new() creates a null-index, it does not store anything, but + * the entry-added signal works and this is what we use to build the + * statistics */ + index = gst_index_new (); + if (index) { + index_stats = g_ptr_array_new (); + g_signal_connect (G_OBJECT (index), "entry-added", + G_CALLBACK (entry_added), index_stats); + g_object_set (G_OBJECT (index), "resolver", GST_INDEX_RESOLVER_GTYPE, + NULL); + gst_element_set_index (pipeline, index); + } + } +#endif + + bus = gst_element_get_bus (pipeline); + gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline, NULL); + gst_object_unref (bus); + + PRINT (_("Setting pipeline to PAUSED ...\n")); + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + g_printerr (_("ERROR: Pipeline doesn't want to pause.\n")); + res = -1; + event_loop (pipeline, FALSE, FALSE, GST_STATE_VOID_PENDING); + goto end; + case GST_STATE_CHANGE_NO_PREROLL: + PRINT (_("Pipeline is live and does not need PREROLL ...\n")); + is_live = TRUE; + break; + case GST_STATE_CHANGE_ASYNC: + PRINT (_("Pipeline is PREROLLING ...\n")); + caught_error = event_loop (pipeline, TRUE, TRUE, GST_STATE_PAUSED); + if (caught_error) { + g_printerr (_("ERROR: pipeline doesn't want to preroll.\n")); + res = caught_error; + goto end; + } + state = GST_STATE_PAUSED; + /* fallthrough */ + case GST_STATE_CHANGE_SUCCESS: + PRINT (_("Pipeline is PREROLLED ...\n")); + break; + } + + caught_error = event_loop (pipeline, FALSE, TRUE, GST_STATE_PLAYING); + + if (caught_error) { + g_printerr (_("ERROR: pipeline doesn't want to preroll.\n")); + res = caught_error; + } else { + GstClockTime tfthen, tfnow; + GstClockTimeDiff diff; + + PRINT (_("Setting pipeline to PLAYING ...\n")); + + if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + GstMessage *err_msg; + GstBus *bus; + + g_printerr (_("ERROR: pipeline doesn't want to play.\n")); + bus = gst_element_get_bus (pipeline); + if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) { + print_error_message (err_msg); + gst_message_unref (err_msg); + } + gst_object_unref (bus); + res = -1; + goto end; + } + + tfthen = gst_util_get_timestamp (); + caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING); + res = caught_error; + if (eos_on_shutdown && caught_error != ELR_NO_ERROR) { + gboolean ignore_errors; + + waiting_eos = TRUE; + if (caught_error == ELR_INTERRUPT) { + PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n")); + gst_element_send_event (pipeline, gst_event_new_eos ()); + ignore_errors = FALSE; + } else { + PRINT (_("EOS on shutdown enabled -- waiting for EOS after Error\n")); + ignore_errors = TRUE; + } + PRINT (_("Waiting for EOS...\n")); + + while (TRUE) { + caught_error = event_loop (pipeline, TRUE, FALSE, GST_STATE_PLAYING); + + if (caught_error == ELR_NO_ERROR) { + /* we got EOS */ + PRINT (_("EOS received - stopping pipeline...\n")); + break; + } else if (caught_error == ELR_INTERRUPT) { + PRINT (_ + ("Interrupt while waiting for EOS - stopping pipeline...\n")); + res = caught_error; + break; + } else if (caught_error == ELR_ERROR) { + if (!ignore_errors) { + PRINT (_("An error happened while waiting for EOS\n")); + res = caught_error; + break; + } + } + } + } + tfnow = gst_util_get_timestamp (); + + diff = GST_CLOCK_DIFF (tfthen, tfnow); + + PRINT (_("Execution ended after %" GST_TIME_FORMAT "\n"), + GST_TIME_ARGS (diff)); + } + + PRINT (_("Setting pipeline to PAUSED ...\n")); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (caught_error == ELR_NO_ERROR) + gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE); + + /* iterate mainloop to process pending stuff */ + while (g_main_context_iteration (NULL, FALSE)); + + /* No need to see all those pad caps going to NULL etc., it's just noise */ + if (deep_notify_id != 0) + g_signal_handler_disconnect (pipeline, deep_notify_id); + + PRINT (_("Setting pipeline to READY ...\n")); + gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE); + +#if 0 + if (check_index) { + print_index_stats (index_stats); + g_ptr_array_free (index_stats, TRUE); + } +#endif + + end: + PRINT (_("Setting pipeline to NULL ...\n")); + gst_element_set_state (pipeline, GST_STATE_NULL); + } + + PRINT (_("Freeing pipeline ...\n")); + gst_object_unref (pipeline); + + gst_deinit (); + + return res; +} diff --git a/tools/gst-stats-1.0.1 b/tools/gst-stats-1.0.1 new file mode 100644 index 0000000..397acff --- /dev/null +++ b/tools/gst-stats-1.0.1 @@ -0,0 +1,30 @@ +.TH GStreamer 1 "April 2017" +.SH "NAME" +gst\-stats\-1.0 \- print info gathered from a GStreamer log file +.SH "SYNOPSIS" +.B gst\-stats\-1.0 [OPTION...] FILE +.SH "DESCRIPTION" +.PP +\fIgst\-stats\-1.0\fP is a tool that analyses information collected +from a log file based on \fIGStreamer tracer messages. +.SH "OPTIONS" +.l +\fIgst\-stats\-1.0\fP accepts the following arguments and options: +.TP 8 +.B FILE +Name of a file +.TP 8 +.B \-h, \-\-help +Print help synopsis and available FLAGS +.TP 8 +.B \-\-gst\-help\-all +Show all help options +. +.TP 8 +.B \-\-gst\-help\-gst +Show \FIGstreamer options +. +.SH "SEE ALSO" +.BR gst\-launch\-1.0 (1) +.SH "AUTHOR" +The GStreamer team at http://gstreamer.freedesktop.org/ diff --git a/tools/gst-stats.c b/tools/gst-stats.c new file mode 100644 index 0000000..065f8ca --- /dev/null +++ b/tools/gst-stats.c @@ -0,0 +1,903 @@ +/* GStreamer + * Copyright (C) 2013 Stefan Sauer + * + * gst-stats.c: statistics tracing front end + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "tools.h" + +/* log parser */ +static GRegex *raw_log = NULL; +static GRegex *ansi_log = NULL; + +/* global statistics */ +static GHashTable *threads = NULL; +static GPtrArray *elements = NULL; +static GPtrArray *pads = NULL; +static guint64 num_buffers = 0, num_events = 0, num_messages = 0, num_queries = + 0; +static guint num_elements = 0, num_bins = 0, num_pads = 0, num_ghostpads = 0; +static GstClockTime last_ts = G_GUINT64_CONSTANT (0); +static guint total_cpuload = 0; +static gboolean have_cpuload = FALSE; + +typedef struct +{ + /* human readable pad name and details */ + gchar *name, *type_name; + guint index; + gboolean is_ghost_pad; + GstPadDirection dir; + /* buffer statistics */ + guint num_buffers; + guint num_live, num_decode_only, num_discont, num_resync, num_corrupted, + num_marker, num_header, num_gap, num_droppable, num_delta; + guint min_size, max_size, avg_size; + /* first and last activity on the pad, expected next_ts */ + GstClockTime first_ts, last_ts, next_ts; + /* in which thread does it operate */ + gpointer thread_id; + /* hierarchy */ + guint parent_ix; +} GstPadStats; + +typedef struct +{ + /* human readable element name */ + gchar *name, *type_name; + guint index; + gboolean is_bin; + /* buffer statistics */ + guint recv_buffers, sent_buffers; + guint64 recv_bytes, sent_bytes; + /* event, message statistics */ + guint num_events, num_messages, num_queries; + /* first activity on the element */ + GstClockTime first_ts, last_ts; + /* hierarchy */ + guint parent_ix; +} GstElementStats; + +typedef struct +{ + /* time spend in this thread */ + GstClockTime tthread; + guint cpuload; +} GstThreadStats; + +/* stats helper */ + +static void +free_element_stats (gpointer data) +{ + g_slice_free (GstElementStats, data); +} + +static inline GstElementStats * +get_element_stats (guint ix) +{ + return (ix != G_MAXUINT && ix < elements->len) ? + g_ptr_array_index (elements, ix) : NULL; +} + +static inline GstPadStats * +get_pad_stats (guint ix) +{ + return (ix != G_MAXUINT && ix < pads->len) ? + g_ptr_array_index (pads, ix) : NULL; +} + +static void +free_pad_stats (gpointer data) +{ + g_slice_free (GstPadStats, data); +} + +static inline GstThreadStats * +get_thread_stats (gpointer id) +{ + GstThreadStats *stats = g_hash_table_lookup (threads, id); + + if (G_UNLIKELY (!stats)) { + stats = g_slice_new0 (GstThreadStats); + stats->tthread = GST_CLOCK_TIME_NONE; + g_hash_table_insert (threads, id, stats); + } + return stats; +} + +static void +new_pad_stats (GstStructure * s) +{ + GstPadStats *stats; + guint ix, parent_ix; + gchar *type, *name; + gboolean is_ghost_pad; + GstPadDirection dir; + guint64 thread_id; + + gst_structure_get (s, + "ix", G_TYPE_UINT, &ix, + "parent-ix", G_TYPE_UINT, &parent_ix, + "name", G_TYPE_STRING, &name, + "type", G_TYPE_STRING, &type, + "is-ghostpad", G_TYPE_BOOLEAN, &is_ghost_pad, + "pad-direction", GST_TYPE_PAD_DIRECTION, &dir, + "thread-id", G_TYPE_UINT64, &thread_id, NULL); + + stats = g_slice_new0 (GstPadStats); + if (is_ghost_pad) + num_ghostpads++; + num_pads++; + stats->name = name; + stats->type_name = type; + stats->index = ix; + stats->is_ghost_pad = is_ghost_pad; + stats->dir = dir; + stats->min_size = G_MAXUINT; + stats->first_ts = stats->last_ts = stats->next_ts = GST_CLOCK_TIME_NONE; + stats->thread_id = (gpointer) (guintptr) thread_id; + stats->parent_ix = parent_ix; + + if (pads->len <= ix) + g_ptr_array_set_size (pads, ix + 1); + g_ptr_array_index (pads, ix) = stats; +} + +static void +new_element_stats (GstStructure * s) +{ + GstElementStats *stats; + guint ix, parent_ix; + gchar *type, *name; + gboolean is_bin; + + gst_structure_get (s, + "ix", G_TYPE_UINT, &ix, + "parent-ix", G_TYPE_UINT, &parent_ix, + "name", G_TYPE_STRING, &name, + "type", G_TYPE_STRING, &type, "is-bin", G_TYPE_BOOLEAN, &is_bin, NULL); + + stats = g_slice_new0 (GstElementStats); + if (is_bin) + num_bins++; + num_elements++; + stats->index = ix; + stats->name = name; + stats->type_name = type; + stats->is_bin = is_bin; + stats->first_ts = GST_CLOCK_TIME_NONE; + stats->parent_ix = parent_ix; + + if (elements->len <= ix) + g_ptr_array_set_size (elements, ix + 1); + g_ptr_array_index (elements, ix) = stats; +} + +static void +free_thread_stats (gpointer data) +{ + g_slice_free (GstThreadStats, data); +} + +static void +do_pad_stats (GstPadStats * stats, guint elem_ix, guint size, guint64 ts, + guint64 buffer_ts, guint64 buffer_dur, GstBufferFlags buffer_flags) +{ + gulong avg_size; + + /* parentage */ + if (stats->parent_ix == G_MAXUINT) { + stats->parent_ix = elem_ix; + } + + if (stats->thread_id) { + get_thread_stats (stats->thread_id); + } + + /* size stats */ + avg_size = (((gulong) stats->avg_size * (gulong) stats->num_buffers) + size); + stats->num_buffers++; + stats->avg_size = (guint) (avg_size / stats->num_buffers); + if (size < stats->min_size) + stats->min_size = size; + else if (size > stats->max_size) + stats->max_size = size; + /* time stats */ + if (!GST_CLOCK_TIME_IS_VALID (stats->last_ts)) + stats->first_ts = ts; + stats->last_ts = ts; + /* flag stats */ + if (buffer_flags & GST_BUFFER_FLAG_LIVE) + stats->num_live++; + if (buffer_flags & GST_BUFFER_FLAG_DECODE_ONLY) + stats->num_decode_only++; + if (buffer_flags & GST_BUFFER_FLAG_DISCONT) + stats->num_discont++; + if (buffer_flags & GST_BUFFER_FLAG_RESYNC) + stats->num_resync++; + if (buffer_flags & GST_BUFFER_FLAG_CORRUPTED) + stats->num_corrupted++; + if (buffer_flags & GST_BUFFER_FLAG_MARKER) + stats->num_marker++; + if (buffer_flags & GST_BUFFER_FLAG_HEADER) + stats->num_header++; + if (buffer_flags & GST_BUFFER_FLAG_GAP) + stats->num_gap++; + if (buffer_flags & GST_BUFFER_FLAG_DROPPABLE) + stats->num_droppable++; + if (buffer_flags & GST_BUFFER_FLAG_DELTA_UNIT) + stats->num_delta++; + /* update timestamps */ + if (GST_CLOCK_TIME_IS_VALID (buffer_ts) && + GST_CLOCK_TIME_IS_VALID (buffer_dur)) { + stats->next_ts = buffer_ts + buffer_dur; + } else { + stats->next_ts = GST_CLOCK_TIME_NONE; + } +} + +static void +do_element_stats (GstElementStats * stats, GstElementStats * peer_stats, + guint size, guint64 ts) +{ + stats->sent_buffers++; + peer_stats->recv_buffers++; + stats->sent_bytes += size; + peer_stats->recv_bytes += size; + /* time stats */ + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (stats->first_ts))) { + stats->first_ts = ts; + } + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (peer_stats->first_ts))) { + peer_stats->first_ts = ts + 1; + } +} + +static void +do_buffer_stats (GstStructure * s) +{ + guint64 ts; + guint64 buffer_pts = GST_CLOCK_TIME_NONE, buffer_dur = GST_CLOCK_TIME_NONE; + guint pad_ix, elem_ix, peer_elem_ix; + guint size; + GstBufferFlags buffer_flags; + GstPadStats *pad_stats; + GstElementStats *elem_stats, *peer_elem_stats; + + num_buffers++; + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "pad-ix", G_TYPE_UINT, &pad_ix, + "element-ix", G_TYPE_UINT, &elem_ix, + "peer-element-ix", G_TYPE_UINT, &peer_elem_ix, + "buffer-size", G_TYPE_UINT, &size, + "buffer-flags", GST_TYPE_BUFFER_FLAGS, &buffer_flags, NULL); + gst_structure_get_uint64 (s, "buffer-pts", &buffer_pts); + gst_structure_get_uint64 (s, "buffer-duration", &buffer_dur); + last_ts = MAX (last_ts, ts); + if (!(pad_stats = get_pad_stats (pad_ix))) { + GST_WARNING ("no pad stats found for ix=%u", pad_ix); + return; + } + if (!(elem_stats = get_element_stats (elem_ix))) { + GST_WARNING ("no element stats found for ix=%u", elem_ix); + return; + } + if (!(peer_elem_stats = get_element_stats (peer_elem_ix))) { + GST_WARNING ("no element stats found for ix=%u", peer_elem_ix); + return; + } + do_pad_stats (pad_stats, elem_ix, size, ts, buffer_pts, buffer_dur, + buffer_flags); + if (pad_stats->dir == GST_PAD_SRC) { + /* push */ + do_element_stats (elem_stats, peer_elem_stats, size, ts); + } else { + /* pull */ + do_element_stats (peer_elem_stats, elem_stats, size, ts); + } +} + +static void +do_event_stats (GstStructure * s) +{ + guint64 ts; + guint pad_ix, elem_ix; + GstPadStats *pad_stats; + GstElementStats *elem_stats; + + num_events++; + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "pad-ix", G_TYPE_UINT, &pad_ix, "element-ix", G_TYPE_UINT, &elem_ix, + NULL); + last_ts = MAX (last_ts, ts); + if (!(pad_stats = get_pad_stats (pad_ix))) { + GST_WARNING ("no pad stats found for ix=%u", pad_ix); + return; + } + if (!(elem_stats = get_element_stats (elem_ix))) { + // e.g. reconfigure events are send over unparented pads + GST_INFO ("no element stats found for ix=%u", elem_ix); + return; + } + elem_stats->num_events++; +} + +static void +do_message_stats (GstStructure * s) +{ + guint64 ts; + guint elem_ix; + GstElementStats *elem_stats; + + num_messages++; + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "element-ix", G_TYPE_UINT, &elem_ix, NULL); + last_ts = MAX (last_ts, ts); + if (!(elem_stats = get_element_stats (elem_ix))) { + GST_WARNING ("no element stats found for ix=%u", elem_ix); + return; + } + elem_stats->num_messages++; +} + +static void +do_query_stats (GstStructure * s) +{ + guint64 ts; + guint elem_ix; + GstElementStats *elem_stats; + + num_queries++; + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "element-ix", G_TYPE_UINT, &elem_ix, NULL); + last_ts = MAX (last_ts, ts); + if (!(elem_stats = get_element_stats (elem_ix))) { + GST_WARNING ("no element stats found for ix=%u", elem_ix); + return; + } + elem_stats->num_queries++; +} + +static void +do_thread_rusage_stats (GstStructure * s) +{ + guint64 ts, tthread, thread_id; + guint cpuload; + GstThreadStats *thread_stats; + + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "thread-id", G_TYPE_UINT64, &thread_id, + "average-cpuload", G_TYPE_UINT, &cpuload, "time", G_TYPE_UINT64, &tthread, + NULL); + thread_stats = get_thread_stats ((gpointer) (guintptr) thread_id); + thread_stats->cpuload = cpuload; + thread_stats->tthread = tthread; + last_ts = MAX (last_ts, ts); +} + +static void +do_proc_rusage_stats (GstStructure * s) +{ + guint64 ts; + + gst_structure_get (s, "ts", G_TYPE_UINT64, &ts, + "average-cpuload", G_TYPE_UINT, &total_cpuload, NULL); + last_ts = MAX (last_ts, ts); + have_cpuload = TRUE; +} + +/* reporting */ + +static gint +find_pad_stats_for_thread (gconstpointer value, gconstpointer user_data) +{ + const GstPadStats *stats = (const GstPadStats *) value; + + if ((stats->thread_id == user_data) && (stats->num_buffers)) { + return 0; + } + return 1; +} + +static void +print_pad_stats (gpointer value, gpointer user_data) +{ + GstPadStats *stats = (GstPadStats *) value; + + if (stats->thread_id == user_data) { + /* there seem to be some temporary pads */ + if (stats->num_buffers) { + GstClockTimeDiff running = + GST_CLOCK_DIFF (stats->first_ts, stats->last_ts); + GstElementStats *elem_stats = get_element_stats (stats->parent_ix); + gchar fullname[30 + 1]; + + g_snprintf (fullname, 30, "%s.%s", elem_stats->name, stats->name); + + printf + (" %c %-30.30s: buffers %7u (live %5u,dec %5u,dis %5u,res %5u," + "cor %5u,mar %5u,hdr %5u,gap %5u,drop %5u,dlt %5u),", + (stats->dir == GST_PAD_SRC) ? '>' : '<', fullname, stats->num_buffers, + stats->num_live, stats->num_decode_only, stats->num_discont, + stats->num_resync, stats->num_corrupted, stats->num_marker, + stats->num_header, stats->num_gap, stats->num_droppable, + stats->num_delta); + if (stats->min_size == stats->max_size) { + printf (" size (min/avg/max) ......./%7u/.......,", stats->avg_size); + } else { + printf (" size (min/avg/max) %7u/%7u/%7u,", + stats->min_size, stats->avg_size, stats->max_size); + } + printf (" time %" GST_TIME_FORMAT "," + " bytes/sec %lf\n", + GST_TIME_ARGS (running), + ((gdouble) (stats->num_buffers * stats->avg_size) * GST_SECOND) / + ((gdouble) running)); + } + } +} + +static void +print_thread_stats (gpointer key, gpointer value, gpointer user_data) +{ + GSList *list = user_data; + GSList *node = g_slist_find_custom (list, key, find_pad_stats_for_thread); + GstThreadStats *stats = (GstThreadStats *) value; + + /* skip stats if there are no pads for that thread (e.g. a pipeline) */ + if (!node) + return; + + printf ("Thread %p Statistics:\n", key); + if (GST_CLOCK_TIME_IS_VALID (stats->tthread)) { + printf (" Time: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (stats->tthread)); + printf (" Avg CPU load: %4.1f %%\n", (gfloat) stats->cpuload / 10.0); + } + + puts (" Pad Statistics:"); + g_slist_foreach (node, print_pad_stats, key); +} + +static void +print_element_stats (gpointer value, gpointer user_data) +{ + GstElementStats *stats = (GstElementStats *) value; + + /* skip temporary elements */ + if (stats->first_ts != GST_CLOCK_TIME_NONE) { + gchar fullname[45 + 1]; + + g_snprintf (fullname, 45, "%s:%s", stats->type_name, stats->name); + + printf (" %-45s:", fullname); + if (stats->recv_buffers) + printf (" buffers in/out %7u", stats->recv_buffers); + else + printf (" buffers in/out %7s", "-"); + if (stats->sent_buffers) + printf ("/%7u", stats->sent_buffers); + else + printf ("/%7s", "-"); + if (stats->recv_bytes) + printf (" bytes in/out %12" G_GUINT64_FORMAT, stats->recv_bytes); + else + printf (" bytes in/out %12s", "-"); + if (stats->sent_bytes) + printf ("/%12" G_GUINT64_FORMAT, stats->sent_bytes); + else + printf ("/%12s", "-"); + printf (" first activity %" GST_TIME_FORMAT ", " + " ev/msg/qry sent %5u/%5u/%5u\n", GST_TIME_ARGS (stats->first_ts), + stats->num_events, stats->num_messages, stats->num_queries); + } +} + +static void +accum_element_stats (gpointer value, gpointer user_data) +{ + GstElementStats *stats = (GstElementStats *) value; + + if (stats->parent_ix != G_MAXUINT) { + GstElementStats *parent_stats = get_element_stats (stats->parent_ix); + + parent_stats->num_events += stats->num_events; + parent_stats->num_messages += stats->num_messages; + parent_stats->num_queries += stats->num_queries; + if (!GST_CLOCK_TIME_IS_VALID (parent_stats->first_ts)) { + parent_stats->first_ts = stats->first_ts; + } else if (GST_CLOCK_TIME_IS_VALID (stats->first_ts)) { + parent_stats->first_ts = MIN (parent_stats->first_ts, stats->first_ts); + } + if (!GST_CLOCK_TIME_IS_VALID (parent_stats->last_ts)) { + parent_stats->last_ts = stats->last_ts; + } else if (GST_CLOCK_TIME_IS_VALID (stats->last_ts)) { + parent_stats->last_ts = MAX (parent_stats->last_ts, stats->last_ts); + } + } +} + +/* sorting */ + +static gint +sort_pad_stats_by_first_activity (gconstpointer ps1, gconstpointer ps2) +{ + GstPadStats *s1 = (GstPadStats *) ps1; + GstPadStats *s2 = (GstPadStats *) ps2; + + gint order = GST_CLOCK_DIFF (s2->first_ts, s1->first_ts); + + if (!order) { + order = s1->dir - s2->dir; + } + return (order); +} + +static void +sort_pad_stats (gpointer value, gpointer user_data) +{ + GSList **list = user_data; + + *list = + g_slist_insert_sorted (*list, value, sort_pad_stats_by_first_activity); +} + +static gint +sort_element_stats_by_first_activity (gconstpointer es1, gconstpointer es2) +{ + return (GST_CLOCK_DIFF (((GstElementStats *) es2)->first_ts, + ((GstElementStats *) es1)->first_ts)); +} + +static void +sort_bin_stats (gpointer value, gpointer user_data) +{ + if (((GstElementStats *) value)->is_bin) { + GSList **list = user_data; + + *list = + g_slist_insert_sorted (*list, value, + sort_element_stats_by_first_activity); + } +} + +static void +sort_element_stats (gpointer value, gpointer user_data) +{ + if (!(((GstElementStats *) value)->is_bin)) { + GSList **list = user_data; + + *list = + g_slist_insert_sorted (*list, value, + sort_element_stats_by_first_activity); + } +} + +static gboolean +check_bin_parent (gpointer key, gpointer value, gpointer user_data) +{ + GstElementStats *stats = (GstElementStats *) value; + + return (stats->parent_ix == GPOINTER_TO_UINT (user_data)); +} + +static gboolean +process_leaf_bins (gpointer key, gpointer value, gpointer user_data) +{ + GHashTable *accum_bins = user_data; + + /* if we find no bin that has this bin as a parent ... */ + if (!g_hash_table_find (accum_bins, check_bin_parent, key)) { + /* accumulate stats to the parent and remove */ + accum_element_stats (value, NULL); + return TRUE; + } + return FALSE; +} + +/* main */ + +static gboolean +init (void) +{ + /* compile the parser regexps */ + /* 0:00:00.004925027 31586 0x1c5c600 DEBUG GST_REGISTRY gstregistry.c:463:gst_registry_add_plugin: adding plugin 0x1c79160 for filename "/usr/lib/gstreamer-1.0/libgstxxx.so" */ + raw_log = g_regex_new ( + /* 1: ts */ + "^([0-9:.]+) +" + /* 2: pid */ + "([0-9]+) +" + /* 3: thread */ + "(0x[0-9a-fA-F]+) +" + /* 4: level */ + "([A-Z]+) +" + /* 5: category */ + "([a-zA-Z_-]+) +" + /* 6: file:line:func: */ + "([^:]*:[0-9]+:[^:]*:) +" + /* 7: (obj)? log-text */ + "(.*)$", 0, 0, NULL); + if (!raw_log) { + GST_WARNING ("failed to compile the 'raw' parser"); + return FALSE; + } + + ansi_log = g_regex_new ( + /* 1: ts */ + "^([0-9:.]+) +" + /* 2: pid */ + "\\\x1b\\[[0-9;]+m *([0-9]+)\\\x1b\\[00m +" + /* 3: thread */ + "(0x[0-9a-fA-F]+) +" + /* 4: level */ + "(?:\\\x1b\\[[0-9;]+m)?([A-Z]+) +\\\x1b\\[00m +" + /* 5: category */ + "\\\x1b\\[[0-9;]+m +([a-zA-Z_-]+) +" + /* 6: file:line:func: */ + "([^:]*:[0-9]+:[^:]*:)(?:\\\x1b\\[00m)? +" + /* 7: (obj)? log-text */ + "(.*)$", 0, 0, NULL); + if (!raw_log) { + GST_WARNING ("failed to compile the 'ansi' parser"); + return FALSE; + } + + elements = g_ptr_array_new_with_free_func (free_element_stats); + pads = g_ptr_array_new_with_free_func (free_pad_stats); + threads = g_hash_table_new_full (NULL, NULL, NULL, free_thread_stats); + + return TRUE; +} + +static void +done (void) +{ + if (pads) + g_ptr_array_free (pads, TRUE); + if (elements) + g_ptr_array_free (elements, TRUE); + if (threads) + g_hash_table_destroy (threads); + + if (raw_log) + g_regex_unref (raw_log); + if (ansi_log) + g_regex_unref (ansi_log); +} + +static void +print_stats (void) +{ + guint num_threads = g_hash_table_size (threads); + + /* print overall stats */ + puts ("\nOverall Statistics:"); + printf ("Number of Threads: %u\n", num_threads); + printf ("Number of Elements: %u\n", num_elements - num_bins); + printf ("Number of Bins: %u\n", num_bins); + printf ("Number of Pads: %u\n", num_pads - num_ghostpads); + printf ("Number of GhostPads: %u\n", num_ghostpads); + printf ("Number of Buffers passed: %" G_GUINT64_FORMAT "\n", num_buffers); + printf ("Number of Events sent: %" G_GUINT64_FORMAT "\n", num_events); + printf ("Number of Message sent: %" G_GUINT64_FORMAT "\n", num_messages); + printf ("Number of Queries sent: %" G_GUINT64_FORMAT "\n", num_queries); + printf ("Time: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (last_ts)); + if (have_cpuload) { + printf ("Avg CPU load: %4.1f %%\n", (gfloat) total_cpuload / 10.0); + } + puts (""); + + /* thread stats */ + if (num_threads) { + GSList *list = NULL; + + g_ptr_array_foreach (pads, sort_pad_stats, &list); + g_hash_table_foreach (threads, print_thread_stats, list); + puts (""); + g_slist_free (list); + } + + /* element stats */ + if (num_elements) { + GSList *list = NULL; + + puts ("Element Statistics:"); + /* sort by first_activity */ + g_ptr_array_foreach (elements, sort_element_stats, &list); + /* attribute element stats to bins */ + g_slist_foreach (list, accum_element_stats, NULL); + g_slist_foreach (list, print_element_stats, NULL); + puts (""); + g_slist_free (list); + } + + /* bin stats */ + if (num_bins) { + GSList *list = NULL; + guint i; + GHashTable *accum_bins = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + puts ("Bin Statistics:"); + /* attribute bin stats to parent-bins */ + for (i = 0; i < num_elements; i++) { + GstElementStats *stats = g_ptr_array_index (elements, i); + if (stats->is_bin) { + g_hash_table_insert (accum_bins, GUINT_TO_POINTER (i), stats); + } + } + while (g_hash_table_size (accum_bins)) { + g_hash_table_foreach_remove (accum_bins, process_leaf_bins, accum_bins); + } + g_hash_table_destroy (accum_bins); + /* sort by first_activity */ + g_ptr_array_foreach (elements, sort_bin_stats, &list); + g_slist_foreach (list, print_element_stats, NULL); + puts (""); + g_slist_free (list); + } +} + +static void +collect_stats (const gchar * filename) +{ + FILE *log; + + if ((log = fopen (filename, "rt"))) { + gchar line[5001]; + + /* probe format */ + if (fgets (line, 5000, log)) { + GMatchInfo *match_info; + GRegex *parser; + GstStructure *s; + guint lnr = 0; + gchar *level, *data; + + if (strchr (line, 27)) { + parser = ansi_log; + GST_INFO ("format is 'ansi'"); + } else { + parser = raw_log; + GST_INFO ("format is 'raw'"); + } + rewind (log); + + /* parse the log */ + while (!feof (log)) { + if (fgets (line, 5000, log)) { + if (g_regex_match (parser, line, 0, &match_info)) { + /* filter by level */ + level = g_match_info_fetch (match_info, 4); + if (!strcmp (level, "TRACE")) { + data = g_match_info_fetch (match_info, 7); + if ((s = gst_structure_from_string (data, NULL))) { + const gchar *name = gst_structure_get_name (s); + + if (!strcmp (name, "new-pad")) { + new_pad_stats (s); + } else if (!strcmp (name, "new-element")) { + new_element_stats (s); + } else if (!strcmp (name, "buffer")) { + do_buffer_stats (s); + } else if (!strcmp (name, "event")) { + do_event_stats (s); + } else if (!strcmp (name, "message")) { + do_message_stats (s); + } else if (!strcmp (name, "query")) { + do_query_stats (s); + } else if (!strcmp (name, "thread-rusage")) { + do_thread_rusage_stats (s); + } else if (!strcmp (name, "proc-rusage")) { + do_proc_rusage_stats (s); + } else { + // TODO(ensonic): parse the xxx.class log lines + if (!g_str_has_suffix (data, ".class")) { + GST_WARNING ("unknown log entry: '%s'", data); + } + } + gst_structure_free (s); + } else { + GST_WARNING ("unknown log entry: '%s'", data); + } + } + } else { + if (*line) { + GST_WARNING ("foreign log entry: %s:%d:'%s'", filename, lnr, + g_strchomp (line)); + } + } + g_match_info_free (match_info); + match_info = NULL; + lnr++; + } else { + if (!feof (log)) { + // TODO(ensonic): run wc -L on the log file + fprintf (stderr, "line too long"); + } + } + } + } else { + GST_WARNING ("empty log"); + } + fclose (log); + } +} + +gint +main (gint argc, gchar * argv[]) +{ + gchar **filenames = NULL; + guint num; + GError *err = NULL; + GOptionContext *ctx; + GOptionEntry options[] = { + GST_TOOLS_GOPTION_VERSION, + // TODO(ensonic): add a summary flag, if set read the whole thing, print + // stats once, and exit + {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 + + g_set_prgname ("gst-stats-" GST_API_VERSION); + + ctx = g_option_context_new ("FILE"); + g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", GST_STR_NULL (err->message)); + exit (1); + } + g_option_context_free (ctx); + + gst_tools_print_version (); + + if (filenames == NULL || *filenames == NULL) { + g_print ("Please give one filename to %s\n\n", g_get_prgname ()); + return 1; + } + num = g_strv_length (filenames); + if (num == 0 || num > 1) { + g_print ("Please give exactly one filename to %s (%d given).\n\n", + g_get_prgname (), num); + return 1; + } + + if (init ()) { + collect_stats (filenames[0]); + print_stats (); + } + done (); + + g_strfreev (filenames); + return 0; +} diff --git a/tools/gst-typefind-1.0.1 b/tools/gst-typefind-1.0.1 new file mode 100644 index 0000000..b5bf0b7 --- /dev/null +++ b/tools/gst-typefind-1.0.1 @@ -0,0 +1,39 @@ +.TH GStreamer 1 "May 2003" +.SH "NAME" +gst\-typefind\-1.0 \- print Media type of file +.SH "SYNOPSIS" +.B gst\-typefind\-1.0 +.SH "DESCRIPTION" +.PP +\fIgst\-typefind\-1.0\fP uses the GStreamer type finding system to +determine the relevant GStreamer plugin to parse or decode \fBfile\fP, +and the corresponding media type. +. +.SH "OPTIONS" +.l +\fIgst\-typefind\-1.0\fP accepts the following options: +.TP 8 +.B \-\-help +Print help synopsis and available FLAGS +.TP 8 +.B \-\-gst\-info\-mask=FLAGS +\fIGStreamer\fP info flags to set (list with \-\-help) +.TP 8 +.B \-\-gst\-debug\-mask=FLAGS +\fIGStreamer\fP debugging flags to set (list with \-\-help) +.TP 8 +.B \-\-gst\-mask=FLAGS +\fIGStreamer\fP info and debugging flags to set (list with \-\-help) +.TP 8 +.B \-\-gst\-plugin\-spew +\fIGStreamer\fP info flags to set +Enable printout of errors while loading \fIGStreamer\fP plugins +.TP 8 +.B \-\-gst\-plugin\-path=PATH +Add directories separated with ':' to the plugin search path +. +.SH "SEE ALSO" +.BR gst\-inspect\-1.0 (1), +.BR gst\-launch\-1.0 (1) +.SH "AUTHOR" +The GStreamer team at http://gstreamer.freedesktop.org/ diff --git a/tools/gst-typefind.c b/tools/gst-typefind.c new file mode 100644 index 0000000..490aca8 --- /dev/null +++ b/tools/gst-typefind.c @@ -0,0 +1,187 @@ +/* GStreamer + * Copyright (C) 2003 Thomas Vander Stichele + * 2003 Benjamin Otte + * 2005 Andy Wingo + * + * gst-typefind.c: Use GStreamer to find the type of a file + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "tools.h" + +static void +have_type_handler (GstElement * typefind, guint probability, + const GstCaps * caps, GstCaps ** p_caps) +{ + if (p_caps) { + *p_caps = gst_caps_copy (caps); + } +} + +static void +typefind_file (const gchar * filename) +{ + GstStateChangeReturn sret; + GstElement *pipeline; + GstElement *source; + GstElement *typefind; + GstElement *fakesink; + GstState state; + GstCaps *caps = NULL; + GDir *dir; + + if ((dir = g_dir_open (filename, 0, NULL))) { + const gchar *entry; + + while ((entry = g_dir_read_name (dir))) { + gchar *path; + + path = g_strconcat (filename, G_DIR_SEPARATOR_S, entry, NULL); + typefind_file (path); + g_free (path); + } + + g_dir_close (dir); + return; + } + + pipeline = gst_pipeline_new ("pipeline"); + + source = gst_element_factory_make ("filesrc", "source"); + g_assert (GST_IS_ELEMENT (source)); + typefind = gst_element_factory_make ("typefind", "typefind"); + g_assert (GST_IS_ELEMENT (typefind)); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + g_assert (GST_IS_ELEMENT (typefind)); + + gst_bin_add_many (GST_BIN (pipeline), source, typefind, fakesink, NULL); + gst_element_link_many (source, typefind, fakesink, NULL); + + g_signal_connect (G_OBJECT (typefind), "have-type", + G_CALLBACK (have_type_handler), &caps); + + g_object_set (source, "location", filename, NULL); + + GST_DEBUG ("Starting typefinding for %s", filename); + + /* typefind will only commit to PAUSED if it actually finds a type; + * otherwise the state change fails */ + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); + + /* wait until state change either completes or fails */ + sret = gst_element_get_state (GST_ELEMENT (pipeline), &state, NULL, -1); + + switch (sret) { + case GST_STATE_CHANGE_FAILURE:{ + GstMessage *msg; + GstBus *bus; + GError *err = NULL; + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0); + gst_object_unref (bus); + + if (msg) { + gst_message_parse_error (msg, &err, NULL); + g_printerr ("%s - FAILED: %s\n", filename, err->message); + g_clear_error (&err); + gst_message_unref (msg); + } else { + g_printerr ("%s - FAILED: unknown error\n", filename); + } + break; + } + case GST_STATE_CHANGE_SUCCESS:{ + if (caps) { + gchar *caps_str; + + caps_str = gst_caps_to_string (caps); + g_print ("%s - %s\n", filename, caps_str); + g_free (caps_str); + gst_caps_unref (caps); + } else { + g_print ("%s - %s\n", filename, "No type found"); + } + break; + } + default: + g_assert_not_reached (); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +int +main (int argc, char *argv[]) +{ + gchar **filenames = NULL; + guint num, i; + GError *err = NULL; + GOptionContext *ctx; + GOptionEntry options[] = { + GST_TOOLS_GOPTION_VERSION, + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}, + {NULL} + }; + + setlocale (LC_ALL, ""); + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + g_set_prgname ("gst-typefind-" GST_API_VERSION); + + 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)); + g_clear_error (&err); + g_option_context_free (ctx); + exit (1); + } + g_option_context_free (ctx); + + gst_tools_print_version (); + + if (filenames == NULL || *filenames == NULL) { + g_print ("Please give one or more filenames to %s\n\n", g_get_prgname ()); + return 1; + } + + num = g_strv_length (filenames); + + for (i = 0; i < num; ++i) { + typefind_file (filenames[i]); + } + + g_strfreev (filenames); + + return 0; +} diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000..322312a --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,18 @@ +tools = [ 'gst-inspect', 'gst-launch', 'gst-stats', 'gst-typefind' ] + +foreach tool : tools + exe_name = '@0@-@1@'.format(tool, apiversion) + src_file = '@0@.c'.format(tool) + + executable(exe_name, + src_file, + install: true, + include_directories : [configinc], + dependencies : [glib_dep, gobject_dep, gmodule_dep, mathlib, gst_dep], + link_with: [printf_lib], + c_args: gst_c_args, + ) + + man_page = '@0@-1.0.1'.format(tool) + install_man(man_page) +endforeach diff --git a/tools/tools.h b/tools/tools.h new file mode 100644 index 0000000..6bed5ac --- /dev/null +++ b/tools/tools.h @@ -0,0 +1,60 @@ +/* GStreamer + * Copyright (C) 2005 Benjamin Otte + * + * tools.h: header for common stuff of all GStreamer tools + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_TOOLS_H__ +#define __GST_TOOLS_H__ + +#include + +#include +#include "gst/gst-i18n-app.h" + +/* + * This is a kind of hacky way to make all the tools use the same version code. + * If anyone knows a less hacky way to get this done, feel free to implement it. + * + * It also includes all the files that all the tools require. + */ + +static gboolean __gst_tools_version = FALSE; + +#define GST_TOOLS_GOPTION_VERSION \ + { "version", 0, 0, G_OPTION_ARG_NONE, &__gst_tools_version, \ + N_("Print version information and exit"), NULL } + +static void +gst_tools_print_version (void) +{ + if (__gst_tools_version) { + gchar *version_str; + + version_str = gst_version_string (); + g_print ("%s version %d.%d.%d\n", g_get_prgname (), + GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO); + g_print ("%s\n", version_str); + g_print ("%s\n", GST_PACKAGE_ORIGIN); + g_free (version_str); + exit (0); + } +} + +#endif /* __GST_TOOLS_H__ */ diff --git a/win32/MANIFEST b/win32/MANIFEST new file mode 100644 index 0000000..dda1ec7 --- /dev/null +++ b/win32/MANIFEST @@ -0,0 +1,6 @@ +win32/MANIFEST +win32/README.txt +win32/common/libgstbase.def +win32/common/libgstcontroller.def +win32/common/libgstnet.def +win32/common/libgstreamer.def diff --git a/win32/README.txt b/win32/README.txt new file mode 100644 index 0000000..892b1f1 --- /dev/null +++ b/win32/README.txt @@ -0,0 +1,32 @@ +Building GStreamer on Windows +----------------------------- + +Running GStreamer on Windows is supported. + +Official Windows binaries for each release can be found at: + + https://gstreamer.freedesktop.org/data/pkg/windows/ + + +Building with MinGW/MSys +------------------------ + +Should work out of the box from the toplevel directory using the standard +Unix build system provided. + +This build type is officially supported. + +You can build Windows binaries including all required dependencies +using the 'cerbero' build tool: + + http://cgit.freedesktop.org/gstreamer/cerbero/ + +This works both natively on Windows or as cross-compile from Linux. + + +Building with Visual Studio +--------------------------- + +Building with Visual Studio is possible using the Meson-based build +definitions, but there is currently no support for this in cerbero yet, +so it's not for the faint-hearted. diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def new file mode 100644 index 0000000..792a86d --- /dev/null +++ b/win32/common/libgstbase.def @@ -0,0 +1,332 @@ +EXPORTS + gst_adapter_available + gst_adapter_available_fast + gst_adapter_clear + gst_adapter_copy + gst_adapter_copy_bytes + gst_adapter_distance_from_discont + gst_adapter_dts_at_discont + gst_adapter_flush + gst_adapter_get_buffer + gst_adapter_get_buffer_fast + gst_adapter_get_buffer_list + gst_adapter_get_list + gst_adapter_get_type + gst_adapter_map + gst_adapter_masked_scan_uint32 + gst_adapter_masked_scan_uint32_peek + gst_adapter_new + gst_adapter_offset_at_discont + gst_adapter_prev_dts + gst_adapter_prev_dts_at_offset + gst_adapter_prev_offset + gst_adapter_prev_pts + gst_adapter_prev_pts_at_offset + gst_adapter_pts_at_discont + gst_adapter_push + gst_adapter_take + gst_adapter_take_buffer + gst_adapter_take_buffer_fast + gst_adapter_take_buffer_list + gst_adapter_take_list + gst_adapter_unmap + gst_aggregator_finish_buffer + gst_aggregator_get_allocator + gst_aggregator_get_buffer_pool + gst_aggregator_get_latency + gst_aggregator_get_type + gst_aggregator_pad_drop_buffer + gst_aggregator_pad_get_type + gst_aggregator_pad_has_buffer + gst_aggregator_pad_is_eos + gst_aggregator_pad_peek_buffer + gst_aggregator_pad_pop_buffer + gst_aggregator_set_latency + gst_aggregator_set_src_caps + gst_base_parse_add_index_entry + gst_base_parse_convert_default + gst_base_parse_drain + gst_base_parse_finish_frame + gst_base_parse_frame_copy + gst_base_parse_frame_free + gst_base_parse_frame_get_type + gst_base_parse_frame_init + gst_base_parse_frame_new + gst_base_parse_get_type + gst_base_parse_merge_tags + gst_base_parse_push_frame + gst_base_parse_set_average_bitrate + gst_base_parse_set_duration + gst_base_parse_set_frame_rate + gst_base_parse_set_has_timing_info + gst_base_parse_set_infer_ts + gst_base_parse_set_latency + gst_base_parse_set_min_frame_size + gst_base_parse_set_passthrough + gst_base_parse_set_pts_interpolation + gst_base_parse_set_syncable + gst_base_parse_set_ts_at_offset + gst_base_sink_do_preroll + gst_base_sink_get_blocksize + gst_base_sink_get_drop_out_of_segment + gst_base_sink_get_last_sample + gst_base_sink_get_latency + gst_base_sink_get_max_bitrate + gst_base_sink_get_max_lateness + gst_base_sink_get_render_delay + gst_base_sink_get_sync + gst_base_sink_get_throttle_time + gst_base_sink_get_ts_offset + gst_base_sink_get_type + gst_base_sink_is_async_enabled + gst_base_sink_is_last_sample_enabled + gst_base_sink_is_qos_enabled + gst_base_sink_query_latency + gst_base_sink_set_async_enabled + gst_base_sink_set_blocksize + gst_base_sink_set_drop_out_of_segment + gst_base_sink_set_last_sample_enabled + gst_base_sink_set_max_bitrate + gst_base_sink_set_max_lateness + gst_base_sink_set_qos_enabled + gst_base_sink_set_render_delay + gst_base_sink_set_sync + gst_base_sink_set_throttle_time + gst_base_sink_set_ts_offset + gst_base_sink_wait + gst_base_sink_wait_clock + gst_base_sink_wait_preroll + gst_base_src_get_allocator + gst_base_src_get_blocksize + gst_base_src_get_buffer_pool + gst_base_src_get_do_timestamp + gst_base_src_get_type + gst_base_src_is_async + gst_base_src_is_live + gst_base_src_new_seamless_segment + gst_base_src_query_latency + gst_base_src_set_async + gst_base_src_set_automatic_eos + gst_base_src_set_blocksize + gst_base_src_set_caps + gst_base_src_set_do_timestamp + gst_base_src_set_dynamic_size + gst_base_src_set_format + gst_base_src_set_live + gst_base_src_start_complete + gst_base_src_start_wait + gst_base_src_submit_buffer_list + gst_base_src_wait_playing + gst_base_transform_get_allocator + gst_base_transform_get_buffer_pool + gst_base_transform_get_type + gst_base_transform_is_in_place + gst_base_transform_is_passthrough + gst_base_transform_is_qos_enabled + gst_base_transform_reconfigure_sink + gst_base_transform_reconfigure_src + gst_base_transform_set_gap_aware + gst_base_transform_set_in_place + gst_base_transform_set_passthrough + gst_base_transform_set_prefer_passthrough + gst_base_transform_set_qos_enabled + gst_base_transform_update_qos + gst_base_transform_update_src_caps + gst_bit_reader_free + gst_bit_reader_get_bits_uint16 + gst_bit_reader_get_bits_uint32 + gst_bit_reader_get_bits_uint64 + gst_bit_reader_get_bits_uint8 + gst_bit_reader_get_pos + gst_bit_reader_get_remaining + gst_bit_reader_get_size + gst_bit_reader_init + gst_bit_reader_new + gst_bit_reader_peek_bits_uint16 + gst_bit_reader_peek_bits_uint32 + gst_bit_reader_peek_bits_uint64 + gst_bit_reader_peek_bits_uint8 + gst_bit_reader_set_pos + gst_bit_reader_skip + gst_bit_reader_skip_to_byte + gst_byte_reader_dup_data + gst_byte_reader_dup_string_utf16 + gst_byte_reader_dup_string_utf32 + gst_byte_reader_dup_string_utf8 + gst_byte_reader_free + gst_byte_reader_get_data + gst_byte_reader_get_float32_be + gst_byte_reader_get_float32_le + gst_byte_reader_get_float64_be + gst_byte_reader_get_float64_le + gst_byte_reader_get_int16_be + gst_byte_reader_get_int16_le + gst_byte_reader_get_int24_be + gst_byte_reader_get_int24_le + gst_byte_reader_get_int32_be + gst_byte_reader_get_int32_le + gst_byte_reader_get_int64_be + gst_byte_reader_get_int64_le + gst_byte_reader_get_int8 + gst_byte_reader_get_pos + gst_byte_reader_get_remaining + gst_byte_reader_get_size + gst_byte_reader_get_string_utf8 + gst_byte_reader_get_sub_reader + gst_byte_reader_get_uint16_be + gst_byte_reader_get_uint16_le + gst_byte_reader_get_uint24_be + gst_byte_reader_get_uint24_le + gst_byte_reader_get_uint32_be + gst_byte_reader_get_uint32_le + gst_byte_reader_get_uint64_be + gst_byte_reader_get_uint64_le + gst_byte_reader_get_uint8 + gst_byte_reader_init + gst_byte_reader_masked_scan_uint32 + gst_byte_reader_masked_scan_uint32_peek + gst_byte_reader_new + gst_byte_reader_peek_data + gst_byte_reader_peek_float32_be + gst_byte_reader_peek_float32_le + gst_byte_reader_peek_float64_be + gst_byte_reader_peek_float64_le + gst_byte_reader_peek_int16_be + gst_byte_reader_peek_int16_le + gst_byte_reader_peek_int24_be + gst_byte_reader_peek_int24_le + gst_byte_reader_peek_int32_be + gst_byte_reader_peek_int32_le + gst_byte_reader_peek_int64_be + gst_byte_reader_peek_int64_le + gst_byte_reader_peek_int8 + gst_byte_reader_peek_string_utf8 + gst_byte_reader_peek_sub_reader + gst_byte_reader_peek_uint16_be + gst_byte_reader_peek_uint16_le + gst_byte_reader_peek_uint24_be + gst_byte_reader_peek_uint24_le + gst_byte_reader_peek_uint32_be + gst_byte_reader_peek_uint32_le + gst_byte_reader_peek_uint64_be + gst_byte_reader_peek_uint64_le + gst_byte_reader_peek_uint8 + gst_byte_reader_set_pos + gst_byte_reader_skip + gst_byte_reader_skip_string_utf16 + gst_byte_reader_skip_string_utf32 + gst_byte_reader_skip_string_utf8 + gst_byte_writer_ensure_free_space + gst_byte_writer_fill + gst_byte_writer_free + gst_byte_writer_free_and_get_buffer + gst_byte_writer_free_and_get_data + gst_byte_writer_get_remaining + gst_byte_writer_init + gst_byte_writer_init_with_data + gst_byte_writer_init_with_size + gst_byte_writer_new + gst_byte_writer_new_with_data + gst_byte_writer_new_with_size + gst_byte_writer_put_data + gst_byte_writer_put_float32_be + gst_byte_writer_put_float32_le + gst_byte_writer_put_float64_be + gst_byte_writer_put_float64_le + gst_byte_writer_put_int16_be + gst_byte_writer_put_int16_le + gst_byte_writer_put_int24_be + gst_byte_writer_put_int24_le + gst_byte_writer_put_int32_be + gst_byte_writer_put_int32_le + gst_byte_writer_put_int64_be + gst_byte_writer_put_int64_le + gst_byte_writer_put_int8 + gst_byte_writer_put_string_utf16 + gst_byte_writer_put_string_utf32 + gst_byte_writer_put_string_utf8 + gst_byte_writer_put_uint16_be + gst_byte_writer_put_uint16_le + gst_byte_writer_put_uint24_be + gst_byte_writer_put_uint24_le + gst_byte_writer_put_uint32_be + gst_byte_writer_put_uint32_le + gst_byte_writer_put_uint64_be + gst_byte_writer_put_uint64_le + gst_byte_writer_put_uint8 + gst_byte_writer_reset + gst_byte_writer_reset_and_get_buffer + gst_byte_writer_reset_and_get_data + gst_collect_pads_add_pad + gst_collect_pads_available + gst_collect_pads_clip_running_time + gst_collect_pads_event_default + gst_collect_pads_flush + gst_collect_pads_get_type + gst_collect_pads_new + gst_collect_pads_peek + gst_collect_pads_pop + gst_collect_pads_query_default + gst_collect_pads_read_buffer + gst_collect_pads_remove_pad + gst_collect_pads_set_buffer_function + gst_collect_pads_set_clip_function + gst_collect_pads_set_compare_function + gst_collect_pads_set_event_function + gst_collect_pads_set_flush_function + gst_collect_pads_set_flushing + gst_collect_pads_set_function + gst_collect_pads_set_query_function + gst_collect_pads_set_waiting + gst_collect_pads_src_event_default + gst_collect_pads_start + gst_collect_pads_stop + gst_collect_pads_take_buffer + gst_data_queue_drop_head + gst_data_queue_flush + gst_data_queue_get_level + gst_data_queue_get_type + gst_data_queue_is_empty + gst_data_queue_is_full + gst_data_queue_limits_changed + gst_data_queue_new + gst_data_queue_peek + gst_data_queue_pop + gst_data_queue_push + gst_data_queue_push_force + gst_data_queue_set_flushing + gst_flow_combiner_add_pad + gst_flow_combiner_clear + gst_flow_combiner_free + gst_flow_combiner_get_type + gst_flow_combiner_new + gst_flow_combiner_ref + gst_flow_combiner_remove_pad + gst_flow_combiner_reset + gst_flow_combiner_unref + gst_flow_combiner_update_flow + gst_flow_combiner_update_pad_flow + gst_push_src_get_type + gst_queue_array_drop_element + gst_queue_array_drop_struct + gst_queue_array_find + gst_queue_array_free + gst_queue_array_get_length + gst_queue_array_is_empty + gst_queue_array_new + gst_queue_array_new_for_struct + gst_queue_array_peek_head + gst_queue_array_peek_head_struct + gst_queue_array_peek_tail + gst_queue_array_peek_tail_struct + gst_queue_array_pop_head + gst_queue_array_pop_head_struct + gst_queue_array_pop_tail + gst_queue_array_pop_tail_struct + gst_queue_array_push_tail + gst_queue_array_push_tail_struct + gst_type_find_helper + gst_type_find_helper_for_buffer + gst_type_find_helper_for_data + gst_type_find_helper_for_extension + gst_type_find_helper_get_range diff --git a/win32/common/libgstcontroller.def b/win32/common/libgstcontroller.def new file mode 100644 index 0000000..66657e6 --- /dev/null +++ b/win32/common/libgstcontroller.def @@ -0,0 +1,28 @@ +EXPORTS + gst_argb_control_binding_get_type + gst_argb_control_binding_new + gst_control_point_copy + gst_control_point_free + gst_control_point_get_type + gst_direct_control_binding_get_type + gst_direct_control_binding_new + gst_direct_control_binding_new_absolute + gst_interpolation_control_source_get_type + gst_interpolation_control_source_new + gst_interpolation_mode_get_type + gst_lfo_control_source_get_type + gst_lfo_control_source_new + gst_lfo_waveform_get_type + gst_proxy_control_binding_get_type + gst_proxy_control_binding_new + gst_timed_value_control_invalidate_cache + gst_timed_value_control_source_find_control_point_iter + gst_timed_value_control_source_get_all + gst_timed_value_control_source_get_count + gst_timed_value_control_source_get_type + gst_timed_value_control_source_set + gst_timed_value_control_source_set_from_list + gst_timed_value_control_source_unset + gst_timed_value_control_source_unset_all + gst_trigger_control_source_get_type + gst_trigger_control_source_new diff --git a/win32/common/libgstnet.def b/win32/common/libgstnet.def new file mode 100644 index 0000000..6fdab1e --- /dev/null +++ b/win32/common/libgstnet.def @@ -0,0 +1,29 @@ +EXPORTS + gst_buffer_add_net_address_meta + gst_buffer_add_net_control_message_meta + gst_buffer_get_net_address_meta + gst_net_address_meta_api_get_type + gst_net_address_meta_get_info + gst_net_client_clock_get_type + gst_net_client_clock_new + gst_net_control_message_meta_api_get_type + gst_net_control_message_meta_get_info + gst_net_time_packet_copy + gst_net_time_packet_free + gst_net_time_packet_get_type + gst_net_time_packet_new + gst_net_time_packet_receive + gst_net_time_packet_send + gst_net_time_packet_serialize + gst_net_time_provider_get_type + gst_net_time_provider_new + gst_ntp_clock_get_type + gst_ntp_clock_new + gst_ptp_clock_get_type + gst_ptp_clock_new + gst_ptp_deinit + gst_ptp_init + gst_ptp_is_initialized + gst_ptp_is_supported + gst_ptp_statistics_callback_add + gst_ptp_statistics_callback_remove diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def new file mode 100644 index 0000000..4abfeec --- /dev/null +++ b/win32/common/libgstreamer.def @@ -0,0 +1,1675 @@ +EXPORTS + GST_CAT_BUFFER DATA + GST_CAT_BUFFER_LIST DATA + GST_CAT_BUS DATA + GST_CAT_CALL_TRACE DATA + GST_CAT_CAPS DATA + GST_CAT_CLOCK DATA + GST_CAT_CONTEXT DATA + GST_CAT_DEFAULT DATA + GST_CAT_ELEMENT_PADS DATA + GST_CAT_ERROR_SYSTEM DATA + GST_CAT_EVENT DATA + GST_CAT_GST_INIT DATA + GST_CAT_LOCKING DATA + GST_CAT_MEMORY DATA + GST_CAT_MESSAGE DATA + GST_CAT_META DATA + GST_CAT_NEGOTIATION DATA + GST_CAT_PADS DATA + GST_CAT_PARAMS DATA + GST_CAT_PARENTAGE DATA + GST_CAT_PERFORMANCE DATA + GST_CAT_PIPELINE DATA + GST_CAT_PLUGIN_INFO DATA + GST_CAT_PLUGIN_LOADING DATA + GST_CAT_PROBE DATA + GST_CAT_PROPERTIES DATA + GST_CAT_QOS DATA + GST_CAT_REFCOUNTING DATA + GST_CAT_REGISTRY DATA + GST_CAT_SCHEDULING DATA + GST_CAT_SIGNAL DATA + GST_CAT_STATES DATA + _gst_bitmask_type DATA + _gst_buffer_list_type DATA + _gst_buffer_type DATA + _gst_caps_any DATA + _gst_caps_features_any DATA + _gst_caps_features_memory_system_memory DATA + _gst_caps_features_type DATA + _gst_caps_none DATA + _gst_caps_type DATA + _gst_context_type DATA + _gst_date_time_type DATA + _gst_debug_category_new + _gst_debug_dump_mem + _gst_debug_enabled DATA + _gst_debug_get_category + _gst_debug_min DATA + _gst_debug_nameof_funcptr + _gst_debug_register_funcptr + _gst_disable_registry_cache DATA + _gst_double_range_type DATA + _gst_element_error_printf + _gst_event_type DATA + _gst_executable_path DATA + _gst_flagset_type DATA + _gst_fraction_range_type DATA + _gst_fraction_type DATA + _gst_int64_range_type DATA + _gst_int_range_type DATA + _gst_memory_type DATA + _gst_message_type DATA + _gst_meta_tag_memory DATA + _gst_meta_transform_copy DATA + _gst_plugin_loader_client_run + _gst_query_type DATA + _gst_sample_type DATA + _gst_structure_type DATA + _gst_tag_list_type DATA + _gst_toc_entry_type DATA + _gst_toc_type DATA + _gst_value_array_type DATA + _gst_value_list_type DATA + gst_allocation_params_copy + gst_allocation_params_free + gst_allocation_params_get_type + gst_allocation_params_init + gst_allocator_alloc + gst_allocator_find + gst_allocator_flags_get_type + gst_allocator_free + gst_allocator_get_type + gst_allocator_register + gst_allocator_set_default + gst_atomic_queue_get_type + gst_atomic_queue_length + gst_atomic_queue_new + gst_atomic_queue_peek + gst_atomic_queue_pop + gst_atomic_queue_push + gst_atomic_queue_ref + gst_atomic_queue_unref + gst_bin_add + gst_bin_add_many + gst_bin_find_unlinked_pad + gst_bin_flags_get_type + gst_bin_get_by_interface + gst_bin_get_by_name + gst_bin_get_by_name_recurse_up + gst_bin_get_suppressed_flags + gst_bin_get_type + gst_bin_iterate_all_by_interface + gst_bin_iterate_elements + gst_bin_iterate_recurse + gst_bin_iterate_sinks + gst_bin_iterate_sorted + gst_bin_iterate_sources + gst_bin_new + gst_bin_recalculate_latency + gst_bin_remove + gst_bin_remove_many + gst_bin_set_suppressed_flags + gst_bin_sync_children_states + gst_bitmask_get_type + gst_buffer_add_meta + gst_buffer_add_parent_buffer_meta + gst_buffer_add_protection_meta + gst_buffer_add_reference_timestamp_meta + gst_buffer_append + gst_buffer_append_memory + gst_buffer_append_region + gst_buffer_copy_deep + gst_buffer_copy_flags_get_type + gst_buffer_copy_into + gst_buffer_copy_region + gst_buffer_extract + gst_buffer_extract_dup + gst_buffer_fill + gst_buffer_find_memory + gst_buffer_flags_get_type + gst_buffer_foreach_meta + gst_buffer_get_all_memory + gst_buffer_get_flags + gst_buffer_get_max_memory + gst_buffer_get_memory + gst_buffer_get_memory_range + gst_buffer_get_meta + gst_buffer_get_n_meta + gst_buffer_get_reference_timestamp_meta + gst_buffer_get_size + gst_buffer_get_sizes + gst_buffer_get_sizes_range + gst_buffer_get_type + gst_buffer_has_flags + gst_buffer_insert_memory + gst_buffer_is_all_memory_writable + gst_buffer_is_memory_range_writable + gst_buffer_iterate_meta + gst_buffer_iterate_meta_filtered + gst_buffer_list_calculate_size + gst_buffer_list_copy_deep + gst_buffer_list_foreach + gst_buffer_list_get + gst_buffer_list_get_type + gst_buffer_list_get_writable + gst_buffer_list_insert + gst_buffer_list_length + gst_buffer_list_new + gst_buffer_list_new_sized + gst_buffer_list_remove + gst_buffer_map + gst_buffer_map_range + gst_buffer_memcmp + gst_buffer_memset + gst_buffer_n_memory + gst_buffer_new + gst_buffer_new_allocate + gst_buffer_new_wrapped + gst_buffer_new_wrapped_full + gst_buffer_peek_memory + gst_buffer_pool_acquire_buffer + gst_buffer_pool_acquire_flags_get_type + gst_buffer_pool_config_add_option + gst_buffer_pool_config_get_allocator + gst_buffer_pool_config_get_option + gst_buffer_pool_config_get_params + gst_buffer_pool_config_has_option + gst_buffer_pool_config_n_options + gst_buffer_pool_config_set_allocator + gst_buffer_pool_config_set_params + gst_buffer_pool_config_validate_params + gst_buffer_pool_get_config + gst_buffer_pool_get_options + gst_buffer_pool_get_type + gst_buffer_pool_has_option + gst_buffer_pool_is_active + gst_buffer_pool_new + gst_buffer_pool_release_buffer + gst_buffer_pool_set_active + gst_buffer_pool_set_config + gst_buffer_pool_set_flushing + gst_buffer_prepend_memory + gst_buffer_remove_all_memory + gst_buffer_remove_memory + gst_buffer_remove_memory_range + gst_buffer_remove_meta + gst_buffer_replace_all_memory + gst_buffer_replace_memory + gst_buffer_replace_memory_range + gst_buffer_resize + gst_buffer_resize_range + gst_buffer_set_flags + gst_buffer_set_size + gst_buffer_unmap + gst_buffer_unset_flags + gst_buffering_mode_get_type + gst_bus_add_signal_watch + gst_bus_add_signal_watch_full + gst_bus_add_watch + gst_bus_add_watch_full + gst_bus_async_signal_func + gst_bus_create_watch + gst_bus_disable_sync_message_emission + gst_bus_enable_sync_message_emission + gst_bus_flags_get_type + gst_bus_get_pollfd + gst_bus_get_type + gst_bus_have_pending + gst_bus_new + gst_bus_peek + gst_bus_poll + gst_bus_pop + gst_bus_pop_filtered + gst_bus_post + gst_bus_remove_signal_watch + gst_bus_remove_watch + gst_bus_set_flushing + gst_bus_set_sync_handler + gst_bus_sync_reply_get_type + gst_bus_sync_signal_handler + gst_bus_timed_pop + gst_bus_timed_pop_filtered + gst_calculate_linear_regression + gst_caps_append + gst_caps_append_structure + gst_caps_append_structure_full + gst_caps_can_intersect + gst_caps_copy_nth + gst_caps_features_add + gst_caps_features_add_id + gst_caps_features_contains + gst_caps_features_contains_id + gst_caps_features_copy + gst_caps_features_free + gst_caps_features_from_string + gst_caps_features_get_nth + gst_caps_features_get_nth_id + gst_caps_features_get_size + gst_caps_features_get_type + gst_caps_features_is_any + gst_caps_features_is_equal + gst_caps_features_new + gst_caps_features_new_any + gst_caps_features_new_empty + gst_caps_features_new_id + gst_caps_features_new_id_valist + gst_caps_features_new_valist + gst_caps_features_remove + gst_caps_features_remove_id + gst_caps_features_set_parent_refcount + gst_caps_features_to_string + gst_caps_filter_and_map_in_place + gst_caps_fixate + gst_caps_flags_get_type + gst_caps_foreach + gst_caps_from_string + gst_caps_get_features + gst_caps_get_size + gst_caps_get_structure + gst_caps_get_type + gst_caps_intersect + gst_caps_intersect_full + gst_caps_intersect_mode_get_type + gst_caps_is_always_compatible + gst_caps_is_any + gst_caps_is_empty + gst_caps_is_equal + gst_caps_is_equal_fixed + gst_caps_is_fixed + gst_caps_is_strictly_equal + gst_caps_is_subset + gst_caps_is_subset_structure + gst_caps_is_subset_structure_full + gst_caps_map_in_place + gst_caps_merge + gst_caps_merge_structure + gst_caps_merge_structure_full + gst_caps_new_any + gst_caps_new_empty + gst_caps_new_empty_simple + gst_caps_new_full + gst_caps_new_full_valist + gst_caps_new_simple + gst_caps_normalize + gst_caps_remove_structure + gst_caps_set_features + gst_caps_set_simple + gst_caps_set_simple_valist + gst_caps_set_value + gst_caps_simplify + gst_caps_steal_structure + gst_caps_subtract + gst_caps_to_string + gst_caps_truncate + gst_child_proxy_child_added + gst_child_proxy_child_removed + gst_child_proxy_get + gst_child_proxy_get_child_by_index + gst_child_proxy_get_child_by_name + gst_child_proxy_get_children_count + gst_child_proxy_get_property + gst_child_proxy_get_type + gst_child_proxy_get_valist + gst_child_proxy_lookup + gst_child_proxy_set + gst_child_proxy_set_property + gst_child_proxy_set_valist + gst_clock_add_observation + gst_clock_add_observation_unapplied + gst_clock_adjust_unlocked + gst_clock_adjust_with_calibration + gst_clock_entry_type_get_type + gst_clock_flags_get_type + gst_clock_get_calibration + gst_clock_get_internal_time + gst_clock_get_master + gst_clock_get_resolution + gst_clock_get_time + gst_clock_get_timeout + gst_clock_get_type + gst_clock_id_compare_func + gst_clock_id_get_time + gst_clock_id_ref + gst_clock_id_unref + gst_clock_id_unschedule + gst_clock_id_wait + gst_clock_id_wait_async + gst_clock_is_synced + gst_clock_new_periodic_id + gst_clock_new_single_shot_id + gst_clock_periodic_id_reinit + gst_clock_return_get_type + gst_clock_set_calibration + gst_clock_set_master + gst_clock_set_resolution + gst_clock_set_synced + gst_clock_set_timeout + gst_clock_single_shot_id_reinit + gst_clock_type_get_type + gst_clock_unadjust_unlocked + gst_clock_unadjust_with_calibration + gst_clock_wait_for_sync + gst_context_get_context_type + gst_context_get_structure + gst_context_get_type + gst_context_has_context_type + gst_context_is_persistent + gst_context_new + gst_context_writable_structure + gst_control_binding_get_g_value_array + gst_control_binding_get_type + gst_control_binding_get_value + gst_control_binding_get_value_array + gst_control_binding_is_disabled + gst_control_binding_set_disabled + gst_control_binding_sync_values + gst_control_source_get_type + gst_control_source_get_value + gst_control_source_get_value_array + gst_core_error_get_type + gst_core_error_quark + gst_date_time_get_day + gst_date_time_get_hour + gst_date_time_get_microsecond + gst_date_time_get_minute + gst_date_time_get_month + gst_date_time_get_second + gst_date_time_get_time_zone_offset + gst_date_time_get_type + gst_date_time_get_year + gst_date_time_has_day + gst_date_time_has_month + gst_date_time_has_second + gst_date_time_has_time + gst_date_time_has_year + gst_date_time_new + gst_date_time_new_from_g_date_time + gst_date_time_new_from_iso8601_string + gst_date_time_new_from_unix_epoch_local_time + gst_date_time_new_from_unix_epoch_utc + gst_date_time_new_local_time + gst_date_time_new_now_local_time + gst_date_time_new_now_utc + gst_date_time_new_y + gst_date_time_new_ym + gst_date_time_new_ymd + gst_date_time_ref + gst_date_time_to_g_date_time + gst_date_time_to_iso8601_string + gst_date_time_unref + gst_debug_add_log_function + gst_debug_add_ring_buffer_logger + gst_debug_bin_to_dot_data + gst_debug_bin_to_dot_file + gst_debug_bin_to_dot_file_with_ts + gst_debug_category_free + gst_debug_category_get_color + gst_debug_category_get_description + gst_debug_category_get_name + gst_debug_category_get_threshold + gst_debug_category_reset_threshold + gst_debug_category_set_threshold + gst_debug_color_flags_get_type + gst_debug_color_mode_get_type + gst_debug_construct_term_color + gst_debug_construct_win_color + gst_debug_get_all_categories + gst_debug_get_color_mode + gst_debug_get_default_threshold + gst_debug_get_stack_trace + gst_debug_graph_details_get_type + gst_debug_is_active + gst_debug_is_colored + gst_debug_level_get_name + gst_debug_level_get_type + gst_debug_log + gst_debug_log_default + gst_debug_log_valist + gst_debug_message_get + gst_debug_print_stack_trace + gst_debug_remove_log_function + gst_debug_remove_log_function_by_data + gst_debug_remove_ring_buffer_logger + gst_debug_ring_buffer_logger_get_logs + gst_debug_set_active + gst_debug_set_color_mode + gst_debug_set_color_mode_from_string + gst_debug_set_colored + gst_debug_set_default_threshold + gst_debug_set_threshold_for_name + gst_debug_set_threshold_from_string + gst_debug_unset_threshold_for_name + gst_deinit + gst_device_create_element + gst_device_get_caps + gst_device_get_device_class + gst_device_get_display_name + gst_device_get_properties + gst_device_get_type + gst_device_has_classes + gst_device_has_classesv + gst_device_monitor_add_filter + gst_device_monitor_get_bus + gst_device_monitor_get_devices + gst_device_monitor_get_providers + gst_device_monitor_get_show_all_devices + gst_device_monitor_get_type + gst_device_monitor_new + gst_device_monitor_remove_filter + gst_device_monitor_set_show_all_devices + gst_device_monitor_start + gst_device_monitor_stop + gst_device_provider_can_monitor + gst_device_provider_class_add_metadata + gst_device_provider_class_add_static_metadata + gst_device_provider_class_get_metadata + gst_device_provider_class_set_metadata + gst_device_provider_class_set_static_metadata + gst_device_provider_device_add + gst_device_provider_device_remove + gst_device_provider_factory_find + gst_device_provider_factory_get + gst_device_provider_factory_get_by_name + gst_device_provider_factory_get_device_provider_type + gst_device_provider_factory_get_metadata + gst_device_provider_factory_get_metadata_keys + gst_device_provider_factory_get_type + gst_device_provider_factory_has_classes + gst_device_provider_factory_has_classesv + gst_device_provider_factory_list_get_device_providers + gst_device_provider_get_bus + gst_device_provider_get_devices + gst_device_provider_get_factory + gst_device_provider_get_hidden_providers + gst_device_provider_get_metadata + gst_device_provider_get_type + gst_device_provider_hide_provider + gst_device_provider_register + gst_device_provider_start + gst_device_provider_stop + gst_device_provider_unhide_provider + gst_device_reconfigure_element + gst_double_range_get_type + gst_dynamic_type_factory_get_type + gst_dynamic_type_factory_load + gst_dynamic_type_register + gst_element_abort_state + gst_element_add_pad + gst_element_add_property_deep_notify_watch + gst_element_add_property_notify_watch + gst_element_call_async + gst_element_change_state + gst_element_class_add_metadata + gst_element_class_add_pad_template + gst_element_class_add_static_metadata + gst_element_class_add_static_pad_template + gst_element_class_add_static_pad_template_with_gtype + gst_element_class_get_metadata + gst_element_class_get_pad_template + gst_element_class_get_pad_template_list + gst_element_class_set_metadata + gst_element_class_set_static_metadata + gst_element_continue_state + gst_element_create_all_pads + gst_element_factory_can_sink_all_caps + gst_element_factory_can_sink_any_caps + gst_element_factory_can_src_all_caps + gst_element_factory_can_src_any_caps + gst_element_factory_create + gst_element_factory_find + gst_element_factory_get_element_type + gst_element_factory_get_metadata + gst_element_factory_get_metadata_keys + gst_element_factory_get_num_pad_templates + gst_element_factory_get_static_pad_templates + gst_element_factory_get_type + gst_element_factory_get_uri_protocols + gst_element_factory_get_uri_type + gst_element_factory_has_interface + gst_element_factory_list_filter + gst_element_factory_list_get_elements + gst_element_factory_list_is_type + gst_element_factory_make + gst_element_flags_get_type + gst_element_foreach_pad + gst_element_foreach_sink_pad + gst_element_foreach_src_pad + gst_element_get_base_time + gst_element_get_bus + gst_element_get_clock + gst_element_get_compatible_pad + gst_element_get_compatible_pad_template + gst_element_get_context + gst_element_get_context_unlocked + gst_element_get_contexts + gst_element_get_factory + gst_element_get_metadata + gst_element_get_pad_template + gst_element_get_pad_template_list + gst_element_get_request_pad + gst_element_get_start_time + gst_element_get_state + gst_element_get_static_pad + gst_element_get_type + gst_element_is_locked_state + gst_element_iterate_pads + gst_element_iterate_sink_pads + gst_element_iterate_src_pads + gst_element_link + gst_element_link_filtered + gst_element_link_many + gst_element_link_pads + gst_element_link_pads_filtered + gst_element_link_pads_full + gst_element_lost_state + gst_element_make_from_uri + gst_element_message_full + gst_element_message_full_with_details + gst_element_no_more_pads + gst_element_post_message + gst_element_provide_clock + gst_element_query + gst_element_query_convert + gst_element_query_duration + gst_element_query_position + gst_element_register + gst_element_release_request_pad + gst_element_remove_pad + gst_element_remove_property_notify_watch + gst_element_request_pad + gst_element_seek + gst_element_seek_simple + gst_element_send_event + gst_element_set_base_time + gst_element_set_bus + gst_element_set_clock + gst_element_set_context + gst_element_set_locked_state + gst_element_set_start_time + gst_element_set_state + gst_element_state_change_return_get_name + gst_element_state_get_name + gst_element_sync_state_with_parent + gst_element_unlink + gst_element_unlink_many + gst_element_unlink_pads + gst_error_get_message + gst_event_copy_segment + gst_event_get_running_time_offset + gst_event_get_seqnum + gst_event_get_structure + gst_event_get_type + gst_event_has_name + gst_event_new_buffer_size + gst_event_new_caps + gst_event_new_custom + gst_event_new_eos + gst_event_new_flush_start + gst_event_new_flush_stop + gst_event_new_gap + gst_event_new_latency + gst_event_new_navigation + gst_event_new_protection + gst_event_new_qos + gst_event_new_reconfigure + gst_event_new_seek + gst_event_new_segment + gst_event_new_segment_done + gst_event_new_select_streams + gst_event_new_sink_message + gst_event_new_step + gst_event_new_stream_collection + gst_event_new_stream_group_done + gst_event_new_stream_start + gst_event_new_tag + gst_event_new_toc + gst_event_new_toc_select + gst_event_parse_buffer_size + gst_event_parse_caps + gst_event_parse_flush_stop + gst_event_parse_gap + gst_event_parse_group_id + gst_event_parse_latency + gst_event_parse_protection + gst_event_parse_qos + gst_event_parse_seek + gst_event_parse_segment + gst_event_parse_segment_done + gst_event_parse_select_streams + gst_event_parse_sink_message + gst_event_parse_step + gst_event_parse_stream + gst_event_parse_stream_collection + gst_event_parse_stream_flags + gst_event_parse_stream_group_done + gst_event_parse_stream_start + gst_event_parse_tag + gst_event_parse_toc + gst_event_parse_toc_select + gst_event_set_group_id + gst_event_set_running_time_offset + gst_event_set_seqnum + gst_event_set_stream + gst_event_set_stream_flags + gst_event_type_flags_get_type + gst_event_type_get_flags + gst_event_type_get_name + gst_event_type_get_type + gst_event_type_to_quark + gst_event_writable_structure + gst_filename_to_uri + gst_flagset_get_type + gst_flagset_register + gst_flow_get_name + gst_flow_return_get_type + gst_flow_to_quark + gst_format_get_by_nick + gst_format_get_details + gst_format_get_name + gst_format_get_type + gst_format_iterate_definitions + gst_format_register + gst_format_to_quark + gst_formats_contains + gst_fraction_get_type + gst_fraction_range_get_type + gst_g_thread_get_type + gst_get_main_executable_path + gst_ghost_pad_activate_mode_default + gst_ghost_pad_construct + gst_ghost_pad_get_target + gst_ghost_pad_get_type + gst_ghost_pad_internal_activate_mode_default + gst_ghost_pad_new + gst_ghost_pad_new_from_template + gst_ghost_pad_new_no_target + gst_ghost_pad_new_no_target_from_template + gst_ghost_pad_set_target + gst_info_strdup_printf + gst_info_strdup_vprintf + gst_info_vasprintf + gst_init + gst_init_check + gst_init_get_option_group + gst_int64_range_get_type + gst_int_range_get_type + gst_is_caps_features + gst_is_initialized + gst_iterator_copy + gst_iterator_filter + gst_iterator_find_custom + gst_iterator_fold + gst_iterator_foreach + gst_iterator_free + gst_iterator_get_type + gst_iterator_item_get_type + gst_iterator_new + gst_iterator_new_list + gst_iterator_new_single + gst_iterator_next + gst_iterator_push + gst_iterator_result_get_type + gst_iterator_resync + gst_library_error_get_type + gst_library_error_quark + gst_lock_flags_get_type + gst_make_element_message_details + gst_map_flags_get_type + gst_memory_alignment DATA + gst_memory_copy + gst_memory_flags_get_type + gst_memory_get_sizes + gst_memory_get_type + gst_memory_init + gst_memory_is_span + gst_memory_is_type + gst_memory_make_mapped + gst_memory_map + gst_memory_new_wrapped + gst_memory_resize + gst_memory_share + gst_memory_unmap + gst_message_add_redirect_entry + gst_message_get_num_redirect_entries + gst_message_get_seqnum + gst_message_get_stream_status_object + gst_message_get_structure + gst_message_get_type + gst_message_has_name + gst_message_new_application + gst_message_new_async_done + gst_message_new_async_start + gst_message_new_buffering + gst_message_new_clock_lost + gst_message_new_clock_provide + gst_message_new_custom + gst_message_new_device_added + gst_message_new_device_removed + gst_message_new_duration_changed + gst_message_new_element + gst_message_new_eos + gst_message_new_error + gst_message_new_error_with_details + gst_message_new_have_context + gst_message_new_info + gst_message_new_info_with_details + gst_message_new_latency + gst_message_new_need_context + gst_message_new_new_clock + gst_message_new_progress + gst_message_new_property_notify + gst_message_new_qos + gst_message_new_redirect + gst_message_new_request_state + gst_message_new_reset_time + gst_message_new_segment_done + gst_message_new_segment_start + gst_message_new_state_changed + gst_message_new_state_dirty + gst_message_new_step_done + gst_message_new_step_start + gst_message_new_stream_collection + gst_message_new_stream_start + gst_message_new_stream_status + gst_message_new_streams_selected + gst_message_new_structure_change + gst_message_new_tag + gst_message_new_toc + gst_message_new_warning + gst_message_new_warning_with_details + gst_message_parse_async_done + gst_message_parse_buffering + gst_message_parse_buffering_stats + gst_message_parse_clock_lost + gst_message_parse_clock_provide + gst_message_parse_context_type + gst_message_parse_device_added + gst_message_parse_device_removed + gst_message_parse_error + gst_message_parse_error_details + gst_message_parse_group_id + gst_message_parse_have_context + gst_message_parse_info + gst_message_parse_info_details + gst_message_parse_new_clock + gst_message_parse_progress + gst_message_parse_property_notify + gst_message_parse_qos + gst_message_parse_qos_stats + gst_message_parse_qos_values + gst_message_parse_redirect_entry + gst_message_parse_request_state + gst_message_parse_reset_time + gst_message_parse_segment_done + gst_message_parse_segment_start + gst_message_parse_state_changed + gst_message_parse_step_done + gst_message_parse_step_start + gst_message_parse_stream_collection + gst_message_parse_stream_status + gst_message_parse_streams_selected + gst_message_parse_structure_change + gst_message_parse_tag + gst_message_parse_toc + gst_message_parse_warning + gst_message_parse_warning_details + gst_message_set_buffering_stats + gst_message_set_group_id + gst_message_set_qos_stats + gst_message_set_qos_values + gst_message_set_seqnum + gst_message_set_stream_status_object + gst_message_streams_selected_add + gst_message_streams_selected_get_size + gst_message_streams_selected_get_stream + gst_message_type_get_name + gst_message_type_get_type + gst_message_type_to_quark + gst_message_writable_structure + gst_meta_api_type_get_tags + gst_meta_api_type_has_tag + gst_meta_api_type_register + gst_meta_flags_get_type + gst_meta_get_info + gst_meta_register + gst_mini_object_copy + gst_mini_object_flags_get_type + gst_mini_object_get_qdata + gst_mini_object_init + gst_mini_object_is_writable + gst_mini_object_lock + gst_mini_object_make_writable + gst_mini_object_ref + gst_mini_object_replace + gst_mini_object_set_qdata + gst_mini_object_steal + gst_mini_object_steal_qdata + gst_mini_object_take + gst_mini_object_unlock + gst_mini_object_unref + gst_mini_object_weak_ref + gst_mini_object_weak_unref + gst_object_add_control_binding + gst_object_check_uniqueness + gst_object_default_deep_notify + gst_object_default_error + gst_object_flags_get_type + gst_object_get_control_binding + gst_object_get_control_rate + gst_object_get_g_value_array + gst_object_get_name + gst_object_get_parent + gst_object_get_path_string + gst_object_get_type + gst_object_get_value + gst_object_get_value_array + gst_object_has_active_control_bindings + gst_object_has_ancestor + gst_object_has_as_ancestor + gst_object_has_as_parent + gst_object_ref + gst_object_ref_sink + gst_object_remove_control_binding + gst_object_replace + gst_object_set_control_binding_disabled + gst_object_set_control_bindings_disabled + gst_object_set_control_rate + gst_object_set_name + gst_object_set_parent + gst_object_suggest_next_sync + gst_object_sync_values + gst_object_unparent + gst_object_unref + gst_pad_activate_mode + gst_pad_add_probe + gst_pad_can_link + gst_pad_chain + gst_pad_chain_list + gst_pad_check_reconfigure + gst_pad_create_stream_id + gst_pad_create_stream_id_printf + gst_pad_create_stream_id_printf_valist + gst_pad_direction_get_type + gst_pad_event_default + gst_pad_flags_get_type + gst_pad_forward + gst_pad_get_allowed_caps + gst_pad_get_current_caps + gst_pad_get_direction + gst_pad_get_element_private + gst_pad_get_last_flow_return + gst_pad_get_offset + gst_pad_get_pad_template + gst_pad_get_pad_template_caps + gst_pad_get_parent_element + gst_pad_get_peer + gst_pad_get_range + gst_pad_get_sticky_event + gst_pad_get_stream + gst_pad_get_stream_id + gst_pad_get_task_state + gst_pad_get_type + gst_pad_has_current_caps + gst_pad_is_active + gst_pad_is_blocked + gst_pad_is_blocking + gst_pad_is_linked + gst_pad_iterate_internal_links + gst_pad_iterate_internal_links_default + gst_pad_link + gst_pad_link_check_get_type + gst_pad_link_full + gst_pad_link_get_name + gst_pad_link_maybe_ghosting + gst_pad_link_maybe_ghosting_full + gst_pad_link_return_get_type + gst_pad_mark_reconfigure + gst_pad_mode_get_name + gst_pad_mode_get_type + gst_pad_needs_reconfigure + gst_pad_new + gst_pad_new_from_static_template + gst_pad_new_from_template + gst_pad_pause_task + gst_pad_peer_query + gst_pad_peer_query_accept_caps + gst_pad_peer_query_caps + gst_pad_peer_query_convert + gst_pad_peer_query_duration + gst_pad_peer_query_position + gst_pad_presence_get_type + gst_pad_probe_info_get_buffer + gst_pad_probe_info_get_buffer_list + gst_pad_probe_info_get_event + gst_pad_probe_info_get_query + gst_pad_probe_return_get_type + gst_pad_probe_type_get_type + gst_pad_proxy_query_accept_caps + gst_pad_proxy_query_caps + gst_pad_pull_range + gst_pad_push + gst_pad_push_event + gst_pad_push_list + gst_pad_query + gst_pad_query_accept_caps + gst_pad_query_caps + gst_pad_query_convert + gst_pad_query_default + gst_pad_query_duration + gst_pad_query_position + gst_pad_remove_probe + gst_pad_send_event + gst_pad_set_activate_function_full + gst_pad_set_activatemode_function_full + gst_pad_set_active + gst_pad_set_chain_function_full + gst_pad_set_chain_list_function_full + gst_pad_set_element_private + gst_pad_set_event_full_function_full + gst_pad_set_event_function_full + gst_pad_set_getrange_function_full + gst_pad_set_iterate_internal_links_function_full + gst_pad_set_link_function_full + gst_pad_set_offset + gst_pad_set_query_function_full + gst_pad_set_unlink_function_full + gst_pad_start_task + gst_pad_sticky_events_foreach + gst_pad_stop_task + gst_pad_store_sticky_event + gst_pad_template_flags_get_type + gst_pad_template_get_caps + gst_pad_template_get_type + gst_pad_template_new + gst_pad_template_new_from_static_pad_template_with_gtype + gst_pad_template_new_with_gtype + gst_pad_template_pad_created + gst_pad_unlink + gst_pad_use_fixed_caps + gst_param_spec_array + gst_param_spec_array_get_type + gst_param_spec_fraction + gst_param_spec_fraction_get_type + gst_parent_buffer_meta_api_get_type + gst_parent_buffer_meta_get_info + gst_parse_bin_from_description + gst_parse_bin_from_description_full + gst_parse_context_copy + gst_parse_context_free + gst_parse_context_get_missing_elements + gst_parse_context_get_type + gst_parse_context_new + gst_parse_error_get_type + gst_parse_error_quark + gst_parse_flags_get_type + gst_parse_launch + gst_parse_launch_full + gst_parse_launchv + gst_parse_launchv_full + gst_pipeline_auto_clock + gst_pipeline_flags_get_type + gst_pipeline_get_auto_flush_bus + gst_pipeline_get_bus + gst_pipeline_get_clock + gst_pipeline_get_delay + gst_pipeline_get_latency + gst_pipeline_get_pipeline_clock + gst_pipeline_get_type + gst_pipeline_new + gst_pipeline_set_auto_flush_bus + gst_pipeline_set_clock + gst_pipeline_set_delay + gst_pipeline_set_latency + gst_pipeline_use_clock + gst_plugin_add_dependency + gst_plugin_add_dependency_simple + gst_plugin_dependency_flags_get_type + gst_plugin_error_get_type + gst_plugin_error_quark + gst_plugin_feature_check_version + gst_plugin_feature_get_plugin + gst_plugin_feature_get_plugin_name + gst_plugin_feature_get_rank + gst_plugin_feature_get_type + gst_plugin_feature_list_copy + gst_plugin_feature_list_debug + gst_plugin_feature_list_free + gst_plugin_feature_load + gst_plugin_feature_rank_compare_func + gst_plugin_feature_set_rank + gst_plugin_flags_get_type + gst_plugin_get_cache_data + gst_plugin_get_description + gst_plugin_get_filename + gst_plugin_get_license + gst_plugin_get_name + gst_plugin_get_origin + gst_plugin_get_package + gst_plugin_get_release_date_string + gst_plugin_get_source + gst_plugin_get_type + gst_plugin_get_version + gst_plugin_is_loaded + gst_plugin_list_free + gst_plugin_load + gst_plugin_load_by_name + gst_plugin_load_file + gst_plugin_register_static + gst_plugin_register_static_full + gst_plugin_set_cache_data + gst_poll_add_fd + gst_poll_fd_can_read + gst_poll_fd_can_write + gst_poll_fd_ctl_read + gst_poll_fd_ctl_write + gst_poll_fd_has_closed + gst_poll_fd_has_error + gst_poll_fd_ignored + gst_poll_fd_init + gst_poll_free + gst_poll_get_read_gpollfd + gst_poll_new + gst_poll_new_timer + gst_poll_read_control + gst_poll_remove_fd + gst_poll_restart + gst_poll_set_controllable + gst_poll_set_flushing + gst_poll_wait + gst_poll_write_control + gst_preset_delete_preset + gst_preset_get_app_dir + gst_preset_get_meta + gst_preset_get_preset_names + gst_preset_get_property_names + gst_preset_get_type + gst_preset_is_editable + gst_preset_load_preset + gst_preset_rename_preset + gst_preset_save_preset + gst_preset_set_app_dir + gst_preset_set_meta + gst_print + gst_printerr + gst_printerrln + gst_println + gst_progress_type_get_type + gst_promise_expire + gst_promise_get_reply + gst_promise_get_type + gst_promise_interrupt + gst_promise_new + gst_promise_new_with_change_func + gst_promise_reply + gst_promise_result_get_type + gst_promise_wait + gst_protection_filter_systems_by_available_decryptors + gst_protection_meta_api_get_type + gst_protection_meta_get_info + gst_protection_select_system + gst_proxy_pad_chain_default + gst_proxy_pad_chain_list_default + gst_proxy_pad_get_internal + gst_proxy_pad_get_type + gst_proxy_pad_getrange_default + gst_proxy_pad_iterate_internal_links_default + gst_qos_type_get_type + gst_query_add_allocation_meta + gst_query_add_allocation_param + gst_query_add_allocation_pool + gst_query_add_buffering_range + gst_query_add_scheduling_mode + gst_query_find_allocation_meta + gst_query_get_n_allocation_metas + gst_query_get_n_allocation_params + gst_query_get_n_allocation_pools + gst_query_get_n_buffering_ranges + gst_query_get_n_scheduling_modes + gst_query_get_structure + gst_query_get_type + gst_query_has_scheduling_mode + gst_query_has_scheduling_mode_with_flags + gst_query_new_accept_caps + gst_query_new_allocation + gst_query_new_buffering + gst_query_new_caps + gst_query_new_context + gst_query_new_convert + gst_query_new_custom + gst_query_new_drain + gst_query_new_duration + gst_query_new_formats + gst_query_new_latency + gst_query_new_position + gst_query_new_scheduling + gst_query_new_seeking + gst_query_new_segment + gst_query_new_uri + gst_query_parse_accept_caps + gst_query_parse_accept_caps_result + gst_query_parse_allocation + gst_query_parse_buffering_percent + gst_query_parse_buffering_range + gst_query_parse_buffering_stats + gst_query_parse_caps + gst_query_parse_caps_result + gst_query_parse_context + gst_query_parse_context_type + gst_query_parse_convert + gst_query_parse_duration + gst_query_parse_latency + gst_query_parse_n_formats + gst_query_parse_nth_allocation_meta + gst_query_parse_nth_allocation_param + gst_query_parse_nth_allocation_pool + gst_query_parse_nth_buffering_range + gst_query_parse_nth_format + gst_query_parse_nth_scheduling_mode + gst_query_parse_position + gst_query_parse_scheduling + gst_query_parse_seeking + gst_query_parse_segment + gst_query_parse_uri + gst_query_parse_uri_redirection + gst_query_parse_uri_redirection_permanent + gst_query_remove_nth_allocation_meta + gst_query_remove_nth_allocation_param + gst_query_remove_nth_allocation_pool + gst_query_set_accept_caps_result + gst_query_set_buffering_percent + gst_query_set_buffering_range + gst_query_set_buffering_stats + gst_query_set_caps_result + gst_query_set_context + gst_query_set_convert + gst_query_set_duration + gst_query_set_formats + gst_query_set_formatsv + gst_query_set_latency + gst_query_set_nth_allocation_param + gst_query_set_nth_allocation_pool + gst_query_set_position + gst_query_set_scheduling + gst_query_set_seeking + gst_query_set_segment + gst_query_set_uri + gst_query_set_uri_redirection + gst_query_set_uri_redirection_permanent + gst_query_type_flags_get_type + gst_query_type_get_flags + gst_query_type_get_name + gst_query_type_get_type + gst_query_type_to_quark + gst_query_writable_structure + gst_rank_get_type + gst_reference_timestamp_meta_api_get_type + gst_reference_timestamp_meta_get_info + gst_registry_add_feature + gst_registry_add_plugin + gst_registry_check_feature_version + gst_registry_feature_filter + gst_registry_find_feature + gst_registry_find_plugin + gst_registry_fork_is_enabled + gst_registry_fork_set_enabled + gst_registry_get + gst_registry_get_feature_list + gst_registry_get_feature_list_by_plugin + gst_registry_get_feature_list_cookie + gst_registry_get_plugin_list + gst_registry_get_type + gst_registry_lookup + gst_registry_lookup_feature + gst_registry_plugin_filter + gst_registry_remove_feature + gst_registry_remove_plugin + gst_registry_scan_path + gst_resource_error_get_type + gst_resource_error_quark + gst_sample_get_buffer + gst_sample_get_buffer_list + gst_sample_get_caps + gst_sample_get_info + gst_sample_get_segment + gst_sample_get_type + gst_sample_new + gst_sample_set_buffer_list + gst_scheduling_flags_get_type + gst_search_mode_get_type + gst_seek_flags_get_type + gst_seek_type_get_type + gst_segment_clip + gst_segment_copy + gst_segment_copy_into + gst_segment_do_seek + gst_segment_flags_get_type + gst_segment_free + gst_segment_get_type + gst_segment_init + gst_segment_is_equal + gst_segment_new + gst_segment_offset_running_time + gst_segment_position_from_running_time + gst_segment_position_from_running_time_full + gst_segment_position_from_stream_time + gst_segment_position_from_stream_time_full + gst_segment_set_running_time + gst_segment_to_position + gst_segment_to_running_time + gst_segment_to_running_time_full + gst_segment_to_stream_time + gst_segment_to_stream_time_full + gst_segtrap_is_enabled + gst_segtrap_set_enabled + gst_stack_trace_flags_get_type + gst_state_change_get_name + gst_state_change_get_type + gst_state_change_return_get_type + gst_state_get_type + gst_static_caps_cleanup + gst_static_caps_get + gst_static_caps_get_type + gst_static_pad_template_get + gst_static_pad_template_get_caps + gst_static_pad_template_get_type + gst_stream_collection_add_stream + gst_stream_collection_get_size + gst_stream_collection_get_stream + gst_stream_collection_get_type + gst_stream_collection_get_upstream_id + gst_stream_collection_new + gst_stream_error_get_type + gst_stream_error_quark + gst_stream_flags_get_type + gst_stream_get_caps + gst_stream_get_stream_flags + gst_stream_get_stream_id + gst_stream_get_stream_type + gst_stream_get_tags + gst_stream_get_type + gst_stream_new + gst_stream_set_caps + gst_stream_set_stream_flags + gst_stream_set_stream_type + gst_stream_set_tags + gst_stream_status_type_get_type + gst_stream_type_get_name + gst_stream_type_get_type + gst_structure_can_intersect + gst_structure_change_type_get_type + gst_structure_copy + gst_structure_filter_and_map_in_place + gst_structure_fixate + gst_structure_fixate_field + gst_structure_fixate_field_boolean + gst_structure_fixate_field_nearest_double + gst_structure_fixate_field_nearest_fraction + gst_structure_fixate_field_nearest_int + gst_structure_fixate_field_string + gst_structure_foreach + gst_structure_free + gst_structure_from_string + gst_structure_get + gst_structure_get_array + gst_structure_get_boolean + gst_structure_get_clock_time + gst_structure_get_date + gst_structure_get_date_time + gst_structure_get_double + gst_structure_get_enum + gst_structure_get_field_type + gst_structure_get_flagset + gst_structure_get_fraction + gst_structure_get_int + gst_structure_get_int64 + gst_structure_get_list + gst_structure_get_name + gst_structure_get_name_id + gst_structure_get_string + gst_structure_get_type + gst_structure_get_uint + gst_structure_get_uint64 + gst_structure_get_valist + gst_structure_get_value + gst_structure_has_field + gst_structure_has_field_typed + gst_structure_has_name + gst_structure_id_get + gst_structure_id_get_valist + gst_structure_id_get_value + gst_structure_id_has_field + gst_structure_id_has_field_typed + gst_structure_id_set + gst_structure_id_set_valist + gst_structure_id_set_value + gst_structure_id_take_value + gst_structure_intersect + gst_structure_is_equal + gst_structure_is_subset + gst_structure_map_in_place + gst_structure_n_fields + gst_structure_new + gst_structure_new_empty + gst_structure_new_from_string + gst_structure_new_id + gst_structure_new_id_empty + gst_structure_new_valist + gst_structure_nth_field_name + gst_structure_remove_all_fields + gst_structure_remove_field + gst_structure_remove_fields + gst_structure_remove_fields_valist + gst_structure_set + gst_structure_set_array + gst_structure_set_list + gst_structure_set_name + gst_structure_set_parent_refcount + gst_structure_set_valist + gst_structure_set_value + gst_structure_take_value + gst_structure_to_string + gst_system_clock_get_type + gst_system_clock_obtain + gst_system_clock_set_default + gst_tag_exists + gst_tag_flag_get_type + gst_tag_get_description + gst_tag_get_flag + gst_tag_get_nick + gst_tag_get_type + gst_tag_is_fixed + gst_tag_list_add + gst_tag_list_add_valist + gst_tag_list_add_valist_values + gst_tag_list_add_value + gst_tag_list_add_values + gst_tag_list_copy_value + gst_tag_list_foreach + gst_tag_list_get_boolean + gst_tag_list_get_boolean_index + gst_tag_list_get_date + gst_tag_list_get_date_index + gst_tag_list_get_date_time + gst_tag_list_get_date_time_index + gst_tag_list_get_double + gst_tag_list_get_double_index + gst_tag_list_get_float + gst_tag_list_get_float_index + gst_tag_list_get_int + gst_tag_list_get_int64 + gst_tag_list_get_int64_index + gst_tag_list_get_int_index + gst_tag_list_get_pointer + gst_tag_list_get_pointer_index + gst_tag_list_get_sample + gst_tag_list_get_sample_index + gst_tag_list_get_scope + gst_tag_list_get_string + gst_tag_list_get_string_index + gst_tag_list_get_tag_size + gst_tag_list_get_type + gst_tag_list_get_uint + gst_tag_list_get_uint64 + gst_tag_list_get_uint64_index + gst_tag_list_get_uint_index + gst_tag_list_get_value_index + gst_tag_list_insert + gst_tag_list_is_empty + gst_tag_list_is_equal + gst_tag_list_merge + gst_tag_list_n_tags + gst_tag_list_new + gst_tag_list_new_empty + gst_tag_list_new_from_string + gst_tag_list_new_valist + gst_tag_list_nth_tag_name + gst_tag_list_peek_string_index + gst_tag_list_remove_tag + gst_tag_list_set_scope + gst_tag_list_to_string + gst_tag_merge_mode_get_type + gst_tag_merge_strings_with_comma + gst_tag_merge_use_first + gst_tag_register + gst_tag_register_static + gst_tag_scope_get_type + gst_tag_setter_add_tag_valist + gst_tag_setter_add_tag_valist_values + gst_tag_setter_add_tag_value + gst_tag_setter_add_tag_values + gst_tag_setter_add_tags + gst_tag_setter_get_tag_list + gst_tag_setter_get_tag_merge_mode + gst_tag_setter_get_type + gst_tag_setter_merge_tags + gst_tag_setter_reset_tags + gst_tag_setter_set_tag_merge_mode + gst_task_cleanup_all + gst_task_get_pool + gst_task_get_state + gst_task_get_type + gst_task_join + gst_task_new + gst_task_pause + gst_task_pool_cleanup + gst_task_pool_get_type + gst_task_pool_join + gst_task_pool_new + gst_task_pool_prepare + gst_task_pool_push + gst_task_set_enter_callback + gst_task_set_leave_callback + gst_task_set_lock + gst_task_set_pool + gst_task_set_state + gst_task_start + gst_task_state_get_type + gst_task_stop + gst_toc_append_entry + gst_toc_dump + gst_toc_entry_append_sub_entry + gst_toc_entry_get_entry_type + gst_toc_entry_get_loop + gst_toc_entry_get_parent + gst_toc_entry_get_start_stop_times + gst_toc_entry_get_sub_entries + gst_toc_entry_get_tags + gst_toc_entry_get_toc + gst_toc_entry_get_type + gst_toc_entry_get_uid + gst_toc_entry_is_alternative + gst_toc_entry_is_sequence + gst_toc_entry_merge_tags + gst_toc_entry_new + gst_toc_entry_set_loop + gst_toc_entry_set_start_stop_times + gst_toc_entry_set_tags + gst_toc_entry_type_get_nick + gst_toc_entry_type_get_type + gst_toc_find_entry + gst_toc_get_entries + gst_toc_get_scope + gst_toc_get_tags + gst_toc_get_type + gst_toc_loop_type_get_type + gst_toc_merge_tags + gst_toc_new + gst_toc_scope_get_type + gst_toc_set_tags + gst_toc_setter_get_toc + gst_toc_setter_get_type + gst_toc_setter_reset + gst_toc_setter_set_toc + gst_tracer_factory_get_list + gst_tracer_factory_get_tracer_type + gst_tracer_factory_get_type + gst_tracer_get_type + gst_tracer_record_get_type + gst_tracer_record_log + gst_tracer_record_new + gst_tracer_register + gst_tracer_value_flags_get_type + gst_tracer_value_scope_get_type + gst_tracing_register_hook + gst_type_find_factory_call_function + gst_type_find_factory_get_caps + gst_type_find_factory_get_extensions + gst_type_find_factory_get_list + gst_type_find_factory_get_type + gst_type_find_factory_has_function + gst_type_find_get_length + gst_type_find_get_type + gst_type_find_peek + gst_type_find_probability_get_type + gst_type_find_register + gst_type_find_suggest + gst_type_find_suggest_simple + gst_update_registry + gst_uri_append_path + gst_uri_append_path_segment + gst_uri_construct + gst_uri_equal + gst_uri_error_get_type + gst_uri_error_quark + gst_uri_from_string + gst_uri_from_string_with_base + gst_uri_get_fragment + gst_uri_get_host + gst_uri_get_location + gst_uri_get_media_fragment_table + gst_uri_get_path + gst_uri_get_path_segments + gst_uri_get_path_string + gst_uri_get_port + gst_uri_get_protocol + gst_uri_get_query_keys + gst_uri_get_query_string + gst_uri_get_query_table + gst_uri_get_query_value + gst_uri_get_scheme + gst_uri_get_type + gst_uri_get_userinfo + gst_uri_handler_get_protocols + gst_uri_handler_get_type + gst_uri_handler_get_uri + gst_uri_handler_get_uri_type + gst_uri_handler_set_uri + gst_uri_has_protocol + gst_uri_is_normalized + gst_uri_is_valid + gst_uri_is_writable + gst_uri_join + gst_uri_join_strings + gst_uri_make_writable + gst_uri_new + gst_uri_new_with_base + gst_uri_normalize + gst_uri_protocol_is_supported + gst_uri_protocol_is_valid + gst_uri_query_has_key + gst_uri_remove_query_key + gst_uri_set_fragment + gst_uri_set_host + gst_uri_set_path + gst_uri_set_path_segments + gst_uri_set_path_string + gst_uri_set_port + gst_uri_set_query_string + gst_uri_set_query_table + gst_uri_set_query_value + gst_uri_set_scheme + gst_uri_set_userinfo + gst_uri_to_string + gst_uri_type_get_type + gst_util_array_binary_search + gst_util_double_to_fraction + gst_util_dump_buffer + gst_util_dump_mem + gst_util_fraction_add + gst_util_fraction_compare + gst_util_fraction_multiply + gst_util_fraction_to_double + gst_util_gdouble_to_guint64 + gst_util_get_object_array + gst_util_get_timestamp + gst_util_greatest_common_divisor + gst_util_greatest_common_divisor_int64 + gst_util_group_id_next + gst_util_guint64_to_gdouble + gst_util_seqnum_compare + gst_util_seqnum_next + gst_util_set_object_arg + gst_util_set_object_array + gst_util_set_value_from_string + gst_util_uint64_scale + gst_util_uint64_scale_ceil + gst_util_uint64_scale_int + gst_util_uint64_scale_int_ceil + gst_util_uint64_scale_int_round + gst_util_uint64_scale_round + gst_value_array_append_and_take_value + gst_value_array_append_value + gst_value_array_get_size + gst_value_array_get_type + gst_value_array_get_value + gst_value_array_prepend_value + gst_value_can_compare + gst_value_can_intersect + gst_value_can_subtract + gst_value_can_union + gst_value_compare + gst_value_deserialize + gst_value_fixate + gst_value_fraction_multiply + gst_value_fraction_subtract + gst_value_get_bitmask + gst_value_get_caps + gst_value_get_caps_features + gst_value_get_double_range_max + gst_value_get_double_range_min + gst_value_get_flagset_flags + gst_value_get_flagset_mask + gst_value_get_fraction_denominator + gst_value_get_fraction_numerator + gst_value_get_fraction_range_max + gst_value_get_fraction_range_min + gst_value_get_int64_range_max + gst_value_get_int64_range_min + gst_value_get_int64_range_step + gst_value_get_int_range_max + gst_value_get_int_range_min + gst_value_get_int_range_step + gst_value_get_structure + gst_value_init_and_copy + gst_value_intersect + gst_value_is_fixed + gst_value_is_subset + gst_value_list_append_and_take_value + gst_value_list_append_value + gst_value_list_concat + gst_value_list_get_size + gst_value_list_get_type + gst_value_list_get_value + gst_value_list_merge + gst_value_list_prepend_value + gst_value_register + gst_value_serialize + gst_value_set_bitmask + gst_value_set_caps + gst_value_set_caps_features + gst_value_set_double_range + gst_value_set_flagset + gst_value_set_fraction + gst_value_set_fraction_range + gst_value_set_fraction_range_full + gst_value_set_int64_range + gst_value_set_int64_range_step + gst_value_set_int_range + gst_value_set_int_range_step + gst_value_set_structure + gst_value_subtract + gst_value_union + gst_version + gst_version_string